aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-01-02 19:18:08 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-01-02 19:18:08 +0000
commitbab175ec4b075c8076ba14c762900392533f6ee4 (patch)
tree01f4f29419a2cb10abe13c1e63cd2a66068b0137
parent8b7a8012d223fac5d17d16a66bb39168a9a1dfc0 (diff)
downloadsrc-bab175ec4b075c8076ba14c762900392533f6ee4.tar.gz
src-bab175ec4b075c8076ba14c762900392533f6ee4.zip
Vendor import of clang trunk r290819:vendor/clang/clang-trunk-r290819
Notes
Notes: svn path=/vendor/clang/dist/; revision=311118 svn path=/vendor/clang/clang-trunk-r290819/; revision=311119; tag=vendor/clang/clang-trunk-r290819
-rw-r--r--CMakeLists.txt188
-rw-r--r--bindings/python/clang/cindex.py308
-rw-r--r--bindings/python/tests/cindex/test_cursor.py2
-rw-r--r--bindings/python/tests/cindex/test_cursor_kind.py3
-rw-r--r--bindings/python/tests/cindex/test_tokens.py2
-rw-r--r--bindings/python/tests/cindex/test_translation_unit.py8
-rw-r--r--cmake/caches/Apple-stage1.cmake5
-rw-r--r--cmake/caches/Apple-stage2.cmake3
-rw-r--r--cmake/caches/DistributionExample-stage2.cmake30
-rw-r--r--cmake/caches/DistributionExample.cmake34
-rw-r--r--cmake/caches/PGO-stage2-instrumented.cmake25
-rw-r--r--cmake/caches/PGO.cmake13
-rw-r--r--cmake/modules/AddClang.cmake17
-rw-r--r--cmake/modules/CMakeLists.txt5
-rw-r--r--docs/AddressSanitizer.rst9
-rw-r--r--docs/AttributeReference.rst2735
-rw-r--r--docs/AutomaticReferenceCounting.rst4
-rw-r--r--docs/Block-ABI-Apple.rst4
-rw-r--r--docs/ClangCheck.rst6
-rw-r--r--docs/ClangFormat.rst2
-rw-r--r--docs/ClangFormatStyleOptions.rst3
-rw-r--r--docs/CommandGuide/clang.rst39
-rw-r--r--docs/ControlFlowIntegrityDesign.rst54
-rw-r--r--docs/CrossCompilation.rst4
-rw-r--r--docs/DiagnosticsReference.rst10560
-rw-r--r--docs/HowToSetupToolingForLLVM.rst2
-rw-r--r--docs/JSONCompilationDatabase.rst5
-rw-r--r--docs/LanguageExtensions.rst76
-rw-r--r--docs/LibASTMatchers.rst2
-rw-r--r--docs/LibASTMatchersReference.html519
-rw-r--r--docs/LibASTMatchersTutorial.rst4
-rw-r--r--docs/MSVCCompatibility.rst13
-rw-r--r--docs/MemorySanitizer.rst10
-rw-r--r--docs/Modules.rst14
-rw-r--r--docs/ReleaseNotes.rst249
-rw-r--r--docs/SanitizerCoverage.rst154
-rw-r--r--docs/SourceBasedCodeCoverage.rst110
-rw-r--r--docs/ThinLTO.rst159
-rw-r--r--docs/ThreadSanitizer.rst10
-rw-r--r--docs/Toolchain.rst354
-rw-r--r--docs/UndefinedBehaviorSanitizer.rst4
-rw-r--r--docs/UsersManual.rst115
-rw-r--r--docs/analyzer/DebugChecks.rst39
-rw-r--r--docs/analyzer/IPA.txt2
-rw-r--r--docs/analyzer/conf.py4
-rw-r--r--docs/conf.py4
-rw-r--r--docs/index.rst3
-rw-r--r--examples/AnnotateFunctions/CMakeLists.txt2
-rw-r--r--examples/PrintFunctionNames/CMakeLists.txt2
-rw-r--r--examples/PrintFunctionNames/PrintFunctionNames.cpp5
-rw-r--r--include/clang-c/Index.h81
-rw-r--r--include/clang/AST/APValue.h14
-rw-r--r--include/clang/AST/ASTConsumer.h2
-rw-r--r--include/clang/AST/ASTContext.h248
-rw-r--r--include/clang/AST/ASTImporter.h19
-rw-r--r--include/clang/AST/ASTMutationListener.h4
-rw-r--r--include/clang/AST/ASTTypeTraits.h6
-rw-r--r--include/clang/AST/ASTVector.h3
-rw-r--r--include/clang/AST/Attr.h11
-rw-r--r--include/clang/AST/AttrIterator.h3
-rw-r--r--include/clang/AST/CXXInheritance.h4
-rw-r--r--include/clang/AST/CanonicalType.h8
-rw-r--r--include/clang/AST/CommentLexer.h1
-rw-r--r--include/clang/AST/Decl.h135
-rw-r--r--include/clang/AST/DeclBase.h20
-rw-r--r--include/clang/AST/DeclCXX.h322
-rw-r--r--include/clang/AST/DeclFriend.h2
-rw-r--r--include/clang/AST/DeclGroup.h2
-rw-r--r--include/clang/AST/DeclObjC.h8
-rw-r--r--include/clang/AST/DeclOpenMP.h11
-rw-r--r--include/clang/AST/DeclTemplate.h81
-rw-r--r--include/clang/AST/Expr.h139
-rw-r--r--include/clang/AST/ExprCXX.h89
-rw-r--r--include/clang/AST/ExprObjC.h2
-rw-r--r--include/clang/AST/Mangle.h8
-rw-r--r--include/clang/AST/MangleNumberingContext.h3
-rw-r--r--include/clang/AST/OpenMPClause.h233
-rw-r--r--include/clang/AST/OperationKinds.def5
-rw-r--r--include/clang/AST/RecursiveASTVisitor.h145
-rw-r--r--include/clang/AST/Redeclarable.h65
-rw-r--r--include/clang/AST/Stmt.h23
-rw-r--r--include/clang/AST/StmtCXX.h13
-rw-r--r--include/clang/AST/StmtGraphTraits.h14
-rw-r--r--include/clang/AST/StmtOpenMP.h552
-rw-r--r--include/clang/AST/TemplateBase.h14
-rw-r--r--include/clang/AST/Type.h285
-rw-r--r--include/clang/AST/TypeLoc.h127
-rw-r--r--include/clang/AST/TypeNodes.def1
-rw-r--r--include/clang/AST/UnresolvedSet.h5
-rw-r--r--include/clang/AST/VTTBuilder.h1
-rw-r--r--include/clang/AST/VTableBuilder.h144
-rw-r--r--include/clang/ASTMatchers/ASTMatchFinder.h7
-rw-r--r--include/clang/ASTMatchers/ASTMatchers.h245
-rw-r--r--include/clang/ASTMatchers/ASTMatchersInternal.h29
-rw-r--r--include/clang/ASTMatchers/ASTMatchersMacros.h4
-rw-r--r--include/clang/ASTMatchers/Dynamic/Registry.h33
-rw-r--r--include/clang/ASTMatchers/Dynamic/VariantValue.h5
-rw-r--r--include/clang/Analysis/Analyses/Consumed.h5
-rw-r--r--include/clang/Analysis/Analyses/Dominators.h28
-rw-r--r--include/clang/Analysis/Analyses/FormatString.h49
-rw-r--r--include/clang/Analysis/Analyses/LiveVariables.h1
-rw-r--r--include/clang/Analysis/Analyses/OSLog.h155
-rw-r--r--include/clang/Analysis/Analyses/ThreadSafetyCommon.h21
-rw-r--r--include/clang/Analysis/Analyses/ThreadSafetyUtil.h2
-rw-r--r--include/clang/Analysis/AnalysisContext.h3
-rw-r--r--include/clang/Analysis/CFG.h152
-rw-r--r--include/clang/Analysis/CallGraph.h60
-rw-r--r--include/clang/Analysis/CloneDetection.h288
-rw-r--r--include/clang/Analysis/ProgramPoint.h4
-rw-r--r--include/clang/Basic/Attr.td90
-rw-r--r--include/clang/Basic/AttrDocs.td550
-rw-r--r--include/clang/Basic/Attributes.h2
-rw-r--r--include/clang/Basic/Builtins.def106
-rw-r--r--include/clang/Basic/Builtins.h7
-rw-r--r--include/clang/Basic/BuiltinsAMDGPU.def20
-rw-r--r--include/clang/Basic/BuiltinsARM.def27
-rw-r--r--include/clang/Basic/BuiltinsNVPTX.def73
-rw-r--r--include/clang/Basic/BuiltinsPPC.def78
-rw-r--r--include/clang/Basic/BuiltinsX86.def459
-rw-r--r--include/clang/Basic/BuiltinsX86_64.def90
-rw-r--r--include/clang/Basic/DeclNodes.td4
-rw-r--r--include/clang/Basic/Diagnostic.h79
-rw-r--r--include/clang/Basic/Diagnostic.td3
-rw-r--r--include/clang/Basic/DiagnosticASTKinds.td6
-rw-r--r--include/clang/Basic/DiagnosticCommonKinds.td4
-rw-r--r--include/clang/Basic/DiagnosticDocs.td84
-rw-r--r--include/clang/Basic/DiagnosticDriverKinds.td28
-rw-r--r--include/clang/Basic/DiagnosticFrontendKinds.td9
-rw-r--r--include/clang/Basic/DiagnosticGroups.td51
-rw-r--r--include/clang/Basic/DiagnosticLexKinds.td11
-rw-r--r--include/clang/Basic/DiagnosticOptions.def1
-rw-r--r--include/clang/Basic/DiagnosticParseKinds.td94
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td663
-rw-r--r--include/clang/Basic/DiagnosticSerializationKinds.td6
-rw-r--r--include/clang/Basic/FileManager.h43
-rw-r--r--include/clang/Basic/FileSystemStatCache.h8
-rw-r--r--include/clang/Basic/IdentifierTable.h75
-rw-r--r--include/clang/Basic/LLVM.h4
-rw-r--r--include/clang/Basic/LangOptions.def13
-rw-r--r--include/clang/Basic/LangOptions.h19
-rw-r--r--include/clang/Basic/Linkage.h4
-rw-r--r--include/clang/Basic/Module.h4
-rw-r--r--include/clang/Basic/ObjCRuntime.h1
-rw-r--r--include/clang/Basic/OpenCLExtensions.def5
-rw-r--r--include/clang/Basic/OpenCLImageTypes.def100
-rw-r--r--include/clang/Basic/OpenCLOptions.h124
-rw-r--r--include/clang/Basic/OpenMPKinds.def183
-rw-r--r--include/clang/Basic/OpenMPKinds.h22
-rw-r--r--include/clang/Basic/PlistSupport.h1
-rw-r--r--include/clang/Basic/SourceManager.h64
-rw-r--r--include/clang/Basic/SourceManagerInternals.h4
-rw-r--r--include/clang/Basic/Specifiers.h2
-rw-r--r--include/clang/Basic/StmtNodes.td10
-rw-r--r--include/clang/Basic/TargetBuiltins.h12
-rw-r--r--include/clang/Basic/TargetCXXABI.h1
-rw-r--r--include/clang/Basic/TargetInfo.h58
-rw-r--r--include/clang/Basic/TargetOptions.h4
-rw-r--r--include/clang/Basic/TokenKinds.def10
-rw-r--r--include/clang/Basic/Version.h20
-rw-r--r--include/clang/Basic/Version.inc.in3
-rw-r--r--include/clang/Basic/VirtualFileSystem.h63
-rw-r--r--include/clang/CodeGen/CGFunctionInfo.h23
-rw-r--r--include/clang/CodeGen/ModuleBuilder.h1
-rw-r--r--include/clang/CodeGen/ObjectFilePCHContainerOperations.h6
-rw-r--r--include/clang/CodeGen/SwiftCallingConv.h6
-rw-r--r--include/clang/Config/config.h.cmake9
-rw-r--r--include/clang/Driver/Action.h95
-rw-r--r--include/clang/Driver/CC1Options.td51
-rw-r--r--include/clang/Driver/CLCompatOptions.td15
-rw-r--r--include/clang/Driver/Compilation.h41
-rw-r--r--include/clang/Driver/Distro.h122
-rw-r--r--include/clang/Driver/Driver.h102
-rw-r--r--include/clang/Driver/Job.h3
-rw-r--r--include/clang/Driver/Multilib.h1
-rw-r--r--include/clang/Driver/Options.td188
-rw-r--r--include/clang/Driver/SanitizerArgs.h4
-rw-r--r--include/clang/Driver/Tool.h14
-rw-r--r--include/clang/Driver/ToolChain.h55
-rw-r--r--include/clang/Driver/Types.def3
-rw-r--r--include/clang/Driver/Types.h19
-rw-r--r--include/clang/Edit/Rewriters.h1
-rw-r--r--include/clang/Format/Format.h49
-rw-r--r--include/clang/Frontend/ASTUnit.h8
-rw-r--r--include/clang/Frontend/CodeGenOptions.def33
-rw-r--r--include/clang/Frontend/CodeGenOptions.h24
-rw-r--r--include/clang/Frontend/CompilerInstance.h9
-rw-r--r--include/clang/Frontend/CompilerInvocation.h15
-rw-r--r--include/clang/Frontend/DiagnosticRenderer.h1
-rw-r--r--include/clang/Frontend/FrontendActions.h39
-rw-r--r--include/clang/Frontend/FrontendOptions.h7
-rw-r--r--include/clang/Frontend/FrontendPluginRegistry.h3
-rw-r--r--include/clang/Frontend/LangStandards.def2
-rw-r--r--include/clang/Frontend/PCHContainerOperations.h12
-rw-r--r--include/clang/Frontend/PreprocessorOutputOptions.h2
-rw-r--r--include/clang/Frontend/SerializedDiagnosticReader.h1
-rw-r--r--include/clang/Frontend/TextDiagnostic.h2
-rw-r--r--include/clang/Frontend/Utils.h4
-rw-r--r--include/clang/Index/CommentToXML.h5
-rw-r--r--include/clang/Index/IndexSymbol.h20
-rw-r--r--include/clang/Lex/DirectoryLookup.h2
-rw-r--r--include/clang/Lex/HeaderMap.h2
-rw-r--r--include/clang/Lex/HeaderSearch.h27
-rw-r--r--include/clang/Lex/HeaderSearchOptions.h14
-rw-r--r--include/clang/Lex/LiteralSupport.h2
-rw-r--r--include/clang/Lex/ModuleLoader.h25
-rw-r--r--include/clang/Lex/ModuleMap.h44
-rw-r--r--include/clang/Lex/PPCallbacks.h4
-rw-r--r--include/clang/Lex/PTHManager.h7
-rw-r--r--include/clang/Lex/PreprocessingRecord.h23
-rw-r--r--include/clang/Lex/Preprocessor.h47
-rw-r--r--include/clang/Lex/PreprocessorOptions.h1
-rw-r--r--include/clang/Parse/Parser.h91
-rw-r--r--include/clang/Rewrite/Core/HTMLRewrite.h4
-rw-r--r--include/clang/Sema/AttributeList.h24
-rw-r--r--include/clang/Sema/CodeCompleteConsumer.h17
-rw-r--r--include/clang/Sema/DeclSpec.h251
-rw-r--r--include/clang/Sema/DelayedDiagnostic.h44
-rw-r--r--include/clang/Sema/ExternalSemaSource.h3
-rw-r--r--include/clang/Sema/Initialization.h90
-rw-r--r--include/clang/Sema/MultiplexExternalSemaSource.h4
-rw-r--r--include/clang/Sema/Overload.h37
-rw-r--r--include/clang/Sema/Ownership.h1
-rw-r--r--include/clang/Sema/ScopeInfo.h18
-rw-r--r--include/clang/Sema/Sema.h914
-rw-r--r--include/clang/Sema/SemaInternal.h6
-rw-r--r--include/clang/Sema/Template.h9
-rw-r--r--include/clang/Sema/TemplateDeduction.h23
-rw-r--r--include/clang/Sema/TypoCorrection.h11
-rw-r--r--include/clang/Serialization/ASTBitCodes.h65
-rw-r--r--include/clang/Serialization/ASTReader.h349
-rw-r--r--include/clang/Serialization/ASTWriter.h29
-rw-r--r--include/clang/Serialization/Module.h10
-rw-r--r--include/clang/Serialization/ModuleManager.h2
-rw-r--r--include/clang/StaticAnalyzer/Checkers/Checkers.td99
-rw-r--r--include/clang/StaticAnalyzer/Checkers/MPIFunctionClassifier.h (renamed from lib/StaticAnalyzer/Checkers/MPI-Checker/MPIFunctionClassifier.h)0
-rw-r--r--include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h10
-rw-r--r--include/clang/StaticAnalyzer/Checkers/SValExplainer.h15
-rw-r--r--include/clang/StaticAnalyzer/Core/AnalyzerOptions.h16
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h70
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h24
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/BugType.h1
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h26
-rw-r--r--include/clang/StaticAnalyzer/Core/Checker.h9
-rw-r--r--include/clang/StaticAnalyzer/Core/CheckerManager.h14
-rw-r--r--include/clang/StaticAnalyzer/Core/CheckerRegistry.h4
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h48
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h35
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h5
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h51
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h23
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h6
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h77
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h10
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h18
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SVals.def1
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h46
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/Store.h8
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h7
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SummaryManager.h3
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h18
-rw-r--r--include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h5
-rw-r--r--include/clang/StaticAnalyzer/Frontend/FrontendActions.h3
-rw-r--r--include/clang/Tooling/CompilationDatabase.h8
-rw-r--r--include/clang/Tooling/Core/Replacement.h236
-rw-r--r--include/clang/Tooling/FileMatchTrie.h7
-rw-r--r--include/clang/Tooling/JSONCompilationDatabase.h23
-rw-r--r--include/clang/Tooling/Refactoring.h22
-rw-r--r--include/clang/Tooling/ReplacementsYaml.h1
-rw-r--r--include/clang/module.modulemap1
-rw-r--r--lib/ARCMigrate/ARCMT.cpp1
-rw-r--r--lib/ARCMigrate/FileRemapper.cpp2
-rw-r--r--lib/ARCMigrate/Transforms.cpp5
-rw-r--r--lib/AST/APValue.cpp21
-rw-r--r--lib/AST/ASTContext.cpp619
-rw-r--r--lib/AST/ASTDiagnostic.cpp18
-rw-r--r--lib/AST/ASTDumper.cpp58
-rw-r--r--lib/AST/ASTImporter.cpp726
-rw-r--r--lib/AST/ASTTypeTraits.cpp5
-rw-r--r--lib/AST/AttrImpl.cpp3
-rw-r--r--lib/AST/CXXABI.h9
-rw-r--r--lib/AST/CXXInheritance.cpp1
-rw-r--r--lib/AST/Comment.cpp157
-rw-r--r--lib/AST/CommentBriefParser.cpp1
-rw-r--r--lib/AST/CommentLexer.cpp10
-rw-r--r--lib/AST/CommentParser.cpp2
-rw-r--r--lib/AST/CommentSema.cpp11
-rw-r--r--lib/AST/Decl.cpp164
-rw-r--r--lib/AST/DeclBase.cpp96
-rw-r--r--lib/AST/DeclCXX.cpp198
-rw-r--r--lib/AST/DeclGroup.cpp3
-rw-r--r--lib/AST/DeclObjC.cpp29
-rw-r--r--lib/AST/DeclOpenMP.cpp13
-rw-r--r--lib/AST/DeclPrinter.cpp237
-rw-r--r--lib/AST/DeclTemplate.cpp109
-rw-r--r--lib/AST/DeclarationName.cpp13
-rw-r--r--lib/AST/Expr.cpp185
-rw-r--r--lib/AST/ExprCXX.cpp101
-rw-r--r--lib/AST/ExprClassification.cpp21
-rw-r--r--lib/AST/ExprConstant.cpp1053
-rw-r--r--lib/AST/ExprObjC.cpp2
-rw-r--r--lib/AST/ItaniumCXXABI.cpp18
-rw-r--r--lib/AST/ItaniumMangle.cpp163
-rw-r--r--lib/AST/Mangle.cpp3
-rw-r--r--lib/AST/MicrosoftCXXABI.cpp17
-rw-r--r--lib/AST/MicrosoftMangle.cpp114
-rw-r--r--lib/AST/NestedNameSpecifier.cpp13
-rw-r--r--lib/AST/OpenMPClause.cpp127
-rw-r--r--lib/AST/RawCommentList.cpp9
-rw-r--r--lib/AST/Stmt.cpp30
-rw-r--r--lib/AST/StmtCXX.cpp4
-rw-r--r--lib/AST/StmtObjC.cpp4
-rw-r--r--lib/AST/StmtOpenMP.cpp609
-rw-r--r--lib/AST/StmtPrinter.cpp58
-rw-r--r--lib/AST/StmtProfile.cpp58
-rw-r--r--lib/AST/TemplateBase.cpp27
-rw-r--r--lib/AST/Type.cpp136
-rw-r--r--lib/AST/TypeLoc.cpp16
-rw-r--r--lib/AST/TypePrinter.cpp31
-rw-r--r--lib/AST/VTableBuilder.cpp230
-rw-r--r--lib/ASTMatchers/ASTMatchFinder.cpp38
-rw-r--r--lib/ASTMatchers/ASTMatchersInternal.cpp13
-rw-r--r--lib/ASTMatchers/Dynamic/Marshallers.h69
-rw-r--r--lib/ASTMatchers/Dynamic/Parser.cpp1
-rw-r--r--lib/ASTMatchers/Dynamic/Registry.cpp61
-rw-r--r--lib/Analysis/AnalysisDeclContext.cpp14
-rw-r--r--lib/Analysis/CFG.cpp50
-rw-r--r--lib/Analysis/CMakeLists.txt2
-rw-r--r--lib/Analysis/CallGraph.cpp18
-rw-r--r--lib/Analysis/CloneDetection.cpp894
-rw-r--r--lib/Analysis/Consumed.cpp5
-rw-r--r--lib/Analysis/FormatString.cpp27
-rw-r--r--lib/Analysis/FormatStringParsing.h1
-rw-r--r--lib/Analysis/LiveVariables.cpp27
-rw-r--r--lib/Analysis/OSLog.cpp202
-rw-r--r--lib/Analysis/PrintfFormatString.cpp43
-rw-r--r--lib/Analysis/ReachableCode.cpp2
-rw-r--r--lib/Analysis/ScanfFormatString.cpp6
-rw-r--r--lib/Analysis/ThreadSafety.cpp8
-rw-r--r--lib/Analysis/ThreadSafetyCommon.cpp9
-rw-r--r--lib/Analysis/UninitializedValues.cpp3
-rw-r--r--lib/Basic/CMakeLists.txt2
-rw-r--r--lib/Basic/Diagnostic.cpp21
-rw-r--r--lib/Basic/DiagnosticOptions.cpp2
-rw-r--r--lib/Basic/FileManager.cpp24
-rw-r--r--lib/Basic/FileSystemStatCache.cpp6
-rw-r--r--lib/Basic/IdentifierTable.cpp18
-rw-r--r--lib/Basic/LangOptions.cpp7
-rw-r--r--lib/Basic/Module.cpp11
-rw-r--r--lib/Basic/OpenMPKinds.cpp137
-rw-r--r--lib/Basic/SourceLocation.cpp1
-rw-r--r--lib/Basic/SourceManager.cpp40
-rw-r--r--lib/Basic/TargetInfo.cpp48
-rw-r--r--lib/Basic/Targets.cpp590
-rw-r--r--lib/Basic/Version.cpp2
-rw-r--r--lib/Basic/VirtualFileSystem.cpp134
-rw-r--r--lib/CodeGen/ABIInfo.h2
-rw-r--r--lib/CodeGen/BackendUtil.cpp390
-rw-r--r--lib/CodeGen/CGAtomic.cpp6
-rw-r--r--lib/CodeGen/CGBlocks.cpp152
-rw-r--r--lib/CodeGen/CGBlocks.h17
-rw-r--r--lib/CodeGen/CGBuilder.h18
-rw-r--r--lib/CodeGen/CGBuiltin.cpp1093
-rw-r--r--lib/CodeGen/CGCUDABuiltin.cpp6
-rw-r--r--lib/CodeGen/CGCUDANV.cpp92
-rw-r--r--lib/CodeGen/CGCUDARuntime.cpp11
-rw-r--r--lib/CodeGen/CGCXX.cpp67
-rw-r--r--lib/CodeGen/CGCXXABI.cpp5
-rw-r--r--lib/CodeGen/CGCXXABI.h13
-rw-r--r--lib/CodeGen/CGCall.cpp352
-rw-r--r--lib/CodeGen/CGCall.h143
-rw-r--r--lib/CodeGen/CGClass.cpp246
-rw-r--r--lib/CodeGen/CGCleanup.cpp2
-rw-r--r--lib/CodeGen/CGCleanup.h3
-rw-r--r--lib/CodeGen/CGCoroutine.cpp116
-rw-r--r--lib/CodeGen/CGDebugInfo.cpp593
-rw-r--r--lib/CodeGen/CGDebugInfo.h54
-rw-r--r--lib/CodeGen/CGDecl.cpp122
-rw-r--r--lib/CodeGen/CGDeclCXX.cpp9
-rw-r--r--lib/CodeGen/CGException.cpp14
-rw-r--r--lib/CodeGen/CGExpr.cpp383
-rw-r--r--lib/CodeGen/CGExprAgg.cpp115
-rw-r--r--lib/CodeGen/CGExprCXX.cpp684
-rw-r--r--lib/CodeGen/CGExprComplex.cpp11
-rw-r--r--lib/CodeGen/CGExprConstant.cpp99
-rw-r--r--lib/CodeGen/CGExprScalar.cpp149
-rw-r--r--lib/CodeGen/CGLoopInfo.cpp31
-rw-r--r--lib/CodeGen/CGLoopInfo.h11
-rw-r--r--lib/CodeGen/CGObjC.cpp49
-rw-r--r--lib/CodeGen/CGObjCGNU.cpp1059
-rw-r--r--lib/CodeGen/CGObjCMac.cpp2207
-rw-r--r--lib/CodeGen/CGObjCRuntime.cpp27
-rw-r--r--lib/CodeGen/CGObjCRuntime.h3
-rw-r--r--lib/CodeGen/CGOpenCLRuntime.cpp38
-rw-r--r--lib/CodeGen/CGOpenCLRuntime.h14
-rw-r--r--lib/CodeGen/CGOpenMPRuntime.cpp613
-rw-r--r--lib/CodeGen/CGOpenMPRuntime.h50
-rw-r--r--lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp5
-rw-r--r--lib/CodeGen/CGOpenMPRuntimeNVPTX.h7
-rw-r--r--lib/CodeGen/CGStmt.cpp64
-rw-r--r--lib/CodeGen/CGStmtOpenMP.cpp256
-rw-r--r--lib/CodeGen/CGVTT.cpp16
-rw-r--r--lib/CodeGen/CGVTables.cpp328
-rw-r--r--lib/CodeGen/CGVTables.h33
-rw-r--r--lib/CodeGen/CMakeLists.txt7
-rw-r--r--lib/CodeGen/CodeGenAction.cpp133
-rw-r--r--lib/CodeGen/CodeGenFunction.cpp143
-rw-r--r--lib/CodeGen/CodeGenFunction.h177
-rw-r--r--lib/CodeGen/CodeGenModule.cpp607
-rw-r--r--lib/CodeGen/CodeGenModule.h97
-rw-r--r--lib/CodeGen/CodeGenPGO.cpp4
-rw-r--r--lib/CodeGen/CodeGenPGO.h2
-rw-r--r--lib/CodeGen/CodeGenTypeCache.h5
-rw-r--r--lib/CodeGen/CodeGenTypes.cpp24
-rw-r--r--lib/CodeGen/CodeGenTypes.h10
-rw-r--r--lib/CodeGen/ConstantBuilder.h444
-rw-r--r--lib/CodeGen/CoverageMappingGen.cpp73
-rw-r--r--lib/CodeGen/CoverageMappingGen.h1
-rw-r--r--lib/CodeGen/EHScopeStack.h6
-rw-r--r--lib/CodeGen/ItaniumCXXABI.cpp293
-rw-r--r--lib/CodeGen/MicrosoftCXXABI.cpp314
-rw-r--r--lib/CodeGen/ModuleBuilder.cpp2
-rw-r--r--lib/CodeGen/ObjectFilePCHContainerOperations.cpp37
-rw-r--r--lib/CodeGen/SanitizerMetadata.cpp8
-rw-r--r--lib/CodeGen/SwiftCallingConv.cpp9
-rw-r--r--lib/CodeGen/TargetInfo.cpp488
-rw-r--r--lib/CodeGen/TargetInfo.h16
-rw-r--r--lib/CodeGen/VarBypassDetector.cpp168
-rw-r--r--lib/CodeGen/VarBypassDetector.h70
-rw-r--r--lib/Driver/Action.cpp57
-rw-r--r--lib/Driver/CMakeLists.txt1
-rw-r--r--lib/Driver/Compilation.cpp17
-rw-r--r--lib/Driver/CrossWindowsToolChain.cpp1
-rw-r--r--lib/Driver/Distro.cpp134
-rw-r--r--lib/Driver/Driver.cpp1921
-rw-r--r--lib/Driver/Job.cpp141
-rw-r--r--lib/Driver/MSVCToolChain.cpp105
-rw-r--r--lib/Driver/Multilib.cpp2
-rw-r--r--lib/Driver/SanitizerArgs.cpp67
-rw-r--r--lib/Driver/Tool.cpp10
-rw-r--r--lib/Driver/ToolChain.cpp194
-rw-r--r--lib/Driver/ToolChains.cpp1133
-rw-r--r--lib/Driver/ToolChains.h318
-rw-r--r--lib/Driver/Tools.cpp1755
-rw-r--r--lib/Driver/Tools.h46
-rw-r--r--lib/Driver/Types.cpp116
-rw-r--r--lib/Edit/RewriteObjCFoundationAPI.cpp2
-rw-r--r--lib/Format/BreakableToken.cpp16
-rw-r--r--lib/Format/CMakeLists.txt1
-rw-r--r--lib/Format/Comments.cpp36
-rw-r--r--lib/Format/Comments.h33
-rw-r--r--lib/Format/ContinuationIndenter.cpp14
-rw-r--r--lib/Format/Encoding.h29
-rw-r--r--lib/Format/Format.cpp498
-rw-r--r--lib/Format/FormatToken.cpp15
-rw-r--r--lib/Format/FormatToken.h19
-rw-r--r--lib/Format/FormatTokenLexer.cpp70
-rw-r--r--lib/Format/FormatTokenLexer.h21
-rw-r--r--lib/Format/SortJavaScriptImports.cpp62
-rw-r--r--lib/Format/TokenAnalyzer.cpp16
-rw-r--r--lib/Format/TokenAnalyzer.h7
-rw-r--r--lib/Format/TokenAnnotator.cpp197
-rw-r--r--lib/Format/TokenAnnotator.h1
-rw-r--r--lib/Format/UnwrappedLineFormatter.cpp3
-rw-r--r--lib/Format/UnwrappedLineFormatter.h2
-rw-r--r--lib/Format/UnwrappedLineParser.cpp46
-rw-r--r--lib/Format/WhitespaceManager.cpp15
-rw-r--r--lib/Format/WhitespaceManager.h3
-rw-r--r--lib/Frontend/ASTConsumers.cpp1
-rw-r--r--lib/Frontend/ASTUnit.cpp13
-rw-r--r--lib/Frontend/CacheTokens.cpp30
-rw-r--r--lib/Frontend/ChainedIncludesSource.cpp3
-rw-r--r--lib/Frontend/CompilerInstance.cpp228
-rw-r--r--lib/Frontend/CompilerInvocation.cpp211
-rw-r--r--lib/Frontend/DependencyFile.cpp19
-rw-r--r--lib/Frontend/DiagnosticRenderer.cpp2
-rw-r--r--lib/Frontend/FrontendAction.cpp12
-rw-r--r--lib/Frontend/FrontendActions.cpp116
-rw-r--r--lib/Frontend/FrontendOptions.cpp2
-rw-r--r--lib/Frontend/InitHeaderSearch.cpp7
-rw-r--r--lib/Frontend/InitPreprocessor.cpp82
-rw-r--r--lib/Frontend/ModuleDependencyCollector.cpp66
-rw-r--r--lib/Frontend/MultiplexConsumer.cpp6
-rw-r--r--lib/Frontend/PCHContainerOperations.cpp7
-rw-r--r--lib/Frontend/PrintPreprocessedOutput.cpp34
-rw-r--r--lib/Frontend/Rewrite/FrontendActions.cpp3
-rw-r--r--lib/Frontend/Rewrite/HTMLPrint.cpp5
-rw-r--r--lib/Frontend/Rewrite/InclusionRewriter.cpp6
-rw-r--r--lib/Frontend/Rewrite/RewriteModernObjC.cpp33
-rw-r--r--lib/Frontend/Rewrite/RewriteObjC.cpp36
-rw-r--r--lib/Frontend/Rewrite/RewriteTest.cpp4
-rw-r--r--lib/Frontend/SerializedDiagnosticPrinter.cpp5
-rw-r--r--lib/Frontend/SerializedDiagnosticReader.cpp17
-rw-r--r--lib/Frontend/TextDiagnostic.cpp37
-rw-r--r--lib/Frontend/TextDiagnosticPrinter.cpp2
-rw-r--r--lib/Frontend/VerifyDiagnosticConsumer.cpp3
-rw-r--r--lib/FrontendTool/ExecuteCompilerInvocation.cpp10
-rw-r--r--lib/Headers/CMakeLists.txt18
-rw-r--r--lib/Headers/__clang_cuda_builtin_vars.h (renamed from lib/Headers/cuda_builtin_vars.h)0
-rw-r--r--lib/Headers/__clang_cuda_cmath.h341
-rw-r--r--lib/Headers/__clang_cuda_complex_builtins.h203
-rw-r--r--lib/Headers/__clang_cuda_math_forward_declares.h25
-rw-r--r--lib/Headers/__clang_cuda_runtime_wrapper.h46
-rw-r--r--lib/Headers/__wmmintrin_aes.h12
-rw-r--r--lib/Headers/__wmmintrin_pclmul.h15
-rw-r--r--lib/Headers/altivec.h2274
-rw-r--r--lib/Headers/ammintrin.h77
-rw-r--r--lib/Headers/armintr.h45
-rw-r--r--lib/Headers/avx512bwintrin.h428
-rw-r--r--lib/Headers/avx512dqintrin.h437
-rw-r--r--lib/Headers/avx512fintrin.h2346
-rw-r--r--lib/Headers/avx512vlbwintrin.h1822
-rw-r--r--lib/Headers/avx512vldqintrin.h439
-rw-r--r--lib/Headers/avx512vlintrin.h2470
-rw-r--r--lib/Headers/avxintrin.h3096
-rw-r--r--lib/Headers/bmiintrin.h64
-rw-r--r--lib/Headers/cuda_wrappers/algorithm96
-rw-r--r--lib/Headers/cuda_wrappers/complex82
-rw-r--r--lib/Headers/cuda_wrappers/new47
-rw-r--r--lib/Headers/emmintrin.h2546
-rw-r--r--lib/Headers/f16cintrin.h28
-rw-r--r--lib/Headers/float.h7
-rw-r--r--lib/Headers/fxsrintrin.h62
-rw-r--r--lib/Headers/ia32intrin.h6
-rw-r--r--lib/Headers/immintrin.h35
-rw-r--r--lib/Headers/intrin.h682
-rw-r--r--lib/Headers/lzcntintrin.h50
-rw-r--r--lib/Headers/mmintrin.h174
-rw-r--r--lib/Headers/module.modulemap2
-rw-r--r--lib/Headers/opencl-c.h655
-rw-r--r--lib/Headers/pmmintrin.h53
-rw-r--r--lib/Headers/popcntintrin.h8
-rw-r--r--lib/Headers/stdatomic.h10
-rw-r--r--lib/Headers/tmmintrin.h42
-rw-r--r--lib/Headers/xmmintrin.h579
-rw-r--r--lib/Index/CommentToXML.cpp45
-rw-r--r--lib/Index/IndexBody.cpp45
-rw-r--r--lib/Index/IndexDecl.cpp46
-rw-r--r--lib/Index/IndexSymbol.cpp130
-rw-r--r--lib/Index/IndexingContext.cpp20
-rw-r--r--lib/Index/USRGeneration.cpp32
-rw-r--r--lib/Lex/HeaderMap.cpp2
-rw-r--r--lib/Lex/HeaderSearch.cpp128
-rw-r--r--lib/Lex/Lexer.cpp82
-rw-r--r--lib/Lex/LiteralSupport.cpp52
-rw-r--r--lib/Lex/MacroInfo.cpp2
-rw-r--r--lib/Lex/ModuleMap.cpp119
-rw-r--r--lib/Lex/PPCaching.cpp4
-rw-r--r--lib/Lex/PPDirectives.cpp87
-rw-r--r--lib/Lex/PPExpressions.cpp17
-rw-r--r--lib/Lex/PPLexerChange.cpp16
-rw-r--r--lib/Lex/PPMacroExpansion.cpp95
-rw-r--r--lib/Lex/PTHLexer.cpp17
-rw-r--r--lib/Lex/Pragma.cpp66
-rw-r--r--lib/Lex/PreprocessingRecord.cpp15
-rw-r--r--lib/Lex/Preprocessor.cpp73
-rw-r--r--lib/Lex/TokenConcatenation.cpp2
-rw-r--r--lib/Lex/TokenLexer.cpp11
-rw-r--r--lib/Parse/ParseAST.cpp22
-rw-r--r--lib/Parse/ParseCXXInlineMethods.cpp52
-rw-r--r--lib/Parse/ParseDecl.cpp211
-rw-r--r--lib/Parse/ParseDeclCXX.cpp539
-rw-r--r--lib/Parse/ParseExpr.cpp19
-rw-r--r--lib/Parse/ParseExprCXX.cpp168
-rw-r--r--lib/Parse/ParseInit.cpp3
-rw-r--r--lib/Parse/ParseObjc.cpp47
-rw-r--r--lib/Parse/ParseOpenMP.cpp58
-rw-r--r--lib/Parse/ParsePragma.cpp201
-rw-r--r--lib/Parse/ParseStmt.cpp10
-rw-r--r--lib/Parse/ParseStmtAsm.cpp6
-rw-r--r--lib/Parse/ParseTemplate.cpp12
-rw-r--r--lib/Parse/ParseTentative.cpp13
-rw-r--r--lib/Parse/Parser.cpp219
-rw-r--r--lib/Rewrite/HTMLRewrite.cpp19
-rw-r--r--lib/Sema/AnalysisBasedWarnings.cpp60
-rw-r--r--lib/Sema/AttributeList.cpp3
-rw-r--r--lib/Sema/CodeCompleteConsumer.cpp31
-rw-r--r--lib/Sema/DeclSpec.cpp95
-rw-r--r--lib/Sema/DelayedDiagnostic.cpp33
-rw-r--r--lib/Sema/JumpDiagnostics.cpp23
-rw-r--r--lib/Sema/MultiplexExternalSemaSource.cpp3
-rw-r--r--lib/Sema/ScopeInfo.cpp2
-rw-r--r--lib/Sema/Sema.cpp192
-rw-r--r--lib/Sema/SemaAttr.cpp2
-rw-r--r--lib/Sema/SemaCUDA.cpp520
-rw-r--r--lib/Sema/SemaCXXScopeSpec.cpp133
-rw-r--r--lib/Sema/SemaCast.cpp50
-rw-r--r--lib/Sema/SemaChecking.cpp1250
-rw-r--r--lib/Sema/SemaCodeComplete.cpp397
-rw-r--r--lib/Sema/SemaCoroutine.cpp373
-rw-r--r--lib/Sema/SemaDecl.cpp1311
-rw-r--r--lib/Sema/SemaDeclAttr.cpp626
-rw-r--r--lib/Sema/SemaDeclCXX.cpp1223
-rw-r--r--lib/Sema/SemaDeclObjC.cpp49
-rw-r--r--lib/Sema/SemaExceptionSpec.cpp240
-rw-r--r--lib/Sema/SemaExpr.cpp885
-rw-r--r--lib/Sema/SemaExprCXX.cpp1908
-rw-r--r--lib/Sema/SemaExprMember.cpp111
-rw-r--r--lib/Sema/SemaExprObjC.cpp22
-rw-r--r--lib/Sema/SemaInit.cpp1192
-rw-r--r--lib/Sema/SemaLambda.cpp125
-rw-r--r--lib/Sema/SemaLookup.cpp38
-rw-r--r--lib/Sema/SemaObjCProperty.cpp48
-rw-r--r--lib/Sema/SemaOpenMP.cpp2179
-rw-r--r--lib/Sema/SemaOverload.cpp548
-rw-r--r--lib/Sema/SemaPseudoObject.cpp14
-rw-r--r--lib/Sema/SemaStmt.cpp26
-rw-r--r--lib/Sema/SemaStmtAsm.cpp81
-rw-r--r--lib/Sema/SemaStmtAttr.cpp10
-rw-r--r--lib/Sema/SemaTemplate.cpp957
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp1669
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp144
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp457
-rw-r--r--lib/Sema/SemaTemplateVariadic.cpp84
-rw-r--r--lib/Sema/SemaType.cpp693
-rw-r--r--lib/Sema/TreeTransform.h423
-rw-r--r--lib/Sema/TypeLocBuilder.h2
-rw-r--r--lib/Serialization/ASTCommon.cpp5
-rw-r--r--lib/Serialization/ASTCommon.h1
-rw-r--r--lib/Serialization/ASTReader.cpp1067
-rw-r--r--lib/Serialization/ASTReaderDecl.cpp1427
-rw-r--r--lib/Serialization/ASTReaderInternals.h17
-rw-r--r--lib/Serialization/ASTReaderStmt.cpp2196
-rw-r--r--lib/Serialization/ASTWriter.cpp297
-rw-r--r--lib/Serialization/ASTWriterDecl.cpp75
-rw-r--r--lib/Serialization/ASTWriterStmt.cpp109
-rw-r--r--lib/Serialization/GeneratePCH.cpp27
-rw-r--r--lib/Serialization/GlobalModuleIndex.cpp12
-rw-r--r--lib/Serialization/Module.cpp1
-rw-r--r--lib/Serialization/ModuleFileExtension.cpp1
-rw-r--r--lib/Serialization/ModuleManager.cpp101
-rw-r--r--lib/Serialization/MultiOnDiskHashTable.h4
-rw-r--r--lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp68
-rw-r--r--lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp92
-rw-r--r--lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp77
-rw-r--r--lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp109
-rw-r--r--lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp1
-rw-r--r--lib/StaticAnalyzer/Checkers/CMakeLists.txt11
-rw-r--r--lib/StaticAnalyzer/Checkers/CStringChecker.cpp8
-rw-r--r--lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp62
-rw-r--r--lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp21
-rw-r--r--lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp7
-rw-r--r--lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp87
-rw-r--r--lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp33
-rw-r--r--lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp1
-rw-r--r--lib/StaticAnalyzer/Checkers/ChrootChecker.cpp1
-rw-r--r--lib/StaticAnalyzer/Checkers/CloneChecker.cpp161
-rw-r--r--lib/StaticAnalyzer/Checkers/ConversionChecker.cpp192
-rw-r--r--lib/StaticAnalyzer/Checkers/DynamicTypeChecker.cpp7
-rw-r--r--lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp40
-rw-r--r--lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp105
-rw-r--r--lib/StaticAnalyzer/Checkers/GTestChecker.cpp299
-rw-r--r--lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp44
-rw-r--r--lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.h4
-rw-r--r--lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp9
-rw-r--r--lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.h12
-rw-r--r--lib/StaticAnalyzer/Checkers/MPI-Checker/MPIFunctionClassifier.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/MPI-Checker/MPITypes.h3
-rw-r--r--lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp7
-rw-r--r--lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp73
-rw-r--r--lib/StaticAnalyzer/Checkers/MallocChecker.cpp87
-rw-r--r--lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp29
-rw-r--r--lib/StaticAnalyzer/Checkers/NumberObjectConversionChecker.cpp348
-rw-r--r--lib/StaticAnalyzer/Checkers/ObjCPropertyChecker.cpp82
-rw-r--r--lib/StaticAnalyzer/Checkers/ObjCSuperDeallocChecker.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/PaddingChecker.cpp58
-rw-r--r--lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp1
-rw-r--r--lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp1
-rw-r--r--lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp82
-rw-r--r--lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp1055
-rw-r--r--lib/StaticAnalyzer/Checkers/StreamChecker.cpp1
-rw-r--r--lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp105
-rw-r--r--lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp14
-rw-r--r--lib/StaticAnalyzer/Checkers/ValistChecker.cpp373
-rw-r--r--lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp121
-rw-r--r--lib/StaticAnalyzer/Core/AnalyzerOptions.cpp26
-rw-r--r--lib/StaticAnalyzer/Core/BasicValueFactory.cpp50
-rw-r--r--lib/StaticAnalyzer/Core/BugReporter.cpp107
-rw-r--r--lib/StaticAnalyzer/Core/BugReporterVisitors.cpp197
-rw-r--r--lib/StaticAnalyzer/Core/CallEvent.cpp7
-rw-r--r--lib/StaticAnalyzer/Core/CheckerManager.cpp19
-rw-r--r--lib/StaticAnalyzer/Core/CheckerRegistry.cpp19
-rw-r--r--lib/StaticAnalyzer/Core/CoreEngine.cpp23
-rw-r--r--lib/StaticAnalyzer/Core/ExplodedGraph.cpp2
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngine.cpp227
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngineC.cpp222
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngineCXX.cpp30
-rw-r--r--lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp88
-rw-r--r--lib/StaticAnalyzer/Core/IssueHash.cpp1
-rw-r--r--lib/StaticAnalyzer/Core/MemRegion.cpp42
-rw-r--r--lib/StaticAnalyzer/Core/PathDiagnostic.cpp39
-rw-r--r--lib/StaticAnalyzer/Core/PlistDiagnostics.cpp56
-rw-r--r--lib/StaticAnalyzer/Core/ProgramState.cpp33
-rw-r--r--lib/StaticAnalyzer/Core/RangeConstraintManager.cpp202
-rw-r--r--lib/StaticAnalyzer/Core/RegionStore.cpp9
-rw-r--r--lib/StaticAnalyzer/Core/SValBuilder.cpp12
-rw-r--r--lib/StaticAnalyzer/Core/SVals.cpp53
-rw-r--r--lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp153
-rw-r--r--lib/StaticAnalyzer/Core/SimpleConstraintManager.h80
-rw-r--r--lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp41
-rw-r--r--lib/StaticAnalyzer/Core/Store.cpp2
-rw-r--r--lib/StaticAnalyzer/Core/SymbolManager.cpp10
-rw-r--r--lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp138
-rw-r--r--lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp25
-rw-r--r--lib/StaticAnalyzer/Frontend/ModelInjector.cpp1
-rw-r--r--lib/StaticAnalyzer/Frontend/ModelInjector.h4
-rw-r--r--lib/Tooling/ArgumentsAdjusters.cpp2
-rw-r--r--lib/Tooling/CMakeLists.txt8
-rw-r--r--lib/Tooling/CompilationDatabase.cpp8
-rw-r--r--lib/Tooling/Core/Lookup.cpp94
-rw-r--r--lib/Tooling/Core/QualTypeNames.cpp2
-rw-r--r--lib/Tooling/Core/Replacement.cpp501
-rw-r--r--lib/Tooling/JSONCompilationDatabase.cpp60
-rw-r--r--lib/Tooling/Refactoring.cpp23
-rw-r--r--lib/Tooling/RefactoringCallbacks.cpp50
-rw-r--r--lib/Tooling/Tooling.cpp10
-rw-r--r--runtime/CMakeLists.txt13
-rw-r--r--test/ASTMerge/anonymous-fields/Inputs/anonymous-fields1.cpp (renamed from test/ASTMerge/Inputs/anonymous-fields1.cpp)0
-rw-r--r--test/ASTMerge/anonymous-fields/Inputs/anonymous-fields2.cpp (renamed from test/ASTMerge/Inputs/anonymous-fields2.cpp)0
-rw-r--r--test/ASTMerge/anonymous-fields/test.cpp (renamed from test/ASTMerge/anonymous-fields.cpp)0
-rw-r--r--test/ASTMerge/asm/Inputs/asm-function.cpp11
-rw-r--r--test/ASTMerge/asm/test.cpp7
-rw-r--r--test/ASTMerge/category/Inputs/category1.m (renamed from test/ASTMerge/Inputs/category1.m)0
-rw-r--r--test/ASTMerge/category/Inputs/category2.m (renamed from test/ASTMerge/Inputs/category2.m)0
-rw-r--r--test/ASTMerge/category/test.m (renamed from test/ASTMerge/category.m)0
-rw-r--r--test/ASTMerge/class-template/Inputs/class-template1.cpp (renamed from test/ASTMerge/Inputs/class-template1.cpp)0
-rw-r--r--test/ASTMerge/class-template/Inputs/class-template2.cpp (renamed from test/ASTMerge/Inputs/class-template2.cpp)0
-rw-r--r--test/ASTMerge/class-template/test.cpp (renamed from test/ASTMerge/class-template.cpp)0
-rw-r--r--test/ASTMerge/class/Inputs/class1.cpp (renamed from test/ASTMerge/Inputs/class1.cpp)0
-rw-r--r--test/ASTMerge/class/Inputs/class2.cpp (renamed from test/ASTMerge/Inputs/class2.cpp)0
-rw-r--r--test/ASTMerge/class/test.cpp (renamed from test/ASTMerge/class.cpp)0
-rw-r--r--test/ASTMerge/class2/Inputs/class3.cpp26
-rw-r--r--test/ASTMerge/class2/test.cpp9
-rw-r--r--test/ASTMerge/codegen-body/Inputs/body1.c (renamed from test/ASTMerge/Inputs/body1.c)0
-rw-r--r--test/ASTMerge/codegen-body/Inputs/body2.c (renamed from test/ASTMerge/Inputs/body2.c)0
-rw-r--r--test/ASTMerge/codegen-body/test.c (renamed from test/ASTMerge/codegen-body.c)0
-rw-r--r--test/ASTMerge/codegen-exprs/Inputs/exprs1.c (renamed from test/ASTMerge/Inputs/exprs1.c)0
-rw-r--r--test/ASTMerge/codegen-exprs/Inputs/exprs2.c (renamed from test/ASTMerge/Inputs/exprs2.c)0
-rw-r--r--test/ASTMerge/codegen-exprs/test.c (renamed from test/ASTMerge/codegen-exprs.c)0
-rw-r--r--test/ASTMerge/enum/Inputs/enum1.c (renamed from test/ASTMerge/Inputs/enum1.c)0
-rw-r--r--test/ASTMerge/enum/Inputs/enum2.c (renamed from test/ASTMerge/Inputs/enum2.c)0
-rw-r--r--test/ASTMerge/enum/test.c (renamed from test/ASTMerge/enum.c)0
-rw-r--r--test/ASTMerge/exprs-cpp/Inputs/exprs3.cpp120
-rw-r--r--test/ASTMerge/exprs-cpp/test.cpp45
-rw-r--r--test/ASTMerge/exprs/Inputs/exprs1.c10
-rw-r--r--test/ASTMerge/exprs/Inputs/exprs2.c10
-rw-r--r--test/ASTMerge/exprs/test.c (renamed from test/ASTMerge/exprs.c)0
-rw-r--r--test/ASTMerge/function/Inputs/function1.c (renamed from test/ASTMerge/Inputs/function1.c)0
-rw-r--r--test/ASTMerge/function/Inputs/function2.c (renamed from test/ASTMerge/Inputs/function2.c)0
-rw-r--r--test/ASTMerge/function/test.c (renamed from test/ASTMerge/function.c)0
-rw-r--r--test/ASTMerge/inheritance/Inputs/inheritance-base.cpp (renamed from test/ASTMerge/Inputs/inheritance-base.cpp)0
-rw-r--r--test/ASTMerge/inheritance/test.cpp (renamed from test/ASTMerge/inheritance.cpp)0
-rw-r--r--test/ASTMerge/init-ctors/Inputs/init-ctors-classes.cpp (renamed from test/ASTMerge/Inputs/init-ctors-classes.cpp)0
-rw-r--r--test/ASTMerge/init-ctors/test.cpp (renamed from test/ASTMerge/init-ctors.cpp)0
-rw-r--r--test/ASTMerge/interface/Inputs/interface1.m (renamed from test/ASTMerge/Inputs/interface1.m)0
-rw-r--r--test/ASTMerge/interface/Inputs/interface2.m (renamed from test/ASTMerge/Inputs/interface2.m)0
-rw-r--r--test/ASTMerge/interface/test.m (renamed from test/ASTMerge/interface.m)0
-rw-r--r--test/ASTMerge/macro/Inputs/macro.modulemap4
-rw-r--r--test/ASTMerge/macro/Inputs/macro1.h5
-rw-r--r--test/ASTMerge/macro/Inputs/macro1.m5
-rw-r--r--test/ASTMerge/macro/Inputs/macro2.m5
-rw-r--r--test/ASTMerge/macro/test.m6
-rw-r--r--test/ASTMerge/namespace/Inputs/namespace1.cpp (renamed from test/ASTMerge/Inputs/namespace1.cpp)0
-rw-r--r--test/ASTMerge/namespace/Inputs/namespace2.cpp (renamed from test/ASTMerge/Inputs/namespace2.cpp)0
-rw-r--r--test/ASTMerge/namespace/test.cpp (renamed from test/ASTMerge/namespace.cpp)0
-rw-r--r--test/ASTMerge/property/Inputs/property1.m (renamed from test/ASTMerge/Inputs/property1.m)0
-rw-r--r--test/ASTMerge/property/Inputs/property2.m (renamed from test/ASTMerge/Inputs/property2.m)0
-rw-r--r--test/ASTMerge/property/test.m (renamed from test/ASTMerge/property.m)0
-rw-r--r--test/ASTMerge/struct/Inputs/struct1.c (renamed from test/ASTMerge/Inputs/struct1.c)0
-rw-r--r--test/ASTMerge/struct/Inputs/struct2.c (renamed from test/ASTMerge/Inputs/struct2.c)0
-rw-r--r--test/ASTMerge/struct/test.c (renamed from test/ASTMerge/struct.c)0
-rw-r--r--test/ASTMerge/typedef/Inputs/typedef1.c (renamed from test/ASTMerge/Inputs/typedef1.c)0
-rw-r--r--test/ASTMerge/typedef/Inputs/typedef2.c (renamed from test/ASTMerge/Inputs/typedef2.c)0
-rw-r--r--test/ASTMerge/typedef/test.c (renamed from test/ASTMerge/typedef.c)0
-rw-r--r--test/ASTMerge/var/Inputs/var1.c (renamed from test/ASTMerge/Inputs/var1.c)0
-rw-r--r--test/ASTMerge/var/Inputs/var1.h (renamed from test/ASTMerge/Inputs/var1.h)0
-rw-r--r--test/ASTMerge/var/Inputs/var2.c (renamed from test/ASTMerge/Inputs/var2.c)0
-rw-r--r--test/ASTMerge/var/test.c (renamed from test/ASTMerge/var.c)0
-rw-r--r--test/Analysis/CFDateGC.m2
-rw-r--r--test/Analysis/CFNumber.c26
-rw-r--r--test/Analysis/CFRetainRelease_NSAssertionHandler.m2
-rw-r--r--test/Analysis/CGColorSpace.c2
-rw-r--r--test/Analysis/CheckNSError.m2
-rw-r--r--test/Analysis/DeallocMissingRelease.m59
-rw-r--r--test/Analysis/DeallocUseAfterFreeErrors.m32
-rw-r--r--test/Analysis/Inputs/localization-pch.h5
-rw-r--r--test/Analysis/Inputs/qt-simulator.h17
-rw-r--r--test/Analysis/Inputs/system-header-simulator-cxx.h9
-rw-r--r--test/Analysis/Inputs/system-header-simulator-for-valist.h30
-rw-r--r--test/Analysis/Inputs/system-header-simulator-objc.h12
-rw-r--r--test/Analysis/Inputs/system-header-simulator.h8
-rw-r--r--test/Analysis/NSPanel.m2
-rw-r--r--test/Analysis/NSString.m16
-rw-r--r--test/Analysis/NSWindow.m2
-rw-r--r--test/Analysis/NewDelete-checker-test.cpp16
-rw-r--r--test/Analysis/ObjCProperties.m2
-rw-r--r--test/Analysis/ObjCPropertiesSyntaxChecks.m61
-rw-r--r--test/Analysis/PR2599.m2
-rw-r--r--test/Analysis/PR3991.m2
-rw-r--r--test/Analysis/additive-folding-range-constraints.c2
-rw-r--r--test/Analysis/additive-folding.cpp2
-rw-r--r--test/Analysis/analyzeOneFunction.m2
-rw-r--r--test/Analysis/analyze_display_progress.cpp26
-rw-r--r--test/Analysis/analyzer-display-progress.cpp30
-rw-r--r--test/Analysis/analyzer-display-progress.m30
-rw-r--r--test/Analysis/analyzer-enabled-checkers.c20
-rw-r--r--test/Analysis/array-struct-region.c2
-rw-r--r--test/Analysis/array-struct.c13
-rw-r--r--test/Analysis/block-in-critical-section.cpp50
-rw-r--r--test/Analysis/blocks.m9
-rw-r--r--test/Analysis/cast-to-struct.cpp67
-rw-r--r--test/Analysis/castexpr-callback.c10
-rw-r--r--test/Analysis/casts.c2
-rw-r--r--test/Analysis/cfg.cpp8
-rw-r--r--test/Analysis/cfref_PR2519.c2
-rw-r--r--test/Analysis/cfref_rdar6080742.c2
-rw-r--r--test/Analysis/comparison-implicit-casts.cpp4
-rw-r--r--test/Analysis/complex.c2
-rw-r--r--test/Analysis/conditional-path-notes.c116
-rw-r--r--test/Analysis/conversion.c125
-rw-r--r--test/Analysis/copypaste/asm.cpp44
-rw-r--r--test/Analysis/copypaste/attributes.cpp28
-rw-r--r--test/Analysis/copypaste/blocks.cpp19
-rw-r--r--test/Analysis/copypaste/call.cpp102
-rw-r--r--test/Analysis/copypaste/catch.cpp29
-rw-r--r--test/Analysis/copypaste/delete.cpp29
-rw-r--r--test/Analysis/copypaste/dependent-exist.cpp18
-rw-r--r--test/Analysis/copypaste/expr-types.cpp17
-rw-r--r--test/Analysis/copypaste/fold.cpp35
-rw-r--r--test/Analysis/copypaste/function-try-block.cpp9
-rw-r--r--test/Analysis/copypaste/functions.cpp58
-rw-r--r--test/Analysis/copypaste/generic.c31
-rw-r--r--test/Analysis/copypaste/labels.cpp51
-rw-r--r--test/Analysis/copypaste/lambda.cpp24
-rw-r--r--test/Analysis/copypaste/macro-complexity.cpp50
-rw-r--r--test/Analysis/copypaste/macros.cpp67
-rw-r--r--test/Analysis/copypaste/objc-methods.m27
-rw-r--r--test/Analysis/copypaste/plist-diagnostics-notes-as-events.cpp97
-rw-r--r--test/Analysis/copypaste/plist-diagnostics.cpp71
-rw-r--r--test/Analysis/copypaste/sub-sequences.cpp27
-rw-r--r--test/Analysis/copypaste/suspicious-clones.cpp97
-rw-r--r--test/Analysis/copypaste/text-diagnostics.cpp17
-rw-r--r--test/Analysis/dead-stores.c2
-rw-r--r--test/Analysis/dead-stores.cpp2
-rw-r--r--test/Analysis/diagnostics/Inputs/include/plist-diagnostics-include-check-macro.def1
-rw-r--r--test/Analysis/diagnostics/Inputs/include/plist-diagnostics-include-check-macro.h9
-rw-r--r--test/Analysis/diagnostics/diag-cross-file-boundaries.c12
-rw-r--r--test/Analysis/diagnostics/diag-cross-file-boundaries.h4
-rw-r--r--test/Analysis/diagnostics/macros.cpp48
-rw-r--r--test/Analysis/diagnostics/macros.m31
-rw-r--r--test/Analysis/diagnostics/plist-diagnostics-include-check.cpp140
-rw-r--r--test/Analysis/dispatch-once.m109
-rw-r--r--test/Analysis/edges-new.mm1637
-rw-r--r--test/Analysis/explain-svals.cpp4
-rw-r--r--test/Analysis/explain-svals.m27
-rw-r--r--test/Analysis/expr-inspection.c22
-rw-r--r--test/Analysis/generics.m12245
-rw-r--r--test/Analysis/gtest.cpp153
-rw-r--r--test/Analysis/inline.c2
-rw-r--r--test/Analysis/inline.cpp2
-rw-r--r--test/Analysis/inlining/InlineObjCClassMethod.m4
-rw-r--r--test/Analysis/inlining/false-positive-suppression.m30
-rw-r--r--test/Analysis/inlining/path-notes.m71
-rw-r--r--test/Analysis/lifetime-extension.cpp46
-rw-r--r--test/Analysis/localization-aggressive.m8
-rw-r--r--test/Analysis/localization.m2
-rw-r--r--test/Analysis/malloc-custom.c32
-rw-r--r--test/Analysis/malloc-plist.c63
-rw-r--r--test/Analysis/malloc.c11
-rw-r--r--test/Analysis/malloc.cpp37
-rw-r--r--test/Analysis/max-nodes-suppress-on-sink.c31
-rw-r--r--test/Analysis/misc-ps-64.m2
-rw-r--r--test/Analysis/misc-ps-eager-assume.m2
-rw-r--r--test/Analysis/misc-ps-ranges.m2
-rw-r--r--test/Analysis/misc-ps-region-store.cpp2
-rw-r--r--test/Analysis/misc-ps.c10
-rw-r--r--test/Analysis/misc-ps.m4
-rw-r--r--test/Analysis/model-file.cpp29
-rw-r--r--test/Analysis/nil-receiver-undefined-larger-than-voidptr-ret-region.m2
-rw-r--r--test/Analysis/nil-receiver-undefined-larger-than-voidptr-ret.m6
-rw-r--r--test/Analysis/non-diagnosable-assumptions.c47
-rw-r--r--test/Analysis/null-deref-ps.c4
-rw-r--r--test/Analysis/nullability-no-arc.mm12
-rw-r--r--test/Analysis/nullability.c12
-rw-r--r--test/Analysis/nullability.mm10
-rw-r--r--test/Analysis/nullability_nullonly.mm18
-rw-r--r--test/Analysis/number-object-conversion.c40
-rw-r--r--test/Analysis/number-object-conversion.cpp94
-rw-r--r--test/Analysis/number-object-conversion.m112
-rw-r--r--test/Analysis/objc-arc.m24
-rw-r--r--test/Analysis/out-of-bounds-new.cpp156
-rw-r--r--test/Analysis/out-of-bounds.c26
-rw-r--r--test/Analysis/padding_message.cpp166
-rw-r--r--test/Analysis/plist-html-macros.c5
-rw-r--r--test/Analysis/plist-output-alternate.m4
-rw-r--r--test/Analysis/plist-output.m126
-rw-r--r--test/Analysis/pointer-to-member.cpp154
-rw-r--r--test/Analysis/qt_malloc.cpp8
-rw-r--r--test/Analysis/rdar-6562655.m2
-rw-r--r--test/Analysis/rdar-6600344-nil-receiver-undefined-struct-ret.m2
-rw-r--r--test/Analysis/reference.cpp2
-rw-r--r--test/Analysis/retain-release-arc.m166
-rw-r--r--test/Analysis/retain-release-path-notes-gc.m30
-rw-r--r--test/Analysis/retain-release-path-notes.m96
-rw-r--r--test/Analysis/retain-release.m102
-rw-r--r--test/Analysis/self-assign.cpp89
-rw-r--r--test/Analysis/std-c-library-functions.c188
-rw-r--r--test/Analysis/std-c-library-functions.cpp14
-rw-r--r--test/Analysis/string.c17
-rw-r--r--test/Analysis/symbol-reaper.c4
-rw-r--r--test/Analysis/temp-obj-dtors-cfg-output.cpp6
-rw-r--r--test/Analysis/temporaries.cpp26
-rw-r--r--test/Analysis/uninit-vals-union.c13
-rw-r--r--test/Analysis/uninit-vals.cpp34
-rw-r--r--test/Analysis/unions-region.m2
-rw-r--r--test/Analysis/unix-api.c29
-rw-r--r--test/Analysis/unix-api.cpp62
-rw-r--r--test/Analysis/unix-fns.c3854
-rw-r--r--test/Analysis/unreachable-code-path.c55
-rw-r--r--test/Analysis/valist-uninitialized.c178
-rw-r--r--test/Analysis/valist-unterminated.c133
-rw-r--r--test/Analysis/virtualcall.cpp64
-rw-r--r--test/Analysis/virtualcall.h10
-rw-r--r--test/CMakeLists.txt11
-rw-r--r--test/CXX/basic/basic.lookup/basic.lookup.elab/p2.cpp4
-rw-r--r--test/CXX/basic/basic.stc/basic.stc.dynamic/basic.stc.dynamic.deallocation/p2.cpp19
-rw-r--r--test/CXX/basic/basic.stc/basic.stc.dynamic/p2-noexceptions.cpp2
-rw-r--r--test/CXX/basic/basic.stc/basic.stc.dynamic/p2.cpp19
-rw-r--r--test/CXX/class.access/class.friend/p1.cpp21
-rw-r--r--test/CXX/class.access/p4.cpp82
-rw-r--r--test/CXX/class.derived/class.abstract/p16.cpp18
-rw-r--r--test/CXX/class.derived/class.abstract/p2.cpp23
-rw-r--r--test/CXX/class.derived/class.abstract/p3.cpp97
-rw-r--r--test/CXX/class/class.union/p1.cpp2
-rw-r--r--test/CXX/conv/conv.fctptr/p1.cpp43
-rw-r--r--test/CXX/cpp/cpp.predefined/p1.cpp9
-rw-r--r--test/CXX/dcl.dcl/basic.namespace/namespace.def/p7.cpp9
-rw-r--r--test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp157
-rw-r--r--test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p2-0x.cpp6
-rw-r--r--test/CXX/dcl.decl/dcl.decomp/p2.cpp34
-rw-r--r--test/CXX/dcl.decl/dcl.decomp/p3.cpp232
-rw-r--r--test/CXX/dcl.decl/dcl.decomp/p4.cpp200
-rw-r--r--test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1.cpp36
-rw-r--r--test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x-fixits.cpp2
-rw-r--r--test/CXX/dcl.decl/dcl.init/dcl.init.ref/p4.cpp13
-rw-r--r--test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-cxx03-extra-copy.cpp8
-rw-r--r--test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp23
-rw-r--r--test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5.cpp4
-rw-r--r--test/CXX/dcl.decl/dcl.init/p5.cpp41
-rw-r--r--test/CXX/dcl.decl/dcl.init/p7.cpp2
-rw-r--r--test/CXX/dcl.decl/dcl.meaning/dcl.fct/p6-0x.cpp14
-rw-r--r--test/CXX/drs/dr0xx.cpp130
-rw-r--r--test/CXX/drs/dr10xx.cpp14
-rw-r--r--test/CXX/drs/dr118.cpp26
-rw-r--r--test/CXX/drs/dr12xx.cpp37
-rw-r--r--test/CXX/drs/dr13xx.cpp130
-rw-r--r--test/CXX/drs/dr14xx.cpp28
-rw-r--r--test/CXX/drs/dr158.cpp27
-rw-r--r--test/CXX/drs/dr15xx.cpp218
-rw-r--r--test/CXX/drs/dr16xx.cpp49
-rw-r--r--test/CXX/drs/dr18xx.cpp11
-rw-r--r--test/CXX/drs/dr1xx.cpp41
-rw-r--r--test/CXX/drs/dr2xx.cpp49
-rw-r--r--test/CXX/drs/dr4xx.cpp36
-rw-r--r--test/CXX/drs/dr5xx.cpp20
-rw-r--r--test/CXX/drs/dr6xx.cpp83
-rw-r--r--test/CXX/except/except.spec/p2-places-1z.cpp17
-rw-r--r--test/CXX/except/except.spec/p2-places.cpp2
-rw-r--r--test/CXX/except/except.spec/p5-pointers.cpp12
-rw-r--r--test/CXX/expr/expr.cond/p4.cpp10
-rw-r--r--test/CXX/expr/expr.const/p2-0x.cpp24
-rw-r--r--test/CXX/expr/expr.const/p3-0x.cpp15
-rw-r--r--test/CXX/expr/expr.post/expr.static.cast/p3-p4-0x.cpp43
-rw-r--r--test/CXX/expr/expr.post/expr.static.cast/p7.cpp10
-rw-r--r--test/CXX/expr/expr.prim/expr.prim.lambda/p19.cpp4
-rw-r--r--test/CXX/expr/expr.prim/expr.prim.lambda/p6.cpp10
-rw-r--r--test/CXX/expr/expr.unary/expr.delete/p10.cpp25
-rw-r--r--test/CXX/expr/expr.unary/expr.new/p14.cpp69
-rw-r--r--test/CXX/expr/expr.unary/expr.new/p20-0x.cpp57
-rw-r--r--test/CXX/expr/p13.cpp51
-rw-r--r--test/CXX/over/over.built/p15.cpp83
-rw-r--r--test/CXX/over/over.built/p16.cpp75
-rw-r--r--test/CXX/over/over.match/over.match.best/over.best.ics/over.ics.scs/p3.cpp12
-rw-r--r--test/CXX/over/over.oper/over.literal/p6.cpp4
-rw-r--r--test/CXX/over/over.over/p1.cpp23
-rw-r--r--test/CXX/special/class.copy/implicit-move-def.cpp2
-rw-r--r--test/CXX/special/class.copy/p20.cpp3
-rw-r--r--test/CXX/special/class.dtor/p3-0x.cpp2
-rw-r--r--test/CXX/special/class.dtor/p5-0x.cpp2
-rw-r--r--test/CXX/special/class.dtor/p9.cpp37
-rw-r--r--test/CXX/special/class.init/class.inhctor.init/p1.cpp7
-rw-r--r--test/CXX/stmt.stmt/stmt.select/stmt.if/p2.cpp5
-rw-r--r--test/CXX/temp/temp.arg/temp.arg.nontype/p5.cpp108
-rw-r--r--test/CXX/temp/temp.decls/temp.class.spec/p8-0x.cpp9
-rw-r--r--test/CXX/temp/temp.decls/temp.class.spec/p8-1y.cpp17
-rw-r--r--test/CXX/temp/temp.decls/temp.class/temp.static/p1.cpp2
-rw-r--r--test/CXX/temp/temp.decls/temp.friend/p1.cpp2
-rw-r--r--test/CXX/temp/temp.decls/temp.variadic/fixed-expansion.cpp4
-rw-r--r--test/CXX/temp/temp.fct.spec/temp.deduct/p9.cpp5
-rw-r--r--test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p4.cpp37
-rw-r--r--test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p4.cpp48
-rw-r--r--test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p5.cpp61
-rw-r--r--test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p9-0x.cpp2
-rw-r--r--test/CXX/temp/temp.spec/no-body.cpp2
-rw-r--r--test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp28
-rw-r--r--test/CXX/temp/temp.spec/temp.expl.spec/p4.cpp18
-rw-r--r--test/CXX/temp/temp.spec/temp.explicit/p4.cpp15
-rw-r--r--test/CXX/temp/temp.spec/temp.explicit/p9-linkage.cpp2
-rw-r--r--test/CodeCompletion/ctor-initializer.cpp31
-rw-r--r--test/CodeCompletion/objc-message.mm4
-rw-r--r--test/CodeCompletion/objc-protocol-member-access.m24
-rw-r--r--test/CodeGen/2008-04-08-NoExceptions.c2
-rw-r--r--test/CodeGen/2009-10-20-GlobalDebug.c20
-rw-r--r--test/CodeGen/2010-08-10-DbgConstant.c3
-rw-r--r--test/CodeGen/3dnow-builtins.c6
-rw-r--r--test/CodeGen/64bit-swiftcall.c1007
-rw-r--r--test/CodeGen/CFStrings.c28
-rw-r--r--test/CodeGen/Inputs/debug-info-file-checksum.c3
-rw-r--r--test/CodeGen/Inputs/opt-record.proftext26
-rw-r--r--test/CodeGen/aarch64-neon-2velem.c2063
-rw-r--r--test/CodeGen/aarch64-neon-across.c112
-rw-r--r--test/CodeGen/aarch64-neon-fma.c16
-rw-r--r--test/CodeGen/aarch64-neon-intrinsics.c6632
-rw-r--r--test/CodeGen/aarch64-neon-misc.c1636
-rw-r--r--test/CodeGen/aarch64-neon-perm.c1416
-rw-r--r--test/CodeGen/aarch64-neon-scalar-x-indexed-elem.c4
-rw-r--r--test/CodeGen/aarch64-poly64.c36
-rw-r--r--test/CodeGen/address-safety-attr-kasan.cpp24
-rw-r--r--test/CodeGen/address-safety-attr.cpp21
-rw-r--r--test/CodeGen/address-space-field1.c2
-rw-r--r--test/CodeGen/alias.c4
-rw-r--r--test/CodeGen/alloc-size.c352
-rw-r--r--test/CodeGen/always_inline.c2
-rw-r--r--test/CodeGen/arm-neon-directed-rounding.c96
-rw-r--r--test/CodeGen/arm-neon-fma.c16
-rw-r--r--test/CodeGen/arm-neon-numeric-maxmin.c40
-rw-r--r--test/CodeGen/arm-neon-vcvtX.c64
-rw-r--r--test/CodeGen/arm-swiftcall.c541
-rw-r--r--test/CodeGen/arm-target-features.c2
-rw-r--r--test/CodeGen/arm64_crypto.c1
-rw-r--r--test/CodeGen/arm_neon_intrinsics.c8629
-rw-r--r--test/CodeGen/asan-globals.cpp15
-rw-r--r--test/CodeGen/atomics-inlining.c13
-rw-r--r--test/CodeGen/attr-minsize.cpp14
-rw-r--r--test/CodeGen/attr-mrecip.c7
-rw-r--r--test/CodeGen/attributes.c4
-rw-r--r--test/CodeGen/avx-builtins.c12
-rw-r--r--test/CodeGen/avx-cmp-builtins.c4
-rw-r--r--test/CodeGen/avx-shuffle-builtins.c20
-rw-r--r--test/CodeGen/avx2-builtins.c6
-rw-r--r--test/CodeGen/avx512-inline-asm-kregisters-basics.c11
-rw-r--r--test/CodeGen/avx512-kconstraints-att_inline_asm.c59
-rw-r--r--test/CodeGen/avx512-reduceIntrin.c410
-rw-r--r--test/CodeGen/avx512-reduceMinMaxIntrin.c437
-rw-r--r--test/CodeGen/avx512bw-builtins.c220
-rw-r--r--test/CodeGen/avx512cdintrin.c4
-rw-r--r--test/CodeGen/avx512dq-builtins.c216
-rw-r--r--test/CodeGen/avx512er-builtins.c64
-rw-r--r--test/CodeGen/avx512f-builtins.c1269
-rw-r--r--test/CodeGen/avx512ifma-builtins.c4
-rw-r--r--test/CodeGen/avx512ifmavl-builtins.c2
-rw-r--r--test/CodeGen/avx512pf-builtins.c4
-rw-r--r--test/CodeGen/avx512vbmi-builtins.c4
-rw-r--r--test/CodeGen/avx512vbmivl-builtin.c4
-rw-r--r--test/CodeGen/avx512vl-builtins.c1047
-rw-r--r--test/CodeGen/avx512vlbw-builtins.c835
-rw-r--r--test/CodeGen/avx512vlcd-builtins.c4
-rw-r--r--test/CodeGen/avx512vldq-builtins.c154
-rw-r--r--test/CodeGen/bitscan-builtins.c4
-rw-r--r--test/CodeGen/block-with-perdefinedexpr.cpp87
-rw-r--r--test/CodeGen/blocks-opencl.cl2
-rw-r--r--test/CodeGen/bmi-builtins.c4
-rw-r--r--test/CodeGen/bmi2-builtins.c6
-rw-r--r--test/CodeGen/bool_test.c2
-rw-r--r--test/CodeGen/builtin-clflushopt.c2
-rw-r--r--test/CodeGen/builtin-expect.c2
-rw-r--r--test/CodeGen/builtin-unpredictable.c2
-rw-r--r--test/CodeGen/builtins-ms.c11
-rw-r--r--test/CodeGen/builtins-nvptx.c266
-rw-r--r--test/CodeGen/builtins-ppc-altivec.c464
-rw-r--r--test/CodeGen/builtins-ppc-crypto.c24
-rw-r--r--test/CodeGen/builtins-ppc-p8vector.c150
-rw-r--r--test/CodeGen/builtins-ppc-p9vector.c1182
-rw-r--r--test/CodeGen/builtins-ppc-quadword.c91
-rw-r--r--test/CodeGen/builtins-ppc-vsx.c615
-rw-r--r--test/CodeGen/builtins-systemz-zvector-error.c33
-rw-r--r--test/CodeGen/builtins-x86.c9
-rw-r--r--test/CodeGen/builtins.c237
-rw-r--r--test/CodeGen/captured-statements-nested.c4
-rw-r--r--test/CodeGen/cfi-icall-cross-dso2.c11
-rw-r--r--test/CodeGen/cleanup-destslot-simple.c4
-rw-r--r--test/CodeGen/code-coverage.c4
-rw-r--r--test/CodeGen/compound-literal.c16
-rw-r--r--test/CodeGen/dbg-const-int128.c8
-rw-r--r--test/CodeGen/debug-info-atomic.c8
-rw-r--r--test/CodeGen/debug-info-file-checksum.c5
-rw-r--r--test/CodeGen/debug-info-global-constant.c18
-rw-r--r--test/CodeGen/debug-info-imported-entity.cpp4
-rw-r--r--test/CodeGen/debug-info-packed-struct.c20
-rw-r--r--test/CodeGen/debug-info-static-const-fp.c54
-rw-r--r--test/CodeGen/debug-info-static.c5
-rw-r--r--test/CodeGen/debug-info-vector.c2
-rw-r--r--test/CodeGen/decl-in-prototype.c7
-rw-r--r--test/CodeGen/denormalfpmode.c12
-rw-r--r--test/CodeGen/dwarf-version.c8
-rw-r--r--test/CodeGen/ext-vector.c37
-rw-r--r--test/CodeGen/f16c-builtins.c4
-rw-r--r--test/CodeGen/fixup-depth-overflow.c2
-rw-r--r--test/CodeGen/fma-builtins.c4
-rw-r--r--test/CodeGen/fma4-builtins.c4
-rw-r--r--test/CodeGen/fsgsbase-builtins.c4
-rw-r--r--test/CodeGen/func-in-block.c4
-rw-r--r--test/CodeGen/function-attributes.c4
-rw-r--r--test/CodeGen/incomplete-function-type-2.c2
-rw-r--r--test/CodeGen/inline-optim.c12
-rw-r--r--test/CodeGen/inline.c14
-rw-r--r--test/CodeGen/lifetime2.c78
-rw-r--r--test/CodeGen/lzcnt-builtins.c4
-rw-r--r--test/CodeGen/mangle-blocks.c4
-rw-r--r--test/CodeGen/may-alias.c4
-rw-r--r--test/CodeGen/mcount.c20
-rw-r--r--test/CodeGen/mips16-attr.c4
-rw-r--r--test/CodeGen/mmx-builtins.c6
-rw-r--r--test/CodeGen/mozilla-ms-inline-asm.c4
-rw-r--r--test/CodeGen/mrtd.c2
-rw-r--r--test/CodeGen/ms-barriers-intrinsics.c39
-rw-r--r--test/CodeGen/ms-declspecs.c2
-rw-r--r--test/CodeGen/ms-inline-asm.c49
-rw-r--r--test/CodeGen/ms-inline-asm.cpp4
-rw-r--r--test/CodeGen/ms-intrinsics-rotations.c181
-rw-r--r--test/CodeGen/ms-intrinsics.c394
-rw-r--r--test/CodeGen/ms-mm-align.c2
-rw-r--r--test/CodeGen/ms-volatile-arm.c13
-rw-r--r--test/CodeGen/ms-x86-intrinsics.c74
-rw-r--r--test/CodeGen/ms_abi.c19
-rw-r--r--test/CodeGen/nobuiltin.c14
-rw-r--r--test/CodeGen/noexceptionsfpmath.c8
-rw-r--r--test/CodeGen/object-size.c25
-rw-r--r--test/CodeGen/opt-record.c33
-rw-r--r--test/CodeGen/overloadable.c35
-rw-r--r--test/CodeGen/pass-object-size.c9
-rw-r--r--test/CodeGen/pclmul-builtins.c4
-rw-r--r--test/CodeGen/pgo-sample.c3
-rw-r--r--test/CodeGen/pku.c4
-rw-r--r--test/CodeGen/popcnt-builtins.c4
-rw-r--r--test/CodeGen/ppc64-complex-parms.c2
-rw-r--r--test/CodeGen/ppc64-complex-return.c2
-rw-r--r--test/CodeGen/ppc64-dwarf.c129
-rw-r--r--test/CodeGen/ppc64-extend.c2
-rw-r--r--test/CodeGen/ppc64-soft-float.c171
-rw-r--r--test/CodeGen/ppc64-struct-onevect.c2
-rw-r--r--test/CodeGen/pr27892.c4
-rw-r--r--test/CodeGen/prefetchw-builtins.c4
-rw-r--r--test/CodeGen/rd-builtins.c4
-rw-r--r--test/CodeGen/rdrand-builtins.c4
-rw-r--r--test/CodeGen/regcall.c120
-rw-r--r--test/CodeGen/renderscript.c115
-rw-r--r--test/CodeGen/rtm-builtins.c4
-rw-r--r--test/CodeGen/sanitize-init-order.cpp3
-rw-r--r--test/CodeGen/sanitize-thread-attr.cpp12
-rw-r--r--test/CodeGen/sanitize-thread-no-checking-at-run-time.m34
-rw-r--r--test/CodeGen/sha-builtins.c4
-rw-r--r--test/CodeGen/split-debug-filename.c4
-rw-r--r--test/CodeGen/split-debug-inlining.c7
-rw-r--r--test/CodeGen/sse-builtins.c4
-rw-r--r--test/CodeGen/sse.c4
-rw-r--r--test/CodeGen/sse2-builtins.c16
-rw-r--r--test/CodeGen/sse3-builtins.c4
-rw-r--r--test/CodeGen/sse41-builtins.c6
-rw-r--r--test/CodeGen/sse42-builtins.c6
-rw-r--r--test/CodeGen/sse4a-builtins.c4
-rw-r--r--test/CodeGen/ssse3-builtins.c4
-rw-r--r--test/CodeGen/systemz-abi-vector.c2
-rw-r--r--test/CodeGen/systemz-abi.c2
-rw-r--r--test/CodeGen/target-data.c8
-rw-r--r--test/CodeGen/tbaa-class.cpp4
-rw-r--r--test/CodeGen/tbaa-ms-abi.cpp2
-rw-r--r--test/CodeGen/tbaa.cpp8
-rw-r--r--test/CodeGen/tbm-builtins.c4
-rw-r--r--test/CodeGen/temporary-lifetime-exceptions.cpp12
-rw-r--r--test/CodeGen/temporary-lifetime.cpp48
-rw-r--r--test/CodeGen/thinlto_backend.ll9
-rw-r--r--test/CodeGen/ubsan-blacklist.c5
-rw-r--r--test/CodeGen/unwind-attr.c6
-rw-r--r--test/CodeGen/vecshift.c162
-rw-r--r--test/CodeGen/vector.c4
-rw-r--r--test/CodeGen/windows-on-arm-itanium-thread-local.c11
-rw-r--r--test/CodeGen/windows-on-arm-stack-probe-size.c2
-rw-r--r--test/CodeGen/windows-swiftcall.c458
-rw-r--r--test/CodeGen/x86-inline-asm-v-constraint.c30
-rw-r--r--test/CodeGen/x86_32-xsave.c20
-rw-r--r--test/CodeGen/x86_64-arguments.c18
-rw-r--r--test/CodeGen/x86_64-xsave.c20
-rw-r--r--test/CodeGen/x86_inlineasm_curly_bracket_escape.c8
-rw-r--r--test/CodeGen/xop-builtins.c6
-rw-r--r--test/CodeGen/xray-attributes-supported-arm.cpp13
-rw-r--r--test/CodeGenCUDA/convergent.cu4
-rw-r--r--test/CodeGenCUDA/cuda-builtin-vars.cu2
-rw-r--r--test/CodeGenCUDA/device-stub.cu6
-rw-r--r--test/CodeGenCUDA/device-var-init.cu6
-rw-r--r--test/CodeGenCUDA/function-overload.cu8
-rw-r--r--test/CodeGenCUDA/host-device-calls-host.cu32
-rw-r--r--test/CodeGenCUDA/kernel-args-alignment.cu36
-rw-r--r--test/CodeGenCUDA/launch-bounds.cu6
-rw-r--r--test/CodeGenCUDA/nothrow.cu39
-rw-r--r--test/CodeGenCXX/PR26569.cpp16
-rw-r--r--test/CodeGenCXX/alias-available-externally.cpp20
-rw-r--r--test/CodeGenCXX/alloc-size.cpp72
-rw-r--r--test/CodeGenCXX/apple-kext-indirect-call-2.cpp16
-rw-r--r--test/CodeGenCXX/apple-kext-indirect-call.cpp6
-rw-r--r--test/CodeGenCXX/apple-kext-indirect-virtual-dtor-call.cpp8
-rw-r--r--test/CodeGenCXX/arm-swiftcall.cpp2
-rw-r--r--test/CodeGenCXX/arm64.cpp36
-rw-r--r--test/CodeGenCXX/atomicinit.cpp4
-rw-r--r--test/CodeGenCXX/attr.cpp2
-rw-r--r--test/CodeGenCXX/block-in-ctor-dtor.cpp2
-rw-r--r--test/CodeGenCXX/builtins-arm-exclusive.cpp24
-rw-r--r--test/CodeGenCXX/catch-undef-behavior.cpp8
-rw-r--r--test/CodeGenCXX/cfi-cross-dso.cpp2
-rw-r--r--test/CodeGenCXX/compound-literals.cpp40
-rw-r--r--test/CodeGenCXX/const-init-cxx11.cpp6
-rw-r--r--test/CodeGenCXX/constructor-destructor-return-this.cpp2
-rw-r--r--test/CodeGenCXX/constructor-init.cpp17
-rw-r--r--test/CodeGenCXX/copy-constructor-elim-2.cpp20
-rw-r--r--test/CodeGenCXX/copy-constructor-synthesis-2.cpp2
-rw-r--r--test/CodeGenCXX/copy-constructor-synthesis.cpp2
-rw-r--r--test/CodeGenCXX/ctor-dtor-alias.cpp6
-rw-r--r--test/CodeGenCXX/cxx11-exception-spec.cpp2
-rw-r--r--test/CodeGenCXX/cxx11-noreturn.cpp2
-rw-r--r--test/CodeGenCXX/cxx1y-initializer-aggregate.cpp2
-rw-r--r--test/CodeGenCXX/cxx1y-variable-template-linkage.cpp4
-rw-r--r--test/CodeGenCXX/cxx1z-aligned-allocation.cpp206
-rw-r--r--test/CodeGenCXX/cxx1z-constexpr-if.cpp13
-rw-r--r--test/CodeGenCXX/cxx1z-copy-omission.cpp81
-rw-r--r--test/CodeGenCXX/cxx1z-decomposition.cpp118
-rw-r--r--test/CodeGenCXX/cxx1z-eval-order.cpp271
-rw-r--r--test/CodeGenCXX/cxx1z-noexcept-function-type.cpp9
-rw-r--r--test/CodeGenCXX/debug-info-access.cpp2
-rw-r--r--test/CodeGenCXX/debug-info-alias.cpp5
-rw-r--r--test/CodeGenCXX/debug-info-anon-namespace.cpp3
-rw-r--r--test/CodeGenCXX/debug-info-anon-union-vars.cpp2
-rw-r--r--test/CodeGenCXX/debug-info-calling-conventions.cpp2
-rw-r--r--test/CodeGenCXX/debug-info-class-nolimit.cpp24
-rw-r--r--test/CodeGenCXX/debug-info-class.cpp1
-rw-r--r--test/CodeGenCXX/debug-info-codeview-injected-class.cpp21
-rw-r--r--test/CodeGenCXX/debug-info-cxx1y.cpp6
-rw-r--r--test/CodeGenCXX/debug-info-dllimport-base-class.cpp53
-rw-r--r--test/CodeGenCXX/debug-info-dup-fwd-decl.cpp2
-rw-r--r--test/CodeGenCXX/debug-info-enum-class.cpp8
-rw-r--r--test/CodeGenCXX/debug-info-flex-member.cpp9
-rw-r--r--test/CodeGenCXX/debug-info-global.cpp5
-rw-r--r--test/CodeGenCXX/debug-info-indirect-field-decl.cpp4
-rw-r--r--test/CodeGenCXX/debug-info-line-if.cpp20
-rw-r--r--test/CodeGenCXX/debug-info-line.cpp4
-rw-r--r--test/CodeGenCXX/debug-info-loops.cpp49
-rw-r--r--test/CodeGenCXX/debug-info-method.cpp2
-rw-r--r--test/CodeGenCXX/debug-info-ms-abi.cpp24
-rw-r--r--test/CodeGenCXX/debug-info-ms-anonymous-tag.cpp3
-rw-r--r--test/CodeGenCXX/debug-info-ms-bitfields.cpp2
-rw-r--r--test/CodeGenCXX/debug-info-ms-ptr-to-member.cpp7
-rw-r--r--test/CodeGenCXX/debug-info-ms-vbase.cpp68
-rw-r--r--test/CodeGenCXX/debug-info-namespace.cpp17
-rw-r--r--test/CodeGenCXX/debug-info-rvalue-ref.cpp2
-rw-r--r--test/CodeGenCXX/debug-info-static-member.cpp32
-rw-r--r--test/CodeGenCXX/debug-info-template-explicit-specialization.cpp7
-rw-r--r--test/CodeGenCXX/debug-info-template-member.cpp10
-rw-r--r--test/CodeGenCXX/debug-info-template-quals.cpp4
-rw-r--r--test/CodeGenCXX/debug-info-template.cpp30
-rw-r--r--test/CodeGenCXX/debug-info-thunk-msabi.cpp19
-rw-r--r--test/CodeGenCXX/debug-info-thunk.cpp13
-rw-r--r--test/CodeGenCXX/debug-info-union.cpp2
-rw-r--r--test/CodeGenCXX/debug-info-uuid.cpp29
-rw-r--r--test/CodeGenCXX/debug-info-vla.cpp20
-rw-r--r--test/CodeGenCXX/debug-info-windows-dtor.cpp2
-rw-r--r--test/CodeGenCXX/debug-info-zero-length-arrays.cpp1
-rw-r--r--test/CodeGenCXX/debug-info.cpp12
-rw-r--r--test/CodeGenCXX/debug-lambda-expressions.cpp10
-rw-r--r--test/CodeGenCXX/debug-lambda-this.cpp4
-rw-r--r--test/CodeGenCXX/default-arg-temps.cpp9
-rw-r--r--test/CodeGenCXX/derived-to-base.cpp2
-rw-r--r--test/CodeGenCXX/destructors.cpp128
-rw-r--r--test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp16
-rw-r--r--test/CodeGenCXX/devirtualize-virtual-function-calls.cpp97
-rw-r--r--test/CodeGenCXX/dllexport.cpp17
-rw-r--r--test/CodeGenCXX/dllimport-members.cpp2
-rw-r--r--test/CodeGenCXX/dllimport-rtti.cpp8
-rw-r--r--test/CodeGenCXX/dllimport.cpp27
-rw-r--r--test/CodeGenCXX/empty-classes.cpp21
-rw-r--r--test/CodeGenCXX/enable_if.cpp2
-rw-r--r--test/CodeGenCXX/exceptions-seh.cpp2
-rw-r--r--test/CodeGenCXX/explicit-instantiation.cpp2
-rw-r--r--test/CodeGenCXX/global-dtor-no-atexit.cpp2
-rw-r--r--test/CodeGenCXX/global-init.cpp9
-rw-r--r--test/CodeGenCXX/implicit-copy-constructor.cpp8
-rw-r--r--test/CodeGenCXX/init-invariant.cpp14
-rw-r--r--test/CodeGenCXX/inline-dllexport-member.cpp8
-rw-r--r--test/CodeGenCXX/inline-hint.cpp6
-rw-r--r--test/CodeGenCXX/invariant.group-for-vptrs.cpp6
-rw-r--r--test/CodeGenCXX/key-function-vtable.cpp10
-rw-r--r--test/CodeGenCXX/lambda-expressions.cpp78
-rw-r--r--test/CodeGenCXX/linkage.cpp2
-rw-r--r--test/CodeGenCXX/main-norecurse.cpp2
-rw-r--r--test/CodeGenCXX/mangle-abi-tag.cpp29
-rw-r--r--test/CodeGenCXX/mangle-exception-spec.cpp49
-rw-r--r--test/CodeGenCXX/mangle-lambdas.cpp10
-rw-r--r--test/CodeGenCXX/mangle-ms-cxx11.cpp29
-rw-r--r--test/CodeGenCXX/mangle-unnamed.cpp3
-rw-r--r--test/CodeGenCXX/mangle.cpp14
-rw-r--r--test/CodeGenCXX/microsoft-abi-array-cookies.cpp2
-rw-r--r--test/CodeGenCXX/microsoft-abi-constexpr-vs-inheritance.cpp4
-rw-r--r--test/CodeGenCXX/microsoft-abi-eh-catch.cpp2
-rw-r--r--test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp37
-rw-r--r--test/CodeGenCXX/microsoft-abi-extern-template.cpp6
-rw-r--r--test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp12
-rw-r--r--test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp48
-rw-r--r--test/CodeGenCXX/microsoft-abi-structors-alias.cpp2
-rw-r--r--test/CodeGenCXX/microsoft-abi-structors.cpp4
-rw-r--r--test/CodeGenCXX/microsoft-abi-vftables.cpp34
-rw-r--r--test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp16
-rw-r--r--test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-this-adjustment.cpp23
-rw-r--r--test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp16
-rw-r--r--test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp10
-rw-r--r--test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp16
-rw-r--r--test/CodeGenCXX/microsoft-interface.cpp6
-rw-r--r--test/CodeGenCXX/microsoft-no-rtti-data.cpp2
-rw-r--r--test/CodeGenCXX/microsoft-uuidof.cpp8
-rw-r--r--test/CodeGenCXX/modules-ts.cppm20
-rw-r--r--test/CodeGenCXX/ms-inline-asm-return.cpp10
-rw-r--r--test/CodeGenCXX/ms-thread_local.cpp5
-rw-r--r--test/CodeGenCXX/naked.cpp13
-rw-r--r--test/CodeGenCXX/new-array-init.cpp84
-rw-r--r--test/CodeGenCXX/no-exceptions.cpp2
-rw-r--r--test/CodeGenCXX/nrvo.cpp28
-rw-r--r--test/CodeGenCXX/optnone-class-members.cpp2
-rw-r--r--test/CodeGenCXX/optnone-def-decl.cpp2
-rw-r--r--test/CodeGenCXX/partial-destruction.cpp39
-rw-r--r--test/CodeGenCXX/pr24097.cpp2
-rw-r--r--test/CodeGenCXX/pr30731.cpp21
-rw-r--r--test/CodeGenCXX/pragma-loop-distribute.cpp23
-rw-r--r--test/CodeGenCXX/pragma-loop-safety.cpp24
-rw-r--r--test/CodeGenCXX/predefined-expr-cxx14.cpp4
-rw-r--r--test/CodeGenCXX/reference-cast.cpp2
-rw-r--r--test/CodeGenCXX/regcall.cpp97
-rw-r--r--test/CodeGenCXX/rtti-mingw64.cpp13
-rw-r--r--test/CodeGenCXX/rtti-qualfn.cpp23
-rw-r--r--test/CodeGenCXX/runtime-dllstorage.cpp158
-rw-r--r--test/CodeGenCXX/sanitize-dtor-bit-field.cpp4
-rw-r--r--test/CodeGenCXX/sanitize-dtor-derived-class.cpp4
-rw-r--r--test/CodeGenCXX/sanitize-dtor-tail-call.cpp4
-rw-r--r--test/CodeGenCXX/sanitize-dtor-trivial.cpp4
-rw-r--r--test/CodeGenCXX/sanitize-dtor-vtable.cpp4
-rw-r--r--test/CodeGenCXX/skip-vtable-pointer-initialization.cpp16
-rw-r--r--test/CodeGenCXX/stack-reuse-miscompile.cpp2
-rw-r--r--test/CodeGenCXX/stack-reuse.cpp2
-rw-r--r--test/CodeGenCXX/strict-vtable-pointers.cpp36
-rw-r--r--test/CodeGenCXX/template-instantiation.cpp2
-rw-r--r--test/CodeGenCXX/temporaries.cpp30
-rw-r--r--test/CodeGenCXX/threadsafe-statics.cpp4
-rw-r--r--test/CodeGenCXX/thunks.cpp11
-rw-r--r--test/CodeGenCXX/ubsan-devirtualized-calls.cpp81
-rw-r--r--test/CodeGenCXX/ubsan-vtable-checks.cpp40
-rw-r--r--test/CodeGenCXX/uncopyable-args.cpp74
-rw-r--r--test/CodeGenCXX/value-init.cpp10
-rw-r--r--test/CodeGenCXX/virtual-base-cast.cpp2
-rw-r--r--test/CodeGenCXX/virtual-destructor-calls.cpp2
-rw-r--r--test/CodeGenCXX/virtual-function-calls.cpp7
-rw-r--r--test/CodeGenCXX/visibility-inlines-hidden.cpp2
-rw-r--r--test/CodeGenCXX/vla-lambda-capturing.cpp4
-rw-r--r--test/CodeGenCXX/vtable-align.cpp4
-rw-r--r--test/CodeGenCXX/vtable-assume-load.cpp42
-rw-r--r--test/CodeGenCXX/vtable-available-externally.cpp2
-rw-r--r--test/CodeGenCXX/vtable-layout.cpp2
-rw-r--r--test/CodeGenCXX/vtable-linkage.cpp11
-rw-r--r--test/CodeGenCXX/vtable-pointer-initialization.cpp8
-rw-r--r--test/CodeGenCXX/vtt-layout.cpp13
-rw-r--r--test/CodeGenCXX/wasm-args-returns.cpp4
-rw-r--r--test/CodeGenCXX/windows-implicit-dllexport-template-specialization.cpp18
-rw-r--r--test/CodeGenCXX/windows-itanium-dllexport.cpp30
-rw-r--r--test/CodeGenCXX/windows-itanium-type-info.cpp40
-rw-r--r--test/CodeGenCoroutines/coro-alloc.cpp114
-rw-r--r--test/CodeGenCoroutines/coro-builtins-err.c10
-rw-r--r--test/CodeGenCoroutines/coro-builtins.c56
-rw-r--r--test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp25
-rw-r--r--test/CodeGenObjC/2010-02-01-utf16-with-null.m2
-rw-r--r--test/CodeGenObjC/arc-blocks.m2
-rw-r--r--test/CodeGenObjC/arc-bridged-cast.m2
-rw-r--r--test/CodeGenObjC/arc-linetable-autorelease.m5
-rw-r--r--test/CodeGenObjC/arc-literals.m2
-rw-r--r--test/CodeGenObjC/arc-no-arc-exceptions.m6
-rw-r--r--test/CodeGenObjC/arc-precise-lifetime.m2
-rw-r--r--test/CodeGenObjC/arc-ternary-op.m2
-rw-r--r--test/CodeGenObjC/arc-unsafeclaim.m7
-rw-r--r--test/CodeGenObjC/arc.m2
-rw-r--r--test/CodeGenObjC/block-byref-debuginfo.m1
-rw-r--r--test/CodeGenObjC/boxing.m12
-rw-r--r--test/CodeGenObjC/complex-property.m4
-rw-r--r--test/CodeGenObjC/debug-info-block-type.m2
-rw-r--r--test/CodeGenObjC/debug-info-ivars-extension.m4
-rw-r--r--test/CodeGenObjC/debug-info-ivars-private.m4
-rw-r--r--test/CodeGenObjC/debug-info-ivars.m8
-rw-r--r--test/CodeGenObjC/encode-cstyle-method.m2
-rw-r--r--test/CodeGenObjC/encode-test-6.m8
-rw-r--r--test/CodeGenObjC/encode-test.m2
-rw-r--r--test/CodeGenObjC/exceptions.m2
-rw-r--r--test/CodeGenObjC/fragile-arc.m8
-rw-r--r--test/CodeGenObjC/gnu-exceptions.m2
-rw-r--r--test/CodeGenObjC/ivar-layout-64.m40
-rw-r--r--test/CodeGenObjC/mangle-blocks.m5
-rw-r--r--test/CodeGenObjC/metadata-symbols-32.m11
-rw-r--r--test/CodeGenObjC/metadata-symbols-64.m8
-rw-r--r--test/CodeGenObjC/nsvalue-objc-boxable-ios-arc.m4
-rw-r--r--test/CodeGenObjC/nsvalue-objc-boxable-ios.m4
-rw-r--r--test/CodeGenObjC/nsvalue-objc-boxable-mac-arc.m4
-rw-r--r--test/CodeGenObjC/nsvalue-objc-boxable-mac.m4
-rw-r--r--test/CodeGenObjC/nullptr-assert.m22
-rw-r--r--test/CodeGenObjC/objc-asm-attribute-test.m6
-rw-r--r--test/CodeGenObjC/objc-literal-tests.m2
-rw-r--r--test/CodeGenObjC/os_log.m39
-rw-r--r--test/CodeGenObjC/property-list-in-extension.m10
-rw-r--r--test/CodeGenObjC/protocol-comdat.m20
-rw-r--r--test/CodeGenObjC/reorder-synthesized-ivars.m36
-rw-r--r--test/CodeGenObjC/runtime-abi-match.m25
-rw-r--r--test/CodeGenObjC/section-name.m45
-rw-r--r--test/CodeGenObjC/tentative-cfconstantstring.m2
-rw-r--r--test/CodeGenObjC/ubsan-array-bounds.m59
-rw-r--r--test/CodeGenObjC/ubsan-bool.m13
-rw-r--r--test/CodeGenObjC/unqual-copy-restore.m14
-rw-r--r--test/CodeGenObjCXX/arc-attrs.mm21
-rw-r--r--test/CodeGenObjCXX/arc-blocks.mm2
-rw-r--r--test/CodeGenObjCXX/arc-constexpr.mm18
-rw-r--r--test/CodeGenObjCXX/arc-cxx11-init-list.mm4
-rw-r--r--test/CodeGenObjCXX/arc-globals.mm2
-rw-r--r--test/CodeGenObjCXX/arc-move.mm2
-rw-r--r--test/CodeGenObjCXX/arc-new-delete.mm2
-rw-r--r--test/CodeGenObjCXX/arc-references.mm2
-rw-r--r--test/CodeGenObjCXX/arc-special-member-functions.mm3
-rw-r--r--test/CodeGenObjCXX/arc.mm2
-rw-r--r--test/CodeGenObjCXX/debug-info-cyclic.mm2
-rw-r--r--test/CodeGenObjCXX/destroy.mm2
-rw-r--r--test/CodeGenObjCXX/encode.mm23
-rw-r--r--test/CodeGenObjCXX/exceptions-legacy.mm8
-rw-r--r--test/CodeGenObjCXX/implicit-copy-constructor.mm8
-rw-r--r--test/CodeGenObjCXX/lambda-expressions.mm44
-rw-r--r--test/CodeGenObjCXX/literals.mm2
-rw-r--r--test/CodeGenObjCXX/property-object-reference-2.mm2
-rw-r--r--test/CodeGenOpenCL/address-space-constant-initializers.cl4
-rw-r--r--test/CodeGenOpenCL/address-spaces-mangling.cl18
-rw-r--r--test/CodeGenOpenCL/address-spaces.cl8
-rw-r--r--test/CodeGenOpenCL/amdgpu-abi-struct-coerce.cl66
-rw-r--r--test/CodeGenOpenCL/amdgpu-attrs.cl166
-rw-r--r--test/CodeGenOpenCL/amdgpu-nullptr.cl534
-rw-r--r--test/CodeGenOpenCL/amdgpu-num-gpr-attr.cl48
-rw-r--r--test/CodeGenOpenCL/as_type.cl41
-rw-r--r--test/CodeGenOpenCL/builtins-amdgcn-error.cl18
-rw-r--r--test/CodeGenOpenCL/builtins-amdgcn-vi.cl71
-rw-r--r--test/CodeGenOpenCL/builtins-amdgcn.cl79
-rw-r--r--test/CodeGenOpenCL/cast_image.cl18
-rw-r--r--test/CodeGenOpenCL/cl20-device-side-enqueue.cl139
-rw-r--r--test/CodeGenOpenCL/const-str-array-decay.cl2
-rw-r--r--test/CodeGenOpenCL/constant-addr-space-globals.cl21
-rw-r--r--test/CodeGenOpenCL/convergent.cl118
-rw-r--r--test/CodeGenOpenCL/denorms-are-zero.cl16
-rw-r--r--test/CodeGenOpenCL/extension-begin.cl25
-rw-r--r--test/CodeGenOpenCL/fpmath.cl36
-rw-r--r--test/CodeGenOpenCL/kernel-arg-info.cl20
-rw-r--r--test/CodeGenOpenCL/local-initializer-undef.cl8
-rw-r--r--test/CodeGenOpenCL/local.cl2
-rw-r--r--test/CodeGenOpenCL/memcpy.cl2
-rw-r--r--test/CodeGenOpenCL/null_queue.cl18
-rw-r--r--test/CodeGenOpenCL/opencl_types.cl48
-rw-r--r--test/CodeGenOpenCL/partial_initializer.cl66
-rw-r--r--test/CodeGenOpenCL/pipe_builtin.cl52
-rw-r--r--test/CodeGenOpenCL/pipe_types.cl4
-rw-r--r--test/CodeGenOpenCL/private-array-initialization.cl9
-rw-r--r--test/CodeGenOpenCL/sampler.cl57
-rw-r--r--test/CodeGenOpenCL/size_t.cl110
-rw-r--r--test/CodeGenOpenCL/spir_version.cl50
-rw-r--r--test/CodeGenOpenCL/str_literals.cl8
-rw-r--r--test/CodeGenOpenCL/unroll-hint.cl1
-rw-r--r--test/Coverage/ast-print-func.cpp12
-rw-r--r--test/Coverage/ast-print-temp-class.cpp64
-rw-r--r--test/Coverage/ast-print-temp-func.cpp25
-rw-r--r--test/Coverage/ast-printing.c4
-rw-r--r--test/Coverage/ast-printing.cpp4
-rw-r--r--test/CoverageMapping/abspath.cpp15
-rw-r--r--test/CoverageMapping/if.cpp (renamed from test/CoverageMapping/if.c)13
-rw-r--r--test/CoverageMapping/macroception.c6
-rw-r--r--test/CoverageMapping/macros.c23
-rw-r--r--test/CoverageMapping/switch.cpp (renamed from test/CoverageMapping/switch.c)40
-rw-r--r--test/CoverageMapping/switchmacro.c2
-rw-r--r--test/Driver/Inputs/CUDA-macosx/usr/local/cuda/bin/.keep (renamed from test/Driver/Inputs/CUDA/usr/local/cuda/nvvm/libdevice/libdevice.compute_20.10.bc)0
-rw-r--r--test/Driver/Inputs/CUDA-macosx/usr/local/cuda/include/.keep (renamed from test/Driver/Inputs/basic_android_tree/lib/gcc/mipsel-linux-android/4.4.3/mips-r6/crtbegin.o)0
-rw-r--r--test/Driver/Inputs/CUDA-macosx/usr/local/cuda/lib/.keep (renamed from test/Driver/Inputs/basic_android_tree/lib/gcc/mipsel-linux-android/4.4.3/mips-r6/crtbeginS.o)0
-rw-r--r--test/Driver/Inputs/CUDA-macosx/usr/local/cuda/nvvm/libdevice/libdevice.compute_30.10.bc (renamed from test/Driver/Inputs/basic_android_tree/lib/gcc/mipsel-linux-android/4.4.3/mips-r6/crtbeginT.o)0
-rw-r--r--test/Driver/Inputs/CUDA-macosx/usr/local/cuda/nvvm/libdevice/libdevice.compute_35.10.bc (renamed from test/Driver/Inputs/basic_android_tree/lib/gcc/mipsel-linux-android/4.4.3/mips-r6/crtend.o)0
-rw-r--r--test/Driver/Inputs/CUDA/usr/local/cuda/nvvm/libdevice/libdevice.compute_30.10.bc (renamed from test/Driver/Inputs/basic_android_tree/lib/gcc/mipsel-linux-android/4.4.3/mips-r6/crtendS.o)0
-rw-r--r--test/Driver/Inputs/CUDA_80/usr/local/cuda/nvvm/libdevice/libdevice.compute_30.10.bc0
-rw-r--r--test/Driver/Inputs/CUDA_80/usr/local/cuda/nvvm/libdevice/libdevice.compute_50.10.bc0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/lib/gcc/mips64el-linux-android/4.9/32/mips-r1/crtbegin.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/lib/gcc/mips64el-linux-android/4.9/32/mips-r1/crtend.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/lib/gcc/mips64el-linux-android/4.9/32/mips-r2/crtbegin.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/lib/gcc/mips64el-linux-android/4.9/32/mips-r2/crtend.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/lib/gcc/mips64el-linux-android/4.9/32/mips-r6/crtbegin.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/lib/gcc/mips64el-linux-android/4.9/32/mips-r6/crtend.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/lib/gcc/mips64el-linux-android/4.9/crtbegin.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/lib/gcc/mips64el-linux-android/4.9/crtend.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/lib/gcc/mips64el-linux-android/4.9/include/.keep0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/mips64el-linux-android/bin/.keep0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/mips64el-linux-android/lib/.keep0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/mips64el-linux-android/lib64/.keep0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/mips64el-linux-android/libr2/.keep0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/mips64el-linux-android/libr6/.keep0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/mipsel-linux-android/libr2/.keep0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/mipsel-linux-android/libr6/.keep0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr2/crtbegin_dynamic.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr2/crtbegin_so.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr2/crtbegin_static.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr2/crtend_android.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr2/crtend_so.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr6/crtbegin_dynamic.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr6/crtbegin_so.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr6/crtbegin_static.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr6/crtend_android.o0
-rw-r--r--test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr6/crtend_so.o0
-rw-r--r--test/Driver/Inputs/basic_myriad_tree/bin/.keep0
-rw-r--r--test/Driver/Inputs/gentoo_linux_gcc_multi_version_tree/etc/env.d/gcc/config-x86_64-pc-linux-gnu1
-rw-r--r--test/Driver/Inputs/gentoo_linux_gcc_multi_version_tree/etc/env.d/gcc/x86_64-pc-linux-gnu-4.9.310
-rw-r--r--test/Driver/Inputs/gentoo_linux_gcc_multi_version_tree/etc/gentoo-release1
-rw-r--r--test/Driver/Inputs/gentoo_linux_gcc_multi_version_tree/usr/include/.keep0
-rw-r--r--test/Driver/Inputs/gentoo_linux_gcc_multi_version_tree/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/32/crtbegin.o0
-rw-r--r--test/Driver/Inputs/gentoo_linux_gcc_multi_version_tree/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/crtbegin.o0
-rw-r--r--test/Driver/Inputs/gentoo_linux_gcc_multi_version_tree/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/include/g++-v4.9.3/.keep0
-rw-r--r--test/Driver/Inputs/gentoo_linux_gcc_multi_version_tree/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/x32/crtbegin.o0
-rw-r--r--test/Driver/Inputs/gentoo_linux_gcc_multi_version_tree/usr/lib/gcc/x86_64-pc-linux-gnu/5.4.0/32/crtbegin.o0
-rw-r--r--test/Driver/Inputs/gentoo_linux_gcc_multi_version_tree/usr/lib/gcc/x86_64-pc-linux-gnu/5.4.0/crtbegin.o0
-rw-r--r--test/Driver/Inputs/gentoo_linux_gcc_multi_version_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_multi_version_tree/usr/lib/gcc/x86_64-pc-linux-gnu/5.4.0/x32/crtbegin.o0
-rw-r--r--test/Driver/Inputs/gentoo_linux_gcc_multi_version_tree/usr/x86_64-pc-linux-gnu/lib/.keep0
-rw-r--r--test/Driver/Inputs/hexagon_tree/Tools/bin/.keep0
-rw-r--r--test/Driver/Inputs/hexagon_tree/Tools/bin/readme4
-rw-r--r--test/Driver/Inputs/hexagon_tree/Tools/readme4
-rw-r--r--test/Driver/Inputs/hexagon_tree/Tools/target/.keep0
-rw-r--r--test/Driver/Inputs/hexagon_tree/Tools/target/hexagon/include/c++/readme4
-rw-r--r--test/Driver/Inputs/hexagon_tree/Tools/target/hexagon/include/readme4
-rw-r--r--test/Driver/Inputs/hexagon_tree/Tools/target/hexagon/readme4
-rw-r--r--test/Driver/Inputs/hexagon_tree/Tools/target/readme4
-rw-r--r--test/Driver/Inputs/rewrite-1.map0
-rw-r--r--test/Driver/Inputs/rewrite-2.map0
-rw-r--r--test/Driver/Inputs/rewrite.map0
-rw-r--r--test/Driver/XRay/lit.local.cfg2
-rw-r--r--test/Driver/XRay/xray-instrument-cpu.c4
-rw-r--r--test/Driver/XRay/xray-instrument-os.c4
-rw-r--r--test/Driver/aarch64-cpus.c74
-rw-r--r--test/Driver/analyzer-target-enabled-checkers.cpp60
-rw-r--r--test/Driver/android-aarch64-link.cpp17
-rw-r--r--test/Driver/android-ndk-standalone.cpp48
-rw-r--r--test/Driver/android-standalone.cpp16
-rw-r--r--test/Driver/arm-cortex-cpus.c43
-rw-r--r--test/Driver/arm-execute-only.c99
-rw-r--r--test/Driver/arm-implicit-it.s24
-rw-r--r--test/Driver/cc1-response-files.c2
-rw-r--r--test/Driver/cl-fallback.c6
-rw-r--r--test/Driver/cl-link.c3
-rw-r--r--test/Driver/cl-options.c55
-rw-r--r--test/Driver/cl-outputs.c2
-rw-r--r--test/Driver/cl-pch.c57
-rw-r--r--test/Driver/cl-pch.cpp6
-rw-r--r--test/Driver/clang-g-opts.c5
-rw-r--r--test/Driver/clang-offload-bundler.c260
-rw-r--r--test/Driver/clang-offload-bundler.c.obin0 -> 1921 bytes
-rw-r--r--test/Driver/clang-translation.c17
-rw-r--r--test/Driver/clang_f_opts.c23
-rw-r--r--test/Driver/compilation_database.c11
-rw-r--r--test/Driver/coroutines.c6
-rw-r--r--test/Driver/coroutines.cpp9
-rw-r--r--test/Driver/coverage_no_integrated_as.c8
-rw-r--r--test/Driver/crash-report-crashfile.m17
-rw-r--r--test/Driver/cuda-bad-arch.cu5
-rw-r--r--test/Driver/cuda-bindings.cu137
-rw-r--r--test/Driver/cuda-detect.cu98
-rw-r--r--test/Driver/cuda-external-tools.cu11
-rw-r--r--test/Driver/cuda-macosx.cu8
-rw-r--r--test/Driver/cuda-no-sanitizers.cu13
-rw-r--r--test/Driver/cuda-options.cu73
-rw-r--r--test/Driver/cuda-output-asm.cu6
-rw-r--r--test/Driver/cuda-phases.cu201
-rw-r--r--test/Driver/cuda-ptxas-path.cu12
-rw-r--r--test/Driver/cuda-simple.cu2
-rw-r--r--test/Driver/cuda-version-check.cu9
-rw-r--r--test/Driver/cuda_phases.cu206
-rw-r--r--test/Driver/darwin-debug-flags.c2
-rw-r--r--test/Driver/darwin-iphone-defaults.m2
-rw-r--r--test/Driver/darwin-ld-dedup.c46
-rw-r--r--test/Driver/darwin-ld-lto.c3
-rw-r--r--test/Driver/darwin-ld.c14
-rw-r--r--test/Driver/darwin-multiarch-arm.c2
-rw-r--r--test/Driver/darwin-objc-gc.m19
-rw-r--r--test/Driver/darwin-stdlib.cpp4
-rw-r--r--test/Driver/debug-options.c92
-rw-r--r--test/Driver/defsym.s37
-rw-r--r--test/Driver/denormal-fp-math.c12
-rw-r--r--test/Driver/embed-bitcode.c12
-rw-r--r--test/Driver/esan.c4
-rw-r--r--test/Driver/fast-math.c4
-rw-r--r--test/Driver/frame-pointer-elim.c20
-rw-r--r--test/Driver/fsanitize-blacklist.c2
-rw-r--r--test/Driver/fsanitize-coverage.c12
-rw-r--r--test/Driver/fsanitize.c50
-rw-r--r--test/Driver/fuchsia.c40
-rw-r--r--test/Driver/fuchsia.cpp33
-rw-r--r--test/Driver/gold-lto-sections.c8
-rw-r--r--test/Driver/hexagon-long-calls.c15
-rw-r--r--test/Driver/integrated-as.s30
-rw-r--r--test/Driver/linux-header-search.cpp42
-rw-r--r--test/Driver/linux-ld.c141
-rw-r--r--test/Driver/lto-jobs.c11
-rw-r--r--test/Driver/masm.s11
-rw-r--r--test/Driver/miamcu-opt.c14
-rw-r--r--test/Driver/miamcu-opt.cpp2
-rw-r--r--test/Driver/mingw-libgcc.c24
-rw-r--r--test/Driver/mingw.cpp14
-rw-r--r--test/Driver/mips-cs.cpp2
-rw-r--r--test/Driver/mips-fsf.cpp2
-rw-r--r--test/Driver/mips-img-v2.cpp2
-rw-r--r--test/Driver/mips-img.cpp2
-rw-r--r--test/Driver/mips-mti-linux.c4
-rw-r--r--test/Driver/modules-ts.cpp38
-rw-r--r--test/Driver/modules.m17
-rw-r--r--test/Driver/montavista-gcc-toolchain.c2
-rw-r--r--test/Driver/msc-version.c9
-rw-r--r--test/Driver/msvc-triple.c2
-rw-r--r--test/Driver/myriad-toolchain.c17
-rw-r--r--test/Driver/nostdlib.c10
-rw-r--r--test/Driver/offloading-interoperability.c17
-rw-r--r--test/Driver/opencl.cl2
-rw-r--r--test/Driver/openmp-offload.c589
-rw-r--r--test/Driver/opt-record.c18
-rw-r--r--test/Driver/ppc-abi.c3
-rw-r--r--test/Driver/ppc-dependent-options.cpp22
-rw-r--r--test/Driver/ppc-features.cpp26
-rw-r--r--test/Driver/preserve-as-comments.c2
-rw-r--r--test/Driver/print-libgcc-file-name-clangrt.c11
-rw-r--r--test/Driver/print-libgcc-file-name-libgcc.c7
-rw-r--r--test/Driver/response-file-extra-whitespace.c2
-rw-r--r--test/Driver/rewrite-map-files.c2
-rw-r--r--test/Driver/ropi-rwpi.c38
-rw-r--r--test/Driver/sanitizer-ld.c49
-rw-r--r--test/Driver/save-stats.c20
-rw-r--r--test/Driver/show-option-names.c7
-rw-r--r--test/Driver/split-debug.c32
-rw-r--r--test/Driver/stack-protector.c28
-rw-r--r--test/Driver/sysroot.c2
-rw-r--r--test/Driver/systemz-march.c10
-rw-r--r--test/Driver/unsupported-target-arch.c25
-rw-r--r--test/Driver/warning-options.cpp4
-rw-r--r--test/Driver/windows-cross.c2
-rw-r--r--test/Driver/windows-pic.cpp59
-rw-r--r--test/Driver/windows-thumb.s2
-rw-r--r--test/FixIt/Inputs/nullability.h27
-rw-r--r--test/FixIt/fixit.cpp22
-rw-r--r--test/FixIt/nullability.mm78
-rw-r--r--test/Format/remove-duplicate-includes.cpp14
-rw-r--r--test/Frontend/Inputs/absolute-paths.h3
-rw-r--r--test/Frontend/Inputs/optimization-remark-with-hotness.proftext25
-rw-r--r--test/Frontend/aarch64-target-cpu.c14
-rw-r--r--test/Frontend/absolute-paths.c17
-rw-r--r--test/Frontend/gnu-mcount.c64
-rw-r--r--test/Frontend/include-duplicate-removal.c12
-rw-r--r--test/Frontend/int128.cpp11
-rw-r--r--test/Frontend/objc-bool-is-bool.m13
-rw-r--r--test/Frontend/optimization-remark-with-hotness.c45
-rw-r--r--test/Frontend/plugin-vs-debug-info.cpp32
-rw-r--r--test/Frontend/stats-file.c8
-rw-r--r--test/Headers/Inputs/usr/include/float.h6
-rw-r--r--test/Headers/float-darwin.c13
-rw-r--r--test/Headers/ms-intrin.cpp6
-rw-r--r--test/Headers/opencl-c-header.cl35
-rw-r--r--test/Headers/stdatomic.c32
-rw-r--r--test/Headers/x86intrin.cpp11
-rw-r--r--test/Import/clang-flags/Inputs/S.c2
-rw-r--r--test/Import/clang-flags/test.c5
-rw-r--r--test/Import/empty-struct/Inputs/S.c2
-rw-r--r--test/Import/empty-struct/test.c5
-rw-r--r--test/Import/error-in-expression/Inputs/S.c2
-rw-r--r--test/Import/error-in-expression/test.c6
-rw-r--r--test/Import/error-in-import/Inputs/S.c2
-rw-r--r--test/Import/error-in-import/test.c6
-rw-r--r--test/Import/missing-import/test.c6
-rw-r--r--test/Index/Core/designated-inits.c33
-rw-r--r--test/Index/Core/index-source.cpp37
-rw-r--r--test/Index/Core/index-source.m44
-rw-r--r--test/Index/Core/index-subkinds.m18
-rw-r--r--test/Index/annotate-tokens.c4
-rw-r--r--test/Index/comment-cplus-decls.cpp2
-rw-r--r--test/Index/comment-to-html-xml-conversion.cpp6
-rw-r--r--test/Index/complete-block-properties.m88
-rw-r--r--test/Index/complete-block-property-assignment.m68
-rw-r--r--test/Index/complete-kvc.m2
-rw-r--r--test/Index/complete-method-decls.m2
-rw-r--r--test/Index/complete-objc-message-id.m4
-rw-r--r--test/Index/complete-objc-message.m8
-rw-r--r--test/Index/complete-properties.m81
-rw-r--r--test/Index/complete-recovery.m2
-rw-r--r--test/Index/complete-super.m4
-rw-r--r--test/Index/evaluate-cursor.cpp14
-rw-r--r--test/Index/get-cursor.cpp5
-rw-r--r--test/Index/keep-going.cpp4
-rw-r--r--test/Index/load-classes.cpp22
-rw-r--r--test/Index/load-staticassert.cpp11
-rw-r--r--test/Index/pr20320.cpp2
-rw-r--r--test/Index/pr20320.h14
-rw-r--r--test/Index/print-type.cpp31
-rw-r--r--test/Lexer/coroutines.cpp2
-rw-r--r--test/Lexer/cxx-features.cpp118
-rw-r--r--test/Lexer/modules-ts.cpp11
-rw-r--r--test/Misc/amdgcn.languageOptsOpenCL.cl31
-rw-r--r--test/Misc/ast-dump-color.cpp4
-rw-r--r--test/Misc/ast-dump-decl.c10
-rw-r--r--test/Misc/ast-dump-decl.cpp20
-rw-r--r--test/Misc/ast-dump-pipe.cl10
-rw-r--r--test/Misc/ast-dump-stmt.cpp16
-rw-r--r--test/Misc/ast-dump-templates.cpp18
-rw-r--r--test/Misc/ast-dump-wchar.cpp4
-rw-r--r--test/Misc/ast-print-objectivec.m6
-rw-r--r--test/Misc/backend-optimization-failure-nodbg.cpp4
-rw-r--r--test/Misc/backend-optimization-failure.cpp4
-rw-r--r--test/Misc/backend-stack-frame-diagnostics.cpp2
-rw-r--r--test/Misc/diag-template-diffing.cpp5
-rw-r--r--test/Misc/warning-flags.c8
-rw-r--r--test/Modules/ExtDebugInfo.cpp46
-rw-r--r--test/Modules/ExtDebugInfo.m20
-rw-r--r--test/Modules/Inputs/DebugCXX.h6
-rw-r--r--test/Modules/Inputs/DebugNestedA.h8
-rw-r--r--test/Modules/Inputs/DebugNestedB.h7
-rw-r--r--test/Modules/Inputs/DiagOutOfDate.h1
-rw-r--r--test/Modules/Inputs/GNUAsm/NeedsGNUInlineAsm.framework/Headers/NeedsGNUInlineAsm.h1
-rw-r--r--test/Modules/Inputs/GNUAsm/NeedsGNUInlineAsm.framework/Headers/asm.h1
-rw-r--r--test/Modules/Inputs/GNUAsm/NeedsGNUInlineAsm.framework/module.map8
-rw-r--r--test/Modules/Inputs/PR27699/Subdir/a.h1
-rw-r--r--test/Modules/Inputs/PR27699/Subdir/b.h1
-rw-r--r--test/Modules/Inputs/PR27699/module.modulemap1
-rw-r--r--test/Modules/Inputs/PR27699/streambuf7
-rw-r--r--test/Modules/Inputs/PR28438/a.h1
-rw-r--r--test/Modules/Inputs/PR28438/b1.h2
-rw-r--r--test/Modules/Inputs/PR28438/b2.h0
-rw-r--r--test/Modules/Inputs/PR28438/module.modulemap2
-rw-r--r--test/Modules/Inputs/PR28752/Subdir1/b.h4
-rw-r--r--test/Modules/Inputs/PR28752/Subdir1/c.h2
-rw-r--r--test/Modules/Inputs/PR28752/Subdir1/module.modulemap5
-rw-r--r--test/Modules/Inputs/PR28752/a.h1
-rw-r--r--test/Modules/Inputs/PR28752/module.modulemap1
-rw-r--r--test/Modules/Inputs/PR28752/vector28
-rw-r--r--test/Modules/Inputs/PR28794/LibAHeader.h12
-rw-r--r--test/Modules/Inputs/PR28794/Subdir/Empty.h1
-rw-r--r--test/Modules/Inputs/PR28794/Subdir/LibBHeader.h12
-rw-r--r--test/Modules/Inputs/PR28794/module.modulemap3
-rw-r--r--test/Modules/Inputs/PR28812/Textual.h11
-rw-r--r--test/Modules/Inputs/PR28812/a.h1
-rw-r--r--test/Modules/Inputs/PR28812/b.h1
-rw-r--r--test/Modules/Inputs/PR28812/module.modulemap6
-rw-r--r--test/Modules/Inputs/cxx-header.h5
-rw-r--r--test/Modules/Inputs/implicit-private-with-different-name/A.framework/Headers/a.h1
-rw-r--r--test/Modules/Inputs/implicit-private-with-different-name/A.framework/Headers/aprivate.h1
-rw-r--r--test/Modules/Inputs/implicit-private-with-different-name/A.framework/Modules/module.modulemap4
-rw-r--r--test/Modules/Inputs/implicit-private-with-different-name/A.framework/Modules/module.private.modulemap4
-rw-r--r--test/Modules/Inputs/libc-libcxx/include/c++/math.h2
-rw-r--r--test/Modules/Inputs/libc-libcxx/include/c++/module.modulemap4
-rw-r--r--test/Modules/Inputs/libc-libcxx/include/c++/stdlib.h1
-rw-r--r--test/Modules/Inputs/libc-libcxx/include/math.h1
-rw-r--r--test/Modules/Inputs/libc-libcxx/include/module.modulemap4
-rw-r--r--test/Modules/Inputs/libc-libcxx/include/stdlib.h1
-rw-r--r--test/Modules/Inputs/libc-libcxx/sysroot/Frameworks/A.framework/Headers/A.h15
-rw-r--r--test/Modules/Inputs/libc-libcxx/sysroot/Frameworks/A.framework/Headers/int.h14
-rw-r--r--test/Modules/Inputs/libc-libcxx/sysroot/Frameworks/A.framework/Modules/module.modulemap4
-rw-r--r--test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/__config6
-rw-r--r--test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/math.h7
-rw-r--r--test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/module.modulemap10
-rw-r--r--test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/stddef.h6
-rw-r--r--test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/stdint.h6
-rw-r--r--test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/stdio.h6
-rw-r--r--test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/stdlib.h6
-rw-r--r--test/Modules/Inputs/libc-libcxx/sysroot/usr/include/math.h1
-rw-r--r--test/Modules/Inputs/libc-libcxx/sysroot/usr/include/module.modulemap8
-rw-r--r--test/Modules/Inputs/libc-libcxx/sysroot/usr/include/stddef.h1
-rw-r--r--test/Modules/Inputs/libc-libcxx/sysroot/usr/include/stdint.h22
-rw-r--r--test/Modules/Inputs/libc-libcxx/sysroot/usr/include/stdio.h4
-rw-r--r--test/Modules/Inputs/libc-libcxx/sysroot/usr/include/stdlib.h1
-rw-r--r--test/Modules/Inputs/libc-libcxx/sysroot/usr/include/util.h6
-rw-r--r--test/Modules/Inputs/lookup-assert/Base.h3
-rw-r--r--test/Modules/Inputs/lookup-assert/Derive.h3
-rw-r--r--test/Modules/Inputs/lookup-assert/H3.h1
-rw-r--r--test/Modules/Inputs/lookup-assert/module.map4
-rw-r--r--test/Modules/Inputs/merge-decl-context/a.h1
-rw-r--r--test/Modules/Inputs/merge-fn-prototype-tags/a.h2
-rw-r--r--test/Modules/Inputs/merge-fn-prototype-tags/b.h1
-rw-r--r--test/Modules/Inputs/merge-fn-prototype-tags/c.h4
-rw-r--r--test/Modules/Inputs/merge-fn-prototype-tags/module.modulemap5
-rw-r--r--test/Modules/Inputs/merge-template-pattern-visibility/a.h1
-rw-r--r--test/Modules/Inputs/merge-template-pattern-visibility/b.h11
-rw-r--r--test/Modules/Inputs/merge-template-pattern-visibility/c.h9
-rw-r--r--test/Modules/Inputs/merge-template-pattern-visibility/d.h1
-rw-r--r--test/Modules/Inputs/merge-template-pattern-visibility/module.modulemap4
-rw-r--r--test/Modules/Inputs/merge-template-specializations/a.h1
-rw-r--r--test/Modules/Inputs/merge-template-specializations/b.h2
-rw-r--r--test/Modules/Inputs/merge-template-specializations/c.h3
-rw-r--r--test/Modules/Inputs/merge-template-specializations/module.modulemap3
-rw-r--r--test/Modules/Inputs/merge-var-template-def/a.h8
-rw-r--r--test/Modules/Inputs/merge-var-template-def/b1.h9
-rw-r--r--test/Modules/Inputs/merge-var-template-def/b2.h9
-rw-r--r--test/Modules/Inputs/merge-var-template-def/module.modulemap5
-rw-r--r--test/Modules/Inputs/module.map14
-rw-r--r--test/Modules/Inputs/objc-category-2/Base.h3
-rw-r--r--test/Modules/Inputs/objc-category-2/Category.h4
-rw-r--r--test/Modules/Inputs/objc-category-2/H3.h1
-rw-r--r--test/Modules/Inputs/objc-category-2/module.map4
-rw-r--r--test/Modules/Inputs/objc-category-3/Base.h2
-rw-r--r--test/Modules/Inputs/objc-category-3/Category.h4
-rw-r--r--test/Modules/Inputs/objc-category-3/Category_B.h4
-rw-r--r--test/Modules/Inputs/objc-category-3/H3.h1
-rw-r--r--test/Modules/Inputs/objc-category-3/module.map4
-rw-r--r--test/Modules/Inputs/objc-category/Base.h2
-rw-r--r--test/Modules/Inputs/objc-category/Category.h4
-rw-r--r--test/Modules/Inputs/objc-category/H3.h1
-rw-r--r--test/Modules/Inputs/objc-category/module.map4
-rw-r--r--test/Modules/Inputs/objc-hidden/FakeUnavailableObjCFramework.framework/Headers/FakeUnavailableObjCFramework.h7
-rw-r--r--test/Modules/Inputs/objc-hidden/FakeUnavailableObjCFramework.framework/Modules/module.modulemap5
-rw-r--r--test/Modules/Inputs/objc-hidden/System/X.h5
-rw-r--r--test/Modules/Inputs/objc-hidden/System/module.map4
-rw-r--r--test/Modules/Inputs/objc-initializer/X.h3
-rw-r--r--test/Modules/Inputs/objc-initializer/module.modulemap7
-rw-r--r--test/Modules/Inputs/objc-method-redecl.h4
-rw-r--r--test/Modules/Inputs/pch-import-module-out-of-date.pch1
-rw-r--r--test/Modules/Inputs/prebuilt-module/a.h1
-rw-r--r--test/Modules/Inputs/prebuilt-module/module.modulemap1
-rw-r--r--test/Modules/Inputs/templates-left.h2
-rw-r--r--test/Modules/Inputs/templates-right.h2
-rw-r--r--test/Modules/Inputs/templates-top.h5
-rw-r--r--test/Modules/Inputs/unused-global-init/init.h1
-rw-r--r--test/Modules/Inputs/unused-global-init/module.modulemap3
-rw-r--r--test/Modules/Inputs/unused-global-init/other.h1
-rw-r--r--test/Modules/Inputs/unused-global-init/unused.h1
-rw-r--r--test/Modules/Inputs/unused-global-init/used.h2
-rw-r--r--test/Modules/ModuleDebugInfo.cpp14
-rw-r--r--test/Modules/ModuleDebugInfo.m2
-rw-r--r--test/Modules/ModuleModuleDebugInfo.cpp18
-rw-r--r--test/Modules/compiler_builtins.m1
-rw-r--r--test/Modules/compiler_builtins_x86.c7
-rw-r--r--test/Modules/config-mismatch.cpp13
-rw-r--r--test/Modules/crash-vfs-headermaps.m55
-rw-r--r--test/Modules/crash-vfs-include-pch.m43
-rw-r--r--test/Modules/crash-vfs-ivfsoverlay.m45
-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-path-traversal.m2
-rw-r--r--test/Modules/crash-vfs-relative-incdir.m57
-rw-r--r--test/Modules/crash-vfs-relative-overlay.m2
-rw-r--r--test/Modules/crash-vfs-run-reproducer.m4
-rw-r--r--test/Modules/cstd.m2
-rw-r--r--test/Modules/cxx-irgen.cpp4
-rw-r--r--test/Modules/cxx-templates.cpp24
-rw-r--r--test/Modules/dependency-dump-dependent-module.m6
-rw-r--r--test/Modules/diagnostic-options-out-of-date.m12
-rw-r--r--test/Modules/embed-files.cpp5
-rw-r--r--test/Modules/empty.modulemap1
-rw-r--r--test/Modules/explicit-build-extra-files.cpp2
-rw-r--r--test/Modules/explicit-build.cpp4
-rw-r--r--test/Modules/global-init.cpp19
-rw-r--r--test/Modules/implicit-private-with-different-name.m20
-rw-r--r--test/Modules/incomplete-module.m2
-rw-r--r--test/Modules/lambda-context.cpp22
-rw-r--r--test/Modules/libc-libcxx.cpp10
-rw-r--r--test/Modules/lookup-assert.m10
-rw-r--r--test/Modules/merge-fn-prototype-tags.c8
-rw-r--r--test/Modules/merge-name-for-linkage.cpp1
-rw-r--r--test/Modules/merge-template-pattern-visibility.cpp18
-rw-r--r--test/Modules/merge-template-specializations.cpp5
-rw-r--r--test/Modules/merge-var-template-def.cpp7
-rw-r--r--test/Modules/module-file-modified.c11
-rw-r--r--test/Modules/module_file_info.m11
-rw-r--r--test/Modules/no-stale-modtime.m14
-rw-r--r--test/Modules/objc-category-2.m12
-rw-r--r--test/Modules/objc-category-3.m14
-rw-r--r--test/Modules/objc-category.m13
-rw-r--r--test/Modules/objc-hidden.m11
-rw-r--r--test/Modules/objc-initializer.m15
-rw-r--r--test/Modules/objc-method-redecl.m8
-rw-r--r--test/Modules/odr.cpp8
-rw-r--r--test/Modules/pr27699.cpp9
-rw-r--r--test/Modules/pr28438.cpp7
-rw-r--r--test/Modules/pr28752.cpp22
-rw-r--r--test/Modules/pr28812.cpp22
-rw-r--r--test/Modules/prebuilt-module.m10
-rw-r--r--test/Modules/prune.m7
-rw-r--r--test/Modules/redundant-include.mm12
-rw-r--r--test/Modules/requires-gnuinlineasm.m16
-rw-r--r--test/Modules/signal.m2
-rw-r--r--test/Modules/stress-objc.m22
-rw-r--r--test/Modules/templates.mm15
-rw-r--r--test/Modules/umbrella-header-include-builtin.mm6
-rw-r--r--test/Modules/unused-global-init.cpp37
-rw-r--r--test/OpenMP/atomic_ast_print.cpp4
-rw-r--r--test/OpenMP/atomic_capture_codegen.cpp1
-rw-r--r--test/OpenMP/atomic_messages.c4
-rw-r--r--test/OpenMP/atomic_messages.cpp4
-rw-r--r--test/OpenMP/atomic_update_codegen.cpp1
-rw-r--r--test/OpenMP/barrier_ast_print.cpp4
-rw-r--r--test/OpenMP/barrier_codegen.cpp1
-rw-r--r--test/OpenMP/cancel_ast_print.cpp6
-rw-r--r--test/OpenMP/cancel_codegen.cpp7
-rw-r--r--test/OpenMP/cancel_if_messages.cpp6
-rw-r--r--test/OpenMP/cancellation_point_codegen.cpp1
-rw-r--r--test/OpenMP/critical_ast_print.cpp12
-rw-r--r--test/OpenMP/critical_codegen.cpp1
-rw-r--r--test/OpenMP/declare_reduction_ast_print.cpp15
-rw-r--r--test/OpenMP/declare_reduction_codegen.c6
-rw-r--r--test/OpenMP/declare_reduction_codegen.cpp6
-rw-r--r--test/OpenMP/declare_simd_ast_print.cpp38
-rw-r--r--test/OpenMP/declare_simd_codegen.cpp1
-rw-r--r--test/OpenMP/declare_target_ast_print.cpp12
-rw-r--r--test/OpenMP/distribute_ast_print.cpp6
-rw-r--r--test/OpenMP/distribute_dist_schedule_ast_print.cpp1
-rw-r--r--test/OpenMP/distribute_parallel_for_ast_print.cpp8
-rw-r--r--test/OpenMP/distribute_parallel_for_if_messages.cpp6
-rw-r--r--test/OpenMP/distribute_parallel_for_simd_aligned_messages.cpp3
-rw-r--r--test/OpenMP/distribute_parallel_for_simd_ast_print.cpp8
-rw-r--r--test/OpenMP/distribute_parallel_for_simd_if_messages.cpp6
-rw-r--r--test/OpenMP/distribute_simd_aligned_messages.cpp3
-rw-r--r--test/OpenMP/distribute_simd_ast_print.cpp2
-rw-r--r--test/OpenMP/flush_ast_print.cpp6
-rw-r--r--test/OpenMP/flush_codegen.cpp1
-rw-r--r--test/OpenMP/for_ast_print.cpp7
-rw-r--r--test/OpenMP/for_codegen.cpp4
-rw-r--r--test/OpenMP/for_firstprivate_codegen.cpp1
-rw-r--r--test/OpenMP/for_lastprivate_codegen.cpp1
-rw-r--r--test/OpenMP/for_linear_codegen.cpp1
-rw-r--r--test/OpenMP/for_private_codegen.cpp1
-rw-r--r--test/OpenMP/for_reduction_codegen.cpp1
-rw-r--r--test/OpenMP/for_reduction_codegen_UDR.cpp1
-rw-r--r--test/OpenMP/for_simd_aligned_messages.cpp3
-rw-r--r--test/OpenMP/for_simd_ast_print.cpp4
-rw-r--r--test/OpenMP/for_simd_codegen.cpp111
-rw-r--r--test/OpenMP/linking.c18
-rw-r--r--test/OpenMP/master_codegen.cpp1
-rw-r--r--test/OpenMP/nesting_of_regions.cpp6524
-rw-r--r--test/OpenMP/nvptx_target_codegen.cpp37
-rw-r--r--test/OpenMP/ordered_ast_print.cpp8
-rw-r--r--test/OpenMP/ordered_codegen.cpp1
-rw-r--r--test/OpenMP/ordered_doacross_codegen.cpp1
-rw-r--r--test/OpenMP/parallel_ast_print.cpp52
-rw-r--r--test/OpenMP/parallel_codegen.cpp1
-rw-r--r--test/OpenMP/parallel_for_ast_print.cpp8
-rw-r--r--test/OpenMP/parallel_for_codegen.cpp1
-rw-r--r--test/OpenMP/parallel_for_if_messages.cpp6
-rw-r--r--test/OpenMP/parallel_for_linear_codegen.cpp1
-rw-r--r--test/OpenMP/parallel_for_simd_aligned_messages.cpp3
-rw-r--r--test/OpenMP/parallel_for_simd_ast_print.cpp10
-rw-r--r--test/OpenMP/parallel_for_simd_codegen.cpp111
-rw-r--r--test/OpenMP/parallel_for_simd_if_messages.cpp6
-rw-r--r--test/OpenMP/parallel_if_codegen.cpp6
-rw-r--r--test/OpenMP/parallel_if_messages.cpp6
-rw-r--r--test/OpenMP/parallel_private_codegen.cpp1
-rw-r--r--test/OpenMP/parallel_reduction_codegen.cpp1
-rw-r--r--test/OpenMP/parallel_sections_ast_print.cpp54
-rw-r--r--test/OpenMP/parallel_sections_codegen.cpp1
-rw-r--r--test/OpenMP/parallel_sections_if_messages.cpp2
-rw-r--r--test/OpenMP/sections_ast_print.cpp1
-rw-r--r--test/OpenMP/sections_codegen.cpp1
-rw-r--r--test/OpenMP/sections_firstprivate_codegen.cpp1
-rw-r--r--test/OpenMP/sections_lastprivate_codegen.cpp1
-rw-r--r--test/OpenMP/sections_private_codegen.cpp1
-rw-r--r--test/OpenMP/sections_reduction_codegen.cpp1
-rw-r--r--test/OpenMP/simd_aligned_messages.cpp3
-rw-r--r--test/OpenMP/simd_ast_print.cpp4
-rw-r--r--test/OpenMP/simd_codegen.cpp61
-rw-r--r--test/OpenMP/single_ast_print.cpp1
-rw-r--r--test/OpenMP/single_codegen.cpp1
-rw-r--r--test/OpenMP/single_firstprivate_codegen.cpp1
-rw-r--r--test/OpenMP/single_private_codegen.cpp1
-rw-r--r--test/OpenMP/target_ast_print.cpp24
-rw-r--r--test/OpenMP/target_data_ast_print.cpp18
-rw-r--r--test/OpenMP/target_data_if_messages.cpp2
-rw-r--r--test/OpenMP/target_data_use_device_ptr_ast_print.cpp4
-rw-r--r--test/OpenMP/target_data_use_device_ptr_codegen.cpp464
-rw-r--r--test/OpenMP/target_depend_messages.cpp2
-rw-r--r--test/OpenMP/target_enter_data_ast_print.cpp18
-rw-r--r--test/OpenMP/target_enter_data_depend_messages.cpp4
-rw-r--r--test/OpenMP/target_enter_data_if_messages.cpp2
-rw-r--r--test/OpenMP/target_exit_data_ast_print.cpp18
-rw-r--r--test/OpenMP/target_exit_data_depend_messages.cpp4
-rw-r--r--test/OpenMP/target_exit_data_if_messages.cpp2
-rw-r--r--test/OpenMP/target_if_messages.cpp2
-rw-r--r--test/OpenMP/target_is_device_ptr_ast_print.cpp4
-rw-r--r--test/OpenMP/target_is_device_ptr_codegen.cpp293
-rw-r--r--test/OpenMP/target_is_device_ptr_messages.cpp34
-rw-r--r--test/OpenMP/target_map_codegen.cpp290
-rw-r--r--test/OpenMP/target_map_messages.cpp16
-rw-r--r--test/OpenMP/target_parallel_ast_print.cpp72
-rw-r--r--test/OpenMP/target_parallel_depend_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_for_ast_print.cpp8
-rw-r--r--test/OpenMP/target_parallel_for_depend_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_for_if_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_for_map_messages.cpp8
-rw-r--r--test/OpenMP/target_parallel_for_simd_aligned_messages.cpp3
-rw-r--r--test/OpenMP/target_parallel_for_simd_ast_print.cpp8
-rw-r--r--test/OpenMP/target_parallel_for_simd_depend_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_for_simd_if_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_for_simd_map_messages.cpp8
-rw-r--r--test/OpenMP/target_parallel_if_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_is_device_ptr_ast_print.cpp294
-rw-r--r--test/OpenMP/target_parallel_is_device_ptr_messages.cpp268
-rw-r--r--test/OpenMP/target_parallel_map_messages.cpp8
-rw-r--r--test/OpenMP/target_simd_aligned_messages.cpp204
-rw-r--r--test/OpenMP/target_simd_ast_print.cpp310
-rw-r--r--test/OpenMP/target_simd_collapse_messages.cpp100
-rw-r--r--test/OpenMP/target_simd_defaultmap_messages.cpp58
-rw-r--r--test/OpenMP/target_simd_depend_messages.cpp90
-rw-r--r--test/OpenMP/target_simd_device_messages.cpp40
-rw-r--r--test/OpenMP/target_simd_firstprivate_messages.cpp261
-rw-r--r--test/OpenMP/target_simd_if_messages.cpp91
-rw-r--r--test/OpenMP/target_simd_is_device_ptr_messages.cpp288
-rw-r--r--test/OpenMP/target_simd_lastprivate_messages.cpp238
-rw-r--r--test/OpenMP/target_simd_linear_messages.cpp269
-rw-r--r--test/OpenMP/target_simd_loop_messages.cpp629
-rw-r--r--test/OpenMP/target_simd_map_messages.cpp273
-rw-r--r--test/OpenMP/target_simd_messages.cpp92
-rw-r--r--test/OpenMP/target_simd_misc_messages.c485
-rw-r--r--test/OpenMP/target_simd_nowait_messages.cpp18
-rw-r--r--test/OpenMP/target_simd_private_messages.cpp231
-rw-r--r--test/OpenMP/target_simd_reduction_messages.cpp319
-rw-r--r--test/OpenMP/target_simd_safelen_messages.cpp102
-rw-r--r--test/OpenMP/target_simd_simdlen_messages.cpp142
-rw-r--r--test/OpenMP/target_teams_ast_print.cpp98
-rw-r--r--test/OpenMP/target_teams_default_messages.cpp26
-rw-r--r--test/OpenMP/target_teams_defaultmap_messages.cpp56
-rw-r--r--test/OpenMP/target_teams_depend_messages.cpp89
-rw-r--r--test/OpenMP/target_teams_device_messages.cpp39
-rw-r--r--test/OpenMP/target_teams_distribute_ast_print.cpp150
-rw-r--r--test/OpenMP/target_teams_distribute_collapse_messages.cpp127
-rw-r--r--test/OpenMP/target_teams_distribute_default_messages.cpp23
-rw-r--r--test/OpenMP/target_teams_distribute_defaultmap_messages.cpp58
-rw-r--r--test/OpenMP/target_teams_distribute_depend_messages.cpp90
-rw-r--r--test/OpenMP/target_teams_distribute_device_messages.cpp40
-rw-r--r--test/OpenMP/target_teams_distribute_dist_schedule_messages.cpp84
-rw-r--r--test/OpenMP/target_teams_distribute_firstprivate_messages.cpp132
-rw-r--r--test/OpenMP/target_teams_distribute_if_messages.cpp150
-rw-r--r--test/OpenMP/target_teams_distribute_lastprivate_messages.cpp229
-rw-r--r--test/OpenMP/target_teams_distribute_loop_messages.cpp620
-rw-r--r--test/OpenMP/target_teams_distribute_map_messages.cpp281
-rw-r--r--test/OpenMP/target_teams_distribute_messages.cpp92
-rw-r--r--test/OpenMP/target_teams_distribute_misc_messages.c312
-rw-r--r--test/OpenMP/target_teams_distribute_nowait_messages.cpp18
-rw-r--r--test/OpenMP/target_teams_distribute_num_teams_messages.cpp85
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_ast_print.cpp170
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_collapse_messages.cpp149
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_default_messages.cpp23
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_defaultmap_messages.cpp58
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_depend_messages.cpp90
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_device_messages.cpp40
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_dist_schedule_messages.cpp84
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_firstprivate_messages.cpp131
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_if_messages.cpp109
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_is_device_ptr_ast_print.cpp318
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_is_device_ptr_messages.cpp337
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_lastprivate_messages.cpp233
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_linear_messages.cpp248
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_loop_messages.cpp624
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_map_messages.cpp281
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_messages.cpp92
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_misc_messages.c312
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_nowait_messages.cpp18
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_num_teams_messages.cpp85
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_num_threads_messages.cpp65
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_private_messages.cpp124
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_proc_bind_messages.cpp69
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_reduction_messages.cpp241
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_schedule_messages.cpp143
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_shared_messages.cpp106
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_thread_limit_messages.cpp98
-rw-r--r--test/OpenMP/target_teams_distribute_private_messages.cpp111
-rw-r--r--test/OpenMP/target_teams_distribute_reduction_messages.cpp246
-rw-r--r--test/OpenMP/target_teams_distribute_shared_messages.cpp110
-rw-r--r--test/OpenMP/target_teams_firstprivate_messages.cpp114
-rw-r--r--test/OpenMP/target_teams_if_messages.cpp91
-rw-r--r--test/OpenMP/target_teams_is_device_ptr_ast_print.cpp291
-rw-r--r--test/OpenMP/target_teams_is_device_ptr_messages.cpp268
-rw-r--r--test/OpenMP/target_teams_map_messages.cpp538
-rw-r--r--test/OpenMP/target_teams_messages.cpp65
-rw-r--r--test/OpenMP/target_teams_nowait_messages.cpp17
-rw-r--r--test/OpenMP/target_teams_num_teams_messages.cpp85
-rw-r--r--test/OpenMP/target_teams_private_messages.cpp109
-rw-r--r--test/OpenMP/target_teams_reduction_messages.cpp266
-rw-r--r--test/OpenMP/target_teams_shared_messages.cpp110
-rw-r--r--test/OpenMP/target_teams_thread_limit_messages.cpp85
-rw-r--r--test/OpenMP/target_update_ast_print.cpp10
-rw-r--r--test/OpenMP/target_update_depend_messages.cpp4
-rw-r--r--test/OpenMP/target_update_if_messages.cpp6
-rw-r--r--test/OpenMP/task_ast_print.cpp46
-rw-r--r--test/OpenMP/task_codegen.cpp1
-rw-r--r--test/OpenMP/task_depend_messages.cpp2
-rw-r--r--test/OpenMP/task_firstprivate_codegen.cpp37
-rw-r--r--test/OpenMP/task_if_codegen.cpp7
-rw-r--r--test/OpenMP/task_if_messages.cpp2
-rw-r--r--test/OpenMP/task_private_codegen.cpp1
-rw-r--r--test/OpenMP/taskgroup_codegen.cpp1
-rw-r--r--test/OpenMP/taskloop_ast_print.cpp7
-rw-r--r--test/OpenMP/taskloop_codegen.cpp1
-rw-r--r--test/OpenMP/taskloop_firstprivate_codegen.cpp1
-rw-r--r--test/OpenMP/taskloop_lastprivate_codegen.cpp1
-rw-r--r--test/OpenMP/taskloop_private_codegen.cpp1
-rw-r--r--test/OpenMP/taskloop_simd_aligned_messages.cpp3
-rw-r--r--test/OpenMP/taskloop_simd_ast_print.cpp7
-rw-r--r--test/OpenMP/taskloop_simd_codegen.cpp1
-rw-r--r--test/OpenMP/taskloop_simd_firstprivate_codegen.cpp1
-rw-r--r--test/OpenMP/taskloop_simd_lastprivate_codegen.cpp1
-rw-r--r--test/OpenMP/taskloop_simd_private_codegen.cpp1
-rw-r--r--test/OpenMP/taskwait_ast_print.cpp4
-rw-r--r--test/OpenMP/taskwait_codegen.cpp1
-rw-r--r--test/OpenMP/taskyield_ast_print.cpp4
-rw-r--r--test/OpenMP/taskyield_codegen.cpp1
-rw-r--r--test/OpenMP/teams_ast_print.cpp42
-rw-r--r--test/OpenMP/teams_distribute_ast_print.cpp179
-rw-r--r--test/OpenMP/teams_distribute_collapse_messages.cpp172
-rw-r--r--test/OpenMP/teams_distribute_default_messages.cpp30
-rw-r--r--test/OpenMP/teams_distribute_dist_schedule_messages.cpp104
-rw-r--r--test/OpenMP/teams_distribute_firstprivate_messages.cpp152
-rw-r--r--test/OpenMP/teams_distribute_lastprivate_messages.cpp272
-rw-r--r--test/OpenMP/teams_distribute_loop_messages.cpp716
-rw-r--r--test/OpenMP/teams_distribute_num_teams_messages.cpp111
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_ast_print.cpp203
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_collapse_messages.cpp172
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_default_messages.cpp30
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_dist_schedule_messages.cpp104
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_firstprivate_messages.cpp152
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_if_messages.cpp140
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_lastprivate_messages.cpp272
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_linear_messages.cpp293
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_loop_messages.cpp714
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_messages.cpp109
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_num_teams_messages.cpp111
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_private_messages.cpp146
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_proc_bind_messages.cpp85
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_reduction_messages.cpp303
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_schedule_messages.cpp172
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_shared_messages.cpp127
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_aligned_messages.cpp271
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_ast_print.cpp245
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_collapse_messages.cpp172
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_default_messages.cpp30
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_dist_schedule_messages.cpp104
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_firstprivate_messages.cpp152
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_if_messages.cpp140
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_lastprivate_messages.cpp272
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_linear_messages.cpp293
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_loop_messages.cpp716
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_messages.cpp109
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_num_teams_messages.cpp111
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_num_threads_messages.cpp86
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_private_messages.cpp146
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_proc_bind_messages.cpp85
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_reduction_messages.cpp303
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_safelen_messages.cpp155
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_shared_messages.cpp127
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_simdlen_messages.cpp155
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_thread_limit_messages.cpp111
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_thread_limit_messages.cpp111
-rw-r--r--test/OpenMP/teams_distribute_private_messages.cpp146
-rw-r--r--test/OpenMP/teams_distribute_reduction_messages.cpp309
-rw-r--r--test/OpenMP/teams_distribute_shared_messages.cpp133
-rw-r--r--test/OpenMP/teams_distribute_simd_aligned_messages.cpp271
-rw-r--r--test/OpenMP/teams_distribute_simd_ast_print.cpp239
-rw-r--r--test/OpenMP/teams_distribute_simd_collapse_messages.cpp172
-rw-r--r--test/OpenMP/teams_distribute_simd_default_messages.cpp30
-rw-r--r--test/OpenMP/teams_distribute_simd_dist_schedule_messages.cpp104
-rw-r--r--test/OpenMP/teams_distribute_simd_firstprivate_messages.cpp152
-rw-r--r--test/OpenMP/teams_distribute_simd_lastprivate_messages.cpp272
-rw-r--r--test/OpenMP/teams_distribute_simd_linear_messages.cpp293
-rw-r--r--test/OpenMP/teams_distribute_simd_loop_messages.cpp716
-rw-r--r--test/OpenMP/teams_distribute_simd_messages.cpp109
-rw-r--r--test/OpenMP/teams_distribute_simd_num_teams_messages.cpp111
-rw-r--r--test/OpenMP/teams_distribute_simd_private_messages.cpp146
-rw-r--r--test/OpenMP/teams_distribute_simd_reduction_messages.cpp303
-rw-r--r--test/OpenMP/teams_distribute_simd_safelen_messages.cpp155
-rw-r--r--test/OpenMP/teams_distribute_simd_shared_messages.cpp127
-rw-r--r--test/OpenMP/teams_distribute_simd_simdlen_messages.cpp155
-rw-r--r--test/OpenMP/teams_distribute_simd_thread_limit_messages.cpp111
-rw-r--r--test/OpenMP/teams_distribute_thread_limit_messages.cpp111
-rw-r--r--test/OpenMP/threadprivate_ast_print.cpp7
-rw-r--r--test/OpenMP/threadprivate_codegen.cpp2
-rw-r--r--test/PCH/builtin-macro.c35
-rw-r--r--test/PCH/cxx11-lambdas.mm7
-rw-r--r--test/PCH/cxx1y-default-initializer.cpp27
-rw-r--r--test/PCH/cxx1z-aligned-alloc.cpp35
-rw-r--r--test/PCH/cxx1z-decomposition.cpp32
-rw-r--r--test/PCH/cxx1z-using-declaration.cpp35
-rw-r--r--test/PCH/debug-info-pch-path.c2
-rw-r--r--test/PCH/decl-in-prototype.c27
-rw-r--r--test/PCH/dllexport-default-arg-closure.cpp26
-rw-r--r--test/PCH/no-validate-pch.cl39
-rw-r--r--test/PCH/objc_container.m2
-rw-r--r--test/PCH/ocl_types.cl6
-rw-r--r--test/PCH/pragma-cuda-force-host-device.cu27
-rw-r--r--test/Parser/MicrosoftExtensions.c9
-rw-r--r--test/Parser/MicrosoftExtensions.cpp19
-rw-r--r--test/Parser/backtrack-off-by-one.cpp21
-rw-r--r--test/Parser/colon-colon-parentheses.cpp34
-rw-r--r--test/Parser/cuda-force-host-device-templates.cu40
-rw-r--r--test/Parser/cuda-force-host-device.cu36
-rw-r--r--test/Parser/cxx-modules-import.cpp58
-rw-r--r--test/Parser/cxx-modules-interface.cppm32
-rw-r--r--test/Parser/cxx0x-decl.cpp2
-rw-r--r--test/Parser/cxx1z-constexpr-lambdas.cpp31
-rw-r--r--test/Parser/cxx1z-coroutines.cpp2
-rw-r--r--test/Parser/cxx1z-decomposition.cpp150
-rw-r--r--test/Parser/cxx1z-fold-expressions.cpp7
-rw-r--r--test/Parser/cxx1z-using-declaration.cpp35
-rw-r--r--test/Parser/gcc-__final-compatibility.cpp9
-rw-r--r--test/Parser/lambda-attr.cu42
-rw-r--r--test/Parser/ms-inline-asm.c10
-rw-r--r--test/Parser/ms-square-bracket-attributes.mm174
-rw-r--r--test/Parser/nullability.c8
-rw-r--r--test/Parser/objc-at-directive-fixit.m28
-rw-r--r--test/Parser/objc-available.m2
-rw-r--r--test/Parser/objc-property-syntax.m2
-rw-r--r--test/Parser/opencl-atomics-cl20.cl19
-rw-r--r--test/Parser/opencl-pragma.cl4
-rw-r--r--test/Preprocessor/aarch64-target-features.c2
-rw-r--r--test/Preprocessor/arm-target-features.c10
-rw-r--r--test/Preprocessor/cuda-approx-transcendentals.cu6
-rw-r--r--test/Preprocessor/cuda-macos-includes.cu13
-rw-r--r--test/Preprocessor/cuda-preprocess.cu8
-rw-r--r--test/Preprocessor/cuda-types.cu45
-rw-r--r--test/Preprocessor/dump_import.h1
-rw-r--r--test/Preprocessor/dump_import.m6
-rw-r--r--test/Preprocessor/dump_include.c11
-rw-r--r--test/Preprocessor/dump_include.h2
-rw-r--r--test/Preprocessor/header_is_main_file.c8
-rw-r--r--test/Preprocessor/init.c133
-rw-r--r--test/Preprocessor/missing-include-range-check.h8
-rw-r--r--test/Preprocessor/pragma_microsoft.c28
-rw-r--r--test/Preprocessor/predefined-arch-macros.c12
-rw-r--r--test/Preprocessor/x86_target_features.c6
-rw-r--r--test/Profile/c-generate.c4
-rw-r--r--test/Profile/c-indirect-call.c18
-rw-r--r--test/Profile/c-linkage-available_externally.c2
-rw-r--r--test/Profile/cxx-indirect-call.cpp2
-rw-r--r--test/Profile/cxx-stmt-initializers.cpp29
-rw-r--r--test/Profile/func-entry.c2
-rw-r--r--test/Profile/gcc-flag-compatibility.c13
-rw-r--r--test/Profile/profile-summary.c2
-rw-r--r--test/Rewriter/modern-write-bf-abi.mm2
-rw-r--r--test/Rewriter/objc-modern-property-bitfield.m2
-rw-r--r--test/Rewriter/property-dot-syntax.mm2
-rw-r--r--test/Rewriter/rewrite-block-literal-1.mm4
-rw-r--r--test/Rewriter/rewrite-block-pointer.mm4
-rw-r--r--test/Rewriter/rewrite-byref-in-nested-blocks.mm4
-rw-r--r--test/Rewriter/rewrite-byref-vars.mm2
-rw-r--r--test/Rewriter/rewrite-cast-ivar-modern-access.mm2
-rw-r--r--test/Rewriter/rewrite-elaborated-type.mm4
-rw-r--r--test/Rewriter/rewrite-foreach-in-block.mm4
-rw-r--r--test/Rewriter/rewrite-foreach-protocol-id.m2
-rw-r--r--test/Rewriter/rewrite-forward-class.m2
-rw-r--r--test/Rewriter/rewrite-forward-class.mm2
-rw-r--r--test/Rewriter/rewrite-ivar-use.m2
-rw-r--r--test/Rewriter/rewrite-modern-atautoreleasepool.mm2
-rw-r--r--test/Rewriter/rewrite-modern-block-ivar-call.mm2
-rw-r--r--test/Rewriter/rewrite-modern-class.mm2
-rw-r--r--test/Rewriter/rewrite-modern-default-property-synthesis.mm2
-rw-r--r--test/Rewriter/rewrite-modern-extern-c-func-decl.mm2
-rw-r--r--test/Rewriter/rewrite-modern-ivar-use.mm2
-rw-r--r--test/Rewriter/rewrite-modern-ivars-2.mm2
-rw-r--r--test/Rewriter/rewrite-modern-ivars.mm2
-rw-r--r--test/Rewriter/rewrite-modern-nested-ivar.mm2
-rw-r--r--test/Rewriter/rewrite-modern-throw.m2
-rw-r--r--test/Rewriter/rewrite-nested-blocks-1.mm4
-rw-r--r--test/Rewriter/rewrite-nested-blocks.mm4
-rw-r--r--test/Rewriter/rewrite-nested-ivar.mm4
-rw-r--r--test/Rewriter/rewrite-property-attributes.mm2
-rw-r--r--test/Rewriter/rewrite-property-set-cfstring.mm2
-rw-r--r--test/Rewriter/rewrite-protocol-property.mm2
-rw-r--r--test/Rewriter/rewrite-user-defined-accessors.mm2
-rw-r--r--test/Rewriter/rewrite-vararg.m2
-rw-r--r--test/Sema/MicrosoftExtensions.c2
-rw-r--r--test/Sema/aarch64-special-register.c28
-rw-r--r--test/Sema/address-packed-member-memops.c26
-rw-r--r--test/Sema/address-packed.c331
-rw-r--r--test/Sema/alloc-size.c25
-rw-r--r--test/Sema/arm-interrupt-attr.c3
-rw-r--r--test/Sema/arm-special-register.c24
-rw-r--r--test/Sema/asm.c10
-rw-r--r--test/Sema/atomic-ops.c19
-rw-r--r--test/Sema/attr-availability.c2
-rw-r--r--test/Sema/attr-naked.c18
-rw-r--r--test/Sema/attr-section.c4
-rw-r--r--test/Sema/attr-selectany.c8
-rw-r--r--test/Sema/attr-swiftcall.c5
-rw-r--r--test/Sema/attr-unavailable-message.c2
-rw-r--r--test/Sema/builtin-alloca-with-align.c33
-rw-r--r--test/Sema/builtin-unary-fp.c1
-rw-r--r--test/Sema/builtins-x86.c8
-rw-r--r--test/Sema/builtins-x86_64.c60
-rw-r--r--test/Sema/builtins.cl5
-rw-r--r--test/Sema/compound-literal.c8
-rw-r--r--test/Sema/constant-conversion.c32
-rw-r--r--test/Sema/decl-in-prototype.c59
-rw-r--r--test/Sema/dllimport.c4
-rw-r--r--test/Sema/ext_vector_components.c27
-rw-r--r--test/Sema/format-strings-enum.c16
-rw-r--r--test/Sema/format-strings.c48
-rw-r--r--test/Sema/generic-selection.c10
-rw-r--r--test/Sema/implicit-intel-builtin-decl.c40
-rw-r--r--test/Sema/implicit-ms-builtin-decl.c44
-rw-r--r--test/Sema/incompatible-function-pointer-types.c14
-rw-r--r--test/Sema/initialize-noreturn.c13
-rw-r--r--test/Sema/no-warn-unused-const-variables.c4
-rw-r--r--test/Sema/nullability.c119
-rw-r--r--test/Sema/overloadable.c33
-rw-r--r--test/Sema/pass-object-size.c2
-rw-r--r--test/Sema/pr30372.c12
-rw-r--r--test/Sema/shift.c11
-rw-r--r--test/Sema/transparent-union.c9
-rw-r--r--test/Sema/varargs.c20
-rw-r--r--test/Sema/vecshift.c99
-rw-r--r--test/Sema/vector-cast.c9
-rw-r--r--test/Sema/vfprintf-invalid-redecl.c2
-rw-r--r--test/Sema/vfprintf-valid-redecl.c8
-rw-r--r--test/Sema/warn-cast-align.c20
-rw-r--r--test/Sema/warn-documentation-unknown-command.cpp4
-rw-r--r--test/Sema/warn-documentation.cpp95
-rw-r--r--test/Sema/warn-main-returns-bool-literal.cpp20
-rw-r--r--test/Sema/warn-strict-prototypes.c62
-rw-r--r--test/Sema/warn-strict-prototypes.m20
-rw-r--r--test/SemaCUDA/Inputs/cuda.h7
-rw-r--r--test/SemaCUDA/add-inline-in-definition.cu52
-rw-r--r--test/SemaCUDA/amdgpu-attrs.cu110
-rw-r--r--test/SemaCUDA/amdgpu-num-gpr-attr.cu14
-rw-r--r--test/SemaCUDA/bad-attributes.cu11
-rw-r--r--test/SemaCUDA/bad-calls-on-same-line.cu40
-rw-r--r--test/SemaCUDA/call-device-fn-from-host.cu85
-rw-r--r--test/SemaCUDA/call-host-fn-from-device.cu140
-rw-r--r--test/SemaCUDA/call-overloaded-destructor.cu17
-rw-r--r--test/SemaCUDA/call-stack-for-deferred-err.cu18
-rw-r--r--test/SemaCUDA/cuda-builtin-vars.cu12
-rw-r--r--test/SemaCUDA/device-var-init.cu18
-rw-r--r--test/SemaCUDA/exceptions.cu55
-rw-r--r--test/SemaCUDA/extern-shared.cu23
-rw-r--r--test/SemaCUDA/function-overload.cu155
-rw-r--r--test/SemaCUDA/function-template-overload.cu113
-rw-r--r--test/SemaCUDA/global-initializers-host.cu32
-rw-r--r--test/SemaCUDA/gnu-inline.cu10
-rw-r--r--test/SemaCUDA/implicit-device-lambda.cu106
-rw-r--r--test/SemaCUDA/method-target.cu10
-rw-r--r--test/SemaCUDA/no-call-stack-for-immediate-errs.cu17
-rw-r--r--test/SemaCUDA/no-destructor-overload.cu33
-rw-r--r--test/SemaCUDA/overloaded-delete.cu46
-rw-r--r--test/SemaCUDA/reference-to-kernel-fn.cu29
-rw-r--r--test/SemaCUDA/trace-through-global.cu48
-rw-r--r--test/SemaCUDA/vla.cu25
-rw-r--r--test/SemaCXX/MicrosoftCompatibility.cpp27
-rw-r--r--test/SemaCXX/MicrosoftExtensions.cpp19
-rw-r--r--test/SemaCXX/PR25848.cpp16
-rw-r--r--test/SemaCXX/PR29152.cpp15
-rw-r--r--test/SemaCXX/PR8755.cpp2
-rw-r--r--test/SemaCXX/address-packed-member-memops.cpp28
-rw-r--r--test/SemaCXX/address-packed.cpp114
-rw-r--r--test/SemaCXX/aggregate-init-cxx98.cpp7
-rw-r--r--test/SemaCXX/aggregate-initialization.cpp14
-rw-r--r--test/SemaCXX/ambig-user-defined-conversions.cpp5
-rw-r--r--test/SemaCXX/attr-gnu.cpp16
-rw-r--r--test/SemaCXX/attr-no-sanitize-address.cpp3
-rw-r--r--test/SemaCXX/attr-no-sanitize.cpp2
-rw-r--r--test/SemaCXX/attr-noreturn.cpp2
-rw-r--r--test/SemaCXX/attr-require-constant-initialization.cpp282
-rw-r--r--test/SemaCXX/attr-swiftcall.cpp4
-rw-r--r--test/SemaCXX/builtin-exception-spec.cpp1
-rw-r--r--test/SemaCXX/builtins.cpp11
-rw-r--r--test/SemaCXX/compare.cpp3
-rw-r--r--test/SemaCXX/composite-pointer-type.cpp4
-rw-r--r--test/SemaCXX/compound-literal.cpp10
-rw-r--r--test/SemaCXX/conditional-expr.cpp2
-rw-r--r--test/SemaCXX/constant-expression-cxx11.cpp108
-rw-r--r--test/SemaCXX/constant-expression-cxx1y.cpp20
-rw-r--r--test/SemaCXX/constant-expression-cxx1z.cpp21
-rw-r--r--test/SemaCXX/constexpr-string.cpp201
-rw-r--r--test/SemaCXX/constexpr-strlen.cpp15
-rw-r--r--test/SemaCXX/constexpr-value-init.cpp11
-rw-r--r--test/SemaCXX/conversion-function.cpp6
-rw-r--r--test/SemaCXX/conversion.cpp2
-rw-r--r--test/SemaCXX/copy-assignment.cpp15
-rw-r--r--test/SemaCXX/copy-initialization.cpp11
-rw-r--r--test/SemaCXX/coreturn.cpp73
-rw-r--r--test/SemaCXX/coroutines.cpp155
-rw-r--r--test/SemaCXX/cxx0x-defaulted-functions.cpp53
-rw-r--r--test/SemaCXX/cxx0x-initializer-constructor.cpp5
-rw-r--r--test/SemaCXX/cxx0x-initializer-references.cpp5
-rw-r--r--test/SemaCXX/cxx0x-initializer-scalars.cpp21
-rw-r--r--test/SemaCXX/cxx11-ast-print.cpp8
-rw-r--r--test/SemaCXX/cxx11-inheriting-ctors.cpp32
-rw-r--r--test/SemaCXX/cxx1y-initializer-aggregates.cpp16
-rw-r--r--test/SemaCXX/cxx1y-variable-templates_in_class.cpp8
-rw-r--r--test/SemaCXX/cxx1y-variable-templates_top_level.cpp6
-rw-r--r--test/SemaCXX/cxx1z-constexpr-lambdas.cpp62
-rw-r--r--test/SemaCXX/cxx1z-copy-omission.cpp134
-rw-r--r--test/SemaCXX/cxx1z-decomposition.cpp68
-rw-r--r--test/SemaCXX/cxx1z-noexcept-function-type.cpp167
-rw-r--r--test/SemaCXX/cxx1z-user-defined-literals.cpp21
-rw-r--r--test/SemaCXX/cxx98-compat-flags.cpp2
-rw-r--r--test/SemaCXX/cxx98-compat-pedantic.cpp6
-rw-r--r--test/SemaCXX/cxx98-compat.cpp4
-rw-r--r--test/SemaCXX/default-arg-closures.cpp45
-rw-r--r--test/SemaCXX/deprecated.cpp16
-rw-r--r--test/SemaCXX/derived-to-base-ambig.cpp4
-rw-r--r--test/SemaCXX/designated-initializers.cpp31
-rw-r--r--test/SemaCXX/elaborated-type-specifier.cpp9
-rw-r--r--test/SemaCXX/enable_if.cpp24
-rw-r--r--test/SemaCXX/expression-traits.cpp2
-rw-r--r--test/SemaCXX/friend.cpp9
-rw-r--r--test/SemaCXX/friend2.cpp172
-rw-r--r--test/SemaCXX/function-redecl-2.cpp19
-rw-r--r--test/SemaCXX/implicit-exception-spec.cpp18
-rw-r--r--test/SemaCXX/instantiate-template-fatal-error.cpp22
-rw-r--r--test/SemaCXX/lambda-expressions.cpp48
-rw-r--r--test/SemaCXX/libstdcxx_libcxx_less_hack.cpp67
-rw-r--r--test/SemaCXX/libstdcxx_pair_swap_hack.cpp24
-rw-r--r--test/SemaCXX/member-init.cpp24
-rw-r--r--test/SemaCXX/member-pointer-ms.cpp8
-rw-r--r--test/SemaCXX/microsoft-new-delete.cpp2
-rw-r--r--test/SemaCXX/modules-ts.cppm83
-rw-r--r--test/SemaCXX/ms-uuid.cpp95
-rw-r--r--test/SemaCXX/new-delete-cxx0x.cpp48
-rw-r--r--test/SemaCXX/null_in_arithmetic_ops.cpp4
-rw-r--r--test/SemaCXX/nullability.cpp33
-rw-r--r--test/SemaCXX/nullptr.cpp46
-rw-r--r--test/SemaCXX/nullptr_in_arithmetic_ops.cpp8
-rw-r--r--test/SemaCXX/overload-call.cpp11
-rw-r--r--test/SemaCXX/pr28050.cpp11
-rw-r--r--test/SemaCXX/predefined-expr.cpp18
-rw-r--r--test/SemaCXX/reinterpret-cast.cpp2
-rw-r--r--test/SemaCXX/rval-references.cpp10
-rw-r--r--test/SemaCXX/switch.cpp30
-rw-r--r--test/SemaCXX/template-ambiguous-overload.cpp16
-rw-r--r--test/SemaCXX/type-definition-in-specifier.cpp21
-rw-r--r--test/SemaCXX/unknown-anytype.cpp12
-rw-r--r--test/SemaCXX/using-decl-templates.cpp11
-rw-r--r--test/SemaCXX/vartemplate-lambda.cpp20
-rw-r--r--test/SemaCXX/warn-c++1z-extensions.cpp8
-rw-r--r--test/SemaCXX/warn-everthing.cpp2
-rw-r--r--test/SemaCXX/warn-logical-not-compare.cpp41
-rw-r--r--test/SemaCXX/warn-max-unsigned-zero.cpp55
-rw-r--r--test/SemaCXX/warn-memset-bad-sizeof.cpp43
-rw-r--r--test/SemaCXX/warn-memsize-comparison.cpp8
-rw-r--r--test/SemaCXX/warn-missing-variable-declarations.cpp5
-rw-r--r--test/SemaCXX/warn-msvc-enum-bitfield.cpp40
-rw-r--r--test/SemaCXX/warn-range-loop-analysis.cpp2
-rw-r--r--test/SemaCXX/warn-shadow-in-lambdas.cpp139
-rw-r--r--test/SemaCXX/warn-unused-variables.cpp44
-rw-r--r--test/SemaCXX/warn-weak-vtables.cpp5
-rw-r--r--test/SemaObjC/arc.m9
-rw-r--r--test/SemaObjC/assign-rvalue-message.m5
-rw-r--r--test/SemaObjC/attr-availability.m46
-rw-r--r--test/SemaObjC/call-super-2.m15
-rw-r--r--test/SemaObjC/check-dup-objc-decls-1.m6
-rw-r--r--test/SemaObjC/class-unavail-warning.m25
-rw-r--r--test/SemaObjC/crash-on-type-args-protocols.m40
-rw-r--r--test/SemaObjC/format-strings-objc.m40
-rw-r--r--test/SemaObjC/format-strings-oslog.m65
-rw-r--r--test/SemaObjC/kindof.m10
-rw-r--r--test/SemaObjC/method-redecls-invalid-interface.m21
-rw-r--r--test/SemaObjC/nsobject-attribute.m2
-rw-r--r--test/SemaObjC/nullability.m51
-rw-r--r--test/SemaObjC/objc-array-literal.m8
-rw-r--r--test/SemaObjC/objc-dictionary-literal.m7
-rw-r--r--test/SemaObjC/objcbridge-attribute-arc.m5
-rw-r--r--test/SemaObjC/parameterized_classes_subst.m33
-rw-r--r--test/SemaObjC/property-deprecated-warning.m20
-rw-r--r--test/SemaObjC/subclassing-restricted-attr.m36
-rw-r--r--test/SemaObjC/typo-correction.m25
-rw-r--r--test/SemaObjC/unguarded-availability.m179
-rw-r--r--test/SemaObjCXX/Inputs/nullability-consistency-1.h18
-rw-r--r--test/SemaObjCXX/Inputs/nullability-consistency-2.h10
-rw-r--r--test/SemaObjCXX/Inputs/nullability-consistency-3.h2
-rw-r--r--test/SemaObjCXX/Inputs/nullability-consistency-4.h2
-rw-r--r--test/SemaObjCXX/Inputs/nullability-consistency-5.h2
-rw-r--r--test/SemaObjCXX/Inputs/nullability-consistency-6.h5
-rw-r--r--test/SemaObjCXX/Inputs/nullability-consistency-7.h4
-rw-r--r--test/SemaObjCXX/Inputs/nullability-consistency-8.h10
-rw-r--r--test/SemaObjCXX/Inputs/nullability-consistency-arrays.h141
-rw-r--r--test/SemaObjCXX/Inputs/nullability-consistency-system/nullability-consistency-system.h2
-rw-r--r--test/SemaObjCXX/Inputs/nullability-pragmas-1.h36
-rw-r--r--test/SemaObjCXX/crash.mm35
-rw-r--r--test/SemaObjCXX/null_objc_pointer.mm5
-rw-r--r--test/SemaObjCXX/nullability-consistency-arrays.mm12
-rw-r--r--test/SemaOpenCL/access-qualifier.cl9
-rw-r--r--test/SemaOpenCL/amdgpu-attrs.cl66
-rw-r--r--test/SemaOpenCL/amdgpu-num-register-attrs.cl40
-rw-r--r--test/SemaOpenCL/builtin.cl2
-rw-r--r--test/SemaOpenCL/builtins-amdgcn-error-f16.cl18
-rw-r--r--test/SemaOpenCL/builtins-amdgcn-error.cl64
-rw-r--r--test/SemaOpenCL/cl20-device-side-enqueue.cl54
-rw-r--r--test/SemaOpenCL/convergent.cl12
-rw-r--r--test/SemaOpenCL/event_t.cl2
-rw-r--r--test/SemaOpenCL/event_t_overload.cl6
-rw-r--r--test/SemaOpenCL/ext_vectors.cl11
-rw-r--r--test/SemaOpenCL/extension-begin.cl56
-rw-r--r--test/SemaOpenCL/extension-version.cl26
-rw-r--r--test/SemaOpenCL/extensions.cl44
-rw-r--r--test/SemaOpenCL/extern.cl2
-rw-r--r--test/SemaOpenCL/func.cl (renamed from test/SemaOpenCL/func_ptr.cl)7
-rw-r--r--test/SemaOpenCL/half.cl15
-rw-r--r--test/SemaOpenCL/invalid-block.cl27
-rw-r--r--test/SemaOpenCL/invalid-clk-events-cl2.0.cl3
-rw-r--r--test/SemaOpenCL/invalid-image.cl6
-rw-r--r--test/SemaOpenCL/invalid-kernel-parameters.cl5
-rw-r--r--test/SemaOpenCL/invalid-kernel.cl10
-rw-r--r--test/SemaOpenCL/invalid-pipes-cl2.0.cl29
-rw-r--r--test/SemaOpenCL/null_queue.cl12
-rw-r--r--test/SemaOpenCL/queue_t_overload.cl12
-rw-r--r--test/SemaOpenCL/sampler_t.cl64
-rw-r--r--test/SemaOpenCL/unroll-hint.cl15
-rw-r--r--test/SemaOpenCL/unsupported.cl2
-rw-r--r--test/SemaTemplate/alias-templates.cpp17
-rw-r--r--test/SemaTemplate/array-redeclaration.cpp33
-rw-r--r--test/SemaTemplate/class-template-decl.cpp6
-rw-r--r--test/SemaTemplate/class-template-spec.cpp47
-rw-r--r--test/SemaTemplate/cxx1z-decomposition.cpp33
-rw-r--r--test/SemaTemplate/cxx1z-using-declaration.cpp230
-rw-r--r--test/SemaTemplate/deduction.cpp85
-rw-r--r--test/SemaTemplate/default-expr-arguments-3.cpp55
-rw-r--r--test/SemaTemplate/dependent-type-identity.cpp9
-rw-r--r--test/SemaTemplate/instantiate-exception-spec-cxx11.cpp18
-rw-r--r--test/SemaTemplate/instantiation-default-1.cpp2
-rw-r--r--test/SemaTemplate/instantiation-depth-default.cpp17
-rw-r--r--test/SemaTemplate/ms-class-specialization-class-scope.cpp2
-rw-r--r--test/SemaTemplate/temp_arg_enum_printing.cpp6
-rw-r--r--test/SemaTemplate/temp_arg_nontype.cpp87
-rw-r--r--test/SemaTemplate/temp_arg_nontype_cxx11.cpp13
-rw-r--r--test/SemaTemplate/temp_arg_nontype_cxx1z.cpp179
-rw-r--r--test/SemaTemplate/temp_arg_template.cpp4
-rw-r--r--test/SemaTemplate/temp_arg_template_cxx1z.cpp102
-rw-r--r--test/SemaTemplate/temp_class_spec_neg.cpp6
-rw-r--r--test/SemaTemplate/temp_explicit.cpp2
-rw-r--r--test/SemaTemplate/template-id-expr.cpp2
-rw-r--r--test/Unit/lit.cfg11
-rw-r--r--test/VFS/Inputs/Bar.framework/Headers/A.h1
-rw-r--r--test/VFS/Inputs/Bar.framework/Headers/B.h1
-rw-r--r--test/VFS/Inputs/Bar.framework/Headers/C.h1
-rw-r--r--test/VFS/Inputs/Bar.framework/Modules/module.modulemap6
-rw-r--r--test/VFS/Inputs/Nonmodular/A.h1
-rw-r--r--test/VFS/Inputs/Nonmodular/Nonmodular.modulemap5
-rw-r--r--test/VFS/Inputs/Nonmodular/nonmodular-headers.yaml34
-rw-r--r--test/VFS/Inputs/Nonmodular/test.c3
-rw-r--r--test/VFS/Inputs/Nonmodular/umbrella.h5
-rw-r--r--test/VFS/Inputs/bar-headers.yaml39
-rw-r--r--test/VFS/Inputs/vfsoverlay2.yaml1
-rw-r--r--test/VFS/test_nonmodular.c11
-rw-r--r--test/VFS/umbrella-framework-import-skipnonexist.m14
-rw-r--r--test/lit.cfg18
-rw-r--r--test/lit.site.cfg.in1
-rw-r--r--tools/CMakeLists.txt2
-rw-r--r--tools/arcmt-test/arcmt-test.cpp6
-rw-r--r--tools/c-index-test/c-index-test.c54
-rw-r--r--tools/c-index-test/core_main.cpp7
-rw-r--r--tools/clang-format-vs/.gitignore12
-rw-r--r--tools/clang-format-vs/CMakeLists.txt14
-rw-r--r--tools/clang-format-vs/ClangFormat.sln4
-rw-r--r--tools/clang-format-vs/ClangFormat/ClangFormat.csproj102
-rw-r--r--tools/clang-format-vs/ClangFormat/ClangFormat.vsct18
-rw-r--r--tools/clang-format-vs/ClangFormat/ClangFormatPackage.cs92
-rw-r--r--tools/clang-format-vs/ClangFormat/PkgCmdID.cs3
-rw-r--r--tools/clang-format-vs/ClangFormat/Resources.Designer.cs2
-rw-r--r--tools/clang-format-vs/ClangFormat/packages.config22
-rw-r--r--tools/clang-format-vs/README.txt46
-rw-r--r--tools/clang-format/ClangFormat.cpp18
-rwxr-xr-xtools/clang-format/clang-format-diff.py2
-rw-r--r--tools/clang-format/clang-format.el89
-rw-r--r--tools/clang-format/clang-format.py28
-rwxr-xr-xtools/clang-format/git-clang-format159
-rw-r--r--tools/clang-fuzzer/ClangFuzzer.cpp1
-rw-r--r--tools/clang-import-test/CMakeLists.txt27
-rw-r--r--tools/clang-import-test/clang-import-test.cpp319
-rw-r--r--tools/clang-offload-bundler/CMakeLists.txt24
-rw-r--r--tools/clang-offload-bundler/ClangOffloadBundler.cpp1012
-rw-r--r--tools/diagtool/DiagTool.cpp1
-rw-r--r--tools/diagtool/TreeView.cpp1
-rw-r--r--tools/driver/CMakeLists.txt27
-rw-r--r--tools/driver/Info.plist.in2
-rw-r--r--tools/driver/cc1_main.cpp105
-rw-r--r--tools/driver/cc1as_main.cpp21
-rw-r--r--tools/driver/driver.cpp6
-rw-r--r--tools/libclang/ARCMigrate.cpp4
-rw-r--r--tools/libclang/BuildSystem.cpp4
-rw-r--r--tools/libclang/CIndex.cpp222
-rw-r--r--tools/libclang/CIndexCXX.cpp4
-rw-r--r--tools/libclang/CIndexCodeCompletion.cpp15
-rw-r--r--tools/libclang/CIndexDiagnostic.cpp10
-rw-r--r--tools/libclang/CIndexHigh.cpp5
-rw-r--r--tools/libclang/CIndexInclusionStack.cpp4
-rw-r--r--tools/libclang/CIndexUSRs.cpp4
-rw-r--r--tools/libclang/CIndexer.cpp15
-rw-r--r--tools/libclang/CIndexer.h5
-rw-r--r--tools/libclang/CLog.h2
-rw-r--r--tools/libclang/CMakeLists.txt1
-rw-r--r--tools/libclang/CXComment.cpp7
-rw-r--r--tools/libclang/CXCompilationDatabase.cpp4
-rw-r--r--tools/libclang/CXCursor.cpp35
-rw-r--r--tools/libclang/CXIndexDataConsumer.cpp20
-rw-r--r--tools/libclang/CXIndexDataConsumer.h1
-rw-r--r--tools/libclang/CXLoadedDiagnostic.cpp4
-rw-r--r--tools/libclang/CXLoadedDiagnostic.h1
-rw-r--r--tools/libclang/CXSourceLocation.cpp21
-rw-r--r--tools/libclang/CXStoredDiagnostic.cpp3
-rw-r--r--tools/libclang/CXString.cpp4
-rw-r--r--tools/libclang/CXType.cpp90
-rw-r--r--tools/libclang/CursorVisitor.h3
-rw-r--r--tools/libclang/Indexing.cpp6
-rw-r--r--tools/libclang/libclang.exports4
-rw-r--r--tools/scan-build-py/libscanbuild/analyze.py3
-rw-r--r--tools/scan-build-py/libscanbuild/clang.py191
-rw-r--r--tools/scan-build-py/libscanbuild/report.py4
-rw-r--r--tools/scan-build-py/libscanbuild/runner.py13
-rw-r--r--tools/scan-build-py/tests/unit/test_clang.py62
-rw-r--r--tools/scan-build-py/tests/unit/test_report.py13
-rw-r--r--tools/scan-build-py/tests/unit/test_runner.py14
-rwxr-xr-xtools/scan-build/bin/scan-build32
-rw-r--r--unittests/AST/ASTImporterTest.cpp37
-rw-r--r--unittests/AST/ASTTypeTraitsTest.cpp2
-rw-r--r--unittests/AST/ASTVectorTest.cpp1
-rw-r--r--unittests/AST/CommentParser.cpp1
-rw-r--r--unittests/AST/DeclPrinterTest.cpp126
-rw-r--r--unittests/AST/ExternalASTSourceTest.cpp1
-rw-r--r--unittests/AST/PostOrderASTVisitor.cpp13
-rw-r--r--unittests/AST/SourceLocationTest.cpp90
-rw-r--r--unittests/AST/StmtPrinterTest.cpp2
-rw-r--r--unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp45
-rw-r--r--unittests/ASTMatchers/ASTMatchersNodeTest.cpp7
-rw-r--r--unittests/ASTMatchers/ASTMatchersTest.h2
-rw-r--r--unittests/ASTMatchers/ASTMatchersTraversalTest.cpp170
-rw-r--r--unittests/ASTMatchers/Dynamic/ParserTest.cpp1
-rw-r--r--unittests/Analysis/CFGTest.cpp68
-rw-r--r--unittests/Basic/FileManagerTest.cpp20
-rw-r--r--unittests/Basic/VirtualFileSystemTest.cpp16
-rw-r--r--unittests/Driver/CMakeLists.txt1
-rw-r--r--unittests/Driver/DistroTest.cpp305
-rw-r--r--unittests/Driver/ToolChainTest.cpp25
-rw-r--r--unittests/Format/CMakeLists.txt1
-rw-r--r--unittests/Format/CleanupTest.cpp492
-rw-r--r--unittests/Format/FormatTest.cpp1075
-rw-r--r--unittests/Format/FormatTestJS.cpp207
-rw-r--r--unittests/Format/FormatTestObjC.cpp822
-rw-r--r--unittests/Format/SortImportsTestJS.cpp55
-rw-r--r--unittests/Format/SortIncludesTest.cpp105
-rw-r--r--unittests/Frontend/CodeGenActionTest.cpp5
-rw-r--r--unittests/Frontend/FrontendActionTest.cpp66
-rw-r--r--unittests/StaticAnalyzer/AnalyzerOptionsTest.cpp17
-rw-r--r--unittests/Tooling/CMakeLists.txt1
-rw-r--r--unittests/Tooling/CompilationDatabaseTest.cpp89
-rw-r--r--unittests/Tooling/LookupTest.cpp61
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTest.cpp22
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTestCallVisitor.cpp1
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTestDeclVisitor.cpp1
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTestExprVisitor.cpp49
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTestTypeLocVisitor.cpp1
-rw-r--r--unittests/Tooling/RefactoringTest.cpp855
-rw-r--r--unittests/Tooling/ReplacementTest.h56
-rw-r--r--unittests/Tooling/RewriterTest.cpp7
-rw-r--r--unittests/Tooling/TestVisitor.h29
-rw-r--r--unittests/Tooling/ToolingTest.cpp41
-rw-r--r--unittests/libclang/LibclangTest.cpp82
-rw-r--r--utils/TableGen/ClangASTNodesEmitter.cpp2
-rw-r--r--utils/TableGen/ClangAttrEmitter.cpp144
-rw-r--r--utils/TableGen/ClangDiagnosticsEmitter.cpp449
-rw-r--r--utils/TableGen/NeonEmitter.cpp98
-rw-r--r--utils/TableGen/TableGen.cpp10
-rw-r--r--utils/TableGen/TableGenBackends.h1
-rw-r--r--utils/analyzer/SATestBuild.py8
-rw-r--r--utils/clang-completion-mode.el249
-rw-r--r--utils/perf-training/CMakeLists.txt6
-rw-r--r--utils/perf-training/order-files.lit.cfg5
-rw-r--r--utils/perf-training/perf-helper.py3
-rw-r--r--www/analyzer/alpha_checks.html82
-rw-r--r--www/analyzer/annotations.html2
-rw-r--r--www/analyzer/checker_dev_manual.html224
-rw-r--r--www/analyzer/faq.html64
-rw-r--r--www/analyzer/index.html2
-rw-r--r--www/analyzer/latest_checker.html.incl2
-rw-r--r--www/analyzer/potential_checkers.html61
-rw-r--r--www/analyzer/release_notes.html19
-rw-r--r--www/cxx_dr_status.html1118
-rw-r--r--www/cxx_status.html169
-rw-r--r--www/get_started.html7
-rwxr-xr-xwww/make_cxx_dr_status11
-rw-r--r--www/menu.html.incl2
-rw-r--r--www/related.html2
2692 files changed, 178954 insertions, 59347 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index cfcd2212cfaf..c09b75f990e5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -124,6 +124,7 @@ Please install Python or specify the PYTHON_EXECUTABLE CMake variable.")
endif()
if(EXISTS ${LLVM_MAIN_SRC_DIR}/utils/lit/lit.py)
+ # Note: path not really used, except for checking if lit was found
set(LLVM_LIT ${LLVM_MAIN_SRC_DIR}/utils/lit/lit.py)
if(NOT LLVM_UTILS_PROVIDED)
add_subdirectory(${LLVM_MAIN_SRC_DIR}/utils/FileCheck utils/FileCheck)
@@ -140,8 +141,10 @@ Please install Python or specify the PYTHON_EXECUTABLE CMake variable.")
endif()
else()
# Seek installed Lit.
- find_program(LLVM_LIT "lit.py" ${LLVM_MAIN_SRC_DIR}/utils/lit
- DOC "Path to lit.py")
+ find_program(LLVM_LIT
+ NAMES llvm-lit lit.py lit
+ PATHS "${LLVM_MAIN_SRC_DIR}/utils/lit"
+ DOC "Path to lit.py")
endif()
if(LLVM_LIT)
@@ -177,6 +180,9 @@ if (LIBXML2_FOUND)
set(CLANG_HAVE_LIBXML 1)
endif()
+include(CheckIncludeFile)
+check_include_file(sys/resource.h CLANG_HAVE_RLIMITS)
+
set(CLANG_RESOURCE_DIR "" CACHE STRING
"Relative directory from the Clang binary to its resource files.")
@@ -192,13 +198,27 @@ 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(CLANG_DEFAULT_LINKER "" CACHE STRING
+ "Default linker to use (linker name or absolute path, empty for platform default)")
+
set(CLANG_DEFAULT_CXX_STDLIB "" CACHE STRING
- "Default C++ stdlib to use (empty for architecture default, \"libstdc++\" or \"libc++\"")
+ "Default C++ stdlib to use (\"libstdc++\" or \"libc++\", empty for platform default")
if (NOT(CLANG_DEFAULT_CXX_STDLIB STREQUAL "" OR
CLANG_DEFAULT_CXX_STDLIB STREQUAL "libstdc++" OR
CLANG_DEFAULT_CXX_STDLIB STREQUAL "libc++"))
- message(WARNING "Resetting default C++ stdlib to use architecture default")
- set(CLANG_DEFAULT_CXX_STDLIB "")
+ message(WARNING "Resetting default C++ stdlib to use platform default")
+ set(CLANG_DEFAULT_CXX_STDLIB "" CACHE STRING
+ "Default C++ stdlib to use (\"libstdc++\" or \"libc++\", empty for platform default" FORCE)
+endif()
+
+set(CLANG_DEFAULT_RTLIB "" CACHE STRING
+ "Default runtime library to use (\"libgcc\" or \"compiler-rt\", empty for platform default)")
+if (NOT(CLANG_DEFAULT_RTLIB STREQUAL "" OR
+ CLANG_DEFAULT_RTLIB STREQUAL "libgcc" OR
+ CLANG_DEFAULT_RTLIB STREQUAL "compiler-rt"))
+ message(WARNING "Resetting default rtlib to use platform default")
+ set(CLANG_DEFAULT_RTLIB "" CACHE STRING
+ "Default runtime library to use (\"libgcc\" or \"compiler-rt\", empty for platform default)" FORCE)
endif()
set(CLANG_DEFAULT_OPENMP_RUNTIME "libomp" CACHE STRING
@@ -247,22 +267,19 @@ if( NOT CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR )
endif()
endif()
-# Compute the Clang version from the LLVM version.
-string(REGEX MATCH "[0-9]+\\.[0-9]+(\\.[0-9]+)?" CLANG_VERSION
- ${PACKAGE_VERSION})
-message(STATUS "Clang version: ${CLANG_VERSION}")
-
-string(REGEX REPLACE "([0-9]+)\\.[0-9]+(\\.[0-9]+)?" "\\1" CLANG_VERSION_MAJOR
- ${CLANG_VERSION})
-string(REGEX REPLACE "[0-9]+\\.([0-9]+)(\\.[0-9]+)?" "\\1" CLANG_VERSION_MINOR
- ${CLANG_VERSION})
-if (${CLANG_VERSION} MATCHES "[0-9]+\\.[0-9]+\\.[0-9]+")
- set(CLANG_HAS_VERSION_PATCHLEVEL 1)
- string(REGEX REPLACE "[0-9]+\\.[0-9]+\\.([0-9]+)" "\\1" CLANG_VERSION_PATCHLEVEL
- ${CLANG_VERSION})
-else()
- set(CLANG_HAS_VERSION_PATCHLEVEL 0)
+# If CLANG_VERSION_* is specified, use it, if not use LLVM_VERSION_*.
+if(NOT DEFINED CLANG_VERSION_MAJOR)
+ set(CLANG_VERSION_MAJOR ${LLVM_VERSION_MAJOR})
+endif()
+if(NOT DEFINED CLANG_VERSION_MINOR)
+ set(CLANG_VERSION_MINOR ${LLVM_VERSION_MINOR})
endif()
+if(NOT DEFINED CLANG_VERSION_PATCHLEVEL)
+ set(CLANG_VERSION_PATCHLEVEL ${LLVM_VERSION_PATCH})
+endif()
+# Unlike PACKAGE_VERSION, CLANG_VERSION does not include LLVM_VERSION_SUFFIX.
+set(CLANG_VERSION "${CLANG_VERSION_MAJOR}.${CLANG_VERSION_MINOR}.${CLANG_VERSION_PATCHLEVEL}")
+message(STATUS "Clang version: ${CLANG_VERSION}")
# Configure the Version.inc file.
configure_file(
@@ -404,6 +421,29 @@ else()
endif()
add_subdirectory(examples)
+if(APPLE)
+ # this line is needed as a cleanup to ensure that any CMakeCaches with the old
+ # default value get updated to the new default.
+ if(CLANG_ORDER_FILE STREQUAL "")
+ unset(CLANG_ORDER_FILE CACHE)
+ unset(CLANG_ORDER_FILE)
+ endif()
+
+
+ set(CLANG_ORDER_FILE ${CMAKE_CURRENT_BINARY_DIR}/clang.order CACHE FILEPATH
+ "Order file to use when compiling clang in order to improve startup time (Darwin Only - requires ld64).")
+
+ if(NOT EXISTS ${CLANG_ORDER_FILE})
+ string(FIND "${CLANG_ORDER_FILE}" "${CMAKE_CURRENT_BINARY_DIR}" PATH_START)
+ if(PATH_START EQUAL 0)
+ file(WRITE ${CLANG_ORDER_FILE} "\n")
+ else()
+ message(FATAL_ERROR "Specified order file '${CLANG_ORDER_FILE}' does not exist.")
+ endif()
+ endif()
+endif()
+
+
if( CLANG_INCLUDE_TESTS )
if(EXISTS ${LLVM_MAIN_SRC_DIR}/utils/unittest/googletest/include/gtest/gtest.h)
add_subdirectory(unittests)
@@ -438,37 +478,19 @@ if( CLANG_INCLUDE_DOCS )
add_subdirectory(docs)
endif()
+add_subdirectory(cmake/modules)
-if(APPLE)
- # this line is needed as a cleanup to ensure that any CMakeCaches with the old
- # default value get updated to the new default.
- if(CLANG_ORDER_FILE STREQUAL "")
- unset(CLANG_ORDER_FILE CACHE)
- unset(CLANG_ORDER_FILE)
- endif()
-
-
- set(CLANG_ORDER_FILE ${CMAKE_CURRENT_BINARY_DIR}/clang.order CACHE FILEPATH
- "Order file to use when compiling clang in order to improve startup time (Darwin Only - requires ld64).")
-
- if(CLANG_ORDER_FILE AND NOT EXISTS ${CLANG_ORDER_FILE})
- string(FIND "${CLANG_ORDER_FILE}" "${CMAKE_CURRENT_BINARY_DIR}" PATH_START)
- if(PATH_START EQUAL 0)
- file(WRITE ${CLANG_ORDER_FILE} "\n")
- else()
- message(FATAL_ERROR "Specified order file '${CLANG_ORDER_FILE}' does not exist.")
- endif()
- endif()
+if(CLANG_STAGE)
+ message(STATUS "Setting current clang stage to: ${CLANG_STAGE}")
endif()
-add_subdirectory(cmake/modules)
-
if (CLANG_ENABLE_BOOTSTRAP)
include(ExternalProject)
+ add_custom_target(clang-bootstrap-deps DEPENDS clang)
+
if(NOT CLANG_STAGE)
set(CLANG_STAGE stage1)
- message(STATUS "Setting current clang stage to: ${CLANG_STAGE}")
endif()
string(REGEX MATCH "stage([0-9]*)" MATCHED_STAGE "${CLANG_STAGE}")
@@ -491,19 +513,28 @@ if (CLANG_ENABLE_BOOTSTRAP)
set(STAMP_DIR ${CMAKE_CURRENT_BINARY_DIR}/${NEXT_CLANG_STAGE}-stamps/)
set(BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${NEXT_CLANG_STAGE}-bins/)
- set(cmake_command ${CMAKE_COMMAND})
- # If the next stage is LTO we need to depend on LTO and possibly LLVMgold
- if(BOOTSTRAP_LLVM_ENABLE_LTO OR LLVM_ENABLE_LTO)
- set(LTO_DEP LTO)
+ # If the next stage is LTO we need to depend on LTO and possibly lld or LLVMgold
+ if(BOOTSTRAP_LLVM_ENABLE_LTO OR LLVM_ENABLE_LTO AND NOT LLVM_BUILD_INSTRUMENTED)
if(APPLE)
+ add_dependencies(clang-bootstrap-deps LTO)
# on Darwin we need to set DARWIN_LTO_LIBRARY so that -flto will work
# using the just-built compiler, and we need to override DYLD_LIBRARY_PATH
# so that the host object file tools will use the just-built libLTO.
- set(LTO_LIBRARY -DDARWIN_LTO_LIBRARY=${LLVM_SHLIB_OUTPUT_INTDIR}/libLTO.dylib)
- set(cmake_command ${CMAKE_COMMAND} -E env DYLD_LIBRARY_PATH=${LLVM_LIBRARY_OUTPUT_INTDIR} ${CMAKE_COMMAND})
+ # However if System Integrity Protection is enabled the DYLD variables
+ # will be scrubbed from the environment of any base system commands. This
+ # includes /bin/sh, which ninja uses when executing build commands. To
+ # work around the envar being filtered away we pass it in as a CMake
+ # variable, and have LLVM's CMake append the envar to the archiver calls.
+ set(LTO_LIBRARY -DDARWIN_LTO_LIBRARY=${LLVM_SHLIB_OUTPUT_INTDIR}/libLTO.dylib
+ -DDYLD_LIBRARY_PATH=${LLVM_LIBRARY_OUTPUT_INTDIR})
elseif(NOT WIN32)
- list(APPEND LTO_DEP LLVMgold llvm-ar llvm-ranlib)
+ add_dependencies(clang-bootstrap-deps llvm-ar llvm-ranlib)
+ if(BOOTSTRAP_LLVM_ENABLE_LLD)
+ add_dependencies(clang-bootstrap-deps lld)
+ elseif(LLVM_BINUTILS_INCDIR)
+ add_dependencies(clang-bootstrap-deps LLVMgold)
+ endif()
set(LTO_AR -DCMAKE_AR=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-ar)
set(LTO_RANLIB -DCMAKE_RANLIB=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-ranlib)
endif()
@@ -514,7 +545,7 @@ if (CLANG_ENABLE_BOOTSTRAP)
)
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${NEXT_CLANG_STAGE}-cleared
- DEPENDS clang ${LTO_DEP}
+ DEPENDS clang-bootstrap-deps
COMMAND ${CMAKE_COMMAND} -E remove_directory ${BINARY_DIR}
COMMAND ${CMAKE_COMMAND} -E make_directory ${BINARY_DIR}
COMMAND ${CMAKE_COMMAND} -E remove_directory ${STAMP_DIR}
@@ -526,18 +557,25 @@ if (CLANG_ENABLE_BOOTSTRAP)
set(verbose -DCMAKE_VERBOSE_MAKEFILE=On)
endif()
- set(BOOTSTRAP_DEFAULT_PASSTHROUGH
+ set(_BOOTSTRAP_DEFAULT_PASSTHROUGH
PACKAGE_VERSION
+ PACKAGE_VENDOR
LLVM_VERSION_MAJOR
LLVM_VERSION_MINOR
LLVM_VERSION_PATCH
+ CLANG_VERSION_MAJOR
+ CLANG_VERSION_MINOR
+ CLANG_VERSION_PATCHLEVEL
LLVM_VERSION_SUFFIX
LLVM_BINUTILS_INCDIR
CLANG_REPOSITORY_STRING
- CMAKE_MAKE_PROGRAM)
+ CMAKE_MAKE_PROGRAM
+ CMAKE_OSX_ARCHITECTURES)
- if(TARGET compiler-rt)
- set(RUNTIME_DEP compiler-rt)
+ # We don't need to depend on compiler-rt 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)
endif()
set(COMPILER_OPTIONS
@@ -546,18 +584,27 @@ if (CLANG_ENABLE_BOOTSTRAP)
-DCMAKE_ASM_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/clang)
if(BOOTSTRAP_LLVM_BUILD_INSTRUMENTED)
- set(PGO_DEP llvm-profdata)
+ add_dependencies(clang-bootstrap-deps llvm-profdata)
set(PGO_OPT -DLLVM_PROFDATA=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-profdata)
endif()
if(LLVM_BUILD_INSTRUMENTED)
- set(PGO_DEP generate-profdata)
+ add_dependencies(clang-bootstrap-deps generate-profdata)
set(PGO_OPT -DLLVM_PROFDATA_FILE=${CMAKE_CURRENT_BINARY_DIR}/utils/perf-training/clang.profdata)
- set(COMPILER_OPTIONS
- -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
- -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
- -DCMAKE_ASM_COMPILER=${CMAKE_ASM_COMPILER})
- set(RUNTIME_DEP) # Don't set runtime dependencies
+ # Use the current tools for LTO instead of the instrumented ones
+ list(APPEND _BOOTSTRAP_DEFAULT_PASSTHROUGH
+ CMAKE_CXX_COMPILER
+ CMAKE_C_COMPILER
+ CMAKE_ASM_COMPILER
+ CMAKE_AR
+ CMAKE_RANLIB
+ DARWIN_LTO_LIBRARY
+ DYLD_LIBRARY_PATH)
+
+ set(COMPILER_OPTIONS)
+ set(LTO_LIBRARY)
+ set(LTO_AR)
+ set(LTO_RANLIB)
endif()
# Find all variables that start with BOOTSTRAP_ and populate a variable with
@@ -577,16 +624,20 @@ if (CLANG_ENABLE_BOOTSTRAP)
endforeach()
# Populate the passthrough variables
- foreach(variableName ${CLANG_BOOTSTRAP_PASSTHROUGH} ${BOOTSTRAP_DEFAULT_PASSTHROUGH})
- if(${variableName})
- string(REPLACE ";" "\;" value ${${variableName}})
+ foreach(variableName ${CLANG_BOOTSTRAP_PASSTHROUGH} ${_BOOTSTRAP_DEFAULT_PASSTHROUGH})
+ if(DEFINED ${variableName})
+ if("${${variableName}}" STREQUAL "")
+ set(value "")
+ else()
+ string(REPLACE ";" "\;" value ${${variableName}})
+ endif()
list(APPEND PASSTHROUGH_VARIABLES
-D${variableName}=${value})
endif()
endforeach()
ExternalProject_Add(${NEXT_CLANG_STAGE}
- DEPENDS clang ${LTO_DEP} ${RUNTIME_DEP} ${PGO_DEP}
+ DEPENDS clang-bootstrap-deps
PREFIX ${NEXT_CLANG_STAGE}
SOURCE_DIR ${CMAKE_SOURCE_DIR}
STAMP_DIR ${STAMP_DIR}
@@ -601,7 +652,6 @@ if (CLANG_ENABLE_BOOTSTRAP)
-DCLANG_STAGE=${NEXT_CLANG_STAGE}
${COMPILER_OPTIONS}
${LTO_LIBRARY} ${LTO_AR} ${LTO_RANLIB} ${verbose} ${PGO_OPT}
- CMAKE_COMMAND ${cmake_command}
INSTALL_COMMAND ""
STEP_TARGETS configure build
USES_TERMINAL_CONFIGURE 1
@@ -612,7 +662,7 @@ if (CLANG_ENABLE_BOOTSTRAP)
# exclude really-install from main target
set_target_properties(${NEXT_CLANG_STAGE} PROPERTIES _EP_really-install_EXCLUDE_FROM_MAIN On)
ExternalProject_Add_Step(${NEXT_CLANG_STAGE} really-install
- COMMAND ${cmake_command} --build <BINARY_DIR> --target install
+ COMMAND ${CMAKE_COMMAND} --build <BINARY_DIR> --target install
COMMENT "Performing install step for '${NEXT_CLANG_STAGE}'"
DEPENDEES build
USES_TERMINAL 1
@@ -628,7 +678,7 @@ if (CLANG_ENABLE_BOOTSTRAP)
set_target_properties(${NEXT_CLANG_STAGE} PROPERTIES _EP_${target}_EXCLUDE_FROM_MAIN On)
ExternalProject_Add_Step(${NEXT_CLANG_STAGE} ${target}
- COMMAND ${cmake_command} --build <BINARY_DIR> --target ${target}
+ COMMAND ${CMAKE_COMMAND} --build <BINARY_DIR> --target ${target}
COMMENT "Performing ${target} for '${NEXT_CLANG_STAGE}'"
DEPENDEES configure
USES_TERMINAL 1
diff --git a/bindings/python/clang/cindex.py b/bindings/python/clang/cindex.py
index aeb34f8cb232..c22d2510c62c 100644
--- a/bindings/python/clang/cindex.py
+++ b/bindings/python/clang/cindex.py
@@ -64,6 +64,7 @@ call is efficient.
from ctypes import *
import collections
+import sys
import clang.enumerations
@@ -73,6 +74,33 @@ import clang.enumerations
# this by marshalling object arguments as void**.
c_object_p = POINTER(c_void_p)
+if sys.version_info[0] > 2:
+# Python 3 strings are unicode, translate them to/from utf8 for C-interop
+# Python 3 replaces xrange with range, we want xrange behaviour
+ xrange = range
+
+ class c_string_p(c_char_p):
+ def __init__(self, p=None):
+ if type(p) == str:
+ p = p.encode("utf8")
+ super(c_char_p, self).__init__(p)
+
+ def __str__(self):
+ return str(self.value)
+
+ @property
+ def value(self):
+ if super(c_char_p, self).value is None:
+ return None
+ return super(c_char_p, self).value.decode("utf8")
+
+ @classmethod
+ def from_param(cls, param):
+ return cls(param)
+else:
+ c_string_p = c_char_p
+
+
callbacks = {}
### Exception Classes ###
@@ -147,7 +175,7 @@ class CachedProperty(object):
class _CXString(Structure):
"""Helper for transforming CXString results."""
- _fields_ = [("spelling", c_char_p), ("free", c_int)]
+ _fields_ = [("spelling", c_string_p), ("free", c_int)]
def __del__(self):
conf.lib.clang_disposeString(self)
@@ -305,6 +333,14 @@ class Diagnostic(object):
Error = 3
Fatal = 4
+ DisplaySourceLocation = 0x01
+ DisplayColumn = 0x02
+ DisplaySourceRanges = 0x04
+ DisplayOption = 0x08
+ DisplayCategoryId = 0x10
+ DisplayCategoryName = 0x20
+ _FormatOptionsMask = 0x3f
+
def __init__(self, ptr):
self.ptr = ptr
@@ -321,7 +357,7 @@ class Diagnostic(object):
@property
def spelling(self):
- return conf.lib.clang_getDiagnosticSpelling(self)
+ return str(conf.lib.clang_getDiagnosticSpelling(self))
@property
def ranges(self):
@@ -350,8 +386,8 @@ class Diagnostic(object):
def __getitem__(self, key):
range = SourceRange()
- value = conf.lib.clang_getDiagnosticFixIt(self.diag, key,
- byref(range))
+ value = str(conf.lib.clang_getDiagnosticFixIt(self.diag, key,
+ byref(range)))
if len(value) == 0:
raise IndexError
@@ -384,12 +420,12 @@ class Diagnostic(object):
@property
def category_name(self):
"""The string name of the category for this diagnostic."""
- return conf.lib.clang_getDiagnosticCategoryText(self)
+ return str(conf.lib.clang_getDiagnosticCategoryText(self))
@property
def option(self):
"""The command-line option that enables this diagnostic."""
- return conf.lib.clang_getDiagnosticOption(self, None)
+ return str(conf.lib.clang_getDiagnosticOption(self, None))
@property
def disable_option(self):
@@ -397,12 +433,29 @@ class Diagnostic(object):
disable = _CXString()
conf.lib.clang_getDiagnosticOption(self, byref(disable))
- return conf.lib.clang_getCString(disable)
+ return str(conf.lib.clang_getCString(disable))
+
+ def format(self, options=None):
+ """
+ Format this diagnostic for display. The options argument takes
+ Diagnostic.Display* flags, which can be combined using bitwise OR. If
+ the options argument is not provided, the default display options will
+ be used.
+ """
+ if options is None:
+ options = conf.lib.clang_defaultDiagnosticDisplayOptions()
+ if options & ~Diagnostic._FormatOptionsMask:
+ raise ValueError('Invalid format options')
+ formatted = conf.lib.clang_formatDiagnostic(self, options)
+ return conf.lib.clang_getCString(formatted)
def __repr__(self):
return "<Diagnostic severity %r, location %r, spelling %r>" % (
self.severity, self.location, self.spelling)
+ def __str__(self):
+ return self.format()
+
def from_param(self):
return self.ptr
@@ -529,8 +582,8 @@ class BaseEnumeration(object):
if value >= len(self.__class__._kinds):
self.__class__._kinds += [None] * (value - len(self.__class__._kinds) + 1)
if self.__class__._kinds[value] is not None:
- raise ValueError,'{0} value {1} already loaded'.format(
- str(self.__class__), value)
+ raise ValueError('{0} value {1} already loaded'.format(
+ str(self.__class__), value))
self.value = value
self.__class__._kinds[value] = self
self.__class__._name_map = None
@@ -547,12 +600,12 @@ class BaseEnumeration(object):
for key, value in self.__class__.__dict__.items():
if isinstance(value, self.__class__):
self._name_map[value] = key
- return self._name_map[self]
+ return str(self._name_map[self])
@classmethod
def from_id(cls, id):
if id >= len(cls._kinds) or cls._kinds[id] is None:
- raise ValueError,'Unknown template argument kind %d' % id
+ raise ValueError('Unknown template argument kind %d' % id)
return cls._kinds[id]
def __repr__(self):
@@ -571,7 +624,7 @@ class CursorKind(BaseEnumeration):
@staticmethod
def get_all_kinds():
"""Return all CursorKind enumeration instances."""
- return filter(None, CursorKind._kinds)
+ return [x for x in CursorKind._kinds if x]
def is_declaration(self):
"""Test if this is a declaration kind."""
@@ -983,6 +1036,12 @@ CursorKind.OBJ_BOOL_LITERAL_EXPR = CursorKind(145)
# Represents the "self" expression in a ObjC method.
CursorKind.OBJ_SELF_EXPR = CursorKind(146)
+# OpenMP 4.0 [2.4, Array Section].
+CursorKind.OMP_ARRAY_SECTION_EXPR = CursorKind(147)
+
+# Represents an @available(...) check.
+CursorKind.OBJC_AVAILABILITY_CHECK_EXPR = CursorKind(148)
+
# A statement whose specific kind is not exposed via this interface.
#
@@ -1084,6 +1143,126 @@ CursorKind.NULL_STMT = CursorKind(230)
# Adaptor class for mixing declarations with statements and expressions.
CursorKind.DECL_STMT = CursorKind(231)
+# OpenMP parallel directive.
+CursorKind.OMP_PARALLEL_DIRECTIVE = CursorKind(232)
+
+# OpenMP SIMD directive.
+CursorKind.OMP_SIMD_DIRECTIVE = CursorKind(233)
+
+# OpenMP for directive.
+CursorKind.OMP_FOR_DIRECTIVE = CursorKind(234)
+
+# OpenMP sections directive.
+CursorKind.OMP_SECTIONS_DIRECTIVE = CursorKind(235)
+
+# OpenMP section directive.
+CursorKind.OMP_SECTION_DIRECTIVE = CursorKind(236)
+
+# OpenMP single directive.
+CursorKind.OMP_SINGLE_DIRECTIVE = CursorKind(237)
+
+# OpenMP parallel for directive.
+CursorKind.OMP_PARALLEL_FOR_DIRECTIVE = CursorKind(238)
+
+# OpenMP parallel sections directive.
+CursorKind.OMP_PARALLEL_SECTIONS_DIRECTIVE = CursorKind(239)
+
+# OpenMP task directive.
+CursorKind.OMP_TASK_DIRECTIVE = CursorKind(240)
+
+# OpenMP master directive.
+CursorKind.OMP_MASTER_DIRECTIVE = CursorKind(241)
+
+# OpenMP critical directive.
+CursorKind.OMP_CRITICAL_DIRECTIVE = CursorKind(242)
+
+# OpenMP taskyield directive.
+CursorKind.OMP_TASKYIELD_DIRECTIVE = CursorKind(243)
+
+# OpenMP barrier directive.
+CursorKind.OMP_BARRIER_DIRECTIVE = CursorKind(244)
+
+# OpenMP taskwait directive.
+CursorKind.OMP_TASKWAIT_DIRECTIVE = CursorKind(245)
+
+# OpenMP flush directive.
+CursorKind.OMP_FLUSH_DIRECTIVE = CursorKind(246)
+
+# Windows Structured Exception Handling's leave statement.
+CursorKind.SEH_LEAVE_STMT = CursorKind(247)
+
+# OpenMP ordered directive.
+CursorKind.OMP_ORDERED_DIRECTIVE = CursorKind(248)
+
+# OpenMP atomic directive.
+CursorKind.OMP_ATOMIC_DIRECTIVE = CursorKind(249)
+
+# OpenMP for SIMD directive.
+CursorKind.OMP_FOR_SIMD_DIRECTIVE = CursorKind(250)
+
+# OpenMP parallel for SIMD directive.
+CursorKind.OMP_PARALLELFORSIMD_DIRECTIVE = CursorKind(251)
+
+# OpenMP target directive.
+CursorKind.OMP_TARGET_DIRECTIVE = CursorKind(252)
+
+# OpenMP teams directive.
+CursorKind.OMP_TEAMS_DIRECTIVE = CursorKind(253)
+
+# OpenMP taskgroup directive.
+CursorKind.OMP_TASKGROUP_DIRECTIVE = CursorKind(254)
+
+# OpenMP cancellation point directive.
+CursorKind.OMP_CANCELLATION_POINT_DIRECTIVE = CursorKind(255)
+
+# OpenMP cancel directive.
+CursorKind.OMP_CANCEL_DIRECTIVE = CursorKind(256)
+
+# OpenMP target data directive.
+CursorKind.OMP_TARGET_DATA_DIRECTIVE = CursorKind(257)
+
+# OpenMP taskloop directive.
+CursorKind.OMP_TASK_LOOP_DIRECTIVE = CursorKind(258)
+
+# OpenMP taskloop simd directive.
+CursorKind.OMP_TASK_LOOP_SIMD_DIRECTIVE = CursorKind(259)
+
+# OpenMP distribute directive.
+CursorKind.OMP_DISTRIBUTE_DIRECTIVE = CursorKind(260)
+
+# OpenMP target enter data directive.
+CursorKind.OMP_TARGET_ENTER_DATA_DIRECTIVE = CursorKind(261)
+
+# OpenMP target exit data directive.
+CursorKind.OMP_TARGET_EXIT_DATA_DIRECTIVE = CursorKind(262)
+
+# OpenMP target parallel directive.
+CursorKind.OMP_TARGET_PARALLEL_DIRECTIVE = CursorKind(263)
+
+# OpenMP target parallel for directive.
+CursorKind.OMP_TARGET_PARALLELFOR_DIRECTIVE = CursorKind(264)
+
+# OpenMP target update directive.
+CursorKind.OMP_TARGET_UPDATE_DIRECTIVE = CursorKind(265)
+
+# OpenMP distribute parallel for directive.
+CursorKind.OMP_DISTRIBUTE_PARALLELFOR_DIRECTIVE = CursorKind(266)
+
+# OpenMP distribute parallel for simd directive.
+CursorKind.OMP_DISTRIBUTE_PARALLEL_FOR_SIMD_DIRECTIVE = CursorKind(267)
+
+# OpenMP distribute simd directive.
+CursorKind.OMP_DISTRIBUTE_SIMD_DIRECTIVE = CursorKind(268)
+
+# OpenMP target parallel for simd directive.
+CursorKind.OMP_TARGET_PARALLEL_FOR_SIMD_DIRECTIVE = CursorKind(269)
+
+# OpenMP target simd directive.
+CursorKind.OMP_TARGET_SIMD_DIRECTIVE = CursorKind(270)
+
+# OpenMP teams distribute directive.
+CursorKind.OMP_TEAMS_DISTRIBUTE_DIRECTIVE = CursorKind(271)
+
###
# Other Kinds
@@ -1136,6 +1315,10 @@ CursorKind.INCLUSION_DIRECTIVE = CursorKind(503)
CursorKind.MODULE_IMPORT_DECL = CursorKind(600)
# A type alias template declaration
CursorKind.TYPE_ALIAS_TEMPLATE_DECL = CursorKind(601)
+# A static_assert or _Static_assert node
+CursorKind.STATIC_ASSERT = CursorKind(602)
+# A friend declaration
+CursorKind.FRIEND_DECL = CursorKind(603)
# A code completion overload candidate.
CursorKind.OVERLOAD_CANDIDATE = CursorKind(700)
@@ -1274,9 +1457,9 @@ class Cursor(Structure):
def spelling(self):
"""Return the spelling of the entity pointed at by the cursor."""
if not hasattr(self, '_spelling'):
- self._spelling = conf.lib.clang_getCursorSpelling(self)
+ self._spelling = str(conf.lib.clang_getCursorSpelling(self))
- return self._spelling
+ return str(self._spelling)
@property
def displayname(self):
@@ -1288,7 +1471,7 @@ class Cursor(Structure):
arguments of a class template specialization.
"""
if not hasattr(self, '_displayname'):
- self._displayname = conf.lib.clang_getCursorDisplayName(self)
+ self._displayname = str(conf.lib.clang_getCursorDisplayName(self))
return self._displayname
@@ -1296,7 +1479,7 @@ class Cursor(Structure):
def mangled_name(self):
"""Return the mangled name for the entity referenced by this cursor."""
if not hasattr(self, '_mangled_name'):
- self._mangled_name = conf.lib.clang_Cursor_getMangling(self)
+ self._mangled_name = str(conf.lib.clang_Cursor_getMangling(self))
return self._mangled_name
@@ -1435,7 +1618,7 @@ class Cursor(Structure):
self._objc_type_encoding = \
conf.lib.clang_getDeclObjCTypeEncoding(self)
- return self._objc_type_encoding
+ return str(self._objc_type_encoding)
@property
def hash(self):
@@ -1482,17 +1665,23 @@ class Cursor(Structure):
@property
def brief_comment(self):
"""Returns the brief comment text associated with that Cursor"""
- return conf.lib.clang_Cursor_getBriefCommentText(self)
+ r = conf.lib.clang_Cursor_getBriefCommentText(self)
+ if not r:
+ return None
+ return str(r)
@property
def raw_comment(self):
"""Returns the raw comment text associated with that Cursor"""
- return conf.lib.clang_Cursor_getRawCommentText(self)
+ r = conf.lib.clang_Cursor_getRawCommentText(self)
+ if not r:
+ return None
+ return str(r)
def get_arguments(self):
"""Return an iterator for accessing the arguments of this cursor."""
num_args = conf.lib.clang_Cursor_getNumArguments(self)
- for i in range(0, num_args):
+ for i in xrange(0, num_args):
yield conf.lib.clang_Cursor_getArgument(self, i)
def get_num_template_arguments(self):
@@ -1622,7 +1811,7 @@ class StorageClass(object):
if value >= len(StorageClass._kinds):
StorageClass._kinds += [None] * (value - len(StorageClass._kinds) + 1)
if StorageClass._kinds[value] is not None:
- raise ValueError,'StorageClass already loaded'
+ raise ValueError('StorageClass already loaded')
self.value = value
StorageClass._kinds[value] = self
StorageClass._name_map = None
@@ -1643,7 +1832,7 @@ class StorageClass(object):
@staticmethod
def from_id(id):
if id >= len(StorageClass._kinds) or not StorageClass._kinds[id]:
- raise ValueError,'Unknown storage class %d' % id
+ raise ValueError('Unknown storage class %d' % id)
return StorageClass._kinds[id]
def __repr__(self):
@@ -1696,7 +1885,7 @@ class TypeKind(BaseEnumeration):
@property
def spelling(self):
"""Retrieve the spelling of this TypeKind."""
- return conf.lib.clang_getTypeKindSpelling(self.value)
+ return str(conf.lib.clang_getTypeKindSpelling(self.value))
def __repr__(self):
return 'TypeKind.%s' % (self.name,)
@@ -1972,7 +2161,7 @@ class Type(Structure):
"""
Retrieve the offset of a field in the record.
"""
- return conf.lib.clang_Type_getOffsetOf(self, c_char_p(fieldname))
+ return conf.lib.clang_Type_getOffsetOf(self, fieldname)
def get_ref_qualifier(self):
"""
@@ -1999,7 +2188,7 @@ class Type(Structure):
@property
def spelling(self):
"""Retrieve the spelling of this Type."""
- return conf.lib.clang_getTypeSpelling(self)
+ return str(conf.lib.clang_getTypeSpelling(self))
def __eq__(self, other):
if type(other) != type(self):
@@ -2031,7 +2220,7 @@ class ClangObject(object):
class _CXUnsavedFile(Structure):
"""Helper for passing unsaved file arguments."""
- _fields_ = [("name", c_char_p), ("contents", c_char_p), ('length', c_ulong)]
+ _fields_ = [("name", c_string_p), ("contents", c_string_p), ('length', c_ulong)]
# Functions calls through the python interface are rather slow. Fortunately,
# for most symboles, we do not need to perform a function call. Their spelling
@@ -2077,7 +2266,7 @@ class CompletionChunk:
self.__kindNumberCache = -1
def __repr__(self):
- return "{'" + self.spelling + "', " + str(self.kind) + "}"
+ return "{'" + str(self.spelling) + "', " + str(self.kind) + "}"
@CachedProperty
def spelling(self):
@@ -2386,7 +2575,9 @@ class TranslationUnit(ClangObject):
args_array = None
if len(args) > 0:
- args_array = (c_char_p * len(args))(* args)
+ args_array = (c_string_p * len(args))()
+ for i,a in enumerate(args):
+ args_array[i] = c_string_p(a)
unsaved_array = None
if len(unsaved_files) > 0:
@@ -2395,8 +2586,8 @@ class TranslationUnit(ClangObject):
if hasattr(contents, "read"):
contents = contents.read()
- unsaved_array[i].name = name
- unsaved_array[i].contents = contents
+ unsaved_array[i].name = c_string_p(name)
+ unsaved_array[i].contents = c_string_p(contents)
unsaved_array[i].length = len(contents)
ptr = conf.lib.clang_parseTranslationUnit(index, filename, args_array,
@@ -2451,7 +2642,7 @@ class TranslationUnit(ClangObject):
@property
def spelling(self):
"""Get the original translation unit source file name."""
- return conf.lib.clang_getTranslationUnitSpelling(self)
+ return str(conf.lib.clang_getTranslationUnitSpelling(self))
def get_includes(self):
"""
@@ -2574,9 +2765,9 @@ class TranslationUnit(ClangObject):
# FIXME: It would be great to support an efficient version
# of this, one day.
value = value.read()
- print value
+ print(value)
if not isinstance(value, str):
- raise TypeError,'Unexpected unsaved file contents.'
+ raise TypeError('Unexpected unsaved file contents.')
unsaved_files_array[i].name = name
unsaved_files_array[i].contents = value
unsaved_files_array[i].length = len(value)
@@ -2638,11 +2829,11 @@ class TranslationUnit(ClangObject):
# FIXME: It would be great to support an efficient version
# of this, one day.
value = value.read()
- print value
+ print(value)
if not isinstance(value, str):
- raise TypeError,'Unexpected unsaved file contents.'
- unsaved_files_array[i].name = name
- unsaved_files_array[i].contents = value
+ raise TypeError('Unexpected unsaved file contents.')
+ unsaved_files_array[i].name = c_string_p(name)
+ unsaved_files_array[i].contents = c_string_p(value)
unsaved_files_array[i].length = len(value)
ptr = conf.lib.clang_codeCompleteAt(self, path, line, column,
unsaved_files_array, len(unsaved_files), options)
@@ -2677,7 +2868,7 @@ class File(ClangObject):
@property
def name(self):
"""Return the complete file and path name of the file."""
- return conf.lib.clang_getCString(conf.lib.clang_getFileName(self))
+ return str(conf.lib.clang_getCString(conf.lib.clang_getFileName(self)))
@property
def time(self):
@@ -2685,7 +2876,7 @@ class File(ClangObject):
return conf.lib.clang_getFileTime(self)
def __str__(self):
- return self.name
+ return str(self.name)
def __repr__(self):
return "<File: %s>" % (self.name)
@@ -2754,12 +2945,12 @@ class CompileCommand(object):
@property
def directory(self):
"""Get the working directory for this CompileCommand"""
- return conf.lib.clang_CompileCommand_getDirectory(self.cmd)
+ return str(conf.lib.clang_CompileCommand_getDirectory(self.cmd))
@property
def filename(self):
"""Get the working filename for this CompileCommand"""
- return conf.lib.clang_CompileCommand_getFilename(self.cmd)
+ return str(conf.lib.clang_CompileCommand_getFilename(self.cmd))
@property
def arguments(self):
@@ -2771,7 +2962,7 @@ class CompileCommand(object):
"""
length = conf.lib.clang_CompileCommand_getNumArgs(self.cmd)
for i in xrange(length):
- yield conf.lib.clang_CompileCommand_getArg(self.cmd, i)
+ yield str(conf.lib.clang_CompileCommand_getArg(self.cmd, i))
class CompileCommands(object):
"""
@@ -2865,7 +3056,7 @@ class Token(Structure):
This is the textual representation of the token in source.
"""
- return conf.lib.clang_getTokenSpelling(self._tu, self)
+ return str(conf.lib.clang_getTokenSpelling(self._tu, self))
@property
def kind(self):
@@ -2908,7 +3099,7 @@ functionList = [
[c_object_p]),
("clang_CompilationDatabase_fromDirectory",
- [c_char_p, POINTER(c_uint)],
+ [c_string_p, POINTER(c_uint)],
c_object_p,
CompilationDatabase.from_result),
@@ -2918,7 +3109,7 @@ functionList = [
CompileCommands.from_result),
("clang_CompilationDatabase_getCompileCommands",
- [c_object_p, c_char_p],
+ [c_object_p, c_string_p],
c_object_p,
CompileCommands.from_result),
@@ -2953,7 +3144,7 @@ functionList = [
c_uint),
("clang_codeCompleteAt",
- [TranslationUnit, c_char_p, c_int, c_int, c_void_p, c_int, c_int],
+ [TranslationUnit, c_string_p, c_int, c_int, c_void_p, c_int, c_int],
POINTER(CCRStructure)),
("clang_codeCompleteGetDiagnostic",
@@ -2969,7 +3160,7 @@ functionList = [
c_object_p),
("clang_createTranslationUnit",
- [Index, c_char_p],
+ [Index, c_string_p],
c_object_p),
("clang_CXXConstructor_isConvertingConstructor",
@@ -3012,6 +3203,10 @@ functionList = [
[Cursor],
bool),
+ ("clang_defaultDiagnosticDisplayOptions",
+ [],
+ c_uint),
+
("clang_defaultSaveOptions",
[TranslationUnit],
c_uint),
@@ -3053,6 +3248,10 @@ functionList = [
[Type, Type],
bool),
+ ("clang_formatDiagnostic",
+ [Diagnostic, c_uint],
+ _CXString),
+
("clang_getArgType",
[Type, c_uint],
Type,
@@ -3111,7 +3310,7 @@ functionList = [
("clang_getCString",
[_CXString],
- c_char_p),
+ c_string_p),
("clang_getCursor",
[TranslationUnit, SourceLocation],
@@ -3258,7 +3457,7 @@ functionList = [
Type.from_result),
("clang_getFile",
- [TranslationUnit, c_char_p],
+ [TranslationUnit, c_string_p],
c_object_p),
("clang_getFileName",
@@ -3387,7 +3586,7 @@ functionList = [
("clang_getTUResourceUsageName",
[c_uint],
- c_char_p),
+ c_string_p),
("clang_getTypeDeclaration",
[Type],
@@ -3482,7 +3681,7 @@ functionList = [
bool),
("clang_parseTranslationUnit",
- [Index, c_char_p, c_void_p, c_int, c_void_p, c_int, c_int],
+ [Index, c_string_p, c_void_p, c_int, c_void_p, c_int, c_int],
c_object_p),
("clang_reparseTranslationUnit",
@@ -3490,7 +3689,7 @@ functionList = [
c_int),
("clang_saveTranslationUnit",
- [TranslationUnit, c_char_p, c_uint],
+ [TranslationUnit, c_string_p, c_uint],
c_int),
("clang_tokenize",
@@ -3562,7 +3761,7 @@ functionList = [
Type.from_result),
("clang_Type_getOffsetOf",
- [Type, c_char_p],
+ [Type, c_string_p],
c_longlong),
("clang_Type_getSizeOf",
@@ -3621,7 +3820,8 @@ def register_functions(lib, ignore_errors):
def register(item):
return register_function(lib, item, ignore_errors)
- map(register, functionList)
+ for f in functionList:
+ register(f)
class Config:
library_path = None
diff --git a/bindings/python/tests/cindex/test_cursor.py b/bindings/python/tests/cindex/test_cursor.py
index 6c8230d4283c..8103e96df4f9 100644
--- a/bindings/python/tests/cindex/test_cursor.py
+++ b/bindings/python/tests/cindex/test_cursor.py
@@ -375,7 +375,7 @@ def test_get_tokens():
foo = get_cursor(tu, 'foo')
tokens = list(foo.get_tokens())
- assert len(tokens) == 7
+ assert len(tokens) == 6
assert tokens[0].spelling == 'int'
assert tokens[1].spelling == 'foo'
diff --git a/bindings/python/tests/cindex/test_cursor_kind.py b/bindings/python/tests/cindex/test_cursor_kind.py
index 5bac289625be..4d8d88b92131 100644
--- a/bindings/python/tests/cindex/test_cursor_kind.py
+++ b/bindings/python/tests/cindex/test_cursor_kind.py
@@ -42,7 +42,8 @@ def test_kind_groups():
CursorKind.MACRO_DEFINITION,
CursorKind.MACRO_INSTANTIATION,
CursorKind.INCLUSION_DIRECTIVE,
- CursorKind.PREPROCESSING_DIRECTIVE):
+ CursorKind.PREPROCESSING_DIRECTIVE,
+ CursorKind.OVERLOAD_CANDIDATE):
assert len(group) == 0
else:
assert len(group) == 1
diff --git a/bindings/python/tests/cindex/test_tokens.py b/bindings/python/tests/cindex/test_tokens.py
index 70748429094a..688b5c1c900e 100644
--- a/bindings/python/tests/cindex/test_tokens.py
+++ b/bindings/python/tests/cindex/test_tokens.py
@@ -14,7 +14,7 @@ def test_token_to_cursor():
r = tu.get_extent('t.c', (0, 9))
tokens = list(tu.get_tokens(extent=r))
- assert len(tokens) == 5
+ assert len(tokens) == 4
assert tokens[1].spelling == 'i'
assert tokens[1].kind == TokenKind.IDENTIFIER
diff --git a/bindings/python/tests/cindex/test_translation_unit.py b/bindings/python/tests/cindex/test_translation_unit.py
index be6cd671ae0c..f959cf4aafcc 100644
--- a/bindings/python/tests/cindex/test_translation_unit.py
+++ b/bindings/python/tests/cindex/test_translation_unit.py
@@ -59,9 +59,13 @@ int SOME_DEFINE;
assert spellings[-1] == 'y'
def test_unsaved_files_2():
- import StringIO
+ try:
+ from StringIO import StringIO
+ except:
+ from io import StringIO
+
tu = TranslationUnit.from_source('fake.c', unsaved_files = [
- ('fake.c', StringIO.StringIO('int x;'))])
+ ('fake.c', StringIO('int x;'))])
spellings = [c.spelling for c in tu.cursor.get_children()]
assert spellings[-1] == 'x'
diff --git a/cmake/caches/Apple-stage1.cmake b/cmake/caches/Apple-stage1.cmake
index 814cfdf48603..32159811a884 100644
--- a/cmake/caches/Apple-stage1.cmake
+++ b/cmake/caches/Apple-stage1.cmake
@@ -27,11 +27,6 @@ set(CLANG_BOOTSTRAP_PASSTHROUGH
set(BOOTSTRAP_LLVM_ENABLE_LTO ON CACHE BOOL "")
set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "")
-# LIBCXX Settings
-set(LIBCXX_INSTALL_LIBRARY OFF CACHE BOOL "")
-set(LIBCXX_INSTALL_HEADERS ON CACHE BOOL "")
-set(LIBCXX_OVERRIDE_DARWIN_INSTALL ON CACHE BOOL "")
-
set(CLANG_BOOTSTRAP_TARGETS
generate-order-file
check-all
diff --git a/cmake/caches/Apple-stage2.cmake b/cmake/caches/Apple-stage2.cmake
index 9076868fd6d4..11c595c1530f 100644
--- a/cmake/caches/Apple-stage2.cmake
+++ b/cmake/caches/Apple-stage2.cmake
@@ -3,6 +3,7 @@
set(LLVM_TARGETS_TO_BUILD X86 ARM AArch64 CACHE STRING "")
set(PACKAGE_VENDOR Apple CACHE STRING "")
+set(CLANG_VENDOR_UTI com.apple.clang CACHE STRING "")
set(LLVM_INCLUDE_EXAMPLES OFF CACHE BOOL "")
set(LLVM_INCLUDE_DOCS OFF CACHE BOOL "")
set(LLVM_TOOL_CLANG_TOOLS_EXTRA_BUILD OFF CACHE BOOL "")
@@ -19,6 +20,8 @@ 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")
+
# Make unit tests (if present) part of the ALL target
set(LLVM_BUILD_TESTS ON CACHE BOOL "")
diff --git a/cmake/caches/DistributionExample-stage2.cmake b/cmake/caches/DistributionExample-stage2.cmake
new file mode 100644
index 000000000000..894ea6af6c39
--- /dev/null
+++ b/cmake/caches/DistributionExample-stage2.cmake
@@ -0,0 +1,30 @@
+# This file sets up a CMakeCache for the second stage of a simple distribution
+# bootstrap build.
+
+set(LLVM_TARGETS_TO_BUILD X86;ARM;AArch64 CACHE STRING "")
+
+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 "")
+
+# setup toolchain
+set(LLVM_INSTALL_TOOLCHAIN_ONLY ON CACHE BOOL "")
+set(LLVM_TOOLCHAIN_TOOLS
+ llvm-dsymutil
+ llvm-cov
+ llvm-dwarfdump
+ llvm-profdata
+ llvm-objdump
+ llvm-nm
+ llvm-size
+ CACHE STRING "")
+
+set(LLVM_DISTRIBUTION_COMPONENTS
+ clang
+ LTO
+ clang-format
+ clang-headers
+ builtins
+ runtimes
+ ${LLVM_TOOLCHAIN_TOOLS}
+ CACHE STRING "")
diff --git a/cmake/caches/DistributionExample.cmake b/cmake/caches/DistributionExample.cmake
new file mode 100644
index 000000000000..862f547c1656
--- /dev/null
+++ b/cmake/caches/DistributionExample.cmake
@@ -0,0 +1,34 @@
+# This file sets up a CMakeCache for a simple distribution bootstrap build.
+
+# Only build the native target in stage1 since it is a throwaway build.
+set(LLVM_TARGETS_TO_BUILD Native CACHE STRING "")
+
+# Optimize the stage1 compiler, but don't LTO it because that wastes time.
+set(CMAKE_BUILD_TYPE Release CACHE STRING "")
+
+# Setup vendor-specific settings.
+set(PACKAGE_VENDOR LLVM.org CACHE STRING "")
+
+# Setting up the stage2 LTO option needs to be done on the stage1 build so that
+# the proper LTO library dependencies can be connected.
+set(BOOTSTRAP_LLVM_ENABLE_LTO ON CACHE BOOL "")
+
+# Expose stage2 targets through the stage1 build configuration.
+set(CLANG_BOOTSTRAP_TARGETS
+ check-all
+ check-llvm
+ check-clang
+ llvm-config
+ test-suite
+ test-depends
+ llvm-test-depends
+ clang-test-depends
+ distribution
+ install-distribution
+ clang CACHE STRING "")
+
+# Setup the bootstrap build.
+set(CLANG_ENABLE_BOOTSTRAP ON CACHE BOOL "")
+set(CLANG_BOOTSTRAP_CMAKE_ARGS
+ -C ${CMAKE_CURRENT_LIST_DIR}/DistributionExample-stage2.cmake
+ CACHE STRING "")
diff --git a/cmake/caches/PGO-stage2-instrumented.cmake b/cmake/caches/PGO-stage2-instrumented.cmake
index fe5e83d28a2a..858c07f56265 100644
--- a/cmake/caches/PGO-stage2-instrumented.cmake
+++ b/cmake/caches/PGO-stage2-instrumented.cmake
@@ -1,9 +1,22 @@
-set(CMAKE_BUILD_TYPE RELEASE CACHE STRING "")
set(CLANG_ENABLE_BOOTSTRAP ON CACHE BOOL "")
-set(LLVM_BUILD_EXTERNAL_COMPILER_RT ON CACHE BOOL "")
+set(CLANG_BOOTSTRAP_TARGETS
+ distribution
+ install-distribution
+ install-distribution-toolchain
+ check-all
+ check-llvm
+ check-clang
+ test-suite CACHE STRING "")
-set(CLANG_BOOTSTRAP_TARGETS check-all check-llvm check-clang test-suite CACHE STRING "")
+if(PGO_BUILD_CONFIGURATION)
+ include(${PGO_BUILD_CONFIGURATION})
+ set(CLANG_BOOTSTRAP_CMAKE_ARGS
+ -C ${PGO_BUILD_CONFIGURATION}
+ CACHE STRING "")
+else()
+ include(${CMAKE_CURRENT_LIST_DIR}/PGO-stage2.cmake)
-set(CLANG_BOOTSTRAP_CMAKE_ARGS
- -C ${CMAKE_CURRENT_LIST_DIR}/PGO-stage2.cmake
- CACHE STRING "")
+ set(CLANG_BOOTSTRAP_CMAKE_ARGS
+ -C ${CMAKE_CURRENT_LIST_DIR}/PGO-stage2.cmake
+ CACHE STRING "")
+endif()
diff --git a/cmake/caches/PGO.cmake b/cmake/caches/PGO.cmake
index dc11173fae3f..7e4a001129cb 100644
--- a/cmake/caches/PGO.cmake
+++ b/cmake/caches/PGO.cmake
@@ -7,11 +7,24 @@ set(BOOTSTRAP_LLVM_BUILD_INSTRUMENTED ON CACHE BOOL "")
set(CLANG_BOOTSTRAP_TARGETS
generate-profdata
stage2
+ stage2-distribution
+ stage2-install-distribution
+ stage2-install-distribution-toolchain
stage2-check-all
stage2-check-llvm
stage2-check-clang
stage2-test-suite CACHE STRING "")
+if(PGO_INSTRUMENT_LTO)
+ set(BOOTSTRAP_LLVM_ENABLE_LTO ${PGO_INSTRUMENT_LTO} CACHE BOOL "")
+ set(BOOTSTRAP_BOOTSTRAP_LLVM_ENABLE_LTO ${PGO_INSTRUMENT_LTO} CACHE BOOL "")
+endif()
+
+if(PGO_BUILD_CONFIGURATION)
+ set(EXTRA_ARGS -DPGO_BUILD_CONFIGURATION=${PGO_BUILD_CONFIGURATION})
+endif()
+
set(CLANG_BOOTSTRAP_CMAKE_ARGS
+ ${EXTRA_ARGS}
-C ${CMAKE_CURRENT_LIST_DIR}/PGO-stage2-instrumented.cmake
CACHE STRING "")
diff --git a/cmake/modules/AddClang.cmake b/cmake/modules/AddClang.cmake
index 6e063a706bf2..e657059744a4 100644
--- a/cmake/modules/AddClang.cmake
+++ b/cmake/modules/AddClang.cmake
@@ -89,9 +89,16 @@ macro(add_clang_library name)
target_link_libraries(${name} INTERFACE ${LLVM_COMMON_LIBS})
if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY OR ${name} STREQUAL "libclang")
+
+ if(${name} IN_LIST LLVM_DISTRIBUTION_COMPONENTS OR
+ NOT LLVM_DISTRIBUTION_COMPONENTS)
+ set(export_to_clangtargets EXPORT ClangTargets)
+ set_property(GLOBAL PROPERTY CLANG_HAS_EXPORTS True)
+ endif()
+
install(TARGETS ${name}
COMPONENT ${name}
- EXPORT ClangTargets
+ ${export_to_clangtargets}
LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX}
ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX}
RUNTIME DESTINATION bin)
@@ -128,7 +135,14 @@ macro(add_clang_tool name)
add_clang_executable(${name} ${ARGN})
if (CLANG_BUILD_TOOLS)
+ if(${name} IN_LIST LLVM_DISTRIBUTION_COMPONENTS OR
+ NOT LLVM_DISTRIBUTION_COMPONENTS)
+ set(export_to_clangtargets EXPORT ClangTargets)
+ set_property(GLOBAL PROPERTY CLANG_HAS_EXPORTS True)
+ endif()
+
install(TARGETS ${name}
+ ${export_to_clangtargets}
RUNTIME DESTINATION bin
COMPONENT ${name})
@@ -139,6 +153,7 @@ macro(add_clang_tool name)
-DCMAKE_INSTALL_COMPONENT=${name}
-P "${CMAKE_BINARY_DIR}/cmake_install.cmake")
endif()
+ set_property(GLOBAL APPEND PROPERTY CLANG_EXPORTS ${name})
endif()
endmacro()
diff --git a/cmake/modules/CMakeLists.txt b/cmake/modules/CMakeLists.txt
index 3cc808a46b95..b784c0d215ea 100644
--- a/cmake/modules/CMakeLists.txt
+++ b/cmake/modules/CMakeLists.txt
@@ -39,7 +39,10 @@ set(CLANG_CONFIG_CMAKE_DIR)
set(CLANG_CONFIG_EXPORTS_FILE)
if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY)
- install(EXPORT ClangTargets DESTINATION ${CLANG_INSTALL_PACKAGE_DIR})
+ get_property(clang_has_exports GLOBAL PROPERTY CLANG_HAS_EXPORTS)
+ if(clang_has_exports)
+ install(EXPORT ClangTargets DESTINATION ${CLANG_INSTALL_PACKAGE_DIR})
+ endif()
install(FILES
${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/ClangConfig.cmake
diff --git a/docs/AddressSanitizer.rst b/docs/AddressSanitizer.rst
index a42a1ff62377..ed28ad4de6ed 100644
--- a/docs/AddressSanitizer.rst
+++ b/docs/AddressSanitizer.rst
@@ -14,7 +14,8 @@ following types of bugs:
* Out-of-bounds accesses to heap, stack and globals
* Use-after-free
-* Use-after-return (to some extent)
+* Use-after-return (runtime flag `ASAN_OPTIONS=detect_stack_use_after_return=1`)
+* Use-after-scope (clang flag `-fsanitize-address-use-after-scope`)
* Double-free, invalid free
* Memory leaks (experimental)
@@ -48,16 +49,16 @@ you may need to disable inlining (just use ``-O1``) and tail call elimination
}
# Compile and link
- % clang -O1 -g -fsanitize=address -fno-omit-frame-pointer example_UseAfterFree.cc
+ % clang++ -O1 -g -fsanitize=address -fno-omit-frame-pointer example_UseAfterFree.cc
or:
.. code-block:: console
# Compile
- % clang -O1 -g -fsanitize=address -fno-omit-frame-pointer -c example_UseAfterFree.cc
+ % clang++ -O1 -g -fsanitize=address -fno-omit-frame-pointer -c example_UseAfterFree.cc
# Link
- % clang -g -fsanitize=address example_UseAfterFree.o
+ % clang++ -g -fsanitize=address example_UseAfterFree.o
If a bug is detected, the program will print an error message to stderr and
exit with a non-zero exit code. AddressSanitizer exits on the first detected error.
diff --git a/docs/AttributeReference.rst b/docs/AttributeReference.rst
index 054d706fb28e..a763ddeaeb10 100644
--- a/docs/AttributeReference.rst
+++ b/docs/AttributeReference.rst
@@ -1,2736 +1,13 @@
..
-------------------------------------------------------------------
NOTE: This file is automatically generated by running clang-tblgen
- -gen-attr-docs. Do not edit this file by hand!!
+ -gen-attr-docs. Do not edit this file by hand!! The contents for
+ this file are automatically generated by a server-side process.
+
+ Please do not commit this file. The file exists for local testing
+ purposes only.
-------------------------------------------------------------------
===================
Attributes in Clang
-===================
-.. contents::
- :local:
-
-Introduction
-============
-
-This page lists the attributes currently supported by Clang.
-
-Function Attributes
-===================
-
-
-interrupt
----------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","","","", ""
-
-Clang supports the GNU style ``__attribute__((interrupt("TYPE")))`` attribute on
-ARM targets. This attribute may be attached to a function definition and
-instructs the backend to generate appropriate function entry/exit code so that
-it can be used directly as an interrupt service routine.
-
-The parameter passed to the interrupt attribute is optional, but if
-provided it must be a string literal with one of the following values: "IRQ",
-"FIQ", "SWI", "ABORT", "UNDEF".
-
-The semantics are as follows:
-
-- If the function is AAPCS, Clang instructs the backend to realign the stack to
- 8 bytes on entry. This is a general requirement of the AAPCS at public
- interfaces, but may not hold when an exception is taken. Doing this allows
- other AAPCS functions to be called.
-- If the CPU is M-class this is all that needs to be done since the architecture
- itself is designed in such a way that functions obeying the normal AAPCS ABI
- constraints are valid exception handlers.
-- If the CPU is not M-class, the prologue and epilogue are modified to save all
- non-banked registers that are used, so that upon return the user-mode state
- will not be corrupted. Note that to avoid unnecessary overhead, only
- general-purpose (integer) registers are saved in this way. If VFP operations
- are needed, that state must be saved manually.
-
- Specifically, interrupt kinds other than "FIQ" will save all core registers
- except "lr" and "sp". "FIQ" interrupts will save r0-r7.
-- If the CPU is not M-class, the return instruction is changed to one of the
- canonical sequences permitted by the architecture for exception return. Where
- possible the function itself will make the necessary "lr" adjustments so that
- the "preferred return address" is selected.
-
- Unfortunately the compiler is unable to make this guarantee for an "UNDEF"
- handler, where the offset from "lr" to the preferred return address depends on
- the execution state of the code which generated the exception. In this case
- a sequence equivalent to "movs pc, lr" will be used.
-
-
-abi_tag (gnu::abi_tag)
-----------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","X","","", ""
-
-The ``abi_tag`` attribute can be applied to a function, variable, class or
-inline namespace declaration to modify the mangled name of the entity. It gives
-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
-the old manged name and the new code will use the new mangled name with tags.
-
-
-acquire_capability (acquire_shared_capability, clang::acquire_capability, clang::acquire_shared_capability)
------------------------------------------------------------------------------------------------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","X","","", ""
-
-Marks a function as acquiring a capability.
-
-
-interrupt
----------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","","","", ""
-
-Clang supports the GNU style ``__attribute__((interrupt))`` attribute on
-x86/x86-64 targets.The compiler generates function entry and exit sequences
-suitable for use in an interrupt handler when this attribute is present.
-The 'IRET' instruction, instead of the 'RET' instruction, is used to return
-from interrupt or exception handlers. All registers, except for the EFLAGS
-register which is restored by the 'IRET' instruction, are preserved by the
-compiler.
-
-Any interruptible-without-stack-switch code must be compiled with
--mno-red-zone since interrupt handlers can and will, because of the
-hardware design, touch the red zone.
-
-1. interrupt handler must be declared with a mandatory pointer argument:
-
- .. code-block:: c
-
- struct interrupt_frame
- {
- uword_t ip;
- uword_t cs;
- uword_t flags;
- uword_t sp;
- uword_t ss;
- };
-
- __attribute__ ((interrupt))
- void f (struct interrupt_frame *frame) {
- ...
- }
-
-2. exception handler:
-
- The exception handler is very similar to the interrupt handler with
- a different mandatory function signature:
-
- .. code-block:: c
-
- __attribute__ ((interrupt))
- void f (struct interrupt_frame *frame, uword_t error_code) {
- ...
- }
-
- and compiler pops 'ERROR_CODE' off stack before the 'IRET' instruction.
-
- The exception handler should only be used for exceptions which push an
- error code and all other exceptions must use the interrupt handler.
- The system will crash if the wrong handler is used.
-
-
-assert_capability (assert_shared_capability, clang::assert_capability, clang::assert_shared_capability)
--------------------------------------------------------------------------------------------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","X","","", ""
-
-Marks a function that dynamically tests whether a capability is held, and halts
-the program if it is not held.
-
-
-assume_aligned (gnu::assume_aligned)
-------------------------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","X","","", ""
-
-Use ``__attribute__((assume_aligned(<alignment>[,<offset>]))`` on a function
-declaration to specify that the return value of the function (which must be a
-pointer type) has the specified offset, in bytes, from an address with the
-specified alignment. The offset is taken to be zero if omitted.
-
-.. code-block:: c++
-
- // The returned pointer value has 32-byte alignment.
- void *a() __attribute__((assume_aligned (32)));
-
- // The returned pointer value is 4 bytes greater than an address having
- // 32-byte alignment.
- void *b() __attribute__((assume_aligned (32, 4)));
-
-Note that this attribute provides information to the compiler regarding a
-condition that the code already ensures is true. It does not cause the compiler
-to enforce the provided alignment assumption.
-
-
-availability
-------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","","","", ""
-
-The ``availability`` attribute can be placed on declarations to describe the
-lifecycle of that declaration relative to operating system versions. Consider
-the function declaration for a hypothetical function ``f``:
-
-.. code-block:: c++
-
- void f(void) __attribute__((availability(macos,introduced=10.4,deprecated=10.6,obsoleted=10.7)));
-
-The availability attribute states that ``f`` was introduced in Mac OS X 10.4,
-deprecated in Mac OS X 10.6, and obsoleted in Mac OS X 10.7. This information
-is used by Clang to determine when it is safe to use ``f``: for example, if
-Clang is instructed to compile code for Mac OS X 10.5, a call to ``f()``
-succeeds. If Clang is instructed to compile code for Mac OS X 10.6, the call
-succeeds but Clang emits a warning specifying that the function is deprecated.
-Finally, if Clang is instructed to compile code for Mac OS X 10.7, the call
-fails because ``f()`` is no longer available.
-
-The availability attribute is a comma-separated list starting with the
-platform name and then including clauses specifying important milestones in the
-declaration's lifetime (in any order) along with additional information. Those
-clauses can be:
-
-introduced=\ *version*
- The first version in which this declaration was introduced.
-
-deprecated=\ *version*
- The first version in which this declaration was deprecated, meaning that
- users should migrate away from this API.
-
-obsoleted=\ *version*
- The first version in which this declaration was obsoleted, meaning that it
- was removed completely and can no longer be used.
-
-unavailable
- This declaration is never available on this platform.
-
-message=\ *string-literal*
- Additional message text that Clang will provide when emitting a warning or
- error about use of a deprecated or obsoleted declaration. Useful to direct
- users to replacement APIs.
-
-replacement=\ *string-literal*
- Additional message text that Clang will use to provide Fix-It when emitting
- a warning about use of a deprecated declaration. The Fix-It will replace
- the deprecated declaration with the new declaration specified.
-
-Multiple availability attributes can be placed on a declaration, which may
-correspond to different platforms. Only the availability attribute with the
-platform corresponding to the target platform will be used; any others will be
-ignored. If no availability attribute specifies availability for the current
-target platform, the availability attributes are ignored. Supported platforms
-are:
-
-``ios``
- Apple's iOS operating system. The minimum deployment target is specified by
- the ``-mios-version-min=*version*`` or ``-miphoneos-version-min=*version*``
- command-line arguments.
-
-``macos``
- Apple's Mac OS X operating system. The minimum deployment target is
- specified by the ``-mmacosx-version-min=*version*`` command-line argument.
- ``macosx`` is supported for backward-compatibility reasons, but it is
- deprecated.
-
-``tvos``
- Apple's tvOS operating system. The minimum deployment target is specified by
- the ``-mtvos-version-min=*version*`` command-line argument.
-
-``watchos``
- Apple's watchOS operating system. The minimum deployment target is specified by
- the ``-mwatchos-version-min=*version*`` command-line argument.
-
-A declaration can typically be used even when deploying back to a platform
-version prior to when the declaration was introduced. When this happens, the
-declaration is `weakly linked
-<https://developer.apple.com/library/mac/#documentation/MacOSX/Conceptual/BPFrameworks/Concepts/WeakLinking.html>`_,
-as if the ``weak_import`` attribute were added to the declaration. A
-weakly-linked declaration may or may not be present a run-time, and a program
-can determine whether the declaration is present by checking whether the
-address of that declaration is non-NULL.
-
-The flag ``strict`` disallows using API when deploying back to a
-platform version prior to when the declaration was introduced. An
-attempt to use such API before its introduction causes a hard error.
-Weakly-linking is almost always a better API choice, since it allows
-users to query availability at runtime.
-
-If there are multiple declarations of the same entity, the availability
-attributes must either match on a per-platform basis or later
-declarations must not have availability attributes for that
-platform. For example:
-
-.. code-block:: c
-
- void g(void) __attribute__((availability(macos,introduced=10.4)));
- void g(void) __attribute__((availability(macos,introduced=10.4))); // okay, matches
- void g(void) __attribute__((availability(ios,introduced=4.0))); // okay, adds a new platform
- void g(void); // okay, inherits both macos and ios availability from above.
- void g(void) __attribute__((availability(macos,introduced=10.5))); // error: mismatch
-
-When one method overrides another, the overriding method can be more widely available than the overridden method, e.g.,:
-
-.. code-block:: objc
-
- @interface A
- - (id)method __attribute__((availability(macos,introduced=10.4)));
- - (id)method2 __attribute__((availability(macos,introduced=10.4)));
- @end
-
- @interface B : A
- - (id)method __attribute__((availability(macos,introduced=10.3))); // okay: method moved into base class later
- - (id)method __attribute__((availability(macos,introduced=10.5))); // error: this method was available via the base class in 10.4
- @end
-
-
-_Noreturn
----------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "","","","X", ""
-
-A function declared as ``_Noreturn`` shall not return to its caller. The
-compiler will generate a diagnostic for a function declared as ``_Noreturn``
-that appears to be capable of returning to its caller.
-
-
-noreturn
---------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "","X","","", ""
-
-A function declared as ``[[noreturn]]`` shall not return to its caller. The
-compiler will generate a diagnostic for a function declared as ``[[noreturn]]``
-that appears to be capable of returning to its caller.
-
-
-carries_dependency
-------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","X","","", ""
-
-The ``carries_dependency`` attribute specifies dependency propagation into and
-out of functions.
-
-When specified on a function or Objective-C method, the ``carries_dependency``
-attribute means that the return value carries a dependency out of the function,
-so that the implementation need not constrain ordering upon return from that
-function. Implementations of the function and its caller may choose to preserve
-dependencies instead of emitting memory ordering instructions such as fences.
-
-Note, this attribute does not change the meaning of the program, but may result
-in generation of more efficient code.
-
-
-deprecated (gnu::deprecated)
-----------------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","X","X","", ""
-
-The ``deprecated`` attribute can be applied to a function, a variable, or a
-type. This is useful when identifying functions, variables, or types that are
-expected to be removed in a future version of a program.
-
-Consider the function declaration for a hypothetical function ``f``:
-
-.. code-block:: c++
-
- void f(void) __attribute__((deprecated("message", "replacement")));
-
-When spelled as `__attribute__((deprecated))`, the deprecated attribute can have
-two optional string arguments. The first one is the message to display when
-emitting the warning; the second one enables the compiler to provide a Fix-It
-to replace the deprecated name with a new name. Otherwise, when spelled as
-`[[gnu::deprecated]] or [[deprecated]]`, the attribute can have one optional
-string argument which is the message to display when emitting the warning.
-
-
-disable_tail_calls (clang::disable_tail_calls)
-----------------------------------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","X","","", ""
-
-The ``disable_tail_calls`` attribute instructs the backend to not perform tail call optimization inside the marked function.
-
-For example:
-
- .. code-block:: c
-
- int callee(int);
-
- int foo(int a) __attribute__((disable_tail_calls)) {
- return callee(a); // This call is not tail-call optimized.
- }
-
-Marking virtual functions as ``disable_tail_calls`` is legal.
-
- .. code-block:: c++
-
- int callee(int);
-
- class Base {
- public:
- [[clang::disable_tail_calls]] virtual int foo1() {
- return callee(); // This call is not tail-call optimized.
- }
- };
-
- class Derived1 : public Base {
- public:
- int foo1() override {
- return callee(); // This call is tail-call optimized.
- }
- };
-
-
-enable_if
----------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","","","", ""
-
-.. Note:: Some features of this attribute are experimental. The meaning of
- multiple enable_if attributes on a single declaration is subject to change in
- a future version of clang. Also, the ABI is not standardized and the name
- mangling may change in future versions. To avoid that, use asm labels.
-
-The ``enable_if`` attribute can be placed on function declarations to control
-which overload is selected based on the values of the function's arguments.
-When combined with the ``overloadable`` attribute, this feature is also
-available in C.
-
-.. code-block:: c++
-
- int isdigit(int c);
- int isdigit(int c) __attribute__((enable_if(c <= -1 || c > 255, "chosen when 'c' is out of range"))) __attribute__((unavailable("'c' must have the value of an unsigned char or EOF")));
-
- void foo(char c) {
- isdigit(c);
- isdigit(10);
- isdigit(-10); // results in a compile-time error.
- }
-
-The enable_if attribute takes two arguments, the first is an expression written
-in terms of the function parameters, the second is a string explaining why this
-overload candidate could not be selected to be displayed in diagnostics. The
-expression is part of the function signature for the purposes of determining
-whether it is a redeclaration (following the rules used when determining
-whether a C++ template specialization is ODR-equivalent), but is not part of
-the type.
-
-The enable_if expression is evaluated as if it were the body of a
-bool-returning constexpr function declared with the arguments of the function
-it is being applied to, then called with the parameters at the call site. If the
-result is false or could not be determined through constant expression
-evaluation, then this overload will not be chosen and the provided string may
-be used in a diagnostic if the compile fails as a result.
-
-Because the enable_if expression is an unevaluated context, there are no global
-state changes, nor the ability to pass information from the enable_if
-expression to the function body. For example, suppose we want calls to
-strnlen(strbuf, maxlen) to resolve to strnlen_chk(strbuf, maxlen, size of
-strbuf) only if the size of strbuf can be determined:
-
-.. code-block:: c++
-
- __attribute__((always_inline))
- static inline size_t strnlen(const char *s, size_t maxlen)
- __attribute__((overloadable))
- __attribute__((enable_if(__builtin_object_size(s, 0) != -1))),
- "chosen when the buffer size is known but 'maxlen' is not")))
- {
- return strnlen_chk(s, maxlen, __builtin_object_size(s, 0));
- }
-
-Multiple enable_if attributes may be applied to a single declaration. In this
-case, the enable_if expressions are evaluated from left to right in the
-following manner. First, the candidates whose enable_if expressions evaluate to
-false or cannot be evaluated are discarded. If the remaining candidates do not
-share ODR-equivalent enable_if expressions, the overload resolution is
-ambiguous. Otherwise, enable_if overload resolution continues with the next
-enable_if attribute on the candidates that have not been discarded and have
-remaining enable_if attributes. In this way, we pick the most specific
-overload out of a number of viable overloads using enable_if.
-
-.. code-block:: c++
-
- void f() __attribute__((enable_if(true, ""))); // #1
- void f() __attribute__((enable_if(true, ""))) __attribute__((enable_if(true, ""))); // #2
-
- void g(int i, int j) __attribute__((enable_if(i, ""))); // #1
- void g(int i, int j) __attribute__((enable_if(j, ""))) __attribute__((enable_if(true))); // #2
-
-In this example, a call to f() is always resolved to #2, as the first enable_if
-expression is ODR-equivalent for both declarations, but #1 does not have another
-enable_if expression to continue evaluating, so the next round of evaluation has
-only a single candidate. In a call to g(1, 1), the call is ambiguous even though
-#2 has more enable_if attributes, because the first enable_if expressions are
-not ODR-equivalent.
-
-Query for this feature with ``__has_attribute(enable_if)``.
-
-Note that functions with one or more ``enable_if`` attributes may not have
-their address taken, unless all of the conditions specified by said
-``enable_if`` are constants that evaluate to ``true``. For example:
-
-.. code-block:: c
-
- const int TrueConstant = 1;
- const int FalseConstant = 0;
- int f(int a) __attribute__((enable_if(a > 0, "")));
- int g(int a) __attribute__((enable_if(a == 0 || a != 0, "")));
- int h(int a) __attribute__((enable_if(1, "")));
- int i(int a) __attribute__((enable_if(TrueConstant, "")));
- int j(int a) __attribute__((enable_if(FalseConstant, "")));
-
- void fn() {
- int (*ptr)(int);
- ptr = &f; // error: 'a > 0' is not always true
- ptr = &g; // error: 'a == 0 || a != 0' is not a truthy constant
- ptr = &h; // OK: 1 is a truthy constant
- ptr = &i; // OK: 'TrueConstant' is a truthy constant
- ptr = &j; // error: 'FalseConstant' is a constant, but not truthy
- }
-
-Because ``enable_if`` evaluation happens during overload resolution,
-``enable_if`` may give unintuitive results when used with templates, depending
-on when overloads are resolved. In the example below, clang will emit a
-diagnostic about no viable overloads for ``foo`` in ``bar``, but not in ``baz``:
-
-.. code-block:: c++
-
- double foo(int i) __attribute__((enable_if(i > 0, "")));
- void *foo(int i) __attribute__((enable_if(i <= 0, "")));
- template <int I>
- auto bar() { return foo(I); }
-
- template <typename T>
- auto baz() { return foo(T::number); }
-
- struct WithNumber { constexpr static int number = 1; };
- void callThem() {
- bar<sizeof(WithNumber)>();
- baz<WithNumber>();
- }
-
-This is because, in ``bar``, ``foo`` is resolved prior to template
-instantiation, so the value for ``I`` isn't known (thus, both ``enable_if``
-conditions for ``foo`` fail). However, in ``baz``, ``foo`` is resolved during
-template instantiation, so the value for ``T::number`` is known.
-
-
-flatten (gnu::flatten)
-----------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","X","","", ""
-
-The ``flatten`` attribute causes calls within the attributed function to
-be inlined unless it is impossible to do so, for example if the body of the
-callee is unavailable or if the callee has the ``noinline`` attribute.
-
-
-format (gnu::format)
---------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","X","","", ""
-
-Clang supports the ``format`` attribute, which indicates that the function
-accepts a ``printf`` or ``scanf``-like format string and corresponding
-arguments or a ``va_list`` that contains these arguments.
-
-Please see `GCC documentation about format attribute
-<http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html>`_ to find details
-about attribute syntax.
-
-Clang implements two kinds of checks with this attribute.
-
-#. Clang checks that the function with the ``format`` attribute is called with
- a format string that uses format specifiers that are allowed, and that
- arguments match the format string. This is the ``-Wformat`` warning, it is
- on by default.
-
-#. Clang checks that the format string argument is a literal string. This is
- the ``-Wformat-nonliteral`` warning, it is off by default.
-
- Clang implements this mostly the same way as GCC, but there is a difference
- for functions that accept a ``va_list`` argument (for example, ``vprintf``).
- GCC does not emit ``-Wformat-nonliteral`` warning for calls to such
- functions. Clang does not warn if the format string comes from a function
- parameter, where the function is annotated with a compatible attribute,
- otherwise it warns. For example:
-
- .. code-block:: c
-
- __attribute__((__format__ (__scanf__, 1, 3)))
- void foo(const char* s, char *buf, ...) {
- va_list ap;
- va_start(ap, buf);
-
- vprintf(s, ap); // warning: format string is not a string literal
- }
-
- In this case we warn because ``s`` contains a format string for a
- ``scanf``-like function, but it is passed to a ``printf``-like function.
-
- If the attribute is removed, clang still warns, because the format string is
- not a string literal.
-
- Another example:
-
- .. code-block:: c
-
- __attribute__((__format__ (__printf__, 1, 3)))
- void foo(const char* s, char *buf, ...) {
- va_list ap;
- va_start(ap, buf);
-
- vprintf(s, ap); // warning
- }
-
- In this case Clang does not warn because the format string ``s`` and
- the corresponding arguments are annotated. If the arguments are
- incorrect, the caller of ``foo`` will receive a warning.
-
-
-ifunc (gnu::ifunc)
-------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","X","","", ""
-
-``__attribute__((ifunc("resolver")))`` is used to mark that the address of a declaration should be resolved at runtime by calling a resolver function.
-
-The symbol name of the resolver function is given in quotes. A function with this name (after mangling) must be defined in the current translation unit; it may be ``static``. The resolver function should take no arguments and return a pointer.
-
-The ``ifunc`` attribute may only be used on a function declaration. A function declaration with an ``ifunc`` attribute is considered to be a definition of the declared entity. The entity must not have weak linkage; for example, in C++, it cannot be applied to a declaration if a definition at that location would be considered inline.
-
-Not all targets support this attribute. ELF targets support this attribute when using binutils v2.20.1 or higher and glibc v2.11.1 or higher. Non-ELF targets currently do not support this attribute.
-
-
-internal_linkage (clang::internal_linkage)
-------------------------------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","X","","", ""
-
-The ``internal_linkage`` attribute changes the linkage type of the declaration to internal.
-This is similar to C-style ``static``, but can be used on classes and class methods. When applied to a class definition,
-this attribute affects all methods and static data members of that class.
-This can be used to contain the ABI of a C++ library by excluding unwanted class methods from the export tables.
-
-
-interrupt
----------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","","","", ""
-
-Clang supports the GNU style ``__attribute__((interrupt("ARGUMENT")))`` attribute on
-MIPS 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.
-
-By default, the compiler will produce a function prologue and epilogue suitable for
-an interrupt service routine that handles an External Interrupt Controller (eic)
-generated interrupt. This behaviour can be explicitly requested with the "eic"
-argument.
-
-Otherwise, for use with vectored interrupt mode, the argument passed should be
-of the form "vector=LEVEL" where LEVEL is one of the following values:
-"sw0", "sw1", "hw0", "hw1", "hw2", "hw3", "hw4", "hw5". The compiler will
-then set the interrupt mask to the corresponding level which will mask all
-interrupts up to and including the argument.
-
-The semantics are as follows:
-
-- The prologue is modified so that the Exception Program Counter (EPC) and
- Status coprocessor registers are saved to the stack. The interrupt mask is
- set so that the function can only be interrupted by a higher priority
- interrupt. The epilogue will restore the previous values of EPC and Status.
-
-- The prologue and epilogue are modified to save and restore all non-kernel
- registers as necessary.
-
-- The FPU is disabled in the prologue, as the floating pointer registers are not
- spilled to the stack.
-
-- The function return sequence is changed to use an exception return instruction.
-
-- The parameter sets the interrupt mask for the function corresponding to the
- interrupt level specified. If no mask is specified the interrupt mask
- defaults to "eic".
-
-
-noalias
--------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "","","X","", ""
-
-The ``noalias`` attribute indicates that the only memory accesses inside
-function are loads and stores from objects pointed to by its pointer-typed
-arguments, with arbitrary offsets.
-
-
-noduplicate (clang::noduplicate)
---------------------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","X","","", ""
-
-The ``noduplicate`` attribute can be placed on function declarations to control
-whether function calls to this function can be duplicated or not as a result of
-optimizations. This is required for the implementation of functions with
-certain special requirements, like the OpenCL "barrier" function, that might
-need to be run concurrently by all the threads that are executing in lockstep
-on the hardware. For example this attribute applied on the function
-"nodupfunc" in the code below avoids that:
-
-.. code-block:: c
-
- void nodupfunc() __attribute__((noduplicate));
- // Setting it as a C++11 attribute is also valid
- // void nodupfunc() [[clang::noduplicate]];
- void foo();
- void bar();
-
- nodupfunc();
- if (a > n) {
- foo();
- } else {
- bar();
- }
-
-gets possibly modified by some optimizations into code similar to this:
-
-.. code-block:: c
-
- if (a > n) {
- nodupfunc();
- foo();
- } else {
- nodupfunc();
- bar();
- }
-
-where the call to "nodupfunc" is duplicated and sunk into the two branches
-of the condition.
-
-
-no_sanitize (clang::no_sanitize)
---------------------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","X","","", ""
-
-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.
-
-See :ref:`Controlling Code Generation <controlling-code-generation>` for a
-full list of supported sanitizer flags.
-
-
-no_sanitize_address (no_address_safety_analysis, gnu::no_address_safety_analysis, gnu::no_sanitize_address)
------------------------------------------------------------------------------------------------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","X","","", ""
-
-.. _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.
-
-
-no_sanitize_thread
-------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","X","","", ""
-
-.. _langext-thread_sanitizer:
-
-Use ``__attribute__((no_sanitize_thread))`` on a function declaration to
-specify that checks for data races on plain (non-atomic) memory accesses should
-not be inserted by ThreadSanitizer. The function is still instrumented by the
-tool to avoid false positives and provide meaningful stack traces.
-
-
-no_sanitize_memory
-------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","X","","", ""
-
-.. _langext-memory_sanitizer:
-
-Use ``__attribute__((no_sanitize_memory))`` on a function declaration to
-specify that checks for uninitialized memory should not be inserted
-(e.g. by MemorySanitizer). The function may still be instrumented by the tool
-to avoid false positives in other places.
-
-
-no_split_stack (gnu::no_split_stack)
-------------------------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","X","","", ""
-
-The ``no_split_stack`` attribute disables the emission of the split stack
-preamble for a particular function. It has no effect if ``-fsplit-stack``
-is not specified.
-
-
-not_tail_called (clang::not_tail_called)
-----------------------------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","X","","", ""
-
-The ``not_tail_called`` attribute prevents tail-call optimization on statically bound calls. It has no effect on indirect calls. Virtual functions, objective-c methods, and functions marked as ``always_inline`` cannot be marked as ``not_tail_called``.
-
-For example, it prevents tail-call optimization in the following case:
-
- .. code-block:: c
-
- int __attribute__((not_tail_called)) foo1(int);
-
- int foo2(int a) {
- return foo1(a); // No tail-call optimization on direct calls.
- }
-
-However, it doesn't prevent tail-call optimization in this case:
-
- .. code-block:: c
-
- int __attribute__((not_tail_called)) foo1(int);
-
- int foo2(int a) {
- int (*fn)(int) = &foo1;
-
- // not_tail_called has no effect on an indirect call even if the call can be
- // resolved at compile time.
- return (*fn)(a);
- }
-
-Marking virtual functions as ``not_tail_called`` is an error:
-
- .. code-block:: c++
-
- class Base {
- public:
- // not_tail_called on a virtual function is an error.
- [[clang::not_tail_called]] virtual int foo1();
-
- virtual int foo2();
-
- // Non-virtual functions can be marked ``not_tail_called``.
- [[clang::not_tail_called]] int foo3();
- };
-
- class Derived1 : public Base {
- public:
- int foo1() override;
-
- // not_tail_called on a virtual function is an error.
- [[clang::not_tail_called]] int foo2() override;
- };
-
-
-#pragma omp declare simd
-------------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "","","","", "X"
-
-The `declare simd` construct can be applied to a function to enable the creation
-of one or more versions that can process multiple arguments using SIMD
-instructions from a single invocation in a SIMD loop. The `declare simd`
-directive is a declarative directive. There may be multiple `declare simd`
-directives for a function. The use of a `declare simd` construct on a function
-enables the creation of SIMD versions of the associated function that can be
-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
-
- #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
-
- simdlen(length)
- linear(argument-list[:constant-linear-step])
- aligned(argument-list[:alignment])
- uniform(argument-list)
- inbranch
- notinbranch
-
-
-#pragma omp declare target
---------------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "","","","", "X"
-
-The `declare target` directive specifies that variables and functions are mapped
-to a device for OpenMP offload mechanism.
-
-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
-
-
-objc_boxable
-------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","","","", ""
-
-Structs and unions marked with the ``objc_boxable`` attribute can be used
-with the Objective-C boxed expression syntax, ``@(...)``.
-
-**Usage**: ``__attribute__((objc_boxable))``. This attribute
-can only be placed on a declaration of a trivially-copyable struct or union:
-
-.. code-block:: objc
-
- struct __attribute__((objc_boxable)) some_struct {
- int i;
- };
- union __attribute__((objc_boxable)) some_union {
- int i;
- float f;
- };
- typedef struct __attribute__((objc_boxable)) _some_struct some_struct;
-
- // ...
-
- some_struct ss;
- NSValue *boxed = @(ss);
-
-
-objc_method_family
-------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","","","", ""
-
-Many methods in Objective-C have conventional meanings determined by their
-selectors. It is sometimes useful to be able to mark a method as having a
-particular conventional meaning despite not having the right selector, or as
-not having the conventional meaning that its selector would suggest. For these
-use cases, we provide an attribute to specifically describe the "method family"
-that a method belongs to.
-
-**Usage**: ``__attribute__((objc_method_family(X)))``, where ``X`` is one of
-``none``, ``alloc``, ``copy``, ``init``, ``mutableCopy``, or ``new``. This
-attribute can only be placed at the end of a method declaration:
-
-.. code-block:: objc
-
- - (NSString *)initMyStringValue __attribute__((objc_method_family(none)));
-
-Users who do not wish to change the conventional meaning of a method, and who
-merely want to document its non-standard retain and release semantics, should
-use the retaining behavior attributes (``ns_returns_retained``,
-``ns_returns_not_retained``, etc).
-
-Query for this feature with ``__has_attribute(objc_method_family)``.
-
-
-objc_requires_super
--------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","","","", ""
-
-Some Objective-C classes allow a subclass to override a particular method in a
-parent class but expect that the overriding method also calls the overridden
-method in the parent class. For these cases, we provide an attribute to
-designate that a method requires a "call to ``super``" in the overriding
-method in the subclass.
-
-**Usage**: ``__attribute__((objc_requires_super))``. This attribute can only
-be placed at the end of a method declaration:
-
-.. code-block:: objc
-
- - (void)foo __attribute__((objc_requires_super));
-
-This attribute can only be applied the method declarations within a class, and
-not a protocol. Currently this attribute does not enforce any placement of
-where the call occurs in the overriding method (such as in the case of
-``-dealloc`` where the call must appear at the end). It checks only that it
-exists.
-
-Note that on both OS X and iOS that the Foundation framework provides a
-convenience macro ``NS_REQUIRES_SUPER`` that provides syntactic sugar for this
-attribute:
-
-.. code-block:: objc
-
- - (void)foo NS_REQUIRES_SUPER;
-
-This macro is conditionally defined depending on the compiler's support for
-this attribute. If the compiler does not support the attribute the macro
-expands to nothing.
-
-Operationally, when a method has this annotation the compiler will warn if the
-implementation of an override in a subclass does not call super. For example:
-
-.. code-block:: objc
-
- warning: method possibly missing a [super AnnotMeth] call
- - (void) AnnotMeth{};
- ^
-
-
-objc_runtime_name
------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","","","", ""
-
-By default, the Objective-C interface or protocol identifier is used
-in the metadata name for that object. The `objc_runtime_name`
-attribute allows annotated interfaces or protocols to use the
-specified string argument in the object's metadata name instead of the
-default name.
-
-**Usage**: ``__attribute__((objc_runtime_name("MyLocalName")))``. This attribute
-can only be placed before an @protocol or @interface declaration:
-
-.. code-block:: objc
-
- __attribute__((objc_runtime_name("MyLocalName")))
- @interface Message
- @end
-
-
-objc_runtime_visible
---------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","","","", ""
-
-This attribute specifies that the Objective-C class to which it applies is visible to the Objective-C runtime but not to the linker. Classes annotated with this attribute cannot be subclassed and cannot have categories defined for them.
-
-
-optnone (clang::optnone)
-------------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","X","","", ""
-
-The ``optnone`` attribute suppresses essentially all optimizations
-on a function or method, regardless of the optimization level applied to
-the compilation unit as a whole. This is particularly useful when you
-need to debug a particular function, but it is infeasible to build the
-entire application without optimization. Avoiding optimization on the
-specified function can improve the quality of the debugging information
-for that function.
-
-This attribute is incompatible with the ``always_inline`` and ``minsize``
-attributes.
-
-
-overloadable
-------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","","","", ""
-
-Clang provides support for C++ function overloading in C. Function overloading
-in C is introduced using the ``overloadable`` attribute. For example, one
-might provide several overloaded versions of a ``tgsin`` function that invokes
-the appropriate standard function computing the sine of a value with ``float``,
-``double``, or ``long double`` precision:
-
-.. code-block:: c
-
- #include <math.h>
- float __attribute__((overloadable)) tgsin(float x) { return sinf(x); }
- double __attribute__((overloadable)) tgsin(double x) { return sin(x); }
- long double __attribute__((overloadable)) tgsin(long double x) { return sinl(x); }
-
-Given these declarations, one can call ``tgsin`` with a ``float`` value to
-receive a ``float`` result, with a ``double`` to receive a ``double`` result,
-etc. Function overloading in C follows the rules of C++ function overloading
-to pick the best overload given the call arguments, with a few C-specific
-semantics:
-
-* Conversion from ``float`` or ``double`` to ``long double`` is ranked as a
- floating-point promotion (per C99) rather than as a floating-point conversion
- (as in C++).
-
-* A conversion from a pointer of type ``T*`` to a pointer of type ``U*`` is
- considered a pointer conversion (with conversion rank) if ``T`` and ``U`` are
- compatible types.
-
-* A conversion from type ``T`` to a value of type ``U`` is permitted if ``T``
- and ``U`` are compatible types. This conversion is given "conversion" rank.
-
-The declaration of ``overloadable`` functions is restricted to function
-declarations and definitions. Most importantly, if any function with a given
-name is given the ``overloadable`` attribute, then all function declarations
-and definitions with that name (and in that scope) must have the
-``overloadable`` attribute. This rule even applies to redeclarations of
-functions whose original declaration had the ``overloadable`` attribute, e.g.,
-
-.. code-block:: c
-
- int f(int) __attribute__((overloadable));
- float f(float); // error: declaration of "f" must have the "overloadable" attribute
-
- int g(int) __attribute__((overloadable));
- int g(int) { } // error: redeclaration of "g" must also have the "overloadable" attribute
-
-Functions marked ``overloadable`` must have prototypes. Therefore, the
-following code is ill-formed:
-
-.. code-block:: c
-
- int h() __attribute__((overloadable)); // error: h does not have a prototype
-
-However, ``overloadable`` functions are allowed to use a ellipsis even if there
-are no named parameters (as is permitted in C++). This feature is particularly
-useful when combined with the ``unavailable`` attribute:
-
-.. code-block:: c++
-
- void honeypot(...) __attribute__((overloadable, unavailable)); // calling me is an error
-
-Functions declared with the ``overloadable`` attribute have their names mangled
-according to the same rules as C++ function names. For example, the three
-``tgsin`` functions in our motivating example get the mangled names
-``_Z5tgsinf``, ``_Z5tgsind``, and ``_Z5tgsine``, respectively. There are two
-caveats to this use of name mangling:
-
-* Future versions of Clang may change the name mangling of functions overloaded
- in C, so you should not depend on an specific mangling. To be completely
- safe, we strongly urge the use of ``static inline`` with ``overloadable``
- functions.
-
-* The ``overloadable`` attribute has almost no meaning when used in C++,
- because names will already be mangled and functions are already overloadable.
- However, when an ``overloadable`` function occurs within an ``extern "C"``
- linkage specification, it's name *will* be mangled in the same way as it
- would in C.
-
-Query for this feature with ``__has_extension(attribute_overloadable)``.
-
-
-release_capability (release_shared_capability, clang::release_capability, clang::release_shared_capability)
------------------------------------------------------------------------------------------------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","X","","", ""
-
-Marks a function as releasing a capability.
-
-
-kernel
-------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","","","", ""
-
-``__attribute__((kernel))`` is used to mark a ``kernel`` function in
-RenderScript.
-
-In RenderScript, ``kernel`` functions are used to express data-parallel
-computations. The RenderScript runtime efficiently parallelizes ``kernel``
-functions to run on computational resources such as multi-core CPUs and GPUs.
-See the RenderScript_ documentation for more information.
-
-.. _RenderScript: https://developer.android.com/guide/topics/renderscript/compute.html
-
-
-target (gnu::target)
---------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","X","","", ""
-
-Clang supports the GNU style ``__attribute__((target("OPTIONS")))`` attribute.
-This attribute may be attached to a function definition and instructs
-the backend to use different code generation options than were passed on the
-command line.
-
-The current set of options correspond to the existing "subtarget features" for
-the target with or without a "-mno-" in front corresponding to the absence
-of the feature, as well as ``arch="CPU"`` which will change the default "CPU"
-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.
-
-
-try_acquire_capability (try_acquire_shared_capability, clang::try_acquire_capability, clang::try_acquire_shared_capability)
----------------------------------------------------------------------------------------------------------------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","X","","", ""
-
-Marks a function that attempts to acquire a capability. This function may fail to
-actually acquire the capability; they accept a Boolean value determining
-whether acquiring the capability means success (true), or failing to acquire
-the capability means success (false).
-
-
-nodiscard, warn_unused_result, clang::warn_unused_result, gnu::warn_unused_result
----------------------------------------------------------------------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","X","","", ""
-
-Clang supports the ability to diagnose when the results of a function call
-expression are discarded under suspicious circumstances. A diagnostic is
-generated when a function or its return type is marked with ``[[nodiscard]]``
-(or ``__attribute__((warn_unused_result))``) and the function call appears as a
-potentially-evaluated discarded-value expression that is not explicitly cast to
-`void`.
-
-.. code-block: c++
- struct [[nodiscard]] error_info { /*...*/ };
- error_info enable_missile_safety_mode();
-
- void launch_missiles();
- void test_missiles() {
- enable_missile_safety_mode(); // diagnoses
- launch_missiles();
- }
- error_info &foo();
- void f() { foo(); } // Does not diagnose, error_info is a reference.
-
-
-xray_always_instrument (clang::xray_always_instrument), xray_never_instrument (clang::xray_never_instrument)
-------------------------------------------------------------------------------------------------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","X","","", ""
-
-``__attribute__((xray_always_instrument))`` or ``[[clang::xray_always_instrument]]`` is used to mark member functions (in C++), methods (in Objective C), and free functions (in C, C++, and Objective C) to be instrumented with XRay. This will cause the function to always have space at the beginning and exit points to allow for runtime patching.
-
-Conversely, ``__attribute__((xray_never_instrument))`` or ``[[clang::xray_never_instrument]]`` will inhibit the insertion of these instrumentation points.
-
-If a function has neither of these attributes, they become subject to the XRay heuristics used to determine whether a function should be instrumented or otherwise.
-
-
-Variable Attributes
-===================
-
-
-dllexport (gnu::dllexport)
---------------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","X","X","", ""
-
-The ``__declspec(dllexport)`` attribute declares a variable, function, or
-Objective-C interface to be exported from the module. It is available under the
-``-fdeclspec`` flag for compatibility with various compilers. The primary use
-is for COFF object files which explicitly specify what interfaces are available
-for external use. See the dllexport_ documentation on MSDN for more
-information.
-
-.. _dllexport: https://msdn.microsoft.com/en-us/library/3y1sfaz2.aspx
-
-
-dllimport (gnu::dllimport)
---------------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","X","X","", ""
-
-The ``__declspec(dllimport)`` attribute declares a variable, function, or
-Objective-C interface to be imported from an external module. It is available
-under the ``-fdeclspec`` flag for compatibility with various compilers. The
-primary use is for COFF object files which explicitly specify what interfaces
-are imported from external modules. See the dllimport_ documentation on MSDN
-for more information.
-
-.. _dllimport: https://msdn.microsoft.com/en-us/library/3y1sfaz2.aspx
-
-
-init_seg
---------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "","","","", "X"
-
-The attribute applied by ``pragma init_seg()`` controls the section into
-which global initialization function pointers are emitted. It is only
-available with ``-fms-extensions``. Typically, this function pointer is
-emitted into ``.CRT$XCU`` on Windows. The user can change the order of
-initialization by using a different section name with the same
-``.CRT$XC`` prefix and a suffix that sorts lexicographically before or
-after the standard ``.CRT$XCU`` sections. See the init_seg_
-documentation on MSDN for more information.
-
-.. _init_seg: http://msdn.microsoft.com/en-us/library/7977wcck(v=vs.110).aspx
-
-
-nodebug (gnu::nodebug)
-----------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","X","","", ""
-
-The ``nodebug`` attribute allows you to suppress debugging information for a
-function or method, or for a variable that is not a parameter or a non-static
-data member.
-
-
-nosvm
------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","","","", ""
-
-OpenCL 2.0 supports the optional ``__attribute__((nosvm))`` qualifier for
-pointer variable. It informs the compiler that the pointer does not refer
-to a shared virtual memory region. See OpenCL v2.0 s6.7.2 for details.
-
-Since it is not widely used and has been removed from OpenCL 2.1, it is ignored
-by Clang.
-
-
-pass_object_size
-----------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","","","", ""
-
-.. Note:: The mangling of functions with parameters that are annotated with
- ``pass_object_size`` is subject to change. You can get around this by
- using ``__asm__("foo")`` to explicitly name your functions, thus preserving
- your ABI; also, non-overloadable C functions with ``pass_object_size`` are
- not mangled.
-
-The ``pass_object_size(Type)`` attribute can be placed on function parameters to
-instruct clang to call ``__builtin_object_size(param, Type)`` at each callsite
-of said function, and implicitly pass the result of this call in as an invisible
-argument of type ``size_t`` directly after the parameter annotated with
-``pass_object_size``. Clang will also replace any calls to
-``__builtin_object_size(param, Type)`` in the function by said implicit
-parameter.
-
-Example usage:
-
-.. code-block:: c
-
- int bzero1(char *const p __attribute__((pass_object_size(0))))
- __attribute__((noinline)) {
- int i = 0;
- for (/**/; i < (int)__builtin_object_size(p, 0); ++i) {
- p[i] = 0;
- }
- return i;
- }
-
- int main() {
- char chars[100];
- int n = bzero1(&chars[0]);
- assert(n == sizeof(chars));
- return 0;
- }
-
-If successfully evaluating ``__builtin_object_size(param, Type)`` at the
-callsite is not possible, then the "failed" value is passed in. So, using the
-definition of ``bzero1`` from above, the following code would exit cleanly:
-
-.. code-block:: c
-
- int main2(int argc, char *argv[]) {
- int n = bzero1(argv);
- assert(n == -1);
- return 0;
- }
-
-``pass_object_size`` plays a part in overload resolution. If two overload
-candidates are otherwise equally good, then the overload with one or more
-parameters with ``pass_object_size`` is preferred. This implies that the choice
-between two identical overloads both with ``pass_object_size`` on one or more
-parameters will always be ambiguous; for this reason, having two such overloads
-is illegal. For example:
-
-.. code-block:: c++
-
- #define PS(N) __attribute__((pass_object_size(N)))
- // OK
- void Foo(char *a, char *b); // Overload A
- // OK -- overload A has no parameters with pass_object_size.
- void Foo(char *a PS(0), char *b PS(0)); // Overload B
- // Error -- Same signature (sans pass_object_size) as overload B, and both
- // overloads have one or more parameters with the pass_object_size attribute.
- void Foo(void *a PS(0), void *b);
-
- // OK
- void Bar(void *a PS(0)); // Overload C
- // OK
- void Bar(char *c PS(1)); // Overload D
-
- void main() {
- char known[10], *unknown;
- Foo(unknown, unknown); // Calls overload B
- Foo(known, unknown); // Calls overload B
- Foo(unknown, known); // Calls overload B
- Foo(known, known); // Calls overload B
-
- Bar(known); // Calls overload D
- Bar(unknown); // Calls overload D
- }
-
-Currently, ``pass_object_size`` is a bit restricted in terms of its usage:
-
-* Only one use of ``pass_object_size`` is allowed per parameter.
-
-* It is an error to take the address of a function with ``pass_object_size`` on
- any of its parameters. If you wish to do this, you can create an overload
- without ``pass_object_size`` on any parameters.
-
-* It is an error to apply the ``pass_object_size`` attribute to parameters that
- are not pointers. Additionally, any parameter that ``pass_object_size`` is
- applied to must be marked ``const`` at its function's definition.
-
-
-section (gnu::section, __declspec(allocate))
---------------------------------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","X","X","", ""
-
-The ``section`` attribute allows you to specify a specific section a
-global variable or function should be in after translation.
-
-
-swiftcall (gnu::swiftcall)
---------------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","X","","", ""
-
-The ``swiftcall`` attribute indicates that a function should be called
-using the Swift calling convention for a function or function pointer.
-
-The lowering for the Swift calling convention, as described by the Swift
-ABI documentation, occurs in multiple phases. The first, "high-level"
-phase breaks down the formal parameters and results into innately direct
-and indirect components, adds implicit paraameters for the generic
-signature, and assigns the context and error ABI treatments to parameters
-where applicable. The second phase breaks down the direct parameters
-and results from the first phase and assigns them to registers or the
-stack. The ``swiftcall`` convention only handles this second phase of
-lowering; the C function type must accurately reflect the results
-of the first phase, as follows:
-
-- Results classified as indirect by high-level lowering should be
- represented as parameters with the ``swift_indirect_result`` attribute.
-
-- Results classified as direct by high-level lowering should be represented
- as follows:
-
- - First, remove any empty direct results.
-
- - If there are no direct results, the C result type should be ``void``.
-
- - If there is one direct result, the C result type should be a type with
- the exact layout of that result type.
-
- - If there are a multiple direct results, the C result type should be
- a struct type with the exact layout of a tuple of those results.
-
-- Parameters classified as indirect by high-level lowering should be
- represented as parameters of pointer type.
-
-- Parameters classified as direct by high-level lowering should be
- omitted if they are empty types; otherwise, they should be represented
- as a parameter type with a layout exactly matching the layout of the
- Swift parameter type.
-
-- The context parameter, if present, should be represented as a trailing
- parameter with the ``swift_context`` attribute.
-
-- The error result parameter, if present, should be represented as a
- trailing parameter (always following a context parameter) with the
- ``swift_error_result`` attribute.
-
-``swiftcall`` does not support variadic arguments or unprototyped functions.
-
-The parameter ABI treatment attributes are aspects of the function type.
-A function type which which applies an ABI treatment attribute to a
-parameter is a different type from an otherwise-identical function type
-that does not. A single parameter may not have multiple ABI treatment
-attributes.
-
-Support for this feature is target-dependent, although it should be
-supported on every target that Swift supports. Query for this support
-with ``__has_attribute(swiftcall)``. This implies support for the
-``swift_context``, ``swift_error_result``, and ``swift_indirect_result``
-attributes.
-
-
-swift_context (gnu::swift_context)
-----------------------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","X","","", ""
-
-The ``swift_context`` attribute marks a parameter of a ``swiftcall``
-function as having the special context-parameter ABI treatment.
-
-This treatment generally passes the context value in a special register
-which is normally callee-preserved.
-
-A ``swift_context`` parameter must either be the last parameter or must be
-followed by a ``swift_error_result`` parameter (which itself must always be
-the last parameter).
-
-A context parameter must have pointer or reference type.
-
-
-swift_error_result (gnu::swift_error_result)
---------------------------------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","X","","", ""
-
-The ``swift_error_result`` attribute marks a parameter of a ``swiftcall``
-function as having the special error-result ABI treatment.
-
-This treatment generally passes the underlying error value in and out of
-the function through a special register which is normally callee-preserved.
-This is modeled in C by pretending that the register is addressable memory:
-
-- The caller appears to pass the address of a variable of pointer type.
- The current value of this variable is copied into the register before
- the call; if the call returns normally, the value is copied back into the
- variable.
-
-- The callee appears to receive the address of a variable. This address
- is actually a hidden location in its own stack, initialized with the
- value of the register upon entry. When the function returns normally,
- the value in that hidden location is written back to the register.
-
-A ``swift_error_result`` parameter must be the last parameter, and it must be
-preceded by a ``swift_context`` parameter.
-
-A ``swift_error_result`` parameter must have type ``T**`` or ``T*&`` for some
-type T. Note that no qualifiers are permitted on the intermediate level.
-
-It is undefined behavior if the caller does not pass a pointer or
-reference to a valid object.
-
-The standard convention is that the error value itself (that is, the
-value stored in the apparent argument) will be null upon function entry,
-but this is not enforced by the ABI.
-
-
-swift_indirect_result (gnu::swift_indirect_result)
---------------------------------------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","X","","", ""
-
-The ``swift_indirect_result`` attribute marks a parameter of a ``swiftcall``
-function as having the special indirect-result ABI treatmenet.
-
-This treatment gives the parameter the target's normal indirect-result
-ABI treatment, which may involve passing it differently from an ordinary
-parameter. However, only the first indirect result will receive this
-treatment. Furthermore, low-level lowering may decide that a direct result
-must be returned indirectly; if so, this will take priority over the
-``swift_indirect_result`` parameters.
-
-A ``swift_indirect_result`` parameter must either be the first parameter or
-follow another ``swift_indirect_result`` parameter.
-
-A ``swift_indirect_result`` parameter must have type ``T*`` or ``T&`` for
-some object type ``T``. If ``T`` is a complete type at the point of
-definition of a function, it is undefined behavior if the argument
-value does not point to storage of adequate size and alignment for a
-value of type ``T``.
-
-Making indirect results explicit in the signature allows C functions to
-directly construct objects into them without relying on language
-optimizations like C++'s named return value optimization (NRVO).
-
-
-tls_model (gnu::tls_model)
---------------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","X","","", ""
-
-The ``tls_model`` attribute allows you to specify which thread-local storage
-model to use. It accepts the following strings:
-
-* global-dynamic
-* local-dynamic
-* initial-exec
-* local-exec
-
-TLS models are mutually exclusive.
-
-
-thread
-------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "","","X","", ""
-
-The ``__declspec(thread)`` attribute declares a variable with thread local
-storage. It is available under the ``-fms-extensions`` flag for MSVC
-compatibility. See the documentation for `__declspec(thread)`_ on MSDN.
-
-.. _`__declspec(thread)`: http://msdn.microsoft.com/en-us/library/9w1sdazb.aspx
-
-In Clang, ``__declspec(thread)`` is generally equivalent in functionality to the
-GNU ``__thread`` keyword. The variable must not have a destructor and must have
-a constant initializer, if any. The attribute only applies to variables
-declared with static storage duration, such as globals, class static data
-members, and static locals.
-
-
-maybe_unused, unused, gnu::unused
----------------------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","X","","", ""
-
-When passing the ``-Wunused`` flag to Clang, entities that are unused by the
-program may be diagnosed. The ``[[maybe_unused]]`` (or
-``__attribute__((unused))``) attribute can be used to silence such diagnostics
-when the entity cannot be removed. For instance, a local variable may exist
-solely for use in an ``assert()`` statement, which makes the local variable
-unused when ``NDEBUG`` is defined.
-
-The attribute may be applied to the declaration of a class, a typedef, a
-variable, a function or method, a function parameter, an enumeration, an
-enumerator, a non-static data member, or a label.
-
-.. code-block: c++
- #include <cassert>
-
- [[maybe_unused]] void f([[maybe_unused]] bool thing1,
- [[maybe_unused]] bool thing2) {
- [[maybe_unused]] bool b = thing1 && thing2;
- assert(b);
- }
-
-
-Type Attributes
-===============
-
-
-align_value
------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","","","", ""
-
-The align_value attribute can be added to the typedef of a pointer type or the
-declaration of a variable of pointer or reference type. It specifies that the
-pointer will point to, or the reference will bind to, only objects with at
-least the provided alignment. This alignment value must be some positive power
-of 2.
-
- .. code-block:: c
-
- typedef double * aligned_double_ptr __attribute__((align_value(64)));
- void foo(double & x __attribute__((align_value(128)),
- aligned_double_ptr y) { ... }
-
-If the pointer value does not have the specified alignment at runtime, the
-behavior of the program is undefined.
-
-
-empty_bases
------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "","","X","", ""
-
-The empty_bases attribute permits the compiler to utilize the
-empty-base-optimization more frequently.
-This attribute only applies to struct, class, and union types.
-It is only supported when using the Microsoft C++ ABI.
-
-
-flag_enum
----------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","","","", ""
-
-This attribute can be added to an enumerator to signal to the compiler that it
-is intended to be used as a flag type. This will cause the compiler to assume
-that the range of the type includes all of the values that you can get by
-manipulating bits of the enumerator when issuing warnings.
-
-
-lto_visibility_public (clang::lto_visibility_public)
-----------------------------------------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "","X","","", ""
-
-See :doc:`LTOVisibility`.
-
-
-layout_version
---------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "","","X","", ""
-
-The layout_version attribute requests that the compiler utilize the class
-layout rules of a particular compiler version.
-This attribute only applies to struct, class, and union types.
-It is only supported when using the Microsoft C++ ABI.
-
-
-__single_inhertiance, __multiple_inheritance, __virtual_inheritance
--------------------------------------------------------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "","","","X", ""
-
-This collection of keywords is enabled under ``-fms-extensions`` and controls
-the pointer-to-member representation used on ``*-*-win32`` targets.
-
-The ``*-*-win32`` targets utilize a pointer-to-member representation which
-varies in size and alignment depending on the definition of the underlying
-class.
-
-However, this is problematic when a forward declaration is only available and
-no definition has been made yet. In such cases, Clang is forced to utilize the
-most general representation that is available to it.
-
-These keywords make it possible to use a pointer-to-member representation other
-than the most general one regardless of whether or not the definition will ever
-be present in the current translation unit.
-
-This family of keywords belong between the ``class-key`` and ``class-name``:
-
-.. code-block:: c++
-
- struct __single_inheritance S;
- int S::*i;
- struct S {};
-
-This keyword can be applied to class templates but only has an effect when used
-on full specializations:
-
-.. code-block:: c++
-
- template <typename T, typename U> struct __single_inheritance A; // warning: inheritance model ignored on primary template
- template <typename T> struct __multiple_inheritance A<T, T>; // warning: inheritance model ignored on partial specialization
- template <> struct __single_inheritance A<int, float>;
-
-Note that choosing an inheritance model less general than strictly necessary is
-an error:
-
-.. code-block:: c++
-
- struct __multiple_inheritance S; // error: inheritance model does not match definition
- int S::*i;
- struct S {};
-
-
-novtable
---------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "","","X","", ""
-
-This attribute can be added to a class declaration or definition to signal to
-the compiler that constructors and destructors will not reference the virtual
-function table. It is only supported when using the Microsoft C++ ABI.
-
-
-Statement Attributes
-====================
-
-
-fallthrough, clang::fallthrough
--------------------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "","X","","", ""
-
-The ``fallthrough`` (or ``clang::fallthrough``) attribute is used
-to annotate intentional fall-through
-between switch labels. It can only be applied to a null statement placed at a
-point of execution between any statement and the next switch label. It is
-common to mark these places with a specific comment, but this attribute is
-meant to replace comments with a more strict annotation, which can be checked
-by the compiler. This attribute doesn't change semantics of the code and can
-be used wherever an intended fall-through occurs. It is designed to mimic
-control-flow statements like ``break;``, so it can be placed in most places
-where ``break;`` can, but only if there are no statements on the execution path
-between it and the next switch label.
-
-By default, Clang does not warn on unannotated fallthrough from one ``switch``
-case to another. Diagnostics on fallthrough without a corresponding annotation
-can be enabled with the ``-Wimplicit-fallthrough`` argument.
-
-Here is an example:
-
-.. code-block:: c++
-
- // compile with -Wimplicit-fallthrough
- switch (n) {
- case 22:
- case 33: // no warning: no statements between case labels
- f();
- case 44: // warning: unannotated fall-through
- g();
- [[clang::fallthrough]];
- case 55: // no warning
- if (x) {
- h();
- break;
- }
- else {
- i();
- [[clang::fallthrough]];
- }
- case 66: // no warning
- p();
- [[clang::fallthrough]]; // warning: fallthrough annotation does not
- // directly precede case label
- q();
- case 77: // warning: unannotated fall-through
- r();
- }
-
-
-#pragma clang loop
-------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "","","","", "X"
-
-The ``#pragma clang loop`` directive allows loop optimization hints to be
-specified for the subsequent loop. The directive allows vectorization,
-interleaving, and unrolling to be enabled or disabled. Vector width as well
-as interleave and unrolling count can be manually specified. See
-`language extensions
-<http://clang.llvm.org/docs/LanguageExtensions.html#extensions-for-loop-hint-optimizations>`_
-for details.
-
-
-#pragma unroll, #pragma nounroll
---------------------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "","","","", "X"
-
-Loop unrolling optimization hints can be specified with ``#pragma unroll`` and
-``#pragma nounroll``. The pragma is placed immediately before a for, while,
-do-while, or c++11 range-based for loop.
-
-Specifying ``#pragma unroll`` without a parameter directs the loop unroller to
-attempt to fully unroll the loop if the trip count is known at compile time and
-attempt to partially unroll the loop if the trip count is not known at compile
-time:
-
-.. code-block:: c++
-
- #pragma unroll
- for (...) {
- ...
- }
-
-Specifying the optional parameter, ``#pragma unroll _value_``, directs the
-unroller to unroll the loop ``_value_`` times. The parameter may optionally be
-enclosed in parentheses:
-
-.. code-block:: c++
-
- #pragma unroll 16
- for (...) {
- ...
- }
-
- #pragma unroll(16)
- for (...) {
- ...
- }
-
-Specifying ``#pragma nounroll`` indicates that the loop should not be unrolled:
-
-.. code-block:: c++
-
- #pragma nounroll
- for (...) {
- ...
- }
-
-``#pragma unroll`` and ``#pragma unroll _value_`` have identical semantics to
-``#pragma clang loop unroll(full)`` and
-``#pragma clang loop unroll_count(_value_)`` respectively. ``#pragma nounroll``
-is equivalent to ``#pragma clang loop unroll(disable)``. See
-`language extensions
-<http://clang.llvm.org/docs/LanguageExtensions.html#extensions-for-loop-hint-optimizations>`_
-for further details including limitations of the unroll hints.
-
-
-__read_only, __write_only, __read_write (read_only, write_only, read_write)
----------------------------------------------------------------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "","","","X", ""
-
-The access qualifiers must be used with image object arguments or pipe arguments
-to declare if they are being read or written by a kernel or function.
-
-The read_only/__read_only, write_only/__write_only and read_write/__read_write
-names are reserved for use as access qualifiers and shall not be used otherwise.
-
-.. code-block:: c
-
- kernel void
- foo (read_only image2d_t imageA,
- write_only image2d_t imageB) {
- ...
- }
-
-In the above example imageA is a read-only 2D image object, and imageB is a
-write-only 2D image object.
-
-The read_write (or __read_write) qualifier can not be used with pipe.
-
-More details can be found in the OpenCL C language Spec v2.0, Section 6.6.
-
-
-__attribute__((opencl_unroll_hint))
------------------------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","","","", ""
-
-The opencl_unroll_hint attribute qualifier can be used to specify that a loop
-(for, while and do loops) can be unrolled. This attribute qualifier can be
-used to specify full unrolling or partial unrolling by a specified amount.
-This is a compiler hint and the compiler may ignore this directive. See
-`OpenCL v2.0 <https://www.khronos.org/registry/cl/specs/opencl-2.0.pdf>`_
-s6.11.5 for details.
-
-
-AMD GPU Register Attributes
-===========================
-Clang supports attributes for controlling register usage on AMD GPU
-targets. These attributes may be attached to a kernel function
-definition and is an optimization hint to the backend for the maximum
-number of registers to use. This is useful in cases where register
-limited occupancy is known to be an important factor for the
-performance for the kernel.
-
-The semantics are as follows:
-
-- The backend will attempt to limit the number of used registers to
- the specified value, but the exact number used is not
- guaranteed. The number used may be rounded up to satisfy the
- allocation requirements or ABI constraints of the subtarget. For
- example, on Southern Islands VGPRs may only be allocated in
- increments of 4, so requesting a limit of 39 VGPRs will really
- attempt to use up to 40. Requesting more registers than the
- subtarget supports will truncate to the maximum allowed. The backend
- may also use fewer registers than requested whenever possible.
-
-- 0 implies the default no limit on register usage.
-
-- Ignored on older VLIW subtargets which did not have separate scalar
- and vector registers, R600 through Northern Islands.
-
-amdgpu_num_sgpr
----------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","","","", ""
-
-Clang supports the
-``__attribute__((amdgpu_num_sgpr(<num_registers>)))`` attribute on AMD
-Southern Islands GPUs and later for controlling the number of scalar
-registers. A typical value would be between 8 and 104 in increments of
-8.
-
-Due to common instruction constraints, an additional 2-4 SGPRs are
-typically required for internal use depending on features used. This
-value is a hint for the total number of SGPRs to use, and not the
-number of user SGPRs, so no special consideration needs to be given
-for these.
-
-
-amdgpu_num_vgpr
----------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","","","", ""
-
-Clang supports the
-``__attribute__((amdgpu_num_vgpr(<num_registers>)))`` attribute on AMD
-Southern Islands GPUs and later for controlling the number of vector
-registers. A typical value would be between 4 and 256 in increments
-of 4.
-
-
-Calling Conventions
-===================
-Clang supports several different calling conventions, depending on the target
-platform and architecture. The calling convention used for a function determines
-how parameters are passed, how results are returned to the caller, and other
-low-level details of calling a function.
-
-fastcall (gnu::fastcall, __fastcall, _fastcall)
------------------------------------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","X","","X", ""
-
-On 32-bit x86 targets, this attribute changes the calling convention of a
-function to use ECX and EDX as register parameters and clear parameters off of
-the stack on return. This convention does not support variadic calls or
-unprototyped functions in C, and has no effect on x86_64 targets. This calling
-convention is supported primarily for compatibility with existing code. Users
-seeking register parameters should use the ``regparm`` attribute, which does
-not require callee-cleanup. See the documentation for `__fastcall`_ on MSDN.
-
-.. _`__fastcall`: http://msdn.microsoft.com/en-us/library/6xa169sk.aspx
-
-
-ms_abi (gnu::ms_abi)
---------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","X","","", ""
-
-On non-Windows x86_64 targets, this attribute changes the calling convention of
-a function to match the default convention used on Windows x86_64. This
-attribute has no effect on Windows targets or non-x86_64 targets.
-
-
-pcs (gnu::pcs)
---------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","X","","", ""
-
-On ARM targets, this attribute can be used to select calling conventions
-similar to ``stdcall`` on x86. Valid parameter values are "aapcs" and
-"aapcs-vfp".
-
-
-preserve_all
-------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","","","", ""
-
-On X86-64 and AArch64 targets, this attribute changes the calling convention of
-a function. The ``preserve_all`` calling convention attempts to make the code
-in the caller even less intrusive than the ``preserve_most`` calling convention.
-This calling convention also behaves identical to the ``C`` calling convention
-on how arguments and return values are passed, but it uses a different set of
-caller/callee-saved registers. This removes the burden of saving and
-recovering a large register set before and after the call in the caller. If
-the arguments are passed in callee-saved registers, then they will be
-preserved by the callee across the call. This doesn't apply for values
-returned in callee-saved registers.
-
-- On X86-64 the callee preserves all general purpose registers, except for
- R11. R11 can be used as a scratch register. Furthermore it also preserves
- all floating-point registers (XMMs/YMMs).
-
-The idea behind this convention is to support calls to runtime functions
-that don't need to call out to any other functions.
-
-This calling convention, like the ``preserve_most`` calling convention, will be
-used by a future version of the Objective-C runtime and should be considered
-experimental at this time.
-
-
-preserve_most
--------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","","","", ""
-
-On X86-64 and AArch64 targets, this attribute changes the calling convention of
-a function. The ``preserve_most`` calling convention attempts to make the code
-in the caller as unintrusive as possible. This convention behaves identically
-to the ``C`` calling convention on how arguments and return values are passed,
-but it uses a different set of caller/callee-saved registers. This alleviates
-the burden of saving and recovering a large register set before and after the
-call in the caller. If the arguments are passed in callee-saved registers,
-then they will be preserved by the callee across the call. This doesn't
-apply for values returned in callee-saved registers.
-
-- On X86-64 the callee preserves all general purpose registers, except for
- R11. R11 can be used as a scratch register. Floating-point registers
- (XMMs/YMMs) are not preserved and need to be saved by the caller.
-
-The idea behind this convention is to support calls to runtime functions
-that have a hot path and a cold path. The hot path is usually a small piece
-of code that doesn't use many registers. The cold path might need to call out to
-another function and therefore only needs to preserve the caller-saved
-registers, which haven't already been saved by the caller. The
-`preserve_most` calling convention is very similar to the ``cold`` calling
-convention in terms of caller/callee-saved registers, but they are used for
-different types of function calls. ``coldcc`` is for function calls that are
-rarely executed, whereas `preserve_most` function calls are intended to be
-on the hot path and definitely executed a lot. Furthermore ``preserve_most``
-doesn't prevent the inliner from inlining the function call.
-
-This calling convention will be used by a future version of the Objective-C
-runtime and should therefore still be considered experimental at this time.
-Although this convention was created to optimize certain runtime calls to
-the Objective-C runtime, it is not limited to this runtime and might be used
-by other runtimes in the future too. The current implementation only
-supports X86-64 and AArch64, but the intention is to support more architectures
-in the future.
-
-
-regparm (gnu::regparm)
-----------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","X","","", ""
-
-On 32-bit x86 targets, the regparm attribute causes the compiler to pass
-the first three integer parameters in EAX, EDX, and ECX instead of on the
-stack. This attribute has no effect on variadic functions, and all parameters
-are passed via the stack as normal.
-
-
-stdcall (gnu::stdcall, __stdcall, _stdcall)
--------------------------------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","X","","X", ""
-
-On 32-bit x86 targets, this attribute changes the calling convention of a
-function to clear parameters off of the stack on return. This convention does
-not support variadic calls or unprototyped functions in C, and has no effect on
-x86_64 targets. This calling convention is used widely by the Windows API and
-COM applications. See the documentation for `__stdcall`_ on MSDN.
-
-.. _`__stdcall`: http://msdn.microsoft.com/en-us/library/zxk0tw93.aspx
-
-
-thiscall (gnu::thiscall, __thiscall, _thiscall)
------------------------------------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","X","","X", ""
-
-On 32-bit x86 targets, this attribute changes the calling convention of a
-function to use ECX for the first parameter (typically the implicit ``this``
-parameter of C++ methods) and clear parameters off of the stack on return. This
-convention does not support variadic calls or unprototyped functions in C, and
-has no effect on x86_64 targets. See the documentation for `__thiscall`_ on
-MSDN.
-
-.. _`__thiscall`: http://msdn.microsoft.com/en-us/library/ek8tkfbw.aspx
-
-
-vectorcall (__vectorcall, _vectorcall)
---------------------------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","","","X", ""
-
-On 32-bit x86 *and* x86_64 targets, this attribute changes the calling
-convention of a function to pass vector parameters in SSE registers.
-
-On 32-bit x86 targets, this calling convention is similar to ``__fastcall``.
-The first two integer parameters are passed in ECX and EDX. Subsequent integer
-parameters are passed in memory, and callee clears the stack. On x86_64
-targets, the callee does *not* clear the stack, and integer parameters are
-passed in RCX, RDX, R8, and R9 as is done for the default Windows x64 calling
-convention.
-
-On both 32-bit x86 and x86_64 targets, vector and floating point arguments are
-passed in XMM0-XMM5. Homogenous vector aggregates of up to four elements are
-passed in sequential SSE registers if enough are available. If AVX is enabled,
-256 bit vectors are passed in YMM0-YMM5. Any vector or aggregate type that
-cannot be passed in registers for any reason is passed by reference, which
-allows the caller to align the parameter memory.
-
-See the documentation for `__vectorcall`_ on MSDN for more details.
-
-.. _`__vectorcall`: http://msdn.microsoft.com/en-us/library/dn375768.aspx
-
-
-Consumed Annotation Checking
-============================
-Clang supports additional attributes for checking basic resource management
-properties, specifically for unique objects that have a single owning reference.
-The following attributes are currently supported, although **the implementation
-for these annotations is currently in development and are subject to change.**
-
-callable_when
--------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","","","", ""
-
-Use ``__attribute__((callable_when(...)))`` to indicate what states a method
-may be called in. Valid states are unconsumed, consumed, or unknown. Each
-argument to this attribute must be a quoted string. E.g.:
-
-``__attribute__((callable_when("unconsumed", "unknown")))``
-
-
-consumable
-----------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","","","", ""
-
-Each ``class`` that uses any of the typestate annotations must first be marked
-using the ``consumable`` attribute. Failure to do so will result in a warning.
-
-This attribute accepts a single parameter that must be one of the following:
-``unknown``, ``consumed``, or ``unconsumed``.
-
-
-param_typestate
----------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","","","", ""
-
-This attribute specifies expectations about function parameters. Calls to an
-function with annotated parameters will issue a warning if the corresponding
-argument isn't in the expected state. The attribute is also used to set the
-initial state of the parameter when analyzing the function's body.
-
-
-return_typestate
-----------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","","","", ""
-
-The ``return_typestate`` attribute can be applied to functions or parameters.
-When applied to a function the attribute specifies the state of the returned
-value. The function's body is checked to ensure that it always returns a value
-in the specified state. On the caller side, values returned by the annotated
-function are initialized to the given state.
-
-When applied to a function parameter it modifies the state of an argument after
-a call to the function returns. The function's body is checked to ensure that
-the parameter is in the expected state before returning.
-
-
-set_typestate
--------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","","","", ""
-
-Annotate methods that transition an object into a new state with
-``__attribute__((set_typestate(new_state)))``. The new state must be
-unconsumed, consumed, or unknown.
-
-
-test_typestate
---------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","","","", ""
-
-Use ``__attribute__((test_typestate(tested_state)))`` to indicate that a method
-returns true if the object is in the specified state..
-
-
-Type Safety Checking
-====================
-Clang supports additional attributes to enable checking type safety properties
-that can't be enforced by the C type system. Use cases include:
-
-* MPI library implementations, where these attributes enable checking that
- the buffer type matches the passed ``MPI_Datatype``;
-* for HDF5 library there is a similar use case to MPI;
-* checking types of variadic functions' arguments for functions like
- ``fcntl()`` and ``ioctl()``.
-
-You can detect support for these attributes with ``__has_attribute()``. For
-example:
-
-.. code-block:: c++
-
- #if defined(__has_attribute)
- # if __has_attribute(argument_with_type_tag) && \
- __has_attribute(pointer_with_type_tag) && \
- __has_attribute(type_tag_for_datatype)
- # define ATTR_MPI_PWT(buffer_idx, type_idx) __attribute__((pointer_with_type_tag(mpi,buffer_idx,type_idx)))
- /* ... other macros ... */
- # endif
- #endif
-
- #if !defined(ATTR_MPI_PWT)
- # define ATTR_MPI_PWT(buffer_idx, type_idx)
- #endif
-
- int MPI_Send(void *buf, int count, MPI_Datatype datatype /*, other args omitted */)
- ATTR_MPI_PWT(1,3);
-
-argument_with_type_tag
-----------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","","","", ""
-
-Use ``__attribute__((argument_with_type_tag(arg_kind, arg_idx,
-type_tag_idx)))`` on a function declaration to specify that the function
-accepts a type tag that determines the type of some other argument.
-``arg_kind`` is an identifier that should be used when annotating all
-applicable type tags.
-
-This attribute is primarily useful for checking arguments of variadic functions
-(``pointer_with_type_tag`` can be used in most non-variadic cases).
-
-For example:
-
-.. code-block:: c++
-
- int fcntl(int fd, int cmd, ...)
- __attribute__(( argument_with_type_tag(fcntl,3,2) ));
-
-
-pointer_with_type_tag
----------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","","","", ""
-
-Use ``__attribute__((pointer_with_type_tag(ptr_kind, ptr_idx, type_tag_idx)))``
-on a function declaration to specify that the function accepts a type tag that
-determines the pointee type of some other pointer argument.
-
-For example:
-
-.. code-block:: c++
-
- int MPI_Send(void *buf, int count, MPI_Datatype datatype /*, other args omitted */)
- __attribute__(( pointer_with_type_tag(mpi,1,3) ));
-
-
-type_tag_for_datatype
----------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","","","", ""
-
-Clang supports annotating type tags of two forms.
-
-* **Type tag that is an expression containing a reference to some declared
- identifier.** Use ``__attribute__((type_tag_for_datatype(kind, type)))`` on a
- declaration with that identifier:
-
- .. code-block:: c++
-
- extern struct mpi_datatype mpi_datatype_int
- __attribute__(( type_tag_for_datatype(mpi,int) ));
- #define MPI_INT ((MPI_Datatype) &mpi_datatype_int)
-
-* **Type tag that is an integral literal.** Introduce a ``static const``
- variable with a corresponding initializer value and attach
- ``__attribute__((type_tag_for_datatype(kind, type)))`` on that declaration,
- for example:
-
- .. code-block:: c++
-
- #define MPI_INT ((MPI_Datatype) 42)
- static const MPI_Datatype mpi_datatype_int
- __attribute__(( type_tag_for_datatype(mpi,int) )) = 42
-
-The attribute also accepts an optional third argument that determines how the
-expression is compared to the type tag. There are two supported flags:
-
-* ``layout_compatible`` will cause types to be compared according to
- layout-compatibility rules (C++11 [class.mem] p 17, 18). This is
- implemented to support annotating types like ``MPI_DOUBLE_INT``.
-
- For example:
-
- .. code-block:: c++
-
- /* In mpi.h */
- struct internal_mpi_double_int { double d; int i; };
- extern struct mpi_datatype mpi_datatype_double_int
- __attribute__(( type_tag_for_datatype(mpi, struct internal_mpi_double_int, layout_compatible) ));
-
- #define MPI_DOUBLE_INT ((MPI_Datatype) &mpi_datatype_double_int)
-
- /* In user code */
- struct my_pair { double a; int b; };
- struct my_pair *buffer;
- MPI_Send(buffer, 1, MPI_DOUBLE_INT /*, ... */); // no warning
-
- struct my_int_pair { int a; int b; }
- struct my_int_pair *buffer2;
- MPI_Send(buffer2, 1, MPI_DOUBLE_INT /*, ... */); // warning: actual buffer element
- // type 'struct my_int_pair'
- // doesn't match specified MPI_Datatype
-
-* ``must_be_null`` specifies that the expression should be a null pointer
- constant, for example:
-
- .. code-block:: c++
-
- /* In mpi.h */
- extern struct mpi_datatype mpi_datatype_null
- __attribute__(( type_tag_for_datatype(mpi, void, must_be_null) ));
-
- #define MPI_DATATYPE_NULL ((MPI_Datatype) &mpi_datatype_null)
-
- /* In user code */
- MPI_Send(buffer, 1, MPI_DATATYPE_NULL /*, ... */); // warning: MPI_DATATYPE_NULL
- // was specified but buffer
- // is not a null pointer
-
-
-OpenCL Address Spaces
-=====================
-The address space qualifier may be used to specify the region of memory that is
-used to allocate the object. OpenCL supports the following address spaces:
-__generic(generic), __global(global), __local(local), __private(private),
-__constant(constant).
-
- .. code-block:: c
-
- __constant int c = ...;
-
- __generic int* foo(global int* g) {
- __local int* l;
- private int p;
- ...
- return l;
- }
-
-More details can be found in the OpenCL C language Spec v2.0, Section 6.5.
-
-constant (__constant)
----------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "","","","X", ""
-
-The constant address space attribute signals that an object is located in
-a constant (non-modifiable) memory region. It is available to all work items.
-Any type can be annotated with the constant address space attribute. Objects
-with the constant address space qualifier can be declared in any scope and must
-have an initializer.
-
-
-generic (__generic)
--------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "","","","X", ""
-
-The generic address space attribute is only available with OpenCL v2.0 and later.
-It can be used with pointer types. Variables in global and local scope and
-function parameters in non-kernel functions can have the generic address space
-type attribute. It is intended to be a placeholder for any other address space
-except for '__constant' in OpenCL code which can be used with multiple address
-spaces.
-
-
-global (__global)
------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "","","","X", ""
-
-The global address space attribute specifies that an object is allocated in
-global memory, which is accessible by all work items. The content stored in this
-memory area persists between kernel executions. Pointer types to the global
-address space are allowed as function parameters or local variables. Starting
-with OpenCL v2.0, the global address space can be used with global (program
-scope) variables and static local variable as well.
-
-
-local (__local)
----------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "","","","X", ""
-
-The local address space specifies that an object is allocated in the local (work
-group) memory area, which is accessible to all work items in the same work
-group. The content stored in this memory region is not accessible after
-the kernel execution ends. In a kernel function scope, any variable can be in
-the local address space. In other scopes, only pointer types to the local address
-space are allowed. Local address space variables cannot have an initializer.
-
-
-private (__private)
--------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "","","","X", ""
-
-The private address space specifies that an object is allocated in the private
-(work item) memory. Other work items cannot access the same memory area and its
-content is destroyed after work item execution ends. Local variables can be
-declared in the private address space. Function arguments are always in the
-private address space. Kernel function arguments of a pointer or an array type
-cannot point to the private address space.
-
-
-Nullability Attributes
-======================
-Whether a particular pointer may be "null" is an important concern when working with pointers in the C family of languages. The various nullability attributes indicate whether a particular pointer can be null or not, which makes APIs more expressive and can help static analysis tools identify bugs involving null pointers. Clang supports several kinds of nullability attributes: the ``nonnull`` and ``returns_nonnull`` attributes indicate which function or method parameters and result types can never be null, while nullability type qualifiers indicate which pointer types can be null (``_Nullable``) or cannot be null (``_Nonnull``).
-
-The nullability (type) qualifiers express whether a value of a given pointer type can be null (the ``_Nullable`` qualifier), doesn't have a defined meaning for null (the ``_Nonnull`` qualifier), or for which the purpose of null is unclear (the ``_Null_unspecified`` qualifier). Because nullability qualifiers are expressed within the type system, they are more general than the ``nonnull`` and ``returns_nonnull`` attributes, allowing one to express (for example) a nullable pointer to an array of nonnull pointers. Nullability qualifiers are written to the right of the pointer to which they apply. For example:
-
- .. code-block:: c
-
- // No meaningful result when 'ptr' is null (here, it happens to be undefined behavior).
- int fetch(int * _Nonnull ptr) { return *ptr; }
-
- // 'ptr' may be null.
- int fetch_or_zero(int * _Nullable ptr) {
- return ptr ? *ptr : 0;
- }
-
- // A nullable pointer to non-null pointers to const characters.
- const char *join_strings(const char * _Nonnull * _Nullable strings, unsigned n);
-
-In Objective-C, there is an alternate spelling for the nullability qualifiers that can be used in Objective-C methods and properties using context-sensitive, non-underscored keywords. For example:
-
- .. code-block:: objective-c
-
- @interface NSView : NSResponder
- - (nullable NSView *)ancestorSharedWithView:(nonnull NSView *)aView;
- @property (assign, nullable) NSView *superview;
- @property (readonly, nonnull) NSArray *subviews;
- @end
-
-nonnull (gnu::nonnull)
-----------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","X","","", ""
-
-The ``nonnull`` attribute indicates that some function parameters must not be null, and can be used in several different ways. It's original usage (`from GCC <https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#Common-Function-Attributes>`_) is as a function (or Objective-C method) attribute that specifies which parameters of the function are nonnull in a comma-separated list. For example:
-
- .. code-block:: c
-
- extern void * my_memcpy (void *dest, const void *src, size_t len)
- __attribute__((nonnull (1, 2)));
-
-Here, the ``nonnull`` attribute indicates that parameters 1 and 2
-cannot have a null value. Omitting the parenthesized list of parameter indices means that all parameters of pointer type cannot be null:
-
- .. code-block:: c
-
- extern void * my_memcpy (void *dest, const void *src, size_t len)
- __attribute__((nonnull));
-
-Clang also allows the ``nonnull`` attribute to be placed directly on a function (or Objective-C method) parameter, eliminating the need to specify the parameter index ahead of type. For example:
-
- .. code-block:: c
-
- extern void * my_memcpy (void *dest __attribute__((nonnull)),
- const void *src __attribute__((nonnull)), size_t len);
-
-Note that the ``nonnull`` attribute indicates that passing null to a non-null parameter is undefined behavior, which the optimizer may take advantage of to, e.g., remove null checks. The ``_Nonnull`` type qualifier indicates that a pointer cannot be null in a more general manner (because it is part of the type system) and does not imply undefined behavior, making it more widely applicable.
-
-
-returns_nonnull (gnu::returns_nonnull)
---------------------------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "X","X","","", ""
-
-The ``returns_nonnull`` attribute indicates that a particular function (or Objective-C method) always returns a non-null pointer. For example, a particular system ``malloc`` might be defined to terminate a process when memory is not available rather than returning a null pointer:
-
- .. code-block:: c
-
- extern void * malloc (size_t size) __attribute__((returns_nonnull));
-
-The ``returns_nonnull`` attribute implies that returning a null pointer is undefined behavior, which the optimizer may take advantage of. The ``_Nonnull`` type qualifier indicates that a pointer cannot be null in a more general manner (because it is part of the type system) and does not imply undefined behavior, making it more widely applicable
-
-
-_Nonnull
---------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "","","","X", ""
-
-The ``_Nonnull`` nullability qualifier indicates that null is not a meaningful value for a value of the ``_Nonnull`` pointer type. For example, given a declaration such as:
-
- .. code-block:: c
-
- int fetch(int * _Nonnull ptr);
-
-a caller of ``fetch`` should not provide a null value, and the compiler will produce a warning if it sees a literal null value passed to ``fetch``. Note that, unlike the declaration attribute ``nonnull``, the presence of ``_Nonnull`` does not imply that passing null is undefined behavior: ``fetch`` is free to consider null undefined behavior or (perhaps for backward-compatibility reasons) defensively handle null.
-
-
-_Null_unspecified
------------------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "","","","X", ""
-
-The ``_Null_unspecified`` nullability qualifier indicates that neither the ``_Nonnull`` nor ``_Nullable`` qualifiers make sense for a particular pointer type. It is used primarily to indicate that the role of null with specific pointers in a nullability-annotated header is unclear, e.g., due to overly-complex implementations or historical factors with a long-lived API.
-
-
-_Nullable
----------
-.. csv-table:: Supported Syntaxes
- :header: "GNU", "C++11", "__declspec", "Keyword", "Pragma"
-
- "","","","X", ""
-
-The ``_Nullable`` nullability qualifier indicates that a value of the ``_Nullable`` pointer type can be null. For example, given:
-
- .. code-block:: c
-
- int fetch_or_zero(int * _Nullable ptr);
-
-a caller of ``fetch_or_zero`` can provide null.
-
-
+=================== \ No newline at end of file
diff --git a/docs/AutomaticReferenceCounting.rst b/docs/AutomaticReferenceCounting.rst
index 2faed2379164..aa2a28399d14 100644
--- a/docs/AutomaticReferenceCounting.rst
+++ b/docs/AutomaticReferenceCounting.rst
@@ -910,10 +910,10 @@ not support ``__weak`` references.
binary compatibility.
A class may indicate that it does not support weak references by providing the
-``objc_arc_weak_unavailable`` attribute on the class's interface declaration. A
+``objc_arc_weak_reference_unavailable`` attribute on the class's interface declaration. A
retainable object pointer type is **weak-unavailable** if
is a pointer to an (optionally protocol-qualified) Objective-C class ``T`` where
-``T`` or one of its superclasses has the ``objc_arc_weak_unavailable``
+``T`` or one of its superclasses has the ``objc_arc_weak_reference_unavailable``
attribute. A program is ill-formed if it applies the ``__weak`` ownership
qualifier to a weak-unavailable type or if the value operand of a weak
assignment operation has a weak-unavailable type.
diff --git a/docs/Block-ABI-Apple.rst b/docs/Block-ABI-Apple.rst
index 08f346447e03..628e6f3d90ba 100644
--- a/docs/Block-ABI-Apple.rst
+++ b/docs/Block-ABI-Apple.rst
@@ -530,13 +530,13 @@ and:
.. code-block:: c
- struct _block_byref_i i = {( .forwarding=&i, .flags=0, .size=sizeof(struct _block_byref_i) )};
+ struct _block_byref_i i = {( .isa=NULL, .forwarding=&i, .flags=0, .size=sizeof(struct _block_byref_i), .captured_i=2 )};
struct __block_literal_5 _block_literal = {
&_NSConcreteStackBlock,
(1<<25)|(1<<29), <uninitialized>,
__block_invoke_5,
&__block_descriptor_5,
- 2,
+ &i,
};
Importing ``__attribute__((NSObject))`` ``__block`` variables
diff --git a/docs/ClangCheck.rst b/docs/ClangCheck.rst
index 4650049b1fbf..c249c126770f 100644
--- a/docs/ClangCheck.rst
+++ b/docs/ClangCheck.rst
@@ -31,6 +31,6 @@ do basic error checking and AST dumping.
1 error generated.
Error while processing snippet.cc.
-The '--' at the end is important as it prevents `clang-check` from search for a
-compilation database. For more information on how to setup and use `clang-check`
-in a project, see :doc:`HowToSetupToolingForLLVM`.
+The '--' at the end is important as it prevents :program:`clang-check` from
+searching for a compilation database. For more information on how to setup and
+use :program:`clang-check` in a project, see :doc:`HowToSetupToolingForLLVM`.
diff --git a/docs/ClangFormat.rst b/docs/ClangFormat.rst
index 3f52b767e3ad..dc1e2b9a7639 100644
--- a/docs/ClangFormat.rst
+++ b/docs/ClangFormat.rst
@@ -184,7 +184,7 @@ So to reformat all the lines in the latest :program:`git` commit, just do:
.. code-block:: console
- git diff -U0 HEAD^ | clang-format-diff.py -i -p1
+ git diff -U0 --no-color HEAD^ | clang-format-diff.py -i -p1
In an SVN client, you can do:
diff --git a/docs/ClangFormatStyleOptions.rst b/docs/ClangFormatStyleOptions.rst
index a548e835a56d..3f76da6dca32 100644
--- a/docs/ClangFormatStyleOptions.rst
+++ b/docs/ClangFormatStyleOptions.rst
@@ -670,6 +670,9 @@ the configuration (without a prefix: ``Auto``).
**SpaceAfterCStyleCast** (``bool``)
If ``true``, a space may be inserted after C style casts.
+**SpaceAfterTemplateKeyword** (``bool``)
+ If ``true``, a space will be inserted after the 'template' keyword.
+
**SpaceBeforeAssignmentOperators** (``bool``)
If ``false``, spaces will be removed before assignment operators.
diff --git a/docs/CommandGuide/clang.rst b/docs/CommandGuide/clang.rst
index 0546304e710e..16bb09f3c740 100644
--- a/docs/CommandGuide/clang.rst
+++ b/docs/CommandGuide/clang.rst
@@ -105,7 +105,12 @@ Language Selection and Mode Options
.. option:: -stdlib=<library>
Specify the C++ standard library to use; supported options are libstdc++ and
- libc++.
+ libc++. If not specified, platform default will be used.
+
+.. option:: -rtlib=<library>
+
+ Specify the compiler runtime library to use; supported options are libgcc and
+ compiler-rt. If not specified, platform default will be used.
.. option:: -ansi
@@ -162,16 +167,6 @@ Language Selection and Mode Options
Enable the "Blocks" language feature.
-.. option:: -fobjc-gc-only
-
- Indicate that Objective-C code should be compiled in GC-only mode, which only
- works when Objective-C Garbage Collection is enabled.
-
-.. option:: -fobjc-gc
-
- Indicate that Objective-C code should be compiled in hybrid-GC mode, which
- works with both GC and non-GC mode.
-
.. option:: -fobjc-abi-version=version
Select the Objective-C ABI version to use. Available versions are 1 (legacy
@@ -221,7 +216,7 @@ number of cross compilers, or may only support a native target.
Code Generation Options
~~~~~~~~~~~~~~~~~~~~~~~
-.. option:: -O0, -O1, -O2, -O3, -Ofast, -Os, -Oz, -O, -O4
+.. option:: -O0, -O1, -O2, -O3, -Ofast, -Os, -Oz, -Og, -O, -O4
Specify which optimization level to use:
@@ -247,6 +242,9 @@ Code Generation Options
:option:`-Oz` Like :option:`-Os` (and thus :option:`-O2`), but reduces code
size further.
+ :option:`-Og` Like :option:`-O1`. In future versions, this option might
+ disable different optimizations in order to improve debuggability.
+
:option:`-O` Equivalent to :option:`-O2`.
:option:`-O4` and higher
@@ -323,13 +321,19 @@ Code Generation Options
model can be overridden with the tls_model attribute. The compiler will try
to choose a more efficient model if possible.
-.. option:: -flto, -emit-llvm
+.. option:: -flto, -flto=full, -flto=thin, -emit-llvm
Generate output files in LLVM formats, suitable for link time optimization.
When used with :option:`-S` this generates LLVM intermediate language
assembly files, otherwise this generates LLVM bitcode format object files
(which may be passed to the linker depending on the stage selection options).
+ The default for :option:`-flto` is "full", in which the
+ LLVM bitcode is suitable for monolithic Link Time Optimization (LTO), where
+ the linker merges all such modules into a single combined module for
+ optimization. With "thin", :doc:`ThinLTO <../ThinLTO>`
+ compilation is invoked instead.
+
Driver Options
~~~~~~~~~~~~~~
@@ -383,7 +387,8 @@ Driver Options
.. option:: -print-libgcc-file-name
- Print the library path for "libgcc.a".
+ Print the library path for the currently used compiler runtime library
+ ("libgcc.a" or "libclang_rt.builtins.*.a").
.. option:: -print-prog-name=<name>
@@ -397,6 +402,12 @@ Driver Options
Save intermediate compilation results.
+.. option:: -save-stats, -save-stats=cwd, -save-stats=obj
+
+ Save internal code generation (LLVM) statistics to a file in the current
+ directory (:option:`-save-stats`/"-save-stats=cwd") or the directory
+ of the output file ("-save-state=obj").
+
.. option:: -integrated-as, -no-integrated-as
Used to enable and disable, respectively, the use of the integrated
diff --git a/docs/ControlFlowIntegrityDesign.rst b/docs/ControlFlowIntegrityDesign.rst
index 38c5e5b99e31..a9f0b28a95f5 100644
--- a/docs/ControlFlowIntegrityDesign.rst
+++ b/docs/ControlFlowIntegrityDesign.rst
@@ -497,3 +497,57 @@ Cross-DSO CFI mode requires that the main executable is built as PIE.
In non-PIE executables the address of an external function (taken from
the main executable) is the address of that function’s PLT record in
the main executable. This would break the CFI checks.
+
+
+Hardware support
+================
+
+We believe that the above design can be efficiently implemented in hardware.
+A single new instruction added to an ISA would allow to perform the CFI check
+with fewer bytes per check (smaller code size overhead) and potentially more
+efficiently. The current software-only instrumentation requires at least
+32-bytes per check (on x86_64).
+A hardware instruction may probably be less than ~ 12 bytes.
+Such instruction would check that the argument pointer is in-bounds,
+and is properly aligned, and if the checks fail it will either trap (in monolithic scheme)
+or call the slow path function (cross-DSO scheme).
+The bit vector lookup is probably too complex for a hardware implementation.
+
+.. code-block:: none
+
+ // This instruction checks that 'Ptr'
+ // * is aligned by (1 << kAlignment) and
+ // * is inside [kRangeBeg, kRangeBeg+(kRangeSize<<kAlignment))
+ // and if the check fails it jumps to the given target (slow path).
+ //
+ // 'Ptr' is a register, pointing to the virtual function table
+ // or to the function which we need to check. We may require an explicit
+ // fixed register to be used.
+ // 'kAlignment' is a 4-bit constant.
+ // 'kRangeSize' is a ~20-bit constant.
+ // 'kRangeBeg' is a PC-relative constant (~28 bits)
+ // pointing to the beginning of the allowed range for 'Ptr'.
+ // 'kFailedCheckTarget': is a PC-relative constant (~28 bits)
+ // representing the target to branch to when the check fails.
+ // If kFailedCheckTarget==0, the process will trap
+ // (monolithic binary scheme).
+ // Otherwise it will jump to a handler that implements `CFI_SlowPath`
+ // (cross-DSO scheme).
+ CFI_Check(Ptr, kAlignment, kRangeSize, kRangeBeg, kFailedCheckTarget) {
+ if (Ptr < kRangeBeg ||
+ Ptr >= kRangeBeg + (kRangeSize << kAlignment) ||
+ Ptr & ((1 << kAlignment) - 1))
+ Jump(kFailedCheckTarget);
+ }
+
+An alternative and more compact enconding would not use `kFailedCheckTarget`,
+and will trap on check failure instead.
+This will allow us to fit the instruction into **8-9 bytes**.
+The cross-DSO checks will be performed by a trap handler and
+performance-critical ones will have to be black-listed and checked using the
+software-only scheme.
+
+Note that such hardware extension would be complementary to checks
+at the callee side, such as e.g. **Intel ENDBRANCH**.
+Moreover, CFI would have two benefits over ENDBRANCH: a) precision and b)
+ability to protect against invalid casts between polymorphic types.
diff --git a/docs/CrossCompilation.rst b/docs/CrossCompilation.rst
index c07bc21a430d..5e1253ddf853 100644
--- a/docs/CrossCompilation.rst
+++ b/docs/CrossCompilation.rst
@@ -78,14 +78,14 @@ go ahead, creating code for the host platform, which will break later
on when assembling or linking.
The triple has the general format ``<arch><sub>-<vendor>-<sys>-<abi>``, where:
- * ``arch`` = ``x86``, ``arm``, ``thumb``, ``mips``, etc.
+ * ``arch`` = ``x86_64``, ``i386``, ``arm``, ``thumb``, ``mips``, etc.
* ``sub`` = for ex. on ARM: ``v5``, ``v6m``, ``v7a``, ``v7m``, etc.
* ``vendor`` = ``pc``, ``apple``, ``nvidia``, ``ibm``, etc.
* ``sys`` = ``none``, ``linux``, ``win32``, ``darwin``, ``cuda``, etc.
* ``abi`` = ``eabi``, ``gnu``, ``android``, ``macho``, ``elf``, etc.
The sub-architecture options are available for their own architectures,
-of course, so "x86v7a" doesn't make sense. The vendor needs to be
+of course, so "x86v7a" doesn't make sense. The vendor needs to be
specified only if there's a relevant change, for instance between PC
and Apple. Most of the time it can be omitted (and Unknown)
will be assumed, which sets the defaults for the specified architecture.
diff --git a/docs/DiagnosticsReference.rst b/docs/DiagnosticsReference.rst
new file mode 100644
index 000000000000..7294c3662027
--- /dev/null
+++ b/docs/DiagnosticsReference.rst
@@ -0,0 +1,10560 @@
+..
+ -------------------------------------------------------------------
+ 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
+================
+
+-W
+--
+Synonym for `-Wextra`_.
+
+
+-W#pragma-messages
+------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
+The text of this diagnostic is not controlled by Clang.
+
+
+-W#warnings
+-----------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
+The text of this diagnostic is not controlled by Clang.
+
+
+-WCFString-literal
+------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`input conversion stopped due to an input byte that does not belong to the input codeset UTF-8`|
++------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-WCL4
+-----
+Some of the diagnostics controlled by this flag are enabled by default.
+
+Controls `-Wall`_, `-Wextra`_.
+
+
+-WIndependentClass-attribute
+----------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'objc\_independent\_class' attribute may be put on a typedef only; attribute is ignored`|
++------------------------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'objc\_independent\_class' attribute may be put on Objective-C object pointer type only; attribute is ignored`|
++----------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-WNSObject-attribute
+--------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'NSObject' attribute may be put on a typedef only; attribute is ignored`|
++--------------------------------------------------------------------------------------------------------------+
+
+
+-Wabi
+-----
+This diagnostic flag exists for GCC compatibility, and has no effect in Clang.
+
+-Wabsolute-value
+----------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`absolute value function` |nbsp| :placeholder:`A` |nbsp| :diagtext:`given an argument of type` |nbsp| :placeholder:`B` |nbsp| :diagtext:`but has parameter of type` |nbsp| :placeholder:`C` |nbsp| :diagtext:`which may cause truncation of value`|
++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------+----------------------+---------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`taking the absolute value of` |nbsp| |+--------------------+| |nbsp| :diagtext:`type` |nbsp| :placeholder:`B` |nbsp| :diagtext:`is suspicious`|
+| ||:diagtext:`pointer` || |
+| |+--------------------+| |
+| ||:diagtext:`function`|| |
+| |+--------------------+| |
+| ||:diagtext:`array` || |
+| |+--------------------+| |
++---------------------------------------------------------------------------+----------------------+---------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`taking the absolute value of unsigned type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`has no effect`|
++------------------------------------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------+----------------------------+------------------------------------------------------------------------------------------------------------------+----------------------------+------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`using` |nbsp| |+--------------------------+| |nbsp| :diagtext:`absolute value function` |nbsp| :placeholder:`A` |nbsp| :diagtext:`when argument is of` |nbsp| |+--------------------------+| |nbsp| :diagtext:`type`|
+| ||:diagtext:`integer` || ||:diagtext:`integer` || |
+| |+--------------------------+| |+--------------------------+| |
+| ||:diagtext:`floating point`|| ||:diagtext:`floating point`|| |
+| |+--------------------------+| |+--------------------------+| |
+| ||:diagtext:`complex` || ||:diagtext:`complex` || |
+| |+--------------------------+| |+--------------------------+| |
++----------------------------------------------------+----------------------------+------------------------------------------------------------------------------------------------------------------+----------------------------+------------------------+
+
+
+-Wabstract-final-class
+----------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------+--------------------+-------------+
+|:warning:`warning:` |nbsp| :diagtext:`abstract class is marked '`|+------------------+|:diagtext:`'`|
+| ||:diagtext:`final` || |
+| |+------------------+| |
+| ||:diagtext:`sealed`|| |
+| |+------------------+| |
++-----------------------------------------------------------------+--------------------+-------------+
+
+
+-Wabstract-vbase-init
+---------------------
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`initializer for virtual base class` |nbsp| :placeholder:`A` |nbsp| :diagtext:`of abstract class` |nbsp| :placeholder:`B` |nbsp| :diagtext:`will never be used`|
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Waddress
+---------
+This diagnostic is enabled by default.
+
+Controls `-Wpointer-bool-conversion`_, `-Wstring-compare`_, `-Wtautological-pointer-compare`_.
+
+
+-Waddress-of-array-temporary
+----------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`pointer is initialized by a temporary array, which will be destroyed at the end of the full-expression`|
++---------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Waddress-of-packed-member
+--------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`taking address of packed member` |nbsp| :placeholder:`A` |nbsp| :diagtext:`of class or structure` |nbsp| :placeholder:`B` |nbsp| :diagtext:`may result in an unaligned pointer value`|
++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Waddress-of-temporary
+----------------------
+This diagnostic is an error by default, but the flag ``-Wno-address-of-temporary`` can be used to disable the error.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------------+
+|:error:`error:` |nbsp| :diagtext:`taking the address of a temporary object of type` |nbsp| :placeholder:`A`|
++-----------------------------------------------------------------------------------------------------------+
+
+
+-Waggregate-return
+------------------
+This diagnostic flag exists for GCC compatibility, and has no effect in Clang.
+
+-Wall
+-----
+Some of the diagnostics controlled by this flag are enabled by default.
+
+Controls `-Wmost`_, `-Wparentheses`_, `-Wswitch`_, `-Wswitch-bool`_.
+
+
+-Wambiguous-ellipsis
+--------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------+---------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'...' in this location creates a C-style varargs function`|+-------------------------------------------+|
+| ||:diagtext:`, not a function parameter pack`||
+| |+-------------------------------------------+|
+| || ||
+| |+-------------------------------------------+|
++------------------------------------------------------------------------------------------------+---------------------------------------------+
+
+
+-Wambiguous-macro
+-----------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`ambiguous expansion of macro` |nbsp| :placeholder:`A`|
++-------------------------------------------------------------------------------------------+
+
+
+-Wambiguous-member-template
+---------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`lookup of` |nbsp| :placeholder:`A` |nbsp| :diagtext:`in member access expression is ambiguous; using member of` |nbsp| :placeholder:`B`|
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wanalyzer-incompatible-plugin
+------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`checker plugin '`:placeholder:`A`:diagtext:`' is not compatible with this version of the analyzer`|
++----------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wanonymous-pack-parens
+-----------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`ISO C++11 requires a parenthesized pack declaration to have a name`|
++---------------------------------------------------------------------------------------------------------+
+
+
+-Warc
+-----
+This diagnostic is enabled by default.
+
+Controls `-Warc-non-pod-memaccess`_, `-Warc-retain-cycles`_, `-Warc-unsafe-retained-assign`_.
+
+
+-Warc-bridge-casts-disallowed-in-nonarc
+---------------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'`:placeholder:`A`:diagtext:`' casts have no effect when not using ARC`|
++-------------------------------------------------------------------------------------------------------------+
+
+
+-Warc-maybe-repeated-use-of-weak
+--------------------------------
+**Diagnostic text:**
+
++---------------------------------------------------+-------------------------------+------------------------------------------------------------------------------------------+----------------------+-------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`weak` |nbsp| |+-----------------------------+| |nbsp| :placeholder:`B` |nbsp| :diagtext:`may be accessed multiple times in this` |nbsp| |+--------------------+| |nbsp| :diagtext:`and may be unpredictably set to nil; assign to a strong variable to keep the object alive`|
+| ||:diagtext:`variable` || ||:diagtext:`function`|| |
+| |+-----------------------------+| |+--------------------+| |
+| ||:diagtext:`property` || ||:diagtext:`method` || |
+| |+-----------------------------+| |+--------------------+| |
+| ||:diagtext:`implicit property`|| ||:diagtext:`block` || |
+| |+-----------------------------+| |+--------------------+| |
+| ||:diagtext:`instance variable`|| ||:diagtext:`lambda` || |
+| |+-----------------------------+| |+--------------------+| |
++---------------------------------------------------+-------------------------------+------------------------------------------------------------------------------------------+----------------------+-------------------------------------------------------------------------------------------------------------+
+
+
+-Warc-non-pod-memaccess
+-----------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------+-----------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| |+---------------------------+| |nbsp| :diagtext:`this` |nbsp| :placeholder:`B` |nbsp| :diagtext:`call is a pointer to ownership-qualified type` |nbsp| :placeholder:`C`|
+| ||:diagtext:`destination for`|| |
+| |+---------------------------+| |
+| ||:diagtext:`source of` || |
+| |+---------------------------+| |
++---------------------------+-----------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Warc-performSelector-leaks
+---------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`performSelector may cause a leak because its selector is unknown`|
++-------------------------------------------------------------------------------------------------------+
+
+
+-Warc-repeated-use-of-weak
+--------------------------
+Also controls `-Warc-maybe-repeated-use-of-weak`_.
+
+**Diagnostic text:**
+
++---------------------------------------------------+-------------------------------+--------------------------------------------------------------------------------------+----------------------+-------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`weak` |nbsp| |+-----------------------------+| |nbsp| :placeholder:`B` |nbsp| :diagtext:`is accessed multiple times in this` |nbsp| |+--------------------+| |nbsp| :diagtext:`but may be unpredictably set to nil; assign to a strong variable to keep the object alive`|
+| ||:diagtext:`variable` || ||:diagtext:`function`|| |
+| |+-----------------------------+| |+--------------------+| |
+| ||:diagtext:`property` || ||:diagtext:`method` || |
+| |+-----------------------------+| |+--------------------+| |
+| ||:diagtext:`implicit property`|| ||:diagtext:`block` || |
+| |+-----------------------------+| |+--------------------+| |
+| ||:diagtext:`instance variable`|| ||:diagtext:`lambda` || |
+| |+-----------------------------+| |+--------------------+| |
++---------------------------------------------------+-------------------------------+--------------------------------------------------------------------------------------+----------------------+-------------------------------------------------------------------------------------------------------------+
+
+
+-Warc-retain-cycles
+-------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`capturing` |nbsp| :placeholder:`A` |nbsp| :diagtext:`strongly in this block is likely to lead to a retain cycle`|
++------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Warc-unsafe-retained-assign
+----------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------------+---------------------------------+-------------------------------------+----------------------+------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`assigning` |nbsp| |+-------------------------------+| |nbsp| :diagtext:`to a weak` |nbsp| |+--------------------+|:diagtext:`; object will be released after assignment`|
+| ||:diagtext:`array literal` || ||:diagtext:`property`|| |
+| |+-------------------------------+| |+--------------------+| |
+| ||:diagtext:`dictionary literal` || ||:diagtext:`variable`|| |
+| |+-------------------------------+| |+--------------------+| |
+| ||:diagtext:`numeric literal` || | | |
+| |+-------------------------------+| | | |
+| ||:diagtext:`boxed expression` || | | |
+| |+-------------------------------+| | | |
+| ||:diagtext:`<should not happen>`|| | | |
+| |+-------------------------------+| | | |
+| ||:diagtext:`block literal` || | | |
+| |+-------------------------------+| | | |
++--------------------------------------------------------+---------------------------------+-------------------------------------+----------------------+------------------------------------------------------+
+
++---------------------------------------------------------------------------+--------------------------------+--------+----------------------+------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`assigning retained object to` |nbsp| |+------------------------------+| |nbsp| |+--------------------+|:diagtext:`; object will be released after assignment`|
+| ||:diagtext:`weak` || ||:diagtext:`property`|| |
+| |+------------------------------+| |+--------------------+| |
+| ||:diagtext:`unsafe\_unretained`|| ||:diagtext:`variable`|| |
+| |+------------------------------+| |+--------------------+| |
++---------------------------------------------------------------------------+--------------------------------+--------+----------------------+------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`assigning retained object to unsafe property; object will be released after assignment`|
++-----------------------------------------------------------------------------------------------------------------------------+
+
+
+-Warray-bounds
+--------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------+-------------+
+|:warning:`warning:` |nbsp| :diagtext:`array index` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is past the end of the array (which contains` |nbsp| :placeholder:`B` |nbsp| :diagtext:`element`|+-------------+|:diagtext:`)`|
+| || || |
+| |+-------------+| |
+| ||:diagtext:`s`|| |
+| |+-------------+| |
++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------+-------------+
+
++----------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`array index` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is before the beginning of the array`|
++----------------------------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`array argument is too small; contains` |nbsp| :placeholder:`A` |nbsp| :diagtext:`elements, callee requires at least` |nbsp| :placeholder:`B`|
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'static' has no effect on zero-length arrays`|
++-----------------------------------------------------------------------------------+
+
+
+-Warray-bounds-pointer-arithmetic
+---------------------------------
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------+-------------+
+|:warning:`warning:` |nbsp| :diagtext:`the pointer incremented by` |nbsp| :placeholder:`A` |nbsp| :diagtext:`refers past the end of the array (that contains` |nbsp| :placeholder:`B` |nbsp| :diagtext:`element`|+-------------+|:diagtext:`)`|
+| || || |
+| |+-------------+| |
+| ||:diagtext:`s`|| |
+| |+-------------+| |
++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------+-------------+
+
++-----------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`the pointer decremented by` |nbsp| :placeholder:`A` |nbsp| :diagtext:`refers before the beginning of the array`|
++-----------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wasm
+-----
+Synonym for `-Wasm-operand-widths`_.
+
+
+-Wasm-operand-widths
+--------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`value size does not match register size specified by the constraint and modifier`|
++-----------------------------------------------------------------------------------------------------------------------+
+
+
+-Wassign-enum
+-------------
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`integer constant not in range of enumerated type` |nbsp| :placeholder:`A`|
++---------------------------------------------------------------------------------------------------------------+
+
+
+-Wassume
+--------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`the argument to` |nbsp| :placeholder:`A` |nbsp| :diagtext:`has side effects that will be discarded`|
++-----------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wat-protocol
+-------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`@protocol is using a forward protocol declaration of` |nbsp| :placeholder:`A`|
++-------------------------------------------------------------------------------------------------------------------+
+
+
+-Watomic-memory-ordering
+------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`memory order argument to atomic operation is invalid`|
++-------------------------------------------------------------------------------------------+
+
+
+-Watomic-properties
+-------------------
+Controls `-Wcustom-atomic-properties`_, `-Wimplicit-atomic-properties`_.
+
+
+-Watomic-property-with-user-defined-accessor
+--------------------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------------------------------------------+--------------------+-----------------------------------------------+--------------------+
+|:warning:`warning:` |nbsp| :diagtext:`writable atomic property` |nbsp| :placeholder:`A` |nbsp| :diagtext:`cannot pair a synthesized` |nbsp| |+------------------+| |nbsp| :diagtext:`with a user defined` |nbsp| |+------------------+|
+| ||:diagtext:`getter`|| ||:diagtext:`getter`||
+| |+------------------+| |+------------------+|
+| ||:diagtext:`setter`|| ||:diagtext:`setter`||
+| |+------------------+| |+------------------+|
++--------------------------------------------------------------------------------------------------------------------------------------------+--------------------+-----------------------------------------------+--------------------+
+
+
+-Wattribute-packed-for-bitfield
+-------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'packed' attribute was ignored on bit-fields with single-byte alignment in older versions of GCC and Clang`|
++-------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wattributes
+------------
+This diagnostic is enabled by default.
+
+Controls `-Wignored-attributes`_, `-Wunknown-attributes`_.
+
+
+-Wauto-disable-vptr-sanitizer
+-----------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`implicitly disabling vptr sanitizer because rtti wasn't enabled`|
++------------------------------------------------------------------------------------------------------+
+
+
+-Wauto-import
+-------------
+**Diagnostic text:**
+
++-------------------------------------------------+---------------------------------+-------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`treating #`|+-------------------------------+| |nbsp| :diagtext:`as an import of module '`:placeholder:`B`:diagtext:`'`|
+| ||:diagtext:`include` || |
+| |+-------------------------------+| |
+| ||:diagtext:`import` || |
+| |+-------------------------------+| |
+| ||:diagtext:`include\_next` || |
+| |+-------------------------------+| |
+| ||:diagtext:`\_\_include\_macros`|| |
+| |+-------------------------------+| |
++-------------------------------------------------+---------------------------------+-------------------------------------------------------------------------+
+
+
+-Wauto-storage-class
+--------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'auto' storage class specifier is not permitted in C++11, and will not be supported in future releases`|
++---------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wauto-var-id
+-------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'auto' deduced as 'id' in declaration of` |nbsp| :placeholder:`A`|
++-------------------------------------------------------------------------------------------------------+
+
+
+-Wavailability
+--------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'unavailable' availability overrides all other availability information`|
++--------------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`unknown platform` |nbsp| :placeholder:`A` |nbsp| :diagtext:`in availability macro`|
++------------------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------+------------------------+------------------------------------------------------------------------------------------------------------------------------------------+------------------------+-------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`feature cannot be` |nbsp| |+----------------------+| |nbsp| :diagtext:`in` |nbsp| :placeholder:`B` |nbsp| :diagtext:`version` |nbsp| :placeholder:`C` |nbsp| :diagtext:`before it was` |nbsp| |+----------------------+| |nbsp| :diagtext:`in version` |nbsp| :placeholder:`E`:diagtext:`; attribute ignored`|
+| ||:diagtext:`introduced`|| ||:diagtext:`introduced`|| |
+| |+----------------------+| |+----------------------+| |
+| ||:diagtext:`deprecated`|| ||:diagtext:`deprecated`|| |
+| |+----------------------+| |+----------------------+| |
+| ||:diagtext:`obsoleted` || ||:diagtext:`obsoleted` || |
+| |+----------------------+| |+----------------------+| |
++----------------------------------------------------------------+------------------------+------------------------------------------------------------------------------------------------------------------------------------------+------------------------+-------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`use same version number separators '\_' or '.'; as in 'major\[.minor\[.subminor\]\]'`|
++---------------------------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`availability does not match previous declaration`|
++---------------------------------------------------------------------------------------+
+
++---------------------------+--------------------------------+--------------------------+-------------------------------+--------+-----------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| |+------------------------------+|:diagtext:`method` |nbsp| |+-----------------------------+| |nbsp| |+---------------------------------------------+| |nbsp| :diagtext:`on` |nbsp| :placeholder:`B` |nbsp| :diagtext:`(`:placeholder:`C` |nbsp| :diagtext:`vs.` |nbsp| :placeholder:`D`:diagtext:`)`|
+| || || ||:diagtext:`introduced after` || ||:diagtext:`the protocol method it implements`|| |
+| |+------------------------------+| |+-----------------------------+| |+---------------------------------------------+| |
+| ||:diagtext:`overriding` |nbsp| || ||:diagtext:`deprecated before`|| ||:diagtext:`overridden method` || |
+| |+------------------------------+| |+-----------------------------+| |+---------------------------------------------+| |
+| | | ||:diagtext:`obsoleted before` || | | |
+| | | |+-----------------------------+| | | |
++---------------------------+--------------------------------+--------------------------+-------------------------------+--------+-----------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+
+
++---------------------------+--------------------------------+---------------------------------------------------------------------------------------------------+-----------------------------------------------+--------------------------------+
+|:warning:`warning:` |nbsp| |+------------------------------+|:diagtext:`method cannot be unavailable on` |nbsp| :placeholder:`A` |nbsp| :diagtext:`when` |nbsp| |+---------------------------------------------+| |nbsp| :diagtext:`is available`|
+| || || ||:diagtext:`the protocol method it implements`|| |
+| |+------------------------------+| |+---------------------------------------------+| |
+| ||:diagtext:`overriding` |nbsp| || ||:diagtext:`its overridden method` || |
+| |+------------------------------+| |+---------------------------------------------+| |
++---------------------------+--------------------------------+---------------------------------------------------------------------------------------------------+-----------------------------------------------+--------------------------------+
+
+
+-Wbackend-plugin
+----------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
+The text of this diagnostic is not controlled by Clang.
+
+
+-Wbackslash-newline-escape
+--------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`backslash and newline separated by space`|
++-------------------------------------------------------------------------------+
+
+
+-Wbad-array-new-length
+----------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`array is too large (`:placeholder:`A` |nbsp| :diagtext:`elements)`|
++--------------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`array size is negative`|
++-------------------------------------------------------------+
+
+
+-Wbad-function-cast
+-------------------
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`cast from function call of type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to non-matching type` |nbsp| :placeholder:`B`|
++--------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wbind-to-temporary-copy
+------------------------
+Also controls `-Wc++98-compat-bind-to-temporary-copy`_.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------+
+|:warning:`warning:` |nbsp| :diagtext:`C++98 requires an accessible copy constructor for class` |nbsp| :placeholder:`C` |nbsp| :diagtext:`when binding a reference to a temporary; was` |nbsp| |+---------------------+|
+| ||:diagtext:`private` ||
+| |+---------------------+|
+| ||:diagtext:`protected`||
+| |+---------------------+|
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------+
+
++--------------------------------------------------------------------+-----------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`no viable constructor` |nbsp| |+---------------------------------------+| |nbsp| :diagtext:`of type` |nbsp| :placeholder:`B`:diagtext:`; C++98 requires a copy constructor when binding a reference to a temporary`|
+| ||:diagtext:`copying variable` || |
+| |+---------------------------------------+| |
+| ||:diagtext:`copying parameter` || |
+| |+---------------------------------------+| |
+| ||:diagtext:`returning object` || |
+| |+---------------------------------------+| |
+| ||:diagtext:`throwing object` || |
+| |+---------------------------------------+| |
+| ||:diagtext:`copying member subobject` || |
+| |+---------------------------------------+| |
+| ||:diagtext:`copying array element` || |
+| |+---------------------------------------+| |
+| ||:diagtext:`allocating object` || |
+| |+---------------------------------------+| |
+| ||:diagtext:`copying temporary` || |
+| |+---------------------------------------+| |
+| ||:diagtext:`initializing base subobject`|| |
+| |+---------------------------------------+| |
+| ||:diagtext:`initializing vector element`|| |
+| |+---------------------------------------+| |
+| ||:diagtext:`capturing value` || |
+| |+---------------------------------------+| |
++--------------------------------------------------------------------+-----------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wbitfield-constant-conversion
+------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`implicit truncation from` |nbsp| :placeholder:`C` |nbsp| :diagtext:`to bitfield changes value from` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B`|
++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wbitfield-width
+----------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------+
+|:warning:`warning:` |nbsp| :diagtext:`width of anonymous bit-field (`:placeholder:`A` |nbsp| :diagtext:`bits) exceeds width of its type; value will be truncated to` |nbsp| :placeholder:`B` |nbsp| :diagtext:`bit`|+-------------+|
+| || ||
+| |+-------------+|
+| ||:diagtext:`s`||
+| |+-------------+|
++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------+
+
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------+
+|:warning:`warning:` |nbsp| :diagtext:`width of bit-field` |nbsp| :placeholder:`A` |nbsp| :diagtext:`(`:placeholder:`B` |nbsp| :diagtext:`bits) exceeds the width of its type; value will be truncated to` |nbsp| :placeholder:`C` |nbsp| :diagtext:`bit`|+-------------+|
+| || ||
+| |+-------------+|
+| ||:diagtext:`s`||
+| |+-------------+|
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------+
+
+
+-Wbitwise-op-parentheses
+------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'`:placeholder:`A`:diagtext:`' within '`:placeholder:`B`:diagtext:`'`|
++-----------------------------------------------------------------------------------------------------------+
+
+
+-Wbool-conversion
+-----------------
+This diagnostic is enabled by default.
+
+Also controls `-Wpointer-bool-conversion`_, `-Wundefined-bool-conversion`_.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`initialization of pointer of type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to null from a constant boolean expression`|
++--------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wbool-conversions
+------------------
+Synonym for `-Wbool-conversion`_.
+
+
+-Wbraced-scalar-init
+--------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`braces around scalar initializer`|
++-----------------------------------------------------------------------+
+
+
+-Wbridge-cast
+-------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`bridges to` |nbsp| :placeholder:`B`:diagtext:`, not` |nbsp| :placeholder:`C`|
++------------------------------------------------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`cannot bridge to` |nbsp| :placeholder:`B`|
++-------------------------------------------------------------------------------------------------------+
+
+
+-Wbuiltin-macro-redefined
+-------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`redefining builtin macro`|
++---------------------------------------------------------------+
+
++---------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`undefining builtin macro`|
++---------------------------------------------------------------+
+
+
+-Wbuiltin-memcpy-chk-size
+-------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`will always overflow destination buffer`|
++------------------------------------------------------------------------------------------------------+
+
+
+-Wbuiltin-requires-header
+-------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`declaration of built-in function '`:placeholder:`B`:diagtext:`' requires inclusion of the header <`:placeholder:`A`:diagtext:`>`|
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wc++-compat
+------------
+**Diagnostic text:**
+
++---------------------------+---------------------------+--------------------+--------------------------------------------+---------------------------+--------------------------+
+|:warning:`warning:` |nbsp| |+-------------------------+|+------------------+| |nbsp| :diagtext:`has size 0 in C,` |nbsp| |+-------------------------+| |nbsp| :diagtext:`in C++`|
+| || |||:diagtext:`struct`|| ||:diagtext:`size 1` || |
+| |+-------------------------+|+------------------+| |+-------------------------+| |
+| ||:diagtext:`empty` |nbsp| |||:diagtext:`union` || ||:diagtext:`non-zero size`|| |
+| |+-------------------------+|+------------------+| |+-------------------------+| |
++---------------------------+---------------------------+--------------------+--------------------------------------------+---------------------------+--------------------------+
+
+
+-Wc++0x-compat
+--------------
+Synonym for `-Wc++11-compat`_.
+
+
+-Wc++0x-extensions
+------------------
+Synonym for `-Wc++11-extensions`_.
+
+
+-Wc++0x-narrowing
+-----------------
+Synonym for `-Wc++11-narrowing`_.
+
+
+-Wc++11-compat
+--------------
+Some of the diagnostics controlled by this flag are enabled by default.
+
+Also controls `-Wc++11-compat-deprecated-writable-strings`_, `-Wc++11-compat-reserved-user-defined-literal`_, `-Wc++11-narrowing`_, `-Wc++98-c++11-c++14-compat`_, `-Wc++98-c++11-compat`_.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------+------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`integer literal is too large to be represented in type 'long' and is subject to undefined behavior under C++98, interpreting as 'unsigned long'; this literal will` |nbsp| |+---------------------------------+| |nbsp| :diagtext:`in C++11 onwards`|
+| ||:diagtext:`have type 'long long'`|| |
+| |+---------------------------------+| |
+| ||:diagtext:`be ill-formed` || |
+| |+---------------------------------+| |
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------+------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'auto' storage class specifier is redundant and incompatible with C++11`|
++--------------------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`identifier after literal will be treated as a user-defined literal suffix in C++11`|
++-------------------------------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'`:placeholder:`A`:diagtext:`' is a keyword in C++11`|
++-------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`use of right-shift operator ('>>') in template argument will require parentheses in C++11`|
++--------------------------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`explicit instantiation cannot be 'inline'`|
++--------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`explicit instantiation of` |nbsp| :placeholder:`A` |nbsp| :diagtext:`must occur at global scope`|
++--------------------------------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`explicit instantiation of` |nbsp| :placeholder:`A` |nbsp| :diagtext:`not in a namespace enclosing` |nbsp| :placeholder:`B`|
++----------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`explicit instantiation of` |nbsp| :placeholder:`A` |nbsp| :diagtext:`must occur in namespace` |nbsp| :placeholder:`B`|
++-----------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------+------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`integer literal is too large to be represented in type 'long', interpreting as 'unsigned long' per C++98; this literal will` |nbsp| |+---------------------------------+| |nbsp| :diagtext:`in C++11 onwards`|
+| ||:diagtext:`have type 'long long'`|| |
+| |+---------------------------------+| |
+| ||:diagtext:`be ill-formed` || |
+| |+---------------------------------+| |
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------+------------------------------------+
+
+
+-Wc++11-compat-deprecated-writable-strings
+------------------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`conversion from string literal to` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is deprecated`|
++---------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wc++11-compat-pedantic
+-----------------------
+Controls `-Wc++98-c++11-c++14-compat-pedantic`_, `-Wc++98-c++11-compat-pedantic`_.
+
+
+-Wc++11-compat-reserved-user-defined-literal
+--------------------------------------------
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`identifier after literal will be treated as a reserved user-defined literal suffix in C++11`|
++----------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wc++11-extensions
+------------------
+Some of the diagnostics controlled by this flag are enabled by default.
+
+Also controls `-Wc++11-extra-semi`_, `-Wc++11-inline-namespace`_, `-Wc++11-long-long`_.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`alias declarations are a C++11 extension`|
++-------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------+----------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`implicit conversion from array size expression of type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| |+-----------------------+| |nbsp| :diagtext:`type` |nbsp| :placeholder:`C` |nbsp| :diagtext:`is a C++11 extension`|
+| ||:diagtext:`integral` || |
+| |+-----------------------+| |
+| ||:diagtext:`enumeration`|| |
+| |+-----------------------+| |
++---------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------+----------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'auto' type specifier is a C++11 extension`|
++---------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`enumeration types with a fixed underlying type are a C++11 extension`|
++-----------------------------------------------------------------------------------------------------------+
+
++---------------------------+-----------------------+--------------------------------------------------------------+
+|:warning:`warning:` |nbsp| |+---------------------+| |nbsp| :diagtext:`function definitions are a C++11 extension`|
+| ||:diagtext:`defaulted`|| |
+| |+---------------------+| |
+| ||:diagtext:`deleted` || |
+| |+---------------------+| |
++---------------------------+-----------------------+--------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`befriending enumeration type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is a C++11 extension`|
++-----------------------------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`commas at the end of enumerator lists are a C++11 extension`|
++--------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`explicit conversion functions are a C++11 extension`|
++------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`extern templates are a C++11 extension`|
++-----------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`range-based for loop is a C++11 extension`|
++--------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`generalized initializer lists are a C++11 extension`|
++------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`use of enumeration in a nested name specifier is a C++11 extension`|
++---------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`non-class friend type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is a C++11 extension`|
++----------------------------------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`in-class initialization of non-static data member is a C++11 extension`|
++-------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'`:placeholder:`A`:diagtext:`' keyword is a C++11 extension`|
++--------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`reference qualifiers on functions are a C++11 extension`|
++----------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`rvalue references are a C++11 extension`|
++------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`scoped enumerations are a C++11 extension`|
++--------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`static data member` |nbsp| :placeholder:`A` |nbsp| :diagtext:`in union is a C++11 extension`|
++----------------------------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------+----------------------+--------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`non-type template argument referring to` |nbsp| |+--------------------+| |nbsp| :placeholder:`B` |nbsp| :diagtext:`with internal linkage is a C++11 extension`|
+| ||:diagtext:`function`|| |
+| |+--------------------+| |
+| ||:diagtext:`object` || |
+| |+--------------------+| |
++--------------------------------------------------------------------------------------+----------------------+--------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'template' keyword outside of a template`|
++-------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`default template arguments for a function template are a C++11 extension`|
++---------------------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------+---------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`first declaration of` |nbsp| |+-------------------------------------+| |nbsp| :diagtext:`specialization of` |nbsp| :placeholder:`B` |nbsp| :diagtext:`outside namespace` |nbsp| :placeholder:`C` |nbsp| :diagtext:`is a C++11 extension`|
+| ||:diagtext:`class template` || |
+| |+-------------------------------------+| |
+| ||:diagtext:`class template partial` || |
+| |+-------------------------------------+| |
+| ||:diagtext:`variable template` || |
+| |+-------------------------------------+| |
+| ||:diagtext:`variable template partial`|| |
+| |+-------------------------------------+| |
+| ||:diagtext:`function template` || |
+| |+-------------------------------------+| |
+| ||:diagtext:`member function` || |
+| |+-------------------------------------+| |
+| ||:diagtext:`static data member` || |
+| |+-------------------------------------+| |
+| ||:diagtext:`member class` || |
+| |+-------------------------------------+| |
+| ||:diagtext:`member enumeration` || |
+| |+-------------------------------------+| |
++-------------------------------------------------------------------+---------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'typename' occurs outside of a template`|
++------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------------+-----------------------+-------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`unelaborated friend declaration is a C++11 extension; specify '`|+---------------------+|:diagtext:`' to befriend` |nbsp| :placeholder:`B`|
+| ||:diagtext:`struct` || |
+| |+---------------------+| |
+| ||:diagtext:`interface`|| |
+| |+---------------------+| |
+| ||:diagtext:`union` || |
+| |+---------------------+| |
+| ||:diagtext:`class` || |
+| |+---------------------+| |
+| ||:diagtext:`enum` || |
+| |+---------------------+| |
++------------------------------------------------------------------------------------------------------+-----------------------+-------------------------------------------------+
+
++-------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`variadic templates are a C++11 extension`|
++-------------------------------------------------------------------------------+
+
+
+-Wc++11-extra-semi
+------------------
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`extra ';' outside of a function is a C++11 extension`|
++-------------------------------------------------------------------------------------------+
+
+
+-Wc++11-inline-namespace
+------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`inline namespaces are a C++11 feature`|
++----------------------------------------------------------------------------+
+
+
+-Wc++11-long-long
+-----------------
+**Diagnostic text:**
+
++-----------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'long long' is a C++11 extension`|
++-----------------------------------------------------------------------+
+
+
+-Wc++11-narrowing
+-----------------
+Some of the diagnostics controlled by this flag are enabled by default.
+
+**Diagnostic text:**
+
++-----------------------+----------------------------------------+--------+--------------------------------------------------------------------------------------------------------------------------+
+|:error:`error:` |nbsp| |+--------------------------------------+| |nbsp| |+------------------------------------------------------------------------------------------------------------------------+|
+| ||:diagtext:`case value` || ||+--------------------------------------------------------------------------------------------------------------+ ||
+| |+--------------------------------------+| |||:diagtext:`cannot be narrowed from type` |nbsp| :placeholder:`C` |nbsp| :diagtext:`to` |nbsp| :placeholder:`D`| ||
+| ||:diagtext:`enumerator value` || ||+--------------------------------------------------------------------------------------------------------------+ ||
+| |+--------------------------------------+| |+------------------------------------------------------------------------------------------------------------------------+|
+| ||:diagtext:`non-type template argument`|| ||+----------------------------------------------------------------------------------------------------------------------+||
+| |+--------------------------------------+| |||:diagtext:`evaluates to` |nbsp| :placeholder:`C`:diagtext:`, which cannot be narrowed to type` |nbsp| :placeholder:`D`|||
+| ||:diagtext:`array size` || ||+----------------------------------------------------------------------------------------------------------------------+||
+| |+--------------------------------------+| |+------------------------------------------------------------------------------------------------------------------------+|
+| ||:diagtext:`constexpr if condition` || | |
+| |+--------------------------------------+| | |
++-----------------------+----------------------------------------+--------+--------------------------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:error:`error:` |nbsp| :diagtext:`constant expression evaluates to` |nbsp| :placeholder:`A` |nbsp| :diagtext:`which cannot be narrowed to type` |nbsp| :placeholder:`B`|
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:error:`error:` |nbsp| :diagtext:`type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`cannot be narrowed to` |nbsp| :placeholder:`B` |nbsp| :diagtext:`in initializer list`|
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:error:`error:` |nbsp| :diagtext:`non-constant-expression cannot be narrowed from type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B` |nbsp| :diagtext:`in initializer list`|
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`constant expression evaluates to` |nbsp| :placeholder:`A` |nbsp| :diagtext:`which cannot be narrowed to type` |nbsp| :placeholder:`B` |nbsp| :diagtext:`in C++11`|
++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`cannot be narrowed to` |nbsp| :placeholder:`B` |nbsp| :diagtext:`in initializer list in C++11`|
++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`non-constant-expression cannot be narrowed from type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B` |nbsp| :diagtext:`in initializer list in C++11`|
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wc++14-binary-literal
+----------------------
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`binary integer literals are a C++14 extension`|
++------------------------------------------------------------------------------------+
+
+
+-Wc++14-compat
+--------------
+Synonym for `-Wc++98-c++11-c++14-compat`_.
+
+
+-Wc++14-compat-pedantic
+-----------------------
+Synonym for `-Wc++98-c++11-c++14-compat-pedantic`_.
+
+
+-Wc++14-extensions
+------------------
+Some of the diagnostics controlled by this flag are enabled by default.
+
+Also controls `-Wc++14-binary-literal`_.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------+-------------------------+----------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`use of this statement in a constexpr` |nbsp| |+-----------------------+| |nbsp| :diagtext:`is a C++14 extension`|
+| ||:diagtext:`function` || |
+| |+-----------------------+| |
+| ||:diagtext:`constructor`|| |
+| |+-----------------------+| |
++-----------------------------------------------------------------------------------+-------------------------+----------------------------------------+
+
++------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`multiple return statements in constexpr function is a C++14 extension`|
++------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------+-------------------------+----------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`variable declaration in a constexpr` |nbsp| |+-----------------------+| |nbsp| :diagtext:`is a C++14 extension`|
+| ||:diagtext:`function` || |
+| |+-----------------------+| |
+| ||:diagtext:`constructor`|| |
+| |+-----------------------+| |
++----------------------------------------------------------------------------------+-------------------------+----------------------------------------+
+
++-----------------------------------------------------------------------------+-------------------------+----------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`type definition in a constexpr` |nbsp| |+-----------------------+| |nbsp| :diagtext:`is a C++14 extension`|
+| ||:diagtext:`function` || |
+| |+-----------------------+| |
+| ||:diagtext:`constructor`|| |
+| |+-----------------------+| |
++-----------------------------------------------------------------------------+-------------------------+----------------------------------------+
+
++---------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`use of the` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute is a C++14 extension`|
++---------------------------------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'decltype(auto)' type specifier is a C++14 extension`|
++-------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`initialized lambda captures are a C++14 extension`|
++----------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`variable templates are a C++14 extension`|
++-------------------------------------------------------------------------------+
+
+
+-Wc++1y-extensions
+------------------
+Synonym for `-Wc++14-extensions`_.
+
+
+-Wc++1z-compat
+--------------
+This diagnostic is enabled by default.
+
+Controls `-Wdeprecated-increment-bool`_, `-Wdeprecated-register`_.
+
+
+-Wc++1z-extensions
+------------------
+Some of the diagnostics controlled by this flag are enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`constexpr if is a C++1z extension`|
++------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'constexpr' on lambda expressions is a C++1z extension`|
++---------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`use of the` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute is a C++1z extension`|
++---------------------------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`decomposition declarations are a C++1z extension`|
++---------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`pack fold expression is a C++1z extension`|
++--------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'begin' and 'end' returning different types (`:placeholder:`A` |nbsp| :diagtext:`and` |nbsp| :placeholder:`B`:diagtext:`) is a C++1z extension`|
++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`hexadecimal floating literals are a C++1z feature`|
++----------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`inline variables are a C++1z extension`|
++-----------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`nested namespace definition is a C++1z extension; define each namespace separately`|
++-------------------------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`capture of '\*this' by copy is a C++1z extension`|
++---------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`static\_assert with no message is a C++1z extension`|
++------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`template template parameter using 'typename' is a C++1z extension`|
++--------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`default scope specifier for attributes is a C++1z extension`|
++--------------------------------------------------------------------------------------------------+
+
+
+-Wc++98-c++11-c++14-compat
+--------------------------
+**Diagnostic text:**
+
++------------------------------------------------------------+---------------------------+--------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`attributes on` |nbsp| |+-------------------------+| |nbsp| :diagtext:`declaration are incompatible with C++ standards before C++1z`|
+| ||:diagtext:`a namespace` || |
+| |+-------------------------+| |
+| ||:diagtext:`an enumerator`|| |
+| |+-------------------------+| |
++------------------------------------------------------------+---------------------------+--------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`constexpr if is incompatible with C++ standards before C++1z`|
++---------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`constexpr on lambda expressions is incompatible with C++ standards before C++1z`|
++----------------------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`decomposition declarations are incompatible with C++ standards before C++1z`|
++------------------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`pack fold expression is incompatible with C++ standards before C++1z`|
++-----------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`inline variables are incompatible with C++ standards before C++1z`|
++--------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`nested namespace definition is incompatible with C++ standards before C++1z`|
++------------------------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`by value capture of '\*this' is incompatible with C++ standards before C++1z`|
++-------------------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`static\_assert with no message is incompatible with C++ standards before C++1z`|
++---------------------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`template template parameter using 'typename' is incompatible with C++ standards before C++1z`|
++-----------------------------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`unicode literals are incompatible with C++ standards before C++1z`|
++--------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`default scope specifier for attributes is incompatible with C++ standards before C++1z`|
++-----------------------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'begin' and 'end' returning different types (`:placeholder:`A` |nbsp| :diagtext:`and` |nbsp| :placeholder:`B`:diagtext:`) is incompatible with C++ standards before C++1z`|
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wc++98-c++11-c++14-compat-pedantic
+-----------------------------------
+Also controls `-Wc++98-c++11-c++14-compat`_.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`hexidecimal floating literals are incompatible with C++ standards before C++1z`|
++---------------------------------------------------------------------------------------------------------------------+
+
+
+-Wc++98-c++11-compat
+--------------------
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------+-------------------------+-------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`use of this statement in a constexpr` |nbsp| |+-----------------------+| |nbsp| :diagtext:`is incompatible with C++ standards before C++14`|
+| ||:diagtext:`function` || |
+| |+-----------------------+| |
+| ||:diagtext:`constructor`|| |
+| |+-----------------------+| |
++-----------------------------------------------------------------------------------+-------------------------+-------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`multiple return statements in constexpr function is incompatible with C++ standards before C++14`|
++---------------------------------------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`constexpr function with no return statements is incompatible with C++ standards before C++14`|
++-----------------------------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------+-------------------------+-------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`variable declaration in a constexpr` |nbsp| |+-----------------------+| |nbsp| :diagtext:`is incompatible with C++ standards before C++14`|
+| ||:diagtext:`function` || |
+| |+-----------------------+| |
+| ||:diagtext:`constructor`|| |
+| |+-----------------------+| |
++----------------------------------------------------------------------------------+-------------------------+-------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------+-------------------------+-------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`type definition in a constexpr` |nbsp| |+-----------------------+| |nbsp| :diagtext:`is incompatible with C++ standards before C++14`|
+| ||:diagtext:`function` || |
+| |+-----------------------+| |
+| ||:diagtext:`constructor`|| |
+| |+-----------------------+| |
++-----------------------------------------------------------------------------+-------------------------+-------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'decltype(auto)' type specifier is incompatible with C++ standards before C++14`|
++----------------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`digit separators are incompatible with C++ standards before C++14`|
++--------------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`initialized lambda captures are incompatible with C++ standards before C++14`|
++-------------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`variable templates are incompatible with C++ standards before C++14`|
++----------------------------------------------------------------------------------------------------------+
+
+
+-Wc++98-c++11-compat-pedantic
+-----------------------------
+Also controls `-Wc++98-c++11-compat`_.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`binary integer literals are incompatible with C++ standards before C++14`|
++---------------------------------------------------------------------------------------------------------------+
+
+
+-Wc++98-compat
+--------------
+Also controls `-Wc++98-c++11-c++14-compat`_, `-Wc++98-c++11-compat`_, `-Wc++98-compat-local-type-template-args`_, `-Wc++98-compat-unnamed-type-template-args`_.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`alias declarations are incompatible with C++98`|
++-------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'alignas' is incompatible with C++98`|
++---------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`alignof expressions are incompatible with C++98`|
++--------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`C++11 attribute syntax is incompatible with C++98`|
++----------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'auto' type specifier is incompatible with C++98`|
++---------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'constexpr' specifier is incompatible with C++98`|
++---------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`constructor call from initializer list is incompatible with C++98`|
++--------------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'decltype' type specifier is incompatible with C++98`|
++-------------------------------------------------------------------------------------------+
+
++---------------------------+-----------------------+--------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| |+---------------------+| |nbsp| :diagtext:`function definitions are incompatible with C++98`|
+| ||:diagtext:`defaulted`|| |
+| |+---------------------+| |
+| ||:diagtext:`deleted` || |
+| |+---------------------+| |
++---------------------------+-----------------------+--------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`delegating constructors are incompatible with C++98`|
++------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`scalar initialized from empty initializer list is incompatible with C++98`|
++----------------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`enumeration types with a fixed underlying type are incompatible with C++98`|
++-----------------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`befriending enumeration type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is incompatible with C++98`|
++-----------------------------------------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`enumeration type in nested name specifier is incompatible with C++98`|
++-----------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`explicit conversion functions are incompatible with C++98`|
++------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`range-based for loop is incompatible with C++98`|
++--------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`friend declaration naming a member of the declaring class is incompatible with C++98`|
++---------------------------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`generalized initializer lists are incompatible with C++98`|
++------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`jump from this goto statement to its label is incompatible with C++98`|
++------------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`jump from this indirect goto statement to one of its possible targets is incompatible with C++98`|
++---------------------------------------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`initialization of initializer\_list object is incompatible with C++98`|
++------------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`inline namespaces are incompatible with C++98`|
++------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`lambda expressions are incompatible with C++98`|
++-------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'<::' is treated as digraph '<:' (aka '\[') followed by ':' in C++98`|
++-----------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`literal operators are incompatible with C++98`|
++------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`universal character name referring to a control character is incompatible with C++98`|
++---------------------------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`specifying character '`:placeholder:`A`:diagtext:`' with a universal character name is incompatible with C++98`|
++-----------------------------------------------------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`noexcept specifications are incompatible with C++98`|
++------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`noexcept expressions are incompatible with C++98`|
++---------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`use of non-static data member` |nbsp| :placeholder:`A` |nbsp| :diagtext:`in an unevaluated context is incompatible with C++98`|
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`non-class friend type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is incompatible with C++98`|
++----------------------------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`in-class initialization of non-static data members is incompatible with C++98`|
++--------------------------------------------------------------------------------------------------------------------+
+
++---------------------------+------------------------------+------------------------------------------------------------------------------------------------+--------------------------------------+----------------------------------------------+
+|:warning:`warning:` |nbsp| |+----------------------------+| |nbsp| :diagtext:`member` |nbsp| :placeholder:`B` |nbsp| :diagtext:`with a non-trivial` |nbsp| |+------------------------------------+| |nbsp| :diagtext:`is incompatible with C++98`|
+| ||:diagtext:`anonymous struct`|| ||:diagtext:`constructor` || |
+| |+----------------------------+| |+------------------------------------+| |
+| ||:diagtext:`union` || ||:diagtext:`copy constructor` || |
+| |+----------------------------+| |+------------------------------------+| |
+| | | ||:diagtext:`move constructor` || |
+| | | |+------------------------------------+| |
+| | | ||:diagtext:`copy assignment operator`|| |
+| | | |+------------------------------------+| |
+| | | ||:diagtext:`move assignment operator`|| |
+| | | |+------------------------------------+| |
+| | | ||:diagtext:`destructor` || |
+| | | |+------------------------------------+| |
++---------------------------+------------------------------+------------------------------------------------------------------------------------------------+--------------------------------------+----------------------------------------------+
+
++---------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'nullptr' is incompatible with C++98`|
++---------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'`:placeholder:`A`:diagtext:`' keyword is incompatible with C++98`|
++--------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------+----------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`passing object of trivial but non-POD type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`through variadic` |nbsp| |+-----------------------+| |nbsp| :diagtext:`is incompatible with C++98`|
+| ||:diagtext:`function` || |
+| |+-----------------------+| |
+| ||:diagtext:`block` || |
+| |+-----------------------+| |
+| ||:diagtext:`method` || |
+| |+-----------------------+| |
+| ||:diagtext:`constructor`|| |
+| |+-----------------------+| |
++-----------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------+----------------------------------------------+
+
++--------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`raw string literals are incompatible with C++98`|
++--------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`reference qualifiers on functions are incompatible with C++98`|
++----------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`reference initialized from initializer list is incompatible with C++98`|
++-------------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`rvalue references are incompatible with C++98`|
++------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`scoped enumerations are incompatible with C++98`|
++--------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`substitution failure due to access control is incompatible with C++98`|
++------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`static\_assert declarations are incompatible with C++98`|
++----------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`static data member` |nbsp| :placeholder:`A` |nbsp| :diagtext:`in union is incompatible with C++98`|
++----------------------------------------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`jump from switch statement to this case label is incompatible with C++98`|
++---------------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`redundant parentheses surrounding address non-type template argument are incompatible with C++98`|
++---------------------------------------------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`use of null pointer as non-type template argument is incompatible with C++98`|
++-------------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------+----------------------+--------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`non-type template argument referring to` |nbsp| |+--------------------+| |nbsp| :placeholder:`B` |nbsp| :diagtext:`with internal linkage is incompatible with C++98`|
+| ||:diagtext:`function`|| |
+| |+--------------------+| |
+| ||:diagtext:`object` || |
+| |+--------------------+| |
++--------------------------------------------------------------------------------------+----------------------+--------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`use of 'template' keyword outside of a template is incompatible with C++98`|
++-----------------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`default template arguments for a function template are incompatible with C++98`|
++---------------------------------------------------------------------------------------------------------------------+
+
++---------------------------+---------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| |+-------------------------------------+| |nbsp| :diagtext:`specialization of` |nbsp| :placeholder:`B` |nbsp| :diagtext:`outside namespace` |nbsp| :placeholder:`C` |nbsp| :diagtext:`is incompatible with C++98`|
+| ||:diagtext:`class template` || |
+| |+-------------------------------------+| |
+| ||:diagtext:`class template partial` || |
+| |+-------------------------------------+| |
+| ||:diagtext:`variable template` || |
+| |+-------------------------------------+| |
+| ||:diagtext:`variable template partial`|| |
+| |+-------------------------------------+| |
+| ||:diagtext:`function template` || |
+| |+-------------------------------------+| |
+| ||:diagtext:`member function` || |
+| |+-------------------------------------+| |
+| ||:diagtext:`static data member` || |
+| |+-------------------------------------+| |
+| ||:diagtext:`member class` || |
+| |+-------------------------------------+| |
+| ||:diagtext:`member enumeration` || |
+| |+-------------------------------------+| |
++---------------------------+---------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`trailing return types are incompatible with C++98`|
++----------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`consecutive right angle brackets are incompatible with C++98 (use '> >')`|
++---------------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`use of 'typename' outside of a template is incompatible with C++98`|
++---------------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------+-----------------------+------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`befriending` |nbsp| :placeholder:`B` |nbsp| :diagtext:`without '`|+---------------------+|:diagtext:`' keyword is incompatible with C++98`|
+| ||:diagtext:`struct` || |
+| |+---------------------+| |
+| ||:diagtext:`interface`|| |
+| |+---------------------+| |
+| ||:diagtext:`union` || |
+| |+---------------------+| |
+| ||:diagtext:`class` || |
+| |+---------------------+| |
+| ||:diagtext:`enum` || |
+| |+---------------------+| |
++-------------------------------------------------------------------------------------------------------+-----------------------+------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`using this character in an identifier is incompatible with C++98`|
++-------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`unicode literals are incompatible with C++98`|
++-----------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'`:placeholder:`A`:diagtext:`' type specifier is incompatible with C++98`|
++---------------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`inheriting constructors are incompatible with C++98`|
++------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`variadic templates are incompatible with C++98`|
++-------------------------------------------------------------------------------------+
+
+
+-Wc++98-compat-bind-to-temporary-copy
+-------------------------------------
+**Diagnostic text:**
+
++---------------------------+-----------------------------------------+----------------------------------------------------------------------------------------------------------------------------+------------------------------------------------+----------------------------+
+|:warning:`warning:` |nbsp| |+---------------------------------------+| |nbsp| :diagtext:`of type` |nbsp| :placeholder:`C` |nbsp| :diagtext:`when binding a reference to a temporary would` |nbsp| |+----------------------------------------------+| |nbsp| :diagtext:`in C++98`|
+| ||:diagtext:`copying variable` || ||:diagtext:`invoke an inaccessible constructor`|| |
+| |+---------------------------------------+| |+----------------------------------------------+| |
+| ||:diagtext:`copying parameter` || ||:diagtext:`find no viable constructor` || |
+| |+---------------------------------------+| |+----------------------------------------------+| |
+| ||:diagtext:`returning object` || ||:diagtext:`find ambiguous constructors` || |
+| |+---------------------------------------+| |+----------------------------------------------+| |
+| ||:diagtext:`throwing object` || ||:diagtext:`invoke a deleted constructor` || |
+| |+---------------------------------------+| |+----------------------------------------------+| |
+| ||:diagtext:`copying member subobject` || | | |
+| |+---------------------------------------+| | | |
+| ||:diagtext:`copying array element` || | | |
+| |+---------------------------------------+| | | |
+| ||:diagtext:`allocating object` || | | |
+| |+---------------------------------------+| | | |
+| ||:diagtext:`copying temporary` || | | |
+| |+---------------------------------------+| | | |
+| ||:diagtext:`initializing base subobject`|| | | |
+| |+---------------------------------------+| | | |
+| ||:diagtext:`initializing vector element`|| | | |
+| |+---------------------------------------+| | | |
++---------------------------+-----------------------------------------+----------------------------------------------------------------------------------------------------------------------------+------------------------------------------------+----------------------------+
+
+
+-Wc++98-compat-local-type-template-args
+---------------------------------------
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`local type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`as template argument is incompatible with C++98`|
++--------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wc++98-compat-pedantic
+-----------------------
+Also controls `-Wc++98-c++11-c++14-compat-pedantic`_, `-Wc++98-c++11-compat-pedantic`_, `-Wc++98-compat`_, `-Wc++98-compat-bind-to-temporary-copy`_.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------+----------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`implicit conversion from array size expression of type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| |+-----------------------+| |nbsp| :diagtext:`type` |nbsp| :placeholder:`C` |nbsp| :diagtext:`is incompatible with C++98`|
+| ||:diagtext:`integral` || |
+| |+-----------------------+| |
+| ||:diagtext:`enumeration`|| |
+| |+-----------------------+| |
++---------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------+----------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`cast between pointer-to-function and pointer-to-object is incompatible with C++98`|
++------------------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`empty macro arguments are incompatible with C++98`|
++----------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`commas at the end of enumerator lists are incompatible with C++98`|
++--------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`extern templates are incompatible with C++98`|
++-----------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'long long' is incompatible with C++98`|
++-----------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`C++98 requires newline at end of file`|
++----------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`#line number greater than 32767 is incompatible with C++98`|
++-------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`extra ';' outside of a function is incompatible with C++98`|
++-------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`variadic macros are incompatible with C++98`|
++----------------------------------------------------------------------------------+
+
+
+-Wc++98-compat-unnamed-type-template-args
+-----------------------------------------
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`unnamed type as template argument is incompatible with C++98`|
++---------------------------------------------------------------------------------------------------+
+
+
+-Wc11-extensions
+----------------
+**Diagnostic text:**
+
++---------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`anonymous unions are a C11 extension`|
++---------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is a C11-specific feature`|
++----------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`anonymous structs are a C11 extension`|
++----------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`generic selections are a C11-specific feature`|
++------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`\_Noreturn functions are a C11-specific feature`|
++--------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`\_Static\_assert is a C11-specific feature`|
++---------------------------------------------------------------------------------+
+
+
+-Wc99-compat
+------------
+Some of the diagnostics controlled by this flag are enabled by default.
+
+**Diagnostic text:**
+
++---------------------------+--------------------------------------------------------+--------------------------------------------+
+|:warning:`warning:` |nbsp| |+------------------------------------------------------+| |nbsp| :diagtext:`is incompatible with C99`|
+| ||:diagtext:`using this character in an identifier` || |
+| |+------------------------------------------------------+| |
+| ||:diagtext:`starting an identifier with this character`|| |
+| |+------------------------------------------------------+| |
++---------------------------+--------------------------------------------------------+--------------------------------------------+
+
++---------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`unicode literals are incompatible with C99`|
++---------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------+----------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`integer literal is too large to be represented in type 'long', interpreting as 'unsigned long' per C89; this literal will` |nbsp| |+---------------------------------+| |nbsp| :diagtext:`in C99 onwards`|
+| ||:diagtext:`have type 'long long'`|| |
+| |+---------------------------------+| |
+| ||:diagtext:`be ill-formed` || |
+| |+---------------------------------+| |
++------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------+----------------------------------+
+
+
+-Wc99-extensions
+----------------
+Some of the diagnostics controlled by this flag are enabled by default.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`initializer for aggregate is not a compile-time constant`|
++-----------------------------------------------------------------------------------------------+
+
++---------------------------+----------------------------------+------------------------------+-----------------------+----------------------------+
+|:warning:`warning:` |nbsp| |+--------------------------------+|:diagtext:`array size` |nbsp| |+---------------------+|:diagtext:`is a C99 feature`|
+| ||:diagtext:`qualifier in` |nbsp| || || || |
+| |+--------------------------------+| |+---------------------+| |
+| ||:diagtext:`static` |nbsp| || || || |
+| |+--------------------------------+| |+---------------------+| |
+| || || ||:diagtext:`'\[\*\] '`|| |
+| |+--------------------------------+| |+---------------------+| |
++---------------------------+----------------------------------+------------------------------+-----------------------+----------------------------+
+
++-----------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`compound literals are a C99-specific feature`|
++-----------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`flexible array members are a C99 feature`|
++-------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`variable declaration in for loop is a C99-specific feature`|
++-------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`ISO C99 requires whitespace after the macro name`|
++---------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`designated initializers are a C99 feature`|
++--------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`empty macro arguments are a C99 feature`|
++------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`commas at the end of enumerator lists are a C99-specific feature`|
++-------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`hexadecimal floating constants are a C99 feature`|
++---------------------------------------------------------------------------------------+
+
+
+-Wcast-align
+------------
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`cast from` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B` |nbsp| :diagtext:`increases required alignment from` |nbsp| :placeholder:`C` |nbsp| :diagtext:`to` |nbsp| :placeholder:`D`|
++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wcast-calling-convention
+-------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`cast between incompatible calling conventions '`:placeholder:`A`:diagtext:`' and '`:placeholder:`B`:diagtext:`'; calls through this pointer may abort at runtime`|
++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wcast-of-sel-type
+------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`cast of type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B` |nbsp| :diagtext:`is deprecated; use sel\_getName instead`|
++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wcast-qual
+-----------
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`cast from` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B` |nbsp| :diagtext:`drops` |nbsp| |+-----------------------------------------+|
+| ||:diagtext:`const and volatile qualifiers`||
+| |+-----------------------------------------+|
+| ||:diagtext:`const qualifier` ||
+| |+-----------------------------------------+|
+| ||:diagtext:`volatile qualifier` ||
+| |+-----------------------------------------+|
++-------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`cast from` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B` |nbsp| :diagtext:`must have all intermediate pointers const qualified to be safe`|
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wchar-align
+------------
+This diagnostic flag exists for GCC compatibility, and has no effect in Clang.
+
+-Wchar-subscripts
+-----------------
+**Diagnostic text:**
+
++------------------------------------------------------------+-------------------------+-------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`array section` |nbsp| |+-----------------------+| |nbsp| :diagtext:`is of type 'char'`|
+| ||:diagtext:`lower bound`|| |
+| |+-----------------------+| |
+| ||:diagtext:`length` || |
+| |+-----------------------+| |
++------------------------------------------------------------+-------------------------+-------------------------------------+
+
++------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`array subscript is of type 'char'`|
++------------------------------------------------------------------------+
+
+
+-Wclang-cl-pch
+--------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`support for '/Yc' with more than one source file not implemented yet; flag ignored`|
++-------------------------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`support for '/Yc' and '/Yu' with different filenames not implemented yet; flags ignored`|
++------------------------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`support for '`:placeholder:`A`:diagtext:`' without a filename not implemented yet; flag ignored`|
++--------------------------------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`support for '`:placeholder:`A`:diagtext:`' without a corresponding /FI flag not implemented yet; flag ignored`|
++----------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wclass-varargs
+---------------
+Some of the diagnostics controlled by this flag are enabled by default.
+
+Also controls `-Wnon-pod-varargs`_.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------------------------------+-------------------------+----------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`passing object of class type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`through variadic` |nbsp| |+-----------------------+|+--------------------------------------------------------------------+|
+| ||:diagtext:`function` ||| ||
+| |+-----------------------+|+--------------------------------------------------------------------+|
+| ||:diagtext:`block` |||+------------------------------------------------------------------+||
+| |+-----------------------+|||:diagtext:`; did you mean to call '`:placeholder:`D`:diagtext:`'?`|||
+| ||:diagtext:`method` |||+------------------------------------------------------------------+||
+| |+-----------------------+|+--------------------------------------------------------------------+|
+| ||:diagtext:`constructor`|| |
+| |+-----------------------+| |
++---------------------------------------------------------------------------------------------------------------------------------------+-------------------------+----------------------------------------------------------------------+
+
+
+-Wcomma
+-------
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`possible misuse of comma operator here`|
++-----------------------------------------------------------------------------+
+
+
+-Wcomment
+---------
+Some of the diagnostics controlled by this flag are enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`escaped newline between \*/ characters at block comment end`|
++--------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`// comments are not allowed in this language`|
++-----------------------------------------------------------------------------------+
+
++------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`multi-line // comment`|
++------------------------------------------------------------+
+
++-----------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'/\*' within block comment`|
++-----------------------------------------------------------------+
+
+
+-Wcomments
+----------
+Synonym for `-Wcomment`_.
+
+
+-Wcompare-distinct-pointer-types
+--------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`comparison of distinct pointer types`|
++---------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`comparison of distinct pointer types (`:placeholder:`A` |nbsp| :diagtext:`and` |nbsp| :placeholder:`B`:diagtext:`) uses non-standard composite pointer type` |nbsp| :placeholder:`C`|
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wcomplex-component-init
+------------------------
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`complex initialization specifying real and imaginary components is an extension`|
++----------------------------------------------------------------------------------------------------------------------+
+
+
+-Wconditional-type-mismatch
+---------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`pointer/integer type mismatch in conditional expression`|
++----------------------------------------------------------------------------------------------+
+
+
+-Wconditional-uninitialized
+---------------------------
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------------------+-------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`variable` |nbsp| :placeholder:`A` |nbsp| :diagtext:`may be uninitialized when` |nbsp| |+-----------------------------+|
+| ||:diagtext:`used here` ||
+| |+-----------------------------+|
+| ||:diagtext:`captured by block`||
+| |+-----------------------------+|
++----------------------------------------------------------------------------------------------------------------------------+-------------------------------+
+
+
+-Wconfig-macros
+---------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------+---------------------------------------------------------+
+|:warning:`warning:` |nbsp| |+----------------------+| |nbsp| :diagtext:`of configuration macro '`:placeholder:`B`:diagtext:`' has no effect on the import of '`:placeholder:`C`:diagtext:`'; pass '`|+------------------------------------------------+|:diagtext:`' on the command line to configure the module`|
+| ||:diagtext:`definition`|| ||+----------------------------------------------+|| |
+| |+----------------------+| |||:diagtext:`-D`:placeholder:`B`:diagtext:`=...`||| |
+| ||:diagtext:`#undef` || ||+----------------------------------------------+|| |
+| |+----------------------+| |+------------------------------------------------+| |
+| | | ||+------------------------------+ || |
+| | | |||:diagtext:`-U`:placeholder:`B`| || |
+| | | ||+------------------------------+ || |
+| | | |+------------------------------------------------+| |
++---------------------------+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------+---------------------------------------------------------+
+
+
+-Wconstant-conversion
+---------------------
+This diagnostic is enabled by default.
+
+Also controls `-Wbitfield-constant-conversion`_.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`implicit conversion from` |nbsp| :placeholder:`C` |nbsp| :diagtext:`to` |nbsp| :placeholder:`D` |nbsp| :diagtext:`changes value from` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B`|
++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wconstant-logical-operand
+--------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`use of logical '`:placeholder:`A`:diagtext:`' with constant operand`|
++----------------------------------------------------------------------------------------------------------+
+
+
+-Wconstexpr-not-const
+---------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'constexpr' non-static member function will not be implicitly 'const' in C++14; add 'const' to avoid a change in behavior`|
++----------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wconsumed
+----------
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`consumed analysis attribute is attached to member of class '`:placeholder:`A`:diagtext:`' which isn't marked as consumable`|
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`state of variable '`:placeholder:`A`:diagtext:`' must match at the entry and exit of loop`|
++--------------------------------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`parameter '`:placeholder:`A`:diagtext:`' not in expected state when the function returns: expected '`:placeholder:`B`:diagtext:`', observed '`:placeholder:`C`:diagtext:`'`|
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`argument not in expected state; expected '`:placeholder:`A`:diagtext:`', observed '`:placeholder:`B`:diagtext:`'`|
++-------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`return state set for an unconsumable type '`:placeholder:`A`:diagtext:`'`|
++---------------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`return value not in expected state; expected '`:placeholder:`A`:diagtext:`', observed '`:placeholder:`B`:diagtext:`'`|
++-----------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`invalid invocation of method '`:placeholder:`A`:diagtext:`' on object '`:placeholder:`B`:diagtext:`' while it is in the '`:placeholder:`C`:diagtext:`' state`|
++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`invalid invocation of method '`:placeholder:`A`:diagtext:`' on a temporary object while it is in the '`:placeholder:`B`:diagtext:`' state`|
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wconversion
+------------
+Some of the diagnostics controlled by this flag are enabled by default.
+
+Also controls `-Wbool-conversion`_, `-Wconstant-conversion`_, `-Wenum-conversion`_, `-Wfloat-conversion`_, `-Wint-conversion`_, `-Wliteral-conversion`_, `-Wnon-literal-null-conversion`_, `-Wnull-conversion`_, `-Wobjc-literal-conversion`_, `-Wshorten-64-to-32`_, `-Wsign-conversion`_, `-Wstring-conversion`_.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`implicit conversion discards imaginary component:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B`|
++--------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`implicit conversion loses floating-point precision:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B`|
++----------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`implicit conversion loses integer precision:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B`|
++---------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`implicit conversion turns vector to scalar:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B`|
++--------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`non-type template argument with value '`:placeholder:`A`:diagtext:`' converted to '`:placeholder:`B`:diagtext:`' for unsigned template parameter of type` |nbsp| :placeholder:`C`|
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`non-type template argument value '`:placeholder:`A`:diagtext:`' truncated to '`:placeholder:`B`:diagtext:`' for template parameter of type` |nbsp| :placeholder:`C`|
++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wconversion-null
+-----------------
+Synonym for `-Wnull-conversion`_.
+
+
+-Wcoreturn-without-coawait
+--------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'co\_return' used in a function that uses neither 'co\_await' nor 'co\_yield'`|
++--------------------------------------------------------------------------------------------------------------------+
+
+
+-Wcovered-switch-default
+------------------------
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`default label in switch which covers all enumeration values`|
++--------------------------------------------------------------------------------------------------+
+
+
+-Wcstring-format-directive
+--------------------------
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------------------+----------------------+--------------------------------------------------------------------------------------------+------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`using` |nbsp| :placeholder:`A` |nbsp| :diagtext:`directive in` |nbsp| |+--------------------+| |nbsp| :diagtext:`which is being passed as a formatting argument to the formatting` |nbsp| |+----------------------+|
+| ||:diagtext:`NSString`|| ||:diagtext:`method` ||
+| |+--------------------+| |+----------------------+|
+| ||:diagtext:`CFString`|| ||:diagtext:`CFfunction`||
+| |+--------------------+| |+----------------------+|
++------------------------------------------------------------------------------------------------------------+----------------------+--------------------------------------------------------------------------------------------+------------------------+
+
+
+-Wctor-dtor-privacy
+-------------------
+This diagnostic flag exists for GCC compatibility, and has no effect in Clang.
+
+-Wcuda-compat
+-------------
+Some of the diagnostics controlled by this flag are enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute parameter` |nbsp| :placeholder:`B` |nbsp| :diagtext:`is negative and will be ignored`|
++-------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`ignored 'inline' attribute on kernel function` |nbsp| :placeholder:`A`|
++------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`kernel function` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is a member function; this may not be accepted by nvcc`|
++--------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`argument to '#pragma unroll' should not be in parentheses in CUDA C/C++`|
++--------------------------------------------------------------------------------------------------------------+
+
+
+-Wcustom-atomic-properties
+--------------------------
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------------------------------+--------------------+----------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`atomic by default property` |nbsp| :placeholder:`A` |nbsp| :diagtext:`has a user defined` |nbsp| |+------------------+| |nbsp| :diagtext:`(property should be marked 'atomic' if this is intended)`|
+| ||:diagtext:`getter`|| |
+| |+------------------+| |
+| ||:diagtext:`setter`|| |
+| |+------------------+| |
++---------------------------------------------------------------------------------------------------------------------------------------+--------------------+----------------------------------------------------------------------------+
+
+
+-Wdangling-else
+---------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`add explicit braces to avoid dangling else`|
++---------------------------------------------------------------------------------+
+
+
+-Wdangling-field
+----------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`binding reference member` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to stack allocated parameter` |nbsp| :placeholder:`B`|
++---------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------+----------------------------------+----------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`binding reference` |nbsp| |+--------------------------------+|:diagtext:`member` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to a temporary value`|
+| || || |
+| |+--------------------------------+| |
+| ||:diagtext:`subobject of` |nbsp| || |
+| |+--------------------------------+| |
++----------------------------------------------------------------+----------------------------------+----------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`initializing pointer member` |nbsp| :placeholder:`A` |nbsp| :diagtext:`with the stack address of parameter` |nbsp| :placeholder:`B`|
++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wdangling-initializer-list
+---------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------------------+---------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`array backing the initializer list will be destroyed at the end of` |nbsp| |+-------------------------------+|
+| ||:diagtext:`the full-expression`||
+| |+-------------------------------+|
+| ||:diagtext:`the constructor` ||
+| |+-------------------------------+|
++-----------------------------------------------------------------------------------------------------------------+---------------------------------+
+
+
+-Wdate-time
+-----------
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`expansion of date or time macro is not reproducible`|
++------------------------------------------------------------------------------------------+
+
+
+-Wdealloc-in-category
+---------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`-dealloc is being overridden in a category`|
++---------------------------------------------------------------------------------+
+
+
+-Wdebug-compression-unavailable
+-------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`cannot compress debug sections (zlib not installed)`|
++------------------------------------------------------------------------------------------+
+
+
+-Wdeclaration-after-statement
+-----------------------------
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`ISO C90 forbids mixing declarations and code`|
++-----------------------------------------------------------------------------------+
+
+
+-Wdelegating-ctor-cycles
+------------------------
+This diagnostic is an error by default, but the flag ``-Wno-delegating-ctor-cycles`` can be used to disable the error.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------------------------------+
+|:error:`error:` |nbsp| :diagtext:`constructor for` |nbsp| :placeholder:`A` |nbsp| :diagtext:`creates a delegation cycle`|
++------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wdelete-incomplete
+-------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`cannot delete expression with pointer-to-'void' type` |nbsp| :placeholder:`A`|
++-------------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`deleting pointer to incomplete type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`may cause undefined behavior`|
++--------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wdelete-non-virtual-dtor
+-------------------------
+Some of the diagnostics controlled by this flag are enabled by default.
+
+**Diagnostic text:**
+
++---------------------------+------------------------+------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| |+----------------------+| |nbsp| :diagtext:`called on` |nbsp| :placeholder:`B` |nbsp| :diagtext:`that is abstract but has non-virtual destructor`|
+| ||:diagtext:`delete` || |
+| |+----------------------+| |
+| ||:diagtext:`destructor`|| |
+| |+----------------------+| |
++---------------------------+------------------------+------------------------------------------------------------------------------------------------------------------------+
+
++---------------------------+------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| |+----------------------+| |nbsp| :diagtext:`called on non-final` |nbsp| :placeholder:`B` |nbsp| :diagtext:`that has virtual functions but non-virtual destructor`|
+| ||:diagtext:`delete` || |
+| |+----------------------+| |
+| ||:diagtext:`destructor`|| |
+| |+----------------------+| |
++---------------------------+------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wdeprecated
+------------
+Some of the diagnostics controlled by this flag are enabled by default.
+
+Also controls `-Wdeprecated-attributes`_, `-Wdeprecated-declarations`_, `-Wdeprecated-increment-bool`_, `-Wdeprecated-register`_, `-Wdeprecated-writable-strings`_.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`-O4 is equivalent to -O3`|
++---------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`access declarations are deprecated; use using declarations instead`|
++---------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------+---------------------------------+-----------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`definition of implicit copy` |nbsp| |+-------------------------------+| |nbsp| :diagtext:`for` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is deprecated because it has a user-declared` |nbsp| |+------------------------------------------------------------+|
+| ||:diagtext:`constructor` || ||+------------------------+---------------------------------+||
+| |+-------------------------------+| |||:diagtext:`copy` |nbsp| |+-------------------------------+|||
+| ||:diagtext:`assignment operator`|| ||| ||:diagtext:`assignment operator`||||
+| |+-------------------------------+| ||| |+-------------------------------+|||
+| | | ||| ||:diagtext:`constructor` ||||
+| | | ||| |+-------------------------------+|||
+| | | ||+------------------------+---------------------------------+||
+| | | |+------------------------------------------------------------+|
+| | | ||:diagtext:`destructor` ||
+| | | |+------------------------------------------------------------+|
++--------------------------------------------------------------------------+---------------------------------+-----------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`out-of-line definition of constexpr static data member is redundant in C++17 and is deprecated`|
++-------------------------------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`argument '`:placeholder:`A`:diagtext:`' is deprecated, use '`:placeholder:`B`:diagtext:`' instead`|
++----------------------------------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`treating '`:placeholder:`A`:diagtext:`' input as '`:placeholder:`B`:diagtext:`' when in C++ mode, this behavior is deprecated`|
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`dynamic exception specifications are deprecated`|
++--------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`OpenCL version` |nbsp| :placeholder:`A` |nbsp| :diagtext:`does not support the option '`:placeholder:`B`:diagtext:`'`|
++-----------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`Use of 'long' with '\_\_vector' is deprecated`|
++------------------------------------------------------------------------------------+
+
+
+-Wdeprecated-attributes
+-----------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`specifying vector types with the 'mode' attribute is deprecated; use the 'vector\_size' attribute instead`|
++------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wdeprecated-declarations
+-------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`use of C-style parameters in Objective-C method declarations is deprecated`|
++-----------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is deprecated`|
++----------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`may be deprecated because the receiver type is unknown`|
++---------------------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is deprecated:` |nbsp| :placeholder:`B`|
++-----------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`property access is using` |nbsp| :placeholder:`A` |nbsp| :diagtext:`method which is deprecated`|
++-------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wdeprecated-implementations
+----------------------------
+**Diagnostic text:**
+
++----------------------------------------------------------------------+----------------------+
+|:warning:`warning:` |nbsp| :diagtext:`Implementing deprecated` |nbsp| |+--------------------+|
+| ||:diagtext:`method` ||
+| |+--------------------+|
+| ||:diagtext:`class` ||
+| |+--------------------+|
+| ||:diagtext:`category`||
+| |+--------------------+|
++----------------------------------------------------------------------+----------------------+
+
+
+-Wdeprecated-increment-bool
+---------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`incrementing expression of type bool is deprecated and incompatible with C++1z`|
++---------------------------------------------------------------------------------------------------------------------+
+
+
+-Wdeprecated-objc-isa-usage
+---------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`assignment to Objective-C's isa is deprecated in favor of object\_setClass()`|
++-------------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`direct access to Objective-C's isa is deprecated in favor of object\_getClass()`|
++----------------------------------------------------------------------------------------------------------------------+
+
+
+-Wdeprecated-objc-pointer-introspection
+---------------------------------------
+This diagnostic is enabled by default.
+
+Also controls `-Wdeprecated-objc-pointer-introspection-performSelector`_.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`bitmasking for introspection of Objective-C object pointers is strongly discouraged`|
++--------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wdeprecated-objc-pointer-introspection-performSelector
+-------------------------------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`bitmasking for introspection of Objective-C object pointers is strongly discouraged`|
++--------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wdeprecated-register
+---------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'register' storage class specifier is deprecated and incompatible with C++1z`|
++-------------------------------------------------------------------------------------------------------------------+
+
+
+-Wdeprecated-writable-strings
+-----------------------------
+Synonym for `-Wc++11-compat-deprecated-writable-strings`_.
+
+
+-Wdirect-ivar-access
+--------------------
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`instance variable` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is being directly accessed`|
++------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wdisabled-macro-expansion
+--------------------------
+**Diagnostic text:**
+
++----------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`disabled expansion of recursive macro`|
++----------------------------------------------------------------------------+
+
+
+-Wdisabled-optimization
+-----------------------
+This diagnostic flag exists for GCC compatibility, and has no effect in Clang.
+
+-Wdiscard-qual
+--------------
+This diagnostic flag exists for GCC compatibility, and has no effect in Clang.
+
+-Wdistributed-object-modifiers
+------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`conflicting distributed object modifiers on parameter type in implementation of` |nbsp| :placeholder:`A`|
++----------------------------------------------------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`conflicting distributed object modifiers on return type in implementation of` |nbsp| :placeholder:`A`|
++-------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wdiv-by-zero
+-------------
+Synonym for `-Wdivision-by-zero`_.
+
+
+-Wdivision-by-zero
+------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------+-----------------------+----------------------------------------+
+|:warning:`warning:` |nbsp| |+---------------------+| |nbsp| :diagtext:`by zero is undefined`|
+| ||:diagtext:`remainder`|| |
+| |+---------------------+| |
+| ||:diagtext:`division` || |
+| |+---------------------+| |
++---------------------------+-----------------------+----------------------------------------+
+
+
+-Wdll-attribute-on-redeclaration
+--------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`redeclaration of` |nbsp| :placeholder:`A` |nbsp| :diagtext:`should not add` |nbsp| :placeholder:`B` |nbsp| :diagtext:`attribute`|
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wdllexport-explicit-instantiation-decl
+---------------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`explicit instantiation declaration should not be 'dllexport'`|
++---------------------------------------------------------------------------------------------------+
+
+
+-Wdllimport-static-field-def
+----------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`definition of dllimport static field`|
++---------------------------------------------------------------------------+
+
+
+-Wdocumentation
+---------------
+Also controls `-Wdocumentation-deprecated-sync`_, `-Wdocumentation-html`_.
+
+**Diagnostic text:**
+
++----------------------------------------+----------------+-----------------------+------------------------------------------------------------------------+-----------------------+-------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'`|+--------------+|+---------------------+|:diagtext:`' command should not be used in a comment attached to a non-`|+---------------------+| |nbsp| :diagtext:`declaration`|
+| ||:diagtext:`\\`|||:diagtext:`class` || ||:diagtext:`class` || |
+| |+--------------+|+---------------------+| |+---------------------+| |
+| ||:diagtext:`@` |||:diagtext:`interface`|| ||:diagtext:`interface`|| |
+| |+--------------+|+---------------------+| |+---------------------+| |
+| | ||:diagtext:`protocol` || ||:diagtext:`protocol` || |
+| | |+---------------------+| |+---------------------+| |
+| | ||:diagtext:`struct` || ||:diagtext:`struct` || |
+| | |+---------------------+| |+---------------------+| |
+| | ||:diagtext:`union` || ||:diagtext:`union` || |
+| | |+---------------------+| |+---------------------+| |
++----------------------------------------+----------------+-----------------------+------------------------------------------------------------------------+-----------------------+-------------------------------+
+
++-----------------------------------------------------------+----------------+-----------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`duplicated command '`|+--------------+|:placeholder:`B`:diagtext:`'`|
+| ||:diagtext:`\\`|| |
+| |+--------------+| |
+| ||:diagtext:`@` || |
+| |+--------------+| |
++-----------------------------------------------------------+----------------+-----------------------------+
+
++------------------------------------------------------------------+----------------+-------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`empty paragraph passed to '`|+--------------+|:placeholder:`B`:diagtext:`' command`|
+| ||:diagtext:`\\`|| |
+| |+--------------+| |
+| ||:diagtext:`@` || |
+| |+--------------+| |
++------------------------------------------------------------------+----------------+-------------------------------------+
+
++----------------------------------------+----------------+--------------------------+---------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'`|+--------------+|+------------------------+|:diagtext:`' command should not be used in a comment attached to a non-container declaration`|
+| ||:diagtext:`\\`|||:diagtext:`classdesign` || |
+| |+--------------+|+------------------------+| |
+| ||:diagtext:`@` |||:diagtext:`coclass` || |
+| |+--------------+|+------------------------+| |
+| | ||:diagtext:`dependency` || |
+| | |+------------------------+| |
+| | ||:diagtext:`helper` || |
+| | |+------------------------+| |
+| | ||:diagtext:`helperclass` || |
+| | |+------------------------+| |
+| | ||:diagtext:`helps` || |
+| | |+------------------------+| |
+| | ||:diagtext:`instancesize`|| |
+| | |+------------------------+| |
+| | ||:diagtext:`ownership` || |
+| | |+------------------------+| |
+| | ||:diagtext:`performance` || |
+| | |+------------------------+| |
+| | ||:diagtext:`security` || |
+| | |+------------------------+| |
+| | ||:diagtext:`superclass` || |
+| | |+------------------------+| |
++----------------------------------------+----------------+--------------------------+---------------------------------------------------------------------------------------------+
+
++----------------------------------------+----------------+---------------------------+---------------------------------------------------------------------+-----------------------------------+-------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'`|+--------------+|+-------------------------+|:diagtext:`' command should be used in a comment attached to` |nbsp| |+---------------------------------+| |nbsp| :diagtext:`declaration`|
+| ||:diagtext:`\\`|||:diagtext:`function` || ||:diagtext:`a function` || |
+| |+--------------+|+-------------------------+| |+---------------------------------+| |
+| ||:diagtext:`@` |||:diagtext:`functiongroup`|| ||:diagtext:`a function` || |
+| |+--------------+|+-------------------------+| |+---------------------------------+| |
+| | ||:diagtext:`method` || ||:diagtext:`an Objective-C method`|| |
+| | |+-------------------------+| |+---------------------------------+| |
+| | ||:diagtext:`methodgroup` || ||:diagtext:`an Objective-C method`|| |
+| | |+-------------------------+| |+---------------------------------+| |
+| | ||:diagtext:`callback` || ||:diagtext:`a pointer to function`|| |
+| | |+-------------------------+| |+---------------------------------+| |
++----------------------------------------+----------------+---------------------------+---------------------------------------------------------------------+-----------------------------------+-------------------------------+
+
++-------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`HTML start tag prematurely ended, expected attribute name or '>'`|
++-------------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`expected quoted string after equals sign`|
++-------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`parameter '`:placeholder:`A`:diagtext:`' is already documented`|
++-----------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`unrecognized parameter passing direction, valid directions are '\[in\]', '\[out\]' and '\[in,out\]'`|
++------------------------------------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------+----------------+-------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'`|+--------------+|:diagtext:`param' command used in a comment that is not attached to a function declaration`|
+| ||:diagtext:`\\`|| |
+| |+--------------+| |
+| ||:diagtext:`@` || |
+| |+--------------+| |
++----------------------------------------+----------------+-------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`parameter '`:placeholder:`A`:diagtext:`' not found in the function declaration`|
++---------------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------+----------------+-------------------------------------------------------------------------------------+-------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'`|+--------------+|:placeholder:`B`:diagtext:`' command used in a comment that is attached to a` |nbsp| |+-----------------------------------+|
+| ||:diagtext:`\\`|| ||:diagtext:`function returning void`||
+| |+--------------+| |+-----------------------------------+|
+| ||:diagtext:`@` || ||:diagtext:`constructor` ||
+| |+--------------+| |+-----------------------------------+|
+| | | ||:diagtext:`destructor` ||
+| | | |+-----------------------------------+|
+| | | ||:diagtext:`method returning void` ||
+| | | |+-----------------------------------+|
++----------------------------------------+----------------+-------------------------------------------------------------------------------------+-------------------------------------+
+
++----------------------------------------+----------------+----------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'`|+--------------+|:placeholder:`B`:diagtext:`' command used in a comment that is not attached to a function or method declaration`|
+| ||:diagtext:`\\`|| |
+| |+--------------+| |
+| ||:diagtext:`@` || |
+| |+--------------+| |
++----------------------------------------+----------------+----------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`template parameter '`:placeholder:`A`:diagtext:`' is already documented`|
++--------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------+----------------+--------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'`|+--------------+|:diagtext:`tparam' command used in a comment that is not attached to a template declaration`|
+| ||:diagtext:`\\`|| |
+| |+--------------+| |
+| ||:diagtext:`@` || |
+| |+--------------+| |
++----------------------------------------+----------------+--------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`template parameter '`:placeholder:`A`:diagtext:`' not found in the template declaration`|
++------------------------------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`not a Doxygen trailing comment`|
++---------------------------------------------------------------------+
+
++----------------------------------------+----------------+------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'`|+--------------+|:placeholder:`B`:diagtext:`' command does not terminate a verbatim text block`|
+| ||:diagtext:`\\`|| |
+| |+--------------+| |
+| ||:diagtext:`@` || |
+| |+--------------+| |
++----------------------------------------+----------------+------------------------------------------------------------------------------+
+
+
+-Wdocumentation-deprecated-sync
+-------------------------------
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`declaration is marked with '\\deprecated' command but does not have a deprecation attribute`|
++----------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wdocumentation-html
+--------------------
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`HTML end tag '`:placeholder:`A`:diagtext:`' is forbidden`|
++-----------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`HTML end tag does not match any start tag`|
++--------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`HTML tag '`:placeholder:`A`:diagtext:`' requires an end tag`|
++--------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`HTML start tag '`:placeholder:`A`:diagtext:`' closed by '`:placeholder:`B`:diagtext:`'`|
++-----------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wdocumentation-pedantic
+------------------------
+Also controls `-Wdocumentation-unknown-command`_.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`whitespace is not allowed in parameter passing direction`|
++-----------------------------------------------------------------------------------------------+
+
+
+-Wdocumentation-unknown-command
+-------------------------------
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`unknown command tag name '`:placeholder:`A`:diagtext:`'; did you mean '`:placeholder:`B`:diagtext:`'?`|
++--------------------------------------------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`unknown command tag name`|
++---------------------------------------------------------------+
+
+
+-Wdollar-in-identifier-extension
+--------------------------------
+**Diagnostic text:**
+
++--------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'$' in identifier`|
++--------------------------------------------------------+
+
+
+-Wdouble-promotion
+------------------
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`implicit conversion increases floating-point precision:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B`|
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wduplicate-decl-specifier
+--------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`duplicate '`:placeholder:`A`:diagtext:`' declaration specifier`|
++-----------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`duplicate '`:placeholder:`A`:diagtext:`' declaration specifier`|
++-----------------------------------------------------------------------------------------------------+
+
+
+-Wduplicate-enum
+----------------
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`element` |nbsp| :placeholder:`A` |nbsp| :diagtext:`has been implicitly assigned` |nbsp| :placeholder:`B` |nbsp| :diagtext:`which another element has been assigned`|
++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wduplicate-method-arg
+----------------------
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`redeclaration of method parameter` |nbsp| :placeholder:`A`|
++------------------------------------------------------------------------------------------------+
+
+
+-Wduplicate-method-match
+------------------------
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`multiple declarations of method` |nbsp| :placeholder:`A` |nbsp| :diagtext:`found and ignored`|
++-----------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wdynamic-class-memaccess
+-------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------+-------------------------------+------------------------------------------------------------------------------------------------+----------------------------------------+---------------------------------------------------------------------------------------------+-------------------------+
+|:warning:`warning:` |nbsp| |+-----------------------------+| |nbsp| :diagtext:`this` |nbsp| :placeholder:`B` |nbsp| :diagtext:`call is a pointer to` |nbsp| |+--------------------------------------+|:diagtext:`dynamic class` |nbsp| :placeholder:`D`:diagtext:`; vtable pointer will be` |nbsp| |+-----------------------+|
+| ||:diagtext:`destination for` || || || ||:diagtext:`overwritten`||
+| |+-----------------------------+| |+--------------------------------------+| |+-----------------------+|
+| ||:diagtext:`source of` || ||:diagtext:`class containing a` |nbsp| || ||:diagtext:`copied` ||
+| |+-----------------------------+| |+--------------------------------------+| |+-----------------------+|
+| ||:diagtext:`first operand of` || | | ||:diagtext:`moved` ||
+| |+-----------------------------+| | | |+-----------------------+|
+| ||:diagtext:`second operand of`|| | | ||:diagtext:`compared` ||
+| |+-----------------------------+| | | |+-----------------------+|
++---------------------------+-------------------------------+------------------------------------------------------------------------------------------------+----------------------------------------+---------------------------------------------------------------------------------------------+-------------------------+
+
+
+-Weffc++
+--------
+Synonym for `-Wnon-virtual-dtor`_.
+
+
+-Wembedded-directive
+--------------------
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`embedding a directive within macro arguments has undefined behavior`|
++----------------------------------------------------------------------------------------------------------+
+
+
+-Wempty-body
+------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`for loop has empty body`|
++--------------------------------------------------------------+
+
++------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`if statement has empty body`|
++------------------------------------------------------------------+
+
++--------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`range-based for loop has empty body`|
++--------------------------------------------------------------------------+
+
++----------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`switch statement has empty body`|
++----------------------------------------------------------------------+
+
++----------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`while loop has empty body`|
++----------------------------------------------------------------+
+
+
+-Wempty-decomposition
+---------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`ISO C++1z does not allow a decomposition group to be empty`|
++-------------------------------------------------------------------------------------------------+
+
+
+-Wempty-translation-unit
+------------------------
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`ISO C requires a translation unit to contain at least one declaration`|
++------------------------------------------------------------------------------------------------------------+
+
+
+-Wencode-type
+-------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`encoding of` |nbsp| :placeholder:`A` |nbsp| :diagtext:`type is incomplete because` |nbsp| :placeholder:`B` |nbsp| :diagtext:`component has unknown encoding`|
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wendif-labels
+--------------
+Synonym for `-Wextra-tokens`_.
+
+
+-Wenum-compare
+--------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`comparison of two values with different enumeration types`|
++------------------------------------------------------------------------------------------------+
+
+
+-Wenum-conversion
+-----------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`implicit conversion from enumeration type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to different enumeration type` |nbsp| :placeholder:`B`|
++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wenum-too-large
+----------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`enumeration values exceed range of largest integer`|
++-----------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`incremented enumerator value` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is not representable in the largest integer type`|
++---------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wexceptions
+------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------+-------------------------+--------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`cannot refer to a non-static member from the handler of a` |nbsp| |+-----------------------+| |nbsp| :diagtext:`function try block`|
+| ||:diagtext:`constructor`|| |
+| |+-----------------------+| |
+| ||:diagtext:`destructor` || |
+| |+-----------------------+| |
++--------------------------------------------------------------------------------------------------------+-------------------------+--------------------------------------+
+
++-------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`exception of type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`will be caught by earlier handler`|
++-------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wexit-time-destructors
+-----------------------
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`declaration requires an exit-time destructor`|
++-----------------------------------------------------------------------------------+
+
+
+-Wexpansion-to-defined
+----------------------
+Some of the diagnostics controlled by this flag are enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`macro expansion producing 'defined' has undefined behavior`|
++-------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`macro expansion producing 'defined' has undefined behavior`|
++-------------------------------------------------------------------------------------------------+
+
+
+-Wexplicit-initialize-call
+--------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`explicit call to +initialize results in duplicate call to +initialize`|
++------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`explicit call to \[super initialize\] should only be in implementation of +initialize`|
++----------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wexplicit-ownership-type
+-------------------------
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`method parameter of type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`with no explicit ownership`|
++-------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wextended-offsetof
+-------------------
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`using extended field designator is an extension`|
++--------------------------------------------------------------------------------------+
+
+
+-Wextern-c-compat
+-----------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------+---------------------------+--------------------+--------------------------------------------+---------------------------+--------------------------+
+|:warning:`warning:` |nbsp| |+-------------------------+|+------------------+| |nbsp| :diagtext:`has size 0 in C,` |nbsp| |+-------------------------+| |nbsp| :diagtext:`in C++`|
+| || |||:diagtext:`struct`|| ||:diagtext:`size 1` || |
+| |+-------------------------+|+------------------+| |+-------------------------+| |
+| ||:diagtext:`empty` |nbsp| |||:diagtext:`union` || ||:diagtext:`non-zero size`|| |
+| |+-------------------------+|+------------------+| |+-------------------------+| |
++---------------------------+---------------------------+--------------------+--------------------------------------------+---------------------------+--------------------------+
+
+
+-Wextern-initializer
+--------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'extern' variable has an initializer`|
++---------------------------------------------------------------------------+
+
+
+-Wextra
+-------
+Some of the diagnostics controlled by this flag are enabled by default.
+
+Controls `-Wignored-qualifiers`_, `-Winitializer-overrides`_, `-Wmissing-field-initializers`_, `-Wmissing-method-return-type`_, `-Wsemicolon-before-method-body`_, `-Wsign-compare`_, `-Wunused-parameter`_.
+
+
+-Wextra-qualification
+---------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`extra qualification on member` |nbsp| :placeholder:`A`|
++--------------------------------------------------------------------------------------------+
+
+
+-Wextra-semi
+------------
+Also controls `-Wc++11-extra-semi`_.
+
+**Diagnostic text:**
+
++--------------------------------------------------------+------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`extra ';'` |nbsp| |+----------------------------------------------+|
+| ||:diagtext:`outside of a function` ||
+| |+----------------------------------------------+|
+| ||+--------------------------------------------+||
+| |||:diagtext:`inside a` |nbsp| :placeholder:`B`|||
+| ||+--------------------------------------------+||
+| |+----------------------------------------------+|
+| ||:diagtext:`inside instance variable list` ||
+| |+----------------------------------------------+|
+| ||:diagtext:`after member function definition` ||
+| |+----------------------------------------------+|
++--------------------------------------------------------+------------------------------------------------+
+
++---------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`extra ';' after member function definition`|
++---------------------------------------------------------------------------------+
+
+
+-Wextra-tokens
+--------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`extra tokens at end of #`:placeholder:`A` |nbsp| :diagtext:`directive`|
++------------------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`extra tokens at the end of '#pragma omp` |nbsp| :placeholder:`A`:diagtext:`' are ignored`|
++-------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wfallback
+----------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`falling back to` |nbsp| :placeholder:`A`|
++------------------------------------------------------------------------------+
+
+
+-Wflag-enum
+-----------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`enumeration value` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is out of range of flags in enumeration type` |nbsp| :placeholder:`B`|
++------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wflexible-array-extensions
+---------------------------
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`may not be used as an array element due to flexible array member`|
++-------------------------------------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`may not be nested in a struct due to flexible array member`|
++-------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wfloat-conversion
+------------------
+Also controls `-Wfloat-overflow-conversion`_, `-Wfloat-zero-conversion`_.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`implicit conversion turns floating-point number into integer:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B`|
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wfloat-equal
+-------------
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`comparing floating point with == or != is unsafe`|
++---------------------------------------------------------------------------------------+
+
+
+-Wfloat-overflow-conversion
+---------------------------
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`implicit conversion of out of range value from` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B` |nbsp| :diagtext:`changes value from` |nbsp| :placeholder:`C` |nbsp| :diagtext:`to` |nbsp| :placeholder:`D`|
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wfloat-zero-conversion
+-----------------------
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`implicit conversion from` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B` |nbsp| :diagtext:`changes non-zero value from` |nbsp| :placeholder:`C` |nbsp| :diagtext:`to` |nbsp| :placeholder:`D`|
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wfor-loop-analysis
+-------------------
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------+-------------------------+----------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`variable` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is` |nbsp| |+-----------------------+| |nbsp| :diagtext:`both in the loop header and in the loop body`|
+| ||:diagtext:`decremented`|| |
+| |+-----------------------+| |
+| ||:diagtext:`incremented`|| |
+| |+-----------------------+| |
++-----------------------------------------------------------------------------------------------------+-------------------------+----------------------------------------------------------------+
+
++-----------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`variable`|+----------------------------------------------------------------------------------------------------------------------------------------------------------+| |nbsp| :diagtext:`used in loop condition not modified in loop body`|
+| ||:diagtext:`s` || |
+| |+----------------------------------------------------------------------------------------------------------------------------------------------------------+| |
+| ||+------------------------+ || |
+| ||| |nbsp| :placeholder:`B`| || |
+| ||+------------------------+ || |
+| |+----------------------------------------------------------------------------------------------------------------------------------------------------------+| |
+| ||+------------------------------------------------------------------------------------+ || |
+| |||:diagtext:`s` |nbsp| :placeholder:`B` |nbsp| :diagtext:`and` |nbsp| :placeholder:`C`| || |
+| ||+------------------------------------------------------------------------------------+ || |
+| |+----------------------------------------------------------------------------------------------------------------------------------------------------------+| |
+| ||+-------------------------------------------------------------------------------------------------------------------+ || |
+| |||:diagtext:`s` |nbsp| :placeholder:`B`:diagtext:`,` |nbsp| :placeholder:`C`:diagtext:`, and` |nbsp| :placeholder:`D`| || |
+| ||+-------------------------------------------------------------------------------------------------------------------+ || |
+| |+----------------------------------------------------------------------------------------------------------------------------------------------------------+| |
+| ||+--------------------------------------------------------------------------------------------------------------------------------------------------------+|| |
+| |||:diagtext:`s` |nbsp| :placeholder:`B`:diagtext:`,` |nbsp| :placeholder:`C`:diagtext:`,` |nbsp| :placeholder:`D`:diagtext:`, and` |nbsp| :placeholder:`E`||| |
+| ||+--------------------------------------------------------------------------------------------------------------------------------------------------------+|| |
+| |+----------------------------------------------------------------------------------------------------------------------------------------------------------+| |
++-----------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------+
+
+
+-Wformat
+--------
+This diagnostic is enabled by default.
+
+Also controls `-Wformat-extra-args`_, `-Wformat-invalid-specifier`_, `-Wformat-security`_, `-Wformat-y2k`_, `-Wformat-zero-length`_, `-Wnonnull`_.
+
+**Diagnostic text:**
+
++---------------------------+----------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| |+--------------------------------------------+| |nbsp| :diagtext:`'`:placeholder:`A`:diagtext:`' should not be used as format arguments; add an explicit cast to` |nbsp| :placeholder:`B` |nbsp| :diagtext:`instead`|
+| ||:diagtext:`values of type` || |
+| |+--------------------------------------------+| |
+| ||:diagtext:`enum values with underlying type`|| |
+| |+--------------------------------------------+| |
++---------------------------+----------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------------------------------------------+-----------------------------+------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`format specifies type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`but the argument has` |nbsp| |+---------------------------+| |nbsp| :placeholder:`B`|
+| ||:diagtext:`type` || |
+| |+---------------------------+| |
+| ||:diagtext:`underlying type`|| |
+| |+---------------------------+| |
++------------------------------------------------------------------------------------------------------------------------------------+-----------------------------+------------------------+
+
++-----------------------------------------------------------------------------+-----------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`invalid position specified for` |nbsp| |+---------------------------+|
+| ||:diagtext:`field width` ||
+| |+---------------------------+|
+| ||:diagtext:`field precision`||
+| |+---------------------------+|
++-----------------------------------------------------------------------------+-----------------------------+
+
++----------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`cannot mix positional and non-positional arguments in format string`|
++----------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`length modifier '`:placeholder:`A`:diagtext:`' results in undefined behavior or no effect with '`:placeholder:`B`:diagtext:`' conversion specifier`|
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`format string should not be a wide string`|
++--------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`position arguments in format strings start counting at 1 (not 0)`|
++-------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`format string missing`|
++------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`object format flags cannot be used with '`:placeholder:`A`:diagtext:`' conversion specifier`|
++----------------------------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------+-----------------+-------------------------------------+-----------------------+--------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'`|+---------------+|:diagtext:`' specified field` |nbsp| |+---------------------+| |nbsp| :diagtext:`is missing a matching 'int' argument`|
+| ||:diagtext:`\*` || ||:diagtext:`width` || |
+| |+---------------+| |+---------------------+| |
+| ||:diagtext:`.\*`|| ||:diagtext:`precision`|| |
+| |+---------------+| |+---------------------+| |
++----------------------------------------+-----------------+-------------------------------------+-----------------------+--------------------------------------------------------+
+
++----------------------------------------------------+-----------------------+-----------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`field` |nbsp| |+---------------------+| |nbsp| :diagtext:`should have type` |nbsp| :placeholder:`B`:diagtext:`, but argument has type` |nbsp| :placeholder:`C`|
+| ||:diagtext:`width` || |
+| |+---------------------+| |
+| ||:diagtext:`precision`|| |
+| |+---------------------+| |
++----------------------------------------------------+-----------------------+-----------------------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`missing object format flag`|
++-----------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`format string contains '\\0' within the string body`|
++------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`format string is not null-terminated`|
++---------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`flag '`:placeholder:`A`:diagtext:`' is ignored when flag '`:placeholder:`B`:diagtext:`' is present`|
++-----------------------------------------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`incomplete format specifier`|
++------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`more '%%' conversions than data arguments`|
++--------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'`:placeholder:`A`:diagtext:`' is not a valid object format flag`|
++-------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`flag '`:placeholder:`A`:diagtext:`' results in undefined behavior with '`:placeholder:`B`:diagtext:`' conversion specifier`|
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++---------------------------+-------------------------+------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| |+-----------------------+| |nbsp| :diagtext:`used with '`:placeholder:`B`:diagtext:`' conversion specifier, resulting in undefined behavior`|
+| ||:diagtext:`field width`|| |
+| |+-----------------------+| |
+| ||:diagtext:`precision` || |
+| |+-----------------------+| |
++---------------------------+-------------------------+------------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`data argument position '`:placeholder:`A`:diagtext:`' exceeds the number of data arguments (`:placeholder:`B`:diagtext:`)`|
++----------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`zero field width in scanf format string is unused`|
++----------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`no closing '\]' for '%%\[' in scanf format string`|
++----------------------------------------------------------------------------------------+
+
+
+-Wformat-extra-args
+-------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`data argument not used by format string`|
++------------------------------------------------------------------------------+
+
+
+-Wformat-invalid-specifier
+--------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`invalid conversion specifier '`:placeholder:`A`:diagtext:`'`|
++--------------------------------------------------------------------------------------------------+
+
+
+-Wformat-non-iso
+----------------
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------+----------------------------------+---------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'`:placeholder:`A`:diagtext:`'` |nbsp| |+--------------------------------+| |nbsp| :diagtext:`is not supported by ISO C`|
+| ||:diagtext:`length modifier` || |
+| |+--------------------------------+| |
+| ||:diagtext:`conversion specifier`|| |
+| |+--------------------------------+| |
++-----------------------------------------------------------------------------+----------------------------------+---------------------------------------------+
+
++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`using length modifier '`:placeholder:`A`:diagtext:`' with conversion specifier '`:placeholder:`B`:diagtext:`' is not supported by ISO C`|
++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`positional arguments are not supported by ISO C`|
++--------------------------------------------------------------------------------------+
+
+
+-Wformat-nonliteral
+-------------------
+**Diagnostic text:**
+
++----------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`format string is not a string literal`|
++----------------------------------------------------------------------------+
+
+
+-Wformat-pedantic
+-----------------
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------------------------------------------+-----------------------------+------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`format specifies type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`but the argument has` |nbsp| |+---------------------------+| |nbsp| :placeholder:`B`|
+| ||:diagtext:`type` || |
+| |+---------------------------+| |
+| ||:diagtext:`underlying type`|| |
+| |+---------------------------+| |
++------------------------------------------------------------------------------------------------------------------------------------+-----------------------------+------------------------+
+
+
+-Wformat-security
+-----------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`format string is not a string literal (potentially insecure)`|
++---------------------------------------------------------------------------------------------------+
+
+
+-Wformat-y2k
+------------
+This diagnostic flag exists for GCC compatibility, and has no effect in Clang.
+
+-Wformat-zero-length
+--------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`format string is empty`|
++-------------------------------------------------------------+
+
+
+-Wformat=2
+----------
+Some of the diagnostics controlled by this flag are enabled by default.
+
+Controls `-Wformat-nonliteral`_, `-Wformat-security`_, `-Wformat-y2k`_.
+
+
+-Wfour-char-constants
+---------------------
+**Diagnostic text:**
+
++-------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`multi-character character constant`|
++-------------------------------------------------------------------------+
+
+
+-Wframe-larger-than=
+--------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
+The text of this diagnostic is not controlled by Clang.
+
++--------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`stack frame size of` |nbsp| :placeholder:`A` |nbsp| :diagtext:`bytes in` |nbsp| :placeholder:`B`|
++--------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wfunction-def-in-objc-container
+--------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`function definition inside an Objective-C container is deprecated`|
++--------------------------------------------------------------------------------------------------------+
+
+
+-Wfuture-compat
+---------------
+This diagnostic flag exists for GCC compatibility, and has no effect in Clang.
+
+-Wgcc-compat
+------------
+Some of the diagnostics controlled by this flag are enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'enable\_if' is a clang extension`|
++------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`\_\_final is a GNU extension, consider using C++11 final`|
++-----------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`GCC does not allow` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute in this position on a function definition`|
++--------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'break' is bound to loop, GCC binds it to switch`|
++---------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`GCC does not allow the 'cleanup' attribute argument to be anything other than a simple identifier`|
++----------------------------------------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`GCC does not allow an attribute in this position on a function declaration`|
++-----------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'`:placeholder:`A`:diagtext:`' is bound to current loop, GCC binds it to the enclosing loop`|
++----------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wglobal-constructors
+---------------------
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`declaration requires a global constructor`|
++--------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`declaration requires a global destructor`|
++-------------------------------------------------------------------------------+
+
+
+-Wgnu
+-----
+Some of the diagnostics controlled by this flag are enabled by default.
+
+Controls `-Wgnu-alignof-expression`_, `-Wgnu-anonymous-struct`_, `-Wgnu-auto-type`_, `-Wgnu-binary-literal`_, `-Wgnu-case-range`_, `-Wgnu-complex-integer`_, `-Wgnu-compound-literal-initializer`_, `-Wgnu-conditional-omitted-operand`_, `-Wgnu-designator`_, `-Wgnu-empty-initializer`_, `-Wgnu-empty-struct`_, `-Wgnu-flexible-array-initializer`_, `-Wgnu-flexible-array-union-member`_, `-Wgnu-folding-constant`_, `-Wgnu-imaginary-constant`_, `-Wgnu-include-next`_, `-Wgnu-label-as-value`_, `-Wgnu-redeclared-enum`_, `-Wgnu-statement-expression`_, `-Wgnu-static-float-init`_, `-Wgnu-string-literal-operator-template`_, `-Wgnu-union-cast`_, `-Wgnu-variable-sized-type-not-at-end`_, `-Wgnu-zero-line-directive`_, `-Wgnu-zero-variadic-macro-arguments`_, `-Wredeclared-class-member`_, `-Wvla-extension`_, `-Wzero-length-array`_.
+
+
+-Wgnu-alignof-expression
+------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`applied to an expression is a GNU extension`|
++----------------------------------------------------------------------------------------------------------+
+
+
+-Wgnu-anonymous-struct
+----------------------
+**Diagnostic text:**
+
++----------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`anonymous structs are a GNU extension`|
++----------------------------------------------------------------------------+
+
+
+-Wgnu-array-member-paren-init
+-----------------------------
+This diagnostic is an error by default, but the flag ``-Wno-gnu-array-member-paren-init`` can be used to disable the error.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------+
+|:error:`error:` |nbsp| :diagtext:`parenthesized initialization of a member array is a GNU extension`|
++----------------------------------------------------------------------------------------------------+
+
+
+-Wgnu-auto-type
+---------------
+**Diagnostic text:**
+
++--------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'\_\_auto\_type' is a GNU extension`|
++--------------------------------------------------------------------------+
+
+
+-Wgnu-binary-literal
+--------------------
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`binary integer literals are a GNU extension`|
++----------------------------------------------------------------------------------+
+
+
+-Wgnu-case-range
+----------------
+**Diagnostic text:**
+
++----------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`use of GNU case range extension`|
++----------------------------------------------------------------------+
+
+
+-Wgnu-complex-integer
+---------------------
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`complex integer types are a GNU extension`|
++--------------------------------------------------------------------------------+
+
+
+-Wgnu-compound-literal-initializer
+----------------------------------
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`initialization of an array` |nbsp| :diagtext:`from a compound literal` |nbsp| :diagtext:`is a GNU extension`|
++--------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wgnu-conditional-omitted-operand
+---------------------------------
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`use of GNU ?: conditional expression extension, omitting middle operand`|
++--------------------------------------------------------------------------------------------------------------+
+
+
+-Wgnu-designator
+----------------
+Some of the diagnostics controlled by this flag are enabled by default.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`use of GNU array range extension`|
++-----------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`use of GNU 'missing =' extension in designator`|
++-------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`use of GNU old-style field designator extension`|
++--------------------------------------------------------------------------------------+
+
+
+-Wgnu-empty-initializer
+-----------------------
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`use of GNU empty initializer extension`|
++-----------------------------------------------------------------------------+
+
+
+-Wgnu-empty-struct
+------------------
+**Diagnostic text:**
+
++----------------------------------------------------+--------------------+--------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`empty` |nbsp| |+------------------+| |nbsp| :diagtext:`is a GNU extension`|
+| ||:diagtext:`struct`|| |
+| |+------------------+| |
+| ||:diagtext:`union` || |
+| |+------------------+| |
++----------------------------------------------------+--------------------+--------------------------------------+
+
++----------------------------------------------------------------------------------------------------------------------------------+-----------------------+--------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`flexible array member` |nbsp| :placeholder:`A` |nbsp| :diagtext:`in otherwise empty` |nbsp| |+---------------------+| |nbsp| :diagtext:`is a GNU extension`|
+| ||:diagtext:`struct` || |
+| |+---------------------+| |
+| ||:diagtext:`interface`|| |
+| |+---------------------+| |
+| ||:diagtext:`union` || |
+| |+---------------------+| |
+| ||:diagtext:`class` || |
+| |+---------------------+| |
+| ||:diagtext:`enum` || |
+| |+---------------------+| |
++----------------------------------------------------------------------------------------------------------------------------------+-----------------------+--------------------------------------+
+
++---------------------------+--------------------+------------------------------------------------------------+
+|:warning:`warning:` |nbsp| |+------------------+| |nbsp| :diagtext:`without named members is a GNU extension`|
+| ||:diagtext:`struct`|| |
+| |+------------------+| |
+| ||:diagtext:`union` || |
+| |+------------------+| |
++---------------------------+--------------------+------------------------------------------------------------+
+
+
+-Wgnu-flexible-array-initializer
+--------------------------------
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`flexible array initialization is a GNU extension`|
++---------------------------------------------------------------------------------------+
+
+
+-Wgnu-flexible-array-union-member
+---------------------------------
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`flexible array member` |nbsp| :placeholder:`A` |nbsp| :diagtext:`in a union is a GNU extension`|
++-------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wgnu-folding-constant
+----------------------
+**Diagnostic text:**
+
++-------------------------------------------------------------------+----------------------+------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`expression is not an` |nbsp| |+--------------------+| |nbsp| :diagtext:`constant expression; folding it to a constant is a GNU extension`|
+| ||:diagtext:`integer` || |
+| |+--------------------+| |
+| ||:diagtext:`integral`|| |
+| |+--------------------+| |
++-------------------------------------------------------------------+----------------------+------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`in-class initializer for static data member is not a constant expression; folding it to a constant is a GNU extension`|
++------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`variable length array folded to constant array as an extension`|
++-----------------------------------------------------------------------------------------------------+
+
+
+-Wgnu-imaginary-constant
+------------------------
+**Diagnostic text:**
+
++------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`imaginary constants are a GNU extension`|
++------------------------------------------------------------------------------+
+
+
+-Wgnu-include-next
+------------------
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`#include\_next is a language extension`|
++-----------------------------------------------------------------------------+
+
+
+-Wgnu-label-as-value
+--------------------
+**Diagnostic text:**
+
++----------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`use of GNU address-of-label extension`|
++----------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`use of GNU indirect-goto extension`|
++-------------------------------------------------------------------------+
+
+
+-Wgnu-redeclared-enum
+---------------------
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`redeclaration of already-defined enum` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is a GNU extension`|
++------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wgnu-statement-expression
+--------------------------
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`use of GNU statement expression extension`|
++--------------------------------------------------------------------------------+
+
+
+-Wgnu-static-float-init
+-----------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`in-class initializer for static data member of type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is a GNU extension`|
++--------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wgnu-string-literal-operator-template
+--------------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`string literal operator templates are a GNU extension`|
++--------------------------------------------------------------------------------------------+
+
+
+-Wgnu-union-cast
+----------------
+**Diagnostic text:**
+
++----------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`cast to union type is a GNU extension`|
++----------------------------------------------------------------------------+
+
+
+-Wgnu-variable-sized-type-not-at-end
+------------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`field` |nbsp| :placeholder:`A` |nbsp| :diagtext:`with variable sized type` |nbsp| :placeholder:`B` |nbsp| :diagtext:`not at the end of a struct or class is a GNU extension`|
++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wgnu-zero-line-directive
+-------------------------
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`#line directive with zero argument is a GNU extension`|
++--------------------------------------------------------------------------------------------+
+
+
+-Wgnu-zero-variadic-macro-arguments
+-----------------------------------
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`must specify at least one argument for '...' parameter of variadic macro`|
++---------------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`token pasting of ',' and \_\_VA\_ARGS\_\_ is a GNU extension`|
++---------------------------------------------------------------------------------------------------+
+
+
+-Wheader-guard
+--------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is used as a header guard here, followed by #define of a different macro`|
++---------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wheader-hygiene
+----------------
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`using namespace directive in global context in header`|
++--------------------------------------------------------------------------------------------+
+
+
+-Widiomatic-parentheses
+-----------------------
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`using the result of an assignment as a condition without parentheses`|
++-----------------------------------------------------------------------------------------------------------+
+
+
+-Wignored-attributes
+--------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------+-------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| |+-----------------+| |nbsp| :diagtext:`will always resolve to` |nbsp| :placeholder:`A` |nbsp| :diagtext:`even if weak definition of` |nbsp| :placeholder:`B` |nbsp| :diagtext:`is overridden`|
+| ||:diagtext:`alias`|| |
+| |+-----------------+| |
+| ||:diagtext:`ifunc`|| |
+| |+-----------------+| |
++---------------------------+-------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++---------------------------+-------------------+----------------------------------------------------------------------------------------------------------------+----------------------+
+|:warning:`warning:` |nbsp| |+-----------------+| |nbsp| :diagtext:`will not be in section '`:placeholder:`A`:diagtext:`' but in the same section as the` |nbsp| |+--------------------+|
+| ||:diagtext:`alias`|| ||:diagtext:`aliasee` ||
+| |+-----------------+| |+--------------------+|
+| ||:diagtext:`ifunc`|| ||:diagtext:`resolver`||
+| |+-----------------+| |+--------------------+|
++---------------------------+-------------------+----------------------------------------------------------------------------------------------------------------+----------------------+
+
++----------------------------------------------------------------------+------------------------+-------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'abi\_tag' attribute on` |nbsp| |+----------------------+| |nbsp| :diagtext:`namespace ignored`|
+| ||:diagtext:`non-inline`|| |
+| |+----------------------+| |
+| ||:diagtext:`anonymous` || |
+| |+----------------------+| |
++----------------------------------------------------------------------+------------------------+-------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`attribute` |nbsp| :placeholder:`A` |nbsp| :diagtext:`after definition is ignored`|
++-----------------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute can only be applied to instance variables or properties`|
++--------------------------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute ignored`|
++--------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute ignored on inline function`|
++---------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'`:placeholder:`A`:diagtext:`' attribute cannot be specified on a definition`|
++-------------------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`attribute` |nbsp| :placeholder:`A` |nbsp| :diagtext:`ignored, because it is not attached to a declaration`|
++------------------------------------------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'nonnull' attribute applied to function with no pointer arguments`|
++--------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'nonnull' attribute when used on parameters takes no arguments`|
++-----------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute ignored when parsing type`|
++--------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute only applies to a pointer or reference (`:placeholder:`B` |nbsp| :diagtext:`is invalid)`|
++----------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------+------------------------------+-------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute only applies to`|+----------------------------+| |nbsp| :diagtext:`pointer arguments`|
+| || || |
+| |+----------------------------+| |
+| || |nbsp| :diagtext:`constant`|| |
+| |+----------------------------+| |
++----------------------------------------------------------------------------------------+------------------------------+-------------------------------------+
+
++------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`attribute declaration must precede definition`|
++------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute only applies to return values that are pointers`|
++------------------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute only applies to return values that are pointers or references`|
++--------------------------------------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'sentinel' attribute requires named arguments`|
++------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------+-----------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'sentinel' attribute only supported for variadic` |nbsp| |+---------------------+|
+| ||:diagtext:`functions`||
+| |+---------------------+|
+| ||:diagtext:`blocks` ||
+| |+---------------------+|
++-----------------------------------------------------------------------------------------------+-----------------------+
+
++------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute argument not supported:` |nbsp| :placeholder:`B`|
++------------------------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`unknown visibility` |nbsp| :placeholder:`A`|
++---------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------------------------------+--------------------------------+----------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`attribute` |nbsp| :placeholder:`A` |nbsp| :diagtext:`cannot be applied to` |nbsp| |+------------------------------+| |nbsp| :diagtext:`without return value`|
+| ||:diagtext:`functions` || |
+| |+------------------------------+| |
+| ||:diagtext:`Objective-C method`|| |
+| |+------------------------------+| |
++------------------------------------------------------------------------------------------------------------------------+--------------------------------+----------------------------------------+
+
++----------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`\_\_weak attribute cannot be specified on a field declaration`|
++----------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`\_\_weak attribute cannot be specified on an automatic variable when ARC is not enabled`|
++------------------------------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute only applies to` |nbsp| |+----------------------------------------------------------------------------------------------------------------+|
+| ||:diagtext:`functions` ||
+| |+----------------------------------------------------------------------------------------------------------------+|
+| ||:diagtext:`unions` ||
+| |+----------------------------------------------------------------------------------------------------------------+|
+| ||:diagtext:`variables and functions` ||
+| |+----------------------------------------------------------------------------------------------------------------+|
+| ||:diagtext:`functions, variables, and Objective-C interfaces` ||
+| |+----------------------------------------------------------------------------------------------------------------+|
+| ||:diagtext:`functions and methods` ||
+| |+----------------------------------------------------------------------------------------------------------------+|
+| ||:diagtext:`parameters` ||
+| |+----------------------------------------------------------------------------------------------------------------+|
+| ||:diagtext:`functions, methods and blocks` ||
+| |+----------------------------------------------------------------------------------------------------------------+|
+| ||:diagtext:`functions, methods, and classes` ||
+| |+----------------------------------------------------------------------------------------------------------------+|
+| ||:diagtext:`functions, methods, and parameters` ||
+| |+----------------------------------------------------------------------------------------------------------------+|
+| ||:diagtext:`classes` ||
+| |+----------------------------------------------------------------------------------------------------------------+|
+| ||:diagtext:`enums` ||
+| |+----------------------------------------------------------------------------------------------------------------+|
+| ||:diagtext:`variables` ||
+| |+----------------------------------------------------------------------------------------------------------------+|
+| ||:diagtext:`methods` ||
+| |+----------------------------------------------------------------------------------------------------------------+|
+| ||:diagtext:`fields and global variables` ||
+| |+----------------------------------------------------------------------------------------------------------------+|
+| ||:diagtext:`structs` ||
+| |+----------------------------------------------------------------------------------------------------------------+|
+| ||:diagtext:`parameters and typedefs` ||
+| |+----------------------------------------------------------------------------------------------------------------+|
+| ||:diagtext:`variables and typedefs` ||
+| |+----------------------------------------------------------------------------------------------------------------+|
+| ||:diagtext:`thread-local variables` ||
+| |+----------------------------------------------------------------------------------------------------------------+|
+| ||:diagtext:`variables and fields` ||
+| |+----------------------------------------------------------------------------------------------------------------+|
+| ||:diagtext:`variables, data members and tag types` ||
+| |+----------------------------------------------------------------------------------------------------------------+|
+| ||:diagtext:`types and namespaces` ||
+| |+----------------------------------------------------------------------------------------------------------------+|
+| ||:diagtext:`Objective-C interfaces` ||
+| |+----------------------------------------------------------------------------------------------------------------+|
+| ||:diagtext:`methods and properties` ||
+| |+----------------------------------------------------------------------------------------------------------------+|
+| ||:diagtext:`struct or union` ||
+| |+----------------------------------------------------------------------------------------------------------------+|
+| ||:diagtext:`struct, union or class` ||
+| |+----------------------------------------------------------------------------------------------------------------+|
+| ||:diagtext:`types` ||
+| |+----------------------------------------------------------------------------------------------------------------+|
+| ||:diagtext:`Objective-C instance methods` ||
+| |+----------------------------------------------------------------------------------------------------------------+|
+| ||:diagtext:`init methods of interface or class extension declarations` ||
+| |+----------------------------------------------------------------------------------------------------------------+|
+| ||:diagtext:`variables, functions and classes` ||
+| |+----------------------------------------------------------------------------------------------------------------+|
+| ||:diagtext:`functions, variables, classes, and Objective-C interfaces` ||
+| |+----------------------------------------------------------------------------------------------------------------+|
+| ||:diagtext:`Objective-C protocols` ||
+| |+----------------------------------------------------------------------------------------------------------------+|
+| ||:diagtext:`variables with static or thread storage duration` ||
+| |+----------------------------------------------------------------------------------------------------------------+|
+| ||:diagtext:`functions and global variables` ||
+| |+----------------------------------------------------------------------------------------------------------------+|
+| ||:diagtext:`structs, unions, and typedefs` ||
+| |+----------------------------------------------------------------------------------------------------------------+|
+| ||:diagtext:`structs and typedefs` ||
+| |+----------------------------------------------------------------------------------------------------------------+|
+| ||:diagtext:`interface or protocol declarations` ||
+| |+----------------------------------------------------------------------------------------------------------------+|
+| ||:diagtext:`kernel functions` ||
+| |+----------------------------------------------------------------------------------------------------------------+|
+| ||:diagtext:`non-K&R-style functions` ||
+| |+----------------------------------------------------------------------------------------------------------------+|
+| ||:diagtext:`variables, enums, fields and typedefs` ||
+| |+----------------------------------------------------------------------------------------------------------------+|
+| ||:diagtext:`functions, methods, enums, and classes` ||
+| |+----------------------------------------------------------------------------------------------------------------+|
+| ||:diagtext:`structs, classes, variables, functions, and inline namespaces` ||
+| |+----------------------------------------------------------------------------------------------------------------+|
+| ||:diagtext:`variables, functions, methods, types, enumerations, enumerators, labels, and non-static data members`||
+| |+----------------------------------------------------------------------------------------------------------------+|
++------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`attribute` |nbsp| :placeholder:`A` |nbsp| :diagtext:`ignored, because it cannot be applied to omitted return type`|
++--------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`calling convention` |nbsp| :placeholder:`A` |nbsp| :diagtext:`ignored for this target`|
++----------------------------------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`calling convention ignored on constructor/destructor`|
++-------------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`calling convention ignored on variadic function`|
++--------------------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`attribute` |nbsp| :placeholder:`A` |nbsp| :diagtext:`ignored, because it cannot be applied to a type`|
++-------------------------------------------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`attribute` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is ignored, place it after "`|+---------------------+|:diagtext:`" to apply attribute to type declaration`|
+| ||:diagtext:`class` || |
+| |+---------------------+| |
+| ||:diagtext:`struct` || |
+| |+---------------------+| |
+| ||:diagtext:`interface`|| |
+| |+---------------------+| |
+| ||:diagtext:`union` || |
+| |+---------------------+| |
+| ||:diagtext:`enum` || |
+| |+---------------------+| |
++------------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------------------------+
+
++--------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'deprecated' attribute on anonymous namespace ignored`|
++--------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`redeclared inline;` |nbsp| :placeholder:`B` |nbsp| :diagtext:`attribute ignored`|
++----------------------------------------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`attribute` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is already applied with different parameters`|
++----------------------------------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`attribute` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is already applied`|
++--------------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`Objective-C GC does not allow weak variables on the stack`|
++------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'gnu\_inline' attribute requires function to be marked 'inline', attribute ignored`|
++-------------------------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------+------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`inheritance model ignored on` |nbsp| |+----------------------------------+|
+| ||:diagtext:`primary template` ||
+| |+----------------------------------+|
+| ||:diagtext:`partial specialization`||
+| |+----------------------------------+|
++---------------------------------------------------------------------------+------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'internal\_linkage' attribute on a non-static local variable is ignored`|
++--------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`qualifiers after comma in declarator list are ignored`|
++--------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------------+----------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`MIPS 'interrupt' attribute only applies to functions that have` |nbsp| |+--------------------------------+|
+| ||:diagtext:`no parameters` ||
+| |+--------------------------------+|
+| ||:diagtext:`a 'void' return type`||
+| |+--------------------------------+|
++-------------------------------------------------------------------------------------------------------------+----------------------------------+
+
++---------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`unknown attribute '`:placeholder:`A`:diagtext:`'`|
++---------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------+-----------------------------------+------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute only applies to` |nbsp| |+---------------------------------+| |nbsp| :diagtext:`parameters`|
+| ||:diagtext:`Objective-C object` || |
+| |+---------------------------------+| |
+| ||:diagtext:`pointer` || |
+| |+---------------------------------+| |
+| ||:diagtext:`pointer-to-CF-pointer`|| |
+| |+---------------------------------+| |
++------------------------------------------------------------------------------------------------+-----------------------------------+------------------------------+
+
++------------------------------------------------------------------------------------------------+------------------------+---------------------------------------+--------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute only applies to` |nbsp| |+----------------------+| |nbsp| :diagtext:`that return` |nbsp| |+------------------------------------+|
+| ||:diagtext:`functions` || ||:diagtext:`an Objective-C object` ||
+| |+----------------------+| |+------------------------------------+|
+| ||:diagtext:`methods` || ||:diagtext:`a pointer` ||
+| |+----------------------+| |+------------------------------------+|
+| ||:diagtext:`properties`|| ||:diagtext:`a non-retainable pointer`||
+| |+----------------------+| |+------------------------------------+|
++------------------------------------------------------------------------------------------------+------------------------+---------------------------------------+--------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute is deprecated and ignored in OpenCL version` |nbsp| :placeholder:`B`|
++--------------------------------------------------------------------------------------------------------------------------------------------+
+
++---------------------------+-----------------------+---------------------------------------------------------------------------------------------------------------------------------------------+-----------------------+-------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| |+---------------------+| |nbsp| :diagtext:`of field` |nbsp| :placeholder:`B` |nbsp| :diagtext:`(`:placeholder:`C` |nbsp| :diagtext:`bits) does not match the` |nbsp| |+---------------------+| |nbsp| :diagtext:`of the first field in transparent union; transparent\_union attribute ignored`|
+| ||:diagtext:`alignment`|| ||:diagtext:`alignment`|| |
+| |+---------------------+| |+---------------------+| |
+| ||:diagtext:`size` || ||:diagtext:`size` || |
+| |+---------------------+| |+---------------------+| |
++---------------------------+-----------------------+---------------------------------------------------------------------------------------------------------------------------------------------+-----------------------+-------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------+----------------------------+--------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`first field of a transparent union cannot have` |nbsp| |+--------------------------+| |nbsp| :diagtext:`type` |nbsp| :placeholder:`B`:diagtext:`; transparent\_union attribute ignored`|
+| ||:diagtext:`floating point`|| |
+| |+--------------------------+| |
+| ||:diagtext:`vector` || |
+| |+--------------------------+| |
++---------------------------------------------------------------------------------------------+----------------------------+--------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`transparent\_union attribute can only be applied to a union definition; attribute ignored`|
++--------------------------------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`transparent union definition must contain at least one field; transparent\_union attribute ignored`|
++-----------------------------------------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------+-------------------------------------------------+---------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'`:placeholder:`A`:diagtext:`' only applies to` |nbsp| |+-----------------------------------------------+| |nbsp| :diagtext:`types; type here is` |nbsp| :placeholder:`C`|
+| ||:diagtext:`function` || |
+| |+-----------------------------------------------+| |
+| ||:diagtext:`pointer` || |
+| |+-----------------------------------------------+| |
+| ||:diagtext:`Objective-C object or block pointer`|| |
+| |+-----------------------------------------------+| |
++---------------------------------------------------------------------------------------------+-------------------------------------------------+---------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`\_\_declspec attribute` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is not supported`|
++-------------------------------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`Ignoring unsupported '`:placeholder:`A`:diagtext:`' in the target attribute string`|
++-------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wignored-optimization-argument
+-------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`optimization flag '`:placeholder:`A`:diagtext:`' is not supported for target '`:placeholder:`B`:diagtext:`'`|
++--------------------------------------------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`optimization flag '`:placeholder:`A`:diagtext:`' is not supported`|
++--------------------------------------------------------------------------------------------------------+
+
+
+-Wignored-pragmas
+-----------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------------+---------------------------+-----------------------+
+|:warning:`warning:` |nbsp| :diagtext:`expected '=' following '#pragma` |nbsp| |+-------------------------+|:diagtext:`' - ignored`|
+| ||:diagtext:`align` || |
+| |+-------------------------+| |
+| ||:diagtext:`options align`|| |
+| |+-------------------------+| |
++------------------------------------------------------------------------------+---------------------------+-----------------------+
+
++-----------------------------------------------------------------------------------+---------------------------+-----------------------+
+|:warning:`warning:` |nbsp| :diagtext:`invalid alignment option in '#pragma` |nbsp| |+-------------------------+|:diagtext:`' - ignored`|
+| ||:diagtext:`align` || |
+| |+-------------------------+| |
+| ||:diagtext:`options align`|| |
+| |+-------------------------+| |
++-----------------------------------------------------------------------------------+---------------------------+-----------------------+
+
++----------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'#pragma comment` |nbsp| :placeholder:`A`:diagtext:`' ignored`|
++----------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`missing argument to debug command '`:placeholder:`A`:diagtext:`'`|
++-------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`unexpected debug command '`:placeholder:`A`:diagtext:`'`|
++----------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`expected action or ')' in '#pragma` |nbsp| :placeholder:`A`:diagtext:`' - ignored`|
++------------------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`missing ':' after` |nbsp| :placeholder:`A` |nbsp| :diagtext:`- ignoring`|
++--------------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`missing ':' or ')' after` |nbsp| :placeholder:`A` |nbsp| :diagtext:`- ignoring`|
++---------------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`expected 'enable' or 'disable' - ignoring`|
++--------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`expected identifier in '#pragma` |nbsp| :placeholder:`A`:diagtext:`' - ignored`|
++---------------------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`expected 'compiler', 'lib', 'user', or a string literal for the section name in '#pragma` |nbsp| :placeholder:`A`:diagtext:`' - ignored`|
++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`expected integer between` |nbsp| :placeholder:`A` |nbsp| :diagtext:`and` |nbsp| :placeholder:`B` |nbsp| :diagtext:`inclusive in '#pragma` |nbsp| :placeholder:`C`:diagtext:`' - ignored`|
++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`missing '(' after '#pragma` |nbsp| :placeholder:`A`:diagtext:`' - ignoring`|
++-----------------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`expected non-wide string literal in '#pragma` |nbsp| :placeholder:`A`:diagtext:`'`|
++------------------------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`expected ')' or ',' in '#pragma` |nbsp| :placeholder:`A`:diagtext:`'`|
++-----------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`missing ')' after '#pragma` |nbsp| :placeholder:`A`:diagtext:`' - ignoring`|
++-----------------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`expected a stack label or a string literal for the section name in '#pragma` |nbsp| :placeholder:`A`:diagtext:`' - ignored`|
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`expected a string literal for the section name in '#pragma` |nbsp| :placeholder:`A`:diagtext:`' - ignored`|
++------------------------------------------------------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`expected push, pop or a string literal for the section name in '#pragma` |nbsp| :placeholder:`A`:diagtext:`' - ignored`|
++-------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`extra tokens at end of '#pragma` |nbsp| :placeholder:`A`:diagtext:`' - ignored`|
++---------------------------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'#pragma init\_seg' is only supported when targeting a Microsoft environment`|
++-------------------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------+------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is not a recognized builtin`|+----------------------------------------------------------------------------+|
+| || ||
+| |+----------------------------------------------------------------------------+|
+| ||:diagtext:`; consider including <intrin.h> to access non-builtin intrinsics`||
+| |+----------------------------------------------------------------------------+|
++------------------------------------------------------------------------------------------+------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`unknown action for '#pragma` |nbsp| :placeholder:`A`:diagtext:`' - ignored`|
++-----------------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`unknown action '`:placeholder:`B`:diagtext:`' for '#pragma` |nbsp| :placeholder:`A`:diagtext:`' - ignored`|
++------------------------------------------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`incorrect use of '#pragma ms\_struct on\|off' - ignored`|
++----------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`#pragma options align=reset failed:` |nbsp| :placeholder:`A`|
++--------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`expected 'align' following '#pragma options' - ignored`|
++---------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`expected #pragma pack parameter to be '1', '2', '4', '8', or '16'`|
++--------------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`expected integer or identifier in '#pragma pack' - ignored`|
++-------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`#pragma` |nbsp| :placeholder:`A`:diagtext:`(pop, ...) failed:` |nbsp| :placeholder:`B`|
++----------------------------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`pragma pop\_macro could not pop '`:placeholder:`A`:diagtext:`', no matching push\_macro`|
++------------------------------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`unknown OpenCL extension` |nbsp| :placeholder:`A` |nbsp| :diagtext:`- ignoring`|
++---------------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`known but unsupported action '`:placeholder:`B`:diagtext:`' for '#pragma` |nbsp| :placeholder:`A`:diagtext:`' - ignored`|
++--------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`unsupported OpenCL extension` |nbsp| :placeholder:`A` |nbsp| :diagtext:`- ignoring`|
++-------------------------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`expected '#pragma unused' argument to be a variable name`|
++-----------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`only variables can be arguments to '#pragma unused'`|
++------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`undeclared variable` |nbsp| :placeholder:`A` |nbsp| :diagtext:`used as an argument for '#pragma unused'`|
++----------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wignored-qualifiers
+--------------------
+Some of the diagnostics controlled by this flag are enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------+------------------------------------+----------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`ARC` |nbsp| |+----------------------------------+| |nbsp| :diagtext:`lifetime qualifier on return type is ignored`|
+| ||:diagtext:`unused` || |
+| |+----------------------------------+| |
+| ||:diagtext:`\_\_unsafe\_unretained`|| |
+| |+----------------------------------+| |
+| ||:diagtext:`\_\_strong` || |
+| |+----------------------------------+| |
+| ||:diagtext:`\_\_weak` || |
+| |+----------------------------------+| |
+| ||:diagtext:`\_\_autoreleasing` || |
+| |+----------------------------------+| |
++--------------------------------------------------+------------------------------------+----------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'`:placeholder:`A`:diagtext:`' qualifier on omitted return type` |nbsp| :placeholder:`B` |nbsp| :diagtext:`has no effect`|
++---------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------+---------------+------------------------------------------+-------------------+-----------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'`:placeholder:`A`:diagtext:`' type qualifier`|+-------------+| |nbsp| :diagtext:`on return type` |nbsp| |+-----------------+| |nbsp| :diagtext:`no effect`|
+| || || ||:diagtext:`:has` || |
+| |+-------------+| |+-----------------+| |
+| ||:diagtext:`s`|| ||:diagtext:`:have`|| |
+| |+-------------+| |+-----------------+| |
++------------------------------------------------------------------------------------+---------------+------------------------------------------+-------------------+-----------------------------+
+
++---------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'`:placeholder:`A`:diagtext:`' qualifier on function type` |nbsp| :placeholder:`B` |nbsp| :diagtext:`has no effect`|
++---------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'`:placeholder:`A`:diagtext:`' qualifier on reference type` |nbsp| :placeholder:`B` |nbsp| :diagtext:`has no effect`|
++----------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wimplicit
+----------
+Some of the diagnostics controlled by this flag are enabled by default.
+
+Controls `-Wimplicit-function-declaration`_, `-Wimplicit-int`_.
+
+
+-Wimplicit-atomic-properties
+----------------------------
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`property is assumed atomic when auto-synthesizing the property`|
++-----------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`property is assumed atomic by default`|
++----------------------------------------------------------------------------+
+
+
+-Wimplicit-conversion-floating-point-to-bool
+--------------------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`implicit conversion turns floating-point number into bool:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B`|
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wimplicit-exception-spec-mismatch
+----------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------+----------------------+----------------------------------------------------------------------+----------------------+-------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`function previously declared with an` |nbsp| |+--------------------+| |nbsp| :diagtext:`exception specification redeclared with an` |nbsp| |+--------------------+| |nbsp| :diagtext:`exception specification`|
+| ||:diagtext:`explicit`|| ||:diagtext:`implicit`|| |
+| |+--------------------+| |+--------------------+| |
+| ||:diagtext:`implicit`|| ||:diagtext:`explicit`|| |
+| |+--------------------+| |+--------------------+| |
++-----------------------------------------------------------------------------------+----------------------+----------------------------------------------------------------------+----------------------+-------------------------------------------+
+
+
+-Wimplicit-fallthrough
+----------------------
+Also controls `-Wimplicit-fallthrough-per-function`_.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`fallthrough annotation in unreachable code`|
++---------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`unannotated fall-through between switch labels`|
++-------------------------------------------------------------------------------------+
+
+
+-Wimplicit-fallthrough-per-function
+-----------------------------------
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`unannotated fall-through between switch labels in partly-annotated function`|
++------------------------------------------------------------------------------------------------------------------+
+
+
+-Wimplicit-function-declaration
+-------------------------------
+Some of the diagnostics controlled by this flag are enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`implicit declaration of function` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is invalid in C99`|
++------------------------------------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`implicitly declaring library function '`:placeholder:`A`:diagtext:`' with type` |nbsp| :placeholder:`B`|
++---------------------------------------------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------+
+|:error:`error:` |nbsp| :diagtext:`use of unknown builtin` |nbsp| :placeholder:`A`|
++---------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`implicit declaration of function` |nbsp| :placeholder:`A`|
++-----------------------------------------------------------------------------------------------+
+
+
+-Wimplicit-int
+--------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`type specifier missing, defaults to 'int'`|
++--------------------------------------------------------------------------------+
+
+
+-Wimplicit-retain-self
+----------------------
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior`|
++---------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wimplicitly-unsigned-literal
+-----------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`integer literal is too large to be represented in a signed integer type, interpreting as unsigned`|
++----------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wimport
+--------
+This diagnostic flag exists for GCC compatibility, and has no effect in Clang.
+
+-Wimport-preprocessor-directive-pedantic
+----------------------------------------
+**Diagnostic text:**
+
++----------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`#import is a language extension`|
++----------------------------------------------------------------------+
+
+
+-Winaccessible-base
+-------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`direct base` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is inaccessible due to ambiguity:`:placeholder:`B`|
++-----------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Winclude-next-absolute-path
+----------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`#include\_next with absolute path`|
++------------------------------------------------------------------------+
+
+
+-Winclude-next-outside-header
+-----------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`#include\_next in primary source file`|
++----------------------------------------------------------------------------+
+
+
+-Wincompatible-function-pointer-types
+-------------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------+----------------------------------------------------------------+---------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`incompatible function pointer types` |nbsp| |+--------------------------------------------------------------+|+-------------------------------------+|
+| ||:diagtext:`assigning to different types` ||| ||
+| |+--------------------------------------------------------------+|+-------------------------------------+|
+| ||:diagtext:`passing to parameter of different type` |||:diagtext:`; dereference with \*` ||
+| |+--------------------------------------------------------------+|+-------------------------------------+|
+| ||:diagtext:`returning from function with different return type`|||:diagtext:`; take the address with &`||
+| |+--------------------------------------------------------------+|+-------------------------------------+|
+| ||:diagtext:`converting between types` |||:diagtext:`; remove \*` ||
+| |+--------------------------------------------------------------+|+-------------------------------------+|
+| ||:diagtext:`initializing with expression of different type` |||:diagtext:`; remove &` ||
+| |+--------------------------------------------------------------+|+-------------------------------------+|
+| ||:diagtext:`sending to parameter of different type` || |
+| |+--------------------------------------------------------------+| |
+| ||:diagtext:`casting between types` || |
+| |+--------------------------------------------------------------+| |
++----------------------------------------------------------------------------------+----------------------------------------------------------------+---------------------------------------+
+
+
+-Wincompatible-library-redeclaration
+------------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`incompatible redeclaration of library function` |nbsp| :placeholder:`A`|
++-------------------------------------------------------------------------------------------------------------+
+
+
+-Wincompatible-ms-struct
+------------------------
+This diagnostic is an error by default, but the flag ``-Wno-incompatible-ms-struct`` can be used to disable the error.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------------------------------------+
+|:error:`error:` |nbsp| :diagtext:`ms\_struct may not produce Microsoft-compatible layouts for classes with base classes or virtual functions`|
++---------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wincompatible-pointer-types
+----------------------------
+This diagnostic is enabled by default.
+
+Also controls `-Wincompatible-function-pointer-types`_, `-Wincompatible-pointer-types-discards-qualifiers`_.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------+----------------------------------------------------------------+---------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`incompatible pointer types` |nbsp| |+--------------------------------------------------------------+|+-------------------------------------+|
+| ||:diagtext:`assigning to different types` ||| ||
+| |+--------------------------------------------------------------+|+-------------------------------------+|
+| ||:diagtext:`passing to parameter of different type` |||:diagtext:`; dereference with \*` ||
+| |+--------------------------------------------------------------+|+-------------------------------------+|
+| ||:diagtext:`returning from function with different return type`|||:diagtext:`; take the address with &`||
+| |+--------------------------------------------------------------+|+-------------------------------------+|
+| ||:diagtext:`converting between types` |||:diagtext:`; remove \*` ||
+| |+--------------------------------------------------------------+|+-------------------------------------+|
+| ||:diagtext:`initializing with expression of different type` |||:diagtext:`; remove &` ||
+| |+--------------------------------------------------------------+|+-------------------------------------+|
+| ||:diagtext:`sending to parameter of different type` || |
+| |+--------------------------------------------------------------+| |
+| ||:diagtext:`casting between types` || |
+| |+--------------------------------------------------------------+| |
++-------------------------------------------------------------------------+----------------------------------------------------------------+---------------------------------------+
+
+
+-Wincompatible-pointer-types-discards-qualifiers
+------------------------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------+----------------------------------------------------------------+---------------------------------------------------------------+
+|:warning:`warning:` |nbsp| |+--------------------------------------------------------------+| |nbsp| :diagtext:`discards qualifiers in nested pointer types`|
+| ||:diagtext:`assigning to different types` || |
+| |+--------------------------------------------------------------+| |
+| ||:diagtext:`passing to parameter of different type` || |
+| |+--------------------------------------------------------------+| |
+| ||:diagtext:`returning from function with different return type`|| |
+| |+--------------------------------------------------------------+| |
+| ||:diagtext:`converting between types` || |
+| |+--------------------------------------------------------------+| |
+| ||:diagtext:`initializing with expression of different type` || |
+| |+--------------------------------------------------------------+| |
+| ||:diagtext:`sending to parameter of different type` || |
+| |+--------------------------------------------------------------+| |
+| ||:diagtext:`casting between types` || |
+| |+--------------------------------------------------------------+| |
++---------------------------+----------------------------------------------------------------+---------------------------------------------------------------+
+
++---------------------------+----------------------------------------------------------------+---------------------------------------+
+|:warning:`warning:` |nbsp| |+--------------------------------------------------------------+| |nbsp| :diagtext:`discards qualifiers`|
+| ||:diagtext:`assigning to different types` || |
+| |+--------------------------------------------------------------+| |
+| ||:diagtext:`passing to parameter of different type` || |
+| |+--------------------------------------------------------------+| |
+| ||:diagtext:`returning from function with different return type`|| |
+| |+--------------------------------------------------------------+| |
+| ||:diagtext:`converting between types` || |
+| |+--------------------------------------------------------------+| |
+| ||:diagtext:`initializing with expression of different type` || |
+| |+--------------------------------------------------------------+| |
+| ||:diagtext:`sending to parameter of different type` || |
+| |+--------------------------------------------------------------+| |
+| ||:diagtext:`casting between types` || |
+| |+--------------------------------------------------------------+| |
++---------------------------+----------------------------------------------------------------+---------------------------------------+
+
+
+-Wincompatible-property-type
+----------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`property type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is incompatible with type` |nbsp| :placeholder:`B` |nbsp| :diagtext:`inherited from` |nbsp| :placeholder:`C`|
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wincompatible-sysroot
+----------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`using sysroot for '`:placeholder:`A`:diagtext:`' but targeting '`:placeholder:`B`:diagtext:`'`|
++------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wincomplete-implementation
+---------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`method definition for` |nbsp| :placeholder:`A` |nbsp| :diagtext:`not found`|
++-----------------------------------------------------------------------------------------------------------------+
+
+
+-Wincomplete-module
+-------------------
+Some of the diagnostics controlled by this flag are enabled by default.
+
+Controls `-Wincomplete-umbrella`_, `-Wnon-modular-include-in-module`_.
+
+
+-Wincomplete-umbrella
+---------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`missing submodule '`:placeholder:`A`:diagtext:`'`|
++---------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`umbrella header for module '`:placeholder:`A`:diagtext:`' does not include header '`:placeholder:`B`:diagtext:`'`|
++-------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Winconsistent-dllimport
+------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`redeclared without` |nbsp| :placeholder:`B` |nbsp| :diagtext:`attribute: previous` |nbsp| :placeholder:`B` |nbsp| :diagtext:`ignored`|
++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`redeclared without 'dllimport' attribute: 'dllexport' attribute added`|
++------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Winconsistent-missing-override
+-------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`overrides a member function but is not marked 'override'`|
++-----------------------------------------------------------------------------------------------------------------------+
+
+
+-Wincrement-bool
+----------------
+This diagnostic is enabled by default.
+
+Also controls `-Wdeprecated-increment-bool`_.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------+
+|:error:`error:` |nbsp| :diagtext:`ISO C++1z does not allow incrementing expression of type bool`|
++------------------------------------------------------------------------------------------------+
+
+
+-Winfinite-recursion
+--------------------
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`all paths through this function will call itself`|
++---------------------------------------------------------------------------------------+
+
+
+-Winit-self
+-----------
+This diagnostic flag exists for GCC compatibility, and has no effect in Clang.
+
+-Winitializer-overrides
+-----------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`initializer overrides prior initialization of this subobject`|
++---------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`subobject initialization overrides initialization of other fields within its enclosing subobject`|
++---------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Winline
+--------
+This diagnostic flag exists for GCC compatibility, and has no effect in Clang.
+
+-Winline-asm
+------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
+The text of this diagnostic is not controlled by Clang.
+
+
+-Winline-new-delete
+-------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`replacement function` |nbsp| :placeholder:`A` |nbsp| :diagtext:`cannot be declared 'inline'`|
++----------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Winstantiation-after-specialization
+------------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`explicit instantiation of` |nbsp| :placeholder:`A` |nbsp| :diagtext:`that occurs after an explicit specialization has no effect`|
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wint-conversion
+----------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------+----------------------------------------------------------------+---------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`incompatible integer to pointer conversion` |nbsp| |+--------------------------------------------------------------+|+-------------------------------------+|
+| ||:diagtext:`assigning to different types` ||| ||
+| |+--------------------------------------------------------------+|+-------------------------------------+|
+| ||:diagtext:`passing to parameter of different type` |||:diagtext:`; dereference with \*` ||
+| |+--------------------------------------------------------------+|+-------------------------------------+|
+| ||:diagtext:`returning from function with different return type`|||:diagtext:`; take the address with &`||
+| |+--------------------------------------------------------------+|+-------------------------------------+|
+| ||:diagtext:`converting between types` |||:diagtext:`; remove \*` ||
+| |+--------------------------------------------------------------+|+-------------------------------------+|
+| ||:diagtext:`initializing with expression of different type` |||:diagtext:`; remove &` ||
+| |+--------------------------------------------------------------+|+-------------------------------------+|
+| ||:diagtext:`sending to parameter of different type` || |
+| |+--------------------------------------------------------------+| |
+| ||:diagtext:`casting between types` || |
+| |+--------------------------------------------------------------+| |
++-----------------------------------------------------------------------------------------+----------------------------------------------------------------+---------------------------------------+
+
++-----------------------------------------------------------------------------------------+----------------------------------------------------------------+---------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`incompatible pointer to integer conversion` |nbsp| |+--------------------------------------------------------------+|+-------------------------------------+|
+| ||:diagtext:`assigning to different types` ||| ||
+| |+--------------------------------------------------------------+|+-------------------------------------+|
+| ||:diagtext:`passing to parameter of different type` |||:diagtext:`; dereference with \*` ||
+| |+--------------------------------------------------------------+|+-------------------------------------+|
+| ||:diagtext:`returning from function with different return type`|||:diagtext:`; take the address with &`||
+| |+--------------------------------------------------------------+|+-------------------------------------+|
+| ||:diagtext:`converting between types` |||:diagtext:`; remove \*` ||
+| |+--------------------------------------------------------------+|+-------------------------------------+|
+| ||:diagtext:`initializing with expression of different type` |||:diagtext:`; remove &` ||
+| |+--------------------------------------------------------------+|+-------------------------------------+|
+| ||:diagtext:`sending to parameter of different type` || |
+| |+--------------------------------------------------------------+| |
+| ||:diagtext:`casting between types` || |
+| |+--------------------------------------------------------------+| |
++-----------------------------------------------------------------------------------------+----------------------------------------------------------------+---------------------------------------+
+
+
+-Wint-conversions
+-----------------
+Synonym for `-Wint-conversion`_.
+
+
+-Wint-to-pointer-cast
+---------------------
+This diagnostic is enabled by default.
+
+Also controls `-Wint-to-void-pointer-cast`_.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`cast to` |nbsp| :placeholder:`B` |nbsp| :diagtext:`from smaller integer type` |nbsp| :placeholder:`A`|
++-------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wint-to-void-pointer-cast
+--------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`cast to` |nbsp| :placeholder:`B` |nbsp| :diagtext:`from smaller integer type` |nbsp| :placeholder:`A`|
++-------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Winteger-overflow
+------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`overflow in expression; result is` |nbsp| :placeholder:`A` |nbsp| :diagtext:`with type` |nbsp| :placeholder:`B`|
++-----------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Winvalid-command-line-argument
+-------------------------------
+This diagnostic is enabled by default.
+
+Also controls `-Wignored-optimization-argument`_.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`optimization level '`:placeholder:`A`:diagtext:`' is not supported; using '`:placeholder:`B`:placeholder:`C`:diagtext:`' instead`|
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Winvalid-constexpr
+-------------------
+This diagnostic is an error by default, but the flag ``-Wno-invalid-constexpr`` can be used to disable the error.
+
+**Diagnostic text:**
+
++----------------------------------------------------+-------------------------+--------------------------------------------------------+
+|:error:`error:` |nbsp| :diagtext:`constexpr` |nbsp| |+-----------------------+| |nbsp| :diagtext:`never produces a constant expression`|
+| ||:diagtext:`function` || |
+| |+-----------------------+| |
+| ||:diagtext:`constructor`|| |
+| |+-----------------------+| |
++----------------------------------------------------+-------------------------+--------------------------------------------------------+
+
+
+-Winvalid-iboutlet
+------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------+-------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| |+-----------------------------+| |nbsp| :diagtext:`with` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute must be an object type (invalid` |nbsp| :placeholder:`B`:diagtext:`)`|
+| ||:diagtext:`instance variable`|| |
+| |+-----------------------------+| |
+| ||:diagtext:`property` || |
+| |+-----------------------------+| |
++---------------------------+-------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`IBOutletCollection properties should be copy/strong and not assign`|
++---------------------------------------------------------------------------------------------------------+
+
+
+-Winvalid-initializer-from-system-header
+----------------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`invalid constructor form class in system header, should not be explicit`|
++--------------------------------------------------------------------------------------------------------------+
+
+
+-Winvalid-noreturn
+------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`function declared 'noreturn' should not return`|
++-------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`function` |nbsp| :placeholder:`A` |nbsp| :diagtext:`declared 'noreturn' should not return`|
++--------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Winvalid-offsetof
+------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`offset of on non-POD type` |nbsp| :placeholder:`A`|
++----------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`offset of on non-standard-layout type` |nbsp| :placeholder:`A`|
++----------------------------------------------------------------------------------------------------+
+
+
+-Winvalid-or-nonexistent-directory
+----------------------------------
+Some of the diagnostics controlled by this flag are enabled by default.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`environment variable SCE\_ORBIS\_SDK\_DIR is set, but points to invalid or nonexistent directory '`:placeholder:`A`:diagtext:`'`|
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`unable to find` |nbsp| :placeholder:`A` |nbsp| :diagtext:`directory, expected to be in '`:placeholder:`B`:diagtext:`'`|
++------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Winvalid-pch
+-------------
+This diagnostic flag exists for GCC compatibility, and has no effect in Clang.
+
+-Winvalid-pp-token
+------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`empty character constant`|
++---------------------------------------------------------------+
+
++------------------------------------------------------------------+-----------------+-----------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`missing terminating` |nbsp| |+---------------+| |nbsp| :diagtext:`character`|
+| ||:diagtext:`'` || |
+| |+---------------+| |
+| ||:diagtext:`'"'`|| |
+| |+---------------+| |
++------------------------------------------------------------------+-----------------+-----------------------------+
+
+
+-Winvalid-source-encoding
+-------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`illegal character encoding in character literal`|
++--------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`illegal character encoding in string literal`|
++-----------------------------------------------------------------------------------+
+
+
+-Winvalid-token-paste
+---------------------
+This diagnostic is an error by default, but the flag ``-Wno-invalid-token-paste`` can be used to disable the error.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------+
+|:error:`error:` |nbsp| :diagtext:`pasting formed '`:placeholder:`A`:diagtext:`', an invalid preprocessing token`|
++----------------------------------------------------------------------------------------------------------------+
+
+
+-Wjump-seh-finally
+------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`jump out of \_\_finally block has undefined behavior`|
++-------------------------------------------------------------------------------------------+
+
+
+-Wkeyword-compat
+----------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`keyword '`:placeholder:`A`:diagtext:`' will be made available as an identifier` |nbsp| |+-----------------------------------------------------+|
+| ||:diagtext:`here` ||
+| |+-----------------------------------------------------+|
+| ||:diagtext:`for the remainder of the translation unit`||
+| |+-----------------------------------------------------+|
++-----------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------+
+
+
+-Wkeyword-macro
+---------------
+**Diagnostic text:**
+
++----------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`keyword is hidden by macro definition`|
++----------------------------------------------------------------------------+
+
+
+-Wknr-promoted-parameter
+------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`promoted type of K&R function parameter is not compatible with parameter type` |nbsp| :diagtext:`declared in a previous prototype`|
++------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wlanguage-extension-token
+--------------------------
+**Diagnostic text:**
+
++-----------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`extension used`|
++-----------------------------------------------------+
+
+
+-Wlarge-by-value-copy
+---------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is a large (`:placeholder:`B` |nbsp| :diagtext:`bytes) pass-by-value argument; pass it by reference instead ?`|
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`return value of` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is a large (`:placeholder:`B` |nbsp| :diagtext:`bytes) pass-by-value object; pass it by reference instead ?`|
++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wliblto
+--------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`libLTO.dylib relative to clang installed dir not found; using 'ld' default search path instead`|
++-------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wliteral-conversion
+--------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`implicit conversion from` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B` |nbsp| :diagtext:`changes value from` |nbsp| :placeholder:`C` |nbsp| :diagtext:`to` |nbsp| :placeholder:`D`|
++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wliteral-range
+---------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`magnitude of floating-point constant too large for type` |nbsp| :placeholder:`A`:diagtext:`; maximum is` |nbsp| :placeholder:`B`|
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`magnitude of floating-point constant too small for type` |nbsp| :placeholder:`A`:diagtext:`; minimum is` |nbsp| :placeholder:`B`|
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wlocal-type-template-args
+--------------------------
+Some of the diagnostics controlled by this flag are enabled by default.
+
+Also controls `-Wc++98-compat-local-type-template-args`_.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`template argument uses local type` |nbsp| :placeholder:`A`|
++------------------------------------------------------------------------------------------------+
+
+
+-Wlogical-not-parentheses
+-------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`logical not is only applied to the left hand side of this comparison`|
++-----------------------------------------------------------------------------------------------------------+
+
+
+-Wlogical-op-parentheses
+------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'&&' within '\|\|'`|
++---------------------------------------------------------+
+
+
+-Wlong-long
+-----------
+Also controls `-Wc++11-long-long`_.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'long long' is an extension when C99 mode is not enabled`|
++-----------------------------------------------------------------------------------------------+
+
+
+-Wloop-analysis
+---------------
+Controls `-Wfor-loop-analysis`_, `-Wrange-loop-analysis`_.
+
+
+-Wmacro-redefined
+-----------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`macro redefined`|
++------------------------------------------------------------------------------+
+
+
+-Wmain
+------
+Some of the diagnostics controlled by this flag are enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`ISO C++ does not allow 'main' to be used by a program`|
++--------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'main' is not allowed to be declared \_Noreturn`|
++--------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'main' is not allowed to be declared variadic`|
++------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`only one parameter on 'main' declaration`|
++-------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`variable named 'main' with external linkage has undefined behavior`|
++---------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'main' should not be declared static`|
++---------------------------------------------------------------------------+
+
+
+-Wmain-return-type
+------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`return type of 'main' is not 'int'`|
++-------------------------------------------------------------------------+
+
+
+-Wmalformed-warning-check
+-------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`\_\_has\_warning expected option name (e.g. "-Wundef")`|
++---------------------------------------------------------------------------------------------+
+
+
+-Wmany-braces-around-scalar-init
+--------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`too many braces around scalar initializer`|
++--------------------------------------------------------------------------------+
+
+
+-Wmemsize-comparison
+--------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`size argument in` |nbsp| :placeholder:`A` |nbsp| :diagtext:`call is a comparison`|
++-----------------------------------------------------------------------------------------------------------------------+
+
+
+-Wmethod-signatures
+-------------------
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`conflicting parameter types in implementation of` |nbsp| :placeholder:`A`:diagtext:`:` |nbsp| :placeholder:`B` |nbsp| :diagtext:`vs` |nbsp| :placeholder:`C`|
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`conflicting return type in implementation of` |nbsp| :placeholder:`A`:diagtext:`:` |nbsp| :placeholder:`B` |nbsp| :diagtext:`vs` |nbsp| :placeholder:`C`|
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wmicrosoft
+-----------
+Some of the diagnostics controlled by this flag are enabled by default.
+
+Controls `-Winconsistent-dllimport`_, `-Wmicrosoft-anon-tag`_, `-Wmicrosoft-cast`_, `-Wmicrosoft-charize`_, `-Wmicrosoft-comment-paste`_, `-Wmicrosoft-const-init`_, `-Wmicrosoft-cpp-macro`_, `-Wmicrosoft-default-arg-redefinition`_, `-Wmicrosoft-end-of-file`_, `-Wmicrosoft-enum-forward-reference`_, `-Wmicrosoft-enum-value`_, `-Wmicrosoft-exception-spec`_, `-Wmicrosoft-explicit-constructor-call`_, `-Wmicrosoft-extra-qualification`_, `-Wmicrosoft-fixed-enum`_, `-Wmicrosoft-flexible-array`_, `-Wmicrosoft-goto`_, `-Wmicrosoft-include`_, `-Wmicrosoft-mutable-reference`_, `-Wmicrosoft-pure-definition`_, `-Wmicrosoft-redeclare-static`_, `-Wmicrosoft-sealed`_, `-Wmicrosoft-template`_, `-Wmicrosoft-union-member-reference`_, `-Wmicrosoft-unqualified-friend`_, `-Wmicrosoft-using-decl`_, `-Wmicrosoft-void-pseudo-dtor`_.
+
+
+-Wmicrosoft-anon-tag
+--------------------
+Some of the diagnostics controlled by this flag are enabled by default.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------+--------------------+---------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`types declared in an anonymous` |nbsp| |+------------------+| |nbsp| :diagtext:`are a Microsoft extension`|
+| ||:diagtext:`struct`|| |
+| |+------------------+| |
+| ||:diagtext:`union` || |
+| |+------------------+| |
++-----------------------------------------------------------------------------+--------------------+---------------------------------------------+
+
++--------------------------------------------------------+---------------------+---------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`anonymous` |nbsp| |+-------------------+| |nbsp| :diagtext:`are a Microsoft extension`|
+| ||:diagtext:`structs`|| |
+| |+-------------------+| |
+| ||:diagtext:`unions` || |
+| |+-------------------+| |
++--------------------------------------------------------+---------------------+---------------------------------------------+
+
+
+-Wmicrosoft-cast
+----------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`static\_cast between pointer-to-function and pointer-to-object is a Microsoft extension`|
++------------------------------------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`implicit conversion between pointer-to-function and pointer-to-object is a Microsoft extension`|
++-------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wmicrosoft-charize
+-------------------
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`charizing operator #@ is a Microsoft extension`|
++-------------------------------------------------------------------------------------+
+
+
+-Wmicrosoft-comment-paste
+-------------------------
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`pasting two '/' tokens into a '//' comment is a Microsoft extension`|
++----------------------------------------------------------------------------------------------------------+
+
+
+-Wmicrosoft-const-init
+----------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------+--------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`default initialization of an object of const type` |nbsp| :placeholder:`A`|+---------------------------------------------------------------+| |nbsp| :diagtext:`is a Microsoft extension`|
+| || || |
+| |+---------------------------------------------------------------+| |
+| || |nbsp| :diagtext:`without a user-provided default constructor`|| |
+| |+---------------------------------------------------------------+| |
++----------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------+--------------------------------------------+
+
+
+-Wmicrosoft-cpp-macro
+---------------------
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`C++ operator` |nbsp| :placeholder:`A` |nbsp| :diagtext:`(aka` |nbsp| :placeholder:`B`:diagtext:`) used as a macro name`|
++-------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wmicrosoft-default-arg-redefinition
+------------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`redefinition of default argument`|
++-----------------------------------------------------------------------+
+
+
+-Wmicrosoft-end-of-file
+-----------------------
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`treating Ctrl-Z as end-of-file is a Microsoft extension`|
++----------------------------------------------------------------------------------------------+
+
+
+-Wmicrosoft-enum-forward-reference
+----------------------------------
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`forward references to 'enum' types are a Microsoft extension`|
++---------------------------------------------------------------------------------------------------+
+
+
+-Wmicrosoft-enum-value
+----------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`enumerator value is not representable in the underlying type` |nbsp| :placeholder:`A`|
++---------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wmicrosoft-exception-spec
+--------------------------
+Some of the diagnostics controlled by this flag are enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`exception specification of '...' is a Microsoft extension`|
++------------------------------------------------------------------------------------------------+
+
++---------------------------+----------------------------------+----------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| |+--------------------------------+|:diagtext:`incomplete type` |nbsp| :placeholder:`B` |nbsp| :diagtext:`is not allowed in exception specification`|
+| || || |
+| |+--------------------------------+| |
+| ||:diagtext:`pointer to` |nbsp| || |
+| |+--------------------------------+| |
+| ||:diagtext:`reference to` |nbsp| || |
+| |+--------------------------------+| |
++---------------------------+----------------------------------+----------------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`exception specification in declaration does not match previous declaration`|
++-----------------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`exception specification in explicit instantiation does not match instantiated one`|
++------------------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is missing exception specification '`:placeholder:`B`:diagtext:`'`|
++--------------------------------------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`exception specification of overriding function is more lax than base version`|
++-------------------------------------------------------------------------------------------------------------------+
+
+
+-Wmicrosoft-exists
+------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------------+---------------------------------+--------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`dependent` |nbsp| |+-------------------------------+| |nbsp| :diagtext:`declarations are ignored`|
+| ||:diagtext:`\_\_if\_not\_exists`|| |
+| |+-------------------------------+| |
+| ||:diagtext:`\_\_if\_exists` || |
+| |+-------------------------------+| |
++--------------------------------------------------------+---------------------------------+--------------------------------------------+
+
+
+-Wmicrosoft-explicit-constructor-call
+-------------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`explicit constructor calls are a Microsoft extension`|
++-------------------------------------------------------------------------------------------+
+
+
+-Wmicrosoft-extra-qualification
+-------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`extra qualification on member` |nbsp| :placeholder:`A`|
++--------------------------------------------------------------------------------------------+
+
+
+-Wmicrosoft-fixed-enum
+----------------------
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`enumeration types with a fixed underlying type are a Microsoft extension`|
++---------------------------------------------------------------------------------------------------------------+
+
+
+-Wmicrosoft-flexible-array
+--------------------------
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------------------------+-----------------------+--------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`flexible array member` |nbsp| :placeholder:`A` |nbsp| :diagtext:`in otherwise empty` |nbsp| |+---------------------+| |nbsp| :diagtext:`is a Microsoft extension`|
+| ||:diagtext:`struct` || |
+| |+---------------------+| |
+| ||:diagtext:`interface`|| |
+| |+---------------------+| |
+| ||:diagtext:`union` || |
+| |+---------------------+| |
+| ||:diagtext:`class` || |
+| |+---------------------+| |
+| ||:diagtext:`enum` || |
+| |+---------------------+| |
++----------------------------------------------------------------------------------------------------------------------------------+-----------------------+--------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`flexible array member` |nbsp| :placeholder:`A` |nbsp| :diagtext:`in a union is a Microsoft extension`|
++-------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wmicrosoft-goto
+----------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`jump from this goto statement to its label is a Microsoft extension`|
++----------------------------------------------------------------------------------------------------------+
+
+
+-Wmicrosoft-include
+-------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`#include resolved using non-portable Microsoft search rules as:` |nbsp| :placeholder:`A`|
++------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wmicrosoft-mutable-reference
+-----------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'mutable' on a reference type is a Microsoft extension`|
++---------------------------------------------------------------------------------------------+
+
+
+-Wmicrosoft-pure-definition
+---------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`function definition with pure-specifier is a Microsoft extension`|
++-------------------------------------------------------------------------------------------------------+
+
+
+-Wmicrosoft-redeclare-static
+----------------------------
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`redeclaring non-static` |nbsp| :placeholder:`A` |nbsp| :diagtext:`as static is a Microsoft extension`|
++-------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wmicrosoft-sealed
+------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'sealed' keyword is a Microsoft extension`|
++--------------------------------------------------------------------------------+
+
+
+-Wmicrosoft-template
+--------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`duplicate explicit instantiation of` |nbsp| :placeholder:`A` |nbsp| :diagtext:`ignored as a Microsoft extension`|
++------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`use of identifier` |nbsp| :placeholder:`A` |nbsp| :diagtext:`found via unqualified lookup into dependent bases of class templates is a Microsoft extension`|
++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`explicit specialization of` |nbsp| :placeholder:`A` |nbsp| :diagtext:`within class scope is a Microsoft extension`|
++--------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`using the undeclared type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`as a default template argument is a Microsoft extension`|
++-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`non-type template argument containing a dereference operation is a Microsoft extension`|
++-----------------------------------------------------------------------------------------------------------------------------+
+
++---------------------------+---------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| |+-------------------------------------+| |nbsp| :diagtext:`specialization of` |nbsp| :placeholder:`B` |nbsp| :diagtext:`outside namespace enclosing` |nbsp| :placeholder:`C` |nbsp| :diagtext:`is a Microsoft extension`|
+| ||:diagtext:`class template` || |
+| |+-------------------------------------+| |
+| ||:diagtext:`class template partial` || |
+| |+-------------------------------------+| |
+| ||:diagtext:`variable template` || |
+| |+-------------------------------------+| |
+| ||:diagtext:`variable template partial`|| |
+| |+-------------------------------------+| |
+| ||:diagtext:`function template` || |
+| |+-------------------------------------+| |
+| ||:diagtext:`member function` || |
+| |+-------------------------------------+| |
+| ||:diagtext:`static data member` || |
+| |+-------------------------------------+| |
+| ||:diagtext:`member class` || |
+| |+-------------------------------------+| |
+| ||:diagtext:`member enumeration` || |
+| |+-------------------------------------+| |
++---------------------------+---------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`template argument for template type parameter must be a type; omitted 'typename' is a Microsoft extension`|
++------------------------------------------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`use of undeclared identifier` |nbsp| :placeholder:`A`:diagtext:`; unqualified lookup into dependent bases of class template` |nbsp| :placeholder:`B` |nbsp| :diagtext:`is a Microsoft extension`|
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wmicrosoft-union-member-reference
+----------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`union member` |nbsp| :placeholder:`A` |nbsp| :diagtext:`has reference type` |nbsp| :placeholder:`B`:diagtext:`, which is a Microsoft extension`|
++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wmicrosoft-unqualified-friend
+------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`unqualified friend declaration referring to type outside of the nearest enclosing namespace is a Microsoft extension; add a nested name specifier`|
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wmicrosoft-using-decl
+----------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`using declaration referring to inaccessible member '`:placeholder:`A`:diagtext:`' (which refers to accessible member '`:placeholder:`B`:diagtext:`') is a Microsoft compatibility extension`|
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wmicrosoft-void-pseudo-dtor
+----------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`pseudo-destructors on type void are a Microsoft extension`|
++------------------------------------------------------------------------------------------------+
+
+
+-Wmismatched-new-delete
+-----------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++----------------------------------------------+------------------+---------------------------------------------------------------+------------------+-----------------------------------+------------------+--------------+
+|:warning:`warning:` |nbsp| :diagtext:`'delete`|+----------------+|:diagtext:`' applied to a pointer that was allocated with 'new`|+----------------+|:diagtext:`'; did you mean 'delete`|+----------------+|:diagtext:`'?`|
+| || || ||:diagtext:`\[\]`|| ||:diagtext:`\[\]`|| |
+| |+----------------+| |+----------------+| |+----------------+| |
+| ||:diagtext:`\[\]`|| || || || || |
+| |+----------------+| |+----------------+| |+----------------+| |
++----------------------------------------------+------------------+---------------------------------------------------------------+------------------+-----------------------------------+------------------+--------------+
+
+
+-Wmismatched-parameter-types
+----------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`conflicting parameter types in implementation of` |nbsp| :placeholder:`A`|
++---------------------------------------------------------------------------------------------------------------+
+
+
+-Wmismatched-return-types
+-------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`conflicting return type in implementation of` |nbsp| :placeholder:`A`|
++-----------------------------------------------------------------------------------------------------------+
+
+
+-Wmismatched-tags
+-----------------
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------+--------------------------+------------------------------+-----------------------------------------------------------+--------------------------+------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`C` |nbsp| :diagtext:`defined as` |nbsp| |+------------------------+|+----------------------------+| |nbsp| :diagtext:`here but previously declared as` |nbsp| |+------------------------+|+----------------------------+|
+| ||:diagtext:`a struct` ||| || ||:diagtext:`a struct` ||| ||
+| |+------------------------+|+----------------------------+| |+------------------------+|+----------------------------+|
+| ||:diagtext:`an interface`||| |nbsp| :diagtext:`template`|| ||:diagtext:`an interface`||| |nbsp| :diagtext:`template`||
+| |+------------------------+|+----------------------------+| |+------------------------+|+----------------------------+|
+| ||:diagtext:`a class` || | ||:diagtext:`a class` || |
+| |+------------------------+| | |+------------------------+| |
++---------------------------------------------------------------------------------+--------------------------+------------------------------+-----------------------------------------------------------+--------------------------+------------------------------+
+
++---------------------------+-----------------------+------------------------------+--------------------------------------------------------------------------------+-----------------------+------------------------------+
+|:warning:`warning:` |nbsp| |+---------------------+|+----------------------------+| |nbsp| :placeholder:`C` |nbsp| :diagtext:`was previously declared as a` |nbsp| |+---------------------+|+----------------------------+|
+| ||:diagtext:`struct` ||| || ||:diagtext:`struct` ||| ||
+| |+---------------------+|+----------------------------+| |+---------------------+|+----------------------------+|
+| ||:diagtext:`interface`||| |nbsp| :diagtext:`template`|| ||:diagtext:`interface`||| |nbsp| :diagtext:`template`||
+| |+---------------------+|+----------------------------+| |+---------------------+|+----------------------------+|
+| ||:diagtext:`class` || | ||:diagtext:`class` || |
+| |+---------------------+| | |+---------------------+| |
++---------------------------+-----------------------+------------------------------+--------------------------------------------------------------------------------+-----------------------+------------------------------+
+
+
+-Wmissing-braces
+----------------
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`suggest braces around initialization of subobject`|
++----------------------------------------------------------------------------------------+
+
+
+-Wmissing-declarations
+----------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`declaration does not declare anything`|
++----------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'`:placeholder:`A`:diagtext:`' is not permitted on a declaration of a type`|
++-----------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`typedef requires a name`|
++--------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'`:placeholder:`A`:diagtext:`' ignored on this declaration`|
++-------------------------------------------------------------------------------------------------+
+
+
+-Wmissing-exception-spec
+------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is missing exception specification '`:placeholder:`B`:diagtext:`'`|
++--------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wmissing-field-initializers
+----------------------------
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`missing field` |nbsp| :placeholder:`A` |nbsp| :diagtext:`initializer`|
++-----------------------------------------------------------------------------------------------------------+
+
+
+-Wmissing-format-attribute
+--------------------------
+This diagnostic flag exists for GCC compatibility, and has no effect in Clang.
+
+-Wmissing-include-dirs
+----------------------
+This diagnostic flag exists for GCC compatibility, and has no effect in Clang.
+
+-Wmissing-method-return-type
+----------------------------
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`method has no return type specified; defaults to 'id'`|
++--------------------------------------------------------------------------------------------+
+
+
+-Wmissing-noreturn
+------------------
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`block could be declared with attribute 'noreturn'`|
++----------------------------------------------------------------------------------------+
+
++---------------------------+----------------------+---------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| |+--------------------+| |nbsp| :placeholder:`B` |nbsp| :diagtext:`could be declared with attribute 'noreturn'`|
+| ||:diagtext:`function`|| |
+| |+--------------------+| |
+| ||:diagtext:`method` || |
+| |+--------------------+| |
++---------------------------+----------------------+---------------------------------------------------------------------------------------+
+
+
+-Wmissing-prototype-for-cc
+--------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`function with no prototype cannot use the` |nbsp| :placeholder:`A` |nbsp| :diagtext:`calling convention`|
++----------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wmissing-prototypes
+--------------------
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`no previous prototype for function` |nbsp| :placeholder:`A`|
++-------------------------------------------------------------------------------------------------+
+
+
+-Wmissing-selector-name
+-----------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`used as the name of the previous parameter rather than as part of the selector`|
++---------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wmissing-sysroot
+-----------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`no such sysroot directory: '`:placeholder:`A`:diagtext:`'`|
++------------------------------------------------------------------------------------------------+
+
+
+-Wmissing-variable-declarations
+-------------------------------
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`no previous extern declaration for non-static variable` |nbsp| :placeholder:`A`|
++---------------------------------------------------------------------------------------------------------------------+
+
+
+-Rmodule-build
+--------------
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------------+
+|:remark:`remark:` |nbsp| :diagtext:`building module '`:placeholder:`A`:diagtext:`' as '`:placeholder:`B`:diagtext:`'`|
++---------------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------+
+|:remark:`remark:` |nbsp| :diagtext:`finished building module '`:placeholder:`A`:diagtext:`'`|
++--------------------------------------------------------------------------------------------+
+
+
+-Wmodule-conflict
+-----------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`module '`:placeholder:`A`:diagtext:`' conflicts with already-imported module '`:placeholder:`B`:diagtext:`':` |nbsp| :placeholder:`C`|
++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wmodule-file-config-mismatch
+-----------------------------
+This diagnostic is an error by default, but the flag ``-Wno-module-file-config-mismatch`` can be used to disable the error.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:error:`error:` |nbsp| :diagtext:`module file` |nbsp| :placeholder:`A` |nbsp| :diagtext:`cannot be loaded due to a configuration mismatch with the current compilation`|
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wmodule-file-extension
+-----------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`duplicate module file extension block name '`:placeholder:`A`:diagtext:`'`|
++----------------------------------------------------------------------------------------------------------------+
+
+
+-Wmodule-import-in-extern-c
+---------------------------
+This diagnostic is an error by default, but the flag ``-Wno-module-import-in-extern-c`` can be used to disable the error.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------------------------------------------------+
+|:error:`error:` |nbsp| :diagtext:`import of C++ module '`:placeholder:`A`:diagtext:`' appears within extern "C" language linkage specification`|
++-----------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wmodules-ambiguous-internal-linkage
+------------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`ambiguous use of internal linkage declaration` |nbsp| :placeholder:`A` |nbsp| :diagtext:`defined in multiple modules`|
++-----------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wmodules-import-nested-redundant
+---------------------------------
+This diagnostic is an error by default, but the flag ``-Wno-modules-import-nested-redundant`` can be used to disable the error.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------------------------------------+
+|:error:`error:` |nbsp| :diagtext:`redundant #include of module '`:placeholder:`A`:diagtext:`' appears within` |nbsp| :placeholder:`B`|
++-------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wmost
+------
+Some of the diagnostics controlled by this flag are enabled by default.
+
+Controls `-Wcast-of-sel-type`_, `-Wchar-subscripts`_, `-Wcomment`_, `-Wdelete-non-virtual-dtor`_, `-Wextern-c-compat`_, `-Wfor-loop-analysis`_, `-Wformat`_, `-Wimplicit`_, `-Winfinite-recursion`_, `-Wmismatched-tags`_, `-Wmissing-braces`_, `-Wmove`_, `-Wmultichar`_, `-Wobjc-designated-initializers`_, `-Wobjc-missing-super-calls`_, `-Woverloaded-virtual`_, `-Wprivate-extern`_, `-Wreorder`_, `-Wreturn-type`_, `-Wself-assign`_, `-Wself-move`_, `-Wsizeof-array-argument`_, `-Wsizeof-array-decay`_, `-Wstring-plus-int`_, `-Wtrigraphs`_, `-Wuninitialized`_, `-Wunknown-pragmas`_, `-Wunused`_, `-Wvolatile-register-var`_.
+
+
+-Wmove
+------
+Controls `-Wpessimizing-move`_, `-Wredundant-move`_, `-Wself-move`_.
+
+
+-Wmsvc-include
+--------------
+Synonym for `-Wmicrosoft-include`_.
+
+
+-Wmultichar
+-----------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`multi-character character constant`|
++-------------------------------------------------------------------------+
+
+
+-Wmultiple-move-vbase
+---------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`defaulted move assignment operator of` |nbsp| :placeholder:`A` |nbsp| :diagtext:`will move assign virtual base class` |nbsp| :placeholder:`B` |nbsp| :diagtext:`multiple times`|
++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wnarrowing
+-----------
+Synonym for `-Wc++11-narrowing`_.
+
+
+-Wnested-anon-types
+-------------------
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------+--------------------+------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`anonymous types declared in an anonymous` |nbsp| |+------------------+| |nbsp| :diagtext:`are an extension`|
+| ||:diagtext:`struct`|| |
+| |+------------------+| |
+| ||:diagtext:`union` || |
+| |+------------------+| |
++---------------------------------------------------------------------------------------+--------------------+------------------------------------+
+
+
+-Wnested-externs
+----------------
+This diagnostic flag exists for GCC compatibility, and has no effect in Clang.
+
+-Wnew-returns-null
+------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------------------------------+-----------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`should not return a null pointer unless it is declared 'throw()'`|+---------------------------------+|
+| || ||
+| |+---------------------------------+|
+| || |nbsp| :diagtext:`or 'noexcept'`||
+| |+---------------------------------+|
++-------------------------------------------------------------------------------------------------------------------------------+-----------------------------------+
+
+
+-Wnewline-eof
+-------------
+**Diagnostic text:**
+
++----------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`no newline at end of file`|
++----------------------------------------------------------------+
+
++----------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`no newline at end of file`|
++----------------------------------------------------------------+
+
+
+-Wnon-gcc
+---------
+Some of the diagnostics controlled by this flag are enabled by default.
+
+Controls `-Wconversion`_, `-Wliteral-range`_, `-Wsign-compare`_.
+
+
+-Wnon-literal-null-conversion
+-----------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`expression which evaluates to zero treated as a null pointer constant of type` |nbsp| :placeholder:`A`|
++--------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wnon-modular-include-in-framework-module
+-----------------------------------------
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`include of non-modular header inside framework module '`:placeholder:`A`:diagtext:`'`|
++---------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wnon-modular-include-in-module
+-------------------------------
+Also controls `-Wnon-modular-include-in-framework-module`_.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`include of non-modular header inside module '`:placeholder:`A`:diagtext:`'`|
++-----------------------------------------------------------------------------------------------------------------+
+
+
+-Wnon-pod-varargs
+-----------------
+This diagnostic is an error by default, but the flag ``-Wno-non-pod-varargs`` can be used to disable the error.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------+-------------------------+--------------------------------------------------------------------------------------------+-------------------------+----------------------------------------+
+|:error:`error:` |nbsp| :diagtext:`cannot pass object of` |nbsp| |+-----------------------+| |nbsp| :diagtext:`type` |nbsp| :placeholder:`B` |nbsp| :diagtext:`through variadic` |nbsp| |+-----------------------+|:diagtext:`; call will abort at runtime`|
+| ||:diagtext:`non-POD` || ||:diagtext:`function` || |
+| |+-----------------------+| |+-----------------------+| |
+| ||:diagtext:`non-trivial`|| ||:diagtext:`block` || |
+| |+-----------------------+| |+-----------------------+| |
+| | | ||:diagtext:`method` || |
+| | | |+-----------------------+| |
+| | | ||:diagtext:`constructor`|| |
+| | | |+-----------------------+| |
++----------------------------------------------------------------+-------------------------+--------------------------------------------------------------------------------------------+-------------------------+----------------------------------------+
+
++------------------------------------------------------+-------------------------+-------------------------------------------------------------------------------------------------+-------------------------+--------------------------------------------------------------------------+
+|:error:`error:` |nbsp| :diagtext:`cannot pass` |nbsp| |+-----------------------+| |nbsp| :diagtext:`object of type` |nbsp| :placeholder:`B` |nbsp| :diagtext:`to variadic` |nbsp| |+-----------------------+|:diagtext:`; expected type from format string was` |nbsp| :placeholder:`D`|
+| ||:diagtext:`non-POD` || ||:diagtext:`function` || |
+| |+-----------------------+| |+-----------------------+| |
+| ||:diagtext:`non-trivial`|| ||:diagtext:`block` || |
+| |+-----------------------+| |+-----------------------+| |
+| | | ||:diagtext:`method` || |
+| | | |+-----------------------+| |
+| | | ||:diagtext:`constructor`|| |
+| | | |+-----------------------+| |
++------------------------------------------------------+-------------------------+-------------------------------------------------------------------------------------------------+-------------------------+--------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------------+
+|:error:`error:` |nbsp| :diagtext:`second argument to 'va\_arg' is of non-POD type` |nbsp| :placeholder:`A`|
++----------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------------------+
+|:error:`error:` |nbsp| :diagtext:`second argument to 'va\_arg' is of ARC ownership-qualified type` |nbsp| :placeholder:`A`|
++--------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wnon-virtual-dtor
+------------------
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`has virtual functions but non-virtual destructor`|
++---------------------------------------------------------------------------------------------------------------+
+
+
+-Wnonnull
+---------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`null passed to a callee that requires a non-null argument`|
++------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------+----------------------+---------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`null returned from` |nbsp| |+--------------------+| |nbsp| :diagtext:`that requires a non-null return value`|
+| ||:diagtext:`function`|| |
+| |+--------------------+| |
+| ||:diagtext:`method` || |
+| |+--------------------+| |
++-----------------------------------------------------------------+----------------------+---------------------------------------------------------+
+
+
+-Wnonportable-cfstrings
+-----------------------
+This diagnostic flag exists for GCC compatibility, and has no effect in Clang.
+
+-Wnonportable-include-path
+--------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`non-portable path to file '`:placeholder:`A`:diagtext:`'; specified path differs in case from file name on disk`|
++------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wnonportable-system-include-path
+---------------------------------
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`non-portable path to file '`:placeholder:`A`:diagtext:`'; specified path differs in case from file name on disk`|
++------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wnonportable-vector-initialization
+-----------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`vector initializers are not compatible with NEON intrinsics in big endian mode`|
++---------------------------------------------------------------------------------------------------------------------+
+
+
+-Wnull-arithmetic
+-----------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`use of NULL in arithmetic operation`|
++--------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------+--------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`comparison between NULL and non-pointer` |nbsp| |+------------------------------------------------------------+|
+| ||+----------------------------------------------------------+||
+| |||:diagtext:`(`:placeholder:`B` |nbsp| :diagtext:`and NULL)`|||
+| ||+----------------------------------------------------------+||
+| |+------------------------------------------------------------+|
+| ||+----------------------------------------------------------+||
+| |||:diagtext:`(NULL and` |nbsp| :placeholder:`B`:diagtext:`)`|||
+| ||+----------------------------------------------------------+||
+| |+------------------------------------------------------------+|
++--------------------------------------------------------------------------------------+--------------------------------------------------------------+
+
+
+-Wnull-character
+----------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------+--------------------+---------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`null character(s) preserved in` |nbsp| |+------------------+| |nbsp| :diagtext:`literal`|
+| ||:diagtext:`char` || |
+| |+------------------+| |
+| ||:diagtext:`string`|| |
+| |+------------------+| |
++-----------------------------------------------------------------------------+--------------------+---------------------------+
+
++-------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`null character ignored`|
++-------------------------------------------------------------+
+
+
+-Wnull-conversion
+-----------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------+---------------------+-------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`implicit conversion of` |nbsp| |+-------------------+| |nbsp| :diagtext:`constant to` |nbsp| :placeholder:`B`|
+| ||:diagtext:`NULL` || |
+| |+-------------------+| |
+| ||:diagtext:`nullptr`|| |
+| |+-------------------+| |
++---------------------------------------------------------------------+---------------------+-------------------------------------------------------+
+
+
+-Wnull-dereference
+------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`binding dereferenced null pointer to reference has undefined behavior`|
++------------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`indirection of non-volatile null pointer will be deleted, not trap`|
++---------------------------------------------------------------------------------------------------------+
+
+
+-Wnullability
+-------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`conflicting nullability specifier on parameter types,` |nbsp| :placeholder:`A` |nbsp| :diagtext:`conflicts with existing specifier` |nbsp| :placeholder:`B`|
++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`conflicting nullability specifier on return types,` |nbsp| :placeholder:`A` |nbsp| :diagtext:`conflicts with existing specifier` |nbsp| :placeholder:`B`|
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`nullability specifier` |nbsp| :placeholder:`A` |nbsp| :diagtext:`conflicts with existing specifier` |nbsp| :placeholder:`B`|
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`synthesized setter` |nbsp| :placeholder:`A` |nbsp| :diagtext:`for null\_resettable property` |nbsp| :placeholder:`B` |nbsp| :diagtext:`does not handle nil`|
++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`duplicate nullability specifier` |nbsp| :placeholder:`A`|
++----------------------------------------------------------------------------------------------+
+
+
+-Wnullability-completeness
+--------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------+----------------------------+-----------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| |+--------------------------+| |nbsp| :diagtext:`is missing a nullability type specifier (\_Nonnull, \_Nullable, or \_Null\_unspecified)`|
+| ||:diagtext:`pointer` || |
+| |+--------------------------+| |
+| ||:diagtext:`block pointer` || |
+| |+--------------------------+| |
+| ||:diagtext:`member pointer`|| |
+| |+--------------------------+| |
++---------------------------+----------------------------+-----------------------------------------------------------------------------------------------------------+
+
+
+-Wnullability-declspec
+----------------------
+This diagnostic is an error by default, but the flag ``-Wno-nullability-declspec`` can be used to disable the error.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------+-------------+
+|:error:`error:` |nbsp| :diagtext:`nullability specifier` |nbsp| :placeholder:`A` |nbsp| :diagtext:`cannot be applied to non-pointer type` |nbsp| :placeholder:`B`:diagtext:`; did you mean to apply the specifier to the` |nbsp| |+-----------------------------------+|:diagtext:`?`|
+| ||:diagtext:`pointer` || |
+| |+-----------------------------------+| |
+| ||:diagtext:`block pointer` || |
+| |+-----------------------------------+| |
+| ||:diagtext:`member pointer` || |
+| |+-----------------------------------+| |
+| ||:diagtext:`function pointer` || |
+| |+-----------------------------------+| |
+| ||:diagtext:`member function pointer`|| |
+| |+-----------------------------------+| |
++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------+-------------+
+
+
+-Wnullability-extension
+-----------------------
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`type nullability specifier` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is a Clang extension`|
++---------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wnullable-to-nonnull-conversion
+--------------------------------
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`implicit conversion from nullable pointer` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to non-nullable pointer type` |nbsp| :placeholder:`B`|
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wobjc-autosynthesis-property-ivar-name-match
+---------------------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------------------+-------------------------+---------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`autosynthesized property` |nbsp| :placeholder:`A` |nbsp| :diagtext:`will use` |nbsp| |+-----------------------+| |nbsp| :diagtext:`instance variable` |nbsp| :placeholder:`C`:diagtext:`, not existing instance variable` |nbsp| :placeholder:`D`|
+| || || |
+| |+-----------------------+| |
+| ||:diagtext:`synthesized`|| |
+| |+-----------------------+| |
++---------------------------------------------------------------------------------------------------------------------------+-------------------------+---------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wobjc-circular-container
+-------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`adding '`:placeholder:`A`:diagtext:`' to '`:placeholder:`B`:diagtext:`' might cause circular dependency in container`|
++-----------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wobjc-cocoa-api
+----------------
+Synonym for `-Wobjc-redundant-api-use`_.
+
+
+-Wobjc-designated-initializers
+------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`designated initializer missing a 'super' call to a designated initializer of the super class`|
++-----------------------------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`designated initializer invoked a non-designated initializer`|
++--------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`designated initializer should only invoke a designated initializer on 'super'`|
++--------------------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`method override for the designated initializer of the superclass` |nbsp| :placeholder:`A` |nbsp| :diagtext:`not found`|
++------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`convenience initializer missing a 'self' call to another initializer`|
++-----------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`convenience initializer should not invoke an initializer on 'super'`|
++----------------------------------------------------------------------------------------------------------+
+
+
+-Wobjc-forward-class-redefinition
+---------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`redefinition of forward class` |nbsp| :placeholder:`A` |nbsp| :diagtext:`of a typedef name of an object type is ignored`|
++--------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wobjc-interface-ivars
+----------------------
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`declaration of instance variables in the interface is deprecated`|
++-------------------------------------------------------------------------------------------------------+
+
+
+-Wobjc-literal-compare
+----------------------
+This diagnostic is enabled by default.
+
+Also controls `-Wobjc-string-compare`_.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------+----------------------------------+------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`direct comparison of` |nbsp| |+--------------------------------+| |nbsp| :diagtext:`has undefined behavior`|
+| ||:diagtext:`an array literal` || |
+| |+--------------------------------+| |
+| ||:diagtext:`a dictionary literal`|| |
+| |+--------------------------------+| |
+| ||:diagtext:`a numeric literal` || |
+| |+--------------------------------+| |
+| ||:diagtext:`a boxed expression` || |
+| |+--------------------------------+| |
+| || || |
+| |+--------------------------------+| |
++-------------------------------------------------------------------+----------------------------------+------------------------------------------+
+
+
+-Wobjc-literal-conversion
+-------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`implicit boolean conversion of Objective-C object literal always evaluates to true`|
++-------------------------------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------------------------------+-----------------------------------+------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`object of type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is not compatible with` |nbsp| |+---------------------------------+| |nbsp| :placeholder:`C`|
+| ||:diagtext:`array element type` || |
+| |+---------------------------------+| |
+| ||:diagtext:`dictionary key type` || |
+| |+---------------------------------+| |
+| ||:diagtext:`dictionary value type`|| |
+| |+---------------------------------+| |
++-------------------------------------------------------------------------------------------------------------------------------+-----------------------------------+------------------------+
+
+
+-Wobjc-macro-redefinition
+-------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`ignoring redefinition of Objective-C qualifier macro`|
++-------------------------------------------------------------------------------------------+
+
+
+-Wobjc-method-access
+--------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`class method` |nbsp| :placeholder:`A` |nbsp| :diagtext:`not found (return type defaults to 'id')`|
++---------------------------------------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`class method` |nbsp| :placeholder:`A` |nbsp| :diagtext:`not found (return type defaults to 'id'); did you mean` |nbsp| :placeholder:`C`:diagtext:`?`|
++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`instance method` |nbsp| :placeholder:`A` |nbsp| :diagtext:`not found (return type defaults to 'id')`|
++------------------------------------------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`instance method` |nbsp| :placeholder:`A` |nbsp| :diagtext:`not found (return type defaults to 'id'); did you mean` |nbsp| :placeholder:`C`:diagtext:`?`|
++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`instance method` |nbsp| :placeholder:`A` |nbsp| :diagtext:`found instead of class method` |nbsp| :placeholder:`B`|
++-------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`instance method` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is being used on 'Class' which is not in the root class`|
++---------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wobjc-missing-property-synthesis
+---------------------------------
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`auto property synthesis is synthesizing property not explicitly synthesized`|
++------------------------------------------------------------------------------------------------------------------+
+
+
+-Wobjc-missing-super-calls
+--------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`method possibly missing a \[super` |nbsp| :placeholder:`A`:diagtext:`\] call`|
++-------------------------------------------------------------------------------------------------------------------+
+
+
+-Wobjc-multiple-method-names
+----------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`multiple methods named` |nbsp| :placeholder:`A` |nbsp| :diagtext:`found`|
++--------------------------------------------------------------------------------------------------------------+
+
+
+-Wobjc-noncopy-retain-block-property
+------------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`retain'ed block property does not copy the block - use copy attribute instead`|
++--------------------------------------------------------------------------------------------------------------------+
+
+
+-Wobjc-nonunified-exceptions
+----------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`cannot catch an exception thrown with @throw in C++ in the non-unified exception model`|
++-----------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wobjc-property-implementation
+------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`class property` |nbsp| :placeholder:`A` |nbsp| :diagtext:`requires method` |nbsp| :placeholder:`B` |nbsp| :diagtext:`to be defined - use @dynamic or provide a method implementation in this class implementation`|
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`class property` |nbsp| :placeholder:`A` |nbsp| :diagtext:`requires method` |nbsp| :placeholder:`B` |nbsp| :diagtext:`to be defined - use @dynamic or provide a method implementation in this category`|
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`property` |nbsp| :placeholder:`A` |nbsp| :diagtext:`requires method` |nbsp| :placeholder:`B` |nbsp| :diagtext:`to be defined - use @synthesize, @dynamic or provide a method implementation in this class implementation`|
++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`property` |nbsp| :placeholder:`A` |nbsp| :diagtext:`requires method` |nbsp| :placeholder:`B` |nbsp| :diagtext:`to be defined - use @dynamic or provide a method implementation in this category`|
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wobjc-property-implicit-mismatch
+---------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`primary property declaration is implicitly strong while redeclaration in class extension is weak`|
++---------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wobjc-property-matches-cocoa-ownership-rule
+--------------------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`property follows Cocoa naming convention for returning 'owned' objects`|
++-------------------------------------------------------------------------------------------------------------+
+
+
+-Wobjc-property-no-attribute
+----------------------------
+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:`no 'assign', 'retain', or 'copy' attribute is specified - 'assign' is assumed`|
++--------------------------------------------------------------------------------------------------------------------+
+
+
+-Wobjc-property-synthesis
+-------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`auto property synthesis will not synthesize property` |nbsp| :placeholder:`A`:diagtext:`; it will be implemented by its superclass, use @dynamic to acknowledge intention`|
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`auto property synthesis will not synthesize property` |nbsp| :placeholder:`A` |nbsp| :diagtext:`because it is 'readwrite' but it will be synthesized 'readonly' via another property`|
++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`auto property synthesis will not synthesize property` |nbsp| :placeholder:`A` |nbsp| :diagtext:`because it cannot share an ivar with another synthesized property`|
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wobjc-protocol-method-implementation
+-------------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`category is implementing a method which will also be implemented by its primary class`|
++----------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wobjc-protocol-property-synthesis
+----------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`auto property synthesis will not synthesize property` |nbsp| :placeholder:`A` |nbsp| :diagtext:`declared in protocol` |nbsp| :placeholder:`B`|
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wobjc-protocol-qualifiers
+--------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`parameterized class` |nbsp| :placeholder:`A` |nbsp| :diagtext:`already conforms to the protocols listed; did you forget a '\*'?`|
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wobjc-readonly-with-setter-property
+------------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`setter cannot be specified for a readonly property`|
++-----------------------------------------------------------------------------------------+
+
+
+-Wobjc-redundant-api-use
+------------------------
+Synonym for `-Wobjc-redundant-literal-use`_.
+
+
+-Wobjc-redundant-literal-use
+----------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`using` |nbsp| :placeholder:`A` |nbsp| :diagtext:`with a literal is redundant`|
++-------------------------------------------------------------------------------------------------------------------+
+
+
+-Wobjc-root-class
+-----------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`class` |nbsp| :placeholder:`A` |nbsp| :diagtext:`defined without specifying a base class`|
++-------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wobjc-string-compare
+---------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`direct comparison of a string literal has undefined behavior`|
++---------------------------------------------------------------------------------------------------+
+
+
+-Wobjc-string-concatenation
+---------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`concatenated NSString literal for an NSArray expression - possibly missing a comma`|
++-------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wodr
+-----
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`has incompatible definitions in different translation units`|
++--------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wold-style-cast
+----------------
+**Diagnostic text:**
+
++------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`use of old-style cast`|
++------------------------------------------------------------+
+
+
+-Wold-style-definition
+----------------------
+This diagnostic flag exists for GCC compatibility, and has no effect in Clang.
+
+-Wopencl-unsupported-rgba
+-------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`vector component name '`:placeholder:`A`:diagtext:`' is an OpenCL version 2.2 feature`|
++----------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wopenmp-clauses
+----------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`aligned clause will be ignored because the requested alignment is not a power of 2`|
++-------------------------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------+---------------------------------------------------+-------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`zero linear step (`:placeholder:`A` |nbsp| |+-------------------------------------------------+|:diagtext:`should probably be const)`|
+| || || |
+| |+-------------------------------------------------+| |
+| ||:diagtext:`and other variables in clause` |nbsp| || |
+| |+-------------------------------------------------+| |
++---------------------------------------------------------------------------------+---------------------------------------------------+-------------------------------------+
+
+
+-Wopenmp-loop-form
+------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')`|
++-----------------------------------------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`OpenMP loop iteration variable cannot have more than 64 bits size and will be narrowed`|
++-----------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wopenmp-target
+---------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`declaration is not declared in any declare target region`|
++-----------------------------------------------------------------------------------------------+
+
+
+-Woption-ignored
+----------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`option '`:placeholder:`A`:diagtext:`' was ignored by the PS4 toolchain, using '-fPIC'`|
++----------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wout-of-line-declaration
+-------------------------
+This diagnostic is an error by default, but the flag ``-Wno-out-of-line-declaration`` can be used to disable the error.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------+
+|:error:`error:` |nbsp| :diagtext:`out-of-line declaration of a member must be a definition`|
++-------------------------------------------------------------------------------------------+
+
+
+-Wover-aligned
+--------------
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`requires` |nbsp| :placeholder:`B` |nbsp| :diagtext:`bytes of alignment and the default allocator only guarantees` |nbsp| :placeholder:`C` |nbsp| :diagtext:`bytes`|
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Woverflow
+----------
+This diagnostic flag exists for GCC compatibility, and has no effect in Clang.
+
+-Woverlength-strings
+--------------------
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+-----------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`string literal of length` |nbsp| :placeholder:`A` |nbsp| :diagtext:`exceeds maximum length` |nbsp| :placeholder:`B` |nbsp| :diagtext:`that` |nbsp| |+-------------------+| |nbsp| :diagtext:`compilers are required to support`|
+| ||:diagtext:`C90` || |
+| |+-------------------+| |
+| ||:diagtext:`ISO C99`|| |
+| |+-------------------+| |
+| ||:diagtext:`C++` || |
+| |+-------------------+| |
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+-----------------------------------------------------+
+
+
+-Woverloaded-shift-op-parentheses
+---------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------+----------------+------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`overloaded operator` |nbsp| |+--------------+| |nbsp| :diagtext:`has higher precedence than comparison operator`|
+| ||:diagtext:`>>`|| |
+| |+--------------+| |
+| ||:diagtext:`<<`|| |
+| |+--------------+| |
++------------------------------------------------------------------+----------------+------------------------------------------------------------------+
+
+
+-Woverloaded-virtual
+--------------------
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------+-----------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`hides overloaded virtual` |nbsp| |+---------------------+|
+| ||:diagtext:`function` ||
+| |+---------------------+|
+| ||:diagtext:`functions`||
+| |+---------------------+|
++-----------------------------------------------------------------------------------------------+-----------------------+
+
+
+-Woverride-module
+-----------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`overriding the module target triple with` |nbsp| :placeholder:`A`|
++-------------------------------------------------------------------------------------------------------+
+
+
+-Woverriding-method-mismatch
+----------------------------
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`conflicting distributed object modifiers on parameter type in declaration of` |nbsp| :placeholder:`A`|
++-------------------------------------------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`conflicting parameter types in declaration of` |nbsp| :placeholder:`A`|
++------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`conflicting distributed object modifiers on return type in declaration of` |nbsp| :placeholder:`A`|
++----------------------------------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`conflicting return type in declaration of` |nbsp| :placeholder:`A`|
++--------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`conflicting variadic declaration of method and its implementation`|
++--------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`conflicting parameter types in declaration of` |nbsp| :placeholder:`A`:diagtext:`:` |nbsp| :placeholder:`B` |nbsp| :diagtext:`vs` |nbsp| :placeholder:`C`|
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`conflicting return type in declaration of` |nbsp| :placeholder:`A`:diagtext:`:` |nbsp| :placeholder:`B` |nbsp| :diagtext:`vs` |nbsp| :placeholder:`C`|
++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Woverriding-t-option
+---------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`overriding '`:placeholder:`A`:diagtext:`' option with '`:placeholder:`B`:diagtext:`'`|
++---------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wpacked
+--------
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`packed attribute is unnecessary for` |nbsp| :placeholder:`A`|
++--------------------------------------------------------------------------------------------------+
+
+
+-Wpadded
+--------
+**Diagnostic text:**
+
++------------------------------------------------------+-----------------------+--------------------------------------------------------------------------------+------------------+---------------+------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`padding` |nbsp| |+---------------------+| |nbsp| :placeholder:`B` |nbsp| :diagtext:`with` |nbsp| :placeholder:`C` |nbsp| |+----------------+|+-------------+| |nbsp| :diagtext:`to align anonymous bit-field`|
+| ||:diagtext:`struct` || ||:diagtext:`byte`||| || |
+| |+---------------------+| |+----------------+|+-------------+| |
+| ||:diagtext:`interface`|| ||:diagtext:`bit` |||:diagtext:`s`|| |
+| |+---------------------+| |+----------------+|+-------------+| |
+| ||:diagtext:`class` || | | | |
+| |+---------------------+| | | | |
++------------------------------------------------------+-----------------------+--------------------------------------------------------------------------------+------------------+---------------+------------------------------------------------+
+
++------------------------------------------------------+-----------------------+--------------------------------------------------------------------------------+------------------+---------------+----------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`padding` |nbsp| |+---------------------+| |nbsp| :placeholder:`B` |nbsp| :diagtext:`with` |nbsp| :placeholder:`C` |nbsp| |+----------------+|+-------------+| |nbsp| :diagtext:`to align` |nbsp| :placeholder:`E`|
+| ||:diagtext:`struct` || ||:diagtext:`byte`||| || |
+| |+---------------------+| |+----------------+|+-------------+| |
+| ||:diagtext:`interface`|| ||:diagtext:`bit` |||:diagtext:`s`|| |
+| |+---------------------+| |+----------------+|+-------------+| |
+| ||:diagtext:`class` || | | | |
+| |+---------------------+| | | | |
++------------------------------------------------------+-----------------------+--------------------------------------------------------------------------------+------------------+---------------+----------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------------------------------+------------------+---------------+-----------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`padding size of` |nbsp| :placeholder:`A` |nbsp| :diagtext:`with` |nbsp| :placeholder:`B` |nbsp| |+----------------+|+-------------+| |nbsp| :diagtext:`to alignment boundary`|
+| ||:diagtext:`byte`||| || |
+| |+----------------+|+-------------+| |
+| ||:diagtext:`bit` |||:diagtext:`s`|| |
+| |+----------------+|+-------------+| |
++--------------------------------------------------------------------------------------------------------------------------------------+------------------+---------------+-----------------------------------------+
+
+
+-Wparentheses
+-------------
+This diagnostic is enabled by default.
+
+Also controls `-Wbitwise-op-parentheses`_, `-Wdangling-else`_, `-Wlogical-not-parentheses`_, `-Wlogical-op-parentheses`_, `-Woverloaded-shift-op-parentheses`_, `-Wparentheses-equality`_, `-Wshift-op-parentheses`_.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`using the result of an assignment as a condition without parentheses`|
++-----------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`has lower precedence than` |nbsp| :placeholder:`B`:diagtext:`;` |nbsp| :placeholder:`B` |nbsp| :diagtext:`will be evaluated first`|
++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`operator '?:' has lower precedence than '`:placeholder:`A`:diagtext:`'; '`:placeholder:`A`:diagtext:`' will be evaluated first`|
++---------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wparentheses-equality
+----------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`equality comparison with extraneous parentheses`|
++--------------------------------------------------------------------------------------+
+
+
+-Wpartial-availability
+----------------------
+Synonym for `-Wunguarded-availability`_.
+
+
+-Rpass
+------
+**Diagnostic text:**
+
+The text of this diagnostic is not controlled by Clang.
+
+
+-Rpass-analysis
+---------------
+**Diagnostic text:**
+
+The text of this diagnostic is not controlled by Clang.
+
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:remark:`remark:` |nbsp| :placeholder:`A`:diagtext:`; allow reordering by specifying '#pragma clang loop vectorize(enable)' before the loop. If the arrays will always be independent specify '#pragma clang loop vectorize(assume\_safety)' before the loop or provide the '\_\_restrict\_\_' qualifier with the independent array arguments. Erroneous results will occur if these options are incorrectly applied!`|
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:remark:`remark:` |nbsp| :placeholder:`A`:diagtext:`; allow reordering by specifying '#pragma clang loop vectorize(enable)' before the loop or by providing the compiler option '-ffast-math'.`|
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wpass-failed
+-------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
+The text of this diagnostic is not controlled by Clang.
+
+
+-Rpass-missed
+-------------
+**Diagnostic text:**
+
+The text of this diagnostic is not controlled by Clang.
+
+
+-Wpch-date-time
+---------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------+--------------------------------+-----------------------------------------------------+
+|:warning:`warning:` |nbsp| |+------------------------------+| |nbsp| :diagtext:`uses \_\_DATE\_\_ or \_\_TIME\_\_`|
+| ||:diagtext:`precompiled header`|| |
+| |+------------------------------+| |
+| ||:diagtext:`module` || |
+| |+------------------------------+| |
++---------------------------+--------------------------------+-----------------------------------------------------+
+
+
+-Wpedantic
+----------
+Also controls `-Wc++11-extra-semi`_, `-Wc++11-long-long`_, `-Wc++14-binary-literal`_, `-Wc11-extensions`_, `-Wcomplex-component-init`_, `-Wdeclaration-after-statement`_, `-Wdollar-in-identifier-extension`_, `-Wembedded-directive`_, `-Wempty-translation-unit`_, `-Wextended-offsetof`_, `-Wflexible-array-extensions`_, `-Wformat-pedantic`_, `-Wfour-char-constants`_, `-Wgnu-anonymous-struct`_, `-Wgnu-auto-type`_, `-Wgnu-binary-literal`_, `-Wgnu-case-range`_, `-Wgnu-complex-integer`_, `-Wgnu-compound-literal-initializer`_, `-Wgnu-conditional-omitted-operand`_, `-Wgnu-empty-initializer`_, `-Wgnu-empty-struct`_, `-Wgnu-flexible-array-initializer`_, `-Wgnu-flexible-array-union-member`_, `-Wgnu-folding-constant`_, `-Wgnu-imaginary-constant`_, `-Wgnu-include-next`_, `-Wgnu-label-as-value`_, `-Wgnu-redeclared-enum`_, `-Wgnu-statement-expression`_, `-Wgnu-union-cast`_, `-Wgnu-zero-line-directive`_, `-Wgnu-zero-variadic-macro-arguments`_, `-Wimport-preprocessor-directive-pedantic`_, `-Wkeyword-macro`_, `-Wlanguage-extension-token`_, `-Wlong-long`_, `-Wmicrosoft-charize`_, `-Wmicrosoft-comment-paste`_, `-Wmicrosoft-cpp-macro`_, `-Wmicrosoft-end-of-file`_, `-Wmicrosoft-enum-forward-reference`_, `-Wmicrosoft-fixed-enum`_, `-Wmicrosoft-flexible-array`_, `-Wmicrosoft-redeclare-static`_, `-Wnested-anon-types`_, `-Wnullability-extension`_, `-Woverlength-strings`_, `-Wretained-language-linkage`_, `-Wvariadic-macros`_, `-Wvla-extension`_, `-Wzero-length-array`_.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'enable\_if' is a clang extension`|
++------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`designated initializers are a C99 feature`|
++--------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`ISO C++ does not allow 'main' to be used by a program`|
++--------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------+
+|:warning:`warning:` |nbsp| :diagtext:`C++98 requires an accessible copy constructor for class` |nbsp| :placeholder:`C` |nbsp| :diagtext:`when binding a reference to a temporary; was` |nbsp| |+---------------------+|
+| ||:diagtext:`private` ||
+| |+---------------------+|
+| ||:diagtext:`protected`||
+| |+---------------------+|
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------+
+
++--------------------------------------------------------+--------------------+------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`anonymous` |nbsp| |+------------------+| |nbsp| :diagtext:`cannot be '`:placeholder:`B`:diagtext:`'`|
+| ||:diagtext:`struct`|| |
+| |+------------------+| |
+| ||:diagtext:`union` || |
+| |+------------------+| |
++--------------------------------------------------------+--------------------+------------------------------------------------------------+
+
++--------------------------------------------------------------------+-----------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`no viable constructor` |nbsp| |+---------------------------------------+| |nbsp| :diagtext:`of type` |nbsp| :placeholder:`B`:diagtext:`; C++98 requires a copy constructor when binding a reference to a temporary`|
+| ||:diagtext:`copying variable` || |
+| |+---------------------------------------+| |
+| ||:diagtext:`copying parameter` || |
+| |+---------------------------------------+| |
+| ||:diagtext:`returning object` || |
+| |+---------------------------------------+| |
+| ||:diagtext:`throwing object` || |
+| |+---------------------------------------+| |
+| ||:diagtext:`copying member subobject` || |
+| |+---------------------------------------+| |
+| ||:diagtext:`copying array element` || |
+| |+---------------------------------------+| |
+| ||:diagtext:`allocating object` || |
+| |+---------------------------------------+| |
+| ||:diagtext:`copying temporary` || |
+| |+---------------------------------------+| |
+| ||:diagtext:`initializing base subobject`|| |
+| |+---------------------------------------+| |
+| ||:diagtext:`initializing vector element`|| |
+| |+---------------------------------------+| |
+| ||:diagtext:`capturing value` || |
+| |+---------------------------------------+| |
++--------------------------------------------------------------------+-----------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`parameter` |nbsp| :placeholder:`A` |nbsp| :diagtext:`was not declared, defaulting to type 'int'`|
++--------------------------------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`qualifier in explicit instantiation of` |nbsp| :placeholder:`A` |nbsp| :diagtext:`requires a template-id (a typedef is not permitted)`|
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------+----------------------+-----------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`static` |nbsp| |+--------------------+| |nbsp| :placeholder:`B` |nbsp| :diagtext:`is used in an inline function with external linkage`|
+| ||:diagtext:`function`|| |
+| |+--------------------+| |
+| ||:diagtext:`variable`|| |
+| |+--------------------+| |
++-----------------------------------------------------+----------------------+-----------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`ISO C forbids forward references to 'enum' types`|
++---------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------------------------------------------------+-------------------+-------------+
+|:warning:`warning:` |nbsp| :diagtext:`ISO C restricts enumerator values to range of 'int' (`:placeholder:`A` |nbsp| :diagtext:`is too` |nbsp| |+-----------------+|:diagtext:`)`|
+| ||:diagtext:`small`|| |
+| |+-----------------+| |
+| ||:diagtext:`large`|| |
+| |+-----------------+| |
++----------------------------------------------------------------------------------------------------------------------------------------------+-------------------+-------------+
+
++--------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`size of static array must be an integer constant expression`|
++--------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`initializer for aggregate is not a compile-time constant`|
++-----------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`flexible array members are a C99 feature`|
++-------------------------------------------------------------------------------+
+
++---------------------------------------------------------------+-----------------------+--------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`invalid application of '`|+---------------------+|:diagtext:`' to a function type`|
+| ||:diagtext:`sizeof` || |
+| |+---------------------+| |
+| ||:diagtext:`alignof` || |
+| |+---------------------+| |
+| ||:diagtext:`vec\_step`|| |
+| |+---------------------+| |
++---------------------------------------------------------------+-----------------------+--------------------------------+
+
++---------------------------------------------------------------+-----------------------+----------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`invalid application of '`|+---------------------+|:diagtext:`' to a void type`|
+| ||:diagtext:`sizeof` || |
+| |+---------------------+| |
+| ||:diagtext:`alignof` || |
+| |+---------------------+| |
+| ||:diagtext:`vec\_step`|| |
+| |+---------------------+| |
++---------------------------------------------------------------+-----------------------+----------------------------+
+
++-------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`ISO C90 does not allow subscripting non-lvalue array`|
++-------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`subscript of a pointer to void is a GNU extension`|
++----------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`ISO C forbids taking the address of an expression of type 'void'`|
++-------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`ordered comparison between pointer and zero (`:placeholder:`A` |nbsp| :diagtext:`and` |nbsp| :placeholder:`B`:diagtext:`) is an extension`|
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`equality comparison between function pointer and void pointer (`:placeholder:`A` |nbsp| :diagtext:`and` |nbsp| :placeholder:`B`:diagtext:`)`|
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------+-----------------------+---------------------------+---------------+----------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`arithmetic on`|+---------------------+| |nbsp| :diagtext:`pointer`|+-------------+| |nbsp| :diagtext:`to void is a GNU extension`|
+| || |nbsp| :diagtext:`a`|| || || |
+| |+---------------------+| |+-------------+| |
+| || || ||:diagtext:`s`|| |
+| |+---------------------+| |+-------------+| |
++----------------------------------------------------+-----------------------+---------------------------+---------------+----------------------------------------------+
+
++----------------------------------------------------+-----------------------+---------------------------+---------------+----------------------+-------------------------+---------------------------------+---------------+------------------------+---------------------------------------------------+--------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`arithmetic on`|+---------------------+| |nbsp| :diagtext:`pointer`|+-------------+| |nbsp| :diagtext:`to`|+-----------------------+| |nbsp| :diagtext:`function type`|+-------------+| |nbsp| :placeholder:`B`|+-------------------------------------------------+| |nbsp| :diagtext:`is a GNU extension`|
+| || |nbsp| :diagtext:`a`|| || || || |nbsp| :diagtext:`the`|| || || || || |
+| |+---------------------+| |+-------------+| |+-----------------------+| |+-------------+| |+-------------------------------------------------+| |
+| || || ||:diagtext:`s`|| || || ||:diagtext:`s`|| ||+-----------------------------------------------+|| |
+| |+---------------------+| |+-------------+| |+-----------------------+| |+-------------+| ||| |nbsp| :diagtext:`and` |nbsp| :placeholder:`D`||| |
+| | | | | | | | | ||+-----------------------------------------------+|| |
+| | | | | | | | | |+-------------------------------------------------+| |
++----------------------------------------------------+-----------------------+---------------------------+---------------+----------------------+-------------------------+---------------------------------+---------------+------------------------+---------------------------------------------------+--------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`ISO C does not support '++'/'--' on complex integer type` |nbsp| :placeholder:`A`|
++-----------------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`ISO C does not support '~' for complex conjugation of` |nbsp| :placeholder:`A`|
++--------------------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`complex numbers are an extension in a freestanding C99 implementation`|
++------------------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`cast between pointer-to-function and pointer-to-object is an extension`|
++-------------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------+----------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`implicit conversion from array size expression of type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| |+-----------------------+| |nbsp| :diagtext:`type` |nbsp| :placeholder:`C` |nbsp| :diagtext:`is a C++11 extension`|
+| ||:diagtext:`integral` || |
+| |+-----------------------+| |
+| ||:diagtext:`enumeration`|| |
+| |+-----------------------+| |
++---------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------+----------------------------------------------------------------------------------------+
+
++---------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| |+--------------------------------------------------------------+| |nbsp| :diagtext:`converts between void pointer and function pointer`|
+| ||:diagtext:`assigning to different types` || |
+| |+--------------------------------------------------------------+| |
+| ||:diagtext:`passing to parameter of different type` || |
+| |+--------------------------------------------------------------+| |
+| ||:diagtext:`returning from function with different return type`|| |
+| |+--------------------------------------------------------------+| |
+| ||:diagtext:`converting between types` || |
+| |+--------------------------------------------------------------+| |
+| ||:diagtext:`initializing with expression of different type` || |
+| |+--------------------------------------------------------------+| |
+| ||:diagtext:`sending to parameter of different type` || |
+| |+--------------------------------------------------------------+| |
+| ||:diagtext:`casting between types` || |
+| |+--------------------------------------------------------------+| |
++---------------------------+----------------------------------------------------------------+----------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`kernel function` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is a member function; this may not be accepted by nvcc`|
++--------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`C99 forbids conditional expressions with only one void side`|
++--------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`C99 forbids casting nonscalar type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to the same type`|
++-------------------------------------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`use of the` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute is a C++14 extension`|
++---------------------------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`use of the` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute is a C++1z extension`|
++---------------------------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------+--------------------+---------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`types declared in an anonymous` |nbsp| |+------------------+| |nbsp| :diagtext:`are a Microsoft extension`|
+| ||:diagtext:`struct`|| |
+| |+------------------+| |
+| ||:diagtext:`union` || |
+| |+------------------+| |
++-----------------------------------------------------------------------------+--------------------+---------------------------------------------+
+
++---------------------------------------------------+----------------------+-----------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`void` |nbsp| |+--------------------+| |nbsp| :placeholder:`A` |nbsp| :diagtext:`should not return void expression`|
+| ||:diagtext:`function`|| |
+| |+--------------------+| |
+| ||:diagtext:`method` || |
+| |+--------------------+| |
+| ||:diagtext:`block` || |
+| |+--------------------+| |
++---------------------------------------------------+----------------------+-----------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'`:placeholder:`A`:diagtext:`' cannot be signed or unsigned`|
++--------------------------------------------------------------------------------------------------+
+
++---------------------------+----------------------------------+------------------------------+-----------------------+----------------------------+
+|:warning:`warning:` |nbsp| |+--------------------------------+|:diagtext:`array size` |nbsp| |+---------------------+|:diagtext:`is a C99 feature`|
+| ||:diagtext:`qualifier in` |nbsp| || || || |
+| |+--------------------------------+| |+---------------------+| |
+| ||:diagtext:`static` |nbsp| || || || |
+| |+--------------------------------+| |+---------------------+| |
+| || || ||:diagtext:`'\[\*\] '`|| |
+| |+--------------------------------+| |+---------------------+| |
++---------------------------+----------------------------------+------------------------------+-----------------------+----------------------------+
+
++--------------------------------------------------------+------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`extra ';'` |nbsp| |+----------------------------------------------+|
+| ||:diagtext:`outside of a function` ||
+| |+----------------------------------------------+|
+| ||+--------------------------------------------+||
+| |||:diagtext:`inside a` |nbsp| :placeholder:`B`|||
+| ||+--------------------------------------------+||
+| |+----------------------------------------------+|
+| ||:diagtext:`inside instance variable list` ||
+| |+----------------------------------------------+|
+| ||:diagtext:`after member function definition` ||
+| |+----------------------------------------------+|
++--------------------------------------------------------+------------------------------------------------+
+
++-----------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'\_\_thread' before '`:placeholder:`A`:diagtext:`'`|
++-----------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`type-less parameter names in function declaration`|
++----------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`variable declaration in for loop is a C99-specific feature`|
++-------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`compound literals are a C99-specific feature`|
++-----------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`commas at the end of enumerator lists are a C99-specific feature`|
++-------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`commas at the end of enumerator lists are a C++11 extension`|
++--------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`enumeration types with a fixed underlying type are a C++11 extension`|
++-----------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`use of GNU array range extension`|
++-----------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`exception specification of '...' is a Microsoft extension`|
++------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`extern templates are a C++11 extension`|
++-----------------------------------------------------------------------------+
+
++------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`multi-line // comment`|
++------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`// comments are not allowed in this language`|
++-----------------------------------------------------------------------------------+
+
++----------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`no newline at end of file`|
++----------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`use of non-standard escape character '\\`:placeholder:`A`:diagtext:`'`|
++------------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`hexadecimal floating constants are a C99 feature`|
++---------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`hexadecimal floating literals are a C++1z feature`|
++----------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`#ident is a language extension`|
++---------------------------------------------------------------------+
+
++-----------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`#warning is a language extension`|
++-----------------------------------------------------------------------+
+
++-----------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`comma operator in operand of #if`|
++-----------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`\_\_VA\_ARGS\_\_ can only appear in the expansion of a C99 variadic macro`|
++----------------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`empty macro arguments are a C99 feature`|
++------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`C requires #line number to be less than` |nbsp| :placeholder:`A`:diagtext:`, allowed as extension`|
++----------------------------------------------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`macro expansion producing 'defined' has undefined behavior`|
++-------------------------------------------------------------------------------------------------+
+
+
+-Wpedantic-core-features
+------------------------
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`OpenCL extension` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is core feature or supported optional core feature - ignoring`|
++----------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wpessimizing-move
+------------------
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`moving a temporary object prevents copy elision`|
++--------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`moving a local object in a return statement prevents copy elision`|
++--------------------------------------------------------------------------------------------------------+
+
+
+-Wpointer-arith
+---------------
+Some of the diagnostics controlled by this flag are enabled by default.
+
+**Diagnostic text:**
+
++----------------------------------------------------+-----------------------+---------------------------+---------------+----------------------+-------------------------+---------------------------------+---------------+------------------------+---------------------------------------------------+--------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`arithmetic on`|+---------------------+| |nbsp| :diagtext:`pointer`|+-------------+| |nbsp| :diagtext:`to`|+-----------------------+| |nbsp| :diagtext:`function type`|+-------------+| |nbsp| :placeholder:`B`|+-------------------------------------------------+| |nbsp| :diagtext:`is a GNU extension`|
+| || |nbsp| :diagtext:`a`|| || || || |nbsp| :diagtext:`the`|| || || || || |
+| |+---------------------+| |+-------------+| |+-----------------------+| |+-------------+| |+-------------------------------------------------+| |
+| || || ||:diagtext:`s`|| || || ||:diagtext:`s`|| ||+-----------------------------------------------+|| |
+| |+---------------------+| |+-------------+| |+-----------------------+| |+-------------+| ||| |nbsp| :diagtext:`and` |nbsp| :placeholder:`D`||| |
+| | | | | | | | | ||+-----------------------------------------------+|| |
+| | | | | | | | | |+-------------------------------------------------+| |
++----------------------------------------------------+-----------------------+---------------------------+---------------+----------------------+-------------------------+---------------------------------+---------------+------------------------+---------------------------------------------------+--------------------------------------+
+
++----------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`subscript of a pointer to void is a GNU extension`|
++----------------------------------------------------------------------------------------+
+
++----------------------------------------------------+-----------------------+---------------------------+---------------+----------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`arithmetic on`|+---------------------+| |nbsp| :diagtext:`pointer`|+-------------+| |nbsp| :diagtext:`to void is a GNU extension`|
+| || |nbsp| :diagtext:`a`|| || || |
+| |+---------------------+| |+-------------+| |
+| || || ||:diagtext:`s`|| |
+| |+---------------------+| |+-------------+| |
++----------------------------------------------------+-----------------------+---------------------------+---------------+----------------------------------------------+
+
++---------------------------------------------------------------+-----------------------+--------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`invalid application of '`|+---------------------+|:diagtext:`' to a function type`|
+| ||:diagtext:`sizeof` || |
+| |+---------------------+| |
+| ||:diagtext:`alignof` || |
+| |+---------------------+| |
+| ||:diagtext:`vec\_step`|| |
+| |+---------------------+| |
++---------------------------------------------------------------+-----------------------+--------------------------------+
+
++---------------------------------------------------------------+-----------------------+----------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`invalid application of '`|+---------------------+|:diagtext:`' to a void type`|
+| ||:diagtext:`sizeof` || |
+| |+---------------------+| |
+| ||:diagtext:`alignof` || |
+| |+---------------------+| |
+| ||:diagtext:`vec\_step`|| |
+| |+---------------------+| |
++---------------------------------------------------------------+-----------------------+----------------------------+
+
++-----------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`subtraction of pointers to type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`of zero size has undefined behavior`|
++-----------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wpointer-bool-conversion
+-------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------+---------------------------+---------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`nonnull` |nbsp| |+-------------------------+| |nbsp| :diagtext:`'`:placeholder:`B`:diagtext:`' will evaluate to 'true' on first encounter`|
+| ||:diagtext:`function call`|| |
+| |+-------------------------+| |
+| ||:diagtext:`parameter` || |
+| |+-------------------------+| |
++------------------------------------------------------+---------------------------+---------------------------------------------------------------------------------------------+
+
++-------------------------------------------------+------------------------------+---------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`address of`|+----------------------------+| |nbsp| :diagtext:`'`:placeholder:`B`:diagtext:`' will always evaluate to 'true'`|
+| || || |
+| |+----------------------------+| |
+| || |nbsp| :diagtext:`function`|| |
+| |+----------------------------+| |
+| || |nbsp| :diagtext:`array` || |
+| |+----------------------------+| |
++-------------------------------------------------+------------------------------+---------------------------------------------------------------------------------+
+
+
+-Wpointer-sign
+--------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------+----------------------------------------------------------------+----------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| |+--------------------------------------------------------------+| |nbsp| :diagtext:`converts between pointers to integer types with different sign`|
+| ||:diagtext:`assigning to different types` || |
+| |+--------------------------------------------------------------+| |
+| ||:diagtext:`passing to parameter of different type` || |
+| |+--------------------------------------------------------------+| |
+| ||:diagtext:`returning from function with different return type`|| |
+| |+--------------------------------------------------------------+| |
+| ||:diagtext:`converting between types` || |
+| |+--------------------------------------------------------------+| |
+| ||:diagtext:`initializing with expression of different type` || |
+| |+--------------------------------------------------------------+| |
+| ||:diagtext:`sending to parameter of different type` || |
+| |+--------------------------------------------------------------+| |
+| ||:diagtext:`casting between types` || |
+| |+--------------------------------------------------------------+| |
++---------------------------+----------------------------------------------------------------+----------------------------------------------------------------------------------+
+
+
+-Wpointer-to-int-cast
+---------------------
+This diagnostic flag exists for GCC compatibility, and has no effect in Clang.
+
+-Wpointer-type-mismatch
+-----------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`pointer type mismatch`|
++------------------------------------------------------------+
+
+
+-Wpotentially-evaluated-expression
+----------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`expression with side effects will be evaluated despite being used as an operand to 'typeid'`|
++----------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wpragma-once-outside-header
+----------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`#pragma once in main file`|
++----------------------------------------------------------------+
+
+
+-Wpragma-system-header-outside-header
+-------------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`#pragma system\_header ignored in main file`|
++----------------------------------------------------------------------------------+
+
+
+-Wpragmas
+---------
+Some of the diagnostics controlled by this flag are enabled by default.
+
+Also controls `-Wignored-pragmas`_, `-Wunknown-pragmas`_.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------------------------------------+----------------------+------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`#pragma redefine\_extname is applicable to external C declarations only; not applied to` |nbsp| |+--------------------+| |nbsp| :placeholder:`B`|
+| ||:diagtext:`function`|| |
+| |+--------------------+| |
+| ||:diagtext:`variable`|| |
+| |+--------------------+| |
++--------------------------------------------------------------------------------------------------------------------------------------+----------------------+------------------------+
+
+
+-Wpredefined-identifier-outside-function
+----------------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`predefined identifier is only valid inside function`|
++------------------------------------------------------------------------------------------+
+
+
+-Wprivate-extern
+----------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`use of \_\_private\_extern\_\_ on a declaration may not produce external symbol private to the linkage unit and is deprecated`|
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wprivate-header
+----------------
+This diagnostic is an error by default, but the flag ``-Wno-private-header`` can be used to disable the error.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------+
+|:error:`error:` |nbsp| :diagtext:`use of private header from outside its module: '`:placeholder:`A`:diagtext:`'`|
++----------------------------------------------------------------------------------------------------------------+
+
+
+-Wprofile-instr-out-of-date
+---------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------------------------------------+---------------+---------------------------------------------+-------------------+---------------------------------------------------------------+-------------------+--------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`profile data may be out of date: of` |nbsp| :placeholder:`A` |nbsp| :diagtext:`function`|+-------------+|:diagtext:`,` |nbsp| :placeholder:`B` |nbsp| |+-----------------+| |nbsp| :diagtext:`no data and` |nbsp| :placeholder:`C` |nbsp| |+-----------------+| |nbsp| :diagtext:`mismatched data that will be ignored`|
+| || || ||:diagtext:`:has` || ||:diagtext:`:has` || |
+| |+-------------+| |+-----------------+| |+-----------------+| |
+| ||:diagtext:`s`|| ||:diagtext:`:have`|| ||:diagtext:`:have`|| |
+| |+-------------+| |+-----------------+| |+-----------------+| |
++------------------------------------------------------------------------------------------------------------------------------+---------------+---------------------------------------------+-------------------+---------------------------------------------------------------+-------------------+--------------------------------------------------------+
+
+
+-Wprofile-instr-unprofiled
+--------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`no profile data available for file "`:placeholder:`A`:diagtext:`"`|
++--------------------------------------------------------------------------------------------------------+
+
+
+-Wproperty-access-dot-syntax
+----------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`property` |nbsp| :placeholder:`A` |nbsp| :diagtext:`not found on object of type` |nbsp| :placeholder:`B`:diagtext:`; did you mean to access property` |nbsp| :placeholder:`C`:diagtext:`?`|
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wproperty-attribute-mismatch
+-----------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`property attribute in class extension does not match the primary class`|
++-------------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'`:placeholder:`B`:diagtext:`' attribute on property` |nbsp| :placeholder:`A` |nbsp| :diagtext:`does not match the property inherited from` |nbsp| :placeholder:`C`|
++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`getter name mismatch between property redeclaration (`:placeholder:`B`:diagtext:`) and its original declaration (`:placeholder:`A`:diagtext:`)`|
++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`attribute 'readonly' of property` |nbsp| :placeholder:`A` |nbsp| :diagtext:`restricts attribute 'readwrite' of property inherited from` |nbsp| :placeholder:`B`|
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wprotocol
+----------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`method` |nbsp| :placeholder:`A` |nbsp| :diagtext:`in protocol` |nbsp| :placeholder:`B` |nbsp| :diagtext:`not implemented`|
++---------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wprotocol-property-synthesis-ambiguity
+---------------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`property of type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`was selected for synthesis`|
++-----------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wqualified-void-return-type
+----------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`function cannot return qualified void type` |nbsp| :placeholder:`A`|
++---------------------------------------------------------------------------------------------------------+
+
+
+-Wrange-loop-analysis
+---------------------
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`loop variable` |nbsp| :placeholder:`A` |nbsp| |nbsp| :diagtext:`is initialized with a value of a different type` |nbsp| :diagtext:`resulting in a copy`|
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`loop variable` |nbsp| :placeholder:`A` |nbsp| :diagtext:`of type` |nbsp| :placeholder:`B` |nbsp| :diagtext:`creates a copy from type` |nbsp| :placeholder:`C`|
++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`loop variable` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is always a copy because the range of type` |nbsp| :placeholder:`B` |nbsp| :diagtext:`does not return a reference`|
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wreadonly-iboutlet-property
+----------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`readonly IBOutlet property` |nbsp| :placeholder:`A` |nbsp| :diagtext:`when auto-synthesized may not work correctly with 'nib' loader`|
++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wreceiver-expr
+---------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`receiver type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is not 'id' or interface pointer, consider casting it to 'id'`|
++-------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wreceiver-forward-class
+------------------------
+Some of the diagnostics controlled by this flag are enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`receiver` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is a forward class and corresponding @interface may not exist`|
++--------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`receiver type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`for instance message is a forward declaration`|
++---------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wredeclared-class-member
+-------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`class member cannot be redeclared`|
++------------------------------------------------------------------------+
+
+
+-Wredundant-decls
+-----------------
+This diagnostic flag exists for GCC compatibility, and has no effect in Clang.
+
+-Wredundant-move
+----------------
+**Diagnostic text:**
+
++-------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`redundant move in return statement`|
++-------------------------------------------------------------------------+
+
+
+-Wregister
+----------
+This diagnostic is enabled by default.
+
+Also controls `-Wdeprecated-register`_.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------+
+|:error:`error:` |nbsp| :diagtext:`ISO C++1z does not allow 'register' storage class specifier`|
++----------------------------------------------------------------------------------------------+
+
+
+-Wreinterpret-base-class
+------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------+------------------+---------------------------------------------------------+------------------+-------------------------------+-------------------------------------+-----------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'reinterpret\_cast'` |nbsp| |+----------------+| |nbsp| :diagtext:`class` |nbsp| :placeholder:`A` |nbsp| |+----------------+| |nbsp| :diagtext:`its` |nbsp| |+-----------------------------------+| |nbsp| :placeholder:`B` |nbsp| :diagtext:`behaves differently from 'static\_cast'`|
+| ||:diagtext:`from`|| ||:diagtext:`to` || ||:diagtext:`virtual base` || |
+| |+----------------+| |+----------------+| |+-----------------------------------+| |
+| ||:diagtext:`to` || ||:diagtext:`from`|| ||:diagtext:`base at non-zero offset`|| |
+| |+----------------+| |+----------------+| |+-----------------------------------+| |
++------------------------------------------------------------------+------------------+---------------------------------------------------------+------------------+-------------------------------+-------------------------------------+-----------------------------------------------------------------------------------+
+
+
+-Rremark-backend-plugin
+-----------------------
+**Diagnostic text:**
+
+The text of this diagnostic is not controlled by Clang.
+
+
+-Wreorder
+---------
+**Diagnostic text:**
+
++---------------------------+------------------------+-----------------------------------------------------------------------------+-------------------+------------------------+
+|:warning:`warning:` |nbsp| |+----------------------+| |nbsp| :placeholder:`B` |nbsp| :diagtext:`will be initialized after` |nbsp| |+-----------------+| |nbsp| :placeholder:`D`|
+| ||:diagtext:`field` || ||:diagtext:`field`|| |
+| |+----------------------+| |+-----------------+| |
+| ||:diagtext:`base class`|| ||:diagtext:`base` || |
+| |+----------------------+| |+-----------------+| |
++---------------------------+------------------------+-----------------------------------------------------------------------------+-------------------+------------------------+
+
+
+-Wrequires-super-attribute
+--------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------+----------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute cannot be applied to` |nbsp| |+--------------------------------+|
+| ||:diagtext:`methods in protocols`||
+| |+--------------------------------+|
+| ||:diagtext:`dealloc` ||
+| |+--------------------------------+|
++-----------------------------------------------------------------------------------------------------+----------------------------------+
+
+
+-Wreserved-id-macro
+-------------------
+**Diagnostic text:**
+
++--------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`macro name is a reserved identifier`|
++--------------------------------------------------------------------------+
+
+
+-Wreserved-user-defined-literal
+-------------------------------
+Some of the diagnostics controlled by this flag are enabled by default.
+
+Also controls `-Wc++11-compat-reserved-user-defined-literal`_.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`invalid suffix on literal; C++11 requires a space between literal and identifier`|
++-----------------------------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------------------+
+|:error:`error:` |nbsp| :diagtext:`invalid suffix on literal; C++11 requires a space between literal and identifier`|
++-------------------------------------------------------------------------------------------------------------------+
+
+
+-Wretained-language-linkage
+---------------------------
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`friend function` |nbsp| :placeholder:`A` |nbsp| :diagtext:`retaining previous language linkage is an extension`|
++-----------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wreturn-stack-address
+----------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`returning address of label, which is local`|
++---------------------------------------------------------------------------------+
+
++--------------------------------------------------------+--------------------------+------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`returning` |nbsp| |+------------------------+| |nbsp| :diagtext:`local temporary object`|
+| ||:diagtext:`address of` || |
+| |+------------------------+| |
+| ||:diagtext:`reference to`|| |
+| |+------------------------+| |
++--------------------------------------------------------+--------------------------+------------------------------------------+
+
++---------------------------+--------------------------+-------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| |+------------------------+| |nbsp| :diagtext:`stack memory associated with local variable` |nbsp| :placeholder:`B` |nbsp| :diagtext:`returned`|
+| ||:diagtext:`address of` || |
+| |+------------------------+| |
+| ||:diagtext:`reference to`|| |
+| |+------------------------+| |
++---------------------------+--------------------------+-------------------------------------------------------------------------------------------------------------------+
+
+
+-Wreturn-type
+-------------
+This diagnostic is enabled by default.
+
+Also controls `-Wreturn-type-c-linkage`_.
+
+**Diagnostic text:**
+
++-----------------------+---------------------------+---------------------------------------------------------------------+
+|:error:`error:` |nbsp| |+-------------------------+| |nbsp| :placeholder:`A` |nbsp| :diagtext:`should not return a value`|
+| ||:diagtext:`void function`|| |
+| |+-------------------------+| |
+| ||:diagtext:`void method` || |
+| |+-------------------------+| |
+| ||:diagtext:`constructor` || |
+| |+-------------------------+| |
+| ||:diagtext:`destructor` || |
+| |+-------------------------+| |
++-----------------------+---------------------------+---------------------------------------------------------------------+
+
++---------------------------------------------------+----------------------+-----------------------------------------------------------------+
+|:error:`error:` |nbsp| :diagtext:`non-void` |nbsp| |+--------------------+| |nbsp| :placeholder:`A` |nbsp| :diagtext:`should return a value`|
+| ||:diagtext:`function`|| |
+| |+--------------------+| |
+| ||:diagtext:`method` || |
+| |+--------------------+| |
++---------------------------------------------------+----------------------+-----------------------------------------------------------------+
+
++-------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`control reaches end of non-void function`|
++-------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`control reaches end of non-void lambda`|
++-----------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`control may reach end of non-void function`|
++---------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`control may reach end of non-void lambda`|
++-------------------------------------------------------------------------------+
+
++---------------------------------------------------+----------------------+-----------------------------------------------------------------+
+|:error:`error:` |nbsp| :diagtext:`non-void` |nbsp| |+--------------------+| |nbsp| :placeholder:`A` |nbsp| :diagtext:`should return a value`|
+| ||:diagtext:`function`|| |
+| |+--------------------+| |
+| ||:diagtext:`method` || |
+| |+--------------------+| |
++---------------------------------------------------+----------------------+-----------------------------------------------------------------+
+
+
+-Wreturn-type-c-linkage
+-----------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`has C-linkage specified, but returns user-defined type` |nbsp| :placeholder:`B` |nbsp| :diagtext:`which is incompatible with C`|
++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`has C-linkage specified, but returns incomplete type` |nbsp| :placeholder:`B` |nbsp| :diagtext:`which could be incompatible with C`|
++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wrtti-for-exceptions
+---------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`implicitly enabling rtti for exception handling`|
++--------------------------------------------------------------------------------------+
+
+
+-Rsanitize-address
+------------------
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------+
+|:remark:`remark:` |nbsp| :diagtext:`-fsanitize-address-field-padding applied to` |nbsp| :placeholder:`A`|
++--------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------+
+|:remark:`remark:` |nbsp| :diagtext:`-fsanitize-address-field-padding ignored for` |nbsp| :placeholder:`A` |nbsp| :diagtext:`because it` |nbsp| |+------------------------------------+|
+| ||:diagtext:`is not C++` ||
+| |+------------------------------------+|
+| ||:diagtext:`is packed` ||
+| |+------------------------------------+|
+| ||:diagtext:`is a union` ||
+| |+------------------------------------+|
+| ||:diagtext:`is trivially copyable` ||
+| |+------------------------------------+|
+| ||:diagtext:`has trivial destructor` ||
+| |+------------------------------------+|
+| ||:diagtext:`is standard layout` ||
+| |+------------------------------------+|
+| ||:diagtext:`is in a blacklisted file`||
+| |+------------------------------------+|
+| ||:diagtext:`is blacklisted` ||
+| |+------------------------------------+|
++-----------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------+
+
+
+-Wsection
+---------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`section does not match previous declaration`|
++----------------------------------------------------------------------------------+
+
+
+-Wselector
+----------
+Also controls `-Wselector-type-mismatch`_.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`no method with selector` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is implemented in this translation unit`|
++-------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wselector-type-mismatch
+------------------------
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`several methods with selector` |nbsp| :placeholder:`A` |nbsp| :diagtext:`of mismatched types are found for the @selector expression`|
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wself-assign
+-------------
+Some of the diagnostics controlled by this flag are enabled by default.
+
+Also controls `-Wself-assign-field`_.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`explicitly assigning value of variable of type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to itself`|
++------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wself-assign-field
+-------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------------+-------------------------------+-----------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`assigning` |nbsp| |+-----------------------------+| |nbsp| :diagtext:`to itself`|
+| ||:diagtext:`field` || |
+| |+-----------------------------+| |
+| ||:diagtext:`instance variable`|| |
+| |+-----------------------------+| |
++--------------------------------------------------------+-------------------------------+-----------------------------+
+
+
+-Wself-move
+-----------
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`explicitly moving variable of type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to itself`|
++------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wsemicolon-before-method-body
+------------------------------
+**Diagnostic text:**
+
++------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`semicolon before method body is ignored`|
++------------------------------------------------------------------------------+
+
+
+-Wsentinel
+----------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------+-----------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`missing sentinel in` |nbsp| |+---------------------------+|
+| ||:diagtext:`function call` ||
+| |+---------------------------+|
+| ||:diagtext:`method dispatch`||
+| |+---------------------------+|
+| ||:diagtext:`block call` ||
+| |+---------------------------+|
++------------------------------------------------------------------+-----------------------------+
+
++------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`not enough variable arguments in` |nbsp| :placeholder:`A` |nbsp| :diagtext:`declaration to fit a sentinel`|
++------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wsequence-point
+----------------
+Synonym for `-Wunsequenced`_.
+
+
+-Wserialized-diagnostics
+------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`unable to open file` |nbsp| :placeholder:`A` |nbsp| :diagtext:`for serializing diagnostics (`:placeholder:`B`:diagtext:`)`|
++----------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`unable to merge a subprocess's serialized diagnostics`|
++--------------------------------------------------------------------------------------------+
+
+
+-Wshadow
+--------
+Some of the diagnostics controlled by this flag are enabled by default.
+
+Also controls `-Wshadow-field-in-constructor-modified`_, `-Wshadow-ivar`_.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------+-------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`declaration shadows a` |nbsp| |+-----------------------------------------------------------+|
+| ||:diagtext:`local variable` ||
+| |+-----------------------------------------------------------+|
+| ||+-----------------------------------------------+ ||
+| |||:diagtext:`variable in` |nbsp| :placeholder:`C`| ||
+| ||+-----------------------------------------------+ ||
+| |+-----------------------------------------------------------+|
+| ||+---------------------------------------------------------+||
+| |||:diagtext:`static data member of` |nbsp| :placeholder:`C`|||
+| ||+---------------------------------------------------------+||
+| |+-----------------------------------------------------------+|
+| ||+--------------------------------------------+ ||
+| |||:diagtext:`field of` |nbsp| :placeholder:`C`| ||
+| ||+--------------------------------------------+ ||
+| |+-----------------------------------------------------------+|
++--------------------------------------------------------------------+-------------------------------------------------------------+
+
+
+-Wshadow-all
+------------
+Some of the diagnostics controlled by this flag are enabled by default.
+
+Controls `-Wshadow`_, `-Wshadow-field-in-constructor`_.
+
+
+-Wshadow-field-in-constructor
+-----------------------------
+Also controls `-Wshadow-field-in-constructor-modified`_.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`constructor parameter` |nbsp| :placeholder:`A` |nbsp| :diagtext:`shadows the field` |nbsp| :placeholder:`B` |nbsp| :diagtext:`of` |nbsp| :placeholder:`C`|
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wshadow-field-in-constructor-modified
+--------------------------------------
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`modifying constructor parameter` |nbsp| :placeholder:`A` |nbsp| :diagtext:`that shadows a field of` |nbsp| :placeholder:`B`|
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wshadow-ivar
+-------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`local declaration of` |nbsp| :placeholder:`A` |nbsp| :diagtext:`hides instance variable`|
++------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wshift-count-negative
+----------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`shift count is negative`|
++--------------------------------------------------------------+
+
+
+-Wshift-count-overflow
+----------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`shift count >= width of type`|
++-------------------------------------------------------------------+
+
+
+-Wshift-negative-value
+----------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`shifting a negative signed value is undefined`|
++------------------------------------------------------------------------------------+
+
+
+-Wshift-op-parentheses
+----------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`operator '`:placeholder:`A`:diagtext:`' has lower precedence than '`:placeholder:`B`:diagtext:`'; '`:placeholder:`B`:diagtext:`' will be evaluated first`|
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wshift-overflow
+----------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`signed shift result (`:placeholder:`A`:diagtext:`) requires` |nbsp| :placeholder:`B` |nbsp| :diagtext:`bits to represent, but` |nbsp| :placeholder:`C` |nbsp| :diagtext:`only has` |nbsp| :placeholder:`D` |nbsp| :diagtext:`bits`|
++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wshift-sign-overflow
+---------------------
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`signed shift result (`:placeholder:`A`:diagtext:`) sets the sign bit of the shift expression's type (`:placeholder:`B`:diagtext:`) and becomes negative`|
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wshorten-64-to-32
+------------------
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`implicit conversion loses integer precision:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B`|
++---------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wsign-compare
+--------------
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`comparison of integers of different signs:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`and` |nbsp| :placeholder:`B`|
++--------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wsign-conversion
+-----------------
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`implicit conversion changes signedness:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B`|
++----------------------------------------------------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`operand of ? changes signedness:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B`|
++---------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wsign-promo
+------------
+This diagnostic flag exists for GCC compatibility, and has no effect in Clang.
+
+-Wsizeof-array-argument
+-----------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`sizeof on array function parameter will return size of` |nbsp| :placeholder:`A` |nbsp| :diagtext:`instead of` |nbsp| :placeholder:`B`|
++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wsizeof-array-decay
+--------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`sizeof on pointer operation will return size of` |nbsp| :placeholder:`A` |nbsp| :diagtext:`instead of` |nbsp| :placeholder:`B`|
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wsizeof-pointer-memaccess
+--------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'`:placeholder:`A`:diagtext:`' call operates on objects of type` |nbsp| :placeholder:`B` |nbsp| :diagtext:`while the size is based on a different type` |nbsp| :placeholder:`C`|
++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------+---------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`argument to 'sizeof' in` |nbsp| :placeholder:`A` |nbsp| :diagtext:`call is the same pointer type` |nbsp| :placeholder:`B` |nbsp| :diagtext:`as the` |nbsp| |+-----------------------+|:diagtext:`; expected` |nbsp| :placeholder:`D` |nbsp| :diagtext:`or an explicit length`|
+| ||:diagtext:`destination`|| |
+| |+-----------------------+| |
+| ||:diagtext:`source` || |
+| |+-----------------------+| |
++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------+---------------------------------------------------------------------------------------+
+
+
+-Wsometimes-uninitialized
+-------------------------
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------+----------------------+--------------------------------------------------+--------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`variable` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is` |nbsp| |+--------------------+| |nbsp| :diagtext:`uninitialized whenever` |nbsp| |+------------------------------------------------------------------------------------------------------------+|
+| ||:diagtext:`used` || ||+---------------------------------------------------------------+-------------------+ ||
+| |+--------------------+| |||:diagtext:`'`:placeholder:`D`:diagtext:`' condition is` |nbsp| |+-----------------+| ||
+| ||:diagtext:`captured`|| ||| ||:diagtext:`true` || ||
+| |+--------------------+| ||| |+-----------------+| ||
+| | | ||| ||:diagtext:`false`|| ||
+| | | ||| |+-----------------+| ||
+| | | ||+---------------------------------------------------------------+-------------------+ ||
+| | | |+------------------------------------------------------------------------------------------------------------+|
+| | | ||+-------------------------------------------------------+--------------------------------------------------+||
+| | | |||:diagtext:`'`:placeholder:`D`:diagtext:`' loop` |nbsp| |+------------------------------------------------+|||
+| | | ||| ||:diagtext:`is entered` ||||
+| | | ||| |+------------------------------------------------+|||
+| | | ||| ||:diagtext:`exits because its condition is false`||||
+| | | ||| |+------------------------------------------------+|||
+| | | ||+-------------------------------------------------------+--------------------------------------------------+||
+| | | |+------------------------------------------------------------------------------------------------------------+|
+| | | ||+-------------------------------------------------------+--------------------------------------------------+||
+| | | |||:diagtext:`'`:placeholder:`D`:diagtext:`' loop` |nbsp| |+------------------------------------------------+|||
+| | | ||| ||:diagtext:`condition is true` ||||
+| | | ||| |+------------------------------------------------+|||
+| | | ||| ||:diagtext:`exits because its condition is false`||||
+| | | ||| |+------------------------------------------------+|||
+| | | ||+-------------------------------------------------------+--------------------------------------------------+||
+| | | |+------------------------------------------------------------------------------------------------------------+|
+| | | ||+----------------------------------------------------------------------+ ||
+| | | |||:diagtext:`switch` |nbsp| :placeholder:`D` |nbsp| :diagtext:`is taken`| ||
+| | | ||+----------------------------------------------------------------------+ ||
+| | | |+------------------------------------------------------------------------------------------------------------+|
+| | | ||:diagtext:`its declaration is reached` ||
+| | | |+------------------------------------------------------------------------------------------------------------+|
+| | | ||+---------------------------------------------+ ||
+| | | |||:placeholder:`D` |nbsp| :diagtext:`is called`| ||
+| | | ||+---------------------------------------------+ ||
+| | | |+------------------------------------------------------------------------------------------------------------+|
++-----------------------------------------------------------------------------------------------------+----------------------+--------------------------------------------------+--------------------------------------------------------------------------------------------------------------+
+
+
+-Wsource-uses-openmp
+--------------------
+Some of the diagnostics controlled by this flag are enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`OpenMP only allows an ordered construct with the simd clause nested in a simd construct`|
++------------------------------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`unexpected '#pragma omp ...' in program`|
++------------------------------------------------------------------------------+
+
+
+-Wspir-compat
+-------------
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`sampler initializer has invalid` |nbsp| :placeholder:`A` |nbsp| :diagtext:`bits`|
++----------------------------------------------------------------------------------------------------------------------+
+
+
+-Wstack-protector
+-----------------
+This diagnostic flag exists for GCC compatibility, and has no effect in Clang.
+
+-Wstatic-float-init
+-------------------
+This diagnostic is enabled by default.
+
+Also controls `-Wgnu-static-float-init`_.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:error:`error:` |nbsp| :diagtext:`in-class initializer for static data member of type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`requires 'constexpr' specifier`|
++----------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wstatic-in-inline
+------------------
+Some of the diagnostics controlled by this flag are enabled by default.
+
+**Diagnostic text:**
+
++-----------------------------------------------------+----------------------+-----------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`static` |nbsp| |+--------------------+| |nbsp| :placeholder:`B` |nbsp| :diagtext:`is used in an inline function with external linkage`|
+| ||:diagtext:`function`|| |
+| |+--------------------+| |
+| ||:diagtext:`variable`|| |
+| |+--------------------+| |
++-----------------------------------------------------+----------------------+-----------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------+----------------------+-----------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`static` |nbsp| |+--------------------+| |nbsp| :placeholder:`B` |nbsp| :diagtext:`is used in an inline function with external linkage`|
+| ||:diagtext:`function`|| |
+| |+--------------------+| |
+| ||:diagtext:`variable`|| |
+| |+--------------------+| |
++-----------------------------------------------------+----------------------+-----------------------------------------------------------------------------------------------+
+
+
+-Wstatic-inline-explicit-instantiation
+--------------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------+--------------------+--------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`ignoring '`|+------------------+|:diagtext:`' keyword on explicit template instantiation`|
+| ||:diagtext:`static`|| |
+| |+------------------+| |
+| ||:diagtext:`inline`|| |
+| |+------------------+| |
++-------------------------------------------------+--------------------+--------------------------------------------------------+
+
+
+-Wstatic-local-in-inline
+------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`non-constant static local variable in inline function may be different in different files`|
++--------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wstatic-self-init
+------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`static variable` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is suspiciously used within its own initialization`|
++----------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wstrict-aliasing
+-----------------
+This diagnostic flag exists for GCC compatibility, and has no effect in Clang.
+
+-Wstrict-aliasing=0
+-------------------
+This diagnostic flag exists for GCC compatibility, and has no effect in Clang.
+
+-Wstrict-aliasing=1
+-------------------
+This diagnostic flag exists for GCC compatibility, and has no effect in Clang.
+
+-Wstrict-aliasing=2
+-------------------
+This diagnostic flag exists for GCC compatibility, and has no effect in Clang.
+
+-Wstrict-overflow
+-----------------
+This diagnostic flag exists for GCC compatibility, and has no effect in Clang.
+
+-Wstrict-overflow=0
+-------------------
+This diagnostic flag exists for GCC compatibility, and has no effect in Clang.
+
+-Wstrict-overflow=1
+-------------------
+This diagnostic flag exists for GCC compatibility, and has no effect in Clang.
+
+-Wstrict-overflow=2
+-------------------
+This diagnostic flag exists for GCC compatibility, and has no effect in Clang.
+
+-Wstrict-overflow=3
+-------------------
+This diagnostic flag exists for GCC compatibility, and has no effect in Clang.
+
+-Wstrict-overflow=4
+-------------------
+This diagnostic flag exists for GCC compatibility, and has no effect in Clang.
+
+-Wstrict-overflow=5
+-------------------
+This diagnostic flag exists for GCC compatibility, and has no effect in Clang.
+
+-Wstrict-prototypes
+-------------------
+This diagnostic flag exists for GCC compatibility, and has no effect in Clang.
+
+-Wstrict-selector-match
+-----------------------
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`multiple methods named` |nbsp| :placeholder:`A` |nbsp| :diagtext:`found`|
++--------------------------------------------------------------------------------------------------------------+
+
+
+-Wstring-compare
+----------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------+------------------------------+--------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`result of comparison against` |nbsp| |+----------------------------+| |nbsp| :diagtext:`is unspecified (use strncmp instead)`|
+| ||:diagtext:`a string literal`|| |
+| |+----------------------------+| |
+| ||:diagtext:`@encode` || |
+| |+----------------------------+| |
++---------------------------------------------------------------------------+------------------------------+--------------------------------------------------------+
+
+
+-Wstring-conversion
+-------------------
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`implicit conversion turns string literal into bool:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B`|
++----------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wstring-plus-char
+------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`adding` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to a string pointer does not append to the string`|
++------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wstring-plus-int
+-----------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`adding` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to a string does not append to the string`|
++----------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wstrlcpy-strlcat-size
+----------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`size argument in` |nbsp| :placeholder:`A` |nbsp| :diagtext:`call appears to be size of the source; expected the size of the destination`|
++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wstrncat-size
+--------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`the value of the size argument in 'strncat' is too large, might lead to a buffer overflow`|
++--------------------------------------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`size argument in 'strncat' call appears to be size of the source`|
++-------------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`the value of the size argument to 'strncat' is wrong`|
++-------------------------------------------------------------------------------------------+
+
+
+-Wsuper-class-method-mismatch
+-----------------------------
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`method parameter type` |nbsp| :diagtext:`does not match super class method parameter type`|
++--------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wswitch
+--------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`overflow converting case value to switch condition type (`:placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B`:diagtext:`)`|
++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++---------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| |+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+|
+| ||+-----------------------------------------------------------------------------------------------+ ||
+| |||:diagtext:`:enumeration value` |nbsp| :placeholder:`B` |nbsp| :diagtext:`not handled in switch`| ||
+| ||+-----------------------------------------------------------------------------------------------+ ||
+| |+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+|
+| ||+-----------------------------------------------------------------------------------------------------------------------------------------------+ ||
+| |||:diagtext:`:enumeration values` |nbsp| :placeholder:`B` |nbsp| :diagtext:`and` |nbsp| :placeholder:`C` |nbsp| :diagtext:`not handled in switch`| ||
+| ||+-----------------------------------------------------------------------------------------------------------------------------------------------+ ||
+| |+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+|
+| ||+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ||
+| |||:diagtext:`:enumeration values` |nbsp| :placeholder:`B`:diagtext:`,` |nbsp| :placeholder:`C`:diagtext:`, and` |nbsp| :placeholder:`D` |nbsp| :diagtext:`not handled in switch`| ||
+| ||+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ||
+| |+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+|
+| ||+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+||
+| |||:diagtext:`:`:placeholder:`A` |nbsp| :diagtext:`enumeration values not handled in switch:` |nbsp| :placeholder:`B`:diagtext:`,` |nbsp| :placeholder:`C`:diagtext:`,` |nbsp| :placeholder:`D`:diagtext:`...`|||
+| ||+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+||
+| |+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+|
++---------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`case value not in enumerated type` |nbsp| :placeholder:`A`|
++------------------------------------------------------------------------------------------------+
+
+
+-Wswitch-bool
+-------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`switch condition has boolean value`|
++-------------------------------------------------------------------------+
+
+
+-Wswitch-default
+----------------
+This diagnostic flag exists for GCC compatibility, and has no effect in Clang.
+
+-Wswitch-enum
+-------------
+**Diagnostic text:**
+
++---------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| |+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+|
+| ||+----------------------------------------------------------------------------------------------------------+ ||
+| |||:diagtext:`:enumeration value` |nbsp| :placeholder:`B` |nbsp| :diagtext:`not explicitly handled in switch`| ||
+| ||+----------------------------------------------------------------------------------------------------------+ ||
+| |+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+|
+| ||+----------------------------------------------------------------------------------------------------------------------------------------------------------+ ||
+| |||:diagtext:`:enumeration values` |nbsp| :placeholder:`B` |nbsp| :diagtext:`and` |nbsp| :placeholder:`C` |nbsp| :diagtext:`not explicitly handled in switch`| ||
+| ||+----------------------------------------------------------------------------------------------------------------------------------------------------------+ ||
+| |+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+|
+| ||+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ||
+| |||:diagtext:`:enumeration values` |nbsp| :placeholder:`B`:diagtext:`,` |nbsp| :placeholder:`C`:diagtext:`, and` |nbsp| :placeholder:`D` |nbsp| :diagtext:`not explicitly handled in switch`| ||
+| ||+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ||
+| |+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+|
+| ||+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+||
+| |||:diagtext:`:`:placeholder:`A` |nbsp| :diagtext:`enumeration values not explicitly handled in switch:` |nbsp| :placeholder:`B`:diagtext:`,` |nbsp| :placeholder:`C`:diagtext:`,` |nbsp| :placeholder:`D`:diagtext:`...`|||
+| ||+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+||
+| |+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+|
++---------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wsync-fetch-and-nand-semantics-changed
+---------------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`the semantics of this intrinsic changed with GCC version 4.4 - the newer semantics are provided here`|
++-------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wsynth
+-------
+This diagnostic flag exists for GCC compatibility, and has no effect in Clang.
+
+-Wtautological-compare
+----------------------
+Some of the diagnostics controlled by this flag are enabled by default.
+
+Also controls `-Wtautological-constant-out-of-range-compare`_, `-Wtautological-overlap-compare`_, `-Wtautological-pointer-compare`_, `-Wtautological-undefined-compare`_.
+
+**Diagnostic text:**
+
++---------------------------+---------------------------+--------------------------------------------------+------------------------+
+|:warning:`warning:` |nbsp| |+-------------------------+|:diagtext:`comparison always evaluates to` |nbsp| |+----------------------+|
+| ||:diagtext:`self-` || ||:diagtext:`false` ||
+| |+-------------------------+| |+----------------------+|
+| ||:diagtext:`array` |nbsp| || ||:diagtext:`true` ||
+| |+-------------------------+| |+----------------------+|
+| | | ||:diagtext:`a constant`||
+| | | |+----------------------+|
++---------------------------+---------------------------+--------------------------------------------------+------------------------+
+
++-------------------------------------------------------------------------------------+-------------------+
+|:warning:`warning:` |nbsp| :diagtext:`bitwise comparison always evaluates to` |nbsp| |+-----------------+|
+| ||:diagtext:`false`||
+| |+-----------------+|
+| ||:diagtext:`true` ||
+| |+-----------------+|
++-------------------------------------------------------------------------------------+-------------------+
+
++-------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`comparison of unsigned`|+------------------------+| |nbsp| :diagtext:`expression` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is always` |nbsp| :placeholder:`B`|
+| || || |
+| |+------------------------+| |
+| || |nbsp| :diagtext:`enum`|| |
+| |+------------------------+| |
++-------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------+--------------------------+----------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`comparison of` |nbsp| :placeholder:`A` |nbsp| :diagtext:`unsigned`|+------------------------+| |nbsp| :diagtext:`expression is always` |nbsp| :placeholder:`B`|
+| || || |
+| |+------------------------+| |
+| || |nbsp| :diagtext:`enum`|| |
+| |+------------------------+| |
++--------------------------------------------------------------------------------------------------------+--------------------------+----------------------------------------------------------------+
+
+
+-Wtautological-constant-out-of-range-compare
+--------------------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------+------------------------------------------------+--------------------------------+----------------------------------------------------------+-------------------------------------+-------------------+
+|:warning:`warning:` |nbsp| :diagtext:`comparison of` |nbsp| |+----------------------------------------------+| |nbsp| :diagtext:`with` |nbsp| |+--------------------------------------------------------+| |nbsp| :diagtext:`is always` |nbsp| |+-----------------+|
+| ||+--------------------------------------------+|| ||+------------------------------------------------------+|| ||:diagtext:`false`||
+| |||:diagtext:`constant` |nbsp| :placeholder:`A`||| |||:diagtext:`expression of type` |nbsp| :placeholder:`C`||| |+-----------------+|
+| ||+--------------------------------------------+|| ||+------------------------------------------------------+|| ||:diagtext:`true` ||
+| |+----------------------------------------------+| |+--------------------------------------------------------+| |+-----------------+|
+| ||:diagtext:`true` || ||:diagtext:`boolean expression` || | |
+| |+----------------------------------------------+| |+--------------------------------------------------------+| | |
+| ||:diagtext:`false` || | | | |
+| |+----------------------------------------------+| | | | |
++------------------------------------------------------------+------------------------------------------------+--------------------------------+----------------------------------------------------------+-------------------------------------+-------------------+
+
+
+-Wtautological-overlap-compare
+------------------------------
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------+-------------------+
+|:warning:`warning:` |nbsp| :diagtext:`overlapping comparisons always evaluate to` |nbsp| |+-----------------+|
+| ||:diagtext:`false`||
+| |+-----------------+|
+| ||:diagtext:`true` ||
+| |+-----------------+|
++-----------------------------------------------------------------------------------------+-------------------+
+
+
+-Wtautological-pointer-compare
+------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------+---------------------------+----------------------------------------------------------+-------------------------+----------------------------------------+-------------------+--------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`comparison of nonnull` |nbsp| |+-------------------------+| |nbsp| :diagtext:`'`:placeholder:`B`:diagtext:`'` |nbsp| |+-----------------------+|:diagtext:`equal to a null pointer is '`|+-----------------+|:diagtext:`' on first encounter`|
+| ||:diagtext:`function call`|| ||:diagtext:`not` |nbsp| || ||:diagtext:`true` || |
+| |+-------------------------+| |+-----------------------+| |+-----------------+| |
+| ||:diagtext:`parameter` || || || ||:diagtext:`false`|| |
+| |+-------------------------+| |+-----------------------+| |+-----------------+| |
++--------------------------------------------------------------------+---------------------------+----------------------------------------------------------+-------------------------+----------------------------------------+-------------------+--------------------------------+
+
++------------------------------------------------------------+------------------------+----------------------------------------------------------+-------------------------+-----------------------------------------------------+-------------------+
+|:warning:`warning:` |nbsp| :diagtext:`comparison of` |nbsp| |+----------------------+| |nbsp| :diagtext:`'`:placeholder:`B`:diagtext:`'` |nbsp| |+-----------------------+|:diagtext:`equal to a null pointer is always` |nbsp| |+-----------------+|
+| ||:diagtext:`address of`|| ||:diagtext:`not` |nbsp| || ||:diagtext:`true` ||
+| |+----------------------+| |+-----------------------+| |+-----------------+|
+| ||:diagtext:`function` || || || ||:diagtext:`false`||
+| |+----------------------+| |+-----------------------+| |+-----------------+|
+| ||:diagtext:`array` || | | | |
+| |+----------------------+| | | | |
++------------------------------------------------------------+------------------------+----------------------------------------------------------+-------------------------+-----------------------------------------------------+-------------------+
+
+
+-Wtautological-undefined-compare
+--------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------+
+|:warning:`warning:` |nbsp| :diagtext:`reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to` |nbsp| |+-----------------+|
+| ||:diagtext:`true` ||
+| |+-----------------+|
+| ||:diagtext:`false`||
+| |+-----------------+|
++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------+
+
++------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'this' pointer cannot be null in well-defined C++ code; comparison may be assumed to always evaluate to` |nbsp| |+-----------------+|
+| ||:diagtext:`true` ||
+| |+-----------------+|
+| ||:diagtext:`false`||
+| |+-----------------+|
++------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------+
+
+
+-Wtentative-definition-incomplete-type
+--------------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`tentative definition of variable with internal linkage has incomplete non-array type` |nbsp| :placeholder:`A`|
++---------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wthread-safety
+---------------
+Controls `-Wthread-safety-analysis`_, `-Wthread-safety-attributes`_, `-Wthread-safety-precise`_, `-Wthread-safety-reference`_.
+
+
+-Wthread-safety-analysis
+------------------------
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`'`:placeholder:`B`:diagtext:`' must be acquired before '`:placeholder:`C`:diagtext:`'`|
++----------------------------------------------------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`Cycle in acquired\_before/after dependencies, starting with '`:placeholder:`A`:diagtext:`'`|
++---------------------------------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`cannot resolve lock expression`|
++---------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`acquiring` |nbsp| :placeholder:`A` |nbsp| :diagtext:`'`:placeholder:`B`:diagtext:`' that is already held`|
++-----------------------------------------------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`expecting` |nbsp| :placeholder:`A` |nbsp| :diagtext:`'`:placeholder:`B`:diagtext:`' to be held at start of each loop`|
++-----------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`expecting` |nbsp| :placeholder:`A` |nbsp| :diagtext:`'`:placeholder:`B`:diagtext:`' to be held at the end of function`|
++------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`cannot call function '`:placeholder:`B`:diagtext:`' while` |nbsp| :placeholder:`A` |nbsp| :diagtext:`'`:placeholder:`C`:diagtext:`' is held`|
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`calling function '`:placeholder:`B`:diagtext:`' requires holding` |nbsp| :placeholder:`A` |nbsp| |+--------------------------------------------------------+|
+| ||+------------------------------------------+ ||
+| |||:diagtext:`'`:placeholder:`C`:diagtext:`'`| ||
+| ||+------------------------------------------+ ||
+| |+--------------------------------------------------------+|
+| ||+------------------------------------------------------+||
+| |||:diagtext:`'`:placeholder:`C`:diagtext:`' exclusively`|||
+| ||+------------------------------------------------------+||
+| |+--------------------------------------------------------+|
++---------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`'`:placeholder:`B`:diagtext:`' is acquired exclusively and shared in the same scope`|
++--------------------------------------------------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`'`:placeholder:`B`:diagtext:`' is not held on every path through here`|
++------------------------------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`'`:placeholder:`B`:diagtext:`' is still held at the end of function`|
++----------------------------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`releasing` |nbsp| :placeholder:`A` |nbsp| :diagtext:`'`:placeholder:`B`:diagtext:`' that was not held`|
++--------------------------------------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------------------------------------------+-----------------------+--------------------------------------------+-----------------------+--------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`releasing` |nbsp| :placeholder:`A` |nbsp| :diagtext:`'`:placeholder:`B`:diagtext:`' using` |nbsp| |+---------------------+| |nbsp| :diagtext:`access, expected` |nbsp| |+---------------------+| |nbsp| :diagtext:`access`|
+| ||:diagtext:`shared` || ||:diagtext:`shared` || |
+| |+---------------------+| |+---------------------+| |
+| ||:diagtext:`exclusive`|| ||:diagtext:`exclusive`|| |
+| |+---------------------+| |+---------------------+| |
++----------------------------------------------------------------------------------------------------------------------------------------+-----------------------+--------------------------------------------+-----------------------+--------------------------+
+
++---------------------------+---------------------+---------------------------------------------------------------------------------------------------+-----------------------------------+
+|:warning:`warning:` |nbsp| |+-------------------+| |nbsp| :diagtext:`the value pointed to by '`:placeholder:`A`:diagtext:`' requires holding` |nbsp| |+---------------------------------+|
+| ||:diagtext:`reading`|| ||:diagtext:`any mutex` ||
+| |+-------------------+| |+---------------------------------+|
+| ||:diagtext:`writing`|| ||:diagtext:`any mutex exclusively`||
+| |+-------------------+| |+---------------------------------+|
++---------------------------+---------------------+---------------------------------------------------------------------------------------------------+-----------------------------------+
+
++---------------------------+---------------------+---------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+
+|:warning:`warning:` |nbsp| |+-------------------+| |nbsp| :diagtext:`the value pointed to by '`:placeholder:`B`:diagtext:`' requires holding` |nbsp| :placeholder:`A` |nbsp| |+--------------------------------------------------------+|
+| ||:diagtext:`reading`|| ||+------------------------------------------+ ||
+| |+-------------------+| |||:diagtext:`'`:placeholder:`C`:diagtext:`'`| ||
+| ||:diagtext:`writing`|| ||+------------------------------------------+ ||
+| |+-------------------+| |+--------------------------------------------------------+|
+| | | ||+------------------------------------------------------+||
+| | | |||:diagtext:`'`:placeholder:`C`:diagtext:`' exclusively`|||
+| | | ||+------------------------------------------------------+||
+| | | |+--------------------------------------------------------+|
++---------------------------+---------------------+---------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+
+
++---------------------------+---------------------+------------------------------------------------------------------------------------+-----------------------------------+
+|:warning:`warning:` |nbsp| |+-------------------+| |nbsp| :diagtext:`variable '`:placeholder:`A`:diagtext:`' requires holding` |nbsp| |+---------------------------------+|
+| ||:diagtext:`reading`|| ||:diagtext:`any mutex` ||
+| |+-------------------+| |+---------------------------------+|
+| ||:diagtext:`writing`|| ||:diagtext:`any mutex exclusively`||
+| |+-------------------+| |+---------------------------------+|
++---------------------------+---------------------+------------------------------------------------------------------------------------+-----------------------------------+
+
++---------------------------+---------------------+------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+
+|:warning:`warning:` |nbsp| |+-------------------+| |nbsp| :diagtext:`variable '`:placeholder:`B`:diagtext:`' requires holding` |nbsp| :placeholder:`A` |nbsp| |+--------------------------------------------------------+|
+| ||:diagtext:`reading`|| ||+------------------------------------------+ ||
+| |+-------------------+| |||:diagtext:`'`:placeholder:`C`:diagtext:`'`| ||
+| ||:diagtext:`writing`|| ||+------------------------------------------+ ||
+| |+-------------------+| |+--------------------------------------------------------+|
+| | | ||+------------------------------------------------------+||
+| | | |||:diagtext:`'`:placeholder:`C`:diagtext:`' exclusively`|||
+| | | ||+------------------------------------------------------+||
+| | | |+--------------------------------------------------------+|
++---------------------------+---------------------+------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+
+
+
+-Wthread-safety-attributes
+--------------------------
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`invalid capability name '`:placeholder:`A`:diagtext:`'; capability name must be 'mutex' or 'role'`|
++----------------------------------------------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute requires arguments whose type is annotated with 'capability' attribute; type here is` |nbsp| :placeholder:`B`|
++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute can only be applied in a context annotated with 'capability("mutex")' attribute`|
++--------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`only applies to pointer types; type here is` |nbsp| :placeholder:`B`|
++----------------------------------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`ignoring` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute because its argument is invalid`|
++------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wthread-safety-beta
+--------------------
+**Diagnostic text:**
+
++------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`Thread safety beta warning.`|
++------------------------------------------------------------------+
+
+
+-Wthread-safety-negative
+------------------------
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`acquiring` |nbsp| :placeholder:`A` |nbsp| :diagtext:`'`:placeholder:`B`:diagtext:`' requires negative capability '`:placeholder:`C`:diagtext:`'`|
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wthread-safety-precise
+-----------------------
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`calling function '`:placeholder:`B`:diagtext:`' requires holding` |nbsp| :placeholder:`A` |nbsp| |+--------------------------------------------------------+|
+| ||+------------------------------------------+ ||
+| |||:diagtext:`'`:placeholder:`C`:diagtext:`'`| ||
+| ||+------------------------------------------+ ||
+| |+--------------------------------------------------------+|
+| ||+------------------------------------------------------+||
+| |||:diagtext:`'`:placeholder:`C`:diagtext:`' exclusively`|||
+| ||+------------------------------------------------------+||
+| |+--------------------------------------------------------+|
++---------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+
+
++---------------------------+---------------------+---------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+
+|:warning:`warning:` |nbsp| |+-------------------+| |nbsp| :diagtext:`the value pointed to by '`:placeholder:`B`:diagtext:`' requires holding` |nbsp| :placeholder:`A` |nbsp| |+--------------------------------------------------------+|
+| ||:diagtext:`reading`|| ||+------------------------------------------+ ||
+| |+-------------------+| |||:diagtext:`'`:placeholder:`C`:diagtext:`'`| ||
+| ||:diagtext:`writing`|| ||+------------------------------------------+ ||
+| |+-------------------+| |+--------------------------------------------------------+|
+| | | ||+------------------------------------------------------+||
+| | | |||:diagtext:`'`:placeholder:`C`:diagtext:`' exclusively`|||
+| | | ||+------------------------------------------------------+||
+| | | |+--------------------------------------------------------+|
++---------------------------+---------------------+---------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+
+
++---------------------------+---------------------+------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+
+|:warning:`warning:` |nbsp| |+-------------------+| |nbsp| :diagtext:`variable '`:placeholder:`B`:diagtext:`' requires holding` |nbsp| :placeholder:`A` |nbsp| |+--------------------------------------------------------+|
+| ||:diagtext:`reading`|| ||+------------------------------------------+ ||
+| |+-------------------+| |||:diagtext:`'`:placeholder:`C`:diagtext:`'`| ||
+| ||:diagtext:`writing`|| ||+------------------------------------------+ ||
+| |+-------------------+| |+--------------------------------------------------------+|
+| | | ||+------------------------------------------------------+||
+| | | |||:diagtext:`'`:placeholder:`C`:diagtext:`' exclusively`|||
+| | | ||+------------------------------------------------------+||
+| | | |+--------------------------------------------------------+|
++---------------------------+---------------------+------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+
+
+
+-Wthread-safety-reference
+-------------------------
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`passing variable '`:placeholder:`B`:diagtext:`' by reference requires holding` |nbsp| :placeholder:`A` |nbsp| |+--------------------------------------------------------+|
+| ||+------------------------------------------+ ||
+| |||:diagtext:`'`:placeholder:`C`:diagtext:`'`| ||
+| ||+------------------------------------------+ ||
+| |+--------------------------------------------------------+|
+| ||+------------------------------------------------------+||
+| |||:diagtext:`'`:placeholder:`C`:diagtext:`' exclusively`|||
+| ||+------------------------------------------------------+||
+| |+--------------------------------------------------------+|
++----------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`passing the value that '`:placeholder:`B`:diagtext:`' points to by reference requires holding` |nbsp| :placeholder:`A` |nbsp| |+--------------------------------------------------------+|
+| ||+------------------------------------------+ ||
+| |||:diagtext:`'`:placeholder:`C`:diagtext:`'`| ||
+| ||+------------------------------------------+ ||
+| |+--------------------------------------------------------+|
+| ||+------------------------------------------------------+||
+| |||:diagtext:`'`:placeholder:`C`:diagtext:`' exclusively`|||
+| ||+------------------------------------------------------+||
+| |+--------------------------------------------------------+|
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+
+
+
+-Wthread-safety-verbose
+-----------------------
+**Diagnostic text:**
+
++---------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`Thread safety verbose warning.`|
++---------------------------------------------------------------------+
+
+
+-Wtrigraphs
+-----------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`trigraph converted to '`:placeholder:`A`:diagtext:`' character`|
++-----------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`trigraph ends block comment`|
++------------------------------------------------------------------+
+
++-------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`trigraph ignored`|
++-------------------------------------------------------+
+
++-------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`ignored trigraph would end block comment`|
++-------------------------------------------------------------------------------+
+
+
+-Wtype-limits
+-------------
+This diagnostic flag exists for GCC compatibility, and has no effect in Clang.
+
+-Wtype-safety
+-------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`specified` |nbsp| :placeholder:`A` |nbsp| :diagtext:`type tag requires a null pointer`|
++----------------------------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`argument type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`doesn't match specified` |nbsp| :placeholder:`B` |nbsp| :diagtext:`type tag` |nbsp| |+---------------------------------------------------+|
+| ||+-------------------------------------------------+||
+| |||:diagtext:`that requires` |nbsp| :placeholder:`D`|||
+| ||+-------------------------------------------------+||
+| |+---------------------------------------------------+|
+| || ||
+| |+---------------------------------------------------+|
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`this type tag was not designed to be used with this function`|
++---------------------------------------------------------------------------------------------------+
+
+
+-Wtypedef-redefinition
+----------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`redefinition of typedef` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is a C11 feature`|
++--------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wtypename-missing
+------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`missing 'typename' prior to dependent type name '`:placeholder:`A`:placeholder:`B`:diagtext:`'`|
++-------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wunavailable-declarations
+--------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`may be unavailable because the receiver type is unknown`|
++----------------------------------------------------------------------------------------------------------------------+
+
+
+-Wundeclared-selector
+---------------------
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`undeclared selector` |nbsp| :placeholder:`A`|
++----------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`undeclared selector` |nbsp| :placeholder:`A`:diagtext:`; did you mean` |nbsp| :placeholder:`B`:diagtext:`?`|
++-------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wundef
+-------
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is not defined, evaluates to 0`|
++---------------------------------------------------------------------------------------------+
+
+
+-Wundefined-bool-conversion
+---------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`reference cannot be bound to dereferenced null pointer in well-defined C++ code; pointer may be assumed to always convert to true`|
++------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'this' pointer cannot be null in well-defined C++ code; pointer may be assumed to always convert to true`|
++-----------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wundefined-func-template
+-------------------------
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`instantiation of function` |nbsp| :placeholder:`A` |nbsp| :diagtext:`required here, but no definition is available`|
++---------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wundefined-inline
+------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`inline function` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is not defined`|
++----------------------------------------------------------------------------------------------------------------+
+
+
+-Wundefined-internal
+--------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------+----------------------+-----------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| |+--------------------+| |nbsp| :placeholder:`B` |nbsp| :diagtext:`has internal linkage but is not defined`|
+| ||:diagtext:`function`|| |
+| |+--------------------+| |
+| ||:diagtext:`variable`|| |
+| |+--------------------+| |
++---------------------------+----------------------+-----------------------------------------------------------------------------------+
+
+
+-Wundefined-reinterpret-cast
+----------------------------
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`dereference of type` |nbsp| :placeholder:`B` |nbsp| :diagtext:`that was reinterpret\_cast from type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`has undefined behavior`|
++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`reinterpret\_cast from` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B` |nbsp| :diagtext:`has undefined behavior`|
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wundefined-var-template
+------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`instantiation of variable` |nbsp| :placeholder:`A` |nbsp| :diagtext:`required here, but no definition is available`|
++---------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wunevaluated-expression
+------------------------
+This diagnostic is enabled by default.
+
+Also controls `-Wpotentially-evaluated-expression`_.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`expression with side effects has no effect in an unevaluated context`|
++-----------------------------------------------------------------------------------------------------------+
+
+
+-Wunguarded-availability
+------------------------
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is only available conditionally`|
++----------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`may be partial because the receiver type is unknown`|
++------------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is partial:` |nbsp| :placeholder:`B`|
++--------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is only available on` |nbsp| :placeholder:`B` |nbsp| :placeholder:`C` |nbsp| :diagtext:`or newer`|
++---------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wunicode
+---------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`incomplete universal character name; treating as '\\' followed by identifier`|
++-------------------------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`\\`:placeholder:`A` |nbsp| :diagtext:`used with no following hex digits; treating as '\\' followed by identifier`|
++-------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`universal character name refers to a surrogate character`|
++-----------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`universal character names are only valid in C99 or C++; treating as '\\' followed by identifier`|
++--------------------------------------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`universal character names are only valid in C99 or C++`|
++---------------------------------------------------------------------------------------------+
+
+
+-Wunicode-whitespace
+--------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`treating Unicode character as whitespace`|
++-------------------------------------------------------------------------------+
+
+
+-Wuninitialized
+---------------
+Some of the diagnostics controlled by this flag are enabled by default.
+
+Also controls `-Wsometimes-uninitialized`_, `-Wstatic-self-init`_.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`base class` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is uninitialized when used here to access` |nbsp| :placeholder:`B`|
++--------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`field` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is uninitialized when used here`|
++-----------------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`reference` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is not yet bound to a value when used here`|
++--------------------------------------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`block pointer variable` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is uninitialized when captured by block`|
++------------------------------------------------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`variable` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is uninitialized when used within its own initialization`|
++---------------------------------------------------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`reference` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is not yet bound to a value when used within its own initialization`|
++---------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------------------------------------------------------+-------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`variable` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is uninitialized when` |nbsp| |+-----------------------------+|
+| ||:diagtext:`used here` ||
+| |+-----------------------------+|
+| ||:diagtext:`captured by block`||
+| |+-----------------------------+|
++------------------------------------------------------------------------------------------------------------------------+-------------------------------+
+
+
+-Wunknown-argument
+------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`unknown argument ignored in clang-cl: '`:placeholder:`A`:diagtext:`'`|
++-----------------------------------------------------------------------------------------------------------+
+
+
+-Wunknown-attributes
+--------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`unknown attribute` |nbsp| :placeholder:`A` |nbsp| :diagtext:`ignored`|
++-----------------------------------------------------------------------------------------------------------+
+
+
+-Wunknown-escape-sequence
+-------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`unknown escape sequence '\\`:placeholder:`A`:diagtext:`'`|
++-----------------------------------------------------------------------------------------------+
+
+
+-Wunknown-pragmas
+-----------------
+Some of the diagnostics controlled by this flag are enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`expected 'ON' or 'OFF' or 'DEFAULT' in pragma`|
++------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`expected end of directive in pragma`|
++--------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`unknown pragma in STDC namespace`|
++-----------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`pragma diagnostic pop could not pop, no matching push`|
++--------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`pragma diagnostic expected 'error', 'warning', 'ignored', 'fatal', 'push', or 'pop'`|
++--------------------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`pragma diagnostic expected option name (e.g. "-Wundef")`|
++----------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`unexpected token in pragma diagnostic`|
++----------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`unknown warning group '`:placeholder:`A`:diagtext:`', ignored`|
++----------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`unknown pragma ignored`|
++-------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`pragma include\_alias expected '`:placeholder:`A`:diagtext:`'`|
++----------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`pragma include\_alias expected include filename`|
++--------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`angle-bracketed include <`:placeholder:`A`:diagtext:`> cannot be aliased to double-quoted include "`:placeholder:`B`:diagtext:`"`|
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`double-quoted include "`:placeholder:`A`:diagtext:`" cannot be aliased to angle-bracketed include <`:placeholder:`B`:diagtext:`>`|
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`#pragma warning expected '`:placeholder:`A`:diagtext:`'`|
++----------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`#pragma warning expected a warning number`|
++--------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`#pragma warning(push, level) requires a level between 0 and 4`|
++----------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`#pragma warning expected 'push', 'pop', 'default', 'disable', 'error', 'once', 'suppress', 1, 2, 3, or 4`|
++-----------------------------------------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`pragma STDC FENV\_ACCESS ON is not supported, ignoring pragma`|
++----------------------------------------------------------------------------------------------------+
+
+
+-Wunknown-sanitizers
+--------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`unknown sanitizer '`:placeholder:`A`:diagtext:`' ignored`|
++-----------------------------------------------------------------------------------------------+
+
+
+-Wunknown-warning-option
+------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------+---------------------+---------------------------------------------------------+--------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`unknown` |nbsp| |+-------------------+| |nbsp| :diagtext:`option '`:placeholder:`B`:diagtext:`'`|+------------------------------------------------------------+|
+| ||:diagtext:`warning`|| || ||
+| |+-------------------+| |+------------------------------------------------------------+|
+| ||:diagtext:`remark` || ||+----------------------------------------------------------+||
+| |+-------------------+| |||:diagtext:`; did you mean '`:placeholder:`D`:diagtext:`'?`|||
+| | | ||+----------------------------------------------------------+||
+| | | |+------------------------------------------------------------+|
++------------------------------------------------------+---------------------+---------------------------------------------------------+--------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`unknown` |nbsp| :placeholder:`A` |nbsp| :diagtext:`warning specifier: '`:placeholder:`B`:diagtext:`'`|
++-------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wunnamed-type-template-args
+----------------------------
+Some of the diagnostics controlled by this flag are enabled by default.
+
+Also controls `-Wc++98-compat-unnamed-type-template-args`_.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`template argument uses unnamed type`|
++--------------------------------------------------------------------------+
+
+
+-Wunneeded-internal-declaration
+-------------------------------
+**Diagnostic text:**
+
++---------------------------+----------------------+---------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| |+--------------------+| |nbsp| :placeholder:`B` |nbsp| :diagtext:`is not needed and will not be emitted`|
+| ||:diagtext:`function`|| |
+| |+--------------------+| |
+| ||:diagtext:`variable`|| |
+| |+--------------------+| |
++---------------------------+----------------------+---------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'static' function` |nbsp| :placeholder:`A` |nbsp| :diagtext:`declared in header file should be declared 'static inline'`|
++--------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wunneeded-member-function
+--------------------------
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`member function` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is not needed and will not be emitted`|
++---------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wunreachable-code
+------------------
+Also controls `-Wunreachable-code-loop-increment`_.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`code will never be executed`|
++------------------------------------------------------------------+
+
+
+-Wunreachable-code-aggressive
+-----------------------------
+Controls `-Wunreachable-code`_, `-Wunreachable-code-break`_, `-Wunreachable-code-return`_.
+
+
+-Wunreachable-code-break
+------------------------
+**Diagnostic text:**
+
++---------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'break' will never be executed`|
++---------------------------------------------------------------------+
+
+
+-Wunreachable-code-loop-increment
+---------------------------------
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`loop will run at most once (loop increment never executed)`|
++-------------------------------------------------------------------------------------------------+
+
+
+-Wunreachable-code-return
+-------------------------
+**Diagnostic text:**
+
++----------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`'return' will never be executed`|
++----------------------------------------------------------------------+
+
+
+-Wunsequenced
+-------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`multiple unsequenced modifications to` |nbsp| :placeholder:`A`|
++----------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`unsequenced modification and access to` |nbsp| :placeholder:`A`|
++-----------------------------------------------------------------------------------------------------+
+
+
+-Wunsupported-cb
+----------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`ignoring '-mcompact-branches=' option because the '`:placeholder:`A`:diagtext:`' architecture does not support it`|
++--------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wunsupported-dll-base-class-template
+-------------------------------------
+**Diagnostic text:**
+
++---------------------------------------------------------------------------+------------------------------------+------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`propagating dll attribute to` |nbsp| |+----------------------------------+| |nbsp| :diagtext:`base class template without dll attribute is not supported`|
+| ||:diagtext:`already instantiated` || |
+| |+----------------------------------+| |
+| ||:diagtext:`explicitly specialized`|| |
+| |+----------------------------------+| |
++---------------------------------------------------------------------------+------------------------------------+------------------------------------------------------------------------------+
+
+
+-Wunsupported-friend
+--------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`dependent nested name specifier '`:placeholder:`A`:diagtext:`' for friend template declaration is not supported; ignoring this friend declaration`|
++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`dependent nested name specifier '`:placeholder:`A`:diagtext:`' for friend class declaration is not supported; turning off access control for` |nbsp| :placeholder:`B`|
++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wunsupported-nan
+-----------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`ignoring '-mnan=2008' option because the '`:placeholder:`A`:diagtext:`' architecture does not support it`|
++-----------------------------------------------------------------------------------------------------------------------------------------------+
+
++-------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`ignoring '-mnan=legacy' option because the '`:placeholder:`A`:diagtext:`' architecture does not support it`|
++-------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wunsupported-visibility
+------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`target does not support 'protected' visibility; using 'default'`|
++------------------------------------------------------------------------------------------------------+
+
+
+-Wunused
+--------
+Some of the diagnostics controlled by this flag are enabled by default.
+
+Controls `-Wunused-argument`_, `-Wunused-function`_, `-Wunused-label`_, `-Wunused-local-typedef`_, `-Wunused-private-field`_, `-Wunused-property-ivar`_, `-Wunused-value`_, `-Wunused-variable`_.
+
+
+-Wunused-argument
+-----------------
+This diagnostic flag exists for GCC compatibility, and has no effect in Clang.
+
+-Wunused-command-line-argument
+------------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`joined argument expects additional value: '`:placeholder:`A`:diagtext:`'`|
++---------------------------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`argument '-fdiagnostics-show-hotness' requires profile-guided optimization information`|
++-----------------------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------+----------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A`:diagtext:`: '`:placeholder:`B`:diagtext:`' input unused`|+--------------------------------------------------------------------+|
+| ||+------------------------------------------------------------------+||
+| ||| |nbsp| :diagtext:`when '`:placeholder:`D`:diagtext:`' is present`|||
+| ||+------------------------------------------------------------------+||
+| |+--------------------------------------------------------------------+|
+| || ||
+| |+--------------------------------------------------------------------+|
++----------------------------------------------------------------------------------------------------+----------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A`:diagtext:`: '`:placeholder:`B`:diagtext:`' input unused in cpp mode`|
++----------------------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------+-----------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A`:diagtext:`: previously preprocessed input`|+---------------------------------------------------------------------------+|
+| ||+-------------------------------------------------------------------------+||
+| ||| |nbsp| :diagtext:`unused when '`:placeholder:`C`:diagtext:`' is present`|||
+| ||+-------------------------------------------------------------------------+||
+| |+---------------------------------------------------------------------------+|
+| || ||
+| |+---------------------------------------------------------------------------+|
++--------------------------------------------------------------------------------------+-----------------------------------------------------------------------------+
+
++---------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`argument unused during compilation: '`:placeholder:`A`:diagtext:`'`|
++---------------------------------------------------------------------------------------------------------+
+
+
+-Wunused-comparison
+-------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------+-----------------------------------------+--------------------------------------------+
+|:warning:`warning:` |nbsp| |+---------------------------------------+| |nbsp| :diagtext:`comparison result unused`|
+| ||+----------------+--------------------+|| |
+| |||+--------------+|:diagtext:`equality`||| |
+| |||| || ||| |
+| |||+--------------+| ||| |
+| ||||:diagtext:`in`|| ||| |
+| |||+--------------+| ||| |
+| ||+----------------+--------------------+|| |
+| |+---------------------------------------+| |
+| ||:diagtext:`relational` || |
+| |+---------------------------------------+| |
++---------------------------+-----------------------------------------+--------------------------------------------+
+
+
+-Wunused-const-variable
+-----------------------
+**Diagnostic text:**
+
++------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`unused variable` |nbsp| :placeholder:`A`|
++------------------------------------------------------------------------------+
+
+
+-Wunused-exception-parameter
+----------------------------
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`unused exception parameter` |nbsp| :placeholder:`A`|
++-----------------------------------------------------------------------------------------+
+
+
+-Wunused-function
+-----------------
+Also controls `-Wunneeded-internal-declaration`_.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`unused function` |nbsp| :placeholder:`A`|
++------------------------------------------------------------------------------+
+
+
+-Wunused-getter-return-value
+----------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`property access result unused - getters should not be used for side effects`|
++------------------------------------------------------------------------------------------------------------------+
+
+
+-Wunused-label
+--------------
+**Diagnostic text:**
+
++---------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`unused label` |nbsp| :placeholder:`A`|
++---------------------------------------------------------------------------+
+
+
+-Wunused-local-typedef
+----------------------
+**Diagnostic text:**
+
++-----------------------------------------------------+------------------------+------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`unused` |nbsp| |+----------------------+| |nbsp| :placeholder:`B`|
+| ||:diagtext:`typedef` || |
+| |+----------------------+| |
+| ||:diagtext:`type alias`|| |
+| |+----------------------+| |
++-----------------------------------------------------+------------------------+------------------------+
+
+
+-Wunused-local-typedefs
+-----------------------
+Synonym for `-Wunused-local-typedef`_.
+
+
+-Wunused-macros
+---------------
+**Diagnostic text:**
+
++--------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`macro is not used`|
++--------------------------------------------------------+
+
+
+-Wunused-member-function
+------------------------
+Also controls `-Wunneeded-member-function`_.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`unused member function` |nbsp| :placeholder:`A`|
++-------------------------------------------------------------------------------------+
+
+
+-Wunused-parameter
+------------------
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`unused parameter` |nbsp| :placeholder:`A`|
++-------------------------------------------------------------------------------+
+
+
+-Wunused-private-field
+----------------------
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`private field` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is not used`|
++-----------------------------------------------------------------------------------------------------------+
+
+
+-Wunused-property-ivar
+----------------------
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`ivar` |nbsp| :placeholder:`A` |nbsp| :diagtext:`which backs the property is not referenced in this property's accessor`|
++-------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wunused-result
+---------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`ignoring return value of function declared with` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute`|
++-------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wunused-value
+--------------
+This diagnostic is enabled by default.
+
+Also controls `-Wunevaluated-expression`_, `-Wunused-comparison`_, `-Wunused-result`_.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`ignoring return value of function declared with` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute`|
++-------------------------------------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`container access result unused - container access should not be used for side effects`|
++----------------------------------------------------------------------------------------------------------------------------+
+
++---------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`expression result unused`|
++---------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`expression result unused; should this cast be to 'void'?`|
++-----------------------------------------------------------------------------------------------+
+
+
+-Wunused-variable
+-----------------
+Also controls `-Wunused-const-variable`_.
+
+**Diagnostic text:**
+
++------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`unused variable` |nbsp| :placeholder:`A`|
++------------------------------------------------------------------------------+
+
+
+-Wunused-volatile-lvalue
+------------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`expression result unused; assign into a variable to force a volatile load`|
++----------------------------------------------------------------------------------------------------------------+
+
+
+-Wused-but-marked-unused
+------------------------
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`was marked unused but was used`|
++---------------------------------------------------------------------------------------------+
+
+
+-Wuser-defined-literals
+-----------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------+----------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`user-defined literal suffixes not starting with '\_' are reserved`|+--------------------------------------------------+|
+| ||:diagtext:`; no literal will invoke this operator`||
+| |+--------------------------------------------------+|
+| || ||
+| |+--------------------------------------------------+|
++--------------------------------------------------------------------------------------------------------+----------------------------------------------------+
+
+
+-Wvarargs
+---------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++-----------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`second argument to 'va\_start' is not the last named parameter`|
++-----------------------------------------------------------------------------------------------------+
+
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`second argument to 'va\_arg' is of promotable type` |nbsp| :placeholder:`A`:diagtext:`; this va\_arg has undefined behavior because arguments will be promoted to` |nbsp| :placeholder:`B`|
++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
++------------------------------------------------------+-----------------------------------------------------------------+---------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`passing` |nbsp| |+---------------------------------------------------------------+| |nbsp| :diagtext:`to 'va\_start' has undefined behavior`|
+| ||:diagtext:`an object that undergoes default argument promotion`|| |
+| |+---------------------------------------------------------------+| |
+| ||:diagtext:`an object of reference type` || |
+| |+---------------------------------------------------------------+| |
+| ||:diagtext:`a parameter declared with the 'register' keyword` || |
+| |+---------------------------------------------------------------+| |
++------------------------------------------------------+-----------------------------------------------------------------+---------------------------------------------------------+
+
+
+-Wvariadic-macros
+-----------------
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`named variadic macros are a GNU extension`|
++--------------------------------------------------------------------------------+
+
++------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`variadic macros are a C99 feature`|
++------------------------------------------------------------------------+
+
+
+-Wvector-conversion
+-------------------
+**Diagnostic text:**
+
++------------------------------------------------------------------------+----------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`incompatible vector types` |nbsp| |+--------------------------------------------------------------+|
+| ||:diagtext:`assigning to different types` ||
+| |+--------------------------------------------------------------+|
+| ||:diagtext:`passing to parameter of different type` ||
+| |+--------------------------------------------------------------+|
+| ||:diagtext:`returning from function with different return type`||
+| |+--------------------------------------------------------------+|
+| ||:diagtext:`converting between types` ||
+| |+--------------------------------------------------------------+|
+| ||:diagtext:`initializing with expression of different type` ||
+| |+--------------------------------------------------------------+|
+| ||:diagtext:`sending to parameter of different type` ||
+| |+--------------------------------------------------------------+|
+| ||:diagtext:`casting between types` ||
+| |+--------------------------------------------------------------+|
++------------------------------------------------------------------------+----------------------------------------------------------------+
+
+
+-Wvector-conversions
+--------------------
+Synonym for `-Wvector-conversion`_.
+
+
+-Wvexing-parse
+--------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++----------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`empty parentheses interpreted as a function declaration`|
++----------------------------------------------------------------------------------------------+
+
++-----------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`parentheses were disambiguated as a function declaration`|
++-----------------------------------------------------------------------------------------------+
+
+
+-Wvisibility
+------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++---------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`declaration of` |nbsp| :placeholder:`A` |nbsp| :diagtext:`will not be visible outside of this function`|
++---------------------------------------------------------------------------------------------------------------------------------------------+
+
++----------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`redefinition of` |nbsp| :placeholder:`A` |nbsp| :diagtext:`will not be visible outside of this function`|
++----------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wvla
+-----
+**Diagnostic text:**
+
++-----------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`variable length array used`|
++-----------------------------------------------------------------+
+
+
+-Wvla-extension
+---------------
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`variable length arrays are a C99 feature`|
++-------------------------------------------------------------------------------+
+
+
+-Wvoid-ptr-dereference
+----------------------
+This diagnostic is enabled by default.
+
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`ISO C++ does not allow indirection on operand of type` |nbsp| :placeholder:`A`|
++--------------------------------------------------------------------------------------------------------------------+
+
+
+-Wvolatile-register-var
+-----------------------
+This diagnostic flag exists for GCC compatibility, and has no effect in Clang.
+
+-Wweak-template-vtables
+-----------------------
+**Diagnostic text:**
+
++--------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`explicit template instantiation` |nbsp| :placeholder:`A` |nbsp| :diagtext:`will emit a vtable in every translation unit`|
++--------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wweak-vtables
+--------------
+**Diagnostic text:**
+
++------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`has no out-of-line virtual method definitions; its vtable will be emitted in every translation unit`|
++------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wwritable-strings
+------------------
+This diagnostic is enabled by default.
+
+Also controls `-Wdeprecated-writable-strings`_.
+
+**Diagnostic text:**
+
++-------------------------------------------------------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`ISO C++11 does not allow conversion from string literal to` |nbsp| :placeholder:`A`|
++-------------------------------------------------------------------------------------------------------------------------+
+
+
+-Wwrite-strings
+---------------
+Synonym for `-Wwritable-strings`_.
+
+
+-Wzero-length-array
+-------------------
+**Diagnostic text:**
+
++------------------------------------------------------------------------+
+|:warning:`warning:` |nbsp| :diagtext:`zero size arrays are an extension`|
++------------------------------------------------------------------------+
+
+
diff --git a/docs/HowToSetupToolingForLLVM.rst b/docs/HowToSetupToolingForLLVM.rst
index 924774210b33..3812fc9f46e7 100644
--- a/docs/HowToSetupToolingForLLVM.rst
+++ b/docs/HowToSetupToolingForLLVM.rst
@@ -13,7 +13,7 @@ Introduction
Clang Tooling needs a compilation database to figure out specific build
options for each file. Currently it can create a compilation database
-from the ``compilation_commands.json`` file, generated by CMake. When
+from the ``compile_commands.json`` file, generated by CMake. When
invoking clang tools, you can either specify a path to a build directory
using a command line parameter ``-p`` or let Clang Tooling find this
file in your source tree. In either case you need to configure your
diff --git a/docs/JSONCompilationDatabase.rst b/docs/JSONCompilationDatabase.rst
index 926dcba6a4aa..8631e8365cea 100644
--- a/docs/JSONCompilationDatabase.rst
+++ b/docs/JSONCompilationDatabase.rst
@@ -78,6 +78,11 @@ The contracts for each field in the command object are:
Parameters use shell quoting and shell escaping of quotes, with '``"``'
and '``\``' being the only special characters. Shell expansion is not
supported.
+- **arguments:** The compile command executed as list of strings.
+ Either **arguments** or **command** is required.
+- **output:** The name of the output created by this compilation step.
+ This field is optional. It can be used to distinguish different processing
+ modes of the same input file.
Build System Integration
========================
diff --git a/docs/LanguageExtensions.rst b/docs/LanguageExtensions.rst
index 51ac3ab1a8c3..64e6ffb7f3eb 100644
--- a/docs/LanguageExtensions.rst
+++ b/docs/LanguageExtensions.rst
@@ -1865,6 +1865,82 @@ The types ``T`` currently supported are:
Note that the compiler does not guarantee that non-temporal loads or stores
will be used.
+C++ Coroutines support builtins
+--------------------------------
+
+.. warning::
+ This is a work in progress. Compatibility across Clang/LLVM releases is not
+ guaranteed.
+
+Clang provides experimental builtins to support C++ Coroutines as defined by
+http://wg21.link/P0057. The following four are intended to be used by the
+standard library to implement `std::experimental::coroutine_handle` type.
+
+**Syntax**:
+
+.. code-block:: c
+
+ void __builtin_coro_resume(void *addr);
+ void __builtin_coro_destroy(void *addr);
+ bool __builtin_coro_done(void *addr);
+ void *__builtin_coro_promise(void *addr, int alignment, bool from_promise)
+
+**Example of use**:
+
+.. code-block:: c++
+
+ template <> struct coroutine_handle<void> {
+ void resume() const { __builtin_coro_resume(ptr); }
+ void destroy() const { __builtin_coro_destroy(ptr); }
+ bool done() const { return __builtin_coro_done(ptr); }
+ // ...
+ protected:
+ void *ptr;
+ };
+
+ template <typename Promise> struct coroutine_handle : coroutine_handle<> {
+ // ...
+ Promise &promise() const {
+ return *reinterpret_cast<Promise *>(
+ __builtin_coro_promise(ptr, alignof(Promise), /*from-promise=*/false));
+ }
+ static coroutine_handle from_promise(Promise &promise) {
+ coroutine_handle p;
+ p.ptr = __builtin_coro_promise(&promise, alignof(Promise),
+ /*from-promise=*/true);
+ return p;
+ }
+ };
+
+
+Other coroutine builtins are either for internal clang use or for use during
+development of the coroutine feature. See `Coroutines in LLVM
+<http://llvm.org/docs/Coroutines.html#intrinsics>`_ for
+more information on their semantics. Note that builtins matching the intrinsics
+that take token as the first parameter (llvm.coro.begin, llvm.coro.alloc,
+llvm.coro.free and llvm.coro.suspend) omit the token parameter and fill it to
+an appropriate value during the emission.
+
+**Syntax**:
+
+.. code-block:: c
+
+ size_t __builtin_coro_size()
+ void *__builtin_coro_frame()
+ void *__builtin_coro_free(void *coro_frame)
+
+ void *__builtin_coro_id(int align, void *promise, void *fnaddr, void *parts)
+ bool __builtin_coro_alloc()
+ void *__builtin_coro_begin(void *memory)
+ void __builtin_coro_end(void *coro_frame, bool unwind)
+ char __builtin_coro_suspend(bool final)
+ bool __builtin_coro_param(void *original, void *copy)
+
+Note that there is no builtin matching the `llvm.coro.save` intrinsic. LLVM
+automatically will insert one if the first argument to `llvm.coro.suspend` is
+token `none`. If a user calls `__builin_suspend`, clang will insert `token none`
+as the first argument to the intrinsic.
+
Non-standard C++11 Attributes
=============================
diff --git a/docs/LibASTMatchers.rst b/docs/LibASTMatchers.rst
index 738de79d5da6..aea9f3233b4b 100644
--- a/docs/LibASTMatchers.rst
+++ b/docs/LibASTMatchers.rst
@@ -103,7 +103,7 @@ you can :ref:`bind <astmatchers-bind>` the node they represent to ids for later
processing.
``VariadicDynCastAllOfMatchers`` are callable classes that model variadic
-template functions in C++03. They take an aribtrary number of
+template functions in C++03. They take an arbitrary number of
``Matcher<Derived>`` and return a ``Matcher<Base>``.
``AST_MATCHER_P(Type, Name, ParamType, Param)``
diff --git a/docs/LibASTMatchersReference.html b/docs/LibASTMatchersReference.html
index 70c83ea5ccaa..4ee953f1838e 100644
--- a/docs/LibASTMatchersReference.html
+++ b/docs/LibASTMatchersReference.html
@@ -599,7 +599,7 @@ breakStmt()
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cStyleCastExpr0')"><a name="cStyleCastExpr0Anchor">cStyleCastExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CStyleCastExpr.html">CStyleCastExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="cStyleCastExpr0"><pre>Matches a C-style cast expression.
-Example: Matches (int*) 2.2f in
+Example: Matches (int) 2.2f in
int i = (int) 2.2f;
</pre></td></tr>
@@ -1318,6 +1318,17 @@ templateArgument()
</pre></td></tr>
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateName.html">TemplateName</a>&gt;</td><td class="name" onclick="toggle('templateName0')"><a name="templateName0Anchor">templateName</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateName.html">TemplateName</a>&gt;...</td></tr>
+<tr><td colspan="4" class="doc" id="templateName0"><pre>Matches template name.
+
+Given
+ template &lt;typename T&gt; class X { };
+ X&lt;int&gt; xi;
+templateName()
+ matches 'X' in X&lt;int&gt;.
+</pre></td></tr>
+
+
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>&gt;</td><td class="name" onclick="toggle('typeLoc0')"><a name="typeLoc0Anchor">typeLoc</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="typeLoc0"><pre>Matches TypeLocs in the clang AST.
</pre></td></tr>
@@ -2419,7 +2430,8 @@ designatorCountIs(2)
<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.
+<tr><td colspan="4" class="doc" id="hasBitWidth0"><pre>Matches non-static data members that are bit-fields of the specified
+bit width.
Given
class C {
@@ -2427,7 +2439,7 @@ Given
int b : 4;
int c : 2;
};
-fieldDecl(isBitField())
+fieldDecl(hasBitWidth(2))
matches 'int a;' and 'int c;' but not 'int b;'.
</pre></td></tr>
@@ -2599,6 +2611,22 @@ functionDecl(isNoThrow()) and functionProtoType(isNoThrow())
</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('isStaticStorageClass0')"><a name="isStaticStorageClass0Anchor">isStaticStorageClass</a></td><td></td></tr>
+<tr><td colspan="4" class="doc" id="isStaticStorageClass0"><pre>Matches variablefunction declarations that have "static" storage
+class specifier ("static" keyword) written in the source.
+
+Given:
+ static void f() {}
+ static int i = 0;
+ extern int j;
+ int k;
+functionDecl(isStaticStorageClass())
+ matches the function declaration f.
+varDecl(isStaticStorageClass())
+ matches the variable declaration i.
+</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('isTemplateInstantiation0')"><a name="isTemplateInstantiation0Anchor">isTemplateInstantiation</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isTemplateInstantiation0"><pre>Matches template instantiations of function, class, or static
member variable template instantiations.
@@ -2729,6 +2757,26 @@ memberExpr(isArrow())
</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('hasExternalFormalLinkage0')"><a name="hasExternalFormalLinkage0Anchor">hasExternalFormalLinkage</a></td><td></td></tr>
+<tr><td colspan="4" class="doc" id="hasExternalFormalLinkage0"><pre>Matches a declaration that has external formal linkage.
+
+Example matches only z (matcher = varDecl(hasExternalFormalLinkage()))
+void f() {
+ int x;
+ static int y;
+}
+int z;
+
+Example matches f() because it has external formal linkage despite being
+unique to the translation unit as though it has internal likage
+(matcher = functionDecl(hasExternalFormalLinkage()))
+
+namespace {
+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 colspan="4" class="doc" id="hasName0"><pre>Matches NamedDecl nodes that have the specified name.
@@ -2975,7 +3023,7 @@ Given
void a(int);
void b(unsigned long);
void c(double);
-functionDecl(hasAnyParameter(hasType(isInteger())))
+functionDecl(hasAnyParameter(hasType(isSignedInteger())))
matches "a(int)", but not "b(unsigned long)" and "c(double)".
</pre></td></tr>
@@ -2987,7 +3035,7 @@ Given
void a(int);
void b(unsigned long);
void c(double);
-functionDecl(hasAnyParameter(hasType(isInteger())))
+functionDecl(hasAnyParameter(hasType(isUnsignedInteger())))
matches "b(unsigned long)", but not "a(int)" and "c(double)".
</pre></td></tr>
@@ -3349,15 +3397,19 @@ int z;
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;</td><td class="name" onclick="toggle('hasStaticStorageDuration0')"><a name="hasStaticStorageDuration0Anchor">hasStaticStorageDuration</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="hasStaticStorageDuration0"><pre>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.
-Example matches y and a, but not x or z.
-(matcher = varDecl(hasStaticStorageDuration())
void f() {
int x;
static int y;
thread_local int z;
}
int a;
+static int b;
+extern int c;
+varDecl(hasStaticStorageDuration())
+ matches the function declaration y, a, b and c.
</pre></td></tr>
@@ -3430,6 +3482,34 @@ Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Funct
</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 declarations.
+
+Given:
+ extern "C" void f() {}
+ extern "C" { void g() {} }
+ void h() {}
+functionDecl(isExternC())
+ matches the declaration of f and g, but not the declaration h
+</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.
+
+Given:
+ static void f() {}
+ static int i = 0;
+ extern int j;
+ int k;
+functionDecl(isStaticStorageClass())
+ matches the function declaration f.
+varDecl(isStaticStorageClass())
+ matches the variable declaration i.
+</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('isTemplateInstantiation1')"><a name="isTemplateInstantiation1Anchor">isTemplateInstantiation</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isTemplateInstantiation1"><pre>Matches template instantiations of function, class, or static
member variable template instantiations.
@@ -3679,8 +3759,8 @@ 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('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 colspan="4" class="doc" id="hasDeclaration8"><pre>Matches a node if the declaration associated with that node
+<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 colspan="4" class="doc" id="hasDeclaration15"><pre>Matches a node if the declaration associated with that node
matches the given matcher.
The associated declaration is:
@@ -3688,16 +3768,18 @@ The associated declaration is:
- for CallExpr, the declaration of the callee
- for MemberExpr, the declaration of the referenced member
- for CXXConstructExpr, the declaration of the constructor
+- for CXXNewExpr, the declaration of the operator new
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.
-Usable as: 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_1DeclRefExpr.html">DeclRefExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;, 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_1MemberExpr.html">MemberExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
+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;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
</pre></td></tr>
@@ -3918,16 +4000,18 @@ The associated declaration is:
- for CallExpr, the declaration of the callee
- for MemberExpr, the declaration of the referenced member
- for CXXConstructExpr, the declaration of the constructor
+- for CXXNewExpr, the declaration of the operator new
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.
-Usable as: 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_1DeclRefExpr.html">DeclRefExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;, 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_1MemberExpr.html">MemberExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
+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;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
</pre></td></tr>
@@ -4091,6 +4175,30 @@ Example matches A() in the last line
</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 colspan="4" class="doc" id="hasDeclaration12"><pre>Matches a node if the declaration associated with that node
+matches the given matcher.
+
+The associated declaration is:
+- for type nodes, the declaration of the underlying type
+- for CallExpr, the declaration of the callee
+- for MemberExpr, the declaration of the referenced member
+- for CXXConstructExpr, the declaration of the constructor
+- for CXXNewExpr, the declaration of the operator new
+
+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.
+
+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;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
+</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('hasMethod0')"><a name="hasMethod0Anchor">hasMethod</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="hasMethod0"><pre>Matches the first method of a class or struct that satisfies InnerMatcher.
@@ -4211,16 +4319,18 @@ The associated declaration is:
- for CallExpr, the declaration of the callee
- for MemberExpr, the declaration of the referenced member
- for CXXConstructExpr, the declaration of the constructor
+- for CXXNewExpr, the declaration of the operator new
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.
-Usable as: 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_1DeclRefExpr.html">DeclRefExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;, 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_1MemberExpr.html">MemberExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
+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;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
</pre></td></tr>
@@ -4240,30 +4350,44 @@ caseStmt(hasCaseConstant(integerLiteral()))
<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>
-<tr><td colspan="4" class="doc" id="hasAnyTemplateArgument0"><pre>Matches classTemplateSpecializations that have at least one
-TemplateArgument matching the given InnerMatcher.
+<tr><td colspan="4" class="doc" id="hasAnyTemplateArgument0"><pre>Matches classTemplateSpecializations, templateSpecializationType and
+functionDecl that have at least one TemplateArgument matching the given
+InnerMatcher.
Given
template&lt;typename T&gt; class A {};
template&lt;&gt; class A&lt;double&gt; {};
A&lt;int&gt; a;
+
+ template&lt;typename T&gt; f() {};
+ void func() { f&lt;int&gt;(); };
+
classTemplateSpecializationDecl(hasAnyTemplateArgument(
refersToType(asString("int"))))
matches the specialization A&lt;int&gt;
+
+functionDecl(hasAnyTemplateArgument(refersToType(asString("int"))))
+ matches the specialization f&lt;int&gt;
</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('hasTemplateArgument0')"><a name="hasTemplateArgument0Anchor">hasTemplateArgument</a></td><td>unsigned N, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt; InnerMatcher</td></tr>
-<tr><td colspan="4" class="doc" id="hasTemplateArgument0"><pre>Matches classTemplateSpecializations where the n'th TemplateArgument
-matches the given InnerMatcher.
+<tr><td colspan="4" class="doc" id="hasTemplateArgument0"><pre>Matches classTemplateSpecializations, templateSpecializationType and
+functionDecl where the n'th TemplateArgument matches the given InnerMatcher.
Given
template&lt;typename T, typename U&gt; class A {};
A&lt;bool, int&gt; b;
A&lt;int, bool&gt; c;
+
+ template&lt;typename T&gt; f() {};
+ void func() { f&lt;int&gt;(); };
classTemplateSpecializationDecl(hasTemplateArgument(
1, refersToType(asString("int"))))
matches the specialization A&lt;bool, int&gt;
+
+functionDecl(hasTemplateArgument(0, refersToType(asString("int"))))
+ matches the specialization f&lt;int&gt;
</pre></td></tr>
@@ -4315,8 +4439,8 @@ 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('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 colspan="4" class="doc" id="hasDeclaration12"><pre>Matches a node if the declaration associated with that node
+<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 colspan="4" class="doc" id="hasDeclaration11"><pre>Matches a node if the declaration associated with that node
matches the given matcher.
The associated declaration is:
@@ -4324,16 +4448,18 @@ The associated declaration is:
- for CallExpr, the declaration of the callee
- for MemberExpr, the declaration of the referenced member
- for CXXConstructExpr, the declaration of the constructor
+- for CXXNewExpr, the declaration of the operator new
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.
-Usable as: 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_1DeclRefExpr.html">DeclRefExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;, 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_1MemberExpr.html">MemberExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
+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;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
</pre></td></tr>
@@ -4477,8 +4603,8 @@ 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('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 colspan="4" class="doc" id="hasDeclaration11"><pre>Matches a node if the declaration associated with that node
+<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 colspan="4" class="doc" id="hasDeclaration10"><pre>Matches a node if the declaration associated with that node
matches the given matcher.
The associated declaration is:
@@ -4486,16 +4612,18 @@ The associated declaration is:
- for CallExpr, the declaration of the callee
- for MemberExpr, the declaration of the referenced member
- for CXXConstructExpr, the declaration of the constructor
+- for CXXNewExpr, the declaration of the operator new
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.
-Usable as: 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_1DeclRefExpr.html">DeclRefExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;, 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_1MemberExpr.html">MemberExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
+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;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
</pre></td></tr>
@@ -4623,6 +4751,22 @@ would only match the declaration for a.
</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('hasInClassInitializer0')"><a name="hasInClassInitializer0Anchor">hasInClassInitializer</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="hasInClassInitializer0"><pre>Matches non-static data members that have an in-class initializer.
+
+Given
+ class C {
+ int a = 2;
+ int b = 3;
+ int c;
+ };
+fieldDecl(hasInClassInitializer(integerLiteral(equals(2))))
+ matches 'int a;' but not 'int b;'.
+fieldDecl(hasInClassInitializer(anything()))
+ matches 'int a;' and 'int b;' but not 'int c;'.
+</pre></td></tr>
+
+
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ForStmt.html">ForStmt</a>&gt;</td><td class="name" onclick="toggle('hasBody1')"><a name="hasBody1Anchor">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="hasBody1"><pre>Matches a 'for', 'while', 'do while' statement or a function
definition that has a given body.
@@ -4679,6 +4823,28 @@ with hasAnyParameter(...)
</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('hasAnyTemplateArgument2')"><a name="hasAnyTemplateArgument2Anchor">hasAnyTemplateArgument</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt; InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="hasAnyTemplateArgument2"><pre>Matches classTemplateSpecializations, templateSpecializationType and
+functionDecl that have at least one TemplateArgument matching the given
+InnerMatcher.
+
+Given
+ template&lt;typename T&gt; class A {};
+ template&lt;&gt; class A&lt;double&gt; {};
+ A&lt;int&gt; a;
+
+ template&lt;typename T&gt; f() {};
+ void func() { f&lt;int&gt;(); };
+
+classTemplateSpecializationDecl(hasAnyTemplateArgument(
+ refersToType(asString("int"))))
+ matches the specialization A&lt;int&gt;
+
+functionDecl(hasAnyTemplateArgument(refersToType(asString("int"))))
+ matches the specialization f&lt;int&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('hasBody4')"><a name="hasBody4Anchor">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="hasBody4"><pre>Matches a 'for', 'while', 'do while' statement or a function
definition that has a given body.
@@ -4704,6 +4870,26 @@ with hasParameter(...)
</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('hasTemplateArgument2')"><a name="hasTemplateArgument2Anchor">hasTemplateArgument</a></td><td>unsigned N, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt; InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="hasTemplateArgument2"><pre>Matches classTemplateSpecializations, templateSpecializationType and
+functionDecl where the n'th TemplateArgument matches the given InnerMatcher.
+
+Given
+ template&lt;typename T, typename U&gt; class A {};
+ A&lt;bool, int&gt; b;
+ A&lt;int, bool&gt; c;
+
+ template&lt;typename T&gt; f() {};
+ void func() { f&lt;int&gt;(); };
+classTemplateSpecializationDecl(hasTemplateArgument(
+ 1, refersToType(asString("int"))))
+ matches the specialization A&lt;bool, int&gt;
+
+functionDecl(hasTemplateArgument(0, refersToType(asString("int"))))
+ matches the specialization f&lt;int&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('returns0')"><a name="returns0Anchor">returns</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="returns0"><pre>Matches the return type of a function declaration.
@@ -4765,8 +4951,8 @@ 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('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 colspan="4" class="doc" id="hasDeclaration10"><pre>Matches a node if the declaration associated with that node
+<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 colspan="4" class="doc" id="hasDeclaration9"><pre>Matches a node if the declaration associated with that node
matches the given matcher.
The associated declaration is:
@@ -4774,21 +4960,23 @@ The associated declaration is:
- for CallExpr, the declaration of the callee
- for MemberExpr, the declaration of the referenced member
- for CXXConstructExpr, the declaration of the constructor
+- for CXXNewExpr, the declaration of the operator new
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.
-Usable as: 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_1DeclRefExpr.html">DeclRefExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;, 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_1MemberExpr.html">MemberExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
+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;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
</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('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 colspan="4" class="doc" id="hasDeclaration9"><pre>Matches a node if the declaration associated with that node
+<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 colspan="4" class="doc" id="hasDeclaration8"><pre>Matches a node if the declaration associated with that node
matches the given matcher.
The associated declaration is:
@@ -4796,16 +4984,18 @@ The associated declaration is:
- for CallExpr, the declaration of the callee
- for MemberExpr, the declaration of the referenced member
- for CXXConstructExpr, the declaration of the constructor
+- for CXXNewExpr, the declaration of the operator new
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.
-Usable as: 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_1DeclRefExpr.html">DeclRefExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;, 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_1MemberExpr.html">MemberExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
+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;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
</pre></td></tr>
@@ -4818,16 +5008,18 @@ The associated declaration is:
- for CallExpr, the declaration of the callee
- for MemberExpr, the declaration of the referenced member
- for CXXConstructExpr, the declaration of the constructor
+- for CXXNewExpr, the declaration of the operator new
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.
-Usable as: 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_1DeclRefExpr.html">DeclRefExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;, 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_1MemberExpr.html">MemberExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
+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;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
</pre></td></tr>
@@ -4891,6 +5083,19 @@ Usable as: Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Block
</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('hasUnderlyingDecl0')"><a name="hasUnderlyingDecl0Anchor">hasUnderlyingDecl</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1NamedDecl.html">NamedDecl</a>&gt; InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="hasUnderlyingDecl0"><pre>Matches a NamedDecl whose underlying declaration matches the given
+matcher.
+
+Given
+ namespace N { template&lt;class T&gt; void f(T t); }
+ template &lt;class T&gt; void g() { using N::f; f(T()); }
+unresolvedLookupExpr(hasAnyDeclaration(
+ namedDecl(hasUnderlyingDecl(hasName("::N::f")))))
+ matches the use of f in g() .
+</pre></td></tr>
+
+
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifierLoc.html">NestedNameSpecifierLoc</a>&gt;</td><td class="name" onclick="toggle('hasPrefix1')"><a name="hasPrefix1Anchor">hasPrefix</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifierLoc.html">NestedNameSpecifierLoc</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasPrefix1"><pre>Matches on the prefix of a NestedNameSpecifierLoc.
@@ -4978,6 +5183,23 @@ matches the [webView ...] message invocation.
<tr><td colspan="4" class="doc" id="hasSourceExpression1"><pre></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>
+<tr><td colspan="4" class="doc" id="hasAnyDeclaration0"><pre>Matches an OverloadExpr if any of the declarations in the set of
+overloads matches the given matcher.
+
+Given
+ template &lt;typename T&gt; void foo(T);
+ template &lt;typename T&gt; void bar(T);
+ template &lt;typename T&gt; void baz(T t) {
+ foo(t);
+ bar(t);
+ }
+unresolvedLookupExpr(hasAnyDeclaration(
+ functionTemplateDecl(hasName("foo"))))
+ matches foo in foo(t); but not bar in bar(t);
+</pre></td></tr>
+
+
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ParenType.html">ParenType</a>&gt;</td><td class="name" onclick="toggle('innerType0')"><a name="innerType0Anchor">innerType</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="innerType0"><pre>Matches ParenType nodes where the inner type is a specific type.
@@ -5046,16 +5268,18 @@ The associated declaration is:
- for CallExpr, the declaration of the callee
- for MemberExpr, the declaration of the referenced member
- for CXXConstructExpr, the declaration of the constructor
+- for CXXNewExpr, the declaration of the operator new
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.
-Usable as: 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_1DeclRefExpr.html">DeclRefExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;, 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_1MemberExpr.html">MemberExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
+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;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
</pre></td></tr>
@@ -5116,16 +5340,18 @@ The associated declaration is:
- for CallExpr, the declaration of the callee
- for MemberExpr, the declaration of the referenced member
- for CXXConstructExpr, the declaration of the constructor
+- for CXXNewExpr, the declaration of the operator new
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.
-Usable as: 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_1DeclRefExpr.html">DeclRefExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;, 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_1MemberExpr.html">MemberExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
+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;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
</pre></td></tr>
@@ -5212,6 +5438,20 @@ sizeof.
</pre></td></tr>
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1SubstTemplateTypeParmType.html">SubstTemplateTypeParmType</a>&gt;</td><td class="name" onclick="toggle('hasReplacementType0')"><a name="hasReplacementType0Anchor">hasReplacementType</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="hasReplacementType0"><pre>Matches template type parameter substitutions that have a replacement
+type that matches the provided matcher.
+
+Given
+ template &lt;typename T&gt;
+ double F(T t);
+ int i;
+ double j = F(i);
+
+substTemplateTypeParmType(hasReplacementType(type())) matches int
+</pre></td></tr>
+
+
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1SwitchStmt.html">SwitchStmt</a>&gt;</td><td class="name" onclick="toggle('forEachSwitchCase0')"><a name="forEachSwitchCase0Anchor">forEachSwitchCase</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1SwitchCase.html">SwitchCase</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="forEachSwitchCase0"><pre>Matches each case or default statement belonging to the given switch
statement. This matcher may produce multiple matches.
@@ -5243,16 +5483,18 @@ The associated declaration is:
- for CallExpr, the declaration of the callee
- for MemberExpr, the declaration of the referenced member
- for CXXConstructExpr, the declaration of the constructor
+- for CXXNewExpr, the declaration of the operator new
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.
-Usable as: 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_1DeclRefExpr.html">DeclRefExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;, 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_1MemberExpr.html">MemberExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
+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;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
</pre></td></tr>
@@ -5297,6 +5539,19 @@ classTemplateSpecializationDecl(
</pre></td></tr>
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt;</td><td class="name" onclick="toggle('refersToTemplate0')"><a name="refersToTemplate0Anchor">refersToTemplate</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateName.html">TemplateName</a>&gt; InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="refersToTemplate0"><pre>Matches a TemplateArgument that refers to a certain template.
+
+Given
+ template&lt;template &lt;typename&gt; class S&gt; class X {};
+ template&lt;typename T&gt; class Y {};"
+ X&lt;Y&gt; xi;
+classTemplateSpecializationDecl(hasAnyTemplateArgument(
+ refersToTemplate(templateName())))
+ matches the specialization X&lt;Y&gt;
+</pre></td></tr>
+
+
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt;</td><td class="name" onclick="toggle('refersToType0')"><a name="refersToType0Anchor">refersToType</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="refersToType0"><pre>Matches a TemplateArgument that refers to a certain type.
@@ -5311,16 +5566,24 @@ classTemplateSpecializationDecl(hasAnyTemplateArgument(
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;</td><td class="name" onclick="toggle('hasAnyTemplateArgument1')"><a name="hasAnyTemplateArgument1Anchor">hasAnyTemplateArgument</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt; InnerMatcher</td></tr>
-<tr><td colspan="4" class="doc" id="hasAnyTemplateArgument1"><pre>Matches classTemplateSpecializations that have at least one
-TemplateArgument matching the given InnerMatcher.
+<tr><td colspan="4" class="doc" id="hasAnyTemplateArgument1"><pre>Matches classTemplateSpecializations, templateSpecializationType and
+functionDecl that have at least one TemplateArgument matching the given
+InnerMatcher.
Given
template&lt;typename T&gt; class A {};
template&lt;&gt; class A&lt;double&gt; {};
A&lt;int&gt; a;
+
+ template&lt;typename T&gt; f() {};
+ void func() { f&lt;int&gt;(); };
+
classTemplateSpecializationDecl(hasAnyTemplateArgument(
refersToType(asString("int"))))
matches the specialization A&lt;int&gt;
+
+functionDecl(hasAnyTemplateArgument(refersToType(asString("int"))))
+ matches the specialization f&lt;int&gt;
</pre></td></tr>
@@ -5333,30 +5596,38 @@ The associated declaration is:
- for CallExpr, the declaration of the callee
- for MemberExpr, the declaration of the referenced member
- for CXXConstructExpr, the declaration of the constructor
+- for CXXNewExpr, the declaration of the operator new
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.
-Usable as: 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_1DeclRefExpr.html">DeclRefExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;, 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_1MemberExpr.html">MemberExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
+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;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
</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('hasTemplateArgument1')"><a name="hasTemplateArgument1Anchor">hasTemplateArgument</a></td><td>unsigned N, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt; InnerMatcher</td></tr>
-<tr><td colspan="4" class="doc" id="hasTemplateArgument1"><pre>Matches classTemplateSpecializations where the n'th TemplateArgument
-matches the given InnerMatcher.
+<tr><td colspan="4" class="doc" id="hasTemplateArgument1"><pre>Matches classTemplateSpecializations, templateSpecializationType and
+functionDecl where the n'th TemplateArgument matches the given InnerMatcher.
Given
template&lt;typename T, typename U&gt; class A {};
A&lt;bool, int&gt; b;
A&lt;int, bool&gt; c;
+
+ template&lt;typename T&gt; f() {};
+ void func() { f&lt;int&gt;(); };
classTemplateSpecializationDecl(hasTemplateArgument(
1, refersToType(asString("int"))))
matches the specialization A&lt;bool, int&gt;
+
+functionDecl(hasTemplateArgument(0, refersToType(asString("int"))))
+ matches the specialization f&lt;int&gt;
</pre></td></tr>
@@ -5369,16 +5640,18 @@ The associated declaration is:
- for CallExpr, the declaration of the callee
- for MemberExpr, the declaration of the referenced member
- for CXXConstructExpr, the declaration of the constructor
+- for CXXNewExpr, the declaration of the operator new
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.
-Usable as: 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_1DeclRefExpr.html">DeclRefExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;, 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_1MemberExpr.html">MemberExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
+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;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
</pre></td></tr>
@@ -5420,16 +5693,30 @@ The associated declaration is:
- for CallExpr, the declaration of the callee
- for MemberExpr, the declaration of the referenced member
- for CXXConstructExpr, the declaration of the constructor
+- for CXXNewExpr, the declaration of the operator new
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.
-Usable as: 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_1DeclRefExpr.html">DeclRefExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;, 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_1MemberExpr.html">MemberExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
+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;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
+</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('hasUnqualifiedDesugaredType0')"><a name="hasUnqualifiedDesugaredType0Anchor">hasUnqualifiedDesugaredType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt; InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="hasUnqualifiedDesugaredType0"><pre>Matches if the matched type matches the unqualified desugared
+type of the matched node.
+
+For example, in:
+ class A {};
+ using B = A;
+The matcher type(hasUniqualifeidDesugaredType(recordType())) matches
+both B and A.
</pre></td></tr>
@@ -5461,16 +5748,18 @@ The associated declaration is:
- for CallExpr, the declaration of the callee
- for MemberExpr, the declaration of the referenced member
- for CXXConstructExpr, the declaration of the constructor
+- for CXXNewExpr, the declaration of the operator new
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.
-Usable as: 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_1DeclRefExpr.html">DeclRefExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;, 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_1MemberExpr.html">MemberExpr</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;,
- Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
+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;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1EnumType.html">EnumType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1InjectedClassNameType.html">InjectedClassNameType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1LabelStmt.html">LabelStmt</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TagType.html">TagType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateTypeParmType.html">TemplateTypeParmType</a>&gt;, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;,
+ Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingType.html">UnresolvedUsingType</a>&gt;
</pre></td></tr>
diff --git a/docs/LibASTMatchersTutorial.rst b/docs/LibASTMatchersTutorial.rst
index 603b2faf01da..baf2c1c3e699 100644
--- a/docs/LibASTMatchersTutorial.rst
+++ b/docs/LibASTMatchersTutorial.rst
@@ -496,9 +496,9 @@ And change ``LoopPrinter::run`` to
void LoopPrinter::run(const MatchFinder::MatchResult &Result) {
ASTContext *Context = Result.Context;
- const ForStmt *FS = Result.Nodes.getStmtAs<ForStmt>("forLoop");
+ const ForStmt *FS = Result.Nodes.getNodeAs<ForStmt>("forLoop");
// We do not want to convert header files!
- if (!FS || !Context->getSourceManager().isFromMainFile(FS->getForLoc()))
+ if (!FS || !Context->getSourceManager().isWrittenInMainFile(FS->getForLoc()))
return;
const VarDecl *IncVar = Result.Nodes.getNodeAs<VarDecl>("incVarName");
const VarDecl *CondVar = Result.Nodes.getNodeAs<VarDecl>("condVarName");
diff --git a/docs/MSVCCompatibility.rst b/docs/MSVCCompatibility.rst
index ead0ae847a26..b82869b267cd 100644
--- a/docs/MSVCCompatibility.rst
+++ b/docs/MSVCCompatibility.rst
@@ -72,14 +72,11 @@ The status of major ABI-impacting C++ features:
.. _/vm: http://msdn.microsoft.com/en-us/library/yad46a6z.aspx
.. _pointer to a member of a virtual base class: http://llvm.org/PR15713
-* Debug info: :partial:`Minimal`. Clang emits both CodeView line tables
- (similar to what MSVC emits when given the ``/Z7`` flag) and DWARF debug
- information into the object file.
- Microsoft's link.exe will transform the CodeView line tables into a PDB,
- enabling stack traces in all modern Windows debuggers. Clang does not emit
- any CodeView-compatible type info or description of variable layout.
- Binaries linked with either binutils' ld or LLVM's lld should be usable with
- GDB however sophisticated C++ expressions are likely to fail.
+* Debug info: :good:`Mostly complete`. Clang emits relatively complete CodeView
+ debug information if ``/Z7`` or ``/Zi`` is passed. Microsoft's link.exe will
+ transform the CodeView debug information into a PDB that works in Windows
+ debuggers and other tools that consume PDB files like ETW. Work to teach lld
+ about CodeView and PDBs is ongoing.
* RTTI: :good:`Complete`. Generation of RTTI data structures has been
finished, along with support for the ``/GR`` flag.
diff --git a/docs/MemorySanitizer.rst b/docs/MemorySanitizer.rst
index 4e58588b8018..8088ecdf561f 100644
--- a/docs/MemorySanitizer.rst
+++ b/docs/MemorySanitizer.rst
@@ -76,14 +76,14 @@ whether MemorySanitizer is enabled. :ref:`\_\_has\_feature
# endif
#endif
-``__attribute__((no_sanitize_memory))``
+``__attribute__((no_sanitize("memory")))``
-----------------------------------------------
Some code should not be checked by MemorySanitizer. One may use the function
-attribute `no_sanitize_memory` to disable uninitialized checks in a particular
-function. MemorySanitizer may still instrument such functions to avoid false
-positives. This attribute may not be supported by other compilers, so we
-suggest to use it together with ``__has_feature(memory_sanitizer)``.
+attribute ``no_sanitize("memory")`` to disable uninitialized checks in a
+particular function. MemorySanitizer may still instrument such functions to
+avoid false positives. This attribute may not be supported by other compilers,
+so we suggest to use it together with ``__has_feature(memory_sanitizer)``.
Blacklist
---------
diff --git a/docs/Modules.rst b/docs/Modules.rst
index 0ea3b5bb3776..141d3b85753f 100644
--- a/docs/Modules.rst
+++ b/docs/Modules.rst
@@ -174,6 +174,9 @@ Command-line parameters
``-fmodules``
Enable the modules feature.
+``-fbuiltin-module-map``
+ Load the Clang builtins module map file. (Equivalent to ``-fmodule-map-file=<resource dir>/include/module.modulemap``)
+
``-fimplicit-module-maps``
Enable implicit search for module map files named ``module.modulemap`` and similar. This option is implied by ``-fmodules``. If this is disabled with ``-fno-implicit-module-maps``, module map files will only be loaded if they are explicitly specified via ``-fmodule-map-file`` or transitively used by another module map file.
@@ -213,6 +216,9 @@ Command-line parameters
``-fmodule-file=<file>``
Load the given precompiled module file.
+``-fprebuilt-module-path=<directory>``
+ Specify the path to the prebuilt modules. If specified, we will look for modules in this directory for a given top-level module name. We don't need a module map for loading prebuilt modules in this directory and the compiler will not try to rebuild these modules. This can be specified multiple times.
+
Module Semantics
================
@@ -362,6 +368,8 @@ The ``system`` attribute specifies that the module is a system module. When a sy
The ``extern_c`` attribute specifies that the module contains C code that can be used from within C++. When such a module is built for use in C++ code, all of the module's headers will be treated as if they were contained within an implicit ``extern "C"`` block. An import for a module with this attribute can appear within an ``extern "C"`` block. No other restrictions are lifted, however: the module currently cannot be imported within an ``extern "C"`` block in a namespace.
+The ``no_undeclared_includes`` attribute specifies that the module can only reach non-modular headers and headers from used modules. Since some headers could be present in more than one search path and map to different modules in each path, this mechanism helps clang to find the right header, i.e., prefer the one for the current module or in a submodule instead of the first usual match in the search paths.
+
Modules can have a number of different kinds of members, each of which is described below:
.. parsed-literal::
@@ -410,6 +418,12 @@ cplusplus
cplusplus11
C++11 support is available.
+freestanding
+ A freestanding environment is available.
+
+gnuinlineasm
+ GNU inline ASM is available.
+
objc
Objective-C support is available.
diff --git a/docs/ReleaseNotes.rst b/docs/ReleaseNotes.rst
index e4fa953f9319..11ee88f4ae20 100644
--- a/docs/ReleaseNotes.rst
+++ b/docs/ReleaseNotes.rst
@@ -1,6 +1,6 @@
-=======================
-Clang 3.9 Release Notes
-=======================
+=======================================
+Clang 4.0.0 (In-Progress) Release Notes
+=======================================
.. contents::
:local:
@@ -8,11 +8,17 @@ Clang 3.9 Release Notes
Written by the `LLVM Team <http://llvm.org/>`_
+.. warning::
+
+ These are in-progress notes for the upcoming Clang 4.0.0 release. You may
+ prefer the `Clang 3.9 Release Notes
+ <http://llvm.org/releases/3.9.0/tools/clang/docs/ReleaseNotes.html>`_.
+
Introduction
============
This document contains the release notes for the Clang C/C++/Objective-C
-frontend, part of the LLVM Compiler Infrastructure, release 3.9. Here we
+frontend, part of the LLVM Compiler Infrastructure, release 4.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
@@ -25,8 +31,13 @@ the latest release, please check out the main please see the `Clang Web
Site <http://clang.llvm.org>`_ or the `LLVM Web
Site <http://llvm.org>`_.
-What's New in Clang 3.9?
-========================
+Note that if you are reading this file from a Subversion checkout or the
+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 4.0.0?
+==========================
Some of the major new features and improvements to Clang are listed
here. Generic improvements to Clang as a whole or to its underlying
@@ -36,224 +47,124 @@ sections with improvements to Clang's support for those languages.
Major New Features
------------------
-- Clang will no longer pass ``--build-id`` by default to the linker. In modern
- linkers that is a relatively expensive option. It can be passed explicitly
- with ``-Wl,--build-id``. To have clang always pass it, build clang with
- ``-DENABLE_LINKER_BUILD_ID``.
-- On Itanium ABI targets, attribute abi_tag is now supported for compatibility
- with GCC. Clang's implementation of abi_tag is mostly compatible with GCC ABI
- version 10.
+- ...
Improvements to Clang's diagnostics
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Clang's diagnostics are constantly being improved to catch more issues,
-explain them more clearly, and provide more accurate source information
-about them. The improvements since the 3.8 release include:
+- ...
+
+New Compiler Flags
+------------------
+
+The option -Og has been added to optimize the debugging experience.
+For now, this option is exactly the same as -O1. However, in the future,
+some other optimizations might be enabled or disabled.
-- ``-Wcomma`` is a new warning to show most uses of the builtin comma operator.
-- ``-Wfloat-conversion`` has two new sub-warnings to give finer grain control for
- floating point to integer conversion warnings.
+The option ....
- - ``-Wfloat-overflow-conversion`` detects when a constant floating point value
- is converted to an integer type and will overflow the target type.
+New Pragmas in Clang
+-----------------------
+
+Clang now supports the ...
- - ``-Wfloat-zero-conversion`` detects when a non-zero floating point value is
- converted to a zero integer value.
Attribute Changes in Clang
--------------------------
-- The ``nodebug`` attribute may now be applied to static, global, and local
- variables (but not parameters or non-static data members). This will suppress
- all debugging information for the variable (and its type, if there are no
- other uses of the type).
-
+- ...
Windows Support
---------------
-TLS is enabled for Cygwin and defaults to -femulated-tls.
+Clang's support for building native Windows programs ...
-Proper support, including correct mangling and overloading, added for
-MS-specific "__unaligned" type qualifier.
-
-clang-cl now has limited support for the precompiled header flags /Yc, /Yu, and
-/Fp. If the precompiled header is passed on the compile command with /FI, then
-the precompiled header flags are honored. But if the precompiled header is
-included by an ``#include <stdafx.h>`` in each source file instead of by a
-``/FIstdafx.h`` flag, these flag continue to be ignored.
-
-clang-cl has a new flag, ``/imsvc <dir>``, for adding a directory to the system
-include search path (where warnings are disabled by default) without having to
-set ``%INCLUDE%``.
C Language Changes in Clang
---------------------------
-The -faltivec and -maltivec flags no longer silently include altivec.h on Power platforms.
-
-`RenderScript
-<https://developer.android.com/guide/topics/renderscript/compute.html>`_
-support has been added to the frontend and enabled by the '-x renderscript'
-option or the '.rs' file extension.
-
-
-C++ Language Changes in Clang
------------------------------
-
-- Clang now enforces the rule that a *using-declaration* cannot name an enumerator of a
- scoped enumeration.
- .. code-block:: c++
+- ...
- namespace Foo { enum class E { e }; }
- namespace Bar {
- using Foo::E::e; // error
- constexpr auto e = Foo::E::e; // ok
- }
+...
-- Clang now enforces the rule that an enumerator of an unscoped enumeration declared at
- class scope can only be named by a *using-declaration* in a derived class.
+C11 Feature Support
+^^^^^^^^^^^^^^^^^^^
- .. code-block:: c++
+...
- class Foo { enum E { e }; }
- using Foo::e; // error
- static constexpr auto e = Foo::e; // ok
+C++ Language Changes in Clang
+-----------------------------
+...
C++1z Feature Support
^^^^^^^^^^^^^^^^^^^^^
-Clang's experimental support for the upcoming C++1z standard can be enabled with ``-std=c++1z``.
-Changes to C++1z features since Clang 3.8:
-
-- The ``[[fallthrough]]``, ``[[nodiscard]]``, and ``[[maybe_unused]]`` attributes are
- supported in C++11 onwards, and are largely synonymous with Clang's existing attributes
- ``[[clang::fallthrough]]``, ``[[gnu::warn_unused_result]]``, and ``[[gnu::unused]]``.
- Use ``-Wimplicit-fallthrough`` to warn on unannotated fallthrough within ``switch``
- statements.
-
-- In C++1z mode, aggregate initialization can be performed for classes with base classes:
-
- .. code-block:: c++
-
- struct A { int n; };
- struct B : A { int x, y; };
- B b = { 1, 2, 3 }; // b.n == 1, b.x == 2, b.y == 3
-
-- The range in a range-based ``for`` statement can have different types for its ``begin``
- and ``end`` iterators. This is permitted as an extension in C++11 onwards.
-
-- Lambda-expressions can explicitly capture ``*this`` (to capture the surrounding object
- by copy). This is permitted as an extension in C++11 onwards.
+...
-- Objects of enumeration type can be direct-list-initialized from a value of the underlying
- type. ``E{n}`` is equivalent to ``E(n)``, except that it implies a check for a narrowing
- conversion.
+Objective-C Language Changes in Clang
+-------------------------------------
-- Unary *fold-expression*\s over an empty pack are now rejected for all operators
- other than ``&&``, ``||``, and ``,``.
+...
OpenCL C Language Changes in Clang
----------------------------------
-Clang now has support for all OpenCL 2.0 features. In particular, the following
-features have been completed since the previous release:
-
-- Pipe builtin functions (s6.13.16.2-4).
-- Dynamic parallelism support via the ``enqueue_kernel`` Clang builtin function,
- as well as the kernel query functions from s6.13.17.6.
-- Address space conversion functions ``to_{global/local/private}``.
-- ``nosvm`` attribute support.
-- Improved diagnostic and generation of Clang Blocks used in OpenCL kernel code.
-- ``opencl_unroll_hint`` pragma.
-
-Several miscellaneous improvements have been made:
-
-- Supported extensions are now part of the target representation to give correct
- diagnostics for unsupported target features during compilation. For example,
- when compiling for a target that does not support the double precision
- floating point extension, Clang will give an error when encountering the
- ``cl_khr_fp64`` pragma. Several missing extensions were added covering up to
- and including OpenCL 2.0.
-- Clang now comes with the OpenCL standard headers declaring builtin types and
- functions up to and including OpenCL 2.0 in ``lib/Headers/opencl-c.h``. By
- default, Clang will not include this header. It can be included either using
- the regular ``-I<path to header location>`` directive or (if the default one
- from installation is to be used) using the ``-finclude-default-header``
- frontend flag.
-
- Example:
-
- .. code-block:: none
-
- echo "bool is_wg_uniform(int i){return get_enqueued_local_size(i)==get_local_size(i);}" > test.cl
- clang -cc1 -finclude-default-header -cl-std=CL2.0 test.cl
-
- All builtin function declarations from OpenCL 2.0 will be automatically
- visible in test.cl.
-- Image types have been improved with better diagnostics for access qualifiers.
- Images with one access qualifier type cannot be used in declarations for
- another type. Also qualifiers are now propagated from the frontend down to
- libraries and backends.
-- Diagnostic improvements for OpenCL types, address spaces and vectors.
-- Half type literal support has been added. For example, ``1.0h`` represents a
- floating point literal in half precision, i.e., the value ``0xH3C00``.
-- The Clang driver now accepts OpenCL compiler options ``-cl-*`` (following the
- OpenCL Spec v1.1-1.2 s5.8). For example, the ``-cl-std=CL1.2`` option from the
- spec enables compilation for OpenCL 1.2, or ``-cl-mad-enable`` will enable
- fusing multiply-and-add operations.
-- Clang now uses function metadata instead of module metadata to propagate
- information related to OpenCL kernels e.g. kernel argument information.
+...
OpenMP Support in Clang
----------------------------------
-Added support for all non-offloading features from OpenMP 4.5, including using
-data members in private clauses of non-static member functions. Additionally,
-data members can be used as loop control variables in loop-based directives.
+...
-Currently Clang supports OpenMP 3.1 and all non-offloading features of
-OpenMP 4.0/4.5. Offloading features are under development. Clang defines macro
-_OPENMP and sets it to OpenMP 3.1 (in accordance with OpenMP standard) by
-default. User may change this value using ``-fopenmp-version=[31|40|45]`` option.
+Internal API Changes
+--------------------
-The codegen for OpenMP constructs was significantly improved to produce much
-more stable and faster code.
+These are major API changes that have happened since the 3.9 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.
+
+- ...
AST Matchers
------------
-- has and hasAnyArgument: Matchers no longer ignore parentheses and implicit
- casts on the argument before applying the inner matcher. The fix was done to
- allow for greater control by the user. In all existing checkers that use this
- matcher all instances of code ``hasAnyArgument(<inner matcher>)`` or
- ``has(<inner matcher>)`` must be changed to
- ``hasAnyArgument(ignoringParenImpCasts(<inner matcher>))`` or
- ``has(ignoringParenImpCasts(<inner matcher>))``.
+...
+
+libclang
+--------
+
+...
+
+With the option --show-description, scan-build's list of defects will also
+show the description of the defects.
+
Static Analyzer
---------------
-The analyzer now checks for incorrect usage of MPI APIs in C and C++. This
-check can be enabled by passing the following command to scan-build:
-``-enable-checker optin.mpi.MPI-Checker.``
+...
+
+Core Analysis Improvements
+==========================
+
+- ...
+
+New Issues Found
+================
-The analyzer now checks for improper instance cleanup up in Objective-C
-``-dealloc`` methods under manual retain/release.
+- ...
-On Windows, checks for memory leaks, double frees, and use-after-free problems
-are now enabled by default.
+Python Binding Changes
+----------------------
-The analyzer now includes scan-build-py, an experimental reimplementation of
-scan-build in Python that also creates compilation databases.
+The following methods have been added:
-The scan-build tool now supports a ``--force-analyze-debug-code`` flag that
-forces projects to analyze in debug mode. This flag leaves in assertions and so
-typically results in fewer false positives.
+- ...
+Significant Known Problems
+==========================
Additional Information
======================
diff --git a/docs/SanitizerCoverage.rst b/docs/SanitizerCoverage.rst
index f7ec65fdd155..3e8102a12f67 100644
--- a/docs/SanitizerCoverage.rst
+++ b/docs/SanitizerCoverage.rst
@@ -114,7 +114,7 @@ Sancov matches these files using module names and binaries file names.
-print - Print coverage addresses
-covered-functions - Print all covered functions.
-not-covered-functions - Print all not covered functions.
- -html-report - Print HTML coverage report.
+ -symbolize - Symbolizes the report.
Options
-blacklist=<string> - Blacklist file (sanitizer blacklist format).
@@ -122,13 +122,21 @@ Sancov matches these files using module names and binaries file names.
-strip_path_prefix=<string> - Strip this prefix from file paths in reports
-Automatic HTML Report Generation
+Coverage Reports (Experimental)
================================
-If ``*SAN_OPTIONS`` contains ``html_cov_report=1`` option set, then html
-coverage report would be automatically generated alongside the coverage files.
-The ``sancov`` binary should be present in ``PATH`` or
-``sancov_path=<path_to_sancov`` option can be used to specify tool location.
+``.sancov`` files do not contain enough information to generate a source-level
+coverage report. The missing information is contained
+in debug info of the binary. Thus the ``.sancov`` has to be symbolized
+to produce a ``.symcov`` file first:
+
+.. code-block:: console
+
+ sancov -symbolize my_program.123.sancov my_program > my_program.123.symcov
+
+The ``.symcov`` file can be browsed overlayed over the source code by
+running ``tools/sancov/coverage-report-server.py`` script that will start
+an HTTP server.
How good is the coverage?
@@ -321,23 +329,133 @@ by the user. So, these flags do not require the other sanitizer to be used.
This mechanism is used for fuzzing the Linux kernel (https://github.com/google/syzkaller)
and can be used with `AFL <http://lcamtuf.coredump.cx/afl>`__.
+Tracing PCs with guards
+=======================
+Another *experimental* feature that tries to combine the functionality of `trace-pc`,
+`8bit-counters` and boolean coverage.
+
+With ``-fsanitize-coverage=trace-pc-guard`` the compiler will insert the following code
+on every edge:
+
+.. code-block:: none
+
+ if (guard_variable)
+ __sanitizer_cov_trace_pc_guard(&guard_variable)
+
+Every edge will have its own `guard_variable` (uint32_t).
+
+The compler will also insert a module constructor that will call
+
+.. code-block:: c++
+
+ // The guards are [start, stop).
+ // This function may be called multiple times with the same values of start/stop.
+ __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop);
+
+Similarly to `trace-pc,indirect-calls`, with `trace-pc-guards,indirect-calls`
+``__sanitizer_cov_trace_pc_indirect(void *callee)`` will be inserted on every indirect call.
+
+The functions `__sanitizer_cov_trace_pc_*` should be defined by the user.
+
+Example:
+
+.. code-block:: c++
+
+ // trace-pc-guard-cb.cc
+ #include <stdint.h>
+ #include <stdio.h>
+ #include <sanitizer/coverage_interface.h>
+
+ // This callback is inserted by the compiler as a module constructor
+ // into every compilation unit. 'start' and 'stop' correspond to the
+ // beginning and end of the section with the guards for the entire
+ // binary (executable or DSO) and so it will be called multiple times
+ // with the same parameters.
+ extern "C" void __sanitizer_cov_trace_pc_guard_init(uint32_t *start,
+ uint32_t *stop) {
+ static uint64_t N; // Counter for the guards.
+ if (start == stop || *start) return; // Initialize only once.
+ printf("INIT: %p %p\n", start, stop);
+ for (uint32_t *x = start; x < stop; x++)
+ *x = ++N; // Guards should start from 1.
+ }
+
+ // This callback is inserted by the compiler on every edge in the
+ // control flow (some optimizations apply).
+ // Typically, the compiler will emit the code like this:
+ // if(*guard)
+ // __sanitizer_cov_trace_pc_guard(guard);
+ // But for large functions it will emit a simple call:
+ // __sanitizer_cov_trace_pc_guard(guard);
+ extern "C" void __sanitizer_cov_trace_pc_guard(uint32_t *guard) {
+ if (!*guard) return; // Duplicate the guard check.
+ // If you set *guard to 0 this code will not be called again for this edge.
+ // Now you can get the PC and do whatever you want:
+ // store it somewhere or symbolize it and print right away.
+ // The values of `*guard` are as you set them in
+ // __sanitizer_cov_trace_pc_guard_init and so you can make them consecutive
+ // and use them to dereference an array or a bit vector.
+ void *PC = __builtin_return_address(0);
+ char PcDescr[1024];
+ // This function is a part of the sanitizer run-time.
+ // To use it, link with AddressSanitizer or other sanitizer.
+ __sanitizer_symbolize_pc(PC, "%p %F %L", PcDescr, sizeof(PcDescr));
+ printf("guard: %p %x PC %s\n", guard, *guard, PcDescr);
+ }
+
+.. code-block:: c++
+
+ // trace-pc-guard-example.cc
+ void foo() { }
+ int main(int argc, char **argv) {
+ if (argc > 1) foo();
+ }
+
+.. code-block:: console
+
+ clang++ -g -fsanitize-coverage=trace-pc-guard trace-pc-guard-example.cc -c
+ clang++ trace-pc-guard-cb.cc trace-pc-guard-example.o -fsanitize=address
+ ASAN_OPTIONS=strip_path_prefix=`pwd`/ ./a.out
+
+.. code-block:: console
+
+ INIT: 0x71bcd0 0x71bce0
+ guard: 0x71bcd4 2 PC 0x4ecd5b in main trace-pc-guard-example.cc:2
+ guard: 0x71bcd8 3 PC 0x4ecd9e in main trace-pc-guard-example.cc:3:7
+
+.. code-block:: console
+
+ ASAN_OPTIONS=strip_path_prefix=`pwd`/ ./a.out with-foo
+
+
+.. code-block:: console
+
+ INIT: 0x71bcd0 0x71bce0
+ guard: 0x71bcd4 2 PC 0x4ecd5b in main trace-pc-guard-example.cc:3
+ guard: 0x71bcdc 4 PC 0x4ecdc7 in main trace-pc-guard-example.cc:4:17
+ guard: 0x71bcd0 1 PC 0x4ecd20 in foo() trace-pc-guard-example.cc:2:14
+
+
Tracing data flow
=================
-An *experimental* feature to support data-flow-guided fuzzing.
+Support for data-flow-guided fuzzing.
With ``-fsanitize-coverage=trace-cmp`` the compiler will insert extra instrumentation
around comparison instructions and switch statements.
-The fuzzer will need to define the following functions,
-they will be called by the instrumented code.
+Similarly, with ``-fsanitize-coverage=trace-div`` the compiler will instrument
+integer division instructions (to capture the right argument of division)
+and with ``-fsanitize-coverage=trace-gep`` --
+the `LLVM GEP instructions <http://llvm.org/docs/GetElementPtr.html>`_
+(to capture array indices).
.. code-block:: c++
// Called before a comparison instruction.
- // SizeAndType is a packed value containing
- // - [63:32] the Size of the operands of comparison in bits
- // - [31:0] the Type of comparison (one of ICMP_EQ, ... ICMP_SLE)
// Arg1 and Arg2 are arguments of the comparison.
- void __sanitizer_cov_trace_cmp(uint64_t SizeAndType, uint64_t Arg1, uint64_t Arg2);
+ void __sanitizer_cov_trace_cmp1(uint8_t Arg1, uint8_t Arg2);
+ void __sanitizer_cov_trace_cmp2(uint16_t Arg1, uint16_t Arg2);
+ void __sanitizer_cov_trace_cmp4(uint32_t Arg1, uint32_t Arg2);
+ void __sanitizer_cov_trace_cmp8(uint64_t Arg1, uint64_t Arg2);
// Called before a switch statement.
// Val is the switch operand.
@@ -346,6 +464,16 @@ they will be called by the instrumented code.
// Cases[2:] are the case constants.
void __sanitizer_cov_trace_switch(uint64_t Val, uint64_t *Cases);
+ // Called before a division statement.
+ // Val is the second argument of division.
+ void __sanitizer_cov_trace_div4(uint32_t Val);
+ void __sanitizer_cov_trace_div8(uint64_t Val);
+
+ // Called before a GetElemementPtr (GEP) instruction
+ // for every non-constant array index.
+ void __sanitizer_cov_trace_gep(uintptr_t Idx);
+
+
This interface is a subject to change.
The current implementation is not thread-safe and thus can be safely used only for single-threaded targets.
diff --git a/docs/SourceBasedCodeCoverage.rst b/docs/SourceBasedCodeCoverage.rst
index 8d0a51fd3315..abb682355b1c 100644
--- a/docs/SourceBasedCodeCoverage.rst
+++ b/docs/SourceBasedCodeCoverage.rst
@@ -61,7 +61,7 @@ To compile code with coverage enabled, pass ``-fprofile-instr-generate
% clang++ -fprofile-instr-generate -fcoverage-mapping foo.cc -o foo
Note that linking together code with and without coverage instrumentation is
-supported: any uninstrumented code simply won't be accounted for.
+supported. Uninstrumented code simply won't be accounted for in reports.
Running the instrumented program
================================
@@ -95,28 +95,22 @@ Creating coverage reports
=========================
Raw profiles have to be **indexed** before they can be used to generate
-coverage reports. This is done using the "merge" tool in ``llvm-profdata``, so
-named because it can combine and index profiles at the same time:
+coverage reports. This is done using the "merge" tool in ``llvm-profdata``
+(which can combine multiple raw profiles and index them at the same time):
.. code-block:: console
# Step 3(a): Index the raw profile.
% llvm-profdata merge -sparse foo.profraw -o foo.profdata
-There are multiple different ways to render coverage reports. One option is to
-generate a line-oriented report:
+There are multiple different ways to render coverage reports. The simplest
+option is to generate a line-oriented report:
.. code-block:: console
# Step 3(b): Create a line-oriented coverage report.
% llvm-cov show ./foo -instr-profile=foo.profdata
-To demangle any C++ identifiers in the output, use:
-
-.. code-block:: console
-
- % llvm-cov show ./foo -instr-profile=foo.profdata | c++filt -n
-
This report includes a summary view as well as dedicated sub-views for
templated functions and their instantiations. For our example program, we get
distinct views for ``foo<int>(...)`` and ``foo<float>(...)``. If
@@ -125,38 +119,43 @@ region counts (even in macro expansions):
.. code-block:: none
- 20| 1|#define BAR(x) ((x) || (x))
+ 1| 20|#define BAR(x) ((x) || (x))
^20 ^2
2| 2|template <typename T> void foo(T x) {
- 22| 3| for (unsigned I = 0; I < 10; ++I) { BAR(I); }
+ 3| 22| for (unsigned I = 0; I < 10; ++I) { BAR(I); }
^22 ^20 ^20^20
- 2| 4|}
+ 4| 2|}
------------------
| void foo<int>(int):
- | 1| 2|template <typename T> void foo(T x) {
- | 11| 3| for (unsigned I = 0; I < 10; ++I) { BAR(I); }
+ | 2| 1|template <typename T> void foo(T x) {
+ | 3| 11| for (unsigned I = 0; I < 10; ++I) { BAR(I); }
| ^11 ^10 ^10^10
- | 1| 4|}
+ | 4| 1|}
------------------
| void foo<float>(int):
- | 1| 2|template <typename T> void foo(T x) {
- | 11| 3| for (unsigned I = 0; I < 10; ++I) { BAR(I); }
+ | 2| 1|template <typename T> void foo(T x) {
+ | 3| 11| for (unsigned I = 0; I < 10; ++I) { BAR(I); }
| ^11 ^10 ^10^10
- | 1| 4|}
+ | 4| 1|}
------------------
-It's possible to generate a file-level summary of coverage statistics (instead
-of a line-oriented report) with:
+To generate a file-level summary of coverage statistics instead of a
+line-oriented report, try:
.. code-block:: console
# Step 3(c): Create a coverage summary.
% llvm-cov report ./foo -instr-profile=foo.profdata
- Filename Regions Miss Cover Functions Executed
- -----------------------------------------------------------------------
- /tmp/foo.cc 13 0 100.00% 3 100.00%
- -----------------------------------------------------------------------
- TOTAL 13 0 100.00% 3 100.00%
+ Filename Regions Missed Regions Cover Functions Missed Functions Executed Lines Missed Lines Cover
+ --------------------------------------------------------------------------------------------------------------------------------------
+ /tmp/foo.cc 13 0 100.00% 3 0 100.00% 13 0 100.00%
+ --------------------------------------------------------------------------------------------------------------------------------------
+ TOTAL 13 0 100.00% 3 0 100.00% 13 0 100.00%
+
+The ``llvm-cov`` tool supports specifying a custom demangler, writing out
+reports in a directory structure, and generating html reports. For the full
+list of options, please refer to the `command guide
+<http://llvm.org/docs/CommandGuide/llvm-cov.html>`_.
A few final notes:
@@ -177,6 +176,40 @@ A few final notes:
% llvm-profdata merge -sparse foo1.profraw foo2.profdata -o foo3.profdata
+Exporting coverage data
+=======================
+
+Coverage data can be exported into JSON using the ``llvm-cov export``
+sub-command. There is a comprehensive reference which defines the structure of
+the exported data at a high level in the llvm-cov source code.
+
+Interpreting reports
+====================
+
+There are four statistics tracked in a coverage summary:
+
+* Function coverage is the percentage of functions which have been executed at
+ least once. A function is considered to be executed if any of its
+ instantiations are executed.
+
+* Instantiation coverage is the percentage of function instantiations which
+ have been executed at least once. Template functions and static inline
+ functions from headers are two kinds of functions which may have multiple
+ instantiations.
+
+* Line coverage is the percentage of code lines which have been executed at
+ least once. Only executable lines within function bodies are considered to be
+ code lines.
+
+* Region coverage is the percentage of code regions which have been executed at
+ least once. A code region may span multiple lines (e.g in a large function
+ body with no control flow). However, it's also possible for a single line to
+ contain multiple code regions (e.g in "return x || y && z").
+
+Of these four statistics, function coverage is usually the least granular while
+region coverage is the most granular. The project-wide totals for each
+statistic are listed in the summary.
+
Format compatibility guarantees
===============================
@@ -189,9 +222,14 @@ Format compatibility guarantees
These formats are not forwards-compatible: i.e, a tool which uses format
version X will not be able to understand format version (X+k).
-* There is a third format in play: the format of the coverage mappings emitted
- into instrumented binaries. Tools must retain **backwards** compatibility
- with these formats. These formats are not forwards-compatible.
+* Tools must also retain **backwards** compatibility with the format of the
+ coverage mappings emitted into instrumented binaries. These formats are not
+ forwards-compatible.
+
+* The JSON coverage export format has a (major, minor, patch) version triple.
+ Only a major version increment indicates a backwards-incompatible change. A
+ minor version increment is for added functionality, and patch version
+ increments are for bugfixes.
Using the profiling runtime without static initializers
=======================================================
@@ -218,6 +256,18 @@ without using static initializers, do this manually:
otherwise. Calling this function multiple times appends profile data to an
existing on-disk raw profile.
+Collecting coverage reports for the llvm project
+================================================
+
+To prepare a coverage report for llvm (and any of its sub-projects), add
+``-DLLVM_BUILD_INSTRUMENTED_COVERAGE=On`` to the cmake configuration. Raw
+profiles will be written to ``$BUILD_DIR/profiles/``. To prepare an html
+report, run ``llvm/utils/prepare-code-coverage-artifact.py``.
+
+To specify an alternate directory for raw profiles, use
+``-DLLVM_PROFILE_DATA_DIR``. To change the size of the profile merge pool, use
+``-DLLVM_PROFILE_MERGE_POOL_SIZE``.
+
Drawbacks and limitations
=========================
diff --git a/docs/ThinLTO.rst b/docs/ThinLTO.rst
new file mode 100644
index 000000000000..7c7d9513025a
--- /dev/null
+++ b/docs/ThinLTO.rst
@@ -0,0 +1,159 @@
+=======
+ThinLTO
+=======
+
+.. contents::
+ :local:
+
+Introduction
+============
+
+*ThinLTO* compilation is a new type of LTO that is both scalable and
+incremental. *LTO* (Link Time Optimization) achieves better
+runtime performance through whole-program analysis and cross-module
+optimization. However, monolithic LTO implements this by merging all
+input into a single module, which is not scalable
+in time or memory, and also prevents fast incremental compiles.
+
+In ThinLTO mode, as with regular LTO, clang emits LLVM bitcode after the
+compile phase. The ThinLTO bitcode is augmented with a compact summary
+of the module. During the link step, only the summaries are read and
+merged into a combined summary index, which includes an index of function
+locations for later cross-module function importing. Fast and efficient
+whole-program analysis is then performed on the combined summary index.
+
+However, all transformations, including function importing, occur
+later when the modules are optimized in fully parallel backends.
+By default, linkers_ that support ThinLTO are set up to launch
+the ThinLTO backends in threads. So the usage model is not affected
+as the distinction between the fast serial thin link step and the backends
+is transparent to the user.
+
+For more information on the ThinLTO design and current performance,
+see the LLVM blog post `ThinLTO: Scalable and Incremental LTO
+<http://blog.llvm.org/2016/06/thinlto-scalable-and-incremental-lto.html>`_.
+While tuning is still in progress, results in the blog post show that
+ThinLTO already performs well compared to LTO, in many cases matching
+the performance improvement.
+
+Current Status
+==============
+
+Clang/LLVM
+----------
+.. _compiler:
+
+The 3.9 release of clang includes ThinLTO support. However, ThinLTO
+is under active development, and new features, improvements and bugfixes
+are being added for the next release. For the latest ThinLTO support,
+`build a recent version of clang and LLVM
+<http://llvm.org/docs/CMake.html>`_.
+
+Linkers
+-------
+.. _linkers:
+.. _linker:
+
+ThinLTO is currently supported for the following linkers:
+
+- **gold (via the gold-plugin)**:
+ Similar to monolithic LTO, this requires using
+ a `gold linker configured with plugins enabled
+ <http://llvm.org/docs/GoldPlugin.html>`_.
+- **ld64**:
+ Starting with `Xcode 8 <https://developer.apple.com/xcode/>`_.
+- **lld**:
+ Starting with r284050 (ELF only).
+
+Usage
+=====
+
+Basic
+-----
+
+To utilize ThinLTO, simply add the -flto=thin option to compile and link. E.g.
+
+.. code-block:: console
+
+ % clang -flto=thin -O2 file1.c file2.c -c
+ % clang -flto=thin -O2 file1.o file2.o -o a.out
+
+As mentioned earlier, by default the linkers will launch the ThinLTO backend
+threads in parallel, passing the resulting native object files back to the
+linker for the final native link. As such, the usage model the same as
+non-LTO.
+
+With gold, if you see an error during the link of the form:
+
+.. code-block:: console
+
+ /usr/bin/ld: error: /path/to/clang/bin/../lib/LLVMgold.so: could not load plugin library: /path/to/clang/bin/../lib/LLVMgold.so: cannot open shared object file: No such file or directory
+
+Then either gold was not configured with plugins enabled, or clang
+was not built with ``-DLLVM_BINUTILS_INCDIR`` set properly. See
+the instructions for the
+`LLVM gold plugin <http://llvm.org/docs/GoldPlugin.html#how-to-build-it>`_.
+
+Controlling Backend Parallelism
+-------------------------------
+.. _parallelism:
+
+By default, the ThinLTO link step will launch up to
+``std::thread::hardware_concurrency`` number of threads in parallel.
+For machines with hyper-threading, this is the total number of
+virtual cores. For some applications and machine configurations this
+may be too aggressive, in which case the amount of parallelism can
+be reduced to ``N`` via:
+
+- gold:
+ ``-Wl,-plugin-opt,jobs=N``
+- ld64:
+ ``-Wl,-mllvm,-threads=N``
+- lld:
+ ``-Wl,--thinlto-jobs=N``
+
+Incremental
+-----------
+.. _incremental:
+
+ThinLTO supports fast incremental builds through the use of a cache,
+which currently must be enabled through a linker option.
+
+- gold (as of LLVM r279883):
+ ``-Wl,-plugin-opt,cache-dir=/path/to/cache``
+- ld64 (support in clang 3.9 and Xcode 8):
+ ``-Wl,-cache_path_lto,/path/to/cache``
+
+Clang Bootstrap
+---------------
+
+To bootstrap clang/LLVM with ThinLTO, follow these steps:
+
+1. The host compiler_ must be a version of clang that supports ThinLTO.
+#. The host linker_ must support ThinLTO (and in the case of gold, must be
+ `configured with plugins enabled <http://llvm.org/docs/GoldPlugin.html>`_.
+#. Use the following additional `CMake variables
+ <http://llvm.org/docs/CMake.html#options-and-variables>`_
+ when configuring the bootstrap compiler build:
+
+ * ``-DLLVM_ENABLE_LTO=Thin``
+ * ``-DLLVM_PARALLEL_LINK_JOBS=1``
+ (since the ThinLTO link invokes parallel backend jobs)
+ * ``-DCMAKE_C_COMPILER=/path/to/host/clang``
+ * ``-DCMAKE_CXX_COMPILER=/path/to/host/clang++``
+ * ``-DCMAKE_RANLIB=/path/to/host/llvm-ranlib``
+ * ``-DCMAKE_AR=/path/to/host/llvm-ar``
+
+#. To use additional linker arguments for controlling the backend
+ parallelism_ or enabling incremental_ builds of the bootstrap compiler,
+ after configuring the build, modify the resulting CMakeCache.txt file in the
+ build directory. Specify any additional linker options after
+ ``CMAKE_EXE_LINKER_FLAGS:STRING=``. Note the configure may fail if
+ linker plugin options are instead specified directly in the previous step.
+
+More Information
+================
+
+* From LLVM project blog:
+ `ThinLTO: Scalable and Incremental LTO
+ <http://blog.llvm.org/2016/06/thinlto-scalable-and-incremental-lto.html>`_
diff --git a/docs/ThreadSanitizer.rst b/docs/ThreadSanitizer.rst
index cfb0a952e12e..cfbaa63d6432 100644
--- a/docs/ThreadSanitizer.rst
+++ b/docs/ThreadSanitizer.rst
@@ -83,11 +83,11 @@ this purpose.
# endif
#endif
-``__attribute__((no_sanitize_thread))``
+``__attribute__((no_sanitize("thread")))``
-----------------------------------------------
Some code should not be instrumented by ThreadSanitizer. One may use the
-function attribute `no_sanitize_thread` to disable instrumentation of plain
+function attribute ``no_sanitize("thread")`` to disable instrumentation of plain
(non-atomic) loads/stores in a particular function. ThreadSanitizer still
instruments such functions to avoid false positives and provide meaningful stack
traces. This attribute may not be supported by other compilers, so we suggest
@@ -99,9 +99,9 @@ Blacklist
ThreadSanitizer supports ``src`` and ``fun`` entity types in
:doc:`SanitizerSpecialCaseList`, that can be used to suppress data race reports
in the specified source files or functions. Unlike functions marked with
-`no_sanitize_thread` attribute, blacklisted functions are not instrumented at
-all. This can lead to false positives due to missed synchronization via atomic
-operations and missed stack frames in reports.
+``no_sanitize("thread")`` attribute, blacklisted functions are not instrumented
+at all. This can lead to false positives due to missed synchronization via
+atomic operations and missed stack frames in reports.
Limitations
-----------
diff --git a/docs/Toolchain.rst b/docs/Toolchain.rst
new file mode 100644
index 000000000000..6ae8888c6936
--- /dev/null
+++ b/docs/Toolchain.rst
@@ -0,0 +1,354 @@
+===============================
+Assembling a Complete Toolchain
+===============================
+
+.. contents::
+ :local:
+ :depth: 2
+
+Introduction
+============
+
+Clang is only one component in a complete tool chain for C family
+programming languages. In order to assemble a complete toolchain,
+additional tools and runtime libraries are required. Clang is designed
+to interoperate with existing tools and libraries for its target
+platforms, and the LLVM project provides alternatives for a number
+of these components.
+
+This document describes the required and optional components in a
+complete toolchain, where to find them, and the supported versions
+and limitations of each option.
+
+.. warning::
+
+ This document currently describes Clang configurations on POSIX-like
+ operating systems with the GCC-compatible ``clang`` driver. When
+ targeting Windows with the MSVC-compatible ``clang-cl`` driver, some
+ of the details are different.
+
+Tools
+=====
+
+.. FIXME: Describe DWARF-related tools
+
+A complete compilation of C family programming languages typically
+involves the following pipeline of tools, some of which are omitted
+in some compilations:
+
+* **Preprocessor**: This performs the actions of the C preprocessor:
+ expanding #includes and #defines.
+ The ``-E`` flag instructs Clang to stop after this step.
+
+* **Parsing**: This parses and semantically analyzes the source language and
+ builds a source-level intermediate representation ("AST"), producing a
+ :ref:`precompiled header (PCH) <usersmanual-precompiled-headers>`,
+ preamble, or
+ :doc:`precompiled module file (PCM) <Modules>`,
+ depending on the input.
+ The ``-precompile`` flag instructs Clang to stop after this step. This is
+ the default when the input is a header file.
+
+* **IR generation**: This converts the source-level intermediate representation
+ into an optimizer-specific intermediate representation (IR); for Clang, this
+ is LLVM IR.
+ The ``-emit-llvm`` flag instructs Clang to stop after this step. If combined
+ with ``-S``, Clang will produce textual LLVM IR; otherwise, it will produce
+ LLVM IR bitcode.
+
+* **Compiler backend**: This converts the intermediate representation
+ into target-specific assembly code.
+ The ``-S`` flag instructs Clang to stop after this step.
+
+* **Assembler**: This converts target-specific assembly code into
+ target-specific machine code object files.
+ The ``-c`` flag instructs Clang to stop after this step.
+
+* **Linker**: This combines multiple object files into a single image
+ (either a shared object or an executable).
+
+Clang provides all of these pieces other than the linker. When multiple
+steps are performed by the same tool, it is common for the steps to be
+fused together to avoid creating intermediate files.
+
+When given an output of one of the above steps as an input, earlier steps
+are skipped (for instance, a ``.s`` file input will be assembled and linked).
+
+The Clang driver can be invoked with the ``-###`` flag (this argument will need
+to be escaped under most shells) to see which commands it would run for the
+above steps, without running them. The ``-v`` (verbose) flag will print the
+commands in addition to running them.
+
+Clang frontend
+--------------
+
+The Clang frontend (``clang -cc1``) is used to compile C family languages. The
+command-line interface of the frontend is considered to be an implementation
+detail, intentionally has no external documentation, and is subject to change
+without notice.
+
+Language frontends for other languages
+--------------------------------------
+
+Clang can be provided with inputs written in non-C-family languages. In such
+cases, an external tool will be used to compile the input. The
+currently-supported languages are:
+
+* Ada (``-x ada``, ``.ad[bs]``)
+* Fortran (``-x f95``, ``.f``, ``.f9[05]``, ``.for``, ``.fpp``, case-insensitive)
+* Java (``-x java``)
+
+In each case, GCC will be invoked to compile the input.
+
+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
+supported. If you wish to use the system assember instead, use the
+``-fno-integrated-as`` option.
+
+Linker
+------
+
+Clang can be configured to use one of several different linkers:
+
+* GNU ld
+* GNU gold
+* LLVM's `lld <http://lld.llvm.org>`_
+* MSVC's link.exe
+
+Link-time optimization is natively supported by lld, and supported via
+a `linker plugin <http://llvm.org/docs/GoldPlugin.html>`_ when using gold.
+
+The default linker varies between targets, and can be overridden via the
+``-fuse-ld=<linker name>`` flag.
+
+Runtime libraries
+=================
+
+A number of different runtime libraries are required to provide different
+layers of support for C family programs. Clang will implicitly link an
+appropriate implementation of each runtime library, selected based on
+target defaults or explicitly selected by the ``--rtlib=`` and ``--stdlib=``
+flags.
+
+The set of implicitly-linked libraries depend on the language mode. As a
+consequence, you should use ``clang++`` when linking C++ programs in order
+to ensure the C++ runtimes are provided.
+
+.. note::
+
+ There may exist other implementations for these components not described
+ below. Please let us know how well those other implementations work with
+ Clang so they can be added to this list!
+
+.. FIXME: Describe Objective-C runtime libraries
+.. FIXME: Describe profiling runtime library
+.. FIXME: Describe cuda/openmp/opencl/... runtime libraries
+
+Compiler runtime
+----------------
+
+The compiler runtime library provides definitions of functions implicitly
+invoked by the compiler to support operations not natively supported by
+the underlying hardware (for instance, 128-bit integer multiplications),
+and where inline expansion of the operation is deemed unsuitable.
+
+The default runtime library is target-specific. For targets where GCC is
+the dominant compiler, Clang currently defaults to using libgcc_s. On most
+other targets, compiler-rt is used by default.
+
+compiler-rt (LLVM)
+^^^^^^^^^^^^^^^^^^
+
+`LLVM's compiler runtime library <http://compiler-rt.llvm.org/>`_ provides a
+complete set of runtime library functions containing all functions that
+Clang will implicitly call, in ``libclang_rt.builtins.<arch>.a``.
+
+You can instruct Clang to use compiler-rt with the ``--rtlib=compiler-rt`` flag.
+This is not supported on every platform.
+
+If using libc++ and/or libc++abi, you may need to configure them to use
+compiler-rt rather than libgcc_s by passing ``-DLIBCXX_USE_COMPILER_RT=YES``
+and/or ``-DLIBCXXABI_USE_COMPILER_RT=YES`` to ``cmake``. Otherwise, you
+may end up with both runtime libraries linked into your program (this is
+typically harmless, but wasteful).
+
+libgcc_s (GNU)
+^^^^^^^^^^^^^^
+
+`GCC's runtime library <https://gcc.gnu.org/onlinedocs/gccint/Libgcc.html>`_
+can be used in place of compiler-rt. However, it lacks several functions
+that LLVM may emit references to, particularly when using Clang's
+``__builtin_*_overflow`` family of intrinsics.
+
+You can instruct Clang to use libgcc_s with the ``--rtlib=libgcc`` flag.
+This is not supported on every platform.
+
+Atomics library
+---------------
+
+If your program makes use of atomic operations and the compiler is not able
+to lower them all directly to machine instructions (because there either is
+no known suitable machine instruction or the operand is not known to be
+suitably aligned), a call to a runtime library ``__atomic_*`` function
+will be generated. A runtime library containing these atomics functions is
+necessary for such programs.
+
+compiler-rt (LLVM)
+^^^^^^^^^^^^^^^^^^
+
+compiler-rt contains an implementation of an atomics library.
+
+libatomic (GNU)
+^^^^^^^^^^^^^^^
+
+libgcc_s does not provide an implementation of an atomics library. Instead,
+`GCC's libatomic library <https://gcc.gnu.org/wiki/Atomic/GCCMM>`_ can be
+used to supply these when using libgcc_s.
+
+.. note::
+
+ Clang does not currently automatically link against libatomic when using
+ libgcc_s. You may need to manually add ``-latomic`` to support this
+ configuration when using non-native atomic operations (if you see link errors
+ referring to ``__atomic_*`` functions).
+
+Unwind library
+--------------
+
+The unwind library provides a family of ``_Unwind_*`` functions implementing
+the language-neutral stack unwinding portion of the Itanium C++ ABI
+(`Level I <http://mentorembedded.github.io/cxx-abi/abi-eh.html#base-abi>`_).
+It is a dependency of the C++ ABI library, and sometimes is a dependency
+of other runtimes.
+
+libunwind (LLVM)
+^^^^^^^^^^^^^^^^
+
+LLVM's unwinder library can be obtained from subversion:
+
+.. code-block:: console
+
+ llvm-src$ svn co http://llvm.org/svn/llvm-project/libunwind/trunk projects/libunwind
+
+When checked out into projects/libunwind within an LLVM checkout,
+it should be automatically picked up by the LLVM build system.
+
+If using libc++abi, you may need to configure it to use libunwind
+rather than libgcc_s by passing ``-DLIBCXXABI_USE_LLVM_UNWINDER=YES``
+to ``cmake``. If libc++abi is configured to use some version of
+libunwind, that library will be implicitly linked into binaries that
+link to libc++abi.
+
+libgcc_s (GNU)
+^^^^^^^^^^^^^^
+
+libgcc_s has an integrated unwinder, and does not need an external unwind
+library to be provided.
+
+libunwind (nongnu.org)
+^^^^^^^^^^^^^^^^^^^^^^
+
+This is another implementation of the libunwind specification.
+See `libunwind (nongnu.org) <http://www.nongnu.org/libunwind>`_.
+
+libunwind (PathScale)
+^^^^^^^^^^^^^^^^^^^^^
+
+This is another implementation of the libunwind specification.
+See `libunwind (pathscale) <https://github.com/pathscale/libunwind>`_.
+
+Sanitizer runtime
+-----------------
+
+The instrumentation added by Clang's sanitizers (``-fsanitize=...``) implicitly
+makes calls to a runtime library, in order to maintain side state about the
+execution of the program and to issue diagnostic messages when a problem is
+detected.
+
+The only supported implementation of these runtimes is provided by LLVM's
+compiler-rt, and the relevant portion of that library
+(``libclang_rt.<sanitizer>.<arch>.a``)
+will be implicitly linked when linking with a ``-fsanitize=...`` flag.
+
+C standard library
+------------------
+
+Clang supports a wide variety of
+`C standard library <http://en.cppreference.com/w/c>`_
+implementations.
+
+C++ ABI library
+---------------
+
+The C++ ABI library provides an implementation of the library portion of
+the Itanium C++ ABI, covering both the
+`support functionality in the main Itanium C++ ABI document
+<http://mentorembedded.github.io/cxx-abi/abi.html>`_ and
+`Level II of the exception handling support
+<http://mentorembedded.github.io/cxx-abi/abi-eh.html#cxx-abi>`_.
+References to the functions and objects in this library are implicitly
+generated by Clang when compiling C++ code.
+
+While it is possible to link C++ code using libstdc++ and code using libc++
+together into the same program (so long as you do not attempt to pass C++
+standard library objects across the boundary), it is not generally possible
+to have more than one C++ ABI library in a program.
+
+The version of the C++ ABI library used by Clang will be the one that the
+chosen C++ standard library was linked against. Several implementations are
+available:
+
+libc++abi (LLVM)
+^^^^^^^^^^^^^^^^
+
+`libc++abi <http://libcxxabi.llvm.org/>`_ is LLVM's implementation of this
+specification.
+
+libsupc++ (GNU)
+^^^^^^^^^^^^^^^
+
+libsupc++ is GCC's implementation of this specification. However, this
+library is only used when libstdc++ is linked statically. The dynamic
+library version of libstdc++ contains a copy of libsupc++.
+
+.. note::
+
+ Clang does not currently automatically link against libatomic when statically
+ linking libstdc++. You may need to manually add ``-lsupc++`` to support this
+ configuration when using ``-static`` or ``-static-libstdc++``.
+
+libcxxrt (PathScale)
+^^^^^^^^^^^^^^^^^^^^
+
+This is another implementation of the Itanium C++ ABI specification.
+See `libcxxrt <https://github.com/pathscale/libcxxrt>`_.
+
+C++ standard library
+--------------------
+
+Clang supports use of either LLVM's libc++ or GCC's libstdc++ implementation
+of the `C++ standard library <http://en.cppreference.com/w/cpp>`_.
+
+libc++ (LLVM)
+^^^^^^^^^^^^^
+
+`libc++ <http://libcxx.llvm.org/>`_ is LLVM's implementation of the C++
+standard library, aimed at being a complete implementation of the C++
+standards from C++11 onwards.
+
+You can instruct Clang to use libc++ with the ``-stdlib=libc++`` flag.
+
+libstdc++ (GNU)
+^^^^^^^^^^^^^^^
+
+`libstdc++ <https://gcc.gnu.org/onlinedocs/libstdc++/>`_ is GCC's implementation
+of the C++ standard library. Clang supports a wide range of versions of
+libstdc++, from around version 4.2 onwards, and will implicitly work around
+some bugs in older versions of libstdc++.
+
+You can instruct Clang to use libstdc++ with the ``-stdlib=libstdc++`` flag.
diff --git a/docs/UndefinedBehaviorSanitizer.rst b/docs/UndefinedBehaviorSanitizer.rst
index 7babb96a65a1..09ee78f5876d 100644
--- a/docs/UndefinedBehaviorSanitizer.rst
+++ b/docs/UndefinedBehaviorSanitizer.rst
@@ -66,8 +66,8 @@ pointer.
.. _ubsan-checks:
-Availablle checks
-=================
+Available checks
+================
Available checks are:
diff --git a/docs/UsersManual.rst b/docs/UsersManual.rst
index 2ebcbdf60317..96b7ac95cb5d 100644
--- a/docs/UsersManual.rst
+++ b/docs/UsersManual.rst
@@ -2,6 +2,8 @@
Clang Compiler User's Manual
============================
+.. include:: <isonum.txt>
+
.. contents::
:local:
@@ -23,6 +25,10 @@ processes code, please see :doc:`InternalsManual`. If you are interested in the
`Clang Static Analyzer <http://clang-analyzer.llvm.org>`_, please see its web
page.
+Clang is one component in a complete toolchain for C family languages.
+A separate document describes the other pieces necessary to
+:doc:`assemble a complete toolchain <Toolchain>`.
+
Clang is designed to support the C family of programming languages,
which includes :ref:`C <c>`, :ref:`Objective-C <objc>`, :ref:`C++ <cxx>`, and
:ref:`Objective-C++ <objcxx>` as well as many dialects of those. For
@@ -105,6 +111,8 @@ Options to Control Error and Warning Messages
.. option:: -Wfoo
Enable warning "foo".
+ See the :doc:`diagnostics reference <DiagnosticsReference>` for a complete
+ list of the warning flags that can be specified in this way.
.. option:: -Wno-foo
@@ -313,6 +321,28 @@ output format of the diagnostics that it generates.
by category, so it should be a high level category. We want dozens
of these, not hundreds or thousands of them.
+.. _opt_fdiagnostics-show-hotness:
+
+**-f[no-]diagnostics-show-hotness**
+ Enable profile hotness information in diagnostic line.
+
+ This option, which defaults to off, controls whether Clang prints the
+ profile hotness associated with a diagnostics in the presence of
+ profile-guided optimization information. This is currently supported with
+ optimization remarks (see :ref:`Options to Emit Optimization Reports
+ <rpass>`). The hotness information allows users to focus on the hot
+ optimization remarks that are likely to be more relevant for run-time
+ performance.
+
+ For example, in this output, the block containing the callsite of `foo` was
+ executed 3000 times according to the profile data:
+
+ ::
+
+ s.c:7:10: remark: foo inlined into bar (hotness: 3000) [-Rpass-analysis=inline]
+ sum += foo(x, x - 2);
+ ^
+
.. _opt_fdiagnostics-fixit-info:
**-f[no-]diagnostics-fixit-info**
@@ -531,6 +561,8 @@ control the crash diagnostics.
The -fno-crash-diagnostics flag can be helpful for speeding the process
of generating a delta reduced test case.
+.. _rpass:
+
Options to Emit Optimization Reports
------------------------------------
@@ -574,6 +606,10 @@ outside of the major transformations (e.g., inlining, vectorization,
loop optimizations) and not every optimization pass supports this
feature.
+Note that when using profile-guided optimization information, profile hotness
+information can be included in the remarks (see
+:ref:`-fdiagnostics-show-hotness <opt_fdiagnostics-show-hotness>`).
+
Current limitations
^^^^^^^^^^^^^^^^^^^
@@ -1073,6 +1109,15 @@ are listed below.
``Inf``, and
* ``+0`` and ``-0`` are interchangeable.
+.. option:: -fdenormal-fp-math=[values]
+
+ Select which denormal numbers the code is permitted to require.
+
+ Valid values are: ``ieee``, ``preserve-sign``, and ``positive-zero``,
+ which correspond to IEEE 754 denormal numbers, the sign of a
+ flushed-to-zero number is preserved in the sign of 0, denormals are
+ flushed to positive zero, respectively.
+
.. option:: -fwhole-program-vtables
Enable whole-program vtable optimizations, such as single-implementation
@@ -1470,8 +1515,13 @@ instrumentation:
2. Run the instrumented executable with inputs that reflect the typical usage.
By default, the profile data will be written to a ``default.profraw`` file
- in the current directory. You can override that default by setting the
- ``LLVM_PROFILE_FILE`` environment variable to specify an alternate file.
+ in the current directory. You can override that default by using option
+ ``-fprofile-instr-generate=`` or by setting the ``LLVM_PROFILE_FILE``
+ environment variable to specify an alternate file. If non-default file name
+ is specified by both the environment variable and the command line option,
+ the environment variable takes precedence. The file name pattern specified
+ can include different modifiers: ``%p``, ``%h``, and ``%m``.
+
Any instance of ``%p`` in that file name will be replaced by the process
ID, so that you can easily distinguish the profile output from multiple
runs.
@@ -1480,6 +1530,33 @@ instrumentation:
$ LLVM_PROFILE_FILE="code-%p.profraw" ./code
+ The modifier ``%h`` can be used in scenarios where the same instrumented
+ binary is run in multiple different host machines dumping profile data
+ to a shared network based storage. The ``%h`` specifier will be substituted
+ with the hostname so that profiles collected from different hosts do not
+ clobber each other.
+
+ While the use of ``%p`` specifier can reduce the likelihood for the profiles
+ dumped from different processes to clobber each other, such clobbering can still
+ happen because of the ``pid`` re-use by the OS. Another side-effect of using
+ ``%p`` is that the storage requirement for raw profile data files is greatly
+ increased. To avoid issues like this, the ``%m`` specifier can used in the profile
+ name. When this specifier is used, the profiler runtime will substitute ``%m``
+ with a unique integer identifier associated with the instrumented binary. Additionally,
+ multiple raw profiles dumped from different processes that share a file system (can be
+ on different hosts) will be automatically merged by the profiler runtime during the
+ dumping. If the program links in multiple instrumented shared libraries, each library
+ will dump the profile data into its own profile data file (with its unique integer
+ id embedded in the profile name). Note that the merging enabled by ``%m`` is for raw
+ profile data generated by profiler runtime. The resulting merged "raw" profile data
+ file still needs to be converted to a different format expected by the compiler (
+ see step 3 below).
+
+ .. code-block:: console
+
+ $ LLVM_PROFILE_FILE="code-%m.profraw" ./code
+
+
3. Combine profiles from multiple runs and convert the "raw" profile format to
the input expected by clang. Use the ``merge`` command of the
``llvm-profdata`` tool to do this.
@@ -1514,27 +1591,31 @@ profile creation and use.
The ``-fprofile-generate`` and ``-fprofile-generate=`` flags will use
an alterantive instrumentation method for profile generation. When
given a directory name, it generates the profile file
- ``default.profraw`` in the directory named ``dirname``. If ``dirname``
- does not exist, it will be created at runtime. The environment variable
- ``LLVM_PROFILE_FILE`` can be used to override the directory and
- filename for the profile file at runtime. For example,
+ ``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,
+ 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,
.. code-block:: console
$ clang++ -O2 -fprofile-generate=yyy/zzz code.cc -o code
When ``code`` is executed, the profile will be written to the file
- ``yyy/zzz/default.profraw``. This can be altered at runtime via the
- ``LLVM_PROFILE_FILE`` environment variable:
+ ``yyy/zzz/default_xxxx.profraw``.
- .. code-block:: console
+ To generate the profile data file with the compiler readable format, the
+ ``llvm-profdata`` tool can be used with the profile directory as the input:
+
+ .. code-block:: console
- $ LLVM_PROFILE_FILE=/tmp/myprofile/code.profraw ./code
+ $ llvm-profdata merge -output=code.profdata yyy/zzz/
- The above invocation will produce the profile file
- ``/tmp/myprofile/code.profraw`` instead of ``yyy/zzz/default.profraw``.
- Notice that ``LLVM_PROFILE_FILE`` overrides the directory *and* the file
- name for the profile file.
+ If the user wants to turn off the auto-merging feature, or simply override the
+ the profile dumping path specified at command line, the environment variable
+ ``LLVM_PROFILE_FILE`` can still be used to override
+ the directory and filename for the profile file at runtime.
.. option:: -fprofile-use[=<pathname>]
@@ -1614,7 +1695,7 @@ features. You can "tune" the debug info for one of several different debuggers.
.. option:: -ggdb, -glldb, -gsce
- Tune the debug info for the ``gdb``, ``lldb``, or Sony Computer Entertainment
+ Tune the debug info for the ``gdb``, ``lldb``, or Sony PlayStation\ |reg|
debugger, respectively. Each of these options implies **-g**. (Therefore, if
you want both **-gline-tables-only** and debugger tuning, the tuning option
must come first.)
@@ -1749,6 +1830,10 @@ extensions are not implemented yet:
...
local_function(1);
+- clang only supports global register variables when the register specified
+ is non-allocatable (e.g. the stack pointer). Support for general global
+ register variables is unlikely to be implemented soon because it requires
+ additional LLVM backend support.
- clang does not support static initialization of flexible array
members. This appears to be a rarely used extension, but could be
implemented pending user demand.
diff --git a/docs/analyzer/DebugChecks.rst b/docs/analyzer/DebugChecks.rst
index bfa3142efbdf..ecf11ca0f133 100644
--- a/docs/analyzer/DebugChecks.rst
+++ b/docs/analyzer/DebugChecks.rst
@@ -138,6 +138,17 @@ ExprInspection checks
clang_analyzer_warnIfReached(); // no-warning
}
+- void clang_analyzer_numTimesReached();
+
+ Same as above, but include the number of times this call expression
+ gets reached by the analyzer during the current analysis.
+
+ Example usage::
+
+ for (int x = 0; x < 3; ++x) {
+ clang_analyzer_numTimesReached(); // expected-warning{{3}}
+ }
+
- void clang_analyzer_warnOnDeadSymbol(int);
Subscribe for a delayed warning when the symbol that represents the value of
@@ -180,6 +191,18 @@ ExprInspection checks
clang_analyzer_explain(ptr); // expected-warning{{memory address '0'}}
}
+- void clang_analyzer_dump(a single argument of any type);
+
+ Similar to clang_analyzer_explain, but produces a raw dump of the value,
+ same as SVal::dump().
+
+ Example usage::
+
+ void clang_analyzer_dump(int);
+ void foo(int x) {
+ clang_analyzer_dump(x); // expected-warning{{reg_$0<x>}}
+ }
+
- size_t clang_analyzer_getExtent(void *);
This function returns the value that represents the extent of a memory region
@@ -197,6 +220,22 @@ ExprInspection checks
clang_analyzer_explain(ys); // expected-warning{{'8'}}
}
+- void clang_analyzer_printState();
+
+ Dumps the current ProgramState to the stderr. Quickly lookup the program state
+ at any execution point without ViewExplodedGraph or re-compiling the program.
+ This is not very useful for writing tests (apart from testing how ProgramState
+ gets printed), but useful for debugging tests. Also, this method doesn't
+ produce a warning, so it gets printed on the console before all other
+ ExprInspection warnings.
+
+ Example usage::
+
+ void foo() {
+ int x = 1;
+ clang_analyzer_printState(); // Read the stderr!
+ }
+
Statistics
==========
diff --git a/docs/analyzer/IPA.txt b/docs/analyzer/IPA.txt
index 14da71e09030..3842075fcd6a 100644
--- a/docs/analyzer/IPA.txt
+++ b/docs/analyzer/IPA.txt
@@ -303,7 +303,7 @@ Currently, there are 2 modes:
DynamicDispatchModeConservative - Models the case where the dynamic type
information is assumed to be incorrect, for example, implies that the method
- definition is overriden in a subclass. In such cases, ExprEngine does not
+ definition is overridden in a subclass. In such cases, ExprEngine does not
inline the methods sent to the receiver (MemoryRegion), even if a candidate
definition is available. This mode is conservative about simulating the
effects of a call.
diff --git a/docs/analyzer/conf.py b/docs/analyzer/conf.py
index afbfbee6f379..6b54b0646eca 100644
--- a/docs/analyzer/conf.py
+++ b/docs/analyzer/conf.py
@@ -49,9 +49,9 @@ copyright = u'2013-%d, Analyzer Team' % date.today().year
# built documents.
#
# The short X.Y version.
-version = '3.9'
+version = '4.0'
# The full version, including alpha/beta/rc tags.
-release = '3.9'
+release = '4.0'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
diff --git a/docs/conf.py b/docs/conf.py
index 1e8894ac8fe7..4683ca567ec6 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 X.Y version.
-version = '3.9'
+version = '4.0'
# The full version, including alpha/beta/rc tags.
-release = '3.9'
+release = '4.0'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
diff --git a/docs/index.rst b/docs/index.rst
index 296054766d68..61f9c2c49426 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -17,8 +17,10 @@ Using Clang as a Compiler
:maxdepth: 1
UsersManual
+ Toolchain
LanguageExtensions
AttributeReference
+ DiagnosticsReference
CrossCompilation
ThreadSafetyAnalysis
AddressSanitizer
@@ -36,6 +38,7 @@ Using Clang as a Compiler
SourceBasedCodeCoverage
Modules
MSVCCompatibility
+ ThinLTO
CommandGuide/index
FAQ
diff --git a/examples/AnnotateFunctions/CMakeLists.txt b/examples/AnnotateFunctions/CMakeLists.txt
index cf564d527d6a..5684abf2380d 100644
--- a/examples/AnnotateFunctions/CMakeLists.txt
+++ b/examples/AnnotateFunctions/CMakeLists.txt
@@ -1,4 +1,4 @@
-add_llvm_loadable_module(AnnotateFunctions AnnotateFunctions.cpp)
+add_llvm_loadable_module(AnnotateFunctions AnnotateFunctions.cpp PLUGIN_TOOL clang)
if(LLVM_ENABLE_PLUGINS AND (WIN32 OR CYGWIN))
target_link_libraries(AnnotateFunctions PRIVATE
diff --git a/examples/PrintFunctionNames/CMakeLists.txt b/examples/PrintFunctionNames/CMakeLists.txt
index 5a00d5036fb1..f5f818866ca6 100644
--- a/examples/PrintFunctionNames/CMakeLists.txt
+++ b/examples/PrintFunctionNames/CMakeLists.txt
@@ -9,7 +9,7 @@ if( NOT MSVC ) # MSVC mangles symbols differently, and
endif()
endif()
-add_llvm_loadable_module(PrintFunctionNames PrintFunctionNames.cpp)
+add_llvm_loadable_module(PrintFunctionNames PrintFunctionNames.cpp PLUGIN_TOOL clang)
if(LLVM_ENABLE_PLUGINS AND (WIN32 OR CYGWIN))
target_link_libraries(PrintFunctionNames PRIVATE
diff --git a/examples/PrintFunctionNames/PrintFunctionNames.cpp b/examples/PrintFunctionNames/PrintFunctionNames.cpp
index 9f8f6e3f050a..9f6d495caec7 100644
--- a/examples/PrintFunctionNames/PrintFunctionNames.cpp
+++ b/examples/PrintFunctionNames/PrintFunctionNames.cpp
@@ -69,8 +69,9 @@ public:
v.TraverseDecl(context.getTranslationUnitDecl());
clang::Sema &sema = Instance.getSema();
for (const FunctionDecl *FD : v.LateParsedDecls) {
- clang::LateParsedTemplate* LPT = sema.LateParsedTemplateMap.lookup(FD);
- sema.LateTemplateParser(sema.OpaqueParser, *LPT);
+ clang::LateParsedTemplate &LPT =
+ *sema.LateParsedTemplateMap.find(FD)->second;
+ sema.LateTemplateParser(sema.OpaqueParser, LPT);
llvm::errs() << "late-parsed-decl: \"" << FD->getNameAsString() << "\"\n";
}
}
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h
index 13db2085ba69..47998859f674 100644
--- a/include/clang-c/Index.h
+++ b/include/clang-c/Index.h
@@ -32,7 +32,7 @@
* compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable.
*/
#define CINDEX_VERSION_MAJOR 0
-#define CINDEX_VERSION_MINOR 35
+#define CINDEX_VERSION_MINOR 37
#define CINDEX_VERSION_ENCODE(major, minor) ( \
((major) * 10000) \
@@ -326,7 +326,7 @@ clang_isFileMultipleIncludeGuarded(CXTranslationUnit tu, CXFile file);
*
* \param tu the translation unit
*
-* \param file_name the name of the file.
+ * \param file_name the name of the file.
*
* \returns the file handle for the named file in the translation unit \p tu,
* or a NULL file handle if the file was not a part of this translation unit.
@@ -627,6 +627,15 @@ CINDEX_LINKAGE CXSourceRangeList *clang_getSkippedRanges(CXTranslationUnit tu,
CXFile file);
/**
+ * \brief Retrieve all ranges from all files that were skipped by the
+ * preprocessor.
+ *
+ * The preprocessor will skip lines when they are surrounded by an
+ * if/ifdef/ifndef directive whose condition does not evaluate to true.
+ */
+CINDEX_LINKAGE CXSourceRangeList *clang_getAllSkippedRanges(CXTranslationUnit tu);
+
+/**
* \brief Destroy the given \c CXSourceRangeList.
*/
CINDEX_LINKAGE void clang_disposeSourceRangeList(CXSourceRangeList *ranges);
@@ -2325,7 +2334,39 @@ enum CXCursorKind {
*/
CXCursor_OMPTargetParallelForSimdDirective = 269,
- CXCursor_LastStmt = CXCursor_OMPTargetParallelForSimdDirective,
+ /** \brief OpenMP target simd directive.
+ */
+ CXCursor_OMPTargetSimdDirective = 270,
+
+ /** \brief OpenMP teams distribute directive.
+ */
+ CXCursor_OMPTeamsDistributeDirective = 271,
+
+ /** \brief OpenMP teams distribute simd directive.
+ */
+ CXCursor_OMPTeamsDistributeSimdDirective = 272,
+
+ /** \brief OpenMP teams distribute parallel for simd directive.
+ */
+ CXCursor_OMPTeamsDistributeParallelForSimdDirective = 273,
+
+ /** \brief OpenMP teams distribute parallel for directive.
+ */
+ CXCursor_OMPTeamsDistributeParallelForDirective = 274,
+
+ /** \brief OpenMP target teams directive.
+ */
+ CXCursor_OMPTargetTeamsDirective = 275,
+
+ /** \brief OpenMP target teams distribute directive.
+ */
+ CXCursor_OMPTargetTeamsDistributeDirective = 276,
+
+ /** \brief OpenMP target teams distribute parallel for directive.
+ */
+ CXCursor_OMPTargetTeamsDistributeParallelForDirective = 277,
+
+ CXCursor_LastStmt = CXCursor_OMPTargetTeamsDistributeParallelForDirective,
/**
* \brief Cursor that represents the translation unit itself.
@@ -2383,8 +2424,12 @@ enum CXCursorKind {
* \brief A static_assert or _Static_assert node
*/
CXCursor_StaticAssert = 602,
+ /**
+ * \brief a friend declaration.
+ */
+ CXCursor_FriendDecl = 603,
CXCursor_FirstExtraDecl = CXCursor_ModuleImportDecl,
- CXCursor_LastExtraDecl = CXCursor_StaticAssert,
+ CXCursor_LastExtraDecl = CXCursor_FriendDecl,
/**
* \brief A code completion overload candidate.
@@ -3001,7 +3046,7 @@ enum CXCallingConv {
CXCallingConv_X86Pascal = 5,
CXCallingConv_AAPCS = 6,
CXCallingConv_AAPCS_VFP = 7,
- /* Value 8 was PnaclCall, but it was never used, so it could safely be re-used. */
+ CXCallingConv_X86RegCall = 8,
CXCallingConv_IntelOclBicc = 9,
CXCallingConv_X86_64Win64 = 10,
CXCallingConv_X86_64SysV = 11,
@@ -3491,11 +3536,8 @@ enum CXRefQualifierKind {
};
/**
- * \brief Returns the number of template arguments for given class template
- * specialization, or -1 if type \c T is not a class template specialization.
- *
- * Variadic argument packs count as only one argument, and can not be inspected
- * further.
+ * \brief 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);
@@ -5240,6 +5282,25 @@ CINDEX_LINKAGE CXEvalResultKind clang_EvalResult_getKind(CXEvalResult E);
CINDEX_LINKAGE int clang_EvalResult_getAsInt(CXEvalResult E);
/**
+ * \brief 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
+ * result resulted in an unsigned integer.
+ */
+CINDEX_LINKAGE unsigned clang_EvalResult_isUnsignedInt(CXEvalResult E);
+
+/**
+ * \brief 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
* kind is double.
*/
diff --git a/include/clang/AST/APValue.h b/include/clang/AST/APValue.h
index e58c21923f51..7c431f3be8c4 100644
--- a/include/clang/AST/APValue.h
+++ b/include/clang/AST/APValue.h
@@ -135,14 +135,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, unsigned CallIndex,
+ bool IsNullPtr = false)
: Kind(Uninitialized) {
- MakeLValue(); setLValue(B, O, N, CallIndex);
+ MakeLValue(); setLValue(B, O, N, CallIndex, IsNullPtr);
}
APValue(LValueBase B, const CharUnits &O, ArrayRef<LValuePathEntry> Path,
- bool OnePastTheEnd, unsigned CallIndex)
+ bool OnePastTheEnd, unsigned CallIndex, bool IsNullPtr = false)
: Kind(Uninitialized) {
- MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, CallIndex);
+ MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, CallIndex, IsNullPtr);
}
APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(Uninitialized) {
MakeArray(InitElts, Size);
@@ -254,6 +255,7 @@ public:
bool hasLValuePath() const;
ArrayRef<LValuePathEntry> getLValuePath() const;
unsigned getLValueCallIndex() const;
+ bool isNullPointer() const;
APValue &getVectorElt(unsigned I) {
assert(isVector() && "Invalid accessor");
@@ -374,10 +376,10 @@ public:
((ComplexAPFloat *)(char *)Data.buffer)->Imag = std::move(I);
}
void setLValue(LValueBase B, const CharUnits &O, NoLValuePath,
- unsigned CallIndex);
+ unsigned CallIndex, bool IsNullPtr);
void setLValue(LValueBase B, const CharUnits &O,
ArrayRef<LValuePathEntry> Path, bool OnePastTheEnd,
- unsigned CallIndex);
+ unsigned CallIndex, bool IsNullPtr);
void setUnion(const FieldDecl *Field, const APValue &Value) {
assert(isUnion() && "Invalid accessor");
((UnionData*)(char*)Data.buffer)->Field = Field;
diff --git a/include/clang/AST/ASTConsumer.h b/include/clang/AST/ASTConsumer.h
index 0b1f0068fa6f..ad368c86c79c 100644
--- a/include/clang/AST/ASTConsumer.h
+++ b/include/clang/AST/ASTConsumer.h
@@ -14,8 +14,6 @@
#ifndef LLVM_CLANG_AST_ASTCONSUMER_H
#define LLVM_CLANG_AST_ASTCONSUMER_H
-#include "llvm/ADT/StringRef.h"
-
namespace clang {
class ASTContext;
class CXXMethodDecl;
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index 1d223f47a9ae..1c9ce821438d 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -19,73 +19,107 @@
#include "clang/AST/CanonicalType.h"
#include "clang/AST/CommentCommandTraits.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/DeclarationName.h"
+#include "clang/AST/DeclBase.h"
#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/RawCommentList.h"
+#include "clang/AST/TemplateBase.h"
#include "clang/AST/TemplateName.h"
#include "clang/AST/Type.h"
#include "clang/Basic/AddressSpaces.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/Linkage.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Basic/Module.h"
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/SanitizerBlacklist.h"
-#include "clang/Basic/VersionTuple.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/Specifiers.h"
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/iterator_range.h"
#include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/TinyPtrVector.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/AlignOf.h"
#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Compiler.h"
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <iterator>
#include <memory>
+#include <new>
+#include <string>
+#include <utility>
#include <vector>
namespace llvm {
- struct fltSemantics;
-}
+
+struct fltSemantics;
+
+} // end namespace llvm
namespace clang {
- class FileManager;
- class AtomicExpr;
- class ASTRecordLayout;
- class BlockExpr;
- class CharUnits;
- class DiagnosticsEngine;
- class Expr;
- class ASTMutationListener;
- class IdentifierTable;
- class MaterializeTemporaryExpr;
- class SelectorTable;
- class TargetInfo;
- class CXXABI;
- class MangleNumberingContext;
- // Decls
- class MangleContext;
- class ObjCIvarDecl;
- class ObjCPropertyDecl;
- class UnresolvedSetIterator;
- class UsingDecl;
- class UsingShadowDecl;
- class VTableContextBase;
-
- namespace Builtin { class Context; }
- enum BuiltinTemplateKind : int;
-
- namespace comments {
- class FullComment;
- }
-
- struct TypeInfo {
- uint64_t Width;
- unsigned Align;
- bool AlignIsRequired : 1;
- TypeInfo() : Width(0), Align(0), AlignIsRequired(false) {}
- TypeInfo(uint64_t Width, unsigned Align, bool AlignIsRequired)
- : Width(Width), Align(Align), AlignIsRequired(AlignIsRequired) {}
- };
+
+class ASTMutationListener;
+class ASTRecordLayout;
+class AtomicExpr;
+class BlockExpr;
+class CharUnits;
+class CXXABI;
+class DiagnosticsEngine;
+class Expr;
+class MangleNumberingContext;
+class MaterializeTemporaryExpr;
+class TargetInfo;
+// Decls
+class MangleContext;
+class ObjCIvarDecl;
+class ObjCPropertyDecl;
+class UnresolvedSetIterator;
+class UsingDecl;
+class UsingShadowDecl;
+class VTableContextBase;
+
+namespace Builtin {
+
+ class Context;
+
+} // end namespace Builtin
+
+enum BuiltinTemplateKind : int;
+
+namespace comments {
+
+ class FullComment;
+
+} // end namespace comments
+
+struct TypeInfo {
+ uint64_t Width;
+ unsigned Align;
+ bool AlignIsRequired : 1;
+
+ TypeInfo() : Width(0), Align(0), AlignIsRequired(false) {}
+ TypeInfo(uint64_t Width, unsigned Align, bool AlignIsRequired)
+ : Width(Width), Align(Align), AlignIsRequired(AlignIsRequired) {}
+};
/// \brief Holds long-lived AST nodes (such as types and decls) that can be
/// referred to throughout the semantic analysis of a file.
@@ -114,6 +148,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
mutable llvm::FoldingSet<DependentTypeOfExprType> DependentTypeOfExprTypes;
mutable llvm::FoldingSet<DependentDecltypeType> DependentDecltypeTypes;
mutable llvm::FoldingSet<TemplateTypeParmType> TemplateTypeParmTypes;
+ mutable llvm::FoldingSet<ObjCTypeParamType> ObjCTypeParamTypes;
mutable llvm::FoldingSet<SubstTemplateTypeParmType>
SubstTemplateTypeParmTypes;
mutable llvm::FoldingSet<SubstTemplateTypeParmPackType>
@@ -312,13 +347,24 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// definitions of that entity.
llvm::DenseMap<NamedDecl*, llvm::TinyPtrVector<Module*>> MergedDefModules;
+ /// \brief 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).
+ struct PerModuleInitializers {
+ llvm::SmallVector<Decl*, 4> Initializers;
+ llvm::SmallVector<uint32_t, 4> LazyInitializers;
+
+ void resolve(ASTContext &Ctx);
+ };
+ llvm::DenseMap<Module*, PerModuleInitializers*> ModuleInitializers;
+
public:
/// \brief A type synonym for the TemplateOrInstantiation mapping.
typedef llvm::PointerUnion<VarTemplateDecl *, MemberSpecializationInfo *>
TemplateOrSpecializationInfo;
private:
-
/// \brief A mapping to contain the template or declaration that
/// a variable declaration describes or was instantiated from,
/// respectively.
@@ -352,11 +398,11 @@ private:
llvm::DenseMap<const VarDecl *, TemplateOrSpecializationInfo>
TemplateOrInstantiation;
- /// \brief Keeps track of the declaration from which a UsingDecl was
+ /// \brief Keeps track of the declaration from which a using declaration was
/// created during instantiation.
///
- /// The source declaration is always a UsingDecl, an UnresolvedUsingValueDecl,
- /// or an UnresolvedUsingTypenameDecl.
+ /// The source and target declarations are always a UsingDecl, an
+ /// UnresolvedUsingValueDecl, or an UnresolvedUsingTypenameDecl.
///
/// For example:
/// \code
@@ -375,7 +421,7 @@ private:
///
/// This mapping will contain an entry that maps from the UsingDecl in
/// B<int> to the UnresolvedUsingDecl in B<T>.
- llvm::DenseMap<UsingDecl *, NamedDecl *> InstantiatedFromUsingDecl;
+ llvm::DenseMap<NamedDecl *, NamedDecl *> InstantiatedFromUsingDecl;
llvm::DenseMap<UsingShadowDecl*, UsingShadowDecl*>
InstantiatedFromUsingShadowDecl;
@@ -394,7 +440,7 @@ private:
/// \brief 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 *, MangleNumberingContext *>
+ llvm::DenseMap<const DeclContext *, std::unique_ptr<MangleNumberingContext>>
MangleNumberingContexts;
/// \brief Side-table of mangling numbers for declarations which rarely
@@ -514,6 +560,7 @@ public:
size_t size() const { return end() - begin(); }
bool empty() const { return begin() == end(); }
+
const DynTypedNode &operator[](size_t N) const {
assert(N < size() && "Out of bounds!");
return *(begin() + N);
@@ -569,7 +616,7 @@ public:
return BumpAlloc.Allocate(Size, Align);
}
template <typename T> T *Allocate(size_t Num = 1) const {
- return static_cast<T *>(Allocate(Num * sizeof(T), llvm::alignOf<T>()));
+ return static_cast<T *>(Allocate(Num * sizeof(T), alignof(T)));
}
void Deallocate(void *Ptr) const { }
@@ -802,11 +849,11 @@ public:
/// \brief If the given using decl \p Inst is an instantiation of a
/// (possibly unresolved) using decl from a template instantiation,
/// return it.
- NamedDecl *getInstantiatedFromUsingDecl(UsingDecl *Inst);
+ NamedDecl *getInstantiatedFromUsingDecl(NamedDecl *Inst);
/// \brief Remember that the using decl \p Inst is an instantiation
/// of the using decl \p Pattern of a class template.
- void setInstantiatedFromUsingDecl(UsingDecl *Inst, NamedDecl *Pattern);
+ void setInstantiatedFromUsingDecl(NamedDecl *Inst, NamedDecl *Pattern);
void setInstantiatedFromUsingShadowDecl(UsingShadowDecl *Inst,
UsingShadowDecl *Pattern);
@@ -883,6 +930,17 @@ public:
return MergedIt->second;
}
+ /// Add a declaration to the list of declarations that are initialized
+ /// for a module. This will typically be a global variable (with internal
+ /// linkage) that runs module initializers, such as the iostream initializer,
+ /// or an ImportDecl nominating another module that has initializers.
+ void addModuleInitializer(Module *M, Decl *Init);
+
+ void addLazyModuleInitializers(Module *M, ArrayRef<uint32_t> IDs);
+
+ /// Get the initializations to perform when importing a module, if any.
+ ArrayRef<Decl*> getModuleInitializers(Module *M);
+
TranslationUnitDecl *getTranslationUnitDecl() const { return TUDecl; }
ExternCContextDecl *getExternCContextDecl() const;
@@ -928,7 +986,8 @@ public:
ASTContext(LangOptions &LOpts, SourceManager &SM, IdentifierTable &idents,
SelectorTable &sels, Builtin::Context &builtins);
-
+ ASTContext(const ASTContext &) = delete;
+ ASTContext &operator=(const ASTContext &) = delete;
~ASTContext();
/// \brief Attach an external AST source to the AST context.
@@ -987,6 +1046,8 @@ private:
QualType getTypeDeclTypeSlow(const TypeDecl *Decl) const;
+ QualType getPipeType(QualType T, bool ReadOnly) const;
+
public:
/// \brief Return the uniqued reference to the type for an address space
/// qualified type with the specified type and address space.
@@ -996,6 +1057,14 @@ public:
/// replaced.
QualType getAddrSpaceQualType(QualType T, unsigned AddressSpace) const;
+ /// \brief 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.
+ 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
/// gc-qualified type.
///
@@ -1040,6 +1109,10 @@ public:
/// \brief 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
+ /// 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
/// delay-parsed, instantiated, or computed.
void adjustExceptionSpec(FunctionDecl *FD,
@@ -1088,8 +1161,10 @@ public:
/// blocks.
QualType getBlockDescriptorType() const;
- /// \brief Return pipe type for the specified type.
- QualType getPipeType(QualType T) const;
+ /// \brief Return a read_only pipe type for the specified type.
+ QualType getReadPipeType(QualType T) const;
+ /// \brief Return a write_only pipe type for the specified type.
+ QualType getWritePipeType(QualType T) const;
/// Gets the struct used to keep track of the extended descriptor for
/// pointer to blocks.
@@ -1192,8 +1267,17 @@ public:
/// \brief Return a normal function type with a typed argument list.
QualType getFunctionType(QualType ResultTy, ArrayRef<QualType> Args,
- const FunctionProtoType::ExtProtoInfo &EPI) const;
+ const FunctionProtoType::ExtProtoInfo &EPI) const {
+ return getFunctionTypeInternal(ResultTy, Args, EPI, false);
+ }
+
+private:
+ /// \brief 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
/// declaration.
QualType getTypeDeclType(const TypeDecl *Decl,
@@ -1271,6 +1355,12 @@ public:
ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS,
const IdentifierInfo *Name, ArrayRef<TemplateArgument> Args) const;
+ /// Get a template argument list with one argument per template parameter
+ /// in a template parameter list, such as for the injected class name of
+ /// a class template.
+ void getInjectedTemplateArgs(const TemplateParameterList *Params,
+ SmallVectorImpl<TemplateArgument> &Args);
+
QualType getPackExpansionType(QualType Pattern,
Optional<unsigned> NumExpansions);
@@ -1286,6 +1376,10 @@ public:
ArrayRef<QualType> typeArgs,
ArrayRef<ObjCProtocolDecl *> protocols,
bool isKindOf) const;
+
+ QualType getObjCTypeParamType(const ObjCTypeParamDecl *Decl,
+ ArrayRef<ObjCProtocolDecl *> protocols,
+ QualType Canonical = QualType()) const;
bool ObjCObjectAdoptsQTypeProtocols(QualType QT, ObjCInterfaceDecl *Decl);
/// QIdProtocolsAdoptObjCObjectProtocols - Checks that protocols in
@@ -1440,7 +1534,6 @@ public:
return getObjCSelType();
return ObjCSelRedefinitionType;
}
-
/// \brief Set the user-written type that redefines 'SEL'.
void setObjCSelRedefinitionType(QualType RedefType) {
@@ -1569,16 +1662,12 @@ public:
///
/// \returns true if an error occurred (e.g., because one of the parameter
/// types is incomplete), false otherwise.
- bool getObjCEncodingForFunctionDecl(const FunctionDecl *Decl, std::string& S);
+ std::string getObjCEncodingForFunctionDecl(const FunctionDecl *Decl) const;
/// \brief Emit the encoded type for the method declaration \p Decl into
/// \p S.
- ///
- /// \returns true if an error occurred (e.g., because one of the parameter
- /// types is incomplete), false otherwise.
- bool getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, std::string &S,
- bool Extended = false)
- const;
+ std::string getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl,
+ bool Extended = false) const;
/// \brief Return the encoded type for this block declaration.
std::string getObjCEncodingForBlock(const BlockExpr *blockExpr) const;
@@ -1587,9 +1676,8 @@ public:
/// this method declaration. If non-NULL, Container must be either
/// an ObjCCategoryImplDecl or ObjCImplementationDecl; it should
/// only be NULL when getting encodings for protocol properties.
- void getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD,
- const Decl *Container,
- std::string &S) const;
+ std::string getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD,
+ const Decl *Container) const;
bool ProtocolCompatibleWithProtocol(ObjCProtocolDecl *lProto,
ObjCProtocolDecl *rProto) const;
@@ -1834,6 +1922,11 @@ public:
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
+ /// 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
/// characters.
CharUnits getTypeAlignInChars(QualType T) const;
@@ -1860,7 +1953,7 @@ public:
/// \brief Return the default alignment for __attribute__((aligned)) on
/// this target, to be used if no alignment value is specified.
- unsigned getTargetDefaultAlignForAttributeAligned(void) const;
+ unsigned getTargetDefaultAlignForAttributeAligned() const;
/// \brief Return the alignment in bits that should be given to a
/// global variable with type \p T.
@@ -2212,6 +2305,10 @@ public:
return (*AddrSpaceMap)[AS - LangAS::Offset];
}
+ /// Get target-dependent integer value for null pointer which is used for
+ /// constant folding.
+ uint64_t getTargetNullPointerValue(QualType QT) const;
+
bool addressSpaceMapManglingFor(unsigned AS) const {
return AddrSpaceMapMangling ||
AS < LangAS::Offset ||
@@ -2223,7 +2320,6 @@ private:
unsigned getIntegerRank(const Type *T) const;
public:
-
//===--------------------------------------------------------------------===//
// Type Compatibility Predicates
//===--------------------------------------------------------------------===//
@@ -2399,12 +2495,6 @@ public:
void addCopyConstructorForExceptionObject(CXXRecordDecl *RD,
CXXConstructorDecl *CD);
- void addDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
- unsigned ParmIdx, Expr *DAE);
-
- Expr *getDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
- unsigned ParmIdx);
-
void addTypedefNameForUnnamedTagDecl(TagDecl *TD, TypedefNameDecl *TND);
TypedefNameDecl *getTypedefNameForUnnamedTagDecl(const TagDecl *TD);
@@ -2423,7 +2513,7 @@ public:
/// DeclContext.
MangleNumberingContext &getManglingNumberContext(const DeclContext *DC);
- MangleNumberingContext *createMangleNumberingContext() const;
+ std::unique_ptr<MangleNumberingContext> createMangleNumberingContext() const;
/// \brief Used by ParmVarDecl to store on the side the
/// index of the parameter when it exceeds the size of the normal bitfield.
@@ -2484,10 +2574,6 @@ public:
/// declarations were built.
static unsigned NumImplicitDestructorsDeclared;
-private:
- ASTContext(const ASTContext &) = delete;
- void operator=(const ASTContext &) = delete;
-
public:
/// \brief Initialize built-in types.
///
@@ -2567,6 +2653,7 @@ private:
friend class DeclContext;
friend class DeclarationNameTable;
+
void ReleaseDeclContextMaps();
void ReleaseParentMapEntries();
@@ -2589,7 +2676,8 @@ public:
DeclaratorDecl *Decl;
SourceLocation PragmaSectionLocation;
int SectionFlags;
- SectionInfo() {}
+
+ SectionInfo() = default;
SectionInfo(DeclaratorDecl *Decl,
SourceLocation PragmaSectionLocation,
int SectionFlags)
@@ -2711,4 +2799,4 @@ typename clang::LazyGenerationalUpdatePtr<Owner, T, Update>::ValueType
return Value;
}
-#endif
+#endif // LLVM_CLANG_AST_ASTCONTEXT_H
diff --git a/include/clang/AST/ASTImporter.h b/include/clang/AST/ASTImporter.h
index e116abaef797..66b9cd394b9d 100644
--- a/include/clang/AST/ASTImporter.h
+++ b/include/clang/AST/ASTImporter.h
@@ -24,6 +24,7 @@
namespace clang {
class ASTContext;
class CXXCtorInitializer;
+ class CXXBaseSpecifier;
class Decl;
class DeclContext;
class DiagnosticsEngine;
@@ -39,7 +40,9 @@ namespace clang {
class ASTImporter {
public:
typedef llvm::DenseSet<std::pair<Decl *, Decl *> > NonEquivalentDeclSet;
-
+ typedef llvm::DenseMap<const CXXBaseSpecifier *, CXXBaseSpecifier *>
+ ImportedCXXBaseSpecifierMap;
+
private:
/// \brief The contexts we're importing to and from.
ASTContext &ToContext, &FromContext;
@@ -68,7 +71,12 @@ namespace clang {
/// \brief 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
+ /// 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;
@@ -212,8 +220,13 @@ namespace clang {
/// \returns the equivalent initializer in the "to" context.
CXXCtorInitializer *Import(CXXCtorInitializer *FromInit);
+ /// \brief 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
/// the declarations it contains.
///
diff --git a/include/clang/AST/ASTMutationListener.h b/include/clang/AST/ASTMutationListener.h
index e2d184d654e3..a8eff1a2fcbb 100644
--- a/include/clang/AST/ASTMutationListener.h
+++ b/include/clang/AST/ASTMutationListener.h
@@ -22,6 +22,7 @@ namespace clang {
class CXXRecordDecl;
class Decl;
class DeclContext;
+ class FieldDecl;
class FunctionDecl;
class FunctionTemplateDecl;
class Module;
@@ -93,6 +94,9 @@ public:
/// \brief A default argument was instantiated.
virtual void DefaultArgumentInstantiated(const ParmVarDecl *D) {}
+ /// \brief A default member initializer was instantiated.
+ virtual void DefaultMemberInitializerInstantiated(const FieldDecl *D) {}
+
/// \brief A new objc category class was added for an interface.
virtual void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
const ObjCInterfaceDecl *IFD) {}
diff --git a/include/clang/AST/ASTTypeTraits.h b/include/clang/AST/ASTTypeTraits.h
index ad301b14829e..51d60a90a146 100644
--- a/include/clang/AST/ASTTypeTraits.h
+++ b/include/clang/AST/ASTTypeTraits.h
@@ -121,6 +121,7 @@ private:
enum NodeKindId {
NKI_None,
NKI_TemplateArgument,
+ NKI_TemplateName,
NKI_NestedNameSpecifierLoc,
NKI_QualType,
NKI_TypeLoc,
@@ -175,6 +176,7 @@ private:
};
KIND_TO_KIND_ID(CXXCtorInitializer)
KIND_TO_KIND_ID(TemplateArgument)
+KIND_TO_KIND_ID(TemplateName)
KIND_TO_KIND_ID(NestedNameSpecifier)
KIND_TO_KIND_ID(NestedNameSpecifierLoc)
KIND_TO_KIND_ID(QualType)
@@ -472,6 +474,10 @@ struct DynTypedNode::BaseConverter<
template <>
struct DynTypedNode::BaseConverter<
+ TemplateName, void> : public ValueConverter<TemplateName> {};
+
+template <>
+struct DynTypedNode::BaseConverter<
NestedNameSpecifierLoc,
void> : public ValueConverter<NestedNameSpecifierLoc> {};
diff --git a/include/clang/AST/ASTVector.h b/include/clang/AST/ASTVector.h
index 79453bf10871..9ae5fd62c65a 100644
--- a/include/clang/AST/ASTVector.h
+++ b/include/clang/AST/ASTVector.h
@@ -20,7 +20,6 @@
#include "clang/AST/AttrIterator.h"
#include "llvm/ADT/PointerIntPair.h"
-#include "llvm/Support/Allocator.h"
#include "llvm/Support/type_traits.h"
#include <algorithm>
#include <cstring>
@@ -381,7 +380,7 @@ void ASTVector<T>::grow(const ASTContext &C, size_t MinSize) {
NewCapacity = MinSize;
// Allocate the memory from the ASTContext.
- T *NewElts = new (C, llvm::alignOf<T>()) T[NewCapacity];
+ T *NewElts = new (C, alignof(T)) T[NewCapacity];
// Copy the elements over.
if (Begin != End) {
diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h
index a94b161a04bc..bbe320c28a3b 100644
--- a/include/clang/AST/Attr.h
+++ b/include/clang/AST/Attr.h
@@ -24,8 +24,6 @@
#include "clang/Basic/Sanitizers.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/VersionTuple.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
@@ -57,21 +55,20 @@ protected:
unsigned IsLateParsed : 1;
unsigned DuplicatesAllowed : 1;
- void *operator new(size_t bytes) LLVM_NOEXCEPT {
+ void *operator new(size_t bytes) noexcept {
llvm_unreachable("Attrs cannot be allocated with regular 'new'.");
}
- void operator delete(void *data) LLVM_NOEXCEPT {
+ void operator delete(void *data) noexcept {
llvm_unreachable("Attrs cannot be released with regular 'delete'.");
}
public:
// Forward so that the regular new and delete do not hide global ones.
void *operator new(size_t Bytes, ASTContext &C,
- size_t Alignment = 8) LLVM_NOEXCEPT {
+ size_t Alignment = 8) noexcept {
return ::operator new(Bytes, C, Alignment);
}
- void operator delete(void *Ptr, ASTContext &C,
- size_t Alignment) LLVM_NOEXCEPT {
+ void operator delete(void *Ptr, ASTContext &C, size_t Alignment) noexcept {
return ::operator delete(Ptr, C, Alignment);
}
diff --git a/include/clang/AST/AttrIterator.h b/include/clang/AST/AttrIterator.h
index a0c803096af8..fb9b049e5d6b 100644
--- a/include/clang/AST/AttrIterator.h
+++ b/include/clang/AST/AttrIterator.h
@@ -39,8 +39,7 @@ void operator delete[](void *Ptr, const clang::ASTContext &C, size_t);
namespace clang {
/// AttrVec - A vector of Attr, which is how they are stored on the AST.
-typedef SmallVector<Attr*, 2> AttrVec;
-typedef SmallVector<const Attr*, 2> ConstAttrVec;
+typedef SmallVector<Attr *, 4> AttrVec;
/// specific_attr_iterator - Iterates over a subrange of an AttrVec, only
/// providing attributes that are of a specific type.
diff --git a/include/clang/AST/CXXInheritance.h b/include/clang/AST/CXXInheritance.h
index 8587260049a0..3cf058f26bc6 100644
--- a/include/clang/AST/CXXInheritance.h
+++ b/include/clang/AST/CXXInheritance.h
@@ -16,7 +16,6 @@
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
-#include "clang/AST/DeclarationName.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeOrdering.h"
#include "llvm/ADT/MapVector.h"
@@ -24,7 +23,6 @@
#include "llvm/ADT/SmallVector.h"
#include <cassert>
#include <list>
-#include <map>
namespace clang {
@@ -174,7 +172,7 @@ public:
/// paths for a derived-to-base search.
explicit CXXBasePaths(bool FindAmbiguities = true, bool RecordPaths = true,
bool DetectVirtual = true)
- : FindAmbiguities(FindAmbiguities), RecordPaths(RecordPaths),
+ : Origin(), FindAmbiguities(FindAmbiguities), RecordPaths(RecordPaths),
DetectVirtual(DetectVirtual), DetectedVirtual(nullptr),
NumDeclsFound(0) {}
diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h
index 77510afeec1b..25f6172be9b1 100644
--- a/include/clang/AST/CanonicalType.h
+++ b/include/clang/AST/CanonicalType.h
@@ -630,8 +630,8 @@ CanQual<T> CanQual<T>::CreateUnsafe(QualType Other) {
template<typename T>
template<typename U>
CanProxy<U> CanQual<T>::getAs() const {
- ArrayType_cannot_be_used_with_getAs<U> at;
- (void)at;
+ static_assert(!TypeIsArrayType<T>::value,
+ "ArrayType cannot be used with getAs!");
if (Stored.isNull())
return CanProxy<U>();
@@ -645,8 +645,8 @@ CanProxy<U> CanQual<T>::getAs() const {
template<typename T>
template<typename U>
CanProxy<U> CanQual<T>::castAs() const {
- ArrayType_cannot_be_used_with_getAs<U> at;
- (void)at;
+ static_assert(!TypeIsArrayType<U>::value,
+ "ArrayType cannot be used with castAs!");
assert(!Stored.isNull() && isa<U>(Stored.getTypePtr()));
return CanQual<U>::CreateUnsafe(Stored);
diff --git a/include/clang/AST/CommentLexer.h b/include/clang/AST/CommentLexer.h
index f190b932c0a0..5bb075807be5 100644
--- a/include/clang/AST/CommentLexer.h
+++ b/include/clang/AST/CommentLexer.h
@@ -17,7 +17,6 @@
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/raw_ostream.h"
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index 109036f9588e..b2e332d6d85c 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -251,7 +251,7 @@ public:
// FIXME: Deprecated, move clients to getName().
std::string getNameAsString() const { return Name.getAsString(); }
- void printName(raw_ostream &os) const { os << Name; }
+ virtual void printName(raw_ostream &os) const;
/// getDeclName - Get the actual, stored name of the declaration,
/// which may be a special name.
@@ -789,7 +789,7 @@ public:
protected:
// A pointer union of Stmt * and EvaluatedStmt *. When an EvaluatedStmt, we
- // have allocated the auxilliary struct of information there.
+ // have allocated the auxiliary struct of information there.
//
// TODO: It is a bit unfortunate to use a PointerUnion inside the VarDecl for
// this as *many* VarDecls are ParmVarDecls that don't have default
@@ -865,6 +865,11 @@ protected:
unsigned : NumVarDeclBits;
+ // FIXME: We need something similar to CXXRecordDecl::DefinitionData.
+ /// \brief 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
/// or an Objective-C @catch statement.
unsigned ExceptionVar : 1;
@@ -1025,7 +1030,7 @@ public:
/// void foo() { int x; static int y; extern int z; }
///
bool isLocalVarDecl() const {
- if (getKind() != Decl::Var)
+ if (getKind() != Decl::Var && getKind() != Decl::Decomposition)
return false;
if (const DeclContext *DC = getLexicalDeclContext())
return DC->getRedeclContext()->isFunctionOrMethod();
@@ -1040,7 +1045,7 @@ public:
/// isFunctionOrMethodVarDecl - Similar to isLocalVarDecl, but
/// excludes variables declared in blocks.
bool isFunctionOrMethodVarDecl() const {
- if (getKind() != Decl::Var)
+ if (getKind() != Decl::Var && getKind() != Decl::Decomposition)
return false;
const DeclContext *DC = getLexicalDeclContext()->getRedeclContext();
return DC->isFunctionOrMethod() && DC->getDeclKind() != Decl::Block;
@@ -1198,12 +1203,28 @@ public:
InitializationStyle getInitStyle() const {
return static_cast<InitializationStyle>(VarDeclBits.InitStyle);
}
-
/// \brief Whether the initializer is a direct-initializer (list or call).
bool isDirectInit() const {
return getInitStyle() != CInit;
}
+ /// \brief 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.
+ ///
+ /// 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
+ /// the AST invariants.
+ void demoteThisDefinitionToDeclaration() {
+ assert (isThisDeclarationADefinition() && "Not a definition!");
+ assert (!isa<ParmVarDecl>(this) && "Cannot demote ParmVarDecls!");
+ NonParmVarDeclBits.IsThisDeclarationADemotedDefinition = 1;
+ }
+
/// \brief Determine whether this variable is the exception variable in a
/// C++ catch statememt or an Objective-C \@catch statement.
bool isExceptionVariable() const {
@@ -1302,6 +1323,10 @@ public:
NonParmVarDeclBits.PreviousDeclInSameBlockScope = Same;
}
+ /// \brief 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
/// class template specialization, returns the templated static data member
/// from which it was instantiated.
@@ -1576,11 +1601,6 @@ private:
/// no formals.
ParmVarDecl **ParamInfo;
- /// DeclsInPrototypeScope - Array of pointers to NamedDecls for
- /// decls defined in the function prototype that are not parameters. E.g.
- /// 'enum Y' in 'void f(enum Y {AA} x) {}'.
- ArrayRef<NamedDecl *> DeclsInPrototypeScope;
-
LazyDeclStmtPtr Body;
// FIXME: This can be packed into the bitfields in DeclContext.
@@ -1607,6 +1627,11 @@ private:
/// skipped.
unsigned HasSkippedBody : 1;
+ /// Indicates if the function declaration will have a body, once we're done
+ /// parsing it. (We don't set it to false when we're done parsing, in the
+ /// hopes this is simpler.)
+ unsigned WillHaveBody : 1;
+
/// \brief End part of this FunctionDecl's source range.
///
/// We could compute the full range in getSourceRange(). However, when we're
@@ -1676,25 +1701,21 @@ private:
protected:
FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
- const DeclarationNameInfo &NameInfo,
- QualType T, TypeSourceInfo *TInfo,
- StorageClass S, bool isInlineSpecified,
+ const DeclarationNameInfo &NameInfo, QualType T,
+ TypeSourceInfo *TInfo, StorageClass S, bool isInlineSpecified,
bool isConstexprSpecified)
- : DeclaratorDecl(DK, DC, NameInfo.getLoc(), NameInfo.getName(), T, TInfo,
- StartLoc),
- DeclContext(DK),
- redeclarable_base(C),
- ParamInfo(nullptr), Body(),
- SClass(S),
- IsInline(isInlineSpecified), IsInlineSpecified(isInlineSpecified),
- IsVirtualAsWritten(false), IsPure(false), HasInheritedPrototype(false),
- HasWrittenPrototype(true), IsDeleted(false), IsTrivial(false),
- IsDefaulted(false), IsExplicitlyDefaulted(false),
- HasImplicitReturnZero(false), IsLateTemplateParsed(false),
- IsConstexpr(isConstexprSpecified), UsesSEHTry(false),
- HasSkippedBody(false), EndRangeLoc(NameInfo.getEndLoc()),
- TemplateOrSpecialization(),
- DNLoc(NameInfo.getInfo()) {}
+ : DeclaratorDecl(DK, DC, NameInfo.getLoc(), NameInfo.getName(), T, TInfo,
+ StartLoc),
+ DeclContext(DK), redeclarable_base(C), ParamInfo(nullptr), Body(),
+ SClass(S), IsInline(isInlineSpecified),
+ IsInlineSpecified(isInlineSpecified), IsVirtualAsWritten(false),
+ IsPure(false), HasInheritedPrototype(false), HasWrittenPrototype(true),
+ IsDeleted(false), IsTrivial(false), IsDefaulted(false),
+ IsExplicitlyDefaulted(false), HasImplicitReturnZero(false),
+ IsLateTemplateParsed(false), IsConstexpr(isConstexprSpecified),
+ UsesSEHTry(false), HasSkippedBody(false), WillHaveBody(false),
+ EndRangeLoc(NameInfo.getEndLoc()), TemplateOrSpecialization(),
+ DNLoc(NameInfo.getInfo()) {}
typedef Redeclarable<FunctionDecl> redeclarable_base;
FunctionDecl *getNextRedeclarationImpl() override {
@@ -1976,6 +1997,10 @@ public:
bool hasSkippedBody() const { return HasSkippedBody; }
void setHasSkippedBody(bool Skipped = true) { HasSkippedBody = Skipped; }
+ /// True if this function will eventually have a body, once it's fully parsed.
+ bool willHaveBody() const { return WillHaveBody; }
+ void setWillHaveBody(bool V = true) { WillHaveBody = V; }
+
void setPreviousDeclaration(FunctionDecl * PrevDecl);
FunctionDecl *getCanonicalDecl() override;
@@ -2020,11 +2045,6 @@ public:
setParams(getASTContext(), NewParamInfo);
}
- ArrayRef<NamedDecl *> getDeclsInPrototypeScope() const {
- return DeclsInPrototypeScope;
- }
- void setDeclsInPrototypeScope(ArrayRef<NamedDecl *> NewDecls);
-
/// getMinRequiredArguments - Returns the minimum number of arguments
/// needed to call this function. This may be fewer than the number of
/// function parameters, if some of the parameters have default
@@ -3784,6 +3804,55 @@ public:
static bool classofKind(Kind K) { return K == Import; }
};
+/// \brief Represents a C++ Modules TS module export declaration.
+///
+/// For example:
+/// \code
+/// export void foo();
+/// \endcode
+class ExportDecl final : public Decl, public DeclContext {
+ virtual void anchor();
+private:
+ /// \brief The source location for the right brace (if valid).
+ SourceLocation RBraceLoc;
+
+ ExportDecl(DeclContext *DC, SourceLocation ExportLoc)
+ : Decl(Export, DC, ExportLoc), DeclContext(Export),
+ RBraceLoc(SourceLocation()) { }
+
+ friend class ASTDeclReader;
+
+public:
+ static ExportDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation ExportLoc);
+ static ExportDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+ SourceLocation getExportLoc() const { return getLocation(); }
+ SourceLocation getRBraceLoc() const { return RBraceLoc; }
+ void setRBraceLoc(SourceLocation L) { RBraceLoc = L; }
+
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ if (RBraceLoc.isValid())
+ return RBraceLoc;
+ // No braces: get the end location of the (only) declaration in context
+ // (if present).
+ return decls_empty() ? getLocation() : decls_begin()->getLocEnd();
+ }
+
+ SourceRange getSourceRange() const override LLVM_READONLY {
+ return SourceRange(getLocation(), getLocEnd());
+ }
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K == Export; }
+ static DeclContext *castToDeclContext(const ExportDecl *D) {
+ return static_cast<DeclContext *>(const_cast<ExportDecl*>(D));
+ }
+ static ExportDecl *castFromDeclContext(const DeclContext *DC) {
+ return static_cast<ExportDecl *>(const_cast<DeclContext*>(DC));
+ }
+};
+
/// \brief Represents an empty-declaration.
class EmptyDecl : public Decl {
virtual void anchor();
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h
index ec8bb3aaa305..5de1d0588e80 100644
--- a/include/clang/AST/DeclBase.h
+++ b/include/clang/AST/DeclBase.h
@@ -17,6 +17,7 @@
#include "clang/AST/AttrIterator.h"
#include "clang/AST/DeclarationName.h"
#include "clang/Basic/Specifiers.h"
+#include "clang/Basic/VersionTuple.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/iterator.h"
#include "llvm/ADT/iterator_range.h"
@@ -32,6 +33,7 @@ class DeclContext;
class DeclarationName;
class DependentDiagnostic;
class EnumDecl;
+class ExportDecl;
class FunctionDecl;
class FunctionType;
enum Linkage : unsigned char;
@@ -566,6 +568,10 @@ public:
return NextInContextAndBits.getInt() & ModulePrivateFlag;
}
+ /// \brief Whether this declaration is exported (by virtue of being lexically
+ /// within an ExportDecl or by being a NamespaceDecl).
+ bool isExported() const;
+
/// Return true if this declaration has an attribute which acts as
/// definition of the entity, such as 'alias' or 'ifunc'.
bool hasDefiningAttr() const;
@@ -603,7 +609,12 @@ public:
/// AR_Available, will be set to a (possibly empty) message
/// describing why the declaration has not been introduced, is
/// deprecated, or is unavailable.
- AvailabilityResult getAvailability(std::string *Message = nullptr) const;
+ ///
+ /// \param EnclosingVersion The version to compare with. If empty, assume the
+ /// deployment target version.
+ AvailabilityResult
+ getAvailability(std::string *Message = nullptr,
+ VersionTuple EnclosingVersion = VersionTuple()) const;
/// \brief Determine whether this declaration is marked 'deprecated'.
///
@@ -1129,6 +1140,7 @@ public:
/// ObjCMethodDecl
/// ObjCContainerDecl
/// LinkageSpecDecl
+/// ExportDecl
/// BlockDecl
/// OMPDeclareReductionDecl
///
@@ -1273,7 +1285,8 @@ public:
/// \brief Test whether the context supports looking up names.
bool isLookupContext() const {
- return !isFunctionOrMethod() && DeclKind != Decl::LinkageSpec;
+ return !isFunctionOrMethod() && DeclKind != Decl::LinkageSpec &&
+ DeclKind != Decl::Export;
}
bool isFileContext() const {
@@ -1321,6 +1334,9 @@ public:
/// linkage specification context that specifies C linkage.
bool isExternCContext() const;
+ /// \brief Retrieve the nearest enclosing C linkage specification context.
+ const LinkageSpecDecl *getExternCContext() const;
+
/// \brief Determines whether this context or some of its ancestors is a
/// linkage specification context that specifies C++ linkage.
bool isExternCXXContext() const;
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h
index 66acfee60db0..06ecd3c37342 100644
--- a/include/clang/AST/DeclCXX.h
+++ b/include/clang/AST/DeclCXX.h
@@ -139,7 +139,6 @@ public:
static bool classofKind(Kind K) { return K == AccessSpec; }
};
-
/// \brief Represents a base class of a C++ class.
///
/// Each CXXBaseSpecifier represents a single, direct base class (or
@@ -536,11 +535,10 @@ class CXXRecordDecl : public RecordDecl {
MethodTyInfo(Info) {
IsLambda = true;
- // C++11 [expr.prim.lambda]p3:
- // This class type is neither an aggregate nor a literal type.
+ // C++1z [expr.prim.lambda]p4:
+ // This class type is not an aggregate type.
Aggregate = false;
PlainOldData = false;
- HasNonLiteralTypeFieldsOrBases = true;
}
/// \brief Whether this lambda is known to be dependent, even if its
@@ -573,7 +571,7 @@ class CXXRecordDecl : public RecordDecl {
/// 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.
- Decl *ContextDecl;
+ LazyDeclPtr ContextDecl;
/// \brief The list of captures, both explicit and implicit, for this
/// lambda.
@@ -995,7 +993,11 @@ public:
!hasUserDeclaredCopyConstructor() &&
!hasUserDeclaredCopyAssignment() &&
!hasUserDeclaredMoveConstructor() &&
- !hasUserDeclaredDestructor();
+ !hasUserDeclaredDestructor() &&
+ // C++1z [expr.prim.lambda]p21: "the closure type has a deleted copy
+ // assignment operator". The intent is that this counts as a user
+ // declared copy assignment, but we do not model it that way.
+ !isLambda();
}
/// \brief Determine whether we need to eagerly declare a move assignment
@@ -1149,6 +1151,12 @@ 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.
+ bool hasDirectFields() const {
+ auto &D = data();
+ return D.HasPublicFields || D.HasProtectedFields || D.HasPrivateFields;
+ }
+
/// Whether this class is polymorphic (C++ [class.virtual]),
/// which means that the class contains or inherits a virtual function.
bool isPolymorphic() const { return data().Polymorphic; }
@@ -1339,11 +1347,15 @@ public:
///
/// We resolve DR1361 by ignoring the second bullet. We resolve DR1452 by
/// treating types with trivial default constructors as literal types.
+ ///
+ /// Only in C++1z and beyond, are lambdas literal types.
bool isLiteral() const {
return hasTrivialDestructor() &&
- (isAggregate() || hasConstexprNonCopyMoveConstructor() ||
- hasTrivialDefaultConstructor()) &&
- !hasNonLiteralTypeFieldsOrBases();
+ (!isLambda() || getASTContext().getLangOpts().CPlusPlus1z) &&
+ !hasNonLiteralTypeFieldsOrBases() &&
+ (isAggregate() || isLambda() ||
+ hasConstexprNonCopyMoveConstructor() ||
+ hasTrivialDefaultConstructor());
}
/// \brief If this record is an instantiation of a member class,
@@ -1665,10 +1677,7 @@ public:
/// the declaration in which the lambda occurs, e.g., the function parameter
/// or the non-static data member. Otherwise, it returns NULL to imply that
/// the declaration context suffices.
- Decl *getLambdaContextDecl() const {
- assert(isLambda() && "Not a lambda closure type!");
- return getLambdaData().ContextDecl;
- }
+ Decl *getLambdaContextDecl() const;
/// \brief Set the mangling number and context declaration for a lambda
/// class.
@@ -1919,8 +1928,7 @@ public:
/// B(A& a) : A(a), f(3.14159) { }
/// };
/// \endcode
-class CXXCtorInitializer final
- : private llvm::TrailingObjects<CXXCtorInitializer, VarDecl *> {
+class CXXCtorInitializer final {
/// \brief Either the base class name/delegating constructor type (stored as
/// a TypeSourceInfo*), an normal field (FieldDecl), or an anonymous field
/// (IndirectFieldDecl*) being initialized.
@@ -1958,14 +1966,8 @@ class CXXCtorInitializer final
unsigned IsWritten : 1;
/// If IsWritten is true, then this number keeps track of the textual order
- /// of this initializer in the original sources, counting from 0; otherwise,
- /// it stores the number of array index variables stored after this object
- /// in memory.
- unsigned SourceOrderOrNumArrayIndices : 13;
-
- CXXCtorInitializer(ASTContext &Context, FieldDecl *Member,
- SourceLocation MemberLoc, SourceLocation L, Expr *Init,
- SourceLocation R, VarDecl **Indices, unsigned NumIndices);
+ /// of this initializer in the original sources, counting from 0.
+ unsigned SourceOrder : 13;
public:
/// \brief Creates a new base-class initializer.
@@ -1991,13 +1993,6 @@ public:
CXXCtorInitializer(ASTContext &Context, TypeSourceInfo *TInfo,
SourceLocation L, Expr *Init, SourceLocation R);
- /// \brief Creates a new member initializer that optionally contains
- /// array indices used to describe an elementwise initialization.
- static CXXCtorInitializer *Create(ASTContext &Context, FieldDecl *Member,
- SourceLocation MemberLoc, SourceLocation L,
- Expr *Init, SourceLocation R,
- VarDecl **Indices, unsigned NumIndices);
-
/// \brief Determine whether this initializer is initializing a base class.
bool isBaseInitializer() const {
return Initializee.is<TypeSourceInfo*>() && !IsDelegating;
@@ -2102,7 +2097,7 @@ public:
/// \brief 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>(SourceOrderOrNumArrayIndices) : -1;
+ return IsWritten ? static_cast<int>(SourceOrder) : -1;
}
/// \brief Set the source order of this initializer.
@@ -2112,49 +2107,22 @@ public:
///
/// This assumes that the initializer was written in the source code, and
/// ensures that isWritten() returns true.
- void setSourceOrder(int pos) {
+ void setSourceOrder(int Pos) {
assert(!IsWritten &&
+ "setSourceOrder() used on implicit initializer");
+ assert(SourceOrder == 0 &&
"calling twice setSourceOrder() on the same initializer");
- assert(SourceOrderOrNumArrayIndices == 0 &&
- "setSourceOrder() used when there are implicit array indices");
- assert(pos >= 0 &&
+ assert(Pos >= 0 &&
"setSourceOrder() used to make an initializer implicit");
IsWritten = true;
- SourceOrderOrNumArrayIndices = static_cast<unsigned>(pos);
+ SourceOrder = static_cast<unsigned>(Pos);
}
SourceLocation getLParenLoc() const { return LParenLoc; }
SourceLocation getRParenLoc() const { return RParenLoc; }
- /// \brief Determine the number of implicit array indices used while
- /// described an array member initialization.
- unsigned getNumArrayIndices() const {
- return IsWritten ? 0 : SourceOrderOrNumArrayIndices;
- }
-
- /// \brief Retrieve a particular array index variable used to
- /// describe an array member initialization.
- VarDecl *getArrayIndex(unsigned I) {
- assert(I < getNumArrayIndices() && "Out of bounds member array index");
- return getTrailingObjects<VarDecl *>()[I];
- }
- const VarDecl *getArrayIndex(unsigned I) const {
- assert(I < getNumArrayIndices() && "Out of bounds member array index");
- return getTrailingObjects<VarDecl *>()[I];
- }
- void setArrayIndex(unsigned I, VarDecl *Index) {
- assert(I < getNumArrayIndices() && "Out of bounds member array index");
- getTrailingObjects<VarDecl *>()[I] = Index;
- }
- ArrayRef<VarDecl *> getArrayIndices() {
- return llvm::makeArrayRef(getTrailingObjects<VarDecl *>(),
- getNumArrayIndices());
- }
-
/// \brief Get the initializer.
Expr *getInit() const { return static_cast<Expr*>(Init); }
-
- friend TrailingObjects;
};
/// Description of a constructor that was inherited from a base class.
@@ -2952,11 +2920,10 @@ class ConstructorUsingShadowDecl final : public UsingShadowDecl {
dyn_cast<ConstructorUsingShadowDecl>(Target)),
ConstructedBaseClassShadowDecl(NominatedBaseClassShadowDecl),
IsVirtual(TargetInVirtualBase) {
- // If we found a constructor for a non-virtual base class, but it chains to
- // a constructor for a virtual base, we should directly call the virtual
- // base constructor instead.
+ // If we found a constructor that chains to a constructor for a virtual
+ // base, we should directly call that virtual base constructor instead.
// FIXME: This logic belongs in Sema.
- if (!TargetInVirtualBase && NominatedBaseClassShadowDecl &&
+ if (NominatedBaseClassShadowDecl &&
NominatedBaseClassShadowDecl->constructsVirtualBase()) {
ConstructedBaseClassShadowDecl =
NominatedBaseClassShadowDecl->ConstructedBaseClassShadowDecl;
@@ -2964,7 +2931,9 @@ class ConstructorUsingShadowDecl final : public UsingShadowDecl {
}
}
ConstructorUsingShadowDecl(ASTContext &C, EmptyShell Empty)
- : UsingShadowDecl(ConstructorUsingShadow, C, Empty) {}
+ : UsingShadowDecl(ConstructorUsingShadow, C, Empty),
+ NominatedBaseClassShadowDecl(), ConstructedBaseClassShadowDecl(),
+ IsVirtual(false) {}
public:
static ConstructorUsingShadowDecl *Create(ASTContext &C, DeclContext *DC,
@@ -3171,6 +3140,77 @@ public:
friend class ASTDeclWriter;
};
+/// Represents a pack of using declarations that a single
+/// using-declarator pack-expanded into.
+///
+/// \code
+/// template<typename ...T> struct X : T... {
+/// using T::operator()...;
+/// using T::operator T...;
+/// };
+/// \endcode
+///
+/// In the second case above, the UsingPackDecl will have the name
+/// 'operator T' (which contains an unexpanded pack), but the individual
+/// UsingDecls and UsingShadowDecls will have more reasonable names.
+class UsingPackDecl final
+ : public NamedDecl, public Mergeable<UsingPackDecl>,
+ private llvm::TrailingObjects<UsingPackDecl, NamedDecl *> {
+ void anchor() override;
+
+ /// The UnresolvedUsingValueDecl or UnresolvedUsingTypenameDecl from
+ /// which this waas instantiated.
+ NamedDecl *InstantiatedFrom;
+
+ /// The number of using-declarations created by this pack expansion.
+ unsigned NumExpansions;
+
+ UsingPackDecl(DeclContext *DC, NamedDecl *InstantiatedFrom,
+ ArrayRef<NamedDecl *> UsingDecls)
+ : NamedDecl(UsingPack, DC,
+ InstantiatedFrom ? InstantiatedFrom->getLocation()
+ : SourceLocation(),
+ InstantiatedFrom ? InstantiatedFrom->getDeclName()
+ : DeclarationName()),
+ InstantiatedFrom(InstantiatedFrom), NumExpansions(UsingDecls.size()) {
+ std::uninitialized_copy(UsingDecls.begin(), UsingDecls.end(),
+ getTrailingObjects<NamedDecl *>());
+ }
+
+public:
+ /// Get the using declaration from which this was instantiated. This will
+ /// always be an UnresolvedUsingValueDecl or an UnresolvedUsingTypenameDecl
+ /// that is a pack expansion.
+ NamedDecl *getInstantiatedFromUsingDecl() { return InstantiatedFrom; }
+
+ /// Get the set of using declarations that this pack expanded into. Note that
+ /// some of these may still be unresolved.
+ ArrayRef<NamedDecl *> expansions() const {
+ return llvm::makeArrayRef(getTrailingObjects<NamedDecl *>(), NumExpansions);
+ }
+
+ static UsingPackDecl *Create(ASTContext &C, DeclContext *DC,
+ NamedDecl *InstantiatedFrom,
+ ArrayRef<NamedDecl *> UsingDecls);
+
+ static UsingPackDecl *CreateDeserialized(ASTContext &C, unsigned ID,
+ unsigned NumExpansions);
+
+ SourceRange getSourceRange() const override LLVM_READONLY {
+ return InstantiatedFrom->getSourceRange();
+ }
+
+ UsingPackDecl *getCanonicalDecl() override { return getFirstDecl(); }
+ const UsingPackDecl *getCanonicalDecl() const { return getFirstDecl(); }
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K == UsingPack; }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+ friend TrailingObjects;
+};
+
/// \brief Represents a dependent using declaration which was not marked with
/// \c typename.
///
@@ -3189,6 +3229,9 @@ class UnresolvedUsingValueDecl : public ValueDecl,
/// \brief The source location of the 'using' keyword
SourceLocation UsingLocation;
+ /// \brief If this is a pack expansion, the location of the '...'.
+ SourceLocation EllipsisLoc;
+
/// \brief The nested-name-specifier that precedes the name.
NestedNameSpecifierLoc QualifierLoc;
@@ -3199,11 +3242,12 @@ class UnresolvedUsingValueDecl : public ValueDecl,
UnresolvedUsingValueDecl(DeclContext *DC, QualType Ty,
SourceLocation UsingLoc,
NestedNameSpecifierLoc QualifierLoc,
- const DeclarationNameInfo &NameInfo)
+ const DeclarationNameInfo &NameInfo,
+ SourceLocation EllipsisLoc)
: ValueDecl(UnresolvedUsingValue, DC,
NameInfo.getLoc(), NameInfo.getName(), Ty),
- UsingLocation(UsingLoc), QualifierLoc(QualifierLoc),
- DNLoc(NameInfo.getInfo())
+ UsingLocation(UsingLoc), EllipsisLoc(EllipsisLoc),
+ QualifierLoc(QualifierLoc), DNLoc(NameInfo.getInfo())
{ }
public:
@@ -3229,10 +3273,20 @@ public:
return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc);
}
+ /// \brief 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.
+ SourceLocation getEllipsisLoc() const {
+ return EllipsisLoc;
+ }
+
static UnresolvedUsingValueDecl *
Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc,
NestedNameSpecifierLoc QualifierLoc,
- const DeclarationNameInfo &NameInfo);
+ const DeclarationNameInfo &NameInfo, SourceLocation EllipsisLoc);
static UnresolvedUsingValueDecl *
CreateDeserialized(ASTContext &C, unsigned ID);
@@ -3273,6 +3327,9 @@ class UnresolvedUsingTypenameDecl
/// \brief The source location of the 'typename' keyword
SourceLocation TypenameLocation;
+ /// \brief If this is a pack expansion, the location of the '...'.
+ SourceLocation EllipsisLoc;
+
/// \brief The nested-name-specifier that precedes the name.
NestedNameSpecifierLoc QualifierLoc;
@@ -3280,10 +3337,12 @@ class UnresolvedUsingTypenameDecl
SourceLocation TypenameLoc,
NestedNameSpecifierLoc QualifierLoc,
SourceLocation TargetNameLoc,
- IdentifierInfo *TargetName)
+ IdentifierInfo *TargetName,
+ SourceLocation EllipsisLoc)
: TypeDecl(UnresolvedUsingTypename, DC, TargetNameLoc, TargetName,
UsingLoc),
- TypenameLocation(TypenameLoc), QualifierLoc(QualifierLoc) { }
+ TypenameLocation(TypenameLoc), EllipsisLoc(EllipsisLoc),
+ QualifierLoc(QualifierLoc) { }
friend class ASTDeclReader;
@@ -3303,10 +3362,25 @@ public:
return QualifierLoc.getNestedNameSpecifier();
}
+ DeclarationNameInfo getNameInfo() const {
+ return DeclarationNameInfo(getDeclName(), getLocation());
+ }
+
+ /// \brief 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.
+ SourceLocation getEllipsisLoc() const {
+ return EllipsisLoc;
+ }
+
static UnresolvedUsingTypenameDecl *
Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc,
SourceLocation TypenameLoc, NestedNameSpecifierLoc QualifierLoc,
- SourceLocation TargetNameLoc, DeclarationName TargetName);
+ SourceLocation TargetNameLoc, DeclarationName TargetName,
+ SourceLocation EllipsisLoc);
static UnresolvedUsingTypenameDecl *
CreateDeserialized(ASTContext &C, unsigned ID);
@@ -3364,6 +3438,104 @@ public:
friend class ASTDeclReader;
};
+/// A binding in a decomposition declaration. For instance, given:
+///
+/// int n[3];
+/// auto &[a, b, c] = n;
+///
+/// a, b, and c are BindingDecls, whose bindings are the expressions
+/// x[0], x[1], and x[2] respectively, where x is the implicit
+/// DecompositionDecl of type 'int (&)[3]'.
+class BindingDecl : public ValueDecl {
+ void anchor() override;
+
+ /// The binding represented by this declaration. References to this
+ /// declaration are effectively equivalent to this expression (except
+ /// that it is only evaluated once at the point of declaration of the
+ /// binding).
+ Expr *Binding;
+
+ BindingDecl(DeclContext *DC, SourceLocation IdLoc, IdentifierInfo *Id)
+ : ValueDecl(Decl::Binding, DC, IdLoc, Id, QualType()), Binding(nullptr) {}
+
+public:
+ static BindingDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation IdLoc, IdentifierInfo *Id);
+ static BindingDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+ /// Get the expression to which this declaration is bound. This may be null
+ /// in two different cases: while parsing the initializer for the
+ /// decomposition declaration, and when the initializer is type-dependent.
+ Expr *getBinding() const { return Binding; }
+
+ /// Get the variable (if any) that holds the value of evaluating the binding.
+ /// Only present for user-defined bindings for tuple-like types.
+ VarDecl *getHoldingVar() const;
+
+ /// Set the binding for this BindingDecl, along with its declared type (which
+ /// should be a possibly-cv-qualified form of the type of the binding, or a
+ /// reference to such a type).
+ void setBinding(QualType DeclaredType, Expr *Binding) {
+ setType(DeclaredType);
+ this->Binding = Binding;
+ }
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K == Decl::Binding; }
+
+ friend class ASTDeclReader;
+};
+
+/// A decomposition declaration. For instance, given:
+///
+/// int n[3];
+/// auto &[a, b, c] = n;
+///
+/// the second line declares a DecompositionDecl of type 'int (&)[3]', and
+/// three BindingDecls (named a, b, and c). An instance of this class is always
+/// unnamed, but behaves in almost all other respects like a VarDecl.
+class DecompositionDecl final
+ : public VarDecl,
+ private llvm::TrailingObjects<DecompositionDecl, BindingDecl *> {
+ void anchor() override;
+
+ /// The number of BindingDecl*s following this object.
+ unsigned NumBindings;
+
+ DecompositionDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
+ SourceLocation LSquareLoc, QualType T,
+ TypeSourceInfo *TInfo, StorageClass SC,
+ ArrayRef<BindingDecl *> Bindings)
+ : VarDecl(Decomposition, C, DC, StartLoc, LSquareLoc, nullptr, T, TInfo,
+ SC),
+ NumBindings(Bindings.size()) {
+ std::uninitialized_copy(Bindings.begin(), Bindings.end(),
+ getTrailingObjects<BindingDecl *>());
+ }
+
+public:
+ static DecompositionDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation StartLoc,
+ SourceLocation LSquareLoc,
+ QualType T, TypeSourceInfo *TInfo,
+ StorageClass S,
+ ArrayRef<BindingDecl *> Bindings);
+ static DecompositionDecl *CreateDeserialized(ASTContext &C, unsigned ID,
+ unsigned NumBindings);
+
+ ArrayRef<BindingDecl *> bindings() const {
+ return llvm::makeArrayRef(getTrailingObjects<BindingDecl *>(), NumBindings);
+ }
+
+ void printName(raw_ostream &os) const override;
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K == Decomposition; }
+
+ friend TrailingObjects;
+ friend class ASTDeclReader;
+};
+
/// An instance of this class represents the declaration of a property
/// member. This is a Microsoft extension to C++, first introduced in
/// Visual Studio .NET 2003 as a parallel to similar features in C#
diff --git a/include/clang/AST/DeclFriend.h b/include/clang/AST/DeclFriend.h
index 5b2e2d9915eb..172c46a44ac1 100644
--- a/include/clang/AST/DeclFriend.h
+++ b/include/clang/AST/DeclFriend.h
@@ -82,6 +82,7 @@ private:
FriendDecl(EmptyShell Empty, unsigned NumFriendTypeTPLists)
: Decl(Decl::Friend, Empty), NextFriend(),
+ UnsupportedFriend(false),
NumTPLists(NumFriendTypeTPLists) { }
FriendDecl *getNextFriend() {
@@ -166,6 +167,7 @@ public:
friend class ASTDeclReader;
friend class ASTDeclWriter;
+ friend class ASTNodeImporter;
friend TrailingObjects;
};
diff --git a/include/clang/AST/DeclGroup.h b/include/clang/AST/DeclGroup.h
index c84bb5e60481..6353b26f7bf5 100644
--- a/include/clang/AST/DeclGroup.h
+++ b/include/clang/AST/DeclGroup.h
@@ -84,7 +84,7 @@ public:
bool isDeclGroup() const { return getKind() == DeclGroupKind; }
Decl *getSingleDecl() {
- assert(isSingleDecl() && "Isn't a declgroup");
+ assert(isSingleDecl() && "Isn't a single decl");
return D;
}
const Decl *getSingleDecl() const {
diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h
index ad9b5a26b7c8..f5098f06a9f6 100644
--- a/include/clang/AST/DeclObjC.h
+++ b/include/clang/AST/DeclObjC.h
@@ -394,7 +394,7 @@ public:
/// createImplicitParams - Used to lazily create the self and cmd
/// implict parameters. This must be called prior to using getSelfDecl()
- /// or getCmdDecl(). The call is ignored if the implicit paramters
+ /// or getCmdDecl(). The call is ignored if the implicit parameters
/// have already been created.
void createImplicitParams(ASTContext &Context, const ObjCInterfaceDecl *ID);
@@ -463,6 +463,9 @@ public:
ImplementationControl getImplementationControl() const {
return ImplementationControl(DeclImplementation);
}
+ bool isOptional() const {
+ return getImplementationControl() == Optional;
+ }
/// Returns true if this specific method declaration is marked with the
/// designated initializer attribute.
@@ -870,6 +873,9 @@ public:
PropertyControl getPropertyImplementation() const {
return PropertyControl(PropertyImplementation);
}
+ bool isOptional() const {
+ return getPropertyImplementation() == PropertyControl::Optional;
+ }
void setPropertyIvarDecl(ObjCIvarDecl *Ivar) {
PropertyIvarDecl = Ivar;
diff --git a/include/clang/AST/DeclOpenMP.h b/include/clang/AST/DeclOpenMP.h
index 1975bc551ca5..30ca79e9d005 100644
--- a/include/clang/AST/DeclOpenMP.h
+++ b/include/clang/AST/DeclOpenMP.h
@@ -173,18 +173,21 @@ class OMPCapturedExprDecl final : public VarDecl {
void anchor() override;
OMPCapturedExprDecl(ASTContext &C, DeclContext *DC, IdentifierInfo *Id,
- QualType Type)
- : VarDecl(OMPCapturedExpr, C, DC, SourceLocation(), SourceLocation(), Id,
- Type, nullptr, SC_None) {
+ QualType Type, SourceLocation StartLoc)
+ : VarDecl(OMPCapturedExpr, C, DC, StartLoc, SourceLocation(), Id, Type,
+ nullptr, SC_None) {
setImplicit();
}
public:
static OMPCapturedExprDecl *Create(ASTContext &C, DeclContext *DC,
- IdentifierInfo *Id, QualType T);
+ IdentifierInfo *Id, QualType T,
+ SourceLocation StartLoc);
static OMPCapturedExprDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+ SourceRange getSourceRange() const override LLVM_READONLY;
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == OMPCapturedExpr; }
diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h
index d553e739c388..2af95c02c460 100644
--- a/include/clang/AST/DeclTemplate.h
+++ b/include/clang/AST/DeclTemplate.h
@@ -21,7 +21,6 @@
#include "llvm/ADT/PointerUnion.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/TrailingObjects.h"
-#include <limits>
#include <utility>
namespace clang {
@@ -49,7 +48,8 @@ NamedDecl *getAsNamedDecl(TemplateParameter P);
/// \brief Stores a list of template parameters for a TemplateDecl and its
/// derived classes.
class TemplateParameterList final
- : private llvm::TrailingObjects<TemplateParameterList, NamedDecl *> {
+ : private llvm::TrailingObjects<TemplateParameterList, NamedDecl *,
+ Expr *> {
/// The location of the 'template' keyword.
SourceLocation TemplateLoc;
@@ -59,26 +59,35 @@ class TemplateParameterList final
/// The number of template parameters in this template
/// parameter list.
- unsigned NumParams : 31;
+ unsigned NumParams : 30;
/// Whether this template parameter list contains an unexpanded parameter
/// pack.
unsigned ContainsUnexpandedParameterPack : 1;
+ /// Whether this template parameter list has an associated requires-clause
+ unsigned HasRequiresClause : 1;
+
protected:
size_t numTrailingObjects(OverloadToken<NamedDecl *>) const {
return NumParams;
}
+ size_t numTrailingObjects(OverloadToken<Expr *>) const {
+ return HasRequiresClause;
+ }
+
TemplateParameterList(SourceLocation TemplateLoc, SourceLocation LAngleLoc,
- ArrayRef<NamedDecl *> Params, SourceLocation RAngleLoc);
+ ArrayRef<NamedDecl *> Params, SourceLocation RAngleLoc,
+ Expr *RequiresClause);
public:
static TemplateParameterList *Create(const ASTContext &C,
SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
ArrayRef<NamedDecl *> Params,
- SourceLocation RAngleLoc);
+ SourceLocation RAngleLoc,
+ Expr *RequiresClause);
/// \brief Iterates through the template parameters in this list.
typedef NamedDecl** iterator;
@@ -130,6 +139,16 @@ public:
return ContainsUnexpandedParameterPack;
}
+ /// \brief The constraint-expression of the associated requires-clause.
+ Expr *getRequiresClause() {
+ return HasRequiresClause ? *getTrailingObjects<Expr *>() : nullptr;
+ }
+
+ /// \brief The constraint-expression of the associated requires-clause.
+ const Expr *getRequiresClause() const {
+ return HasRequiresClause ? *getTrailingObjects<Expr *>() : nullptr;
+ }
+
SourceLocation getTemplateLoc() const { return TemplateLoc; }
SourceLocation getLAngleLoc() const { return LAngleLoc; }
SourceLocation getRAngleLoc() const { return RAngleLoc; }
@@ -139,36 +158,37 @@ public:
}
friend TrailingObjects;
- template <size_t N> friend class FixedSizeTemplateParameterListStorage;
+
+ template <size_t N, bool HasRequiresClause>
+ friend class FixedSizeTemplateParameterListStorage;
+
+public:
+ // FIXME: workaround for MSVC 2013; remove when no longer needed
+ using FixedSizeStorageOwner = TrailingObjects::FixedSizeStorageOwner;
};
-/// \brief Stores a list of template parameters for a TemplateDecl and its
-/// derived classes. Suitable for creating on the stack.
-template <size_t N> class FixedSizeTemplateParameterListStorage {
- // This is kinda ugly: TemplateParameterList usually gets allocated
- // in a block of memory with NamedDecls appended to it. Here, to get
- // it stack allocated, we include the params as a separate
- // variable. After allocation, the TemplateParameterList object
- // treats them as part of itself.
- TemplateParameterList List;
- NamedDecl *Params[N];
+/// \brief 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>
+class FixedSizeTemplateParameterListStorage
+ : public TemplateParameterList::FixedSizeStorageOwner {
+ typename TemplateParameterList::FixedSizeStorage<
+ NamedDecl *, Expr *>::with_counts<
+ N, HasRequiresClause ? 1u : 0u
+ >::type storage;
public:
FixedSizeTemplateParameterListStorage(SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
ArrayRef<NamedDecl *> Params,
- SourceLocation RAngleLoc)
- : List(TemplateLoc, LAngleLoc, Params, RAngleLoc) {
- // Because we're doing an evil layout hack above, have some
- // asserts, just to double-check everything is laid out like
- // expected.
- assert(sizeof(*this) ==
- TemplateParameterList::totalSizeToAlloc<NamedDecl *>(N) &&
- "Object layout not as expected");
- assert(this->Params == List.getTrailingObjects<NamedDecl *>() &&
- "Object layout not as expected");
- }
- TemplateParameterList *get() { return &List; }
+ SourceLocation RAngleLoc,
+ Expr *RequiresClause)
+ : FixedSizeStorageOwner(
+ (assert(N == Params.size()),
+ assert(HasRequiresClause == static_cast<bool>(RequiresClause)),
+ new (static_cast<void *>(&storage)) TemplateParameterList(
+ TemplateLoc, LAngleLoc, Params, RAngleLoc, RequiresClause))) {}
};
/// \brief A template argument list.
@@ -356,6 +376,11 @@ public:
return TemplateParams;
}
+ /// Get the constraint-expression from the associated requires-clause (if any)
+ const Expr *getRequiresClause() const {
+ return TemplateParams ? TemplateParams->getRequiresClause() : nullptr;
+ }
+
/// Get the underlying, templated declaration.
NamedDecl *getTemplatedDecl() const { return TemplatedDecl.getPointer(); }
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index 9179c7736a9a..41ae6d2b721e 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -445,6 +445,11 @@ public:
return const_cast<Expr*>(this)->getSourceBitField();
}
+ Decl *getReferencedDeclOfCallee();
+ const Decl *getReferencedDeclOfCallee() const {
+ return const_cast<Expr*>(this)->getReferencedDeclOfCallee();
+ }
+
/// \brief If this expression is an l-value for an Objective C
/// property, find the underlying property reference expression.
const ObjCPropertyRefExpr *getObjCProperty() const;
@@ -823,12 +828,22 @@ 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.
+ /// If this is a prvalue, we guarantee that it is of the most-derived type
+ /// for the object itself.
+ const Expr *getBestDynamicClassTypeExpr() const;
+
/// Walk outwards from an expression we want to bind a reference to and
/// find the expression whose lifetime needs to be extended. Record
/// the LHSs of comma expressions and adjustments needed along the path.
const Expr *skipRValueSubobjectAdjustments(
SmallVectorImpl<const Expr *> &CommaLHS,
SmallVectorImpl<SubobjectAdjustment> &Adjustments) const;
+ const Expr *skipRValueSubobjectAdjustments() const {
+ SmallVector<const Expr *, 8> CommaLHSs;
+ SmallVector<SubobjectAdjustment, 8> Adjustments;
+ return skipRValueSubobjectAdjustments(CommaLHSs, Adjustments);
+ }
static bool classof(const Stmt *T) {
return T->getStmtClass() >= firstExprConstant &&
@@ -2406,8 +2421,8 @@ public:
/// \brief Retrieve the member declaration to which this expression refers.
///
- /// The returned declaration will either be a FieldDecl or (in C++)
- /// a CXXMethodDecl.
+ /// 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; }
@@ -3771,17 +3786,26 @@ public:
/// \brief Build an empty initializer list.
explicit InitListExpr(EmptyShell Empty)
- : Expr(InitListExprClass, Empty) { }
+ : Expr(InitListExprClass, Empty), AltForm(nullptr, true) { }
unsigned getNumInits() const { return InitExprs.size(); }
/// \brief Retrieve the set of initializers.
Expr **getInits() { return reinterpret_cast<Expr **>(InitExprs.data()); }
+ /// \brief Retrieve the set of initializers.
+ Expr * const *getInits() const {
+ return reinterpret_cast<Expr * const *>(InitExprs.data());
+ }
+
ArrayRef<Expr *> inits() {
return llvm::makeArrayRef(getInits(), getNumInits());
}
+ ArrayRef<Expr *> inits() const {
+ return llvm::makeArrayRef(getInits(), getNumInits());
+ }
+
const Expr *getInit(unsigned Init) const {
assert(Init < getNumInits() && "Initializer access out of range!");
return cast_or_null<Expr>(InitExprs[Init]);
@@ -3862,7 +3886,7 @@ public:
// Explicit InitListExpr's originate from source code (and have valid source
// locations). Implicit InitListExpr's are created by the semantic analyzer.
- bool isExplicit() {
+ bool isExplicit() const {
return LBraceLoc.isValid() && RBraceLoc.isValid();
}
@@ -3870,6 +3894,11 @@ public:
// literal or an @encode?
bool isStringLiteralInit() const;
+ /// Is this a transparent initializer list (that is, an InitListExpr that is
+ /// purely syntactic, and whose semantics are that of the sole contained
+ /// initializer)?
+ bool isTransparent() const;
+
SourceLocation getLBraceLoc() const { return LBraceLoc; }
void setLBraceLoc(SourceLocation Loc) { LBraceLoc = Loc; }
SourceLocation getRBraceLoc() const { return RBraceLoc; }
@@ -4304,6 +4333,98 @@ public:
}
};
+/// \brief Represents a loop initializing the elements of an array.
+///
+/// The need to initialize the elements of an array occurs in a number of
+/// contexts:
+///
+/// * in the implicit copy/move constructor for a class with an array member
+/// * when a lambda-expression captures an array by value
+/// * when a decomposition declaration decomposes an array
+///
+/// There are two subexpressions: a common expression (the source array)
+/// that is evaluated once up-front, and a per-element initializer that
+/// runs once for each array element.
+///
+/// Within the per-element initializer, the common expression may be referenced
+/// via an OpaqueValueExpr, and the current index may be obtained via an
+/// ArrayInitIndexExpr.
+class ArrayInitLoopExpr : public Expr {
+ Stmt *SubExprs[2];
+
+ explicit ArrayInitLoopExpr(EmptyShell Empty)
+ : Expr(ArrayInitLoopExprClass, Empty), SubExprs{} {}
+
+public:
+ explicit ArrayInitLoopExpr(QualType T, Expr *CommonInit, Expr *ElementInit)
+ : Expr(ArrayInitLoopExprClass, T, VK_RValue, OK_Ordinary, false,
+ CommonInit->isValueDependent() || ElementInit->isValueDependent(),
+ T->isInstantiationDependentType(),
+ CommonInit->containsUnexpandedParameterPack() ||
+ ElementInit->containsUnexpandedParameterPack()),
+ SubExprs{CommonInit, ElementInit} {}
+
+ /// Get the common subexpression shared by all initializations (the source
+ /// array).
+ OpaqueValueExpr *getCommonExpr() const {
+ return cast<OpaqueValueExpr>(SubExprs[0]);
+ }
+
+ /// Get the initializer to use for each array element.
+ Expr *getSubExpr() const { return cast<Expr>(SubExprs[1]); }
+
+ llvm::APInt getArraySize() const {
+ return cast<ConstantArrayType>(getType()->castAsArrayTypeUnsafe())
+ ->getSize();
+ }
+
+ static bool classof(const Stmt *S) {
+ return S->getStmtClass() == ArrayInitLoopExprClass;
+ }
+
+ SourceLocation getLocStart() const LLVM_READONLY {
+ return getCommonExpr()->getLocStart();
+ }
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ return getCommonExpr()->getLocEnd();
+ }
+
+ child_range children() {
+ return child_range(SubExprs, SubExprs + 2);
+ }
+
+ friend class ASTReader;
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+};
+
+/// \brief 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 {
+ explicit ArrayInitIndexExpr(EmptyShell Empty)
+ : Expr(ArrayInitIndexExprClass, Empty) {}
+
+public:
+ explicit ArrayInitIndexExpr(QualType T)
+ : Expr(ArrayInitIndexExprClass, T, VK_RValue, OK_Ordinary,
+ false, false, false, false) {}
+
+ static bool classof(const Stmt *S) {
+ return S->getStmtClass() == ArrayInitIndexExprClass;
+ }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return SourceLocation(); }
+ SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); }
+
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+
+ friend class ASTReader;
+ friend class ASTStmtReader;
+};
+
/// \brief Represents an implicitly-generated value initialization of
/// an object of a given type.
///
@@ -4447,11 +4568,19 @@ public:
return cast<Expr>(SubExprs[END_EXPR+i]);
}
Expr *getAssocExpr(unsigned i) { return cast<Expr>(SubExprs[END_EXPR+i]); }
-
+ ArrayRef<Expr *> getAssocExprs() const {
+ return NumAssocs
+ ? llvm::makeArrayRef(
+ &reinterpret_cast<Expr **>(SubExprs)[END_EXPR], NumAssocs)
+ : None;
+ }
const TypeSourceInfo *getAssocTypeSourceInfo(unsigned i) const {
return AssocTypes[i];
}
TypeSourceInfo *getAssocTypeSourceInfo(unsigned i) { return AssocTypes[i]; }
+ ArrayRef<TypeSourceInfo *> getAssocTypeSourceInfos() const {
+ return NumAssocs ? llvm::makeArrayRef(&AssocTypes[0], NumAssocs) : None;
+ }
QualType getAssocType(unsigned i) const {
if (const TypeSourceInfo *TS = getAssocTypeSourceInfo(i))
diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h
index 86cbfb2cd0b4..37e59771a723 100644
--- a/include/clang/AST/ExprCXX.h
+++ b/include/clang/AST/ExprCXX.h
@@ -76,6 +76,19 @@ public:
/// expression refers to.
OverloadedOperatorKind getOperator() const { return Operator; }
+ static bool isAssignmentOp(OverloadedOperatorKind Opc) {
+ return Opc == OO_Equal || Opc == OO_StarEqual ||
+ Opc == OO_SlashEqual || Opc == OO_PercentEqual ||
+ Opc == OO_PlusEqual || Opc == OO_MinusEqual ||
+ Opc == OO_LessLessEqual || Opc == OO_GreaterGreaterEqual ||
+ Opc == OO_AmpEqual || Opc == OO_CaretEqual ||
+ Opc == OO_PipeEqual;
+ }
+ bool isAssignmentOp() const { return isAssignmentOp(getOperator()); }
+
+ /// \brief Is this written as an infix binary operator?
+ bool isInfixBinaryOp() const;
+
/// \brief Returns the location of the operator symbol in the expression.
///
/// When \c getOperator()==OO_Call, this is the location of the right
@@ -1500,9 +1513,8 @@ public:
/// C++1y introduces a new form of "capture" called an init-capture that
/// includes an initializing expression (rather than capturing a variable),
/// and which can never occur implicitly.
-class LambdaExpr final
- : public Expr,
- private llvm::TrailingObjects<LambdaExpr, Stmt *, unsigned, VarDecl *> {
+class LambdaExpr final : public Expr,
+ private llvm::TrailingObjects<LambdaExpr, Stmt *> {
/// \brief The source range that covers the lambda introducer ([...]).
SourceRange IntroducerRange;
@@ -1523,10 +1535,6 @@ class LambdaExpr final
/// \brief Whether this lambda had the result type explicitly specified.
unsigned ExplicitResultType : 1;
- /// \brief Whether there are any array index variables stored at the end of
- /// this lambda expression.
- unsigned HasArrayIndexVars : 1;
-
/// \brief The location of the closing brace ('}') that completes
/// the lambda.
///
@@ -1537,28 +1545,19 @@ class LambdaExpr final
/// module file just to determine the source range.
SourceLocation ClosingBrace;
- size_t numTrailingObjects(OverloadToken<Stmt *>) const {
- return NumCaptures + 1;
- }
-
- size_t numTrailingObjects(OverloadToken<unsigned>) const {
- return HasArrayIndexVars ? NumCaptures + 1 : 0;
- }
-
/// \brief Construct a lambda expression.
LambdaExpr(QualType T, SourceRange IntroducerRange,
LambdaCaptureDefault CaptureDefault,
SourceLocation CaptureDefaultLoc, ArrayRef<LambdaCapture> Captures,
bool ExplicitParams, bool ExplicitResultType,
- ArrayRef<Expr *> CaptureInits, ArrayRef<VarDecl *> ArrayIndexVars,
- ArrayRef<unsigned> ArrayIndexStarts, SourceLocation ClosingBrace,
+ ArrayRef<Expr *> CaptureInits, SourceLocation ClosingBrace,
bool ContainsUnexpandedParameterPack);
/// \brief Construct an empty lambda expression.
- LambdaExpr(EmptyShell Empty, unsigned NumCaptures, bool HasArrayIndexVars)
+ LambdaExpr(EmptyShell Empty, unsigned NumCaptures)
: Expr(LambdaExprClass, Empty),
NumCaptures(NumCaptures), CaptureDefault(LCD_None), ExplicitParams(false),
- ExplicitResultType(false), HasArrayIndexVars(true) {
+ ExplicitResultType(false) {
getStoredStmts()[NumCaptures] = nullptr;
}
@@ -1566,21 +1565,6 @@ class LambdaExpr final
Stmt *const *getStoredStmts() const { return getTrailingObjects<Stmt *>(); }
- /// \brief Retrieve the mapping from captures to the first array index
- /// variable.
- unsigned *getArrayIndexStarts() { return getTrailingObjects<unsigned>(); }
-
- const unsigned *getArrayIndexStarts() const {
- return getTrailingObjects<unsigned>();
- }
-
- /// \brief Retrieve the complete set of array-index variables.
- VarDecl **getArrayIndexVars() { return getTrailingObjects<VarDecl *>(); }
-
- VarDecl *const *getArrayIndexVars() const {
- return getTrailingObjects<VarDecl *>();
- }
-
public:
/// \brief Construct a new lambda expression.
static LambdaExpr *
@@ -1588,15 +1572,12 @@ public:
LambdaCaptureDefault CaptureDefault, SourceLocation CaptureDefaultLoc,
ArrayRef<LambdaCapture> Captures, bool ExplicitParams,
bool ExplicitResultType, ArrayRef<Expr *> CaptureInits,
- ArrayRef<VarDecl *> ArrayIndexVars,
- ArrayRef<unsigned> ArrayIndexStarts, SourceLocation ClosingBrace,
- bool ContainsUnexpandedParameterPack);
+ SourceLocation ClosingBrace, bool ContainsUnexpandedParameterPack);
/// \brief Construct a new lambda expression that will be deserialized from
/// an external source.
static LambdaExpr *CreateDeserialized(const ASTContext &C,
- unsigned NumCaptures,
- unsigned NumArrayIndexVars);
+ unsigned NumCaptures);
/// \brief Determine the default capture kind for this lambda.
LambdaCaptureDefault getCaptureDefault() const {
@@ -1695,14 +1676,6 @@ public:
return capture_init_begin() + NumCaptures;
}
- /// \brief Retrieve the set of index variables used in the capture
- /// initializer of an array captured by copy.
- ///
- /// \param Iter The iterator that points at the capture initializer for
- /// which we are extracting the corresponding index variables.
- ArrayRef<VarDecl *>
- getCaptureInitIndexVars(const_capture_init_iterator Iter) const;
-
/// \brief Retrieve the source range covering the lambda introducer,
/// which contains the explicit capture list surrounded by square
/// brackets ([...]).
@@ -1828,11 +1801,13 @@ class CXXNewExpr : public Expr {
unsigned GlobalNew : 1;
/// Do we allocate an array? If so, the first SubExpr is the size expression.
unsigned Array : 1;
+ /// Should the alignment be passed to the allocation function?
+ unsigned PassAlignment : 1;
/// If this is an array allocation, does the usual deallocation
/// function for the allocated type want to know the allocated size?
unsigned UsualArrayDeleteWantsSize : 1;
/// The number of placement new arguments.
- unsigned NumPlacementArgs : 13;
+ unsigned NumPlacementArgs : 26;
/// What kind of initializer do we have? Could be none, parens, or braces.
/// In storage, we distinguish between "none, and no initializer expr", and
/// "none, but an implicit initializer expr".
@@ -1848,8 +1823,8 @@ public:
};
CXXNewExpr(const ASTContext &C, bool globalNew, FunctionDecl *operatorNew,
- FunctionDecl *operatorDelete, bool usualArrayDeleteWantsSize,
- ArrayRef<Expr*> placementArgs,
+ FunctionDecl *operatorDelete, bool PassAlignment,
+ bool usualArrayDeleteWantsSize, ArrayRef<Expr*> placementArgs,
SourceRange typeIdParens, Expr *arraySize,
InitializationStyle initializationStyle, Expr *initializer,
QualType ty, TypeSourceInfo *AllocatedTypeInfo,
@@ -1937,10 +1912,16 @@ public:
}
/// \brief Returns the CXXConstructExpr from this new-expression, or null.
- const CXXConstructExpr* getConstructExpr() const {
+ const CXXConstructExpr *getConstructExpr() const {
return dyn_cast_or_null<CXXConstructExpr>(getInitializer());
}
+ /// Indicates whether the required alignment should be implicitly passed to
+ /// the allocation function.
+ bool passAlignment() const {
+ return PassAlignment;
+ }
+
/// Answers whether the usual array deallocation function for the
/// allocated type expects the size of the allocation as a
/// parameter.
@@ -4011,6 +3992,12 @@ public:
// within a default initializer.
if (isa<FieldDecl>(ExtendingDecl))
return SD_Automatic;
+ // FIXME: This only works because storage class specifiers are not allowed
+ // on decomposition declarations.
+ if (isa<BindingDecl>(ExtendingDecl))
+ return ExtendingDecl->getDeclContext()->isFunctionOrMethod()
+ ? SD_Automatic
+ : SD_Static;
return cast<VarDecl>(ExtendingDecl)->getStorageDuration();
}
diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h
index 5f9623db2416..cd9381758618 100644
--- a/include/clang/AST/ExprObjC.h
+++ b/include/clang/AST/ExprObjC.h
@@ -90,7 +90,7 @@ public:
/// ObjCBoxedExpr - used for generalized expression boxing.
/// as in: @(strdup("hello world")), @(random()) or @(view.frame)
/// Also used for boxing non-parenthesized numeric literals;
-/// as in: @42 or \@true (c++/objc++) or \@__yes (c/objc).
+/// as in: @42 or \@true (c++/objc++) or \@__objc_yes (c/objc).
class ObjCBoxedExpr : public Expr {
Stmt *SubExpr;
ObjCMethodDecl *BoxingMethod;
diff --git a/include/clang/AST/Mangle.h b/include/clang/AST/Mangle.h
index 6e3ef9da0c3d..7a45d88c23c8 100644
--- a/include/clang/AST/Mangle.h
+++ b/include/clang/AST/Mangle.h
@@ -14,14 +14,14 @@
#ifndef LLVM_CLANG_AST_MANGLE_H
#define LLVM_CLANG_AST_MANGLE_H
-#include "clang/AST/Decl.h"
#include "clang/AST/Type.h"
#include "clang/Basic/ABI.h"
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Casting.h"
-#include "llvm/Support/raw_ostream.h"
+
+namespace llvm {
+ class raw_ostream;
+}
namespace clang {
class ASTContext;
diff --git a/include/clang/AST/MangleNumberingContext.h b/include/clang/AST/MangleNumberingContext.h
index 7a818557fdb7..869221dbf31b 100644
--- a/include/clang/AST/MangleNumberingContext.h
+++ b/include/clang/AST/MangleNumberingContext.h
@@ -16,7 +16,6 @@
#define LLVM_CLANG_AST_MANGLENUMBERINGCONTEXT_H
#include "clang/Basic/LLVM.h"
-#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
namespace clang {
@@ -30,7 +29,7 @@ class VarDecl;
/// \brief Keeps track of the mangled names of lambda expressions and block
/// literals within a particular context.
-class MangleNumberingContext : public RefCountedBase<MangleNumberingContext> {
+class MangleNumberingContext {
public:
virtual ~MangleNumberingContext() {}
diff --git a/include/clang/AST/OpenMPClause.h b/include/clang/AST/OpenMPClause.h
index 43988cd864bb..3e4c4bc7ea40 100644
--- a/include/clang/AST/OpenMPClause.h
+++ b/include/clang/AST/OpenMPClause.h
@@ -4228,50 +4228,153 @@ public:
/// 'use_device_ptr' with the variables 'a' and 'b'.
///
class OMPUseDevicePtrClause final
- : public OMPVarListClause<OMPUseDevicePtrClause>,
- private llvm::TrailingObjects<OMPUseDevicePtrClause, Expr *> {
+ : public OMPMappableExprListClause<OMPUseDevicePtrClause>,
+ private llvm::TrailingObjects<
+ OMPUseDevicePtrClause, Expr *, ValueDecl *, unsigned,
+ OMPClauseMappableExprCommon::MappableComponent> {
friend TrailingObjects;
friend OMPVarListClause;
+ friend OMPMappableExprListClause;
friend class OMPClauseReader;
- /// Build clause with number of variables \a N.
+
+ /// Define the sizes of each trailing object array except the last one. This
+ /// is required for TrailingObjects to work properly.
+ size_t numTrailingObjects(OverloadToken<Expr *>) const {
+ return 3 * varlist_size();
+ }
+ size_t numTrailingObjects(OverloadToken<ValueDecl *>) const {
+ return getUniqueDeclarationsNum();
+ }
+ size_t numTrailingObjects(OverloadToken<unsigned>) const {
+ return getUniqueDeclarationsNum() + getTotalComponentListNum();
+ }
+
+ /// Build clause with number of variables \a NumVars.
///
/// \param StartLoc Starting location of the clause.
- /// \param LParenLoc Location of '('.
/// \param EndLoc Ending location of the clause.
- /// \param N Number of the variables in the clause.
+ /// \param NumVars Number of expressions listed in this clause.
+ /// \param NumUniqueDeclarations Number of unique base declarations in this
+ /// clause.
+ /// \param NumComponentLists Number of component lists in this clause.
+ /// \param NumComponents Total number of expression components in the clause.
///
- OMPUseDevicePtrClause(SourceLocation StartLoc, SourceLocation LParenLoc,
- SourceLocation EndLoc, unsigned N)
- : OMPVarListClause<OMPUseDevicePtrClause>(OMPC_use_device_ptr, StartLoc,
- LParenLoc, EndLoc, N) {}
+ explicit OMPUseDevicePtrClause(SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc, unsigned NumVars,
+ unsigned NumUniqueDeclarations,
+ unsigned NumComponentLists,
+ unsigned NumComponents)
+ : OMPMappableExprListClause(OMPC_use_device_ptr, StartLoc, LParenLoc,
+ EndLoc, NumVars, NumUniqueDeclarations,
+ NumComponentLists, NumComponents) {}
- /// \brief Build an empty clause.
+ /// Build an empty clause.
///
- /// \param N Number of variables.
+ /// \param NumVars Number of expressions listed in this clause.
+ /// \param NumUniqueDeclarations Number of unique base declarations in this
+ /// clause.
+ /// \param NumComponentLists Number of component lists in this clause.
+ /// \param NumComponents Total number of expression components in the clause.
///
- explicit OMPUseDevicePtrClause(unsigned N)
- : OMPVarListClause<OMPUseDevicePtrClause>(
- OMPC_use_device_ptr, SourceLocation(), SourceLocation(),
- SourceLocation(), N) {}
+ explicit OMPUseDevicePtrClause(unsigned NumVars,
+ unsigned NumUniqueDeclarations,
+ unsigned NumComponentLists,
+ unsigned NumComponents)
+ : OMPMappableExprListClause(OMPC_use_device_ptr, SourceLocation(),
+ SourceLocation(), SourceLocation(), NumVars,
+ NumUniqueDeclarations, NumComponentLists,
+ NumComponents) {}
+
+ /// Sets the list of references to private copies with initializers for new
+ /// private variables.
+ /// \param VL List of references.
+ void setPrivateCopies(ArrayRef<Expr *> VL);
+
+ /// Gets the list of references to private copies with initializers for new
+ /// private variables.
+ MutableArrayRef<Expr *> getPrivateCopies() {
+ return MutableArrayRef<Expr *>(varlist_end(), varlist_size());
+ }
+ ArrayRef<const Expr *> getPrivateCopies() const {
+ return llvm::makeArrayRef(varlist_end(), varlist_size());
+ }
+
+ /// Sets the list of references to initializer variables for new private
+ /// variables.
+ /// \param VL List of references.
+ void setInits(ArrayRef<Expr *> VL);
+
+ /// Gets the list of references to initializer variables for new private
+ /// variables.
+ MutableArrayRef<Expr *> getInits() {
+ return MutableArrayRef<Expr *>(getPrivateCopies().end(), varlist_size());
+ }
+ ArrayRef<const Expr *> getInits() const {
+ return llvm::makeArrayRef(getPrivateCopies().end(), varlist_size());
+ }
public:
- /// Creates clause with a list of variables \a VL.
+ /// Creates clause with a list of variables \a Vars.
///
/// \param C AST context.
/// \param StartLoc Starting location of the clause.
- /// \param LParenLoc Location of '('.
/// \param EndLoc Ending location of the clause.
- /// \param VL List of references to the variables.
+ /// \param Vars The original expression used in the clause.
+ /// \param PrivateVars Expressions referring to private copies.
+ /// \param Inits Expressions referring to private copy initializers.
+ /// \param Declarations Declarations used in the clause.
+ /// \param ComponentLists Component lists used in the clause.
///
static OMPUseDevicePtrClause *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
- SourceLocation EndLoc, ArrayRef<Expr *> VL);
- /// Creates an empty clause with the place for \a N variables.
+ SourceLocation EndLoc, ArrayRef<Expr *> Vars,
+ ArrayRef<Expr *> PrivateVars, ArrayRef<Expr *> Inits,
+ ArrayRef<ValueDecl *> Declarations,
+ MappableExprComponentListsRef ComponentLists);
+
+ /// Creates an empty clause with the place for \a NumVars variables.
///
/// \param C AST context.
- /// \param N The number of variables.
+ /// \param NumVars Number of expressions listed in the clause.
+ /// \param NumUniqueDeclarations Number of unique base declarations in this
+ /// clause.
+ /// \param NumComponentLists Number of unique base declarations in this
+ /// clause.
+ /// \param NumComponents Total number of expression components in the clause.
///
- static OMPUseDevicePtrClause *CreateEmpty(const ASTContext &C, unsigned N);
+ static OMPUseDevicePtrClause *CreateEmpty(const ASTContext &C,
+ unsigned NumVars,
+ unsigned NumUniqueDeclarations,
+ unsigned NumComponentLists,
+ unsigned NumComponents);
+
+ typedef MutableArrayRef<Expr *>::iterator private_copies_iterator;
+ typedef ArrayRef<const Expr *>::iterator private_copies_const_iterator;
+ typedef llvm::iterator_range<private_copies_iterator> private_copies_range;
+ typedef llvm::iterator_range<private_copies_const_iterator>
+ private_copies_const_range;
+
+ private_copies_range private_copies() {
+ return private_copies_range(getPrivateCopies().begin(),
+ getPrivateCopies().end());
+ }
+ private_copies_const_range private_copies() const {
+ return private_copies_const_range(getPrivateCopies().begin(),
+ getPrivateCopies().end());
+ }
+
+ typedef MutableArrayRef<Expr *>::iterator inits_iterator;
+ typedef ArrayRef<const Expr *>::iterator inits_const_iterator;
+ typedef llvm::iterator_range<inits_iterator> inits_range;
+ typedef llvm::iterator_range<inits_const_iterator> inits_const_range;
+
+ inits_range inits() {
+ return inits_range(getInits().begin(), getInits().end());
+ }
+ inits_const_range inits() const {
+ return inits_const_range(getInits().begin(), getInits().end());
+ }
child_range children() {
return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
@@ -4293,50 +4396,94 @@ public:
/// 'is_device_ptr' with the variables 'a' and 'b'.
///
class OMPIsDevicePtrClause final
- : public OMPVarListClause<OMPIsDevicePtrClause>,
- private llvm::TrailingObjects<OMPIsDevicePtrClause, Expr *> {
+ : public OMPMappableExprListClause<OMPIsDevicePtrClause>,
+ private llvm::TrailingObjects<
+ OMPIsDevicePtrClause, Expr *, ValueDecl *, unsigned,
+ OMPClauseMappableExprCommon::MappableComponent> {
friend TrailingObjects;
friend OMPVarListClause;
+ friend OMPMappableExprListClause;
friend class OMPClauseReader;
- /// Build clause with number of variables \a N.
+
+ /// Define the sizes of each trailing object array except the last one. This
+ /// is required for TrailingObjects to work properly.
+ size_t numTrailingObjects(OverloadToken<Expr *>) const {
+ return varlist_size();
+ }
+ size_t numTrailingObjects(OverloadToken<ValueDecl *>) const {
+ return getUniqueDeclarationsNum();
+ }
+ size_t numTrailingObjects(OverloadToken<unsigned>) const {
+ return getUniqueDeclarationsNum() + getTotalComponentListNum();
+ }
+ /// Build clause with number of variables \a NumVars.
///
/// \param StartLoc Starting location of the clause.
- /// \param LParenLoc Location of '('.
/// \param EndLoc Ending location of the clause.
- /// \param N Number of the variables in the clause.
+ /// \param NumVars Number of expressions listed in this clause.
+ /// \param NumUniqueDeclarations Number of unique base declarations in this
+ /// clause.
+ /// \param NumComponentLists Number of component lists in this clause.
+ /// \param NumComponents Total number of expression components in the clause.
///
- OMPIsDevicePtrClause(SourceLocation StartLoc, SourceLocation LParenLoc,
- SourceLocation EndLoc, unsigned N)
- : OMPVarListClause<OMPIsDevicePtrClause>(OMPC_is_device_ptr, StartLoc,
- LParenLoc, EndLoc, N) {}
+ explicit OMPIsDevicePtrClause(SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc,
+ unsigned NumVars,
+ unsigned NumUniqueDeclarations,
+ unsigned NumComponentLists,
+ unsigned NumComponents)
+ : OMPMappableExprListClause(OMPC_is_device_ptr, StartLoc, LParenLoc,
+ EndLoc, NumVars, NumUniqueDeclarations,
+ NumComponentLists, NumComponents) {}
/// Build an empty clause.
///
- /// \param N Number of variables.
+ /// \param NumVars Number of expressions listed in this clause.
+ /// \param NumUniqueDeclarations Number of unique base declarations in this
+ /// clause.
+ /// \param NumComponentLists Number of component lists in this clause.
+ /// \param NumComponents Total number of expression components in the clause.
///
- explicit OMPIsDevicePtrClause(unsigned N)
- : OMPVarListClause<OMPIsDevicePtrClause>(
- OMPC_is_device_ptr, SourceLocation(), SourceLocation(),
- SourceLocation(), N) {}
+ explicit OMPIsDevicePtrClause(unsigned NumVars,
+ unsigned NumUniqueDeclarations,
+ unsigned NumComponentLists,
+ unsigned NumComponents)
+ : OMPMappableExprListClause(OMPC_is_device_ptr, SourceLocation(),
+ SourceLocation(), SourceLocation(), NumVars,
+ NumUniqueDeclarations, NumComponentLists,
+ NumComponents) {}
public:
- /// Creates clause with a list of variables \a VL.
+ /// Creates clause with a list of variables \a Vars.
///
/// \param C AST context.
/// \param StartLoc Starting location of the clause.
- /// \param LParenLoc Location of '('.
/// \param EndLoc Ending location of the clause.
- /// \param VL List of references to the variables.
+ /// \param Vars The original expression used in the clause.
+ /// \param Declarations Declarations used in the clause.
+ /// \param ComponentLists Component lists used in the clause.
///
static OMPIsDevicePtrClause *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
- SourceLocation EndLoc, ArrayRef<Expr *> VL);
- /// Creates an empty clause with the place for \a N variables.
+ SourceLocation EndLoc, ArrayRef<Expr *> Vars,
+ ArrayRef<ValueDecl *> Declarations,
+ MappableExprComponentListsRef ComponentLists);
+
+ /// Creates an empty clause with the place for \a NumVars variables.
///
/// \param C AST context.
- /// \param N The number of variables.
+ /// \param NumVars Number of expressions listed in the clause.
+ /// \param NumUniqueDeclarations Number of unique base declarations in this
+ /// clause.
+ /// \param NumComponentLists Number of unique base declarations in this
+ /// clause.
+ /// \param NumComponents Total number of expression components in the clause.
///
- static OMPIsDevicePtrClause *CreateEmpty(const ASTContext &C, unsigned N);
+ static OMPIsDevicePtrClause *CreateEmpty(const ASTContext &C,
+ unsigned NumVars,
+ unsigned NumUniqueDeclarations,
+ unsigned NumComponentLists,
+ unsigned NumComponents);
child_range children() {
return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
diff --git a/include/clang/AST/OperationKinds.def b/include/clang/AST/OperationKinds.def
index 82f494bec995..2d48a7df47b7 100644
--- a/include/clang/AST/OperationKinds.def
+++ b/include/clang/AST/OperationKinds.def
@@ -321,9 +321,14 @@ CAST_OPERATION(BuiltinFnToFnPtr)
// Convert a zero value for OpenCL event_t initialization.
CAST_OPERATION(ZeroToOCLEvent)
+// Convert a zero value for OpenCL queue_t initialization.
+CAST_OPERATION(ZeroToOCLQueue)
+
// Convert a pointer to a different address space.
CAST_OPERATION(AddressSpaceConversion)
+// Convert an integer initializer to an OpenCL sampler.
+CAST_OPERATION(IntToOCLSampler)
//===- Binary Operations -------------------------------------------------===//
// Operators listed in order of precedence.
diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h
index f918b830d421..c0b0400cb88c 100644
--- a/include/clang/AST/RecursiveASTVisitor.h
+++ b/include/clang/AST/RecursiveASTVisitor.h
@@ -14,10 +14,10 @@
#ifndef LLVM_CLANG_AST_RECURSIVEASTVISITOR_H
#define LLVM_CLANG_AST_RECURSIVEASTVISITOR_H
-#include <type_traits>
-
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/DeclarationName.h"
+#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclFriend.h"
#include "clang/AST/DeclObjC.h"
@@ -27,7 +27,9 @@
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/ExprOpenMP.h"
+#include "clang/AST/LambdaCapture.h"
#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/OpenMPClause.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
@@ -36,6 +38,15 @@
#include "clang/AST/TemplateName.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeLoc.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/OpenMPKinds.h"
+#include "clang/Basic/Specifiers.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Casting.h"
+#include <algorithm>
+#include <cstddef>
+#include <type_traits>
// The following three macros are used for meta programming. The code
// using them is responsible for defining macro OPERATOR().
@@ -70,7 +81,7 @@ namespace clang {
do { \
if (!getDerived().CALL_EXPR) \
return false; \
- } while (0)
+ } while (false)
/// \brief A class that does preordor or postorder
/// depth-first traversal on the entire Clang AST and visits each node.
@@ -264,10 +275,12 @@ public:
/// \returns false if the visitation was terminated early, true otherwise.
bool TraverseConstructorInitializer(CXXCtorInitializer *Init);
- /// \brief Recursively visit a lambda capture.
+ /// \brief 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);
+ bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C,
+ Expr *Init);
/// \brief Recursively visit the body of a lambda expression.
///
@@ -327,7 +340,7 @@ private:
do { \
if (!TRAVERSE_STMT_BASE(Stmt, Stmt, S, Queue)) \
return false; \
- } while (0)
+ } while (false)
public:
// Declare Traverse*() for all concrete Stmt classes.
@@ -355,7 +368,8 @@ public:
#define OPERATOR(NAME) \
bool TraverseUnary##NAME(UnaryOperator *S, \
DataRecursionQueue *Queue = nullptr) { \
- TRY_TO(WalkUpFromUnary##NAME(S)); \
+ if (!getDerived().shouldTraversePostOrder()) \
+ TRY_TO(WalkUpFromUnary##NAME(S)); \
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getSubExpr()); \
return true; \
} \
@@ -480,6 +494,11 @@ public:
private:
// These are helper methods used by more than one Traverse* method.
bool TraverseTemplateParameterListHelper(TemplateParameterList *TPL);
+
+ // Traverses template parameter lists of either a DeclaratorDecl or TagDecl.
+ template <typename T>
+ bool TraverseDeclTemplateParameterLists(T *D);
+
#define DEF_TRAVERSE_TMPL_INST(TMPLDECLKIND) \
bool TraverseTemplateInstantiations(TMPLDECLKIND##TemplateDecl *D);
DEF_TRAVERSE_TMPL_INST(Class)
@@ -565,7 +584,6 @@ bool RecursiveASTVisitor<Derived>::dataTraverseNode(Stmt *S,
#undef DISPATCH_STMT
-
template <typename Derived>
bool RecursiveASTVisitor<Derived>::PostVisitStmt(Stmt *S) {
switch (S->getStmtClass()) {
@@ -754,7 +772,6 @@ bool RecursiveASTVisitor<Derived>::TraverseDeclarationNameInfo(
case DeclarationName::CXXConversionFunctionName:
if (TypeSourceInfo *TSInfo = NameInfo.getNamedTypeInfo())
TRY_TO(TraverseTypeLoc(TSInfo->getTypeLoc()));
-
break;
case DeclarationName::Identifier:
@@ -869,25 +886,18 @@ bool RecursiveASTVisitor<Derived>::TraverseConstructorInitializer(
if (Init->isWritten() || getDerived().shouldVisitImplicitCode())
TRY_TO(TraverseStmt(Init->getInit()));
- if (getDerived().shouldVisitImplicitCode())
- // The braces for this one-line loop are required for MSVC2013. It
- // refuses to compile
- // for (int i : int_vec)
- // do {} while(false);
- // without braces on the for loop.
- for (VarDecl *VD : Init->getArrayIndices()) {
- TRY_TO(TraverseDecl(VD));
- }
-
return true;
}
template <typename Derived>
bool
RecursiveASTVisitor<Derived>::TraverseLambdaCapture(LambdaExpr *LE,
- const LambdaCapture *C) {
+ const LambdaCapture *C,
+ Expr *Init) {
if (LE->isInitCapture(C))
TRY_TO(TraverseDecl(C->getCapturedVar()));
+ else
+ TRY_TO(TraverseStmt(Init));
return true;
}
@@ -1034,6 +1044,8 @@ DEF_TRAVERSE_TYPE(DependentTemplateSpecializationType, {
DEF_TRAVERSE_TYPE(PackExpansionType, { TRY_TO(TraverseType(T->getPattern())); })
+DEF_TRAVERSE_TYPE(ObjCTypeParamType, {})
+
DEF_TRAVERSE_TYPE(ObjCInterfaceType, {})
DEF_TRAVERSE_TYPE(ObjCObjectType, {
@@ -1265,6 +1277,8 @@ DEF_TRAVERSE_TYPELOC(DependentTemplateSpecializationType, {
DEF_TRAVERSE_TYPELOC(PackExpansionType,
{ TRY_TO(TraverseTypeLoc(TL.getPatternLoc())); })
+DEF_TRAVERSE_TYPELOC(ObjCTypeParamType, {})
+
DEF_TRAVERSE_TYPELOC(ObjCInterfaceType, {})
DEF_TRAVERSE_TYPELOC(ObjCObjectType, {
@@ -1383,6 +1397,8 @@ DEF_TRAVERSE_DECL(ClassScopeFunctionSpecializationDecl, {
DEF_TRAVERSE_DECL(LinkageSpecDecl, {})
+DEF_TRAVERSE_DECL(ExportDecl, {})
+
DEF_TRAVERSE_DECL(ObjCPropertyImplDecl, {// FIXME: implement this
})
@@ -1489,6 +1505,8 @@ DEF_TRAVERSE_DECL(UsingDecl, {
TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo()));
})
+DEF_TRAVERSE_DECL(UsingPackDecl, {})
+
DEF_TRAVERSE_DECL(UsingDirectiveDecl, {
TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
})
@@ -1527,6 +1545,16 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateParameterListHelper(
}
template <typename Derived>
+template <typename T>
+bool RecursiveASTVisitor<Derived>::TraverseDeclTemplateParameterLists(T *D) {
+ for (unsigned i = 0; i < D->getNumTemplateParameterLists(); i++) {
+ TemplateParameterList *TPL = D->getTemplateParameterList(i);
+ TraverseTemplateParameterListHelper(TPL);
+ }
+ return true;
+}
+
+template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseTemplateInstantiations(
ClassTemplateDecl *D) {
for (auto *SD : D->specializations()) {
@@ -1687,6 +1715,8 @@ DEF_TRAVERSE_DECL(UnresolvedUsingTypenameDecl, {
})
DEF_TRAVERSE_DECL(EnumDecl, {
+ TRY_TO(TraverseDeclTemplateParameterLists(D));
+
if (D->getTypeForDecl())
TRY_TO(TraverseType(QualType(D->getTypeForDecl(), 0)));
@@ -1701,6 +1731,7 @@ bool RecursiveASTVisitor<Derived>::TraverseRecordHelper(RecordDecl *D) {
// We shouldn't traverse D->getTypeForDecl(); it's a result of
// declaring the type, not something that was written in the source.
+ TRY_TO(TraverseDeclTemplateParameterLists(D));
TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
return true;
}
@@ -1795,6 +1826,7 @@ DEF_TRAVERSE_DECL(IndirectFieldDecl, {})
template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseDeclaratorHelper(DeclaratorDecl *D) {
+ TRY_TO(TraverseDeclTemplateParameterLists(D));
TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
if (D->getTypeSourceInfo())
TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
@@ -1803,6 +1835,18 @@ bool RecursiveASTVisitor<Derived>::TraverseDeclaratorHelper(DeclaratorDecl *D) {
return true;
}
+DEF_TRAVERSE_DECL(DecompositionDecl, {
+ TRY_TO(TraverseVarHelper(D));
+ for (auto *Binding : D->bindings()) {
+ TRY_TO(TraverseDecl(Binding));
+ }
+})
+
+DEF_TRAVERSE_DECL(BindingDecl, {
+ if (getDerived().shouldVisitImplicitCode())
+ TRY_TO(TraverseStmt(D->getBinding()));
+})
+
DEF_TRAVERSE_DECL(MSPropertyDecl, { TRY_TO(TraverseDeclaratorHelper(D)); })
DEF_TRAVERSE_DECL(FieldDecl, {
@@ -1829,6 +1873,7 @@ DEF_TRAVERSE_DECL(ObjCIvarDecl, {
template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) {
+ TRY_TO(TraverseDeclTemplateParameterLists(D));
TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo()));
@@ -2041,6 +2086,7 @@ DEF_TRAVERSE_STMT(ObjCAtThrowStmt, {})
DEF_TRAVERSE_STMT(ObjCAtTryStmt, {})
DEF_TRAVERSE_STMT(ObjCForCollectionStmt, {})
DEF_TRAVERSE_STMT(ObjCAutoreleasePoolStmt, {})
+
DEF_TRAVERSE_STMT(CXXForRangeStmt, {
if (!getDerived().shouldVisitImplicitCode()) {
TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getLoopVarStmt());
@@ -2050,10 +2096,12 @@ DEF_TRAVERSE_STMT(CXXForRangeStmt, {
ShouldVisitChildren = false;
}
})
+
DEF_TRAVERSE_STMT(MSDependentExistsStmt, {
TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
TRY_TO(TraverseDeclarationNameInfo(S->getNameInfo()));
})
+
DEF_TRAVERSE_STMT(ReturnStmt, {})
DEF_TRAVERSE_STMT(SwitchStmt, {})
DEF_TRAVERSE_STMT(WhileStmt, {})
@@ -2249,10 +2297,11 @@ DEF_TRAVERSE_STMT(CXXTemporaryObjectExpr, {
// Walk only the visible parts of lambda expressions.
DEF_TRAVERSE_STMT(LambdaExpr, {
- for (LambdaExpr::capture_iterator C = S->explicit_capture_begin(),
- CEnd = S->explicit_capture_end();
- C != CEnd; ++C) {
- TRY_TO(TraverseLambdaCapture(S, C));
+ for (unsigned I = 0, N = S->capture_size(); I != N; ++I) {
+ const LambdaCapture *C = S->capture_begin() + I;
+ if (C->isExplicit() || getDerived().shouldVisitImplicitCode()) {
+ TRY_TO(TraverseLambdaCapture(S, C, S->capture_init_begin()[I]));
+ }
}
TypeLoc TL = S->getCallOperator()->getTypeSourceInfo()->getTypeLoc();
@@ -2300,23 +2349,31 @@ DEF_TRAVERSE_STMT(CXXMemberCallExpr, {})
DEF_TRAVERSE_STMT(AddrLabelExpr, {})
DEF_TRAVERSE_STMT(ArraySubscriptExpr, {})
DEF_TRAVERSE_STMT(OMPArraySectionExpr, {})
+
DEF_TRAVERSE_STMT(BlockExpr, {
TRY_TO(TraverseDecl(S->getBlockDecl()));
return true; // no child statements to loop through.
})
+
DEF_TRAVERSE_STMT(ChooseExpr, {})
DEF_TRAVERSE_STMT(CompoundLiteralExpr, {
TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc()));
})
DEF_TRAVERSE_STMT(CXXBindTemporaryExpr, {})
DEF_TRAVERSE_STMT(CXXBoolLiteralExpr, {})
-DEF_TRAVERSE_STMT(CXXDefaultArgExpr, {})
+
+DEF_TRAVERSE_STMT(CXXDefaultArgExpr, {
+ if (getDerived().shouldVisitImplicitCode())
+ TRY_TO(TraverseStmt(S->getExpr()));
+})
+
DEF_TRAVERSE_STMT(CXXDefaultInitExpr, {})
DEF_TRAVERSE_STMT(CXXDeleteExpr, {})
DEF_TRAVERSE_STMT(ExprWithCleanups, {})
DEF_TRAVERSE_STMT(CXXInheritedCtorInitExpr, {})
DEF_TRAVERSE_STMT(CXXNullPtrLiteralExpr, {})
DEF_TRAVERSE_STMT(CXXStdInitializerListExpr, {})
+
DEF_TRAVERSE_STMT(CXXPseudoDestructorExpr, {
TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
if (TypeSourceInfo *ScopeInfo = S->getScopeTypeInfo())
@@ -2324,6 +2381,7 @@ DEF_TRAVERSE_STMT(CXXPseudoDestructorExpr, {
if (TypeSourceInfo *DestroyedTypeInfo = S->getDestroyedTypeInfo())
TRY_TO(TraverseTypeLoc(DestroyedTypeInfo->getTypeLoc()));
})
+
DEF_TRAVERSE_STMT(CXXThisExpr, {})
DEF_TRAVERSE_STMT(CXXThrowExpr, {})
DEF_TRAVERSE_STMT(UserDefinedLiteral, {})
@@ -2333,25 +2391,38 @@ DEF_TRAVERSE_STMT(ExtVectorElementExpr, {})
DEF_TRAVERSE_STMT(GNUNullExpr, {})
DEF_TRAVERSE_STMT(ImplicitValueInitExpr, {})
DEF_TRAVERSE_STMT(NoInitExpr, {})
+DEF_TRAVERSE_STMT(ArrayInitLoopExpr, {
+ // FIXME: The source expression of the OVE should be listed as
+ // a child of the ArrayInitLoopExpr.
+ if (OpaqueValueExpr *OVE = S->getCommonExpr())
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(OVE->getSourceExpr());
+})
+DEF_TRAVERSE_STMT(ArrayInitIndexExpr, {})
DEF_TRAVERSE_STMT(ObjCBoolLiteralExpr, {})
+
DEF_TRAVERSE_STMT(ObjCEncodeExpr, {
if (TypeSourceInfo *TInfo = S->getEncodedTypeSourceInfo())
TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc()));
})
+
DEF_TRAVERSE_STMT(ObjCIsaExpr, {})
DEF_TRAVERSE_STMT(ObjCIvarRefExpr, {})
+
DEF_TRAVERSE_STMT(ObjCMessageExpr, {
if (TypeSourceInfo *TInfo = S->getClassReceiverTypeInfo())
TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc()));
})
+
DEF_TRAVERSE_STMT(ObjCPropertyRefExpr, {})
DEF_TRAVERSE_STMT(ObjCSubscriptRefExpr, {})
DEF_TRAVERSE_STMT(ObjCProtocolExpr, {})
DEF_TRAVERSE_STMT(ObjCSelectorExpr, {})
DEF_TRAVERSE_STMT(ObjCIndirectCopyRestoreExpr, {})
+
DEF_TRAVERSE_STMT(ObjCBridgedCastExpr, {
TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
})
+
DEF_TRAVERSE_STMT(ObjCAvailabilityCheckExpr, {})
DEF_TRAVERSE_STMT(ParenExpr, {})
DEF_TRAVERSE_STMT(ParenListExpr, {})
@@ -2574,6 +2645,30 @@ DEF_TRAVERSE_STMT(OMPDistributeSimdDirective,
DEF_TRAVERSE_STMT(OMPTargetParallelForSimdDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
+DEF_TRAVERSE_STMT(OMPTargetSimdDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPTeamsDistributeDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPTeamsDistributeSimdDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPTeamsDistributeParallelForSimdDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPTeamsDistributeParallelForDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPTargetTeamsDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPTargetTeamsDistributeDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPTargetTeamsDistributeParallelForDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
// OpenMP clauses.
template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) {
diff --git a/include/clang/AST/Redeclarable.h b/include/clang/AST/Redeclarable.h
index eaa22f8d0102..cd5f186a2086 100644
--- a/include/clang/AST/Redeclarable.h
+++ b/include/clang/AST/Redeclarable.h
@@ -15,7 +15,6 @@
#define LLVM_CLANG_AST_REDECLARABLE_H
#include "clang/AST/ExternalASTSource.h"
-#include "llvm/ADT/PointerIntPair.h"
#include "llvm/Support/Casting.h"
#include <iterator>
@@ -280,6 +279,68 @@ public:
bool isFirstDecl() const { return getFirstDecl() == this; }
};
-}
+/// A wrapper class around a pointer that always points to its canonical
+/// declaration.
+///
+/// CanonicalDeclPtr<decl_type> behaves just like decl_type*, except we call
+/// decl_type::getCanonicalDecl() on construction.
+///
+/// This is useful for hashtables that you want to be keyed on a declaration's
+/// canonical decl -- if you use CanonicalDeclPtr as the key, you don't need to
+/// remember to call getCanonicalDecl() everywhere.
+template <typename decl_type> class CanonicalDeclPtr {
+public:
+ CanonicalDeclPtr() : Ptr(nullptr) {}
+ CanonicalDeclPtr(decl_type *Ptr)
+ : Ptr(Ptr ? Ptr->getCanonicalDecl() : nullptr) {}
+ CanonicalDeclPtr(const CanonicalDeclPtr &) = default;
+ CanonicalDeclPtr &operator=(const CanonicalDeclPtr &) = default;
+
+ operator decl_type *() { return Ptr; }
+ operator const decl_type *() const { return Ptr; }
+
+ decl_type *operator->() { return Ptr; }
+ const decl_type *operator->() const { return Ptr; }
+
+ decl_type &operator*() { return *Ptr; }
+ const decl_type &operator*() const { return *Ptr; }
+
+private:
+ friend struct llvm::DenseMapInfo<CanonicalDeclPtr<decl_type>>;
+
+ decl_type *Ptr;
+};
+} // namespace clang
+
+namespace llvm {
+template <typename decl_type>
+struct DenseMapInfo<clang::CanonicalDeclPtr<decl_type>> {
+ using CanonicalDeclPtr = clang::CanonicalDeclPtr<decl_type>;
+ using BaseInfo = DenseMapInfo<decl_type *>;
+
+ static CanonicalDeclPtr getEmptyKey() {
+ // Construct our CanonicalDeclPtr this way because the regular constructor
+ // would dereference P.Ptr, which is not allowed.
+ CanonicalDeclPtr P;
+ P.Ptr = BaseInfo::getEmptyKey();
+ return P;
+ }
+
+ static CanonicalDeclPtr getTombstoneKey() {
+ CanonicalDeclPtr P;
+ P.Ptr = BaseInfo::getTombstoneKey();
+ return P;
+ }
+
+ static unsigned getHashValue(const CanonicalDeclPtr &P) {
+ return BaseInfo::getHashValue(P);
+ }
+
+ static bool isEqual(const CanonicalDeclPtr &LHS,
+ const CanonicalDeclPtr &RHS) {
+ return BaseInfo::isEqual(LHS, RHS);
+ }
+};
+} // namespace llvm
#endif
diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h
index 96847cf88f96..e28675d6a828 100644
--- a/include/clang/AST/Stmt.h
+++ b/include/clang/AST/Stmt.h
@@ -56,7 +56,7 @@ namespace clang {
/// Stmt - This represents one statement.
///
-class LLVM_ALIGNAS(LLVM_PTR_SIZE) Stmt {
+class alignas(void *) Stmt {
public:
enum StmtClass {
NoStmtClass = 0,
@@ -71,10 +71,10 @@ public:
// Make vanilla 'new' and 'delete' illegal for Stmts.
protected:
- void *operator new(size_t bytes) LLVM_NOEXCEPT {
+ void *operator new(size_t bytes) noexcept {
llvm_unreachable("Stmts cannot be allocated with regular 'new'.");
}
- void operator delete(void *data) LLVM_NOEXCEPT {
+ void operator delete(void *data) noexcept {
llvm_unreachable("Stmts cannot be released with regular 'delete'.");
}
@@ -284,12 +284,12 @@ public:
return operator new(bytes, *C, alignment);
}
- void *operator new(size_t bytes, void *mem) LLVM_NOEXCEPT { return mem; }
+ void *operator new(size_t bytes, void *mem) noexcept { return mem; }
- void operator delete(void *, const ASTContext &, unsigned) LLVM_NOEXCEPT {}
- void operator delete(void *, const ASTContext *, unsigned) LLVM_NOEXCEPT {}
- void operator delete(void *, size_t) LLVM_NOEXCEPT {}
- void operator delete(void *, void *) LLVM_NOEXCEPT {}
+ void operator delete(void *, const ASTContext &, unsigned) noexcept {}
+ void operator delete(void *, const ASTContext *, unsigned) noexcept {}
+ void operator delete(void *, size_t) noexcept {}
+ void operator delete(void *, void *) noexcept {}
public:
/// \brief A placeholder type used to construct an empty shell of a
@@ -340,7 +340,7 @@ protected:
public:
Stmt(StmtClass SC) {
- static_assert(sizeof(*this) % llvm::AlignOf<void *>::Alignment == 0,
+ static_assert(sizeof(*this) % alignof(void *) == 0,
"Insufficient alignment!");
StmtBits.sClass = SC;
if (StatisticsEnabled) Stmt::addStmtClass(SC);
@@ -387,6 +387,9 @@ public:
/// Skip past any implicit AST nodes which might surround this
/// statement, such as ExprWithCleanups or ImplicitCastExpr nodes.
Stmt *IgnoreImplicit();
+ const Stmt *IgnoreImplicit() const {
+ return const_cast<Stmt *>(this)->IgnoreImplicit();
+ }
/// \brief Skip no-op (attributed, compound) container stmts and skip captured
/// stmt at the top, if \a IgnoreCaptured is true.
@@ -933,6 +936,8 @@ public:
bool isConstexpr() const { return IfStmtBits.IsConstexpr; }
void setConstexpr(bool C) { IfStmtBits.IsConstexpr = C; }
+ bool isObjCAvailabilityCheck() const;
+
SourceLocation getLocStart() const LLVM_READONLY { return IfLoc; }
SourceLocation getLocEnd() const LLVM_READONLY {
if (SubExprs[ELSE])
diff --git a/include/clang/AST/StmtCXX.h b/include/clang/AST/StmtCXX.h
index 1d29c228a4b3..8eef34cb21b3 100644
--- a/include/clang/AST/StmtCXX.h
+++ b/include/clang/AST/StmtCXX.h
@@ -304,6 +304,8 @@ class CoroutineBodyStmt : public Stmt {
FinalSuspend, ///< The final suspend statement, run after the body.
OnException, ///< Handler for exceptions thrown in the body.
OnFallthrough, ///< Handler for control flow falling off the body.
+ Allocate, ///< Coroutine frame memory allocation.
+ Deallocate, ///< Coroutine frame memory deallocation.
ReturnValue, ///< Return value for thunk function.
FirstParamMove ///< First offset for move construction of parameter copies.
};
@@ -313,6 +315,7 @@ class CoroutineBodyStmt : public Stmt {
public:
CoroutineBodyStmt(Stmt *Body, Stmt *Promise, Stmt *InitSuspend,
Stmt *FinalSuspend, Stmt *OnException, Stmt *OnFallthrough,
+ Expr *Allocate, Stmt *Deallocate,
Expr *ReturnValue, ArrayRef<Expr *> ParamMoves)
: Stmt(CoroutineBodyStmtClass) {
SubStmts[CoroutineBodyStmt::Body] = Body;
@@ -321,6 +324,8 @@ public:
SubStmts[CoroutineBodyStmt::FinalSuspend] = FinalSuspend;
SubStmts[CoroutineBodyStmt::OnException] = OnException;
SubStmts[CoroutineBodyStmt::OnFallthrough] = OnFallthrough;
+ SubStmts[CoroutineBodyStmt::Allocate] = Allocate;
+ SubStmts[CoroutineBodyStmt::Deallocate] = Deallocate;
SubStmts[CoroutineBodyStmt::ReturnValue] = ReturnValue;
// FIXME: Tail-allocate space for parameter move expressions and store them.
assert(ParamMoves.empty() && "not implemented yet");
@@ -345,6 +350,9 @@ public:
return SubStmts[SubStmt::OnFallthrough];
}
+ Expr *getAllocate() const { return cast<Expr>(SubStmts[SubStmt::Allocate]); }
+ Stmt *getDeallocate() const { return SubStmts[SubStmt::Deallocate]; }
+
Expr *getReturnValueInit() const {
return cast<Expr>(SubStmts[SubStmt::ReturnValue]);
}
@@ -405,10 +413,13 @@ public:
SourceLocation getLocStart() const LLVM_READONLY { return CoreturnLoc; }
SourceLocation getLocEnd() const LLVM_READONLY {
- return getOperand()->getLocEnd();
+ return getOperand() ? getOperand()->getLocEnd() : getLocStart();
}
child_range children() {
+ if (!getOperand())
+ return child_range(SubStmts + SubStmt::PromiseCall,
+ SubStmts + SubStmt::Count);
return child_range(SubStmts, SubStmts + SubStmt::Count);
}
diff --git a/include/clang/AST/StmtGraphTraits.h b/include/clang/AST/StmtGraphTraits.h
index dac4495c6a0f..92eb64430f73 100644
--- a/include/clang/AST/StmtGraphTraits.h
+++ b/include/clang/AST/StmtGraphTraits.h
@@ -25,19 +25,18 @@ namespace llvm {
template <> struct GraphTraits<clang::Stmt*> {
- typedef clang::Stmt NodeType;
typedef clang::Stmt * NodeRef;
typedef clang::Stmt::child_iterator ChildIteratorType;
typedef llvm::df_iterator<clang::Stmt*> nodes_iterator;
- static NodeType* getEntryNode(clang::Stmt* S) { return S; }
+ static NodeRef getEntryNode(clang::Stmt *S) { return S; }
- static inline ChildIteratorType child_begin(NodeType* N) {
+ static ChildIteratorType child_begin(NodeRef N) {
if (N) return N->child_begin();
else return ChildIteratorType();
}
- static inline ChildIteratorType child_end(NodeType* N) {
+ static ChildIteratorType child_end(NodeRef N) {
if (N) return N->child_end();
else return ChildIteratorType();
}
@@ -53,19 +52,18 @@ template <> struct GraphTraits<clang::Stmt*> {
template <> struct GraphTraits<const clang::Stmt*> {
- typedef const clang::Stmt NodeType;
typedef const clang::Stmt * NodeRef;
typedef clang::Stmt::const_child_iterator ChildIteratorType;
typedef llvm::df_iterator<const clang::Stmt*> nodes_iterator;
- static NodeType* getEntryNode(const clang::Stmt* S) { return S; }
+ static NodeRef getEntryNode(const clang::Stmt *S) { return S; }
- static inline ChildIteratorType child_begin(NodeType* N) {
+ static ChildIteratorType child_begin(NodeRef N) {
if (N) return N->child_begin();
else return ChildIteratorType();
}
- static inline ChildIteratorType child_end(NodeType* N) {
+ static ChildIteratorType child_end(NodeRef N) {
if (N) return N->child_end();
else return ChildIteratorType();
}
diff --git a/include/clang/AST/StmtOpenMP.h b/include/clang/AST/StmtOpenMP.h
index 1e357263461e..80300dae80df 100644
--- a/include/clang/AST/StmtOpenMP.h
+++ b/include/clang/AST/StmtOpenMP.h
@@ -70,7 +70,7 @@ protected:
: Stmt(SC), Kind(K), StartLoc(std::move(StartLoc)),
EndLoc(std::move(EndLoc)), NumClauses(NumClauses),
NumChildren(NumChildren),
- ClausesOffset(llvm::alignTo(sizeof(T), llvm::alignOf<OMPClause *>())) {}
+ ClausesOffset(llvm::alignTo(sizeof(T), alignof(OMPClause *))) {}
/// \brief Sets the list of variables for this clause.
///
@@ -773,7 +773,12 @@ public:
T->getStmtClass() == OMPDistributeParallelForDirectiveClass ||
T->getStmtClass() == OMPDistributeParallelForSimdDirectiveClass ||
T->getStmtClass() == OMPDistributeSimdDirectiveClass ||
- T->getStmtClass() == OMPTargetParallelForSimdDirectiveClass;
+ T->getStmtClass() == OMPTargetParallelForSimdDirectiveClass ||
+ T->getStmtClass() == OMPTargetSimdDirectiveClass ||
+ T->getStmtClass() == OMPTeamsDistributeDirectiveClass ||
+ T->getStmtClass() == OMPTeamsDistributeSimdDirectiveClass ||
+ T->getStmtClass() == OMPTeamsDistributeParallelForSimdDirectiveClass ||
+ T->getStmtClass() == OMPTeamsDistributeParallelForDirectiveClass;
}
};
@@ -3090,6 +3095,549 @@ public:
}
};
+/// This represents '#pragma omp target simd' directive.
+///
+/// \code
+/// #pragma omp target simd private(a) map(b) safelen(c)
+/// \endcode
+/// In this example directive '#pragma omp target simd' has clauses 'private'
+/// with the variable 'a', 'map' with the variable 'b' and 'safelen' with
+/// the variable 'c'.
+///
+class OMPTargetSimdDirective final : public OMPLoopDirective {
+ friend class ASTStmtReader;
+
+ /// Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ OMPTargetSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, unsigned NumClauses)
+ : OMPLoopDirective(this, OMPTargetSimdDirectiveClass,
+ OMPD_target_simd, StartLoc, EndLoc, CollapsedNum,
+ NumClauses) {}
+
+ /// Build an empty directive.
+ ///
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPTargetSimdDirective(unsigned CollapsedNum, unsigned NumClauses)
+ : OMPLoopDirective(this, OMPTargetSimdDirectiveClass, OMPD_target_simd,
+ SourceLocation(),SourceLocation(), CollapsedNum,
+ NumClauses) {}
+
+public:
+ /// Creates directive with a list of \a Clauses.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param CollapsedNum Number of collapsed loops.
+ /// \param Clauses List of clauses.
+ /// \param AssociatedStmt Statement, associated with the directive.
+ /// \param Exprs Helper expressions for CodeGen.
+ ///
+ static OMPTargetSimdDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt, const HelperExprs &Exprs);
+
+ /// Creates an empty directive with the place for \a NumClauses clauses.
+ ///
+ /// \param C AST context.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ static OMPTargetSimdDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ unsigned CollapsedNum,
+ EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPTargetSimdDirectiveClass;
+ }
+};
+
+/// This represents '#pragma omp teams distribute' directive.
+///
+/// \code
+/// #pragma omp teams distribute private(a,b)
+/// \endcode
+/// In this example directive '#pragma omp teams distribute' has clauses
+/// 'private' with the variables 'a' and 'b'
+///
+class OMPTeamsDistributeDirective final : public OMPLoopDirective {
+ friend class ASTStmtReader;
+
+ /// Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ OMPTeamsDistributeDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, unsigned NumClauses)
+ : OMPLoopDirective(this, OMPTeamsDistributeDirectiveClass,
+ OMPD_teams_distribute, StartLoc, EndLoc,
+ CollapsedNum, NumClauses) {}
+
+ /// Build an empty directive.
+ ///
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPTeamsDistributeDirective(unsigned CollapsedNum,
+ unsigned NumClauses)
+ : OMPLoopDirective(this, OMPTeamsDistributeDirectiveClass,
+ OMPD_teams_distribute, SourceLocation(),
+ SourceLocation(), CollapsedNum, NumClauses) {}
+
+public:
+ /// Creates directive with a list of \a Clauses.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param CollapsedNum Number of collapsed loops.
+ /// \param Clauses List of clauses.
+ /// \param AssociatedStmt Statement, associated with the directive.
+ /// \param Exprs Helper expressions for CodeGen.
+ ///
+ static OMPTeamsDistributeDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt, const HelperExprs &Exprs);
+
+ /// Creates an empty directive with the place for \a NumClauses clauses.
+ ///
+ /// \param C AST context.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ static OMPTeamsDistributeDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ unsigned CollapsedNum,
+ EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPTeamsDistributeDirectiveClass;
+ }
+};
+
+/// This represents '#pragma omp teams distribute simd'
+/// combined directive.
+///
+/// \code
+/// #pragma omp teams distribute simd private(a,b)
+/// \endcode
+/// In this example directive '#pragma omp teams distribute simd'
+/// has clause 'private' with the variables 'a' and 'b'
+///
+class OMPTeamsDistributeSimdDirective final : public OMPLoopDirective {
+ friend class ASTStmtReader;
+
+ /// Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ OMPTeamsDistributeSimdDirective(SourceLocation StartLoc,
+ SourceLocation EndLoc, unsigned CollapsedNum,
+ unsigned NumClauses)
+ : OMPLoopDirective(this, OMPTeamsDistributeSimdDirectiveClass,
+ OMPD_teams_distribute_simd, StartLoc, EndLoc,
+ CollapsedNum, NumClauses) {}
+
+ /// Build an empty directive.
+ ///
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPTeamsDistributeSimdDirective(unsigned CollapsedNum,
+ unsigned NumClauses)
+ : OMPLoopDirective(this, OMPTeamsDistributeSimdDirectiveClass,
+ OMPD_teams_distribute_simd, SourceLocation(),
+ SourceLocation(), CollapsedNum, NumClauses) {}
+
+public:
+ /// Creates directive with a list of \a Clauses.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param CollapsedNum Number of collapsed loops.
+ /// \param Clauses List of clauses.
+ /// \param AssociatedStmt Statement, associated with the directive.
+ /// \param Exprs Helper expressions for CodeGen.
+ ///
+ static OMPTeamsDistributeSimdDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt, const HelperExprs &Exprs);
+
+ /// Creates an empty directive with the place
+ /// for \a NumClauses clauses.
+ ///
+ /// \param C AST context.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ static OMPTeamsDistributeSimdDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ unsigned CollapsedNum,
+ EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPTeamsDistributeSimdDirectiveClass;
+ }
+};
+
+/// This represents '#pragma omp teams distribute parallel for simd' composite
+/// directive.
+///
+/// \code
+/// #pragma omp teams distribute parallel for simd private(x)
+/// \endcode
+/// In this example directive '#pragma omp teams distribute parallel for simd'
+/// has clause 'private' with the variables 'x'
+///
+class OMPTeamsDistributeParallelForSimdDirective final
+ : public OMPLoopDirective {
+ friend class ASTStmtReader;
+
+ /// Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ OMPTeamsDistributeParallelForSimdDirective(SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ unsigned CollapsedNum,
+ unsigned NumClauses)
+ : OMPLoopDirective(this, OMPTeamsDistributeParallelForSimdDirectiveClass,
+ OMPD_teams_distribute_parallel_for_simd, StartLoc,
+ EndLoc, CollapsedNum, NumClauses) {}
+
+ /// Build an empty directive.
+ ///
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPTeamsDistributeParallelForSimdDirective(unsigned CollapsedNum,
+ unsigned NumClauses)
+ : OMPLoopDirective(this, OMPTeamsDistributeParallelForSimdDirectiveClass,
+ OMPD_teams_distribute_parallel_for_simd,
+ SourceLocation(), SourceLocation(), CollapsedNum,
+ NumClauses) {}
+
+public:
+ /// Creates directive with a list of \a Clauses.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param CollapsedNum Number of collapsed loops.
+ /// \param Clauses List of clauses.
+ /// \param AssociatedStmt Statement, associated with the directive.
+ /// \param Exprs Helper expressions for CodeGen.
+ ///
+ static OMPTeamsDistributeParallelForSimdDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt, const HelperExprs &Exprs);
+
+ /// Creates an empty directive with the place for \a NumClauses clauses.
+ ///
+ /// \param C AST context.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ static OMPTeamsDistributeParallelForSimdDirective *
+ CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
+ EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPTeamsDistributeParallelForSimdDirectiveClass;
+ }
+};
+
+/// This represents '#pragma omp teams distribute parallel for' composite
+/// directive.
+///
+/// \code
+/// #pragma omp teams distribute parallel for private(x)
+/// \endcode
+/// In this example directive '#pragma omp teams distribute parallel for'
+/// has clause 'private' with the variables 'x'
+///
+class OMPTeamsDistributeParallelForDirective final : public OMPLoopDirective {
+ friend class ASTStmtReader;
+
+ /// Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ OMPTeamsDistributeParallelForDirective(SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ unsigned CollapsedNum,
+ unsigned NumClauses)
+ : OMPLoopDirective(this, OMPTeamsDistributeParallelForDirectiveClass,
+ OMPD_teams_distribute_parallel_for, StartLoc, EndLoc,
+ CollapsedNum, NumClauses) {}
+
+ /// Build an empty directive.
+ ///
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPTeamsDistributeParallelForDirective(unsigned CollapsedNum,
+ unsigned NumClauses)
+ : OMPLoopDirective(this, OMPTeamsDistributeParallelForDirectiveClass,
+ OMPD_teams_distribute_parallel_for, SourceLocation(),
+ SourceLocation(), CollapsedNum, NumClauses) {}
+
+public:
+ /// Creates directive with a list of \a Clauses.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param CollapsedNum Number of collapsed loops.
+ /// \param Clauses List of clauses.
+ /// \param AssociatedStmt Statement, associated with the directive.
+ /// \param Exprs Helper expressions for CodeGen.
+ ///
+ static OMPTeamsDistributeParallelForDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt, const HelperExprs &Exprs);
+
+ /// Creates an empty directive with the place for \a NumClauses clauses.
+ ///
+ /// \param C AST context.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ static OMPTeamsDistributeParallelForDirective *
+ CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
+ EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPTeamsDistributeParallelForDirectiveClass;
+ }
+};
+
+/// This represents '#pragma omp target teams' directive.
+///
+/// \code
+/// #pragma omp target teams if(a>0)
+/// \endcode
+/// In this example directive '#pragma omp target teams' has clause 'if' with
+/// condition 'a>0'.
+///
+class OMPTargetTeamsDirective final : public OMPExecutableDirective {
+ friend class ASTStmtReader;
+ /// Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ /// \param NumClauses Number of clauses.
+ ///
+ OMPTargetTeamsDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPTargetTeamsDirectiveClass,
+ OMPD_target_teams, StartLoc, EndLoc, NumClauses,
+ 1) {}
+
+ /// Build an empty directive.
+ ///
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPTargetTeamsDirective(unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPTargetTeamsDirectiveClass,
+ OMPD_target_teams, SourceLocation(),
+ SourceLocation(), NumClauses, 1) {}
+
+public:
+ /// Creates directive with a list of \a Clauses.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param Clauses List of clauses.
+ /// \param AssociatedStmt Statement, associated with the directive.
+ ///
+ static OMPTargetTeamsDirective *Create(const ASTContext &C,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt);
+
+ /// Creates an empty directive with the place for \a NumClauses clauses.
+ ///
+ /// \param C AST context.
+ /// \param NumClauses Number of clauses.
+ ///
+ static OMPTargetTeamsDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses, EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPTargetTeamsDirectiveClass;
+ }
+};
+
+/// This represents '#pragma omp target teams distribute' combined directive.
+///
+/// \code
+/// #pragma omp target teams distribute private(x)
+/// \endcode
+/// In this example directive '#pragma omp target teams distribute' has clause
+/// 'private' with the variables 'x'
+///
+class OMPTargetTeamsDistributeDirective final : public OMPLoopDirective {
+ friend class ASTStmtReader;
+
+ /// Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ OMPTargetTeamsDistributeDirective(SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ unsigned CollapsedNum, unsigned NumClauses)
+ : OMPLoopDirective(this, OMPTargetTeamsDistributeDirectiveClass,
+ OMPD_target_teams_distribute, StartLoc, EndLoc,
+ CollapsedNum, NumClauses) {}
+
+ /// Build an empty directive.
+ ///
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPTargetTeamsDistributeDirective(unsigned CollapsedNum,
+ unsigned NumClauses)
+ : OMPLoopDirective(this, OMPTargetTeamsDistributeDirectiveClass,
+ OMPD_target_teams_distribute, SourceLocation(),
+ SourceLocation(), CollapsedNum, NumClauses) {}
+
+public:
+ /// Creates directive with a list of \a Clauses.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param CollapsedNum Number of collapsed loops.
+ /// \param Clauses List of clauses.
+ /// \param AssociatedStmt Statement, associated with the directive.
+ /// \param Exprs Helper expressions for CodeGen.
+ ///
+ static OMPTargetTeamsDistributeDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt, const HelperExprs &Exprs);
+
+ /// Creates an empty directive with the place for \a NumClauses clauses.
+ ///
+ /// \param C AST context.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ static OMPTargetTeamsDistributeDirective *
+ CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
+ EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPTargetTeamsDistributeDirectiveClass;
+ }
+};
+
+/// This represents '#pragma omp target teams distribute parallel for' combined
+/// directive.
+///
+/// \code
+/// #pragma omp target teams distribute parallel for private(x)
+/// \endcode
+/// In this example directive '#pragma omp target teams distribute parallel
+/// for' has clause 'private' with the variables 'x'
+///
+class OMPTargetTeamsDistributeParallelForDirective final
+ : public OMPLoopDirective {
+ friend class ASTStmtReader;
+
+ /// Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ OMPTargetTeamsDistributeParallelForDirective(SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ unsigned CollapsedNum,
+ unsigned NumClauses)
+ : OMPLoopDirective(this,
+ OMPTargetTeamsDistributeParallelForDirectiveClass,
+ OMPD_target_teams_distribute_parallel_for, StartLoc,
+ EndLoc, CollapsedNum, NumClauses) {}
+
+ /// Build an empty directive.
+ ///
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPTargetTeamsDistributeParallelForDirective(unsigned CollapsedNum,
+ unsigned NumClauses)
+ : OMPLoopDirective(
+ this, OMPTargetTeamsDistributeParallelForDirectiveClass,
+ OMPD_target_teams_distribute_parallel_for, SourceLocation(),
+ SourceLocation(), CollapsedNum, NumClauses) {}
+
+public:
+ /// Creates directive with a list of \a Clauses.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param CollapsedNum Number of collapsed loops.
+ /// \param Clauses List of clauses.
+ /// \param AssociatedStmt Statement, associated with the directive.
+ /// \param Exprs Helper expressions for CodeGen.
+ ///
+ static OMPTargetTeamsDistributeParallelForDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt, const HelperExprs &Exprs);
+
+ /// Creates an empty directive with the place for \a NumClauses clauses.
+ ///
+ /// \param C AST context.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ static OMPTargetTeamsDistributeParallelForDirective *
+ CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
+ EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() ==
+ OMPTargetTeamsDistributeParallelForDirectiveClass;
+ }
+};
+
} // end namespace clang
#endif
diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h
index b9c2c08943e9..7f289862578d 100644
--- a/include/clang/AST/TemplateBase.h
+++ b/include/clang/AST/TemplateBase.h
@@ -301,6 +301,10 @@ public:
Integer.Type = T.getAsOpaquePtr();
}
+ /// \brief 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.
Expr *getAsExpr() const {
assert(getKind() == Expression && "Unexpected kind");
@@ -326,8 +330,8 @@ public:
/// \brief Iterator range referencing all of the elements of a template
/// argument pack.
- llvm::iterator_range<pack_iterator> pack_elements() const {
- return llvm::make_range(pack_begin(), pack_end());
+ ArrayRef<TemplateArgument> pack_elements() const {
+ return llvm::makeArrayRef(pack_begin(), pack_end());
}
/// \brief The number of template arguments in the given template argument
@@ -592,6 +596,10 @@ public:
return getTrailingObjects<TemplateArgumentLoc>();
}
+ llvm::ArrayRef<TemplateArgumentLoc> arguments() const {
+ return llvm::makeArrayRef(getTemplateArgs(), NumTemplateArgs);
+ }
+
const TemplateArgumentLoc &operator[](unsigned I) const {
return getTemplateArgs()[I];
}
@@ -607,7 +615,7 @@ public:
/// as such, doesn't contain the array of TemplateArgumentLoc itself,
/// but expects the containing object to also provide storage for
/// that.
-struct LLVM_ALIGNAS(LLVM_PTR_SIZE) ASTTemplateKWAndArgsInfo {
+struct alignas(void *) ASTTemplateKWAndArgsInfo {
/// \brief The source location of the left angle bracket ('<').
SourceLocation LAngleLoc;
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index 1067c086c764..744a408e5796 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -88,6 +88,7 @@ namespace clang {
class ObjCInterfaceDecl;
class ObjCProtocolDecl;
class ObjCMethodDecl;
+ class ObjCTypeParamDecl;
class UnresolvedUsingTypenameDecl;
class Expr;
class Stmt;
@@ -984,6 +985,7 @@ public:
void dump(const char *s) const;
void dump() const;
+ void dump(llvm::raw_ostream &OS) const;
void Profile(llvm::FoldingSetNodeID &ID) const {
ID.AddPointer(getAsOpaquePtr());
@@ -1377,7 +1379,7 @@ protected:
/// Extra information which affects how the function is called, like
/// regparm and the calling convention.
- unsigned ExtInfo : 9;
+ unsigned ExtInfo : 10;
/// Used only by FunctionProtoType, put here to pack with the
/// other bitfields.
@@ -1728,7 +1730,8 @@ public:
bool isObjCARCBridgableType() const;
bool isCARCBridgableType() const;
bool isTemplateTypeParmType() const; // C++ template type parameter
- bool isNullPtrType() const; // C++0x nullptr_t
+ bool isNullPtrType() const; // C++11 std::nullptr_t
+ bool isAlignValT() const; // C++17 std::align_val_t
bool isAtomicType() const; // C11 _Atomic()
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
@@ -2003,6 +2006,7 @@ public:
}
CanQualType getCanonicalTypeUnqualified() const; // in CanonicalType.h
void dump() const;
+ void dump(llvm::raw_ostream &OS) const;
friend class ASTReader;
friend class ASTWriter;
@@ -2262,19 +2266,15 @@ public:
/// Represents a pointer type decayed from an array or function type.
class DecayedType : public AdjustedType {
- DecayedType(QualType OriginalType, QualType DecayedPtr, QualType CanonicalPtr)
- : AdjustedType(Decayed, OriginalType, DecayedPtr, CanonicalPtr) {
- assert(isa<PointerType>(getAdjustedType()));
- }
+ inline
+ DecayedType(QualType OriginalType, QualType Decayed, QualType Canonical);
friend class ASTContext; // ASTContext creates these.
public:
QualType getDecayedType() const { return getAdjustedType(); }
- QualType getPointeeType() const {
- return cast<PointerType>(getDecayedType())->getPointeeType();
- }
+ inline QualType getPointeeType() const;
static bool classof(const Type *T) { return T->getTypeClass() == Decayed; }
};
@@ -2812,7 +2812,8 @@ public:
/// __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
/// class enables syntactic extensions, like Vector Components for accessing
-/// points, colors, and textures (modeled after OpenGL Shading Language).
+/// points (as .xyzw), colors (as .rgba), and textures (modeled after OpenGL
+/// Shading Language).
class ExtVectorType : public VectorType {
ExtVectorType(QualType vecType, unsigned nElements, QualType canonType) :
VectorType(ExtVector, vecType, nElements, canonType, GenericVector) {}
@@ -2821,10 +2822,10 @@ public:
static int getPointAccessorIdx(char c) {
switch (c) {
default: return -1;
- case 'x': return 0;
- case 'y': return 1;
- case 'z': return 2;
- case 'w': return 3;
+ case 'x': case 'r': return 0;
+ case 'y': case 'g': return 1;
+ case 'z': case 'b': return 2;
+ case 'w': case 'a': return 3;
}
}
static int getNumericAccessorIdx(char c) {
@@ -2855,13 +2856,15 @@ public:
}
}
- static int getAccessorIdx(char c) {
- if (int idx = getPointAccessorIdx(c)+1) return idx-1;
- return getNumericAccessorIdx(c);
+ static int getAccessorIdx(char c, bool isNumericAccessor) {
+ if (isNumericAccessor)
+ return getNumericAccessorIdx(c);
+ else
+ return getPointAccessorIdx(c);
}
- bool isAccessorWithinNumElements(char c) const {
- if (int idx = getAccessorIdx(c)+1)
+ bool isAccessorWithinNumElements(char c, bool isNumericAccessor) const {
+ if (int idx = getAccessorIdx(c, isNumericAccessor)+1)
return unsigned(idx-1) < getNumElements();
return false;
}
@@ -2902,19 +2905,19 @@ class FunctionType : public Type {
// * AST read and write
// * Codegen
class ExtInfo {
- // Feel free to rearrange or add bits, but if you go over 9,
+ // Feel free to rearrange or add bits, but if you go over 10,
// you'll need to adjust both the Bits field below and
// Type::FunctionTypeBitfields.
// | CC |noreturn|produces|regparm|
- // |0 .. 3| 4 | 5 | 6 .. 8|
+ // |0 .. 4| 5 | 6 | 7 .. 9|
//
// regparm is either 0 (no regparm attribute) or the regparm value+1.
- enum { CallConvMask = 0xF };
- enum { NoReturnMask = 0x10 };
- enum { ProducesResultMask = 0x20 };
+ enum { CallConvMask = 0x1F };
+ enum { NoReturnMask = 0x20 };
+ enum { ProducesResultMask = 0x40 };
enum { RegParmMask = ~(CallConvMask | NoReturnMask | ProducesResultMask),
- RegParmOffset = 6 }; // Assumed to be the last field
+ RegParmOffset = 7 }; // Assumed to be the last field
uint16_t Bits;
@@ -3318,6 +3321,9 @@ public:
}
/// Return whether this function has a dependent exception spec.
bool hasDependentExceptionSpec() const;
+ /// Return whether this function has an instantiation-dependent exception
+ /// spec.
+ bool hasInstantiationDependentExceptionSpec() const;
/// Result type of getNoexceptSpec().
enum NoexceptResult {
NR_NoNoexcept, ///< There is no noexcept specifier.
@@ -3359,9 +3365,15 @@ public:
return reinterpret_cast<FunctionDecl *const *>(param_type_end())[1];
}
/// Determine whether this function type has a non-throwing exception
+ /// specification.
+ CanThrowResult canThrow(const ASTContext &Ctx) const;
+ /// Determine whether this function type has a non-throwing exception
/// specification. If this depends on template arguments, returns
/// \c ResultIfDependent.
- bool isNothrow(const ASTContext &Ctx, bool ResultIfDependent = false) const;
+ bool isNothrow(const ASTContext &Ctx, bool ResultIfDependent = false) const {
+ return ResultIfDependent ? canThrow(Ctx) != CT_Can
+ : canThrow(Ctx) == CT_Cannot;
+ }
bool isVariadic() const { return Variadic; }
@@ -3462,7 +3474,8 @@ public:
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx);
static void Profile(llvm::FoldingSetNodeID &ID, QualType Result,
param_type_iterator ArgTys, unsigned NumArgs,
- const ExtProtoInfo &EPI, const ASTContext &Context);
+ const ExtProtoInfo &EPI, const ASTContext &Context,
+ bool Canonical);
};
/// \brief Represents the dependent type named by a dependently-scoped
@@ -3788,6 +3801,7 @@ public:
attr_fastcall,
attr_stdcall,
attr_thiscall,
+ attr_regcall,
attr_pascal,
attr_swiftcall,
attr_vectorcall,
@@ -4078,18 +4092,22 @@ public:
/// \brief Represents a C++11 auto or C++14 decltype(auto) type.
///
/// These types are usually a placeholder for a deduced type. However, before
-/// the initializer is attached, or if the initializer is type-dependent, there
-/// is no deduced type and an auto type is canonical. In the latter case, it is
-/// also a dependent type.
+/// the initializer is attached, or (usually) if the initializer is
+/// type-dependent, there is no deduced type and an auto type is canonical. In
+/// the latter case, it is also a dependent type.
class AutoType : public Type, public llvm::FoldingSetNode {
AutoType(QualType DeducedType, AutoTypeKeyword Keyword, bool IsDependent)
: Type(Auto, DeducedType.isNull() ? QualType(this, 0) : DeducedType,
/*Dependent=*/IsDependent, /*InstantiationDependent=*/IsDependent,
- /*VariablyModified=*/false,
- /*ContainsParameterPack=*/DeducedType.isNull()
- ? false : DeducedType->containsUnexpandedParameterPack()) {
- assert((DeducedType.isNull() || !IsDependent) &&
- "auto deduced to dependent type");
+ /*VariablyModified=*/false, /*ContainsParameterPack=*/false) {
+ if (!DeducedType.isNull()) {
+ if (DeducedType->isDependentType())
+ setDependent();
+ if (DeducedType->isInstantiationDependentType())
+ setInstantiationDependent();
+ if (DeducedType->containsUnexpandedParameterPack())
+ setContainsUnexpandedParameterPack();
+ }
AutoTypeBits.Keyword = (unsigned)Keyword;
}
@@ -4696,6 +4714,102 @@ public:
}
};
+/// This class wraps the list of protocol qualifiers. For types that can
+/// take ObjC protocol qualifers, they can subclass this class.
+template <class T>
+class ObjCProtocolQualifiers {
+protected:
+ ObjCProtocolQualifiers() {}
+ ObjCProtocolDecl * const *getProtocolStorage() const {
+ return const_cast<ObjCProtocolQualifiers*>(this)->getProtocolStorage();
+ }
+
+ ObjCProtocolDecl **getProtocolStorage() {
+ return static_cast<T*>(this)->getProtocolStorageImpl();
+ }
+ void setNumProtocols(unsigned N) {
+ static_cast<T*>(this)->setNumProtocolsImpl(N);
+ }
+ void initialize(ArrayRef<ObjCProtocolDecl *> protocols) {
+ setNumProtocols(protocols.size());
+ assert(getNumProtocols() == protocols.size() &&
+ "bitfield overflow in protocol count");
+ if (!protocols.empty())
+ memcpy(getProtocolStorage(), protocols.data(),
+ protocols.size() * sizeof(ObjCProtocolDecl*));
+ }
+
+public:
+ typedef ObjCProtocolDecl * const *qual_iterator;
+ typedef llvm::iterator_range<qual_iterator> qual_range;
+
+ qual_range quals() const { return qual_range(qual_begin(), qual_end()); }
+ qual_iterator qual_begin() const { return getProtocolStorage(); }
+ qual_iterator qual_end() const { return qual_begin() + getNumProtocols(); }
+
+ bool qual_empty() const { return getNumProtocols() == 0; }
+
+ /// Return the number of qualifying protocols in this type, or 0 if
+ /// there are none.
+ unsigned getNumProtocols() const {
+ return static_cast<const T*>(this)->getNumProtocolsImpl();
+ }
+
+ /// Fetch a protocol by index.
+ ObjCProtocolDecl *getProtocol(unsigned I) const {
+ assert(I < getNumProtocols() && "Out-of-range protocol access");
+ return qual_begin()[I];
+ }
+
+ /// Retrieve all of the protocol qualifiers.
+ ArrayRef<ObjCProtocolDecl *> getProtocols() const {
+ return ArrayRef<ObjCProtocolDecl *>(qual_begin(), getNumProtocols());
+ }
+};
+
+/// Represents a type parameter type in Objective C. It can take
+/// a list of protocols.
+class ObjCTypeParamType : public Type,
+ public ObjCProtocolQualifiers<ObjCTypeParamType>,
+ public llvm::FoldingSetNode {
+ friend class ASTContext;
+ friend class ObjCProtocolQualifiers<ObjCTypeParamType>;
+
+ /// The number of protocols stored on this type.
+ unsigned NumProtocols : 6;
+
+ ObjCTypeParamDecl *OTPDecl;
+ /// The protocols are stored after the ObjCTypeParamType node. In the
+ /// canonical type, the list of protocols are sorted alphabetically
+ /// and uniqued.
+ ObjCProtocolDecl **getProtocolStorageImpl();
+ /// Return the number of qualifying protocols in this interface type,
+ /// or 0 if there are none.
+ unsigned getNumProtocolsImpl() const {
+ return NumProtocols;
+ }
+ void setNumProtocolsImpl(unsigned N) {
+ NumProtocols = N;
+ }
+ ObjCTypeParamType(const ObjCTypeParamDecl *D,
+ QualType can,
+ ArrayRef<ObjCProtocolDecl *> protocols);
+public:
+ bool isSugared() const { return true; }
+ QualType desugar() const { return getCanonicalTypeInternal(); }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == ObjCTypeParam;
+ }
+
+ void Profile(llvm::FoldingSetNodeID &ID);
+ static void Profile(llvm::FoldingSetNodeID &ID,
+ const ObjCTypeParamDecl *OTPDecl,
+ ArrayRef<ObjCProtocolDecl *> protocols);
+
+ ObjCTypeParamDecl *getDecl() const { return OTPDecl; }
+};
+
/// Represents a class type in Objective C.
///
/// Every Objective C type is a combination of a base type, a set of
@@ -4724,7 +4838,9 @@ public:
/// 'id<P>' is an ObjCObjectPointerType whose pointee is an ObjCObjectType
/// with base BuiltinType::ObjCIdType and protocol list [P]. Eventually
/// this should get its own sugar class to better represent the source.
-class ObjCObjectType : public Type {
+class ObjCObjectType : public Type,
+ public ObjCProtocolQualifiers<ObjCObjectType> {
+ friend class ObjCProtocolQualifiers<ObjCObjectType>;
// ObjCObjectType.NumTypeArgs - the number of type arguments stored
// after the ObjCObjectPointerType node.
// ObjCObjectType.NumProtocols - the number of protocols stored
@@ -4744,16 +4860,20 @@ class ObjCObjectType : public Type {
mutable llvm::PointerIntPair<const ObjCObjectType *, 1, bool>
CachedSuperClassType;
- ObjCProtocolDecl * const *getProtocolStorage() const {
- return const_cast<ObjCObjectType*>(this)->getProtocolStorage();
- }
-
QualType *getTypeArgStorage();
const QualType *getTypeArgStorage() const {
return const_cast<ObjCObjectType *>(this)->getTypeArgStorage();
}
- ObjCProtocolDecl **getProtocolStorage();
+ ObjCProtocolDecl **getProtocolStorageImpl();
+ /// Return the number of qualifying protocols in this interface type,
+ /// or 0 if there are none.
+ unsigned getNumProtocolsImpl() const {
+ return ObjCObjectTypeBits.NumProtocols;
+ }
+ void setNumProtocolsImpl(unsigned N) {
+ ObjCObjectTypeBits.NumProtocols = N;
+ }
protected:
ObjCObjectType(QualType Canonical, QualType Base,
@@ -4830,30 +4950,6 @@ public:
ObjCObjectTypeBits.NumTypeArgs);
}
- typedef ObjCProtocolDecl * const *qual_iterator;
- typedef llvm::iterator_range<qual_iterator> qual_range;
-
- qual_range quals() const { return qual_range(qual_begin(), qual_end()); }
- qual_iterator qual_begin() const { return getProtocolStorage(); }
- qual_iterator qual_end() const { return qual_begin() + getNumProtocols(); }
-
- bool qual_empty() const { return getNumProtocols() == 0; }
-
- /// Return the number of qualifying protocols in this interface type,
- /// or 0 if there are none.
- unsigned getNumProtocols() const { return ObjCObjectTypeBits.NumProtocols; }
-
- /// Fetch a protocol by index.
- ObjCProtocolDecl *getProtocol(unsigned I) const {
- assert(I < getNumProtocols() && "Out-of-range protocol access");
- return qual_begin()[I];
- }
-
- /// Retrieve all of the protocol qualifiers.
- ArrayRef<ObjCProtocolDecl *> getProtocols() const {
- return ArrayRef<ObjCProtocolDecl *>(qual_begin(), getNumProtocols());
- }
-
/// Whether this is a "__kindof" type as written.
bool isKindOfTypeAsWritten() const { return ObjCObjectTypeBits.IsKindOf; }
@@ -4916,11 +5012,16 @@ inline QualType *ObjCObjectType::getTypeArgStorage() {
return reinterpret_cast<QualType *>(static_cast<ObjCObjectTypeImpl*>(this)+1);
}
-inline ObjCProtocolDecl **ObjCObjectType::getProtocolStorage() {
+inline ObjCProtocolDecl **ObjCObjectType::getProtocolStorageImpl() {
return reinterpret_cast<ObjCProtocolDecl**>(
getTypeArgStorage() + ObjCObjectTypeBits.NumTypeArgs);
}
+inline ObjCProtocolDecl **ObjCTypeParamType::getProtocolStorageImpl() {
+ return reinterpret_cast<ObjCProtocolDecl**>(
+ static_cast<ObjCTypeParamType*>(this)+1);
+}
+
/// Interfaces are the core concept in Objective-C for object oriented design.
/// They basically correspond to C++ classes. There are two kinds of interface
/// types: normal interfaces like `NSString`, and qualified interfaces, which
@@ -5189,17 +5290,17 @@ class AtomicType : public Type, public llvm::FoldingSetNode {
/// PipeType - OpenCL20.
class PipeType : public Type, public llvm::FoldingSetNode {
QualType ElementType;
+ bool isRead;
- PipeType(QualType elemType, QualType CanonicalPtr) :
+ PipeType(QualType elemType, QualType CanonicalPtr, bool isRead) :
Type(Pipe, CanonicalPtr, elemType->isDependentType(),
elemType->isInstantiationDependentType(),
elemType->isVariablyModifiedType(),
elemType->containsUnexpandedParameterPack()),
- ElementType(elemType) {}
+ ElementType(elemType), isRead(isRead) {}
friend class ASTContext; // ASTContext creates these.
public:
-
QualType getElementType() const { return ElementType; }
bool isSugared() const { return false; }
@@ -5207,18 +5308,19 @@ public:
QualType desugar() const { return QualType(this, 0); }
void Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, getElementType());
+ Profile(ID, getElementType(), isReadOnly());
}
- static void Profile(llvm::FoldingSetNodeID &ID, QualType T) {
+ static void Profile(llvm::FoldingSetNodeID &ID, QualType T, bool isRead) {
ID.AddPointer(T.getAsOpaquePtr());
+ ID.AddBoolean(isRead);
}
-
static bool classof(const Type *T) {
return T->getTypeClass() == Pipe;
}
+ bool isReadOnly() const { return isRead; }
};
/// A qualifier set is used to build a set of qualifiers.
@@ -5696,8 +5798,8 @@ inline bool Type::isNullPtrType() const {
return false;
}
-extern bool IsEnumDeclComplete(EnumDecl *);
-extern bool IsEnumDeclScoped(EnumDecl *);
+bool IsEnumDeclComplete(EnumDecl *);
+bool IsEnumDeclScoped(EnumDecl *);
inline bool Type::isIntegerType() const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
@@ -5807,17 +5909,15 @@ inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
// Helper class template that is used by Type::getAs to ensure that one does
// not try to look through a qualified type to get to an array type.
-template <typename T, bool isArrayType = (std::is_same<T, ArrayType>::value ||
- std::is_base_of<ArrayType, T>::value)>
-struct ArrayType_cannot_be_used_with_getAs {};
-
-template<typename T>
-struct ArrayType_cannot_be_used_with_getAs<T, true>;
+template <typename T>
+using TypeIsArrayType =
+ std::integral_constant<bool, std::is_same<T, ArrayType>::value ||
+ std::is_base_of<ArrayType, T>::value>;
// Member-template getAs<specific type>'.
template <typename T> const T *Type::getAs() const {
- ArrayType_cannot_be_used_with_getAs<T> at;
- (void)at;
+ static_assert(!TypeIsArrayType<T>::value,
+ "ArrayType cannot be used with getAs!");
// If this is directly a T type, return it.
if (const T *Ty = dyn_cast<T>(this))
@@ -5847,8 +5947,8 @@ inline const ArrayType *Type::getAsArrayTypeUnsafe() const {
}
template <typename T> const T *Type::castAs() const {
- ArrayType_cannot_be_used_with_getAs<T> at;
- (void) at;
+ static_assert(!TypeIsArrayType<T>::value,
+ "ArrayType cannot be used with castAs!");
if (const T *ty = dyn_cast<T>(this)) return ty;
assert(isa<T>(CanonicalType));
@@ -5861,6 +5961,23 @@ inline const ArrayType *Type::castAsArrayTypeUnsafe() const {
return cast<ArrayType>(getUnqualifiedDesugaredType());
}
+DecayedType::DecayedType(QualType OriginalType, QualType DecayedPtr,
+ QualType CanonicalPtr)
+ : AdjustedType(Decayed, OriginalType, DecayedPtr, CanonicalPtr) {
+#ifndef NDEBUG
+ QualType Adjusted = getAdjustedType();
+ (void)AttributedType::stripOuterNullability(Adjusted);
+ assert(isa<PointerType>(Adjusted));
+#endif
+}
+
+QualType DecayedType::getPointeeType() const {
+ QualType Decayed = getDecayedType();
+ (void)AttributedType::stripOuterNullability(Decayed);
+ return cast<PointerType>(Decayed)->getPointeeType();
+}
+
+
} // end namespace clang
#endif
diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h
index 67adf4a638bc..7de666838d44 100644
--- a/include/clang/AST/TypeLoc.h
+++ b/include/clang/AST/TypeLoc.h
@@ -347,7 +347,7 @@ class ConcreteTypeLoc : public Base {
public:
unsigned getLocalDataAlignment() const {
- return std::max(llvm::alignOf<LocalData>(),
+ return std::max(unsigned(alignof(LocalData)),
asDerived()->getExtraLocalDataAlignment());
}
unsigned getLocalDataSize() const {
@@ -487,8 +487,10 @@ class TypeSpecTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
Type,
TypeSpecLocInfo> {
public:
- enum { LocalDataSize = sizeof(TypeSpecLocInfo),
- LocalDataAlignment = llvm::AlignOf<TypeSpecLocInfo>::Alignment };
+ enum {
+ LocalDataSize = sizeof(TypeSpecLocInfo),
+ LocalDataAlignment = alignof(TypeSpecLocInfo)
+ };
SourceLocation getNameLoc() const {
return this->getLocalData()->NameLoc;
@@ -510,7 +512,7 @@ private:
struct BuiltinLocInfo {
- SourceLocation BuiltinLoc;
+ SourceRange BuiltinRange;
};
/// \brief Wrapper for source info for builtin types.
@@ -520,10 +522,19 @@ class BuiltinTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
BuiltinLocInfo> {
public:
SourceLocation getBuiltinLoc() const {
- return getLocalData()->BuiltinLoc;
+ return getLocalData()->BuiltinRange.getBegin();
}
void setBuiltinLoc(SourceLocation Loc) {
- getLocalData()->BuiltinLoc = Loc;
+ getLocalData()->BuiltinRange = Loc;
+ }
+ void expandBuiltinRange(SourceRange Range) {
+ SourceRange &BuiltinRange = getLocalData()->BuiltinRange;
+ if (!BuiltinRange.getBegin().isValid()) {
+ BuiltinRange = Range;
+ } else {
+ BuiltinRange.setBegin(std::min(Range.getBegin(), BuiltinRange.getBegin()));
+ BuiltinRange.setEnd(std::max(Range.getEnd(), BuiltinRange.getEnd()));
+ }
}
SourceLocation getNameLoc() const { return getBuiltinLoc(); }
@@ -548,11 +559,11 @@ public:
}
unsigned getExtraLocalDataAlignment() const {
- return needsExtraLocalData() ? llvm::alignOf<WrittenBuiltinSpecs>() : 1;
+ return needsExtraLocalData() ? alignof(WrittenBuiltinSpecs) : 1;
}
SourceRange getLocalSourceRange() const {
- return SourceRange(getBuiltinLoc(), getBuiltinLoc());
+ return getLocalData()->BuiltinRange;
}
TypeSpecifierSign getWrittenSignSpec() const {
@@ -693,6 +704,91 @@ public:
TemplateTypeParmDecl *getDecl() const { return getTypePtr()->getDecl(); }
};
+struct ObjCTypeParamTypeLocInfo {
+ SourceLocation NameLoc;
+};
+
+/// ProtocolLAngleLoc, ProtocolRAngleLoc, and the source locations for
+/// protocol qualifiers are stored after Info.
+class ObjCTypeParamTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
+ ObjCTypeParamTypeLoc,
+ ObjCTypeParamType,
+ ObjCTypeParamTypeLocInfo> {
+ // SourceLocations are stored after Info, one for each protocol qualifier.
+ SourceLocation *getProtocolLocArray() const {
+ return (SourceLocation*)this->getExtraLocalData() + 2;
+ }
+
+public:
+ ObjCTypeParamDecl *getDecl() const { return getTypePtr()->getDecl(); }
+
+ SourceLocation getNameLoc() const {
+ return this->getLocalData()->NameLoc;
+ }
+
+ void setNameLoc(SourceLocation Loc) {
+ this->getLocalData()->NameLoc = Loc;
+ }
+
+ SourceLocation getProtocolLAngleLoc() const {
+ return getNumProtocols() ?
+ *((SourceLocation*)this->getExtraLocalData()) :
+ SourceLocation();
+ }
+ void setProtocolLAngleLoc(SourceLocation Loc) {
+ *((SourceLocation*)this->getExtraLocalData()) = Loc;
+ }
+
+ SourceLocation getProtocolRAngleLoc() const {
+ return getNumProtocols() ?
+ *((SourceLocation*)this->getExtraLocalData() + 1) :
+ SourceLocation();
+ }
+ void setProtocolRAngleLoc(SourceLocation Loc) {
+ *((SourceLocation*)this->getExtraLocalData() + 1) = Loc;
+ }
+
+ unsigned getNumProtocols() const {
+ return this->getTypePtr()->getNumProtocols();
+ }
+
+ SourceLocation getProtocolLoc(unsigned i) const {
+ assert(i < getNumProtocols() && "Index is out of bounds!");
+ return getProtocolLocArray()[i];
+ }
+ void setProtocolLoc(unsigned i, SourceLocation Loc) {
+ assert(i < getNumProtocols() && "Index is out of bounds!");
+ getProtocolLocArray()[i] = Loc;
+ }
+
+ ObjCProtocolDecl *getProtocol(unsigned i) const {
+ assert(i < getNumProtocols() && "Index is out of bounds!");
+ return *(this->getTypePtr()->qual_begin() + i);
+ }
+
+ ArrayRef<SourceLocation> getProtocolLocs() const {
+ return llvm::makeArrayRef(getProtocolLocArray(), getNumProtocols());
+ }
+
+ void initializeLocal(ASTContext &Context, SourceLocation Loc);
+
+ unsigned getExtraLocalDataSize() const {
+ if (!this->getNumProtocols()) return 0;
+ // When there are protocol qualifers, we have LAngleLoc and RAngleLoc
+ // as well.
+ return (this->getNumProtocols() + 2) * sizeof(SourceLocation) ;
+ }
+ unsigned getExtraLocalDataAlignment() const {
+ return alignof(SourceLocation);
+ }
+ SourceRange getLocalSourceRange() const {
+ SourceLocation start = getNameLoc();
+ SourceLocation end = getProtocolRAngleLoc();
+ if (end.isInvalid()) return SourceRange(start, start);
+ return SourceRange(start, end);
+ }
+};
+
/// \brief Wrapper for substituted template type parameters.
class SubstTemplateTypeParmTypeLoc :
public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
@@ -960,10 +1056,9 @@ public:
}
unsigned getExtraLocalDataAlignment() const {
- assert(llvm::alignOf<ObjCObjectTypeLoc>()
- >= llvm::alignOf<TypeSourceInfo *>() &&
- "not enough alignment for tail-allocated data");
- return llvm::alignOf<TypeSourceInfo *>();
+ static_assert(alignof(ObjCObjectTypeLoc) >= alignof(TypeSourceInfo *),
+ "not enough alignment for tail-allocated data");
+ return alignof(TypeSourceInfo *);
}
QualType getInnerType() const {
@@ -1329,9 +1424,7 @@ public:
return getNumParams() * sizeof(ParmVarDecl *);
}
- unsigned getExtraLocalDataAlignment() const {
- return llvm::alignOf<ParmVarDecl*>();
- }
+ unsigned getExtraLocalDataAlignment() const { return alignof(ParmVarDecl *); }
QualType getInnerType() const { return getTypePtr()->getReturnType(); }
};
@@ -1525,7 +1618,7 @@ public:
}
unsigned getExtraLocalDataAlignment() const {
- return llvm::alignOf<TemplateArgumentLocInfo>();
+ return alignof(TemplateArgumentLocInfo);
}
private:
@@ -1935,7 +2028,7 @@ public:
}
unsigned getExtraLocalDataAlignment() const {
- return llvm::alignOf<TemplateArgumentLocInfo>();
+ return alignof(TemplateArgumentLocInfo);
}
private:
diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def
index 8caf1024142d..27ab21bf7fcb 100644
--- a/include/clang/AST/TypeNodes.def
+++ b/include/clang/AST/TypeNodes.def
@@ -101,6 +101,7 @@ DEPENDENT_TYPE(InjectedClassName, Type)
DEPENDENT_TYPE(DependentName, Type)
DEPENDENT_TYPE(DependentTemplateSpecialization, Type)
NON_CANONICAL_UNLESS_DEPENDENT_TYPE(PackExpansion, Type)
+NON_CANONICAL_TYPE(ObjCTypeParam, Type)
TYPE(ObjCObject, Type)
TYPE(ObjCInterface, ObjCObjectType)
TYPE(ObjCObjectPointer, Type)
diff --git a/include/clang/AST/UnresolvedSet.h b/include/clang/AST/UnresolvedSet.h
index c1be2aa0f201..b63c6eb21769 100644
--- a/include/clang/AST/UnresolvedSet.h
+++ b/include/clang/AST/UnresolvedSet.h
@@ -17,7 +17,6 @@
#include "clang/AST/DeclAccessPair.h"
#include "clang/Basic/LLVM.h"
-#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/iterator.h"
@@ -39,7 +38,9 @@ class UnresolvedSetIterator : public llvm::iterator_adaptor_base<
: iterator_adaptor_base(const_cast<DeclAccessPair *>(Iter)) {}
public:
- UnresolvedSetIterator() {}
+ // Work around a bug in MSVC 2013 where explicitly default constructed
+ // temporaries with defaulted ctors are not zero initialized.
+ UnresolvedSetIterator() : iterator_adaptor_base(nullptr) {}
NamedDecl *getDecl() const { return I->getDecl(); }
void setDecl(NamedDecl *ND) const { return I->setDecl(ND); }
diff --git a/include/clang/AST/VTTBuilder.h b/include/clang/AST/VTTBuilder.h
index 727bf5109ad4..b4a6fe3bdb94 100644
--- a/include/clang/AST/VTTBuilder.h
+++ b/include/clang/AST/VTTBuilder.h
@@ -20,7 +20,6 @@
#include "clang/AST/GlobalDecl.h"
#include "clang/AST/RecordLayout.h"
#include "clang/Basic/ABI.h"
-#include "llvm/ADT/SetVector.h"
#include <utility>
namespace clang {
diff --git a/include/clang/AST/VTableBuilder.h b/include/clang/AST/VTableBuilder.h
index 481fd11d6afb..5cbcf51dd69b 100644
--- a/include/clang/AST/VTableBuilder.h
+++ b/include/clang/AST/VTableBuilder.h
@@ -20,7 +20,6 @@
#include "clang/AST/RecordLayout.h"
#include "clang/Basic/ABI.h"
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/SetVector.h"
#include <memory>
#include <utility>
@@ -219,76 +218,76 @@ private:
class VTableLayout {
public:
typedef std::pair<uint64_t, ThunkInfo> VTableThunkTy;
-
- typedef const VTableComponent *vtable_component_iterator;
- typedef const VTableThunkTy *vtable_thunk_iterator;
- typedef llvm::iterator_range<vtable_component_iterator>
- vtable_component_range;
-
- typedef llvm::DenseMap<BaseSubobject, uint64_t> AddressPointsMapTy;
+ struct AddressPointLocation {
+ unsigned VTableIndex, AddressPointIndex;
+ };
+ typedef llvm::DenseMap<BaseSubobject, AddressPointLocation>
+ AddressPointsMapTy;
private:
- uint64_t NumVTableComponents;
- std::unique_ptr<VTableComponent[]> VTableComponents;
+ // Stores the component indices of the first component of each virtual table in
+ // the virtual table group. To save a little memory in the common case where
+ // the vtable group contains a single vtable, an empty vector here represents
+ // the vector {0}.
+ OwningArrayRef<size_t> VTableIndices;
+
+ OwningArrayRef<VTableComponent> VTableComponents;
/// \brief Contains thunks needed by vtables, sorted by indices.
- uint64_t NumVTableThunks;
- std::unique_ptr<VTableThunkTy[]> VTableThunks;
+ OwningArrayRef<VTableThunkTy> VTableThunks;
/// \brief Address points for all vtables.
AddressPointsMapTy AddressPoints;
- bool IsMicrosoftABI;
-
public:
- VTableLayout(uint64_t NumVTableComponents,
- const VTableComponent *VTableComponents,
- uint64_t NumVTableThunks,
- const VTableThunkTy *VTableThunks,
- const AddressPointsMapTy &AddressPoints,
- bool IsMicrosoftABI);
+ VTableLayout(ArrayRef<size_t> VTableIndices,
+ ArrayRef<VTableComponent> VTableComponents,
+ ArrayRef<VTableThunkTy> VTableThunks,
+ const AddressPointsMapTy &AddressPoints);
~VTableLayout();
- uint64_t getNumVTableComponents() const {
- return NumVTableComponents;
+ ArrayRef<VTableComponent> vtable_components() const {
+ return VTableComponents;
}
- vtable_component_range vtable_components() const {
- return vtable_component_range(vtable_component_begin(),
- vtable_component_end());
+ ArrayRef<VTableThunkTy> vtable_thunks() const {
+ return VTableThunks;
}
- vtable_component_iterator vtable_component_begin() const {
- return VTableComponents.get();
+ AddressPointLocation getAddressPoint(BaseSubobject Base) const {
+ assert(AddressPoints.count(Base) && "Did not find address point!");
+ return AddressPoints.find(Base)->second;
}
- vtable_component_iterator vtable_component_end() const {
- return VTableComponents.get() + NumVTableComponents;
+ const AddressPointsMapTy &getAddressPoints() const {
+ return AddressPoints;
}
- uint64_t getNumVTableThunks() const { return NumVTableThunks; }
-
- vtable_thunk_iterator vtable_thunk_begin() const {
- return VTableThunks.get();
+ size_t getNumVTables() const {
+ if (VTableIndices.empty())
+ return 1;
+ return VTableIndices.size();
}
- vtable_thunk_iterator vtable_thunk_end() const {
- return VTableThunks.get() + NumVTableThunks;
+ size_t getVTableOffset(size_t i) const {
+ if (VTableIndices.empty()) {
+ assert(i == 0);
+ return 0;
+ }
+ return VTableIndices[i];
}
- uint64_t getAddressPoint(BaseSubobject Base) const {
- assert(AddressPoints.count(Base) &&
- "Did not find address point!");
-
- uint64_t AddressPoint = AddressPoints.lookup(Base);
- assert(AddressPoint != 0 || IsMicrosoftABI);
- (void)IsMicrosoftABI;
+ size_t getVTableSize(size_t i) const {
+ if (VTableIndices.empty()) {
+ assert(i == 0);
+ return vtable_components().size();
+ }
- return AddressPoint;
- }
-
- const AddressPointsMapTy &getAddressPoints() const {
- return AddressPoints;
+ size_t thisIndex = VTableIndices[i];
+ size_t nextIndex = (i + 1 == VTableIndices.size())
+ ? vtable_components().size()
+ : VTableIndices[i + 1];
+ return nextIndex - thisIndex;
}
};
@@ -339,8 +338,9 @@ private:
typedef llvm::DenseMap<GlobalDecl, int64_t> MethodVTableIndicesTy;
MethodVTableIndicesTy MethodVTableIndices;
- typedef llvm::DenseMap<const CXXRecordDecl *, const VTableLayout *>
- VTableLayoutMapTy;
+ typedef llvm::DenseMap<const CXXRecordDecl *,
+ std::unique_ptr<const VTableLayout>>
+ VTableLayoutMapTy;
VTableLayoutMapTy VTableLayouts;
typedef std::pair<const CXXRecordDecl *,
@@ -367,11 +367,9 @@ public:
return *VTableLayouts[RD];
}
- VTableLayout *
- createConstructionVTableLayout(const CXXRecordDecl *MostDerivedClass,
- CharUnits MostDerivedClassOffset,
- bool MostDerivedClassIsVirtual,
- const CXXRecordDecl *LayoutClass);
+ std::unique_ptr<VTableLayout> createConstructionVTableLayout(
+ const CXXRecordDecl *MostDerivedClass, CharUnits MostDerivedClassOffset,
+ bool MostDerivedClassIsVirtual, const CXXRecordDecl *LayoutClass);
/// \brief Locate a virtual function in the vtable.
///
@@ -399,21 +397,21 @@ struct VPtrInfo {
typedef SmallVector<const CXXRecordDecl *, 1> BasePath;
VPtrInfo(const CXXRecordDecl *RD)
- : ReusingBase(RD), BaseWithVPtr(RD), NextBaseToMangle(RD) {}
+ : ObjectWithVPtr(RD), IntroducingObject(RD), NextBaseToMangle(RD) {}
+
+ /// This is the most derived class that has this vptr at offset zero. When
+ /// single inheritance is used, this is always the most derived class. If
+ /// multiple inheritance is used, it may be any direct or indirect base.
+ const CXXRecordDecl *ObjectWithVPtr;
- /// The vtable will hold all of the virtual bases or virtual methods of
- /// ReusingBase. This may or may not be the same class as VPtrSubobject.Base.
- /// A derived class will reuse the vptr of the first non-virtual base
- /// subobject that has one.
- const CXXRecordDecl *ReusingBase;
+ /// This is the class that introduced the vptr by declaring new virtual
+ /// methods or virtual bases.
+ const CXXRecordDecl *IntroducingObject;
- /// BaseWithVPtr is at this offset from its containing complete object or
+ /// IntroducingObject is at this offset from its containing complete object or
/// virtual base.
CharUnits NonVirtualOffset;
- /// The vptr is stored inside this subobject.
- const CXXRecordDecl *BaseWithVPtr;
-
/// The bases from the inheritance path that got used to mangle the vbtable
/// name. This is not really a full path like a CXXBasePath. It holds the
/// subset of records that need to be mangled into the vbtable symbol name in
@@ -432,7 +430,7 @@ struct VPtrInfo {
/// This holds the base classes path from the complete type to the first base
/// with the given vfptr offset, in the base-to-derived order. Only used for
/// vftables.
- BasePath PathToBaseWithVPtr;
+ BasePath PathToIntroducingObject;
/// Static offset from the top of the most derived class to this vfptr,
/// including any virtual base offset. Only used for vftables.
@@ -444,14 +442,12 @@ struct VPtrInfo {
}
};
-typedef SmallVector<VPtrInfo *, 2> VPtrInfoVector;
+typedef SmallVector<std::unique_ptr<VPtrInfo>, 2> VPtrInfoVector;
/// All virtual base related information about a given record decl. Includes
/// information on all virtual base tables and the path components that are used
/// to mangle them.
struct VirtualBaseInfo {
- ~VirtualBaseInfo() { llvm::DeleteContainerPointers(VBPtrPaths); }
-
/// A map from virtual base to vbtable index for doing a conversion from the
/// the derived class to the a base.
llvm::DenseMap<const CXXRecordDecl *, unsigned> VBTableIndices;
@@ -504,15 +500,17 @@ private:
MethodVFTableLocationsTy;
MethodVFTableLocationsTy MethodVFTableLocations;
- typedef llvm::DenseMap<const CXXRecordDecl *, VPtrInfoVector *>
- VFPtrLocationsMapTy;
+ typedef llvm::DenseMap<const CXXRecordDecl *, VPtrInfoVector>
+ VFPtrLocationsMapTy;
VFPtrLocationsMapTy VFPtrLocations;
typedef std::pair<const CXXRecordDecl *, CharUnits> VFTableIdTy;
- typedef llvm::DenseMap<VFTableIdTy, const VTableLayout *> VFTableLayoutMapTy;
+ typedef llvm::DenseMap<VFTableIdTy, std::unique_ptr<const VTableLayout>>
+ VFTableLayoutMapTy;
VFTableLayoutMapTy VFTableLayouts;
- llvm::DenseMap<const CXXRecordDecl *, VirtualBaseInfo *> VBaseInfo;
+ llvm::DenseMap<const CXXRecordDecl *, std::unique_ptr<VirtualBaseInfo>>
+ VBaseInfo;
void enumerateVFPtrs(const CXXRecordDecl *ForClass, VPtrInfoVector &Result);
@@ -522,7 +520,7 @@ private:
const MethodVFTableLocationsTy &NewMethods,
raw_ostream &);
- const VirtualBaseInfo *
+ const VirtualBaseInfo &
computeVBTableRelatedInformation(const CXXRecordDecl *RD);
void computeVTablePaths(bool ForVBTables, const CXXRecordDecl *RD,
diff --git a/include/clang/ASTMatchers/ASTMatchFinder.h b/include/clang/ASTMatchers/ASTMatchFinder.h
index 042408859c9d..389af1b6e259 100644
--- a/include/clang/ASTMatchers/ASTMatchFinder.h
+++ b/include/clang/ASTMatchers/ASTMatchFinder.h
@@ -158,6 +158,8 @@ public:
MatchCallback *Action);
void addMatcher(const TypeLocMatcher &NodeMatch,
MatchCallback *Action);
+ void addMatcher(const CXXCtorInitializerMatcher &NodeMatch,
+ MatchCallback *Action);
/// @}
/// \brief Adds a matcher to execute when running over the AST.
@@ -208,6 +210,7 @@ public:
std::vector<std::pair<NestedNameSpecifierLocMatcher, MatchCallback *>>
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.
llvm::SmallPtrSet<MatchCallback *, 16> AllCallbacks;
};
@@ -229,6 +232,10 @@ private:
/// Multiple results occur when using matchers like \c forEachDescendant,
/// which generate a result for each sub-match.
///
+/// If you want to find all matches on the sub-tree rooted at \c Node (rather
+/// than only the matches on \c Node itself), surround the \c Matcher with a
+/// \c findAll().
+///
/// \see selectFirst
/// @{
template <typename MatcherT, typename NodeT>
diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h
index aef4b4eafd9a..6a5224febab5 100644
--- a/include/clang/ASTMatchers/ASTMatchers.h
+++ b/include/clang/ASTMatchers/ASTMatchers.h
@@ -51,7 +51,6 @@
#include "clang/AST/DeclTemplate.h"
#include "clang/ASTMatchers/ASTMatchersInternal.h"
#include "clang/ASTMatchers/ASTMatchersMacros.h"
-#include "llvm/ADT/Twine.h"
#include "llvm/Support/Regex.h"
#include <iterator>
@@ -76,18 +75,6 @@ public:
return MyBoundNodes.getNodeAs<T>(ID);
}
- /// \brief Deprecated. Please use \c getNodeAs instead.
- /// @{
- template <typename T>
- const T *getDeclAs(StringRef ID) const {
- return getNodeAs<T>(ID);
- }
- template <typename T>
- const T *getStmtAs(StringRef ID) const {
- return getNodeAs<T>(ID);
- }
- /// @}
-
/// \brief Type of mapping from binding identifiers to bound nodes. This type
/// is an associative container with a key type of \c std::string and a value
/// type of \c clang::ast_type_traits::DynTypedNode
@@ -126,6 +113,7 @@ typedef internal::Matcher<QualType> TypeMatcher;
typedef internal::Matcher<TypeLoc> TypeLocMatcher;
typedef internal::Matcher<NestedNameSpecifier> NestedNameSpecifierMatcher;
typedef internal::Matcher<NestedNameSpecifierLoc> NestedNameSpecifierLocMatcher;
+typedef internal::Matcher<CXXCtorInitializer> CXXCtorInitializerMatcher;
/// @}
/// \brief Matches any node.
@@ -447,6 +435,17 @@ const internal::VariadicAllOfMatcher<CXXCtorInitializer> cxxCtorInitializer;
/// matches 'int' in C<int>.
const internal::VariadicAllOfMatcher<TemplateArgument> templateArgument;
+/// \brief Matches template name.
+///
+/// Given
+/// \code
+/// template <typename T> class X { };
+/// X<int> xi;
+/// \endcode
+/// templateName()
+/// matches 'X' in X<int>.
+const internal::VariadicAllOfMatcher<TemplateName> templateName;
+
/// \brief Matches non-type template parameter declarations.
///
/// Given
@@ -534,7 +533,8 @@ AST_MATCHER(FieldDecl, isBitField) {
return Node.isBitField();
}
-/// \brief Matches non-static data members that are bit-fields.
+/// \brief Matches non-static data members that are bit-fields of the specified
+/// bit width.
///
/// Given
/// \code
@@ -544,35 +544,66 @@ AST_MATCHER(FieldDecl, isBitField) {
/// int c : 2;
/// };
/// \endcode
-/// fieldDecl(isBitField())
+/// fieldDecl(hasBitWidth(2))
/// matches 'int a;' and 'int c;' but not 'int b;'.
AST_MATCHER_P(FieldDecl, hasBitWidth, unsigned, Width) {
return Node.isBitField() &&
Node.getBitWidthValue(Finder->getASTContext()) == Width;
}
+/// \brief Matches non-static data members that have an in-class initializer.
+///
+/// Given
+/// \code
+/// class C {
+/// int a = 2;
+/// int b = 3;
+/// int c;
+/// };
+/// \endcode
+/// fieldDecl(hasInClassInitializer(integerLiteral(equals(2))))
+/// matches 'int a;' but not 'int b;'.
+/// fieldDecl(hasInClassInitializer(anything()))
+/// matches 'int a;' and 'int b;' but not 'int c;'.
+AST_MATCHER_P(FieldDecl, hasInClassInitializer, internal::Matcher<Expr>,
+ InnerMatcher) {
+ const Expr *Initializer = Node.getInClassInitializer();
+ return (Initializer != nullptr &&
+ InnerMatcher.matches(*Initializer, Finder, Builder));
+}
+
/// \brief Matches a declaration that has been implicitly added
/// by the compiler (eg. implicit default/copy constructors).
AST_MATCHER(Decl, isImplicit) {
return Node.isImplicit();
}
-/// \brief Matches classTemplateSpecializations that have at least one
-/// TemplateArgument matching the given InnerMatcher.
+/// \brief Matches classTemplateSpecializations, templateSpecializationType and
+/// functionDecl that have at least one TemplateArgument matching the given
+/// InnerMatcher.
///
/// Given
/// \code
/// template<typename T> class A {};
/// template<> class A<double> {};
/// A<int> a;
+///
+/// template<typename T> f() {};
+/// void func() { f<int>(); };
+/// \endcode
+///
/// \endcode
/// classTemplateSpecializationDecl(hasAnyTemplateArgument(
/// refersToType(asString("int"))))
/// matches the specialization \c A<int>
+///
+/// functionDecl(hasAnyTemplateArgument(refersToType(asString("int"))))
+/// matches the specialization \c f<int>
AST_POLYMORPHIC_MATCHER_P(
hasAnyTemplateArgument,
AST_POLYMORPHIC_SUPPORTED_TYPES(ClassTemplateSpecializationDecl,
- TemplateSpecializationType),
+ TemplateSpecializationType,
+ FunctionDecl),
internal::Matcher<TemplateArgument>, InnerMatcher) {
ArrayRef<TemplateArgument> List =
internal::getTemplateSpecializationArgs(Node);
@@ -699,22 +730,29 @@ AST_MATCHER_P(QualType, ignoringParens,
return InnerMatcher.matches(Node.IgnoreParens(), Finder, Builder);
}
-/// \brief Matches classTemplateSpecializations where the n'th TemplateArgument
-/// matches the given InnerMatcher.
+/// \brief Matches classTemplateSpecializations, templateSpecializationType and
+/// functionDecl where the n'th TemplateArgument matches the given InnerMatcher.
///
/// Given
/// \code
/// template<typename T, typename U> class A {};
/// A<bool, int> b;
/// A<int, bool> c;
+///
+/// template<typename T> f() {};
+/// void func() { f<int>(); };
/// \endcode
/// classTemplateSpecializationDecl(hasTemplateArgument(
/// 1, refersToType(asString("int"))))
/// matches the specialization \c A<bool, int>
+///
+/// functionDecl(hasTemplateArgument(0, refersToType(asString("int"))))
+/// matches the specialization \c f<int>
AST_POLYMORPHIC_MATCHER_P2(
hasTemplateArgument,
AST_POLYMORPHIC_SUPPORTED_TYPES(ClassTemplateSpecializationDecl,
- TemplateSpecializationType),
+ TemplateSpecializationType,
+ FunctionDecl),
unsigned, N, internal::Matcher<TemplateArgument>, InnerMatcher) {
ArrayRef<TemplateArgument> List =
internal::getTemplateSpecializationArgs(Node);
@@ -758,6 +796,24 @@ AST_MATCHER_P(TemplateArgument, refersToType,
return InnerMatcher.matches(Node.getAsType(), Finder, Builder);
}
+/// \brief Matches a TemplateArgument that refers to a certain template.
+///
+/// Given
+/// \code
+/// template<template <typename> class S> class X {};
+/// template<typename T> class Y {};"
+/// X<Y> xi;
+/// \endcode
+/// classTemplateSpecializationDecl(hasAnyTemplateArgument(
+/// refersToTemplate(templateName())))
+/// matches the specialization \c X<Y>
+AST_MATCHER_P(TemplateArgument, refersToTemplate,
+ internal::Matcher<TemplateName>, InnerMatcher) {
+ if (Node.getKind() != TemplateArgument::Template)
+ return false;
+ return InnerMatcher.matches(Node.getAsTemplate(), Finder, Builder);
+}
+
/// \brief Matches a canonical TemplateArgument that refers to a certain
/// declaration.
///
@@ -1863,7 +1919,7 @@ const internal::VariadicDynCastAllOfMatcher<
/// \brief Matches a C-style cast expression.
///
-/// Example: Matches (int*) 2.2f in
+/// Example: Matches (int) 2.2f in
/// \code
/// int i = (int) 2.2f;
/// \endcode
@@ -2404,16 +2460,18 @@ const internal::VariadicOperatorMatcherFunc<1, 1> unless = {
/// - for CallExpr, the declaration of the callee
/// - for MemberExpr, the declaration of the referenced member
/// - for CXXConstructExpr, the declaration of the constructor
+/// - for CXXNewExpr, the declaration of the operator new
///
/// Also usable as Matcher<T> for any T supporting the getDecl() member
/// function. e.g. various subtypes of clang::Type and various expressions.
///
-/// Usable as: Matcher<CallExpr>, Matcher<CXXConstructExpr>,
-/// Matcher<DeclRefExpr>, Matcher<EnumType>, Matcher<InjectedClassNameType>,
-/// Matcher<LabelStmt>, Matcher<AddrLabelExpr>, Matcher<MemberExpr>,
-/// Matcher<QualType>, Matcher<RecordType>, Matcher<TagType>,
-/// Matcher<TemplateSpecializationType>, Matcher<TemplateTypeParmType>,
-/// Matcher<TypedefType>, Matcher<UnresolvedUsingType>
+/// Usable as: Matcher<AddrLabelExpr>, Matcher<CallExpr>,
+/// Matcher<CXXConstructExpr>, Matcher<CXXNewExpr>, Matcher<DeclRefExpr>,
+/// Matcher<EnumType>, Matcher<InjectedClassNameType>, Matcher<LabelStmt>,
+/// Matcher<MemberExpr>, Matcher<QualType>, Matcher<RecordType>,
+/// Matcher<TagType>, Matcher<TemplateSpecializationType>,
+/// Matcher<TemplateTypeParmType>, Matcher<TypedefType>,
+/// Matcher<UnresolvedUsingType>
inline internal::PolymorphicMatcherWithParam1<
internal::HasDeclarationMatcher, internal::Matcher<Decl>,
void(internal::HasDeclarationSupportedTypes)>
@@ -2423,6 +2481,25 @@ hasDeclaration(const internal::Matcher<Decl> &InnerMatcher) {
void(internal::HasDeclarationSupportedTypes)>(InnerMatcher);
}
+/// \brief Matches a \c NamedDecl whose underlying declaration matches the given
+/// matcher.
+///
+/// Given
+/// \code
+/// namespace N { template<class T> void f(T t); }
+/// template <class T> void g() { using N::f; f(T()); }
+/// \endcode
+/// \c unresolvedLookupExpr(hasAnyDeclaration(
+/// namedDecl(hasUnderlyingDecl(hasName("::N::f")))))
+/// matches the use of \c f in \c g() .
+AST_MATCHER_P(NamedDecl, hasUnderlyingDecl, internal::Matcher<NamedDecl>,
+ InnerMatcher) {
+ const NamedDecl *UnderlyingDecl = Node.getUnderlyingDecl();
+
+ return UnderlyingDecl != nullptr &&
+ InnerMatcher.matches(*UnderlyingDecl, Finder, Builder);
+}
+
/// \brief Matches on the implicit object argument of a member call expression.
///
/// Example matches y.x()
@@ -2671,6 +2748,22 @@ AST_MATCHER_P_OVERLOAD(QualType, pointsTo, internal::Matcher<Decl>,
.matches(Node, Finder, Builder);
}
+/// \brief Matches if the matched type matches the unqualified desugared
+/// type of the matched node.
+///
+/// For example, in:
+/// \code
+/// class A {};
+/// using B = A;
+/// \endcode
+/// The matcher type(hasUniqualifeidDesugaredType(recordType())) matches
+/// both B and A.
+AST_MATCHER_P(Type, hasUnqualifiedDesugaredType, internal::Matcher<Type>,
+ InnerMatcher) {
+ return InnerMatcher.matches(*Node.getUnqualifiedDesugaredType(), Finder,
+ Builder);
+}
+
/// \brief Matches if the matched type is a reference type and the referenced
/// type matches the specified matcher.
///
@@ -2778,6 +2871,27 @@ AST_MATCHER_P(DeclRefExpr, throughUsingDecl,
return false;
}
+/// \brief Matches an \c OverloadExpr if any of the declarations in the set of
+/// overloads matches the given matcher.
+///
+/// Given
+/// \code
+/// template <typename T> void foo(T);
+/// template <typename T> void bar(T);
+/// template <typename T> void baz(T t) {
+/// foo(t);
+/// bar(t);
+/// }
+/// \endcode
+/// unresolvedLookupExpr(hasAnyDeclaration(
+/// functionTemplateDecl(hasName("foo"))))
+/// matches \c foo in \c foo(t); but not \c bar in \c bar(t);
+AST_MATCHER_P(OverloadExpr, hasAnyDeclaration, internal::Matcher<Decl>,
+ InnerMatcher) {
+ return matchesFirstInPointerRange(InnerMatcher, Node.decls_begin(),
+ Node.decls_end(), Finder, Builder);
+}
+
/// \brief Matches the Decl of a DeclStmt which has a single declaration.
///
/// Given
@@ -2857,9 +2971,9 @@ AST_MATCHER(VarDecl, hasAutomaticStorageDuration) {
}
/// \brief 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.
///
-/// Example matches y and a, but not x or z.
-/// (matcher = varDecl(hasStaticStorageDuration())
/// \code
/// void f() {
/// int x;
@@ -2867,6 +2981,10 @@ AST_MATCHER(VarDecl, hasAutomaticStorageDuration) {
/// thread_local int z;
/// }
/// int a;
+/// static int b;
+/// extern int c;
+/// varDecl(hasStaticStorageDuration())
+/// matches the function declaration y, a, b and c.
/// \endcode
AST_MATCHER(VarDecl, hasStaticStorageDuration) {
return Node.getStorageDuration() == SD_Static;
@@ -3297,10 +3415,31 @@ AST_MATCHER_P(FunctionDecl, returns,
/// \endcode
/// functionDecl(isExternC())
/// matches the declaration of f and g, but not the declaration h
-AST_MATCHER(FunctionDecl, isExternC) {
+AST_POLYMORPHIC_MATCHER(isExternC, AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl,
+ VarDecl)) {
return Node.isExternC();
}
+/// \brief Matches variable/function declarations that have "static" storage
+/// class specifier ("static" keyword) written in the source.
+///
+/// Given:
+/// \code
+/// static void f() {}
+/// static int i = 0;
+/// extern int j;
+/// int k;
+/// \endcode
+/// functionDecl(isStaticStorageClass())
+/// matches the function declaration f.
+/// varDecl(isStaticStorageClass())
+/// matches the variable declaration i.
+AST_POLYMORPHIC_MATCHER(isStaticStorageClass,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl,
+ VarDecl)) {
+ return Node.getStorageClass() == SC_Static;
+}
+
/// \brief Matches deleted function declarations.
///
/// Given:
@@ -4075,7 +4214,7 @@ AST_MATCHER(QualType, isInteger) {
/// void b(unsigned long);
/// void c(double);
/// \endcode
-/// functionDecl(hasAnyParameter(hasType(isInteger())))
+/// functionDecl(hasAnyParameter(hasType(isUnsignedInteger())))
/// matches "b(unsigned long)", but not "a(int)" and "c(double)".
AST_MATCHER(QualType, isUnsignedInteger) {
return Node->isUnsignedIntegerType();
@@ -4089,7 +4228,7 @@ AST_MATCHER(QualType, isUnsignedInteger) {
/// void b(unsigned long);
/// void c(double);
/// \endcode
-/// functionDecl(hasAnyParameter(hasType(isInteger())))
+/// functionDecl(hasAnyParameter(hasType(isSignedInteger())))
/// matches "a(int)", but not "b(unsigned long)" and "c(double)".
AST_MATCHER(QualType, isSignedInteger) {
return Node->isSignedIntegerType();
@@ -4890,6 +5029,22 @@ AST_MATCHER_P(ElaboratedType, namesType, internal::Matcher<QualType>,
/// \c substTemplateTypeParmType() matches the type of 't' but not '1'
AST_TYPE_MATCHER(SubstTemplateTypeParmType, substTemplateTypeParmType);
+/// \brief Matches template type parameter substitutions that have a replacement
+/// type that matches the provided matcher.
+///
+/// Given
+/// \code
+/// template <typename T>
+/// double F(T t);
+/// int i;
+/// double j = F(i);
+/// \endcode
+///
+/// \c substTemplateTypeParmType(hasReplacementType(type())) matches int
+AST_TYPE_TRAVERSE_MATCHER(
+ hasReplacementType, getReplacementType,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(SubstTemplateTypeParmType));
+
/// \brief Matches template type parameter types.
///
/// Example matches T, but not int.
@@ -5390,6 +5545,30 @@ AST_MATCHER_P(Stmt, forFunction, internal::Matcher<FunctionDecl>,
return false;
}
+/// \brief Matches a declaration that has external formal linkage.
+///
+/// Example matches only z (matcher = varDecl(hasExternalFormalLinkage()))
+/// \code
+/// void f() {
+/// int x;
+/// static int y;
+/// }
+/// int z;
+/// \endcode
+///
+/// Example matches f() because it has external formal linkage despite being
+/// unique to the translation unit as though it has internal likage
+/// (matcher = functionDecl(hasExternalFormalLinkage()))
+///
+/// \code
+/// namespace {
+/// void f() {}
+/// }
+/// \endcode
+AST_MATCHER(NamedDecl, hasExternalFormalLinkage) {
+ return Node.hasExternalFormalLinkage();
+}
+
} // end namespace ast_matchers
} // end namespace clang
diff --git a/include/clang/ASTMatchers/ASTMatchersInternal.h b/include/clang/ASTMatchers/ASTMatchersInternal.h
index c2c01fbd78ea..bc75e807ced9 100644
--- a/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ b/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -787,6 +787,14 @@ private:
return matchesDecl(Node.getConstructor(), Finder, Builder);
}
+ /// \brief Extracts the operator new of the new call and returns whether the
+ /// inner matcher matches on it.
+ bool matchesSpecialized(const CXXNewExpr &Node,
+ ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const {
+ return matchesDecl(Node.getOperatorNew(), Finder, Builder);
+ }
+
/// \brief Extracts the \c ValueDecl a \c MemberExpr refers to and returns
/// whether the inner matcher matches on it.
bool matchesSpecialized(const MemberExpr &Node,
@@ -1007,11 +1015,11 @@ typedef TypeList<Decl, Stmt, NestedNameSpecifier, NestedNameSpecifierLoc,
TypeLoc, QualType> AdaptativeDefaultToTypes;
/// \brief All types that are supported by HasDeclarationMatcher above.
-typedef TypeList<CallExpr, CXXConstructExpr, DeclRefExpr, EnumType,
+typedef TypeList<CallExpr, CXXConstructExpr, CXXNewExpr, DeclRefExpr, EnumType,
InjectedClassNameType, LabelStmt, AddrLabelExpr, MemberExpr,
QualType, RecordType, TagType, TemplateSpecializationType,
- TemplateTypeParmType, TypedefType,
- UnresolvedUsingType> HasDeclarationSupportedTypes;
+ TemplateTypeParmType, TypedefType, UnresolvedUsingType>
+ HasDeclarationSupportedTypes;
/// \brief Converts a \c Matcher<T> to a matcher of desired type \c To by
/// "adapting" a \c To into a \c T.
@@ -1413,18 +1421,18 @@ private:
template <>
inline bool ValueEqualsMatcher<FloatingLiteral, double>::matchesNode(
const FloatingLiteral &Node) const {
- if ((&Node.getSemantics()) == &llvm::APFloat::IEEEsingle)
+ if ((&Node.getSemantics()) == &llvm::APFloat::IEEEsingle())
return Node.getValue().convertToFloat() == ExpectedValue;
- if ((&Node.getSemantics()) == &llvm::APFloat::IEEEdouble)
+ if ((&Node.getSemantics()) == &llvm::APFloat::IEEEdouble())
return Node.getValue().convertToDouble() == ExpectedValue;
return false;
}
template <>
inline bool ValueEqualsMatcher<FloatingLiteral, float>::matchesNode(
const FloatingLiteral &Node) const {
- if ((&Node.getSemantics()) == &llvm::APFloat::IEEEsingle)
+ if ((&Node.getSemantics()) == &llvm::APFloat::IEEEsingle())
return Node.getValue().convertToFloat() == ExpectedValue;
- if ((&Node.getSemantics()) == &llvm::APFloat::IEEEdouble)
+ if ((&Node.getSemantics()) == &llvm::APFloat::IEEEdouble())
return Node.getValue().convertToDouble() == ExpectedValue;
return false;
}
@@ -1638,6 +1646,13 @@ getTemplateSpecializationArgs(const TemplateSpecializationType &T) {
return llvm::makeArrayRef(T.getArgs(), T.getNumArgs());
}
+inline ArrayRef<TemplateArgument>
+getTemplateSpecializationArgs(const FunctionDecl &FD) {
+ if (const auto* TemplateArgs = FD.getTemplateSpecializationArgs())
+ return TemplateArgs->asArray();
+ return ArrayRef<TemplateArgument>();
+}
+
struct NotEqualsBoundNodePredicate {
bool operator()(const internal::BoundNodesMap &Nodes) const {
return Nodes.getNode(ID) != Node;
diff --git a/include/clang/ASTMatchers/ASTMatchersMacros.h b/include/clang/ASTMatchers/ASTMatchersMacros.h
index 8ad0c16ef83a..ddc48378e714 100644
--- a/include/clang/ASTMatchers/ASTMatchersMacros.h
+++ b/include/clang/ASTMatchers/ASTMatchersMacros.h
@@ -97,7 +97,7 @@
class matcher_##DefineMatcher##Matcher \
: public ::clang::ast_matchers::internal::MatcherInterface<Type> { \
public: \
- explicit matcher_##DefineMatcher##Matcher() {} \
+ explicit matcher_##DefineMatcher##Matcher() = default; \
bool matches(const Type &Node, \
::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
::clang::ast_matchers::internal::BoundNodesTreeBuilder \
@@ -401,4 +401,4 @@
ReturnTypesF>::Func MatcherName##Loc; \
AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName##Type, ReturnTypesF)
-#endif
+#endif // LLVM_CLANG_ASTMATCHERS_ASTMATCHERSMACROS_H
diff --git a/include/clang/ASTMatchers/Dynamic/Registry.h b/include/clang/ASTMatchers/Dynamic/Registry.h
index 3808adb11e7f..7bba95dbffea 100644
--- a/include/clang/ASTMatchers/Dynamic/Registry.h
+++ b/include/clang/ASTMatchers/Dynamic/Registry.h
@@ -1,4 +1,4 @@
-//===--- Registry.h - Matcher registry -----*- C++ -*-===//
+//===--- Registry.h - Matcher registry --------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -19,28 +19,36 @@
#include "clang/ASTMatchers/Dynamic/Diagnostics.h"
#include "clang/ASTMatchers/Dynamic/VariantValue.h"
-#include "clang/Basic/LLVM.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringRef.h"
+#include <string>
+#include <utility>
+#include <vector>
namespace clang {
namespace ast_matchers {
namespace dynamic {
namespace internal {
+
class MatcherDescriptor;
-}
+
+} // end namespace internal
typedef const internal::MatcherDescriptor *MatcherCtor;
struct MatcherCompletion {
- MatcherCompletion() {}
+ MatcherCompletion() = default;
MatcherCompletion(StringRef TypedText, StringRef MatcherDecl,
unsigned Specificity)
: TypedText(TypedText), MatcherDecl(MatcherDecl),
Specificity(Specificity) {}
+ bool operator==(const MatcherCompletion &Other) const {
+ return TypedText == Other.TypedText && MatcherDecl == Other.MatcherDecl;
+ }
+
/// \brief The text to type to select this matcher.
std::string TypedText;
@@ -53,14 +61,12 @@ struct MatcherCompletion {
/// matcher that will either always or never match.
/// Such matchers are excluded from code completion results.
unsigned Specificity;
-
- bool operator==(const MatcherCompletion &Other) const {
- return TypedText == Other.TypedText && MatcherDecl == Other.MatcherDecl;
- }
};
class Registry {
public:
+ Registry() = delete;
+
/// \brief Look up a matcher in the registry by name,
///
/// \return An opaque value which may be used to refer to the matcher
@@ -121,13 +127,10 @@ public:
StringRef BindID,
ArrayRef<ParserValue> Args,
Diagnostics *Error);
-
-private:
- Registry() = delete;
};
-} // namespace dynamic
-} // namespace ast_matchers
-} // namespace clang
+} // end namespace dynamic
+} // end namespace ast_matchers
+} // end namespace clang
-#endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_REGISTRY_H
+#endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_REGISTRY_H
diff --git a/include/clang/ASTMatchers/Dynamic/VariantValue.h b/include/clang/ASTMatchers/Dynamic/VariantValue.h
index c391b24a3330..9f694d0ce434 100644
--- a/include/clang/ASTMatchers/Dynamic/VariantValue.h
+++ b/include/clang/ASTMatchers/Dynamic/VariantValue.h
@@ -21,7 +21,6 @@
#include "clang/ASTMatchers/ASTMatchersInternal.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/Twine.h"
#include <memory>
#include <vector>
@@ -120,9 +119,9 @@ class VariantMatcher {
/// \brief Payload interface to be specialized by each matcher type.
///
/// It follows a similar interface as VariantMatcher itself.
- class Payload : public RefCountedBaseVPTR {
+ class Payload : public RefCountedBase<Payload> {
public:
- ~Payload() override;
+ virtual ~Payload();
virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const = 0;
virtual std::string getTypeAsString() const = 0;
virtual llvm::Optional<DynTypedMatcher>
diff --git a/include/clang/Analysis/Analyses/Consumed.h b/include/clang/Analysis/Analyses/Consumed.h
index 1f5aa12111c1..c0fc02724f09 100644
--- a/include/clang/Analysis/Analyses/Consumed.h
+++ b/include/clang/Analysis/Analyses/Consumed.h
@@ -201,11 +201,6 @@ namespace consumed {
public:
ConsumedBlockInfo() = default;
- ConsumedBlockInfo &operator=(ConsumedBlockInfo &&Other) {
- StateMapsArray = std::move(Other.StateMapsArray);
- VisitOrder = std::move(Other.VisitOrder);
- return *this;
- }
ConsumedBlockInfo(unsigned int NumBlocks, PostOrderCFGView *SortedGraph)
: StateMapsArray(NumBlocks), VisitOrder(NumBlocks, 0) {
diff --git a/include/clang/Analysis/Analyses/Dominators.h b/include/clang/Analysis/Analyses/Dominators.h
index c64a3ca2551d..1229f8a8efac 100644
--- a/include/clang/Analysis/Analyses/Dominators.h
+++ b/include/clang/Analysis/Analyses/Dominators.h
@@ -167,43 +167,37 @@ private:
///
namespace llvm {
template <> struct GraphTraits< ::clang::DomTreeNode* > {
- typedef ::clang::DomTreeNode NodeType;
typedef ::clang::DomTreeNode *NodeRef;
- typedef NodeType::iterator ChildIteratorType;
+ typedef ::clang::DomTreeNode::iterator ChildIteratorType;
- static NodeType *getEntryNode(NodeType *N) {
- return N;
- }
- static inline ChildIteratorType child_begin(NodeType *N) {
- return N->begin();
- }
- static inline ChildIteratorType child_end(NodeType *N) {
- return N->end();
- }
+ 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 df_iterator< ::clang::DomTreeNode* > nodes_iterator;
+ typedef llvm::pointer_iterator<df_iterator<::clang::DomTreeNode *>>
+ nodes_iterator;
static nodes_iterator nodes_begin(::clang::DomTreeNode *N) {
- return df_begin(getEntryNode(N));
+ return nodes_iterator(df_begin(getEntryNode(N)));
}
static nodes_iterator nodes_end(::clang::DomTreeNode *N) {
- return df_end(getEntryNode(N));
+ return nodes_iterator(df_end(getEntryNode(N)));
}
};
template <> struct GraphTraits< ::clang::DominatorTree* >
: public GraphTraits< ::clang::DomTreeNode* > {
- static NodeType *getEntryNode(::clang::DominatorTree *DT) {
+ static NodeRef getEntryNode(::clang::DominatorTree *DT) {
return DT->getRootNode();
}
static nodes_iterator nodes_begin(::clang::DominatorTree *N) {
- return df_begin(getEntryNode(N));
+ return nodes_iterator(df_begin(getEntryNode(N)));
}
static nodes_iterator nodes_end(::clang::DominatorTree *N) {
- return df_end(getEntryNode(N));
+ return nodes_iterator(df_end(getEntryNode(N)));
}
};
} // end namespace llvm
diff --git a/include/clang/Analysis/Analyses/FormatString.h b/include/clang/Analysis/Analyses/FormatString.h
index 74803a295d71..8c531d638cc2 100644
--- a/include/clang/Analysis/Analyses/FormatString.h
+++ b/include/clang/Analysis/Analyses/FormatString.h
@@ -35,7 +35,7 @@ class OptionalFlag {
public:
OptionalFlag(const char *Representation)
: representation(Representation), flag(false) {}
- bool isSet() { return flag; }
+ bool isSet() const { return flag; }
void set() { flag = true; }
void clear() { flag = false; }
void setPosition(const char *position) {
@@ -122,12 +122,13 @@ class ConversionSpecifier {
public:
enum Kind {
InvalidSpecifier = 0,
- // C99 conversion specifiers.
+ // C99 conversion specifiers.
cArg,
dArg,
DArg, // Apple extension
iArg,
- IntArgBeg = dArg, IntArgEnd = iArg,
+ IntArgBeg = dArg,
+ IntArgEnd = iArg,
oArg,
OArg, // Apple extension
@@ -135,7 +136,8 @@ public:
UArg, // Apple extension
xArg,
XArg,
- UIntArgBeg = oArg, UIntArgEnd = XArg,
+ UIntArgBeg = oArg,
+ UIntArgEnd = XArg,
fArg,
FArg,
@@ -145,7 +147,8 @@ public:
GArg,
aArg,
AArg,
- DoubleArgBeg = fArg, DoubleArgEnd = AArg,
+ DoubleArgBeg = fArg,
+ DoubleArgEnd = AArg,
sArg,
pArg,
@@ -154,13 +157,19 @@ public:
CArg,
SArg,
+ // Apple extension: P specifies to os_log that the data being pointed to is
+ // to be copied by os_log. The precision indicates the number of bytes to
+ // copy.
+ PArg,
+
// ** Printf-specific **
ZArg, // MS extension
// Objective-C specific specifiers.
- ObjCObjArg, // '@'
- ObjCBeg = ObjCObjArg, ObjCEnd = ObjCObjArg,
+ ObjCObjArg, // '@'
+ ObjCBeg = ObjCObjArg,
+ ObjCEnd = ObjCObjArg,
// FreeBSD kernel specific specifiers.
FreeBSDbArg,
@@ -169,13 +178,15 @@ public:
FreeBSDyArg,
// GlibC specific specifiers.
- PrintErrno, // 'm'
+ PrintErrno, // 'm'
- PrintfConvBeg = ObjCObjArg, PrintfConvEnd = PrintErrno,
+ PrintfConvBeg = ObjCObjArg,
+ PrintfConvEnd = PrintErrno,
// ** Scanf-specific **
ScanListArg, // '['
- ScanfConvBeg = ScanListArg, ScanfConvEnd = ScanListArg
+ ScanfConvBeg = ScanListArg,
+ ScanfConvEnd = ScanListArg
};
ConversionSpecifier(bool isPrintf = true)
@@ -200,6 +211,8 @@ public:
return false;
case PercentArg:
return false;
+ case InvalidSpecifier:
+ return false;
default:
return true;
}
@@ -437,13 +450,15 @@ class PrintfSpecifier : public analyze_format_string::FormatSpecifier {
OptionalFlag HasAlternativeForm; // '#'
OptionalFlag HasLeadingZeroes; // '0'
OptionalFlag HasObjCTechnicalTerm; // '[tt]'
+ OptionalFlag IsPrivate; // '{private}'
+ OptionalFlag IsPublic; // '{public}'
OptionalAmount Precision;
public:
- PrintfSpecifier() :
- FormatSpecifier(/* isPrintf = */ true),
- HasThousandsGrouping("'"), IsLeftJustified("-"), HasPlusPrefix("+"),
- HasSpacePrefix(" "), HasAlternativeForm("#"), HasLeadingZeroes("0"),
- HasObjCTechnicalTerm("tt") {}
+ PrintfSpecifier()
+ : FormatSpecifier(/* isPrintf = */ true), HasThousandsGrouping("'"),
+ IsLeftJustified("-"), HasPlusPrefix("+"), HasSpacePrefix(" "),
+ HasAlternativeForm("#"), HasLeadingZeroes("0"),
+ HasObjCTechnicalTerm("tt"), IsPrivate("private"), IsPublic("public") {}
static PrintfSpecifier Parse(const char *beg, const char *end);
@@ -472,6 +487,8 @@ public:
void setHasObjCTechnicalTerm(const char *position) {
HasObjCTechnicalTerm.setPosition(position);
}
+ void setIsPrivate(const char *position) { IsPrivate.setPosition(position); }
+ void setIsPublic(const char *position) { IsPublic.setPosition(position); }
void setUsesPositionalArg() { UsesPositionalArg = true; }
// Methods for querying the format specifier.
@@ -509,6 +526,8 @@ public:
const OptionalFlag &hasLeadingZeros() const { return HasLeadingZeroes; }
const OptionalFlag &hasSpacePrefix() const { return HasSpacePrefix; }
const OptionalFlag &hasObjCTechnicalTerm() const { return HasObjCTechnicalTerm; }
+ const OptionalFlag &isPrivate() const { return IsPrivate; }
+ const OptionalFlag &isPublic() const { return IsPublic; }
bool usesPositionalArg() const { return UsesPositionalArg; }
/// Changes the specifier and length according to a QualType, retaining any
diff --git a/include/clang/Analysis/Analyses/LiveVariables.h b/include/clang/Analysis/Analyses/LiveVariables.h
index e17f73a61f81..8db4b0a58f86 100644
--- a/include/clang/Analysis/Analyses/LiveVariables.h
+++ b/include/clang/Analysis/Analyses/LiveVariables.h
@@ -16,7 +16,6 @@
#include "clang/AST/Decl.h"
#include "clang/Analysis/AnalysisContext.h"
-#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/ImmutableSet.h"
namespace clang {
diff --git a/include/clang/Analysis/Analyses/OSLog.h b/include/clang/Analysis/Analyses/OSLog.h
new file mode 100644
index 000000000000..1e60a237b770
--- /dev/null
+++ b/include/clang/Analysis/Analyses/OSLog.h
@@ -0,0 +1,155 @@
+//= OSLog.h - Analysis of calls to os_log builtins --*- 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 APIs for determining the layout of the data buffer for
+// os_log() and os_trace().
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_OSLOG_H
+#define LLVM_CLANG_ANALYSIS_ANALYSES_OSLOG_H
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Expr.h"
+
+namespace clang {
+namespace analyze_os_log {
+
+/// An OSLogBufferItem represents a single item in the data written by a call
+/// to os_log() or os_trace().
+class OSLogBufferItem {
+public:
+ enum Kind {
+ // The item is a scalar (int, float, raw pointer, etc.). No further copying
+ // is required. This is the only kind allowed by os_trace().
+ ScalarKind = 0,
+
+ // The item is a count, which describes the length of the following item to
+ // be copied. A count may only be followed by an item of kind StringKind,
+ // WideStringKind, or PointerKind.
+ CountKind,
+
+ // The item is a pointer to a C string. If preceded by a count 'n',
+ // os_log() will copy at most 'n' bytes from the pointer.
+ StringKind,
+
+ // The item is a pointer to a block of raw data. This item must be preceded
+ // by a count 'n'. os_log() will copy exactly 'n' bytes from the pointer.
+ PointerKind,
+
+ // The item is a pointer to an Objective-C object. os_log() may retain the
+ // object for later processing.
+ ObjCObjKind,
+
+ // The item is a pointer to wide-char string.
+ WideStringKind,
+
+ // The item is corresponding to the '%m' format specifier, no value is
+ // populated in the buffer and the runtime is loading the errno value.
+ ErrnoKind
+ };
+
+ enum {
+ // The item is marked "private" in the format string.
+ IsPrivate = 0x1,
+
+ // The item is marked "public" in the format string.
+ IsPublic = 0x2
+ };
+
+private:
+ Kind TheKind = ScalarKind;
+ const Expr *TheExpr = nullptr;
+ CharUnits ConstValue;
+ CharUnits Size; // size of the data, not including the header bytes
+ unsigned Flags = 0;
+
+public:
+ OSLogBufferItem(Kind kind, const Expr *expr, CharUnits size, unsigned flags)
+ : TheKind(kind), TheExpr(expr), Size(size), Flags(flags) {}
+
+ OSLogBufferItem(ASTContext &Ctx, CharUnits value, unsigned flags)
+ : TheKind(CountKind), ConstValue(value),
+ Size(Ctx.getTypeSizeInChars(Ctx.IntTy)), Flags(flags) {}
+
+ unsigned char getDescriptorByte() const {
+ unsigned char result = 0;
+ if (getIsPrivate())
+ result |= IsPrivate;
+ if (getIsPublic())
+ result |= IsPublic;
+ result |= ((unsigned)getKind()) << 4;
+ return result;
+ }
+
+ unsigned char getSizeByte() const { return size().getQuantity(); }
+
+ Kind getKind() const { return TheKind; }
+ bool getIsPrivate() const { return (Flags & IsPrivate) != 0; }
+ bool getIsPublic() const { return (Flags & IsPublic) != 0; }
+
+ const Expr *getExpr() const { return TheExpr; }
+ CharUnits getConstValue() const { return ConstValue; }
+ CharUnits size() const { return Size; }
+};
+
+class OSLogBufferLayout {
+public:
+ SmallVector<OSLogBufferItem, 4> Items;
+
+ enum Flags { HasPrivateItems = 1, HasNonScalarItems = 1 << 1 };
+
+ CharUnits size() const {
+ CharUnits result;
+ result += CharUnits::fromQuantity(2); // summary byte, num-args byte
+ for (auto &item : Items) {
+ // descriptor byte, size byte
+ result += item.size() + CharUnits::fromQuantity(2);
+ }
+ return result;
+ }
+
+ bool hasPrivateItems() const {
+ return llvm::any_of(
+ Items, [](const OSLogBufferItem &Item) { return Item.getIsPrivate(); });
+ }
+
+ bool hasPublicItems() const {
+ return llvm::any_of(
+ Items, [](const OSLogBufferItem &Item) { return Item.getIsPublic(); });
+ }
+
+ bool hasNonScalar() const {
+ return llvm::any_of(Items, [](const OSLogBufferItem &Item) {
+ return Item.getKind() != OSLogBufferItem::ScalarKind;
+ });
+ }
+
+ unsigned char getSummaryByte() const {
+ unsigned char result = 0;
+ if (hasPrivateItems())
+ result |= HasPrivateItems;
+ if (hasNonScalar())
+ result |= HasNonScalarItems;
+ return result;
+ }
+
+ unsigned char getNumArgsByte() const { return Items.size(); }
+};
+
+// Given a call 'E' to one of the builtins __builtin_os_log_format() or
+// __builtin_os_log_format_buffer_size(), compute the layout of the buffer that
+// the call will write into and store it in 'layout'. Returns 'false' if there
+// was some error encountered while computing the layout, and 'true' otherwise.
+bool computeOSLogBufferLayout(clang::ASTContext &Ctx, const clang::CallExpr *E,
+ OSLogBufferLayout &layout);
+
+} // namespace analyze_os_log
+} // namespace clang
+#endif
diff --git a/include/clang/Analysis/Analyses/ThreadSafetyCommon.h b/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
index e3570130c2c2..8c1d1da554bd 100644
--- a/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
+++ b/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
@@ -415,25 +415,8 @@ private:
BlockInfo()
: HasBackEdges(false), UnprocessedSuccessors(0),
ProcessedPredecessors(0) {}
- BlockInfo(BlockInfo &&RHS)
- : ExitMap(std::move(RHS.ExitMap)),
- HasBackEdges(RHS.HasBackEdges),
- UnprocessedSuccessors(RHS.UnprocessedSuccessors),
- ProcessedPredecessors(RHS.ProcessedPredecessors) {}
-
- BlockInfo &operator=(BlockInfo &&RHS) {
- if (this != &RHS) {
- ExitMap = std::move(RHS.ExitMap);
- HasBackEdges = RHS.HasBackEdges;
- UnprocessedSuccessors = RHS.UnprocessedSuccessors;
- ProcessedPredecessors = RHS.ProcessedPredecessors;
- }
- return *this;
- }
-
- private:
- BlockInfo(const BlockInfo &) = delete;
- void operator=(const BlockInfo &) = delete;
+ BlockInfo(BlockInfo &&) = default;
+ BlockInfo &operator=(BlockInfo &&) = default;
};
// We implement the CFGVisitor API
diff --git a/include/clang/Analysis/Analyses/ThreadSafetyUtil.h b/include/clang/Analysis/Analyses/ThreadSafetyUtil.h
index 6ea93653b91a..cb80ce5da8d2 100644
--- a/include/clang/Analysis/Analyses/ThreadSafetyUtil.h
+++ b/include/clang/Analysis/Analyses/ThreadSafetyUtil.h
@@ -45,7 +45,7 @@ public:
MemRegionRef(llvm::BumpPtrAllocator *A) : Allocator(A) {}
void *allocate(size_t Sz) {
- return Allocator->Allocate(Sz, llvm::AlignOf<AlignmentType>::Alignment);
+ return Allocator->Allocate(Sz, alignof(AlignmentType));
}
template <typename T> T *allocateT() { return Allocator->Allocate<T>(); }
diff --git a/include/clang/Analysis/AnalysisContext.h b/include/clang/Analysis/AnalysisContext.h
index 4324a0352e3a..f6a47d646d1d 100644
--- a/include/clang/Analysis/AnalysisContext.h
+++ b/include/clang/Analysis/AnalysisContext.h
@@ -406,7 +406,8 @@ private:
};
class AnalysisDeclContextManager {
- typedef llvm::DenseMap<const Decl*, AnalysisDeclContext*> ContextMap;
+ typedef llvm::DenseMap<const Decl *, std::unique_ptr<AnalysisDeclContext>>
+ ContextMap;
ContextMap Contexts;
LocationContextManager LocContexts;
diff --git a/include/clang/Analysis/CFG.h b/include/clang/Analysis/CFG.h
index 293990c88e70..d23ed77ded13 100644
--- a/include/clang/Analysis/CFG.h
+++ b/include/clang/Analysis/CFG.h
@@ -22,6 +22,7 @@
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/raw_ostream.h"
@@ -522,11 +523,15 @@ public:
typedef AdjacentBlocks::const_iterator const_pred_iterator;
typedef AdjacentBlocks::reverse_iterator pred_reverse_iterator;
typedef AdjacentBlocks::const_reverse_iterator const_pred_reverse_iterator;
+ typedef llvm::iterator_range<pred_iterator> pred_range;
+ typedef llvm::iterator_range<const_pred_iterator> pred_const_range;
typedef AdjacentBlocks::iterator succ_iterator;
typedef AdjacentBlocks::const_iterator const_succ_iterator;
typedef AdjacentBlocks::reverse_iterator succ_reverse_iterator;
typedef AdjacentBlocks::const_reverse_iterator const_succ_reverse_iterator;
+ typedef llvm::iterator_range<succ_iterator> succ_range;
+ typedef llvm::iterator_range<const_succ_iterator> succ_const_range;
pred_iterator pred_begin() { return Preds.begin(); }
pred_iterator pred_end() { return Preds.end(); }
@@ -538,6 +543,13 @@ public:
const_pred_reverse_iterator pred_rbegin() const { return Preds.rbegin(); }
const_pred_reverse_iterator pred_rend() const { return Preds.rend(); }
+ pred_range preds() {
+ return pred_range(pred_begin(), pred_end());
+ }
+ pred_const_range preds() const {
+ return pred_const_range(pred_begin(), pred_end());
+ }
+
succ_iterator succ_begin() { return Succs.begin(); }
succ_iterator succ_end() { return Succs.end(); }
const_succ_iterator succ_begin() const { return Succs.begin(); }
@@ -548,6 +560,13 @@ public:
const_succ_reverse_iterator succ_rbegin() const { return Succs.rbegin(); }
const_succ_reverse_iterator succ_rend() const { return Succs.rend(); }
+ succ_range succs() {
+ return succ_range(succ_begin(), succ_end());
+ }
+ succ_const_range succs() const {
+ return succ_const_range(succ_begin(), succ_end());
+ }
+
unsigned succ_size() const { return Succs.size(); }
bool succ_empty() const { return Succs.empty(); }
@@ -761,55 +780,6 @@ public:
AddCXXNewAllocator(false), AddCXXDefaultInitExprInCtors(false) {}
};
- /// \brief Provides a custom implementation of the iterator class to have the
- /// same interface as Function::iterator - iterator returns CFGBlock
- /// (not a pointer to CFGBlock).
- class graph_iterator {
- public:
- typedef CFGBlock value_type;
- typedef value_type& reference;
- typedef value_type* pointer;
- typedef BumpVector<CFGBlock*>::iterator ImplTy;
-
- graph_iterator(const ImplTy &i) : I(i) {}
-
- bool operator==(const graph_iterator &X) const { return I == X.I; }
- bool operator!=(const graph_iterator &X) const { return I != X.I; }
-
- reference operator*() const { return **I; }
- pointer operator->() const { return *I; }
- operator CFGBlock* () { return *I; }
-
- graph_iterator &operator++() { ++I; return *this; }
- graph_iterator &operator--() { --I; return *this; }
-
- private:
- ImplTy I;
- };
-
- class const_graph_iterator {
- public:
- typedef const CFGBlock value_type;
- typedef value_type& reference;
- typedef value_type* pointer;
- typedef BumpVector<CFGBlock*>::const_iterator ImplTy;
-
- const_graph_iterator(const ImplTy &i) : I(i) {}
-
- bool operator==(const const_graph_iterator &X) const { return I == X.I; }
- bool operator!=(const const_graph_iterator &X) const { return I != X.I; }
-
- reference operator*() const { return **I; }
- pointer operator->() const { return *I; }
- operator CFGBlock* () const { return *I; }
-
- const_graph_iterator &operator++() { ++I; return *this; }
- const_graph_iterator &operator--() { --I; return *this; }
-
- private:
- ImplTy I;
- };
-
/// buildCFG - Builds a CFG from an AST.
static std::unique_ptr<CFG> buildCFG(const Decl *D, Stmt *AST, ASTContext *C,
const BuildOptions &BO);
@@ -845,14 +815,10 @@ public:
const_iterator begin() const { return Blocks.begin(); }
const_iterator end() const { return Blocks.end(); }
- graph_iterator nodes_begin() { return graph_iterator(Blocks.begin()); }
- graph_iterator nodes_end() { return graph_iterator(Blocks.end()); }
- const_graph_iterator nodes_begin() const {
- return const_graph_iterator(Blocks.begin());
- }
- const_graph_iterator nodes_end() const {
- return const_graph_iterator(Blocks.end());
- }
+ iterator nodes_begin() { return iterator(Blocks.begin()); }
+ iterator nodes_end() { return iterator(Blocks.end()); }
+ const_iterator nodes_begin() const { return const_iterator(Blocks.begin()); }
+ const_iterator nodes_end() const { return const_iterator(Blocks.end()); }
reverse_iterator rbegin() { return Blocks.rbegin(); }
reverse_iterator rend() { return Blocks.rend(); }
@@ -893,6 +859,7 @@ public:
typedef llvm::DenseMap<const DeclStmt *, const DeclStmt *>::const_iterator
synthetic_stmt_iterator;
+ typedef llvm::iterator_range<synthetic_stmt_iterator> synthetic_stmt_range;
/// Iterates over synthetic DeclStmts in the CFG.
///
@@ -908,6 +875,11 @@ public:
return SyntheticDeclStmts.end();
}
+ /// \sa synthetic_stmt_begin
+ synthetic_stmt_range synthetic_stmts() const {
+ return synthetic_stmt_range(synthetic_stmt_begin(), synthetic_stmt_end());
+ }
+
//===--------------------------------------------------------------------===//
// Member templates useful for various batch operations over CFGs.
//===--------------------------------------------------------------------===//
@@ -998,59 +970,51 @@ template <> struct simplify_type< ::clang::CFGTerminator> {
// Traits for: CFGBlock
template <> struct GraphTraits< ::clang::CFGBlock *> {
- typedef ::clang::CFGBlock NodeType;
+ typedef ::clang::CFGBlock *NodeRef;
typedef ::clang::CFGBlock::succ_iterator ChildIteratorType;
- static NodeType* getEntryNode(::clang::CFGBlock *BB)
- { return BB; }
+ static NodeRef getEntryNode(::clang::CFGBlock *BB) { return BB; }
- static inline ChildIteratorType child_begin(NodeType* N)
- { return N->succ_begin(); }
+ static ChildIteratorType child_begin(NodeRef N) { return N->succ_begin(); }
- static inline ChildIteratorType child_end(NodeType* N)
- { return N->succ_end(); }
+ static ChildIteratorType child_end(NodeRef N) { return N->succ_end(); }
};
template <> struct GraphTraits< const ::clang::CFGBlock *> {
- typedef const ::clang::CFGBlock NodeType;
+ typedef const ::clang::CFGBlock *NodeRef;
typedef ::clang::CFGBlock::const_succ_iterator ChildIteratorType;
- static NodeType* getEntryNode(const clang::CFGBlock *BB)
- { return BB; }
+ static NodeRef getEntryNode(const clang::CFGBlock *BB) { return BB; }
- static inline ChildIteratorType child_begin(NodeType* N)
- { return N->succ_begin(); }
+ static ChildIteratorType child_begin(NodeRef N) { return N->succ_begin(); }
- static inline ChildIteratorType child_end(NodeType* N)
- { return N->succ_end(); }
+ static ChildIteratorType child_end(NodeRef N) { return N->succ_end(); }
};
template <> struct GraphTraits<Inverse< ::clang::CFGBlock*> > {
- typedef ::clang::CFGBlock NodeType;
+ typedef ::clang::CFGBlock *NodeRef;
typedef ::clang::CFGBlock::const_pred_iterator ChildIteratorType;
- static NodeType *getEntryNode(Inverse< ::clang::CFGBlock*> G)
- { return G.Graph; }
+ static NodeRef getEntryNode(Inverse<::clang::CFGBlock *> G) {
+ return G.Graph;
+ }
- static inline ChildIteratorType child_begin(NodeType* N)
- { return N->pred_begin(); }
+ static ChildIteratorType child_begin(NodeRef N) { return N->pred_begin(); }
- static inline ChildIteratorType child_end(NodeType* N)
- { return N->pred_end(); }
+ static ChildIteratorType child_end(NodeRef N) { return N->pred_end(); }
};
template <> struct GraphTraits<Inverse<const ::clang::CFGBlock*> > {
- typedef const ::clang::CFGBlock NodeType;
+ typedef const ::clang::CFGBlock *NodeRef;
typedef ::clang::CFGBlock::const_pred_iterator ChildIteratorType;
- static NodeType *getEntryNode(Inverse<const ::clang::CFGBlock*> G)
- { return G.Graph; }
+ static NodeRef getEntryNode(Inverse<const ::clang::CFGBlock *> G) {
+ return G.Graph;
+ }
- static inline ChildIteratorType child_begin(NodeType* N)
- { return N->pred_begin(); }
+ static ChildIteratorType child_begin(NodeRef N) { return N->pred_begin(); }
- static inline ChildIteratorType child_end(NodeType* N)
- { return N->pred_end(); }
+ static ChildIteratorType child_end(NodeRef N) { return N->pred_end(); }
};
// Traits for: CFG
@@ -1058,9 +1022,9 @@ template <> struct GraphTraits<Inverse<const ::clang::CFGBlock*> > {
template <> struct GraphTraits< ::clang::CFG* >
: public GraphTraits< ::clang::CFGBlock *> {
- typedef ::clang::CFG::graph_iterator nodes_iterator;
+ typedef ::clang::CFG::iterator nodes_iterator;
- static NodeType *getEntryNode(::clang::CFG* F) { return &F->getEntry(); }
+ static NodeRef getEntryNode(::clang::CFG *F) { return &F->getEntry(); }
static nodes_iterator nodes_begin(::clang::CFG* F) { return F->nodes_begin();}
static nodes_iterator nodes_end(::clang::CFG* F) { return F->nodes_end(); }
static unsigned size(::clang::CFG* F) { return F->size(); }
@@ -1069,11 +1033,9 @@ template <> struct GraphTraits< ::clang::CFG* >
template <> struct GraphTraits<const ::clang::CFG* >
: public GraphTraits<const ::clang::CFGBlock *> {
- typedef ::clang::CFG::const_graph_iterator nodes_iterator;
+ typedef ::clang::CFG::const_iterator nodes_iterator;
- static NodeType *getEntryNode( const ::clang::CFG* F) {
- return &F->getEntry();
- }
+ static NodeRef getEntryNode(const ::clang::CFG *F) { return &F->getEntry(); }
static nodes_iterator nodes_begin( const ::clang::CFG* F) {
return F->nodes_begin();
}
@@ -1088,9 +1050,9 @@ template <> struct GraphTraits<const ::clang::CFG* >
template <> struct GraphTraits<Inverse< ::clang::CFG*> >
: public GraphTraits<Inverse< ::clang::CFGBlock*> > {
- typedef ::clang::CFG::graph_iterator nodes_iterator;
+ typedef ::clang::CFG::iterator nodes_iterator;
- static NodeType *getEntryNode( ::clang::CFG* F) { return &F->getExit(); }
+ static NodeRef getEntryNode(::clang::CFG *F) { return &F->getExit(); }
static nodes_iterator nodes_begin( ::clang::CFG* F) {return F->nodes_begin();}
static nodes_iterator nodes_end( ::clang::CFG* F) { return F->nodes_end(); }
};
@@ -1098,9 +1060,9 @@ template <> struct GraphTraits<Inverse< ::clang::CFG*> >
template <> struct GraphTraits<Inverse<const ::clang::CFG*> >
: public GraphTraits<Inverse<const ::clang::CFGBlock*> > {
- typedef ::clang::CFG::const_graph_iterator nodes_iterator;
+ typedef ::clang::CFG::const_iterator nodes_iterator;
- static NodeType *getEntryNode(const ::clang::CFG* F) { return &F->getExit(); }
+ static NodeRef getEntryNode(const ::clang::CFG *F) { return &F->getExit(); }
static nodes_iterator nodes_begin(const ::clang::CFG* F) {
return F->nodes_begin();
}
diff --git a/include/clang/Analysis/CallGraph.h b/include/clang/Analysis/CallGraph.h
index eda22a57e8a5..b8ae67cbba49 100644
--- a/include/clang/Analysis/CallGraph.h
+++ b/include/clang/Analysis/CallGraph.h
@@ -34,7 +34,8 @@ class CallGraphNode;
class CallGraph : public RecursiveASTVisitor<CallGraph> {
friend class CallGraphNode;
- typedef llvm::DenseMap<const Decl *, CallGraphNode *> FunctionMapTy;
+ typedef llvm::DenseMap<const Decl *, std::unique_ptr<CallGraphNode>>
+ FunctionMapTy;
/// FunctionMap owns all CallGraphNodes.
FunctionMapTy FunctionMap;
@@ -156,7 +157,7 @@ public:
inline bool empty() const {return CalledFunctions.empty(); }
inline unsigned size() const {return CalledFunctions.size(); }
- void addCallee(CallGraphNode *N, CallGraph *CG) {
+ void addCallee(CallGraphNode *N) {
CalledFunctions.push_back(N);
}
@@ -172,25 +173,21 @@ public:
namespace llvm {
template <> struct GraphTraits<clang::CallGraphNode*> {
typedef clang::CallGraphNode NodeType;
- typedef clang::CallGraphNode::CallRecord CallRecordTy;
- typedef std::pointer_to_unary_function<CallRecordTy,
- clang::CallGraphNode*> CGNDerefFun;
+ typedef clang::CallGraphNode *NodeRef;
+ typedef NodeType::iterator ChildIteratorType;
+
static NodeType *getEntryNode(clang::CallGraphNode *CGN) { return CGN; }
- typedef mapped_iterator<NodeType::iterator, CGNDerefFun> ChildIteratorType;
static inline ChildIteratorType child_begin(NodeType *N) {
- return map_iterator(N->begin(), CGNDerefFun(CGNDeref));
- }
- static inline ChildIteratorType child_end (NodeType *N) {
- return map_iterator(N->end(), CGNDerefFun(CGNDeref));
- }
- static clang::CallGraphNode *CGNDeref(CallRecordTy P) {
- return P;
+ return N->begin();
}
+ static inline ChildIteratorType child_end(NodeType *N) { return N->end(); }
};
template <> struct GraphTraits<const clang::CallGraphNode*> {
typedef const clang::CallGraphNode NodeType;
+ typedef const clang::CallGraphNode *NodeRef;
typedef NodeType::const_iterator ChildIteratorType;
+
static NodeType *getEntryNode(const clang::CallGraphNode *CGN) { return CGN; }
static inline ChildIteratorType child_begin(NodeType *N) { return N->begin();}
static inline ChildIteratorType child_end(NodeType *N) { return N->end(); }
@@ -202,19 +199,21 @@ template <> struct GraphTraits<clang::CallGraph*>
static NodeType *getEntryNode(clang::CallGraph *CGN) {
return CGN->getRoot(); // Start at the external node!
}
- typedef std::pair<const clang::Decl*, clang::CallGraphNode*> PairTy;
- typedef std::pointer_to_unary_function<PairTy, clang::CallGraphNode&> DerefFun;
+
+ static clang::CallGraphNode *
+ CGGetValue(clang::CallGraph::const_iterator::value_type &P) {
+ return P.second.get();
+ }
+
// nodes_iterator/begin/end - Allow iteration over all nodes in the graph
- typedef mapped_iterator<clang::CallGraph::iterator, DerefFun> nodes_iterator;
+ typedef mapped_iterator<clang::CallGraph::iterator, decltype(&CGGetValue)>
+ nodes_iterator;
static nodes_iterator nodes_begin(clang::CallGraph *CG) {
- return map_iterator(CG->begin(), DerefFun(CGdereference));
+ return nodes_iterator(CG->begin(), &CGGetValue);
}
static nodes_iterator nodes_end (clang::CallGraph *CG) {
- return map_iterator(CG->end(), DerefFun(CGdereference));
- }
- static clang::CallGraphNode &CGdereference(PairTy P) {
- return *(P.second);
+ return nodes_iterator(CG->end(), &CGGetValue);
}
static unsigned size(clang::CallGraph *CG) {
@@ -227,22 +226,23 @@ template <> struct GraphTraits<const clang::CallGraph*> :
static NodeType *getEntryNode(const clang::CallGraph *CGN) {
return CGN->getRoot();
}
- typedef std::pair<const clang::Decl*, clang::CallGraphNode*> PairTy;
- typedef std::pointer_to_unary_function<PairTy, clang::CallGraphNode&> DerefFun;
+
+ static clang::CallGraphNode *
+ CGGetValue(clang::CallGraph::const_iterator::value_type &P) {
+ return P.second.get();
+ }
+
// nodes_iterator/begin/end - Allow iteration over all nodes in the graph
typedef mapped_iterator<clang::CallGraph::const_iterator,
- DerefFun> nodes_iterator;
+ decltype(&CGGetValue)>
+ nodes_iterator;
static nodes_iterator nodes_begin(const clang::CallGraph *CG) {
- return map_iterator(CG->begin(), DerefFun(CGdereference));
+ return nodes_iterator(CG->begin(), &CGGetValue);
}
static nodes_iterator nodes_end(const clang::CallGraph *CG) {
- return map_iterator(CG->end(), DerefFun(CGdereference));
- }
- static clang::CallGraphNode &CGdereference(PairTy P) {
- return *(P.second);
+ return nodes_iterator(CG->end(), &CGGetValue);
}
-
static unsigned size(const clang::CallGraph *CG) {
return CG->size();
}
diff --git a/include/clang/Analysis/CloneDetection.h b/include/clang/Analysis/CloneDetection.h
new file mode 100644
index 000000000000..51cad7a96d6f
--- /dev/null
+++ b/include/clang/Analysis/CloneDetection.h
@@ -0,0 +1,288 @@
+//===--- CloneDetection.h - Finds code clones in an AST ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// /file
+/// This file defines classes for searching and anlyzing source code clones.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_CLONEDETECTION_H
+#define LLVM_CLANG_AST_CLONEDETECTION_H
+
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/StringMap.h"
+
+#include <vector>
+
+namespace clang {
+
+class Stmt;
+class Decl;
+class VarDecl;
+class ASTContext;
+class CompoundStmt;
+
+/// \brief Identifies a list of statements.
+///
+/// Can either identify a single arbitrary Stmt object, a continuous sequence of
+/// child statements inside a CompoundStmt or no statements at all.
+class StmtSequence {
+ /// If this object identifies a sequence of statements inside a CompoundStmt,
+ /// S points to this CompoundStmt. If this object only identifies a single
+ /// Stmt, then S is a pointer to this Stmt.
+ const Stmt *S;
+
+ /// The related ASTContext for S.
+ ASTContext *Context;
+
+ /// If EndIndex is non-zero, then S is a CompoundStmt and this StmtSequence
+ /// instance is representing the CompoundStmt children inside the array
+ /// [StartIndex, EndIndex).
+ unsigned StartIndex;
+ unsigned EndIndex;
+
+public:
+ /// \brief Constructs a StmtSequence holding multiple statements.
+ ///
+ /// The resulting StmtSequence identifies a continuous sequence of statements
+ /// in the body of the given CompoundStmt. Which statements of the body should
+ /// be identified needs to be specified by providing a start and end index
+ /// that describe a non-empty sub-array in the body of the given CompoundStmt.
+ ///
+ /// \param Stmt A CompoundStmt that contains all statements in its body.
+ /// \param Context The ASTContext for the given CompoundStmt.
+ /// \param StartIndex The inclusive start index in the children array of
+ /// \p Stmt
+ /// \param EndIndex The exclusive end index in the children array of \p Stmt.
+ StmtSequence(const CompoundStmt *Stmt, ASTContext &Context,
+ unsigned StartIndex, unsigned EndIndex);
+
+ /// \brief Constructs a StmtSequence holding a single statement.
+ ///
+ /// \param Stmt An arbitrary Stmt.
+ /// \param Context The ASTContext for the given Stmt.
+ StmtSequence(const Stmt *Stmt, ASTContext &Context);
+
+ /// \brief Constructs an empty StmtSequence.
+ StmtSequence();
+
+ typedef const Stmt *const *iterator;
+
+ /// Returns an iterator pointing to the first statement in this sequence.
+ iterator begin() const;
+
+ /// Returns an iterator pointing behind the last statement in this sequence.
+ iterator end() const;
+
+ /// Returns the first statement in this sequence.
+ ///
+ /// This method should only be called on a non-empty StmtSequence object.
+ const Stmt *front() const {
+ assert(!empty());
+ return begin()[0];
+ }
+
+ /// Returns the last statement in this sequence.
+ ///
+ /// This method should only be called on a non-empty StmtSequence object.
+ const Stmt *back() const {
+ assert(!empty());
+ return begin()[size() - 1];
+ }
+
+ /// Returns the number of statements this object holds.
+ unsigned size() const {
+ if (holdsSequence())
+ return EndIndex - StartIndex;
+ if (S == nullptr)
+ return 0;
+ return 1;
+ }
+
+ /// Returns true if and only if this StmtSequence contains no statements.
+ bool empty() const { return size() == 0; }
+
+ /// Returns the related ASTContext for the stored Stmts.
+ ASTContext &getASTContext() const {
+ assert(Context);
+ return *Context;
+ }
+
+ /// Returns true if this objects holds a list of statements.
+ bool holdsSequence() const { return EndIndex != 0; }
+
+ /// Returns the start sourcelocation of the first statement in this sequence.
+ ///
+ /// This method should only be called on a non-empty StmtSequence object.
+ SourceLocation getStartLoc() const;
+
+ /// Returns the end sourcelocation of the last statement in this sequence.
+ ///
+ /// This method should only be called on a non-empty StmtSequence object.
+ SourceLocation getEndLoc() const;
+
+ /// Returns the source range of the whole sequence - from the beginning
+ /// of the first statement to the end of the last statement.
+ SourceRange getSourceRange() const;
+
+ bool operator==(const StmtSequence &Other) const {
+ return std::tie(S, StartIndex, EndIndex) ==
+ std::tie(Other.S, Other.StartIndex, Other.EndIndex);
+ }
+
+ bool operator!=(const StmtSequence &Other) const {
+ return std::tie(S, StartIndex, EndIndex) !=
+ std::tie(Other.S, Other.StartIndex, Other.EndIndex);
+ }
+
+ /// Returns true if and only if this sequence covers a source range that
+ /// contains the source range of the given sequence \p Other.
+ ///
+ /// This method should only be called on a non-empty StmtSequence object
+ /// and passed a non-empty StmtSequence object.
+ bool contains(const StmtSequence &Other) const;
+};
+
+/// \brief Searches for clones in source code.
+///
+/// First, this class needs a translation unit which is passed via
+/// \p analyzeTranslationUnit . It will then generate and store search data
+/// for all statements inside the given translation unit.
+/// Afterwards the generated data can be used to find code clones by calling
+/// \p findClones .
+///
+/// This class only searches for clones in exectuable source code
+/// (e.g. function bodies). Other clones (e.g. cloned comments or declarations)
+/// are not supported.
+class CloneDetector {
+public:
+ typedef unsigned DataPiece;
+
+ /// Holds the data about a StmtSequence that is needed during the search for
+ /// code clones.
+ struct CloneSignature {
+ /// \brief The hash code of the StmtSequence.
+ ///
+ /// The initial clone groups that are formed during the search for clones
+ /// consist only of Sequences that share the same hash code. This makes this
+ /// value the central part of this heuristic that is needed to find clones
+ /// in a performant way. For this to work, the type of this variable
+ /// always needs to be small and fast to compare.
+ ///
+ /// Also, StmtSequences that are clones of each others have to share
+ /// the same hash code. StmtSequences that are not clones of each other
+ /// shouldn't share the same hash code, but if they do, it will only
+ /// degrade the performance of the hash search but doesn't influence
+ /// the correctness of the result.
+ size_t Hash;
+
+ /// \brief The complexity of the StmtSequence.
+ ///
+ /// This value gives an approximation on how many direct or indirect child
+ /// statements are contained in the related StmtSequence. In general, the
+ /// greater this value, the greater the amount of statements. However, this
+ /// is only an approximation and the actual amount of statements can be
+ /// higher or lower than this value. Statements that are generated by the
+ /// compiler (e.g. macro expansions) for example barely influence the
+ /// complexity value.
+ ///
+ /// The main purpose of this value is to filter clones that are too small
+ /// and therefore probably not interesting enough for the user.
+ unsigned Complexity;
+
+ /// \brief Creates an empty CloneSignature without any data.
+ CloneSignature() : Complexity(1) {}
+
+ CloneSignature(llvm::hash_code Hash, unsigned Complexity)
+ : Hash(Hash), Complexity(Complexity) {}
+ };
+
+ /// Holds group of StmtSequences that are clones of each other and the
+ /// complexity value (see CloneSignature::Complexity) that all stored
+ /// StmtSequences have in common.
+ struct CloneGroup {
+ std::vector<StmtSequence> Sequences;
+ CloneSignature Signature;
+
+ CloneGroup() {}
+
+ CloneGroup(const StmtSequence &Seq, CloneSignature Signature)
+ : Signature(Signature) {
+ Sequences.push_back(Seq);
+ }
+
+ /// \brief Returns false if and only if this group should be skipped when
+ /// searching for clones.
+ bool isValid() const {
+ // A clone group with only one member makes no sense, so we skip them.
+ return Sequences.size() > 1;
+ }
+ };
+
+ /// \brief Generates and stores search data for all statements in the body of
+ /// the given Decl.
+ void analyzeCodeBody(const Decl *D);
+
+ /// \brief Stores the CloneSignature to allow future querying.
+ void add(const StmtSequence &S, const CloneSignature &Signature);
+
+ /// \brief Searches the provided statements for clones.
+ ///
+ /// \param Result Output parameter that is filled with a list of found
+ /// clone groups. Each group contains multiple StmtSequences
+ /// that were identified to be clones of each other.
+ /// \param MinGroupComplexity Only return clones which have at least this
+ /// complexity value.
+ /// \param CheckPatterns Returns only clone groups in which the referenced
+ /// variables follow the same pattern.
+ void findClones(std::vector<CloneGroup> &Result, unsigned MinGroupComplexity,
+ bool CheckPatterns = true);
+
+ /// \brief Describes two clones that reference their variables in a different
+ /// pattern which could indicate a programming error.
+ struct SuspiciousClonePair {
+ /// \brief Utility class holding the relevant information about a single
+ /// clone in this pair.
+ struct SuspiciousCloneInfo {
+ /// The variable which referencing in this clone was against the pattern.
+ const VarDecl *Variable;
+ /// Where the variable was referenced.
+ const Stmt *Mention;
+ /// The variable that should have been referenced to follow the pattern.
+ /// If Suggestion is a nullptr then it's not possible to fix the pattern
+ /// by referencing a different variable in this clone.
+ const VarDecl *Suggestion;
+ SuspiciousCloneInfo(const VarDecl *Variable, const Stmt *Mention,
+ const VarDecl *Suggestion)
+ : Variable(Variable), Mention(Mention), Suggestion(Suggestion) {}
+ SuspiciousCloneInfo() {}
+ };
+ /// The first clone in the pair which always has a suggested variable.
+ SuspiciousCloneInfo FirstCloneInfo;
+ /// This other clone in the pair which can have a suggested variable.
+ SuspiciousCloneInfo SecondCloneInfo;
+ };
+
+ /// \brief Searches the provided statements for pairs of clones that don't
+ /// follow the same pattern when referencing variables.
+ /// \param Result Output parameter that will contain the clone pairs.
+ /// \param MinGroupComplexity Only clone pairs in which the clones have at
+ /// least this complexity value.
+ void findSuspiciousClones(std::vector<SuspiciousClonePair> &Result,
+ unsigned MinGroupComplexity);
+
+private:
+ /// Stores all encountered StmtSequences alongside their CloneSignature.
+ std::vector<std::pair<CloneSignature, StmtSequence>> Sequences;
+};
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_AST_CLONEDETECTION_H
diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h
index 5045194ef864..be5adfb29423 100644
--- a/include/clang/Analysis/ProgramPoint.h
+++ b/include/clang/Analysis/ProgramPoint.h
@@ -622,8 +622,8 @@ private:
class CallExitBegin : public ProgramPoint {
public:
// CallExitBegin uses the callee's location context.
- CallExitBegin(const StackFrameContext *L)
- : ProgramPoint(nullptr, CallExitBeginKind, L, nullptr) {}
+ CallExitBegin(const StackFrameContext *L, const ReturnStmt *RS)
+ : ProgramPoint(RS, CallExitBeginKind, L, nullptr) { }
private:
friend class ProgramPoint;
diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td
index 7da1efe5ff40..107a3bdffa65 100644
--- a/include/clang/Basic/Attr.td
+++ b/include/clang/Basic/Attr.td
@@ -198,6 +198,7 @@ class Spelling<string name, string variety> {
class GNU<string name> : Spelling<name, "GNU">;
class Declspec<string name> : Spelling<name, "Declspec">;
+class Microsoft<string name> : Spelling<name, "Microsoft">;
class CXX11<string namespace, string name, int version = 1>
: Spelling<name, "CXX11"> {
string Namespace = namespace;
@@ -241,6 +242,7 @@ def MicrosoftExt : LangOpt<"MicrosoftExt">;
def Borland : LangOpt<"Borland">;
def CUDA : LangOpt<"CUDA">;
def COnly : LangOpt<"CPlusPlus", 1>;
+def CPlusPlus : LangOpt<"CPlusPlus">;
def OpenCL : LangOpt<"OpenCL">;
def RenderScript : LangOpt<"RenderScript">;
@@ -252,7 +254,7 @@ class TargetArch<list<string> arches> {
list<string> OSes;
list<string> CXXABIs;
}
-def TargetARM : TargetArch<["arm", "thumb"]>;
+def TargetARM : TargetArch<["arm", "thumb", "armeb", "thumbeb"]>;
def TargetMips : TargetArch<["mips", "mipsel"]>;
def TargetMSP430 : TargetArch<["msp430"]>;
def TargetX86 : TargetArch<["x86"]>;
@@ -380,7 +382,7 @@ def Alias : Attr {
let Spellings = [GCC<"alias">];
let Args = [StringArgument<"Aliasee">];
let Subjects = SubjectList<[Function, GlobalVar], ErrorDiag,
- "ExpectedFunctionGlobalVarMethodOrProperty">;
+ "ExpectedFunctionOrGlobalVar">;
let Documentation = [Undocumented];
}
@@ -778,6 +780,14 @@ def EmptyBases : InheritableAttr, TargetSpecificAttr<TargetMicrosoftCXXABI> {
let Documentation = [EmptyBasesDocs];
}
+def AllocSize : InheritableAttr {
+ let Spellings = [GCC<"alloc_size">];
+ let Subjects = SubjectList<[Function]>;
+ let Args = [IntArgument<"ElemSizeParam">, IntArgument<"NumElemsParam", 1>];
+ let TemplateDependent = 1;
+ let Documentation = [AllocSizeDocs];
+}
+
def EnableIf : InheritableAttr {
let Spellings = [GNU<"enable_if">];
let Subjects = SubjectList<[Function]>;
@@ -808,6 +818,11 @@ def FastCall : InheritableAttr {
let Documentation = [FastCallDocs];
}
+def RegCall : InheritableAttr {
+ let Spellings = [GCC<"regcall">, Keyword<"__regcall">];
+ let Documentation = [RegCallDocs];
+}
+
def Final : InheritableAttr {
let Spellings = [Keyword<"final">, Keyword<"sealed">];
let Accessors = [Accessor<"isSpelledAsSealed", [Keyword<"sealed">]>];
@@ -1024,6 +1039,12 @@ def NoDuplicate : InheritableAttr {
let Documentation = [NoDuplicateDocs];
}
+def Convergent : InheritableAttr {
+ let Spellings = [GNU<"convergent">, CXX11<"clang", "convergent">];
+ let Subjects = SubjectList<[Function]>;
+ let Documentation = [ConvergentDocs];
+}
+
def NoInline : InheritableAttr {
let Spellings = [GCC<"noinline">, Declspec<"noinline">];
let Subjects = SubjectList<[Function]>;
@@ -1048,24 +1069,37 @@ def NoMips16 : InheritableAttr, TargetSpecificAttr<TargetMips> {
//
// FIXME: This provides a sub-optimal error message if you attempt to
// use this in CUDA, since CUDA does not use the same terminology.
-def AMDGPUNumVGPR : InheritableAttr {
- let Spellings = [GNU<"amdgpu_num_vgpr">];
- let Args = [UnsignedArgument<"NumVGPR">];
- let Documentation = [AMDGPUNumVGPRDocs];
-
-// FIXME: This should be for OpenCLKernelFunction, but is not to
+//
+// FIXME: SubjectList should be for OpenCLKernelFunction, but is not to
// workaround needing to see kernel attribute before others to know if
// this should be rejected on non-kernels.
- let Subjects = SubjectList<[Function], ErrorDiag,
- "ExpectedKernelFunction">;
+
+def AMDGPUFlatWorkGroupSize : InheritableAttr {
+ let Spellings = [GNU<"amdgpu_flat_work_group_size">];
+ let Args = [UnsignedArgument<"Min">, UnsignedArgument<"Max">];
+ let Documentation = [AMDGPUFlatWorkGroupSizeDocs];
+ let Subjects = SubjectList<[Function], ErrorDiag, "ExpectedKernelFunction">;
+}
+
+def AMDGPUWavesPerEU : InheritableAttr {
+ let Spellings = [GNU<"amdgpu_waves_per_eu">];
+ let Args = [UnsignedArgument<"Min">, UnsignedArgument<"Max", 1>];
+ let Documentation = [AMDGPUWavesPerEUDocs];
+ let Subjects = SubjectList<[Function], ErrorDiag, "ExpectedKernelFunction">;
}
def AMDGPUNumSGPR : InheritableAttr {
let Spellings = [GNU<"amdgpu_num_sgpr">];
let Args = [UnsignedArgument<"NumSGPR">];
- let Documentation = [AMDGPUNumSGPRDocs];
- let Subjects = SubjectList<[Function], ErrorDiag,
- "ExpectedKernelFunction">;
+ let Documentation = [AMDGPUNumSGPRNumVGPRDocs];
+ let Subjects = SubjectList<[Function], ErrorDiag, "ExpectedKernelFunction">;
+}
+
+def AMDGPUNumVGPR : InheritableAttr {
+ let Spellings = [GNU<"amdgpu_num_vgpr">];
+ let Args = [UnsignedArgument<"NumVGPR">];
+ let Documentation = [AMDGPUNumSGPRNumVGPRDocs];
+ let Subjects = SubjectList<[Function], ErrorDiag, "ExpectedKernelFunction">;
}
def NoSplitStack : InheritableAttr {
@@ -1270,6 +1304,12 @@ def ObjCRootClass : InheritableAttr {
let Documentation = [Undocumented];
}
+def ObjCSubclassingRestricted : InheritableAttr {
+ let Spellings = [GNU<"objc_subclassing_restricted">];
+ let Subjects = SubjectList<[ObjCInterface], ErrorDiag>;
+ let Documentation = [ObjCSubclassingRestrictedDocs];
+}
+
def ObjCExplicitProtocolImpl : InheritableAttr {
let Spellings = [GNU<"objc_protocol_requires_explicit_implementation">];
let Subjects = SubjectList<[ObjCProtocol], ErrorDiag>;
@@ -1380,6 +1420,15 @@ def ReqdWorkGroupSize : InheritableAttr {
let Documentation = [Undocumented];
}
+def RequireConstantInit : InheritableAttr {
+ let Spellings = [GNU<"require_constant_initialization">,
+ CXX11<"clang", "require_constant_initialization">];
+ let Subjects = SubjectList<[GlobalVar], ErrorDiag,
+ "ExpectedStaticOrTLSVar">;
+ let Documentation = [RequireConstantInitDocs];
+ let LangOpts = [CPlusPlus];
+}
+
def WorkGroupSizeHint : InheritableAttr {
let Spellings = [GNU<"work_group_size_hint">];
let Args = [UnsignedArgument<"XDim">,
@@ -1518,7 +1567,8 @@ def Target : InheritableAttr {
def TransparentUnion : InheritableAttr {
let Spellings = [GCC<"transparent_union">];
// let Subjects = SubjectList<[Record, TypedefName]>;
- let Documentation = [Undocumented];
+ let Documentation = [TransparentUnionDocs];
+ let LangOpts = [COnly];
}
def Unavailable : InheritableAttr {
@@ -1574,9 +1624,11 @@ def Used : InheritableAttr {
}
def Uuid : InheritableAttr {
- let Spellings = [Declspec<"uuid">];
+ let Spellings = [Declspec<"uuid">, Microsoft<"uuid">];
let Args = [StringArgument<"Guid">];
-// let Subjects = SubjectList<[CXXRecord]>;
+ let Subjects = SubjectList<[Record, Enum], WarnDiag, "ExpectedEnumOrClass">;
+ // FIXME: Allow expressing logical AND for LangOpts. Our condition should be:
+ // CPlusPlus && (MicrosoftExt || Borland)
let LangOpts = [MicrosoftExt, Borland];
let Documentation = [Undocumented];
}
@@ -1680,7 +1732,8 @@ def X86ForceAlignArgPointer : InheritableAttr, TargetSpecificAttr<TargetX86> {
def NoSanitize : InheritableAttr {
let Spellings = [GNU<"no_sanitize">, CXX11<"clang", "no_sanitize">];
let Args = [VariadicStringArgument<"Sanitizers">];
- let Subjects = SubjectList<[Function, ObjCMethod], ErrorDiag>;
+ let Subjects = SubjectList<[Function, ObjCMethod, GlobalVar], ErrorDiag,
+ "ExpectedFunctionMethodOrGlobalVar">;
let Documentation = [NoSanitizeDocs];
let AdditionalMembers = [{
SanitizerMask getMask() const {
@@ -1702,7 +1755,8 @@ def NoSanitizeSpecific : InheritableAttr {
GCC<"no_sanitize_address">,
GCC<"no_sanitize_thread">,
GNU<"no_sanitize_memory">];
- let Subjects = SubjectList<[Function], ErrorDiag>;
+ let Subjects = SubjectList<[Function, GlobalVar], ErrorDiag,
+ "ExpectedFunctionOrGlobalVar">;
let Documentation = [NoSanitizeAddressDocs, NoSanitizeThreadDocs,
NoSanitizeMemoryDocs];
let ASTNode = 0;
diff --git a/include/clang/Basic/AttrDocs.td b/include/clang/Basic/AttrDocs.td
index d0342bc6038a..b57833a15f31 100644
--- a/include/clang/Basic/AttrDocs.td
+++ b/include/clang/Basic/AttrDocs.td
@@ -119,7 +119,7 @@ The ``carries_dependency`` attribute specifies dependency propagation into and
out of functions.
When specified on a function or Objective-C method, the ``carries_dependency``
-attribute means that the return value carries a dependency out of the function,
+attribute means that the return value carries a dependency out of the function,
so that the implementation need not constrain ordering upon return from that
function. Implementations of the function and its caller may choose to preserve
dependencies instead of emitting memory ordering instructions such as fences.
@@ -206,6 +206,44 @@ to enforce the provided alignment assumption.
}];
}
+def AllocSizeDocs : Documentation {
+ let Category = DocCatFunction;
+ 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.
+
+- ``alloc_size(N)`` implies that argument number N equals the number of
+ available bytes at the returned pointer.
+- ``alloc_size(N, M)`` implies that the product of argument number N and
+ argument number M equals the number of available bytes at the returned
+ pointer.
+
+Argument numbers are 1-based.
+
+An example of how to use ``alloc_size``
+
+.. code-block:: c
+
+ void *my_malloc(int a) __attribute__((alloc_size(1)));
+ void *my_calloc(int a, int b) __attribute__((alloc_size(1, 2)));
+
+ int main() {
+ void *const p = my_malloc(100);
+ assert(__builtin_object_size(p, 0) == 100);
+ void *const a = my_calloc(20, 5);
+ assert(__builtin_object_size(a, 0) == 100);
+ }
+
+.. Note:: This attribute works differently in clang than it does in GCC.
+ Specifically, clang will only trace ``const`` pointers (as above); we give up
+ on pointers that are not marked as ``const``. In the vast majority of cases,
+ this is unimportant, because LLVM has support for the ``alloc_size``
+ attribute. However, this may cause mildly unintuitive behavior when used with
+ other attributes, such as ``enable_if``.
+ }];
+}
+
def EnableIfDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
@@ -470,6 +508,12 @@ semantics:
* A conversion from type ``T`` to a value of type ``U`` is permitted if ``T``
and ``U`` are compatible types. This conversion is given "conversion" rank.
+* If no viable candidates are otherwise available, we allow a conversion from a
+ pointer of type ``T*`` to a pointer of type ``U*``, where ``T`` and ``U`` are
+ incompatible. This conversion is ranked below all other types of conversions.
+ Please note: ``U`` lacking qualifiers that are present on ``T`` is sufficient
+ for ``T`` and ``U`` to be incompatible.
+
The declaration of ``overloadable`` functions is restricted to function
declarations and definitions. Most importantly, if any function with a given
name is given the ``overloadable`` attribute, then all function declarations
@@ -600,6 +644,33 @@ of the condition.
}];
}
+def ConvergentDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+The ``convergent`` attribute can be placed on a function declaration. It is
+translated into the LLVM ``convergent`` attribute, which indicates that the call
+instructions of a function with this attribute cannot be made control-dependent
+on any additional values.
+
+In languages designed for SPMD/SIMT programming model, e.g. OpenCL or CUDA,
+the call instructions of a function with this attribute must be executed by
+all work items or threads in a work group or sub group.
+
+This attribute is different from ``noduplicate`` because it allows duplicating
+function calls if it can be proved that the duplicated function calls are
+not made control-dependent on any additional values, e.g., unrolling a loop
+executed by all work items.
+
+Sample usage:
+.. code-block:: c
+
+ void convfunc(void) __attribute__((convergent));
+ // Setting it as a C++11 attribute is also valid in a C++ program.
+ // void convfunc(void) [[clang::convergent]];
+
+ }];
+}
+
def NoSplitStackDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
@@ -685,10 +756,10 @@ This attribute specifies that the Objective-C class to which it applies is visib
def ObjCBoxableDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
-Structs and unions marked with the ``objc_boxable`` attribute can be used
+Structs and unions marked with the ``objc_boxable`` attribute can be used
with the Objective-C boxed expression syntax, ``@(...)``.
-**Usage**: ``__attribute__((objc_boxable))``. This attribute
+**Usage**: ``__attribute__((objc_boxable))``. This attribute
can only be placed on a declaration of a trivially-copyable struct or union:
.. code-block:: objc
@@ -829,6 +900,44 @@ When one method overrides another, the overriding method can be more widely avai
}];
}
+
+def RequireConstantInitDocs : Documentation {
+ let Category = DocCatVariable;
+ let Content = [{
+This attribute specifies that the variable to which it is attached is intended
+to have a `constant initializer <http://en.cppreference.com/w/cpp/language/constant_initialization>`_
+according to the rules of [basic.start.static]. The variable is required to
+have static or thread storage duration. If the initialization of the variable
+is not a constant initializer an error will be produced. This attribute may
+only be used in C++.
+
+Note that in C++03 strict constant expression checking is not done. Instead
+the attribute reports if Clang can emit the variable as a constant, even if it's
+not technically a 'constant initializer'. This behavior is non-portable.
+
+Static storage duration variables with constant initializers avoid hard-to-find
+bugs caused by the indeterminate order of dynamic initialization. They can also
+be safely used during dynamic initialization across translation units.
+
+This attribute acts as a compile time assertion that the requirements
+for constant initialization have been met. Since these requirements change
+between dialects and have subtle pitfalls it's important to fail fast instead
+of silently falling back on dynamic initialization.
+
+.. code-block:: c++
+
+ // -std=c++14
+ #define SAFE_STATIC [[clang::require_constant_initialization]]
+ struct T {
+ constexpr T(int) {}
+ ~T(); // non-trivial
+ };
+ SAFE_STATIC T x = {42}; // Initialization OK. Doesn't check destructor.
+ SAFE_STATIC T y = 42; // error: variable does not have a constant initializer
+ // copy initialization is not a constant expression on a non-literal type.
+ }];
+}
+
def WarnMaybeUnusedDocs : Documentation {
let Category = DocCatVariable;
let Heading = "maybe_unused, unused, gnu::unused";
@@ -845,12 +954,12 @@ variable, a function or method, a function parameter, an enumeration, an
enumerator, a non-static data member, or a label.
.. code-block: c++
- #include <cassert>
-
- [[maybe_unused]] void f([[maybe_unused]] bool thing1,
- [[maybe_unused]] bool thing2) {
- [[maybe_unused]] bool b = thing1 && thing2;
- assert(b);
+ #include <cassert>
+
+ [[maybe_unused]] void f([[maybe_unused]] bool thing1,
+ [[maybe_unused]] bool thing2) {
+ [[maybe_unused]] bool b = thing1 && thing2;
+ assert(b);
}
}];
}
@@ -867,16 +976,16 @@ potentially-evaluated discarded-value expression that is not explicitly cast to
`void`.
.. code-block: c++
- struct [[nodiscard]] error_info { /*...*/ };
- error_info enable_missile_safety_mode();
-
- void launch_missiles();
- void test_missiles() {
- enable_missile_safety_mode(); // diagnoses
- launch_missiles();
- }
- error_info &foo();
- void f() { foo(); } // Does not diagnose, error_info is a reference.
+ struct [[nodiscard]] error_info { /*...*/ };
+ error_info enable_missile_safety_mode();
+
+ void launch_missiles();
+ void test_missiles() {
+ enable_missile_safety_mode(); // diagnoses
+ launch_missiles();
+ }
+ error_info &foo();
+ void f() { foo(); } // Does not diagnose, error_info is a reference.
}];
}
@@ -1032,64 +1141,110 @@ the front end.
}];
}
-def DocCatAMDGPURegisterAttributes :
- DocumentationCategory<"AMD GPU Register Attributes"> {
- let Content = [{
-Clang supports attributes for controlling register usage on AMD GPU
-targets. These attributes may be attached to a kernel function
-definition and is an optimization hint to the backend for the maximum
-number of registers to use. This is useful in cases where register
-limited occupancy is known to be an important factor for the
-performance for the kernel.
-
-The semantics are as follows:
-
-- The backend will attempt to limit the number of used registers to
- the specified value, but the exact number used is not
- guaranteed. The number used may be rounded up to satisfy the
- allocation requirements or ABI constraints of the subtarget. For
- example, on Southern Islands VGPRs may only be allocated in
- increments of 4, so requesting a limit of 39 VGPRs will really
- attempt to use up to 40. Requesting more registers than the
- subtarget supports will truncate to the maximum allowed. The backend
- may also use fewer registers than requested whenever possible.
-
-- 0 implies the default no limit on register usage.
-
-- Ignored on older VLIW subtargets which did not have separate scalar
- and vector registers, R600 through Northern Islands.
-
-}];
-}
+def DocCatAMDGPUAttributes : DocumentationCategory<"AMD GPU Attributes">;
-
-def AMDGPUNumVGPRDocs : Documentation {
- let Category = DocCatAMDGPURegisterAttributes;
- let Content = [{
-Clang supports the
-``__attribute__((amdgpu_num_vgpr(<num_registers>)))`` attribute on AMD
-Southern Islands GPUs and later for controlling the number of vector
-registers. A typical value would be between 4 and 256 in increments
-of 4.
-}];
-}
-
-def AMDGPUNumSGPRDocs : Documentation {
- let Category = DocCatAMDGPURegisterAttributes;
+def AMDGPUFlatWorkGroupSizeDocs : Documentation {
+ let Category = DocCatAMDGPUAttributes;
let Content = [{
+The flat work-group size is the number of work-items in the work-group size
+specified when the kernel is dispatched. It is the product of the sizes of the
+x, y, and z dimension of the work-group.
Clang supports the
-``__attribute__((amdgpu_num_sgpr(<num_registers>)))`` attribute on AMD
-Southern Islands GPUs and later for controlling the number of scalar
-registers. A typical value would be between 8 and 104 in increments of
-8.
-
-Due to common instruction constraints, an additional 2-4 SGPRs are
-typically required for internal use depending on features used. This
-value is a hint for the total number of SGPRs to use, and not the
-number of user SGPRs, so no special consideration needs to be given
-for these.
-}];
+``__attribute__((amdgpu_flat_work_group_size(<min>, <max>)))`` attribute for the
+AMDGPU target. This attribute may be attached to a kernel function definition
+and is an optimization hint.
+
+``<min>`` parameter specifies the minimum flat work-group size, and ``<max>``
+parameter specifies the maximum flat work-group size (must be greater than
+``<min>``) to which all dispatches of the kernel will conform. Passing ``0, 0``
+as ``<min>, <max>`` implies the default behavior (``128, 256``).
+
+If specified, the AMDGPU target backend might be able to produce better machine
+code for barriers and perform scratch promotion by estimating available group
+segment size.
+
+An error will be given if:
+ - Specified values violate subtarget specifications;
+ - Specified values are not compatible with values provided through other
+ attributes.
+ }];
+}
+
+def AMDGPUWavesPerEUDocs : Documentation {
+ let Category = DocCatAMDGPUAttributes;
+ let Content = [{
+A compute unit (CU) is responsible for executing the wavefronts of a work-group.
+It is composed of one or more execution units (EU), which are responsible for
+executing the wavefronts. An EU can have enough resources to maintain the state
+of more than one executing wavefront. This allows an EU to hide latency by
+switching between wavefronts in a similar way to symmetric multithreading on a
+CPU. In order to allow the state for multiple wavefronts to fit on an EU, the
+resources used by a single wavefront have to be limited. For example, the number
+of SGPRs and VGPRs. Limiting such resources can allow greater latency hiding,
+but can result in having to spill some register state to memory.
+
+Clang supports the ``__attribute__((amdgpu_waves_per_eu(<min>[, <max>])))``
+attribute for the AMDGPU target. This attribute may be attached to a kernel
+function definition and is an optimization hint.
+
+``<min>`` parameter specifies the requested minimum number of waves per EU, and
+*optional* ``<max>`` parameter specifies the requested maximum number of waves
+per EU (must be greater than ``<min>`` if specified). If ``<max>`` is omitted,
+then there is no restriction on the maximum number of waves per EU other than
+the one dictated by the hardware for which the kernel is compiled. Passing
+``0, 0`` as ``<min>, <max>`` implies the default behavior (no limits).
+
+If specified, this attribute allows an advanced developer to tune the number of
+wavefronts that are capable of fitting within the resources of an EU. The AMDGPU
+target backend can use this information to limit resources, such as number of
+SGPRs, number of VGPRs, size of available group and private memory segments, in
+such a way that guarantees that at least ``<min>`` wavefronts and at most
+``<max>`` wavefronts are able to fit within the resources of an EU. Requesting
+more wavefronts can hide memory latency but limits available registers which
+can result in spilling. Requesting fewer wavefronts can help reduce cache
+thrashing, but can reduce memory latency hiding.
+
+This attribute controls the machine code generated by the AMDGPU target backend
+to ensure it is capable of meeting the requested values. However, when the
+kernel is executed, there may be other reasons that prevent meeting the request,
+for example, there may be wavefronts from other kernels executing on the EU.
+
+An error will be given if:
+ - Specified values violate subtarget specifications;
+ - Specified values are not compatible with values provided through other
+ attributes;
+ - The AMDGPU target backend is unable to create machine code that can meet the
+ request.
+ }];
+}
+
+def AMDGPUNumSGPRNumVGPRDocs : Documentation {
+ let Category = DocCatAMDGPUAttributes;
+ let Content = [{
+Clang supports the ``__attribute__((amdgpu_num_sgpr(<num_sgpr>)))`` and
+``__attribute__((amdgpu_num_vgpr(<num_vgpr>)))`` attributes for the AMDGPU
+target. These attributes may be attached to a kernel function definition and are
+an optimization hint.
+
+If these attributes are specified, then the AMDGPU target backend will attempt
+to limit the number of SGPRs and/or VGPRs used to the specified value(s). The
+number of used SGPRs and/or VGPRs may further be rounded up to satisfy the
+allocation requirements or constraints of the subtarget. Passing ``0`` as
+``num_sgpr`` and/or ``num_vgpr`` implies the default behavior (no limits).
+
+These attributes can be used to test the AMDGPU target backend. It is
+recommended that the ``amdgpu_waves_per_eu`` attribute be used to control
+resources such as SGPRs and VGPRs since it is aware of the limits for different
+subtargets.
+
+An error will be given if:
+ - Specified values violate subtarget specifications;
+ - Specified values are not compatible with values provided through other
+ attributes;
+ - The AMDGPU target backend is unable to create machine code that can meet the
+ request.
+ }];
}
def DocCatCallingConvs : DocumentationCategory<"Calling Conventions"> {
@@ -1166,6 +1321,18 @@ not require callee-cleanup. See the documentation for `__fastcall`_ on MSDN.
}];
}
+def RegCallDocs : Documentation {
+ let Category = DocCatCallingConvs;
+ let Content = [{
+On x86 targets, this attribute changes the calling convention to
+`__regcall`_ convention. This convention aims to pass as many arguments
+as possible in registers. It also tries to utilize registers for the
+return value whenever it is possible.
+
+.. _`__regcall`: https://software.intel.com/en-us/node/693069
+ }];
+}
+
def ThisCallDocs : Documentation {
let Category = DocCatCallingConvs;
let Content = [{
@@ -1194,7 +1361,7 @@ passed in RCX, RDX, R8, and R9 as is done for the default Windows x64 calling
convention.
On both 32-bit x86 and x86_64 targets, vector and floating point arguments are
-passed in XMM0-XMM5. Homogenous vector aggregates of up to four elements are
+passed in XMM0-XMM5. Homogeneous vector aggregates of up to four elements are
passed in sequential SSE registers if enough are available. If AVX is enabled,
256 bit vectors are passed in YMM0-YMM5. Any vector or aggregate type that
cannot be passed in registers for any reason is passed by reference, which
@@ -1329,7 +1496,7 @@ def NoSanitizeMemoryDocs : Documentation {
.. _langext-memory_sanitizer:
Use ``__attribute__((no_sanitize_memory))`` on a function declaration to
-specify that checks for uninitialized memory should not be inserted
+specify that checks for uninitialized memory should not be inserted
(e.g. by MemorySanitizer). The function may still be instrumented by the tool
to avoid false positives in other places.
}];
@@ -1338,7 +1505,8 @@ to avoid false positives in other places.
def DocCatTypeSafety : DocumentationCategory<"Type Safety Checking"> {
let Content = [{
Clang supports additional attributes to enable checking type safety properties
-that can't be enforced by the C type system. Use cases include:
+that can't be enforced by the C type system. To see warnings produced by these
+checks, ensure that -Wtype-safety is enabled. Use cases include:
* MPI library implementations, where these attributes enable checking that
the buffer type matches the passed ``MPI_Datatype``;
@@ -1376,18 +1544,31 @@ def ArgumentWithTypeTagDocs : Documentation {
Use ``__attribute__((argument_with_type_tag(arg_kind, arg_idx,
type_tag_idx)))`` on a function declaration to specify that the function
accepts a type tag that determines the type of some other argument.
-``arg_kind`` is an identifier that should be used when annotating all
-applicable type tags.
This attribute is primarily useful for checking arguments of variadic functions
(``pointer_with_type_tag`` can be used in most non-variadic cases).
+In the attribute prototype above:
+ * ``arg_kind`` is an identifier that should be used when annotating all
+ applicable type tags.
+ * ``arg_idx`` provides the position of a function argument. The expected type of
+ this function argument will be determined by the function argument specified
+ by ``type_tag_idx``. In the code example below, "3" means that the type of the
+ function's third argument will be determined by ``type_tag_idx``.
+ * ``type_tag_idx`` provides the position of a function argument. This function
+ argument will be a type tag. The type tag will determine the expected type of
+ the argument specified by ``arg_idx``. In the code example below, "2" means
+ that the type tag associated with the function's second argument should agree
+ with the type of the argument specified by ``arg_idx``.
+
For example:
.. code-block:: c++
int fcntl(int fd, int cmd, ...)
__attribute__(( argument_with_type_tag(fcntl,3,2) ));
+ // The function's second argument will be a type tag; this type tag will
+ // determine the expected type of the function's third argument.
}];
}
@@ -1399,85 +1580,140 @@ Use ``__attribute__((pointer_with_type_tag(ptr_kind, ptr_idx, type_tag_idx)))``
on a function declaration to specify that the function accepts a type tag that
determines the pointee type of some other pointer argument.
+In the attribute prototype above:
+ * ``ptr_kind`` is an identifier that should be used when annotating all
+ applicable type tags.
+ * ``ptr_idx`` provides the position of a function argument; this function
+ argument will have a pointer type. The expected pointee type of this pointer
+ type will be determined by the function argument specified by
+ ``type_tag_idx``. In the code example below, "1" means that the pointee type
+ of the function's first argument will be determined by ``type_tag_idx``.
+ * ``type_tag_idx`` provides the position of a function argument; this function
+ argument will be a type tag. The type tag will determine the expected pointee
+ type of the pointer argument specified by ``ptr_idx``. In the code example
+ below, "3" means that the type tag associated with the function's third
+ argument should agree with the pointee type of the pointer argument specified
+ by ``ptr_idx``.
+
For example:
.. code-block:: c++
+ typedef int MPI_Datatype;
int MPI_Send(void *buf, int count, MPI_Datatype datatype /*, other args omitted */)
__attribute__(( pointer_with_type_tag(mpi,1,3) ));
+ // The function's 3rd argument will be a type tag; this type tag will
+ // determine the expected pointee type of the function's 1st argument.
}];
}
def TypeTagForDatatypeDocs : Documentation {
let Category = DocCatTypeSafety;
let Content = [{
-Clang supports annotating type tags of two forms.
-
-* **Type tag that is an expression containing a reference to some declared
- identifier.** Use ``__attribute__((type_tag_for_datatype(kind, type)))`` on a
- declaration with that identifier:
-
- .. code-block:: c++
-
- extern struct mpi_datatype mpi_datatype_int
- __attribute__(( type_tag_for_datatype(mpi,int) ));
- #define MPI_INT ((MPI_Datatype) &mpi_datatype_int)
-
-* **Type tag that is an integral literal.** Introduce a ``static const``
- variable with a corresponding initializer value and attach
- ``__attribute__((type_tag_for_datatype(kind, type)))`` on that declaration,
- for example:
-
- .. code-block:: c++
-
- #define MPI_INT ((MPI_Datatype) 42)
- static const MPI_Datatype mpi_datatype_int
- __attribute__(( type_tag_for_datatype(mpi,int) )) = 42
-
-The attribute also accepts an optional third argument that determines how the
-expression is compared to the type tag. There are two supported flags:
+When declaring a variable, use
+``__attribute__((type_tag_for_datatype(kind, type)))`` to create a type tag that
+is tied to the ``type`` argument given to the attribute.
-* ``layout_compatible`` will cause types to be compared according to
- layout-compatibility rules (C++11 [class.mem] p 17, 18). This is
- implemented to support annotating types like ``MPI_DOUBLE_INT``.
+In the attribute prototype above:
+ * ``kind`` is an identifier that should be used when annotating all applicable
+ type tags.
+ * ``type`` indicates the name of the type.
- For example:
-
- .. code-block:: c++
-
- /* In mpi.h */
- struct internal_mpi_double_int { double d; int i; };
- extern struct mpi_datatype mpi_datatype_double_int
- __attribute__(( type_tag_for_datatype(mpi, struct internal_mpi_double_int, layout_compatible) ));
-
- #define MPI_DOUBLE_INT ((MPI_Datatype) &mpi_datatype_double_int)
-
- /* In user code */
- struct my_pair { double a; int b; };
- struct my_pair *buffer;
- MPI_Send(buffer, 1, MPI_DOUBLE_INT /*, ... */); // no warning
-
- struct my_int_pair { int a; int b; }
- struct my_int_pair *buffer2;
- MPI_Send(buffer2, 1, MPI_DOUBLE_INT /*, ... */); // warning: actual buffer element
- // type 'struct my_int_pair'
- // doesn't match specified MPI_Datatype
-
-* ``must_be_null`` specifies that the expression should be a null pointer
- constant, for example:
-
- .. code-block:: c++
-
- /* In mpi.h */
- extern struct mpi_datatype mpi_datatype_null
- __attribute__(( type_tag_for_datatype(mpi, void, must_be_null) ));
-
- #define MPI_DATATYPE_NULL ((MPI_Datatype) &mpi_datatype_null)
+Clang supports annotating type tags of two forms.
- /* In user code */
- MPI_Send(buffer, 1, MPI_DATATYPE_NULL /*, ... */); // warning: MPI_DATATYPE_NULL
- // was specified but buffer
- // is not a null pointer
+ * **Type tag that is a reference to a declared identifier.**
+ Use ``__attribute__((type_tag_for_datatype(kind, type)))`` when declaring that
+ identifier:
+
+ .. code-block:: c++
+
+ typedef int MPI_Datatype;
+ extern struct mpi_datatype mpi_datatype_int
+ __attribute__(( type_tag_for_datatype(mpi,int) ));
+ #define MPI_INT ((MPI_Datatype) &mpi_datatype_int)
+ // &mpi_datatype_int is a type tag. It is tied to type "int".
+
+ * **Type tag that is an integral literal.**
+ Declare a ``static const`` variable with an initializer value and attach
+ ``__attribute__((type_tag_for_datatype(kind, type)))`` on that declaration:
+
+ .. code-block:: c++
+
+ typedef int MPI_Datatype;
+ static const MPI_Datatype mpi_datatype_int
+ __attribute__(( type_tag_for_datatype(mpi,int) )) = 42;
+ #define MPI_INT ((MPI_Datatype) 42)
+ // The number 42 is a type tag. It is tied to type "int".
+
+
+The ``type_tag_for_datatype`` attribute also accepts an optional third argument
+that determines how the type of the function argument specified by either
+``arg_idx`` or ``ptr_idx`` is compared against the type associated with the type
+tag. (Recall that for the ``argument_with_type_tag`` attribute, the type of the
+function argument specified by ``arg_idx`` is compared against the type
+associated with the type tag. Also recall that for the ``pointer_with_type_tag``
+attribute, the pointee type of the function argument specified by ``ptr_idx`` is
+compared against the type associated with the type tag.) There are two supported
+values for this optional third argument:
+
+ * ``layout_compatible`` will cause types to be compared according to
+ layout-compatibility rules (In C++11 [class.mem] p 17, 18, see the
+ layout-compatibility rules for two standard-layout struct types and for two
+ standard-layout union types). This is useful when creating a type tag
+ associated with a struct or union type. For example:
+
+ .. code-block:: c++
+
+ /* In mpi.h */
+ typedef int MPI_Datatype;
+ struct internal_mpi_double_int { double d; int i; };
+ extern struct mpi_datatype mpi_datatype_double_int
+ __attribute__(( type_tag_for_datatype(mpi,
+ struct internal_mpi_double_int, layout_compatible) ));
+
+ #define MPI_DOUBLE_INT ((MPI_Datatype) &mpi_datatype_double_int)
+
+ int MPI_Send(void *buf, int count, MPI_Datatype datatype, ...)
+ __attribute__(( pointer_with_type_tag(mpi,1,3) ));
+
+ /* In user code */
+ struct my_pair { double a; int b; };
+ struct my_pair *buffer;
+ MPI_Send(buffer, 1, MPI_DOUBLE_INT /*, ... */); // no warning because the
+ // layout of my_pair is
+ // compatible with that of
+ // internal_mpi_double_int
+
+ struct my_int_pair { int a; int b; }
+ struct my_int_pair *buffer2;
+ MPI_Send(buffer2, 1, MPI_DOUBLE_INT /*, ... */); // warning because the
+ // layout of my_int_pair
+ // does not match that of
+ // internal_mpi_double_int
+
+ * ``must_be_null`` specifies that the function argument specified by either
+ ``arg_idx`` (for the ``argument_with_type_tag`` attribute) or ``ptr_idx`` (for
+ the ``pointer_with_type_tag`` attribute) should be a null pointer constant.
+ The second argument to the ``type_tag_for_datatype`` attribute is ignored. For
+ example:
+
+ .. code-block:: c++
+
+ /* In mpi.h */
+ typedef int MPI_Datatype;
+ extern struct mpi_datatype mpi_datatype_null
+ __attribute__(( type_tag_for_datatype(mpi, void, must_be_null) ));
+
+ #define MPI_DATATYPE_NULL ((MPI_Datatype) &mpi_datatype_null)
+ int MPI_Send(void *buf, int count, MPI_Datatype datatype, ...)
+ __attribute__(( pointer_with_type_tag(mpi,1,3) ));
+
+ /* In user code */
+ struct my_pair { double a; int b; };
+ struct my_pair *buffer;
+ MPI_Send(buffer, 1, MPI_DATATYPE_NULL /*, ... */); // warning: MPI_DATATYPE_NULL
+ // was specified but buffer
+ // is not a null pointer
}];
}
@@ -1878,7 +2114,7 @@ by Clang.
}
def NullabilityDocs : DocumentationCategory<"Nullability Attributes"> {
let Content = [{
-Whether a particular pointer may be "null" is an important concern when working with pointers in the C family of languages. The various nullability attributes indicate whether a particular pointer can be null or not, which makes APIs more expressive and can help static analysis tools identify bugs involving null pointers. Clang supports several kinds of nullability attributes: the ``nonnull`` and ``returns_nonnull`` attributes indicate which function or method parameters and result types can never be null, while nullability type qualifiers indicate which pointer types can be null (``_Nullable``) or cannot be null (``_Nonnull``).
+Whether a particular pointer may be "null" is an important concern when working with pointers in the C family of languages. The various nullability attributes indicate whether a particular pointer can be null or not, which makes APIs more expressive and can help static analysis tools identify bugs involving null pointers. Clang supports several kinds of nullability attributes: the ``nonnull`` and ``returns_nonnull`` attributes indicate which function or method parameters and result types can never be null, while nullability type qualifiers indicate which pointer types can be null (``_Nullable``) or cannot be null (``_Nonnull``).
The nullability (type) qualifiers express whether a value of a given pointer type can be null (the ``_Nullable`` qualifier), doesn't have a defined meaning for null (the ``_Nonnull`` qualifier), or for which the purpose of null is unclear (the ``_Null_unspecified`` qualifier). Because nullability qualifiers are expressed within the type system, they are more general than the ``nonnull`` and ``returns_nonnull`` attributes, allowing one to express (for example) a nullable pointer to an array of nonnull pointers. Nullability qualifiers are written to the right of the pointer to which they apply. For example:
@@ -2318,7 +2554,7 @@ def SwiftIndirectResultDocs : Documentation {
let Category = DocCatVariable;
let Content = [{
The ``swift_indirect_result`` attribute marks a parameter of a ``swiftcall``
-function as having the special indirect-result ABI treatmenet.
+function as having the special indirect-result ABI treatment.
This treatment gives the parameter the target's normal indirect-result
ABI treatment, which may involve passing it differently from an ordinary
@@ -2490,3 +2726,29 @@ Conversely, ``__attribute__((xray_never_instrument))`` or ``[[clang::xray_never_
If a function has neither of these attributes, they become subject to the XRay heuristics used to determine whether a function should be instrumented or otherwise.
}];
}
+
+def TransparentUnionDocs : Documentation {
+ let Category = DocCatType;
+ let Content = [{
+This attribute can be applied to a union to change the behaviour of calls to
+functions that have an argument with a transparent union type. The compiler
+behaviour is changed in the following manner:
+
+- A value whose type is any member of the transparent union can be passed as an
+ argument without the need to cast that value.
+
+- The argument is passed to the function using the calling convention of the
+ first member of the transparent union. Consequently, all the members of the
+ transparent union should have the same calling convention as its first member.
+
+Transparent unions are not supported in C++.
+ }];
+}
+
+def ObjCSubclassingRestrictedDocs : Documentation {
+ let Category = DocCatType;
+ let Content = [{
+This attribute can be added to an Objective-C ``@interface`` declaration to
+ensure that this class cannot be subclassed.
+ }];
+}
diff --git a/include/clang/Basic/Attributes.h b/include/clang/Basic/Attributes.h
index a2b86841cddf..ea9e28ae681a 100644
--- a/include/clang/Basic/Attributes.h
+++ b/include/clang/Basic/Attributes.h
@@ -22,6 +22,8 @@ enum class AttrSyntax {
GNU,
/// Is the identifier known as a __declspec-style attribute?
Declspec,
+ /// Is the identifier known as a [] Microsoft-style attribute?
+ Microsoft,
// Is the identifier known as a C++-style attribute?
CXX,
// Is the identifier known as a pragma attribute?
diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def
index 96bb359e51cb..ec0a2796ec08 100644
--- a/include/clang/Basic/Builtins.def
+++ b/include/clang/Basic/Builtins.def
@@ -29,6 +29,7 @@
// f -> float
// d -> double
// z -> size_t
+// w -> wchar_t
// F -> constant CFString
// G -> id
// H -> SEL
@@ -74,6 +75,7 @@
// f -> this is a libc/libm function without the '__builtin_' prefix. It can
// be followed by ':headername:' to state which header this function
// comes from.
+// h -> this function requires a specific header or an explicit declaration.
// i -> this is a runtime library implemented function without the
// '__builtin_' prefix. It will be implemented in compiler-rt or libgcc.
// p:N: -> this is a printf-like function whose Nth argument is the format
@@ -366,7 +368,7 @@ BUILTIN(__builtin_islessgreater , "i.", "Fnc")
BUILTIN(__builtin_isunordered , "i.", "Fnc")
// Unary FP classification
-BUILTIN(__builtin_fpclassify, "iiiii.", "Fnc")
+BUILTIN(__builtin_fpclassify, "iiiiii.", "Fnc")
BUILTIN(__builtin_isfinite, "i.", "Fnc")
BUILTIN(__builtin_isinf, "i.", "Fnc")
BUILTIN(__builtin_isinf_sign, "i.", "Fnc")
@@ -455,6 +457,12 @@ BUILTIN(__builtin_strpbrk, "c*cC*cC*", "nF")
BUILTIN(__builtin_strrchr, "c*cC*i", "nF")
BUILTIN(__builtin_strspn, "zcC*cC*", "nF")
BUILTIN(__builtin_strstr, "c*cC*cC*", "nF")
+BUILTIN(__builtin_wcschr, "w*wC*w", "nF")
+BUILTIN(__builtin_wcscmp, "iwC*wC*", "nF")
+BUILTIN(__builtin_wcslen, "zwC*", "nF")
+BUILTIN(__builtin_wcsncmp, "iwC*wC*z", "nF")
+BUILTIN(__builtin_wmemchr, "w*wC*wz", "nF")
+BUILTIN(__builtin_wmemcmp, "iwC*wC*z", "nF")
BUILTIN(__builtin_return_address, "v*IUi", "n")
BUILTIN(__builtin_extract_return_addr, "v*v*", "n")
BUILTIN(__builtin_frame_address, "v*IUi", "n")
@@ -511,6 +519,7 @@ BUILTIN(__builtin_unreachable, "v", "nr")
BUILTIN(__builtin_shufflevector, "v." , "nc")
BUILTIN(__builtin_convertvector, "v." , "nct")
BUILTIN(__builtin_alloca, "v*z" , "Fn")
+BUILTIN(__builtin_alloca_with_align, "v*zIz", "Fn")
BUILTIN(__builtin_call_with_static_chain, "v.", "nt")
// "Overloaded" Atomic operator builtins. These are overloaded to support data
@@ -693,7 +702,7 @@ BUILTIN(__atomic_is_lock_free, "izvCD*", "n")
#undef ATOMIC_BUILTIN
// Non-overloaded atomic builtins.
-BUILTIN(__sync_synchronize, "v.", "n")
+BUILTIN(__sync_synchronize, "v", "n")
// GCC does not support these, they are a Clang extension.
BUILTIN(__sync_fetch_and_min, "iiD*i", "n")
BUILTIN(__sync_fetch_and_max, "iiD*i", "n")
@@ -708,6 +717,9 @@ BUILTIN(__builtin_rindex, "c*cC*i", "Fn")
// Microsoft builtins. These are only active with -fms-extensions.
LANGBUILTIN(_alloca, "v*z", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__assume, "vb", "n", ALL_MS_LANGUAGES)
+LIBBUILTIN(_byteswap_ushort, "UsUs", "fnc", "stdlib.h", ALL_MS_LANGUAGES)
+LIBBUILTIN(_byteswap_ulong, "ULiULi", "fnc", "stdlib.h", ALL_MS_LANGUAGES)
+LIBBUILTIN(_byteswap_uint64, "ULLiULLi", "fnc", "stdlib.h", ALL_MS_LANGUAGES)
LANGBUILTIN(__debugbreak, "v", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__exception_code, "ULi", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_exception_code, "ULi", "n", ALL_MS_LANGUAGES)
@@ -716,15 +728,50 @@ LANGBUILTIN(_exception_info, "v*", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__abnormal_termination, "i", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_abnormal_termination, "i", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__GetExceptionInfo, "v*.", "ntu", ALL_MS_LANGUAGES)
-LANGBUILTIN(_InterlockedCompareExchange, "LiLiD*LiLi", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_InterlockedAnd8, "ccD*c", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_InterlockedAnd16, "ssD*s", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_InterlockedAnd, "LiLiD*Li", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_InterlockedCompareExchange8, "ccD*cc", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_InterlockedCompareExchange16, "ssD*ss", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_InterlockedCompareExchange, "LiLiD*LiLi", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_InterlockedCompareExchange64, "LLiLLiD*LLiLLi", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedCompareExchangePointer, "v*v*D*v*v*", "n", ALL_MS_LANGUAGES)
-LANGBUILTIN(_InterlockedDecrement, "LiLiD*", "n", ALL_MS_LANGUAGES)
-LANGBUILTIN(_InterlockedExchangeAdd, "LiLiD*Li", "n", ALL_MS_LANGUAGES)
-LANGBUILTIN(_InterlockedExchange, "LiLiD*Li", "n", ALL_MS_LANGUAGES)
-LANGBUILTIN(_InterlockedExchangePointer, "v*v*D*v*", "n", ALL_MS_LANGUAGES)
-LANGBUILTIN(_InterlockedIncrement, "LiLiD*", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_InterlockedDecrement16, "ssD*", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_InterlockedDecrement, "LiLiD*", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_InterlockedExchange, "LiLiD*Li", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_InterlockedExchange8, "ccD*c", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_InterlockedExchange16, "ssD*s", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_InterlockedExchangeAdd8, "ccD*c", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_InterlockedExchangeAdd16, "ssD*s", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_InterlockedExchangeAdd, "LiLiD*Li", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_InterlockedExchangePointer, "v*v*D*v*", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_InterlockedExchangeSub8, "ccD*c", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_InterlockedExchangeSub16, "ssD*s", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_InterlockedExchangeSub, "LiLiD*Li", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_InterlockedIncrement16, "ssD*", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_InterlockedIncrement, "LiLiD*", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_InterlockedOr8, "ccD*c", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_InterlockedOr16, "ssD*s", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_InterlockedOr, "LiLiD*Li", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_InterlockedXor8, "ccD*c", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_InterlockedXor16, "ssD*s", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_InterlockedXor, "LiLiD*Li", "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)
+LANGBUILTIN(__popcnt64, "ULLiULLi", "nc", ALL_MS_LANGUAGES)
LANGBUILTIN(__readfsdword, "ULiULi", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_ReturnAddress, "v*", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_rotl8, "UcUcUc", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_rotl16, "UsUsUc", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_rotl, "UiUii", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_lrotl, "ULiULii", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_rotl64, "ULLiULLii", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_rotr8, "UcUcUc", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_rotr16, "UsUsUc", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_rotr, "UiUii", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_lrotr, "ULiULii", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_rotr64, "ULLiULLii", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__va_start, "vc**.", "nt", ALL_MS_LANGUAGES)
// Microsoft library builtins.
@@ -766,7 +813,7 @@ LIBBUILTIN(fprintf, "iP*cC*.", "fp:1:", "stdio.h", ALL_LANGUAGES)
LIBBUILTIN(snprintf, "ic*zcC*.", "fp:2:", "stdio.h", ALL_LANGUAGES)
LIBBUILTIN(sprintf, "ic*cC*.", "fp:1:", "stdio.h", ALL_LANGUAGES)
LIBBUILTIN(vprintf, "icC*a", "fP:0:", "stdio.h", ALL_LANGUAGES)
-LIBBUILTIN(vfprintf, "i.", "fP:1:", "stdio.h", ALL_LANGUAGES)
+LIBBUILTIN(vfprintf, "iP*cC*a", "fP:1:", "stdio.h", ALL_LANGUAGES)
LIBBUILTIN(vsnprintf, "ic*zcC*a", "fP:2:", "stdio.h", ALL_LANGUAGES)
LIBBUILTIN(vsprintf, "ic*cC*a", "fP:1:", "stdio.h", ALL_LANGUAGES)
LIBBUILTIN(scanf, "icC*R.", "fs:0:", "stdio.h", ALL_LANGUAGES)
@@ -790,6 +837,15 @@ LIBBUILTIN(isupper, "ii", "fnU", "ctype.h", ALL_LANGUAGES)
LIBBUILTIN(isxdigit, "ii", "fnU", "ctype.h", ALL_LANGUAGES)
LIBBUILTIN(tolower, "ii", "fnU", "ctype.h", ALL_LANGUAGES)
LIBBUILTIN(toupper, "ii", "fnU", "ctype.h", ALL_LANGUAGES)
+// C99 wchar.h
+// FIXME: This list is incomplete. We should cover at least the functions that
+// take format strings.
+LIBBUILTIN(wcschr, "w*wC*w", "f", "wchar.h", ALL_LANGUAGES)
+LIBBUILTIN(wcscmp, "iwC*wC*", "f", "wchar.h", ALL_LANGUAGES)
+LIBBUILTIN(wcslen, "zwC*", "f", "wchar.h", ALL_LANGUAGES)
+LIBBUILTIN(wcsncmp, "iwC*wC*z", "f", "wchar.h", ALL_LANGUAGES)
+LIBBUILTIN(wmemchr, "w*wC*wz", "f", "wchar.h", ALL_LANGUAGES)
+LIBBUILTIN(wmemcmp, "iwC*wC*z", "f", "wchar.h", ALL_LANGUAGES)
// C99
// In some systems setjmp is a macro that expands to _setjmp. We undefine
@@ -906,6 +962,18 @@ LIBBUILTIN(fabs, "dd", "fnc", "math.h", ALL_LANGUAGES)
LIBBUILTIN(fabsf, "ff", "fnc", "math.h", ALL_LANGUAGES)
LIBBUILTIN(fabsl, "LdLd", "fnc", "math.h", ALL_LANGUAGES)
+// Some systems define finitef as alias of _finitef.
+#if defined (finitef)
+#undef finitef
+#endif
+LIBBUILTIN(finite, "id", "fnc", "math.h", GNU_LANG)
+LIBBUILTIN(finitef, "if", "fnc", "math.h", GNU_LANG)
+LIBBUILTIN(finitel, "iLd", "fnc", "math.h", GNU_LANG)
+// glibc's math.h generates calls to __finite
+LIBBUILTIN(__finite, "id", "fnc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(__finitef, "if", "fnc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(__finitel, "iLd", "fnc", "math.h", ALL_LANGUAGES)
+
LIBBUILTIN(fmod, "ddd", "fne", "math.h", ALL_LANGUAGES)
LIBBUILTIN(fmodf, "fff", "fne", "math.h", ALL_LANGUAGES)
LIBBUILTIN(fmodl, "LdLdLd", "fne", "math.h", ALL_LANGUAGES)
@@ -1280,6 +1348,22 @@ BUILTIN(__builtin___get_unsafe_stack_ptr, "v*", "Fn")
BUILTIN(__builtin_nontemporal_store, "v.", "t")
BUILTIN(__builtin_nontemporal_load, "v.", "t")
+// Coroutine intrinsics.
+BUILTIN(__builtin_coro_resume, "vv*", "")
+BUILTIN(__builtin_coro_destroy, "vv*", "")
+BUILTIN(__builtin_coro_done, "bv*", "n")
+BUILTIN(__builtin_coro_promise, "v*v*IiIb", "n")
+
+BUILTIN(__builtin_coro_size, "z", "n")
+BUILTIN(__builtin_coro_frame, "v*", "n")
+BUILTIN(__builtin_coro_free, "v*v*", "n")
+
+BUILTIN(__builtin_coro_id, "v*Iiv*v*v*", "n")
+BUILTIN(__builtin_coro_alloc, "b", "n")
+BUILTIN(__builtin_coro_begin, "v*v*", "n")
+BUILTIN(__builtin_coro_end, "vv*Ib", "n")
+BUILTIN(__builtin_coro_suspend, "cIb", "n")
+BUILTIN(__builtin_coro_param, "bv*v*", "n")
// OpenCL v2.0 s6.13.16, s9.17.3.5 - Pipe functions.
// We need the generic prototype, since the packet type could be anything.
LANGBUILTIN(read_pipe, "i.", "tn", OCLC20_LANG)
@@ -1317,6 +1401,10 @@ LANGBUILTIN(to_global, "v*v*", "tn", OCLC20_LANG)
LANGBUILTIN(to_local, "v*v*", "tn", OCLC20_LANG)
LANGBUILTIN(to_private, "v*v*", "tn", OCLC20_LANG)
+// Builtins for os_log/os_trace
+BUILTIN(__builtin_os_log_format_buffer_size, "zcC*.", "p:0:nut")
+BUILTIN(__builtin_os_log_format, "v*v*cC*.", "p:0:nt")
+
#undef BUILTIN
#undef LIBBUILTIN
#undef LANGBUILTIN
diff --git a/include/clang/Basic/Builtins.h b/include/clang/Basic/Builtins.h
index 15e9a413fb42..87c1f93eedef 100644
--- a/include/clang/Basic/Builtins.h
+++ b/include/clang/Basic/Builtins.h
@@ -139,6 +139,13 @@ public:
return strchr(getRecord(ID).Attributes, 'f') != nullptr;
}
+ /// \brief 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
/// function, such as "__clear_cache", where we know the signature a
/// priori.
diff --git a/include/clang/Basic/BuiltinsAMDGPU.def b/include/clang/Basic/BuiltinsAMDGPU.def
index ea63ea10f84c..f0f63fa73a79 100644
--- a/include/clang/Basic/BuiltinsAMDGPU.def
+++ b/include/clang/Basic/BuiltinsAMDGPU.def
@@ -36,6 +36,7 @@ BUILTIN(__builtin_amdgcn_workitem_id_z, "Ui", "nc")
// Instruction builtins.
//===----------------------------------------------------------------------===//
BUILTIN(__builtin_amdgcn_s_barrier, "v", "n")
+BUILTIN(__builtin_amdgcn_wave_barrier, "v", "n")
BUILTIN(__builtin_amdgcn_div_scale, "dddbb*", "n")
BUILTIN(__builtin_amdgcn_div_scalef, "fffbb*", "n")
BUILTIN(__builtin_amdgcn_div_fmas, "ddddb", "nc")
@@ -70,11 +71,30 @@ BUILTIN(__builtin_amdgcn_cubetc, "ffff", "nc")
BUILTIN(__builtin_amdgcn_cubema, "ffff", "nc")
BUILTIN(__builtin_amdgcn_s_memtime, "LUi", "n")
BUILTIN(__builtin_amdgcn_s_sleep, "vIi", "n")
+BUILTIN(__builtin_amdgcn_s_incperflevel, "vIi", "n")
+BUILTIN(__builtin_amdgcn_s_decperflevel, "vIi", "n")
+BUILTIN(__builtin_amdgcn_uicmp, "LUiUiUiIi", "nc")
+BUILTIN(__builtin_amdgcn_uicmpl, "LUiLUiLUiIi", "nc")
+BUILTIN(__builtin_amdgcn_sicmp, "LUiiiIi", "nc")
+BUILTIN(__builtin_amdgcn_sicmpl, "LUiLiLiIi", "nc")
+BUILTIN(__builtin_amdgcn_fcmp, "LUiddIi", "nc")
+BUILTIN(__builtin_amdgcn_fcmpf, "LUiffIi", "nc")
+BUILTIN(__builtin_amdgcn_ds_swizzle, "iiIi", "nc")
//===----------------------------------------------------------------------===//
// VI+ only builtins.
//===----------------------------------------------------------------------===//
+TARGET_BUILTIN(__builtin_amdgcn_div_fixuph, "hhhh", "nc", "16-bit-insts")
+TARGET_BUILTIN(__builtin_amdgcn_rcph, "hh", "nc", "16-bit-insts")
+TARGET_BUILTIN(__builtin_amdgcn_rsqh, "hh", "nc", "16-bit-insts")
+TARGET_BUILTIN(__builtin_amdgcn_sinh, "hh", "nc", "16-bit-insts")
+TARGET_BUILTIN(__builtin_amdgcn_cosh, "hh", "nc", "16-bit-insts")
+TARGET_BUILTIN(__builtin_amdgcn_ldexph, "hhi", "nc", "16-bit-insts")
+TARGET_BUILTIN(__builtin_amdgcn_frexp_manth, "hh", "nc", "16-bit-insts")
+TARGET_BUILTIN(__builtin_amdgcn_frexp_exph, "sh", "nc", "16-bit-insts")
+TARGET_BUILTIN(__builtin_amdgcn_fracth, "hh", "nc", "16-bit-insts")
+TARGET_BUILTIN(__builtin_amdgcn_classh, "bhi", "nc", "16-bit-insts")
TARGET_BUILTIN(__builtin_amdgcn_s_memrealtime, "LUi", "n", "s-memrealtime")
//===----------------------------------------------------------------------===//
diff --git a/include/clang/Basic/BuiltinsARM.def b/include/clang/Basic/BuiltinsARM.def
index 93b6458c5ef2..6cc7308d4cbc 100644
--- a/include/clang/Basic/BuiltinsARM.def
+++ b/include/clang/Basic/BuiltinsARM.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")
@@ -115,11 +119,34 @@ LANGBUILTIN(__sevl, "v", "", ALL_MS_LANGUAGES)
LANGBUILTIN(__dmb, "vUi", "nc", ALL_MS_LANGUAGES)
LANGBUILTIN(__dsb, "vUi", "nc", ALL_MS_LANGUAGES)
LANGBUILTIN(__isb, "vUi", "nc", ALL_MS_LANGUAGES)
+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)
LANGBUILTIN(__ldrexd, "WiWiCD*", "", ALL_MS_LANGUAGES)
LANGBUILTIN(_MoveFromCoprocessor, "UiIUiIUiIUiIUiIUi", "", ALL_MS_LANGUAGES)
LANGBUILTIN(_MoveFromCoprocessor2, "UiIUiIUiIUiIUiIUi", "", ALL_MS_LANGUAGES)
LANGBUILTIN(_MoveToCoprocessor, "vUiIUiIUiIUiIUiIUi", "", ALL_MS_LANGUAGES)
LANGBUILTIN(_MoveToCoprocessor2, "vUiIUiIUiIUiIUiIUi", "", ALL_MS_LANGUAGES)
+TARGET_HEADER_BUILTIN(_BitScanForward, "UcULi*ULi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_BitScanReverse, "UcULi*ULi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_BitScanForward64, "UcULi*ULLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_BitScanReverse64, "UcULi*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/BuiltinsNVPTX.def b/include/clang/Basic/BuiltinsNVPTX.def
index 456d0001a12d..b6329fbd4251 100644
--- a/include/clang/Basic/BuiltinsNVPTX.def
+++ b/include/clang/Basic/BuiltinsNVPTX.def
@@ -14,6 +14,10 @@
// The format of this database matches clang/Basic/Builtins.def.
+#if defined(BUILTIN) && !defined(TARGET_BUILTIN)
+# define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) BUILTIN(ID, TYPE, ATTRS)
+#endif
+
// Special Registers
BUILTIN(__nvvm_read_ptx_sreg_tid_x, "i", "nc")
@@ -452,18 +456,28 @@ BUILTIN(__builtin_ptx_get_image_channel_orderi_, "ii", "")
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")
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")
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")
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")
BUILTIN(__nvvm_atom_add_gen_d, "ddD*d", "n")
+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")
@@ -478,97 +492,155 @@ 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")
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")
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")
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")
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")
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")
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")
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")
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")
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")
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")
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")
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")
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")
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")
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")
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")
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")
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")
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")
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")
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")
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")
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")
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")
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")
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")
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")
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")
// Compiler Error Warn
BUILTIN(__nvvm_compiler_error, "vcC*4", "n")
@@ -611,3 +683,4 @@ BUILTIN(__nvvm_ldg_f4, "E4fE4fC*", "")
BUILTIN(__nvvm_ldg_d2, "E2dE2dC*", "")
#undef BUILTIN
+#undef TARGET_BUILTIN
diff --git a/include/clang/Basic/BuiltinsPPC.def b/include/clang/Basic/BuiltinsPPC.def
index 365dcc02a46d..657ea4225aa8 100644
--- a/include/clang/Basic/BuiltinsPPC.def
+++ b/include/clang/Basic/BuiltinsPPC.def
@@ -134,6 +134,14 @@ BUILTIN(__builtin_altivec_vcmpequw, "V4iV4iV4i", "")
BUILTIN(__builtin_altivec_vcmpequd, "V2LLiV2LLiV2LLi", "")
BUILTIN(__builtin_altivec_vcmpeqfp, "V4iV4fV4f", "")
+BUILTIN(__builtin_altivec_vcmpneb, "V16cV16cV16c", "")
+BUILTIN(__builtin_altivec_vcmpneh, "V8sV8sV8s", "")
+BUILTIN(__builtin_altivec_vcmpnew, "V4iV4iV4i", "")
+
+BUILTIN(__builtin_altivec_vcmpnezb, "V16cV16cV16c", "")
+BUILTIN(__builtin_altivec_vcmpnezh, "V8sV8sV8s", "")
+BUILTIN(__builtin_altivec_vcmpnezw, "V4iV4iV4i", "")
+
BUILTIN(__builtin_altivec_vcmpgtsb, "V16cV16ScV16Sc", "")
BUILTIN(__builtin_altivec_vcmpgtub, "V16cV16UcV16Uc", "")
BUILTIN(__builtin_altivec_vcmpgtsh, "V8sV8SsV8Ss", "")
@@ -223,6 +231,11 @@ BUILTIN(__builtin_altivec_vcmpequw_p, "iiV4iV4i", "")
BUILTIN(__builtin_altivec_vcmpequd_p, "iiV2LLiV2LLi", "")
BUILTIN(__builtin_altivec_vcmpeqfp_p, "iiV4fV4f", "")
+BUILTIN(__builtin_altivec_vcmpneb_p, "iiV16cV16c", "")
+BUILTIN(__builtin_altivec_vcmpneh_p, "iiV8sV8s", "")
+BUILTIN(__builtin_altivec_vcmpnew_p, "iiV4iV4i", "")
+BUILTIN(__builtin_altivec_vcmpned_p, "iiV2LLiV2LLi", "")
+
BUILTIN(__builtin_altivec_vcmpgtsb_p, "iiV16ScV16Sc", "")
BUILTIN(__builtin_altivec_vcmpgtub_p, "iiV16UcV16Uc", "")
BUILTIN(__builtin_altivec_vcmpgtsh_p, "iiV8SsV8Ss", "")
@@ -254,14 +267,54 @@ BUILTIN(__builtin_altivec_vclzb, "V16UcV16Uc", "")
BUILTIN(__builtin_altivec_vclzh, "V8UsV8Us", "")
BUILTIN(__builtin_altivec_vclzw, "V4UiV4Ui", "")
BUILTIN(__builtin_altivec_vclzd, "V2ULLiV2ULLi", "")
+BUILTIN(__builtin_altivec_vctzb, "V16UcV16Uc", "")
+BUILTIN(__builtin_altivec_vctzh, "V8UsV8Us", "")
+BUILTIN(__builtin_altivec_vctzw, "V4UiV4Ui", "")
+BUILTIN(__builtin_altivec_vctzd, "V2ULLiV2ULLi", "")
+
+BUILTIN(__builtin_altivec_vclzlsbb, "SiV16Uc", "")
+BUILTIN(__builtin_altivec_vctzlsbb, "SiV16Uc", "")
+BUILTIN(__builtin_altivec_vprtybw, "V4UiV4Ui", "")
+BUILTIN(__builtin_altivec_vprtybd, "V2ULLiV2ULLi", "")
+BUILTIN(__builtin_altivec_vprtybq, "V1ULLLiV1ULLLi", "")
+
+// Vector population count built-ins
+BUILTIN(__builtin_altivec_vpopcntb, "V16UcV16Uc", "")
+BUILTIN(__builtin_altivec_vpopcnth, "V8UsV8Us", "")
+BUILTIN(__builtin_altivec_vpopcntw, "V4UiV4Ui", "")
+BUILTIN(__builtin_altivec_vpopcntd, "V2ULLiV2ULLi", "")
+
+// Absolute difference built-ins
+BUILTIN(__builtin_altivec_vabsdub, "V16UcV16UcV16Uc", "")
+BUILTIN(__builtin_altivec_vabsduh, "V8UsV8UsV8Us", "")
+BUILTIN(__builtin_altivec_vabsduw, "V4UiV4UiV4Ui", "")
+
+// P9 Shift built-ins.
+BUILTIN(__builtin_altivec_vslv, "V16UcV16UcV16Uc", "")
+BUILTIN(__builtin_altivec_vsrv, "V16UcV16UcV16Uc", "")
+
+// P9 Vector rotate built-ins
+BUILTIN(__builtin_altivec_vrlwmi, "V4UiV4UiV4UiV4Ui", "")
+BUILTIN(__builtin_altivec_vrldmi, "V2ULLiV2ULLiV2ULLiV2ULLi", "")
+BUILTIN(__builtin_altivec_vrlwnm, "V4UiV4UiV4Ui", "")
+BUILTIN(__builtin_altivec_vrldnm, "V2ULLiV2ULLiV2ULLi", "")
// VSX built-ins.
BUILTIN(__builtin_vsx_lxvd2x, "V2divC*", "")
BUILTIN(__builtin_vsx_lxvw4x, "V4iivC*", "")
+BUILTIN(__builtin_vsx_lxvd2x_be, "V2dSLLivC*", "")
+BUILTIN(__builtin_vsx_lxvw4x_be, "V4iSLLivC*", "")
BUILTIN(__builtin_vsx_stxvd2x, "vV2div*", "")
BUILTIN(__builtin_vsx_stxvw4x, "vV4iiv*", "")
+BUILTIN(__builtin_vsx_stxvd2x_be, "vV2dSLLivC*", "")
+BUILTIN(__builtin_vsx_stxvw4x_be, "vV4iSLLivC*", "")
+
+BUILTIN(__builtin_vsx_lxvl, "V4ivC*ULLi", "")
+BUILTIN(__builtin_vsx_lxvll, "V4ivC*ULLi", "")
+BUILTIN(__builtin_vsx_stxvl, "vV4iv*ULLi", "")
+BUILTIN(__builtin_vsx_stxvll, "vV4iv*ULLi", "")
BUILTIN(__builtin_vsx_xvmaxdp, "V2dV2dV2d", "")
BUILTIN(__builtin_vsx_xvmaxsp, "V4fV4fV4f", "")
@@ -339,6 +392,31 @@ BUILTIN(__builtin_vsx_xvcpsgnsp, "V4fV4fV4f", "")
BUILTIN(__builtin_vsx_xvabssp, "V4fV4f", "")
BUILTIN(__builtin_vsx_xvabsdp, "V2dV2d", "")
+// vector Insert/Extract exponent/significand builtins
+BUILTIN(__builtin_vsx_xviexpdp, "V2dV2ULLiV2ULLi", "")
+BUILTIN(__builtin_vsx_xviexpsp, "V4fV4UiV4Ui", "")
+BUILTIN(__builtin_vsx_xvxexpdp, "V2ULLiV2d", "")
+BUILTIN(__builtin_vsx_xvxexpsp, "V4UiV4f", "")
+BUILTIN(__builtin_vsx_xvxsigdp, "V2ULLiV2d", "")
+BUILTIN(__builtin_vsx_xvxsigsp, "V4UiV4f", "")
+
+// Conversion builtins
+BUILTIN(__builtin_vsx_xvcvdpsxws, "V4SiV2d", "")
+BUILTIN(__builtin_vsx_xvcvdpuxws, "V4UiV2d", "")
+BUILTIN(__builtin_vsx_xvcvsxwdp, "V2dV4Si", "")
+BUILTIN(__builtin_vsx_xvcvuxwdp, "V2dV4Ui", "")
+BUILTIN(__builtin_vsx_xvcvspdp, "V2dV4f", "")
+BUILTIN(__builtin_vsx_xvcvsxdsp, "V4fV2SLLi", "")
+BUILTIN(__builtin_vsx_xvcvuxdsp, "V4fV2ULLi", "")
+BUILTIN(__builtin_vsx_xvcvdpsp, "V4fV2d", "")
+
+BUILTIN(__builtin_vsx_xvcvsphp, "V4fV4f", "")
+BUILTIN(__builtin_vsx_xvcvhpsp, "V4fV8Us", "")
+
+// Vector Test Data Class builtins
+BUILTIN(__builtin_vsx_xvtstdcdp, "V2ULLiV2dIi", "")
+BUILTIN(__builtin_vsx_xvtstdcsp, "V4UiV4fIi", "")
+
// HTM builtins
BUILTIN(__builtin_tbegin, "UiUIi", "")
BUILTIN(__builtin_tend, "UiUIi", "")
diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def
index 0accba4abab1..e53992bbf50e 100644
--- a/include/clang/Basic/BuiltinsX86.def
+++ b/include/clang/Basic/BuiltinsX86.def
@@ -23,6 +23,10 @@
# define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) 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
+
// FIXME: Are these nothrow/const?
// Miscellaneous builtin for checking x86 cpu features.
@@ -44,9 +48,7 @@ TARGET_BUILTIN(__builtin_ia32_undef512, "V8d", "nc", "")
// FLAGS
//
TARGET_BUILTIN(__builtin_ia32_readeflags_u32, "Ui", "n", "")
-TARGET_BUILTIN(__builtin_ia32_readeflags_u64, "ULLi", "n", "")
TARGET_BUILTIN(__builtin_ia32_writeeflags_u32, "vUi", "n", "")
-TARGET_BUILTIN(__builtin_ia32_writeeflags_u64, "vULLi", "n", "")
// 3DNow!
//
@@ -301,15 +303,16 @@ 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_cvtss2si64, "LLiV4f", "", "sse")
-TARGET_BUILTIN(__builtin_ia32_cvttss2si64, "LLiV4f", "", "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")
@@ -331,15 +334,17 @@ 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_cvtsd2si64, "LLiV2d", "", "sse2")
-TARGET_BUILTIN(__builtin_ia32_cvttsd2si64, "LLiV2d", "", "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", "", "sse2")
+TARGET_HEADER_BUILTIN(_mm_pause, "v", "h", "emmintrin.h", ALL_LANGUAGES, "sse2")
TARGET_BUILTIN(__builtin_ia32_pmuludq128, "V2LLiV4iV4i", "", "sse2")
TARGET_BUILTIN(__builtin_ia32_psraw128, "V8sV8sV8s", "", "sse2")
TARGET_BUILTIN(__builtin_ia32_psrad128, "V4iV4iV4i", "", "sse2")
@@ -413,7 +418,6 @@ 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_crc32di, "ULLiULLiULLi", "", "sse4.2")
// SSE4a
TARGET_BUILTIN(__builtin_ia32_extrqi, "V2LLiV2LLiIcIc", "", "sse4a")
@@ -627,65 +631,44 @@ TARGET_BUILTIN(__builtin_ia32_rdrand64_step, "UiULLi*", "", "rdrnd")
// FSGSBASE
TARGET_BUILTIN(__builtin_ia32_rdfsbase32, "Ui", "", "fsgsbase")
-TARGET_BUILTIN(__builtin_ia32_rdfsbase64, "ULLi", "", "fsgsbase")
TARGET_BUILTIN(__builtin_ia32_rdgsbase32, "Ui", "", "fsgsbase")
-TARGET_BUILTIN(__builtin_ia32_rdgsbase64, "ULLi", "", "fsgsbase")
TARGET_BUILTIN(__builtin_ia32_wrfsbase32, "vUi", "", "fsgsbase")
-TARGET_BUILTIN(__builtin_ia32_wrfsbase64, "vULLi", "", "fsgsbase")
TARGET_BUILTIN(__builtin_ia32_wrgsbase32, "vUi", "", "fsgsbase")
-TARGET_BUILTIN(__builtin_ia32_wrgsbase64, "vULLi", "", "fsgsbase")
// FXSR
TARGET_BUILTIN(__builtin_ia32_fxrstor, "vv*", "", "fxsr")
-TARGET_BUILTIN(__builtin_ia32_fxrstor64, "vv*", "", "fxsr")
TARGET_BUILTIN(__builtin_ia32_fxsave, "vv*", "", "fxsr")
-TARGET_BUILTIN(__builtin_ia32_fxsave64, "vv*", "", "fxsr")
// XSAVE
TARGET_BUILTIN(__builtin_ia32_xsave, "vv*ULLi", "", "xsave")
-TARGET_BUILTIN(__builtin_ia32_xsave64, "vv*ULLi", "", "xsave")
TARGET_BUILTIN(__builtin_ia32_xrstor, "vv*ULLi", "", "xsave")
-TARGET_BUILTIN(__builtin_ia32_xrstor64, "vv*ULLi", "", "xsave")
TARGET_BUILTIN(__builtin_ia32_xsaveopt, "vv*ULLi", "", "xsaveopt")
-TARGET_BUILTIN(__builtin_ia32_xsaveopt64, "vv*ULLi", "", "xsaveopt")
TARGET_BUILTIN(__builtin_ia32_xrstors, "vv*ULLi", "", "xsaves")
-TARGET_BUILTIN(__builtin_ia32_xrstors64, "vv*ULLi", "", "xsaves")
TARGET_BUILTIN(__builtin_ia32_xsavec, "vv*ULLi", "", "xsavec")
-TARGET_BUILTIN(__builtin_ia32_xsavec64, "vv*ULLi", "", "xsavec")
TARGET_BUILTIN(__builtin_ia32_xsaves, "vv*ULLi", "", "xsaves")
-TARGET_BUILTIN(__builtin_ia32_xsaves64, "vv*ULLi", "", "xsaves")
//CLFLUSHOPT
TARGET_BUILTIN(__builtin_ia32_clflushopt, "vc*", "", "clflushopt")
// ADX
TARGET_BUILTIN(__builtin_ia32_addcarryx_u32, "UcUcUiUiUi*", "", "adx")
-TARGET_BUILTIN(__builtin_ia32_addcarryx_u64, "UcUcULLiULLiULLi*", "", "adx")
TARGET_BUILTIN(__builtin_ia32_addcarry_u32, "UcUcUiUiUi*", "", "")
-TARGET_BUILTIN(__builtin_ia32_addcarry_u64, "UcUcULLiULLiULLi*", "", "")
TARGET_BUILTIN(__builtin_ia32_subborrow_u32, "UcUcUiUiUi*", "", "")
-TARGET_BUILTIN(__builtin_ia32_subborrow_u64, "UcUcULLiULLiULLi*", "", "")
// RDSEED
TARGET_BUILTIN(__builtin_ia32_rdseed16_step, "UiUs*", "", "rdseed")
TARGET_BUILTIN(__builtin_ia32_rdseed32_step, "UiUi*", "", "rdseed")
-TARGET_BUILTIN(__builtin_ia32_rdseed64_step, "UiULLi*", "", "rdseed")
// BMI
TARGET_BUILTIN(__builtin_ia32_bextr_u32, "UiUiUi", "", "bmi")
-TARGET_BUILTIN(__builtin_ia32_bextr_u64, "ULLiULLiULLi", "", "bmi")
// BMI2
TARGET_BUILTIN(__builtin_ia32_bzhi_si, "UiUiUi", "", "bmi2")
-TARGET_BUILTIN(__builtin_ia32_bzhi_di, "ULLiULLiULLi", "", "bmi2")
TARGET_BUILTIN(__builtin_ia32_pdep_si, "UiUiUi", "", "bmi2")
-TARGET_BUILTIN(__builtin_ia32_pdep_di, "ULLiULLiULLi", "", "bmi2")
TARGET_BUILTIN(__builtin_ia32_pext_si, "UiUiUi", "", "bmi2")
-TARGET_BUILTIN(__builtin_ia32_pext_di, "ULLiULLiULLi", "", "bmi2")
// TBM
TARGET_BUILTIN(__builtin_ia32_bextri_u32, "UiUiIUi", "", "tbm")
-TARGET_BUILTIN(__builtin_ia32_bextri_u64, "ULLiULLiIULLi", "", "tbm")
// SHA
TARGET_BUILTIN(__builtin_ia32_sha1rnds4, "V4iV4iV4iIc", "", "sha")
@@ -894,6 +877,7 @@ TARGET_BUILTIN(__builtin_ia32_xtest, "i", "", "rtm")
BUILTIN(__builtin_ia32_rdpmc, "ULLii", "")
BUILTIN(__builtin_ia32_rdtsc, "ULLi", "")
+BUILTIN(__rdtsc, "ULLi", "")
BUILTIN(__builtin_ia32_rdtscp, "ULLiUi*", "")
// PKU
TARGET_BUILTIN(__builtin_ia32_rdpkru, "Ui", "", "pku")
@@ -977,8 +961,6 @@ TARGET_BUILTIN(__builtin_ia32_maxps512_mask, "V16fV16fV16fV16fUsIi", "", "avx512
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_cvtdq2pd512_mask, "V8dV8iV8dUc", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_cvtudq2pd512_mask, "V8dV8iV8dUc", "", "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")
@@ -992,12 +974,11 @@ 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_mask, "V8LLiV16iV16iV8LLiUc", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_pmuludq512_mask, "V8LLiV16iV16iV8LLiUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmuldq512, "V8LLiV16iV16i", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmuludq512, "V8LLiV16iV16i", "", "avx512f")
TARGET_BUILTIN(__builtin_ia32_ptestmd512, "UsV16iV16iUs", "", "avx512f")
TARGET_BUILTIN(__builtin_ia32_ptestmq512, "UcV8LLiV8LLiUc", "", "avx512f")
TARGET_BUILTIN(__builtin_ia32_pbroadcastd512_gpr_mask, "V16iiV16iUs", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_pbroadcastq512_gpr_mask, "V8LLiLLiV8LLiUc", "", "avx512f")
TARGET_BUILTIN(__builtin_ia32_pbroadcastq512_mem_mask, "V8LLiLLiV8LLiUc", "", "avx512f")
TARGET_BUILTIN(__builtin_ia32_loaddqusi512_mask, "V16iiC*V16iUs", "", "avx512f")
TARGET_BUILTIN(__builtin_ia32_loaddqudi512_mask, "V8LLiLLiC*V8LLiUc", "", "avx512f")
@@ -1015,27 +996,19 @@ TARGET_BUILTIN(__builtin_ia32_vpermt2vard512_mask, "V16iV16iV16iV16iUs", "", "av
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_alignq512_mask, "V8LLiV8LLiV8LLiIiV8LLiUc", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_alignd512_mask, "V16iV16iV16iIiV16iUs", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_alignd128_mask, "V4iV4iV4iIiV4iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_alignd256_mask, "V8iV8iV8iIiV8iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_alignq128_mask, "V2LLiV2LLiV2LLiIiV2LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_alignq256_mask, "V4LLiV4LLiV4LLiIiV4LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_extractf64x4_mask, "V4dV8dIiV4dUc", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_extractf32x4_mask, "V4fV16fIiV4fUc", "", "avx512f")
TARGET_BUILTIN(__builtin_ia32_gather3div2df, "V2dV2ddC*V2LLiUci","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_gather3div2di, "V4iV2LLiLLiC*V2LLiUci","","avx512vl")
+TARGET_BUILTIN(__builtin_ia32_gather3div2di, "V2LLiV2LLiLLiC*V2LLiUci","","avx512vl")
TARGET_BUILTIN(__builtin_ia32_gather3div4df, "V4dV4ddC*V4LLiUci","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_gather3div4di, "V8iV4LLiLLiC*V4LLiUci","","avx512vl")
+TARGET_BUILTIN(__builtin_ia32_gather3div4di, "V4LLiV4LLiLLiC*V4LLiUci","","avx512vl")
TARGET_BUILTIN(__builtin_ia32_gather3div4sf, "V4fV4ffC*V2LLiUci","","avx512vl")
TARGET_BUILTIN(__builtin_ia32_gather3div4si, "V4iV4iiC*V2LLiUci","","avx512vl")
TARGET_BUILTIN(__builtin_ia32_gather3div8sf, "V4fV4ffC*V4LLiUci","","avx512vl")
TARGET_BUILTIN(__builtin_ia32_gather3div8si, "V4iV4iiC*V4LLiUci","","avx512vl")
TARGET_BUILTIN(__builtin_ia32_gather3siv2df, "V2dV2ddC*V4iUci","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_gather3siv2di, "V4iV2LLiLLiC*V4iUci","","avx512vl")
+TARGET_BUILTIN(__builtin_ia32_gather3siv2di, "V2LLiV2LLiLLiC*V4iUci","","avx512vl")
TARGET_BUILTIN(__builtin_ia32_gather3siv4df, "V4dV4ddC*V4iUci","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_gather3siv4di, "V8iV4LLiLLiC*V4iUci","","avx512vl")
+TARGET_BUILTIN(__builtin_ia32_gather3siv4di, "V4LLiV4LLiLLiC*V4iUci","","avx512vl")
TARGET_BUILTIN(__builtin_ia32_gather3siv4sf, "V4fV4ffC*V4iUci","","avx512vl")
TARGET_BUILTIN(__builtin_ia32_gather3siv4si, "V4iV4iiC*V4iUci","","avx512vl")
TARGET_BUILTIN(__builtin_ia32_gather3siv8sf, "V8fV8ffC*V8iUci","","avx512vl")
@@ -1093,71 +1066,6 @@ 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_paddd256_mask, "V8iV8iV8iV8iUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_paddq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psubd256_mask, "V8iV8iV8iV8iUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psubq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_paddd128_mask, "V4iV4iV4iV4iUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_paddq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psubd128_mask, "V4iV4iV4iV4iUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psubq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmuldq256_mask, "V4LLiV8iV8iV4LLiUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmuldq128_mask, "V2LLiV4iV4iV2LLiUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmuludq256_mask, "V4LLiV8iV8iV4LLiUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmuludq128_mask, "V2LLiV4iV4iV2LLiUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmulld256_mask, "V8iV8iV8iV8iUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmulld128_mask, "V4iV4iV4iV4iUc", "", "avx512vl")
-
-TARGET_BUILTIN(__builtin_ia32_paddb512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_psubb512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_paddw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_psubw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pmullw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
-TARGET_BUILTIN(__builtin_ia32_paddb256_mask, "V32cV32cV32cV32cUi", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_paddw256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_psubb256_mask, "V32cV32cV32cV32cUi", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_psubw256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_paddb128_mask, "V16cV16cV16cV16cUs", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_paddw128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_psubb128_mask, "V16cV16cV16cV16cUs", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_psubw128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pmullw256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pmullw128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
-
-TARGET_BUILTIN(__builtin_ia32_paddq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_psubq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_paddd512_mask, "V16iV16iV16iV16iUs", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_psubd512_mask, "V16iV16iV16iV16iUs", "", "avx512f")
-
-TARGET_BUILTIN(__builtin_ia32_pmulld512_mask, "V16iV16iV16iV16iUs", "", "avx512f")
-TARGET_BUILTIN(__builtin_ia32_pmullq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "", "avx512dq")
-TARGET_BUILTIN(__builtin_ia32_xorpd512_mask, "V8dV8dV8dV8dUc", "", "avx512dq")
-TARGET_BUILTIN(__builtin_ia32_xorps512_mask, "V16fV16fV16fV16fUs", "", "avx512dq")
-TARGET_BUILTIN(__builtin_ia32_orpd512_mask, "V8dV8dV8dV8dUc", "", "avx512dq")
-TARGET_BUILTIN(__builtin_ia32_orps512_mask, "V16fV16fV16fV16fUs", "", "avx512dq")
-TARGET_BUILTIN(__builtin_ia32_andpd512_mask, "V8dV8dV8dV8dUc", "", "avx512dq")
-TARGET_BUILTIN(__builtin_ia32_andps512_mask, "V16fV16fV16fV16fUs", "", "avx512dq")
-TARGET_BUILTIN(__builtin_ia32_andnpd512_mask, "V8dV8dV8dV8dUc", "", "avx512dq")
-TARGET_BUILTIN(__builtin_ia32_andnps512_mask, "V16fV16fV16fV16fUs", "", "avx512dq")
-TARGET_BUILTIN(__builtin_ia32_pmullq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl,avx512dq")
-TARGET_BUILTIN(__builtin_ia32_pmullq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl,avx512dq")
-TARGET_BUILTIN(__builtin_ia32_andnpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl,avx512dq")
-TARGET_BUILTIN(__builtin_ia32_andnpd128_mask, "V2dV2dV2dV2dUc", "", "avx512vl,avx512dq")
-TARGET_BUILTIN(__builtin_ia32_andnps256_mask, "V8fV8fV8fV8fUc", "", "avx512vl,avx512dq")
-TARGET_BUILTIN(__builtin_ia32_andnps128_mask, "V4fV4fV4fV4fUc", "", "avx512vl,avx512dq")
-TARGET_BUILTIN(__builtin_ia32_andpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl,avx512dq")
-TARGET_BUILTIN(__builtin_ia32_andpd128_mask, "V2dV2dV2dV2dUc", "", "avx512vl,avx512dq")
-TARGET_BUILTIN(__builtin_ia32_andps256_mask, "V8fV8fV8fV8fUc", "", "avx512vl,avx512dq")
-TARGET_BUILTIN(__builtin_ia32_andps128_mask, "V4fV4fV4fV4fUc", "", "avx512vl,avx512dq")
-TARGET_BUILTIN(__builtin_ia32_xorpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl,avx512dq")
-TARGET_BUILTIN(__builtin_ia32_xorpd128_mask, "V2dV2dV2dV2dUc", "", "avx512vl,avx512dq")
-TARGET_BUILTIN(__builtin_ia32_xorps256_mask, "V8fV8fV8fV8fUc", "", "avx512vl,avx512dq")
-TARGET_BUILTIN(__builtin_ia32_xorps128_mask, "V4fV4fV4fV4fUc", "", "avx512vl,avx512dq")
-TARGET_BUILTIN(__builtin_ia32_orpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl,avx512dq")
-TARGET_BUILTIN(__builtin_ia32_orpd128_mask, "V2dV2dV2dV2dUc", "", "avx512vl,avx512dq")
-TARGET_BUILTIN(__builtin_ia32_orps256_mask, "V8fV8fV8fV8fUc", "", "avx512vl,avx512dq")
-TARGET_BUILTIN(__builtin_ia32_orps128_mask, "V4fV4fV4fV4fUc", "", "avx512vl,avx512dq")
-
TARGET_BUILTIN(__builtin_ia32_pabsb512_mask, "V64cV64cV64cULLi", "", "avx512bw")
TARGET_BUILTIN(__builtin_ia32_pabsw512_mask, "V32sV32sV32sUi", "", "avx512bw")
TARGET_BUILTIN(__builtin_ia32_packssdw512_mask, "V32sV16iV16iV32sUi", "", "avx512bw")
@@ -1178,7 +1086,7 @@ TARGET_BUILTIN(__builtin_ia32_pminsb512_mask, "V64cV64cV64cV64cULLi", "", "avx51
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_mask, "V64cV64cV64cV64cULLi", "", "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")
@@ -1197,57 +1105,6 @@ TARGET_BUILTIN(__builtin_ia32_vpconflictsi_512_mask, "V16iV16iV16iUs", "", "avx5
TARGET_BUILTIN(__builtin_ia32_vplzcntd_512_mask, "V16iV16iV16iUs", "", "avx512cd")
TARGET_BUILTIN(__builtin_ia32_vplzcntq_512_mask, "V8LLiV8LLiV8LLiUc", "", "avx512cd")
-TARGET_BUILTIN(__builtin_ia32_pabsb128_mask, "V16cV16cV16cUs", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pabsb256_mask, "V32cV32cV32cUi", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pabsw128_mask, "V8sV8sV8sUc", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pabsw256_mask, "V16sV16sV16sUs", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_packssdw128_mask, "V8sV4iV4iV8sUc", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_packssdw256_mask, "V16sV8iV8iV16sUs", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_packsswb128_mask, "V16cV8sV8sV16cUs", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_packsswb256_mask, "V32cV16sV16sV32cUi", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_packusdw128_mask, "V8sV4iV4iV8sUc", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_packusdw256_mask, "V16sV8iV8iV16sUs", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_packuswb128_mask, "V16cV8sV8sV16cUs", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_packuswb256_mask, "V32cV16sV16sV32cUi", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_paddsb128_mask, "V16cV16cV16cV16cUs", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_paddsb256_mask, "V32cV32cV32cV32cUi", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_paddsw128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_paddsw256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_paddusb128_mask, "V16cV16cV16cV16cUs", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_paddusb256_mask, "V32cV32cV32cV32cUi", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_paddusw128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_paddusw256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pavgb128_mask, "V16cV16cV16cV16cUs", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pavgb256_mask, "V32cV32cV32cV32cUi", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pavgw128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pavgw256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pmaxsb128_mask, "V16cV16cV16cV16cUs", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pmaxsb256_mask, "V32cV32cV32cV32cUi", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pmaxsw128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pmaxsw256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pmaxub128_mask, "V16cV16cV16cV16cUs", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pmaxub256_mask, "V32cV32cV32cV32cUi", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pmaxuw128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pmaxuw256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pminsb128_mask, "V16cV16cV16cV16cUs", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pminsb256_mask, "V32cV32cV32cV32cUi", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pminsw128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pminsw256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pminub128_mask, "V16cV16cV16cV16cUs", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pminub256_mask, "V32cV32cV32cV32cUi", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pminuw128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pminuw256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pshufb128_mask, "V16cV16cV16cV16cUs", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pshufb256_mask, "V32cV32cV32cV32cUi", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_psubsb128_mask, "V16cV16cV16cV16cUs", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_psubsb256_mask, "V32cV32cV32cV32cUi", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_psubsw128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_psubsw256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_psubusb128_mask, "V16cV16cV16cV16cUs", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_psubusb256_mask, "V32cV32cV32cV32cUi", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_psubusw128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_psubusw256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
-
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")
@@ -1284,10 +1141,6 @@ 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_addpd128_mask, "V2dV2dV2dV2dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_addpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_addps128_mask, "V4fV4fV4fV4fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_addps256_mask, "V8fV8fV8fV8fUc", "", "avx512vl")
TARGET_BUILTIN(__builtin_ia32_compressdf128_mask, "V2dV2dV2dUc", "", "avx512vl")
TARGET_BUILTIN(__builtin_ia32_compressdf256_mask, "V4dV4dV4dUc", "", "avx512vl")
TARGET_BUILTIN(__builtin_ia32_compressdi128_mask, "V2LLiV2LLiV2LLiUc", "", "avx512vl")
@@ -1304,8 +1157,6 @@ TARGET_BUILTIN(__builtin_ia32_compressstoresf128_mask, "vV4f*V4fUc", "", "avx512
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_cvtdq2pd128_mask, "V2dV4iV2dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_cvtdq2pd256_mask, "V4dV4iV4dUc", "", "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")
@@ -1328,14 +1179,8 @@ 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_cvtudq2pd128_mask, "V2dV4iV2dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_cvtudq2pd256_mask, "V4dV4iV4dUc", "", "avx512vl")
TARGET_BUILTIN(__builtin_ia32_cvtudq2ps128_mask, "V4fV4iV4fUc", "", "avx512vl")
TARGET_BUILTIN(__builtin_ia32_cvtudq2ps256_mask, "V8fV8iV8fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_divpd_mask, "V2dV2dV2dV2dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_divpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_divps_mask, "V4fV4fV4fV4fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_divps256_mask, "V8fV8fV8fV8fUc", "", "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")
@@ -1356,36 +1201,14 @@ 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_maxpd_mask, "V2dV2dV2dV2dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_maxpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_maxps_mask, "V4fV4fV4fV4fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_maxps256_mask, "V8fV8fV8fV8fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_minpd_mask, "V2dV2dV2dV2dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_minpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_minps_mask, "V4fV4fV4fV4fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_minps256_mask, "V8fV8fV8fV8fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_mulpd_mask, "V2dV2dV2dV2dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_mulpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_mulps_mask, "V4fV4fV4fV4fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_mulps256_mask, "V8fV8fV8fV8fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pabsd128_mask, "V4iV4iV4iUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pabsd256_mask, "V8iV8iV8iUc", "", "avx512vl")
TARGET_BUILTIN(__builtin_ia32_pabsq128_mask, "V2LLiV2LLiV2LLiUc", "", "avx512vl")
TARGET_BUILTIN(__builtin_ia32_pabsq256_mask, "V4LLiV4LLiV4LLiUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmaxsd128_mask, "V4iV4iV4iV4iUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmaxsd256_mask, "V8iV8iV8iV8iUc", "", "avx512vl")
TARGET_BUILTIN(__builtin_ia32_pmaxsq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl")
TARGET_BUILTIN(__builtin_ia32_pmaxsq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmaxud128_mask, "V4iV4iV4iV4iUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmaxud256_mask, "V8iV8iV8iV8iUc", "", "avx512vl")
TARGET_BUILTIN(__builtin_ia32_pmaxuq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl")
TARGET_BUILTIN(__builtin_ia32_pmaxuq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pminsd128_mask, "V4iV4iV4iV4iUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pminsd256_mask, "V8iV8iV8iV8iUc", "", "avx512vl")
TARGET_BUILTIN(__builtin_ia32_pminsq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl")
TARGET_BUILTIN(__builtin_ia32_pminsq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pminud128_mask, "V4iV4iV4iV4iUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pminud256_mask, "V8iV8iV8iV8iUc", "", "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")
@@ -1414,14 +1237,6 @@ 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_sqrtpd128_mask, "V2dV2dV2dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_sqrtpd256_mask, "V4dV4dV4dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_sqrtps128_mask, "V4fV4fV4fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_sqrtps256_mask, "V8fV8fV8fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_subpd128_mask, "V2dV2dV2dV2dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_subpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_subps128_mask, "V4fV4fV4fV4fUc", "", "avx512vl")
-TARGET_BUILTIN(__builtin_ia32_subps256_mask, "V8fV8fV8fV8fUc", "", "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")
@@ -1485,22 +1300,12 @@ TARGET_BUILTIN(__builtin_ia32_reduceps128_mask, "V4fV4fIiV4fUc", "", "avx512vl,a
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_pmaddubsw128_mask, "V8sV16cV16cV8sUc", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pmaddubsw256_mask, "V16sV32cV32cV16sUs", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pmaddwd128_mask, "V4iV8sV8sV4iUc", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pmaddwd256_mask, "V8iV16sV16sV8iUc", "", "avx512vl,avx512bw")
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_pmulhrsw128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pmulhrsw256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pmulhuw128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pmulhuw256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pmulhw128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pmulhw256_mask, "V16sV16sV16sV16sUs", "", "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")
@@ -1517,42 +1322,6 @@ TARGET_BUILTIN(__builtin_ia32_rangepd512_mask, "V8dV8dV8dIiV8dUcIi", "", "avx512
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_pmovsxbw512_mask, "V32sV32cV32sUi","","avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pmovsxbd512_mask, "V16iV16cV16iUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_pmovsxbq512_mask, "V8LLiV16cV8LLiUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_pmovsxdq512_mask, "V8LLiV8iV8LLiUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_pmovsxwd512_mask, "V16iV16sV16iUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_pmovsxwq512_mask, "V8LLiV8sV8LLiUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_pmovsxbw128_mask, "V8sV16cV8sUc","","avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pmovsxbw256_mask, "V16sV16cV16sUs","","avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pmovsxbd128_mask, "V4iV16cV4iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovsxbd256_mask, "V8iV16cV8iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovsxbq128_mask, "V2LLiV16cV2LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovsxbq256_mask, "V4LLiV16cV4LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovsxdq128_mask, "V2LLiV4iV2LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovsxdq256_mask, "V4LLiV4iV4LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovsxwd128_mask, "V4iV8sV4iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovsxwd256_mask, "V8iV8sV8iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovsxwq128_mask, "V2LLiV8sV2LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovsxwq256_mask, "V4LLiV8sV4LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovzxbw512_mask, "V32sV32cV32sUi","","avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pmovzxbd512_mask, "V16iV16cV16iUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_pmovzxbq512_mask, "V8LLiV16cV8LLiUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_pmovzxdq512_mask, "V8LLiV8iV8LLiUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_pmovzxwd512_mask, "V16iV16sV16iUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_pmovzxwq512_mask, "V8LLiV8sV8LLiUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_pmovzxbw128_mask, "V8sV16cV8sUc","","avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pmovzxbw256_mask, "V16sV16cV16sUs","","avx512vl,avx512bw")
-TARGET_BUILTIN(__builtin_ia32_pmovzxbd128_mask, "V4iV16cV4iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovzxbd256_mask, "V8iV16cV8iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovzxbq128_mask, "V2LLiV16cV2LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovzxbq256_mask, "V4LLiV16cV4LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovzxdq128_mask, "V2LLiV4iV2LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovzxdq256_mask, "V4LLiV4iV4LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovzxwd128_mask, "V4iV8sV4iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovzxwd256_mask, "V8iV8sV8iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovzxwq128_mask, "V2LLiV8sV2LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pmovzxwq256_mask, "V4LLiV8sV4LLiUc","","avx512vl")
TARGET_BUILTIN(__builtin_ia32_prold512_mask, "V16iV16iIiV16iUs","","avx512f")
TARGET_BUILTIN(__builtin_ia32_prolq512_mask, "V8LLiV8LLiIiV8LLiUc","","avx512f")
TARGET_BUILTIN(__builtin_ia32_prold128_mask, "V4iV4iIiV4iUc","","avx512vl")
@@ -1577,65 +1346,27 @@ 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_mask, "V32sV32sV32sV32sUi","","avx512bw")
-TARGET_BUILTIN(__builtin_ia32_psllw512_mask, "V32sV32sV8sV32sUi","","avx512bw")
-TARGET_BUILTIN(__builtin_ia32_psllwi512_mask, "V32sV32sIiV32sUi","","avx512bw")
-TARGET_BUILTIN(__builtin_ia32_psllv16hi_mask, "V16sV16sV16sV16sUs","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psllv8hi_mask, "V8sV8sV8sV8sUc","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psllw128_mask, "V8sV8sV8sV8sUc","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psllw256_mask, "V16sV16sV8sV16sUs","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psllwi128_mask, "V8sV8sIiV8sUc","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psllwi256_mask, "V16sV16sIiV16sUs","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psllv2di_mask, "V2LLiV2LLiV2LLiV2LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psllv4di_mask, "V4LLiV4LLiV4LLiV4LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psllv4si_mask, "V4iV4iV4iV4iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psllv8si_mask, "V8iV8iV8iV8iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pslldi512_mask, "V16iV16iIiV16iUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_psllqi512_mask, "V8LLiV8LLiIiV8LLiUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_pslld128_mask, "V4iV4iV4iV4iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pslld256_mask, "V8iV8iV4iV8iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pslldi128_mask, "V4iV4iIiV4iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pslldi256_mask, "V8iV8iIiV8iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psllq128_mask, "V2LLiV2LLiV2LLiV2LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psllq256_mask, "V4LLiV4LLiV2LLiV4LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psllqi128_mask, "V2LLiV2LLiIiV2LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psllqi256_mask, "V4LLiV4LLiIiV4LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psrlv32hi_mask, "V32sV32sV32sV32sUi","","avx512bw")
-TARGET_BUILTIN(__builtin_ia32_psrlv16hi_mask, "V16sV16sV16sV16sUs","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psrlv8hi_mask, "V8sV8sV8sV8sUc","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psrlv2di_mask, "V2LLiV2LLiV2LLiV2LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psrlv4di_mask, "V4LLiV4LLiV4LLiV4LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psrlv4si_mask, "V4iV4iV4iV4iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psrlv8si_mask, "V8iV8iV8iV8iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psrldi512_mask, "V16iV16iIiV16iUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_psrlqi512_mask, "V8LLiV8LLiIiV8LLiUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_psrld128_mask, "V4iV4iV4iV4iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psrld256_mask, "V8iV8iV4iV8iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psrldi128_mask, "V4iV4iIiV4iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psrldi256_mask, "V8iV8iIiV8iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psrlq128_mask, "V2LLiV2LLiV2LLiV2LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psrlq256_mask, "V4LLiV4LLiV2LLiV4LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psrlqi128_mask, "V2LLiV2LLiIiV2LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psrlqi256_mask, "V4LLiV4LLiIiV4LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psrav32hi_mask, "V32sV32sV32sV32sUi","","avx512bw")
-TARGET_BUILTIN(__builtin_ia32_psrav16hi_mask, "V16sV16sV16sV16sUs","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psrav8hi_mask, "V8sV8sV8sV8sUc","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psrav4si_mask, "V4iV4iV4iV4iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psrav8si_mask, "V8iV8iV8iV8iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psravq128_mask, "V2LLiV2LLiV2LLiV2LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psravq256_mask, "V4LLiV4LLiV4LLiV4LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psraw512_mask, "V32sV32sV8sV32sUi","","avx512bw")
-TARGET_BUILTIN(__builtin_ia32_psrawi512_mask, "V32sV32sIiV32sUi","","avx512bw")
-TARGET_BUILTIN(__builtin_ia32_psraw128_mask, "V8sV8sV8sV8sUc","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psraw256_mask, "V16sV16sV8sV16sUs","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psrawi128_mask, "V8sV8sIiV8sUc","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psrawi256_mask, "V16sV16sIiV16sUs","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psrlw512_mask, "V32sV32sV8sV32sUi","","avx512bw")
-TARGET_BUILTIN(__builtin_ia32_psrlwi512_mask, "V32sV32sIiV32sUi","","avx512bw")
-TARGET_BUILTIN(__builtin_ia32_psrlw128_mask, "V8sV8sV8sV8sUc","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psrlw256_mask, "V16sV16sV8sV16sUs","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psrlwi128_mask, "V8sV8sIiV8sUc","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psrlwi256_mask, "V16sV16sIiV16sUs","","avx512bw,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")
@@ -1653,8 +1384,6 @@ TARGET_BUILTIN(__builtin_ia32_pbroadcastb128_gpr_mask, "V16ccV16cUs","","avx512b
TARGET_BUILTIN(__builtin_ia32_pbroadcastb256_gpr_mask, "V32ccV32cUi","","avx512bw,avx512vl")
TARGET_BUILTIN(__builtin_ia32_pbroadcastd128_gpr_mask, "V4iiV4iUc","","avx512vl")
TARGET_BUILTIN(__builtin_ia32_pbroadcastd256_gpr_mask, "V8iiV8iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pbroadcastq128_gpr_mask, "V2LLiULLiV2LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pbroadcastq256_gpr_mask, "V4LLiULLiV4LLiUc","","avx512vl")
TARGET_BUILTIN(__builtin_ia32_vpmadd52huq512_mask, "V8LLiV8LLiV8LLiV8LLiUc","","avx512ifma")
TARGET_BUILTIN(__builtin_ia32_vpmadd52huq512_maskz, "V8LLiV8LLiV8LLiV8LLiUc","","avx512ifma")
TARGET_BUILTIN(__builtin_ia32_vpmadd52luq512_mask, "V8LLiV8LLiV8LLiV8LLiUc","","avx512ifma")
@@ -1707,8 +1436,10 @@ TARGET_BUILTIN(__builtin_ia32_fixupimmps128_maskz, "V4fV4fV4fV4iIiUc","","avx512
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")
@@ -1725,8 +1456,10 @@ TARGET_BUILTIN(__builtin_ia32_storedquhi256_mask, "vV16s*V16sUs","","avx512vl,av
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")
@@ -1744,36 +1477,24 @@ TARGET_BUILTIN(__builtin_ia32_vplzcntd_128_mask, "V4iV4iV4iUc","","avx512cd,avx5
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_vcvtsd2si64, "LLiV2dIi","","avx512f")
TARGET_BUILTIN(__builtin_ia32_vcvtsd2si32, "iV2dIi","","avx512f")
TARGET_BUILTIN(__builtin_ia32_vcvtsd2usi32, "UiV2dIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_vcvtsd2usi64, "ULLiV2dIi","","avx512f")
TARGET_BUILTIN(__builtin_ia32_vcvtss2si32, "iV4fIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_vcvtss2si64, "LLiV4fIi","","avx512f")
TARGET_BUILTIN(__builtin_ia32_vcvtss2usi32, "UiV4fIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_vcvtss2usi64, "ULLiV4fIi","","avx512f")
TARGET_BUILTIN(__builtin_ia32_vcvttsd2si32, "iV2dIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_vcvttsd2si64, "LLiV2dIi","","avx512f")
TARGET_BUILTIN(__builtin_ia32_vcvttsd2usi32, "UiV2dIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_vcvttsd2usi64, "ULLiV2dIi","","avx512f")
TARGET_BUILTIN(__builtin_ia32_vcvttss2si32, "iV4fIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_vcvttss2si64, "LLiV4fIi","","avx512f")
TARGET_BUILTIN(__builtin_ia32_vcvttss2usi32, "UiV4fIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_vcvttss2usi64, "ULLiV4fIi","","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_mask, "V8dV8dV8LLiV8dUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_vpermilvarps512_mask, "V16fV16fV16iV16fUs","","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_vpermilvarpd_mask, "V2dV2dV2LLiV2dUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vpermilvarpd256_mask, "V4dV4dV4LLiV4dUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vpermilvarps_mask, "V4fV4fV4iV4fUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_vpermilvarps256_mask, "V8fV8fV8iV8fUc","","avx512vl")
TARGET_BUILTIN(__builtin_ia32_ptestmb512, "ULLiV64cV64cULLi","","avx512bw")
TARGET_BUILTIN(__builtin_ia32_ptestmw512, "UiV32sV32sUi","","avx512bw")
TARGET_BUILTIN(__builtin_ia32_ptestnmb512, "ULLiV64cV64cULLi","","avx512bw")
@@ -1802,28 +1523,24 @@ 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_mask, "V16iV16iIiV16iUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_psraqi512_mask, "V8LLiV8LLiIiV8LLiUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_psrad128_mask, "V4iV4iV4iV4iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psrad256_mask, "V8iV8iV4iV8iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psradi128_mask, "V4iV4iIiV4iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psradi256_mask, "V8iV8iIiV8iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psraq128_mask, "V2LLiV2LLiV2LLiV2LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psraq256_mask, "V4LLiV4LLiV2LLiV4LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psraqi128_mask, "V2LLiV2LLiIiV2LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_psraqi256_mask, "V4LLiV4LLiIiV4LLiUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_pslld512_mask, "V16iV16iV4iV16iUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_psllq512_mask, "V8LLiV8LLiV2LLiV8LLiUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_psllv16si_mask, "V16iV16iV16iV16iUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_psllv8di_mask, "V8LLiV8LLiV8LLiV8LLiUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_psrad512_mask, "V16iV16iV4iV16iUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_psraq512_mask, "V8LLiV8LLiV2LLiV8LLiUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_psrav16si_mask, "V16iV16iV16iV16iUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_psrav8di_mask, "V8LLiV8LLiV8LLiV8LLiUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_psrld512_mask, "V16iV16iV4iV16iUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_psrlq512_mask, "V8LLiV8LLiV2LLiV8LLiUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_psrlv16si_mask, "V16iV16iV16iV16iUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_psrlv8di_mask, "V8LLiV8LLiV8LLiV8LLiUc","","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")
@@ -1996,28 +1713,6 @@ 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_extractf32x8_mask, "V8fV16fIiV8fUc","","avx512dq")
-TARGET_BUILTIN(__builtin_ia32_extractf64x2_512_mask, "V2dV8dIiV2dUc","","avx512dq")
-TARGET_BUILTIN(__builtin_ia32_extracti32x8_mask, "V8iV16iIiV8iUc","","avx512dq")
-TARGET_BUILTIN(__builtin_ia32_extracti64x2_512_mask, "V2LLiV8LLiIiV2LLiUc","","avx512dq")
-TARGET_BUILTIN(__builtin_ia32_extracti32x4_mask, "V4iV16iIiV4iUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_extracti64x4_mask, "V4LLiV8LLiIiV4LLiUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_extractf64x2_256_mask, "V2dV4dIiV2dUc","","avx512dq,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_extracti64x2_256_mask, "V2LLiV4LLiIiV2LLiUc","","avx512dq,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_extractf32x4_256_mask, "V4fV8fIiV4fUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_extracti32x4_256_mask, "V4iV8iIiV4iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_insertf32x8_mask, "V16fV16fV8fIiV16fUs","","avx512dq")
-TARGET_BUILTIN(__builtin_ia32_insertf64x2_512_mask, "V8dV8dV2dIiV8dUc","","avx512dq")
-TARGET_BUILTIN(__builtin_ia32_inserti32x8_mask, "V16iV16iV8iIiV16iUs","","avx512dq")
-TARGET_BUILTIN(__builtin_ia32_inserti64x2_512_mask, "V8LLiV8LLiV2LLiIiV8LLiUc","","avx512dq")
-TARGET_BUILTIN(__builtin_ia32_insertf64x4_mask, "V8dV8dV4dIiV8dUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_inserti64x4_mask, "V8LLiV8LLiV4LLiIiV8LLiUc","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_insertf64x2_256_mask, "V4dV4dV2dIiV4dUc","","avx512dq,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_inserti64x2_256_mask, "V4LLiV4LLiV2LLiIiV4LLiUc","","avx512dq,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_insertf32x4_256_mask, "V8fV8fV4fIiV8fUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_inserti32x4_256_mask, "V8iV8iV4iIiV8iUc","","avx512vl")
-TARGET_BUILTIN(__builtin_ia32_insertf32x4_mask, "V16fV16fV4fIiV16fUs","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_inserti32x4_mask, "V16iV16iV4iIiV16iUs","","avx512f")
TARGET_BUILTIN(__builtin_ia32_getmantpd128_mask, "V2dV2diV2dUc","","avx512vl")
TARGET_BUILTIN(__builtin_ia32_getmantpd256_mask, "V4dV4diV4dUc","","avx512vl")
TARGET_BUILTIN(__builtin_ia32_getmantps128_mask, "V4fV4fiV4fUc","","avx512vl")
@@ -2032,6 +1727,10 @@ 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")
@@ -2064,8 +1763,6 @@ TARGET_BUILTIN(__builtin_ia32_kxnorhi, "UsUsUs","","avx512f")
TARGET_BUILTIN(__builtin_ia32_kxorhi, "UsUsUs","","avx512f")
TARGET_BUILTIN(__builtin_ia32_movntdqa512, "V8LLiV8LLi*","","avx512f")
TARGET_BUILTIN(__builtin_ia32_palignr512_mask, "V64cV64cV64cIiV64cULLi","","avx512bw")
-TARGET_BUILTIN(__builtin_ia32_palignr128_mask, "V16cV16cV16cIiV16cUs","","avx512bw,avx512vl")
-TARGET_BUILTIN(__builtin_ia32_palignr256_mask, "V32cV32cV32cIiV32cUi","","avx512bw,avx512vl")
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")
@@ -2097,14 +1794,10 @@ 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_cvtsi2sd64, "V2dV2dLLiIi","","avx512f")
TARGET_BUILTIN(__builtin_ia32_cvtsi2ss32, "V4fV4fiIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_cvtsi2ss64, "V4fV4fLLiIi","","avx512f")
TARGET_BUILTIN(__builtin_ia32_cvtss2sd_round_mask, "V2dV2dV4fV2dUcIi","","avx512f")
TARGET_BUILTIN(__builtin_ia32_cvtusi2sd32, "V2dV2dUi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_cvtusi2sd64, "V2dV2dULLiIi","","avx512f")
TARGET_BUILTIN(__builtin_ia32_cvtusi2ss32, "V4fV4fUiIi","","avx512f")
-TARGET_BUILTIN(__builtin_ia32_cvtusi2ss64, "V4fV4fULLiIi","","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")
@@ -2133,5 +1826,21 @@ TARGET_BUILTIN(__builtin_ia32_selectpd_512, "V8dUcV8dV8d", "", "")
TARGET_BUILTIN(__builtin_ia32_monitorx, "vv*UiUi", "", "mwaitx")
TARGET_BUILTIN(__builtin_ia32_mwaitx, "vUiUiUi", "", "mwaitx")
+// MSVC
+TARGET_HEADER_BUILTIN(_BitScanForward, "UcULi*ULi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_BitScanReverse, "UcULi*ULi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+
+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(_AddressOfReturnAddress, "v*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+
+TARGET_HEADER_BUILTIN(__stosb, "vUc*Ucz", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+
#undef BUILTIN
#undef TARGET_BUILTIN
+#undef TARGET_HEADER_BUILTIN
diff --git a/include/clang/Basic/BuiltinsX86_64.def b/include/clang/Basic/BuiltinsX86_64.def
new file mode 100644
index 000000000000..d38f522c3812
--- /dev/null
+++ b/include/clang/Basic/BuiltinsX86_64.def
@@ -0,0 +1,90 @@
+//===--- BuiltinsX86_64.def - X86-64 Builtin function database --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the X86-64-specific builtin function database. Users of
+// this file must define the BUILTIN macro to make use of this information.
+//
+//===----------------------------------------------------------------------===//
+
+// The format of this database matches clang/Basic/Builtins.def.
+
+#if defined(BUILTIN) && !defined(TARGET_BUILTIN)
+# define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) 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
+
+TARGET_HEADER_BUILTIN(_BitScanForward64, "UcULi*ULLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_BitScanReverse64, "UcULi*ULLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+
+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(__faststorefence, "v", "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, "")
+
+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_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_pbroadcastq512_gpr_mask, "V8LLiLLiV8LLiUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pbroadcastq128_gpr_mask, "V2LLiULLiV2LLiUc","","avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pbroadcastq256_gpr_mask, "V4LLiULLiV4LLiUc","","avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vcvtsd2si64, "LLiV2dIi","","avx512f")
+TARGET_BUILTIN(__builtin_ia32_vcvtsd2usi64, "ULLiV2dIi","","avx512f")
+TARGET_BUILTIN(__builtin_ia32_vcvtss2si64, "LLiV4fIi","","avx512f")
+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")
+
+#undef BUILTIN
+#undef TARGET_BUILTIN
+#undef TARGET_HEADER_BUILTIN
diff --git a/include/clang/Basic/DeclNodes.td b/include/clang/Basic/DeclNodes.td
index 4f7bbc078d98..7b581d3eec0f 100644
--- a/include/clang/Basic/DeclNodes.td
+++ b/include/clang/Basic/DeclNodes.td
@@ -37,6 +37,7 @@ def Named : Decl<1>;
def EnumConstant : DDecl<Value>;
def UnresolvedUsingValue : DDecl<Value>;
def IndirectField : DDecl<Value>;
+ def Binding : DDecl<Value>;
def OMPDeclareReduction : DDecl<Value>, DeclContext;
def Declarator : DDecl<Value, 1>;
def Field : DDecl<Declarator>;
@@ -54,6 +55,7 @@ def Named : Decl<1>;
: DDecl<VarTemplateSpecialization>;
def ImplicitParam : DDecl<Var>;
def ParmVar : DDecl<Var>;
+ def Decomposition : DDecl<Var>;
def OMPCapturedExpr : DDecl<Var>;
def NonTypeTemplateParm : DDecl<Declarator>;
def Template : DDecl<Named, 1>;
@@ -65,6 +67,7 @@ def Named : Decl<1>;
def TemplateTemplateParm : DDecl<Template>;
def BuiltinTemplate : DDecl<Template>;
def Using : DDecl<Named>;
+ def UsingPack : DDecl<Named>;
def UsingShadow : DDecl<Named>;
def ConstructorUsingShadow : DDecl<UsingShadow>;
def ObjCMethod : DDecl<Named>, DeclContext;
@@ -78,6 +81,7 @@ def Named : Decl<1>;
def ObjCProperty : DDecl<Named>;
def ObjCCompatibleAlias : DDecl<Named>;
def LinkageSpec : Decl, DeclContext;
+def Export : Decl, DeclContext;
def ObjCPropertyImpl : Decl;
def FileScopeAsm : Decl;
def AccessSpec : Decl;
diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h
index 085faeae4834..b83ef4d44b24 100644
--- a/include/clang/Basic/Diagnostic.h
+++ b/include/clang/Basic/Diagnostic.h
@@ -23,22 +23,33 @@
#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 <cassert>
+#include <cstdint>
#include <list>
+#include <memory>
+#include <string>
+#include <type_traits>
+#include <utility>
#include <vector>
namespace clang {
- class DeclContext;
- class DiagnosticBuilder;
- class DiagnosticConsumer;
- class DiagnosticErrorTrap;
- class DiagnosticOptions;
- class IdentifierInfo;
- class LangOptions;
- class Preprocessor;
- class StoredDiagnostic;
- namespace tok {
+
+class DeclContext;
+class DiagnosticBuilder;
+class DiagnosticConsumer;
+class IdentifierInfo;
+class LangOptions;
+class Preprocessor;
+class StoredDiagnostic;
+
+namespace tok {
+
enum TokenKind : unsigned short;
- }
+
+} // end namespace tok
/// \brief Annotates a diagnostic with some code that should be
/// inserted, removed, or replaced to fix the problem.
@@ -133,9 +144,6 @@ public:
/// the user. DiagnosticsEngine is tied to one translation unit and one
/// SourceManager.
class DiagnosticsEngine : public RefCountedBase<DiagnosticsEngine> {
- DiagnosticsEngine(const DiagnosticsEngine &) = delete;
- void operator=(const DiagnosticsEngine &) = delete;
-
public:
/// \brief The level of the diagnostic, after it has been through mapping.
enum Level {
@@ -344,11 +352,12 @@ private:
std::string FlagValue;
public:
- explicit DiagnosticsEngine(
- const IntrusiveRefCntPtr<DiagnosticIDs> &Diags,
- DiagnosticOptions *DiagOpts,
- DiagnosticConsumer *client = nullptr,
- bool ShouldOwnClient = true);
+ explicit DiagnosticsEngine(IntrusiveRefCntPtr<DiagnosticIDs> Diags,
+ DiagnosticOptions *DiagOpts,
+ DiagnosticConsumer *client = nullptr,
+ bool ShouldOwnClient = true);
+ DiagnosticsEngine(const DiagnosticsEngine &) = delete;
+ DiagnosticsEngine &operator=(const DiagnosticsEngine &) = delete;
~DiagnosticsEngine();
const IntrusiveRefCntPtr<DiagnosticIDs> &getDiagnosticIDs() const {
@@ -885,7 +894,6 @@ class DiagnosticBuilder {
/// call to ForceEmit.
mutable bool IsForceEmit = false;
- void operator=(const DiagnosticBuilder &) = delete;
friend class DiagnosticsEngine;
DiagnosticBuilder() = default;
@@ -950,16 +958,18 @@ public:
NumArgs = D.NumArgs;
}
- /// \brief Retrieve an empty diagnostic builder.
- static DiagnosticBuilder getEmpty() {
- return DiagnosticBuilder();
- }
+ DiagnosticBuilder &operator=(const DiagnosticBuilder &) = delete;
/// \brief Emits the diagnostic.
~DiagnosticBuilder() {
Emit();
}
-
+
+ /// \brief Retrieve an empty diagnostic builder.
+ static DiagnosticBuilder getEmpty() {
+ return DiagnosticBuilder();
+ }
+
/// \brief Forces the diagnostic to be emitted.
const DiagnosticBuilder &setForceEmit() const {
IsForceEmit = true;
@@ -1144,6 +1154,7 @@ inline DiagnosticBuilder DiagnosticsEngine::Report(unsigned DiagID) {
class Diagnostic {
const DiagnosticsEngine *DiagObj;
StringRef StoredDiagMessage;
+
public:
explicit Diagnostic(const DiagnosticsEngine *DO) : DiagObj(DO) {}
Diagnostic(const DiagnosticsEngine *DO, StringRef storedDiagMessage)
@@ -1280,7 +1291,7 @@ public:
ArrayRef<FixItHint> Fixits);
/// \brief Evaluates true when this object stores a diagnostic.
- explicit operator bool() const { return Message.size() > 0; }
+ explicit operator bool() const { return !Message.empty(); }
unsigned getID() const { return ID; }
DiagnosticsEngine::Level getLevel() const { return Level; }
@@ -1298,7 +1309,6 @@ public:
return llvm::makeArrayRef(Ranges);
}
-
typedef std::vector<FixItHint>::const_iterator fixit_iterator;
fixit_iterator fixit_begin() const { return FixIts.begin(); }
fixit_iterator fixit_end() const { return FixIts.end(); }
@@ -1313,18 +1323,18 @@ public:
/// formats and prints fully processed diagnostics.
class DiagnosticConsumer {
protected:
- unsigned NumWarnings; ///< Number of warnings reported
- unsigned NumErrors; ///< Number of errors reported
+ unsigned NumWarnings = 0; ///< Number of warnings reported
+ unsigned NumErrors = 0; ///< Number of errors reported
public:
- DiagnosticConsumer() : NumWarnings(0), NumErrors(0) { }
+ DiagnosticConsumer() = default;
+
+ virtual ~DiagnosticConsumer();
unsigned getNumErrors() const { return NumErrors; }
unsigned getNumWarnings() const { return NumWarnings; }
virtual void clear() { NumWarnings = NumErrors = 0; }
- virtual ~DiagnosticConsumer();
-
/// \brief Callback to inform the diagnostic client that processing
/// of a source file is beginning.
///
@@ -1369,6 +1379,7 @@ public:
/// \brief A diagnostic client that ignores all diagnostics.
class IgnoringDiagConsumer : public DiagnosticConsumer {
virtual void anchor();
+
void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
const Diagnostic &Info) override {
// Just ignore it.
@@ -1416,6 +1427,6 @@ void ProcessWarningOptions(DiagnosticsEngine &Diags,
const DiagnosticOptions &Opts,
bool ReportDiags = true);
-} // end namespace clang
+} // end namespace clang
-#endif
+#endif // LLVM_CLANG_BASIC_DIAGNOSTIC_H
diff --git a/include/clang/Basic/Diagnostic.td b/include/clang/Basic/Diagnostic.td
index 48cbf09419b3..39da0060ddbd 100644
--- a/include/clang/Basic/Diagnostic.td
+++ b/include/clang/Basic/Diagnostic.td
@@ -48,10 +48,13 @@ 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>; }
+// This defines documentation for diagnostic groups.
+include "DiagnosticDocs.td"
// This defines all of the named diagnostic categories.
include "DiagnosticCategories.td"
diff --git a/include/clang/Basic/DiagnosticASTKinds.td b/include/clang/Basic/DiagnosticASTKinds.td
index 039888ba6631..03ed8aa74597 100644
--- a/include/clang/Basic/DiagnosticASTKinds.td
+++ b/include/clang/Basic/DiagnosticASTKinds.td
@@ -158,6 +158,12 @@ def warn_integer_constant_overflow : Warning<
"overflow in expression; result is %0 with type %1">,
InGroup<DiagGroup<"integer-overflow">>;
+// This is a temporary diagnostic, and shall be removed once our
+// implementation is complete, and like the preceding constexpr notes belongs
+// in Sema.
+def note_unimplemented_constexpr_lambda_feature_ast : Note<
+ "unimplemented constexpr lambda feature: %0 (coming soon!)">;
+
// inline asm related.
let CategoryName = "Inline Assembly Issue" in {
def err_asm_invalid_escape : Error<
diff --git a/include/clang/Basic/DiagnosticCommonKinds.td b/include/clang/Basic/DiagnosticCommonKinds.td
index 1c3bbfc11840..e8180eb1db48 100644
--- a/include/clang/Basic/DiagnosticCommonKinds.td
+++ b/include/clang/Basic/DiagnosticCommonKinds.td
@@ -94,6 +94,8 @@ def err_module_lock_timeout : Error<
"timed out waiting to acquire lock file for module '%0'">, DefaultFatal;
def err_module_cycle : Error<"cyclic dependency in module '%0': %1">,
DefaultFatal;
+def err_module_prebuilt : Error<
+ "error in loading module '%0' from prebuilt module path">, DefaultFatal;
def note_pragma_entered_here : Note<"#pragma entered here">;
def note_decl_hiding_tag_type : Note<
"%1 %0 is hidden by a non-type declaration of %0 here">;
@@ -188,6 +190,8 @@ def err_target_unsupported_fpmath : Error<
"the '%0' unit is not supported with this instruction set">;
def err_target_unsupported_unaligned : Error<
"the %0 sub-architecture does not support unaligned accesses">;
+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'">;
diff --git a/include/clang/Basic/DiagnosticDocs.td b/include/clang/Basic/DiagnosticDocs.td
new file mode 100644
index 000000000000..0a3e1ce5f2f2
--- /dev/null
+++ b/include/clang/Basic/DiagnosticDocs.td
@@ -0,0 +1,84 @@
+//==--- DiagnosticDocs.td - Diagnostic documentation ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+
+def GlobalDocumentation {
+ code Intro =[{..
+ -------------------------------------------------------------------
+ NOTE: This file is automatically generated by running clang-tblgen
+ -gen-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/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td
index 0a9b34827dc2..2fcd3a5a2fba 100644
--- a/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/include/clang/Basic/DiagnosticDriverKinds.td
@@ -26,10 +26,14 @@ 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 "
"-nocudainc to build without CUDA includes.">;
+def err_drv_no_cuda_libdevice : Error<
+ "cannot find libdevice for %0. Provide path to different CUDA installation "
+ "via --cuda-path, or pass -nocudalib to build without linking with libdevice.">;
def err_drv_cuda_version_too_low : Error<
"GPU arch %1 requires CUDA version at least %3, but installation at %0 is %2. "
"Use --cuda-path to specify a different CUDA install, or pass "
"--no-cuda-version-check.">;
+def err_drv_cuda_nvptx_host : Error<"unsupported use of NVPTX for host compilation.">;
def err_drv_invalid_thread_model_for_target : Error<
"invalid thread model '%0' in '%1' for this target">;
def err_drv_invalid_linker_name : Error<
@@ -83,6 +87,8 @@ def err_drv_clang_unsupported_opt_cxx_darwin_i386 : Error<
"the clang compiler does not support '%0' for C++ on Darwin/i386">;
def err_drv_command_failed : Error<
"%0 command failed with exit code %1 (use -v to see invocation)">;
+def err_drv_compilationdatabase : Error<
+ "compilation database '%0' could not be opened: %1">;
def err_drv_command_signalled : Error<
"%0 command failed due to signal (use -v to see invocation)">;
def err_drv_force_crash : Error<
@@ -131,8 +137,6 @@ def err_drv_preamble_format : Error<
"incorrect format for -preamble-bytes=N,END">;
def err_drv_conflicting_deployment_targets : Error<
"conflicting deployment targets, both '%0' and '%1' are present in environment">;
-def err_drv_objc_gc_arr : Error<
- "cannot specify both '-fobjc-arc' and '%0'">;
def err_arc_unsupported_on_runtime : Error<
"-fobjc-arc is not supported on platforms using the legacy runtime">;
def err_arc_unsupported_on_toolchain : Error< // feel free to generalize this
@@ -155,6 +159,11 @@ def err_drv_omp_host_ir_file_not_found : Error<
"The provided host compiler IR file '%0' is required to generate code for OpenMP target regions but cannot be found.">;
def err_drv_omp_host_target_not_supported : Error<
"The target '%0' is not a supported OpenMP host target.">;
+def err_drv_expecting_fopenmp_with_fopenmp_targets : Error<
+ "The option -fopenmp-targets must be used in conjunction with a -fopenmp option compatible with offloading, please use -fopenmp=libomp or -fopenmp=libiomp5.">;
+def warn_drv_omp_offload_target_duplicate : Warning<
+ "The OpenMP offloading target '%0' is similar to target '%1' already specified - will be ignored.">,
+ InGroup<OpenMPTarget>;
def err_drv_bitcode_unsupported_on_toolchain : Error<
"-fembed-bitcode is not supported on versions of iOS prior to 6.0">;
@@ -163,6 +172,9 @@ def warn_drv_optimization_value : Warning<"optimization level '%0' is not suppor
InGroup<InvalidCommandLineArgument>;
def warn_ignored_gcc_optimization : Warning<"optimization flag '%0' is not supported">,
InGroup<IgnoredOptimizationArgument>;
+def warn_drv_unsupported_opt_for_target : Warning<
+ "optimization flag '%0' is not supported for target '%1'">,
+ InGroup<IgnoredOptimizationArgument>;
def warn_c_kext : Warning<
"ignoring -fapple-kext which is valid for C++ and Objective-C++ only">;
def warn_drv_input_file_unused : Warning<
@@ -180,6 +192,9 @@ def warn_drv_unused_argument : Warning<
def warn_drv_empty_joined_argument : Warning<
"joined argument expects additional value: '%0'">,
InGroup<UnusedCommandLineArgument>;
+def warn_drv_fdiagnostics_show_hotness_requires_pgo : Warning<
+ "argument '-fdiagnostics-show-hotness' requires profile-guided optimization information">,
+ InGroup<UnusedCommandLineArgument>;
def warn_drv_clang_unsupported : Warning<
"the clang compiler does not support '%0'">;
def warn_drv_deprecated_arg : Warning<
@@ -194,8 +209,6 @@ def warn_drv_overriding_flag_option : Warning<
def warn_drv_treating_input_as_cxx : Warning<
"treating '%0' input as '%1' when in C++ mode, this behavior is deprecated">,
InGroup<Deprecated>;
-def warn_drv_objc_gc_unsupported : Warning<
- "Objective-C garbage collection is not supported on this platform, ignoring '%0'">;
def warn_drv_pch_not_first_include : Warning<
"precompiled header '%0' was ignored because '%1' is not first '-include'">;
def warn_missing_sysroot : Warning<"no such sysroot directory: '%0'">,
@@ -234,6 +247,11 @@ def err_test_module_file_extension_format : Error<
def warn_drv_invoking_fallback : Warning<"falling back to %0">,
InGroup<Fallback>;
+def err_drv_ropi_rwpi_incompatible_with_pic : Error<
+ "embedded and GOT-based position independence are incompatible">;
+def err_drv_ropi_incompatible_with_cxx : Error<
+ "ROPI is not compatible with c++">;
+
def warn_target_unsupported_nan2008 : Warning<
"ignoring '-mnan=2008' option because the '%0' architecture does not support it">,
InGroup<UnsupportedNan>;
@@ -257,4 +275,6 @@ def warn_drv_ps4_sdk_dir : Warning<
InGroup<InvalidOrNonExistentDirectory>;
def err_drv_unsupported_linker : Error<"unsupported value '%0' for -linker option">;
+def err_drv_defsym_invalid_format : Error<"defsym must be of the form: sym=value: %0">;
+def err_drv_defsym_invalid_symval : Error<"Value is not an integer: %0">;
}
diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td
index 2aa8f103500d..1267f8d09f58 100644
--- a/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -107,10 +107,15 @@ def warn_fe_cc_print_header_failure : Warning<
"unable to open CC_PRINT_HEADERS file: %0 (using stderr)">;
def warn_fe_cc_log_diagnostics_failure : Warning<
"unable to open CC_LOG_DIAGNOSTICS file: %0 (using stderr)">;
+def warn_fe_unable_to_open_stats_file : Warning<
+ "unable to open statistics output file '%0': '%1'">,
+ InGroup<DiagGroup<"unable-to-open-stats-file">>;
def err_fe_no_pch_in_dir : Error<
"no suitable precompiled header file found in directory '%0'">;
def err_fe_action_not_available : Error<
"action %0 not compiled in">;
+def err_fe_invalid_alignment : Error<
+ "invalid value '%1' in '%0'; alignment must be a power of 2">;
def warn_fe_serialized_diag_merge_failure : Warning<
"unable to merge a subprocess's serialized diagnostics">,
@@ -174,6 +179,8 @@ def warn_incompatible_analyzer_plugin_api : Warning<
def note_incompatible_analyzer_plugin_api : Note<
"current API version is '%0', but plugin was compiled with version '%1'">;
+def err_module_interface_requires_modules_ts : Error<
+ "module interface compilation requires '-fmodules-ts'">;
def warn_module_config_mismatch : Warning<
"module file %0 cannot be loaded due to a configuration mismatch with the current "
"compilation">, InGroup<DiagGroup<"module-file-config-mismatch">>, DefaultError;
@@ -217,4 +224,4 @@ def err_invalid_vfs_overlay : Error<
def warn_option_invalid_ocl_version : Warning<
"OpenCL version %0 does not support the option '%1'">, InGroup<Deprecated>;
-} \ No newline at end of file
+}
diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td
index 72dfedbbaef0..ba82b36cea31 100644
--- a/include/clang/Basic/DiagnosticGroups.td
+++ b/include/clang/Basic/DiagnosticGroups.td
@@ -62,7 +62,6 @@ def NullConversion : DiagGroup<"null-conversion">;
def ImplicitConversionFloatingPointToBool :
DiagGroup<"implicit-conversion-floating-point-to-bool">;
def ObjCLiteralConversion : DiagGroup<"objc-literal-conversion">;
-def BadArrayNewLength : DiagGroup<"bad-array-new-length">;
def MacroRedefined : DiagGroup<"macro-redefined">;
def BuiltinMacroRedefined : DiagGroup<"builtin-macro-redefined">;
def BuiltinRequiresHeader : DiagGroup<"builtin-requires-header">;
@@ -95,8 +94,11 @@ def CXX11CompatDeprecatedWritableStr :
def DeprecatedAttributes : DiagGroup<"deprecated-attributes">;
def DeprecatedDeclarations : DiagGroup<"deprecated-declarations">;
def UnavailableDeclarations : DiagGroup<"unavailable-declarations">;
-def PartialAvailability : DiagGroup<"partial-availability">;
def UnguardedAvailability : DiagGroup<"unguarded-availability">;
+// partial-availability is an alias of unguarded-availability.
+def : DiagGroup<"partial-availability", [UnguardedAvailability]>;
+def DeprecatedDynamicExceptionSpec
+ : DiagGroup<"deprecated-dynamic-exception-spec">;
def DeprecatedImplementations :DiagGroup<"deprecated-implementations">;
def DeprecatedIncrementBool : DiagGroup<"deprecated-increment-bool">;
def DeprecatedRegister : DiagGroup<"deprecated-register">;
@@ -105,15 +107,20 @@ def DeprecatedWritableStr : DiagGroup<"deprecated-writable-strings",
// FIXME: Why is DeprecatedImplementations not in this group?
def Deprecated : DiagGroup<"deprecated", [DeprecatedAttributes,
DeprecatedDeclarations,
+ DeprecatedDynamicExceptionSpec,
DeprecatedIncrementBool,
DeprecatedRegister,
DeprecatedWritableStr]>,
DiagCategory<"Deprecations">;
+def DynamicExceptionSpec
+ : DiagGroup<"dynamic-exception-spec", [DeprecatedDynamicExceptionSpec]>;
+
def LibLTO : DiagGroup<"liblto">;
def : DiagGroup<"disabled-optimization">;
def : DiagGroup<"discard-qual">;
-def : DiagGroup<"div-by-zero">;
+def DivZero : DiagGroup<"division-by-zero">;
+def : DiagGroup<"div-by-zero", [DivZero]>;
def DocumentationHTML : DiagGroup<"documentation-html">;
def DocumentationUnknownCommand : DiagGroup<"documentation-unknown-command">;
@@ -200,8 +207,6 @@ def CXX14CompatPedantic : DiagGroup<"c++14-compat-pedantic",
def CXX1zCompat : DiagGroup<"c++1z-compat", [DeprecatedRegister,
DeprecatedIncrementBool]>;
-def : DiagGroup<"effc++">;
-def DivZero : DiagGroup<"division-by-zero">;
def ExitTimeDestructors : DiagGroup<"exit-time-destructors">;
def FlexibleArrayExtensions : DiagGroup<"flexible-array-extensions">;
def FourByteMultiChar : DiagGroup<"four-char-constants">;
@@ -225,9 +230,12 @@ def GNUIncludeNext : DiagGroup<"gnu-include-next">;
def IncompatibleMSStruct : DiagGroup<"incompatible-ms-struct">;
def IncompatiblePointerTypesDiscardsQualifiers
: DiagGroup<"incompatible-pointer-types-discards-qualifiers">;
+def IncompatibleFunctionPointerTypes
+ : DiagGroup<"incompatible-function-pointer-types">;
def IncompatiblePointerTypes
: DiagGroup<"incompatible-pointer-types",
- [IncompatiblePointerTypesDiscardsQualifiers]>;
+ [IncompatiblePointerTypesDiscardsQualifiers,
+ IncompatibleFunctionPointerTypes]>;
def IncompleteUmbrella : DiagGroup<"incomplete-umbrella">;
def NonModularIncludeInFrameworkModule
: DiagGroup<"non-modular-include-in-framework-module">;
@@ -235,6 +243,7 @@ def NonModularIncludeInModule : DiagGroup<"non-modular-include-in-module",
[NonModularIncludeInFrameworkModule]>;
def IncompleteModule : DiagGroup<"incomplete-module",
[IncompleteUmbrella, NonModularIncludeInModule]>;
+def PrivateModule : DiagGroup<"private-module">;
def CXX11InlineNamespace : DiagGroup<"c++11-inline-namespace">;
def InvalidNoreturn : DiagGroup<"invalid-noreturn">;
@@ -254,6 +263,7 @@ def LoopAnalysis : DiagGroup<"loop-analysis", [ForLoopAnalysis,
def MalformedWarningCheck : DiagGroup<"malformed-warning-check">;
def Main : DiagGroup<"main">;
def MainReturnType : DiagGroup<"main-return-type">;
+def MaxUnsignedZero : DiagGroup<"max-unsigned-zero">;
def MissingBraces : DiagGroup<"missing-braces">;
def MissingDeclarations: DiagGroup<"missing-declarations">;
def : DiagGroup<"missing-format-attribute">;
@@ -275,8 +285,11 @@ def ModuleFileExtension : DiagGroup<"module-file-extension">;
def NewlineEOF : DiagGroup<"newline-eof">;
def Nullability : DiagGroup<"nullability">;
def NullabilityDeclSpec : DiagGroup<"nullability-declspec">;
+def NullabilityInferredOnNestedType : DiagGroup<"nullability-inferred-on-nested-type">;
def NullableToNonNullConversion : DiagGroup<"nullable-to-nonnull-conversion">;
-def NullabilityCompleteness : DiagGroup<"nullability-completeness">;
+def NullabilityCompletenessOnArrays : DiagGroup<"nullability-completeness-on-arrays">;
+def NullabilityCompleteness : DiagGroup<"nullability-completeness",
+ [NullabilityCompletenessOnArrays]>;
def NullArithmetic : DiagGroup<"null-arithmetic">;
def NullCharacter : DiagGroup<"null-character">;
def NullDereference : DiagGroup<"null-dereference">;
@@ -286,6 +299,7 @@ def NonPODVarargs : DiagGroup<"non-pod-varargs">;
def ClassVarargs : DiagGroup<"class-varargs", [NonPODVarargs]>;
def : DiagGroup<"nonportable-cfstrings">;
def NonVirtualDtor : DiagGroup<"non-virtual-dtor">;
+def : DiagGroup<"effc++", [NonVirtualDtor]>;
def OveralignedType : DiagGroup<"over-aligned">;
def OldStyleCast : DiagGroup<"old-style-cast">;
def : DiagGroup<"old-style-definition">;
@@ -313,6 +327,7 @@ def ObjCRootClass : DiagGroup<"objc-root-class">;
def ObjCPointerIntrospectPerformSelector : DiagGroup<"deprecated-objc-pointer-introspection-performSelector">;
def ObjCPointerIntrospect : DiagGroup<"deprecated-objc-pointer-introspection", [ObjCPointerIntrospectPerformSelector]>;
def ObjCMultipleMethodNames : DiagGroup<"objc-multiple-method-names">;
+def OpenCLUnsupportedRGBA: DiagGroup<"opencl-unsupported-rgba">;
def DeprecatedObjCIsaUsage : DiagGroup<"deprecated-objc-isa-usage">;
def ExplicitInitializeCall : DiagGroup<"explicit-initialize-call">;
def Packed : DiagGroup<"packed">;
@@ -343,11 +358,15 @@ def MissingMethodReturnType : DiagGroup<"missing-method-return-type">;
def ShadowFieldInConstructorModified : DiagGroup<"shadow-field-in-constructor-modified">;
def ShadowFieldInConstructor : DiagGroup<"shadow-field-in-constructor",
[ShadowFieldInConstructorModified]>;
+def ShadowIvar : DiagGroup<"shadow-ivar">;
+def ShadowUncapturedLocal : DiagGroup<"shadow-uncaptured-local">;
// -Wshadow-all is a catch-all for all shadowing. -Wshadow is just the
// shadowing that we think is unsafe.
-def Shadow : DiagGroup<"shadow", [ShadowFieldInConstructorModified]>;
-def ShadowAll : DiagGroup<"shadow-all", [Shadow, ShadowFieldInConstructor]>;
+def Shadow : DiagGroup<"shadow", [ShadowFieldInConstructorModified,
+ ShadowIvar]>;
+def ShadowAll : DiagGroup<"shadow-all", [Shadow, ShadowFieldInConstructor,
+ ShadowUncapturedLocal]>;
def Shorten64To32 : DiagGroup<"shorten-64-to-32">;
def : DiagGroup<"sign-promo">;
@@ -432,8 +451,9 @@ def UninitializedSometimes : DiagGroup<"sometimes-uninitialized">;
def UninitializedStaticSelfInit : DiagGroup<"static-self-init">;
def Uninitialized : DiagGroup<"uninitialized", [UninitializedSometimes,
UninitializedStaticSelfInit]>;
+def IgnoredPragmaIntrinsic : DiagGroup<"ignored-pragma-intrinsic">;
def UnknownPragmas : DiagGroup<"unknown-pragmas">;
-def IgnoredPragmas : DiagGroup<"ignored-pragmas">;
+def IgnoredPragmas : DiagGroup<"ignored-pragmas", [IgnoredPragmaIntrinsic]>;
def Pragmas : DiagGroup<"pragmas", [UnknownPragmas, IgnoredPragmas]>;
def UnknownWarningOption : DiagGroup<"unknown-warning-option">;
def NSobjectAttribute : DiagGroup<"NSObject-attribute">;
@@ -491,6 +511,7 @@ def AutomaticReferenceCounting : DiagGroup<"arc",
def ARCRepeatedUseOfWeakMaybe : DiagGroup<"arc-maybe-repeated-use-of-weak">;
def ARCRepeatedUseOfWeak : DiagGroup<"arc-repeated-use-of-weak",
[ARCRepeatedUseOfWeakMaybe]>;
+def BlockCaptureAutoReleasing : DiagGroup<"block-capture-autoreleasing">;
def ObjCBridge : DiagGroup<"bridge-cast">;
def DeallocInCategory:DiagGroup<"dealloc-in-category">;
@@ -530,6 +551,7 @@ def GCCWriteStrings : DiagGroup<"write-strings" , [WritableStrings]>;
def CharSubscript : DiagGroup<"char-subscripts">;
def LargeByValueCopy : DiagGroup<"large-by-value-copy">;
def DuplicateArgDecl : DiagGroup<"duplicate-method-arg">;
+def SignedEnumBitfield : DiagGroup<"signed-enum-bitfield">;
// Unreachable code warning groups.
//
@@ -614,6 +636,8 @@ def Format2 : DiagGroup<"format=2",
def TypeSafety : DiagGroup<"type-safety">;
+def IncompatibleExceptionSpec : DiagGroup<"incompatible-exception-spec">;
+
def IntToVoidPointerCast : DiagGroup<"int-to-void-pointer-cast">;
def IntToPointerCast : DiagGroup<"int-to-pointer-cast",
[IntToVoidPointerCast]>;
@@ -830,8 +854,9 @@ def ObjCLiteralComparison : DiagGroup<"objc-literal-compare", [
// Inline ASM warnings.
def ASMOperandWidths : DiagGroup<"asm-operand-widths">;
+def ASMIgnoredQualifier : DiagGroup<"asm-ignored-qualifier">;
def ASM : DiagGroup<"asm", [
- ASMOperandWidths
+ ASMOperandWidths, ASMIgnoredQualifier
]>;
// OpenMP warnings.
@@ -872,3 +897,7 @@ def InvalidOrNonExistentDirectory : DiagGroup<"invalid-or-nonexistent-directory"
def OptionIgnored : DiagGroup<"option-ignored">;
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">;
diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td
index 604d51db1ffe..7f7022b49e3d 100644
--- a/include/clang/Basic/DiagnosticLexKinds.td
+++ b/include/clang/Basic/DiagnosticLexKinds.td
@@ -183,7 +183,7 @@ def ext_hex_constant_invalid : Extension<
def ext_hex_literal_invalid : Extension<
"hexadecimal floating literals are a C++1z feature">, InGroup<CXX1z>;
def warn_cxx1z_hex_literal : Warning<
- "hexidecimal floating literals are incompatible with "
+ "hexadecimal floating literals are incompatible with "
"C++ standards before C++1z">,
InGroup<CXXPre1zCompatPedantic>, DefaultIgnore;
def ext_binary_literal : Extension<
@@ -642,6 +642,11 @@ def err_mmap_expected_feature : Error<"expected a feature name">;
def err_mmap_expected_attribute : Error<"expected an attribute name">;
def warn_mmap_unknown_attribute : Warning<"unknown attribute '%0'">,
InGroup<IgnoredAttributes>;
+def warn_mmap_mismatched_top_level_private : Warning<
+ "top-level module '%0' in private module map, expected a submodule of '%1'">,
+ InGroup<PrivateModule>;
+def note_mmap_rename_top_level_private_as_submodule : Note<
+ "make '%0' a submodule of '%1' to ensure it can be found by name">;
def warn_auto_module_import : Warning<
"treating #%select{include|import|include_next|__include_macros}0 as an "
@@ -659,10 +664,10 @@ def warn_use_of_private_header_outside_module : Warning<
def err_undeclared_use_of_module : Error<
"module %0 does not depend on a module exporting '%1'">;
def warn_non_modular_include_in_framework_module : Warning<
- "include of non-modular header inside framework module '%0'">,
+ "include of non-modular header inside framework module '%0': '%1'">,
InGroup<NonModularIncludeInFrameworkModule>, DefaultIgnore;
def warn_non_modular_include_in_module : Warning<
- "include of non-modular header inside module '%0'">,
+ "include of non-modular header inside module '%0': '%1'">,
InGroup<NonModularIncludeInModule>, DefaultIgnore;
def warn_module_conflict : Warning<
"module '%0' conflicts with already-imported module '%1': %2">,
diff --git a/include/clang/Basic/DiagnosticOptions.def b/include/clang/Basic/DiagnosticOptions.def
index f4ba6da81fe0..0ab6724ed9ef 100644
--- a/include/clang/Basic/DiagnosticOptions.def
+++ b/include/clang/Basic/DiagnosticOptions.def
@@ -50,6 +50,7 @@ DIAGOPT(Pedantic, 1, 0) /// -pedantic
DIAGOPT(PedanticErrors, 1, 0) /// -pedantic-errors
DIAGOPT(ShowColumn, 1, 1) /// Show column number on diagnostics.
DIAGOPT(ShowLocation, 1, 1) /// Show source location information.
+DIAGOPT(AbsolutePath, 1, 0) /// Use absolute paths.
DIAGOPT(ShowCarets, 1, 1) /// Show carets in diagnostics.
DIAGOPT(ShowFixits, 1, 1) /// Show fixit information.
DIAGOPT(ShowSourceRanges, 1, 0) /// Show source ranges in numeric form.
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index 45044e626770..0943feae950e 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -13,10 +13,11 @@
let Component = "Parse" in {
-def w_asm_qualifier_ignored : Warning<"ignored %0 qualifier on asm">,
- CatInlineAsm;
+def warn_asm_qualifier_ignored : Warning<
+ "ignored %0 qualifier on asm">, CatInlineAsm, InGroup<ASMIgnoredQualifier>;
def warn_file_asm_volatile : Warning<
- "meaningless 'volatile' on asm outside function">, CatInlineAsm;
+ "meaningless 'volatile' on asm outside function">, CatInlineAsm,
+ InGroup<ASMIgnoredQualifier>;
let CategoryName = "Inline Assembly Issue" in {
def err_asm_empty : Error<"__asm used with no assembly instructions">;
@@ -63,7 +64,7 @@ def ext_nullability : Extension<
"type nullability specifier %0 is a Clang extension">,
InGroup<DiagGroup<"nullability-extension">>;
-def error_empty_enum : Error<"use of empty enum">;
+def err_empty_enum : Error<"use of empty enum">;
def ext_ident_list_in_param : Extension<
"type-less parameter names in function declaration">;
@@ -346,8 +347,6 @@ def ext_c11_static_assert : Extension<
def warn_cxx98_compat_static_assert : Warning<
"static_assert declarations are incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore;
-def err_paren_after_colon_colon : Error<
- "unexpected parenthesis after '::'">;
def err_function_definition_not_allowed : Error<
"function definition is not allowed here">;
def err_expected_end_of_enumerator : Error<
@@ -355,6 +354,10 @@ def err_expected_end_of_enumerator : Error<
def err_expected_coloncolon_after_super : Error<
"expected '::' after '__super'">;
+def ext_decomp_decl_empty : ExtWarn<
+ "ISO C++1z does not allow a decomposition group to be empty">,
+ InGroup<DiagGroup<"empty-decomposition">>;
+
/// Objective-C parser diagnostics
def err_expected_minus_or_plus : Error<
"method type specifier must start with '-' or '+'">;
@@ -395,7 +398,7 @@ def err_objc_expected_selector_for_getter_setter : Error<
"expected selector for Objective-C %select{setter|getter}0">;
def err_objc_property_requires_field_name : Error<
"property requires fields to be named">;
-def err_objc_property_bitfield : Error<"property name cannot be a bitfield">;
+def err_objc_property_bitfield : Error<"property name cannot be a bit-field">;
def err_objc_expected_property_attr : Error<"unknown property attribute %0">;
def err_objc_properties_require_objc2 : Error<
"properties are an Objective-C 2 feature">;
@@ -417,13 +420,11 @@ def err_unexpected_protocol_qualifier : Error<
"@implementation declaration cannot be protocol qualified">;
def err_objc_unexpected_atend : Error<
"'@end' appears where closing brace '}' is expected">;
-def error_property_ivar_decl : Error<
- "property synthesize requires specification of an ivar">;
def err_synthesized_property_name : Error<
"expected a property name in @synthesize">;
def warn_semicolon_before_method_body : Warning<
"semicolon before method body is ignored">,
- InGroup<DiagGroup<"semicolon-before-method-body">>, DefaultIgnore;
+ InGroup<SemiBeforeMethodBody>, DefaultIgnore;
def note_extra_comma_message_arg : Note<
"comma separating Objective-C messaging arguments">;
@@ -517,6 +518,12 @@ def ext_constexpr_if : ExtWarn<
def warn_cxx14_compat_constexpr_if : Warning<
"constexpr if is incompatible with C++ standards before C++1z">,
DefaultIgnore, InGroup<CXXPre1zCompat>;
+def ext_init_statement : ExtWarn<
+ "'%select{if|switch}0' initialization statements are a C++1z extension">,
+ InGroup<CXX1z>;
+def warn_cxx14_compat_init_statement : Warning<
+ "%select{if|switch}0 initialization statements are incompatible with "
+ "C++ standards before C++1z">, DefaultIgnore, InGroup<CXXPre1zCompat>;
// C++ derived classes
def err_dup_virtual : Error<"duplicate 'virtual' in base specifier">;
@@ -719,7 +726,7 @@ def warn_cxx98_compat_nonstatic_member_init : Warning<
"in-class initialization of non-static data members is incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore;
def err_bitfield_member_init: Error<
- "bitfield member cannot have an in-class initializer">;
+ "bit-field member cannot have an in-class initializer">;
def err_incomplete_array_member_init: Error<
"array bound cannot be deduced from an in-class initializer">;
@@ -733,6 +740,22 @@ def err_alias_declaration_not_identifier : Error<
"name defined in alias declaration must be an identifier">;
def err_alias_declaration_specialization : Error<
"%select{partial specialization|explicit specialization|explicit instantiation}0 of alias templates is not permitted">;
+def err_alias_declaration_pack_expansion : Error<
+ "alias declaration cannot be a pack expansion">;
+
+// C++1z using-declaration pack expansions
+def ext_multi_using_declaration : ExtWarn<
+ "use of multiple declarators in a single using declaration is "
+ "a C++1z extension">, InGroup<CXX1z>;
+def warn_cxx1z_compat_multi_using_declaration : Warning<
+ "use of multiple declarators in a single using declaration is "
+ "incompatible with C++ standards before C++1z">,
+ InGroup<CXXPre1zCompat>, DefaultIgnore;
+def ext_using_declaration_pack : ExtWarn<
+ "pack expansion of using declaration is a C++1z extension">, InGroup<CXX1z>;
+def warn_cxx1z_compat_using_declaration_pack : Warning<
+ "pack expansion using declaration is incompatible with C++ standards "
+ "before C++1z">, InGroup<CXXPre1zCompat>, DefaultIgnore;
// C++11 override control
def ext_override_control_keyword : ExtWarn<
@@ -780,11 +803,20 @@ def warn_cxx98_compat_lambda : Warning<
InGroup<CXX98Compat>, DefaultIgnore;
def err_lambda_missing_parens : Error<
"lambda requires '()' before %select{'mutable'|return type|"
- "attribute specifier}0">;
-// C++1z lambda expressions
+ "attribute specifier|'constexpr'}0">;
+def err_lambda_decl_specifier_repeated : Error<
+ "%select{'mutable'|'constexpr'}0 cannot appear multiple times in a lambda declarator">;
+// C++1z lambda expressions
def err_expected_star_this_capture : Error<
"expected 'this' following '*' in lambda capture list">;
+// C++1z constexpr lambda expressions
+def warn_cxx14_compat_constexpr_on_lambda : Warning<
+ "constexpr on lambda expressions is incompatible with C++ standards before C++1z">,
+ InGroup<CXXPre1zCompat>, DefaultIgnore;
+def ext_constexpr_on_lambda_cxx1z : ExtWarn<
+ "'constexpr' on lambda expressions is a C++1z extension">, InGroup<CXX1z>;
+
// Availability attribute
def err_expected_version : Error<
"expected a version of the form 'major[.minor[.subminor]]'">;
@@ -815,8 +847,6 @@ def warn_availability_and_unavailable : Warning<
InGroup<Availability>;
// @available(...)
-def err_avail_query_expected_condition : Error<
- "expected an availability condition here">;
def err_avail_query_expected_platform_name : Error<
"expected a platform name here">;
@@ -900,6 +930,10 @@ def warn_pragma_invalid_action : Warning<
def warn_pragma_pack_malformed : Warning<
"expected integer or identifier in '#pragma pack' - ignored">,
InGroup<IgnoredPragmas>;
+// - #pragma intrinsic
+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 unused
def warn_pragma_unused_expected_var : Warning<
"expected '#pragma unused' argument to be a variable name">,
@@ -941,8 +975,10 @@ def err_opencl_unroll_hint_on_non_loop : Error<
// OpenCL EXTENSION pragma (OpenCL 1.1 [9.1])
def warn_pragma_expected_colon : Warning<
"missing ':' after %0 - ignoring">, InGroup<IgnoredPragmas>;
-def warn_pragma_expected_enable_disable : Warning<
- "expected 'enable' or 'disable' - ignoring">, InGroup<IgnoredPragmas>;
+def warn_pragma_expected_predicate : Warning<
+ "expected %select{'enable', 'disable', 'begin' or 'end'|'disable'}0 - ignoring">, InGroup<IgnoredPragmas>;
+def warn_pragma_begin_end_mismatch : Warning<
+ "OpenCL extension end directive mismatches begin directive - ignoring">, InGroup<IgnoredPragmas>;
def warn_pragma_unknown_extension : Warning<
"unknown OpenCL extension %0 - ignoring">, InGroup<IgnoredPragmas>;
def warn_pragma_unsupported_extension : Warning<
@@ -1007,14 +1043,36 @@ def err_pragma_invalid_keyword : Error<
def warn_pragma_unroll_cuda_value_in_parens : Warning<
"argument to '#pragma unroll' should not be in parentheses in CUDA C/C++">,
InGroup<CudaCompat>;
+
+def warn_cuda_attr_lambda_position : Warning<
+ "nvcc does not allow '__%0__' to appear after '()' in lambdas">,
+ InGroup<CudaCompat>;
+def warn_pragma_force_cuda_host_device_bad_arg : Warning<
+ "incorrect use of #pragma clang force_cuda_host_device begin|end">,
+ InGroup<IgnoredPragmas>;
+def err_pragma_cannot_end_force_cuda_host_device : Error<
+ "force_cuda_host_device end pragma without matching "
+ "force_cuda_host_device begin">;
} // end of Parse Issue category.
let CategoryName = "Modules Issue" in {
+def err_expected_module_interface_decl : Error<
+ "expected module declaration at start of module interface">;
+def err_unexpected_module_decl : Error<
+ "module declaration must be the first declaration in the translation unit">;
def err_module_expected_ident : Error<
- "expected a module name after module import">;
+ "expected a module name after module%select{| import}0">;
+def err_unexpected_module_kind : Error<
+ "unexpected module kind %0; expected 'implementation' or 'partition'">;
+def err_attribute_not_module_attr : Error<
+ "%0 attribute cannot be applied to a module">;
+def err_attribute_not_import_attr : Error<
+ "%0 attribute cannot be applied to a module import">;
def err_module_expected_semi : Error<
"expected ';' after module name">;
def err_missing_before_module_end : Error<"expected %0 at end of module">;
+
+def err_export_empty : Error<"export declaration cannot be empty">;
}
let CategoryName = "Generics Issue" in {
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 98b687b8e821..c4e4e2b60192 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -53,6 +53,14 @@ def warn_pointer_abs : Warning<
"taking the absolute value of %select{pointer|function|array}0 type %1 is suspicious">,
InGroup<AbsoluteValue>;
+def warn_max_unsigned_zero : Warning<
+ "taking the max of "
+ "%select{a value and unsigned zero|unsigned zero and a value}0 "
+ "is always equal to the other value">,
+ InGroup<MaxUnsignedZero>;
+def note_remove_max_call : Note<
+ "remove call to max function and unsigned zero argument">;
+
def warn_infinite_recursive_function : Warning<
"all paths through this function will call itself">,
InGroup<InfiniteRecursion>, DefaultIgnore;
@@ -357,6 +365,9 @@ def warn_decl_shadow :
"static data member of %2|"
"field of %2}1">,
InGroup<Shadow>, DefaultIgnore;
+def warn_decl_shadow_uncaptured_local :
+ Warning<warn_decl_shadow.Text>,
+ InGroup<ShadowUncapturedLocal>, DefaultIgnore;
def warn_ctor_parm_shadows_field:
Warning<"constructor parameter %0 shadows the field %1 of %2">,
InGroup<ShadowFieldInConstructor>, DefaultIgnore;
@@ -365,6 +376,58 @@ def warn_modifying_shadowing_decl :
"field of %1">,
InGroup<ShadowFieldInConstructorModified>, DefaultIgnore;
+// C++ decomposition declarations
+def err_decomp_decl_context : Error<
+ "decomposition declaration not permitted in this context">;
+def warn_cxx14_compat_decomp_decl : Warning<
+ "decomposition declarations are incompatible with "
+ "C++ standards before C++1z">, DefaultIgnore, InGroup<CXXPre1zCompat>;
+def ext_decomp_decl : ExtWarn<
+ "decomposition declarations are a C++1z extension">, InGroup<CXX1z>;
+def err_decomp_decl_spec : Error<
+ "decomposition declaration cannot be declared "
+ "%plural{1:'%1'|:with '%1' specifiers}0">;
+def err_decomp_decl_type : Error<
+ "decomposition declaration cannot be declared with type %0; "
+ "declared type must be 'auto' or reference to 'auto'">;
+def err_decomp_decl_parens : Error<
+ "decomposition declaration cannot be declared with parentheses">;
+def err_decomp_decl_template : Error<
+ "decomposition declaration template not supported">;
+def err_decomp_decl_not_alone : Error<
+ "decomposition declaration must be the only declaration in its group">;
+def err_decomp_decl_requires_init : Error<
+ "decomposition declaration %0 requires an initializer">;
+def err_decomp_decl_wrong_number_bindings : Error<
+ "type %0 decomposes into %2 elements, but %select{only |}3%1 "
+ "names were provided">;
+def err_decomp_decl_unbindable_type : Error<
+ "cannot decompose %select{union|non-class, non-array}1 type %2">;
+def err_decomp_decl_multiple_bases_with_members : Error<
+ "cannot decompose class type %1: "
+ "%select{its base classes %2 and|both it and its base class}0 %3 "
+ "have non-static data members">;
+def err_decomp_decl_ambiguous_base : Error<
+ "cannot decompose members of ambiguous base class %1 of %0:%2">;
+def err_decomp_decl_non_public_base : Error<
+ "cannot decompose members of non-public base class %1 of %0">;
+def err_decomp_decl_non_public_member : Error<
+ "cannot decompose non-public member %0 of %1">;
+def err_decomp_decl_anon_union_member : Error<
+ "cannot decompose class type %0 because it has an anonymous "
+ "%select{struct|union}1 member">;
+def err_decomp_decl_std_tuple_element_not_specialized : Error<
+ "cannot decompose this type; 'std::tuple_element<%0>::type' "
+ "does not name a type">;
+def err_decomp_decl_std_tuple_size_not_constant : Error<
+ "cannot decompose this type; 'std::tuple_size<%0>::value' "
+ "is not a valid integral constant expression">;
+def note_in_binding_decl_init : Note<
+ "in implicit initialization of binding declaration %0">;
+
+def err_std_type_trait_not_class_template : Error<
+ "unsupported standard library implementation: "
+ "'std::%0' is not a class template">;
// C++ using declarations
def err_using_requires_qualname : Error<
@@ -411,6 +474,8 @@ def err_using_decl_conflict : Error<
def err_using_decl_conflict_reverse : Error<
"declaration conflicts with target of using declaration already in scope">;
def note_using_decl : Note<"%select{|previous }0using declaration">;
+def err_using_decl_redeclaration_expansion : Error<
+ "using declaration pack expansion at block scope produces multiple values">;
def warn_access_decl_deprecated : Warning<
"access declarations are deprecated; use using declarations instead">,
@@ -418,15 +483,21 @@ def warn_access_decl_deprecated : Warning<
def err_access_decl : Error<
"ISO C++11 does not allow access declarations; "
"use using declarations instead">;
+def ext_dynamic_exception_spec : ExtWarn<
+ "ISO C++1z does not allow dynamic exception specifications">,
+ InGroup<DynamicExceptionSpec>, DefaultError;
def warn_exception_spec_deprecated : Warning<
"dynamic exception specifications are deprecated">,
- InGroup<Deprecated>, DefaultIgnore;
+ InGroup<DeprecatedDynamicExceptionSpec>, DefaultIgnore;
def note_exception_spec_deprecated : Note<"use '%0' instead">;
def warn_deprecated_copy_operation : Warning<
"definition of implicit copy %select{constructor|assignment operator}1 "
"for %0 is deprecated because it has a user-declared "
"%select{copy %select{assignment operator|constructor}1|destructor}2">,
InGroup<Deprecated>, DefaultIgnore;
+def warn_cxx1z_compat_exception_spec_in_signature : Warning<
+ "mangled name of %0 will change in C++17 due to non-throwing exception "
+ "specification in function signature">, InGroup<CXX1zCompat>;
def warn_global_constructor : Warning<
"declaration requires a global constructor">,
@@ -455,6 +526,12 @@ def err_maybe_falloff_nonvoid_block : Error<
"control may reach end of non-void block">;
def err_falloff_nonvoid_block : Error<
"control reaches end of non-void block">;
+def warn_maybe_falloff_nonvoid_coroutine : Warning<
+ "control may reach end of non-void coroutine">,
+ InGroup<ReturnType>;
+def warn_falloff_nonvoid_coroutine : Warning<
+ "control reaches end of non-void coroutine">,
+ InGroup<ReturnType>;
def warn_suggest_noreturn_function : Warning<
"%select{function|method}0 %1 could be declared with attribute 'noreturn'">,
InGroup<MissingNoreturn>, DefaultIgnore;
@@ -580,6 +657,8 @@ def warn_main_one_arg : Warning<"only one parameter on 'main' declaration">,
def err_main_arg_wrong : Error<"%select{first|second|third|fourth}0 "
"parameter of 'main' (%select{argument count|argument array|environment|"
"platform-specific data}0) must be of type %1">;
+def warn_main_returns_bool_literal : Warning<"bool literal returned from "
+ "'main'">, InGroup<Main>;
def err_main_global_variable :
Error<"main cannot be declared as global variable">;
def warn_main_redefined : Warning<"variable named 'main' with external linkage "
@@ -605,7 +684,8 @@ def err_object_cannot_be_passed_returned_by_value : Error<
def err_parameters_retval_cannot_have_fp16_type : Error<
"%select{parameters|function return value}0 cannot have __fp16 type; did you forget * ?">;
def err_opencl_half_load_store : Error<
- "%select{loading directly from|assigning directly to}0 pointer to type %1 is not allowed">;
+ "%select{loading directly from|assigning directly to}0 pointer to type %1 requires "
+ "cl_khr_fp16. Use vector data %select{load|store}0 builtin functions instead">;
def err_opencl_cast_to_half : Error<"casting to type %0 is not allowed">;
def err_opencl_half_declaration : Error<
"declaring variable of type %0 is not allowed">;
@@ -675,7 +755,9 @@ def err_recursive_superclass : Error<
"trying to recursively use %0 as superclass of %1">;
def err_conflicting_aliasing_type : Error<"conflicting types for alias %0">;
def warn_undef_interface : Warning<"cannot find interface declaration for %0">;
-def warn_duplicate_protocol_def : Warning<"duplicate protocol definition of %0 is ignored">;
+def warn_duplicate_protocol_def : Warning<
+ "duplicate protocol definition of %0 is ignored">,
+ InGroup<DiagGroup<"duplicate-protocol">>;
def err_protocol_has_circular_dependency : Error<
"protocol has circular dependency">;
def err_undeclared_protocol : Error<"cannot find protocol declaration for %0">;
@@ -717,6 +799,9 @@ def note_suppressed_class_declare : Note<
"class with specified objc_requires_property_definitions attribute is declared here">;
def err_objc_root_class_subclass : Error<
"objc_root_class attribute may only be specified on a root class declaration">;
+def err_restricted_superclass_mismatch : Error<
+ "cannot subclass a class that was declared with the "
+ "'objc_subclassing_restricted' attribute">;
def warn_objc_root_class_missing : Warning<
"class %0 defined without specifying a base class">,
InGroup<ObjCRootClass>;
@@ -832,7 +917,7 @@ def warn_strict_multiple_method_decl : Warning<
"multiple methods named %0 found">, InGroup<StrictSelector>, DefaultIgnore;
def warn_accessor_property_type_mismatch : Warning<
"type of property %0 does not match type of accessor %1">;
-def not_conv_function_declared_at : Note<"type conversion function declared here">;
+def note_conv_function_declared_at : Note<"type conversion function declared here">;
def note_method_declared_at : Note<"method %0 declared here">;
def note_property_attribute : Note<"property %0 is declared "
"%select{deprecated|unavailable|partial}1 here">;
@@ -848,7 +933,7 @@ def warn_objc_cdirective_format_string :
InGroup<ObjCCStringFormat>, DefaultIgnore;
def err_objc_var_decl_inclass :
Error<"cannot declare variable inside @interface or @protocol">;
-def error_missing_method_context : Error<
+def err_missing_method_context : Error<
"missing context for method declaration">;
def err_objc_property_attr_mutually_exclusive : Error<
"property attributes '%0' and '%1' are mutually exclusive">;
@@ -939,7 +1024,7 @@ def warn_property_getter_owning_mismatch : Warning<
def warn_property_redecl_getter_mismatch : Warning<
"getter name mismatch between property redeclaration (%1) and its original "
"declaration (%0)">, InGroup<PropertyAttr>;
-def error_property_setter_ambiguous_use : Error<
+def err_property_setter_ambiguous_use : Error<
"synthesized properties %0 and %1 both claim setter %2 -"
" use of this setter will cause unexpected behavior">;
def warn_default_atomic_custom_getter_setter : Warning<
@@ -958,12 +1043,12 @@ def err_use_continuation_class_redeclaration_readwrite : Error<
"'readonly' public property?)">;
def err_continuation_class : Error<"class extension has no primary class">;
def err_property_type : Error<"property cannot have array or function type %0">;
-def error_missing_property_context : Error<
+def err_missing_property_context : Error<
"missing context for property implementation declaration">;
-def error_bad_property_decl : Error<
+def err_bad_property_decl : Error<
"property implementation must have its declaration in interface %0 or one of "
"its extensions">;
-def error_category_property : Error<
+def err_category_property : Error<
"property declared in category %0 cannot be implemented in "
"class implementation">;
def note_property_declare : Note<
@@ -972,19 +1057,17 @@ def note_protocol_property_declare : Note<
"it could also be property of type %0 declared here">;
def note_property_synthesize : Note<
"property synthesized here">;
-def error_synthesize_category_decl : Error<
+def err_synthesize_category_decl : Error<
"@synthesize not allowed in a category's implementation">;
-def error_synthesize_on_class_property : Error<
+def err_synthesize_on_class_property : Error<
"@synthesize not allowed on a class property %0">;
-def error_reference_property : Error<
- "property of reference type is not supported">;
-def error_missing_property_interface : Error<
+def err_missing_property_interface : Error<
"property implementation in a category with no category declaration">;
-def error_bad_category_property_decl : Error<
+def err_bad_category_property_decl : Error<
"property implementation must have its declaration in the category %0">;
-def error_bad_property_context : Error<
+def err_bad_property_context : Error<
"property implementation must be in a class or category implementation">;
-def error_missing_property_ivar_decl : Error<
+def err_missing_property_ivar_decl : Error<
"synthesized property %0 must either be named the same as a compatible"
" instance variable or must explicitly name an instance variable">;
def err_arc_perform_selector_retains : Error<
@@ -1018,25 +1101,25 @@ def note_arc_weak_also_accessed_here : Note<
def err_incomplete_synthesized_property : Error<
"cannot synthesize property %0 with incomplete type %1">;
-def error_property_ivar_type : Error<
+def err_property_ivar_type : Error<
"type of property %0 (%1) does not match type of instance variable %2 (%3)">;
-def error_property_accessor_type : Error<
+def err_property_accessor_type : Error<
"type of property %0 (%1) does not match type of accessor %2 (%3)">;
-def error_ivar_in_superclass_use : Error<
+def err_ivar_in_superclass_use : Error<
"property %0 attempting to use instance variable %1 declared in super class %2">;
-def error_weak_property : Error<
+def err_weak_property : Error<
"existing instance variable %1 for __weak property %0 must be __weak">;
-def error_strong_property : Error<
+def err_strong_property : Error<
"existing instance variable %1 for strong property %0 may not be __weak">;
-def error_dynamic_property_ivar_decl : Error<
+def err_dynamic_property_ivar_decl : Error<
"dynamic property cannot have instance variable specification">;
-def error_duplicate_ivar_use : Error<
+def err_duplicate_ivar_use : Error<
"synthesized properties %0 and %1 both claim instance variable %2">;
-def error_property_implemented : Error<"property %0 is already implemented">;
+def err_property_implemented : Error<"property %0 is already implemented">;
def warn_objc_missing_super_call : Warning<
"method possibly missing a [super %0] call">,
InGroup<ObjCMissingSuperCalls>;
-def error_dealloc_bad_result_type : Error<
+def err_dealloc_bad_result_type : Error<
"dealloc return type must be correctly specified as 'void' under ARC, "
"instead of %0">;
def warn_undeclared_selector : Warning<
@@ -1060,7 +1143,7 @@ def warn_unimplemented_selector: Warning<
InGroup<Selector>, DefaultIgnore;
def warn_unimplemented_protocol_method : Warning<
"method %0 in protocol %1 not implemented">, InGroup<Protocol>;
-def warning_multiple_selectors: Warning<
+def warn_multiple_selectors: Warning<
"several methods with selector %0 of mismatched types are found "
"for the @selector expression">,
InGroup<SelectorTypeMismatch>, DefaultIgnore;
@@ -1087,10 +1170,9 @@ def warn_cxx14_compat_inline_variable : Warning<
DefaultIgnore, InGroup<CXXPre1zCompat>;
def warn_inline_namespace_reopened_noninline : Warning<
- "inline namespace cannot be reopened as a non-inline namespace">;
+ "inline namespace reopened as a non-inline namespace">;
def err_inline_namespace_mismatch : Error<
- "%select{|non-}0inline namespace "
- "cannot be reopened as %select{non-|}0inline">;
+ "non-inline namespace cannot be reopened as inline">;
def err_unexpected_friend : Error<
"friends can only be classes or functions">;
@@ -1240,8 +1322,12 @@ def ext_override_exception_spec : ExtWarn<err_override_exception_spec.Text>,
InGroup<MicrosoftExceptionSpec>;
def err_incompatible_exception_specs : Error<
"target exception specification is not superset of source">;
+def warn_incompatible_exception_specs : Warning<
+ err_incompatible_exception_specs.Text>, InGroup<IncompatibleExceptionSpec>;
def err_deep_exception_specs_differ : Error<
"exception specifications of %select{return|argument}0 types differ">;
+def warn_deep_exception_specs_differ : Warning<
+ err_deep_exception_specs_differ.Text>, InGroup<IncompatibleExceptionSpec>;
def err_missing_exception_specification : Error<
"%0 is missing exception specification '%1'">;
def ext_missing_exception_specification : ExtWarn<
@@ -1590,7 +1676,8 @@ def err_init_conversion_failed : Error<
"%select{none|const|restrict|const and restrict|volatile|const and volatile|"
"volatile and restrict|const, volatile, and restrict}5 vs "
"%select{none|const|restrict|const and restrict|volatile|const and volatile|"
- "volatile and restrict|const, volatile, and restrict}6)}4">;
+ "volatile and restrict|const, volatile, and restrict}6)"
+ "|: different exception specifications}4">;
def err_lvalue_to_rvalue_ref : Error<"rvalue reference %diff{to type $ cannot "
"bind to lvalue of type $|cannot bind to incompatible lvalue}0,1">;
@@ -1691,8 +1778,10 @@ def warn_uninit_byref_blockvar_captured_by_block : Warning<
def note_block_var_fixit_add_initialization : Note<
"did you mean to use __block %0?">;
def note_in_omitted_aggregate_initializer : Note<
- "in implicit initialization of %select{array element %1|field %1}0 "
- "with omitted initializer">;
+ "in implicit initialization of %select{"
+ "array element %1 with omitted initializer|"
+ "field %1 with omitted initializer|"
+ "trailing array elements in runtime-sized array new}0">;
def note_in_reference_temporary_list_initializer : Note<
"in initialization of temporary of type %0 created to "
"list-initialize this reference">;
@@ -1702,6 +1791,8 @@ def note_uninit_fixit_remove_cond : Note<
"remove the %select{'%1' if its condition|condition if it}0 "
"is always %select{false|true}2">;
def err_init_incomplete_type : Error<"initialization of incomplete type %0">;
+def err_list_init_in_parens : Error<"list-initializer for non-class type %0 "
+ "must not be parenthesized">;
def warn_unsequenced_mod_mod : Warning<
"multiple unsequenced modifications to %0">, InGroup<Unsequenced>;
@@ -1756,6 +1847,9 @@ def warn_cxx98_compat_auto_type_specifier : Warning<
def err_auto_variable_cannot_appear_in_own_initializer : Error<
"variable %0 declared with %select{'auto'|'decltype(auto)'|'__auto_type'}1 "
"type cannot appear in its own initializer">;
+def err_binding_cannot_appear_in_own_initializer : Error<
+ "binding %0 cannot appear in the initializer of its own "
+ "decomposition declaration">;
def err_illegal_decl_array_of_auto : Error<
"'%0' declared as array of %1">;
def err_new_array_of_auto : Error<
@@ -1769,7 +1863,8 @@ def err_auto_not_allowed : Error<
"|in exception declaration|in template parameter|in block literal"
"|in template argument|in typedef|in type alias|in function return type"
"|in conversion function type|here|in lambda parameter"
- "|in type allocated by 'new'|in K&R-style function parameter}1">;
+ "|in type allocated by 'new'|in K&R-style function parameter}1"
+ "%select{|||||||| until C++1z||||||||||}1">;
def err_auto_not_allowed_var_inst : Error<
"'auto' variable template instantiation is not allowed">;
def err_auto_var_requires_init : Error<
@@ -2198,10 +2293,15 @@ def err_attribute_only_once_per_parameter : Error<
"%0 attribute can only be applied once per parameter">;
def err_attribute_uuid_malformed_guid : Error<
"uuid attribute contains a malformed GUID">;
+def err_mismatched_uuid : Error<"uuid does not match previous declaration">;
+def note_previous_uuid : Note<"previous uuid specified here">;
def warn_attribute_pointers_only : Warning<
"%0 attribute only applies to%select{| constant}1 pointer arguments">,
InGroup<IgnoredAttributes>;
def err_attribute_pointers_only : Error<warn_attribute_pointers_only.Text>;
+def err_attribute_integers_only : Error<
+ "%0 attribute argument may only refer to a function parameter of integer "
+ "type">;
def warn_attribute_return_pointers_only : Warning<
"%0 attribute only applies to return values that are pointers">,
InGroup<IgnoredAttributes>;
@@ -2242,6 +2342,9 @@ def err_typecheck_vector_not_convertable_non_scalar : Error<
"cannot convert between vector and non-scalar values (%0 and %1)">;
def err_typecheck_vector_lengths_not_equal : Error<
"vector operands do not have the same number of elements (%0 and %1)">;
+def warn_typecheck_vector_element_sizes_not_equal : Warning<
+ "vector operands do not have the same elements sizes (%0 and %1)">,
+ InGroup<DiagGroup<"vec-elem-size">>, DefaultError;
def err_ext_vector_component_exceeds_length : Error<
"vector component access exceeds type %0">;
def err_ext_vector_component_name_illegal : Error<
@@ -2311,17 +2414,15 @@ def err_swift_param_attr_not_swiftcall : Error<
"'%0' parameter can only be used with swiftcall calling convention">;
def err_swift_indirect_result_not_first : Error<
"'swift_indirect_result' parameters must be first parameters of function">;
-def err_swift_context_not_before_swift_error_result : Error<
- "'swift_context' parameter can only be followed by 'swift_error_result' "
- "parameter">;
-def err_swift_error_result_not_last : Error<
- "'swift_error_result' parameter must be last parameter of function">;
def err_swift_error_result_not_after_swift_context : Error<
"'swift_error_result' parameter must follow 'swift_context' parameter">;
def err_swift_abi_parameter_wrong_type : Error<
"'%0' parameter must have pointer%select{| to unqualified pointer}1 type; "
"type here is %2">;
+def err_attribute_argument_invalid : Error<
+ "%0 attribute argument is invalid: %select{max must be 0 since min is 0|"
+ "min must not be greater than max}1">;
def err_attribute_argument_is_zero : Error<
"%0 attribute must be greater than 0">;
def warn_attribute_argument_n_negative : Warning<
@@ -2357,9 +2458,17 @@ def err_property_is_variably_modified : Error<
"property %0 has a variably modified type">;
def err_no_accessor_for_property : Error<
"no %select{getter|setter}0 defined for property %1">;
-def error_cannot_find_suitable_accessor : Error<
+def err_cannot_find_suitable_accessor : Error<
"cannot find suitable %select{getter|setter}0 for property %1">;
+def warn_alloca_align_alignof : Warning<
+ "second argument to __builtin_alloca_with_align is supposed to be in bits">,
+ InGroup<DiagGroup<"alloca-with-align-alignof">>;
+
+def err_alignment_too_small : Error<
+ "requested alignment must be %0 or greater">;
+def err_alignment_too_big : Error<
+ "requested alignment must be %0 or smaller">;
def err_alignment_not_power_of_two : Error<
"requested alignment is not a power of 2">;
def err_alignment_dependent_typedef_name : Error<
@@ -2502,25 +2611,52 @@ def err_ifunc_resolver_return : Error<
def err_ifunc_resolver_params : Error<
"ifunc resolver function must have no parameters">;
def warn_attribute_wrong_decl_type : Warning<
- "%0 attribute only applies to %select{functions|unions|"
- "variables and functions|"
- "functions, variables, and Objective-C interfaces|"
- "functions and methods|parameters|"
- "functions, methods and blocks|functions, methods, and classes|"
- "functions, methods, and parameters|classes|enums|variables|methods|"
- "fields and global variables|structs|parameters and typedefs|variables and typedefs|"
- "thread-local variables|variables and fields|variables, data members and tag types|"
- "types and namespaces|Objective-C interfaces|methods and properties|"
- "struct or union|struct, union or class|types|"
- "Objective-C instance methods|init methods of interface or class extension declarations|"
- "variables, functions and classes|"
- "functions, variables, classes, and Objective-C interfaces|"
- "Objective-C protocols|"
- "functions and global variables|structs, unions, and typedefs|structs and typedefs|"
- "interface or protocol declarations|kernel functions|non-K&R-style functions|"
- "variables, enums, fields and typedefs|functions, methods, enums, and classes|"
- "structs, classes, variables, functions, and inline namespaces|"
- "variables, functions, methods, types, enumerations, enumerators, labels, and non-static data members}1">,
+ "%0 attribute only applies to %select{"
+ "functions"
+ "|unions"
+ "|variables and functions"
+ "|functions and global variables"
+ "|functions, variables, and Objective-C interfaces"
+ "|functions and methods"
+ "|parameters"
+ "|functions, methods and blocks"
+ "|functions, methods, and classes"
+ "|functions, methods, and parameters"
+ "|functions, methods, and global variables"
+ "|classes"
+ "|enums"
+ "|variables"
+ "|methods"
+ "|fields and global variables"
+ "|structs"
+ "|parameters and typedefs"
+ "|variables and typedefs"
+ "|thread-local variables"
+ "|variables and fields"
+ "|variables, data members and tag types"
+ "|types and namespaces"
+ "|Objective-C interfaces"
+ "|methods and properties"
+ "|struct or union"
+ "|struct, union or class"
+ "|types"
+ "|Objective-C instance methods"
+ "|init methods of interface or class extension declarations"
+ "|variables, functions and classes"
+ "|functions, variables, classes, and Objective-C interfaces"
+ "|Objective-C protocols"
+ "|variables with static or thread storage duration"
+ "|functions, methods, properties, and global variables"
+ "|structs, unions, and typedefs"
+ "|structs and typedefs"
+ "|interface or protocol declarations"
+ "|kernel functions"
+ "|non-K&R-style functions"
+ "|variables, enums, fields and typedefs"
+ "|functions, methods, enums, and classes"
+ "|structs, classes, variables, functions, and inline namespaces"
+ "|variables, functions, methods, types, enumerations, enumerators, labels, and non-static data members"
+ "|classes and enumerations}1">,
InGroup<IgnoredAttributes>;
def err_attribute_wrong_decl_type : Error<warn_attribute_wrong_decl_type.Text>;
def warn_type_attribute_wrong_type : Warning<
@@ -2599,8 +2735,20 @@ def note_overridden_method : Note<
def note_protocol_method : Note<
"protocol method is here">;
-def warn_available_using_star_case : Warning<
- "using '*' case here, platform %0 is not accounted for">, InGroup<UnguardedAvailability>;
+def warn_unguarded_availability :
+ Warning<"%0 is only available on %1 %2 or newer">,
+ InGroup<UnguardedAvailability>, DefaultIgnore;
+def warn_partial_availability : Warning<"%0 is only available conditionally">,
+ InGroup<UnguardedAvailability>, DefaultIgnore;
+def note_partial_availability_silence : Note<
+ "explicitly redeclare %0 to silence this warning">;
+def note_unguarded_available_silence : Note<
+ "enclose %0 in an @available check to silence this warning">;
+def warn_partial_message : Warning<"%0 is partial: %1">,
+ InGroup<UnguardedAvailability>, DefaultIgnore;
+def warn_partial_fwdclass_message : Warning<
+ "%0 may be partial because the receiver type is unknown">,
+ InGroup<UnguardedAvailability>, DefaultIgnore;
// Thread Safety Attributes
def warn_invalid_capability_name : Warning<
@@ -2784,7 +2932,7 @@ def warn_impcast_integer_precision_constant : Warning<
"implicit conversion from %2 to %3 changes value from %0 to %1">,
InGroup<ConstantConversion>;
def warn_impcast_bitfield_precision_constant : Warning<
- "implicit truncation from %2 to bitfield changes value from %0 to %1">,
+ "implicit truncation from %2 to bit-field changes value from %0 to %1">,
InGroup<BitFieldConstantConversion>;
def warn_impcast_literal_float_to_integer : Warning<
@@ -2887,6 +3035,10 @@ def warn_int_to_void_pointer_cast : Warning<
"cast to %1 from smaller integer type %0">,
InGroup<IntToVoidPointerCast>;
+def warn_no_underlying_type_specified_for_enum_bitfield : Warning<
+ "enums in the Microsoft ABI are signed integers by default; consider giving "
+ "the enum %0 an unsigned underlying type to make this code portable">,
+ InGroup<SignedEnumBitfield>, DefaultIgnore;
def warn_attribute_packed_for_bitfield : Warning<
"'packed' attribute was ignored on bit-fields with single-byte alignment "
"in older versions of GCC and Clang">,
@@ -3166,17 +3318,18 @@ def note_ovl_candidate : Note<"candidate "
"is the implicit copy assignment operator|"
"is the implicit move assignment operator|"
"inherited constructor|"
- "inherited constructor }0%1"
- "%select{| has different class%diff{ (expected $ but has $)|}3,4"
- "| has different number of parameters (expected %3 but has %4)"
- "| has type mismatch at %ordinal3 parameter"
- "%diff{ (expected $ but has $)|}4,5"
- "| has different return type%diff{ ($ expected but has $)|}3,4"
+ "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"
"| has different qualifiers (expected "
"%select{none|const|restrict|const and restrict|volatile|const and volatile"
- "|volatile and restrict|const, volatile, and restrict}3 but found "
+ "|volatile and restrict|const, volatile, and restrict}4 but found "
"%select{none|const|restrict|const and restrict|volatile|const and volatile"
- "|volatile and restrict|const, volatile, and restrict}4)}2">;
+ "|volatile and restrict|const, volatile, and restrict}5)"
+ "| has different exception specification}3">;
def note_ovl_candidate_inherited_constructor : Note<
"constructor from base class %0 inherited here">;
@@ -3190,6 +3343,10 @@ def note_ovl_candidate_incomplete_deduction : Note<"candidate template ignored:
def note_ovl_candidate_inconsistent_deduction : Note<
"candidate template ignored: deduced conflicting %select{types|values|"
"templates}0 for parameter %1%diff{ ($ vs. $)|}2,3">;
+def note_ovl_candidate_inconsistent_deduction_types : Note<
+ "candidate template ignored: deduced values %diff{"
+ "of conflicting types for parameter %0 (%1 of type $ vs. %3 of type $)|"
+ "%1 and %3 of conflicting types for parameter %0}2,4">;
def note_ovl_candidate_explicit_arg_mismatch_named : Note<
"candidate template ignored: invalid explicitly-specified argument "
"for template parameter %0">;
@@ -3211,6 +3368,8 @@ def note_ovl_candidate_has_pass_object_size_params: Note<
"pass_object_size attribute">;
def note_ovl_candidate_disabled_by_enable_if_attr : Note<
"candidate disabled: %0">;
+def note_ovl_candidate_disabled_by_extension : Note<
+ "candidate disabled due to OpenCL extension">;
def err_addrof_function_disabled_by_enable_if_attr : Error<
"cannot take address of function %0 becuase it has one or more "
"non-tautological enable_if conditions">;
@@ -3581,6 +3740,10 @@ def note_template_nontype_parm_prev_declaration : Note<
"previous non-type template parameter with type %0 is here">;
def err_template_nontype_parm_bad_type : Error<
"a non-type template parameter cannot have type %0">;
+def warn_cxx14_compat_template_nontype_parm_auto_type : Warning<
+ "non-type template parameters declared with %0 are incompatible with C++ "
+ "standards before C++1z">,
+ DefaultIgnore, InGroup<CXXPre1zCompat>;
def err_template_param_default_arg_redefinition : Error<
"template parameter redefines default argument">;
def note_template_param_prev_default_arg : Note<
@@ -3675,11 +3838,13 @@ def warn_cxx98_compat_template_arg_null : Warning<
def err_template_arg_untyped_null_constant : Error<
"null non-type template argument must be cast to template parameter type %0">;
def err_template_arg_wrongtype_null_constant : Error<
- "null non-type template argument of type %0 does not match template parameter "
- "of type %1">;
+ "null non-type template argument of type %0 does not match template parameter "
+ "of type %1">;
+def err_non_type_template_parm_type_deduction_failure : Error<
+ "non-type template parameter %0 with type %1 has incompatible initializer of type %2">;
def err_deduced_non_type_template_arg_type_mismatch : Error<
"deduced non-type template argument does not have the same type as the "
- "its corresponding template parameter%diff{ ($ vs $)|}0,1">;
+ "corresponding template parameter%diff{ ($ vs $)|}0,1">;
def err_non_type_template_arg_subobject : Error<
"non-type template argument refers to subobject '%0'">;
def err_non_type_template_arg_addr_label_diff : Error<
@@ -3867,8 +4032,8 @@ def err_specialize_member_of_template : Error<
def err_default_arg_in_partial_spec : Error<
"default template argument in a class template partial specialization">;
def err_dependent_non_type_arg_in_partial_spec : Error<
- "non-type template argument depends on a template parameter of the "
- "partial specialization">;
+ "type of specialized non-type template argument depends on a template "
+ "parameter of the partial specialization">;
def note_dependent_non_type_default_arg_in_partial_spec : Note<
"template parameter is used in default argument declared here">;
def err_dependent_typed_non_type_arg_in_partial_spec : Error<
@@ -3878,10 +4043,16 @@ def err_partial_spec_args_match_primary_template : Error<
"%select{class|variable}0 template partial specialization does not "
"specialize any template argument; to %select{declare|define}1 the "
"primary template, remove the template argument list">;
-def warn_partial_specs_not_deducible : Warning<
+def ext_partial_spec_not_more_specialized_than_primary : ExtWarn<
+ "%select{class|variable}0 template partial specialization is not "
+ "more specialized than the primary template">, DefaultError,
+ InGroup<DiagGroup<"invalid-partial-specialization">>;
+def note_partial_spec_not_more_specialized_than_primary : Note<"%0">;
+def ext_partial_specs_not_deducible : ExtWarn<
"%select{class|variable}0 template partial specialization contains "
"%select{a template parameter|template parameters}1 that cannot be "
- "deduced; this partial specialization will never be used">;
+ "deduced; this partial specialization will never be used">,
+ DefaultError, InGroup<DiagGroup<"unusable-partial-specialization">>;
def note_partial_spec_unused_parameter : Note<
"non-deducible template parameter %0">;
def err_partial_spec_ordering_ambiguous : Error<
@@ -3915,7 +4086,7 @@ def err_function_template_spec_ambiguous : Error<
"function template; explicitly specify%select{| additional}1 template "
"arguments to identify a particular function template">;
def note_function_template_spec_matched : Note<
- "function template matches specialization %0">;
+ "function template %q0 matches specialization %1">;
def err_function_template_partial_spec : Error<
"function template partial specialization is not allowed">;
@@ -3938,9 +4109,9 @@ def note_template_class_instantiation_was_here : Note<
def note_template_class_explicit_specialization_was_here : Note<
"class template %0 was explicitly specialized here">;
def note_template_class_instantiation_here : Note<
- "in instantiation of template class %0 requested here">;
+ "in instantiation of template class %q0 requested here">;
def note_template_member_class_here : Note<
- "in instantiation of member class %0 requested here">;
+ "in instantiation of member class %q0 requested here">;
def note_template_member_function_here : Note<
"in instantiation of member function %q0 requested here">;
def note_function_template_spec_here : Note<
@@ -3980,9 +4151,9 @@ def note_explicit_template_arg_substitution_here : Note<
def note_function_template_deduction_instantiation_here : Note<
"while substituting deduced template arguments into function template %0 "
"%1">;
-def note_partial_spec_deduct_instantiation_here : Note<
- "during template argument deduction for class template partial "
- "specialization %0 %1">;
+def note_deduced_template_arg_substitution_here : Note<
+ "during template argument deduction for %select{class|variable}0 template "
+ "%select{partial specialization |}1%2 %3">;
def note_prior_template_arg_substitution : Note<
"while substituting prior template arguments into %select{non-type|template}0"
" template parameter%1 %2">;
@@ -3999,6 +4170,9 @@ def err_variable_instantiates_to_function : Error<
def err_nested_name_spec_non_tag : Error<
"type %0 cannot be used prior to '::' because it has no members">;
+def err_using_pack_expansion_empty : Error<
+ "%select{|member}0 using declaration %1 instantiates to an empty pack">;
+
// C++ Explicit Instantiation
def err_explicit_instantiation_duplicate : Error<
"duplicate explicit instantiation of %0">;
@@ -4007,14 +4181,10 @@ def ext_explicit_instantiation_duplicate : ExtWarn<
InGroup<MicrosoftTemplate>;
def note_previous_explicit_instantiation : Note<
"previous explicit instantiation is here">;
-def ext_explicit_instantiation_after_specialization : Extension<
- "explicit instantiation of %0 that occurs after an explicit "
- "specialization will be ignored (C++11 extension)">,
- InGroup<CXX11>;
-def warn_cxx98_compat_explicit_instantiation_after_specialization : Warning<
- "explicit instantiation of %0 that occurs after an explicit "
- "specialization is incompatible with C++98">,
- InGroup<CXX98CompatPedantic>, DefaultIgnore;
+def warn_explicit_instantiation_after_specialization : Warning<
+ "explicit instantiation of %0 that occurs after an explicit "
+ "specialization has no effect">,
+ InGroup<DiagGroup<"instantiation-after-specialization">>;
def note_previous_template_specialization : Note<
"previous template specialization is here">;
def err_explicit_instantiation_nontemplate_type : Error<
@@ -4054,7 +4224,7 @@ def err_explicit_instantiation_member_function_not_instantiated : Error<
def err_explicit_instantiation_ambiguous : Error<
"partial ordering for explicit instantiation of %0 is ambiguous">;
def note_explicit_instantiation_candidate : Note<
- "explicit instantiation candidate function template here %0">;
+ "explicit instantiation candidate function %q0 template here %1">;
def err_explicit_instantiation_inline : Error<
"explicit instantiation cannot be 'inline'">;
def warn_explicit_instantiation_inline_0x : Warning<
@@ -4222,15 +4392,6 @@ def err_not_found_by_two_phase_lookup : Error<"call to function %0 that is neith
def note_not_found_by_two_phase_lookup : Note<"%0 should be declared prior to the "
"call site%select{| or in %2| or in an associated namespace of one of its arguments}1">;
def err_undeclared_use : Error<"use of undeclared %0">;
-def warn_partial_availability : Warning<"%0 is only available conditionally">,
- InGroup<PartialAvailability>, DefaultIgnore;
-def note_partial_availability_silence : Note<
- "explicitly redeclare %0 to silence this warning">;
-def warn_partial_message : Warning<"%0 is partial: %1">,
- InGroup<PartialAvailability>, DefaultIgnore;
-def warn_partial_fwdclass_message : Warning<
- "%0 may be partial because the receiver type is unknown">,
- InGroup<PartialAvailability>, DefaultIgnore;
def warn_deprecated : Warning<"%0 is deprecated">,
InGroup<DeprecatedDeclarations>;
def warn_property_method_deprecated :
@@ -4259,8 +4420,6 @@ def note_availability_specified_here : Note<
"%select{unavailable|deleted|deprecated|partial}1 here">;
def note_implicitly_deleted : Note<
"explicitly defaulted function was implicitly deleted here">;
-def note_inherited_deleted_here : Note<
- "deleted constructor was inherited here">;
def warn_not_enough_argument : Warning<
"not enough variable arguments in %0 declaration to fit a sentinel">,
InGroup<Sentinel>;
@@ -4274,6 +4433,10 @@ def warn_missing_prototype : Warning<
InGroup<DiagGroup<"missing-prototypes">>, DefaultIgnore;
def note_declaration_not_a_prototype : Note<
"this declaration is not a prototype; add 'void' to make it a prototype for a zero-parameter function">;
+def warn_strict_prototypes : Warning<
+ "this %select{function declaration is not|"
+ "old-style function definition is not preceded by}0 a prototype">,
+ InGroup<DiagGroup<"strict-prototypes">>, DefaultIgnore;
def warn_missing_variable_declarations : Warning<
"no previous extern declaration for non-static variable %0">,
InGroup<DiagGroup<"missing-variable-declarations">>, DefaultIgnore;
@@ -4385,6 +4548,8 @@ def err_extern_c_global_conflict : Error<
"conflicts with declaration %select{in global scope|with C language linkage}0">;
def note_extern_c_global_conflict : Note<
"declared %select{in global scope|with C language linkage}0 here">;
+def note_extern_c_begins_here : Note<
+ "extern \"C\" language linkage specification begins here">;
def warn_weak_import : Warning <
"an already-declared variable is made a weak_import declaration %0">;
def ext_static_non_static : Extension<
@@ -4418,10 +4583,15 @@ def err_redefinition_different_typedef : Error<
"%select{typedef|type alias|type alias template}0 "
"redefinition with different types%diff{ ($ vs $)|}1,2">;
def err_tag_reference_non_tag : Error<
- "elaborated type refers to %select{a non-tag type|a typedef|a type alias|a template|a type alias template|a template template argument}0">;
+ "%select{non-struct type|non-class type|non-union type|non-enum "
+ "type|typedef|type alias|template|type alias template|template "
+ "template argument}1 %0 cannot be referenced with a "
+ "%select{struct|interface|union|class|enum}2 specifier">;
def err_tag_reference_conflict : Error<
- "implicit declaration introduced by elaborated type conflicts with "
- "%select{a declaration|a typedef|a type alias|a template}0 of the same name">;
+ "implicit declaration introduced by elaborated type conflicts with a "
+ "%select{non-struct type|non-class type|non-union type|non-enum "
+ "type|typedef|type alias|template|type alias template|template "
+ "template argument}0 of the same name">;
def err_dependent_tag_decl : Error<
"%select{declaration|definition}0 of "
"%select{struct|interface|union|class|enum}1 in a dependent scope">;
@@ -4490,9 +4660,6 @@ def err_vm_func_decl : Error<
"function declaration cannot have variably modified type">;
def err_array_too_large : Error<
"array is too large (%0 elements)">;
-def warn_array_new_too_large : Warning<"array is too large (%0 elements)">,
- // FIXME PR11644: ", will throw std::bad_array_new_length at runtime"
- InGroup<BadArrayNewLength>;
// -Wpadded, -Wpacked
def warn_padded_struct_field : Warning<
@@ -4510,9 +4677,6 @@ def warn_unnecessary_packed : Warning<
"packed attribute is unnecessary for %0">, InGroup<Packed>, DefaultIgnore;
def err_typecheck_negative_array_size : Error<"array size is negative">;
-def warn_typecheck_negative_array_new_size : Warning<"array size is negative">,
- // FIXME PR11644: ", will throw std::bad_array_new_length at runtime"
- InGroup<BadArrayNewLength>;
def warn_typecheck_function_qualifiers_ignored : Warning<
"'%0' qualifier on function type %1 has no effect">,
InGroup<IgnoredQualifiers>;
@@ -4683,6 +4847,8 @@ def note_protected_by_vla_type_alias : Note<
"jump bypasses initialization of VLA type alias">;
def note_protected_by_constexpr_if : Note<
"jump enters controlled statement of constexpr if">;
+def note_protected_by_if_available : Note<
+ "jump enters controlled statement of if available">;
def note_protected_by_vla : Note<
"jump bypasses initialization of variable length array">;
def note_protected_by_objc_try : Note<
@@ -4984,6 +5150,16 @@ def err_arc_inconsistent_property_ownership : Error<
} // end "ARC and @properties" category
+def warn_block_capture_autoreleasing : Warning<
+ "block captures an autoreleasing out-parameter, which may result in "
+ "use-after-free bugs">,
+ InGroup<BlockCaptureAutoReleasing>, DefaultIgnore;
+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">;
+
def err_arc_atomic_ownership : Error<
"cannot perform atomic operation on a pointer to type %0: type has "
"non-trivial ownership">;
@@ -5232,7 +5408,7 @@ def err_typecheck_member_reference_struct_union : Error<
"member reference base type %0 is not a structure or union">;
def err_typecheck_member_reference_ivar : Error<
"%0 does not have a member named %1">;
-def error_arc_weak_ivar_access : Error<
+def err_arc_weak_ivar_access : Error<
"dereferencing a __weak pointer is not allowed due to possible "
"null value caused by race condition, assign it to strong variable first">;
def err_typecheck_member_reference_arrow : Error<
@@ -5408,7 +5584,7 @@ def err_typecheck_invalid_lvalue_addrof : Error<
"cannot take the address of an rvalue of type %0">;
def ext_typecheck_addrof_temporary : ExtWarn<
"taking the address of a temporary object of type %0">,
- InGroup<DiagGroup<"address-of-temporary">>, DefaultError;
+ InGroup<AddressOfTemporary>, DefaultError;
def err_typecheck_addrof_temporary : Error<
"taking the address of a temporary object of type %0">;
def err_typecheck_addrof_dtor : Error<
@@ -5432,6 +5608,9 @@ def warn_pointer_indirection_from_incompatible_type : Warning<
"dereference of type %1 that was reinterpret_cast from type %0 has undefined "
"behavior">,
InGroup<UndefinedReinterpretCast>, DefaultIgnore;
+def warn_taking_address_of_packed_member : Warning<
+ "taking address of packed member %0 of class or structure %q1 may result in an unaligned pointer value">,
+ InGroup<DiagGroup<"address-of-packed-member">>;
def err_objc_object_assignment : Error<
"cannot assign to class object (%0 invalid)">;
@@ -5444,6 +5623,8 @@ def ext_typecheck_ordered_comparison_of_pointer_integer : ExtWarn<
"ordered comparison between pointer and integer (%0 and %1)">;
def ext_typecheck_ordered_comparison_of_pointer_and_zero : Extension<
"ordered comparison between pointer and zero (%0 and %1) is an 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)">;
def ext_typecheck_comparison_of_fptr_to_void : Extension<
@@ -5464,9 +5645,6 @@ def err_cond_voidptr_arc : Error <
"in ARC mode">;
def err_typecheck_comparison_of_distinct_pointers : Error<
"comparison of distinct pointer types%diff{ ($ and $)|}0,1">;
-def ext_typecheck_comparison_of_distinct_pointers_nonstandard : ExtWarn<
- "comparison of distinct pointer types (%0 and %1) uses non-standard "
- "composite pointer type %2">, InGroup<CompareDistinctPointerType>;
def err_typecheck_op_on_nonoverlapping_address_space_pointers : Error<
"%select{comparison between %diff{ ($ and $)|}0,1"
"|arithmetic operation with operands of type %diff{ ($ and $)|}0,1"
@@ -5518,11 +5696,13 @@ def err_shift_rhs_only_vector : Error<
"requested shift is a vector of type %0 but the first operand is not a "
"vector (%1)">;
-def warn_logical_not_on_lhs_of_comparison : Warning<
- "logical not is only applied to the left hand side of this comparison">,
+def warn_logical_not_on_lhs_of_check : Warning<
+ "logical not is only applied to the left hand side of this "
+ "%select{comparison|bitwise operator}0">,
InGroup<LogicalNotParentheses>;
def note_logical_not_fix : Note<
- "add parentheses after the '!' to evaluate the comparison first">;
+ "add parentheses after the '!' to evaluate the "
+ "%select{comparison|bitwise operator}0 first">;
def note_logical_not_silence_with_parens : Note<
"add parentheses around left hand side expression to silence this warning">;
@@ -5630,7 +5810,7 @@ def ext_gnu_ptr_func_arith : Extension<
"arithmetic on%select{ a|}0 pointer%select{|s}0 to%select{ the|}2 function "
"type%select{|s}2 %1%select{| and %3}2 is a GNU extension">,
InGroup<PointerArith>;
-def error_readonly_message_assignment : Error<
+def err_readonly_message_assignment : Error<
"assigning to 'readonly' return result of an Objective-C message not allowed">;
def ext_integer_increment_complex : Extension<
"ISO C does not support '++'/'--' on complex integer type %0">;
@@ -5646,7 +5826,7 @@ def err_nogetter_property_compound_assignment : Error<
"a getter method is needed to perform a compound assignment on a property">;
def err_nogetter_property_incdec : Error<
"no getter method %1 for %select{increment|decrement}0 of property">;
-def error_no_subobject_property_setting : Error<
+def err_no_subobject_property_setting : Error<
"expression is not assignable">;
def err_qualified_objc_access : Error<
"%select{property|instance variable}0 access cannot be qualified with '%1'">;
@@ -5676,12 +5856,12 @@ def warn_instance_method_not_found_with_typo : Warning<
def warn_class_method_not_found_with_typo : Warning<
"class method %objcclass0 not found (return type defaults to 'id')"
"; did you mean %objcclass2?">, InGroup<MethodAccess>;
-def error_method_not_found_with_typo : Error<
+def err_method_not_found_with_typo : Error<
"%select{instance|class}1 method %0 not found "
"; did you mean %2?">;
-def error_no_super_class_message : Error<
+def err_no_super_class_message : Error<
"no @interface declaration found in class messaging of %0">;
-def error_root_class_cannot_use_super : Error<
+def err_root_class_cannot_use_super : Error<
"%0 cannot use 'super' because it is a root class">;
def err_invalid_receiver_to_message_super : Error<
"'super' is only valid in a method body">;
@@ -5696,11 +5876,11 @@ def err_bad_receiver_type : Error<"bad receiver type %0">;
def err_incomplete_receiver_type : Error<"incomplete receiver type %0">;
def err_unknown_receiver_suggest : Error<
"unknown receiver %0; did you mean %1?">;
-def error_objc_throw_expects_object : Error<
+def err_objc_throw_expects_object : Error<
"@throw requires an Objective-C object type (%0 invalid)">;
-def error_objc_synchronized_expects_object : Error<
+def err_objc_synchronized_expects_object : Error<
"@synchronized requires an Objective-C object type (%0 invalid)">;
-def error_rethrow_used_outside_catch : Error<
+def err_rethrow_used_outside_catch : Error<
"@throw (rethrow) used outside of a @catch block">;
def err_attribute_multiple_objc_gc : Error<
"multiple garbage collection attributes specified for type">;
@@ -5815,6 +5995,9 @@ def err_bad_cxx_cast_vector_to_vector_different_size : Error<
def err_bad_lvalue_to_rvalue_cast : Error<
"cannot cast from lvalue of type %1 to rvalue reference type %2; types are "
"not compatible">;
+def err_bad_rvalue_to_rvalue_cast : Error<
+ "cannot cast from rvalue of type %1 to rvalue reference type %2; types are "
+ "not compatible">;
def err_bad_static_cast_pointer_nonpointer : Error<
"cannot cast from type %1 to pointer type %2">;
def err_bad_static_cast_member_pointer_nonmp : Error<
@@ -5934,6 +6117,10 @@ def err_no_suitable_delete_member_function_found : Error<
"no suitable member %0 in %1">;
def err_ambiguous_suitable_delete_member_function_found : Error<
"multiple suitable %0 functions in %1">;
+def warn_ambiguous_suitable_delete_function_found : Warning<
+ "multiple suitable %0 functions for %1; no 'operator delete' function "
+ "will be invoked if initialization throws an exception">,
+ InGroup<DiagGroup<"ambiguous-delete">>;
def note_member_declared_here : Note<
"member %0 declared here">;
def err_decrement_bool : Error<"cannot decrement expression of type bool">;
@@ -6005,7 +6192,8 @@ def note_hidden_overloaded_virtual_declared_here : Note<
"%select{none|const|restrict|const and restrict|volatile|const and volatile|"
"volatile and restrict|const, volatile, and restrict}2 vs "
"%select{none|const|restrict|const and restrict|volatile|const and volatile|"
- "volatile and restrict|const, volatile, and restrict}3)}1">;
+ "volatile and restrict|const, volatile, and restrict}3)"
+ "|: different exception specifications}1">;
def warn_using_directive_in_header : Warning<
"using namespace directive in global context in header">,
InGroup<HeaderHygiene>, DefaultIgnore;
@@ -6093,6 +6281,8 @@ let CategoryName = "Lambda Issue" in {
def note_lambda_to_block_conv : Note<
"implicit capture of lambda object due to conversion to block pointer "
"here">;
+ def note_var_explicitly_captured_here : Note<"variable %0 is"
+ "%select{| explicitly}1 captured here">;
// C++14 lambda init-captures.
def warn_cxx11_compat_init_capture : Warning<
@@ -6247,13 +6437,14 @@ def err_typecheck_convert_incompatible : Error<
"%select{none|const|restrict|const and restrict|volatile|const and volatile|"
"volatile and restrict|const, volatile, and restrict}5 vs "
"%select{none|const|restrict|const and restrict|volatile|const and volatile|"
- "volatile and restrict|const, volatile, and restrict}6)}4">;
+ "volatile and restrict|const, volatile, and restrict}6)"
+ "|: different exception specifications}4">;
def err_typecheck_missing_return_type_incompatible : Error<
"%diff{return type $ must match previous return type $|"
"return type must match previous return type}0,1 when %select{block "
"literal|lambda expression}2 has unspecified explicit return type">;
-def not_incomplete_class_and_qualified_id : Note<
+def note_incomplete_class_and_qualified_id : Note<
"conformance of forward class %0 to protocol %1 can not be confirmed">;
def warn_incompatible_qualified_id : Warning<
"%select{%diff{assigning to $ from incompatible type $|"
@@ -6351,6 +6542,24 @@ def ext_typecheck_convert_incompatible_pointer : ExtWarn<
"; remove *|"
"; remove &}3">,
InGroup<IncompatiblePointerTypes>;
+def ext_typecheck_convert_incompatible_function_pointer : ExtWarn<
+ "incompatible function pointer types "
+ "%select{%diff{assigning to $ from $|assigning to different types}0,1"
+ "|%diff{passing $ to parameter of type $|"
+ "passing to parameter of different type}0,1"
+ "|%diff{returning $ from a function with result type $|"
+ "returning from function with different return type}0,1"
+ "|%diff{converting $ to type $|converting between types}0,1"
+ "|%diff{initializing $ with an expression of type $|"
+ "initializing with expression of different type}0,1"
+ "|%diff{sending $ to parameter of type $|"
+ "sending to parameter of different type}0,1"
+ "|%diff{casting $ to type $|casting between types}0,1}2"
+ "%select{|; dereference with *|"
+ "; take the address with &|"
+ "; remove *|"
+ "; remove &}3">,
+ InGroup<IncompatibleFunctionPointerTypes>;
def ext_typecheck_convert_discards_qualifiers : ExtWarn<
"%select{%diff{assigning to $ from $|assigning to different types}0,1"
"|%diff{passing $ to parameter of type $|"
@@ -6586,6 +6795,7 @@ def err_deleted_function_use : Error<"attempt to use a deleted function">;
def err_deleted_inherited_ctor_use : Error<
"constructor inherited by %0 from base class %1 is implicitly deleted">;
+def note_called_by : Note<"called by %0">;
def err_kern_type_not_void_return : Error<
"kernel function type %0 must have void return type">;
def err_kern_is_nonstatic_method : Error<
@@ -6599,6 +6809,9 @@ def err_global_call_not_config : Error<
def err_ref_bad_target : Error<
"reference to %select{__device__|__global__|__host__|__host__ __device__}0 "
"function %1 in %select{__device__|__global__|__host__|__host__ __device__}2 function">;
+def err_ref_bad_target_global_initializer : Error<
+ "reference to %select{__device__|__global__|__host__|__host__ __device__}0 "
+ "function %1 in global initializer">;
def warn_kern_is_method : Extension<
"kernel function %0 is a member function; this may not be accepted by nvcc">,
InGroup<CudaCompat>;
@@ -6616,14 +6829,31 @@ def err_cuda_unattributed_constexpr_cannot_overload_device : Error<
"attribute, or build with -fno-cuda-host-device-constexpr.">;
def note_cuda_conflicting_device_function_declared_here : Note<
"conflicting __device__ function declared here">;
+def err_cuda_device_exceptions : Error<
+ "cannot use '%0' in "
+ "%select{__device__|__global__|__host__|__host__ __device__}1 function">;
def err_dynamic_var_init : Error<
"dynamic initialization is not supported for "
"__device__, __constant__, and __shared__ variables.">;
def err_shared_var_init : Error<
"initialization is not supported for __shared__ variables.">;
def err_device_static_local_var : Error<
- "Within a __device__/__global__ function, "
- "only __shared__ variables may be marked \"static\"">;
+ "within a %select{__device__|__global__|__host__|__host__ __device__}0 "
+ "function, only __shared__ variables may be marked 'static'">;
+def err_cuda_vla : Error<
+ "cannot use variable-length arrays in "
+ "%select{__device__|__global__|__host__|__host__ __device__}0 functions">;
+def err_cuda_extern_shared : Error<"__shared__ variable %0 cannot be 'extern'">;
+def err_cuda_host_shared : Error<
+ "__shared__ local variables not allowed in "
+ "%select{__device__|__global__|__host__|__host__ __device__}0 functions">;
+def err_cuda_nonglobal_constant : Error<"__constant__ variables must be global">;
+def err_cuda_ovl_target : Error<
+ "%select{__device__|__global__|__host__|__host__ __device__}0 function %1 "
+ "cannot overload %select{__device__|__global__|__host__|__host__ __device__}2 function %3">;
+def note_cuda_ovl_candidate_target_mismatch : Note<
+ "candidate template ignored: target attributes do not match">;
+
def warn_non_pod_vararg_with_format_string : Warning<
"cannot pass %select{non-POD|non-trivial}0 object of type %1 to variadic "
"%select{function|block|method|constructor}2; expected type from format "
@@ -6705,9 +6935,6 @@ def err_typecheck_expect_scalar_operand : Error<
"operand of type %0 where arithmetic or pointer type is required">;
def err_typecheck_cond_incompatible_operands : Error<
"incompatible operand types%diff{ ($ and $)|}0,1">;
-def ext_typecheck_cond_incompatible_operands_nonstandard : ExtWarn<
- "incompatible operand types%diff{ ($ and $)|}0,1 use non-standard composite "
- "pointer type %2">;
def err_cast_selector_expr : Error<
"cannot type cast @selector expression">;
def ext_typecheck_cond_incompatible_pointers : ExtWarn<
@@ -6741,7 +6968,7 @@ def warn_side_effects_typeid : Warning<
"operand to 'typeid'">, InGroup<PotentiallyEvaluatedExpression>;
def warn_unused_result : Warning<
"ignoring return value of function declared with %0 attribute">,
- InGroup<DiagGroup<"unused-result">>;
+ InGroup<UnusedResult>;
def warn_unused_volatile : Warning<
"expression result unused; assign into a variable to force a volatile load">,
InGroup<DiagGroup<"unused-volatile-lvalue">>;
@@ -6759,7 +6986,12 @@ def note_inequality_comparison_to_or_assign : Note<
def err_incomplete_type_used_in_type_trait_expr : Error<
"incomplete type %0 used in type trait expression">;
-
+
+def err_require_constant_init_failed : Error<
+ "variable does not have a constant initializer">;
+def note_declared_required_constant_init_here : Note<
+ "required by 'require_constant_initializer' attribute here">;
+
def err_dimension_expr_not_constant_integer : Error<
"dimension expression does not evaluate to a constant unsigned int">;
@@ -6843,6 +7075,10 @@ let CategoryName = "Inline Assembly Issue" in {
"constraint '%0' is already present here">;
}
+ def error_inoutput_conflict_with_clobber : Error<
+ "asm-specifier for input or output variable conflicts with asm"
+ " clobber list">;
+
let CategoryName = "Semantic Issue" in {
def err_invalid_conversion_between_vectors : Error<
@@ -6911,12 +7147,11 @@ def err_in_class_initializer_literal_type : Error<
"'constexpr' specifier">;
def err_in_class_initializer_non_constant : Error<
"in-class initializer for static data member is not a constant expression">;
-def err_in_class_initializer_not_yet_parsed
- : Error<"cannot use defaulted default constructor of %0 within the class "
- "outside of member functions because %1 has an initializer">;
-def err_in_class_initializer_not_yet_parsed_outer_class
- : Error<"cannot use defaulted default constructor of %0 within "
- "%1 outside of member functions because %2 has an initializer">;
+def err_in_class_initializer_not_yet_parsed : Error<
+ "default member initializer for %1 needed within definition of enclosing "
+ "class %0 outside of member functions">;
+def note_in_class_initializer_not_yet_parsed : Note<
+ "default member initializer declared here">;
def err_in_class_initializer_cycle
: Error<"default member initializer for %0 uses itself">;
def err_exception_spec_cycle
@@ -6971,14 +7206,9 @@ def ext_ms_anonymous_record : ExtWarn<
InGroup<MicrosoftAnonTag>;
// C++ local classes
-def err_reference_to_local_var_in_enclosing_function : Error<
- "reference to local variable %0 declared in enclosing function %1">;
-def err_reference_to_local_var_in_enclosing_block : Error<
- "reference to local variable %0 declared in enclosing block literal">;
-def err_reference_to_local_var_in_enclosing_lambda : Error<
- "reference to local variable %0 declared in enclosing lambda expression">;
-def err_reference_to_local_var_in_enclosing_context : Error<
- "reference to local variable %0 declared in enclosing context">;
+def err_reference_to_local_in_enclosing_context : Error<
+ "reference to local %select{variable|binding}1 %0 declared in enclosing "
+ "%select{%3|block literal|lambda expression|context}2">;
def err_static_data_member_not_allowed_in_local_class : Error<
"static data member %0 not allowed in local class %1">;
@@ -7281,6 +7511,12 @@ def warn_format_non_standard: Warning<
def warn_format_non_standard_conversion_spec: Warning<
"using length modifier '%0' with conversion specifier '%1' is not supported by ISO C">,
InGroup<FormatNonStandard>, DefaultIgnore;
+def warn_format_invalid_annotation : Warning<
+ "using '%0' format specifier annotation outside of os_log()/os_trace()">,
+ InGroup<Format>;
+def warn_format_P_no_precision : Warning<
+ "using '%%P' format specifier without precision">,
+ InGroup<Format>;
def warn_printf_ignored_flag: Warning<
"flag '%0' is ignored when flag '%1' is present">,
InGroup<Format>;
@@ -7417,6 +7653,15 @@ def warn_cfstring_truncated : Warning<
"belong to the input codeset UTF-8">,
InGroup<DiagGroup<"CFString-literal">>;
+// os_log checking
+// TODO: separate diagnostic for os_trace()
+def err_os_log_format_not_string_constant : Error<
+ "os_log() format argument is not a string constant">;
+def err_os_log_argument_too_big : Error<
+ "os_log() argument %0 is too big (%1 bytes, max %2)">;
+def warn_os_log_format_narg : Error<
+ "os_log() '%%n' format specifier is not allowed">, DefaultError;
+
// Statements.
def err_continue_not_in_loop : Error<
"'continue' statement not in loop statement">;
@@ -7641,6 +7886,8 @@ def err_ppc_builtin_only_on_pwr7 : Error<
"this builtin is only valid on POWER7 or later CPUs">;
def err_x86_builtin_32_bit_tgt : Error<
"this builtin is only available on x86-64 targets">;
+def err_x86_builtin_invalid_rounding : Error<
+ "invalid rounding argument">;
def err_builtin_longjmp_unsupported : Error<
"__builtin_longjmp is not supported for the current target">;
@@ -7713,8 +7960,6 @@ def ext_c99_array_usage : Extension<
def err_c99_array_usage_cxx : Error<
"%select{qualifier in |static |}0array size %select{||'[*] '}0is a C99 "
"feature, not permitted in C++">;
- def err_type_requires_extension : Error<
- "use of type %0 requires %1 extension to be enabled">;
def err_type_unsupported : Error<
"%0 is not supported on this target">;
def err_nsconsumed_attribute_mismatch : Error<
@@ -7730,7 +7975,7 @@ def err_invalid_protocol_qualifiers : Error<
"invalid protocol qualifiers on non-ObjC type">;
def warn_ivar_use_hidden : Warning<
"local declaration of %0 hides instance variable">,
- InGroup<DiagGroup<"shadow-ivar">>;
+ InGroup<ShadowIvar>;
def warn_direct_initialize_call : Warning<
"explicit call to +initialize results in duplicate call to +initialize">,
InGroup<ExplicitInitializeCall>;
@@ -7738,13 +7983,11 @@ def warn_direct_super_initialize_call : Warning<
"explicit call to [super initialize] should only be in implementation "
"of +initialize">,
InGroup<ExplicitInitializeCall>;
-def error_ivar_use_in_class_method : Error<
+def err_ivar_use_in_class_method : Error<
"instance variable %0 accessed in class method">;
-def error_implicit_ivar_access : Error<
- "instance variable %0 cannot be accessed because 'self' has been redeclared">;
-def error_private_ivar_access : Error<"instance variable %0 is private">,
+def err_private_ivar_access : Error<"instance variable %0 is private">,
AccessControl;
-def error_protected_ivar_access : Error<"instance variable %0 is protected">,
+def err_protected_ivar_access : Error<"instance variable %0 is protected">,
AccessControl;
def warn_maynot_respond : Warning<"%0 may not respond to %1">;
def ext_typecheck_base_super : Warning<
@@ -7831,6 +8074,9 @@ def err_unsupported_unknown_any_call : Error<
def err_unknown_any_addrof : Error<
"the address of a declaration with unknown type "
"can only be cast to a pointer type">;
+def err_unknown_any_addrof_call : Error<
+ "address-of operator cannot be applied to a call to a function with "
+ "unknown return type">;
def err_unknown_any_var_function_type : Error<
"variable %0 with unknown type cannot be given a function type">;
def err_unknown_any_function : Error<
@@ -7853,14 +8099,15 @@ def err_static_kernel : Error<
"kernel functions cannot be declared static">;
def err_opencl_ptrptr_kernel_param : Error<
"kernel parameter cannot be declared as a pointer to a pointer">;
-def err_opencl_private_ptr_kernel_param : Error<
- "kernel parameter cannot be declared as a pointer to the __private address space">;
+def err_kernel_arg_address_space : Error<
+ "pointer arguments to kernel functions must reside in '__global', "
+ "'__constant' or '__local' address space">;
def err_opencl_function_variable : Error<
"%select{non-kernel function|function scope}0 variable cannot be declared in %1 address space">;
def err_static_function_scope : Error<
"variables in function scope cannot be declared static">;
def err_opencl_bitfields : Error<
- "bitfields are not supported in OpenCL">;
+ "bit-fields are not supported in OpenCL">;
def err_opencl_vla : Error<
"variable length arrays are not supported in OpenCL">;
def err_bad_kernel_param_type : Error<
@@ -7871,19 +8118,21 @@ def note_within_field_of_type : Note<
"within field of type %0 declared here">;
def note_illegal_field_declared_here : Note<
"field of illegal %select{type|pointer type}0 %1 declared here">;
-def err_event_t_global_var : Error<
- "the event_t type cannot be used to declare a program scope variable">;
def err_opencl_type_struct_or_union_field : Error<
"the %0 type cannot be used to declare a structure or union field">;
def err_event_t_addr_space_qual : Error<
"the event_t type can only be used with __private address space qualifier">;
def err_expected_kernel_void_return_type : Error<
"kernel must have void return type">;
+def err_sampler_initializer_not_integer : Error<
+ "sampler_t initialization requires 32-bit integer, not %0">;
+def warn_sampler_initializer_invalid_bits : Warning<
+ "sampler initializer has invalid %0 bits">, InGroup<SpirCompat>, DefaultIgnore;
def err_sampler_argument_required : Error<
"sampler_t variable required - got %0">;
def err_wrong_sampler_addressspace: Error<
"sampler type cannot be used with the __local and __global address space qualifiers">;
-def error_opencl_cast_non_zero_to_event_t : Error<
+def err_opencl_cast_non_zero_to_event_t : Error<
"cannot cast non-zero value '%0' to 'event_t'">;
def err_opencl_global_invalid_addr_space : Error<
"%select{program scope|static local|extern}0 variable must reside in %1 address space">;
@@ -7903,8 +8152,6 @@ def err_atomic_init_constant : Error<
" in the declaration statement in the program scope">;
def err_opencl_implicit_vector_conversion : Error<
"implicit conversions between vector types (%0 and %1) are not permitted">;
-def err_opencl_block_proto_variadic : Error<
- "invalid block prototype, variadic arguments are not allowed in OpenCL">;
def err_opencl_invalid_type_array : Error<
"array of %0 type is invalid in OpenCL">;
def err_opencl_ternary_with_block : Error<
@@ -7916,6 +8163,10 @@ def err_opencl_type_can_only_be_used_as_function_parameter : Error <
def warn_opencl_attr_deprecated_ignored : Warning <
"%0 attribute is deprecated and ignored in OpenCL version %1">,
InGroup<IgnoredAttributes>;
+def err_opencl_variadic_function : Error<
+ "invalid prototype, variadic arguments are not allowed in OpenCL">;
+def err_opencl_requires_extension : Error<
+ "use of %select{type |declaration}0%1 requires %2 extension to be enabled">;
// OpenCL v2.0 s6.13.6 -- Builtin Pipe Functions
def err_opencl_builtin_pipe_first_arg : Error<
@@ -7963,11 +8214,16 @@ def err_opencl_enqueue_kernel_expected_type : Error<
def err_opencl_enqueue_kernel_local_size_args : Error<
"mismatch in number of block parameters and local size arguments passed">;
def err_opencl_enqueue_kernel_invalid_local_size_type : Error<
- "local memory sizes need to be specified as uint">;
+ "illegal call to enqueue_kernel, parameter needs to be specified as integer type">;
def err_opencl_enqueue_kernel_blocks_non_local_void_args : Error<
"blocks used in device side enqueue are expected to have parameters of type 'local void*'">;
def err_opencl_enqueue_kernel_blocks_no_args : Error<
"blocks in this form of device side enqueue call are expected to have have no parameters">;
+
+// OpenCL v2.2 s2.1.2.3 - Vector Component Access
+def ext_opencl_ext_vector_type_rgba_selector: ExtWarn<
+ "vector component name '%0' is an OpenCL version 2.2 feature">,
+ InGroup<OpenCLUnsupportedRGBA>;
} // end of sema category
let CategoryName = "OpenMP Issue" in {
@@ -8248,8 +8504,10 @@ def warn_omp_section_is_char : Warning<"array section %select{lower bound|length
InGroup<CharSubscript>, DefaultIgnore;
def err_omp_section_incomplete_type : Error<
"section of pointer to incomplete type %0">;
-def err_omp_section_negative : Error<
- "section %select{lower bound|length}0 is evaluated to a negative value %1">;
+def err_omp_section_not_subset_of_array : Error<
+ "array section must be a subset of the original array">;
+def err_omp_section_length_negative : Error<
+ "section length is evaluated to a negative value %0">;
def err_omp_section_length_undefined : Error<
"section length is unspecified and cannot be inferred because subscripted value is %select{not an array|an array of unknown bound}0">;
def err_omp_wrong_linear_modifier : Error<
@@ -8330,8 +8588,8 @@ def err_omp_schedule_nonmonotonic_ordered : Error<
"'schedule' clause with 'nonmonotonic' modifier cannot be specified if an 'ordered' clause is specified">;
def err_omp_ordered_simd : Error<
"'ordered' clause with a parameter can not be specified in '#pragma omp %0' directive">;
-def err_omp_variable_in_map_and_dsa : Error<
- "%0 variable cannot be in a map clause in '#pragma omp %1' directive">;
+def err_omp_variable_in_given_clause_and_dsa : Error<
+ "%0 variable cannot be in a %1 clause in '#pragma omp %2' directive">;
def err_omp_param_or_this_in_clause : Error<
"expected reference to one of the parameters of function %0%select{| or 'this'}1">;
def err_omp_expected_uniform_param : Error<
@@ -8340,13 +8598,16 @@ def err_omp_expected_int_param : Error<
"expected a reference to an integer-typed parameter">;
def err_omp_at_least_one_motion_clause_required : Error<
"expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'">;
-def err_omp_usedeviceptr_not_a_pointer : Error<
+def err_omp_usedeviceptr_not_a_pointer : Error<
"expected pointer or reference to pointer in 'use_device_ptr' clause">;
def err_omp_argument_type_isdeviceptr : Error <
"expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'">;
def warn_omp_nesting_simd : Warning<
"OpenMP only allows an ordered construct with the simd clause nested in a simd construct">,
InGroup<SourceUsesOpenMP>;
+def err_omp_orphaned_device_directive : Error<
+ "orphaned 'omp %0' directives are prohibited"
+ "; perhaps you forget to enclose the directive into a %select{|||target |teams }1region?">;
} // end of OpenMP category
let CategoryName = "Related Result Type Issue" in {
@@ -8371,10 +8632,21 @@ def note_related_result_type_inferred : Note<
def note_related_result_type_explicit : Note<
"%select{overridden|current}0 method is explicitly declared 'instancetype'"
"%select{| and is expected to return an instance of its class type}0">;
+def err_invalid_type_for_program_scope_var : Error<
+ "the %0 type cannot be used to declare a program scope variable">;
}
let CategoryName = "Modules Issue" in {
+def err_module_interface_implementation_mismatch : Error<
+ "%select{'module'|'module partition'|'module implementation'}0 declaration "
+ "found while %select{not |not |}0building module interface">;
+def err_current_module_name_mismatch : Error<
+ "module name '%0' specified on command line does not match name of module">;
+def err_module_redefinition : Error<
+ "redefinition of module '%0'">;
+def note_prev_module_definition : Note<"previously defined here">;
+def note_prev_module_definition_from_ast_file : Note<"module loaded from '%0'">;
def err_module_private_specialization : Error<
"%select{template|partial|member}0 specialization cannot be "
"declared __module_private__">;
@@ -8401,8 +8673,6 @@ def ext_module_import_in_extern_c : ExtWarn<
"import of C++ module '%0' appears within extern \"C\" language linkage "
"specification">, DefaultError,
InGroup<DiagGroup<"module-import-in-extern-c">>;
-def note_module_import_in_extern_c : Note<
- "extern \"C\" language linkage specification begins here">;
def err_module_import_not_at_top_level_fatal : Error<
"import of module '%0' appears within %1">, DefaultFatal;
def ext_module_import_not_at_top_level_noop : ExtWarn<
@@ -8413,6 +8683,8 @@ def err_module_self_import : Error<
"import of module '%0' appears within same top-level module '%1'">;
def err_module_import_in_implementation : Error<
"@import of module '%0' in implementation of '%1'; use #import">;
+def err_export_within_export : Error<
+ "export declaration appears within another export declaration">;
def ext_equivalent_internal_linkage_decl_in_modules : ExtWarn<
"ambiguous use of internal linkage declaration %0 defined in multiple modules">,
@@ -8433,20 +8705,19 @@ def err_coroutine_unevaluated_context : Error<
"'%0' cannot be used in an unevaluated context">;
def err_coroutine_outside_function : Error<
"'%0' cannot be used outside a function">;
-def err_coroutine_ctor_dtor : Error<
- "'%1' cannot be used in a %select{constructor|destructor}0">;
-def err_coroutine_constexpr : Error<
- "'%0' cannot be used in a constexpr function">;
-def err_coroutine_varargs : Error<
- "'%0' cannot be used in a varargs function">;
+def err_coroutine_invalid_func_context : Error<
+ "'%1' cannot be used in %select{a constructor|a destructor"
+ "|a copy assignment operator|a move assignment operator|the 'main' function"
+ "|a constexpr function|a function with a deduced return type"
+ "|a varargs function}0">;
def ext_coroutine_without_co_await_co_yield : ExtWarn<
"'co_return' used in a function "
"that uses neither 'co_await' nor 'co_yield'">,
InGroup<DiagGroup<"coreturn-without-coawait">>;
def err_implied_std_coroutine_traits_not_found : Error<
- "you need to include <coroutine> before defining a coroutine">;
+ "you need to include <experimental/coroutine> before defining a coroutine">;
def err_malformed_std_coroutine_traits : Error<
- "'std::coroutine_traits' must be a class template">;
+ "'std::experimental::coroutine_traits' must be a class template">;
def err_implied_std_coroutine_traits_promise_type_not_found : Error<
"this function cannot be a coroutine: %q0 has no member named 'promise_type'">;
def err_implied_std_coroutine_traits_promise_type_not_class : Error<
@@ -8454,6 +8725,13 @@ def err_implied_std_coroutine_traits_promise_type_not_class : Error<
def err_coroutine_traits_missing_specialization : Error<
"this function cannot be a coroutine: missing definition of "
"specialization %q0">;
+def err_implied_std_current_exception_not_found : Error<
+ "you need to include <exception> before defining a coroutine that implicitly "
+ "uses 'set_exception'">;
+def err_malformed_std_current_exception : Error<
+ "'std::current_exception' must be a function">;
+def err_coroutine_promise_return_ill_formed : Error<
+ "%0 declares both 'return_value' and 'return_void'">;
}
let CategoryName = "Documentation Issue" in {
@@ -8510,6 +8788,19 @@ def warn_nullability_missing : Warning<
"%select{pointer|block pointer|member pointer}0 is missing a nullability "
"type specifier (_Nonnull, _Nullable, or _Null_unspecified)">,
InGroup<NullabilityCompleteness>;
+def warn_nullability_missing_array : Warning<
+ "array parameter is missing a nullability type specifier (_Nonnull, "
+ "_Nullable, or _Null_unspecified)">,
+ InGroup<NullabilityCompletenessOnArrays>;
+def note_nullability_fix_it : Note<
+ "insert '%select{_Nonnull|_Nullable|_Null_unspecified}0' if the "
+ "%select{pointer|block pointer|member pointer|array parameter}1 "
+ "%select{should never be null|may be null|should not declare nullability}0">;
+
+def warn_nullability_inferred_on_nested_type : Warning<
+ "inferring '_Nonnull' for pointer type within %select{array|reference}0 is "
+ "deprecated">,
+ InGroup<NullabilityInferredOnNestedType>;
def err_objc_type_arg_explicit_nullability : Error<
"type argument %0 cannot explicitly specify nullability">;
@@ -8603,4 +8894,8 @@ def warn_block_literal_qualifiers_on_omitted_return_type : Warning<
"'%0' qualifier on omitted return type %1 has no effect">,
InGroup<IgnoredQualifiers>;
+def ext_warn_gnu_final : ExtWarn<
+ "__final is a GNU extension, consider using C++11 final">,
+ InGroup<GccCompat>;
+
} // end of sema component.
diff --git a/include/clang/Basic/DiagnosticSerializationKinds.td b/include/clang/Basic/DiagnosticSerializationKinds.td
index 16c77435558f..066a1f5fa68f 100644
--- a/include/clang/Basic/DiagnosticSerializationKinds.td
+++ b/include/clang/Basic/DiagnosticSerializationKinds.td
@@ -21,6 +21,12 @@ def err_fe_pch_malformed_block : Error<
def err_fe_pch_file_modified : Error<
"file '%0' has been modified since the precompiled header '%1' was built">,
DefaultFatal;
+def err_fe_module_file_modified : Error<
+ "file '%0' has been modified since the module file '%1' was built">,
+ DefaultFatal;
+def err_fe_ast_file_modified : Error<
+ "file '%0' has been modified since the AST file '%1' was built">,
+ DefaultFatal;
def err_fe_pch_file_overridden : Error<
"file '%0' from the precompiled header has been overridden">;
def note_pch_required_by : Note<"'%0' required by '%1'">;
diff --git a/include/clang/Basic/FileManager.h b/include/clang/Basic/FileManager.h
index b6a9ca702842..b817dd20c301 100644
--- a/include/clang/Basic/FileManager.h
+++ b/include/clang/Basic/FileManager.h
@@ -16,7 +16,6 @@
#define LLVM_CLANG_BASIC_FILEMANAGER_H
#include "clang/Basic/FileSystemOptions.h"
-#include "clang/Basic/LLVM.h"
#include "clang/Basic/VirtualFileSystem.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
@@ -24,25 +23,32 @@
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Allocator.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/FileSystem.h"
+#include <ctime>
#include <memory>
#include <map>
+#include <string>
namespace llvm {
+
class MemoryBuffer;
-}
+
+} // end namespace llvm
namespace clang {
-class FileManager;
+
class FileSystemStatCache;
/// \brief Cached information about one directory (either on disk or in
/// the virtual file system).
class DirectoryEntry {
- const char *Name; // Name of the directory.
friend class FileManager;
+
+ StringRef Name; // Name of the directory.
+
public:
- DirectoryEntry() : Name(nullptr) {}
- const char *getName() const { return Name; }
+ StringRef getName() const { return Name; }
};
/// \brief Cached information about one file (either on disk
@@ -51,7 +57,9 @@ public:
/// If the 'File' member is valid, then this FileEntry has an open file
/// descriptor for the file.
class FileEntry {
- const char *Name; // Name of the file.
+ friend class FileManager;
+
+ StringRef Name; // Name of the file.
std::string RealPathName; // Real path to the file; could be empty.
off_t Size; // File size in bytes.
time_t ModTime; // Modification time of file.
@@ -64,25 +72,16 @@ class FileEntry {
/// \brief The open file, if it is owned by the \p FileEntry.
mutable std::unique_ptr<vfs::File> File;
- friend class FileManager;
-
- void operator=(const FileEntry &) = delete;
public:
FileEntry()
: UniqueID(0, 0), IsNamedPipe(false), InPCH(false), IsValid(false)
{}
- // FIXME: this is here to allow putting FileEntry in std::map. Once we have
- // emplace, we shouldn't need a copy constructor anymore.
- /// Intentionally does not copy fields that are not set in an uninitialized
- /// \c FileEntry.
- FileEntry(const FileEntry &FE) : UniqueID(FE.UniqueID),
- IsNamedPipe(FE.IsNamedPipe), InPCH(FE.InPCH), IsValid(FE.IsValid) {
- assert(!isValid() && "Cannot copy an initialized FileEntry");
- }
+ FileEntry(const FileEntry &) = delete;
+ FileEntry &operator=(const FileEntry &) = delete;
- const char *getName() const { return Name; }
+ StringRef getName() const { return Name; }
StringRef tryGetRealPathName() const { return RealPathName; }
bool isValid() const { return IsValid; }
off_t getSize() const { return Size; }
@@ -165,7 +164,7 @@ class FileManager : public RefCountedBase<FileManager> {
// Caching.
std::unique_ptr<FileSystemStatCache> StatCache;
- bool getStatValue(const char *Path, FileData &Data, bool isFile,
+ bool getStatValue(StringRef Path, FileData &Data, bool isFile,
std::unique_ptr<vfs::File> *F);
/// Add all ancestors of the given path (pointing to either a file
@@ -285,6 +284,6 @@ public:
void PrintStats() const;
};
-} // end namespace clang
+} // end namespace clang
-#endif
+#endif // LLVM_CLANG_BASIC_FILEMANAGER_H
diff --git a/include/clang/Basic/FileSystemStatCache.h b/include/clang/Basic/FileSystemStatCache.h
index cad91893489b..75f986b59bdd 100644
--- a/include/clang/Basic/FileSystemStatCache.h
+++ b/include/clang/Basic/FileSystemStatCache.h
@@ -68,7 +68,7 @@ public:
/// success for directories (not files). On a successful file lookup, the
/// implementation can optionally fill in \p F with a valid \p File object and
/// the client guarantees that it will close it.
- static bool get(const char *Path, FileData &Data, bool isFile,
+ static bool get(StringRef Path, FileData &Data, bool isFile,
std::unique_ptr<vfs::File> *F, FileSystemStatCache *Cache,
vfs::FileSystem &FS);
@@ -92,11 +92,11 @@ protected:
// FIXME: The pointer here is a non-owning/optional reference to the
// unique_ptr. Optional<unique_ptr<vfs::File>&> might be nicer, but
// Optional needs some work to support references so this isn't possible yet.
- virtual LookupResult getStat(const char *Path, FileData &Data, bool isFile,
+ virtual LookupResult getStat(StringRef Path, FileData &Data, bool isFile,
std::unique_ptr<vfs::File> *F,
vfs::FileSystem &FS) = 0;
- LookupResult statChained(const char *Path, FileData &Data, bool isFile,
+ LookupResult statChained(StringRef Path, FileData &Data, bool isFile,
std::unique_ptr<vfs::File> *F, vfs::FileSystem &FS) {
if (FileSystemStatCache *Next = getNextStatCache())
return Next->getStat(Path, Data, isFile, F, FS);
@@ -121,7 +121,7 @@ public:
iterator begin() const { return StatCalls.begin(); }
iterator end() const { return StatCalls.end(); }
- LookupResult getStat(const char *Path, FileData &Data, bool isFile,
+ LookupResult getStat(StringRef Path, FileData &Data, bool isFile,
std::unique_ptr<vfs::File> *F,
vfs::FileSystem &FS) override;
};
diff --git a/include/clang/Basic/IdentifierTable.h b/include/clang/Basic/IdentifierTable.h
index fffb50493bfe..3001d0b1b0c7 100644
--- a/include/clang/Basic/IdentifierTable.h
+++ b/include/clang/Basic/IdentifierTable.h
@@ -18,16 +18,26 @@
#include "clang/Basic/LLVM.h"
#include "clang/Basic/TokenKinds.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Allocator.h"
#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+#include <new>
#include <string>
+#include <utility>
namespace llvm {
+
template <typename T> struct DenseMapInfo;
-}
+
+} // end namespace llvm
namespace clang {
+
class LangOptions;
class IdentifierInfo;
class IdentifierTable;
@@ -38,13 +48,14 @@ namespace clang {
/// \brief A simple pair of identifier info and location.
typedef std::pair<IdentifierInfo*, SourceLocation> IdentifierLocPair;
-
/// One of these records is kept for each identifier that
/// is lexed. This contains information about whether the token was \#define'd,
/// is a language keyword, or if it is a front-end token of some sort (e.g. a
/// variable or function name). The preprocessor keeps this information in a
/// set, and all tok::identifier tokens have a pointer to one of these.
class IdentifierInfo {
+ friend class IdentifierTable;
+
unsigned TokenID : 9; // Front-end token ID or tok::identifier.
// Objective-C keyword ('protocol' in '@protocol') or builtin (__builtin_inf).
// First NUM_OBJC_KEYWORDS values are for Objective-C, the remaining values
@@ -77,21 +88,18 @@ class IdentifierInfo {
void *FETokenInfo; // Managed by the language front-end.
llvm::StringMapEntry<IdentifierInfo*> *Entry;
- IdentifierInfo(const IdentifierInfo&) = delete;
- void operator=(const IdentifierInfo&) = delete;
-
- friend class IdentifierTable;
-
public:
IdentifierInfo();
-
+ IdentifierInfo(const IdentifierInfo &) = delete;
+ IdentifierInfo &operator=(const IdentifierInfo &) = delete;
/// \brief 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>
bool isStr(const char (&Str)[StrLen]) const {
- return getLength() == StrLen-1 && !memcmp(getNameStart(), Str, StrLen-1);
+ return getLength() == StrLen-1 &&
+ memcmp(getNameStart(), Str, StrLen-1) == 0;
}
/// \brief Return the beginning of the actual null-terminated string for this
@@ -137,7 +145,7 @@ public:
HasMacro = Val;
if (Val) {
- NeedsHandleIdentifier = 1;
+ NeedsHandleIdentifier = true;
HadMacro = true;
} else {
RecomputeNeedsHandleIdentifier();
@@ -205,8 +213,7 @@ public:
/// \brief Return a value indicating whether this is a builtin function.
///
- /// 0 is not-built-in. 1 is builtin-for-some-nonprimary-target.
- /// 2+ are specific builtin functions.
+ /// 0 is not-built-in. 1+ are specific builtin functions.
unsigned getBuiltinID() const {
if (ObjCOrBuiltinID >= tok::NUM_OBJC_KEYWORDS)
return ObjCOrBuiltinID - tok::NUM_OBJC_KEYWORDS;
@@ -229,7 +236,7 @@ public:
void setIsExtensionToken(bool Val) {
IsExtension = Val;
if (Val)
- NeedsHandleIdentifier = 1;
+ NeedsHandleIdentifier = true;
else
RecomputeNeedsHandleIdentifier();
}
@@ -243,7 +250,7 @@ public:
void setIsFutureCompatKeyword(bool Val) {
IsFutureCompatKeyword = Val;
if (Val)
- NeedsHandleIdentifier = 1;
+ NeedsHandleIdentifier = true;
else
RecomputeNeedsHandleIdentifier();
}
@@ -253,7 +260,7 @@ public:
void setIsPoisoned(bool Value = true) {
IsPoisoned = Value;
if (Value)
- NeedsHandleIdentifier = 1;
+ NeedsHandleIdentifier = true;
else
RecomputeNeedsHandleIdentifier();
}
@@ -266,7 +273,7 @@ public:
void setIsCPlusPlusOperatorKeyword(bool Val = true) {
IsCPPOperatorKeyword = Val;
if (Val)
- NeedsHandleIdentifier = 1;
+ NeedsHandleIdentifier = true;
else
RecomputeNeedsHandleIdentifier();
}
@@ -371,6 +378,7 @@ private:
class PoisonIdentifierRAIIObject {
IdentifierInfo *const II;
const bool OldValue;
+
public:
PoisonIdentifierRAIIObject(IdentifierInfo *II, bool NewValue)
: II(II), OldValue(II ? II->isPoisoned() : false) {
@@ -395,14 +403,13 @@ public:
/// operation. Subclasses of this iterator type will provide the
/// actual functionality.
class IdentifierIterator {
-private:
- IdentifierIterator(const IdentifierIterator &) = delete;
- void operator=(const IdentifierIterator &) = delete;
-
protected:
- IdentifierIterator() { }
+ IdentifierIterator() = default;
public:
+ IdentifierIterator(const IdentifierIterator &) = delete;
+ IdentifierIterator &operator=(const IdentifierIterator &) = delete;
+
virtual ~IdentifierIterator();
/// \brief Retrieve the next string in the identifier table and
@@ -537,7 +544,7 @@ public:
iterator begin() const { return HashTable.begin(); }
iterator end() const { return HashTable.end(); }
- unsigned size() const { return HashTable.size(); }
+ unsigned size() const { return HashTable.size(); }
/// \brief Print some statistics to stderr that indicate how well the
/// hashing is doing.
@@ -654,6 +661,7 @@ class Selector {
return reinterpret_cast<IdentifierInfo *>(InfoPtr & ~ArgFlags);
return nullptr;
}
+
MultiKeywordSelector *getMultiKeywordSelector() const {
return reinterpret_cast<MultiKeywordSelector *>(InfoPtr & ~ArgFlags);
}
@@ -682,6 +690,7 @@ public:
bool operator!=(Selector RHS) const {
return InfoPtr != RHS.InfoPtr;
}
+
void *getAsOpaquePtr() const {
return reinterpret_cast<void*>(InfoPtr);
}
@@ -693,12 +702,13 @@ public:
bool isKeywordSelector() const {
return getIdentifierInfoFlag() != ZeroArg;
}
+
bool isUnarySelector() const {
return getIdentifierInfoFlag() == ZeroArg;
}
+
unsigned getNumArgs() const;
-
/// \brief Retrieve the identifier at a given position in the selector.
///
/// Note that the identifier pointer returned may be NULL. Clients that only
@@ -743,6 +753,7 @@ public:
static Selector getEmptyMarker() {
return Selector(uintptr_t(-1));
}
+
static Selector getTombstoneMarker() {
return Selector(uintptr_t(-2));
}
@@ -754,10 +765,11 @@ public:
/// multi-keyword caching.
class SelectorTable {
void *Impl; // Actually a SelectorTableImpl
- SelectorTable(const SelectorTable &) = delete;
- void operator=(const SelectorTable &) = delete;
+
public:
SelectorTable();
+ SelectorTable(const SelectorTable &) = delete;
+ SelectorTable &operator=(const SelectorTable &) = delete;
~SelectorTable();
/// \brief Can create any sort of selector.
@@ -826,6 +838,7 @@ public:
} // end namespace clang
namespace llvm {
+
/// Define DenseMapInfo so that Selectors can be used as keys in DenseMap and
/// DenseSets.
template <>
@@ -833,6 +846,7 @@ struct DenseMapInfo<clang::Selector> {
static inline clang::Selector getEmptyKey() {
return clang::Selector::getEmptyMarker();
}
+
static inline clang::Selector getTombstoneKey() {
return clang::Selector::getTombstoneMarker();
}
@@ -855,9 +869,11 @@ public:
static inline const void *getAsVoidPointer(clang::Selector P) {
return P.getAsOpaquePtr();
}
+
static inline clang::Selector getFromVoidPointer(const void *P) {
return clang::Selector(reinterpret_cast<uintptr_t>(P));
}
+
enum { NumLowBitsAvailable = 0 };
};
@@ -869,9 +885,11 @@ public:
static inline void *getAsVoidPointer(clang::IdentifierInfo* P) {
return P;
}
+
static inline clang::IdentifierInfo *getFromVoidPointer(void *P) {
return static_cast<clang::IdentifierInfo*>(P);
}
+
enum { NumLowBitsAvailable = 1 };
};
@@ -881,11 +899,14 @@ public:
static inline const void *getAsVoidPointer(const clang::IdentifierInfo* P) {
return P;
}
+
static inline const clang::IdentifierInfo *getFromVoidPointer(const void *P) {
return static_cast<const clang::IdentifierInfo*>(P);
}
+
enum { NumLowBitsAvailable = 1 };
};
-} // end namespace llvm
-#endif
+} // end namespace llvm
+
+#endif // LLVM_CLANG_BASIC_IDENTIFIERTABLE_H
diff --git a/include/clang/Basic/LLVM.h b/include/clang/Basic/LLVM.h
index 0e6ff9259a15..f32ab5e11bd4 100644
--- a/include/clang/Basic/LLVM.h
+++ b/include/clang/Basic/LLVM.h
@@ -30,6 +30,7 @@ namespace llvm {
class Twine;
template<typename T> class ArrayRef;
template<typename T> class MutableArrayRef;
+ template<typename T> class OwningArrayRef;
template<unsigned InternalLen> class SmallString;
template<typename T, unsigned N> class SmallVector;
template<typename T> class SmallVectorImpl;
@@ -42,7 +43,6 @@ namespace llvm {
template <typename T> class IntrusiveRefCntPtr;
template <typename T> struct IntrusiveRefCntPtrInfo;
template <class Derived> class RefCountedBase;
- class RefCountedBaseVPTR;
class raw_ostream;
class raw_pwrite_stream;
@@ -65,6 +65,7 @@ namespace clang {
using llvm::Twine;
using llvm::ArrayRef;
using llvm::MutableArrayRef;
+ using llvm::OwningArrayRef;
using llvm::SmallString;
using llvm::SmallVector;
using llvm::SmallVectorImpl;
@@ -74,7 +75,6 @@ namespace clang {
using llvm::IntrusiveRefCntPtr;
using llvm::IntrusiveRefCntPtrInfo;
using llvm::RefCountedBase;
- using llvm::RefCountedBaseVPTR;
using llvm::raw_ostream;
using llvm::raw_pwrite_stream;
diff --git a/include/clang/Basic/LangOptions.def b/include/clang/Basic/LangOptions.def
index 03561961dd21..47db50c52b74 100644
--- a/include/clang/Basic/LangOptions.def
+++ b/include/clang/Basic/LangOptions.def
@@ -133,7 +133,8 @@ LANGOPT(Freestanding, 1, 0, "freestanding implementation")
LANGOPT(NoBuiltin , 1, 0, "disable builtin functions")
LANGOPT(NoMathBuiltin , 1, 0, "disable math builtin functions")
LANGOPT(GNUAsm , 1, 1, "GNU-style inline assembly")
-LANGOPT(Coroutines , 1, 0, "C++ coroutines")
+LANGOPT(CoroutinesTS , 1, 0, "C++ coroutines TS")
+LANGOPT(RelaxedTemplateTemplateArgs, 1, 0, "C++17 relaxed matching of template template arguments")
BENIGN_LANGOPT(ThreadsafeStatics , 1, 1, "thread-safe static initializers")
LANGOPT(POSIXThreads , 1, 0, "POSIX thread support")
@@ -142,7 +143,9 @@ BENIGN_LANGOPT(EmitAllDecls , 1, 0, "emitting all declarations")
LANGOPT(MathErrno , 1, 1, "errno in math functions")
BENIGN_LANGOPT(HeinousExtensions , 1, 0, "extensions that we really don't like and may be ripped out at any time")
LANGOPT(Modules , 1, 0, "modules extension to C")
-BENIGN_LANGOPT(CompilingModule, 1, 0, "compiling a module interface")
+COMPATIBLE_LANGOPT(ModulesTS , 1, 0, "C++ Modules TS")
+BENIGN_ENUM_LANGOPT(CompilingModule, CompilingModuleKind, 2, CMK_None,
+ "compiling a module interface")
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")
@@ -193,7 +196,9 @@ LANGOPT(CUDAHostDeviceConstexpr, 1, 1, "treating unattributed constexpr function
LANGOPT(CUDADeviceFlushDenormalsToZero, 1, 0, "flushing denormals to zero")
LANGOPT(CUDADeviceApproxTranscendentals, 1, 0, "using approximate transcendental functions")
-LANGOPT(SizedDeallocation , 1, 0, "enable sized deallocation functions")
+LANGOPT(SizedDeallocation , 1, 0, "sized deallocation")
+LANGOPT(AlignedAllocation , 1, 0, "aligned allocation")
+LANGOPT(NewAlignOverride , 32, 0, "maximum alignment guaranteed by '::operator new(size_t)'")
LANGOPT(ConceptsTS , 1, 0, "enable C++ Extensions for Concepts")
BENIGN_LANGOPT(ElideConstructors , 1, 1, "C++ copy constructor elision")
BENIGN_LANGOPT(DumpRecordLayouts , 1, 0, "dumping the layout of IRgen'd records")
@@ -234,7 +239,7 @@ ENUM_LANGOPT(SignedOverflowBehavior, SignedOverflowBehaviorTy, 2, SOB_Undefined,
BENIGN_LANGOPT(ArrowDepth, 32, 256,
"maximum number of operator->s to follow")
-BENIGN_LANGOPT(InstantiationDepth, 32, 256,
+BENIGN_LANGOPT(InstantiationDepth, 32, 1024,
"maximum template instantiation depth")
BENIGN_LANGOPT(ConstexprCallDepth, 32, 512,
"maximum constexpr call depth")
diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h
index 6ec499f1c74a..10635b11225e 100644
--- a/include/clang/Basic/LangOptions.h
+++ b/include/clang/Basic/LangOptions.h
@@ -58,6 +58,12 @@ public:
SOB_Trapping // -ftrapv
};
+ 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.
+ };
+
enum PragmaMSPointersToMembersKind {
PPTMK_BestCase,
PPTMK_FullGeneralitySingleInheritance,
@@ -126,6 +132,10 @@ public:
/// host code generation.
std::string OMPHostIRFile;
+ /// \brief Indicates whether the front-end is explicitly told that the
+ /// input is a header file (i.e. -x c-header).
+ bool IsHeaderFile;
+
LangOptions();
// Define accessors/mutators for language options of enumeration type.
@@ -134,7 +144,12 @@ public:
Type get##Name() const { return static_cast<Type>(Name); } \
void set##Name(Type Value) { Name = static_cast<unsigned>(Value); }
#include "clang/Basic/LangOptions.def"
-
+
+ /// Are we compiling a module interface (.cppm or module map)?
+ bool isCompilingModule() const {
+ return getCompilingModule() != CMK_None;
+ }
+
bool isSignedOverflowDefined() const {
return getSignedOverflowBehavior() == SOB_Defined;
}
@@ -154,7 +169,7 @@ public:
/// \brief 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;
+ bool isNoBuiltinFunc(StringRef Name) const;
};
/// \brief Floating point control options
diff --git a/include/clang/Basic/Linkage.h b/include/clang/Basic/Linkage.h
index 8b15c8ed6ee8..e96fb568c009 100644
--- a/include/clang/Basic/Linkage.h
+++ b/include/clang/Basic/Linkage.h
@@ -69,6 +69,10 @@ enum GVALinkage {
GVA_StrongODR
};
+inline bool isDiscardableGVALinkage(GVALinkage L) {
+ return L <= GVA_DiscardableODR;
+}
+
inline bool isExternallyVisible(Linkage L) {
return L == ExternalLinkage || L == VisibleNoLinkage;
}
diff --git a/include/clang/Basic/Module.h b/include/clang/Basic/Module.h
index 1702fb1114d7..31c5c7ec9ca8 100644
--- a/include/clang/Basic/Module.h
+++ b/include/clang/Basic/Module.h
@@ -201,6 +201,10 @@ public:
/// built.
unsigned ConfigMacrosExhaustive : 1;
+ /// \brief 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
/// particular module.
enum NameVisibilityKind {
diff --git a/include/clang/Basic/ObjCRuntime.h b/include/clang/Basic/ObjCRuntime.h
index 6975b6c9bb9e..78fc89988245 100644
--- a/include/clang/Basic/ObjCRuntime.h
+++ b/include/clang/Basic/ObjCRuntime.h
@@ -312,6 +312,7 @@ public:
bool hasARCUnsafeClaimAutoreleasedReturnValue() const {
switch (getKind()) {
case MacOSX:
+ case FragileMacOSX:
return getVersion() >= VersionTuple(10, 11);
case iOS:
return getVersion() >= VersionTuple(9);
diff --git a/include/clang/Basic/OpenCLExtensions.def b/include/clang/Basic/OpenCLExtensions.def
index c5776d3bab43..360fec4281ac 100644
--- a/include/clang/Basic/OpenCLExtensions.def
+++ b/include/clang/Basic/OpenCLExtensions.def
@@ -67,6 +67,7 @@ OPENCLEXT_INTERNAL(cl_khr_spir, 120, ~0U)
// OpenCL 2.0.
OPENCLEXT_INTERNAL(cl_khr_egl_event, 200, ~0U)
OPENCLEXT_INTERNAL(cl_khr_egl_image, 200, ~0U)
+OPENCLEXT_INTERNAL(cl_khr_mipmap_image, 200, ~0U)
OPENCLEXT_INTERNAL(cl_khr_srgb_image_writes, 200, ~0U)
OPENCLEXT_INTERNAL(cl_khr_subgroups, 200, ~0U)
OPENCLEXT_INTERNAL(cl_khr_terminate_context, 200, ~0U)
@@ -74,6 +75,10 @@ OPENCLEXT_INTERNAL(cl_khr_terminate_context, 200, ~0U)
// Clang Extensions.
OPENCLEXT_INTERNAL(cl_clang_storage_class_specifiers, 100, ~0U)
+// AMD OpenCL extensions
+OPENCLEXT_INTERNAL(cl_amd_media_ops, 100, ~0U)
+OPENCLEXT_INTERNAL(cl_amd_media_ops2, 100, ~0U)
+
#undef OPENCLEXT_INTERNAL
#ifdef OPENCLEXT
diff --git a/include/clang/Basic/OpenCLImageTypes.def b/include/clang/Basic/OpenCLImageTypes.def
index 9b929929e2ba..1ca12f683beb 100644
--- a/include/clang/Basic/OpenCLImageTypes.def
+++ b/include/clang/Basic/OpenCLImageTypes.def
@@ -7,76 +7,82 @@
//
//===----------------------------------------------------------------------===//
// This file extends builtin types database with OpenCL image singleton types.
-// Custom code should define one of those two macros:
-// GENERIC_IMAGE_TYPE(Type, Id) - a generic image with its Id without an
+// Custom code should define one of those three macros:
+// GENERIC_IMAGE_TYPE(Type, Id) - a generic image with its Id without an
// access type
// IMAGE_TYPE(Type, Id, SingletonId, AccessType, CGSuffix) - an image type
-// with given ID, singleton ID access type and a codegen suffix
+// with given ID, singleton ID access type and a codegen suffix
+// GENERIC_IMAGE_TYPE_EXT(Type, Id, Ext) - a generic image with its Id and
+// required extension without an access type
#ifdef GENERIC_IMAGE_TYPE
-#define IMAGE_READ_TYPE(Type, Id) GENERIC_IMAGE_TYPE(Type, Id)
-#define IMAGE_WRITE_TYPE(Type, Id)
-#define IMAGE_READ_WRITE_TYPE(Type, Id)
+#define IMAGE_READ_TYPE(Type, Id, Ext) GENERIC_IMAGE_TYPE(Type, Id)
+#define IMAGE_WRITE_TYPE(Type, Id, Ext)
+#define IMAGE_READ_WRITE_TYPE(Type, Id, Ext)
-#else
+#elif defined(GENERIC_IMAGE_TYPE_EXT)
+#define IMAGE_READ_TYPE(Type, Id, Ext) GENERIC_IMAGE_TYPE_EXT(Type, Id##ROTy, Ext)
+#define IMAGE_WRITE_TYPE(Type, Id, Ext) GENERIC_IMAGE_TYPE_EXT(Type, Id##WOTy, Ext)
+#define IMAGE_READ_WRITE_TYPE(Type, Id, Ext) GENERIC_IMAGE_TYPE_EXT(Type, Id##RWTy, Ext)
+#else
#ifndef IMAGE_READ_TYPE
-#define IMAGE_READ_TYPE(Type, Id) \
+#define IMAGE_READ_TYPE(Type, Id, Ext) \
IMAGE_TYPE(Type, Id##RO, Id##ROTy, read_only, ro)
#endif
#ifndef IMAGE_WRITE_TYPE
-#define IMAGE_WRITE_TYPE(Type, Id) \
+#define IMAGE_WRITE_TYPE(Type, Id, Ext) \
IMAGE_TYPE(Type, Id##WO, Id##WOTy, write_only, wo)
#endif
#ifndef IMAGE_READ_WRITE_TYPE
-#define IMAGE_READ_WRITE_TYPE(Type, Id) \
+#define IMAGE_READ_WRITE_TYPE(Type, Id, Ext) \
IMAGE_TYPE(Type, Id##RW, Id##RWTy, read_write, rw)
#endif
#endif
-IMAGE_READ_TYPE(image1d, OCLImage1d)
-IMAGE_READ_TYPE(image1d_array, OCLImage1dArray)
-IMAGE_READ_TYPE(image1d_buffer, OCLImage1dBuffer)
-IMAGE_READ_TYPE(image2d, OCLImage2d)
-IMAGE_READ_TYPE(image2d_array, OCLImage2dArray)
-IMAGE_READ_TYPE(image2d_depth, OCLImage2dDepth)
-IMAGE_READ_TYPE(image2d_array_depth, OCLImage2dArrayDepth)
-IMAGE_READ_TYPE(image2d_msaa, OCLImage2dMSAA)
-IMAGE_READ_TYPE(image2d_array_msaa, OCLImage2dArrayMSAA)
-IMAGE_READ_TYPE(image2d_msaa_depth, OCLImage2dMSAADepth)
-IMAGE_READ_TYPE(image2d_array_msaa_depth, OCLImage2dArrayMSAADepth)
-IMAGE_READ_TYPE(image3d, OCLImage3d)
+IMAGE_READ_TYPE(image1d, OCLImage1d, "")
+IMAGE_READ_TYPE(image1d_array, OCLImage1dArray, "")
+IMAGE_READ_TYPE(image1d_buffer, OCLImage1dBuffer, "")
+IMAGE_READ_TYPE(image2d, OCLImage2d, "")
+IMAGE_READ_TYPE(image2d_array, OCLImage2dArray, "")
+IMAGE_READ_TYPE(image2d_depth, OCLImage2dDepth, "")
+IMAGE_READ_TYPE(image2d_array_depth, OCLImage2dArrayDepth, "")
+IMAGE_READ_TYPE(image2d_msaa, OCLImage2dMSAA, "cl_khr_gl_msaa_sharing")
+IMAGE_READ_TYPE(image2d_array_msaa, OCLImage2dArrayMSAA, "cl_khr_gl_msaa_sharing")
+IMAGE_READ_TYPE(image2d_msaa_depth, OCLImage2dMSAADepth, "cl_khr_gl_msaa_sharing")
+IMAGE_READ_TYPE(image2d_array_msaa_depth, OCLImage2dArrayMSAADepth, "cl_khr_gl_msaa_sharing")
+IMAGE_READ_TYPE(image3d, OCLImage3d, "")
-IMAGE_WRITE_TYPE(image1d, OCLImage1d)
-IMAGE_WRITE_TYPE(image1d_array, OCLImage1dArray)
-IMAGE_WRITE_TYPE(image1d_buffer, OCLImage1dBuffer)
-IMAGE_WRITE_TYPE(image2d, OCLImage2d)
-IMAGE_WRITE_TYPE(image2d_array, OCLImage2dArray)
-IMAGE_WRITE_TYPE(image2d_depth, OCLImage2dDepth)
-IMAGE_WRITE_TYPE(image2d_array_depth, OCLImage2dArrayDepth)
-IMAGE_WRITE_TYPE(image2d_msaa, OCLImage2dMSAA)
-IMAGE_WRITE_TYPE(image2d_array_msaa, OCLImage2dArrayMSAA)
-IMAGE_WRITE_TYPE(image2d_msaa_depth, OCLImage2dMSAADepth)
-IMAGE_WRITE_TYPE(image2d_array_msaa_depth, OCLImage2dArrayMSAADepth)
-IMAGE_WRITE_TYPE(image3d, OCLImage3d)
+IMAGE_WRITE_TYPE(image1d, OCLImage1d, "")
+IMAGE_WRITE_TYPE(image1d_array, OCLImage1dArray, "")
+IMAGE_WRITE_TYPE(image1d_buffer, OCLImage1dBuffer, "")
+IMAGE_WRITE_TYPE(image2d, OCLImage2d, "")
+IMAGE_WRITE_TYPE(image2d_array, OCLImage2dArray, "")
+IMAGE_WRITE_TYPE(image2d_depth, OCLImage2dDepth, "")
+IMAGE_WRITE_TYPE(image2d_array_depth, OCLImage2dArrayDepth, "")
+IMAGE_WRITE_TYPE(image2d_msaa, OCLImage2dMSAA, "cl_khr_gl_msaa_sharing")
+IMAGE_WRITE_TYPE(image2d_array_msaa, OCLImage2dArrayMSAA, "cl_khr_gl_msaa_sharing")
+IMAGE_WRITE_TYPE(image2d_msaa_depth, OCLImage2dMSAADepth, "cl_khr_gl_msaa_sharing")
+IMAGE_WRITE_TYPE(image2d_array_msaa_depth, OCLImage2dArrayMSAADepth, "cl_khr_gl_msaa_sharing")
+IMAGE_WRITE_TYPE(image3d, OCLImage3d, "")
-IMAGE_READ_WRITE_TYPE(image1d, OCLImage1d)
-IMAGE_READ_WRITE_TYPE(image1d_array, OCLImage1dArray)
-IMAGE_READ_WRITE_TYPE(image1d_buffer, OCLImage1dBuffer)
-IMAGE_READ_WRITE_TYPE(image2d, OCLImage2d)
-IMAGE_READ_WRITE_TYPE(image2d_array, OCLImage2dArray)
-IMAGE_READ_WRITE_TYPE(image2d_depth, OCLImage2dDepth)
-IMAGE_READ_WRITE_TYPE(image2d_array_depth, OCLImage2dArrayDepth)
-IMAGE_READ_WRITE_TYPE(image2d_msaa, OCLImage2dMSAA)
-IMAGE_READ_WRITE_TYPE(image2d_array_msaa, OCLImage2dArrayMSAA)
-IMAGE_READ_WRITE_TYPE(image2d_msaa_depth, OCLImage2dMSAADepth)
-IMAGE_READ_WRITE_TYPE(image2d_array_msaa_depth, OCLImage2dArrayMSAADepth)
-IMAGE_READ_WRITE_TYPE(image3d, OCLImage3d)
+IMAGE_READ_WRITE_TYPE(image1d, OCLImage1d, "")
+IMAGE_READ_WRITE_TYPE(image1d_array, OCLImage1dArray, "")
+IMAGE_READ_WRITE_TYPE(image1d_buffer, OCLImage1dBuffer, "")
+IMAGE_READ_WRITE_TYPE(image2d, OCLImage2d, "")
+IMAGE_READ_WRITE_TYPE(image2d_array, OCLImage2dArray, "")
+IMAGE_READ_WRITE_TYPE(image2d_depth, OCLImage2dDepth, "")
+IMAGE_READ_WRITE_TYPE(image2d_array_depth, OCLImage2dArrayDepth, "")
+IMAGE_READ_WRITE_TYPE(image2d_msaa, OCLImage2dMSAA, "cl_khr_gl_msaa_sharing")
+IMAGE_READ_WRITE_TYPE(image2d_array_msaa, OCLImage2dArrayMSAA, "cl_khr_gl_msaa_sharing")
+IMAGE_READ_WRITE_TYPE(image2d_msaa_depth, OCLImage2dMSAADepth, "cl_khr_gl_msaa_sharing")
+IMAGE_READ_WRITE_TYPE(image2d_array_msaa_depth, OCLImage2dArrayMSAADepth, "cl_khr_gl_msaa_sharing")
+IMAGE_READ_WRITE_TYPE(image3d, OCLImage3d, "")
#undef IMAGE_TYPE
#undef GENERIC_IMAGE_TYPE
#undef IMAGE_READ_TYPE
#undef IMAGE_WRITE_TYPE
-#undef IMAGE_READ_WRITE_TYPE \ No newline at end of file
+#undef IMAGE_READ_WRITE_TYPE
diff --git a/include/clang/Basic/OpenCLOptions.h b/include/clang/Basic/OpenCLOptions.h
index 4aaa3d74ccbf..cc850f0b0b24 100644
--- a/include/clang/Basic/OpenCLOptions.h
+++ b/include/clang/Basic/OpenCLOptions.h
@@ -15,52 +15,122 @@
#ifndef LLVM_CLANG_BASIC_OPENCLOPTIONS_H
#define LLVM_CLANG_BASIC_OPENCLOPTIONS_H
-#include <string>
-#include <vector>
+#include "llvm/ADT/StringMap.h"
namespace clang {
/// \brief OpenCL supported extensions and optional core features
class OpenCLOptions {
+ struct Info {
+ bool Supported; // Is this option supported
+ bool Enabled; // Is this option enabled
+ unsigned Avail; // Option starts to be available in this OpenCL version
+ unsigned Core; // Option becomes (optional) core feature in this OpenCL
+ // version
+ Info(bool S = false, bool E = false, unsigned A = 100, unsigned C = ~0U)
+ :Supported(S), Enabled(E), Avail(A), Core(C){}
+ };
+ llvm::StringMap<Info> OptMap;
public:
-#define OPENCLEXT(nm) unsigned nm : 1;
-#include "clang/Basic/OpenCLExtensions.def"
+ bool isKnown(llvm::StringRef Ext) const {
+ return OptMap.find(Ext) != OptMap.end();
+ }
- OpenCLOptions() {
-#define OPENCLEXT(nm) nm = 0;
-#include "clang/Basic/OpenCLExtensions.def"
+ bool isEnabled(llvm::StringRef Ext) const {
+ return OptMap.find(Ext)->second.Enabled;
}
- // Enable all options.
- void setAll() {
-#define OPENCLEXT(nm) nm = 1;
-#include "clang/Basic/OpenCLExtensions.def"
+ // Is supported as either an extension or an (optional) core feature for
+ // OpenCL version \p CLVer.
+ bool isSupported(llvm::StringRef Ext, unsigned CLVer) const {
+ auto I = OptMap.find(Ext)->getValue();
+ return I.Supported && I.Avail <= CLVer;
}
- // Is supported with OpenCL version \p OCLVer.
-#define OPENCLEXT_INTERNAL(Ext, Avail, ...) \
- bool is_##Ext##_supported(unsigned OCLVer) const { \
- return Ext && OCLVer >= Avail; \
+ // Is supported (optional) OpenCL core features for OpenCL version \p CLVer.
+ // For supported extension, return false.
+ bool isSupportedCore(llvm::StringRef Ext, unsigned CLVer) const {
+ auto I = OptMap.find(Ext)->getValue();
+ return I.Supported && I.Avail <= CLVer &&
+ I.Core != ~0U && CLVer >= I.Core;
}
-#include "clang/Basic/OpenCLExtensions.def"
+ // Is supported OpenCL extension for OpenCL version \p CLVer.
+ // For supported (optional) core feature, return false.
+ bool isSupportedExtension(llvm::StringRef Ext, unsigned CLVer) const {
+ auto I = OptMap.find(Ext)->getValue();
+ return I.Supported && I.Avail <= CLVer &&
+ (I.Core == ~0U || CLVer < I.Core);
+ }
- // Is supported OpenCL extension with OpenCL version \p OCLVer.
- // For supported optional core feature, return false.
-#define OPENCLEXT_INTERNAL(Ext, Avail, Core) \
- bool is_##Ext##_supported_extension(unsigned CLVer) const { \
- return is_##Ext##_supported(CLVer) && (Core == ~0U || CLVer < Core); \
+ void enable(llvm::StringRef Ext, bool V = true) {
+ OptMap[Ext].Enabled = V;
}
-#include "clang/Basic/OpenCLExtensions.def"
- // Is supported OpenCL core features with OpenCL version \p OCLVer.
- // For supported extension, return false.
-#define OPENCLEXT_INTERNAL(Ext, Avail, Core) \
- bool is_##Ext##_supported_core(unsigned CLVer) const { \
- return is_##Ext##_supported(CLVer) && Core != ~0U && CLVer >= Core; \
+ /// \brief 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 '-'
+ void support(llvm::StringRef Ext, bool V = true) {
+ assert(!Ext.empty() && "Extension is empty.");
+
+ switch (Ext[0]) {
+ case '+':
+ V = true;
+ Ext = Ext.drop_front();
+ break;
+ case '-':
+ V = false;
+ Ext = Ext.drop_front();
+ break;
+ }
+
+ if (Ext.equals("all")) {
+ supportAll(V);
+ return;
+ }
+ OptMap[Ext].Supported = V;
}
+
+ OpenCLOptions(){
+#define OPENCLEXT_INTERNAL(Ext, AvailVer, CoreVer) \
+ OptMap[#Ext].Avail = AvailVer; \
+ OptMap[#Ext].Core = CoreVer;
#include "clang/Basic/OpenCLExtensions.def"
+ }
+
+ void addSupport(const OpenCLOptions &Opts) {
+ for (auto &I:Opts.OptMap)
+ if (I.second.Supported)
+ OptMap[I.getKey()].Supported = true;
+ }
+
+ void copy(const OpenCLOptions &Opts) {
+ OptMap = Opts.OptMap;
+ }
+
+ // Turn on or off support of all options.
+ void supportAll(bool On = true) {
+ for (llvm::StringMap<Info>::iterator I = OptMap.begin(),
+ E = OptMap.end(); I != E; ++I)
+ I->second.Supported = On;
+ }
+
+ void disableAll() {
+ for (llvm::StringMap<Info>::iterator I = OptMap.begin(),
+ E = OptMap.end(); I != E; ++I)
+ I->second.Enabled = false;
+ }
+
+ void enableSupportedCore(unsigned CLVer) {
+ for (llvm::StringMap<Info>::iterator I = OptMap.begin(),
+ E = OptMap.end(); I != E; ++I)
+ if (isSupportedCore(I->getKey(), CLVer))
+ I->second.Enabled = true;
+ }
+ friend class ASTWriter;
+ friend class ASTReader;
};
} // end namespace clang
diff --git a/include/clang/Basic/OpenMPKinds.def b/include/clang/Basic/OpenMPKinds.def
index 5189779809b8..808e0d2bb0c7 100644
--- a/include/clang/Basic/OpenMPKinds.def
+++ b/include/clang/Basic/OpenMPKinds.def
@@ -138,6 +138,30 @@
#ifndef OPENMP_TARGET_PARALLEL_FOR_SIMD_CLAUSE
#define OPENMP_TARGET_PARALLEL_FOR_SIMD_CLAUSE(Name)
#endif
+#ifndef OPENMP_TARGET_SIMD_CLAUSE
+#define OPENMP_TARGET_SIMD_CLAUSE(Name)
+#endif
+#ifndef OPENMP_TEAMS_DISTRIBUTE_CLAUSE
+#define OPENMP_TEAMS_DISTRIBUTE_CLAUSE(Name)
+#endif
+#ifndef OPENMP_TEAMS_DISTRIBUTE_SIMD_CLAUSE
+#define OPENMP_TEAMS_DISTRIBUTE_SIMD_CLAUSE(Name)
+#endif
+#ifndef OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE
+#define OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE(Name)
+#endif
+#ifndef OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE
+#define OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(Name)
+#endif
+#ifndef OPENMP_TARGET_TEAMS_CLAUSE
+#define OPENMP_TARGET_TEAMS_CLAUSE(Name)
+#endif
+#ifndef OPENMP_TARGET_TEAMS_DISTRIBUTE_CLAUSE
+#define OPENMP_TARGET_TEAMS_DISTRIBUTE_CLAUSE(Name)
+#endif
+#ifndef OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE
+#define OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(Name)
+#endif
// OpenMP directives.
OPENMP_DIRECTIVE(threadprivate)
@@ -182,6 +206,14 @@ OPENMP_DIRECTIVE_EXT(distribute_parallel_for, "distribute parallel for")
OPENMP_DIRECTIVE_EXT(distribute_parallel_for_simd, "distribute parallel for simd")
OPENMP_DIRECTIVE_EXT(distribute_simd, "distribute simd")
OPENMP_DIRECTIVE_EXT(target_parallel_for_simd, "target parallel for simd")
+OPENMP_DIRECTIVE_EXT(target_simd, "target simd")
+OPENMP_DIRECTIVE_EXT(teams_distribute, "teams distribute")
+OPENMP_DIRECTIVE_EXT(teams_distribute_simd, "teams distribute simd")
+OPENMP_DIRECTIVE_EXT(teams_distribute_parallel_for_simd, "teams distribute parallel for simd")
+OPENMP_DIRECTIVE_EXT(teams_distribute_parallel_for, "teams distribute parallel for")
+OPENMP_DIRECTIVE_EXT(target_teams, "target teams")
+OPENMP_DIRECTIVE_EXT(target_teams_distribute, "target teams distribute")
+OPENMP_DIRECTIVE_EXT(target_teams_distribute_parallel_for, "target teams distribute parallel for")
// OpenMP clauses.
OPENMP_CLAUSE(if, OMPIfClause)
@@ -431,7 +463,6 @@ OPENMP_TARGET_EXIT_DATA_CLAUSE(nowait)
OPENMP_TARGET_EXIT_DATA_CLAUSE(depend)
// Clauses allowed for OpenMP directive 'target parallel'.
-// TODO: add target clauses 'is_device_ptr'
OPENMP_TARGET_PARALLEL_CLAUSE(if)
OPENMP_TARGET_PARALLEL_CLAUSE(device)
OPENMP_TARGET_PARALLEL_CLAUSE(map)
@@ -445,6 +476,7 @@ OPENMP_TARGET_PARALLEL_CLAUSE(default)
OPENMP_TARGET_PARALLEL_CLAUSE(proc_bind)
OPENMP_TARGET_PARALLEL_CLAUSE(shared)
OPENMP_TARGET_PARALLEL_CLAUSE(reduction)
+OPENMP_TARGET_PARALLEL_CLAUSE(is_device_ptr)
// Clauses allowed for OpenMP directive 'target parallel for'.
// TODO: add target clauses 'is_device_ptr'
@@ -620,6 +652,147 @@ OPENMP_TARGET_PARALLEL_FOR_SIMD_CLAUSE(safelen)
OPENMP_TARGET_PARALLEL_FOR_SIMD_CLAUSE(simdlen)
OPENMP_TARGET_PARALLEL_FOR_SIMD_CLAUSE(aligned)
+// Clauses allowed for OpenMP directive 'target simd'.
+OPENMP_TARGET_SIMD_CLAUSE(if)
+OPENMP_TARGET_SIMD_CLAUSE(device)
+OPENMP_TARGET_SIMD_CLAUSE(map)
+OPENMP_TARGET_SIMD_CLAUSE(private)
+OPENMP_TARGET_SIMD_CLAUSE(nowait)
+OPENMP_TARGET_SIMD_CLAUSE(depend)
+OPENMP_TARGET_SIMD_CLAUSE(defaultmap)
+OPENMP_TARGET_SIMD_CLAUSE(firstprivate)
+OPENMP_TARGET_SIMD_CLAUSE(is_device_ptr)
+OPENMP_TARGET_SIMD_CLAUSE(lastprivate)
+OPENMP_TARGET_SIMD_CLAUSE(linear)
+OPENMP_TARGET_SIMD_CLAUSE(aligned)
+OPENMP_TARGET_SIMD_CLAUSE(safelen)
+OPENMP_TARGET_SIMD_CLAUSE(simdlen)
+OPENMP_TARGET_SIMD_CLAUSE(collapse)
+OPENMP_TARGET_SIMD_CLAUSE(reduction)
+
+// Clauses allowed for OpenMP directive 'teams distribute'.
+OPENMP_TEAMS_DISTRIBUTE_CLAUSE(default)
+OPENMP_TEAMS_DISTRIBUTE_CLAUSE(private)
+OPENMP_TEAMS_DISTRIBUTE_CLAUSE(firstprivate)
+OPENMP_TEAMS_DISTRIBUTE_CLAUSE(shared)
+OPENMP_TEAMS_DISTRIBUTE_CLAUSE(reduction)
+OPENMP_TEAMS_DISTRIBUTE_CLAUSE(num_teams)
+OPENMP_TEAMS_DISTRIBUTE_CLAUSE(thread_limit)
+OPENMP_TEAMS_DISTRIBUTE_CLAUSE(lastprivate)
+OPENMP_TEAMS_DISTRIBUTE_CLAUSE(collapse)
+OPENMP_TEAMS_DISTRIBUTE_CLAUSE(dist_schedule)
+
+// Clauses allowed for OpenMP directive 'teams distribute simd'
+OPENMP_TEAMS_DISTRIBUTE_SIMD_CLAUSE(default)
+OPENMP_TEAMS_DISTRIBUTE_SIMD_CLAUSE(private)
+OPENMP_TEAMS_DISTRIBUTE_SIMD_CLAUSE(firstprivate)
+OPENMP_TEAMS_DISTRIBUTE_SIMD_CLAUSE(shared)
+OPENMP_TEAMS_DISTRIBUTE_SIMD_CLAUSE(reduction)
+OPENMP_TEAMS_DISTRIBUTE_SIMD_CLAUSE(num_teams)
+OPENMP_TEAMS_DISTRIBUTE_SIMD_CLAUSE(thread_limit)
+OPENMP_TEAMS_DISTRIBUTE_SIMD_CLAUSE(lastprivate)
+OPENMP_TEAMS_DISTRIBUTE_SIMD_CLAUSE(collapse)
+OPENMP_TEAMS_DISTRIBUTE_SIMD_CLAUSE(dist_schedule)
+OPENMP_TEAMS_DISTRIBUTE_SIMD_CLAUSE(linear)
+OPENMP_TEAMS_DISTRIBUTE_SIMD_CLAUSE(aligned)
+OPENMP_TEAMS_DISTRIBUTE_SIMD_CLAUSE(safelen)
+OPENMP_TEAMS_DISTRIBUTE_SIMD_CLAUSE(simdlen)
+
+// Clauses allowed for OpenMP directive 'teams distribute parallel for simd'
+OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE(firstprivate)
+OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE(lastprivate)
+OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE(collapse)
+OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE(dist_schedule)
+OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE(if)
+OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE(num_threads)
+OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE(default)
+OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE(proc_bind)
+OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE(private)
+OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE(shared)
+OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE(reduction)
+OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE(schedule)
+OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE(linear)
+OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE(aligned)
+OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE(safelen)
+OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE(simdlen)
+OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE(num_teams)
+OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE(thread_limit)
+
+// Clauses allowed for OpenMP directive 'teams distribute parallel for'
+OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(firstprivate)
+OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(lastprivate)
+OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(collapse)
+OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(dist_schedule)
+OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(if)
+OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(num_threads)
+OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(default)
+OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(proc_bind)
+OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(private)
+OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(shared)
+OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(reduction)
+OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(schedule)
+OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(linear)
+OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(num_teams)
+OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(thread_limit)
+
+// Clauses allowed for OpenMP directive 'target teams'.
+OPENMP_TARGET_TEAMS_CLAUSE(if)
+OPENMP_TARGET_TEAMS_CLAUSE(device)
+OPENMP_TARGET_TEAMS_CLAUSE(map)
+OPENMP_TARGET_TEAMS_CLAUSE(private)
+OPENMP_TARGET_TEAMS_CLAUSE(nowait)
+OPENMP_TARGET_TEAMS_CLAUSE(depend)
+OPENMP_TARGET_TEAMS_CLAUSE(defaultmap)
+OPENMP_TARGET_TEAMS_CLAUSE(firstprivate)
+OPENMP_TARGET_TEAMS_CLAUSE(is_device_ptr)
+OPENMP_TARGET_TEAMS_CLAUSE(default)
+OPENMP_TARGET_TEAMS_CLAUSE(shared)
+OPENMP_TARGET_TEAMS_CLAUSE(reduction)
+OPENMP_TARGET_TEAMS_CLAUSE(num_teams)
+OPENMP_TARGET_TEAMS_CLAUSE(thread_limit)
+
+// Clauses allowed for OpenMP directive 'target teams distribute'.
+OPENMP_TARGET_TEAMS_DISTRIBUTE_CLAUSE(if)
+OPENMP_TARGET_TEAMS_DISTRIBUTE_CLAUSE(device)
+OPENMP_TARGET_TEAMS_DISTRIBUTE_CLAUSE(map)
+OPENMP_TARGET_TEAMS_DISTRIBUTE_CLAUSE(private)
+OPENMP_TARGET_TEAMS_DISTRIBUTE_CLAUSE(nowait)
+OPENMP_TARGET_TEAMS_DISTRIBUTE_CLAUSE(depend)
+OPENMP_TARGET_TEAMS_DISTRIBUTE_CLAUSE(defaultmap)
+OPENMP_TARGET_TEAMS_DISTRIBUTE_CLAUSE(firstprivate)
+OPENMP_TARGET_TEAMS_DISTRIBUTE_CLAUSE(is_device_ptr)
+OPENMP_TARGET_TEAMS_DISTRIBUTE_CLAUSE(default)
+OPENMP_TARGET_TEAMS_DISTRIBUTE_CLAUSE(shared)
+OPENMP_TARGET_TEAMS_DISTRIBUTE_CLAUSE(reduction)
+OPENMP_TARGET_TEAMS_DISTRIBUTE_CLAUSE(num_teams)
+OPENMP_TARGET_TEAMS_DISTRIBUTE_CLAUSE(thread_limit)
+OPENMP_TARGET_TEAMS_DISTRIBUTE_CLAUSE(lastprivate)
+OPENMP_TARGET_TEAMS_DISTRIBUTE_CLAUSE(collapse)
+OPENMP_TARGET_TEAMS_DISTRIBUTE_CLAUSE(dist_schedule)
+
+// Clauses allowed for OpenMP directive 'target teams distribute parallel for'.
+OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(if)
+OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(device)
+OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(map)
+OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(private)
+OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(nowait)
+OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(depend)
+OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(defaultmap)
+OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(firstprivate)
+OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(is_device_ptr)
+OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(default)
+OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(shared)
+OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(reduction)
+OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(num_teams)
+OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(thread_limit)
+OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(lastprivate)
+OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(collapse)
+OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(dist_schedule)
+OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(num_threads)
+OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(proc_bind)
+OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(schedule)
+OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(linear)
+
#undef OPENMP_TASKLOOP_SIMD_CLAUSE
#undef OPENMP_TASKLOOP_CLAUSE
#undef OPENMP_LINEAR_KIND
@@ -662,3 +835,11 @@ OPENMP_TARGET_PARALLEL_FOR_SIMD_CLAUSE(aligned)
#undef OPENMP_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE
#undef OPENMP_DISTRIBUTE_SIMD_CLAUSE
#undef OPENMP_TARGET_PARALLEL_FOR_SIMD_CLAUSE
+#undef OPENMP_TARGET_SIMD_CLAUSE
+#undef OPENMP_TEAMS_DISTRIBUTE_CLAUSE
+#undef OPENMP_TEAMS_DISTRIBUTE_SIMD_CLAUSE
+#undef OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE
+#undef OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE
+#undef OPENMP_TARGET_TEAMS_CLAUSE
+#undef OPENMP_TARGET_TEAMS_DISTRIBUTE_CLAUSE
+#undef OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE
diff --git a/include/clang/Basic/OpenMPKinds.h b/include/clang/Basic/OpenMPKinds.h
index 0a8e890b7c44..60b9fcef9219 100644
--- a/include/clang/Basic/OpenMPKinds.h
+++ b/include/clang/Basic/OpenMPKinds.h
@@ -179,10 +179,18 @@ bool isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind);
/// otherwise - false.
bool isOpenMPTargetDataManagementDirective(OpenMPDirectiveKind DKind);
-/// \brief Checks if the specified directive is a teams-kind directive.
+/// Checks if the specified composite/combined directive constitutes a teams
+/// directive in the outermost nest. For example
+/// 'omp teams distribute' or 'omp teams distribute parallel for'.
/// \param DKind Specified directive.
-/// \return true - the directive is a teams-like directive like 'omp teams',
-/// otherwise - false.
+/// \return true - the directive has teams on the outermost nest, otherwise -
+/// false.
+bool isOpenMPNestingTeamsDirective(OpenMPDirectiveKind DKind);
+
+/// Checks if the specified directive is a teams-kind directive. For example,
+/// 'omp teams distribute' or 'omp target teams'.
+/// \param DKind Specified directive.
+/// \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.
@@ -198,6 +206,14 @@ bool isOpenMPSimdDirective(OpenMPDirectiveKind DKind);
/// otherwise - false.
bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind);
+/// Checks if the specified composite/combined directive constitutes a
+/// distribute directive in the outermost nest. For example,
+/// 'omp distribute parallel for' or 'omp distribute'.
+/// \param DKind Specified directive.
+/// \return true - the directive has distribute on the outermost nest.
+/// otherwise - false.
+bool isOpenMPNestingDistributeDirective(OpenMPDirectiveKind DKind);
+
/// \brief Checks if the specified clause is one of private clauses like
/// 'private', 'firstprivate', 'reduction' etc..
/// \param Kind Clause kind.
diff --git a/include/clang/Basic/PlistSupport.h b/include/clang/Basic/PlistSupport.h
index 84dd29138a80..61de82450cf7 100644
--- a/include/clang/Basic/PlistSupport.h
+++ b/include/clang/Basic/PlistSupport.h
@@ -10,7 +10,6 @@
#ifndef LLVM_CLANG_BASIC_PLISTSUPPORT_H
#define LLVM_CLANG_BASIC_PLISTSUPPORT_H
-#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/Support/raw_ostream.h"
diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h
index 23ad73894fd3..c8fe2ab90c29 100644
--- a/include/clang/Basic/SourceManager.h
+++ b/include/clang/Basic/SourceManager.h
@@ -44,30 +44,34 @@
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/PointerIntPair.h"
-#include "llvm/ADT/PointerUnion.h"
-#include "llvm/Support/AlignOf.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Allocator.h"
-#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/MemoryBuffer.h"
+#include <algorithm>
#include <cassert>
+#include <cstddef>
+#include <cstdint>
#include <map>
#include <memory>
+#include <string>
+#include <utility>
#include <vector>
namespace clang {
+class ASTReader;
+class ASTWriter;
class DiagnosticsEngine;
-class SourceManager;
-class FileManager;
-class FileEntry;
class LineTableInfo;
-class ASTWriter;
-class ASTReader;
+class SourceManager;
/// \brief Public enums and private classes that are part of the
/// SourceManager implementation.
///
namespace SrcMgr {
+
/// \brief Indicates whether a file or directory holds normal user code,
/// system code, or system code which is implicitly 'extern "C"' in C++ mode.
///
@@ -146,8 +150,6 @@ namespace SrcMgr {
SourceLineCache(nullptr), NumLines(0), BufferOverridden(false),
IsSystemFile(false), IsTransient(false) {}
- ~ContentCache();
-
/// The copy ctor does not allow copies where source object has either
/// a non-NULL Buffer or SourceLineCache. Ownership of allocated memory
/// is not transferred, so this is a logical error.
@@ -164,6 +166,10 @@ namespace SrcMgr {
NumLines = RHS.NumLines;
}
+ ContentCache &operator=(const ContentCache& RHS) = delete;
+
+ ~ContentCache();
+
/// \brief Returns the memory buffer for the associated content.
///
/// \param Diag Object through which diagnostics will be emitted if the
@@ -219,15 +225,11 @@ namespace SrcMgr {
bool shouldFreeBuffer() const {
return (Buffer.getInt() & DoNotFreeFlag) == 0;
}
-
- private:
- // Disable assignments.
- ContentCache &operator=(const ContentCache& RHS) = delete;
};
// Assert that the \c ContentCache objects will always be 8-byte aligned so
// that we can pack 3 bits of integer into pointers to such objects.
- static_assert(llvm::AlignOf<ContentCache>::Alignment >= 8,
+ static_assert(alignof(ContentCache) >= 8,
"ContentCache must be 8-byte aligned.");
/// \brief Information about a FileID, basically just the logical file
@@ -259,6 +261,7 @@ namespace SrcMgr {
friend class clang::SourceManager;
friend class clang::ASTWriter;
friend class clang::ASTReader;
+
public:
/// \brief Return a FileInfo object.
static FileInfo get(SourceLocation IL, const ContentCache *Con,
@@ -276,6 +279,7 @@ namespace SrcMgr {
SourceLocation getIncludeLoc() const {
return SourceLocation::getFromRawEncoding(IncludeLoc);
}
+
const ContentCache* getContentCache() const {
return reinterpret_cast<const ContentCache*>(Data & ~uintptr_t(7));
}
@@ -316,9 +320,11 @@ namespace SrcMgr {
SourceLocation getSpellingLoc() const {
return SourceLocation::getFromRawEncoding(SpellingLoc);
}
+
SourceLocation getExpansionLocStart() const {
return SourceLocation::getFromRawEncoding(ExpansionLocStart);
}
+
SourceLocation getExpansionLocEnd() const {
SourceLocation EndLoc =
SourceLocation::getFromRawEncoding(ExpansionLocEnd);
@@ -399,6 +405,7 @@ namespace SrcMgr {
FileInfo File;
ExpansionInfo Expansion;
};
+
public:
unsigned getOffset() const { return Offset; }
@@ -433,6 +440,7 @@ namespace SrcMgr {
return E;
}
};
+
} // end SrcMgr namespace.
/// \brief External source of source location entries.
@@ -453,7 +461,6 @@ public:
virtual std::pair<SourceLocation, StringRef> getModuleImportLoc(int ID) = 0;
};
-
/// \brief Holds the cache used by isBeforeInTranslationUnit.
///
/// The cache structure is complex enough to be worth breaking out of
@@ -479,6 +486,7 @@ class InBeforeInTUCacheEntry {
/// if LQueryFID is a parent of RQueryFID (or vice versa) then these can be a
/// random token in the parent.
unsigned LCommonOffset, RCommonOffset;
+
public:
/// \brief Return true if the currently cached values match up with
/// the specified LHS/RHS query.
@@ -526,13 +534,12 @@ public:
LCommonOffset = lCommonOffset;
RCommonOffset = rCommonOffset;
}
-
};
/// \brief The stack used when building modules on demand, which is used
/// to provide a link between the source managers of the different compiler
/// instances.
-typedef ArrayRef<std::pair<std::string, FullSourceLoc> > ModuleBuildStack;
+typedef ArrayRef<std::pair<std::string, FullSourceLoc>> ModuleBuildStack;
/// \brief This class handles loading and caching of source files into memory.
///
@@ -667,7 +674,7 @@ class SourceManager : public RefCountedBase<SourceManager> {
///
/// Used to cache results from and speed-up \c getDecomposedIncludedLoc
/// function.
- mutable llvm::DenseMap<FileID, std::pair<FileID, unsigned> > IncludedLocMap;
+ mutable llvm::DenseMap<FileID, std::pair<FileID, unsigned>> IncludedLocMap;
/// The key value into the IsBeforeInTUCache table.
typedef std::pair<FileID, FileID> IsBeforeInTUCacheKey;
@@ -694,7 +701,8 @@ class SourceManager : public RefCountedBase<SourceManager> {
/// source location.
typedef std::map<unsigned, SourceLocation> MacroArgsMap;
- mutable llvm::DenseMap<FileID, MacroArgsMap *> MacroArgsCacheMap;
+ mutable llvm::DenseMap<FileID, std::unique_ptr<MacroArgsMap>>
+ MacroArgsCacheMap;
/// \brief The stack of modules being built, which is used to detect
/// cycles in the module dependency graph as modules are being built, as
@@ -705,12 +713,11 @@ class SourceManager : public RefCountedBase<SourceManager> {
/// we can add a cc1-level option to do so.
SmallVector<std::pair<std::string, FullSourceLoc>, 2> StoredModuleBuildStack;
- // SourceManager doesn't support copy construction.
- explicit SourceManager(const SourceManager&) = delete;
- void operator=(const SourceManager&) = delete;
public:
SourceManager(DiagnosticsEngine &Diag, FileManager &FileMgr,
bool UserFilesAreVolatile = false);
+ explicit SourceManager(const SourceManager &) = delete;
+ SourceManager &operator=(const SourceManager &) = delete;
~SourceManager();
void clearIDTables();
@@ -1292,7 +1299,7 @@ public:
///
/// Note that this name does not respect \#line directives. Use
/// getPresumedLoc for normal clients.
- const char *getBufferName(SourceLocation Loc, bool *Invalid = nullptr) const;
+ StringRef getBufferName(SourceLocation Loc, bool *Invalid = nullptr) const;
/// \brief Return the file characteristic of the specified source
/// location, indicating whether this is a normal file, a system
@@ -1358,7 +1365,7 @@ public:
}
/// \brief Returns whether \p Loc is expanded from a macro in a system header.
- bool isInSystemMacro(SourceLocation loc) {
+ bool isInSystemMacro(SourceLocation loc) const {
return loc.isMacroID() && isInSystemHeader(getSpellingLoc(loc));
}
@@ -1673,7 +1680,7 @@ private:
std::pair<FileID, unsigned>
getDecomposedSpellingLocSlowCase(const SrcMgr::SLocEntry *E,
unsigned Offset) const;
- void computeMacroArgsCache(MacroArgsMap *&MacroArgsCache, FileID FID) const;
+ void computeMacroArgsCache(MacroArgsMap &MacroArgsCache, FileID FID) const;
void associateFileChunkWithMacroArgExp(MacroArgsMap &MacroArgsCache,
FileID FID,
SourceLocation SpellLoc,
@@ -1713,7 +1720,6 @@ public:
}
};
-} // end namespace clang
-
+} // end namespace clang
-#endif
+#endif // LLVM_CLANG_BASIC_SOURCEMANAGER_H
diff --git a/include/clang/Basic/SourceManagerInternals.h b/include/clang/Basic/SourceManagerInternals.h
index 27dea9f84b5a..e65c97b0031d 100644
--- a/include/clang/Basic/SourceManagerInternals.h
+++ b/include/clang/Basic/SourceManagerInternals.h
@@ -95,9 +95,9 @@ public:
}
unsigned getLineTableFilenameID(StringRef Str);
- const char *getFilename(unsigned ID) const {
+ StringRef getFilename(unsigned ID) const {
assert(ID < FilenamesByID.size() && "Invalid FilenameID");
- return FilenamesByID[ID]->getKeyData();
+ return FilenamesByID[ID]->getKey();
}
unsigned getNumFilenames() const { return FilenamesByID.size(); }
diff --git a/include/clang/Basic/Specifiers.h b/include/clang/Basic/Specifiers.h
index fffd4b1cd20b..369a36f3dca6 100644
--- a/include/clang/Basic/Specifiers.h
+++ b/include/clang/Basic/Specifiers.h
@@ -237,6 +237,7 @@ namespace clang {
CC_X86Pascal, // __attribute__((pascal))
CC_X86_64Win64, // __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))
@@ -254,6 +255,7 @@ namespace clang {
case CC_X86StdCall:
case CC_X86FastCall:
case CC_X86ThisCall:
+ case CC_X86RegCall:
case CC_X86Pascal:
case CC_X86VectorCall:
case CC_SpirFunction:
diff --git a/include/clang/Basic/StmtNodes.td b/include/clang/Basic/StmtNodes.td
index 973b3bb6fd17..d8eed553d86e 100644
--- a/include/clang/Basic/StmtNodes.td
+++ b/include/clang/Basic/StmtNodes.td
@@ -85,6 +85,8 @@ def DesignatedInitExpr : DStmt<Expr>;
def DesignatedInitUpdateExpr : DStmt<Expr>;
def ImplicitValueInitExpr : DStmt<Expr>;
def NoInitExpr : DStmt<Expr>;
+def ArrayInitLoopExpr : DStmt<Expr>;
+def ArrayInitIndexExpr : DStmt<Expr>;
def ParenListExpr : DStmt<Expr>;
def VAArgExpr : DStmt<Expr>;
def GenericSelectionExpr : DStmt<Expr>;
@@ -233,3 +235,11 @@ def OMPDistributeParallelForDirective : DStmt<OMPLoopDirective>;
def OMPDistributeParallelForSimdDirective : DStmt<OMPLoopDirective>;
def OMPDistributeSimdDirective : DStmt<OMPLoopDirective>;
def OMPTargetParallelForSimdDirective : DStmt<OMPLoopDirective>;
+def OMPTargetSimdDirective : DStmt<OMPLoopDirective>;
+def OMPTeamsDistributeDirective : DStmt<OMPLoopDirective>;
+def OMPTeamsDistributeSimdDirective : DStmt<OMPLoopDirective>;
+def OMPTeamsDistributeParallelForSimdDirective : DStmt<OMPLoopDirective>;
+def OMPTeamsDistributeParallelForDirective : DStmt<OMPLoopDirective>;
+def OMPTargetTeamsDirective : DStmt<OMPExecutableDirective>;
+def OMPTargetTeamsDistributeDirective : DStmt<OMPLoopDirective>;
+def OMPTargetTeamsDistributeParallelForDirective : DStmt<OMPLoopDirective>;
diff --git a/include/clang/Basic/TargetBuiltins.h b/include/clang/Basic/TargetBuiltins.h
index 623c0b64dbf3..5d45e162d9f6 100644
--- a/include/clang/Basic/TargetBuiltins.h
+++ b/include/clang/Basic/TargetBuiltins.h
@@ -85,12 +85,16 @@ namespace clang {
/// \brief X86 builtins
namespace X86 {
- enum {
- LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1,
+ enum {
+ LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1,
#define BUILTIN(ID, TYPE, ATTRS) BI##ID,
#include "clang/Basic/BuiltinsX86.def"
- LastTSBuiltin
- };
+ FirstX86_64Builtin,
+ LastX86CommonBuiltin = FirstX86_64Builtin - 1,
+#define BUILTIN(ID, TYPE, ATTRS) BI##ID,
+#include "clang/Basic/BuiltinsX86_64.def"
+ LastTSBuiltin
+ };
}
/// \brief Flags to identify the types for overloaded Neon builtins.
diff --git a/include/clang/Basic/TargetCXXABI.h b/include/clang/Basic/TargetCXXABI.h
index f7d4b920ca15..7fb1f826b0f6 100644
--- a/include/clang/Basic/TargetCXXABI.h
+++ b/include/clang/Basic/TargetCXXABI.h
@@ -16,7 +16,6 @@
#ifndef LLVM_CLANG_BASIC_TARGETCXXABI_H
#define LLVM_CLANG_BASIC_TARGETCXXABI_H
-#include "llvm/ADT/Triple.h"
#include "llvm/Support/ErrorHandling.h"
namespace clang {
diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h
index f458c166a7a8..208f8e8c7137 100644
--- a/include/clang/Basic/TargetInfo.h
+++ b/include/clang/Basic/TargetInfo.h
@@ -26,7 +26,6 @@
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Triple.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/Support/DataTypes.h"
@@ -41,7 +40,9 @@ struct fltSemantics;
namespace clang {
class DiagnosticsEngine;
class LangOptions;
+class CodeGenOptions;
class MacroBuilder;
+class QualType;
class SourceLocation;
class SourceManager;
@@ -76,6 +77,7 @@ protected:
unsigned short MaxVectorAlign;
unsigned short MaxTLSAlign;
unsigned short SimdDefaultAlign;
+ unsigned short NewAlign;
std::unique_ptr<llvm::DataLayout> DataLayout;
const char *MCountName;
const llvm::fltSemantics *HalfFormat, *FloatFormat, *DoubleFormat,
@@ -93,6 +95,8 @@ protected:
unsigned HasBuiltinMSVaList : 1;
+ unsigned IsRenderScriptTarget : 1;
+
// TargetInfo Constructor. Default initializes all fields.
TargetInfo(const llvm::Triple &T);
@@ -292,6 +296,17 @@ public:
return AddrSpace == 0 ? PointerAlign : getPointerAlignV(AddrSpace);
}
+ /// \brief Return the maximum width of pointers on this target.
+ virtual uint64_t getMaxPointerWidth() const {
+ return PointerWidth;
+ }
+
+ /// \brief Get integer value for null pointer.
+ /// \param AddrSpace address space of pointee in source language.
+ virtual uint64_t getNullPointerValue(unsigned AddrSpace) const {
+ return 0;
+ }
+
/// \brief Return the size of '_Bool' and C++ 'bool' for this target, in bits.
unsigned getBoolWidth() const { return BoolWidth; }
@@ -346,6 +361,13 @@ public:
/// unless its alignment is explicitly reduced via attributes.
unsigned getMinGlobalAlign() const { return MinGlobalAlign; }
+ /// Return the largest alignment for which a suitably-sized allocation with
+ /// '::operator new(size_t)' is guaranteed to produce a correctly-aligned
+ /// pointer.
+ unsigned getNewAlign() const {
+ return NewAlign ? NewAlign : std::max(LongDoubleAlign, LongLongAlign);
+ }
+
/// getWCharWidth/Align - Return the size of 'wchar_t' for this target, in
/// bits.
unsigned getWCharWidth() const { return getTypeWidth(WCharType); }
@@ -566,6 +588,9 @@ public:
/// available on this target.
bool hasBuiltinMSVaList() const { return HasBuiltinMSVaList; }
+ /// Returns true for RenderScript.
+ bool isRenderScriptTarget() const { return IsRenderScriptTarget; }
+
/// \brief Returns whether the passed in string is a valid clobber in an
/// inline asm statement.
///
@@ -580,8 +605,16 @@ public:
/// \brief Returns the "normalized" GCC register name.
///
- /// For example, on x86 it will return "ax" when "eax" is passed in.
- StringRef getNormalizedGCCRegisterName(StringRef Name) const;
+ /// 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 {
+ return "";
+ }
struct ConstraintInfo {
enum {
@@ -793,6 +826,10 @@ public:
/// language options which change the target configuration.
virtual void adjust(const LangOptions &Opts);
+ /// \brief 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
/// CPU this should include all legal feature strings on the target.
///
@@ -925,6 +962,7 @@ public:
VersionTuple getPlatformMinVersion() const { return PlatformMinVersion; }
bool isBigEndian() const { return BigEndian; }
+ bool isLittleEndian() const { return !BigEndian; }
enum CallingConvMethodType {
CCMT_Unknown,
@@ -966,12 +1004,19 @@ public:
return false;
}
- /// \brief Whether target allows to overalign ABI-specified prefered alignment
+ /// \brief Whether target allows to overalign ABI-specified preferred alignment
virtual bool allowsLargerPreferedTypeAlignment() const { return true; }
/// \brief Set supported OpenCL extensions and optional core features.
virtual void setSupportedOpenCLOpts() {}
+ /// \brief 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.
OpenCLOptions &getSupportedOpenCLOpts() {
return getTargetOpts().SupportedOpenCLOptions;
@@ -982,6 +1027,11 @@ public:
return getTargetOpts().SupportedOpenCLOptions;
}
+ /// \brief Get OpenCL image type address space.
+ virtual LangAS::ID getOpenCLImageAddrSpace() const {
+ return LangAS::opencl_global;
+ }
+
/// \brief Check the target is valid after it is fully initialized.
virtual bool validateTarget(DiagnosticsEngine &Diags) const {
return true;
diff --git a/include/clang/Basic/TargetOptions.h b/include/clang/Basic/TargetOptions.h
index fde294c92251..2889cce5963b 100644
--- a/include/clang/Basic/TargetOptions.h
+++ b/include/clang/Basic/TargetOptions.h
@@ -58,6 +58,10 @@ public:
/// Supported OpenCL extensions and optional core features.
OpenCLOptions SupportedOpenCLOptions;
+
+ /// \brief The list of OpenCL extensions to enable or disable, as written on
+ /// the command line.
+ std::vector<std::string> OpenCLExtensionsAsWritten;
};
} // end namespace clang
diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def
index 882c6e4cac2c..104b053a14af 100644
--- a/include/clang/Basic/TokenKinds.def
+++ b/include/clang/Basic/TokenKinds.def
@@ -30,6 +30,9 @@
#ifndef CONCEPTS_KEYWORD
#define CONCEPTS_KEYWORD(X) KEYWORD(X,KEYCONCEPTS)
#endif
+#ifndef MODULES_KEYWORD
+#define MODULES_KEYWORD(X) KEYWORD(X,KEYMODULES)
+#endif
#ifndef TYPE_TRAIT
#define TYPE_TRAIT(N,I,K) KEYWORD(I,K)
#endif
@@ -235,6 +238,8 @@ PUNCTUATOR(caretcaret, "^^")
// KEYCXX11 - This is a C++ keyword introduced to C++ in C++11
// KEYCONCEPTS - This is a keyword if the C++ extensions for concepts
// are enabled.
+// KEYMODULES - This is a keyword if the C++ extensions for modules
+// are enabled.
// KEYGNU - This is a keyword if GNU extensions are enabled
// KEYMS - This is a keyword if Microsoft extensions are enabled
// KEYNOMS18 - This is a keyword that must never be enabled under
@@ -366,6 +371,10 @@ KEYWORD(co_await , KEYCOROUTINES)
KEYWORD(co_return , KEYCOROUTINES)
KEYWORD(co_yield , KEYCOROUTINES)
+// C++ modules TS keywords
+MODULES_KEYWORD(module)
+MODULES_KEYWORD(import)
+
// GNU Extensions (in impl-reserved namespace)
KEYWORD(_Decimal32 , KEYALL)
KEYWORD(_Decimal64 , KEYALL)
@@ -493,6 +502,7 @@ KEYWORD(__cdecl , KEYALL)
KEYWORD(__stdcall , KEYALL)
KEYWORD(__fastcall , KEYALL)
KEYWORD(__thiscall , KEYALL)
+KEYWORD(__regcall , KEYALL)
KEYWORD(__vectorcall , KEYALL)
KEYWORD(__forceinline , KEYMS)
KEYWORD(__unaligned , KEYMS)
diff --git a/include/clang/Basic/Version.h b/include/clang/Basic/Version.h
index 02da432a40db..57dcf92c3b28 100644
--- a/include/clang/Basic/Version.h
+++ b/include/clang/Basic/Version.h
@@ -19,26 +19,6 @@
#include "clang/Basic/Version.inc"
#include "llvm/ADT/StringRef.h"
-/// \brief Helper macro for CLANG_VERSION_STRING.
-#define CLANG_MAKE_VERSION_STRING2(X) #X
-
-#ifdef CLANG_VERSION_PATCHLEVEL
-/// \brief Helper macro for CLANG_VERSION_STRING.
-#define CLANG_MAKE_VERSION_STRING(X,Y,Z) CLANG_MAKE_VERSION_STRING2(X.Y.Z)
-
-/// \brief A string that describes the Clang version number, e.g., "1.0".
-#define CLANG_VERSION_STRING \
- CLANG_MAKE_VERSION_STRING(CLANG_VERSION_MAJOR,CLANG_VERSION_MINOR, \
- CLANG_VERSION_PATCHLEVEL)
-#else
-/// \brief Helper macro for CLANG_VERSION_STRING.
-#define CLANG_MAKE_VERSION_STRING(X,Y) CLANG_MAKE_VERSION_STRING2(X.Y)
-
-/// \brief A string that describes the Clang version number, e.g., "1.0".
-#define CLANG_VERSION_STRING \
- CLANG_MAKE_VERSION_STRING(CLANG_VERSION_MAJOR,CLANG_VERSION_MINOR)
-#endif
-
namespace clang {
/// \brief Retrieves the repository path (e.g., Subversion path) that
/// identifies the particular Clang branch, tag, or trunk from which this
diff --git a/include/clang/Basic/Version.inc.in b/include/clang/Basic/Version.inc.in
index ccf8430c8ba2..fd80af4b5110 100644
--- a/include/clang/Basic/Version.inc.in
+++ b/include/clang/Basic/Version.inc.in
@@ -1,6 +1,5 @@
#define CLANG_VERSION @CLANG_VERSION@
+#define CLANG_VERSION_STRING "@CLANG_VERSION@"
#define CLANG_VERSION_MAJOR @CLANG_VERSION_MAJOR@
#define CLANG_VERSION_MINOR @CLANG_VERSION_MINOR@
-#if @CLANG_HAS_VERSION_PATCHLEVEL@
#define CLANG_VERSION_PATCHLEVEL @CLANG_VERSION_PATCHLEVEL@
-#endif
diff --git a/include/clang/Basic/VirtualFileSystem.h b/include/clang/Basic/VirtualFileSystem.h
index 6ac0812dbb17..39dab6cbf045 100644
--- a/include/clang/Basic/VirtualFileSystem.h
+++ b/include/clang/Basic/VirtualFileSystem.h
@@ -16,15 +16,30 @@
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/Chrono.h"
#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>
+#include <memory>
+#include <stack>
+#include <string>
+#include <system_error>
#include <utility>
+#include <vector>
namespace llvm {
+
class MemoryBuffer;
-}
+
+} // end namespace llvm
namespace clang {
namespace vfs {
@@ -33,7 +48,7 @@ namespace vfs {
class Status {
std::string Name;
llvm::sys::fs::UniqueID UID;
- llvm::sys::TimeValue MTime;
+ llvm::sys::TimePoint<> MTime;
uint32_t User;
uint32_t Group;
uint64_t Size;
@@ -47,7 +62,7 @@ public:
Status() : Type(llvm::sys::fs::file_type::status_error) {}
Status(const llvm::sys::fs::file_status &Status);
Status(StringRef Name, llvm::sys::fs::UniqueID UID,
- llvm::sys::TimeValue MTime, uint32_t User, uint32_t Group,
+ llvm::sys::TimePoint<> MTime, uint32_t User, uint32_t Group,
uint64_t Size, llvm::sys::fs::file_type Type,
llvm::sys::fs::perms Perms);
@@ -63,7 +78,7 @@ public:
/// @{
llvm::sys::fs::file_type getType() const { return Type; }
llvm::sys::fs::perms getPermissions() const { return Perms; }
- llvm::sys::TimeValue getLastModificationTime() const { return MTime; }
+ llvm::sys::TimePoint<> getLastModificationTime() const { return MTime; }
llvm::sys::fs::UniqueID getUniqueID() const { return UID; }
uint32_t getUser() const { return User; }
uint32_t getGroup() const { return Group; }
@@ -89,8 +104,10 @@ public:
/// Sub-classes should generally call close() inside their destructors. We
/// cannot do that from the base class, since close is virtual.
virtual ~File();
+
/// \brief Get the status of the file.
virtual llvm::ErrorOr<Status> status() = 0;
+
/// \brief Get the name of the file
virtual llvm::ErrorOr<std::string> getName() {
if (auto Status = status())
@@ -98,24 +115,30 @@ public:
else
return Status.getError();
}
+
/// \brief 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.
virtual std::error_code close() = 0;
};
namespace detail {
+
/// \brief An interface for virtual file systems to provide an iterator over the
/// (non-recursive) contents of a directory.
struct DirIterImpl {
virtual ~DirIterImpl();
+
/// \brief Sets \c CurrentEntry to the next entry in the directory on success,
/// or returns a system-defined \c error_code.
virtual std::error_code increment() = 0;
+
Status CurrentEntry;
};
+
} // end namespace detail
/// \brief An input iterator over the entries in a virtual path, similar to
@@ -132,7 +155,7 @@ public:
}
/// \brief Construct an 'end' iterator.
- directory_iterator() { }
+ directory_iterator() = default;
/// \brief Equivalent to operator++, with an error code.
directory_iterator &increment(std::error_code &EC) {
@@ -171,7 +194,7 @@ public:
recursive_directory_iterator(FileSystem &FS, const Twine &Path,
std::error_code &EC);
/// \brief Construct an 'end' iterator.
- recursive_directory_iterator() { }
+ recursive_directory_iterator() = default;
/// \brief Equivalent to operator++, with an error code.
recursive_directory_iterator &increment(std::error_code &EC);
@@ -185,6 +208,7 @@ public:
bool operator!=(const recursive_directory_iterator &RHS) const {
return !(*this == RHS);
}
+
/// \brief Gets the current level. Starting path is at level 0.
int level() const {
assert(State->size() && "Cannot get level without any iteration state");
@@ -280,7 +304,9 @@ public:
};
namespace detail {
+
class InMemoryDirectory;
+
} // end namespace detail
/// An in-memory file system.
@@ -292,6 +318,7 @@ class InMemoryFileSystem : public FileSystem {
public:
explicit InMemoryFileSystem(bool UseNormalizedPaths = true);
~InMemoryFileSystem() override;
+
/// Add a buffer to the VFS with a path. The VFS owns the buffer.
/// \return true if the file was successfully added, false if the file already
/// exists in the file system with different contents.
@@ -335,22 +362,41 @@ struct YAMLVFSEntry {
std::string RPath;
};
+/// \brief 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(
+ std::unique_ptr<llvm::MemoryBuffer> Buffer,
+ llvm::SourceMgr::DiagHandlerTy DiagHandler, StringRef YAMLFilePath,
+ SmallVectorImpl<YAMLVFSEntry> &CollectedEntries,
+ void *DiagContext = nullptr,
+ IntrusiveRefCntPtr<FileSystem> ExternalFS = getRealFileSystem());
+
class YAMLVFSWriter {
std::vector<YAMLVFSEntry> Mappings;
Optional<bool> IsCaseSensitive;
Optional<bool> IsOverlayRelative;
Optional<bool> UseExternalNames;
+ Optional<bool> IgnoreNonExistentContents;
std::string OverlayDir;
public:
- YAMLVFSWriter() {}
+ YAMLVFSWriter() = default;
+
void addFileMapping(StringRef VirtualPath, StringRef RealPath);
+
void setCaseSensitivity(bool CaseSensitive) {
IsCaseSensitive = CaseSensitive;
}
+
void setUseExternalNames(bool UseExtNames) {
UseExternalNames = UseExtNames;
}
+
+ void setIgnoreNonExistentContents(bool IgnoreContents) {
+ IgnoreNonExistentContents = IgnoreContents;
+ }
+
void setOverlayDir(StringRef OverlayDirectory) {
IsOverlayRelative = true;
OverlayDir.assign(OverlayDirectory.str());
@@ -361,4 +407,5 @@ public:
} // end namespace vfs
} // end namespace clang
-#endif
+
+#endif // LLVM_CLANG_BASIC_VIRTUALFILESYSTEM_H
diff --git a/include/clang/CodeGen/CGFunctionInfo.h b/include/clang/CodeGen/CGFunctionInfo.h
index 8dd6ad1c21ee..2703f299d217 100644
--- a/include/clang/CodeGen/CGFunctionInfo.h
+++ b/include/clang/CodeGen/CGFunctionInfo.h
@@ -664,29 +664,6 @@ public:
}
};
-/// CGCalleeInfo - Class to encapsulate the information about a callee to be
-/// used during the generation of call/invoke instructions.
-class CGCalleeInfo {
- /// \brief The function proto type of the callee.
- const FunctionProtoType *CalleeProtoTy;
- /// \brief The function declaration of the callee.
- const Decl *CalleeDecl;
-
-public:
- explicit CGCalleeInfo() : CalleeProtoTy(nullptr), CalleeDecl(nullptr) {}
- CGCalleeInfo(const FunctionProtoType *calleeProtoTy, const Decl *calleeDecl)
- : CalleeProtoTy(calleeProtoTy), CalleeDecl(calleeDecl) {}
- CGCalleeInfo(const FunctionProtoType *calleeProtoTy)
- : CalleeProtoTy(calleeProtoTy), CalleeDecl(nullptr) {}
- CGCalleeInfo(const Decl *calleeDecl)
- : CalleeProtoTy(nullptr), CalleeDecl(calleeDecl) {}
-
- const FunctionProtoType *getCalleeFunctionProtoType() {
- return CalleeProtoTy;
- }
- const Decl *getCalleeDecl() { return CalleeDecl; }
-};
-
} // end namespace CodeGen
} // end namespace clang
diff --git a/include/clang/CodeGen/ModuleBuilder.h b/include/clang/CodeGen/ModuleBuilder.h
index ce7696dd00cf..58638348653f 100644
--- a/include/clang/CodeGen/ModuleBuilder.h
+++ b/include/clang/CodeGen/ModuleBuilder.h
@@ -20,6 +20,7 @@ namespace llvm {
class Constant;
class LLVMContext;
class Module;
+ class StringRef;
}
namespace clang {
diff --git a/include/clang/CodeGen/ObjectFilePCHContainerOperations.h b/include/clang/CodeGen/ObjectFilePCHContainerOperations.h
index 6437f4f9b4f5..67be6718fec4 100644
--- a/include/clang/CodeGen/ObjectFilePCHContainerOperations.h
+++ b/include/clang/CodeGen/ObjectFilePCHContainerOperations.h
@@ -35,10 +35,8 @@ class ObjectFilePCHContainerWriter : public PCHContainerWriter {
class ObjectFilePCHContainerReader : public PCHContainerReader {
StringRef getFormat() const override { return "obj"; }
- /// Initialize an llvm::BitstreamReader with the serialized
- /// AST inside the PCH container Buffer.
- void ExtractPCH(llvm::MemoryBufferRef Buffer,
- llvm::BitstreamReader &StreamFile) const override;
+ /// Returns the serialized AST inside the PCH container Buffer.
+ StringRef ExtractPCH(llvm::MemoryBufferRef Buffer) const override;
};
}
diff --git a/include/clang/CodeGen/SwiftCallingConv.h b/include/clang/CodeGen/SwiftCallingConv.h
index f9c2fd94ca8d..23db43e6739c 100644
--- a/include/clang/CodeGen/SwiftCallingConv.h
+++ b/include/clang/CodeGen/SwiftCallingConv.h
@@ -17,7 +17,6 @@
#include "clang/AST/CanonicalType.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/Type.h"
-#include "llvm/ADT/FoldingSet.h"
#include "llvm/Support/TrailingObjects.h"
#include <cassert>
@@ -91,7 +90,7 @@ public:
bool shouldPassIndirectly(bool asReturnValue) const;
using EnumerationCallback =
- llvm::function_ref<void(CharUnits offset, llvm::Type *type)>;
+ llvm::function_ref<void(CharUnits offset, CharUnits end, llvm::Type *type)>;
/// Enumerate the expanded components of this type.
///
@@ -161,6 +160,9 @@ 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.
+bool isSwiftErrorLoweredInRegister(CodeGenModule &CGM);
+
} // end namespace swiftcall
} // end namespace CodeGen
} // end namespace clang
diff --git a/include/clang/Config/config.h.cmake b/include/clang/Config/config.h.cmake
index e5a1d0dac837..55f0ca94dedc 100644
--- a/include/clang/Config/config.h.cmake
+++ b/include/clang/Config/config.h.cmake
@@ -8,9 +8,15 @@
/* Bug report URL. */
#define BUG_REPORT_URL "${BUG_REPORT_URL}"
+/* Default linker to use. */
+#define CLANG_DEFAULT_LINKER "${CLANG_DEFAULT_LINKER}"
+
/* Default C++ stdlib to use. */
#define CLANG_DEFAULT_CXX_STDLIB "${CLANG_DEFAULT_CXX_STDLIB}"
+/* Default runtime library to use. */
+#define CLANG_DEFAULT_RTLIB "${CLANG_DEFAULT_RTLIB}"
+
/* Default OpenMP runtime used by -fopenmp. */
#define CLANG_DEFAULT_OPENMP_RUNTIME "${CLANG_DEFAULT_OPENMP_RUNTIME}"
@@ -32,6 +38,9 @@
/* Define if we have libxml2 */
#cmakedefine CLANG_HAVE_LIBXML ${CLANG_HAVE_LIBXML}
+/* Define if we have sys/resource.h (rlimits) */
+#cmakedefine CLANG_HAVE_RLIMITS ${CLANG_HAVE_RLIMITS}
+
/* The LLVM product name and version */
#define BACKEND_PACKAGE_STRING "${BACKEND_PACKAGE_STRING}"
diff --git a/include/clang/Driver/Action.h b/include/clang/Driver/Action.h
index 3fe6510fec98..72456d34a0d9 100644
--- a/include/clang/Driver/Action.h
+++ b/include/clang/Driver/Action.h
@@ -66,9 +66,11 @@ public:
DsymutilJobClass,
VerifyDebugInfoJobClass,
VerifyPCHJobClass,
+ OffloadBundlingJobClass,
+ OffloadUnbundlingJobClass,
JobClassFirst = PreprocessJobClass,
- JobClassLast = VerifyPCHJobClass
+ JobClassLast = OffloadUnbundlingJobClass
};
// The offloading kind determines if this action is binded to a particular
@@ -80,6 +82,7 @@ public:
OFK_Host = 0x01,
// The device offloading tool chains - one bit for each programming model.
OFK_Cuda = 0x02,
+ OFK_OpenMP = 0x04,
};
static const char *getClassName(ActionClass AC);
@@ -92,6 +95,12 @@ private:
ActionList Inputs;
+ /// Flag that is set to true if this action can be collapsed with others
+ /// actions that depend on it. This is true by default and set to false when
+ /// the action is used by two different tool chains, which is enabled by the
+ /// offloading support implementation.
+ bool CanBeCollapsedWithNextDependentAction = true;
+
protected:
///
/// Offload information.
@@ -136,12 +145,26 @@ public:
return input_const_range(input_begin(), input_end());
}
+ /// Mark this action as not legal to collapse.
+ void setCannotBeCollapsedWithNextDependentAction() {
+ CanBeCollapsedWithNextDependentAction = false;
+ }
+ /// Return true if this function can be collapsed with others.
+ bool isCollapsingWithNextDependentActionLegal() const {
+ return CanBeCollapsedWithNextDependentAction;
+ }
+
/// 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.
- std::string
- getOffloadingFileNamePrefix(llvm::StringRef NormalizedTriple) const;
+ /// 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,
+ 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.
@@ -190,12 +213,12 @@ class BindArchAction : public Action {
virtual void anchor();
/// The architecture to bind, or 0 if the default architecture
/// should be bound.
- const char *ArchName;
+ StringRef ArchName;
public:
- BindArchAction(Action *Input, const char *ArchName);
+ BindArchAction(Action *Input, StringRef ArchName);
- const char *getArchName() const { return ArchName; }
+ StringRef getArchName() const { return ArchName; }
static bool classof(const Action *A) {
return A->getKind() == BindArchClass;
@@ -465,6 +488,64 @@ public:
}
};
+class OffloadBundlingJobAction : public JobAction {
+ void anchor() override;
+
+public:
+ // Offloading bundling doesn't change the type of output.
+ OffloadBundlingJobAction(ActionList &Inputs);
+
+ static bool classof(const Action *A) {
+ return A->getKind() == OffloadBundlingJobClass;
+ }
+};
+
+class OffloadUnbundlingJobAction final : public JobAction {
+ void anchor() override;
+
+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.
+ const ToolChain *DependentToolChain = nullptr;
+ /// \brief The bound architecture of the dependent action.
+ StringRef DependentBoundArch;
+ /// \brief 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){};
+ };
+
+private:
+ /// Container that keeps information about each dependence of this unbundling
+ /// action.
+ SmallVector<DependentActionInfo, 6> DependentActionInfoArray;
+
+public:
+ // Offloading unbundling doesn't change the type of output.
+ OffloadUnbundlingJobAction(Action *Input);
+
+ /// Register information about a dependent action.
+ void registerDependentActionInfo(const ToolChain *TC, StringRef BoundArch,
+ OffloadKind Kind) {
+ DependentActionInfoArray.push_back({TC, BoundArch, Kind});
+ }
+
+ /// Return the information about all depending actions.
+ ArrayRef<DependentActionInfo> getDependentActionsInfo() const {
+ return DependentActionInfoArray;
+ }
+
+ static bool classof(const Action *A) {
+ return A->getKind() == OffloadUnbundlingJobClass;
+ }
+};
+
} // end namespace driver
} // end namespace clang
diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td
index 1401984c2a34..2910b8521bab 100644
--- a/include/clang/Driver/CC1Options.td
+++ b/include/clang/Driver/CC1Options.td
@@ -114,6 +114,9 @@ def analyzer_disable_all_checks : Flag<["-"], "analyzer-disable-all-checks">,
def analyzer_checker_help : Flag<["-"], "analyzer-checker-help">,
HelpText<"Display the list of analyzer checkers that are available">;
+def analyzer_list_enabled_checkers : Flag<["-"], "analyzer-list-enabled-checkers">,
+ HelpText<"Display the list of enabled analyzer checkers">;
+
def analyzer_config : Separate<["-"], "analyzer-config">,
HelpText<"Choose analyzer options to enable">;
@@ -157,13 +160,13 @@ def fno_math_builtin : Flag<["-"], "fno-math-builtin">,
HelpText<"Disable implicit builtin knowledge of math functions">;
}
-def disable_llvm_optzns : Flag<["-"], "disable-llvm-optzns">,
- HelpText<"Don't run LLVM optimization passes">;
def disable_llvm_verifier : Flag<["-"], "disable-llvm-verifier">,
HelpText<"Don't run the LLVM IR verifier pass">;
def disable_llvm_passes : Flag<["-"], "disable-llvm-passes">,
HelpText<"Use together with -emit-llvm to get pristine LLVM IR from the "
"frontend by not running any LLVM passes at all">;
+def disable_llvm_optzns : Flag<["-"], "disable-llvm-optzns">,
+ Alias<disable_llvm_passes>;
def disable_red_zone : Flag<["-"], "disable-red-zone">,
HelpText<"Do not emit code that uses the red zone.">;
def dwarf_column_info : Flag<["-"], "dwarf-column-info">,
@@ -189,9 +192,14 @@ def femit_coverage_notes : Flag<["-"], "femit-coverage-notes">,
HelpText<"Emit a gcov coverage notes file when compiling.">;
def femit_coverage_data: Flag<["-"], "femit-coverage-data">,
HelpText<"Instrument the program to emit gcov coverage data when run.">;
-def coverage_file : Separate<["-"], "coverage-file">,
- HelpText<"Emit coverage data to this filename. The extension will be replaced.">;
-def coverage_file_EQ : Joined<["-"], "coverage-file=">, Alias<coverage_file>;
+def coverage_data_file : Separate<["-"], "coverage-data-file">,
+ HelpText<"Emit coverage data to this filename.">;
+def coverage_data_file_EQ : Joined<["-"], "coverage-data-file=">,
+ Alias<coverage_data_file>;
+def coverage_notes_file : Separate<["-"], "coverage-notes-file">,
+ HelpText<"Emit coverage notes to this filename.">;
+def coverage_notes_file_EQ : Joined<["-"], "coverage-notes-file=">,
+ Alias<coverage_notes_file>;
def coverage_cfg_checksum : Flag<["-"], "coverage-cfg-checksum">,
HelpText<"Emit CFG checksum for functions in .gcno files.">;
def coverage_no_function_names_in_data : Flag<["-"], "coverage-no-function-names-in-data">,
@@ -269,12 +277,21 @@ def fsanitize_coverage_trace_bb
def fsanitize_coverage_trace_cmp
: Flag<["-"], "fsanitize-coverage-trace-cmp">,
HelpText<"Enable cmp instruction tracing in sanitizer coverage">;
+def fsanitize_coverage_trace_div
+ : Flag<["-"], "fsanitize-coverage-trace-div">,
+ HelpText<"Enable div instruction tracing in sanitizer coverage">;
+def fsanitize_coverage_trace_gep
+ : Flag<["-"], "fsanitize-coverage-trace-gep">,
+ HelpText<"Enable gep instruction tracing in sanitizer coverage">;
def fsanitize_coverage_8bit_counters
: Flag<["-"], "fsanitize-coverage-8bit-counters">,
HelpText<"Enable frequency counters in sanitizer coverage">;
def fsanitize_coverage_trace_pc
: Flag<["-"], "fsanitize-coverage-trace-pc">,
HelpText<"Enable PC tracing in sanitizer coverage">;
+def fsanitize_coverage_trace_pc_guard
+ : Flag<["-"], "fsanitize-coverage-trace-pc-guard">,
+ HelpText<"Enable PC tracing with guard in sanitizer coverage">;
def fprofile_instrument_EQ : Joined<["-"], "fprofile-instrument=">,
HelpText<"Enable PGO instrumentation. The accepted value is clang, llvm, "
"or none">;
@@ -454,6 +471,8 @@ def print_decl_contexts : Flag<["-"], "print-decl-contexts">,
HelpText<"Print DeclContexts and their Decls">;
def emit_module : Flag<["-"], "emit-module">,
HelpText<"Generate pre-compiled module file from a module map">;
+def emit_module_interface : Flag<["-"], "emit-module-interface">,
+ HelpText<"Generate pre-compiled module file from a C++ module interface">;
def emit_pth : Flag<["-"], "emit-pth">,
HelpText<"Generate pre-tokenized header file">;
def emit_pch : Flag<["-"], "emit-pch">,
@@ -488,8 +507,13 @@ def arcmt_modify : Flag<["-"], "arcmt-modify">,
def arcmt_migrate : Flag<["-"], "arcmt-migrate">,
HelpText<"Apply modifications and produces temporary files that conform to ARC">;
+def opt_record_file : Separate<["-"], "opt-record-file">,
+ HelpText<"File name to use for YAML optimization record output">;
+
def print_stats : Flag<["-"], "print-stats">,
HelpText<"Print performance metrics and statistics">;
+def stats_file : Joined<["-"], "stats-file=">,
+ HelpText<"Filename to write statistics to">;
def fdump_record_layouts : Flag<["-"], "fdump-record-layouts">,
HelpText<"Dump record layout information">;
def fdump_record_layouts_simple : Flag<["-"], "fdump-record-layouts-simple">,
@@ -617,9 +641,11 @@ def fdefault_calling_conv_EQ : Joined<["-"], "fdefault-calling-conv=">,
def finclude_default_header : Flag<["-"], "finclude-default-header">,
HelpText<"Include the default header file for OpenCL">;
-// C++ TSes.
-def fcoroutines : Flag<["-"], "fcoroutines">,
- HelpText<"Enable support for the C++ Coroutines TS">;
+// FIXME: Remove these entirely once functionality/tests have been excised.
+def fobjc_gc_only : Flag<["-"], "fobjc-gc-only">, Group<f_Group>,
+ HelpText<"Use GC exclusively for Objective-C related memory management">;
+def fobjc_gc : Flag<["-"], "fobjc-gc">, Group<f_Group>,
+ HelpText<"Enable Objective-C garbage collection">;
//===----------------------------------------------------------------------===//
// Header Search Options
@@ -666,6 +692,13 @@ def detailed_preprocessing_record : Flag<["-"], "detailed-preprocessing-record">
HelpText<"include a detailed record of preprocessing actions">;
//===----------------------------------------------------------------------===//
+// OpenCL Options
+//===----------------------------------------------------------------------===//
+
+def cl_ext_EQ : CommaJoined<["-"], "cl-ext=">,
+ HelpText<"OpenCL only. Enable or disable OpenCL extensions. The argument is a comma-separated sequence of one or more extension names, each prefixed by '+' or '-'.">;
+
+//===----------------------------------------------------------------------===//
// CUDA Options
//===----------------------------------------------------------------------===//
@@ -716,4 +749,6 @@ def show_inst : Flag<["-"], "show-inst">,
def dwarf_debug_producer : Separate<["-"], "dwarf-debug-producer">,
HelpText<"The string to embed in the Dwarf debug AT_producer record.">;
+def defsym : Separate<["-"], "defsym">,
+ HelpText<"Define a value for a symbol">;
} // let Flags = [CC1AsOption]
diff --git a/include/clang/Driver/CLCompatOptions.td b/include/clang/Driver/CLCompatOptions.td
index b1d2459f71cf..cb2745afb7e4 100644
--- a/include/clang/Driver/CLCompatOptions.td
+++ b/include/clang/Driver/CLCompatOptions.td
@@ -54,10 +54,10 @@ class CLRemainingArgsJoined<string name> : Option<["/", "-"], name,
def _SLASH_Brepro : CLFlag<"Brepro">,
HelpText<"Emit an object file which can be reproduced over time">,
- Alias<mincremental_linker_compatible>;
+ Alias<mno_incremental_linker_compatible>;
def _SLASH_Brepro_ : CLFlag<"Brepro-">,
HelpText<"Emit an object file which cannot be reproduced over time">,
- Alias<mno_incremental_linker_compatible>;
+ Alias<mincremental_linker_compatible>;
def _SLASH_C : CLFlag<"C">,
HelpText<"Don't discard comments when preprocessing">, Alias<C>;
def _SLASH_c : CLFlag<"c">, HelpText<"Compile only">, Alias<c>;
@@ -120,10 +120,18 @@ def _SLASH_Qvec_ : CLFlag<"Qvec-">,
def _SLASH_showIncludes : CLFlag<"showIncludes">,
HelpText<"Print info about included files to stderr">,
Alias<show_includes>;
+def _SLASH_source_charset : CLCompileJoined<"source-charset:">,
+ HelpText<"Source encoding, supports only UTF-8">, Alias<finput_charset_EQ>;
+def _SLASH_execution_charset : CLCompileJoined<"execution-charset:">,
+ HelpText<"Runtime encoding, supports only UTF-8">, Alias<fexec_charset_EQ>;
def _SLASH_std : CLCompileJoined<"std:">,
HelpText<"Language standard to compile for">;
def _SLASH_U : CLJoinedOrSeparate<"U">, HelpText<"Undefine macro">,
MetaVarName<"<macro>">, Alias<U>;
+def _SLASH_validate_charset : CLFlag<"validate-charset">,
+ Alias<W_Joined>, AliasArgs<["invalid-source-encoding"]>;
+def _SLASH_validate_charset_ : CLFlag<"validate-charset-">,
+ Alias<W_Joined>, AliasArgs<["no-invalid-source-encoding"]>;
def _SLASH_W0 : CLFlag<"W0">, HelpText<"Disable all warnings">, Alias<w>;
def _SLASH_W1 : CLFlag<"W1">, HelpText<"Enable -Wall">, Alias<Wall>;
def _SLASH_W2 : CLFlag<"W2">, HelpText<"Enable -Wall">, Alias<Wall>;
@@ -289,8 +297,8 @@ def _SLASH_cgthreads : CLIgnoredJoined<"cgthreads">;
def _SLASH_d2FastFail : CLIgnoredFlag<"d2FastFail">;
def _SLASH_d2Zi_PLUS : CLIgnoredFlag<"d2Zi+">;
def _SLASH_errorReport : CLIgnoredJoined<"errorReport">;
-def _SLASH_Fd : CLIgnoredJoined<"Fd">;
def _SLASH_FC : CLIgnoredFlag<"FC">;
+def _SLASH_Fd : CLIgnoredJoined<"Fd">;
def _SLASH_FS : CLIgnoredFlag<"FS">, HelpText<"Force synchronous PDB writes">;
def _SLASH_GF : CLIgnoredFlag<"GF">;
def _SLASH_kernel_ : CLIgnoredFlag<"kernel-">;
@@ -300,6 +308,7 @@ def _SLASH_openmp_ : CLIgnoredFlag<"openmp-">;
def _SLASH_RTC : CLIgnoredJoined<"RTC">;
def _SLASH_sdl : CLIgnoredFlag<"sdl">;
def _SLASH_sdl_ : CLIgnoredFlag<"sdl-">;
+def _SLASH_utf8 : CLIgnoredFlag<"utf-8">;
def _SLASH_w : CLIgnoredJoined<"w">;
def _SLASH_Zc_auto : CLIgnoredFlag<"Zc:auto">;
def _SLASH_Zc_forScope : CLIgnoredFlag<"Zc:forScope">;
diff --git a/include/clang/Driver/Compilation.h b/include/clang/Driver/Compilation.h
index 3f387151a3d4..114e0b33c75a 100644
--- a/include/clang/Driver/Compilation.h
+++ b/include/clang/Driver/Compilation.h
@@ -14,7 +14,6 @@
#include "clang/Driver/Job.h"
#include "clang/Driver/Util.h"
#include "llvm/ADT/DenseMap.h"
-#include "llvm/Support/Path.h"
#include <map>
namespace llvm {
@@ -68,10 +67,27 @@ class Compilation {
/// The root list of jobs.
JobList Jobs;
- /// Cache of translated arguments for a particular tool chain and bound
- /// architecture.
- llvm::DenseMap<std::pair<const ToolChain *, const char *>,
- llvm::opt::DerivedArgList *> TCArgs;
+ /// Cache of translated arguments for a particular tool chain, bound
+ /// architecture, and device offload kind.
+ struct TCArgsKey final {
+ const ToolChain *TC = nullptr;
+ StringRef BoundArch;
+ Action::OffloadKind DeviceOffloadKind = Action::OFK_None;
+ bool operator<(const TCArgsKey &K) const {
+ if (TC < K.TC)
+ return true;
+ else if (TC == K.TC && BoundArch < K.BoundArch)
+ return true;
+ else if (TC == K.TC && BoundArch == K.BoundArch &&
+ DeviceOffloadKind < K.DeviceOffloadKind)
+ 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;
/// Temporary files which should be removed on exit.
llvm::opt::ArgStringList TempFiles;
@@ -116,6 +132,12 @@ public:
return OrderedOffloadingToolchains.equal_range(Kind);
}
+ /// Return true if an offloading tool chain of a given kind exists.
+ template <Action::OffloadKind Kind> bool hasOffloadToolChain() const {
+ return OrderedOffloadingToolchains.find(Kind) !=
+ OrderedOffloadingToolchains.end();
+ }
+
/// Return an offload toolchain of the provided kind. Only one is expected to
/// exist.
template <Action::OffloadKind Kind>
@@ -176,10 +198,15 @@ public:
/// getArgsForToolChain - Return the derived argument list for the
/// tool chain \p TC (or the default tool chain, if TC is not specified).
+ /// If a device offloading kind is specified, a translation specific for that
+ /// kind is performed, if any.
///
/// \param BoundArch - The bound architecture name, or 0.
- const llvm::opt::DerivedArgList &getArgsForToolChain(const ToolChain *TC,
- const char *BoundArch);
+ /// \param DeviceOffloadKind - The offload device kind that should be used in
+ /// the translation, if any.
+ const llvm::opt::DerivedArgList &
+ getArgsForToolChain(const ToolChain *TC, StringRef BoundArch,
+ Action::OffloadKind DeviceOffloadKind);
/// addTempFile - Add a file to remove on exit, and returns its
/// argument.
diff --git a/include/clang/Driver/Distro.h b/include/clang/Driver/Distro.h
new file mode 100644
index 000000000000..e2fb8b643350
--- /dev/null
+++ b/include/clang/Driver/Distro.h
@@ -0,0 +1,122 @@
+//===--- Distro.h - Linux distribution detection support --------*- 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_DRIVER_DISTRO_H
+#define LLVM_CLANG_DRIVER_DISTRO_H
+
+#include "clang/Basic/VirtualFileSystem.h"
+
+namespace clang {
+namespace driver {
+
+/// Distro - Helper class for detecting and classifying Linux distributions.
+///
+/// This class encapsulates the clang Linux distribution detection mechanism
+/// as well as helper functions that match the specific (versioned) results
+/// into wider distribution classes.
+class Distro {
+public:
+ enum DistroType {
+ // NB: Releases of a particular Linux distro should be kept together
+ // in this enum, because some tests are done by integer comparison against
+ // the first and last known member in the family, e.g. IsRedHat().
+ ArchLinux,
+ DebianLenny,
+ DebianSqueeze,
+ DebianWheezy,
+ DebianJessie,
+ DebianStretch,
+ Exherbo,
+ RHEL5,
+ RHEL6,
+ RHEL7,
+ Fedora,
+ OpenSUSE,
+ UbuntuHardy,
+ UbuntuIntrepid,
+ UbuntuJaunty,
+ UbuntuKarmic,
+ UbuntuLucid,
+ UbuntuMaverick,
+ UbuntuNatty,
+ UbuntuOneiric,
+ UbuntuPrecise,
+ UbuntuQuantal,
+ UbuntuRaring,
+ UbuntuSaucy,
+ UbuntuTrusty,
+ UbuntuUtopic,
+ UbuntuVivid,
+ UbuntuWily,
+ UbuntuXenial,
+ UbuntuYakkety,
+ UbuntuZesty,
+ UnknownDistro
+ };
+
+private:
+ /// The distribution, possibly with specific version.
+ DistroType DistroVal;
+
+public:
+ /// @name Constructors
+ /// @{
+
+ /// Default constructor leaves the distribution unknown.
+ Distro() : DistroVal() {}
+
+ /// Constructs a Distro type for specific distribution.
+ Distro(DistroType D) : DistroVal(D) {}
+
+ /// Detects the distribution using specified VFS.
+ explicit Distro(clang::vfs::FileSystem& VFS);
+
+ bool operator==(const Distro &Other) const {
+ return DistroVal == Other.DistroVal;
+ }
+
+ bool operator!=(const Distro &Other) const {
+ return DistroVal != Other.DistroVal;
+ }
+
+ bool operator>=(const Distro &Other) const {
+ return DistroVal >= Other.DistroVal;
+ }
+
+ bool operator<=(const Distro &Other) const {
+ return DistroVal <= Other.DistroVal;
+ }
+
+ /// @}
+ /// @name Convenience Predicates
+ /// @{
+
+ bool IsRedhat() const {
+ return DistroVal == Fedora || (DistroVal >= RHEL5 && DistroVal <= RHEL7);
+ }
+
+ bool IsOpenSUSE() const {
+ return DistroVal == OpenSUSE;
+ }
+
+ bool IsDebian() const {
+ return DistroVal >= DebianLenny && DistroVal <= DebianStretch;
+ }
+
+ bool IsUbuntu() const {
+ return DistroVal >= UbuntuHardy && DistroVal <= UbuntuZesty;
+ }
+
+ /// @}
+};
+
+} // end namespace driver
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Driver/Driver.h b/include/clang/Driver/Driver.h
index 9ecf434a87e2..0ce461ca61e1 100644
--- a/include/clang/Driver/Driver.h
+++ b/include/clang/Driver/Driver.h
@@ -12,21 +12,20 @@
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/LLVM.h"
+#include "clang/Driver/Action.h"
#include "clang/Driver/Phases.h"
#include "clang/Driver/Types.h"
#include "clang/Driver/Util.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/Support/Path.h" // FIXME: Kill when CompilationInfo lands.
#include <list>
#include <map>
-#include <memory>
-#include <set>
#include <string>
namespace llvm {
+class Triple;
+
namespace opt {
class Arg;
class ArgList;
@@ -44,7 +43,6 @@ class FileSystem;
namespace driver {
- class Action;
class Command;
class Compilation;
class InputInfo;
@@ -93,6 +91,26 @@ class Driver {
LTOKind LTOMode;
public:
+ enum OpenMPRuntimeKind {
+ /// An unknown OpenMP runtime. We can't generate effective OpenMP code
+ /// without knowing what runtime to target.
+ OMPRT_Unknown,
+
+ /// The LLVM OpenMP runtime. When completed and integrated, this will become
+ /// the default for Clang.
+ OMPRT_OMP,
+
+ /// The GNU OpenMP runtime. Clang doesn't support generating OpenMP code for
+ /// this runtime but can swallow the pragmas, and find and link against the
+ /// runtime library itself.
+ OMPRT_GOMP,
+
+ /// The legacy name for the LLVM OpenMP runtime from when it was the Intel
+ /// OpenMP runtime. We support this mode for users with existing
+ /// dependencies on this runtime library name.
+ OMPRT_IOMP5
+ };
+
// Diag - Forwarding function for diagnostics.
DiagnosticBuilder Diag(unsigned DiagID) const {
return Diags.Report(DiagID);
@@ -132,9 +150,6 @@ public:
/// If the standard library is used
bool UseStdLib;
- /// Default target triple.
- std::string DefaultTargetTriple;
-
/// Driver title to use with help.
std::string DriverTitle;
@@ -160,6 +175,9 @@ public:
/// Whether the driver is just the preprocessor.
bool CCCIsCPP() const { return Mode == CPPMode; }
+ /// Whether the driver should follow gcc like behavior.
+ bool CCCIsCC() const { return Mode == GCCMode; }
+
/// Whether the driver should follow cl.exe like behavior.
bool IsCLMode() const { return Mode == CLMode; }
@@ -183,6 +201,9 @@ public:
unsigned CCGenDiagnostics : 1;
private:
+ /// Default target triple.
+ std::string DefaultTargetTriple;
+
/// Name to use when invoking gcc/g++.
std::string CCCGenericGCCName;
@@ -222,9 +243,23 @@ private:
// Before executing jobs, sets up response files for commands that need them.
void setUpResponseFiles(Compilation &C, Command &Cmd);
- void generatePrefixedToolNames(const char *Tool, const ToolChain &TC,
+ void generatePrefixedToolNames(StringRef Tool, const ToolChain &TC,
SmallVectorImpl<std::string> &Names) const;
+ /// \brief 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.
+ ///
+ /// \param ReproCrashFilename The file path to copy the .crash to.
+ /// \param CrashDiagDir The suggested directory for the user to look at
+ /// in case the search or copy fails.
+ ///
+ /// \returns If the .crash is found and successfully copied return true,
+ /// otherwise false and return the suggested directory in \p CrashDiagDir.
+ bool getCrashDiagnosticFile(StringRef ReproCrashFilename,
+ SmallString<128> &CrashDiagDir);
+
public:
Driver(StringRef ClangExecutable, StringRef DefaultTargetTriple,
DiagnosticsEngine &Diags,
@@ -268,8 +303,17 @@ public:
bool isSaveTempsEnabled() const { return SaveTemps != SaveTempsNone; }
bool isSaveTempsObj() const { return SaveTemps == SaveTempsObj; }
- bool embedBitcodeEnabled() const { return BitcodeEmbed == EmbedBitcode; }
- bool embedBitcodeMarkerOnly() const { return BitcodeEmbed == EmbedMarker; }
+ bool embedBitcodeEnabled() const { return BitcodeEmbed != EmbedNone; }
+ bool embedBitcodeInObject() const {
+ // LTO has no object file output so ignore embed bitcode option in LTO.
+ return (BitcodeEmbed == EmbedBitcode) && !isUsingLTO();
+ }
+ bool embedBitcodeMarkerOnly() const {
+ return (BitcodeEmbed == EmbedMarker) && !isUsingLTO();
+ }
+
+ /// Compute the desired OpenMP runtime from the flags provided.
+ OpenMPRuntimeKind getOpenMPRuntime(const llvm::opt::ArgList &Args) const;
/// @}
/// @name Primary Functionality
@@ -293,7 +337,7 @@ public:
/// @{
/// ParseDriverMode - Look for and handle the driver mode option in Args.
- void ParseDriverMode(ArrayRef<const char *> Args);
+ void ParseDriverMode(StringRef ProgramName, ArrayRef<const char *> Args);
/// ParseArgStrings - Parse the given list of strings into an
/// ArgList.
@@ -340,7 +384,7 @@ public:
/// up response files, removing temporary files, etc.
int ExecuteCompilation(Compilation &C,
SmallVectorImpl< std::pair<int, const Command *> > &FailingCommands);
-
+
/// generateCompilationDiagnostics - Generate diagnostics information
/// including preprocessed source file(s).
///
@@ -368,7 +412,7 @@ public:
/// directories to search.
//
// FIXME: This should be in CompilationInfo.
- std::string GetFilePath(const char *Name, const ToolChain &TC) const;
+ std::string GetFilePath(StringRef Name, const ToolChain &TC) const;
/// GetProgramPath - Lookup \p Name in the list of program search paths.
///
@@ -376,7 +420,7 @@ public:
/// directories to search.
//
// FIXME: This should be in CompilationInfo.
- std::string GetProgramPath(const char *Name, const ToolChain &TC) const;
+ std::string GetProgramPath(StringRef Name, const ToolChain &TC) const;
/// HandleImmediateArgs - Handle any arguments which should be
/// treated before building actions or binding tools.
@@ -393,14 +437,14 @@ public:
/// 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
- /// jobs for a given (Action, ToolChain, BoundArch) tuple once.
+ /// jobs for a given (Action, ToolChain, BoundArch, DeviceKind) tuple once.
InputInfo
BuildJobsForAction(Compilation &C, const Action *A, const ToolChain *TC,
- const char *BoundArch, bool AtTopLevel, bool MultipleArchs,
+ StringRef BoundArch, bool AtTopLevel, bool MultipleArchs,
const char *LinkingOutput,
std::map<std::pair<const Action *, std::string>, InputInfo>
&CachedResults,
- bool BuildForOffloadDevice) const;
+ Action::OffloadKind TargetDeviceOffloadKind) const;
/// Returns the default name for linked images (e.g., "a.out").
const char *getDefaultImageName() const;
@@ -418,7 +462,7 @@ public:
/// \param MultipleArchs - Whether multiple -arch options were supplied.
/// \param NormalizedTriple - The normalized triple of the relevant target.
const char *GetNamedOutputPath(Compilation &C, const JobAction &JA,
- const char *BaseInput, const char *BoundArch,
+ const char *BaseInput, StringRef BoundArch,
bool AtTopLevel, bool MultipleArchs,
StringRef NormalizedTriple) const;
@@ -426,7 +470,7 @@ public:
/// as part of compilation; the file will have the given prefix and suffix.
///
/// GCC goes to extra lengths here to be a bit more robust.
- std::string GetTemporaryPath(StringRef Prefix, const char *Suffix) const;
+ std::string GetTemporaryPath(StringRef Prefix, StringRef Suffix) const;
/// Return the pathname of the pch file in clang-cl mode.
std::string GetClPchPath(Compilation &C, StringRef BaseName) const;
@@ -442,6 +486,10 @@ public:
LTOKind getLTOMode() const { return LTOMode; }
private:
+ /// Set the driver mode (cl, gcc, etc) from an option string of the form
+ /// --driver-mode=<mode>.
+ void setDriverModeFromOption(StringRef Opt);
+
/// Parse the \p Args list for LTO options and record the type of LTO
/// compilation based on which -f(no-)?lto(=.*)? option occurs last.
void setLTOMode(const llvm::opt::ArgList &Args);
@@ -463,12 +511,11 @@ private:
/// jobs specifically for the given action, but will use the cache when
/// building jobs for the Action's inputs.
InputInfo BuildJobsForActionNoCache(
- Compilation &C, const Action *A, const ToolChain *TC,
- const char *BoundArch, bool AtTopLevel, bool MultipleArchs,
- const char *LinkingOutput,
+ Compilation &C, const Action *A, const ToolChain *TC, StringRef BoundArch,
+ bool AtTopLevel, bool MultipleArchs, const char *LinkingOutput,
std::map<std::pair<const Action *, std::string>, InputInfo>
&CachedResults,
- bool BuildForOffloadDevice) const;
+ Action::OffloadKind TargetDeviceOffloadKind) const;
public:
/// GetReleaseVersion - Parse (([0-9]+)(.([0-9]+)(.([0-9]+)?))?)? and
@@ -478,9 +525,8 @@ public:
/// \return True if the entire string was parsed (9.2), or all
/// groups were parsed (10.3.5extrastuff). HadExtra is true if all
/// groups were parsed but extra characters remain at the end.
- static bool GetReleaseVersion(const char *Str, unsigned &Major,
- unsigned &Minor, unsigned &Micro,
- bool &HadExtra);
+ static bool GetReleaseVersion(StringRef Str, unsigned &Major, unsigned &Minor,
+ unsigned &Micro, bool &HadExtra);
/// Parse digits from a string \p Str and fulfill \p Digits with
/// the parsed numbers. This method assumes that the max number of
@@ -488,7 +534,7 @@ public:
///
/// \return True if the entire string was parsed and there are
/// no extra characters remaining at the end.
- static bool GetReleaseVersion(const char *Str,
+ static bool GetReleaseVersion(StringRef Str,
MutableArrayRef<unsigned> Digits);
};
diff --git a/include/clang/Driver/Job.h b/include/clang/Driver/Job.h
index 3366fc48d711..54bed09e0adf 100644
--- a/include/clang/Driver/Job.h
+++ b/include/clang/Driver/Job.h
@@ -116,7 +116,7 @@ public:
const llvm::opt::ArgStringList &getArguments() const { return Arguments; }
/// Print a command argument, and optionally quote it.
- static void printArg(llvm::raw_ostream &OS, const char *Arg, bool Quote);
+ static void printArg(llvm::raw_ostream &OS, StringRef Arg, bool Quote);
};
/// Like Command, but with a fallback which is executed in case
@@ -175,6 +175,7 @@ public:
const list_type &getJobs() const { return Jobs; }
+ bool empty() const { return Jobs.empty(); }
size_type size() const { return Jobs.size(); }
iterator begin() { return Jobs.begin(); }
const_iterator begin() const { return Jobs.begin(); }
diff --git a/include/clang/Driver/Multilib.h b/include/clang/Driver/Multilib.h
index 6b54d72d7c49..0419186b745d 100644
--- a/include/clang/Driver/Multilib.h
+++ b/include/clang/Driver/Multilib.h
@@ -12,7 +12,6 @@
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/Triple.h"
#include "llvm/Option/Option.h"
#include <functional>
#include <string>
diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td
index d03ab0435a6e..1f1222e10636 100644
--- a/include/clang/Driver/Options.td
+++ b/include/clang/Driver/Options.td
@@ -266,6 +266,8 @@ def MF : JoinedOrSeparate<["-"], "MF">, Group<M_Group>,
MetaVarName<"<file>">;
def MG : Flag<["-"], "MG">, Group<M_Group>, Flags<[CC1Option]>,
HelpText<"Add missing headers to depfile">;
+def MJ : JoinedOrSeparate<["-"], "MJ">, Group<M_Group>,
+ HelpText<"Write a compilation database entry per input">;
def MP : Flag<["-"], "MP">, Group<M_Group>, Flags<[CC1Option]>,
HelpText<"Create phony target for each dependency (other than main file)">;
def MQ : JoinedOrSeparate<["-"], "MQ">, Group<M_Group>, Flags<[CC1Option]>,
@@ -389,6 +391,8 @@ def cl_std_EQ : Joined<["-"], "cl-std=">, Group<opencl_Group>, Flags<[CC1Option]
HelpText<"OpenCL language standard to compile for.">;
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 client__name : JoinedOrSeparate<["-"], "client_name">;
def combine : Flag<["-", "--"], "combine">, Flags<[DriverOption, Unsupported]>;
def compatibility__version : JoinedOrSeparate<["-"], "compatibility_version">;
@@ -410,6 +414,9 @@ def cuda_compile_host_device : Flag<["--"], "cuda-compile-host-device">,
"effect on non-CUDA compilations.">;
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 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.">;
def cuda_noopt_device_debug : Flag<["--"], "cuda-noopt-device-debug">,
HelpText<"Enable device-side debug info generation. Disables ptxas optimizations.">;
def no_cuda_version_check : Flag<["--"], "no-cuda-version-check">,
@@ -418,6 +425,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 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">,
Flags<[CC1Option]>, HelpText<"Flush denormal floating point values to zero in CUDA device mode.">;
def fno_cuda_flush_denormals_to_zero : Flag<["-"], "fno-cuda-flush-denormals-to-zero">;
@@ -427,6 +436,8 @@ def fno_cuda_approx_transcendentals : Flag<["-"], "fno-cuda-approx-transcendenta
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">;
+def dI : Flag<["-"], "dI">, Group<d_Group>, Flags<[CC1Option]>,
+ HelpText<"Print include directives in -E mode in addition to normal output">;
def dM : Flag<["-"], "dM">, Group<d_Group>, Flags<[CC1Option]>,
HelpText<"Print macro definitions in -E mode instead of normal output">;
def dead__strip : Flag<["-"], "dead_strip">;
@@ -479,6 +490,13 @@ def fno_autolink : Flag <["-"], "fno-autolink">, Group<f_Group>,
Flags<[DriverOption, CC1Option]>,
HelpText<"Disable generation of linker directives for automatic library linking">;
+// C++ Coroutines TS
+def fcoroutines_ts : Flag <["-"], "fcoroutines-ts">, Group<f_Group>,
+ Flags<[DriverOption, CC1Option]>,
+ HelpText<"Enable support for the C++ Coroutines TS">;
+def fno_coroutines_ts : Flag <["-"], "fno-coroutines-ts">, Group<f_Group>,
+ Flags<[DriverOption]>;
+
def fembed_bitcode_EQ : Joined<["-"], "fembed-bitcode=">,
Group<f_Group>, Flags<[DriverOption, CC1Option]>, MetaVarName<"<option>">,
HelpText<"Embed LLVM bitcode (option: off, all, bitcode, marker)">;
@@ -499,15 +517,15 @@ def fprofile_sample_use_EQ : Joined<["-"], "fprofile-sample-use=">,
def fauto_profile_EQ : Joined<["-"], "fauto-profile=">,
Alias<fprofile_sample_use_EQ>;
def fprofile_instr_generate : Flag<["-"], "fprofile-instr-generate">,
- Group<f_Group>, Flags<[DriverOption]>,
+ Group<f_Group>, Flags<[CoreOption]>,
HelpText<"Generate instrumented code to collect execution counts into default.profraw file (overriden by '=' form of option or LLVM_PROFILE_FILE env var)">;
def fprofile_instr_generate_EQ : Joined<["-"], "fprofile-instr-generate=">,
- Group<f_Group>, Flags<[DriverOption]>, MetaVarName<"<file>">,
+ Group<f_Group>, Flags<[CoreOption]>, MetaVarName<"<file>">,
HelpText<"Generate instrumented code to collect execution counts into <file> (overridden by LLVM_PROFILE_FILE env var)">;
def fprofile_instr_use : Flag<["-"], "fprofile-instr-use">, Group<f_Group>,
- Flags<[DriverOption]>;
+ Flags<[CoreOption]>;
def fprofile_instr_use_EQ : Joined<["-"], "fprofile-instr-use=">,
- Group<f_Group>, Flags<[DriverOption]>,
+ Group<f_Group>, Flags<[CoreOption]>,
HelpText<"Use instrumentation data for profile-guided optimization">;
def fcoverage_mapping : Flag<["-"], "fcoverage-mapping">,
Group<f_Group>, Flags<[CC1Option]>,
@@ -544,6 +562,8 @@ 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_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>;
def fclasspath_EQ : Joined<["-"], "fclasspath=">, Group<f_Group>;
def fcolor_diagnostics : Flag<["-"], "fcolor-diagnostics">, Group<f_Group>,
@@ -581,6 +601,8 @@ def fdiagnostics_parseable_fixits : Flag<["-"], "fdiagnostics-parseable-fixits">
def fdiagnostics_print_source_range_info : Flag<["-"], "fdiagnostics-print-source-range-info">,
Group<f_clang_Group>, Flags<[CC1Option]>,
HelpText<"Print source range spans in numeric form">;
+def fdiagnostics_show_hotness : Flag<["-"], "fdiagnostics-show-hotness">, Group<f_Group>,
+ Flags<[CC1Option]>, HelpText<"Enable profile hotness information in diagnostic line">;
def fdiagnostics_show_option : Flag<["-"], "fdiagnostics-show-option">, Group<f_Group>,
Flags<[CC1Option]>, HelpText<"Print option name with mappable diagnostics">;
def fdiagnostics_show_note_include_stack : Flag<["-"], "fdiagnostics-show-note-include-stack">,
@@ -624,6 +646,7 @@ def : Flag<["-"], "fno-defer-pop">, Group<clang_ignored_gcc_optimization_f_Group
def : Flag<["-"], "fextended-identifiers">, Group<clang_ignored_f_Group>;
def : Flag<["-"], "fno-extended-identifiers">, Group<f_Group>, Flags<[Unsupported]>;
def fhosted : Flag<["-"], "fhosted">, Group<f_Group>;
+def fdenormal_fp_math_EQ : Joined<["-"], "fdenormal-fp-math=">, Group<f_Group>, Flags<[CC1Option]>;
def ffast_math : Flag<["-"], "ffast-math">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Allow aggressive, lossy floating-point optimizations">;
def fno_fast_math : Flag<["-"], "fno-fast-math">, Group<f_Group>;
@@ -675,6 +698,9 @@ def fsanitize_address_field_padding : Joined<["-"], "fsanitize-address-field-pad
def fsanitize_address_use_after_scope : Flag<["-"], "fsanitize-address-use-after-scope">,
Group<f_clang_Group>, Flags<[CC1Option]>,
HelpText<"Enable use-after-scope detection in AddressSanitizer">;
+def fno_sanitize_address_use_after_scope : Flag<["-"], "fno-sanitize-address-use-after-scope">,
+ Group<f_clang_Group>, Flags<[CC1Option]>,
+ HelpText<"Disable use-after-scope detection in AddressSanitizer">;
def fsanitize_recover : Flag<["-"], "fsanitize-recover">, Group<f_clang_Group>,
Flags<[CoreOption]>;
def fno_sanitize_recover : Flag<["-"], "fno-sanitize-recover">,
@@ -711,6 +737,24 @@ def fsanitize_stats : Flag<["-"], "fsanitize-stats">,
def fno_sanitize_stats : Flag<["-"], "fno-sanitize-stats">,
Group<f_clang_Group>, Flags<[CC1Option]>,
HelpText<"Disable sanitizer statistics gathering.">;
+def fsanitize_thread_memory_access : Flag<["-"], "fsanitize-thread-memory-access">,
+ Group<f_clang_Group>,
+ HelpText<"Enable memory access instrumentation in ThreadSanitizer (default)">;
+def fno_sanitize_thread_memory_access : Flag<["-"], "fno-sanitize-thread-memory-access">,
+ Group<f_clang_Group>,
+ HelpText<"Disable memory access instrumentation in ThreadSanitizer">;
+def fsanitize_thread_func_entry_exit : Flag<["-"], "fsanitize-thread-func-entry-exit">,
+ Group<f_clang_Group>,
+ HelpText<"Enable function entry/exit instrumentation in ThreadSanitizer (default)">;
+def fno_sanitize_thread_func_entry_exit : Flag<["-"], "fno-sanitize-thread-func-entry-exit">,
+ Group<f_clang_Group>,
+ HelpText<"Disable function entry/exit instrumentation in ThreadSanitizer">;
+def fsanitize_thread_atomics : Flag<["-"], "fsanitize-thread-atomics">,
+ Group<f_clang_Group>,
+ HelpText<"Enable atomic operations instrumentation in ThreadSanitizer (default)">;
+def fno_sanitize_thread_atomics : Flag<["-"], "fno-sanitize-thread-atomics">,
+ Group<f_clang_Group>,
+ HelpText<"Disable atomic operations instrumentation in ThreadSanitizer">;
def fsanitize_undefined_strip_path_components_EQ : Joined<["-"], "fsanitize-undefined-strip-path-components=">,
Group<f_clang_Group>, Flags<[CC1Option]>, MetaVarName<"<number>">,
HelpText<"Strip (or keep only, if negative) a given number of path components "
@@ -738,8 +782,8 @@ def fno_honor_infinities : Flag<["-"], "fno-honor-infinities">, Group<f_Group>;
// This option was originally misspelt "infinites" [sic].
def : Flag<["-"], "fhonor-infinites">, Alias<fhonor_infinities>;
def : Flag<["-"], "fno-honor-infinites">, Alias<fno_honor_infinities>;
-def ftrapping_math : Flag<["-"], "ftrapping-math">, Group<f_Group>;
-def fno_trapping_math : Flag<["-"], "fno-trapping-math">, Group<f_Group>;
+def ftrapping_math : Flag<["-"], "ftrapping-math">, Group<f_Group>, Flags<[CC1Option]>;
+def fno_trapping_math : Flag<["-"], "fno-trapping-math">, Group<f_Group>, Flags<[CC1Option]>;
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)">;
@@ -779,6 +823,9 @@ 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 wich are (explicitly or implicitly) marked inline">;
def finline : Flag<["-"], "finline">, Group<clang_ignored_f_Group>;
+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.">;
def finput_charset_EQ : Joined<["-"], "finput-charset=">, Group<f_Group>;
def fexec_charset_EQ : Joined<["-"], "fexec-charset=">, Group<f_Group>;
def finstrument_functions : Flag<["-"], "finstrument-functions">, Group<f_Group>, Flags<[CC1Option]>,
@@ -803,10 +850,15 @@ def flax_vector_conversions : Flag<["-"], "flax-vector-conversions">, Group<f_Gr
def flimited_precision_EQ : Joined<["-"], "flimited-precision=">, Group<f_Group>;
def flto_EQ : Joined<["-"], "flto=">, Flags<[CC1Option]>, Group<f_Group>,
HelpText<"Set LTO mode to either 'full' or 'thin'">;
-def flto : Flag<["-"], "flto">, Flags<[CC1Option]>, Group<f_Group>,
+def flto : Flag<["-"], "flto">, Flags<[CoreOption, CC1Option]>, Group<f_Group>,
HelpText<"Enable LTO in 'full' mode">;
def fno_lto : Flag<["-"], "fno-lto">, Group<f_Group>,
HelpText<"Disable LTO mode (default)">;
+def flto_jobs_EQ : Joined<["-"], "flto-jobs=">,
+ Flags<[CC1Option]>, Group<f_Group>,
+ HelpText<"Controls the backend parallelism of -flto=thin (default "
+ "of 0 means the number of threads will be derived from "
+ "the number of CPUs detected)">;
def fthinlto_index_EQ : Joined<["-"], "fthinlto-index=">,
Flags<[CC1Option]>, Group<f_Group>,
HelpText<"Perform ThinLTO importing using provided function summary index">;
@@ -838,6 +890,9 @@ def fmodules_cache_path : Joined<["-"], "fmodules-cache-path=">, Group<i_Group>,
def fmodules_user_build_path : Separate<["-"], "fmodules-user-build-path">, Group<i_Group>,
Flags<[DriverOption, CC1Option]>, MetaVarName<"<directory>">,
HelpText<"Specify the module user build path">;
+def fprebuilt_module_path : Joined<["-"], "fprebuilt-module-path=">, Group<i_Group>,
+ Flags<[DriverOption, CC1Option]>, MetaVarName<"<directory>">,
+ HelpText<"Specify the prebuilt module path">;
def fmodules_prune_interval : Joined<["-"], "fmodules-prune-interval=">, Group<i_Group>,
Flags<[CC1Option]>, MetaVarName<"<seconds>">,
HelpText<"Specify the interval (in seconds) between attempts to prune the module cache">;
@@ -857,6 +912,9 @@ def fmodules_validate_once_per_build_session : Flag<["-"], "fmodules-validate-on
Group<i_Group>, Flags<[CC1Option]>,
HelpText<"Don't verify input files for the modules if the module has been "
"successfully validated or loaded during this build session">;
+def fmodules_disable_diagnostic_validation : Flag<["-"], "fmodules-disable-diagnostic-validation">,
+ Group<i_Group>, Flags<[CC1Option]>,
+ HelpText<"Disable validation of the diagnostic options when loading the module">;
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">;
@@ -866,6 +924,8 @@ def fmodules : Flag <["-"], "fmodules">, Group<f_Group>,
def fimplicit_module_maps : Flag <["-"], "fimplicit-module-maps">, Group<f_Group>,
Flags<[DriverOption, CC1Option]>,
HelpText<"Implicitly search the file system for module map files.">;
+def fmodules_ts : Flag <["-"], "fmodules-ts">, Group<f_Group>,
+ Flags<[CC1Option]>, HelpText<"Enable support for the C++ Modules TS">;
def fmodule_maps : Flag <["-"], "fmodule-maps">, Alias<fimplicit_module_maps>;
def fmodule_name_EQ : Joined<["-"], "fmodule-name=">, Group<f_Group>,
Flags<[DriverOption,CC1Option]>, MetaVarName<"<name>">,
@@ -928,6 +988,7 @@ def fno_cxx_modules : Flag <["-"], "fno-cxx-modules">, Group<f_Group>,
Flags<[DriverOption]>;
def fno_diagnostics_fixit_info : Flag<["-"], "fno-diagnostics-fixit-info">, Group<f_Group>,
Flags<[CC1Option]>, HelpText<"Do not include fixit information in diagnostics">;
+def fno_diagnostics_show_hotness : Flag<["-"], "fno-diagnostics-show-hotness">, Group<f_Group>;
def fno_diagnostics_show_option : Flag<["-"], "fno-diagnostics-show-option">, Group<f_Group>;
def fno_diagnostics_show_note_include_stack : Flag<["-"], "fno-diagnostics-show-note-include-stack">,
Flags<[CC1Option]>, Group<f_Group>;
@@ -942,6 +1003,9 @@ 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_new_pass_manager : Flag<["-"], "fno-experimental-new-pass-manager">,
+ Group<f_clang_Group>, Flags<[CC1Option]>,
+ HelpText<"Disables an experimental new pass manager in LLVM.">;
def fveclib : Joined<["-"], "fveclib=">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Use the given vector functions library">;
def fno_lax_vector_conversions : Flag<["-"], "fno-lax-vector-conversions">, Group<f_Group>,
@@ -983,6 +1047,8 @@ def fno_show_column : Flag<["-"], "fno-show-column">, Group<f_Group>, Flags<[CC1
HelpText<"Do not include column number on diagnostics">;
def fno_show_source_location : Flag<["-"], "fno-show-source-location">, Group<f_Group>,
Flags<[CC1Option]>, HelpText<"Do not include source location information with diagnostics">;
+def fdiagnostics_absolute_paths : Flag<["-"], "fdiagnostics-absolute-paths">, Group<f_Group>,
+ Flags<[CC1Option, CoreOption]>, HelpText<"Print absolute paths in diagnostics">;
def fno_spell_checking : Flag<["-"], "fno-spell-checking">, Group<f_Group>,
Flags<[CC1Option]>, HelpText<"Disable spell-checking">;
def fno_stack_protector : Flag<["-"], "fno-stack-protector">, Group<f_Group>,
@@ -1022,14 +1088,26 @@ def fapplication_extension : Flag<["-"], "fapplication-extension">,
HelpText<"Restrict code to those available for App Extensions">;
def fno_application_extension : Flag<["-"], "fno-application-extension">,
Group<f_Group>;
+def frelaxed_template_template_args : Flag<["-"], "frelaxed-template-template-args">,
+ Flags<[CC1Option]>, HelpText<"Enable C++17 relaxed template template argument matching">,
+ Group<f_Group>;
+def fno_relaxed_template_template_args : Flag<["-"], "fno-relaxed-template-template-args">,
+ Group<f_Group>;
def fsized_deallocation : Flag<["-"], "fsized-deallocation">, Flags<[CC1Option]>,
HelpText<"Enable C++14 sized global deallocation functions">, Group<f_Group>;
def fno_sized_deallocation: Flag<["-"], "fno-sized-deallocation">, Group<f_Group>;
+def faligned_allocation : Flag<["-"], "faligned-allocation">, Flags<[CC1Option]>,
+ HelpText<"Enable C++17 aligned allocation functions">, Group<f_Group>;
+def fno_aligned_allocation: Flag<["-"], "fno-aligned-allocation">,
+ Group<f_Group>, Flags<[CC1Option]>;
+def fnew_alignment_EQ : Joined<["-"], "fnew-alignment=">,
+ HelpText<"Specifies the largest alignment guaranteed by '::operator new(size_t)'">,
+ MetaVarName<"<align>">, Group<f_Group>, Flags<[CC1Option]>;
+def : Separate<["-"], "fnew-alignment">, Alias<fnew_alignment_EQ>;
+def : Flag<["-"], "faligned-new">, Alias<faligned_allocation>;
+def : Flag<["-"], "fno-aligned-new">, Alias<fno_aligned_allocation>;
+def faligned_new_EQ : Joined<["-"], "faligned-new=">;
-def fobjc_gc_only : Flag<["-"], "fobjc-gc-only">, Group<f_Group>, Flags<[CC1Option]>,
- HelpText<"Use GC exclusively for Objective-C related memory management">;
-def fobjc_gc : Flag<["-"], "fobjc-gc">, Group<f_Group>, Flags<[CC1Option]>,
- HelpText<"Enable Objective-C garbage collection">;
def fobjc_legacy_dispatch : Flag<["-"], "fobjc-legacy-dispatch">, Group<f_Group>;
def fobjc_new_property : Flag<["-"], "fobjc-new-property">, Group<clang_ignored_f_Group>;
def fobjc_infer_related_result_type : Flag<["-"], "fobjc-infer-related-result-type">,
@@ -1061,6 +1139,8 @@ def fopenmp_use_tls : Flag<["-"], "fopenmp-use-tls">, Group<f_Group>, Flags<[NoA
def fnoopenmp_use_tls : Flag<["-"], "fnoopenmp-use-tls">, Group<f_Group>, Flags<[CC1Option, NoArgumentUnused]>;
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 fno_optimize_sibling_calls : Flag<["-"], "fno-optimize-sibling-calls">, Group<f_Group>;
def foptimize_sibling_calls : Flag<["-"], "foptimize-sibling-calls">, Group<f_Group>;
def force__cpusubtype__ALL : Flag<["-"], "force_cpusubtype_ALL">;
@@ -1084,8 +1164,15 @@ def fpic : Flag<["-"], "fpic">, Group<f_Group>;
def fno_pic : Flag<["-"], "fno-pic">, Group<f_Group>;
def fpie : Flag<["-"], "fpie">, Group<f_Group>;
def fno_pie : Flag<["-"], "fno-pie">, Group<f_Group>;
+def fropi : Flag<["-"], "fropi">, Group<f_Group>;
+def fno_ropi : Flag<["-"], "fno-ropi">, Group<f_Group>;
+def frwpi : Flag<["-"], "frwpi">, Group<f_Group>;
+def fno_rwpi : Flag<["-"], "fno-rwpi">, Group<f_Group>;
def fplugin_EQ : Joined<["-"], "fplugin=">, Group<f_Group>, Flags<[DriverOption]>, MetaVarName<"<dsopath>">,
HelpText<"Load the named plugin (dynamic shared object)">;
+def fpreserve_as_comments : Flag<["-"], "fpreserve-as-comments">, Group<f_Group>;
+def fno_preserve_as_comments : Flag<["-"], "fno-preserve-as-comments">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Do not preserve comments in inline assembly">;
def fprofile_arcs : Flag<["-"], "fprofile-arcs">, Group<f_Group>;
def fno_profile_arcs : Flag<["-"], "fno-profile-arcs">, Group<f_Group>;
def framework : Separate<["-"], "framework">, Flags<[LinkerInput]>;
@@ -1118,12 +1205,12 @@ def fstack_protector_strong : Flag<["-"], "fstack-protector-strong">, Group<f_Gr
HelpText<"Use a strong heuristic to apply stack protectors to functions">;
def fstack_protector : Flag<["-"], "fstack-protector">, Group<f_Group>,
HelpText<"Enable stack protectors for functions potentially vulnerable to stack smashing">;
-def fstandalone_debug : Flag<["-"], "fstandalone-debug">, Group<f_Group>,
+def fstandalone_debug : Flag<["-"], "fstandalone-debug">, Group<f_Group>, Flags<[CoreOption]>,
HelpText<"Emit full debug info for all types used by the program">;
-def fno_standalone_debug : Flag<["-"], "fno-standalone-debug">, Group<f_Group>,
+def fno_standalone_debug : Flag<["-"], "fno-standalone-debug">, Group<f_Group>, Flags<[CoreOption]>,
HelpText<"Limit debug information produced to reduce size of debug binary">;
-def flimit_debug_info : Flag<["-"], "flimit-debug-info">, Alias<fno_standalone_debug>;
-def fno_limit_debug_info : Flag<["-"], "fno-limit-debug-info">, Alias<fstandalone_debug>;
+def flimit_debug_info : Flag<["-"], "flimit-debug-info">, Flags<[CoreOption]>, Alias<fno_standalone_debug>;
+def fno_limit_debug_info : Flag<["-"], "fno-limit-debug-info">, Flags<[CoreOption]>, Alias<fstandalone_debug>;
def fstrict_aliasing : Flag<["-"], "fstrict-aliasing">, Group<f_Group>,
Flags<[DriverOption, CoreOption]>;
def fstrict_enums : Flag<["-"], "fstrict-enums">, Group<f_Group>, Flags<[CC1Option]>,
@@ -1143,6 +1230,15 @@ def ftemplate_backtrace_limit_EQ : Joined<["-"], "ftemplate-backtrace-limit=">,
Group<f_Group>;
def foperator_arrow_depth_EQ : Joined<["-"], "foperator-arrow-depth=">,
Group<f_Group>;
+
+def fsave_optimization_record : Flag<["-"], "fsave-optimization-record">,
+ Group<f_Group>, HelpText<"Generate a YAML optimization record file">;
+def fno_save_optimization_record : Flag<["-"], "fno-save-optimization-record">,
+ Group<f_Group>, Flags<[NoArgumentUnused]>;
+def foptimization_record_file_EQ : Joined<["-"], "foptimization-record-file=">,
+ Group<f_Group>,
+ HelpText<"Specify the file name of any generated YAML optimization record">;
+
def ftest_coverage : Flag<["-"], "ftest-coverage">, Group<f_Group>;
def fvectorize : Flag<["-"], "fvectorize">, Group<f_Group>,
HelpText<"Enable the loop vectorization passes">;
@@ -1240,6 +1336,10 @@ def fdebug_types_section: Flag <["-"], "fdebug-types-section">, Group<f_Group>,
Flags<[CC1Option]>, HelpText<"Place debug types in their own section (ELF Only)">;
def fno_debug_types_section: Flag<["-"], "fno-debug-types-section">, Group<f_Group>,
Flags<[CC1Option]>;
+def fsplit_dwarf_inlining: Flag <["-"], "fsplit-dwarf-inlining">, Group<f_Group>,
+ Flags<[CC1Option]>, HelpText<"Place debug types in their own section (ELF Only)">;
+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]>,
HelpText<"remap file source paths in debug info">;
@@ -1286,12 +1386,12 @@ def gno_record_gcc_switches : Flag<["-"], "gno-record-gcc-switches">,
Group<g_flags_Group>;
def gstrict_dwarf : Flag<["-"], "gstrict-dwarf">, Group<g_flags_Group>;
def gno_strict_dwarf : Flag<["-"], "gno-strict-dwarf">, Group<g_flags_Group>;
-def gcolumn_info : Flag<["-"], "gcolumn-info">, Group<g_flags_Group>;
-def gno_column_info : Flag<["-"], "gno-column-info">, Group<g_flags_Group>;
+def gcolumn_info : Flag<["-"], "gcolumn-info">, Group<g_flags_Group>, Flags<[CoreOption]>;
+def gno_column_info : Flag<["-"], "gno-column-info">, Group<g_flags_Group>, Flags<[CoreOption]>;
def gsplit_dwarf : Flag<["-"], "gsplit-dwarf">, Group<g_flags_Group>;
def ggnu_pubnames : Flag<["-"], "ggnu-pubnames">, Group<g_flags_Group>;
def gdwarf_aranges : Flag<["-"], "gdwarf-aranges">, Group<g_flags_Group>;
-def gmodules : Flag <["-"], "gmodules">, Group<f_Group>,
+def gmodules : Flag <["-"], "gmodules">, Group<gN_Group>,
HelpText<"Generate debug info with external references to clang modules"
" or precompiled headers">;
def headerpad__max__install__names : Joined<["-"], "headerpad_max_install_names">;
@@ -1364,6 +1464,16 @@ def malign_functions_EQ : Joined<["-"], "malign-functions=">, Group<clang_ignore
def malign_loops_EQ : Joined<["-"], "malign-loops=">, Group<clang_ignored_m_Group>;
def malign_jumps_EQ : Joined<["-"], "malign-jumps=">, Group<clang_ignored_m_Group>;
def mfancy_math_387 : Flag<["-"], "mfancy-math-387">, Group<clang_ignored_m_Group>;
+def mlong_calls : Flag<["-"], "mlong-calls">, Group<m_Group>,
+ HelpText<"Generate branches with extended addressability, usually via indirect jumps.">;
+def mno_long_calls : Flag<["-"], "mno-long-calls">, Group<m_Group>,
+ HelpText<"Restore the default behaviour of not generating long calls">;
+def mexecute_only : Flag<["-"], "mexecute-only">, Group<m_arm_Features_Group>,
+ HelpText<"Disallow generation of data access to code sections (ARM only)">;
+def mno_execute_only : Flag<["-"], "mno-execute-only">, Group<m_arm_Features_Group>,
+ HelpText<"Allow generation of data access to code sections (ARM only)">;
+def mpure_code : Flag<["-"], "mpure-code">, Alias<mexecute_only>; // Alias for GCC compatibility
+def mno_pure_code : Flag<["-"], "mno-pure-code">, Alias<mno_execute_only>;
def mtvos_version_min_EQ : Joined<["-"], "mtvos-version-min=">, Group<m_Group>;
def mappletvos_version_min_EQ : Joined<["-"], "mappletvos-version-min=">, Alias<mtvos_version_min_EQ>;
def mtvos_simulator_version_min_EQ : Joined<["-"], "mtvos-simulator-version-min=">, Alias<mtvos_version_min_EQ>;
@@ -1374,6 +1484,7 @@ def mwatchsimulator_version_min_EQ : Joined<["-"], "mwatchsimulator-version-min=
def march_EQ : Joined<["-"], "march=">, Group<m_Group>;
def masm_EQ : Joined<["-"], "masm=">, Group<m_Group>, Flags<[DriverOption]>;
def mcmodel_EQ : Joined<["-"], "mcmodel=">, Group<m_Group>;
+def mimplicit_it_EQ : Joined<["-"], "mimplicit-it=">, Group<m_Group>;
def mconstant_cfstrings : Flag<["-"], "mconstant-cfstrings">, Group<clang_ignored_m_Group>;
def mconsole : Joined<["-"], "mconsole">, Group<m_Group>, Flags<[DriverOption]>;
def mwindows : Joined<["-"], "mwindows">, Group<m_Group>, Flags<[DriverOption]>;
@@ -1507,10 +1618,6 @@ def mcrc : Flag<["-"], "mcrc">, Group<m_arm_Features_Group>,
HelpText<"Allow use of CRC instructions (ARM only)">;
def mnocrc : Flag<["-"], "mnocrc">, Group<m_arm_Features_Group>,
HelpText<"Disallow use of CRC instructions (ARM only)">;
-def mlong_calls : Flag<["-"], "mlong-calls">, Group<m_arm_Features_Group>,
- HelpText<"Generate an indirect jump to enable jumps further than 64M">;
-def mno_long_calls : Flag<["-"], "mno-long-calls">, Group<m_arm_Features_Group>,
- HelpText<"Restore the default behaviour of not generating long calls">;
def mgeneral_regs_only : Flag<["-"], "mgeneral-regs-only">, Group<m_aarch64_Features_Group>,
HelpText<"Generate code which only uses the general purpose registers (AArch64 only)">;
@@ -1539,6 +1646,10 @@ def mpower8_vector : Flag<["-"], "mpower8-vector">,
Group<m_ppc_Features_Group>;
def mno_power8_vector : Flag<["-"], "mno-power8-vector">,
Group<m_ppc_Features_Group>;
+def mpower9_vector : Flag<["-"], "mpower9-vector">,
+ Group<m_ppc_Features_Group>;
+def mno_power9_vector : Flag<["-"], "mno-power9-vector">,
+ Group<m_ppc_Features_Group>;
def mpower8_crypto : Flag<["-"], "mcrypto">,
Group<m_ppc_Features_Group>;
def mnopower8_crypto : Flag<["-"], "mno-crypto">,
@@ -1574,6 +1685,10 @@ def mfloat128: Flag<["-"], "mfloat128">,
Group<m_ppc_Features_Group>;
def mno_float128 : Flag<["-"], "mno-float128">,
Group<m_ppc_Features_Group>;
+def mlongcall: Flag<["-"], "mlongcall">,
+ Group<m_ppc_Features_Group>;
+def mno_longcall : Flag<["-"], "mno-longcall">,
+ Group<m_ppc_Features_Group>;
def faltivec : Flag<["-"], "faltivec">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Enable AltiVec vector initializer syntax">;
@@ -1620,6 +1735,10 @@ def mno_implicit_float : Flag<["-"], "mno-implicit-float">, Group<m_Group>,
def mimplicit_float : Flag<["-"], "mimplicit-float">, Group<m_Group>;
def mrecip : Flag<["-"], "mrecip">, Group<m_Group>;
def mrecip_EQ : CommaJoined<["-"], "mrecip=">, Group<m_Group>, Flags<[CC1Option]>;
+def mpie_copy_relocations : Flag<["-"], "mpie-copy-relocations">, Group<m_Group>,
+ Flags<[CC1Option]>,
+ HelpText<"Use copy relocations support for PIE builds">;
+def mno_pie_copy_relocations : Flag<["-"], "mno-pie-copy-relocations">, Group<m_Group>;
def mx87 : Flag<["-"], "mx87">, Group<m_x86_Features_Group>;
def m80387 : Flag<["-"], "m80387">, Alias<mx87>;
def msse2 : Flag<["-"], "msse2">, Group<m_x86_Features_Group>;
@@ -1754,7 +1873,8 @@ def mno_odd_spreg : Flag<["-"], "mno-odd-spreg">, Group<m_Group>,
Flags<[HelpHidden]>;
def mglibc : Flag<["-"], "mglibc">, Group<m_libc_Group>, Flags<[HelpHidden]>;
def muclibc : Flag<["-"], "muclibc">, Group<m_libc_Group>, Flags<[HelpHidden]>;
-def module_file_info : Flag<["-"], "module-file-info">, Flags<[DriverOption,CC1Option]>, Group<Action_Group>;
+def module_file_info : Flag<["-"], "module-file-info">, Flags<[DriverOption,CC1Option]>, Group<Action_Group>,
+ HelpText<"Provide information about a particular module file">;
def mthumb : Flag<["-"], "mthumb">, Group<m_Group>;
def mtune_EQ : Joined<["-"], "mtune=">, Group<m_Group>;
def multi__module : Flag<["-"], "multi_module">;
@@ -1802,7 +1922,8 @@ def print_file_name_EQ : Joined<["-", "--"], "print-file-name=">,
def print_ivar_layout : Flag<["-"], "print-ivar-layout">, Flags<[CC1Option]>,
HelpText<"Enable Objective-C Ivar layout bitmap print trace">;
def print_libgcc_file_name : Flag<["-", "--"], "print-libgcc-file-name">,
- HelpText<"Print the library path for \"libgcc.a\"">;
+ HelpText<"Print the library path for the currently used compiler runtime "
+ "library (\"libgcc.a\" or \"libclang_rt.builtins.*.a\")">;
def print_multi_directory : Flag<["-", "--"], "print-multi-directory">;
def print_multi_lib : Flag<["-", "--"], "print-multi-lib">;
def print_multi_os_directory : Flag<["-", "--"], "print-multi-os-directory">,
@@ -1828,16 +1949,22 @@ def rdynamic : Flag<["-"], "rdynamic">;
def resource_dir : Separate<["-"], "resource-dir">,
Flags<[DriverOption, CC1Option, CoreOption, HelpHidden]>,
HelpText<"The directory which holds the compiler resource files">;
-def resource_dir_EQ : Joined<["-"], "resource-dir=">, Flags<[DriverOption]>,
+def resource_dir_EQ : Joined<["-"], "resource-dir=">, Flags<[DriverOption, CoreOption]>,
Alias<resource_dir>;
def rpath : Separate<["-"], "rpath">, Flags<[LinkerInput]>;
-def rtlib_EQ : Joined<["-", "--"], "rtlib=">;
+def rtlib_EQ : Joined<["-", "--"], "rtlib=">,
+ HelpText<"Compiler runtime library to use">;
def r : Flag<["-"], "r">, Flags<[LinkerInput,NoArgumentUnused]>;
def save_temps_EQ : Joined<["-", "--"], "save-temps=">, Flags<[DriverOption]>,
HelpText<"Save intermediate compilation results.">;
def save_temps : Flag<["-", "--"], "save-temps">, Flags<[DriverOption]>,
Alias<save_temps_EQ>, AliasArgs<["cwd"]>,
HelpText<"Save intermediate compilation results">;
+def save_stats_EQ : Joined<["-", "--"], "save-stats=">, Flags<[DriverOption]>,
+ HelpText<"Save llvm statistics.">;
+def save_stats : Flag<["-", "--"], "save-stats">, Flags<[DriverOption]>,
+ Alias<save_stats_EQ>, AliasArgs<["cwd"]>,
+ HelpText<"Save llvm statistics.">;
def via_file_asm : Flag<["-", "--"], "via-file-asm">, InternalDebugOpt,
HelpText<"Write assembly to file for input to assemble jobs">;
def sectalign : MultiArg<["-"], "sectalign", 3>;
@@ -1940,7 +2067,8 @@ def _CLASSPATH : Separate<["--"], "CLASSPATH">, Alias<fclasspath_EQ>;
def _all_warnings : Flag<["--"], "all-warnings">, Alias<Wall>;
def _analyze_auto : Flag<["--"], "analyze-auto">, Flags<[DriverOption]>;
def _analyzer_no_default_checks : Flag<["--"], "analyzer-no-default-checks">, Flags<[DriverOption]>;
-def _analyzer_output : JoinedOrSeparate<["--"], "analyzer-output">, Flags<[DriverOption]>;
+def _analyzer_output : JoinedOrSeparate<["--"], "analyzer-output">, Flags<[DriverOption]>,
+ HelpText<"Static analyzer report output format (html|plist|plist-multi-file|plist-html|text).">;
def _analyze : Flag<["--"], "analyze">, Flags<[DriverOption, CoreOption]>,
HelpText<"Run the static analyzer">;
def _assemble : Flag<["--"], "assemble">, Alias<S>;
@@ -2004,6 +2132,8 @@ def _output_EQ : Joined<["--"], "output=">, Alias<o>;
def _output : Separate<["--"], "output">, Alias<o>;
def _param : Separate<["--"], "param">, Group<CompileOnly_Group>;
def _param_EQ : Joined<["--"], "param=">, Alias<_param>;
+def _precompile : Flag<["--"], "precompile">, Flags<[DriverOption]>,
+ Group<Action_Group>, HelpText<"Only precompile the input">;
def _prefix_EQ : Joined<["--"], "prefix=">, Alias<B>;
def _prefix : Separate<["--"], "prefix">, Alias<B>;
def _preprocess : Flag<["--"], "preprocess">, Alias<E>;
@@ -2086,9 +2216,9 @@ multiclass BooleanFFlag<string name> {
defm : BooleanFFlag<"keep-inline-functions">, Group<clang_ignored_gcc_optimization_f_Group>;
-def fprofile_dir : Joined<["-"], "fprofile-dir=">, Group<clang_ignored_gcc_optimization_f_Group>;
+def fprofile_dir : Joined<["-"], "fprofile-dir=">, Group<f_Group>;
-def fuse_ld_EQ : Joined<["-"], "fuse-ld=">, 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>;
diff --git a/include/clang/Driver/SanitizerArgs.h b/include/clang/Driver/SanitizerArgs.h
index 7b293e03d350..6206680118d5 100644
--- a/include/clang/Driver/SanitizerArgs.h
+++ b/include/clang/Driver/SanitizerArgs.h
@@ -38,6 +38,9 @@ class SanitizerArgs {
bool LinkCXXRuntimes = false;
bool NeedPIE = false;
bool Stats = false;
+ bool TsanMemoryAccess = true;
+ bool TsanFuncEntryExit = true;
+ bool TsanAtomics = true;
public:
/// Parses the sanitizer arguments from an argument list.
@@ -66,6 +69,7 @@ class SanitizerArgs {
bool requiresPIE() const;
bool needsUnwindTables() const;
bool linkCXXRuntimes() const { return LinkCXXRuntimes; }
+ bool hasCrossDsoCfi() const { return CfiCrossDso; }
void addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs, types::ID InputType) const;
};
diff --git a/include/clang/Driver/Tool.h b/include/clang/Driver/Tool.h
index b9eac1cad65d..5012cc896683 100644
--- a/include/clang/Driver/Tool.h
+++ b/include/clang/Driver/Tool.h
@@ -129,6 +129,20 @@ public:
const InputInfoList &Inputs,
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const = 0;
+ /// Construct jobs to perform the action \p JA, writing to the \p Outputs and
+ /// with \p Inputs, and add the jobs to \p C. The default implementation
+ /// assumes a single output and is expected to be overloaded for the tools
+ /// that support multiple inputs.
+ ///
+ /// \param TCArgs The argument list for this toolchain, with any
+ /// tool chain specific translations applied.
+ /// \param LinkingOutput If this output will eventually feed the
+ /// linker, then this is the final output name of the linked image.
+ virtual void ConstructJobMultipleOutputs(Compilation &C, const JobAction &JA,
+ const InputInfoList &Outputs,
+ const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const;
};
} // end namespace driver
diff --git a/include/clang/Driver/ToolChain.h b/include/clang/Driver/ToolChain.h
index 2a15d7ab061c..cca239c4be2a 100644
--- a/include/clang/Driver/ToolChain.h
+++ b/include/clang/Driver/ToolChain.h
@@ -18,7 +18,6 @@
#include "clang/Driver/Util.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Triple.h"
-#include "llvm/Support/Path.h"
#include "llvm/Target/TargetOptions.h"
#include <memory>
#include <string>
@@ -39,8 +38,10 @@ class FileSystem;
namespace driver {
class Compilation;
+ class CudaInstallationDetector;
class Driver;
class JobAction;
+ class RegisterEffectiveTriple;
class SanitizerArgs;
class Tool;
@@ -85,16 +86,25 @@ private:
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;
Tool *getClangAs() const;
+ Tool *getOffloadBundler() const;
mutable std::unique_ptr<SanitizerArgs> SanitizerArguments;
+ /// The effective clang triple for the current Job.
+ mutable llvm::Triple EffectiveTriple;
+
+ /// Set the toolchain's effective clang triple.
+ void setEffectiveTriple(llvm::Triple ET) const { EffectiveTriple = ET; }
+
+ friend class RegisterEffectiveTriple;
+
protected:
MultilibSet Multilibs;
- const char *DefaultLinker = "ld";
ToolChain(const Driver &D, const llvm::Triple &T,
const llvm::opt::ArgList &Args);
@@ -142,6 +152,12 @@ public:
return Triple.getTriple();
}
+ /// Get the toolchain's effective clang triple.
+ const llvm::Triple &getEffectiveTriple() const {
+ assert(!EffectiveTriple.getTriple().empty() && "No effective triple");
+ return EffectiveTriple;
+ }
+
path_list &getFilePaths() { return FilePaths; }
const path_list &getFilePaths() const { return FilePaths; }
@@ -176,12 +192,15 @@ public:
/// TranslateArgs - Create a new derived argument list for any argument
/// translations this ToolChain may wish to perform, or 0 if no tool chain
- /// specific translations are needed.
+ /// specific translations are needed. If \p DeviceOffloadKind is specified
+ /// the translation specific for that offload kind is performed.
///
/// \param BoundArch - The bound architecture name, or 0.
+ /// \param DeviceOffloadKind - The device offload kind used for the
+ /// translation.
virtual llvm::opt::DerivedArgList *
- TranslateArgs(const llvm::opt::DerivedArgList &Args,
- const char *BoundArch) const {
+ TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
+ Action::OffloadKind DeviceOffloadKind) const {
return nullptr;
}
@@ -219,7 +238,7 @@ public:
/// LookupTypeForExtension - Return the default language type to use for the
/// given extension.
- virtual types::ID LookupTypeForExtension(const char *Ext) const;
+ virtual types::ID LookupTypeForExtension(StringRef Ext) const;
/// IsBlocksDefault - Does this tool chain enable -fblocks by default.
virtual bool IsBlocksDefault() const { return false; }
@@ -252,6 +271,11 @@ public:
return 0;
}
+ /// GetDefaultLinker - Get the default linker to use.
+ virtual const char *getDefaultLinker() const {
+ return "ld";
+ }
+
/// GetDefaultRuntimeLibType - Get the default runtime library variant to use.
virtual RuntimeLibType GetDefaultRuntimeLibType() const {
return ToolChain::RLT_Libgcc;
@@ -422,15 +446,28 @@ public:
virtual void AddIAMCUIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const;
+ /// \brief 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.
virtual SanitizerMask getSupportedSanitizers() const;
/// \brief Return sanitizers which are enabled by default.
virtual SanitizerMask getDefaultSanitizers() const { return 0; }
+};
+
+/// Set a ToolChain's effective triple. Reset it when the registration object
+/// is destroyed.
+class RegisterEffectiveTriple {
+ const ToolChain &TC;
+
+public:
+ RegisterEffectiveTriple(const ToolChain &TC, llvm::Triple T) : TC(TC) {
+ TC.setEffectiveTriple(T);
+ }
- /// \brief On Windows, returns the version of cl.exe. On other platforms,
- /// returns an empty VersionTuple.
- virtual VersionTuple getMSVCVersionFromExe() const { return VersionTuple(); }
+ ~RegisterEffectiveTriple() { TC.setEffectiveTriple(llvm::Triple()); }
};
} // end namespace driver
diff --git a/include/clang/Driver/Types.def b/include/clang/Driver/Types.def
index f2ff194ee646..2430b5b924c3 100644
--- a/include/clang/Driver/Types.def
+++ b/include/clang/Driver/Types.def
@@ -34,6 +34,7 @@
// a - The type should only be assembled.
// p - The type should only be precompiled.
// u - The type can be user specified (with -x).
+// m - Precompiling this type produces a module file.
// A - The type's temporary suffix should be appended when generating
// outputs of this type.
@@ -65,6 +66,8 @@ TYPE("c++-header-cpp-output", PP_CXXHeader, INVALID, "ii", "p")
TYPE("c++-header", CXXHeader, PP_CXXHeader, "hh", "pu")
TYPE("objective-c++-header-cpp-output", PP_ObjCXXHeader, INVALID, "mii", "p")
TYPE("objective-c++-header", ObjCXXHeader, PP_ObjCXXHeader, "h", "pu")
+TYPE("c++-module", CXXModule, PP_CXXModule, "cppm", "mu")
+TYPE("c++-module-cpp-output", PP_CXXModule, INVALID, "iim", "m")
// Other languages.
TYPE("ada", Ada, INVALID, nullptr, "u")
diff --git a/include/clang/Driver/Types.h b/include/clang/Driver/Types.h
index 22122c7a8eb9..22a26ae46a0b 100644
--- a/include/clang/Driver/Types.h
+++ b/include/clang/Driver/Types.h
@@ -13,6 +13,9 @@
#include "clang/Driver/Phases.h"
#include "llvm/ADT/SmallVector.h"
+namespace llvm {
+class StringRef;
+}
namespace clang {
namespace driver {
namespace types {
@@ -32,6 +35,11 @@ namespace types {
/// preprocessed.
ID getPreprocessedType(ID Id);
+ /// getPrecompiledType - Get the ID of the type for this input when
+ /// it has been precompiled, or INVALID if this input is not
+ /// precompiled.
+ ID getPrecompiledType(ID Id);
+
/// getTypeTempSuffix - Return the suffix to use when creating a
/// temp file of this type, or null if unspecified.
const char *getTypeTempSuffix(ID Id, bool CLMode = false);
@@ -72,9 +80,14 @@ namespace types {
/// isObjC - Is this an "ObjC" input (Obj-C and Obj-C++ sources and headers).
bool isObjC(ID Id);
+ /// isSrcFile - Is this a source file, i.e. something that still has to be
+ /// preprocessed. The logic behind this is the same that decides if the first
+ /// compilation phase is a preprocessing one.
+ bool isSrcFile(ID Id);
+
/// lookupTypeForExtension - Lookup the type to use for the file
/// extension \p Ext.
- ID lookupTypeForExtension(const char *Ext);
+ ID lookupTypeForExtension(llvm::StringRef Ext);
/// lookupTypeForTypSpecifier - Lookup the type to use for a user
/// specified type name.
@@ -90,6 +103,10 @@ namespace types {
/// C type (used for clang++ emulation of g++ behaviour)
ID lookupCXXTypeForCType(ID Id);
+ /// Lookup header file input type that corresponds to given
+ /// source file type (used for clang-cl emulation of \Yc).
+ ID lookupHeaderTypeForSourceType(ID Id);
+
} // end namespace types
} // end namespace driver
} // end namespace clang
diff --git a/include/clang/Edit/Rewriters.h b/include/clang/Edit/Rewriters.h
index 5e3425f56f73..980ed1d3363f 100644
--- a/include/clang/Edit/Rewriters.h
+++ b/include/clang/Edit/Rewriters.h
@@ -9,7 +9,6 @@
#ifndef LLVM_CLANG_EDIT_REWRITERS_H
#define LLVM_CLANG_EDIT_REWRITERS_H
-#include "llvm/ADT/SmallVector.h"
namespace clang {
class ObjCMessageExpr;
diff --git a/include/clang/Format/Format.h b/include/clang/Format/Format.h
index 1ff305d030aa..6c6458b33d85 100644
--- a/include/clang/Format/Format.h
+++ b/include/clang/Format/Format.h
@@ -35,7 +35,7 @@ namespace format {
enum class ParseError { Success = 0, Error, Unsuitable };
class ParseErrorCategory final : public std::error_category {
public:
- const char *name() const LLVM_NOEXCEPT override;
+ const char *name() const noexcept override;
std::string message(int EV) const override;
};
const std::error_category &getParseCategory();
@@ -465,6 +465,8 @@ struct FormatStyle {
LK_Java,
/// Should be used for JavaScript.
LK_JavaScript,
+ /// Should be used for ObjC code.
+ LK_ObjC,
/// Should be used for Protocol Buffers
/// (https://developers.google.com/protocol-buffers/).
LK_Proto,
@@ -549,6 +551,9 @@ struct FormatStyle {
/// \brief If ``true``, a space may be inserted after C style casts.
bool SpaceAfterCStyleCast;
+ /// \brief If \c true, a space will be inserted after the 'template' keyword.
+ bool SpaceAfterTemplateKeyword;
+
/// \brief If ``false``, spaces will be removed before assignment operators.
bool SpaceBeforeAssignmentOperators;
@@ -698,6 +703,7 @@ struct FormatStyle {
PenaltyReturnTypeOnItsOwnLine == R.PenaltyReturnTypeOnItsOwnLine &&
PointerAlignment == R.PointerAlignment &&
SpaceAfterCStyleCast == R.SpaceAfterCStyleCast &&
+ SpaceAfterTemplateKeyword == R.SpaceAfterTemplateKeyword &&
SpaceBeforeAssignmentOperators == R.SpaceBeforeAssignmentOperators &&
SpaceBeforeParens == R.SpaceBeforeParens &&
SpaceInEmptyParentheses == R.SpaceInEmptyParentheses &&
@@ -779,13 +785,25 @@ formatReplacements(StringRef Code, const tooling::Replacements &Replaces,
/// \brief 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 inserts a C++ #include directive into the correct block if the
-/// replacement corresponding to the header insertion has offset UINT_MAX.
+/// 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).
+/// - 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.
llvm::Expected<tooling::Replacements>
cleanupAroundReplacements(StringRef Code, const tooling::Replacements &Replaces,
const FormatStyle &Style);
-/// \brief Reformats the given \p Ranges in the file \p ID.
+/// \brief 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
@@ -797,31 +815,15 @@ cleanupAroundReplacements(StringRef Code, const tooling::Replacements &Replaces,
/// 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,
- SourceManager &SourceMgr, FileID ID,
- ArrayRef<CharSourceRange> Ranges,
- bool *IncompleteFormat = nullptr);
-
-/// \brief Reformats the given \p Ranges in \p Code.
-///
-/// Otherwise identical to the reformat() function using a file ID.
tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
ArrayRef<tooling::Range> Ranges,
StringRef FileName = "<stdin>",
bool *IncompleteFormat = nullptr);
-/// \brief Clean up any erroneous/redundant code in the given \p Ranges in the
-/// file \p ID.
-///
-/// Returns the ``Replacements`` that clean up all \p Ranges in the file \p ID.
-tooling::Replacements cleanup(const FormatStyle &Style,
- SourceManager &SourceMgr, FileID ID,
- ArrayRef<CharSourceRange> Ranges);
-
/// \brief Clean up any erroneous/redundant code in the given \p Ranges in \p
/// Code.
///
-/// Otherwise identical to the cleanup() function using a file ID.
+/// Returns the ``Replacements`` that clean up all \p Ranges in \p Code.
tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code,
ArrayRef<tooling::Range> Ranges,
StringRef FileName = "<stdin>");
@@ -852,13 +854,16 @@ extern const char *StyleOptionHelpDescription;
/// == "file".
/// \param[in] FallbackStyle The name of a predefined style used to fallback to
/// in case the style can't be determined from \p StyleName.
+/// \param[in] Code The actual code to be formatted. Used to determine the
+/// language if the filename isn't sufficient.
/// \param[in] FS The underlying file system, in which the file resides. By
/// default, the file system is the real file system.
///
/// \returns FormatStyle as specified by ``StyleName``. If no style could be
/// determined, the default is LLVM Style (see ``getLLVMStyle()``).
FormatStyle getStyle(StringRef StyleName, StringRef FileName,
- StringRef FallbackStyle, vfs::FileSystem *FS = nullptr);
+ StringRef FallbackStyle, StringRef Code = "",
+ vfs::FileSystem *FS = nullptr);
// \brief Returns a string representation of ``Language``.
inline StringRef getLanguageName(FormatStyle::LanguageKind Language) {
diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h
index 04e6dce5110e..cc8d4e6e3e70 100644
--- a/include/clang/Frontend/ASTUnit.h
+++ b/include/clang/Frontend/ASTUnit.h
@@ -16,7 +16,6 @@
#include "clang-c/Index.h"
#include "clang/AST/ASTContext.h"
-#include "clang/Basic/FileManager.h"
#include "clang/Basic/FileSystemOptions.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/SourceManager.h"
@@ -30,9 +29,7 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/MD5.h"
-#include "llvm/Support/Path.h"
#include <cassert>
-#include <map>
#include <memory>
#include <string>
#include <sys/types.h>
@@ -47,7 +44,6 @@ namespace clang {
class Sema;
class ASTContext;
class ASTReader;
-class CodeCompleteConsumer;
class CompilerInvocation;
class CompilerInstance;
class Decl;
@@ -58,7 +54,6 @@ class HeaderSearch;
class Preprocessor;
class PCHContainerOperations;
class PCHContainerReader;
-class SourceManager;
class TargetInfo;
class FrontendAction;
class ASTDeserializationListener;
@@ -437,9 +432,6 @@ private:
bool PreambleEndsAtStartOfLine)
: Buffer(Buffer), Owner(std::move(Owner)), Size(Size),
PreambleEndsAtStartOfLine(PreambleEndsAtStartOfLine) {}
- ComputedPreamble(ComputedPreamble &&C)
- : Buffer(C.Buffer), Owner(std::move(C.Owner)), Size(C.Size),
- PreambleEndsAtStartOfLine(C.PreambleEndsAtStartOfLine) {}
};
ComputedPreamble ComputePreamble(CompilerInvocation &Invocation,
unsigned MaxLines);
diff --git a/include/clang/Frontend/CodeGenOptions.def b/include/clang/Frontend/CodeGenOptions.def
index 6a4474cfe75f..1f0c83b5bfa7 100644
--- a/include/clang/Frontend/CodeGenOptions.def
+++ b/include/clang/Frontend/CodeGenOptions.def
@@ -1,4 +1,4 @@
-//===--- CodeGenOptions.def - Code generation option database ------ C++ -*-===//
+//===--- CodeGenOptions.def - Code generation option database ----- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -32,6 +32,7 @@ CODEGENOPT(DisableIntegratedAS, 1, 0) ///< -no-integrated-as
CODEGENOPT(CompressDebugSections, 1, 0) ///< -Wa,-compress-debug-sections
CODEGENOPT(RelaxELFRelocations, 1, 0) ///< -Wa,--mrelax-relocations
CODEGENOPT(AsmVerbose , 1, 0) ///< -dA, -fverbose-asm.
+CODEGENOPT(PreserveAsmComments, 1, 1) ///< -dA, -fno-preserve-as-comments.
CODEGENOPT(AssumeSaneOperatorNew , 1, 1) ///< implicit __attribute__((malloc)) operator new
CODEGENOPT(Autolink , 1, 1) ///< -fno-autolink
CODEGENOPT(ObjCAutoRefCountExceptions , 1, 0) ///< Whether ARC should be EH-safe.
@@ -48,13 +49,11 @@ CODEGENOPT(DisableFPElim , 1, 0) ///< Set when -fomit-frame-pointer is enabl
CODEGENOPT(DisableFree , 1, 0) ///< Don't free memory.
CODEGENOPT(DiscardValueNames , 1, 0) ///< Discard Value Names from the IR (LLVMContext flag)
CODEGENOPT(DisableGCov , 1, 0) ///< Don't run the GCov pass, for testing.
-CODEGENOPT(DisableLLVMOpts , 1, 0) ///< Don't run any optimizations, for use in
- ///< getting .bc files that correspond to the
- ///< internal state before optimizations are
- ///< done.
CODEGENOPT(DisableLLVMPasses , 1, 0) ///< Don't run any LLVM IR passes to get
///< the pristine IR generated by the
///< frontend.
+CODEGENOPT(ExperimentalNewPassManager, 1, 0) ///< Enables the new, experimental
+ ///< pass manager.
CODEGENOPT(DisableRedZone , 1, 0) ///< Set when -mno-red-zone is enabled.
CODEGENOPT(DisableTailCalls , 1, 0) ///< Do not emit tail calls.
CODEGENOPT(EmitDeclMetadata , 1, 0) ///< Emit special metadata indicating what
@@ -106,9 +105,10 @@ CODEGENOPT(NoImplicitFloat , 1, 0) ///< Set when -mno-implicit-float is enable
CODEGENOPT(NoInfsFPMath , 1, 0) ///< Assume FP arguments, results not +-Inf.
CODEGENOPT(NoSignedZeros , 1, 0) ///< Allow ignoring the signedness of FP zero
CODEGENOPT(ReciprocalMath , 1, 0) ///< Allow FP divisions to be reassociated.
-CODEGENOPT(NoInline , 1, 0) ///< Set when -fno-inline is enabled.
- ///< Disables use of the inline keyword.
+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
CODEGENOPT(NoZeroInitializedInBSS , 1, 0) ///< -fno-zero-initialized-in-bss.
/// \brief Method of Objective-C dispatch to use.
ENUM_CODEGENOPT(ObjCDispatchMethod, ObjCDispatchMethodKind, 2, Legacy)
@@ -148,10 +148,16 @@ CODEGENOPT(SanitizeCoverageTraceBB, 1, 0) ///< Enable basic block tracing in
///< in sanitizer coverage.
CODEGENOPT(SanitizeCoverageTraceCmp, 1, 0) ///< Enable cmp instruction tracing
///< in sanitizer coverage.
+CODEGENOPT(SanitizeCoverageTraceDiv, 1, 0) ///< Enable div instruction tracing
+ ///< in sanitizer coverage.
+CODEGENOPT(SanitizeCoverageTraceGep, 1, 0) ///< Enable GEP instruction tracing
+ ///< in sanitizer coverage.
CODEGENOPT(SanitizeCoverage8bitCounters, 1, 0) ///< Use 8-bit frequency counters
///< in sanitizer coverage.
CODEGENOPT(SanitizeCoverageTracePC, 1, 0) ///< Enable PC tracing
///< in sanitizer coverage.
+CODEGENOPT(SanitizeCoverageTracePCGuard, 1, 0) ///< Enable PC tracing with guard
+ ///< in sanitizer coverage.
CODEGENOPT(SanitizeStats , 1, 0) ///< Collect statistics for sanitizers.
CODEGENOPT(SimplifyLibCalls , 1, 1) ///< Set when -fbuiltin is enabled.
CODEGENOPT(SoftFloat , 1, 0) ///< -soft-float.
@@ -191,6 +197,9 @@ CODEGENOPT(DebugTypeExtRefs, 1, 0) ///< Whether or not debug info should contain
CODEGENOPT(DebugExplicitImport, 1, 0) ///< Whether or not debug info should
///< contain explicit imports for
///< anonymous namespaces
+CODEGENOPT(SplitDwarfInlining, 1, 1) ///< Whether to include inlining info in the
+ ///< skeleton CU to allow for symbolication
+ ///< of inline stack frames without .dwo files.
CODEGENOPT(EmitLLVMUseLists, 1, 0) ///< Control whether to serialize use-lists.
@@ -224,10 +233,10 @@ VALUE_CODEGENOPT(DwarfVersion, 3, 0)
CODEGENOPT(EmitCodeView, 1, 0)
/// The kind of inlining to perform.
-ENUM_CODEGENOPT(Inlining, InliningMethod, 2, NoInlining)
+ENUM_CODEGENOPT(Inlining, InliningMethod, 2, NormalInlining)
// Vector functions library to use.
-ENUM_CODEGENOPT(VecLib, VectorLibrary, 1, NoLibrary)
+ENUM_CODEGENOPT(VecLib, VectorLibrary, 2, NoLibrary)
/// The default TLS model to use.
ENUM_CODEGENOPT(DefaultTLSModel, TLSModel, 2, GeneralDynamicTLSModel)
@@ -236,6 +245,12 @@ ENUM_CODEGENOPT(DefaultTLSModel, TLSModel, 2, GeneralDynamicTLSModel)
/// filename)
VALUE_CODEGENOPT(EmitCheckPathComponentsToStrip, 32, 0)
+/// Whether to report the hotness of the code region for optimization remarks.
+CODEGENOPT(DiagnosticsWithHotness, 1, 0)
+
+/// Whether copy relocations support is available when building as PIE.
+CODEGENOPT(PIECopyRelocations, 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 4bc3120908f0..52bd1c5aff79 100644
--- a/include/clang/Frontend/CodeGenOptions.h
+++ b/include/clang/Frontend/CodeGenOptions.h
@@ -44,17 +44,18 @@ protected:
class CodeGenOptions : public CodeGenOptionsBase {
public:
enum InliningMethod {
- NoInlining, // Perform no inlining whatsoever.
NormalInlining, // Use the standard function inlining pass.
OnlyHintInlining, // Inline only (implicitly) hinted functions.
OnlyAlwaysInlining // Only run the always inlining pass.
};
enum VectorLibrary {
- NoLibrary, // Don't use any vector library.
- Accelerate // Use the Accelerate framework.
+ NoLibrary, // Don't use any vector library.
+ Accelerate, // Use the Accelerate framework.
+ SVML // Intel short vector math library.
};
+
enum ObjCDispatchMethodKind {
Legacy = 0,
NonLegacy = 1,
@@ -97,9 +98,13 @@ public:
/// The code model to use (-mcmodel).
std::string CodeModel;
- /// The filename with path we use for coverage files. The extension will be
- /// replaced.
- std::string CoverageFile;
+ /// The filename with path we use for coverage data files. The runtime
+ /// allows further manipulation with the GCOV_PREFIX and GCOV_PREFIX_STRIP
+ /// environment variables.
+ std::string CoverageDataFile;
+
+ /// The filename with path we use for coverage notes files.
+ std::string CoverageNotesFile;
/// The version string to put into coverage files.
char CoverageVersion[4];
@@ -119,6 +124,9 @@ public:
/// The ABI to use for passing floating point arguments.
std::string FloatABI;
+ /// The floating-point denormal mode to use.
+ std::string FPDenormalMode;
+
/// The float precision limit to use, if non-empty.
std::string LimitFloatPrecision;
@@ -172,6 +180,10 @@ public:
/// object file.
std::vector<std::string> CudaGpuBinaryFileNames;
+ /// The name of the file to which the backend should save YAML optimization
+ /// records.
+ std::string OptRecordFile;
+
/// Regular expression to select optimizations for which we should enable
/// optimization remarks. Transformation passes whose name matches this
/// expression (and support this feature), will emit a diagnostic
diff --git a/include/clang/Frontend/CompilerInstance.h b/include/clang/Frontend/CompilerInstance.h
index 1228cf4d5fcd..3f754d999874 100644
--- a/include/clang/Frontend/CompilerInstance.h
+++ b/include/clang/Frontend/CompilerInstance.h
@@ -11,11 +11,12 @@
#define LLVM_CLANG_FRONTEND_COMPILERINSTANCE_H_
#include "clang/AST/ASTConsumer.h"
-#include "clang/Frontend/PCHContainerOperations.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Frontend/PCHContainerOperations.h"
#include "clang/Frontend/Utils.h"
+#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Lex/ModuleLoader.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
@@ -35,7 +36,6 @@ class TimerGroup;
namespace clang {
class ASTContext;
-class ASTConsumer;
class ASTReader;
class CodeCompleteConsumer;
class DiagnosticsEngine;
@@ -96,6 +96,9 @@ class CompilerInstance : public ModuleLoader {
/// The AST context.
IntrusiveRefCntPtr<ASTContext> Context;
+ /// An optional sema source that will be attached to sema.
+ IntrusiveRefCntPtr<ExternalSemaSource> ExternalSemaSrc;
+
/// The AST consumer.
std::unique_ptr<ASTConsumer> Consumer;
@@ -774,6 +777,8 @@ public:
void addDependencyCollector(std::shared_ptr<DependencyCollector> Listener) {
DependencyCollectors.push_back(std::move(Listener));
}
+
+ void setExternalSemaSource(IntrusiveRefCntPtr<ExternalSemaSource> ESS);
};
} // end namespace clang
diff --git a/include/clang/Frontend/CompilerInvocation.h b/include/clang/Frontend/CompilerInvocation.h
index 0d5008e9a665..cb037c26546f 100644
--- a/include/clang/Frontend/CompilerInvocation.h
+++ b/include/clang/Frontend/CompilerInvocation.h
@@ -13,29 +13,29 @@
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/FileSystemOptions.h"
#include "clang/Basic/LangOptions.h"
-#include "clang/Basic/TargetOptions.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "clang/Frontend/DependencyOutputOptions.h"
#include "clang/Frontend/FrontendOptions.h"
#include "clang/Frontend/LangStandard.h"
#include "clang/Frontend/MigratorOptions.h"
#include "clang/Frontend/PreprocessorOutputOptions.h"
-#include "clang/Lex/HeaderSearchOptions.h"
-#include "clang/Lex/PreprocessorOptions.h"
#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/StringRef.h"
#include <string>
-#include <vector>
namespace llvm {
+class Triple;
+
namespace opt {
class ArgList;
}
}
namespace clang {
+class PreprocessorOptions;
+class HeaderSearchOptions;
+class TargetOptions;
+class LangOptions;
class CompilerInvocation;
class DiagnosticsEngine;
@@ -48,7 +48,8 @@ class DiagnosticsEngine;
/// report the error(s).
bool ParseDiagnosticArgs(DiagnosticOptions &Opts, llvm::opt::ArgList &Args,
DiagnosticsEngine *Diags = nullptr,
- bool DefaultDiagColor = true);
+ bool DefaultDiagColor = true,
+ bool DefaultShowOpt = true);
class CompilerInvocationBase : public RefCountedBase<CompilerInvocation> {
void operator=(const CompilerInvocationBase &) = delete;
diff --git a/include/clang/Frontend/DiagnosticRenderer.h b/include/clang/Frontend/DiagnosticRenderer.h
index c372fdd0872f..2588feb2b87d 100644
--- a/include/clang/Frontend/DiagnosticRenderer.h
+++ b/include/clang/Frontend/DiagnosticRenderer.h
@@ -19,7 +19,6 @@
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
-#include "llvm/ADT/Optional.h"
#include "llvm/ADT/PointerUnion.h"
namespace clang {
diff --git a/include/clang/Frontend/FrontendActions.h b/include/clang/Frontend/FrontendActions.h
index 0cbacbb4b122..a073ca5bfd2a 100644
--- a/include/clang/Frontend/FrontendActions.h
+++ b/include/clang/Frontend/FrontendActions.h
@@ -91,11 +91,12 @@ public:
};
class GenerateModuleAction : public ASTFrontendAction {
- clang::Module *Module;
- const FileEntry *ModuleMapForUniquing;
- bool IsSystem;
-
+ virtual std::unique_ptr<raw_pwrite_stream>
+ CreateOutputFile(CompilerInstance &CI, StringRef InFile) = 0;
+
protected:
+ bool BeginSourceFileAction(CompilerInstance &CI, StringRef Filename) override;
+
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
StringRef InFile) override;
@@ -104,22 +105,31 @@ protected:
}
bool hasASTFileSupport() const override { return false; }
+};
+
+class GenerateModuleFromModuleMapAction : public GenerateModuleAction {
+ clang::Module *Module = nullptr;
+ const FileEntry *ModuleMapForUniquing = nullptr;
+ bool IsSystem = false;
+
+private:
+ bool BeginSourceFileAction(CompilerInstance &CI, StringRef Filename) override;
+
+ std::unique_ptr<raw_pwrite_stream>
+ CreateOutputFile(CompilerInstance &CI, StringRef InFile) override;
public:
- GenerateModuleAction(const FileEntry *ModuleMap = nullptr,
- bool IsSystem = false)
- : ASTFrontendAction(), ModuleMapForUniquing(ModuleMap), IsSystem(IsSystem)
- { }
+ GenerateModuleFromModuleMapAction() {}
+ GenerateModuleFromModuleMapAction(const FileEntry *ModuleMap, bool IsSystem)
+ : ModuleMapForUniquing(ModuleMap), IsSystem(IsSystem) {}
+};
+class GenerateModuleInterfaceAction : public GenerateModuleAction {
+private:
bool BeginSourceFileAction(CompilerInstance &CI, StringRef Filename) override;
- /// \brief Compute the AST consumer arguments that will be used to
- /// create the PCHGenerator instance returned by CreateASTConsumer.
- ///
- /// \returns true if an error occurred, false otherwise.
std::unique_ptr<raw_pwrite_stream>
- ComputeASTConsumerArguments(CompilerInstance &CI, StringRef InFile,
- std::string &Sysroot, std::string &OutputFile);
+ CreateOutputFile(CompilerInstance &CI, StringRef InFile) override;
};
class SyntaxOnlyAction : public ASTFrontendAction {
@@ -138,6 +148,7 @@ class DumpModuleInfoAction : public ASTFrontendAction {
protected:
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
StringRef InFile) override;
+ bool BeginInvocation(CompilerInstance &CI) override;
void ExecuteAction() override;
public:
diff --git a/include/clang/Frontend/FrontendOptions.h b/include/clang/Frontend/FrontendOptions.h
index a75523f25648..aad397526a03 100644
--- a/include/clang/Frontend/FrontendOptions.h
+++ b/include/clang/Frontend/FrontendOptions.h
@@ -40,7 +40,9 @@ namespace frontend {
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.
+ 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.
@@ -271,6 +273,9 @@ public:
// included by this file.
std::string FindPchSource;
+ /// Filename to write statistics to.
+ std::string StatsFile;
+
public:
FrontendOptions() :
DisableFree(false), RelocatablePCH(false), ShowHelp(false),
diff --git a/include/clang/Frontend/FrontendPluginRegistry.h b/include/clang/Frontend/FrontendPluginRegistry.h
index ecab630c1228..9d7ee08d95d4 100644
--- a/include/clang/Frontend/FrontendPluginRegistry.h
+++ b/include/clang/Frontend/FrontendPluginRegistry.h
@@ -13,9 +13,6 @@
#include "clang/Frontend/FrontendAction.h"
#include "llvm/Support/Registry.h"
-// Instantiated in FrontendAction.cpp.
-extern template class llvm::Registry<clang::PluginASTAction>;
-
namespace clang {
/// The frontend plugin registry.
diff --git a/include/clang/Frontend/LangStandards.def b/include/clang/Frontend/LangStandards.def
index a3036932f049..06fe1a3350ce 100644
--- a/include/clang/Frontend/LangStandards.def
+++ b/include/clang/Frontend/LangStandards.def
@@ -81,7 +81,7 @@ LANGSTANDARD(iso9899_2011,
"iso9899:2011", "ISO C 2011",
LineComment | C99 | C11 | Digraphs | HexFloat)
LANGSTANDARD(iso9899_201x,
- "iso9899:2011", "ISO C 2011",
+ "iso9899:201x", "ISO C 2011",
LineComment | C99 | C11 | Digraphs | HexFloat)
LANGSTANDARD(gnu11, "gnu11",
diff --git a/include/clang/Frontend/PCHContainerOperations.h b/include/clang/Frontend/PCHContainerOperations.h
index 0c1b28e9a51f..d323fb3e8b94 100644
--- a/include/clang/Frontend/PCHContainerOperations.h
+++ b/include/clang/Frontend/PCHContainerOperations.h
@@ -17,7 +17,6 @@
namespace llvm {
class raw_pwrite_stream;
-class BitstreamReader;
}
using llvm::StringRef;
@@ -63,10 +62,8 @@ public:
/// Equivalent to the format passed to -fmodule-format=
virtual StringRef getFormat() const = 0;
- /// Initialize an llvm::BitstreamReader with the serialized AST inside
- /// the PCH container Buffer.
- virtual void ExtractPCH(llvm::MemoryBufferRef Buffer,
- llvm::BitstreamReader &StreamFile) const = 0;
+ /// Returns the serialized AST inside the PCH container Buffer.
+ virtual StringRef ExtractPCH(llvm::MemoryBufferRef Buffer) const = 0;
};
/// Implements write operations for a raw pass-through PCH container.
@@ -87,9 +84,8 @@ class RawPCHContainerWriter : public PCHContainerWriter {
class RawPCHContainerReader : public PCHContainerReader {
StringRef getFormat() const override { return "raw"; }
- /// Initialize an llvm::BitstreamReader with Buffer.
- void ExtractPCH(llvm::MemoryBufferRef Buffer,
- llvm::BitstreamReader &StreamFile) const override;
+ /// Simply returns the buffer contained in Buffer.
+ StringRef ExtractPCH(llvm::MemoryBufferRef Buffer) const override;
};
/// A registry of PCHContainerWriter and -Reader objects for different formats.
diff --git a/include/clang/Frontend/PreprocessorOutputOptions.h b/include/clang/Frontend/PreprocessorOutputOptions.h
index f86c49039ed2..3261b6653809 100644
--- a/include/clang/Frontend/PreprocessorOutputOptions.h
+++ b/include/clang/Frontend/PreprocessorOutputOptions.h
@@ -22,6 +22,7 @@ public:
unsigned UseLineDirectives : 1; ///< Use \#line instead of GCC-style \# N.
unsigned ShowMacroComments : 1; ///< Show comments, even in macros.
unsigned ShowMacros : 1; ///< Print macro definitions.
+ unsigned ShowIncludeDirectives : 1; ///< Print includes, imports etc. within preprocessed output.
unsigned RewriteIncludes : 1; ///< Preprocess include directives only.
public:
@@ -32,6 +33,7 @@ public:
UseLineDirectives = 0;
ShowMacroComments = 0;
ShowMacros = 0;
+ ShowIncludeDirectives = 0;
RewriteIncludes = 0;
}
};
diff --git a/include/clang/Frontend/SerializedDiagnosticReader.h b/include/clang/Frontend/SerializedDiagnosticReader.h
index 3db362bf3470..07479844d465 100644
--- a/include/clang/Frontend/SerializedDiagnosticReader.h
+++ b/include/clang/Frontend/SerializedDiagnosticReader.h
@@ -11,7 +11,6 @@
#define LLVM_CLANG_FRONTEND_SERIALIZED_DIAGNOSTIC_READER_H_
#include "clang/Basic/LLVM.h"
-#include "llvm/ADT/ArrayRef.h"
#include "llvm/Bitcode/BitstreamReader.h"
#include "llvm/Support/ErrorOr.h"
diff --git a/include/clang/Frontend/TextDiagnostic.h b/include/clang/Frontend/TextDiagnostic.h
index d41f15a1ff72..9b108c28bd1c 100644
--- a/include/clang/Frontend/TextDiagnostic.h
+++ b/include/clang/Frontend/TextDiagnostic.h
@@ -107,6 +107,8 @@ protected:
const SourceManager &SM) override;
private:
+ void emitFilename(StringRef Filename, const SourceManager &SM);
+
void emitSnippetAndCaret(SourceLocation Loc, DiagnosticsEngine::Level Level,
SmallVectorImpl<CharSourceRange>& Ranges,
ArrayRef<FixItHint> Hints,
diff --git a/include/clang/Frontend/Utils.h b/include/clang/Frontend/Utils.h
index cf943a5960bd..60419ff9b41d 100644
--- a/include/clang/Frontend/Utils.h
+++ b/include/clang/Frontend/Utils.h
@@ -128,11 +128,11 @@ class ModuleDependencyCollector : public DependencyCollector {
llvm::StringMap<std::string> SymLinkMap;
bool getRealPath(StringRef SrcPath, SmallVectorImpl<char> &Result);
- std::error_code copyToRoot(StringRef Src);
+ std::error_code copyToRoot(StringRef Src, StringRef Dst = "");
public:
StringRef getDest() { return DestDir; }
bool insertSeen(StringRef Filename) { return Seen.insert(Filename).second; }
- void addFile(StringRef Filename);
+ void addFile(StringRef Filename, StringRef FileDst = "");
void addFileMapping(StringRef VPath, StringRef RPath) {
VFSWriter.addFileMapping(VPath, RPath);
}
diff --git a/include/clang/Index/CommentToXML.h b/include/clang/Index/CommentToXML.h
index bb7b71ad411b..04f9501288ba 100644
--- a/include/clang/Index/CommentToXML.h
+++ b/include/clang/Index/CommentToXML.h
@@ -22,12 +22,7 @@ class HTMLTagComment;
}
namespace index {
-class SimpleFormatContext;
-
class CommentToXMLConverter {
- std::unique_ptr<SimpleFormatContext> FormatContext;
- unsigned FormatInMemoryUniqueId;
-
public:
CommentToXMLConverter();
~CommentToXMLConverter();
diff --git a/include/clang/Index/IndexSymbol.h b/include/clang/Index/IndexSymbol.h
index b0bc93e464b4..cac0b53a939e 100644
--- a/include/clang/Index/IndexSymbol.h
+++ b/include/clang/Index/IndexSymbol.h
@@ -59,16 +59,18 @@ enum class SymbolLanguage {
CXX,
};
-enum class SymbolSubKind : uint8_t {
+/// Set of properties that provide additional info about a symbol.
+enum class SymbolProperty : uint8_t {
Generic = 1 << 0,
TemplatePartialSpecialization = 1 << 1,
TemplateSpecialization = 1 << 2,
UnitTest = 1 << 3,
IBAnnotated = 1 << 4,
IBOutletCollection = 1 << 5,
+ GKInspectable = 1 << 6,
};
-static const unsigned SymbolSubKindBitNum = 6;
-typedef unsigned SymbolSubKindSet;
+static const unsigned SymbolPropertyBitNum = 7;
+typedef unsigned SymbolPropertySet;
/// Set of roles that are attributed to symbol occurrences.
enum class SymbolRole : uint16_t {
@@ -88,8 +90,10 @@ enum class SymbolRole : uint16_t {
RelationOverrideOf = 1 << 11,
RelationReceivedBy = 1 << 12,
RelationCalledBy = 1 << 13,
+ RelationExtendedBy = 1 << 14,
+ RelationAccessorOf = 1 << 15,
};
-static const unsigned SymbolRoleBitNum = 14;
+static const unsigned SymbolRoleBitNum = 16;
typedef unsigned SymbolRoleSet;
/// Represents a relation to another symbol for a symbol occurrence.
@@ -103,7 +107,7 @@ struct SymbolRelation {
struct SymbolInfo {
SymbolKind Kind;
- SymbolSubKindSet SubKinds;
+ SymbolPropertySet Properties;
SymbolLanguage Lang;
};
@@ -119,9 +123,9 @@ bool printSymbolName(const Decl *D, const LangOptions &LO, raw_ostream &OS);
StringRef getSymbolKindString(SymbolKind K);
StringRef getSymbolLanguageString(SymbolLanguage K);
-void applyForEachSymbolSubKind(SymbolSubKindSet SubKinds,
- llvm::function_ref<void(SymbolSubKind)> Fn);
-void printSymbolSubKinds(SymbolSubKindSet SubKinds, raw_ostream &OS);
+void applyForEachSymbolProperty(SymbolPropertySet Props,
+ llvm::function_ref<void(SymbolProperty)> Fn);
+void printSymbolProperties(SymbolPropertySet Props, raw_ostream &OS);
} // namespace index
} // namespace clang
diff --git a/include/clang/Lex/DirectoryLookup.h b/include/clang/Lex/DirectoryLookup.h
index ee0af292e6fc..dcd58f434fa2 100644
--- a/include/clang/Lex/DirectoryLookup.h
+++ b/include/clang/Lex/DirectoryLookup.h
@@ -88,7 +88,7 @@ public:
/// getName - Return the directory or filename corresponding to this lookup
/// object.
- const char *getName() const;
+ StringRef getName() const;
/// getDir - Return the directory that this entry refers to.
///
diff --git a/include/clang/Lex/HeaderMap.h b/include/clang/Lex/HeaderMap.h
index 8466f1a24d52..58bf79579a6a 100644
--- a/include/clang/Lex/HeaderMap.h
+++ b/include/clang/Lex/HeaderMap.h
@@ -45,7 +45,7 @@ public:
SmallVectorImpl<char> &DestPath) const;
/// Return the filename of the headermap.
- const char *getFileName() const;
+ StringRef getFileName() const;
/// Print the contents of this headermap to stderr.
void dump() const;
diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h
index 7bac01ef3a4c..b145d7bae15a 100644
--- a/include/clang/Lex/HeaderSearch.h
+++ b/include/clang/Lex/HeaderSearch.h
@@ -464,6 +464,9 @@ public:
/// FileEntry, uniquing them through the 'HeaderMaps' datastructure.
const HeaderMap *CreateHeaderMap(const FileEntry *FE);
+ /// \brief Get filenames for all registered header maps.
+ void getHeaderMapFileNames(SmallVectorImpl<std::string> &Names) const;
+
/// \brief Retrieve the name of the module file that should be used to
/// load the given module.
///
@@ -481,9 +484,12 @@ public:
/// \param ModuleMapPath A path that when combined with \c ModuleName
/// uniquely identifies this module. See Module::ModuleMap.
///
+ /// \param UsePrebuiltPath Whether we should use the prebuilt module path.
+ ///
/// \returns The name of the module file that corresponds to this module,
/// or an empty string if this module does not correspond to any module file.
- std::string getModuleFileName(StringRef ModuleName, StringRef ModuleMapPath);
+ std::string getModuleFileName(StringRef ModuleName, StringRef ModuleMapPath,
+ bool UsePrebuiltPath);
/// \brief Lookup a module Search for a module with the given name.
///
@@ -520,8 +526,10 @@ public:
/// \brief Retrieve the module that corresponds to the given file, if any.
///
/// \param File The header that we wish to map to a module.
- ModuleMap::KnownHeader findModuleForHeader(const FileEntry *File) const;
-
+ /// \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.
///
/// \param File The module map file.
@@ -539,6 +547,19 @@ public:
void loadTopLevelSystemModules();
private:
+
+ /// \brief Lookup a module with the given module name and search-name.
+ ///
+ /// \param ModuleName The name of the module we're looking for.
+ ///
+ /// \param SearchName The "search-name" to derive filesystem paths from
+ /// when looking for the module map; this is usually equal to ModuleName,
+ /// but for compatibility with some buggy frameworks, additional attempts
+ /// may be made to find the module under a related-but-different search-name.
+ ///
+ /// \returns The module named ModuleName.
+ Module *lookupModule(StringRef ModuleName, StringRef SearchName);
+
/// \brief Retrieve a module with the given name, which may be part of the
/// given framework.
///
diff --git a/include/clang/Lex/HeaderSearchOptions.h b/include/clang/Lex/HeaderSearchOptions.h
index 915dbf74b2a4..815b68c60e80 100644
--- a/include/clang/Lex/HeaderSearchOptions.h
+++ b/include/clang/Lex/HeaderSearchOptions.h
@@ -11,6 +11,7 @@
#define LLVM_CLANG_LEX_HEADERSEARCHOPTIONS_H
#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/CachedHashString.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/StringRef.h"
@@ -93,6 +94,9 @@ public:
/// \brief The directory used for a user build.
std::string ModuleUserBuildPath;
+ /// \brief The directories used to load prebuilt module files.
+ std::vector<std::string> PrebuiltModulePaths;
+
/// The module/pch container format.
std::string ModuleFormat;
@@ -141,7 +145,7 @@ public:
/// \brief The set of macro names that should be ignored for the purposes
/// of computing the module hash.
- llvm::SmallSetVector<std::string, 16> ModulesIgnoreMacros;
+ llvm::SmallSetVector<llvm::CachedHashString, 16> ModulesIgnoreMacros;
/// \brief The set of user-provided virtual filesystem overlay files.
std::vector<std::string> VFSOverlayFiles;
@@ -172,6 +176,8 @@ public:
/// Whether the module includes debug information (-gmodules).
unsigned UseDebugInfo : 1;
+ unsigned ModulesValidateDiagnosticOptions : 1;
+
HeaderSearchOptions(StringRef _Sysroot = "/")
: Sysroot(_Sysroot), ModuleFormat("raw"), DisableModuleHash(0),
ImplicitModuleMaps(0), ModuleMapFileHomeIsCwd(0),
@@ -181,7 +187,7 @@ public:
UseStandardCXXIncludes(true), UseLibcxx(false), Verbose(false),
ModulesValidateOncePerBuildSession(false),
ModulesValidateSystemHeaders(false),
- UseDebugInfo(false) {}
+ UseDebugInfo(false), ModulesValidateDiagnosticOptions(true) {}
/// AddPath - Add the \p Path path to the specified \p Group list.
void AddPath(StringRef Path, frontend::IncludeDirGroup Group,
@@ -199,6 +205,10 @@ public:
void AddVFSOverlayFile(StringRef Name) {
VFSOverlayFiles.push_back(Name);
}
+
+ void AddPrebuiltModulePath(StringRef Name) {
+ PrebuiltModulePaths.push_back(Name);
+ }
};
} // end namespace clang
diff --git a/include/clang/Lex/LiteralSupport.h b/include/clang/Lex/LiteralSupport.h
index 5f946fc8337e..b66581b428b1 100644
--- a/include/clang/Lex/LiteralSupport.h
+++ b/include/clang/Lex/LiteralSupport.h
@@ -259,6 +259,8 @@ public:
return UDSuffixOffset;
}
+ static bool isValidUDSuffix(const LangOptions &LangOpts, StringRef Suffix);
+
private:
void init(ArrayRef<Token> StringToks);
bool CopyStringFragment(const Token &Tok, const char *TokBegin,
diff --git a/include/clang/Lex/ModuleLoader.h b/include/clang/Lex/ModuleLoader.h
index ae79650d1fd0..70770d17e9ff 100644
--- a/include/clang/Lex/ModuleLoader.h
+++ b/include/clang/Lex/ModuleLoader.h
@@ -31,13 +31,22 @@ typedef ArrayRef<std::pair<IdentifierInfo *, SourceLocation> > ModuleIdPath;
/// \brief Describes the result of attempting to load a module.
class ModuleLoadResult {
- llvm::PointerIntPair<Module *, 1, bool> Storage;
-
public:
- ModuleLoadResult() : Storage() { }
+ enum LoadResultKind {
+ // We either succeeded or failed to load the named module.
+ Normal,
+ // The module exists, but does not actually contain the named submodule.
+ // This should only happen if the named submodule was inferred from an
+ // umbrella directory, but not actually part of the umbrella header.
+ MissingExpected,
+ // The module exists but cannot be imported due to a configuration mismatch.
+ ConfigMismatch
+ };
+ llvm::PointerIntPair<Module *, 2, LoadResultKind> Storage;
- ModuleLoadResult(Module *module, bool missingExpected)
- : Storage(module, missingExpected) { }
+ ModuleLoadResult() : Storage() { }
+ ModuleLoadResult(Module *M) : Storage(M, Normal) {}
+ ModuleLoadResult(LoadResultKind Kind) : Storage(nullptr, Kind) {}
operator Module *() const { return Storage.getPointer(); }
@@ -45,7 +54,11 @@ public:
/// 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(); }
+ bool isMissingExpected() const { return Storage.getInt() == MissingExpected; }
+
+ /// \brief 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.
diff --git a/include/clang/Lex/ModuleMap.h b/include/clang/Lex/ModuleMap.h
index 1e86f736983f..b3a2421af86e 100644
--- a/include/clang/Lex/ModuleMap.h
+++ b/include/clang/Lex/ModuleMap.h
@@ -12,22 +12,28 @@
//
//===----------------------------------------------------------------------===//
-
#ifndef LLVM_CLANG_LEX_MODULEMAP_H
#define LLVM_CLANG_LEX_MODULEMAP_H
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/Module.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include <algorithm>
+#include <memory>
#include <string>
+#include <utility>
namespace clang {
-
+
class DirectoryEntry;
class FileEntry;
class FileManager;
@@ -40,7 +46,7 @@ class ModuleMapParser;
/// reads module map files.
class ModuleMapCallbacks {
public:
- virtual ~ModuleMapCallbacks() {}
+ virtual ~ModuleMapCallbacks() = default;
/// \brief Called when a module map file has been read.
///
@@ -153,7 +159,7 @@ public:
typedef llvm::SmallPtrSet<const FileEntry *, 1> AdditionalModMapsSet;
private:
- typedef llvm::DenseMap<const FileEntry *, SmallVector<KnownHeader, 1> >
+ typedef llvm::DenseMap<const FileEntry *, SmallVector<KnownHeader, 1>>
HeadersMap;
/// \brief Mapping from each header to the module that owns the contents of
@@ -170,7 +176,8 @@ private:
/// \brief The set of attributes that can be attached to a module.
struct Attributes {
- Attributes() : IsSystem(), IsExternC(), IsExhaustive() {}
+ Attributes()
+ : IsSystem(), IsExternC(), IsExhaustive(), NoUndeclaredIncludes() {}
/// \brief Whether this is a system module.
unsigned IsSystem : 1;
@@ -180,6 +187,10 @@ private:
/// \brief Whether this is an exhaustive set of configuration macros.
unsigned IsExhaustive : 1;
+
+ /// \brief Whether files in this module can only include non-modular headers
+ /// and headers from used modules.
+ unsigned NoUndeclaredIncludes : 1;
};
/// \brief A directory for which framework modules can be inferred.
@@ -314,10 +325,15 @@ public:
///
/// \param File The header file that is likely to be included.
///
+ /// \param AllowTextual If \c true and \p File is a textual header, return
+ /// its owning module. Otherwise, no KnownHeader will be returned if the
+ /// file is only known as a textual header.
+ ///
/// \returns The module KnownHeader, which provides the module that owns the
/// given header file. The KnownHeader is default constructed to indicate
/// that no module owns this header file.
- KnownHeader findModuleForHeader(const FileEntry *File);
+ KnownHeader findModuleForHeader(const FileEntry *File,
+ bool AllowTextual = false);
/// \brief Retrieve all the modules that contain the given header file. This
/// may not include umbrella modules, nor information from external sources,
@@ -402,6 +418,15 @@ public:
bool IsFramework,
bool IsExplicit);
+ /// \brief Create a new module for a C++ Modules TS module interface unit.
+ /// The module must not already exist, and will be configured for the current
+ /// compilation.
+ ///
+ /// Note that this also sets the current module to the newly-created module.
+ ///
+ /// \returns The newly-created module.
+ Module *createModuleForInterfaceUnit(SourceLocation Loc, StringRef Name);
+
/// \brief Infer the contents of a framework module map from the given
/// framework directory.
Module *inferFrameworkModule(const DirectoryEntry *FrameworkDir,
@@ -529,5 +554,6 @@ public:
module_iterator module_end() const { return Modules.end(); }
};
-}
-#endif
+} // end namespace clang
+
+#endif // LLVM_CLANG_LEX_MODULEMAP_H
diff --git a/include/clang/Lex/PPCallbacks.h b/include/clang/Lex/PPCallbacks.h
index 68b8f1cc7348..2d027f314b5f 100644
--- a/include/clang/Lex/PPCallbacks.h
+++ b/include/clang/Lex/PPCallbacks.h
@@ -17,14 +17,12 @@
#include "clang/Basic/DiagnosticIDs.h"
#include "clang/Basic/SourceLocation.h"
-#include "clang/Lex/DirectoryLookup.h"
+#include "clang/Basic/SourceManager.h"
#include "clang/Lex/ModuleLoader.h"
#include "clang/Lex/Pragma.h"
#include "llvm/ADT/StringRef.h"
-#include <string>
namespace clang {
- class SourceLocation;
class Token;
class IdentifierInfo;
class MacroDefinition;
diff --git a/include/clang/Lex/PTHManager.h b/include/clang/Lex/PTHManager.h
index 26178eddf36d..f4e4774429f9 100644
--- a/include/clang/Lex/PTHManager.h
+++ b/include/clang/Lex/PTHManager.h
@@ -14,15 +14,11 @@
#ifndef LLVM_CLANG_LEX_PTHMANAGER_H
#define LLVM_CLANG_LEX_PTHMANAGER_H
-#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/IdentifierTable.h"
-#include "clang/Basic/LangOptions.h"
-#include "clang/Lex/PTHLexer.h"
-#include "llvm/ADT/DenseMap.h"
+#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/OnDiskHashTable.h"
-#include <string>
namespace llvm {
class MemoryBuffer;
@@ -31,6 +27,7 @@ namespace llvm {
namespace clang {
class FileEntry;
+class Preprocessor;
class PTHLexer;
class DiagnosticsEngine;
class FileSystemStatCache;
diff --git a/include/clang/Lex/PreprocessingRecord.h b/include/clang/Lex/PreprocessingRecord.h
index 87b8ce1af0de..826ba33fbb72 100644
--- a/include/clang/Lex/PreprocessingRecord.h
+++ b/include/clang/Lex/PreprocessingRecord.h
@@ -19,7 +19,6 @@
#include "clang/Lex/PPCallbacks.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/iterator.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Compiler.h"
@@ -33,11 +32,11 @@ namespace clang {
/// \brief Allocates memory within a Clang preprocessing record.
void *operator new(size_t bytes, clang::PreprocessingRecord &PR,
- unsigned alignment = 8) LLVM_NOEXCEPT;
+ unsigned alignment = 8) noexcept;
/// \brief Frees memory allocated in a Clang preprocessing record.
void operator delete(void *ptr, clang::PreprocessingRecord &PR,
- unsigned) LLVM_NOEXCEPT;
+ unsigned) noexcept;
namespace clang {
class MacroDefinitionRecord;
@@ -99,24 +98,24 @@ namespace clang {
// Only allow allocation of preprocessed entities using the allocator
// in PreprocessingRecord or by doing a placement new.
void *operator new(size_t bytes, PreprocessingRecord &PR,
- unsigned alignment = 8) LLVM_NOEXCEPT {
+ unsigned alignment = 8) noexcept {
return ::operator new(bytes, PR, alignment);
}
- void *operator new(size_t bytes, void *mem) LLVM_NOEXCEPT { return mem; }
+ void *operator new(size_t bytes, void *mem) noexcept { return mem; }
void operator delete(void *ptr, PreprocessingRecord &PR,
- unsigned alignment) LLVM_NOEXCEPT {
+ unsigned alignment) noexcept {
return ::operator delete(ptr, PR, alignment);
}
- void operator delete(void *, std::size_t) LLVM_NOEXCEPT {}
- void operator delete(void *, void *) LLVM_NOEXCEPT {}
+ void operator delete(void *, std::size_t) noexcept {}
+ void operator delete(void *, void *) noexcept {}
private:
// Make vanilla 'new' and 'delete' illegal for preprocessed entities.
- void *operator new(size_t bytes) LLVM_NOEXCEPT;
- void operator delete(void *data) LLVM_NOEXCEPT;
+ void *operator new(size_t bytes) noexcept;
+ void operator delete(void *data) noexcept;
};
/// \brief Records the presence of a preprocessor directive.
@@ -524,12 +523,12 @@ namespace clang {
} // end namespace clang
inline void *operator new(size_t bytes, clang::PreprocessingRecord &PR,
- unsigned alignment) LLVM_NOEXCEPT {
+ unsigned alignment) noexcept {
return PR.Allocate(bytes, alignment);
}
inline void operator delete(void *ptr, clang::PreprocessingRecord &PR,
- unsigned) LLVM_NOEXCEPT {
+ unsigned) noexcept {
PR.Deallocate(ptr);
}
diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h
index 30cc37f6f884..bb71f49290b4 100644
--- a/include/clang/Lex/Preprocessor.h
+++ b/include/clang/Lex/Preprocessor.h
@@ -265,6 +265,10 @@ class Preprocessor : public RefCountedBase<Preprocessor> {
/// \brief True if we hit the code-completion point.
bool CodeCompletionReached;
+ /// \brief The code completion token containing the information
+ /// on the stem that is to be code completed.
+ IdentifierInfo *CodeCompletionII;
+
/// \brief The directory that the main file should be considered to occupy,
/// if it does not correspond to a real file (as happens when building a
/// module).
@@ -346,14 +350,6 @@ class Preprocessor : public RefCountedBase<Preprocessor> {
ThePPLexer(std::move(ThePPLexer)),
TheTokenLexer(std::move(TheTokenLexer)),
TheDirLookup(std::move(TheDirLookup)) {}
- IncludeStackInfo(IncludeStackInfo &&RHS)
- : CurLexerKind(std::move(RHS.CurLexerKind)),
- TheSubmodule(std::move(RHS.TheSubmodule)),
- TheLexer(std::move(RHS.TheLexer)),
- ThePTHLexer(std::move(RHS.ThePTHLexer)),
- ThePPLexer(std::move(RHS.ThePPLexer)),
- TheTokenLexer(std::move(RHS.TheTokenLexer)),
- TheDirLookup(std::move(RHS.TheDirLookup)) {}
};
std::vector<IncludeStackInfo> IncludeMacroStack;
@@ -394,6 +390,8 @@ class Preprocessor : public RefCountedBase<Preprocessor> {
ModuleMacroInfo *getModuleInfo(Preprocessor &PP,
const IdentifierInfo *II) const {
+ if (II->isOutOfDate())
+ PP.updateOutOfDateIdentifier(const_cast<IdentifierInfo&>(*II));
// FIXME: Find a spare bit on IdentifierInfo and store a
// HasModuleMacros flag.
if (!II->hasMacroDefinition() ||
@@ -418,10 +416,10 @@ class Preprocessor : public RefCountedBase<Preprocessor> {
public:
MacroState() : MacroState(nullptr) {}
MacroState(MacroDirective *MD) : State(MD) {}
- MacroState(MacroState &&O) LLVM_NOEXCEPT : State(O.State) {
+ MacroState(MacroState &&O) noexcept : State(O.State) {
O.State = (MacroDirective *)nullptr;
}
- MacroState &operator=(MacroState &&O) LLVM_NOEXCEPT {
+ MacroState &operator=(MacroState &&O) noexcept {
auto S = O.State;
O.State = (MacroDirective *)nullptr;
State = S;
@@ -649,6 +647,8 @@ class Preprocessor : public RefCountedBase<Preprocessor> {
};
DeserializedMacroInfoChain *DeserialMIChainHead;
+ void updateOutOfDateIdentifier(IdentifierInfo &II) const;
+
public:
Preprocessor(IntrusiveRefCntPtr<PreprocessorOptions> PPOpts,
DiagnosticsEngine &diags, LangOptions &opts,
@@ -887,7 +887,8 @@ public:
return appendDefMacroDirective(II, MI, MI->getDefinitionLoc());
}
/// \brief Set a MacroDirective that was loaded from a PCH file.
- void setLoadedMacroDirective(IdentifierInfo *II, MacroDirective *MD);
+ void setLoadedMacroDirective(IdentifierInfo *II, MacroDirective *ED,
+ MacroDirective *MD);
/// \brief Register an exported macro for a module and identifier.
ModuleMacro *addModuleMacro(Module *Mod, IdentifierInfo *II, MacroInfo *Macro,
@@ -896,6 +897,8 @@ public:
/// \brief 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));
auto I = LeafModuleMacros.find(II);
if (I != LeafModuleMacros.end())
return I->second;
@@ -984,6 +987,18 @@ public:
/// completion point.
void CodeCompleteNaturalLanguage();
+ /// \brief Set the code completion token for filtering purposes.
+ void setCodeCompletionIdentifierInfo(IdentifierInfo *Filter) {
+ CodeCompletionII = Filter;
+ }
+
+ /// \brief 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
/// preprocessing record.
PreprocessingRecord *getPreprocessingRecord() const { return Record; }
@@ -1862,12 +1877,12 @@ private:
/// Handle*Directive - implement the various preprocessor directives. These
/// should side-effect the current preprocessor object so that the next call
/// to Lex() will return the appropriate token next.
- void HandleLineDirective(Token &Tok);
+ void HandleLineDirective();
void HandleDigitDirective(Token &Tok);
void HandleUserDiagnosticDirective(Token &Tok, bool isWarning);
void HandleIdentSCCSDirective(Token &Tok);
void HandleMacroPublicDirective(Token &Tok);
- void HandleMacroPrivateDirective(Token &Tok);
+ void HandleMacroPrivateDirective();
// File inclusion.
void HandleIncludeDirective(SourceLocation HashLoc,
@@ -1907,7 +1922,7 @@ public:
private:
// Macro handling.
void HandleDefineDirective(Token &Tok, bool ImmediatelyAfterTopLevelIfndef);
- void HandleUndefDirective(Token &Tok);
+ void HandleUndefDirective();
// Conditional Inclusion.
void HandleIfdefDirective(Token &Tok, bool isIfndef,
@@ -1923,7 +1938,7 @@ private:
public:
void HandlePragmaOnce(Token &OnceTok);
void HandlePragmaMark();
- void HandlePragmaPoison(Token &PoisonTok);
+ void HandlePragmaPoison();
void HandlePragmaSystemHeader(Token &SysHeaderTok);
void HandlePragmaDependency(Token &DependencyTok);
void HandlePragmaPushMacro(Token &Tok);
@@ -1956,6 +1971,4 @@ typedef llvm::Registry<PragmaHandler> PragmaHandlerRegistry;
} // end namespace clang
-extern template class llvm::Registry<clang::PragmaHandler>;
-
#endif
diff --git a/include/clang/Lex/PreprocessorOptions.h b/include/clang/Lex/PreprocessorOptions.h
index 963d95d7f1d1..de652cccb83a 100644
--- a/include/clang/Lex/PreprocessorOptions.h
+++ b/include/clang/Lex/PreprocessorOptions.h
@@ -12,7 +12,6 @@
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
-#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include <cassert>
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index 5838a447c3b9..972f13daca46 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -74,7 +74,8 @@ class Parser : public CodeCompletionHandler {
// a statement).
SourceLocation PrevTokLocation;
- unsigned short ParenCount, BracketCount, BraceCount;
+ unsigned short ParenCount = 0, BracketCount = 0, BraceCount = 0;
+ unsigned short MisplacedModuleBeginCount = 0;
/// Actions - These are the callbacks we invoke as we parse various constructs
/// in the file.
@@ -143,6 +144,7 @@ class Parser : public CodeCompletionHandler {
/// C++0x contextual keywords.
mutable IdentifierInfo *Ident_final;
+ mutable IdentifierInfo *Ident_GNU_final;
mutable IdentifierInfo *Ident_override;
// C++ type trait keywords that can be reverted to identifiers and still be
@@ -171,6 +173,8 @@ class Parser : public CodeCompletionHandler {
std::unique_ptr<PragmaHandler> MSCodeSeg;
std::unique_ptr<PragmaHandler> MSSection;
std::unique_ptr<PragmaHandler> MSRuntimeChecks;
+ std::unique_ptr<PragmaHandler> MSIntrinsic;
+ std::unique_ptr<PragmaHandler> CUDAForceHostDeviceHandler;
std::unique_ptr<PragmaHandler> OptimizeHandler;
std::unique_ptr<PragmaHandler> LoopHintHandler;
std::unique_ptr<PragmaHandler> UnrollHintHandler;
@@ -244,6 +248,11 @@ class Parser : public CodeCompletionHandler {
bool SkipFunctionBodies;
+ /// The location of the expression statement that is being parsed right now.
+ /// Used to determine if an expression that is being parsed is a statement or
+ /// just a regular sub-expression.
+ SourceLocation ExprStatementTokLoc;
+
public:
Parser(Preprocessor &PP, Sema &Actions, bool SkipFunctionBodies);
~Parser() override;
@@ -277,6 +286,9 @@ public:
///
void Initialize();
+ /// Parse the first top-level declaration in a translation unit.
+ bool ParseFirstTopLevelDecl(DeclGroupPtrTy &Result);
+
/// ParseTopLevelDecl - Parse one top-level declaration. Returns true if
/// the EOF was encountered.
bool ParseTopLevelDecl(DeclGroupPtrTy &Result);
@@ -314,6 +326,10 @@ public:
return true;
}
+ SourceLocation getEndOfPreviousToken() {
+ return PP.getLocForEndOfToken(PrevTokLocation);
+ }
+
/// Retrieve the underscored keyword (_Nonnull, _Nullable) that corresponds
/// to the given nullability kind.
IdentifierInfo *getNullabilityKeyword(NullabilityKind nullability) {
@@ -868,8 +884,8 @@ public:
StopAtCodeCompletion = 1 << 2 ///< Stop at code completion
};
- friend LLVM_CONSTEXPR SkipUntilFlags operator|(SkipUntilFlags L,
- SkipUntilFlags R) {
+ friend constexpr SkipUntilFlags operator|(SkipUntilFlags L,
+ SkipUntilFlags R) {
return static_cast<SkipUntilFlags>(static_cast<unsigned>(L) |
static_cast<unsigned>(R));
}
@@ -1002,8 +1018,8 @@ private:
/// (C++ [class.mem]p2).
struct LateParsedDefaultArgument {
explicit LateParsedDefaultArgument(Decl *P,
- CachedTokens *Toks = nullptr)
- : Param(P), Toks(Toks) { }
+ std::unique_ptr<CachedTokens> Toks = nullptr)
+ : Param(P), Toks(std::move(Toks)) { }
/// Param - The parameter declaration for this parameter.
Decl *Param;
@@ -1012,7 +1028,7 @@ private:
/// argument expression, not including the '=' or the terminating
/// ')' or ','. This will be NULL for parameters that have no
/// default argument.
- CachedTokens *Toks;
+ std::unique_ptr<CachedTokens> Toks;
};
/// LateParsedMethodDeclaration - A method declaration inside a class that
@@ -1245,6 +1261,11 @@ private:
ParsedAttributesWithRange(AttributeFactory &factory)
: ParsedAttributes(factory) {}
+ void clear() {
+ ParsedAttributes::clear();
+ Range = SourceRange();
+ }
+
SourceRange Range;
};
@@ -1514,8 +1535,6 @@ private:
bool IsTypename = false,
IdentifierInfo **LastII = nullptr);
- void CheckForLParenAfterColonColon();
-
//===--------------------------------------------------------------------===//
// C++0x 5.1.2: Lambda expressions
@@ -2098,8 +2117,8 @@ private:
void DiagnoseMisplacedCXX11Attribute(ParsedAttributesWithRange &Attrs,
SourceLocation CorrectLocation);
- void handleDeclspecAlignBeforeClassKey(ParsedAttributesWithRange &Attrs,
- DeclSpec &DS, Sema::TagUseKind TUK);
+ void stripTypeAttributesOffDeclSpec(ParsedAttributesWithRange &Attrs,
+ DeclSpec &DS, Sema::TagUseKind TUK);
void ProhibitAttributes(ParsedAttributesWithRange &attrs) {
if (!attrs.Range.isValid()) return;
@@ -2111,7 +2130,8 @@ private:
// Forbid C++11 attributes that appear on certain syntactic
// locations which standard permits but we don't supported yet,
// for example, attributes appertain to decl specifiers.
- void ProhibitCXX11Attributes(ParsedAttributesWithRange &attrs);
+ void ProhibitCXX11Attributes(ParsedAttributesWithRange &Attrs,
+ unsigned DiagID);
/// \brief Skip C++11 attributes and return the end location of the last one.
/// \returns SourceLocation() if there are no attributes.
@@ -2203,6 +2223,7 @@ private:
if (getLangOpts().MicrosoftExt && Tok.is(tok::l_square))
ParseMicrosoftAttributes(attrs, endLoc);
}
+ void ParseMicrosoftUuidAttributeArgs(ParsedAttributes &Attrs);
void ParseMicrosoftAttributes(ParsedAttributes &attrs,
SourceLocation *endLoc = nullptr);
void MaybeParseMicrosoftDeclSpecs(ParsedAttributes &Attrs,
@@ -2352,6 +2373,7 @@ private:
bool AtomicAllowed = true,
bool IdentifierRequired = false);
void ParseDirectDeclarator(Declarator &D);
+ void ParseDecompositionDeclarator(Declarator &D);
void ParseParenDeclarator(Declarator &D);
void ParseFunctionDeclarator(Declarator &D,
ParsedAttributes &attrs,
@@ -2400,21 +2422,40 @@ private:
ParsedAttributes& attrs,
BalancedDelimiterTracker &Tracker);
Decl *ParseLinkage(ParsingDeclSpec &DS, unsigned Context);
- Decl *ParseUsingDirectiveOrDeclaration(unsigned Context,
- const ParsedTemplateInfo &TemplateInfo,
- SourceLocation &DeclEnd,
- ParsedAttributesWithRange &attrs,
- Decl **OwnedType = nullptr);
+ Decl *ParseExportDeclaration();
+ DeclGroupPtrTy ParseUsingDirectiveOrDeclaration(
+ unsigned Context, const ParsedTemplateInfo &TemplateInfo,
+ SourceLocation &DeclEnd, ParsedAttributesWithRange &attrs);
Decl *ParseUsingDirective(unsigned Context,
SourceLocation UsingLoc,
SourceLocation &DeclEnd,
ParsedAttributes &attrs);
- Decl *ParseUsingDeclaration(unsigned Context,
- const ParsedTemplateInfo &TemplateInfo,
- SourceLocation UsingLoc,
- SourceLocation &DeclEnd,
- AccessSpecifier AS = AS_none,
- Decl **OwnedType = nullptr);
+
+ struct UsingDeclarator {
+ SourceLocation TypenameLoc;
+ CXXScopeSpec SS;
+ SourceLocation TemplateKWLoc;
+ UnqualifiedId Name;
+ SourceLocation EllipsisLoc;
+
+ void clear() {
+ TypenameLoc = TemplateKWLoc = EllipsisLoc = SourceLocation();
+ SS.clear();
+ Name.clear();
+ }
+ };
+
+ bool ParseUsingDeclarator(unsigned Context, UsingDeclarator &D);
+ DeclGroupPtrTy ParseUsingDeclaration(unsigned Context,
+ const ParsedTemplateInfo &TemplateInfo,
+ SourceLocation UsingLoc,
+ SourceLocation &DeclEnd,
+ AccessSpecifier AS = AS_none);
+ Decl *ParseAliasDeclarationAfterDeclarator(
+ const ParsedTemplateInfo &TemplateInfo, SourceLocation UsingLoc,
+ UsingDeclarator &D, SourceLocation &DeclEnd, AccessSpecifier AS,
+ ParsedAttributes &Attrs, Decl **OwnedType = nullptr);
+
Decl *ParseStaticAssertDeclaration(SourceLocation &DeclEnd);
Decl *ParseNamespaceAlias(SourceLocation NamespaceLoc,
SourceLocation AliasLoc, IdentifierInfo *Alias,
@@ -2649,6 +2690,7 @@ private:
//===--------------------------------------------------------------------===//
// Modules
+ DeclGroupPtrTy ParseModuleDecl();
DeclGroupPtrTy ParseModuleImport(SourceLocation AtLoc);
bool parseMisplacedModuleImport();
bool tryParseMisplacedModuleImport() {
@@ -2659,6 +2701,11 @@ private:
return false;
}
+ bool ParseModuleName(
+ SourceLocation UseLoc,
+ SmallVectorImpl<std::pair<IdentifierInfo *, SourceLocation>> &Path,
+ bool IsImport);
+
//===--------------------------------------------------------------------===//
// C++11/G++: Type Traits [Type-Traits.html in the GCC manual]
ExprResult ParseTypeTrait();
diff --git a/include/clang/Rewrite/Core/HTMLRewrite.h b/include/clang/Rewrite/Core/HTMLRewrite.h
index dafdf51ce63b..1fd7c7a3f84e 100644
--- a/include/clang/Rewrite/Core/HTMLRewrite.h
+++ b/include/clang/Rewrite/Core/HTMLRewrite.h
@@ -62,8 +62,8 @@ namespace html {
void AddLineNumbers(Rewriter& R, FileID FID);
- void AddHeaderFooterInternalBuiltinCSS(Rewriter& R, FileID FID,
- const char *title = nullptr);
+ void AddHeaderFooterInternalBuiltinCSS(Rewriter &R, FileID FID,
+ StringRef title);
/// SyntaxHighlight - Relex the specified FileID and annotate the HTML with
/// information about keywords, comments, etc.
diff --git a/include/clang/Sema/AttributeList.h b/include/clang/Sema/AttributeList.h
index fcddbecc029c..e74bf6a7cc86 100644
--- a/include/clang/Sema/AttributeList.h
+++ b/include/clang/Sema/AttributeList.h
@@ -101,12 +101,14 @@ public:
AS_CXX11,
/// __declspec(...)
AS_Declspec,
+ /// [uuid("...")] class Foo
+ AS_Microsoft,
/// __ptr16, alignas(...), etc.
AS_Keyword,
/// Context-sensitive version of a keyword attribute.
AS_ContextSensitiveKeyword,
/// #pragma ...
- AS_Pragma
+ AS_Pragma,
};
private:
@@ -369,6 +371,7 @@ public:
}
bool isDeclspecAttribute() const { return SyntaxUsed == AS_Declspec; }
+ bool isMicrosoftAttribute() const { return SyntaxUsed == AS_Microsoft; }
bool isCXX11Attribute() const {
return SyntaxUsed == AS_CXX11 || isAlignasAttribute();
}
@@ -745,6 +748,19 @@ public:
list = newList;
}
+ void addAllAtEnd(AttributeList *newList) {
+ if (!list) {
+ list = newList;
+ return;
+ }
+
+ AttributeList *lastInList = list;
+ while (AttributeList *next = lastInList->getNext())
+ lastInList = next;
+
+ lastInList->setNext(newList);
+ }
+
void set(AttributeList *newList) {
list = newList;
}
@@ -869,12 +885,14 @@ enum AttributeDeclKind {
ExpectedFunction,
ExpectedUnion,
ExpectedVariableOrFunction,
+ ExpectedFunctionOrGlobalVar,
ExpectedFunctionVariableOrObjCInterface,
ExpectedFunctionOrMethod,
ExpectedParameter,
ExpectedFunctionMethodOrBlock,
ExpectedFunctionMethodOrClass,
ExpectedFunctionMethodOrParameter,
+ ExpectedFunctionMethodOrGlobalVar,
ExpectedClass,
ExpectedEnum,
ExpectedVariable,
@@ -897,6 +915,7 @@ enum AttributeDeclKind {
ExpectedFunctionVariableOrClass,
ExpectedFunctionVariableClassOrObjCInterface,
ExpectedObjectiveCProtocol,
+ ExpectedStaticOrTLSVar,
ExpectedFunctionGlobalVarMethodOrProperty,
ExpectedStructOrUnionOrTypedef,
ExpectedStructOrTypedef,
@@ -906,7 +925,8 @@ enum AttributeDeclKind {
ExpectedVariableEnumFieldOrTypedef,
ExpectedFunctionMethodEnumOrClass,
ExpectedStructClassVariableFunctionOrInlineNamespace,
- ExpectedForMaybeUnused
+ ExpectedForMaybeUnused,
+ ExpectedEnumOrClass,
};
} // end namespace clang
diff --git a/include/clang/Sema/CodeCompleteConsumer.h b/include/clang/Sema/CodeCompleteConsumer.h
index 014ea5d61dfd..b80924ea11fc 100644
--- a/include/clang/Sema/CodeCompleteConsumer.h
+++ b/include/clang/Sema/CodeCompleteConsumer.h
@@ -90,7 +90,11 @@ enum {
CCD_ProbablyNotObjCCollection = 15,
/// \brief An Objective-C method being used as a property.
- CCD_MethodAsProperty = 2
+ CCD_MethodAsProperty = 2,
+
+ /// \brief 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
@@ -737,7 +741,7 @@ public:
/// \brief Build a result that refers to a pattern with an associated
/// declaration.
- CodeCompletionResult(CodeCompletionString *Pattern, NamedDecl *D,
+ CodeCompletionResult(CodeCompletionString *Pattern, const NamedDecl *D,
unsigned Priority)
: Declaration(D), Pattern(Pattern), Priority(Priority), StartParameter(0),
Kind(RK_Pattern), Availability(CXAvailability_Available), Hidden(false),
@@ -913,6 +917,13 @@ public:
/// \brief Deregisters and destroys this code-completion consumer.
virtual ~CodeCompleteConsumer();
+ /// \name Code-completion filtering
+ /// \brief Check if the result should be filtered out.
+ virtual bool isResultFilteredOut(StringRef Filter,
+ CodeCompletionResult Results) {
+ return false;
+ }
+
/// \name Code-completion callbacks
//@{
/// \brief Process the finalized code-completion results.
@@ -966,6 +977,8 @@ public:
OverloadCandidate *Candidates,
unsigned NumCandidates) override;
+ bool isResultFilteredOut(StringRef Filter, CodeCompletionResult Results) override;
+
CodeCompletionAllocator &getAllocator() override {
return CCTUInfo.getAllocator();
}
diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h
index afcd791bca29..331fd0db6724 100644
--- a/include/clang/Sema/DeclSpec.h
+++ b/include/clang/Sema/DeclSpec.h
@@ -380,7 +380,8 @@ private:
SourceRange Range;
SourceLocation StorageClassSpecLoc, ThreadStorageClassSpecLoc;
- SourceLocation TSWLoc, TSCLoc, TSSLoc, TSTLoc, AltiVecLoc;
+ SourceRange TSWRange;
+ SourceLocation TSCLoc, TSSLoc, TSTLoc, AltiVecLoc;
/// 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
@@ -503,7 +504,8 @@ public:
SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
- SourceLocation getTypeSpecWidthLoc() const { return TSWLoc; }
+ SourceLocation getTypeSpecWidthLoc() const { return TSWRange.getBegin(); }
+ SourceRange getTypeSpecWidthRange() const { return TSWRange; }
SourceLocation getTypeSpecComplexLoc() const { return TSCLoc; }
SourceLocation getTypeSpecSignLoc() const { return TSSLoc; }
SourceLocation getTypeSpecTypeLoc() const { return TSTLoc; }
@@ -1186,14 +1188,14 @@ struct DeclaratorChunk {
/// declaration of a member function), it will be stored here as a
/// sequence of tokens to be parsed once the class definition is
/// complete. Non-NULL indicates that there is a default argument.
- CachedTokens *DefaultArgTokens;
+ std::unique_ptr<CachedTokens> DefaultArgTokens;
- ParamInfo() {}
+ ParamInfo() = default;
ParamInfo(IdentifierInfo *ident, SourceLocation iloc,
Decl *param,
- CachedTokens *DefArgTokens = nullptr)
+ std::unique_ptr<CachedTokens> DefArgTokens = nullptr)
: Ident(ident), IdentLoc(iloc), Param(param),
- DefaultArgTokens(DefArgTokens) {}
+ DefaultArgTokens(std::move(DefArgTokens)) {}
};
struct TypeAndRange {
@@ -1246,9 +1248,10 @@ struct DeclaratorChunk {
/// declarator.
unsigned NumParams;
- /// NumExceptions - This is the number of types in the dynamic-exception-
- /// decl, if the function has one.
- unsigned NumExceptions;
+ /// NumExceptionsOrDecls - This is the number of types in the
+ /// dynamic-exception-decl, if the function has one. In C, this is the
+ /// number of declarations in the function prototype.
+ unsigned NumExceptionsOrDecls;
/// \brief The location of the ref-qualifier, if any.
///
@@ -1298,6 +1301,11 @@ struct DeclaratorChunk {
/// \brief Pointer to the cached tokens for an exception-specification
/// that has not yet been parsed.
CachedTokens *ExceptionSpecTokens;
+
+ /// Pointer to a new[]'d array of declarations that need to be available
+ /// for lookup inside the function body, if one exists. Does not exist in
+ /// C++.
+ NamedDecl **DeclsInPrototype;
};
/// \brief If HasTrailingReturnType is true, this is the trailing return
@@ -1308,10 +1316,8 @@ struct DeclaratorChunk {
///
/// This is used in various places for error recovery.
void freeParams() {
- for (unsigned I = 0; I < NumParams; ++I) {
- delete Params[I].DefaultArgTokens;
- Params[I].DefaultArgTokens = nullptr;
- }
+ for (unsigned I = 0; I < NumParams; ++I)
+ Params[I].DefaultArgTokens.reset();
if (DeleteParams) {
delete[] Params;
DeleteParams = false;
@@ -1322,10 +1328,20 @@ struct DeclaratorChunk {
void destroy() {
if (DeleteParams)
delete[] Params;
- if (getExceptionSpecType() == EST_Dynamic)
+ switch (getExceptionSpecType()) {
+ default:
+ break;
+ case EST_Dynamic:
delete[] Exceptions;
- else if (getExceptionSpecType() == EST_Unparsed)
+ break;
+ case EST_Unparsed:
delete ExceptionSpecTokens;
+ break;
+ case EST_None:
+ if (NumExceptionsOrDecls != 0)
+ delete[] DeclsInPrototype;
+ break;
+ }
}
/// isKNRPrototype - Return true if this is a K&R style identifier list,
@@ -1395,6 +1411,19 @@ struct DeclaratorChunk {
return static_cast<ExceptionSpecificationType>(ExceptionSpecType);
}
+ /// \brief 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
+ /// 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
/// trailing-return-type.
bool hasTrailingReturnType() const { return HasTrailingReturnType; }
@@ -1417,15 +1446,12 @@ struct DeclaratorChunk {
unsigned TypeQuals : 5;
// CXXScopeSpec has a constructor, so it can't be a direct member.
// So we need some pointer-aligned storage and a bit of trickery.
- union {
- void *Aligner;
- char Mem[sizeof(CXXScopeSpec)];
- } ScopeMem;
+ alignas(CXXScopeSpec) char ScopeMem[sizeof(CXXScopeSpec)];
CXXScopeSpec &Scope() {
- return *reinterpret_cast<CXXScopeSpec*>(ScopeMem.Mem);
+ return *reinterpret_cast<CXXScopeSpec *>(ScopeMem);
}
const CXXScopeSpec &Scope() const {
- return *reinterpret_cast<const CXXScopeSpec*>(ScopeMem.Mem);
+ return *reinterpret_cast<const CXXScopeSpec *>(ScopeMem);
}
void destroy() {
Scope().~CXXScopeSpec();
@@ -1543,6 +1569,7 @@ struct DeclaratorChunk {
unsigned NumExceptions,
Expr *NoexceptExpr,
CachedTokens *ExceptionSpecTokens,
+ ArrayRef<NamedDecl *> DeclsInPrototype,
SourceLocation LocalRangeBegin,
SourceLocation LocalRangeEnd,
Declarator &TheDeclarator,
@@ -1580,7 +1607,7 @@ struct DeclaratorChunk {
I.EndLoc = Loc;
I.Mem.TypeQuals = TypeQuals;
I.Mem.AttrList = nullptr;
- new (I.Mem.ScopeMem.Mem) CXXScopeSpec(SS);
+ new (I.Mem.ScopeMem) CXXScopeSpec(SS);
return I;
}
@@ -1600,6 +1627,58 @@ struct DeclaratorChunk {
}
};
+/// A parsed C++17 decomposition declarator of the form
+/// '[' identifier-list ']'
+class DecompositionDeclarator {
+public:
+ struct Binding {
+ IdentifierInfo *Name;
+ SourceLocation NameLoc;
+ };
+
+private:
+ /// The locations of the '[' and ']' tokens.
+ SourceLocation LSquareLoc, RSquareLoc;
+
+ /// The bindings.
+ Binding *Bindings;
+ unsigned NumBindings : 31;
+ unsigned DeleteBindings : 1;
+
+ friend class Declarator;
+
+public:
+ DecompositionDeclarator()
+ : Bindings(nullptr), NumBindings(0), DeleteBindings(false) {}
+ DecompositionDeclarator(const DecompositionDeclarator &G) = delete;
+ DecompositionDeclarator &operator=(const DecompositionDeclarator &G) = delete;
+ ~DecompositionDeclarator() {
+ if (DeleteBindings)
+ delete[] Bindings;
+ }
+
+ void clear() {
+ LSquareLoc = RSquareLoc = SourceLocation();
+ if (DeleteBindings)
+ delete[] Bindings;
+ Bindings = nullptr;
+ NumBindings = 0;
+ DeleteBindings = false;
+ }
+
+ ArrayRef<Binding> bindings() const {
+ return llvm::makeArrayRef(Bindings, NumBindings);
+ }
+
+ bool isSet() const { return LSquareLoc.isValid(); }
+
+ SourceLocation getLSquareLoc() const { return LSquareLoc; }
+ SourceLocation getRSquareLoc() const { return RSquareLoc; }
+ SourceRange getSourceRange() const {
+ return SourceRange(LSquareLoc, RSquareLoc);
+ }
+};
+
/// \brief Described the kind of function definition (if any) provided for
/// a function.
enum FunctionDefinitionKind {
@@ -1658,6 +1737,9 @@ private:
/// \brief Where we are parsing this declarator.
TheContext Context;
+ /// The C++17 structured binding, if any. This is an alternative to a Name.
+ DecompositionDeclarator BindingGroup;
+
/// DeclTypeInfo - This holds each type that the declarator includes as it is
/// parsed. This is pushed from the identifier out, which means that element
/// #0 will be the most closely bound to the identifier, and
@@ -1679,18 +1761,6 @@ private:
/// \brief Is this Declarator a redeclaration?
unsigned Redeclaration : 1;
- /// Attrs - Attributes.
- ParsedAttributes Attrs;
-
- /// \brief The asm label, if specified.
- Expr *AsmLabel;
-
- /// InlineParams - This is a local array used for the first function decl
- /// chunk to avoid going to the heap for the common case when we have one
- /// function chunk in the declarator.
- DeclaratorChunk::ParamInfo InlineParams[16];
- bool InlineParamsUsed;
-
/// \brief true if the declaration is preceded by \c __extension__.
unsigned Extension : 1;
@@ -1700,6 +1770,27 @@ private:
/// Indicates whether this is an Objective-C 'weak' property.
unsigned ObjCWeakProperty : 1;
+ /// Indicates whether the InlineParams / InlineBindings storage has been used.
+ unsigned InlineStorageUsed : 1;
+
+ /// Attrs - Attributes.
+ ParsedAttributes Attrs;
+
+ /// \brief The asm label, if specified.
+ Expr *AsmLabel;
+
+#ifndef _MSC_VER
+ union {
+#endif
+ /// InlineParams - This is a local array used for the first function decl
+ /// chunk to avoid going to the heap for the common case when we have one
+ /// function chunk in the declarator.
+ DeclaratorChunk::ParamInfo InlineParams[16];
+ DecompositionDeclarator::Binding InlineBindings[16];
+#ifndef _MSC_VER
+ };
+#endif
+
/// \brief If this is the second or subsequent declarator in this declaration,
/// the location of the comma before this declarator.
SourceLocation CommaLoc;
@@ -1712,14 +1803,12 @@ private:
public:
Declarator(const DeclSpec &ds, TheContext C)
- : DS(ds), Range(ds.getSourceRange()), Context(C),
- InvalidType(DS.getTypeSpecType() == DeclSpec::TST_error),
- GroupingParens(false), FunctionDefinition(FDK_Declaration),
- Redeclaration(false),
- Attrs(ds.getAttributePool().getFactory()), AsmLabel(nullptr),
- InlineParamsUsed(false), Extension(false), ObjCIvar(false),
- ObjCWeakProperty(false) {
- }
+ : DS(ds), Range(ds.getSourceRange()), Context(C),
+ InvalidType(DS.getTypeSpecType() == DeclSpec::TST_error),
+ GroupingParens(false), FunctionDefinition(FDK_Declaration),
+ Redeclaration(false), Extension(false), ObjCIvar(false),
+ ObjCWeakProperty(false), InlineStorageUsed(false),
+ Attrs(ds.getAttributePool().getFactory()), AsmLabel(nullptr) {}
~Declarator() {
clear();
@@ -1746,6 +1835,10 @@ public:
/// \brief Retrieve the name specified by this declarator.
UnqualifiedId &getName() { return Name; }
+
+ const DecompositionDeclarator &getDecompositionDeclarator() const {
+ return BindingGroup;
+ }
TheContext getContext() const { return Context; }
@@ -1789,13 +1882,14 @@ public:
SS.clear();
Name.clear();
Range = DS.getSourceRange();
-
+ BindingGroup.clear();
+
for (unsigned i = 0, e = DeclTypeInfo.size(); i != e; ++i)
DeclTypeInfo[i].destroy();
DeclTypeInfo.clear();
Attrs.clear();
AsmLabel = nullptr;
- InlineParamsUsed = false;
+ InlineStorageUsed = false;
ObjCIvar = false;
ObjCWeakProperty = false;
CommaLoc = SourceLocation();
@@ -1906,6 +2000,45 @@ public:
llvm_unreachable("unknown context kind!");
}
+ /// Return true if the context permits a C++17 decomposition declarator.
+ bool mayHaveDecompositionDeclarator() const {
+ switch (Context) {
+ case 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:
+ return true;
+
+ case ConditionContext:
+ case MemberContext:
+ case PrototypeContext:
+ case TemplateParamContext:
+ // Maybe one day...
+ return false;
+
+ // These contexts don't allow any kind of non-abstract declarator.
+ case KNRTypeListContext:
+ case TypeNameContext:
+ 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:
+ return false;
+ }
+ llvm_unreachable("unknown context kind!");
+ }
+
/// mayBeFollowedByCXXDirectInit - Return true if the declarator can be
/// followed by a C++ direct initializer, e.g. "int x(1);".
bool mayBeFollowedByCXXDirectInit() const {
@@ -1959,14 +2092,22 @@ public:
}
/// isPastIdentifier - Return true if we have parsed beyond the point where
- /// the
+ /// the name would appear. (This may happen even if we haven't actually parsed
+ /// a name, perhaps because this context doesn't require one.)
bool isPastIdentifier() const { return Name.isValid(); }
/// hasName - Whether this declarator has a name, which might be an
/// identifier (accessible via getIdentifier()) or some kind of
- /// special C++ name (constructor, destructor, etc.).
- bool hasName() const {
- return Name.getKind() != UnqualifiedId::IK_Identifier || Name.Identifier;
+ /// 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 whether this declarator is a decomposition declarator.
+ bool isDecompositionDeclarator() const {
+ return BindingGroup.isSet();
}
IdentifierInfo *getIdentifier() const {
@@ -1981,7 +2122,13 @@ public:
void SetIdentifier(IdentifierInfo *Id, SourceLocation IdLoc) {
Name.setIdentifier(Id, IdLoc);
}
-
+
+ /// Set the decomposition bindings for this declarator.
+ void
+ setDecompositionBindings(SourceLocation LSquareLoc,
+ ArrayRef<DecompositionDeclarator::Binding> Bindings,
+ SourceLocation RSquareLoc);
+
/// 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,
@@ -2279,7 +2426,9 @@ public:
VS_None = 0,
VS_Override = 1,
VS_Final = 2,
- VS_Sealed = 4
+ VS_Sealed = 4,
+ // Represents the __final keyword, which is legal for gcc in pre-C++11 mode.
+ VS_GNU_Final = 8
};
VirtSpecifiers() : Specifiers(0), LastSpecifier(VS_None) { }
@@ -2292,7 +2441,7 @@ public:
bool isOverrideSpecified() const { return Specifiers & VS_Override; }
SourceLocation getOverrideLoc() const { return VS_overrideLoc; }
- bool isFinalSpecified() const { return Specifiers & (VS_Final | VS_Sealed); }
+ bool isFinalSpecified() const { return Specifiers & (VS_Final | VS_Sealed | VS_GNU_Final); }
bool isFinalSpelledSealed() const { return Specifiers & VS_Sealed; }
SourceLocation getFinalLoc() const { return VS_finalLoc; }
diff --git a/include/clang/Sema/DelayedDiagnostic.h b/include/clang/Sema/DelayedDiagnostic.h
index 155b3aa72d70..b73ec0868f52 100644
--- a/include/clang/Sema/DelayedDiagnostic.h
+++ b/include/clang/Sema/DelayedDiagnostic.h
@@ -113,16 +113,16 @@ private:
/// the complete parsing of the current declaration.
class DelayedDiagnostic {
public:
- enum DDKind { Deprecation, Unavailable, Access, ForbiddenType };
+ enum DDKind : unsigned char { Availability, Access, ForbiddenType };
- unsigned char Kind; // actually a DDKind
+ DDKind Kind;
bool Triggered;
SourceLocation Loc;
void Destroy();
- static DelayedDiagnostic makeAvailability(Sema::AvailabilityDiagnostic AD,
+ static DelayedDiagnostic makeAvailability(AvailabilityResult AR,
SourceLocation Loc,
const NamedDecl *D,
const ObjCInterfaceDecl *UnknownObjCClass,
@@ -164,17 +164,19 @@ public:
return *reinterpret_cast<const AccessedEntity*>(AccessData);
}
- const NamedDecl *getDeprecationDecl() const {
- assert((Kind == Deprecation || Kind == Unavailable) &&
- "Not a deprecation diagnostic.");
- return DeprecationData.Decl;
+ const NamedDecl *getAvailabilityDecl() const {
+ assert(Kind == Availability && "Not an availability diagnostic.");
+ return AvailabilityData.Decl;
}
- StringRef getDeprecationMessage() const {
- assert((Kind == Deprecation || Kind == Unavailable) &&
- "Not a deprecation diagnostic.");
- return StringRef(DeprecationData.Message,
- DeprecationData.MessageLen);
+ StringRef getAvailabilityMessage() const {
+ assert(Kind == Availability && "Not an availability diagnostic.");
+ return StringRef(AvailabilityData.Message, AvailabilityData.MessageLen);
+ }
+
+ AvailabilityResult getAvailabilityResult() const {
+ assert(Kind == Availability && "Not an availability diagnostic.");
+ return AvailabilityData.AR;
}
/// The diagnostic ID to emit. Used like so:
@@ -195,27 +197,28 @@ public:
assert(Kind == ForbiddenType && "not a forbidden-type diagnostic");
return QualType::getFromOpaquePtr(ForbiddenTypeData.OperandType);
}
-
+
const ObjCInterfaceDecl *getUnknownObjCClass() const {
- return DeprecationData.UnknownObjCClass;
+ return AvailabilityData.UnknownObjCClass;
}
const ObjCPropertyDecl *getObjCProperty() const {
- return DeprecationData.ObjCProperty;
+ return AvailabilityData.ObjCProperty;
}
-
+
bool getObjCPropertyAccess() const {
- return DeprecationData.ObjCPropertyAccess;
+ return AvailabilityData.ObjCPropertyAccess;
}
-
+
private:
- struct DD {
+ struct AD {
const NamedDecl *Decl;
const ObjCInterfaceDecl *UnknownObjCClass;
const ObjCPropertyDecl *ObjCProperty;
const char *Message;
size_t MessageLen;
+ AvailabilityResult AR;
bool ObjCPropertyAccess;
};
@@ -226,8 +229,7 @@ private:
};
union {
- /// Deprecation
- struct DD DeprecationData;
+ struct AD AvailabilityData;
struct FTD ForbiddenTypeData;
/// Access control.
diff --git a/include/clang/Sema/ExternalSemaSource.h b/include/clang/Sema/ExternalSemaSource.h
index c2b13046d709..c5cb7b12b3f1 100644
--- a/include/clang/Sema/ExternalSemaSource.h
+++ b/include/clang/Sema/ExternalSemaSource.h
@@ -190,7 +190,8 @@ public:
/// external source should take care not to introduce the same map entries
/// repeatedly.
virtual void ReadLateParsedTemplates(
- llvm::MapVector<const FunctionDecl *, LateParsedTemplate *> &LPTMap) {}
+ llvm::MapVector<const FunctionDecl *, std::unique_ptr<LateParsedTemplate>>
+ &LPTMap) {}
/// \copydoc Sema::CorrectTypo
/// \note LookupKind must correspond to a valid Sema::LookupNameKind
diff --git a/include/clang/Sema/Initialization.h b/include/clang/Sema/Initialization.h
index a0bf78bf1688..a7b8cce32691 100644
--- a/include/clang/Sema/Initialization.h
+++ b/include/clang/Sema/Initialization.h
@@ -20,7 +20,6 @@
#include "clang/Basic/SourceLocation.h"
#include "clang/Sema/Overload.h"
#include "clang/Sema/Ownership.h"
-#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/SmallVector.h"
#include <cassert>
@@ -85,7 +84,10 @@ public:
EK_RelatedResult,
/// \brief The entity being initialized is a function parameter; function
/// is member of group of audited CF APIs.
- EK_Parameter_CF_Audited
+ EK_Parameter_CF_Audited,
+ /// \brief The entity being initialized is a structured binding of a
+ /// decomposition declaration.
+ EK_Binding,
// Note: err_init_conversion_failed in DiagnosticSemaKinds.td uses this
// enum as an index for its first %select. When modifying this list,
@@ -118,6 +120,16 @@ private:
bool NRVO;
};
+ struct VD {
+ /// \brief The VarDecl, FieldDecl, or BindingDecl being initialized.
+ ValueDecl *VariableOrMember;
+
+ /// \brief When Kind == EK_Member, whether this is an implicit member
+ /// initialization in a copy or move constructor. These can perform array
+ /// copies.
+ bool IsImplicitFieldInit;
+ };
+
struct C {
/// \brief The name of the variable being captured by an EK_LambdaCapture.
IdentifierInfo *VarID;
@@ -127,9 +139,8 @@ private:
};
union {
- /// \brief When Kind == EK_Variable, or EK_Member, the VarDecl or
- /// FieldDecl, respectively.
- DeclaratorDecl *VariableOrMember;
+ /// \brief When Kind == EK_Variable, EK_Member or EK_Binding, the variable.
+ VD Variable;
/// \brief When Kind == EK_RelatedResult, the ObjectiveC method where
/// result type was implicitly changed to accommodate ARC semantics.
@@ -161,9 +172,9 @@ private:
InitializedEntity() : ManglingNumber(0) {}
/// \brief Create the initialization entity for a variable.
- InitializedEntity(VarDecl *Var)
- : Kind(EK_Variable), Parent(nullptr), Type(Var->getType()),
- ManglingNumber(0), VariableOrMember(Var) { }
+ InitializedEntity(VarDecl *Var, EntityKind EK = EK_Variable)
+ : Kind(EK), Parent(nullptr), Type(Var->getType()),
+ ManglingNumber(0), Variable{Var, false} { }
/// \brief Create the initialization entity for the result of a
/// function, throwing an object, performing an explicit cast, or
@@ -177,9 +188,11 @@ private:
}
/// \brief Create the initialization entity for a member subobject.
- InitializedEntity(FieldDecl *Member, const InitializedEntity *Parent)
+ InitializedEntity(FieldDecl *Member, const InitializedEntity *Parent,
+ bool Implicit)
: Kind(EK_Member), Parent(Parent), Type(Member->getType()),
- ManglingNumber(0), VariableOrMember(Member) { }
+ ManglingNumber(0), Variable{Member, Implicit} {
+ }
/// \brief Create the initialization entity for an array element.
InitializedEntity(ASTContext &Context, unsigned Index,
@@ -297,15 +310,17 @@ public:
/// \brief Create the initialization entity for a member subobject.
static InitializedEntity
InitializeMember(FieldDecl *Member,
- const InitializedEntity *Parent = nullptr) {
- return InitializedEntity(Member, Parent);
+ const InitializedEntity *Parent = nullptr,
+ bool Implicit = false) {
+ return InitializedEntity(Member, Parent, Implicit);
}
/// \brief Create the initialization entity for a member subobject.
static InitializedEntity
InitializeMember(IndirectFieldDecl *Member,
- const InitializedEntity *Parent = nullptr) {
- return InitializedEntity(Member->getAnonField(), Parent);
+ const InitializedEntity *Parent = nullptr,
+ bool Implicit = false) {
+ return InitializedEntity(Member->getAnonField(), Parent, Implicit);
}
/// \brief Create the initialization entity for an array element.
@@ -315,6 +330,11 @@ public:
return InitializedEntity(Context, Index, Parent);
}
+ /// \brief 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.
static InitializedEntity InitializeLambdaCapture(IdentifierInfo *VarID,
QualType FieldType,
@@ -356,7 +376,7 @@ public:
/// \brief Retrieve the variable, parameter, or field being
/// initialized.
- DeclaratorDecl *getDecl() const;
+ ValueDecl *getDecl() const;
/// \brief Retrieve the ObjectiveC method being initialized.
ObjCMethodDecl *getMethodDecl() const { return MethodDecl; }
@@ -388,6 +408,18 @@ public:
return Base & 0x1;
}
+ /// \brief 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
+ /// a defaulted constructor?
+ bool isImplicitMemberInitializer() const {
+ return getKind() == EK_Member && Variable.IsImplicitFieldInit;
+ }
+
/// \brief Determine the location of the 'return' keyword when initializing
/// the result of a function call.
SourceLocation getReturnLoc() const {
@@ -655,6 +687,9 @@ public:
/// 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
+ /// final stage of class copy-initialization.
+ SK_FinalCopy,
/// \brief Perform a user-defined conversion, either via a conversion
/// function or via a constructor.
SK_UserConversion,
@@ -692,9 +727,14 @@ public:
/// \brief 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.
+ SK_ArrayLoopIndex,
+ /// \brief Array initialization by elementwise copy.
+ SK_ArrayLoopInit,
/// \brief Array initialization (from an array rvalue).
- /// This is a GNU C extension.
SK_ArrayInit,
+ /// \brief Array initialization (from an array rvalue) as a GNU extension.
+ SK_GNUArrayInit,
/// \brief Array initialization from a parenthesized initializer list.
/// This is a GNU C++ extension.
SK_ParenthesizedArrayInit,
@@ -711,6 +751,8 @@ public:
SK_StdInitializerListConstructorCall,
/// \brief Initialize an OpenCL sampler from an integer.
SK_OCLSamplerInit,
+ /// \brief Initialize queue_t from 0.
+ SK_OCLZeroQueue,
/// \brief Passing zero to a function where OpenCL event_t is expected.
SK_OCLZeroEvent
};
@@ -792,6 +834,10 @@ public:
FK_ReferenceInitOverloadFailed,
/// \brief Non-const lvalue reference binding to a temporary.
FK_NonConstLValueReferenceBindingToTemporary,
+ /// \brief Non-const lvalue reference binding to a bit-field.
+ FK_NonConstLValueReferenceBindingToBitfield,
+ /// \brief Non-const lvalue reference binding to a vector element.
+ FK_NonConstLValueReferenceBindingToVectorElement,
/// \brief Non-const lvalue reference binding to an lvalue of unrelated
/// type.
FK_NonConstLValueReferenceBindingToUnrelated,
@@ -1015,6 +1061,10 @@ 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
+ /// 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
/// a constructor or a conversion function.
void AddUserConversionStep(FunctionDecl *Function,
@@ -1072,8 +1122,11 @@ public:
/// always a no-op.
void AddObjCObjectConversionStep(QualType T);
+ /// \brief Add an array initialization loop step.
+ void AddArrayInitLoopStep(QualType T, QualType EltTy);
+
/// \brief Add an array initialization step.
- void AddArrayInitStep(QualType T);
+ void AddArrayInitStep(QualType T, bool IsGNUExtension);
/// \brief Add a parenthesized array initialization step.
void AddParenthesizedArrayInitStep(QualType T);
@@ -1097,6 +1150,9 @@ public:
/// constant.
void AddOCLZeroEventStep(QualType T);
+ /// \brief 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
/// single element and rewrap it at the end.
void RewrapReferenceInitList(QualType T, InitListExpr *Syntactic);
diff --git a/include/clang/Sema/MultiplexExternalSemaSource.h b/include/clang/Sema/MultiplexExternalSemaSource.h
index 9bf8cd3d9252..37157204ea10 100644
--- a/include/clang/Sema/MultiplexExternalSemaSource.h
+++ b/include/clang/Sema/MultiplexExternalSemaSource.h
@@ -322,8 +322,8 @@ public:
/// external source should take care not to introduce the same map entries
/// repeatedly.
void ReadLateParsedTemplates(
- llvm::MapVector<const FunctionDecl *, LateParsedTemplate *> &LPTMap)
- override;
+ llvm::MapVector<const FunctionDecl *, std::unique_ptr<LateParsedTemplate>>
+ &LPTMap) override;
/// \copydoc ExternalSemaSource::CorrectTypo
/// \note Returns the first nonempty correction.
diff --git a/include/clang/Sema/Overload.h b/include/clang/Sema/Overload.h
index d0f21cd71f8d..376db92d03bd 100644
--- a/include/clang/Sema/Overload.h
+++ b/include/clang/Sema/Overload.h
@@ -62,7 +62,7 @@ namespace clang {
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_NoReturn_Adjustment, ///< Removal of noreturn from a type (Clang)
+ 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)
@@ -83,7 +83,10 @@ namespace clang {
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
};
@@ -97,8 +100,10 @@ namespace clang {
ICR_Conversion, ///< Conversion
ICR_Complex_Real_Conversion, ///< Complex <-> Real conversion
ICR_Writeback_Conversion, ///< ObjC ARC writeback conversion
- ICR_C_Conversion ///< Conversion only allowed in the C standard.
+ 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.
};
ImplicitConversionRank GetConversionRank(ImplicitConversionKind Kind);
@@ -117,7 +122,11 @@ namespace clang {
/// A narrowing conversion, because a non-constant-expression variable might
/// have got narrowed.
- NK_Variable_Narrowing
+ NK_Variable_Narrowing,
+
+ /// Cannot tell whether this is a narrowing conversion because the
+ /// expression is value-dependent.
+ NK_Dependent_Narrowing,
};
/// StandardConversionSequence - represents a standard conversion
@@ -141,7 +150,8 @@ namespace clang {
/// pointer-to-member conversion, or boolean conversion.
ImplicitConversionKind Second : 8;
- /// Third - The third conversion can be a qualification conversion.
+ /// Third - The third conversion can be a qualification conversion
+ /// or a function conversion.
ImplicitConversionKind Third : 8;
/// \brief Whether this is the deprecated conversion of a
@@ -428,8 +438,9 @@ namespace clang {
};
ImplicitConversionSequence()
- : ConversionKind(Uninitialized), StdInitializerListElement(false)
- {}
+ : ConversionKind(Uninitialized), StdInitializerListElement(false) {
+ Standard.setAsIdentityConversion();
+ }
~ImplicitConversionSequence() {
destruct();
}
@@ -586,7 +597,10 @@ namespace clang {
ovl_fail_enable_if,
/// This candidate was not viable because its address could not be taken.
- ovl_fail_addr_not_available
+ ovl_fail_addr_not_available,
+
+ /// This candidate was not viable because its OpenCL extension is disabled.
+ ovl_fail_ext_disabled,
};
/// OverloadCandidate - A single candidate in an overload set (C++ 13.3).
@@ -722,8 +736,9 @@ namespace clang {
CandidateSetKind Kind;
unsigned NumInlineSequences;
- llvm::AlignedCharArray<llvm::AlignOf<ImplicitConversionSequence>::Alignment,
- 16 * sizeof(ImplicitConversionSequence)> InlineSpace;
+ llvm::AlignedCharArray<alignof(ImplicitConversionSequence),
+ 16 * sizeof(ImplicitConversionSequence)>
+ InlineSpace;
OverloadCandidateSet(const OverloadCandidateSet &) = delete;
void operator=(const OverloadCandidateSet &) = delete;
@@ -790,7 +805,9 @@ namespace clang {
OverloadCandidateDisplayKind OCD,
ArrayRef<Expr *> Args,
StringRef Opc = "",
- SourceLocation Loc = SourceLocation());
+ SourceLocation Loc = SourceLocation(),
+ llvm::function_ref<bool(OverloadCandidate&)> Filter =
+ [](OverloadCandidate&) { return true; });
};
bool isBetterOverloadCandidate(Sema &S,
diff --git a/include/clang/Sema/Ownership.h b/include/clang/Sema/Ownership.h
index 68d13f97e2e4..92ea5296c45b 100644
--- a/include/clang/Sema/Ownership.h
+++ b/include/clang/Sema/Ownership.h
@@ -17,7 +17,6 @@
#include "clang/AST/Expr.h"
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/PointerIntPair.h"
//===----------------------------------------------------------------------===//
// OpaquePtr
diff --git a/include/clang/Sema/ScopeInfo.h b/include/clang/Sema/ScopeInfo.h
index ee724f7d728c..4b54807ab660 100644
--- a/include/clang/Sema/ScopeInfo.h
+++ b/include/clang/Sema/ScopeInfo.h
@@ -106,11 +106,15 @@ public:
bool HasDroppedStmt : 1;
/// \brief True if current scope is for OpenMP declare reduction combiner.
- bool HasOMPDeclareReductionCombiner;
+ bool HasOMPDeclareReductionCombiner : 1;
/// \brief Whether there is a fallthrough statement in this function.
bool HasFallthroughStmt : 1;
+ /// \brief Whether we make reference to a declaration that could be
+ /// unavailable.
+ bool HasPotentialAvailabilityViolations : 1;
+
/// A flag that is set when parsing a method that must call super's
/// implementation, such as \c -dealloc, \c -finalize, or any method marked
/// with \c __attribute__((objc_requires_super)).
@@ -381,6 +385,7 @@ public:
HasDroppedStmt(false),
HasOMPDeclareReductionCombiner(false),
HasFallthroughStmt(false),
+ HasPotentialAvailabilityViolations(false),
ObjCShouldCallSuper(false),
ObjCIsDesignatedInit(false),
ObjCWarnForNoDesignatedInitChain(false),
@@ -730,7 +735,16 @@ public:
/// 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;
+ llvm::SmallSet<Expr *, 8> NonODRUsedCapturingExprs;
+
+ /// 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.
+ struct ShadowedOuterDecl {
+ const VarDecl *VD;
+ const VarDecl *ShadowedDecl;
+ };
+ llvm::SmallVector<ShadowedOuterDecl, 4> ShadowingDecls;
SourceLocation PotentialThisCaptureLocation;
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 437a44a30711..82caaeb24ae7 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -74,6 +74,7 @@ namespace clang {
class ASTWriter;
class ArrayType;
class AttributeList;
+ class BindingDecl;
class BlockDecl;
class CapturedDecl;
class CXXBasePath;
@@ -454,9 +455,9 @@ public:
/// \brief 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
- /// of the enclosing full expression. This is cleared at the end of each
- /// full expression.
+ /// and discarded value conversions have been applied to all subexpressions
+ /// of the enclosing full expression. This is cleared at the end of each
+ /// full expression.
llvm::SmallPtrSet<Expr*, 2> MaybeODRUseExprs;
/// \brief Stack containing information about each of the nested
@@ -550,7 +551,8 @@ public:
SmallVector<std::pair<CXXMethodDecl*, const FunctionProtoType*>, 2>
DelayedDefaultedMemberExceptionSpecs;
- typedef llvm::MapVector<const FunctionDecl *, LateParsedTemplate *>
+ typedef llvm::MapVector<const FunctionDecl *,
+ std::unique_ptr<LateParsedTemplate>>
LateParsedTemplateMapT;
LateParsedTemplateMapT LateParsedTemplateMap;
@@ -669,15 +671,15 @@ public:
class SynthesizedFunctionScope {
Sema &S;
Sema::ContextRAII SavedContext;
-
+
public:
SynthesizedFunctionScope(Sema &S, DeclContext *DC)
- : S(S), SavedContext(S, DC)
+ : S(S), SavedContext(S, DC)
{
S.PushFunctionScope();
S.PushExpressionEvaluationContext(Sema::PotentiallyEvaluated);
}
-
+
~SynthesizedFunctionScope() {
S.PopExpressionEvaluationContext();
S.PopFunctionScopeInfo();
@@ -720,6 +722,14 @@ public:
/// standard library.
LazyDeclPtr StdBadAlloc;
+ /// \brief 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
+ /// of the standard library resides.
+ NamespaceDecl *StdExperimentalNamespaceCache;
+
/// \brief The C++ "std::initializer_list" template, which is defined in
/// \<initializer_list>.
ClassTemplateDecl *StdInitializerList;
@@ -778,15 +788,12 @@ public:
/// \brief will hold 'respondsToSelector:'
Selector RespondsToSelectorSel;
- /// \brief counter for internal MS Asm label names.
- unsigned MSAsmLabelNameCounter;
-
/// A flag to remember whether the implicit forms of operator new and delete
/// have been declared.
bool GlobalNewDeleteDeclared;
/// A flag to indicate that we're in a context that permits abstract
- /// references to fields. This is really a
+ /// references to fields. This is really a
bool AllowAbstractFieldReference;
/// \brief Describes how the expressions currently being parsed are
@@ -866,7 +873,7 @@ public:
///
/// This mangling information is allocated lazily, since most contexts
/// do not have lambda expressions or block literals.
- IntrusiveRefCntPtr<MangleNumberingContext> MangleNumbering;
+ std::unique_ptr<MangleNumberingContext> MangleNumbering;
/// \brief If we are processing a decltype type, a set of call expressions
/// for which we have deferred checking the completeness of the return type.
@@ -1177,7 +1184,7 @@ public:
/// is during Parsing. Currently it is used to pass on the depth
/// when parsing generic lambda 'auto' parameters.
void RecordParsingTemplateParameterDepth(unsigned Depth);
-
+
void PushCapturedRegionScope(Scope *RegionScope, CapturedDecl *CD,
RecordDecl *RD,
CapturedRegionKind K);
@@ -1189,11 +1196,11 @@ public:
sema::FunctionScopeInfo *getCurFunction() const {
return FunctionScopes.back();
}
-
+
sema::FunctionScopeInfo *getEnclosingFunction() const {
if (FunctionScopes.empty())
return nullptr;
-
+
for (int e = FunctionScopes.size()-1; e >= 0; --e) {
if (isa<sema::BlockScopeInfo>(FunctionScopes[e]))
continue;
@@ -1201,13 +1208,13 @@ public:
}
return nullptr;
}
-
+
template <typename ExprT>
void recordUseOfEvaluatedWeak(const ExprT *E, bool IsRead=true) {
if (!isUnevaluatedContext())
getCurFunction()->recordUseOfWeak(E, IsRead);
}
-
+
void PushCompoundScope();
void PopCompoundScope();
@@ -1293,7 +1300,9 @@ public:
SourceLocation Loc, DeclarationName Entity);
QualType BuildParenType(QualType T);
QualType BuildAtomicType(QualType T, SourceLocation Loc);
- QualType BuildPipeType(QualType T,
+ QualType BuildReadPipeType(QualType T,
+ SourceLocation Loc);
+ QualType BuildWritePipeType(QualType T,
SourceLocation Loc);
TypeSourceInfo *GetTypeForDeclarator(Declarator &D, Scope *S);
@@ -1321,18 +1330,20 @@ public:
bool CheckEquivalentExceptionSpec(
const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID,
const FunctionProtoType *Old, SourceLocation OldLoc,
- const FunctionProtoType *New, SourceLocation NewLoc,
- bool *MissingExceptionSpecification = nullptr,
- bool *MissingEmptyExceptionSpecification = nullptr,
- bool AllowNoexceptAllMatchWithNoSpec = false,
- bool IsOperatorNew = false);
- bool CheckExceptionSpecSubset(
- const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID,
- const FunctionProtoType *Superset, SourceLocation SuperLoc,
- const FunctionProtoType *Subset, SourceLocation SubLoc);
- bool CheckParamExceptionSpec(const PartialDiagnostic & NoteID,
- const FunctionProtoType *Target, SourceLocation TargetLoc,
- const FunctionProtoType *Source, SourceLocation SourceLoc);
+ const FunctionProtoType *New, SourceLocation NewLoc);
+ bool CheckExceptionSpecSubset(const PartialDiagnostic &DiagID,
+ const PartialDiagnostic &NestedDiagID,
+ const PartialDiagnostic &NoteID,
+ const FunctionProtoType *Superset,
+ SourceLocation SuperLoc,
+ const FunctionProtoType *Subset,
+ SourceLocation SubLoc);
+ bool CheckParamExceptionSpec(const PartialDiagnostic &NestedDiagID,
+ const PartialDiagnostic &NoteID,
+ const FunctionProtoType *Target,
+ SourceLocation TargetLoc,
+ const FunctionProtoType *Source,
+ SourceLocation SourceLoc);
TypeResult ActOnTypeName(Scope *S, Declarator &D);
@@ -1393,8 +1404,14 @@ private:
bool RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
TypeDiagnoser *Diagnoser);
+ struct ModuleScope {
+ clang::Module *Module;
+ VisibleModuleSet OuterVisibleModules;
+ };
+ /// The modules we're currently parsing.
+ llvm::SmallVector<ModuleScope, 16> ModuleScopes;
+
VisibleModuleSet VisibleModules;
- llvm::SmallVector<VisibleModuleSet, 16> VisibleModulesStack;
Module *CachedFakeTopLevelModule;
@@ -1510,12 +1527,6 @@ public:
NamedDecl *Previous;
};
- /// List of decls defined in a function prototype. This contains EnumConstants
- /// that incorrectly end up in translation unit scope because there is no
- /// function to pin them on. ActOnFunctionDeclarator reads this list and patches
- /// them into the FunctionDecl.
- std::vector<NamedDecl*> DeclsInPrototypeScope;
-
DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType = nullptr);
void DiagnoseUseOfUnimplementedSelectors();
@@ -1696,6 +1707,8 @@ public:
/// to a shadowing declaration.
void CheckShadowingDeclModification(Expr *E, SourceLocation Loc);
+ void DiagnoseShadowingLambdaDecls(const sema::LambdaScopeInfo *LSI);
+
private:
/// Map of current shadowing declarations to shadowed declarations. Warn if
/// it looks like the user is trying to modify the shadowing declaration.
@@ -1716,11 +1729,16 @@ public:
TypeSourceInfo *TInfo,
LookupResult &Previous,
MultiTemplateParamsArg TemplateParamLists,
- bool &AddToScope);
+ bool &AddToScope,
+ ArrayRef<BindingDecl *> Bindings = None);
+ NamedDecl *
+ ActOnDecompositionDeclarator(Scope *S, Declarator &D,
+ MultiTemplateParamsArg TemplateParamLists);
// Returns true if the variable declaration is a redeclaration
bool CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous);
void CheckVariableDeclarationType(VarDecl *NewVD);
- void CheckCompleteVariableDeclaration(VarDecl *var);
+ void CheckCompleteVariableDeclaration(VarDecl *VD);
+ void CheckCompleteDecompositionDeclaration(DecompositionDecl *DD);
void MaybeSuggestAddingStaticToDecl(const FunctionDecl *D);
NamedDecl* ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
@@ -1742,6 +1760,7 @@ public:
bool CheckFunctionDeclaration(Scope *S,
FunctionDecl *NewFD, LookupResult &Previous,
bool IsExplicitSpecialization);
+ bool shouldLinkDependentDeclWithPrevious(Decl *D, Decl *OldDecl);
void CheckMain(FunctionDecl *FD, const DeclSpec &D);
void CheckMSVCRTEntryPoint(FunctionDecl *FD);
Decl *ActOnParamDeclarator(Scope *S, Declarator &D);
@@ -1766,6 +1785,8 @@ public:
bool TypeMayContainAuto);
void ActOnUninitializedDecl(Decl *dcl, bool TypeMayContainAuto);
void ActOnInitializerError(Decl *Dcl);
+ bool canInitializeWithParenthesizedList(QualType TargetType);
+
void ActOnPureSpecifier(Decl *D, SourceLocation PureSpecLoc);
void ActOnCXXForRangeDecl(Decl *D);
StmtResult ActOnCXXForRangeIdentifier(Scope *S, SourceLocation IdentLoc,
@@ -1850,6 +1871,17 @@ public:
AttributeList *AttrList,
SourceLocation SemiLoc);
+ enum class ModuleDeclKind {
+ Module, ///< 'module X;'
+ Partition, ///< 'module partition X;'
+ Implementation, ///< 'module implementation X;'
+ };
+
+ /// The parser has processed a module-declaration that begins the definition
+ /// of a module interface or implementation.
+ DeclGroupPtrTy ActOnModuleDecl(SourceLocation ModuleLoc, ModuleDeclKind MDK,
+ ModuleIdPath Path);
+
/// \brief The parser has processed a module import declaration.
///
/// \param AtLoc The location of the '@' symbol, if any.
@@ -1863,16 +1895,13 @@ public:
/// \brief 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.
void ActOnModuleBegin(SourceLocation DirectiveLoc, Module *Mod);
/// \brief The parser has left a submodule.
void ActOnModuleEnd(SourceLocation DirectiveLoc, Module *Mod);
- /// \brief Check if module import may be found in the current context,
- /// emit error if not.
- void diagnoseMisplacedModuleImport(Module *M, SourceLocation ImportLoc);
-
/// \brief Create an implicit import of the given module at the given
/// source location, for error recovery, if possible.
///
@@ -1900,6 +1929,11 @@ public:
SourceLocation DeclLoc, ArrayRef<Module *> Modules,
MissingImportKind MIK, bool Recover);
+ Decl *ActOnStartExportDecl(Scope *S, SourceLocation ExportLoc,
+ SourceLocation LBraceLoc);
+ Decl *ActOnFinishExportDecl(Scope *S, Decl *ExportDecl,
+ SourceLocation RBraceLoc);
+
/// \brief 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.
@@ -1939,6 +1973,24 @@ public:
Decl *BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS,
RecordDecl *Record);
+ /// Common ways to introduce type names without a tag for use in diagnostics.
+ /// Keep in sync with err_tag_reference_non_tag.
+ enum NonTagKind {
+ NTK_NonStruct,
+ NTK_NonClass,
+ NTK_NonUnion,
+ NTK_NonEnum,
+ NTK_Typedef,
+ NTK_TypeAlias,
+ NTK_Template,
+ NTK_TypeAliasTemplate,
+ NTK_TemplateTemplateArgument,
+ };
+
+ /// Given a non-tag type declaration, returns an enum useful for indicating
+ /// what kind of non-tag type this is.
+ NonTagKind getNonTagTypeDeclKind(const Decl *D, TagTypeKind TTK);
+
bool isAcceptableTagRedeclaration(const TagDecl *Previous,
TagTypeKind NewTag, bool isDefinition,
SourceLocation NewTagLoc,
@@ -2181,6 +2233,8 @@ public:
VisibilityAttr *mergeVisibilityAttr(Decl *D, SourceRange Range,
VisibilityAttr::VisibilityType Vis,
unsigned AttrSpellingListIndex);
+ UuidAttr *mergeUuidAttr(Decl *D, SourceRange Range,
+ unsigned AttrSpellingListIndex, StringRef Uuid);
DLLImportAttr *mergeDLLImportAttr(Decl *D, SourceRange Range,
unsigned AttrSpellingListIndex);
DLLExportAttr *mergeDLLExportAttr(Decl *D, SourceRange Range,
@@ -2219,6 +2273,7 @@ public:
void MergeVarDecl(VarDecl *New, LookupResult &Previous);
void MergeVarDeclTypes(VarDecl *New, VarDecl *Old, bool MergeTypeWithOld);
void MergeVarDeclExceptionSpecs(VarDecl *New, VarDecl *Old);
+ bool checkVarDeclRedefinition(VarDecl *OldDefn, VarDecl *NewDefn);
bool MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, Scope *S);
// AssignmentAction - This is used by all the assignment diagnostic functions
@@ -2305,7 +2360,7 @@ public:
bool IgnoreBaseAccess);
bool IsQualificationConversion(QualType FromType, QualType ToType,
bool CStyle, bool &ObjCLifetimeConversion);
- bool IsNoReturnConversion(QualType FromType, QualType ToType,
+ bool IsFunctionConversion(QualType FromType, QualType ToType,
QualType &ResultTy);
bool DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType);
bool isSameOrCompatibleFunctionType(CanQualType Param, CanQualType Arg);
@@ -2519,7 +2574,7 @@ public:
OverloadCandidateSet& CandidateSet,
SourceRange OpRange = SourceRange());
void AddBuiltinCandidate(QualType ResultTy, QualType *ParamTys,
- ArrayRef<Expr *> Args,
+ ArrayRef<Expr *> Args,
OverloadCandidateSet& CandidateSet,
bool IsAssignmentOperator = false,
unsigned NumContextualBoolArguments = 0);
@@ -2799,8 +2854,8 @@ private:
TypoDiagnosticGenerator DiagHandler;
TypoRecoveryCallback RecoveryHandler;
TypoExprState();
- TypoExprState(TypoExprState&& other) LLVM_NOEXCEPT;
- TypoExprState& operator=(TypoExprState&& other) LLVM_NOEXCEPT;
+ TypoExprState(TypoExprState &&other) noexcept;
+ TypoExprState &operator=(TypoExprState &&other) noexcept;
};
/// \brief The set of unhandled TypoExprs and their associated state.
@@ -3015,7 +3070,7 @@ public:
bool isValidPointerAttrType(QualType T, bool RefOkay = false);
bool CheckRegparmAttr(const AttributeList &attr, unsigned &value);
- bool CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC,
+ bool CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC,
const FunctionDecl *FD = nullptr);
bool CheckNoReturnAttr(const AttributeList &attr);
bool checkStringLiteralArgumentAttr(const AttributeList &Attr,
@@ -3059,10 +3114,14 @@ public:
/// method) or an Objective-C property attribute, rather than as an
/// underscored type specifier.
///
+ /// \param allowArrayTypes Whether to accept nullability specifiers on an
+ /// array type (e.g., because it will decay to a pointer).
+ ///
/// \returns true if nullability cannot be applied, false otherwise.
bool checkNullabilityTypeSpecifier(QualType &type, NullabilityKind nullability,
SourceLocation nullabilityLoc,
- bool isContextSensitive);
+ bool isContextSensitive,
+ bool allowArrayTypes);
/// \brief Stmt attributes - this routine is the top level dispatcher.
StmtResult ProcessStmtAttributes(Stmt *Stmt, AttributeList *Attrs,
@@ -3117,18 +3176,18 @@ public:
/// declared in class 'IFace'.
bool IvarBacksCurrentMethodAccessor(ObjCInterfaceDecl *IFace,
ObjCMethodDecl *Method, ObjCIvarDecl *IV);
-
+
/// DiagnoseUnusedBackingIvarInAccessor - Issue an 'unused' warning if ivar which
/// backs the property is not used in the property's accessor.
void DiagnoseUnusedBackingIvarInAccessor(Scope *S,
const ObjCImplementationDecl *ImplD);
-
+
/// GetIvarBackingPropertyAccessor - If method is a property setter/getter and
/// it property has a backing ivar, returns this ivar; otherwise, returns NULL.
/// It also returns ivar's property on success.
ObjCIvarDecl *GetIvarBackingPropertyAccessor(const ObjCMethodDecl *Method,
const ObjCPropertyDecl *&PDecl) const;
-
+
/// Called by ActOnProperty to handle \@property declarations in
/// class extensions.
ObjCPropertyDecl *HandlePropertyInClassExtension(Scope *S,
@@ -3228,12 +3287,12 @@ public:
SmallVectorImpl<ObjCMethodDecl*>& Methods,
bool InstanceFirst, bool CheckTheOther,
const ObjCObjectType *TypeBound = nullptr);
-
+
bool
AreMultipleMethodsInGlobalPool(Selector Sel, ObjCMethodDecl *BestMethod,
SourceRange R, bool receiverIdOrClass,
SmallVectorImpl<ObjCMethodDecl*>& Methods);
-
+
void
DiagnoseMultipleMethodInGlobalPool(SmallVectorImpl<ObjCMethodDecl*> &Methods,
Selector Sel, SourceRange R,
@@ -3245,7 +3304,7 @@ private:
ObjCMethodDecl *SelectBestMethod(Selector Sel, MultiExprArg Args,
bool IsInstance,
SmallVectorImpl<ObjCMethodDecl*>& Methods);
-
+
/// \brief Record the typo correction failure and return an empty correction.
TypoCorrection FailedCorrection(IdentifierInfo *Typo, SourceLocation TypoLoc,
@@ -3621,18 +3680,18 @@ public:
void redelayDiagnostics(sema::DelayedDiagnosticPool &pool);
- enum AvailabilityDiagnostic { AD_Deprecation, AD_Unavailable, AD_Partial };
-
- void EmitAvailabilityWarning(AvailabilityDiagnostic AD,
- NamedDecl *D, StringRef Message,
- SourceLocation Loc,
+ void EmitAvailabilityWarning(AvailabilityResult AR, NamedDecl *D,
+ StringRef Message, SourceLocation Loc,
const ObjCInterfaceDecl *UnknownObjCClass,
- const ObjCPropertyDecl *ObjCProperty,
+ const ObjCPropertyDecl *ObjCProperty,
bool ObjCPropertyAccess);
bool makeUnavailableInSystemHeader(SourceLocation loc,
UnavailableAttr::ImplicitReason reason);
+ /// \brief Issue any -Wunguarded-availability warnings in \c FD
+ void DiagnoseUnguardedAvailabilityViolations(Decl *FD);
+
//===--------------------------------------------------------------------===//
// Expression Parsing Callbacks: SemaExpr.cpp.
@@ -3718,16 +3777,16 @@ public:
///
/// \param FunctionScopeIndexToStopAt If non-null, it points to the index
/// of the FunctionScopeInfo stack beyond which we do not attempt to capture.
- /// This is useful when enclosing lambdas must speculatively capture
+ /// This is useful when enclosing lambdas must speculatively capture
/// variables that may or may not be used in certain specializations of
/// a nested generic lambda.
- ///
+ ///
/// \returns true if an error occurred (i.e., the variable cannot be
/// captured) and false if the capture succeeded.
bool tryCaptureVariable(VarDecl *Var, SourceLocation Loc, TryCaptureKind Kind,
SourceLocation EllipsisLoc, bool BuildAndDiagnose,
QualType &CaptureType,
- QualType &DeclRefType,
+ QualType &DeclRefType,
const unsigned *const FunctionScopeIndexToStopAt);
/// \brief Try to capture the given variable.
@@ -3965,6 +4024,12 @@ public:
bool SuppressQualifierCheck = false,
ActOnMemberAccessExtraArgs *ExtraArgs = nullptr);
+ ExprResult BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow,
+ SourceLocation OpLoc,
+ const CXXScopeSpec &SS, FieldDecl *Field,
+ DeclAccessPair FoundDecl,
+ const DeclarationNameInfo &MemberNameInfo);
+
ExprResult PerformMemberExprBaseConversion(Expr *Base, bool IsArrow);
bool CheckQualifiedMemberReference(Expr *BaseExpr, QualType BaseType,
@@ -4201,7 +4266,10 @@ public:
NamespaceDecl *getStdNamespace() const;
NamespaceDecl *getOrCreateStdNamespace();
+ NamespaceDecl *lookupStdExperimentalNamespace();
+
CXXRecordDecl *getStdBadAlloc() const;
+ EnumDecl *getStdAlignValT() const;
/// \brief 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.
@@ -4249,18 +4317,22 @@ public:
SourceLocation NameLoc,
const LookupResult &Previous);
bool CheckUsingDeclQualifier(SourceLocation UsingLoc,
+ bool HasTypename,
const CXXScopeSpec &SS,
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,
- bool HasTypenameKeyword,
- SourceLocation TypenameLoc);
+ bool IsInstantiation);
+ NamedDecl *BuildUsingPackDecl(NamedDecl *InstantiatedFrom,
+ ArrayRef<NamedDecl *> Expansions);
bool CheckInheritingConstructorUsingDecl(UsingDecl *UD);
@@ -4273,13 +4345,12 @@ public:
Decl *ActOnUsingDeclaration(Scope *CurScope,
AccessSpecifier AS,
- bool HasUsingKeyword,
SourceLocation UsingLoc,
+ SourceLocation TypenameLoc,
CXXScopeSpec &SS,
UnqualifiedId &Name,
- AttributeList *AttrList,
- bool HasTypenameKeyword,
- SourceLocation TypenameLoc);
+ SourceLocation EllipsisLoc,
+ AttributeList *AttrList);
Decl *ActOnAliasDeclaration(Scope *CurScope,
AccessSpecifier AS,
MultiTemplateParamsArg TemplateParams,
@@ -4326,6 +4397,12 @@ public:
ExprResult BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field);
+
+ /// Instantiate or parse a C++ default argument expression as necessary.
+ /// Return true on error.
+ bool CheckCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD,
+ ParmVarDecl *Param);
+
/// BuildCXXDefaultArgExpr - Creates a CXXDefaultArgExpr, instantiating
/// the default expr if needed.
ExprResult BuildCXXDefaultArgExpr(SourceLocation CallLoc,
@@ -4721,12 +4798,12 @@ public:
///
/// \param FunctionScopeIndexToStopAt If non-null, it points to the index
/// of the FunctionScopeInfo stack beyond which we do not attempt to capture.
- /// This is useful when enclosing lambdas must speculatively capture
+ /// This is useful when enclosing lambdas must speculatively capture
/// 'this' that may or may not be used in certain specializations of
- /// a nested generic lambda (depending on whether the name resolves to
+ /// a nested generic lambda (depending on whether the name resolves to
/// a non-static member function or a static function).
/// \return returns 'true' if failed, 'false' if success.
- bool CheckCXXThisCapture(SourceLocation Loc, bool Explicit = false,
+ bool CheckCXXThisCapture(SourceLocation Loc, bool Explicit = false,
bool BuildAndDiagnose = true,
const unsigned *const FunctionScopeIndexToStopAt = nullptr,
bool ByCopy = false);
@@ -4793,25 +4870,22 @@ public:
SourceRange R);
bool FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
bool UseGlobal, QualType AllocType, bool IsArray,
- MultiExprArg PlaceArgs,
+ bool &PassAlignment, MultiExprArg PlaceArgs,
FunctionDecl *&OperatorNew,
FunctionDecl *&OperatorDelete);
- bool FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,
- DeclarationName Name, MultiExprArg Args,
- DeclContext *Ctx,
- bool AllowMissing, FunctionDecl *&Operator,
- bool Diagnose = true);
void DeclareGlobalNewDelete();
void DeclareGlobalAllocationFunction(DeclarationName Name, QualType Return,
- QualType Param1,
- QualType Param2 = QualType());
+ ArrayRef<QualType> Params);
bool FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
DeclarationName Name, FunctionDecl* &Operator,
bool Diagnose = true);
FunctionDecl *FindUsualDeallocationFunction(SourceLocation StartLoc,
bool CanProvideSize,
+ bool Overaligned,
DeclarationName Name);
+ FunctionDecl *FindDeallocationFunctionForDestructor(SourceLocation StartLoc,
+ CXXRecordDecl *RD);
/// ActOnCXXDelete - Parsed a C++ 'delete' expression
ExprResult ActOnCXXDelete(SourceLocation StartLoc,
@@ -4949,16 +5023,41 @@ public:
bool *CanCorrect = nullptr);
NamedDecl *FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS);
+ /// \brief 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
+ /// a member access expression.
+ ParsedType ObjectType;
+
+ /// \brief The identifier preceding the '::'.
+ IdentifierInfo *Identifier;
+
+ /// \brief The location of the identifier.
+ SourceLocation IdentifierLoc;
+
+ /// \brief The location of the '::'.
+ SourceLocation CCLoc;
+
+ /// \brief Creates info object for the most typical case.
+ NestedNameSpecInfo(IdentifierInfo *II, SourceLocation IdLoc,
+ SourceLocation ColonColonLoc, ParsedType ObjectType = ParsedType())
+ : ObjectType(ObjectType), Identifier(II), IdentifierLoc(IdLoc),
+ CCLoc(ColonColonLoc) {
+ }
+
+ NestedNameSpecInfo(IdentifierInfo *II, SourceLocation IdLoc,
+ SourceLocation ColonColonLoc, QualType ObjectType)
+ : ObjectType(ParsedType::make(ObjectType)), Identifier(II),
+ IdentifierLoc(IdLoc), CCLoc(ColonColonLoc) {
+ }
+ };
+
bool isNonTypeNestedNameSpecifier(Scope *S, CXXScopeSpec &SS,
- SourceLocation IdLoc,
- IdentifierInfo &II,
- ParsedType ObjectType);
+ NestedNameSpecInfo &IdInfo);
bool BuildCXXNestedNameSpecifier(Scope *S,
- IdentifierInfo &Identifier,
- SourceLocation IdentifierLoc,
- SourceLocation CCLoc,
- QualType ObjectType,
+ NestedNameSpecInfo &IdInfo,
bool EnteringContext,
CXXScopeSpec &SS,
NamedDecl *ScopeLookupResult,
@@ -4969,14 +5068,8 @@ public:
///
/// \param S The scope in which this nested-name-specifier occurs.
///
- /// \param Identifier The identifier preceding the '::'.
- ///
- /// \param IdentifierLoc The location of the identifier.
- ///
- /// \param CCLoc The location of the '::'.
- ///
- /// \param ObjectType The type of the object, if we're parsing
- /// nested-name-specifier in a member access expression.
+ /// \param IdInfo Parser information about an identifier in the
+ /// nested-name-spec.
///
/// \param EnteringContext Whether we're entering the context nominated by
/// this nested-name-specifier.
@@ -4995,10 +5088,7 @@ public:
///
/// \returns true if an error occurred, false otherwise.
bool ActOnCXXNestedNameSpecifier(Scope *S,
- IdentifierInfo &Identifier,
- SourceLocation IdentifierLoc,
- SourceLocation CCLoc,
- ParsedType ObjectType,
+ NestedNameSpecInfo &IdInfo,
bool EnteringContext,
CXXScopeSpec &SS,
bool ErrorRecoveryLookup = false,
@@ -5011,10 +5101,7 @@ public:
SourceLocation ColonColonLoc);
bool IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS,
- IdentifierInfo &Identifier,
- SourceLocation IdentifierLoc,
- SourceLocation ColonLoc,
- ParsedType ObjectType,
+ NestedNameSpecInfo &IdInfo,
bool EnteringContext);
/// \brief The parser has parsed a nested-name-specifier
@@ -5106,7 +5193,7 @@ public:
/// \brief Create a new lambda closure type.
CXXRecordDecl *createLambdaClosureType(SourceRange IntroducerRange,
TypeSourceInfo *Info,
- bool KnownDependent,
+ bool KnownDependent,
LambdaCaptureDefault CaptureDefault);
/// \brief Start the definition of a lambda expression.
@@ -5114,10 +5201,11 @@ public:
SourceRange IntroducerRange,
TypeSourceInfo *MethodType,
SourceLocation EndLoc,
- ArrayRef<ParmVarDecl *> Params);
+ ArrayRef<ParmVarDecl *> Params,
+ bool IsConstexprSpecified);
/// \brief Endow the lambda scope info with the relevant properties.
- void buildLambdaScope(sema::LambdaScopeInfo *LSI,
+ void buildLambdaScope(sema::LambdaScopeInfo *LSI,
CXXMethodDecl *CallOperator,
SourceRange IntroducerRange,
LambdaCaptureDefault CaptureDefault,
@@ -5141,7 +5229,7 @@ public:
/// \brief 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
/// variables appropriately.
VarDecl *createLambdaInitCaptureVarDecl(SourceLocation Loc,
@@ -5540,7 +5628,7 @@ public:
/// CheckOverrideControl - Check C++11 override control semantics.
void CheckOverrideControl(NamedDecl *D);
-
+
/// DiagnoseAbsenceOfOverrideControl - Diagnose if 'override' keyword was
/// not used in the declaration of an overriding method.
void DiagnoseAbsenceOfOverrideControl(NamedDecl *D);
@@ -5682,6 +5770,14 @@ public:
TemplateTy &SuggestedTemplate,
TemplateNameKind &SuggestedKind);
+ bool DiagnoseUninstantiableTemplate(SourceLocation PointOfInstantiation,
+ NamedDecl *Instantiation,
+ bool InstantiatedFromMember,
+ const NamedDecl *Pattern,
+ const NamedDecl *PatternDef,
+ TemplateSpecializationKind TSK,
+ bool Complain = true);
+
void DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl);
TemplateDecl *AdjustDeclIfTemplate(Decl *&Decl);
@@ -5694,7 +5790,10 @@ public:
SourceLocation EqualLoc,
ParsedType DefaultArg);
+ QualType CheckNonTypeTemplateParameterType(TypeSourceInfo *&TSI,
+ SourceLocation Loc);
QualType CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc);
+
Decl *ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
unsigned Depth,
unsigned Position,
@@ -5753,6 +5852,10 @@ public:
TemplateParameterList **OuterTemplateParamLists,
SkipBodyInfo *SkipBody = nullptr);
+ TemplateArgumentLoc getTrivialTemplateArgumentLoc(const TemplateArgument &Arg,
+ QualType NTTPType,
+ SourceLocation Loc);
+
void translateTemplateArguments(const ASTTemplateArgsPtr &In,
TemplateArgumentListInfo &Out);
@@ -5827,6 +5930,15 @@ public:
MultiTemplateParamsArg TemplateParameterLists,
SkipBodyInfo *SkipBody = nullptr);
+ bool CheckTemplatePartialSpecializationArgs(SourceLocation Loc,
+ TemplateDecl *PrimaryTemplate,
+ unsigned NumExplicitArgs,
+ ArrayRef<TemplateArgument> Args);
+ void CheckTemplatePartialSpecialization(
+ ClassTemplatePartialSpecializationDecl *Partial);
+ void CheckTemplatePartialSpecialization(
+ VarTemplatePartialSpecializationDecl *Partial);
+
Decl *ActOnTemplateDeclarator(Scope *S,
MultiTemplateParamsArg TemplateParameterLists,
Declarator &D);
@@ -6253,9 +6365,9 @@ public:
/// \brief Collect the set of unexpanded parameter packs within the given
/// nested-name-specifier.
///
- /// \param SS The nested-name-specifier that will be traversed to find
+ /// \param NNS The nested-name-specifier that will be traversed to find
/// unexpanded parameter packs.
- void collectUnexpandedParameterPacks(CXXScopeSpec &SS,
+ void collectUnexpandedParameterPacks(NestedNameSpecifierLoc NNS,
SmallVectorImpl<UnexpandedParameterPack> &Unexpanded);
/// \brief Collect the set of unexpanded parameter packs within the given
@@ -6399,11 +6511,24 @@ public:
SourceLocation &Ellipsis,
Optional<unsigned> &NumExpansions) const;
+ /// Given a template argument that contains an unexpanded parameter pack, but
+ /// which has already been substituted, attempt to determine the number of
+ /// elements that will be produced once this argument is fully-expanded.
+ ///
+ /// This is intended for use when transforming 'sizeof...(Arg)' in order to
+ /// avoid actually expanding the pack where possible.
+ Optional<unsigned> getFullyPackExpandedSize(TemplateArgument Arg);
+
//===--------------------------------------------------------------------===//
// C++ Template Argument Deduction (C++ [temp.deduct])
//===--------------------------------------------------------------------===//
- QualType adjustCCAndNoReturn(QualType ArgFunctionType, QualType FunctionType);
+ /// Adjust the type \p ArgFunctionType to match the calling convention,
+ /// noreturn, and optionally the exception specification of \p FunctionType.
+ /// Deduction often wants to ignore these properties when matching function
+ /// types.
+ QualType adjustCCAndNoReturn(QualType ArgFunctionType, QualType FunctionType,
+ bool AdjustExceptionSpec = false);
/// \brief Describes the result of template argument deduction.
///
@@ -6455,7 +6580,9 @@ public:
/// not be resolved to a suitable function.
TDK_FailedOverloadResolution,
/// \brief Deduction failed; that's all we know.
- TDK_MiscellaneousDeductionFailure
+ TDK_MiscellaneousDeductionFailure,
+ /// \brief CUDA Target attributes do not match.
+ TDK_CUDATargetMismatch
};
TemplateDeductionResult
@@ -6512,7 +6639,7 @@ public:
QualType ArgFunctionType,
FunctionDecl *&Specialization,
sema::TemplateDeductionInfo &Info,
- bool InOverloadResolution = false);
+ bool IsAddressOfFunction = false);
TemplateDeductionResult
DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
@@ -6525,12 +6652,12 @@ public:
TemplateArgumentListInfo *ExplicitTemplateArgs,
FunctionDecl *&Specialization,
sema::TemplateDeductionInfo &Info,
- bool InOverloadResolution = false);
+ bool IsAddressOfFunction = false);
/// \brief Substitute Replacement for \p auto in \p TypeWithAuto
QualType SubstAutoType(QualType TypeWithAuto, QualType Replacement);
/// \brief Substitute Replacement for auto in TypeWithAuto
- TypeSourceInfo* SubstAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto,
+ TypeSourceInfo* SubstAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto,
QualType Replacement);
/// \brief Result type of DeduceAutoType.
@@ -6540,10 +6667,12 @@ public:
DAR_FailedAlreadyDiagnosed
};
- DeduceAutoResult DeduceAutoType(TypeSourceInfo *AutoType, Expr *&Initializer,
- QualType &Result);
- DeduceAutoResult DeduceAutoType(TypeLoc AutoTypeLoc, Expr *&Initializer,
- QualType &Result);
+ DeduceAutoResult
+ DeduceAutoType(TypeSourceInfo *AutoType, Expr *&Initializer, QualType &Result,
+ Optional<unsigned> DependentDeductionDepth = None);
+ DeduceAutoResult
+ DeduceAutoType(TypeLoc AutoTypeLoc, Expr *&Initializer, QualType &Result,
+ Optional<unsigned> DependentDeductionDepth = None);
void DiagnoseAutoDeductionFailure(VarDecl *VDecl, Expr *Init);
bool DeduceReturnType(FunctionDecl *FD, SourceLocation Loc,
bool Diagnose = true);
@@ -6580,10 +6709,19 @@ public:
ClassTemplatePartialSpecializationDecl *PS2,
SourceLocation Loc);
+ bool isMoreSpecializedThanPrimary(ClassTemplatePartialSpecializationDecl *T,
+ sema::TemplateDeductionInfo &Info);
+
VarTemplatePartialSpecializationDecl *getMoreSpecializedPartialSpecialization(
VarTemplatePartialSpecializationDecl *PS1,
VarTemplatePartialSpecializationDecl *PS2, SourceLocation Loc);
+ bool isMoreSpecializedThanPrimary(VarTemplatePartialSpecializationDecl *T,
+ sema::TemplateDeductionInfo &Info);
+
+ bool isTemplateTemplateParameterAtLeastAsSpecializedAs(
+ TemplateParameterList *P, TemplateDecl *AArg, SourceLocation Loc);
+
void MarkUsedTemplateParameters(const TemplateArgumentList &TemplateArgs,
bool OnlyDeduced,
unsigned Depth,
@@ -6634,8 +6772,8 @@ public:
/// We are substituting template argument determined as part of
/// template argument deduction for either a class template
/// partial specialization or a function template. The
- /// Entity is either a ClassTemplatePartialSpecializationDecl or
- /// a FunctionTemplateDecl.
+ /// Entity is either a {Class|Var}TemplatePartialSpecializationDecl or
+ /// a TemplateDecl.
DeducedTemplateArgumentSubstitution,
/// We are substituting prior template arguments into a new
@@ -6857,6 +6995,14 @@ public:
SourceRange InstantiationRange = SourceRange());
/// \brief Note that we are instantiating as part of template
+ /// argument deduction for a class template declaration.
+ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ TemplateDecl *Template,
+ ArrayRef<TemplateArgument> TemplateArgs,
+ sema::TemplateDeductionInfo &DeductionInfo,
+ SourceRange InstantiationRange = SourceRange());
+
+ /// \brief Note that we are instantiating as part of template
/// argument deduction for a class template partial
/// specialization.
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
@@ -7118,7 +7264,7 @@ public:
public:
/// Set the ExtParameterInfo for the parameter at the given index,
- ///
+ ///
void set(unsigned index, FunctionProtoType::ExtParameterInfo info) {
assert(Infos.size() <= index);
Infos.resize(index);
@@ -7357,7 +7503,7 @@ public:
const SourceLocation *ProtoLocs,
SourceLocation EndProtoLoc,
AttributeList *AttrList);
-
+
void ActOnSuperClassOfClassInterface(Scope *S,
SourceLocation AtInterfaceLoc,
ObjCInterfaceDecl *IDecl,
@@ -7367,8 +7513,9 @@ public:
SourceLocation SuperLoc,
ArrayRef<ParsedType> SuperTypeArgs,
SourceRange SuperTypeArgsRange);
-
+
void ActOnTypedefedProtocols(SmallVectorImpl<Decl *> &ProtocolRefs,
+ SmallVectorImpl<SourceLocation> &ProtocolLocs,
IdentifierInfo *SuperName,
SourceLocation SuperLoc);
@@ -7475,6 +7622,14 @@ public:
ArrayRef<SourceLocation> ProtocolLocs,
SourceLocation ProtocolRAngleLoc);
+ /// Build an Objective-C type parameter type.
+ QualType BuildObjCTypeParamType(const ObjCTypeParamDecl *Decl,
+ SourceLocation ProtocolLAngleLoc,
+ ArrayRef<ObjCProtocolDecl *> Protocols,
+ ArrayRef<SourceLocation> ProtocolLocs,
+ SourceLocation ProtocolRAngleLoc,
+ bool FailOnError = false);
+
/// Build an Objective-C object pointer type.
QualType BuildObjCObjectType(QualType BaseType,
SourceLocation Loc,
@@ -7685,14 +7840,14 @@ public:
ParsedType Type,
SourceLocation RParenLoc,
Expr *SubExpr);
-
+
void CheckTollFreeBridgeCast(QualType castType, Expr *castExpr);
-
+
void CheckObjCBridgeRelatedCast(QualType castType, Expr *castExpr);
-
+
bool CheckTollFreeBridgeStaticCast(QualType castType, Expr *castExpr,
CastKind &Kind);
-
+
bool checkObjCBridgeRelatedComponents(SourceLocation Loc,
QualType DestType, QualType SrcType,
ObjCInterfaceDecl *&RelatedClass,
@@ -7932,6 +8087,58 @@ public:
void CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body);
//===--------------------------------------------------------------------===//
+ // OpenCL extensions.
+ //
+private:
+ std::string CurrOpenCLExtension;
+ /// Extensions required by an OpenCL type.
+ llvm::DenseMap<const Type*, std::set<std::string>> OpenCLTypeExtMap;
+ /// Extensions required by an OpenCL declaration.
+ llvm::DenseMap<const Decl*, std::set<std::string>> OpenCLDeclExtMap;
+public:
+ llvm::StringRef getCurrentOpenCLExtension() const {
+ return CurrOpenCLExtension;
+ }
+ void setCurrentOpenCLExtension(llvm::StringRef Ext) {
+ CurrOpenCLExtension = Ext;
+ }
+
+ /// \brief 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
+ /// 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
+ /// 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
+ /// 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
+ /// 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
+ /// is disabled due to required OpenCL extensions being disabled. If so,
+ /// emit diagnostics.
+ /// \return true if type is disabled.
+ bool checkOpenCLDisabledDecl(const Decl &D, const Expr &E);
+
+ //===--------------------------------------------------------------------===//
// OpenMP directives and clauses.
//
private:
@@ -7947,6 +8154,21 @@ private:
/// Returns OpenMP nesting level for current directive.
unsigned getOpenMPNestingLevel() const;
+ /// Checks if a type or a declaration is disabled due to the owning extension
+ /// being disabled, and emits diagnostic messages if it is disabled.
+ /// \param D type or declaration to be checked.
+ /// \param DiagLoc source location for the diagnostic message.
+ /// \param DiagInfo information to be emitted for the diagnostic message.
+ /// \param SrcRange source range of the declaration.
+ /// \param Map maps type or declaration to the extensions.
+ /// \param Selector selects diagnostic message: 0 for type and 1 for
+ /// declaration.
+ /// \return true if the type or declaration is disabled.
+ template <typename T, typename DiagLocT, typename DiagInfoT, typename MapT>
+ bool checkOpenCLDisabledTypeOrDecl(T D, DiagLocT DiagLoc, DiagInfoT DiagInfo,
+ MapT &Map, unsigned Selector = 0,
+ SourceRange SrcRange = SourceRange());
+
public:
/// \brief Return true if the provided declaration \a VD should be captured by
/// reference.
@@ -8244,6 +8466,54 @@ public:
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
+ /// the associated statement.
+ StmtResult ActOnOpenMPTargetSimdDirective(
+ ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ llvm::DenseMap<ValueDecl *, Expr *> &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);
+ /// 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);
+ /// 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);
+ /// 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);
+ /// Called on well-formed '\#pragma omp target teams' after parsing of the
+ /// associated statement.
+ StmtResult ActOnOpenMPTargetTeamsDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// Called on well-formed '\#pragma omp target teams distribute' after parsing
+ /// of the associated statement.
+ StmtResult ActOnOpenMPTargetTeamsDistributeDirective(
+ ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ llvm::DenseMap<ValueDecl *, Expr *> &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);
/// Checks correctness of linear modifiers.
bool CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind,
@@ -8565,6 +8835,11 @@ public:
// argument, and arguments that have type float are promoted to double.
ExprResult DefaultArgumentPromotion(Expr *E);
+ /// If \p E is a prvalue denoting an unmaterialized temporary, materialize
+ /// it as an xvalue. In C++98, the result will still be a prvalue, because
+ /// we don't have xvalues there.
+ ExprResult TemporaryMaterializationConversion(Expr *E);
+
// Used for emitting the right warning by DefaultVariadicArgumentPromotion
enum VariadicCallType {
VariadicFunction,
@@ -8646,8 +8921,8 @@ public:
/// are not compatible, but we accept them as an extension.
IncompatiblePointer,
- /// IncompatiblePointer - The assignment is between two pointers types which
- /// point to integers which have a different sign, but are otherwise
+ /// IncompatiblePointerSign - The assignment is between two pointers types
+ /// which point to integers which have a different sign, but are otherwise
/// identical. This is a subset of the above, but broken out because it's by
/// far the most common case of incompatible pointers.
IncompatiblePointerSign,
@@ -8728,15 +9003,23 @@ public:
CastKind &Kind,
bool ConvertRHS = true);
- // CheckSingleAssignmentConstraints - Currently used by
- // CheckAssignmentOperands, and ActOnReturnStmt. Prior to type checking,
- // this routine performs the default function/array converions, if ConvertRHS
- // is true.
- AssignConvertType CheckSingleAssignmentConstraints(QualType LHSType,
- ExprResult &RHS,
- bool Diagnose = true,
- bool DiagnoseCFAudited = false,
- bool ConvertRHS = true);
+ /// Check assignment constraints for an assignment of RHS to LHSType.
+ ///
+ /// \param LHSType The destination type for the assignment.
+ /// \param RHS The source expression for the assignment.
+ /// \param Diagnose If \c true, diagnostics may be produced when checking
+ /// for assignability. If a diagnostic is produced, \p RHS will be
+ /// set to ExprError(). Note that this function may still return
+ /// without producing a diagnostic, even for an invalid assignment.
+ /// \param DiagnoseCFAudited If \c true, the target is a function parameter
+ /// in an audited Core Foundation API and does not need to be checked
+ /// for ARC retain issues.
+ /// \param ConvertRHS If \c true, \p RHS will be updated to model the
+ /// conversions necessary to perform the assignment. If \c false,
+ /// \p Diagnose must also be \c false.
+ AssignConvertType CheckSingleAssignmentConstraints(
+ 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
// can initialize the transparent union with the given expression.
@@ -8792,8 +9075,8 @@ public:
ExprResult &LHS, ExprResult &RHS, SourceLocation Loc,
BinaryOperatorKind Opc, bool isRelational);
QualType CheckBitwiseOperands( // C99 6.5.[10...12]
- ExprResult &LHS, ExprResult &RHS, SourceLocation Loc,
- bool IsCompAssign = false);
+ ExprResult &LHS, ExprResult &RHS, SourceLocation Loc,
+ BinaryOperatorKind Opc);
QualType CheckLogicalOperands( // C99 6.5.[13,14]
ExprResult &LHS, ExprResult &RHS, SourceLocation Loc,
BinaryOperatorKind Opc);
@@ -8818,13 +9101,13 @@ public:
ExprResult &cond, ExprResult &lhs, ExprResult &rhs,
ExprValueKind &VK, ExprObjectKind &OK, SourceLocation questionLoc);
QualType FindCompositePointerType(SourceLocation Loc, Expr *&E1, Expr *&E2,
- bool *NonStandardCompositeType = nullptr);
+ bool ConvertArgs = true);
QualType FindCompositePointerType(SourceLocation Loc,
ExprResult &E1, ExprResult &E2,
- bool *NonStandardCompositeType = nullptr) {
+ bool ConvertArgs = true) {
Expr *E1Tmp = E1.get(), *E2Tmp = E2.get();
- QualType Composite = FindCompositePointerType(Loc, E1Tmp, E2Tmp,
- NonStandardCompositeType);
+ QualType Composite =
+ FindCompositePointerType(Loc, E1Tmp, E2Tmp, ConvertArgs);
E1 = E1Tmp;
E2 = E2Tmp;
return Composite;
@@ -8869,13 +9152,7 @@ public:
/// that their unqualified forms (T1 and T2) are either the same
/// or T1 is a base class of T2.
Ref_Related,
- /// Ref_Compatible_With_Added_Qualification - The two types are
- /// reference-compatible with added qualification, meaning that
- /// they are reference-compatible and the qualifiers on T1 (cv1)
- /// are greater than the qualifiers on T2 (cv2).
- Ref_Compatible_With_Added_Qualification,
- /// Ref_Compatible - The two types are reference-compatible and
- /// have equivalent qualifiers (cv1 == cv2).
+ /// Ref_Compatible - The two types are reference-compatible.
Ref_Compatible
};
@@ -9104,6 +9381,154 @@ public:
QualType FieldTy, bool IsMsStruct,
Expr *BitWidth, bool *ZeroWidth = nullptr);
+private:
+ unsigned ForceCUDAHostDeviceDepth = 0;
+
+public:
+ /// Increments our count of the number of times we've seen a pragma forcing
+ /// functions to be __host__ __device__. So long as this count is greater
+ /// than zero, all functions encountered will be __host__ __device__.
+ void PushForceCUDAHostDevice();
+
+ /// Decrements our count of the number of times we've seen a pragma forcing
+ /// functions to be __host__ __device__. Returns false if the count is 0
+ /// before incrementing, so you can emit an error.
+ bool PopForceCUDAHostDevice();
+
+ /// Diagnostics that are emitted only if we discover that the given function
+ /// must be codegen'ed. Because handling these correctly adds overhead to
+ /// compilation, this is currently only enabled for CUDA compilations.
+ llvm::DenseMap<CanonicalDeclPtr<FunctionDecl>,
+ std::vector<PartialDiagnosticAt>>
+ CUDADeferredDiags;
+
+ /// A pair of a canonical FunctionDecl and a SourceLocation. When used as the
+ /// key in a hashtable, both the FD and location are hashed.
+ struct FunctionDeclAndLoc {
+ CanonicalDeclPtr<FunctionDecl> FD;
+ SourceLocation Loc;
+ };
+
+ /// FunctionDecls and SourceLocations for which CheckCUDACall has emitted a
+ /// (maybe deferred) "bad call" diagnostic. We use this to avoid emitting the
+ /// same deferred diag twice.
+ llvm::DenseSet<FunctionDeclAndLoc> LocsWithCUDACallDiags;
+
+ /// An inverse call graph, mapping known-emitted functions to one of their
+ /// known-emitted callers (plus the location of the call).
+ ///
+ /// Functions that we can tell a priori must be emitted aren't added to this
+ /// map.
+ llvm::DenseMap</* Callee = */ CanonicalDeclPtr<FunctionDecl>,
+ /* Caller = */ FunctionDeclAndLoc>
+ CUDAKnownEmittedFns;
+
+ /// A partial call graph maintained during CUDA compilation to support
+ /// deferred diagnostics.
+ ///
+ /// Functions are only added here if, at the time they're considered, they are
+ /// not known-emitted. As soon as we discover that a function is
+ /// known-emitted, we remove it and everything it transitively calls from this
+ /// set and add those functions to CUDAKnownEmittedFns.
+ llvm::DenseMap</* Caller = */ CanonicalDeclPtr<FunctionDecl>,
+ /* Callees = */ llvm::MapVector<CanonicalDeclPtr<FunctionDecl>,
+ SourceLocation>>
+ CUDACallGraph;
+
+ /// Diagnostic builder for CUDA errors which may or may not be deferred.
+ ///
+ /// In CUDA, there exist constructs (e.g. variable-length arrays, try/catch)
+ /// which are not allowed to appear inside __device__ functions and are
+ /// allowed to appear in __host__ __device__ functions only if the host+device
+ /// function is never codegen'ed.
+ ///
+ /// To handle this, we use the notion of "deferred diagnostics", where we
+ /// attach a diagnostic to a FunctionDecl that's emitted iff it's codegen'ed.
+ ///
+ /// This class lets you emit either a regular diagnostic, a deferred
+ /// diagnostic, or no diagnostic at all, according to an argument you pass to
+ /// its constructor, thus simplifying the process of creating these "maybe
+ /// deferred" diagnostics.
+ class CUDADiagBuilder {
+ public:
+ enum Kind {
+ /// Emit no diagnostics.
+ K_Nop,
+ /// Emit the diagnostic immediately (i.e., behave like Sema::Diag()).
+ K_Immediate,
+ /// Emit the diagnostic immediately, and, if it's a warning or error, also
+ /// emit a call stack showing how this function can be reached by an a
+ /// priori known-emitted function.
+ K_ImmediateWithCallStack,
+ /// Create a deferred diagnostic, which is emitted only if the function
+ /// it's attached to is codegen'ed. Also emit a call stack as with
+ /// K_ImmediateWithCallStack.
+ K_Deferred
+ };
+
+ CUDADiagBuilder(Kind K, SourceLocation Loc, unsigned DiagID,
+ FunctionDecl *Fn, Sema &S);
+ ~CUDADiagBuilder();
+
+ /// Convertible to bool: True if we immediately emitted an error, false if
+ /// we didn't emit an error or we created a deferred error.
+ ///
+ /// Example usage:
+ ///
+ /// if (CUDADiagBuilder(...) << foo << bar)
+ /// return ExprError();
+ ///
+ /// But see CUDADiagIfDeviceCode() and CUDADiagIfHostCode() -- you probably
+ /// want to use these instead of creating a CUDADiagBuilder yourself.
+ operator bool() const { return ImmediateDiag.hasValue(); }
+
+ template <typename T>
+ friend const CUDADiagBuilder &operator<<(const CUDADiagBuilder &Diag,
+ const T &Value) {
+ if (Diag.ImmediateDiag.hasValue())
+ *Diag.ImmediateDiag << Value;
+ else if (Diag.PartialDiag.hasValue())
+ *Diag.PartialDiag << Value;
+ return Diag;
+ }
+
+ private:
+ Sema &S;
+ SourceLocation Loc;
+ unsigned DiagID;
+ FunctionDecl *Fn;
+ bool ShowCallStack;
+
+ // Invariant: At most one of these Optionals has a value.
+ // FIXME: Switch these to a Variant once that exists.
+ llvm::Optional<SemaDiagnosticBuilder> ImmediateDiag;
+ llvm::Optional<PartialDiagnostic> PartialDiag;
+ };
+
+ /// Creates a CUDADiagBuilder that emits the diagnostic if the current context
+ /// is "used as device code".
+ ///
+ /// - If CurContext is a __host__ function, does not emit any diagnostics.
+ /// - If CurContext is a __device__ or __global__ function, emits the
+ /// diagnostics immediately.
+ /// - If CurContext is a __host__ __device__ function and we are compiling for
+ /// the device, creates a diagnostic which is emitted if and when we realize
+ /// that the function will be codegen'ed.
+ ///
+ /// Example usage:
+ ///
+ /// // Variable-length arrays are not allowed in CUDA device code.
+ /// if (CUDADiagIfDeviceCode(Loc, diag::err_cuda_vla) << CurrentCUDATarget())
+ /// return ExprError();
+ /// // Otherwise, continue parsing as normal.
+ CUDADiagBuilder CUDADiagIfDeviceCode(SourceLocation Loc, unsigned DiagID);
+
+ /// Creates a CUDADiagBuilder that emits the diagnostic if the current context
+ /// is "used as host code".
+ ///
+ /// Same as CUDADiagIfDeviceCode, with "host" and "device" switched.
+ CUDADiagBuilder CUDADiagIfHostCode(SourceLocation Loc, unsigned DiagID);
+
enum CUDAFunctionTarget {
CFT_Device,
CFT_Global,
@@ -9112,7 +9537,19 @@ public:
CFT_InvalidTarget
};
- CUDAFunctionTarget IdentifyCUDATarget(const FunctionDecl *D);
+ /// Determines whether the given function is a CUDA device/host/kernel/etc.
+ /// function.
+ ///
+ /// Use this rather than examining the function's attributes yourself -- you
+ /// will get it wrong. Returns CFT_Host if D is null.
+ CUDAFunctionTarget IdentifyCUDATarget(const FunctionDecl *D,
+ bool IgnoreImplicitHDAttr = false);
+ CUDAFunctionTarget IdentifyCUDATarget(const AttributeList *Attr);
+
+ /// Gets the CUDA target for the current context.
+ CUDAFunctionTarget CurrentCUDATarget() {
+ return IdentifyCUDATarget(dyn_cast<FunctionDecl>(CurContext));
+ }
// CUDA function call preference. Must be ordered numerically from
// worst to best.
@@ -9120,8 +9557,7 @@ public:
CFP_Never, // Invalid caller/callee combination.
CFP_WrongSide, // Calls from host-device to host or device
// function that do not match current compilation
- // mode. Only in effect if
- // LangOpts.CUDADisableTargetCallChecks is true.
+ // mode.
CFP_HostDevice, // Any calls to host/device functions.
CFP_SameSide, // Calls from host-device to host or device
// function matching current compilation mode.
@@ -9139,23 +9575,48 @@ public:
const FunctionDecl *Callee);
/// Determines whether Caller may invoke Callee, based on their CUDA
- /// host/device attributes. Returns true if the call is not allowed.
- bool CheckCUDATarget(const FunctionDecl *Caller, const FunctionDecl *Callee) {
- return IdentifyCUDAPreference(Caller, Callee) == CFP_Never;
+ /// host/device attributes. Returns false if the call is not allowed.
+ ///
+ /// Note: Will return true for CFP_WrongSide calls. These may appear in
+ /// semantically correct CUDA programs, but only if they're never codegen'ed.
+ bool IsAllowedCUDACall(const FunctionDecl *Caller,
+ const FunctionDecl *Callee) {
+ return IdentifyCUDAPreference(Caller, Callee) != CFP_Never;
}
/// May add implicit CUDAHostAttr and CUDADeviceAttr attributes to FD,
/// depending on FD and the current compilation settings.
- void maybeAddCUDAHostDeviceAttrs(Scope *S, FunctionDecl *FD,
+ void maybeAddCUDAHostDeviceAttrs(FunctionDecl *FD,
const LookupResult &Previous);
+public:
+ /// Check whether we're allowed to call Callee from the current context.
+ ///
+ /// - If the call is never allowed in a semantically-correct program
+ /// (CFP_Never), emits an error and returns false.
+ ///
+ /// - If the call is allowed in semantically-correct programs, but only if
+ /// it's never codegen'ed (CFP_WrongSide), creates a deferred diagnostic to
+ /// be emitted if and when the caller is codegen'ed, and returns true.
+ ///
+ /// Will only create deferred diagnostics for a given SourceLocation once,
+ /// so you can safely call this multiple times without generating duplicate
+ /// deferred errors.
+ ///
+ /// - Otherwise, returns true without emitting any diagnostics.
+ bool CheckCUDACall(SourceLocation Loc, FunctionDecl *Callee);
+
+ /// Set __device__ or __host__ __device__ attributes on the given lambda
+ /// operator() method.
+ ///
+ /// CUDA lambdas declared inside __device__ or __global__ functions inherit
+ /// the __device__ attribute. Similarly, lambdas inside __host__ __device__
+ /// functions become __host__ __device__ themselves.
+ void CUDASetLambdaAttrs(CXXMethodDecl *Method);
+
/// Finds a function in \p Matches with highest calling priority
/// from \p Caller context and erases all functions with lower
/// calling priority.
- void EraseUnwantedCUDAMatches(const FunctionDecl *Caller,
- SmallVectorImpl<FunctionDecl *> &Matches);
- void EraseUnwantedCUDAMatches(const FunctionDecl *Caller,
- SmallVectorImpl<DeclAccessPair> &Matches);
void EraseUnwantedCUDAMatches(
const FunctionDecl *Caller,
SmallVectorImpl<std::pair<DeclAccessPair, FunctionDecl *>> &Matches);
@@ -9182,6 +9643,13 @@ public:
bool isEmptyCudaConstructor(SourceLocation Loc, CXXConstructorDecl *CD);
bool isEmptyCudaDestructor(SourceLocation Loc, CXXDestructorDecl *CD);
+ /// Check whether NewFD is a valid overload for CUDA. Emits
+ /// diagnostics and invalidates NewFD if not.
+ void checkCUDATargetOverload(FunctionDecl *NewFD,
+ const LookupResult &Previous);
+ /// Copies target attributes from the template TD to the function FD.
+ void inheritCUDATargetAttrs(FunctionDecl *FD, const FunctionTemplateDecl &TD);
+
/// \name Code completion
//@{
/// \brief Describes the context in which code completion occurs.
@@ -9241,8 +9709,8 @@ public:
void CodeCompleteExpression(Scope *S,
const CodeCompleteExpressionData &Data);
void CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
- SourceLocation OpLoc,
- bool IsArrow);
+ SourceLocation OpLoc, bool IsArrow,
+ bool IsBaseExprStatement);
void CodeCompletePostfixExpression(Scope *S, ExprResult LHS);
void CodeCompleteTag(Scope *S, unsigned TagSpec);
void CodeCompleteTypeQualifiers(DeclSpec &DS);
@@ -9320,6 +9788,9 @@ public:
bool AtParameterName,
ParsedType ReturnType,
ArrayRef<IdentifierInfo *> SelIdents);
+ void CodeCompleteObjCClassPropertyRefExpr(Scope *S, IdentifierInfo &ClassName,
+ SourceLocation ClassNameLoc,
+ bool IsBaseExprStatement);
void CodeCompletePreprocessorDirective(bool InConditional);
void CodeCompleteInPreprocessorConditionalExclusion(Scope *S);
void CodeCompletePreprocessorMacroName(bool IsDefinition);
@@ -9369,11 +9840,12 @@ private:
SourceLocation Loc);
void checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto,
- ArrayRef<const Expr *> Args, bool IsMemberFunction,
- SourceLocation Loc, SourceRange Range,
+ ArrayRef<const Expr *> Args, bool IsMemberFunction,
+ SourceLocation Loc, SourceRange Range,
VariadicCallType CallType);
bool CheckObjCString(Expr *Arg);
+ ExprResult CheckOSLogFormatStringArg(Expr *Arg);
ExprResult CheckBuiltinFunctionCall(FunctionDecl *FDecl,
unsigned BuiltinID, CallExpr *TheCall);
@@ -9386,6 +9858,7 @@ private:
bool CheckAArch64BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
bool CheckMipsBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
bool CheckSystemZBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
+ bool CheckX86BuiltinRoundingOrSAE(unsigned BuiltinID, CallExpr *TheCall);
bool CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
bool CheckPPCBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
@@ -9395,6 +9868,7 @@ private:
bool SemaBuiltinVAStartARM(CallExpr *Call);
bool SemaBuiltinUnorderedCompare(CallExpr *TheCall);
bool SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs);
+ bool SemaBuiltinOSLogFormat(CallExpr *TheCall);
public:
// Used by C++ template instantiation.
@@ -9405,6 +9879,7 @@ public:
private:
bool SemaBuiltinPrefetch(CallExpr *TheCall);
+ bool SemaBuiltinAllocaWithAlign(CallExpr *TheCall);
bool SemaBuiltinAssume(CallExpr *TheCall);
bool SemaBuiltinAssumeAligned(CallExpr *TheCall);
bool SemaBuiltinLongjmp(CallExpr *TheCall);
@@ -9432,12 +9907,13 @@ public:
FST_Kprintf,
FST_FreeBSDKPrintf,
FST_OSTrace,
+ FST_OSLog,
FST_Unknown
};
static FormatStringType GetFormatStringType(const FormatAttr *Format);
bool FormatStringHasSArg(const StringLiteral *FExpr);
-
+
static bool GetFormatNSStringIdx(const FormatAttr *Format, unsigned &Idx);
private:
@@ -9455,8 +9931,9 @@ private:
llvm::SmallBitVector &CheckedVarArgs);
void CheckAbsoluteValueFunction(const CallExpr *Call,
- const FunctionDecl *FDecl,
- IdentifierInfo *FnInfo);
+ const FunctionDecl *FDecl);
+
+ void CheckMaxUnsignedZero(const CallExpr *Call, const FunctionDecl *FDecl);
void CheckMemaccessArguments(const CallExpr *Call,
unsigned BId,
@@ -9535,6 +10012,10 @@ private:
void CheckArgumentWithTypeTag(const ArgumentWithTypeTagAttr *Attr,
const Expr * const *ExprArgs);
+ /// \brief 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 maintains this state here.
@@ -9590,8 +10071,17 @@ public:
return OriginalLexicalContext ? OriginalLexicalContext : CurContext;
}
- AvailabilityResult getCurContextAvailability() const;
-
+ /// \brief The diagnostic we should emit for \c D, or \c AR_Available.
+ ///
+ /// \param D The declaration to check. Note that this may be altered to point
+ /// to another declaration that \c D gets it's availability from. i.e., we
+ /// walk the list of typedefs to find an availability attribute.
+ ///
+ /// \param Message If non-null, this will be populated with the message from
+ /// the availability attribute that is selected.
+ AvailabilityResult ShouldDiagnoseAvailabilityOfDecl(NamedDecl *&D,
+ std::string *Message);
+
const DeclContext *getCurObjCLexicalContext() const {
const DeclContext *DC = getCurLexicalContext();
// A category implicitly has the attribute of the interface.
@@ -9613,6 +10103,53 @@ public:
// Emitting members of dllexported classes is delayed until the class
// (including field initializers) is fully parsed.
SmallVector<CXXRecordDecl*, 4> DelayedDllExportClasses;
+
+private:
+ /// \brief Helper class that collects misaligned member designations and
+ /// their location info for delayed diagnostics.
+ struct MisalignedMember {
+ Expr *E;
+ RecordDecl *RD;
+ ValueDecl *MD;
+ CharUnits Alignment;
+
+ MisalignedMember() : E(), RD(), MD(), Alignment() {}
+ MisalignedMember(Expr *E, RecordDecl *RD, ValueDecl *MD,
+ CharUnits Alignment)
+ : E(E), RD(RD), MD(MD), Alignment(Alignment) {}
+ explicit MisalignedMember(Expr *E)
+ : MisalignedMember(E, nullptr, nullptr, CharUnits()) {}
+
+ bool operator==(const MisalignedMember &m) { return this->E == m.E; }
+ };
+ /// \brief 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.
+ void AddPotentialMisalignedMembers(Expr *E, RecordDecl *RD, ValueDecl *MD,
+ CharUnits Alignment);
+
+public:
+ /// \brief 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
+ /// 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
+ /// misaligned member due to the packed attribute. This is used to emit
+ /// local diagnostics like in reference binding.
+ void RefersToMemberWithReducedAlignment(
+ Expr *E,
+ llvm::function_ref<void(Expr *, RecordDecl *, FieldDecl *, CharUnits)>
+ Action);
};
/// \brief RAII object that enters a new expression evaluation context.
@@ -9636,7 +10173,7 @@ public:
Sema::ReuseLambdaContextDecl_t,
bool IsDecltype = false)
: Actions(Actions) {
- Actions.PushExpressionEvaluationContext(NewContext,
+ Actions.PushExpressionEvaluationContext(NewContext,
Sema::ReuseLambdaContextDecl,
IsDecltype);
}
@@ -9661,4 +10198,31 @@ struct LateParsedTemplate {
} // end namespace clang
+namespace llvm {
+// Hash a FunctionDeclAndLoc by looking at both its FunctionDecl and its
+// SourceLocation.
+template <> struct DenseMapInfo<clang::Sema::FunctionDeclAndLoc> {
+ using FunctionDeclAndLoc = clang::Sema::FunctionDeclAndLoc;
+ using FDBaseInfo = DenseMapInfo<clang::CanonicalDeclPtr<clang::FunctionDecl>>;
+
+ static FunctionDeclAndLoc getEmptyKey() {
+ return {FDBaseInfo::getEmptyKey(), clang::SourceLocation()};
+ }
+
+ static FunctionDeclAndLoc getTombstoneKey() {
+ return {FDBaseInfo::getTombstoneKey(), clang::SourceLocation()};
+ }
+
+ static unsigned getHashValue(const FunctionDeclAndLoc &FDL) {
+ return hash_combine(FDBaseInfo::getHashValue(FDL.FD),
+ FDL.Loc.getRawEncoding());
+ }
+
+ static bool isEqual(const FunctionDeclAndLoc &LHS,
+ const FunctionDeclAndLoc &RHS) {
+ return LHS.FD == RHS.FD && LHS.Loc == RHS.Loc;
+ }
+};
+} // namespace llvm
+
#endif
diff --git a/include/clang/Sema/SemaInternal.h b/include/clang/Sema/SemaInternal.h
index 76567f3b77f4..a01e8d639f60 100644
--- a/include/clang/Sema/SemaInternal.h
+++ b/include/clang/Sema/SemaInternal.h
@@ -333,12 +333,12 @@ private:
inline Sema::TypoExprState::TypoExprState() {}
-inline Sema::TypoExprState::TypoExprState(TypoExprState &&other) LLVM_NOEXCEPT {
+inline Sema::TypoExprState::TypoExprState(TypoExprState &&other) noexcept {
*this = std::move(other);
}
-inline Sema::TypoExprState &Sema::TypoExprState::operator=(
- Sema::TypoExprState &&other) LLVM_NOEXCEPT {
+inline Sema::TypoExprState &Sema::TypoExprState::
+operator=(Sema::TypoExprState &&other) noexcept {
Consumer = std::move(other.Consumer);
DiagHandler = std::move(other.DiagHandler);
RecoveryHandler = std::move(other.RecoveryHandler);
diff --git a/include/clang/Sema/Template.h b/include/clang/Sema/Template.h
index c0926304cf43..401bbbf1e566 100644
--- a/include/clang/Sema/Template.h
+++ b/include/clang/Sema/Template.h
@@ -410,6 +410,7 @@ namespace clang {
#define OBJCCONTAINER(DERIVED, BASE)
#define FILESCOPEASM(DERIVED, BASE)
#define IMPORT(DERIVED, BASE)
+#define EXPORT(DERIVED, BASE)
#define LINKAGESPEC(DERIVED, BASE)
#define OBJCCOMPATIBLEALIAS(DERIVED, BASE)
#define OBJCMETHOD(DERIVED, BASE)
@@ -433,7 +434,8 @@ namespace clang {
Decl *VisitFunctionDecl(FunctionDecl *D,
TemplateParameterList *TemplateParams);
Decl *VisitDecl(Decl *D);
- Decl *VisitVarDecl(VarDecl *D, bool InstantiatingVarTemplate);
+ Decl *VisitVarDecl(VarDecl *D, bool InstantiatingVarTemplate,
+ ArrayRef<BindingDecl *> *Bindings = nullptr);
// Enable late instantiation of attributes. Late instantiated attributes
// will be stored in LA.
@@ -513,6 +515,11 @@ namespace clang {
VarTemplateDecl *VarTemplate,
VarTemplatePartialSpecializationDecl *PartialSpec);
void InstantiateEnumDefinition(EnumDecl *Enum, EnumDecl *Pattern);
+
+ private:
+ template<typename T>
+ Decl *instantiateUnresolvedUsingDecl(T *D,
+ bool InstantiatingPackElement = false);
};
}
diff --git a/include/clang/Sema/TemplateDeduction.h b/include/clang/Sema/TemplateDeduction.h
index ed1e768832cc..f4a706ecb9ab 100644
--- a/include/clang/Sema/TemplateDeduction.h
+++ b/include/clang/Sema/TemplateDeduction.h
@@ -40,6 +40,9 @@ class TemplateDeductionInfo {
/// \brief Have we suppressed an error during deduction?
bool HasSFINAEDiagnostic;
+ /// \brief The template parameter depth for which we're performing deduction.
+ unsigned DeducedDepth;
+
/// \brief Warnings (and follow-on notes) that were suppressed due to
/// SFINAE while performing template argument deduction.
SmallVector<PartialDiagnosticAt, 4> SuppressedDiagnostics;
@@ -48,9 +51,9 @@ class TemplateDeductionInfo {
void operator=(const TemplateDeductionInfo &) = delete;
public:
- TemplateDeductionInfo(SourceLocation Loc)
+ TemplateDeductionInfo(SourceLocation Loc, unsigned DeducedDepth = 0)
: Deduced(nullptr), Loc(Loc), HasSFINAEDiagnostic(false),
- Expression(nullptr) {}
+ DeducedDepth(DeducedDepth), Expression(nullptr) {}
/// \brief Returns the location at which template argument is
/// occurring.
@@ -58,6 +61,12 @@ public:
return Loc;
}
+ /// \brief 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.
TemplateArgumentList *take() {
TemplateArgumentList *Result = Deduced;
@@ -70,6 +79,11 @@ public:
assert(HasSFINAEDiagnostic);
PD.first = SuppressedDiagnostics.front().first;
PD.second.swap(SuppressedDiagnostics.front().second);
+ clearSFINAEDiagnostic();
+ }
+
+ /// \brief Discard any SFINAE diagnostics.
+ void clearSFINAEDiagnostic() {
SuppressedDiagnostics.clear();
HasSFINAEDiagnostic = false;
}
@@ -199,10 +213,7 @@ struct DeductionFailureInfo {
void *Data;
/// \brief A diagnostic indicating why deduction failed.
- union {
- void *Align;
- char Diagnostic[sizeof(PartialDiagnosticAt)];
- };
+ alignas(PartialDiagnosticAt) char Diagnostic[sizeof(PartialDiagnosticAt)];
/// \brief Retrieve the diagnostic which caused this deduction failure,
/// if any.
diff --git a/include/clang/Sema/TypoCorrection.h b/include/clang/Sema/TypoCorrection.h
index 3b0385ef2a9d..5bebe52325c6 100644
--- a/include/clang/Sema/TypoCorrection.h
+++ b/include/clang/Sema/TypoCorrection.h
@@ -230,6 +230,15 @@ public:
bool requiresImport() const { return RequiresImport; }
void setRequiresImport(bool Req) { RequiresImport = Req; }
+ /// Extra diagnostics are printed after the first diagnostic for the typo.
+ /// This can be used to attach external notes to the diag.
+ void addExtraDiagnostic(PartialDiagnostic PD) {
+ ExtraDiagnostics.push_back(std::move(PD));
+ }
+ ArrayRef<PartialDiagnostic> getExtraDiagnostics() const {
+ return ExtraDiagnostics;
+ }
+
private:
bool hasCorrectionDecl() const {
return (!isKeyword() && !CorrectionDecls.empty());
@@ -245,6 +254,8 @@ private:
SourceRange CorrectionRange;
bool ForceSpecifierReplacement;
bool RequiresImport;
+
+ std::vector<PartialDiagnostic> ExtraDiagnostics;
};
/// @brief Base class for callback objects used by Sema::CorrectTypo to check
diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h
index 79c6a0622257..861fe64096af 100644
--- a/include/clang/Serialization/ASTBitCodes.h
+++ b/include/clang/Serialization/ASTBitCodes.h
@@ -344,7 +344,7 @@ namespace clang {
///
/// The TYPE_OFFSET constant describes the record that occurs
/// within the AST block. The record itself is an array of offsets that
- /// point into the declarations and types block (identified by
+ /// point into the declarations and types block (identified by
/// DECLTYPES_BLOCK_ID). The index into the array is based on the ID
/// of a type. For a given type ID @c T, the lower three bits of
/// @c T are its qualifiers (const, volatile, restrict), as in
@@ -446,10 +446,10 @@ namespace clang {
/// \brief 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.
UNUSED_FILESCOPED_DECLS = 17,
-
+
/// \brief Record code for the table of offsets to entries in the
/// preprocessing record.
PPD_ENTITIES_OFFSETS = 18,
@@ -465,7 +465,7 @@ namespace clang {
/// \brief 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.
@@ -490,7 +490,7 @@ namespace clang {
// ID 30 used to be a decl update record. These are now in the DECLTYPES
// block.
-
+
// ID 31 used to be a list of offsets to DECL_CXX_BASE_SPECIFIERS records.
/// \brief Record code for \#pragma diagnostic mappings.
@@ -498,7 +498,7 @@ namespace clang {
/// \brief Record code for special CUDA declarations.
CUDA_SPECIAL_DECL_REFS = 33,
-
+
/// \brief Record code for header search information.
HEADER_SEARCH_TABLE = 34,
@@ -516,7 +516,7 @@ namespace clang {
KNOWN_NAMESPACES = 38,
/// \brief Record code for the remapping information used to relate
- /// loaded modules to the various offsets and IDs(e.g., source location
+ /// 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,
@@ -525,20 +525,20 @@ namespace clang {
/// which stores information about \#line directives.
SOURCE_MANAGER_LINE_TABLE = 40,
- /// \brief Record code for map of Objective-C class definition IDs to the
+ /// \brief 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.
FILE_SORTED_DECLS = 42,
-
+
/// \brief 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
/// extensions).
///
@@ -580,7 +580,17 @@ namespace clang {
MSSTRUCT_PRAGMA_OPTIONS = 55,
/// \brief Record code for \#pragma ms_struct options.
- POINTERS_TO_MEMBERS_PRAGMA_OPTIONS = 56
+ POINTERS_TO_MEMBERS_PRAGMA_OPTIONS = 56,
+
+ /// \brief 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.
+ OPENCL_EXTENSION_TYPES = 58,
+
+ /// \brief Record code for declarations associated with OpenCL extensions.
+ OPENCL_EXTENSION_DECLS = 59,
};
/// \brief Record types used within a source manager block.
@@ -684,6 +694,9 @@ namespace clang {
/// \brief Specifies a header that is private to this submodule but
/// must be textually included.
SUBMODULE_PRIVATE_TEXTUAL_HEADER = 15,
+ /// \brief Specifies some declarations with initializers that must be
+ /// emitted to initialize the module.
+ SUBMODULE_INITIALIZERS = 16,
};
/// \brief Record types used within a comments block.
@@ -899,7 +912,9 @@ namespace clang {
/// \brief An AdjustedType record.
TYPE_ADJUSTED = 42,
/// \brief A PipeType record.
- TYPE_PIPE = 43
+ TYPE_PIPE = 43,
+ /// \brief An ObjCTypeParamType record.
+ TYPE_OBJC_TYPE_PARAM = 44
};
/// \brief The type IDs for special types constructed by semantic
@@ -1053,6 +1068,10 @@ namespace clang {
DECL_IMPLICIT_PARAM,
/// \brief A ParmVarDecl record.
DECL_PARM_VAR,
+ /// \brief A DecompositionDecl record.
+ DECL_DECOMPOSITION,
+ /// \brief A BindingDecl record.
+ DECL_BINDING,
/// \brief A FileScopeAsmDecl record.
DECL_FILE_SCOPE_ASM,
/// \brief A BlockDecl record.
@@ -1084,6 +1103,8 @@ namespace clang {
DECL_NAMESPACE_ALIAS,
/// \brief A UsingDecl record.
DECL_USING,
+ /// \brief A UsingPackDecl record.
+ DECL_USING_PACK,
/// \brief A UsingShadowDecl record.
DECL_USING_SHADOW,
/// \brief A ConstructorUsingShadowDecl record.
@@ -1096,6 +1117,8 @@ namespace clang {
DECL_UNRESOLVED_USING_TYPENAME,
/// \brief A LinkageSpecDecl record.
DECL_LINKAGE_SPEC,
+ /// \brief An ExportDecl record.
+ DECL_EXPORT,
/// \brief A CXXRecordDecl record.
DECL_CXX_RECORD,
/// \brief A CXXMethodDecl record.
@@ -1277,10 +1300,14 @@ namespace clang {
EXPR_DESIGNATED_INIT,
/// \brief A DesignatedInitUpdateExpr record.
EXPR_DESIGNATED_INIT_UPDATE,
- /// \brief An ImplicitValueInitExpr record.
- EXPR_IMPLICIT_VALUE_INIT,
/// \brief An NoInitExpr record.
EXPR_NO_INIT,
+ /// \brief An ArrayInitLoopExpr record.
+ EXPR_ARRAY_INIT_LOOP,
+ /// \brief An ArrayInitIndexExpr record.
+ EXPR_ARRAY_INIT_INDEX,
+ /// \brief An ImplicitValueInitExpr record.
+ EXPR_IMPLICIT_VALUE_INIT,
/// \brief A VAArgExpr record.
EXPR_VA_ARG,
/// \brief An AddrLabelExpr record.
@@ -1481,6 +1508,14 @@ namespace clang {
STMT_OMP_DISTRIBUTE_PARALLEL_FOR_SIMD_DIRECTIVE,
STMT_OMP_DISTRIBUTE_SIMD_DIRECTIVE,
STMT_OMP_TARGET_PARALLEL_FOR_SIMD_DIRECTIVE,
+ STMT_OMP_TARGET_SIMD_DIRECTIVE,
+ STMT_OMP_TEAMS_DISTRIBUTE_DIRECTIVE,
+ STMT_OMP_TEAMS_DISTRIBUTE_SIMD_DIRECTIVE,
+ STMT_OMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_DIRECTIVE,
+ STMT_OMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_DIRECTIVE,
+ STMT_OMP_TARGET_TEAMS_DIRECTIVE,
+ STMT_OMP_TARGET_TEAMS_DISTRIBUTE_DIRECTIVE,
+ STMT_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_DIRECTIVE,
EXPR_OMP_ARRAY_SECTION,
// ARC
diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h
index 18e23870a765..5230e2ae0013 100644
--- a/include/clang/Serialization/ASTReader.h
+++ b/include/clang/Serialization/ASTReader.h
@@ -18,10 +18,8 @@
#include "clang/AST/DeclarationName.h"
#include "clang/AST/TemplateBase.h"
#include "clang/Basic/Diagnostic.h"
-#include "clang/Basic/FileManager.h"
#include "clang/Basic/FileSystemOptions.h"
#include "clang/Basic/IdentifierTable.h"
-#include "clang/Basic/SourceManager.h"
#include "clang/Basic/Version.h"
#include "clang/Lex/ExternalPreprocessorSource.h"
#include "clang/Lex/HeaderSearch.h"
@@ -33,9 +31,6 @@
#include "clang/Serialization/Module.h"
#include "clang/Serialization/ModuleFileExtension.h"
#include "clang/Serialization/ModuleManager.h"
-#include "llvm/ADT/APFloat.h"
-#include "llvm/ADT/APInt.h"
-#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallSet.h"
@@ -43,22 +38,27 @@
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/TinyPtrVector.h"
-#include "llvm/Bitcode/BitstreamReader.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/Timer.h"
#include <deque>
-#include <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>
namespace llvm {
+ class BitstreamCursor;
class MemoryBuffer;
+ class APInt;
+ class APSInt;
+ class APFloat;
}
namespace clang {
+class SourceManager;
+class HeaderSearchOptions;
+class FileManager;
class AddrLabelExpr;
class ASTConsumer;
class ASTContext;
@@ -89,6 +89,7 @@ class ASTWriter;
class ASTReader;
class ASTDeclReader;
class ASTStmtReader;
+class ASTRecordReader;
class TypeLocReader;
struct HeaderFileInfo;
class VersionTuple;
@@ -285,6 +286,21 @@ private:
void Error(const char *Msg);
};
+/// \brief 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.
+class SimpleASTReaderListener : public ASTReaderListener {
+ Preprocessor &PP;
+
+public:
+ SimpleASTReaderListener(Preprocessor &PP)
+ : PP(PP) {}
+
+ bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts, bool Complain,
+ std::string &SuggestedPredefines) override;
+};
+
namespace serialization {
class ReadMethodPoolVisitor;
@@ -342,7 +358,7 @@ public:
/// \brief The AST file has errors.
HadErrors
};
-
+
/// \brief Types of AST files.
friend class PCHValidator;
friend class ASTDeclReader;
@@ -350,6 +366,7 @@ public:
friend class ASTIdentifierIterator;
friend class serialization::reader::ASTIdentifierLookupTrait;
friend class TypeLocReader;
+ friend class ASTRecordReader;
friend class ASTWriter;
friend class ASTUnit; // ASTUnit needs to remap source locations.
friend class serialization::ReadMethodPoolVisitor;
@@ -758,6 +775,10 @@ private:
/// Sema tracks these to emit warnings.
SmallVector<uint64_t, 16> UnusedLocalTypedefNameCandidates;
+ /// \brief Our current depth in #pragma cuda force_host_device begin/end
+ /// macros.
+ unsigned ForceCUDAHostDeviceDepth = 0;
+
/// \brief The IDs of the declarations Sema stores directly.
///
/// Sema tracks a few important decls, such as namespace std, directly.
@@ -788,7 +809,13 @@ private:
SourceLocation PointersToMembersPragmaLocation;
/// \brief The OpenCL extension settings.
- SmallVector<uint64_t, 1> OpenCLExtensions;
+ OpenCLOptions OpenCLExtensions;
+
+ /// \brief Extensions required by an OpenCL type.
+ llvm::DenseMap<const Type *, std::set<std::string>> OpenCLTypeExtMap;
+
+ /// \brief Extensions required by an OpenCL declaration.
+ llvm::DenseMap<const Decl *, std::set<std::string>> OpenCLDeclExtMap;
/// \brief A list of the namespaces we've seen.
SmallVector<uint64_t, 4> KnownNamespaces;
@@ -803,6 +830,7 @@ private:
// \brief A list of late parsed template function data.
SmallVector<uint64_t, 1> LateParsedTemplates;
+public:
struct ImportedSubmodule {
serialization::SubmoduleID ID;
SourceLocation ImportLoc;
@@ -811,6 +839,7 @@ private:
: ID(ID), ImportLoc(ImportLoc) {}
};
+private:
/// \brief A list of modules that were imported by precompiled headers or
/// any other non-module AST file.
SmallVector<ImportedSubmodule, 2> ImportedModules;
@@ -1154,7 +1183,7 @@ private:
static ASTReadResult ReadOptionsBlock(
llvm::BitstreamCursor &Stream, unsigned ClientLoadCapabilities,
bool AllowCompatibleConfigurationMismatch, ASTReaderListener &Listener,
- std::string &SuggestedPredefines);
+ std::string &SuggestedPredefines, bool ValidateDiagnosticOptions);
ASTReadResult ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities);
ASTReadResult ReadExtensionBlock(ModuleFile &F);
bool ParseLineTable(ModuleFile &F, const RecordData &Record);
@@ -1386,9 +1415,13 @@ public:
/// \param ClientLoadCapabilities The set of client load-failure
/// capabilities, represented as a bitset of the enumerators of
/// LoadFailureCapabilities.
+ ///
+ /// \param Imported optional out-parameter to append the list of modules
+ /// that were imported by precompiled headers or any other non-module AST file
ASTReadResult ReadAST(StringRef FileName, ModuleKind Type,
SourceLocation ImportLoc,
- unsigned ClientLoadCapabilities);
+ unsigned ClientLoadCapabilities,
+ SmallVectorImpl<ImportedSubmodule> *Imported = nullptr);
/// \brief Make the entities in the given module and any of its (non-explicit)
/// submodules visible to name lookup.
@@ -1406,6 +1439,10 @@ public:
/// \brief 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
+ /// Def, so Def should be visible whenever MergedDef is.
+ void mergeDefinitionVisibility(NamedDecl *Def, NamedDecl *MergedDef);
+
/// \brief Take the AST callbacks listener.
std::unique_ptr<ASTReaderListener> takeListener() {
return std::move(Listener);
@@ -1517,7 +1554,8 @@ public:
readASTFileControlBlock(StringRef Filename, FileManager &FileMgr,
const PCHContainerReader &PCHContainerRdr,
bool FindModuleFileExtensions,
- ASTReaderListener &Listener);
+ ASTReaderListener &Listener,
+ bool ValidateDiagnosticOptions);
/// \brief Determine whether the given AST file is acceptable to load into a
/// translation unit with the given language and target options.
@@ -1854,8 +1892,8 @@ public:
SourceLocation> > &Pending) override;
void ReadLateParsedTemplates(
- llvm::MapVector<const FunctionDecl *, LateParsedTemplate *> &LPTMap)
- override;
+ llvm::MapVector<const FunctionDecl *, std::unique_ptr<LateParsedTemplate>>
+ &LPTMap) override;
/// \brief Load a selector from disk, registering its ID if it exists.
void LoadSelector(Selector Sel);
@@ -1910,7 +1948,7 @@ public:
/// number.
serialization::SubmoduleID
getGlobalSubmoduleID(ModuleFile &M, unsigned LocalID);
-
+
/// \brief Retrieve the submodule that corresponds to a global submodule ID.
///
Module *getSubmodule(serialization::SubmoduleID GlobalID);
@@ -2154,6 +2192,287 @@ public:
bool isProcessingUpdateRecords() { return ProcessingUpdateRecords; }
};
+/// \brief An object for streaming information from a record.
+class ASTRecordReader {
+ typedef serialization::ModuleFile ModuleFile;
+
+ ASTReader *Reader;
+ ModuleFile *F;
+ unsigned Idx = 0;
+ ASTReader::RecordData Record;
+
+ typedef ASTReader::RecordData RecordData;
+ typedef ASTReader::RecordDataImpl RecordDataImpl;
+
+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
+ /// internal state.
+ unsigned readRecord(llvm::BitstreamCursor &Cursor, unsigned AbbrevID);
+
+ /// \brief 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.
+ ASTContext &getContext() { return Reader->getContext(); }
+
+ /// \brief The current position in this record.
+ unsigned getIdx() const { return Idx; }
+ /// \brief The length of this record.
+ size_t size() const { return Record.size(); }
+
+ /// \brief An arbitrary index in this record.
+ const uint64_t &operator[](size_t N) { return Record[N]; }
+ /// \brief The last element in this record.
+ const uint64_t &back() const { return Record.back(); }
+
+ /// \brief Returns the current value in this record, and advances to the
+ /// next value.
+ const uint64_t &readInt() { return Record[Idx++]; }
+ /// \brief Returns the current value in this record, without advancing.
+ const uint64_t &peekInt() { return Record[Idx]; }
+
+ /// \brief Skips the specified number of values.
+ void skipInts(unsigned N) { Idx += N; }
+
+ /// \brief 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.
+ Module *getSubmodule(serialization::SubmoduleID GlobalID) {
+ return Reader->getSubmodule(GlobalID);
+ }
+
+ /// \brief 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.
+ bool readVisibleDeclContextStorage(uint64_t Offset,
+ serialization::DeclID ID) {
+ return Reader->ReadVisibleDeclContextStorage(*F, F->DeclsCursor, Offset,
+ ID);
+ }
+
+ void readExceptionSpec(SmallVectorImpl<QualType> &ExceptionStorage,
+ FunctionProtoType::ExceptionSpecInfo &ESI) {
+ return Reader->readExceptionSpec(*F, ExceptionStorage, ESI, Record, Idx);
+ }
+
+ /// \brief Get the global offset corresponding to a local offset.
+ uint64_t getGlobalBitOffset(uint32_t LocalOffset) {
+ return Reader->getGlobalBitOffset(*F, LocalOffset);
+ }
+
+ /// \brief Reads a statement.
+ Stmt *readStmt() { return Reader->ReadStmt(*F); }
+
+ /// \brief Reads an expression.
+ Expr *readExpr() { return Reader->ReadExpr(*F); }
+
+ /// \brief Reads a sub-statement operand during statement reading.
+ Stmt *readSubStmt() { return Reader->ReadSubStmt(); }
+
+ /// \brief Reads a sub-expression operand during statement reading.
+ Expr *readSubExpr() { return Reader->ReadSubExpr(); }
+
+ /// \brief 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.
+ TemplateArgumentLoc
+ readTemplateArgumentLoc() {
+ return Reader->ReadTemplateArgumentLoc(*F, Record, Idx);
+ }
+
+ const ASTTemplateArgumentListInfo*
+ readASTTemplateArgumentListInfo() {
+ return Reader->ReadASTTemplateArgumentListInfo(*F, Record, Idx);
+ }
+
+ /// \brief 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.
+ serialization::TypeID getGlobalTypeID(unsigned LocalID) const {
+ return Reader->getGlobalTypeID(*F, LocalID);
+ }
+
+ /// \brief 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.
+ ///
+ /// \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
+ /// given module, advancing Idx.
+ Decl *readDecl() {
+ return Reader->ReadDecl(*F, Record, Idx);
+ }
+
+ /// \brief Reads a declaration from the given position in the record,
+ /// advancing Idx.
+ ///
+ /// \returns The declaration read from this location, casted to the given
+ /// result type.
+ template<typename T>
+ T *readDeclAs() {
+ return Reader->ReadDeclAs<T>(*F, Record, Idx);
+ }
+
+ IdentifierInfo *getIdentifierInfo() {
+ return Reader->GetIdentifierInfo(*F, Record, Idx);
+ }
+
+ /// \brief Read a selector from the Record, advancing Idx.
+ Selector readSelector() {
+ return Reader->ReadSelector(*F, Record, Idx);
+ }
+
+ /// \brief Read a declaration name, advancing Idx.
+ DeclarationName readDeclarationName() {
+ return Reader->ReadDeclarationName(*F, Record, Idx);
+ }
+ void readDeclarationNameLoc(DeclarationNameLoc &DNLoc, DeclarationName Name) {
+ return Reader->ReadDeclarationNameLoc(*F, DNLoc, Name, Record, Idx);
+ }
+ void readDeclarationNameInfo(DeclarationNameInfo &NameInfo) {
+ return Reader->ReadDeclarationNameInfo(*F, NameInfo, Record, Idx);
+ }
+
+ void readQualifierInfo(QualifierInfo &Info) {
+ return Reader->ReadQualifierInfo(*F, Info, Record, Idx);
+ }
+
+ NestedNameSpecifier *readNestedNameSpecifier() {
+ return Reader->ReadNestedNameSpecifier(*F, Record, Idx);
+ }
+
+ NestedNameSpecifierLoc readNestedNameSpecifierLoc() {
+ return Reader->ReadNestedNameSpecifierLoc(*F, Record, Idx);
+ }
+
+ /// \brief Read a template name, advancing Idx.
+ TemplateName readTemplateName() {
+ return Reader->ReadTemplateName(*F, Record, Idx);
+ }
+
+ /// \brief 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.
+ TemplateParameterList *readTemplateParameterList() {
+ return Reader->ReadTemplateParameterList(*F, Record, Idx);
+ }
+
+ /// \brief 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.
+ void readUnresolvedSet(LazyASTUnresolvedSet &Set) {
+ return Reader->ReadUnresolvedSet(*F, Set, Record, Idx);
+ }
+
+ /// \brief Read a C++ base specifier, advancing Idx.
+ CXXBaseSpecifier readCXXBaseSpecifier() {
+ return Reader->ReadCXXBaseSpecifier(*F, Record, Idx);
+ }
+
+ /// \brief Read a CXXCtorInitializer array, advancing Idx.
+ CXXCtorInitializer **readCXXCtorInitializers() {
+ return Reader->ReadCXXCtorInitializers(*F, Record, Idx);
+ }
+
+ CXXTemporary *readCXXTemporary() {
+ return Reader->ReadCXXTemporary(*F, Record, Idx);
+ }
+
+ /// \brief Read a source location, advancing Idx.
+ SourceLocation readSourceLocation() {
+ return Reader->ReadSourceLocation(*F, Record, Idx);
+ }
+
+ /// \brief Read a source range, advancing Idx.
+ SourceRange readSourceRange() {
+ return Reader->ReadSourceRange(*F, Record, Idx);
+ }
+
+ /// \brief Read an integral value, advancing Idx.
+ llvm::APInt readAPInt() {
+ return Reader->ReadAPInt(Record, Idx);
+ }
+
+ /// \brief Read a signed integral value, advancing Idx.
+ llvm::APSInt readAPSInt() {
+ return Reader->ReadAPSInt(Record, Idx);
+ }
+
+ /// \brief 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.
+ std::string readString() {
+ return Reader->ReadString(Record, Idx);
+ }
+
+ /// \brief Read a path, advancing Idx.
+ std::string readPath() {
+ return Reader->ReadPath(*F, Record, Idx);
+ }
+
+ /// \brief Read a version tuple, advancing Idx.
+ VersionTuple readVersionTuple() {
+ return ASTReader::ReadVersionTuple(Record, Idx);
+ }
+
+ /// \brief Reads attributes from the current stream position, advancing Idx.
+ void readAttributes(AttrVec &Attrs) {
+ return Reader->ReadAttributes(*F, Attrs, Record, Idx);
+ }
+
+ /// \brief Reads a token out of a record, advancing Idx.
+ Token readToken() {
+ return Reader->ReadToken(*F, Record, Idx);
+ }
+
+ void recordSwitchCaseID(SwitchCase *SC, unsigned ID) {
+ Reader->RecordSwitchCaseID(SC, ID);
+ }
+
+ /// \brief 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
/// then restores it when destroyed.
struct SavedStreamPosition {
diff --git a/include/clang/Serialization/ASTWriter.h b/include/clang/Serialization/ASTWriter.h
index bfdb9f2262b5..1469555ec21e 100644
--- a/include/clang/Serialization/ASTWriter.h
+++ b/include/clang/Serialization/ASTWriter.h
@@ -16,9 +16,8 @@
#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/Decl.h"
-#include "clang/AST/DeclarationName.h"
-#include "clang/Frontend/PCHContainerOperations.h"
#include "clang/AST/TemplateBase.h"
+#include "clang/Frontend/PCHContainerOperations.h"
#include "clang/Sema/SemaConsumer.h"
#include "clang/Serialization/ASTBitCodes.h"
#include "clang/Serialization/ASTDeserializationListener.h"
@@ -26,21 +25,19 @@
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SetVector.h"
-#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Bitcode/BitstreamWriter.h"
-#include <map>
#include <queue>
#include <vector>
namespace llvm {
class APFloat;
class APInt;
- class BitstreamWriter;
}
namespace clang {
+class DeclarationName;
class ASTContext;
class Attr;
class NestedNameSpecifier;
@@ -376,9 +373,10 @@ private:
/// it.
llvm::SmallSetVector<const DeclContext *, 16> UpdatedDeclContexts;
- /// \brief Keeps track of visible decls that were added in DeclContexts
- /// coming from another AST file.
- SmallVector<const Decl *, 16> UpdatingVisibleDecls;
+ /// \brief 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
/// should serialize.
@@ -461,6 +459,9 @@ private:
void WriteDeclContextVisibleUpdate(const DeclContext *DC);
void WriteFPPragmaOptions(const FPOptions &Opts);
void WriteOpenCLExtensions(Sema &SemaRef);
+ void WriteOpenCLExtensionTypes(Sema &SemaRef);
+ void WriteOpenCLExtensionDecls(Sema &SemaRef);
+ void WriteCUDAPragmas(Sema &SemaRef);
void WriteObjCCategories();
void WriteLateParsedTemplates(Sema &SemaRef);
void WriteOptimizePragmaOptions(Sema &SemaRef);
@@ -670,6 +671,14 @@ private:
void CompletedTagDefinition(const TagDecl *D) override;
void AddedVisibleDecl(const DeclContext *DC, const Decl *D) override;
void AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D) override;
+ void AddedCXXTemplateSpecialization(
+ const ClassTemplateDecl *TD,
+ const ClassTemplateSpecializationDecl *D) override;
+ void AddedCXXTemplateSpecialization(
+ const VarTemplateDecl *TD,
+ const VarTemplateSpecializationDecl *D) override;
+ void AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,
+ const FunctionDecl *D) override;
void ResolvedExceptionSpec(const FunctionDecl *FD) override;
void DeducedReturnType(const FunctionDecl *FD, QualType ReturnType) override;
void ResolvedOperatorDelete(const CXXDestructorDecl *DD,
@@ -677,6 +686,7 @@ private:
void CompletedImplicitDefinition(const FunctionDecl *D) override;
void StaticDataMemberInstantiated(const VarDecl *D) override;
void DefaultArgumentInstantiated(const ParmVarDecl *D) override;
+ void DefaultMemberInitializerInstantiated(const FieldDecl *D) override;
void FunctionDefinitionInstantiated(const FunctionDecl *D) override;
void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
const ObjCInterfaceDecl *IFD) override;
@@ -911,7 +921,6 @@ public:
class PCHGenerator : public SemaConsumer {
const Preprocessor &PP;
std::string OutputFile;
- clang::Module *Module;
std::string isysroot;
Sema *SemaPtr;
std::shared_ptr<PCHBuffer> Buffer;
@@ -927,7 +936,7 @@ protected:
public:
PCHGenerator(
const Preprocessor &PP, StringRef OutputFile,
- clang::Module *Module, StringRef isysroot,
+ StringRef isysroot,
std::shared_ptr<PCHBuffer> Buffer,
ArrayRef<llvm::IntrusiveRefCntPtr<ModuleFileExtension>> Extensions,
bool AllowASTWithErrors = false,
diff --git a/include/clang/Serialization/Module.h b/include/clang/Serialization/Module.h
index aa0392f0ecfb..58b3149d407e 100644
--- a/include/clang/Serialization/Module.h
+++ b/include/clang/Serialization/Module.h
@@ -48,7 +48,8 @@ enum ModuleKind {
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_MainFile, ///< File is a PCH file treated as the actual main file.
+ MK_PrebuiltModule ///< File is from a prebuilt module path.
};
/// \brief The input file that has been loaded from this AST file, along with
@@ -172,8 +173,8 @@ public:
/// \brief The global bit offset (or base) of this module
uint64_t GlobalBitOffset;
- /// \brief The bitstream reader from which we'll read the AST file.
- llvm::BitstreamReader StreamFile;
+ /// \brief The serialized bitstream data for this file.
+ StringRef Data;
/// \brief The main bitstream cursor for the main block.
llvm::BitstreamCursor Stream;
@@ -447,7 +448,8 @@ public:
/// \brief Is this a module file for a module (rather than a PCH or similar).
bool isModule() const {
- return Kind == MK_ImplicitModule || Kind == MK_ExplicitModule;
+ return Kind == MK_ImplicitModule || Kind == MK_ExplicitModule ||
+ Kind == MK_PrebuiltModule;
}
/// \brief Dump debugging output for this module.
diff --git a/include/clang/Serialization/ModuleManager.h b/include/clang/Serialization/ModuleManager.h
index 08e7d4049e55..1c4d88e979e3 100644
--- a/include/clang/Serialization/ModuleManager.h
+++ b/include/clang/Serialization/ModuleManager.h
@@ -175,7 +175,7 @@ public:
OutOfDate
};
- typedef ASTFileSignature(*ASTFileSignatureReader)(llvm::BitstreamReader &);
+ typedef ASTFileSignature(*ASTFileSignatureReader)(StringRef);
/// \brief Attempts to create a new module and add it to the list of known
/// modules.
diff --git a/include/clang/StaticAnalyzer/Checkers/Checkers.td b/include/clang/StaticAnalyzer/Checkers/Checkers.td
index 785e064e72a9..2e58debf80fc 100644
--- a/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ b/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -42,6 +42,10 @@ def Nullability : Package<"nullability">;
def Cplusplus : Package<"cplusplus">;
def CplusplusAlpha : Package<"cplusplus">, InPackage<Alpha>, Hidden;
+def CplusplusOptIn : Package<"cplusplus">, InPackage<OptIn>;
+
+def Valist : Package<"valist">;
+def ValistAlpha : Package<"valist">, InPackage<Alpha>, Hidden;
def DeadCode : Package<"deadcode">;
def DeadCodeAlpha : Package<"deadcode">, InPackage<Alpha>, Hidden;
@@ -75,8 +79,17 @@ def LocalizabilityOptIn : Package<"localizability">, InPackage<CocoaOptIn>;
def MPI : Package<"mpi">, InPackage<OptIn>;
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.
+def APIModeling : Package<"apiModeling">, Hidden;
+def GoogleAPIModeling : Package<"google">, InPackage<APIModeling>;
+
def Debug : Package<"debug">;
+def CloneDetectionAlpha : Package<"clone">, InPackage<Alpha>, Hidden;
+
//===----------------------------------------------------------------------===//
// Core Checkers.
//===----------------------------------------------------------------------===//
@@ -131,6 +144,10 @@ def CastToStructChecker : Checker<"CastToStruct">,
HelpText<"Check for cast from non-struct pointer to struct pointer">,
DescFile<"CastToStructChecker.cpp">;
+def ConversionChecker : Checker<"Conversion">,
+ HelpText<"Loss of sign/precision in implicit conversions">,
+ DescFile<"ConversionChecker.cpp">;
+
def IdenticalExprChecker : Checker<"IdenticalExpr">,
HelpText<"Warn about unintended use of identical expressions in operators">,
DescFile<"IdenticalExprChecker.cpp">;
@@ -183,7 +200,7 @@ def NullablePassedToNonnullChecker : Checker<"NullablePassedToNonnull">,
HelpText<"Warns when a nullable pointer is passed to a pointer which has a _Nonnull type.">,
DescFile<"NullabilityChecker.cpp">;
-def NullableReturnedFromNonnullChecker : Checker<"NullablePassedToNonnull">,
+def NullableReturnedFromNonnullChecker : Checker<"NullableReturnedFromNonnull">,
HelpText<"Warns when a nullable pointer is returned from a function that has _Nonnull return type.">,
DescFile<"NullabilityChecker.cpp">;
@@ -247,15 +264,40 @@ def NewDeleteLeaksChecker : Checker<"NewDeleteLeaks">,
HelpText<"Check for memory leaks. Traces memory managed by new/delete.">,
DescFile<"MallocChecker.cpp">;
+def CXXSelfAssignmentChecker : Checker<"SelfAssignment">,
+ HelpText<"Checks C++ copy and move assignment operators for self assignment">,
+ DescFile<"CXXSelfAssignmentChecker.cpp">;
+
} // end: "cplusplus"
-let ParentPackage = CplusplusAlpha in {
+let ParentPackage = CplusplusOptIn in {
def VirtualCallChecker : Checker<"VirtualCall">,
HelpText<"Check virtual function calls during construction or destruction">,
DescFile<"VirtualCallChecker.cpp">;
-} // end: "alpha.cplusplus"
+} // end: "optin.cplusplus"
+
+
+//===----------------------------------------------------------------------===//
+// Valist checkers.
+//===----------------------------------------------------------------------===//
+
+let ParentPackage = ValistAlpha in {
+
+def UninitializedChecker : Checker<"Uninitialized">,
+ HelpText<"Check for usages of uninitialized (or already released) va_lists.">,
+ DescFile<"ValistChecker.cpp">;
+
+def UnterminatedChecker : Checker<"Unterminated">,
+ HelpText<"Check for va_lists which are not released by a va_end call.">,
+ DescFile<"ValistChecker.cpp">;
+
+def CopyToSelfChecker : Checker<"CopyToSelf">,
+ HelpText<"Check for va_lists which are copied onto itself.">,
+ DescFile<"ValistChecker.cpp">;
+
+} // end : "alpha.valist"
//===----------------------------------------------------------------------===//
// Deadcode checkers.
@@ -382,6 +424,10 @@ def VforkChecker : Checker<"Vfork">,
HelpText<"Check for proper usage of vfork">,
DescFile<"VforkChecker.cpp">;
+def StdCLibraryFunctionsChecker : Checker<"StdCLibraryFunctions">,
+ HelpText<"Improve modeling of the C standard library functions">,
+ DescFile<"StdLibraryFunctionsChecker.cpp">;
+
} // end "unix"
let ParentPackage = UnixAlpha in {
@@ -402,6 +448,10 @@ def SimpleStreamChecker : Checker<"SimpleStream">,
HelpText<"Check for misuses of stream APIs">,
DescFile<"SimpleStreamChecker.cpp">;
+def BlockInCriticalSectionChecker : Checker<"BlockInCriticalSection">,
+ HelpText<"Check for calls to blocking functions inside a critical section">,
+ DescFile<"BlockInCriticalSectionChecker.cpp">;
+
} // end "alpha.unix"
let ParentPackage = CString in {
@@ -436,16 +486,22 @@ def CStringNotNullTerm : Checker<"NotNullTerminated">,
let ParentPackage = OSX in {
+def NumberObjectConversionChecker : Checker<"NumberObjectConversion">,
+ HelpText<"Check for erroneous conversions of objects representing numbers into numbers">,
+ DescFile<"NumberObjectConversionChecker.cpp">;
+
def MacOSXAPIChecker : Checker<"API">,
- InPackage<OSX>,
HelpText<"Check for proper uses of various Apple APIs">,
DescFile<"MacOSXAPIChecker.cpp">;
def MacOSKeychainAPIChecker : Checker<"SecKeychainAPI">,
- InPackage<OSX>,
HelpText<"Check for proper uses of Secure Keychain APIs">,
DescFile<"MacOSKeychainAPIChecker.cpp">;
+def ObjCPropertyChecker : Checker<"ObjCProperty">,
+ HelpText<"Check for proper uses of Objective-C properties">,
+ DescFile<"ObjCPropertyChecker.cpp">;
+
} // end "osx"
let ParentPackage = Cocoa in {
@@ -539,8 +595,8 @@ def DirectIvarAssignmentForAnnotatedFunctions : Checker<"DirectIvarAssignmentFor
let ParentPackage = CoreFoundation in {
-def CFNumberCreateChecker : Checker<"CFNumber">,
- HelpText<"Check for proper uses of CFNumberCreate">,
+def CFNumberChecker : Checker<"CFNumber">,
+ HelpText<"Check for proper uses of CFNumber APIs">,
DescFile<"BasicObjCFoundationChecks.cpp">;
def CFRetainReleaseChecker : Checker<"CFRetainRelease">,
@@ -594,12 +650,27 @@ def LLVMConventionsChecker : Checker<"Conventions">,
HelpText<"Check code for LLVM codebase conventions">,
DescFile<"LLVMConventionsChecker.cpp">;
+
+
+//===----------------------------------------------------------------------===//
+// Checkers modeling Google APIs.
+//===----------------------------------------------------------------------===//
+
+def GTestChecker : Checker<"GTest">,
+ InPackage<GoogleAPIModeling>,
+ HelpText<"Model gtest assertion APIs">,
+ DescFile<"GTestChecker.cpp">;
+
//===----------------------------------------------------------------------===//
// Debugging checkers (for analyzer development).
//===----------------------------------------------------------------------===//
let ParentPackage = Debug in {
+def AnalysisOrderChecker : Checker<"AnalysisOrder">,
+ HelpText<"Print callbacks that are called during analysis in order">,
+ DescFile<"AnalysisOrder.cpp">;
+
def DominatorsTreeDumper : Checker<"DumpDominators">,
HelpText<"Print the dominance tree for a given CFG">,
DescFile<"DebugCheckers.cpp">;
@@ -657,3 +728,17 @@ def BugHashDumper : Checker<"DumpBugHash">,
DescFile<"DebugCheckers.cpp">;
} // end "debug"
+
+
+//===----------------------------------------------------------------------===//
+// Clone Detection
+//===----------------------------------------------------------------------===//
+
+let ParentPackage = CloneDetectionAlpha in {
+
+def CloneChecker : Checker<"CloneChecker">,
+ HelpText<"Reports similar pieces of code.">,
+ DescFile<"CloneChecker.cpp">;
+
+} // end "clone"
+
diff --git a/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIFunctionClassifier.h b/include/clang/StaticAnalyzer/Checkers/MPIFunctionClassifier.h
index 65e908912c54..65e908912c54 100644
--- a/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIFunctionClassifier.h
+++ b/include/clang/StaticAnalyzer/Checkers/MPIFunctionClassifier.h
diff --git a/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h b/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h
index 5850656916e3..25886545e2f7 100644
--- a/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h
+++ b/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h
@@ -120,9 +120,6 @@ public:
NoRet,
/// Indicates that the returned value is an owned (+1) symbol.
OwnedSymbol,
- /// Indicates that the returned value is an owned (+1) symbol and
- /// that it should be treated as freshly allocated.
- OwnedAllocatedSymbol,
/// Indicates that the returned value is an object with retain count
/// semantics but that it is not owned (+0). This is the default
/// for getters, etc.
@@ -163,8 +160,7 @@ public:
ObjKind getObjKind() const { return O; }
bool isOwned() const {
- return K == OwnedSymbol || K == OwnedAllocatedSymbol ||
- K == OwnedWhenTrackedReceiver;
+ return K == OwnedSymbol || K == OwnedWhenTrackedReceiver;
}
bool notOwned() const {
@@ -179,8 +175,8 @@ public:
return RetEffect(OwnedWhenTrackedReceiver, ObjC);
}
- static RetEffect MakeOwned(ObjKind o, bool isAllocated = false) {
- return RetEffect(isAllocated ? OwnedAllocatedSymbol : OwnedSymbol, o);
+ static RetEffect MakeOwned(ObjKind o) {
+ return RetEffect(OwnedSymbol, o);
}
static RetEffect MakeNotOwned(ObjKind o) {
return RetEffect(NotOwnedSymbol, o);
diff --git a/include/clang/StaticAnalyzer/Checkers/SValExplainer.h b/include/clang/StaticAnalyzer/Checkers/SValExplainer.h
index 28cfbef91038..62bb0f666d44 100644
--- a/include/clang/StaticAnalyzer/Checkers/SValExplainer.h
+++ b/include/clang/StaticAnalyzer/Checkers/SValExplainer.h
@@ -142,6 +142,14 @@ public:
// TODO: Explain CXXThisRegion itself, find a way to test it.
if (isThisObject(R))
return "'this' object";
+ // Objective-C objects are not normal symbolic regions. At least,
+ // they're always on the heap.
+ if (R->getSymbol()->getType()
+ .getCanonicalType()->getAs<ObjCObjectPointerType>())
+ return "object at " + Visit(R->getSymbol());
+ // Other heap-based symbolic regions are also special.
+ if (isa<HeapSpaceRegion>(R->getMemorySpace()))
+ return "heap segment that starts at " + Visit(R->getSymbol());
return "pointee of " + Visit(R->getSymbol());
}
@@ -176,6 +184,8 @@ public:
std::string Name = VD->getQualifiedNameAsString();
if (isa<ParmVarDecl>(VD))
return "parameter '" + Name + "'";
+ else if (VD->hasAttr<BlocksAttr>())
+ return "block variable '" + Name + "'";
else if (VD->hasLocalStorage())
return "local variable '" + Name + "'";
else if (VD->isStaticLocal())
@@ -186,6 +196,11 @@ public:
llvm_unreachable("A variable is either local or global");
}
+ std::string VisitObjCIvarRegion(const ObjCIvarRegion *R) {
+ return "instance variable '" + R->getDecl()->getNameAsString() + "' of " +
+ Visit(R->getSuperRegion());
+ }
+
std::string VisitFieldRegion(const FieldRegion *R) {
return "field '" + R->getDecl()->getNameAsString() + "' of " +
Visit(R->getSuperRegion());
diff --git a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
index 3959de24d431..4fb50deb0f6b 100644
--- a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
+++ b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
@@ -125,6 +125,9 @@ class AnalyzerOptions : public RefCountedBase<AnalyzerOptions> {
public:
typedef llvm::StringMap<std::string> ConfigTable;
+ static std::vector<StringRef>
+ getRegisteredCheckers(bool IncludeExperimental = false);
+
/// \brief Pair of checker name and enable/disable.
std::vector<std::pair<std::string, bool> > CheckersControlList;
@@ -149,6 +152,7 @@ public:
unsigned DisableAllChecks : 1;
unsigned ShowCheckerHelp : 1;
+ unsigned ShowEnabledCheckerList : 1;
unsigned AnalyzeAll : 1;
unsigned AnalyzerDisplayProgress : 1;
unsigned AnalyzeNestedBlocks : 1;
@@ -265,6 +269,9 @@ private:
/// \sa shouldWidenLoops
Optional<bool> WidenLoops;
+ /// \sa shouldDisplayNotesAsEvents
+ Optional<bool> DisplayNotesAsEvents;
+
/// A helper function that retrieves option for a given full-qualified
/// checker name.
/// Options for checkers can be specified via 'analyzer-config' command-line
@@ -533,6 +540,14 @@ public:
/// This is controlled by the 'widen-loops' config option.
bool shouldWidenLoops();
+ /// Returns true if the bug reporter should transparently treat extra note
+ /// diagnostic pieces as event diagnostic pieces. Useful when the diagnostic
+ /// consumer doesn't support the extra note pieces.
+ ///
+ /// This is controlled by the 'extra-notes-as-events' option, which defaults
+ /// to false when unset.
+ bool shouldDisplayNotesAsEvents();
+
public:
AnalyzerOptions() :
AnalysisStoreOpt(RegionStoreModel),
@@ -541,6 +556,7 @@ public:
AnalysisPurgeOpt(PurgeStmt),
DisableAllChecks(0),
ShowCheckerHelp(0),
+ ShowEnabledCheckerList(0),
AnalyzeAll(0),
AnalyzerDisplayProgress(0),
AnalyzeNestedBlocks(0),
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
index 57c73fd6eca1..73f4dd5a3e91 100644
--- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
+++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
@@ -66,6 +66,8 @@ public:
typedef SmallVector<std::unique_ptr<BugReporterVisitor>, 8> VisitorList;
typedef VisitorList::iterator visitor_iterator;
typedef SmallVector<StringRef, 2> ExtraTextList;
+ typedef SmallVector<llvm::IntrusiveRefCntPtr<PathDiagnosticNotePiece>, 4>
+ NoteList;
protected:
friend class BugReporter;
@@ -82,7 +84,8 @@ protected:
const ExplodedNode *ErrorNode;
SmallVector<SourceRange, 4> Ranges;
ExtraTextList ExtraText;
-
+ NoteList Notes;
+
typedef llvm::DenseSet<SymbolRef> Symbols;
typedef llvm::DenseSet<const MemRegion *> Regions;
@@ -177,6 +180,18 @@ public:
const BugType& getBugType() const { return BT; }
BugType& getBugType() { return BT; }
+ /// \brief 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.
+ /// Path-sensitive reports have their intermediate path diagnostics
+ /// auto-generated, perhaps with the help of checker-defined visitors,
+ /// and may contain extra notes.
+ /// Path-insensitive reports consist only of a single warning message
+ /// in a specific location, and perhaps extra notes.
+ /// Path-sensitive checkers are allowed to throw path-insensitive reports.
+ bool isPathSensitive() const { return ErrorNode != nullptr; }
+
const ExplodedNode *getErrorNode() const { return ErrorNode; }
StringRef getDescription() const { return Description; }
@@ -245,7 +260,33 @@ public:
void setDeclWithIssue(const Decl *declWithIssue) {
DeclWithIssue = declWithIssue;
}
-
+
+ /// Add new item to the list of additional notes that need to be attached to
+ /// this path-insensitive report. If you want to add extra notes to a
+ /// path-sensitive report, you need to use a BugReporterVisitor because it
+ /// allows you to specify where exactly in the auto-generated path diagnostic
+ /// the extra note should appear.
+ void addNote(StringRef Msg, const PathDiagnosticLocation &Pos,
+ ArrayRef<SourceRange> Ranges) {
+ PathDiagnosticNotePiece *P = new PathDiagnosticNotePiece(Pos, Msg);
+
+ for (const auto &R : Ranges)
+ P->addRange(R);
+
+ Notes.push_back(P);
+ }
+
+ // FIXME: Instead of making an override, we could have default-initialized
+ // Ranges with {}, however it crashes the MSVC 2013 compiler.
+ void addNote(StringRef Msg, const PathDiagnosticLocation &Pos) {
+ std::vector<SourceRange> Ranges;
+ addNote(Msg, Pos, Ranges);
+ }
+
+ virtual const NoteList &getNotes() {
+ return Notes;
+ }
+
/// \brief This allows for addition of meta data to the diagnostic.
///
/// Currently, only the HTMLDiagnosticClient knows how to display it.
@@ -311,31 +352,6 @@ public:
virtual void Profile(llvm::FoldingSetNodeID& hash) const;
};
-} // end ento namespace
-} // end clang namespace
-
-namespace llvm {
- template<> struct ilist_traits<clang::ento::BugReport>
- : public ilist_default_traits<clang::ento::BugReport> {
- clang::ento::BugReport *createSentinel() const {
- return static_cast<clang::ento::BugReport *>(&Sentinel);
- }
- void destroySentinel(clang::ento::BugReport *) const {}
-
- clang::ento::BugReport *provideInitialHead() const {
- return createSentinel();
- }
- clang::ento::BugReport *ensureHead(clang::ento::BugReport *) const {
- return createSentinel();
- }
- private:
- mutable ilist_half_node<clang::ento::BugReport> Sentinel;
- };
-}
-
-namespace clang {
-namespace ento {
-
//===----------------------------------------------------------------------===//
// BugTypes (collections of related reports).
//===----------------------------------------------------------------------===//
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h
index c954bbfad8cb..8c3a1d0d4b40 100644
--- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h
+++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h
@@ -185,6 +185,11 @@ public:
/// Visitor that tries to report interesting diagnostics from conditions.
class ConditionBRVisitor final
: public BugReporterVisitorImpl<ConditionBRVisitor> {
+
+ // FIXME: constexpr initialization isn't supported by MSVC2013.
+ static const char *const GenericTrueMessage;
+ static const char *const GenericFalseMessage;
+
public:
void Profile(llvm::FoldingSetNodeID &ID) const override {
static int x = 0;
@@ -240,11 +245,14 @@ public:
const ExplodedNode *N);
bool patternMatch(const Expr *Ex,
+ const Expr *ParentEx,
raw_ostream &Out,
BugReporterContext &BRC,
BugReport &R,
const ExplodedNode *N,
Optional<bool> &prunable);
+
+ static bool isPieceMessageGeneric(const PathDiagnosticPiece *Piece);
};
/// \brief Suppress reports that might lead to known false positives.
@@ -331,6 +339,22 @@ public:
BugReport &BR) override;
};
+class CXXSelfAssignmentBRVisitor final
+ : public BugReporterVisitorImpl<CXXSelfAssignmentBRVisitor> {
+
+ bool Satisfied;
+
+public:
+ CXXSelfAssignmentBRVisitor() : Satisfied(false) {}
+
+ void Profile(llvm::FoldingSetNodeID &ID) const override {}
+
+ PathDiagnosticPiece *VisitNode(const ExplodedNode *Succ,
+ const ExplodedNode *Pred,
+ BugReporterContext &BRC,
+ BugReport &BR) override;
+};
+
namespace bugreporter {
/// Attempts to add visitors to trace a null or undefined value back to its
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h
index 16226e94df48..18fa85c9657f 100644
--- a/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h
+++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h
@@ -17,7 +17,6 @@
#include "clang/Basic/LLVM.h"
#include "clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
-#include "llvm/ADT/FoldingSet.h"
#include <string>
namespace clang {
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
index c34b14cbf9e2..efe809fb1981 100644
--- a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
+++ b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
@@ -334,9 +334,9 @@ public:
// Path "pieces" for path-sensitive diagnostics.
//===----------------------------------------------------------------------===//
-class PathDiagnosticPiece : public RefCountedBaseVPTR {
+class PathDiagnosticPiece : public RefCountedBase<PathDiagnosticPiece> {
public:
- enum Kind { ControlFlow, Event, Macro, Call };
+ enum Kind { ControlFlow, Event, Macro, Call, Note };
enum DisplayHint { Above, Below };
private:
@@ -366,7 +366,7 @@ protected:
PathDiagnosticPiece(Kind k, DisplayHint hint = Below);
public:
- ~PathDiagnosticPiece() override;
+ virtual ~PathDiagnosticPiece();
StringRef getString() const { return str; }
@@ -452,7 +452,8 @@ public:
void Profile(llvm::FoldingSetNodeID &ID) const override;
static bool classof(const PathDiagnosticPiece *P) {
- return P->getKind() == Event || P->getKind() == Macro;
+ return P->getKind() == Event || P->getKind() == Macro ||
+ P->getKind() == Note;
}
};
@@ -710,6 +711,23 @@ public:
void Profile(llvm::FoldingSetNodeID &ID) const override;
};
+class PathDiagnosticNotePiece: public PathDiagnosticSpotPiece {
+public:
+ PathDiagnosticNotePiece(const PathDiagnosticLocation &Pos, StringRef S,
+ bool AddPosRange = true)
+ : PathDiagnosticSpotPiece(Pos, S, Note, AddPosRange) {}
+
+ ~PathDiagnosticNotePiece() override;
+
+ static inline bool classof(const PathDiagnosticPiece *P) {
+ return P->getKind() == Note;
+ }
+
+ void dump() const override;
+
+ void Profile(llvm::FoldingSetNodeID &ID) const override;
+};
+
/// PathDiagnostic - PathDiagnostic objects represent a single path-sensitive
/// diagnostic. It represents an ordered-collection of PathDiagnosticPieces,
/// each which represent the pieces of the path.
diff --git a/include/clang/StaticAnalyzer/Core/Checker.h b/include/clang/StaticAnalyzer/Core/Checker.h
index 137f238cced9..dd7a6c863be0 100644
--- a/include/clang/StaticAnalyzer/Core/Checker.h
+++ b/include/clang/StaticAnalyzer/Core/Checker.h
@@ -325,20 +325,13 @@ class RegionChanges {
return ((const CHECKER *)checker)->checkRegionChanges(state, invalidated,
Explicits, Regions, Call);
}
- template <typename CHECKER>
- static bool _wantsRegionChangeUpdate(void *checker,
- ProgramStateRef state) {
- return ((const CHECKER *)checker)->wantsRegionChangeUpdate(state);
- }
public:
template <typename CHECKER>
static void _register(CHECKER *checker, CheckerManager &mgr) {
mgr._registerForRegionChanges(
CheckerManager::CheckRegionChangesFunc(checker,
- _checkRegionChanges<CHECKER>),
- CheckerManager::WantsRegionChangeUpdateFunc(checker,
- _wantsRegionChangeUpdate<CHECKER>));
+ _checkRegionChanges<CHECKER>));
}
};
diff --git a/include/clang/StaticAnalyzer/Core/CheckerManager.h b/include/clang/StaticAnalyzer/Core/CheckerManager.h
index b06b74d326de..5af717d90268 100644
--- a/include/clang/StaticAnalyzer/Core/CheckerManager.h
+++ b/include/clang/StaticAnalyzer/Core/CheckerManager.h
@@ -322,9 +322,6 @@ public:
ExprEngine &Eng,
ProgramPoint::Kind K);
- /// \brief True if at least one checker wants to check region changes.
- bool wantsRegionChangeUpdate(ProgramStateRef state);
-
/// \brief Run checkers for region changes.
///
/// This corresponds to the check::RegionChanges callback.
@@ -452,8 +449,6 @@ public:
const CallEvent *Call)>
CheckRegionChangesFunc;
- typedef CheckerFn<bool (ProgramStateRef)> WantsRegionChangeUpdateFunc;
-
typedef CheckerFn<ProgramStateRef (ProgramStateRef,
const InvalidatedSymbols &Escaped,
const CallEvent *Call,
@@ -501,8 +496,7 @@ public:
void _registerForDeadSymbols(CheckDeadSymbolsFunc checkfn);
- void _registerForRegionChanges(CheckRegionChangesFunc checkfn,
- WantsRegionChangeUpdateFunc wantUpdateFn);
+ void _registerForRegionChanges(CheckRegionChangesFunc checkfn);
void _registerForPointerEscape(CheckPointerEscapeFunc checkfn);
@@ -611,11 +605,7 @@ private:
std::vector<CheckDeadSymbolsFunc> DeadSymbolsCheckers;
- struct RegionChangesCheckerInfo {
- CheckRegionChangesFunc CheckFn;
- WantsRegionChangeUpdateFunc WantUpdateFn;
- };
- std::vector<RegionChangesCheckerInfo> RegionChangesCheckers;
+ std::vector<CheckRegionChangesFunc> RegionChangesCheckers;
std::vector<CheckPointerEscapeFunc> PointerEscapeCheckers;
diff --git a/include/clang/StaticAnalyzer/Core/CheckerRegistry.h b/include/clang/StaticAnalyzer/Core/CheckerRegistry.h
index c9724c08da2d..3b26ed3e1a09 100644
--- a/include/clang/StaticAnalyzer/Core/CheckerRegistry.h
+++ b/include/clang/StaticAnalyzer/Core/CheckerRegistry.h
@@ -127,7 +127,9 @@ public:
/// Prints the name and description of all checkers in this registry.
/// This output is not intended to be machine-parseable.
- void printHelp(raw_ostream &out, size_t maxNameChars = 30) const ;
+ void printHelp(raw_ostream &out, size_t maxNameChars = 30) const;
+ void printList(raw_ostream &out,
+ SmallVectorImpl<CheckerOptInfo> &opts) const;
private:
mutable CheckerInfoList Checkers;
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h b/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h
index 5b007f1531df..0d1a120c9dd4 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h
@@ -59,6 +59,29 @@ public:
void Profile(llvm::FoldingSetNodeID& ID) { Profile(ID, store, region); }
};
+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) {}
+
+ typedef llvm::ImmutableList<const CXXBaseSpecifier *>::iterator iterator;
+ iterator begin() const { return L.begin(); }
+ iterator end() const { return L.end(); }
+
+ static void Profile(llvm::FoldingSetNodeID& ID, const DeclaratorDecl *D,
+ llvm::ImmutableList<const CXXBaseSpecifier *> L);
+
+ 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;
@@ -71,8 +94,10 @@ class BasicValueFactory {
void * PersistentSValPairs;
llvm::ImmutableList<SVal>::Factory SValListFactory;
+ llvm::ImmutableList<const CXXBaseSpecifier*>::Factory CXXBaseListFactory;
llvm::FoldingSet<CompoundValData> CompoundValDataSet;
llvm::FoldingSet<LazyCompoundValData> LazyCompoundValDataSet;
+ llvm::FoldingSet<PointerToMemberData> PointerToMemberDataSet;
// This is private because external clients should use the factory
// method that takes a QualType.
@@ -81,7 +106,8 @@ class BasicValueFactory {
public:
BasicValueFactory(ASTContext &ctx, llvm::BumpPtrAllocator &Alloc)
: Ctx(ctx), BPAlloc(Alloc), PersistentSVals(nullptr),
- PersistentSValPairs(nullptr), SValListFactory(Alloc) {}
+ PersistentSValPairs(nullptr), SValListFactory(Alloc),
+ CXXBaseListFactory(Alloc) {}
~BasicValueFactory();
@@ -172,14 +198,32 @@ public:
const LazyCompoundValData *getLazyCompoundValData(const StoreRef &store,
const TypedValueRegion *region);
+ const PointerToMemberData *getPointerToMemberData(
+ const DeclaratorDecl *DD,
+ llvm::ImmutableList<const CXXBaseSpecifier *> L);
+
llvm::ImmutableList<SVal> getEmptySValList() {
return SValListFactory.getEmptyList();
}
- llvm::ImmutableList<SVal> consVals(SVal X, llvm::ImmutableList<SVal> L) {
+ llvm::ImmutableList<SVal> prependSVal(SVal X, llvm::ImmutableList<SVal> L) {
return SValListFactory.add(X, L);
}
+ llvm::ImmutableList<const CXXBaseSpecifier *> getEmptyCXXBaseList() {
+ return CXXBaseListFactory.getEmptyList();
+ }
+
+ llvm::ImmutableList<const CXXBaseSpecifier *> prependCXXBase(
+ const CXXBaseSpecifier *CBS,
+ llvm::ImmutableList<const CXXBaseSpecifier *> L) {
+ return CXXBaseListFactory.add(CBS, L);
+ }
+
+ const clang::ento::PointerToMemberData *accumCXXBase(
+ llvm::iterator_range<CastExpr::path_const_iterator> PathRange,
+ const nonloc::PointerToMember &PTM);
+
const llvm::APSInt* evalAPSInt(BinaryOperator::Opcode Op,
const llvm::APSInt& V1,
const llvm::APSInt& V2);
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
index 9a858c2cfb01..6651382d9e95 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
@@ -36,7 +36,7 @@ public:
/// Construct a ConstraintVal indicating the constraint is underconstrained.
ConditionTruthVal() {}
-
+
/// Return true if the constraint is perfectly constrained to 'true'.
bool isConstrainedTrue() const {
return Val.hasValue() && Val.getValue();
@@ -58,11 +58,11 @@ public:
return !Val.hasValue();
}
};
-
+
class ConstraintManager {
public:
ConstraintManager() : NotifyAssumeClients(true) {}
-
+
virtual ~ConstraintManager();
virtual ProgramStateRef assume(ProgramStateRef state,
DefinedSVal Cond,
@@ -99,25 +99,26 @@ public:
return ProgramStatePair(StTrue, StFalse);
}
- virtual ProgramStateRef assumeWithinInclusiveRange(ProgramStateRef State,
- NonLoc Value,
- const llvm::APSInt &From,
- const llvm::APSInt &To,
- bool InBound) = 0;
+ virtual ProgramStateRef assumeInclusiveRange(ProgramStateRef State,
+ NonLoc Value,
+ const llvm::APSInt &From,
+ const llvm::APSInt &To,
+ bool InBound) = 0;
- virtual ProgramStatePair assumeWithinInclusiveRangeDual(
- ProgramStateRef State, NonLoc Value, const llvm::APSInt &From,
- const llvm::APSInt &To) {
- ProgramStateRef StInRange = assumeWithinInclusiveRange(State, Value, From,
- To, true);
+ virtual ProgramStatePair assumeInclusiveRangeDual(ProgramStateRef State,
+ NonLoc Value,
+ const llvm::APSInt &From,
+ const llvm::APSInt &To) {
+ ProgramStateRef StInRange =
+ assumeInclusiveRange(State, Value, From, To, true);
// If StTrue is infeasible, asserting the falseness of Cond is unnecessary
// because the existing constraints already establish this.
if (!StInRange)
return ProgramStatePair((ProgramStateRef)nullptr, State);
- ProgramStateRef StOutOfRange = assumeWithinInclusiveRange(State, Value,
- From, To, false);
+ ProgramStateRef StOutOfRange =
+ assumeInclusiveRange(State, Value, From, To, false);
if (!StOutOfRange) {
// We are careful to return the original state, /not/ StTrue,
// because we want to avoid having callers generate a new node
@@ -147,7 +148,7 @@ public:
const char *sep) = 0;
virtual void EndPath(ProgramStateRef state) {}
-
+
/// Convenience method to query the state to see if a symbol is null or
/// not null, or if neither assumption can be made.
ConditionTruthVal isNull(ProgramStateRef State, SymbolRef Sym) {
@@ -173,7 +174,7 @@ protected:
virtual bool canReasonAbout(SVal X) const = 0;
/// Returns whether or not a symbol is known to be null ("true"), known to be
- /// non-null ("false"), or may be either ("underconstrained").
+ /// non-null ("false"), or may be either ("underconstrained").
virtual ConditionTruthVal checkNull(ProgramStateRef State, SymbolRef Sym);
};
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
index 0fa736d76c99..12ec5b6c64a4 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
@@ -109,7 +109,8 @@ private:
CoreEngine(const CoreEngine &) = delete;
void operator=(const CoreEngine &) = delete;
- ExplodedNode *generateCallExitBeginNode(ExplodedNode *N);
+ ExplodedNode *generateCallExitBeginNode(ExplodedNode *N,
+ const ReturnStmt *RS);
public:
/// Construct a CoreEngine object to analyze the provided CFG.
@@ -172,7 +173,7 @@ public:
/// \brief enqueue the nodes corresponding to the end of function onto the
/// end of path / work list.
- void enqueueEndOfFunction(ExplodedNodeSet &Set);
+ void enqueueEndOfFunction(ExplodedNodeSet &Set, const ReturnStmt *RS);
/// \brief Enqueue a single node created as a result of statement processing.
void enqueueStmtNode(ExplodedNode *N, const CFGBlock *Block, unsigned Idx);
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
index 549db1a6a1e8..a710ae68be60 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
@@ -28,7 +28,6 @@
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/SmallPtrSet.h"
-#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Casting.h"
#include <memory>
@@ -451,57 +450,35 @@ public:
namespace llvm {
template<> struct GraphTraits<clang::ento::ExplodedNode*> {
- typedef clang::ento::ExplodedNode NodeType;
typedef clang::ento::ExplodedNode *NodeRef;
- typedef NodeType::succ_iterator ChildIteratorType;
- typedef llvm::df_iterator<NodeType*> nodes_iterator;
+ typedef clang::ento::ExplodedNode::succ_iterator ChildIteratorType;
+ typedef llvm::df_iterator<NodeRef> nodes_iterator;
- static inline NodeType* getEntryNode(NodeType* N) {
- return N;
- }
+ static NodeRef getEntryNode(NodeRef N) { return N; }
- static inline ChildIteratorType child_begin(NodeType* N) {
- return N->succ_begin();
- }
+ static ChildIteratorType child_begin(NodeRef N) { return N->succ_begin(); }
- static inline ChildIteratorType child_end(NodeType* N) {
- return N->succ_end();
- }
+ static ChildIteratorType child_end(NodeRef N) { return N->succ_end(); }
- static inline nodes_iterator nodes_begin(NodeType* N) {
- return df_begin(N);
- }
+ static nodes_iterator nodes_begin(NodeRef N) { return df_begin(N); }
- static inline nodes_iterator nodes_end(NodeType* N) {
- return df_end(N);
- }
+ static nodes_iterator nodes_end(NodeRef N) { return df_end(N); }
};
template<> struct GraphTraits<const clang::ento::ExplodedNode*> {
- typedef const clang::ento::ExplodedNode NodeType;
typedef const clang::ento::ExplodedNode *NodeRef;
- typedef NodeType::const_succ_iterator ChildIteratorType;
- typedef llvm::df_iterator<NodeType*> nodes_iterator;
+ typedef clang::ento::ExplodedNode::const_succ_iterator ChildIteratorType;
+ typedef llvm::df_iterator<NodeRef> nodes_iterator;
- static inline NodeType* getEntryNode(NodeType* N) {
- return N;
- }
+ static NodeRef getEntryNode(NodeRef N) { return N; }
- static inline ChildIteratorType child_begin(NodeType* N) {
- return N->succ_begin();
- }
+ static ChildIteratorType child_begin(NodeRef N) { return N->succ_begin(); }
- static inline ChildIteratorType child_end(NodeType* N) {
- return N->succ_end();
- }
+ static ChildIteratorType child_end(NodeRef N) { return N->succ_end(); }
- static inline nodes_iterator nodes_begin(NodeType* N) {
- return df_begin(N);
- }
+ static nodes_iterator nodes_begin(NodeRef N) { return df_begin(N); }
- static inline nodes_iterator nodes_end(NodeType* N) {
- return df_end(N);
- }
+ static nodes_iterator nodes_end(NodeRef N) { return df_end(N); }
};
} // end llvm namespace
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
index 50d85057041d..591b112d60ac 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -262,7 +262,8 @@ public:
/// Called by CoreEngine. Used to notify checkers that processing a
/// function has ended. Called for both inlined and and top-level functions.
void processEndOfFunction(NodeBuilderContext& BC,
- ExplodedNode *Pred) override;
+ ExplodedNode *Pred,
+ const ReturnStmt *RS = nullptr) override;
/// Remove dead bindings/symbols before exiting a function.
void removeDeadOnEndOfFunction(NodeBuilderContext& BC,
@@ -285,10 +286,6 @@ public:
ProgramStateRef processAssume(ProgramStateRef state, SVal cond,
bool assumption) override;
- /// wantsRegionChangeUpdate - Called by ProgramStateManager to determine if a
- /// region change should trigger a processRegionChanges update.
- bool wantsRegionChangeUpdate(ProgramStateRef state) override;
-
/// processRegionChanges - Called by ProgramStateManager whenever a change is made
/// to the store. Used to update checkers that track region values.
ProgramStateRef
@@ -482,6 +479,22 @@ public:
return X.isValid() ? svalBuilder.evalComplement(X.castAs<NonLoc>()) : X;
}
+ ProgramStateRef handleLValueBitCast(ProgramStateRef state, const Expr *Ex,
+ const LocationContext *LCtx, QualType T,
+ QualType ExTy, const CastExpr *CastE,
+ StmtNodeBuilder &Bldr,
+ ExplodedNode *Pred);
+
+ ProgramStateRef handleLVectorSplat(ProgramStateRef state,
+ const LocationContext *LCtx,
+ const CastExpr *CastE,
+ StmtNodeBuilder &Bldr,
+ ExplodedNode *Pred);
+
+ void handleUOExtension(ExplodedNodeSet::iterator I,
+ const UnaryOperator* U,
+ StmtNodeBuilder &Bldr);
+
public:
SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op,
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
index 40cd4e4b3c4e..da4b964424c3 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
@@ -1277,15 +1277,9 @@ public:
private:
template <typename RegionTy, typename A1>
- RegionTy* getRegion(const A1 a1);
-
- template <typename RegionTy, typename A1>
RegionTy* getSubRegion(const A1 a1, const MemRegion* superRegion);
template <typename RegionTy, typename A1, typename A2>
- RegionTy* getRegion(const A1 a1, const A2 a2);
-
- template <typename RegionTy, typename A1, typename A2>
RegionTy* getSubRegion(const A1 a1, const A2 a2,
const MemRegion* superRegion);
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
index f89747ee1756..463b375fda30 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
@@ -24,7 +24,6 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/ImmutableMap.h"
-#include "llvm/ADT/PointerIntPair.h"
#include "llvm/Support/Allocator.h"
#include <utility>
@@ -99,18 +98,18 @@ public:
/// This ctor is used when creating the first ProgramState object.
ProgramState(ProgramStateManager *mgr, const Environment& env,
StoreRef st, GenericDataMap gdm);
-
+
/// Copy ctor - We must explicitly define this or else the "Next" ptr
/// in FoldingSetNode will also get copied.
ProgramState(const ProgramState &RHS);
-
+
~ProgramState();
/// Return the ProgramStateManager associated with this state.
ProgramStateManager &getStateManager() const {
return *stateMgr;
}
-
+
/// Return the ConstraintManager.
ConstraintManager &getConstraintManager() const;
@@ -122,7 +121,7 @@ public:
/// is a mapping from locations to values.
Store getStore() const { return store; }
-
+
/// getGDM - Return the generic data map associated with this state.
GenericDataMap getGDM() const { return GDM; }
@@ -198,10 +197,10 @@ public:
///
/// This returns a new state with the added constraint on \p cond.
/// If no new state is feasible, NULL is returned.
- ProgramStateRef assumeWithinInclusiveRange(DefinedOrUnknownSVal Val,
- const llvm::APSInt &From,
- const llvm::APSInt &To,
- bool assumption) const;
+ 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).
@@ -209,14 +208,13 @@ public:
/// 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>
- assumeWithinInclusiveRange(DefinedOrUnknownSVal Val, const llvm::APSInt &From,
- const llvm::APSInt &To) const;
+ 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
/// constant.
ConditionTruthVal isNull(SVal V) const;
-
+
/// Utility method for getting regions.
const VarRegion* getRegion(const VarDecl *D, const LocationContext *LC) const;
@@ -255,7 +253,7 @@ public:
/// \param IS the set of invalidated symbols.
/// \param Call if non-null, the invalidated regions represent parameters to
/// the call and should be considered directly invalidated.
- /// \param ITraits information about special handling for a particular
+ /// \param ITraits information about special handling for a particular
/// region/symbol.
ProgramStateRef
invalidateRegions(ArrayRef<const MemRegion *> Regions, const Expr *E,
@@ -279,7 +277,7 @@ public:
/// Get the lvalue for a variable reference.
Loc getLValue(const VarDecl *D, const LocationContext *LC) const;
- Loc getLValue(const CompoundLiteralExpr *literal,
+ Loc getLValue(const CompoundLiteralExpr *literal,
const LocationContext *LC) const;
/// Get the lvalue for an ivar reference.
@@ -296,7 +294,7 @@ public:
/// Returns the SVal bound to the statement 'S' in the state's environment.
SVal getSVal(const Stmt *S, const LocationContext *LCtx) const;
-
+
SVal getSValAsScalarOrLoc(const Stmt *Ex, const LocationContext *LCtx) const;
/// \brief Return the value bound to the specified location.
@@ -311,7 +309,7 @@ public:
SVal getSVal(const MemRegion* R) const;
SVal getSValAsScalarOrLoc(const MemRegion *R) const;
-
+
/// \brief Visits the symbols reachable from the given SVal using the provided
/// SymbolVisitor.
///
@@ -320,22 +318,22 @@ public:
/// visitor to avoid repeated initialization cost.
/// \sa ScanReachableSymbols
bool scanReachableSymbols(SVal val, SymbolVisitor& visitor) const;
-
+
/// \brief 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
/// MemRegions range using the provided SymbolVisitor.
- bool scanReachableSymbols(const MemRegion * const *I,
+ bool scanReachableSymbols(const MemRegion * const *I,
const MemRegion * const *E,
SymbolVisitor &visitor) const;
template <typename CB> CB scanReachableSymbols(SVal val) const;
template <typename CB> CB scanReachableSymbols(const SVal *beg,
const SVal *end) const;
-
+
template <typename CB> CB
scanReachableSymbols(const MemRegion * const *beg,
const MemRegion * const *end) const;
@@ -470,7 +468,7 @@ private:
/// A BumpPtrAllocator to allocate states.
llvm::BumpPtrAllocator &Alloc;
-
+
/// A vector of ProgramStates that we can reuse.
std::vector<ProgramState *> freeStates;
@@ -633,9 +631,9 @@ public:
inline ConstraintManager &ProgramState::getConstraintManager() const {
return stateMgr->getConstraintManager();
}
-
+
inline const VarRegion* ProgramState::getRegion(const VarDecl *D,
- const LocationContext *LC) const
+ const LocationContext *LC) const
{
return getStateManager().getRegionManager().getVarRegion(D, LC);
}
@@ -648,7 +646,7 @@ inline ProgramStateRef ProgramState::assume(DefinedOrUnknownSVal Cond,
return getStateManager().ConstraintMgr
->assume(this, Cond.castAs<DefinedSVal>(), Assumption);
}
-
+
inline std::pair<ProgramStateRef , ProgramStateRef >
ProgramState::assume(DefinedOrUnknownSVal Cond) const {
if (Cond.isUnknown())
@@ -658,31 +656,29 @@ ProgramState::assume(DefinedOrUnknownSVal Cond) const {
->assumeDual(this, Cond.castAs<DefinedSVal>());
}
-inline ProgramStateRef
-ProgramState::assumeWithinInclusiveRange(DefinedOrUnknownSVal Val,
- const llvm::APSInt &From,
- const llvm::APSInt &To,
- bool Assumption) const {
+inline ProgramStateRef ProgramState::assumeInclusiveRange(
+ DefinedOrUnknownSVal Val, const llvm::APSInt &From, const llvm::APSInt &To,
+ bool Assumption) const {
if (Val.isUnknown())
return this;
assert(Val.getAs<NonLoc>() && "Only NonLocs are supported!");
- return getStateManager().ConstraintMgr->assumeWithinInclusiveRange(
- this, Val.castAs<NonLoc>(), From, To, Assumption);
+ return getStateManager().ConstraintMgr->assumeInclusiveRange(
+ this, Val.castAs<NonLoc>(), From, To, Assumption);
}
inline std::pair<ProgramStateRef, ProgramStateRef>
-ProgramState::assumeWithinInclusiveRange(DefinedOrUnknownSVal Val,
- const llvm::APSInt &From,
- const llvm::APSInt &To) const {
+ProgramState::assumeInclusiveRange(DefinedOrUnknownSVal Val,
+ const llvm::APSInt &From,
+ const llvm::APSInt &To) const {
if (Val.isUnknown())
return std::make_pair(this, this);
assert(Val.getAs<NonLoc>() && "Only NonLocs are supported!");
- return getStateManager().ConstraintMgr
- ->assumeWithinInclusiveRangeDual(this, Val.castAs<NonLoc>(), From, To);
+ return getStateManager().ConstraintMgr->assumeInclusiveRangeDual(
+ this, Val.castAs<NonLoc>(), From, To);
}
inline ProgramStateRef ProgramState::bindLoc(SVal LV, SVal V) const {
@@ -811,7 +807,7 @@ CB ProgramState::scanReachableSymbols(SVal val) const {
scanReachableSymbols(val, cb);
return cb;
}
-
+
template <typename CB>
CB ProgramState::scanReachableSymbols(const SVal *beg, const SVal *end) const {
CB cb(this);
@@ -828,8 +824,9 @@ CB ProgramState::scanReachableSymbols(const MemRegion * const *beg,
}
/// \class ScanReachableSymbols
-/// A Utility class that allows to visit the reachable symbols using a custom
-/// SymbolVisitor.
+/// A utility class that visits the reachable symbols using a custom
+/// SymbolVisitor. Terminates recursive traversal when the visitor function
+/// returns false.
class ScanReachableSymbols {
typedef llvm::DenseSet<const void*> VisitedItems;
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h
index 6b4da7db244d..a04fa9005955 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
//
// This file defines partial implementations of template specializations of
-// the class ProgramStateTrait<>. ProgramStateTrait<> is used by ProgramState
+// the class ProgramStateTrait<>. ProgramStateTrait<> is used by ProgramState
// to implement set/get methods for manipulating a ProgramState's
// generic data map.
//
@@ -81,6 +81,10 @@ namespace ento {
return F.remove(B, K);
}
+ static bool Contains(data_type B, key_type K) {
+ return B.contains(K);
+ }
+
static inline context_type MakeContext(void *p) {
return *((typename data_type::Factory*) p);
}
@@ -185,7 +189,7 @@ namespace ento {
}
};
-
+
// Partial specialization for bool.
template <> struct ProgramStatePartialTrait<bool> {
typedef bool data_type;
@@ -198,7 +202,7 @@ namespace ento {
return (void*) (uintptr_t) d;
}
};
-
+
// Partial specialization for unsigned.
template <> struct ProgramStatePartialTrait<unsigned> {
typedef unsigned data_type;
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
index e4be349c0263..a4c01fc45334 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
@@ -198,9 +198,13 @@ public:
DefinedOrUnknownSVal getDerivedRegionValueSymbolVal(
SymbolRef parentSymbol, const TypedValueRegion *region);
- DefinedSVal getMetadataSymbolVal(
- const void *symbolTag, const MemRegion *region,
- const Expr *expr, QualType type, unsigned count);
+ DefinedSVal getMetadataSymbolVal(const void *symbolTag,
+ const MemRegion *region,
+ const Expr *expr, QualType type,
+ const LocationContext *LCtx,
+ unsigned count);
+
+ DefinedSVal getMemberPointer(const DeclaratorDecl *DD);
DefinedSVal getFunctionPointer(const FunctionDecl *func);
@@ -224,6 +228,14 @@ public:
BasicVals.getLazyCompoundValData(store, region));
}
+ NonLoc makePointerToMember(const DeclaratorDecl *DD) {
+ return nonloc::PointerToMember(DD);
+ }
+
+ NonLoc makePointerToMember(const PointerToMemberData *PTMD) {
+ return nonloc::PointerToMember(PTMD);
+ }
+
NonLoc makeZeroArrayIndex() {
return nonloc::ConcreteInt(BasicVals.getValue(0, ArrayIndexTy));
}
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.def b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.def
index 2faec670b338..a0e309937892 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.def
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.def
@@ -66,6 +66,7 @@ ABSTRACT_SVAL(DefinedOrUnknownSVal, SVal)
NONLOC_SVAL(LazyCompoundVal, NonLoc)
NONLOC_SVAL(LocAsInteger, NonLoc)
NONLOC_SVAL(SymbolVal, NonLoc)
+ NONLOC_SVAL(PointerToMember, NonLoc)
#undef NONLOC_SVAL
#undef LOC_SVAL
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
index dbc7c99c6101..cc3c02a02c64 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
@@ -32,6 +32,7 @@ namespace ento {
class CompoundValData;
class LazyCompoundValData;
+class PointerToMemberData;
class ProgramState;
class BasicValueFactory;
class MemRegion;
@@ -459,6 +460,51 @@ private:
}
};
+/// \brief 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
+/// 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
+/// is required to accumulate the pointer-to-member cast history to figure out
+/// the correct subobject field.
+class PointerToMember : public NonLoc {
+ friend class ento::SValBuilder;
+
+public:
+ typedef llvm::PointerUnion<const DeclaratorDecl *,
+ const PointerToMemberData *> PTMDataType;
+ 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 {
+ return dyn_cast_or_null<AdjustedDecl>(getDecl());
+ }
+ typedef llvm::ImmutableList<const CXXBaseSpecifier *>::iterator iterator;
+ iterator begin() const;
+ iterator end() const;
+
+private:
+ explicit PointerToMember(const PTMDataType D)
+ : NonLoc(PointerToMemberKind, D.getOpaqueValue()) {}
+ friend class SVal;
+ PointerToMember() {}
+ static bool isKind(const SVal& V) {
+ return V.getBaseKind() == NonLocKind &&
+ V.getSubKind() == PointerToMemberKind;
+ }
+
+ static bool isKind(const NonLoc& V) {
+ return V.getSubKind() == PointerToMemberKind;
+ }
+};
+
} // end namespace ento::nonloc
//==------------------------------------------------------------------------==//
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
index a03b6306a0ed..fa7d3f72abf1 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
@@ -18,7 +18,6 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h"
#include "llvm/ADT/DenseSet.h"
-#include "llvm/ADT/Optional.h"
namespace clang {
@@ -124,15 +123,18 @@ public:
SVal evalDerivedToBase(SVal Derived, QualType DerivedPtrType,
bool IsVirtual);
- /// \brief Evaluates C++ dynamic_cast cast.
+ /// \brief Attempts to do a down cast. Used to model BaseToDerived and C++
+ /// dynamic_cast.
/// The callback may result in the following 3 scenarios:
/// - Successful cast (ex: derived is subclass of base).
/// - Failed cast (ex: derived is definitely not a subclass of base).
+ /// The distinction of this case from the next one is necessary to model
+ /// dynamic_cast.
/// - We don't know (base is a symbolic region and we don't have
/// enough info to determine if the cast will succeed at run time).
/// The function returns an SVal representing the derived class; it's
/// valid only if Failed flag is set to false.
- SVal evalDynamicCast(SVal Base, QualType DerivedPtrType, bool &Failed);
+ SVal attemptDownCast(SVal Base, QualType DerivedPtrType, bool &Failed);
const ElementRegion *GetElementZeroRegion(const MemRegion *R, QualType T);
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
index 1a731cf865ea..581ef206cff3 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
@@ -109,7 +109,8 @@ public:
/// Called by CoreEngine. Used to notify checkers that processing a
/// function has ended. Called for both inlined and and top-level functions.
virtual void processEndOfFunction(NodeBuilderContext& BC,
- ExplodedNode *Pred) = 0;
+ ExplodedNode *Pred,
+ const ReturnStmt *RS = nullptr) = 0;
// Generate the entry node of the callee.
virtual void processCallEnter(NodeBuilderContext& BC, CallEnter CE,
@@ -123,10 +124,6 @@ public:
virtual ProgramStateRef processAssume(ProgramStateRef state,
SVal cond, bool assumption) = 0;
- /// wantsRegionChangeUpdate - Called by ProgramStateManager to determine if a
- /// region change should trigger a processRegionChanges update.
- virtual bool wantsRegionChangeUpdate(ProgramStateRef state) = 0;
-
/// processRegionChanges - Called by ProgramStateManager whenever a change is
/// made to the store. Used to update checkers that track region values.
virtual ProgramStateRef
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SummaryManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SummaryManager.h
index ed878515988a..52d78b6a3c82 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SummaryManager.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SummaryManager.h
@@ -15,9 +15,6 @@
#ifndef LLVM_CLANG_GR_SUMMARY
#define LLVM_CLANG_GR_SUMMARY
-#include "llvm/ADT/FoldingSet.h"
-#include "llvm/Support/Allocator.h"
-
namespace clang {
namespace ento {
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
index 087430583e0c..f00dce568e3a 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
@@ -186,15 +186,18 @@ class SymbolMetadata : public SymbolData {
const MemRegion* R;
const Stmt *S;
QualType T;
+ const LocationContext *LCtx;
unsigned Count;
const void *Tag;
public:
SymbolMetadata(SymbolID sym, const MemRegion* r, const Stmt *s, QualType t,
- unsigned count, const void *tag)
- : SymbolData(SymbolMetadataKind, sym), R(r), S(s), T(t), Count(count), Tag(tag) {}
+ const LocationContext *LCtx, unsigned count, const void *tag)
+ : SymbolData(SymbolMetadataKind, sym), R(r), S(s), T(t), LCtx(LCtx),
+ Count(count), Tag(tag) {}
const MemRegion *getRegion() const { return R; }
const Stmt *getStmt() const { return S; }
+ const LocationContext *getLocationContext() const { return LCtx; }
unsigned getCount() const { return Count; }
const void *getTag() const { return Tag; }
@@ -203,18 +206,19 @@ public:
void dumpToStream(raw_ostream &os) const override;
static void Profile(llvm::FoldingSetNodeID& profile, const MemRegion *R,
- const Stmt *S, QualType T, unsigned Count,
- const void *Tag) {
+ const Stmt *S, QualType T, const LocationContext *LCtx,
+ unsigned Count, const void *Tag) {
profile.AddInteger((unsigned) SymbolMetadataKind);
profile.AddPointer(R);
profile.AddPointer(S);
profile.Add(T);
+ profile.AddPointer(LCtx);
profile.AddInteger(Count);
profile.AddPointer(Tag);
}
void Profile(llvm::FoldingSetNodeID& profile) override {
- Profile(profile, R, S, T, Count, Tag);
+ Profile(profile, R, S, T, LCtx, Count, Tag);
}
// Implement isa<T> support.
@@ -435,7 +439,9 @@ public:
/// VisitCount can be used to differentiate regions corresponding to
/// different loop iterations, thus, making the symbol path-dependent.
const SymbolMetadata *getMetadataSymbol(const MemRegion *R, const Stmt *S,
- QualType T, unsigned VisitCount,
+ QualType T,
+ const LocationContext *LCtx,
+ unsigned VisitCount,
const void *SymbolTag = nullptr);
const SymbolCast* getCastSymbol(const SymExpr *Operand,
diff --git a/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h b/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h
index 37ea05fb99cf..a9dad6c5e9a2 100644
--- a/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h
+++ b/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h
@@ -17,9 +17,7 @@
#include "clang/AST/ASTConsumer.h"
#include "clang/Basic/LLVM.h"
-#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
-#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
-#include <string>
+#include <memory>
namespace clang {
@@ -29,6 +27,7 @@ class CodeInjector;
class CompilerInstance;
namespace ento {
+class PathDiagnosticConsumer;
class CheckerManager;
class AnalysisASTConsumer : public ASTConsumer {
diff --git a/include/clang/StaticAnalyzer/Frontend/FrontendActions.h b/include/clang/StaticAnalyzer/Frontend/FrontendActions.h
index 36afb4bc5d73..e66d48b1be1d 100644
--- a/include/clang/StaticAnalyzer/Frontend/FrontendActions.h
+++ b/include/clang/StaticAnalyzer/Frontend/FrontendActions.h
@@ -17,6 +17,7 @@
namespace clang {
class Stmt;
+class AnalyzerOptions;
namespace ento {
@@ -52,6 +53,8 @@ private:
};
void printCheckerHelp(raw_ostream &OS, ArrayRef<std::string> plugins);
+void printEnabledCheckerList(raw_ostream &OS, ArrayRef<std::string> plugins,
+ const AnalyzerOptions &opts);
} // end GR namespace
diff --git a/include/clang/Tooling/CompilationDatabase.h b/include/clang/Tooling/CompilationDatabase.h
index 08a0ffec9d63..4611d3cdae5e 100644
--- a/include/clang/Tooling/CompilationDatabase.h
+++ b/include/clang/Tooling/CompilationDatabase.h
@@ -43,10 +43,11 @@ namespace tooling {
struct CompileCommand {
CompileCommand() {}
CompileCommand(Twine Directory, Twine Filename,
- std::vector<std::string> CommandLine)
+ std::vector<std::string> CommandLine, Twine Output)
: Directory(Directory.str()),
Filename(Filename.str()),
- CommandLine(std::move(CommandLine)) {}
+ CommandLine(std::move(CommandLine)),
+ Output(Output.str()){}
/// \brief The working directory the command was executed from.
std::string Directory;
@@ -57,6 +58,9 @@ struct CompileCommand {
/// \brief The command line that was executed.
std::vector<std::string> CommandLine;
+ /// The output file associated with the command.
+ std::string Output;
+
/// \brief An optional mapping from each file's path to its content for all
/// files needed for the compilation that are not available via the file
/// system.
diff --git a/include/clang/Tooling/Core/Replacement.h b/include/clang/Tooling/Core/Replacement.h
index 4815302ee455..95dc3cd6e763 100644
--- a/include/clang/Tooling/Core/Replacement.h
+++ b/include/clang/Tooling/Core/Replacement.h
@@ -19,13 +19,17 @@
#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/Error.h"
+#include "llvm/Support/raw_ostream.h"
#include <map>
#include <set>
#include <string>
+#include <system_error>
#include <vector>
namespace clang {
@@ -123,37 +127,185 @@ public:
/// \brief Returns a human readable string representation.
std::string toString() const;
- private:
- void setFromSourceLocation(const SourceManager &Sources,
- SourceLocation Start, unsigned Length,
- StringRef ReplacementText);
- void setFromSourceRange(const SourceManager &Sources,
- const CharSourceRange &Range,
- StringRef ReplacementText,
- const LangOptions &LangOpts);
+private:
+ void setFromSourceLocation(const SourceManager &Sources, SourceLocation Start,
+ unsigned Length, StringRef ReplacementText);
+ void setFromSourceRange(const SourceManager &Sources,
+ const CharSourceRange &Range,
+ StringRef ReplacementText,
+ const LangOptions &LangOpts);
std::string FilePath;
Range ReplacementRange;
std::string ReplacementText;
};
+enum class replacement_error {
+ fail_to_apply = 0,
+ wrong_file_path,
+ overlap_conflict,
+ insert_conflict,
+};
+
+/// \brief 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.
+ ReplacementError(replacement_error Err, Replacement Existing)
+ : Err(Err), ExistingReplacement(std::move(Existing)) {}
+
+ /// \brief 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)),
+ ExistingReplacement(std::move(Existing)) {}
+
+ std::string message() const override;
+
+ void log(raw_ostream &OS) const override { OS << message(); }
+
+ replacement_error get() const { return Err; }
+
+ static char ID;
+
+ const llvm::Optional<Replacement> &getNewReplacement() const {
+ return NewReplacement;
+ }
+
+ const llvm::Optional<Replacement> &getExistingReplacement() const {
+ return ExistingReplacement;
+ }
+
+private:
+ // Users are not expected to use error_code.
+ std::error_code convertToErrorCode() const override {
+ return llvm::inconvertibleErrorCode();
+ }
+
+ 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.
bool operator<(const Replacement &LHS, const Replacement &RHS);
/// \brief Equal-to operator between two Replacements.
bool operator==(const Replacement &LHS, const Replacement &RHS);
-/// \brief A set of Replacements.
-/// FIXME: Change to a vector and deduplicate in the RefactoringTool.
-typedef std::set<Replacement> Replacements;
+/// \brief 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;
+
+ public:
+ typedef ReplacementsImpl::const_iterator const_iterator;
+ typedef ReplacementsImpl::const_reverse_iterator 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.
+ /// \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
+ /// existing replacements (i.e. they are order-dependent) or R's file path is
+ /// different from the filepath of existing replacements. Callers must
+ /// explicitly check the Error returned, and the returned error can be
+ /// converted to a string message with `llvm::toString()`. This prevents users
+ /// from adding order-dependent replacements. To control the order in which
+ /// order-dependent replacements are applied, use merge({R}) with R referring
+ /// to the changed code after applying all existing replacements.
+ /// Two replacements A and B are considered order-independent if applying them
+ /// in either order produces the same result. Note that the range of the
+ /// replacement that is applied later still refers to the original code.
+ /// These include (but not restricted to) replacements that:
+ /// - don't overlap (being directly adjacent is fine) and
+ /// - are overlapping deletions.
+ /// - are insertions at the same offset and applying them in either order
+ /// has the same effect, i.e. X + Y = Y + X when inserting X and Y
+ /// respectively.
+ /// - are identical replacements, i.e. applying the same replacement twice
+ /// is equivalent to applying it once.
+ /// Examples:
+ /// 1. Replacement A(0, 0, "a") and B(0, 0, "aa") are order-independent since
+ /// applying them in either order gives replacement (0, 0, "aaa").
+ /// However, A(0, 0, "a") and B(0, 0, "b") are order-dependent since
+ /// applying A first gives (0, 0, "ab") while applying B first gives (B, A,
+ /// "ba").
+ /// 2. Replacement A(0, 2, "123") and B(0, 2, "123") are order-independent
+ /// since applying them in either order gives (0, 2, "123").
+ /// 3. Replacement A(0, 3, "123") and B(2, 3, "321") are order-independent
+ /// since either order gives (0, 5, "12321").
+ /// 4. Replacement A(0, 3, "ab") and B(0, 3, "ab") are order-independent since
+ /// applying the same replacement twice is equivalent to applying it once.
+ /// Replacements with offset UINT_MAX are special - we do not detect conflicts
+ /// for such replacements since users may add them intentionally as a special
+ /// category of replacements.
+ llvm::Error add(const Replacement &R);
+
+ /// \brief Merges \p Replaces into the current replacements. \p Replaces
+ /// refers to code after applying the current replacements.
+ Replacements merge(const Replacements &Replaces) const;
+
+ // Returns the affected ranges in the changed code.
+ std::vector<Range> getAffectedRanges() const;
+
+ // Returns the new offset in the code after replacements being applied.
+ // Note that if there is an insertion at Offset in the current replacements,
+ // \p Offset will be shifted to Offset + Length in inserted text.
+ unsigned getShiftedCodePosition(unsigned Position) const;
+
+ unsigned size() const { return Replaces.size(); }
+
+ void clear() { Replaces.clear(); }
+
+ bool empty() const { return Replaces.empty(); }
+
+ const_iterator begin() const { return Replaces.begin(); }
+
+ const_iterator end() const { return Replaces.end(); }
+
+ const_reverse_iterator rbegin() const { return Replaces.rbegin(); }
+
+ const_reverse_iterator rend() const { return Replaces.rend(); }
+
+ bool operator==(const Replacements &RHS) const {
+ return Replaces == RHS.Replaces;
+ }
-/// \brief Apply all replacements in \p Replaces to the Rewriter \p Rewrite.
-///
-/// Replacement applications happen independently of the success of
-/// other applications.
-///
-/// \returns true if all replacements apply. false otherwise.
-bool applyAllReplacements(const Replacements &Replaces, Rewriter &Rewrite);
+
+private:
+ Replacements(const_iterator Begin, const_iterator End)
+ : Replaces(Begin, End) {}
+
+ // Returns `R` with new range that refers to code after `Replaces` being
+ // applied.
+ Replacement getReplacementInChangedCode(const Replacement &R) const;
+
+ // Returns a set of replacements that is equivalent to the current
+ // replacements by merging all adjacent replacements. Two sets of replacements
+ // are considered equivalent if they have the same effect when they are
+ // applied.
+ Replacements getCanonicalReplacements() const;
+
+ // If `R` and all existing replacements are order-indepedent, then merge it
+ // with `Replaces` and returns the merged replacements; otherwise, returns an
+ // error.
+ llvm::Expected<Replacements>
+ mergeIfOrderIndependent(const Replacement &R) const;
+
+ ReplacementsImpl Replaces;
+};
/// \brief Apply all replacements in \p Replaces to the Rewriter \p Rewrite.
///
@@ -161,8 +313,7 @@ bool applyAllReplacements(const Replacements &Replaces, Rewriter &Rewrite);
/// other applications.
///
/// \returns true if all replacements apply. false otherwise.
-bool applyAllReplacements(const std::vector<Replacement> &Replaces,
- Rewriter &Rewrite);
+bool applyAllReplacements(const Replacements &Replaces, Rewriter &Rewrite);
/// \brief Applies all replacements in \p Replaces to \p Code.
///
@@ -174,27 +325,6 @@ bool applyAllReplacements(const std::vector<Replacement> &Replaces,
llvm::Expected<std::string> applyAllReplacements(StringRef Code,
const Replacements &Replaces);
-/// \brief Calculates how a code \p Position is shifted when \p Replaces are
-/// applied.
-unsigned shiftedCodePosition(const Replacements& Replaces, unsigned Position);
-
-/// \brief Calculates how a code \p Position is shifted when \p Replaces are
-/// applied.
-///
-/// \pre Replaces[i].getOffset() <= Replaces[i+1].getOffset().
-unsigned shiftedCodePosition(const std::vector<Replacement> &Replaces,
- unsigned Position);
-
-/// \brief Removes duplicate Replacements and reports if Replacements conflict
-/// with one another. All Replacements are assumed to be in the same file.
-///
-/// \post Replaces[i].getOffset() <= Replaces[i+1].getOffset().
-///
-/// This function sorts \p Replaces so that conflicts can be reported simply by
-/// offset into \p Replaces and number of elements in the conflict.
-void deduplicate(std::vector<Replacement> &Replaces,
- std::vector<Range> &Conflicts);
-
/// \brief Collection of Replacements generated from a single translation unit.
struct TranslationUnitReplacements {
/// Name of the main source for the translation unit.
@@ -208,14 +338,6 @@ struct TranslationUnitReplacements {
std::vector<Replacement> Replacements;
};
-/// \brief Calculates the ranges in a single file that are affected by the
-/// Replacements. Overlapping ranges will be merged.
-///
-/// \pre Replacements must be for the same file.
-///
-/// \returns a non-overlapping and sorted ranges.
-std::vector<Range> calculateChangedRanges(const Replacements &Replaces);
-
/// \brief 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.
@@ -228,16 +350,12 @@ std::vector<Range>
calculateRangesAfterReplacements(const Replacements &Replaces,
const std::vector<Range> &Ranges);
-/// \brief Groups a random set of replacements by file path. Replacements
-/// related to the same file entry are put into the same vector.
-std::map<std::string, Replacements>
-groupReplacementsByFile(const Replacements &Replaces);
-
-/// \brief Merges two sets of replacements with the second set referring to the
-/// code after applying the first set. Within both 'First' and 'Second',
-/// replacements must not overlap.
-Replacements mergeReplacements(const Replacements &First,
- const Replacements &Second);
+/// \brief 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(
+ FileManager &FileMgr,
+ const std::map<std::string, Replacements> &FileToReplaces);
template <typename Node>
Replacement::Replacement(const SourceManager &Sources,
diff --git a/include/clang/Tooling/FileMatchTrie.h b/include/clang/Tooling/FileMatchTrie.h
index 745c1645068a..882979ef8ff6 100644
--- a/include/clang/Tooling/FileMatchTrie.h
+++ b/include/clang/Tooling/FileMatchTrie.h
@@ -16,10 +16,11 @@
#define LLVM_CLANG_TOOLING_FILEMATCHTRIE_H
#include "clang/Basic/LLVM.h"
-#include "llvm/ADT/StringRef.h"
#include <memory>
-#include <string>
-#include <vector>
+
+namespace llvm {
+class StringRef;
+}
namespace clang {
namespace tooling {
diff --git a/include/clang/Tooling/JSONCompilationDatabase.h b/include/clang/Tooling/JSONCompilationDatabase.h
index 2a13fc155cea..9a6866240b08 100644
--- a/include/clang/Tooling/JSONCompilationDatabase.h
+++ b/include/clang/Tooling/JSONCompilationDatabase.h
@@ -55,6 +55,7 @@ namespace tooling {
///
/// JSON compilation databases can for example be generated in CMake projects
/// by setting the flag -DCMAKE_EXPORT_COMPILE_COMMANDS.
+enum class JSONCommandLineSyntax { Windows, Gnu, AutoDetect };
class JSONCompilationDatabase : public CompilationDatabase {
public:
/// \brief Loads a JSON compilation database from the specified file.
@@ -62,15 +63,17 @@ public:
/// Returns NULL and sets ErrorMessage if the database could not be
/// loaded from the given file.
static std::unique_ptr<JSONCompilationDatabase>
- loadFromFile(StringRef FilePath, std::string &ErrorMessage);
+ loadFromFile(StringRef FilePath, std::string &ErrorMessage,
+ JSONCommandLineSyntax Syntax);
/// \brief 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);
+ loadFromBuffer(StringRef DatabaseString, std::string &ErrorMessage,
+ JSONCommandLineSyntax Syntax);
- /// \brief Returns all compile comamnds in which the specified file was
+ /// \brief Returns all compile commands in which the specified file was
/// compiled.
///
/// FIXME: Currently FilePath must be an absolute path inside the
@@ -89,8 +92,9 @@ public:
private:
/// \brief Constructs a JSON compilation database on a memory buffer.
- JSONCompilationDatabase(std::unique_ptr<llvm::MemoryBuffer> Database)
- : Database(std::move(Database)),
+ 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.
@@ -99,15 +103,17 @@ private:
/// failed.
bool parse(std::string &ErrorMessage);
- // Tuple (directory, filename, commandline) where 'commandline' points to the
- // corresponding scalar nodes in the YAML stream.
+ // Tuple (directory, filename, commandline, output) where 'commandline'
+ // points to the corresponding scalar nodes in the YAML stream.
// If the command line contains a single argument, it is a shell-escaped
// command line.
// 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 *>> CompileCommandRef;
+ std::vector<llvm::yaml::ScalarNode *>,
+ llvm::yaml::ScalarNode *> CompileCommandRef;
/// \brief Converts the given array of CompileCommandRefs to CompileCommands.
void getCommands(ArrayRef<CompileCommandRef> CommandsRef,
@@ -123,6 +129,7 @@ private:
FileMatchTrie MatchTrie;
std::unique_ptr<llvm::MemoryBuffer> Database;
+ JSONCommandLineSyntax Syntax;
llvm::SourceMgr SM;
llvm::yaml::Stream YAMLStream;
};
diff --git a/include/clang/Tooling/Refactoring.h b/include/clang/Tooling/Refactoring.h
index 06ec8b087629..bc95c3b09ec2 100644
--- a/include/clang/Tooling/Refactoring.h
+++ b/include/clang/Tooling/Refactoring.h
@@ -21,6 +21,7 @@
#include "clang/Tooling/Core/Replacement.h"
#include "clang/Tooling/Tooling.h"
+#include <map>
#include <string>
namespace clang {
@@ -42,9 +43,9 @@ public:
std::shared_ptr<PCHContainerOperations> PCHContainerOps =
std::make_shared<PCHContainerOperations>());
- /// \brief Returns the set of replacements to which replacements should
- /// be added during the run of the tool.
- Replacements &getReplacements();
+ /// \brief 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
/// the results to disk.
@@ -54,6 +55,9 @@ public:
/// \brief Apply all stored replacements to the given Rewriter.
///
+ /// FileToReplaces will be deduplicated with `groupReplacementsByFile` before
+ /// application.
+ ///
/// Replacement applications happen independently of the success of other
/// applications.
///
@@ -65,7 +69,7 @@ private:
int saveRewrittenFiles(Rewriter &Rewrite);
private:
- Replacements Replace;
+ std::map<std::string, Replacements> FileToReplaces;
};
/// \brief Groups \p Replaces by the file path and applies each group of
@@ -74,17 +78,21 @@ private:
///
/// \pre Replacements must be conflict-free.
///
+/// FileToReplaces will be deduplicated with `groupReplacementsByFile` before
+/// application.
+///
/// Replacement applications happen independently of the success of other
/// applications.
///
-/// \param[in] Replaces Replacements to apply.
+/// \param[in] FileToReplaces Replacements (grouped by files) to apply.
/// \param[in] Rewrite The `Rewritter` to apply replacements on.
/// \param[in] Style The style name used for reformatting. See ```getStyle``` in
/// "include/clang/Format/Format.h" for all possible style forms.
///
/// \returns true if all replacements applied and formatted. false otherwise.
-bool formatAndApplyAllReplacements(const Replacements &Replaces,
- Rewriter &Rewrite, StringRef Style = "file");
+bool formatAndApplyAllReplacements(
+ const std::map<std::string, Replacements> &FileToReplaces,
+ Rewriter &Rewrite, StringRef Style = "file");
} // end namespace tooling
} // end namespace clang
diff --git a/include/clang/Tooling/ReplacementsYaml.h b/include/clang/Tooling/ReplacementsYaml.h
index 4a7666d2c555..47b7f3f9a534 100644
--- a/include/clang/Tooling/ReplacementsYaml.h
+++ b/include/clang/Tooling/ReplacementsYaml.h
@@ -19,7 +19,6 @@
#include "clang/Tooling/Refactoring.h"
#include "llvm/Support/YAMLTraits.h"
#include <string>
-#include <vector>
LLVM_YAML_IS_SEQUENCE_VECTOR(clang::tooling::Replacement)
diff --git a/include/clang/module.modulemap b/include/clang/module.modulemap
index 7fa8b82515eb..3b4238110026 100644
--- a/include/clang/module.modulemap
+++ b/include/clang/module.modulemap
@@ -38,6 +38,7 @@ module Clang_Basic {
textual header "Basic/BuiltinsSystemZ.def"
textual header "Basic/BuiltinsWebAssembly.def"
textual header "Basic/BuiltinsX86.def"
+ textual header "Basic/BuiltinsX86_64.def"
textual header "Basic/BuiltinsXCore.def"
textual header "Basic/DiagnosticOptions.def"
textual header "Basic/LangOptions.def"
diff --git a/lib/ARCMigrate/ARCMT.cpp b/lib/ARCMigrate/ARCMT.cpp
index da93d8418e78..680aa3e48da4 100644
--- a/lib/ARCMigrate/ARCMT.cpp
+++ b/lib/ARCMigrate/ARCMT.cpp
@@ -16,6 +16,7 @@
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Frontend/Utils.h"
#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Rewrite/Core/Rewriter.h"
#include "clang/Sema/SemaDiagnostic.h"
#include "clang/Serialization/ASTReader.h"
diff --git a/lib/ARCMigrate/FileRemapper.cpp b/lib/ARCMigrate/FileRemapper.cpp
index 2cf20699aeef..4dedac88f982 100644
--- a/lib/ARCMigrate/FileRemapper.cpp
+++ b/lib/ARCMigrate/FileRemapper.cpp
@@ -64,7 +64,7 @@ bool FileRemapper::initFromFile(StringRef filePath, DiagnosticsEngine &Diag,
std::vector<std::pair<const FileEntry *, const FileEntry *> > pairs;
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> fileBuf =
- llvm::MemoryBuffer::getFile(infoFile.c_str());
+ llvm::MemoryBuffer::getFile(infoFile);
if (!fileBuf)
return report("Error opening file: " + infoFile, Diag);
diff --git a/lib/ARCMigrate/Transforms.cpp b/lib/ARCMigrate/Transforms.cpp
index 3fd36ff310f3..cb96a547fbac 100644
--- a/lib/ARCMigrate/Transforms.cpp
+++ b/lib/ARCMigrate/Transforms.cpp
@@ -11,17 +11,12 @@
#include "Internals.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/RecursiveASTVisitor.h"
-#include "clang/AST/StmtVisitor.h"
#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/Lexer.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Sema.h"
-#include "clang/Sema/SemaDiagnostic.h"
-#include "llvm/ADT/DenseSet.h"
-#include "llvm/ADT/StringSwitch.h"
-#include <map>
using namespace clang;
using namespace arcmt;
diff --git a/lib/AST/APValue.cpp b/lib/AST/APValue.cpp
index 3c587331ed07..488ad3373ca3 100644
--- a/lib/AST/APValue.cpp
+++ b/lib/AST/APValue.cpp
@@ -17,8 +17,6 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Expr.h"
#include "clang/AST/Type.h"
-#include "clang/Basic/Diagnostic.h"
-#include "llvm/ADT/SmallString.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
@@ -29,6 +27,7 @@ namespace {
CharUnits Offset;
unsigned PathLength;
unsigned CallIndex;
+ bool IsNullPtr;
};
}
@@ -151,10 +150,11 @@ APValue::APValue(const APValue &RHS) : Kind(Uninitialized) {
MakeLValue();
if (RHS.hasLValuePath())
setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), RHS.getLValuePath(),
- RHS.isLValueOnePastTheEnd(), RHS.getLValueCallIndex());
+ RHS.isLValueOnePastTheEnd(), RHS.getLValueCallIndex(),
+ RHS.isNullPointer());
else
setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), NoLValuePath(),
- RHS.getLValueCallIndex());
+ RHS.getLValueCallIndex(), RHS.isNullPointer());
break;
case Array:
MakeArray(RHS.getArrayInitializedElts(), RHS.getArraySize());
@@ -263,7 +263,7 @@ LLVM_DUMP_METHOD void APValue::dump() const {
static double GetApproxValue(const llvm::APFloat &F) {
llvm::APFloat V = F;
bool ignored;
- V.convert(llvm::APFloat::IEEEdouble, llvm::APFloat::rmNearestTiesToEven,
+ V.convert(llvm::APFloat::IEEEdouble(), llvm::APFloat::rmNearestTiesToEven,
&ignored);
return V.convertToDouble();
}
@@ -581,8 +581,13 @@ unsigned APValue::getLValueCallIndex() const {
return ((const LV*)(const char*)Data.buffer)->CallIndex;
}
+bool APValue::isNullPointer() const {
+ assert(isLValue() && "Invalid usage");
+ return ((const LV*)(const char*)Data.buffer)->IsNullPtr;
+}
+
void APValue::setLValue(LValueBase B, const CharUnits &O, NoLValuePath,
- unsigned CallIndex) {
+ unsigned CallIndex, bool IsNullPtr) {
assert(isLValue() && "Invalid accessor");
LV &LVal = *((LV*)(char*)Data.buffer);
LVal.BaseAndIsOnePastTheEnd.setPointer(B);
@@ -590,11 +595,12 @@ void APValue::setLValue(LValueBase B, const CharUnits &O, NoLValuePath,
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) {
+ unsigned CallIndex, bool IsNullPtr) {
assert(isLValue() && "Invalid accessor");
LV &LVal = *((LV*)(char*)Data.buffer);
LVal.BaseAndIsOnePastTheEnd.setPointer(B);
@@ -603,6 +609,7 @@ void APValue::setLValue(LValueBase B, const CharUnits &O,
LVal.CallIndex = CallIndex;
LVal.resizePath(Path.size());
memcpy(LVal.getPath(), Path.data(), Path.size() * sizeof(LValuePathEntry));
+ LVal.IsNullPtr = IsNullPtr;
}
const ValueDecl *APValue::getMemberPointerDecl() const {
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 6aad4d1d570b..1b5988d01988 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -34,7 +34,6 @@
#include "clang/Basic/Builtins.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
-#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/Capacity.h"
@@ -652,6 +651,10 @@ ASTContext::getCanonicalTemplateTemplateParmDecl(
cast<TemplateTemplateParmDecl>(*P)));
}
+ assert(!TTP->getRequiresClause() &&
+ "Unexpected requires-clause on template template-parameter");
+ Expr *const CanonRequiresClause = nullptr;
+
TemplateTemplateParmDecl *CanonTTP
= TemplateTemplateParmDecl::Create(*this, getTranslationUnitDecl(),
SourceLocation(), TTP->getDepth(),
@@ -661,7 +664,8 @@ ASTContext::getCanonicalTemplateTemplateParmDecl(
TemplateParameterList::Create(*this, SourceLocation(),
SourceLocation(),
CanonParams,
- SourceLocation()));
+ SourceLocation(),
+ CanonRequiresClause));
// Get the new insert position for the node we care about.
Canonical = CanonTemplateTemplateParms.FindNodeOrInsertPos(ID, InsertPos);
@@ -700,8 +704,8 @@ static const LangAS::Map *getAddressSpaceMap(const TargetInfo &T,
// language-specific address space.
static const unsigned FakeAddrSpaceMap[] = {
1, // opencl_global
- 2, // opencl_local
- 3, // opencl_constant
+ 3, // opencl_local
+ 2, // opencl_constant
4, // opencl_generic
5, // cuda_device
6, // cuda_constant
@@ -788,7 +792,8 @@ ASTContext::~ASTContext() {
MaterializedTemporaryValues)
MTVPair.second->~APValue();
- llvm::DeleteContainerSeconds(MangleNumberingContexts);
+ for (const auto &Value : ModuleInitializers)
+ Value.second->~PerModuleInitializers();
}
void ASTContext::ReleaseParentMapEntries() {
@@ -902,6 +907,67 @@ void ASTContext::deduplicateMergedDefinitonsFor(NamedDecl *ND) {
Merged.erase(std::remove(Merged.begin(), Merged.end(), nullptr), Merged.end());
}
+void ASTContext::PerModuleInitializers::resolve(ASTContext &Ctx) {
+ if (LazyInitializers.empty())
+ return;
+
+ auto *Source = Ctx.getExternalSource();
+ assert(Source && "lazy initializers but no external source");
+
+ auto LazyInits = std::move(LazyInitializers);
+ LazyInitializers.clear();
+
+ for (auto ID : LazyInits)
+ Initializers.push_back(Source->GetExternalDecl(ID));
+
+ assert(LazyInitializers.empty() &&
+ "GetExternalDecl for lazy module initializer added more inits");
+}
+
+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)) {
+ auto It = ModuleInitializers.find(ID->getImportedModule());
+
+ // Maybe the ImportDecl does nothing at all. (Common case.)
+ if (It == ModuleInitializers.end())
+ return;
+
+ // Maybe the ImportDecl only imports another ImportDecl.
+ auto &Imported = *It->second;
+ if (Imported.Initializers.size() + Imported.LazyInitializers.size() == 1) {
+ Imported.resolve(*this);
+ auto *OnlyDecl = Imported.Initializers.front();
+ if (isa<ImportDecl>(OnlyDecl))
+ D = OnlyDecl;
+ }
+ }
+
+ auto *&Inits = ModuleInitializers[M];
+ if (!Inits)
+ Inits = new (*this) PerModuleInitializers;
+ Inits->Initializers.push_back(D);
+}
+
+void ASTContext::addLazyModuleInitializers(Module *M, ArrayRef<uint32_t> IDs) {
+ auto *&Inits = ModuleInitializers[M];
+ if (!Inits)
+ Inits = new (*this) PerModuleInitializers;
+ Inits->LazyInitializers.insert(Inits->LazyInitializers.end(),
+ IDs.begin(), IDs.end());
+}
+
+ArrayRef<Decl*> ASTContext::getModuleInitializers(Module *M) {
+ auto It = ModuleInitializers.find(M);
+ if (It == ModuleInitializers.end())
+ return None;
+
+ auto *Inits = It->second;
+ Inits->resolve(*this);
+ return Inits->Initializers;
+}
+
ExternCContextDecl *ASTContext::getExternCContextDecl() const {
if (!ExternCContext)
ExternCContext = ExternCContextDecl::Create(*this, getTranslationUnitDecl());
@@ -1204,9 +1270,8 @@ void ASTContext::setClassScopeSpecializationPattern(FunctionDecl *FD,
}
NamedDecl *
-ASTContext::getInstantiatedFromUsingDecl(UsingDecl *UUD) {
- llvm::DenseMap<UsingDecl *, NamedDecl *>::const_iterator Pos
- = InstantiatedFromUsingDecl.find(UUD);
+ASTContext::getInstantiatedFromUsingDecl(NamedDecl *UUD) {
+ auto Pos = InstantiatedFromUsingDecl.find(UUD);
if (Pos == InstantiatedFromUsingDecl.end())
return nullptr;
@@ -1214,11 +1279,15 @@ ASTContext::getInstantiatedFromUsingDecl(UsingDecl *UUD) {
}
void
-ASTContext::setInstantiatedFromUsingDecl(UsingDecl *Inst, NamedDecl *Pattern) {
+ASTContext::setInstantiatedFromUsingDecl(NamedDecl *Inst, NamedDecl *Pattern) {
assert((isa<UsingDecl>(Pattern) ||
isa<UnresolvedUsingValueDecl>(Pattern) ||
isa<UnresolvedUsingTypenameDecl>(Pattern)) &&
"pattern decl is not a using decl");
+ assert((isa<UsingDecl>(Inst) ||
+ isa<UnresolvedUsingValueDecl>(Inst) ||
+ isa<UnresolvedUsingTypenameDecl>(Inst)) &&
+ "instantiation did not produce a using decl");
assert(!InstantiatedFromUsingDecl[Inst] && "pattern already exists");
InstantiatedFromUsingDecl[Inst] = Pattern;
}
@@ -1504,6 +1573,30 @@ bool ASTContext::isAlignmentRequired(QualType T) const {
return isAlignmentRequired(T.getTypePtr());
}
+unsigned ASTContext::getTypeAlignIfKnown(QualType T) const {
+ // An alignment on a typedef overrides anything else.
+ if (auto *TT = T->getAs<TypedefType>())
+ if (unsigned Align = TT->getDecl()->getMaxAlignment())
+ return Align;
+
+ // If we have an (array of) complete type, we're done.
+ T = getBaseElementType(T);
+ if (!T->isIncompleteType())
+ return getTypeAlign(T);
+
+ // 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 (unsigned Align = TT->getDecl()->getMaxAlignment())
+ return Align;
+
+ // Otherwise, see if the declaration of the type had an attribute.
+ if (auto *TT = T->getAs<TagType>())
+ return TT->getDecl()->getMaxAlignment();
+
+ return 0;
+}
+
TypeInfo ASTContext::getTypeInfo(const Type *T) const {
TypeInfoMap::iterator I = MemoizedTypeInfo.find(T);
if (I != MemoizedTypeInfo.end())
@@ -1671,24 +1764,29 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
Width = Target->getPointerWidth(0);
Align = Target->getPointerAlign(0);
break;
- case BuiltinType::OCLSampler:
- // Samplers are modeled as integers.
- Width = Target->getIntWidth();
- Align = Target->getIntAlign();
+ case BuiltinType::OCLSampler: {
+ auto AS = getTargetAddressSpace(LangAS::opencl_constant);
+ Width = Target->getPointerWidth(AS);
+ Align = Target->getPointerAlign(AS);
break;
+ }
case BuiltinType::OCLEvent:
case BuiltinType::OCLClkEvent:
case BuiltinType::OCLQueue:
case BuiltinType::OCLNDRange:
case BuiltinType::OCLReserveID:
-#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
- case BuiltinType::Id:
-#include "clang/Basic/OpenCLImageTypes.def"
-
// Currently these types are pointers to opaque types.
Width = Target->getPointerWidth(0);
Align = Target->getPointerAlign(0);
break;
+#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
+ case BuiltinType::Id:
+#include "clang/Basic/OpenCLImageTypes.def"
+ {
+ auto AS = getTargetAddressSpace(Target->getOpenCLImageAddrSpace());
+ Width = Target->getPointerWidth(AS);
+ Align = Target->getPointerAlign(AS);
+ }
}
break;
case Type::ObjCObjectPointer:
@@ -1787,6 +1885,9 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
case Type::Paren:
return getTypeInfo(cast<ParenType>(T)->getInnerType().getTypePtr());
+ case Type::ObjCTypeParam:
+ return getTypeInfo(cast<ObjCTypeParamType>(T)->desugar().getTypePtr());
+
case Type::Typedef: {
const TypedefNameDecl *Typedef = cast<TypedefType>(T)->getDecl();
TypeInfo Info = getTypeInfo(Typedef->getUnderlyingType().getTypePtr());
@@ -2284,6 +2385,14 @@ static QualType getFunctionTypeWithExceptionSpec(
Proto->getExtProtoInfo().withExceptionSpec(ESI));
}
+bool ASTContext::hasSameFunctionTypeIgnoringExceptionSpec(QualType T,
+ QualType U) {
+ return hasSameType(T, U) ||
+ (getLangOpts().CPlusPlus1z &&
+ hasSameType(getFunctionTypeWithExceptionSpec(*this, T, EST_None),
+ getFunctionTypeWithExceptionSpec(*this, U, EST_None)));
+}
+
void ASTContext::adjustExceptionSpec(
FunctionDecl *FD, const FunctionProtoType::ExceptionSpecInfo &ESI,
bool AsWritten) {
@@ -3039,46 +3148,160 @@ ASTContext::getCanonicalFunctionResultType(QualType ResultType) const {
return CanResultType;
}
-QualType
-ASTContext::getFunctionType(QualType ResultTy, ArrayRef<QualType> ArgArray,
- const FunctionProtoType::ExtProtoInfo &EPI) const {
+static bool isCanonicalExceptionSpecification(
+ const FunctionProtoType::ExceptionSpecInfo &ESI, bool NoexceptInType) {
+ if (ESI.Type == EST_None)
+ return true;
+ if (!NoexceptInType)
+ return false;
+
+ // C++17 onwards: exception specification is part of the type, as a simple
+ // boolean "can this function type throw".
+ if (ESI.Type == EST_BasicNoexcept)
+ 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.
+ if (ESI.Type == EST_Dynamic) {
+ bool AnyPackExpansions = false;
+ for (QualType ET : ESI.Exceptions) {
+ if (!ET.isCanonical())
+ return false;
+ if (ET->getAs<PackExpansionType>())
+ AnyPackExpansions = true;
+ }
+ 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;
+}
+
+QualType ASTContext::getFunctionTypeInternal(
+ QualType ResultTy, ArrayRef<QualType> ArgArray,
+ const FunctionProtoType::ExtProtoInfo &EPI, bool OnlyWantCanonical) const {
size_t NumArgs = ArgArray.size();
// Unique functions, to guarantee there is only one function of a particular
// structure.
llvm::FoldingSetNodeID ID;
FunctionProtoType::Profile(ID, ResultTy, ArgArray.begin(), NumArgs, EPI,
- *this);
+ *this, true);
+
+ QualType Canonical;
+ bool Unique = false;
void *InsertPos = nullptr;
- if (FunctionProtoType *FTP =
- FunctionProtoTypes.FindNodeOrInsertPos(ID, InsertPos))
- return QualType(FTP, 0);
+ if (FunctionProtoType *FPT =
+ FunctionProtoTypes.FindNodeOrInsertPos(ID, InsertPos)) {
+ QualType Existing = QualType(FPT, 0);
+
+ // If we find a pre-existing equivalent FunctionProtoType, we can just reuse
+ // it so long as our exception specification doesn't contain a dependent
+ // 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 ||
+ EPI.ExceptionSpec.NoexceptExpr == FPT->getNoexceptExpr())
+ return Existing;
+
+ // We need a new type sugar node for this one, to hold the new noexcept
+ // expression. We do no canonicalization here, but that's OK since we don't
+ // expect to see the same noexcept expression much more than once.
+ Canonical = getCanonicalType(Existing);
+ Unique = true;
+ }
+
+ bool NoexceptInType = getLangOpts().CPlusPlus1z;
+ bool IsCanonicalExceptionSpec =
+ isCanonicalExceptionSpecification(EPI.ExceptionSpec, NoexceptInType);
// Determine whether the type being created is already canonical or not.
- bool isCanonical =
- EPI.ExceptionSpec.Type == EST_None && isCanonicalResultType(ResultTy) &&
- !EPI.HasTrailingReturn;
+ bool isCanonical = !Unique && IsCanonicalExceptionSpec &&
+ isCanonicalResultType(ResultTy) && !EPI.HasTrailingReturn;
for (unsigned i = 0; i != NumArgs && isCanonical; ++i)
if (!ArgArray[i].isCanonicalAsParam())
isCanonical = false;
- // If this type isn't canonical, get the canonical version of it.
- // The exception spec is not part of the canonical type.
- QualType Canonical;
- if (!isCanonical) {
+ if (OnlyWantCanonical)
+ assert(isCanonical &&
+ "given non-canonical parameters constructing canonical type");
+
+ // If this type isn't canonical, get the canonical version of it if we don't
+ // already have it. The exception spec is only partially part of the
+ // canonical type, and only in C++17 onwards.
+ if (!isCanonical && Canonical.isNull()) {
SmallVector<QualType, 16> CanonicalArgs;
CanonicalArgs.reserve(NumArgs);
for (unsigned i = 0; i != NumArgs; ++i)
CanonicalArgs.push_back(getCanonicalParamType(ArgArray[i]));
+ llvm::SmallVector<QualType, 8> ExceptionTypeStorage;
FunctionProtoType::ExtProtoInfo CanonicalEPI = EPI;
CanonicalEPI.HasTrailingReturn = false;
- CanonicalEPI.ExceptionSpec = FunctionProtoType::ExceptionSpecInfo();
+
+ if (IsCanonicalExceptionSpec) {
+ // Exception spec is already OK.
+ } else if (NoexceptInType) {
+ switch (EPI.ExceptionSpec.Type) {
+ case EST_Unparsed: case EST_Unevaluated: case EST_Uninstantiated:
+ // 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:
+ CanonicalEPI.ExceptionSpec.Type = EST_None;
+ break;
+
+ // A dynamic exception specification is almost always "not noexcept",
+ // with the exception that a pack expansion might expand to no types.
+ case EST_Dynamic: {
+ bool AnyPacks = false;
+ for (QualType ET : EPI.ExceptionSpec.Exceptions) {
+ if (ET->getAs<PackExpansionType>())
+ AnyPacks = true;
+ ExceptionTypeStorage.push_back(getCanonicalType(ET));
+ }
+ if (!AnyPacks)
+ CanonicalEPI.ExceptionSpec.Type = EST_None;
+ else {
+ CanonicalEPI.ExceptionSpec.Type = EST_Dynamic;
+ CanonicalEPI.ExceptionSpec.Exceptions = ExceptionTypeStorage;
+ }
+ break;
+ }
+
+ case EST_DynamicNone: case EST_BasicNoexcept:
+ 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;
+ }
+ } else {
+ CanonicalEPI.ExceptionSpec = FunctionProtoType::ExceptionSpecInfo();
+ }
// Adjust the canonical function result type.
CanQualType CanResultTy = getCanonicalFunctionResultType(ResultTy);
- Canonical = getFunctionType(CanResultTy, CanonicalArgs, CanonicalEPI);
+ Canonical =
+ getFunctionTypeInternal(CanResultTy, CanonicalArgs, CanonicalEPI, true);
// Get the new insert position for the node we care about.
FunctionProtoType *NewIP =
@@ -3121,14 +3344,14 @@ ASTContext::getFunctionType(QualType ResultTy, ArrayRef<QualType> ArgArray,
FunctionProtoType::ExtProtoInfo newEPI = EPI;
new (FTP) FunctionProtoType(ResultTy, ArgArray, Canonical, newEPI);
Types.push_back(FTP);
- FunctionProtoTypes.InsertNode(FTP, InsertPos);
+ if (!Unique)
+ FunctionProtoTypes.InsertNode(FTP, InsertPos);
return QualType(FTP, 0);
}
-/// Return pipe type for the specified type.
-QualType ASTContext::getPipeType(QualType T) const {
+QualType ASTContext::getPipeType(QualType T, bool ReadOnly) const {
llvm::FoldingSetNodeID ID;
- PipeType::Profile(ID, T);
+ PipeType::Profile(ID, T, ReadOnly);
void *InsertPos = 0;
if (PipeType *PT = PipeTypes.FindNodeOrInsertPos(ID, InsertPos))
@@ -3138,19 +3361,27 @@ QualType ASTContext::getPipeType(QualType T) const {
// either, so fill in the canonical type field.
QualType Canonical;
if (!T.isCanonical()) {
- Canonical = getPipeType(getCanonicalType(T));
+ Canonical = getPipeType(getCanonicalType(T), ReadOnly);
// Get the new insert position for the node we care about.
PipeType *NewIP = PipeTypes.FindNodeOrInsertPos(ID, InsertPos);
assert(!NewIP && "Shouldn't be in the map!");
(void)NewIP;
}
- PipeType *New = new (*this, TypeAlignment) PipeType(T, Canonical);
+ PipeType *New = new (*this, TypeAlignment) PipeType(T, Canonical, ReadOnly);
Types.push_back(New);
PipeTypes.InsertNode(New, InsertPos);
return QualType(New, 0);
}
+QualType ASTContext::getReadPipeType(QualType T) const {
+ return getPipeType(T, true);
+}
+
+QualType ASTContext::getWritePipeType(QualType T) const {
+ return getPipeType(T, false);
+}
+
#ifndef NDEBUG
static bool NeedsInjectedClassNameType(const RecordDecl *D) {
if (!isa<CXXRecordDecl>(D)) return false;
@@ -3641,6 +3872,44 @@ ASTContext::getDependentTemplateSpecializationType(
return QualType(T, 0);
}
+void
+ASTContext::getInjectedTemplateArgs(const TemplateParameterList *Params,
+ SmallVectorImpl<TemplateArgument> &Args) {
+ Args.reserve(Args.size() + Params->size());
+
+ for (NamedDecl *Param : *Params) {
+ TemplateArgument Arg;
+ if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) {
+ QualType ArgType = getTypeDeclType(TTP);
+ if (TTP->isParameterPack())
+ ArgType = getPackExpansionType(ArgType, None);
+
+ Arg = TemplateArgument(ArgType);
+ } else if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
+ Expr *E = new (*this) DeclRefExpr(
+ NTTP, /*enclosing*/false,
+ NTTP->getType().getNonLValueExprType(*this),
+ Expr::getValueKindForType(NTTP->getType()), NTTP->getLocation());
+
+ if (NTTP->isParameterPack())
+ E = new (*this) PackExpansionExpr(DependentTy, E, NTTP->getLocation(),
+ None);
+ Arg = TemplateArgument(E);
+ } else {
+ auto *TTP = cast<TemplateTemplateParmDecl>(Param);
+ if (TTP->isParameterPack())
+ Arg = TemplateArgument(TemplateName(TTP), Optional<unsigned>());
+ else
+ Arg = TemplateArgument(TemplateName(TTP));
+ }
+
+ if (Param->isTemplateParameterPack())
+ Arg = TemplateArgument::CreatePackCopy(*this, Arg);
+
+ Args.push_back(Arg);
+ }
+}
+
QualType ASTContext::getPackExpansionType(QualType Pattern,
Optional<unsigned> NumExpansions) {
llvm::FoldingSetNodeID ID;
@@ -3798,6 +4067,116 @@ QualType ASTContext::getObjCObjectType(
return QualType(T, 0);
}
+/// Apply Objective-C protocol qualifiers to the given type.
+/// If this is for the canonical type of a type parameter, we can apply
+/// protocol qualifiers on the ObjCObjectPointerType.
+QualType
+ASTContext::applyObjCProtocolQualifiers(QualType type,
+ ArrayRef<ObjCProtocolDecl *> protocols, bool &hasError,
+ bool allowOnPointerType) const {
+ hasError = false;
+
+ if (const ObjCTypeParamType *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())) {
+ const ObjCObjectType *objT = objPtr->getObjectType();
+ // Merge protocol lists and construct ObjCObjectType.
+ SmallVector<ObjCProtocolDecl*, 8> protocolsVec;
+ protocolsVec.append(objT->qual_begin(),
+ objT->qual_end());
+ protocolsVec.append(protocols.begin(), protocols.end());
+ ArrayRef<ObjCProtocolDecl *> protocols = protocolsVec;
+ type = getObjCObjectType(
+ objT->getBaseType(),
+ objT->getTypeArgsAsWritten(),
+ protocols,
+ objT->isKindOfTypeAsWritten());
+ return getObjCObjectPointerType(type);
+ }
+ }
+
+ // Apply protocol qualifiers to ObjCObjectType.
+ if (const ObjCObjectType *objT = dyn_cast<ObjCObjectType>(type.getTypePtr())){
+ // FIXME: Check for protocols to which the class type is already
+ // known to conform.
+
+ return getObjCObjectType(objT->getBaseType(),
+ objT->getTypeArgsAsWritten(),
+ protocols,
+ objT->isKindOfTypeAsWritten());
+ }
+
+ // If the canonical type is ObjCObjectType, ...
+ if (type->isObjCObjectType()) {
+ // Silently overwrite any existing protocol qualifiers.
+ // TODO: determine whether that's the right thing to do.
+
+ // FIXME: Check for protocols to which the class type is already
+ // known to conform.
+ return getObjCObjectType(type, { }, protocols, false);
+ }
+
+ // id<protocol-list>
+ if (type->isObjCIdType()) {
+ const ObjCObjectPointerType *objPtr = type->castAs<ObjCObjectPointerType>();
+ type = getObjCObjectType(ObjCBuiltinIdTy, { }, protocols,
+ objPtr->isKindOfType());
+ return getObjCObjectPointerType(type);
+ }
+
+ // Class<protocol-list>
+ if (type->isObjCClassType()) {
+ const ObjCObjectPointerType *objPtr = type->castAs<ObjCObjectPointerType>();
+ type = getObjCObjectType(ObjCBuiltinClassTy, { }, protocols,
+ objPtr->isKindOfType());
+ return getObjCObjectPointerType(type);
+ }
+
+ hasError = true;
+ return type;
+}
+
+QualType
+ASTContext::getObjCTypeParamType(const ObjCTypeParamDecl *Decl,
+ ArrayRef<ObjCProtocolDecl *> protocols,
+ QualType Canonical) const {
+ // Look in the folding set for an existing type.
+ llvm::FoldingSetNodeID ID;
+ ObjCTypeParamType::Profile(ID, Decl, protocols);
+ void *InsertPos = nullptr;
+ if (ObjCTypeParamType *TypeParam =
+ ObjCTypeParamTypes.FindNodeOrInsertPos(ID, InsertPos))
+ return QualType(TypeParam, 0);
+
+ if (Canonical.isNull()) {
+ // We canonicalize to the underlying type.
+ Canonical = getCanonicalType(Decl->getUnderlyingType());
+ if (!protocols.empty()) {
+ // Apply the protocol qualifers.
+ bool hasError;
+ Canonical = applyObjCProtocolQualifiers(Canonical, protocols, hasError,
+ true/*allowOnPointerType*/);
+ assert(!hasError && "Error when apply protocol qualifier to bound type");
+ }
+ }
+
+ unsigned size = sizeof(ObjCTypeParamType);
+ size += protocols.size() * sizeof(ObjCProtocolDecl *);
+ void *mem = Allocate(size, TypeAlignment);
+ ObjCTypeParamType *newType = new (mem)
+ ObjCTypeParamType(Decl, Canonical, protocols);
+
+ Types.push_back(newType);
+ ObjCTypeParamTypes.InsertNode(newType, InsertPos);
+ return QualType(newType, 0);
+}
+
/// ObjCObjectAdoptsQTypeProtocols - Checks that protocols in IC's
/// protocol list adopt all protocols in QT's qualified-id protocol
/// list.
@@ -3983,7 +4362,7 @@ QualType ASTContext::getDecltypeType(Expr *e, QualType UnderlyingType) const {
DependentDecltypeType *Canon
= DependentDecltypeTypes.FindNodeOrInsertPos(ID, InsertPos);
if (!Canon) {
- // Build a new, canonical typeof(expr) type.
+ // Build a new, canonical decltype(expr) type.
Canon = new (*this, TypeAlignment) DependentDecltypeType(*this, e);
DependentDecltypeTypes.InsertNode(Canon, InsertPos);
}
@@ -4590,7 +4969,15 @@ QualType ASTContext::getArrayDecayedType(QualType Ty) const {
QualType PtrTy = getPointerType(PrettyArrayType->getElementType());
// int x[restrict 4] -> int *restrict
- return getQualifiedType(PtrTy, PrettyArrayType->getIndexTypeQualifiers());
+ QualType Result = getQualifiedType(PtrTy,
+ PrettyArrayType->getIndexTypeQualifiers());
+
+ // int x[_Nullable] -> int * _Nullable
+ if (auto Nullability = Ty->getNullability(*this)) {
+ Result = const_cast<ASTContext *>(this)->getAttributedType(
+ AttributedType::getNullabilityAttrKind(*Nullability), Result, Result);
+ }
+ return Result;
}
QualType ASTContext::getBaseElementType(const ArrayType *array) const {
@@ -5223,8 +5610,9 @@ std::string ASTContext::getObjCEncodingForBlock(const BlockExpr *Expr) const {
return S;
}
-bool ASTContext::getObjCEncodingForFunctionDecl(const FunctionDecl *Decl,
- std::string& S) {
+std::string
+ASTContext::getObjCEncodingForFunctionDecl(const FunctionDecl *Decl) const {
+ std::string S;
// Encode result type.
getObjCEncodingForType(Decl->getReturnType(), S);
CharUnits ParmOffset;
@@ -5235,8 +5623,8 @@ bool ASTContext::getObjCEncodingForFunctionDecl(const FunctionDecl *Decl,
if (sz.isZero())
continue;
- assert (sz.isPositive() &&
- "getObjCEncodingForFunctionDecl - Incomplete param type");
+ assert(sz.isPositive() &&
+ "getObjCEncodingForFunctionDecl - Incomplete param type");
ParmOffset += sz;
}
S += charUnitsToString(ParmOffset);
@@ -5258,7 +5646,7 @@ bool ASTContext::getObjCEncodingForFunctionDecl(const FunctionDecl *Decl,
ParmOffset += getObjCEncodingTypeSize(PType);
}
- return false;
+ return S;
}
/// getObjCEncodingForMethodParameter - Return the encoded type for a single
@@ -5280,11 +5668,11 @@ void ASTContext::getObjCEncodingForMethodParameter(Decl::ObjCDeclQualifier QT,
/// getObjCEncodingForMethodDecl - Return the encoded type for this method
/// declaration.
-bool ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl,
- std::string& S,
- bool Extended) const {
+std::string ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl,
+ bool Extended) const {
// FIXME: This is not very efficient.
// Encode return type.
+ std::string S;
getObjCEncodingForMethodParameter(Decl->getObjCDeclQualifier(),
Decl->getReturnType(), S, Extended);
// Compute size of all parameters.
@@ -5330,7 +5718,7 @@ bool ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl,
ParmOffset += getObjCEncodingTypeSize(PType);
}
- return false;
+ return S;
}
ObjCPropertyImplDecl *
@@ -5378,9 +5766,9 @@ ASTContext::getObjCPropertyImplDeclForPropertyDecl(
/// kPropertyNonAtomic = 'N' // property non-atomic
/// };
/// @endcode
-void ASTContext::getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD,
- const Decl *Container,
- std::string& S) const {
+std::string
+ASTContext::getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD,
+ const Decl *Container) const {
// Collect information from the property implementation decl(s).
bool Dynamic = false;
ObjCPropertyImplDecl *SynthesizePID = nullptr;
@@ -5394,7 +5782,7 @@ void ASTContext::getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD,
}
// FIXME: This is not very efficient.
- S = "T";
+ std::string S = "T";
// Encode result type.
// GCC has some special rules regarding encoding of properties which
@@ -5443,6 +5831,7 @@ void ASTContext::getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD,
}
// FIXME: OBJCGC: weak & strong
+ return S;
}
/// getLegacyIntegralTypeEncoding -
@@ -5833,18 +6222,20 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
ObjCInterfaceDecl *OI = T->castAs<ObjCObjectType>()->getInterface();
S += '{';
S += OI->getObjCRuntimeNameAsString();
- 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]);
- if (Field->isBitField())
- getObjCEncodingForTypeImpl(Field->getType(), S, false, true, Field);
- else
- getObjCEncodingForTypeImpl(Field->getType(), S, false, true, FD,
- false, false, false, false, false,
- EncodePointerToObjCTypedef,
- NotEncodedT);
+ if (ExpandStructures) {
+ 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]);
+ if (Field->isBitField())
+ getObjCEncodingForTypeImpl(Field->getType(), S, false, true, Field);
+ else
+ getObjCEncodingForTypeImpl(Field->getType(), S, false, true, FD,
+ false, false, false, false, false,
+ EncodePointerToObjCTypedef,
+ NotEncodedT);
+ }
}
S += '}';
return;
@@ -6369,9 +6760,8 @@ CreateX86_64ABIBuiltinVaListDecl(const ASTContext *Context) {
static TypedefDecl *CreatePNaClABIBuiltinVaListDecl(const ASTContext *Context) {
// typedef int __builtin_va_list[4];
llvm::APInt Size(Context->getTypeSize(Context->getSizeType()), 4);
- QualType IntArrayType
- = Context->getConstantArrayType(Context->IntTy,
- Size, ArrayType::Normal, 0);
+ QualType IntArrayType =
+ Context->getConstantArrayType(Context->IntTy, Size, ArrayType::Normal, 0);
return Context->buildImplicitTypedef(IntArrayType, "__builtin_va_list");
}
@@ -6567,7 +6957,7 @@ ASTContext::getQualifiedTemplateName(NestedNameSpecifier *NNS,
QualifiedTemplateName *QTN =
QualifiedTemplateNames.FindNodeOrInsertPos(ID, InsertPos);
if (!QTN) {
- QTN = new (*this, llvm::alignOf<QualifiedTemplateName>())
+ QTN = new (*this, alignof(QualifiedTemplateName))
QualifiedTemplateName(NNS, TemplateKeyword, Template);
QualifiedTemplateNames.InsertNode(QTN, InsertPos);
}
@@ -6595,11 +6985,11 @@ ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS,
NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS);
if (CanonNNS == NNS) {
- QTN = new (*this, llvm::alignOf<DependentTemplateName>())
+ QTN = new (*this, alignof(DependentTemplateName))
DependentTemplateName(NNS, Name);
} else {
TemplateName Canon = getDependentTemplateName(CanonNNS, Name);
- QTN = new (*this, llvm::alignOf<DependentTemplateName>())
+ QTN = new (*this, alignof(DependentTemplateName))
DependentTemplateName(NNS, Name, Canon);
DependentTemplateName *CheckQTN =
DependentTemplateNames.FindNodeOrInsertPos(ID, InsertPos);
@@ -6631,13 +7021,13 @@ ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS,
NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS);
if (CanonNNS == NNS) {
- QTN = new (*this, llvm::alignOf<DependentTemplateName>())
+ QTN = new (*this, alignof(DependentTemplateName))
DependentTemplateName(NNS, Operator);
} else {
TemplateName Canon = getDependentTemplateName(CanonNNS, Operator);
- QTN = new (*this, llvm::alignOf<DependentTemplateName>())
+ QTN = new (*this, alignof(DependentTemplateName))
DependentTemplateName(NNS, Operator, Canon);
-
+
DependentTemplateName *CheckQTN
= DependentTemplateNames.FindNodeOrInsertPos(ID, InsertPos);
assert(!CheckQTN && "Dependent template name canonicalization broken");
@@ -7388,7 +7778,7 @@ bool ASTContext::typesAreCompatible(QualType LHS, QualType RHS,
bool CompareUnqualified) {
if (getLangOpts().CPlusPlus)
return hasSameType(LHS, RHS);
-
+
return !mergeTypes(LHS, RHS, false, CompareUnqualified).isNull();
}
@@ -7902,21 +8292,9 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
}
case Type::Pipe:
{
- // Merge two pointer types, while trying to preserve typedef info
- QualType LHSValue = LHS->getAs<PipeType>()->getElementType();
- QualType RHSValue = RHS->getAs<PipeType>()->getElementType();
- if (Unqualified) {
- LHSValue = LHSValue.getUnqualifiedType();
- RHSValue = RHSValue.getUnqualifiedType();
- }
- QualType ResultType = mergeTypes(LHSValue, RHSValue, false,
- Unqualified);
- if (ResultType.isNull()) return QualType();
- if (getCanonicalType(LHSValue) == getCanonicalType(ResultType))
- return LHS;
- if (getCanonicalType(RHSValue) == getCanonicalType(ResultType))
- return RHS;
- return getPipeType(ResultType);
+ assert(LHS != RHS &&
+ "Equivalent pipe types should have already been handled!");
+ return QualType();
}
}
@@ -8197,6 +8575,10 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context,
assert(HowLong == 0 && !Signed && !Unsigned && "Bad modifiers for 'z'!");
Type = Context.getSizeType();
break;
+ case 'w': // wchar_t.
+ assert(HowLong == 0 && !Signed && !Unsigned && "Bad modifiers for 'w'!");
+ Type = Context.getWideCharType();
+ break;
case 'F':
Type = Context.getCFConstantStringType();
break;
@@ -8385,13 +8767,16 @@ QualType ASTContext::GetBuiltinType(unsigned Id,
bool Variadic = (TypeStr[0] == '.');
- // We really shouldn't be making a no-proto type here, especially in C++.
- if (ArgTypes.empty() && Variadic)
+ // We really shouldn't be making a no-proto type here.
+ if (ArgTypes.empty() && Variadic && !getLangOpts().CPlusPlus)
return getFunctionNoProtoType(ResType, EI);
FunctionProtoType::ExtProtoInfo EPI;
EPI.ExtInfo = EI;
EPI.Variadic = Variadic;
+ if (getLangOpts().CPlusPlus && BuiltinInfo.isNoThrow(Id))
+ EPI.ExceptionSpec.Type =
+ getLangOpts().CPlusPlus11 ? EST_BasicNoexcept : EST_DynamicNone;
return getFunctionType(ResType, ArgTypes, EPI);
}
@@ -8576,6 +8961,8 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
return !D->getDeclContext()->isDependentContext();
else if (isa<OMPDeclareReductionDecl>(D))
return !D->getDeclContext()->isDependentContext();
+ else if (isa<ImportDecl>(D))
+ return true;
else
return false;
@@ -8613,15 +9000,10 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
}
}
- GVALinkage Linkage = GetGVALinkageForFunction(FD);
-
// static, static inline, always_inline, and extern inline functions can
// always be deferred. Normal inline functions can be deferred in C99/C++.
// Implicit template instantiations can also be deferred in C++.
- if (Linkage == GVA_Internal || Linkage == GVA_AvailableExternally ||
- Linkage == GVA_DiscardableODR)
- return false;
- return true;
+ return !isDiscardableGVALinkage(GetGVALinkageForFunction(FD));
}
const VarDecl *VD = cast<VarDecl>(D);
@@ -8632,9 +9014,7 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
return false;
// Variables that can be needed in other TUs are required.
- GVALinkage L = GetGVALinkageForVariable(VD);
- if (L != GVA_Internal && L != GVA_AvailableExternally &&
- L != GVA_DiscardableODR)
+ if (!isDiscardableGVALinkage(GetGVALinkageForVariable(VD)))
return true;
// Variables that have destruction with side-effects are required.
@@ -8646,6 +9026,14 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
!VD->evaluateValue())
return true;
+ // 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 (DeclMustBeEmitted(BindingVD))
+ return true;
+
return false;
}
@@ -8785,13 +9173,14 @@ unsigned ASTContext::getStaticLocalNumber(const VarDecl *VD) const {
MangleNumberingContext &
ASTContext::getManglingNumberContext(const DeclContext *DC) {
assert(LangOpts.CPlusPlus); // We don't need mangling numbers for plain C.
- MangleNumberingContext *&MCtx = MangleNumberingContexts[DC];
+ std::unique_ptr<MangleNumberingContext> &MCtx = MangleNumberingContexts[DC];
if (!MCtx)
MCtx = createMangleNumberingContext();
return *MCtx;
}
-MangleNumberingContext *ASTContext::createMangleNumberingContext() const {
+std::unique_ptr<MangleNumberingContext>
+ASTContext::createMangleNumberingContext() const {
return ABI->createMangleNumberingContext();
}
@@ -8808,18 +9197,6 @@ void ASTContext::addCopyConstructorForExceptionObject(CXXRecordDecl *RD,
cast<CXXConstructorDecl>(CD->getFirstDecl()));
}
-void ASTContext::addDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
- unsigned ParmIdx, Expr *DAE) {
- ABI->addDefaultArgExprForConstructor(
- cast<CXXConstructorDecl>(CD->getFirstDecl()), ParmIdx, DAE);
-}
-
-Expr *ASTContext::getDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
- unsigned ParmIdx) {
- return ABI->getDefaultArgExprForConstructor(
- cast<CXXConstructorDecl>(CD->getFirstDecl()), ParmIdx);
-}
-
void ASTContext::addTypedefNameForUnnamedTagDecl(TagDecl *TD,
TypedefNameDecl *DD) {
return ABI->addTypedefNameForUnnamedTagDecl(TD, DD);
@@ -9098,6 +9475,16 @@ ASTContext::ObjCMethodsAreEqual(const ObjCMethodDecl *MethodDecl,
}
+uint64_t ASTContext::getTargetNullPointerValue(QualType QT) const {
+ unsigned AS;
+ if (QT->getUnqualifiedDesugaredType()->isNullPtrType())
+ AS = 0;
+ else
+ AS = QT->getPointeeType().getAddressSpace();
+
+ return getTargetInfo().getNullPointerValue(AS);
+}
+
// Explicitly instantiate this in case a Redeclarable<T> is used from a TU that
// doesn't include ASTContext.h
template
diff --git a/lib/AST/ASTDiagnostic.cpp b/lib/AST/ASTDiagnostic.cpp
index 0f5a8b5ae892..03e6115a0dba 100644
--- a/lib/AST/ASTDiagnostic.cpp
+++ b/lib/AST/ASTDiagnostic.cpp
@@ -20,7 +20,6 @@
#include "clang/AST/ExprCXX.h"
#include "clang/AST/TemplateBase.h"
#include "clang/AST/Type.h"
-#include "llvm/ADT/SmallString.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
@@ -937,6 +936,9 @@ class TemplateDiff {
++(*this);
}
+ /// Return true if the iterator is non-singular.
+ bool isValid() const { return TST; }
+
/// isEnd - Returns true if the iterator is one past the end.
bool isEnd() const {
assert(TST && "InternalIterator is invalid with a null TST.");
@@ -996,21 +998,21 @@ class TemplateDiff {
}
};
- bool UseDesugaredIterator;
InternalIterator SugaredIterator;
InternalIterator DesugaredIterator;
public:
TSTiterator(ASTContext &Context, const TemplateSpecializationType *TST)
- : UseDesugaredIterator(TST->isSugared() && !TST->isTypeAlias()),
- SugaredIterator(TST),
+ : SugaredIterator(TST),
DesugaredIterator(
- GetTemplateSpecializationType(Context, TST->desugar())) {}
+ (TST->isSugared() && !TST->isTypeAlias())
+ ? GetTemplateSpecializationType(Context, TST->desugar())
+ : nullptr) {}
/// &operator++ - Increment the iterator to the next template argument.
TSTiterator &operator++() {
++SugaredIterator;
- if (UseDesugaredIterator)
+ if (DesugaredIterator.isValid())
++DesugaredIterator;
return *this;
}
@@ -1033,12 +1035,12 @@ class TemplateDiff {
/// hasDesugaredTA - Returns true if there is another TemplateArgument
/// available.
bool hasDesugaredTA() const {
- return UseDesugaredIterator && !DesugaredIterator.isEnd();
+ return DesugaredIterator.isValid() && !DesugaredIterator.isEnd();
}
/// getDesugaredTA - Returns the desugared TemplateArgument.
reference getDesugaredTA() const {
- assert(UseDesugaredIterator &&
+ assert(DesugaredIterator.isValid() &&
"Desugared TemplateArgument should not be used.");
return *DesugaredIterator;
}
diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp
index 872ba356a9b2..62261ccc905b 100644
--- a/lib/AST/ASTDumper.cpp
+++ b/lib/AST/ASTDumper.cpp
@@ -428,6 +428,8 @@ namespace {
void VisitFunctionDecl(const FunctionDecl *D);
void VisitFieldDecl(const FieldDecl *D);
void VisitVarDecl(const VarDecl *D);
+ void VisitDecompositionDecl(const DecompositionDecl *D);
+ void VisitBindingDecl(const BindingDecl *D);
void VisitFileScopeAsmDecl(const FileScopeAsmDecl *D);
void VisitImportDecl(const ImportDecl *D);
void VisitPragmaCommentDecl(const PragmaCommentDecl *D);
@@ -515,6 +517,8 @@ namespace {
void VisitFloatingLiteral(const FloatingLiteral *Node);
void VisitStringLiteral(const StringLiteral *Str);
void VisitInitListExpr(const InitListExpr *ILE);
+ void VisitArrayInitLoopExpr(const ArrayInitLoopExpr *ILE);
+ void VisitArrayInitIndexExpr(const ArrayInitIndexExpr *ILE);
void VisitUnaryOperator(const UnaryOperator *Node);
void VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Node);
void VisitMemberExpr(const MemberExpr *Node);
@@ -543,6 +547,8 @@ namespace {
dumpDecl(Node->getLambdaClass());
}
void VisitSizeOfPackExpr(const SizeOfPackExpr *Node);
+ void
+ VisitCXXDependentScopeMemberExpr(const CXXDependentScopeMemberExpr *Node);
// ObjC
void VisitObjCAtCatchStmt(const ObjCAtCatchStmt *Node);
@@ -1133,8 +1139,15 @@ void ASTDumper::VisitFunctionDecl(const FunctionDecl *D) {
if (D->isPure())
OS << " pure";
- else if (D->isDeletedAsWritten())
+ if (D->isDefaulted()) {
+ OS << " default";
+ if (D->isDeleted())
+ OS << "_delete";
+ }
+ if (D->isDeletedAsWritten())
OS << " delete";
+ if (D->isTrivial())
+ OS << " trivial";
if (const FunctionProtoType *FPT = D->getType()->getAs<FunctionProtoType>()) {
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
@@ -1153,11 +1166,6 @@ void ASTDumper::VisitFunctionDecl(const FunctionDecl *D) {
D->getTemplateSpecializationInfo())
dumpTemplateArgumentList(*FTSI->TemplateArguments);
- for (ArrayRef<NamedDecl *>::iterator
- I = D->getDeclsInPrototypeScope().begin(),
- E = D->getDeclsInPrototypeScope().end(); I != E; ++I)
- dumpDecl(*I);
-
if (!D->param_begin() && D->getNumParams())
dumpChild([=] { OS << "<<NULL params x " << D->getNumParams() << ">>"; });
else
@@ -1217,6 +1225,19 @@ void ASTDumper::VisitVarDecl(const VarDecl *D) {
}
}
+void ASTDumper::VisitDecompositionDecl(const DecompositionDecl *D) {
+ VisitVarDecl(D);
+ for (auto *B : D->bindings())
+ dumpDecl(B);
+}
+
+void ASTDumper::VisitBindingDecl(const BindingDecl *D) {
+ dumpName(D);
+ dumpType(D->getType());
+ if (auto *E = D->getBinding())
+ dumpStmt(E);
+}
+
void ASTDumper::VisitFileScopeAsmDecl(const FileScopeAsmDecl *D) {
dumpStmt(D->getAsmString());
}
@@ -2005,6 +2026,14 @@ void ASTDumper::VisitInitListExpr(const InitListExpr *ILE) {
}
}
+void ASTDumper::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E) {
+ VisitExpr(E);
+}
+
+void ASTDumper::VisitArrayInitIndexExpr(const ArrayInitIndexExpr *E) {
+ VisitExpr(E);
+}
+
void ASTDumper::VisitUnaryOperator(const UnaryOperator *Node) {
VisitExpr(Node);
OS << " " << (Node->isPostfix() ? "postfix" : "prefix")
@@ -2179,6 +2208,11 @@ void ASTDumper::VisitSizeOfPackExpr(const SizeOfPackExpr *Node) {
dumpTemplateArgument(A);
}
+void ASTDumper::VisitCXXDependentScopeMemberExpr(
+ const CXXDependentScopeMemberExpr *Node) {
+ VisitExpr(Node);
+ OS << " " << (Node->isArrow() ? "->" : ".") << Node->getMember();
+}
//===----------------------------------------------------------------------===//
// Obj-C Expressions
@@ -2451,12 +2485,18 @@ void QualType::dump(const char *msg) const {
dump();
}
-LLVM_DUMP_METHOD void QualType::dump() const {
- ASTDumper Dumper(llvm::errs(), nullptr, nullptr);
+LLVM_DUMP_METHOD void QualType::dump() const { dump(llvm::errs()); }
+
+LLVM_DUMP_METHOD void QualType::dump(llvm::raw_ostream &OS) const {
+ ASTDumper Dumper(OS, nullptr, nullptr);
Dumper.dumpTypeAsChild(*this);
}
-LLVM_DUMP_METHOD void Type::dump() const { QualType(this, 0).dump(); }
+LLVM_DUMP_METHOD void Type::dump() const { dump(llvm::errs()); }
+
+LLVM_DUMP_METHOD void Type::dump(llvm::raw_ostream &OS) const {
+ QualType(this, 0).dump(OS);
+}
//===----------------------------------------------------------------------===//
// Decl method implementations
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index bc1f9f96a06b..67e96ea828bd 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -39,7 +39,9 @@ namespace clang {
// Importing types
QualType VisitType(const Type *T);
+ QualType VisitAtomicType(const AtomicType *T);
QualType VisitBuiltinType(const BuiltinType *T);
+ QualType VisitDecayedType(const DecayedType *T);
QualType VisitComplexType(const ComplexType *T);
QualType VisitPointerType(const PointerType *T);
QualType VisitBlockPointerType(const BlockPointerType *T);
@@ -88,6 +90,8 @@ namespace clang {
DeclarationNameInfo& To);
void ImportDeclContext(DeclContext *FromDC, bool ForceImport = false);
+ bool ImportCastPath(CastExpr *E, CXXCastPath &Path);
+
typedef DesignatedInitExpr::Designator Designator;
Designator ImportDesignator(const Designator &D);
@@ -123,6 +127,8 @@ namespace clang {
TemplateParameterList *ImportTemplateParameterList(
TemplateParameterList *Params);
TemplateArgument ImportTemplateArgument(const TemplateArgument &From);
+ TemplateArgumentLoc ImportTemplateArgumentLoc(
+ const TemplateArgumentLoc &TALoc, bool &Error);
bool ImportTemplateArguments(const TemplateArgument *FromArgs,
unsigned NumFromArgs,
SmallVectorImpl<TemplateArgument> &ToArgs);
@@ -136,6 +142,7 @@ namespace clang {
bool IsStructuralMatch(VarTemplateDecl *From, VarTemplateDecl *To);
Decl *VisitDecl(Decl *D);
Decl *VisitAccessSpecDecl(AccessSpecDecl *D);
+ Decl *VisitStaticAssertDecl(StaticAssertDecl *D);
Decl *VisitTranslationUnitDecl(TranslationUnitDecl *D);
Decl *VisitNamespaceDecl(NamespaceDecl *D);
Decl *VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias);
@@ -152,6 +159,7 @@ namespace clang {
Decl *VisitCXXConversionDecl(CXXConversionDecl *D);
Decl *VisitFieldDecl(FieldDecl *D);
Decl *VisitIndirectFieldDecl(IndirectFieldDecl *D);
+ Decl *VisitFriendDecl(FriendDecl *D);
Decl *VisitObjCIvarDecl(ObjCIvarDecl *D);
Decl *VisitVarDecl(VarDecl *D);
Decl *VisitImplicitParamDecl(ImplicitParamDecl *D);
@@ -242,16 +250,32 @@ namespace clang {
Expr *VisitConditionalOperator(ConditionalOperator *E);
Expr *VisitBinaryConditionalOperator(BinaryConditionalOperator *E);
Expr *VisitOpaqueValueExpr(OpaqueValueExpr *E);
+ Expr *VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E);
+ Expr *VisitExpressionTraitExpr(ExpressionTraitExpr *E);
+ Expr *VisitArraySubscriptExpr(ArraySubscriptExpr *E);
Expr *VisitCompoundAssignOperator(CompoundAssignOperator *E);
Expr *VisitImplicitCastExpr(ImplicitCastExpr *E);
- Expr *VisitCStyleCastExpr(CStyleCastExpr *E);
+ Expr *VisitExplicitCastExpr(ExplicitCastExpr *E);
+ Expr *VisitOffsetOfExpr(OffsetOfExpr *OE);
+ Expr *VisitCXXThrowExpr(CXXThrowExpr *E);
+ Expr *VisitCXXNoexceptExpr(CXXNoexceptExpr *E);
+ Expr *VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E);
+ Expr *VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E);
+ Expr *VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E);
+ Expr *VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *CE);
+ Expr *VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E);
+ Expr *VisitCXXNewExpr(CXXNewExpr *CE);
+ Expr *VisitCXXDeleteExpr(CXXDeleteExpr *E);
Expr *VisitCXXConstructExpr(CXXConstructExpr *E);
Expr *VisitCXXMemberCallExpr(CXXMemberCallExpr *E);
+ Expr *VisitExprWithCleanups(ExprWithCleanups *EWC);
Expr *VisitCXXThisExpr(CXXThisExpr *E);
Expr *VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E);
Expr *VisitMemberExpr(MemberExpr *E);
Expr *VisitCallExpr(CallExpr *E);
Expr *VisitInitListExpr(InitListExpr *E);
+ Expr *VisitArrayInitLoopExpr(ArrayInitLoopExpr *E);
+ Expr *VisitArrayInitIndexExpr(ArrayInitIndexExpr *E);
Expr *VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E);
Expr *VisitCXXNamedCastExpr(CXXNamedCastExpr *E);
@@ -272,13 +296,26 @@ namespace clang {
bool Failed = false;
std::transform(Ibegin, Iend, Obegin,
[&ImporterRef, &Failed](ItemT *From) -> ItemT * {
- ItemT *To = ImporterRef.Import(From);
+ ItemT *To = cast_or_null<ItemT>(
+ ImporterRef.Import(From));
if (!To && From)
Failed = true;
return To;
});
return Failed;
}
+
+ template<typename InContainerTy, typename OutContainerTy>
+ bool ImportContainerChecked(const InContainerTy &InContainer,
+ OutContainerTy &OutContainer) {
+ return ImportArrayChecked(InContainer.begin(), InContainer.end(),
+ OutContainer.begin());
+ }
+
+ template<typename InContainerTy, typename OIter>
+ bool ImportArrayChecked(const InContainerTy &InContainer, OIter Obegin) {
+ return ImportArrayChecked(InContainer.begin(), InContainer.end(), Obegin);
+ }
};
}
@@ -897,6 +934,23 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
break;
}
+ case Type::ObjCTypeParam: {
+ const ObjCTypeParamType *Obj1 = cast<ObjCTypeParamType>(T1);
+ const ObjCTypeParamType *Obj2 = cast<ObjCTypeParamType>(T2);
+ if (!IsStructurallyEquivalent(Context, Obj1->getDecl(),
+ Obj2->getDecl()))
+ return false;
+
+ if (Obj1->getNumProtocols() != Obj2->getNumProtocols())
+ return false;
+ for (unsigned I = 0, N = Obj1->getNumProtocols(); I != N; ++I) {
+ if (!IsStructurallyEquivalent(Context,
+ Obj1->getProtocol(I),
+ Obj2->getProtocol(I)))
+ return false;
+ }
+ break;
+ }
case Type::ObjCObject: {
const ObjCObjectType *Obj1 = cast<ObjCObjectType>(T1);
const ObjCObjectType *Obj2 = cast<ObjCObjectType>(T2);
@@ -1549,6 +1603,14 @@ QualType ASTNodeImporter::VisitType(const Type *T) {
return QualType();
}
+QualType ASTNodeImporter::VisitAtomicType(const AtomicType *T){
+ QualType UnderlyingType = Importer.Import(T->getValueType());
+ if(UnderlyingType.isNull())
+ return QualType();
+
+ return Importer.getToContext().getAtomicType(UnderlyingType);
+}
+
QualType ASTNodeImporter::VisitBuiltinType(const BuiltinType *T) {
switch (T->getKind()) {
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
@@ -1594,6 +1656,14 @@ QualType ASTNodeImporter::VisitBuiltinType(const BuiltinType *T) {
llvm_unreachable("Invalid BuiltinType Kind!");
}
+QualType ASTNodeImporter::VisitDecayedType(const DecayedType *T) {
+ QualType OrigT = Importer.Import(T->getOriginalType());
+ if (OrigT.isNull())
+ return QualType();
+
+ return Importer.getToContext().getDecayedType(OrigT);
+}
+
QualType ASTNodeImporter::VisitComplexType(const ComplexType *T) {
QualType ToElementType = Importer.Import(T->getElementType());
if (ToElementType.isNull())
@@ -2250,23 +2320,25 @@ bool ASTNodeImporter::ImportDefinition(EnumDecl *From, EnumDecl *To,
TemplateParameterList *ASTNodeImporter::ImportTemplateParameterList(
TemplateParameterList *Params) {
- SmallVector<NamedDecl *, 4> ToParams;
- ToParams.reserve(Params->size());
- for (TemplateParameterList::iterator P = Params->begin(),
- PEnd = Params->end();
- P != PEnd; ++P) {
- Decl *To = Importer.Import(*P);
- if (!To)
+ SmallVector<NamedDecl *, 4> ToParams(Params->size());
+ if (ImportContainerChecked(*Params, ToParams))
+ return nullptr;
+
+ Expr *ToRequiresClause;
+ if (Expr *const R = Params->getRequiresClause()) {
+ ToRequiresClause = Importer.Import(R);
+ if (!ToRequiresClause)
return nullptr;
-
- ToParams.push_back(cast<NamedDecl>(To));
+ } else {
+ ToRequiresClause = nullptr;
}
-
+
return TemplateParameterList::Create(Importer.getToContext(),
Importer.Import(Params->getTemplateLoc()),
Importer.Import(Params->getLAngleLoc()),
ToParams,
- Importer.Import(Params->getRAngleLoc()));
+ Importer.Import(Params->getRAngleLoc()),
+ ToRequiresClause);
}
TemplateArgument
@@ -2340,6 +2412,31 @@ ASTNodeImporter::ImportTemplateArgument(const TemplateArgument &From) {
llvm_unreachable("Invalid template argument kind");
}
+TemplateArgumentLoc ASTNodeImporter::ImportTemplateArgumentLoc(
+ const TemplateArgumentLoc &TALoc, bool &Error) {
+ Error = false;
+ TemplateArgument Arg = ImportTemplateArgument(TALoc.getArgument());
+ TemplateArgumentLocInfo FromInfo = TALoc.getLocInfo();
+ TemplateArgumentLocInfo ToInfo;
+ if (Arg.getKind() == TemplateArgument::Expression) {
+ Expr *E = Importer.Import(FromInfo.getAsExpr());
+ ToInfo = TemplateArgumentLocInfo(E);
+ if (!E)
+ Error = true;
+ } else if (Arg.getKind() == TemplateArgument::Type) {
+ if (TypeSourceInfo *TSI = Importer.Import(FromInfo.getAsTypeSourceInfo()))
+ ToInfo = TemplateArgumentLocInfo(TSI);
+ else
+ Error = true;
+ } else {
+ ToInfo = TemplateArgumentLocInfo(
+ Importer.Import(FromInfo.getTemplateQualifierLoc()),
+ Importer.Import(FromInfo.getTemplateNameLoc()),
+ Importer.Import(FromInfo.getTemplateEllipsisLoc()));
+ }
+ return TemplateArgumentLoc(Arg, ToInfo);
+}
+
bool ASTNodeImporter::ImportTemplateArguments(const TemplateArgument *FromArgs,
unsigned NumFromArgs,
SmallVectorImpl<TemplateArgument> &ToArgs) {
@@ -2454,6 +2551,35 @@ Decl *ASTNodeImporter::VisitAccessSpecDecl(AccessSpecDecl *D) {
return accessSpecDecl;
}
+Decl *ASTNodeImporter::VisitStaticAssertDecl(StaticAssertDecl *D) {
+ DeclContext *DC = Importer.ImportContext(D->getDeclContext());
+ if (!DC)
+ return nullptr;
+
+ DeclContext *LexicalDC = DC;
+
+ // Import the location of this declaration.
+ SourceLocation Loc = Importer.Import(D->getLocation());
+
+ Expr *AssertExpr = Importer.Import(D->getAssertExpr());
+ if (!AssertExpr)
+ return nullptr;
+
+ StringLiteral *FromMsg = D->getMessage();
+ StringLiteral *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());
+
+ ToD->setLexicalDeclContext(LexicalDC);
+ LexicalDC->addDeclInternal(ToD);
+ Importer.Imported(D, ToD);
+ return ToD;
+}
+
Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) {
// Import the major distinguishing characteristics of this namespace.
DeclContext *DC, *LexicalDC;
@@ -3303,6 +3429,70 @@ Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) {
return ToIndirectField;
}
+Decl *ASTNodeImporter::VisitFriendDecl(FriendDecl *D) {
+ // Import the major distinguishing characteristics of a declaration.
+ DeclContext *DC = Importer.ImportContext(D->getDeclContext());
+ DeclContext *LexicalDC = D->getDeclContext() == D->getLexicalDeclContext()
+ ? DC : Importer.ImportContext(D->getLexicalDeclContext());
+ if (!DC || !LexicalDC)
+ return nullptr;
+
+ // Determine whether we've already imported this decl.
+ // 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);
+
+ } else if (D->getFriendType() && ImportedFriend->getFriendType()) {
+ if (Importer.IsStructurallyEquivalent(
+ D->getFriendType()->getType(),
+ ImportedFriend->getFriendType()->getType(), true))
+ return Importer.Imported(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
+ ToFU = Importer.Import(D->getFriendType());
+ if (!ToFU)
+ return nullptr;
+
+ SmallVector<TemplateParameterList *, 1> ToTPLists(D->NumTPLists);
+ TemplateParameterList **FromTPLists =
+ D->getTrailingObjects<TemplateParameterList *>();
+ for (unsigned I = 0; I < D->NumTPLists; I++) {
+ TemplateParameterList *List = ImportTemplateParameterList(FromTPLists[I]);
+ if (!List)
+ return nullptr;
+ 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);
+
+ FrD->setAccess(D->getAccess());
+ FrD->setLexicalDeclContext(LexicalDC);
+ LexicalDC->addDeclInternal(FrD);
+ return FrD;
+}
+
Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) {
// Import the major distinguishing characteristics of an ivar.
DeclContext *DC, *LexicalDC;
@@ -4859,11 +5049,10 @@ Stmt *ASTNodeImporter::VisitGCCAsmStmt(GCCAsmStmt *S) {
}
SmallVector<Expr *, 4> Exprs(S->getNumOutputs() + S->getNumInputs());
- if (ImportArrayChecked(S->begin_outputs(), S->end_outputs(), Exprs.begin()))
+ if (ImportContainerChecked(S->outputs(), Exprs))
return nullptr;
- if (ImportArrayChecked(S->begin_inputs(), S->end_inputs(),
- Exprs.begin() + S->getNumOutputs()))
+ if (ImportArrayChecked(S->inputs(), Exprs.begin() + S->getNumOutputs()))
return nullptr;
StringLiteral *AsmStr = cast_or_null<StringLiteral>(
@@ -4906,8 +5095,8 @@ Stmt *ASTNodeImporter::VisitNullStmt(NullStmt *S) {
Stmt *ASTNodeImporter::VisitCompoundStmt(CompoundStmt *S) {
llvm::SmallVector<Stmt *, 8> ToStmts(S->size());
-
- if (ImportArrayChecked(S->body_begin(), S->body_end(), ToStmts.begin()))
+
+ if (ImportContainerChecked(S->body(), ToStmts))
return nullptr;
SourceLocation ToLBraceLoc = Importer.Import(S->getLBracLoc());
@@ -5361,7 +5550,7 @@ Expr *ASTNodeImporter::VisitGNUNullExpr(GNUNullExpr *E) {
return nullptr;
return new (Importer.getToContext()) GNUNullExpr(
- T, Importer.Import(E->getExprLoc()));
+ T, Importer.Import(E->getLocStart()));
}
Expr *ASTNodeImporter::VisitPredefinedExpr(PredefinedExpr *E) {
@@ -5375,7 +5564,7 @@ Expr *ASTNodeImporter::VisitPredefinedExpr(PredefinedExpr *E) {
return nullptr;
return new (Importer.getToContext()) PredefinedExpr(
- Importer.Import(E->getExprLoc()), T, E->getIdentType(), SL);
+ Importer.Import(E->getLocStart()), T, E->getIdentType(), SL);
}
Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) {
@@ -5394,6 +5583,20 @@ 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()) {
+ bool Error = false;
+ TemplateArgumentLoc ToTALoc = ImportTemplateArgumentLoc(FromLoc, Error);
+ if (Error)
+ return nullptr;
+ ToTAInfo.addArgument(ToTALoc);
+ }
+ ResInfo = &ToTAInfo;
+ }
+
DeclRefExpr *DRE = DeclRefExpr::Create(Importer.getToContext(),
Importer.Import(E->getQualifierLoc()),
Importer.Import(E->getTemplateKeywordLoc()),
@@ -5401,8 +5604,7 @@ Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) {
E->refersToEnclosingVariableOrCapture(),
Importer.Import(E->getLocation()),
T, E->getValueKind(),
- FoundD,
- /*FIXME:TemplateArgs=*/nullptr);
+ FoundD, ResInfo);
if (E->hadMultipleCandidates())
DRE->setHadMultipleCandidates(true);
return DRE;
@@ -5411,7 +5613,7 @@ Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) {
Expr *ASTNodeImporter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
- return NULL;
+ return nullptr;
return new (Importer.getToContext()) ImplicitValueInitExpr(T);
}
@@ -5580,8 +5782,7 @@ Expr *ASTNodeImporter::VisitParenExpr(ParenExpr *E) {
Expr *ASTNodeImporter::VisitParenListExpr(ParenListExpr *E) {
SmallVector<Expr *, 4> Exprs(E->getNumExprs());
- if (ImportArrayChecked(
- E->getExprs(), E->getExprs() + E->getNumExprs(), Exprs.begin()))
+ if (ImportContainerChecked(E->exprs(), Exprs))
return nullptr;
return new (Importer.getToContext()) ParenListExpr(
@@ -5719,6 +5920,38 @@ Expr *ASTNodeImporter::VisitBinaryConditionalOperator(
T, E->getValueKind(), E->getObjectKind());
}
+Expr *ASTNodeImporter::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return nullptr;
+
+ TypeSourceInfo *ToQueried = Importer.Import(E->getQueriedTypeSourceInfo());
+ if (!ToQueried)
+ return nullptr;
+
+ Expr *Dim = Importer.Import(E->getDimensionExpression());
+ if (!Dim && E->getDimensionExpression())
+ return nullptr;
+
+ return new (Importer.getToContext()) ArrayTypeTraitExpr(
+ Importer.Import(E->getLocStart()), E->getTrait(), ToQueried,
+ E->getValue(), Dim, Importer.Import(E->getLocEnd()), T);
+}
+
+Expr *ASTNodeImporter::VisitExpressionTraitExpr(ExpressionTraitExpr *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return nullptr;
+
+ Expr *ToQueried = Importer.Import(E->getQueriedExpression());
+ if (!ToQueried)
+ return nullptr;
+
+ return new (Importer.getToContext()) ExpressionTraitExpr(
+ Importer.Import(E->getLocStart()), E->getTrait(), ToQueried,
+ E->getValue(), Importer.Import(E->getLocEnd()), T);
+}
+
Expr *ASTNodeImporter::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
@@ -5729,10 +5962,28 @@ Expr *ASTNodeImporter::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
return nullptr;
return new (Importer.getToContext()) OpaqueValueExpr(
- Importer.Import(E->getExprLoc()), T, E->getValueKind(),
+ Importer.Import(E->getLocation()), T, E->getValueKind(),
E->getObjectKind(), SourceExpr);
}
+Expr *ASTNodeImporter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return nullptr;
+
+ Expr *ToLHS = Importer.Import(E->getLHS());
+ if (!ToLHS)
+ return nullptr;
+
+ Expr *ToRHS = Importer.Import(E->getRHS());
+ if (!ToRHS)
+ return nullptr;
+
+ return new (Importer.getToContext()) ArraySubscriptExpr(
+ ToLHS, ToRHS, T, E->getValueKind(), E->getObjectKind(),
+ Importer.Import(E->getRBracketLoc()));
+}
+
Expr *ASTNodeImporter::VisitCompoundAssignOperator(CompoundAssignOperator *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
@@ -5763,11 +6014,14 @@ Expr *ASTNodeImporter::VisitCompoundAssignOperator(CompoundAssignOperator *E) {
E->isFPContractable());
}
-static bool ImportCastPath(CastExpr *E, CXXCastPath &Path) {
- if (E->path_empty()) return false;
-
- // TODO: import cast paths
- return true;
+bool ASTNodeImporter::ImportCastPath(CastExpr *CE, CXXCastPath &Path) {
+ for (auto I = CE->path_begin(), E = CE->path_end(); I != E; ++I) {
+ if (CXXBaseSpecifier *Spec = Importer.Import(*I))
+ Path.push_back(Spec);
+ else
+ return true;
+ }
+ return false;
}
Expr *ASTNodeImporter::VisitImplicitCastExpr(ImplicitCastExpr *E) {
@@ -5787,7 +6041,7 @@ Expr *ASTNodeImporter::VisitImplicitCastExpr(ImplicitCastExpr *E) {
SubExpr, &BasePath, E->getValueKind());
}
-Expr *ASTNodeImporter::VisitCStyleCastExpr(CStyleCastExpr *E) {
+Expr *ASTNodeImporter::VisitExplicitCastExpr(ExplicitCastExpr *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
return nullptr;
@@ -5804,11 +6058,320 @@ Expr *ASTNodeImporter::VisitCStyleCastExpr(CStyleCastExpr *E) {
if (ImportCastPath(E, BasePath))
return nullptr;
- return CStyleCastExpr::Create(Importer.getToContext(), T,
- E->getValueKind(), E->getCastKind(),
- SubExpr, &BasePath, TInfo,
- Importer.Import(E->getLParenLoc()),
- Importer.Import(E->getRParenLoc()));
+ switch (E->getStmtClass()) {
+ case Stmt::CStyleCastExprClass: {
+ CStyleCastExpr *CCE = cast<CStyleCastExpr>(E);
+ return CStyleCastExpr::Create(Importer.getToContext(), T,
+ E->getValueKind(), E->getCastKind(),
+ SubExpr, &BasePath, TInfo,
+ Importer.Import(CCE->getLParenLoc()),
+ Importer.Import(CCE->getRParenLoc()));
+ }
+
+ case Stmt::CXXFunctionalCastExprClass: {
+ CXXFunctionalCastExpr *FCE = cast<CXXFunctionalCastExpr>(E);
+ return CXXFunctionalCastExpr::Create(Importer.getToContext(), T,
+ E->getValueKind(), TInfo,
+ E->getCastKind(), SubExpr, &BasePath,
+ Importer.Import(FCE->getLParenLoc()),
+ Importer.Import(FCE->getRParenLoc()));
+ }
+
+ case Stmt::ObjCBridgedCastExprClass: {
+ ObjCBridgedCastExpr *OCE = cast<ObjCBridgedCastExpr>(E);
+ return new (Importer.getToContext()) ObjCBridgedCastExpr(
+ Importer.Import(OCE->getLParenLoc()), OCE->getBridgeKind(),
+ E->getCastKind(), Importer.Import(OCE->getBridgeKeywordLoc()),
+ TInfo, SubExpr);
+ }
+ default:
+ break; // just fall through
+ }
+
+ CXXNamedCastExpr *Named = cast<CXXNamedCastExpr>(E);
+ SourceLocation ExprLoc = Importer.Import(Named->getOperatorLoc()),
+ RParenLoc = Importer.Import(Named->getRParenLoc());
+ SourceRange Brackets = Importer.Import(Named->getAngleBrackets());
+
+ switch (E->getStmtClass()) {
+ case Stmt::CXXStaticCastExprClass:
+ return CXXStaticCastExpr::Create(Importer.getToContext(), T,
+ E->getValueKind(), E->getCastKind(),
+ SubExpr, &BasePath, TInfo,
+ ExprLoc, RParenLoc, Brackets);
+
+ case Stmt::CXXDynamicCastExprClass:
+ return CXXDynamicCastExpr::Create(Importer.getToContext(), T,
+ E->getValueKind(), E->getCastKind(),
+ SubExpr, &BasePath, TInfo,
+ ExprLoc, RParenLoc, Brackets);
+
+ case Stmt::CXXReinterpretCastExprClass:
+ return CXXReinterpretCastExpr::Create(Importer.getToContext(), T,
+ E->getValueKind(), E->getCastKind(),
+ SubExpr, &BasePath, TInfo,
+ ExprLoc, RParenLoc, Brackets);
+
+ case Stmt::CXXConstCastExprClass:
+ return CXXConstCastExpr::Create(Importer.getToContext(), T,
+ E->getValueKind(), SubExpr, TInfo, ExprLoc,
+ RParenLoc, Brackets);
+ default:
+ llvm_unreachable("Cast expression of unsupported type!");
+ return nullptr;
+ }
+}
+
+Expr *ASTNodeImporter::VisitOffsetOfExpr(OffsetOfExpr *OE) {
+ QualType T = Importer.Import(OE->getType());
+ if (T.isNull())
+ return nullptr;
+
+ SmallVector<OffsetOfNode, 4> Nodes;
+ for (int I = 0, E = OE->getNumComponents(); I < E; ++I) {
+ const OffsetOfNode &Node = OE->getComponent(I);
+
+ switch (Node.getKind()) {
+ case OffsetOfNode::Array:
+ Nodes.push_back(OffsetOfNode(Importer.Import(Node.getLocStart()),
+ Node.getArrayExprIndex(),
+ Importer.Import(Node.getLocEnd())));
+ break;
+
+ case OffsetOfNode::Base: {
+ CXXBaseSpecifier *BS = Importer.Import(Node.getBase());
+ if (!BS && Node.getBase())
+ return nullptr;
+ Nodes.push_back(OffsetOfNode(BS));
+ break;
+ }
+ case OffsetOfNode::Field: {
+ FieldDecl *FD = cast_or_null<FieldDecl>(Importer.Import(Node.getField()));
+ if (!FD)
+ return nullptr;
+ Nodes.push_back(OffsetOfNode(Importer.Import(Node.getLocStart()), FD,
+ Importer.Import(Node.getLocEnd())));
+ break;
+ }
+ case OffsetOfNode::Identifier: {
+ IdentifierInfo *ToII = Importer.Import(Node.getFieldName());
+ if (!ToII)
+ return nullptr;
+ Nodes.push_back(OffsetOfNode(Importer.Import(Node.getLocStart()), ToII,
+ Importer.Import(Node.getLocEnd())));
+ break;
+ }
+ }
+ }
+
+ SmallVector<Expr *, 4> Exprs(OE->getNumExpressions());
+ for (int I = 0, E = OE->getNumExpressions(); I < E; ++I) {
+ Expr *ToIndexExpr = Importer.Import(OE->getIndexExpr(I));
+ if (!ToIndexExpr)
+ return nullptr;
+ Exprs[I] = ToIndexExpr;
+ }
+
+ TypeSourceInfo *TInfo = Importer.Import(OE->getTypeSourceInfo());
+ if (!TInfo && OE->getTypeSourceInfo())
+ return nullptr;
+
+ return OffsetOfExpr::Create(Importer.getToContext(), T,
+ Importer.Import(OE->getOperatorLoc()),
+ TInfo, Nodes, Exprs,
+ Importer.Import(OE->getRParenLoc()));
+}
+
+Expr *ASTNodeImporter::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return nullptr;
+
+ Expr *Operand = Importer.Import(E->getOperand());
+ if (!Operand)
+ return nullptr;
+
+ CanThrowResult CanThrow;
+ if (E->isValueDependent())
+ CanThrow = CT_Dependent;
+ else
+ CanThrow = E->getValue() ? CT_Can : CT_Cannot;
+
+ return new (Importer.getToContext()) CXXNoexceptExpr(
+ T, Operand, CanThrow,
+ Importer.Import(E->getLocStart()), Importer.Import(E->getLocEnd()));
+}
+
+Expr *ASTNodeImporter::VisitCXXThrowExpr(CXXThrowExpr *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return nullptr;
+
+ Expr *SubExpr = Importer.Import(E->getSubExpr());
+ if (!SubExpr && E->getSubExpr())
+ return nullptr;
+
+ return new (Importer.getToContext()) CXXThrowExpr(
+ SubExpr, T, Importer.Import(E->getThrowLoc()),
+ E->isThrownVariableInScope());
+}
+
+Expr *ASTNodeImporter::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
+ ParmVarDecl *Param = cast_or_null<ParmVarDecl>(
+ Importer.Import(E->getParam()));
+ if (!Param)
+ return nullptr;
+
+ return CXXDefaultArgExpr::Create(
+ Importer.getToContext(), Importer.Import(E->getUsedLocation()), Param);
+}
+
+Expr *ASTNodeImporter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return nullptr;
+
+ TypeSourceInfo *TypeInfo = Importer.Import(E->getTypeSourceInfo());
+ if (!TypeInfo)
+ return nullptr;
+
+ return new (Importer.getToContext()) CXXScalarValueInitExpr(
+ T, TypeInfo, Importer.Import(E->getRParenLoc()));
+}
+
+Expr *ASTNodeImporter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
+ Expr *SubExpr = Importer.Import(E->getSubExpr());
+ if (!SubExpr)
+ return nullptr;
+
+ auto *Dtor = cast_or_null<CXXDestructorDecl>(
+ Importer.Import(const_cast<CXXDestructorDecl *>(
+ E->getTemporary()->getDestructor())));
+ if (!Dtor)
+ return nullptr;
+
+ ASTContext &ToCtx = Importer.getToContext();
+ CXXTemporary *Temp = CXXTemporary::Create(ToCtx, Dtor);
+ return CXXBindTemporaryExpr::Create(ToCtx, Temp, SubExpr);
+}
+
+Expr *ASTNodeImporter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *CE) {
+ QualType T = Importer.Import(CE->getType());
+ if (T.isNull())
+ return nullptr;
+
+ SmallVector<Expr *, 8> Args(CE->getNumArgs());
+ if (ImportContainerChecked(CE->arguments(), Args))
+ return nullptr;
+
+ auto *Ctor = cast_or_null<CXXConstructorDecl>(
+ Importer.Import(CE->getConstructor()));
+ 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()));
+}
+
+Expr *
+ASTNodeImporter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return nullptr;
+
+ Expr *TempE = Importer.Import(E->GetTemporaryExpr());
+ if (!TempE)
+ return nullptr;
+
+ ValueDecl *ExtendedBy = cast_or_null<ValueDecl>(
+ Importer.Import(const_cast<ValueDecl *>(E->getExtendingDecl())));
+ if (!ExtendedBy && E->getExtendingDecl())
+ return nullptr;
+
+ auto *ToMTE = new (Importer.getToContext()) MaterializeTemporaryExpr(
+ T, TempE, E->isBoundToLvalueReference());
+
+ // FIXME: Should ManglingNumber get numbers associated with 'to' context?
+ ToMTE->setExtendingDecl(ExtendedBy, E->getManglingNumber());
+ return ToMTE;
+}
+
+Expr *ASTNodeImporter::VisitCXXNewExpr(CXXNewExpr *CE) {
+ QualType T = Importer.Import(CE->getType());
+ if (T.isNull())
+ return nullptr;
+
+ SmallVector<Expr *, 4> PlacementArgs(CE->getNumPlacementArgs());
+ if (ImportContainerChecked(CE->placement_arguments(), PlacementArgs))
+ return nullptr;
+
+ FunctionDecl *OperatorNewDecl = cast_or_null<FunctionDecl>(
+ Importer.Import(CE->getOperatorNew()));
+ if (!OperatorNewDecl && CE->getOperatorNew())
+ return nullptr;
+
+ FunctionDecl *OperatorDeleteDecl = cast_or_null<FunctionDecl>(
+ Importer.Import(CE->getOperatorDelete()));
+ if (!OperatorDeleteDecl && CE->getOperatorDelete())
+ return nullptr;
+
+ Expr *ToInit = Importer.Import(CE->getInitializer());
+ if (!ToInit && CE->getInitializer())
+ return nullptr;
+
+ TypeSourceInfo *TInfo = Importer.Import(CE->getAllocatedTypeSourceInfo());
+ if (!TInfo)
+ return nullptr;
+
+ Expr *ToArrSize = Importer.Import(CE->getArraySize());
+ if (!ToArrSize && CE->getArraySize())
+ return nullptr;
+
+ return new (Importer.getToContext()) CXXNewExpr(
+ Importer.getToContext(),
+ CE->isGlobalNew(),
+ OperatorNewDecl, OperatorDeleteDecl,
+ CE->passAlignment(),
+ CE->doesUsualArrayDeleteWantSize(),
+ PlacementArgs,
+ Importer.Import(CE->getTypeIdParens()),
+ ToArrSize, CE->getInitializationStyle(), ToInit, T, TInfo,
+ Importer.Import(CE->getSourceRange()),
+ Importer.Import(CE->getDirectInitRange()));
+}
+
+Expr *ASTNodeImporter::VisitCXXDeleteExpr(CXXDeleteExpr *E) {
+ QualType T = Importer.Import(E->getType());
+ if (T.isNull())
+ return nullptr;
+
+ FunctionDecl *OperatorDeleteDecl = cast_or_null<FunctionDecl>(
+ Importer.Import(E->getOperatorDelete()));
+ if (!OperatorDeleteDecl && E->getOperatorDelete())
+ return nullptr;
+
+ Expr *ToArg = Importer.Import(E->getArgument());
+ if (!ToArg && E->getArgument())
+ return nullptr;
+
+ return new (Importer.getToContext()) CXXDeleteExpr(
+ T, E->isGlobalDelete(),
+ E->isArrayForm(),
+ E->isArrayFormAsWritten(),
+ E->doesUsualArrayDeleteWantSize(),
+ OperatorDeleteDecl,
+ ToArg,
+ Importer.Import(E->getLocStart()));
}
Expr *ASTNodeImporter::VisitCXXConstructExpr(CXXConstructExpr *E) {
@@ -5822,8 +6385,7 @@ Expr *ASTNodeImporter::VisitCXXConstructExpr(CXXConstructExpr *E) {
return nullptr;
SmallVector<Expr *, 6> ToArgs(E->getNumArgs());
- if (ImportArrayChecked(E->getArgs(), E->getArgs() + E->getNumArgs(),
- ToArgs.begin()))
+ if (ImportContainerChecked(E->arguments(), ToArgs))
return nullptr;
return CXXConstructExpr::Create(Importer.getToContext(), T,
@@ -5837,6 +6399,24 @@ Expr *ASTNodeImporter::VisitCXXConstructExpr(CXXConstructExpr *E) {
Importer.Import(E->getParenOrBraceRange()));
}
+Expr *ASTNodeImporter::VisitExprWithCleanups(ExprWithCleanups *EWC) {
+ Expr *SubExpr = Importer.Import(EWC->getSubExpr());
+ if (!SubExpr && EWC->getSubExpr())
+ return nullptr;
+
+ SmallVector<ExprWithCleanups::CleanupObject, 8> Objs(EWC->getNumObjects());
+ for (unsigned I = 0, E = EWC->getNumObjects(); I < E; I++)
+ if (ExprWithCleanups::CleanupObject Obj =
+ cast_or_null<BlockDecl>(Importer.Import(EWC->getObject(I))))
+ Objs[I] = Obj;
+ else
+ return nullptr;
+
+ return ExprWithCleanups::Create(Importer.getToContext(),
+ SubExpr, EWC->cleanupsHaveSideEffects(),
+ Objs);
+}
+
Expr *ASTNodeImporter::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
@@ -5847,8 +6427,7 @@ Expr *ASTNodeImporter::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) {
return nullptr;
SmallVector<Expr *, 4> ToArgs(E->getNumArgs());
-
- if (ImportArrayChecked(E->arg_begin(), E->arg_end(), ToArgs.begin()))
+ if (ImportContainerChecked(E->arguments(), ToArgs))
return nullptr;
return new (Importer.getToContext()) CXXMemberCallExpr(
@@ -5949,8 +6528,7 @@ Expr *ASTNodeImporter::VisitInitListExpr(InitListExpr *ILE) {
return nullptr;
llvm::SmallVector<Expr *, 4> Exprs(ILE->getNumInits());
- if (ImportArrayChecked(
- ILE->getInits(), ILE->getInits() + ILE->getNumInits(), Exprs.begin()))
+ if (ImportContainerChecked(ILE->inits(), Exprs))
return nullptr;
ASTContext &ToCtx = Importer.getToContext();
@@ -5988,6 +6566,30 @@ Expr *ASTNodeImporter::VisitInitListExpr(InitListExpr *ILE) {
return To;
}
+Expr *ASTNodeImporter::VisitArrayInitLoopExpr(ArrayInitLoopExpr *E) {
+ QualType ToType = Importer.Import(E->getType());
+ if (ToType.isNull())
+ return nullptr;
+
+ Expr *ToCommon = Importer.Import(E->getCommonExpr());
+ if (!ToCommon && E->getCommonExpr())
+ return nullptr;
+
+ Expr *ToSubExpr = Importer.Import(E->getSubExpr());
+ if (!ToSubExpr && E->getSubExpr())
+ return nullptr;
+
+ return new (Importer.getToContext())
+ ArrayInitLoopExpr(ToType, ToCommon, ToSubExpr);
+}
+
+Expr *ASTNodeImporter::VisitArrayInitIndexExpr(ArrayInitIndexExpr *E) {
+ QualType ToType = Importer.Import(E->getType());
+ if (ToType.isNull())
+ return nullptr;
+ return new (Importer.getToContext()) ArrayInitIndexExpr(ToType);
+}
+
Expr *ASTNodeImporter::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *DIE) {
FieldDecl *ToField = llvm::dyn_cast_or_null<FieldDecl>(
Importer.Import(DIE->getField()));
@@ -6376,10 +6978,10 @@ SourceLocation ASTImporter::Import(SourceLocation FromLoc) {
SourceManager &FromSM = FromContext.getSourceManager();
- // For now, map everything down to its spelling location, so that we
+ // 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.getSpellingLoc(FromLoc);
+ FromLoc = FromSM.getFileLoc(FromLoc);
std::pair<FileID, unsigned> Decomposed = FromSM.getDecomposedLoc(FromLoc);
SourceManager &ToSM = ToContext.getSourceManager();
FileID ToFileID = Import(Decomposed.first);
@@ -6478,31 +7080,27 @@ CXXCtorInitializer *ASTImporter::Import(CXXCtorInitializer *From) {
return new (ToContext)
CXXCtorInitializer(ToContext, ToTInfo, Import(From->getLParenLoc()),
ToExpr, Import(From->getRParenLoc()));
- } else if (unsigned NumArrayIndices = From->getNumArrayIndices()) {
- FieldDecl *ToField =
- llvm::cast_or_null<FieldDecl>(Import(From->getMember()));
- if (!ToField && From->getMember())
- return nullptr;
-
- SmallVector<VarDecl *, 4> ToAIs(NumArrayIndices);
-
- for (unsigned AII = 0; AII < NumArrayIndices; ++AII) {
- VarDecl *ToArrayIndex =
- dyn_cast_or_null<VarDecl>(Import(From->getArrayIndex(AII)));
- if (!ToArrayIndex && From->getArrayIndex(AII))
- return nullptr;
- }
-
- return CXXCtorInitializer::Create(
- ToContext, ToField, Import(From->getMemberLocation()),
- Import(From->getLParenLoc()), ToExpr, Import(From->getRParenLoc()),
- ToAIs.data(), NumArrayIndices);
} else {
return nullptr;
}
}
+CXXBaseSpecifier *ASTImporter::Import(const CXXBaseSpecifier *BaseSpec) {
+ auto Pos = ImportedCXXBaseSpecifiers.find(BaseSpec);
+ if (Pos != ImportedCXXBaseSpecifiers.end())
+ return Pos->second;
+
+ CXXBaseSpecifier *Imported = new (ToContext) CXXBaseSpecifier(
+ Import(BaseSpec->getSourceRange()),
+ BaseSpec->isVirtual(), BaseSpec->isBaseOfClass(),
+ BaseSpec->getAccessSpecifierAsWritten(),
+ Import(BaseSpec->getTypeSourceInfo()),
+ Import(BaseSpec->getEllipsisLoc()));
+ ImportedCXXBaseSpecifiers[BaseSpec] = Imported;
+ return Imported;
+}
+
void ASTImporter::ImportDefinition(Decl *From) {
Decl *To = Import(From);
if (!To)
diff --git a/lib/AST/ASTTypeTraits.cpp b/lib/AST/ASTTypeTraits.cpp
index 2336c98fe049..461084ce707c 100644
--- a/lib/AST/ASTTypeTraits.cpp
+++ b/lib/AST/ASTTypeTraits.cpp
@@ -23,6 +23,7 @@ namespace ast_type_traits {
const ASTNodeKind::KindInfo ASTNodeKind::AllKindInfo[] = {
{ NKI_None, "<None>" },
{ NKI_None, "TemplateArgument" },
+ { NKI_None, "TemplateName" },
{ NKI_None, "NestedNameSpecifierLoc" },
{ NKI_None, "QualType" },
{ NKI_None, "TypeLoc" },
@@ -109,6 +110,8 @@ void DynTypedNode::print(llvm::raw_ostream &OS,
const PrintingPolicy &PP) const {
if (const TemplateArgument *TA = get<TemplateArgument>())
TA->print(PP, OS);
+ else if (const TemplateName *TN = get<TemplateName>())
+ TN->print(OS, PP);
else if (const NestedNameSpecifier *NNS = get<NestedNameSpecifier>())
NNS->print(OS, PP);
else if (const NestedNameSpecifierLoc *NNSL = get<NestedNameSpecifierLoc>())
@@ -132,6 +135,8 @@ void DynTypedNode::dump(llvm::raw_ostream &OS, SourceManager &SM) const {
D->dump(OS);
else if (const Stmt *S = get<Stmt>())
S->dump(OS, SM);
+ else if (const Type *T = get<Type>())
+ T->dump(OS);
else
OS << "Unable to dump values of type " << NodeKind.asStringRef() << "\n";
}
diff --git a/lib/AST/AttrImpl.cpp b/lib/AST/AttrImpl.cpp
index cb608700133c..b06b50c9b4b8 100644
--- a/lib/AST/AttrImpl.cpp
+++ b/lib/AST/AttrImpl.cpp
@@ -11,11 +11,10 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/AST/Attr.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/Attr.h"
#include "clang/AST/Expr.h"
#include "clang/AST/Type.h"
-#include "llvm/ADT/StringSwitch.h"
using namespace clang;
#include "clang/AST/AttrImpl.inc"
diff --git a/lib/AST/CXXABI.h b/lib/AST/CXXABI.h
index c23b9191c7ab..924ef00e8147 100644
--- a/lib/AST/CXXABI.h
+++ b/lib/AST/CXXABI.h
@@ -43,7 +43,8 @@ public:
virtual bool isNearlyEmpty(const CXXRecordDecl *RD) const = 0;
/// Returns a new mangling number context for this C++ ABI.
- virtual MangleNumberingContext *createMangleNumberingContext() const = 0;
+ virtual std::unique_ptr<MangleNumberingContext>
+ createMangleNumberingContext() const = 0;
/// Adds a mapping from class to copy constructor for this C++ ABI.
virtual void addCopyConstructorForExceptionObject(CXXRecordDecl *,
@@ -53,12 +54,6 @@ public:
virtual const CXXConstructorDecl *
getCopyConstructorForExceptionObject(CXXRecordDecl *) = 0;
- virtual void addDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
- unsigned ParmIdx, Expr *DAE) = 0;
-
- virtual Expr *getDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
- unsigned ParmIdx) = 0;
-
virtual void addTypedefNameForUnnamedTagDecl(TagDecl *TD,
TypedefNameDecl *DD) = 0;
diff --git a/lib/AST/CXXInheritance.cpp b/lib/AST/CXXInheritance.cpp
index 6a6ca76a0165..a97d6a22e7b3 100644
--- a/lib/AST/CXXInheritance.cpp
+++ b/lib/AST/CXXInheritance.cpp
@@ -16,7 +16,6 @@
#include "clang/AST/RecordLayout.h"
#include "llvm/ADT/SetVector.h"
#include <algorithm>
-#include <set>
using namespace clang;
diff --git a/lib/AST/Comment.cpp b/lib/AST/Comment.cpp
index 893bdc5c17bf..7a7d3dd8304e 100644
--- a/lib/AST/Comment.cpp
+++ b/lib/AST/Comment.cpp
@@ -7,14 +7,13 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/AST/ASTContext.h"
#include "clang/AST/Comment.h"
+#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/Basic/CharInfo.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/raw_ostream.h"
namespace clang {
namespace comments {
@@ -114,6 +113,65 @@ bool ParagraphComment::isWhitespaceNoCache() const {
return true;
}
+static TypeLoc lookThroughTypedefOrTypeAliasLocs(TypeLoc &SrcTL) {
+ TypeLoc TL = SrcTL.IgnoreParens();
+
+ // Look through qualified types.
+ if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>())
+ return QualifiedTL.getUnqualifiedLoc();
+ // Look through pointer types.
+ if (PointerTypeLoc PointerTL = TL.getAs<PointerTypeLoc>())
+ return PointerTL.getPointeeLoc().getUnqualifiedLoc();
+ // Look through reference types.
+ if (ReferenceTypeLoc ReferenceTL = TL.getAs<ReferenceTypeLoc>())
+ return ReferenceTL.getPointeeLoc().getUnqualifiedLoc();
+ // Look through adjusted types.
+ if (AdjustedTypeLoc ATL = TL.getAs<AdjustedTypeLoc>())
+ return ATL.getOriginalLoc();
+ if (BlockPointerTypeLoc BlockPointerTL = TL.getAs<BlockPointerTypeLoc>())
+ return BlockPointerTL.getPointeeLoc().getUnqualifiedLoc();
+ if (MemberPointerTypeLoc MemberPointerTL = TL.getAs<MemberPointerTypeLoc>())
+ return MemberPointerTL.getPointeeLoc().getUnqualifiedLoc();
+ if (ElaboratedTypeLoc ETL = TL.getAs<ElaboratedTypeLoc>())
+ return ETL.getNamedTypeLoc();
+
+ return TL;
+}
+
+static bool getFunctionTypeLoc(TypeLoc TL, FunctionTypeLoc &ResFTL) {
+ TypeLoc PrevTL;
+ while (PrevTL != TL) {
+ PrevTL = TL;
+ TL = lookThroughTypedefOrTypeAliasLocs(TL);
+ }
+
+ if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) {
+ ResFTL = FTL;
+ return true;
+ }
+
+ if (TemplateSpecializationTypeLoc STL =
+ TL.getAs<TemplateSpecializationTypeLoc>()) {
+ // If we have a typedef to a template specialization with exactly one
+ // template argument of a function type, this looks like std::function,
+ // boost::function, or other function wrapper. Treat these typedefs as
+ // functions.
+ if (STL.getNumArgs() != 1)
+ return false;
+ TemplateArgumentLoc MaybeFunction = STL.getArgLoc(0);
+ if (MaybeFunction.getArgument().getKind() != TemplateArgument::Type)
+ return false;
+ TypeSourceInfo *MaybeFunctionTSI = MaybeFunction.getTypeSourceInfo();
+ TypeLoc TL = MaybeFunctionTSI->getTypeLoc().getUnqualifiedLoc();
+ if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) {
+ ResFTL = FTL;
+ return true;
+ }
+ }
+
+ return false;
+}
+
const char *ParamCommandComment::getDirectionAsString(PassDirection D) {
switch (D) {
case ParamCommandComment::In:
@@ -227,90 +285,45 @@ void DeclInfo::fill() {
case Decl::Namespace:
Kind = NamespaceKind;
break;
+ case Decl::TypeAlias:
case Decl::Typedef: {
Kind = TypedefKind;
- // If this is a typedef to something we consider a function, extract
+ // If this is a typedef / using to something we consider a function, extract
// arguments and return type.
- const TypedefDecl *TD = cast<TypedefDecl>(CommentDecl);
- const TypeSourceInfo *TSI = TD->getTypeSourceInfo();
+ const TypeSourceInfo *TSI =
+ K == Decl::Typedef
+ ? cast<TypedefDecl>(CommentDecl)->getTypeSourceInfo()
+ : cast<TypeAliasDecl>(CommentDecl)->getTypeSourceInfo();
if (!TSI)
break;
TypeLoc TL = TSI->getTypeLoc().getUnqualifiedLoc();
- while (true) {
- TL = TL.IgnoreParens();
- // Look through qualified types.
- if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>()) {
- TL = QualifiedTL.getUnqualifiedLoc();
- continue;
- }
- // Look through pointer types.
- if (PointerTypeLoc PointerTL = TL.getAs<PointerTypeLoc>()) {
- TL = PointerTL.getPointeeLoc().getUnqualifiedLoc();
- continue;
- }
- // Look through reference types.
- if (ReferenceTypeLoc ReferenceTL = TL.getAs<ReferenceTypeLoc>()) {
- TL = ReferenceTL.getPointeeLoc().getUnqualifiedLoc();
- continue;
- }
- // Look through adjusted types.
- if (AdjustedTypeLoc ATL = TL.getAs<AdjustedTypeLoc>()) {
- TL = ATL.getOriginalLoc();
- continue;
- }
- if (BlockPointerTypeLoc BlockPointerTL =
- TL.getAs<BlockPointerTypeLoc>()) {
- TL = BlockPointerTL.getPointeeLoc().getUnqualifiedLoc();
- continue;
- }
- if (MemberPointerTypeLoc MemberPointerTL =
- TL.getAs<MemberPointerTypeLoc>()) {
- TL = MemberPointerTL.getPointeeLoc().getUnqualifiedLoc();
- continue;
- }
- if (ElaboratedTypeLoc ETL = TL.getAs<ElaboratedTypeLoc>()) {
- TL = ETL.getNamedTypeLoc();
- continue;
- }
- // Is this a typedef for a function type?
- if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) {
- Kind = FunctionKind;
- ParamVars = FTL.getParams();
- ReturnType = FTL.getReturnLoc().getType();
- break;
- }
- if (TemplateSpecializationTypeLoc STL =
- TL.getAs<TemplateSpecializationTypeLoc>()) {
- // If we have a typedef to a template specialization with exactly one
- // template argument of a function type, this looks like std::function,
- // boost::function, or other function wrapper. Treat these typedefs as
- // functions.
- if (STL.getNumArgs() != 1)
- break;
- TemplateArgumentLoc MaybeFunction = STL.getArgLoc(0);
- if (MaybeFunction.getArgument().getKind() != TemplateArgument::Type)
- break;
- TypeSourceInfo *MaybeFunctionTSI = MaybeFunction.getTypeSourceInfo();
- TypeLoc TL = MaybeFunctionTSI->getTypeLoc().getUnqualifiedLoc();
- if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) {
- Kind = FunctionKind;
- ParamVars = FTL.getParams();
- ReturnType = FTL.getReturnLoc().getType();
- }
- break;
- }
- break;
+ FunctionTypeLoc FTL;
+ if (getFunctionTypeLoc(TL, FTL)) {
+ Kind = FunctionKind;
+ ParamVars = FTL.getParams();
+ ReturnType = FTL.getReturnLoc().getType();
}
break;
}
- case Decl::TypeAlias:
- Kind = TypedefKind;
- break;
case Decl::TypeAliasTemplate: {
const TypeAliasTemplateDecl *TAT = cast<TypeAliasTemplateDecl>(CommentDecl);
Kind = TypedefKind;
TemplateKind = Template;
TemplateParameters = TAT->getTemplateParameters();
+ TypeAliasDecl *TAD = TAT->getTemplatedDecl();
+ if (!TAD)
+ break;
+
+ const TypeSourceInfo *TSI = TAD->getTypeSourceInfo();
+ if (!TSI)
+ break;
+ TypeLoc TL = TSI->getTypeLoc().getUnqualifiedLoc();
+ FunctionTypeLoc FTL;
+ if (getFunctionTypeLoc(TL, FTL)) {
+ Kind = FunctionKind;
+ ParamVars = FTL.getParams();
+ ReturnType = FTL.getReturnLoc().getType();
+ }
break;
}
case Decl::Enum:
diff --git a/lib/AST/CommentBriefParser.cpp b/lib/AST/CommentBriefParser.cpp
index 090b9211d4c1..eecea8fc11df 100644
--- a/lib/AST/CommentBriefParser.cpp
+++ b/lib/AST/CommentBriefParser.cpp
@@ -9,7 +9,6 @@
#include "clang/AST/CommentBriefParser.h"
#include "clang/AST/CommentCommandTraits.h"
-#include "llvm/ADT/StringSwitch.h"
namespace clang {
namespace comments {
diff --git a/lib/AST/CommentLexer.cpp b/lib/AST/CommentLexer.cpp
index 57bfef08df6e..65d0f56f09ab 100644
--- a/lib/AST/CommentLexer.cpp
+++ b/lib/AST/CommentLexer.cpp
@@ -378,15 +378,17 @@ void Lexer::lexCommentText(Token &T) {
if ((Info = Traits.getTypoCorrectCommandInfo(CommandName))) {
StringRef CorrectedName = Info->Name;
SourceLocation Loc = getSourceLocation(BufferPtr);
- SourceRange CommandRange(Loc.getLocWithOffset(1),
- getSourceLocation(TokenPtr));
+ SourceLocation EndLoc = getSourceLocation(TokenPtr);
+ SourceRange FullRange = SourceRange(Loc, EndLoc);
+ SourceRange CommandRange(Loc.getLocWithOffset(1), EndLoc);
Diag(Loc, diag::warn_correct_comment_command_name)
- << CommandName << CorrectedName
+ << 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);
+ Diag(T.getLocation(), diag::warn_unknown_comment_command_name)
+ << SourceRange(T.getLocation(), T.getEndLocation());
return;
}
}
diff --git a/lib/AST/CommentParser.cpp b/lib/AST/CommentParser.cpp
index cb37ec35f4d3..c1c04239f58e 100644
--- a/lib/AST/CommentParser.cpp
+++ b/lib/AST/CommentParser.cpp
@@ -40,11 +40,11 @@ class TextTokenRetokenizer {
/// A position in \c Toks.
struct Position {
- unsigned CurToken;
const char *BufferStart;
const char *BufferEnd;
const char *BufferPtr;
SourceLocation BufferStartLoc;
+ unsigned CurToken;
};
/// Current position in Toks.
diff --git a/lib/AST/CommentSema.cpp b/lib/AST/CommentSema.cpp
index f5f4f70dcbbf..d39a9b26b2a8 100644
--- a/lib/AST/CommentSema.cpp
+++ b/lib/AST/CommentSema.cpp
@@ -950,20 +950,19 @@ unsigned Sema::resolveParmVarReference(StringRef Name,
namespace {
class SimpleTypoCorrector {
+ const NamedDecl *BestDecl;
+
StringRef Typo;
const unsigned MaxEditDistance;
- const NamedDecl *BestDecl;
unsigned BestEditDistance;
unsigned BestIndex;
unsigned NextIndex;
public:
- SimpleTypoCorrector(StringRef Typo) :
- Typo(Typo), MaxEditDistance((Typo.size() + 2) / 3),
- BestDecl(nullptr), BestEditDistance(MaxEditDistance + 1),
- BestIndex(0), NextIndex(0)
- { }
+ explicit SimpleTypoCorrector(StringRef Typo)
+ : BestDecl(nullptr), Typo(Typo), MaxEditDistance((Typo.size() + 2) / 3),
+ BestEditDistance(MaxEditDistance + 1), BestIndex(0), NextIndex(0) {}
void addDecl(const NamedDecl *ND);
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index d1e8d25ea044..c3fa1c87affd 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -1395,6 +1395,10 @@ static LinkageInfo getLVForDecl(const NamedDecl *D,
return clang::LinkageComputer::getLVForDecl(D, computation);
}
+void NamedDecl::printName(raw_ostream &os) const {
+ os << Name;
+}
+
std::string NamedDecl::getQualifiedNameAsString() const {
std::string QualName;
llvm::raw_string_ostream OS(QualName);
@@ -1481,7 +1485,7 @@ void NamedDecl::printQualifiedName(raw_ostream &OS,
OS << "::";
}
- if (getDeclName())
+ if (getDeclName() || isa<DecompositionDecl>(this))
OS << *this;
else
OS << "(anonymous)";
@@ -1922,6 +1926,9 @@ VarDecl::isThisDeclarationADefinition(ASTContext &C) const {
//
// FIXME: How do you declare (but not define) a partial specialization of
// a static data member template outside the containing class?
+ if (isThisDeclarationADemotedDefinition())
+ return DeclarationOnly;
+
if (isStaticDataMember()) {
if (isOutOfLine() &&
!(getCanonicalDecl()->isInline() &&
@@ -2246,6 +2253,56 @@ bool VarDecl::checkInitIsICE() const {
return Eval->IsICE;
}
+VarDecl *VarDecl::getTemplateInstantiationPattern() const {
+ // If it's a variable template specialization, find the template or partial
+ // specialization from which it was instantiated.
+ if (auto *VDTemplSpec = dyn_cast<VarTemplateSpecializationDecl>(this)) {
+ auto From = VDTemplSpec->getInstantiatedFrom();
+ if (auto *VTD = From.dyn_cast<VarTemplateDecl *>()) {
+ while (auto *NewVTD = VTD->getInstantiatedFromMemberTemplate()) {
+ if (NewVTD->isMemberSpecialization())
+ break;
+ VTD = NewVTD;
+ }
+ return VTD->getTemplatedDecl()->getDefinition();
+ }
+ if (auto *VTPSD =
+ From.dyn_cast<VarTemplatePartialSpecializationDecl *>()) {
+ while (auto *NewVTPSD = VTPSD->getInstantiatedFromMember()) {
+ if (NewVTPSD->isMemberSpecialization())
+ break;
+ VTPSD = NewVTPSD;
+ }
+ return VTPSD->getDefinition();
+ }
+ }
+
+ if (MemberSpecializationInfo *MSInfo = getMemberSpecializationInfo()) {
+ if (isTemplateInstantiation(MSInfo->getTemplateSpecializationKind())) {
+ VarDecl *VD = getInstantiatedFromStaticDataMember();
+ while (auto *NewVD = VD->getInstantiatedFromStaticDataMember())
+ VD = NewVD;
+ return VD->getDefinition();
+ }
+ }
+
+ if (VarTemplateDecl *VarTemplate = getDescribedVarTemplate()) {
+
+ while (VarTemplate->getInstantiatedFromMemberTemplate()) {
+ if (VarTemplate->isMemberSpecialization())
+ break;
+ VarTemplate = VarTemplate->getInstantiatedFromMemberTemplate();
+ }
+
+ assert((!VarTemplate->getTemplatedDecl() ||
+ !isTemplateInstantiation(getTemplateSpecializationKind())) &&
+ "couldn't find pattern for variable instantiation");
+
+ return VarTemplate->getTemplatedDecl();
+ }
+ return nullptr;
+}
+
VarDecl *VarDecl::getInstantiatedFromStaticDataMember() const {
if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo())
return cast<VarDecl>(MSI->getInstantiatedFrom());
@@ -2592,7 +2649,7 @@ bool FunctionDecl::isReplaceableGlobalAllocationFunction() const {
return false;
const auto *FPT = getType()->castAs<FunctionProtoType>();
- if (FPT->getNumParams() == 0 || FPT->getNumParams() > 2 || FPT->isVariadic())
+ if (FPT->getNumParams() == 0 || FPT->getNumParams() > 3 || FPT->isVariadic())
return false;
// If this is a single-parameter function, it must be a replaceable global
@@ -2600,20 +2657,42 @@ bool FunctionDecl::isReplaceableGlobalAllocationFunction() const {
if (FPT->getNumParams() == 1)
return true;
- // Otherwise, we're looking for a second parameter whose type is
- // 'const std::nothrow_t &', or, in C++1y, 'std::size_t'.
- QualType Ty = FPT->getParamType(1);
+ unsigned Params = 1;
+ QualType Ty = FPT->getParamType(Params);
ASTContext &Ctx = getASTContext();
+
+ auto Consume = [&] {
+ ++Params;
+ Ty = Params < FPT->getNumParams() ? FPT->getParamType(Params) : QualType();
+ };
+
+ // In C++14, the next parameter can be a 'std::size_t' for sized delete.
+ bool IsSizedDelete = false;
if (Ctx.getLangOpts().SizedDeallocation &&
- Ctx.hasSameType(Ty, Ctx.getSizeType()))
- return true;
- if (!Ty->isReferenceType())
- return false;
- Ty = Ty->getPointeeType();
- if (Ty.getCVRQualifiers() != Qualifiers::Const)
- return false;
- const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl();
- return RD && isNamed(RD, "nothrow_t") && RD->isInStdNamespace();
+ (getDeclName().getCXXOverloadedOperator() == OO_Delete ||
+ getDeclName().getCXXOverloadedOperator() == OO_Array_Delete) &&
+ Ctx.hasSameType(Ty, Ctx.getSizeType())) {
+ IsSizedDelete = true;
+ Consume();
+ }
+
+ // In C++17, the next parameter can be a 'std::align_val_t' for aligned
+ // new/delete.
+ if (Ctx.getLangOpts().AlignedAllocation && !Ty.isNull() && Ty->isAlignValT())
+ Consume();
+
+ // Finally, if this is not a sized delete, the final parameter can
+ // be a 'const std::nothrow_t&'.
+ if (!IsSizedDelete && !Ty.isNull() && Ty->isReferenceType()) {
+ Ty = Ty->getPointeeType();
+ if (Ty.getCVRQualifiers() != Qualifiers::Const)
+ return false;
+ const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl();
+ if (RD && isNamed(RD, "nothrow_t") && RD->isInStdNamespace())
+ Consume();
+ }
+
+ return Params == FPT->getNumParams();
}
LanguageLinkage FunctionDecl::getLanguageLinkage() const {
@@ -2653,9 +2732,14 @@ bool FunctionDecl::isGlobal() const {
}
bool FunctionDecl::isNoReturn() const {
- return hasAttr<NoReturnAttr>() || hasAttr<CXX11NoReturnAttr>() ||
- hasAttr<C11NoReturnAttr>() ||
- getType()->getAs<FunctionType>()->getNoReturnAttr();
+ if (hasAttr<NoReturnAttr>() || hasAttr<CXX11NoReturnAttr>() ||
+ hasAttr<C11NoReturnAttr>())
+ return true;
+
+ if (auto *FnTy = getType()->getAs<FunctionType>())
+ return FnTy->getNoReturnAttr();
+
+ return false;
}
void
@@ -2756,28 +2840,6 @@ void FunctionDecl::setParams(ASTContext &C,
}
}
-void FunctionDecl::setDeclsInPrototypeScope(ArrayRef<NamedDecl *> NewDecls) {
- assert(DeclsInPrototypeScope.empty() && "Already has prototype decls!");
-
- if (!NewDecls.empty()) {
- NamedDecl **A = new (getASTContext()) NamedDecl*[NewDecls.size()];
- std::copy(NewDecls.begin(), NewDecls.end(), A);
- DeclsInPrototypeScope = llvm::makeArrayRef(A, NewDecls.size());
- // Move declarations introduced in prototype to the function context.
- for (auto I : NewDecls) {
- DeclContext *DC = I->getDeclContext();
- // Forward-declared reference to an enumeration is not added to
- // declaration scope, so skip declaration that is absent from its
- // declaration contexts.
- if (DC->containsDecl(I)) {
- DC->removeDecl(I);
- I->setDeclContext(this);
- addDecl(I);
- }
- }
- }
-}
-
/// getMinRequiredArguments - Returns the minimum number of arguments
/// needed to call this function. This may be fewer than the number of
/// function parameters, if some of the parameters have default
@@ -2964,7 +3026,8 @@ const Attr *FunctionDecl::getUnusedResultAttr() const {
/// an externally visible symbol, but "extern inline" will not create an
/// externally visible symbol.
bool FunctionDecl::isInlineDefinitionExternallyVisible() const {
- assert(doesThisDeclarationHaveABody() && "Must have the function definition");
+ assert((doesThisDeclarationHaveABody() || willHaveBody()) &&
+ "Must be a function definition");
assert(isInlined() && "Function must be inline");
ASTContext &Context = getASTContext();
@@ -3408,6 +3471,10 @@ unsigned FunctionDecl::getMemoryFunctionKind() const {
case Builtin::BIstrlen:
return Builtin::BIstrlen;
+ case Builtin::BI__builtin_bzero:
+ case Builtin::BIbzero:
+ return Builtin::BIbzero;
+
default:
if (isExternC()) {
if (FnInfo->isStr("memset"))
@@ -3430,6 +3497,8 @@ unsigned FunctionDecl::getMemoryFunctionKind() const {
return Builtin::BIstrndup;
else if (FnInfo->isStr("strlen"))
return Builtin::BIstrlen;
+ else if (FnInfo->isStr("bzero"))
+ return Builtin::BIbzero;
}
break;
}
@@ -4281,3 +4350,18 @@ SourceRange ImportDecl::getSourceRange() const {
return SourceRange(getLocation(), getIdentifierLocs().back());
}
+
+//===----------------------------------------------------------------------===//
+// ExportDecl Implementation
+//===----------------------------------------------------------------------===//
+
+void ExportDecl::anchor() {}
+
+ExportDecl *ExportDecl::Create(ASTContext &C, DeclContext *DC,
+ SourceLocation ExportLoc) {
+ return new (C, DC) ExportDecl(DC, ExportLoc);
+}
+
+ExportDecl *ExportDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
+ return new (C, ID) ExportDecl(nullptr, SourceLocation());
+}
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index bfb7d02b2955..6111abab646e 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -28,7 +28,6 @@
#include "clang/AST/StmtCXX.h"
#include "clang/AST/Type.h"
#include "clang/Basic/TargetInfo.h"
-#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
using namespace clang;
@@ -46,8 +45,7 @@ void Decl::updateOutOfDate(IdentifierInfo &II) const {
}
#define DECL(DERIVED, BASE) \
- static_assert(llvm::AlignOf<Decl>::Alignment >= \
- llvm::AlignOf<DERIVED##Decl>::Alignment, \
+ static_assert(alignof(Decl) >= alignof(DERIVED##Decl), \
"Alignment sufficient after objects prepended to " #DERIVED);
#define ABSTRACT_DECL(DECL)
#include "clang/AST/DeclNodes.inc"
@@ -56,7 +54,7 @@ void *Decl::operator new(std::size_t Size, const ASTContext &Context,
unsigned ID, std::size_t Extra) {
// Allocate an extra 8 bytes worth of storage, which ensures that the
// resulting pointer will still be 8-byte aligned.
- static_assert(sizeof(unsigned) * 2 >= llvm::AlignOf<Decl>::Alignment,
+ static_assert(sizeof(unsigned) * 2 >= alignof(Decl),
"Decl won't be misaligned");
void *Start = Context.Allocate(Size + Extra + 8);
void *Result = (char*)Start + 8;
@@ -81,8 +79,7 @@ void *Decl::operator new(std::size_t Size, const ASTContext &Ctx,
// Ensure required alignment of the resulting object by adding extra
// padding at the start if required.
size_t ExtraAlign =
- llvm::OffsetToAlignment(sizeof(Module *),
- llvm::AlignOf<Decl>::Alignment);
+ llvm::OffsetToAlignment(sizeof(Module *), alignof(Decl));
char *Buffer = reinterpret_cast<char *>(
::operator new(ExtraAlign + sizeof(Module *) + Size + Extra, Ctx));
Buffer += ExtraAlign;
@@ -112,12 +109,24 @@ const char *Decl::getDeclKindName() const {
void Decl::setInvalidDecl(bool Invalid) {
InvalidDecl = Invalid;
assert(!isa<TagDecl>(this) || !cast<TagDecl>(this)->isCompleteDefinition());
- if (Invalid && !isa<ParmVarDecl>(this)) {
+ if (!Invalid) {
+ return;
+ }
+
+ if (!isa<ParmVarDecl>(this)) {
// Defensive maneuver for ill-formed code: we're likely not to make it to
// a point where we set the access specifier, so default it to "public"
// to avoid triggering asserts elsewhere in the front end.
setAccess(AS_public);
}
+
+ // Marking a DecompositionDecl as invalid implies all the child BindingDecl's
+ // are invalid too.
+ if (DecompositionDecl *DD = dyn_cast<DecompositionDecl>(this)) {
+ for (BindingDecl *Binding : DD->bindings()) {
+ Binding->setInvalidDecl();
+ }
+ }
}
const char *DeclContext::getDeclKindName() const {
@@ -378,6 +387,22 @@ bool Decl::isReferenced() const {
return false;
}
+bool Decl::isExported() const {
+ if (isModulePrivate())
+ return false;
+ // Namespaces are always exported.
+ if (isa<TranslationUnitDecl>(this) || isa<NamespaceDecl>(this))
+ return true;
+ // Otherwise, this is a strictly lexical check.
+ for (auto *DC = getLexicalDeclContext(); DC; DC = DC->getLexicalParent()) {
+ if (cast<Decl>(DC)->isModulePrivate())
+ return false;
+ if (isa<ExportDecl>(DC))
+ return true;
+ }
+ return false;
+}
+
bool Decl::hasDefiningAttr() const {
return hasAttr<AliasAttr>() || hasAttr<IFuncAttr>();
}
@@ -401,11 +426,12 @@ const Attr *Decl::getDefiningAttr() const {
/// diagnostics.
static AvailabilityResult CheckAvailability(ASTContext &Context,
const AvailabilityAttr *A,
- std::string *Message) {
- VersionTuple TargetMinVersion =
- Context.getTargetInfo().getPlatformMinVersion();
+ std::string *Message,
+ VersionTuple EnclosingVersion) {
+ if (EnclosingVersion.empty())
+ EnclosingVersion = Context.getTargetInfo().getPlatformMinVersion();
- if (TargetMinVersion.empty())
+ if (EnclosingVersion.empty())
return AR_Available;
// Check if this is an App Extension "platform", and if so chop off
@@ -450,7 +476,7 @@ static AvailabilityResult CheckAvailability(ASTContext &Context,
// Make sure that this declaration has already been introduced.
if (!A->getIntroduced().empty() &&
- TargetMinVersion < A->getIntroduced()) {
+ EnclosingVersion < A->getIntroduced()) {
if (Message) {
Message->clear();
llvm::raw_string_ostream Out(*Message);
@@ -464,7 +490,7 @@ static AvailabilityResult CheckAvailability(ASTContext &Context,
}
// Make sure that this declaration hasn't been obsoleted.
- if (!A->getObsoleted().empty() && TargetMinVersion >= A->getObsoleted()) {
+ if (!A->getObsoleted().empty() && EnclosingVersion >= A->getObsoleted()) {
if (Message) {
Message->clear();
llvm::raw_string_ostream Out(*Message);
@@ -478,7 +504,7 @@ static AvailabilityResult CheckAvailability(ASTContext &Context,
}
// Make sure that this declaration hasn't been deprecated.
- if (!A->getDeprecated().empty() && TargetMinVersion >= A->getDeprecated()) {
+ if (!A->getDeprecated().empty() && EnclosingVersion >= A->getDeprecated()) {
if (Message) {
Message->clear();
llvm::raw_string_ostream Out(*Message);
@@ -494,9 +520,10 @@ static AvailabilityResult CheckAvailability(ASTContext &Context,
return AR_Available;
}
-AvailabilityResult Decl::getAvailability(std::string *Message) const {
+AvailabilityResult Decl::getAvailability(std::string *Message,
+ VersionTuple EnclosingVersion) const {
if (auto *FTD = dyn_cast<FunctionTemplateDecl>(this))
- return FTD->getTemplatedDecl()->getAvailability(Message);
+ return FTD->getTemplatedDecl()->getAvailability(Message, EnclosingVersion);
AvailabilityResult Result = AR_Available;
std::string ResultMessage;
@@ -521,7 +548,7 @@ AvailabilityResult Decl::getAvailability(std::string *Message) const {
if (const auto *Availability = dyn_cast<AvailabilityAttr>(A)) {
AvailabilityResult AR = CheckAvailability(getASTContext(), Availability,
- Message);
+ Message, EnclosingVersion);
if (AR == AR_Unavailable)
return AR_Unavailable;
@@ -580,8 +607,8 @@ bool Decl::isWeakImported() const {
return true;
if (const auto *Availability = dyn_cast<AvailabilityAttr>(A)) {
- if (CheckAvailability(getASTContext(), Availability,
- nullptr) == AR_NotYetIntroduced)
+ if (CheckAvailability(getASTContext(), Availability, nullptr,
+ VersionTuple()) == AR_NotYetIntroduced)
return true;
}
}
@@ -599,6 +626,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case CXXConversion:
case EnumConstant:
case Var:
+ case Binding:
case ImplicitParam:
case ParmVar:
case ObjCMethod:
@@ -623,11 +651,13 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case Typedef:
case TypeAlias:
case TypeAliasTemplate:
- case UnresolvedUsingTypename:
case TemplateTypeParm:
case ObjCTypeParam:
return IDNS_Ordinary | IDNS_Type;
+ case UnresolvedUsingTypename:
+ return IDNS_Ordinary | IDNS_Type | IDNS_Using;
+
case UsingShadow:
return 0; // we'll actually overwrite this later
@@ -635,6 +665,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
return IDNS_Ordinary | IDNS_Using;
case Using:
+ case UsingPack:
return IDNS_Using;
case ObjCProtocol:
@@ -670,6 +701,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case FriendTemplate:
case AccessSpec:
case LinkageSpec:
+ case Export:
case FileScopeAsm:
case StaticAssert:
case ObjCPropertyImpl:
@@ -679,6 +711,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case Captured:
case TranslationUnit:
case ExternCContext:
+ case Decomposition:
case UsingDirective:
case BuiltinTemplate:
@@ -954,7 +987,7 @@ bool DeclContext::isDependentContext() const {
bool DeclContext::isTransparentContext() const {
if (DeclKind == Decl::Enum)
return !cast<EnumDecl>(this)->isScoped();
- else if (DeclKind == Decl::LinkageSpec)
+ else if (DeclKind == Decl::LinkageSpec || DeclKind == Decl::Export)
return true;
return false;
@@ -974,6 +1007,18 @@ bool DeclContext::isExternCContext() const {
return isLinkageSpecContext(this, clang::LinkageSpecDecl::lang_c);
}
+const LinkageSpecDecl *DeclContext::getExternCContext() const {
+ const DeclContext *DC = this;
+ while (DC->getDeclKind() != Decl::TranslationUnit) {
+ if (DC->getDeclKind() == Decl::LinkageSpec &&
+ cast<LinkageSpecDecl>(DC)->getLanguage() ==
+ clang::LinkageSpecDecl::lang_c)
+ return cast<LinkageSpecDecl>(DC);
+ DC = DC->getLexicalParent();
+ }
+ return nullptr;
+}
+
bool DeclContext::isExternCXXContext() const {
return isLinkageSpecContext(this, clang::LinkageSpecDecl::lang_cxx);
}
@@ -993,6 +1038,7 @@ DeclContext *DeclContext::getPrimaryContext() {
case Decl::TranslationUnit:
case Decl::ExternCContext:
case Decl::LinkageSpec:
+ case Decl::Export:
case Decl::Block:
case Decl::Captured:
case Decl::OMPDeclareReduction:
@@ -1405,8 +1451,8 @@ NamedDecl *const DeclContextLookupResult::SingleElementDummyList = nullptr;
DeclContext::lookup_result
DeclContext::lookup(DeclarationName Name) const {
- assert(DeclKind != Decl::LinkageSpec &&
- "Should not perform lookups into linkage specs!");
+ assert(DeclKind != Decl::LinkageSpec && DeclKind != Decl::Export &&
+ "should not perform lookups into transparent contexts");
const DeclContext *PrimaryContext = getPrimaryContext();
if (PrimaryContext != this)
@@ -1467,8 +1513,8 @@ DeclContext::lookup(DeclarationName Name) const {
DeclContext::lookup_result
DeclContext::noload_lookup(DeclarationName Name) {
- assert(DeclKind != Decl::LinkageSpec &&
- "Should not perform lookups into linkage specs!");
+ assert(DeclKind != Decl::LinkageSpec && DeclKind != Decl::Export &&
+ "should not perform lookups into transparent contexts");
DeclContext *PrimaryContext = getPrimaryContext();
if (PrimaryContext != this)
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 81f94148d6ed..a9db65a51518 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -533,6 +533,12 @@ void CXXRecordDecl::addedMember(Decl *D) {
} else if (Constructor->isMoveConstructor())
SMKind |= SMF_MoveConstructor;
}
+
+ // C++11 [dcl.init.aggr]p1: DR1518
+ // An aggregate is an array or a class with no user-provided, explicit, or
+ // inherited constructors
+ if (Constructor->isUserProvided() || Constructor->isExplicit())
+ data().Aggregate = false;
}
// Handle constructors, including those inherited from base classes.
@@ -546,20 +552,6 @@ void CXXRecordDecl::addedMember(Decl *D) {
// constructor [...]
if (Constructor->isConstexpr() && !Constructor->isCopyOrMoveConstructor())
data().HasConstexprNonCopyMoveConstructor = true;
-
- // C++ [dcl.init.aggr]p1:
- // An aggregate is an array or a class with no user-declared
- // constructors [...].
- // C++11 [dcl.init.aggr]p1:
- // An aggregate is an array or a class with no user-provided
- // constructors [...].
- // C++11 [dcl.init.aggr]p1:
- // An aggregate is an array or a class with no user-provided
- // constructors (including those inherited from a base class) [...].
- if (getASTContext().getLangOpts().CPlusPlus11
- ? Constructor->isUserProvided()
- : !Constructor->isImplicit())
- data().Aggregate = false;
}
// Handle destructors.
@@ -739,7 +731,7 @@ void CXXRecordDecl::addedMember(Decl *D) {
}
if (!Field->hasInClassInitializer() && !Field->isMutable()) {
- if (CXXRecordDecl *FieldType = Field->getType()->getAsCXXRecordDecl()) {
+ if (CXXRecordDecl *FieldType = T->getAsCXXRecordDecl()) {
if (FieldType->hasDefinition() && !FieldType->allowConstDefaultInit())
data().HasUninitializedFields = true;
} else {
@@ -989,8 +981,12 @@ void CXXRecordDecl::addedMember(Decl *D) {
if (UsingDecl *Using = dyn_cast<UsingDecl>(D)) {
if (Using->getDeclName().getNameKind() ==
- DeclarationName::CXXConstructorName)
+ DeclarationName::CXXConstructorName) {
data().HasInheritedConstructor = true;
+ // C++1z [dcl.init.aggr]p1:
+ // An aggregate is [...] a class [...] with no inherited constructors
+ data().Aggregate = false;
+ }
if (Using->getDeclName().getCXXOverloadedOperator() == OO_Equal)
data().HasInheritedAssignment = true;
@@ -1107,6 +1103,12 @@ CXXRecordDecl::getGenericLambdaTemplateParameterList() const {
return nullptr;
}
+Decl *CXXRecordDecl::getLambdaContextDecl() const {
+ assert(isLambda() && "Not a lambda closure type!");
+ ExternalASTSource *Source = getParentASTContext().getExternalSource();
+ return getLambdaData().ContextDecl.get(Source);
+}
+
static CanQualType GetConversionType(ASTContext &Context, NamedDecl *Conv) {
QualType T =
cast<CXXConversionDecl>(Conv->getUnderlyingDecl()->getAsFunction())
@@ -1571,17 +1573,35 @@ bool CXXMethodDecl::isUsualDeallocationFunction() const {
// deallocation function. [...]
if (getNumParams() == 1)
return true;
-
- // C++ [basic.stc.dynamic.deallocation]p2:
+ unsigned UsualParams = 1;
+
+ // C++ <=14 [basic.stc.dynamic.deallocation]p2:
// [...] If class T does not declare such an operator delete but does
// declare a member deallocation function named operator delete with
// exactly two parameters, the second of which has type std::size_t (18.1),
// then this function is a usual deallocation function.
+ //
+ // C++17 says a usual deallocation function is one with the signature
+ // (void* [, size_t] [, std::align_val_t] [, ...])
+ // and all such functions are usual deallocation functions. It's not clear
+ // that allowing varargs functions was intentional.
ASTContext &Context = getASTContext();
- if (getNumParams() != 2 ||
- !Context.hasSameUnqualifiedType(getParamDecl(1)->getType(),
- Context.getSizeType()))
+ if (UsualParams < getNumParams() &&
+ Context.hasSameUnqualifiedType(getParamDecl(UsualParams)->getType(),
+ Context.getSizeType()))
+ ++UsualParams;
+
+ if (UsualParams < getNumParams() &&
+ getParamDecl(UsualParams)->getType()->isAlignValT())
+ ++UsualParams;
+
+ if (UsualParams != getNumParams())
return false;
+
+ // In C++17 onwards, all potential usual deallocation functions are actual
+ // usual deallocation functions.
+ if (Context.getLangOpts().AlignedAllocation)
+ return true;
// This function is a usual deallocation function if there are no
// single-parameter deallocation functions of the same kind.
@@ -1714,7 +1734,7 @@ CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context,
SourceLocation EllipsisLoc)
: Initializee(TInfo), MemberOrEllipsisLocation(EllipsisLoc), Init(Init),
LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(IsVirtual),
- IsWritten(false), SourceOrderOrNumArrayIndices(0)
+ IsWritten(false), SourceOrder(0)
{
}
@@ -1725,7 +1745,7 @@ CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context,
SourceLocation R)
: Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init),
LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false),
- IsWritten(false), SourceOrderOrNumArrayIndices(0)
+ IsWritten(false), SourceOrder(0)
{
}
@@ -1736,7 +1756,7 @@ CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context,
SourceLocation R)
: Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init),
LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false),
- IsWritten(false), SourceOrderOrNumArrayIndices(0)
+ IsWritten(false), SourceOrder(0)
{
}
@@ -1746,38 +1766,10 @@ CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context,
SourceLocation R)
: Initializee(TInfo), MemberOrEllipsisLocation(), Init(Init),
LParenLoc(L), RParenLoc(R), IsDelegating(true), IsVirtual(false),
- IsWritten(false), SourceOrderOrNumArrayIndices(0)
+ IsWritten(false), SourceOrder(0)
{
}
-CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context,
- FieldDecl *Member,
- SourceLocation MemberLoc,
- SourceLocation L, Expr *Init,
- SourceLocation R,
- VarDecl **Indices,
- unsigned NumIndices)
- : Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init),
- LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false),
- IsWritten(false), SourceOrderOrNumArrayIndices(NumIndices)
-{
- std::uninitialized_copy(Indices, Indices + NumIndices,
- getTrailingObjects<VarDecl *>());
-}
-
-CXXCtorInitializer *CXXCtorInitializer::Create(ASTContext &Context,
- FieldDecl *Member,
- SourceLocation MemberLoc,
- SourceLocation L, Expr *Init,
- SourceLocation R,
- VarDecl **Indices,
- unsigned NumIndices) {
- void *Mem = Context.Allocate(totalSizeToAlloc<VarDecl *>(NumIndices),
- llvm::alignOf<CXXCtorInitializer>());
- return new (Mem) CXXCtorInitializer(Context, Member, MemberLoc, L, Init, R,
- Indices, NumIndices);
-}
-
TypeLoc CXXCtorInitializer::getBaseClassLoc() const {
if (isBaseInitializer())
return Initializee.get<TypeSourceInfo*>()->getTypeLoc();
@@ -2253,15 +2245,37 @@ SourceRange UsingDecl::getSourceRange() const {
return SourceRange(Begin, getNameInfo().getEndLoc());
}
+void UsingPackDecl::anchor() { }
+
+UsingPackDecl *UsingPackDecl::Create(ASTContext &C, DeclContext *DC,
+ NamedDecl *InstantiatedFrom,
+ ArrayRef<NamedDecl *> UsingDecls) {
+ size_t Extra = additionalSizeToAlloc<NamedDecl *>(UsingDecls.size());
+ return new (C, DC, Extra) UsingPackDecl(DC, InstantiatedFrom, UsingDecls);
+}
+
+UsingPackDecl *UsingPackDecl::CreateDeserialized(ASTContext &C, unsigned ID,
+ unsigned NumExpansions) {
+ size_t Extra = additionalSizeToAlloc<NamedDecl *>(NumExpansions);
+ auto *Result = new (C, ID, Extra) UsingPackDecl(nullptr, nullptr, None);
+ Result->NumExpansions = NumExpansions;
+ auto *Trail = Result->getTrailingObjects<NamedDecl *>();
+ for (unsigned I = 0; I != NumExpansions; ++I)
+ new (Trail + I) NamedDecl*(nullptr);
+ return Result;
+}
+
void UnresolvedUsingValueDecl::anchor() { }
UnresolvedUsingValueDecl *
UnresolvedUsingValueDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation UsingLoc,
NestedNameSpecifierLoc QualifierLoc,
- const DeclarationNameInfo &NameInfo) {
+ const DeclarationNameInfo &NameInfo,
+ SourceLocation EllipsisLoc) {
return new (C, DC) UnresolvedUsingValueDecl(DC, C.DependentTy, UsingLoc,
- QualifierLoc, NameInfo);
+ QualifierLoc, NameInfo,
+ EllipsisLoc);
}
UnresolvedUsingValueDecl *
@@ -2269,7 +2283,8 @@ UnresolvedUsingValueDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
return new (C, ID) UnresolvedUsingValueDecl(nullptr, QualType(),
SourceLocation(),
NestedNameSpecifierLoc(),
- DeclarationNameInfo());
+ DeclarationNameInfo(),
+ SourceLocation());
}
SourceRange UnresolvedUsingValueDecl::getSourceRange() const {
@@ -2286,17 +2301,18 @@ UnresolvedUsingTypenameDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation TypenameLoc,
NestedNameSpecifierLoc QualifierLoc,
SourceLocation TargetNameLoc,
- DeclarationName TargetName) {
+ DeclarationName TargetName,
+ SourceLocation EllipsisLoc) {
return new (C, DC) UnresolvedUsingTypenameDecl(
DC, UsingLoc, TypenameLoc, QualifierLoc, TargetNameLoc,
- TargetName.getAsIdentifierInfo());
+ TargetName.getAsIdentifierInfo(), EllipsisLoc);
}
UnresolvedUsingTypenameDecl *
UnresolvedUsingTypenameDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
return new (C, ID) UnresolvedUsingTypenameDecl(
nullptr, SourceLocation(), SourceLocation(), NestedNameSpecifierLoc(),
- SourceLocation(), nullptr);
+ SourceLocation(), nullptr, SourceLocation());
}
void StaticAssertDecl::anchor() { }
@@ -2317,6 +2333,70 @@ StaticAssertDecl *StaticAssertDecl::CreateDeserialized(ASTContext &C,
nullptr, SourceLocation(), false);
}
+void BindingDecl::anchor() {}
+
+BindingDecl *BindingDecl::Create(ASTContext &C, DeclContext *DC,
+ SourceLocation IdLoc, IdentifierInfo *Id) {
+ return new (C, DC) BindingDecl(DC, IdLoc, Id);
+}
+
+BindingDecl *BindingDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
+ return new (C, ID) BindingDecl(nullptr, SourceLocation(), nullptr);
+}
+
+VarDecl *BindingDecl::getHoldingVar() const {
+ Expr *B = getBinding();
+ if (!B)
+ return nullptr;
+ auto *DRE = dyn_cast<DeclRefExpr>(B->IgnoreImplicit());
+ if (!DRE)
+ return nullptr;
+
+ auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
+ assert(VD->isImplicit() && "holding var for binding decl not implicit");
+ return VD;
+}
+
+void DecompositionDecl::anchor() {}
+
+DecompositionDecl *DecompositionDecl::Create(ASTContext &C, DeclContext *DC,
+ SourceLocation StartLoc,
+ SourceLocation LSquareLoc,
+ QualType T, TypeSourceInfo *TInfo,
+ StorageClass SC,
+ ArrayRef<BindingDecl *> Bindings) {
+ size_t Extra = additionalSizeToAlloc<BindingDecl *>(Bindings.size());
+ return new (C, DC, Extra)
+ DecompositionDecl(C, DC, StartLoc, LSquareLoc, T, TInfo, SC, Bindings);
+}
+
+DecompositionDecl *DecompositionDecl::CreateDeserialized(ASTContext &C,
+ unsigned ID,
+ unsigned NumBindings) {
+ size_t Extra = additionalSizeToAlloc<BindingDecl *>(NumBindings);
+ auto *Result = new (C, ID, Extra)
+ DecompositionDecl(C, nullptr, SourceLocation(), SourceLocation(),
+ QualType(), nullptr, StorageClass(), None);
+ // Set up and clean out the bindings array.
+ Result->NumBindings = NumBindings;
+ auto *Trail = Result->getTrailingObjects<BindingDecl *>();
+ for (unsigned I = 0; I != NumBindings; ++I)
+ new (Trail + I) BindingDecl*(nullptr);
+ return Result;
+}
+
+void DecompositionDecl::printName(llvm::raw_ostream &os) const {
+ os << '[';
+ bool Comma = false;
+ for (auto *B : bindings()) {
+ if (Comma)
+ os << ", ";
+ B->printName(os);
+ Comma = true;
+ }
+ os << ']';
+}
+
MSPropertyDecl *MSPropertyDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L, DeclarationName N,
QualType T, TypeSourceInfo *TInfo,
diff --git a/lib/AST/DeclGroup.cpp b/lib/AST/DeclGroup.cpp
index f162e6d40c48..2f95e1f1c345 100644
--- a/lib/AST/DeclGroup.cpp
+++ b/lib/AST/DeclGroup.cpp
@@ -14,13 +14,12 @@
#include "clang/AST/DeclGroup.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
-#include "llvm/Support/Allocator.h"
using namespace clang;
DeclGroup* DeclGroup::Create(ASTContext &C, Decl **Decls, unsigned NumDecls) {
assert(NumDecls > 1 && "Invalid DeclGroup");
unsigned Size = totalSizeToAlloc<Decl *>(NumDecls);
- void* Mem = C.Allocate(Size, llvm::AlignOf<DeclGroup>::Alignment);
+ void *Mem = C.Allocate(Size, alignof(DeclGroup));
new (Mem) DeclGroup(NumDecls, Decls);
return static_cast<DeclGroup*>(Mem);
}
diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp
index d2701211beae..60d05f682e6e 100644
--- a/lib/AST/DeclObjC.cpp
+++ b/lib/AST/DeclObjC.cpp
@@ -800,8 +800,7 @@ void ObjCMethodDecl::setParamsAndSelLocs(ASTContext &C,
if (Params.empty() && SelLocs.empty())
return;
- static_assert(llvm::AlignOf<ParmVarDecl *>::Alignment >=
- llvm::AlignOf<SourceLocation>::Alignment,
+ static_assert(alignof(ParmVarDecl *) >= alignof(SourceLocation),
"Alignment not sufficient for SourceLocation");
unsigned Size = sizeof(ParmVarDecl *) * NumParams +
@@ -871,6 +870,12 @@ ObjCMethodDecl *ObjCMethodDecl::getNextRedeclarationImpl() {
}
}
+ // Ensure that the discovered method redeclaration has a valid declaration
+ // context. Used to prevent infinite loops when iterating redeclarations in
+ // a partially invalid AST.
+ if (Redecl && cast<Decl>(Redecl->getDeclContext())->isInvalidDecl())
+ Redecl = nullptr;
+
if (!Redecl && isRedeclaration()) {
// This is the last redeclaration, go back to the first method.
return cast<ObjCContainerDecl>(CtxD)->getMethod(getSelector(),
@@ -897,9 +902,13 @@ ObjCMethodDecl *ObjCMethodDecl::getCanonicalDecl() {
return MD;
}
- if (isRedeclaration())
- return cast<ObjCContainerDecl>(CtxD)->getMethod(getSelector(),
- isInstanceMethod());
+ if (isRedeclaration()) {
+ // It is possible that we have not done deserializing the ObjCMethod yet.
+ ObjCMethodDecl *MD =
+ cast<ObjCContainerDecl>(CtxD)->getMethod(getSelector(),
+ isInstanceMethod());
+ return MD ? MD : this;
+ }
return this;
}
@@ -1320,8 +1329,12 @@ ObjCTypeParamDecl *ObjCTypeParamDecl::Create(ASTContext &ctx, DeclContext *dc,
IdentifierInfo *name,
SourceLocation colonLoc,
TypeSourceInfo *boundInfo) {
- return new (ctx, dc) ObjCTypeParamDecl(ctx, dc, variance, varianceLoc, index,
- nameLoc, name, colonLoc, boundInfo);
+ auto *TPDecl =
+ new (ctx, dc) ObjCTypeParamDecl(ctx, dc, variance, varianceLoc, index,
+ nameLoc, name, colonLoc, boundInfo);
+ QualType TPType = ctx.getObjCTypeParamType(TPDecl, {});
+ TPDecl->setTypeForDecl(TPType.getTypePtr());
+ return TPDecl;
}
ObjCTypeParamDecl *ObjCTypeParamDecl::CreateDeserialized(ASTContext &ctx,
@@ -1366,7 +1379,7 @@ ObjCTypeParamList *ObjCTypeParamList::create(
SourceLocation rAngleLoc) {
void *mem =
ctx.Allocate(totalSizeToAlloc<ObjCTypeParamDecl *>(typeParams.size()),
- llvm::alignOf<ObjCTypeParamList>());
+ alignof(ObjCTypeParamList));
return new (mem) ObjCTypeParamList(lAngleLoc, typeParams, rAngleLoc);
}
diff --git a/lib/AST/DeclOpenMP.cpp b/lib/AST/DeclOpenMP.cpp
index 5b06ce0778a7..95e44acca032 100644
--- a/lib/AST/DeclOpenMP.cpp
+++ b/lib/AST/DeclOpenMP.cpp
@@ -90,13 +90,18 @@ OMPDeclareReductionDecl::getPrevDeclInScope() const {
void OMPCapturedExprDecl::anchor() {}
OMPCapturedExprDecl *OMPCapturedExprDecl::Create(ASTContext &C, DeclContext *DC,
- IdentifierInfo *Id,
- QualType T) {
- return new (C, DC) OMPCapturedExprDecl(C, DC, Id, T);
+ IdentifierInfo *Id, QualType T,
+ SourceLocation StartLoc) {
+ return new (C, DC) OMPCapturedExprDecl(C, DC, Id, T, StartLoc);
}
OMPCapturedExprDecl *OMPCapturedExprDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
- return new (C, ID) OMPCapturedExprDecl(C, nullptr, nullptr, QualType());
+ return new (C, ID)
+ OMPCapturedExprDecl(C, nullptr, nullptr, QualType(), SourceLocation());
}
+SourceRange OMPCapturedExprDecl::getSourceRange() const {
+ assert(hasInit());
+ return SourceRange(getInit()->getLocStart(), getInit()->getLocEnd());
+}
diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp
index 7e786990becb..b8ebe1c568c7 100644
--- a/lib/AST/DeclPrinter.cpp
+++ b/lib/AST/DeclPrinter.cpp
@@ -78,6 +78,10 @@ namespace {
void VisitTemplateDecl(const TemplateDecl *D);
void VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
void VisitClassTemplateDecl(ClassTemplateDecl *D);
+ void VisitClassTemplateSpecializationDecl(
+ ClassTemplateSpecializationDecl *D);
+ void VisitClassTemplatePartialSpecializationDecl(
+ ClassTemplatePartialSpecializationDecl *D);
void VisitObjCMethodDecl(ObjCMethodDecl *D);
void VisitObjCImplementationDecl(ObjCImplementationDecl *D);
void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
@@ -95,8 +99,9 @@ namespace {
void VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D);
void VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D);
- void PrintTemplateParameters(const TemplateParameterList *Params,
- const TemplateArgumentList *Args = nullptr);
+ void printTemplateParameters(const TemplateParameterList *Params);
+ void printTemplateArguments(const TemplateArgumentList &Args,
+ const TemplateParameterList *Params = nullptr);
void prettyPrintAttributes(Decl *D);
void prettyPrintPragmas(Decl *D);
void printDeclType(QualType T, StringRef DeclName, bool Pack = false);
@@ -290,6 +295,13 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) {
if (D->isImplicit())
continue;
+ // Don't print implicit specializations, as they are printed when visiting
+ // corresponding templates.
+ if (auto FD = dyn_cast<FunctionDecl>(*D))
+ if (FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation &&
+ !isa<ClassTemplateSpecializationDecl>(DC))
+ continue;
+
// The next bits of code handles 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
@@ -337,12 +349,19 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) {
const char *Terminator = nullptr;
if (isa<OMPThreadPrivateDecl>(*D) || isa<OMPDeclareReductionDecl>(*D))
Terminator = nullptr;
- else if (isa<FunctionDecl>(*D) &&
- cast<FunctionDecl>(*D)->isThisDeclarationADefinition())
+ else if (isa<ObjCMethodDecl>(*D) && cast<ObjCMethodDecl>(*D)->hasBody())
Terminator = nullptr;
- else if (isa<ObjCMethodDecl>(*D) && cast<ObjCMethodDecl>(*D)->getBody())
- Terminator = nullptr;
- else if (isa<NamespaceDecl>(*D) || isa<LinkageSpecDecl>(*D) ||
+ else if (auto FD = dyn_cast<FunctionDecl>(*D)) {
+ if (FD->isThisDeclarationADefinition())
+ Terminator = nullptr;
+ else
+ Terminator = ";";
+ } else if (auto TD = dyn_cast<FunctionTemplateDecl>(*D)) {
+ if (TD->getTemplatedDecl()->isThisDeclarationADefinition())
+ Terminator = nullptr;
+ else
+ Terminator = ";";
+ } else if (isa<NamespaceDecl>(*D) || isa<LinkageSpecDecl>(*D) ||
isa<ObjCImplementationDecl>(*D) ||
isa<ObjCInterfaceDecl>(*D) ||
isa<ObjCProtocolDecl>(*D) ||
@@ -359,7 +378,14 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) {
if (Terminator)
Out << Terminator;
- Out << "\n";
+ if (!Policy.TerseOutput &&
+ ((isa<FunctionDecl>(*D) &&
+ cast<FunctionDecl>(*D)->doesThisDeclarationHaveABody()) ||
+ (isa<FunctionTemplateDecl>(*D) &&
+ cast<FunctionTemplateDecl>(*D)->getTemplatedDecl()->doesThisDeclarationHaveABody())))
+ ; // StmtPrinter already added '\n' after CompoundStmt.
+ else
+ Out << "\n";
// Declare target attribute is special one, natural spelling for the pragma
// assumes "ending" construct so print it here.
@@ -408,7 +434,7 @@ void DeclPrinter::VisitEnumDecl(EnumDecl *D) {
}
Out << *D;
- if (D->isFixed())
+ if (D->isFixed() && D->getASTContext().getLangOpts().CPlusPlus11)
Out << " : " << D->getIntegerType().stream(Policy);
if (D->isCompleteDefinition()) {
@@ -449,6 +475,9 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
!D->isFunctionTemplateSpecialization())
prettyPrintPragmas(D);
+ if (D->isFunctionTemplateSpecialization())
+ Out << "template<> ";
+
CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D);
CXXConversionDecl *ConversionDecl = dyn_cast<CXXConversionDecl>(D);
if (!Policy.SuppressSpecifiers) {
@@ -473,6 +502,11 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
PrintingPolicy SubPolicy(Policy);
SubPolicy.SuppressSpecifiers = false;
std::string Proto = D->getNameInfo().getAsString();
+ if (const TemplateArgumentList *TArgs = D->getTemplateSpecializationArgs()) {
+ llvm::raw_string_ostream POut(Proto);
+ DeclPrinter TArgPrinter(POut, SubPolicy, Indentation);
+ TArgPrinter.printTemplateArguments(*TArgs);
+ }
QualType Ty = D->getType();
while (const ParenType *PT = dyn_cast<ParenType>(Ty)) {
@@ -636,25 +670,29 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
Out << " = delete";
else if (D->isExplicitlyDefaulted())
Out << " = default";
- else if (D->doesThisDeclarationHaveABody() && !Policy.TerseOutput) {
- if (!D->hasPrototype() && D->getNumParams()) {
- // This is a K&R function definition, so we need to print the
- // parameters.
- Out << '\n';
- DeclPrinter ParamPrinter(Out, SubPolicy, Indentation);
- Indentation += Policy.Indentation;
- for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) {
- Indent();
- ParamPrinter.VisitParmVarDecl(D->getParamDecl(i));
- Out << ";\n";
- }
- Indentation -= Policy.Indentation;
- } else
- Out << ' ';
+ else if (D->doesThisDeclarationHaveABody()) {
+ if (!Policy.TerseOutput) {
+ if (!D->hasPrototype() && D->getNumParams()) {
+ // This is a K&R function definition, so we need to print the
+ // parameters.
+ Out << '\n';
+ DeclPrinter ParamPrinter(Out, SubPolicy, Indentation);
+ Indentation += Policy.Indentation;
+ for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) {
+ Indent();
+ ParamPrinter.VisitParmVarDecl(D->getParamDecl(i));
+ Out << ";\n";
+ }
+ Indentation -= Policy.Indentation;
+ } else
+ Out << ' ';
- if (D->getBody())
- D->getBody()->printPretty(Out, nullptr, SubPolicy, Indentation);
- Out << '\n';
+ if (D->getBody())
+ D->getBody()->printPretty(Out, nullptr, SubPolicy, Indentation);
+ } else {
+ if (isa<CXXConstructorDecl>(*D))
+ Out << " {}";
+ }
}
}
@@ -662,7 +700,7 @@ void DeclPrinter::VisitFriendDecl(FriendDecl *D) {
if (TypeSourceInfo *TSI = D->getFriendType()) {
unsigned NumTPLists = D->getFriendTypeNumTemplateParameterLists();
for (unsigned i = 0; i < NumTPLists; ++i)
- PrintTemplateParameters(D->getFriendTypeTemplateParameterList(i));
+ printTemplateParameters(D->getFriendTypeTemplateParameterList(i));
Out << "friend ";
Out << " " << TSI->getType().getAsString(Policy);
}
@@ -839,9 +877,15 @@ void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
prettyPrintAttributes(D);
- if (D->getIdentifier())
+ if (D->getIdentifier()) {
Out << ' ' << *D;
+ if (auto S = dyn_cast<ClassTemplatePartialSpecializationDecl>(D))
+ printTemplateArguments(S->getTemplateArgs(), S->getTemplateParameters());
+ else if (auto S = dyn_cast<ClassTemplateSpecializationDecl>(D))
+ printTemplateArguments(S->getTemplateArgs());
+ }
+
if (D->isCompleteDefinition()) {
// Print the base classes
if (D->getNumBases()) {
@@ -868,9 +912,13 @@ void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
// Print the class definition
// FIXME: Doesn't print access specifiers, e.g., "public:"
- Out << " {\n";
- VisitDeclContext(D);
- Indent() << "}";
+ if (Policy.TerseOutput) {
+ Out << " {}";
+ } else {
+ Out << " {\n";
+ VisitDeclContext(D);
+ Indent() << "}";
+ }
}
}
@@ -893,10 +941,8 @@ void DeclPrinter::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
Visit(*D->decls_begin());
}
-void DeclPrinter::PrintTemplateParameters(const TemplateParameterList *Params,
- const TemplateArgumentList *Args) {
+void DeclPrinter::printTemplateParameters(const TemplateParameterList *Params) {
assert(Params);
- assert(!Args || Params->size() == Args->size());
Out << "template <";
@@ -905,8 +951,7 @@ void DeclPrinter::PrintTemplateParameters(const TemplateParameterList *Params,
Out << ", ";
const Decl *Param = Params->getParam(i);
- if (const TemplateTypeParmDecl *TTP =
- dyn_cast<TemplateTypeParmDecl>(Param)) {
+ if (auto TTP = dyn_cast<TemplateTypeParmDecl>(Param)) {
if (TTP->wasDeclaredWithTypename())
Out << "typename ";
@@ -918,30 +963,22 @@ void DeclPrinter::PrintTemplateParameters(const TemplateParameterList *Params,
Out << *TTP;
- if (Args) {
- Out << " = ";
- Args->get(i).print(Policy, Out);
- } else if (TTP->hasDefaultArgument()) {
+ if (TTP->hasDefaultArgument()) {
Out << " = ";
Out << TTP->getDefaultArgument().getAsString(Policy);
};
- } else if (const NonTypeTemplateParmDecl *NTTP =
- dyn_cast<NonTypeTemplateParmDecl>(Param)) {
+ } else if (auto NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
StringRef Name;
if (IdentifierInfo *II = NTTP->getIdentifier())
Name = II->getName();
printDeclType(NTTP->getType(), Name, NTTP->isParameterPack());
- if (Args) {
- Out << " = ";
- Args->get(i).print(Policy, Out);
- } else if (NTTP->hasDefaultArgument()) {
+ if (NTTP->hasDefaultArgument()) {
Out << " = ";
NTTP->getDefaultArgument()->printPretty(Out, nullptr, Policy,
Indentation);
}
- } else if (const TemplateTemplateParmDecl *TTPD =
- dyn_cast<TemplateTemplateParmDecl>(Param)) {
+ } else if (auto TTPD = dyn_cast<TemplateTemplateParmDecl>(Param)) {
VisitTemplateDecl(TTPD);
// FIXME: print the default argument, if present.
}
@@ -950,8 +987,46 @@ void DeclPrinter::PrintTemplateParameters(const TemplateParameterList *Params,
Out << "> ";
}
+void DeclPrinter::printTemplateArguments(const TemplateArgumentList &Args,
+ const TemplateParameterList *Params) {
+ Out << "<";
+ for (size_t I = 0, E = Args.size(); I < E; ++I) {
+ const TemplateArgument &A = Args[I];
+ if (I)
+ Out << ", ";
+ if (Params) {
+ if (A.getKind() == TemplateArgument::Type)
+ if (auto T = A.getAsType()->getAs<TemplateTypeParmType>()) {
+ auto P = cast<TemplateTypeParmDecl>(Params->getParam(T->getIndex()));
+ Out << *P;
+ continue;
+ }
+ if (A.getKind() == TemplateArgument::Template) {
+ if (auto T = A.getAsTemplate().getAsTemplateDecl())
+ if (auto TD = dyn_cast<TemplateTemplateParmDecl>(T)) {
+ auto P = cast<TemplateTemplateParmDecl>(
+ Params->getParam(TD->getIndex()));
+ Out << *P;
+ continue;
+ }
+ }
+ if (A.getKind() == TemplateArgument::Expression) {
+ if (auto E = dyn_cast<DeclRefExpr>(A.getAsExpr()))
+ if (auto N = dyn_cast<NonTypeTemplateParmDecl>(E->getDecl())) {
+ auto P = cast<NonTypeTemplateParmDecl>(
+ Params->getParam(N->getIndex()));
+ Out << *P;
+ continue;
+ }
+ }
+ }
+ A.print(Policy, Out);
+ }
+ Out << ">";
+}
+
void DeclPrinter::VisitTemplateDecl(const TemplateDecl *D) {
- PrintTemplateParameters(D->getTemplateParameters());
+ printTemplateParameters(D->getTemplateParameters());
if (const TemplateTemplateParmDecl *TTP =
dyn_cast<TemplateTemplateParmDecl>(D)) {
@@ -965,30 +1040,49 @@ void DeclPrinter::VisitTemplateDecl(const TemplateDecl *D) {
}
void DeclPrinter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
+ prettyPrintPragmas(D->getTemplatedDecl());
+ VisitRedeclarableTemplateDecl(D);
+
if (PrintInstantiation) {
- TemplateParameterList *Params = D->getTemplateParameters();
- for (auto *I : D->specializations()) {
- prettyPrintPragmas(I);
- PrintTemplateParameters(Params, I->getTemplateSpecializationArgs());
- Visit(I);
- }
+ FunctionDecl *PrevDecl = D->getTemplatedDecl();
+ const FunctionDecl *Def;
+ if (PrevDecl->isDefined(Def) && Def != PrevDecl)
+ return;
+ for (auto *I : D->specializations())
+ if (I->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) {
+ if (!PrevDecl->isThisDeclarationADefinition())
+ Out << ";\n";
+ Indent();
+ prettyPrintPragmas(I);
+ Visit(I);
+ }
}
-
- prettyPrintPragmas(D->getTemplatedDecl());
- return VisitRedeclarableTemplateDecl(D);
}
void DeclPrinter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
+ VisitRedeclarableTemplateDecl(D);
+
if (PrintInstantiation) {
- TemplateParameterList *Params = D->getTemplateParameters();
- for (auto *I : D->specializations()) {
- PrintTemplateParameters(Params, &I->getTemplateArgs());
- Visit(I);
- Out << '\n';
- }
+ for (auto *I : D->specializations())
+ if (I->getSpecializationKind() == TSK_ImplicitInstantiation) {
+ if (D->isThisDeclarationADefinition())
+ Out << ";";
+ Out << "\n";
+ Visit(I);
+ }
}
+}
+
+void DeclPrinter::VisitClassTemplateSpecializationDecl(
+ ClassTemplateSpecializationDecl *D) {
+ Out << "template<> ";
+ VisitCXXRecordDecl(D);
+}
- return VisitRedeclarableTemplateDecl(D);
+void DeclPrinter::VisitClassTemplatePartialSpecializationDecl(
+ ClassTemplatePartialSpecializationDecl *D) {
+ printTemplateParameters(D->getTemplateParameters());
+ VisitCXXRecordDecl(D);
}
//----------------------------------------------------------------------------
@@ -1346,6 +1440,17 @@ void DeclPrinter::VisitUsingDecl(UsingDecl *D) {
if (D->hasTypename())
Out << "typename ";
D->getQualifier()->print(Out, Policy);
+
+ // Use the correct record name when the using declaration is used for
+ // inheriting constructors.
+ for (const auto *Shadow : D->shadows()) {
+ if (const auto *ConstructorShadow =
+ dyn_cast<ConstructorUsingShadowDecl>(Shadow)) {
+ assert(Shadow->getDeclContext() == ConstructorShadow->getDeclContext());
+ Out << *ConstructorShadow->getNominatedBaseClass();
+ return;
+ }
+ }
Out << *D;
}
diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp
index 37943cdd5b7b..8643cbfcd960 100644
--- a/lib/AST/DeclTemplate.cpp
+++ b/lib/AST/DeclTemplate.cpp
@@ -31,10 +31,11 @@ using namespace clang;
TemplateParameterList::TemplateParameterList(SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
ArrayRef<NamedDecl *> Params,
- SourceLocation RAngleLoc)
+ SourceLocation RAngleLoc,
+ Expr *RequiresClause)
: TemplateLoc(TemplateLoc), LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc),
- NumParams(Params.size()), ContainsUnexpandedParameterPack(false) {
- assert(this->NumParams == NumParams && "Too many template parameters");
+ NumParams(Params.size()), ContainsUnexpandedParameterPack(false),
+ HasRequiresClause(static_cast<bool>(RequiresClause)) {
for (unsigned Idx = 0; Idx < NumParams; ++Idx) {
NamedDecl *P = Params[Idx];
begin()[Idx] = P;
@@ -52,15 +53,21 @@ TemplateParameterList::TemplateParameterList(SourceLocation TemplateLoc,
// template parameter list does too.
}
}
+ if (RequiresClause) {
+ *getTrailingObjects<Expr *>() = RequiresClause;
+ }
}
-TemplateParameterList *TemplateParameterList::Create(
- const ASTContext &C, SourceLocation TemplateLoc, SourceLocation LAngleLoc,
- ArrayRef<NamedDecl *> Params, SourceLocation RAngleLoc) {
- void *Mem = C.Allocate(totalSizeToAlloc<NamedDecl *>(Params.size()),
- llvm::alignOf<TemplateParameterList>());
+TemplateParameterList *
+TemplateParameterList::Create(const ASTContext &C, SourceLocation TemplateLoc,
+ SourceLocation LAngleLoc,
+ ArrayRef<NamedDecl *> Params,
+ SourceLocation RAngleLoc, Expr *RequiresClause) {
+ void *Mem = C.Allocate(totalSizeToAlloc<NamedDecl *, Expr *>(
+ Params.size(), RequiresClause ? 1u : 0u),
+ alignof(TemplateParameterList));
return new (Mem) TemplateParameterList(TemplateLoc, LAngleLoc, Params,
- RAngleLoc);
+ RAngleLoc, RequiresClause);
}
unsigned TemplateParameterList::getMinRequiredArguments() const {
@@ -197,44 +204,6 @@ void RedeclarableTemplateDecl::addSpecializationImpl(
SETraits::getDecl(Entry));
}
-/// \brief Generate the injected template arguments for the given template
-/// parameter list, e.g., for the injected-class-name of a class template.
-static void GenerateInjectedTemplateArgs(ASTContext &Context,
- TemplateParameterList *Params,
- TemplateArgument *Args) {
- for (NamedDecl *Param : *Params) {
- TemplateArgument Arg;
- if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) {
- QualType ArgType = Context.getTypeDeclType(TTP);
- if (TTP->isParameterPack())
- ArgType = Context.getPackExpansionType(ArgType, None);
-
- Arg = TemplateArgument(ArgType);
- } else if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
- Expr *E = new (Context) DeclRefExpr(NTTP, /*enclosing*/ false,
- NTTP->getType().getNonLValueExprType(Context),
- Expr::getValueKindForType(NTTP->getType()),
- NTTP->getLocation());
-
- if (NTTP->isParameterPack())
- E = new (Context) PackExpansionExpr(Context.DependentTy, E,
- NTTP->getLocation(), None);
- Arg = TemplateArgument(E);
- } else {
- auto *TTP = cast<TemplateTemplateParmDecl>(Param);
- if (TTP->isParameterPack())
- Arg = TemplateArgument(TemplateName(TTP), Optional<unsigned>());
- else
- Arg = TemplateArgument(TemplateName(TTP));
- }
-
- if (Param->isTemplateParameterPack())
- Arg = TemplateArgument::CreatePackCopy(Context, Arg);
-
- *Args++ = Arg;
- }
-}
-
//===----------------------------------------------------------------------===//
// FunctionTemplateDecl Implementation
//===----------------------------------------------------------------------===//
@@ -303,10 +272,13 @@ ArrayRef<TemplateArgument> FunctionTemplateDecl::getInjectedTemplateArgs() {
TemplateParameterList *Params = getTemplateParameters();
Common *CommonPtr = getCommonPtr();
if (!CommonPtr->InjectedArgs) {
- CommonPtr->InjectedArgs
- = new (getASTContext()) TemplateArgument[Params->size()];
- GenerateInjectedTemplateArgs(getASTContext(), Params,
- CommonPtr->InjectedArgs);
+ auto &Context = getASTContext();
+ SmallVector<TemplateArgument, 16> TemplateArgs;
+ Context.getInjectedTemplateArgs(Params, TemplateArgs);
+ CommonPtr->InjectedArgs =
+ new (Context) TemplateArgument[TemplateArgs.size()];
+ std::copy(TemplateArgs.begin(), TemplateArgs.end(),
+ CommonPtr->InjectedArgs);
}
return llvm::makeArrayRef(CommonPtr->InjectedArgs, Params->size());
@@ -457,8 +429,7 @@ ClassTemplateDecl::getInjectedClassNameSpecialization() {
ASTContext &Context = getASTContext();
TemplateParameterList *Params = getTemplateParameters();
SmallVector<TemplateArgument, 16> TemplateArgs;
- TemplateArgs.resize(Params->size());
- GenerateInjectedTemplateArgs(getASTContext(), Params, TemplateArgs.data());
+ Context.getInjectedTemplateArgs(Params, TemplateArgs);
CommonPtr->InjectedClassNameType
= Context.getTemplateSpecializationType(TemplateName(this),
TemplateArgs);
@@ -754,9 +725,16 @@ void ClassTemplateSpecializationDecl::getNameForDiagnostic(
raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const {
NamedDecl::getNameForDiagnostic(OS, Policy, Qualified);
- const TemplateArgumentList &TemplateArgs = getTemplateArgs();
- TemplateSpecializationType::PrintTemplateArgumentList(
- OS, TemplateArgs.asArray(), Policy);
+ auto *PS = dyn_cast<ClassTemplatePartialSpecializationDecl>(this);
+ if (const ASTTemplateArgumentListInfo *ArgsAsWritten =
+ PS ? PS->getTemplateArgsAsWritten() : nullptr) {
+ TemplateSpecializationType::PrintTemplateArgumentList(
+ OS, ArgsAsWritten->arguments(), Policy);
+ } else {
+ const TemplateArgumentList &TemplateArgs = getTemplateArgs();
+ TemplateSpecializationType::PrintTemplateArgumentList(
+ OS, TemplateArgs.asArray(), Policy);
+ }
}
ClassTemplateDecl *
@@ -1086,9 +1064,16 @@ void VarTemplateSpecializationDecl::getNameForDiagnostic(
raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const {
NamedDecl::getNameForDiagnostic(OS, Policy, Qualified);
- const TemplateArgumentList &TemplateArgs = getTemplateArgs();
- TemplateSpecializationType::PrintTemplateArgumentList(
- OS, TemplateArgs.asArray(), Policy);
+ auto *PS = dyn_cast<VarTemplatePartialSpecializationDecl>(this);
+ if (const ASTTemplateArgumentListInfo *ArgsAsWritten =
+ PS ? PS->getTemplateArgsAsWritten() : nullptr) {
+ TemplateSpecializationType::PrintTemplateArgumentList(
+ OS, ArgsAsWritten->arguments(), Policy);
+ } else {
+ const TemplateArgumentList &TemplateArgs = getTemplateArgs();
+ TemplateSpecializationType::PrintTemplateArgumentList(
+ OS, TemplateArgs.asArray(), Policy);
+ }
}
VarTemplateDecl *VarTemplateSpecializationDecl::getSpecializedTemplate() const {
@@ -1169,7 +1154,7 @@ createMakeIntegerSeqParameterList(const ASTContext &C, DeclContext *DC) {
// <typename T, T ...Ints>
NamedDecl *P[2] = {T, N};
auto *TPL = TemplateParameterList::Create(
- C, SourceLocation(), SourceLocation(), P, SourceLocation());
+ C, SourceLocation(), SourceLocation(), P, SourceLocation(), nullptr);
// template <typename T, ...Ints> class IntSeq
auto *TemplateTemplateParm = TemplateTemplateParmDecl::Create(
@@ -1194,7 +1179,7 @@ createMakeIntegerSeqParameterList(const ASTContext &C, DeclContext *DC) {
// template <template <typename T, T ...Ints> class IntSeq, typename T, T N>
return TemplateParameterList::Create(C, SourceLocation(), SourceLocation(),
- Params, SourceLocation());
+ Params, SourceLocation(), nullptr);
}
static TemplateParameterList *
@@ -1215,7 +1200,7 @@ createTypePackElementParameterList(const ASTContext &C, DeclContext *DC) {
NamedDecl *Params[] = {Index, Ts};
return TemplateParameterList::Create(C, SourceLocation(), SourceLocation(),
llvm::makeArrayRef(Params),
- SourceLocation());
+ SourceLocation(), nullptr);
}
static TemplateParameterList *createBuiltinTemplateParameterList(
diff --git a/lib/AST/DeclarationName.cpp b/lib/AST/DeclarationName.cpp
index 2a988e1d22d0..52791e51d2dc 100644
--- a/lib/AST/DeclarationName.cpp
+++ b/lib/AST/DeclarationName.cpp
@@ -11,14 +11,13 @@
// classes.
//
//===----------------------------------------------------------------------===//
+#include "clang/AST/DeclarationName.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclCXX.h"
-#include "clang/AST/DeclarationName.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeLoc.h"
#include "clang/AST/TypeOrdering.h"
#include "clang/Basic/IdentifierTable.h"
-#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
@@ -96,12 +95,18 @@ int DeclarationName::compare(DeclarationName LHS, DeclarationName RHS) {
case DeclarationName::ObjCMultiArgSelector: {
Selector LHSSelector = LHS.getObjCSelector();
Selector RHSSelector = RHS.getObjCSelector();
+ // getNumArgs for ZeroArgSelector returns 0, but we still need to compare.
+ if (LHS.getNameKind() == DeclarationName::ObjCZeroArgSelector &&
+ RHS.getNameKind() == DeclarationName::ObjCZeroArgSelector) {
+ return LHSSelector.getAsIdentifierInfo()->getName().compare(
+ RHSSelector.getAsIdentifierInfo()->getName());
+ }
unsigned LN = LHSSelector.getNumArgs(), RN = RHSSelector.getNumArgs();
for (unsigned I = 0, N = std::min(LN, RN); I != N; ++I) {
switch (LHSSelector.getNameForSlot(I).compare(
RHSSelector.getNameForSlot(I))) {
- case -1: return true;
- case 1: return false;
+ case -1: return -1;
+ case 1: return 1;
default: break;
}
}
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 091e8787d8b6..93f3ad5f2bdd 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -11,7 +11,6 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/AST/APValue.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
#include "clang/AST/DeclCXX.h"
@@ -36,9 +35,33 @@
#include <cstring>
using namespace clang;
-const CXXRecordDecl *Expr::getBestDynamicClassType() const {
- const Expr *E = ignoreParenBaseCasts();
+const Expr *Expr::getBestDynamicClassTypeExpr() const {
+ const Expr *E = this;
+ while (true) {
+ E = E->ignoreParenBaseCasts();
+
+ // Follow the RHS of a comma operator.
+ if (auto *BO = dyn_cast<BinaryOperator>(E)) {
+ if (BO->getOpcode() == BO_Comma) {
+ E = BO->getRHS();
+ continue;
+ }
+ }
+
+ // Step into initializer for materialized temporaries.
+ if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E)) {
+ E = MTE->GetTemporaryExpr();
+ continue;
+ }
+
+ break;
+ }
+
+ return E;
+}
+const CXXRecordDecl *Expr::getBestDynamicClassType() const {
+ const Expr *E = getBestDynamicClassTypeExpr();
QualType DerivedType = E->getType();
if (const PointerType *PTy = DerivedType->getAs<PointerType>())
DerivedType = PTy->getPointeeType();
@@ -403,7 +426,7 @@ DeclRefExpr *DeclRefExpr::Create(const ASTContext &Context,
HasTemplateKWAndArgsInfo ? 1 : 0,
TemplateArgs ? TemplateArgs->size() : 0);
- void *Mem = Context.Allocate(Size, llvm::alignOf<DeclRefExpr>());
+ void *Mem = Context.Allocate(Size, alignof(DeclRefExpr));
return new (Mem) DeclRefExpr(Context, QualifierLoc, TemplateKWLoc, D,
RefersToEnclosingVariableOrCapture,
NameInfo, FoundD, TemplateArgs, T, VK);
@@ -420,7 +443,7 @@ DeclRefExpr *DeclRefExpr::CreateEmpty(const ASTContext &Context,
ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
HasQualifier ? 1 : 0, HasFoundDecl ? 1 : 0, HasTemplateKWAndArgsInfo,
NumTemplateArgs);
- void *Mem = Context.Allocate(Size, llvm::alignOf<DeclRefExpr>());
+ void *Mem = Context.Allocate(Size, alignof(DeclRefExpr));
return new (Mem) DeclRefExpr(EmptyShell());
}
@@ -495,20 +518,21 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) {
}
return "";
}
- if (auto *BD = dyn_cast<BlockDecl>(CurrentDecl)) {
- std::unique_ptr<MangleContext> MC;
- MC.reset(Context.createMangleContext());
- SmallString<256> Buffer;
- llvm::raw_svector_ostream Out(Buffer);
+ if (isa<BlockDecl>(CurrentDecl)) {
+ // For blocks we only emit something if it is enclosed in a function
+ // For top-level block we'd like to include the name of variable, but we
+ // don't have it at this point.
auto DC = CurrentDecl->getDeclContext();
if (DC->isFileContext())
- MC->mangleGlobalBlock(BD, /*ID*/ nullptr, Out);
- else if (const auto *CD = dyn_cast<CXXConstructorDecl>(DC))
- MC->mangleCtorBlock(CD, /*CT*/ Ctor_Complete, BD, Out);
- else if (const auto *DD = dyn_cast<CXXDestructorDecl>(DC))
- MC->mangleDtorBlock(DD, /*DT*/ Dtor_Complete, BD, Out);
- else
- MC->mangleBlock(DC, BD, Out);
+ return "";
+
+ SmallString<256> Buffer;
+ llvm::raw_svector_ostream Out(Buffer);
+ if (auto *DCBlock = dyn_cast<BlockDecl>(DC))
+ // For nested blocks, propagate up to the parent.
+ Out << ComputeName(IT, DCBlock);
+ else if (auto *DCDecl = dyn_cast<Decl>(DC))
+ Out << ComputeName(IT, DCDecl) << "_block_invoke";
return Out.str();
}
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurrentDecl)) {
@@ -538,12 +562,14 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) {
FT = dyn_cast<FunctionProtoType>(AFT);
if (IT == FuncSig) {
+ assert(FT && "We must have a written prototype in this case.");
switch (FT->getCallConv()) {
case CC_C: POut << "__cdecl "; break;
case CC_X86StdCall: POut << "__stdcall "; break;
case CC_X86FastCall: POut << "__fastcall "; break;
case CC_X86ThisCall: POut << "__thiscall "; break;
case CC_X86VectorCall: POut << "__vectorcall "; break;
+ case CC_X86RegCall: POut << "__regcall "; break;
// Only bother printing the conventions that MSVC knows about.
default: break;
}
@@ -756,33 +782,33 @@ FloatingLiteral::Create(const ASTContext &C, EmptyShell Empty) {
const llvm::fltSemantics &FloatingLiteral::getSemantics() const {
switch(FloatingLiteralBits.Semantics) {
case IEEEhalf:
- return llvm::APFloat::IEEEhalf;
+ return llvm::APFloat::IEEEhalf();
case IEEEsingle:
- return llvm::APFloat::IEEEsingle;
+ return llvm::APFloat::IEEEsingle();
case IEEEdouble:
- return llvm::APFloat::IEEEdouble;
+ return llvm::APFloat::IEEEdouble();
case x87DoubleExtended:
- return llvm::APFloat::x87DoubleExtended;
+ return llvm::APFloat::x87DoubleExtended();
case IEEEquad:
- return llvm::APFloat::IEEEquad;
+ return llvm::APFloat::IEEEquad();
case PPCDoubleDouble:
- return llvm::APFloat::PPCDoubleDouble;
+ return llvm::APFloat::PPCDoubleDouble();
}
llvm_unreachable("Unrecognised floating semantics");
}
void FloatingLiteral::setSemantics(const llvm::fltSemantics &Sem) {
- if (&Sem == &llvm::APFloat::IEEEhalf)
+ if (&Sem == &llvm::APFloat::IEEEhalf())
FloatingLiteralBits.Semantics = IEEEhalf;
- else if (&Sem == &llvm::APFloat::IEEEsingle)
+ else if (&Sem == &llvm::APFloat::IEEEsingle())
FloatingLiteralBits.Semantics = IEEEsingle;
- else if (&Sem == &llvm::APFloat::IEEEdouble)
+ else if (&Sem == &llvm::APFloat::IEEEdouble())
FloatingLiteralBits.Semantics = IEEEdouble;
- else if (&Sem == &llvm::APFloat::x87DoubleExtended)
+ else if (&Sem == &llvm::APFloat::x87DoubleExtended())
FloatingLiteralBits.Semantics = x87DoubleExtended;
- else if (&Sem == &llvm::APFloat::IEEEquad)
+ else if (&Sem == &llvm::APFloat::IEEEquad())
FloatingLiteralBits.Semantics = IEEEquad;
- else if (&Sem == &llvm::APFloat::PPCDoubleDouble)
+ else if (&Sem == &llvm::APFloat::PPCDoubleDouble())
FloatingLiteralBits.Semantics = PPCDoubleDouble;
else
llvm_unreachable("Unknown floating semantics");
@@ -794,7 +820,7 @@ void FloatingLiteral::setSemantics(const llvm::fltSemantics &Sem) {
double FloatingLiteral::getValueAsApproximateDouble() const {
llvm::APFloat V = getValue();
bool ignored;
- V.convert(llvm::APFloat::IEEEdouble, llvm::APFloat::rmNearestTiesToEven,
+ V.convert(llvm::APFloat::IEEEdouble(), llvm::APFloat::rmNearestTiesToEven,
&ignored);
return V.convertToDouble();
}
@@ -832,9 +858,9 @@ StringLiteral *StringLiteral::Create(const ASTContext &C, StringRef Str,
// Allocate enough space for the StringLiteral plus an array of locations for
// any concatenated string tokens.
- void *Mem = C.Allocate(sizeof(StringLiteral)+
- sizeof(SourceLocation)*(NumStrs-1),
- llvm::alignOf<StringLiteral>());
+ void *Mem =
+ C.Allocate(sizeof(StringLiteral) + sizeof(SourceLocation) * (NumStrs - 1),
+ alignof(StringLiteral));
StringLiteral *SL = new (Mem) StringLiteral(Ty);
// OPTIMIZE: could allocate this appended to the StringLiteral.
@@ -850,9 +876,9 @@ StringLiteral *StringLiteral::Create(const ASTContext &C, StringRef Str,
StringLiteral *StringLiteral::CreateEmpty(const ASTContext &C,
unsigned NumStrs) {
- void *Mem = C.Allocate(sizeof(StringLiteral)+
- sizeof(SourceLocation)*(NumStrs-1),
- llvm::alignOf<StringLiteral>());
+ void *Mem =
+ C.Allocate(sizeof(StringLiteral) + sizeof(SourceLocation) * (NumStrs - 1),
+ alignof(StringLiteral));
StringLiteral *SL = new (Mem) StringLiteral(QualType());
SL->CharByteWidth = 0;
SL->Length = 0;
@@ -944,10 +970,13 @@ void StringLiteral::outputString(raw_ostream &OS) const {
// Handle some common non-printable cases to make dumps prettier.
case '\\': OS << "\\\\"; break;
case '"': OS << "\\\""; break;
- case '\n': OS << "\\n"; break;
- case '\t': OS << "\\t"; break;
case '\a': OS << "\\a"; break;
case '\b': OS << "\\b"; break;
+ case '\f': OS << "\\f"; break;
+ case '\n': OS << "\\n"; break;
+ case '\r': OS << "\\r"; break;
+ case '\t': OS << "\\t"; break;
+ case '\v': OS << "\\v"; break;
}
}
OS << '"';
@@ -1182,8 +1211,16 @@ void CallExpr::updateDependenciesFromArg(Expr *Arg) {
ExprBits.ContainsUnexpandedParameterPack = true;
}
+FunctionDecl *CallExpr::getDirectCallee() {
+ return dyn_cast_or_null<FunctionDecl>(getCalleeDecl());
+}
+
Decl *CallExpr::getCalleeDecl() {
- Expr *CEE = getCallee()->IgnoreParenImpCasts();
+ return getCallee()->getReferencedDeclOfCallee();
+}
+
+Decl *Expr::getReferencedDeclOfCallee() {
+ Expr *CEE = IgnoreParenImpCasts();
while (SubstNonTypeTemplateParmExpr *NTTP
= dyn_cast<SubstNonTypeTemplateParmExpr>(CEE)) {
@@ -1206,10 +1243,6 @@ Decl *CallExpr::getCalleeDecl() {
return nullptr;
}
-FunctionDecl *CallExpr::getDirectCallee() {
- return dyn_cast_or_null<FunctionDecl>(getCalleeDecl());
-}
-
/// setNumArgs - This changes the number of arguments present in this call.
/// Any orphaned expressions are deleted by this, and any new operands are set
/// to null.
@@ -1417,7 +1450,7 @@ MemberExpr *MemberExpr::Create(
HasTemplateKWAndArgsInfo ? 1 : 0,
targs ? targs->size() : 0);
- void *Mem = C.Allocate(Size, llvm::alignOf<MemberExpr>());
+ void *Mem = C.Allocate(Size, alignof(MemberExpr));
MemberExpr *E = new (Mem)
MemberExpr(base, isarrow, OperatorLoc, memberdecl, nameinfo, ty, vk, ok);
@@ -1570,6 +1603,8 @@ bool CastExpr::CastConsistency() const {
case CK_ARCReclaimReturnedObject:
case CK_ARCExtendBlockObject:
case CK_ZeroToOCLEvent:
+ case CK_ZeroToOCLQueue:
+ case CK_IntToOCLSampler:
assert(!getType()->isBooleanType() && "unheralded conversion to bool");
goto CheckNoBasePath;
@@ -1830,6 +1865,24 @@ bool InitListExpr::isStringLiteralInit() const {
return isa<StringLiteral>(Init) || isa<ObjCEncodeExpr>(Init);
}
+bool InitListExpr::isTransparent() const {
+ assert(isSemanticForm() && "syntactic form never semantically transparent");
+
+ // A glvalue InitListExpr is always just sugar.
+ if (isGLValue()) {
+ assert(getNumInits() == 1 && "multiple inits in glvalue init list");
+ return true;
+ }
+
+ // Otherwise, we're sugar if and only if we have exactly one initializer that
+ // is of the same type.
+ if (getNumInits() != 1 || !getInit(0))
+ return false;
+
+ return getType().getCanonicalType() ==
+ getInit(0)->getType().getCanonicalType();
+}
+
SourceLocation InitListExpr::getLocStart() const {
if (InitListExpr *SyntacticForm = getSyntacticForm())
return SyntacticForm->getLocStart();
@@ -2212,12 +2265,15 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc,
// effects (e.g. a placement new with an uninitialized POD).
case CXXDeleteExprClass:
return false;
+ case MaterializeTemporaryExprClass:
+ return cast<MaterializeTemporaryExpr>(this)->GetTemporaryExpr()
+ ->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx);
case CXXBindTemporaryExprClass:
- return (cast<CXXBindTemporaryExpr>(this)
- ->getSubExpr()->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx));
+ return cast<CXXBindTemporaryExpr>(this)->getSubExpr()
+ ->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx);
case ExprWithCleanupsClass:
- return (cast<ExprWithCleanups>(this)
- ->getSubExpr()->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx));
+ return cast<ExprWithCleanups>(this)->getSubExpr()
+ ->isUnusedResultAWarning(WarnE, Loc, R1, R2, Ctx);
}
}
@@ -2748,7 +2804,8 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef,
CE->getCastKind() == CK_ToUnion ||
CE->getCastKind() == CK_ConstructorConversion ||
CE->getCastKind() == CK_NonAtomicToAtomic ||
- CE->getCastKind() == CK_AtomicToNonAtomic)
+ CE->getCastKind() == CK_AtomicToNonAtomic ||
+ CE->getCastKind() == CK_IntToOCLSampler)
return CE->getSubExpr()->isConstantInitializer(Ctx, false, Culprit);
break;
@@ -2843,6 +2900,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
case UnaryExprOrTypeTraitExprClass:
case AddrLabelExprClass:
case GNUNullExprClass:
+ case ArrayInitIndexExprClass:
case NoInitExprClass:
case CXXBoolLiteralExprClass:
case CXXNullPtrLiteralExprClass:
@@ -2919,6 +2977,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
case ExtVectorElementExprClass:
case DesignatedInitExprClass:
case DesignatedInitUpdateExprClass:
+ case ArrayInitLoopExprClass:
case ParenListExprClass:
case CXXPseudoDestructorExprClass:
case CXXStdInitializerListExprClass:
@@ -3307,11 +3366,16 @@ FieldDecl *Expr::getSourceBitField() {
if (Ivar->isBitField())
return Ivar;
- if (DeclRefExpr *DeclRef = dyn_cast<DeclRefExpr>(E))
+ if (DeclRefExpr *DeclRef = dyn_cast<DeclRefExpr>(E)) {
if (FieldDecl *Field = dyn_cast<FieldDecl>(DeclRef->getDecl()))
if (Field->isBitField())
return Field;
+ if (BindingDecl *BD = dyn_cast<BindingDecl>(DeclRef->getDecl()))
+ if (Expr *E = BD->getBinding())
+ return E->getSourceBitField();
+ }
+
if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(E)) {
if (BinOp->isAssignmentOp() && BinOp->getLHS())
return BinOp->getLHS()->getSourceBitField();
@@ -3328,6 +3392,7 @@ FieldDecl *Expr::getSourceBitField() {
}
bool Expr::refersToVectorElement() const {
+ // FIXME: Why do we not just look at the ObjectKind here?
const Expr *E = this->IgnoreParens();
while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
@@ -3344,6 +3409,11 @@ bool Expr::refersToVectorElement() const {
if (isa<ExtVectorElementExpr>(E))
return true;
+ if (auto *DRE = dyn_cast<DeclRefExpr>(E))
+ if (auto *BD = dyn_cast<BindingDecl>(DRE->getDecl()))
+ if (auto *E = BD->getBinding())
+ return E->refersToVectorElement();
+
return false;
}
@@ -3396,8 +3466,11 @@ bool ExtVectorElementExpr::containsDuplicateElements() const {
void ExtVectorElementExpr::getEncodedElementAccess(
SmallVectorImpl<uint32_t> &Elts) const {
StringRef Comp = Accessor->getName();
- if (Comp[0] == 's' || Comp[0] == 'S')
+ bool isNumericAccessor = false;
+ if (Comp[0] == 's' || Comp[0] == 'S') {
Comp = Comp.substr(1);
+ isNumericAccessor = true;
+ }
bool isHi = Comp == "hi";
bool isLo = Comp == "lo";
@@ -3416,7 +3489,7 @@ void ExtVectorElementExpr::getEncodedElementAccess(
else if (isOdd)
Index = 2 * i + 1;
else
- Index = ExtVectorType::getAccessorIdx(Comp[i]);
+ Index = ExtVectorType::getAccessorIdx(Comp[i], isNumericAccessor);
Elts.push_back(Index);
}
@@ -3589,7 +3662,7 @@ DesignatedInitExpr::Create(const ASTContext &C,
SourceLocation ColonOrEqualLoc,
bool UsesColonSyntax, Expr *Init) {
void *Mem = C.Allocate(totalSizeToAlloc<Stmt *>(IndexExprs.size() + 1),
- llvm::alignOf<DesignatedInitExpr>());
+ alignof(DesignatedInitExpr));
return new (Mem) DesignatedInitExpr(C, C.VoidTy, Designators,
ColonOrEqualLoc, UsesColonSyntax,
IndexExprs, Init);
@@ -3598,7 +3671,7 @@ DesignatedInitExpr::Create(const ASTContext &C,
DesignatedInitExpr *DesignatedInitExpr::CreateEmpty(const ASTContext &C,
unsigned NumIndexExprs) {
void *Mem = C.Allocate(totalSizeToAlloc<Stmt *>(NumIndexExprs + 1),
- llvm::alignOf<DesignatedInitExpr>());
+ alignof(DesignatedInitExpr));
return new (Mem) DesignatedInitExpr(NumIndexExprs + 1);
}
@@ -3738,7 +3811,7 @@ PseudoObjectExpr *PseudoObjectExpr::Create(const ASTContext &Context,
unsigned numSemanticExprs) {
void *buffer =
Context.Allocate(totalSizeToAlloc<Expr *>(1 + numSemanticExprs),
- llvm::alignOf<PseudoObjectExpr>());
+ alignof(PseudoObjectExpr));
return new(buffer) PseudoObjectExpr(sh, numSemanticExprs);
}
@@ -3766,7 +3839,7 @@ PseudoObjectExpr *PseudoObjectExpr::Create(const ASTContext &C, Expr *syntax,
}
void *buffer = C.Allocate(totalSizeToAlloc<Expr *>(semantics.size() + 1),
- llvm::alignOf<PseudoObjectExpr>());
+ alignof(PseudoObjectExpr));
return new(buffer) PseudoObjectExpr(type, VK, syntax, semantics,
resultIndex);
}
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index a13033d47467..ad510e0070e6 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -25,6 +25,22 @@ using namespace clang;
// Child Iterators for iterating over subexpressions/substatements
//===----------------------------------------------------------------------===//
+bool CXXOperatorCallExpr::isInfixBinaryOp() const {
+ // An infix binary operator is any operator with two arguments other than
+ // operator() and operator[]. Note that none of these operators can have
+ // default arguments, so it suffices to check the number of argument
+ // expressions.
+ if (getNumArgs() != 2)
+ return false;
+
+ switch (getOperator()) {
+ case OO_Call: case OO_Subscript:
+ return false;
+ default:
+ return true;
+ }
+}
+
bool CXXTypeidExpr::isPotentiallyEvaluated() const {
if (isTypeOperand())
return false;
@@ -62,7 +78,7 @@ SourceLocation CXXScalarValueInitExpr::getLocStart() const {
// CXXNewExpr
CXXNewExpr::CXXNewExpr(const ASTContext &C, bool globalNew,
FunctionDecl *operatorNew, FunctionDecl *operatorDelete,
- bool usualArrayDeleteWantsSize,
+ bool PassAlignment, bool usualArrayDeleteWantsSize,
ArrayRef<Expr*> placementArgs,
SourceRange typeIdParens, Expr *arraySize,
InitializationStyle initializationStyle,
@@ -76,7 +92,8 @@ CXXNewExpr::CXXNewExpr(const ASTContext &C, bool globalNew,
SubExprs(nullptr), OperatorNew(operatorNew), OperatorDelete(operatorDelete),
AllocatedTypeInfo(allocatedTypeInfo), TypeIdParens(typeIdParens),
Range(Range), DirectInitRange(directInitRange),
- GlobalNew(globalNew), UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize) {
+ GlobalNew(globalNew), PassAlignment(PassAlignment),
+ UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize) {
assert((initializer != nullptr || initializationStyle == NoInit) &&
"Only NoInit can have no initializer.");
StoredInitializationStyle = initializer ? initializationStyle + 1 : 0;
@@ -226,7 +243,7 @@ UnresolvedLookupExpr::Create(const ASTContext &C,
std::size_t Size =
totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(1,
num_args);
- void *Mem = C.Allocate(Size, llvm::alignOf<UnresolvedLookupExpr>());
+ void *Mem = C.Allocate(Size, alignof(UnresolvedLookupExpr));
return new (Mem) UnresolvedLookupExpr(C, NamingClass, QualifierLoc,
TemplateKWLoc, NameInfo,
ADL, /*Overload*/ true, Args,
@@ -241,7 +258,7 @@ UnresolvedLookupExpr::CreateEmpty(const ASTContext &C,
std::size_t Size =
totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
HasTemplateKWAndArgsInfo, NumTemplateArgs);
- void *Mem = C.Allocate(Size, llvm::alignOf<UnresolvedLookupExpr>());
+ void *Mem = C.Allocate(Size, alignof(UnresolvedLookupExpr));
UnresolvedLookupExpr *E = new (Mem) UnresolvedLookupExpr(EmptyShell());
E->HasTemplateKWAndArgsInfo = HasTemplateKWAndArgsInfo;
return E;
@@ -284,9 +301,8 @@ OverloadExpr::OverloadExpr(StmtClass K, const ASTContext &C,
}
}
- Results = static_cast<DeclAccessPair *>(
- C.Allocate(sizeof(DeclAccessPair) * NumResults,
- llvm::alignOf<DeclAccessPair>()));
+ Results = static_cast<DeclAccessPair *>(C.Allocate(
+ sizeof(DeclAccessPair) * NumResults, alignof(DeclAccessPair)));
memcpy(Results, Begin.I, NumResults * sizeof(DeclAccessPair));
}
@@ -323,11 +339,11 @@ void OverloadExpr::initializeResults(const ASTContext &C,
assert(!Results && "Results already initialized!");
NumResults = End - Begin;
if (NumResults) {
- Results = static_cast<DeclAccessPair *>(
- C.Allocate(sizeof(DeclAccessPair) * NumResults,
-
- llvm::alignOf<DeclAccessPair>()));
- memcpy(Results, Begin.I, NumResults * sizeof(DeclAccessPair));
+ Results = static_cast<DeclAccessPair *>(
+ C.Allocate(sizeof(DeclAccessPair) * NumResults,
+
+ alignof(DeclAccessPair)));
+ memcpy(Results, Begin.I, NumResults * sizeof(DeclAccessPair));
}
}
@@ -853,8 +869,6 @@ LambdaExpr::LambdaExpr(QualType T, SourceRange IntroducerRange,
SourceLocation CaptureDefaultLoc,
ArrayRef<LambdaCapture> Captures, bool ExplicitParams,
bool ExplicitResultType, ArrayRef<Expr *> CaptureInits,
- ArrayRef<VarDecl *> ArrayIndexVars,
- ArrayRef<unsigned> ArrayIndexStarts,
SourceLocation ClosingBrace,
bool ContainsUnexpandedParameterPack)
: Expr(LambdaExprClass, T, VK_RValue, OK_Ordinary, T->isDependentType(),
@@ -891,17 +905,6 @@ LambdaExpr::LambdaExpr(QualType T, SourceRange IntroducerRange,
// Copy the body of the lambda.
*Stored++ = getCallOperator()->getBody();
-
- // Copy the array index variables, if any.
- HasArrayIndexVars = !ArrayIndexVars.empty();
- if (HasArrayIndexVars) {
- assert(ArrayIndexStarts.size() == NumCaptures);
- memcpy(getArrayIndexVars(), ArrayIndexVars.data(),
- sizeof(VarDecl *) * ArrayIndexVars.size());
- memcpy(getArrayIndexStarts(), ArrayIndexStarts.data(),
- sizeof(unsigned) * Captures.size());
- getArrayIndexStarts()[Captures.size()] = ArrayIndexVars.size();
- }
}
LambdaExpr *LambdaExpr::Create(
@@ -909,31 +912,24 @@ LambdaExpr *LambdaExpr::Create(
SourceRange IntroducerRange, LambdaCaptureDefault CaptureDefault,
SourceLocation CaptureDefaultLoc, ArrayRef<LambdaCapture> Captures,
bool ExplicitParams, bool ExplicitResultType, ArrayRef<Expr *> CaptureInits,
- ArrayRef<VarDecl *> ArrayIndexVars, ArrayRef<unsigned> ArrayIndexStarts,
SourceLocation ClosingBrace, bool ContainsUnexpandedParameterPack) {
// Determine the type of the expression (i.e., the type of the
// function object we're creating).
QualType T = Context.getTypeDeclType(Class);
- unsigned Size = totalSizeToAlloc<Stmt *, unsigned, VarDecl *>(
- Captures.size() + 1, ArrayIndexVars.empty() ? 0 : Captures.size() + 1,
- ArrayIndexVars.size());
+ unsigned Size = totalSizeToAlloc<Stmt *>(Captures.size() + 1);
void *Mem = Context.Allocate(Size);
- return new (Mem) LambdaExpr(T, IntroducerRange,
- CaptureDefault, CaptureDefaultLoc, Captures,
- ExplicitParams, ExplicitResultType,
- CaptureInits, ArrayIndexVars, ArrayIndexStarts,
- ClosingBrace, ContainsUnexpandedParameterPack);
+ return new (Mem)
+ LambdaExpr(T, IntroducerRange, CaptureDefault, CaptureDefaultLoc,
+ Captures, ExplicitParams, ExplicitResultType, CaptureInits,
+ ClosingBrace, ContainsUnexpandedParameterPack);
}
LambdaExpr *LambdaExpr::CreateDeserialized(const ASTContext &C,
- unsigned NumCaptures,
- unsigned NumArrayIndexVars) {
- unsigned Size = totalSizeToAlloc<Stmt *, unsigned, VarDecl *>(
- NumCaptures + 1, NumArrayIndexVars ? NumCaptures + 1 : 0,
- NumArrayIndexVars);
+ unsigned NumCaptures) {
+ unsigned Size = totalSizeToAlloc<Stmt *>(NumCaptures + 1);
void *Mem = C.Allocate(Size);
- return new (Mem) LambdaExpr(EmptyShell(), NumCaptures, NumArrayIndexVars > 0);
+ return new (Mem) LambdaExpr(EmptyShell(), NumCaptures);
}
bool LambdaExpr::isInitCapture(const LambdaCapture *C) const {
@@ -979,19 +975,6 @@ LambdaExpr::capture_range LambdaExpr::implicit_captures() const {
return capture_range(implicit_capture_begin(), implicit_capture_end());
}
-ArrayRef<VarDecl *>
-LambdaExpr::getCaptureInitIndexVars(const_capture_init_iterator Iter) const {
- assert(HasArrayIndexVars && "No array index-var data?");
-
- unsigned Index = Iter - capture_init_begin();
- assert(Index < getLambdaClass()->getLambdaData().NumCaptures &&
- "Capture index out-of-range");
- VarDecl *const *IndexVars = getArrayIndexVars();
- const unsigned *IndexStarts = getArrayIndexStarts();
- return llvm::makeArrayRef(IndexVars + IndexStarts[Index],
- IndexVars + IndexStarts[Index + 1]);
-}
-
CXXRecordDecl *LambdaExpr::getLambdaClass() const {
return getType()->getAsCXXRecordDecl();
}
@@ -1041,7 +1024,7 @@ ExprWithCleanups *ExprWithCleanups::Create(const ASTContext &C, Expr *subexpr,
bool CleanupsHaveSideEffects,
ArrayRef<CleanupObject> objects) {
void *buffer = C.Allocate(totalSizeToAlloc<CleanupObject>(objects.size()),
- llvm::alignOf<ExprWithCleanups>());
+ alignof(ExprWithCleanups));
return new (buffer)
ExprWithCleanups(subexpr, CleanupsHaveSideEffects, objects);
}
@@ -1055,7 +1038,7 @@ ExprWithCleanups *ExprWithCleanups::Create(const ASTContext &C,
EmptyShell empty,
unsigned numObjects) {
void *buffer = C.Allocate(totalSizeToAlloc<CleanupObject>(numObjects),
- llvm::alignOf<ExprWithCleanups>());
+ alignof(ExprWithCleanups));
return new (buffer) ExprWithCleanups(empty, numObjects);
}
@@ -1154,7 +1137,7 @@ CXXDependentScopeMemberExpr::Create(const ASTContext &C,
totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
HasTemplateKWAndArgsInfo, NumTemplateArgs);
- void *Mem = C.Allocate(Size, llvm::alignOf<CXXDependentScopeMemberExpr>());
+ void *Mem = C.Allocate(Size, alignof(CXXDependentScopeMemberExpr));
return new (Mem) CXXDependentScopeMemberExpr(C, Base, BaseType,
IsArrow, OperatorLoc,
QualifierLoc,
@@ -1171,7 +1154,7 @@ CXXDependentScopeMemberExpr::CreateEmpty(const ASTContext &C,
std::size_t Size =
totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
HasTemplateKWAndArgsInfo, NumTemplateArgs);
- void *Mem = C.Allocate(Size, llvm::alignOf<CXXDependentScopeMemberExpr>());
+ void *Mem = C.Allocate(Size, alignof(CXXDependentScopeMemberExpr));
CXXDependentScopeMemberExpr *E
= new (Mem) CXXDependentScopeMemberExpr(C, nullptr, QualType(),
0, SourceLocation(),
@@ -1255,7 +1238,7 @@ UnresolvedMemberExpr *UnresolvedMemberExpr::Create(
totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
HasTemplateKWAndArgsInfo, TemplateArgs ? TemplateArgs->size() : 0);
- void *Mem = C.Allocate(Size, llvm::alignOf<UnresolvedMemberExpr>());
+ void *Mem = C.Allocate(Size, alignof(UnresolvedMemberExpr));
return new (Mem) UnresolvedMemberExpr(
C, HasUnresolvedUsing, Base, BaseType, IsArrow, OperatorLoc, QualifierLoc,
TemplateKWLoc, MemberNameInfo, TemplateArgs, Begin, End);
@@ -1270,7 +1253,7 @@ UnresolvedMemberExpr::CreateEmpty(const ASTContext &C,
totalSizeToAlloc<ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
HasTemplateKWAndArgsInfo, NumTemplateArgs);
- void *Mem = C.Allocate(Size, llvm::alignOf<UnresolvedMemberExpr>());
+ void *Mem = C.Allocate(Size, alignof(UnresolvedMemberExpr));
UnresolvedMemberExpr *E = new (Mem) UnresolvedMemberExpr(EmptyShell());
E->HasTemplateKWAndArgsInfo = HasTemplateKWAndArgsInfo;
return E;
diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp
index 89cc9bc18ef0..adb74b80b198 100644
--- a/lib/AST/ExprClassification.cpp
+++ b/lib/AST/ExprClassification.cpp
@@ -141,10 +141,9 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
return Cl::CL_LValue;
// C99 6.5.2.5p5 says that compound literals are lvalues.
- // In C++, they're prvalue temporaries.
+ // In C++, they're prvalue temporaries, except for file-scope arrays.
case Expr::CompoundLiteralExprClass:
- return Ctx.getLangOpts().CPlusPlus ? ClassifyTemporary(E->getType())
- : Cl::CL_LValue;
+ return !E->isLValue() ? ClassifyTemporary(E->getType()) : Cl::CL_LValue;
// Expressions that are prvalues.
case Expr::CXXBoolLiteralExprClass:
@@ -186,6 +185,8 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
case Expr::ObjCIndirectCopyRestoreExprClass:
case Expr::AtomicExprClass:
case Expr::CXXFoldExprClass:
+ case Expr::ArrayInitLoopExprClass:
+ case Expr::ArrayInitIndexExprClass:
case Expr::NoInitExprClass:
case Expr::DesignatedInitUpdateExprClass:
case Expr::CoyieldExprClass:
@@ -196,11 +197,20 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
return ClassifyInternal(Ctx,
cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement());
- // C++ [expr.sub]p1: The result is an lvalue of type "T".
- // However, subscripting vector types is more like member access.
+ // C, C++98 [expr.sub]p1: The result is an lvalue of type "T".
+ // C++11 (DR1213): in the case of an array operand, the result is an lvalue
+ // if that operand is an lvalue and an xvalue otherwise.
+ // Subscripting vector types is more like member access.
case Expr::ArraySubscriptExprClass:
if (cast<ArraySubscriptExpr>(E)->getBase()->getType()->isVectorType())
return ClassifyInternal(Ctx, cast<ArraySubscriptExpr>(E)->getBase());
+ if (Lang.CPlusPlus11) {
+ // Step over the array-to-pointer decay if present, but not over the
+ // temporary materialization.
+ auto *Base = cast<ArraySubscriptExpr>(E)->getBase()->IgnoreImpCasts();
+ if (Base->getType()->isArrayType())
+ return ClassifyInternal(Ctx, Base);
+ }
return Cl::CL_LValue;
// C++ [expr.prim.general]p3: The result is an lvalue if the entity is a
@@ -429,6 +439,7 @@ static Cl::Kinds ClassifyDecl(ASTContext &Ctx, const Decl *D) {
else
islvalue = isa<VarDecl>(D) || isa<FieldDecl>(D) ||
isa<IndirectFieldDecl>(D) ||
+ isa<BindingDecl>(D) ||
(Ctx.getLangOpts().CPlusPlus &&
(isa<FunctionDecl>(D) || isa<MSPropertyDecl>(D) ||
isa<FunctionTemplateDecl>(D)));
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index df944e8f25f2..b3f8925b6464 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -36,6 +36,7 @@
#include "clang/AST/APValue.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTDiagnostic.h"
+#include "clang/AST/ASTLambda.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/Expr.h"
#include "clang/AST/RecordLayout.h"
@@ -43,7 +44,6 @@
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/TargetInfo.h"
-#include "llvm/ADT/SmallString.h"
#include "llvm/Support/raw_ostream.h"
#include <cstring>
#include <functional>
@@ -76,8 +76,8 @@ namespace {
const Expr *Inner = Temp->skipRValueSubobjectAdjustments(CommaLHSs,
Adjustments);
// Keep any cv-qualifiers from the reference if we generated a temporary
- // for it.
- if (Inner != Temp)
+ // for it directly. Otherwise use the type after adjustment.
+ if (!Adjustments.empty())
return Inner->getType();
}
@@ -109,19 +109,57 @@ namespace {
return getAsBaseOrMember(E).getInt();
}
+ /// Given a CallExpr, try to get the alloc_size attribute. May return null.
+ static const AllocSizeAttr *getAllocSizeAttr(const CallExpr *CE) {
+ const FunctionDecl *Callee = CE->getDirectCallee();
+ return Callee ? Callee->getAttr<AllocSizeAttr>() : nullptr;
+ }
+
+ /// Attempts to unwrap a CallExpr (with an alloc_size attribute) from an Expr.
+ /// This will look through a single cast.
+ ///
+ /// Returns null if we couldn't unwrap a function with alloc_size.
+ static const CallExpr *tryUnwrapAllocSizeCall(const Expr *E) {
+ if (!E->getType()->isPointerType())
+ return nullptr;
+
+ 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.
+ if (const auto *Cast = dyn_cast<CastExpr>(E))
+ E = Cast->getSubExpr()->IgnoreParens();
+
+ if (const auto *CE = dyn_cast<CallExpr>(E))
+ return getAllocSizeAttr(CE) ? CE : nullptr;
+ return nullptr;
+ }
+
+ /// Determines whether or not the given Base contains a call to a function
+ /// with the alloc_size attribute.
+ static bool isBaseAnAllocSizeCall(APValue::LValueBase Base) {
+ const auto *E = Base.dyn_cast<const Expr *>();
+ return E && E->getType()->isPointerType() && tryUnwrapAllocSizeCall(E);
+ }
+
+ /// Determines if an LValue with the given LValueBase will have an unsized
+ /// array in its designator.
/// Find the path length and type of the most-derived subobject in the given
/// path, and find the size of the containing array, if any.
- static
- unsigned findMostDerivedSubobject(ASTContext &Ctx, QualType Base,
- ArrayRef<APValue::LValuePathEntry> Path,
- uint64_t &ArraySize, QualType &Type,
- bool &IsArray) {
+ static unsigned
+ findMostDerivedSubobject(ASTContext &Ctx, APValue::LValueBase Base,
+ ArrayRef<APValue::LValuePathEntry> Path,
+ uint64_t &ArraySize, QualType &Type, bool &IsArray) {
+ // This only accepts LValueBases from APValues, and APValues don't support
+ // arrays that lack size info.
+ assert(!isBaseAnAllocSizeCall(Base) &&
+ "Unsized arrays shouldn't appear here");
unsigned MostDerivedLength = 0;
- Type = Base;
+ Type = getType(Base);
+
for (unsigned I = 0, N = Path.size(); I != N; ++I) {
if (Type->isArrayType()) {
const ConstantArrayType *CAT =
- cast<ConstantArrayType>(Ctx.getAsArrayType(Type));
+ cast<ConstantArrayType>(Ctx.getAsArrayType(Type));
Type = CAT->getElementType();
ArraySize = CAT->getSize().getZExtValue();
MostDerivedLength = I + 1;
@@ -162,17 +200,23 @@ namespace {
/// Is this a pointer one past the end of an object?
unsigned IsOnePastTheEnd : 1;
+ /// Indicator of whether the first entry is an unsized array.
+ unsigned FirstEntryIsAnUnsizedArray : 1;
+
/// Indicator of whether the most-derived object is an array element.
unsigned MostDerivedIsArrayElement : 1;
/// The length of the path to the most-derived object of which this is a
/// subobject.
- unsigned MostDerivedPathLength : 29;
+ unsigned MostDerivedPathLength : 28;
/// The size of the array of which the most-derived object is an element.
/// This will always be 0 if the most-derived object is not an array
/// element. 0 is not an indicator of whether or not the most-derived object
/// is an array, however, because 0-length arrays are allowed.
+ ///
+ /// If the current array is an unsized array, the value of this is
+ /// undefined.
uint64_t MostDerivedArraySize;
/// The type of the most derived object referred to by this address.
@@ -187,23 +231,24 @@ namespace {
explicit SubobjectDesignator(QualType T)
: Invalid(false), IsOnePastTheEnd(false),
- MostDerivedIsArrayElement(false), MostDerivedPathLength(0),
- MostDerivedArraySize(0), MostDerivedType(T) {}
+ FirstEntryIsAnUnsizedArray(false), MostDerivedIsArrayElement(false),
+ MostDerivedPathLength(0), MostDerivedArraySize(0),
+ MostDerivedType(T) {}
SubobjectDesignator(ASTContext &Ctx, const APValue &V)
: Invalid(!V.isLValue() || !V.hasLValuePath()), IsOnePastTheEnd(false),
- MostDerivedIsArrayElement(false), MostDerivedPathLength(0),
- MostDerivedArraySize(0) {
+ FirstEntryIsAnUnsizedArray(false), MostDerivedIsArrayElement(false),
+ MostDerivedPathLength(0), MostDerivedArraySize(0) {
+ assert(V.isLValue() && "Non-LValue used to make an LValue designator?");
if (!Invalid) {
IsOnePastTheEnd = V.isLValueOnePastTheEnd();
ArrayRef<PathEntry> VEntries = V.getLValuePath();
Entries.insert(Entries.end(), VEntries.begin(), VEntries.end());
if (V.getLValueBase()) {
bool IsArray = false;
- MostDerivedPathLength =
- findMostDerivedSubobject(Ctx, getType(V.getLValueBase()),
- V.getLValuePath(), MostDerivedArraySize,
- MostDerivedType, IsArray);
+ MostDerivedPathLength = findMostDerivedSubobject(
+ Ctx, V.getLValueBase(), V.getLValuePath(), MostDerivedArraySize,
+ MostDerivedType, IsArray);
MostDerivedIsArrayElement = IsArray;
}
}
@@ -214,12 +259,26 @@ namespace {
Entries.clear();
}
+ /// Determine whether the most derived subobject is an array without a
+ /// known bound.
+ bool isMostDerivedAnUnsizedArray() const {
+ assert(!Invalid && "Calling this makes no sense on invalid designators");
+ return Entries.size() == 1 && FirstEntryIsAnUnsizedArray;
+ }
+
+ /// Determine what the most derived array's size is. Results in an assertion
+ /// failure if the most derived array lacks a size.
+ uint64_t getMostDerivedArraySize() const {
+ assert(!isMostDerivedAnUnsizedArray() && "Unsized array has no size");
+ return MostDerivedArraySize;
+ }
+
/// Determine whether this is a one-past-the-end pointer.
bool isOnePastTheEnd() const {
assert(!Invalid);
if (IsOnePastTheEnd)
return true;
- if (MostDerivedIsArrayElement &&
+ if (!isMostDerivedAnUnsizedArray() && MostDerivedIsArrayElement &&
Entries[MostDerivedPathLength - 1].ArrayIndex == MostDerivedArraySize)
return true;
return false;
@@ -247,6 +306,21 @@ namespace {
MostDerivedArraySize = CAT->getSize().getZExtValue();
MostDerivedPathLength = Entries.size();
}
+ /// Update this designator to refer to the first element within the array of
+ /// elements of type T. This is an array of unknown size.
+ void addUnsizedArrayUnchecked(QualType ElemTy) {
+ PathEntry Entry;
+ Entry.ArrayIndex = 0;
+ Entries.push_back(Entry);
+
+ MostDerivedType = ElemTy;
+ MostDerivedIsArrayElement = true;
+ // The value in MostDerivedArraySize is undefined in this case. So, set it
+ // to an arbitrary value that's likely to loudly break things if it's
+ // used.
+ MostDerivedArraySize = std::numeric_limits<uint64_t>::max() / 2;
+ MostDerivedPathLength = Entries.size();
+ }
/// Update this designator to refer to the given base or member of this
/// object.
void addDeclUnchecked(const Decl *D, bool Virtual = false) {
@@ -280,10 +354,16 @@ namespace {
/// Add N to the address of this subobject.
void adjustIndex(EvalInfo &Info, const Expr *E, uint64_t N) {
if (Invalid) return;
+ if (isMostDerivedAnUnsizedArray()) {
+ // Can't verify -- trust that the user is doing the right thing (or if
+ // not, trust that the caller will catch the bad behavior).
+ Entries.back().ArrayIndex += N;
+ return;
+ }
if (MostDerivedPathLength == Entries.size() &&
MostDerivedIsArrayElement) {
Entries.back().ArrayIndex += N;
- if (Entries.back().ArrayIndex > MostDerivedArraySize) {
+ if (Entries.back().ArrayIndex > getMostDerivedArraySize()) {
diagnosePointerArithmetic(Info, E, Entries.back().ArrayIndex);
setInvalid();
}
@@ -310,15 +390,9 @@ namespace {
/// Parent - The caller of this stack frame.
CallStackFrame *Caller;
- /// CallLoc - The location of the call expression for this call.
- SourceLocation CallLoc;
-
/// Callee - The function which was called.
const FunctionDecl *Callee;
- /// Index - The call index of this call.
- unsigned Index;
-
/// This - The binding for the this pointer in this call, if any.
const LValue *This;
@@ -333,6 +407,12 @@ namespace {
/// Temporaries - Temporary lvalues materialized within this stack frame.
MapTy Temporaries;
+ /// CallLoc - The location of the call expression for this call.
+ SourceLocation CallLoc;
+
+ /// Index - The call index of this call.
+ unsigned Index;
+
CallStackFrame(EvalInfo &Info, SourceLocation CallLoc,
const FunctionDecl *Callee, const LValue *This,
APValue *Arguments);
@@ -433,7 +513,7 @@ namespace {
/// rules. For example, the RHS of (0 && foo()) is not evaluated. We can
/// evaluate the expression regardless of what the RHS is, but C only allows
/// certain things in certain situations.
- struct EvalInfo {
+ struct LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) EvalInfo {
ASTContext &Ctx;
/// EvalStatus - Contains information about the evaluation.
@@ -469,6 +549,10 @@ namespace {
/// declaration whose initializer is being evaluated, if any.
APValue *EvaluatingDeclValue;
+ /// The current array initialization index, if we're performing array
+ /// initialization.
+ uint64_t ArrayInitIndex = -1;
+
/// HasActiveDiagnostic - Was the previous diagnostic stored? If so, further
/// notes attached to it will also be stored, otherwise they will not be.
bool HasActiveDiagnostic;
@@ -520,9 +604,15 @@ namespace {
/// gets a chance to look at it.
EM_PotentialConstantExpressionUnevaluated,
- /// Evaluate as a constant expression. Continue evaluating if we find a
- /// MemberExpr with a base that can't be evaluated.
- EM_DesignatorFold,
+ /// Evaluate as a constant expression. Continue evaluating if either:
+ /// - We find a MemberExpr with a base that can't be evaluated.
+ /// - We find a variable initialized with a call to a function that has
+ /// the alloc_size attribute on it.
+ /// In either case, the LValue returned shall have an invalid base; in the
+ /// former, the base will be the invalid MemberExpr, in the latter, the
+ /// base will be either the alloc_size CallExpr or a CastExpr wrapping
+ /// said CallExpr.
+ EM_OffsetFold,
} EvalMode;
/// Are we checking whether the expression is a potential constant
@@ -624,7 +714,7 @@ namespace {
case EM_PotentialConstantExpression:
case EM_ConstantExpressionUnevaluated:
case EM_PotentialConstantExpressionUnevaluated:
- case EM_DesignatorFold:
+ case EM_OffsetFold:
HasActiveDiagnostic = false;
return OptionalDiagnostic();
}
@@ -716,7 +806,7 @@ namespace {
case EM_ConstantExpression:
case EM_ConstantExpressionUnevaluated:
case EM_ConstantFold:
- case EM_DesignatorFold:
+ case EM_OffsetFold:
return false;
}
llvm_unreachable("Missed EvalMode case");
@@ -735,7 +825,7 @@ namespace {
case EM_EvaluateForOverflow:
case EM_IgnoreSideEffects:
case EM_ConstantFold:
- case EM_DesignatorFold:
+ case EM_OffsetFold:
return true;
case EM_PotentialConstantExpression:
@@ -771,7 +861,7 @@ namespace {
case EM_ConstantExpressionUnevaluated:
case EM_ConstantFold:
case EM_IgnoreSideEffects:
- case EM_DesignatorFold:
+ case EM_OffsetFold:
return false;
}
llvm_unreachable("Missed EvalMode case");
@@ -787,7 +877,7 @@ namespace {
/// (Foo(), 1) // use noteSideEffect
/// (Foo() || true) // use noteSideEffect
/// Foo() + 1 // use noteFailure
- LLVM_ATTRIBUTE_UNUSED_RESULT bool noteFailure() {
+ LLVM_NODISCARD bool noteFailure() {
// Failure when evaluating some expression often means there is some
// subexpression whose evaluation was skipped. Therefore, (because we
// don't track whether we skipped an expression when unwinding after an
@@ -801,8 +891,22 @@ namespace {
}
bool allowInvalidBaseExpr() const {
- return EvalMode == EM_DesignatorFold;
+ return EvalMode == EM_OffsetFold;
}
+
+ class ArrayInitLoopIndex {
+ EvalInfo &Info;
+ uint64_t OuterIndex;
+
+ public:
+ ArrayInitLoopIndex(EvalInfo &Info)
+ : Info(Info), OuterIndex(Info.ArrayInitIndex) {
+ Info.ArrayInitIndex = 0;
+ }
+ ~ArrayInitLoopIndex() { Info.ArrayInitIndex = OuterIndex; }
+
+ operator uint64_t&() { return Info.ArrayInitIndex; }
+ };
};
/// Object used to treat all foldable expressions as constant expressions.
@@ -838,11 +942,10 @@ namespace {
struct FoldOffsetRAII {
EvalInfo &Info;
EvalInfo::EvaluationMode OldMode;
- explicit FoldOffsetRAII(EvalInfo &Info, bool Subobject)
+ explicit FoldOffsetRAII(EvalInfo &Info)
: Info(Info), OldMode(Info.EvalMode) {
if (!Info.checkingPotentialConstantExpression())
- Info.EvalMode = Subobject ? EvalInfo::EM_DesignatorFold
- : EvalInfo::EM_ConstantFold;
+ Info.EvalMode = EvalInfo::EM_OffsetFold;
}
~FoldOffsetRAII() { Info.EvalMode = OldMode; }
@@ -948,10 +1051,12 @@ bool SubobjectDesignator::checkSubobject(EvalInfo &Info, const Expr *E,
void SubobjectDesignator::diagnosePointerArithmetic(EvalInfo &Info,
const Expr *E, uint64_t N) {
+ // If we're complaining, we must be able to statically determine the size of
+ // the most derived array.
if (MostDerivedPathLength == Entries.size() && MostDerivedIsArrayElement)
Info.CCEDiag(E, diag::note_constexpr_array_index)
<< static_cast<int>(N) << /*array*/ 0
- << static_cast<unsigned>(MostDerivedArraySize);
+ << static_cast<unsigned>(getMostDerivedArraySize());
else
Info.CCEDiag(E, diag::note_constexpr_array_index)
<< static_cast<int>(N) << /*non-array*/ 1;
@@ -961,8 +1066,8 @@ void SubobjectDesignator::diagnosePointerArithmetic(EvalInfo &Info,
CallStackFrame::CallStackFrame(EvalInfo &Info, SourceLocation CallLoc,
const FunctionDecl *Callee, const LValue *This,
APValue *Arguments)
- : Info(Info), Caller(Info.CurrentCall), CallLoc(CallLoc), Callee(Callee),
- Index(Info.NextCallIndex++), This(This), Arguments(Arguments) {
+ : Info(Info), Caller(Info.CurrentCall), Callee(Callee), This(This),
+ Arguments(Arguments), CallLoc(CallLoc), Index(Info.NextCallIndex++) {
Info.CurrentCall = this;
++Info.CallStackDepth;
}
@@ -1032,7 +1137,7 @@ namespace {
APSInt IntReal, IntImag;
APFloat FloatReal, FloatImag;
- ComplexValue() : FloatReal(APFloat::Bogus), FloatImag(APFloat::Bogus) {}
+ ComplexValue() : FloatReal(APFloat::Bogus()), FloatImag(APFloat::Bogus()) {}
void makeComplexFloat() { IsInt = false; }
bool isComplexFloat() const { return !IsInt; }
@@ -1070,6 +1175,7 @@ namespace {
unsigned InvalidBase : 1;
unsigned CallIndex : 31;
SubobjectDesignator Designator;
+ bool IsNullPtr;
const APValue::LValueBase getLValueBase() const { return Base; }
CharUnits &getLValueOffset() { return Offset; }
@@ -1077,29 +1183,47 @@ namespace {
unsigned getLValueCallIndex() const { return CallIndex; }
SubobjectDesignator &getLValueDesignator() { return Designator; }
const SubobjectDesignator &getLValueDesignator() const { return Designator;}
+ bool isNullPointer() const { return IsNullPtr;}
void moveInto(APValue &V) const {
if (Designator.Invalid)
- V = APValue(Base, Offset, APValue::NoLValuePath(), CallIndex);
- else
+ V = APValue(Base, Offset, APValue::NoLValuePath(), CallIndex,
+ IsNullPtr);
+ else {
+ assert(!InvalidBase && "APValues can't handle invalid LValue bases");
+ assert(!Designator.FirstEntryIsAnUnsizedArray &&
+ "Unsized array with a valid base?");
V = APValue(Base, Offset, Designator.Entries,
- Designator.IsOnePastTheEnd, CallIndex);
+ Designator.IsOnePastTheEnd, CallIndex, IsNullPtr);
+ }
}
void setFrom(ASTContext &Ctx, const APValue &V) {
- assert(V.isLValue());
+ assert(V.isLValue() && "Setting LValue from a non-LValue?");
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, unsigned I = 0, bool BInvalid = false,
+ bool IsNullPtr_ = false, uint64_t Offset_ = 0) {
+#ifndef NDEBUG
+ // We only allow a few types of invalid bases. Enforce that here.
+ if (BInvalid) {
+ const auto *E = B.get<const Expr *>();
+ assert((isa<MemberExpr>(E) || tryUnwrapAllocSizeCall(E)) &&
+ "Unexpected type of invalid base");
+ }
+#endif
+
Base = B;
- Offset = CharUnits::Zero();
+ Offset = CharUnits::fromQuantity(Offset_);
InvalidBase = BInvalid;
CallIndex = I;
Designator = SubobjectDesignator(getType(B));
+ IsNullPtr = IsNullPtr_;
}
void setInvalid(APValue::LValueBase B, unsigned I = 0) {
@@ -1112,7 +1236,7 @@ namespace {
CheckSubobjectKind CSK) {
if (Designator.Invalid)
return false;
- if (!Base) {
+ if (IsNullPtr) {
Info.CCEDiag(E, diag::note_constexpr_null_subobject)
<< CSK;
Designator.setInvalid();
@@ -1133,6 +1257,13 @@ namespace {
if (checkSubobject(Info, E, isa<FieldDecl>(D) ? CSK_Field : CSK_Base))
Designator.addDeclUnchecked(D, Virtual);
}
+ void addUnsizedArray(EvalInfo &Info, QualType ElemTy) {
+ assert(Designator.Entries.empty() && getType(Base)->isPointerType());
+ assert(isBaseAnAllocSizeCall(Base) &&
+ "Only alloc_size bases can have unsized arrays");
+ Designator.FirstEntryIsAnUnsizedArray = true;
+ Designator.addUnsizedArrayUnchecked(ElemTy);
+ }
void addArray(EvalInfo &Info, const Expr *E, const ConstantArrayType *CAT) {
if (checkSubobject(Info, E, CSK_ArrayToPointer))
Designator.addArrayUnchecked(CAT);
@@ -1141,9 +1272,22 @@ namespace {
if (checkSubobject(Info, E, Imag ? CSK_Imag : CSK_Real))
Designator.addComplexUnchecked(EltTy, Imag);
}
- void adjustIndex(EvalInfo &Info, const Expr *E, uint64_t N) {
- if (N && checkNullPointer(Info, E, CSK_ArrayIndex))
- Designator.adjustIndex(Info, E, N);
+ void clearIsNullPointer() {
+ IsNullPtr = false;
+ }
+ void adjustOffsetAndIndex(EvalInfo &Info, const Expr *E, uint64_t Index,
+ CharUnits ElementSize) {
+ // Compute the new offset in the appropriate width.
+ Offset += Index * ElementSize;
+ if (Index && checkNullPointer(Info, E, CSK_ArrayIndex))
+ Designator.adjustIndex(Info, E, Index);
+ if (Index)
+ clearIsNullPointer();
+ }
+ void adjustOffset(CharUnits N) {
+ Offset += N;
+ if (N.getQuantity())
+ clearIsNullPointer();
}
};
@@ -2018,7 +2162,7 @@ static bool HandleLValueMember(EvalInfo &Info, const Expr *E, LValue &LVal,
}
unsigned I = FD->getFieldIndex();
- LVal.Offset += Info.Ctx.toCharUnitsFromBits(RL->getFieldOffset(I));
+ LVal.adjustOffset(Info.Ctx.toCharUnitsFromBits(RL->getFieldOffset(I)));
LVal.addDecl(Info, E, FD);
return true;
}
@@ -2072,9 +2216,7 @@ static bool HandleLValueArrayAdjustment(EvalInfo &Info, const Expr *E,
if (!HandleSizeof(Info, E->getExprLoc(), EltTy, SizeOfPointee))
return false;
- // Compute the new offset in the appropriate width.
- LVal.Offset += Adjustment * SizeOfPointee;
- LVal.adjustIndex(Info, E, Adjustment);
+ LVal.adjustOffsetAndIndex(Info, E, Adjustment, SizeOfPointee);
return true;
}
@@ -2125,7 +2267,22 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E,
// If this is a local variable, dig out its value.
if (Frame) {
Result = Frame->getTemporary(VD);
- assert(Result && "missing value for local variable");
+ if (!Result) {
+ // Assume variables referenced within a lambda's call operator that were
+ // not declared within the call operator are captures and during checking
+ // of a potential constant expression, assume they are unknown constant
+ // expressions.
+ assert(isLambdaCallOperator(Frame->Callee) &&
+ (VD->getDeclContext() != Frame->Callee || VD->isInitCapture()) &&
+ "missing value for local variable");
+ if (Info.checkingPotentialConstantExpression())
+ return false;
+ // FIXME: implement capture evaluation during constant expr evaluation.
+ Info.FFDiag(E->getLocStart(),
+ diag::note_unimplemented_constexpr_lambda_feature_ast)
+ << "captures not currently allowed";
+ return false;
+ }
return true;
}
@@ -2771,6 +2928,9 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
} else {
Info.CCEDiag(E);
}
+ } else if (BaseType.isConstQualified() && VD->hasDefinition(Info.Ctx)) {
+ Info.CCEDiag(E, diag::note_constexpr_ltor_non_constexpr) << VD;
+ // Keep evaluating to see what we can do.
} else {
// FIXME: Allow folding of values of any literal type in all languages.
if (Info.checkingPotentialConstantExpression() &&
@@ -2892,7 +3052,6 @@ static bool handleLValueToRValueConversion(EvalInfo &Info, const Expr *Conv,
// In C99, a CompoundLiteralExpr is an lvalue, and we defer evaluating the
// initializer until now for such expressions. Such an expression can't be
// an ICE in C, so this only matters for fold.
- assert(!Info.getLangOpts().CPlusPlus && "lvalue compound literal in c++?");
if (Type.isVolatileQualified()) {
Info.FFDiag(Conv);
return false;
@@ -3385,38 +3544,51 @@ enum EvalStmtResult {
};
}
-static bool EvaluateDecl(EvalInfo &Info, const Decl *D) {
- if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
- // We don't need to evaluate the initializer for a static local.
- if (!VD->hasLocalStorage())
- return true;
+static bool EvaluateVarDecl(EvalInfo &Info, const VarDecl *VD) {
+ // We don't need to evaluate the initializer for a static local.
+ if (!VD->hasLocalStorage())
+ return true;
- LValue Result;
- Result.set(VD, Info.CurrentCall->Index);
- APValue &Val = Info.CurrentCall->createTemporary(VD, true);
+ LValue Result;
+ Result.set(VD, Info.CurrentCall->Index);
+ APValue &Val = Info.CurrentCall->createTemporary(VD, true);
- const Expr *InitE = VD->getInit();
- if (!InitE) {
- Info.FFDiag(D->getLocStart(), diag::note_constexpr_uninitialized)
- << false << VD->getType();
- Val = APValue();
- return false;
- }
+ const Expr *InitE = VD->getInit();
+ if (!InitE) {
+ Info.FFDiag(VD->getLocStart(), diag::note_constexpr_uninitialized)
+ << false << VD->getType();
+ Val = APValue();
+ return false;
+ }
- if (InitE->isValueDependent())
- return false;
+ if (InitE->isValueDependent())
+ return false;
- if (!EvaluateInPlace(Val, Info, Result, InitE)) {
- // Wipe out any partially-computed value, to allow tracking that this
- // evaluation failed.
- Val = APValue();
- return false;
- }
+ if (!EvaluateInPlace(Val, Info, Result, InitE)) {
+ // Wipe out any partially-computed value, to allow tracking that this
+ // evaluation failed.
+ Val = APValue();
+ return false;
}
return true;
}
+static bool EvaluateDecl(EvalInfo &Info, const Decl *D) {
+ bool OK = true;
+
+ if (const VarDecl *VD = dyn_cast<VarDecl>(D))
+ OK &= EvaluateVarDecl(Info, VD);
+
+ if (const DecompositionDecl *DD = dyn_cast<DecompositionDecl>(D))
+ for (auto *BD : DD->bindings())
+ if (auto *VD = BD->getHoldingVar())
+ OK &= EvaluateDecl(Info, VD);
+
+ return OK;
+}
+
+
/// Evaluate a condition (either a variable declaration or an expression).
static bool EvaluateCond(EvalInfo &Info, const VarDecl *CondDecl,
const Expr *Cond, bool &Result) {
@@ -4389,8 +4561,11 @@ public:
}
// Don't call function pointers which have been cast to some other type.
- if (!Info.Ctx.hasSameType(CalleeType->getPointeeType(), FD->getType()))
+ // Per DR (no number yet), the caller and callee can differ in noexcept.
+ if (!Info.Ctx.hasSameFunctionTypeIgnoringExceptionSpec(
+ CalleeType->getPointeeType(), FD->getType())) {
return Error(E);
+ }
} else
return Error(E);
@@ -4683,7 +4858,7 @@ public:
// * VarDecl
// * FunctionDecl
// - Literals
-// * CompoundLiteralExpr in C
+// * CompoundLiteralExpr in C (and in global scope in C++)
// * StringLiteral
// * CXXTypeidExpr
// * PredefinedExpr
@@ -4770,13 +4945,26 @@ bool LValueExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) {
return Success(FD);
if (const VarDecl *VD = dyn_cast<VarDecl>(E->getDecl()))
return VisitVarDecl(E, VD);
+ if (const BindingDecl *BD = dyn_cast<BindingDecl>(E->getDecl()))
+ return Visit(BD->getBinding());
return Error(E);
}
+
bool LValueExprEvaluator::VisitVarDecl(const Expr *E, const VarDecl *VD) {
CallStackFrame *Frame = nullptr;
- if (VD->hasLocalStorage() && Info.CurrentCall->Index > 1)
- Frame = Info.CurrentCall;
+ if (VD->hasLocalStorage() && Info.CurrentCall->Index > 1) {
+ // Only if a local variable was declared in the function currently being
+ // evaluated, do we expect to be able to find its value in the current
+ // frame. (Otherwise it was likely declared in an enclosing context and
+ // could either have a valid evaluatable value (for e.g. a constexpr
+ // variable) or be ill-formed (and trigger an appropriate evaluation
+ // diagnostic)).
+ if (Info.CurrentCall->Callee &&
+ Info.CurrentCall->Callee->Equals(VD->getDeclContext())) {
+ Frame = Info.CurrentCall;
+ }
+ }
if (!VD->getType()->isReferenceType()) {
if (Frame) {
@@ -4865,7 +5053,8 @@ bool LValueExprEvaluator::VisitMaterializeTemporaryExpr(
bool
LValueExprEvaluator::VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) {
- assert(!Info.getLangOpts().CPlusPlus && "lvalue compound literal in c++?");
+ assert((!Info.getLangOpts().CPlusPlus || E->isFileScope()) &&
+ "lvalue compound literal in c++?");
// Defer visiting the literal until the lvalue-to-rvalue conversion. We can
// only see this when folding in C, so there's no standard to follow here.
return Success(E);
@@ -5000,6 +5189,105 @@ bool LValueExprEvaluator::VisitBinAssign(const BinaryOperator *E) {
// Pointer Evaluation
//===----------------------------------------------------------------------===//
+/// \brief 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`.
+///
+/// This expects the given CallExpr to be a call to a function with an
+/// alloc_size attribute.
+static bool getBytesReturnedByAllocSizeCall(const ASTContext &Ctx,
+ const CallExpr *Call,
+ 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;
+ unsigned BitsInSizeT = Ctx.getTypeSize(Ctx.getSizeType());
+ if (Call->getNumArgs() <= SizeArgNo)
+ return false;
+
+ auto EvaluateAsSizeT = [&](const Expr *E, APSInt &Into) {
+ if (!E->EvaluateAsInt(Into, Ctx, Expr::SE_AllowSideEffects))
+ return false;
+ if (Into.isNegative() || !Into.isIntN(BitsInSizeT))
+ return false;
+ Into = Into.zextOrSelf(BitsInSizeT);
+ return true;
+ };
+
+ APSInt SizeOfElem;
+ if (!EvaluateAsSizeT(Call->getArg(SizeArgNo), SizeOfElem))
+ return false;
+
+ if (!AllocSize->getNumElemsParam()) {
+ Result = std::move(SizeOfElem);
+ return true;
+ }
+
+ APSInt NumberOfElems;
+ // Argument numbers start at 1
+ unsigned NumArgNo = AllocSize->getNumElemsParam() - 1;
+ if (!EvaluateAsSizeT(Call->getArg(NumArgNo), NumberOfElems))
+ return false;
+
+ bool Overflow;
+ llvm::APInt BytesAvailable = SizeOfElem.umul_ov(NumberOfElems, Overflow);
+ if (Overflow)
+ return false;
+
+ Result = std::move(BytesAvailable);
+ return true;
+}
+
+/// \brief Convenience function. LVal's base must be a call to an alloc_size
+/// function.
+static bool getBytesReturnedByAllocSizeCall(const ASTContext &Ctx,
+ const LValue &LVal,
+ llvm::APInt &Result) {
+ assert(isBaseAnAllocSizeCall(LVal.getLValueBase()) &&
+ "Can't get the size of a non alloc_size function");
+ const auto *Base = LVal.getLValueBase().get<const Expr *>();
+ const CallExpr *CE = tryUnwrapAllocSizeCall(Base);
+ return getBytesReturnedByAllocSizeCall(Ctx, CE, Result);
+}
+
+/// \brief 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.
+static bool evaluateLValueAsAllocSize(EvalInfo &Info, APValue::LValueBase Base,
+ LValue &Result) {
+ if (!Info.allowInvalidBaseExpr() || Base.isNull())
+ return false;
+
+ // Because we do no form of static analysis, we only support const variables.
+ //
+ // Additionally, we can't support parameters, nor can we support static
+ // variables (in the latter case, use-before-assign isn't UB; in the former,
+ // we have no clue what they'll be assigned to).
+ const auto *VD =
+ dyn_cast_or_null<VarDecl>(Base.dyn_cast<const ValueDecl *>());
+ if (!VD || !VD->isLocalVarDecl() || !VD->getType().isConstQualified())
+ return false;
+
+ const Expr *Init = VD->getAnyInitializer();
+ if (!Init)
+ return false;
+
+ const Expr *E = Init->IgnoreParens();
+ if (!tryUnwrapAllocSizeCall(E))
+ return false;
+
+ // Store E instead of E unwrapped so that the type of the LValue's base is
+ // what the user wanted.
+ Result.setInvalid(E);
+
+ QualType Pointee = E->getType()->castAs<PointerType>()->getPointeeType();
+ Result.addUnsizedArray(Info, Pointee);
+ return true;
+}
+
namespace {
class PointerExprEvaluator
: public ExprEvaluatorBase<PointerExprEvaluator> {
@@ -5009,6 +5297,8 @@ class PointerExprEvaluator
Result.set(E);
return true;
}
+
+ bool visitNonBuiltinCallExpr(const CallExpr *E);
public:
PointerExprEvaluator(EvalInfo &info, LValue &Result)
@@ -5019,7 +5309,9 @@ public:
return true;
}
bool ZeroInitialization(const Expr *E) {
- return Success((Expr*)nullptr);
+ auto Offset = Info.Ctx.getTargetNullPointerValue(E->getType());
+ Result.set((Expr*)nullptr, 0, false, true, Offset);
+ return true;
}
bool VisitBinaryOperator(const BinaryOperator *E);
@@ -5032,6 +5324,7 @@ public:
bool VisitAddrLabelExpr(const AddrLabelExpr *E)
{ return Success(E); }
bool VisitCallExpr(const CallExpr *E);
+ bool VisitBuiltinCallExpr(const CallExpr *E, unsigned BuiltinOp);
bool VisitBlockExpr(const BlockExpr *E) {
if (!E->getBlockDecl()->hasCaptures())
return Success(E);
@@ -5117,6 +5410,8 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) {
else
CCEDiag(E, diag::note_constexpr_invalid_cast) << 2;
}
+ if (E->getCastKind() == CK_AddressSpaceConversion && Result.IsNullPtr)
+ ZeroInitialization(E);
return true;
case CK_DerivedToBase:
@@ -5158,6 +5453,7 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) {
Result.Offset = CharUnits::fromQuantity(N);
Result.CallIndex = 0;
Result.Designator.setInvalid();
+ Result.IsNullPtr = false;
return true;
} else {
// Cast is of an lvalue, no need to change value.
@@ -5185,6 +5481,19 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) {
case CK_FunctionToPointerDecay:
return EvaluateLValue(SubExpr, Result, Info);
+
+ case CK_LValueToRValue: {
+ LValue LVal;
+ if (!EvaluateLValue(E->getSubExpr(), LVal, Info))
+ return false;
+
+ APValue RVal;
+ // Note, we use the subexpression's type in order to retain cv-qualifiers.
+ if (!handleLValueToRValueConversion(Info, E, E->getSubExpr()->getType(),
+ LVal, RVal))
+ return evaluateLValueAsAllocSize(Info, LVal.Base, Result);
+ return Success(RVal, E);
+ }
}
return ExprEvaluatorBaseTy::VisitCastExpr(E);
@@ -5222,11 +5531,33 @@ static CharUnits GetAlignOfExpr(EvalInfo &Info, const Expr *E) {
return GetAlignOfType(Info, E->getType());
}
+// To be clear: this happily visits unsupported builtins. Better name welcomed.
+bool PointerExprEvaluator::visitNonBuiltinCallExpr(const CallExpr *E) {
+ if (ExprEvaluatorBaseTy::VisitCallExpr(E))
+ return true;
+
+ if (!(Info.allowInvalidBaseExpr() && getAllocSizeAttr(E)))
+ return false;
+
+ Result.setInvalid(E);
+ QualType PointeeTy = E->getType()->castAs<PointerType>()->getPointeeType();
+ Result.addUnsizedArray(Info, PointeeTy);
+ return true;
+}
+
bool PointerExprEvaluator::VisitCallExpr(const CallExpr *E) {
if (IsStringLiteralCall(E))
return Success(E);
- switch (E->getBuiltinCallee()) {
+ if (unsigned BuiltinOp = E->getBuiltinCallee())
+ return VisitBuiltinCallExpr(E, BuiltinOp);
+
+ return visitNonBuiltinCallExpr(E);
+}
+
+bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
+ unsigned BuiltinOp) {
+ switch (BuiltinOp) {
case Builtin::BI__builtin_addressof:
return EvaluateLValue(E->getArg(0), Result, Info);
case Builtin::BI__builtin_assume_aligned: {
@@ -5264,8 +5595,8 @@ bool PointerExprEvaluator::VisitCallExpr(const CallExpr *E) {
if (BaseAlignment < Align) {
Result.Designator.setInvalid();
- // FIXME: Quantities here cast to integers because the plural modifier
- // does not work on APSInts yet.
+ // FIXME: Quantities here cast to integers because the plural modifier
+ // does not work on APSInts yet.
CCEDiag(E->getArg(0),
diag::note_constexpr_baa_insufficient_alignment) << 0
<< (int) BaseAlignment.getQuantity()
@@ -5294,8 +5625,93 @@ bool PointerExprEvaluator::VisitCallExpr(const CallExpr *E) {
return true;
}
+
+ case Builtin::BIstrchr:
+ case Builtin::BIwcschr:
+ case Builtin::BImemchr:
+ case Builtin::BIwmemchr:
+ if (Info.getLangOpts().CPlusPlus11)
+ Info.CCEDiag(E, diag::note_constexpr_invalid_function)
+ << /*isConstexpr*/0 << /*isConstructor*/0
+ << (std::string("'") + Info.Ctx.BuiltinInfo.getName(BuiltinOp) + "'");
+ else
+ Info.CCEDiag(E, diag::note_invalid_subexpr_in_const_expr);
+ // Fall through.
+ case Builtin::BI__builtin_strchr:
+ case Builtin::BI__builtin_wcschr:
+ case Builtin::BI__builtin_memchr:
+ case Builtin::BI__builtin_wmemchr: {
+ if (!Visit(E->getArg(0)))
+ return false;
+ APSInt Desired;
+ if (!EvaluateInteger(E->getArg(1), Desired, Info))
+ return false;
+ uint64_t MaxLength = uint64_t(-1);
+ if (BuiltinOp != Builtin::BIstrchr &&
+ BuiltinOp != Builtin::BIwcschr &&
+ BuiltinOp != Builtin::BI__builtin_strchr &&
+ BuiltinOp != Builtin::BI__builtin_wcschr) {
+ APSInt N;
+ if (!EvaluateInteger(E->getArg(2), N, Info))
+ return false;
+ MaxLength = N.getExtValue();
+ }
+
+ QualType CharTy = E->getArg(0)->getType()->getPointeeType();
+
+ // Figure out what value we're actually looking for (after converting to
+ // the corresponding unsigned type if necessary).
+ uint64_t DesiredVal;
+ bool StopAtNull = false;
+ switch (BuiltinOp) {
+ case Builtin::BIstrchr:
+ case Builtin::BI__builtin_strchr:
+ // strchr compares directly to the passed integer, and therefore
+ // always fails if given an int that is not a char.
+ if (!APSInt::isSameValue(HandleIntToIntCast(Info, E, CharTy,
+ E->getArg(1)->getType(),
+ Desired),
+ Desired))
+ return ZeroInitialization(E);
+ StopAtNull = true;
+ // Fall through.
+ case Builtin::BImemchr:
+ case Builtin::BI__builtin_memchr:
+ // memchr compares by converting both sides to unsigned char. That's also
+ // correct for strchr if we get this far (to cope with plain char being
+ // unsigned in the strchr case).
+ DesiredVal = Desired.trunc(Info.Ctx.getCharWidth()).getZExtValue();
+ break;
+
+ case Builtin::BIwcschr:
+ case Builtin::BI__builtin_wcschr:
+ StopAtNull = true;
+ // Fall through.
+ case Builtin::BIwmemchr:
+ case Builtin::BI__builtin_wmemchr:
+ // wcschr and wmemchr are given a wchar_t to look for. Just use it.
+ DesiredVal = Desired.getZExtValue();
+ break;
+ }
+
+ for (; MaxLength; --MaxLength) {
+ APValue Char;
+ if (!handleLValueToRValueConversion(Info, E, CharTy, Result, Char) ||
+ !Char.isInt())
+ return false;
+ if (Char.getInt().getZExtValue() == DesiredVal)
+ return true;
+ if (StopAtNull && !Char.getInt())
+ break;
+ if (!HandleLValueArrayAdjustment(Info, E, Result, CharTy, 1))
+ return false;
+ }
+ // Not found: return nullptr.
+ return ZeroInitialization(E);
+ }
+
default:
- return ExprEvaluatorBaseTy::VisitCallExpr(E);
+ return visitNonBuiltinCallExpr(E);
}
}
@@ -5535,6 +5951,9 @@ bool RecordExprEvaluator::VisitCastExpr(const CastExpr *E) {
}
bool RecordExprEvaluator::VisitInitListExpr(const InitListExpr *E) {
+ if (E->isTransparent())
+ return Visit(E->getInit(0));
+
const RecordDecl *RD = E->getType()->castAs<RecordType>()->getDecl();
if (RD->isInvalidDecl()) return false;
const ASTRecordLayout &Layout = Info.Ctx.getASTRecordLayout(RD);
@@ -5890,7 +6309,7 @@ bool VectorExprEvaluator::VisitCastExpr(const CastExpr *E) {
if (EltTy->isRealFloatingType()) {
const llvm::fltSemantics &Sem = Info.Ctx.getFloatTypeSemantics(EltTy);
unsigned FloatEltSize = EltSize;
- if (&Sem == &APFloat::x87DoubleExtended)
+ if (&Sem == &APFloat::x87DoubleExtended())
FloatEltSize = 80;
for (unsigned i = 0; i < NElts; i++) {
llvm::APInt Elt;
@@ -6030,6 +6449,7 @@ namespace {
return handleCallExpr(E, Result, &This);
}
bool VisitInitListExpr(const InitListExpr *E);
+ bool VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E);
bool VisitCXXConstructExpr(const CXXConstructExpr *E);
bool VisitCXXConstructExpr(const CXXConstructExpr *E,
const LValue &Subobject,
@@ -6112,6 +6532,35 @@ bool ArrayExprEvaluator::VisitInitListExpr(const InitListExpr *E) {
FillerExpr) && Success;
}
+bool ArrayExprEvaluator::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E) {
+ if (E->getCommonExpr() &&
+ !Evaluate(Info.CurrentCall->createTemporary(E->getCommonExpr(), false),
+ Info, E->getCommonExpr()->getSourceExpr()))
+ return false;
+
+ auto *CAT = cast<ConstantArrayType>(E->getType()->castAsArrayTypeUnsafe());
+
+ uint64_t Elements = CAT->getSize().getZExtValue();
+ Result = APValue(APValue::UninitArray(), Elements, Elements);
+
+ LValue Subobject = This;
+ Subobject.addArray(Info, E, CAT);
+
+ bool Success = true;
+ for (EvalInfo::ArrayInitLoopIndex Index(Info); Index != Elements; ++Index) {
+ if (!EvaluateInPlace(Result.getArrayInitializedElt(Index),
+ Info, Subobject, E->getSubExpr()) ||
+ !HandleLValueArrayAdjustment(Info, E, Subobject,
+ CAT->getElementType(), 1)) {
+ if (!Info.noteFailure())
+ return false;
+ Success = false;
+ }
+ }
+
+ return Success;
+}
+
bool ArrayExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E) {
return VisitCXXConstructExpr(E, This, &Result, E->getType());
}
@@ -6252,6 +6701,7 @@ public:
}
bool VisitCallExpr(const CallExpr *E);
+ bool VisitBuiltinCallExpr(const CallExpr *E, unsigned BuiltinOp);
bool VisitBinaryOperator(const BinaryOperator *E);
bool VisitOffsetOfExpr(const OffsetOfExpr *E);
bool VisitUnaryOperator(const UnaryOperator *E);
@@ -6266,6 +6716,16 @@ public:
bool VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *E) {
return Success(E->getValue(), E);
}
+
+ bool VisitArrayInitIndexExpr(const ArrayInitIndexExpr *E) {
+ if (Info.ArrayInitIndex == uint64_t(-1)) {
+ // We were asked to evaluate this subexpression independent of the
+ // enclosing ArrayInitLoopExpr. We can't do that.
+ Info.FFDiag(E);
+ return false;
+ }
+ return Success(Info.ArrayInitIndex, E);
+ }
// Note, GNU defines __null as an integer, not a pointer.
bool VisitGNUNullExpr(const GNUNullExpr *E) {
@@ -6290,8 +6750,6 @@ public:
bool VisitCXXNoexceptExpr(const CXXNoexceptExpr *E);
bool VisitSizeOfPackExpr(const SizeOfPackExpr *E);
-private:
- bool TryEvaluateBuiltinObjectSize(const CallExpr *E, unsigned Type);
// FIXME: Missing: array subscript of vector, member of vector
};
} // end anonymous namespace
@@ -6563,7 +7021,7 @@ static QualType getObjectType(APValue::LValueBase B) {
}
/// A more selective version of E->IgnoreParenCasts for
-/// TryEvaluateBuiltinObjectSize. This ignores some casts/parens that serve only
+/// tryEvaluateBuiltinObjectSize. This ignores some casts/parens that serve only
/// to change the type of E.
/// Ex. For E = `(short*)((char*)(&foo))`, returns `&foo`
///
@@ -6630,82 +7088,191 @@ static bool isDesignatorAtObjectEnd(const ASTContext &Ctx, const LValue &LVal) {
}
}
+ unsigned I = 0;
QualType BaseType = getType(Base);
- for (int I = 0, E = LVal.Designator.Entries.size(); I != E; ++I) {
+ if (LVal.Designator.FirstEntryIsAnUnsizedArray) {
+ assert(isBaseAnAllocSizeCall(Base) &&
+ "Unsized array in non-alloc_size call?");
+ // If this is an alloc_size base, we should ignore the initial array index
+ ++I;
+ BaseType = BaseType->castAs<PointerType>()->getPointeeType();
+ }
+
+ for (unsigned E = LVal.Designator.Entries.size(); I != E; ++I) {
+ const auto &Entry = LVal.Designator.Entries[I];
if (BaseType->isArrayType()) {
// Because __builtin_object_size treats arrays as objects, we can ignore
// the index iff this is the last array in the Designator.
if (I + 1 == E)
return true;
- auto *CAT = cast<ConstantArrayType>(Ctx.getAsArrayType(BaseType));
- uint64_t Index = LVal.Designator.Entries[I].ArrayIndex;
+ const auto *CAT = cast<ConstantArrayType>(Ctx.getAsArrayType(BaseType));
+ uint64_t Index = Entry.ArrayIndex;
if (Index + 1 != CAT->getSize())
return false;
BaseType = CAT->getElementType();
} else if (BaseType->isAnyComplexType()) {
- auto *CT = BaseType->castAs<ComplexType>();
- uint64_t Index = LVal.Designator.Entries[I].ArrayIndex;
+ const auto *CT = BaseType->castAs<ComplexType>();
+ uint64_t Index = Entry.ArrayIndex;
if (Index != 1)
return false;
BaseType = CT->getElementType();
- } else if (auto *FD = getAsField(LVal.Designator.Entries[I])) {
+ } else if (auto *FD = getAsField(Entry)) {
bool Invalid;
if (!IsLastOrInvalidFieldDecl(FD, Invalid))
return Invalid;
BaseType = FD->getType();
} else {
- assert(getAsBaseClass(LVal.Designator.Entries[I]) != nullptr &&
- "Expecting cast to a base class");
+ assert(getAsBaseClass(Entry) && "Expecting cast to a base class");
return false;
}
}
return true;
}
-/// Tests to see if the LValue has a designator (that isn't necessarily valid).
+/// Tests to see if the LValue has a user-specified designator (that isn't
+/// necessarily valid). Note that this always returns 'true' if the LValue has
+/// an unsized array as its first designator entry, because there's currently no
+/// way to tell if the user typed *foo or foo[0].
static bool refersToCompleteObject(const LValue &LVal) {
- if (LVal.Designator.Invalid || !LVal.Designator.Entries.empty())
+ if (LVal.Designator.Invalid)
return false;
+ if (!LVal.Designator.Entries.empty())
+ return LVal.Designator.isMostDerivedAnUnsizedArray();
+
if (!LVal.InvalidBase)
return true;
- auto *E = LVal.Base.dyn_cast<const Expr *>();
- (void)E;
- assert(E != nullptr && isa<MemberExpr>(E));
- return false;
+ // If `E` is a MemberExpr, then the first part of the designator is hiding in
+ // the LValueBase.
+ const auto *E = LVal.Base.dyn_cast<const Expr *>();
+ return !E || !isa<MemberExpr>(E);
+}
+
+/// Attempts to detect a user writing into a piece of memory that's impossible
+/// to figure out the size of by just using types.
+static bool isUserWritingOffTheEnd(const ASTContext &Ctx, const LValue &LVal) {
+ const SubobjectDesignator &Designator = LVal.Designator;
+ // Notes:
+ // - Users can only write off of the end when we have an invalid base. Invalid
+ // bases imply we don't know where the memory came from.
+ // - We used to be a bit more aggressive here; we'd only be conservative if
+ // the array at the end was flexible, or if it had 0 or 1 elements. This
+ // broke some common standard library extensions (PR30346), but was
+ // otherwise seemingly fine. It may be useful to reintroduce this behavior
+ // with some sort of whitelist. OTOH, it seems that GCC is always
+ // conservative with the last element in structs (if it's an array), so our
+ // current behavior is more compatible than a whitelisting approach would
+ // be.
+ return LVal.InvalidBase &&
+ Designator.Entries.size() == Designator.MostDerivedPathLength &&
+ Designator.MostDerivedIsArrayElement &&
+ isDesignatorAtObjectEnd(Ctx, LVal);
+}
+
+/// Converts the given APInt to CharUnits, assuming the APInt is unsigned.
+/// Fails if the conversion would cause loss of precision.
+static bool convertUnsignedAPIntToCharUnits(const llvm::APInt &Int,
+ CharUnits &Result) {
+ auto CharUnitsMax = std::numeric_limits<CharUnits::QuantityType>::max();
+ if (Int.ugt(CharUnitsMax))
+ return false;
+ Result = CharUnits::fromQuantity(Int.getZExtValue());
+ return true;
}
-/// Tries to evaluate the __builtin_object_size for @p E. If successful, returns
-/// true and stores the result in @p Size.
+/// Helper for tryEvaluateBuiltinObjectSize -- Given an LValue, this will
+/// determine how many bytes exist from the beginning of the object to either
+/// the end of the current subobject, or the end of the object itself, depending
+/// on what the LValue looks like + the value of Type.
///
-/// If @p WasError is non-null, this will report whether the failure to evaluate
-/// is to be treated as an Error in IntExprEvaluator.
-static bool tryEvaluateBuiltinObjectSize(const Expr *E, unsigned Type,
- EvalInfo &Info, uint64_t &Size,
- bool *WasError = nullptr) {
- if (WasError != nullptr)
- *WasError = false;
-
- auto Error = [&](const Expr *E) {
- if (WasError != nullptr)
- *WasError = true;
+/// If this returns false, the value of Result is undefined.
+static bool determineEndOffset(EvalInfo &Info, SourceLocation ExprLoc,
+ unsigned Type, const LValue &LVal,
+ CharUnits &EndOffset) {
+ bool DetermineForCompleteObject = refersToCompleteObject(LVal);
+
+ // We want to evaluate the size of the entire object. This is a valid fallback
+ // for when Type=1 and the designator is invalid, because we're asked for an
+ // upper-bound.
+ if (!(Type & 1) || LVal.Designator.Invalid || DetermineForCompleteObject) {
+ // Type=3 wants a lower bound, so we can't fall back to this.
+ if (Type == 3 && !DetermineForCompleteObject)
+ return false;
+
+ llvm::APInt APEndOffset;
+ if (isBaseAnAllocSizeCall(LVal.getLValueBase()) &&
+ getBytesReturnedByAllocSizeCall(Info.Ctx, LVal, APEndOffset))
+ return convertUnsignedAPIntToCharUnits(APEndOffset, EndOffset);
+
+ if (LVal.InvalidBase)
+ return false;
+
+ QualType BaseTy = getObjectType(LVal.getLValueBase());
+ return !BaseTy.isNull() && HandleSizeof(Info, ExprLoc, BaseTy, EndOffset);
+ }
+
+ // We want to evaluate the size of a subobject.
+ const SubobjectDesignator &Designator = LVal.Designator;
+
+ // The following is a moderately common idiom in C:
+ //
+ // struct Foo { int a; char c[1]; };
+ // struct Foo *F = (struct Foo *)malloc(sizeof(struct Foo) + strlen(Bar));
+ // strcpy(&F->c[0], Bar);
+ //
+ // In order to not break too much legacy code, we need to support it.
+ if (isUserWritingOffTheEnd(Info.Ctx, LVal)) {
+ // If we can resolve this to an alloc_size call, we can hand that back,
+ // because we know for certain how many bytes there are to write to.
+ llvm::APInt APEndOffset;
+ if (isBaseAnAllocSizeCall(LVal.getLValueBase()) &&
+ getBytesReturnedByAllocSizeCall(Info.Ctx, LVal, APEndOffset))
+ return convertUnsignedAPIntToCharUnits(APEndOffset, EndOffset);
+
+ // If we cannot determine the size of the initial allocation, then we can't
+ // given an accurate upper-bound. However, we are still able to give
+ // conservative lower-bounds for Type=3.
+ if (Type == 1)
+ return false;
+ }
+
+ CharUnits BytesPerElem;
+ if (!HandleSizeof(Info, ExprLoc, Designator.MostDerivedType, BytesPerElem))
return false;
- };
- auto Success = [&](uint64_t S, const Expr *E) {
- Size = S;
- return true;
- };
+ // According to the GCC documentation, we want the size of the subobject
+ // denoted by the pointer. But that's not quite right -- what we actually
+ // want is the size of the immediately-enclosing array, if there is one.
+ int64_t ElemsRemaining;
+ if (Designator.MostDerivedIsArrayElement &&
+ Designator.Entries.size() == Designator.MostDerivedPathLength) {
+ uint64_t ArraySize = Designator.getMostDerivedArraySize();
+ uint64_t ArrayIndex = Designator.Entries.back().ArrayIndex;
+ ElemsRemaining = ArraySize <= ArrayIndex ? 0 : ArraySize - ArrayIndex;
+ } else {
+ ElemsRemaining = Designator.isOnePastTheEnd() ? 0 : 1;
+ }
+ EndOffset = LVal.getLValueOffset() + BytesPerElem * ElemsRemaining;
+ return true;
+}
+
+/// \brief 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
+/// is to be treated as an Error in IntExprEvaluator.
+static bool tryEvaluateBuiltinObjectSize(const Expr *E, unsigned Type,
+ EvalInfo &Info, uint64_t &Size) {
// Determine the denoted object.
- LValue Base;
+ LValue LVal;
{
// The operand of __builtin_object_size is never evaluated for side-effects.
// If there are any, but we can determine the pointed-to object anyway, then
// ignore the side-effects.
SpeculativeEvaluationRAII SpeculativeEval(Info);
- FoldOffsetRAII Fold(Info, Type & 1);
+ FoldOffsetRAII Fold(Info);
if (E->isGLValue()) {
// It's possible for us to be given GLValues if we're called via
@@ -6713,118 +7280,40 @@ static bool tryEvaluateBuiltinObjectSize(const Expr *E, unsigned Type,
APValue RVal;
if (!EvaluateAsRValue(Info, E, RVal))
return false;
- Base.setFrom(Info.Ctx, RVal);
- } else if (!EvaluatePointer(ignorePointerCastsAndParens(E), Base, Info))
+ LVal.setFrom(Info.Ctx, RVal);
+ } else if (!EvaluatePointer(ignorePointerCastsAndParens(E), LVal, Info))
return false;
}
- CharUnits BaseOffset = Base.getLValueOffset();
// If we point to before the start of the object, there are no accessible
// bytes.
- if (BaseOffset.isNegative())
- return Success(0, E);
-
- // In the case where we're not dealing with a subobject, we discard the
- // subobject bit.
- bool SubobjectOnly = (Type & 1) != 0 && !refersToCompleteObject(Base);
-
- // If Type & 1 is 0, we need to be able to statically guarantee that the bytes
- // exist. If we can't verify the base, then we can't do that.
- //
- // As a special case, we produce a valid object size for an unknown object
- // with a known designator if Type & 1 is 1. For instance:
- //
- // extern struct X { char buff[32]; int a, b, c; } *p;
- // int a = __builtin_object_size(p->buff + 4, 3); // returns 28
- // int b = __builtin_object_size(p->buff + 4, 2); // returns 0, not 40
- //
- // This matches GCC's behavior.
- if (Base.InvalidBase && !SubobjectOnly)
- return Error(E);
-
- // If we're not examining only the subobject, then we reset to a complete
- // object designator
- //
- // If Type is 1 and we've lost track of the subobject, just find the complete
- // object instead. (If Type is 3, that's not correct behavior and we should
- // return 0 instead.)
- LValue End = Base;
- if (!SubobjectOnly || (End.Designator.Invalid && Type == 1)) {
- QualType T = getObjectType(End.getLValueBase());
- if (T.isNull())
- End.Designator.setInvalid();
- else {
- End.Designator = SubobjectDesignator(T);
- End.Offset = CharUnits::Zero();
- }
+ if (LVal.getLValueOffset().isNegative()) {
+ Size = 0;
+ return true;
}
- // If it is not possible to determine which objects ptr points to at compile
- // time, __builtin_object_size should return (size_t) -1 for type 0 or 1
- // and (size_t) 0 for type 2 or 3.
- if (End.Designator.Invalid)
- return false;
-
- // According to the GCC documentation, we want the size of the subobject
- // denoted by the pointer. But that's not quite right -- what we actually
- // want is the size of the immediately-enclosing array, if there is one.
- int64_t AmountToAdd = 1;
- if (End.Designator.MostDerivedIsArrayElement &&
- End.Designator.Entries.size() == End.Designator.MostDerivedPathLength) {
- // We got a pointer to an array. Step to its end.
- AmountToAdd = End.Designator.MostDerivedArraySize -
- End.Designator.Entries.back().ArrayIndex;
- } else if (End.Designator.isOnePastTheEnd()) {
- // We're already pointing at the end of the object.
- AmountToAdd = 0;
- }
-
- QualType PointeeType = End.Designator.MostDerivedType;
- assert(!PointeeType.isNull());
- if (PointeeType->isIncompleteType() || PointeeType->isFunctionType())
- return Error(E);
-
- if (!HandleLValueArrayAdjustment(Info, E, End, End.Designator.MostDerivedType,
- AmountToAdd))
- return false;
-
- auto EndOffset = End.getLValueOffset();
-
- // The following is a moderately common idiom in C:
- //
- // struct Foo { int a; char c[1]; };
- // struct Foo *F = (struct Foo *)malloc(sizeof(struct Foo) + strlen(Bar));
- // strcpy(&F->c[0], Bar);
- //
- // So, if we see that we're examining a 1-length (or 0-length) array at the
- // end of a struct with an unknown base, we give up instead of breaking code
- // that behaves this way. Note that we only do this when Type=1, because
- // Type=3 is a lower bound, so answering conservatively is fine.
- if (End.InvalidBase && SubobjectOnly && Type == 1 &&
- End.Designator.Entries.size() == End.Designator.MostDerivedPathLength &&
- End.Designator.MostDerivedIsArrayElement &&
- End.Designator.MostDerivedArraySize < 2 &&
- isDesignatorAtObjectEnd(Info.Ctx, End))
+ CharUnits EndOffset;
+ if (!determineEndOffset(Info, E->getExprLoc(), Type, LVal, EndOffset))
return false;
- if (BaseOffset > EndOffset)
- return Success(0, E);
-
- return Success((EndOffset - BaseOffset).getQuantity(), E);
+ // If we've fallen outside of the end offset, just pretend there's nothing to
+ // write to/read from.
+ if (EndOffset <= LVal.getLValueOffset())
+ Size = 0;
+ else
+ Size = (EndOffset - LVal.getLValueOffset()).getQuantity();
+ return true;
}
-bool IntExprEvaluator::TryEvaluateBuiltinObjectSize(const CallExpr *E,
- unsigned Type) {
- uint64_t Size;
- bool WasError;
- if (::tryEvaluateBuiltinObjectSize(E->getArg(0), Type, Info, Size, &WasError))
- return Success(Size, E);
- if (WasError)
- return Error(E);
- return false;
+bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
+ if (unsigned BuiltinOp = E->getBuiltinCallee())
+ return VisitBuiltinCallExpr(E, BuiltinOp);
+
+ return ExprEvaluatorBaseTy::VisitCallExpr(E);
}
-bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
+bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
+ unsigned BuiltinOp) {
switch (unsigned BuiltinOp = E->getBuiltinCallee()) {
default:
return ExprEvaluatorBaseTy::VisitCallExpr(E);
@@ -6835,8 +7324,9 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
E->getArg(1)->EvaluateKnownConstInt(Info.Ctx).getZExtValue();
assert(Type <= 3 && "unexpected type");
- if (TryEvaluateBuiltinObjectSize(E, Type))
- return true;
+ uint64_t Size;
+ if (tryEvaluateBuiltinObjectSize(E->getArg(0), Type, Info, Size))
+ return Success(Size, E);
if (E->getArg(0)->HasSideEffects(Info.Ctx))
return Success((Type & 2) ? 0 : -1, E);
@@ -6849,7 +7339,7 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
case EvalInfo::EM_ConstantFold:
case EvalInfo::EM_EvaluateForOverflow:
case EvalInfo::EM_IgnoreSideEffects:
- case EvalInfo::EM_DesignatorFold:
+ case EvalInfo::EM_OffsetFold:
// Leave it to IR generation.
return Error(E);
case EvalInfo::EM_ConstantExpressionUnevaluated:
@@ -6857,6 +7347,8 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
// Reduce it to a constant now.
return Success((Type & 2) ? 0 : -1, E);
}
+
+ llvm_unreachable("unexpected EvalMode");
}
case Builtin::BI__builtin_bswap16:
@@ -6990,20 +7482,25 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
}
case Builtin::BIstrlen:
+ case Builtin::BIwcslen:
// A call to strlen is not a constant expression.
if (Info.getLangOpts().CPlusPlus11)
Info.CCEDiag(E, diag::note_constexpr_invalid_function)
- << /*isConstexpr*/0 << /*isConstructor*/0 << "'strlen'";
+ << /*isConstexpr*/0 << /*isConstructor*/0
+ << (std::string("'") + Info.Ctx.BuiltinInfo.getName(BuiltinOp) + "'");
else
Info.CCEDiag(E, diag::note_invalid_subexpr_in_const_expr);
// Fall through.
- case Builtin::BI__builtin_strlen: {
+ case Builtin::BI__builtin_strlen:
+ case Builtin::BI__builtin_wcslen: {
// As an extension, we support __builtin_strlen() as a constant expression,
// and support folding strlen() to a constant.
LValue String;
if (!EvaluatePointer(E->getArg(0), String, Info))
return false;
+ QualType CharTy = E->getArg(0)->getType()->getPointeeType();
+
// Fast path: if it's a string literal, search the string value.
if (const StringLiteral *S = dyn_cast_or_null<StringLiteral>(
String.getLValueBase().dyn_cast<const Expr *>())) {
@@ -7012,7 +7509,9 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
StringRef Str = S->getBytes();
int64_t Off = String.Offset.getQuantity();
if (Off >= 0 && (uint64_t)Off <= (uint64_t)Str.size() &&
- S->getCharByteWidth() == 1) {
+ S->getCharByteWidth() == 1 &&
+ // FIXME: Add fast-path for wchar_t too.
+ Info.Ctx.hasSameUnqualifiedType(CharTy, Info.Ctx.CharTy)) {
Str = Str.substr(Off);
StringRef::size_type Pos = Str.find(0);
@@ -7026,7 +7525,6 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
}
// Slow path: scan the bytes of the string looking for the terminating 0.
- QualType CharTy = E->getArg(0)->getType()->getPointeeType();
for (uint64_t Strlen = 0; /**/; ++Strlen) {
APValue Char;
if (!handleLValueToRValueConversion(Info, E, CharTy, String, Char) ||
@@ -7039,6 +7537,66 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
}
}
+ case Builtin::BIstrcmp:
+ case Builtin::BIwcscmp:
+ case Builtin::BIstrncmp:
+ case Builtin::BIwcsncmp:
+ case Builtin::BImemcmp:
+ case Builtin::BIwmemcmp:
+ // A call to strlen is not a constant expression.
+ if (Info.getLangOpts().CPlusPlus11)
+ Info.CCEDiag(E, diag::note_constexpr_invalid_function)
+ << /*isConstexpr*/0 << /*isConstructor*/0
+ << (std::string("'") + Info.Ctx.BuiltinInfo.getName(BuiltinOp) + "'");
+ else
+ Info.CCEDiag(E, diag::note_invalid_subexpr_in_const_expr);
+ // Fall through.
+ case Builtin::BI__builtin_strcmp:
+ case Builtin::BI__builtin_wcscmp:
+ case Builtin::BI__builtin_strncmp:
+ case Builtin::BI__builtin_wcsncmp:
+ case Builtin::BI__builtin_memcmp:
+ case Builtin::BI__builtin_wmemcmp: {
+ LValue String1, String2;
+ if (!EvaluatePointer(E->getArg(0), String1, Info) ||
+ !EvaluatePointer(E->getArg(1), String2, Info))
+ return false;
+
+ QualType CharTy = E->getArg(0)->getType()->getPointeeType();
+
+ uint64_t MaxLength = uint64_t(-1);
+ if (BuiltinOp != Builtin::BIstrcmp &&
+ BuiltinOp != Builtin::BIwcscmp &&
+ BuiltinOp != Builtin::BI__builtin_strcmp &&
+ BuiltinOp != Builtin::BI__builtin_wcscmp) {
+ APSInt N;
+ if (!EvaluateInteger(E->getArg(2), N, Info))
+ return false;
+ MaxLength = N.getExtValue();
+ }
+ bool StopAtNull = (BuiltinOp != Builtin::BImemcmp &&
+ BuiltinOp != Builtin::BIwmemcmp &&
+ BuiltinOp != Builtin::BI__builtin_memcmp &&
+ 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 (StopAtNull && !Char1.getInt())
+ return Success(0, E);
+ assert(!(StopAtNull && !Char2.getInt()));
+ if (!HandleLValueArrayAdjustment(Info, E, String1, CharTy, 1) ||
+ !HandleLValueArrayAdjustment(Info, E, String2, CharTy, 1))
+ return false;
+ }
+ // We hit the strncmp / memcmp limit.
+ return Success(0, E);
+ }
+
case Builtin::BI__atomic_always_lock_free:
case Builtin::BI__atomic_is_lock_free:
case Builtin::BI__c11_atomic_is_lock_free: {
@@ -7160,9 +7718,7 @@ class DataRecursiveIntBinOpEvaluator {
enum { AnyExprKind, BinOpKind, BinOpVisitedLHSKind } Kind;
Job() = default;
- Job(Job &&J)
- : E(J.E), LHSResult(J.LHSResult), Kind(J.Kind),
- SpecEvalRAII(std::move(J.SpecEvalRAII)) {}
+ Job(Job &&) = default;
void startSpeculativeEval(EvalInfo &Info) {
SpecEvalRAII = SpeculativeEvaluationRAII(Info);
@@ -8037,8 +8593,10 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) {
case CK_IntegralComplexToFloatingComplex:
case CK_BuiltinFnToFnPtr:
case CK_ZeroToOCLEvent:
+ case CK_ZeroToOCLQueue:
case CK_NonAtomicToAtomic:
case CK_AddressSpaceConversion:
+ case CK_IntToOCLSampler:
llvm_unreachable("invalid cast kind for integral value");
case CK_BitCast:
@@ -8113,8 +8671,13 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) {
return true;
}
- APSInt AsInt = Info.Ctx.MakeIntValue(LV.getLValueOffset().getQuantity(),
- SrcType);
+ uint64_t V;
+ if (LV.isNullPointer())
+ V = Info.Ctx.getTargetNullPointerValue(SrcType);
+ else
+ V = LV.getLValueOffset().getQuantity();
+
+ APSInt AsInt = Info.Ctx.MakeIntValue(V, SrcType);
return Success(HandleIntToIntCast(Info, E, DestType, SrcType, AsInt), E);
}
@@ -8528,8 +9091,10 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) {
case CK_CopyAndAutoreleaseBlockObject:
case CK_BuiltinFnToFnPtr:
case CK_ZeroToOCLEvent:
+ case CK_ZeroToOCLQueue:
case CK_NonAtomicToAtomic:
case CK_AddressSpaceConversion:
+ case CK_IntToOCLSampler:
llvm_unreachable("invalid cast kind for complex value");
case CK_LValueToRValue:
@@ -9341,6 +9906,8 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
case Expr::CompoundLiteralExprClass:
case Expr::ExtVectorElementExprClass:
case Expr::DesignatedInitExprClass:
+ case Expr::ArrayInitLoopExprClass:
+ case Expr::ArrayInitIndexExprClass:
case Expr::NoInitExprClass:
case Expr::DesignatedInitUpdateExprClass:
case Expr::ImplicitValueInitExprClass:
@@ -9877,5 +10444,5 @@ bool Expr::tryEvaluateObjectSize(uint64_t &Result, ASTContext &Ctx,
Expr::EvalStatus Status;
EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantFold);
- return ::tryEvaluateBuiltinObjectSize(this, Type, Info, Result);
+ return tryEvaluateBuiltinObjectSize(this, Type, Info, Result);
}
diff --git a/lib/AST/ExprObjC.cpp b/lib/AST/ExprObjC.cpp
index 0936a81a597a..31c1b3f15621 100644
--- a/lib/AST/ExprObjC.cpp
+++ b/lib/AST/ExprObjC.cpp
@@ -278,7 +278,7 @@ ObjCMessageExpr *ObjCMessageExpr::alloc(const ASTContext &C, unsigned NumArgs,
unsigned NumStoredSelLocs) {
return (ObjCMessageExpr *)C.Allocate(
totalSizeToAlloc<void *, SourceLocation>(NumArgs + 1, NumStoredSelLocs),
- llvm::AlignOf<ObjCMessageExpr>::Alignment);
+ alignof(ObjCMessageExpr));
}
void ObjCMessageExpr::getSelectorLocs(
diff --git a/lib/AST/ItaniumCXXABI.cpp b/lib/AST/ItaniumCXXABI.cpp
index 8a2cc0fbee42..692a455eafc0 100644
--- a/lib/AST/ItaniumCXXABI.cpp
+++ b/lib/AST/ItaniumCXXABI.cpp
@@ -63,9 +63,10 @@ public:
CallOperator->getType()->getAs<FunctionProtoType>();
ASTContext &Context = CallOperator->getASTContext();
+ FunctionProtoType::ExtProtoInfo EPI;
+ EPI.Variadic = Proto->isVariadic();
QualType Key =
- Context.getFunctionType(Context.VoidTy, Proto->getParamTypes(),
- FunctionProtoType::ExtProtoInfo());
+ Context.getFunctionType(Context.VoidTy, Proto->getParamTypes(), EPI);
Key = Context.getCanonicalType(Key);
return ++ManglingNumbers[Key->castAs<FunctionProtoType>()];
}
@@ -141,14 +142,6 @@ public:
void addCopyConstructorForExceptionObject(CXXRecordDecl *RD,
CXXConstructorDecl *CD) override {}
- void addDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
- unsigned ParmIdx, Expr *DAE) override {}
-
- Expr *getDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
- unsigned ParmIdx) override {
- return nullptr;
- }
-
void addTypedefNameForUnnamedTagDecl(TagDecl *TD,
TypedefNameDecl *DD) override {}
@@ -163,8 +156,9 @@ public:
return nullptr;
}
- MangleNumberingContext *createMangleNumberingContext() const override {
- return new ItaniumNumberingContext();
+ std::unique_ptr<MangleNumberingContext>
+ createMangleNumberingContext() const override {
+ return llvm::make_unique<ItaniumNumberingContext>();
}
};
}
diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp
index 694fde317542..ab3e49d903cf 100644
--- a/lib/AST/ItaniumMangle.cpp
+++ b/lib/AST/ItaniumMangle.cpp
@@ -405,12 +405,14 @@ public:
CXXNameMangler(CXXNameMangler &Outer, raw_ostream &Out_)
: Context(Outer.Context), Out(Out_), NullOut(false),
Structor(Outer.Structor), StructorType(Outer.StructorType),
- SeqID(Outer.SeqID), AbiTagsRoot(AbiTags) {}
+ SeqID(Outer.SeqID), FunctionTypeDepth(Outer.FunctionTypeDepth),
+ AbiTagsRoot(AbiTags), Substitutions(Outer.Substitutions) {}
CXXNameMangler(CXXNameMangler &Outer, llvm::raw_null_ostream &Out_)
: Context(Outer.Context), Out(Out_), NullOut(true),
Structor(Outer.Structor), StructorType(Outer.StructorType),
- SeqID(Outer.SeqID), AbiTagsRoot(AbiTags) {}
+ SeqID(Outer.SeqID), FunctionTypeDepth(Outer.FunctionTypeDepth),
+ AbiTagsRoot(AbiTags), Substitutions(Outer.Substitutions) {}
#if MANGLE_CHECKER
~CXXNameMangler() {
@@ -458,11 +460,15 @@ private:
void addSubstitution(QualType T);
void addSubstitution(TemplateName Template);
void addSubstitution(uintptr_t Ptr);
+ // Destructive copy substitutions from other mangler.
+ void extendSubstitutions(CXXNameMangler* Other);
void mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
bool recursive = false);
void mangleUnresolvedName(NestedNameSpecifier *qualifier,
DeclarationName name,
+ const TemplateArgumentLoc *TemplateArgs,
+ unsigned NumTemplateArgs,
unsigned KnownArity = UnknownArity);
void mangleFunctionEncodingBareType(const FunctionDecl *FD);
@@ -487,6 +493,7 @@ private:
void mangleUnscopedTemplateName(TemplateName,
const AbiTagList *AdditionalAbiTags);
void mangleSourceName(const IdentifierInfo *II);
+ void mangleRegCallName(const IdentifierInfo *II);
void mangleSourceNameWithAbiTags(
const NamedDecl *ND, const AbiTagList *AdditionalAbiTags = nullptr);
void mangleLocalName(const Decl *D,
@@ -537,6 +544,8 @@ private:
NestedNameSpecifier *qualifier,
NamedDecl *firstQualifierLookup,
DeclarationName name,
+ const TemplateArgumentLoc *TemplateArgs,
+ unsigned NumTemplateArgs,
unsigned knownArity);
void mangleCastExpression(const Expr *E, StringRef CastEncoding);
void mangleInitListElements(const InitListExpr *InitList);
@@ -593,7 +602,7 @@ bool ItaniumMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) {
return false;
const VarDecl *VD = dyn_cast<VarDecl>(D);
- if (VD) {
+ if (VD && !isa<DecompositionDecl>(D)) {
// C variables are not mangled.
if (VD->isExternC())
return false;
@@ -685,6 +694,10 @@ void CXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) {
// Output name with implicit tags and function encoding from temporary buffer.
mangleNameWithAbiTags(FD, &AdditionalAbiTags);
Out << FunctionEncodingStream.str().substr(EncodingPositionStart);
+
+ // Function encoding could create new substitutions so we have to add
+ // temp mangled substitutions to main mangler.
+ extendSubstitutions(&FunctionEncodingMangler);
}
void CXXNameMangler::mangleFunctionEncodingBareType(const FunctionDecl *FD) {
@@ -1151,9 +1164,10 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
/// Mangle an unresolved-name, which is generally used for names which
/// weren't resolved to specific entities.
-void CXXNameMangler::mangleUnresolvedName(NestedNameSpecifier *qualifier,
- DeclarationName name,
- unsigned knownArity) {
+void CXXNameMangler::mangleUnresolvedName(
+ NestedNameSpecifier *qualifier, DeclarationName name,
+ const TemplateArgumentLoc *TemplateArgs, unsigned NumTemplateArgs,
+ unsigned knownArity) {
if (qualifier) mangleUnresolvedPrefix(qualifier);
switch (name.getNameKind()) {
// <base-unresolved-name> ::= <simple-id>
@@ -1181,6 +1195,11 @@ void CXXNameMangler::mangleUnresolvedName(NestedNameSpecifier *qualifier,
case DeclarationName::ObjCZeroArgSelector:
llvm_unreachable("Can't mangle Objective-C selector names here!");
}
+
+ // The <simple-id> and on <operator-name> productions end in an optional
+ // <template-args>.
+ if (TemplateArgs)
+ mangleTemplateArgs(TemplateArgs, NumTemplateArgs);
}
void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
@@ -1193,7 +1212,26 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
// ::= <source-name>
switch (Name.getNameKind()) {
case DeclarationName::Identifier: {
- if (const IdentifierInfo *II = Name.getAsIdentifierInfo()) {
+ const IdentifierInfo *II = Name.getAsIdentifierInfo();
+
+ // We mangle decomposition declarations as the names of their bindings.
+ if (auto *DD = dyn_cast<DecompositionDecl>(ND)) {
+ // FIXME: Non-standard mangling for decomposition declarations:
+ //
+ // <unqualified-name> ::= DC <source-name>* E
+ //
+ // These can never be referenced across translation units, so we do
+ // not need a cross-vendor mangling for anything other than demanglers.
+ // Proposed on cxx-abi-dev on 2016-08-12
+ Out << "DC";
+ for (auto *BD : DD->bindings())
+ mangleSourceName(BD->getDeclName().getAsIdentifierInfo());
+ Out << 'E';
+ writeAbiTags(ND, AdditionalAbiTags);
+ break;
+ }
+
+ if (II) {
// We must avoid conflicts between internally- and externally-
// linked variable and function declaration names in the same TU:
// void test() { extern void foo(); }
@@ -1204,7 +1242,15 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
getEffectiveDeclContext(ND)->isFileContext())
Out << 'L';
- mangleSourceName(II);
+ auto *FD = dyn_cast<FunctionDecl>(ND);
+ bool IsRegCall = FD &&
+ FD->getType()->castAs<FunctionType>()->getCallConv() ==
+ clang::CC_X86RegCall;
+ if (IsRegCall)
+ mangleRegCallName(II);
+ else
+ mangleSourceName(II);
+
writeAbiTags(ND, AdditionalAbiTags);
break;
}
@@ -1378,6 +1424,14 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
}
}
+void CXXNameMangler::mangleRegCallName(const IdentifierInfo *II) {
+ // <source-name> ::= <positive length number> __regcall3__ <identifier>
+ // <number> ::= [n] <non-negative decimal integer>
+ // <identifier> ::= <unqualified source code identifier>
+ Out << II->getLength() + sizeof("__regcall3__") - 1 << "__regcall3__"
+ << II->getName();
+}
+
void CXXNameMangler::mangleSourceName(const IdentifierInfo *II) {
// <source-name> ::= <positive length number> <identifier>
// <number> ::= [n] <non-negative decimal integer>
@@ -1471,7 +1525,7 @@ void CXXNameMangler::mangleLocalName(const Decl *D,
// numbering will be local to the particular argument in which it appears
// -- other default arguments do not affect its encoding.
const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD);
- if (CXXRD->isLambda()) {
+ if (CXXRD && CXXRD->isLambda()) {
if (const ParmVarDecl *Parm
= dyn_cast_or_null<ParmVarDecl>(CXXRD->getLambdaContextDecl())) {
if (const FunctionDecl *Func
@@ -1820,6 +1874,7 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty,
case Type::ObjCObject:
case Type::ObjCInterface:
case Type::ObjCObjectPointer:
+ case Type::ObjCTypeParam:
case Type::Atomic:
case Type::Pipe:
llvm_unreachable("type is illegal as a nested name specifier");
@@ -2207,6 +2262,22 @@ void CXXNameMangler::mangleType(QualType T) {
// they aren't written.
// - Conversions on non-type template arguments need to be expressed, since
// they can affect the mangling of sizeof/alignof.
+ //
+ // FIXME: This is wrong when mapping to the canonical type for a dependent
+ // type discards instantiation-dependent portions of the type, such as for:
+ //
+ // template<typename T, int N> void f(T (&)[sizeof(N)]);
+ // template<typename T> void f(T() throw(typename T::type)); (pre-C++17)
+ //
+ // It's also wrong in the opposite direction when instantiation-dependent,
+ // canonically-equivalent types differ in some irrelevant portion of inner
+ // type sugar. In such cases, we fail to form correct substitutions, eg:
+ //
+ // template<int N> void f(A<sizeof(N)> *, A<sizeof(N)> (*));
+ //
+ // We should instead canonicalize the non-instantiation-dependent parts,
+ // regardless of whether the type as a whole is dependent or instantiation
+ // dependent.
if (!T->isInstantiationDependentType() || T->isDependentType())
T = T.getCanonicalType();
else {
@@ -2443,6 +2514,7 @@ StringRef CXXNameMangler::getCallingConvQualifierName(CallingConv CC) {
case CC_X86Pascal:
case CC_X86_64Win64:
case CC_X86_64SysV:
+ case CC_X86RegCall:
case CC_AAPCS:
case CC_AAPCS_VFP:
case CC_IntelOclBicc:
@@ -2509,6 +2581,24 @@ void CXXNameMangler::mangleType(const FunctionProtoType *T) {
// e.g. "const" in "int (A::*)() const".
mangleQualifiers(Qualifiers::fromCVRMask(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) {
+ Out << "DO";
+ mangleExpression(T->getNoexceptExpr());
+ Out << "E";
+ } else {
+ assert(T->getExceptionSpecType() == EST_Dynamic);
+ Out << "Dw";
+ for (auto ExceptTy : T->exceptions())
+ mangleType(ExceptTy);
+ Out << "E";
+ }
+ } else if (T->isNothrow(getASTContext())) {
+ Out << "Do";
+ }
+
Out << 'F';
// FIXME: We don't have enough information in the AST to produce the 'Y'
@@ -3115,12 +3205,14 @@ void CXXNameMangler::mangleMemberExpr(const Expr *base,
NestedNameSpecifier *qualifier,
NamedDecl *firstQualifierLookup,
DeclarationName member,
+ const TemplateArgumentLoc *TemplateArgs,
+ unsigned NumTemplateArgs,
unsigned arity) {
// <expression> ::= dt <expression> <unresolved-name>
// ::= pt <expression> <unresolved-name>
if (base)
mangleMemberExprBase(base, isArrow);
- mangleUnresolvedName(qualifier, member, arity);
+ mangleUnresolvedName(qualifier, member, TemplateArgs, NumTemplateArgs, arity);
}
/// Look at the callee of the given call expression and determine if
@@ -3209,6 +3301,8 @@ recurse:
case Expr::AddrLabelExprClass:
case Expr::DesignatedInitUpdateExprClass:
case Expr::ImplicitValueInitExprClass:
+ case Expr::ArrayInitLoopExprClass:
+ case Expr::ArrayInitIndexExprClass:
case Expr::NoInitExprClass:
case Expr::ParenListExprClass:
case Expr::LambdaExprClass:
@@ -3418,7 +3512,9 @@ recurse:
const MemberExpr *ME = cast<MemberExpr>(E);
mangleMemberExpr(ME->getBase(), ME->isArrow(),
ME->getQualifier(), nullptr,
- ME->getMemberDecl()->getDeclName(), Arity);
+ ME->getMemberDecl()->getDeclName(),
+ ME->getTemplateArgs(), ME->getNumTemplateArgs(),
+ Arity);
break;
}
@@ -3426,9 +3522,9 @@ recurse:
const UnresolvedMemberExpr *ME = cast<UnresolvedMemberExpr>(E);
mangleMemberExpr(ME->isImplicitAccess() ? nullptr : ME->getBase(),
ME->isArrow(), ME->getQualifier(), nullptr,
- ME->getMemberName(), Arity);
- if (ME->hasExplicitTemplateArgs())
- mangleTemplateArgs(ME->getTemplateArgs(), ME->getNumTemplateArgs());
+ ME->getMemberName(),
+ ME->getTemplateArgs(), ME->getNumTemplateArgs(),
+ Arity);
break;
}
@@ -3438,21 +3534,17 @@ recurse:
mangleMemberExpr(ME->isImplicitAccess() ? nullptr : ME->getBase(),
ME->isArrow(), ME->getQualifier(),
ME->getFirstQualifierFoundInScope(),
- ME->getMember(), Arity);
- if (ME->hasExplicitTemplateArgs())
- mangleTemplateArgs(ME->getTemplateArgs(), ME->getNumTemplateArgs());
+ ME->getMember(),
+ ME->getTemplateArgs(), ME->getNumTemplateArgs(),
+ Arity);
break;
}
case Expr::UnresolvedLookupExprClass: {
const UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(E);
- mangleUnresolvedName(ULE->getQualifier(), ULE->getName(), Arity);
-
- // All the <unresolved-name> productions end in a
- // base-unresolved-name, where <template-args> are just tacked
- // onto the end.
- if (ULE->hasExplicitTemplateArgs())
- mangleTemplateArgs(ULE->getTemplateArgs(), ULE->getNumTemplateArgs());
+ mangleUnresolvedName(ULE->getQualifier(), ULE->getName(),
+ ULE->getTemplateArgs(), ULE->getNumTemplateArgs(),
+ Arity);
break;
}
@@ -3707,7 +3799,10 @@ recurse:
case Expr::CXXOperatorCallExprClass: {
const CXXOperatorCallExpr *CE = cast<CXXOperatorCallExpr>(E);
unsigned NumArgs = CE->getNumArgs();
- mangleOperatorName(CE->getOperator(), /*Arity=*/NumArgs);
+ // A CXXOperatorCallExpr for OO_Arrow models only semantics, not syntax
+ // (the enclosing MemberExpr covers the syntactic portion).
+ if (CE->getOperator() != OO_Arrow)
+ mangleOperatorName(CE->getOperator(), /*Arity=*/NumArgs);
// Mangle the arguments.
for (unsigned i = 0; i != NumArgs; ++i)
mangleExpression(CE->getArg(i));
@@ -3768,13 +3863,9 @@ recurse:
case Expr::DependentScopeDeclRefExprClass: {
const DependentScopeDeclRefExpr *DRE = cast<DependentScopeDeclRefExpr>(E);
- mangleUnresolvedName(DRE->getQualifier(), DRE->getDeclName(), Arity);
-
- // All the <unresolved-name> productions end in a
- // base-unresolved-name, where <template-args> are just tacked
- // onto the end.
- if (DRE->hasExplicitTemplateArgs())
- mangleTemplateArgs(DRE->getTemplateArgs(), DRE->getNumTemplateArgs());
+ mangleUnresolvedName(DRE->getQualifier(), DRE->getDeclName(),
+ DRE->getTemplateArgs(), DRE->getNumTemplateArgs(),
+ Arity);
break;
}
@@ -4406,6 +4497,14 @@ void CXXNameMangler::addSubstitution(uintptr_t Ptr) {
Substitutions[Ptr] = SeqID++;
}
+void CXXNameMangler::extendSubstitutions(CXXNameMangler* Other) {
+ assert(Other->SeqID >= SeqID && "Must be superset of substitutions!");
+ if (Other->SeqID > SeqID) {
+ Substitutions.swap(Other->Substitutions);
+ SeqID = Other->SeqID;
+ }
+}
+
CXXNameMangler::AbiTagList
CXXNameMangler::makeFunctionReturnTypeTags(const FunctionDecl *FD) {
// When derived abi tags are disabled there is no need to make any list.
diff --git a/lib/AST/Mangle.cpp b/lib/AST/Mangle.cpp
index ee241732e8ad..05dd886adcef 100644
--- a/lib/AST/Mangle.cpp
+++ b/lib/AST/Mangle.cpp
@@ -52,6 +52,7 @@ void MangleContext::anchor() { }
enum CCMangling {
CCM_Other,
CCM_Fast,
+ CCM_RegCall,
CCM_Vector,
CCM_Std
};
@@ -152,6 +153,8 @@ void MangleContext::mangleName(const NamedDecl *D, raw_ostream &Out) {
Out << '_';
else if (CC == CCM_Fast)
Out << '@';
+ else if (CC == CCM_RegCall)
+ Out << "__regcall3__";
if (!MCXX)
Out << D->getIdentifier()->getName();
diff --git a/lib/AST/MicrosoftCXXABI.cpp b/lib/AST/MicrosoftCXXABI.cpp
index 3ae04538d626..73324e40f3b1 100644
--- a/lib/AST/MicrosoftCXXABI.cpp
+++ b/lib/AST/MicrosoftCXXABI.cpp
@@ -67,8 +67,6 @@ public:
class MicrosoftCXXABI : public CXXABI {
ASTContext &Context;
llvm::SmallDenseMap<CXXRecordDecl *, CXXConstructorDecl *> RecordToCopyCtor;
- llvm::SmallDenseMap<std::pair<const CXXConstructorDecl *, unsigned>, Expr *>
- CtorToDefaultArgExpr;
llvm::SmallDenseMap<TagDecl *, DeclaratorDecl *>
UnnamedTagDeclToDeclaratorDecl;
@@ -92,16 +90,6 @@ public:
llvm_unreachable("unapplicable to the MS ABI");
}
- void addDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
- unsigned ParmIdx, Expr *DAE) override {
- CtorToDefaultArgExpr[std::make_pair(CD, ParmIdx)] = DAE;
- }
-
- Expr *getDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
- unsigned ParmIdx) override {
- return CtorToDefaultArgExpr[std::make_pair(CD, ParmIdx)];
- }
-
const CXXConstructorDecl *
getCopyConstructorForExceptionObject(CXXRecordDecl *RD) override {
return RecordToCopyCtor[RD];
@@ -143,8 +131,9 @@ public:
const_cast<TagDecl *>(TD->getCanonicalDecl()));
}
- MangleNumberingContext *createMangleNumberingContext() const override {
- return new MicrosoftNumberingContext();
+ std::unique_ptr<MangleNumberingContext>
+ createMangleNumberingContext() const override {
+ return llvm::make_unique<MicrosoftNumberingContext>();
}
};
}
diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp
index 351997e02a9d..911b8b471a05 100644
--- a/lib/AST/MicrosoftMangle.cpp
+++ b/lib/AST/MicrosoftMangle.cpp
@@ -66,6 +66,16 @@ struct msvc_hashing_ostream : public llvm::raw_svector_ostream {
}
};
+static const DeclContext *
+getLambdaDefaultArgumentDeclContext(const Decl *D) {
+ if (const auto *RD = dyn_cast<CXXRecordDecl>(D))
+ if (RD->isLambda())
+ if (const auto *Parm =
+ dyn_cast_or_null<ParmVarDecl>(RD->getLambdaContextDecl()))
+ return Parm->getDeclContext();
+ return nullptr;
+}
+
/// \brief Retrieve the declaration context that should be used when mangling
/// the given declaration.
static const DeclContext *getEffectiveDeclContext(const Decl *D) {
@@ -75,12 +85,8 @@ static const DeclContext *getEffectiveDeclContext(const Decl *D) {
// not the case: the lambda closure type ends up living in the context
// where the function itself resides, because the function declaration itself
// had not yet been created. Fix the context here.
- if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
- if (RD->isLambda())
- if (ParmVarDecl *ContextParam =
- dyn_cast_or_null<ParmVarDecl>(RD->getLambdaContextDecl()))
- return ContextParam->getDeclContext();
- }
+ if (const auto *LDADC = getLambdaDefaultArgumentDeclContext(D))
+ return LDADC;
// Perform the same check for block literals.
if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
@@ -112,14 +118,6 @@ static const FunctionDecl *getStructor(const NamedDecl *ND) {
return FD;
}
-static bool isLambda(const NamedDecl *ND) {
- const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(ND);
- if (!Record)
- return false;
-
- return Record->isLambda();
-}
-
/// MicrosoftMangleContextImpl - Overrides the default MangleContext for the
/// Microsoft Visual C++ ABI.
class MicrosoftMangleContextImpl : public MicrosoftMangleContext {
@@ -200,9 +198,11 @@ public:
// Lambda closure types are already numbered, give out a phony number so
// that they demangle nicely.
- if (isLambda(ND)) {
- disc = 1;
- return true;
+ if (const auto *RD = dyn_cast<CXXRecordDecl>(ND)) {
+ if (RD->isLambda()) {
+ disc = 1;
+ return true;
+ }
}
// Use the canonical number for externally visible decls.
@@ -394,7 +394,8 @@ bool MicrosoftMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) {
if (!getASTContext().getLangOpts().CPlusPlus)
return false;
- if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ const VarDecl *VD = dyn_cast<VarDecl>(D);
+ if (VD && !isa<DecompositionDecl>(D)) {
// C variables are not mangled.
if (VD->isExternC())
return false;
@@ -780,6 +781,21 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
}
}
+ if (const DecompositionDecl *DD = dyn_cast<DecompositionDecl>(ND)) {
+ // FIXME: Invented mangling for decomposition declarations:
+ // [X,Y,Z]
+ // where X,Y,Z are the names of the bindings.
+ llvm::SmallString<128> Name("[");
+ for (auto *BD : DD->bindings()) {
+ if (Name.size() > 1)
+ Name += ',';
+ Name += BD->getDeclName().getAsIdentifierInfo()->getName();
+ }
+ Name += ']';
+ mangleSourceName(Name);
+ break;
+ }
+
if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) {
// We must have an anonymous union or struct declaration.
const CXXRecordDecl *RD = VD->getType()->getAsCXXRecordDecl();
@@ -808,9 +824,24 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(TD)) {
if (Record->isLambda()) {
llvm::SmallString<10> Name("<lambda_");
+
+ Decl *LambdaContextDecl = Record->getLambdaContextDecl();
+ unsigned LambdaManglingNumber = Record->getLambdaManglingNumber();
unsigned LambdaId;
- if (Record->getLambdaManglingNumber())
- LambdaId = Record->getLambdaManglingNumber();
+ const ParmVarDecl *Parm =
+ dyn_cast_or_null<ParmVarDecl>(LambdaContextDecl);
+ const FunctionDecl *Func =
+ Parm ? dyn_cast<FunctionDecl>(Parm->getDeclContext()) : nullptr;
+
+ if (Func) {
+ unsigned DefaultArgNo =
+ Func->getNumParams() - Parm->getFunctionScopeIndex();
+ Name += llvm::utostr(DefaultArgNo);
+ Name += "_";
+ }
+
+ if (LambdaManglingNumber)
+ LambdaId = LambdaManglingNumber;
else
LambdaId = Context.getLambdaId(Record);
@@ -818,25 +849,42 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
Name += ">";
mangleSourceName(Name);
+
+ // If the context of a closure type is an initializer for a class
+ // member (static or nonstatic), it is encoded in a qualified name.
+ if (LambdaManglingNumber && LambdaContextDecl) {
+ if ((isa<VarDecl>(LambdaContextDecl) ||
+ isa<FieldDecl>(LambdaContextDecl)) &&
+ LambdaContextDecl->getDeclContext()->isRecord()) {
+ mangleUnqualifiedName(cast<NamedDecl>(LambdaContextDecl));
+ }
+ }
break;
}
}
- llvm::SmallString<64> Name("<unnamed-type-");
+ llvm::SmallString<64> Name;
if (DeclaratorDecl *DD =
Context.getASTContext().getDeclaratorForUnnamedTagDecl(TD)) {
// Anonymous types without a name for linkage purposes have their
// declarator mangled in if they have one.
+ Name += "<unnamed-type-";
Name += DD->getName();
} else if (TypedefNameDecl *TND =
Context.getASTContext().getTypedefNameForUnnamedTagDecl(
TD)) {
// Anonymous types without a name for linkage purposes have their
// 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());
+ Name += "<unnamed-enum-";
+ Name += EnumeratorI->getName();
} else {
// Otherwise, number the types using a $S prefix.
- Name += "$S";
+ Name += "<unnamed-type-$S";
Name += llvm::utostr(Context.getAnonymousStructId(TD) + 1);
}
Name += ">";
@@ -921,7 +969,6 @@ void MicrosoftCXXNameMangler::mangleNestedName(const NamedDecl *ND) {
// for how this should be done.
Out << "__block_invoke" << Context.getBlockId(BD, false);
Out << '@';
- continue;
} else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC)) {
mangleObjCMethodName(Method);
} else if (isa<NamedDecl>(DC)) {
@@ -929,8 +976,15 @@ void MicrosoftCXXNameMangler::mangleNestedName(const NamedDecl *ND) {
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
mangle(FD, "?");
break;
- } else
+ } else {
mangleUnqualifiedName(ND);
+ // Lambdas in default arguments conceptually belong to the function the
+ // parameter corresponds to.
+ if (const auto *LDADC = getLambdaDefaultArgumentDeclContext(ND)) {
+ DC = LDADC;
+ continue;
+ }
+ }
}
DC = DC->getParent();
}
@@ -1073,6 +1127,8 @@ void MicrosoftCXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO,
case OO_Array_New: Out << "?_U"; break;
// <operator-name> ::= ?_V # delete[]
case OO_Array_Delete: Out << "?_V"; break;
+ // <operator-name> ::= ?__L # co_await
+ case OO_Coawait: Out << "?__L"; break;
case OO_Conditional: {
DiagnosticsEngine &Diags = Context.getDiags();
@@ -1082,14 +1138,6 @@ void MicrosoftCXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO,
break;
}
- case OO_Coawait: {
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this operator co_await yet");
- Diags.Report(Loc, DiagID);
- break;
- }
-
case OO_None:
case NUM_OVERLOADED_OPERATORS:
llvm_unreachable("Not an overloaded operator");
@@ -1993,6 +2041,7 @@ void MicrosoftCXXNameMangler::mangleCallingConvention(CallingConv CC) {
// ::= I # __fastcall
// ::= J # __export __fastcall
// ::= Q # __vectorcall
+ // ::= w # __regcall
// The 'export' calling conventions are from a bygone era
// (*cough*Win16*cough*) when functions were declared for export with
// that keyword. (It didn't actually export them, it just made them so
@@ -2010,6 +2059,7 @@ 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_X86RegCall: Out << 'w'; break;
}
}
void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T) {
diff --git a/lib/AST/NestedNameSpecifier.cpp b/lib/AST/NestedNameSpecifier.cpp
index 82809d7ea7b5..514c7c9f5b33 100644
--- a/lib/AST/NestedNameSpecifier.cpp
+++ b/lib/AST/NestedNameSpecifier.cpp
@@ -34,8 +34,8 @@ NestedNameSpecifier::FindOrInsert(const ASTContext &Context,
NestedNameSpecifier *NNS
= Context.NestedNameSpecifiers.FindNodeOrInsertPos(ID, InsertPos);
if (!NNS) {
- NNS = new (Context, llvm::alignOf<NestedNameSpecifier>())
- NestedNameSpecifier(Mockup);
+ NNS =
+ new (Context, alignof(NestedNameSpecifier)) NestedNameSpecifier(Mockup);
Context.NestedNameSpecifiers.InsertNode(NNS, InsertPos);
}
@@ -113,8 +113,7 @@ NestedNameSpecifier *
NestedNameSpecifier::GlobalSpecifier(const ASTContext &Context) {
if (!Context.GlobalNestedNameSpecifier)
Context.GlobalNestedNameSpecifier =
- new (Context, llvm::alignOf<NestedNameSpecifier>())
- NestedNameSpecifier();
+ new (Context, alignof(NestedNameSpecifier)) NestedNameSpecifier();
return Context.GlobalNestedNameSpecifier;
}
@@ -155,7 +154,7 @@ NestedNameSpecifier::SpecifierKind NestedNameSpecifier::getKind() const {
/// \brief Retrieve the namespace stored in this nested name specifier.
NamespaceDecl *NestedNameSpecifier::getAsNamespace() const {
- if (Prefix.getInt() == StoredDecl)
+ if (Prefix.getInt() == StoredDecl)
return dyn_cast<NamespaceDecl>(static_cast<NamedDecl *>(Specifier));
return nullptr;
@@ -163,7 +162,7 @@ NamespaceDecl *NestedNameSpecifier::getAsNamespace() const {
/// \brief Retrieve the namespace alias stored in this nested name specifier.
NamespaceAliasDecl *NestedNameSpecifier::getAsNamespaceAlias() const {
- if (Prefix.getInt() == StoredDecl)
+ if (Prefix.getInt() == StoredDecl)
return dyn_cast<NamespaceAliasDecl>(static_cast<NamedDecl *>(Specifier));
return nullptr;
@@ -687,7 +686,7 @@ NestedNameSpecifierLocBuilder::getWithLocInContext(ASTContext &Context) const {
// FIXME: After copying the source-location information, should we free
// our (temporary) buffer and adopt the ASTContext-allocated memory?
// Doing so would optimize repeated calls to getWithLocInContext().
- void *Mem = Context.Allocate(BufferSize, llvm::alignOf<void *>());
+ void *Mem = Context.Allocate(BufferSize, alignof(void *));
memcpy(Mem, Buffer, BufferSize);
return NestedNameSpecifierLoc(Representation, Mem);
}
diff --git a/lib/AST/OpenMPClause.cpp b/lib/AST/OpenMPClause.cpp
index d04ba727bb05..a28b9f3b6d64 100644
--- a/lib/AST/OpenMPClause.cpp
+++ b/lib/AST/OpenMPClause.cpp
@@ -732,38 +732,113 @@ OMPFromClause *OMPFromClause::CreateEmpty(const ASTContext &C, unsigned NumVars,
NumComponentLists, NumComponents);
}
-OMPUseDevicePtrClause *OMPUseDevicePtrClause::Create(const ASTContext &C,
- SourceLocation StartLoc,
- SourceLocation LParenLoc,
- SourceLocation EndLoc,
- ArrayRef<Expr *> VL) {
- void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size()));
- OMPUseDevicePtrClause *Clause =
- new (Mem) OMPUseDevicePtrClause(StartLoc, LParenLoc, EndLoc, VL.size());
- Clause->setVarRefs(VL);
+void OMPUseDevicePtrClause::setPrivateCopies(ArrayRef<Expr *> VL) {
+ assert(VL.size() == varlist_size() &&
+ "Number of private copies is not the same as the preallocated buffer");
+ std::copy(VL.begin(), VL.end(), varlist_end());
+}
+
+void OMPUseDevicePtrClause::setInits(ArrayRef<Expr *> VL) {
+ assert(VL.size() == varlist_size() &&
+ "Number of inits is not the same as the preallocated buffer");
+ std::copy(VL.begin(), VL.end(), getPrivateCopies().end());
+}
+
+OMPUseDevicePtrClause *OMPUseDevicePtrClause::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc, ArrayRef<Expr *> Vars, ArrayRef<Expr *> PrivateVars,
+ ArrayRef<Expr *> Inits, ArrayRef<ValueDecl *> Declarations,
+ MappableExprComponentListsRef ComponentLists) {
+ unsigned NumVars = Vars.size();
+ unsigned NumUniqueDeclarations =
+ getUniqueDeclarationsTotalNumber(Declarations);
+ unsigned NumComponentLists = ComponentLists.size();
+ unsigned NumComponents = getComponentsTotalNumber(ComponentLists);
+
+ // We need to allocate:
+ // 3 x NumVars x Expr* - we have an original list expression for each clause
+ // list entry and an equal number of private copies and inits.
+ // NumUniqueDeclarations x ValueDecl* - unique base declarations associated
+ // with each component list.
+ // (NumUniqueDeclarations + NumComponentLists) x unsigned - we specify the
+ // number of lists for each unique declaration and the size of each component
+ // list.
+ // NumComponents x MappableComponent - the total of all the components in all
+ // the lists.
+ void *Mem = C.Allocate(
+ totalSizeToAlloc<Expr *, ValueDecl *, unsigned,
+ OMPClauseMappableExprCommon::MappableComponent>(
+ 3 * NumVars, NumUniqueDeclarations,
+ NumUniqueDeclarations + NumComponentLists, NumComponents));
+
+ OMPUseDevicePtrClause *Clause = new (Mem) OMPUseDevicePtrClause(
+ StartLoc, LParenLoc, EndLoc, NumVars, NumUniqueDeclarations,
+ NumComponentLists, NumComponents);
+
+ Clause->setVarRefs(Vars);
+ Clause->setPrivateCopies(PrivateVars);
+ Clause->setInits(Inits);
+ Clause->setClauseInfo(Declarations, ComponentLists);
return Clause;
}
-OMPUseDevicePtrClause *OMPUseDevicePtrClause::CreateEmpty(const ASTContext &C,
- unsigned N) {
- void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N));
- return new (Mem) OMPUseDevicePtrClause(N);
+OMPUseDevicePtrClause *OMPUseDevicePtrClause::CreateEmpty(
+ const ASTContext &C, unsigned NumVars, unsigned NumUniqueDeclarations,
+ unsigned NumComponentLists, unsigned NumComponents) {
+ void *Mem = C.Allocate(
+ totalSizeToAlloc<Expr *, ValueDecl *, unsigned,
+ OMPClauseMappableExprCommon::MappableComponent>(
+ 3 * NumVars, NumUniqueDeclarations,
+ NumUniqueDeclarations + NumComponentLists, NumComponents));
+ return new (Mem) OMPUseDevicePtrClause(NumVars, NumUniqueDeclarations,
+ NumComponentLists, NumComponents);
}
-OMPIsDevicePtrClause *OMPIsDevicePtrClause::Create(const ASTContext &C,
- SourceLocation StartLoc,
- SourceLocation LParenLoc,
- SourceLocation EndLoc,
- ArrayRef<Expr *> VL) {
- void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size()));
- OMPIsDevicePtrClause *Clause =
- new (Mem) OMPIsDevicePtrClause(StartLoc, LParenLoc, EndLoc, VL.size());
- Clause->setVarRefs(VL);
+OMPIsDevicePtrClause *
+OMPIsDevicePtrClause::Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc,
+ ArrayRef<Expr *> Vars,
+ ArrayRef<ValueDecl *> Declarations,
+ MappableExprComponentListsRef ComponentLists) {
+ unsigned NumVars = Vars.size();
+ unsigned NumUniqueDeclarations =
+ getUniqueDeclarationsTotalNumber(Declarations);
+ unsigned NumComponentLists = ComponentLists.size();
+ unsigned NumComponents = getComponentsTotalNumber(ComponentLists);
+
+ // We need to allocate:
+ // NumVars x Expr* - we have an original list expression for each clause list
+ // entry.
+ // NumUniqueDeclarations x ValueDecl* - unique base declarations associated
+ // with each component list.
+ // (NumUniqueDeclarations + NumComponentLists) x unsigned - we specify the
+ // number of lists for each unique declaration and the size of each component
+ // list.
+ // NumComponents x MappableComponent - the total of all the components in all
+ // the lists.
+ void *Mem = C.Allocate(
+ totalSizeToAlloc<Expr *, ValueDecl *, unsigned,
+ OMPClauseMappableExprCommon::MappableComponent>(
+ NumVars, NumUniqueDeclarations,
+ NumUniqueDeclarations + NumComponentLists, NumComponents));
+
+ OMPIsDevicePtrClause *Clause = new (Mem) OMPIsDevicePtrClause(
+ StartLoc, LParenLoc, EndLoc, NumVars, NumUniqueDeclarations,
+ NumComponentLists, NumComponents);
+
+ Clause->setVarRefs(Vars);
+ Clause->setClauseInfo(Declarations, ComponentLists);
return Clause;
}
-OMPIsDevicePtrClause *OMPIsDevicePtrClause::CreateEmpty(const ASTContext &C,
- unsigned N) {
- void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N));
- return new (Mem) OMPIsDevicePtrClause(N);
+OMPIsDevicePtrClause *OMPIsDevicePtrClause::CreateEmpty(
+ const ASTContext &C, unsigned NumVars, unsigned NumUniqueDeclarations,
+ unsigned NumComponentLists, unsigned NumComponents) {
+ void *Mem = C.Allocate(
+ totalSizeToAlloc<Expr *, ValueDecl *, unsigned,
+ OMPClauseMappableExprCommon::MappableComponent>(
+ NumVars, NumUniqueDeclarations,
+ NumUniqueDeclarations + NumComponentLists, NumComponents));
+ return new (Mem) OMPIsDevicePtrClause(NumVars, NumUniqueDeclarations,
+ NumComponentLists, NumComponents);
}
diff --git a/lib/AST/RawCommentList.cpp b/lib/AST/RawCommentList.cpp
index 8317f76b8569..881a7d9c61be 100644
--- a/lib/AST/RawCommentList.cpp
+++ b/lib/AST/RawCommentList.cpp
@@ -175,8 +175,8 @@ StringRef RawComment::getRawTextSlow(const SourceManager &SourceMgr) const {
}
const char *RawComment::extractBriefText(const ASTContext &Context) const {
- // Make sure that RawText is valid.
- getRawText(Context.getSourceManager());
+ // Lazily initialize RawText using the accessor before using it.
+ (void)getRawText(Context.getSourceManager());
// Since we will be copying the resulting text, all allocations made during
// parsing are garbage after resulting string is formed. Thus we can use
@@ -202,8 +202,8 @@ const char *RawComment::extractBriefText(const ASTContext &Context) const {
comments::FullComment *RawComment::parse(const ASTContext &Context,
const Preprocessor *PP,
const Decl *D) const {
- // Make sure that RawText is valid.
- getRawText(Context.getSourceManager());
+ // Lazily initialize RawText using the accessor before using it.
+ (void)getRawText(Context.getSourceManager());
comments::Lexer L(Context.getAllocator(), Context.getDiagnostics(),
Context.getCommentCommandTraits(),
@@ -334,4 +334,3 @@ void RawCommentList::addDeserializedComments(ArrayRef<RawComment *> Deserialized
BeforeThanCompare<RawComment>(SourceMgr));
std::swap(Comments, MergedComments);
}
-
diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp
index 75c076399511..697cdc3fb360 100644
--- a/lib/AST/Stmt.cpp
+++ b/lib/AST/Stmt.cpp
@@ -315,7 +315,7 @@ AttributedStmt *AttributedStmt::Create(const ASTContext &C, SourceLocation Loc,
Stmt *SubStmt) {
assert(!Attrs.empty() && "Attrs should not be empty");
void *Mem = C.Allocate(sizeof(AttributedStmt) + sizeof(Attr *) * Attrs.size(),
- llvm::alignOf<AttributedStmt>());
+ alignof(AttributedStmt));
return new (Mem) AttributedStmt(Loc, Attrs, SubStmt);
}
@@ -323,7 +323,7 @@ AttributedStmt *AttributedStmt::CreateEmpty(const ASTContext &C,
unsigned NumAttrs) {
assert(NumAttrs > 0 && "NumAttrs should be greater than zero");
void *Mem = C.Allocate(sizeof(AttributedStmt) + sizeof(Attr *) * NumAttrs,
- llvm::alignOf<AttributedStmt>());
+ alignof(AttributedStmt));
return new (Mem) AttributedStmt(EmptyShell(), NumAttrs);
}
@@ -533,15 +533,17 @@ unsigned GCCAsmStmt::AnalyzeAsmString(SmallVectorImpl<AsmStringPiece>&Pieces,
DiagOffs = CurPtr-StrStart-1;
return diag::err_asm_invalid_escape;
}
-
+ // Handle escaped char and continue looping over the asm string.
char EscapedChar = *CurPtr++;
- if (EscapedChar == '%') { // %% -> %
- // Escaped percentage sign.
- CurStringPiece += '%';
+ switch (EscapedChar) {
+ default:
+ break;
+ case '%': // %% -> %
+ case '{': // %{ -> {
+ case '}': // %} -> }
+ CurStringPiece += EscapedChar;
continue;
- }
-
- if (EscapedChar == '=') { // %= -> Generate an unique ID.
+ case '=': // %= -> Generate a unique ID.
CurStringPiece += "${:uid}";
continue;
}
@@ -794,6 +796,10 @@ void IfStmt::setConditionVariable(const ASTContext &C, VarDecl *V) {
VarRange.getEnd());
}
+bool IfStmt::isObjCAvailabilityCheck() const {
+ return isa<ObjCAvailabilityCheckExpr>(SubExprs[COND]);
+}
+
ForStmt::ForStmt(const ASTContext &C, Stmt *Init, Expr *Cond, VarDecl *condVar,
Expr *Inc, Stmt *Body, SourceLocation FL, SourceLocation LP,
SourceLocation RP)
@@ -998,7 +1004,7 @@ CapturedStmt::Capture *CapturedStmt::getStoredCaptures() const {
unsigned Size = sizeof(CapturedStmt) + sizeof(Stmt *) * (NumCaptures + 1);
// Offset of the first Capture object.
- unsigned FirstCaptureOffset = llvm::alignTo(Size, llvm::alignOf<Capture>());
+ unsigned FirstCaptureOffset = llvm::alignTo(Size, alignof(Capture));
return reinterpret_cast<Capture *>(
reinterpret_cast<char *>(const_cast<CapturedStmt *>(this))
@@ -1055,7 +1061,7 @@ CapturedStmt *CapturedStmt::Create(const ASTContext &Context, Stmt *S,
unsigned Size = sizeof(CapturedStmt) + sizeof(Stmt *) * (Captures.size() + 1);
if (!Captures.empty()) {
// Realign for the following Capture array.
- Size = llvm::alignTo(Size, llvm::alignOf<Capture>());
+ Size = llvm::alignTo(Size, alignof(Capture));
Size += sizeof(Capture) * Captures.size();
}
@@ -1068,7 +1074,7 @@ CapturedStmt *CapturedStmt::CreateDeserialized(const ASTContext &Context,
unsigned Size = sizeof(CapturedStmt) + sizeof(Stmt *) * (NumCaptures + 1);
if (NumCaptures > 0) {
// Realign for the following Capture array.
- Size = llvm::alignTo(Size, llvm::alignOf<Capture>());
+ Size = llvm::alignTo(Size, alignof(Capture));
Size += sizeof(Capture) * NumCaptures;
}
diff --git a/lib/AST/StmtCXX.cpp b/lib/AST/StmtCXX.cpp
index 4692db84b505..4a04fc211262 100644
--- a/lib/AST/StmtCXX.cpp
+++ b/lib/AST/StmtCXX.cpp
@@ -28,7 +28,7 @@ CXXTryStmt *CXXTryStmt::Create(const ASTContext &C, SourceLocation tryLoc,
std::size_t Size = sizeof(CXXTryStmt);
Size += ((handlers.size() + 1) * sizeof(Stmt *));
- void *Mem = C.Allocate(Size, llvm::alignOf<CXXTryStmt>());
+ void *Mem = C.Allocate(Size, alignof(CXXTryStmt));
return new (Mem) CXXTryStmt(tryLoc, tryBlock, handlers);
}
@@ -37,7 +37,7 @@ CXXTryStmt *CXXTryStmt::Create(const ASTContext &C, EmptyShell Empty,
std::size_t Size = sizeof(CXXTryStmt);
Size += ((numHandlers + 1) * sizeof(Stmt *));
- void *Mem = C.Allocate(Size, llvm::alignOf<CXXTryStmt>());
+ void *Mem = C.Allocate(Size, alignof(CXXTryStmt));
return new (Mem) CXXTryStmt(Empty, numHandlers);
}
diff --git a/lib/AST/StmtObjC.cpp b/lib/AST/StmtObjC.cpp
index a77550c7605d..eea03f64c2fe 100644
--- a/lib/AST/StmtObjC.cpp
+++ b/lib/AST/StmtObjC.cpp
@@ -50,7 +50,7 @@ ObjCAtTryStmt *ObjCAtTryStmt::Create(const ASTContext &Context,
unsigned Size =
sizeof(ObjCAtTryStmt) +
(1 + NumCatchStmts + (atFinallyStmt != nullptr)) * sizeof(Stmt *);
- void *Mem = Context.Allocate(Size, llvm::alignOf<ObjCAtTryStmt>());
+ void *Mem = Context.Allocate(Size, alignof(ObjCAtTryStmt));
return new (Mem) ObjCAtTryStmt(atTryLoc, atTryStmt, CatchStmts, NumCatchStmts,
atFinallyStmt);
}
@@ -60,7 +60,7 @@ ObjCAtTryStmt *ObjCAtTryStmt::CreateEmpty(const ASTContext &Context,
bool HasFinally) {
unsigned Size =
sizeof(ObjCAtTryStmt) + (1 + NumCatchStmts + HasFinally) * sizeof(Stmt *);
- void *Mem = Context.Allocate(Size, llvm::alignOf<ObjCAtTryStmt>());
+ void *Mem = Context.Allocate(Size, alignof(ObjCAtTryStmt));
return new (Mem) ObjCAtTryStmt(EmptyShell(), NumCatchStmts, HasFinally);
}
diff --git a/lib/AST/StmtOpenMP.cpp b/lib/AST/StmtOpenMP.cpp
index f1ddedb2b0f2..0a90740162b9 100644
--- a/lib/AST/StmtOpenMP.cpp
+++ b/lib/AST/StmtOpenMP.cpp
@@ -58,7 +58,7 @@ OMPParallelDirective *OMPParallelDirective::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel) {
unsigned Size =
- llvm::alignTo(sizeof(OMPParallelDirective), llvm::alignOf<OMPClause *>());
+ llvm::alignTo(sizeof(OMPParallelDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
OMPParallelDirective *Dir =
@@ -73,7 +73,7 @@ OMPParallelDirective *OMPParallelDirective::CreateEmpty(const ASTContext &C,
unsigned NumClauses,
EmptyShell) {
unsigned Size =
- llvm::alignTo(sizeof(OMPParallelDirective), llvm::alignOf<OMPClause *>());
+ llvm::alignTo(sizeof(OMPParallelDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
return new (Mem) OMPParallelDirective(NumClauses);
@@ -84,8 +84,7 @@ OMPSimdDirective::Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation EndLoc, unsigned CollapsedNum,
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
const HelperExprs &Exprs) {
- unsigned Size =
- llvm::alignTo(sizeof(OMPSimdDirective), llvm::alignOf<OMPClause *>());
+ unsigned Size = llvm::alignTo(sizeof(OMPSimdDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_simd));
@@ -113,8 +112,7 @@ OMPSimdDirective *OMPSimdDirective::CreateEmpty(const ASTContext &C,
unsigned NumClauses,
unsigned CollapsedNum,
EmptyShell) {
- unsigned Size =
- llvm::alignTo(sizeof(OMPSimdDirective), llvm::alignOf<OMPClause *>());
+ unsigned Size = llvm::alignTo(sizeof(OMPSimdDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * NumClauses +
sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_simd));
@@ -126,8 +124,7 @@ OMPForDirective::Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation EndLoc, unsigned CollapsedNum,
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
const HelperExprs &Exprs, bool HasCancel) {
- unsigned Size =
- llvm::alignTo(sizeof(OMPForDirective), llvm::alignOf<OMPClause *>());
+ unsigned Size = llvm::alignTo(sizeof(OMPForDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_for));
@@ -166,8 +163,7 @@ OMPForDirective *OMPForDirective::CreateEmpty(const ASTContext &C,
unsigned NumClauses,
unsigned CollapsedNum,
EmptyShell) {
- unsigned Size =
- llvm::alignTo(sizeof(OMPForDirective), llvm::alignOf<OMPClause *>());
+ unsigned Size = llvm::alignTo(sizeof(OMPForDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * NumClauses +
sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_for));
@@ -180,7 +176,7 @@ OMPForSimdDirective::Create(const ASTContext &C, SourceLocation StartLoc,
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
const HelperExprs &Exprs) {
unsigned Size =
- llvm::alignTo(sizeof(OMPForSimdDirective), llvm::alignOf<OMPClause *>());
+ llvm::alignTo(sizeof(OMPForSimdDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_for_simd));
@@ -219,7 +215,7 @@ OMPForSimdDirective *OMPForSimdDirective::CreateEmpty(const ASTContext &C,
unsigned CollapsedNum,
EmptyShell) {
unsigned Size =
- llvm::alignTo(sizeof(OMPForSimdDirective), llvm::alignOf<OMPClause *>());
+ llvm::alignTo(sizeof(OMPForSimdDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * NumClauses +
sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_for_simd));
@@ -230,7 +226,7 @@ OMPSectionsDirective *OMPSectionsDirective::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel) {
unsigned Size =
- llvm::alignTo(sizeof(OMPSectionsDirective), llvm::alignOf<OMPClause *>());
+ llvm::alignTo(sizeof(OMPSectionsDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
OMPSectionsDirective *Dir =
@@ -245,7 +241,7 @@ OMPSectionsDirective *OMPSectionsDirective::CreateEmpty(const ASTContext &C,
unsigned NumClauses,
EmptyShell) {
unsigned Size =
- llvm::alignTo(sizeof(OMPSectionsDirective), llvm::alignOf<OMPClause *>());
+ llvm::alignTo(sizeof(OMPSectionsDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
return new (Mem) OMPSectionsDirective(NumClauses);
@@ -256,8 +252,7 @@ OMPSectionDirective *OMPSectionDirective::Create(const ASTContext &C,
SourceLocation EndLoc,
Stmt *AssociatedStmt,
bool HasCancel) {
- unsigned Size =
- llvm::alignTo(sizeof(OMPSectionDirective), llvm::alignOf<Stmt *>());
+ unsigned Size = llvm::alignTo(sizeof(OMPSectionDirective), alignof(Stmt *));
void *Mem = C.Allocate(Size + sizeof(Stmt *));
OMPSectionDirective *Dir = new (Mem) OMPSectionDirective(StartLoc, EndLoc);
Dir->setAssociatedStmt(AssociatedStmt);
@@ -267,8 +262,7 @@ OMPSectionDirective *OMPSectionDirective::Create(const ASTContext &C,
OMPSectionDirective *OMPSectionDirective::CreateEmpty(const ASTContext &C,
EmptyShell) {
- unsigned Size =
- llvm::alignTo(sizeof(OMPSectionDirective), llvm::alignOf<Stmt *>());
+ unsigned Size = llvm::alignTo(sizeof(OMPSectionDirective), alignof(Stmt *));
void *Mem = C.Allocate(Size + sizeof(Stmt *));
return new (Mem) OMPSectionDirective();
}
@@ -279,7 +273,7 @@ OMPSingleDirective *OMPSingleDirective::Create(const ASTContext &C,
ArrayRef<OMPClause *> Clauses,
Stmt *AssociatedStmt) {
unsigned Size =
- llvm::alignTo(sizeof(OMPSingleDirective), llvm::alignOf<OMPClause *>());
+ llvm::alignTo(sizeof(OMPSingleDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
OMPSingleDirective *Dir =
@@ -293,7 +287,7 @@ OMPSingleDirective *OMPSingleDirective::CreateEmpty(const ASTContext &C,
unsigned NumClauses,
EmptyShell) {
unsigned Size =
- llvm::alignTo(sizeof(OMPSingleDirective), llvm::alignOf<OMPClause *>());
+ llvm::alignTo(sizeof(OMPSingleDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
return new (Mem) OMPSingleDirective(NumClauses);
@@ -303,8 +297,7 @@ OMPMasterDirective *OMPMasterDirective::Create(const ASTContext &C,
SourceLocation StartLoc,
SourceLocation EndLoc,
Stmt *AssociatedStmt) {
- unsigned Size =
- llvm::alignTo(sizeof(OMPMasterDirective), llvm::alignOf<Stmt *>());
+ unsigned Size = llvm::alignTo(sizeof(OMPMasterDirective), alignof(Stmt *));
void *Mem = C.Allocate(Size + sizeof(Stmt *));
OMPMasterDirective *Dir = new (Mem) OMPMasterDirective(StartLoc, EndLoc);
Dir->setAssociatedStmt(AssociatedStmt);
@@ -313,8 +306,7 @@ OMPMasterDirective *OMPMasterDirective::Create(const ASTContext &C,
OMPMasterDirective *OMPMasterDirective::CreateEmpty(const ASTContext &C,
EmptyShell) {
- unsigned Size =
- llvm::alignTo(sizeof(OMPMasterDirective), llvm::alignOf<Stmt *>());
+ unsigned Size = llvm::alignTo(sizeof(OMPMasterDirective), alignof(Stmt *));
void *Mem = C.Allocate(Size + sizeof(Stmt *));
return new (Mem) OMPMasterDirective();
}
@@ -324,7 +316,7 @@ OMPCriticalDirective *OMPCriticalDirective::Create(
SourceLocation StartLoc, SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) {
unsigned Size =
- llvm::alignTo(sizeof(OMPCriticalDirective), llvm::alignOf<OMPClause *>());
+ llvm::alignTo(sizeof(OMPCriticalDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
OMPCriticalDirective *Dir =
@@ -338,7 +330,7 @@ OMPCriticalDirective *OMPCriticalDirective::CreateEmpty(const ASTContext &C,
unsigned NumClauses,
EmptyShell) {
unsigned Size =
- llvm::alignTo(sizeof(OMPCriticalDirective), llvm::alignOf<OMPClause *>());
+ llvm::alignTo(sizeof(OMPCriticalDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
return new (Mem) OMPCriticalDirective(NumClauses);
@@ -348,8 +340,8 @@ OMPParallelForDirective *OMPParallelForDirective::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
const HelperExprs &Exprs, bool HasCancel) {
- unsigned Size = llvm::alignTo(sizeof(OMPParallelForDirective),
- llvm::alignOf<OMPClause *>());
+ unsigned Size =
+ llvm::alignTo(sizeof(OMPParallelForDirective), alignof(OMPClause *));
void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
sizeof(Stmt *) *
numLoopChildren(CollapsedNum, OMPD_parallel_for));
@@ -387,8 +379,8 @@ OMPParallelForDirective *OMPParallelForDirective::Create(
OMPParallelForDirective *
OMPParallelForDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses,
unsigned CollapsedNum, EmptyShell) {
- unsigned Size = llvm::alignTo(sizeof(OMPParallelForDirective),
- llvm::alignOf<OMPClause *>());
+ unsigned Size =
+ llvm::alignTo(sizeof(OMPParallelForDirective), alignof(OMPClause *));
void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses +
sizeof(Stmt *) *
numLoopChildren(CollapsedNum, OMPD_parallel_for));
@@ -399,8 +391,8 @@ OMPParallelForSimdDirective *OMPParallelForSimdDirective::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
const HelperExprs &Exprs) {
- unsigned Size = llvm::alignTo(sizeof(OMPParallelForSimdDirective),
- llvm::alignOf<OMPClause *>());
+ unsigned Size =
+ llvm::alignTo(sizeof(OMPParallelForSimdDirective), alignof(OMPClause *));
void *Mem = C.Allocate(
Size + sizeof(OMPClause *) * Clauses.size() +
sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_parallel_for_simd));
@@ -438,8 +430,8 @@ OMPParallelForSimdDirective *
OMPParallelForSimdDirective::CreateEmpty(const ASTContext &C,
unsigned NumClauses,
unsigned CollapsedNum, EmptyShell) {
- unsigned Size = llvm::alignTo(sizeof(OMPParallelForSimdDirective),
- llvm::alignOf<OMPClause *>());
+ unsigned Size =
+ llvm::alignTo(sizeof(OMPParallelForSimdDirective), alignof(OMPClause *));
void *Mem = C.Allocate(
Size + sizeof(OMPClause *) * NumClauses +
sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_parallel_for_simd));
@@ -449,8 +441,8 @@ OMPParallelForSimdDirective::CreateEmpty(const ASTContext &C,
OMPParallelSectionsDirective *OMPParallelSectionsDirective::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel) {
- unsigned Size = llvm::alignTo(sizeof(OMPParallelSectionsDirective),
- llvm::alignOf<OMPClause *>());
+ unsigned Size =
+ llvm::alignTo(sizeof(OMPParallelSectionsDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
OMPParallelSectionsDirective *Dir =
@@ -464,8 +456,8 @@ OMPParallelSectionsDirective *OMPParallelSectionsDirective::Create(
OMPParallelSectionsDirective *
OMPParallelSectionsDirective::CreateEmpty(const ASTContext &C,
unsigned NumClauses, EmptyShell) {
- unsigned Size = llvm::alignTo(sizeof(OMPParallelSectionsDirective),
- llvm::alignOf<OMPClause *>());
+ unsigned Size =
+ llvm::alignTo(sizeof(OMPParallelSectionsDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
return new (Mem) OMPParallelSectionsDirective(NumClauses);
@@ -475,8 +467,7 @@ OMPTaskDirective *
OMPTaskDirective::Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses,
Stmt *AssociatedStmt, bool HasCancel) {
- unsigned Size =
- llvm::alignTo(sizeof(OMPTaskDirective), llvm::alignOf<OMPClause *>());
+ unsigned Size = llvm::alignTo(sizeof(OMPTaskDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
OMPTaskDirective *Dir =
@@ -490,8 +481,7 @@ OMPTaskDirective::Create(const ASTContext &C, SourceLocation StartLoc,
OMPTaskDirective *OMPTaskDirective::CreateEmpty(const ASTContext &C,
unsigned NumClauses,
EmptyShell) {
- unsigned Size =
- llvm::alignTo(sizeof(OMPTaskDirective), llvm::alignOf<OMPClause *>());
+ unsigned Size = llvm::alignTo(sizeof(OMPTaskDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
return new (Mem) OMPTaskDirective(NumClauses);
@@ -544,8 +534,7 @@ OMPTaskgroupDirective *OMPTaskgroupDirective::Create(const ASTContext &C,
SourceLocation StartLoc,
SourceLocation EndLoc,
Stmt *AssociatedStmt) {
- unsigned Size =
- llvm::alignTo(sizeof(OMPTaskgroupDirective), llvm::alignOf<Stmt *>());
+ unsigned Size = llvm::alignTo(sizeof(OMPTaskgroupDirective), alignof(Stmt *));
void *Mem = C.Allocate(Size + sizeof(Stmt *));
OMPTaskgroupDirective *Dir =
new (Mem) OMPTaskgroupDirective(StartLoc, EndLoc);
@@ -555,8 +544,7 @@ OMPTaskgroupDirective *OMPTaskgroupDirective::Create(const ASTContext &C,
OMPTaskgroupDirective *OMPTaskgroupDirective::CreateEmpty(const ASTContext &C,
EmptyShell) {
- unsigned Size =
- llvm::alignTo(sizeof(OMPTaskgroupDirective), llvm::alignOf<Stmt *>());
+ unsigned Size = llvm::alignTo(sizeof(OMPTaskgroupDirective), alignof(Stmt *));
void *Mem = C.Allocate(Size + sizeof(Stmt *));
return new (Mem) OMPTaskgroupDirective();
}
@@ -564,8 +552,8 @@ OMPTaskgroupDirective *OMPTaskgroupDirective::CreateEmpty(const ASTContext &C,
OMPCancellationPointDirective *OMPCancellationPointDirective::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
OpenMPDirectiveKind CancelRegion) {
- unsigned Size = llvm::alignTo(sizeof(OMPCancellationPointDirective),
- llvm::alignOf<Stmt *>());
+ unsigned Size =
+ llvm::alignTo(sizeof(OMPCancellationPointDirective), alignof(Stmt *));
void *Mem = C.Allocate(Size);
OMPCancellationPointDirective *Dir =
new (Mem) OMPCancellationPointDirective(StartLoc, EndLoc);
@@ -575,8 +563,8 @@ OMPCancellationPointDirective *OMPCancellationPointDirective::Create(
OMPCancellationPointDirective *
OMPCancellationPointDirective::CreateEmpty(const ASTContext &C, EmptyShell) {
- unsigned Size = llvm::alignTo(sizeof(OMPCancellationPointDirective),
- llvm::alignOf<Stmt *>());
+ unsigned Size =
+ llvm::alignTo(sizeof(OMPCancellationPointDirective), alignof(Stmt *));
void *Mem = C.Allocate(Size);
return new (Mem) OMPCancellationPointDirective();
}
@@ -587,7 +575,7 @@ OMPCancelDirective::Create(const ASTContext &C, SourceLocation StartLoc,
OpenMPDirectiveKind CancelRegion) {
unsigned Size = llvm::alignTo(sizeof(OMPCancelDirective) +
sizeof(OMPClause *) * Clauses.size(),
- llvm::alignOf<Stmt *>());
+ alignof(Stmt *));
void *Mem = C.Allocate(Size);
OMPCancelDirective *Dir =
new (Mem) OMPCancelDirective(StartLoc, EndLoc, Clauses.size());
@@ -601,7 +589,7 @@ OMPCancelDirective *OMPCancelDirective::CreateEmpty(const ASTContext &C,
EmptyShell) {
unsigned Size = llvm::alignTo(sizeof(OMPCancelDirective) +
sizeof(OMPClause *) * NumClauses,
- llvm::alignOf<Stmt *>());
+ alignof(Stmt *));
void *Mem = C.Allocate(Size);
return new (Mem) OMPCancelDirective(NumClauses);
}
@@ -611,7 +599,7 @@ OMPFlushDirective *OMPFlushDirective::Create(const ASTContext &C,
SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses) {
unsigned Size =
- llvm::alignTo(sizeof(OMPFlushDirective), llvm::alignOf<OMPClause *>());
+ llvm::alignTo(sizeof(OMPFlushDirective), alignof(OMPClause *));
void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size());
OMPFlushDirective *Dir =
new (Mem) OMPFlushDirective(StartLoc, EndLoc, Clauses.size());
@@ -623,7 +611,7 @@ OMPFlushDirective *OMPFlushDirective::CreateEmpty(const ASTContext &C,
unsigned NumClauses,
EmptyShell) {
unsigned Size =
- llvm::alignTo(sizeof(OMPFlushDirective), llvm::alignOf<OMPClause *>());
+ llvm::alignTo(sizeof(OMPFlushDirective), alignof(OMPClause *));
void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses);
return new (Mem) OMPFlushDirective(NumClauses);
}
@@ -634,7 +622,7 @@ OMPOrderedDirective *OMPOrderedDirective::Create(const ASTContext &C,
ArrayRef<OMPClause *> Clauses,
Stmt *AssociatedStmt) {
unsigned Size =
- llvm::alignTo(sizeof(OMPOrderedDirective), llvm::alignOf<OMPClause *>());
+ llvm::alignTo(sizeof(OMPOrderedDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(Stmt *) + sizeof(OMPClause *) * Clauses.size());
OMPOrderedDirective *Dir =
@@ -648,7 +636,7 @@ OMPOrderedDirective *OMPOrderedDirective::CreateEmpty(const ASTContext &C,
unsigned NumClauses,
EmptyShell) {
unsigned Size =
- llvm::alignTo(sizeof(OMPOrderedDirective), llvm::alignOf<OMPClause *>());
+ llvm::alignTo(sizeof(OMPOrderedDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(Stmt *) + sizeof(OMPClause *) * NumClauses);
return new (Mem) OMPOrderedDirective(NumClauses);
@@ -659,7 +647,7 @@ OMPAtomicDirective *OMPAtomicDirective::Create(
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *X, Expr *V,
Expr *E, Expr *UE, bool IsXLHSInRHSPart, bool IsPostfixUpdate) {
unsigned Size =
- llvm::alignTo(sizeof(OMPAtomicDirective), llvm::alignOf<OMPClause *>());
+ llvm::alignTo(sizeof(OMPAtomicDirective), alignof(OMPClause *));
void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
5 * sizeof(Stmt *));
OMPAtomicDirective *Dir =
@@ -679,7 +667,7 @@ OMPAtomicDirective *OMPAtomicDirective::CreateEmpty(const ASTContext &C,
unsigned NumClauses,
EmptyShell) {
unsigned Size =
- llvm::alignTo(sizeof(OMPAtomicDirective), llvm::alignOf<OMPClause *>());
+ llvm::alignTo(sizeof(OMPAtomicDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * NumClauses + 5 * sizeof(Stmt *));
return new (Mem) OMPAtomicDirective(NumClauses);
@@ -691,7 +679,7 @@ OMPTargetDirective *OMPTargetDirective::Create(const ASTContext &C,
ArrayRef<OMPClause *> Clauses,
Stmt *AssociatedStmt) {
unsigned Size =
- llvm::alignTo(sizeof(OMPTargetDirective), llvm::alignOf<OMPClause *>());
+ llvm::alignTo(sizeof(OMPTargetDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
OMPTargetDirective *Dir =
@@ -705,7 +693,7 @@ OMPTargetDirective *OMPTargetDirective::CreateEmpty(const ASTContext &C,
unsigned NumClauses,
EmptyShell) {
unsigned Size =
- llvm::alignTo(sizeof(OMPTargetDirective), llvm::alignOf<OMPClause *>());
+ llvm::alignTo(sizeof(OMPTargetDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
return new (Mem) OMPTargetDirective(NumClauses);
@@ -714,8 +702,8 @@ OMPTargetDirective *OMPTargetDirective::CreateEmpty(const ASTContext &C,
OMPTargetParallelDirective *OMPTargetParallelDirective::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) {
- unsigned Size = llvm::alignTo(sizeof(OMPTargetParallelDirective),
- llvm::alignOf<OMPClause *>());
+ unsigned Size =
+ llvm::alignTo(sizeof(OMPTargetParallelDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
OMPTargetParallelDirective *Dir =
@@ -728,8 +716,8 @@ OMPTargetParallelDirective *OMPTargetParallelDirective::Create(
OMPTargetParallelDirective *
OMPTargetParallelDirective::CreateEmpty(const ASTContext &C,
unsigned NumClauses, EmptyShell) {
- unsigned Size = llvm::alignTo(sizeof(OMPTargetParallelDirective),
- llvm::alignOf<OMPClause *>());
+ unsigned Size =
+ llvm::alignTo(sizeof(OMPTargetParallelDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
return new (Mem) OMPTargetParallelDirective(NumClauses);
@@ -740,7 +728,7 @@ OMPTargetParallelForDirective *OMPTargetParallelForDirective::Create(
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
const HelperExprs &Exprs, bool HasCancel) {
unsigned Size = llvm::alignTo(sizeof(OMPTargetParallelForDirective),
- llvm::alignOf<OMPClause *>());
+ alignof(OMPClause *));
void *Mem = C.Allocate(
Size + sizeof(OMPClause *) * Clauses.size() +
sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_target_parallel_for));
@@ -780,7 +768,7 @@ OMPTargetParallelForDirective::CreateEmpty(const ASTContext &C,
unsigned NumClauses,
unsigned CollapsedNum, EmptyShell) {
unsigned Size = llvm::alignTo(sizeof(OMPTargetParallelForDirective),
- llvm::alignOf<OMPClause *>());
+ alignof(OMPClause *));
void *Mem = C.Allocate(
Size + sizeof(OMPClause *) * NumClauses +
sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_target_parallel_for));
@@ -790,9 +778,9 @@ OMPTargetParallelForDirective::CreateEmpty(const ASTContext &C,
OMPTargetDataDirective *OMPTargetDataDirective::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) {
- void *Mem = C.Allocate(llvm::alignTo(sizeof(OMPTargetDataDirective),
- llvm::alignOf<OMPClause *>()) +
- sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
+ void *Mem = C.Allocate(
+ llvm::alignTo(sizeof(OMPTargetDataDirective), alignof(OMPClause *)) +
+ sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
OMPTargetDataDirective *Dir =
new (Mem) OMPTargetDataDirective(StartLoc, EndLoc, Clauses.size());
Dir->setClauses(Clauses);
@@ -803,18 +791,18 @@ OMPTargetDataDirective *OMPTargetDataDirective::Create(
OMPTargetDataDirective *OMPTargetDataDirective::CreateEmpty(const ASTContext &C,
unsigned N,
EmptyShell) {
- void *Mem = C.Allocate(llvm::alignTo(sizeof(OMPTargetDataDirective),
- llvm::alignOf<OMPClause *>()) +
- sizeof(OMPClause *) * N + sizeof(Stmt *));
+ void *Mem = C.Allocate(
+ llvm::alignTo(sizeof(OMPTargetDataDirective), alignof(OMPClause *)) +
+ sizeof(OMPClause *) * N + sizeof(Stmt *));
return new (Mem) OMPTargetDataDirective(N);
}
OMPTargetEnterDataDirective *OMPTargetEnterDataDirective::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses) {
- void *Mem = C.Allocate(llvm::alignTo(sizeof(OMPTargetEnterDataDirective),
- llvm::alignOf<OMPClause *>()) +
- sizeof(OMPClause *) * Clauses.size());
+ void *Mem = C.Allocate(
+ llvm::alignTo(sizeof(OMPTargetEnterDataDirective), alignof(OMPClause *)) +
+ sizeof(OMPClause *) * Clauses.size());
OMPTargetEnterDataDirective *Dir =
new (Mem) OMPTargetEnterDataDirective(StartLoc, EndLoc, Clauses.size());
Dir->setClauses(Clauses);
@@ -824,9 +812,9 @@ OMPTargetEnterDataDirective *OMPTargetEnterDataDirective::Create(
OMPTargetEnterDataDirective *
OMPTargetEnterDataDirective::CreateEmpty(const ASTContext &C, unsigned N,
EmptyShell) {
- void *Mem = C.Allocate(llvm::alignTo(sizeof(OMPTargetEnterDataDirective),
- llvm::alignOf<OMPClause *>()) +
- sizeof(OMPClause *) * N);
+ void *Mem = C.Allocate(
+ llvm::alignTo(sizeof(OMPTargetEnterDataDirective), alignof(OMPClause *)) +
+ sizeof(OMPClause *) * N);
return new (Mem) OMPTargetEnterDataDirective(N);
}
@@ -834,9 +822,9 @@ OMPTargetExitDataDirective *
OMPTargetExitDataDirective::Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses) {
- void *Mem = C.Allocate(llvm::alignTo(sizeof(OMPTargetExitDataDirective),
- llvm::alignOf<OMPClause *>()) +
- sizeof(OMPClause *) * Clauses.size());
+ void *Mem = C.Allocate(
+ llvm::alignTo(sizeof(OMPTargetExitDataDirective), alignof(OMPClause *)) +
+ sizeof(OMPClause *) * Clauses.size());
OMPTargetExitDataDirective *Dir =
new (Mem) OMPTargetExitDataDirective(StartLoc, EndLoc, Clauses.size());
Dir->setClauses(Clauses);
@@ -846,9 +834,9 @@ OMPTargetExitDataDirective::Create(const ASTContext &C, SourceLocation StartLoc,
OMPTargetExitDataDirective *
OMPTargetExitDataDirective::CreateEmpty(const ASTContext &C, unsigned N,
EmptyShell) {
- void *Mem = C.Allocate(llvm::alignTo(sizeof(OMPTargetExitDataDirective),
- llvm::alignOf<OMPClause *>()) +
- sizeof(OMPClause *) * N);
+ void *Mem = C.Allocate(
+ llvm::alignTo(sizeof(OMPTargetExitDataDirective), alignof(OMPClause *)) +
+ sizeof(OMPClause *) * N);
return new (Mem) OMPTargetExitDataDirective(N);
}
@@ -858,7 +846,7 @@ OMPTeamsDirective *OMPTeamsDirective::Create(const ASTContext &C,
ArrayRef<OMPClause *> Clauses,
Stmt *AssociatedStmt) {
unsigned Size =
- llvm::alignTo(sizeof(OMPTeamsDirective), llvm::alignOf<OMPClause *>());
+ llvm::alignTo(sizeof(OMPTeamsDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
OMPTeamsDirective *Dir =
@@ -872,7 +860,7 @@ OMPTeamsDirective *OMPTeamsDirective::CreateEmpty(const ASTContext &C,
unsigned NumClauses,
EmptyShell) {
unsigned Size =
- llvm::alignTo(sizeof(OMPTeamsDirective), llvm::alignOf<OMPClause *>());
+ llvm::alignTo(sizeof(OMPTeamsDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
return new (Mem) OMPTeamsDirective(NumClauses);
@@ -883,7 +871,7 @@ OMPTaskLoopDirective *OMPTaskLoopDirective::Create(
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
const HelperExprs &Exprs) {
unsigned Size =
- llvm::alignTo(sizeof(OMPTaskLoopDirective), llvm::alignOf<OMPClause *>());
+ llvm::alignTo(sizeof(OMPTaskLoopDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_taskloop));
@@ -922,7 +910,7 @@ OMPTaskLoopDirective *OMPTaskLoopDirective::CreateEmpty(const ASTContext &C,
unsigned CollapsedNum,
EmptyShell) {
unsigned Size =
- llvm::alignTo(sizeof(OMPTaskLoopDirective), llvm::alignOf<OMPClause *>());
+ llvm::alignTo(sizeof(OMPTaskLoopDirective), alignof(OMPClause *));
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * NumClauses +
sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_taskloop));
@@ -933,8 +921,8 @@ OMPTaskLoopSimdDirective *OMPTaskLoopSimdDirective::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
const HelperExprs &Exprs) {
- unsigned Size = llvm::alignTo(sizeof(OMPTaskLoopSimdDirective),
- llvm::alignOf<OMPClause *>());
+ unsigned Size =
+ llvm::alignTo(sizeof(OMPTaskLoopSimdDirective), alignof(OMPClause *));
void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
sizeof(Stmt *) *
numLoopChildren(CollapsedNum, OMPD_taskloop_simd));
@@ -971,8 +959,8 @@ OMPTaskLoopSimdDirective *OMPTaskLoopSimdDirective::Create(
OMPTaskLoopSimdDirective *
OMPTaskLoopSimdDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses,
unsigned CollapsedNum, EmptyShell) {
- unsigned Size = llvm::alignTo(sizeof(OMPTaskLoopSimdDirective),
- llvm::alignOf<OMPClause *>());
+ unsigned Size =
+ llvm::alignTo(sizeof(OMPTaskLoopSimdDirective), alignof(OMPClause *));
void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses +
sizeof(Stmt *) *
numLoopChildren(CollapsedNum, OMPD_taskloop_simd));
@@ -983,8 +971,8 @@ OMPDistributeDirective *OMPDistributeDirective::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
const HelperExprs &Exprs) {
- unsigned Size = llvm::alignTo(sizeof(OMPDistributeDirective),
- llvm::alignOf<OMPClause *>());
+ unsigned Size =
+ llvm::alignTo(sizeof(OMPDistributeDirective), alignof(OMPClause *));
void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
sizeof(Stmt *) *
numLoopChildren(CollapsedNum, OMPD_distribute));
@@ -1021,8 +1009,8 @@ OMPDistributeDirective *OMPDistributeDirective::Create(
OMPDistributeDirective *
OMPDistributeDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses,
unsigned CollapsedNum, EmptyShell) {
- unsigned Size = llvm::alignTo(sizeof(OMPDistributeDirective),
- llvm::alignOf<OMPClause *>());
+ unsigned Size =
+ llvm::alignTo(sizeof(OMPDistributeDirective), alignof(OMPClause *));
void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses +
sizeof(Stmt *) *
numLoopChildren(CollapsedNum, OMPD_distribute));
@@ -1033,8 +1021,8 @@ OMPTargetUpdateDirective *
OMPTargetUpdateDirective::Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses) {
- unsigned Size = llvm::alignTo(sizeof(OMPTargetUpdateDirective),
- llvm::alignOf<OMPClause *>());
+ unsigned Size =
+ llvm::alignTo(sizeof(OMPTargetUpdateDirective), alignof(OMPClause *));
void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size());
OMPTargetUpdateDirective *Dir =
new (Mem) OMPTargetUpdateDirective(StartLoc, EndLoc, Clauses.size());
@@ -1045,8 +1033,8 @@ OMPTargetUpdateDirective::Create(const ASTContext &C, SourceLocation StartLoc,
OMPTargetUpdateDirective *
OMPTargetUpdateDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses,
EmptyShell) {
- unsigned Size = llvm::alignTo(sizeof(OMPTargetUpdateDirective),
- llvm::alignOf<OMPClause *>());
+ unsigned Size =
+ llvm::alignTo(sizeof(OMPTargetUpdateDirective), alignof(OMPClause *));
void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses);
return new (Mem) OMPTargetUpdateDirective(NumClauses);
}
@@ -1056,7 +1044,7 @@ OMPDistributeParallelForDirective *OMPDistributeParallelForDirective::Create(
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
const HelperExprs &Exprs) {
unsigned Size = llvm::alignTo(sizeof(OMPDistributeParallelForDirective),
- llvm::alignOf<OMPClause *>());
+ alignof(OMPClause *));
void *Mem = C.Allocate(
Size + sizeof(OMPClause *) * Clauses.size() +
sizeof(Stmt *) *
@@ -1098,7 +1086,7 @@ OMPDistributeParallelForDirective::CreateEmpty(const ASTContext &C,
unsigned CollapsedNum,
EmptyShell) {
unsigned Size = llvm::alignTo(sizeof(OMPDistributeParallelForDirective),
- llvm::alignOf<OMPClause *>());
+ alignof(OMPClause *));
void *Mem = C.Allocate(
Size + sizeof(OMPClause *) * NumClauses +
sizeof(Stmt *) *
@@ -1112,7 +1100,7 @@ OMPDistributeParallelForSimdDirective::Create(
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
const HelperExprs &Exprs) {
unsigned Size = llvm::alignTo(sizeof(OMPDistributeParallelForSimdDirective),
- llvm::alignOf<OMPClause *>());
+ alignof(OMPClause *));
void *Mem = C.Allocate(
Size + sizeof(OMPClause *) * Clauses.size() +
sizeof(Stmt *) *
@@ -1154,7 +1142,7 @@ OMPDistributeParallelForSimdDirective::CreateEmpty(const ASTContext &C,
unsigned CollapsedNum,
EmptyShell) {
unsigned Size = llvm::alignTo(sizeof(OMPDistributeParallelForSimdDirective),
- llvm::alignOf<OMPClause *>());
+ alignof(OMPClause *));
void *Mem = C.Allocate(
Size + sizeof(OMPClause *) * NumClauses +
sizeof(Stmt *) *
@@ -1167,8 +1155,8 @@ OMPDistributeSimdDirective *OMPDistributeSimdDirective::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
const HelperExprs &Exprs) {
- unsigned Size = llvm::alignTo(sizeof(OMPDistributeSimdDirective),
- llvm::alignOf<OMPClause *>());
+ unsigned Size =
+ llvm::alignTo(sizeof(OMPDistributeSimdDirective), alignof(OMPClause *));
void *Mem = C.Allocate(
Size + sizeof(OMPClause *) * Clauses.size() +
sizeof(Stmt *) *
@@ -1207,8 +1195,8 @@ OMPDistributeSimdDirective *
OMPDistributeSimdDirective::CreateEmpty(const ASTContext &C,
unsigned NumClauses,
unsigned CollapsedNum, EmptyShell) {
- unsigned Size = llvm::alignTo(sizeof(OMPDistributeSimdDirective),
- llvm::alignOf<OMPClause *>());
+ unsigned Size =
+ llvm::alignTo(sizeof(OMPDistributeSimdDirective), alignof(OMPClause *));
void *Mem = C.Allocate(
Size + sizeof(OMPClause *) * NumClauses +
sizeof(Stmt *) *
@@ -1221,7 +1209,7 @@ OMPTargetParallelForSimdDirective *OMPTargetParallelForSimdDirective::Create(
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
const HelperExprs &Exprs) {
unsigned Size = llvm::alignTo(sizeof(OMPTargetParallelForSimdDirective),
- llvm::alignOf<OMPClause *>());
+ alignof(OMPClause *));
void *Mem = C.Allocate(
Size + sizeof(OMPClause *) * Clauses.size() +
sizeof(Stmt *) *
@@ -1263,10 +1251,411 @@ OMPTargetParallelForSimdDirective::CreateEmpty(const ASTContext &C,
unsigned CollapsedNum,
EmptyShell) {
unsigned Size = llvm::alignTo(sizeof(OMPTargetParallelForSimdDirective),
- llvm::alignOf<OMPClause *>());
+ alignof(OMPClause *));
void *Mem = C.Allocate(
Size + sizeof(OMPClause *) * NumClauses +
sizeof(Stmt *) *
numLoopChildren(CollapsedNum, OMPD_target_parallel_for_simd));
return new (Mem) OMPTargetParallelForSimdDirective(CollapsedNum, NumClauses);
}
+
+OMPTargetSimdDirective *
+OMPTargetSimdDirective::Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation EndLoc, unsigned CollapsedNum,
+ ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt, const HelperExprs &Exprs) {
+ unsigned Size =
+ llvm::alignTo(sizeof(OMPTargetSimdDirective), alignof(OMPClause *));
+ void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
+ sizeof(Stmt *) *
+ numLoopChildren(CollapsedNum, OMPD_target_simd));
+ OMPTargetSimdDirective *Dir = new (Mem)
+ OMPTargetSimdDirective(StartLoc, EndLoc, CollapsedNum, Clauses.size());
+ Dir->setClauses(Clauses);
+ Dir->setAssociatedStmt(AssociatedStmt);
+ Dir->setIterationVariable(Exprs.IterationVarRef);
+ Dir->setLastIteration(Exprs.LastIteration);
+ Dir->setCalcLastIteration(Exprs.CalcLastIteration);
+ Dir->setPreCond(Exprs.PreCond);
+ Dir->setCond(Exprs.Cond);
+ Dir->setInit(Exprs.Init);
+ Dir->setInc(Exprs.Inc);
+ Dir->setCounters(Exprs.Counters);
+ Dir->setPrivateCounters(Exprs.PrivateCounters);
+ Dir->setInits(Exprs.Inits);
+ Dir->setUpdates(Exprs.Updates);
+ Dir->setFinals(Exprs.Finals);
+ Dir->setPreInits(Exprs.PreInits);
+ return Dir;
+}
+
+OMPTargetSimdDirective *
+OMPTargetSimdDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses,
+ unsigned CollapsedNum, EmptyShell) {
+ unsigned Size =
+ llvm::alignTo(sizeof(OMPTargetSimdDirective), alignof(OMPClause *));
+ void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses +
+ sizeof(Stmt *) *
+ numLoopChildren(CollapsedNum, OMPD_target_simd));
+ return new (Mem) OMPTargetSimdDirective(CollapsedNum, NumClauses);
+}
+
+OMPTeamsDistributeDirective *OMPTeamsDistributeDirective::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
+ const HelperExprs &Exprs) {
+ unsigned Size =
+ llvm::alignTo(sizeof(OMPTeamsDistributeDirective), alignof(OMPClause *));
+ void *Mem = C.Allocate(
+ Size + sizeof(OMPClause *) * Clauses.size() +
+ sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_teams_distribute));
+ OMPTeamsDistributeDirective *Dir = new (Mem) OMPTeamsDistributeDirective(
+ StartLoc, EndLoc, CollapsedNum, Clauses.size());
+ Dir->setClauses(Clauses);
+ Dir->setAssociatedStmt(AssociatedStmt);
+ Dir->setIterationVariable(Exprs.IterationVarRef);
+ Dir->setLastIteration(Exprs.LastIteration);
+ Dir->setCalcLastIteration(Exprs.CalcLastIteration);
+ Dir->setPreCond(Exprs.PreCond);
+ Dir->setCond(Exprs.Cond);
+ Dir->setInit(Exprs.Init);
+ Dir->setInc(Exprs.Inc);
+ Dir->setIsLastIterVariable(Exprs.IL);
+ Dir->setLowerBoundVariable(Exprs.LB);
+ Dir->setUpperBoundVariable(Exprs.UB);
+ Dir->setStrideVariable(Exprs.ST);
+ Dir->setEnsureUpperBound(Exprs.EUB);
+ Dir->setNextLowerBound(Exprs.NLB);
+ Dir->setNextUpperBound(Exprs.NUB);
+ Dir->setNumIterations(Exprs.NumIterations);
+ Dir->setPrevLowerBoundVariable(Exprs.PrevLB);
+ Dir->setPrevUpperBoundVariable(Exprs.PrevUB);
+ Dir->setCounters(Exprs.Counters);
+ Dir->setPrivateCounters(Exprs.PrivateCounters);
+ Dir->setInits(Exprs.Inits);
+ Dir->setUpdates(Exprs.Updates);
+ Dir->setFinals(Exprs.Finals);
+ Dir->setPreInits(Exprs.PreInits);
+ return Dir;
+}
+
+OMPTeamsDistributeDirective *
+OMPTeamsDistributeDirective::CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ unsigned CollapsedNum, EmptyShell) {
+ unsigned Size =
+ llvm::alignTo(sizeof(OMPTeamsDistributeDirective), alignof(OMPClause *));
+ void *Mem = C.Allocate(
+ Size + sizeof(OMPClause *) * NumClauses +
+ sizeof(Stmt *) * numLoopChildren(CollapsedNum, OMPD_teams_distribute));
+ return new (Mem) OMPTeamsDistributeDirective(CollapsedNum, NumClauses);
+}
+
+OMPTeamsDistributeSimdDirective *OMPTeamsDistributeSimdDirective::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
+ const HelperExprs &Exprs) {
+ unsigned Size = llvm::alignTo(sizeof(OMPTeamsDistributeSimdDirective),
+ alignof(OMPClause *));
+ void *Mem =
+ C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
+ sizeof(Stmt *) *
+ numLoopChildren(CollapsedNum, OMPD_teams_distribute_simd));
+ OMPTeamsDistributeSimdDirective *Dir =
+ new (Mem) OMPTeamsDistributeSimdDirective(StartLoc, EndLoc, CollapsedNum,
+ Clauses.size());
+ Dir->setClauses(Clauses);
+ Dir->setAssociatedStmt(AssociatedStmt);
+ Dir->setIterationVariable(Exprs.IterationVarRef);
+ Dir->setLastIteration(Exprs.LastIteration);
+ Dir->setCalcLastIteration(Exprs.CalcLastIteration);
+ Dir->setPreCond(Exprs.PreCond);
+ Dir->setCond(Exprs.Cond);
+ Dir->setInit(Exprs.Init);
+ Dir->setInc(Exprs.Inc);
+ Dir->setIsLastIterVariable(Exprs.IL);
+ Dir->setLowerBoundVariable(Exprs.LB);
+ Dir->setUpperBoundVariable(Exprs.UB);
+ Dir->setStrideVariable(Exprs.ST);
+ Dir->setEnsureUpperBound(Exprs.EUB);
+ Dir->setNextLowerBound(Exprs.NLB);
+ Dir->setNextUpperBound(Exprs.NUB);
+ Dir->setNumIterations(Exprs.NumIterations);
+ Dir->setPrevLowerBoundVariable(Exprs.PrevLB);
+ Dir->setPrevUpperBoundVariable(Exprs.PrevUB);
+ Dir->setCounters(Exprs.Counters);
+ Dir->setPrivateCounters(Exprs.PrivateCounters);
+ Dir->setInits(Exprs.Inits);
+ Dir->setUpdates(Exprs.Updates);
+ Dir->setFinals(Exprs.Finals);
+ Dir->setPreInits(Exprs.PreInits);
+ return Dir;
+}
+
+OMPTeamsDistributeSimdDirective *OMPTeamsDistributeSimdDirective::CreateEmpty(
+ const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
+ EmptyShell) {
+ unsigned Size = llvm::alignTo(sizeof(OMPTeamsDistributeSimdDirective),
+ alignof(OMPClause *));
+ void *Mem =
+ C.Allocate(Size + sizeof(OMPClause *) * NumClauses +
+ sizeof(Stmt *) *
+ numLoopChildren(CollapsedNum, OMPD_teams_distribute_simd));
+ return new (Mem) OMPTeamsDistributeSimdDirective(CollapsedNum, NumClauses);
+}
+
+OMPTeamsDistributeParallelForSimdDirective *
+OMPTeamsDistributeParallelForSimdDirective::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
+ const HelperExprs &Exprs) {
+ auto Size = llvm::alignTo(sizeof(OMPTeamsDistributeParallelForSimdDirective),
+ alignof(OMPClause *));
+ void *Mem =
+ C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() +
+ sizeof(Stmt *) *
+ numLoopChildren(CollapsedNum,
+ OMPD_teams_distribute_parallel_for_simd));
+ OMPTeamsDistributeParallelForSimdDirective *Dir = new (Mem)
+ OMPTeamsDistributeParallelForSimdDirective(StartLoc, EndLoc, CollapsedNum,
+ Clauses.size());
+ Dir->setClauses(Clauses);
+ Dir->setAssociatedStmt(AssociatedStmt);
+ Dir->setIterationVariable(Exprs.IterationVarRef);
+ Dir->setLastIteration(Exprs.LastIteration);
+ Dir->setCalcLastIteration(Exprs.CalcLastIteration);
+ Dir->setPreCond(Exprs.PreCond);
+ Dir->setCond(Exprs.Cond);
+ Dir->setInit(Exprs.Init);
+ Dir->setInc(Exprs.Inc);
+ Dir->setIsLastIterVariable(Exprs.IL);
+ Dir->setLowerBoundVariable(Exprs.LB);
+ Dir->setUpperBoundVariable(Exprs.UB);
+ Dir->setStrideVariable(Exprs.ST);
+ Dir->setEnsureUpperBound(Exprs.EUB);
+ Dir->setNextLowerBound(Exprs.NLB);
+ Dir->setNextUpperBound(Exprs.NUB);
+ Dir->setNumIterations(Exprs.NumIterations);
+ Dir->setPrevLowerBoundVariable(Exprs.PrevLB);
+ Dir->setPrevUpperBoundVariable(Exprs.PrevUB);
+ Dir->setCounters(Exprs.Counters);
+ Dir->setPrivateCounters(Exprs.PrivateCounters);
+ Dir->setInits(Exprs.Inits);
+ Dir->setUpdates(Exprs.Updates);
+ Dir->setFinals(Exprs.Finals);
+ Dir->setPreInits(Exprs.PreInits);
+ return Dir;
+}
+
+OMPTeamsDistributeParallelForSimdDirective *
+OMPTeamsDistributeParallelForSimdDirective::CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ unsigned CollapsedNum,
+ EmptyShell) {
+ auto Size = llvm::alignTo(sizeof(OMPTeamsDistributeParallelForSimdDirective),
+ alignof(OMPClause *));
+ void *Mem =
+ C.Allocate(Size + sizeof(OMPClause *) * NumClauses +
+ sizeof(Stmt *) *
+ numLoopChildren(CollapsedNum,
+ OMPD_teams_distribute_parallel_for_simd));
+ return new (Mem)
+ OMPTeamsDistributeParallelForSimdDirective(CollapsedNum, NumClauses);
+}
+
+OMPTeamsDistributeParallelForDirective *
+OMPTeamsDistributeParallelForDirective::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
+ const HelperExprs &Exprs) {
+ auto Size = llvm::alignTo(sizeof(OMPTeamsDistributeParallelForDirective),
+ alignof(OMPClause *));
+ void *Mem = C.Allocate(
+ Size + sizeof(OMPClause *) * Clauses.size() +
+ sizeof(Stmt *) *
+ numLoopChildren(CollapsedNum, OMPD_teams_distribute_parallel_for));
+ OMPTeamsDistributeParallelForDirective *Dir = new (Mem)
+ OMPTeamsDistributeParallelForDirective(StartLoc, EndLoc, CollapsedNum,
+ Clauses.size());
+ Dir->setClauses(Clauses);
+ Dir->setAssociatedStmt(AssociatedStmt);
+ Dir->setIterationVariable(Exprs.IterationVarRef);
+ Dir->setLastIteration(Exprs.LastIteration);
+ Dir->setCalcLastIteration(Exprs.CalcLastIteration);
+ Dir->setPreCond(Exprs.PreCond);
+ Dir->setCond(Exprs.Cond);
+ Dir->setInit(Exprs.Init);
+ Dir->setInc(Exprs.Inc);
+ Dir->setIsLastIterVariable(Exprs.IL);
+ Dir->setLowerBoundVariable(Exprs.LB);
+ Dir->setUpperBoundVariable(Exprs.UB);
+ Dir->setStrideVariable(Exprs.ST);
+ Dir->setEnsureUpperBound(Exprs.EUB);
+ Dir->setNextLowerBound(Exprs.NLB);
+ Dir->setNextUpperBound(Exprs.NUB);
+ Dir->setNumIterations(Exprs.NumIterations);
+ Dir->setPrevLowerBoundVariable(Exprs.PrevLB);
+ Dir->setPrevUpperBoundVariable(Exprs.PrevUB);
+ Dir->setCounters(Exprs.Counters);
+ Dir->setPrivateCounters(Exprs.PrivateCounters);
+ Dir->setInits(Exprs.Inits);
+ Dir->setUpdates(Exprs.Updates);
+ Dir->setFinals(Exprs.Finals);
+ Dir->setPreInits(Exprs.PreInits);
+ return Dir;
+}
+
+OMPTeamsDistributeParallelForDirective *
+OMPTeamsDistributeParallelForDirective::CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ unsigned CollapsedNum,
+ EmptyShell) {
+ auto Size = llvm::alignTo(sizeof(OMPTeamsDistributeParallelForDirective),
+ alignof(OMPClause *));
+ void *Mem = C.Allocate(
+ Size + sizeof(OMPClause *) * NumClauses +
+ sizeof(Stmt *) *
+ numLoopChildren(CollapsedNum, OMPD_teams_distribute_parallel_for));
+ return new (Mem)
+ OMPTeamsDistributeParallelForDirective(CollapsedNum, NumClauses);
+}
+
+OMPTargetTeamsDirective *OMPTargetTeamsDirective::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) {
+ auto Size =
+ llvm::alignTo(sizeof(OMPTargetTeamsDirective), alignof(OMPClause *));
+ void *Mem =
+ C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
+ OMPTargetTeamsDirective *Dir =
+ new (Mem) OMPTargetTeamsDirective(StartLoc, EndLoc, Clauses.size());
+ Dir->setClauses(Clauses);
+ Dir->setAssociatedStmt(AssociatedStmt);
+ return Dir;
+}
+
+OMPTargetTeamsDirective *
+OMPTargetTeamsDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses,
+ EmptyShell) {
+ auto Size =
+ llvm::alignTo(sizeof(OMPTargetTeamsDirective), alignof(OMPClause *));
+ void *Mem =
+ C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
+ return new (Mem) OMPTargetTeamsDirective(NumClauses);
+}
+
+OMPTargetTeamsDistributeDirective *OMPTargetTeamsDistributeDirective::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
+ const HelperExprs &Exprs) {
+ auto Size = llvm::alignTo(sizeof(OMPTargetTeamsDistributeDirective),
+ alignof(OMPClause *));
+ void *Mem = C.Allocate(
+ Size + sizeof(OMPClause *) * Clauses.size() +
+ sizeof(Stmt *) *
+ numLoopChildren(CollapsedNum, OMPD_target_teams_distribute));
+ OMPTargetTeamsDistributeDirective *Dir =
+ new (Mem) OMPTargetTeamsDistributeDirective(StartLoc, EndLoc, CollapsedNum,
+ Clauses.size());
+ Dir->setClauses(Clauses);
+ Dir->setAssociatedStmt(AssociatedStmt);
+ Dir->setIterationVariable(Exprs.IterationVarRef);
+ Dir->setLastIteration(Exprs.LastIteration);
+ Dir->setCalcLastIteration(Exprs.CalcLastIteration);
+ Dir->setPreCond(Exprs.PreCond);
+ Dir->setCond(Exprs.Cond);
+ Dir->setInit(Exprs.Init);
+ Dir->setInc(Exprs.Inc);
+ Dir->setIsLastIterVariable(Exprs.IL);
+ Dir->setLowerBoundVariable(Exprs.LB);
+ Dir->setUpperBoundVariable(Exprs.UB);
+ Dir->setStrideVariable(Exprs.ST);
+ Dir->setEnsureUpperBound(Exprs.EUB);
+ Dir->setNextLowerBound(Exprs.NLB);
+ Dir->setNextUpperBound(Exprs.NUB);
+ Dir->setNumIterations(Exprs.NumIterations);
+ Dir->setPrevLowerBoundVariable(Exprs.PrevLB);
+ Dir->setPrevUpperBoundVariable(Exprs.PrevUB);
+ Dir->setCounters(Exprs.Counters);
+ Dir->setPrivateCounters(Exprs.PrivateCounters);
+ Dir->setInits(Exprs.Inits);
+ Dir->setUpdates(Exprs.Updates);
+ Dir->setFinals(Exprs.Finals);
+ Dir->setPreInits(Exprs.PreInits);
+ return Dir;
+}
+
+OMPTargetTeamsDistributeDirective *
+OMPTargetTeamsDistributeDirective::CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ unsigned CollapsedNum,
+ EmptyShell) {
+ auto Size = llvm::alignTo(sizeof(OMPTargetTeamsDistributeDirective),
+ alignof(OMPClause *));
+ void *Mem = C.Allocate(
+ Size + sizeof(OMPClause *) * NumClauses +
+ sizeof(Stmt *) *
+ numLoopChildren(CollapsedNum, OMPD_target_teams_distribute));
+ return new (Mem) OMPTargetTeamsDistributeDirective(CollapsedNum, NumClauses);
+}
+
+OMPTargetTeamsDistributeParallelForDirective *
+OMPTargetTeamsDistributeParallelForDirective::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
+ const HelperExprs &Exprs) {
+ auto Size =
+ llvm::alignTo(sizeof(OMPTargetTeamsDistributeParallelForDirective),
+ alignof(OMPClause *));
+ void *Mem = C.Allocate(
+ Size + sizeof(OMPClause *) * Clauses.size() +
+ sizeof(Stmt *) *
+ numLoopChildren(CollapsedNum,
+ OMPD_target_teams_distribute_parallel_for));
+ OMPTargetTeamsDistributeParallelForDirective *Dir =
+ new (Mem) OMPTargetTeamsDistributeParallelForDirective(
+ StartLoc, EndLoc, CollapsedNum, Clauses.size());
+ Dir->setClauses(Clauses);
+ Dir->setAssociatedStmt(AssociatedStmt);
+ Dir->setIterationVariable(Exprs.IterationVarRef);
+ Dir->setLastIteration(Exprs.LastIteration);
+ Dir->setCalcLastIteration(Exprs.CalcLastIteration);
+ Dir->setPreCond(Exprs.PreCond);
+ Dir->setCond(Exprs.Cond);
+ Dir->setInit(Exprs.Init);
+ Dir->setInc(Exprs.Inc);
+ Dir->setIsLastIterVariable(Exprs.IL);
+ Dir->setLowerBoundVariable(Exprs.LB);
+ Dir->setUpperBoundVariable(Exprs.UB);
+ Dir->setStrideVariable(Exprs.ST);
+ Dir->setEnsureUpperBound(Exprs.EUB);
+ Dir->setNextLowerBound(Exprs.NLB);
+ Dir->setNextUpperBound(Exprs.NUB);
+ Dir->setNumIterations(Exprs.NumIterations);
+ Dir->setPrevLowerBoundVariable(Exprs.PrevLB);
+ Dir->setPrevUpperBoundVariable(Exprs.PrevUB);
+ Dir->setCounters(Exprs.Counters);
+ Dir->setPrivateCounters(Exprs.PrivateCounters);
+ Dir->setInits(Exprs.Inits);
+ Dir->setUpdates(Exprs.Updates);
+ Dir->setFinals(Exprs.Finals);
+ Dir->setPreInits(Exprs.PreInits);
+ return Dir;
+}
+
+OMPTargetTeamsDistributeParallelForDirective *
+OMPTargetTeamsDistributeParallelForDirective::CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ unsigned CollapsedNum,
+ EmptyShell) {
+ auto Size =
+ llvm::alignTo(sizeof(OMPTargetTeamsDistributeParallelForDirective),
+ alignof(OMPClause *));
+ void *Mem = C.Allocate(
+ Size + sizeof(OMPClause *) * NumClauses +
+ sizeof(Stmt *) *
+ numLoopChildren(CollapsedNum,
+ OMPD_target_teams_distribute_parallel_for));
+ return new (Mem)
+ OMPTargetTeamsDistributeParallelForDirective(CollapsedNum, NumClauses);
+}
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index 8797a13335c4..a8f493dca07d 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -1198,6 +1198,52 @@ void StmtPrinter::VisitOMPTargetParallelForSimdDirective(
PrintOMPExecutableDirective(Node);
}
+void StmtPrinter::VisitOMPTargetSimdDirective(OMPTargetSimdDirective *Node) {
+ Indent() << "#pragma omp target simd ";
+ PrintOMPExecutableDirective(Node);
+}
+
+void StmtPrinter::VisitOMPTeamsDistributeDirective(
+ OMPTeamsDistributeDirective *Node) {
+ Indent() << "#pragma omp teams distribute ";
+ PrintOMPExecutableDirective(Node);
+}
+
+void StmtPrinter::VisitOMPTeamsDistributeSimdDirective(
+ OMPTeamsDistributeSimdDirective *Node) {
+ Indent() << "#pragma omp teams distribute simd ";
+ PrintOMPExecutableDirective(Node);
+}
+
+void StmtPrinter::VisitOMPTeamsDistributeParallelForSimdDirective(
+ OMPTeamsDistributeParallelForSimdDirective *Node) {
+ Indent() << "#pragma omp teams distribute parallel for simd ";
+ PrintOMPExecutableDirective(Node);
+}
+
+void StmtPrinter::VisitOMPTeamsDistributeParallelForDirective(
+ OMPTeamsDistributeParallelForDirective *Node) {
+ Indent() << "#pragma omp teams distribute parallel for ";
+ PrintOMPExecutableDirective(Node);
+}
+
+void StmtPrinter::VisitOMPTargetTeamsDirective(OMPTargetTeamsDirective *Node) {
+ Indent() << "#pragma omp target teams ";
+ PrintOMPExecutableDirective(Node);
+}
+
+void StmtPrinter::VisitOMPTargetTeamsDistributeDirective(
+ OMPTargetTeamsDistributeDirective *Node) {
+ Indent() << "#pragma omp target teams distribute ";
+ PrintOMPExecutableDirective(Node);
+}
+
+void StmtPrinter::VisitOMPTargetTeamsDistributeParallelForDirective(
+ OMPTargetTeamsDistributeParallelForDirective *Node) {
+ Indent() << "#pragma omp target teams distribute parallel for ";
+ PrintOMPExecutableDirective(Node);
+}
+
//===----------------------------------------------------------------------===//
// Expr printing methods.
//===----------------------------------------------------------------------===//
@@ -1676,6 +1722,18 @@ void StmtPrinter::VisitInitListExpr(InitListExpr* Node) {
OS << "}";
}
+void StmtPrinter::VisitArrayInitLoopExpr(ArrayInitLoopExpr *Node) {
+ // There's no way to express this expression in any of our supported
+ // languages, so just emit something terse and (hopefully) clear.
+ OS << "{";
+ PrintExpr(Node->getSubExpr());
+ OS << "}";
+}
+
+void StmtPrinter::VisitArrayInitIndexExpr(ArrayInitIndexExpr *Node) {
+ OS << "*";
+}
+
void StmtPrinter::VisitParenListExpr(ParenListExpr* Node) {
OS << "(";
for (unsigned i = 0, e = Node->getNumExprs(); i != e; ++i) {
diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp
index 0a39413853a0..dd59a9b96c98 100644
--- a/lib/AST/StmtProfile.cpp
+++ b/lib/AST/StmtProfile.cpp
@@ -93,10 +93,6 @@ void StmtProfiler::VisitCompoundStmt(const CompoundStmt *S) {
VisitStmt(S);
}
-void StmtProfiler::VisitSwitchCase(const SwitchCase *S) {
- VisitStmt(S);
-}
-
void StmtProfiler::VisitCaseStmt(const CaseStmt *S) {
VisitStmt(S);
}
@@ -727,6 +723,46 @@ void StmtProfiler::VisitOMPTargetParallelForSimdDirective(
VisitOMPLoopDirective(S);
}
+void StmtProfiler::VisitOMPTargetSimdDirective(
+ const OMPTargetSimdDirective *S) {
+ VisitOMPLoopDirective(S);
+}
+
+void StmtProfiler::VisitOMPTeamsDistributeDirective(
+ const OMPTeamsDistributeDirective *S) {
+ VisitOMPLoopDirective(S);
+}
+
+void StmtProfiler::VisitOMPTeamsDistributeSimdDirective(
+ const OMPTeamsDistributeSimdDirective *S) {
+ VisitOMPLoopDirective(S);
+}
+
+void StmtProfiler::VisitOMPTeamsDistributeParallelForSimdDirective(
+ const OMPTeamsDistributeParallelForSimdDirective *S) {
+ VisitOMPLoopDirective(S);
+}
+
+void StmtProfiler::VisitOMPTeamsDistributeParallelForDirective(
+ const OMPTeamsDistributeParallelForDirective *S) {
+ VisitOMPLoopDirective(S);
+}
+
+void StmtProfiler::VisitOMPTargetTeamsDirective(
+ const OMPTargetTeamsDirective *S) {
+ VisitOMPExecutableDirective(S);
+}
+
+void StmtProfiler::VisitOMPTargetTeamsDistributeDirective(
+ const OMPTargetTeamsDistributeDirective *S) {
+ VisitOMPLoopDirective(S);
+}
+
+void StmtProfiler::VisitOMPTargetTeamsDistributeParallelForDirective(
+ const OMPTargetTeamsDistributeParallelForDirective *S) {
+ VisitOMPLoopDirective(S);
+}
+
void StmtProfiler::VisitExpr(const Expr *S) {
VisitStmt(S);
}
@@ -951,6 +987,14 @@ void StmtProfiler::VisitDesignatedInitUpdateExpr(
"initializer");
}
+void StmtProfiler::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *S) {
+ VisitExpr(S);
+}
+
+void StmtProfiler::VisitArrayInitIndexExpr(const ArrayInitIndexExpr *S) {
+ VisitExpr(S);
+}
+
void StmtProfiler::VisitNoInitExpr(const NoInitExpr *S) {
llvm_unreachable("Unexpected NoInitExpr in syntactic form of initializer");
}
@@ -1184,6 +1228,12 @@ void StmtProfiler::VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *S) {
if (S->isTypeDependent()) {
// Type-dependent operator calls are profiled like their underlying
// syntactic operator.
+ //
+ // An operator call to operator-> is always implicit, so just skip it. The
+ // enclosing MemberExpr will profile the actual member access.
+ if (S->getOperator() == OO_Arrow)
+ return Visit(S->getArg(0));
+
UnaryOperatorKind UnaryOp = UO_Extension;
BinaryOperatorKind BinaryOp = BO_Comma;
Stmt::StmtClass SC = DecodeOperatorCall(S, UnaryOp, BinaryOp);
diff --git a/lib/AST/TemplateBase.cpp b/lib/AST/TemplateBase.cpp
index b75ede862f7a..099f939c7a75 100644
--- a/lib/AST/TemplateBase.cpp
+++ b/lib/AST/TemplateBase.cpp
@@ -243,6 +243,31 @@ Optional<unsigned> TemplateArgument::getNumTemplateExpansions() const {
return None;
}
+QualType TemplateArgument::getNonTypeTemplateArgumentType() const {
+ switch (getKind()) {
+ case TemplateArgument::Null:
+ case TemplateArgument::Type:
+ case TemplateArgument::Template:
+ case TemplateArgument::TemplateExpansion:
+ case TemplateArgument::Pack:
+ return QualType();
+
+ case TemplateArgument::Integral:
+ return getIntegralType();
+
+ case TemplateArgument::Expression:
+ return getAsExpr()->getType();
+
+ case TemplateArgument::Declaration:
+ return getParamTypeForDecl();
+
+ case TemplateArgument::NullPtr:
+ return getNullPtrType();
+ }
+
+ llvm_unreachable("Invalid TemplateArgument Kind!");
+}
+
void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
const ASTContext &Context) const {
ID.AddInteger(getKind());
@@ -530,7 +555,7 @@ const ASTTemplateArgumentListInfo *
ASTTemplateArgumentListInfo::Create(ASTContext &C,
const TemplateArgumentListInfo &List) {
std::size_t size = totalSizeToAlloc<TemplateArgumentLoc>(List.size());
- void *Mem = C.Allocate(size, llvm::alignOf<ASTTemplateArgumentListInfo>());
+ void *Mem = C.Allocate(size, alignof(ASTTemplateArgumentListInfo));
return new (Mem) ASTTemplateArgumentListInfo(List);
}
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 99b024701aa3..0d0cd2e305be 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -11,6 +11,7 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/AST/Type.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
#include "clang/AST/CharUnits.h"
@@ -19,13 +20,11 @@
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
#include "clang/AST/PrettyPrinter.h"
-#include "clang/AST/Type.h"
#include "clang/AST/TypeVisitor.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/StringExtras.h"
-#include "llvm/Support/raw_ostream.h"
#include <algorithm>
using namespace clang;
@@ -532,6 +531,18 @@ bool Type::isObjCInertUnsafeUnretainedType() const {
}
}
+ObjCTypeParamType::ObjCTypeParamType(const ObjCTypeParamDecl *D,
+ QualType can,
+ ArrayRef<ObjCProtocolDecl *> protocols)
+ : Type(ObjCTypeParam, can, can->isDependentType(),
+ can->isInstantiationDependentType(),
+ can->isVariablyModifiedType(),
+ /*ContainsUnexpandedParameterPack=*/false),
+ OTPDecl(const_cast<ObjCTypeParamDecl*>(D))
+{
+ initialize(protocols);
+}
+
ObjCObjectType::ObjCObjectType(QualType Canonical, QualType Base,
ArrayRef<QualType> typeArgs,
ArrayRef<ObjCProtocolDecl *> protocols,
@@ -547,15 +558,9 @@ ObjCObjectType::ObjCObjectType(QualType Canonical, QualType Base,
ObjCObjectTypeBits.NumTypeArgs = typeArgs.size();
assert(getTypeArgsAsWritten().size() == typeArgs.size() &&
"bitfield overflow in type argument count");
- ObjCObjectTypeBits.NumProtocols = protocols.size();
- assert(getNumProtocols() == protocols.size() &&
- "bitfield overflow in protocol count");
if (!typeArgs.empty())
memcpy(getTypeArgStorage(), typeArgs.data(),
typeArgs.size() * sizeof(QualType));
- if (!protocols.empty())
- memcpy(getProtocolStorage(), protocols.data(),
- protocols.size() * sizeof(ObjCProtocolDecl*));
for (auto typeArg : typeArgs) {
if (typeArg->isDependentType())
@@ -566,6 +571,9 @@ ObjCObjectType::ObjCObjectType(QualType Canonical, QualType Base,
if (typeArg->containsUnexpandedParameterPack())
setContainsUnexpandedParameterPack();
}
+ // Initialize the protocol qualifiers. The protocol storage is known
+ // after we set number of type arguments.
+ initialize(protocols);
}
bool ObjCObjectType::isSpecialized() const {
@@ -883,6 +891,7 @@ public:
}
TRIVIAL_TYPE_CLASS(Typedef)
+ TRIVIAL_TYPE_CLASS(ObjCTypeParam)
QualType VisitAdjustedType(const AdjustedType *T) {
QualType originalType = recurse(T->getOriginalType());
@@ -1048,7 +1057,7 @@ QualType simpleTransform(ASTContext &ctx, QualType type, F &&f) {
SplitQualType splitType = type.split();
// Visit the type itself.
- SimpleTransformVisitor<F> visitor(ctx, std::move(f));
+ SimpleTransformVisitor<F> visitor(ctx, std::forward<F>(f));
QualType result = visitor.Visit(splitType.Ty);
if (result.isNull())
return result;
@@ -1072,13 +1081,24 @@ QualType QualType::substObjCTypeArgs(
// Replace an Objective-C type parameter reference with the corresponding
// type argument.
- if (const auto *typedefTy = dyn_cast<TypedefType>(splitType.Ty)) {
- if (auto *typeParam = dyn_cast<ObjCTypeParamDecl>(typedefTy->getDecl())) {
+ 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()) {
- // FIXME: Introduce SubstObjCTypeParamType ?
QualType argType = typeArgs[typeParam->getIndex()];
- return ctx.getQualifiedType(argType, splitType.Quals);
+ 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) {
@@ -2317,6 +2337,15 @@ bool QualType::isCXX11PODType(const ASTContext &Context) const {
return false;
}
+bool Type::isAlignValT() const {
+ if (auto *ET = getAs<EnumType>()) {
+ auto *II = ET->getDecl()->getIdentifier();
+ if (II && II->isStr("align_val_t") && ET->getDecl()->isInStdNamespace())
+ return true;
+ }
+ return false;
+}
+
bool Type::isPromotableIntegerType() const {
if (const BuiltinType *BT = getAs<BuiltinType>())
switch (BT->getKind()) {
@@ -2638,6 +2667,7 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) {
case CC_X86VectorCall: return "vectorcall";
case CC_X86_64Win64: return "ms_abi";
case CC_X86_64SysV: return "sysv_abi";
+ case CC_X86RegCall : return "regcall";
case CC_AAPCS: return "aapcs";
case CC_AAPCS_VFP: return "aapcs-vfp";
case CC_IntelOclBicc: return "intel_ocl_bicc";
@@ -2688,8 +2718,9 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params,
QualType *exnSlot = argSlot + NumParams;
unsigned I = 0;
for (QualType ExceptionType : epi.ExceptionSpec.Exceptions) {
- // Note that a dependent exception specification does *not* make
- // a type dependent; it's not even part of the C++ type system.
+ // Note that, before C++17, a dependent exception specification does
+ // *not* make a type dependent; it's not even part of the C++ type
+ // system.
if (ExceptionType->isInstantiationDependentType())
setInstantiationDependent();
@@ -2728,6 +2759,19 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params,
slot[0] = epi.ExceptionSpec.SourceDecl;
}
+ // If this is a canonical type, and its exception specification is dependent,
+ // then it's a dependent type. This only happens in C++17 onwards.
+ if (isCanonicalUnqualified()) {
+ if (getExceptionSpecType() == EST_Dynamic ||
+ getExceptionSpecType() == EST_ComputedNoexcept) {
+ assert(hasDependentExceptionSpec() && "type should not be canonical");
+ setDependent();
+ }
+ } else if (getCanonicalTypeInternal()->isDependentType()) {
+ // Ask our canonical type whether our exception specification was dependent.
+ setDependent();
+ }
+
if (epi.ExtParameterInfos) {
ExtParameterInfo *extParamInfos =
const_cast<ExtParameterInfo *>(getExtParameterInfosBuffer());
@@ -2748,6 +2792,15 @@ bool FunctionProtoType::hasDependentExceptionSpec() const {
return false;
}
+bool FunctionProtoType::hasInstantiationDependentExceptionSpec() const {
+ if (Expr *NE = getNoexceptExpr())
+ return NE->isInstantiationDependent();
+ for (QualType ET : exceptions())
+ if (ET->isInstantiationDependentType())
+ return true;
+ return false;
+}
+
FunctionProtoType::NoexceptResult
FunctionProtoType::getNoexceptSpec(const ASTContext &ctx) const {
ExceptionSpecificationType est = getExceptionSpecType();
@@ -2772,29 +2825,28 @@ FunctionProtoType::getNoexceptSpec(const ASTContext &ctx) const {
return value.getBoolValue() ? NR_Nothrow : NR_Throw;
}
-bool FunctionProtoType::isNothrow(const ASTContext &Ctx,
- bool ResultIfDependent) const {
+CanThrowResult FunctionProtoType::canThrow(const ASTContext &Ctx) const {
ExceptionSpecificationType EST = getExceptionSpecType();
assert(EST != EST_Unevaluated && EST != EST_Uninstantiated);
if (EST == EST_DynamicNone || EST == EST_BasicNoexcept)
- return true;
+ return CT_Cannot;
- if (EST == EST_Dynamic && ResultIfDependent) {
+ if (EST == 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 false;
- return ResultIfDependent;
+ return CT_Can;
+ return CT_Dependent;
}
if (EST != EST_ComputedNoexcept)
- return false;
+ return CT_Can;
NoexceptResult NR = getNoexceptSpec(Ctx);
if (NR == NR_Dependent)
- return ResultIfDependent;
- return NR == NR_Nothrow;
+ return CT_Dependent;
+ return NR == NR_Nothrow ? CT_Cannot : CT_Can;
}
bool FunctionProtoType::isTemplateVariadic() const {
@@ -2808,7 +2860,7 @@ bool FunctionProtoType::isTemplateVariadic() const {
void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result,
const QualType *ArgTys, unsigned NumParams,
const ExtProtoInfo &epi,
- const ASTContext &Context) {
+ const ASTContext &Context, bool Canonical) {
// We have to be careful not to get ambiguous profile encodings.
// Note that valid type pointers are never ambiguous with anything else.
@@ -2847,7 +2899,7 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result,
ID.AddPointer(Ex.getAsOpaquePtr());
} else if (epi.ExceptionSpec.Type == EST_ComputedNoexcept &&
epi.ExceptionSpec.NoexceptExpr) {
- epi.ExceptionSpec.NoexceptExpr->Profile(ID, Context, false);
+ epi.ExceptionSpec.NoexceptExpr->Profile(ID, Context, Canonical);
} else if (epi.ExceptionSpec.Type == EST_Uninstantiated ||
epi.ExceptionSpec.Type == EST_Unevaluated) {
ID.AddPointer(epi.ExceptionSpec.SourceDecl->getCanonicalDecl());
@@ -2863,7 +2915,7 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result,
void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID,
const ASTContext &Ctx) {
Profile(ID, getReturnType(), param_type_begin(), NumParams, getExtProtoInfo(),
- Ctx);
+ Ctx, isCanonicalUnqualified());
}
QualType TypedefType::desugar() const {
@@ -2992,6 +3044,7 @@ bool AttributedType::isQualifier() const {
case AttributedType::attr_fastcall:
case AttributedType::attr_stdcall:
case AttributedType::attr_thiscall:
+ case AttributedType::attr_regcall:
case AttributedType::attr_pascal:
case AttributedType::attr_swiftcall:
case AttributedType::attr_vectorcall:
@@ -3049,6 +3102,7 @@ bool AttributedType::isCallingConv() const {
case attr_fastcall:
case attr_stdcall:
case attr_thiscall:
+ case attr_regcall:
case attr_swiftcall:
case attr_vectorcall:
case attr_pascal:
@@ -3212,6 +3266,20 @@ void ObjCObjectTypeImpl::Profile(llvm::FoldingSetNodeID &ID) {
isKindOfTypeAsWritten());
}
+void ObjCTypeParamType::Profile(llvm::FoldingSetNodeID &ID,
+ const ObjCTypeParamDecl *OTPDecl,
+ ArrayRef<ObjCProtocolDecl *> protocols) {
+ ID.AddPointer(OTPDecl);
+ ID.AddInteger(protocols.size());
+ for (auto proto : protocols)
+ ID.AddPointer(proto);
+}
+
+void ObjCTypeParamType::Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getDecl(),
+ llvm::makeArrayRef(qual_begin(), getNumProtocols()));
+}
+
namespace {
/// \brief The cached properties of a type.
@@ -3687,10 +3755,18 @@ bool Type::isObjCARCImplicitlyUnretainedType() const {
}
bool Type::isObjCNSObjectType() const {
- if (const TypedefType *typedefType = dyn_cast<TypedefType>(this))
- return typedefType->getDecl()->hasAttr<ObjCNSObjectAttr>();
- return false;
+ const Type *cur = this;
+ while (true) {
+ if (const TypedefType *typedefType = dyn_cast<TypedefType>(cur))
+ return typedefType->getDecl()->hasAttr<ObjCNSObjectAttr>();
+
+ // Single-step desugar until we run out of sugar.
+ QualType next = cur->getLocallyUnqualifiedSingleStepDesugaredType();
+ if (next.getTypePtr() == cur) return false;
+ cur = next.getTypePtr();
+ }
}
+
bool Type::isObjCIndependentClassType() const {
if (const TypedefType *typedefType = dyn_cast<TypedefType>(this))
return typedefType->getDecl()->hasAttr<ObjCIndependentClassAttr>();
diff --git a/lib/AST/TypeLoc.cpp b/lib/AST/TypeLoc.cpp
index 78947d18f953..7242858f21e6 100644
--- a/lib/AST/TypeLoc.cpp
+++ b/lib/AST/TypeLoc.cpp
@@ -16,10 +16,9 @@
#include "clang/AST/Expr.h"
#include "clang/AST/TypeLocVisitor.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/raw_ostream.h"
using namespace clang;
-static const unsigned TypeLocMaxDataAlign = llvm::alignOf<void *>();
+static const unsigned TypeLocMaxDataAlign = alignof(void *);
//===----------------------------------------------------------------------===//
// TypeLoc Implementation
@@ -211,7 +210,7 @@ SourceLocation TypeLoc::getEndLoc() const {
switch (Cur.getTypeLocClass()) {
default:
if (!Last)
- Last = Cur;
+ Last = Cur;
return Last.getLocalSourceRange().getEnd();
case Paren:
case ConstantArray:
@@ -389,6 +388,17 @@ TypeLoc TypeLoc::findExplicitQualifierLoc() const {
return TypeLoc();
}
+void ObjCTypeParamTypeLoc::initializeLocal(ASTContext &Context,
+ SourceLocation Loc) {
+ setNameLoc(Loc);
+ if (!getNumProtocols()) return;
+
+ setProtocolLAngleLoc(Loc);
+ setProtocolRAngleLoc(Loc);
+ for (unsigned i = 0, e = getNumProtocols(); i != e; ++i)
+ setProtocolLoc(i, Loc);
+}
+
void ObjCObjectTypeLoc::initializeLocal(ASTContext &Context,
SourceLocation Loc) {
setHasBaseTypeAsWritten(true);
diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp
index 065a2db09141..cccc90876321 100644
--- a/lib/AST/TypePrinter.cpp
+++ b/lib/AST/TypePrinter.cpp
@@ -194,6 +194,7 @@ bool TypePrinter::canPrefixQualifiers(const Type *T,
case Type::DependentName:
case Type::DependentTemplateSpecialization:
case Type::ObjCObject:
+ case Type::ObjCTypeParam:
case Type::ObjCInterface:
case Type::Atomic:
case Type::Pipe:
@@ -724,6 +725,9 @@ void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T,
case CC_X86_64SysV:
OS << " __attribute__((sysv_abi))";
break;
+ case CC_X86RegCall:
+ OS << " __attribute__((regcall))";
+ break;
case CC_SpirFunction:
case CC_OpenCLKernel:
// Do nothing. These CCs are not available as attributes.
@@ -897,6 +901,10 @@ void TypePrinter::printAtomicAfter(const AtomicType *T, raw_ostream &OS) { }
void TypePrinter::printPipeBefore(const PipeType *T, raw_ostream &OS) {
IncludeStrongLifetimeRAII Strong(Policy);
+ if (T->isReadOnly())
+ OS << "read_only ";
+ else
+ OS << "write_only ";
OS << "pipe ";
print(T->getElementType(), OS, StringRef());
spaceBeforePlaceHolder(OS);
@@ -1338,6 +1346,7 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
case AttributedType::attr_pascal: OS << "pascal"; break;
case AttributedType::attr_ms_abi: OS << "ms_abi"; break;
case AttributedType::attr_sysv_abi: OS << "sysv_abi"; break;
+ case AttributedType::attr_regcall: OS << "regcall"; break;
case AttributedType::attr_pcs:
case AttributedType::attr_pcs_vfp: {
OS << "pcs(";
@@ -1368,6 +1377,28 @@ void TypePrinter::printObjCInterfaceBefore(const ObjCInterfaceType *T,
void TypePrinter::printObjCInterfaceAfter(const ObjCInterfaceType *T,
raw_ostream &OS) { }
+void TypePrinter::printObjCTypeParamBefore(const ObjCTypeParamType *T,
+ raw_ostream &OS) {
+ OS << T->getDecl()->getName();
+ if (!T->qual_empty()) {
+ bool isFirst = true;
+ OS << '<';
+ for (const auto *I : T->quals()) {
+ if (isFirst)
+ isFirst = false;
+ else
+ OS << ',';
+ OS << I->getName();
+ }
+ OS << '>';
+ }
+
+ spaceBeforePlaceHolder(OS);
+}
+
+void TypePrinter::printObjCTypeParamAfter(const ObjCTypeParamType *T,
+ raw_ostream &OS) { }
+
void TypePrinter::printObjCObjectBefore(const ObjCObjectType *T,
raw_ostream &OS) {
if (T->qual_empty() && T->isUnspecializedAsWritten() &&
diff --git a/lib/AST/VTableBuilder.cpp b/lib/AST/VTableBuilder.cpp
index 640fbf47aeab..e60ae33f2e5c 100644
--- a/lib/AST/VTableBuilder.cpp
+++ b/lib/AST/VTableBuilder.cpp
@@ -777,9 +777,8 @@ public:
typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits>
VBaseOffsetOffsetsMapTy;
-
- typedef llvm::DenseMap<BaseSubobject, uint64_t>
- AddressPointsMapTy;
+
+ typedef VTableLayout::AddressPointsMapTy AddressPointsMapTy;
typedef llvm::DenseMap<GlobalDecl, int64_t> MethodVTableIndicesTy;
@@ -817,7 +816,7 @@ private:
/// VBaseOffsetOffsets - Contains the offsets of the virtual base offsets for
/// the most derived class.
VBaseOffsetOffsetsMapTy VBaseOffsetOffsets;
-
+
/// Components - The components of the vtable being built.
SmallVector<VTableComponent, 64> Components;
@@ -982,6 +981,10 @@ private:
}
public:
+ /// Component indices of the first component of each of the vtables in the
+ /// vtable group.
+ SmallVector<size_t, 4> VTableIndices;
+
ItaniumVTableBuilder(ItaniumVTableContext &VTables,
const CXXRecordDecl *MostDerivedClass,
CharUnits MostDerivedClassOffset,
@@ -1028,20 +1031,8 @@ public:
return MethodVTableIndices.end();
}
- /// getNumVTableComponents - Return the number of components in the vtable
- /// currently built.
- uint64_t getNumVTableComponents() const {
- return Components.size();
- }
+ ArrayRef<VTableComponent> vtable_components() const { return Components; }
- const VTableComponent *vtable_component_begin() const {
- return Components.begin();
- }
-
- const VTableComponent *vtable_component_end() const {
- return Components.end();
- }
-
AddressPointsMapTy::const_iterator address_points_begin() const {
return AddressPoints.begin();
}
@@ -1639,6 +1630,9 @@ void ItaniumVTableBuilder::LayoutPrimaryAndSecondaryVTables(
bool BaseIsVirtualInLayoutClass, CharUnits OffsetInLayoutClass) {
assert(Base.getBase()->isDynamicClass() && "class does not have a vtable!");
+ unsigned VTableIndex = Components.size();
+ VTableIndices.push_back(VTableIndex);
+
// Add vcall and vbase offsets for this vtable.
VCallAndVBaseOffsetBuilder Builder(MostDerivedClass, LayoutClass, &Overriders,
Base, BaseIsVirtualInLayoutClass,
@@ -1695,9 +1689,11 @@ void ItaniumVTableBuilder::LayoutPrimaryAndSecondaryVTables(
// Add all address points.
while (true) {
- AddressPoints.insert(std::make_pair(
- BaseSubobject(RD, OffsetInLayoutClass),
- AddressPoint));
+ AddressPoints.insert(
+ std::make_pair(BaseSubobject(RD, OffsetInLayoutClass),
+ VTableLayout::AddressPointLocation{
+ unsigned(VTableIndices.size() - 1),
+ unsigned(AddressPoint - VTableIndex)}));
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
@@ -1901,7 +1897,8 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
std::multimap<uint64_t, BaseSubobject> AddressPointsByIndex;
for (const auto &AP : AddressPoints) {
const BaseSubobject &Base = AP.first;
- uint64_t Index = AP.second;
+ uint64_t Index =
+ VTableIndices[AP.second.VTableIndex] + AP.second.AddressPointIndex;
AddressPointsByIndex.insert(std::make_pair(Index, Base));
}
@@ -2203,30 +2200,24 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) {
}
}
-VTableLayout::VTableLayout(uint64_t NumVTableComponents,
- const VTableComponent *VTableComponents,
- uint64_t NumVTableThunks,
- const VTableThunkTy *VTableThunks,
- const AddressPointsMapTy &AddressPoints,
- bool IsMicrosoftABI)
- : NumVTableComponents(NumVTableComponents),
- VTableComponents(new VTableComponent[NumVTableComponents]),
- NumVTableThunks(NumVTableThunks),
- VTableThunks(new VTableThunkTy[NumVTableThunks]),
- AddressPoints(AddressPoints),
- IsMicrosoftABI(IsMicrosoftABI) {
- std::copy(VTableComponents, VTableComponents+NumVTableComponents,
- this->VTableComponents.get());
- std::copy(VTableThunks, VTableThunks+NumVTableThunks,
- this->VTableThunks.get());
- std::sort(this->VTableThunks.get(),
- this->VTableThunks.get() + NumVTableThunks,
+VTableLayout::VTableLayout(ArrayRef<size_t> VTableIndices,
+ ArrayRef<VTableComponent> VTableComponents,
+ ArrayRef<VTableThunkTy> VTableThunks,
+ const AddressPointsMapTy &AddressPoints)
+ : VTableComponents(VTableComponents), VTableThunks(VTableThunks),
+ AddressPoints(AddressPoints) {
+ if (VTableIndices.size() <= 1)
+ assert(VTableIndices.size() == 1 && VTableIndices[0] == 0);
+ else
+ this->VTableIndices = OwningArrayRef<size_t>(VTableIndices);
+
+ std::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;
- });
+ assert((LHS.first != RHS.first || LHS.second == RHS.second) &&
+ "Different thunks should have unique indices!");
+ return LHS.first < RHS.first;
+ });
}
VTableLayout::~VTableLayout() { }
@@ -2234,9 +2225,7 @@ VTableLayout::~VTableLayout() { }
ItaniumVTableContext::ItaniumVTableContext(ASTContext &Context)
: VTableContextBase(/*MS=*/false) {}
-ItaniumVTableContext::~ItaniumVTableContext() {
- llvm::DeleteContainerSeconds(VTableLayouts);
-}
+ItaniumVTableContext::~ItaniumVTableContext() {}
uint64_t ItaniumVTableContext::getMethodVTableIndex(GlobalDecl GD) {
MethodVTableIndicesTy::iterator I = MethodVTableIndices.find(GD);
@@ -2280,21 +2269,19 @@ ItaniumVTableContext::getVirtualBaseOffsetOffset(const CXXRecordDecl *RD,
return I->second;
}
-static VTableLayout *CreateVTableLayout(const ItaniumVTableBuilder &Builder) {
+static std::unique_ptr<VTableLayout>
+CreateVTableLayout(const ItaniumVTableBuilder &Builder) {
SmallVector<VTableLayout::VTableThunkTy, 1>
VTableThunks(Builder.vtable_thunks_begin(), Builder.vtable_thunks_end());
- return new VTableLayout(Builder.getNumVTableComponents(),
- Builder.vtable_component_begin(),
- VTableThunks.size(),
- VTableThunks.data(),
- Builder.getAddressPoints(),
- /*IsMicrosoftABI=*/false);
+ return llvm::make_unique<VTableLayout>(
+ Builder.VTableIndices, Builder.vtable_components(), VTableThunks,
+ Builder.getAddressPoints());
}
void
ItaniumVTableContext::computeVTableRelatedInformation(const CXXRecordDecl *RD) {
- const VTableLayout *&Entry = VTableLayouts[RD];
+ std::unique_ptr<const VTableLayout> &Entry = VTableLayouts[RD];
// Check if we've computed this information before.
if (Entry)
@@ -2330,7 +2317,8 @@ ItaniumVTableContext::computeVTableRelatedInformation(const CXXRecordDecl *RD) {
}
}
-VTableLayout *ItaniumVTableContext::createConstructionVTableLayout(
+std::unique_ptr<VTableLayout>
+ItaniumVTableContext::createConstructionVTableLayout(
const CXXRecordDecl *MostDerivedClass, CharUnits MostDerivedClassOffset,
bool MostDerivedClassIsVirtual, const CXXRecordDecl *LayoutClass) {
ItaniumVTableBuilder Builder(*this, MostDerivedClass, MostDerivedClassOffset,
@@ -2538,12 +2526,12 @@ private:
public:
VFTableBuilder(MicrosoftVTableContext &VTables,
- const CXXRecordDecl *MostDerivedClass, const VPtrInfo *Which)
+ const CXXRecordDecl *MostDerivedClass, const VPtrInfo &Which)
: VTables(VTables),
Context(MostDerivedClass->getASTContext()),
MostDerivedClass(MostDerivedClass),
MostDerivedClassLayout(Context.getASTRecordLayout(MostDerivedClass)),
- WhichVFPtr(*Which),
+ WhichVFPtr(Which),
Overriders(MostDerivedClass, CharUnits(), MostDerivedClass) {
// Provide the RTTI component if RTTIData is enabled. If the vftable would
// be available externally, we should not provide the RTTI componenent. It
@@ -2570,15 +2558,7 @@ public:
MethodVFTableLocations.end());
}
- uint64_t getNumVTableComponents() const { return Components.size(); }
-
- const VTableComponent *vtable_component_begin() const {
- return Components.begin();
- }
-
- const VTableComponent *vtable_component_end() const {
- return Components.end();
- }
+ ArrayRef<VTableComponent> vtable_components() const { return Components; }
VTableThunksMapTy::const_iterator vtable_thunks_begin() const {
return VTableThunks.begin();
@@ -2931,8 +2911,8 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth,
// class.
const CXXRecordDecl *NextBase = nullptr, *NextLastVBase = LastVBase;
CharUnits NextBaseOffset;
- if (BaseDepth < WhichVFPtr.PathToBaseWithVPtr.size()) {
- NextBase = WhichVFPtr.PathToBaseWithVPtr[BaseDepth];
+ if (BaseDepth < WhichVFPtr.PathToIntroducingObject.size()) {
+ NextBase = WhichVFPtr.PathToIntroducingObject[BaseDepth];
if (isDirectVBase(NextBase, RD)) {
NextLastVBase = NextBase;
NextBaseOffset = MostDerivedClassLayout.getVBaseClassOffset(NextBase);
@@ -3124,7 +3104,7 @@ static void dumpMicrosoftThunkAdjustment(const ThunkInfo &TI, raw_ostream &Out,
void VFTableBuilder::dumpLayout(raw_ostream &Out) {
Out << "VFTable for ";
- PrintBasePath(WhichVFPtr.PathToBaseWithVPtr, Out);
+ PrintBasePath(WhichVFPtr.PathToIntroducingObject, Out);
Out << "'";
MostDerivedClass->printQualifiedName(Out);
Out << "' (" << Components.size()
@@ -3278,7 +3258,7 @@ void MicrosoftVTableContext::computeVTablePaths(bool ForVBTables,
// Base case: this subobject has its own vptr.
if (ForVBTables ? Layout.hasOwnVBPtr() : Layout.hasOwnVFPtr())
- Paths.push_back(new VPtrInfo(RD));
+ Paths.push_back(llvm::make_unique<VPtrInfo>(RD));
// Recursive case: get all the vbtables from our bases and remove anything
// that shares a virtual base.
@@ -3294,14 +3274,14 @@ void MicrosoftVTableContext::computeVTablePaths(bool ForVBTables,
const VPtrInfoVector &BasePaths =
ForVBTables ? enumerateVBTables(Base) : getVFPtrOffsets(Base);
- for (VPtrInfo *BaseInfo : BasePaths) {
+ for (const std::unique_ptr<VPtrInfo> &BaseInfo : BasePaths) {
// Don't include the path if it goes through a virtual base that we've
// already included.
if (setsIntersect(VBasesSeen, BaseInfo->ContainingVBases))
continue;
// Copy the path and adjust it as necessary.
- VPtrInfo *P = new VPtrInfo(*BaseInfo);
+ auto P = llvm::make_unique<VPtrInfo>(*BaseInfo);
// We mangle Base into the path if the path would've been ambiguous and it
// wasn't already extended with Base.
@@ -3311,10 +3291,10 @@ void MicrosoftVTableContext::computeVTablePaths(bool ForVBTables,
// Keep track of which vtable the derived class is going to extend with
// new methods or bases. We append to either the vftable of our primary
// base, or the first non-virtual base that has a vbtable.
- if (P->ReusingBase == Base &&
+ if (P->ObjectWithVPtr == Base &&
Base == (ForVBTables ? Layout.getBaseSharingVBPtr()
: Layout.getPrimaryBase()))
- P->ReusingBase = RD;
+ P->ObjectWithVPtr = RD;
// Keep track of the full adjustment from the MDC to this vtable. The
// adjustment is captured by an optional vbase and a non-virtual offset.
@@ -3328,7 +3308,7 @@ void MicrosoftVTableContext::computeVTablePaths(bool ForVBTables,
if (const CXXRecordDecl *VB = P->getVBaseWithVPtr())
P->FullOffsetInMDC += Layout.getVBaseClassOffset(VB);
- Paths.push_back(P);
+ Paths.push_back(std::move(P));
}
if (B.isVirtual())
@@ -3347,10 +3327,10 @@ void MicrosoftVTableContext::computeVTablePaths(bool ForVBTables,
Changed = rebucketPaths(Paths);
}
-static bool extendPath(VPtrInfo *P) {
- if (P->NextBaseToMangle) {
- P->MangledPath.push_back(P->NextBaseToMangle);
- P->NextBaseToMangle = nullptr;// Prevent the path from being extended twice.
+static bool extendPath(VPtrInfo &P) {
+ if (P.NextBaseToMangle) {
+ P.MangledPath.push_back(P.NextBaseToMangle);
+ P.NextBaseToMangle = nullptr;// Prevent the path from being extended twice.
return true;
}
return false;
@@ -3363,10 +3343,13 @@ static bool rebucketPaths(VPtrInfoVector &Paths) {
// sorted vector to implement a multiset to form the buckets. Note that the
// ordering is based on pointers, but it doesn't change our output order. The
// current algorithm is designed to match MSVC 2012's names.
- VPtrInfoVector PathsSorted(Paths);
+ llvm::SmallVector<std::reference_wrapper<VPtrInfo>, 2> PathsSorted;
+ PathsSorted.reserve(Paths.size());
+ for (auto& P : Paths)
+ PathsSorted.push_back(*P);
std::sort(PathsSorted.begin(), PathsSorted.end(),
- [](const VPtrInfo *LHS, const VPtrInfo *RHS) {
- return LHS->MangledPath < RHS->MangledPath;
+ [](const VPtrInfo &LHS, const VPtrInfo &RHS) {
+ return LHS.MangledPath < RHS.MangledPath;
});
bool Changed = false;
for (size_t I = 0, E = PathsSorted.size(); I != E;) {
@@ -3374,8 +3357,9 @@ static bool rebucketPaths(VPtrInfoVector &Paths) {
size_t BucketStart = I;
do {
++I;
- } while (I != E && PathsSorted[BucketStart]->MangledPath ==
- PathsSorted[I]->MangledPath);
+ } while (I != E &&
+ PathsSorted[BucketStart].get().MangledPath ==
+ PathsSorted[I].get().MangledPath);
// If this bucket has multiple paths, extend them all.
if (I - BucketStart > 1) {
@@ -3387,13 +3371,7 @@ static bool rebucketPaths(VPtrInfoVector &Paths) {
return Changed;
}
-MicrosoftVTableContext::~MicrosoftVTableContext() {
- for (auto &P : VFPtrLocations)
- llvm::DeleteContainerPointers(*P.second);
- llvm::DeleteContainerSeconds(VFPtrLocations);
- llvm::DeleteContainerSeconds(VFTableLayouts);
- llvm::DeleteContainerSeconds(VBaseInfo);
-}
+MicrosoftVTableContext::~MicrosoftVTableContext() {}
namespace {
typedef llvm::SetVector<BaseSubobject, std::vector<BaseSubobject>,
@@ -3401,14 +3379,14 @@ typedef llvm::SetVector<BaseSubobject, std::vector<BaseSubobject>,
}
// This recursive function finds all paths from a subobject centered at
-// (RD, Offset) to the subobject located at BaseWithVPtr.
+// (RD, Offset) to the subobject located at IntroducingObject.
static void findPathsToSubobject(ASTContext &Context,
const ASTRecordLayout &MostDerivedLayout,
const CXXRecordDecl *RD, CharUnits Offset,
- BaseSubobject BaseWithVPtr,
+ BaseSubobject IntroducingObject,
FullPathTy &FullPath,
std::list<FullPathTy> &Paths) {
- if (BaseSubobject(RD, Offset) == BaseWithVPtr) {
+ if (BaseSubobject(RD, Offset) == IntroducingObject) {
Paths.push_back(FullPath);
return;
}
@@ -3422,7 +3400,7 @@ static void findPathsToSubobject(ASTContext &Context,
: Offset + Layout.getBaseClassOffset(Base);
FullPath.insert(BaseSubobject(Base, NewOffset));
findPathsToSubobject(Context, MostDerivedLayout, Base, NewOffset,
- BaseWithVPtr, FullPath, Paths);
+ IntroducingObject, FullPath, Paths);
FullPath.pop_back();
}
}
@@ -3477,7 +3455,8 @@ static CharUnits getOffsetOfFullPath(ASTContext &Context,
// two paths introduce overrides which the other path doesn't contain, issue a
// diagnostic.
static const FullPathTy *selectBestPath(ASTContext &Context,
- const CXXRecordDecl *RD, VPtrInfo *Info,
+ const CXXRecordDecl *RD,
+ const VPtrInfo &Info,
std::list<FullPathTy> &FullPaths) {
// Handle some easy cases first.
if (FullPaths.empty())
@@ -3497,7 +3476,7 @@ static const FullPathTy *selectBestPath(ASTContext &Context,
CharUnits BaseOffset =
getOffsetOfFullPath(Context, TopLevelRD, SpecificPath);
FinalOverriders Overriders(TopLevelRD, CharUnits::Zero(), TopLevelRD);
- for (const CXXMethodDecl *MD : Info->BaseWithVPtr->methods()) {
+ for (const CXXMethodDecl *MD : Info.IntroducingObject->methods()) {
if (!MD->isVirtual())
continue;
FinalOverriders::OverriderInfo OI =
@@ -3552,18 +3531,18 @@ static void computeFullPathsForVFTables(ASTContext &Context,
const ASTRecordLayout &MostDerivedLayout = Context.getASTRecordLayout(RD);
FullPathTy FullPath;
std::list<FullPathTy> FullPaths;
- for (VPtrInfo *Info : Paths) {
+ for (const std::unique_ptr<VPtrInfo>& Info : Paths) {
findPathsToSubobject(
Context, MostDerivedLayout, RD, CharUnits::Zero(),
- BaseSubobject(Info->BaseWithVPtr, Info->FullOffsetInMDC), FullPath,
+ BaseSubobject(Info->IntroducingObject, Info->FullOffsetInMDC), FullPath,
FullPaths);
FullPath.clear();
removeRedundantPaths(FullPaths);
- Info->PathToBaseWithVPtr.clear();
+ Info->PathToIntroducingObject.clear();
if (const FullPathTy *BestPath =
- selectBestPath(Context, RD, Info, FullPaths))
+ selectBestPath(Context, RD, *Info, FullPaths))
for (const BaseSubobject &BSO : *BestPath)
- Info->PathToBaseWithVPtr.push_back(BSO.getBase());
+ Info->PathToIntroducingObject.push_back(BSO.getBase());
FullPaths.clear();
}
}
@@ -3578,22 +3557,24 @@ void MicrosoftVTableContext::computeVTableRelatedInformation(
const VTableLayout::AddressPointsMapTy EmptyAddressPointsMap;
- VPtrInfoVector *VFPtrs = new VPtrInfoVector();
- computeVTablePaths(/*ForVBTables=*/false, RD, *VFPtrs);
- computeFullPathsForVFTables(Context, RD, *VFPtrs);
- VFPtrLocations[RD] = VFPtrs;
+ {
+ VPtrInfoVector VFPtrs;
+ computeVTablePaths(/*ForVBTables=*/false, RD, VFPtrs);
+ computeFullPathsForVFTables(Context, RD, VFPtrs);
+ VFPtrLocations[RD] = std::move(VFPtrs);
+ }
MethodVFTableLocationsTy NewMethodLocations;
- for (const VPtrInfo *VFPtr : *VFPtrs) {
- VFTableBuilder Builder(*this, RD, VFPtr);
+ for (const std::unique_ptr<VPtrInfo> &VFPtr : VFPtrLocations[RD]) {
+ VFTableBuilder Builder(*this, RD, *VFPtr);
VFTableIdTy id(RD, VFPtr->FullOffsetInMDC);
assert(VFTableLayouts.count(id) == 0);
SmallVector<VTableLayout::VTableThunkTy, 1> VTableThunks(
Builder.vtable_thunks_begin(), Builder.vtable_thunks_end());
- VFTableLayouts[id] = new VTableLayout(
- Builder.getNumVTableComponents(), Builder.vtable_component_begin(),
- VTableThunks.size(), VTableThunks.data(), EmptyAddressPointsMap, true);
+ VFTableLayouts[id] = llvm::make_unique<VTableLayout>(
+ ArrayRef<size_t>{0}, Builder.vtable_components(), VTableThunks,
+ EmptyAddressPointsMap);
Thunks.insert(Builder.thunks_begin(), Builder.thunks_end());
for (const auto &Loc : Builder.vtable_locations()) {
@@ -3670,17 +3651,18 @@ void MicrosoftVTableContext::dumpMethodLocations(
Out.flush();
}
-const VirtualBaseInfo *MicrosoftVTableContext::computeVBTableRelatedInformation(
+const VirtualBaseInfo &MicrosoftVTableContext::computeVBTableRelatedInformation(
const CXXRecordDecl *RD) {
VirtualBaseInfo *VBI;
{
// Get or create a VBI for RD. Don't hold a reference to the DenseMap cell,
// as it may be modified and rehashed under us.
- VirtualBaseInfo *&Entry = VBaseInfo[RD];
+ std::unique_ptr<VirtualBaseInfo> &Entry = VBaseInfo[RD];
if (Entry)
- return Entry;
- Entry = VBI = new VirtualBaseInfo();
+ return *Entry;
+ Entry = llvm::make_unique<VirtualBaseInfo>();
+ VBI = Entry.get();
}
computeVTablePaths(/*ForVBTables=*/true, RD, VBI->VBPtrPaths);
@@ -3690,10 +3672,10 @@ const VirtualBaseInfo *MicrosoftVTableContext::computeVBTableRelatedInformation(
if (const CXXRecordDecl *VBPtrBase = Layout.getBaseSharingVBPtr()) {
// If the Derived class shares the vbptr with a non-virtual base, the shared
// virtual bases come first so that the layout is the same.
- const VirtualBaseInfo *BaseInfo =
+ const VirtualBaseInfo &BaseInfo =
computeVBTableRelatedInformation(VBPtrBase);
- VBI->VBTableIndices.insert(BaseInfo->VBTableIndices.begin(),
- BaseInfo->VBTableIndices.end());
+ VBI->VBTableIndices.insert(BaseInfo.VBTableIndices.begin(),
+ BaseInfo.VBTableIndices.end());
}
// New vbases are added to the end of the vbtable.
@@ -3705,19 +3687,19 @@ const VirtualBaseInfo *MicrosoftVTableContext::computeVBTableRelatedInformation(
VBI->VBTableIndices[CurVBase] = VBTableIndex++;
}
- return VBI;
+ return *VBI;
}
unsigned MicrosoftVTableContext::getVBTableIndex(const CXXRecordDecl *Derived,
const CXXRecordDecl *VBase) {
- const VirtualBaseInfo *VBInfo = computeVBTableRelatedInformation(Derived);
- assert(VBInfo->VBTableIndices.count(VBase));
- return VBInfo->VBTableIndices.find(VBase)->second;
+ const VirtualBaseInfo &VBInfo = computeVBTableRelatedInformation(Derived);
+ assert(VBInfo.VBTableIndices.count(VBase));
+ return VBInfo.VBTableIndices.find(VBase)->second;
}
const VPtrInfoVector &
MicrosoftVTableContext::enumerateVBTables(const CXXRecordDecl *RD) {
- return computeVBTableRelatedInformation(RD)->VBPtrPaths;
+ return computeVBTableRelatedInformation(RD).VBPtrPaths;
}
const VPtrInfoVector &
@@ -3725,7 +3707,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 &
diff --git a/lib/ASTMatchers/ASTMatchFinder.cpp b/lib/ASTMatchers/ASTMatchFinder.cpp
index 19e5743ea1cb..49b15ee68500 100644
--- a/lib/ASTMatchers/ASTMatchFinder.cpp
+++ b/lib/ASTMatchers/ASTMatchFinder.cpp
@@ -126,6 +126,8 @@ public:
traverse(*Q);
else if (const TypeLoc *T = DynNode.get<TypeLoc>())
traverse(*T);
+ else if (const auto *C = DynNode.get<CXXCtorInitializer>())
+ traverse(*C);
// FIXME: Add other base types after adding tests.
// It's OK to always overwrite the bound nodes, as if there was
@@ -194,6 +196,12 @@ public:
return false;
return traverse(NNS);
}
+ bool TraverseConstructorInitializer(CXXCtorInitializer *CtorInit) {
+ if (!CtorInit)
+ return true;
+ ScopedIncrement ScopedDepth(&CurrentDepth);
+ return traverse(*CtorInit);
+ }
bool shouldVisitTemplateInstantiations() const { return true; }
bool shouldVisitImplicitCode() const { return true; }
@@ -235,6 +243,10 @@ private:
bool baseTraverse(NestedNameSpecifierLoc NNS) {
return VisitorBase::TraverseNestedNameSpecifierLoc(NNS);
}
+ bool baseTraverse(const CXXCtorInitializer &CtorInit) {
+ return VisitorBase::TraverseConstructorInitializer(
+ const_cast<CXXCtorInitializer *>(&CtorInit));
+ }
// Sets 'Matched' to true if 'Matcher' matches 'Node' and:
// 0 < CurrentDepth <= MaxDepth.
@@ -371,6 +383,7 @@ public:
bool TraverseTypeLoc(TypeLoc TypeNode);
bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS);
bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);
+ bool TraverseConstructorInitializer(CXXCtorInitializer *CtorInit);
// Matches children or descendants of 'Node' with 'BaseMatcher'.
bool memoizedMatchesRecursively(const ast_type_traits::DynTypedNode &Node,
@@ -472,6 +485,8 @@ public:
match(*N);
} else if (auto *N = Node.get<TypeLoc>()) {
match(*N);
+ } else if (auto *N = Node.get<CXXCtorInitializer>()) {
+ match(*N);
}
}
@@ -593,6 +608,9 @@ private:
void matchDispatch(const NestedNameSpecifierLoc *Node) {
matchWithoutFilter(*Node, Matchers->NestedNameSpecifierLoc);
}
+ void matchDispatch(const CXXCtorInitializer *Node) {
+ matchWithoutFilter(*Node, Matchers->CtorInit);
+ }
void matchDispatch(const void *) { /* Do nothing. */ }
/// @}
@@ -864,6 +882,17 @@ bool MatchASTVisitor::TraverseNestedNameSpecifierLoc(
RecursiveASTVisitor<MatchASTVisitor>::TraverseNestedNameSpecifierLoc(NNS);
}
+bool MatchASTVisitor::TraverseConstructorInitializer(
+ CXXCtorInitializer *CtorInit) {
+ if (!CtorInit)
+ return true;
+
+ match(*CtorInit);
+
+ return RecursiveASTVisitor<MatchASTVisitor>::TraverseConstructorInitializer(
+ CtorInit);
+}
+
class MatchASTConsumer : public ASTConsumer {
public:
MatchASTConsumer(MatchFinder *Finder,
@@ -934,6 +963,12 @@ void MatchFinder::addMatcher(const TypeLocMatcher &NodeMatch,
Matchers.AllCallbacks.insert(Action);
}
+void MatchFinder::addMatcher(const CXXCtorInitializerMatcher &NodeMatch,
+ MatchCallback *Action) {
+ Matchers.CtorInit.emplace_back(NodeMatch, Action);
+ Matchers.AllCallbacks.insert(Action);
+}
+
bool MatchFinder::addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch,
MatchCallback *Action) {
if (NodeMatch.canConvertTo<Decl>()) {
@@ -954,6 +989,9 @@ bool MatchFinder::addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch,
} else if (NodeMatch.canConvertTo<TypeLoc>()) {
addMatcher(NodeMatch.convertTo<TypeLoc>(), Action);
return true;
+ } else if (NodeMatch.canConvertTo<CXXCtorInitializer>()) {
+ addMatcher(NodeMatch.convertTo<CXXCtorInitializer>(), Action);
+ return true;
}
return false;
}
diff --git a/lib/ASTMatchers/ASTMatchersInternal.cpp b/lib/ASTMatchers/ASTMatchersInternal.cpp
index 107052ef1ded..f0bfbf9e32d8 100644
--- a/lib/ASTMatchers/ASTMatchersInternal.cpp
+++ b/lib/ASTMatchers/ASTMatchersInternal.cpp
@@ -72,10 +72,10 @@ private:
};
class IdDynMatcher : public DynMatcherInterface {
- public:
+public:
IdDynMatcher(StringRef ID,
- const IntrusiveRefCntPtr<DynMatcherInterface> &InnerMatcher)
- : ID(ID), InnerMatcher(InnerMatcher) {}
+ IntrusiveRefCntPtr<DynMatcherInterface> InnerMatcher)
+ : ID(ID), InnerMatcher(std::move(InnerMatcher)) {}
bool dynMatches(const ast_type_traits::DynTypedNode &DynNode,
ASTMatchFinder *Finder,
@@ -85,7 +85,7 @@ class IdDynMatcher : public DynMatcherInterface {
return Result;
}
- private:
+private:
const std::string ID;
const IntrusiveRefCntPtr<DynMatcherInterface> InnerMatcher;
};
@@ -210,8 +210,9 @@ bool DynTypedMatcher::matchesNoKindCheck(
llvm::Optional<DynTypedMatcher> DynTypedMatcher::tryBind(StringRef ID) const {
if (!AllowBind) return llvm::None;
auto Result = *this;
- Result.Implementation = new IdDynMatcher(ID, Result.Implementation);
- return Result;
+ Result.Implementation =
+ new IdDynMatcher(ID, std::move(Result.Implementation));
+ return std::move(Result);
}
bool DynTypedMatcher::canConvertTo(ast_type_traits::ASTNodeKind To) const {
diff --git a/lib/ASTMatchers/Dynamic/Marshallers.h b/lib/ASTMatchers/Dynamic/Marshallers.h
index 7b1a30702633..fb6b349a811c 100644
--- a/lib/ASTMatchers/Dynamic/Marshallers.h
+++ b/lib/ASTMatchers/Dynamic/Marshallers.h
@@ -480,8 +480,8 @@ template <template <typename ToArg, typename FromArg> class ArgumentAdapterT,
typename FromTypes, typename ToTypes>
class AdaptativeOverloadCollector {
public:
- AdaptativeOverloadCollector(StringRef Name,
- std::vector<MatcherDescriptor *> &Out)
+ AdaptativeOverloadCollector(
+ StringRef Name, std::vector<std::unique_ptr<MatcherDescriptor>> &Out)
: Name(Name), Out(Out) {
collect(FromTypes());
}
@@ -499,7 +499,7 @@ private:
inline void collect(FromTypeList);
StringRef Name;
- std::vector<MatcherDescriptor *> &Out;
+ std::vector<std::unique_ptr<MatcherDescriptor>> &Out;
};
/// \brief MatcherDescriptor that wraps multiple "overloads" of the same
@@ -509,8 +509,10 @@ private:
/// more than one overloads match the arguments.
class OverloadedMatcherDescriptor : public MatcherDescriptor {
public:
- OverloadedMatcherDescriptor(ArrayRef<MatcherDescriptor *> Callbacks)
- : Overloads(Callbacks.begin(), Callbacks.end()) {}
+ OverloadedMatcherDescriptor(
+ MutableArrayRef<std::unique_ptr<MatcherDescriptor>> Callbacks)
+ : Overloads(std::make_move_iterator(Callbacks.begin()),
+ std::make_move_iterator(Callbacks.end())) {}
~OverloadedMatcherDescriptor() override {}
@@ -641,36 +643,37 @@ private:
/// \brief 0-arg overload
template <typename ReturnType>
-MatcherDescriptor *makeMatcherAutoMarshall(ReturnType (*Func)(),
- StringRef MatcherName) {
+std::unique_ptr<MatcherDescriptor>
+makeMatcherAutoMarshall(ReturnType (*Func)(), StringRef MatcherName) {
std::vector<ast_type_traits::ASTNodeKind> RetTypes;
BuildReturnTypeVector<ReturnType>::build(RetTypes);
- return new FixedArgCountMatcherDescriptor(
+ return llvm::make_unique<FixedArgCountMatcherDescriptor>(
matcherMarshall0<ReturnType>, reinterpret_cast<void (*)()>(Func),
MatcherName, RetTypes, None);
}
/// \brief 1-arg overload
template <typename ReturnType, typename ArgType1>
-MatcherDescriptor *makeMatcherAutoMarshall(ReturnType (*Func)(ArgType1),
- StringRef MatcherName) {
+std::unique_ptr<MatcherDescriptor>
+makeMatcherAutoMarshall(ReturnType (*Func)(ArgType1), StringRef MatcherName) {
std::vector<ast_type_traits::ASTNodeKind> RetTypes;
BuildReturnTypeVector<ReturnType>::build(RetTypes);
ArgKind AK = ArgTypeTraits<ArgType1>::getKind();
- return new FixedArgCountMatcherDescriptor(
+ return llvm::make_unique<FixedArgCountMatcherDescriptor>(
matcherMarshall1<ReturnType, ArgType1>,
reinterpret_cast<void (*)()>(Func), MatcherName, RetTypes, AK);
}
/// \brief 2-arg overload
template <typename ReturnType, typename ArgType1, typename ArgType2>
-MatcherDescriptor *makeMatcherAutoMarshall(ReturnType (*Func)(ArgType1, ArgType2),
- StringRef MatcherName) {
+std::unique_ptr<MatcherDescriptor>
+makeMatcherAutoMarshall(ReturnType (*Func)(ArgType1, ArgType2),
+ StringRef MatcherName) {
std::vector<ast_type_traits::ASTNodeKind> RetTypes;
BuildReturnTypeVector<ReturnType>::build(RetTypes);
ArgKind AKs[] = { ArgTypeTraits<ArgType1>::getKind(),
ArgTypeTraits<ArgType2>::getKind() };
- return new FixedArgCountMatcherDescriptor(
+ return llvm::make_unique<FixedArgCountMatcherDescriptor>(
matcherMarshall2<ReturnType, ArgType1, ArgType2>,
reinterpret_cast<void (*)()>(Func), MatcherName, RetTypes, AKs);
}
@@ -678,10 +681,10 @@ MatcherDescriptor *makeMatcherAutoMarshall(ReturnType (*Func)(ArgType1, ArgType2
/// \brief Variadic overload.
template <typename ResultT, typename ArgT,
ResultT (*Func)(ArrayRef<const ArgT *>)>
-MatcherDescriptor *makeMatcherAutoMarshall(
+std::unique_ptr<MatcherDescriptor> makeMatcherAutoMarshall(
ast_matchers::internal::VariadicFunction<ResultT, ArgT, Func> VarFunc,
StringRef MatcherName) {
- return new VariadicFuncMatcherDescriptor(VarFunc, MatcherName);
+ return llvm::make_unique<VariadicFuncMatcherDescriptor>(VarFunc, MatcherName);
}
/// \brief Overload for VariadicDynCastAllOfMatchers.
@@ -689,24 +692,24 @@ MatcherDescriptor *makeMatcherAutoMarshall(
/// Not strictly necessary, but DynCastAllOfMatcherDescriptor gives us better
/// completion results for that type of matcher.
template <typename BaseT, typename DerivedT>
-MatcherDescriptor *
-makeMatcherAutoMarshall(ast_matchers::internal::VariadicDynCastAllOfMatcher<
- BaseT, DerivedT> VarFunc,
- StringRef MatcherName) {
- return new DynCastAllOfMatcherDescriptor(VarFunc, MatcherName);
+std::unique_ptr<MatcherDescriptor> makeMatcherAutoMarshall(
+ ast_matchers::internal::VariadicDynCastAllOfMatcher<BaseT, DerivedT>
+ VarFunc,
+ StringRef MatcherName) {
+ return llvm::make_unique<DynCastAllOfMatcherDescriptor>(VarFunc, MatcherName);
}
/// \brief Argument adaptative overload.
template <template <typename ToArg, typename FromArg> class ArgumentAdapterT,
typename FromTypes, typename ToTypes>
-MatcherDescriptor *
-makeMatcherAutoMarshall(ast_matchers::internal::ArgumentAdaptingMatcherFunc<
- ArgumentAdapterT, FromTypes, ToTypes>,
- StringRef MatcherName) {
- std::vector<MatcherDescriptor *> Overloads;
+std::unique_ptr<MatcherDescriptor> makeMatcherAutoMarshall(
+ ast_matchers::internal::ArgumentAdaptingMatcherFunc<ArgumentAdapterT,
+ FromTypes, ToTypes>,
+ StringRef MatcherName) {
+ std::vector<std::unique_ptr<MatcherDescriptor>> Overloads;
AdaptativeOverloadCollector<ArgumentAdapterT, FromTypes, ToTypes>(MatcherName,
Overloads);
- return new OverloadedMatcherDescriptor(Overloads);
+ return llvm::make_unique<OverloadedMatcherDescriptor>(Overloads);
}
template <template <typename ToArg, typename FromArg> class ArgumentAdapterT,
@@ -721,12 +724,12 @@ inline void AdaptativeOverloadCollector<ArgumentAdapterT, FromTypes,
/// \brief Variadic operator overload.
template <unsigned MinCount, unsigned MaxCount>
-MatcherDescriptor *
-makeMatcherAutoMarshall(ast_matchers::internal::VariadicOperatorMatcherFunc<
- MinCount, MaxCount> Func,
- StringRef MatcherName) {
- return new VariadicOperatorMatcherDescriptor(MinCount, MaxCount, Func.Op,
- MatcherName);
+std::unique_ptr<MatcherDescriptor> makeMatcherAutoMarshall(
+ ast_matchers::internal::VariadicOperatorMatcherFunc<MinCount, MaxCount>
+ Func,
+ StringRef MatcherName) {
+ return llvm::make_unique<VariadicOperatorMatcherDescriptor>(
+ MinCount, MaxCount, Func.Op, MatcherName);
}
} // namespace internal
diff --git a/lib/ASTMatchers/Dynamic/Parser.cpp b/lib/ASTMatchers/Dynamic/Parser.cpp
index cf9dab6dc7db..ce8d0a9a0206 100644
--- a/lib/ASTMatchers/Dynamic/Parser.cpp
+++ b/lib/ASTMatchers/Dynamic/Parser.cpp
@@ -16,7 +16,6 @@
#include "clang/ASTMatchers/Dynamic/Registry.h"
#include "clang/Basic/CharInfo.h"
#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/Twine.h"
#include "llvm/Support/ManagedStatic.h"
#include <string>
#include <vector>
diff --git a/lib/ASTMatchers/Dynamic/Registry.cpp b/lib/ASTMatchers/Dynamic/Registry.cpp
index a8d4b88d8580..d1cab80c1a53 100644
--- a/lib/ASTMatchers/Dynamic/Registry.cpp
+++ b/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -31,7 +31,7 @@ namespace {
using internal::MatcherDescriptor;
-typedef llvm::StringMap<const MatcherDescriptor *> ConstructorMap;
+typedef llvm::StringMap<std::unique_ptr<const MatcherDescriptor>> ConstructorMap;
class RegistryMaps {
public:
RegistryMaps();
@@ -40,14 +40,16 @@ public:
const ConstructorMap &constructors() const { return Constructors; }
private:
- void registerMatcher(StringRef MatcherName, MatcherDescriptor *Callback);
+ void registerMatcher(StringRef MatcherName,
+ std::unique_ptr<MatcherDescriptor> Callback);
+
ConstructorMap Constructors;
};
-void RegistryMaps::registerMatcher(StringRef MatcherName,
- MatcherDescriptor *Callback) {
+void RegistryMaps::registerMatcher(
+ StringRef MatcherName, std::unique_ptr<MatcherDescriptor> Callback) {
assert(Constructors.find(MatcherName) == Constructors.end());
- Constructors[MatcherName] = Callback;
+ Constructors[MatcherName] = std::move(Callback);
}
#define REGISTER_MATCHER(name) \
@@ -55,19 +57,19 @@ void RegistryMaps::registerMatcher(StringRef MatcherName,
::clang::ast_matchers::name, #name));
#define SPECIFIC_MATCHER_OVERLOAD(name, Id) \
- static_cast< ::clang::ast_matchers::name##_Type##Id>( \
+ static_cast<::clang::ast_matchers::name##_Type##Id>( \
::clang::ast_matchers::name)
#define REGISTER_OVERLOADED_2(name) \
do { \
- MatcherDescriptor *Callbacks[] = { \
- internal::makeMatcherAutoMarshall(SPECIFIC_MATCHER_OVERLOAD(name, 0), \
- #name), \
- internal::makeMatcherAutoMarshall(SPECIFIC_MATCHER_OVERLOAD(name, 1), \
- #name) \
- }; \
- registerMatcher(#name, \
- new internal::OverloadedMatcherDescriptor(Callbacks)); \
+ std::unique_ptr<MatcherDescriptor> Callbacks[] = { \
+ internal::makeMatcherAutoMarshall(SPECIFIC_MATCHER_OVERLOAD(name, 0), \
+ #name), \
+ internal::makeMatcherAutoMarshall(SPECIFIC_MATCHER_OVERLOAD(name, 1), \
+ #name)}; \
+ registerMatcher( \
+ #name, \
+ llvm::make_unique<internal::OverloadedMatcherDescriptor>(Callbacks)); \
} while (0)
/// \brief Generate a registry map with all the known matchers.
@@ -198,6 +200,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(hasAncestor);
REGISTER_MATCHER(hasAnyArgument);
REGISTER_MATCHER(hasAnyConstructorInitializer);
+ REGISTER_MATCHER(hasAnyDeclaration);
REGISTER_MATCHER(hasAnyName);
REGISTER_MATCHER(hasAnyParameter);
REGISTER_MATCHER(hasAnySubstatement);
@@ -225,9 +228,11 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(hasEitherOperand);
REGISTER_MATCHER(hasElementType);
REGISTER_MATCHER(hasElse);
+ REGISTER_MATCHER(hasExternalFormalLinkage);
REGISTER_MATCHER(hasFalseExpression);
REGISTER_MATCHER(hasGlobalStorage);
REGISTER_MATCHER(hasImplicitDestinationType);
+ REGISTER_MATCHER(hasInClassInitializer);
REGISTER_MATCHER(hasIncrement);
REGISTER_MATCHER(hasIndex);
REGISTER_MATCHER(hasInitializer);
@@ -248,6 +253,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(hasQualifier);
REGISTER_MATCHER(hasRangeInit);
REGISTER_MATCHER(hasReceiverType);
+ REGISTER_MATCHER(hasReplacementType);
REGISTER_MATCHER(hasReturnValue);
REGISTER_MATCHER(hasRHS);
REGISTER_MATCHER(hasSelector);
@@ -265,6 +271,8 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(hasTypeLoc);
REGISTER_MATCHER(hasUnaryOperand);
REGISTER_MATCHER(hasUnarySelector);
+ REGISTER_MATCHER(hasUnderlyingDecl);
+ REGISTER_MATCHER(hasUnqualifiedDesugaredType);
REGISTER_MATCHER(hasValueType);
REGISTER_MATCHER(ifStmt);
REGISTER_MATCHER(ignoringImplicit);
@@ -391,8 +399,10 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(switchCase);
REGISTER_MATCHER(switchStmt);
REGISTER_MATCHER(templateArgument);
+ REGISTER_MATCHER(templateName);
REGISTER_MATCHER(templateArgumentCountIs);
REGISTER_MATCHER(templateSpecializationType);
+ REGISTER_MATCHER(templateTypeParmDecl);
REGISTER_MATCHER(templateTypeParmType);
REGISTER_MATCHER(throughUsingDecl);
REGISTER_MATCHER(to);
@@ -421,9 +431,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(withInitializer);
}
-RegistryMaps::~RegistryMaps() {
- llvm::DeleteContainerSeconds(Constructors);
-}
+RegistryMaps::~RegistryMaps() {}
static llvm::ManagedStatic<RegistryMaps> RegistryData;
@@ -431,11 +439,10 @@ static llvm::ManagedStatic<RegistryMaps> RegistryData;
// static
llvm::Optional<MatcherCtor> Registry::lookupMatcherCtor(StringRef MatcherName) {
- ConstructorMap::const_iterator it =
- RegistryData->constructors().find(MatcherName);
+ auto it = RegistryData->constructors().find(MatcherName);
return it == RegistryData->constructors().end()
? llvm::Optional<MatcherCtor>()
- : it->second;
+ : it->second.get();
}
namespace {
@@ -494,12 +501,12 @@ Registry::getMatcherCompletions(ArrayRef<ArgKind> AcceptedTypes) {
// Search the registry for acceptable matchers.
for (const auto &M : RegistryData->constructors()) {
- const auto *Matcher = M.getValue();
+ const MatcherDescriptor& Matcher = *M.getValue();
StringRef Name = M.getKey();
std::set<ASTNodeKind> RetKinds;
- unsigned NumArgs = Matcher->isVariadic() ? 1 : Matcher->getNumArgs();
- bool IsPolymorphic = Matcher->isPolymorphic();
+ unsigned NumArgs = Matcher.isVariadic() ? 1 : Matcher.getNumArgs();
+ bool IsPolymorphic = Matcher.isPolymorphic();
std::vector<std::vector<ArgKind>> ArgsKinds(NumArgs);
unsigned MaxSpecificity = 0;
for (const ArgKind& Kind : AcceptedTypes) {
@@ -507,13 +514,13 @@ Registry::getMatcherCompletions(ArrayRef<ArgKind> AcceptedTypes) {
continue;
unsigned Specificity;
ASTNodeKind LeastDerivedKind;
- if (Matcher->isConvertibleTo(Kind.getMatcherKind(), &Specificity,
- &LeastDerivedKind)) {
+ if (Matcher.isConvertibleTo(Kind.getMatcherKind(), &Specificity,
+ &LeastDerivedKind)) {
if (MaxSpecificity < Specificity)
MaxSpecificity = Specificity;
RetKinds.insert(LeastDerivedKind);
for (unsigned Arg = 0; Arg != NumArgs; ++Arg)
- Matcher->getArgKinds(Kind.getMatcherKind(), Arg, ArgsKinds[Arg]);
+ Matcher.getArgKinds(Kind.getMatcherKind(), Arg, ArgsKinds[Arg]);
if (IsPolymorphic)
break;
}
@@ -549,7 +556,7 @@ Registry::getMatcherCompletions(ArrayRef<ArgKind> AcceptedTypes) {
}
}
}
- if (Matcher->isVariadic())
+ if (Matcher.isVariadic())
OS << "...";
OS << ")";
diff --git a/lib/Analysis/AnalysisDeclContext.cpp b/lib/Analysis/AnalysisDeclContext.cpp
index 6bbe8f86d48e..6b58916162f6 100644
--- a/lib/Analysis/AnalysisDeclContext.cpp
+++ b/lib/Analysis/AnalysisDeclContext.cpp
@@ -81,9 +81,7 @@ AnalysisDeclContextManager::AnalysisDeclContextManager(bool useUnoptimizedCFG,
cfgBuildOptions.AddCXXNewAllocator = addCXXNewAllocator;
}
-void AnalysisDeclContextManager::clear() {
- llvm::DeleteContainerSeconds(Contexts);
-}
+void AnalysisDeclContextManager::clear() { Contexts.clear(); }
static BodyFarm &getBodyFarm(ASTContext &C, CodeInjector *injector = nullptr) {
static BodyFarm *BF = new BodyFarm(C, injector);
@@ -307,10 +305,10 @@ AnalysisDeclContext *AnalysisDeclContextManager::getContext(const Decl *D) {
D = FD;
}
- AnalysisDeclContext *&AC = Contexts[D];
+ std::unique_ptr<AnalysisDeclContext> &AC = Contexts[D];
if (!AC)
- AC = new AnalysisDeclContext(this, D, cfgBuildOptions);
- return AC;
+ AC = llvm::make_unique<AnalysisDeclContext>(this, D, cfgBuildOptions);
+ return AC.get();
}
const StackFrameContext *
@@ -606,9 +604,7 @@ AnalysisDeclContext::~AnalysisDeclContext() {
}
}
-AnalysisDeclContextManager::~AnalysisDeclContextManager() {
- llvm::DeleteContainerSeconds(Contexts);
-}
+AnalysisDeclContextManager::~AnalysisDeclContextManager() {}
LocationContext::~LocationContext() {}
diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp
index a67f0910e15a..bf3cc05cdb6e 100644
--- a/lib/Analysis/CFG.cpp
+++ b/lib/Analysis/CFG.cpp
@@ -1164,7 +1164,8 @@ CFGBlock *CFGBuilder::addInitializer(CXXCtorInitializer *I) {
/// \brief 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) {
+ const Expr *Init,
+ bool *FoundMTE = nullptr) {
while (true) {
// Skip parentheses.
Init = Init->IgnoreParens();
@@ -1179,6 +1180,8 @@ static QualType getReferenceInitTemporaryType(ASTContext &Context,
if (const MaterializeTemporaryExpr *MTE
= dyn_cast<MaterializeTemporaryExpr>(Init)) {
Init = MTE->GetTemporaryExpr();
+ if (FoundMTE)
+ *FoundMTE = true;
continue;
}
@@ -1370,13 +1373,12 @@ LocalScope* CFGBuilder::addLocalScopeForVarDecl(VarDecl *VD,
const Expr *Init = VD->getInit();
if (!Init)
return Scope;
- if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(Init))
- Init = EWC->getSubExpr();
- if (!isa<MaterializeTemporaryExpr>(Init))
- return Scope;
// Lifetime-extending a temporary.
- QT = getReferenceInitTemporaryType(*Context, Init);
+ bool FoundMTE = false;
+ QT = getReferenceInitTemporaryType(*Context, Init, &FoundMTE);
+ if (!FoundMTE)
+ return Scope;
}
// Check for constant size array. Set type to array element type.
@@ -2050,8 +2052,7 @@ CFGBlock *CFGBuilder::VisitDeclStmt(DeclStmt *DS) {
E = DS->decl_rend();
I != E; ++I) {
// Get the alignment of the new DeclStmt, padding out to >=8 bytes.
- unsigned A = llvm::AlignOf<DeclStmt>::Alignment < 8
- ? 8 : llvm::AlignOf<DeclStmt>::Alignment;
+ unsigned A = alignof(DeclStmt) < 8 ? 8 : alignof(DeclStmt);
// Allocate the DeclStmt using the BumpPtrAllocator. It will get
// automatically freed with the CFG.
@@ -2983,20 +2984,19 @@ CFGBlock *CFGBuilder::VisitDoStmt(DoStmt *D) {
return nullptr;
}
- if (!KnownVal.isFalse()) {
- // Add an intermediate block between the BodyBlock and the
- // ExitConditionBlock to represent the "loop back" transition. Create an
- // empty block to represent the transition block for looping back to the
- // head of the loop.
- // FIXME: Can we do this more efficiently without adding another block?
- Block = nullptr;
- Succ = BodyBlock;
- CFGBlock *LoopBackBlock = createBlock();
- LoopBackBlock->setLoopTarget(D);
+ // Add an intermediate block between the BodyBlock and the
+ // ExitConditionBlock to represent the "loop back" transition. Create an
+ // empty block to represent the transition block for looping back to the
+ // head of the loop.
+ // FIXME: Can we do this more efficiently without adding another block?
+ Block = nullptr;
+ Succ = BodyBlock;
+ CFGBlock *LoopBackBlock = createBlock();
+ LoopBackBlock->setLoopTarget(D);
+ if (!KnownVal.isFalse())
// Add the loop body entry as a successor to the condition.
addSuccessor(ExitConditionBlock, LoopBackBlock);
- }
else
addSuccessor(ExitConditionBlock, nullptr);
}
@@ -3583,11 +3583,13 @@ CFGBlock *CFGBuilder::VisitCXXDeleteExpr(CXXDeleteExpr *DE,
autoCreateBlock();
appendStmt(Block, DE);
QualType DTy = DE->getDestroyedType();
- DTy = DTy.getNonReferenceType();
- CXXRecordDecl *RD = Context->getBaseElementType(DTy)->getAsCXXRecordDecl();
- if (RD) {
- if (RD->isCompleteDefinition() && !RD->hasTrivialDestructor())
- appendDeleteDtor(Block, RD, DE);
+ if (!DTy.isNull()) {
+ DTy = DTy.getNonReferenceType();
+ CXXRecordDecl *RD = Context->getBaseElementType(DTy)->getAsCXXRecordDecl();
+ if (RD) {
+ if (RD->isCompleteDefinition() && !RD->hasTrivialDestructor())
+ appendDeleteDtor(Block, RD, DE);
+ }
}
return VisitChildren(DE);
diff --git a/lib/Analysis/CMakeLists.txt b/lib/Analysis/CMakeLists.txt
index 1df093d85098..fdc9e6cee8e1 100644
--- a/lib/Analysis/CMakeLists.txt
+++ b/lib/Analysis/CMakeLists.txt
@@ -9,12 +9,14 @@ add_clang_library(clangAnalysis
CFGReachabilityAnalysis.cpp
CFGStmtMap.cpp
CallGraph.cpp
+ CloneDetection.cpp
CocoaConventions.cpp
Consumed.cpp
CodeInjector.cpp
Dominators.cpp
FormatString.cpp
LiveVariables.cpp
+ OSLog.cpp
ObjCNoReturn.cpp
PostOrderCFGView.cpp
PrintfFormatString.cpp
diff --git a/lib/Analysis/CallGraph.cpp b/lib/Analysis/CallGraph.cpp
index 9d522fe7c6c5..8c126b09d057 100644
--- a/lib/Analysis/CallGraph.cpp
+++ b/lib/Analysis/CallGraph.cpp
@@ -55,7 +55,7 @@ public:
void addCalledDecl(Decl *D) {
if (G->includeInGraph(D)) {
CallGraphNode *CalleeNode = G->getOrInsertNode(D);
- CallerNode->addCallee(CalleeNode, G);
+ CallerNode->addCallee(CalleeNode);
}
}
@@ -104,9 +104,7 @@ CallGraph::CallGraph() {
Root = getOrInsertNode(nullptr);
}
-CallGraph::~CallGraph() {
- llvm::DeleteContainerSeconds(FunctionMap);
-}
+CallGraph::~CallGraph() {}
bool CallGraph::includeInGraph(const Decl *D) {
assert(D);
@@ -142,22 +140,22 @@ void CallGraph::addNodeForDecl(Decl* D, bool IsGlobal) {
CallGraphNode *CallGraph::getNode(const Decl *F) const {
FunctionMapTy::const_iterator I = FunctionMap.find(F);
if (I == FunctionMap.end()) return nullptr;
- return I->second;
+ return I->second.get();
}
CallGraphNode *CallGraph::getOrInsertNode(Decl *F) {
if (F && !isa<ObjCMethodDecl>(F))
F = F->getCanonicalDecl();
- CallGraphNode *&Node = FunctionMap[F];
+ std::unique_ptr<CallGraphNode> &Node = FunctionMap[F];
if (Node)
- return Node;
+ return Node.get();
- Node = new CallGraphNode(F);
+ Node = llvm::make_unique<CallGraphNode>(F);
// Make Root node a parent of all functions to make sure all are reachable.
if (F)
- Root->addCallee(Node, this);
- return Node;
+ Root->addCallee(Node.get());
+ return Node.get();
}
void CallGraph::print(raw_ostream &OS) const {
diff --git a/lib/Analysis/CloneDetection.cpp b/lib/Analysis/CloneDetection.cpp
new file mode 100644
index 000000000000..e761738214c6
--- /dev/null
+++ b/lib/Analysis/CloneDetection.cpp
@@ -0,0 +1,894 @@
+//===--- CloneDetection.cpp - Finds code clones in an AST -------*- 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 classes for searching and anlyzing source code clones.
+///
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/CloneDetection.h"
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/Lex/Lexer.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/MD5.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+
+StmtSequence::StmtSequence(const CompoundStmt *Stmt, ASTContext &Context,
+ unsigned StartIndex, unsigned EndIndex)
+ : S(Stmt), Context(&Context), StartIndex(StartIndex), EndIndex(EndIndex) {
+ assert(Stmt && "Stmt must not be a nullptr");
+ assert(StartIndex < EndIndex && "Given array should not be empty");
+ assert(EndIndex <= Stmt->size() && "Given array too big for this Stmt");
+}
+
+StmtSequence::StmtSequence(const Stmt *Stmt, ASTContext &Context)
+ : S(Stmt), Context(&Context), StartIndex(0), EndIndex(0) {}
+
+StmtSequence::StmtSequence()
+ : S(nullptr), Context(nullptr), StartIndex(0), EndIndex(0) {}
+
+bool StmtSequence::contains(const StmtSequence &Other) const {
+ // If both sequences reside in different translation units, they can never
+ // contain each other.
+ if (Context != Other.Context)
+ return false;
+
+ const SourceManager &SM = Context->getSourceManager();
+
+ // Otherwise check if the start and end locations of the current sequence
+ // surround the other sequence.
+ bool StartIsInBounds =
+ SM.isBeforeInTranslationUnit(getStartLoc(), Other.getStartLoc()) ||
+ getStartLoc() == Other.getStartLoc();
+ if (!StartIsInBounds)
+ return false;
+
+ bool EndIsInBounds =
+ SM.isBeforeInTranslationUnit(Other.getEndLoc(), getEndLoc()) ||
+ Other.getEndLoc() == getEndLoc();
+ return EndIsInBounds;
+}
+
+StmtSequence::iterator StmtSequence::begin() const {
+ if (!holdsSequence()) {
+ return &S;
+ }
+ auto CS = cast<CompoundStmt>(S);
+ return CS->body_begin() + StartIndex;
+}
+
+StmtSequence::iterator StmtSequence::end() const {
+ if (!holdsSequence()) {
+ return reinterpret_cast<StmtSequence::iterator>(&S) + 1;
+ }
+ auto CS = cast<CompoundStmt>(S);
+ return CS->body_begin() + EndIndex;
+}
+
+SourceLocation StmtSequence::getStartLoc() const {
+ return front()->getLocStart();
+}
+
+SourceLocation StmtSequence::getEndLoc() const { return back()->getLocEnd(); }
+
+SourceRange StmtSequence::getSourceRange() const {
+ return SourceRange(getStartLoc(), getEndLoc());
+}
+
+namespace {
+
+/// \brief Analyzes the pattern of the referenced variables in a statement.
+class VariablePattern {
+
+ /// \brief Describes an occurence of a variable reference in a statement.
+ struct VariableOccurence {
+ /// The index of the associated VarDecl in the Variables vector.
+ size_t KindID;
+ /// The statement in the code where the variable was referenced.
+ const Stmt *Mention;
+
+ VariableOccurence(size_t KindID, const Stmt *Mention)
+ : KindID(KindID), Mention(Mention) {}
+ };
+
+ /// All occurences 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.
+ std::vector<const VarDecl *> Variables;
+
+ /// \brief Adds a new variable referenced to this pattern.
+ /// \param VarDecl The declaration of the variable that is referenced.
+ /// \param Mention The SourceRange where this variable is referenced.
+ void addVariableOccurence(const VarDecl *VarDecl, const Stmt *Mention) {
+ // 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
+ // 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.
+ Occurences.emplace_back(Variables.size(), Mention);
+ Variables.push_back(VarDecl);
+ }
+
+ /// \brief Adds each referenced variable from the given statement.
+ void addVariables(const Stmt *S) {
+ // Sometimes we get a nullptr (such as from IfStmts which often have nullptr
+ // children). We skip such statements as they don't reference any
+ // variables.
+ if (!S)
+ return;
+
+ // Check if S is a reference to a variable. If yes, add it to the pattern.
+ if (auto D = dyn_cast<DeclRefExpr>(S)) {
+ if (auto VD = dyn_cast<VarDecl>(D->getDecl()->getCanonicalDecl()))
+ addVariableOccurence(VD, D);
+ }
+
+ // Recursively check all children of the given statement.
+ for (const Stmt *Child : S->children()) {
+ addVariables(Child);
+ }
+ }
+
+public:
+ /// \brief Creates an VariablePattern object with information about the given
+ /// StmtSequence.
+ VariablePattern(const StmtSequence &Sequence) {
+ for (const Stmt *S : Sequence)
+ addVariables(S);
+ }
+
+ /// \brief Counts the differences between this pattern and the given one.
+ /// \param Other The given VariablePattern to compare with.
+ /// \param FirstMismatch Output parameter that will be filled with information
+ /// about the first difference between the two patterns. This parameter
+ /// can be a nullptr, in which case it will be ignored.
+ /// \return Returns the number of differences between the pattern this object
+ /// is following and the given VariablePattern.
+ ///
+ /// For example, the following statements all have the same pattern and this
+ /// function would return zero:
+ ///
+ /// if (a < b) return a; return b;
+ /// if (x < y) return x; return y;
+ /// if (u2 < u1) return u2; return u1;
+ ///
+ /// But the following statement has a different pattern (note the changed
+ /// variables in the return statements) and would have two differences when
+ /// compared with one of the statements above.
+ ///
+ /// if (a < b) return b; return a;
+ ///
+ /// This function should only be called if the related statements of the given
+ /// pattern and the statements of this objects are clones of each other.
+ unsigned countPatternDifferences(
+ const VariablePattern &Other,
+ CloneDetector::SuspiciousClonePair *FirstMismatch = nullptr) {
+ unsigned NumberOfDifferences = 0;
+
+ assert(Other.Occurences.size() == Occurences.size());
+ for (unsigned i = 0; i < Occurences.size(); ++i) {
+ auto ThisOccurence = Occurences[i];
+ auto OtherOccurence = Other.Occurences[i];
+ if (ThisOccurence.KindID == OtherOccurence.KindID)
+ continue;
+
+ ++NumberOfDifferences;
+
+ // If FirstMismatch is not a nullptr, we need to store information about
+ // the first difference between the two patterns.
+ if (FirstMismatch == nullptr)
+ continue;
+
+ // Only proceed if we just found the first difference as we only store
+ // information about the first difference.
+ if (NumberOfDifferences != 1)
+ continue;
+
+ const VarDecl *FirstSuggestion = nullptr;
+ // If there is a variable available in the list of referenced variables
+ // which wouldn't break the pattern if it is used in place of the
+ // current variable, we provide this variable as the suggested fix.
+ if (OtherOccurence.KindID < Variables.size())
+ FirstSuggestion = Variables[OtherOccurence.KindID];
+
+ // Store information about the first clone.
+ FirstMismatch->FirstCloneInfo =
+ CloneDetector::SuspiciousClonePair::SuspiciousCloneInfo(
+ Variables[ThisOccurence.KindID], ThisOccurence.Mention,
+ FirstSuggestion);
+
+ // Same as above but with the other clone. We do this for both clones as
+ // we don't know which clone is the one containing the unintended
+ // pattern error.
+ const VarDecl *SecondSuggestion = nullptr;
+ if (ThisOccurence.KindID < Other.Variables.size())
+ SecondSuggestion = Other.Variables[ThisOccurence.KindID];
+
+ // Store information about the second clone.
+ FirstMismatch->SecondCloneInfo =
+ CloneDetector::SuspiciousClonePair::SuspiciousCloneInfo(
+ Other.Variables[OtherOccurence.KindID], OtherOccurence.Mention,
+ SecondSuggestion);
+
+ // SuspiciousClonePair guarantees that the first clone always has a
+ // suggested variable associated with it. As we know that one of the two
+ // clones in the pair always has suggestion, we swap the two clones
+ // in case the first clone has no suggested variable which means that
+ // the second clone has a suggested variable and should be first.
+ if (!FirstMismatch->FirstCloneInfo.Suggestion)
+ std::swap(FirstMismatch->FirstCloneInfo,
+ FirstMismatch->SecondCloneInfo);
+
+ // This ensures that we always have at least one suggestion in a pair.
+ assert(FirstMismatch->FirstCloneInfo.Suggestion);
+ }
+
+ return NumberOfDifferences;
+ }
+};
+}
+
+/// \brief Prints the macro name that contains the given SourceLocation into
+/// the given raw_string_ostream.
+static void printMacroName(llvm::raw_string_ostream &MacroStack,
+ ASTContext &Context, SourceLocation Loc) {
+ MacroStack << Lexer::getImmediateMacroName(Loc, Context.getSourceManager(),
+ Context.getLangOpts());
+
+ // Add an empty space at the end as a padding to prevent
+ // that macro names concatenate to the names of other macros.
+ MacroStack << " ";
+}
+
+/// \brief Returns a string that represents all macro expansions that
+/// expanded into the given SourceLocation.
+///
+/// If 'getMacroStack(A) == getMacroStack(B)' is true, then the SourceLocations
+/// A and B are expanded from the same macros in the same order.
+static std::string getMacroStack(SourceLocation Loc, ASTContext &Context) {
+ std::string MacroStack;
+ llvm::raw_string_ostream MacroStackStream(MacroStack);
+ SourceManager &SM = Context.getSourceManager();
+
+ // Iterate over all macros that expanded into the given SourceLocation.
+ while (Loc.isMacroID()) {
+ // Add the macro name to the stream.
+ printMacroName(MacroStackStream, Context, Loc);
+ Loc = SM.getImmediateMacroCallerLoc(Loc);
+ }
+ MacroStackStream.flush();
+ return MacroStack;
+}
+
+namespace {
+/// \brief Collects the data of a single Stmt.
+///
+/// This class defines what a code clone is: If it collects for two statements
+/// the same data, then those two statements are considered to be clones of each
+/// other.
+///
+/// All collected data is forwarded to the given data consumer of the type T.
+/// The data consumer class needs to provide a member method with the signature:
+/// update(StringRef Str)
+template <typename T>
+class StmtDataCollector : public ConstStmtVisitor<StmtDataCollector<T>> {
+
+ ASTContext &Context;
+ /// \brief The data sink to which all data is forwarded.
+ T &DataConsumer;
+
+public:
+ /// \brief Collects data of the given Stmt.
+ /// \param S The given statement.
+ /// \param Context The ASTContext of S.
+ /// \param DataConsumer The data sink to which all data is forwarded.
+ StmtDataCollector(const Stmt *S, ASTContext &Context, T &DataConsumer)
+ : Context(Context), DataConsumer(DataConsumer) {
+ this->Visit(S);
+ }
+
+ // Below are utility methods for appending different data to the vector.
+
+ void addData(CloneDetector::DataPiece Integer) {
+ DataConsumer.update(
+ StringRef(reinterpret_cast<char *>(&Integer), sizeof(Integer)));
+ }
+
+ void addData(llvm::StringRef Str) { DataConsumer.update(Str); }
+
+ void addData(const QualType &QT) { addData(QT.getAsString()); }
+
+// The functions below collect the class specific data of each Stmt subclass.
+
+// Utility macro for defining a visit method for a given class. This method
+// calls back to the ConstStmtVisitor to visit all parent classes.
+#define DEF_ADD_DATA(CLASS, CODE) \
+ void Visit##CLASS(const CLASS *S) { \
+ CODE; \
+ ConstStmtVisitor<StmtDataCollector>::Visit##CLASS(S); \
+ }
+
+ DEF_ADD_DATA(Stmt, {
+ addData(S->getStmtClass());
+ // This ensures that macro generated code isn't identical to macro-generated
+ // code.
+ addData(getMacroStack(S->getLocStart(), Context));
+ addData(getMacroStack(S->getLocEnd(), Context));
+ })
+ DEF_ADD_DATA(Expr, { addData(S->getType()); })
+
+ //--- Builtin functionality ----------------------------------------------//
+ DEF_ADD_DATA(ArrayTypeTraitExpr, { addData(S->getTrait()); })
+ DEF_ADD_DATA(ExpressionTraitExpr, { addData(S->getTrait()); })
+ DEF_ADD_DATA(PredefinedExpr, { addData(S->getIdentType()); })
+ DEF_ADD_DATA(TypeTraitExpr, {
+ addData(S->getTrait());
+ for (unsigned i = 0; i < S->getNumArgs(); ++i)
+ addData(S->getArg(i)->getType());
+ })
+
+ //--- Calls --------------------------------------------------------------//
+ DEF_ADD_DATA(CallExpr, {
+ // Function pointers don't have a callee and we just skip hashing it.
+ if (const FunctionDecl *D = S->getDirectCallee()) {
+ // If the function is a template specialization, we also need to handle
+ // the template arguments as they are not included in the qualified name.
+ if (auto Args = D->getTemplateSpecializationArgs()) {
+ std::string ArgString;
+
+ // Print all template arguments into ArgString
+ llvm::raw_string_ostream OS(ArgString);
+ for (unsigned i = 0; i < Args->size(); ++i) {
+ Args->get(i).print(Context.getLangOpts(), OS);
+ // Add a padding character so that 'foo<X, XX>()' != 'foo<XX, X>()'.
+ OS << '\n';
+ }
+ OS.flush();
+
+ addData(ArgString);
+ }
+ addData(D->getQualifiedNameAsString());
+ }
+ })
+
+ //--- Exceptions ---------------------------------------------------------//
+ DEF_ADD_DATA(CXXCatchStmt, { addData(S->getCaughtType()); })
+
+ //--- C++ OOP Stmts ------------------------------------------------------//
+ DEF_ADD_DATA(CXXDeleteExpr, {
+ addData(S->isArrayFormAsWritten());
+ addData(S->isGlobalDelete());
+ })
+
+ //--- Casts --------------------------------------------------------------//
+ DEF_ADD_DATA(ObjCBridgedCastExpr, { addData(S->getBridgeKind()); })
+
+ //--- Miscellaneous Exprs ------------------------------------------------//
+ DEF_ADD_DATA(BinaryOperator, { addData(S->getOpcode()); })
+ DEF_ADD_DATA(UnaryOperator, { addData(S->getOpcode()); })
+
+ //--- Control flow -------------------------------------------------------//
+ DEF_ADD_DATA(GotoStmt, { addData(S->getLabel()->getName()); })
+ DEF_ADD_DATA(IndirectGotoStmt, {
+ if (S->getConstantTarget())
+ addData(S->getConstantTarget()->getName());
+ })
+ DEF_ADD_DATA(LabelStmt, { addData(S->getDecl()->getName()); })
+ DEF_ADD_DATA(MSDependentExistsStmt, { addData(S->isIfExists()); })
+ DEF_ADD_DATA(AddrLabelExpr, { addData(S->getLabel()->getName()); })
+
+ //--- Objective-C --------------------------------------------------------//
+ DEF_ADD_DATA(ObjCIndirectCopyRestoreExpr, { addData(S->shouldCopy()); })
+ DEF_ADD_DATA(ObjCPropertyRefExpr, {
+ addData(S->isSuperReceiver());
+ addData(S->isImplicitProperty());
+ })
+ DEF_ADD_DATA(ObjCAtCatchStmt, { addData(S->hasEllipsis()); })
+
+ //--- Miscellaneous Stmts ------------------------------------------------//
+ DEF_ADD_DATA(CXXFoldExpr, {
+ addData(S->isRightFold());
+ addData(S->getOperator());
+ })
+ DEF_ADD_DATA(GenericSelectionExpr, {
+ for (unsigned i = 0; i < S->getNumAssocs(); ++i) {
+ addData(S->getAssocType(i));
+ }
+ })
+ DEF_ADD_DATA(LambdaExpr, {
+ for (const LambdaCapture &C : S->captures()) {
+ addData(C.isPackExpansion());
+ addData(C.getCaptureKind());
+ if (C.capturesVariable())
+ addData(C.getCapturedVar()->getType());
+ }
+ addData(S->isGenericLambda());
+ addData(S->isMutable());
+ })
+ DEF_ADD_DATA(DeclStmt, {
+ auto numDecls = std::distance(S->decl_begin(), S->decl_end());
+ addData(static_cast<CloneDetector::DataPiece>(numDecls));
+ for (const Decl *D : S->decls()) {
+ if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ addData(VD->getType());
+ }
+ }
+ })
+ DEF_ADD_DATA(AsmStmt, {
+ addData(S->isSimple());
+ addData(S->isVolatile());
+ addData(S->generateAsmString(Context));
+ for (unsigned i = 0; i < S->getNumInputs(); ++i) {
+ addData(S->getInputConstraint(i));
+ }
+ for (unsigned i = 0; i < S->getNumOutputs(); ++i) {
+ addData(S->getOutputConstraint(i));
+ }
+ for (unsigned i = 0; i < S->getNumClobbers(); ++i) {
+ addData(S->getClobber(i));
+ }
+ })
+ DEF_ADD_DATA(AttributedStmt, {
+ for (const Attr *A : S->getAttrs()) {
+ addData(std::string(A->getSpelling()));
+ }
+ })
+};
+} // end anonymous namespace
+
+namespace {
+/// Generates CloneSignatures for a set of statements and stores the results in
+/// a CloneDetector object.
+class CloneSignatureGenerator {
+
+ CloneDetector &CD;
+ ASTContext &Context;
+
+ /// \brief Generates CloneSignatures for all statements in the given statement
+ /// tree and stores them in the CloneDetector.
+ ///
+ /// \param S The root of the given statement tree.
+ /// \param ParentMacroStack A string representing the macros that generated
+ /// the parent statement or an empty string if no
+ /// macros generated the parent statement.
+ /// See getMacroStack() for generating such a string.
+ /// \return The CloneSignature of the root statement.
+ CloneDetector::CloneSignature
+ generateSignatures(const Stmt *S, const std::string &ParentMacroStack) {
+ // Create an empty signature that will be filled in this method.
+ CloneDetector::CloneSignature Signature;
+
+ llvm::MD5 Hash;
+
+ // Collect all relevant data from S and hash it.
+ StmtDataCollector<llvm::MD5>(S, Context, Hash);
+
+ // Look up what macros expanded into the current statement.
+ std::string StartMacroStack = getMacroStack(S->getLocStart(), Context);
+ std::string EndMacroStack = getMacroStack(S->getLocEnd(), Context);
+
+ // First, check if ParentMacroStack is not empty which means we are currently
+ // dealing with a parent statement which was expanded from a macro.
+ // If this parent statement was expanded from the same macros as this
+ // statement, we reduce the initial complexity of this statement to zero.
+ // This causes that a group of statements that were generated by a single
+ // macro expansion will only increase the total complexity by one.
+ // Note: This is not the final complexity of this statement as we still
+ // add the complexity of the child statements to the complexity value.
+ if (!ParentMacroStack.empty() && (StartMacroStack == ParentMacroStack &&
+ EndMacroStack == ParentMacroStack)) {
+ Signature.Complexity = 0;
+ }
+
+ // Storage for the signatures of the direct child statements. This is only
+ // needed if the current statement is a CompoundStmt.
+ std::vector<CloneDetector::CloneSignature> ChildSignatures;
+ const CompoundStmt *CS = dyn_cast<const CompoundStmt>(S);
+
+ // The signature of a statement includes the signatures of its children.
+ // Therefore we create the signatures for every child and add them to the
+ // current signature.
+ for (const Stmt *Child : S->children()) {
+ // Some statements like 'if' can have nullptr children that we will skip.
+ if (!Child)
+ continue;
+
+ // Recursive call to create the signature of the child statement. This
+ // will also create and store all clone groups in this child statement.
+ // We pass only the StartMacroStack along to keep things simple.
+ auto ChildSignature = generateSignatures(Child, StartMacroStack);
+
+ // Add the collected data to the signature of the current statement.
+ Signature.Complexity += ChildSignature.Complexity;
+ Hash.update(StringRef(reinterpret_cast<char *>(&ChildSignature.Hash),
+ sizeof(ChildSignature.Hash)));
+
+ // If the current statement is a CompoundStatement, we need to store the
+ // signature for the generation of the sub-sequences.
+ if (CS)
+ ChildSignatures.push_back(ChildSignature);
+ }
+
+ // If the current statement is a CompoundStmt, we also need to create the
+ // clone groups from the sub-sequences inside the children.
+ if (CS)
+ handleSubSequences(CS, ChildSignatures);
+
+ // Create the final hash code for the current signature.
+ llvm::MD5::MD5Result HashResult;
+ Hash.final(HashResult);
+
+ // Copy as much of the generated hash code to the signature's hash code.
+ std::memcpy(&Signature.Hash, &HashResult,
+ std::min(sizeof(Signature.Hash), sizeof(HashResult)));
+
+ // Save the signature for the current statement in the CloneDetector object.
+ CD.add(StmtSequence(S, Context), Signature);
+
+ return Signature;
+ }
+
+ /// \brief Adds all possible sub-sequences in the child array of the given
+ /// CompoundStmt to the CloneDetector.
+ /// \param CS The given CompoundStmt.
+ /// \param ChildSignatures A list of calculated signatures for each child in
+ /// the given CompoundStmt.
+ void handleSubSequences(
+ const CompoundStmt *CS,
+ const std::vector<CloneDetector::CloneSignature> &ChildSignatures) {
+
+ // FIXME: This function has quadratic runtime right now. Check if skipping
+ // this function for too long CompoundStmts is an option.
+
+ // The length of the sub-sequence. We don't need to handle sequences with
+ // the length 1 as they are already handled in CollectData().
+ for (unsigned Length = 2; Length <= CS->size(); ++Length) {
+ // The start index in the body of the CompoundStmt. We increase the
+ // position until the end of the sub-sequence reaches the end of the
+ // CompoundStmt body.
+ for (unsigned Pos = 0; Pos <= CS->size() - Length; ++Pos) {
+ // Create an empty signature and add the signatures of all selected
+ // child statements to it.
+ CloneDetector::CloneSignature SubSignature;
+ llvm::MD5 SubHash;
+
+ for (unsigned i = Pos; i < Pos + Length; ++i) {
+ SubSignature.Complexity += ChildSignatures[i].Complexity;
+ size_t ChildHash = ChildSignatures[i].Hash;
+
+ SubHash.update(StringRef(reinterpret_cast<char *>(&ChildHash),
+ sizeof(ChildHash)));
+ }
+
+ // Create the final hash code for the current signature.
+ llvm::MD5::MD5Result HashResult;
+ SubHash.final(HashResult);
+
+ // Copy as much of the generated hash code to the signature's hash code.
+ std::memcpy(&SubSignature.Hash, &HashResult,
+ std::min(sizeof(SubSignature.Hash), sizeof(HashResult)));
+
+ // Save the signature together with the information about what children
+ // sequence we selected.
+ CD.add(StmtSequence(CS, Context, Pos, Pos + Length), SubSignature);
+ }
+ }
+ }
+
+public:
+ explicit CloneSignatureGenerator(CloneDetector &CD, ASTContext &Context)
+ : CD(CD), Context(Context) {}
+
+ /// \brief Generates signatures for all statements in the given function body.
+ void consumeCodeBody(const Stmt *S) { generateSignatures(S, ""); }
+};
+} // end anonymous namespace
+
+void CloneDetector::analyzeCodeBody(const Decl *D) {
+ assert(D);
+ assert(D->hasBody());
+ CloneSignatureGenerator Generator(*this, D->getASTContext());
+ Generator.consumeCodeBody(D->getBody());
+}
+
+void CloneDetector::add(const StmtSequence &S,
+ const CloneSignature &Signature) {
+ Sequences.push_back(std::make_pair(Signature, S));
+}
+
+namespace {
+/// \brief Returns true if and only if \p Stmt contains at least one other
+/// sequence in the \p Group.
+bool containsAnyInGroup(StmtSequence &Stmt, CloneDetector::CloneGroup &Group) {
+ for (StmtSequence &GroupStmt : Group.Sequences) {
+ if (Stmt.contains(GroupStmt))
+ return true;
+ }
+ return false;
+}
+
+/// \brief Returns true if and only if all sequences in \p OtherGroup are
+/// contained by a sequence in \p Group.
+bool containsGroup(CloneDetector::CloneGroup &Group,
+ CloneDetector::CloneGroup &OtherGroup) {
+ // We have less sequences in the current group than we have in the other,
+ // so we will never fulfill the requirement for returning true. This is only
+ // possible because we know that a sequence in Group can contain at most
+ // one sequence in OtherGroup.
+ if (Group.Sequences.size() < OtherGroup.Sequences.size())
+ return false;
+
+ for (StmtSequence &Stmt : Group.Sequences) {
+ if (!containsAnyInGroup(Stmt, OtherGroup))
+ return false;
+ }
+ return true;
+}
+} // end anonymous namespace
+
+namespace {
+/// \brief Wrapper around FoldingSetNodeID that it can be used as the template
+/// argument of the StmtDataCollector.
+class FoldingSetNodeIDWrapper {
+
+ llvm::FoldingSetNodeID &FS;
+
+public:
+ FoldingSetNodeIDWrapper(llvm::FoldingSetNodeID &FS) : FS(FS) {}
+
+ void update(StringRef Str) { FS.AddString(Str); }
+};
+} // end anonymous namespace
+
+/// \brief Writes the relevant data from all statements and child statements
+/// in the given StmtSequence into the given FoldingSetNodeID.
+static void CollectStmtSequenceData(const StmtSequence &Sequence,
+ FoldingSetNodeIDWrapper &OutputData) {
+ for (const Stmt *S : Sequence) {
+ StmtDataCollector<FoldingSetNodeIDWrapper>(S, Sequence.getASTContext(),
+ OutputData);
+
+ for (const Stmt *Child : S->children()) {
+ if (!Child)
+ continue;
+
+ CollectStmtSequenceData(StmtSequence(Child, Sequence.getASTContext()),
+ OutputData);
+ }
+ }
+}
+
+/// \brief Returns true if both sequences are clones of each other.
+static bool areSequencesClones(const StmtSequence &LHS,
+ const StmtSequence &RHS) {
+ // We collect the data from all statements in the sequence as we did before
+ // when generating a hash value for each sequence. But this time we don't
+ // hash the collected data and compare the whole data set instead. This
+ // prevents any false-positives due to hash code collisions.
+ llvm::FoldingSetNodeID DataLHS, DataRHS;
+ FoldingSetNodeIDWrapper LHSWrapper(DataLHS);
+ FoldingSetNodeIDWrapper RHSWrapper(DataRHS);
+
+ CollectStmtSequenceData(LHS, LHSWrapper);
+ CollectStmtSequenceData(RHS, RHSWrapper);
+
+ return DataLHS == DataRHS;
+}
+
+/// \brief Finds all actual clone groups in a single group of presumed clones.
+/// \param Result Output parameter to which all found groups are added.
+/// \param Group A group of presumed clones. The clones are allowed to have a
+/// different variable pattern and may not be actual clones of each
+/// other.
+/// \param CheckVariablePattern If true, every clone in a group that was added
+/// to the output follows the same variable pattern as the other
+/// clones in its group.
+static void createCloneGroups(std::vector<CloneDetector::CloneGroup> &Result,
+ const CloneDetector::CloneGroup &Group,
+ bool CheckVariablePattern) {
+ // We remove the Sequences one by one, so a list is more appropriate.
+ std::list<StmtSequence> UnassignedSequences(Group.Sequences.begin(),
+ Group.Sequences.end());
+
+ // Search for clones as long as there could be clones in UnassignedSequences.
+ while (UnassignedSequences.size() > 1) {
+
+ // Pick the first Sequence as a protoype for a new clone group.
+ StmtSequence Prototype = UnassignedSequences.front();
+ UnassignedSequences.pop_front();
+
+ CloneDetector::CloneGroup FilteredGroup(Prototype, Group.Signature);
+
+ // Analyze the variable pattern of the prototype. Every other StmtSequence
+ // needs to have the same pattern to get into the new clone group.
+ VariablePattern PrototypeFeatures(Prototype);
+
+ // Search all remaining StmtSequences for an identical variable pattern
+ // and assign them to our new clone group.
+ auto I = UnassignedSequences.begin(), E = UnassignedSequences.end();
+ while (I != E) {
+ // If the sequence doesn't fit to the prototype, we have encountered
+ // an unintended hash code collision and we skip it.
+ if (!areSequencesClones(Prototype, *I)) {
+ ++I;
+ continue;
+ }
+
+ // If we weren't asked to check for a matching variable pattern in clone
+ // groups we can add the sequence now to the new clone group.
+ // If we were asked to check for matching variable pattern, we first have
+ // to check that there are no differences between the two patterns and
+ // only proceed if they match.
+ if (!CheckVariablePattern ||
+ VariablePattern(*I).countPatternDifferences(PrototypeFeatures) == 0) {
+ FilteredGroup.Sequences.push_back(*I);
+ I = UnassignedSequences.erase(I);
+ continue;
+ }
+
+ // We didn't found a matching variable pattern, so we continue with the
+ // next sequence.
+ ++I;
+ }
+
+ // Add a valid clone group to the list of found clone groups.
+ if (!FilteredGroup.isValid())
+ continue;
+
+ Result.push_back(FilteredGroup);
+ }
+}
+
+void CloneDetector::findClones(std::vector<CloneGroup> &Result,
+ unsigned MinGroupComplexity,
+ bool CheckPatterns) {
+ // A shortcut (and necessary for the for-loop later in this function).
+ if (Sequences.empty())
+ return;
+
+ // We need to search for groups of StmtSequences with the same hash code to
+ // create our initial clone groups. By sorting all known StmtSequences by
+ // their hash value we make sure that StmtSequences with the same hash code
+ // are grouped together in the Sequences vector.
+ // Note: We stable sort here because the StmtSequences are added in the order
+ // in which they appear in the source file. We want to preserve that order
+ // because we also want to report them in that order in the CloneChecker.
+ std::stable_sort(Sequences.begin(), Sequences.end(),
+ [](std::pair<CloneSignature, StmtSequence> LHS,
+ std::pair<CloneSignature, StmtSequence> RHS) {
+ return LHS.first.Hash < RHS.first.Hash;
+ });
+
+ std::vector<CloneGroup> CloneGroups;
+
+ // Check for each CloneSignature if its successor has the same hash value.
+ // We don't check the last CloneSignature as it has no successor.
+ // Note: The 'size - 1' in the condition is safe because we check for an empty
+ // Sequences vector at the beginning of this function.
+ for (unsigned i = 0; i < Sequences.size() - 1; ++i) {
+ const auto Current = Sequences[i];
+ const auto Next = Sequences[i + 1];
+
+ if (Current.first.Hash != Next.first.Hash)
+ continue;
+
+ // It's likely that we just found an sequence of CloneSignatures that
+ // represent a CloneGroup, so we create a new group and start checking and
+ // adding the CloneSignatures in this sequence.
+ CloneGroup Group;
+ Group.Signature = Current.first;
+
+ for (; i < Sequences.size(); ++i) {
+ const auto &Signature = Sequences[i];
+
+ // A different hash value means we have reached the end of the sequence.
+ if (Current.first.Hash != Signature.first.Hash) {
+ // The current Signature could be the start of a new CloneGroup. So we
+ // decrement i so that we visit it again in the outer loop.
+ // Note: i can never be 0 at this point because we are just comparing
+ // the hash of the Current CloneSignature with itself in the 'if' above.
+ assert(i != 0);
+ --i;
+ break;
+ }
+
+ // Skip CloneSignatures that won't pass the complexity requirement.
+ if (Signature.first.Complexity < MinGroupComplexity)
+ continue;
+
+ Group.Sequences.push_back(Signature.second);
+ }
+
+ // There is a chance that we haven't found more than two fitting
+ // CloneSignature because not enough CloneSignatures passed the complexity
+ // requirement. As a CloneGroup with less than two members makes no sense,
+ // we ignore this CloneGroup and won't add it to the result.
+ if (!Group.isValid())
+ continue;
+
+ CloneGroups.push_back(Group);
+ }
+
+ // Add every valid clone group that fulfills the complexity requirement.
+ for (const CloneGroup &Group : CloneGroups) {
+ createCloneGroups(Result, Group, CheckPatterns);
+ }
+
+ std::vector<unsigned> IndexesToRemove;
+
+ // Compare every group in the result with the rest. If one groups contains
+ // another group, we only need to return the bigger group.
+ // Note: This doesn't scale well, so if possible avoid calling any heavy
+ // function from this loop to minimize the performance impact.
+ for (unsigned i = 0; i < Result.size(); ++i) {
+ for (unsigned j = 0; j < Result.size(); ++j) {
+ // Don't compare a group with itself.
+ if (i == j)
+ continue;
+
+ if (containsGroup(Result[j], Result[i])) {
+ IndexesToRemove.push_back(i);
+ break;
+ }
+ }
+ }
+
+ // Erasing a list of indexes from the vector should be done with decreasing
+ // indexes. As IndexesToRemove is constructed with increasing values, we just
+ // reverse iterate over it to get the desired order.
+ for (auto I = IndexesToRemove.rbegin(); I != IndexesToRemove.rend(); ++I) {
+ Result.erase(Result.begin() + *I);
+ }
+}
+
+void CloneDetector::findSuspiciousClones(
+ std::vector<CloneDetector::SuspiciousClonePair> &Result,
+ unsigned MinGroupComplexity) {
+ std::vector<CloneGroup> Clones;
+ // Reuse the normal search for clones but specify that the clone groups don't
+ // need to have a common referenced variable pattern so that we can manually
+ // search for the kind of pattern errors this function is supposed to find.
+ findClones(Clones, MinGroupComplexity, false);
+
+ for (const CloneGroup &Group : Clones) {
+ for (unsigned i = 0; i < Group.Sequences.size(); ++i) {
+ VariablePattern PatternA(Group.Sequences[i]);
+
+ for (unsigned j = i + 1; j < Group.Sequences.size(); ++j) {
+ VariablePattern PatternB(Group.Sequences[j]);
+
+ CloneDetector::SuspiciousClonePair ClonePair;
+ // For now, we only report clones which break the variable pattern just
+ // once because multiple differences in a pattern are an indicator that
+ // those differences are maybe intended (e.g. because it's actually
+ // a different algorithm).
+ // TODO: In very big clones even multiple variables can be unintended,
+ // so replacing this number with a percentage could better handle such
+ // cases. On the other hand it could increase the false-positive rate
+ // for all clones if the percentage is too high.
+ if (PatternA.countPatternDifferences(PatternB, &ClonePair) == 1) {
+ Result.push_back(ClonePair);
+ break;
+ }
+ }
+ }
+ }
+}
diff --git a/lib/Analysis/Consumed.cpp b/lib/Analysis/Consumed.cpp
index 47bef1b927c9..f6fe78ac4619 100644
--- a/lib/Analysis/Consumed.cpp
+++ b/lib/Analysis/Consumed.cpp
@@ -12,6 +12,7 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/Analysis/Analyses/Consumed.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
#include "clang/AST/DeclCXX.h"
@@ -20,16 +21,12 @@
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/Type.h"
-#include "clang/Analysis/Analyses/Consumed.h"
#include "clang/Analysis/Analyses/PostOrderCFGView.h"
#include "clang/Analysis/AnalysisContext.h"
#include "clang/Analysis/CFG.h"
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/raw_ostream.h"
#include <memory>
// TODO: Adjust states of args to constructors in the same way that arguments to
diff --git a/lib/Analysis/FormatString.cpp b/lib/Analysis/FormatString.cpp
index 83d08b55427f..c62e537e92dd 100644
--- a/lib/Analysis/FormatString.cpp
+++ b/lib/Analysis/FormatString.cpp
@@ -266,14 +266,15 @@ bool clang::analyze_format_string::ParseUTF8InvalidSpecifier(
if (SpecifierBegin + 1 >= FmtStrEnd)
return false;
- const UTF8 *SB = reinterpret_cast<const UTF8 *>(SpecifierBegin + 1);
- const UTF8 *SE = reinterpret_cast<const UTF8 *>(FmtStrEnd);
+ const llvm::UTF8 *SB =
+ reinterpret_cast<const llvm::UTF8 *>(SpecifierBegin + 1);
+ const llvm::UTF8 *SE = reinterpret_cast<const llvm::UTF8 *>(FmtStrEnd);
const char FirstByte = *SB;
// If the invalid specifier is a multibyte UTF-8 string, return the
// total length accordingly so that the conversion specifier can be
// properly updated to reflect a complete UTF-8 specifier.
- unsigned NumBytes = getNumBytesForUTF8(FirstByte);
+ unsigned NumBytes = llvm::getNumBytesForUTF8(FirstByte);
if (NumBytes == 1)
return false;
if (SB + NumBytes > SE)
@@ -310,8 +311,13 @@ ArgType::matchesType(ASTContext &C, QualType argTy) const {
return Match;
case AnyCharTy: {
- if (const EnumType *ETy = argTy->getAs<EnumType>())
+ if (const EnumType *ETy = argTy->getAs<EnumType>()) {
+ // If the enum is incomplete we know nothing about the underlying type.
+ // Assume that it's 'int'.
+ if (!ETy->getDecl()->isComplete())
+ return NoMatch;
argTy = ETy->getDecl()->getIntegerType();
+ }
if (const BuiltinType *BT = argTy->getAs<BuiltinType>())
switch (BT->getKind()) {
@@ -327,8 +333,14 @@ ArgType::matchesType(ASTContext &C, QualType argTy) const {
}
case SpecificTy: {
- if (const EnumType *ETy = argTy->getAs<EnumType>())
- argTy = ETy->getDecl()->getIntegerType();
+ if (const EnumType *ETy = argTy->getAs<EnumType>()) {
+ // If the enum is incomplete we know nothing about the underlying type.
+ // Assume that it's 'int'.
+ if (!ETy->getDecl()->isComplete())
+ argTy = C.IntTy;
+ else
+ argTy = ETy->getDecl()->getIntegerType();
+ }
argTy = C.getCanonicalType(argTy).getUnqualifiedType();
if (T == argTy)
@@ -579,6 +591,8 @@ const char *ConversionSpecifier::toString() const {
case cArg: return "c";
case sArg: return "s";
case pArg: return "p";
+ case PArg:
+ return "P";
case nArg: return "n";
case PercentArg: return "%";
case ScanListArg: return "[";
@@ -854,6 +868,7 @@ bool FormatSpecifier::hasStandardConversionSpecifier(
case ConversionSpecifier::ObjCObjArg:
case ConversionSpecifier::ScanListArg:
case ConversionSpecifier::PercentArg:
+ case ConversionSpecifier::PArg:
return true;
case ConversionSpecifier::CArg:
case ConversionSpecifier::SArg:
diff --git a/lib/Analysis/FormatStringParsing.h b/lib/Analysis/FormatStringParsing.h
index 8463fcec5bf4..17fd2f6aefb8 100644
--- a/lib/Analysis/FormatStringParsing.h
+++ b/lib/Analysis/FormatStringParsing.h
@@ -4,7 +4,6 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/Type.h"
#include "clang/Analysis/Analyses/FormatString.h"
-#include "llvm/Support/raw_ostream.h"
namespace clang {
diff --git a/lib/Analysis/LiveVariables.cpp b/lib/Analysis/LiveVariables.cpp
index 5e0a9a0d73c8..cd73a62e6918 100644
--- a/lib/Analysis/LiveVariables.cpp
+++ b/lib/Analysis/LiveVariables.cpp
@@ -19,6 +19,7 @@
#include "clang/Analysis/CFG.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/PostOrderIterator.h"
+#include "llvm/ADT/PriorityQueue.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <vector>
@@ -28,20 +29,21 @@ using namespace clang;
namespace {
class DataflowWorklist {
- SmallVector<const CFGBlock *, 20> worklist;
llvm::BitVector enqueuedBlocks;
PostOrderCFGView *POV;
+ llvm::PriorityQueue<const CFGBlock *, SmallVector<const CFGBlock *, 20>,
+ PostOrderCFGView::BlockOrderCompare> worklist;
+
public:
DataflowWorklist(const CFG &cfg, AnalysisDeclContext &Ctx)
: enqueuedBlocks(cfg.getNumBlockIDs()),
- POV(Ctx.getAnalysis<PostOrderCFGView>()) {}
+ POV(Ctx.getAnalysis<PostOrderCFGView>()),
+ worklist(POV->getComparator()) {}
void enqueueBlock(const CFGBlock *block);
void enqueuePredecessors(const CFGBlock *block);
const CFGBlock *dequeue();
-
- void sortWorklist();
};
}
@@ -49,31 +51,22 @@ public:
void DataflowWorklist::enqueueBlock(const clang::CFGBlock *block) {
if (block && !enqueuedBlocks[block->getBlockID()]) {
enqueuedBlocks[block->getBlockID()] = true;
- worklist.push_back(block);
+ worklist.push(block);
}
}
void DataflowWorklist::enqueuePredecessors(const clang::CFGBlock *block) {
- const unsigned OldWorklistSize = worklist.size();
for (CFGBlock::const_pred_iterator I = block->pred_begin(),
E = block->pred_end(); I != E; ++I) {
enqueueBlock(*I);
}
-
- if (OldWorklistSize == 0 || OldWorklistSize == worklist.size())
- return;
-
- sortWorklist();
-}
-
-void DataflowWorklist::sortWorklist() {
- std::sort(worklist.begin(), worklist.end(), POV->getComparator());
}
const CFGBlock *DataflowWorklist::dequeue() {
if (worklist.empty())
return nullptr;
- const CFGBlock *b = worklist.pop_back_val();
+ const CFGBlock *b = worklist.top();
+ worklist.pop();
enqueuedBlocks[b->getBlockID()] = false;
return b;
}
@@ -528,8 +521,6 @@ LiveVariables::computeLiveness(AnalysisDeclContext &AC,
}
}
- worklist.sortWorklist();
-
while (const CFGBlock *block = worklist.dequeue()) {
// Determine if the block's end value has changed. If not, we
// have nothing left to do for this block.
diff --git a/lib/Analysis/OSLog.cpp b/lib/Analysis/OSLog.cpp
new file mode 100644
index 000000000000..3e13a153c65f
--- /dev/null
+++ b/lib/Analysis/OSLog.cpp
@@ -0,0 +1,202 @@
+// TODO: header template
+
+#include "clang/Analysis/Analyses/OSLog.h"
+#include "clang/AST/Attr.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/Analysis/Analyses/FormatString.h"
+#include "clang/Basic/Builtins.h"
+#include "llvm/ADT/SmallBitVector.h"
+
+using namespace clang;
+using llvm::APInt;
+
+using clang::analyze_os_log::OSLogBufferItem;
+using clang::analyze_os_log::OSLogBufferLayout;
+
+class OSLogFormatStringHandler
+ : public analyze_format_string::FormatStringHandler {
+private:
+ struct ArgData {
+ const Expr *E = nullptr;
+ Optional<OSLogBufferItem::Kind> Kind;
+ Optional<unsigned> Size;
+ Optional<const Expr *> Count;
+ Optional<const Expr *> Precision;
+ Optional<const Expr *> FieldWidth;
+ unsigned char Flags = 0;
+ };
+ SmallVector<ArgData, 4> ArgsData;
+ ArrayRef<const Expr *> Args;
+
+ OSLogBufferItem::Kind
+ getKind(analyze_format_string::ConversionSpecifier::Kind K) {
+ switch (K) {
+ case clang::analyze_format_string::ConversionSpecifier::sArg: // "%s"
+ return OSLogBufferItem::StringKind;
+ case clang::analyze_format_string::ConversionSpecifier::SArg: // "%S"
+ return OSLogBufferItem::WideStringKind;
+ case clang::analyze_format_string::ConversionSpecifier::PArg: { // "%P"
+ return OSLogBufferItem::PointerKind;
+ case clang::analyze_format_string::ConversionSpecifier::ObjCObjArg: // "%@"
+ return OSLogBufferItem::ObjCObjKind;
+ case clang::analyze_format_string::ConversionSpecifier::PrintErrno: // "%m"
+ return OSLogBufferItem::ErrnoKind;
+ default:
+ return OSLogBufferItem::ScalarKind;
+ }
+ }
+ }
+
+public:
+ OSLogFormatStringHandler(ArrayRef<const Expr *> Args) : Args(Args) {
+ ArgsData.reserve(Args.size());
+ }
+
+ virtual bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS,
+ const char *StartSpecifier,
+ unsigned SpecifierLen) {
+ if (!FS.consumesDataArgument() &&
+ FS.getConversionSpecifier().getKind() !=
+ clang::analyze_format_string::ConversionSpecifier::PrintErrno)
+ return true;
+
+ ArgsData.emplace_back();
+ unsigned ArgIndex = FS.getArgIndex();
+ if (ArgIndex < Args.size())
+ ArgsData.back().E = Args[ArgIndex];
+
+ // First get the Kind
+ ArgsData.back().Kind = getKind(FS.getConversionSpecifier().getKind());
+ if (ArgsData.back().Kind != OSLogBufferItem::ErrnoKind &&
+ !ArgsData.back().E) {
+ // missing argument
+ ArgsData.pop_back();
+ return false;
+ }
+
+ switch (FS.getConversionSpecifier().getKind()) {
+ case clang::analyze_format_string::ConversionSpecifier::sArg: // "%s"
+ case clang::analyze_format_string::ConversionSpecifier::SArg: { // "%S"
+ auto &precision = FS.getPrecision();
+ switch (precision.getHowSpecified()) {
+ case clang::analyze_format_string::OptionalAmount::NotSpecified: // "%s"
+ break;
+ case clang::analyze_format_string::OptionalAmount::Constant: // "%.16s"
+ ArgsData.back().Size = precision.getConstantAmount();
+ break;
+ case clang::analyze_format_string::OptionalAmount::Arg: // "%.*s"
+ ArgsData.back().Count = Args[precision.getArgIndex()];
+ break;
+ case clang::analyze_format_string::OptionalAmount::Invalid:
+ return false;
+ }
+ break;
+ }
+ case clang::analyze_format_string::ConversionSpecifier::PArg: { // "%P"
+ auto &precision = FS.getPrecision();
+ switch (precision.getHowSpecified()) {
+ case clang::analyze_format_string::OptionalAmount::NotSpecified: // "%P"
+ return false; // length must be supplied with pointer format specifier
+ case clang::analyze_format_string::OptionalAmount::Constant: // "%.16P"
+ ArgsData.back().Size = precision.getConstantAmount();
+ break;
+ case clang::analyze_format_string::OptionalAmount::Arg: // "%.*P"
+ ArgsData.back().Count = Args[precision.getArgIndex()];
+ break;
+ case clang::analyze_format_string::OptionalAmount::Invalid:
+ return false;
+ }
+ break;
+ }
+ default:
+ if (FS.getPrecision().hasDataArgument()) {
+ ArgsData.back().Precision = Args[FS.getPrecision().getArgIndex()];
+ }
+ break;
+ }
+ if (FS.getFieldWidth().hasDataArgument()) {
+ ArgsData.back().FieldWidth = Args[FS.getFieldWidth().getArgIndex()];
+ }
+
+ if (FS.isPrivate()) {
+ ArgsData.back().Flags |= OSLogBufferItem::IsPrivate;
+ }
+ if (FS.isPublic()) {
+ ArgsData.back().Flags |= OSLogBufferItem::IsPublic;
+ }
+ return true;
+ }
+
+ void computeLayout(ASTContext &Ctx, OSLogBufferLayout &Layout) const {
+ Layout.Items.clear();
+ for (auto &Data : ArgsData) {
+ if (Data.FieldWidth) {
+ CharUnits Size = Ctx.getTypeSizeInChars((*Data.FieldWidth)->getType());
+ Layout.Items.emplace_back(OSLogBufferItem::ScalarKind, *Data.FieldWidth,
+ Size, 0);
+ }
+ if (Data.Precision) {
+ CharUnits Size = Ctx.getTypeSizeInChars((*Data.Precision)->getType());
+ Layout.Items.emplace_back(OSLogBufferItem::ScalarKind, *Data.Precision,
+ Size, 0);
+ }
+ if (Data.Count) {
+ // "%.*P" has an extra "count" that we insert before the argument.
+ CharUnits Size = Ctx.getTypeSizeInChars((*Data.Count)->getType());
+ Layout.Items.emplace_back(OSLogBufferItem::CountKind, *Data.Count, Size,
+ 0);
+ }
+ if (Data.Size)
+ Layout.Items.emplace_back(Ctx, CharUnits::fromQuantity(*Data.Size),
+ Data.Flags);
+ if (Data.Kind) {
+ CharUnits Size;
+ if (*Data.Kind == OSLogBufferItem::ErrnoKind)
+ Size = CharUnits::Zero();
+ else
+ Size = Ctx.getTypeSizeInChars(Data.E->getType());
+ Layout.Items.emplace_back(*Data.Kind, Data.E, Size, Data.Flags);
+ } else {
+ auto Size = Ctx.getTypeSizeInChars(Data.E->getType());
+ Layout.Items.emplace_back(OSLogBufferItem::ScalarKind, Data.E, Size,
+ Data.Flags);
+ }
+ }
+ }
+};
+
+bool clang::analyze_os_log::computeOSLogBufferLayout(
+ ASTContext &Ctx, const CallExpr *E, OSLogBufferLayout &Layout) {
+ ArrayRef<const Expr *> Args(E->getArgs(), E->getArgs() + E->getNumArgs());
+
+ const Expr *StringArg;
+ ArrayRef<const Expr *> VarArgs;
+ switch (E->getBuiltinCallee()) {
+ case Builtin::BI__builtin_os_log_format_buffer_size:
+ assert(E->getNumArgs() >= 1 &&
+ "__builtin_os_log_format_buffer_size takes at least 1 argument");
+ StringArg = E->getArg(0);
+ VarArgs = Args.slice(1);
+ break;
+ case Builtin::BI__builtin_os_log_format:
+ assert(E->getNumArgs() >= 2 &&
+ "__builtin_os_log_format takes at least 2 arguments");
+ StringArg = E->getArg(1);
+ VarArgs = Args.slice(2);
+ break;
+ default:
+ llvm_unreachable("non-os_log builtin passed to computeOSLogBufferLayout");
+ }
+
+ const StringLiteral *Lit = cast<StringLiteral>(StringArg->IgnoreParenCasts());
+ assert(Lit && (Lit->isAscii() || Lit->isUTF8()));
+ StringRef Data = Lit->getString();
+ OSLogFormatStringHandler H(VarArgs);
+ ParsePrintfString(H, Data.begin(), Data.end(), Ctx.getLangOpts(),
+ Ctx.getTargetInfo(), /*isFreeBSDKPrintf*/ false);
+
+ H.computeLayout(Ctx, Layout);
+ return true;
+}
diff --git a/lib/Analysis/PrintfFormatString.cpp b/lib/Analysis/PrintfFormatString.cpp
index ac6cef9d0842..ed7193ecb437 100644
--- a/lib/Analysis/PrintfFormatString.cpp
+++ b/lib/Analysis/PrintfFormatString.cpp
@@ -119,6 +119,39 @@ 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);
+ }
+ }
+
// Look for flags (if any).
bool hasMore = true;
for ( ; I != E; ++I) {
@@ -253,6 +286,10 @@ static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H,
// POSIX specific.
case 'C': k = ConversionSpecifier::CArg; break;
case 'S': k = ConversionSpecifier::SArg; break;
+ // Apple extension for os_log
+ case 'P':
+ k = ConversionSpecifier::PArg;
+ break;
// Objective-C.
case '@': k = ConversionSpecifier::ObjCObjArg; break;
// Glibc specific.
@@ -301,7 +338,7 @@ static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H,
conversionPosition);
return true;
}
-
+
PrintfConversionSpecifier CS(conversionPosition, k);
FS.setConversionSpecifier(CS);
if (CS.consumesDataArgument() && !FS.usesPositionalArg())
@@ -541,6 +578,7 @@ ArgType PrintfSpecifier::getArgType(ASTContext &Ctx,
return Ctx.IntTy;
return ArgType(Ctx.WideCharTy, "wchar_t");
case ConversionSpecifier::pArg:
+ case ConversionSpecifier::PArg:
return ArgType::CPointerTy;
case ConversionSpecifier::ObjCObjArg:
return ArgType::ObjCPointerTy;
@@ -900,7 +938,7 @@ bool PrintfSpecifier::hasValidPrecision() const {
if (Precision.getHowSpecified() == OptionalAmount::NotSpecified)
return true;
- // Precision is only valid with the diouxXaAeEfFgGs conversions
+ // Precision is only valid with the diouxXaAeEfFgGsP conversions
switch (CS.getKind()) {
case ConversionSpecifier::dArg:
case ConversionSpecifier::DArg:
@@ -922,6 +960,7 @@ bool PrintfSpecifier::hasValidPrecision() const {
case ConversionSpecifier::sArg:
case ConversionSpecifier::FreeBSDrArg:
case ConversionSpecifier::FreeBSDyArg:
+ case ConversionSpecifier::PArg:
return true;
default:
diff --git a/lib/Analysis/ReachableCode.cpp b/lib/Analysis/ReachableCode.cpp
index 8165b09f4080..69d000c03bac 100644
--- a/lib/Analysis/ReachableCode.cpp
+++ b/lib/Analysis/ReachableCode.cpp
@@ -164,6 +164,8 @@ static bool isConfigurationValue(const Stmt *S,
if (!S)
return false;
+ S = S->IgnoreImplicit();
+
if (const Expr *Ex = dyn_cast<Expr>(S))
S = Ex->IgnoreCasts();
diff --git a/lib/Analysis/ScanfFormatString.cpp b/lib/Analysis/ScanfFormatString.cpp
index 82b038864c23..3b93f1a57f1f 100644
--- a/lib/Analysis/ScanfFormatString.cpp
+++ b/lib/Analysis/ScanfFormatString.cpp
@@ -418,8 +418,12 @@ bool ScanfSpecifier::fixType(QualType QT, QualType RawQT,
QualType PT = QT->getPointeeType();
// If it's an enum, get its underlying type.
- if (const EnumType *ETy = PT->getAs<EnumType>())
+ if (const EnumType *ETy = PT->getAs<EnumType>()) {
+ // Don't try to fix incomplete enums.
+ if (!ETy->getDecl()->isComplete())
+ return false;
PT = ETy->getDecl()->getIntegerType();
+ }
const BuiltinType *BT = PT->getAs<BuiltinType>();
if (!BT)
diff --git a/lib/Analysis/ThreadSafety.cpp b/lib/Analysis/ThreadSafety.cpp
index b282a5bbd8d8..879a15c9c2a8 100644
--- a/lib/Analysis/ThreadSafety.cpp
+++ b/lib/Analysis/ThreadSafety.cpp
@@ -15,13 +15,13 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/Analysis/Analyses/ThreadSafety.h"
#include "clang/AST/Attr.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Analysis/Analyses/PostOrderCFGView.h"
-#include "clang/Analysis/Analyses/ThreadSafety.h"
#include "clang/Analysis/Analyses/ThreadSafetyCommon.h"
#include "clang/Analysis/Analyses/ThreadSafetyLogical.h"
#include "clang/Analysis/Analyses/ThreadSafetyTIL.h"
@@ -32,8 +32,6 @@
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
-#include "llvm/ADT/BitVector.h"
-#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/ImmutableMap.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/SmallVector.h"
@@ -259,7 +257,7 @@ private:
struct BeforeInfo {
BeforeInfo() : Visited(0) {}
- BeforeInfo(BeforeInfo &&O) : Vect(std::move(O.Vect)), Visited(O.Visited) {}
+ BeforeInfo(BeforeInfo &&) = default;
BeforeVect Vect;
int Visited;
@@ -1585,7 +1583,7 @@ void BuildLockset::warnIfMutexHeld(const NamedDecl *D, const Expr *Exp,
/// a pointer marked with pt_guarded_by.
void BuildLockset::checkAccess(const Expr *Exp, AccessKind AK,
ProtectedOperationKind POK) {
- Exp = Exp->IgnoreParenCasts();
+ Exp = Exp->IgnoreImplicit()->IgnoreParenCasts();
SourceLocation Loc = Exp->getExprLoc();
diff --git a/lib/Analysis/ThreadSafetyCommon.cpp b/lib/Analysis/ThreadSafetyCommon.cpp
index ffe95ea22a42..cbd5464c34d7 100644
--- a/lib/Analysis/ThreadSafetyCommon.cpp
+++ b/lib/Analysis/ThreadSafetyCommon.cpp
@@ -17,20 +17,14 @@
#include "clang/AST/DeclObjC.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/StmtCXX.h"
-#include "clang/Analysis/Analyses/PostOrderCFGView.h"
#include "clang/Analysis/Analyses/ThreadSafetyTIL.h"
#include "clang/Analysis/Analyses/ThreadSafetyTraverse.h"
#include "clang/Analysis/AnalysisContext.h"
#include "clang/Analysis/CFG.h"
#include "clang/Basic/OperatorKinds.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 <algorithm>
-#include <climits>
-#include <vector>
using namespace clang;
using namespace threadSafety;
@@ -239,6 +233,9 @@ til::SExpr *SExprBuilder::translate(const Stmt *S, CallingContext *Ctx) {
return translate(cast<ExprWithCleanups>(S)->getSubExpr(), Ctx);
case Stmt::CXXBindTemporaryExprClass:
return translate(cast<CXXBindTemporaryExpr>(S)->getSubExpr(), Ctx);
+ case Stmt::MaterializeTemporaryExprClass:
+ return translate(cast<MaterializeTemporaryExpr>(S)->GetTemporaryExpr(),
+ Ctx);
// Collect all literals
case Stmt::CharacterLiteralClass:
diff --git a/lib/Analysis/UninitializedValues.cpp b/lib/Analysis/UninitializedValues.cpp
index f2f791957aa3..d5289fb9d427 100644
--- a/lib/Analysis/UninitializedValues.cpp
+++ b/lib/Analysis/UninitializedValues.cpp
@@ -348,7 +348,8 @@ public:
}
static const DeclRefExpr *getSelfInitExpr(VarDecl *VD) {
- if (VD->getType()->isRecordType()) return nullptr;
+ if (VD->getType()->isRecordType())
+ return nullptr;
if (Expr *Init = VD->getInit()) {
const DeclRefExpr *DRE
= dyn_cast<DeclRefExpr>(stripCasts(VD->getASTContext(), Init));
diff --git a/lib/Basic/CMakeLists.txt b/lib/Basic/CMakeLists.txt
index ad460d496533..8929ec30ff7b 100644
--- a/lib/Basic/CMakeLists.txt
+++ b/lib/Basic/CMakeLists.txt
@@ -28,7 +28,7 @@ find_first_existing_vc_file(clang_vc "${CLANG_SOURCE_DIR}")
# The VC revision include that we want to generate.
set(version_inc "${CMAKE_CURRENT_BINARY_DIR}/SVNVersion.inc")
-set(get_svn_script "${LLVM_MAIN_SRC_DIR}/cmake/modules/GetSVN.cmake")
+set(get_svn_script "${LLVM_CMAKE_PATH}/GetSVN.cmake")
if(DEFINED llvm_vc AND DEFINED clang_vc)
# Create custom target to generate the VC revision include.
diff --git a/lib/Basic/Diagnostic.cpp b/lib/Basic/Diagnostic.cpp
index f10d156743b2..7529c475d6b9 100644
--- a/lib/Basic/Diagnostic.cpp
+++ b/lib/Basic/Diagnostic.cpp
@@ -55,10 +55,12 @@ static void DummyArgToStringFn(DiagnosticsEngine::ArgumentKind AK, intptr_t QT,
Output.append(Str.begin(), Str.end());
}
-DiagnosticsEngine::DiagnosticsEngine(
- const IntrusiveRefCntPtr<DiagnosticIDs> &diags, DiagnosticOptions *DiagOpts,
- DiagnosticConsumer *client, bool ShouldOwnClient)
- : Diags(diags), DiagOpts(DiagOpts), Client(nullptr), SourceMgr(nullptr) {
+DiagnosticsEngine::DiagnosticsEngine(IntrusiveRefCntPtr<DiagnosticIDs> diags,
+ DiagnosticOptions *DiagOpts,
+ DiagnosticConsumer *client,
+ bool ShouldOwnClient)
+ : Diags(std::move(diags)), DiagOpts(DiagOpts), Client(nullptr),
+ SourceMgr(nullptr) {
setClient(client, ShouldOwnClient);
ArgToStringFn = DummyArgToStringFn;
ArgToStringCookie = nullptr;
@@ -740,7 +742,10 @@ FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
// "%diff{compare $ to $|other text}1,2"
// treat it as:
// "compare %1 to %2"
- const char *Pipe = ScanFormat(Argument, Argument + ArgumentLen, '|');
+ const char *ArgumentEnd = Argument + ArgumentLen;
+ const char *Pipe = ScanFormat(Argument, ArgumentEnd, '|');
+ assert(ScanFormat(Pipe + 1, ArgumentEnd, '|') == ArgumentEnd &&
+ "Found too many '|'s in a %diff modifier!");
const char *FirstDollar = ScanFormat(Argument, Pipe, '$');
const char *SecondDollar = ScanFormat(FirstDollar + 1, Pipe, '$');
const char ArgStr1[] = { '%', static_cast<char>('0' + ArgNo) };
@@ -1008,7 +1013,7 @@ PartialDiagnostic::StorageAllocator::StorageAllocator() {
PartialDiagnostic::StorageAllocator::~StorageAllocator() {
// Don't assert if we are in a CrashRecovery context, as this invariant may
// be invalidated during a crash.
- assert((NumFreeListEntries == NumCached ||
- llvm::CrashRecoveryContext::isRecoveringFromCrash()) &&
- "A partial is on the lamb");
+ assert((NumFreeListEntries == NumCached ||
+ llvm::CrashRecoveryContext::isRecoveringFromCrash()) &&
+ "A partial is on the lam");
}
diff --git a/lib/Basic/DiagnosticOptions.cpp b/lib/Basic/DiagnosticOptions.cpp
index f54a0ef4edb2..93c2196ca979 100644
--- a/lib/Basic/DiagnosticOptions.cpp
+++ b/lib/Basic/DiagnosticOptions.cpp
@@ -16,7 +16,7 @@
namespace clang {
-raw_ostream& operator<<(raw_ostream& Out, DiagnosticLevelMask M) {
+raw_ostream &operator<<(raw_ostream &Out, DiagnosticLevelMask M) {
using UT = std::underlying_type<DiagnosticLevelMask>::type;
return Out << static_cast<UT>(M);
}
diff --git a/lib/Basic/FileManager.cpp b/lib/Basic/FileManager.cpp
index ce9b7e1bb48c..50050d0a519b 100644
--- a/lib/Basic/FileManager.cpp
+++ b/lib/Basic/FileManager.cpp
@@ -26,10 +26,13 @@
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
-#include <map>
-#include <set>
+#include <algorithm>
+#include <cassert>
+#include <climits>
+#include <cstdint>
+#include <cstdlib>
#include <string>
-#include <system_error>
+#include <utility>
using namespace clang;
@@ -137,7 +140,7 @@ void FileManager::addAncestorsAsVirtualDirs(StringRef Path) {
// Add the virtual directory to the cache.
auto UDE = llvm::make_unique<DirectoryEntry>();
- UDE->Name = NamedDirEnt.first().data();
+ UDE->Name = NamedDirEnt.first();
NamedDirEnt.second = UDE.get();
VirtualDirectoryEntries.push_back(std::move(UDE));
@@ -182,7 +185,7 @@ const DirectoryEntry *FileManager::getDirectory(StringRef DirName,
// Get the null-terminated directory name as stored as the key of the
// SeenDirEntries map.
- const char *InterndDirName = NamedDirEnt.first().data();
+ StringRef InterndDirName = NamedDirEnt.first();
// Check to see if the directory exists.
FileData Data;
@@ -200,7 +203,7 @@ const DirectoryEntry *FileManager::getDirectory(StringRef DirName,
DirectoryEntry &UDE = UniqueRealDirs[Data.UniqueID];
NamedDirEnt.second = &UDE;
- if (!UDE.getName()) {
+ if (UDE.getName().empty()) {
// We don't have this directory yet, add it. We use the string
// key from the SeenDirEntries map as the string.
UDE.Name = InterndDirName;
@@ -229,7 +232,7 @@ const FileEntry *FileManager::getFile(StringRef Filename, bool openFile,
// Get the null-terminated file name as stored as the key of the
// SeenFileEntries map.
- const char *InterndFileName = NamedFileEnt.first().data();
+ StringRef InterndFileName = NamedFileEnt.first();
// Look up the directory for the file. When looking up something like
// sys/foo.h we'll discover all of the search directories that have a 'sys'
@@ -420,7 +423,7 @@ FileManager::getBufferForFile(const FileEntry *Entry, bool isVolatile,
if (isVolatile)
FileSize = -1;
- const char *Filename = Entry->getName();
+ StringRef Filename = Entry->getName();
// If the file is already open, use the open file descriptor.
if (Entry->File) {
auto Result =
@@ -460,7 +463,7 @@ FileManager::getBufferForFile(StringRef Filename) {
/// if the path points to a virtual file or does not exist, or returns
/// false if it's an existent real file. If FileDescriptor is NULL,
/// do directory look-up instead of file look-up.
-bool FileManager::getStatValue(const char *Path, FileData &Data, bool isFile,
+bool FileManager::getStatValue(StringRef Path, FileData &Data, bool isFile,
std::unique_ptr<vfs::File> *F) {
// FIXME: FileSystemOpts shouldn't be passed in here, all paths should be
// absolute!
@@ -497,7 +500,6 @@ void FileManager::invalidateCache(const FileEntry *Entry) {
UniqueRealFiles.erase(Entry->getUniqueID());
}
-
void FileManager::GetUniqueIDMapping(
SmallVectorImpl<const FileEntry *> &UIDToFiles) const {
UIDToFiles.clear();
@@ -533,7 +535,7 @@ StringRef FileManager::getCanonicalName(const DirectoryEntry *Dir) {
#ifdef LLVM_ON_UNIX
char CanonicalNameBuf[PATH_MAX];
- if (realpath(Dir->getName(), CanonicalNameBuf))
+ if (realpath(Dir->getName().str().c_str(), CanonicalNameBuf))
CanonicalName = StringRef(CanonicalNameBuf).copy(CanonicalNameStorage);
#else
SmallString<256> CanonicalNameBuf(CanonicalName);
diff --git a/lib/Basic/FileSystemStatCache.cpp b/lib/Basic/FileSystemStatCache.cpp
index 187ea37e0c28..799df1d3c3a6 100644
--- a/lib/Basic/FileSystemStatCache.cpp
+++ b/lib/Basic/FileSystemStatCache.cpp
@@ -23,7 +23,7 @@ static void copyStatusToFileData(const vfs::Status &Status,
FileData &Data) {
Data.Name = Status.getName();
Data.Size = Status.getSize();
- Data.ModTime = Status.getLastModificationTime().toEpochTime();
+ Data.ModTime = llvm::sys::toTimeT(Status.getLastModificationTime());
Data.UniqueID = Status.getUniqueID();
Data.IsDirectory = Status.isDirectory();
Data.IsNamedPipe = Status.getType() == llvm::sys::fs::file_type::fifo_file;
@@ -40,7 +40,7 @@ static void copyStatusToFileData(const vfs::Status &Status,
/// success for directories (not files). On a successful file lookup, the
/// implementation can optionally fill in FileDescriptor with a valid
/// descriptor and the client guarantees that it will close it.
-bool FileSystemStatCache::get(const char *Path, FileData &Data, bool isFile,
+bool FileSystemStatCache::get(StringRef Path, FileData &Data, bool isFile,
std::unique_ptr<vfs::File> *F,
FileSystemStatCache *Cache, vfs::FileSystem &FS) {
LookupResult R;
@@ -107,7 +107,7 @@ bool FileSystemStatCache::get(const char *Path, FileData &Data, bool isFile,
}
MemorizeStatCalls::LookupResult
-MemorizeStatCalls::getStat(const char *Path, FileData &Data, bool isFile,
+MemorizeStatCalls::getStat(StringRef Path, FileData &Data, bool isFile,
std::unique_ptr<vfs::File> *F, vfs::FileSystem &FS) {
LookupResult Result = statChained(Path, Data, isFile, F, FS);
diff --git a/lib/Basic/IdentifierTable.cpp b/lib/Basic/IdentifierTable.cpp
index d6ad0f5c9158..af424cd92390 100644
--- a/lib/Basic/IdentifierTable.cpp
+++ b/lib/Basic/IdentifierTable.cpp
@@ -113,7 +113,8 @@ namespace {
KEYOBJC2 = 0x20000,
KEYZVECTOR = 0x40000,
KEYCOROUTINES = 0x80000,
- KEYALL = (0xfffff & ~KEYNOMS18 &
+ KEYMODULES = 0x100000,
+ KEYALL = (0x1fffff & ~KEYNOMS18 &
~KEYNOOPENCL) // KEYNOMS18 and KEYNOOPENCL are used to exclude.
};
@@ -147,9 +148,10 @@ static KeywordStatus getKeywordStatus(const LangOptions &LangOpts,
// We treat bridge casts as objective-C keywords so we can warn on them
// in non-arc mode.
if (LangOpts.ObjC2 && (Flags & KEYARC)) return KS_Enabled;
- if (LangOpts.ConceptsTS && (Flags & KEYCONCEPTS)) return KS_Enabled;
if (LangOpts.ObjC2 && (Flags & KEYOBJC2)) return KS_Enabled;
- if (LangOpts.Coroutines && (Flags & KEYCOROUTINES)) return KS_Enabled;
+ if (LangOpts.ConceptsTS && (Flags & KEYCONCEPTS)) return KS_Enabled;
+ if (LangOpts.CoroutinesTS && (Flags & KEYCOROUTINES)) return KS_Enabled;
+ if (LangOpts.ModulesTS && (Flags & KEYMODULES)) return KS_Enabled;
if (LangOpts.CPlusPlus && (Flags & KEYCXX11)) return KS_Future;
return KS_Disabled;
}
@@ -441,9 +443,11 @@ std::string Selector::getAsString() const {
if (getIdentifierInfoFlag() < MultiArg) {
IdentifierInfo *II = getAsIdentifierInfo();
- // If the number of arguments is 0 then II is guaranteed to not be null.
- if (getNumArgs() == 0)
+ if (getNumArgs() == 0) {
+ assert(II && "If the number of arguments is 0 then II is guaranteed to "
+ "not be null.");
return II->getName();
+ }
if (!II)
return ":";
@@ -619,8 +623,8 @@ Selector SelectorTable::getSelector(unsigned nKeys, IdentifierInfo **IIV) {
// variable size array (for parameter types) at the end of them.
unsigned Size = sizeof(MultiKeywordSelector) + nKeys*sizeof(IdentifierInfo *);
MultiKeywordSelector *SI =
- (MultiKeywordSelector*)SelTabImpl.Allocator.Allocate(Size,
- llvm::alignOf<MultiKeywordSelector>());
+ (MultiKeywordSelector *)SelTabImpl.Allocator.Allocate(
+ Size, alignof(MultiKeywordSelector));
new (SI) MultiKeywordSelector(nKeys, IIV);
SelTabImpl.Table.InsertNode(SI, InsertPos);
return Selector(SI);
diff --git a/lib/Basic/LangOptions.cpp b/lib/Basic/LangOptions.cpp
index 8c0ecd46ad55..ff10a773a97c 100644
--- a/lib/Basic/LangOptions.cpp
+++ b/lib/Basic/LangOptions.cpp
@@ -15,7 +15,8 @@
using namespace clang;
-LangOptions::LangOptions() {
+LangOptions::LangOptions()
+ : IsHeaderFile(false) {
#define LANGOPT(Name, Bits, Default, Description) Name = Default;
#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) set##Name(Default);
#include "clang/Basic/LangOptions.def"
@@ -34,10 +35,10 @@ void LangOptions::resetNonModularOptions() {
SanitizerBlacklistFiles.clear();
CurrentModule.clear();
+ IsHeaderFile = false;
}
-bool LangOptions::isNoBuiltinFunc(const char *Name) const {
- StringRef FuncName(Name);
+bool LangOptions::isNoBuiltinFunc(StringRef FuncName) const {
for (unsigned i = 0, e = NoBuiltinFuncs.size(); i != e; ++i)
if (FuncName.equals(NoBuiltinFuncs[i]))
return true;
diff --git a/lib/Basic/Module.cpp b/lib/Basic/Module.cpp
index 3d1a40db5ea2..80bbc24f3db3 100644
--- a/lib/Basic/Module.cpp
+++ b/lib/Basic/Module.cpp
@@ -33,7 +33,7 @@ Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,
IsExplicit(IsExplicit), IsSystem(false), IsExternC(false),
IsInferred(false), InferSubmodules(false), InferExplicitSubmodules(false),
InferExportWildcard(false), ConfigMacrosExhaustive(false),
- NameVisibility(Hidden) {
+ NoUndeclaredIncludes(false), NameVisibility(Hidden) {
if (Parent) {
if (!Parent->isAvailable())
IsAvailable = false;
@@ -41,6 +41,8 @@ Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,
IsSystem = true;
if (Parent->IsExternC)
IsExternC = true;
+ if (Parent->NoUndeclaredIncludes)
+ NoUndeclaredIncludes = true;
IsMissingRequirement = Parent->IsMissingRequirement;
Parent->SubModuleIndex[Name] = Parent->SubModules.size();
@@ -64,6 +66,8 @@ static bool hasFeature(StringRef Feature, const LangOptions &LangOpts,
.Case("blocks", LangOpts.Blocks)
.Case("cplusplus", LangOpts.CPlusPlus)
.Case("cplusplus11", LangOpts.CPlusPlus11)
+ .Case("freestanding", LangOpts.Freestanding)
+ .Case("gnuinlineasm", LangOpts.GNUAsm)
.Case("objc", LangOpts.ObjC1)
.Case("objc_arc", LangOpts.ObjCAutoRefCount)
.Case("opencl", LangOpts.OpenCL)
@@ -179,6 +183,11 @@ bool Module::directlyUses(const Module *Requested) const {
for (auto *Use : Top->DirectUses)
if (Requested->isSubModuleOf(Use))
return true;
+
+ // Anyone is allowed to use our builtin stddef.h and its accompanying module.
+ if (!Requested->Parent && Requested->Name == "_Builtin_stddef_max_align_t")
+ return true;
+
return false;
}
diff --git a/lib/Basic/OpenMPKinds.cpp b/lib/Basic/OpenMPKinds.cpp
index d1e4779e2c72..4675995ea722 100644
--- a/lib/Basic/OpenMPKinds.cpp
+++ b/lib/Basic/OpenMPKinds.cpp
@@ -610,6 +610,86 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind,
break;
}
break;
+ case OMPD_target_simd:
+ switch (CKind) {
+#define OPENMP_TARGET_SIMD_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_teams_distribute:
+ switch (CKind) {
+#define OPENMP_TEAMS_DISTRIBUTE_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_teams_distribute_simd:
+ switch (CKind) {
+#define OPENMP_TEAMS_DISTRIBUTE_SIMD_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_teams_distribute_parallel_for_simd:
+ switch (CKind) {
+#define OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_teams_distribute_parallel_for:
+ switch (CKind) {
+#define OPENMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_target_teams:
+ switch (CKind) {
+#define OPENMP_TARGET_TEAMS_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_target_teams_distribute:
+ switch (CKind) {
+#define OPENMP_TARGET_TEAMS_DISTRIBUTE_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
+ case OMPD_target_teams_distribute_parallel_for:
+ switch (CKind) {
+#define OPENMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_unknown:
@@ -635,8 +715,13 @@ bool clang::isOpenMPLoopDirective(OpenMPDirectiveKind DKind) {
DKind == OMPD_distribute_parallel_for ||
DKind == OMPD_distribute_parallel_for_simd ||
DKind == OMPD_distribute_simd ||
- DKind == OMPD_target_parallel_for_simd;
- // TODO add next directives.
+ DKind == OMPD_target_parallel_for_simd || DKind == OMPD_target_simd ||
+ DKind == OMPD_teams_distribute ||
+ DKind == OMPD_teams_distribute_simd ||
+ DKind == OMPD_teams_distribute_parallel_for_simd ||
+ DKind == OMPD_teams_distribute_parallel_for ||
+ DKind == OMPD_target_teams_distribute ||
+ DKind == OMPD_target_teams_distribute_parallel_for;
}
bool clang::isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind) {
@@ -647,7 +732,10 @@ bool clang::isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind) {
DKind == OMPD_target_parallel_for ||
DKind == OMPD_distribute_parallel_for ||
DKind == OMPD_distribute_parallel_for_simd ||
- DKind == OMPD_target_parallel_for_simd;
+ DKind == OMPD_target_parallel_for_simd ||
+ DKind == OMPD_teams_distribute_parallel_for_simd ||
+ DKind == OMPD_teams_distribute_parallel_for ||
+ DKind == OMPD_target_teams_distribute_parallel_for;
// TODO add next directives.
}
@@ -661,15 +749,19 @@ bool clang::isOpenMPParallelDirective(OpenMPDirectiveKind DKind) {
DKind == OMPD_target_parallel || DKind == OMPD_target_parallel_for ||
DKind == OMPD_distribute_parallel_for ||
DKind == OMPD_distribute_parallel_for_simd ||
- DKind == OMPD_target_parallel_for_simd;
+ DKind == OMPD_target_parallel_for_simd ||
+ DKind == OMPD_teams_distribute_parallel_for ||
+ DKind == OMPD_teams_distribute_parallel_for_simd ||
+ DKind == OMPD_target_teams_distribute_parallel_for;
// TODO add next directives.
}
bool clang::isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind) {
- // TODO add next directives.
return DKind == OMPD_target || DKind == OMPD_target_parallel ||
DKind == OMPD_target_parallel_for ||
- DKind == OMPD_target_parallel_for_simd;
+ DKind == OMPD_target_parallel_for_simd || DKind == OMPD_target_simd ||
+ DKind == OMPD_target_teams || DKind == OMPD_target_teams_distribute ||
+ DKind == OMPD_target_teams_distribute_parallel_for;
}
bool clang::isOpenMPTargetDataManagementDirective(OpenMPDirectiveKind DKind) {
@@ -677,25 +769,45 @@ bool clang::isOpenMPTargetDataManagementDirective(OpenMPDirectiveKind DKind) {
DKind == OMPD_target_exit_data || DKind == OMPD_target_update;
}
+bool clang::isOpenMPNestingTeamsDirective(OpenMPDirectiveKind DKind) {
+ return DKind == OMPD_teams || DKind == OMPD_teams_distribute ||
+ DKind == OMPD_teams_distribute_simd ||
+ DKind == OMPD_teams_distribute_parallel_for_simd ||
+ DKind == OMPD_teams_distribute_parallel_for;
+}
+
bool clang::isOpenMPTeamsDirective(OpenMPDirectiveKind DKind) {
- return DKind == OMPD_teams; // TODO add next directives.
+ return isOpenMPNestingTeamsDirective(DKind) ||
+ DKind == OMPD_target_teams || DKind == OMPD_target_teams_distribute ||
+ DKind == OMPD_target_teams_distribute_parallel_for;
}
bool clang::isOpenMPSimdDirective(OpenMPDirectiveKind DKind) {
return DKind == OMPD_simd || DKind == OMPD_for_simd ||
DKind == OMPD_parallel_for_simd || DKind == OMPD_taskloop_simd ||
DKind == OMPD_distribute_parallel_for_simd ||
- DKind == OMPD_distribute_simd;
+ DKind == OMPD_distribute_simd || DKind == OMPD_target_simd ||
+ DKind == OMPD_teams_distribute_simd ||
+ DKind == OMPD_teams_distribute_parallel_for_simd;
// TODO add next directives.
}
-bool clang::isOpenMPDistributeDirective(OpenMPDirectiveKind Kind) {
+bool clang::isOpenMPNestingDistributeDirective(OpenMPDirectiveKind Kind) {
return Kind == OMPD_distribute || Kind == OMPD_distribute_parallel_for ||
Kind == OMPD_distribute_parallel_for_simd ||
Kind == OMPD_distribute_simd;
// TODO add next directives.
}
+bool clang::isOpenMPDistributeDirective(OpenMPDirectiveKind Kind) {
+ return isOpenMPNestingDistributeDirective(Kind) ||
+ Kind == OMPD_teams_distribute || Kind == OMPD_teams_distribute_simd ||
+ Kind == OMPD_teams_distribute_parallel_for_simd ||
+ Kind == OMPD_teams_distribute_parallel_for ||
+ Kind == OMPD_target_teams_distribute ||
+ Kind == OMPD_target_teams_distribute_parallel_for;
+}
+
bool clang::isOpenMPPrivate(OpenMPClauseKind Kind) {
return Kind == OMPC_private || Kind == OMPC_firstprivate ||
Kind == OMPC_lastprivate || Kind == OMPC_linear ||
@@ -713,5 +825,10 @@ bool clang::isOpenMPTaskingDirective(OpenMPDirectiveKind Kind) {
bool clang::isOpenMPLoopBoundSharingDirective(OpenMPDirectiveKind Kind) {
return Kind == OMPD_distribute_parallel_for ||
Kind == OMPD_distribute_parallel_for_simd ||
- Kind == OMPD_distribute_simd;
+ Kind == OMPD_distribute_simd || Kind == OMPD_teams_distribute ||
+ Kind == OMPD_teams_distribute_simd ||
+ Kind == OMPD_teams_distribute_parallel_for_simd ||
+ Kind == OMPD_teams_distribute_parallel_for ||
+ Kind == OMPD_target_teams_distribute ||
+ Kind == OMPD_target_teams_distribute_parallel_for;
}
diff --git a/lib/Basic/SourceLocation.cpp b/lib/Basic/SourceLocation.cpp
index d254e8620a96..a58d0465a6f4 100644
--- a/lib/Basic/SourceLocation.cpp
+++ b/lib/Basic/SourceLocation.cpp
@@ -14,7 +14,6 @@
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/PrettyStackTrace.h"
#include "clang/Basic/SourceManager.h"
-#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdio>
using namespace clang;
diff --git a/lib/Basic/SourceManager.cpp b/lib/Basic/SourceManager.cpp
index 1e83b63cf82e..380ca373e69b 100644
--- a/lib/Basic/SourceManager.cpp
+++ b/lib/Basic/SourceManager.cpp
@@ -25,7 +25,6 @@
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cstring>
-#include <string>
using namespace clang;
using namespace SrcMgr;
@@ -387,8 +386,6 @@ SourceManager::~SourceManager() {
ContentCacheAlloc.Deallocate(I->second);
}
}
-
- llvm::DeleteContainerSeconds(MacroArgsCacheMap);
}
void SourceManager::clearIDTables() {
@@ -1438,8 +1435,8 @@ SourceManager::getFileCharacteristic(SourceLocation Loc) const {
/// Return the filename or buffer identifier of the buffer the location is in.
/// Note that this name does not respect \#line directives. Use getPresumedLoc
/// for normal clients.
-const char *SourceManager::getBufferName(SourceLocation Loc,
- bool *Invalid) const {
+StringRef SourceManager::getBufferName(SourceLocation Loc,
+ bool *Invalid) const {
if (isInvalid(Loc, Invalid)) return "<invalid loc>";
return getBuffer(getFileID(Loc), Invalid)->getBufferIdentifier();
@@ -1471,7 +1468,7 @@ PresumedLoc SourceManager::getPresumedLoc(SourceLocation Loc,
// To get the source name, first consult the FileEntry (if one exists)
// before the MemBuffer as this will avoid unnecessarily paging in the
// MemBuffer.
- const char *Filename;
+ StringRef Filename;
if (C->OrigEntry)
Filename = C->OrigEntry->getName();
else
@@ -1514,7 +1511,7 @@ PresumedLoc SourceManager::getPresumedLoc(SourceLocation Loc,
}
}
- return PresumedLoc(Filename, LineNo, ColNo, IncludeLoc);
+ return PresumedLoc(Filename.data(), LineNo, ColNo, IncludeLoc);
}
/// \brief Returns whether the PresumedLoc for a given SourceLocation is
@@ -1785,13 +1782,10 @@ SourceLocation SourceManager::translateLineCol(FileID FID,
/// 0 -> SourceLocation()
/// 100 -> Expanded macro arg location
/// 110 -> SourceLocation()
-void SourceManager::computeMacroArgsCache(MacroArgsMap *&CachePtr,
+void SourceManager::computeMacroArgsCache(MacroArgsMap &MacroArgsCache,
FileID FID) const {
assert(FID.isValid());
- assert(!CachePtr);
- CachePtr = new MacroArgsMap();
- MacroArgsMap &MacroArgsCache = *CachePtr;
// Initially no macro argument chunk is present.
MacroArgsCache.insert(std::make_pair(0, SourceLocation()));
@@ -1941,9 +1935,11 @@ SourceManager::getMacroArgExpandedLocation(SourceLocation Loc) const {
if (FID.isInvalid())
return Loc;
- MacroArgsMap *&MacroArgsCache = MacroArgsCacheMap[FID];
- if (!MacroArgsCache)
- computeMacroArgsCache(MacroArgsCache, FID);
+ std::unique_ptr<MacroArgsMap> &MacroArgsCache = MacroArgsCacheMap[FID];
+ if (!MacroArgsCache) {
+ MacroArgsCache = llvm::make_unique<MacroArgsMap>();
+ computeMacroArgsCache(*MacroArgsCache, FID);
+ }
assert(!MacroArgsCache->empty());
MacroArgsMap::iterator I = MacroArgsCache->upper_bound(Offset);
@@ -2096,10 +2092,10 @@ bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS,
// Clear the lookup cache, it depends on a common location.
IsBeforeInTUCache.clear();
- const char *LB = getBuffer(LOffs.first)->getBufferIdentifier();
- const char *RB = getBuffer(ROffs.first)->getBufferIdentifier();
- bool LIsBuiltins = strcmp("<built-in>", LB) == 0;
- bool RIsBuiltins = strcmp("<built-in>", RB) == 0;
+ StringRef LB = getBuffer(LOffs.first)->getBufferIdentifier();
+ StringRef RB = getBuffer(ROffs.first)->getBufferIdentifier();
+ bool LIsBuiltins = LB == "<built-in>";
+ bool RIsBuiltins = RB == "<built-in>";
// Sort built-in before non-built-in.
if (LIsBuiltins || RIsBuiltins) {
if (LIsBuiltins != RIsBuiltins)
@@ -2108,8 +2104,8 @@ bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS,
// lower IDs come first.
return LOffs.first < ROffs.first;
}
- bool LIsAsm = strcmp("<inline asm>", LB) == 0;
- bool RIsAsm = strcmp("<inline asm>", RB) == 0;
+ bool LIsAsm = LB == "<inline asm>";
+ bool RIsAsm = RB == "<inline asm>";
// Sort assembler after built-ins, but before the rest.
if (LIsAsm || RIsAsm) {
if (LIsAsm != RIsAsm)
@@ -2117,8 +2113,8 @@ bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS,
assert(LOffs.first == ROffs.first);
return false;
}
- bool LIsScratch = strcmp("<scratch space>", LB) == 0;
- bool RIsScratch = strcmp("<scratch space>", RB) == 0;
+ bool LIsScratch = LB == "<scratch space>";
+ bool RIsScratch = RB == "<scratch space>";
// Sort scratch after inline asm, but before the rest.
if (LIsScratch || RIsScratch) {
if (LIsScratch != RIsScratch)
diff --git a/lib/Basic/TargetInfo.cpp b/lib/Basic/TargetInfo.cpp
index 92f658a6a37f..b1b01e5f584f 100644
--- a/lib/Basic/TargetInfo.cpp
+++ b/lib/Basic/TargetInfo.cpp
@@ -27,7 +27,7 @@ static const LangAS::Map DefaultAddrSpaceMap = { 0 };
TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) {
// Set defaults. Defaults are set for a 32-bit RISC platform, like PPC or
// SPARC. These should be overridden by concrete targets as needed.
- BigEndian = true;
+ BigEndian = !T.isLittleEndian();
TLSSupported = true;
NoAsmVariants = false;
HasFloat128 = false;
@@ -39,6 +39,13 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) {
SuitableAlign = 64;
DefaultAlignForAttributeAligned = 128;
MinGlobalAlign = 0;
+ // From the glibc documentation, on GNU systems, malloc guarantees 16-byte
+ // alignment on 64-bit systems and 8-byte alignment on 32-bit systems. See
+ // https://www.gnu.org/software/libc/manual/html_node/Malloc-Examples.html
+ if (T.isGNUEnvironment())
+ NewAlign = Triple.isArch64Bit() ? 128 : Triple.isArch32Bit() ? 64 : 0;
+ else
+ NewAlign = 0; // Infer from basic type alignment.
HalfWidth = 16;
HalfAlign = 16;
FloatWidth = 32;
@@ -70,16 +77,17 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) {
UseZeroLengthBitfieldAlignment = false;
UseExplicitBitFieldAlignment = true;
ZeroLengthBitfieldBoundary = 0;
- HalfFormat = &llvm::APFloat::IEEEhalf;
- FloatFormat = &llvm::APFloat::IEEEsingle;
- DoubleFormat = &llvm::APFloat::IEEEdouble;
- LongDoubleFormat = &llvm::APFloat::IEEEdouble;
- Float128Format = &llvm::APFloat::IEEEquad;
+ HalfFormat = &llvm::APFloat::IEEEhalf();
+ FloatFormat = &llvm::APFloat::IEEEsingle();
+ DoubleFormat = &llvm::APFloat::IEEEdouble();
+ LongDoubleFormat = &llvm::APFloat::IEEEdouble();
+ Float128Format = &llvm::APFloat::IEEEquad();
MCountName = "mcount";
RegParmMax = 0;
SSERegParmMax = 0;
HasAlignMac68kSupport = false;
HasBuiltinMSVaList = false;
+ IsRenderScriptTarget = false;
// Default to no types using fpret.
RealTypeUsesObjCFPRet = 0;
@@ -219,12 +227,12 @@ TargetInfo::RealType TargetInfo::getRealTypeByWidth(unsigned BitWidth) const {
switch (BitWidth) {
case 96:
- if (&getLongDoubleFormat() == &llvm::APFloat::x87DoubleExtended)
+ if (&getLongDoubleFormat() == &llvm::APFloat::x87DoubleExtended())
return LongDouble;
break;
case 128:
- if (&getLongDoubleFormat() == &llvm::APFloat::PPCDoubleDouble ||
- &getLongDoubleFormat() == &llvm::APFloat::IEEEquad)
+ if (&getLongDoubleFormat() == &llvm::APFloat::PPCDoubleDouble() ||
+ &getLongDoubleFormat() == &llvm::APFloat::IEEEquad())
return LongDouble;
if (hasFloat128Type())
return Float128;
@@ -301,12 +309,13 @@ void TargetInfo::adjust(const LangOptions &Opts) {
// to generating illegal code that uses 64bit doubles.
if (DoubleWidth != FloatWidth) {
DoubleWidth = DoubleAlign = 64;
- DoubleFormat = &llvm::APFloat::IEEEdouble;
+ DoubleFormat = &llvm::APFloat::IEEEdouble();
}
LongDoubleWidth = LongDoubleAlign = 128;
- assert(PointerWidth == 32 || PointerWidth == 64);
- bool Is32BitArch = PointerWidth == 32;
+ unsigned MaxPointerWidth = getMaxPointerWidth();
+ assert(MaxPointerWidth == 32 || MaxPointerWidth == 64);
+ bool Is32BitArch = MaxPointerWidth == 32;
SizeType = Is32BitArch ? UnsignedInt : UnsignedLong;
PtrDiffType = Is32BitArch ? SignedInt : SignedLong;
IntPtrType = Is32BitArch ? SignedInt : SignedLong;
@@ -314,10 +323,13 @@ void TargetInfo::adjust(const LangOptions &Opts) {
IntMaxType = SignedLongLong;
Int64Type = SignedLong;
- HalfFormat = &llvm::APFloat::IEEEhalf;
- FloatFormat = &llvm::APFloat::IEEEsingle;
- LongDoubleFormat = &llvm::APFloat::IEEEquad;
+ HalfFormat = &llvm::APFloat::IEEEhalf();
+ FloatFormat = &llvm::APFloat::IEEEsingle();
+ LongDoubleFormat = &llvm::APFloat::IEEEquad();
}
+
+ if (Opts.NewAlignOverride)
+ NewAlign = Opts.NewAlignOverride * getCharWidth();
}
bool TargetInfo::initFeatureMap(
@@ -398,8 +410,8 @@ bool TargetInfo::isValidGCCRegisterName(StringRef Name) const {
return false;
}
-StringRef
-TargetInfo::getNormalizedGCCRegisterName(StringRef Name) const {
+StringRef TargetInfo::getNormalizedGCCRegisterName(StringRef Name,
+ bool ReturnCanonical) const {
assert(isValidGCCRegisterName(Name) && "Invalid register passed in");
// Get rid of any register prefix.
@@ -424,7 +436,7 @@ TargetInfo::getNormalizedGCCRegisterName(StringRef Name) const {
// Make sure the register that the additional name is for is within
// the bounds of the register names from above.
if (AN == Name && ARN.RegNum < Names.size())
- return Name;
+ return ReturnCanonical ? Names[ARN.RegNum] : Name;
}
// Now check aliases.
diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp
index be5d4ad8feda..85a83bca002b 100644
--- a/lib/Basic/Targets.cpp
+++ b/lib/Basic/Targets.cpp
@@ -21,6 +21,7 @@
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Basic/Version.h"
+#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
@@ -464,6 +465,8 @@ protected:
Triple.getEnvironmentVersion(Maj, Min, Rev);
this->PlatformName = "android";
this->PlatformMinVersion = VersionTuple(Maj, Min, Rev);
+ if (Maj)
+ Builder.defineMacro("__ANDROID_API__", Twine(Maj));
}
if (Opts.POSIXThreads)
Builder.defineMacro("_REENTRANT");
@@ -805,8 +808,8 @@ public:
this->SizeType = TargetInfo::UnsignedInt;
this->PtrDiffType = TargetInfo::SignedInt;
this->IntPtrType = TargetInfo::SignedInt;
- // RegParmMax is inherited from the underlying architecture
- this->LongDoubleFormat = &llvm::APFloat::IEEEdouble;
+ // RegParmMax is inherited from the underlying architecture.
+ this->LongDoubleFormat = &llvm::APFloat::IEEEdouble();
if (Triple.getArch() == llvm::Triple::arm) {
// Handled in ARM's setABI().
} else if (Triple.getArch() == llvm::Triple::x86) {
@@ -822,6 +825,28 @@ public:
}
};
+// Fuchsia Target
+template<typename Target>
+class FuchsiaTargetInfo : public OSTargetInfo<Target> {
+protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override {
+ Builder.defineMacro("__Fuchsia__");
+ Builder.defineMacro("__ELF__");
+ if (Opts.POSIXThreads)
+ Builder.defineMacro("_REENTRANT");
+ // Required by the libc++ locale support.
+ if (Opts.CPlusPlus)
+ Builder.defineMacro("_GNU_SOURCE");
+ }
+public:
+ FuchsiaTargetInfo(const llvm::Triple &Triple,
+ const TargetOptions &Opts)
+ : OSTargetInfo<Target>(Triple, Opts) {
+ this->MCountName = "__mcount";
+ }
+};
+
// WebAssembly target
template <typename Target>
class WebAssemblyOSTargetInfo : public OSTargetInfo<Target> {
@@ -869,6 +894,7 @@ class PPCTargetInfo : public TargetInfo {
bool HasHTM;
bool HasBPERMD;
bool HasExtDiv;
+ bool HasP9Vector;
protected:
std::string ABI;
@@ -877,11 +903,10 @@ public:
PPCTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
: TargetInfo(Triple), HasVSX(false), HasP8Vector(false),
HasP8Crypto(false), HasDirectMove(false), HasQPX(false), HasHTM(false),
- HasBPERMD(false), HasExtDiv(false) {
- BigEndian = (Triple.getArch() != llvm::Triple::ppc64le);
+ HasBPERMD(false), HasExtDiv(false), HasP9Vector(false) {
SimdDefaultAlign = 128;
LongDoubleWidth = LongDoubleAlign = 128;
- LongDoubleFormat = &llvm::APFloat::PPCDoubleDouble;
+ LongDoubleFormat = &llvm::APFloat::PPCDoubleDouble();
}
/// \brief Flags for architecture specific defines.
@@ -1121,7 +1146,7 @@ public:
bool useFloat128ManglingForLongDouble() const override {
return LongDoubleWidth == 128 &&
- LongDoubleFormat == &llvm::APFloat::PPCDoubleDouble &&
+ LongDoubleFormat == &llvm::APFloat::PPCDoubleDouble() &&
getTriple().isOSBinFormatELF();
}
};
@@ -1157,6 +1182,8 @@ bool PPCTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
HasHTM = true;
} else if (Feature == "+float128") {
HasFloat128 = true;
+ } else if (Feature == "+power9-vector") {
+ HasP9Vector = true;
}
// TODO: Finish this list and add an assert that we've handled them
// all.
@@ -1326,6 +1353,8 @@ void PPCTargetInfo::getTargetDefines(const LangOptions &Opts,
Builder.defineMacro("__HTM__");
if (HasFloat128)
Builder.defineMacro("__FLOAT128__");
+ if (HasP9Vector)
+ Builder.defineMacro("__POWER9_VECTOR__");
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
@@ -1355,8 +1384,12 @@ void PPCTargetInfo::getTargetDefines(const LangOptions &Opts,
}
// Handle explicit options being passed to the compiler here: if we've
-// explicitly turned off vsx and turned on power8-vector or direct-move then
-// go ahead and error since the customer has expressed a somewhat incompatible
+// explicitly turned off vsx and turned on any of:
+// - power8-vector
+// - direct-move
+// - float128
+// - power9-vector
+// then go ahead and error since the customer has expressed an incompatible
// set of options.
static bool ppcUserFeaturesCheck(DiagnosticsEngine &Diags,
const std::vector<std::string> &FeaturesVec) {
@@ -1383,6 +1416,13 @@ static bool ppcUserFeaturesCheck(DiagnosticsEngine &Diags,
<< "-mno-vsx";
return false;
}
+
+ if (std::find(FeaturesVec.begin(), FeaturesVec.end(), "+power9-vector") !=
+ FeaturesVec.end()) {
+ Diags.Report(diag::err_opt_not_valid_with_opt) << "-mpower9-vector"
+ << "-mno-vsx";
+ return false;
+ }
}
return true;
@@ -1407,6 +1447,7 @@ bool PPCTargetInfo::initFeatureMap(
.Default(false);
Features["qpx"] = (CPU == "a2q");
+ Features["power9-vector"] = (CPU == "pwr9");
Features["crypto"] = llvm::StringSwitch<bool>(CPU)
.Case("ppc64le", true)
.Case("pwr9", true)
@@ -1459,6 +1500,7 @@ bool PPCTargetInfo::hasFeature(StringRef Feature) const {
.Case("bpermd", HasBPERMD)
.Case("extdiv", HasExtDiv)
.Case("float128", HasFloat128)
+ .Case("power9-vector", HasP9Vector)
.Default(false);
}
@@ -1468,19 +1510,21 @@ void PPCTargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features,
// as well. Do the inverse if we're disabling vsx. We'll diagnose any user
// incompatible options.
if (Enabled) {
- if (Name == "direct-move") {
- Features[Name] = Features["vsx"] = true;
- } else if (Name == "power8-vector") {
- Features[Name] = Features["vsx"] = true;
- } else if (Name == "float128") {
+ if (Name == "direct-move" ||
+ Name == "power8-vector" ||
+ Name == "float128" ||
+ Name == "power9-vector") {
+ // power9-vector is really a superset of power8-vector so encode that.
Features[Name] = Features["vsx"] = true;
+ if (Name == "power9-vector")
+ Features["power8-vector"] = true;
} else {
Features[Name] = true;
}
} else {
if (Name == "vsx") {
Features[Name] = Features["direct-move"] = Features["power8-vector"] =
- Features["float128"] = false;
+ Features["float128"] = Features["power9-vector"] = false;
} else {
Features[Name] = false;
}
@@ -1606,7 +1650,7 @@ public:
if (getTriple().getOS() == llvm::Triple::FreeBSD) {
LongDoubleWidth = LongDoubleAlign = 64;
- LongDoubleFormat = &llvm::APFloat::IEEEdouble;
+ LongDoubleFormat = &llvm::APFloat::IEEEdouble();
}
// PPC32 supports atomics up to 4 bytes.
@@ -1640,7 +1684,7 @@ public:
switch (getTriple().getOS()) {
case llvm::Triple::FreeBSD:
LongDoubleWidth = LongDoubleAlign = 64;
- LongDoubleFormat = &llvm::APFloat::IEEEdouble;
+ LongDoubleFormat = &llvm::APFloat::IEEEdouble();
break;
case llvm::Triple::NetBSD:
IntMaxType = SignedLongLong;
@@ -1711,7 +1755,6 @@ class NVPTXTargetInfo : public TargetInfo {
public:
NVPTXTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: TargetInfo(Triple) {
- BigEndian = false;
TLSSupported = false;
LongWidth = LongAlign = 64;
AddrSpaceMap = &NVPTXAddrSpaceMap;
@@ -1749,6 +1792,7 @@ public:
LongLongWidth = HostTarget->getLongLongWidth();
LongLongAlign = HostTarget->getLongLongAlign();
MinGlobalAlign = HostTarget->getMinGlobalAlign();
+ NewAlign = HostTarget->getNewAlign();
DefaultAlignForAttributeAligned =
HostTarget->getDefaultAlignForAttributeAligned();
SizeType = HostTarget->getSizeType();
@@ -1769,6 +1813,12 @@ public:
UseExplicitBitFieldAlignment = HostTarget->useExplicitBitFieldAlignment();
ZeroLengthBitfieldBoundary = HostTarget->getZeroLengthBitfieldBoundary();
+ // This is a bit of a lie, but it controls __GCC_ATOMIC_XXX_LOCK_FREE, and
+ // we need those macros to be identical on host and device, because (among
+ // other things) they affect which standard library classes are defined, and
+ // we need all classes to be defined on both the host and device.
+ MaxAtomicInlineWidth = HostTarget->getMaxAtomicInlineWidth();
+
// Properties intentionally not copied from host:
// - LargeArrayMinWidth, LargeArrayAlign: Not visible across the
// host/device boundary.
@@ -1825,8 +1875,19 @@ public:
return llvm::makeArrayRef(BuiltinInfo,
clang::NVPTX::LastTSBuiltin - Builtin::FirstTSBuiltin);
}
+ bool
+ initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
+ StringRef CPU,
+ const std::vector<std::string> &FeaturesVec) const override {
+ Features["satom"] = GPU >= CudaArch::SM_60;
+ return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
+ }
+
bool hasFeature(StringRef Feature) const override {
- return Feature == "ptx" || Feature == "nvptx";
+ return llvm::StringSwitch<bool>(Feature)
+ .Cases("ptx", "nvptx", true)
+ .Case("satom", GPU >= CudaArch::SM_60) // Atomics w/ scope.
+ .Default(false);
}
ArrayRef<const char *> getGCCRegNames() const override;
@@ -1863,16 +1924,16 @@ public:
}
void setSupportedOpenCLOpts() override {
auto &Opts = getSupportedOpenCLOpts();
- Opts.cl_clang_storage_class_specifiers = 1;
- Opts.cl_khr_gl_sharing = 1;
- Opts.cl_khr_icd = 1;
+ Opts.support("cl_clang_storage_class_specifiers");
+ Opts.support("cl_khr_gl_sharing");
+ Opts.support("cl_khr_icd");
- Opts.cl_khr_fp64 = 1;
- Opts.cl_khr_byte_addressable_store = 1;
- Opts.cl_khr_global_int32_base_atomics = 1;
- Opts.cl_khr_global_int32_extended_atomics = 1;
- Opts.cl_khr_local_int32_base_atomics = 1;
- Opts.cl_khr_local_int32_extended_atomics = 1;
+ Opts.support("cl_khr_fp64");
+ Opts.support("cl_khr_byte_addressable_store");
+ Opts.support("cl_khr_global_int32_base_atomics");
+ Opts.support("cl_khr_global_int32_extended_atomics");
+ Opts.support("cl_khr_local_int32_base_atomics");
+ Opts.support("cl_khr_local_int32_extended_atomics");
}
};
@@ -1881,6 +1942,8 @@ const Builtin::Info NVPTXTargetInfo::BuiltinInfo[] = {
{ #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr },
#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
{ #ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr },
+#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
+ { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE },
#include "clang/Basic/BuiltinsNVPTX.def"
};
@@ -1952,26 +2015,28 @@ class AMDGPUTargetInfo final : public TargetInfo {
GK_EVERGREEN_DOUBLE_OPS,
GK_NORTHERN_ISLANDS,
GK_CAYMAN,
- GK_SOUTHERN_ISLANDS,
- GK_SEA_ISLANDS,
- GK_VOLCANIC_ISLANDS
+ GK_GFX6,
+ GK_GFX7,
+ GK_GFX8
} GPU;
bool hasFP64:1;
bool hasFMAF:1;
bool hasLDEXPF:1;
+ bool hasFullSpeedFP32Denorms:1;
static bool isAMDGCN(const llvm::Triple &TT) {
return TT.getArch() == llvm::Triple::amdgcn;
}
public:
- AMDGPUTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
+ AMDGPUTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: TargetInfo(Triple) ,
- GPU(isAMDGCN(Triple) ? GK_SOUTHERN_ISLANDS : GK_R600),
+ GPU(isAMDGCN(Triple) ? GK_GFX6 : GK_R600),
hasFP64(false),
hasFMAF(false),
- hasLDEXPF(false) {
+ hasLDEXPF(false),
+ hasFullSpeedFP32Denorms(false){
if (getTriple().getArch() == llvm::Triple::amdgcn) {
hasFP64 = true;
hasFMAF = true;
@@ -1999,6 +2064,10 @@ public:
}
}
+ uint64_t getMaxPointerWidth() const override {
+ return getTriple().getArch() == llvm::Triple::amdgcn ? 64 : 32;
+ }
+
const char * getClobbers() const override {
return "";
}
@@ -2025,6 +2094,24 @@ public:
DiagnosticsEngine &Diags, StringRef CPU,
const std::vector<std::string> &FeatureVec) const override;
+ void adjustTargetOptions(const CodeGenOptions &CGOpts,
+ TargetOptions &TargetOpts) const override {
+ bool hasFP32Denormals = false;
+ bool hasFP64Denormals = false;
+ for (auto &I : TargetOpts.FeaturesAsWritten) {
+ if (I == "+fp32-denormals" || I == "-fp32-denormals")
+ hasFP32Denormals = true;
+ if (I == "+fp64-denormals" || I == "-fp64-denormals")
+ hasFP64Denormals = true;
+ }
+ if (!hasFP32Denormals)
+ TargetOpts.Features.push_back((Twine(hasFullSpeedFP32Denorms &&
+ !CGOpts.FlushDenorm ? '+' : '-') + Twine("fp32-denormals")).str());
+ // Always do not flush fp64 denorms.
+ if (!hasFP64Denormals && hasFP64)
+ TargetOpts.Features.push_back("+fp64-denormals");
+ }
+
ArrayRef<Builtin::Info> getTargetBuiltins() const override {
return llvm::makeArrayRef(BuiltinInfo,
clang::AMDGPU::LastTSBuiltin - Builtin::FirstTSBuiltin);
@@ -2081,23 +2168,32 @@ public:
static GPUKind parseAMDGCNName(StringRef Name) {
return llvm::StringSwitch<GPUKind>(Name)
- .Case("tahiti", GK_SOUTHERN_ISLANDS)
- .Case("pitcairn", GK_SOUTHERN_ISLANDS)
- .Case("verde", GK_SOUTHERN_ISLANDS)
- .Case("oland", GK_SOUTHERN_ISLANDS)
- .Case("hainan", GK_SOUTHERN_ISLANDS)
- .Case("bonaire", GK_SEA_ISLANDS)
- .Case("kabini", GK_SEA_ISLANDS)
- .Case("kaveri", GK_SEA_ISLANDS)
- .Case("hawaii", GK_SEA_ISLANDS)
- .Case("mullins", GK_SEA_ISLANDS)
- .Case("tonga", GK_VOLCANIC_ISLANDS)
- .Case("iceland", GK_VOLCANIC_ISLANDS)
- .Case("carrizo", GK_VOLCANIC_ISLANDS)
- .Case("fiji", GK_VOLCANIC_ISLANDS)
- .Case("stoney", GK_VOLCANIC_ISLANDS)
- .Case("polaris10", GK_VOLCANIC_ISLANDS)
- .Case("polaris11", GK_VOLCANIC_ISLANDS)
+ .Case("tahiti", GK_GFX6)
+ .Case("pitcairn", GK_GFX6)
+ .Case("verde", GK_GFX6)
+ .Case("oland", GK_GFX6)
+ .Case("hainan", GK_GFX6)
+ .Case("bonaire", GK_GFX7)
+ .Case("kabini", GK_GFX7)
+ .Case("kaveri", GK_GFX7)
+ .Case("hawaii", GK_GFX7)
+ .Case("mullins", GK_GFX7)
+ .Case("gfx700", GK_GFX7)
+ .Case("gfx701", GK_GFX7)
+ .Case("gfx702", GK_GFX7)
+ .Case("tonga", GK_GFX8)
+ .Case("iceland", GK_GFX8)
+ .Case("carrizo", GK_GFX8)
+ .Case("fiji", GK_GFX8)
+ .Case("stoney", GK_GFX8)
+ .Case("polaris10", GK_GFX8)
+ .Case("polaris11", GK_GFX8)
+ .Case("gfx800", GK_GFX8)
+ .Case("gfx801", GK_GFX8)
+ .Case("gfx802", GK_GFX8)
+ .Case("gfx803", GK_GFX8)
+ .Case("gfx804", GK_GFX8)
+ .Case("gfx810", GK_GFX8)
.Default(GK_NONE);
}
@@ -2112,26 +2208,34 @@ public:
void setSupportedOpenCLOpts() override {
auto &Opts = getSupportedOpenCLOpts();
- Opts.cl_clang_storage_class_specifiers = 1;
- Opts.cl_khr_icd = 1;
+ Opts.support("cl_clang_storage_class_specifiers");
+ Opts.support("cl_khr_icd");
if (hasFP64)
- Opts.cl_khr_fp64 = 1;
+ Opts.support("cl_khr_fp64");
if (GPU >= GK_EVERGREEN) {
- Opts.cl_khr_byte_addressable_store = 1;
- Opts.cl_khr_global_int32_base_atomics = 1;
- Opts.cl_khr_global_int32_extended_atomics = 1;
- Opts.cl_khr_local_int32_base_atomics = 1;
- Opts.cl_khr_local_int32_extended_atomics = 1;
+ 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_SOUTHERN_ISLANDS) {
- Opts.cl_khr_fp16 = 1;
- Opts.cl_khr_int64_base_atomics = 1;
- Opts.cl_khr_int64_extended_atomics = 1;
- Opts.cl_khr_3d_image_writes = 1;
+ if (GPU >= GK_GFX6) {
+ Opts.support("cl_khr_fp16");
+ Opts.support("cl_khr_int64_base_atomics");
+ Opts.support("cl_khr_int64_extended_atomics");
+ Opts.support("cl_khr_mipmap_image");
+ Opts.support("cl_khr_subgroups");
+ Opts.support("cl_khr_3d_image_writes");
+ Opts.support("cl_amd_media_ops");
+ Opts.support("cl_amd_media_ops2");
}
}
+ LangAS::ID getOpenCLImageAddrSpace() const override {
+ return LangAS::opencl_constant;
+ }
+
CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
switch (CC) {
default:
@@ -2141,6 +2245,13 @@ public:
return CCCR_OK;
}
}
+
+ // In amdgcn target the null pointer in global, constant, and generic
+ // address space has value 0 but in private and local address space has
+ // value ~0.
+ uint64_t getNullPointerValue(unsigned AS) const override {
+ return AS != LangAS::opencl_local && AS != 0 ? 0 : ~0;
+ }
};
const Builtin::Info AMDGPUTargetInfo::BuiltinInfo[] = {
@@ -2218,11 +2329,11 @@ bool AMDGPUTargetInfo::initFeatureMap(
CPU = "tahiti";
switch (parseAMDGCNName(CPU)) {
- case GK_SOUTHERN_ISLANDS:
- case GK_SEA_ISLANDS:
+ case GK_GFX6:
+ case GK_GFX7:
break;
- case GK_VOLCANIC_ISLANDS:
+ case GK_GFX8:
Features["s-memrealtime"] = true;
Features["16-bit-insts"] = true;
break;
@@ -2258,17 +2369,25 @@ bool AMDGPUTargetInfo::initFeatureMap(
return TargetInfo::initFeatureMap(Features, Diags, CPU, FeatureVec);
}
-// Namespace for x86 abstract base class
-const Builtin::Info BuiltinInfo[] = {
+const Builtin::Info BuiltinInfoX86[] = {
#define BUILTIN(ID, TYPE, ATTRS) \
{ #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr },
-#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
- { #ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr },
#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
{ #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE },
+#define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE) \
+ { #ID, TYPE, ATTRS, HEADER, LANGS, FEATURE },
#include "clang/Basic/BuiltinsX86.def"
+
+#define BUILTIN(ID, TYPE, ATTRS) \
+ { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr },
+#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
+ { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE },
+#define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE) \
+ { #ID, TYPE, ATTRS, HEADER, LANGS, FEATURE },
+#include "clang/Basic/BuiltinsX86_64.def"
};
+
static const char* const GCCRegNames[] = {
"ax", "dx", "cx", "bx", "si", "di", "bp", "sp",
"st", "st(1)", "st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)",
@@ -2287,6 +2406,7 @@ static const char* const GCCRegNames[] = {
"zmm8", "zmm9", "zmm10", "zmm11", "zmm12", "zmm13", "zmm14", "zmm15",
"zmm16", "zmm17", "zmm18", "zmm19", "zmm20", "zmm21", "zmm22", "zmm23",
"zmm24", "zmm25", "zmm26", "zmm27", "zmm28", "zmm29", "zmm30", "zmm31",
+ "k0", "k1", "k2", "k3", "k4", "k5", "k6", "k7",
};
const TargetInfo::AddlRegName AddlRegNames[] = {
@@ -2626,17 +2746,12 @@ class X86TargetInfo : public TargetInfo {
public:
X86TargetInfo(const llvm::Triple &Triple, const TargetOptions &)
: TargetInfo(Triple) {
- BigEndian = false;
- LongDoubleFormat = &llvm::APFloat::x87DoubleExtended;
+ LongDoubleFormat = &llvm::APFloat::x87DoubleExtended();
}
unsigned getFloatEvalMethod() const override {
// X87 evaluates with 80 bits "long double" precision.
return SSELevel == NoSSE ? 2 : 0;
}
- ArrayRef<Builtin::Info> getTargetBuiltins() const override {
- return llvm::makeArrayRef(BuiltinInfo,
- clang::X86::LastTSBuiltin-Builtin::FirstTSBuiltin);
- }
ArrayRef<const char *> getGCCRegNames() const override {
return llvm::makeArrayRef(GCCRegNames);
}
@@ -2674,6 +2789,40 @@ public:
const char *getClobbers() const override {
return "~{dirflag},~{fpsr},~{flags}";
}
+
+ StringRef getConstraintRegister(const StringRef &Constraint,
+ const StringRef &Expression) const override {
+ StringRef::iterator I, E;
+ for (I = Constraint.begin(), E = Constraint.end(); I != E; ++I) {
+ if (isalpha(*I))
+ break;
+ }
+ if (I == E)
+ return "";
+ switch (*I) {
+ // For the register constraints, return the matching register name
+ case 'a':
+ return "ax";
+ case 'b':
+ return "bx";
+ case 'c':
+ return "cx";
+ case 'd':
+ return "dx";
+ case 'S':
+ return "si";
+ case 'D':
+ return "di";
+ // In case the constraint is 'r' we need to return Expression
+ case 'r':
+ return Expression;
+ default:
+ // Default value if there is no constraint for the register
+ return "";
+ }
+ return "";
+ }
+
void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override;
static void setSSELevel(llvm::StringMap<bool> &Features, X86SSEEnum Level,
@@ -2797,6 +2946,7 @@ public:
case CC_X86FastCall:
case CC_X86StdCall:
case CC_X86VectorCall:
+ case CC_X86RegCall:
case CC_C:
case CC_Swift:
case CC_X86Pascal:
@@ -2816,7 +2966,7 @@ public:
}
void setSupportedOpenCLOpts() override {
- getSupportedOpenCLOpts().setAll();
+ getSupportedOpenCLOpts().supportAll();
}
};
@@ -3244,6 +3394,12 @@ void X86TargetInfo::setFeatureEnabledImpl(llvm::StringMap<bool> &Features,
Name == "avx512vbmi" || Name == "avx512ifma") {
if (Enabled)
setSSELevel(Features, AVX512F, Enabled);
+ // Enable BWI instruction if VBMI is being enabled.
+ if (Name == "avx512vbmi" && Enabled)
+ Features["avx512bw"] = true;
+ // Also disable VBMI if BWI is being disabled.
+ if (Name == "avx512bw" && !Enabled)
+ Features["avx512vbmi"] = false;
} else if (Name == "fma") {
if (Enabled)
setSSELevel(Features, AVX, Enabled);
@@ -3891,6 +4047,7 @@ X86TargetInfo::validateAsmConstraint(const char *&Name,
case 't': // Any SSE register, when SSE2 is enabled.
case 'i': // Any SSE register, when SSE2 and inter-unit moves enabled.
case 'm': // Any MMX register, when inter-unit moves enabled.
+ case 'k': // AVX512 arch mask registers: k1-k7.
Info.setAllowsRegister();
return true;
}
@@ -3911,7 +4068,10 @@ X86TargetInfo::validateAsmConstraint(const char *&Name,
case 'u': // Second from top of floating point stack.
case 'q': // Any register accessible as [r]l: a, b, c, and d.
case 'y': // Any MMX register.
+ case 'v': // Any {X,Y,Z}MM register (Arch & context dependent)
case 'x': // Any SSE register.
+ case 'k': // Any AVX512 mask register (same as Yk, additionaly allows k0
+ // for intermideate k reg operations).
case 'Q': // Any register accessible as [r]h: a, b, c, and d.
case 'R': // "Legacy" registers: ax, bx, cx, dx, di, si, sp, bp.
case 'l': // "Index" registers: any general register that can be used as an
@@ -3945,12 +4105,15 @@ bool X86TargetInfo::validateOperandSize(StringRef Constraint,
unsigned Size) const {
switch (Constraint[0]) {
default: break;
+ case 'k':
+ // Registers k0-k7 (AVX512) size limit is 64 bit.
case 'y':
return Size <= 64;
case 'f':
case 't':
case 'u':
return Size <= 128;
+ case 'v':
case 'x':
if (SSELevel >= AVX512F)
// 512-bit zmm registers can be used if target supports AVX512F.
@@ -3965,6 +4128,7 @@ bool X86TargetInfo::validateOperandSize(StringRef Constraint,
default: break;
case 'm':
// 'Ym' is synonymous with 'y'.
+ case 'k':
return Size <= 64;
case 'i':
case 't':
@@ -3996,6 +4160,20 @@ X86TargetInfo::convertConstraint(const char *&Constraint) const {
return std::string("{st}");
case 'u': // second from top of floating point stack.
return std::string("{st(1)}"); // second from top of floating point stack.
+ case 'Y':
+ switch (Constraint[1]) {
+ default:
+ // Break from inner switch and fall through (copy single char),
+ // continue parsing after copying the current constraint into
+ // the return string.
+ break;
+ case 'k':
+ // "^" hints llvm that this is a 2 letter constraint.
+ // "Constraint++" is used to promote the string iterator
+ // to the next constraint.
+ return std::string("^") + std::string(Constraint++, 2);
+ }
+ LLVM_FALLTHROUGH;
default:
return std::string(1, *Constraint);
}
@@ -4055,6 +4233,10 @@ public:
return X86TargetInfo::validateOperandSize(Constraint, Size);
}
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override {
+ return llvm::makeArrayRef(BuiltinInfoX86, clang::X86::LastX86CommonBuiltin -
+ Builtin::FirstTSBuiltin + 1);
+ }
};
class NetBSDI386TargetInfo : public NetBSDTargetInfo<X86_32TargetInfo> {
@@ -4149,7 +4331,7 @@ public:
const TargetOptions &Opts)
: WindowsX86_32TargetInfo(Triple, Opts) {
LongDoubleWidth = LongDoubleAlign = 64;
- LongDoubleFormat = &llvm::APFloat::IEEEdouble;
+ LongDoubleFormat = &llvm::APFloat::IEEEdouble();
}
void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override {
@@ -4248,7 +4430,7 @@ public:
MCUX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: X86_32TargetInfo(Triple, Opts) {
LongDoubleWidth = 64;
- LongDoubleFormat = &llvm::APFloat::IEEEdouble;
+ LongDoubleFormat = &llvm::APFloat::IEEEdouble();
resetDataLayout("e-m:e-p:32:32-i64:32-f64:32-f128:32-n8:16:32-a:0:32-S32");
WIntType = UnsignedInt;
}
@@ -4380,6 +4562,7 @@ public:
case CC_X86_64Win64:
case CC_PreserveMost:
case CC_PreserveAll:
+ case CC_X86RegCall:
return CCCR_OK;
default:
return CCCR_Warning;
@@ -4410,6 +4593,10 @@ public:
return X86TargetInfo::validateGlobalRegisterVariable(RegName, RegSize,
HasSizeMismatch);
}
+ ArrayRef<Builtin::Info> getTargetBuiltins() const override {
+ return llvm::makeArrayRef(BuiltinInfoX86,
+ X86::LastTSBuiltin - Builtin::FirstTSBuiltin);
+ }
};
// x86-64 Windows target
@@ -4447,6 +4634,8 @@ public:
case CC_X86VectorCall:
case CC_IntelOclBicc:
case CC_X86_64SysV:
+ case CC_Swift:
+ case CC_X86RegCall:
return CCCR_OK;
default:
return CCCR_Warning;
@@ -4461,7 +4650,7 @@ public:
const TargetOptions &Opts)
: WindowsX86_64TargetInfo(Triple, Opts) {
LongDoubleWidth = LongDoubleAlign = 64;
- LongDoubleFormat = &llvm::APFloat::IEEEdouble;
+ LongDoubleFormat = &llvm::APFloat::IEEEdouble();
}
void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override {
@@ -4480,7 +4669,7 @@ public:
// Mingw64 rounds long double size and alignment up to 16 bytes, but sticks
// with x86 FP ops. Weird.
LongDoubleWidth = LongDoubleAlign = 128;
- LongDoubleFormat = &llvm::APFloat::x87DoubleExtended;
+ LongDoubleFormat = &llvm::APFloat::x87DoubleExtended();
}
void getTargetDefines(const LangOptions &Opts,
@@ -4641,8 +4830,10 @@ class ARMTargetInfo : public TargetInfo {
DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 64;
const llvm::Triple &T = getTriple();
- // size_t is unsigned long on MachO-derived environments, NetBSD and Bitrig.
+ // size_t is unsigned long on MachO-derived environments, NetBSD,
+ // OpenBSD and Bitrig.
if (T.isOSBinFormatMachO() || T.getOS() == llvm::Triple::NetBSD ||
+ T.getOS() == llvm::Triple::OpenBSD ||
T.getOS() == llvm::Triple::Bitrig)
SizeType = UnsignedLong;
else
@@ -4650,6 +4841,7 @@ class ARMTargetInfo : public TargetInfo {
switch (T.getOS()) {
case llvm::Triple::NetBSD:
+ case llvm::Triple::OpenBSD:
WCharType = SignedInt;
break;
case llvm::Triple::Win32:
@@ -4824,6 +5016,8 @@ class ARMTargetInfo : public TargetInfo {
return "8M_BASE";
case llvm::ARM::AK_ARMV8MMainline:
return "8M_MAIN";
+ case llvm::ARM::AK_ARMV8R:
+ return "8R";
}
}
@@ -4841,14 +5035,13 @@ class ARMTargetInfo : public TargetInfo {
}
public:
- ARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts,
- bool IsBigEndian)
+ ARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: TargetInfo(Triple), FPMath(FP_Default), IsAAPCS(true), LDREX(0),
HW_FP(0) {
- BigEndian = IsBigEndian;
switch (getTriple().getOS()) {
case llvm::Triple::NetBSD:
+ case llvm::Triple::OpenBSD:
PtrDiffType = SignedLong;
break;
default:
@@ -4871,7 +5064,7 @@ public:
// the frontend matches that.
if (Triple.getEnvironment() == llvm::Triple::EABI ||
Triple.getOS() == llvm::Triple::UnknownOS ||
- StringRef(CPU).startswith("cortex-m")) {
+ ArchProfile == llvm::ARM::PK_M) {
setABI("aapcs");
} else if (Triple.isWatchABI()) {
setABI("aapcs16");
@@ -4951,7 +5144,7 @@ public:
StringRef CPU,
const std::vector<std::string> &FeaturesVec) const override {
- std::vector<const char*> TargetFeatures;
+ std::vector<StringRef> TargetFeatures;
unsigned Arch = llvm::ARM::parseArch(getTriple().getArchName());
// get default FPU features
@@ -4962,9 +5155,9 @@ public:
unsigned Extensions = llvm::ARM::getDefaultExtensions(CPU, Arch);
llvm::ARM::getExtensionFeatures(Extensions, TargetFeatures);
- for (const char *Feature : TargetFeatures)
+ for (auto Feature : TargetFeatures)
if (Feature[0] == '+')
- Features[Feature+1] = true;
+ Features[Feature.drop_front(1)] = true;
return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
}
@@ -5200,7 +5393,7 @@ public:
if (SoftFloat)
Builder.defineMacro("__SOFTFP__");
- if (CPU == "xscale")
+ if (ArchKind == llvm::ARM::AK_XSCALE)
Builder.defineMacro("__XSCALE__");
if (isThumb()) {
@@ -5232,6 +5425,8 @@ public:
Builder.defineMacro("__ARM_VFPV3__");
if (FPU & VFP4FPU)
Builder.defineMacro("__ARM_VFPV4__");
+ if (FPU & FPARMV8)
+ Builder.defineMacro("__ARM_FPV5__");
}
// This only gets set when Neon instructions are actually available, unlike
@@ -5479,13 +5674,15 @@ const Builtin::Info ARMTargetInfo::BuiltinInfo[] = {
{ #ID, TYPE, ATTRS, nullptr, LANG, nullptr },
#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
{ #ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr },
+#define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE) \
+ { #ID, TYPE, ATTRS, HEADER, LANGS, FEATURE },
#include "clang/Basic/BuiltinsARM.def"
};
class ARMleTargetInfo : public ARMTargetInfo {
public:
ARMleTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : ARMTargetInfo(Triple, Opts, /*BigEndian=*/false) {}
+ : ARMTargetInfo(Triple, Opts) {}
void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override {
Builder.defineMacro("__ARMEL__");
@@ -5496,7 +5693,7 @@ public:
class ARMbeTargetInfo : public ARMTargetInfo {
public:
ARMbeTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
- : ARMTargetInfo(Triple, Opts, /*BigEndian=*/true) {}
+ : ARMTargetInfo(Triple, Opts) {}
void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override {
Builder.defineMacro("__ARMEB__");
@@ -5697,7 +5894,7 @@ public:
MaxAtomicPromoteWidth = 128;
LongDoubleWidth = LongDoubleAlign = SuitableAlign = 128;
- LongDoubleFormat = &llvm::APFloat::IEEEquad;
+ LongDoubleFormat = &llvm::APFloat::IEEEquad();
// {} in inline assembly are neon specifiers, not assembly variant
// specifiers.
@@ -5728,16 +5925,9 @@ public:
}
bool setCPU(const std::string &Name) override {
- bool CPUKnown = llvm::StringSwitch<bool>(Name)
- .Case("generic", true)
- .Cases("cortex-a53", "cortex-a57", "cortex-a72",
- "cortex-a35", "exynos-m1", true)
- .Case("cortex-a73", true)
- .Case("cyclone", true)
- .Case("kryo", true)
- .Case("vulcan", true)
- .Default(false);
- return CPUKnown;
+ return Name == "generic" ||
+ llvm::AArch64::parseCPUArch(Name) !=
+ static_cast<unsigned>(llvm::AArch64::ArchKind::AK_INVALID);
}
void getTargetDefines(const LangOptions &Opts,
@@ -6014,7 +6204,6 @@ class AArch64leTargetInfo : public AArch64TargetInfo {
public:
AArch64leTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: AArch64TargetInfo(Triple, Opts) {
- BigEndian = false;
}
void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override {
@@ -6064,7 +6253,7 @@ public:
UseSignedCharForObjCBool = false;
LongDoubleWidth = LongDoubleAlign = SuitableAlign = 64;
- LongDoubleFormat = &llvm::APFloat::IEEEdouble;
+ LongDoubleFormat = &llvm::APFloat::IEEEdouble();
TheCXXABI.set(TargetCXXABI::iOS64);
}
@@ -6081,11 +6270,11 @@ class HexagonTargetInfo : public TargetInfo {
static const TargetInfo::GCCRegAlias GCCRegAliases[];
std::string CPU;
bool HasHVX, HasHVXDouble;
+ bool UseLongCalls;
public:
HexagonTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
: TargetInfo(Triple) {
- BigEndian = false;
// Specify the vector alignment explicitly. For v512x1, the calculated
// alignment would be 512*alignment(i1), which is 512 bytes, instead of
// the required minimum of 64 bytes.
@@ -6105,6 +6294,7 @@ public:
UseBitFieldTypeAlignment = true;
ZeroLengthBitfieldBoundary = 32;
HasHVX = HasHVXDouble = false;
+ UseLongCalls = false;
}
ArrayRef<Builtin::Info> getTargetBuiltins() const override {
@@ -6139,6 +6329,7 @@ public:
.Case("hexagon", true)
.Case("hvx", HasHVX)
.Case("hvx-double", HasHVXDouble)
+ .Case("long-calls", UseLongCalls)
.Default(false);
}
@@ -6149,6 +6340,9 @@ public:
bool handleTargetFeatures(std::vector<std::string> &Features,
DiagnosticsEngine &Diags) override;
+ void setFeatureEnabled(llvm::StringMap<bool> &Features, StringRef Name,
+ bool Enabled) const override;
+
BuiltinVaListKind getBuiltinVaListKind() const override {
return TargetInfo::CharPtrBuiltinVaList;
}
@@ -6217,6 +6411,17 @@ void HexagonTargetInfo::getTargetDefines(const LangOptions &Opts,
}
}
+bool HexagonTargetInfo::initFeatureMap(llvm::StringMap<bool> &Features,
+ DiagnosticsEngine &Diags, StringRef CPU,
+ const std::vector<std::string> &FeaturesVec) const {
+ // Default for v60: -hvx, -hvx-double.
+ Features["hvx"] = false;
+ Features["hvx-double"] = false;
+ Features["long-calls"] = false;
+
+ return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
+}
+
bool HexagonTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
DiagnosticsEngine &Diags) {
for (auto &F : Features) {
@@ -6228,21 +6433,27 @@ bool HexagonTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
HasHVX = HasHVXDouble = true;
else if (F == "-hvx-double")
HasHVXDouble = false;
+
+ if (F == "+long-calls")
+ UseLongCalls = true;
+ else if (F == "-long-calls")
+ UseLongCalls = false;
}
return true;
}
-bool HexagonTargetInfo::initFeatureMap(llvm::StringMap<bool> &Features,
- DiagnosticsEngine &Diags, StringRef CPU,
- const std::vector<std::string> &FeaturesVec) const {
- // Default for v60: -hvx, -hvx-double.
- Features["hvx"] = false;
- Features["hvx-double"] = false;
-
- return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
+void HexagonTargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features,
+ StringRef Name, bool Enabled) const {
+ if (Enabled) {
+ if (Name == "hvx-double")
+ Features["hvx"] = true;
+ } else {
+ if (Name == "hvx")
+ Features["hvx-double"] = false;
+ }
+ Features[Name] = Enabled;
}
-
const char *const HexagonTargetInfo::GCCRegNames[] = {
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
@@ -6472,8 +6683,9 @@ public:
CK_NIAGARA2,
CK_NIAGARA3,
CK_NIAGARA4,
- CK_MYRIAD2_1,
- CK_MYRIAD2_2,
+ CK_MYRIAD2100,
+ CK_MYRIAD2150,
+ CK_MYRIAD2450,
CK_LEON2,
CK_LEON2_AT697E,
CK_LEON2_AT697F,
@@ -6500,8 +6712,9 @@ public:
case CK_SPARCLITE86X:
case CK_SPARCLET:
case CK_TSC701:
- case CK_MYRIAD2_1:
- case CK_MYRIAD2_2:
+ case CK_MYRIAD2100:
+ case CK_MYRIAD2150:
+ case CK_MYRIAD2450:
case CK_LEON2:
case CK_LEON2_AT697E:
case CK_LEON2_AT697F:
@@ -6540,9 +6753,14 @@ public:
.Case("niagara2", CK_NIAGARA2)
.Case("niagara3", CK_NIAGARA3)
.Case("niagara4", CK_NIAGARA4)
- .Case("myriad2", CK_MYRIAD2_1)
- .Case("myriad2.1", CK_MYRIAD2_1)
- .Case("myriad2.2", CK_MYRIAD2_2)
+ .Case("ma2100", CK_MYRIAD2100)
+ .Case("ma2150", CK_MYRIAD2150)
+ .Case("ma2450", CK_MYRIAD2450)
+ // FIXME: the myriad2[.n] spellings are obsolete,
+ // but a grace period is needed to allow updating dependent builds.
+ .Case("myriad2", CK_MYRIAD2100)
+ .Case("myriad2.1", CK_MYRIAD2100)
+ .Case("myriad2.2", CK_MYRIAD2150)
.Case("leon2", CK_LEON2)
.Case("at697e", CK_LEON2_AT697E)
.Case("at697f", CK_LEON2_AT697F)
@@ -6630,7 +6848,10 @@ public:
PtrDiffType = SignedLong;
break;
}
- MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
+ // Up to 32 bits are lock-free atomic, but we're willing to do atomic ops
+ // on up to 64 bits.
+ MaxAtomicPromoteWidth = 64;
+ MaxAtomicInlineWidth = 32;
}
void getTargetDefines(const LangOptions &Opts,
@@ -6651,18 +6872,27 @@ public:
break;
}
if (getTriple().getVendor() == llvm::Triple::Myriad) {
+ std::string MyriadArchValue, Myriad2Value;
+ Builder.defineMacro("__sparc_v8__");
+ Builder.defineMacro("__leon__");
switch (CPU) {
- case CK_MYRIAD2_1:
- Builder.defineMacro("__myriad2", "1");
- Builder.defineMacro("__myriad2__", "1");
+ case CK_MYRIAD2150:
+ MyriadArchValue = "__ma2150";
+ Myriad2Value = "2";
break;
- case CK_MYRIAD2_2:
- Builder.defineMacro("__myriad2", "2");
- Builder.defineMacro("__myriad2__", "2");
+ case CK_MYRIAD2450:
+ MyriadArchValue = "__ma2450";
+ Myriad2Value = "2";
break;
default:
+ MyriadArchValue = "__ma2100";
+ Myriad2Value = "1";
break;
}
+ Builder.defineMacro(MyriadArchValue, "1");
+ Builder.defineMacro(MyriadArchValue+"__", "1");
+ Builder.defineMacro("__myriad2__", Myriad2Value);
+ Builder.defineMacro("__myriad2", Myriad2Value);
}
}
@@ -6677,7 +6907,6 @@ class SparcV8elTargetInfo : public SparcV8TargetInfo {
SparcV8elTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: SparcV8TargetInfo(Triple, Opts) {
resetDataLayout("e-m:e-p:32:32-i64:64-f128:64-n32-S64");
- BigEndian = false;
}
};
@@ -6702,7 +6931,7 @@ public:
// aligned. The SPARCv9 SCD 2.4.1 says 16-byte aligned.
LongDoubleWidth = 128;
LongDoubleAlign = 128;
- LongDoubleFormat = &llvm::APFloat::IEEEquad;
+ LongDoubleFormat = &llvm::APFloat::IEEEquad();
MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
}
@@ -6745,7 +6974,7 @@ public:
PointerWidth = PointerAlign = 64;
LongDoubleWidth = 128;
LongDoubleAlign = 64;
- LongDoubleFormat = &llvm::APFloat::IEEEquad;
+ LongDoubleFormat = &llvm::APFloat::IEEEquad();
DefaultAlignForAttributeAligned = 64;
MinGlobalAlign = 16;
resetDataLayout("E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-a:8:16-n32:64");
@@ -6791,9 +7020,13 @@ public:
CPU = Name;
bool CPUKnown = llvm::StringSwitch<bool>(Name)
.Case("z10", true)
+ .Case("arch8", true)
.Case("z196", true)
+ .Case("arch9", true)
.Case("zEC12", true)
+ .Case("arch10", true)
.Case("z13", true)
+ .Case("arch11", true)
.Default(false);
return CPUKnown;
@@ -6802,9 +7035,9 @@ public:
initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
StringRef CPU,
const std::vector<std::string> &FeaturesVec) const override {
- if (CPU == "zEC12")
+ if (CPU == "zEC12" || CPU == "arch10")
Features["transactional-execution"] = true;
- if (CPU == "z13") {
+ if (CPU == "z13" || CPU == "arch11") {
Features["transactional-execution"] = true;
Features["vector"] = true;
}
@@ -6912,7 +7145,6 @@ class MSP430TargetInfo : public TargetInfo {
public:
MSP430TargetInfo(const llvm::Triple &Triple, const TargetOptions &)
: TargetInfo(Triple) {
- BigEndian = false;
TLSSupported = false;
IntWidth = 16;
IntAlign = 16;
@@ -7018,11 +7250,14 @@ public:
DoubleAlign = 32;
LongDoubleWidth = 32;
LongDoubleAlign = 32;
- FloatFormat = &llvm::APFloat::IEEEsingle;
- DoubleFormat = &llvm::APFloat::IEEEsingle;
- LongDoubleFormat = &llvm::APFloat::IEEEsingle;
- resetDataLayout("E-p:32:32-i8:8:32-i16:16:32-i64:32"
- "-f64:32-v64:32-v128:32-a:0:32-n32");
+ FloatFormat = &llvm::APFloat::IEEEsingle();
+ DoubleFormat = &llvm::APFloat::IEEEsingle();
+ LongDoubleFormat = &llvm::APFloat::IEEEsingle();
+ resetDataLayout("E-p:32:32:32-i1:8:8-i8:8:32-"
+ "i16:16:32-i32:32:32-i64:32:32-"
+ "f32:32:32-f64:32:32-v64:32:32-"
+ "v128:32:32-v256:32:32-v512:32:32-"
+ "v1024:32:32-a0:0:32-n32");
AddrSpaceMap = &TCEOpenCLAddrSpaceMap;
UseAddrSpaceMapMangling = true;
}
@@ -7050,6 +7285,31 @@ public:
}
};
+class TCELETargetInfo : public TCETargetInfo {
+public:
+ TCELETargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : TCETargetInfo(Triple, Opts) {
+ BigEndian = false;
+
+ resetDataLayout("e-p:32:32:32-i1:8:8-i8:8:32-"
+ "i16:16:32-i32:32:32-i64:32:32-"
+ "f32:32:32-f64:32:32-v64:32:32-"
+ "v128:32:32-v256:32:32-v512:32:32-"
+ "v1024:32:32-a0:0:32-n32");
+
+ }
+
+ virtual void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const {
+ DefineStd(Builder, "tcele", Opts);
+ Builder.defineMacro("__TCE__");
+ Builder.defineMacro("__TCE_V1__");
+ Builder.defineMacro("__TCELE__");
+ Builder.defineMacro("__TCELE_V1__");
+ }
+
+};
+
class BPFTargetInfo : public TargetInfo {
public:
BPFTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
@@ -7062,10 +7322,8 @@ public:
Int64Type = SignedLong;
RegParmMax = 5;
if (Triple.getArch() == llvm::Triple::bpfeb) {
- BigEndian = true;
resetDataLayout("E-m:e-p:64:64-i64:64-n32:64-S128");
} else {
- BigEndian = false;
resetDataLayout("e-m:e-p:64:64-i64:64-n32:64-S128");
}
MaxAtomicPromoteWidth = 64;
@@ -7144,8 +7402,6 @@ public:
IsNan2008(false), IsSingleFloat(false), FloatABI(HardFloat),
DspRev(NoDSP), HasMSA(false), HasFP64(false) {
TheCXXABI.set(TargetCXXABI::GenericMIPS);
- BigEndian = getTriple().getArch() == llvm::Triple::mips ||
- getTriple().getArch() == llvm::Triple::mips64;
setABI((getTriple().getArch() == llvm::Triple::mips ||
getTriple().getArch() == llvm::Triple::mipsel)
@@ -7206,7 +7462,7 @@ public:
void setO32ABITypes() {
Int64Type = SignedLongLong;
IntMaxType = Int64Type;
- LongDoubleFormat = &llvm::APFloat::IEEEdouble;
+ LongDoubleFormat = &llvm::APFloat::IEEEdouble();
LongDoubleWidth = LongDoubleAlign = 64;
LongWidth = LongAlign = 32;
MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 32;
@@ -7218,10 +7474,10 @@ public:
void setN32N64ABITypes() {
LongDoubleWidth = LongDoubleAlign = 128;
- LongDoubleFormat = &llvm::APFloat::IEEEquad;
+ LongDoubleFormat = &llvm::APFloat::IEEEquad();
if (getTriple().getOS() == llvm::Triple::FreeBSD) {
LongDoubleWidth = LongDoubleAlign = 64;
- LongDoubleFormat = &llvm::APFloat::IEEEdouble;
+ LongDoubleFormat = &llvm::APFloat::IEEEdouble();
}
MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
SuitableAlign = 128;
@@ -7648,7 +7904,6 @@ class PNaClTargetInfo : public TargetInfo {
public:
PNaClTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: TargetInfo(Triple) {
- BigEndian = false;
this->LongAlign = 32;
this->LongWidth = 32;
this->PointerAlign = 32;
@@ -7716,7 +7971,6 @@ class Le64TargetInfo : public TargetInfo {
public:
Le64TargetInfo(const llvm::Triple &Triple, const TargetOptions &)
: TargetInfo(Triple) {
- BigEndian = false;
NoAsmVariants = true;
LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
@@ -7762,7 +8016,6 @@ class WebAssemblyTargetInfo : public TargetInfo {
public:
explicit WebAssemblyTargetInfo(const llvm::Triple &T, const TargetOptions &)
: TargetInfo(T), SIMDLevel(NoSIMD) {
- BigEndian = false;
NoAsmVariants = true;
SuitableAlign = 128;
LargeArrayMinWidth = 128;
@@ -7770,7 +8023,10 @@ public:
SimdDefaultAlign = 128;
SigAtomicType = SignedLong;
LongDoubleWidth = LongDoubleAlign = 128;
- LongDoubleFormat = &llvm::APFloat::IEEEquad;
+ LongDoubleFormat = &llvm::APFloat::IEEEquad();
+ SizeType = UnsignedInt;
+ PtrDiffType = SignedInt;
+ IntPtrType = SignedInt;
}
protected:
@@ -7889,6 +8145,9 @@ public:
LongAlign = LongWidth = 64;
PointerAlign = PointerWidth = 64;
MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
+ SizeType = UnsignedLong;
+ PtrDiffType = SignedLong;
+ IntPtrType = SignedLong;
resetDataLayout("e-m:e-p:64:64-i64:64-n32:64-S128");
}
@@ -7923,7 +8182,6 @@ public:
"SPIR target must use unknown OS");
assert(getTriple().getEnvironment() == llvm::Triple::UnknownEnvironment &&
"SPIR target must use unknown environment type");
- BigEndian = false;
TLSSupported = false;
LongWidth = LongAlign = 64;
AddrSpaceMap = &SPIRAddrSpaceMap;
@@ -7966,7 +8224,7 @@ public:
void setSupportedOpenCLOpts() override {
// Assume all OpenCL extensions and optional core features are supported
// for SPIR since it is a generic target.
- getSupportedOpenCLOpts().setAll();
+ getSupportedOpenCLOpts().supportAll();
}
};
@@ -8007,7 +8265,6 @@ class XCoreTargetInfo : public TargetInfo {
public:
XCoreTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
: TargetInfo(Triple) {
- BigEndian = false;
NoAsmVariants = true;
LongLongAlign = 32;
SuitableAlign = 32;
@@ -8073,7 +8330,7 @@ public:
: LinuxTargetInfo<X86_32TargetInfo>(Triple, Opts) {
SuitableAlign = 32;
LongDoubleWidth = 64;
- LongDoubleFormat = &llvm::APFloat::IEEEdouble;
+ LongDoubleFormat = &llvm::APFloat::IEEEdouble();
}
};
@@ -8082,7 +8339,7 @@ class AndroidX86_64TargetInfo : public LinuxTargetInfo<X86_64TargetInfo> {
public:
AndroidX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: LinuxTargetInfo<X86_64TargetInfo>(Triple, Opts) {
- LongDoubleFormat = &llvm::APFloat::IEEEquad;
+ LongDoubleFormat = &llvm::APFloat::IEEEquad();
}
bool useFloat128ManglingForLongDouble() const override {
@@ -8099,6 +8356,7 @@ public:
Triple.getOSName(),
Triple.getEnvironmentName()),
Opts) {
+ IsRenderScriptTarget = true;
LongWidth = LongAlign = 64;
}
void getTargetDefines(const LangOptions &Opts,
@@ -8116,7 +8374,9 @@ public:
: AArch64leTargetInfo(llvm::Triple("aarch64", Triple.getVendorName(),
Triple.getOSName(),
Triple.getEnvironmentName()),
- Opts) {}
+ Opts) {
+ IsRenderScriptTarget = true;
+ }
void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override {
@@ -8157,6 +8417,8 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple,
return new CloudABITargetInfo<AArch64leTargetInfo>(Triple, Opts);
case llvm::Triple::FreeBSD:
return new FreeBSDTargetInfo<AArch64leTargetInfo>(Triple, Opts);
+ case llvm::Triple::Fuchsia:
+ return new FuchsiaTargetInfo<AArch64leTargetInfo>(Triple, Opts);
case llvm::Triple::Linux:
return new LinuxTargetInfo<AArch64leTargetInfo>(Triple, Opts);
case llvm::Triple::NetBSD:
@@ -8169,6 +8431,8 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple,
switch (os) {
case llvm::Triple::FreeBSD:
return new FreeBSDTargetInfo<AArch64beTargetInfo>(Triple, Opts);
+ case llvm::Triple::Fuchsia:
+ return new FuchsiaTargetInfo<AArch64beTargetInfo>(Triple, Opts);
case llvm::Triple::Linux:
return new LinuxTargetInfo<AArch64beTargetInfo>(Triple, Opts);
case llvm::Triple::NetBSD:
@@ -8189,6 +8453,8 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple,
return new LinuxTargetInfo<ARMleTargetInfo>(Triple, Opts);
case llvm::Triple::FreeBSD:
return new FreeBSDTargetInfo<ARMleTargetInfo>(Triple, Opts);
+ case llvm::Triple::Fuchsia:
+ return new FuchsiaTargetInfo<ARMleTargetInfo>(Triple, Opts);
case llvm::Triple::NetBSD:
return new NetBSDTargetInfo<ARMleTargetInfo>(Triple, Opts);
case llvm::Triple::OpenBSD:
@@ -8225,6 +8491,8 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple,
return new LinuxTargetInfo<ARMbeTargetInfo>(Triple, Opts);
case llvm::Triple::FreeBSD:
return new FreeBSDTargetInfo<ARMbeTargetInfo>(Triple, Opts);
+ case llvm::Triple::Fuchsia:
+ return new FuchsiaTargetInfo<ARMbeTargetInfo>(Triple, Opts);
case llvm::Triple::NetBSD:
return new NetBSDTargetInfo<ARMbeTargetInfo>(Triple, Opts);
case llvm::Triple::OpenBSD:
@@ -8430,6 +8698,9 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple,
case llvm::Triple::tce:
return new TCETargetInfo(Triple, Opts);
+ case llvm::Triple::tcele:
+ return new TCELETargetInfo(Triple, Opts);
+
case llvm::Triple::x86:
if (Triple.isOSDarwin())
return new DarwinI386TargetInfo(Triple, Opts);
@@ -8455,6 +8726,8 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple,
return new BitrigI386TargetInfo(Triple, Opts);
case llvm::Triple::FreeBSD:
return new FreeBSDTargetInfo<X86_32TargetInfo>(Triple, Opts);
+ case llvm::Triple::Fuchsia:
+ return new FuchsiaTargetInfo<X86_32TargetInfo>(Triple, Opts);
case llvm::Triple::KFreeBSD:
return new KFreeBSDTargetInfo<X86_32TargetInfo>(Triple, Opts);
case llvm::Triple::Minix:
@@ -8510,6 +8783,8 @@ static TargetInfo *AllocateTarget(const llvm::Triple &Triple,
return new BitrigX86_64TargetInfo(Triple, Opts);
case llvm::Triple::FreeBSD:
return new FreeBSDTargetInfo<X86_64TargetInfo>(Triple, Opts);
+ case llvm::Triple::Fuchsia:
+ return new FuchsiaTargetInfo<X86_64TargetInfo>(Triple, Opts);
case llvm::Triple::KFreeBSD:
return new KFreeBSDTargetInfo<X86_64TargetInfo>(Triple, Opts);
case llvm::Triple::Solaris:
@@ -8612,6 +8887,7 @@ TargetInfo::CreateTargetInfo(DiagnosticsEngine &Diags,
return nullptr;
Target->setSupportedOpenCLOpts();
+ Target->setOpenCLExtensionOpts();
if (!Target->validateTarget(Diags))
return nullptr;
diff --git a/lib/Basic/Version.cpp b/lib/Basic/Version.cpp
index 4fa52b4acce0..a1a67c2bc144 100644
--- a/lib/Basic/Version.cpp
+++ b/lib/Basic/Version.cpp
@@ -36,7 +36,7 @@ std::string getClangRepositoryPath() {
// If the SVN_REPOSITORY is empty, try to use the SVN keyword. This helps us
// pick up a tag in an SVN export, for example.
- StringRef SVNRepository("$URL: https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_391/final/lib/Basic/Version.cpp $");
+ StringRef SVNRepository("$URL: https://llvm.org/svn/llvm-project/cfe/trunk/lib/Basic/Version.cpp $");
if (URL.empty()) {
URL = SVNRepository.slice(SVNRepository.find(':'),
SVNRepository.find("/lib/Basic"));
diff --git a/lib/Basic/VirtualFileSystem.cpp b/lib/Basic/VirtualFileSystem.cpp
index 8ace2b3dc838..50fcb22faf53 100644
--- a/lib/Basic/VirtualFileSystem.cpp
+++ b/lib/Basic/VirtualFileSystem.cpp
@@ -47,7 +47,7 @@ Status::Status(const file_status &Status)
User(Status.getUser()), Group(Status.getGroup()), Size(Status.getSize()),
Type(Status.type()), Perms(Status.permissions()), IsVFSMapped(false) {}
-Status::Status(StringRef Name, UniqueID UID, sys::TimeValue MTime,
+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),
@@ -494,8 +494,8 @@ public:
InMemoryFileSystem::InMemoryFileSystem(bool UseNormalizedPaths)
: Root(new detail::InMemoryDirectory(
- Status("", getNextVirtualUniqueID(), llvm::sys::TimeValue::MinTime(),
- 0, 0, 0, llvm::sys::fs::file_type::directory_file,
+ Status("", getNextVirtualUniqueID(), llvm::sys::TimePoint<>(), 0, 0,
+ 0, llvm::sys::fs::file_type::directory_file,
llvm::sys::fs::perms::all_all))),
UseNormalizedPaths(UseNormalizedPaths) {}
@@ -532,7 +532,7 @@ bool InMemoryFileSystem::addFile(const Twine &P, time_t ModificationTime,
// End of the path, create a new file.
// FIXME: expose the status details in the interface.
Status Stat(P.str(), getNextVirtualUniqueID(),
- llvm::sys::TimeValue(ModificationTime, 0), 0, 0,
+ llvm::sys::toTimePoint(ModificationTime), 0, 0,
Buffer->getBufferSize(),
llvm::sys::fs::file_type::regular_file,
llvm::sys::fs::all_all);
@@ -545,9 +545,9 @@ bool InMemoryFileSystem::addFile(const Twine &P, time_t ModificationTime,
// FIXME: expose the status details in the interface.
Status Stat(
StringRef(Path.str().begin(), Name.end() - Path.str().begin()),
- getNextVirtualUniqueID(), llvm::sys::TimeValue(ModificationTime, 0),
- 0, 0, Buffer->getBufferSize(),
- llvm::sys::fs::file_type::directory_file, llvm::sys::fs::all_all);
+ getNextVirtualUniqueID(), llvm::sys::toTimePoint(ModificationTime), 0,
+ 0, Buffer->getBufferSize(), llvm::sys::fs::file_type::directory_file,
+ llvm::sys::fs::all_all);
Dir = cast<detail::InMemoryDirectory>(Dir->addChild(
Name, llvm::make_unique<detail::InMemoryDirectory>(std::move(Stat))));
continue;
@@ -801,6 +801,7 @@ public:
/// 'case-sensitive': <boolean, default=true>
/// 'use-external-names': <boolean, default=true>
/// 'overlay-relative': <boolean, default=false>
+/// 'ignore-non-existent-contents': <boolean, default=true>
///
/// Virtual directories are represented as
/// \verbatim
@@ -860,6 +861,14 @@ class RedirectingFileSystem : public vfs::FileSystem {
/// \brief 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
+ /// 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
+ /// paths in 'external-contents'. This global value is overridable on a
+ /// per-file basis.
+ bool IgnoreNonExistentContents = true;
/// @}
/// Virtual file paths and external files could be canonicalized without "..",
@@ -878,9 +887,6 @@ private:
RedirectingFileSystem(IntrusiveRefCntPtr<FileSystem> ExternalFS)
: ExternalFS(std::move(ExternalFS)) {}
- /// \brief Looks up \p Path in \c Roots.
- ErrorOr<Entry *> lookupPath(const Twine &Path);
-
/// \brief 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,
@@ -890,6 +896,9 @@ private:
ErrorOr<Status> status(const Twine &Path, Entry *E);
public:
+ /// \brief 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
/// returns a virtual file system representing its contents.
static RedirectingFileSystem *
@@ -937,6 +946,10 @@ public:
return ExternalContentsPrefixDir;
}
+ bool ignoreNonExistentContents() const {
+ return IgnoreNonExistentContents;
+ }
+
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
LLVM_DUMP_METHOD void dump() const {
for (const std::unique_ptr<Entry> &Root : Roots)
@@ -1060,8 +1073,9 @@ class RedirectingFileSystemParser {
// ... or create a new one
std::unique_ptr<Entry> E = llvm::make_unique<RedirectingDirectoryEntry>(
- Name, Status("", getNextVirtualUniqueID(), sys::TimeValue::now(), 0, 0,
- 0, file_type::directory_file, sys::fs::all_all));
+ Name,
+ Status("", getNextVirtualUniqueID(), std::chrono::system_clock::now(),
+ 0, 0, 0, file_type::directory_file, sys::fs::all_all));
if (!ParentEntry) { // Add a new root to the overlay
FS->Roots.push_back(std::move(E));
@@ -1262,8 +1276,8 @@ class RedirectingFileSystemParser {
case EK_Directory:
Result = llvm::make_unique<RedirectingDirectoryEntry>(
LastComponent, std::move(EntryArrayContents),
- Status("", getNextVirtualUniqueID(), sys::TimeValue::now(), 0, 0, 0,
- file_type::directory_file, sys::fs::all_all));
+ Status("", getNextVirtualUniqueID(), std::chrono::system_clock::now(),
+ 0, 0, 0, file_type::directory_file, sys::fs::all_all));
break;
}
@@ -1279,8 +1293,8 @@ class RedirectingFileSystemParser {
Entries.push_back(std::move(Result));
Result = llvm::make_unique<RedirectingDirectoryEntry>(
*I, std::move(Entries),
- Status("", getNextVirtualUniqueID(), sys::TimeValue::now(), 0, 0, 0,
- file_type::directory_file, sys::fs::all_all));
+ Status("", getNextVirtualUniqueID(), std::chrono::system_clock::now(),
+ 0, 0, 0, file_type::directory_file, sys::fs::all_all));
}
return Result;
}
@@ -1301,6 +1315,7 @@ public:
KeyStatusPair("case-sensitive", false),
KeyStatusPair("use-external-names", false),
KeyStatusPair("overlay-relative", false),
+ KeyStatusPair("ignore-non-existent-contents", false),
KeyStatusPair("roots", true),
};
@@ -1359,6 +1374,9 @@ public:
} else if (Key == "use-external-names") {
if (!parseScalarBool(I->getValue(), FS->UseExternalNames))
return false;
+ } else if (Key == "ignore-non-existent-contents") {
+ if (!parseScalarBool(I->getValue(), FS->IgnoreNonExistentContents))
+ return false;
} else {
llvm_unreachable("key missing from Keys");
}
@@ -1588,6 +1606,47 @@ vfs::getVFSFromYAML(std::unique_ptr<MemoryBuffer> Buffer,
std::move(ExternalFS));
}
+static void getVFSEntries(Entry *SrcE, SmallVectorImpl<StringRef> &Path,
+ SmallVectorImpl<YAMLVFSEntry> &Entries) {
+ auto Kind = SrcE->getKind();
+ if (Kind == EK_Directory) {
+ auto *DE = dyn_cast<RedirectingDirectoryEntry>(SrcE);
+ assert(DE && "Must be a directory");
+ for (std::unique_ptr<Entry> &SubEntry :
+ llvm::make_range(DE->contents_begin(), DE->contents_end())) {
+ Path.push_back(SubEntry->getName());
+ getVFSEntries(SubEntry.get(), Path, Entries);
+ Path.pop_back();
+ }
+ return;
+ }
+
+ assert(Kind == EK_File && "Must be a EK_File");
+ auto *FE = dyn_cast<RedirectingFileEntry>(SrcE);
+ assert(FE && "Must be a file");
+ SmallString<128> VPath;
+ for (auto &Comp : Path)
+ llvm::sys::path::append(VPath, Comp);
+ Entries.push_back(YAMLVFSEntry(VPath.c_str(), FE->getExternalContentsPath()));
+}
+
+void vfs::collectVFSFromYAML(std::unique_ptr<MemoryBuffer> Buffer,
+ SourceMgr::DiagHandlerTy DiagHandler,
+ StringRef YAMLFilePath,
+ SmallVectorImpl<YAMLVFSEntry> &CollectedEntries,
+ void *DiagContext,
+ IntrusiveRefCntPtr<FileSystem> ExternalFS) {
+ RedirectingFileSystem *VFS = RedirectingFileSystem::create(
+ std::move(Buffer), DiagHandler, YAMLFilePath, DiagContext,
+ std::move(ExternalFS));
+ ErrorOr<Entry *> RootE = VFS->lookupPath("/");
+ if (!RootE)
+ return;
+ SmallVector<StringRef, 8> Components;
+ Components.push_back("/");
+ getVFSEntries(*RootE, Components, CollectedEntries);
+}
+
UniqueID vfs::getNextVirtualUniqueID() {
static std::atomic<unsigned> UID;
unsigned ID = ++UID;
@@ -1619,7 +1678,7 @@ public:
JSONWriter(llvm::raw_ostream &OS) : OS(OS) {}
void write(ArrayRef<YAMLVFSEntry> Entries, Optional<bool> UseExternalNames,
Optional<bool> IsCaseSensitive, Optional<bool> IsOverlayRelative,
- StringRef OverlayDir);
+ Optional<bool> IgnoreNonExistentContents, StringRef OverlayDir);
};
}
@@ -1675,6 +1734,7 @@ void JSONWriter::write(ArrayRef<YAMLVFSEntry> Entries,
Optional<bool> UseExternalNames,
Optional<bool> IsCaseSensitive,
Optional<bool> IsOverlayRelative,
+ Optional<bool> IgnoreNonExistentContents,
StringRef OverlayDir) {
using namespace llvm::sys;
@@ -1692,6 +1752,9 @@ void JSONWriter::write(ArrayRef<YAMLVFSEntry> Entries,
OS << " 'overlay-relative': '"
<< (UseOverlayRelative ? "true" : "false") << "',\n";
}
+ if (IgnoreNonExistentContents.hasValue())
+ OS << " 'ignore-non-existent-contents': '"
+ << (IgnoreNonExistentContents.getValue() ? "true" : "false") << "',\n";
OS << " 'roots': [\n";
if (!Entries.empty()) {
@@ -1748,7 +1811,8 @@ void YAMLVFSWriter::write(llvm::raw_ostream &OS) {
});
JSONWriter(OS).write(Mappings, UseExternalNames, IsCaseSensitive,
- IsOverlayRelative, OverlayDir);
+ IsOverlayRelative, IgnoreNonExistentContents,
+ OverlayDir);
}
VFSFromYamlDirIterImpl::VFSFromYamlDirIterImpl(
@@ -1756,29 +1820,47 @@ VFSFromYamlDirIterImpl::VFSFromYamlDirIterImpl(
RedirectingDirectoryEntry::iterator Begin,
RedirectingDirectoryEntry::iterator End, std::error_code &EC)
: Dir(_Path.str()), FS(FS), Current(Begin), End(End) {
- if (Current != End) {
+ while (Current != End) {
SmallString<128> PathStr(Dir);
llvm::sys::path::append(PathStr, (*Current)->getName());
llvm::ErrorOr<vfs::Status> S = FS.status(PathStr);
- if (S)
+ if (S) {
CurrentEntry = *S;
- else
+ return;
+ }
+ // Skip entries which do not map to a reliable external content.
+ if (FS.ignoreNonExistentContents() &&
+ S.getError() == llvm::errc::no_such_file_or_directory) {
+ ++Current;
+ continue;
+ } else {
EC = S.getError();
+ break;
+ }
}
}
std::error_code VFSFromYamlDirIterImpl::increment() {
assert(Current != End && "cannot iterate past end");
- if (++Current != End) {
+ while (++Current != End) {
SmallString<128> PathStr(Dir);
llvm::sys::path::append(PathStr, (*Current)->getName());
llvm::ErrorOr<vfs::Status> S = FS.status(PathStr);
- if (!S)
- return S.getError();
+ if (!S) {
+ // Skip entries which do not map to a reliable external content.
+ if (FS.ignoreNonExistentContents() &&
+ S.getError() == llvm::errc::no_such_file_or_directory) {
+ continue;
+ } else {
+ return S.getError();
+ }
+ }
CurrentEntry = *S;
- } else {
- CurrentEntry = Status();
+ break;
}
+
+ if (Current == End)
+ CurrentEntry = Status();
return std::error_code();
}
diff --git a/lib/CodeGen/ABIInfo.h b/lib/CodeGen/ABIInfo.h
index 530a7ef560c5..ac31dfdaf3e4 100644
--- a/lib/CodeGen/ABIInfo.h
+++ b/lib/CodeGen/ABIInfo.h
@@ -142,6 +142,8 @@ namespace swiftcall {
llvm::Type *eltTy,
unsigned elts) const;
+ virtual bool isSwiftErrorInRegister() const = 0;
+
static bool classof(const ABIInfo *info) {
return info->supportsSwift();
}
diff --git a/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp
index 165b6dd55c9b..164e52d7de27 100644
--- a/lib/CodeGen/BackendUtil.cpp
+++ b/lib/CodeGen/BackendUtil.cpp
@@ -14,24 +14,29 @@
#include "clang/Frontend/CodeGenOptions.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/Utils.h"
+#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/TargetTransformInfo.h"
+#include "llvm/Bitcode/BitcodeReader.h"
+#include "llvm/Bitcode/BitcodeWriter.h"
#include "llvm/Bitcode/BitcodeWriterPass.h"
-#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/CodeGen/RegAllocRegistry.h"
#include "llvm/CodeGen/SchedulerRegistry.h"
#include "llvm/IR/DataLayout.h"
-#include "llvm/IR/ModuleSummaryIndex.h"
#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Module.h"
+#include "llvm/IR/ModuleSummaryIndex.h"
#include "llvm/IR/Verifier.h"
+#include "llvm/LTO/LTOBackend.h"
#include "llvm/MC/SubtargetFeature.h"
#include "llvm/Object/ModuleSummaryIndexObjectFile.h"
+#include "llvm/Passes/PassBuilder.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/Timer.h"
@@ -39,7 +44,9 @@
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/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/Instrumentation.h"
#include "llvm/Transforms/ObjCARC.h"
@@ -74,8 +81,7 @@ private:
/// Set LLVM command line options passed through -backend-option.
void setCommandLineOpts();
- void CreatePasses(legacy::PassManager &MPM, legacy::FunctionPassManager &FPM,
- ModuleSummaryIndex *ModuleSummary);
+ void CreatePasses(legacy::PassManager &MPM, legacy::FunctionPassManager &FPM);
/// Generates the TargetMachine.
/// Leaves TM unchanged if it is unable to create the target machine.
@@ -98,7 +104,7 @@ public:
const clang::TargetOptions &TOpts,
const LangOptions &LOpts, Module *M)
: Diags(_Diags), CodeGenOpts(CGOpts), TargetOpts(TOpts), LangOpts(LOpts),
- TheModule(M), CodeGenerationTime("Code Generation Time") {}
+ TheModule(M), CodeGenerationTime("codegen", "Code Generation Time") {}
~EmitAssemblyHelper() {
if (CodeGenOpts.DisableFree)
@@ -109,6 +115,9 @@ public:
void EmitAssembly(BackendAction Action,
std::unique_ptr<raw_pwrite_stream> OS);
+
+ void EmitAssemblyWithNewPassManager(BackendAction Action,
+ std::unique_ptr<raw_pwrite_stream> OS);
};
// We need this wrapper to access LangOpts and CGOpts from extension functions
@@ -147,17 +156,6 @@ static void addAddDiscriminatorsPass(const PassManagerBuilder &Builder,
PM.add(createAddDiscriminatorsPass());
}
-static void addCleanupPassesForSampleProfiler(
- const PassManagerBuilder &Builder, legacy::PassManagerBase &PM) {
- // instcombine is needed before sample profile annotation because it converts
- // certain function calls to be inlinable. simplifycfg and sroa are needed
- // before instcombine for necessary preparation. E.g. load store is eliminated
- // properly so that instcombine will not introduce unecessary liverange.
- PM.add(createCFGSimplificationPass());
- PM.add(createSROAPass());
- PM.add(createInstructionCombiningPass());
-}
-
static void addBoundsCheckingPass(const PassManagerBuilder &Builder,
legacy::PassManagerBase &PM) {
PM.add(createBoundsCheckingPass());
@@ -174,8 +172,11 @@ static void addSanitizerCoveragePass(const PassManagerBuilder &Builder,
Opts.IndirectCalls = CGOpts.SanitizeCoverageIndirectCalls;
Opts.TraceBB = CGOpts.SanitizeCoverageTraceBB;
Opts.TraceCmp = CGOpts.SanitizeCoverageTraceCmp;
+ Opts.TraceDiv = CGOpts.SanitizeCoverageTraceDiv;
+ Opts.TraceGep = CGOpts.SanitizeCoverageTraceGep;
Opts.Use8bitCounters = CGOpts.SanitizeCoverage8bitCounters;
Opts.TracePC = CGOpts.SanitizeCoverageTracePC;
+ Opts.TracePCGuard = CGOpts.SanitizeCoverageTracePCGuard;
PM.add(createSanitizerCoverageModulePass(Opts));
}
@@ -205,7 +206,9 @@ static void addMemorySanitizerPass(const PassManagerBuilder &Builder,
const PassManagerBuilderWrapper &BuilderWrapper =
static_cast<const PassManagerBuilderWrapper&>(Builder);
const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts();
- PM.add(createMemorySanitizerPass(CGOpts.SanitizeMemoryTrackOrigins));
+ int TrackOrigins = CGOpts.SanitizeMemoryTrackOrigins;
+ bool Recover = CGOpts.SanitizeRecover.has(SanitizerKind::Memory);
+ PM.add(createMemorySanitizerPass(TrackOrigins, Recover));
// MemorySanitizer inserts complex instrumentation that mostly follows
// the logic of the original code, but operates on "shadow" values.
@@ -263,6 +266,9 @@ static TargetLibraryInfoImpl *createTLII(llvm::Triple &TargetTriple,
case CodeGenOptions::Accelerate:
TLII->addVectorizableFunctionsFromVecLib(TargetLibraryInfoImpl::Accelerate);
break;
+ case CodeGenOptions::SVML:
+ TLII->addVectorizableFunctionsFromVecLib(TargetLibraryInfoImpl::SVML);
+ break;
default:
break;
}
@@ -281,47 +287,33 @@ static void addSymbolRewriterPass(const CodeGenOptions &Opts,
}
void EmitAssemblyHelper::CreatePasses(legacy::PassManager &MPM,
- legacy::FunctionPassManager &FPM,
- ModuleSummaryIndex *ModuleSummary) {
+ legacy::FunctionPassManager &FPM) {
+ // Handle disabling of all LLVM passes, where we want to preserve the
+ // internal module before any optimization.
if (CodeGenOpts.DisableLLVMPasses)
return;
- unsigned OptLevel = CodeGenOpts.OptimizationLevel;
- CodeGenOptions::InliningMethod Inlining = CodeGenOpts.getInlining();
-
- // Handle disabling of LLVM optimization, where we want to preserve the
- // internal module before any optimization.
- if (CodeGenOpts.DisableLLVMOpts) {
- OptLevel = 0;
- Inlining = CodeGenOpts.NoInlining;
- }
-
PassManagerBuilderWrapper PMBuilder(CodeGenOpts, LangOpts);
- // Figure out TargetLibraryInfo.
+ // Figure out TargetLibraryInfo. This needs to be added to MPM and FPM
+ // manually (and not via PMBuilder), since some passes (eg. InstrProfiling)
+ // are inserted before PMBuilder ones - they'd get the default-constructed
+ // TLI with an unknown target otherwise.
Triple TargetTriple(TheModule->getTargetTriple());
- PMBuilder.LibraryInfo = createTLII(TargetTriple, CodeGenOpts);
+ std::unique_ptr<TargetLibraryInfoImpl> TLII(
+ createTLII(TargetTriple, CodeGenOpts));
- switch (Inlining) {
- case CodeGenOptions::NoInlining:
- break;
- case CodeGenOptions::NormalInlining:
- case CodeGenOptions::OnlyHintInlining: {
- PMBuilder.Inliner =
- createFunctionInliningPass(OptLevel, CodeGenOpts.OptimizeSize);
- break;
- }
- case CodeGenOptions::OnlyAlwaysInlining:
- // Respect always_inline.
- if (OptLevel == 0)
- // Do not insert lifetime intrinsics at -O0.
- PMBuilder.Inliner = createAlwaysInlinerPass(false);
- else
- PMBuilder.Inliner = createAlwaysInlinerPass();
- break;
+ // At O0 and O1 we only run the always inliner which is more efficient. At
+ // higher optimization levels we run the normal inliner.
+ if (CodeGenOpts.OptimizationLevel <= 1) {
+ bool InsertLifetimeIntrinsics = CodeGenOpts.OptimizationLevel != 0;
+ PMBuilder.Inliner = createAlwaysInlinerLegacyPass(InsertLifetimeIntrinsics);
+ } else {
+ PMBuilder.Inliner = createFunctionInliningPass(
+ CodeGenOpts.OptimizationLevel, CodeGenOpts.OptimizeSize);
}
- PMBuilder.OptLevel = OptLevel;
+ PMBuilder.OptLevel = CodeGenOpts.OptimizationLevel;
PMBuilder.SizeLevel = CodeGenOpts.OptimizeSize;
PMBuilder.BBVectorize = CodeGenOpts.VectorizeBB;
PMBuilder.SLPVectorize = CodeGenOpts.VectorizeSLP;
@@ -333,13 +325,7 @@ void EmitAssemblyHelper::CreatePasses(legacy::PassManager &MPM,
PMBuilder.PrepareForLTO = CodeGenOpts.PrepareForLTO;
PMBuilder.RerollLoops = CodeGenOpts.RerollLoops;
- // If we are performing a ThinLTO importing compile, invoke the LTO
- // pipeline and pass down the in-memory module summary index.
- if (ModuleSummary) {
- PMBuilder.ModuleSummary = ModuleSummary;
- PMBuilder.populateThinLTOPassManager(MPM);
- return;
- }
+ MPM.add(new TargetLibraryInfoWrapperPass(*TLII));
// Add target-specific passes that need to run as early as possible.
if (TM)
@@ -413,6 +399,9 @@ void EmitAssemblyHelper::CreatePasses(legacy::PassManager &MPM,
addDataFlowSanitizerPass);
}
+ if (LangOpts.CoroutinesTS)
+ addCoroutinePassesToExtensionPoints(PMBuilder);
+
if (LangOpts.Sanitize.hasOneOf(SanitizerKind::Efficiency)) {
PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast,
addEfficiencySanitizerPass);
@@ -421,6 +410,7 @@ void EmitAssemblyHelper::CreatePasses(legacy::PassManager &MPM,
}
// Set up the per-function pass manager.
+ FPM.add(new TargetLibraryInfoWrapperPass(*TLII));
if (CodeGenOpts.VerifyModule)
FPM.add(createVerifierPass());
@@ -453,20 +443,17 @@ void EmitAssemblyHelper::CreatePasses(legacy::PassManager &MPM,
MPM.add(createInstrProfilingLegacyPass(Options));
}
if (CodeGenOpts.hasProfileIRInstr()) {
+ PMBuilder.EnablePGOInstrGen = true;
if (!CodeGenOpts.InstrProfileOutput.empty())
PMBuilder.PGOInstrGen = CodeGenOpts.InstrProfileOutput;
else
- PMBuilder.PGOInstrGen = "default.profraw";
+ PMBuilder.PGOInstrGen = "default_%m.profraw";
}
if (CodeGenOpts.hasProfileIRUse())
PMBuilder.PGOInstrUse = CodeGenOpts.ProfileInstrumentUsePath;
- if (!CodeGenOpts.SampleProfileFile.empty()) {
- MPM.add(createPruneEHPass());
- MPM.add(createSampleProfileLoaderPass(CodeGenOpts.SampleProfileFile));
- PMBuilder.addExtension(PassManagerBuilder::EP_EarlyAsPossible,
- addCleanupPassesForSampleProfiler);
- }
+ if (!CodeGenOpts.SampleProfileFile.empty())
+ PMBuilder.PGOSampleUse = CodeGenOpts.SampleProfileFile;
PMBuilder.populateFunctionPassManager(FPM);
PMBuilder.populateModulePassManager(MPM);
@@ -517,15 +504,14 @@ void EmitAssemblyHelper::CreateTargetMachine(bool MustCreateTM) {
// Keep this synced with the equivalent code in tools/driver/cc1as_main.cpp.
llvm::Optional<llvm::Reloc::Model> RM;
- if (CodeGenOpts.RelocationModel == "static") {
- RM = llvm::Reloc::Static;
- } else if (CodeGenOpts.RelocationModel == "pic") {
- RM = llvm::Reloc::PIC_;
- } else {
- assert(CodeGenOpts.RelocationModel == "dynamic-no-pic" &&
- "Invalid PIC model!");
- RM = llvm::Reloc::DynamicNoPIC;
- }
+ 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!");
CodeGenOpt::Level OptLevel = CodeGenOpt::Default;
switch (CodeGenOpts.OptimizationLevel) {
@@ -536,9 +522,6 @@ void EmitAssemblyHelper::CreateTargetMachine(bool MustCreateTM) {
llvm::TargetOptions Options;
- if (!TargetOpts.Reciprocals.empty())
- Options.Reciprocals = TargetRecip(TargetOpts.Reciprocals);
-
Options.ThreadModel =
llvm::StringSwitch<llvm::ThreadModel::Model>(CodeGenOpts.ThreadModel)
.Case("posix", llvm::ThreadModel::POSIX)
@@ -601,8 +584,11 @@ void EmitAssemblyHelper::CreateTargetMachine(bool MustCreateTM) {
Options.MCOptions.MCNoExecStack = CodeGenOpts.NoExecStack;
Options.MCOptions.MCIncrementalLinkerCompatible =
CodeGenOpts.IncrementalLinkerCompatible;
+ Options.MCOptions.MCPIECopyRelocations =
+ CodeGenOpts.PIECopyRelocations;
Options.MCOptions.MCFatalWarnings = CodeGenOpts.FatalWarnings;
Options.MCOptions.AsmVerbose = CodeGenOpts.AsmVerbose;
+ Options.MCOptions.PreserveAsmComments = CodeGenOpts.PreserveAsmComments;
Options.MCOptions.ABIName = TargetOpts.ABI;
TM.reset(TheTarget->createTargetMachine(Triple, TargetOpts.CPU, FeaturesStr,
@@ -659,26 +645,6 @@ void EmitAssemblyHelper::EmitAssembly(BackendAction Action,
if (TM)
TheModule->setDataLayout(TM->createDataLayout());
- // If we are performing a ThinLTO importing compile, load the function
- // index into memory and pass it into CreatePasses, which will add it
- // to the PassManagerBuilder and invoke LTO passes.
- std::unique_ptr<ModuleSummaryIndex> ModuleSummary;
- if (!CodeGenOpts.ThinLTOIndexFile.empty()) {
- ErrorOr<std::unique_ptr<ModuleSummaryIndex>> IndexOrErr =
- llvm::getModuleSummaryIndexForFile(
- CodeGenOpts.ThinLTOIndexFile, [&](const DiagnosticInfo &DI) {
- TheModule->getContext().diagnose(DI);
- });
- if (std::error_code EC = IndexOrErr.getError()) {
- std::string Error = EC.message();
- errs() << "Error loading index file '" << CodeGenOpts.ThinLTOIndexFile
- << "': " << Error << "\n";
- return;
- }
- ModuleSummary = std::move(IndexOrErr.get());
- assert(ModuleSummary && "Expected non-empty module summary index");
- }
-
legacy::PassManager PerModulePasses;
PerModulePasses.add(
createTargetTransformInfoWrapperPass(getTargetIRAnalysis()));
@@ -687,7 +653,7 @@ void EmitAssemblyHelper::EmitAssembly(BackendAction Action,
PerFunctionPasses.add(
createTargetTransformInfoWrapperPass(getTargetIRAnalysis()));
- CreatePasses(PerModulePasses, PerFunctionPasses, ModuleSummary.get());
+ CreatePasses(PerModulePasses, PerFunctionPasses);
legacy::PassManager CodeGenPasses;
CodeGenPasses.add(
@@ -740,15 +706,245 @@ void EmitAssemblyHelper::EmitAssembly(BackendAction Action,
}
}
+static PassBuilder::OptimizationLevel mapToLevel(const CodeGenOptions &Opts) {
+ switch (Opts.OptimizationLevel) {
+ default:
+ llvm_unreachable("Invalid optimization level!");
+
+ case 1:
+ return PassBuilder::O1;
+
+ case 2:
+ switch (Opts.OptimizeSize) {
+ default:
+ llvm_unreachable("Invalide optimization level for size!");
+
+ case 0:
+ return PassBuilder::O2;
+
+ case 1:
+ return PassBuilder::Os;
+
+ case 2:
+ return PassBuilder::Oz;
+ }
+
+ case 3:
+ return PassBuilder::O3;
+ }
+}
+
+/// A clean version of `EmitAssembly` that uses the new pass manager.
+///
+/// Not all features are currently supported in this system, but where
+/// necessary it falls back to the legacy pass manager to at least provide
+/// basic functionality.
+///
+/// This API is planned to have its functionality finished and then to replace
+/// `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);
+ setCommandLineOpts();
+
+ // The new pass manager always makes a target machine available to passes
+ // during construction.
+ CreateTargetMachine(/*MustCreateTM*/ true);
+ if (!TM)
+ // This will already be diagnosed, just bail.
+ return;
+ TheModule->setDataLayout(TM->createDataLayout());
+
+ PassBuilder PB(TM.get());
+
+ LoopAnalysisManager LAM;
+ FunctionAnalysisManager FAM;
+ CGSCCAnalysisManager CGAM;
+ ModuleAnalysisManager MAM;
+
+ // Register the AA manager first so that our version is the one used.
+ FAM.registerPass([&] { return PB.buildDefaultAAPipeline(); });
+
+ // Register all the basic analyses with the managers.
+ PB.registerModuleAnalyses(MAM);
+ PB.registerCGSCCAnalyses(CGAM);
+ PB.registerFunctionAnalyses(FAM);
+ PB.registerLoopAnalyses(LAM);
+ PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
+
+ ModulePassManager MPM;
+
+ if (!CodeGenOpts.DisableLLVMPasses) {
+ if (CodeGenOpts.OptimizationLevel == 0) {
+ // Build a minimal pipeline based on the semantics required by Clang,
+ // which is just that always inlining occurs.
+ MPM.addPass(AlwaysInlinerPass());
+ } else {
+ // Otherwise, use the default pass pipeline. We also have to map our
+ // optimization levels into one of the distinct levels used to configure
+ // the pipeline.
+ PassBuilder::OptimizationLevel Level = mapToLevel(CodeGenOpts);
+
+ MPM = PB.buildPerModuleDefaultPipeline(Level);
+ }
+ }
+
+ // FIXME: We still use the legacy pass manager to do code generation. We
+ // create that pass manager here and use it as needed below.
+ legacy::PassManager CodeGenPasses;
+ bool NeedCodeGen = false;
+
+ // Append any output we need to the pass manager.
+ switch (Action) {
+ case Backend_EmitNothing:
+ break;
+
+ case Backend_EmitBC:
+ MPM.addPass(BitcodeWriterPass(*OS, CodeGenOpts.EmitLLVMUseLists,
+ CodeGenOpts.EmitSummaryIndex,
+ CodeGenOpts.EmitSummaryIndex));
+ break;
+
+ case Backend_EmitLL:
+ MPM.addPass(PrintModulePass(*OS, "", CodeGenOpts.EmitLLVMUseLists));
+ break;
+
+ case Backend_EmitAssembly:
+ case Backend_EmitMCNull:
+ case Backend_EmitObj:
+ NeedCodeGen = true;
+ CodeGenPasses.add(
+ createTargetTransformInfoWrapperPass(getTargetIRAnalysis()));
+ if (!AddEmitPasses(CodeGenPasses, Action, *OS))
+ // FIXME: Should we handle this error differently?
+ return;
+ break;
+ }
+
+ // Before executing passes, print the final values of the LLVM options.
+ cl::PrintOptionValues();
+
+ // Now that we have all of the passes ready, run them.
+ {
+ PrettyStackTraceString CrashInfo("Optimizer");
+ MPM.run(*TheModule, MAM);
+ }
+
+ // Now if needed, run the legacy PM for codegen.
+ if (NeedCodeGen) {
+ PrettyStackTraceString CrashInfo("Code generation");
+ CodeGenPasses.run(*TheModule);
+ }
+}
+
+static void runThinLTOBackend(const CodeGenOptions &CGOpts, Module *M,
+ std::unique_ptr<raw_pwrite_stream> OS) {
+ // If we are performing a ThinLTO importing compile, load the function index
+ // into memory and pass it into thinBackend, which will run the function
+ // importer and invoke LTO passes.
+ Expected<std::unique_ptr<ModuleSummaryIndex>> IndexOrErr =
+ llvm::getModuleSummaryIndexForFile(CGOpts.ThinLTOIndexFile);
+ if (!IndexOrErr) {
+ logAllUnhandledErrors(IndexOrErr.takeError(), errs(),
+ "Error loading index file '" +
+ CGOpts.ThinLTOIndexFile + "': ");
+ return;
+ }
+ std::unique_ptr<ModuleSummaryIndex> CombinedIndex = std::move(*IndexOrErr);
+
+ StringMap<std::map<GlobalValue::GUID, GlobalValueSummary *>>
+ ModuleToDefinedGVSummaries;
+ CombinedIndex->collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);
+
+ // We can simply import the values mentioned in the combined index, since
+ // we should only invoke this using the individual indexes written out
+ // via a WriteIndexesThinBackend.
+ FunctionImporter::ImportMapTy ImportList;
+ for (auto &GlobalList : *CombinedIndex) {
+ auto GUID = GlobalList.first;
+ assert(GlobalList.second.size() == 1 &&
+ "Expected individual combined index to have one summary per GUID");
+ auto &Summary = GlobalList.second[0];
+ // Skip the summaries for the importing module. These are included to
+ // 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;
+ }
+
+ std::vector<std::unique_ptr<llvm::MemoryBuffer>> OwnedImports;
+ MapVector<llvm::StringRef, llvm::BitcodeModule> ModuleMap;
+
+ for (auto &I : ImportList) {
+ ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> MBOrErr =
+ llvm::MemoryBuffer::getFile(I.first());
+ if (!MBOrErr) {
+ errs() << "Error loading imported file '" << I.first()
+ << "': " << MBOrErr.getError().message() << "\n";
+ return;
+ }
+
+ Expected<std::vector<BitcodeModule>> BMsOrErr =
+ getBitcodeModuleList(**MBOrErr);
+ if (!BMsOrErr) {
+ handleAllErrors(BMsOrErr.takeError(), [&](ErrorInfoBase &EIB) {
+ errs() << "Error loading imported file '" << I.first()
+ << "': " << EIB.message() << '\n';
+ });
+ return;
+ }
+
+ // The bitcode file may contain multiple modules, we want the one with a
+ // summary.
+ bool FoundModule = false;
+ for (BitcodeModule &BM : *BMsOrErr) {
+ Expected<bool> HasSummary = BM.hasSummary();
+ if (HasSummary && *HasSummary) {
+ ModuleMap.insert({I.first(), BM});
+ FoundModule = true;
+ break;
+ }
+ }
+ if (!FoundModule) {
+ errs() << "Error loading imported file '" << I.first()
+ << "': Could not find module summary\n";
+ return;
+ }
+
+ OwnedImports.push_back(std::move(*MBOrErr));
+ }
+ auto AddStream = [&](size_t Task) {
+ return llvm::make_unique<lto::NativeObjectStream>(std::move(OS));
+ };
+ lto::Config Conf;
+ if (Error E = thinBackend(
+ Conf, 0, AddStream, *M, *CombinedIndex, ImportList,
+ ModuleToDefinedGVSummaries[M->getModuleIdentifier()], ModuleMap)) {
+ handleAllErrors(std::move(E), [&](ErrorInfoBase &EIB) {
+ errs() << "Error running ThinLTO backend: " << EIB.message() << '\n';
+ });
+ }
+}
+
void clang::EmitBackendOutput(DiagnosticsEngine &Diags,
const CodeGenOptions &CGOpts,
const clang::TargetOptions &TOpts,
const LangOptions &LOpts, const llvm::DataLayout &TDesc,
Module *M, BackendAction Action,
std::unique_ptr<raw_pwrite_stream> OS) {
+ if (!CGOpts.ThinLTOIndexFile.empty()) {
+ runThinLTOBackend(CGOpts, M, std::move(OS));
+ return;
+ }
+
EmitAssemblyHelper AsmHelper(Diags, CGOpts, TOpts, LOpts, M);
- AsmHelper.EmitAssembly(Action, std::move(OS));
+ if (CGOpts.ExperimentalNewPassManager)
+ AsmHelper.EmitAssemblyWithNewPassManager(Action, std::move(OS));
+ else
+ AsmHelper.EmitAssembly(Action, std::move(OS));
// Verify clang's TargetInfo DataLayout against the LLVM TargetMachine's
// DataLayout.
diff --git a/lib/CodeGen/CGAtomic.cpp b/lib/CodeGen/CGAtomic.cpp
index 7b747c138303..9287e46127bd 100644
--- a/lib/CodeGen/CGAtomic.cpp
+++ b/lib/CodeGen/CGAtomic.cpp
@@ -11,13 +11,12 @@
//
//===----------------------------------------------------------------------===//
-#include "CodeGenFunction.h"
#include "CGCall.h"
#include "CGRecordLayout.h"
+#include "CodeGenFunction.h"
#include "CodeGenModule.h"
#include "clang/AST/ASTContext.h"
#include "clang/CodeGen/CGFunctionInfo.h"
-#include "llvm/ADT/StringExtras.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/Operator.h"
@@ -308,7 +307,8 @@ static RValue emitAtomicLibcall(CodeGenFunction &CGF,
CGF.CGM.getTypes().arrangeBuiltinFunctionCall(resultType, args);
llvm::FunctionType *fnTy = CGF.CGM.getTypes().GetFunctionType(fnInfo);
llvm::Constant *fn = CGF.CGM.CreateRuntimeFunction(fnTy, fnName);
- return CGF.EmitCall(fnInfo, fn, ReturnValueSlot(), args);
+ auto callee = CGCallee::forDirect(fn);
+ return CGF.EmitCall(fnInfo, callee, ReturnValueSlot(), args);
}
/// Does a store of the given IR type modify the full expected width?
diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp
index e3658ab9b762..b250b9a32b18 100644
--- a/lib/CodeGen/CGBlocks.cpp
+++ b/lib/CodeGen/CGBlocks.cpp
@@ -16,6 +16,7 @@
#include "CGObjCRuntime.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
+#include "ConstantBuilder.h"
#include "clang/AST/DeclObjC.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/IR/CallSite.h"
@@ -77,63 +78,63 @@ static llvm::Constant *buildBlockDescriptor(CodeGenModule &CGM,
const CGBlockInfo &blockInfo) {
ASTContext &C = CGM.getContext();
- llvm::Type *ulong = CGM.getTypes().ConvertType(C.UnsignedLongTy);
- llvm::Type *i8p = nullptr;
+ llvm::IntegerType *ulong =
+ cast<llvm::IntegerType>(CGM.getTypes().ConvertType(C.UnsignedLongTy));
+ llvm::PointerType *i8p = nullptr;
if (CGM.getLangOpts().OpenCL)
i8p =
llvm::Type::getInt8PtrTy(
CGM.getLLVMContext(), C.getTargetAddressSpace(LangAS::opencl_constant));
else
- i8p = CGM.getTypes().ConvertType(C.VoidPtrTy);
+ i8p = CGM.VoidPtrTy;
- SmallVector<llvm::Constant*, 6> elements;
+ ConstantInitBuilder builder(CGM);
+ auto elements = builder.beginStruct();
// reserved
- elements.push_back(llvm::ConstantInt::get(ulong, 0));
+ elements.addInt(ulong, 0);
// Size
// FIXME: What is the right way to say this doesn't fit? We should give
// a user diagnostic in that case. Better fix would be to change the
// API to size_t.
- elements.push_back(llvm::ConstantInt::get(ulong,
- blockInfo.BlockSize.getQuantity()));
+ elements.addInt(ulong, blockInfo.BlockSize.getQuantity());
// Optional copy/dispose helpers.
if (blockInfo.NeedsCopyDispose) {
// copy_func_helper_decl
- elements.push_back(buildCopyHelper(CGM, blockInfo));
+ elements.add(buildCopyHelper(CGM, blockInfo));
// destroy_func_decl
- elements.push_back(buildDisposeHelper(CGM, blockInfo));
+ elements.add(buildDisposeHelper(CGM, blockInfo));
}
// Signature. Mandatory ObjC-style method descriptor @encode sequence.
std::string typeAtEncoding =
CGM.getContext().getObjCEncodingForBlock(blockInfo.getBlockExpr());
- elements.push_back(llvm::ConstantExpr::getBitCast(
+ elements.add(llvm::ConstantExpr::getBitCast(
CGM.GetAddrOfConstantCString(typeAtEncoding).getPointer(), i8p));
// GC layout.
if (C.getLangOpts().ObjC1) {
if (CGM.getLangOpts().getGC() != LangOptions::NonGC)
- elements.push_back(CGM.getObjCRuntime().BuildGCBlockLayout(CGM, blockInfo));
+ elements.add(CGM.getObjCRuntime().BuildGCBlockLayout(CGM, blockInfo));
else
- elements.push_back(CGM.getObjCRuntime().BuildRCBlockLayout(CGM, blockInfo));
+ elements.add(CGM.getObjCRuntime().BuildRCBlockLayout(CGM, blockInfo));
}
else
- elements.push_back(llvm::Constant::getNullValue(i8p));
-
- llvm::Constant *init = llvm::ConstantStruct::getAnon(elements);
+ elements.addNullPointer(i8p);
unsigned AddrSpace = 0;
if (C.getLangOpts().OpenCL)
AddrSpace = C.getTargetAddressSpace(LangAS::opencl_constant);
+
llvm::GlobalVariable *global =
- new llvm::GlobalVariable(CGM.getModule(), init->getType(), true,
- llvm::GlobalValue::InternalLinkage,
- init, "__block_descriptor_tmp", nullptr,
- llvm::GlobalValue::NotThreadLocal,
- AddrSpace);
+ elements.finishAndCreateGlobal("__block_descriptor_tmp",
+ CGM.getPointerAlign(),
+ /*constant*/ true,
+ llvm::GlobalValue::InternalLinkage,
+ AddrSpace);
return llvm::ConstantExpr::getBitCast(global, CGM.getBlockDescriptorType());
}
@@ -188,9 +189,6 @@ static llvm::Constant *buildBlockDescriptor(CodeGenModule &CGM,
};
*/
-/// The number of fields in a block header.
-const unsigned BlockHeaderSize = 5;
-
namespace {
/// A chunk of data that we actually have to capture in the block.
struct BlockLayoutChunk {
@@ -199,13 +197,14 @@ namespace {
Qualifiers::ObjCLifetime Lifetime;
const BlockDecl::Capture *Capture; // null for 'this'
llvm::Type *Type;
+ QualType FieldType;
BlockLayoutChunk(CharUnits align, CharUnits size,
Qualifiers::ObjCLifetime lifetime,
const BlockDecl::Capture *capture,
- llvm::Type *type)
+ llvm::Type *type, QualType fieldType)
: Alignment(align), Size(size), Lifetime(lifetime),
- Capture(capture), Type(type) {}
+ Capture(capture), Type(type), FieldType(fieldType) {}
/// Tell the block info that this chunk has the given field index.
void setIndex(CGBlockInfo &info, unsigned index, CharUnits offset) {
@@ -213,8 +212,8 @@ namespace {
info.CXXThisIndex = index;
info.CXXThisOffset = offset;
} else {
- info.Captures.insert({Capture->getVariable(),
- CGBlockInfo::Capture::makeIndex(index, offset)});
+ auto C = CGBlockInfo::Capture::makeIndex(index, offset, FieldType);
+ info.Captures.insert({Capture->getVariable(), C});
}
}
};
@@ -317,8 +316,6 @@ static void initializeForBlockHeader(CodeGenModule &CGM, CGBlockInfo &info,
elementTypes.push_back(CGM.IntTy);
elementTypes.push_back(CGM.VoidPtrTy);
elementTypes.push_back(CGM.getBlockDescriptorType());
-
- assert(elementTypes.size() == BlockHeaderSize);
}
/// Compute the layout of the given block. Attempts to lay the block
@@ -363,7 +360,7 @@ static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF,
layout.push_back(BlockLayoutChunk(tinfo.second, tinfo.first,
Qualifiers::OCL_None,
- nullptr, llvmType));
+ nullptr, llvmType, thisType));
}
// Next, all the block captures.
@@ -380,7 +377,7 @@ static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF,
layout.push_back(BlockLayoutChunk(align, CGM.getPointerSize(),
Qualifiers::OCL_None, &CI,
- CGM.VoidPtrTy));
+ CGM.VoidPtrTy, variable->getType()));
continue;
}
@@ -436,6 +433,14 @@ static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF,
}
QualType VT = variable->getType();
+
+ // If the variable is captured by an enclosing block or lambda expression,
+ // use the type of the capture field.
+ if (CGF->BlockInfo && CI.isNested())
+ VT = CGF->BlockInfo->getCapture(variable).fieldType();
+ else if (auto *FD = CGF->LambdaCaptureFields.lookup(variable))
+ VT = FD->getType();
+
CharUnits size = C.getTypeSizeInChars(VT);
CharUnits align = C.getDeclAlign(variable);
@@ -444,7 +449,8 @@ static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF,
llvm::Type *llvmType =
CGM.getTypes().ConvertTypeForMem(VT);
- layout.push_back(BlockLayoutChunk(align, size, lifetime, &CI, llvmType));
+ layout.push_back(
+ BlockLayoutChunk(align, size, lifetime, &CI, llvmType, VT));
}
// If that was everything, we're done here.
@@ -680,6 +686,8 @@ 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()) {
+ if (llvm::Constant *Block = CGM.getAddrOfGlobalBlockIfEmitted(blockExpr))
+ return Block;
CGBlockInfo blockInfo(blockExpr->getBlockDecl(), CurFn->getName());
computeBlockInfo(CGM, this, blockInfo);
blockInfo.BlockExpression = blockExpr;
@@ -775,7 +783,7 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
// Ignore constant captures.
if (capture.isConstant()) continue;
- QualType type = variable->getType();
+ QualType type = capture.fieldType();
// This will be a [[type]]*, except that a byref entry will just be
// an i8**.
@@ -965,25 +973,24 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E,
const BlockPointerType *BPT =
E->getCallee()->getType()->getAs<BlockPointerType>();
- llvm::Value *Callee = EmitScalarExpr(E->getCallee());
+ llvm::Value *BlockPtr = EmitScalarExpr(E->getCallee());
// Get a pointer to the generic block literal.
llvm::Type *BlockLiteralTy =
llvm::PointerType::getUnqual(CGM.getGenericBlockLiteralType());
// Bitcast the callee to a block literal.
- llvm::Value *BlockLiteral =
- Builder.CreateBitCast(Callee, BlockLiteralTy, "block.literal");
+ BlockPtr = Builder.CreateBitCast(BlockPtr, BlockLiteralTy, "block.literal");
// Get the function pointer from the literal.
llvm::Value *FuncPtr =
- Builder.CreateStructGEP(CGM.getGenericBlockLiteralType(), BlockLiteral, 3);
+ Builder.CreateStructGEP(CGM.getGenericBlockLiteralType(), BlockPtr, 3);
- BlockLiteral = Builder.CreateBitCast(BlockLiteral, VoidPtrTy);
+ BlockPtr = Builder.CreateBitCast(BlockPtr, VoidPtrTy);
// Add the block literal.
CallArgList Args;
- Args.add(RValue::get(BlockLiteral), getContext().VoidPtrTy);
+ Args.add(RValue::get(BlockPtr), getContext().VoidPtrTy);
QualType FnType = BPT->getPointeeType();
@@ -1003,8 +1010,11 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E,
llvm::Type *BlockFTyPtr = llvm::PointerType::getUnqual(BlockFTy);
Func = Builder.CreateBitCast(Func, BlockFTyPtr);
+ // Prepare the callee.
+ CGCallee Callee(CGCalleeInfo(), Func);
+
// And call the block.
- return EmitCall(FnInfo, Func, ReturnValue, Args);
+ return EmitCall(FnInfo, Callee, ReturnValue, Args);
}
Address CodeGenFunction::GetAddrOfBlockDecl(const VarDecl *variable,
@@ -1033,18 +1043,27 @@ Address CodeGenFunction::GetAddrOfBlockDecl(const VarDecl *variable,
variable->getName());
}
- if (auto refType = variable->getType()->getAs<ReferenceType>()) {
+ if (auto refType = capture.fieldType()->getAs<ReferenceType>())
addr = EmitLoadOfReference(addr, refType);
- }
return addr;
}
+void CodeGenModule::setAddrOfGlobalBlock(const BlockExpr *BE,
+ llvm::Constant *Addr) {
+ bool Ok = EmittedGlobalBlocks.insert(std::make_pair(BE, Addr)).second;
+ (void)Ok;
+ assert(Ok && "Trying to replace an already-existing global block!");
+}
+
llvm::Constant *
-CodeGenModule::GetAddrOfGlobalBlock(const BlockExpr *blockExpr,
- const char *name) {
- CGBlockInfo blockInfo(blockExpr->getBlockDecl(), name);
- blockInfo.BlockExpression = blockExpr;
+CodeGenModule::GetAddrOfGlobalBlock(const BlockExpr *BE,
+ StringRef Name) {
+ if (llvm::Constant *Block = getAddrOfGlobalBlockIfEmitted(BE))
+ return Block;
+
+ CGBlockInfo blockInfo(BE->getBlockDecl(), Name);
+ blockInfo.BlockExpression = BE;
// Compute information about the layout, etc., of this block.
computeBlockInfo(*this, nullptr, blockInfo);
@@ -1067,43 +1086,46 @@ static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM,
const CGBlockInfo &blockInfo,
llvm::Constant *blockFn) {
assert(blockInfo.CanBeGlobal);
+ // Callers should detect this case on their own: calling this function
+ // generally requires computing layout information, which is a waste of time
+ // if we've already emitted this block.
+ assert(!CGM.getAddrOfGlobalBlockIfEmitted(blockInfo.BlockExpression) &&
+ "Refusing to re-emit a global block.");
// Generate the constants for the block literal initializer.
- llvm::Constant *fields[BlockHeaderSize];
+ ConstantInitBuilder builder(CGM);
+ auto fields = builder.beginStruct();
// isa
- fields[0] = CGM.getNSConcreteGlobalBlock();
+ fields.add(CGM.getNSConcreteGlobalBlock());
// __flags
BlockFlags flags = BLOCK_IS_GLOBAL | BLOCK_HAS_SIGNATURE;
if (blockInfo.UsesStret) flags |= BLOCK_USE_STRET;
- fields[1] = llvm::ConstantInt::get(CGM.IntTy, flags.getBitMask());
+ fields.addInt(CGM.IntTy, flags.getBitMask());
// Reserved
- fields[2] = llvm::Constant::getNullValue(CGM.IntTy);
+ fields.addInt(CGM.IntTy, 0);
// Function
- fields[3] = blockFn;
+ fields.add(blockFn);
// Descriptor
- fields[4] = buildBlockDescriptor(CGM, blockInfo);
-
- llvm::Constant *init = llvm::ConstantStruct::getAnon(fields);
+ fields.add(buildBlockDescriptor(CGM, blockInfo));
- llvm::GlobalVariable *literal =
- new llvm::GlobalVariable(CGM.getModule(),
- init->getType(),
- /*constant*/ true,
- llvm::GlobalVariable::InternalLinkage,
- init,
- "__block_literal_global");
- literal->setAlignment(blockInfo.BlockAlign.getQuantity());
+ llvm::Constant *literal =
+ fields.finishAndCreateGlobal("__block_literal_global",
+ blockInfo.BlockAlign,
+ /*constant*/ true);
// Return a constant of the appropriately-casted type.
- llvm::Type *requiredType =
+ llvm::Type *RequiredType =
CGM.getTypes().ConvertType(blockInfo.getBlockExpr()->getType());
- return llvm::ConstantExpr::getBitCast(literal, requiredType);
+ llvm::Constant *Result =
+ llvm::ConstantExpr::getBitCast(literal, RequiredType);
+ CGM.setAddrOfGlobalBlock(blockInfo.BlockExpression, Result);
+ return Result;
}
void CodeGenFunction::setBlockContextParameter(const ImplicitParamDecl *D,
@@ -1939,7 +1961,7 @@ static T *buildByrefHelpers(CodeGenModule &CGM, const BlockByrefInfo &byrefInfo,
generator.CopyHelper = buildByrefCopyHelper(CGM, byrefInfo, generator);
generator.DisposeHelper = buildByrefDisposeHelper(CGM, byrefInfo, generator);
- T *copy = new (CGM.getContext()) T(std::move(generator));
+ T *copy = new (CGM.getContext()) T(std::forward<T>(generator));
CGM.ByrefHelpersCache.InsertNode(copy, insertPos);
return copy;
}
diff --git a/lib/CodeGen/CGBlocks.h b/lib/CodeGen/CGBlocks.h
index 1edabef4ec74..80e255f75417 100644
--- a/lib/CodeGen/CGBlocks.h
+++ b/lib/CodeGen/CGBlocks.h
@@ -25,10 +25,8 @@
#include "clang/AST/ExprObjC.h"
#include "clang/AST/Type.h"
#include "clang/Basic/TargetInfo.h"
-#include "llvm/IR/Module.h"
namespace llvm {
-class Module;
class Constant;
class Function;
class GlobalValue;
@@ -40,10 +38,8 @@ class LLVMContext;
}
namespace clang {
-
namespace CodeGen {
-class CodeGenModule;
class CGBlockInfo;
// Flags stored in __block variables.
@@ -163,6 +159,11 @@ public:
EHScopeStack::stable_iterator Cleanup;
CharUnits::QuantityType Offset;
+ /// Type of the capture field. Normally, this is identical to the type of
+ /// the capture's VarDecl, but can be different if there is an enclosing
+ /// lambda.
+ QualType FieldType;
+
public:
bool isIndex() const { return (Data & 1) != 0; }
bool isConstant() const { return !isIndex(); }
@@ -189,10 +190,16 @@ public:
return reinterpret_cast<llvm::Value*>(Data);
}
- static Capture makeIndex(unsigned index, CharUnits offset) {
+ QualType fieldType() const {
+ return FieldType;
+ }
+
+ static Capture makeIndex(unsigned index, CharUnits offset,
+ QualType FieldType) {
Capture v;
v.Data = (index << 1) | 1;
v.Offset = offset.getQuantity();
+ v.FieldType = FieldType;
return v;
}
diff --git a/lib/CodeGen/CGBuilder.h b/lib/CodeGen/CGBuilder.h
index 027435d7c599..42f9a428bb3a 100644
--- a/lib/CodeGen/CGBuilder.h
+++ b/lib/CodeGen/CGBuilder.h
@@ -102,11 +102,6 @@ public:
assert(Addr->getType()->getPointerElementType() == Ty);
return CreateAlignedLoad(Addr, Align.getQuantity(), Name);
}
- llvm::LoadInst *CreateAlignedLoad(llvm::Value *Addr, CharUnits Align,
- bool IsVolatile,
- const llvm::Twine &Name = "") {
- return CreateAlignedLoad(Addr, Align.getQuantity(), IsVolatile, Name);
- }
// Note that we intentionally hide the CreateStore APIs that don't
// take an alignment.
@@ -124,19 +119,6 @@ public:
// FIXME: these "default-aligned" APIs should be removed,
// but I don't feel like fixing all the builtin code right now.
- llvm::LoadInst *CreateDefaultAlignedLoad(llvm::Value *Addr,
- const llvm::Twine &Name = "") {
- return CGBuilderBaseTy::CreateLoad(Addr, false, Name);
- }
- llvm::LoadInst *CreateDefaultAlignedLoad(llvm::Value *Addr,
- const char *Name) {
- return CGBuilderBaseTy::CreateLoad(Addr, false, Name);
- }
- llvm::LoadInst *CreateDefaultAlignedLoad(llvm::Value *Addr, bool IsVolatile,
- const llvm::Twine &Name = "") {
- return CGBuilderBaseTy::CreateLoad(Addr, IsVolatile, Name);
- }
-
llvm::StoreInst *CreateDefaultAlignedStore(llvm::Value *Val,
llvm::Value *Addr,
bool IsVolatile = false) {
diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp
index a5fc53113bdc..43ca74761fbd 100644
--- a/lib/CodeGen/CGBuiltin.cpp
+++ b/lib/CodeGen/CGBuiltin.cpp
@@ -11,13 +11,15 @@
//
//===----------------------------------------------------------------------===//
-#include "CodeGenFunction.h"
#include "CGCXXABI.h"
#include "CGObjCRuntime.h"
+#include "CGOpenCLRuntime.h"
+#include "CodeGenFunction.h"
#include "CodeGenModule.h"
#include "TargetInfo.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
+#include "clang/Analysis/Analyses/OSLog.h"
#include "clang/Basic/TargetBuiltins.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/CodeGen/CGFunctionInfo.h"
@@ -35,8 +37,8 @@ using namespace llvm;
/// getBuiltinLibFunction - Given a builtin id for a function like
/// "__builtin_fabsf", return a Function* for "fabsf".
-llvm::Value *CodeGenModule::getBuiltinLibFunction(const FunctionDecl *FD,
- unsigned BuiltinID) {
+llvm::Constant *CodeGenModule::getBuiltinLibFunction(const FunctionDecl *FD,
+ unsigned BuiltinID) {
assert(Context.BuiltinInfo.isLibFunction(BuiltinID));
// Get the name, skip over the __builtin_ prefix (if necessary).
@@ -302,10 +304,10 @@ static Value *EmitSignBit(CodeGenFunction &CGF, Value *V) {
return CGF.Builder.CreateICmpSLT(V, Zero);
}
-static RValue emitLibraryCall(CodeGenFunction &CGF, const FunctionDecl *Fn,
- const CallExpr *E, llvm::Value *calleeValue) {
- return CGF.EmitCall(E->getCallee()->getType(), calleeValue, E,
- ReturnValueSlot(), Fn);
+static RValue emitLibraryCall(CodeGenFunction &CGF, const FunctionDecl *FD,
+ const CallExpr *E, llvm::Constant *calleeValue) {
+ CGCallee callee = CGCallee::forDirect(calleeValue, FD);
+ return CGF.EmitCall(E->getCallee()->getType(), callee, E, ReturnValueSlot());
}
/// \brief Emit a call to llvm.{sadd,uadd,ssub,usub,smul,umul}.with.overflow.*
@@ -462,6 +464,119 @@ CodeGenFunction::emitBuiltinObjectSize(const Expr *E, unsigned Type,
return Builder.CreateCall(F, {EmitScalarExpr(E), CI});
}
+// Many of MSVC builtins are on both x64 and ARM; to avoid repeating code, we
+// handle them here.
+enum class CodeGenFunction::MSVCIntrin {
+ _BitScanForward,
+ _BitScanReverse,
+ _InterlockedAnd,
+ _InterlockedDecrement,
+ _InterlockedExchange,
+ _InterlockedExchangeAdd,
+ _InterlockedExchangeSub,
+ _InterlockedIncrement,
+ _InterlockedOr,
+ _InterlockedXor,
+};
+
+Value *CodeGenFunction::EmitMSVCBuiltinExpr(MSVCIntrin BuiltinID,
+ const CallExpr *E) {
+ switch (BuiltinID) {
+ case MSVCIntrin::_BitScanForward:
+ case MSVCIntrin::_BitScanReverse: {
+ Value *ArgValue = EmitScalarExpr(E->getArg(1));
+
+ llvm::Type *ArgType = ArgValue->getType();
+ llvm::Type *IndexType =
+ EmitScalarExpr(E->getArg(0))->getType()->getPointerElementType();
+ llvm::Type *ResultType = ConvertType(E->getType());
+
+ Value *ArgZero = llvm::Constant::getNullValue(ArgType);
+ Value *ResZero = llvm::Constant::getNullValue(ResultType);
+ Value *ResOne = llvm::ConstantInt::get(ResultType, 1);
+
+ BasicBlock *Begin = Builder.GetInsertBlock();
+ BasicBlock *End = createBasicBlock("bitscan_end", this->CurFn);
+ Builder.SetInsertPoint(End);
+ PHINode *Result = Builder.CreatePHI(ResultType, 2, "bitscan_result");
+
+ Builder.SetInsertPoint(Begin);
+ Value *IsZero = Builder.CreateICmpEQ(ArgValue, ArgZero);
+ BasicBlock *NotZero = createBasicBlock("bitscan_not_zero", this->CurFn);
+ Builder.CreateCondBr(IsZero, End, NotZero);
+ Result->addIncoming(ResZero, Begin);
+
+ Builder.SetInsertPoint(NotZero);
+ Address IndexAddress = EmitPointerWithAlignment(E->getArg(0));
+
+ if (BuiltinID == MSVCIntrin::_BitScanForward) {
+ Value *F = CGM.getIntrinsic(Intrinsic::cttz, ArgType);
+ Value *ZeroCount = Builder.CreateCall(F, {ArgValue, Builder.getTrue()});
+ ZeroCount = Builder.CreateIntCast(ZeroCount, IndexType, false);
+ Builder.CreateStore(ZeroCount, IndexAddress, false);
+ } else {
+ unsigned ArgWidth = cast<llvm::IntegerType>(ArgType)->getBitWidth();
+ Value *ArgTypeLastIndex = llvm::ConstantInt::get(IndexType, ArgWidth - 1);
+
+ Value *F = CGM.getIntrinsic(Intrinsic::ctlz, ArgType);
+ Value *ZeroCount = Builder.CreateCall(F, {ArgValue, Builder.getTrue()});
+ ZeroCount = Builder.CreateIntCast(ZeroCount, IndexType, false);
+ Value *Index = Builder.CreateNSWSub(ArgTypeLastIndex, ZeroCount);
+ Builder.CreateStore(Index, IndexAddress, false);
+ }
+ Builder.CreateBr(End);
+ Result->addIncoming(ResOne, NotZero);
+
+ Builder.SetInsertPoint(End);
+ return Result;
+ }
+ case MSVCIntrin::_InterlockedAnd:
+ return MakeBinaryAtomicValue(*this, AtomicRMWInst::And, E);
+ case MSVCIntrin::_InterlockedExchange:
+ return MakeBinaryAtomicValue(*this, AtomicRMWInst::Xchg, E);
+ case MSVCIntrin::_InterlockedExchangeAdd:
+ return MakeBinaryAtomicValue(*this, AtomicRMWInst::Add, E);
+ case MSVCIntrin::_InterlockedExchangeSub:
+ return MakeBinaryAtomicValue(*this, AtomicRMWInst::Sub, E);
+ case MSVCIntrin::_InterlockedOr:
+ return MakeBinaryAtomicValue(*this, AtomicRMWInst::Or, E);
+ case MSVCIntrin::_InterlockedXor:
+ return MakeBinaryAtomicValue(*this, AtomicRMWInst::Xor, E);
+
+ case MSVCIntrin::_InterlockedDecrement: {
+ llvm::Type *IntTy = ConvertType(E->getType());
+ AtomicRMWInst *RMWI = Builder.CreateAtomicRMW(
+ AtomicRMWInst::Sub,
+ EmitScalarExpr(E->getArg(0)),
+ ConstantInt::get(IntTy, 1),
+ llvm::AtomicOrdering::SequentiallyConsistent);
+ return Builder.CreateSub(RMWI, ConstantInt::get(IntTy, 1));
+ }
+ case MSVCIntrin::_InterlockedIncrement: {
+ llvm::Type *IntTy = ConvertType(E->getType());
+ AtomicRMWInst *RMWI = Builder.CreateAtomicRMW(
+ AtomicRMWInst::Add,
+ EmitScalarExpr(E->getArg(0)),
+ ConstantInt::get(IntTy, 1),
+ llvm::AtomicOrdering::SequentiallyConsistent);
+ return Builder.CreateAdd(RMWI, ConstantInt::get(IntTy, 1));
+ }
+ }
+ llvm_unreachable("Incorrect MSVC intrinsic!");
+}
+
+namespace {
+// ARC cleanup for __builtin_os_log_format
+struct CallObjCArcUse final : EHScopeStack::Cleanup {
+ CallObjCArcUse(llvm::Value *object) : object(object) {}
+ llvm::Value *object;
+
+ void Emit(CodeGenFunction &CGF, Flags flags) override {
+ CGF.EmitARCIntrinsicUse(object);
+ }
+};
+}
+
RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
unsigned BuiltinID, const CallExpr *E,
ReturnValueSlot ReturnValue) {
@@ -681,6 +796,9 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
"cast");
return RValue::get(Result);
}
+ case Builtin::BI__popcnt16:
+ case Builtin::BI__popcnt:
+ case Builtin::BI__popcnt64:
case Builtin::BI__builtin_popcount:
case Builtin::BI__builtin_popcountl:
case Builtin::BI__builtin_popcountll: {
@@ -696,6 +814,58 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
"cast");
return RValue::get(Result);
}
+ case Builtin::BI_rotr8:
+ case Builtin::BI_rotr16:
+ case Builtin::BI_rotr:
+ case Builtin::BI_lrotr:
+ case Builtin::BI_rotr64: {
+ Value *Val = EmitScalarExpr(E->getArg(0));
+ Value *Shift = EmitScalarExpr(E->getArg(1));
+
+ 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);
+
+ 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);
+ return RValue::get(Result);
+ }
+ case Builtin::BI_rotl8:
+ case Builtin::BI_rotl16:
+ case Builtin::BI_rotl:
+ case Builtin::BI_lrotl:
+ case Builtin::BI_rotl64: {
+ Value *Val = EmitScalarExpr(E->getArg(0));
+ Value *Shift = EmitScalarExpr(E->getArg(1));
+
+ 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);
+
+ 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);
+ return RValue::get(Result);
+ }
case Builtin::BI__builtin_unpredictable: {
// Always return the argument of __builtin_unpredictable. LLVM does not
// handle this builtin. Metadata for this builtin should be added directly
@@ -789,8 +959,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
SanitizerScope SanScope(this);
EmitCheck(std::make_pair(static_cast<llvm::Value *>(Builder.getFalse()),
SanitizerKind::Unreachable),
- "builtin_unreachable", EmitCheckSourceLocation(E->getExprLoc()),
- None);
+ SanitizerHandler::BuiltinUnreachable,
+ EmitCheckSourceLocation(E->getExprLoc()), None);
} else
Builder.CreateUnreachable();
@@ -851,6 +1021,12 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
return RValue::get(Builder.CreateZExt(V, ConvertType(E->getType())));
}
+ case Builtin::BIfinite:
+ case Builtin::BI__finite:
+ case Builtin::BIfinitef:
+ case Builtin::BI__finitef:
+ case Builtin::BIfinitel:
+ case Builtin::BI__finitel:
case Builtin::BI__builtin_isinf:
case Builtin::BI__builtin_isfinite: {
// isinf(x) --> fabs(x) == infinity
@@ -963,8 +1139,29 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
case Builtin::BI_alloca:
case Builtin::BI__builtin_alloca: {
Value *Size = EmitScalarExpr(E->getArg(0));
- return RValue::get(Builder.CreateAlloca(Builder.getInt8Ty(), Size));
+ const TargetInfo &TI = getContext().getTargetInfo();
+ // The alignment of the alloca should correspond to __BIGGEST_ALIGNMENT__.
+ unsigned SuitableAlignmentInBytes =
+ CGM.getContext()
+ .toCharUnitsFromBits(TI.getSuitableAlign())
+ .getQuantity();
+ AllocaInst *AI = Builder.CreateAlloca(Builder.getInt8Ty(), Size);
+ AI->setAlignment(SuitableAlignmentInBytes);
+ return RValue::get(AI);
+ }
+
+ case Builtin::BI__builtin_alloca_with_align: {
+ Value *Size = EmitScalarExpr(E->getArg(0));
+ Value *AlignmentInBitsValue = EmitScalarExpr(E->getArg(1));
+ auto *AlignmentInBitsCI = cast<ConstantInt>(AlignmentInBitsValue);
+ unsigned AlignmentInBits = AlignmentInBitsCI->getZExtValue();
+ unsigned AlignmentInBytes =
+ CGM.getContext().toCharUnitsFromBits(AlignmentInBits).getQuantity();
+ AllocaInst *AI = Builder.CreateAlloca(Builder.getInt8Ty(), Size);
+ AI->setAlignment(AlignmentInBytes);
+ return RValue::get(AI);
}
+
case Builtin::BIbzero:
case Builtin::BI__builtin_bzero: {
Address Dest = EmitPointerWithAlignment(E->getArg(0));
@@ -1085,6 +1282,10 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
Value *F = CGM.getIntrinsic(Intrinsic::returnaddress);
return RValue::get(Builder.CreateCall(F, Depth));
}
+ case Builtin::BI_ReturnAddress: {
+ Value *F = CGM.getIntrinsic(Intrinsic::returnaddress);
+ return RValue::get(Builder.CreateCall(F, Builder.getInt32(0)));
+ }
case Builtin::BI__builtin_frame_address: {
Value *Depth =
CGM.EmitConstantExpr(E->getArg(0), getContext().UnsignedIntTy, this);
@@ -1390,7 +1591,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
CGM.getTypes().arrangeBuiltinFunctionCall(E->getType(), Args);
llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FuncInfo);
llvm::Constant *Func = CGM.CreateRuntimeFunction(FTy, LibCallName);
- return EmitCall(FuncInfo, Func, ReturnValueSlot(), Args);
+ return EmitCall(FuncInfo, CGCallee::forDirect(Func),
+ ReturnValueSlot(), Args);
}
case Builtin::BI__atomic_test_and_set: {
@@ -1905,12 +2107,15 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
const CallExpr *Call = cast<CallExpr>(E->getArg(0));
const Expr *Chain = E->getArg(1);
return EmitCall(Call->getCallee()->getType(),
- EmitScalarExpr(Call->getCallee()), Call, ReturnValue,
- Call->getCalleeDecl(), EmitScalarExpr(Chain));
+ EmitCallee(Call->getCallee()), Call, ReturnValue,
+ EmitScalarExpr(Chain));
}
+ case Builtin::BI_InterlockedExchange8:
+ case Builtin::BI_InterlockedExchange16:
case Builtin::BI_InterlockedExchange:
case Builtin::BI_InterlockedExchangePointer:
- return EmitBinaryAtomic(*this, llvm::AtomicRMWInst::Xchg, E);
+ return RValue::get(
+ EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchange, E));
case Builtin::BI_InterlockedCompareExchangePointer: {
llvm::Type *RTy;
llvm::IntegerType *IntType =
@@ -1938,7 +2143,10 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
0),
RTy));
}
- case Builtin::BI_InterlockedCompareExchange: {
+ case Builtin::BI_InterlockedCompareExchange8:
+ case Builtin::BI_InterlockedCompareExchange16:
+ case Builtin::BI_InterlockedCompareExchange:
+ case Builtin::BI_InterlockedCompareExchange64: {
AtomicCmpXchgInst *CXI = Builder.CreateAtomicCmpXchg(
EmitScalarExpr(E->getArg(0)),
EmitScalarExpr(E->getArg(2)),
@@ -1948,42 +2156,44 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
CXI->setVolatile(true);
return RValue::get(Builder.CreateExtractValue(CXI, 0));
}
- case Builtin::BI_InterlockedIncrement: {
- llvm::Type *IntTy = ConvertType(E->getType());
- AtomicRMWInst *RMWI = Builder.CreateAtomicRMW(
- AtomicRMWInst::Add,
- EmitScalarExpr(E->getArg(0)),
- ConstantInt::get(IntTy, 1),
- llvm::AtomicOrdering::SequentiallyConsistent);
- RMWI->setVolatile(true);
- return RValue::get(Builder.CreateAdd(RMWI, ConstantInt::get(IntTy, 1)));
- }
- case Builtin::BI_InterlockedDecrement: {
- llvm::Type *IntTy = ConvertType(E->getType());
- AtomicRMWInst *RMWI = Builder.CreateAtomicRMW(
- AtomicRMWInst::Sub,
- EmitScalarExpr(E->getArg(0)),
- ConstantInt::get(IntTy, 1),
- llvm::AtomicOrdering::SequentiallyConsistent);
- RMWI->setVolatile(true);
- return RValue::get(Builder.CreateSub(RMWI, ConstantInt::get(IntTy, 1)));
- }
- case Builtin::BI_InterlockedExchangeAdd: {
- AtomicRMWInst *RMWI = Builder.CreateAtomicRMW(
- AtomicRMWInst::Add,
- EmitScalarExpr(E->getArg(0)),
- EmitScalarExpr(E->getArg(1)),
- llvm::AtomicOrdering::SequentiallyConsistent);
- RMWI->setVolatile(true);
- return RValue::get(RMWI);
- }
+ case Builtin::BI_InterlockedIncrement16:
+ case Builtin::BI_InterlockedIncrement:
+ return RValue::get(
+ EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedIncrement, E));
+ case Builtin::BI_InterlockedDecrement16:
+ case Builtin::BI_InterlockedDecrement:
+ return RValue::get(
+ EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedDecrement, E));
+ case Builtin::BI_InterlockedAnd8:
+ case Builtin::BI_InterlockedAnd16:
+ case Builtin::BI_InterlockedAnd:
+ return RValue::get(EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedAnd, E));
+ case Builtin::BI_InterlockedExchangeAdd8:
+ case Builtin::BI_InterlockedExchangeAdd16:
+ case Builtin::BI_InterlockedExchangeAdd:
+ return RValue::get(
+ EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchangeAdd, E));
+ case Builtin::BI_InterlockedExchangeSub8:
+ case Builtin::BI_InterlockedExchangeSub16:
+ case Builtin::BI_InterlockedExchangeSub:
+ return RValue::get(
+ EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchangeSub, E));
+ case Builtin::BI_InterlockedOr8:
+ case Builtin::BI_InterlockedOr16:
+ case Builtin::BI_InterlockedOr:
+ return RValue::get(EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedOr, E));
+ case Builtin::BI_InterlockedXor8:
+ case Builtin::BI_InterlockedXor16:
+ case Builtin::BI_InterlockedXor:
+ return RValue::get(EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedXor, E));
case Builtin::BI__readfsdword: {
llvm::Type *IntTy = ConvertType(E->getType());
Value *IntToPtr =
Builder.CreateIntToPtr(EmitScalarExpr(E->getArg(0)),
llvm::PointerType::get(IntTy, 257));
- LoadInst *Load =
- Builder.CreateDefaultAlignedLoad(IntToPtr, /*isVolatile=*/true);
+ LoadInst *Load = Builder.CreateAlignedLoad(
+ IntTy, IntToPtr, getContext().getTypeAlignInChars(E->getType()));
+ Load->setVolatile(true);
return RValue::get(Load);
}
@@ -2004,7 +2214,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
llvm::Attribute::ReturnsTwice);
llvm::Constant *SetJmpEx = CGM.CreateRuntimeFunction(
llvm::FunctionType::get(IntTy, ArgTypes, /*isVarArg=*/false),
- "_setjmpex", ReturnsTwiceAttr);
+ "_setjmpex", ReturnsTwiceAttr, /*Local=*/true);
llvm::Value *Buf = Builder.CreateBitOrPointerCast(
EmitScalarExpr(E->getArg(0)), Int8PtrTy);
llvm::Value *FrameAddr =
@@ -2029,7 +2239,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
llvm::Type *ArgTypes[] = {Int8PtrTy, IntTy};
llvm::Constant *SetJmp3 = CGM.CreateRuntimeFunction(
llvm::FunctionType::get(IntTy, ArgTypes, /*isVarArg=*/true),
- "_setjmp3", ReturnsTwiceAttr);
+ "_setjmp3", ReturnsTwiceAttr, /*Local=*/true);
llvm::Value *Count = ConstantInt::get(IntTy, 0);
llvm::Value *Args[] = {Buf, Count};
CS = EmitRuntimeCallOrInvoke(SetJmp3, Args);
@@ -2037,7 +2247,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
llvm::Type *ArgTypes[] = {Int8PtrTy, Int8PtrTy};
llvm::Constant *SetJmp = CGM.CreateRuntimeFunction(
llvm::FunctionType::get(IntTy, ArgTypes, /*isVarArg=*/false),
- "_setjmp", ReturnsTwiceAttr);
+ "_setjmp", ReturnsTwiceAttr, /*Local=*/true);
llvm::Value *FrameAddr =
Builder.CreateCall(CGM.getIntrinsic(Intrinsic::frameaddress),
ConstantInt::get(Int32Ty, 0));
@@ -2057,11 +2267,47 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
break;
}
+ case Builtin::BI__builtin_coro_size: {
+ auto & Context = getContext();
+ auto SizeTy = Context.getSizeType();
+ auto T = Builder.getIntNTy(Context.getTypeSize(SizeTy));
+ Value *F = CGM.getIntrinsic(Intrinsic::coro_size, T);
+ return RValue::get(Builder.CreateCall(F));
+ }
+
+ case Builtin::BI__builtin_coro_id:
+ return EmitCoroutineIntrinsic(E, Intrinsic::coro_id);
+ case Builtin::BI__builtin_coro_promise:
+ return EmitCoroutineIntrinsic(E, Intrinsic::coro_promise);
+ case Builtin::BI__builtin_coro_resume:
+ return EmitCoroutineIntrinsic(E, Intrinsic::coro_resume);
+ case Builtin::BI__builtin_coro_frame:
+ return EmitCoroutineIntrinsic(E, Intrinsic::coro_frame);
+ case Builtin::BI__builtin_coro_free:
+ return EmitCoroutineIntrinsic(E, Intrinsic::coro_free);
+ case Builtin::BI__builtin_coro_destroy:
+ return EmitCoroutineIntrinsic(E, Intrinsic::coro_destroy);
+ case Builtin::BI__builtin_coro_done:
+ return EmitCoroutineIntrinsic(E, Intrinsic::coro_done);
+ case Builtin::BI__builtin_coro_alloc:
+ return EmitCoroutineIntrinsic(E, Intrinsic::coro_alloc);
+ case Builtin::BI__builtin_coro_begin:
+ return EmitCoroutineIntrinsic(E, Intrinsic::coro_begin);
+ case Builtin::BI__builtin_coro_end:
+ return EmitCoroutineIntrinsic(E, Intrinsic::coro_end);
+ case Builtin::BI__builtin_coro_suspend:
+ return EmitCoroutineIntrinsic(E, Intrinsic::coro_suspend);
+ case Builtin::BI__builtin_coro_param:
+ return EmitCoroutineIntrinsic(E, Intrinsic::coro_param);
+
// OpenCL v2.0 s6.13.16.2, Built-in pipe read and write functions
case Builtin::BIread_pipe:
case Builtin::BIwrite_pipe: {
Value *Arg0 = EmitScalarExpr(E->getArg(0)),
*Arg1 = EmitScalarExpr(E->getArg(1));
+ CGOpenCLRuntime OpenCLRT(CGM);
+ Value *PacketSize = OpenCLRT.getPipeElemSize(E->getArg(0));
+ Value *PacketAlign = OpenCLRT.getPipeElemAlign(E->getArg(0));
// Type of the generic packet parameter.
unsigned GenericAS =
@@ -2075,19 +2321,21 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
: "__write_pipe_2";
// Creating a generic function type to be able to call with any builtin or
// user defined type.
- llvm::Type *ArgTys[] = {Arg0->getType(), I8PTy};
+ llvm::Type *ArgTys[] = {Arg0->getType(), I8PTy, Int32Ty, Int32Ty};
llvm::FunctionType *FTy = llvm::FunctionType::get(
Int32Ty, llvm::ArrayRef<llvm::Type *>(ArgTys), false);
Value *BCast = Builder.CreatePointerCast(Arg1, I8PTy);
- return RValue::get(Builder.CreateCall(
- CGM.CreateRuntimeFunction(FTy, Name), {Arg0, BCast}));
+ return RValue::get(
+ Builder.CreateCall(CGM.CreateRuntimeFunction(FTy, Name),
+ {Arg0, BCast, PacketSize, PacketAlign}));
} else {
assert(4 == E->getNumArgs() &&
"Illegal number of parameters to pipe function");
const char *Name = (BuiltinID == Builtin::BIread_pipe) ? "__read_pipe_4"
: "__write_pipe_4";
- llvm::Type *ArgTys[] = {Arg0->getType(), Arg1->getType(), Int32Ty, I8PTy};
+ llvm::Type *ArgTys[] = {Arg0->getType(), Arg1->getType(), Int32Ty, I8PTy,
+ Int32Ty, Int32Ty};
Value *Arg2 = EmitScalarExpr(E->getArg(2)),
*Arg3 = EmitScalarExpr(E->getArg(3));
llvm::FunctionType *FTy = llvm::FunctionType::get(
@@ -2098,7 +2346,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
if (Arg2->getType() != Int32Ty)
Arg2 = Builder.CreateZExtOrTrunc(Arg2, Int32Ty);
return RValue::get(Builder.CreateCall(
- CGM.CreateRuntimeFunction(FTy, Name), {Arg0, Arg1, Arg2, BCast}));
+ CGM.CreateRuntimeFunction(FTy, Name),
+ {Arg0, Arg1, Arg2, BCast, PacketSize, PacketAlign}));
}
}
// OpenCL v2.0 s6.13.16 ,s9.17.3.5 - Built-in pipe reserve read and write
@@ -2127,9 +2376,12 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
Value *Arg0 = EmitScalarExpr(E->getArg(0)),
*Arg1 = EmitScalarExpr(E->getArg(1));
llvm::Type *ReservedIDTy = ConvertType(getContext().OCLReserveIDTy);
+ CGOpenCLRuntime OpenCLRT(CGM);
+ Value *PacketSize = OpenCLRT.getPipeElemSize(E->getArg(0));
+ Value *PacketAlign = OpenCLRT.getPipeElemAlign(E->getArg(0));
// Building the generic function prototype.
- llvm::Type *ArgTys[] = {Arg0->getType(), Int32Ty};
+ llvm::Type *ArgTys[] = {Arg0->getType(), Int32Ty, Int32Ty, Int32Ty};
llvm::FunctionType *FTy = llvm::FunctionType::get(
ReservedIDTy, llvm::ArrayRef<llvm::Type *>(ArgTys), false);
// We know the second argument is an integer type, but we may need to cast
@@ -2137,7 +2389,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
if (Arg1->getType() != Int32Ty)
Arg1 = Builder.CreateZExtOrTrunc(Arg1, Int32Ty);
return RValue::get(
- Builder.CreateCall(CGM.CreateRuntimeFunction(FTy, Name), {Arg0, Arg1}));
+ Builder.CreateCall(CGM.CreateRuntimeFunction(FTy, Name),
+ {Arg0, Arg1, PacketSize, PacketAlign}));
}
// OpenCL v2.0 s6.13.16, s9.17.3.5 - Built-in pipe commit read and write
// functions
@@ -2163,15 +2416,19 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
Value *Arg0 = EmitScalarExpr(E->getArg(0)),
*Arg1 = EmitScalarExpr(E->getArg(1));
+ CGOpenCLRuntime OpenCLRT(CGM);
+ Value *PacketSize = OpenCLRT.getPipeElemSize(E->getArg(0));
+ Value *PacketAlign = OpenCLRT.getPipeElemAlign(E->getArg(0));
// Building the generic function prototype.
- llvm::Type *ArgTys[] = {Arg0->getType(), Arg1->getType()};
+ llvm::Type *ArgTys[] = {Arg0->getType(), Arg1->getType(), Int32Ty, Int32Ty};
llvm::FunctionType *FTy =
llvm::FunctionType::get(llvm::Type::getVoidTy(getLLVMContext()),
llvm::ArrayRef<llvm::Type *>(ArgTys), false);
return RValue::get(
- Builder.CreateCall(CGM.CreateRuntimeFunction(FTy, Name), {Arg0, Arg1}));
+ Builder.CreateCall(CGM.CreateRuntimeFunction(FTy, Name),
+ {Arg0, Arg1, PacketSize, PacketAlign}));
}
// OpenCL v2.0 s6.13.16.4 Built-in pipe query functions
case Builtin::BIget_pipe_num_packets:
@@ -2184,12 +2441,15 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
// Building the generic function prototype.
Value *Arg0 = EmitScalarExpr(E->getArg(0));
- llvm::Type *ArgTys[] = {Arg0->getType()};
+ CGOpenCLRuntime OpenCLRT(CGM);
+ Value *PacketSize = OpenCLRT.getPipeElemSize(E->getArg(0));
+ Value *PacketAlign = OpenCLRT.getPipeElemAlign(E->getArg(0));
+ llvm::Type *ArgTys[] = {Arg0->getType(), Int32Ty, Int32Ty};
llvm::FunctionType *FTy = llvm::FunctionType::get(
Int32Ty, llvm::ArrayRef<llvm::Type *>(ArgTys), false);
- return RValue::get(
- Builder.CreateCall(CGM.CreateRuntimeFunction(FTy, Name), {Arg0}));
+ return RValue::get(Builder.CreateCall(CGM.CreateRuntimeFunction(FTy, Name),
+ {Arg0, PacketSize, PacketAlign}));
}
// OpenCL v2.0 s6.13.9 - Address space qualifier functions.
@@ -2258,17 +2518,11 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
std::vector<llvm::Type *> ArgTys = {QueueTy, IntTy, RangeTy, Int8PtrTy,
IntTy};
- // Add the variadics.
- for (unsigned I = 4; I < NumArgs; ++I) {
- llvm::Value *ArgSize = EmitScalarExpr(E->getArg(I));
- unsigned TypeSizeInBytes =
- getContext()
- .getTypeSizeInChars(E->getArg(I)->getType())
- .getQuantity();
- Args.push_back(TypeSizeInBytes < 4
- ? Builder.CreateZExt(ArgSize, Int32Ty)
- : ArgSize);
- }
+ // Each of the following arguments specifies the size of the corresponding
+ // argument passed to the enqueued block.
+ for (unsigned I = 4/*Position of the first size arg*/; I < NumArgs; ++I)
+ Args.push_back(
+ Builder.CreateZExtOrTrunc(EmitScalarExpr(E->getArg(I)), SizeTy));
llvm::FunctionType *FTy = llvm::FunctionType::get(
Int32Ty, llvm::ArrayRef<llvm::Type *>(ArgTys), true);
@@ -2279,29 +2533,26 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
// Any calls now have event arguments passed.
if (NumArgs >= 7) {
llvm::Type *EventTy = ConvertType(getContext().OCLClkEventTy);
- unsigned AS4 =
- E->getArg(4)->getType()->isArrayType()
- ? E->getArg(4)->getType().getAddressSpace()
- : E->getArg(4)->getType()->getPointeeType().getAddressSpace();
- llvm::Type *EventPtrAS4Ty =
- EventTy->getPointerTo(CGM.getContext().getTargetAddressSpace(AS4));
- unsigned AS5 =
- E->getArg(5)->getType()->getPointeeType().getAddressSpace();
- llvm::Type *EventPtrAS5Ty =
- EventTy->getPointerTo(CGM.getContext().getTargetAddressSpace(AS5));
-
- llvm::Value *NumEvents = EmitScalarExpr(E->getArg(3));
+ llvm::Type *EventPtrTy = EventTy->getPointerTo(
+ CGM.getContext().getTargetAddressSpace(LangAS::opencl_generic));
+
+ llvm::Value *NumEvents =
+ Builder.CreateZExtOrTrunc(EmitScalarExpr(E->getArg(3)), Int32Ty);
llvm::Value *EventList =
E->getArg(4)->getType()->isArrayType()
? EmitArrayToPointerDecay(E->getArg(4)).getPointer()
: EmitScalarExpr(E->getArg(4));
llvm::Value *ClkEvent = EmitScalarExpr(E->getArg(5));
+ // Convert to generic address space.
+ EventList = Builder.CreatePointerCast(EventList, EventPtrTy);
+ ClkEvent = Builder.CreatePointerCast(ClkEvent, EventPtrTy);
llvm::Value *Block =
Builder.CreateBitCast(EmitScalarExpr(E->getArg(6)), Int8PtrTy);
- std::vector<llvm::Type *> ArgTys = {
- QueueTy, Int32Ty, RangeTy, Int32Ty,
- EventPtrAS4Ty, EventPtrAS5Ty, Int8PtrTy};
+ std::vector<llvm::Type *> ArgTys = {QueueTy, Int32Ty, RangeTy,
+ Int32Ty, EventPtrTy, EventPtrTy,
+ Int8PtrTy};
+
std::vector<llvm::Value *> Args = {Queue, Flags, Range, NumEvents,
EventList, ClkEvent, Block};
@@ -2320,17 +2571,12 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
ArgTys.push_back(Int32Ty);
Name = "__enqueue_kernel_events_vaargs";
- // Add the variadics.
- for (unsigned I = 7; I < NumArgs; ++I) {
- llvm::Value *ArgSize = EmitScalarExpr(E->getArg(I));
- unsigned TypeSizeInBytes =
- getContext()
- .getTypeSizeInChars(E->getArg(I)->getType())
- .getQuantity();
- Args.push_back(TypeSizeInBytes < 4
- ? Builder.CreateZExt(ArgSize, Int32Ty)
- : ArgSize);
- }
+ // Each of the following arguments specifies the size of the corresponding
+ // argument passed to the enqueued block.
+ for (unsigned I = 7/*Position of the first size arg*/; I < NumArgs; ++I)
+ Args.push_back(
+ Builder.CreateZExtOrTrunc(EmitScalarExpr(E->getArg(I)), SizeTy));
+
llvm::FunctionType *FTy = llvm::FunctionType::get(
Int32Ty, llvm::ArrayRef<llvm::Type *>(ArgTys), true);
return RValue::get(
@@ -2373,6 +2619,76 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
// Fall through - it's already mapped to the intrinsic by GCCBuiltin.
break;
}
+ case Builtin::BI__builtin_os_log_format: {
+ assert(E->getNumArgs() >= 2 &&
+ "__builtin_os_log_format takes at least 2 arguments");
+ analyze_os_log::OSLogBufferLayout Layout;
+ analyze_os_log::computeOSLogBufferLayout(CGM.getContext(), E, Layout);
+ Address BufAddr = EmitPointerWithAlignment(E->getArg(0));
+ // Ignore argument 1, the format string. It is not currently used.
+ CharUnits Offset;
+ Builder.CreateStore(
+ Builder.getInt8(Layout.getSummaryByte()),
+ Builder.CreateConstByteGEP(BufAddr, Offset++, "summary"));
+ Builder.CreateStore(
+ Builder.getInt8(Layout.getNumArgsByte()),
+ Builder.CreateConstByteGEP(BufAddr, Offset++, "numArgs"));
+
+ llvm::SmallVector<llvm::Value *, 4> RetainableOperands;
+ for (const auto &Item : Layout.Items) {
+ Builder.CreateStore(
+ Builder.getInt8(Item.getDescriptorByte()),
+ Builder.CreateConstByteGEP(BufAddr, Offset++, "argDescriptor"));
+ Builder.CreateStore(
+ Builder.getInt8(Item.getSizeByte()),
+ Builder.CreateConstByteGEP(BufAddr, Offset++, "argSize"));
+ Address Addr = Builder.CreateConstByteGEP(BufAddr, Offset);
+ if (const Expr *TheExpr = Item.getExpr()) {
+ Addr = Builder.CreateElementBitCast(
+ Addr, ConvertTypeForMem(TheExpr->getType()));
+ // Check if this is a retainable type.
+ if (TheExpr->getType()->isObjCRetainableType()) {
+ assert(getEvaluationKind(TheExpr->getType()) == TEK_Scalar &&
+ "Only scalar can be a ObjC retainable type");
+ llvm::Value *SV = EmitScalarExpr(TheExpr, /*Ignore*/ false);
+ RValue RV = RValue::get(SV);
+ LValue LV = MakeAddrLValue(Addr, TheExpr->getType());
+ EmitStoreThroughLValue(RV, LV);
+ // Check if the object is constant, if not, save it in
+ // RetainableOperands.
+ if (!isa<Constant>(SV))
+ RetainableOperands.push_back(SV);
+ } else {
+ EmitAnyExprToMem(TheExpr, Addr, Qualifiers(), /*isInit*/ true);
+ }
+ } else {
+ Addr = Builder.CreateElementBitCast(Addr, Int32Ty);
+ Builder.CreateStore(
+ Builder.getInt32(Item.getConstValue().getQuantity()), Addr);
+ }
+ Offset += Item.size();
+ }
+
+ // Push a clang.arc.use cleanup for each object in RetainableOperands. The
+ // cleanup will cause the use to appear after the final log call, keeping
+ // the object valid while it’s held in the log buffer. Note that if there’s
+ // a release cleanup on the object, it will already be active; since
+ // cleanups are emitted in reverse order, the use will occur before the
+ // object is released.
+ if (!RetainableOperands.empty() && getLangOpts().ObjCAutoRefCount &&
+ CGM.getCodeGenOpts().OptimizationLevel != 0)
+ for (llvm::Value *object : RetainableOperands)
+ pushFullExprCleanup<CallObjCArcUse>(getARCCleanupKind(), object);
+
+ return RValue::get(BufAddr.getPointer());
+ }
+
+ case Builtin::BI__builtin_os_log_format_buffer_size: {
+ analyze_os_log::OSLogBufferLayout Layout;
+ analyze_os_log::computeOSLogBufferLayout(CGM.getContext(), E, Layout);
+ return RValue::get(ConstantInt::get(ConvertType(E->getType()),
+ Layout.size().getQuantity()));
+ }
}
// If this is an alias for a lib function (e.g. __builtin_sin), emit
@@ -2385,7 +2701,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
// If this is a predefined lib function (e.g. malloc), emit the call
// using exactly the normal call path.
if (getContext().BuiltinInfo.isPredefinedLibFunction(BuiltinID))
- return emitLibraryCall(*this, FD, E, EmitScalarExpr(E->getCallee()));
+ return emitLibraryCall(*this, FD, E,
+ cast<llvm::Constant>(EmitScalarExpr(E->getCallee())));
// Check that a call to a target specific builtin has the correct target
// features.
@@ -2397,14 +2714,15 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
// See if we have a target specific intrinsic.
const char *Name = getContext().BuiltinInfo.getName(BuiltinID);
Intrinsic::ID IntrinsicID = Intrinsic::not_intrinsic;
- if (const char *Prefix =
- llvm::Triple::getArchTypePrefix(getTarget().getTriple().getArch())) {
- IntrinsicID = Intrinsic::getIntrinsicForGCCBuiltin(Prefix, Name);
+ StringRef Prefix =
+ 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
// 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)
- IntrinsicID = Intrinsic::getIntrinsicForMSBuiltin(Prefix, Name);
+ IntrinsicID = Intrinsic::getIntrinsicForMSBuiltin(Prefix.data(), Name);
}
if (IntrinsicID != Intrinsic::not_intrinsic) {
@@ -3871,7 +4189,7 @@ static Value *EmitSpecialRegisterBuiltin(CodeGenFunction &CGF,
if (SysReg.empty()) {
const Expr *SysRegStrExpr = E->getArg(0)->IgnoreParenCasts();
- SysReg = cast<StringLiteral>(SysRegStrExpr)->getString();
+ SysReg = cast<clang::StringLiteral>(SysRegStrExpr)->getString();
}
llvm::Metadata *Ops[] = { llvm::MDString::get(Context, SysReg) };
@@ -4120,19 +4438,21 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
QualType Ty = E->getType();
llvm::Type *RealResTy = ConvertType(Ty);
- llvm::Type *IntResTy = llvm::IntegerType::get(getLLVMContext(),
- getContext().getTypeSize(Ty));
- LoadAddr = Builder.CreateBitCast(LoadAddr, IntResTy->getPointerTo());
+ llvm::Type *PtrTy = llvm::IntegerType::get(
+ getLLVMContext(), getContext().getTypeSize(Ty))->getPointerTo();
+ LoadAddr = Builder.CreateBitCast(LoadAddr, PtrTy);
Function *F = CGM.getIntrinsic(BuiltinID == ARM::BI__builtin_arm_ldaex
? Intrinsic::arm_ldaex
: Intrinsic::arm_ldrex,
- LoadAddr->getType());
+ PtrTy);
Value *Val = Builder.CreateCall(F, LoadAddr, "ldrex");
if (RealResTy->isPointerTy())
return Builder.CreateIntToPtr(Val, RealResTy);
else {
+ llvm::Type *IntResTy = llvm::IntegerType::get(
+ getLLVMContext(), CGM.getDataLayout().getTypeSizeInBits(RealResTy));
Val = Builder.CreateTruncOrBitCast(Val, IntResTy);
return Builder.CreateBitCast(Val, RealResTy);
}
@@ -4173,7 +4493,10 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
if (StoreVal->getType()->isPointerTy())
StoreVal = Builder.CreatePtrToInt(StoreVal, Int32Ty);
else {
- StoreVal = Builder.CreateBitCast(StoreVal, StoreTy);
+ llvm::Type *IntTy = llvm::IntegerType::get(
+ getLLVMContext(),
+ CGM.getDataLayout().getTypeSizeInBits(StoreVal->getType()));
+ StoreVal = Builder.CreateBitCast(StoreVal, IntTy);
StoreVal = Builder.CreateZExtOrBitCast(StoreVal, Int32Ty);
}
@@ -4184,6 +4507,41 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
return Builder.CreateCall(F, {StoreVal, StoreAddr}, "strex");
}
+ switch (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_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;
+ }
+ }
+
if (BuiltinID == ARM::BI__builtin_arm_clrex) {
Function *F = CGM.getIntrinsic(Intrinsic::arm_clrex);
return Builder.CreateCall(F);
@@ -4397,6 +4755,29 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
return Builder.CreateCall(F, {Ops[1], Ops[2], Ops[0],
Ops[3], Ops[4], Ops[5]});
}
+ case ARM::BI_BitScanForward:
+ case ARM::BI_BitScanForward64:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_BitScanForward, E);
+ case ARM::BI_BitScanReverse:
+ case ARM::BI_BitScanReverse64:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_BitScanReverse, E);
+
+ case ARM::BI_InterlockedAnd64:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedAnd, E);
+ case ARM::BI_InterlockedExchange64:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchange, E);
+ case ARM::BI_InterlockedExchangeAdd64:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchangeAdd, E);
+ case ARM::BI_InterlockedExchangeSub64:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchangeSub, E);
+ case ARM::BI_InterlockedOr64:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedOr, E);
+ case ARM::BI_InterlockedXor64:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedXor, E);
+ case ARM::BI_InterlockedDecrement64:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedDecrement, E);
+ case ARM::BI_InterlockedIncrement64:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedIncrement, E);
}
// Get the last argument, which specifies the vector type.
@@ -4889,19 +5270,21 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
QualType Ty = E->getType();
llvm::Type *RealResTy = ConvertType(Ty);
- llvm::Type *IntResTy = llvm::IntegerType::get(getLLVMContext(),
- getContext().getTypeSize(Ty));
- LoadAddr = Builder.CreateBitCast(LoadAddr, IntResTy->getPointerTo());
+ llvm::Type *PtrTy = llvm::IntegerType::get(
+ getLLVMContext(), getContext().getTypeSize(Ty))->getPointerTo();
+ LoadAddr = Builder.CreateBitCast(LoadAddr, PtrTy);
Function *F = CGM.getIntrinsic(BuiltinID == AArch64::BI__builtin_arm_ldaex
? Intrinsic::aarch64_ldaxr
: Intrinsic::aarch64_ldxr,
- LoadAddr->getType());
+ PtrTy);
Value *Val = Builder.CreateCall(F, LoadAddr, "ldxr");
if (RealResTy->isPointerTy())
return Builder.CreateIntToPtr(Val, RealResTy);
+ llvm::Type *IntResTy = llvm::IntegerType::get(
+ getLLVMContext(), CGM.getDataLayout().getTypeSizeInBits(RealResTy));
Val = Builder.CreateTruncOrBitCast(Val, IntResTy);
return Builder.CreateBitCast(Val, RealResTy);
}
@@ -4940,7 +5323,10 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
if (StoreVal->getType()->isPointerTy())
StoreVal = Builder.CreatePtrToInt(StoreVal, Int64Ty);
else {
- StoreVal = Builder.CreateBitCast(StoreVal, StoreTy);
+ llvm::Type *IntTy = llvm::IntegerType::get(
+ getLLVMContext(),
+ CGM.getDataLayout().getTypeSizeInBits(StoreVal->getType()));
+ StoreVal = Builder.CreateBitCast(StoreVal, IntTy);
StoreVal = Builder.CreateZExtOrBitCast(StoreVal, Int64Ty);
}
@@ -5065,9 +5451,11 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
switch (BuiltinID) {
default: break;
case NEON::BI__builtin_neon_vldrq_p128: {
- llvm::Type *Int128PTy = llvm::Type::getIntNPtrTy(getLLVMContext(), 128);
+ llvm::Type *Int128Ty = llvm::Type::getIntNTy(getLLVMContext(), 128);
+ llvm::Type *Int128PTy = llvm::PointerType::get(Int128Ty, 0);
Value *Ptr = Builder.CreateBitCast(EmitScalarExpr(E->getArg(0)), Int128PTy);
- return Builder.CreateDefaultAlignedLoad(Ptr);
+ return Builder.CreateAlignedLoad(Int128Ty, Ptr,
+ CharUnits::fromQuantity(16));
}
case NEON::BI__builtin_neon_vstrq_p128: {
llvm::Type *Int128PTy = llvm::Type::getIntNPtrTy(getLLVMContext(), 128);
@@ -6240,27 +6628,37 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
return EmitNeonCall(CGM.getIntrinsic(Int, Tys), Ops, "");
}
case NEON::BI__builtin_neon_vld1_v:
- case NEON::BI__builtin_neon_vld1q_v:
+ case NEON::BI__builtin_neon_vld1q_v: {
Ops[0] = Builder.CreateBitCast(Ops[0], llvm::PointerType::getUnqual(VTy));
- return Builder.CreateDefaultAlignedLoad(Ops[0]);
+ auto Alignment = CharUnits::fromQuantity(
+ BuiltinID == NEON::BI__builtin_neon_vld1_v ? 8 : 16);
+ return Builder.CreateAlignedLoad(VTy, Ops[0], Alignment);
+ }
case NEON::BI__builtin_neon_vst1_v:
case NEON::BI__builtin_neon_vst1q_v:
Ops[0] = Builder.CreateBitCast(Ops[0], llvm::PointerType::getUnqual(VTy));
Ops[1] = Builder.CreateBitCast(Ops[1], VTy);
return Builder.CreateDefaultAlignedStore(Ops[1], Ops[0]);
case NEON::BI__builtin_neon_vld1_lane_v:
- case NEON::BI__builtin_neon_vld1q_lane_v:
+ case NEON::BI__builtin_neon_vld1q_lane_v: {
Ops[1] = Builder.CreateBitCast(Ops[1], Ty);
Ty = llvm::PointerType::getUnqual(VTy->getElementType());
Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
- Ops[0] = Builder.CreateDefaultAlignedLoad(Ops[0]);
+ auto Alignment = CharUnits::fromQuantity(
+ BuiltinID == NEON::BI__builtin_neon_vld1_lane_v ? 8 : 16);
+ Ops[0] =
+ Builder.CreateAlignedLoad(VTy->getElementType(), Ops[0], Alignment);
return Builder.CreateInsertElement(Ops[1], Ops[0], Ops[2], "vld1_lane");
+ }
case NEON::BI__builtin_neon_vld1_dup_v:
case NEON::BI__builtin_neon_vld1q_dup_v: {
Value *V = UndefValue::get(Ty);
Ty = llvm::PointerType::getUnqual(VTy->getElementType());
Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
- Ops[0] = Builder.CreateDefaultAlignedLoad(Ops[0]);
+ auto Alignment = CharUnits::fromQuantity(
+ BuiltinID == NEON::BI__builtin_neon_vld1_dup_v ? 8 : 16);
+ Ops[0] =
+ Builder.CreateAlignedLoad(VTy->getElementType(), Ops[0], Alignment);
llvm::Constant *CI = ConstantInt::get(Int32Ty, 0);
Ops[0] = Builder.CreateInsertElement(V, Ops[0], CI);
return EmitNeonSplat(Ops[0], CI);
@@ -6620,6 +7018,26 @@ static Value *EmitX86MaskedLoad(CodeGenFunction &CGF,
return CGF.Builder.CreateMaskedLoad(Ops[0], Align, MaskVec, Ops[1]);
}
+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) {
@@ -6676,6 +7094,18 @@ static Value *EmitX86MaskedCompare(CodeGenFunction &CGF, unsigned CC,
std::max(NumElts, 8U)));
}
+static Value *EmitX86MinMax(CodeGenFunction &CGF, ICmpInst::Predicate Pred,
+ ArrayRef<Value *> Ops) {
+ 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() == 4);
+ return EmitX86Select(CGF, Ops[3], Res, Ops[2]);
+}
+
Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
const CallExpr *E) {
if (BuiltinID == X86::BI__builtin_ms_va_start ||
@@ -6860,6 +7290,25 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
Value *F = CGM.getIntrinsic(Intrinsic::prefetch);
return Builder.CreateCall(F, {Address, RW, Locality, Data});
}
+ case X86::BI_mm_clflush: {
+ return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_sse2_clflush),
+ Ops[0]);
+ }
+ case X86::BI_mm_lfence: {
+ return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_sse2_lfence));
+ }
+ case X86::BI_mm_mfence: {
+ return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_sse2_mfence));
+ }
+ case X86::BI_mm_sfence: {
+ return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_sse_sfence));
+ }
+ case X86::BI_mm_pause: {
+ return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_sse2_pause));
+ }
+ case X86::BI__rdtsc: {
+ return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_rdtsc));
+ }
case X86::BI__builtin_ia32_undef128:
case X86::BI__builtin_ia32_undef256:
case X86::BI__builtin_ia32_undef512:
@@ -6872,12 +7321,14 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
case X86::BI__builtin_ia32_vec_ext_v2si:
return Builder.CreateExtractElement(Ops[0],
llvm::ConstantInt::get(Ops[1]->getType(), 0));
+ case X86::BI_mm_setcsr:
case X86::BI__builtin_ia32_ldmxcsr: {
Address Tmp = CreateMemTemp(E->getArg(0)->getType());
Builder.CreateStore(Ops[0], Tmp);
return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_sse_ldmxcsr),
Builder.CreateBitCast(Tmp.getPointer(), Int8PtrTy));
}
+ case X86::BI_mm_getcsr:
case X86::BI__builtin_ia32_stmxcsr: {
Address Tmp = CreateMemTemp(E->getType());
Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_sse_stmxcsr),
@@ -6944,6 +7395,10 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
case X86::BI__builtin_ia32_storeups512_mask:
return EmitX86MaskedStore(*this, Ops, 1);
+ case X86::BI__builtin_ia32_storess128_mask:
+ case X86::BI__builtin_ia32_storesd128_mask: {
+ return EmitX86MaskedStore(*this, Ops, 16);
+ }
case X86::BI__builtin_ia32_movdqa32store128_mask:
case X86::BI__builtin_ia32_movdqa64store128_mask:
case X86::BI__builtin_ia32_storeaps128_mask:
@@ -6980,6 +7435,10 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
case X86::BI__builtin_ia32_loaddqudi512_mask:
return EmitX86MaskedLoad(*this, Ops, 1);
+ case X86::BI__builtin_ia32_loadss128_mask:
+ case X86::BI__builtin_ia32_loadsd128_mask:
+ return EmitX86MaskedLoad(*this, Ops, 16);
+
case X86::BI__builtin_ia32_loadaps128_mask:
case X86::BI__builtin_ia32_loadaps256_mask:
case X86::BI__builtin_ia32_loadaps512_mask:
@@ -6996,6 +7455,13 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
getContext().getTypeAlignInChars(E->getArg(1)->getType()).getQuantity();
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_storehps:
case X86::BI__builtin_ia32_storelps: {
llvm::Type *PtrTy = llvm::PointerType::getUnqual(Int64Ty);
@@ -7015,8 +7481,6 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
}
case X86::BI__builtin_ia32_palignr128:
case X86::BI__builtin_ia32_palignr256:
- case X86::BI__builtin_ia32_palignr128_mask:
- case X86::BI__builtin_ia32_palignr256_mask:
case X86::BI__builtin_ia32_palignr512_mask: {
unsigned ShiftVal = cast<llvm::ConstantInt>(Ops[2])->getZExtValue();
@@ -7059,36 +7523,26 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
}
case X86::BI__builtin_ia32_movnti:
- case X86::BI__builtin_ia32_movnti64: {
- llvm::MDNode *Node = llvm::MDNode::get(
- getLLVMContext(), llvm::ConstantAsMetadata::get(Builder.getInt32(1)));
-
- // Convert the type of the pointer to a pointer to the stored type.
- Value *BC = Builder.CreateBitCast(Ops[0],
- llvm::PointerType::getUnqual(Ops[1]->getType()),
- "cast");
- StoreInst *SI = Builder.CreateDefaultAlignedStore(Ops[1], BC);
- SI->setMetadata(CGM.getModule().getMDKindID("nontemporal"), Node);
-
- // No alignment for scalar intrinsic store.
- SI->setAlignment(1);
- return SI;
- }
+ case X86::BI__builtin_ia32_movnti64:
case X86::BI__builtin_ia32_movntsd:
case X86::BI__builtin_ia32_movntss: {
llvm::MDNode *Node = llvm::MDNode::get(
getLLVMContext(), llvm::ConstantAsMetadata::get(Builder.getInt32(1)));
+ Value *Ptr = Ops[0];
+ Value *Src = Ops[1];
+
// Extract the 0'th element of the source vector.
- Value *Scl = Builder.CreateExtractElement(Ops[1], (uint64_t)0, "extract");
+ if (BuiltinID == X86::BI__builtin_ia32_movntsd ||
+ BuiltinID == X86::BI__builtin_ia32_movntss)
+ Src = Builder.CreateExtractElement(Src, (uint64_t)0, "extract");
// Convert the type of the pointer to a pointer to the stored type.
- Value *BC = Builder.CreateBitCast(Ops[0],
- llvm::PointerType::getUnqual(Scl->getType()),
- "cast");
+ Value *BC = Builder.CreateBitCast(
+ Ptr, llvm::PointerType::getUnqual(Src->getType()), "cast");
// Unaligned nontemporal store of the scalar value.
- StoreInst *SI = Builder.CreateDefaultAlignedStore(Scl, BC);
+ StoreInst *SI = Builder.CreateDefaultAlignedStore(Src, BC);
SI->setMetadata(CGM.getModule().getMDKindID("nontemporal"), Node);
SI->setAlignment(1);
return SI;
@@ -7182,43 +7636,58 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
Ops[1]);
}
- // TODO: Handle 64/512-bit vector widths of min/max.
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_pmaxsb256:
case X86::BI__builtin_ia32_pmaxsw256:
- case X86::BI__builtin_ia32_pmaxsd256: {
- Value *Cmp = Builder.CreateICmp(ICmpInst::ICMP_SGT, Ops[0], Ops[1]);
- return Builder.CreateSelect(Cmp, Ops[0], Ops[1]);
- }
+ 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:
+ 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_pmaxub256:
case X86::BI__builtin_ia32_pmaxuw256:
- case X86::BI__builtin_ia32_pmaxud256: {
- Value *Cmp = Builder.CreateICmp(ICmpInst::ICMP_UGT, Ops[0], Ops[1]);
- return Builder.CreateSelect(Cmp, Ops[0], Ops[1]);
- }
+ 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:
+ 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_pminsb256:
case X86::BI__builtin_ia32_pminsw256:
- case X86::BI__builtin_ia32_pminsd256: {
- Value *Cmp = Builder.CreateICmp(ICmpInst::ICMP_SLT, Ops[0], Ops[1]);
- return Builder.CreateSelect(Cmp, Ops[0], Ops[1]);
- }
+ 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:
+ 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_pminub256:
case X86::BI__builtin_ia32_pminuw256:
- case X86::BI__builtin_ia32_pminud256: {
- Value *Cmp = Builder.CreateICmp(ICmpInst::ICMP_ULT, Ops[0], Ops[1]);
- return Builder.CreateSelect(Cmp, Ops[0], Ops[1]);
- }
+ 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:
+ return EmitX86MinMax(*this, ICmpInst::ICMP_ULT, Ops);
// 3DNow!
case X86::BI__builtin_ia32_pswapdsf:
@@ -7363,6 +7832,87 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
return getCmpIntrinsicCall(Intrinsic::x86_sse2_cmp_sd, 6);
case X86::BI__builtin_ia32_cmpordsd:
return getCmpIntrinsicCall(Intrinsic::x86_sse2_cmp_sd, 7);
+
+ case X86::BI__emul:
+ case X86::BI__emulu: {
+ llvm::Type *Int64Ty = llvm::IntegerType::get(getLLVMContext(), 64);
+ bool isSigned = (BuiltinID == X86::BI__emul);
+ Value *LHS = Builder.CreateIntCast(Ops[0], Int64Ty, isSigned);
+ Value *RHS = Builder.CreateIntCast(Ops[1], Int64Ty, isSigned);
+ return Builder.CreateMul(LHS, RHS, "", !isSigned, isSigned);
+ }
+ case X86::BI__mulh:
+ case X86::BI__umulh:
+ case X86::BI_mul128:
+ case X86::BI_umul128: {
+ llvm::Type *ResType = ConvertType(E->getType());
+ llvm::Type *Int128Ty = llvm::IntegerType::get(getLLVMContext(), 128);
+
+ bool IsSigned = (BuiltinID == X86::BI__mulh || BuiltinID == X86::BI_mul128);
+ Value *LHS = Builder.CreateIntCast(Ops[0], Int128Ty, IsSigned);
+ Value *RHS = Builder.CreateIntCast(Ops[1], Int128Ty, IsSigned);
+
+ Value *MulResult, *HigherBits;
+ if (IsSigned) {
+ MulResult = Builder.CreateNSWMul(LHS, RHS);
+ HigherBits = Builder.CreateAShr(MulResult, 64);
+ } else {
+ MulResult = Builder.CreateNUWMul(LHS, RHS);
+ HigherBits = Builder.CreateLShr(MulResult, 64);
+ }
+ HigherBits = Builder.CreateIntCast(HigherBits, ResType, IsSigned);
+
+ if (BuiltinID == X86::BI__mulh || BuiltinID == X86::BI__umulh)
+ return HigherBits;
+
+ Address HighBitsAddress = EmitPointerWithAlignment(E->getArg(2));
+ Builder.CreateStore(HigherBits, HighBitsAddress);
+ return Builder.CreateIntCast(MulResult, ResType, IsSigned);
+ }
+
+ case X86::BI__faststorefence: {
+ return Builder.CreateFence(llvm::AtomicOrdering::SequentiallyConsistent,
+ llvm::CrossThread);
+ }
+ case X86::BI_ReadWriteBarrier:
+ case X86::BI_ReadBarrier:
+ case X86::BI_WriteBarrier: {
+ return Builder.CreateFence(llvm::AtomicOrdering::SequentiallyConsistent,
+ llvm::SingleThread);
+ }
+ case X86::BI_BitScanForward:
+ case X86::BI_BitScanForward64:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_BitScanForward, E);
+ case X86::BI_BitScanReverse:
+ case X86::BI_BitScanReverse64:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_BitScanReverse, E);
+
+ case X86::BI_InterlockedAnd64:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedAnd, E);
+ case X86::BI_InterlockedExchange64:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchange, E);
+ case X86::BI_InterlockedExchangeAdd64:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchangeAdd, E);
+ case X86::BI_InterlockedExchangeSub64:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchangeSub, E);
+ case X86::BI_InterlockedOr64:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedOr, E);
+ case X86::BI_InterlockedXor64:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedXor, E);
+ case X86::BI_InterlockedDecrement64:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedDecrement, E);
+ case X86::BI_InterlockedIncrement64:
+ return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedIncrement, E);
+
+ case X86::BI_AddressOfReturnAddress: {
+ Value *F = CGM.getIntrinsic(Intrinsic::addressofreturnaddress);
+ return Builder.CreateCall(F);
+ }
+ case X86::BI__stosb: {
+ // We treat __stosb as a volatile memset - it may not generate "rep stosb"
+ // instruction, but it will create a memset that won't be optimized away.
+ return Builder.CreateMemSet(Ops[0], Ops[1], Ops[2], 1, true);
+ }
}
}
@@ -7384,7 +7934,7 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID,
case PPC::BI__builtin_ppc_get_timebase:
return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::readcyclecounter));
- // vec_ld, vec_lvsl, vec_lvsr
+ // vec_ld, vec_xl_be, vec_lvsl, vec_lvsr
case PPC::BI__builtin_altivec_lvx:
case PPC::BI__builtin_altivec_lvxl:
case PPC::BI__builtin_altivec_lvebx:
@@ -7394,11 +7944,19 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID,
case PPC::BI__builtin_altivec_lvsr:
case PPC::BI__builtin_vsx_lxvd2x:
case PPC::BI__builtin_vsx_lxvw4x:
+ case PPC::BI__builtin_vsx_lxvd2x_be:
+ case PPC::BI__builtin_vsx_lxvw4x_be:
+ case PPC::BI__builtin_vsx_lxvl:
+ case PPC::BI__builtin_vsx_lxvll:
{
- Ops[1] = Builder.CreateBitCast(Ops[1], Int8PtrTy);
-
- Ops[0] = Builder.CreateGEP(Ops[1], Ops[0]);
- Ops.pop_back();
+ if(BuiltinID == PPC::BI__builtin_vsx_lxvl ||
+ BuiltinID == PPC::BI__builtin_vsx_lxvll){
+ Ops[0] = Builder.CreateBitCast(Ops[0], Int8PtrTy);
+ }else {
+ Ops[1] = Builder.CreateBitCast(Ops[1], Int8PtrTy);
+ Ops[0] = Builder.CreateGEP(Ops[1], Ops[0]);
+ Ops.pop_back();
+ }
switch (BuiltinID) {
default: llvm_unreachable("Unsupported ld/lvsl/lvsr intrinsic!");
@@ -7429,12 +7987,24 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID,
case PPC::BI__builtin_vsx_lxvw4x:
ID = Intrinsic::ppc_vsx_lxvw4x;
break;
+ case PPC::BI__builtin_vsx_lxvd2x_be:
+ ID = Intrinsic::ppc_vsx_lxvd2x_be;
+ break;
+ case PPC::BI__builtin_vsx_lxvw4x_be:
+ ID = Intrinsic::ppc_vsx_lxvw4x_be;
+ break;
+ case PPC::BI__builtin_vsx_lxvl:
+ ID = Intrinsic::ppc_vsx_lxvl;
+ break;
+ case PPC::BI__builtin_vsx_lxvll:
+ ID = Intrinsic::ppc_vsx_lxvll;
+ break;
}
llvm::Function *F = CGM.getIntrinsic(ID);
return Builder.CreateCall(F, Ops, "");
}
- // vec_st
+ // vec_st, vec_xst_be
case PPC::BI__builtin_altivec_stvx:
case PPC::BI__builtin_altivec_stvxl:
case PPC::BI__builtin_altivec_stvebx:
@@ -7442,10 +8012,19 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID,
case PPC::BI__builtin_altivec_stvewx:
case PPC::BI__builtin_vsx_stxvd2x:
case PPC::BI__builtin_vsx_stxvw4x:
+ case PPC::BI__builtin_vsx_stxvd2x_be:
+ case PPC::BI__builtin_vsx_stxvw4x_be:
+ case PPC::BI__builtin_vsx_stxvl:
+ case PPC::BI__builtin_vsx_stxvll:
{
- Ops[2] = Builder.CreateBitCast(Ops[2], Int8PtrTy);
- Ops[1] = Builder.CreateGEP(Ops[2], Ops[1]);
- Ops.pop_back();
+ if(BuiltinID == PPC::BI__builtin_vsx_stxvl ||
+ BuiltinID == PPC::BI__builtin_vsx_stxvll ){
+ Ops[1] = Builder.CreateBitCast(Ops[1], Int8PtrTy);
+ }else {
+ Ops[2] = Builder.CreateBitCast(Ops[2], Int8PtrTy);
+ Ops[1] = Builder.CreateGEP(Ops[2], Ops[1]);
+ Ops.pop_back();
+ }
switch (BuiltinID) {
default: llvm_unreachable("Unsupported st intrinsic!");
@@ -7470,6 +8049,18 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID,
case PPC::BI__builtin_vsx_stxvw4x:
ID = Intrinsic::ppc_vsx_stxvw4x;
break;
+ case PPC::BI__builtin_vsx_stxvd2x_be:
+ ID = Intrinsic::ppc_vsx_stxvd2x_be;
+ break;
+ case PPC::BI__builtin_vsx_stxvw4x_be:
+ ID = Intrinsic::ppc_vsx_stxvw4x_be;
+ break;
+ case PPC::BI__builtin_vsx_stxvl:
+ ID = Intrinsic::ppc_vsx_stxvl;
+ break;
+ case PPC::BI__builtin_vsx_stxvll:
+ ID = Intrinsic::ppc_vsx_stxvll;
+ break;
}
llvm::Function *F = CGM.getIntrinsic(ID);
return Builder.CreateCall(F, Ops, "");
@@ -7494,6 +8085,25 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID,
Function *F = CGM.getIntrinsic(Intrinsic::ctlz, ResultType);
return Builder.CreateCall(F, {X, Undef});
}
+ case PPC::BI__builtin_altivec_vctzb:
+ case PPC::BI__builtin_altivec_vctzh:
+ case PPC::BI__builtin_altivec_vctzw:
+ case PPC::BI__builtin_altivec_vctzd: {
+ llvm::Type *ResultType = ConvertType(E->getType());
+ Value *X = EmitScalarExpr(E->getArg(0));
+ Value *Undef = ConstantInt::get(Builder.getInt1Ty(), false);
+ Function *F = CGM.getIntrinsic(Intrinsic::cttz, ResultType);
+ return Builder.CreateCall(F, {X, Undef});
+ }
+ case PPC::BI__builtin_altivec_vpopcntb:
+ case PPC::BI__builtin_altivec_vpopcnth:
+ case PPC::BI__builtin_altivec_vpopcntw:
+ case PPC::BI__builtin_altivec_vpopcntd: {
+ llvm::Type *ResultType = ConvertType(E->getType());
+ Value *X = EmitScalarExpr(E->getArg(0));
+ llvm::Function *F = CGM.getIntrinsic(Intrinsic::ctpop, ResultType);
+ return Builder.CreateCall(F, X);
+ }
// Copy sign
case PPC::BI__builtin_vsx_xvcpsgnsp:
case PPC::BI__builtin_vsx_xvcpsgndp: {
@@ -7625,45 +8235,73 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID,
llvm::Value *Src3ToBool = Builder.CreateIsNotNull(Src3);
return Builder.CreateCall(F, {Src0, Src1, Src2, Src3ToBool});
}
+
+ case AMDGPU::BI__builtin_amdgcn_ds_swizzle:
+ return emitBinaryBuiltin(*this, E, Intrinsic::amdgcn_ds_swizzle);
case AMDGPU::BI__builtin_amdgcn_div_fixup:
case AMDGPU::BI__builtin_amdgcn_div_fixupf:
+ case AMDGPU::BI__builtin_amdgcn_div_fixuph:
return emitTernaryBuiltin(*this, E, Intrinsic::amdgcn_div_fixup);
case AMDGPU::BI__builtin_amdgcn_trig_preop:
case AMDGPU::BI__builtin_amdgcn_trig_preopf:
return emitFPIntBuiltin(*this, E, Intrinsic::amdgcn_trig_preop);
case AMDGPU::BI__builtin_amdgcn_rcp:
case AMDGPU::BI__builtin_amdgcn_rcpf:
+ case AMDGPU::BI__builtin_amdgcn_rcph:
return emitUnaryBuiltin(*this, E, Intrinsic::amdgcn_rcp);
case AMDGPU::BI__builtin_amdgcn_rsq:
case AMDGPU::BI__builtin_amdgcn_rsqf:
+ case AMDGPU::BI__builtin_amdgcn_rsqh:
return emitUnaryBuiltin(*this, E, Intrinsic::amdgcn_rsq);
case AMDGPU::BI__builtin_amdgcn_rsq_clamp:
case AMDGPU::BI__builtin_amdgcn_rsq_clampf:
return emitUnaryBuiltin(*this, E, Intrinsic::amdgcn_rsq_clamp);
case AMDGPU::BI__builtin_amdgcn_sinf:
+ case AMDGPU::BI__builtin_amdgcn_sinh:
return emitUnaryBuiltin(*this, E, Intrinsic::amdgcn_sin);
case AMDGPU::BI__builtin_amdgcn_cosf:
+ case AMDGPU::BI__builtin_amdgcn_cosh:
return emitUnaryBuiltin(*this, E, Intrinsic::amdgcn_cos);
case AMDGPU::BI__builtin_amdgcn_log_clampf:
return emitUnaryBuiltin(*this, E, Intrinsic::amdgcn_log_clamp);
case AMDGPU::BI__builtin_amdgcn_ldexp:
case AMDGPU::BI__builtin_amdgcn_ldexpf:
+ case AMDGPU::BI__builtin_amdgcn_ldexph:
return emitFPIntBuiltin(*this, E, Intrinsic::amdgcn_ldexp);
case AMDGPU::BI__builtin_amdgcn_frexp_mant:
- case AMDGPU::BI__builtin_amdgcn_frexp_mantf: {
+ case AMDGPU::BI__builtin_amdgcn_frexp_mantf:
+ case AMDGPU::BI__builtin_amdgcn_frexp_manth:
return emitUnaryBuiltin(*this, E, Intrinsic::amdgcn_frexp_mant);
- }
case AMDGPU::BI__builtin_amdgcn_frexp_exp:
case AMDGPU::BI__builtin_amdgcn_frexp_expf: {
- return emitUnaryBuiltin(*this, E, Intrinsic::amdgcn_frexp_exp);
+ Value *Src0 = EmitScalarExpr(E->getArg(0));
+ Value *F = CGM.getIntrinsic(Intrinsic::amdgcn_frexp_exp,
+ { Builder.getInt32Ty(), Src0->getType() });
+ return Builder.CreateCall(F, Src0);
+ }
+ case AMDGPU::BI__builtin_amdgcn_frexp_exph: {
+ Value *Src0 = EmitScalarExpr(E->getArg(0));
+ Value *F = CGM.getIntrinsic(Intrinsic::amdgcn_frexp_exp,
+ { Builder.getInt16Ty(), Src0->getType() });
+ return Builder.CreateCall(F, Src0);
}
case AMDGPU::BI__builtin_amdgcn_fract:
case AMDGPU::BI__builtin_amdgcn_fractf:
+ case AMDGPU::BI__builtin_amdgcn_fracth:
return emitUnaryBuiltin(*this, E, Intrinsic::amdgcn_fract);
case AMDGPU::BI__builtin_amdgcn_lerp:
return emitTernaryBuiltin(*this, E, Intrinsic::amdgcn_lerp);
+ case AMDGPU::BI__builtin_amdgcn_uicmp:
+ case AMDGPU::BI__builtin_amdgcn_uicmpl:
+ case AMDGPU::BI__builtin_amdgcn_sicmp:
+ case AMDGPU::BI__builtin_amdgcn_sicmpl:
+ return emitTernaryBuiltin(*this, E, Intrinsic::amdgcn_icmp);
+ case AMDGPU::BI__builtin_amdgcn_fcmp:
+ case AMDGPU::BI__builtin_amdgcn_fcmpf:
+ return emitTernaryBuiltin(*this, E, Intrinsic::amdgcn_fcmp);
case AMDGPU::BI__builtin_amdgcn_class:
case AMDGPU::BI__builtin_amdgcn_classf:
+ case AMDGPU::BI__builtin_amdgcn_classh:
return emitFPIntBuiltin(*this, E, Intrinsic::amdgcn_class);
case AMDGPU::BI__builtin_amdgcn_read_exec: {
@@ -7951,7 +8589,13 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID,
Ptr->getType()}),
{Ptr, ConstantInt::get(Builder.getInt32Ty(), Align.getQuantity())});
};
-
+ auto MakeScopedAtomic = [&](unsigned IntrinsicID) {
+ Value *Ptr = EmitScalarExpr(E->getArg(0));
+ return Builder.CreateCall(
+ CGM.getIntrinsic(IntrinsicID, {Ptr->getType()->getPointerElementType(),
+ Ptr->getType()}),
+ {Ptr, EmitScalarExpr(E->getArg(1))});
+ };
switch (BuiltinID) {
case NVPTX::BI__nvvm_atom_add_gen_i:
case NVPTX::BI__nvvm_atom_add_gen_l:
@@ -8070,6 +8714,109 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID,
case NVPTX::BI__nvvm_ldg_d:
case NVPTX::BI__nvvm_ldg_d2:
return MakeLdg(Intrinsic::nvvm_ldg_global_f);
+
+ case NVPTX::BI__nvvm_atom_cta_add_gen_i:
+ case NVPTX::BI__nvvm_atom_cta_add_gen_l:
+ case NVPTX::BI__nvvm_atom_cta_add_gen_ll:
+ return MakeScopedAtomic(Intrinsic::nvvm_atomic_add_gen_i_cta);
+ case NVPTX::BI__nvvm_atom_sys_add_gen_i:
+ case NVPTX::BI__nvvm_atom_sys_add_gen_l:
+ case NVPTX::BI__nvvm_atom_sys_add_gen_ll:
+ return MakeScopedAtomic(Intrinsic::nvvm_atomic_add_gen_i_sys);
+ case NVPTX::BI__nvvm_atom_cta_add_gen_f:
+ case NVPTX::BI__nvvm_atom_cta_add_gen_d:
+ return MakeScopedAtomic(Intrinsic::nvvm_atomic_add_gen_f_cta);
+ case NVPTX::BI__nvvm_atom_sys_add_gen_f:
+ case NVPTX::BI__nvvm_atom_sys_add_gen_d:
+ return MakeScopedAtomic(Intrinsic::nvvm_atomic_add_gen_f_sys);
+ case NVPTX::BI__nvvm_atom_cta_xchg_gen_i:
+ case NVPTX::BI__nvvm_atom_cta_xchg_gen_l:
+ case NVPTX::BI__nvvm_atom_cta_xchg_gen_ll:
+ return MakeScopedAtomic(Intrinsic::nvvm_atomic_exch_gen_i_cta);
+ case NVPTX::BI__nvvm_atom_sys_xchg_gen_i:
+ case NVPTX::BI__nvvm_atom_sys_xchg_gen_l:
+ case NVPTX::BI__nvvm_atom_sys_xchg_gen_ll:
+ return MakeScopedAtomic(Intrinsic::nvvm_atomic_exch_gen_i_sys);
+ case NVPTX::BI__nvvm_atom_cta_max_gen_i:
+ case NVPTX::BI__nvvm_atom_cta_max_gen_ui:
+ case NVPTX::BI__nvvm_atom_cta_max_gen_l:
+ case NVPTX::BI__nvvm_atom_cta_max_gen_ul:
+ case NVPTX::BI__nvvm_atom_cta_max_gen_ll:
+ case NVPTX::BI__nvvm_atom_cta_max_gen_ull:
+ return MakeScopedAtomic(Intrinsic::nvvm_atomic_max_gen_i_cta);
+ case NVPTX::BI__nvvm_atom_sys_max_gen_i:
+ case NVPTX::BI__nvvm_atom_sys_max_gen_ui:
+ case NVPTX::BI__nvvm_atom_sys_max_gen_l:
+ case NVPTX::BI__nvvm_atom_sys_max_gen_ul:
+ case NVPTX::BI__nvvm_atom_sys_max_gen_ll:
+ case NVPTX::BI__nvvm_atom_sys_max_gen_ull:
+ return MakeScopedAtomic(Intrinsic::nvvm_atomic_max_gen_i_sys);
+ case NVPTX::BI__nvvm_atom_cta_min_gen_i:
+ case NVPTX::BI__nvvm_atom_cta_min_gen_ui:
+ case NVPTX::BI__nvvm_atom_cta_min_gen_l:
+ case NVPTX::BI__nvvm_atom_cta_min_gen_ul:
+ case NVPTX::BI__nvvm_atom_cta_min_gen_ll:
+ case NVPTX::BI__nvvm_atom_cta_min_gen_ull:
+ return MakeScopedAtomic(Intrinsic::nvvm_atomic_min_gen_i_cta);
+ case NVPTX::BI__nvvm_atom_sys_min_gen_i:
+ case NVPTX::BI__nvvm_atom_sys_min_gen_ui:
+ case NVPTX::BI__nvvm_atom_sys_min_gen_l:
+ case NVPTX::BI__nvvm_atom_sys_min_gen_ul:
+ case NVPTX::BI__nvvm_atom_sys_min_gen_ll:
+ case NVPTX::BI__nvvm_atom_sys_min_gen_ull:
+ return MakeScopedAtomic(Intrinsic::nvvm_atomic_min_gen_i_sys);
+ case NVPTX::BI__nvvm_atom_cta_inc_gen_ui:
+ return MakeScopedAtomic(Intrinsic::nvvm_atomic_inc_gen_i_cta);
+ case NVPTX::BI__nvvm_atom_cta_dec_gen_ui:
+ return MakeScopedAtomic(Intrinsic::nvvm_atomic_dec_gen_i_cta);
+ case NVPTX::BI__nvvm_atom_sys_inc_gen_ui:
+ return MakeScopedAtomic(Intrinsic::nvvm_atomic_inc_gen_i_sys);
+ case NVPTX::BI__nvvm_atom_sys_dec_gen_ui:
+ return MakeScopedAtomic(Intrinsic::nvvm_atomic_dec_gen_i_sys);
+ case NVPTX::BI__nvvm_atom_cta_and_gen_i:
+ case NVPTX::BI__nvvm_atom_cta_and_gen_l:
+ case NVPTX::BI__nvvm_atom_cta_and_gen_ll:
+ return MakeScopedAtomic(Intrinsic::nvvm_atomic_and_gen_i_cta);
+ case NVPTX::BI__nvvm_atom_sys_and_gen_i:
+ case NVPTX::BI__nvvm_atom_sys_and_gen_l:
+ case NVPTX::BI__nvvm_atom_sys_and_gen_ll:
+ return MakeScopedAtomic(Intrinsic::nvvm_atomic_and_gen_i_sys);
+ case NVPTX::BI__nvvm_atom_cta_or_gen_i:
+ case NVPTX::BI__nvvm_atom_cta_or_gen_l:
+ case NVPTX::BI__nvvm_atom_cta_or_gen_ll:
+ return MakeScopedAtomic(Intrinsic::nvvm_atomic_or_gen_i_cta);
+ case NVPTX::BI__nvvm_atom_sys_or_gen_i:
+ case NVPTX::BI__nvvm_atom_sys_or_gen_l:
+ case NVPTX::BI__nvvm_atom_sys_or_gen_ll:
+ return MakeScopedAtomic(Intrinsic::nvvm_atomic_or_gen_i_sys);
+ case NVPTX::BI__nvvm_atom_cta_xor_gen_i:
+ case NVPTX::BI__nvvm_atom_cta_xor_gen_l:
+ case NVPTX::BI__nvvm_atom_cta_xor_gen_ll:
+ return MakeScopedAtomic(Intrinsic::nvvm_atomic_xor_gen_i_cta);
+ case NVPTX::BI__nvvm_atom_sys_xor_gen_i:
+ case NVPTX::BI__nvvm_atom_sys_xor_gen_l:
+ case NVPTX::BI__nvvm_atom_sys_xor_gen_ll:
+ return MakeScopedAtomic(Intrinsic::nvvm_atomic_xor_gen_i_sys);
+ case NVPTX::BI__nvvm_atom_cta_cas_gen_i:
+ case NVPTX::BI__nvvm_atom_cta_cas_gen_l:
+ case NVPTX::BI__nvvm_atom_cta_cas_gen_ll: {
+ Value *Ptr = EmitScalarExpr(E->getArg(0));
+ return Builder.CreateCall(
+ CGM.getIntrinsic(
+ Intrinsic::nvvm_atomic_cas_gen_i_cta,
+ {Ptr->getType()->getPointerElementType(), Ptr->getType()}),
+ {Ptr, EmitScalarExpr(E->getArg(1)), EmitScalarExpr(E->getArg(2))});
+ }
+ case NVPTX::BI__nvvm_atom_sys_cas_gen_i:
+ case NVPTX::BI__nvvm_atom_sys_cas_gen_l:
+ case NVPTX::BI__nvvm_atom_sys_cas_gen_ll: {
+ Value *Ptr = EmitScalarExpr(E->getArg(0));
+ return Builder.CreateCall(
+ CGM.getIntrinsic(
+ Intrinsic::nvvm_atomic_cas_gen_i_sys,
+ {Ptr->getType()->getPointerElementType(), Ptr->getType()}),
+ {Ptr, EmitScalarExpr(E->getArg(1)), EmitScalarExpr(E->getArg(2))});
+ }
default:
return nullptr;
}
diff --git a/lib/CodeGen/CGCUDABuiltin.cpp b/lib/CodeGen/CGCUDABuiltin.cpp
index ea3b888635c3..44dd003757ad 100644
--- a/lib/CodeGen/CGCUDABuiltin.cpp
+++ b/lib/CodeGen/CGCUDABuiltin.cpp
@@ -99,6 +99,12 @@ CodeGenFunction::EmitCUDADevicePrintfCallExpr(const CallExpr *E,
llvm::SmallVector<llvm::Type *, 8> ArgTypes;
for (unsigned I = 1, NumArgs = Args.size(); I < NumArgs; ++I)
ArgTypes.push_back(Args[I].RV.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
+ // compute the offsets within the alloca -- we wouldn't be able to assume
+ // that the alignment of the llvm type was the same as the alignment of the
+ // clang type.
llvm::Type *AllocaTy = llvm::StructType::create(ArgTypes, "printf_args");
llvm::Value *Alloca = CreateTempAlloca(AllocaTy);
diff --git a/lib/CodeGen/CGCUDANV.cpp b/lib/CodeGen/CGCUDANV.cpp
index 6a04d4eea784..83febcb4af8c 100644
--- a/lib/CodeGen/CGCUDANV.cpp
+++ b/lib/CodeGen/CGCUDANV.cpp
@@ -15,6 +15,7 @@
#include "CGCUDARuntime.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
+#include "ConstantBuilder.h"
#include "clang/AST/Decl.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/CallSite.h"
@@ -29,7 +30,8 @@ namespace {
class CGNVCUDARuntime : public CGCUDARuntime {
private:
- llvm::Type *IntTy, *SizeTy, *VoidTy;
+ llvm::IntegerType *IntTy, *SizeTy;
+ llvm::Type *VoidTy;
llvm::PointerType *CharPtrTy, *VoidPtrTy, *VoidPtrPtrTy;
/// Convenience reference to LLVM Context
@@ -55,10 +57,18 @@ private:
/// where the C code specifies const char*.
llvm::Constant *makeConstantString(const std::string &Str,
const std::string &Name = "",
+ const std::string &SectionName = "",
unsigned Alignment = 0) {
llvm::Constant *Zeros[] = {llvm::ConstantInt::get(SizeTy, 0),
llvm::ConstantInt::get(SizeTy, 0)};
auto ConstStr = CGM.GetAddrOfConstantCString(Str, Name.c_str());
+ llvm::GlobalVariable *GV =
+ cast<llvm::GlobalVariable>(ConstStr.getPointer());
+ if (!SectionName.empty())
+ GV->setSection(SectionName);
+ if (Alignment)
+ GV->setAlignment(Alignment);
+
return llvm::ConstantExpr::getGetElementPtr(ConstStr.getElementType(),
ConstStr.getPointer(), Zeros);
}
@@ -87,9 +97,9 @@ CGNVCUDARuntime::CGNVCUDARuntime(CodeGenModule &CGM)
CodeGen::CodeGenTypes &Types = CGM.getTypes();
ASTContext &Ctx = CGM.getContext();
- IntTy = Types.ConvertType(Ctx.IntTy);
- SizeTy = Types.ConvertType(Ctx.getSizeType());
- VoidTy = llvm::Type::getVoidTy(Context);
+ IntTy = CGM.IntTy;
+ SizeTy = CGM.SizeTy;
+ VoidTy = CGM.VoidTy;
CharPtrTy = llvm::PointerType::getUnqual(Types.ConvertType(Ctx.CharTy));
VoidPtrTy = cast<llvm::PointerType>(Types.ConvertType(Ctx.VoidPtrTy));
@@ -118,37 +128,28 @@ void CGNVCUDARuntime::emitDeviceStub(CodeGenFunction &CGF,
void CGNVCUDARuntime::emitDeviceStubBody(CodeGenFunction &CGF,
FunctionArgList &Args) {
- // Build the argument value list and the argument stack struct type.
- SmallVector<llvm::Value *, 16> ArgValues;
- std::vector<llvm::Type *> ArgTypes;
- for (FunctionArgList::const_iterator I = Args.begin(), E = Args.end();
- I != E; ++I) {
- llvm::Value *V = CGF.GetAddrOfLocalVar(*I).getPointer();
- ArgValues.push_back(V);
- assert(isa<llvm::PointerType>(V->getType()) && "Arg type not PointerType");
- ArgTypes.push_back(cast<llvm::PointerType>(V->getType())->getElementType());
- }
- llvm::StructType *ArgStackTy = llvm::StructType::get(Context, ArgTypes);
-
- llvm::BasicBlock *EndBlock = CGF.createBasicBlock("setup.end");
-
- // Emit the calls to cudaSetupArgument
+ // Emit a call to cudaSetupArgument for each arg in Args.
llvm::Constant *cudaSetupArgFn = getSetupArgumentFn();
- for (unsigned I = 0, E = Args.size(); I != E; ++I) {
- llvm::Value *Args[3];
- llvm::BasicBlock *NextBlock = CGF.createBasicBlock("setup.next");
- Args[0] = CGF.Builder.CreatePointerCast(ArgValues[I], VoidPtrTy);
- Args[1] = CGF.Builder.CreateIntCast(
- llvm::ConstantExpr::getSizeOf(ArgTypes[I]),
- SizeTy, false);
- Args[2] = CGF.Builder.CreateIntCast(
- llvm::ConstantExpr::getOffsetOf(ArgStackTy, I),
- SizeTy, false);
+ llvm::BasicBlock *EndBlock = CGF.createBasicBlock("setup.end");
+ CharUnits Offset = CharUnits::Zero();
+ for (const VarDecl *A : Args) {
+ CharUnits TyWidth, TyAlign;
+ std::tie(TyWidth, TyAlign) =
+ CGM.getContext().getTypeInfoInChars(A->getType());
+ Offset = Offset.alignTo(TyAlign);
+ llvm::Value *Args[] = {
+ CGF.Builder.CreatePointerCast(CGF.GetAddrOfLocalVar(A).getPointer(),
+ VoidPtrTy),
+ llvm::ConstantInt::get(SizeTy, TyWidth.getQuantity()),
+ llvm::ConstantInt::get(SizeTy, Offset.getQuantity()),
+ };
llvm::CallSite CS = CGF.EmitRuntimeCallOrInvoke(cudaSetupArgFn, Args);
llvm::Constant *Zero = llvm::ConstantInt::get(IntTy, 0);
llvm::Value *CSZero = CGF.Builder.CreateICmpEQ(CS.getInstruction(), Zero);
+ llvm::BasicBlock *NextBlock = CGF.createBasicBlock("setup.next");
CGF.Builder.CreateCondBr(CSZero, NextBlock, EndBlock);
CGF.EmitBlock(NextBlock);
+ Offset += TyWidth;
}
// Emit the call to cudaLaunch
@@ -290,18 +291,29 @@ llvm::Function *CGNVCUDARuntime::makeModuleCtorFunction() {
continue;
}
- // Create initialized wrapper structure that points to the loaded GPU binary
- llvm::Constant *Values[] = {
- llvm::ConstantInt::get(IntTy, 0x466243b1), // Fatbin wrapper magic.
- llvm::ConstantInt::get(IntTy, 1), // Fatbin version.
- makeConstantString(GpuBinaryOrErr.get()->getBuffer(), "", 16), // Data.
- llvm::ConstantPointerNull::get(VoidPtrTy)}; // Unused in fatbin v1.
- llvm::GlobalVariable *FatbinWrapper = new llvm::GlobalVariable(
- TheModule, FatbinWrapperTy, true, llvm::GlobalValue::InternalLinkage,
- llvm::ConstantStruct::get(FatbinWrapperTy, Values),
- "__cuda_fatbin_wrapper");
+ const char *FatbinConstantName =
+ CGM.getTriple().isMacOSX() ? "__NV_CUDA,__nv_fatbin" : ".nv_fatbin";
// NVIDIA's cuobjdump looks for fatbins in this section.
- FatbinWrapper->setSection(".nvFatBinSegment");
+ const char *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);
// GpuBinaryHandle = __cudaRegisterFatBinary(&FatbinWrapper);
llvm::CallInst *RegisterFatbinCall = CtorBuilder.CreateCall(
diff --git a/lib/CodeGen/CGCUDARuntime.cpp b/lib/CodeGen/CGCUDARuntime.cpp
index 014a5dbd46d6..1936f9f13692 100644
--- a/lib/CodeGen/CGCUDARuntime.cpp
+++ b/lib/CodeGen/CGCUDARuntime.cpp
@@ -36,16 +36,7 @@ RValue CGCUDARuntime::EmitCUDAKernelCallExpr(CodeGenFunction &CGF,
eval.begin(CGF);
CGF.EmitBlock(ConfigOKBlock);
-
- const Decl *TargetDecl = nullptr;
- if (const ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(E->getCallee())) {
- if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CE->getSubExpr())) {
- TargetDecl = DRE->getDecl();
- }
- }
-
- llvm::Value *Callee = CGF.EmitScalarExpr(E->getCallee());
- CGF.EmitCall(E->getCallee()->getType(), Callee, E, ReturnValue, TargetDecl);
+ CGF.EmitSimpleCallExpr(E, ReturnValue);
CGF.EmitBranch(ContBlock);
CGF.EmitBlock(ContBlock);
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp
index 40f1bc426ff7..59010f4407c2 100644
--- a/lib/CodeGen/CGCXX.cpp
+++ b/lib/CodeGen/CGCXX.cpp
@@ -134,6 +134,11 @@ bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,
llvm::GlobalValue::LinkageTypes TargetLinkage =
getFunctionLinkage(TargetDecl);
+ // available_externally definitions aren't real definitions, so we cannot
+ // create an alias to one.
+ if (TargetLinkage == llvm::GlobalValue::AvailableExternallyLinkage)
+ return true;
+
// Check if we have it already.
StringRef MangledName = getMangledName(AliasDecl);
llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
@@ -156,14 +161,7 @@ bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,
// Instead of creating as alias to a linkonce_odr, replace all of the uses
// of the aliasee.
- if (llvm::GlobalValue::isDiscardableIfUnused(Linkage) &&
- (TargetLinkage != llvm::GlobalValue::AvailableExternallyLinkage ||
- !TargetDecl.getDecl()->hasAttr<AlwaysInlineAttr>())) {
- // FIXME: An extern template instantiation will create functions with
- // linkage "AvailableExternally". In libc++, some classes also define
- // members with attribute "AlwaysInline" and expect no reference to
- // be generated. It is desirable to reenable this optimisation after
- // corresponding LLVM changes.
+ if (llvm::GlobalValue::isDiscardableIfUnused(Linkage)) {
addReplacement(MangledName, Aliasee);
return false;
}
@@ -220,7 +218,7 @@ llvm::Function *CodeGenModule::codegenCXXStructor(const CXXMethodDecl *MD,
getTypes().arrangeCXXStructorDeclaration(MD, Type);
auto *Fn = cast<llvm::Function>(
getAddrOfCXXStructor(MD, Type, &FnInfo, /*FnType=*/nullptr,
- /*DontDefer=*/true, /*IsForDefinition=*/true));
+ /*DontDefer=*/true, ForDefinition));
GlobalDecl GD;
if (const auto *DD = dyn_cast<CXXDestructorDecl>(MD)) {
@@ -241,7 +239,8 @@ llvm::Function *CodeGenModule::codegenCXXStructor(const CXXMethodDecl *MD,
llvm::Constant *CodeGenModule::getAddrOfCXXStructor(
const CXXMethodDecl *MD, StructorType Type, const CGFunctionInfo *FnInfo,
- llvm::FunctionType *FnType, bool DontDefer, bool IsForDefinition) {
+ llvm::FunctionType *FnType, bool DontDefer,
+ ForDefinition_t IsForDefinition) {
GlobalDecl GD;
if (auto *CD = dyn_cast<CXXConstructorDecl>(MD)) {
GD = GlobalDecl(CD, toCXXCtorType(Type));
@@ -260,10 +259,10 @@ llvm::Constant *CodeGenModule::getAddrOfCXXStructor(
/*isThunk=*/false, /*ExtraAttrs=*/llvm::AttributeSet(), IsForDefinition);
}
-static llvm::Value *BuildAppleKextVirtualCall(CodeGenFunction &CGF,
- GlobalDecl GD,
- llvm::Type *Ty,
- const CXXRecordDecl *RD) {
+static CGCallee BuildAppleKextVirtualCall(CodeGenFunction &CGF,
+ GlobalDecl GD,
+ llvm::Type *Ty,
+ const CXXRecordDecl *RD) {
assert(!CGF.CGM.getTarget().getCXXABI().isMicrosoft() &&
"No kext in Microsoft ABI");
GD = GD.getCanonicalDecl();
@@ -273,22 +272,26 @@ static llvm::Value *BuildAppleKextVirtualCall(CodeGenFunction &CGF,
VTable = CGF.Builder.CreateBitCast(VTable, Ty);
assert(VTable && "BuildVirtualCall = kext vtbl pointer is null");
uint64_t VTableIndex = CGM.getItaniumVTableContext().getMethodVTableIndex(GD);
- uint64_t AddressPoint =
- CGM.getItaniumVTableContext().getVTableLayout(RD)
- .getAddressPoint(BaseSubobject(RD, CharUnits::Zero()));
- VTableIndex += AddressPoint;
+ const VTableLayout &VTLayout = CGM.getItaniumVTableContext().getVTableLayout(RD);
+ VTableLayout::AddressPointLocation AddressPoint =
+ VTLayout.getAddressPoint(BaseSubobject(RD, CharUnits::Zero()));
+ VTableIndex += VTLayout.getVTableOffset(AddressPoint.VTableIndex) +
+ AddressPoint.AddressPointIndex;
llvm::Value *VFuncPtr =
CGF.Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfnkxt");
- return CGF.Builder.CreateAlignedLoad(VFuncPtr, CGF.PointerAlignInBytes);
+ llvm::Value *VFunc =
+ CGF.Builder.CreateAlignedLoad(VFuncPtr, CGF.PointerAlignInBytes);
+ CGCallee Callee(GD.getDecl(), VFunc);
+ return Callee;
}
/// BuildAppleKextVirtualCall - This routine is to support gcc's kext ABI making
/// indirect call to virtual functions. It makes the call through indexing
/// into the vtable.
-llvm::Value *
+CGCallee
CodeGenFunction::BuildAppleKextVirtualCall(const CXXMethodDecl *MD,
- NestedNameSpecifier *Qual,
- llvm::Type *Ty) {
+ NestedNameSpecifier *Qual,
+ llvm::Type *Ty) {
assert((Qual->getKind() == NestedNameSpecifier::TypeSpec) &&
"BuildAppleKextVirtualCall - bad Qual kind");
@@ -306,21 +309,15 @@ CodeGenFunction::BuildAppleKextVirtualCall(const CXXMethodDecl *MD,
/// BuildVirtualCall - This routine makes indirect vtable call for
/// call to virtual destructors. It returns 0 if it could not do it.
-llvm::Value *
+CGCallee
CodeGenFunction::BuildAppleKextVirtualDestructorCall(
const CXXDestructorDecl *DD,
CXXDtorType Type,
const CXXRecordDecl *RD) {
- const auto *MD = cast<CXXMethodDecl>(DD);
- // FIXME. Dtor_Base dtor is always direct!!
- // It need be somehow inline expanded into the caller.
- // -O does that. But need to support -O0 as well.
- if (MD->isVirtual() && Type != Dtor_Base) {
- // Compute the function type we're calling.
- const CGFunctionInfo &FInfo = CGM.getTypes().arrangeCXXStructorDeclaration(
- DD, StructorType::Complete);
- llvm::Type *Ty = CGM.getTypes().GetFunctionType(FInfo);
- return ::BuildAppleKextVirtualCall(*this, GlobalDecl(DD, Type), Ty, RD);
- }
- return nullptr;
+ assert(DD->isVirtual() && Type != Dtor_Base);
+ // Compute the function type we're calling.
+ const CGFunctionInfo &FInfo = CGM.getTypes().arrangeCXXStructorDeclaration(
+ DD, StructorType::Complete);
+ llvm::Type *Ty = CGM.getTypes().GetFunctionType(FInfo);
+ return ::BuildAppleKextVirtualCall(*this, GlobalDecl(DD, Type), Ty, RD);
}
diff --git a/lib/CodeGen/CGCXXABI.cpp b/lib/CodeGen/CGCXXABI.cpp
index e4da447eddc7..df75a7d7ffde 100644
--- a/lib/CodeGen/CGCXXABI.cpp
+++ b/lib/CodeGen/CGCXXABI.cpp
@@ -73,7 +73,7 @@ CGCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) {
return CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType());
}
-llvm::Value *CGCXXABI::EmitLoadOfMemberFunctionPointer(
+CGCallee CGCXXABI::EmitLoadOfMemberFunctionPointer(
CodeGenFunction &CGF, const Expr *E, Address This,
llvm::Value *&ThisPtrForCall,
llvm::Value *MemPtr, const MemberPointerType *MPT) {
@@ -86,7 +86,8 @@ llvm::Value *CGCXXABI::EmitLoadOfMemberFunctionPointer(
cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl());
llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(
CGM.getTypes().arrangeCXXMethodType(RD, FPT, /*FD=*/nullptr));
- return llvm::Constant::getNullValue(FTy->getPointerTo());
+ llvm::Constant *FnPtr = llvm::Constant::getNullValue(FTy->getPointerTo());
+ return CGCallee::forDirect(FnPtr, FPT);
}
llvm::Value *
diff --git a/lib/CodeGen/CGCXXABI.h b/lib/CodeGen/CGCXXABI.h
index 9e10ec068e09..d53fd4cb63b2 100644
--- a/lib/CodeGen/CGCXXABI.h
+++ b/lib/CodeGen/CGCXXABI.h
@@ -35,6 +35,7 @@ class FieldDecl;
class MangleContext;
namespace CodeGen {
+class CGCallee;
class CodeGenFunction;
class CodeGenModule;
struct CatchTypeInfo;
@@ -154,7 +155,7 @@ public:
/// Load a member function from an object and a member function
/// pointer. Apply the this-adjustment and set 'This' to the
/// adjusted value.
- virtual llvm::Value *EmitLoadOfMemberFunctionPointer(
+ virtual CGCallee EmitLoadOfMemberFunctionPointer(
CodeGenFunction &CGF, const Expr *E, Address This,
llvm::Value *&ThisPtrForCall, llvm::Value *MemPtr,
const MemberPointerType *MPT);
@@ -403,11 +404,11 @@ public:
CharUnits VPtrOffset) = 0;
/// Build a virtual function pointer in the ABI-specific way.
- virtual llvm::Value *getVirtualFunctionPointer(CodeGenFunction &CGF,
- GlobalDecl GD,
- Address This,
- llvm::Type *Ty,
- SourceLocation Loc) = 0;
+ virtual CGCallee getVirtualFunctionPointer(CodeGenFunction &CGF,
+ GlobalDecl GD,
+ Address This,
+ llvm::Type *Ty,
+ SourceLocation Loc) = 0;
/// Emit the ABI-specific virtual destructor call.
virtual llvm::Value *
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp
index 242b5962070a..9b96a59aec38 100644
--- a/lib/CodeGen/CGCall.cpp
+++ b/lib/CodeGen/CGCall.cpp
@@ -29,6 +29,7 @@
#include "clang/CodeGen/SwiftCallingConv.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/IR/CallSite.h"
@@ -47,6 +48,7 @@ unsigned CodeGenTypes::ClangCallConvToLLVMCallConv(CallingConv CC) {
default: return llvm::CallingConv::C;
case CC_X86StdCall: return llvm::CallingConv::X86_StdCall;
case CC_X86FastCall: return llvm::CallingConv::X86_FastCall;
+ case CC_X86RegCall: return llvm::CallingConv::X86_RegCall;
case CC_X86ThisCall: return llvm::CallingConv::X86_ThisCall;
case CC_X86_64Win64: return llvm::CallingConv::X86_64_Win64;
case CC_X86_64SysV: return llvm::CallingConv::X86_64_SysV;
@@ -172,6 +174,9 @@ static CallingConv getCallingConventionForDecl(const Decl *D, bool IsWindows) {
if (D->hasAttr<FastCallAttr>())
return CC_X86FastCall;
+ if (D->hasAttr<RegCallAttr>())
+ return CC_X86RegCall;
+
if (D->hasAttr<ThisCallAttr>())
return CC_X86ThisCall;
@@ -1647,6 +1652,8 @@ void CodeGenModule::ConstructAttributeList(
FuncAttrs.addAttribute(llvm::Attribute::NoReturn);
if (TargetDecl->hasAttr<NoDuplicateAttr>())
FuncAttrs.addAttribute(llvm::Attribute::NoDuplicate);
+ if (TargetDecl->hasAttr<ConvergentAttr>())
+ FuncAttrs.addAttribute(llvm::Attribute::Convergent);
if (const FunctionDecl *Fn = dyn_cast<FunctionDecl>(TargetDecl)) {
AddAttributesFromFunctionProtoType(
@@ -1676,6 +1683,14 @@ void CodeGenModule::ConstructAttributeList(
HasAnyX86InterruptAttr = TargetDecl->hasAttr<AnyX86InterruptAttr>();
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,
+ NumElemsParam);
+ }
}
// OptimizeNoneAttr takes precedence over -Os or -Oz. No warning needed.
@@ -1722,6 +1737,16 @@ void CodeGenModule::ConstructAttributeList(
FuncAttrs.addAttribute("less-precise-fpmad",
llvm::toStringRef(CodeGenOpts.LessPreciseFPMAD));
+
+ if (!CodeGenOpts.FPDenormalMode.empty())
+ FuncAttrs.addAttribute("denormal-fp-math",
+ CodeGenOpts.FPDenormalMode);
+
+ FuncAttrs.addAttribute("no-trapping-math",
+ llvm::toStringRef(CodeGenOpts.NoTrappingMath));
+
+ // TODO: Are these all needed?
+ // unsafe/inf/nan/nsz are handled by instruction-level FastMathFlags.
FuncAttrs.addAttribute("no-infs-fp-math",
llvm::toStringRef(CodeGenOpts.NoInfsFPMath));
FuncAttrs.addAttribute("no-nans-fp-math",
@@ -1734,6 +1759,15 @@ void CodeGenModule::ConstructAttributeList(
llvm::utostr(CodeGenOpts.SSPBufferSize));
FuncAttrs.addAttribute("no-signed-zeros-fp-math",
llvm::toStringRef(CodeGenOpts.NoSignedZeros));
+ FuncAttrs.addAttribute(
+ "correctly-rounded-divide-sqrt-fp-math",
+ llvm::toStringRef(CodeGenOpts.CorrectlyRoundedDivSqrt));
+
+ // TODO: Reciprocal estimate codegen options should apply to instructions?
+ std::vector<std::string> &Recips = getTarget().getTargetOpts().Reciprocals;
+ if (!Recips.empty())
+ FuncAttrs.addAttribute("reciprocal-estimates",
+ llvm::join(Recips.begin(), Recips.end(), ","));
if (CodeGenOpts.StackRealignment)
FuncAttrs.addAttribute("stackrealign");
@@ -1794,6 +1828,9 @@ void CodeGenModule::ConstructAttributeList(
// them). LLVM will remove this attribute where it safely can.
FuncAttrs.addAttribute(llvm::Attribute::Convergent);
+ // Exceptions aren't supported in CUDA device code.
+ FuncAttrs.addAttribute(llvm::Attribute::NoUnwind);
+
// Respect -fcuda-flush-denormals-to-zero.
if (getLangOpts().CUDADeviceFlushDenormalsToZero)
FuncAttrs.addAttribute("nvptx-f32ftz", "true");
@@ -2299,13 +2336,6 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
if (isPromoted)
V = emitArgumentDemotion(*this, Arg, V);
- if (const CXXMethodDecl *MD =
- dyn_cast_or_null<CXXMethodDecl>(CurCodeDecl)) {
- if (MD->isVirtual() && Arg == CXXABIThisDecl)
- V = CGM.getCXXABI().
- adjustThisParameterInVirtualFunctionPrologue(*this, CurGD, V);
- }
-
// Because of merging of function types from multiple decls it is
// possible for the type of an argument to not match the corresponding
// type in the function type. Since we are codegening the callee
@@ -2465,7 +2495,7 @@ static llvm::Value *tryEmitFusedAutoreleaseOfResult(CodeGenFunction &CGF,
// result is in a BasicBlock and is therefore an Instruction.
llvm::Instruction *generator = cast<llvm::Instruction>(result);
- SmallVector<llvm::Instruction*,4> insnsToKill;
+ SmallVector<llvm::Instruction *, 4> InstsToKill;
// Look for:
// %generator = bitcast %type1* %generator2 to %type2*
@@ -2478,7 +2508,7 @@ static llvm::Value *tryEmitFusedAutoreleaseOfResult(CodeGenFunction &CGF,
if (generator->getNextNode() != bitcast)
return nullptr;
- insnsToKill.push_back(bitcast);
+ InstsToKill.push_back(bitcast);
}
// Look for:
@@ -2511,27 +2541,26 @@ static llvm::Value *tryEmitFusedAutoreleaseOfResult(CodeGenFunction &CGF,
assert(isa<llvm::CallInst>(prev));
assert(cast<llvm::CallInst>(prev)->getCalledValue() ==
CGF.CGM.getObjCEntrypoints().retainAutoreleasedReturnValueMarker);
- insnsToKill.push_back(prev);
+ InstsToKill.push_back(prev);
}
} else {
return nullptr;
}
result = call->getArgOperand(0);
- insnsToKill.push_back(call);
+ InstsToKill.push_back(call);
// Keep killing bitcasts, for sanity. Note that we no longer care
// about precise ordering as long as there's exactly one use.
while (llvm::BitCastInst *bitcast = dyn_cast<llvm::BitCastInst>(result)) {
if (!bitcast->hasOneUse()) break;
- insnsToKill.push_back(bitcast);
+ InstsToKill.push_back(bitcast);
result = bitcast->getOperand(0);
}
// Delete all the unnecessary instructions, from latest to earliest.
- for (SmallVectorImpl<llvm::Instruction*>::iterator
- i = insnsToKill.begin(), e = insnsToKill.end(); i != e; ++i)
- (*i)->eraseFromParent();
+ for (auto *I : InstsToKill)
+ I->eraseFromParent();
// Do the fused retain/autorelease if we were asked to.
if (doRetainAutorelease)
@@ -2841,7 +2870,7 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI,
EmitCheckSourceLocation(RetNNAttr->getLocation()),
};
EmitCheck(std::make_pair(Cond, SanitizerKind::ReturnsNonnullAttribute),
- "nonnull_return", StaticData, None);
+ SanitizerHandler::NonnullReturn, StaticData, None);
}
}
Ret = Builder.CreateRet(RV);
@@ -2863,13 +2892,13 @@ static AggValueSlot createPlaceholderSlot(CodeGenFunction &CGF,
// FIXME: Generate IR in one pass, rather than going back and fixing up these
// placeholders.
llvm::Type *IRTy = CGF.ConvertTypeForMem(Ty);
- llvm::Value *Placeholder =
- llvm::UndefValue::get(IRTy->getPointerTo()->getPointerTo());
- Placeholder = CGF.Builder.CreateDefaultAlignedLoad(Placeholder);
+ llvm::Type *IRPtrTy = IRTy->getPointerTo();
+ llvm::Value *Placeholder = llvm::UndefValue::get(IRPtrTy->getPointerTo());
// FIXME: When we generate this IR in one pass, we shouldn't need
// this win32-specific alignment hack.
CharUnits Align = CharUnits::fromQuantity(4);
+ Placeholder = CGF.Builder.CreateAlignedLoad(IRPtrTy, Placeholder, Align);
return AggValueSlot::forAddr(Address(Placeholder, Align),
Ty.getQualifiers(),
@@ -2891,22 +2920,36 @@ void CodeGenFunction::EmitDelegateCallArg(CallArgList &args,
assert(!isInAllocaArgument(CGM.getCXXABI(), type) &&
"cannot emit delegate call arguments for inalloca arguments!");
+ // GetAddrOfLocalVar returns a pointer-to-pointer for references,
+ // but the argument needs to be the original pointer.
+ if (type->isReferenceType()) {
+ args.add(RValue::get(Builder.CreateLoad(local)), type);
+
+ // In ARC, move out of consumed arguments so that the release cleanup
+ // entered by StartFunction doesn't cause an over-release. This isn't
+ // optimal -O0 code generation, but it should get cleaned up when
+ // optimization is enabled. This also assumes that delegate calls are
+ // performed exactly once for a set of arguments, but that should be safe.
+ } else if (getLangOpts().ObjCAutoRefCount &&
+ param->hasAttr<NSConsumedAttr>() &&
+ type->isObjCRetainableType()) {
+ llvm::Value *ptr = Builder.CreateLoad(local);
+ auto null =
+ llvm::ConstantPointerNull::get(cast<llvm::PointerType>(ptr->getType()));
+ Builder.CreateStore(null, local);
+ args.add(RValue::get(ptr), type);
+
// For the most part, we just need to load the alloca, except that
// aggregate r-values are actually pointers to temporaries.
- if (type->isReferenceType())
- args.add(RValue::get(Builder.CreateLoad(local)), type);
- else
+ } else {
args.add(convertTempToRValue(local, type, loc), type);
+ }
}
static bool isProvablyNull(llvm::Value *addr) {
return isa<llvm::ConstantPointerNull>(addr);
}
-static bool isProvablyNonNull(llvm::Value *addr) {
- return isa<llvm::AllocaInst>(addr);
-}
-
/// Emit the actual writing-back of a writeback.
static void emitWriteback(CodeGenFunction &CGF,
const CallArgList::Writeback &writeback) {
@@ -2919,7 +2962,7 @@ static void emitWriteback(CodeGenFunction &CGF,
// If the argument wasn't provably non-null, we need to null check
// before doing the store.
- bool provablyNonNull = isProvablyNonNull(srcAddr.getPointer());
+ bool provablyNonNull = llvm::isKnownNonNull(srcAddr.getPointer());
if (!provablyNonNull) {
llvm::BasicBlock *writebackBB = CGF.createBasicBlock("icr.writeback");
contBB = CGF.createBasicBlock("icr.done");
@@ -3059,7 +3102,7 @@ static void emitWritebackArg(CodeGenFunction &CGF, CallArgList &args,
// If the address is *not* known to be non-null, we need to switch.
llvm::Value *finalArgument;
- bool provablyNonNull = isProvablyNonNull(srcAddr.getPointer());
+ bool provablyNonNull = llvm::isKnownNonNull(srcAddr.getPointer());
if (provablyNonNull) {
finalArgument = temp.getPointer();
} else {
@@ -3130,7 +3173,7 @@ static void emitWritebackArg(CodeGenFunction &CGF, CallArgList &args,
}
void CallArgList::allocateArgumentMemory(CodeGenFunction &CGF) {
- assert(!StackBase && !StackCleanup.isValid());
+ assert(!StackBase);
// Save the stack.
llvm::Function *F = CGF.CGM.getIntrinsic(llvm::Intrinsic::stacksave);
@@ -3167,13 +3210,14 @@ void CodeGenFunction::EmitNonNullArgCheck(RValue RV, QualType ArgType,
llvm::ConstantInt::get(Int32Ty, ArgNo + 1),
};
EmitCheck(std::make_pair(Cond, SanitizerKind::NonnullAttribute),
- "nonnull_arg", StaticData, None);
+ SanitizerHandler::NonnullArg, StaticData, None);
}
void CodeGenFunction::EmitCallArgs(
CallArgList &Args, ArrayRef<QualType> ArgTypes,
llvm::iterator_range<CallExpr::const_arg_iterator> ArgRange,
- const FunctionDecl *CalleeDecl, unsigned ParamsToSkip) {
+ const FunctionDecl *CalleeDecl, unsigned ParamsToSkip,
+ EvaluationOrder Order) {
assert((int)ArgTypes.size() == (ArgRange.end() - ArgRange.begin()));
auto MaybeEmitImplicitObjectSize = [&](unsigned I, const Expr *Arg) {
@@ -3191,10 +3235,18 @@ void CodeGenFunction::EmitCallArgs(
};
// We *have* to evaluate arguments from right to left in the MS C++ ABI,
- // because arguments are destroyed left to right in the callee.
- if (CGM.getTarget().getCXXABI().areArgsDestroyedLeftToRightInCallee()) {
- // Insert a stack save if we're going to need any inalloca args.
- bool HasInAllocaArgs = false;
+ // because arguments are destroyed left to right in the callee. As a special
+ // case, there are certain language constructs that require left-to-right
+ // evaluation, and in those cases we consider the evaluation order requirement
+ // to trump the "destruction order is reverse construction order" guarantee.
+ bool LeftToRight =
+ CGM.getTarget().getCXXABI().areArgsDestroyedLeftToRightInCallee()
+ ? Order == EvaluationOrder::ForceLeftToRight
+ : Order != EvaluationOrder::ForceRightToLeft;
+
+ // Insert a stack save if we're going to need any inalloca args.
+ bool HasInAllocaArgs = false;
+ if (CGM.getTarget().getCXXABI().isMicrosoft()) {
for (ArrayRef<QualType>::iterator I = ArgTypes.begin(), E = ArgTypes.end();
I != E && !HasInAllocaArgs; ++I)
HasInAllocaArgs = isInAllocaArgument(CGM.getCXXABI(), *I);
@@ -3202,30 +3254,24 @@ void CodeGenFunction::EmitCallArgs(
assert(getTarget().getTriple().getArch() == llvm::Triple::x86);
Args.allocateArgumentMemory(*this);
}
+ }
- // Evaluate each argument.
- size_t CallArgsStart = Args.size();
- for (int I = ArgTypes.size() - 1; I >= 0; --I) {
- CallExpr::const_arg_iterator Arg = ArgRange.begin() + I;
- MaybeEmitImplicitObjectSize(I, *Arg);
- EmitCallArg(Args, *Arg, ArgTypes[I]);
- EmitNonNullArgCheck(Args.back().RV, ArgTypes[I], (*Arg)->getExprLoc(),
- CalleeDecl, ParamsToSkip + I);
- }
+ // Evaluate each argument in the appropriate order.
+ size_t CallArgsStart = Args.size();
+ for (unsigned I = 0, E = ArgTypes.size(); I != E; ++I) {
+ unsigned Idx = LeftToRight ? I : E - I - 1;
+ CallExpr::const_arg_iterator Arg = ArgRange.begin() + Idx;
+ if (!LeftToRight) MaybeEmitImplicitObjectSize(Idx, *Arg);
+ EmitCallArg(Args, *Arg, ArgTypes[Idx]);
+ EmitNonNullArgCheck(Args.back().RV, ArgTypes[Idx], (*Arg)->getExprLoc(),
+ CalleeDecl, ParamsToSkip + Idx);
+ if (LeftToRight) MaybeEmitImplicitObjectSize(Idx, *Arg);
+ }
+ if (!LeftToRight) {
// Un-reverse the arguments we just evaluated so they match up with the LLVM
// IR function.
std::reverse(Args.begin() + CallArgsStart, Args.end());
- return;
- }
-
- for (unsigned I = 0, E = ArgTypes.size(); I != E; ++I) {
- CallExpr::const_arg_iterator Arg = ArgRange.begin() + I;
- assert(Arg != ArgRange.end());
- EmitCallArg(Args, *Arg, ArgTypes[I]);
- EmitNonNullArgCheck(Args.back().RV, ArgTypes[I], (*Arg)->getExprLoc(),
- CalleeDecl, ParamsToSkip + I);
- MaybeEmitImplicitObjectSize(I, *Arg);
}
}
@@ -3267,7 +3313,7 @@ void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E,
if (const ObjCIndirectCopyRestoreExpr *CRE
= dyn_cast<ObjCIndirectCopyRestoreExpr>(E)) {
assert(getLangOpts().ObjCAutoRefCount);
- assert(getContext().hasSameType(E->getType(), type));
+ assert(getContext().hasSameUnqualifiedType(E->getType(), type));
return emitWritebackArg(*this, args, CRE);
}
@@ -3505,21 +3551,22 @@ void CodeGenFunction::deferPlaceholderReplacement(llvm::Instruction *Old,
}
RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
- llvm::Value *Callee,
+ const CGCallee &Callee,
ReturnValueSlot ReturnValue,
const CallArgList &CallArgs,
- CGCalleeInfo CalleeInfo,
llvm::Instruction **callOrInvoke) {
// FIXME: We no longer need the types from CallArgs; lift up and simplify.
+ assert(Callee.isOrdinary());
+
// Handle struct-return functions by passing a pointer to the
// location that we would like to return into.
QualType RetTy = CallInfo.getReturnType();
const ABIArgInfo &RetAI = CallInfo.getReturnInfo();
- llvm::FunctionType *IRFuncTy =
- cast<llvm::FunctionType>(
- cast<llvm::PointerType>(Callee->getType())->getElementType());
+ llvm::FunctionType *IRFuncTy = Callee.getFunctionType();
+
+ // 1. Set up the arguments.
// If we're using inalloca, insert the allocation after the stack save.
// FIXME: Do this earlier rather than hacking it in here!
@@ -3579,6 +3626,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
Address swiftErrorTemp = Address::invalid();
Address swiftErrorArg = Address::invalid();
+ // Translate all of the arguments as necessary to match the IR lowering.
assert(CallInfo.arg_size() == CallArgs.size() &&
"Mismatch between function signature & arguments.");
unsigned ArgNo = 0;
@@ -3826,6 +3874,9 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
}
}
+ llvm::Value *CalleePtr = Callee.getFunctionPointer();
+
+ // If we're using inalloca, set up that argument.
if (ArgMemory.isValid()) {
llvm::Value *Arg = ArgMemory.getPointer();
if (CallInfo.isVariadic()) {
@@ -3833,10 +3884,9 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// end up with a variadic prototype and an inalloca call site. In such
// cases, we can't do any parameter mismatch checks. Give up and bitcast
// the callee.
- unsigned CalleeAS =
- cast<llvm::PointerType>(Callee->getType())->getAddressSpace();
- Callee = Builder.CreateBitCast(
- Callee, getTypes().GetFunctionType(CallInfo)->getPointerTo(CalleeAS));
+ unsigned CalleeAS = CalleePtr->getType()->getPointerAddressSpace();
+ auto FnTy = getTypes().GetFunctionType(CallInfo)->getPointerTo(CalleeAS);
+ CalleePtr = Builder.CreateBitCast(CalleePtr, FnTy);
} else {
llvm::Type *LastParamTy =
IRFuncTy->getParamType(IRFuncTy->getNumParams() - 1);
@@ -3860,39 +3910,57 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
IRCallArgs[IRFunctionArgs.getInallocaArgNo()] = Arg;
}
- if (!CallArgs.getCleanupsToDeactivate().empty())
- deactivateArgCleanupsBeforeCall(*this, CallArgs);
+ // 2. Prepare the function pointer.
+
+ // If the callee is a bitcast of a non-variadic function to have a
+ // variadic function pointer type, check to see if we can remove the
+ // bitcast. This comes up with unprototyped functions.
+ //
+ // This makes the IR nicer, but more importantly it ensures that we
+ // can inline the function at -O0 if it is marked always_inline.
+ auto simplifyVariadicCallee = [](llvm::Value *Ptr) -> llvm::Value* {
+ llvm::FunctionType *CalleeFT =
+ cast<llvm::FunctionType>(Ptr->getType()->getPointerElementType());
+ if (!CalleeFT->isVarArg())
+ return Ptr;
+
+ llvm::ConstantExpr *CE = dyn_cast<llvm::ConstantExpr>(Ptr);
+ if (!CE || CE->getOpcode() != llvm::Instruction::BitCast)
+ return Ptr;
+
+ llvm::Function *OrigFn = dyn_cast<llvm::Function>(CE->getOperand(0));
+ if (!OrigFn)
+ return Ptr;
+
+ llvm::FunctionType *OrigFT = OrigFn->getFunctionType();
+
+ // If the original type is variadic, or if any of the component types
+ // disagree, we cannot remove the cast.
+ if (OrigFT->isVarArg() ||
+ OrigFT->getNumParams() != CalleeFT->getNumParams() ||
+ OrigFT->getReturnType() != CalleeFT->getReturnType())
+ return Ptr;
+
+ for (unsigned i = 0, e = OrigFT->getNumParams(); i != e; ++i)
+ if (OrigFT->getParamType(i) != CalleeFT->getParamType(i))
+ return Ptr;
+
+ return OrigFn;
+ };
+ CalleePtr = simplifyVariadicCallee(CalleePtr);
- // If the callee is a bitcast of a function to a varargs pointer to function
- // type, check to see if we can remove the bitcast. This handles some cases
- // with unprototyped functions.
- if (llvm::ConstantExpr *CE = dyn_cast<llvm::ConstantExpr>(Callee))
- if (llvm::Function *CalleeF = dyn_cast<llvm::Function>(CE->getOperand(0))) {
- llvm::PointerType *CurPT=cast<llvm::PointerType>(Callee->getType());
- llvm::FunctionType *CurFT =
- cast<llvm::FunctionType>(CurPT->getElementType());
- llvm::FunctionType *ActualFT = CalleeF->getFunctionType();
-
- if (CE->getOpcode() == llvm::Instruction::BitCast &&
- ActualFT->getReturnType() == CurFT->getReturnType() &&
- ActualFT->getNumParams() == CurFT->getNumParams() &&
- ActualFT->getNumParams() == IRCallArgs.size() &&
- (CurFT->isVarArg() || !ActualFT->isVarArg())) {
- bool ArgsMatch = true;
- for (unsigned i = 0, e = ActualFT->getNumParams(); i != e; ++i)
- if (ActualFT->getParamType(i) != CurFT->getParamType(i)) {
- ArgsMatch = false;
- break;
- }
+ // 3. Perform the actual call.
- // Strip the cast if we can get away with it. This is a nice cleanup,
- // but also allows us to inline the function at -O0 if it is marked
- // always_inline.
- if (ArgsMatch)
- Callee = CalleeF;
- }
- }
+ // Deactivate any cleanups that we're supposed to do immediately before
+ // the call.
+ if (!CallArgs.getCleanupsToDeactivate().empty())
+ deactivateArgCleanupsBeforeCall(*this, CallArgs);
+ // Assert that the arguments we computed match up. The IR verifier
+ // will catch this, but this is a common enough source of problems
+ // during IRGen changes that it's way better for debugging to catch
+ // it ourselves here.
+#ifndef NDEBUG
assert(IRCallArgs.size() == IRFuncTy->getNumParams() || IRFuncTy->isVarArg());
for (unsigned i = 0; i < IRCallArgs.size(); ++i) {
// Inalloca argument can have different type.
@@ -3902,75 +3970,106 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
if (i < IRFuncTy->getNumParams())
assert(IRCallArgs[i]->getType() == IRFuncTy->getParamType(i));
}
+#endif
+ // Compute the calling convention and attributes.
unsigned CallingConv;
CodeGen::AttributeListType AttributeList;
- CGM.ConstructAttributeList(Callee->getName(), CallInfo, CalleeInfo,
+ CGM.ConstructAttributeList(CalleePtr->getName(), CallInfo,
+ Callee.getAbstractInfo(),
AttributeList, CallingConv,
/*AttrOnCallSite=*/true);
llvm::AttributeSet Attrs = llvm::AttributeSet::get(getLLVMContext(),
AttributeList);
+ // Apply some call-site-specific attributes.
+ // TODO: work this into building the attribute set.
+
+ // Apply always_inline to all calls within flatten functions.
+ // FIXME: should this really take priority over __try, below?
+ if (CurCodeDecl && CurCodeDecl->hasAttr<FlattenAttr>() &&
+ !(Callee.getAbstractInfo().getCalleeDecl() &&
+ Callee.getAbstractInfo().getCalleeDecl()->hasAttr<NoInlineAttr>())) {
+ Attrs =
+ Attrs.addAttribute(getLLVMContext(),
+ llvm::AttributeSet::FunctionIndex,
+ llvm::Attribute::AlwaysInline);
+ }
+
+ // Disable inlining inside SEH __try blocks.
+ if (isSEHTryScope()) {
+ Attrs =
+ Attrs.addAttribute(getLLVMContext(), llvm::AttributeSet::FunctionIndex,
+ llvm::Attribute::NoInline);
+ }
+
+ // Decide whether to use a call or an invoke.
bool CannotThrow;
if (currentFunctionUsesSEHTry()) {
- // SEH cares about asynchronous exceptions, everything can "throw."
+ // SEH cares about asynchronous exceptions, so everything can "throw."
CannotThrow = false;
} else if (isCleanupPadScope() &&
EHPersonality::get(*this).isMSVCXXPersonality()) {
// The MSVC++ personality will implicitly terminate the program if an
- // exception is thrown. An unwind edge cannot be reached.
+ // exception is thrown during a cleanup outside of a try/catch.
+ // We don't need to model anything in IR to get this behavior.
CannotThrow = true;
} else {
- // Otherwise, nowunind callsites will never throw.
+ // Otherwise, nounwind call sites will never throw.
CannotThrow = Attrs.hasAttribute(llvm::AttributeSet::FunctionIndex,
llvm::Attribute::NoUnwind);
}
llvm::BasicBlock *InvokeDest = CannotThrow ? nullptr : getInvokeDest();
SmallVector<llvm::OperandBundleDef, 1> BundleList;
- getBundlesForFunclet(Callee, CurrentFuncletPad, BundleList);
+ getBundlesForFunclet(CalleePtr, CurrentFuncletPad, BundleList);
+ // Emit the actual call/invoke instruction.
llvm::CallSite CS;
if (!InvokeDest) {
- CS = Builder.CreateCall(Callee, IRCallArgs, BundleList);
+ CS = Builder.CreateCall(CalleePtr, IRCallArgs, BundleList);
} else {
llvm::BasicBlock *Cont = createBasicBlock("invoke.cont");
- CS = Builder.CreateInvoke(Callee, Cont, InvokeDest, IRCallArgs,
+ CS = Builder.CreateInvoke(CalleePtr, Cont, InvokeDest, IRCallArgs,
BundleList);
EmitBlock(Cont);
}
+ llvm::Instruction *CI = CS.getInstruction();
if (callOrInvoke)
- *callOrInvoke = CS.getInstruction();
-
- if (CurCodeDecl && CurCodeDecl->hasAttr<FlattenAttr>() &&
- !CS.hasFnAttr(llvm::Attribute::NoInline))
- Attrs =
- Attrs.addAttribute(getLLVMContext(), llvm::AttributeSet::FunctionIndex,
- llvm::Attribute::AlwaysInline);
-
- // Disable inlining inside SEH __try blocks.
- if (isSEHTryScope())
- Attrs =
- Attrs.addAttribute(getLLVMContext(), llvm::AttributeSet::FunctionIndex,
- llvm::Attribute::NoInline);
+ *callOrInvoke = CI;
+ // Apply the attributes and calling convention.
CS.setAttributes(Attrs);
CS.setCallingConv(static_cast<llvm::CallingConv::ID>(CallingConv));
+ // Apply various metadata.
+
+ if (!CI->getType()->isVoidTy())
+ CI->setName("call");
+
// Insert instrumentation or attach profile metadata at indirect call sites.
// For more details, see the comment before the definition of
// IPVK_IndirectCallTarget in InstrProfData.inc.
if (!CS.getCalledFunction())
PGO.valueProfile(Builder, llvm::IPVK_IndirectCallTarget,
- CS.getInstruction(), Callee);
+ CI, CalleePtr);
// In ObjC ARC mode with no ObjC ARC exception safety, tell the ARC
// optimizer it can aggressively ignore unwind edges.
if (CGM.getLangOpts().ObjCAutoRefCount)
- AddObjCARCExceptionMetadata(CS.getInstruction());
+ AddObjCARCExceptionMetadata(CI);
+
+ // Suppress tail calls if requested.
+ if (llvm::CallInst *Call = dyn_cast<llvm::CallInst>(CI)) {
+ const Decl *TargetDecl = Callee.getAbstractInfo().getCalleeDecl();
+ if (TargetDecl && TargetDecl->hasAttr<NotTailCalledAttr>())
+ Call->setTailCallKind(llvm::CallInst::TCK_NoTail);
+ }
+
+ // 4. Finish the call.
// If the call doesn't return, finish the basic block and clear the
- // insertion point; this allows the rest of IRgen to discard
+ // insertion point; this allows the rest of IRGen to discard
// unreachable code.
if (CS.doesNotReturn()) {
if (UnusedReturnSize)
@@ -3989,18 +4088,14 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
return GetUndefRValue(RetTy);
}
- llvm::Instruction *CI = CS.getInstruction();
- if (!CI->getType()->isVoidTy())
- CI->setName("call");
-
// Perform the swifterror writeback.
if (swiftErrorTemp.isValid()) {
llvm::Value *errorResult = Builder.CreateLoad(swiftErrorTemp);
Builder.CreateStore(errorResult, swiftErrorArg);
}
- // Emit any writebacks immediately. Arguably this should happen
- // after any return-value munging.
+ // Emit any call-associated writebacks immediately. Arguably this
+ // should happen after any return-value munging.
if (CallArgs.hasWritebacks())
emitWritebacks(*this, CallArgs);
@@ -4008,12 +4103,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// lexical order, so deactivate it and run it manually here.
CallArgs.freeArgumentMemory(*this);
- if (llvm::CallInst *Call = dyn_cast<llvm::CallInst>(CI)) {
- const Decl *TargetDecl = CalleeInfo.getCalleeDecl();
- if (TargetDecl && TargetDecl->hasAttr<NotTailCalledAttr>())
- Call->setTailCallKind(llvm::CallInst::TCK_NoTail);
- }
-
+ // Extract the return value.
RValue Ret = [&] {
switch (RetAI.getKind()) {
case ABIArgInfo::CoerceAndExpand: {
@@ -4110,8 +4200,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
llvm_unreachable("Unhandled ABIArgInfo::Kind");
} ();
- const Decl *TargetDecl = CalleeInfo.getCalleeDecl();
-
+ // Emit the assume_aligned check on the return value.
+ const Decl *TargetDecl = Callee.getAbstractInfo().getCalleeDecl();
if (Ret.isScalar() && TargetDecl) {
if (const auto *AA = TargetDecl->getAttr<AssumeAlignedAttr>()) {
llvm::Value *OffsetValue = nullptr;
diff --git a/lib/CodeGen/CGCall.h b/lib/CodeGen/CGCall.h
index 2ebd09b9eb57..031ce831cb37 100644
--- a/lib/CodeGen/CGCall.h
+++ b/lib/CodeGen/CGCall.h
@@ -19,7 +19,6 @@
#include "EHScopeStack.h"
#include "clang/AST/CanonicalType.h"
#include "clang/AST/Type.h"
-#include "llvm/ADT/FoldingSet.h"
#include "llvm/IR/Value.h"
// FIXME: Restructure so we don't have to expose so much stuff.
@@ -42,6 +41,134 @@ namespace clang {
namespace CodeGen {
typedef SmallVector<llvm::AttributeSet, 8> AttributeListType;
+ /// Abstract information about a function or function prototype.
+ class CGCalleeInfo {
+ /// \brief The function prototype of the callee.
+ const FunctionProtoType *CalleeProtoTy;
+ /// \brief The function declaration of the callee.
+ const Decl *CalleeDecl;
+
+ public:
+ explicit CGCalleeInfo() : CalleeProtoTy(nullptr), CalleeDecl(nullptr) {}
+ CGCalleeInfo(const FunctionProtoType *calleeProtoTy, const Decl *calleeDecl)
+ : CalleeProtoTy(calleeProtoTy), CalleeDecl(calleeDecl) {}
+ CGCalleeInfo(const FunctionProtoType *calleeProtoTy)
+ : CalleeProtoTy(calleeProtoTy), CalleeDecl(nullptr) {}
+ CGCalleeInfo(const Decl *calleeDecl)
+ : CalleeProtoTy(nullptr), CalleeDecl(calleeDecl) {}
+
+ const FunctionProtoType *getCalleeFunctionProtoType() const {
+ return CalleeProtoTy;
+ }
+ const Decl *getCalleeDecl() const { return CalleeDecl; }
+ };
+
+ /// All available information about a concrete callee.
+ class CGCallee {
+ enum class SpecialKind : uintptr_t {
+ Invalid,
+ Builtin,
+ PseudoDestructor,
+
+ Last = PseudoDestructor
+ };
+
+ struct BuiltinInfoStorage {
+ const FunctionDecl *Decl;
+ unsigned ID;
+ };
+ struct PseudoDestructorInfoStorage {
+ const CXXPseudoDestructorExpr *Expr;
+ };
+
+ SpecialKind KindOrFunctionPointer;
+ union {
+ CGCalleeInfo AbstractInfo;
+ BuiltinInfoStorage BuiltinInfo;
+ PseudoDestructorInfoStorage PseudoDestructorInfo;
+ };
+
+ explicit CGCallee(SpecialKind kind) : KindOrFunctionPointer(kind) {}
+
+ CGCallee(const FunctionDecl *builtinDecl, unsigned builtinID)
+ : KindOrFunctionPointer(SpecialKind::Builtin) {
+ BuiltinInfo.Decl = builtinDecl;
+ BuiltinInfo.ID = builtinID;
+ }
+
+ public:
+ CGCallee() : KindOrFunctionPointer(SpecialKind::Invalid) {}
+
+ /// Construct a callee. Call this constructor directly when this
+ /// isn't a direct call.
+ CGCallee(const CGCalleeInfo &abstractInfo, llvm::Value *functionPtr)
+ : KindOrFunctionPointer(SpecialKind(uintptr_t(functionPtr))) {
+ AbstractInfo = abstractInfo;
+ assert(functionPtr && "configuring callee without function pointer");
+ assert(functionPtr->getType()->isPointerTy());
+ assert(functionPtr->getType()->getPointerElementType()->isFunctionTy());
+ }
+
+ static CGCallee forBuiltin(unsigned builtinID,
+ const FunctionDecl *builtinDecl) {
+ CGCallee result(SpecialKind::Builtin);
+ result.BuiltinInfo.Decl = builtinDecl;
+ result.BuiltinInfo.ID = builtinID;
+ return result;
+ }
+
+ static CGCallee forPseudoDestructor(const CXXPseudoDestructorExpr *E) {
+ CGCallee result(SpecialKind::PseudoDestructor);
+ result.PseudoDestructorInfo.Expr = E;
+ return result;
+ }
+
+ static CGCallee forDirect(llvm::Constant *functionPtr,
+ const CGCalleeInfo &abstractInfo = CGCalleeInfo()) {
+ return CGCallee(abstractInfo, functionPtr);
+ }
+
+ bool isBuiltin() const {
+ return KindOrFunctionPointer == SpecialKind::Builtin;
+ }
+ const FunctionDecl *getBuiltinDecl() const {
+ assert(isBuiltin());
+ return BuiltinInfo.Decl;
+ }
+ unsigned getBuiltinID() const {
+ assert(isBuiltin());
+ return BuiltinInfo.ID;
+ }
+
+ bool isPseudoDestructor() const {
+ return KindOrFunctionPointer == SpecialKind::PseudoDestructor;
+ }
+ const CXXPseudoDestructorExpr *getPseudoDestructorExpr() const {
+ assert(isPseudoDestructor());
+ return PseudoDestructorInfo.Expr;
+ }
+
+ bool isOrdinary() const {
+ return uintptr_t(KindOrFunctionPointer) > uintptr_t(SpecialKind::Last);
+ }
+ const CGCalleeInfo &getAbstractInfo() const {
+ assert(isOrdinary());
+ return AbstractInfo;
+ }
+ llvm::Value *getFunctionPointer() const {
+ 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));
+ }
+ };
+
struct CallArg {
RValue RV;
QualType Ty;
@@ -82,10 +209,19 @@ namespace CodeGen {
push_back(CallArg(rvalue, type, needscopy));
}
+ /// Add all the arguments from another CallArgList to this one. After doing
+ /// this, the old CallArgList retains its list of arguments, but must not
+ /// be used to emit a call.
void addFrom(const CallArgList &other) {
insert(end(), other.begin(), other.end());
Writebacks.insert(Writebacks.end(),
other.Writebacks.begin(), other.Writebacks.end());
+ CleanupsToDeactivate.insert(CleanupsToDeactivate.end(),
+ other.CleanupsToDeactivate.begin(),
+ other.CleanupsToDeactivate.end());
+ assert(!(StackBase && other.StackBase) && "can't merge stackbases");
+ if (!StackBase)
+ StackBase = other.StackBase;
}
void addWriteback(LValue srcLV, Address temporary,
@@ -133,11 +269,6 @@ namespace CodeGen {
/// The stacksave call. It dominates all of the argument evaluation.
llvm::CallInst *StackBase;
-
- /// The iterator pointing to the stack restore cleanup. We manually run and
- /// deactivate this cleanup after the call in the unexceptional case because
- /// it doesn't run in the normal order.
- EHScopeStack::stable_iterator StackCleanup;
};
/// FunctionArgList - Type for representing both the decl and type
diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp
index 7ed891f426aa..05d056739524 100644
--- a/lib/CodeGen/CGClass.cpp
+++ b/lib/CodeGen/CGClass.cpp
@@ -562,105 +562,6 @@ static void EmitBaseInitializer(CodeGenFunction &CGF,
isBaseVirtual);
}
-static void EmitAggMemberInitializer(CodeGenFunction &CGF,
- LValue LHS,
- Expr *Init,
- Address ArrayIndexVar,
- QualType T,
- ArrayRef<VarDecl *> ArrayIndexes,
- unsigned Index) {
- if (Index == ArrayIndexes.size()) {
- LValue LV = LHS;
-
- if (ArrayIndexVar.isValid()) {
- // If we have an array index variable, load it and use it as an offset.
- // Then, increment the value.
- llvm::Value *Dest = LHS.getPointer();
- llvm::Value *ArrayIndex = CGF.Builder.CreateLoad(ArrayIndexVar);
- Dest = CGF.Builder.CreateInBoundsGEP(Dest, ArrayIndex, "destaddress");
- llvm::Value *Next = llvm::ConstantInt::get(ArrayIndex->getType(), 1);
- Next = CGF.Builder.CreateAdd(ArrayIndex, Next, "inc");
- CGF.Builder.CreateStore(Next, ArrayIndexVar);
-
- // Update the LValue.
- CharUnits EltSize = CGF.getContext().getTypeSizeInChars(T);
- CharUnits Align = LV.getAlignment().alignmentOfArrayElement(EltSize);
- LV.setAddress(Address(Dest, Align));
- }
-
- switch (CGF.getEvaluationKind(T)) {
- case TEK_Scalar:
- CGF.EmitScalarInit(Init, /*decl*/ nullptr, LV, false);
- break;
- case TEK_Complex:
- CGF.EmitComplexExprIntoLValue(Init, LV, /*isInit*/ true);
- break;
- case TEK_Aggregate: {
- AggValueSlot Slot =
- AggValueSlot::forLValue(LV,
- AggValueSlot::IsDestructed,
- AggValueSlot::DoesNotNeedGCBarriers,
- AggValueSlot::IsNotAliased);
-
- CGF.EmitAggExpr(Init, Slot);
- break;
- }
- }
-
- return;
- }
-
- const ConstantArrayType *Array = CGF.getContext().getAsConstantArrayType(T);
- assert(Array && "Array initialization without the array type?");
- Address IndexVar = CGF.GetAddrOfLocalVar(ArrayIndexes[Index]);
-
- // Initialize this index variable to zero.
- llvm::Value* Zero
- = llvm::Constant::getNullValue(IndexVar.getElementType());
- CGF.Builder.CreateStore(Zero, IndexVar);
-
- // Start the loop with a block that tests the condition.
- llvm::BasicBlock *CondBlock = CGF.createBasicBlock("for.cond");
- llvm::BasicBlock *AfterFor = CGF.createBasicBlock("for.end");
-
- CGF.EmitBlock(CondBlock);
-
- llvm::BasicBlock *ForBody = CGF.createBasicBlock("for.body");
- // Generate: if (loop-index < number-of-elements) fall to the loop body,
- // otherwise, go to the block after the for-loop.
- uint64_t NumElements = Array->getSize().getZExtValue();
- llvm::Value *Counter = CGF.Builder.CreateLoad(IndexVar);
- llvm::Value *NumElementsPtr =
- llvm::ConstantInt::get(Counter->getType(), NumElements);
- llvm::Value *IsLess = CGF.Builder.CreateICmpULT(Counter, NumElementsPtr,
- "isless");
-
- // If the condition is true, execute the body.
- CGF.Builder.CreateCondBr(IsLess, ForBody, AfterFor);
-
- CGF.EmitBlock(ForBody);
- llvm::BasicBlock *ContinueBlock = CGF.createBasicBlock("for.inc");
-
- // Inside the loop body recurse to emit the inner loop or, eventually, the
- // constructor call.
- EmitAggMemberInitializer(CGF, LHS, Init, ArrayIndexVar,
- Array->getElementType(), ArrayIndexes, Index + 1);
-
- CGF.EmitBlock(ContinueBlock);
-
- // Emit the increment of the loop counter.
- llvm::Value *NextVal = llvm::ConstantInt::get(Counter->getType(), 1);
- Counter = CGF.Builder.CreateLoad(IndexVar);
- NextVal = CGF.Builder.CreateAdd(Counter, NextVal, "inc");
- CGF.Builder.CreateStore(NextVal, IndexVar);
-
- // Finally, branch back up to the condition for the next iteration.
- CGF.EmitBranch(CondBlock);
-
- // Emit the fall-through block.
- CGF.EmitBlock(AfterFor, true);
-}
-
static bool isMemcpyEquivalentSpecialMember(const CXXMethodDecl *D) {
auto *CD = dyn_cast<CXXConstructorDecl>(D);
if (!(CD && CD->isCopyOrMoveConstructor()) &&
@@ -744,14 +645,11 @@ static void EmitMemberInitializer(CodeGenFunction &CGF,
}
}
- ArrayRef<VarDecl *> ArrayIndexes;
- if (MemberInit->getNumArrayIndices())
- ArrayIndexes = MemberInit->getArrayIndices();
- CGF.EmitInitializerForField(Field, LHS, MemberInit->getInit(), ArrayIndexes);
+ CGF.EmitInitializerForField(Field, LHS, MemberInit->getInit());
}
void CodeGenFunction::EmitInitializerForField(FieldDecl *Field, LValue LHS,
- Expr *Init, ArrayRef<VarDecl *> ArrayIndexes) {
+ Expr *Init) {
QualType FieldType = Field->getType();
switch (getEvaluationKind(FieldType)) {
case TEK_Scalar:
@@ -766,30 +664,13 @@ void CodeGenFunction::EmitInitializerForField(FieldDecl *Field, LValue LHS,
EmitComplexExprIntoLValue(Init, LHS, /*isInit*/ true);
break;
case TEK_Aggregate: {
- Address ArrayIndexVar = Address::invalid();
- if (ArrayIndexes.size()) {
- // The LHS is a pointer to the first object we'll be constructing, as
- // a flat array.
- QualType BaseElementTy = getContext().getBaseElementType(FieldType);
- llvm::Type *BasePtr = ConvertType(BaseElementTy);
- BasePtr = llvm::PointerType::getUnqual(BasePtr);
- Address BaseAddrPtr = Builder.CreateBitCast(LHS.getAddress(), BasePtr);
- LHS = MakeAddrLValue(BaseAddrPtr, BaseElementTy);
-
- // Create an array index that will be used to walk over all of the
- // objects we're constructing.
- ArrayIndexVar = CreateMemTemp(getContext().getSizeType(), "object.index");
- llvm::Value *Zero =
- llvm::Constant::getNullValue(ArrayIndexVar.getElementType());
- Builder.CreateStore(Zero, ArrayIndexVar);
-
- // Emit the block variables for the array indices, if any.
- for (unsigned I = 0, N = ArrayIndexes.size(); I != N; ++I)
- EmitAutoVarDecl(*ArrayIndexes[I]);
- }
-
- EmitAggMemberInitializer(*this, LHS, Init, ArrayIndexVar, FieldType,
- ArrayIndexes, 0);
+ AggValueSlot Slot =
+ AggValueSlot::forLValue(LHS,
+ AggValueSlot::IsDestructed,
+ AggValueSlot::DoesNotNeedGCBarriers,
+ AggValueSlot::IsNotAliased);
+ EmitAggExpr(Init, Slot);
+ break;
}
}
@@ -2146,10 +2027,12 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
*this, D, Type, ForVirtualBase, Delegating, Args);
// Emit the call.
- llvm::Value *Callee = CGM.getAddrOfCXXStructor(D, getFromCtorType(Type));
+ llvm::Constant *CalleePtr =
+ CGM.getAddrOfCXXStructor(D, getFromCtorType(Type));
const CGFunctionInfo &Info =
- CGM.getTypes().arrangeCXXConstructorCall(Args, D, Type, ExtraArgs);
- EmitCall(Info, Callee, ReturnValueSlot(), Args, D);
+ CGM.getTypes().arrangeCXXConstructorCall(Args, D, Type, ExtraArgs);
+ CGCallee Callee = CGCallee::forDirect(CalleePtr, D);
+ EmitCall(Info, Callee, ReturnValueSlot(), Args);
// Generate vtable assumptions if we're constructing a complete object
// with a vtable. We don't do this for base subobjects for two reasons:
@@ -2765,8 +2648,8 @@ void CodeGenFunction::EmitVTablePtrCheck(const CXXRecordDecl *RD,
llvm::MDString::get(CGM.getLLVMContext(), "all-vtables"));
llvm::Value *ValidVtable = Builder.CreateCall(
CGM.getIntrinsic(llvm::Intrinsic::type_test), {CastedVTable, AllVtables});
- EmitCheck(std::make_pair(TypeTest, M), "cfi_check_fail", StaticData,
- {CastedVTable, ValidVtable});
+ EmitCheck(std::make_pair(TypeTest, M), SanitizerHandler::CFICheckFail,
+ StaticData, {CastedVTable, ValidVtable});
}
bool CodeGenFunction::ShouldEmitVTableTypeCheckedLoad(const CXXRecordDecl *RD) {
@@ -2798,38 +2681,13 @@ llvm::Value *CodeGenFunction::EmitVTableTypeCheckedLoad(
llvm::Value *CheckResult = Builder.CreateExtractValue(CheckedLoad, 1);
EmitCheck(std::make_pair(CheckResult, SanitizerKind::CFIVCall),
- "cfi_check_fail", nullptr, nullptr);
+ SanitizerHandler::CFICheckFail, nullptr, nullptr);
return Builder.CreateBitCast(
Builder.CreateExtractValue(CheckedLoad, 0),
cast<llvm::PointerType>(VTable->getType())->getElementType());
}
-// FIXME: Ideally Expr::IgnoreParenNoopCasts should do this, but it doesn't do
-// quite what we want.
-static const Expr *skipNoOpCastsAndParens(const Expr *E) {
- while (true) {
- if (const ParenExpr *PE = dyn_cast<ParenExpr>(E)) {
- E = PE->getSubExpr();
- continue;
- }
-
- if (const CastExpr *CE = dyn_cast<CastExpr>(E)) {
- if (CE->getCastKind() == CK_NoOp) {
- E = CE->getSubExpr();
- continue;
- }
- }
- if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) {
- if (UO->getOpcode() == UO_Extension) {
- E = UO->getSubExpr();
- continue;
- }
- }
- return E;
- }
-}
-
bool
CodeGenFunction::CanDevirtualizeMemberFunctionCall(const Expr *Base,
const CXXMethodDecl *MD) {
@@ -2838,31 +2696,41 @@ CodeGenFunction::CanDevirtualizeMemberFunctionCall(const Expr *Base,
if (getLangOpts().AppleKext)
return false;
- // If the most derived class is marked final, we know that no subclass can
- // override this member function and so we can devirtualize it. For example:
- //
- // struct A { virtual void f(); }
- // struct B final : A { };
- //
- // void f(B *b) {
- // b->f();
- // }
- //
- const CXXRecordDecl *MostDerivedClassDecl = Base->getBestDynamicClassType();
- if (MostDerivedClassDecl->hasAttr<FinalAttr>())
- return true;
-
// If the member function is marked 'final', we know that it can't be
- // overridden and can therefore devirtualize it.
+ // overridden and can therefore devirtualize it unless it's pure virtual.
if (MD->hasAttr<FinalAttr>())
+ return !MD->isPure();
+
+ // If the base expression (after skipping derived-to-base conversions) is a
+ // class prvalue, then we can devirtualize.
+ Base = Base->getBestDynamicClassTypeExpr();
+ if (Base->isRValue() && Base->getType()->isRecordType())
+ return true;
+
+ // If we don't even know what we would call, we can't devirtualize.
+ const CXXRecordDecl *BestDynamicDecl = Base->getBestDynamicClassType();
+ if (!BestDynamicDecl)
+ return false;
+
+ // There may be a method corresponding to MD in a derived class.
+ const CXXMethodDecl *DevirtualizedMethod =
+ MD->getCorrespondingMethodInClass(BestDynamicDecl);
+
+ // If that method is pure virtual, we can't devirtualize. If this code is
+ // reached, the result would be UB, not a direct call to the derived class
+ // function, and we can't assume the derived class function is defined.
+ if (DevirtualizedMethod->isPure())
+ return false;
+
+ // If that method is marked final, we can devirtualize it.
+ if (DevirtualizedMethod->hasAttr<FinalAttr>())
return true;
// Similarly, if the class itself is marked 'final' it can't be overridden
// and we can therefore devirtualize the member function call.
- if (MD->getParent()->hasAttr<FinalAttr>())
+ if (BestDynamicDecl->hasAttr<FinalAttr>())
return true;
- Base = skipNoOpCastsAndParens(Base);
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Base)) {
if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
// This is a record decl. We know the type and can devirtualize it.
@@ -2879,17 +2747,15 @@ CodeGenFunction::CanDevirtualizeMemberFunctionCall(const Expr *Base,
if (const ValueDecl *VD = dyn_cast<ValueDecl>(ME->getMemberDecl()))
return VD->getType()->isRecordType();
- // We can always devirtualize calls on temporary object expressions.
- if (isa<CXXConstructExpr>(Base))
- return true;
-
- // And calls on bound temporaries.
- if (isa<CXXBindTemporaryExpr>(Base))
- return true;
-
- // Check if this is a call expr that returns a record type.
- if (const CallExpr *CE = dyn_cast<CallExpr>(Base))
- return CE->getCallReturnType(getContext())->isRecordType();
+ // Likewise for calls on an object accessed by a (non-reference) pointer to
+ // member access.
+ if (auto *BO = dyn_cast<BinaryOperator>(Base)) {
+ if (BO->isPtrMemOp()) {
+ auto *MPT = BO->getRHS()->getType()->castAs<MemberPointerType>();
+ if (MPT->getPointeeType()->isRecordType())
+ return true;
+ }
+ }
// We can't devirtualize the call.
return false;
@@ -2901,7 +2767,7 @@ void CodeGenFunction::EmitForwardingCallToLambda(
// Get the address of the call operator.
const CGFunctionInfo &calleeFnInfo =
CGM.getTypes().arrangeCXXMethodDeclaration(callOperator);
- llvm::Value *callee =
+ llvm::Constant *calleePtr =
CGM.GetAddrOfFunction(GlobalDecl(callOperator),
CGM.getTypes().GetFunctionType(calleeFnInfo));
@@ -2920,8 +2786,8 @@ void CodeGenFunction::EmitForwardingCallToLambda(
// variadic arguments.
// Now emit our call.
- RValue RV = EmitCall(calleeFnInfo, callee, returnSlot,
- callArgs, callOperator);
+ auto callee = CGCallee::forDirect(calleePtr, callOperator);
+ RValue RV = EmitCall(calleeFnInfo, callee, returnSlot, callArgs);
// If necessary, copy the returned value into the slot.
if (!resultType->isVoidType() && returnSlot.isNull())
diff --git a/lib/CodeGen/CGCleanup.cpp b/lib/CodeGen/CGCleanup.cpp
index b3278b3b4fef..3666858e63d2 100644
--- a/lib/CodeGen/CGCleanup.cpp
+++ b/lib/CodeGen/CGCleanup.cpp
@@ -445,7 +445,7 @@ CodeGenFunction::PopCleanupBlocks(EHScopeStack::stable_iterator Old,
for (size_t I = OldLifetimeExtendedSize,
E = LifetimeExtendedCleanupStack.size(); I != E; /**/) {
// Alignment should be guaranteed by the vptrs in the individual cleanups.
- assert((I % llvm::alignOf<LifetimeExtendedCleanupHeader>() == 0) &&
+ assert((I % alignof(LifetimeExtendedCleanupHeader) == 0) &&
"misaligned cleanup stack entry");
LifetimeExtendedCleanupHeader &Header =
diff --git a/lib/CodeGen/CGCleanup.h b/lib/CodeGen/CGCleanup.h
index 98d01b1326c9..2166490ec1fd 100644
--- a/lib/CodeGen/CGCleanup.h
+++ b/lib/CodeGen/CGCleanup.h
@@ -427,8 +427,7 @@ public:
// EHCleanupScope ought to have alignment equal to that -- not more
// (would be misaligned by the stack allocator), and not less (would
// break the appended classes).
-static_assert(llvm::AlignOf<EHCleanupScope>::Alignment ==
- EHScopeStack::ScopeStackAlignment,
+static_assert(alignof(EHCleanupScope) == EHScopeStack::ScopeStackAlignment,
"EHCleanupScope expected alignment");
/// An exceptions scope which filters exceptions thrown through it.
diff --git a/lib/CodeGen/CGCoroutine.cpp b/lib/CodeGen/CGCoroutine.cpp
new file mode 100644
index 000000000000..2fdb1279ece9
--- /dev/null
+++ b/lib/CodeGen/CGCoroutine.cpp
@@ -0,0 +1,116 @@
+//===----- CGCoroutine.cpp - Emit LLVM Code for C++ coroutines ------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This contains code dealing with C++ code generation of coroutines.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenFunction.h"
+#include "clang/AST/StmtCXX.h"
+
+using namespace clang;
+using namespace CodeGen;
+
+namespace clang {
+namespace CodeGen {
+
+struct CGCoroData {
+ // Stores the llvm.coro.id emitted in the function so that we can supply it
+ // as the first argument to coro.begin, coro.alloc and coro.free intrinsics.
+ // Note: llvm.coro.id returns a token that cannot be directly expressed in a
+ // builtin.
+ llvm::CallInst *CoroId = nullptr;
+ // If coro.id came from the builtin, remember the expression to give better
+ // diagnostic. If CoroIdExpr is nullptr, the coro.id was created by
+ // EmitCoroutineBody.
+ CallExpr const *CoroIdExpr = nullptr;
+};
+}
+}
+
+clang::CodeGen::CodeGenFunction::CGCoroInfo::CGCoroInfo() {}
+CodeGenFunction::CGCoroInfo::~CGCoroInfo() {}
+
+static void createCoroData(CodeGenFunction &CGF,
+ CodeGenFunction::CGCoroInfo &CurCoro,
+ llvm::CallInst *CoroId,
+ CallExpr const *CoroIdExpr = nullptr) {
+ if (CurCoro.Data) {
+ if (CurCoro.Data->CoroIdExpr)
+ CGF.CGM.Error(CoroIdExpr->getLocStart(),
+ "only one __builtin_coro_id can be used in a function");
+ else if (CoroIdExpr)
+ CGF.CGM.Error(CoroIdExpr->getLocStart(),
+ "__builtin_coro_id shall not be used in a C++ coroutine");
+ else
+ llvm_unreachable("EmitCoroutineBodyStatement called twice?");
+
+ return;
+ }
+
+ CurCoro.Data = std::unique_ptr<CGCoroData>(new CGCoroData);
+ CurCoro.Data->CoroId = CoroId;
+ CurCoro.Data->CoroIdExpr = CoroIdExpr;
+}
+
+void CodeGenFunction::EmitCoroutineBody(const CoroutineBodyStmt &S) {
+ auto *NullPtr = llvm::ConstantPointerNull::get(Builder.getInt8PtrTy());
+ auto &TI = CGM.getContext().getTargetInfo();
+ unsigned NewAlign = TI.getNewAlign() / TI.getCharWidth();
+
+ auto *CoroId = Builder.CreateCall(
+ CGM.getIntrinsic(llvm::Intrinsic::coro_id),
+ {Builder.getInt32(NewAlign), NullPtr, NullPtr, NullPtr});
+ createCoroData(*this, CurCoro, CoroId);
+
+ EmitScalarExpr(S.getAllocate());
+ // FIXME: Emit the rest of the coroutine.
+ EmitStmt(S.getDeallocate());
+}
+
+// Emit coroutine intrinsic and patch up arguments of the token type.
+RValue CodeGenFunction::EmitCoroutineIntrinsic(const CallExpr *E,
+ unsigned int IID) {
+ SmallVector<llvm::Value *, 8> Args;
+ switch (IID) {
+ default:
+ break;
+ // The following three intrinsics take a token parameter referring to a token
+ // returned by earlier call to @llvm.coro.id. Since we cannot represent it in
+ // builtins, we patch it up here.
+ case llvm::Intrinsic::coro_alloc:
+ case llvm::Intrinsic::coro_begin:
+ case llvm::Intrinsic::coro_free: {
+ if (CurCoro.Data && CurCoro.Data->CoroId) {
+ Args.push_back(CurCoro.Data->CoroId);
+ break;
+ }
+ CGM.Error(E->getLocStart(), "this builtin expect that __builtin_coro_id has"
+ " been used earlier in this function");
+ // Fallthrough to the next case to add TokenNone as the first argument.
+ }
+ // @llvm.coro.suspend takes a token parameter. Add token 'none' as the first
+ // argument.
+ case llvm::Intrinsic::coro_suspend:
+ Args.push_back(llvm::ConstantTokenNone::get(getLLVMContext()));
+ break;
+ }
+ for (auto &Arg : E->arguments())
+ Args.push_back(EmitScalarExpr(Arg));
+
+ llvm::Value *F = CGM.getIntrinsic(IID);
+ llvm::CallInst *Call = Builder.CreateCall(F, Args);
+
+ // If we see @llvm.coro.id remember it in the CoroData. We will update
+ // coro.alloc, coro.begin and coro.free intrinsics to refer to it.
+ if (IID == llvm::Intrinsic::coro_id) {
+ createCoroData(*this, CurCoro, Call, E);
+ }
+ return RValue::get(Call);
+}
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp
index 0607a5157a6f..12a68036b09c 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/lib/CodeGen/CGDebugInfo.cpp
@@ -13,9 +13,9 @@
#include "CGDebugInfo.h"
#include "CGBlocks.h"
-#include "CGRecordLayout.h"
#include "CGCXXABI.h"
#include "CGObjCRuntime.h"
+#include "CGRecordLayout.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
#include "clang/AST/ASTContext.h"
@@ -31,6 +31,7 @@
#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Lex/ModuleMap.h"
#include "clang/Lex/PreprocessorOptions.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/IR/Constants.h"
@@ -40,10 +41,24 @@
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MD5.h"
#include "llvm/Support/Path.h"
using namespace clang;
using namespace clang::CodeGen;
+static uint32_t getTypeAlignIfRequired(const Type *Ty, const ASTContext &Ctx) {
+ auto TI = Ctx.getTypeInfo(Ty);
+ return TI.AlignIsRequired ? TI.Align : 0;
+}
+
+static uint32_t getTypeAlignIfRequired(QualType Ty, const ASTContext &Ctx) {
+ return getTypeAlignIfRequired(Ty.getTypePtr(), Ctx);
+}
+
+static uint32_t getDeclAlignIfRequired(const Decl *D, const ASTContext &Ctx) {
+ return D->hasAttr<AlignedAttr>() ? D->getMaxAlignment() : 0;
+}
+
CGDebugInfo::CGDebugInfo(CodeGenModule &CGM)
: CGM(CGM), DebugKind(CGM.getCodeGenOpts().getDebugInfo()),
DebugTypeExtRefs(CGM.getCodeGenOpts().DebugTypeExtRefs),
@@ -306,11 +321,36 @@ StringRef CGDebugInfo::getClassName(const RecordDecl *RD) {
return StringRef();
}
+llvm::DIFile::ChecksumKind
+CGDebugInfo::computeChecksum(FileID FID, SmallString<32> &Checksum) const {
+ Checksum.clear();
+
+ if (!CGM.getCodeGenOpts().EmitCodeView)
+ return llvm::DIFile::CSK_None;
+
+ SourceManager &SM = CGM.getContext().getSourceManager();
+ bool Invalid;
+ llvm::MemoryBuffer *MemBuffer = SM.getBuffer(FID, &Invalid);
+ if (Invalid)
+ return llvm::DIFile::CSK_None;
+
+ llvm::MD5 Hash;
+ llvm::MD5::MD5Result Result;
+
+ Hash.update(MemBuffer->getBuffer());
+ Hash.final(Result);
+
+ Hash.stringifyResult(Result, Checksum);
+ return llvm::DIFile::CSK_MD5;
+}
+
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()));
+ remapDIPath(TheCU->getDirectory()),
+ TheCU->getFile()->getChecksumKind(),
+ TheCU->getFile()->getChecksum());
SourceManager &SM = CGM.getContext().getSourceManager();
PresumedLoc PLoc = SM.getPresumedLoc(Loc);
@@ -318,7 +358,9 @@ llvm::DIFile *CGDebugInfo::getOrCreateFile(SourceLocation 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()));
+ remapDIPath(TheCU->getDirectory()),
+ TheCU->getFile()->getChecksumKind(),
+ TheCU->getFile()->getChecksum());
// Cache the results.
const char *fname = PLoc.getFilename();
@@ -330,8 +372,13 @@ llvm::DIFile *CGDebugInfo::getOrCreateFile(SourceLocation Loc) {
return cast<llvm::DIFile>(V);
}
+ SmallString<32> Checksum;
+ llvm::DIFile::ChecksumKind CSKind =
+ computeChecksum(SM.getFileID(Loc), Checksum);
+
llvm::DIFile *F = DBuilder.createFile(remapDIPath(PLoc.getFilename()),
- remapDIPath(getCurrentDirname()));
+ remapDIPath(getCurrentDirname()),
+ CSKind, Checksum);
DIFileCache[fname].reset(F);
return F;
@@ -339,7 +386,9 @@ llvm::DIFile *CGDebugInfo::getOrCreateFile(SourceLocation Loc) {
llvm::DIFile *CGDebugInfo::getOrCreateMainFile() {
return DBuilder.createFile(remapDIPath(TheCU->getFilename()),
- remapDIPath(TheCU->getDirectory()));
+ remapDIPath(TheCU->getDirectory()),
+ TheCU->getFile()->getChecksumKind(),
+ TheCU->getFile()->getChecksum());
}
std::string CGDebugInfo::remapDIPath(StringRef Path) const {
@@ -382,6 +431,8 @@ StringRef CGDebugInfo::getCurrentDirname() {
}
void CGDebugInfo::CreateCompileUnit() {
+ SmallString<32> Checksum;
+ llvm::DIFile::ChecksumKind CSKind = llvm::DIFile::CSK_None;
// 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
@@ -408,6 +459,7 @@ void CGDebugInfo::CreateCompileUnit() {
llvm::sys::path::append(MainFileDirSS, MainFileName);
MainFileName = MainFileDirSS.str();
}
+ CSKind = computeChecksum(SM.getMainFileID(), Checksum);
}
llvm::dwarf::SourceLanguage LangTag;
@@ -452,9 +504,12 @@ void CGDebugInfo::CreateCompileUnit() {
// Create new compile unit.
// FIXME - Eliminate TheCU.
TheCU = DBuilder.createCompileUnit(
- LangTag, remapDIPath(MainFileName), remapDIPath(getCurrentDirname()),
+ LangTag, DBuilder.createFile(remapDIPath(MainFileName),
+ remapDIPath(getCurrentDirname()), CSKind,
+ Checksum),
Producer, LO.Optimize, CGM.getCodeGenOpts().DwarfDebugFlags, RuntimeVers,
- CGM.getCodeGenOpts().SplitDwarfFile, EmissionKind, 0 /* DWOid */);
+ CGM.getCodeGenOpts().SplitDwarfFile, EmissionKind, 0 /* DWOid */,
+ CGM.getCodeGenOpts().SplitDwarfInlining);
}
llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) {
@@ -494,14 +549,14 @@ llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) {
auto *ISATy = DBuilder.createPointerType(ClassTy, Size);
- ObjTy =
- DBuilder.createStructType(TheCU, "objc_object", getOrCreateMainFile(),
- 0, 0, 0, 0, nullptr, llvm::DINodeArray());
+ ObjTy = DBuilder.createStructType(
+ TheCU, "objc_object", getOrCreateMainFile(), 0, 0, 0,
+ llvm::DINode::FlagZero, nullptr, llvm::DINodeArray());
DBuilder.replaceArrays(
- ObjTy,
- DBuilder.getOrCreateArray(&*DBuilder.createMemberType(
- ObjTy, "isa", getOrCreateMainFile(), 0, Size, 0, 0, 0, ISATy)));
+ ObjTy, DBuilder.getOrCreateArray(&*DBuilder.createMemberType(
+ ObjTy, "isa", getOrCreateMainFile(), 0, Size, 0, 0,
+ llvm::DINode::FlagZero, ISATy)));
return ObjTy;
}
case BuiltinType::ObjCSel: {
@@ -518,9 +573,8 @@ llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) {
SingletonId);
#include "clang/Basic/OpenCLImageTypes.def"
case BuiltinType::OCLSampler:
- return DBuilder.createBasicType(
- "opencl_sampler_t", CGM.getContext().getTypeSize(BT),
- CGM.getContext().getTypeAlign(BT), llvm::dwarf::DW_ATE_unsigned);
+ return getOrCreateStructPtrType("opencl_sampler_t",
+ OCLSamplerDITy);
case BuiltinType::OCLEvent:
return getOrCreateStructPtrType("opencl_event_t", OCLEventDITy);
case BuiltinType::OCLClkEvent:
@@ -594,21 +648,19 @@ llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) {
BTName = BT->getName(CGM.getLangOpts());
break;
}
- // Bit size, align and offset of the type.
+ // Bit size and offset of the type.
uint64_t Size = CGM.getContext().getTypeSize(BT);
- uint64_t Align = CGM.getContext().getTypeAlign(BT);
- return DBuilder.createBasicType(BTName, Size, Align, Encoding);
+ return DBuilder.createBasicType(BTName, Size, Encoding);
}
llvm::DIType *CGDebugInfo::CreateType(const ComplexType *Ty) {
- // Bit size, align and offset of the type.
+ // Bit size and offset of the type.
llvm::dwarf::TypeKind Encoding = llvm::dwarf::DW_ATE_complex_float;
if (Ty->isComplexIntegerType())
Encoding = llvm::dwarf::DW_ATE_lo_user;
uint64_t Size = CGM.getContext().getTypeSize(Ty);
- uint64_t Align = CGM.getContext().getTypeAlign(Ty);
- return DBuilder.createBasicType("complex", Size, Align, Encoding);
+ return DBuilder.createBasicType("complex", Size, Encoding);
}
llvm::DIType *CGDebugInfo::CreateQualifiedType(QualType Ty,
@@ -721,13 +773,7 @@ CGDebugInfo::getOrCreateRecordFwdDecl(const RecordType *Ty,
StringRef RDName = getClassName(RD);
uint64_t Size = 0;
- uint64_t Align = 0;
-
- const RecordDecl *D = RD->getDefinition();
- if (D && D->isCompleteDefinition()) {
- Size = CGM.getContext().getTypeSize(Ty);
- Align = CGM.getContext().getTypeAlign(Ty);
- }
+ uint32_t Align = 0;
// Create the type.
SmallString<256> FullName = getUniqueTagTypeName(Ty, CGM, TheCU);
@@ -749,7 +795,7 @@ llvm::DIType *CGDebugInfo::CreatePointerLikeType(llvm::dwarf::Tag Tag,
// because that does not return the correct value for references.
unsigned AS = CGM.getContext().getTargetAddressSpace(PointeeTy);
uint64_t Size = CGM.getTarget().getPointerWidth(AS);
- uint64_t Align = CGM.getContext().getTypeAlign(Ty);
+ auto Align = getTypeAlignIfRequired(Ty, CGM.getContext());
if (Tag == llvm::dwarf::DW_TAG_reference_type ||
Tag == llvm::dwarf::DW_TAG_rvalue_reference_type)
@@ -776,7 +822,7 @@ llvm::DIType *CGDebugInfo::CreateType(const BlockPointerType *Ty,
SmallVector<llvm::Metadata *, 8> EltTys;
QualType FType;
uint64_t FieldSize, FieldOffset;
- unsigned FieldAlign;
+ uint32_t FieldAlign;
llvm::DINodeArray Elements;
FieldOffset = 0;
@@ -787,7 +833,7 @@ llvm::DIType *CGDebugInfo::CreateType(const BlockPointerType *Ty,
Elements = DBuilder.getOrCreateArray(EltTys);
EltTys.clear();
- unsigned Flags = llvm::DINode::FlagAppleBlock;
+ llvm::DINode::DIFlags Flags = llvm::DINode::FlagAppleBlock;
unsigned LineNo = 0;
auto *EltTy =
@@ -811,9 +857,9 @@ llvm::DIType *CGDebugInfo::CreateType(const BlockPointerType *Ty,
FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
FieldSize = CGM.getContext().getTypeSize(Ty);
FieldAlign = CGM.getContext().getTypeAlign(Ty);
- EltTys.push_back(DBuilder.createMemberType(Unit, "__descriptor", nullptr, LineNo,
- FieldSize, FieldAlign, FieldOffset,
- 0, DescTy));
+ EltTys.push_back(DBuilder.createMemberType(
+ Unit, "__descriptor", nullptr, LineNo, FieldSize, FieldAlign, FieldOffset,
+ llvm::DINode::FlagZero, DescTy));
FieldOffset += FieldSize;
Elements = DBuilder.getOrCreateArray(EltTys);
@@ -893,6 +939,7 @@ static unsigned getDwarfCC(CallingConv CC) {
case CC_Swift:
case CC_PreserveMost:
case CC_PreserveAll:
+ case CC_X86RegCall:
return 0;
}
return 0;
@@ -917,14 +964,15 @@ llvm::DIType *CGDebugInfo::CreateType(const FunctionType *Ty,
}
llvm::DITypeRefArray EltTypeArray = DBuilder.getOrCreateTypeArray(EltTys);
- return DBuilder.createSubroutineType(EltTypeArray, 0,
+ return DBuilder.createSubroutineType(EltTypeArray, llvm::DINode::FlagZero,
getDwarfCC(Ty->getCallConv()));
}
/// Convert an AccessSpecifier into the corresponding DINode flag.
/// As an optimization, return 0 if the access specifier equals the
/// default for the containing type.
-static unsigned getAccessFlag(AccessSpecifier Access, const RecordDecl *RD) {
+static llvm::DINode::DIFlags getAccessFlag(AccessSpecifier Access,
+ const RecordDecl *RD) {
AccessSpecifier Default = clang::AS_none;
if (RD && RD->isClass())
Default = clang::AS_private;
@@ -932,7 +980,7 @@ static unsigned getAccessFlag(AccessSpecifier Access, const RecordDecl *RD) {
Default = clang::AS_public;
if (Access == Default)
- return 0;
+ return llvm::DINode::FlagZero;
switch (Access) {
case clang::AS_private:
@@ -942,7 +990,7 @@ static unsigned getAccessFlag(AccessSpecifier Access, const RecordDecl *RD) {
case clang::AS_public:
return llvm::DINode::FlagPublic;
case clang::AS_none:
- return 0;
+ return llvm::DINode::FlagZero;
}
llvm_unreachable("unexpected access enumerator");
}
@@ -964,21 +1012,20 @@ llvm::DIType *CGDebugInfo::createBitFieldType(const FieldDecl *BitFieldDecl,
CGM.getTypes().getCGRecordLayout(RD).getBitFieldInfo(BitFieldDecl);
uint64_t SizeInBits = BitFieldInfo.Size;
assert(SizeInBits > 0 && "found named 0-width bitfield");
- unsigned AlignInBits = CGM.getContext().getTypeAlign(Ty);
uint64_t StorageOffsetInBits =
CGM.getContext().toBits(BitFieldInfo.StorageOffset);
uint64_t OffsetInBits = StorageOffsetInBits + BitFieldInfo.Offset;
- unsigned Flags = getAccessFlag(BitFieldDecl->getAccess(), RD);
+ llvm::DINode::DIFlags Flags = getAccessFlag(BitFieldDecl->getAccess(), RD);
return DBuilder.createBitFieldMemberType(
- RecordTy, Name, File, Line, SizeInBits, AlignInBits, OffsetInBits,
- StorageOffsetInBits, Flags, DebugType);
+ RecordTy, Name, File, Line, SizeInBits, OffsetInBits, StorageOffsetInBits,
+ Flags, DebugType);
}
llvm::DIType *
CGDebugInfo::createFieldType(StringRef name, QualType type, SourceLocation loc,
AccessSpecifier AS, uint64_t offsetInBits,
- llvm::DIFile *tunit, llvm::DIScope *scope,
- const RecordDecl *RD) {
+ uint32_t AlignInBits, llvm::DIFile *tunit,
+ llvm::DIScope *scope, const RecordDecl *RD) {
llvm::DIType *debugType = getOrCreateType(type, tunit);
// Get the location for the field.
@@ -986,16 +1033,17 @@ CGDebugInfo::createFieldType(StringRef name, QualType type, SourceLocation loc,
unsigned line = getLineNumber(loc);
uint64_t SizeInBits = 0;
- unsigned AlignInBits = 0;
+ auto Align = AlignInBits;
if (!type->isIncompleteArrayType()) {
TypeInfo TI = CGM.getContext().getTypeInfo(type);
SizeInBits = TI.Width;
- AlignInBits = TI.Align;
+ if (!Align)
+ Align = getTypeAlignIfRequired(type, CGM.getContext());
}
- unsigned flags = getAccessFlag(AS, RD);
+ llvm::DINode::DIFlags flags = getAccessFlag(AS, RD);
return DBuilder.createMemberType(scope, name, file, line, SizeInBits,
- AlignInBits, offsetInBits, flags, debugType);
+ Align, offsetInBits, flags, debugType);
}
void CGDebugInfo::CollectRecordLambdaFields(
@@ -1017,9 +1065,10 @@ void CGDebugInfo::CollectRecordLambdaFields(
VarDecl *V = C.getCapturedVar();
StringRef VName = V->getName();
llvm::DIFile *VUnit = getOrCreateFile(Loc);
+ auto Align = getDeclAlignIfRequired(V, CGM.getContext());
llvm::DIType *FieldType = createFieldType(
VName, Field->getType(), Loc, Field->getAccess(),
- layout.getFieldOffset(fieldno), VUnit, RecordTy, CXXDecl);
+ layout.getFieldOffset(fieldno), Align, VUnit, RecordTy, CXXDecl);
elements.push_back(FieldType);
} else if (C.capturesThis()) {
// TODO: Need to handle 'this' in some way by probably renaming the
@@ -1060,9 +1109,10 @@ CGDebugInfo::CreateRecordStaticField(const VarDecl *Var, llvm::DIType *RecordTy,
}
}
- unsigned Flags = getAccessFlag(Var->getAccess(), RD);
+ llvm::DINode::DIFlags Flags = getAccessFlag(Var->getAccess(), RD);
+ auto Align = getDeclAlignIfRequired(Var, CGM.getContext());
llvm::DIDerivedType *GV = DBuilder.createStaticMemberType(
- RecordTy, VName, VUnit, LineNumber, VTy, Flags, C);
+ RecordTy, VName, VUnit, LineNumber, VTy, Flags, C, Align);
StaticDataMemberCache[Var->getCanonicalDecl()].reset(GV);
return GV;
}
@@ -1082,14 +1132,26 @@ void CGDebugInfo::CollectRecordNormalField(
if (field->isBitField()) {
FieldType = createBitFieldType(field, RecordTy, RD);
} else {
+ auto Align = getDeclAlignIfRequired(field, CGM.getContext());
FieldType =
createFieldType(name, type, field->getLocation(), field->getAccess(),
- OffsetInBits, tunit, RecordTy, RD);
+ OffsetInBits, Align, tunit, RecordTy, RD);
}
elements.push_back(FieldType);
}
+void CGDebugInfo::CollectRecordNestedRecord(
+ const RecordDecl *RD, SmallVectorImpl<llvm::Metadata *> &elements) {
+ QualType Ty = CGM.getContext().getTypeDeclType(RD);
+ // Injected class names are not considered nested records.
+ if (isa<InjectedClassNameType>(Ty))
+ return;
+ SourceLocation Loc = RD->getLocation();
+ llvm::DIType *nestedType = getOrCreateType(Ty, getOrCreateFile(Loc));
+ elements.push_back(nestedType);
+}
+
void CGDebugInfo::CollectRecordFields(
const RecordDecl *record, llvm::DIFile *tunit,
SmallVectorImpl<llvm::Metadata *> &elements,
@@ -1101,6 +1163,10 @@ void CGDebugInfo::CollectRecordFields(
else {
const ASTRecordLayout &layout = CGM.getContext().getASTRecordLayout(record);
+ // Debug info for nested records is included in the member list only for
+ // CodeView.
+ bool IncludeNestedRecords = CGM.getCodeGenOpts().EmitCodeView;
+
// Field number for non-static fields.
unsigned fieldNo = 0;
@@ -1126,7 +1192,10 @@ void CGDebugInfo::CollectRecordFields(
// Bump field number for next field.
++fieldNo;
- }
+ } else if (const auto *nestedRec = dyn_cast<CXXRecordDecl>(I))
+ if (IncludeNestedRecords && !nestedRec->isImplicit() &&
+ nestedRec->getDeclContext() == record)
+ CollectRecordNestedRecord(nestedRec, elements);
}
}
@@ -1162,7 +1231,7 @@ llvm::DISubroutineType *CGDebugInfo::getOrCreateInstanceMethodType(
QualType PointeeTy = ThisPtrTy->getPointeeType();
unsigned AS = CGM.getContext().getTargetAddressSpace(PointeeTy);
uint64_t Size = CGM.getTarget().getPointerWidth(AS);
- uint64_t Align = CGM.getContext().getTypeAlign(ThisPtrTy);
+ auto Align = getTypeAlignIfRequired(ThisPtrTy, CGM.getContext());
llvm::DIType *PointeeType = getOrCreateType(PointeeTy, Unit);
llvm::DIType *ThisPtrType =
DBuilder.createPointerType(PointeeType, Size, Align);
@@ -1185,7 +1254,7 @@ llvm::DISubroutineType *CGDebugInfo::getOrCreateInstanceMethodType(
llvm::DITypeRefArray EltTypeArray = DBuilder.getOrCreateTypeArray(Elts);
- unsigned Flags = 0;
+ llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
if (Func->getExtProtoInfo().RefQualifier == RQ_LValue)
Flags |= llvm::DINode::FlagLValueReference;
if (Func->getExtProtoInfo().RefQualifier == RQ_RValue)
@@ -1236,7 +1305,7 @@ llvm::DISubprogram *CGDebugInfo::CreateCXXMemberFunction(
llvm::DIType *ContainingType = nullptr;
unsigned Virtuality = 0;
unsigned VIndex = 0;
- unsigned Flags = 0;
+ llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
int ThisAdjustment = 0;
if (Method->isVirtual()) {
@@ -1347,13 +1416,33 @@ void CGDebugInfo::CollectCXXMemberFunctions(
void CGDebugInfo::CollectCXXBases(const CXXRecordDecl *RD, llvm::DIFile *Unit,
SmallVectorImpl<llvm::Metadata *> &EltTys,
llvm::DIType *RecordTy) {
- const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
- for (const auto &BI : RD->bases()) {
- unsigned BFlags = 0;
- uint64_t BaseOffset;
+ llvm::DenseSet<CanonicalDeclPtr<const CXXRecordDecl>> SeenTypes;
+ CollectCXXBasesAux(RD, Unit, EltTys, RecordTy, RD->bases(), SeenTypes,
+ llvm::DINode::FlagZero);
+
+ // If we are generating CodeView debug info, we also need to emit records for
+ // indirect virtual base classes.
+ if (CGM.getCodeGenOpts().EmitCodeView) {
+ CollectCXXBasesAux(RD, Unit, EltTys, RecordTy, RD->vbases(), SeenTypes,
+ llvm::DINode::FlagIndirectVirtualBase);
+ }
+}
+void CGDebugInfo::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) {
+ const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
+ for (const auto &BI : Bases) {
const auto *Base =
cast<CXXRecordDecl>(BI.getType()->getAs<RecordType>()->getDecl());
+ if (!SeenTypes.insert(Base).second)
+ continue;
+ auto *BaseTy = getOrCreateType(BI.getType(), Unit);
+ llvm::DINode::DIFlags BFlags = StartingFlags;
+ uint64_t BaseOffset;
if (BI.isVirtual()) {
if (CGM.getTarget().getCXXABI().isItaniumFamily()) {
@@ -1368,15 +1457,15 @@ void CGDebugInfo::CollectCXXBases(const CXXRecordDecl *RD, llvm::DIFile *Unit,
BaseOffset =
4 * CGM.getMicrosoftVTableContext().getVBTableIndex(RD, Base);
}
- BFlags = llvm::DINode::FlagVirtual;
+ BFlags |= llvm::DINode::FlagVirtual;
} else
BaseOffset = CGM.getContext().toBits(RL.getBaseClassOffset(Base));
// FIXME: Inconsistent units for BaseOffset. It is in bytes when
// BI->isVirtual() and bits when not.
BFlags |= getAccessFlag(BI.getAccessSpecifier(), RD);
- llvm::DIType *DTy = DBuilder.createInheritance(
- RecordTy, getOrCreateType(BI.getType(), Unit), BaseOffset, BFlags);
+ llvm::DIType *DTy =
+ DBuilder.createInheritance(RecordTy, BaseTy, BaseOffset, BFlags);
EltTys.push_back(DTy);
}
}
@@ -1531,22 +1620,56 @@ StringRef CGDebugInfo::getVTableName(const CXXRecordDecl *RD) {
}
void CGDebugInfo::CollectVTableInfo(const CXXRecordDecl *RD, llvm::DIFile *Unit,
- SmallVectorImpl<llvm::Metadata *> &EltTys) {
+ SmallVectorImpl<llvm::Metadata *> &EltTys,
+ llvm::DICompositeType *RecordTy) {
+ // If this class is not dynamic then there is not any vtable info to collect.
+ if (!RD->isDynamicClass())
+ return;
+
+ // Don't emit any vtable shape or vptr info if this class doesn't have an
+ // extendable vfptr. This can happen if the class doesn't have virtual
+ // methods, or in the MS ABI if those virtual methods only come from virtually
+ // inherited bases.
const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
+ if (!RL.hasExtendableVFPtr())
+ return;
- // If there is a primary base then it will hold vtable info.
+ // CodeView needs to know how large the vtable of every dynamic class is, so
+ // emit a special named pointer type into the element list. The vptr type
+ // points to this type as well.
+ llvm::DIType *VPtrTy = nullptr;
+ bool NeedVTableShape = CGM.getCodeGenOpts().EmitCodeView &&
+ CGM.getTarget().getCXXABI().isMicrosoft();
+ if (NeedVTableShape) {
+ uint64_t PtrWidth =
+ CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy);
+ const VTableLayout &VFTLayout =
+ CGM.getMicrosoftVTableContext().getVFTableLayout(RD, CharUnits::Zero());
+ unsigned VSlotCount =
+ VFTLayout.vtable_components().size() - CGM.getLangOpts().RTTIData;
+ unsigned VTableWidth = PtrWidth * VSlotCount;
+
+ // Create a very wide void* type and insert it directly in the element list.
+ llvm::DIType *VTableType =
+ DBuilder.createPointerType(nullptr, VTableWidth, 0, "__vtbl_ptr_type");
+ EltTys.push_back(VTableType);
+
+ // The vptr is a pointer to this special vtable type.
+ VPtrTy = DBuilder.createPointerType(VTableType, PtrWidth);
+ }
+
+ // If there is a primary base then the artificial vptr member lives there.
if (RL.getPrimaryBase())
return;
- // If this class is not dynamic then there is not any vtable info to collect.
- if (!RD->isDynamicClass())
- return;
+ if (!VPtrTy)
+ VPtrTy = getOrCreateVTablePtrType(Unit);
unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy);
- llvm::DIType *VPTR = DBuilder.createMemberType(
+ llvm::DIType *VPtrMember = DBuilder.createMemberType(
Unit, getVTableName(RD), Unit, 0, Size, 0, 0,
- llvm::DINode::FlagArtificial, getOrCreateVTablePtrType(Unit));
- EltTys.push_back(VPTR);
+ llvm::DINode::FlagArtificial, VPtrTy);
+ EltTys.push_back(VPtrMember);
}
llvm::DIType *CGDebugInfo::getOrCreateRecordType(QualType RTy,
@@ -1591,23 +1714,6 @@ void CGDebugInfo::completeType(const RecordDecl *RD) {
completeRequiredType(RD);
}
-void CGDebugInfo::completeRequiredType(const RecordDecl *RD) {
- if (DebugKind <= codegenoptions::DebugLineTablesOnly)
- return;
-
- if (const auto *CXXDecl = dyn_cast<CXXRecordDecl>(RD))
- if (CXXDecl->isDynamicClass())
- return;
-
- if (DebugTypeExtRefs && RD->isFromASTFile())
- return;
-
- QualType Ty = CGM.getContext().getRecordType(RD);
- llvm::DIType *T = getTypeOrNull(Ty);
- if (T && T->isForwardDecl())
- completeClassData(RD);
-}
-
void CGDebugInfo::completeClassData(const RecordDecl *RD) {
if (DebugKind <= codegenoptions::DebugLineTablesOnly)
return;
@@ -1633,21 +1739,37 @@ static bool hasExplicitMemberDefinition(CXXRecordDecl::method_iterator I,
/// Does a type definition exist in an imported clang module?
static bool isDefinedInClangModule(const RecordDecl *RD) {
+ // Only definitions that where imported from an AST file come from a module.
if (!RD || !RD->isFromASTFile())
return false;
+ // Anonymous entities cannot be addressed. Treat them as not from module.
if (!RD->isExternallyVisible() && RD->getName().empty())
return false;
if (auto *CXXDecl = dyn_cast<CXXRecordDecl>(RD)) {
- assert(CXXDecl->isCompleteDefinition() && "incomplete record definition");
- if (CXXDecl->getTemplateSpecializationKind() != TSK_Undeclared)
- // Make sure the instantiation is actually in a module.
- if (CXXDecl->field_begin() != CXXDecl->field_end())
- return CXXDecl->field_begin()->isFromASTFile();
+ if (!CXXDecl->isCompleteDefinition())
+ return false;
+ auto TemplateKind = CXXDecl->getTemplateSpecializationKind();
+ if (TemplateKind != TSK_Undeclared) {
+ // This is a template, check the origin of the first member.
+ if (CXXDecl->field_begin() == CXXDecl->field_end())
+ return TemplateKind == TSK_ExplicitInstantiationDeclaration;
+ if (!CXXDecl->field_begin()->isFromASTFile())
+ return false;
+ }
}
-
return true;
}
+/// Return true if the class or any of its methods are marked dllimport.
+static bool isClassOrMethodDLLImport(const CXXRecordDecl *RD) {
+ if (RD->hasAttr<DLLImportAttr>())
+ return true;
+ for (const CXXMethodDecl *MD : RD->methods())
+ if (MD->hasAttr<DLLImportAttr>())
+ return true;
+ return false;
+}
+
static bool shouldOmitDefinition(codegenoptions::DebugInfoKind DebugKind,
bool DebugTypeExtRefs, const RecordDecl *RD,
const LangOptions &LangOpts) {
@@ -1668,7 +1790,14 @@ static bool shouldOmitDefinition(codegenoptions::DebugInfoKind DebugKind,
if (!CXXDecl)
return false;
- if (CXXDecl->hasDefinition() && CXXDecl->isDynamicClass())
+ // Only emit complete debug info for a dynamic class when its vtable is
+ // emitted. However, Microsoft debuggers don't resolve type information
+ // across DLL boundaries, so skip this optimization if the class or any of its
+ // methods are marked dllimport. This isn't a complete solution, since objects
+ // without any dllimport methods can be used in one DLL and constructed in
+ // another, but it is the current behavior of LimitedDebugInfo.
+ if (CXXDecl->hasDefinition() && CXXDecl->isDynamicClass() &&
+ !isClassOrMethodDLLImport(CXXDecl))
return true;
TemplateSpecializationKind Spec = TSK_Undeclared;
@@ -1683,6 +1812,16 @@ static bool shouldOmitDefinition(codegenoptions::DebugInfoKind DebugKind,
return false;
}
+void CGDebugInfo::completeRequiredType(const RecordDecl *RD) {
+ if (shouldOmitDefinition(DebugKind, DebugTypeExtRefs, RD, CGM.getLangOpts()))
+ return;
+
+ QualType Ty = CGM.getContext().getRecordType(RD);
+ llvm::DIType *T = getTypeOrNull(Ty);
+ if (T && T->isForwardDecl())
+ completeClassData(RD);
+}
+
llvm::DIType *CGDebugInfo::CreateType(const RecordType *Ty) {
RecordDecl *RD = Ty->getDecl();
llvm::DIType *T = cast_or_null<llvm::DIType>(getTypeOrNull(QualType(Ty, 0)));
@@ -1732,7 +1871,7 @@ llvm::DIType *CGDebugInfo::CreateTypeDefinition(const RecordType *Ty) {
const auto *CXXDecl = dyn_cast<CXXRecordDecl>(RD);
if (CXXDecl) {
CollectCXXBases(CXXDecl, DefUnit, EltTys, FwdDecl);
- CollectVTableInfo(CXXDecl, DefUnit, EltTys);
+ CollectVTableInfo(CXXDecl, DefUnit, EltTys, FwdDecl);
}
// Collect data fields (including static variables and any initializers).
@@ -1760,6 +1899,18 @@ llvm::DIType *CGDebugInfo::CreateType(const ObjCObjectType *Ty,
return getOrCreateType(Ty->getBaseType(), Unit);
}
+llvm::DIType *CGDebugInfo::CreateType(const ObjCTypeParamType *Ty,
+ llvm::DIFile *Unit) {
+ // Ignore protocols.
+ SourceLocation Loc = Ty->getDecl()->getLocation();
+
+ // Use Typedefs to represent ObjCTypeParamType.
+ return DBuilder.createTypedef(
+ getOrCreateType(Ty->getDecl()->getUnderlyingType(), Unit),
+ Ty->getDecl()->getName(), getOrCreateFile(Loc), getLineNumber(Loc),
+ getDeclContextDescriptor(Ty->getDecl()));
+}
+
/// \return true if Getter has the default name for the property PD.
static bool hasDefaultGetterName(const ObjCPropertyDecl *PD,
const ObjCMethodDecl *Getter) {
@@ -1860,10 +2011,11 @@ CGDebugInfo::getOrCreateModuleRef(ExternalASTSource::ASTSourceDescriptor Mod,
// but LLVM detects skeleton CUs by looking for a non-zero DWO id.
uint64_t Signature = Mod.getSignature() ? Mod.getSignature() : ~1ULL;
llvm::DIBuilder DIB(CGM.getModule());
- DIB.createCompileUnit(TheCU->getSourceLanguage(), Mod.getModuleName(),
- Mod.getPath(), TheCU->getProducer(), true,
- StringRef(), 0, Mod.getASTFile(),
- llvm::DICompileUnit::FullDebug, Signature);
+ DIB.createCompileUnit(TheCU->getSourceLanguage(),
+ DIB.createFile(Mod.getModuleName(), Mod.getPath()),
+ TheCU->getProducer(), true, StringRef(), 0,
+ Mod.getASTFile(), llvm::DICompileUnit::FullDebug,
+ Signature);
DIB.finalize();
}
llvm::DIModule *Parent =
@@ -1887,9 +2039,9 @@ llvm::DIType *CGDebugInfo::CreateTypeDefinition(const ObjCInterfaceType *Ty,
// Bit size, align and offset of the type.
uint64_t Size = CGM.getContext().getTypeSize(Ty);
- uint64_t Align = CGM.getContext().getTypeAlign(Ty);
+ auto Align = getTypeAlignIfRequired(Ty, CGM.getContext());
- unsigned Flags = 0;
+ llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
if (ID->getImplementation())
Flags |= llvm::DINode::FlagObjcClassComplete;
@@ -1915,7 +2067,8 @@ llvm::DIType *CGDebugInfo::CreateTypeDefinition(const ObjCInterfaceType *Ty,
if (!SClassTy)
return nullptr;
- llvm::DIType *InhTag = DBuilder.createInheritance(RealDecl, SClassTy, 0, 0);
+ llvm::DIType *InhTag = DBuilder.createInheritance(RealDecl, SClassTy, 0,
+ llvm::DINode::FlagZero);
EltTys.push_back(InhTag);
}
@@ -1970,7 +2123,7 @@ llvm::DIType *CGDebugInfo::CreateTypeDefinition(const ObjCInterfaceType *Ty,
unsigned FieldLine = getLineNumber(Field->getLocation());
QualType FType = Field->getType();
uint64_t FieldSize = 0;
- unsigned FieldAlign = 0;
+ uint32_t FieldAlign = 0;
if (!FType->isIncompleteArrayType()) {
@@ -1978,7 +2131,7 @@ llvm::DIType *CGDebugInfo::CreateTypeDefinition(const ObjCInterfaceType *Ty,
FieldSize = Field->isBitField()
? Field->getBitWidthValue(CGM.getContext())
: CGM.getContext().getTypeSize(FType);
- FieldAlign = CGM.getContext().getTypeAlign(FType);
+ FieldAlign = getTypeAlignIfRequired(FType, CGM.getContext());
}
uint64_t FieldOffset;
@@ -1997,7 +2150,7 @@ llvm::DIType *CGDebugInfo::CreateTypeDefinition(const ObjCInterfaceType *Ty,
FieldOffset = RL.getFieldOffset(FieldNo);
}
- unsigned Flags = 0;
+ llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
if (Field->getAccessControl() == ObjCIvarDecl::Protected)
Flags = llvm::DINode::FlagProtected;
else if (Field->getAccessControl() == ObjCIvarDecl::Private)
@@ -2052,33 +2205,33 @@ llvm::DIType *CGDebugInfo::CreateType(const VectorType *Ty,
llvm::DINodeArray SubscriptArray = DBuilder.getOrCreateArray(Subscript);
uint64_t Size = CGM.getContext().getTypeSize(Ty);
- uint64_t Align = CGM.getContext().getTypeAlign(Ty);
+ auto Align = getTypeAlignIfRequired(Ty, CGM.getContext());
return DBuilder.createVectorType(Size, Align, ElementTy, SubscriptArray);
}
llvm::DIType *CGDebugInfo::CreateType(const ArrayType *Ty, llvm::DIFile *Unit) {
uint64_t Size;
- uint64_t Align;
+ uint32_t Align;
// FIXME: make getTypeAlign() aware of VLAs and incomplete array types
if (const auto *VAT = dyn_cast<VariableArrayType>(Ty)) {
Size = 0;
- Align =
- CGM.getContext().getTypeAlign(CGM.getContext().getBaseElementType(VAT));
+ Align = getTypeAlignIfRequired(CGM.getContext().getBaseElementType(VAT),
+ CGM.getContext());
} else if (Ty->isIncompleteArrayType()) {
Size = 0;
if (Ty->getElementType()->isIncompleteType())
Align = 0;
else
- Align = CGM.getContext().getTypeAlign(Ty->getElementType());
+ Align = getTypeAlignIfRequired(Ty->getElementType(), CGM.getContext());
} else if (Ty->isIncompleteType()) {
Size = 0;
Align = 0;
} else {
// Size and align of the whole array, not the element type.
Size = CGM.getContext().getTypeSize(Ty);
- Align = CGM.getContext().getTypeAlign(Ty);
+ Align = getTypeAlignIfRequired(Ty, CGM.getContext());
}
// Add the dimensions of the array. FIXME: This loses CV qualifiers from
@@ -2097,6 +2250,13 @@ llvm::DIType *CGDebugInfo::CreateType(const ArrayType *Ty, llvm::DIFile *Unit) {
int64_t Count = -1; // Count == -1 is an unbounded array.
if (const auto *CAT = dyn_cast<ConstantArrayType>(Ty))
Count = CAT->getSize().getZExtValue();
+ else if (const auto *VAT = dyn_cast<VariableArrayType>(Ty)) {
+ if (Expr *Size = VAT->getSizeExpr()) {
+ llvm::APSInt V;
+ if (Size->EvaluateAsInt(V, CGM.getContext()))
+ Count = V.getExtValue();
+ }
+ }
// FIXME: Verify this is right for VLAs.
Subscripts.push_back(DBuilder.getOrCreateSubrange(0, Count));
@@ -2123,7 +2283,7 @@ llvm::DIType *CGDebugInfo::CreateType(const RValueReferenceType *Ty,
llvm::DIType *CGDebugInfo::CreateType(const MemberPointerType *Ty,
llvm::DIFile *U) {
- unsigned Flags = 0;
+ llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
uint64_t Size = 0;
if (!Ty->isIncompleteType()) {
@@ -2163,9 +2323,8 @@ llvm::DIType *CGDebugInfo::CreateType(const MemberPointerType *Ty,
}
llvm::DIType *CGDebugInfo::CreateType(const AtomicType *Ty, llvm::DIFile *U) {
- // Ignore the atomic wrapping
- // FIXME: What is the correct representation?
- return getOrCreateType(Ty->getValueType(), U);
+ auto *FromTy = getOrCreateType(Ty->getValueType(), U);
+ return DBuilder.createQualifiedType(llvm::dwarf::DW_TAG_atomic_type, FromTy);
}
llvm::DIType* CGDebugInfo::CreateType(const PipeType *Ty,
@@ -2177,10 +2336,10 @@ llvm::DIType *CGDebugInfo::CreateEnumType(const EnumType *Ty) {
const EnumDecl *ED = Ty->getDecl();
uint64_t Size = 0;
- uint64_t Align = 0;
+ uint32_t Align = 0;
if (!ED->getTypeForDecl()->isIncompleteType()) {
Size = CGM.getContext().getTypeSize(ED->getTypeForDecl());
- Align = CGM.getContext().getTypeAlign(ED->getTypeForDecl());
+ Align = getDeclAlignIfRequired(ED, CGM.getContext());
}
SmallString<256> FullName = getUniqueTagTypeName(Ty, CGM, TheCU);
@@ -2220,10 +2379,10 @@ llvm::DIType *CGDebugInfo::CreateEnumType(const EnumType *Ty) {
llvm::DIType *CGDebugInfo::CreateTypeDefinition(const EnumType *Ty) {
const EnumDecl *ED = Ty->getDecl();
uint64_t Size = 0;
- uint64_t Align = 0;
+ uint32_t Align = 0;
if (!ED->getTypeForDecl()->isIncompleteType()) {
Size = CGM.getContext().getTypeSize(ED->getTypeForDecl());
- Align = CGM.getContext().getTypeAlign(ED->getTypeForDecl());
+ Align = getDeclAlignIfRequired(ED, CGM.getContext());
}
SmallString<256> FullName = getUniqueTagTypeName(Ty, CGM, TheCU);
@@ -2292,12 +2451,18 @@ static QualType UnwrapTypeForDebugInfo(QualType T, const ASTContext &C) {
case Type::SubstTemplateTypeParm:
T = cast<SubstTemplateTypeParmType>(T)->getReplacementType();
break;
- case Type::Auto:
+ case Type::Auto: {
QualType DT = cast<AutoType>(T)->getDeducedType();
assert(!DT.isNull() && "Undeduced types shouldn't reach here.");
T = DT;
break;
}
+ case Type::Adjusted:
+ case Type::Decayed:
+ // Decayed and adjusted types use the adjusted type in LLVM and DWARF.
+ T = cast<AdjustedType>(T)->getAdjustedType();
+ break;
+ }
assert(T != LastT && "Type unwrapping failed to unwrap!");
(void)LastT;
@@ -2406,6 +2571,8 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) {
return CreateType(cast<ObjCObjectPointerType>(Ty), Unit);
case Type::ObjCObject:
return CreateType(cast<ObjCObjectType>(Ty), Unit);
+ case Type::ObjCTypeParam:
+ return CreateType(cast<ObjCTypeParamType>(Ty), Unit);
case Type::ObjCInterface:
return CreateType(cast<ObjCInterfaceType>(Ty), Unit);
case Type::Builtin:
@@ -2414,11 +2581,6 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) {
return CreateType(cast<ComplexType>(Ty));
case Type::Pointer:
return CreateType(cast<PointerType>(Ty), Unit);
- case Type::Adjusted:
- case Type::Decayed:
- // Decayed and adjusted types use the adjusted type in LLVM and DWARF.
- return CreateType(
- cast<PointerType>(cast<AdjustedType>(Ty)->getAdjustedType()), Unit);
case Type::BlockPointer:
return CreateType(cast<BlockPointerType>(Ty), Unit);
case Type::Typedef:
@@ -2454,6 +2616,8 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) {
case Type::Auto:
case Type::Attributed:
+ case Type::Adjusted:
+ case Type::Decayed:
case Type::Elaborated:
case Type::Paren:
case Type::SubstTemplateTypeParm:
@@ -2518,13 +2682,13 @@ llvm::DICompositeType *CGDebugInfo::CreateLimitedType(const RecordType *Ty) {
return getOrCreateRecordFwdDecl(Ty, RDContext);
uint64_t Size = CGM.getContext().getTypeSize(Ty);
- uint64_t Align = CGM.getContext().getTypeAlign(Ty);
+ auto Align = getDeclAlignIfRequired(D, CGM.getContext());
SmallString<256> FullName = getUniqueTagTypeName(Ty, CGM, TheCU);
llvm::DICompositeType *RealDecl = DBuilder.createReplaceableCompositeType(
- getTagForRecord(RD), RDName, RDContext, DefUnit, Line, 0, Size, Align, 0,
- FullName);
+ getTagForRecord(RD), RDName, RDContext, DefUnit, Line, 0, Size, Align,
+ llvm::DINode::FlagZero, FullName);
// Elements of composite types usually have back to the type, creating
// uniquing cycles. Distinct nodes are more efficient.
@@ -2587,9 +2751,10 @@ llvm::DIType *CGDebugInfo::CreateMemberType(llvm::DIFile *Unit, QualType FType,
StringRef Name, uint64_t *Offset) {
llvm::DIType *FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
uint64_t FieldSize = CGM.getContext().getTypeSize(FType);
- unsigned FieldAlign = CGM.getContext().getTypeAlign(FType);
- llvm::DIType *Ty = DBuilder.createMemberType(Unit, Name, Unit, 0, FieldSize,
- FieldAlign, *Offset, 0, FieldTy);
+ auto FieldAlign = getTypeAlignIfRequired(FType, CGM.getContext());
+ llvm::DIType *Ty =
+ DBuilder.createMemberType(Unit, Name, Unit, 0, FieldSize, FieldAlign,
+ *Offset, llvm::DINode::FlagZero, FieldTy);
*Offset += FieldSize;
return Ty;
}
@@ -2599,7 +2764,7 @@ void CGDebugInfo::collectFunctionDeclProps(GlobalDecl GD, llvm::DIFile *Unit,
StringRef &LinkageName,
llvm::DIScope *&FDContext,
llvm::DINodeArray &TParamsArray,
- unsigned &Flags) {
+ llvm::DINode::DIFlags &Flags) {
const auto *FD = cast<FunctionDecl>(GD.getDecl());
Name = getFunctionName(FD);
// Use mangled name as linkage name for C/C++ functions.
@@ -2624,6 +2789,9 @@ void CGDebugInfo::collectFunctionDeclProps(GlobalDecl GD, llvm::DIFile *Unit,
llvm::DIScope *Mod = getParentModuleOrNull(RDecl);
FDContext = getContextDescriptor(RDecl, Mod ? Mod : TheCU);
}
+ // Check if it is a noreturn-marked function
+ if (FD->isNoReturn())
+ Flags |= llvm::DINode::FlagNoReturn;
// Collect template parameters.
TParamsArray = CollectFunctionTemplateParams(FD, Unit);
}
@@ -2680,7 +2848,7 @@ llvm::DISubprogram *
CGDebugInfo::getFunctionForwardDeclaration(const FunctionDecl *FD) {
llvm::DINodeArray TParamsArray;
StringRef Name, LinkageName;
- unsigned Flags = 0;
+ llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
SourceLocation Loc = FD->getLocation();
llvm::DIFile *Unit = getOrCreateFile(Loc);
llvm::DIScope *DContext = Unit;
@@ -2717,9 +2885,10 @@ CGDebugInfo::getGlobalVariableForwardDeclaration(const VarDecl *VD) {
unsigned Line = getLineNumber(Loc);
collectVarDeclProps(VD, Unit, Line, T, Name, LinkageName, DContext);
+ auto Align = getDeclAlignIfRequired(VD, CGM.getContext());
auto *GV = DBuilder.createTempGlobalVariableFwdDecl(
DContext, Name, LinkageName, Unit, Line, getOrCreateType(T, Unit),
- !VD->isExternallyVisible(), nullptr, nullptr);
+ !VD->isExternallyVisible(), nullptr, Align);
FwdDeclReplaceMap.emplace_back(
std::piecewise_construct,
std::make_tuple(cast<VarDecl>(VD->getCanonicalDecl())),
@@ -2737,8 +2906,12 @@ llvm::DINode *CGDebugInfo::getDeclarationOrDefinition(const Decl *D) {
getOrCreateFile(TD->getLocation()));
auto I = DeclCache.find(D->getCanonicalDecl());
- if (I != DeclCache.end())
- return dyn_cast_or_null<llvm::DINode>(I->second);
+ if (I != DeclCache.end()) {
+ auto N = I->second;
+ if (auto *GVE = dyn_cast_or_null<llvm::DIGlobalVariableExpression>(N))
+ return GVE->getVariable();
+ return dyn_cast_or_null<llvm::DINode>(N);
+ }
// No definition for now. Emit a forward definition that might be
// merged with a potential upcoming definition.
@@ -2834,7 +3007,8 @@ llvm::DISubroutineType *CGDebugInfo::getOrCreateFunctionType(const Decl *D,
Elts.push_back(DBuilder.createUnspecifiedParameter());
llvm::DITypeRefArray EltTypeArray = DBuilder.getOrCreateTypeArray(Elts);
- return DBuilder.createSubroutineType(EltTypeArray, 0, getDwarfCC(CC));
+ return DBuilder.createSubroutineType(EltTypeArray, llvm::DINode::FlagZero,
+ getDwarfCC(CC));
}
// Handle variadic function types; they need an additional
@@ -2848,7 +3022,8 @@ llvm::DISubroutineType *CGDebugInfo::getOrCreateFunctionType(const Decl *D,
EltTys.push_back(getOrCreateType(ParamType, F));
EltTys.push_back(DBuilder.createUnspecifiedParameter());
llvm::DITypeRefArray EltTypeArray = DBuilder.getOrCreateTypeArray(EltTys);
- return DBuilder.createSubroutineType(EltTypeArray, 0, getDwarfCC(CC));
+ return DBuilder.createSubroutineType(EltTypeArray, llvm::DINode::FlagZero,
+ getDwarfCC(CC));
}
return cast<llvm::DISubroutineType>(getOrCreateType(FnType, F));
@@ -2866,7 +3041,7 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, SourceLocation Loc,
const Decl *D = GD.getDecl();
bool HasDecl = (D != nullptr);
- unsigned Flags = 0;
+ llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
llvm::DIFile *Unit = getOrCreateFile(Loc);
llvm::DIScope *FDContext = Unit;
llvm::DINodeArray TParamsArray;
@@ -2899,9 +3074,8 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, SourceLocation Loc,
if (!HasDecl || D->isImplicit()) {
Flags |= llvm::DINode::FlagArtificial;
- // Artificial functions without a location should not silently reuse CurLoc.
- if (Loc.isInvalid())
- CurLoc = SourceLocation();
+ // Artificial functions should not silently reuse CurLoc.
+ CurLoc = SourceLocation();
}
unsigned LineNo = getLineNumber(Loc);
unsigned ScopeLine = getLineNumber(ScopeLoc);
@@ -2939,7 +3113,7 @@ void CGDebugInfo::EmitFunctionDecl(GlobalDecl GD, SourceLocation Loc,
if (!D)
return;
- unsigned Flags = 0;
+ llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
llvm::DIFile *Unit = getOrCreateFile(Loc);
llvm::DIScope *FDContext = getDeclContextDescriptor(D);
llvm::DINodeArray TParamsArray;
@@ -3042,7 +3216,7 @@ llvm::DIType *CGDebugInfo::EmitTypeForVarWithBlocksAttr(const VarDecl *VD,
SmallVector<llvm::Metadata *, 5> EltTys;
QualType FType;
uint64_t FieldSize, FieldOffset;
- unsigned FieldAlign;
+ uint32_t FieldAlign;
llvm::DIFile *Unit = getOrCreateFile(VD->getLocation());
QualType Type = VD->getType();
@@ -3096,13 +3270,14 @@ llvm::DIType *CGDebugInfo::EmitTypeForVarWithBlocksAttr(const VarDecl *VD,
*XOffset = FieldOffset;
FieldTy = DBuilder.createMemberType(Unit, VD->getName(), Unit, 0, FieldSize,
- FieldAlign, FieldOffset, 0, FieldTy);
+ FieldAlign, FieldOffset,
+ llvm::DINode::FlagZero, FieldTy);
EltTys.push_back(FieldTy);
FieldOffset += FieldSize;
llvm::DINodeArray Elements = DBuilder.getOrCreateArray(EltTys);
- unsigned Flags = llvm::DINode::FlagBlockByrefStruct;
+ llvm::DINode::DIFlags Flags = llvm::DINode::FlagBlockByrefStruct;
return DBuilder.createStructType(Unit, "", Unit, 0, FieldOffset, 0, Flags,
nullptr, Elements);
@@ -3142,9 +3317,12 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, llvm::Value *Storage,
Column = getColumnNumber(VD->getLocation());
}
SmallVector<int64_t, 9> Expr;
- unsigned Flags = 0;
+ llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
if (VD->isImplicit())
Flags |= llvm::DINode::FlagArtificial;
+
+ auto Align = getDeclAlignIfRequired(VD, CGM.getContext());
+
// If this is the first argument and it is implicit then
// give it an object pointer flag.
// FIXME: There has to be a better way to do this, but for static
@@ -3179,7 +3357,7 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, llvm::Value *Storage,
? DBuilder.createParameterVariable(Scope, VD->getName(),
*ArgNo, Unit, Line, Ty)
: DBuilder.createAutoVariable(Scope, VD->getName(), Unit,
- Line, Ty);
+ Line, Ty, Align);
// Insert an llvm.dbg.declare into the current block.
DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(Expr),
@@ -3209,9 +3387,10 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, llvm::Value *Storage,
continue;
// Use VarDecl's Tag, Scope and Line number.
+ auto FieldAlign = getDeclAlignIfRequired(Field, CGM.getContext());
auto *D = DBuilder.createAutoVariable(
Scope, FieldName, Unit, Line, FieldTy, CGM.getLangOpts().Optimize,
- Flags | llvm::DINode::FlagArtificial);
+ Flags | llvm::DINode::FlagArtificial, FieldAlign);
// Insert an llvm.dbg.declare into the current block.
DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(Expr),
@@ -3222,13 +3401,13 @@ 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);
+ 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),
@@ -3307,9 +3486,10 @@ void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable(
}
// Create the descriptor for the variable.
+ auto Align = getDeclAlignIfRequired(VD, CGM.getContext());
auto *D = DBuilder.createAutoVariable(
cast<llvm::DILocalScope>(LexicalBlockStack.back()), VD->getName(), Unit,
- Line, Ty);
+ Line, Ty, false, llvm::DINode::FlagZero, Align);
// Insert an llvm.dbg.declare into the current block.
auto DL = llvm::DebugLoc::get(Line, Column, LexicalBlockStack.back());
@@ -3438,17 +3618,19 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
llvm::DIType *fieldType;
if (capture->isByRef()) {
TypeInfo PtrInfo = C.getTypeInfo(C.VoidPtrTy);
+ auto Align = PtrInfo.AlignIsRequired ? PtrInfo.Align : 0;
// FIXME: this creates a second copy of this type!
uint64_t xoffset;
fieldType = EmitTypeForVarWithBlocksAttr(variable, &xoffset);
fieldType = DBuilder.createPointerType(fieldType, PtrInfo.Width);
- fieldType =
- DBuilder.createMemberType(tunit, name, tunit, line, PtrInfo.Width,
- PtrInfo.Align, offsetInBits, 0, fieldType);
+ fieldType = DBuilder.createMemberType(tunit, name, tunit, line,
+ PtrInfo.Width, Align, offsetInBits,
+ llvm::DINode::FlagZero, fieldType);
} else {
+ auto Align = getDeclAlignIfRequired(variable, CGM.getContext());
fieldType = createFieldType(name, variable->getType(), loc, AS_public,
- offsetInBits, tunit, tunit);
+ offsetInBits, Align, tunit, tunit);
}
fields.push_back(fieldType);
}
@@ -3459,14 +3641,14 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
llvm::DINodeArray fieldsArray = DBuilder.getOrCreateArray(fields);
- llvm::DIType *type = DBuilder.createStructType(
- tunit, typeName.str(), tunit, line,
- CGM.getContext().toBits(block.BlockSize),
- CGM.getContext().toBits(block.BlockAlign), 0, nullptr, fieldsArray);
+ llvm::DIType *type =
+ DBuilder.createStructType(tunit, typeName.str(), tunit, line,
+ CGM.getContext().toBits(block.BlockSize), 0,
+ llvm::DINode::FlagZero, nullptr, fieldsArray);
type = DBuilder.createPointerType(type, CGM.PointerWidthInBits);
// Get overall information about the block.
- unsigned flags = llvm::DINode::FlagArtificial;
+ llvm::DINode::DIFlags flags = llvm::DINode::FlagArtificial;
auto *scope = cast<llvm::DILocalScope>(LexicalBlockStack.back());
// Create the descriptor for the parameter.
@@ -3505,10 +3687,10 @@ CGDebugInfo::getOrCreateStaticDataMemberDeclarationOrNull(const VarDecl *D) {
return CreateRecordStaticField(D, Ctxt, cast<RecordDecl>(DC));
}
-llvm::DIGlobalVariable *CGDebugInfo::CollectAnonRecordDecls(
+llvm::DIGlobalVariableExpression *CGDebugInfo::CollectAnonRecordDecls(
const RecordDecl *RD, llvm::DIFile *Unit, unsigned LineNo,
StringRef LinkageName, llvm::GlobalVariable *Var, llvm::DIScope *DContext) {
- llvm::DIGlobalVariable *GV = nullptr;
+ llvm::DIGlobalVariableExpression *GVE = nullptr;
for (const auto *Field : RD->fields()) {
llvm::DIType *FieldTy = getOrCreateType(Field->getType(), Unit);
@@ -3517,16 +3699,17 @@ llvm::DIGlobalVariable *CGDebugInfo::CollectAnonRecordDecls(
// Ignore unnamed fields, but recurse into anonymous records.
if (FieldName.empty()) {
if (const auto *RT = dyn_cast<RecordType>(Field->getType()))
- GV = CollectAnonRecordDecls(RT->getDecl(), Unit, LineNo, LinkageName,
+ GVE = CollectAnonRecordDecls(RT->getDecl(), Unit, LineNo, LinkageName,
Var, DContext);
continue;
}
// Use VarDecl's Tag, Scope and Line number.
- GV = DBuilder.createGlobalVariable(DContext, FieldName, LinkageName, Unit,
- LineNo, FieldTy,
- Var->hasLocalLinkage(), Var, nullptr);
+ GVE = DBuilder.createGlobalVariableExpression(
+ DContext, FieldName, LinkageName, Unit, LineNo, FieldTy,
+ Var->hasLocalLinkage());
+ Var->addDebugInfo(GVE);
}
- return GV;
+ return GVE;
}
void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
@@ -3534,6 +3717,14 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
assert(DebugKind >= codegenoptions::LimitedDebugInfo);
if (D->hasAttr<NoDebugAttr>())
return;
+
+ // If we already created a DIGlobalVariable for this declaration, just attach
+ // it to the llvm::GlobalVariable.
+ auto Cached = DeclCache.find(D->getCanonicalDecl());
+ if (Cached != DeclCache.end())
+ return Var->addDebugInfo(
+ cast<llvm::DIGlobalVariableExpression>(Cached->second));
+
// Create global variable debug descriptor.
llvm::DIFile *Unit = nullptr;
llvm::DIScope *DContext = nullptr;
@@ -3544,7 +3735,7 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
// Attempt to store one global variable for the declaration - even if we
// emit a lot of fields.
- llvm::DIGlobalVariable *GV = nullptr;
+ llvm::DIGlobalVariableExpression *GVE = nullptr;
// If this is an anonymous union then we'll want to emit a global
// variable for each member of the anonymous union so that it's possible
@@ -3553,21 +3744,23 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
const RecordDecl *RD = T->castAs<RecordType>()->getDecl();
assert(RD->isAnonymousStructOrUnion() &&
"unnamed non-anonymous struct or union?");
- GV = CollectAnonRecordDecls(RD, Unit, LineNo, LinkageName, Var, DContext);
+ GVE = CollectAnonRecordDecls(RD, Unit, LineNo, LinkageName, Var, DContext);
} else {
- GV = DBuilder.createGlobalVariable(
+ auto Align = getDeclAlignIfRequired(D, CGM.getContext());
+ GVE = DBuilder.createGlobalVariableExpression(
DContext, DeclName, LinkageName, Unit, LineNo, getOrCreateType(T, Unit),
- Var->hasLocalLinkage(), Var,
- getOrCreateStaticDataMemberDeclarationOrNull(D));
+ Var->hasLocalLinkage(), /*Expr=*/nullptr,
+ getOrCreateStaticDataMemberDeclarationOrNull(D), Align);
+ Var->addDebugInfo(GVE);
}
- DeclCache[D->getCanonicalDecl()].reset(GV);
+ DeclCache[D->getCanonicalDecl()].reset(GVE);
}
-void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD,
- llvm::Constant *Init) {
+void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD, const APValue &Init) {
assert(DebugKind >= codegenoptions::LimitedDebugInfo);
if (VD->hasAttr<NoDebugAttr>())
return;
+ auto Align = getDeclAlignIfRequired(VD, CGM.getContext());
// Create the descriptor for the variable.
llvm::DIFile *Unit = getOrCreateFile(VD->getLocation());
StringRef Name = VD->getName();
@@ -3604,9 +3797,20 @@ void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD,
auto &GV = DeclCache[VD];
if (GV)
return;
- GV.reset(DBuilder.createGlobalVariable(
+ llvm::DIExpression *InitExpr = nullptr;
+ if (CGM.getContext().getTypeSize(VD->getType()) <= 64) {
+ // FIXME: Add a representation for integer constants wider than 64 bits.
+ if (Init.isInt())
+ InitExpr =
+ DBuilder.createConstantValueExpression(Init.getInt().getExtValue());
+ else if (Init.isFloat())
+ InitExpr = DBuilder.createConstantValueExpression(
+ Init.getFloat().bitcastToAPInt().getZExtValue());
+ }
+ GV.reset(DBuilder.createGlobalVariableExpression(
DContext, Name, StringRef(), Unit, getLineNumber(VD->getLocation()), Ty,
- true, Init, getOrCreateStaticDataMemberDeclarationOrNull(VarD)));
+ true, InitExpr, getOrCreateStaticDataMemberDeclarationOrNull(VarD),
+ Align));
}
llvm::DIScope *CGDebugInfo::getCurrentContextDescriptor(const Decl *D) {
@@ -3620,8 +3824,8 @@ void CGDebugInfo::EmitUsingDirective(const UsingDirectiveDecl &UD) {
if (CGM.getCodeGenOpts().getDebugInfo() < codegenoptions::LimitedDebugInfo)
return;
const NamespaceDecl *NSDecl = UD.getNominatedNamespace();
- if (!NSDecl->isAnonymousNamespace() ||
- CGM.getCodeGenOpts().DebugExplicitImport) {
+ if (!NSDecl->isAnonymousNamespace() ||
+ CGM.getCodeGenOpts().DebugExplicitImport) {
DBuilder.createImportedModule(
getCurrentContextDescriptor(cast<Decl>(UD.getDeclContext())),
getOrCreateNameSpace(NSDecl),
@@ -3700,8 +3904,8 @@ CGDebugInfo::getOrCreateNameSpace(const NamespaceDecl *NSDecl) {
unsigned LineNo = getLineNumber(NSDecl->getLocation());
llvm::DIFile *FileD = getOrCreateFile(NSDecl->getLocation());
llvm::DIScope *Context = getDeclContextDescriptor(NSDecl);
- llvm::DINamespace *NS =
- DBuilder.createNameSpace(Context, NSDecl->getName(), FileD, LineNo);
+ llvm::DINamespace *NS = DBuilder.createNameSpace(
+ Context, NSDecl->getName(), FileD, LineNo, NSDecl->isInline());
NameSpaceCache[NSDecl].reset(NS);
return NS;
}
@@ -3750,6 +3954,8 @@ void CGDebugInfo::finalize() {
else
Repl = it->second;
+ if (auto *GVE = dyn_cast_or_null<llvm::DIGlobalVariableExpression>(Repl))
+ Repl = GVE->getVariable();
DBuilder.replaceTemporary(std::move(FwdDecl), cast<llvm::MDNode>(Repl));
}
@@ -3770,3 +3976,12 @@ void CGDebugInfo::EmitExplicitCastType(QualType Ty) {
// Don't ignore in case of explicit cast where it is referenced indirectly.
DBuilder.retainType(DieTy);
}
+
+llvm::DebugLoc CGDebugInfo::SourceLocToDebugLoc(SourceLocation Loc) {
+ if (LexicalBlockStack.empty())
+ return llvm::DebugLoc();
+
+ llvm::MDNode *Scope = LexicalBlockStack.back();
+ return llvm::DebugLoc::get(
+ getLineNumber(Loc), getColumnNumber(Loc), Scope);
+}
diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h
index 366dd81ac812..ac2e8dd2e0a4 100644
--- a/lib/CodeGen/CGDebugInfo.h
+++ b/lib/CodeGen/CGDebugInfo.h
@@ -15,12 +15,14 @@
#define LLVM_CLANG_LIB_CODEGEN_CGDEBUGINFO_H
#include "CGBuilder.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/Type.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/Optional.h"
#include "llvm/IR/DIBuilder.h"
#include "llvm/IR/DebugInfo.h"
@@ -32,7 +34,6 @@ class MDNode;
}
namespace clang {
-class CXXMethodDecl;
class ClassTemplateSpecializationDecl;
class GlobalDecl;
class ModuleMap;
@@ -67,6 +68,7 @@ class CGDebugInfo {
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
llvm::DIType *SingletonId = nullptr;
#include "clang/Basic/OpenCLImageTypes.def"
+ llvm::DIType *OCLSamplerDITy = nullptr;
llvm::DIType *OCLEventDITy = nullptr;
llvm::DIType *OCLClkEventDITy = nullptr;
llvm::DIType *OCLQueueDITy = nullptr;
@@ -96,8 +98,7 @@ class CGDebugInfo {
/// List of interfaces we want to keep even if orphaned.
std::vector<void *> RetainedTypes;
- /// Cache of forward declared types to RAUW at the end of
- /// compilation.
+ /// Cache of forward declared types to RAUW at the end of compilation.
std::vector<std::pair<const TagType *, llvm::TrackingMDRef>> ReplaceMap;
/// Cache of replaceable forward declarations (functions and
@@ -155,6 +156,8 @@ class CGDebugInfo {
llvm::DIFile *F);
/// Get Objective-C object type.
llvm::DIType *CreateType(const ObjCObjectType *Ty, llvm::DIFile *F);
+ llvm::DIType *CreateType(const ObjCTypeParamType *Ty, llvm::DIFile *Unit);
+
llvm::DIType *CreateType(const VectorType *Ty, llvm::DIFile *F);
llvm::DIType *CreateType(const ArrayType *Ty, llvm::DIFile *F);
llvm::DIType *CreateType(const LValueReferenceType *Ty, llvm::DIFile *F);
@@ -216,6 +219,15 @@ class CGDebugInfo {
SmallVectorImpl<llvm::Metadata *> &EltTys,
llvm::DIType *RecordTy);
+ /// 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);
+
/// A helper function to collect template parameters.
llvm::DINodeArray CollectTemplateParams(const TemplateParameterList *TPList,
ArrayRef<TemplateArgument> TAList,
@@ -233,9 +245,19 @@ class CGDebugInfo {
llvm::DIType *createFieldType(StringRef name, QualType type,
SourceLocation loc, AccessSpecifier AS,
+ uint64_t offsetInBits,
+ uint32_t AlignInBits,
+ llvm::DIFile *tunit, llvm::DIScope *scope,
+ const RecordDecl *RD = nullptr);
+
+ llvm::DIType *createFieldType(StringRef name, QualType type,
+ SourceLocation loc, AccessSpecifier AS,
uint64_t offsetInBits, llvm::DIFile *tunit,
llvm::DIScope *scope,
- const RecordDecl *RD = nullptr);
+ const RecordDecl *RD = nullptr) {
+ return createFieldType(name, type, loc, AS, offsetInBits, 0, tunit, scope,
+ RD);
+ }
/// Create new bit field member.
llvm::DIType *createBitFieldType(const FieldDecl *BitFieldDecl,
@@ -254,6 +276,8 @@ class CGDebugInfo {
llvm::DIFile *F,
SmallVectorImpl<llvm::Metadata *> &E,
llvm::DIType *RecordTy, const RecordDecl *RD);
+ void CollectRecordNestedRecord(const RecordDecl *RD,
+ SmallVectorImpl<llvm::Metadata *> &E);
void CollectRecordFields(const RecordDecl *Decl, llvm::DIFile *F,
SmallVectorImpl<llvm::Metadata *> &E,
llvm::DICompositeType *RecordTy);
@@ -261,7 +285,8 @@ class CGDebugInfo {
/// If the C++ class has vtable info then insert appropriate debug
/// info entry in EltTys vector.
void CollectVTableInfo(const CXXRecordDecl *Decl, llvm::DIFile *F,
- SmallVectorImpl<llvm::Metadata *> &EltTys);
+ SmallVectorImpl<llvm::Metadata *> &EltTys,
+ llvm::DICompositeType *RecordTy);
/// @}
/// Create a new lexical block node and push it on the stack.
@@ -295,6 +320,9 @@ public:
/// ignored.
void setLocation(SourceLocation Loc);
+ // Converts a SourceLocation to a DebugLoc
+ llvm::DebugLoc SourceLocToDebugLoc(SourceLocation Loc);
+
/// Emit metadata to indicate a change in line/column information in
/// the source file. If the location is invalid, the previous
/// location will be reused.
@@ -350,8 +378,8 @@ public:
/// Emit information about a global variable.
void EmitGlobalVariable(llvm::GlobalVariable *GV, const VarDecl *Decl);
- /// Emit global variable's debug info.
- void EmitGlobalVariable(const ValueDecl *VD, llvm::Constant *Init);
+ /// Emit a constant global variable's debug info.
+ void EmitGlobalVariable(const ValueDecl *VD, const APValue &Init);
/// Emit C++ using directive.
void EmitUsingDirective(const UsingDirectiveDecl &UD);
@@ -414,6 +442,10 @@ private:
/// Remap a given path with the current debug prefix map
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;
+
/// Get the file debug info descriptor for the input location.
llvm::DIFile *getOrCreateFile(SourceLocation Loc);
@@ -468,14 +500,14 @@ private:
llvm::DIGlobalVariable *
getGlobalVariableForwardDeclaration(const VarDecl *VD);
- /// \brief Return a global variable that represents one of the
- /// collection of global variables created for an anonmyous union.
+ /// Return a global variable that represents one of the collection of global
+ /// variables created for an anonmyous union.
///
/// Recursively collect all of the member fields of a global
/// anonymous decl and create static variables for them. The first
/// time this is called it needs to be on a union and then from
/// there we can have additional unnamed fields.
- llvm::DIGlobalVariable *
+ llvm::DIGlobalVariableExpression *
CollectAnonRecordDecls(const RecordDecl *RD, llvm::DIFile *Unit,
unsigned LineNo, StringRef LinkageName,
llvm::GlobalVariable *Var, llvm::DIScope *DContext);
@@ -514,7 +546,7 @@ private:
StringRef &Name, StringRef &LinkageName,
llvm::DIScope *&FDContext,
llvm::DINodeArray &TParamsArray,
- unsigned &Flags);
+ llvm::DINode::DIFlags &Flags);
/// Collect various properties of a VarDecl.
void collectVarDeclProps(const VarDecl *VD, llvm::DIFile *&Unit,
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index 89407cd70c3d..d76136380160 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -13,6 +13,7 @@
#include "CodeGenFunction.h"
#include "CGBlocks.h"
+#include "CGCXXABI.h"
#include "CGCleanup.h"
#include "CGDebugInfo.h"
#include "CGOpenCLRuntime.h"
@@ -77,6 +78,7 @@ void CodeGenFunction::EmitDecl(const Decl &D) {
case Decl::PragmaDetectMismatch:
case Decl::AccessSpec:
case Decl::LinkageSpec:
+ case Decl::Export:
case Decl::ObjCPropertyImpl:
case Decl::FileScopeAsm:
case Decl::Friend:
@@ -87,6 +89,7 @@ void CodeGenFunction::EmitDecl(const Decl &D) {
case Decl::UsingShadow:
case Decl::ConstructorUsingShadow:
case Decl::ObjCTypeParam:
+ case Decl::Binding:
llvm_unreachable("Declaration should not be in declstmts!");
case Decl::Function: // void X();
case Decl::Record: // struct/union/class X;
@@ -110,15 +113,25 @@ void CodeGenFunction::EmitDecl(const Decl &D) {
if (CGDebugInfo *DI = getDebugInfo())
DI->EmitUsingDecl(cast<UsingDecl>(D));
return;
+ case Decl::UsingPack:
+ for (auto *Using : cast<UsingPackDecl>(D).expansions())
+ EmitDecl(*Using);
+ return;
case Decl::UsingDirective: // using namespace X; [C++]
if (CGDebugInfo *DI = getDebugInfo())
DI->EmitUsingDirective(cast<UsingDirectiveDecl>(D));
return;
- case Decl::Var: {
+ case Decl::Var:
+ case Decl::Decomposition: {
const VarDecl &VD = cast<VarDecl>(D);
assert(VD.isLocalVarDecl() &&
"Should not see file-scope variables inside a function!");
- return EmitVarDecl(VD);
+ EmitVarDecl(VD);
+ if (auto *DD = dyn_cast<DecompositionDecl>(&VD))
+ for (auto *B : DD->bindings())
+ if (auto *HD = B->getHoldingVar())
+ EmitVarDecl(*HD);
+ return;
}
case Decl::OMPDeclareReduction:
@@ -526,7 +539,8 @@ namespace {
CallArgList Args;
Args.add(RValue::get(Arg),
CGF.getContext().getPointerType(Var.getType()));
- CGF.EmitCall(FnInfo, CleanupFn, ReturnValueSlot(), Args);
+ auto Callee = CGCallee::forDirect(CleanupFn);
+ CGF.EmitCall(FnInfo, Callee, ReturnValueSlot(), Args);
}
};
} // end anonymous namespace
@@ -698,7 +712,7 @@ void CodeGenFunction::EmitScalarInit(const Expr *init, const ValueDecl *D,
}
auto ty = cast<llvm::PointerType>(tempLV.getAddress().getElementType());
- llvm::Value *zero = llvm::ConstantPointerNull::get(ty);
+ llvm::Value *zero = CGM.getNullPointer(ty, tempLV.getType());
// If __weak, we want to use a barrier under certain conditions.
if (lifetime == Qualifiers::OCL_Weak)
@@ -765,37 +779,6 @@ void CodeGenFunction::EmitScalarInit(const Expr *init, const ValueDecl *D,
EmitStoreOfScalar(value, lvalue, /* isInitialization */ true);
}
-/// EmitScalarInit - Initialize the given lvalue with the given object.
-void CodeGenFunction::EmitScalarInit(llvm::Value *init, LValue lvalue) {
- Qualifiers::ObjCLifetime lifetime = lvalue.getObjCLifetime();
- if (!lifetime)
- return EmitStoreThroughLValue(RValue::get(init), lvalue, true);
-
- switch (lifetime) {
- case Qualifiers::OCL_None:
- llvm_unreachable("present but none");
-
- case Qualifiers::OCL_ExplicitNone:
- // nothing to do
- break;
-
- case Qualifiers::OCL_Strong:
- init = EmitARCRetain(lvalue.getType(), init);
- break;
-
- case Qualifiers::OCL_Weak:
- // Initialize and then skip the primitive store.
- EmitARCInitWeak(lvalue.getAddress(), init);
- return;
-
- case Qualifiers::OCL_Autoreleasing:
- init = EmitARCRetainAutorelease(lvalue.getType(), init);
- break;
- }
-
- EmitStoreOfScalar(init, 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.
@@ -907,29 +890,12 @@ void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D) {
EmitAutoVarCleanups(emission);
}
-/// shouldEmitLifetimeMarkers - Decide whether we need emit the life-time
-/// markers.
-static bool shouldEmitLifetimeMarkers(const CodeGenOptions &CGOpts,
- const LangOptions &LangOpts) {
- // Asan uses markers for use-after-scope checks.
- if (CGOpts.SanitizeAddressUseAfterScope)
- return true;
-
- // Disable lifetime markers in msan builds.
- // FIXME: Remove this when msan works with lifetime markers.
- if (LangOpts.Sanitize.has(SanitizerKind::Memory))
- return false;
-
- // For now, only in optimized builds.
- return CGOpts.OptimizationLevel != 0;
-}
-
/// Emit a lifetime.begin marker if some criteria are satisfied.
/// \return a pointer to the temporary size Value if a marker was emitted, null
/// otherwise
llvm::Value *CodeGenFunction::EmitLifetimeStart(uint64_t Size,
llvm::Value *Addr) {
- if (!shouldEmitLifetimeMarkers(CGM.getCodeGenOpts(), getLangOpts()))
+ if (!ShouldEmitLifetimeMarkers)
return nullptr;
llvm::Value *SizeV = llvm::ConstantInt::get(Int64Ty, Size);
@@ -986,8 +952,12 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
// If the variable's a const type, and it's neither an NRVO
// candidate nor a __block variable and has no mutable members,
// emit it as a global instead.
- if (CGM.getCodeGenOpts().MergeAllConstants && !NRVO && !isByRef &&
- CGM.isTypeConstant(Ty, true)) {
+ // Exception is if a variable is located in non-constant address space
+ // in OpenCL.
+ if ((!getLangOpts().OpenCL ||
+ Ty.getAddressSpace() == LangAS::opencl_constant) &&
+ (CGM.getCodeGenOpts().MergeAllConstants && !NRVO && !isByRef &&
+ CGM.isTypeConstant(Ty, true))) {
EmitStaticVarDecl(D, llvm::GlobalValue::InternalLinkage);
// Signal this condition to later callbacks.
@@ -1049,12 +1019,18 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
bool IsMSCatchParam =
D.isExceptionVariable() && getTarget().getCXXABI().isMicrosoft();
- // Emit a lifetime intrinsic if meaningful. There's no point
- // in doing this if we don't have a valid insertion point (?).
+ // Emit a lifetime intrinsic if meaningful. There's no point in doing this
+ // if we don't have a valid insertion point (?).
if (HaveInsertPoint() && !IsMSCatchParam) {
- uint64_t size = CGM.getDataLayout().getTypeAllocSize(allocaTy);
- emission.SizeForLifetimeMarkers =
- EmitLifetimeStart(size, address.getPointer());
+ // goto or switch-case statements can break lifetime into several
+ // regions which need more efforts to handle them correctly. PR28267
+ // This is rare case, but it's better just omit intrinsics than have
+ // them incorrectly placed.
+ if (!Bypasses.IsBypassed(&D)) {
+ uint64_t size = CGM.getDataLayout().getTypeAllocSize(allocaTy);
+ emission.SizeForLifetimeMarkers =
+ EmitLifetimeStart(size, address.getPointer());
+ }
} else {
assert(!emission.useLifetimeMarkers());
}
@@ -1257,10 +1233,16 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
// 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);
+ }
llvm::GlobalVariable *GV =
new llvm::GlobalVariable(CGM.getModule(), constant->getType(), true,
llvm::GlobalValue::PrivateLinkage,
- constant, Name);
+ constant, Name, nullptr,
+ llvm::GlobalValue::NotThreadLocal, AS);
GV->setAlignment(Loc.getAlignment().getQuantity());
GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
@@ -1762,6 +1744,24 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, ParamValue Arg,
setBlockContextParameter(IPD, ArgNo, Arg.getDirectValue());
return;
}
+
+ // Apply any prologue 'this' adjustments required by the ABI. Be careful to
+ // handle the case where 'this' is passed indirectly as part of an inalloca
+ // struct.
+ if (const CXXMethodDecl *MD =
+ dyn_cast_or_null<CXXMethodDecl>(CurCodeDecl)) {
+ if (MD->isVirtual() && IPD == CXXABIThisDecl) {
+ llvm::Value *This = Arg.isIndirect()
+ ? Builder.CreateLoad(Arg.getIndirectAddress())
+ : Arg.getDirectValue();
+ This = CGM.getCXXABI().adjustThisParameterInVirtualFunctionPrologue(
+ *this, CurGD, This);
+ if (Arg.isIndirect())
+ Builder.CreateStore(This, Arg.getIndirectAddress());
+ else
+ Arg = ParamValue::forDirect(This);
+ }
+ }
}
Address DeclPtr = Address::invalid();
diff --git a/lib/CodeGen/CGDeclCXX.cpp b/lib/CodeGen/CGDeclCXX.cpp
index 89d142e44b49..8d9d0b21bfe1 100644
--- a/lib/CodeGen/CGDeclCXX.cpp
+++ b/lib/CodeGen/CGDeclCXX.cpp
@@ -121,13 +121,15 @@ static void EmitDeclDestroy(CodeGenFunction &CGF, const VarDecl &D,
/// constant from this point onwards.
static void EmitDeclInvariant(CodeGenFunction &CGF, const VarDecl &D,
llvm::Constant *Addr) {
- // Don't emit the intrinsic if we're not optimizing.
+ // Do not emit the intrinsic if we're not optimizing.
if (!CGF.CGM.getCodeGenOpts().OptimizationLevel)
return;
// Grab the llvm.invariant.start intrinsic.
llvm::Intrinsic::ID InvStartID = llvm::Intrinsic::invariant_start;
- llvm::Constant *InvariantStart = CGF.CGM.getIntrinsic(InvStartID);
+ // Overloaded address space type.
+ llvm::Type *ObjectPtr[1] = {CGF.Int8PtrTy};
+ llvm::Constant *InvariantStart = CGF.CGM.getIntrinsic(InvStartID, ObjectPtr);
// Emit a call with the size in bytes of the object.
CharUnits WidthChars = CGF.getContext().getTypeSizeInChars(D.getType());
@@ -235,7 +237,8 @@ void CodeGenFunction::registerGlobalDtorWithAtExit(const VarDecl &VD,
llvm::FunctionType::get(IntTy, dtorStub->getType(), false);
llvm::Constant *atexit =
- CGM.CreateRuntimeFunction(atexitTy, "atexit");
+ CGM.CreateRuntimeFunction(atexitTy, "atexit", llvm::AttributeSet(),
+ /*Local=*/true);
if (llvm::Function *atexitFn = dyn_cast<llvm::Function>(atexit))
atexitFn->setDoesNotThrow();
diff --git a/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp
index 4a7dc4205e09..7b7880e07a95 100644
--- a/lib/CodeGen/CGException.cpp
+++ b/lib/CodeGen/CGException.cpp
@@ -221,10 +221,9 @@ const EHPersonality &EHPersonality::get(CodeGenFunction &CGF) {
static llvm::Constant *getPersonalityFn(CodeGenModule &CGM,
const EHPersonality &Personality) {
- llvm::Constant *Fn =
- CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.Int32Ty, true),
- Personality.PersonalityFn);
- return Fn;
+ return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.Int32Ty, true),
+ Personality.PersonalityFn,
+ llvm::AttributeSet(), /*Local=*/true);
}
static llvm::Constant *getOpaquePersonalityFn(CodeGenModule &CGM,
@@ -698,6 +697,10 @@ llvm::BasicBlock *CodeGenFunction::getInvokeDestImpl() {
return nullptr;
}
+ // CUDA device code doesn't have exceptions.
+ if (LO.CUDA && LO.CUDAIsDevice)
+ return nullptr;
+
// Check the innermost scope for a cached landing pad. If this is
// a non-EH cleanup, we'll check enclosing scopes in EmitLandingPad.
llvm::BasicBlock *LP = EHStack.begin()->getCachedLandingPad();
@@ -1429,7 +1432,8 @@ struct PerformSEHFinally final : EHScopeStack::Cleanup {
const CGFunctionInfo &FnInfo =
CGM.getTypes().arrangeBuiltinFunctionCall(Context.VoidTy, Args);
- CGF.EmitCall(FnInfo, OutlinedFinally, ReturnValueSlot(), Args);
+ auto Callee = CGCallee::forDirect(OutlinedFinally);
+ CGF.EmitCall(FnInfo, Callee, ReturnValueSlot(), Args);
}
};
} // end anonymous namespace
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index 5f3b290d8eb1..183201c78e36 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -24,6 +24,7 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
#include "clang/AST/DeclObjC.h"
+#include "clang/AST/NSAPI.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/StringExtras.h"
@@ -36,6 +37,8 @@
#include "llvm/Support/Path.h"
#include "llvm/Transforms/Utils/SanitizerStats.h"
+#include <string>
+
using namespace clang;
using namespace CodeGen;
@@ -607,7 +610,7 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
llvm::ConstantInt::get(SizeTy, AlignVal),
llvm::ConstantInt::get(Int8Ty, TCK)
};
- EmitCheck(Checks, "type_mismatch", StaticData, Ptr);
+ EmitCheck(Checks, SanitizerHandler::TypeMismatch, StaticData, Ptr);
}
// If possible, check that the vptr indicates that there is a subobject of
@@ -675,7 +678,8 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
};
llvm::Value *DynamicData[] = { Ptr, Hash };
EmitCheck(std::make_pair(EqualHash, SanitizerKind::Vptr),
- "dynamic_type_cache_miss", StaticData, DynamicData);
+ SanitizerHandler::DynamicTypeCacheMiss, StaticData,
+ DynamicData);
}
}
@@ -708,6 +712,8 @@ static bool isFlexibleArrayMemberExpr(const Expr *E) {
DeclContext::decl_iterator(const_cast<FieldDecl *>(FD)));
return ++FI == FD->getParent()->field_end();
}
+ } else if (const auto *IRE = dyn_cast<ObjCIvarRefExpr>(E)) {
+ return IRE->getDecl()->getNextIvar() == nullptr;
}
return false;
@@ -763,8 +769,8 @@ void CodeGenFunction::EmitBoundsCheck(const Expr *E, const Expr *Base,
};
llvm::Value *Check = Accessed ? Builder.CreateICmpULT(IndexVal, BoundVal)
: Builder.CreateICmpULE(IndexVal, BoundVal);
- EmitCheck(std::make_pair(Check, SanitizerKind::ArrayBounds), "out_of_bounds",
- StaticData, Index);
+ EmitCheck(std::make_pair(Check, SanitizerKind::ArrayBounds),
+ SanitizerHandler::OutOfBounds, StaticData, Index);
}
@@ -1180,10 +1186,10 @@ CodeGenFunction::tryEmitAsConstant(DeclRefExpr *refExpr) {
// This should probably fire even for
if (isa<VarDecl>(value)) {
if (!getContext().DeclMustBeEmitted(cast<VarDecl>(value)))
- EmitDeclRefExprDbgValue(refExpr, C);
+ EmitDeclRefExprDbgValue(refExpr, result.Val);
} else {
assert(isa<EnumConstantDecl>(value));
- EmitDeclRefExprDbgValue(refExpr, C);
+ EmitDeclRefExprDbgValue(refExpr, result.Val);
}
// If we emitted a reference constant, we need to dereference that.
@@ -1217,11 +1223,10 @@ static bool hasBooleanRepresentation(QualType Ty) {
static bool getRangeForType(CodeGenFunction &CGF, QualType Ty,
llvm::APInt &Min, llvm::APInt &End,
- bool StrictEnums) {
+ bool StrictEnums, bool IsBool) {
const EnumType *ET = Ty->getAs<EnumType>();
bool IsRegularCPlusPlusEnum = CGF.getLangOpts().CPlusPlus && StrictEnums &&
ET && !ET->getDecl()->isFixed();
- bool IsBool = hasBooleanRepresentation(Ty);
if (!IsBool && !IsRegularCPlusPlusEnum)
return false;
@@ -1251,8 +1256,8 @@ static bool getRangeForType(CodeGenFunction &CGF, QualType Ty,
llvm::MDNode *CodeGenFunction::getRangeForLoadFromType(QualType Ty) {
llvm::APInt Min, End;
- if (!getRangeForType(*this, Ty, Min, End,
- CGM.getCodeGenOpts().StrictEnums))
+ if (!getRangeForType(*this, Ty, Min, End, CGM.getCodeGenOpts().StrictEnums,
+ hasBooleanRepresentation(Ty)))
return nullptr;
llvm::MDBuilder MDHelper(getLLVMContext());
@@ -1311,14 +1316,15 @@ llvm::Value *CodeGenFunction::EmitLoadOfScalar(Address Addr, bool Volatile,
false /*ConvertTypeToTag*/);
}
- bool NeedsBoolCheck =
- SanOpts.has(SanitizerKind::Bool) && hasBooleanRepresentation(Ty);
+ bool IsBool = hasBooleanRepresentation(Ty) ||
+ NSAPI(CGM.getContext()).isObjCBOOLType(Ty);
+ bool NeedsBoolCheck = SanOpts.has(SanitizerKind::Bool) && IsBool;
bool NeedsEnumCheck =
SanOpts.has(SanitizerKind::Enum) && Ty->getAs<EnumType>();
if (NeedsBoolCheck || NeedsEnumCheck) {
SanitizerScope SanScope(this);
llvm::APInt Min, End;
- if (getRangeForType(*this, Ty, Min, End, true)) {
+ if (getRangeForType(*this, Ty, Min, End, /*StrictEnums=*/true, IsBool)) {
--End;
llvm::Value *Check;
if (!Min)
@@ -1336,8 +1342,8 @@ llvm::Value *CodeGenFunction::EmitLoadOfScalar(Address Addr, bool Volatile,
EmitCheckTypeDescriptor(Ty)
};
SanitizerMask Kind = NeedsEnumCheck ? SanitizerKind::Enum : SanitizerKind::Bool;
- EmitCheck(std::make_pair(Check, Kind), "load_invalid_value", StaticArgs,
- EmitCheckValue(Load));
+ EmitCheck(std::make_pair(Check, Kind), SanitizerHandler::LoadInvalidValue,
+ StaticArgs, EmitCheckValue(Load));
}
} else if (CGM.getCodeGenOpts().OptimizationLevel > 0)
if (llvm::MDNode *RangeInfo = getRangeForLoadFromType(Ty))
@@ -1627,11 +1633,19 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst,
break;
case Qualifiers::OCL_Strong:
+ if (isInit) {
+ Src = RValue::get(EmitARCRetain(Dst.getType(), Src.getScalarVal()));
+ break;
+ }
EmitARCStoreStrong(Dst, Src.getScalarVal(), /*ignore*/ true);
return;
case Qualifiers::OCL_Weak:
- EmitARCStoreWeak(Dst.getAddress(), Src.getScalarVal(), /*ignore*/ true);
+ if (isInit)
+ // Initialize and then skip the primitive store.
+ EmitARCInitWeak(Dst.getAddress(), Src.getScalarVal());
+ else
+ EmitARCStoreWeak(Dst.getAddress(), Src.getScalarVal(), /*ignore*/ true);
return;
case Qualifiers::OCL_Autoreleasing:
@@ -2015,9 +2029,14 @@ static LValue EmitGlobalVarDeclLValue(CodeGenFunction &CGF,
return LV;
}
-static LValue EmitFunctionDeclLValue(CodeGenFunction &CGF,
- const Expr *E, const FunctionDecl *FD) {
- llvm::Value *V = CGF.CGM.GetAddrOfFunction(FD);
+static llvm::Constant *EmitFunctionDeclPointer(CodeGenModule &CGM,
+ const FunctionDecl *FD) {
+ if (FD->hasAttr<WeakRefAttr>()) {
+ ConstantAddress aliasee = CGM.GetWeakRefReference(FD);
+ return aliasee.getPointer();
+ }
+
+ llvm::Constant *V = CGM.GetAddrOfFunction(FD);
if (!FD->hasPrototype()) {
if (const FunctionProtoType *Proto =
FD->getType()->getAs<FunctionProtoType>()) {
@@ -2025,11 +2044,18 @@ static LValue EmitFunctionDeclLValue(CodeGenFunction &CGF,
// isn't the same as the type of a use. Correct for this with a
// bitcast.
QualType NoProtoType =
- CGF.getContext().getFunctionNoProtoType(Proto->getReturnType());
- NoProtoType = CGF.getContext().getPointerType(NoProtoType);
- V = CGF.Builder.CreateBitCast(V, CGF.ConvertType(NoProtoType));
+ CGM.getContext().getFunctionNoProtoType(Proto->getReturnType());
+ NoProtoType = CGM.getContext().getPointerType(NoProtoType);
+ V = llvm::ConstantExpr::getBitCast(V,
+ CGM.getTypes().ConvertType(NoProtoType));
}
}
+ return V;
+}
+
+static LValue EmitFunctionDeclLValue(CodeGenFunction &CGF,
+ const Expr *E, const FunctionDecl *FD) {
+ llvm::Value *V = EmitFunctionDeclPointer(CGF.CGM, FD);
CharUnits Alignment = CGF.getContext().getDeclAlign(FD);
return CGF.MakeAddrLValue(V, E->getType(), Alignment, AlignmentSource::Decl);
}
@@ -2205,6 +2231,12 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
if (const auto *FD = dyn_cast<FunctionDecl>(ND))
return EmitFunctionDeclLValue(*this, E, FD);
+ // FIXME: While we're emitting a binding from an enclosing scope, all other
+ // DeclRefExprs we see should be implicitly treated as if they also refer to
+ // an enclosing scope.
+ if (const auto *BD = dyn_cast<BindingDecl>(ND))
+ return EmitLValue(BD->getBinding());
+
llvm_unreachable("Unhandled DeclRefExpr");
}
@@ -2291,9 +2323,19 @@ LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) {
StringRef NameItems[] = {
PredefinedExpr::getIdentTypeName(E->getIdentType()), FnName};
std::string GVName = llvm::join(NameItems, NameItems + 2, ".");
- if (CurCodeDecl && isa<BlockDecl>(CurCodeDecl)) {
- auto C = CGM.GetAddrOfConstantCString(FnName, GVName.c_str());
- return MakeAddrLValue(C, E->getType(), AlignmentSource::Decl);
+ if (auto *BD = dyn_cast<BlockDecl>(CurCodeDecl)) {
+ std::string Name = SL->getString();
+ if (!Name.empty()) {
+ unsigned Discriminator =
+ CGM.getCXXABI().getMangleContext().getBlockId(BD, true);
+ if (Discriminator)
+ Name += "_" + Twine(Discriminator + 1).str();
+ auto C = CGM.GetAddrOfConstantCString(Name, GVName.c_str());
+ return MakeAddrLValue(C, E->getType(), AlignmentSource::Decl);
+ } else {
+ auto C = CGM.GetAddrOfConstantCString(FnName, GVName.c_str());
+ return MakeAddrLValue(C, E->getType(), AlignmentSource::Decl);
+ }
}
auto C = CGM.GetAddrOfConstantStringFromLiteral(SL, GVName);
return MakeAddrLValue(C, E->getType(), AlignmentSource::Decl);
@@ -2461,17 +2503,35 @@ static CheckRecoverableKind getRecoverableKind(SanitizerMask Kind) {
}
}
+namespace {
+struct SanitizerHandlerInfo {
+ char const *const Name;
+ unsigned Version;
+};
+}
+
+const SanitizerHandlerInfo SanitizerHandlers[] = {
+#define SANITIZER_CHECK(Enum, Name, Version) {#Name, Version},
+ LIST_SANITIZER_CHECKS
+#undef SANITIZER_CHECK
+};
+
static void emitCheckHandlerCall(CodeGenFunction &CGF,
llvm::FunctionType *FnType,
ArrayRef<llvm::Value *> FnArgs,
- StringRef CheckName,
+ SanitizerHandler CheckHandler,
CheckRecoverableKind RecoverKind, bool IsFatal,
llvm::BasicBlock *ContBB) {
assert(IsFatal || RecoverKind != CheckRecoverableKind::Unrecoverable);
bool NeedsAbortSuffix =
IsFatal && RecoverKind != CheckRecoverableKind::Unrecoverable;
- std::string FnName = ("__ubsan_handle_" + CheckName +
- (NeedsAbortSuffix ? "_abort" : "")).str();
+ const SanitizerHandlerInfo &CheckInfo = SanitizerHandlers[CheckHandler];
+ const StringRef CheckName = CheckInfo.Name;
+ std::string FnName =
+ ("__ubsan_handle_" + CheckName +
+ (CheckInfo.Version ? "_v" + llvm::utostr(CheckInfo.Version) : "") +
+ (NeedsAbortSuffix ? "_abort" : ""))
+ .str();
bool MayReturn =
!IsFatal || RecoverKind == CheckRecoverableKind::AlwaysRecoverable;
@@ -2485,7 +2545,8 @@ static void emitCheckHandlerCall(CodeGenFunction &CGF,
llvm::Value *Fn = CGF.CGM.CreateRuntimeFunction(
FnType, FnName,
llvm::AttributeSet::get(CGF.getLLVMContext(),
- llvm::AttributeSet::FunctionIndex, B));
+ llvm::AttributeSet::FunctionIndex, B),
+ /*Local=*/true);
llvm::CallInst *HandlerCall = CGF.EmitNounwindRuntimeCall(Fn, FnArgs);
if (!MayReturn) {
HandlerCall->setDoesNotReturn();
@@ -2497,10 +2558,13 @@ static void emitCheckHandlerCall(CodeGenFunction &CGF,
void CodeGenFunction::EmitCheck(
ArrayRef<std::pair<llvm::Value *, SanitizerMask>> Checked,
- StringRef CheckName, ArrayRef<llvm::Constant *> StaticArgs,
+ SanitizerHandler CheckHandler, ArrayRef<llvm::Constant *> StaticArgs,
ArrayRef<llvm::Value *> DynamicArgs) {
assert(IsSanitizerScope);
assert(Checked.size() > 0);
+ assert(CheckHandler >= 0 &&
+ CheckHandler < sizeof(SanitizerHandlers) / sizeof(*SanitizerHandlers));
+ const StringRef CheckName = SanitizerHandlers[CheckHandler].Name;
llvm::Value *FatalCond = nullptr;
llvm::Value *RecoverableCond = nullptr;
@@ -2580,7 +2644,7 @@ void CodeGenFunction::EmitCheck(
if (!FatalCond || !RecoverableCond) {
// Simple case: we need to generate a single handler call, either
// fatal, or non-fatal.
- emitCheckHandlerCall(*this, FnType, Args, CheckName, RecoverKind,
+ emitCheckHandlerCall(*this, FnType, Args, CheckHandler, RecoverKind,
(FatalCond != nullptr), Cont);
} else {
// Emit two handler calls: first one for set of unrecoverable checks,
@@ -2590,10 +2654,10 @@ void CodeGenFunction::EmitCheck(
llvm::BasicBlock *FatalHandlerBB = createBasicBlock("fatal." + CheckName);
Builder.CreateCondBr(FatalCond, NonFatalHandlerBB, FatalHandlerBB);
EmitBlock(FatalHandlerBB);
- emitCheckHandlerCall(*this, FnType, Args, CheckName, RecoverKind, true,
+ emitCheckHandlerCall(*this, FnType, Args, CheckHandler, RecoverKind, true,
NonFatalHandlerBB);
EmitBlock(NonFatalHandlerBB);
- emitCheckHandlerCall(*this, FnType, Args, CheckName, RecoverKind, false,
+ emitCheckHandlerCall(*this, FnType, Args, CheckHandler, RecoverKind, false,
Cont);
}
@@ -2718,7 +2782,7 @@ void CodeGenFunction::EmitCfiCheckFail() {
llvm::Value *Cond =
Builder.CreateICmpNE(CheckKind, llvm::ConstantInt::get(Int8Ty, Kind));
if (CGM.getLangOpts().Sanitize.has(Mask))
- EmitCheck(std::make_pair(Cond, Mask), "cfi_check_fail", {},
+ EmitCheck(std::make_pair(Cond, Mask), SanitizerHandler::CFICheckFail, {},
{Data, Addr, ValidVtable});
else
EmitTrapCheck(Cond);
@@ -2753,10 +2817,11 @@ void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked) {
llvm::CallInst *CodeGenFunction::EmitTrapCall(llvm::Intrinsic::ID IntrID) {
llvm::CallInst *TrapCall = Builder.CreateCall(CGM.getIntrinsic(IntrID));
- if (!CGM.getCodeGenOpts().TrapFuncName.empty())
- TrapCall->addAttribute(llvm::AttributeSet::FunctionIndex,
- "trap-func-name",
- CGM.getCodeGenOpts().TrapFuncName);
+ if (!CGM.getCodeGenOpts().TrapFuncName.empty()) {
+ auto A = llvm::Attribute::get(getLLVMContext(), "trap-func-name",
+ CGM.getCodeGenOpts().TrapFuncName);
+ TrapCall->addAttribute(llvm::AttributeSet::FunctionIndex, A);
+ }
return TrapCall;
}
@@ -2869,13 +2934,30 @@ static Address emitArraySubscriptGEP(CodeGenFunction &CGF, Address addr,
LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
bool Accessed) {
- // The index must always be an integer, which is not an aggregate. Emit it.
- llvm::Value *Idx = EmitScalarExpr(E->getIdx());
- QualType IdxTy = E->getIdx()->getType();
- bool IdxSigned = IdxTy->isSignedIntegerOrEnumerationType();
+ // The index must always be an integer, which is not an aggregate. Emit it
+ // in lexical order (this complexity is, sadly, required by C++17).
+ llvm::Value *IdxPre =
+ (E->getLHS() == E->getIdx()) ? EmitScalarExpr(E->getIdx()) : nullptr;
+ auto EmitIdxAfterBase = [&, IdxPre](bool Promote) -> llvm::Value * {
+ auto *Idx = IdxPre;
+ if (E->getLHS() != E->getIdx()) {
+ assert(E->getRHS() == E->getIdx() && "index was neither LHS nor RHS");
+ Idx = EmitScalarExpr(E->getIdx());
+ }
+
+ QualType IdxTy = E->getIdx()->getType();
+ bool IdxSigned = IdxTy->isSignedIntegerOrEnumerationType();
- if (SanOpts.has(SanitizerKind::ArrayBounds))
- EmitBoundsCheck(E, E->getBase(), Idx, IdxTy, Accessed);
+ if (SanOpts.has(SanitizerKind::ArrayBounds))
+ EmitBoundsCheck(E, E->getBase(), Idx, IdxTy, Accessed);
+
+ // Extend or truncate the index type to 32 or 64-bits.
+ if (Promote && Idx->getType() != IntPtrTy)
+ Idx = Builder.CreateIntCast(Idx, IntPtrTy, IdxSigned, "idxprom");
+
+ return Idx;
+ };
+ IdxPre = nullptr;
// If the base is a vector type, then we are forming a vector element lvalue
// with this subscript.
@@ -2883,6 +2965,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
!isa<ExtVectorElementExpr>(E->getBase())) {
// Emit the vector as an lvalue to get its address.
LValue LHS = EmitLValue(E->getBase());
+ auto *Idx = EmitIdxAfterBase(/*Promote*/false);
assert(LHS.isSimple() && "Can only subscript lvalue vectors here!");
return LValue::MakeVectorElt(LHS.getAddress(), Idx,
E->getBase()->getType(),
@@ -2891,13 +2974,10 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
// All the other cases basically behave like simple offsetting.
- // Extend or truncate the index type to 32 or 64-bits.
- if (Idx->getType() != IntPtrTy)
- Idx = Builder.CreateIntCast(Idx, IntPtrTy, IdxSigned, "idxprom");
-
// Handle the extvector case we ignored above.
if (isa<ExtVectorElementExpr>(E->getBase())) {
LValue LV = EmitLValue(E->getBase());
+ auto *Idx = EmitIdxAfterBase(/*Promote*/true);
Address Addr = EmitExtVectorElementLValue(LV);
QualType EltType = LV.getType()->castAs<VectorType>()->getElementType();
@@ -2913,6 +2993,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
// it. It needs to be emitted first in case it's what captures
// the VLA bounds.
Addr = EmitPointerWithAlignment(E->getBase(), &AlignSource);
+ auto *Idx = EmitIdxAfterBase(/*Promote*/true);
// The element count here is the total number of non-VLA elements.
llvm::Value *numElements = getVLASize(vla).first;
@@ -2932,14 +3013,16 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
} else if (const ObjCObjectType *OIT = E->getType()->getAs<ObjCObjectType>()){
// Indexing over an interface, as in "NSString *P; P[4];"
- CharUnits InterfaceSize = getContext().getTypeSizeInChars(OIT);
- llvm::Value *InterfaceSizeVal =
- llvm::ConstantInt::get(Idx->getType(), InterfaceSize.getQuantity());;
-
- llvm::Value *ScaledIdx = Builder.CreateMul(Idx, InterfaceSizeVal);
// Emit the base pointer.
Addr = EmitPointerWithAlignment(E->getBase(), &AlignSource);
+ auto *Idx = EmitIdxAfterBase(/*Promote*/true);
+
+ CharUnits InterfaceSize = getContext().getTypeSizeInChars(OIT);
+ llvm::Value *InterfaceSizeVal =
+ llvm::ConstantInt::get(Idx->getType(), InterfaceSize.getQuantity());
+
+ llvm::Value *ScaledIdx = Builder.CreateMul(Idx, InterfaceSizeVal);
// We don't necessarily build correct LLVM struct types for ObjC
// interfaces, so we can't rely on GEP to do this scaling
@@ -2971,6 +3054,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
ArrayLV = EmitArraySubscriptExpr(ASE, /*Accessed*/ true);
else
ArrayLV = EmitLValue(Array);
+ auto *Idx = EmitIdxAfterBase(/*Promote*/true);
// Propagate the alignment from the array itself to the result.
Addr = emitArraySubscriptGEP(*this, ArrayLV.getAddress(),
@@ -2981,6 +3065,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
} else {
// The base must be a pointer; emit it with an estimate of its alignment.
Addr = EmitPointerWithAlignment(E->getBase(), &AlignSource);
+ auto *Idx = EmitIdxAfterBase(/*Promote*/true);
Addr = emitArraySubscriptGEP(*this, Addr, Idx, E->getType(),
!getLangOpts().isSignedOverflowDefined());
}
@@ -3463,7 +3548,7 @@ LValue CodeGenFunction::EmitInitListLValue(const InitListExpr *E) {
return EmitAggExprToLValue(E);
// An lvalue initializer list must be initializing a reference.
- assert(E->getNumInits() == 1 && "reference init with multiple values");
+ assert(E->isTransparent() && "non-transparent glvalue init list");
return EmitLValue(E->getInit(0));
}
@@ -3602,6 +3687,7 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
case CK_ARCExtendBlockObject:
case CK_CopyAndAutoreleaseBlockObject:
case CK_AddressSpaceConversion:
+ case CK_IntToOCLSampler:
return EmitUnsupportedLValue(E, "unexpected cast lvalue");
case CK_Dependent:
@@ -3695,6 +3781,8 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
ConvertType(E->getType()));
return MakeAddrLValue(V, E->getType(), LV.getAlignmentSource());
}
+ case CK_ZeroToOCLQueue:
+ llvm_unreachable("NULL to OpenCL queue lvalue cast is not valid");
case CK_ZeroToOCLEvent:
llvm_unreachable("NULL to OpenCL event lvalue cast is not valid");
}
@@ -3743,70 +3831,86 @@ RValue CodeGenFunction::EmitCallExpr(const CallExpr *E,
if (const auto *CE = dyn_cast<CUDAKernelCallExpr>(E))
return EmitCUDAKernelCallExpr(CE, ReturnValue);
- const Decl *TargetDecl = E->getCalleeDecl();
- if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl)) {
- if (unsigned builtinID = FD->getBuiltinID())
- return EmitBuiltinExpr(FD, builtinID, E, ReturnValue);
- }
-
if (const auto *CE = dyn_cast<CXXOperatorCallExpr>(E))
- if (const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(TargetDecl))
+ if (const CXXMethodDecl *MD =
+ dyn_cast_or_null<CXXMethodDecl>(CE->getCalleeDecl()))
return EmitCXXOperatorMemberCallExpr(CE, MD, ReturnValue);
- if (const auto *PseudoDtor =
- dyn_cast<CXXPseudoDestructorExpr>(E->getCallee()->IgnoreParens())) {
- QualType DestroyedType = PseudoDtor->getDestroyedType();
- if (DestroyedType.hasStrongOrWeakObjCLifetime()) {
- // Automatic Reference Counting:
- // If the pseudo-expression names a retainable object with weak or
- // strong lifetime, the object shall be released.
- Expr *BaseExpr = PseudoDtor->getBase();
- Address BaseValue = Address::invalid();
- Qualifiers BaseQuals;
-
- // If this is s.x, emit s as an lvalue. If it is s->x, emit s as a scalar.
- if (PseudoDtor->isArrow()) {
- BaseValue = EmitPointerWithAlignment(BaseExpr);
- const PointerType *PTy = BaseExpr->getType()->getAs<PointerType>();
- BaseQuals = PTy->getPointeeType().getQualifiers();
- } else {
- LValue BaseLV = EmitLValue(BaseExpr);
- BaseValue = BaseLV.getAddress();
- QualType BaseTy = BaseExpr->getType();
- BaseQuals = BaseTy.getQualifiers();
- }
+ CGCallee callee = EmitCallee(E->getCallee());
- switch (DestroyedType.getObjCLifetime()) {
- case Qualifiers::OCL_None:
- case Qualifiers::OCL_ExplicitNone:
- case Qualifiers::OCL_Autoreleasing:
- break;
+ if (callee.isBuiltin()) {
+ return EmitBuiltinExpr(callee.getBuiltinDecl(), callee.getBuiltinID(),
+ E, ReturnValue);
+ }
- case Qualifiers::OCL_Strong:
- EmitARCRelease(Builder.CreateLoad(BaseValue,
- PseudoDtor->getDestroyedType().isVolatileQualified()),
- ARCPreciseLifetime);
- break;
+ if (callee.isPseudoDestructor()) {
+ return EmitCXXPseudoDestructorExpr(callee.getPseudoDestructorExpr());
+ }
- case Qualifiers::OCL_Weak:
- EmitARCDestroyWeak(BaseValue);
- break;
- }
- } else {
- // C++ [expr.pseudo]p1:
- // The result shall only be used as the operand for the function call
- // operator (), and the result of such a call has type void. The only
- // effect is the evaluation of the postfix-expression before the dot or
- // arrow.
- EmitScalarExpr(E->getCallee());
+ return EmitCall(E->getCallee()->getType(), callee, E, ReturnValue);
+}
+
+/// Emit a CallExpr without considering whether it might be a subclass.
+RValue CodeGenFunction::EmitSimpleCallExpr(const CallExpr *E,
+ ReturnValueSlot ReturnValue) {
+ CGCallee Callee = EmitCallee(E->getCallee());
+ return EmitCall(E->getCallee()->getType(), Callee, E, ReturnValue);
+}
+
+static CGCallee EmitDirectCallee(CodeGenFunction &CGF, const FunctionDecl *FD) {
+ if (auto builtinID = FD->getBuiltinID()) {
+ return CGCallee::forBuiltin(builtinID, FD);
+ }
+
+ llvm::Constant *calleePtr = EmitFunctionDeclPointer(CGF.CGM, FD);
+ return CGCallee::forDirect(calleePtr, FD);
+}
+
+CGCallee CodeGenFunction::EmitCallee(const Expr *E) {
+ E = E->IgnoreParens();
+
+ // Look through function-to-pointer decay.
+ if (auto ICE = dyn_cast<ImplicitCastExpr>(E)) {
+ if (ICE->getCastKind() == CK_FunctionToPointerDecay ||
+ ICE->getCastKind() == CK_BuiltinFnToFnPtr) {
+ return EmitCallee(ICE->getSubExpr());
}
- return RValue::get(nullptr);
+ // Resolve direct calls.
+ } else if (auto DRE = dyn_cast<DeclRefExpr>(E)) {
+ if (auto FD = dyn_cast<FunctionDecl>(DRE->getDecl())) {
+ return EmitDirectCallee(*this, FD);
+ }
+ } else if (auto ME = dyn_cast<MemberExpr>(E)) {
+ if (auto FD = dyn_cast<FunctionDecl>(ME->getMemberDecl())) {
+ EmitIgnoredExpr(ME->getBase());
+ return EmitDirectCallee(*this, FD);
+ }
+
+ // Look through template substitutions.
+ } else if (auto NTTP = dyn_cast<SubstNonTypeTemplateParmExpr>(E)) {
+ return EmitCallee(NTTP->getReplacement());
+
+ // Treat pseudo-destructor calls differently.
+ } else if (auto PDE = dyn_cast<CXXPseudoDestructorExpr>(E)) {
+ return CGCallee::forPseudoDestructor(PDE);
}
- llvm::Value *Callee = EmitScalarExpr(E->getCallee());
- return EmitCall(E->getCallee()->getType(), Callee, E, ReturnValue,
- TargetDecl);
+ // Otherwise, we have an indirect reference.
+ llvm::Value *calleePtr;
+ QualType functionType;
+ if (auto ptrType = E->getType()->getAs<PointerType>()) {
+ calleePtr = EmitScalarExpr(E);
+ functionType = ptrType->getPointeeType();
+ } else {
+ functionType = E->getType();
+ calleePtr = EmitLValue(E).getPointer();
+ }
+ assert(functionType->isFunctionType());
+ CGCalleeInfo calleeInfo(functionType->getAs<FunctionProtoType>(),
+ E->getReferencedDeclOfCallee());
+ CGCallee callee(calleeInfo, calleePtr);
+ return callee;
}
LValue CodeGenFunction::EmitBinaryOperatorLValue(const BinaryOperator *E) {
@@ -3982,22 +4086,15 @@ LValue CodeGenFunction::EmitStmtExprLValue(const StmtExpr *E) {
AlignmentSource::Decl);
}
-RValue CodeGenFunction::EmitCall(QualType CalleeType, llvm::Value *Callee,
+RValue CodeGenFunction::EmitCall(QualType CalleeType, const CGCallee &OrigCallee,
const CallExpr *E, ReturnValueSlot ReturnValue,
- CGCalleeInfo CalleeInfo, llvm::Value *Chain) {
+ llvm::Value *Chain) {
// Get the actual function type. The callee type will always be a pointer to
// function type or a block pointer type.
assert(CalleeType->isFunctionPointerType() &&
"Call must have function pointer type!");
- // Preserve the non-canonical function type because things like exception
- // specifications disappear in the canonical type. That information is useful
- // to drive the generation of more accurate code for this call later on.
- const FunctionProtoType *NonCanonicalFTP = CalleeType->getAs<PointerType>()
- ->getPointeeType()
- ->getAs<FunctionProtoType>();
-
- const Decl *TargetDecl = CalleeInfo.getCalleeDecl();
+ const Decl *TargetDecl = OrigCallee.getAbstractInfo().getCalleeDecl();
if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl))
// We can only guarantee that a function is called from the correct
@@ -4015,6 +4112,8 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, llvm::Value *Callee,
const auto *FnType =
cast<FunctionType>(cast<PointerType>(CalleeType)->getPointeeType());
+ CGCallee Callee = OrigCallee;
+
if (getLangOpts().CPlusPlus && SanOpts.has(SanitizerKind::Function) &&
(!TargetDecl || !isa<FunctionDecl>(TargetDecl))) {
if (llvm::Constant *PrefixSig =
@@ -4029,8 +4128,10 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, llvm::Value *Callee,
llvm::StructType *PrefixStructTy = llvm::StructType::get(
CGM.getLLVMContext(), PrefixStructTyElems, /*isPacked=*/true);
+ llvm::Value *CalleePtr = Callee.getFunctionPointer();
+
llvm::Value *CalleePrefixStruct = Builder.CreateBitCast(
- Callee, llvm::PointerType::getUnqual(PrefixStructTy));
+ CalleePtr, llvm::PointerType::getUnqual(PrefixStructTy));
llvm::Value *CalleeSigPtr =
Builder.CreateConstGEP2_32(PrefixStructTy, CalleePrefixStruct, 0, 0);
llvm::Value *CalleeSig =
@@ -4053,7 +4154,7 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, llvm::Value *Callee,
EmitCheckTypeDescriptor(CalleeType)
};
EmitCheck(std::make_pair(CalleeRTTIMatch, SanitizerKind::Function),
- "function_type_mismatch", StaticData, Callee);
+ SanitizerHandler::FunctionTypeMismatch, StaticData, CalleePtr);
Builder.CreateBr(Cont);
EmitBlock(Cont);
@@ -4070,7 +4171,8 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, llvm::Value *Callee,
llvm::Metadata *MD = CGM.CreateMetadataIdentifierForType(QualType(FnType, 0));
llvm::Value *TypeId = llvm::MetadataAsValue::get(getLLVMContext(), MD);
- llvm::Value *CastedCallee = Builder.CreateBitCast(Callee, Int8PtrTy);
+ llvm::Value *CalleePtr = Callee.getFunctionPointer();
+ llvm::Value *CastedCallee = Builder.CreateBitCast(CalleePtr, Int8PtrTy);
llvm::Value *TypeTest = Builder.CreateCall(
CGM.getIntrinsic(llvm::Intrinsic::type_test), {CastedCallee, TypeId});
@@ -4085,7 +4187,7 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, llvm::Value *Callee,
CastedCallee, StaticData);
} else {
EmitCheck(std::make_pair(TypeTest, SanitizerKind::CFIICall),
- "cfi_check_fail", StaticData,
+ SanitizerHandler::CFICheckFail, StaticData,
{CastedCallee, llvm::UndefValue::get(IntPtrTy)});
}
}
@@ -4094,8 +4196,35 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, llvm::Value *Callee,
if (Chain)
Args.add(RValue::get(Builder.CreateBitCast(Chain, CGM.VoidPtrTy)),
CGM.getContext().VoidPtrTy);
+
+ // C++17 requires that we evaluate arguments to a call using assignment syntax
+ // right-to-left, and that we evaluate arguments to certain other operators
+ // left-to-right. Note that we allow this to override the order dictated by
+ // the calling convention on the MS ABI, which means that parameter
+ // destruction order is not necessarily reverse construction order.
+ // FIXME: Revisit this based on C++ committee response to unimplementability.
+ EvaluationOrder Order = EvaluationOrder::Default;
+ if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(E)) {
+ if (OCE->isAssignmentOp())
+ Order = EvaluationOrder::ForceRightToLeft;
+ else {
+ switch (OCE->getOperator()) {
+ case OO_LessLess:
+ case OO_GreaterGreater:
+ case OO_AmpAmp:
+ case OO_PipePipe:
+ case OO_Comma:
+ case OO_ArrowStar:
+ Order = EvaluationOrder::ForceLeftToRight;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
EmitCallArgs(Args, dyn_cast<FunctionProtoType>(FnType), E->arguments(),
- E->getDirectCallee(), /*ParamsToSkip*/ 0);
+ E->getDirectCallee(), /*ParamsToSkip*/ 0, Order);
const CGFunctionInfo &FnInfo = CGM.getTypes().arrangeFreeFunctionCall(
Args, FnType, /*isChainCall=*/Chain);
@@ -4123,11 +4252,13 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, llvm::Value *Callee,
if (isa<FunctionNoProtoType>(FnType) || Chain) {
llvm::Type *CalleeTy = getTypes().GetFunctionType(FnInfo);
CalleeTy = CalleeTy->getPointerTo();
- Callee = Builder.CreateBitCast(Callee, CalleeTy, "callee.knr.cast");
+
+ llvm::Value *CalleePtr = Callee.getFunctionPointer();
+ CalleePtr = Builder.CreateBitCast(CalleePtr, CalleeTy, "callee.knr.cast");
+ Callee.setFunctionPointer(CalleePtr);
}
- return EmitCall(FnInfo, Callee, ReturnValue, Args,
- CGCalleeInfo(NonCanonicalFTP, TargetDecl));
+ return EmitCall(FnInfo, Callee, ReturnValue, Args);
}
LValue CodeGenFunction::
diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp
index 6d18843591f3..009244784e50 100644
--- a/lib/CodeGen/CGExprAgg.cpp
+++ b/lib/CodeGen/CGExprAgg.cpp
@@ -164,6 +164,8 @@ public:
void VisitAbstractConditionalOperator(const AbstractConditionalOperator *CO);
void VisitChooseExpr(const ChooseExpr *CE);
void VisitInitListExpr(InitListExpr *E);
+ void VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E,
+ llvm::Value *outerBegin = nullptr);
void VisitImplicitValueInitExpr(ImplicitValueInitExpr *E);
void VisitNoInitExpr(NoInitExpr *E) { } // Do nothing.
void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE) {
@@ -749,7 +751,9 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
case CK_CopyAndAutoreleaseBlockObject:
case CK_BuiltinFnToFnPtr:
case CK_ZeroToOCLEvent:
+ case CK_ZeroToOCLQueue:
case CK_AddressSpaceConversion:
+ case CK_IntToOCLSampler:
llvm_unreachable("cast kind invalid for aggregate types");
}
}
@@ -1049,7 +1053,8 @@ static bool isSimpleZero(const Expr *E, CodeGenFunction &CGF) {
return true;
// (int*)0 - Null pointer expressions.
if (const CastExpr *ICE = dyn_cast<CastExpr>(E))
- return ICE->getCastKind() == CK_NullToPointer;
+ return ICE->getCastKind() == CK_NullToPointer &&
+ CGF.getTypes().isPointerZeroInitializable(E->getType());
// '\0'
if (const CharacterLiteral *CL = dyn_cast<CharacterLiteral>(E))
return CL->getValue() == 0;
@@ -1144,15 +1149,15 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {
if (E->hadArrayRangeDesignator())
CGF.ErrorUnsupported(E, "GNU array range designator extension");
+ if (E->isTransparent())
+ return Visit(E->getInit(0));
+
AggValueSlot Dest = EnsureSlot(E->getType());
LValue DestLV = CGF.MakeAddrLValue(Dest.getAddress(), E->getType());
// Handle initialization of an array.
if (E->getType()->isArrayType()) {
- if (E->isStringLiteralInit())
- return Visit(E->getInit(0));
-
QualType elementType =
CGF.getContext().getAsArrayType(E->getType())->getElementType();
@@ -1161,16 +1166,6 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {
return;
}
- if (E->getType()->isAtomicType()) {
- // An _Atomic(T) object can be list-initialized from an expression
- // of the same type.
- assert(E->getNumInits() == 1 &&
- CGF.getContext().hasSameUnqualifiedType(E->getInit(0)->getType(),
- E->getType()) &&
- "unexpected list initialization for atomic object");
- return Visit(E->getInit(0));
- }
-
assert(E->getType()->isRecordType() && "Only support structs/unions here!");
// Do struct initialization; this code just sets each individual member
@@ -1316,6 +1311,98 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {
cleanupDominator->eraseFromParent();
}
+void AggExprEmitter::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E,
+ llvm::Value *outerBegin) {
+ // Emit the common subexpression.
+ CodeGenFunction::OpaqueValueMapping binding(CGF, E->getCommonExpr());
+
+ Address destPtr = EnsureSlot(E->getType()).getAddress();
+ uint64_t numElements = E->getArraySize().getZExtValue();
+
+ if (!numElements)
+ return;
+
+ // destPtr is an array*. Construct an elementType* by drilling down a level.
+ llvm::Value *zero = llvm::ConstantInt::get(CGF.SizeTy, 0);
+ llvm::Value *indices[] = {zero, zero};
+ llvm::Value *begin = Builder.CreateInBoundsGEP(destPtr.getPointer(), indices,
+ "arrayinit.begin");
+
+ // Prepare to special-case multidimensional array initialization: we avoid
+ // emitting multiple destructor loops in that case.
+ if (!outerBegin)
+ outerBegin = begin;
+ ArrayInitLoopExpr *InnerLoop = dyn_cast<ArrayInitLoopExpr>(E->getSubExpr());
+
+ QualType elementType =
+ CGF.getContext().getAsArrayType(E->getType())->getElementType();
+ CharUnits elementSize = CGF.getContext().getTypeSizeInChars(elementType);
+ CharUnits elementAlign =
+ destPtr.getAlignment().alignmentOfArrayElement(elementSize);
+
+ llvm::BasicBlock *entryBB = Builder.GetInsertBlock();
+ llvm::BasicBlock *bodyBB = CGF.createBasicBlock("arrayinit.body");
+
+ // Jump into the body.
+ CGF.EmitBlock(bodyBB);
+ llvm::PHINode *index =
+ Builder.CreatePHI(zero->getType(), 2, "arrayinit.index");
+ index->addIncoming(zero, entryBB);
+ llvm::Value *element = Builder.CreateInBoundsGEP(begin, index);
+
+ // Prepare for a cleanup.
+ QualType::DestructionKind dtorKind = elementType.isDestructedType();
+ EHScopeStack::stable_iterator cleanup;
+ if (CGF.needsEHCleanup(dtorKind) && !InnerLoop) {
+ if (outerBegin->getType() != element->getType())
+ outerBegin = Builder.CreateBitCast(outerBegin, element->getType());
+ CGF.pushRegularPartialArrayCleanup(outerBegin, element, elementType,
+ elementAlign,
+ CGF.getDestroyer(dtorKind));
+ cleanup = CGF.EHStack.stable_begin();
+ } else {
+ dtorKind = QualType::DK_none;
+ }
+
+ // Emit the actual filler expression.
+ {
+ // Temporaries created in an array initialization loop are destroyed
+ // at the end of each iteration.
+ CodeGenFunction::RunCleanupsScope CleanupsScope(CGF);
+ CodeGenFunction::ArrayInitLoopExprScope Scope(CGF, index);
+ LValue elementLV =
+ CGF.MakeAddrLValue(Address(element, elementAlign), elementType);
+
+ if (InnerLoop) {
+ // If the subexpression is an ArrayInitLoopExpr, share its cleanup.
+ auto elementSlot = AggValueSlot::forLValue(
+ elementLV, AggValueSlot::IsDestructed,
+ AggValueSlot::DoesNotNeedGCBarriers, AggValueSlot::IsNotAliased);
+ AggExprEmitter(CGF, elementSlot, false)
+ .VisitArrayInitLoopExpr(InnerLoop, outerBegin);
+ } else
+ EmitInitializationToLValue(E->getSubExpr(), elementLV);
+ }
+
+ // Move on to the next element.
+ llvm::Value *nextIndex = Builder.CreateNUWAdd(
+ index, llvm::ConstantInt::get(CGF.SizeTy, 1), "arrayinit.next");
+ index->addIncoming(nextIndex, Builder.GetInsertBlock());
+
+ // Leave the loop if we're done.
+ llvm::Value *done = Builder.CreateICmpEQ(
+ nextIndex, llvm::ConstantInt::get(CGF.SizeTy, numElements),
+ "arrayinit.done");
+ llvm::BasicBlock *endBB = CGF.createBasicBlock("arrayinit.end");
+ Builder.CreateCondBr(done, endBB, bodyBB);
+
+ CGF.EmitBlock(endBB);
+
+ // Leave the partial-array cleanup if we entered one.
+ if (dtorKind)
+ CGF.DeactivateCleanupBlock(cleanup, index);
+}
+
void AggExprEmitter::VisitDesignatedInitUpdateExpr(DesignatedInitUpdateExpr *E) {
AggValueSlot Dest = EnsureSlot(E->getType());
diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp
index eec2aceb88a2..71c8fb8b7ae3 100644
--- a/lib/CodeGen/CGExprCXX.cpp
+++ b/lib/CodeGen/CGExprCXX.cpp
@@ -28,25 +28,18 @@ static RequiredArgs
commonEmitCXXMemberOrOperatorCall(CodeGenFunction &CGF, const CXXMethodDecl *MD,
llvm::Value *This, llvm::Value *ImplicitParam,
QualType ImplicitParamTy, const CallExpr *CE,
- CallArgList &Args) {
+ CallArgList &Args, CallArgList *RtlArgs) {
assert(CE == nullptr || isa<CXXMemberCallExpr>(CE) ||
isa<CXXOperatorCallExpr>(CE));
assert(MD->isInstance() &&
"Trying to emit a member or operator call expr on a static method!");
-
- // 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.
- SourceLocation CallLoc;
- if (CE)
- CallLoc = CE->getExprLoc();
- CGF.EmitTypeCheck(
- isa<CXXConstructorDecl>(MD) ? CodeGenFunction::TCK_ConstructorCall
- : CodeGenFunction::TCK_MemberCall,
- CallLoc, This, CGF.getContext().getRecordType(MD->getParent()));
+ ASTContext &C = CGF.getContext();
// Push the this ptr.
- Args.add(RValue::get(This), MD->getThisType(CGF.getContext()));
+ const CXXRecordDecl *RD =
+ CGF.CGM.getCXXABI().getThisArgumentTypeForMethod(MD);
+ Args.add(RValue::get(This),
+ RD ? C.getPointerType(C.getTypeDeclType(RD)) : C.VoidPtrTy);
// If there is an implicit parameter (e.g. VTT), emit it.
if (ImplicitParam) {
@@ -57,7 +50,12 @@ commonEmitCXXMemberOrOperatorCall(CodeGenFunction &CGF, const CXXMethodDecl *MD,
RequiredArgs required = RequiredArgs::forPrototypePlus(FPT, Args.size(), MD);
// And the rest of the call args.
- if (CE) {
+ if (RtlArgs) {
+ // Special case: if the caller emitted the arguments right-to-left already
+ // (prior to emitting the *this argument), we're done. This happens for
+ // assignment operators.
+ Args.addFrom(*RtlArgs);
+ } else if (CE) {
// Special case: skip first argument of CXXOperatorCall (it is "this").
unsigned ArgsToSkip = isa<CXXOperatorCallExpr>(CE) ? 1 : 0;
CGF.EmitCallArgs(Args, FPT, drop_begin(CE->arguments(), ArgsToSkip),
@@ -71,26 +69,78 @@ commonEmitCXXMemberOrOperatorCall(CodeGenFunction &CGF, const CXXMethodDecl *MD,
}
RValue CodeGenFunction::EmitCXXMemberOrOperatorCall(
- const CXXMethodDecl *MD, llvm::Value *Callee, ReturnValueSlot ReturnValue,
+ const CXXMethodDecl *MD, const CGCallee &Callee,
+ ReturnValueSlot ReturnValue,
llvm::Value *This, llvm::Value *ImplicitParam, QualType ImplicitParamTy,
- const CallExpr *CE) {
+ const CallExpr *CE, CallArgList *RtlArgs) {
const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>();
CallArgList Args;
RequiredArgs required = commonEmitCXXMemberOrOperatorCall(
- *this, MD, This, ImplicitParam, ImplicitParamTy, CE, Args);
- return EmitCall(CGM.getTypes().arrangeCXXMethodCall(Args, FPT, required),
- Callee, ReturnValue, Args, MD);
+ *this, MD, This, ImplicitParam, ImplicitParamTy, CE, Args, RtlArgs);
+ auto &FnInfo = CGM.getTypes().arrangeCXXMethodCall(Args, FPT, required);
+ return EmitCall(FnInfo, Callee, ReturnValue, Args);
}
RValue CodeGenFunction::EmitCXXDestructorCall(
- const CXXDestructorDecl *DD, llvm::Value *Callee, llvm::Value *This,
+ const CXXDestructorDecl *DD, const CGCallee &Callee, llvm::Value *This,
llvm::Value *ImplicitParam, QualType ImplicitParamTy, const CallExpr *CE,
StructorType Type) {
CallArgList Args;
commonEmitCXXMemberOrOperatorCall(*this, DD, This, ImplicitParam,
- ImplicitParamTy, CE, Args);
+ ImplicitParamTy, CE, Args, nullptr);
return EmitCall(CGM.getTypes().arrangeCXXStructorDeclaration(DD, Type),
- Callee, ReturnValueSlot(), Args, DD);
+ Callee, ReturnValueSlot(), Args);
+}
+
+RValue CodeGenFunction::EmitCXXPseudoDestructorExpr(
+ const CXXPseudoDestructorExpr *E) {
+ QualType DestroyedType = E->getDestroyedType();
+ if (DestroyedType.hasStrongOrWeakObjCLifetime()) {
+ // Automatic Reference Counting:
+ // If the pseudo-expression names a retainable object with weak or
+ // strong lifetime, the object shall be released.
+ Expr *BaseExpr = E->getBase();
+ Address BaseValue = Address::invalid();
+ Qualifiers BaseQuals;
+
+ // If this is s.x, emit s as an lvalue. If it is s->x, emit s as a scalar.
+ if (E->isArrow()) {
+ BaseValue = EmitPointerWithAlignment(BaseExpr);
+ const PointerType *PTy = BaseExpr->getType()->getAs<PointerType>();
+ BaseQuals = PTy->getPointeeType().getQualifiers();
+ } else {
+ LValue BaseLV = EmitLValue(BaseExpr);
+ BaseValue = BaseLV.getAddress();
+ QualType BaseTy = BaseExpr->getType();
+ BaseQuals = BaseTy.getQualifiers();
+ }
+
+ switch (DestroyedType.getObjCLifetime()) {
+ case Qualifiers::OCL_None:
+ case Qualifiers::OCL_ExplicitNone:
+ case Qualifiers::OCL_Autoreleasing:
+ break;
+
+ case Qualifiers::OCL_Strong:
+ EmitARCRelease(Builder.CreateLoad(BaseValue,
+ DestroyedType.isVolatileQualified()),
+ ARCPreciseLifetime);
+ break;
+
+ case Qualifiers::OCL_Weak:
+ EmitARCDestroyWeak(BaseValue);
+ break;
+ }
+ } else {
+ // C++ [expr.pseudo]p1:
+ // The result shall only be used as the operand for the function call
+ // operator (), and the result of such a call has type void. The only
+ // effect is the evaluation of the postfix-expression before the dot or
+ // arrow.
+ EmitIgnoredExpr(E->getBase());
+ }
+
+ return RValue::get(nullptr);
}
static CXXRecordDecl *getCXXRecord(const Expr *E) {
@@ -115,8 +165,8 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE,
if (MD->isStatic()) {
// The method is static, emit it as we would a regular call.
- llvm::Value *Callee = CGM.GetAddrOfFunction(MD);
- return EmitCall(getContext().getPointerType(MD->getType()), Callee, CE,
+ CGCallee callee = CGCallee::forDirect(CGM.GetAddrOfFunction(MD), MD);
+ return EmitCall(getContext().getPointerType(MD->getType()), callee, CE,
ReturnValue);
}
@@ -166,6 +216,19 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(
}
}
+ // C++17 demands that we evaluate the RHS of a (possibly-compound) assignment
+ // operator before the LHS.
+ CallArgList RtlArgStorage;
+ CallArgList *RtlArgs = nullptr;
+ if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(CE)) {
+ if (OCE->isAssignmentOp()) {
+ RtlArgs = &RtlArgStorage;
+ EmitCallArgs(*RtlArgs, MD->getType()->castAs<FunctionProtoType>(),
+ drop_begin(CE->arguments(), 1), CE->getDirectCallee(),
+ /*ParamsToSkip*/0, EvaluationOrder::ForceRightToLeft);
+ }
+ }
+
Address This = Address::invalid();
if (IsArrow)
This = EmitPointerWithAlignment(Base);
@@ -183,10 +246,12 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(
if (MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator()) {
// We don't like to generate the trivial copy/move assignment operator
// when it isn't necessary; just produce the proper effect here.
- // Special case: skip first argument of CXXOperatorCall (it is "this").
- unsigned ArgsToSkip = isa<CXXOperatorCallExpr>(CE) ? 1 : 0;
- Address RHS = EmitLValue(*(CE->arg_begin() + ArgsToSkip)).getAddress();
- EmitAggregateAssign(This, RHS, CE->getType());
+ LValue RHS = isa<CXXOperatorCallExpr>(CE)
+ ? MakeNaturalAlignAddrLValue(
+ (*RtlArgs)[0].RV.getScalarVal(),
+ (*(CE->arg_begin() + 1))->getType())
+ : EmitLValue(*CE->arg_begin());
+ EmitAggregateAssign(This, RHS.getAddress(), CE->getType());
return RValue::get(This.getPointer());
}
@@ -217,6 +282,22 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(
llvm::FunctionType *Ty = CGM.getTypes().GetFunctionType(*FInfo);
+ // 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.
+ SourceLocation CallLoc;
+ ASTContext &C = getContext();
+ if (CE)
+ CallLoc = CE->getExprLoc();
+
+ EmitTypeCheck(isa<CXXConstructorDecl>(CalleeDecl)
+ ? CodeGenFunction::TCK_ConstructorCall
+ : CodeGenFunction::TCK_MemberCall,
+ CallLoc, This.getPointer(), C.getRecordType(CalleeDecl->getParent()));
+
+ // FIXME: Uses of 'MD' past this point need to be audited. We may need to use
+ // 'CalleeDecl' instead.
+
// C++ [class.virtual]p12:
// Explicit qualification with the scope operator (5.1) suppresses the
// virtual call mechanism.
@@ -224,8 +305,7 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(
// We also don't emit a virtual call if the base expression has a record type
// because then we know what the type is.
bool UseVirtualCall = CanUseVirtualCall && !DevirtualizedMethod;
- llvm::Value *Callee;
-
+
if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(MD)) {
assert(CE->arg_begin() == CE->arg_end() &&
"Destructor shouldn't have explicit parameters");
@@ -234,24 +314,32 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(
CGM.getCXXABI().EmitVirtualDestructorCall(
*this, Dtor, Dtor_Complete, This, cast<CXXMemberCallExpr>(CE));
} else {
+ CGCallee Callee;
if (getLangOpts().AppleKext && MD->isVirtual() && HasQualifier)
Callee = BuildAppleKextVirtualCall(MD, Qualifier, Ty);
else if (!DevirtualizedMethod)
- Callee =
- CGM.getAddrOfCXXStructor(Dtor, StructorType::Complete, FInfo, Ty);
+ Callee = CGCallee::forDirect(
+ CGM.getAddrOfCXXStructor(Dtor, StructorType::Complete, FInfo, Ty),
+ Dtor);
else {
const CXXDestructorDecl *DDtor =
cast<CXXDestructorDecl>(DevirtualizedMethod);
- Callee = CGM.GetAddrOfFunction(GlobalDecl(DDtor, Dtor_Complete), Ty);
+ Callee = CGCallee::forDirect(
+ CGM.GetAddrOfFunction(GlobalDecl(DDtor, Dtor_Complete), Ty),
+ DDtor);
}
- EmitCXXMemberOrOperatorCall(MD, Callee, ReturnValue, This.getPointer(),
- /*ImplicitParam=*/nullptr, QualType(), CE);
+ EmitCXXMemberOrOperatorCall(
+ CalleeDecl, Callee, ReturnValue, This.getPointer(),
+ /*ImplicitParam=*/nullptr, QualType(), CE, nullptr);
}
return RValue::get(nullptr);
}
+ CGCallee Callee;
if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(MD)) {
- Callee = CGM.GetAddrOfFunction(GlobalDecl(Ctor, Ctor_Complete), Ty);
+ Callee = CGCallee::forDirect(
+ CGM.GetAddrOfFunction(GlobalDecl(Ctor, Ctor_Complete), Ty),
+ Ctor);
} else if (UseVirtualCall) {
Callee = CGM.getCXXABI().getVirtualFunctionPointer(*this, MD, This, Ty,
CE->getLocStart());
@@ -266,9 +354,11 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(
if (getLangOpts().AppleKext && MD->isVirtual() && HasQualifier)
Callee = BuildAppleKextVirtualCall(MD, Qualifier, Ty);
else if (!DevirtualizedMethod)
- Callee = CGM.GetAddrOfFunction(MD, Ty);
+ Callee = CGCallee::forDirect(CGM.GetAddrOfFunction(MD, Ty), MD);
else {
- Callee = CGM.GetAddrOfFunction(DevirtualizedMethod, Ty);
+ Callee = CGCallee::forDirect(
+ CGM.GetAddrOfFunction(DevirtualizedMethod, Ty),
+ DevirtualizedMethod);
}
}
@@ -277,8 +367,9 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(
*this, CalleeDecl, This, UseVirtualCall);
}
- return EmitCXXMemberOrOperatorCall(MD, Callee, ReturnValue, This.getPointer(),
- /*ImplicitParam=*/nullptr, QualType(), CE);
+ return EmitCXXMemberOrOperatorCall(
+ CalleeDecl, Callee, ReturnValue, This.getPointer(),
+ /*ImplicitParam=*/nullptr, QualType(), CE, RtlArgs);
}
RValue
@@ -297,9 +388,6 @@ CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E,
const CXXRecordDecl *RD =
cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl());
- // Get the member function pointer.
- llvm::Value *MemFnPtr = EmitScalarExpr(MemFnExpr);
-
// Emit the 'this' pointer.
Address This = Address::invalid();
if (BO->getOpcode() == BO_PtrMemI)
@@ -310,9 +398,12 @@ CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E,
EmitTypeCheck(TCK_MemberCall, E->getExprLoc(), This.getPointer(),
QualType(MPT->getClass(), 0));
+ // Get the member function pointer.
+ llvm::Value *MemFnPtr = EmitScalarExpr(MemFnExpr);
+
// Ask the ABI to load the callee. Note that This is modified.
llvm::Value *ThisPtrForCall = nullptr;
- llvm::Value *Callee =
+ CGCallee Callee =
CGM.getCXXABI().EmitLoadOfMemberFunctionPointer(*this, BO, This,
ThisPtrForCall, MemFnPtr, MPT);
@@ -851,8 +942,68 @@ void CodeGenFunction::EmitNewArrayInitializer(
CharUnits ElementAlign =
BeginPtr.getAlignment().alignmentOfArrayElement(ElementSize);
+ // Attempt to perform zero-initialization using memset.
+ auto TryMemsetInitialization = [&]() -> bool {
+ // FIXME: If the type is a pointer-to-data-member under the Itanium ABI,
+ // we can initialize with a memset to -1.
+ if (!CGM.getTypes().isZeroInitializable(ElementType))
+ return false;
+
+ // Optimization: since zero initialization will just set the memory
+ // to all zeroes, generate a single memset to do it in one shot.
+
+ // Subtract out the size of any elements we've already initialized.
+ auto *RemainingSize = AllocSizeWithoutCookie;
+ if (InitListElements) {
+ // We know this can't overflow; we check this when doing the allocation.
+ auto *InitializedSize = llvm::ConstantInt::get(
+ RemainingSize->getType(),
+ getContext().getTypeSizeInChars(ElementType).getQuantity() *
+ InitListElements);
+ RemainingSize = Builder.CreateSub(RemainingSize, InitializedSize);
+ }
+
+ // Create the memset.
+ Builder.CreateMemSet(CurPtr, Builder.getInt8(0), RemainingSize, false);
+ return true;
+ };
+
// If the initializer is an initializer list, first do the explicit elements.
if (const InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
+ // Initializing from a (braced) string literal is a special case; the init
+ // list element does not initialize a (single) array element.
+ if (ILE->isStringLiteralInit()) {
+ // Initialize the initial portion of length equal to that of the string
+ // literal. The allocation must be for at least this much; we emitted a
+ // check for that earlier.
+ AggValueSlot Slot =
+ AggValueSlot::forAddr(CurPtr, ElementType.getQualifiers(),
+ AggValueSlot::IsDestructed,
+ AggValueSlot::DoesNotNeedGCBarriers,
+ AggValueSlot::IsNotAliased);
+ EmitAggExpr(ILE->getInit(0), Slot);
+
+ // Move past these elements.
+ InitListElements =
+ cast<ConstantArrayType>(ILE->getType()->getAsArrayTypeUnsafe())
+ ->getSize().getZExtValue();
+ CurPtr =
+ Address(Builder.CreateInBoundsGEP(CurPtr.getPointer(),
+ Builder.getSize(InitListElements),
+ "string.init.end"),
+ CurPtr.getAlignment().alignmentAtOffset(InitListElements *
+ ElementSize));
+
+ // Zero out the rest, if any remain.
+ llvm::ConstantInt *ConstNum = dyn_cast<llvm::ConstantInt>(NumElements);
+ if (!ConstNum || !ConstNum->equalsInt(InitListElements)) {
+ bool OK = TryMemsetInitialization();
+ (void)OK;
+ assert(OK && "couldn't memset character type?");
+ }
+ return;
+ }
+
InitListElements = ILE->getNumInits();
// If this is a multi-dimensional array new, we will initialize multiple
@@ -919,32 +1070,6 @@ void CodeGenFunction::EmitNewArrayInitializer(
CurPtr = Builder.CreateBitCast(CurPtr, BeginPtr.getType());
}
- // Attempt to perform zero-initialization using memset.
- auto TryMemsetInitialization = [&]() -> bool {
- // FIXME: If the type is a pointer-to-data-member under the Itanium ABI,
- // we can initialize with a memset to -1.
- if (!CGM.getTypes().isZeroInitializable(ElementType))
- return false;
-
- // Optimization: since zero initialization will just set the memory
- // to all zeroes, generate a single memset to do it in one shot.
-
- // Subtract out the size of any elements we've already initialized.
- auto *RemainingSize = AllocSizeWithoutCookie;
- if (InitListElements) {
- // We know this can't overflow; we check this when doing the allocation.
- auto *InitializedSize = llvm::ConstantInt::get(
- RemainingSize->getType(),
- getContext().getTypeSizeInChars(ElementType).getQuantity() *
- InitListElements);
- RemainingSize = Builder.CreateSub(RemainingSize, InitializedSize);
- }
-
- // Create the memset.
- Builder.CreateMemSet(CurPtr, Builder.getInt8(0), RemainingSize, false);
- return true;
- };
-
// If all elements have already been initialized, skip any further
// initialization.
llvm::ConstantInt *ConstNum = dyn_cast<llvm::ConstantInt>(NumElements);
@@ -1110,23 +1235,24 @@ static void EmitNewInitializer(CodeGenFunction &CGF, const CXXNewExpr *E,
/// Emit a call to an operator new or operator delete function, as implicitly
/// created by new-expressions and delete-expressions.
static RValue EmitNewDeleteCall(CodeGenFunction &CGF,
- const FunctionDecl *Callee,
+ const FunctionDecl *CalleeDecl,
const FunctionProtoType *CalleeType,
const CallArgList &Args) {
llvm::Instruction *CallOrInvoke;
- llvm::Value *CalleeAddr = CGF.CGM.GetAddrOfFunction(Callee);
+ llvm::Constant *CalleePtr = CGF.CGM.GetAddrOfFunction(CalleeDecl);
+ CGCallee Callee = CGCallee::forDirect(CalleePtr, CalleeDecl);
RValue RV =
CGF.EmitCall(CGF.CGM.getTypes().arrangeFreeFunctionCall(
Args, CalleeType, /*chainCall=*/false),
- CalleeAddr, ReturnValueSlot(), Args, Callee, &CallOrInvoke);
+ Callee, ReturnValueSlot(), Args, &CallOrInvoke);
/// C++1y [expr.new]p10:
/// [In a new-expression,] an implementation is allowed to omit a call
/// to a replaceable global allocation function.
///
/// We model such elidable calls with the 'builtin' attribute.
- llvm::Function *Fn = dyn_cast<llvm::Function>(CalleeAddr);
- if (Callee->isReplaceableGlobalAllocationFunction() &&
+ llvm::Function *Fn = dyn_cast<llvm::Function>(CalleePtr);
+ if (CalleeDecl->isReplaceableGlobalAllocationFunction() &&
Fn && Fn->hasFnAttribute(llvm::Attribute::NoBuiltin)) {
// FIXME: Add addAttribute to CallSite.
if (llvm::CallInst *CI = dyn_cast<llvm::CallInst>(CallOrInvoke))
@@ -1159,111 +1285,116 @@ RValue CodeGenFunction::EmitBuiltinNewDeleteCall(const FunctionProtoType *Type,
llvm_unreachable("predeclared global operator new/delete is missing");
}
-namespace {
- /// A cleanup to call the given 'operator delete' function upon
- /// abnormal exit from a new expression.
- class CallDeleteDuringNew final : public EHScopeStack::Cleanup {
- size_t NumPlacementArgs;
- const FunctionDecl *OperatorDelete;
- llvm::Value *Ptr;
- llvm::Value *AllocSize;
-
- RValue *getPlacementArgs() { return reinterpret_cast<RValue*>(this+1); }
+static std::pair<bool, bool>
+shouldPassSizeAndAlignToUsualDelete(const FunctionProtoType *FPT) {
+ auto AI = FPT->param_type_begin(), AE = FPT->param_type_end();
- public:
- static size_t getExtraSize(size_t NumPlacementArgs) {
- return NumPlacementArgs * sizeof(RValue);
- }
+ // The first argument is always a void*.
+ ++AI;
- CallDeleteDuringNew(size_t NumPlacementArgs,
- const FunctionDecl *OperatorDelete,
- llvm::Value *Ptr,
- llvm::Value *AllocSize)
- : NumPlacementArgs(NumPlacementArgs), OperatorDelete(OperatorDelete),
- Ptr(Ptr), AllocSize(AllocSize) {}
-
- void setPlacementArg(unsigned I, RValue Arg) {
- assert(I < NumPlacementArgs && "index out of range");
- getPlacementArgs()[I] = Arg;
- }
-
- void Emit(CodeGenFunction &CGF, Flags flags) override {
- const FunctionProtoType *FPT
- = OperatorDelete->getType()->getAs<FunctionProtoType>();
- assert(FPT->getNumParams() == NumPlacementArgs + 1 ||
- (FPT->getNumParams() == 2 && NumPlacementArgs == 0));
+ // Figure out what other parameters we should be implicitly passing.
+ bool PassSize = false;
+ bool PassAlignment = false;
- CallArgList DeleteArgs;
-
- // The first argument is always a void*.
- FunctionProtoType::param_type_iterator AI = FPT->param_type_begin();
- DeleteArgs.add(RValue::get(Ptr), *AI++);
-
- // A member 'operator delete' can take an extra 'size_t' argument.
- if (FPT->getNumParams() == NumPlacementArgs + 2)
- DeleteArgs.add(RValue::get(AllocSize), *AI++);
+ if (AI != AE && (*AI)->isIntegerType()) {
+ PassSize = true;
+ ++AI;
+ }
- // Pass the rest of the arguments, which must match exactly.
- for (unsigned I = 0; I != NumPlacementArgs; ++I)
- DeleteArgs.add(getPlacementArgs()[I], *AI++);
+ if (AI != AE && (*AI)->isAlignValT()) {
+ PassAlignment = true;
+ ++AI;
+ }
- // Call 'operator delete'.
- EmitNewDeleteCall(CGF, OperatorDelete, FPT, DeleteArgs);
- }
- };
+ assert(AI == AE && "unexpected usual deallocation function parameter");
+ return {PassSize, PassAlignment};
+}
- /// A cleanup to call the given 'operator delete' function upon
- /// abnormal exit from a new expression when the new expression is
- /// conditional.
- class CallDeleteDuringConditionalNew final : public EHScopeStack::Cleanup {
- size_t NumPlacementArgs;
+namespace {
+ /// A cleanup to call the given 'operator delete' function upon abnormal
+ /// exit from a new expression. Templated on a traits type that deals with
+ /// ensuring that the arguments dominate the cleanup if necessary.
+ template<typename Traits>
+ class CallDeleteDuringNew final : public EHScopeStack::Cleanup {
+ /// Type used to hold llvm::Value*s.
+ typedef typename Traits::ValueTy ValueTy;
+ /// Type used to hold RValues.
+ typedef typename Traits::RValueTy RValueTy;
+ struct PlacementArg {
+ RValueTy ArgValue;
+ QualType ArgType;
+ };
+
+ unsigned NumPlacementArgs : 31;
+ unsigned PassAlignmentToPlacementDelete : 1;
const FunctionDecl *OperatorDelete;
- DominatingValue<RValue>::saved_type Ptr;
- DominatingValue<RValue>::saved_type AllocSize;
+ ValueTy Ptr;
+ ValueTy AllocSize;
+ CharUnits AllocAlign;
- DominatingValue<RValue>::saved_type *getPlacementArgs() {
- return reinterpret_cast<DominatingValue<RValue>::saved_type*>(this+1);
+ PlacementArg *getPlacementArgs() {
+ return reinterpret_cast<PlacementArg *>(this + 1);
}
public:
static size_t getExtraSize(size_t NumPlacementArgs) {
- return NumPlacementArgs * sizeof(DominatingValue<RValue>::saved_type);
+ return NumPlacementArgs * sizeof(PlacementArg);
}
- CallDeleteDuringConditionalNew(size_t NumPlacementArgs,
- const FunctionDecl *OperatorDelete,
- DominatingValue<RValue>::saved_type Ptr,
- DominatingValue<RValue>::saved_type AllocSize)
- : NumPlacementArgs(NumPlacementArgs), OperatorDelete(OperatorDelete),
- Ptr(Ptr), AllocSize(AllocSize) {}
-
- void setPlacementArg(unsigned I, DominatingValue<RValue>::saved_type Arg) {
+ CallDeleteDuringNew(size_t NumPlacementArgs,
+ const FunctionDecl *OperatorDelete, ValueTy Ptr,
+ ValueTy AllocSize, bool PassAlignmentToPlacementDelete,
+ CharUnits AllocAlign)
+ : NumPlacementArgs(NumPlacementArgs),
+ PassAlignmentToPlacementDelete(PassAlignmentToPlacementDelete),
+ OperatorDelete(OperatorDelete), Ptr(Ptr), AllocSize(AllocSize),
+ AllocAlign(AllocAlign) {}
+
+ void setPlacementArg(unsigned I, RValueTy Arg, QualType Type) {
assert(I < NumPlacementArgs && "index out of range");
- getPlacementArgs()[I] = Arg;
+ getPlacementArgs()[I] = {Arg, Type};
}
void Emit(CodeGenFunction &CGF, Flags flags) override {
- const FunctionProtoType *FPT
- = OperatorDelete->getType()->getAs<FunctionProtoType>();
- assert(FPT->getNumParams() == NumPlacementArgs + 1 ||
- (FPT->getNumParams() == 2 && NumPlacementArgs == 0));
-
+ const FunctionProtoType *FPT =
+ OperatorDelete->getType()->getAs<FunctionProtoType>();
CallArgList DeleteArgs;
// The first argument is always a void*.
- FunctionProtoType::param_type_iterator AI = FPT->param_type_begin();
- DeleteArgs.add(Ptr.restore(CGF), *AI++);
-
- // A member 'operator delete' can take an extra 'size_t' argument.
- if (FPT->getNumParams() == NumPlacementArgs + 2) {
- RValue RV = AllocSize.restore(CGF);
- DeleteArgs.add(RV, *AI++);
+ DeleteArgs.add(Traits::get(CGF, Ptr), FPT->getParamType(0));
+
+ // Figure out what other parameters we should be implicitly passing.
+ bool PassSize = false;
+ bool PassAlignment = false;
+ if (NumPlacementArgs) {
+ // A placement deallocation function is implicitly passed an alignment
+ // if the placement allocation function was, but is never passed a size.
+ PassAlignment = PassAlignmentToPlacementDelete;
+ } else {
+ // For a non-placement new-expression, 'operator delete' can take a
+ // size and/or an alignment if it has the right parameters.
+ std::tie(PassSize, PassAlignment) =
+ shouldPassSizeAndAlignToUsualDelete(FPT);
}
+ // The second argument can be a std::size_t (for non-placement delete).
+ if (PassSize)
+ DeleteArgs.add(Traits::get(CGF, AllocSize),
+ CGF.getContext().getSizeType());
+
+ // The next (second or third) argument can be a std::align_val_t, which
+ // is an enum whose underlying type is std::size_t.
+ // FIXME: Use the right type as the parameter type. Note that in a call
+ // to operator delete(size_t, ...), we may not have it available.
+ if (PassAlignment)
+ DeleteArgs.add(RValue::get(llvm::ConstantInt::get(
+ CGF.SizeTy, AllocAlign.getQuantity())),
+ CGF.getContext().getSizeType());
+
// Pass the rest of the arguments, which must match exactly.
for (unsigned I = 0; I != NumPlacementArgs; ++I) {
- RValue RV = getPlacementArgs()[I].restore(CGF);
- DeleteArgs.add(RV, *AI++);
+ auto Arg = getPlacementArgs()[I];
+ DeleteArgs.add(Traits::get(CGF, Arg.ArgValue), Arg.ArgType);
}
// Call 'operator delete'.
@@ -1278,18 +1409,34 @@ static void EnterNewDeleteCleanup(CodeGenFunction &CGF,
const CXXNewExpr *E,
Address NewPtr,
llvm::Value *AllocSize,
+ CharUnits AllocAlign,
const CallArgList &NewArgs) {
+ unsigned NumNonPlacementArgs = E->passAlignment() ? 2 : 1;
+
// If we're not inside a conditional branch, then the cleanup will
// dominate and we can do the easier (and more efficient) thing.
if (!CGF.isInConditionalBranch()) {
- CallDeleteDuringNew *Cleanup = CGF.EHStack
- .pushCleanupWithExtra<CallDeleteDuringNew>(EHCleanup,
- E->getNumPlacementArgs(),
- E->getOperatorDelete(),
- NewPtr.getPointer(),
- AllocSize);
- for (unsigned I = 0, N = E->getNumPlacementArgs(); I != N; ++I)
- Cleanup->setPlacementArg(I, NewArgs[I+1].RV);
+ struct DirectCleanupTraits {
+ typedef llvm::Value *ValueTy;
+ typedef RValue RValueTy;
+ static RValue get(CodeGenFunction &, ValueTy V) { return RValue::get(V); }
+ static RValue get(CodeGenFunction &, RValueTy V) { return V; }
+ };
+
+ typedef CallDeleteDuringNew<DirectCleanupTraits> DirectCleanup;
+
+ DirectCleanup *Cleanup = CGF.EHStack
+ .pushCleanupWithExtra<DirectCleanup>(EHCleanup,
+ E->getNumPlacementArgs(),
+ E->getOperatorDelete(),
+ NewPtr.getPointer(),
+ AllocSize,
+ E->passAlignment(),
+ AllocAlign);
+ for (unsigned I = 0, N = E->getNumPlacementArgs(); I != N; ++I) {
+ auto &Arg = NewArgs[I + NumNonPlacementArgs];
+ Cleanup->setPlacementArg(I, Arg.RV, Arg.Ty);
+ }
return;
}
@@ -1300,15 +1447,28 @@ static void EnterNewDeleteCleanup(CodeGenFunction &CGF,
DominatingValue<RValue>::saved_type SavedAllocSize =
DominatingValue<RValue>::save(CGF, RValue::get(AllocSize));
- CallDeleteDuringConditionalNew *Cleanup = CGF.EHStack
- .pushCleanupWithExtra<CallDeleteDuringConditionalNew>(EHCleanup,
- E->getNumPlacementArgs(),
- E->getOperatorDelete(),
- SavedNewPtr,
- SavedAllocSize);
- for (unsigned I = 0, N = E->getNumPlacementArgs(); I != N; ++I)
- Cleanup->setPlacementArg(I,
- DominatingValue<RValue>::save(CGF, NewArgs[I+1].RV));
+ struct ConditionalCleanupTraits {
+ typedef DominatingValue<RValue>::saved_type ValueTy;
+ typedef DominatingValue<RValue>::saved_type RValueTy;
+ static RValue get(CodeGenFunction &CGF, ValueTy V) {
+ return V.restore(CGF);
+ }
+ };
+ typedef CallDeleteDuringNew<ConditionalCleanupTraits> ConditionalCleanup;
+
+ ConditionalCleanup *Cleanup = CGF.EHStack
+ .pushCleanupWithExtra<ConditionalCleanup>(EHCleanup,
+ E->getNumPlacementArgs(),
+ E->getOperatorDelete(),
+ SavedNewPtr,
+ SavedAllocSize,
+ E->passAlignment(),
+ 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);
+ }
CGF.initFullExprCleanup();
}
@@ -1323,7 +1483,12 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
// If there is a brace-initializer, cannot allocate fewer elements than inits.
unsigned minElements = 0;
if (E->isArray() && E->hasInitializer()) {
- if (const InitListExpr *ILE = dyn_cast<InitListExpr>(E->getInitializer()))
+ const InitListExpr *ILE = dyn_cast<InitListExpr>(E->getInitializer());
+ if (ILE && ILE->isStringLiteralInit())
+ minElements =
+ cast<ConstantArrayType>(ILE->getType()->getAsArrayTypeUnsafe())
+ ->getSize().getZExtValue();
+ else if (ILE)
minElements = ILE->getNumInits();
}
@@ -1332,6 +1497,7 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
llvm::Value *allocSize =
EmitCXXNewAllocSize(*this, E, minElements, numElements,
allocSizeWithoutCookie);
+ CharUnits allocAlign = getContext().getTypeAlignInChars(allocType);
// Emit the allocation call. If the allocator is a global placement
// operator, just "inline" it directly.
@@ -1347,10 +1513,8 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
// The pointer expression will, in many cases, be an opaque void*.
// In these cases, discard the computed alignment and use the
// formal alignment of the allocated type.
- if (alignSource != AlignmentSource::Decl) {
- allocation = Address(allocation.getPointer(),
- getContext().getTypeAlignInChars(allocType));
- }
+ if (alignSource != AlignmentSource::Decl)
+ allocation = Address(allocation.getPointer(), allocAlign);
// Set up allocatorArgs for the call to operator delete if it's not
// the reserved global operator.
@@ -1363,28 +1527,55 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
} else {
const FunctionProtoType *allocatorType =
allocator->getType()->castAs<FunctionProtoType>();
+ unsigned ParamsToSkip = 0;
// The allocation size is the first argument.
QualType sizeType = getContext().getSizeType();
allocatorArgs.add(RValue::get(allocSize), sizeType);
+ ++ParamsToSkip;
+
+ if (allocSize != allocSizeWithoutCookie) {
+ CharUnits cookieAlign = getSizeAlign(); // FIXME: Ask the ABI.
+ allocAlign = std::max(allocAlign, cookieAlign);
+ }
+
+ // The allocation alignment may be passed as the second argument.
+ if (E->passAlignment()) {
+ QualType AlignValT = sizeType;
+ if (allocatorType->getNumParams() > 1) {
+ AlignValT = allocatorType->getParamType(1);
+ assert(getContext().hasSameUnqualifiedType(
+ AlignValT->castAs<EnumType>()->getDecl()->getIntegerType(),
+ sizeType) &&
+ "wrong type for alignment parameter");
+ ++ParamsToSkip;
+ } else {
+ // Corner case, passing alignment to 'operator new(size_t, ...)'.
+ assert(allocator->isVariadic() && "can't pass alignment to allocator");
+ }
+ allocatorArgs.add(
+ RValue::get(llvm::ConstantInt::get(SizeTy, allocAlign.getQuantity())),
+ AlignValT);
+ }
- // We start at 1 here because the first argument (the allocation size)
- // has already been emitted.
+ // FIXME: Why do we not pass a CalleeDecl here?
EmitCallArgs(allocatorArgs, allocatorType, E->placement_arguments(),
- /* CalleeDecl */ nullptr,
- /*ParamsToSkip*/ 1);
+ /*CalleeDecl*/nullptr, /*ParamsToSkip*/ParamsToSkip);
RValue RV =
EmitNewDeleteCall(*this, allocator, allocatorType, allocatorArgs);
- // For now, only assume that the allocation function returns
- // something satisfactorily aligned for the element type, plus
- // the cookie if we have one.
- CharUnits allocationAlign =
- getContext().getTypeAlignInChars(allocType);
- if (allocSize != allocSizeWithoutCookie) {
- CharUnits cookieAlign = getSizeAlign(); // FIXME?
- allocationAlign = std::max(allocationAlign, cookieAlign);
+ // If this was a call to a global replaceable allocation function that does
+ // not take an alignment argument, the allocator is known to produce
+ // storage that's suitably aligned for any object that fits, up to a known
+ // threshold. Otherwise assume it's suitably aligned for the allocated type.
+ CharUnits allocationAlign = allocAlign;
+ if (!E->passAlignment() &&
+ allocator->isReplaceableGlobalAllocationFunction()) {
+ unsigned AllocatorAlign = llvm::PowerOf2Floor(std::min<uint64_t>(
+ Target.getNewAlign(), getContext().getTypeSize(allocType)));
+ allocationAlign = std::max(
+ allocationAlign, getContext().toCharUnitsFromBits(AllocatorAlign));
}
allocation = Address(RV.getScalarVal(), allocationAlign);
@@ -1423,7 +1614,8 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
llvm::Instruction *cleanupDominator = nullptr;
if (E->getOperatorDelete() &&
!E->getOperatorDelete()->isReservedGlobalPlacementOperator()) {
- EnterNewDeleteCleanup(*this, E, allocation, allocSize, allocatorArgs);
+ EnterNewDeleteCleanup(*this, E, allocation, allocSize, allocAlign,
+ allocatorArgs);
operatorDeleteCleanup = EHStack.stable_begin();
cleanupDominator = Builder.CreateUnreachable();
}
@@ -1485,31 +1677,58 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
}
void CodeGenFunction::EmitDeleteCall(const FunctionDecl *DeleteFD,
- llvm::Value *Ptr,
- QualType DeleteTy) {
- assert(DeleteFD->getOverloadedOperator() == OO_Delete);
+ llvm::Value *Ptr, QualType DeleteTy,
+ llvm::Value *NumElements,
+ CharUnits CookieSize) {
+ assert((!NumElements && CookieSize.isZero()) ||
+ DeleteFD->getOverloadedOperator() == OO_Array_Delete);
const FunctionProtoType *DeleteFTy =
DeleteFD->getType()->getAs<FunctionProtoType>();
CallArgList DeleteArgs;
- // Check if we need to pass the size to the delete operator.
- llvm::Value *Size = nullptr;
- QualType SizeTy;
- if (DeleteFTy->getNumParams() == 2) {
- SizeTy = DeleteFTy->getParamType(1);
- CharUnits DeleteTypeSize = getContext().getTypeSizeInChars(DeleteTy);
- Size = llvm::ConstantInt::get(ConvertType(SizeTy),
- DeleteTypeSize.getQuantity());
- }
+ std::pair<bool, bool> PassSizeAndAlign =
+ shouldPassSizeAndAlignToUsualDelete(DeleteFTy);
+
+ auto ParamTypeIt = DeleteFTy->param_type_begin();
- QualType ArgTy = DeleteFTy->getParamType(0);
+ // Pass the pointer itself.
+ QualType ArgTy = *ParamTypeIt++;
llvm::Value *DeletePtr = Builder.CreateBitCast(Ptr, ConvertType(ArgTy));
DeleteArgs.add(RValue::get(DeletePtr), ArgTy);
- if (Size)
- DeleteArgs.add(RValue::get(Size), SizeTy);
+ // Pass the size if the delete function has a size_t parameter.
+ if (PassSizeAndAlign.first) {
+ QualType SizeType = *ParamTypeIt++;
+ CharUnits DeleteTypeSize = getContext().getTypeSizeInChars(DeleteTy);
+ llvm::Value *Size = llvm::ConstantInt::get(ConvertType(SizeType),
+ DeleteTypeSize.getQuantity());
+
+ // For array new, multiply by the number of elements.
+ if (NumElements)
+ Size = Builder.CreateMul(Size, NumElements);
+
+ // If there is a cookie, add the cookie size.
+ if (!CookieSize.isZero())
+ Size = Builder.CreateAdd(
+ Size, llvm::ConstantInt::get(SizeTy, CookieSize.getQuantity()));
+
+ DeleteArgs.add(RValue::get(Size), SizeType);
+ }
+
+ // Pass the alignment if the delete function has an align_val_t parameter.
+ if (PassSizeAndAlign.second) {
+ QualType AlignValType = *ParamTypeIt++;
+ CharUnits DeleteTypeAlign = getContext().toCharUnitsFromBits(
+ getContext().getTypeAlignIfKnown(DeleteTy));
+ llvm::Value *Align = llvm::ConstantInt::get(ConvertType(AlignValType),
+ DeleteTypeAlign.getQuantity());
+ DeleteArgs.add(RValue::get(Align), AlignValType);
+ }
+
+ assert(ParamTypeIt == DeleteFTy->param_type_end() &&
+ "unknown parameter to usual delete function");
// Emit the call to delete.
EmitNewDeleteCall(*this, DeleteFD, DeleteFTy, DeleteArgs);
@@ -1546,6 +1765,15 @@ static void EmitObjectDelete(CodeGenFunction &CGF,
const CXXDeleteExpr *DE,
Address Ptr,
QualType ElementType) {
+ // C++11 [expr.delete]p3:
+ // If the static type of the object to be deleted is different from its
+ // dynamic type, the static type shall be a base class of the dynamic type
+ // of the object to be deleted and the static type shall have a virtual
+ // destructor or the behavior is undefined.
+ CGF.EmitTypeCheck(CodeGenFunction::TCK_MemberCall,
+ DE->getExprLoc(), Ptr.getPointer(),
+ ElementType);
+
// Find the destructor for the type, if applicable. If the
// destructor is virtual, we'll just emit the vcall and return.
const CXXDestructorDecl *Dtor = nullptr;
@@ -1613,45 +1841,8 @@ namespace {
ElementType(ElementType), CookieSize(CookieSize) {}
void Emit(CodeGenFunction &CGF, Flags flags) override {
- const FunctionProtoType *DeleteFTy =
- OperatorDelete->getType()->getAs<FunctionProtoType>();
- assert(DeleteFTy->getNumParams() == 1 || DeleteFTy->getNumParams() == 2);
-
- CallArgList Args;
-
- // Pass the pointer as the first argument.
- QualType VoidPtrTy = DeleteFTy->getParamType(0);
- llvm::Value *DeletePtr
- = CGF.Builder.CreateBitCast(Ptr, CGF.ConvertType(VoidPtrTy));
- Args.add(RValue::get(DeletePtr), VoidPtrTy);
-
- // Pass the original requested size as the second argument.
- if (DeleteFTy->getNumParams() == 2) {
- QualType size_t = DeleteFTy->getParamType(1);
- llvm::IntegerType *SizeTy
- = cast<llvm::IntegerType>(CGF.ConvertType(size_t));
-
- CharUnits ElementTypeSize =
- CGF.CGM.getContext().getTypeSizeInChars(ElementType);
-
- // The size of an element, multiplied by the number of elements.
- llvm::Value *Size
- = llvm::ConstantInt::get(SizeTy, ElementTypeSize.getQuantity());
- if (NumElements)
- Size = CGF.Builder.CreateMul(Size, NumElements);
-
- // Plus the size of the cookie if applicable.
- if (!CookieSize.isZero()) {
- llvm::Value *CookieSizeV
- = llvm::ConstantInt::get(SizeTy, CookieSize.getQuantity());
- Size = CGF.Builder.CreateAdd(Size, CookieSizeV);
- }
-
- Args.add(RValue::get(Size), size_t);
- }
-
- // Emit the call to delete.
- EmitNewDeleteCall(CGF, OperatorDelete, DeleteFTy, Args);
+ CGF.EmitDeleteCall(OperatorDelete, Ptr, ElementType, NumElements,
+ CookieSize);
}
};
}
@@ -1949,10 +2140,7 @@ void CodeGenFunction::EmitLambdaExpr(const LambdaExpr *E, AggValueSlot Slot) {
auto VAT = CurField->getCapturedVLAType();
EmitStoreThroughLValue(RValue::get(VLASizeMap[VAT->getSizeExpr()]), LV);
} else {
- ArrayRef<VarDecl *> ArrayIndexes;
- if (CurField->getType()->isArrayType())
- ArrayIndexes = E->getCaptureInitIndexVars(i);
- EmitInitializerForField(*CurField, LV, *i, ArrayIndexes);
+ EmitInitializerForField(*CurField, LV, *i);
}
}
}
diff --git a/lib/CodeGen/CGExprComplex.cpp b/lib/CodeGen/CGExprComplex.cpp
index 22910d931ded..59bc9cdbc056 100644
--- a/lib/CodeGen/CGExprComplex.cpp
+++ b/lib/CodeGen/CGExprComplex.cpp
@@ -13,12 +13,9 @@
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
-#include "clang/AST/ASTContext.h"
#include "clang/AST/StmtVisitor.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallString.h"
#include "llvm/IR/Constants.h"
-#include "llvm/IR/Function.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/Metadata.h"
@@ -483,7 +480,9 @@ ComplexPairTy ComplexExprEmitter::EmitCast(CastKind CK, Expr *Op,
case CK_CopyAndAutoreleaseBlockObject:
case CK_BuiltinFnToFnPtr:
case CK_ZeroToOCLEvent:
+ case CK_ZeroToOCLQueue:
case CK_AddressSpaceConversion:
+ case CK_IntToOCLSampler:
llvm_unreachable("invalid cast kind for complex value");
case CK_FloatingRealToComplex:
@@ -600,10 +599,10 @@ ComplexPairTy ComplexExprEmitter::EmitComplexBinOpLibCall(StringRef LibCallName,
llvm::FunctionType *FTy = CGF.CGM.getTypes().GetFunctionType(FuncInfo);
llvm::Constant *Func = CGF.CGM.CreateBuiltinFunction(FTy, LibCallName);
- llvm::Instruction *Call;
+ CGCallee Callee = CGCallee::forDirect(Func, FQTy->getAs<FunctionProtoType>());
- RValue Res = CGF.EmitCall(FuncInfo, Func, ReturnValueSlot(), Args,
- FQTy->getAs<FunctionProtoType>(), &Call);
+ llvm::Instruction *Call;
+ RValue Res = CGF.EmitCall(FuncInfo, Callee, ReturnValueSlot(), Args, &Call);
cast<llvm::CallInst>(Call)->setCallingConv(CGF.CGM.getBuiltinCC());
return Res.getComplexVal();
}
diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp
index 803b39907dd7..3db15c646f43 100644
--- a/lib/CodeGen/CGExprConstant.cpp
+++ b/lib/CodeGen/CGExprConstant.cpp
@@ -16,6 +16,7 @@
#include "CGObjCRuntime.h"
#include "CGRecordLayout.h"
#include "CodeGenModule.h"
+#include "TargetInfo.h"
#include "clang/AST/APValue.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/RecordLayout.h"
@@ -690,6 +691,9 @@ public:
case CK_ConstructorConversion:
return C;
+ case CK_IntToOCLSampler:
+ llvm_unreachable("global sampler variables are not generated");
+
case CK_Dependent: llvm_unreachable("saw dependent cast!");
case CK_BuiltinFnToFnPtr:
@@ -749,6 +753,7 @@ public:
case CK_FloatingToBoolean:
case CK_FloatingCast:
case CK_ZeroToOCLEvent:
+ case CK_ZeroToOCLQueue:
return nullptr;
}
llvm_unreachable("Invalid CastKind");
@@ -775,9 +780,6 @@ public:
}
llvm::Constant *EmitArrayInitialization(InitListExpr *ILE) {
- if (ILE->isStringLiteralInit())
- return Visit(ILE->getInit(0));
-
llvm::ArrayType *AType =
cast<llvm::ArrayType>(ConvertType(ILE->getType()));
llvm::Type *ElemTy = AType->getElementType();
@@ -842,6 +844,9 @@ public:
}
llvm::Constant *VisitInitListExpr(InitListExpr *ILE) {
+ if (ILE->isTransparent())
+ return Visit(ILE->getInit(0));
+
if (ILE->getType()->isArrayType())
return EmitArrayInitialization(ILE);
@@ -1018,16 +1023,17 @@ public:
switch (E->getStmtClass()) {
default: break;
case Expr::CompoundLiteralExprClass: {
- // Note that due to the nature of compound literals, this is guaranteed
- // to be the only use of the variable, so we just generate it here.
CompoundLiteralExpr *CLE = cast<CompoundLiteralExpr>(E);
+ CharUnits Align = CGM.getContext().getTypeAlignInChars(E->getType());
+ if (llvm::GlobalVariable *Addr =
+ CGM.getAddrOfConstantCompoundLiteralIfEmitted(CLE))
+ return ConstantAddress(Addr, Align);
+
llvm::Constant* C = CGM.EmitConstantExpr(CLE->getInitializer(),
CLE->getType(), CGF);
// FIXME: "Leaked" on failure.
if (!C) return ConstantAddress::invalid();
- CharUnits Align = CGM.getContext().getTypeAlignInChars(E->getType());
-
auto GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(),
E->getType().isConstant(CGM.getContext()),
llvm::GlobalValue::InternalLinkage,
@@ -1035,6 +1041,7 @@ public:
llvm::GlobalVariable::NotThreadLocal,
CGM.getContext().getTargetAddressSpace(E->getType()));
GV->setAlignment(Align.getQuantity());
+ CGM.setAddrOfConstantCompoundLiteral(CLE, GV);
return ConstantAddress(GV, Align);
}
case Expr::StringLiteralClass:
@@ -1083,7 +1090,7 @@ public:
return CGM.GetAddrOfConstantCFString(Literal);
}
case Expr::BlockExprClass: {
- std::string FunctionName;
+ StringRef FunctionName;
if (CGF)
FunctionName = CGF->CurFn->getName();
else
@@ -1091,7 +1098,7 @@ public:
// This is not really an l-value.
llvm::Constant *Ptr =
- CGM.GetAddrOfGlobalBlock(cast<BlockExpr>(E), FunctionName.c_str());
+ CGM.GetAddrOfGlobalBlock(cast<BlockExpr>(E), FunctionName);
return ConstantAddress(Ptr, CGM.getPointerAlign());
}
case Expr::CXXTypeidExprClass: {
@@ -1259,6 +1266,10 @@ llvm::Constant *CodeGenModule::EmitConstantExpr(const Expr *E,
return C;
}
+llvm::Constant *CodeGenModule::getNullPointer(llvm::PointerType *T, QualType QT) {
+ return getTargetCodeGenInfo().getNullPointer(*this, T, QT);
+}
+
llvm::Constant *CodeGenModule::EmitConstantValue(const APValue &Value,
QualType DestType,
CodeGenFunction *CGF) {
@@ -1290,6 +1301,7 @@ llvm::Constant *CodeGenModule::EmitConstantValue(const APValue &Value,
llvm::ConstantInt::get(Int64Ty, Value.getLValueOffset().getQuantity());
llvm::Constant *C = nullptr;
+
if (APValue::LValueBase LVBase = Value.getLValueBase()) {
// An array can be represented as an lvalue referring to the base.
if (isa<llvm::ArrayType>(DestTy)) {
@@ -1320,7 +1332,9 @@ llvm::Constant *CodeGenModule::EmitConstantValue(const APValue &Value,
// Convert to the appropriate type; this could be an lvalue for
// an integer.
- if (isa<llvm::PointerType>(DestTy)) {
+ if (auto PT = dyn_cast<llvm::PointerType>(DestTy)) {
+ if (Value.isNullPointer())
+ return getNullPointer(PT, DestType);
// Convert the integer to a pointer-sized integer before converting it
// to a pointer.
C = llvm::ConstantExpr::getIntegerCast(
@@ -1354,7 +1368,7 @@ llvm::Constant *CodeGenModule::EmitConstantValue(const APValue &Value,
}
case APValue::Float: {
const llvm::APFloat &Init = Value.getFloat();
- if (&Init.getSemantics() == &llvm::APFloat::IEEEhalf &&
+ if (&Init.getSemantics() == &llvm::APFloat::IEEEhalf() &&
!Context.getLangOpts().NativeHalfType &&
!Context.getLangOpts().HalfArgsAndReturns)
return llvm::ConstantInt::get(VMContext, Init.bitcastToAPInt());
@@ -1480,6 +1494,18 @@ CodeGenModule::EmitConstantValueForMemory(const APValue &Value,
return C;
}
+llvm::GlobalVariable *CodeGenModule::getAddrOfConstantCompoundLiteralIfEmitted(
+ const CompoundLiteralExpr *E) {
+ return EmittedCompoundLiterals.lookup(E);
+}
+
+void CodeGenModule::setAddrOfConstantCompoundLiteral(
+ const CompoundLiteralExpr *CLE, llvm::GlobalVariable *GV) {
+ bool Ok = EmittedCompoundLiterals.insert(std::make_pair(CLE, GV)).second;
+ (void)Ok;
+ assert(Ok && "CLE has already been emitted!");
+}
+
ConstantAddress
CodeGenModule::GetAddrOfConstantCompoundLiteral(const CompoundLiteralExpr *E) {
assert(E->isFileScope() && "not a file-scope compound literal expr");
@@ -1507,7 +1533,7 @@ static llvm::Constant *EmitNullConstantForBase(CodeGenModule &CGM,
const CXXRecordDecl *base);
static llvm::Constant *EmitNullConstant(CodeGenModule &CGM,
- const CXXRecordDecl *record,
+ const RecordDecl *record,
bool asCompleteObject) {
const CGRecordLayout &layout = CGM.getTypes().getCGRecordLayout(record);
llvm::StructType *structure =
@@ -1517,24 +1543,29 @@ static llvm::Constant *EmitNullConstant(CodeGenModule &CGM,
unsigned numElements = structure->getNumElements();
std::vector<llvm::Constant *> elements(numElements);
+ auto CXXR = dyn_cast<CXXRecordDecl>(record);
// Fill in all the bases.
- for (const auto &I : record->bases()) {
- if (I.isVirtual()) {
- // Ignore virtual bases; if we're laying out for a complete
- // object, we'll lay these out later.
- continue;
- }
+ if (CXXR) {
+ for (const auto &I : CXXR->bases()) {
+ if (I.isVirtual()) {
+ // Ignore virtual bases; if we're laying out for a complete
+ // object, we'll lay these out later.
+ continue;
+ }
- const CXXRecordDecl *base =
- cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl());
+ const CXXRecordDecl *base =
+ cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl());
- // Ignore empty bases.
- if (base->isEmpty())
- continue;
-
- unsigned fieldIndex = layout.getNonVirtualBaseLLVMFieldNo(base);
- llvm::Type *baseType = structure->getElementType(fieldIndex);
- elements[fieldIndex] = EmitNullConstantForBase(CGM, baseType, base);
+ // Ignore empty bases.
+ if (base->isEmpty() ||
+ CGM.getContext().getASTRecordLayout(base).getNonVirtualSize()
+ .isZero())
+ continue;
+
+ unsigned fieldIndex = layout.getNonVirtualBaseLLVMFieldNo(base);
+ llvm::Type *baseType = structure->getElementType(fieldIndex);
+ elements[fieldIndex] = EmitNullConstantForBase(CGM, baseType, base);
+ }
}
// Fill in all the fields.
@@ -1558,8 +1589,8 @@ static llvm::Constant *EmitNullConstant(CodeGenModule &CGM,
}
// Fill in the virtual bases, if we're working with the complete object.
- if (asCompleteObject) {
- for (const auto &I : record->vbases()) {
+ if (CXXR && asCompleteObject) {
+ for (const auto &I : CXXR->vbases()) {
const CXXRecordDecl *base =
cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl());
@@ -1601,6 +1632,10 @@ static llvm::Constant *EmitNullConstantForBase(CodeGenModule &CGM,
}
llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) {
+ if (T->getAs<PointerType>())
+ return getNullPointer(
+ cast<llvm::PointerType>(getTypes().ConvertTypeForMem(T)), T);
+
if (getTypes().isZeroInitializable(T))
return llvm::Constant::getNullValue(getTypes().ConvertTypeForMem(T));
@@ -1616,10 +1651,8 @@ llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) {
return llvm::ConstantArray::get(ATy, Array);
}
- if (const RecordType *RT = T->getAs<RecordType>()) {
- const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
- return ::EmitNullConstant(*this, RD, /*complete object*/ true);
- }
+ if (const RecordType *RT = T->getAs<RecordType>())
+ return ::EmitNullConstant(*this, RT->getDecl(), /*complete object*/ true);
assert(T->isMemberDataPointerType() &&
"Should only see pointers to data members here!");
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp
index 120dacfbb011..1b85c45cd4be 100644
--- a/lib/CodeGen/CGExprScalar.cpp
+++ b/lib/CodeGen/CGExprScalar.cpp
@@ -19,6 +19,7 @@
#include "TargetInfo.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Expr.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Basic/TargetInfo.h"
@@ -171,9 +172,9 @@ public:
}
/// EmitPointerToBoolConversion - Perform a pointer to boolean conversion.
- Value *EmitPointerToBoolConversion(Value *V) {
- Value *Zero = llvm::ConstantPointerNull::get(
- cast<llvm::PointerType>(V->getType()));
+ Value *EmitPointerToBoolConversion(Value *V, QualType QT) {
+ Value *Zero = CGF.CGM.getNullPointer(cast<llvm::PointerType>(V->getType()), QT);
+
return Builder.CreateICmpNE(V, Zero, "tobool");
}
@@ -310,6 +311,12 @@ public:
Value *VisitInitListExpr(InitListExpr *E);
+ Value *VisitArrayInitIndexExpr(ArrayInitIndexExpr *E) {
+ assert(CGF.getArrayInitIndex() &&
+ "ArrayInitIndexExpr not inside an ArrayInitLoopExpr?");
+ return CGF.getArrayInitIndex();
+ }
+
Value *VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) {
return EmitNullValue(E->getType());
}
@@ -591,7 +598,7 @@ Value *ScalarExprEmitter::EmitConversionToBool(Value *Src, QualType SrcType) {
return EmitIntToBoolConversion(Src);
assert(isa<llvm::PointerType>(Src->getType()));
- return EmitPointerToBoolConversion(Src);
+ return EmitPointerToBoolConversion(Src, SrcType);
}
void ScalarExprEmitter::EmitFloatConversionCheck(
@@ -724,7 +731,7 @@ void ScalarExprEmitter::EmitFloatConversionCheck(
CGF.EmitCheckTypeDescriptor(OrigSrcType),
CGF.EmitCheckTypeDescriptor(DstType)};
CGF.EmitCheck(std::make_pair(Check, SanitizerKind::FloatCastOverflow),
- "float_cast_overflow", StaticArgs, OrigSrc);
+ SanitizerHandler::FloatCastOverflow, StaticArgs, OrigSrc);
}
/// Emit a conversion from the specified type to the specified destination type,
@@ -787,7 +794,7 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
// Handle pointer conversions next: pointers can only be converted to/from
// other pointers and integers. Check for pointer types in terms of LLVM, as
// some native types (like Obj-C id) may map to a pointer type.
- if (isa<llvm::PointerType>(DstTy)) {
+ if (auto DstPT = dyn_cast<llvm::PointerType>(DstTy)) {
// The source value may be an integer, or a pointer.
if (isa<llvm::PointerType>(SrcTy))
return Builder.CreateBitCast(Src, DstTy, "conv");
@@ -795,7 +802,7 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
assert(SrcType->isIntegerType() && "Not ptr->ptr or int->ptr conversion?");
// First, convert to the correct width so that we control the kind of
// extension.
- llvm::Type *MiddleTy = CGF.IntPtrTy;
+ llvm::Type *MiddleTy = CGF.CGM.getDataLayout().getIntPtrType(DstPT);
bool InputSigned = SrcType->isSignedIntegerOrEnumerationType();
llvm::Value* IntResult =
Builder.CreateIntCast(Src, MiddleTy, InputSigned, "conv");
@@ -927,7 +934,7 @@ Value *ScalarExprEmitter::EmitNullValue(QualType Ty) {
void ScalarExprEmitter::EmitBinOpCheck(
ArrayRef<std::pair<Value *, SanitizerMask>> Checks, const BinOpInfo &Info) {
assert(CGF.IsSanitizerScope);
- StringRef CheckName;
+ SanitizerHandler Check;
SmallVector<llvm::Constant *, 4> StaticData;
SmallVector<llvm::Value *, 2> DynamicData;
@@ -938,13 +945,13 @@ void ScalarExprEmitter::EmitBinOpCheck(
StaticData.push_back(CGF.EmitCheckSourceLocation(Info.E->getExprLoc()));
const UnaryOperator *UO = dyn_cast<UnaryOperator>(Info.E);
if (UO && UO->getOpcode() == UO_Minus) {
- CheckName = "negate_overflow";
+ Check = SanitizerHandler::NegateOverflow;
StaticData.push_back(CGF.EmitCheckTypeDescriptor(UO->getType()));
DynamicData.push_back(Info.RHS);
} else {
if (BinaryOperator::isShiftOp(Opcode)) {
// Shift LHS negative or too large, or RHS out of bounds.
- CheckName = "shift_out_of_bounds";
+ Check = SanitizerHandler::ShiftOutOfBounds;
const BinaryOperator *BO = cast<BinaryOperator>(Info.E);
StaticData.push_back(
CGF.EmitCheckTypeDescriptor(BO->getLHS()->getType()));
@@ -952,14 +959,14 @@ void ScalarExprEmitter::EmitBinOpCheck(
CGF.EmitCheckTypeDescriptor(BO->getRHS()->getType()));
} else if (Opcode == BO_Div || Opcode == BO_Rem) {
// Divide or modulo by zero, or signed overflow (eg INT_MAX / -1).
- CheckName = "divrem_overflow";
+ Check = SanitizerHandler::DivremOverflow;
StaticData.push_back(CGF.EmitCheckTypeDescriptor(Info.Ty));
} else {
// Arithmetic overflow (+, -, *).
switch (Opcode) {
- case BO_Add: CheckName = "add_overflow"; break;
- case BO_Sub: CheckName = "sub_overflow"; break;
- case BO_Mul: CheckName = "mul_overflow"; break;
+ case BO_Add: Check = SanitizerHandler::AddOverflow; break;
+ case BO_Sub: Check = SanitizerHandler::SubOverflow; break;
+ case BO_Mul: Check = SanitizerHandler::MulOverflow; break;
default: llvm_unreachable("unexpected opcode for bin op check");
}
StaticData.push_back(CGF.EmitCheckTypeDescriptor(Info.Ty));
@@ -968,7 +975,7 @@ void ScalarExprEmitter::EmitBinOpCheck(
DynamicData.push_back(Info.RHS);
}
- CGF.EmitCheck(Checks, CheckName, StaticData, DynamicData);
+ CGF.EmitCheck(Checks, Check, StaticData, DynamicData);
}
//===----------------------------------------------------------------------===//
@@ -1394,11 +1401,23 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
return Builder.CreateBitCast(Src, DstTy);
}
case CK_AddressSpaceConversion: {
- Value *Src = Visit(const_cast<Expr*>(E));
+ Expr::EvalResult Result;
+ if (E->EvaluateAsRValue(Result, CGF.getContext()) &&
+ Result.Val.isNullPointer()) {
+ // If E has side effect, it is emitted even if its final result is a
+ // null pointer. In that case, a DCE pass should be able to
+ // eliminate the useless instructions emitted during translating E.
+ if (Result.HasSideEffects)
+ Visit(E);
+ return CGF.CGM.getNullPointer(cast<llvm::PointerType>(
+ ConvertType(DestTy)), DestTy);
+ }
// Since target may map different address spaces in AST to the same address
// space, an address space conversion may end up as a bitcast.
- return Builder.CreatePointerBitCastOrAddrSpaceCast(Src,
- ConvertType(DestTy));
+ auto *Src = Visit(E);
+ return CGF.CGM.getTargetCodeGenInfo().performAddrSpaceCast(CGF, Src,
+ E->getType(),
+ DestTy);
}
case CK_AtomicToNonAtomic:
case CK_NonAtomicToAtomic:
@@ -1453,8 +1472,8 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
if (MustVisitNullValue(E))
(void) Visit(E);
- return llvm::ConstantPointerNull::get(
- cast<llvm::PointerType>(ConvertType(DestTy)));
+ return CGF.CGM.getNullPointer(cast<llvm::PointerType>(ConvertType(DestTy)),
+ DestTy);
case CK_NullToMemberPointer: {
if (MustVisitNullValue(E))
@@ -1510,12 +1529,13 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
// First, convert to the correct width so that we control the kind of
// extension.
- llvm::Type *MiddleTy = CGF.IntPtrTy;
+ auto DestLLVMTy = ConvertType(DestTy);
+ llvm::Type *MiddleTy = CGF.CGM.getDataLayout().getIntPtrType(DestLLVMTy);
bool InputSigned = E->getType()->isSignedIntegerOrEnumerationType();
llvm::Value* IntResult =
Builder.CreateIntCast(Src, MiddleTy, InputSigned, "conv");
- return Builder.CreateIntToPtr(IntResult, ConvertType(DestTy));
+ return Builder.CreateIntToPtr(IntResult, DestLLVMTy);
}
case CK_PointerToIntegral:
assert(!DestTy->isBooleanType() && "bool should use PointerToBool");
@@ -1546,7 +1566,7 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
case CK_IntegralToBoolean:
return EmitIntToBoolConversion(Visit(E));
case CK_PointerToBoolean:
- return EmitPointerToBoolConversion(Visit(E));
+ return EmitPointerToBoolConversion(Visit(E), E->getType());
case CK_FloatingToBoolean:
return EmitFloatToBoolConversion(Visit(E));
case CK_MemberPointerToBoolean: {
@@ -1573,8 +1593,16 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
return llvm::Constant::getNullValue(ConvertType(DestTy));
}
+ case CK_ZeroToOCLQueue: {
+ assert(DestTy->isQueueT() && "CK_ZeroToOCLQueue cast on non queue_t type");
+ return llvm::Constant::getNullValue(ConvertType(DestTy));
}
+ case CK_IntToOCLSampler:
+ return CGF.CGM.createOpenCLIntToSamplerConversion(E, CGF);
+
+ } // end of switch
+
llvm_unreachable("unknown scalar cast");
}
@@ -2273,8 +2301,13 @@ Value *ScalarExprEmitter::EmitDiv(const BinOpInfo &Ops) {
if (Ops.LHS->getType()->isFPOrFPVectorTy()) {
llvm::Value *Val = Builder.CreateFDiv(Ops.LHS, Ops.RHS, "div");
- if (CGF.getLangOpts().OpenCL) {
- // OpenCL 1.1 7.4: minimum accuracy of single precision / is 2.5ulp
+ if (CGF.getLangOpts().OpenCL &&
+ !CGF.CGM.getCodeGenOpts().CorrectlyRoundedDivSqrt) {
+ // OpenCL v1.1 s7.4: minimum accuracy of single precision / is 2.5ulp
+ // OpenCL v1.2 s5.6.4.2: The -cl-fp32-correctly-rounded-divide-sqrt
+ // build option allows an application to specify that single precision
+ // floating-point divide (x/y and 1/x) and sqrt used in the program
+ // source are correctly rounded.
llvm::Type *ValTy = Val->getType();
if (ValTy->isFloatTy() ||
(isa<llvm::VectorType>(ValTy) &&
@@ -2363,9 +2396,8 @@ Value *ScalarExprEmitter::EmitOverflowCheckedBinOp(const BinOpInfo &Ops) {
// Branch in case of overflow.
llvm::BasicBlock *initialBB = Builder.GetInsertBlock();
- llvm::Function::iterator insertPt = initialBB->getIterator();
- llvm::BasicBlock *continueBB = CGF.createBasicBlock("nooverflow", CGF.CurFn,
- &*std::next(insertPt));
+ llvm::BasicBlock *continueBB =
+ CGF.createBasicBlock("nooverflow", CGF.CurFn, initialBB->getNextNode());
llvm::BasicBlock *overflowBB = CGF.createBasicBlock("overflow", CGF.CurFn);
Builder.CreateCondBr(overflow, overflowBB, continueBB);
@@ -2429,11 +2461,13 @@ static Value *emitPointerArithmetic(CodeGenFunction &CGF,
}
unsigned width = cast<llvm::IntegerType>(index->getType())->getBitWidth();
- if (width != CGF.PointerWidthInBits) {
+ auto &DL = CGF.CGM.getDataLayout();
+ auto PtrTy = cast<llvm::PointerType>(pointer->getType());
+ if (width != DL.getTypeSizeInBits(PtrTy)) {
// Zero-extend or sign-extend the pointer value according to
// whether the index is signed or not.
bool isSigned = indexOperand->getType()->isSignedIntegerOrEnumerationType();
- index = CGF.Builder.CreateIntCast(index, CGF.PtrDiffTy, isSigned,
+ index = CGF.Builder.CreateIntCast(index, DL.getIntPtrType(PtrTy), isSigned,
"idx.ext");
}
@@ -3397,6 +3431,52 @@ static Value *ConvertVec3AndVec4(CGBuilderTy &Builder, CodeGenFunction &CGF,
return Builder.CreateShuffleVector(Src, UnV, Mask);
}
+// Create cast instructions for converting LLVM value \p Src to LLVM type \p
+// DstTy. \p Src has the same size as \p DstTy. Both are single value types
+// but could be scalar or vectors of different lengths, and either can be
+// pointer.
+// There are 4 cases:
+// 1. non-pointer -> non-pointer : needs 1 bitcast
+// 2. pointer -> pointer : needs 1 bitcast or addrspacecast
+// 3. pointer -> non-pointer
+// a) pointer -> intptr_t : needs 1 ptrtoint
+// b) pointer -> non-intptr_t : needs 1 ptrtoint then 1 bitcast
+// 4. non-pointer -> pointer
+// a) intptr_t -> pointer : needs 1 inttoptr
+// b) non-intptr_t -> pointer : needs 1 bitcast then 1 inttoptr
+// Note: for cases 3b and 4b two casts are required since LLVM casts do not
+// allow casting directly between pointer types and non-integer non-pointer
+// types.
+static Value *createCastsForTypeOfSameSize(CGBuilderTy &Builder,
+ const llvm::DataLayout &DL,
+ Value *Src, llvm::Type *DstTy,
+ StringRef Name = "") {
+ auto SrcTy = Src->getType();
+
+ // Case 1.
+ if (!SrcTy->isPointerTy() && !DstTy->isPointerTy())
+ return Builder.CreateBitCast(Src, DstTy, Name);
+
+ // Case 2.
+ if (SrcTy->isPointerTy() && DstTy->isPointerTy())
+ return Builder.CreatePointerBitCastOrAddrSpaceCast(Src, DstTy, Name);
+
+ // Case 3.
+ if (SrcTy->isPointerTy() && !DstTy->isPointerTy()) {
+ // Case 3b.
+ if (!DstTy->isIntegerTy())
+ Src = Builder.CreatePtrToInt(Src, DL.getIntPtrType(SrcTy));
+ // Cases 3a and 3b.
+ return Builder.CreateBitOrPointerCast(Src, DstTy, Name);
+ }
+
+ // Case 4b.
+ if (!SrcTy->isIntegerTy())
+ Src = Builder.CreateBitCast(Src, DL.getIntPtrType(DstTy));
+ // Cases 4a and 4b.
+ return Builder.CreateIntToPtr(Src, DstTy, Name);
+}
+
Value *ScalarExprEmitter::VisitAsTypeExpr(AsTypeExpr *E) {
Value *Src = CGF.EmitScalarExpr(E->getSrcExpr());
llvm::Type *DstTy = ConvertType(E->getType());
@@ -3411,7 +3491,8 @@ Value *ScalarExprEmitter::VisitAsTypeExpr(AsTypeExpr *E) {
// vector to get a vec4, then a bitcast if the target type is different.
if (NumElementsSrc == 3 && NumElementsDst != 3) {
Src = ConvertVec3AndVec4(Builder, CGF, Src, 4);
- Src = Builder.CreateBitCast(Src, DstTy);
+ Src = createCastsForTypeOfSameSize(Builder, CGF.CGM.getDataLayout(), Src,
+ DstTy);
Src->setName("astype");
return Src;
}
@@ -3421,13 +3502,15 @@ Value *ScalarExprEmitter::VisitAsTypeExpr(AsTypeExpr *E) {
// get a vec3.
if (NumElementsSrc != 3 && NumElementsDst == 3) {
auto Vec4Ty = llvm::VectorType::get(DstTy->getVectorElementType(), 4);
- Src = Builder.CreateBitCast(Src, Vec4Ty);
+ Src = createCastsForTypeOfSameSize(Builder, CGF.CGM.getDataLayout(), Src,
+ Vec4Ty);
Src = ConvertVec3AndVec4(Builder, CGF, Src, 3);
Src->setName("astype");
return Src;
}
- return Builder.CreateBitCast(Src, DstTy, "astype");
+ return Src = createCastsForTypeOfSameSize(Builder, CGF.CGM.getDataLayout(),
+ Src, DstTy, "astype");
}
Value *ScalarExprEmitter::VisitAtomicExpr(AtomicExpr *E) {
diff --git a/lib/CodeGen/CGLoopInfo.cpp b/lib/CodeGen/CGLoopInfo.cpp
index 51474f16a018..28998ce8db44 100644
--- a/lib/CodeGen/CGLoopInfo.cpp
+++ b/lib/CodeGen/CGLoopInfo.cpp
@@ -20,14 +20,15 @@ using namespace clang::CodeGen;
using namespace llvm;
static MDNode *createMetadata(LLVMContext &Ctx, const LoopAttributes &Attrs,
- llvm::DebugLoc Location) {
+ const llvm::DebugLoc &StartLoc,
+ const llvm::DebugLoc &EndLoc) {
if (!Attrs.IsParallel && Attrs.VectorizeWidth == 0 &&
Attrs.InterleaveCount == 0 && Attrs.UnrollCount == 0 &&
Attrs.VectorizeEnable == LoopAttributes::Unspecified &&
Attrs.UnrollEnable == LoopAttributes::Unspecified &&
Attrs.DistributeEnable == LoopAttributes::Unspecified &&
- !Location)
+ !StartLoc && !EndLoc)
return nullptr;
SmallVector<Metadata *, 4> Args;
@@ -35,9 +36,14 @@ static MDNode *createMetadata(LLVMContext &Ctx, const LoopAttributes &Attrs,
auto TempNode = MDNode::getTemporary(Ctx, None);
Args.push_back(TempNode.get());
- // If we have a valid debug location for the loop, add it.
- if (Location)
- Args.push_back(Location.getAsMDNode());
+ // If we have a valid start debug location for the loop, add it.
+ if (StartLoc) {
+ Args.push_back(StartLoc.getAsMDNode());
+
+ // If we also have a valid end debug location for the loop, add it.
+ if (EndLoc)
+ Args.push_back(EndLoc.getAsMDNode());
+ }
// Setting vectorize.width
if (Attrs.VectorizeWidth > 0) {
@@ -112,23 +118,26 @@ void LoopAttributes::clear() {
UnrollCount = 0;
VectorizeEnable = LoopAttributes::Unspecified;
UnrollEnable = LoopAttributes::Unspecified;
+ DistributeEnable = LoopAttributes::Unspecified;
}
LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs,
- llvm::DebugLoc Location)
+ const llvm::DebugLoc &StartLoc, const llvm::DebugLoc &EndLoc)
: LoopID(nullptr), Header(Header), Attrs(Attrs) {
- LoopID = createMetadata(Header->getContext(), Attrs, Location);
+ LoopID = createMetadata(Header->getContext(), Attrs, StartLoc, EndLoc);
}
-void LoopInfoStack::push(BasicBlock *Header, llvm::DebugLoc Location) {
- Active.push_back(LoopInfo(Header, StagedAttrs, Location));
+void LoopInfoStack::push(BasicBlock *Header, const llvm::DebugLoc &StartLoc,
+ const llvm::DebugLoc &EndLoc) {
+ Active.push_back(LoopInfo(Header, StagedAttrs, StartLoc, EndLoc));
// Clear the attributes so nested loops do not inherit them.
StagedAttrs.clear();
}
void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
ArrayRef<const clang::Attr *> Attrs,
- llvm::DebugLoc Location) {
+ const llvm::DebugLoc &StartLoc,
+ const llvm::DebugLoc &EndLoc) {
// Identify loop hint attributes from Attrs.
for (const auto *Attr : Attrs) {
@@ -266,7 +275,7 @@ void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
}
/// Stage the attributes.
- push(Header, Location);
+ push(Header, StartLoc, EndLoc);
}
void LoopInfoStack::pop() {
diff --git a/lib/CodeGen/CGLoopInfo.h b/lib/CodeGen/CGLoopInfo.h
index a0111edde5de..15608c105dc7 100644
--- a/lib/CodeGen/CGLoopInfo.h
+++ b/lib/CodeGen/CGLoopInfo.h
@@ -16,7 +16,6 @@
#define LLVM_CLANG_LIB_CODEGEN_CGLOOPINFO_H
#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/Value.h"
@@ -68,7 +67,7 @@ class LoopInfo {
public:
/// \brief Construct a new LoopInfo for the loop with entry Header.
LoopInfo(llvm::BasicBlock *Header, const LoopAttributes &Attrs,
- llvm::DebugLoc Location);
+ const llvm::DebugLoc &StartLoc, const llvm::DebugLoc &EndLoc);
/// \brief Get the loop id metadata for this loop.
llvm::MDNode *getLoopID() const { return LoopID; }
@@ -100,14 +99,14 @@ public:
/// \brief Begin a new structured loop. The set of staged attributes will be
/// applied to the loop and then cleared.
- void push(llvm::BasicBlock *Header,
- llvm::DebugLoc Location = llvm::DebugLoc());
+ 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.
/// The staged attributes are applied to the loop and then cleared.
void push(llvm::BasicBlock *Header, clang::ASTContext &Ctx,
- llvm::ArrayRef<const Attr *> Attrs,
- llvm::DebugLoc Location = llvm::DebugLoc());
+ llvm::ArrayRef<const Attr *> Attrs, const llvm::DebugLoc &StartLoc,
+ const llvm::DebugLoc &EndLoc);
/// \brief End the current loop.
void pop();
diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp
index db894ce67470..932b8a129e6e 100644
--- a/lib/CodeGen/CGObjC.cpp
+++ b/lib/CodeGen/CGObjC.cpp
@@ -589,9 +589,10 @@ static void emitStructGetterCall(CodeGenFunction &CGF, ObjCIvarDecl *ivar,
args.add(RValue::get(CGF.Builder.getInt1(isAtomic)), Context.BoolTy);
args.add(RValue::get(CGF.Builder.getInt1(hasStrong)), Context.BoolTy);
- llvm::Value *fn = CGF.CGM.getObjCRuntime().GetGetStructFunction();
+ llvm::Constant *fn = CGF.CGM.getObjCRuntime().GetGetStructFunction();
+ CGCallee callee = CGCallee::forDirect(fn);
CGF.EmitCall(CGF.getTypes().arrangeBuiltinFunctionCall(Context.VoidTy, args),
- fn, ReturnValueSlot(), args);
+ callee, ReturnValueSlot(), args);
}
/// Determine whether the given architecture supports unaligned atomic
@@ -852,11 +853,12 @@ static void emitCPPObjectAtomicGetterCall(CodeGenFunction &CGF,
// Third argument is the helper function.
args.add(RValue::get(AtomicHelperFn), CGF.getContext().VoidPtrTy);
- llvm::Value *copyCppAtomicObjectFn =
+ llvm::Constant *copyCppAtomicObjectFn =
CGF.CGM.getObjCRuntime().GetCppAtomicObjectGetFunction();
+ CGCallee callee = CGCallee::forDirect(copyCppAtomicObjectFn);
CGF.EmitCall(
CGF.getTypes().arrangeBuiltinFunctionCall(CGF.getContext().VoidTy, args),
- copyCppAtomicObjectFn, ReturnValueSlot(), args);
+ callee, ReturnValueSlot(), args);
}
void
@@ -927,12 +929,13 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl,
}
case PropertyImplStrategy::GetSetProperty: {
- llvm::Value *getPropertyFn =
+ llvm::Constant *getPropertyFn =
CGM.getObjCRuntime().GetPropertyGetFunction();
if (!getPropertyFn) {
CGM.ErrorUnsupported(propImpl, "Obj-C getter requiring atomic copy");
return;
}
+ CGCallee callee = CGCallee::forDirect(getPropertyFn);
// Return (ivar-type) objc_getProperty((id) self, _cmd, offset, true).
// FIXME: Can't this be simpler? This might even be worse than the
@@ -955,8 +958,7 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl,
llvm::Instruction *CallInstruction;
RValue RV = EmitCall(
getTypes().arrangeBuiltinFunctionCall(propType, args),
- getPropertyFn, ReturnValueSlot(), args, CGCalleeInfo(),
- &CallInstruction);
+ callee, ReturnValueSlot(), args, &CallInstruction);
if (llvm::CallInst *call = dyn_cast<llvm::CallInst>(CallInstruction))
call->setTailCall();
@@ -1068,10 +1070,11 @@ static void emitStructSetterCall(CodeGenFunction &CGF, ObjCMethodDecl *OMD,
// FIXME: should this really always be false?
args.add(RValue::get(CGF.Builder.getFalse()), CGF.getContext().BoolTy);
- llvm::Value *copyStructFn = CGF.CGM.getObjCRuntime().GetSetStructFunction();
+ llvm::Constant *fn = CGF.CGM.getObjCRuntime().GetSetStructFunction();
+ CGCallee callee = CGCallee::forDirect(fn);
CGF.EmitCall(
CGF.getTypes().arrangeBuiltinFunctionCall(CGF.getContext().VoidTy, args),
- copyStructFn, ReturnValueSlot(), args);
+ callee, ReturnValueSlot(), args);
}
/// emitCPPObjectAtomicSetterCall - Call the runtime function to store
@@ -1103,11 +1106,12 @@ static void emitCPPObjectAtomicSetterCall(CodeGenFunction &CGF,
// Third argument is the helper function.
args.add(RValue::get(AtomicHelperFn), CGF.getContext().VoidPtrTy);
- llvm::Value *copyCppAtomicObjectFn =
+ llvm::Constant *fn =
CGF.CGM.getObjCRuntime().GetCppAtomicObjectSetFunction();
+ CGCallee callee = CGCallee::forDirect(fn);
CGF.EmitCall(
CGF.getTypes().arrangeBuiltinFunctionCall(CGF.getContext().VoidTy, args),
- copyCppAtomicObjectFn, ReturnValueSlot(), args);
+ callee, ReturnValueSlot(), args);
}
@@ -1197,8 +1201,8 @@ CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl,
case PropertyImplStrategy::GetSetProperty:
case PropertyImplStrategy::SetPropertyAndExpressionGet: {
- llvm::Value *setOptimizedPropertyFn = nullptr;
- llvm::Value *setPropertyFn = nullptr;
+ llvm::Constant *setOptimizedPropertyFn = nullptr;
+ llvm::Constant *setPropertyFn = nullptr;
if (UseOptimizedSetter(CGM)) {
// 10.8 and iOS 6.0 code and GC is off
setOptimizedPropertyFn =
@@ -1236,8 +1240,9 @@ CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl,
if (setOptimizedPropertyFn) {
args.add(RValue::get(arg), getContext().getObjCIdType());
args.add(RValue::get(ivarOffset), getContext().getPointerDiffType());
+ CGCallee callee = CGCallee::forDirect(setOptimizedPropertyFn);
EmitCall(getTypes().arrangeBuiltinFunctionCall(getContext().VoidTy, args),
- setOptimizedPropertyFn, ReturnValueSlot(), args);
+ callee, ReturnValueSlot(), args);
} else {
args.add(RValue::get(ivarOffset), getContext().getPointerDiffType());
args.add(RValue::get(arg), getContext().getObjCIdType());
@@ -1247,8 +1252,9 @@ CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl,
getContext().BoolTy);
// FIXME: We shouldn't need to get the function info here, the runtime
// already should have computed it to build the function.
+ CGCallee callee = CGCallee::forDirect(setPropertyFn);
EmitCall(getTypes().arrangeBuiltinFunctionCall(getContext().VoidTy, args),
- setPropertyFn, ReturnValueSlot(), args);
+ callee, ReturnValueSlot(), args);
}
return;
@@ -1450,13 +1456,14 @@ QualType CodeGenFunction::TypeOfSelfObject() {
}
void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
- llvm::Constant *EnumerationMutationFn =
+ llvm::Constant *EnumerationMutationFnPtr =
CGM.getObjCRuntime().EnumerationMutationFunction();
-
- if (!EnumerationMutationFn) {
+ if (!EnumerationMutationFnPtr) {
CGM.ErrorUnsupported(&S, "Obj-C fast enumeration for this runtime");
return;
}
+ CGCallee EnumerationMutationFn =
+ CGCallee::forDirect(EnumerationMutationFnPtr);
CGDebugInfo *DI = getDebugInfo();
if (DI)
@@ -1662,7 +1669,8 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
elementLValue = EmitLValue(cast<Expr>(S.getElement()));
EmitStoreThroughLValue(RValue::get(CurrentItem), elementLValue);
} else {
- EmitScalarInit(CurrentItem, elementLValue);
+ EmitStoreThroughLValue(RValue::get(CurrentItem), elementLValue,
+ /*isInit*/ true);
}
// If we do have an element variable, this assignment is the end of
@@ -1803,7 +1811,8 @@ static llvm::Constant *createARCRuntimeFunction(CodeGenModule &CGM,
// If the target runtime doesn't naturally support ARC, emit weak
// references to the runtime support library. We don't really
// permit this to fail, but we need a particular relocation style.
- if (!CGM.getLangOpts().ObjCRuntime.hasNativeARC()) {
+ if (!CGM.getLangOpts().ObjCRuntime.hasNativeARC() &&
+ !CGM.getTriple().isOSBinFormatCOFF()) {
f->setLinkage(llvm::Function::ExternalWeakLinkage);
} else if (fnName == "objc_retain" || fnName == "objc_release") {
// If we have Native ARC, set nonlazybind attribute for these APIs for
diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp
index caafef84c333..fa2b3d81e29a 100644
--- a/lib/CodeGen/CGObjCGNU.cpp
+++ b/lib/CodeGen/CGObjCGNU.cpp
@@ -18,6 +18,7 @@
#include "CGCleanup.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
+#include "ConstantBuilder.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
@@ -163,9 +164,8 @@ protected:
/// 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*.
- llvm::Constant *MakeConstantString(const std::string &Str,
- const std::string &Name="") {
- ConstantAddress Array = CGM.GetAddrOfConstantCString(Str, Name.c_str());
+ llvm::Constant *MakeConstantString(StringRef Str, const char *Name = "") {
+ ConstantAddress Array = CGM.GetAddrOfConstantCString(Str, Name);
return llvm::ConstantExpr::getGetElementPtr(Array.getElementType(),
Array.getPointer(), Zeros);
}
@@ -174,14 +174,14 @@ 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,
- const std::string prefix) {
- std::string name = prefix + Str;
- auto *ConstStr = TheModule.getGlobalVariable(name);
+ llvm::Constant *ExportUniqueString(const std::string &Str, StringRef Prefix) {
+ std::string Name = Prefix.str() + 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, prefix + Str);
+ llvm::GlobalValue::LinkOnceODRLinkage,
+ value, Name);
}
return llvm::ConstantExpr::getGetElementPtr(ConstStr->getValueType(),
ConstStr, Zeros);
@@ -190,47 +190,17 @@ protected:
/// 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::StructType *Ty,
- ArrayRef<llvm::Constant *> V,
+ llvm::GlobalVariable *MakeGlobal(llvm::Constant *C,
CharUnits Align,
StringRef Name="",
llvm::GlobalValue::LinkageTypes linkage
=llvm::GlobalValue::InternalLinkage) {
- llvm::Constant *C = llvm::ConstantStruct::get(Ty, V);
- auto GV = new llvm::GlobalVariable(TheModule, Ty, false,
+ auto GV = new llvm::GlobalVariable(TheModule, C->getType(), false,
linkage, C, Name);
GV->setAlignment(Align.getQuantity());
return GV;
}
- /// Generates a global array. The vector must contain the same number of
- /// elements that the array type declares, of the type specified as the array
- /// element type.
- llvm::GlobalVariable *MakeGlobal(llvm::ArrayType *Ty,
- ArrayRef<llvm::Constant *> V,
- CharUnits Align,
- StringRef Name="",
- llvm::GlobalValue::LinkageTypes linkage
- =llvm::GlobalValue::InternalLinkage) {
- llvm::Constant *C = llvm::ConstantArray::get(Ty, V);
- auto GV = new llvm::GlobalVariable(TheModule, Ty, false,
- linkage, C, Name);
- GV->setAlignment(Align.getQuantity());
- return GV;
- }
-
- /// Generates a global array, inferring the array type from the specified
- /// element type and the size of the initialiser.
- llvm::GlobalVariable *MakeGlobalArray(llvm::Type *Ty,
- ArrayRef<llvm::Constant *> V,
- CharUnits Align,
- StringRef Name="",
- llvm::GlobalValue::LinkageTypes linkage
- =llvm::GlobalValue::InternalLinkage) {
- llvm::ArrayType *ArrayTy = llvm::ArrayType::get(Ty, V.size());
- return MakeGlobal(ArrayTy, V, Align, Name, linkage);
- }
-
/// Returns a property name and encoding string.
llvm::Constant *MakePropertyEncodingString(const ObjCPropertyDecl *PD,
const Decl *Container) {
@@ -238,8 +208,8 @@ protected:
if ((R.getKind() == ObjCRuntime::GNUstep) &&
(R.getVersion() >= VersionTuple(1, 6))) {
std::string NameAndAttributes;
- std::string TypeStr;
- CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container, TypeStr);
+ std::string TypeStr =
+ CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container);
NameAndAttributes += '\0';
NameAndAttributes += TypeStr.length() + 3;
NameAndAttributes += TypeStr;
@@ -251,7 +221,7 @@ protected:
}
/// Push the property attributes into two structure fields.
- void PushPropertyAttributes(std::vector<llvm::Constant*> &Fields,
+ void PushPropertyAttributes(ConstantStructBuilder &Fields,
ObjCPropertyDecl *property, bool isSynthesized=true, bool
isDynamic=true) {
int attrs = property->getPropertyAttributes();
@@ -263,7 +233,7 @@ protected:
attrs &= ~ObjCPropertyDecl::OBJC_PR_strong;
}
// The first flags field has the same attribute values as clang uses internally
- Fields.push_back(llvm::ConstantInt::get(Int8Ty, attrs & 0xff));
+ Fields.addInt(Int8Ty, attrs & 0xff);
attrs >>= 8;
attrs <<= 2;
// For protocol properties, synthesized and dynamic have no meaning, so we
@@ -273,10 +243,10 @@ protected:
attrs |= isDynamic ? (1<<1) : 0;
// The second field is the next four fields left shifted by two, with the
// low bit set to indicate whether the field is synthesized or dynamic.
- Fields.push_back(llvm::ConstantInt::get(Int8Ty, attrs & 0xff));
+ Fields.addInt(Int8Ty, attrs & 0xff);
// Two padding fields
- Fields.push_back(llvm::ConstantInt::get(Int8Ty, 0));
- Fields.push_back(llvm::ConstantInt::get(Int8Ty, 0));
+ Fields.addInt(Int8Ty, 0);
+ Fields.addInt(Int8Ty, 0);
}
/// Ensures that the value has the required type, by inserting a bitcast if
@@ -590,11 +560,6 @@ public:
llvm::Constant *BuildByrefLayout(CodeGenModule &CGM, QualType T) override {
return NULLPtr;
}
-
- llvm::GlobalVariable *GetClassGlobal(StringRef Name,
- bool Weak = false) override {
- return nullptr;
- }
};
/// Class representing the legacy GCC Objective-C ABI. This is the default when
@@ -1152,8 +1117,7 @@ llvm::Value *CGObjCGNU::GetSelector(CodeGenFunction &CGF, Selector Sel) {
llvm::Value *CGObjCGNU::GetSelector(CodeGenFunction &CGF,
const ObjCMethodDecl *Method) {
- std::string SelTypes;
- CGM.getContext().getObjCEncodingForMethodDecl(Method, SelTypes);
+ std::string SelTypes = CGM.getContext().getObjCEncodingForMethodDecl(Method);
return GetSelector(CGF, Method->getSelector(), SelTypes);
}
@@ -1233,14 +1197,15 @@ llvm::Constant *CGObjCGNUstep::GetEHType(QualType T) {
llvm::Constant *typeName =
ExportUniqueString(className, "__objc_eh_typename_");
- std::vector<llvm::Constant*> fields;
- fields.push_back(BVtable);
- fields.push_back(typeName);
- llvm::Constant *TI =
- MakeGlobal(llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty, nullptr),
- fields, CGM.getPointerAlign(),
- "__objc_eh_typeinfo_" + className,
- llvm::GlobalValue::LinkOnceODRLinkage);
+ ConstantInitBuilder builder(CGM);
+ auto fields = builder.beginStruct();
+ fields.add(BVtable);
+ fields.add(typeName);
+ llvm::Constant *TI =
+ fields.finishAndCreateGlobal("__objc_eh_typeinfo_" + className,
+ CGM.getPointerAlign(),
+ /*constant*/ false,
+ llvm::GlobalValue::LinkOnceODRLinkage);
return llvm::ConstantExpr::getBitCast(TI, PtrToInt8Ty);
}
@@ -1270,13 +1235,13 @@ ConstantAddress CGObjCGNU::GenerateConstantString(const StringLiteral *SL) {
else if (isa->getType() != PtrToIdTy)
isa = llvm::ConstantExpr::getBitCast(isa, PtrToIdTy);
- std::vector<llvm::Constant*> Ivars;
- Ivars.push_back(isa);
- Ivars.push_back(MakeConstantString(Str));
- Ivars.push_back(llvm::ConstantInt::get(IntTy, Str.size()));
- llvm::Constant *ObjCStr = MakeGlobal(
- llvm::StructType::get(PtrToIdTy, PtrToInt8Ty, IntTy, nullptr),
- Ivars, Align, ".objc_str");
+ ConstantInitBuilder Builder(CGM);
+ auto Fields = Builder.beginStruct();
+ Fields.add(isa);
+ Fields.add(MakeConstantString(Str));
+ Fields.addInt(IntTy, Str.size());
+ llvm::Constant *ObjCStr =
+ Fields.finishAndCreateGlobal(".objc_str", Align);
ObjCStr = llvm::ConstantExpr::getBitCast(ObjCStr, PtrToInt8Ty);
ObjCStrings[Str] = ObjCStr;
ConstantStrings.push_back(ObjCStr);
@@ -1386,9 +1351,10 @@ CGObjCGNU::GenerateMessageSendSuper(CodeGenFunction &CGF,
llvm::Type::getInt1Ty(VMContext), IsClassMessage))};
llvm::MDNode *node = llvm::MDNode::get(VMContext, impMD);
+ CGCallee callee(CGCalleeInfo(), imp);
+
llvm::Instruction *call;
- RValue msgRet = CGF.EmitCall(MSI.CallInfo, imp, Return, ActualArgs,
- CGCalleeInfo(), &call);
+ RValue msgRet = CGF.EmitCall(MSI.CallInfo, callee, Return, ActualArgs, &call);
call->setMetadata(msgSendMDKind, node);
return msgRet;
}
@@ -1500,8 +1466,8 @@ CGObjCGNU::GenerateMessageSend(CodeGenFunction &CGF,
imp = EnforceType(Builder, imp, MSI.MessengerType);
llvm::Instruction *call;
- RValue msgRet = CGF.EmitCall(MSI.CallInfo, imp, Return, ActualArgs,
- CGCalleeInfo(), &call);
+ CGCallee callee(CGCalleeInfo(), imp);
+ RValue msgRet = CGF.EmitCall(MSI.CallInfo, callee, Return, ActualArgs, &call);
call->setMetadata(msgSendMDKind, node);
@@ -1550,50 +1516,38 @@ GenerateMethodList(StringRef ClassName,
bool isClassMethodList) {
if (MethodSels.empty())
return NULLPtr;
+
+ ConstantInitBuilder Builder(CGM);
+
+ auto MethodList = Builder.beginStruct();
+ MethodList.addNullPointer(CGM.Int8PtrTy);
+ MethodList.addInt(Int32Ty, MethodTypes.size());
+
// Get the method structure type.
- llvm::StructType *ObjCMethodTy = llvm::StructType::get(
- PtrToInt8Ty, // Really a selector, but the runtime creates it us.
- PtrToInt8Ty, // Method types
- IMPTy, //Method pointer
- nullptr);
- std::vector<llvm::Constant*> Methods;
+ llvm::StructType *ObjCMethodTy =
+ llvm::StructType::get(CGM.getLLVMContext(), {
+ PtrToInt8Ty, // Really a selector, but the runtime creates it us.
+ PtrToInt8Ty, // Method types
+ IMPTy // Method pointer
+ });
+ auto Methods = MethodList.beginArray();
for (unsigned int i = 0, e = MethodTypes.size(); i < e; ++i) {
- llvm::Constant *Method =
+ llvm::Constant *FnPtr =
TheModule.getFunction(SymbolNameForMethod(ClassName, CategoryName,
MethodSels[i],
isClassMethodList));
- assert(Method && "Can't generate metadata for method that doesn't exist");
- llvm::Constant *C = MakeConstantString(MethodSels[i].getAsString());
- Method = llvm::ConstantExpr::getBitCast(Method,
- IMPTy);
- Methods.push_back(
- llvm::ConstantStruct::get(ObjCMethodTy, {C, MethodTypes[i], Method}));
- }
-
- // Array of method structures
- llvm::ArrayType *ObjCMethodArrayTy = llvm::ArrayType::get(ObjCMethodTy,
- Methods.size());
- llvm::Constant *MethodArray = llvm::ConstantArray::get(ObjCMethodArrayTy,
- Methods);
-
- // Structure containing list pointer, array and array count
- llvm::StructType *ObjCMethodListTy = llvm::StructType::create(VMContext);
- llvm::Type *NextPtrTy = llvm::PointerType::getUnqual(ObjCMethodListTy);
- ObjCMethodListTy->setBody(
- NextPtrTy,
- IntTy,
- ObjCMethodArrayTy,
- nullptr);
-
- Methods.clear();
- Methods.push_back(llvm::ConstantPointerNull::get(
- llvm::PointerType::getUnqual(ObjCMethodListTy)));
- Methods.push_back(llvm::ConstantInt::get(Int32Ty, MethodTypes.size()));
- Methods.push_back(MethodArray);
+ 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);
+ }
+ Methods.finishAndAddTo(MethodList);
// Create an instance of the structure
- return MakeGlobal(ObjCMethodListTy, Methods, CGM.getPointerAlign(),
- ".objc_method_list");
+ return MethodList.finishAndCreateGlobal(".objc_method_list",
+ CGM.getPointerAlign());
}
/// Generates an IvarList. Used in construction of a objc_class.
@@ -1601,35 +1555,36 @@ llvm::Constant *CGObjCGNU::
GenerateIvarList(ArrayRef<llvm::Constant *> IvarNames,
ArrayRef<llvm::Constant *> IvarTypes,
ArrayRef<llvm::Constant *> IvarOffsets) {
- if (IvarNames.size() == 0)
+ if (IvarNames.empty())
return NULLPtr;
- // Get the method structure type.
+
+ ConstantInitBuilder Builder(CGM);
+
+ // Structure containing array count followed by array.
+ auto IvarList = Builder.beginStruct();
+ IvarList.addInt(IntTy, (int)IvarNames.size());
+
+ // Get the ivar structure type.
llvm::StructType *ObjCIvarTy = llvm::StructType::get(
PtrToInt8Ty,
PtrToInt8Ty,
IntTy,
nullptr);
- std::vector<llvm::Constant*> Ivars;
+
+ // Array of ivar structures.
+ auto Ivars = IvarList.beginArray(ObjCIvarTy);
for (unsigned int i = 0, e = IvarNames.size() ; i < e ; i++) {
- Ivars.push_back(llvm::ConstantStruct::get(
- ObjCIvarTy, {IvarNames[i], IvarTypes[i], IvarOffsets[i]}));
+ auto Ivar = Ivars.beginStruct(ObjCIvarTy);
+ Ivar.add(IvarNames[i]);
+ Ivar.add(IvarTypes[i]);
+ Ivar.add(IvarOffsets[i]);
+ Ivar.finishAndAddTo(Ivars);
}
-
- // Array of method structures
- llvm::ArrayType *ObjCIvarArrayTy = llvm::ArrayType::get(ObjCIvarTy,
- IvarNames.size());
-
- llvm::Constant *Elements[] = {
- llvm::ConstantInt::get(IntTy, (int)IvarNames.size()),
- llvm::ConstantArray::get(ObjCIvarArrayTy, Ivars)};
- // Structure containing array and array count
- llvm::StructType *ObjCIvarListTy = llvm::StructType::get(IntTy,
- ObjCIvarArrayTy,
- nullptr);
+ Ivars.finishAndAddTo(IvarList);
// Create an instance of the structure
- return MakeGlobal(ObjCIvarListTy, Elements, CGM.getPointerAlign(),
- ".objc_ivar_list");
+ return IvarList.finishAndCreateGlobal(".objc_ivar_list",
+ CGM.getPointerAlign());
}
/// Generate a class structure
@@ -1677,34 +1632,55 @@ llvm::Constant *CGObjCGNU::GenerateClassStructure(
IntPtrTy, // strong_pointers
IntPtrTy, // weak_pointers
nullptr);
- llvm::Constant *Zero = llvm::ConstantInt::get(LongTy, 0);
+
+ ConstantInitBuilder Builder(CGM);
+ auto Elements = Builder.beginStruct(ClassTy);
+
// Fill in the structure
- std::vector<llvm::Constant*> Elements;
- Elements.push_back(llvm::ConstantExpr::getBitCast(MetaClass, PtrToInt8Ty));
- Elements.push_back(SuperClass);
- Elements.push_back(MakeConstantString(Name, ".class_name"));
- Elements.push_back(Zero);
- Elements.push_back(llvm::ConstantInt::get(LongTy, info));
+
+ // isa
+ Elements.addBitCast(MetaClass, PtrToInt8Ty);
+ // super_class
+ Elements.add(SuperClass);
+ // name
+ Elements.add(MakeConstantString(Name, ".class_name"));
+ // version
+ Elements.addInt(LongTy, 0);
+ // info
+ Elements.addInt(LongTy, info);
+ // instance_size
if (isMeta) {
llvm::DataLayout td(&TheModule);
- Elements.push_back(
- llvm::ConstantInt::get(LongTy,
- td.getTypeSizeInBits(ClassTy) /
- CGM.getContext().getCharWidth()));
+ Elements.addInt(LongTy,
+ td.getTypeSizeInBits(ClassTy) /
+ CGM.getContext().getCharWidth());
} else
- Elements.push_back(InstanceSize);
- Elements.push_back(IVars);
- Elements.push_back(Methods);
- Elements.push_back(NULLPtr);
- Elements.push_back(NULLPtr);
- Elements.push_back(NULLPtr);
- Elements.push_back(llvm::ConstantExpr::getBitCast(Protocols, PtrTy));
- Elements.push_back(NULLPtr);
- Elements.push_back(llvm::ConstantInt::get(LongTy, 1));
- Elements.push_back(IvarOffsets);
- Elements.push_back(Properties);
- Elements.push_back(StrongIvarBitmap);
- Elements.push_back(WeakIvarBitmap);
+ Elements.add(InstanceSize);
+ // ivars
+ Elements.add(IVars);
+ // methods
+ Elements.add(Methods);
+ // These are all filled in by the runtime, so we pretend
+ // dtable
+ Elements.add(NULLPtr);
+ // subclass_list
+ Elements.add(NULLPtr);
+ // sibling_class
+ Elements.add(NULLPtr);
+ // protocols
+ Elements.addBitCast(Protocols, PtrTy);
+ // gc_object_type
+ Elements.add(NULLPtr);
+ // abi_version
+ Elements.addInt(LongTy, 1);
+ // ivar_offsets
+ Elements.add(IvarOffsets);
+ // properties
+ Elements.add(Properties);
+ // strong_pointers
+ Elements.add(StrongIvarBitmap);
+ // weak_pointers
+ Elements.add(WeakIvarBitmap);
// Create an instance of the structure
// This is now an externally visible symbol, so that we can speed up class
// messages in the next ABI. We may already have some weak references to
@@ -1713,13 +1689,13 @@ llvm::Constant *CGObjCGNU::GenerateClassStructure(
std::string(Name));
llvm::GlobalVariable *ClassRef = TheModule.getNamedGlobal(ClassSym);
llvm::Constant *Class =
- MakeGlobal(ClassTy, Elements, CGM.getPointerAlign(), ClassSym,
- llvm::GlobalValue::ExternalLinkage);
+ Elements.finishAndCreateGlobal(ClassSym, CGM.getPointerAlign(), false,
+ llvm::GlobalValue::ExternalLinkage);
if (ClassRef) {
- ClassRef->replaceAllUsesWith(llvm::ConstantExpr::getBitCast(Class,
+ ClassRef->replaceAllUsesWith(llvm::ConstantExpr::getBitCast(Class,
ClassRef->getType()));
- ClassRef->removeFromParent();
- Class->setName(ClassSym);
+ ClassRef->removeFromParent();
+ Class->setName(ClassSym);
}
return Class;
}
@@ -1728,38 +1704,33 @@ llvm::Constant *CGObjCGNU::
GenerateProtocolMethodList(ArrayRef<llvm::Constant *> MethodNames,
ArrayRef<llvm::Constant *> MethodTypes) {
// Get the method structure type.
- llvm::StructType *ObjCMethodDescTy = llvm::StructType::get(
- PtrToInt8Ty, // Really a selector, but the runtime does the casting for us.
- PtrToInt8Ty,
- nullptr);
- std::vector<llvm::Constant*> Methods;
+ llvm::StructType *ObjCMethodDescTy =
+ llvm::StructType::get(CGM.getLLVMContext(), { PtrToInt8Ty, PtrToInt8Ty });
+ 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++) {
- Methods.push_back(llvm::ConstantStruct::get(
- ObjCMethodDescTy, {MethodNames[i], MethodTypes[i]}));
- }
- llvm::ArrayType *ObjCMethodArrayTy = llvm::ArrayType::get(ObjCMethodDescTy,
- MethodNames.size());
- llvm::Constant *Array = llvm::ConstantArray::get(ObjCMethodArrayTy,
- Methods);
- llvm::StructType *ObjCMethodDescListTy = llvm::StructType::get(
- IntTy, ObjCMethodArrayTy, nullptr);
- Methods.clear();
- Methods.push_back(llvm::ConstantInt::get(IntTy, MethodNames.size()));
- Methods.push_back(Array);
- return MakeGlobal(ObjCMethodDescListTy, Methods, CGM.getPointerAlign(),
- ".objc_method_list");
+ auto Method = Methods.beginStruct(ObjCMethodDescTy);
+ Method.add(MethodNames[i]);
+ Method.add(MethodTypes[i]);
+ Method.finishAndAddTo(Methods);
+ }
+ Methods.finishAndAddTo(MethodList);
+ return MethodList.finishAndCreateGlobal(".objc_method_list",
+ CGM.getPointerAlign());
}
// Create the protocol list structure used in classes, categories and so on
-llvm::Constant *CGObjCGNU::GenerateProtocolList(ArrayRef<std::string>Protocols){
- llvm::ArrayType *ProtocolArrayTy = llvm::ArrayType::get(PtrToInt8Ty,
- Protocols.size());
- llvm::StructType *ProtocolListTy = llvm::StructType::get(
- PtrTy, //Should be a recurisve pointer, but it's always NULL here.
- SizeTy,
- ProtocolArrayTy,
- nullptr);
- std::vector<llvm::Constant*> Elements;
+llvm::Constant *
+CGObjCGNU::GenerateProtocolList(ArrayRef<std::string> Protocols) {
+
+ ConstantInitBuilder Builder(CGM);
+ auto ProtocolList = Builder.beginStruct();
+ ProtocolList.add(NULLPtr);
+ ProtocolList.addInt(LongTy, Protocols.size());
+
+ auto Elements = ProtocolList.beginArray(PtrToInt8Ty);
for (const std::string *iter = Protocols.begin(), *endIter = Protocols.end();
iter != endIter ; iter++) {
llvm::Constant *protocol = nullptr;
@@ -1770,18 +1741,11 @@ llvm::Constant *CGObjCGNU::GenerateProtocolList(ArrayRef<std::string>Protocols){
} else {
protocol = value->getValue();
}
- llvm::Constant *Ptr = llvm::ConstantExpr::getBitCast(protocol,
- PtrToInt8Ty);
- Elements.push_back(Ptr);
- }
- llvm::Constant * ProtocolArray = llvm::ConstantArray::get(ProtocolArrayTy,
- Elements);
- Elements.clear();
- Elements.push_back(NULLPtr);
- Elements.push_back(llvm::ConstantInt::get(LongTy, Protocols.size()));
- Elements.push_back(ProtocolArray);
- return MakeGlobal(ProtocolListTy, Elements, CGM.getPointerAlign(),
- ".objc_protocol_list");
+ Elements.addBitCast(protocol, PtrToInt8Ty);
+ }
+ Elements.finishAndAddTo(ProtocolList);
+ return ProtocolList.finishAndCreateGlobal(".objc_protocol_list",
+ CGM.getPointerAlign());
}
llvm::Value *CGObjCGNU::GenerateProtocolRef(CodeGenFunction &CGF,
@@ -1792,33 +1756,28 @@ llvm::Value *CGObjCGNU::GenerateProtocolRef(CodeGenFunction &CGF,
return CGF.Builder.CreateBitCast(protocol, llvm::PointerType::getUnqual(T));
}
-llvm::Constant *CGObjCGNU::GenerateEmptyProtocol(
- const std::string &ProtocolName) {
- SmallVector<std::string, 0> EmptyStringVector;
- SmallVector<llvm::Constant*, 0> EmptyConstantVector;
-
- llvm::Constant *ProtocolList = GenerateProtocolList(EmptyStringVector);
- llvm::Constant *MethodList =
- GenerateProtocolMethodList(EmptyConstantVector, EmptyConstantVector);
+llvm::Constant *
+CGObjCGNU::GenerateEmptyProtocol(const std::string &ProtocolName) {
+ llvm::Constant *ProtocolList = GenerateProtocolList({});
+ llvm::Constant *MethodList = GenerateProtocolMethodList({}, {});
// Protocols are objects containing lists of the methods implemented and
// protocols adopted.
- llvm::StructType *ProtocolTy = llvm::StructType::get(IdTy,
- PtrToInt8Ty,
- ProtocolList->getType(),
- MethodList->getType(),
- MethodList->getType(),
- MethodList->getType(),
- MethodList->getType(),
- nullptr);
+ ConstantInitBuilder Builder(CGM);
+ auto Elements = Builder.beginStruct();
+
// The isa pointer must be set to a magic number so the runtime knows it's
// the correct layout.
- llvm::Constant *Elements[] = {
- llvm::ConstantExpr::getIntToPtr(
- llvm::ConstantInt::get(Int32Ty, ProtocolVersion), IdTy),
- MakeConstantString(ProtocolName, ".objc_protocol_name"), ProtocolList,
- MethodList, MethodList, MethodList, MethodList};
- return MakeGlobal(ProtocolTy, Elements, CGM.getPointerAlign(),
- ".objc_protocol");
+ Elements.add(llvm::ConstantExpr::getIntToPtr(
+ 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",
+ CGM.getPointerAlign());
}
void CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) {
@@ -1837,8 +1796,7 @@ void CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) {
SmallVector<llvm::Constant*, 16> OptionalInstanceMethodNames;
SmallVector<llvm::Constant*, 16> OptionalInstanceMethodTypes;
for (const auto *I : PD->instance_methods()) {
- std::string TypeStr;
- Context.getObjCEncodingForMethodDecl(I, TypeStr);
+ std::string TypeStr = Context.getObjCEncodingForMethodDecl(I);
if (I->getImplementationControl() == ObjCMethodDecl::Optional) {
OptionalInstanceMethodNames.push_back(
MakeConstantString(I->getSelector().getAsString()));
@@ -1855,8 +1813,7 @@ void CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) {
SmallVector<llvm::Constant*, 16> OptionalClassMethodNames;
SmallVector<llvm::Constant*, 16> OptionalClassMethodTypes;
for (const auto *I : PD->class_methods()) {
- std::string TypeStr;
- Context.getObjCEncodingForMethodDecl(I,TypeStr);
+ std::string TypeStr = Context.getObjCEncodingForMethodDecl(I);
if (I->getImplementationControl() == ObjCMethodDecl::Optional) {
OptionalClassMethodNames.push_back(
MakeConstantString(I->getSelector().getAsString()));
@@ -1885,142 +1842,139 @@ void CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) {
// The isSynthesized value is always set to 0 in a protocol. It exists to
// simplify the runtime library by allowing it to use the same data
// structures for protocol metadata everywhere.
- llvm::StructType *PropertyMetadataTy = llvm::StructType::get(
- PtrToInt8Ty, Int8Ty, Int8Ty, Int8Ty, Int8Ty, PtrToInt8Ty,
- PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty, nullptr);
- std::vector<llvm::Constant*> Properties;
- std::vector<llvm::Constant*> OptionalProperties;
- // Add all of the property methods need adding to the method list and to the
- // property metadata list.
- for (auto *property : PD->instance_properties()) {
- std::vector<llvm::Constant*> Fields;
+ 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++;
+ }
- Fields.push_back(MakePropertyEncodingString(property, nullptr));
- PushPropertyAttributes(Fields, property);
+ 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);
+ }
- if (ObjCMethodDecl *getter = property->getGetterMethodDecl()) {
- std::string TypeStr;
- Context.getObjCEncodingForMethodDecl(getter,TypeStr);
- llvm::Constant *TypeEncoding = MakeConstantString(TypeStr);
- InstanceMethodTypes.push_back(TypeEncoding);
- Fields.push_back(MakeConstantString(getter->getSelector().getAsString()));
- Fields.push_back(TypeEncoding);
- } else {
- Fields.push_back(NULLPtr);
- Fields.push_back(NULLPtr);
- }
- if (ObjCMethodDecl *setter = property->getSetterMethodDecl()) {
- std::string TypeStr;
- Context.getObjCEncodingForMethodDecl(setter,TypeStr);
- llvm::Constant *TypeEncoding = MakeConstantString(TypeStr);
- InstanceMethodTypes.push_back(TypeEncoding);
- Fields.push_back(MakeConstantString(setter->getSelector().getAsString()));
- Fields.push_back(TypeEncoding);
- } else {
- Fields.push_back(NULLPtr);
- Fields.push_back(NULLPtr);
- }
- if (property->getPropertyImplementation() == ObjCPropertyDecl::Optional) {
- OptionalProperties.push_back(llvm::ConstantStruct::get(PropertyMetadataTy, Fields));
- } else {
- Properties.push_back(llvm::ConstantStruct::get(PropertyMetadataTy, Fields));
+ 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 *PropertyArray = llvm::ConstantArray::get(
- llvm::ArrayType::get(PropertyMetadataTy, Properties.size()), Properties);
- llvm::Constant* PropertyListInitFields[] =
- {llvm::ConstantInt::get(IntTy, Properties.size()), NULLPtr, PropertyArray};
-
- llvm::Constant *PropertyListInit =
- llvm::ConstantStruct::getAnon(PropertyListInitFields);
- llvm::Constant *PropertyList = new llvm::GlobalVariable(TheModule,
- PropertyListInit->getType(), false, llvm::GlobalValue::InternalLinkage,
- PropertyListInit, ".objc_property_list");
-
- llvm::Constant *OptionalPropertyArray =
- llvm::ConstantArray::get(llvm::ArrayType::get(PropertyMetadataTy,
- OptionalProperties.size()) , OptionalProperties);
- llvm::Constant* OptionalPropertyListInitFields[] = {
- llvm::ConstantInt::get(IntTy, OptionalProperties.size()), NULLPtr,
- OptionalPropertyArray };
-
- llvm::Constant *OptionalPropertyListInit =
- llvm::ConstantStruct::getAnon(OptionalPropertyListInitFields);
- llvm::Constant *OptionalPropertyList = new llvm::GlobalVariable(TheModule,
- OptionalPropertyListInit->getType(), false,
- llvm::GlobalValue::InternalLinkage, OptionalPropertyListInit,
- ".objc_property_list");
// Protocols are objects containing lists of the methods implemented and
// protocols adopted.
- llvm::StructType *ProtocolTy = llvm::StructType::get(IdTy,
- PtrToInt8Ty,
- ProtocolList->getType(),
- InstanceMethodList->getType(),
- ClassMethodList->getType(),
- OptionalInstanceMethodList->getType(),
- OptionalClassMethodList->getType(),
- PropertyList->getType(),
- OptionalPropertyList->getType(),
- nullptr);
// The isa pointer must be set to a magic number so the runtime knows it's
// the correct layout.
- llvm::Constant *Elements[] = {
+ ConstantInitBuilder Builder(CGM);
+ auto Elements = Builder.beginStruct();
+ Elements.add(
llvm::ConstantExpr::getIntToPtr(
- llvm::ConstantInt::get(Int32Ty, ProtocolVersion), IdTy),
- MakeConstantString(ProtocolName, ".objc_protocol_name"), ProtocolList,
- InstanceMethodList, ClassMethodList, OptionalInstanceMethodList,
- OptionalClassMethodList, PropertyList, OptionalPropertyList};
+ llvm::ConstantInt::get(Int32Ty, ProtocolVersion), IdTy));
+ Elements.add(
+ MakeConstantString(ProtocolName, ".objc_protocol_name"));
+ Elements.add(ProtocolList);
+ Elements.add(InstanceMethodList);
+ Elements.add(ClassMethodList);
+ Elements.add(OptionalInstanceMethodList);
+ Elements.add(OptionalClassMethodList);
+ Elements.add(PropertyList);
+ Elements.add(OptionalPropertyList);
ExistingProtocols[ProtocolName] =
- llvm::ConstantExpr::getBitCast(MakeGlobal(ProtocolTy, Elements,
- CGM.getPointerAlign(), ".objc_protocol"), IdTy);
+ llvm::ConstantExpr::getBitCast(
+ Elements.finishAndCreateGlobal(".objc_protocol", CGM.getPointerAlign()),
+ IdTy);
}
void CGObjCGNU::GenerateProtocolHolderCategory() {
// Collect information about instance methods
SmallVector<Selector, 1> MethodSels;
SmallVector<llvm::Constant*, 1> MethodTypes;
- std::vector<llvm::Constant*> Elements;
+ ConstantInitBuilder Builder(CGM);
+ auto Elements = Builder.beginStruct();
+
const std::string ClassName = "__ObjC_Protocol_Holder_Ugly_Hack";
const std::string CategoryName = "AnotherHack";
- Elements.push_back(MakeConstantString(CategoryName));
- Elements.push_back(MakeConstantString(ClassName));
+ Elements.add(MakeConstantString(CategoryName));
+ Elements.add(MakeConstantString(ClassName));
// Instance method list
- Elements.push_back(llvm::ConstantExpr::getBitCast(GenerateMethodList(
- ClassName, CategoryName, MethodSels, MethodTypes, false), PtrTy));
+ Elements.addBitCast(GenerateMethodList(
+ ClassName, CategoryName, MethodSels, MethodTypes, false), PtrTy);
// Class method list
- Elements.push_back(llvm::ConstantExpr::getBitCast(GenerateMethodList(
- ClassName, CategoryName, MethodSels, MethodTypes, true), PtrTy));
+ Elements.addBitCast(GenerateMethodList(
+ ClassName, CategoryName, MethodSels, MethodTypes, true), PtrTy);
+
// Protocol list
- llvm::ArrayType *ProtocolArrayTy = llvm::ArrayType::get(PtrTy,
- ExistingProtocols.size());
- llvm::StructType *ProtocolListTy = llvm::StructType::get(
- PtrTy, //Should be a recurisve pointer, but it's always NULL here.
- SizeTy,
- ProtocolArrayTy,
- nullptr);
- std::vector<llvm::Constant*> ProtocolElements;
- for (llvm::StringMapIterator<llvm::Constant*> iter =
- ExistingProtocols.begin(), endIter = ExistingProtocols.end();
+ ConstantInitBuilder ProtocolListBuilder(CGM);
+ auto ProtocolList = ProtocolListBuilder.beginStruct();
+ ProtocolList.add(NULLPtr);
+ ProtocolList.addInt(LongTy, ExistingProtocols.size());
+ auto ProtocolElements = ProtocolList.beginArray(PtrTy);
+ for (auto iter = ExistingProtocols.begin(), endIter = ExistingProtocols.end();
iter != endIter ; iter++) {
- llvm::Constant *Ptr = llvm::ConstantExpr::getBitCast(iter->getValue(),
- PtrTy);
- ProtocolElements.push_back(Ptr);
- }
- llvm::Constant * ProtocolArray = llvm::ConstantArray::get(ProtocolArrayTy,
- ProtocolElements);
- ProtocolElements.clear();
- ProtocolElements.push_back(NULLPtr);
- ProtocolElements.push_back(llvm::ConstantInt::get(LongTy,
- ExistingProtocols.size()));
- ProtocolElements.push_back(ProtocolArray);
- Elements.push_back(llvm::ConstantExpr::getBitCast(MakeGlobal(ProtocolListTy,
- ProtocolElements, CGM.getPointerAlign(),
- ".objc_protocol_list"), PtrTy));
+ ProtocolElements.addBitCast(iter->getValue(), PtrTy);
+ }
+ ProtocolElements.finishAndAddTo(ProtocolList);
+ Elements.addBitCast(
+ ProtocolList.finishAndCreateGlobal(".objc_protocol_list",
+ CGM.getPointerAlign()),
+ PtrTy);
Categories.push_back(llvm::ConstantExpr::getBitCast(
- MakeGlobal(llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty,
- PtrTy, PtrTy, PtrTy, nullptr), Elements, CGM.getPointerAlign()),
+ Elements.finishAndCreateGlobal("", CGM.getPointerAlign()),
PtrTy));
}
@@ -2055,13 +2009,16 @@ llvm::Constant *CGObjCGNU::MakeBitField(ArrayRef<bool> bits) {
}
values.push_back(llvm::ConstantInt::get(Int32Ty, word));
}
- llvm::ArrayType *arrayTy = llvm::ArrayType::get(Int32Ty, values.size());
- llvm::Constant *array = llvm::ConstantArray::get(arrayTy, values);
- llvm::Constant *fields[2] = {
- llvm::ConstantInt::get(Int32Ty, values.size()),
- array };
- llvm::Constant *GS = MakeGlobal(llvm::StructType::get(Int32Ty, arrayTy,
- nullptr), fields, CharUnits::fromQuantity(4));
+
+ ConstantInitBuilder builder(CGM);
+ auto fields = builder.beginStruct();
+ fields.addInt(Int32Ty, values.size());
+ auto array = fields.beginArray();
+ for (auto v : values) array.add(v);
+ array.finishAndAddTo(fields);
+
+ llvm::Constant *GS =
+ fields.finishAndCreateGlobal("", CharUnits::fromQuantity(4));
llvm::Constant *ptr = llvm::ConstantExpr::getPtrToInt(GS, IntPtrTy);
return ptr;
}
@@ -2074,8 +2031,7 @@ void CGObjCGNU::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
SmallVector<llvm::Constant*, 16> InstanceMethodTypes;
for (const auto *I : OCD->instance_methods()) {
InstanceMethodSels.push_back(I->getSelector());
- std::string TypeStr;
- CGM.getContext().getObjCEncodingForMethodDecl(I,TypeStr);
+ std::string TypeStr = CGM.getContext().getObjCEncodingForMethodDecl(I);
InstanceMethodTypes.push_back(MakeConstantString(TypeStr));
}
@@ -2084,8 +2040,7 @@ void CGObjCGNU::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
SmallVector<llvm::Constant*, 16> ClassMethodTypes;
for (const auto *I : OCD->class_methods()) {
ClassMethodSels.push_back(I->getSelector());
- std::string TypeStr;
- CGM.getContext().getObjCEncodingForMethodDecl(I,TypeStr);
+ std::string TypeStr = CGM.getContext().getObjCEncodingForMethodDecl(I);
ClassMethodTypes.push_back(MakeConstantString(TypeStr));
}
@@ -2097,23 +2052,24 @@ void CGObjCGNU::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
E = Protos.end(); I != E; ++I)
Protocols.push_back((*I)->getNameAsString());
- llvm::Constant *Elements[] = {
- MakeConstantString(CategoryName), MakeConstantString(ClassName),
- // Instance method list
- llvm::ConstantExpr::getBitCast(
+ ConstantInitBuilder Builder(CGM);
+ auto Elements = Builder.beginStruct();
+ Elements.add(MakeConstantString(CategoryName));
+ Elements.add(MakeConstantString(ClassName));
+ // Instance method list
+ Elements.addBitCast(
GenerateMethodList(ClassName, CategoryName, InstanceMethodSels,
InstanceMethodTypes, false),
- PtrTy),
- // Class method list
- llvm::ConstantExpr::getBitCast(GenerateMethodList(ClassName, CategoryName,
- ClassMethodSels,
- ClassMethodTypes, true),
- PtrTy),
- // Protocol list
- llvm::ConstantExpr::getBitCast(GenerateProtocolList(Protocols), PtrTy)};
+ PtrTy);
+ // Class method list
+ Elements.addBitCast(
+ GenerateMethodList(ClassName, CategoryName, ClassMethodSels,
+ ClassMethodTypes, true),
+ PtrTy);
+ // Protocol list
+ Elements.addBitCast(GenerateProtocolList(Protocols), PtrTy);
Categories.push_back(llvm::ConstantExpr::getBitCast(
- MakeGlobal(llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty,
- PtrTy, PtrTy, PtrTy, nullptr), Elements, CGM.getPointerAlign()),
+ Elements.finishAndCreateGlobal("", CGM.getPointerAlign()),
PtrTy));
}
@@ -2123,65 +2079,67 @@ llvm::Constant *CGObjCGNU::GeneratePropertyList(const ObjCImplementationDecl *OI
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(
- PtrToInt8Ty, Int8Ty, Int8Ty, Int8Ty, Int8Ty, PtrToInt8Ty,
- PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty, nullptr);
- std::vector<llvm::Constant*> Properties;
+ 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++;
+ }
+
+ ConstantInitBuilder builder(CGM);
+ auto propertyList = builder.beginStruct();
+ propertyList.addInt(IntTy, numProperties);
+ propertyList.add(NULLPtr);
+ auto properties = propertyList.beginArray(propertyMetadataTy);
// Add all of the property methods need adding to the method list and to the
// property metadata list.
for (auto *propertyImpl : OID->property_impls()) {
- std::vector<llvm::Constant*> Fields;
+ auto fields = properties.beginStruct(propertyMetadataTy);
ObjCPropertyDecl *property = propertyImpl->getPropertyDecl();
bool isSynthesized = (propertyImpl->getPropertyImplementation() ==
ObjCPropertyImplDecl::Synthesize);
bool isDynamic = (propertyImpl->getPropertyImplementation() ==
ObjCPropertyImplDecl::Dynamic);
- Fields.push_back(MakePropertyEncodingString(property, OID));
- PushPropertyAttributes(Fields, property, isSynthesized, isDynamic);
+ fields.add(MakePropertyEncodingString(property, OID));
+ PushPropertyAttributes(fields, property, isSynthesized, isDynamic);
if (ObjCMethodDecl *getter = property->getGetterMethodDecl()) {
- std::string TypeStr;
- Context.getObjCEncodingForMethodDecl(getter,TypeStr);
+ std::string TypeStr = Context.getObjCEncodingForMethodDecl(getter);
llvm::Constant *TypeEncoding = MakeConstantString(TypeStr);
if (isSynthesized) {
InstanceMethodTypes.push_back(TypeEncoding);
InstanceMethodSels.push_back(getter->getSelector());
}
- Fields.push_back(MakeConstantString(getter->getSelector().getAsString()));
- Fields.push_back(TypeEncoding);
+ fields.add(MakeConstantString(getter->getSelector().getAsString()));
+ fields.add(TypeEncoding);
} else {
- Fields.push_back(NULLPtr);
- Fields.push_back(NULLPtr);
+ fields.add(NULLPtr);
+ fields.add(NULLPtr);
}
if (ObjCMethodDecl *setter = property->getSetterMethodDecl()) {
- std::string TypeStr;
- Context.getObjCEncodingForMethodDecl(setter,TypeStr);
+ std::string TypeStr = Context.getObjCEncodingForMethodDecl(setter);
llvm::Constant *TypeEncoding = MakeConstantString(TypeStr);
if (isSynthesized) {
InstanceMethodTypes.push_back(TypeEncoding);
InstanceMethodSels.push_back(setter->getSelector());
}
- Fields.push_back(MakeConstantString(setter->getSelector().getAsString()));
- Fields.push_back(TypeEncoding);
+ fields.add(MakeConstantString(setter->getSelector().getAsString()));
+ fields.add(TypeEncoding);
} else {
- Fields.push_back(NULLPtr);
- Fields.push_back(NULLPtr);
+ fields.add(NULLPtr);
+ fields.add(NULLPtr);
}
- Properties.push_back(llvm::ConstantStruct::get(PropertyMetadataTy, Fields));
- }
- llvm::ArrayType *PropertyArrayTy =
- llvm::ArrayType::get(PropertyMetadataTy, Properties.size());
- llvm::Constant *PropertyArray = llvm::ConstantArray::get(PropertyArrayTy,
- Properties);
- llvm::Constant* PropertyListInitFields[] =
- {llvm::ConstantInt::get(IntTy, Properties.size()), NULLPtr, PropertyArray};
-
- llvm::Constant *PropertyListInit =
- llvm::ConstantStruct::getAnon(PropertyListInitFields);
- return new llvm::GlobalVariable(TheModule, PropertyListInit->getType(), false,
- llvm::GlobalValue::InternalLinkage, PropertyListInit,
- ".objc_property_list");
+ fields.finishAndAddTo(properties);
+ }
+ properties.finishAndAddTo(propertyList);
+
+ return propertyList.finishAndCreateGlobal(".objc_property_list",
+ CGM.getPointerAlign());
}
void CGObjCGNU::RegisterAlias(const ObjCCompatibleAliasDecl *OAD) {
@@ -2230,7 +2188,8 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) {
SmallVector<llvm::Constant*, 16> IvarTypes;
SmallVector<llvm::Constant*, 16> IvarOffsets;
- std::vector<llvm::Constant*> IvarOffsetValues;
+ ConstantInitBuilder IvarOffsetBuilder(CGM);
+ auto IvarOffsetValues = IvarOffsetBuilder.beginArray(PtrToIntTy);
SmallVector<bool, 16> WeakIvars;
SmallVector<bool, 16> StrongIvars;
@@ -2274,7 +2233,7 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) {
"__objc_ivar_offset_value_" + ClassName +"." +
IVD->getNameAsString());
IvarOffsets.push_back(OffsetValue);
- IvarOffsetValues.push_back(OffsetVar);
+ IvarOffsetValues.add(OffsetVar);
Qualifiers::ObjCLifetime lt = IVD->getType().getQualifiers().getObjCLifetime();
switch (lt) {
case Qualifiers::OCL_Strong:
@@ -2293,16 +2252,15 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) {
llvm::Constant *StrongIvarBitmap = MakeBitField(StrongIvars);
llvm::Constant *WeakIvarBitmap = MakeBitField(WeakIvars);
llvm::GlobalVariable *IvarOffsetArray =
- MakeGlobalArray(PtrToIntTy, IvarOffsetValues, CGM.getPointerAlign(),
- ".ivar.offsets");
+ IvarOffsetValues.finishAndCreateGlobal(".ivar.offsets",
+ 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,TypeStr);
+ std::string TypeStr = Context.getObjCEncodingForMethodDecl(I);
InstanceMethodTypes.push_back(MakeConstantString(TypeStr));
}
@@ -2314,8 +2272,7 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) {
SmallVector<llvm::Constant*, 16> ClassMethodTypes;
for (const auto *I : OID->class_methods()) {
ClassMethodSels.push_back(I->getSelector());
- std::string TypeStr;
- Context.getObjCEncodingForMethodDecl(I,TypeStr);
+ std::string TypeStr = Context.getObjCEncodingForMethodDecl(I);
ClassMethodTypes.push_back(MakeConstantString(TypeStr));
}
// Collect the names of referenced protocols
@@ -2439,170 +2396,180 @@ llvm::Function *CGObjCGNU::ModuleInitFunction() {
// Add all referenced protocols to a category.
GenerateProtocolHolderCategory();
- llvm::StructType *SelStructTy = dyn_cast<llvm::StructType>(
- SelectorTy->getElementType());
- llvm::Type *SelStructPtrTy = SelectorTy;
- if (!SelStructTy) {
- SelStructTy = llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty, nullptr);
- SelStructPtrTy = llvm::PointerType::getUnqual(SelStructTy);
+ llvm::StructType *selStructTy =
+ dyn_cast<llvm::StructType>(SelectorTy->getElementType());
+ llvm::Type *selStructPtrTy = SelectorTy;
+ if (!selStructTy) {
+ selStructTy = llvm::StructType::get(CGM.getLLVMContext(),
+ { PtrToInt8Ty, PtrToInt8Ty });
+ selStructPtrTy = llvm::PointerType::getUnqual(selStructTy);
}
- std::vector<llvm::Constant*> Elements;
- llvm::Constant *Statics = NULLPtr;
// Generate statics list:
+ llvm::Constant *statics = NULLPtr;
if (!ConstantStrings.empty()) {
- llvm::ArrayType *StaticsArrayTy = llvm::ArrayType::get(PtrToInt8Ty,
- ConstantStrings.size() + 1);
- ConstantStrings.push_back(NULLPtr);
-
- StringRef StringClass = CGM.getLangOpts().ObjCConstantStringClass;
-
- if (StringClass.empty()) StringClass = "NXConstantString";
-
- Elements.push_back(MakeConstantString(StringClass,
- ".objc_static_class_name"));
- Elements.push_back(llvm::ConstantArray::get(StaticsArrayTy,
- ConstantStrings));
- llvm::StructType *StaticsListTy =
- llvm::StructType::get(PtrToInt8Ty, StaticsArrayTy, nullptr);
- llvm::Type *StaticsListPtrTy =
- llvm::PointerType::getUnqual(StaticsListTy);
- Statics = MakeGlobal(StaticsListTy, Elements, CGM.getPointerAlign(),
- ".objc_statics");
- llvm::ArrayType *StaticsListArrayTy =
- llvm::ArrayType::get(StaticsListPtrTy, 2);
- Elements.clear();
- Elements.push_back(Statics);
- Elements.push_back(llvm::Constant::getNullValue(StaticsListPtrTy));
- Statics = MakeGlobal(StaticsListArrayTy, Elements,
- CGM.getPointerAlign(), ".objc_statics_ptr");
- Statics = llvm::ConstantExpr::getBitCast(Statics, PtrTy);
- }
- // Array of classes, categories, and constant objects
- llvm::ArrayType *ClassListTy = llvm::ArrayType::get(PtrToInt8Ty,
- Classes.size() + Categories.size() + 2);
- llvm::StructType *SymTabTy = llvm::StructType::get(LongTy, SelStructPtrTy,
- llvm::Type::getInt16Ty(VMContext),
- llvm::Type::getInt16Ty(VMContext),
- ClassListTy, nullptr);
-
- Elements.clear();
- // Pointer to an array of selectors used in this module.
- std::vector<llvm::Constant*> Selectors;
- std::vector<llvm::GlobalAlias*> SelectorAliases;
- for (SelectorMap::iterator iter = SelectorTable.begin(),
- iterEnd = SelectorTable.end(); iter != iterEnd ; ++iter) {
+ llvm::GlobalVariable *fileStatics = [&] {
+ ConstantInitBuilder builder(CGM);
+ auto staticsStruct = builder.beginStruct();
- std::string SelNameStr = iter->first.getAsString();
- llvm::Constant *SelName = ExportUniqueString(SelNameStr, ".objc_sel_name");
+ StringRef stringClass = CGM.getLangOpts().ObjCConstantStringClass;
+ if (stringClass.empty()) stringClass = "NXConstantString";
+ staticsStruct.add(MakeConstantString(stringClass,
+ ".objc_static_class_name"));
- SmallVectorImpl<TypedSelector> &Types = iter->second;
- for (SmallVectorImpl<TypedSelector>::iterator i = Types.begin(),
- e = Types.end() ; i!=e ; i++) {
+ auto array = staticsStruct.beginArray();
+ array.addAll(ConstantStrings);
+ array.add(NULLPtr);
+ array.finishAndAddTo(staticsStruct);
- llvm::Constant *SelectorTypeEncoding = NULLPtr;
- if (!i->first.empty())
- SelectorTypeEncoding = MakeConstantString(i->first, ".objc_sel_types");
+ return staticsStruct.finishAndCreateGlobal(".objc_statics",
+ CGM.getPointerAlign());
+ }();
- Elements.push_back(SelName);
- Elements.push_back(SelectorTypeEncoding);
- Selectors.push_back(llvm::ConstantStruct::get(SelStructTy, Elements));
- Elements.clear();
+ ConstantInitBuilder builder(CGM);
+ auto allStaticsArray = builder.beginArray(fileStatics->getType());
+ allStaticsArray.add(fileStatics);
+ allStaticsArray.addNullPointer(fileStatics->getType());
- // Store the selector alias for later replacement
- SelectorAliases.push_back(i->second);
- }
+ statics = allStaticsArray.finishAndCreateGlobal(".objc_statics_ptr",
+ CGM.getPointerAlign());
+ statics = llvm::ConstantExpr::getBitCast(statics, PtrTy);
}
- unsigned SelectorCount = Selectors.size();
- // NULL-terminate the selector list. This should not actually be required,
- // because the selector list has a length field. Unfortunately, the GCC
- // runtime decides to ignore the length field and expects a NULL terminator,
- // and GCC cooperates with this by always setting the length to 0.
- Elements.push_back(NULLPtr);
- Elements.push_back(NULLPtr);
- Selectors.push_back(llvm::ConstantStruct::get(SelStructTy, Elements));
- Elements.clear();
-
- // Number of static selectors
- Elements.push_back(llvm::ConstantInt::get(LongTy, SelectorCount));
- llvm::GlobalVariable *SelectorList =
- MakeGlobalArray(SelStructTy, Selectors, CGM.getPointerAlign(),
- ".objc_selector_list");
- Elements.push_back(llvm::ConstantExpr::getBitCast(SelectorList,
- SelStructPtrTy));
- // Now that all of the static selectors exist, create pointers to them.
- for (unsigned int i=0 ; i<SelectorCount ; i++) {
+ // Array of classes, categories, and constant objects.
+
+ SmallVector<llvm::GlobalAlias*, 16> selectorAliases;
+ unsigned selectorCount;
+
+ // Pointer to an array of selectors used in this module.
+ llvm::GlobalVariable *selectorList = [&] {
+ ConstantInitBuilder builder(CGM);
+ auto selectors = builder.beginArray(selStructTy);
+ auto &table = SelectorTable; // MSVC workaround
+ for (auto &entry : table) {
+
+ std::string selNameStr = entry.first.getAsString();
+ llvm::Constant *selName = ExportUniqueString(selNameStr, ".objc_sel_name");
+
+ for (TypedSelector &sel : entry.second) {
+ llvm::Constant *selectorTypeEncoding = NULLPtr;
+ if (!sel.first.empty())
+ selectorTypeEncoding =
+ MakeConstantString(sel.first, ".objc_sel_types");
+
+ auto selStruct = selectors.beginStruct(selStructTy);
+ selStruct.add(selName);
+ selStruct.add(selectorTypeEncoding);
+ selStruct.finishAndAddTo(selectors);
+
+ // Store the selector alias for later replacement
+ selectorAliases.push_back(sel.second);
+ }
+ }
+
+ // Remember the number of entries in the selector table.
+ selectorCount = selectors.size();
- llvm::Constant *Idxs[] = {Zeros[0],
- llvm::ConstantInt::get(Int32Ty, i), Zeros[0]};
+ // NULL-terminate the selector list. This should not actually be required,
+ // because the selector list has a length field. Unfortunately, the GCC
+ // runtime decides to ignore the length field and expects a NULL terminator,
+ // and GCC cooperates with this by always setting the length to 0.
+ auto selStruct = selectors.beginStruct(selStructTy);
+ selStruct.add(NULLPtr);
+ selStruct.add(NULLPtr);
+ selStruct.finishAndAddTo(selectors);
+
+ return selectors.finishAndCreateGlobal(".objc_selector_list",
+ CGM.getPointerAlign());
+ }();
+
+ // Now that all of the static selectors exist, create pointers to them.
+ for (unsigned i = 0; i < selectorCount; ++i) {
+ llvm::Constant *idxs[] = {
+ Zeros[0],
+ llvm::ConstantInt::get(Int32Ty, i)
+ };
// FIXME: We're generating redundant loads and stores here!
- llvm::Constant *SelPtr = llvm::ConstantExpr::getGetElementPtr(
- SelectorList->getValueType(), SelectorList, makeArrayRef(Idxs, 2));
+ llvm::Constant *selPtr = llvm::ConstantExpr::getGetElementPtr(
+ selectorList->getValueType(), selectorList, idxs);
// If selectors are defined as an opaque type, cast the pointer to this
// type.
- SelPtr = llvm::ConstantExpr::getBitCast(SelPtr, SelectorTy);
- SelectorAliases[i]->replaceAllUsesWith(SelPtr);
- SelectorAliases[i]->eraseFromParent();
- }
-
- // Number of classes defined.
- Elements.push_back(llvm::ConstantInt::get(llvm::Type::getInt16Ty(VMContext),
- Classes.size()));
- // Number of categories defined
- Elements.push_back(llvm::ConstantInt::get(llvm::Type::getInt16Ty(VMContext),
- Categories.size()));
- // Create an array of classes, then categories, then static object instances
- Classes.insert(Classes.end(), Categories.begin(), Categories.end());
- // NULL-terminated list of static object instances (mainly constant strings)
- Classes.push_back(Statics);
- Classes.push_back(NULLPtr);
- llvm::Constant *ClassList = llvm::ConstantArray::get(ClassListTy, Classes);
- Elements.push_back(ClassList);
- // Construct the symbol table
- llvm::Constant *SymTab =
- MakeGlobal(SymTabTy, Elements, CGM.getPointerAlign());
+ selPtr = llvm::ConstantExpr::getBitCast(selPtr, SelectorTy);
+ selectorAliases[i]->replaceAllUsesWith(selPtr);
+ selectorAliases[i]->eraseFromParent();
+ }
+
+ llvm::GlobalVariable *symtab = [&] {
+ ConstantInitBuilder builder(CGM);
+ auto symtab = builder.beginStruct();
+
+ // Number of static selectors
+ symtab.addInt(LongTy, selectorCount);
+
+ symtab.addBitCast(selectorList, selStructPtrTy);
+
+ // Number of classes defined.
+ symtab.addInt(CGM.Int16Ty, Classes.size());
+ // Number of categories defined
+ symtab.addInt(CGM.Int16Ty, Categories.size());
+
+ // Create an array of classes, then categories, then static object instances
+ auto classList = symtab.beginArray(PtrToInt8Ty);
+ classList.addAll(Classes);
+ classList.addAll(Categories);
+ // NULL-terminated list of static object instances (mainly constant strings)
+ classList.add(statics);
+ classList.add(NULLPtr);
+ classList.finishAndAddTo(symtab);
+
+ // Construct the symbol table.
+ return symtab.finishAndCreateGlobal("", CGM.getPointerAlign());
+ }();
// The symbol table is contained in a module which has some version-checking
// constants
- llvm::StructType * ModuleTy = llvm::StructType::get(LongTy, LongTy,
- PtrToInt8Ty, llvm::PointerType::getUnqual(SymTabTy),
- (RuntimeVersion >= 10) ? IntTy : nullptr, nullptr);
- Elements.clear();
- // Runtime version, used for ABI compatibility checking.
- Elements.push_back(llvm::ConstantInt::get(LongTy, RuntimeVersion));
- // sizeof(ModuleTy)
- llvm::DataLayout td(&TheModule);
- Elements.push_back(
- llvm::ConstantInt::get(LongTy,
- td.getTypeSizeInBits(ModuleTy) /
- CGM.getContext().getCharWidth()));
-
- // The path to the source file where this module was declared
- SourceManager &SM = CGM.getContext().getSourceManager();
- const FileEntry *mainFile = SM.getFileEntryForID(SM.getMainFileID());
- std::string path =
- std::string(mainFile->getDir()->getName()) + '/' + mainFile->getName();
- Elements.push_back(MakeConstantString(path, ".objc_source_file_name"));
- Elements.push_back(SymTab);
-
- if (RuntimeVersion >= 10)
- switch (CGM.getLangOpts().getGC()) {
+ llvm::Constant *module = [&] {
+ llvm::Type *moduleEltTys[] = {
+ LongTy, LongTy, PtrToInt8Ty, symtab->getType(), IntTy
+ };
+ llvm::StructType *moduleTy =
+ llvm::StructType::get(CGM.getLLVMContext(),
+ makeArrayRef(moduleEltTys).drop_back(unsigned(RuntimeVersion < 10)));
+
+ ConstantInitBuilder builder(CGM);
+ auto module = builder.beginStruct(moduleTy);
+ // Runtime version, used for ABI compatibility checking.
+ module.addInt(LongTy, RuntimeVersion);
+ // sizeof(ModuleTy)
+ module.addInt(LongTy, CGM.getDataLayout().getTypeStoreSize(moduleTy));
+
+ // The path to the source file where this module was declared
+ SourceManager &SM = CGM.getContext().getSourceManager();
+ const FileEntry *mainFile = SM.getFileEntryForID(SM.getMainFileID());
+ std::string path =
+ (Twine(mainFile->getDir()->getName()) + "/" + mainFile->getName()).str();
+ module.add(MakeConstantString(path, ".objc_source_file_name"));
+ module.add(symtab);
+
+ if (RuntimeVersion >= 10) {
+ switch (CGM.getLangOpts().getGC()) {
case LangOptions::GCOnly:
- Elements.push_back(llvm::ConstantInt::get(IntTy, 2));
+ module.addInt(IntTy, 2);
break;
case LangOptions::NonGC:
if (CGM.getLangOpts().ObjCAutoRefCount)
- Elements.push_back(llvm::ConstantInt::get(IntTy, 1));
+ module.addInt(IntTy, 1);
else
- Elements.push_back(llvm::ConstantInt::get(IntTy, 0));
+ module.addInt(IntTy, 0);
break;
case LangOptions::HybridGC:
- Elements.push_back(llvm::ConstantInt::get(IntTy, 1));
+ module.addInt(IntTy, 1);
break;
+ }
}
- llvm::Value *Module = MakeGlobal(ModuleTy, Elements, CGM.getPointerAlign());
+ return module.finishAndCreateGlobal("", CGM.getPointerAlign());
+ }();
// Create the load function calling the runtime entry point with the module
// structure
@@ -2616,10 +2583,9 @@ llvm::Function *CGObjCGNU::ModuleInitFunction() {
Builder.SetInsertPoint(EntryBB);
llvm::FunctionType *FT =
- llvm::FunctionType::get(Builder.getVoidTy(),
- llvm::PointerType::getUnqual(ModuleTy), true);
+ llvm::FunctionType::get(Builder.getVoidTy(), module->getType(), true);
llvm::Value *Register = CGM.CreateRuntimeFunction(FT, "__objc_exec_class");
- Builder.CreateCall(Register, Module);
+ Builder.CreateCall(Register, module);
if (!ClassAliases.empty()) {
llvm::Type *ArgTypes[2] = {PtrTy, PtrToInt8Ty};
@@ -2646,8 +2612,7 @@ llvm::Function *CGObjCGNU::ModuleInitFunction() {
for (std::vector<ClassAliasPair>::iterator iter = ClassAliases.begin();
iter != ClassAliases.end(); ++iter) {
llvm::Constant *TheClass =
- TheModule.getGlobalVariable(("_OBJC_CLASS_" + iter->first).c_str(),
- true);
+ TheModule.getGlobalVariable("_OBJC_CLASS_" + iter->first, true);
if (TheClass) {
TheClass = llvm::ConstantExpr::getBitCast(TheClass, PtrTy);
Builder.CreateCall(RegisterAlias,
@@ -2910,9 +2875,11 @@ llvm::Value *CGObjCGNU::EmitIvarOffset(CodeGenFunction &CGF,
if (RuntimeVersion < 10 ||
CGF.CGM.getTarget().getTriple().isKnownWindowsMSVCEnvironment())
return CGF.Builder.CreateZExtOrBitCast(
- CGF.Builder.CreateDefaultAlignedLoad(CGF.Builder.CreateAlignedLoad(
- ObjCIvarOffsetVariable(Interface, Ivar),
- CGF.getPointerAlign(), "ivar")),
+ CGF.Builder.CreateAlignedLoad(
+ Int32Ty, CGF.Builder.CreateAlignedLoad(
+ ObjCIvarOffsetVariable(Interface, Ivar),
+ CGF.getPointerAlign(), "ivar"),
+ CharUnits::fromQuantity(4)),
PtrDiffTy);
std::string name = "__objc_ivar_offset_value_" +
Interface->getNameAsString() +"." + Ivar->getNameAsString();
diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp
index 5ab9fc4f9710..7219592fffcd 100644
--- a/lib/CodeGen/CGObjCMac.cpp
+++ b/lib/CodeGen/CGObjCMac.cpp
@@ -11,12 +11,13 @@
//
//===----------------------------------------------------------------------===//
-#include "CGObjCRuntime.h"
#include "CGBlocks.h"
#include "CGCleanup.h"
+#include "CGObjCRuntime.h"
#include "CGRecordLayout.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
+#include "ConstantBuilder.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
@@ -25,6 +26,7 @@
#include "clang/Basic/LangOptions.h"
#include "clang/CodeGen/CGFunctionInfo.h"
#include "clang/Frontend/CodeGenOptions.h"
+#include "llvm/ADT/CachedHashString.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h"
@@ -172,18 +174,18 @@ protected:
CodeGen::CodeGenModule &CGM;
public:
- llvm::Type *ShortTy, *IntTy, *LongTy, *LongLongTy;
- llvm::Type *Int8PtrTy, *Int8PtrPtrTy;
+ llvm::IntegerType *ShortTy, *IntTy, *LongTy;
+ llvm::PointerType *Int8PtrTy, *Int8PtrPtrTy;
llvm::Type *IvarOffsetVarTy;
/// ObjectPtrTy - LLVM type for object handles (typeof(id))
- llvm::Type *ObjectPtrTy;
+ llvm::PointerType *ObjectPtrTy;
/// PtrObjectPtrTy - LLVM type for id *
- llvm::Type *PtrObjectPtrTy;
+ llvm::PointerType *PtrObjectPtrTy;
/// SelectorPtrTy - LLVM type for selector handles (typeof(SEL))
- llvm::Type *SelectorPtrTy;
+ llvm::PointerType *SelectorPtrTy;
private:
/// ProtocolPtrTy - LLVM type for external protocol handles
@@ -212,7 +214,7 @@ public:
/// SuperTy - LLVM type for struct objc_super.
llvm::StructType *SuperTy;
/// SuperPtrTy - LLVM type for struct objc_super *.
- llvm::Type *SuperPtrTy;
+ llvm::PointerType *SuperPtrTy;
/// PropertyTy - LLVM type for struct objc_property (struct _prop_t
/// in GCC parlance).
@@ -222,7 +224,7 @@ public:
/// (_prop_list_t in GCC parlance).
llvm::StructType *PropertyListTy;
/// PropertyListPtrTy - LLVM type for struct objc_property_list*.
- llvm::Type *PropertyListPtrTy;
+ llvm::PointerType *PropertyListPtrTy;
// MethodTy - LLVM type for struct objc_method.
llvm::StructType *MethodTy;
@@ -230,7 +232,7 @@ public:
/// CacheTy - LLVM type for struct objc_cache.
llvm::Type *CacheTy;
/// CachePtrTy - LLVM type for struct objc_cache *.
- llvm::Type *CachePtrTy;
+ llvm::PointerType *CachePtrTy;
llvm::Constant *getGetPropertyFn() {
CodeGen::CodeGenTypes &Types = CGM.getTypes();
@@ -500,20 +502,20 @@ public:
/// SymtabTy - LLVM type for struct objc_symtab.
llvm::StructType *SymtabTy;
/// SymtabPtrTy - LLVM type for struct objc_symtab *.
- llvm::Type *SymtabPtrTy;
+ llvm::PointerType *SymtabPtrTy;
/// ModuleTy - LLVM type for struct objc_module.
llvm::StructType *ModuleTy;
/// ProtocolTy - LLVM type for struct objc_protocol.
llvm::StructType *ProtocolTy;
/// ProtocolPtrTy - LLVM type for struct objc_protocol *.
- llvm::Type *ProtocolPtrTy;
+ llvm::PointerType *ProtocolPtrTy;
/// ProtocolExtensionTy - LLVM type for struct
/// objc_protocol_extension.
llvm::StructType *ProtocolExtensionTy;
/// ProtocolExtensionTy - LLVM type for struct
/// objc_protocol_extension *.
- llvm::Type *ProtocolExtensionPtrTy;
+ llvm::PointerType *ProtocolExtensionPtrTy;
/// MethodDescriptionTy - LLVM type for struct
/// objc_method_description.
llvm::StructType *MethodDescriptionTy;
@@ -522,34 +524,34 @@ public:
llvm::StructType *MethodDescriptionListTy;
/// MethodDescriptionListPtrTy - LLVM type for struct
/// objc_method_description_list *.
- llvm::Type *MethodDescriptionListPtrTy;
+ llvm::PointerType *MethodDescriptionListPtrTy;
/// ProtocolListTy - LLVM type for struct objc_property_list.
llvm::StructType *ProtocolListTy;
/// ProtocolListPtrTy - LLVM type for struct objc_property_list*.
- llvm::Type *ProtocolListPtrTy;
+ llvm::PointerType *ProtocolListPtrTy;
/// CategoryTy - LLVM type for struct objc_category.
llvm::StructType *CategoryTy;
/// ClassTy - LLVM type for struct objc_class.
llvm::StructType *ClassTy;
/// ClassPtrTy - LLVM type for struct objc_class *.
- llvm::Type *ClassPtrTy;
+ llvm::PointerType *ClassPtrTy;
/// ClassExtensionTy - LLVM type for struct objc_class_ext.
llvm::StructType *ClassExtensionTy;
/// ClassExtensionPtrTy - LLVM type for struct objc_class_ext *.
- llvm::Type *ClassExtensionPtrTy;
+ llvm::PointerType *ClassExtensionPtrTy;
// IvarTy - LLVM type for struct objc_ivar.
llvm::StructType *IvarTy;
/// IvarListTy - LLVM type for struct objc_ivar_list.
- llvm::Type *IvarListTy;
+ llvm::StructType *IvarListTy;
/// IvarListPtrTy - LLVM type for struct objc_ivar_list *.
- llvm::Type *IvarListPtrTy;
+ llvm::PointerType *IvarListPtrTy;
/// MethodListTy - LLVM type for struct objc_method_list.
- llvm::Type *MethodListTy;
+ llvm::StructType *MethodListTy;
/// MethodListPtrTy - LLVM type for struct objc_method_list *.
- llvm::Type *MethodListPtrTy;
+ llvm::PointerType *MethodListPtrTy;
/// ExceptionDataTy - LLVM type for struct _objc_exception_data.
- llvm::Type *ExceptionDataTy;
+ llvm::StructType *ExceptionDataTy;
/// ExceptionTryEnterFn - LLVM objc_exception_try_enter function.
llvm::Constant *getExceptionTryEnterFn() {
@@ -608,25 +610,25 @@ public:
llvm::StructType *MethodListnfABITy;
// MethodListnfABIPtrTy - LLVM for struct _method_list_t*
- llvm::Type *MethodListnfABIPtrTy;
+ llvm::PointerType *MethodListnfABIPtrTy;
// ProtocolnfABITy = LLVM for struct _protocol_t
llvm::StructType *ProtocolnfABITy;
// ProtocolnfABIPtrTy = LLVM for struct _protocol_t*
- llvm::Type *ProtocolnfABIPtrTy;
+ llvm::PointerType *ProtocolnfABIPtrTy;
// ProtocolListnfABITy - LLVM for struct _objc_protocol_list
llvm::StructType *ProtocolListnfABITy;
// ProtocolListnfABIPtrTy - LLVM for struct _objc_protocol_list*
- llvm::Type *ProtocolListnfABIPtrTy;
+ llvm::PointerType *ProtocolListnfABIPtrTy;
// ClassnfABITy - LLVM for struct _class_t
llvm::StructType *ClassnfABITy;
// ClassnfABIPtrTy - LLVM for struct _class_t*
- llvm::Type *ClassnfABIPtrTy;
+ llvm::PointerType *ClassnfABIPtrTy;
// IvarnfABITy - LLVM for struct _ivar_t
llvm::StructType *IvarnfABITy;
@@ -635,13 +637,13 @@ public:
llvm::StructType *IvarListnfABITy;
// IvarListnfABIPtrTy = LLVM for struct _ivar_list_t*
- llvm::Type *IvarListnfABIPtrTy;
+ llvm::PointerType *IvarListnfABIPtrTy;
// ClassRonfABITy - LLVM for struct _class_ro_t
llvm::StructType *ClassRonfABITy;
// ImpnfABITy - LLVM for id (*)(id, SEL, ...)
- llvm::Type *ImpnfABITy;
+ llvm::PointerType *ImpnfABITy;
// CategorynfABITy - LLVM for struct _category_t
llvm::StructType *CategorynfABITy;
@@ -670,7 +672,7 @@ public:
llvm::StructType *SuperMessageRefTy;
// SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
- llvm::Type *SuperMessageRefPtrTy;
+ llvm::PointerType *SuperMessageRefPtrTy;
llvm::Constant *getMessageSendFixupFn() {
// id objc_msgSend_fixup(id, struct message_ref_t*, ...)
@@ -733,6 +735,13 @@ public:
ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm);
};
+enum class ObjCLabelType {
+ ClassName,
+ MethodVarName,
+ MethodVarType,
+ PropertyName,
+};
+
class CGObjCCommonMac : public CodeGen::CGObjCRuntime {
public:
class SKIP_SCAN {
@@ -836,7 +845,7 @@ protected:
llvm::DenseMap<Selector, llvm::GlobalVariable*> MethodVarNames;
/// DefinedCategoryNames - list of category names in form Class_Category.
- llvm::SmallSetVector<std::string, 16> DefinedCategoryNames;
+ llvm::SmallSetVector<llvm::CachedHashString, 16> DefinedCategoryNames;
/// MethodVarTypes - uniqued method type signatures. We have to use
/// a StringMap here because have no other unique reference.
@@ -879,6 +888,15 @@ protected:
/// DefinedNonLazyCategories - List of defined "non-lazy" categories.
SmallVector<llvm::GlobalValue*, 16> DefinedNonLazyCategories;
+ /// Cached reference to the class for constant strings. This value has type
+ /// int * but is actually an Obj-C class pointer.
+ llvm::WeakVH ConstantStringClassRef;
+
+ /// \brief The LLVM type corresponding to NSConstantString.
+ llvm::StructType *NSConstantStringType = nullptr;
+
+ llvm::StringMap<llvm::GlobalVariable *> NSConstantStringMap;
+
/// GetNameForMethod - Return a name for the given method.
/// \param[out] NameOut - The return value.
void GetNameForMethod(const ObjCMethodDecl *OMD,
@@ -979,15 +997,6 @@ protected:
ArrayRef<llvm::Constant*> MethodTypes,
const ObjCCommonTypesHelper &ObjCTypes);
- /// PushProtocolProperties - Push protocol's property on the input stack.
- void PushProtocolProperties(
- llvm::SmallPtrSet<const IdentifierInfo*, 16> &PropertySet,
- SmallVectorImpl<llvm::Constant*> &Properties,
- const Decl *Container,
- const ObjCProtocolDecl *Proto,
- const ObjCCommonTypesHelper &ObjCTypes,
- bool IsClassProperty);
-
/// GetProtocolRef - Return a reference to the internal protocol
/// description, creating an empty one if it has not been
/// defined. The return value has type ProtocolPtrTy.
@@ -1009,15 +1018,25 @@ public:
///
/// \param Name - The variable name.
/// \param Init - The variable initializer; this is also used to
- /// define the type of the variable.
+ /// define the type of the variable.
/// \param Section - The section the variable should go into, or empty.
/// \param Align - The alignment for the variable, or 0.
/// \param AddToUsed - Whether the variable should be added to
- /// "llvm.used".
- llvm::GlobalVariable *CreateMetadataVar(Twine Name, llvm::Constant *Init,
+ /// "llvm.used".
+ llvm::GlobalVariable *CreateMetadataVar(Twine Name,
+ ConstantStructBuilder &Init,
+ StringRef Section, CharUnits Align,
+ bool AddToUsed);
+ llvm::GlobalVariable *CreateMetadataVar(Twine Name,
+ llvm::Constant *Init,
StringRef Section, CharUnits Align,
bool AddToUsed);
+ llvm::GlobalVariable *CreateCStringLiteral(StringRef Name,
+ ObjCLabelType LabelType,
+ bool ForceNonFragileABI = false,
+ bool NullTerminate = true);
+
protected:
CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
ReturnValueSlot Return,
@@ -1044,6 +1063,7 @@ public:
}
ConstantAddress GenerateConstantString(const StringLiteral *SL) override;
+ ConstantAddress GenerateConstantNSString(const StringLiteral *SL);
llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
const ObjCContainerDecl *CD=nullptr) override;
@@ -1060,6 +1080,9 @@ public:
/// forward references will be filled in with empty bodies if no
/// definition is seen. The return value has type ProtocolPtrTy.
virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD)=0;
+
+ virtual llvm::Constant *getNSConstantStringClassRef() = 0;
+
llvm::Constant *BuildGCBlockLayout(CodeGen::CodeGenModule &CGM,
const CGBlockInfo &blockInfo) override;
llvm::Constant *BuildRCBlockLayout(CodeGen::CodeGenModule &CGM,
@@ -1069,8 +1092,95 @@ public:
QualType T) override;
};
+namespace {
+
+enum class MethodListType {
+ CategoryInstanceMethods,
+ CategoryClassMethods,
+ InstanceMethods,
+ ClassMethods,
+ ProtocolInstanceMethods,
+ ProtocolClassMethods,
+ OptionalProtocolInstanceMethods,
+ OptionalProtocolClassMethods,
+};
+
+/// A convenience class for splitting the methods of a protocol into
+/// the four interesting groups.
+class ProtocolMethodLists {
+public:
+ enum Kind {
+ RequiredInstanceMethods,
+ RequiredClassMethods,
+ OptionalInstanceMethods,
+ OptionalClassMethods
+ };
+ enum {
+ NumProtocolMethodLists = 4
+ };
+
+ static MethodListType getMethodListKind(Kind kind) {
+ switch (kind) {
+ case RequiredInstanceMethods:
+ return MethodListType::ProtocolInstanceMethods;
+ case RequiredClassMethods:
+ return MethodListType::ProtocolClassMethods;
+ case OptionalInstanceMethods:
+ return MethodListType::OptionalProtocolInstanceMethods;
+ case OptionalClassMethods:
+ return MethodListType::OptionalProtocolClassMethods;
+ }
+ llvm_unreachable("bad kind");
+ }
+
+ SmallVector<const ObjCMethodDecl *, 4> Methods[NumProtocolMethodLists];
+
+ static ProtocolMethodLists get(const ObjCProtocolDecl *PD) {
+ ProtocolMethodLists result;
+
+ for (auto MD : PD->methods()) {
+ size_t index = (2 * size_t(MD->isOptional()))
+ + (size_t(MD->isClassMethod()));
+ result.Methods[index].push_back(MD);
+ }
+
+ return result;
+ }
+
+ template <class Self>
+ SmallVector<llvm::Constant*, 8> emitExtendedTypesArray(Self *self) const {
+ // In both ABIs, the method types list is parallel with the
+ // concatenation of the methods arrays in the following order:
+ // instance methods
+ // class methods
+ // optional instance methods
+ // optional class methods
+ SmallVector<llvm::Constant*, 8> result;
+
+ // Methods is already in the correct order for both ABIs.
+ for (auto &list : Methods) {
+ for (auto MD : list) {
+ result.push_back(self->GetMethodVarType(MD, true));
+ }
+ }
+
+ return result;
+ }
+
+ template <class Self>
+ llvm::Constant *emitMethodList(Self *self, const ObjCProtocolDecl *PD,
+ Kind kind) const {
+ return self->emitMethodList(PD->getObjCRuntimeNameAsString(),
+ getMethodListKind(kind), Methods[kind]);
+ }
+};
+
+} // end anonymous namespace
+
class CGObjCMac : public CGObjCCommonMac {
private:
+ friend ProtocolMethodLists;
+
ObjCTypesHelper ObjCTypes;
/// EmitModuleInfo - Another marker encoding module level
@@ -1091,7 +1201,7 @@ private:
llvm::Constant *EmitClassExtension(const ObjCImplementationDecl *ID,
CharUnits instanceSize,
bool hasMRCWeakIvars,
- bool isClassProperty);
+ bool isMetaclass);
/// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
/// for the given class.
@@ -1123,30 +1233,18 @@ private:
/// given implementation. The return value has type ClassPtrTy.
llvm::Constant *EmitMetaClass(const ObjCImplementationDecl *ID,
llvm::Constant *Protocols,
- ArrayRef<llvm::Constant*> Methods);
+ ArrayRef<const ObjCMethodDecl *> Methods);
- llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
+ void emitMethodConstant(ConstantArrayBuilder &builder,
+ const ObjCMethodDecl *MD);
- llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
+ void emitMethodDescriptionConstant(ConstantArrayBuilder &builder,
+ const ObjCMethodDecl *MD);
/// EmitMethodList - Emit the method list for the given
/// implementation. The return value has type MethodListPtrTy.
- llvm::Constant *EmitMethodList(Twine Name, StringRef Section,
- ArrayRef<llvm::Constant *> Methods);
-
- /// EmitMethodDescList - Emit a method description list for a list of
- /// method declarations.
- /// - TypeName: The name for the type containing the methods.
- /// - IsProtocol: True iff these methods are for a protocol.
- /// - ClassMethds: True iff these are class methods.
- /// - Required: When true, only "required" methods are
- /// listed. Similarly, when false only "optional" methods are
- /// listed. For classes this should always be true.
- /// - begin, end: The method list to output.
- ///
- /// The return value has type MethodDescriptionListPtrTy.
- llvm::Constant *EmitMethodDescList(Twine Name, StringRef Section,
- ArrayRef<llvm::Constant *> Methods);
+ llvm::Constant *emitMethodList(Twine Name, MethodListType MLT,
+ ArrayRef<const ObjCMethodDecl *> Methods);
/// GetOrEmitProtocol - Get the protocol object for the given
/// declaration, emitting it if necessary. The return value has type
@@ -1165,9 +1263,7 @@ private:
/// ProtocolExtensionPtrTy.
llvm::Constant *
EmitProtocolExtension(const ObjCProtocolDecl *PD,
- ArrayRef<llvm::Constant*> OptInstanceMethods,
- ArrayRef<llvm::Constant*> OptClassMethods,
- ArrayRef<llvm::Constant*> MethodTypesExt);
+ const ProtocolMethodLists &methodLists);
/// EmitProtocolList - Generate the list of referenced
/// protocols. The return value has type ProtocolListPtrTy.
@@ -1183,6 +1279,8 @@ private:
public:
CGObjCMac(CodeGen::CodeGenModule &cgm);
+ llvm::Constant *getNSConstantStringClassRef() override;
+
llvm::Function *ModuleInitFunction() override;
CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
@@ -1262,20 +1360,14 @@ public:
llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
const ObjCInterfaceDecl *Interface,
const ObjCIvarDecl *Ivar) override;
-
- /// GetClassGlobal - Return the global variable for the Objective-C
- /// class of the given name.
- llvm::GlobalVariable *GetClassGlobal(StringRef Name,
- bool Weak = false) override {
- llvm_unreachable("CGObjCMac::GetClassGlobal");
- }
};
class CGObjCNonFragileABIMac : public CGObjCCommonMac {
private:
+ friend ProtocolMethodLists;
ObjCNonFragileABITypesHelper ObjCTypes;
llvm::GlobalVariable* ObjCEmptyCacheVar;
- llvm::GlobalVariable* ObjCEmptyVtableVar;
+ llvm::Constant* ObjCEmptyVtableVar;
/// SuperClassReferences - uniqued super class references.
llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> SuperClassReferences;
@@ -1310,21 +1402,22 @@ private:
unsigned InstanceStart,
unsigned InstanceSize,
const ObjCImplementationDecl *ID);
- llvm::GlobalVariable * BuildClassMetaData(const std::string &ClassName,
- llvm::Constant *IsAGV,
- llvm::Constant *SuperClassGV,
- llvm::Constant *ClassRoGV,
- bool HiddenVisibility,
- bool Weak);
-
- llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
+ llvm::GlobalVariable *BuildClassObject(const ObjCInterfaceDecl *CI,
+ bool isMetaclass,
+ llvm::Constant *IsAGV,
+ llvm::Constant *SuperClassGV,
+ llvm::Constant *ClassRoGV,
+ bool HiddenVisibility);
+
+ void emitMethodConstant(ConstantArrayBuilder &builder,
+ const ObjCMethodDecl *MD,
+ bool forProtocol);
+
+ /// Emit the method list for the given implementation. The return value
+ /// has type MethodListnfABITy.
+ llvm::Constant *emitMethodList(Twine Name, MethodListType MLT,
+ ArrayRef<const ObjCMethodDecl *> Methods);
- llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
-
- /// EmitMethodList - Emit the method list for the given
- /// implementation. The return value has type MethodListnfABITy.
- llvm::Constant *EmitMethodList(Twine Name, StringRef Section,
- ArrayRef<llvm::Constant *> Methods);
/// EmitIvarList - Emit the ivar list for the given
/// implementation. If ForClass is true the list of class ivars
/// (i.e. metaclass ivars) is emitted, otherwise the list of
@@ -1365,8 +1458,12 @@ private:
/// GetClassGlobal - Return the global variable for the Objective-C
/// class of the given name.
- llvm::GlobalVariable *GetClassGlobal(StringRef Name,
- bool Weak = false) override;
+ llvm::Constant *GetClassGlobal(StringRef Name,
+ ForDefinition_t IsForDefinition,
+ bool Weak = false, bool DLLImport = false);
+ llvm::Constant *GetClassGlobal(const ObjCInterfaceDecl *ID,
+ bool isMetaclass,
+ ForDefinition_t isForDefinition);
/// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
/// for the given class reference.
@@ -1374,7 +1471,7 @@ private:
const ObjCInterfaceDecl *ID);
llvm::Value *EmitClassRefFromId(CodeGenFunction &CGF,
- IdentifierInfo *II, bool Weak,
+ IdentifierInfo *II,
const ObjCInterfaceDecl *ID);
llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) override;
@@ -1404,7 +1501,7 @@ private:
/// GetInterfaceEHType - Get the cached ehtype for the given Objective-C
/// interface. The return value has type EHTypePtrTy.
llvm::Constant *GetInterfaceEHType(const ObjCInterfaceDecl *ID,
- bool ForDefinition);
+ ForDefinition_t IsForDefinition);
StringRef getMetaclassSymbolPrefix() const { return "OBJC_METACLASS_$_"; }
@@ -1451,7 +1548,9 @@ private:
public:
CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm);
- // FIXME. All stubs for now!
+
+ llvm::Constant *getNSConstantStringClassRef() override;
+
llvm::Function *ModuleInitFunction() override;
CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
@@ -1761,11 +1860,115 @@ llvm::Constant *CGObjCMac::GetEHType(QualType T) {
};
*/
-ConstantAddress CGObjCCommonMac::GenerateConstantString(
- const StringLiteral *SL) {
- return (CGM.getLangOpts().NoConstantCFStrings == 0 ?
- CGM.GetAddrOfConstantCFString(SL) :
- CGM.GetAddrOfConstantString(SL));
+ConstantAddress
+CGObjCCommonMac::GenerateConstantString(const StringLiteral *SL) {
+ return (!CGM.getLangOpts().NoConstantCFStrings
+ ? CGM.GetAddrOfConstantCFString(SL)
+ : GenerateConstantNSString(SL));
+}
+
+static llvm::StringMapEntry<llvm::GlobalVariable *> &
+GetConstantStringEntry(llvm::StringMap<llvm::GlobalVariable *> &Map,
+ const StringLiteral *Literal, unsigned &StringLength) {
+ StringRef String = Literal->getString();
+ StringLength = String.size();
+ return *Map.insert(std::make_pair(String, nullptr)).first;
+}
+
+llvm::Constant *CGObjCMac::getNSConstantStringClassRef() {
+ if (llvm::Value *V = ConstantStringClassRef)
+ return cast<llvm::Constant>(V);
+
+ auto &StringClass = CGM.getLangOpts().ObjCConstantStringClass;
+ std::string str =
+ StringClass.empty() ? "_NSConstantStringClassReference"
+ : "_" + StringClass + "ClassReference";
+
+ llvm::Type *PTy = llvm::ArrayType::get(CGM.IntTy, 0);
+ auto GV = CGM.CreateRuntimeVariable(PTy, str);
+ auto V = llvm::ConstantExpr::getBitCast(GV, CGM.IntTy->getPointerTo());
+ ConstantStringClassRef = V;
+ return V;
+}
+
+llvm::Constant *CGObjCNonFragileABIMac::getNSConstantStringClassRef() {
+ if (llvm::Value *V = ConstantStringClassRef)
+ return cast<llvm::Constant>(V);
+
+ auto &StringClass = CGM.getLangOpts().ObjCConstantStringClass;
+ std::string str =
+ StringClass.empty() ? "OBJC_CLASS_$_NSConstantString"
+ : "OBJC_CLASS_$_" + StringClass;
+ auto GV = GetClassGlobal(str, NotForDefinition);
+
+ // Make sure the result is of the correct type.
+ auto V = llvm::ConstantExpr::getBitCast(GV, CGM.IntTy->getPointerTo());
+
+ ConstantStringClassRef = V;
+ return V;
+}
+
+ConstantAddress
+CGObjCCommonMac::GenerateConstantNSString(const StringLiteral *Literal) {
+ unsigned StringLength = 0;
+ llvm::StringMapEntry<llvm::GlobalVariable *> &Entry =
+ GetConstantStringEntry(NSConstantStringMap, Literal, StringLength);
+
+ if (auto *C = Entry.second)
+ return ConstantAddress(C, CharUnits::fromQuantity(C->getAlignment()));
+
+ // If we don't already have it, get _NSConstantStringClassReference.
+ llvm::Constant *Class = getNSConstantStringClassRef();
+
+ // If we don't already have it, construct the type for a constant NSString.
+ if (!NSConstantStringType) {
+ NSConstantStringType =
+ llvm::StructType::create({
+ CGM.Int32Ty->getPointerTo(),
+ CGM.Int8PtrTy,
+ CGM.IntTy
+ }, "struct.__builtin_NSString");
+ }
+
+ ConstantInitBuilder Builder(CGM);
+ auto Fields = Builder.beginStruct(NSConstantStringType);
+
+ // Class pointer.
+ Fields.add(Class);
+
+ // String pointer.
+ llvm::Constant *C =
+ llvm::ConstantDataArray::getString(VMContext, Entry.first());
+
+ llvm::GlobalValue::LinkageTypes Linkage = llvm::GlobalValue::PrivateLinkage;
+ bool isConstant = !CGM.getLangOpts().WritableStrings;
+
+ auto *GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), isConstant,
+ Linkage, C, ".str");
+ GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
+ // Don't enforce the target's minimum global alignment, since the only use
+ // of the string is via this class initializer.
+ GV->setAlignment(1);
+ Fields.addBitCast(GV, CGM.Int8PtrTy);
+
+ // String length.
+ Fields.addInt(CGM.IntTy, StringLength);
+
+ // The struct.
+ CharUnits Alignment = CGM.getPointerAlign();
+ GV = Fields.finishAndCreateGlobal("_unnamed_nsstring_", Alignment,
+ /*constant*/ true,
+ llvm::GlobalVariable::PrivateLinkage);
+ const char *NSStringSection = "__OBJC,__cstring_object,regular,no_dead_strip";
+ const char *NSStringNonFragileABISection =
+ "__DATA,__objc_stringobj,regular,no_dead_strip";
+ // FIXME. Fix section.
+ GV->setSection(CGM.getLangOpts().ObjCRuntime.isNonFragile()
+ ? NSStringNonFragileABISection
+ : NSStringSection);
+ Entry.second = GV;
+
+ return ConstantAddress(GV, Alignment);
}
enum {
@@ -1953,8 +2156,9 @@ CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF,
llvm::Instruction *CallSite;
Fn = llvm::ConstantExpr::getBitCast(Fn, MSI.MessengerType);
- RValue rvalue = CGF.EmitCall(MSI.CallInfo, Fn, Return, ActualArgs,
- CGCalleeInfo(), &CallSite);
+ CGCallee Callee = CGCallee::forDirect(Fn);
+ RValue rvalue = CGF.EmitCall(MSI.CallInfo, Callee, Return, ActualArgs,
+ &CallSite);
// Mark the call as noreturn if the method is marked noreturn and the
// receiver cannot be null.
@@ -2576,10 +2780,9 @@ llvm::Constant *CGObjCCommonMac::getBitmapBlockLayout(bool ComputeByrefLayout) {
}
}
- llvm::GlobalVariable *Entry = CreateMetadataVar(
- "OBJC_CLASS_NAME_",
- llvm::ConstantDataArray::getString(VMContext, BitMap, false),
- "__TEXT,__objc_classname,cstring_literals", CharUnits::One(), true);
+ auto *Entry = CreateCStringLiteral(BitMap, ObjCLabelType::ClassName,
+ /*ForceNonFragileABI=*/true,
+ /*NullTerminate=*/false);
return getConstantGEP(VMContext, Entry, 0, 0);
}
@@ -2730,66 +2933,29 @@ llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
// Construct method lists.
- std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
- std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
- std::vector<llvm::Constant*> MethodTypesExt, OptMethodTypesExt;
- for (const auto *MD : PD->instance_methods()) {
- llvm::Constant *C = GetMethodDescriptionConstant(MD);
- if (!C)
- return GetOrEmitProtocolRef(PD);
-
- if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
- OptInstanceMethods.push_back(C);
- OptMethodTypesExt.push_back(GetMethodVarType(MD, true));
- } else {
- InstanceMethods.push_back(C);
- MethodTypesExt.push_back(GetMethodVarType(MD, true));
- }
- }
-
- for (const auto *MD : PD->class_methods()) {
- llvm::Constant *C = GetMethodDescriptionConstant(MD);
- if (!C)
- return GetOrEmitProtocolRef(PD);
-
- if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
- OptClassMethods.push_back(C);
- OptMethodTypesExt.push_back(GetMethodVarType(MD, true));
- } else {
- ClassMethods.push_back(C);
- MethodTypesExt.push_back(GetMethodVarType(MD, true));
- }
- }
-
- MethodTypesExt.insert(MethodTypesExt.end(),
- OptMethodTypesExt.begin(), OptMethodTypesExt.end());
-
- llvm::Constant *Values[] = {
- EmitProtocolExtension(PD, OptInstanceMethods, OptClassMethods,
- MethodTypesExt),
- GetClassName(PD->getObjCRuntimeNameAsString()),
- EmitProtocolList("OBJC_PROTOCOL_REFS_" + PD->getName(),
- PD->protocol_begin(), PD->protocol_end()),
- EmitMethodDescList("OBJC_PROTOCOL_INSTANCE_METHODS_" + PD->getName(),
- "__OBJC,__cat_inst_meth,regular,no_dead_strip",
- InstanceMethods),
- EmitMethodDescList("OBJC_PROTOCOL_CLASS_METHODS_" + PD->getName(),
- "__OBJC,__cat_cls_meth,regular,no_dead_strip",
- ClassMethods)};
- llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
- Values);
+ auto methodLists = ProtocolMethodLists::get(PD);
+
+ ConstantInitBuilder builder(CGM);
+ auto values = builder.beginStruct(ObjCTypes.ProtocolTy);
+ values.add(EmitProtocolExtension(PD, methodLists));
+ values.add(GetClassName(PD->getObjCRuntimeNameAsString()));
+ values.add(EmitProtocolList("OBJC_PROTOCOL_REFS_" + PD->getName(),
+ PD->protocol_begin(), PD->protocol_end()));
+ values.add(methodLists.emitMethodList(this, PD,
+ ProtocolMethodLists::RequiredInstanceMethods));
+ values.add(methodLists.emitMethodList(this, PD,
+ ProtocolMethodLists::RequiredClassMethods));
if (Entry) {
// Already created, update the initializer.
assert(Entry->hasPrivateLinkage());
- Entry->setInitializer(Init);
+ values.finishAndSetAsInitializer(Entry);
} else {
- Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy,
- false, llvm::GlobalValue::PrivateLinkage,
- Init, "OBJC_PROTOCOL_" + PD->getName());
+ Entry = values.finishAndCreateGlobal("OBJC_PROTOCOL_" + PD->getName(),
+ CGM.getPointerAlign(),
+ /*constant*/ false,
+ llvm::GlobalValue::PrivateLinkage);
Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
- // FIXME: Is this necessary? Why only for protocol?
- Entry->setAlignment(4);
Protocols[PD->getIdentifier()] = Entry;
}
@@ -2828,37 +2994,49 @@ llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) {
*/
llvm::Constant *
CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
- ArrayRef<llvm::Constant*> OptInstanceMethods,
- ArrayRef<llvm::Constant*> OptClassMethods,
- ArrayRef<llvm::Constant*> MethodTypesExt) {
- uint64_t Size =
- CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy);
- llvm::Constant *Values[] = {
- llvm::ConstantInt::get(ObjCTypes.IntTy, Size),
- EmitMethodDescList("OBJC_PROTOCOL_INSTANCE_METHODS_OPT_" + PD->getName(),
- "__OBJC,__cat_inst_meth,regular,no_dead_strip",
- OptInstanceMethods),
- EmitMethodDescList("OBJC_PROTOCOL_CLASS_METHODS_OPT_" + PD->getName(),
- "__OBJC,__cat_cls_meth,regular,no_dead_strip",
- OptClassMethods),
- EmitPropertyList("OBJC_$_PROP_PROTO_LIST_" + PD->getName(), nullptr, PD,
- ObjCTypes, false),
- EmitProtocolMethodTypes("OBJC_PROTOCOL_METHOD_TYPES_" + PD->getName(),
- MethodTypesExt, ObjCTypes),
- EmitPropertyList("OBJC_$_CLASS_PROP_PROTO_LIST_" + PD->getName(), nullptr,
- PD, ObjCTypes, true)};
+ const ProtocolMethodLists &methodLists) {
+ auto optInstanceMethods =
+ methodLists.emitMethodList(this, PD,
+ ProtocolMethodLists::OptionalInstanceMethods);
+ auto optClassMethods =
+ methodLists.emitMethodList(this, PD,
+ ProtocolMethodLists::OptionalClassMethods);
+
+ auto extendedMethodTypes =
+ EmitProtocolMethodTypes("OBJC_PROTOCOL_METHOD_TYPES_" + PD->getName(),
+ methodLists.emitExtendedTypesArray(this),
+ ObjCTypes);
+
+ auto instanceProperties =
+ EmitPropertyList("OBJC_$_PROP_PROTO_LIST_" + PD->getName(), nullptr, PD,
+ ObjCTypes, false);
+ auto classProperties =
+ EmitPropertyList("OBJC_$_CLASS_PROP_PROTO_LIST_" + PD->getName(), nullptr,
+ PD, ObjCTypes, true);
// Return null if no extension bits are used.
- if (Values[1]->isNullValue() && Values[2]->isNullValue() &&
- Values[3]->isNullValue() && Values[4]->isNullValue() &&
- Values[5]->isNullValue())
+ if (optInstanceMethods->isNullValue() &&
+ optClassMethods->isNullValue() &&
+ extendedMethodTypes->isNullValue() &&
+ instanceProperties->isNullValue() &&
+ classProperties->isNullValue()) {
return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
+ }
- llvm::Constant *Init =
- llvm::ConstantStruct::get(ObjCTypes.ProtocolExtensionTy, Values);
+ uint64_t size =
+ CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy);
+
+ ConstantInitBuilder builder(CGM);
+ auto values = builder.beginStruct(ObjCTypes.ProtocolExtensionTy);
+ values.addInt(ObjCTypes.IntTy, size);
+ values.add(optInstanceMethods);
+ values.add(optClassMethods);
+ values.add(instanceProperties);
+ values.add(extendedMethodTypes);
+ values.add(classProperties);
// No special section, but goes in llvm.used
- return CreateMetadataVar("\01l_OBJC_PROTOCOLEXT_" + PD->getName(), Init,
+ return CreateMetadataVar("\01l_OBJC_PROTOCOLEXT_" + PD->getName(), values,
StringRef(), CGM.getPointerAlign(), true);
}
@@ -2870,59 +3048,57 @@ CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
};
*/
llvm::Constant *
-CGObjCMac::EmitProtocolList(Twine Name,
+CGObjCMac::EmitProtocolList(Twine name,
ObjCProtocolDecl::protocol_iterator begin,
ObjCProtocolDecl::protocol_iterator end) {
- SmallVector<llvm::Constant *, 16> ProtocolRefs;
-
- for (; begin != end; ++begin)
- ProtocolRefs.push_back(GetProtocolRef(*begin));
-
// Just return null for empty protocol lists
- if (ProtocolRefs.empty())
+ if (begin == end)
return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
- // This list is null terminated.
- ProtocolRefs.push_back(llvm::Constant::getNullValue(ObjCTypes.ProtocolPtrTy));
+ ConstantInitBuilder builder(CGM);
+ auto values = builder.beginStruct();
- llvm::Constant *Values[3];
// This field is only used by the runtime.
- Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
- Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy,
- ProtocolRefs.size() - 1);
- Values[2] =
- llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.ProtocolPtrTy,
- ProtocolRefs.size()),
- ProtocolRefs);
-
- llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
+ values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
+
+ // Reserve a slot for the count.
+ auto countSlot = values.addPlaceholder();
+
+ auto refsArray = values.beginArray(ObjCTypes.ProtocolPtrTy);
+ for (; begin != end; ++begin) {
+ refsArray.add(GetProtocolRef(*begin));
+ }
+ auto count = refsArray.size();
+
+ // This list is null terminated.
+ refsArray.addNullPointer(ObjCTypes.ProtocolPtrTy);
+
+ refsArray.finishAndAddTo(values);
+ values.fillPlaceholderWithInt(countSlot, ObjCTypes.LongTy, count);
+
+ StringRef section;
+ if (CGM.getTriple().isOSBinFormatMachO())
+ section = "__OBJC,__cat_cls_meth,regular,no_dead_strip";
+
llvm::GlobalVariable *GV =
- CreateMetadataVar(Name, Init, "__OBJC,__cat_cls_meth,regular,no_dead_strip",
- CGM.getPointerAlign(), false);
+ CreateMetadataVar(name, values, section, CGM.getPointerAlign(), false);
return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListPtrTy);
}
-void CGObjCCommonMac::
+static void
PushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo*,16> &PropertySet,
- SmallVectorImpl<llvm::Constant *> &Properties,
- const Decl *Container,
+ SmallVectorImpl<const ObjCPropertyDecl *> &Properties,
const ObjCProtocolDecl *Proto,
- const ObjCCommonTypesHelper &ObjCTypes,
bool IsClassProperty) {
for (const auto *P : Proto->protocols())
- PushProtocolProperties(PropertySet, Properties, Container, P, ObjCTypes,
- IsClassProperty);
+ PushProtocolProperties(PropertySet, Properties, P, IsClassProperty);
for (const auto *PD : Proto->properties()) {
if (IsClassProperty != PD->isClassProperty())
continue;
if (!PropertySet.insert(PD->getIdentifier()).second)
continue;
- llvm::Constant *Prop[] = {
- GetPropertyName(PD->getIdentifier()),
- GetPropertyTypeString(PD, Container)
- };
- Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy, Prop));
+ Properties.push_back(PD);
}
}
@@ -2952,21 +3128,16 @@ llvm::Constant *CGObjCCommonMac::EmitPropertyList(Twine Name,
return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
}
- SmallVector<llvm::Constant *, 16> Properties;
+ SmallVector<const ObjCPropertyDecl *, 16> Properties;
llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet;
- auto AddProperty = [&](const ObjCPropertyDecl *PD) {
- llvm::Constant *Prop[] = {GetPropertyName(PD->getIdentifier()),
- GetPropertyTypeString(PD, Container)};
- Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy, Prop));
- };
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());
- AddProperty(PD);
+ Properties.push_back(PD);
}
for (const auto *PD : OCD->properties()) {
@@ -2976,40 +3147,45 @@ llvm::Constant *CGObjCCommonMac::EmitPropertyList(Twine Name,
// class extension.
if (!PropertySet.insert(PD->getIdentifier()).second)
continue;
- AddProperty(PD);
+ Properties.push_back(PD);
}
if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD)) {
for (const auto *P : OID->all_referenced_protocols())
- PushProtocolProperties(PropertySet, Properties, Container, P, ObjCTypes,
- IsClassProperty);
+ PushProtocolProperties(PropertySet, Properties, P, IsClassProperty);
}
else if (const ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(OCD)) {
for (const auto *P : CD->protocols())
- PushProtocolProperties(PropertySet, Properties, Container, P, ObjCTypes,
- IsClassProperty);
+ PushProtocolProperties(PropertySet, Properties, P, IsClassProperty);
}
// Return null for empty list.
if (Properties.empty())
return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
- unsigned PropertySize =
+ unsigned propertySize =
CGM.getDataLayout().getTypeAllocSize(ObjCTypes.PropertyTy);
- llvm::Constant *Values[3];
- Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, PropertySize);
- Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Properties.size());
- llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.PropertyTy,
- Properties.size());
- Values[2] = llvm::ConstantArray::get(AT, Properties);
- llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
+
+ ConstantInitBuilder builder(CGM);
+ auto values = builder.beginStruct();
+ values.addInt(ObjCTypes.IntTy, propertySize);
+ values.addInt(ObjCTypes.IntTy, Properties.size());
+ auto propertiesArray = values.beginArray(ObjCTypes.PropertyTy);
+ for (auto PD : Properties) {
+ auto property = propertiesArray.beginStruct(ObjCTypes.PropertyTy);
+ property.add(GetPropertyName(PD->getIdentifier()));
+ property.add(GetPropertyTypeString(PD, Container));
+ property.finishAndAddTo(propertiesArray);
+ }
+ propertiesArray.finishAndAddTo(values);
+
+ StringRef Section;
+ if (CGM.getTriple().isOSBinFormatMachO())
+ Section = (ObjCABI == 2) ? "__DATA, __objc_const"
+ : "__OBJC,__property,regular,no_dead_strip";
llvm::GlobalVariable *GV =
- CreateMetadataVar(Name, Init,
- (ObjCABI == 2) ? "__DATA, __objc_const" :
- "__OBJC,__property,regular,no_dead_strip",
- CGM.getPointerAlign(),
- true);
+ CreateMetadataVar(Name, values, Section, CGM.getPointerAlign(), true);
return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.PropertyListPtrTy);
}
@@ -3025,50 +3201,13 @@ CGObjCCommonMac::EmitProtocolMethodTypes(Twine Name,
MethodTypes.size());
llvm::Constant *Init = llvm::ConstantArray::get(AT, MethodTypes);
- llvm::GlobalVariable *GV = CreateMetadataVar(
- Name, Init, (ObjCABI == 2) ? "__DATA, __objc_const" : StringRef(),
- CGM.getPointerAlign(), true);
- return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.Int8PtrPtrTy);
-}
-
-/*
- struct objc_method_description_list {
- int count;
- struct objc_method_description list[];
- };
-*/
-llvm::Constant *
-CGObjCMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
- llvm::Constant *Desc[] = {
- llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
- ObjCTypes.SelectorPtrTy),
- GetMethodVarType(MD)
- };
- if (!Desc[1])
- return nullptr;
-
- return llvm::ConstantStruct::get(ObjCTypes.MethodDescriptionTy,
- Desc);
-}
-
-llvm::Constant *
-CGObjCMac::EmitMethodDescList(Twine Name, StringRef Section,
- ArrayRef<llvm::Constant *> Methods) {
- // Return null for empty list.
- if (Methods.empty())
- return llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
-
- llvm::Constant *Values[2];
- Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
- llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodDescriptionTy,
- Methods.size());
- Values[1] = llvm::ConstantArray::get(AT, Methods);
- llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
+ StringRef Section;
+ if (CGM.getTriple().isOSBinFormatMachO() && ObjCABI == 2)
+ Section = "__DATA, __objc_const";
llvm::GlobalVariable *GV =
- CreateMetadataVar(Name, Init, Section, CGM.getPointerAlign(), true);
- return llvm::ConstantExpr::getBitCast(GV,
- ObjCTypes.MethodDescriptionListPtrTy);
+ CreateMetadataVar(Name, Init, Section, CGM.getPointerAlign(), true);
+ return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.Int8PtrPtrTy);
}
/*
@@ -3098,54 +3237,53 @@ void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
llvm::raw_svector_ostream(ExtName) << Interface->getName() << '_'
<< OCD->getName();
- SmallVector<llvm::Constant *, 16> InstanceMethods, ClassMethods;
- for (const auto *I : OCD->instance_methods())
- // Instance methods should always be defined.
- InstanceMethods.push_back(GetMethodConstant(I));
+ ConstantInitBuilder Builder(CGM);
+ auto Values = Builder.beginStruct(ObjCTypes.CategoryTy);
- for (const auto *I : OCD->class_methods())
- // Class methods should always be defined.
- ClassMethods.push_back(GetMethodConstant(I));
+ enum {
+ InstanceMethods,
+ ClassMethods,
+ NumMethodLists
+ };
+ SmallVector<const ObjCMethodDecl *, 16> Methods[NumMethodLists];
+ for (const auto *MD : OCD->methods()) {
+ Methods[unsigned(MD->isClassMethod())].push_back(MD);
+ }
- llvm::Constant *Values[8];
- Values[0] = GetClassName(OCD->getName());
- Values[1] = GetClassName(Interface->getObjCRuntimeNameAsString());
+ Values.add(GetClassName(OCD->getName()));
+ Values.add(GetClassName(Interface->getObjCRuntimeNameAsString()));
LazySymbols.insert(Interface->getIdentifier());
- Values[2] = EmitMethodList("OBJC_CATEGORY_INSTANCE_METHODS_" + ExtName.str(),
- "__OBJC,__cat_inst_meth,regular,no_dead_strip",
- InstanceMethods);
- Values[3] = EmitMethodList("OBJC_CATEGORY_CLASS_METHODS_" + ExtName.str(),
- "__OBJC,__cat_cls_meth,regular,no_dead_strip",
- ClassMethods);
+
+ Values.add(emitMethodList(ExtName, MethodListType::CategoryInstanceMethods,
+ Methods[InstanceMethods]));
+ Values.add(emitMethodList(ExtName, MethodListType::CategoryClassMethods,
+ Methods[ClassMethods]));
if (Category) {
- Values[4] =
+ Values.add(
EmitProtocolList("OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(),
- Category->protocol_begin(), Category->protocol_end());
+ Category->protocol_begin(), Category->protocol_end()));
} else {
- Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
+ Values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
}
- Values[5] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
+ Values.addInt(ObjCTypes.IntTy, Size);
// If there is no category @interface then there can be no properties.
if (Category) {
- Values[6] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
- OCD, Category, ObjCTypes, false);
- Values[7] = EmitPropertyList("\01l_OBJC_$_CLASS_PROP_LIST_" + ExtName.str(),
- OCD, Category, ObjCTypes, true);
+ Values.add(EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
+ OCD, Category, ObjCTypes, false));
+ Values.add(EmitPropertyList("\01l_OBJC_$_CLASS_PROP_LIST_" + ExtName.str(),
+ OCD, Category, ObjCTypes, true));
} else {
- Values[6] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
- Values[7] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
+ Values.addNullPointer(ObjCTypes.PropertyListPtrTy);
+ Values.addNullPointer(ObjCTypes.PropertyListPtrTy);
}
- llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.CategoryTy,
- Values);
-
llvm::GlobalVariable *GV =
- CreateMetadataVar("OBJC_CATEGORY_" + ExtName.str(), Init,
+ CreateMetadataVar("OBJC_CATEGORY_" + ExtName.str(), Values,
"__OBJC,__category,regular,no_dead_strip",
CGM.getPointerAlign(), true);
DefinedCategories.push_back(GV);
- DefinedCategoryNames.insert(ExtName.str());
+ DefinedCategoryNames.insert(llvm::CachedHashString(ExtName));
// method definition entries must be clear for next implementation.
MethodDefinitions.clear();
}
@@ -3282,57 +3420,56 @@ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
Flags |= FragileABI_Class_Hidden;
- SmallVector<llvm::Constant *, 16> InstanceMethods, ClassMethods;
- for (const auto *I : ID->instance_methods())
- // Instance methods should always be defined.
- InstanceMethods.push_back(GetMethodConstant(I));
-
- for (const auto *I : ID->class_methods())
- // Class methods should always be defined.
- ClassMethods.push_back(GetMethodConstant(I));
+ enum {
+ InstanceMethods,
+ ClassMethods,
+ NumMethodLists
+ };
+ SmallVector<const ObjCMethodDecl *, 16> Methods[NumMethodLists];
+ for (const auto *MD : ID->methods()) {
+ Methods[unsigned(MD->isClassMethod())].push_back(MD);
+ }
for (const auto *PID : ID->property_impls()) {
if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) {
ObjCPropertyDecl *PD = PID->getPropertyDecl();
if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
- if (llvm::Constant *C = GetMethodConstant(MD))
- InstanceMethods.push_back(C);
+ if (GetMethodDefinition(MD))
+ Methods[InstanceMethods].push_back(MD);
if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
- if (llvm::Constant *C = GetMethodConstant(MD))
- InstanceMethods.push_back(C);
+ if (GetMethodDefinition(MD))
+ Methods[InstanceMethods].push_back(MD);
}
}
- llvm::Constant *Values[12];
- Values[ 0] = EmitMetaClass(ID, Protocols, ClassMethods);
+ ConstantInitBuilder builder(CGM);
+ auto values = builder.beginStruct(ObjCTypes.ClassTy);
+ values.add(EmitMetaClass(ID, Protocols, Methods[ClassMethods]));
if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) {
// Record a reference to the super class.
LazySymbols.insert(Super->getIdentifier());
- Values[ 1] =
- llvm::ConstantExpr::getBitCast(GetClassName(Super->getObjCRuntimeNameAsString()),
- ObjCTypes.ClassPtrTy);
+ values.addBitCast(GetClassName(Super->getObjCRuntimeNameAsString()),
+ ObjCTypes.ClassPtrTy);
} else {
- Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
+ values.addNullPointer(ObjCTypes.ClassPtrTy);
}
- Values[ 2] = GetClassName(ID->getObjCRuntimeNameAsString());
+ values.add(GetClassName(ID->getObjCRuntimeNameAsString()));
// Version is always 0.
- Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
- Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
- Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size.getQuantity());
- Values[ 6] = EmitIvarList(ID, false);
- Values[7] = EmitMethodList("OBJC_INSTANCE_METHODS_" + ID->getName(),
- "__OBJC,__inst_meth,regular,no_dead_strip",
- InstanceMethods);
+ values.addInt(ObjCTypes.LongTy, 0);
+ values.addInt(ObjCTypes.LongTy, Flags);
+ values.addInt(ObjCTypes.LongTy, Size.getQuantity());
+ values.add(EmitIvarList(ID, false));
+ values.add(emitMethodList(ID->getName(), MethodListType::InstanceMethods,
+ Methods[InstanceMethods]));
// cache is always NULL.
- Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
- Values[ 9] = Protocols;
- Values[10] = BuildStrongIvarLayout(ID, CharUnits::Zero(), Size);
- Values[11] = EmitClassExtension(ID, Size, hasMRCWeak,
- false/*isClassProperty*/);
- llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
- Values);
+ values.addNullPointer(ObjCTypes.CachePtrTy);
+ values.add(Protocols);
+ values.add(BuildStrongIvarLayout(ID, CharUnits::Zero(), Size));
+ values.add(EmitClassExtension(ID, Size, hasMRCWeak,
+ /*isMetaclass*/ false));
+
std::string Name("OBJC_CLASS_");
Name += ClassName;
const char *Section = "__OBJC,__class,regular,no_dead_strip";
@@ -3341,12 +3478,12 @@ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
if (GV) {
assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
"Forward metaclass reference has incorrect type.");
- GV->setInitializer(Init);
+ values.finishAndSetAsInitializer(GV);
GV->setSection(Section);
GV->setAlignment(CGM.getPointerAlign().getQuantity());
CGM.addCompilerUsedGlobal(GV);
} else
- GV = CreateMetadataVar(Name, Init, Section, CGM.getPointerAlign(), true);
+ GV = CreateMetadataVar(Name, values, Section, CGM.getPointerAlign(), true);
DefinedClasses.push_back(GV);
ImplementedClasses.push_back(Interface);
// method definition entries must be clear for next implementation.
@@ -3355,50 +3492,46 @@ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID,
llvm::Constant *Protocols,
- ArrayRef<llvm::Constant*> Methods) {
+ ArrayRef<const ObjCMethodDecl*> Methods) {
unsigned Flags = FragileABI_Class_Meta;
unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassTy);
if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
Flags |= FragileABI_Class_Hidden;
- llvm::Constant *Values[12];
+ ConstantInitBuilder builder(CGM);
+ auto values = builder.beginStruct(ObjCTypes.ClassTy);
// The isa for the metaclass is the root of the hierarchy.
const ObjCInterfaceDecl *Root = ID->getClassInterface();
while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
Root = Super;
- Values[ 0] =
- llvm::ConstantExpr::getBitCast(GetClassName(Root->getObjCRuntimeNameAsString()),
- ObjCTypes.ClassPtrTy);
+ values.addBitCast(GetClassName(Root->getObjCRuntimeNameAsString()),
+ ObjCTypes.ClassPtrTy);
// The super class for the metaclass is emitted as the name of the
// super class. The runtime fixes this up to point to the
// *metaclass* for the super class.
if (ObjCInterfaceDecl *Super = ID->getClassInterface()->getSuperClass()) {
- Values[ 1] =
- llvm::ConstantExpr::getBitCast(GetClassName(Super->getObjCRuntimeNameAsString()),
- ObjCTypes.ClassPtrTy);
+ values.addBitCast(GetClassName(Super->getObjCRuntimeNameAsString()),
+ ObjCTypes.ClassPtrTy);
} else {
- Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
+ values.addNullPointer(ObjCTypes.ClassPtrTy);
}
- Values[ 2] = GetClassName(ID->getObjCRuntimeNameAsString());
+ values.add(GetClassName(ID->getObjCRuntimeNameAsString()));
// Version is always 0.
- Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
- Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
- Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
- Values[ 6] = EmitIvarList(ID, true);
- Values[7] =
- EmitMethodList("OBJC_CLASS_METHODS_" + ID->getNameAsString(),
- "__OBJC,__cls_meth,regular,no_dead_strip", Methods);
+ values.addInt(ObjCTypes.LongTy, 0);
+ values.addInt(ObjCTypes.LongTy, Flags);
+ values.addInt(ObjCTypes.LongTy, Size);
+ values.add(EmitIvarList(ID, true));
+ values.add(emitMethodList(ID->getName(), MethodListType::ClassMethods,
+ Methods));
// cache is always NULL.
- Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
- Values[ 9] = Protocols;
+ values.addNullPointer(ObjCTypes.CachePtrTy);
+ values.add(Protocols);
// ivar_layout for metaclass is always NULL.
- Values[10] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
+ values.addNullPointer(ObjCTypes.Int8PtrTy);
// The class extension is used to store class properties for metaclasses.
- Values[11] = EmitClassExtension(ID, CharUnits::Zero(), false/*hasMRCWeak*/,
- true/*isClassProperty*/);
- llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
- Values);
+ values.add(EmitClassExtension(ID, CharUnits::Zero(), false/*hasMRCWeak*/,
+ /*isMetaclass*/true));
std::string Name("OBJC_METACLASS_");
Name += ID->getName();
@@ -3408,14 +3541,13 @@ llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID,
if (GV) {
assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
"Forward metaclass reference has incorrect type.");
- GV->setInitializer(Init);
+ values.finishAndSetAsInitializer(GV);
} else {
- GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
- llvm::GlobalValue::PrivateLinkage,
- Init, Name);
+ GV = values.finishAndCreateGlobal(Name, CGM.getPointerAlign(),
+ /*constant*/ false,
+ llvm::GlobalValue::PrivateLinkage);
}
GV->setSection("__OBJC,__meta_class,regular,no_dead_strip");
- GV->setAlignment(4);
CGM.addCompilerUsedGlobal(GV);
return GV;
@@ -3471,32 +3603,38 @@ llvm::Value *CGObjCMac::EmitSuperClassRef(const ObjCInterfaceDecl *ID) {
llvm::Constant *
CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID,
CharUnits InstanceSize, bool hasMRCWeakIvars,
- bool isClassProperty) {
- uint64_t Size =
- CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassExtensionTy);
+ bool isMetaclass) {
+ // Weak ivar layout.
+ llvm::Constant *layout;
+ if (isMetaclass) {
+ layout = llvm::ConstantPointerNull::get(CGM.Int8PtrTy);
+ } else {
+ layout = BuildWeakIvarLayout(ID, CharUnits::Zero(), InstanceSize,
+ hasMRCWeakIvars);
+ }
- llvm::Constant *Values[3];
- Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
- if (isClassProperty) {
- llvm::Type *PtrTy = CGM.Int8PtrTy;
- Values[1] = llvm::Constant::getNullValue(PtrTy);
- } else
- Values[1] = BuildWeakIvarLayout(ID, CharUnits::Zero(), InstanceSize,
- hasMRCWeakIvars);
- if (isClassProperty)
- Values[2] = EmitPropertyList("\01l_OBJC_$_CLASS_PROP_LIST_" + ID->getName(),
- ID, ID->getClassInterface(), ObjCTypes, true);
- else
- Values[2] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
- ID, ID->getClassInterface(), ObjCTypes, false);
+ // Properties.
+ llvm::Constant *propertyList =
+ EmitPropertyList((isMetaclass ? Twine("\01l_OBJC_$_CLASS_PROP_LIST_")
+ : Twine("\01l_OBJC_$_PROP_LIST_"))
+ + ID->getName(),
+ ID, ID->getClassInterface(), ObjCTypes, isMetaclass);
// Return null if no extension bits are used.
- if ((!Values[1] || Values[1]->isNullValue()) && Values[2]->isNullValue())
+ if (layout->isNullValue() && propertyList->isNullValue()) {
return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
+ }
- llvm::Constant *Init =
- llvm::ConstantStruct::get(ObjCTypes.ClassExtensionTy, Values);
- return CreateMetadataVar("OBJC_CLASSEXT_" + ID->getName(), Init,
+ uint64_t size =
+ CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassExtensionTy);
+
+ ConstantInitBuilder builder(CGM);
+ auto values = builder.beginStruct(ObjCTypes.ClassExtensionTy);
+ values.addInt(ObjCTypes.IntTy, size);
+ values.add(layout);
+ values.add(propertyList);
+
+ return CreateMetadataVar("OBJC_CLASSEXT_" + ID->getName(), values,
"__OBJC,__class_ext,regular,no_dead_strip",
CGM.getPointerAlign(), true);
}
@@ -3515,8 +3653,6 @@ CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID,
*/
llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID,
bool ForClass) {
- std::vector<llvm::Constant*> Ivars;
-
// When emitting the root class GCC emits ivar entries for the
// actual class structure. It is not clear if we need to follow this
// behavior; for now lets try and get away with not doing it. If so,
@@ -3527,91 +3663,181 @@ llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID,
const ObjCInterfaceDecl *OID = ID->getClassInterface();
+ ConstantInitBuilder builder(CGM);
+ auto ivarList = builder.beginStruct();
+ auto countSlot = ivarList.addPlaceholder();
+ auto ivars = ivarList.beginArray(ObjCTypes.IvarTy);
+
for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin();
IVD; IVD = IVD->getNextIvar()) {
// Ignore unnamed bit-fields.
if (!IVD->getDeclName())
continue;
- llvm::Constant *Ivar[] = {
- GetMethodVarName(IVD->getIdentifier()),
- GetMethodVarType(IVD),
- llvm::ConstantInt::get(ObjCTypes.IntTy,
- ComputeIvarBaseOffset(CGM, OID, IVD))
- };
- Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarTy, Ivar));
+
+ auto ivar = ivars.beginStruct(ObjCTypes.IvarTy);
+ ivar.add(GetMethodVarName(IVD->getIdentifier()));
+ ivar.add(GetMethodVarType(IVD));
+ ivar.addInt(ObjCTypes.IntTy, ComputeIvarBaseOffset(CGM, OID, IVD));
+ ivar.finishAndAddTo(ivars);
}
// Return null for empty list.
- if (Ivars.empty())
+ auto count = ivars.size();
+ if (count == 0) {
+ ivars.abandon();
+ ivarList.abandon();
return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
+ }
- llvm::Constant *Values[2];
- Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
- llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarTy,
- Ivars.size());
- Values[1] = llvm::ConstantArray::get(AT, Ivars);
- llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
+ ivars.finishAndAddTo(ivarList);
+ ivarList.fillPlaceholderWithInt(countSlot, ObjCTypes.IntTy, count);
llvm::GlobalVariable *GV;
if (ForClass)
GV =
- CreateMetadataVar("OBJC_CLASS_VARIABLES_" + ID->getName(), Init,
+ CreateMetadataVar("OBJC_CLASS_VARIABLES_" + ID->getName(), ivarList,
"__OBJC,__class_vars,regular,no_dead_strip",
CGM.getPointerAlign(), true);
else
- GV = CreateMetadataVar("OBJC_INSTANCE_VARIABLES_" + ID->getName(), Init,
+ GV = CreateMetadataVar("OBJC_INSTANCE_VARIABLES_" + ID->getName(), ivarList,
"__OBJC,__instance_vars,regular,no_dead_strip",
CGM.getPointerAlign(), true);
return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListPtrTy);
}
-/*
- struct objc_method {
- SEL method_name;
- char *method_types;
- void *method;
- };
+/// Build a struct objc_method_description constant for the given method.
+///
+/// struct objc_method_description {
+/// SEL method_name;
+/// char *method_types;
+/// };
+void CGObjCMac::emitMethodDescriptionConstant(ConstantArrayBuilder &builder,
+ const ObjCMethodDecl *MD) {
+ auto description = builder.beginStruct(ObjCTypes.MethodDescriptionTy);
+ description.addBitCast(GetMethodVarName(MD->getSelector()),
+ ObjCTypes.SelectorPtrTy);
+ description.add(GetMethodVarType(MD));
+ description.finishAndAddTo(builder);
+}
- struct objc_method_list {
- struct objc_method_list *obsolete;
- int count;
- struct objc_method methods_list[count];
- };
-*/
+/// Build a struct objc_method constant for the given method.
+///
+/// struct objc_method {
+/// SEL method_name;
+/// char *method_types;
+/// void *method;
+/// };
+void CGObjCMac::emitMethodConstant(ConstantArrayBuilder &builder,
+ const ObjCMethodDecl *MD) {
+ llvm::Function *fn = GetMethodDefinition(MD);
+ assert(fn && "no definition registered for method");
-/// GetMethodConstant - Return a struct objc_method constant for the
-/// given method if it has been defined. The result is null if the
-/// method has not been defined. The return value has type MethodPtrTy.
-llvm::Constant *CGObjCMac::GetMethodConstant(const ObjCMethodDecl *MD) {
- llvm::Function *Fn = GetMethodDefinition(MD);
- if (!Fn)
- return nullptr;
-
- llvm::Constant *Method[] = {
- llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
- ObjCTypes.SelectorPtrTy),
- GetMethodVarType(MD),
- llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy)
- };
- return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
+ auto method = builder.beginStruct(ObjCTypes.MethodTy);
+ method.addBitCast(GetMethodVarName(MD->getSelector()),
+ ObjCTypes.SelectorPtrTy);
+ method.add(GetMethodVarType(MD));
+ method.addBitCast(fn, ObjCTypes.Int8PtrTy);
+ method.finishAndAddTo(builder);
}
-llvm::Constant *CGObjCMac::EmitMethodList(Twine Name, StringRef Section,
- ArrayRef<llvm::Constant *> Methods) {
+/// Build a struct objc_method_list or struct objc_method_description_list,
+/// as appropriate.
+///
+/// struct objc_method_list {
+/// struct objc_method_list *obsolete;
+/// int count;
+/// struct objc_method methods_list[count];
+/// };
+///
+/// struct objc_method_description_list {
+/// int count;
+/// struct objc_method_description list[count];
+/// };
+llvm::Constant *CGObjCMac::emitMethodList(Twine name, MethodListType MLT,
+ ArrayRef<const ObjCMethodDecl *> methods) {
+ StringRef prefix;
+ StringRef section;
+ bool forProtocol = false;
+ switch (MLT) {
+ case MethodListType::CategoryInstanceMethods:
+ prefix = "OBJC_CATEGORY_INSTANCE_METHODS_";
+ section = "__OBJC,__cat_inst_meth,regular,no_dead_strip";
+ forProtocol = false;
+ break;
+ case MethodListType::CategoryClassMethods:
+ prefix = "OBJC_CATEGORY_CLASS_METHODS_";
+ section = "__OBJC,__cat_cls_meth,regular,no_dead_strip";
+ forProtocol = false;
+ break;
+ case MethodListType::InstanceMethods:
+ prefix = "OBJC_INSTANCE_METHODS_";
+ section = "__OBJC,__inst_meth,regular,no_dead_strip";
+ forProtocol = false;
+ break;
+ case MethodListType::ClassMethods:
+ prefix = "OBJC_CLASS_METHODS_";
+ section = "__OBJC,__cls_meth,regular,no_dead_strip";
+ forProtocol = false;
+ break;
+ case MethodListType::ProtocolInstanceMethods:
+ prefix = "OBJC_PROTOCOL_INSTANCE_METHODS_";
+ section = "__OBJC,__cat_inst_meth,regular,no_dead_strip";
+ forProtocol = true;
+ break;
+ case MethodListType::ProtocolClassMethods:
+ prefix = "OBJC_PROTOCOL_CLASS_METHODS_";
+ section = "__OBJC,__cat_cls_meth,regular,no_dead_strip";
+ forProtocol = true;
+ break;
+ case MethodListType::OptionalProtocolInstanceMethods:
+ prefix = "OBJC_PROTOCOL_INSTANCE_METHODS_OPT_";
+ section = "__OBJC,__cat_inst_meth,regular,no_dead_strip";
+ forProtocol = true;
+ break;
+ case MethodListType::OptionalProtocolClassMethods:
+ prefix = "OBJC_PROTOCOL_CLASS_METHODS_OPT_";
+ section = "__OBJC,__cat_cls_meth,regular,no_dead_strip";
+ forProtocol = true;
+ break;
+ }
+
// Return null for empty list.
- if (Methods.empty())
- return llvm::Constant::getNullValue(ObjCTypes.MethodListPtrTy);
+ if (methods.empty())
+ return llvm::Constant::getNullValue(forProtocol
+ ? ObjCTypes.MethodDescriptionListPtrTy
+ : ObjCTypes.MethodListPtrTy);
+
+ // For protocols, this is an objc_method_description_list, which has
+ // a slightly different structure.
+ if (forProtocol) {
+ ConstantInitBuilder builder(CGM);
+ auto values = builder.beginStruct();
+ values.addInt(ObjCTypes.IntTy, methods.size());
+ auto methodArray = values.beginArray(ObjCTypes.MethodDescriptionTy);
+ for (auto MD : methods) {
+ emitMethodDescriptionConstant(methodArray, MD);
+ }
+ methodArray.finishAndAddTo(values);
+
+ llvm::GlobalVariable *GV = CreateMetadataVar(prefix + name, values, section,
+ CGM.getPointerAlign(), true);
+ return llvm::ConstantExpr::getBitCast(GV,
+ ObjCTypes.MethodDescriptionListPtrTy);
+ }
- llvm::Constant *Values[3];
- Values[0] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
- Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
- llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
- Methods.size());
- Values[2] = llvm::ConstantArray::get(AT, Methods);
- llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
+ // Otherwise, it's an objc_method_list.
+ ConstantInitBuilder builder(CGM);
+ auto values = builder.beginStruct();
+ values.addNullPointer(ObjCTypes.Int8PtrTy);
+ values.addInt(ObjCTypes.IntTy, methods.size());
+ auto methodArray = values.beginArray(ObjCTypes.MethodTy);
+ for (auto MD : methods) {
+ emitMethodConstant(methodArray, MD);
+ }
+ methodArray.finishAndAddTo(values);
- llvm::GlobalVariable *GV =
- CreateMetadataVar(Name, Init, Section, CGM.getPointerAlign(), true);
+ llvm::GlobalVariable *GV = CreateMetadataVar(prefix + name, values, section,
+ CGM.getPointerAlign(), true);
return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodListPtrTy);
}
@@ -3634,6 +3860,21 @@ llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,
}
llvm::GlobalVariable *CGObjCCommonMac::CreateMetadataVar(Twine Name,
+ ConstantStructBuilder &Init,
+ StringRef Section,
+ CharUnits Align,
+ bool AddToUsed) {
+ llvm::GlobalVariable *GV =
+ Init.finishAndCreateGlobal(Name, Align, /*constant*/ false,
+ llvm::GlobalValue::PrivateLinkage);
+ if (!Section.empty())
+ GV->setSection(Section);
+ if (AddToUsed)
+ CGM.addCompilerUsedGlobal(GV);
+ return GV;
+}
+
+llvm::GlobalVariable *CGObjCCommonMac::CreateMetadataVar(Twine Name,
llvm::Constant *Init,
StringRef Section,
CharUnits Align,
@@ -3650,6 +3891,54 @@ llvm::GlobalVariable *CGObjCCommonMac::CreateMetadataVar(Twine Name,
return GV;
}
+llvm::GlobalVariable *
+CGObjCCommonMac::CreateCStringLiteral(StringRef Name, ObjCLabelType Type,
+ bool ForceNonFragileABI,
+ bool NullTerminate) {
+ StringRef Label;
+ switch (Type) {
+ case ObjCLabelType::ClassName: Label = "OBJC_CLASS_NAME_"; break;
+ case ObjCLabelType::MethodVarName: Label = "OBJC_METH_VAR_NAME_"; break;
+ case ObjCLabelType::MethodVarType: Label = "OBJC_METH_VAR_TYPE_"; break;
+ case ObjCLabelType::PropertyName: Label = "OBJC_PROP_NAME_ATTR_"; break;
+ }
+
+ bool NonFragile = ForceNonFragileABI || isNonFragileABI();
+
+ StringRef Section;
+ switch (Type) {
+ case ObjCLabelType::ClassName:
+ Section = NonFragile ? "__TEXT,__objc_classname,cstring_literals"
+ : "__TEXT,__cstring,cstring_literals";
+ break;
+ case ObjCLabelType::MethodVarName:
+ Section = NonFragile ? "__TEXT,__objc_methname,cstring_literals"
+ : "__TEXT,__cstring,cstring_literals";
+ break;
+ case ObjCLabelType::MethodVarType:
+ Section = NonFragile ? "__TEXT,__objc_methtype,cstring_literals"
+ : "__TEXT,__cstring,cstring_literals";
+ break;
+ case ObjCLabelType::PropertyName:
+ Section = "__TEXT,__cstring,cstring_literals";
+ break;
+ }
+
+ llvm::Constant *Value =
+ llvm::ConstantDataArray::getString(VMContext, Name, NullTerminate);
+ llvm::GlobalVariable *GV =
+ new llvm::GlobalVariable(CGM.getModule(), Value->getType(),
+ /*isConstant=*/true,
+ llvm::GlobalValue::PrivateLinkage, Value, Label);
+ if (CGM.getTriple().isOSBinFormatMachO())
+ GV->setSection(Section);
+ GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
+ GV->setAlignment(CharUnits::One().getQuantity());
+ CGM.addCompilerUsedGlobal(GV);
+
+ return GV;
+}
+
llvm::Function *CGObjCMac::ModuleInitFunction() {
// Abuse this interface function as a place to finalize.
FinishModule();
@@ -4390,8 +4679,8 @@ void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
if (!isa<llvm::PointerType>(SrcTy)) {
unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
assert(Size <= 8 && "does not support size > 8");
- src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
- : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
+ src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
+ : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
}
src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
@@ -4411,8 +4700,8 @@ void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
if (!isa<llvm::PointerType>(SrcTy)) {
unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
assert(Size <= 8 && "does not support size > 8");
- src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
- : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
+ src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
+ : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
}
src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
@@ -4437,8 +4726,8 @@ void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
if (!isa<llvm::PointerType>(SrcTy)) {
unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
assert(Size <= 8 && "does not support size > 8");
- src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
- : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
+ src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
+ : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
}
src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
@@ -4456,8 +4745,8 @@ void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
if (!isa<llvm::PointerType>(SrcTy)) {
unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
assert(Size <= 8 && "does not support size > 8");
- src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
- : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
+ src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
+ : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
}
src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
@@ -4590,15 +4879,14 @@ static const int ModuleVersion = 7;
void CGObjCMac::EmitModuleInfo() {
uint64_t Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ModuleTy);
- llvm::Constant *Values[] = {
- llvm::ConstantInt::get(ObjCTypes.LongTy, ModuleVersion),
- llvm::ConstantInt::get(ObjCTypes.LongTy, Size),
- // This used to be the filename, now it is unused. <rdr://4327263>
- GetClassName(StringRef("")),
- EmitModuleSymbols()
- };
- CreateMetadataVar("OBJC_MODULES",
- llvm::ConstantStruct::get(ObjCTypes.ModuleTy, Values),
+ ConstantInitBuilder builder(CGM);
+ auto values = builder.beginStruct(ObjCTypes.ModuleTy);
+ values.addInt(ObjCTypes.LongTy, ModuleVersion);
+ values.addInt(ObjCTypes.LongTy, Size);
+ // This used to be the filename, now it is unused. <rdr://4327263>
+ values.add(GetClassName(StringRef("")));
+ values.add(EmitModuleSymbols());
+ CreateMetadataVar("OBJC_MODULES", values,
"__OBJC,__module_info,regular,no_dead_strip",
CGM.getPointerAlign(), true);
}
@@ -4611,15 +4899,16 @@ llvm::Constant *CGObjCMac::EmitModuleSymbols() {
if (!NumClasses && !NumCategories)
return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy);
- llvm::Constant *Values[5];
- Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
- Values[1] = llvm::Constant::getNullValue(ObjCTypes.SelectorPtrTy);
- Values[2] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumClasses);
- Values[3] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumCategories);
+ ConstantInitBuilder builder(CGM);
+ auto values = builder.beginStruct();
+ values.addInt(ObjCTypes.LongTy, 0);
+ values.addNullPointer(ObjCTypes.SelectorPtrTy);
+ values.addInt(ObjCTypes.ShortTy, NumClasses);
+ values.addInt(ObjCTypes.ShortTy, NumCategories);
// The runtime expects exactly the list of defined classes followed
// by the list of defined categories, in a single array.
- SmallVector<llvm::Constant*, 8> Symbols(NumClasses + NumCategories);
+ auto array = values.beginArray(ObjCTypes.Int8PtrTy);
for (unsigned i=0; i<NumClasses; i++) {
const ObjCInterfaceDecl *ID = ImplementedClasses[i];
assert(ID);
@@ -4627,24 +4916,16 @@ llvm::Constant *CGObjCMac::EmitModuleSymbols() {
// We are implementing a weak imported interface. Give it external linkage
if (ID->isWeakImported() && !IMP->isWeakImported())
DefinedClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage);
-
- Symbols[i] = llvm::ConstantExpr::getBitCast(DefinedClasses[i],
- ObjCTypes.Int8PtrTy);
+
+ array.addBitCast(DefinedClasses[i], ObjCTypes.Int8PtrTy);
}
for (unsigned i=0; i<NumCategories; i++)
- Symbols[NumClasses + i] =
- llvm::ConstantExpr::getBitCast(DefinedCategories[i],
- ObjCTypes.Int8PtrTy);
+ array.addBitCast(DefinedCategories[i], ObjCTypes.Int8PtrTy);
- Values[4] =
- llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
- Symbols.size()),
- Symbols);
-
- llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
+ array.finishAndAddTo(values);
llvm::GlobalVariable *GV = CreateMetadataVar(
- "OBJC_SYMBOLS", Init, "__OBJC,__symbols,regular,no_dead_strip",
+ "OBJC_SYMBOLS", values, "__OBJC,__symbols,regular,no_dead_strip",
CGM.getPointerAlign(), true);
return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.SymtabPtrTy);
}
@@ -4707,12 +4988,7 @@ Address CGObjCMac::EmitSelectorAddr(CodeGenFunction &CGF, Selector Sel) {
llvm::Constant *CGObjCCommonMac::GetClassName(StringRef RuntimeName) {
llvm::GlobalVariable *&Entry = ClassNames[RuntimeName];
if (!Entry)
- Entry = CreateMetadataVar(
- "OBJC_CLASS_NAME_",
- llvm::ConstantDataArray::getString(VMContext, RuntimeName),
- ((ObjCABI == 2) ? "__TEXT,__objc_classname,cstring_literals"
- : "__TEXT,__cstring,cstring_literals"),
- CharUnits::One(), true);
+ Entry = CreateCStringLiteral(RuntimeName, ObjCLabelType::ClassName);
return getConstantGEP(VMContext, Entry, 0, 0);
}
@@ -4960,14 +5236,8 @@ llvm::Constant *IvarLayoutBuilder::buildBitmap(CGObjCCommonMac &CGObjC,
// Null terminate the string.
buffer.push_back(0);
- bool isNonFragileABI = CGObjC.isNonFragileABI();
-
- llvm::GlobalVariable *Entry = CGObjC.CreateMetadataVar(
- "OBJC_CLASS_NAME_",
- llvm::ConstantDataArray::get(CGM.getLLVMContext(), buffer),
- (isNonFragileABI ? "__TEXT,__objc_classname,cstring_literals"
- : "__TEXT,__cstring,cstring_literals"),
- CharUnits::One(), true);
+ auto *Entry = CGObjC.CreateCStringLiteral(
+ reinterpret_cast<char *>(buffer.data()), ObjCLabelType::ClassName);
return getConstantGEP(CGM.getLLVMContext(), Entry, 0, 0);
}
@@ -5062,16 +5332,9 @@ CGObjCCommonMac::BuildIvarLayout(const ObjCImplementationDecl *OMD,
llvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) {
llvm::GlobalVariable *&Entry = MethodVarNames[Sel];
-
// FIXME: Avoid std::string in "Sel.getAsString()"
if (!Entry)
- Entry = CreateMetadataVar(
- "OBJC_METH_VAR_NAME_",
- llvm::ConstantDataArray::getString(VMContext, Sel.getAsString()),
- ((ObjCABI == 2) ? "__TEXT,__objc_methname,cstring_literals"
- : "__TEXT,__cstring,cstring_literals"),
- CharUnits::One(), true);
-
+ Entry = CreateCStringLiteral(Sel.getAsString(), ObjCLabelType::MethodVarName);
return getConstantGEP(VMContext, Entry, 0, 0);
}
@@ -5085,47 +5348,27 @@ llvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) {
CGM.getContext().getObjCEncodingForType(Field->getType(), TypeStr, Field);
llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
-
if (!Entry)
- Entry = CreateMetadataVar(
- "OBJC_METH_VAR_TYPE_",
- llvm::ConstantDataArray::getString(VMContext, TypeStr),
- ((ObjCABI == 2) ? "__TEXT,__objc_methtype,cstring_literals"
- : "__TEXT,__cstring,cstring_literals"),
- CharUnits::One(), true);
-
+ Entry = CreateCStringLiteral(TypeStr, ObjCLabelType::MethodVarType);
return getConstantGEP(VMContext, Entry, 0, 0);
}
llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D,
bool Extended) {
- std::string TypeStr;
- if (CGM.getContext().getObjCEncodingForMethodDecl(D, TypeStr, Extended))
- return nullptr;
+ std::string TypeStr =
+ CGM.getContext().getObjCEncodingForMethodDecl(D, Extended);
llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
-
if (!Entry)
- Entry = CreateMetadataVar(
- "OBJC_METH_VAR_TYPE_",
- llvm::ConstantDataArray::getString(VMContext, TypeStr),
- ((ObjCABI == 2) ? "__TEXT,__objc_methtype,cstring_literals"
- : "__TEXT,__cstring,cstring_literals"),
- CharUnits::One(), true);
-
+ Entry = CreateCStringLiteral(TypeStr, ObjCLabelType::MethodVarType);
return getConstantGEP(VMContext, Entry, 0, 0);
}
// FIXME: Merge into a single cstring creation function.
llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
llvm::GlobalVariable *&Entry = PropertyNames[Ident];
-
if (!Entry)
- Entry = CreateMetadataVar(
- "OBJC_PROP_NAME_ATTR_",
- llvm::ConstantDataArray::getString(VMContext, Ident->getName()),
- "__TEXT,__cstring,cstring_literals", CharUnits::One(), true);
-
+ Entry = CreateCStringLiteral(Ident->getName(), ObjCLabelType::PropertyName);
return getConstantGEP(VMContext, Entry, 0, 0);
}
@@ -5134,8 +5377,8 @@ llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
llvm::Constant *
CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
const Decl *Container) {
- std::string TypeStr;
- CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container, TypeStr);
+ std::string TypeStr =
+ CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container);
return GetPropertyName(&CGM.getContext().Idents.get(TypeStr));
}
@@ -5157,20 +5400,20 @@ void CGObjCMac::FinishModule() {
// Emit the dummy bodies for any protocols which were referenced but
// never defined.
- for (llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*>::iterator
- I = Protocols.begin(), e = Protocols.end(); I != e; ++I) {
- if (I->second->hasInitializer())
+ for (auto &entry : Protocols) {
+ llvm::GlobalVariable *global = entry.second;
+ if (global->hasInitializer())
continue;
- llvm::Constant *Values[5];
- Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
- Values[1] = GetClassName(I->first->getName());
- Values[2] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
- Values[3] = Values[4] =
- llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
- I->second->setInitializer(llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
- Values));
- CGM.addCompilerUsedGlobal(I->second);
+ ConstantInitBuilder builder(CGM);
+ auto values = builder.beginStruct(ObjCTypes.ProtocolTy);
+ values.addNullPointer(ObjCTypes.ProtocolExtensionPtrTy);
+ values.add(GetClassName(entry.first->getName()));
+ values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
+ values.addNullPointer(ObjCTypes.MethodDescriptionListPtrTy);
+ values.addNullPointer(ObjCTypes.MethodDescriptionListPtrTy);
+ values.finishAndSetAsInitializer(global);
+ CGM.addCompilerUsedGlobal(global);
}
// Add assembler directives to add lazy undefined symbol references
@@ -5178,27 +5421,23 @@ void CGObjCMac::FinishModule() {
// important for correct linker interaction.
//
// FIXME: It would be nice if we had an LLVM construct for this.
- if (!LazySymbols.empty() || !DefinedSymbols.empty()) {
+ if ((!LazySymbols.empty() || !DefinedSymbols.empty()) &&
+ CGM.getTriple().isOSBinFormatMachO()) {
SmallString<256> Asm;
Asm += CGM.getModule().getModuleInlineAsm();
if (!Asm.empty() && Asm.back() != '\n')
Asm += '\n';
llvm::raw_svector_ostream OS(Asm);
- for (llvm::SetVector<IdentifierInfo*>::iterator I = DefinedSymbols.begin(),
- e = DefinedSymbols.end(); I != e; ++I)
- OS << "\t.objc_class_name_" << (*I)->getName() << "=0\n"
- << "\t.globl .objc_class_name_" << (*I)->getName() << "\n";
- for (llvm::SetVector<IdentifierInfo*>::iterator I = LazySymbols.begin(),
- e = LazySymbols.end(); I != e; ++I) {
- OS << "\t.lazy_reference .objc_class_name_" << (*I)->getName() << "\n";
- }
+ for (const auto *Sym : DefinedSymbols)
+ OS << "\t.objc_class_name_" << Sym->getName() << "=0\n"
+ << "\t.globl .objc_class_name_" << Sym->getName() << "\n";
+ for (const auto *Sym : LazySymbols)
+ OS << "\t.lazy_reference .objc_class_name_" << Sym->getName() << "\n";
+ for (const auto &Category : DefinedCategoryNames)
+ OS << "\t.objc_category_name_" << Category << "=0\n"
+ << "\t.globl .objc_category_name_" << Category << "\n";
- for (size_t i = 0, e = DefinedCategoryNames.size(); i < e; ++i) {
- OS << "\t.objc_category_name_" << DefinedCategoryNames[i] << "=0\n"
- << "\t.globl .objc_category_name_" << DefinedCategoryNames[i] << "\n";
- }
-
CGM.getModule().setModuleInlineAsm(OS.str());
}
}
@@ -5217,10 +5456,9 @@ ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
CodeGen::CodeGenTypes &Types = CGM.getTypes();
ASTContext &Ctx = CGM.getContext();
- ShortTy = Types.ConvertType(Ctx.ShortTy);
- IntTy = Types.ConvertType(Ctx.IntTy);
- LongTy = Types.ConvertType(Ctx.LongTy);
- LongLongTy = Types.ConvertType(Ctx.LongLongTy);
+ ShortTy = cast<llvm::IntegerType>(Types.ConvertType(Ctx.ShortTy));
+ IntTy = CGM.IntTy;
+ LongTy = cast<llvm::IntegerType>(Types.ConvertType(Ctx.LongTy));
Int8PtrTy = CGM.Int8PtrTy;
Int8PtrPtrTy = CGM.Int8PtrPtrTy;
@@ -5231,9 +5469,12 @@ ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
else
IvarOffsetVarTy = LongTy;
- ObjectPtrTy = Types.ConvertType(Ctx.getObjCIdType());
- PtrObjectPtrTy = llvm::PointerType::getUnqual(ObjectPtrTy);
- SelectorPtrTy = Types.ConvertType(Ctx.getObjCSelType());
+ ObjectPtrTy =
+ cast<llvm::PointerType>(Types.ConvertType(Ctx.getObjCIdType()));
+ PtrObjectPtrTy =
+ llvm::PointerType::getUnqual(ObjectPtrTy);
+ SelectorPtrTy =
+ cast<llvm::PointerType>(Types.ConvertType(Ctx.getObjCSelType()));
// I'm not sure I like this. The implicit coordination is a bit
// gross. We should solve this in a reasonable fashion because this
@@ -5831,7 +6072,6 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
unsigned InstanceSize,
const ObjCImplementationDecl *ID) {
std::string ClassName = ID->getObjCRuntimeNameAsString();
- llvm::Constant *Values[10]; // 11 for 64bit targets!
CharUnits beginInstance = CharUnits::fromQuantity(InstanceStart);
CharUnits endInstance = CharUnits::fromQuantity(InstanceSize);
@@ -5842,85 +6082,84 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
else if ((hasMRCWeak = hasMRCWeakIvars(CGM, ID)))
flags |= NonFragileABI_Class_HasMRCWeakIvars;
- Values[ 0] = llvm::ConstantInt::get(ObjCTypes.IntTy, flags);
- Values[ 1] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceStart);
- Values[ 2] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceSize);
- // FIXME. For 64bit targets add 0 here.
- Values[ 3] = (flags & NonFragileABI_Class_Meta)
- ? GetIvarLayoutName(nullptr, ObjCTypes)
- : BuildStrongIvarLayout(ID, beginInstance, endInstance);
- Values[ 4] = GetClassName(ID->getObjCRuntimeNameAsString());
+ ConstantInitBuilder builder(CGM);
+ auto values = builder.beginStruct(ObjCTypes.ClassRonfABITy);
+
+ values.addInt(ObjCTypes.IntTy, flags);
+ values.addInt(ObjCTypes.IntTy, InstanceStart);
+ values.addInt(ObjCTypes.IntTy, InstanceSize);
+ values.add((flags & NonFragileABI_Class_Meta)
+ ? GetIvarLayoutName(nullptr, ObjCTypes)
+ : BuildStrongIvarLayout(ID, beginInstance, endInstance));
+ values.add(GetClassName(ID->getObjCRuntimeNameAsString()));
+
// const struct _method_list_t * const baseMethods;
- std::vector<llvm::Constant*> Methods;
- std::string MethodListName("\01l_OBJC_$_");
+ SmallVector<const ObjCMethodDecl*, 16> methods;
if (flags & NonFragileABI_Class_Meta) {
- MethodListName += "CLASS_METHODS_";
- MethodListName += ID->getObjCRuntimeNameAsString();
- for (const auto *I : ID->class_methods())
- // Class methods should always be defined.
- Methods.push_back(GetMethodConstant(I));
+ for (const auto *MD : ID->class_methods())
+ methods.push_back(MD);
} else {
- MethodListName += "INSTANCE_METHODS_";
- MethodListName += ID->getObjCRuntimeNameAsString();
- for (const auto *I : ID->instance_methods())
- // Instance methods should always be defined.
- Methods.push_back(GetMethodConstant(I));
+ for (const auto *MD : ID->instance_methods())
+ methods.push_back(MD);
for (const auto *PID : ID->property_impls()) {
if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize){
ObjCPropertyDecl *PD = PID->getPropertyDecl();
- if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
- if (llvm::Constant *C = GetMethodConstant(MD))
- Methods.push_back(C);
- if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
- if (llvm::Constant *C = GetMethodConstant(MD))
- Methods.push_back(C);
+ if (auto MD = PD->getGetterMethodDecl())
+ if (GetMethodDefinition(MD))
+ methods.push_back(MD);
+ if (auto MD = PD->getSetterMethodDecl())
+ if (GetMethodDefinition(MD))
+ methods.push_back(MD);
}
}
}
- Values[ 5] = EmitMethodList(MethodListName,
- "__DATA, __objc_const", Methods);
+
+ values.add(emitMethodList(ID->getObjCRuntimeNameAsString(),
+ (flags & NonFragileABI_Class_Meta)
+ ? MethodListType::ClassMethods
+ : MethodListType::InstanceMethods,
+ methods));
const ObjCInterfaceDecl *OID = ID->getClassInterface();
assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer");
- Values[ 6] = EmitProtocolList("\01l_OBJC_CLASS_PROTOCOLS_$_"
+ values.add(EmitProtocolList("\01l_OBJC_CLASS_PROTOCOLS_$_"
+ OID->getObjCRuntimeNameAsString(),
- OID->all_referenced_protocol_begin(),
- OID->all_referenced_protocol_end());
+ OID->all_referenced_protocol_begin(),
+ OID->all_referenced_protocol_end()));
if (flags & NonFragileABI_Class_Meta) {
- Values[ 7] = llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
- Values[ 8] = GetIvarLayoutName(nullptr, ObjCTypes);
- Values[ 9] = EmitPropertyList(
+ values.addNullPointer(ObjCTypes.IvarListnfABIPtrTy);
+ values.add(GetIvarLayoutName(nullptr, ObjCTypes));
+ values.add(EmitPropertyList(
"\01l_OBJC_$_CLASS_PROP_LIST_" + ID->getObjCRuntimeNameAsString(),
- ID, ID->getClassInterface(), ObjCTypes, true);
+ ID, ID->getClassInterface(), ObjCTypes, true));
} else {
- Values[ 7] = EmitIvarList(ID);
- Values[ 8] = BuildWeakIvarLayout(ID, beginInstance, endInstance,
- hasMRCWeak);
- Values[ 9] = EmitPropertyList(
+ values.add(EmitIvarList(ID));
+ values.add(BuildWeakIvarLayout(ID, beginInstance, endInstance, hasMRCWeak));
+ values.add(EmitPropertyList(
"\01l_OBJC_$_PROP_LIST_" + ID->getObjCRuntimeNameAsString(),
- ID, ID->getClassInterface(), ObjCTypes, false);
+ ID, ID->getClassInterface(), ObjCTypes, false));
}
- llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassRonfABITy,
- Values);
+
+ llvm::SmallString<64> roLabel;
+ llvm::raw_svector_ostream(roLabel)
+ << ((flags & NonFragileABI_Class_Meta) ? "\01l_OBJC_METACLASS_RO_$_"
+ : "\01l_OBJC_CLASS_RO_$_")
+ << ClassName;
+
llvm::GlobalVariable *CLASS_RO_GV =
- new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassRonfABITy, false,
- llvm::GlobalValue::PrivateLinkage,
- Init,
- (flags & NonFragileABI_Class_Meta) ?
- std::string("\01l_OBJC_METACLASS_RO_$_")+ClassName :
- std::string("\01l_OBJC_CLASS_RO_$_")+ClassName);
- CLASS_RO_GV->setAlignment(
- CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ClassRonfABITy));
- CLASS_RO_GV->setSection("__DATA, __objc_const");
+ values.finishAndCreateGlobal(roLabel, CGM.getPointerAlign(),
+ /*constant*/ false,
+ llvm::GlobalValue::PrivateLinkage);
+ if (CGM.getTriple().isOSBinFormatMachO())
+ CLASS_RO_GV->setSection("__DATA, __objc_const");
return CLASS_RO_GV;
-
}
-/// BuildClassMetaData - This routine defines that to-level meta-data
-/// for the given ClassName for:
+/// Build the metaclass object for a class.
+///
/// struct _class_t {
/// struct _class_t *isa;
/// struct _class_t * const superclass;
@@ -5929,28 +6168,33 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
/// struct class_ro_t *ro;
/// }
///
-llvm::GlobalVariable *CGObjCNonFragileABIMac::BuildClassMetaData(
- const std::string &ClassName, llvm::Constant *IsAGV, llvm::Constant *SuperClassGV,
- llvm::Constant *ClassRoGV, bool HiddenVisibility, bool Weak) {
- llvm::Constant *Values[] = {
- IsAGV,
- SuperClassGV,
- ObjCEmptyCacheVar, // &ObjCEmptyCacheVar
- ObjCEmptyVtableVar, // &ObjCEmptyVtableVar
- ClassRoGV // &CLASS_RO_GV
- };
- if (!Values[1])
- Values[1] = llvm::Constant::getNullValue(ObjCTypes.ClassnfABIPtrTy);
- if (!Values[3])
- Values[3] = llvm::Constant::getNullValue(
- llvm::PointerType::getUnqual(ObjCTypes.ImpnfABITy));
- llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassnfABITy,
- Values);
- llvm::GlobalVariable *GV = GetClassGlobal(ClassName, Weak);
- GV->setInitializer(Init);
- GV->setSection("__DATA, __objc_data");
+llvm::GlobalVariable *
+CGObjCNonFragileABIMac::BuildClassObject(const ObjCInterfaceDecl *CI,
+ bool isMetaclass,
+ llvm::Constant *IsAGV,
+ llvm::Constant *SuperClassGV,
+ llvm::Constant *ClassRoGV,
+ bool HiddenVisibility) {
+ ConstantInitBuilder builder(CGM);
+ auto values = builder.beginStruct(ObjCTypes.ClassnfABITy);
+ values.add(IsAGV);
+ if (SuperClassGV) {
+ values.add(SuperClassGV);
+ } else {
+ values.addNullPointer(ObjCTypes.ClassnfABIPtrTy);
+ }
+ values.add(ObjCEmptyCacheVar);
+ values.add(ObjCEmptyVtableVar);
+ values.add(ClassRoGV);
+
+ llvm::GlobalVariable *GV =
+ cast<llvm::GlobalVariable>(GetClassGlobal(CI, isMetaclass, ForDefinition));
+ values.finishAndSetAsInitializer(GV);
+
+ if (CGM.getTriple().isOSBinFormatMachO())
+ GV->setSection("__DATA, __objc_data");
GV->setAlignment(
- CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ClassnfABITy));
+ CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ClassnfABITy));
if (!CGM.getTriple().isOSBinFormatCOFF())
if (HiddenVisibility)
GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
@@ -6014,6 +6258,9 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ImpnfABITy, false,
llvm::GlobalValue::ExternalLinkage, nullptr,
"_objc_empty_vtable");
+ else
+ ObjCEmptyVtableVar =
+ llvm::ConstantPointerNull::get(ObjCTypes.ImpnfABITy->getPointerTo());
}
// FIXME: Is this correct (that meta class size is never computed)?
@@ -6022,9 +6269,8 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
uint32_t InstanceSize = InstanceStart;
uint32_t flags = NonFragileABI_Class_Meta;
- llvm::GlobalVariable *SuperClassGV, *IsAGV;
+ llvm::Constant *SuperClassGV, *IsAGV;
- StringRef ClassName = ID->getObjCRuntimeNameAsString();
const auto *CI = ID->getClassInterface();
assert(CI && "CGObjCNonFragileABIMac::GenerateClass - class is 0");
@@ -6047,17 +6293,8 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
// class is root
flags |= NonFragileABI_Class_Root;
- SuperClassGV = GetClassGlobal((getClassSymbolPrefix() + ClassName).str(),
- CI->isWeakImported());
- if (CGM.getTriple().isOSBinFormatCOFF())
- if (CI->hasAttr<DLLImportAttr>())
- SuperClassGV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
-
- IsAGV = GetClassGlobal((getMetaclassSymbolPrefix() + ClassName).str(),
- CI->isWeakImported());
- if (CGM.getTriple().isOSBinFormatCOFF())
- if (CI->hasAttr<DLLImportAttr>())
- IsAGV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
+ SuperClassGV = GetClassGlobal(CI, /*metaclass*/ false, NotForDefinition);
+ IsAGV = GetClassGlobal(CI, /*metaclass*/ true, NotForDefinition);
} else {
// Has a root. Current class is not a root.
const ObjCInterfaceDecl *Root = ID->getClassInterface();
@@ -6065,31 +6302,16 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
Root = Super;
const auto *Super = CI->getSuperClass();
- StringRef RootClassName = Root->getObjCRuntimeNameAsString();
- StringRef SuperClassName = Super->getObjCRuntimeNameAsString();
-
- IsAGV = GetClassGlobal((getMetaclassSymbolPrefix() + RootClassName).str(),
- Root->isWeakImported());
- if (CGM.getTriple().isOSBinFormatCOFF())
- if (Root->hasAttr<DLLImportAttr>())
- IsAGV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
-
- // work on super class metadata symbol.
- SuperClassGV =
- GetClassGlobal((getMetaclassSymbolPrefix() + SuperClassName).str(),
- Super->isWeakImported());
- if (CGM.getTriple().isOSBinFormatCOFF())
- if (Super->hasAttr<DLLImportAttr>())
- SuperClassGV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
+ IsAGV = GetClassGlobal(Root, /*metaclass*/ true, NotForDefinition);
+ SuperClassGV = GetClassGlobal(Super, /*metaclass*/ true, NotForDefinition);
}
llvm::GlobalVariable *CLASS_RO_GV =
BuildClassRoTInitializer(flags, InstanceStart, InstanceSize, ID);
llvm::GlobalVariable *MetaTClass =
- BuildClassMetaData((getMetaclassSymbolPrefix() + ClassName).str(), IsAGV,
- SuperClassGV, CLASS_RO_GV, classIsHidden,
- CI->isWeakImported());
+ BuildClassObject(CI, /*metaclass*/ true,
+ IsAGV, SuperClassGV, CLASS_RO_GV, classIsHidden);
if (CGM.getTriple().isOSBinFormatCOFF())
if (CI->hasAttr<DLLExportAttr>())
MetaTClass->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
@@ -6122,14 +6344,7 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
} else {
// Has a root. Current class is not a root.
const auto *Super = CI->getSuperClass();
- StringRef SuperClassName = Super->getObjCRuntimeNameAsString();
-
- SuperClassGV =
- GetClassGlobal((getClassSymbolPrefix() + SuperClassName).str(),
- Super->isWeakImported());
- if (CGM.getTriple().isOSBinFormatCOFF())
- if (Super->hasAttr<DLLImportAttr>())
- SuperClassGV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
+ SuperClassGV = GetClassGlobal(Super, /*metaclass*/ false, NotForDefinition);
}
GetClassSizeInfo(ID, InstanceStart, InstanceSize);
@@ -6137,9 +6352,8 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
BuildClassRoTInitializer(flags, InstanceStart, InstanceSize, ID);
llvm::GlobalVariable *ClassMD =
- BuildClassMetaData((getClassSymbolPrefix() + ClassName).str(), MetaTClass,
- SuperClassGV, CLASS_RO_GV, classIsHidden,
- CI->isWeakImported());
+ BuildClassObject(CI, /*metaclass*/ false,
+ MetaTClass, SuperClassGV, CLASS_RO_GV, classIsHidden);
if (CGM.getTriple().isOSBinFormatCOFF())
if (CI->hasAttr<DLLExportAttr>())
ClassMD->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
@@ -6152,7 +6366,7 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
// Force the definition of the EHType if necessary.
if (flags & NonFragileABI_Class_Exception)
- GetInterfaceEHType(CI, true);
+ (void) GetInterfaceEHType(CI, ForDefinition);
// Make sure method definition entries are all clear for next implementation.
MethodDefinitions.clear();
}
@@ -6217,82 +6431,59 @@ void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
ExtCatName += "_$_";
ExtCatName += OCD->getNameAsString();
- llvm::SmallString<64> ExtClassName(getClassSymbolPrefix());
- ExtClassName += Interface->getObjCRuntimeNameAsString();
-
- llvm::Constant *Values[8];
- Values[0] = GetClassName(OCD->getIdentifier()->getName());
+ ConstantInitBuilder builder(CGM);
+ auto values = builder.beginStruct(ObjCTypes.CategorynfABITy);
+ values.add(GetClassName(OCD->getIdentifier()->getName()));
// meta-class entry symbol
- llvm::GlobalVariable *ClassGV =
- GetClassGlobal(ExtClassName.str(), Interface->isWeakImported());
+ values.add(GetClassGlobal(Interface, /*metaclass*/ false, NotForDefinition));
+ std::string listName =
+ (Interface->getObjCRuntimeNameAsString() + "_$_" + OCD->getName()).str();
+
+ SmallVector<const ObjCMethodDecl *, 16> instanceMethods;
+ SmallVector<const ObjCMethodDecl *, 8> classMethods;
+ for (const auto *MD : OCD->methods()) {
+ if (MD->isInstanceMethod()) {
+ instanceMethods.push_back(MD);
+ } else {
+ classMethods.push_back(MD);
+ }
+ }
+
+ values.add(emitMethodList(listName, MethodListType::CategoryInstanceMethods,
+ instanceMethods));
+ values.add(emitMethodList(listName, MethodListType::CategoryClassMethods,
+ classMethods));
- Values[1] = ClassGV;
- std::vector<llvm::Constant*> Methods;
- llvm::SmallString<64> MethodListName(Prefix);
-
- MethodListName += "INSTANCE_METHODS_";
- MethodListName += Interface->getObjCRuntimeNameAsString();
- MethodListName += "_$_";
- MethodListName += OCD->getName();
-
- for (const auto *I : OCD->instance_methods())
- // Instance methods should always be defined.
- Methods.push_back(GetMethodConstant(I));
-
- Values[2] = EmitMethodList(MethodListName.str(),
- "__DATA, __objc_const",
- Methods);
-
- MethodListName = Prefix;
- MethodListName += "CLASS_METHODS_";
- MethodListName += Interface->getObjCRuntimeNameAsString();
- MethodListName += "_$_";
- MethodListName += OCD->getNameAsString();
-
- Methods.clear();
- for (const auto *I : OCD->class_methods())
- // Class methods should always be defined.
- Methods.push_back(GetMethodConstant(I));
-
- Values[3] = EmitMethodList(MethodListName.str(),
- "__DATA, __objc_const",
- Methods);
const ObjCCategoryDecl *Category =
Interface->FindCategoryDeclaration(OCD->getIdentifier());
if (Category) {
SmallString<256> ExtName;
llvm::raw_svector_ostream(ExtName) << Interface->getObjCRuntimeNameAsString() << "_$_"
<< OCD->getName();
- Values[4] = EmitProtocolList("\01l_OBJC_CATEGORY_PROTOCOLS_$_"
+ values.add(EmitProtocolList("\01l_OBJC_CATEGORY_PROTOCOLS_$_"
+ Interface->getObjCRuntimeNameAsString() + "_$_"
+ Category->getName(),
- Category->protocol_begin(),
- Category->protocol_end());
- Values[5] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
- OCD, Category, ObjCTypes, false);
- Values[6] = EmitPropertyList("\01l_OBJC_$_CLASS_PROP_LIST_" + ExtName.str(),
- OCD, Category, ObjCTypes, true);
+ Category->protocol_begin(),
+ Category->protocol_end()));
+ values.add(EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
+ OCD, Category, ObjCTypes, false));
+ values.add(EmitPropertyList("\01l_OBJC_$_CLASS_PROP_LIST_" + ExtName.str(),
+ OCD, Category, ObjCTypes, true));
} else {
- Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
- Values[5] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
- Values[6] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
+ values.addNullPointer(ObjCTypes.ProtocolListnfABIPtrTy);
+ values.addNullPointer(ObjCTypes.PropertyListPtrTy);
+ values.addNullPointer(ObjCTypes.PropertyListPtrTy);
}
unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.CategorynfABITy);
- Values[7] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
-
- llvm::Constant *Init =
- llvm::ConstantStruct::get(ObjCTypes.CategorynfABITy,
- Values);
- llvm::GlobalVariable *GCATV
- = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.CategorynfABITy,
- false,
- llvm::GlobalValue::PrivateLinkage,
- Init,
- ExtCatName.str());
- GCATV->setAlignment(
- CGM.getDataLayout().getABITypeAlignment(ObjCTypes.CategorynfABITy));
- GCATV->setSection("__DATA, __objc_const");
+ values.addInt(ObjCTypes.IntTy, Size);
+
+ llvm::GlobalVariable *GCATV =
+ values.finishAndCreateGlobal(ExtCatName.str(), CGM.getPointerAlign(),
+ /*constant*/ false,
+ llvm::GlobalValue::PrivateLinkage);
+ if (CGM.getTriple().isOSBinFormatMachO())
+ GCATV->setSection("__DATA, __objc_const");
CGM.addCompilerUsedGlobal(GCATV);
DefinedCategories.push_back(GCATV);
@@ -6303,25 +6494,37 @@ void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
MethodDefinitions.clear();
}
-/// GetMethodConstant - Return a struct objc_method constant for the
-/// given method if it has been defined. The result is null if the
-/// method has not been defined. The return value has type MethodPtrTy.
-llvm::Constant *CGObjCNonFragileABIMac::GetMethodConstant(
- const ObjCMethodDecl *MD) {
- llvm::Function *Fn = GetMethodDefinition(MD);
- if (!Fn)
- return nullptr;
-
- llvm::Constant *Method[] = {
- llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
- ObjCTypes.SelectorPtrTy),
- GetMethodVarType(MD),
- llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy)
- };
- return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
+/// emitMethodConstant - Return a struct objc_method constant. If
+/// forProtocol is true, the implementation will be null; otherwise,
+/// the method must have a definition registered with the runtime.
+///
+/// struct _objc_method {
+/// SEL _cmd;
+/// char *method_type;
+/// char *_imp;
+/// }
+void CGObjCNonFragileABIMac::emitMethodConstant(ConstantArrayBuilder &builder,
+ const ObjCMethodDecl *MD,
+ bool forProtocol) {
+ auto method = builder.beginStruct(ObjCTypes.MethodTy);
+ method.addBitCast(GetMethodVarName(MD->getSelector()),
+ ObjCTypes.SelectorPtrTy);
+ method.add(GetMethodVarType(MD));
+
+ if (forProtocol) {
+ // Protocol methods have no implementation. So, this entry is always NULL.
+ method.addNullPointer(ObjCTypes.Int8PtrTy);
+ } else {
+ llvm::Function *fn = GetMethodDefinition(MD);
+ assert(fn && "no definition for method?");
+ method.addBitCast(fn, ObjCTypes.Int8PtrTy);
+ }
+
+ method.finishAndAddTo(builder);
}
-/// EmitMethodList - Build meta-data for method declarations
+/// Build meta-data for method declarations.
+///
/// struct _method_list_t {
/// uint32_t entsize; // sizeof(struct _objc_method)
/// uint32_t method_count;
@@ -6329,28 +6532,69 @@ llvm::Constant *CGObjCNonFragileABIMac::GetMethodConstant(
/// }
///
llvm::Constant *
-CGObjCNonFragileABIMac::EmitMethodList(Twine Name, StringRef Section,
- ArrayRef<llvm::Constant *> Methods) {
+CGObjCNonFragileABIMac::emitMethodList(Twine name, MethodListType kind,
+ ArrayRef<const ObjCMethodDecl *> methods) {
// Return null for empty list.
- if (Methods.empty())
+ if (methods.empty())
return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy);
- llvm::Constant *Values[3];
+ StringRef prefix;
+ bool forProtocol;
+ switch (kind) {
+ case MethodListType::CategoryInstanceMethods:
+ prefix = "\01l_OBJC_$_CATEGORY_INSTANCE_METHODS_";
+ forProtocol = false;
+ break;
+ case MethodListType::CategoryClassMethods:
+ prefix = "\01l_OBJC_$_CATEGORY_CLASS_METHODS_";
+ forProtocol = false;
+ break;
+ case MethodListType::InstanceMethods:
+ prefix = "\01l_OBJC_$_INSTANCE_METHODS_";
+ forProtocol = false;
+ break;
+ case MethodListType::ClassMethods:
+ prefix = "\01l_OBJC_$_CLASS_METHODS_";
+ forProtocol = false;
+ break;
+
+ case MethodListType::ProtocolInstanceMethods:
+ prefix = "\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_";
+ forProtocol = true;
+ break;
+ case MethodListType::ProtocolClassMethods:
+ prefix = "\01l_OBJC_$_PROTOCOL_CLASS_METHODS_";
+ forProtocol = true;
+ break;
+ case MethodListType::OptionalProtocolInstanceMethods:
+ prefix = "\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_";
+ forProtocol = true;
+ break;
+ case MethodListType::OptionalProtocolClassMethods:
+ prefix = "\01l_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_";
+ forProtocol = true;
+ break;
+ }
+
+ ConstantInitBuilder builder(CGM);
+ auto values = builder.beginStruct();
+
// sizeof(struct _objc_method)
unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.MethodTy);
- Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
+ values.addInt(ObjCTypes.IntTy, Size);
// method_count
- Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
- llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
- Methods.size());
- Values[2] = llvm::ConstantArray::get(AT, Methods);
- llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
+ values.addInt(ObjCTypes.IntTy, methods.size());
+ auto methodArray = values.beginArray(ObjCTypes.MethodTy);
+ for (auto MD : methods) {
+ emitMethodConstant(methodArray, MD, forProtocol);
+ }
+ methodArray.finishAndAddTo(values);
- llvm::GlobalVariable *GV =
- new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
- llvm::GlobalValue::PrivateLinkage, Init, Name);
- GV->setAlignment(CGM.getDataLayout().getABITypeAlignment(Init->getType()));
- GV->setSection(Section);
+ auto *GV = values.finishAndCreateGlobal(prefix + name, CGM.getPointerAlign(),
+ /*constant*/ false,
+ llvm::GlobalValue::PrivateLinkage);
+ if (CGM.getTriple().isOSBinFormatMachO())
+ GV->setSection("__DATA, __objc_const");
CGM.addCompilerUsedGlobal(GV);
return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodListnfABIPtrTy);
}
@@ -6406,7 +6650,8 @@ CGObjCNonFragileABIMac::EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility);
}
- IvarOffsetGV->setSection("__DATA, __objc_ivar");
+ if (CGM.getTriple().isOSBinFormatMachO())
+ IvarOffsetGV->setSection("__DATA, __objc_ivar");
return IvarOffsetGV;
}
@@ -6430,7 +6675,12 @@ CGObjCNonFragileABIMac::EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList(
const ObjCImplementationDecl *ID) {
- std::vector<llvm::Constant*> Ivars;
+ ConstantInitBuilder builder(CGM);
+ auto ivarList = builder.beginStruct();
+ ivarList.addInt(ObjCTypes.IntTy,
+ CGM.getDataLayout().getTypeAllocSize(ObjCTypes.IvarnfABITy));
+ auto ivarCountSlot = ivarList.addPlaceholder();
+ auto ivars = ivarList.beginArray(ObjCTypes.IvarnfABITy);
const ObjCInterfaceDecl *OID = ID->getClassInterface();
assert(OID && "CGObjCNonFragileABIMac::EmitIvarList - null interface");
@@ -6442,48 +6692,45 @@ llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList(
// Ignore unnamed bit-fields.
if (!IVD->getDeclName())
continue;
- llvm::Constant *Ivar[5];
- Ivar[0] = EmitIvarOffsetVar(ID->getClassInterface(), IVD,
- ComputeIvarBaseOffset(CGM, ID, IVD));
- Ivar[1] = GetMethodVarName(IVD->getIdentifier());
- Ivar[2] = GetMethodVarType(IVD);
+
+ auto ivar = ivars.beginStruct(ObjCTypes.IvarnfABITy);
+ ivar.add(EmitIvarOffsetVar(ID->getClassInterface(), IVD,
+ ComputeIvarBaseOffset(CGM, ID, IVD)));
+ ivar.add(GetMethodVarName(IVD->getIdentifier()));
+ ivar.add(GetMethodVarType(IVD));
llvm::Type *FieldTy =
CGM.getTypes().ConvertTypeForMem(IVD->getType());
unsigned Size = CGM.getDataLayout().getTypeAllocSize(FieldTy);
unsigned Align = CGM.getContext().getPreferredTypeAlign(
IVD->getType().getTypePtr()) >> 3;
Align = llvm::Log2_32(Align);
- Ivar[3] = llvm::ConstantInt::get(ObjCTypes.IntTy, Align);
+ ivar.addInt(ObjCTypes.IntTy, Align);
// NOTE. Size of a bitfield does not match gcc's, because of the
// way bitfields are treated special in each. But I am told that
// 'size' for bitfield ivars is ignored by the runtime so it does
// not matter. If it matters, there is enough info to get the
// bitfield right!
- Ivar[4] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
- Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarnfABITy, Ivar));
+ ivar.addInt(ObjCTypes.IntTy, Size);
+ ivar.finishAndAddTo(ivars);
}
// Return null for empty list.
- if (Ivars.empty())
+ if (ivars.empty()) {
+ ivars.abandon();
+ ivarList.abandon();
return llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
+ }
+
+ auto ivarCount = ivars.size();
+ ivars.finishAndAddTo(ivarList);
+ ivarList.fillPlaceholderWithInt(ivarCountSlot, ObjCTypes.IntTy, ivarCount);
- llvm::Constant *Values[3];
- unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.IvarnfABITy);
- Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
- Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
- llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarnfABITy,
- Ivars.size());
- Values[2] = llvm::ConstantArray::get(AT, Ivars);
- llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
const char *Prefix = "\01l_OBJC_$_INSTANCE_VARIABLES_";
llvm::GlobalVariable *GV =
- new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
- llvm::GlobalValue::PrivateLinkage,
- Init,
- Prefix + OID->getObjCRuntimeNameAsString());
- GV->setAlignment(
- CGM.getDataLayout().getABITypeAlignment(Init->getType()));
- GV->setSection("__DATA, __objc_const");
-
+ ivarList.finishAndCreateGlobal(Prefix + OID->getObjCRuntimeNameAsString(),
+ CGM.getPointerAlign(), /*constant*/ false,
+ llvm::GlobalValue::PrivateLinkage);
+ if (CGM.getTriple().isOSBinFormatMachO())
+ GV->setSection("__DATA, __objc_const");
CGM.addCompilerUsedGlobal(GV);
return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListnfABIPtrTy);
}
@@ -6492,15 +6739,20 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef(
const ObjCProtocolDecl *PD) {
llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
- if (!Entry)
+ if (!Entry) {
// We use the initializer as a marker of whether this is a forward
// reference or not. At module finalization we add the empty
// contents for protocols which were referenced but never defined.
- Entry =
- new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy,
- false, llvm::GlobalValue::ExternalLinkage,
- nullptr,
- "\01l_OBJC_PROTOCOL_$_" + PD->getObjCRuntimeNameAsString());
+ llvm::SmallString<64> Protocol;
+ llvm::raw_svector_ostream(Protocol) << "\01l_OBJC_PROTOCOL_$_"
+ << PD->getObjCRuntimeNameAsString();
+
+ Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy,
+ false, llvm::GlobalValue::ExternalLinkage,
+ nullptr, Protocol);
+ if (!CGM.getTriple().isOSBinFormatMachO())
+ Entry->setComdat(CGM.getModule().getOrInsertComdat(Protocol));
+ }
return Entry;
}
@@ -6537,96 +6789,59 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
if (const ObjCProtocolDecl *Def = PD->getDefinition())
PD = Def;
- // Construct method lists.
- std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
- std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
- std::vector<llvm::Constant*> MethodTypesExt, OptMethodTypesExt;
- for (const auto *MD : PD->instance_methods()) {
- llvm::Constant *C = GetMethodDescriptionConstant(MD);
- if (!C)
- return GetOrEmitProtocolRef(PD);
-
- if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
- OptInstanceMethods.push_back(C);
- OptMethodTypesExt.push_back(GetMethodVarType(MD, true));
- } else {
- InstanceMethods.push_back(C);
- MethodTypesExt.push_back(GetMethodVarType(MD, true));
- }
- }
-
- for (const auto *MD : PD->class_methods()) {
- llvm::Constant *C = GetMethodDescriptionConstant(MD);
- if (!C)
- return GetOrEmitProtocolRef(PD);
-
- if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
- OptClassMethods.push_back(C);
- OptMethodTypesExt.push_back(GetMethodVarType(MD, true));
- } else {
- ClassMethods.push_back(C);
- MethodTypesExt.push_back(GetMethodVarType(MD, true));
- }
- }
+ auto methodLists = ProtocolMethodLists::get(PD);
- MethodTypesExt.insert(MethodTypesExt.end(),
- OptMethodTypesExt.begin(), OptMethodTypesExt.end());
+ ConstantInitBuilder builder(CGM);
+ auto values = builder.beginStruct(ObjCTypes.ProtocolnfABITy);
- llvm::Constant *Values[13];
// isa is NULL
- Values[0] = llvm::Constant::getNullValue(ObjCTypes.ObjectPtrTy);
- Values[1] = GetClassName(PD->getObjCRuntimeNameAsString());
- Values[2] = EmitProtocolList("\01l_OBJC_$_PROTOCOL_REFS_" + PD->getObjCRuntimeNameAsString(),
+ values.addNullPointer(ObjCTypes.ObjectPtrTy);
+ values.add(GetClassName(PD->getObjCRuntimeNameAsString()));
+ values.add(EmitProtocolList("\01l_OBJC_$_PROTOCOL_REFS_"
+ + PD->getObjCRuntimeNameAsString(),
PD->protocol_begin(),
- PD->protocol_end());
-
- Values[3] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_"
- + PD->getObjCRuntimeNameAsString(),
- "__DATA, __objc_const",
- InstanceMethods);
- Values[4] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_"
- + PD->getObjCRuntimeNameAsString(),
- "__DATA, __objc_const",
- ClassMethods);
- Values[5] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_"
- + PD->getObjCRuntimeNameAsString(),
- "__DATA, __objc_const",
- OptInstanceMethods);
- Values[6] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_"
- + PD->getObjCRuntimeNameAsString(),
- "__DATA, __objc_const",
- OptClassMethods);
- Values[7] = EmitPropertyList(
- "\01l_OBJC_$_PROP_LIST_" + PD->getObjCRuntimeNameAsString(),
- nullptr, PD, ObjCTypes, false);
+ PD->protocol_end()));
+ values.add(methodLists.emitMethodList(this, PD,
+ ProtocolMethodLists::RequiredInstanceMethods));
+ values.add(methodLists.emitMethodList(this, PD,
+ ProtocolMethodLists::RequiredClassMethods));
+ values.add(methodLists.emitMethodList(this, PD,
+ ProtocolMethodLists::OptionalInstanceMethods));
+ values.add(methodLists.emitMethodList(this, PD,
+ ProtocolMethodLists::OptionalClassMethods));
+ values.add(EmitPropertyList(
+ "\01l_OBJC_$_PROP_LIST_" + PD->getObjCRuntimeNameAsString(),
+ nullptr, PD, ObjCTypes, false));
uint32_t Size =
CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolnfABITy);
- Values[8] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
- Values[9] = llvm::Constant::getNullValue(ObjCTypes.IntTy);
- Values[10] = EmitProtocolMethodTypes("\01l_OBJC_$_PROTOCOL_METHOD_TYPES_"
+ values.addInt(ObjCTypes.IntTy, Size);
+ values.addInt(ObjCTypes.IntTy, 0);
+ values.add(EmitProtocolMethodTypes("\01l_OBJC_$_PROTOCOL_METHOD_TYPES_"
+ PD->getObjCRuntimeNameAsString(),
- MethodTypesExt, ObjCTypes);
+ methodLists.emitExtendedTypesArray(this),
+ ObjCTypes));
+
// const char *demangledName;
- Values[11] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
+ values.addNullPointer(ObjCTypes.Int8PtrTy);
- Values[12] = EmitPropertyList(
+ values.add(EmitPropertyList(
"\01l_OBJC_$_CLASS_PROP_LIST_" + PD->getObjCRuntimeNameAsString(),
- nullptr, PD, ObjCTypes, true);
+ nullptr, PD, ObjCTypes, true));
- llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolnfABITy,
- Values);
-
if (Entry) {
// Already created, fix the linkage and update the initializer.
Entry->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
- Entry->setInitializer(Init);
+ values.finishAndSetAsInitializer(Entry);
} else {
- Entry =
- new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy,
- false, llvm::GlobalValue::WeakAnyLinkage, Init,
- "\01l_OBJC_PROTOCOL_$_" + PD->getObjCRuntimeNameAsString());
- Entry->setAlignment(
- CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ProtocolnfABITy));
+ llvm::SmallString<64> symbolName;
+ llvm::raw_svector_ostream(symbolName)
+ << "\01l_OBJC_PROTOCOL_$_" << PD->getObjCRuntimeNameAsString();
+
+ Entry = values.finishAndCreateGlobal(symbolName, CGM.getPointerAlign(),
+ /*constant*/ false,
+ llvm::GlobalValue::WeakAnyLinkage);
+ if (!CGM.getTriple().isOSBinFormatMachO())
+ Entry->setComdat(CGM.getModule().getOrInsertComdat(symbolName));
Protocols[PD->getIdentifier()] = Entry;
}
@@ -6635,13 +6850,20 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
// Use this protocol meta-data to build protocol list table in section
// __DATA, __objc_protolist
+ llvm::SmallString<64> ProtocolRef;
+ llvm::raw_svector_ostream(ProtocolRef) << "\01l_OBJC_LABEL_PROTOCOL_$_"
+ << PD->getObjCRuntimeNameAsString();
+
llvm::GlobalVariable *PTGV =
new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABIPtrTy,
false, llvm::GlobalValue::WeakAnyLinkage, Entry,
- "\01l_OBJC_LABEL_PROTOCOL_$_" + PD->getObjCRuntimeNameAsString());
+ ProtocolRef);
+ if (!CGM.getTriple().isOSBinFormatMachO())
+ PTGV->setComdat(CGM.getModule().getOrInsertComdat(ProtocolRef));
PTGV->setAlignment(
CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ProtocolnfABIPtrTy));
- PTGV->setSection("__DATA, __objc_protolist, coalesced, no_dead_strip");
+ if (CGM.getTriple().isOSBinFormatMachO())
+ PTGV->setSection("__DATA, __objc_protolist, coalesced, no_dead_strip");
PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
CGM.addCompilerUsedGlobal(PTGV);
return Entry;
@@ -6673,55 +6895,30 @@ CGObjCNonFragileABIMac::EmitProtocolList(Twine Name,
if (GV)
return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListnfABIPtrTy);
- for (; begin != end; ++begin)
- ProtocolRefs.push_back(GetProtocolRef(*begin)); // Implemented???
+ ConstantInitBuilder builder(CGM);
+ auto values = builder.beginStruct();
+ auto countSlot = values.addPlaceholder();
- // This list is null terminated.
- ProtocolRefs.push_back(llvm::Constant::getNullValue(
- ObjCTypes.ProtocolnfABIPtrTy));
-
- llvm::Constant *Values[2];
- Values[0] =
- llvm::ConstantInt::get(ObjCTypes.LongTy, ProtocolRefs.size() - 1);
- Values[1] =
- llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.ProtocolnfABIPtrTy,
- ProtocolRefs.size()),
- ProtocolRefs);
-
- llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
- GV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
- llvm::GlobalValue::PrivateLinkage,
- Init, Name);
- GV->setSection("__DATA, __objc_const");
- GV->setAlignment(
- CGM.getDataLayout().getABITypeAlignment(Init->getType()));
+ // A null-terminated array of protocols.
+ auto array = values.beginArray(ObjCTypes.ProtocolnfABIPtrTy);
+ for (; begin != end; ++begin)
+ array.add(GetProtocolRef(*begin)); // Implemented???
+ auto count = array.size();
+ array.addNullPointer(ObjCTypes.ProtocolnfABIPtrTy);
+
+ array.finishAndAddTo(values);
+ values.fillPlaceholderWithInt(countSlot, ObjCTypes.LongTy, count);
+
+ GV = values.finishAndCreateGlobal(Name, CGM.getPointerAlign(),
+ /*constant*/ false,
+ llvm::GlobalValue::PrivateLinkage);
+ if (CGM.getTriple().isOSBinFormatMachO())
+ GV->setSection("__DATA, __objc_const");
CGM.addCompilerUsedGlobal(GV);
return llvm::ConstantExpr::getBitCast(GV,
ObjCTypes.ProtocolListnfABIPtrTy);
}
-/// GetMethodDescriptionConstant - This routine build following meta-data:
-/// struct _objc_method {
-/// SEL _cmd;
-/// char *method_type;
-/// char *_imp;
-/// }
-
-llvm::Constant *
-CGObjCNonFragileABIMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
- llvm::Constant *Desc[3];
- Desc[0] =
- llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
- ObjCTypes.SelectorPtrTy);
- Desc[1] = GetMethodVarType(MD);
- if (!Desc[1])
- return nullptr;
-
- // Protocol methods have no implementation. So, this entry is always NULL.
- Desc[2] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
- return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Desc);
-}
-
/// EmitObjCValueForIvar - Code Gen for nonfragile ivar reference.
/// This code gen. amounts to generating code for:
/// @code
@@ -6853,16 +7050,15 @@ CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF,
= CGM.getModule().getGlobalVariable(messageRefName);
if (!messageRef) {
// Build the message ref structure.
- llvm::Constant *values[] = { fn, GetMethodVarName(selector) };
- llvm::Constant *init = llvm::ConstantStruct::getAnon(values);
- messageRef = new llvm::GlobalVariable(CGM.getModule(),
- init->getType(),
- /*constant*/ false,
- llvm::GlobalValue::WeakAnyLinkage,
- init,
- messageRefName);
+ ConstantInitBuilder builder(CGM);
+ auto values = builder.beginStruct();
+ values.add(fn);
+ values.add(GetMethodVarName(selector));
+ messageRef = values.finishAndCreateGlobal(messageRefName,
+ CharUnits::fromQuantity(16),
+ /*constant*/ false,
+ llvm::GlobalValue::WeakAnyLinkage);
messageRef->setVisibility(llvm::GlobalValue::HiddenVisibility);
- messageRef->setAlignment(16);
messageRef->setSection("__DATA, __objc_msgrefs, coalesced");
}
@@ -6887,9 +7083,10 @@ CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF,
// Load the function to call from the message ref table.
Address calleeAddr =
CGF.Builder.CreateStructGEP(mref, 0, CharUnits::Zero());
- llvm::Value *callee = CGF.Builder.CreateLoad(calleeAddr, "msgSend_fn");
+ llvm::Value *calleePtr = CGF.Builder.CreateLoad(calleeAddr, "msgSend_fn");
- callee = CGF.Builder.CreateBitCast(callee, MSI.MessengerType);
+ calleePtr = CGF.Builder.CreateBitCast(calleePtr, MSI.MessengerType);
+ CGCallee callee(CGCalleeInfo(), calleePtr);
RValue result = CGF.EmitCall(MSI.CallInfo, callee, returnSlot, args);
return nullReturn.complete(CGF, result, resultType, formalArgs,
@@ -6916,33 +7113,59 @@ CGObjCNonFragileABIMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
false, CallArgs, Method, Class, ObjCTypes);
}
-llvm::GlobalVariable *
-CGObjCNonFragileABIMac::GetClassGlobal(StringRef Name, bool Weak) {
+llvm::Constant *
+CGObjCNonFragileABIMac::GetClassGlobal(const ObjCInterfaceDecl *ID,
+ bool metaclass,
+ ForDefinition_t isForDefinition) {
+ auto prefix =
+ (metaclass ? getMetaclassSymbolPrefix() : getClassSymbolPrefix());
+ return GetClassGlobal((prefix + ID->getObjCRuntimeNameAsString()).str(),
+ isForDefinition,
+ ID->isWeakImported(),
+ !isForDefinition
+ && CGM.getTriple().isOSBinFormatCOFF()
+ && ID->hasAttr<DLLImportAttr>());
+}
+
+llvm::Constant *
+CGObjCNonFragileABIMac::GetClassGlobal(StringRef Name,
+ ForDefinition_t IsForDefinition,
+ bool Weak, bool DLLImport) {
llvm::GlobalValue::LinkageTypes L =
Weak ? llvm::GlobalValue::ExternalWeakLinkage
: llvm::GlobalValue::ExternalLinkage;
- llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
- if (!GV)
+
+ llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
+ if (!GV) {
GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABITy,
false, L, nullptr, Name);
+ if (DLLImport)
+ GV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
+ }
+
assert(GV->getLinkage() == L);
return GV;
}
-llvm::Value *CGObjCNonFragileABIMac::EmitClassRefFromId(CodeGenFunction &CGF,
- IdentifierInfo *II,
- bool Weak,
- const ObjCInterfaceDecl *ID) {
+llvm::Value *
+CGObjCNonFragileABIMac::EmitClassRefFromId(CodeGenFunction &CGF,
+ IdentifierInfo *II,
+ const ObjCInterfaceDecl *ID) {
CharUnits Align = CGF.getPointerAlign();
llvm::GlobalVariable *&Entry = ClassReferences[II];
if (!Entry) {
- StringRef Name = ID ? ID->getObjCRuntimeNameAsString() : II->getName();
- std::string ClassName = (getClassSymbolPrefix() + Name).str();
- llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName, Weak);
+ llvm::Constant *ClassGV;
+ if (ID) {
+ ClassGV = GetClassGlobal(ID, /*metaclass*/ false, NotForDefinition);
+ } else {
+ ClassGV = GetClassGlobal((getClassSymbolPrefix() + II->getName()).str(),
+ NotForDefinition);
+ }
+
Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
false, llvm::GlobalValue::PrivateLinkage,
ClassGV, "OBJC_CLASSLIST_REFERENCES_$_");
@@ -6960,13 +7183,13 @@ llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CodeGenFunction &CGF,
if (ID->hasAttr<ObjCRuntimeVisibleAttr>())
return EmitClassRefViaRuntime(CGF, ID, ObjCTypes);
- return EmitClassRefFromId(CGF, ID->getIdentifier(), ID->isWeakImported(), ID);
+ return EmitClassRefFromId(CGF, ID->getIdentifier(), ID);
}
llvm::Value *CGObjCNonFragileABIMac::EmitNSAutoreleasePoolClassRef(
CodeGenFunction &CGF) {
IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool");
- return EmitClassRefFromId(CGF, II, false, nullptr);
+ return EmitClassRefFromId(CGF, II, nullptr);
}
llvm::Value *
@@ -6976,10 +7199,7 @@ CGObjCNonFragileABIMac::EmitSuperClassRef(CodeGenFunction &CGF,
llvm::GlobalVariable *&Entry = SuperClassReferences[ID->getIdentifier()];
if (!Entry) {
- llvm::SmallString<64> ClassName(getClassSymbolPrefix());
- ClassName += ID->getObjCRuntimeNameAsString();
- llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName.str(),
- ID->isWeakImported());
+ auto ClassGV = GetClassGlobal(ID, /*metaclass*/ false, NotForDefinition);
Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
false, llvm::GlobalValue::PrivateLinkage,
ClassGV, "OBJC_CLASSLIST_SUP_REFS_$_");
@@ -6999,10 +7219,7 @@ llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CodeGenFunction &CGF,
CharUnits Align = CGF.getPointerAlign();
llvm::GlobalVariable * &Entry = MetaClassReferences[ID->getIdentifier()];
if (!Entry) {
- llvm::SmallString<64> MetaClassName(getMetaclassSymbolPrefix());
- MetaClassName += ID->getObjCRuntimeNameAsString();
- llvm::GlobalVariable *MetaClassGV =
- GetClassGlobal(MetaClassName.str(), Weak);
+ auto MetaClassGV = GetClassGlobal(ID, /*metaclass*/ true, NotForDefinition);
Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
false, llvm::GlobalValue::PrivateLinkage,
@@ -7021,11 +7238,10 @@ llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CodeGenFunction &CGF,
llvm::Value *CGObjCNonFragileABIMac::GetClass(CodeGenFunction &CGF,
const ObjCInterfaceDecl *ID) {
if (ID->isWeakImported()) {
- llvm::SmallString<64> ClassName(getClassSymbolPrefix());
- ClassName += ID->getObjCRuntimeNameAsString();
- llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName.str(), true);
+ auto ClassGV = GetClassGlobal(ID, /*metaclass*/ false, NotForDefinition);
(void)ClassGV;
- assert(ClassGV->hasExternalWeakLinkage());
+ assert(!isa<llvm::GlobalVariable>(ClassGV) ||
+ cast<llvm::GlobalVariable>(ClassGV)->hasExternalWeakLinkage());
}
return EmitClassRef(CGF, ID);
@@ -7258,7 +7474,7 @@ CGObjCNonFragileABIMac::GetEHType(QualType T) {
const ObjCInterfaceType *IT = PT->getInterfaceType();
assert(IT && "Invalid @catch type.");
- return GetInterfaceEHType(IT->getDecl(), false);
+ return GetInterfaceEHType(IT->getDecl(), NotForDefinition);
}
void CGObjCNonFragileABIMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
@@ -7290,13 +7506,13 @@ void CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
llvm::Constant *
CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
- bool ForDefinition) {
+ ForDefinition_t IsForDefinition) {
llvm::GlobalVariable * &Entry = EHTypeReferences[ID->getIdentifier()];
StringRef ClassName = ID->getObjCRuntimeNameAsString();
// If we don't need a definition, return the entry if found or check
// if we use an external reference.
- if (!ForDefinition) {
+ if (!IsForDefinition) {
if (Entry)
return Entry;
@@ -7332,23 +7548,24 @@ CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
}
llvm::Value *VTableIdx = llvm::ConstantInt::get(CGM.Int32Ty, 2);
- llvm::Constant *Values[] = {
- llvm::ConstantExpr::getGetElementPtr(VTableGV->getValueType(), VTableGV,
- VTableIdx),
- GetClassName(ID->getObjCRuntimeNameAsString()),
- GetClassGlobal((getClassSymbolPrefix() + ClassName).str()),
- };
- llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.EHTypeTy, Values);
-
- llvm::GlobalValue::LinkageTypes L = ForDefinition
+ ConstantInitBuilder builder(CGM);
+ auto values = builder.beginStruct(ObjCTypes.EHTypeTy);
+ values.add(llvm::ConstantExpr::getGetElementPtr(VTableGV->getValueType(),
+ VTableGV, VTableIdx));
+ values.add(GetClassName(ClassName));
+ values.add(GetClassGlobal(ID, /*metaclass*/ false, NotForDefinition));
+
+ llvm::GlobalValue::LinkageTypes L = IsForDefinition
? llvm::GlobalValue::ExternalLinkage
: llvm::GlobalValue::WeakAnyLinkage;
if (Entry) {
- Entry->setInitializer(Init);
+ values.finishAndSetAsInitializer(Entry);
+ Entry->setAlignment(CGM.getPointerAlign().getQuantity());
} else {
- Entry =
- new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false, L,
- Init, ("OBJC_EHTYPE_$_" + ClassName).str());
+ Entry = values.finishAndCreateGlobal("OBJC_EHTYPE_$_" + ClassName,
+ CGM.getPointerAlign(),
+ /*constant*/ false,
+ L);
if (CGM.getTriple().isOSBinFormatCOFF())
if (hasObjCExceptionAttribute(CGM.getContext(), ID))
if (ID->hasAttr<DLLExportAttr>())
@@ -7360,11 +7577,9 @@ CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
if (ID->getVisibility() == HiddenVisibility)
Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
- const auto &DL = CGM.getDataLayout();
- Entry->setAlignment(DL.getABITypeAlignment(ObjCTypes.EHTypeTy));
-
- if (ForDefinition)
- Entry->setSection("__DATA,__objc_const");
+ if (IsForDefinition)
+ if (CGM.getTriple().isOSBinFormatMachO())
+ Entry->setSection("__DATA,__objc_const");
return Entry;
}
diff --git a/lib/CodeGen/CGObjCRuntime.cpp b/lib/CodeGen/CGObjCRuntime.cpp
index 0caf6d9f210a..3da7ed230edd 100644
--- a/lib/CodeGen/CGObjCRuntime.cpp
+++ b/lib/CodeGen/CGObjCRuntime.cpp
@@ -90,7 +90,7 @@ LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF,
unsigned CVRQualifiers,
llvm::Value *Offset) {
// Compute (type*) ( (char *) BaseValue + Offset)
- QualType IvarTy = Ivar->getType();
+ QualType IvarTy = Ivar->getType().withCVRQualifiers(CVRQualifiers);
llvm::Type *LTy = CGF.CGM.getTypes().ConvertTypeForMem(IvarTy);
llvm::Value *V = CGF.Builder.CreateBitCast(BaseValue, CGF.Int8PtrTy);
V = CGF.Builder.CreateInBoundsGEP(V, Offset, "add.ptr");
@@ -98,7 +98,6 @@ LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF,
if (!Ivar->isBitField()) {
V = CGF.Builder.CreateBitCast(V, llvm::PointerType::getUnqual(LTy));
LValue LV = CGF.MakeNaturalAlignAddrLValue(V, IvarTy);
- LV.getQuals().addCVRQualifiers(CVRQualifiers);
return LV;
}
@@ -139,9 +138,7 @@ LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF,
Addr = CGF.Builder.CreateElementBitCast(Addr,
llvm::Type::getIntNTy(CGF.getLLVMContext(),
Info->StorageSize));
- return LValue::MakeBitfield(Addr, *Info,
- IvarTy.withCVRQualifiers(CVRQualifiers),
- AlignmentSource::Decl);
+ return LValue::MakeBitfield(Addr, *Info, IvarTy, AlignmentSource::Decl);
}
namespace {
@@ -153,18 +150,16 @@ namespace {
};
struct CallObjCEndCatch final : EHScopeStack::Cleanup {
- CallObjCEndCatch(bool MightThrow, llvm::Value *Fn) :
- MightThrow(MightThrow), Fn(Fn) {}
+ CallObjCEndCatch(bool MightThrow, llvm::Value *Fn)
+ : MightThrow(MightThrow), Fn(Fn) {}
bool MightThrow;
llvm::Value *Fn;
void Emit(CodeGenFunction &CGF, Flags flags) override {
- if (!MightThrow) {
- CGF.Builder.CreateCall(Fn)->setDoesNotThrow();
- return;
- }
-
- CGF.EmitRuntimeCallOrInvoke(Fn);
+ if (MightThrow)
+ CGF.EmitRuntimeCallOrInvoke(Fn);
+ else
+ CGF.EmitNounwindRuntimeCall(Fn);
}
};
}
@@ -233,10 +228,8 @@ void CGObjCRuntime::EmitTryCatchStmt(CodeGenFunction &CGF,
// Enter the catch.
llvm::Value *Exn = RawExn;
- if (beginCatchFn) {
- Exn = CGF.Builder.CreateCall(beginCatchFn, RawExn, "exn.adjusted");
- cast<llvm::CallInst>(Exn)->setDoesNotThrow();
- }
+ if (beginCatchFn)
+ Exn = CGF.EmitNounwindRuntimeCall(beginCatchFn, RawExn, "exn.adjusted");
CodeGenFunction::LexicalScope cleanups(CGF, Handler.Body->getSourceRange());
diff --git a/lib/CodeGen/CGObjCRuntime.h b/lib/CodeGen/CGObjCRuntime.h
index 6c330590f7cd..a14b44abf413 100644
--- a/lib/CodeGen/CGObjCRuntime.h
+++ b/lib/CodeGen/CGObjCRuntime.h
@@ -280,9 +280,6 @@ public:
virtual llvm::Constant *BuildByrefLayout(CodeGen::CodeGenModule &CGM,
QualType T) = 0;
- virtual llvm::GlobalVariable *GetClassGlobal(StringRef Name,
- bool Weak = false) = 0;
-
struct MessageSendInfo {
const CGFunctionInfo &CallInfo;
llvm::PointerType *MessengerType;
diff --git a/lib/CodeGen/CGOpenCLRuntime.cpp b/lib/CodeGen/CGOpenCLRuntime.cpp
index 38aebea18ed3..9062936fdd14 100644
--- a/lib/CodeGen/CGOpenCLRuntime.cpp
+++ b/lib/CodeGen/CGOpenCLRuntime.cpp
@@ -15,6 +15,7 @@
#include "CGOpenCLRuntime.h"
#include "CodeGenFunction.h"
+#include "TargetInfo.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/GlobalValue.h"
#include <assert.h>
@@ -34,10 +35,10 @@ llvm::Type *CGOpenCLRuntime::convertOpenCLSpecificType(const Type *T) {
"Not an OpenCL specific type!");
llvm::LLVMContext& Ctx = CGM.getLLVMContext();
- uint32_t ImgAddrSpc =
- CGM.getContext().getTargetAddressSpace(LangAS::opencl_global);
+ uint32_t ImgAddrSpc = CGM.getContext().getTargetAddressSpace(
+ CGM.getTarget().getOpenCLImageAddrSpace());
switch (cast<BuiltinType>(T)->getKind()) {
- default:
+ default:
llvm_unreachable("Unexpected opencl builtin type!");
return nullptr;
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
@@ -47,7 +48,7 @@ llvm::Type *CGOpenCLRuntime::convertOpenCLSpecificType(const Type *T) {
ImgAddrSpc);
#include "clang/Basic/OpenCLImageTypes.def"
case BuiltinType::OCLSampler:
- return llvm::IntegerType::get(Ctx, 32);
+ return getSamplerType();
case BuiltinType::OCLEvent:
return llvm::PointerType::get(llvm::StructType::create(
Ctx, "opencl.event_t"), 0);
@@ -76,3 +77,32 @@ llvm::Type *CGOpenCLRuntime::getPipeType() {
return PipeTy;
}
+
+llvm::PointerType *CGOpenCLRuntime::getSamplerType() {
+ if (!SamplerTy)
+ SamplerTy = llvm::PointerType::get(llvm::StructType::create(
+ CGM.getLLVMContext(), "opencl.sampler_t"),
+ CGM.getContext().getTargetAddressSpace(
+ LangAS::opencl_constant));
+ return SamplerTy;
+}
+
+llvm::Value *CGOpenCLRuntime::getPipeElemSize(const Expr *PipeArg) {
+ const PipeType *PipeTy = PipeArg->getType()->getAs<PipeType>();
+ // The type of the last (implicit) argument to be passed.
+ llvm::Type *Int32Ty = llvm::IntegerType::getInt32Ty(CGM.getLLVMContext());
+ unsigned TypeSize = CGM.getContext()
+ .getTypeSizeInChars(PipeTy->getElementType())
+ .getQuantity();
+ return llvm::ConstantInt::get(Int32Ty, TypeSize, false);
+}
+
+llvm::Value *CGOpenCLRuntime::getPipeElemAlign(const Expr *PipeArg) {
+ const PipeType *PipeTy = PipeArg->getType()->getAs<PipeType>();
+ // The type of the last (implicit) argument to be passed.
+ llvm::Type *Int32Ty = llvm::IntegerType::getInt32Ty(CGM.getLLVMContext());
+ unsigned TypeSize = CGM.getContext()
+ .getTypeAlignInChars(PipeTy->getElementType())
+ .getQuantity();
+ return llvm::ConstantInt::get(Int32Ty, TypeSize, false);
+}
diff --git a/lib/CodeGen/CGOpenCLRuntime.h b/lib/CodeGen/CGOpenCLRuntime.h
index f1a7a3106443..ee3cb3dda063 100644
--- a/lib/CodeGen/CGOpenCLRuntime.h
+++ b/lib/CodeGen/CGOpenCLRuntime.h
@@ -33,9 +33,11 @@ class CGOpenCLRuntime {
protected:
CodeGenModule &CGM;
llvm::Type *PipeTy;
+ llvm::PointerType *SamplerTy;
public:
- CGOpenCLRuntime(CodeGenModule &CGM) : CGM(CGM), PipeTy(nullptr) {}
+ CGOpenCLRuntime(CodeGenModule &CGM) : CGM(CGM), PipeTy(nullptr),
+ SamplerTy(nullptr) {}
virtual ~CGOpenCLRuntime();
/// Emit the IR required for a work-group-local variable declaration, and add
@@ -47,6 +49,16 @@ public:
virtual llvm::Type *convertOpenCLSpecificType(const Type *T);
virtual llvm::Type *getPipeType();
+
+ llvm::PointerType *getSamplerType();
+
+ // \brief Returnes 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
+ // element.
+ virtual llvm::Value *getPipeElemAlign(const Expr *PipeArg);
};
}
diff --git a/lib/CodeGen/CGOpenMPRuntime.cpp b/lib/CodeGen/CGOpenMPRuntime.cpp
index 6a0edbe0e7a9..0624d86b564a 100644
--- a/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -15,10 +15,11 @@
#include "CGCleanup.h"
#include "CGOpenMPRuntime.h"
#include "CodeGenFunction.h"
+#include "ConstantBuilder.h"
#include "clang/AST/Decl.h"
#include "clang/AST/StmtOpenMP.h"
#include "llvm/ADT/ArrayRef.h"
-#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/Bitcode/BitcodeReader.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/GlobalValue.h"
@@ -489,7 +490,7 @@ enum OpenMPSchedType {
OMP_sch_runtime = 37,
OMP_sch_auto = 38,
/// static with chunk adjustment (e.g., simd)
- OMP_sch_static_balanced_chunked = 45,
+ OMP_sch_static_balanced_chunked = 45,
/// \brief Lower bound for 'ordered' versions.
OMP_ord_lower = 64,
OMP_ord_static_chunked = 65,
@@ -756,6 +757,7 @@ emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty,
FnTy, llvm::GlobalValue::InternalLinkage,
IsCombiner ? ".omp_combiner." : ".omp_initializer.", &CGM.getModule());
CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, FnInfo);
+ Fn->removeFnAttr(llvm::Attribute::NoInline);
Fn->addFnAttr(llvm::Attribute::AlwaysInline);
CodeGenFunction CGF(CGM);
// Map "T omp_in;" variable to "*omp_in_parm" value in all expressions.
@@ -906,18 +908,19 @@ Address CGOpenMPRuntime::getOrCreateDefaultLocation(unsigned Flags) {
DefaultOpenMPPSource =
llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy);
}
- auto DefaultOpenMPLocation = new llvm::GlobalVariable(
- CGM.getModule(), IdentTy, /*isConstant*/ true,
- llvm::GlobalValue::PrivateLinkage, /*Initializer*/ nullptr);
+
+ 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);
- DefaultOpenMPLocation->setAlignment(Align.getQuantity());
-
- llvm::Constant *Zero = llvm::ConstantInt::get(CGM.Int32Ty, 0, true);
- llvm::Constant *Values[] = {Zero,
- llvm::ConstantInt::get(CGM.Int32Ty, Flags),
- Zero, Zero, DefaultOpenMPPSource};
- llvm::Constant *Init = llvm::ConstantStruct::get(IdentTy, Values);
- DefaultOpenMPLocation->setInitializer(Init);
+
OpenMPDefaultLocMap[Flags] = Entry = DefaultOpenMPLocation;
}
return Address(Entry, Align);
@@ -2767,7 +2770,6 @@ createOffloadingBinaryDescriptorFunction(CodeGenModule &CGM, StringRef Name,
Args.push_back(&DummyPtr);
CodeGenFunction CGF(CGM);
- GlobalDecl();
auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
auto FTy = CGM.getTypes().GetFunctionType(FI);
auto *Fn =
@@ -2810,9 +2812,10 @@ CGOpenMPRuntime::createOffloadingBinaryDescriptorRegistration() {
".omp_offloading.entries_end");
// Create all device images
- llvm::SmallVector<llvm::Constant *, 4> DeviceImagesEntires;
auto *DeviceImageTy = cast<llvm::StructType>(
CGM.getTypes().ConvertTypeForMem(getTgtDeviceImageQTy()));
+ ConstantInitBuilder DeviceImagesBuilder(CGM);
+ auto DeviceImagesEntries = DeviceImagesBuilder.beginArray(DeviceImageTy);
for (unsigned i = 0; i < Devices.size(); ++i) {
StringRef T = Devices[i].getTriple();
@@ -2824,22 +2827,19 @@ CGOpenMPRuntime::createOffloadingBinaryDescriptorRegistration() {
M, CGM.Int8Ty, /*isConstant=*/true, llvm::GlobalValue::ExternalLinkage,
/*Initializer=*/nullptr, Twine(".omp_offloading.img_end.") + Twine(T));
- llvm::Constant *Dev =
- llvm::ConstantStruct::get(DeviceImageTy, ImgBegin, ImgEnd,
- HostEntriesBegin, HostEntriesEnd, nullptr);
- DeviceImagesEntires.push_back(Dev);
+ auto Dev = DeviceImagesEntries.beginStruct(DeviceImageTy);
+ Dev.add(ImgBegin);
+ Dev.add(ImgEnd);
+ Dev.add(HostEntriesBegin);
+ Dev.add(HostEntriesEnd);
+ Dev.finishAndAddTo(DeviceImagesEntries);
}
// Create device images global array.
- llvm::ArrayType *DeviceImagesInitTy =
- llvm::ArrayType::get(DeviceImageTy, DeviceImagesEntires.size());
- llvm::Constant *DeviceImagesInit =
- llvm::ConstantArray::get(DeviceImagesInitTy, DeviceImagesEntires);
-
- llvm::GlobalVariable *DeviceImages = new llvm::GlobalVariable(
- M, DeviceImagesInitTy, /*isConstant=*/true,
- llvm::GlobalValue::InternalLinkage, DeviceImagesInit,
- ".omp_offloading.device_images");
+ llvm::GlobalVariable *DeviceImages =
+ DeviceImagesEntries.finishAndCreateGlobal(".omp_offloading.device_images",
+ 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
@@ -2849,16 +2849,18 @@ CGOpenMPRuntime::createOffloadingBinaryDescriptorRegistration() {
// Create the target region descriptor.
auto *BinaryDescriptorTy = cast<llvm::StructType>(
CGM.getTypes().ConvertTypeForMem(getTgtBinaryDescriptorQTy()));
- llvm::Constant *TargetRegionsDescriptorInit = llvm::ConstantStruct::get(
- BinaryDescriptorTy, llvm::ConstantInt::get(CGM.Int32Ty, Devices.size()),
- llvm::ConstantExpr::getGetElementPtr(DeviceImagesInitTy, DeviceImages,
- Index),
- HostEntriesBegin, HostEntriesEnd, nullptr);
-
- auto *Desc = new llvm::GlobalVariable(
- M, BinaryDescriptorTy, /*isConstant=*/true,
- llvm::GlobalValue::InternalLinkage, TargetRegionsDescriptorInit,
- ".omp_offloading.descriptor");
+ 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);
// Emit code to register or unregister the descriptor at execution
// startup or closing, respectively.
@@ -2906,25 +2908,30 @@ void CGOpenMPRuntime::createOffloadEntry(llvm::Constant *ID,
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.
- llvm::Constant *EntryInit = llvm::ConstantStruct::get(
- TgtOffloadEntryType, AddrPtr, StrPtr,
- llvm::ConstantInt::get(CGM.SizeTy, Size), nullptr);
- llvm::GlobalVariable *Entry = new llvm::GlobalVariable(
- M, TgtOffloadEntryType, true, llvm::GlobalValue::ExternalLinkage,
- EntryInit, ".omp_offloading.entry");
+ ConstantInitBuilder EntryBuilder(CGM);
+ auto EntryInit = EntryBuilder.beginStruct(TgtOffloadEntryType);
+ EntryInit.add(AddrPtr);
+ EntryInit.add(StrPtr);
+ EntryInit.addInt(CGM.SizeTy, Size);
+ llvm::GlobalVariable *Entry =
+ EntryInit.finishAndCreateGlobal(".omp_offloading.entry",
+ Align,
+ /*constant*/ true,
+ llvm::GlobalValue::ExternalLinkage);
// The entry has to be created in the section the linker expects it to be.
Entry->setSection(".omp_offloading.entries");
- // We can't have any padding between symbols, so we need to have 1-byte
- // alignment.
- Entry->setAlignment(1);
}
void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() {
// Emit the offloading entries and metadata so that the device codegen side
- // can
- // easily figure out what to emit. The produced metadata looks like this:
+ // can easily figure out what to emit. The produced metadata looks like
+ // this:
//
// !omp_offload.info = !{!1, ...}
//
@@ -3012,7 +3019,8 @@ void CGOpenMPRuntime::loadOffloadInfoMetadata() {
return;
llvm::LLVMContext C;
- auto ME = llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C);
+ auto ME = expectedToErrorOrAndEmitErrors(
+ C, llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C));
if (ME.getError())
return;
@@ -3465,6 +3473,7 @@ emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc,
".omp_task_privates_map.", &CGM.getModule());
CGM.SetInternalFunctionAttributes(/*D=*/nullptr, TaskPrivatesMap,
TaskPrivatesMapFnInfo);
+ TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline);
TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
CodeGenFunction CGF(CGM);
CGF.disableDebugInfo();
@@ -4436,9 +4445,8 @@ void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
auto *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE);
auto *ThreadId = getThreadID(CGF, Loc);
auto *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy);
- auto *RL =
- CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(ReductionList.getPointer(),
- CGF.VoidPtrTy);
+ auto *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
+ ReductionList.getPointer(), CGF.VoidPtrTy);
llvm::Value *Args[] = {
IdentTLoc, // ident_t *<loc>
ThreadId, // i32 <gtid>
@@ -4981,6 +4989,9 @@ public:
/// map/privatization results in multiple arguments passed to the runtime
/// library.
OMP_MAP_FIRST_REF = 0x20,
+ /// \brief Signal that the runtime library has to return the device pointer
+ /// in the current position for the data being mapped.
+ OMP_MAP_RETURN_PTR = 0x40,
/// \brief This flag signals that the reference being passed is a pointer to
/// private data.
OMP_MAP_PRIVATE_PTR = 0x80,
@@ -4988,12 +4999,30 @@ public:
OMP_MAP_PRIVATE_VAL = 0x100,
};
+ /// Class that associates information with a base pointer to be passed to the
+ /// runtime library.
+ class BasePointerInfo {
+ /// The base pointer.
+ llvm::Value *Ptr = nullptr;
+ /// The base declaration that refers to this device pointer, or null if
+ /// there is none.
+ const ValueDecl *DevPtrDecl = nullptr;
+
+ public:
+ BasePointerInfo(llvm::Value *Ptr, const ValueDecl *DevPtrDecl = nullptr)
+ : Ptr(Ptr), DevPtrDecl(DevPtrDecl) {}
+ llvm::Value *operator*() const { return Ptr; }
+ const ValueDecl *getDevicePtrDecl() const { return DevPtrDecl; }
+ void setDevicePtrDecl(const ValueDecl *D) { DevPtrDecl = D; }
+ };
+
+ typedef SmallVector<BasePointerInfo, 16> MapBaseValuesArrayTy;
typedef SmallVector<llvm::Value *, 16> MapValuesArrayTy;
typedef SmallVector<unsigned, 16> MapFlagsArrayTy;
private:
/// \brief Directive from where the map clauses were extracted.
- const OMPExecutableDirective &Directive;
+ const OMPExecutableDirective &CurDir;
/// \brief Function the directive is being generated for.
CodeGenFunction &CGF;
@@ -5001,6 +5030,13 @@ private:
/// \brief Set of all first private variables in the current directive.
llvm::SmallPtrSet<const VarDecl *, 8> FirstPrivateDecls;
+ /// Map between device pointer declarations and their expression components.
+ /// The key value for declarations in 'this' is null.
+ llvm::DenseMap<
+ const ValueDecl *,
+ SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
+ DevPointersMap;
+
llvm::Value *getExprTypeSize(const Expr *E) const {
auto ExprTy = E->getType().getCanonicalType();
@@ -5129,7 +5165,7 @@ private:
void generateInfoForComponentList(
OpenMPMapClauseKind MapType, OpenMPMapClauseKind MapTypeModifier,
OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
- MapValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
+ MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types,
bool IsFirstComponentList) const {
@@ -5271,15 +5307,13 @@ private:
// 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
- // reference.
- if (I->getAssociatedDeclaration()->getType()->isAnyPointerType() &&
- std::next(I) != CE) {
- auto PtrAddr = CGF.MakeNaturalAlignAddrLValue(
- BP, I->getAssociatedDeclaration()->getType());
+ // reference. References are ignored for mapping purposes.
+ QualType Ty =
+ I->getAssociatedDeclaration()->getType().getNonReferenceType();
+ if (Ty->isAnyPointerType() && std::next(I) != CE) {
+ auto PtrAddr = CGF.MakeNaturalAlignAddrLValue(BP, Ty);
BP = CGF.EmitLoadOfPointerLValue(PtrAddr.getAddress(),
- I->getAssociatedDeclaration()
- ->getType()
- ->getAs<PointerType>())
+ Ty->castAs<PointerType>())
.getPointer();
// We do not need to generate individual map information for the
@@ -5322,14 +5356,34 @@ private:
isa<OMPArraySectionExpr>(Next->getAssociatedExpression())) &&
"Unexpected expression");
- // Save the base we are currently using.
- BasePointers.push_back(BP);
-
auto *LB = CGF.EmitLValue(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(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;
+ }
+
+ BasePointers.push_back(BP);
Pointers.push_back(LB);
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
@@ -5373,17 +5427,23 @@ private:
public:
MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF)
- : Directive(Dir), CGF(CGF) {
+ : CurDir(Dir), CGF(CGF) {
// Extract firstprivate clause information.
for (const auto *C : Dir.getClausesOfKind<OMPFirstprivateClause>())
for (const auto *D : C->varlists())
FirstPrivateDecls.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
- /// types for the extracted mappable expressions.
- void generateAllInfo(MapValuesArrayTy &BasePointers,
+ /// 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();
@@ -5392,9 +5452,32 @@ public:
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;
OpenMPMapClauseKind MapTypeModifier;
+ ReturnPointerKind ReturnDevicePointer;
+
+ MapInfo()
+ : MapType(OMPC_MAP_unknown), MapTypeModifier(OMPC_MAP_unknown),
+ ReturnDevicePointer(RPK_None) {}
+ MapInfo(
+ OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
+ OpenMPMapClauseKind MapType, OpenMPMapClauseKind MapTypeModifier,
+ ReturnPointerKind ReturnDevicePointer)
+ : Components(Components), MapType(MapType),
+ MapTypeModifier(MapTypeModifier),
+ ReturnDevicePointer(ReturnDevicePointer) {}
};
// We have to process the component lists that relate with the same
@@ -5404,24 +5487,77 @@ public:
// Helper function to fill the information map for the different supported
// clauses.
- auto &&InfoGen =
- [&Info](const ValueDecl *D,
- OMPClauseMappableExprCommon::MappableExprComponentListRef L,
- OpenMPMapClauseKind MapType, OpenMPMapClauseKind MapModifier) {
- const ValueDecl *VD =
- D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr;
- Info[VD].push_back({L, MapType, MapModifier});
- };
+ auto &&InfoGen = [&Info](
+ const ValueDecl *D,
+ OMPClauseMappableExprCommon::MappableExprComponentListRef L,
+ OpenMPMapClauseKind MapType, OpenMPMapClauseKind MapModifier,
+ MapInfo::ReturnPointerKind ReturnDevicePointer) {
+ const ValueDecl *VD =
+ D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr;
+ Info[VD].push_back({L, MapType, MapModifier, ReturnDevicePointer});
+ };
- for (auto *C : Directive.getClausesOfKind<OMPMapClause>())
+ // FIXME: MSVC 2013 seems to require this-> to find member CurDir.
+ for (auto *C : this->CurDir.getClausesOfKind<OMPMapClause>())
for (auto L : C->component_lists())
- InfoGen(L.first, L.second, C->getMapType(), C->getMapTypeModifier());
- for (auto *C : Directive.getClausesOfKind<OMPToClause>())
+ InfoGen(L.first, L.second, C->getMapType(), C->getMapTypeModifier(),
+ MapInfo::RPK_None);
+ for (auto *C : this->CurDir.getClausesOfKind<OMPToClause>())
for (auto L : C->component_lists())
- InfoGen(L.first, L.second, OMPC_MAP_to, OMPC_MAP_unknown);
- for (auto *C : Directive.getClausesOfKind<OMPFromClause>())
+ InfoGen(L.first, L.second, OMPC_MAP_to, OMPC_MAP_unknown,
+ MapInfo::RPK_None);
+ for (auto *C : this->CurDir.getClausesOfKind<OMPFromClause>())
for (auto L : C->component_lists())
- InfoGen(L.first, L.second, OMPC_MAP_from, OMPC_MAP_unknown);
+ InfoGen(L.first, L.second, OMPC_MAP_from, OMPC_MAP_unknown,
+ MapInfo::RPK_None);
+
+ // 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.
+ // FIXME: MSVC 2013 seems to require this-> to find member CurDir.
+ for (auto *C : this->CurDir.getClausesOfKind<OMPUseDevicePtrClause>())
+ for (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();
+ // 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.
+ auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD);
+
+ // We potentially have map information for this declaration already.
+ // Look for the first set of components that refer to it.
+ if (It != Info.end()) {
+ auto CI = std::find_if(
+ It->second.begin(), It->second.end(), [VD](const MapInfo &MI) {
+ return MI.Components.back().getAssociatedDeclaration() == VD;
+ });
+ // 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;
+ continue;
+ }
+ }
+
+ // We didn't find any match in our map information - generate a zero
+ // size array section.
+ // 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_PTR | OMP_MAP_FIRST_REF);
+ }
for (auto &M : Info) {
// We need to know when we generate information for the first component
@@ -5430,9 +5566,36 @@ public:
for (MapInfo &L : M.second) {
assert(!L.Components.empty() &&
"Not expecting declaration with no component lists.");
- generateInfoForComponentList(L.MapType, L.MapTypeModifier, L.Components,
- BasePointers, Pointers, Sizes, Types,
- IsFirstComponentList);
+
+ // Remember the current base pointer index.
+ unsigned CurrentBasePointersIdx = BasePointers.size();
+ // FIXME: MSVC 2013 seems to require this-> to find the member method.
+ this->generateInfoForComponentList(L.MapType, L.MapTypeModifier,
+ L.Components, BasePointers, Pointers,
+ Sizes, Types, IsFirstComponentList);
+
+ // 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 &&
+ "Unexpected number of mapped base pointers.");
+
+ auto *RelevantVD = L.Components.back().getAssociatedDeclaration();
+ assert(RelevantVD &&
+ "No relevant declaration related with device pointer??");
+
+ BasePointers[CurrentBasePointersIdx].setDevicePtrDecl(RelevantVD);
+ Types[CurrentBasePointersIdx] |= OMP_MAP_RETURN_PTR;
+ }
IsFirstComponentList = false;
}
}
@@ -5441,7 +5604,8 @@ public:
/// \brief Generate the base pointers, section pointers, sizes and map types
/// associated to a given capture.
void generateInfoForCapture(const CapturedStmt::Capture *Cap,
- MapValuesArrayTy &BasePointers,
+ llvm::Value *Arg,
+ MapBaseValuesArrayTy &BasePointers,
MapValuesArrayTy &Pointers,
MapValuesArrayTy &Sizes,
MapFlagsArrayTy &Types) const {
@@ -5453,15 +5617,40 @@ public:
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());
- // 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;
- for (auto *C : Directive.getClausesOfKind<OMPMapClause>())
+ // 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);
+ IsFirstComponentList = false;
+ }
+ return;
+ }
+ } else if (DevPointersMap.count(VD)) {
+ BasePointers.push_back({Arg, VD});
+ Pointers.push_back(Arg);
+ Sizes.push_back(CGF.getTypeSize(CGF.getContext().VoidPtrTy));
+ Types.push_back(OMP_MAP_PRIVATE_VAL | OMP_MAP_FIRST_REF);
+ return;
+ }
+
+ // 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)) {
assert(L.first == VD &&
"We got information for the wrong declaration??");
@@ -5478,12 +5667,12 @@ public:
/// \brief 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,
- MappableExprsHandler::MapValuesArrayTy &CurBasePointers,
- MappableExprsHandler::MapValuesArrayTy &CurPointers,
- MappableExprsHandler::MapValuesArrayTy &CurSizes,
- MappableExprsHandler::MapFlagsArrayTy &CurMapTypes) {
+ void generateDefaultMapInfo(const CapturedStmt::Capture &CI,
+ const FieldDecl &RI, llvm::Value *CV,
+ MapBaseValuesArrayTy &CurBasePointers,
+ MapValuesArrayTy &CurPointers,
+ MapValuesArrayTy &CurSizes,
+ MapFlagsArrayTy &CurMapTypes) {
// Do the default mapping.
if (CI.capturesThis()) {
@@ -5492,15 +5681,14 @@ public:
const PointerType *PtrTy = cast<PointerType>(RI.getType().getTypePtr());
CurSizes.push_back(CGF.getTypeSize(PtrTy->getPointeeType()));
// Default map type.
- CurMapTypes.push_back(MappableExprsHandler::OMP_MAP_TO |
- MappableExprsHandler::OMP_MAP_FROM);
+ CurMapTypes.push_back(OMP_MAP_TO | OMP_MAP_FROM);
} else if (CI.capturesVariableByCopy()) {
CurBasePointers.push_back(CV);
CurPointers.push_back(CV);
if (!RI.getType()->isAnyPointerType()) {
// We have to signal to the runtime captures passed by value that are
// not pointers.
- CurMapTypes.push_back(MappableExprsHandler::OMP_MAP_PRIVATE_VAL);
+ CurMapTypes.push_back(OMP_MAP_PRIVATE_VAL);
CurSizes.push_back(CGF.getTypeSize(RI.getType()));
} else {
// Pointers are implicitly mapped with a zero size and no flags
@@ -5521,9 +5709,8 @@ public:
// default the value doesn't have to be retrieved. For an aggregate
// type, the default is 'tofrom'.
CurMapTypes.push_back(ElementType->isAggregateType()
- ? (MappableExprsHandler::OMP_MAP_TO |
- MappableExprsHandler::OMP_MAP_FROM)
- : MappableExprsHandler::OMP_MAP_TO);
+ ? (OMP_MAP_TO | OMP_MAP_FROM)
+ : OMP_MAP_TO);
// If we have a capture by reference we may need to add the private
// pointer flag if the base declaration shows in some first-private
@@ -5533,7 +5720,7 @@ public:
}
// Every default map produces a single argument, so, it is always the
// first one.
- CurMapTypes.back() |= MappableExprsHandler::OMP_MAP_FIRST_REF;
+ CurMapTypes.back() |= OMP_MAP_FIRST_REF;
}
};
@@ -5548,19 +5735,20 @@ enum OpenMPOffloadingReservedDeviceIDs {
/// offloading runtime library. If there is no map or capture information,
/// return nullptr by reference.
static void
-emitOffloadingArrays(CodeGenFunction &CGF, llvm::Value *&BasePointersArray,
- llvm::Value *&PointersArray, llvm::Value *&SizesArray,
- llvm::Value *&MapTypesArray,
- MappableExprsHandler::MapValuesArrayTy &BasePointers,
+emitOffloadingArrays(CodeGenFunction &CGF,
+ MappableExprsHandler::MapBaseValuesArrayTy &BasePointers,
MappableExprsHandler::MapValuesArrayTy &Pointers,
MappableExprsHandler::MapValuesArrayTy &Sizes,
- MappableExprsHandler::MapFlagsArrayTy &MapTypes) {
+ MappableExprsHandler::MapFlagsArrayTy &MapTypes,
+ CGOpenMPRuntime::TargetDataInfo &Info) {
auto &CGM = CGF.CGM;
auto &Ctx = CGF.getContext();
- BasePointersArray = PointersArray = SizesArray = MapTypesArray = nullptr;
+ // Reset the array information.
+ Info.clearArrayInfo();
+ Info.NumberOfPtrs = BasePointers.size();
- if (unsigned PointerNumVal = BasePointers.size()) {
+ if (Info.NumberOfPtrs) {
// 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;
@@ -5570,14 +5758,14 @@ emitOffloadingArrays(CodeGenFunction &CGF, llvm::Value *&BasePointersArray,
break;
}
- llvm::APInt PointerNumAP(32, PointerNumVal, /*isSigned=*/true);
+ llvm::APInt PointerNumAP(32, Info.NumberOfPtrs, /*isSigned=*/true);
QualType PointerArrayType =
Ctx.getConstantArrayType(Ctx.VoidPtrTy, PointerNumAP, ArrayType::Normal,
/*IndexTypeQuals=*/0);
- BasePointersArray =
+ Info.BasePointersArray =
CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer();
- PointersArray =
+ Info.PointersArray =
CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer();
// If we don't have any VLA types or other types that require runtime
@@ -5587,7 +5775,7 @@ emitOffloadingArrays(CodeGenFunction &CGF, llvm::Value *&BasePointersArray,
QualType SizeArrayType = Ctx.getConstantArrayType(
Ctx.getSizeType(), PointerNumAP, ArrayType::Normal,
/*IndexTypeQuals=*/0);
- SizesArray =
+ Info.SizesArray =
CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer();
} else {
// We expect all the sizes to be constant, so we collect them to create
@@ -5603,7 +5791,7 @@ emitOffloadingArrays(CodeGenFunction &CGF, llvm::Value *&BasePointersArray,
/*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
SizesArrayInit, ".offload_sizes");
SizesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
- SizesArray = SizesArrayGbl;
+ Info.SizesArray = SizesArrayGbl;
}
// The map types are always constant so we don't need to generate code to
@@ -5615,10 +5803,10 @@ emitOffloadingArrays(CodeGenFunction &CGF, llvm::Value *&BasePointersArray,
/*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
MapTypesArrayInit, ".offload_maptypes");
MapTypesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
- MapTypesArray = MapTypesArrayGbl;
+ Info.MapTypesArray = MapTypesArrayGbl;
- for (unsigned i = 0; i < PointerNumVal; ++i) {
- llvm::Value *BPVal = BasePointers[i];
+ for (unsigned i = 0; i < Info.NumberOfPtrs; ++i) {
+ llvm::Value *BPVal = *BasePointers[i];
if (BPVal->getType()->isPointerTy())
BPVal = CGF.Builder.CreateBitCast(BPVal, CGM.VoidPtrTy);
else {
@@ -5627,11 +5815,15 @@ emitOffloadingArrays(CodeGenFunction &CGF, llvm::Value *&BasePointersArray,
BPVal = CGF.Builder.CreateIntToPtr(BPVal, CGM.VoidPtrTy);
}
llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32(
- llvm::ArrayType::get(CGM.VoidPtrTy, PointerNumVal), BasePointersArray,
- 0, i);
+ llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
+ Info.BasePointersArray, 0, i);
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));
+
llvm::Value *PVal = Pointers[i];
if (PVal->getType()->isPointerTy())
PVal = CGF.Builder.CreateBitCast(PVal, CGM.VoidPtrTy);
@@ -5641,14 +5833,15 @@ emitOffloadingArrays(CodeGenFunction &CGF, llvm::Value *&BasePointersArray,
PVal = CGF.Builder.CreateIntToPtr(PVal, CGM.VoidPtrTy);
}
llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32(
- llvm::ArrayType::get(CGM.VoidPtrTy, PointerNumVal), PointersArray, 0,
- i);
+ llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
+ Info.PointersArray, 0, i);
Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
CGF.Builder.CreateStore(PVal, PAddr);
if (hasRuntimeEvaluationCaptureSize) {
llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32(
- llvm::ArrayType::get(CGM.SizeTy, PointerNumVal), SizesArray,
+ llvm::ArrayType::get(CGM.SizeTy, Info.NumberOfPtrs),
+ Info.SizesArray,
/*Idx0=*/0,
/*Idx1=*/i);
Address SAddr(S, Ctx.getTypeAlignInChars(Ctx.getSizeType()));
@@ -5664,23 +5857,24 @@ emitOffloadingArrays(CodeGenFunction &CGF, llvm::Value *&BasePointersArray,
static void emitOffloadingArraysArgument(
CodeGenFunction &CGF, llvm::Value *&BasePointersArrayArg,
llvm::Value *&PointersArrayArg, llvm::Value *&SizesArrayArg,
- llvm::Value *&MapTypesArrayArg, llvm::Value *BasePointersArray,
- llvm::Value *PointersArray, llvm::Value *SizesArray,
- llvm::Value *MapTypesArray, unsigned NumElems) {
+ llvm::Value *&MapTypesArrayArg, CGOpenMPRuntime::TargetDataInfo &Info) {
auto &CGM = CGF.CGM;
- if (NumElems) {
+ if (Info.NumberOfPtrs) {
BasePointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
- llvm::ArrayType::get(CGM.VoidPtrTy, NumElems), BasePointersArray,
+ llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
+ Info.BasePointersArray,
/*Idx0=*/0, /*Idx1=*/0);
PointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
- llvm::ArrayType::get(CGM.VoidPtrTy, NumElems), PointersArray,
+ llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
+ Info.PointersArray,
/*Idx0=*/0,
/*Idx1=*/0);
SizesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
- llvm::ArrayType::get(CGM.SizeTy, NumElems), SizesArray,
+ llvm::ArrayType::get(CGM.SizeTy, Info.NumberOfPtrs), Info.SizesArray,
/*Idx0=*/0, /*Idx1=*/0);
MapTypesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
- llvm::ArrayType::get(CGM.Int32Ty, NumElems), MapTypesArray,
+ llvm::ArrayType::get(CGM.Int32Ty, Info.NumberOfPtrs),
+ Info.MapTypesArray,
/*Idx0=*/0,
/*Idx1=*/0);
} else {
@@ -5707,12 +5901,12 @@ void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF,
// Fill up the arrays with all the captured variables.
MappableExprsHandler::MapValuesArrayTy KernelArgs;
- MappableExprsHandler::MapValuesArrayTy BasePointers;
+ MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
MappableExprsHandler::MapValuesArrayTy Pointers;
MappableExprsHandler::MapValuesArrayTy Sizes;
MappableExprsHandler::MapFlagsArrayTy MapTypes;
- MappableExprsHandler::MapValuesArrayTy CurBasePointers;
+ MappableExprsHandler::MapBaseValuesArrayTy CurBasePointers;
MappableExprsHandler::MapValuesArrayTy CurPointers;
MappableExprsHandler::MapValuesArrayTy CurSizes;
MappableExprsHandler::MapFlagsArrayTy CurMapTypes;
@@ -5746,7 +5940,7 @@ void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF,
} else {
// If we have any information in the map clause, we use it, otherwise we
// just do a default mapping.
- MEHandler.generateInfoForCapture(CI, CurBasePointers, CurPointers,
+ MEHandler.generateInfoForCapture(CI, *CV, CurBasePointers, CurPointers,
CurSizes, CurMapTypes);
if (CurBasePointers.empty())
MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurBasePointers,
@@ -5761,7 +5955,7 @@ void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF,
// The kernel args are always the first elements of the base pointers
// associated with a capture.
- KernelArgs.push_back(CurBasePointers.front());
+ 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());
@@ -5784,17 +5978,11 @@ void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF,
&D](CodeGenFunction &CGF, PrePostActionTy &) {
auto &RT = CGF.CGM.getOpenMPRuntime();
// Emit the offloading arrays.
- llvm::Value *BasePointersArray;
- llvm::Value *PointersArray;
- llvm::Value *SizesArray;
- llvm::Value *MapTypesArray;
- emitOffloadingArrays(CGF, BasePointersArray, PointersArray, SizesArray,
- MapTypesArray, BasePointers, Pointers, Sizes,
- MapTypes);
- emitOffloadingArraysArgument(CGF, BasePointersArray, PointersArray,
- SizesArray, MapTypesArray, BasePointersArray,
- PointersArray, SizesArray, MapTypesArray,
- BasePointers.size());
+ TargetDataInfo Info;
+ emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
+ emitOffloadingArraysArgument(CGF, Info.BasePointersArray,
+ Info.PointersArray, Info.SizesArray,
+ Info.MapTypesArray, Info);
// 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
@@ -5835,15 +6023,19 @@ void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF,
assert(ThreadLimit && "Thread limit expression should be available along "
"with number of teams.");
llvm::Value *OffloadingArgs[] = {
- DeviceID, OutlinedFnID, PointerNum,
- BasePointersArray, PointersArray, SizesArray,
- MapTypesArray, NumTeams, ThreadLimit};
+ DeviceID, OutlinedFnID,
+ PointerNum, Info.BasePointersArray,
+ Info.PointersArray, Info.SizesArray,
+ Info.MapTypesArray, NumTeams,
+ ThreadLimit};
Return = CGF.EmitRuntimeCall(
RT.createRuntimeFunction(OMPRTL__tgt_target_teams), OffloadingArgs);
} else {
llvm::Value *OffloadingArgs[] = {
- DeviceID, OutlinedFnID, PointerNum, BasePointersArray,
- PointersArray, SizesArray, MapTypesArray};
+ DeviceID, OutlinedFnID,
+ PointerNum, Info.BasePointersArray,
+ Info.PointersArray, Info.SizesArray,
+ Info.MapTypesArray};
Return = CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__tgt_target),
OffloadingArgs);
}
@@ -5951,7 +6143,7 @@ bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) {
// Try to detect target regions in the function.
scanForTargetRegionsFunctions(FD.getBody(), CGM.getMangledName(GD));
- // We should not emit any function othen that the ones created during the
+ // 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;
@@ -6055,29 +6247,23 @@ void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF,
PushNumTeamsArgs);
}
-void CGOpenMPRuntime::emitTargetDataCalls(CodeGenFunction &CGF,
- const OMPExecutableDirective &D,
- const Expr *IfCond,
- const Expr *Device,
- const RegionCodeGenTy &CodeGen) {
-
+void CGOpenMPRuntime::emitTargetDataCalls(
+ CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
+ const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) {
if (!CGF.HaveInsertPoint())
return;
- llvm::Value *BasePointersArray = nullptr;
- llvm::Value *PointersArray = nullptr;
- llvm::Value *SizesArray = nullptr;
- llvm::Value *MapTypesArray = nullptr;
- unsigned NumOfPtrs = 0;
+ // Action used to replace the default codegen action and turn privatization
+ // off.
+ PrePostActionTy NoPrivAction;
// Generate the code for the opening of the data environment. Capture all the
// arguments of the runtime call by reference because they are used in the
// closing of the region.
- auto &&BeginThenGen = [&D, &CGF, &BasePointersArray, &PointersArray,
- &SizesArray, &MapTypesArray, Device,
- &NumOfPtrs](CodeGenFunction &CGF, PrePostActionTy &) {
+ auto &&BeginThenGen = [&D, &CGF, Device, &Info, &CodeGen, &NoPrivAction](
+ CodeGenFunction &CGF, PrePostActionTy &) {
// Fill up the arrays with all the mapped variables.
- MappableExprsHandler::MapValuesArrayTy BasePointers;
+ MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
MappableExprsHandler::MapValuesArrayTy Pointers;
MappableExprsHandler::MapValuesArrayTy Sizes;
MappableExprsHandler::MapFlagsArrayTy MapTypes;
@@ -6085,21 +6271,16 @@ void CGOpenMPRuntime::emitTargetDataCalls(CodeGenFunction &CGF,
// Get map clause information.
MappableExprsHandler MCHandler(D, CGF);
MCHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes);
- NumOfPtrs = BasePointers.size();
// Fill up the arrays and create the arguments.
- emitOffloadingArrays(CGF, BasePointersArray, PointersArray, SizesArray,
- MapTypesArray, BasePointers, Pointers, Sizes,
- MapTypes);
+ emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
llvm::Value *BasePointersArrayArg = nullptr;
llvm::Value *PointersArrayArg = nullptr;
llvm::Value *SizesArrayArg = nullptr;
llvm::Value *MapTypesArrayArg = nullptr;
emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg,
- SizesArrayArg, MapTypesArrayArg,
- BasePointersArray, PointersArray, SizesArray,
- MapTypesArray, NumOfPtrs);
+ SizesArrayArg, MapTypesArrayArg, Info);
// Emit device ID if any.
llvm::Value *DeviceID = nullptr;
@@ -6110,7 +6291,7 @@ void CGOpenMPRuntime::emitTargetDataCalls(CodeGenFunction &CGF,
DeviceID = CGF.Builder.getInt32(OMP_DEVICEID_UNDEF);
// Emit the number of elements in the offloading arrays.
- auto *PointerNum = CGF.Builder.getInt32(NumOfPtrs);
+ auto *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs);
llvm::Value *OffloadingArgs[] = {
DeviceID, PointerNum, BasePointersArrayArg,
@@ -6118,23 +6299,24 @@ void CGOpenMPRuntime::emitTargetDataCalls(CodeGenFunction &CGF,
auto &RT = CGF.CGM.getOpenMPRuntime();
CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__tgt_target_data_begin),
OffloadingArgs);
+
+ // If device pointer privatization is required, emit the body of the region
+ // here. It will have to be duplicated: with and without privatization.
+ if (!Info.CaptureDeviceAddrMap.empty())
+ CodeGen(CGF);
};
// Generate code for the closing of the data region.
- auto &&EndThenGen = [&CGF, &BasePointersArray, &PointersArray, &SizesArray,
- &MapTypesArray, Device,
- &NumOfPtrs](CodeGenFunction &CGF, PrePostActionTy &) {
- assert(BasePointersArray && PointersArray && SizesArray && MapTypesArray &&
- NumOfPtrs && "Invalid data environment closing arguments.");
+ auto &&EndThenGen = [&CGF, Device, &Info](CodeGenFunction &CGF,
+ PrePostActionTy &) {
+ assert(Info.isValid() && "Invalid data environment closing arguments.");
llvm::Value *BasePointersArrayArg = nullptr;
llvm::Value *PointersArrayArg = nullptr;
llvm::Value *SizesArrayArg = nullptr;
llvm::Value *MapTypesArrayArg = nullptr;
emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg,
- SizesArrayArg, MapTypesArrayArg,
- BasePointersArray, PointersArray, SizesArray,
- MapTypesArray, NumOfPtrs);
+ SizesArrayArg, MapTypesArrayArg, Info);
// Emit device ID if any.
llvm::Value *DeviceID = nullptr;
@@ -6145,7 +6327,7 @@ void CGOpenMPRuntime::emitTargetDataCalls(CodeGenFunction &CGF,
DeviceID = CGF.Builder.getInt32(OMP_DEVICEID_UNDEF);
// Emit the number of elements in the offloading arrays.
- auto *PointerNum = CGF.Builder.getInt32(NumOfPtrs);
+ auto *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs);
llvm::Value *OffloadingArgs[] = {
DeviceID, PointerNum, BasePointersArrayArg,
@@ -6155,24 +6337,40 @@ void CGOpenMPRuntime::emitTargetDataCalls(CodeGenFunction &CGF,
OffloadingArgs);
};
- // In the event we get an if clause, we don't have to take any action on the
- // else side.
- auto &&ElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {};
+ // If we need device pointer privatization, we need to emit the body of the
+ // region with no privatization in the 'else' branch of the conditional.
+ // Otherwise, we don't have to do anything.
+ auto &&BeginElseGen = [&Info, &CodeGen, &NoPrivAction](CodeGenFunction &CGF,
+ PrePostActionTy &) {
+ if (!Info.CaptureDeviceAddrMap.empty()) {
+ CodeGen.setAction(NoPrivAction);
+ CodeGen(CGF);
+ }
+ };
+
+ // We don't have to do anything to close the region if the if clause evaluates
+ // to false.
+ auto &&EndElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {};
if (IfCond) {
- emitOMPIfClause(CGF, IfCond, BeginThenGen, ElseGen);
+ emitOMPIfClause(CGF, IfCond, BeginThenGen, BeginElseGen);
} else {
- RegionCodeGenTy BeginThenRCG(BeginThenGen);
- BeginThenRCG(CGF);
+ RegionCodeGenTy RCG(BeginThenGen);
+ RCG(CGF);
}
- CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_target_data, CodeGen);
+ // If we don't require privatization of device pointers, we emit the body in
+ // between the runtime calls. This avoids duplicating the body code.
+ if (Info.CaptureDeviceAddrMap.empty()) {
+ CodeGen.setAction(NoPrivAction);
+ CodeGen(CGF);
+ }
if (IfCond) {
- emitOMPIfClause(CGF, IfCond, EndThenGen, ElseGen);
+ emitOMPIfClause(CGF, IfCond, EndThenGen, EndElseGen);
} else {
- RegionCodeGenTy EndThenRCG(EndThenGen);
- EndThenRCG(CGF);
+ RegionCodeGenTy RCG(EndThenGen);
+ RCG(CGF);
}
}
@@ -6190,7 +6388,7 @@ void CGOpenMPRuntime::emitTargetDataStandAloneCall(
// Generate the code for the opening of the data environment.
auto &&ThenGen = [&D, &CGF, Device](CodeGenFunction &CGF, PrePostActionTy &) {
// Fill up the arrays with all the mapped variables.
- MappableExprsHandler::MapValuesArrayTy BasePointers;
+ MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
MappableExprsHandler::MapValuesArrayTy Pointers;
MappableExprsHandler::MapValuesArrayTy Sizes;
MappableExprsHandler::MapFlagsArrayTy MapTypes;
@@ -6199,19 +6397,12 @@ void CGOpenMPRuntime::emitTargetDataStandAloneCall(
MappableExprsHandler MEHandler(D, CGF);
MEHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes);
- llvm::Value *BasePointersArrayArg = nullptr;
- llvm::Value *PointersArrayArg = nullptr;
- llvm::Value *SizesArrayArg = nullptr;
- llvm::Value *MapTypesArrayArg = nullptr;
-
// Fill up the arrays and create the arguments.
- emitOffloadingArrays(CGF, BasePointersArrayArg, PointersArrayArg,
- SizesArrayArg, MapTypesArrayArg, BasePointers,
- Pointers, Sizes, MapTypes);
- emitOffloadingArraysArgument(
- CGF, BasePointersArrayArg, PointersArrayArg, SizesArrayArg,
- MapTypesArrayArg, BasePointersArrayArg, PointersArrayArg, SizesArrayArg,
- MapTypesArrayArg, BasePointers.size());
+ TargetDataInfo Info;
+ emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
+ emitOffloadingArraysArgument(CGF, Info.BasePointersArray,
+ Info.PointersArray, Info.SizesArray,
+ Info.MapTypesArray, Info);
// Emit device ID if any.
llvm::Value *DeviceID = nullptr;
@@ -6225,8 +6416,8 @@ void CGOpenMPRuntime::emitTargetDataStandAloneCall(
auto *PointerNum = CGF.Builder.getInt32(BasePointers.size());
llvm::Value *OffloadingArgs[] = {
- DeviceID, PointerNum, BasePointersArrayArg,
- PointersArrayArg, SizesArrayArg, MapTypesArrayArg};
+ DeviceID, PointerNum, Info.BasePointersArray,
+ Info.PointersArray, Info.SizesArray, Info.MapTypesArray};
auto &RT = CGF.CGM.getOpenMPRuntime();
// Select the right runtime function call for each expected standalone
@@ -6326,7 +6517,7 @@ static unsigned evaluateCDTSize(const FunctionDecl *FD,
static void
emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn,
- llvm::APSInt VLENVal,
+ const llvm::APSInt &VLENVal,
ArrayRef<ParamAttrTy> ParamAttrs,
OMPDeclareSimdDeclAttr::BranchStateTy State) {
struct ISADataTy {
diff --git a/lib/CodeGen/CGOpenMPRuntime.h b/lib/CodeGen/CGOpenMPRuntime.h
index 270de8dd505e..9057e5ec4c14 100644
--- a/lib/CodeGen/CGOpenMPRuntime.h
+++ b/lib/CodeGen/CGOpenMPRuntime.h
@@ -997,17 +997,59 @@ public:
virtual void emitNumTeamsClause(CodeGenFunction &CGF, const Expr *NumTeams,
const Expr *ThreadLimit, SourceLocation Loc);
+ /// Struct that keeps all the relevant information that should be kept
+ /// throughout a 'target data' region.
+ class TargetDataInfo {
+ /// Set to true if device pointer information have to be obtained.
+ bool RequiresDevicePointerInfo = false;
+
+ public:
+ /// The array of base pointer passed to the runtime library.
+ llvm::Value *BasePointersArray = nullptr;
+ /// The array of section pointers passed to the runtime library.
+ llvm::Value *PointersArray = nullptr;
+ /// The array of sizes passed to the runtime library.
+ llvm::Value *SizesArray = nullptr;
+ /// The array of map types passed to the runtime library.
+ llvm::Value *MapTypesArray = nullptr;
+ /// The total number of pointers passed to the runtime library.
+ unsigned NumberOfPtrs = 0u;
+ /// Map between the a declaration of a capture and the corresponding base
+ /// pointer address where the runtime returns the device pointers.
+ llvm::DenseMap<const ValueDecl *, Address> CaptureDeviceAddrMap;
+
+ explicit TargetDataInfo() {}
+ explicit TargetDataInfo(bool RequiresDevicePointerInfo)
+ : RequiresDevicePointerInfo(RequiresDevicePointerInfo) {}
+ /// Clear information about the data arrays.
+ void clearArrayInfo() {
+ BasePointersArray = nullptr;
+ PointersArray = nullptr;
+ SizesArray = nullptr;
+ MapTypesArray = nullptr;
+ NumberOfPtrs = 0u;
+ }
+ /// Return true if the current target data information has valid arrays.
+ bool isValid() {
+ return BasePointersArray && PointersArray && SizesArray &&
+ MapTypesArray && NumberOfPtrs;
+ }
+ bool requiresDevicePointerInfo() { return RequiresDevicePointerInfo; }
+ };
+
/// \brief 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 if clause is used.
+ /// \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 CodeGen Function that emits the enclosed region.
+ /// \param Info A record used to store information that needs to be preserved
+ /// until the region is closed.
virtual void emitTargetDataCalls(CodeGenFunction &CGF,
const OMPExecutableDirective &D,
const Expr *IfCond, const Expr *Device,
- const RegionCodeGenTy &CodeGen);
+ const RegionCodeGenTy &CodeGen,
+ TargetDataInfo &Info);
/// \brief Emit the data mapping/movement code associated with the directive
/// \a D that should be of the form 'target [{enter|exit} data | update]'.
diff --git a/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp b/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp
index d64f6df72012..451f9e9221ad 100644
--- a/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp
+++ b/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp
@@ -244,6 +244,9 @@ void CGOpenMPRuntimeNVPTX::emitEntryHeader(CodeGenFunction &CGF,
void CGOpenMPRuntimeNVPTX::emitEntryFooter(CodeGenFunction &CGF,
EntryFunctionState &EST) {
+ if (!EST.ExitBB)
+ EST.ExitBB = CGF.createBasicBlock(".exit");
+
CGBuilderTy &Bld = CGF.Builder;
llvm::BasicBlock *TerminateBB = CGF.createBasicBlock(".termination.notifier");
CGF.EmitBranch(TerminateBB);
@@ -259,6 +262,7 @@ void CGOpenMPRuntimeNVPTX::emitEntryFooter(CodeGenFunction &CGF,
CGF.EmitBranch(EST.ExitBB);
CGF.EmitBlock(EST.ExitBB);
+ EST.ExitBB = nullptr;
}
/// \brief Returns specified OpenMP runtime function for the current OpenMP
@@ -368,6 +372,7 @@ llvm::Value *CGOpenMPRuntimeNVPTX::emitParallelOrTeamsOutlinedFunction(
CGOpenMPRuntime::emitParallelOrTeamsOutlinedFunction(
D, ThreadIDVar, InnermostKind, CodeGen);
OutlinedFun = cast<llvm::Function>(OutlinedFunVal);
+ OutlinedFun->removeFnAttr(llvm::Attribute::NoInline);
OutlinedFun->addFnAttr(llvm::Attribute::AlwaysInline);
} else
llvm_unreachable("parallel directive is not yet supported for nvptx "
diff --git a/lib/CodeGen/CGOpenMPRuntimeNVPTX.h b/lib/CodeGen/CGOpenMPRuntimeNVPTX.h
index a6c64b2f6d67..e18d28cdda9f 100644
--- a/lib/CodeGen/CGOpenMPRuntimeNVPTX.h
+++ b/lib/CodeGen/CGOpenMPRuntimeNVPTX.h
@@ -25,11 +25,8 @@ namespace CodeGen {
class CGOpenMPRuntimeNVPTX : public CGOpenMPRuntime {
public:
- class EntryFunctionState {
- public:
- llvm::BasicBlock *ExitBB;
-
- EntryFunctionState() : ExitBB(nullptr){};
+ struct EntryFunctionState {
+ llvm::BasicBlock *ExitBB = nullptr;
};
class WorkerFunctionState {
diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp
index d815863e929d..f2acb798b881 100644
--- a/lib/CodeGen/CGStmt.cpp
+++ b/lib/CodeGen/CGStmt.cpp
@@ -142,6 +142,8 @@ void CodeGenFunction::EmitStmt(const Stmt *S) {
case Stmt::GCCAsmStmtClass: // Intentional fall-through.
case Stmt::MSAsmStmtClass: EmitAsmStmt(cast<AsmStmt>(*S)); break;
case Stmt::CoroutineBodyStmtClass:
+ EmitCoroutineBody(cast<CoroutineBodyStmt>(*S));
+ break;
case Stmt::CoreturnStmtClass:
CGM.ErrorUnsupported(S, "coroutine");
break;
@@ -295,6 +297,35 @@ void CodeGenFunction::EmitStmt(const Stmt *S) {
EmitOMPTargetParallelForSimdDirective(
cast<OMPTargetParallelForSimdDirective>(*S));
break;
+ case Stmt::OMPTargetSimdDirectiveClass:
+ EmitOMPTargetSimdDirective(cast<OMPTargetSimdDirective>(*S));
+ break;
+ case Stmt::OMPTeamsDistributeDirectiveClass:
+ EmitOMPTeamsDistributeDirective(cast<OMPTeamsDistributeDirective>(*S));
+ break;
+ case Stmt::OMPTeamsDistributeSimdDirectiveClass:
+ EmitOMPTeamsDistributeSimdDirective(
+ cast<OMPTeamsDistributeSimdDirective>(*S));
+ break;
+ case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
+ EmitOMPTeamsDistributeParallelForSimdDirective(
+ cast<OMPTeamsDistributeParallelForSimdDirective>(*S));
+ break;
+ case Stmt::OMPTeamsDistributeParallelForDirectiveClass:
+ EmitOMPTeamsDistributeParallelForDirective(
+ cast<OMPTeamsDistributeParallelForDirective>(*S));
+ break;
+ case Stmt::OMPTargetTeamsDirectiveClass:
+ EmitOMPTargetTeamsDirective(cast<OMPTargetTeamsDirective>(*S));
+ break;
+ case Stmt::OMPTargetTeamsDistributeDirectiveClass:
+ EmitOMPTargetTeamsDistributeDirective(
+ cast<OMPTargetTeamsDistributeDirective>(*S));
+ break;
+ case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
+ EmitOMPTargetTeamsDistributeParallelForDirective(
+ cast<OMPTargetTeamsDistributeParallelForDirective>(*S));
+ break;
}
}
@@ -651,8 +682,10 @@ void CodeGenFunction::EmitWhileStmt(const WhileStmt &S,
JumpDest LoopHeader = getJumpDestInCurrentScope("while.cond");
EmitBlock(LoopHeader.getBlock());
+ const SourceRange &R = S.getSourceRange();
LoopStack.push(LoopHeader.getBlock(), CGM.getContext(), WhileAttrs,
- Builder.getCurrentDebugLocation());
+ SourceLocToDebugLoc(R.getBegin()),
+ SourceLocToDebugLoc(R.getEnd()));
// Create an exit block for when the condition fails, which will
// also become the break target.
@@ -743,8 +776,10 @@ 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,
- Builder.getCurrentDebugLocation());
+ SourceLocToDebugLoc(R.getBegin()),
+ SourceLocToDebugLoc(R.getEnd()));
EmitBlockWithFallThrough(LoopBody, &S);
{
@@ -796,8 +831,6 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S,
LexicalScope ForScope(*this, S.getSourceRange());
- llvm::DebugLoc DL = Builder.getCurrentDebugLocation();
-
// Evaluate the first part before the loop.
if (S.getInit())
EmitStmt(S.getInit());
@@ -809,7 +842,10 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S,
llvm::BasicBlock *CondBlock = Continue.getBlock();
EmitBlock(CondBlock);
- LoopStack.push(CondBlock, CGM.getContext(), ForAttrs, DL);
+ const SourceRange &R = S.getSourceRange();
+ LoopStack.push(CondBlock, CGM.getContext(), ForAttrs,
+ SourceLocToDebugLoc(R.getBegin()),
+ SourceLocToDebugLoc(R.getEnd()));
// If the for loop doesn't have an increment we can just use the
// condition as the continue block. Otherwise we'll need to create
@@ -894,8 +930,6 @@ CodeGenFunction::EmitCXXForRangeStmt(const CXXForRangeStmt &S,
LexicalScope ForScope(*this, S.getSourceRange());
- llvm::DebugLoc DL = Builder.getCurrentDebugLocation();
-
// Evaluate the first pieces before the loop.
EmitStmt(S.getRangeStmt());
EmitStmt(S.getBeginStmt());
@@ -907,7 +941,10 @@ CodeGenFunction::EmitCXXForRangeStmt(const CXXForRangeStmt &S,
llvm::BasicBlock *CondBlock = createBasicBlock("for.cond");
EmitBlock(CondBlock);
- LoopStack.push(CondBlock, CGM.getContext(), ForAttrs, DL);
+ const SourceRange &R = S.getSourceRange();
+ LoopStack.push(CondBlock, CGM.getContext(), ForAttrs,
+ 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.
@@ -2085,15 +2122,6 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
Result->addAttribute(llvm::AttributeSet::FunctionIndex,
llvm::Attribute::NoUnwind);
- if (isa<MSAsmStmt>(&S)) {
- // If the assembly contains any labels, mark the call noduplicate to prevent
- // defining the same ASM label twice (PR23715). This is pretty hacky, but it
- // works.
- if (AsmString.find("__MSASMLABEL_") != std::string::npos)
- Result->addAttribute(llvm::AttributeSet::FunctionIndex,
- llvm::Attribute::NoDuplicate);
- }
-
// Attach readnone and readonly attributes.
if (!HasSideEffect) {
if (ReadNone)
@@ -2189,7 +2217,7 @@ LValue CodeGenFunction::InitCapturedStruct(const CapturedStmt &S) {
auto VAT = CurField->getCapturedVLAType();
EmitStoreThroughLValue(RValue::get(VLASizeMap[VAT->getSizeExpr()]), LV);
} else {
- EmitInitializerForField(*CurField, LV, *I, None);
+ EmitInitializerForField(*CurField, LV, *I);
}
}
diff --git a/lib/CodeGen/CGStmtOpenMP.cpp b/lib/CodeGen/CGStmtOpenMP.cpp
index d214340bdafe..ba39e1fbd41f 100644
--- a/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/lib/CodeGen/CGStmtOpenMP.cpp
@@ -188,7 +188,7 @@ static Address castValueFromUintptr(CodeGenFunction &CGF, QualType DstType,
auto *RefVal = TmpAddr.getPointer();
TmpAddr = CGF.CreateMemTemp(RefType, Twine(Name) + ".ref");
auto TmpLVal = CGF.MakeAddrLValue(TmpAddr, RefType);
- CGF.EmitScalarInit(RefVal, TmpLVal);
+ CGF.EmitStoreThroughLValue(RValue::get(RefVal), TmpLVal, /*isInit*/ true);
}
return TmpAddr;
@@ -271,7 +271,17 @@ CodeGenFunction::GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S) {
// If we are capturing a pointer by copy we don't need to do anything, just
// use the value that we get from the arguments.
if (I->capturesVariableByCopy() && FD->getType()->isAnyPointerType()) {
- setAddrOfLocalVar(I->getCapturedVar(), GetAddrOfLocalVar(Args[Cnt]));
+ const VarDecl *CurVD = I->getCapturedVar();
+ Address LocalAddr = GetAddrOfLocalVar(Args[Cnt]);
+ // If the variable is a reference we need to materialize it here.
+ if (CurVD->getType()->isReferenceType()) {
+ Address RefAddr = CreateMemTemp(CurVD->getType(), getPointerAlign(),
+ ".materialized_ref");
+ EmitStoreOfScalar(LocalAddr.getPointer(), RefAddr, /*Volatile=*/false,
+ CurVD->getType());
+ LocalAddr = RefAddr;
+ }
+ setAddrOfLocalVar(CurVD, LocalAddr);
++Cnt;
++I;
continue;
@@ -1294,7 +1304,9 @@ void CodeGenFunction::EmitOMPInnerLoop(
// Start the loop with a block that tests the condition.
auto CondBlock = createBasicBlock("omp.inner.for.cond");
EmitBlock(CondBlock);
- LoopStack.push(CondBlock, Builder.getCurrentDebugLocation());
+ 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.
@@ -1695,7 +1707,9 @@ void CodeGenFunction::EmitOMPOuterLoop(bool DynamicOrOrdered, bool IsMonotonic,
// Start the loop with a block that tests the condition.
auto CondBlock = createBasicBlock("omp.dispatch.cond");
EmitBlock(CondBlock);
- LoopStack.push(CondBlock, Builder.getCurrentDebugLocation());
+ const SourceRange &R = S.getSourceRange();
+ LoopStack.push(CondBlock, SourceLocToDebugLoc(R.getBegin()),
+ SourceLocToDebugLoc(R.getEnd()));
llvm::Value *BoolCondVal = nullptr;
if (!DynamicOrOrdered) {
@@ -1930,6 +1944,94 @@ void CodeGenFunction::EmitOMPTargetParallelForSimdDirective(
});
}
+void CodeGenFunction::EmitOMPTargetSimdDirective(
+ const OMPTargetSimdDirective &S) {
+ OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
+ CGM.getOpenMPRuntime().emitInlinedDirective(
+ *this, OMPD_target_simd, [&S](CodeGenFunction &CGF, PrePostActionTy &) {
+ OMPLoopScope PreInitScope(CGF, S);
+ CGF.EmitStmt(
+ cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
+ });
+}
+
+void CodeGenFunction::EmitOMPTeamsDistributeDirective(
+ const OMPTeamsDistributeDirective &S) {
+ OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
+ CGM.getOpenMPRuntime().emitInlinedDirective(
+ *this, OMPD_teams_distribute,
+ [&S](CodeGenFunction &CGF, PrePostActionTy &) {
+ OMPLoopScope PreInitScope(CGF, S);
+ CGF.EmitStmt(
+ cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
+ });
+}
+
+void CodeGenFunction::EmitOMPTeamsDistributeSimdDirective(
+ const OMPTeamsDistributeSimdDirective &S) {
+ OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
+ CGM.getOpenMPRuntime().emitInlinedDirective(
+ *this, OMPD_teams_distribute_simd,
+ [&S](CodeGenFunction &CGF, PrePostActionTy &) {
+ OMPLoopScope PreInitScope(CGF, S);
+ CGF.EmitStmt(
+ cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
+ });
+}
+
+void CodeGenFunction::EmitOMPTeamsDistributeParallelForSimdDirective(
+ const OMPTeamsDistributeParallelForSimdDirective &S) {
+ OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
+ CGM.getOpenMPRuntime().emitInlinedDirective(
+ *this, OMPD_teams_distribute_parallel_for_simd,
+ [&S](CodeGenFunction &CGF, PrePostActionTy &) {
+ OMPLoopScope PreInitScope(CGF, S);
+ CGF.EmitStmt(
+ cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
+ });
+}
+
+void CodeGenFunction::EmitOMPTeamsDistributeParallelForDirective(
+ const OMPTeamsDistributeParallelForDirective &S) {
+ OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
+ CGM.getOpenMPRuntime().emitInlinedDirective(
+ *this, OMPD_teams_distribute_parallel_for,
+ [&S](CodeGenFunction &CGF, PrePostActionTy &) {
+ OMPLoopScope PreInitScope(CGF, S);
+ CGF.EmitStmt(
+ cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
+ });
+}
+
+void CodeGenFunction::EmitOMPTargetTeamsDirective(
+ const OMPTargetTeamsDirective &S) {
+ CGM.getOpenMPRuntime().emitInlinedDirective(
+ *this, OMPD_target_teams, [&S](CodeGenFunction &CGF, PrePostActionTy &) {
+ CGF.EmitStmt(
+ cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
+ });
+}
+
+void CodeGenFunction::EmitOMPTargetTeamsDistributeDirective(
+ const OMPTargetTeamsDistributeDirective &S) {
+ CGM.getOpenMPRuntime().emitInlinedDirective(
+ *this, OMPD_target_teams_distribute,
+ [&S](CodeGenFunction &CGF, PrePostActionTy &) {
+ CGF.EmitStmt(
+ cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
+ });
+}
+
+void CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDirective(
+ const OMPTargetTeamsDistributeParallelForDirective &S) {
+ CGM.getOpenMPRuntime().emitInlinedDirective(
+ *this, OMPD_target_teams_distribute_parallel_for,
+ [&S](CodeGenFunction &CGF, PrePostActionTy &) {
+ CGF.EmitStmt(
+ cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
+ });
+}
+
/// \brief Emit a helper variable and return corresponding lvalue.
static LValue EmitOMPHelperVar(CodeGenFunction &CGF,
const DeclRefExpr *Helper) {
@@ -2167,7 +2269,7 @@ static LValue createSectionLVal(CodeGenFunction &CGF, QualType Ty,
llvm::Value *Init = nullptr) {
auto LVal = CGF.MakeAddrLValue(CGF.CreateMemTemp(Ty, Name), Ty);
if (Init)
- CGF.EmitScalarInit(Init, LVal);
+ CGF.EmitStoreThroughLValue(RValue::get(Init), LVal, /*isInit*/ true);
return LVal;
}
@@ -2451,10 +2553,8 @@ void CodeGenFunction::EmitOMPTaskBasedDirective(const OMPExecutableDirective &S,
}
// Check if the task has 'priority' clause.
if (const auto *Clause = S.getSingleClause<OMPPriorityClause>()) {
- // Runtime currently does not support codegen for priority clause argument.
- // TODO: Add codegen for priority clause arg when runtime lib support it.
auto *Prio = Clause->getPriority();
- Data.Priority.setInt(Prio);
+ Data.Priority.setInt(/*IntVal=*/true);
Data.Priority.setPointer(EmitScalarConversion(
EmitScalarExpr(Prio), Prio->getType(),
getContext().getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1),
@@ -3368,7 +3468,7 @@ static void emitCommonOMPTeamsDirective(CodeGenFunction &CGF,
}
void CodeGenFunction::EmitOMPTeamsDirective(const OMPTeamsDirective &S) {
- // Emit parallel region as a standalone region.
+ // Emit teams region as a standalone region.
auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
OMPPrivateScope PrivateScope(CGF);
(void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
@@ -3410,22 +3510,137 @@ CodeGenFunction::getOMPCancelDestination(OpenMPDirectiveKind Kind) {
return OMPCancelStack.getExitBlock();
}
+void CodeGenFunction::EmitOMPUseDevicePtrClause(
+ const OMPClause &NC, OMPPrivateScope &PrivateScope,
+ const llvm::DenseMap<const ValueDecl *, Address> &CaptureDeviceAddrMap) {
+ 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());
+
+ // 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)) {
+ // OMPCapturedExprDecl are used to privative fields of the current
+ // structure.
+ auto *ME = cast<MemberExpr>(OED->getInit());
+ assert(isa<CXXThisExpr>(ME->getBase()) &&
+ "Base should be the current struct!");
+ MatchingVD = ME->getMemberDecl();
+ }
+
+ // If we don't have information about the current list item, move on to
+ // the next one.
+ auto InitAddrIt = CaptureDeviceAddrMap.find(MatchingVD);
+ if (InitAddrIt == CaptureDeviceAddrMap.end())
+ continue;
+
+ bool IsRegistered = PrivateScope.addPrivate(OrigVD, [&]() -> Address {
+ // 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
+ // privatization scope, so the initialization here disregards the fact
+ // the original variable is a reference.
+ QualType AddrQTy =
+ getContext().getPointerType(OrigVD->getType().getNonReferenceType());
+ llvm::Type *AddrTy = ConvertTypeForMem(AddrQTy);
+ Address InitAddr = Builder.CreateBitCast(InitAddrIt->second, AddrTy);
+ setAddrOfLocalVar(InitVD, InitAddr);
+
+ // Emit private declaration, it will be initialized by the value we
+ // declaration we just added to the local declarations map.
+ EmitDecl(*PvtVD);
+
+ // The initialization variables reached its purpose in the emission
+ // ofthe previous declaration, so we don't need it anymore.
+ LocalDeclMap.erase(InitVD);
+
+ // Return the address of the private variable.
+ return GetAddrOfLocalVar(PvtVD);
+ });
+ assert(IsRegistered && "firstprivate var already registered as private");
+ // Silence the warning about unused variable.
+ (void)IsRegistered;
+
+ ++OrigVarIt;
+ ++InitIt;
+ }
+}
+
// Generate the instructions for '#pragma omp target data' directive.
void CodeGenFunction::EmitOMPTargetDataDirective(
const OMPTargetDataDirective &S) {
- // The target data enclosed region is implemented just by emitting the
- // statement.
- auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
- CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
+ CGOpenMPRuntime::TargetDataInfo Info(/*RequiresDevicePointerInfo=*/true);
+
+ // Create a pre/post action to signal the privatization of the device pointer.
+ // This action can be replaced by the OpenMP runtime code generation to
+ // deactivate privatization.
+ bool PrivatizeDevicePointers = false;
+ class DevicePointerPrivActionTy : public PrePostActionTy {
+ bool &PrivatizeDevicePointers;
+
+ public:
+ explicit DevicePointerPrivActionTy(bool &PrivatizeDevicePointers)
+ : PrePostActionTy(), PrivatizeDevicePointers(PrivatizeDevicePointers) {}
+ void Enter(CodeGenFunction &CGF) override {
+ PrivatizeDevicePointers = true;
+ }
+ };
+ DevicePointerPrivActionTy PrivAction(PrivatizeDevicePointers);
+
+ auto &&CodeGen = [&S, &Info, &PrivatizeDevicePointers](
+ CodeGenFunction &CGF, PrePostActionTy &Action) {
+ auto &&InnermostCodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
+ CGF.EmitStmt(
+ cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
+ };
+
+ // Codegen that selects wheather to generate the privatization code or not.
+ auto &&PrivCodeGen = [&S, &Info, &PrivatizeDevicePointers,
+ &InnermostCodeGen](CodeGenFunction &CGF,
+ PrePostActionTy &Action) {
+ RegionCodeGenTy RCG(InnermostCodeGen);
+ PrivatizeDevicePointers = false;
+
+ // Call the pre-action to change the status of PrivatizeDevicePointers if
+ // needed.
+ Action.Enter(CGF);
+
+ if (PrivatizeDevicePointers) {
+ OMPPrivateScope PrivateScope(CGF);
+ // Emit all instances of the use_device_ptr clause.
+ for (const auto *C : S.getClausesOfKind<OMPUseDevicePtrClause>())
+ CGF.EmitOMPUseDevicePtrClause(*C, PrivateScope,
+ Info.CaptureDeviceAddrMap);
+ (void)PrivateScope.Privatize();
+ RCG(CGF);
+ } else
+ RCG(CGF);
+ };
+
+ // Forward the provided action to the privatization codegen.
+ RegionCodeGenTy PrivRCG(PrivCodeGen);
+ PrivRCG.setAction(Action);
+
+ // Notwithstanding the body of the region is emitted as inlined directive,
+ // we don't use an inline scope as changes in the references inside the
+ // region are expected to be visible outside, so we do not privative them.
+ OMPLexicalScope Scope(CGF, S);
+ CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_target_data,
+ PrivRCG);
};
+ RegionCodeGenTy RCG(CodeGen);
+
// If we don't have target devices, don't bother emitting the data mapping
// code.
if (CGM.getLangOpts().OMPTargetTriples.empty()) {
- OMPLexicalScope Scope(*this, S, /*AsInlined=*/true);
-
- CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_target_data,
- CodeGen);
+ RCG(*this);
return;
}
@@ -3439,7 +3654,12 @@ void CodeGenFunction::EmitOMPTargetDataDirective(
if (auto *C = S.getSingleClause<OMPDeviceClause>())
Device = C->getDevice();
- CGM.getOpenMPRuntime().emitTargetDataCalls(*this, S, IfCond, Device, CodeGen);
+ // Set the action to signal privatization of device pointers.
+ RCG.setAction(PrivAction);
+
+ // Emit region code.
+ CGM.getOpenMPRuntime().emitTargetDataCalls(*this, S, IfCond, Device, RCG,
+ Info);
}
void CodeGenFunction::EmitOMPTargetEnterDataDirective(
diff --git a/lib/CodeGen/CGVTT.cpp b/lib/CodeGen/CGVTT.cpp
index 5b90ee603307..92fd93b5ca38 100644
--- a/lib/CodeGen/CGVTT.cpp
+++ b/lib/CodeGen/CGVTT.cpp
@@ -23,7 +23,7 @@ GetAddrOfVTTVTable(CodeGenVTables &CGVT, CodeGenModule &CGM,
const CXXRecordDecl *MostDerivedClass,
const VTTVTable &VTable,
llvm::GlobalVariable::LinkageTypes Linkage,
- llvm::DenseMap<BaseSubobject, uint64_t> &AddressPoints) {
+ VTableLayout::AddressPointsMapTy &AddressPoints) {
if (VTable.getBase() == MostDerivedClass) {
assert(VTable.getBaseOffset().isZero() &&
"Most derived class vtable must have a zero offset!");
@@ -62,25 +62,27 @@ CodeGenVTables::EmitVTTDefinition(llvm::GlobalVariable *VTT,
*e = Builder.getVTTComponents().end(); i != e; ++i) {
const VTTVTable &VTTVT = Builder.getVTTVTables()[i->VTableIndex];
llvm::GlobalVariable *VTable = VTables[i->VTableIndex];
- uint64_t AddressPoint;
+ VTableLayout::AddressPointLocation AddressPoint;
if (VTTVT.getBase() == RD) {
// Just get the address point for the regular vtable.
AddressPoint =
getItaniumVTableContext().getVTableLayout(RD).getAddressPoint(
i->VTableBase);
- assert(AddressPoint != 0 && "Did not find vtable address point!");
} else {
AddressPoint = VTableAddressPoints[i->VTableIndex].lookup(i->VTableBase);
- assert(AddressPoint != 0 && "Did not find ctor vtable address point!");
+ assert(AddressPoint.AddressPointIndex != 0 &&
+ "Did not find ctor vtable address point!");
}
llvm::Value *Idxs[] = {
llvm::ConstantInt::get(Int32Ty, 0),
- llvm::ConstantInt::get(Int32Ty, AddressPoint)
+ llvm::ConstantInt::get(Int32Ty, AddressPoint.VTableIndex),
+ llvm::ConstantInt::get(Int32Ty, AddressPoint.AddressPointIndex),
};
- llvm::Constant *Init = llvm::ConstantExpr::getInBoundsGetElementPtr(
- VTable->getValueType(), VTable, Idxs);
+ llvm::Constant *Init = llvm::ConstantExpr::getGetElementPtr(
+ VTable->getValueType(), VTable, Idxs, /*InBounds=*/true,
+ /*InRangeIndex=*/1);
Init = llvm::ConstantExpr::getBitCast(Init, Int8PtrTy);
diff --git a/lib/CodeGen/CGVTables.cpp b/lib/CodeGen/CGVTables.cpp
index 957055033890..1a09830b52fd 100644
--- a/lib/CodeGen/CGVTables.cpp
+++ b/lib/CodeGen/CGVTables.cpp
@@ -11,16 +11,14 @@
//
//===----------------------------------------------------------------------===//
-#include "CodeGenFunction.h"
#include "CGCXXABI.h"
+#include "CodeGenFunction.h"
#include "CodeGenModule.h"
+#include "ConstantBuilder.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/RecordLayout.h"
#include "clang/CodeGen/CGFunctionInfo.h"
#include "clang/Frontend/CodeGenOptions.h"
-#include "llvm/ADT/DenseSet.h"
-#include "llvm/ADT/SetVector.h"
-#include "llvm/Support/Compiler.h"
#include "llvm/Support/Format.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include <algorithm>
@@ -32,7 +30,7 @@ using namespace CodeGen;
CodeGenVTables::CodeGenVTables(CodeGenModule &CGM)
: CGM(CGM), VTContext(CGM.getContext().getVTableContext()) {}
-llvm::Constant *CodeGenModule::GetAddrOfThunk(GlobalDecl GD,
+llvm::Constant *CodeGenModule::GetAddrOfThunk(GlobalDecl GD,
const ThunkInfo &Thunk) {
const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
@@ -96,7 +94,7 @@ static RValue PerformReturnAdjustment(CodeGenFunction &CGF,
AdjustNull = CGF.createBasicBlock("adjust.null");
AdjustNotNull = CGF.createBasicBlock("adjust.notnull");
AdjustEnd = CGF.createBasicBlock("adjust.end");
-
+
llvm::Value *IsNull = CGF.Builder.CreateIsNull(ReturnValue);
CGF.Builder.CreateCondBr(IsNull, AdjustNull, AdjustNotNull);
CGF.EmitBlock(AdjustNotNull);
@@ -113,14 +111,14 @@ static RValue PerformReturnAdjustment(CodeGenFunction &CGF,
CGF.EmitBlock(AdjustNull);
CGF.Builder.CreateBr(AdjustEnd);
CGF.EmitBlock(AdjustEnd);
-
+
llvm::PHINode *PHI = CGF.Builder.CreatePHI(ReturnValue->getType(), 2);
PHI->addIncoming(ReturnValue, AdjustNotNull);
- PHI->addIncoming(llvm::Constant::getNullValue(ReturnValue->getType()),
+ PHI->addIncoming(llvm::Constant::getNullValue(ReturnValue->getType()),
AdjustNull);
ReturnValue = PHI;
}
-
+
return RValue::get(ReturnValue);
}
@@ -232,8 +230,11 @@ void CodeGenFunction::StartThunk(llvm::Function *Fn, GlobalDecl GD,
CGM.getCXXABI().addImplicitStructorParams(*this, ResultType, FunctionArgs);
// Start defining the function.
+ auto NL = ApplyDebugLocation::CreateEmpty(*this);
StartFunction(GlobalDecl(), ResultType, Fn, FnInfo, FunctionArgs,
- MD->getLocation(), MD->getLocation());
+ MD->getLocation());
+ // Create a scope with an artificial location for the body of this function.
+ auto AL = ApplyDebugLocation::CreateArtificial(*this);
// Since we didn't pass a GlobalDecl to StartFunction, do this ourselves.
CGM.getCXXABI().EmitInstanceFunctionProlog(*this);
@@ -251,7 +252,7 @@ void CodeGenFunction::FinishThunk() {
FinishFunction();
}
-void CodeGenFunction::EmitCallAndReturnForThunk(llvm::Value *Callee,
+void CodeGenFunction::EmitCallAndReturnForThunk(llvm::Constant *CalleePtr,
const ThunkInfo *Thunk) {
assert(isa<CXXMethodDecl>(CurGD.getDecl()) &&
"Please use a new CGF for this thunk");
@@ -271,7 +272,7 @@ void CodeGenFunction::EmitCallAndReturnForThunk(llvm::Value *Callee,
CGM.ErrorUnsupported(
MD, "non-trivial argument copy for return-adjusting thunk");
}
- EmitMustTailThunk(MD, AdjustedThisPtr, Callee);
+ EmitMustTailThunk(MD, AdjustedThisPtr, CalleePtr);
return;
}
@@ -285,7 +286,7 @@ void CodeGenFunction::EmitCallAndReturnForThunk(llvm::Value *Callee,
// Add the rest of the arguments.
for (const ParmVarDecl *PD : MD->parameters())
- EmitDelegateCallArg(CallArgs, PD, PD->getLocStart());
+ EmitDelegateCallArg(CallArgs, PD, SourceLocation());
const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
@@ -317,10 +318,11 @@ void CodeGenFunction::EmitCallAndReturnForThunk(llvm::Value *Callee,
CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect &&
!hasScalarEvaluationKind(CurFnInfo->getReturnType()))
Slot = ReturnValueSlot(ReturnValue, ResultType.isVolatileQualified());
-
+
// Now emit our call.
llvm::Instruction *CallOrInvoke;
- RValue RV = EmitCall(*CurFnInfo, Callee, Slot, CallArgs, MD, &CallOrInvoke);
+ CGCallee Callee = CGCallee::forDirect(CalleePtr, MD);
+ RValue RV = EmitCall(*CurFnInfo, Callee, Slot, CallArgs, &CallOrInvoke);
// Consider return adjustment if we have ThunkInfo.
if (Thunk && !Thunk->Return.isEmpty())
@@ -340,7 +342,7 @@ void CodeGenFunction::EmitCallAndReturnForThunk(llvm::Value *Callee,
void CodeGenFunction::EmitMustTailThunk(const CXXMethodDecl *MD,
llvm::Value *AdjustedThisPtr,
- llvm::Value *Callee) {
+ llvm::Value *CalleePtr) {
// Emitting a musttail call thunk doesn't use any of the CGCall.cpp machinery
// to translate AST arguments into LLVM IR arguments. For thunks, we know
// that the caller prototype more or less matches the callee prototype with
@@ -369,13 +371,14 @@ void CodeGenFunction::EmitMustTailThunk(const CXXMethodDecl *MD,
// Emit the musttail call manually. Even if the prologue pushed cleanups, we
// don't actually want to run them.
- llvm::CallInst *Call = Builder.CreateCall(Callee, Args);
+ llvm::CallInst *Call = Builder.CreateCall(CalleePtr, Args);
Call->setTailCallKind(llvm::CallInst::TCK_MustTail);
// Apply the standard set of call attributes.
unsigned CallingConv;
CodeGen::AttributeListType AttributeList;
- CGM.ConstructAttributeList(Callee->getName(), *CurFnInfo, MD, AttributeList,
+ CGM.ConstructAttributeList(CalleePtr->getName(),
+ *CurFnInfo, MD, AttributeList,
CallingConv, /*AttrOnCallSite=*/true);
llvm::AttributeSet Attrs =
llvm::AttributeSet::get(getLLVMContext(), AttributeList);
@@ -397,11 +400,13 @@ void CodeGenFunction::generateThunk(llvm::Function *Fn,
const CGFunctionInfo &FnInfo,
GlobalDecl GD, const ThunkInfo &Thunk) {
StartThunk(Fn, GD, FnInfo);
+ // 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));
- llvm::Value *Callee = CGM.GetAddrOfFunction(GD, Ty, /*ForVTable=*/true);
+ llvm::Constant *Callee = CGM.GetAddrOfFunction(GD, Ty, /*ForVTable=*/true);
// Make the call and return the result.
EmitCallAndReturnForThunk(Callee, &Thunk);
@@ -436,14 +441,14 @@ void CodeGenVTables::emitThunk(GlobalDecl GD, const ThunkInfo &Thunk,
// Remove the name from the old thunk function and get a new thunk.
OldThunkFn->setName(StringRef());
Entry = cast<llvm::GlobalValue>(CGM.GetAddrOfThunk(GD, Thunk));
-
+
// If needed, replace the old thunk with a bitcast.
if (!OldThunkFn->use_empty()) {
llvm::Constant *NewPtrForOldDecl =
llvm::ConstantExpr::getBitCast(Entry, OldThunkFn->getType());
OldThunkFn->replaceAllUsesWith(NewPtrForOldDecl);
}
-
+
// Remove the old thunk.
OldThunkFn->eraseFromParent();
}
@@ -503,7 +508,7 @@ void CodeGenVTables::maybeEmitThunkForVTable(GlobalDecl GD,
void CodeGenVTables::EmitThunks(GlobalDecl GD)
{
- const CXXMethodDecl *MD =
+ const CXXMethodDecl *MD =
cast<CXXMethodDecl>(GD.getDecl())->getCanonicalDecl();
// We don't need to generate thunks for the base destructor.
@@ -520,146 +525,146 @@ void CodeGenVTables::EmitThunks(GlobalDecl GD)
emitThunk(GD, Thunk, /*ForVTable=*/false);
}
-llvm::Constant *CodeGenVTables::CreateVTableInitializer(
- const CXXRecordDecl *RD, const VTableComponent *Components,
- unsigned NumComponents, const VTableLayout::VTableThunkTy *VTableThunks,
- unsigned NumVTableThunks, llvm::Constant *RTTI) {
- SmallVector<llvm::Constant *, 64> Inits;
+void CodeGenVTables::addVTableComponent(
+ ConstantArrayBuilder &builder, const VTableLayout &layout,
+ unsigned idx, llvm::Constant *rtti, unsigned &nextVTableThunkIndex) {
+ auto &component = layout.vtable_components()[idx];
- llvm::Type *Int8PtrTy = CGM.Int8PtrTy;
-
- llvm::Type *PtrDiffTy =
- CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType());
+ auto addOffsetConstant = [&](CharUnits offset) {
+ builder.add(llvm::ConstantExpr::getIntToPtr(
+ llvm::ConstantInt::get(CGM.PtrDiffTy, offset.getQuantity()),
+ CGM.Int8PtrTy));
+ };
- unsigned NextVTableThunkIndex = 0;
+ switch (component.getKind()) {
+ case VTableComponent::CK_VCallOffset:
+ return addOffsetConstant(component.getVCallOffset());
- llvm::Constant *PureVirtualFn = nullptr, *DeletedVirtualFn = nullptr;
+ case VTableComponent::CK_VBaseOffset:
+ return addOffsetConstant(component.getVBaseOffset());
- for (unsigned I = 0; I != NumComponents; ++I) {
- VTableComponent Component = Components[I];
+ case VTableComponent::CK_OffsetToTop:
+ return addOffsetConstant(component.getOffsetToTop());
- llvm::Constant *Init = nullptr;
+ case VTableComponent::CK_RTTI:
+ return builder.add(llvm::ConstantExpr::getBitCast(rtti, CGM.Int8PtrTy));
- switch (Component.getKind()) {
- case VTableComponent::CK_VCallOffset:
- Init = llvm::ConstantInt::get(PtrDiffTy,
- Component.getVCallOffset().getQuantity());
- Init = llvm::ConstantExpr::getIntToPtr(Init, Int8PtrTy);
- break;
- case VTableComponent::CK_VBaseOffset:
- Init = llvm::ConstantInt::get(PtrDiffTy,
- Component.getVBaseOffset().getQuantity());
- Init = llvm::ConstantExpr::getIntToPtr(Init, Int8PtrTy);
+ case VTableComponent::CK_FunctionPointer:
+ case VTableComponent::CK_CompleteDtorPointer:
+ case VTableComponent::CK_DeletingDtorPointer: {
+ GlobalDecl GD;
+
+ // Get the right global decl.
+ switch (component.getKind()) {
+ default:
+ llvm_unreachable("Unexpected vtable component kind");
+ case VTableComponent::CK_FunctionPointer:
+ GD = component.getFunctionDecl();
break;
- case VTableComponent::CK_OffsetToTop:
- Init = llvm::ConstantInt::get(PtrDiffTy,
- Component.getOffsetToTop().getQuantity());
- Init = llvm::ConstantExpr::getIntToPtr(Init, Int8PtrTy);
+ case VTableComponent::CK_CompleteDtorPointer:
+ GD = GlobalDecl(component.getDestructorDecl(), Dtor_Complete);
break;
- case VTableComponent::CK_RTTI:
- Init = llvm::ConstantExpr::getBitCast(RTTI, Int8PtrTy);
+ case VTableComponent::CK_DeletingDtorPointer:
+ GD = GlobalDecl(component.getDestructorDecl(), Dtor_Deleting);
break;
- case VTableComponent::CK_FunctionPointer:
- case VTableComponent::CK_CompleteDtorPointer:
- case VTableComponent::CK_DeletingDtorPointer: {
- GlobalDecl GD;
-
- // Get the right global decl.
- switch (Component.getKind()) {
- default:
- llvm_unreachable("Unexpected vtable component kind");
- case VTableComponent::CK_FunctionPointer:
- GD = Component.getFunctionDecl();
- break;
- case VTableComponent::CK_CompleteDtorPointer:
- GD = GlobalDecl(Component.getDestructorDecl(), Dtor_Complete);
- break;
- case VTableComponent::CK_DeletingDtorPointer:
- GD = GlobalDecl(Component.getDestructorDecl(), Dtor_Deleting);
- break;
- }
-
- if (CGM.getLangOpts().CUDA) {
- // Emit NULL for methods we can't codegen on this
- // side. Otherwise we'd end up with vtable with unresolved
- // references.
- const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
- // OK on device side: functions w/ __device__ attribute
- // OK on host side: anything except __device__-only functions.
- bool CanEmitMethod = CGM.getLangOpts().CUDAIsDevice
- ? MD->hasAttr<CUDADeviceAttr>()
- : (MD->hasAttr<CUDAHostAttr>() ||
- !MD->hasAttr<CUDADeviceAttr>());
- if (!CanEmitMethod) {
- Init = llvm::ConstantExpr::getNullValue(Int8PtrTy);
- break;
- }
- // Method is acceptable, continue processing as usual.
- }
+ }
- if (cast<CXXMethodDecl>(GD.getDecl())->isPure()) {
- // We have a pure virtual member function.
- if (!PureVirtualFn) {
- llvm::FunctionType *Ty =
- llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
- StringRef PureCallName = CGM.getCXXABI().GetPureVirtualCallName();
- PureVirtualFn = CGM.CreateRuntimeFunction(Ty, PureCallName);
- if (auto *F = dyn_cast<llvm::Function>(PureVirtualFn))
- F->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
- PureVirtualFn = llvm::ConstantExpr::getBitCast(PureVirtualFn,
- CGM.Int8PtrTy);
- }
- Init = PureVirtualFn;
- } else if (cast<CXXMethodDecl>(GD.getDecl())->isDeleted()) {
- if (!DeletedVirtualFn) {
- llvm::FunctionType *Ty =
- llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
- StringRef DeletedCallName =
- CGM.getCXXABI().GetDeletedVirtualCallName();
- DeletedVirtualFn = CGM.CreateRuntimeFunction(Ty, DeletedCallName);
- if (auto *F = dyn_cast<llvm::Function>(DeletedVirtualFn))
- F->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
- DeletedVirtualFn = llvm::ConstantExpr::getBitCast(DeletedVirtualFn,
- CGM.Int8PtrTy);
- }
- Init = DeletedVirtualFn;
- } else {
- // Check if we should use a thunk.
- if (NextVTableThunkIndex < NumVTableThunks &&
- VTableThunks[NextVTableThunkIndex].first == I) {
- const ThunkInfo &Thunk = VTableThunks[NextVTableThunkIndex].second;
-
- maybeEmitThunkForVTable(GD, Thunk);
- Init = CGM.GetAddrOfThunk(GD, Thunk);
-
- NextVTableThunkIndex++;
- } else {
- llvm::Type *Ty = CGM.getTypes().GetFunctionTypeForVTable(GD);
-
- Init = CGM.GetAddrOfFunction(GD, Ty, /*ForVTable=*/true);
- }
-
- Init = llvm::ConstantExpr::getBitCast(Init, Int8PtrTy);
- }
- break;
+ if (CGM.getLangOpts().CUDA) {
+ // Emit NULL for methods we can't codegen on this
+ // side. Otherwise we'd end up with vtable with unresolved
+ // references.
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
+ // OK on device side: functions w/ __device__ attribute
+ // OK on host side: anything except __device__-only functions.
+ bool CanEmitMethod =
+ CGM.getLangOpts().CUDAIsDevice
+ ? MD->hasAttr<CUDADeviceAttr>()
+ : (MD->hasAttr<CUDAHostAttr>() || !MD->hasAttr<CUDADeviceAttr>());
+ if (!CanEmitMethod)
+ return builder.addNullPointer(CGM.Int8PtrTy);
+ // Method is acceptable, continue processing as usual.
}
- case VTableComponent::CK_UnusedFunctionPointer:
- Init = llvm::ConstantExpr::getNullValue(Int8PtrTy);
- break;
+ auto getSpecialVirtualFn = [&](StringRef name) {
+ llvm::FunctionType *fnTy =
+ llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
+ llvm::Constant *fn = CGM.CreateRuntimeFunction(fnTy, name);
+ if (auto f = dyn_cast<llvm::Function>(fn))
+ f->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
+ return llvm::ConstantExpr::getBitCast(fn, CGM.Int8PtrTy);
};
-
- Inits.push_back(Init);
+
+ llvm::Constant *fnPtr;
+
+ // Pure virtual member functions.
+ if (cast<CXXMethodDecl>(GD.getDecl())->isPure()) {
+ if (!PureVirtualFn)
+ PureVirtualFn =
+ getSpecialVirtualFn(CGM.getCXXABI().GetPureVirtualCallName());
+ fnPtr = PureVirtualFn;
+
+ // Deleted virtual member functions.
+ } else if (cast<CXXMethodDecl>(GD.getDecl())->isDeleted()) {
+ if (!DeletedVirtualFn)
+ DeletedVirtualFn =
+ getSpecialVirtualFn(CGM.getCXXABI().GetDeletedVirtualCallName());
+ fnPtr = DeletedVirtualFn;
+
+ // Thunks.
+ } else if (nextVTableThunkIndex < layout.vtable_thunks().size() &&
+ layout.vtable_thunks()[nextVTableThunkIndex].first == idx) {
+ auto &thunkInfo = layout.vtable_thunks()[nextVTableThunkIndex].second;
+
+ maybeEmitThunkForVTable(GD, thunkInfo);
+ nextVTableThunkIndex++;
+ fnPtr = CGM.GetAddrOfThunk(GD, thunkInfo);
+
+ // Otherwise we can use the method definition directly.
+ } else {
+ llvm::Type *fnTy = CGM.getTypes().GetFunctionTypeForVTable(GD);
+ fnPtr = CGM.GetAddrOfFunction(GD, fnTy, /*ForVTable=*/true);
+ }
+
+ fnPtr = llvm::ConstantExpr::getBitCast(fnPtr, CGM.Int8PtrTy);
+ builder.add(fnPtr);
+ return;
+ }
+
+ case VTableComponent::CK_UnusedFunctionPointer:
+ return builder.addNullPointer(CGM.Int8PtrTy);
+ }
+
+ llvm_unreachable("Unexpected vtable component kind");
+}
+
+llvm::Type *CodeGenVTables::getVTableType(const VTableLayout &layout) {
+ SmallVector<llvm::Type *, 4> tys;
+ for (unsigned i = 0, e = layout.getNumVTables(); i != e; ++i) {
+ tys.push_back(llvm::ArrayType::get(CGM.Int8PtrTy, layout.getVTableSize(i)));
+ }
+
+ return llvm::StructType::get(CGM.getLLVMContext(), tys);
+}
+
+void CodeGenVTables::createVTableInitializer(ConstantStructBuilder &builder,
+ const VTableLayout &layout,
+ llvm::Constant *rtti) {
+ unsigned nextVTableThunkIndex = 0;
+ for (unsigned i = 0, e = layout.getNumVTables(); i != e; ++i) {
+ auto vtableElem = builder.beginArray(CGM.Int8PtrTy);
+ size_t thisIndex = layout.getVTableOffset(i);
+ size_t nextIndex = thisIndex + layout.getVTableSize(i);
+ for (unsigned i = thisIndex; i != nextIndex; ++i) {
+ addVTableComponent(vtableElem, layout, i, rtti, nextVTableThunkIndex);
+ }
+ vtableElem.finishAndAddTo(builder);
}
-
- llvm::ArrayType *ArrayType = llvm::ArrayType::get(Int8PtrTy, NumComponents);
- return llvm::ConstantArray::get(ArrayType, Inits);
}
llvm::GlobalVariable *
-CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD,
- const BaseSubobject &Base,
- bool BaseIsVirtual,
+CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD,
+ const BaseSubobject &Base,
+ bool BaseIsVirtual,
llvm::GlobalVariable::LinkageTypes Linkage,
VTableAddressPointsMapTy& AddressPoints) {
if (CGDebugInfo *DI = CGM.getModuleDebugInfo())
@@ -680,8 +685,7 @@ CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD,
Base.getBase(), Out);
StringRef Name = OutName.str();
- llvm::ArrayType *ArrayType =
- llvm::ArrayType::get(CGM.Int8PtrTy, VTLayout->getNumVTableComponents());
+ llvm::Type *VTType = getVTableType(*VTLayout);
// Construction vtable symbols are not part of the Itanium ABI, so we cannot
// guarantee that they actually will be available externally. Instead, when
@@ -692,8 +696,8 @@ CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD,
Linkage = llvm::GlobalVariable::InternalLinkage;
// Create the variable that will hold the construction vtable.
- llvm::GlobalVariable *VTable =
- CGM.CreateOrReplaceCXXRuntimeVariable(Name, ArrayType, Linkage);
+ llvm::GlobalVariable *VTable =
+ CGM.CreateOrReplaceCXXRuntimeVariable(Name, VTType, Linkage);
CGM.setGlobalVisibility(VTable, RD);
// V-tables are always unnamed_addr.
@@ -703,12 +707,11 @@ CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD,
CGM.getContext().getTagDeclType(Base.getBase()));
// Create and set the initializer.
- llvm::Constant *Init = CreateVTableInitializer(
- Base.getBase(), VTLayout->vtable_component_begin(),
- VTLayout->getNumVTableComponents(), VTLayout->vtable_thunk_begin(),
- VTLayout->getNumVTableThunks(), RTTI);
- VTable->setInitializer(Init);
-
+ ConstantInitBuilder builder(CGM);
+ auto components = builder.beginStruct();
+ createVTableInitializer(components, *VTLayout, RTTI);
+ components.finishAndSetAsInitializer(VTable);
+
CGM.EmitVTableTypeMetadata(VTable, *VTLayout.get());
return VTable;
@@ -723,7 +726,7 @@ static bool shouldEmitAvailableExternallyVTable(const CodeGenModule &CGM,
/// Compute the required linkage of the vtable for the given class.
///
/// Note that we only call this at the end of the translation unit.
-llvm::GlobalVariable::LinkageTypes
+llvm::GlobalVariable::LinkageTypes
CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) {
if (!RD->isExternallyVisible())
return llvm::GlobalVariable::InternalLinkage;
@@ -737,7 +740,7 @@ CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) {
const FunctionDecl *def = nullptr;
if (keyFunction->hasBody(def))
keyFunction = cast<CXXMethodDecl>(def);
-
+
switch (keyFunction->getTemplateSpecializationKind()) {
case TSK_Undeclared:
case TSK_ExplicitSpecialization:
@@ -751,7 +754,7 @@ CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) {
return !Context.getLangOpts().AppleKext ?
llvm::GlobalVariable::LinkOnceODRLinkage :
llvm::Function::InternalLinkage;
-
+
return llvm::GlobalVariable::ExternalLinkage;
case TSK_ImplicitInstantiation:
@@ -763,7 +766,7 @@ CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) {
return !Context.getLangOpts().AppleKext ?
llvm::GlobalVariable::WeakODRLinkage :
llvm::Function::InternalLinkage;
-
+
case TSK_ExplicitInstantiationDeclaration:
llvm_unreachable("Should not have been asked to emit this");
}
@@ -819,7 +822,7 @@ void CodeGenModule::EmitVTable(CXXRecordDecl *theClass) {
VTables.GenerateClassData(theClass);
}
-void
+void
CodeGenVTables::GenerateClassData(const CXXRecordDecl *RD) {
if (CGDebugInfo *DI = CGM.getModuleDebugInfo())
DI->completeClassData(RD);
@@ -949,7 +952,10 @@ void CodeGenModule::EmitVTableTypeMetadata(llvm::GlobalVariable *VTable,
std::vector<BSEntry> BitsetEntries;
// Create a bit set entry for each address point.
for (auto &&AP : VTLayout.getAddressPoints())
- BitsetEntries.push_back(std::make_pair(AP.first.getBase(), AP.second));
+ 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(),
diff --git a/lib/CodeGen/CGVTables.h b/lib/CodeGen/CGVTables.h
index c27e54af258d..b92212c368a9 100644
--- a/lib/CodeGen/CGVTables.h
+++ b/lib/CodeGen/CGVTables.h
@@ -27,6 +27,8 @@ namespace clang {
namespace CodeGen {
class CodeGenModule;
+ class ConstantArrayBuilder;
+ class ConstantStructBuilder;
class CodeGenVTables {
CodeGenModule &CGM;
@@ -34,7 +36,7 @@ class CodeGenVTables {
VTableContextBase *VTContext;
/// VTableAddressPointsMapTy - Address points for a single vtable.
- typedef llvm::DenseMap<BaseSubobject, uint64_t> VTableAddressPointsMapTy;
+ typedef VTableLayout::AddressPointsMapTy VTableAddressPointsMapTy;
typedef std::pair<const CXXRecordDecl *, BaseSubobject> BaseSubobjectPairTy;
typedef llvm::DenseMap<BaseSubobjectPairTy, uint64_t> SubVTTIndiciesMapTy;
@@ -49,6 +51,12 @@ class CodeGenVTables {
/// indices.
SecondaryVirtualPointerIndicesMapTy SecondaryVirtualPointerIndices;
+ /// Cache for the pure virtual member call function.
+ llvm::Constant *PureVirtualFn = nullptr;
+
+ /// 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);
@@ -56,15 +64,17 @@ class CodeGenVTables {
/// the ABI.
void maybeEmitThunkForVTable(GlobalDecl GD, const ThunkInfo &Thunk);
+ void addVTableComponent(ConstantArrayBuilder &builder,
+ const VTableLayout &layout, unsigned idx,
+ llvm::Constant *rtti,
+ unsigned &nextVTableThunkIndex);
+
public:
- /// CreateVTableInitializer - Create a vtable initializer for the given record
- /// decl.
- /// \param Components - The vtable components; this is really an array of
- /// VTableComponents.
- llvm::Constant *CreateVTableInitializer(
- const CXXRecordDecl *RD, const VTableComponent *Components,
- unsigned NumComponents, const VTableLayout::VTableThunkTy *VTableThunks,
- unsigned NumVTableThunks, llvm::Constant *RTTI);
+ /// Add vtable components for the given vtable layout to the given
+ /// global initializer.
+ void createVTableInitializer(ConstantStructBuilder &builder,
+ const VTableLayout &layout,
+ llvm::Constant *rtti);
CodeGenVTables(CodeGenModule &CGM);
@@ -112,6 +122,11 @@ public:
void GenerateClassData(const CXXRecordDecl *RD);
bool isVTableExternal(const CXXRecordDecl *RD);
+
+ /// Returns the type of a vtable with the given layout. Normally a struct of
+ /// arrays of pointers, with one struct element for each vtable in the vtable
+ /// group.
+ llvm::Type *getVTableType(const VTableLayout &layout);
};
} // end namespace CodeGen
diff --git a/lib/CodeGen/CMakeLists.txt b/lib/CodeGen/CMakeLists.txt
index 257dec9629b2..4fbf9f22a98d 100644
--- a/lib/CodeGen/CMakeLists.txt
+++ b/lib/CodeGen/CMakeLists.txt
@@ -3,15 +3,18 @@ set(LLVM_LINK_COMPONENTS
BitReader
BitWriter
Core
+ Coroutines
Coverage
IPO
IRReader
InstCombine
Instrumentation
+ LTO
Linker
MC
ObjCARCOpts
Object
+ Passes
ProfileData
ScalarOpts
Support
@@ -41,6 +44,7 @@ add_clang_library(clangCodeGen
CGCall.cpp
CGClass.cpp
CGCleanup.cpp
+ CGCoroutine.cpp
CGDebugInfo.cpp
CGDecl.cpp
CGDeclCXX.cpp
@@ -79,12 +83,15 @@ add_clang_library(clangCodeGen
SanitizerMetadata.cpp
SwiftCallingConv.cpp
TargetInfo.cpp
+ VarBypassDetector.cpp
DEPENDS
${codegen_deps}
LINK_LIBS
+ clangAnalysis
clangAST
+ clangAnalysis
clangBasic
clangFrontend
clangLex
diff --git a/lib/CodeGen/CodeGenAction.cpp b/lib/CodeGen/CodeGenAction.cpp
index 49738a20f493..1e17918df4a4 100644
--- a/lib/CodeGen/CodeGenAction.cpp
+++ b/lib/CodeGen/CodeGenAction.cpp
@@ -21,8 +21,7 @@
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Lex/Preprocessor.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/Bitcode/BitcodeReader.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/DiagnosticPrinter.h"
@@ -34,6 +33,8 @@
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/Timer.h"
+#include "llvm/Support/ToolOutputFile.h"
+#include "llvm/Support/YAMLTraits.h"
#include <memory>
using namespace clang;
using namespace llvm;
@@ -50,6 +51,12 @@ namespace clang {
ASTContext *Context;
Timer LLVMIRGeneration;
+ unsigned LLVMIRGenerationRefCount;
+
+ /// True if we've finished generating IR. This prevents us from generating
+ /// additional LLVM IR after emitting output in HandleTranslationUnit. This
+ /// can happen when Clang plugins trigger additional AST deserialization.
+ bool IRGenFinished = false;
std::unique_ptr<CodeGenerator> Gen;
@@ -73,7 +80,8 @@ namespace clang {
: Diags(Diags), Action(Action), CodeGenOpts(CodeGenOpts),
TargetOpts(TargetOpts), LangOpts(LangOpts),
AsmOutStream(std::move(OS)), Context(nullptr),
- LLVMIRGeneration("LLVM IR Generation Time"),
+ LLVMIRGeneration("irgen", "LLVM IR Generation Time"),
+ LLVMIRGenerationRefCount(0),
Gen(CreateLLVMCodeGen(Diags, InFile, HeaderSearchOpts, PPOpts,
CodeGenOpts, C, CoverageInfo)) {
llvm::TimePassesIsEnabled = TimePasses;
@@ -113,13 +121,20 @@ namespace clang {
Context->getSourceManager(),
"LLVM IR generation of declaration");
- if (llvm::TimePassesIsEnabled)
- LLVMIRGeneration.startTimer();
+ // Recurse.
+ if (llvm::TimePassesIsEnabled) {
+ LLVMIRGenerationRefCount += 1;
+ if (LLVMIRGenerationRefCount == 1)
+ LLVMIRGeneration.startTimer();
+ }
Gen->HandleTopLevelDecl(D);
- if (llvm::TimePassesIsEnabled)
- LLVMIRGeneration.stopTimer();
+ if (llvm::TimePassesIsEnabled) {
+ LLVMIRGenerationRefCount -= 1;
+ if (LLVMIRGenerationRefCount == 0)
+ LLVMIRGeneration.stopTimer();
+ }
return true;
}
@@ -137,16 +152,30 @@ namespace clang {
LLVMIRGeneration.stopTimer();
}
+ void HandleInterestingDecl(DeclGroupRef D) override {
+ // Ignore interesting decls from the AST reader after IRGen is finished.
+ if (!IRGenFinished)
+ HandleTopLevelDecl(D);
+ }
+
void HandleTranslationUnit(ASTContext &C) override {
{
PrettyStackTraceString CrashInfo("Per-file LLVM IR generation");
- if (llvm::TimePassesIsEnabled)
- LLVMIRGeneration.startTimer();
+ if (llvm::TimePassesIsEnabled) {
+ LLVMIRGenerationRefCount += 1;
+ if (LLVMIRGenerationRefCount == 1)
+ LLVMIRGeneration.startTimer();
+ }
Gen->HandleTranslationUnit(C);
- if (llvm::TimePassesIsEnabled)
- LLVMIRGeneration.stopTimer();
+ if (llvm::TimePassesIsEnabled) {
+ LLVMIRGenerationRefCount -= 1;
+ if (LLVMIRGenerationRefCount == 0)
+ LLVMIRGeneration.stopTimer();
+ }
+
+ IRGenFinished = true;
}
// Silently ignore if we weren't initialized for some reason.
@@ -165,6 +194,26 @@ namespace clang {
Ctx.getDiagnosticHandler();
void *OldDiagnosticContext = Ctx.getDiagnosticContext();
Ctx.setDiagnosticHandler(DiagnosticHandler, this);
+ Ctx.setDiagnosticHotnessRequested(CodeGenOpts.DiagnosticsWithHotness);
+
+ std::unique_ptr<llvm::tool_output_file> OptRecordFile;
+ if (!CodeGenOpts.OptRecordFile.empty()) {
+ std::error_code EC;
+ OptRecordFile =
+ llvm::make_unique<llvm::tool_output_file>(CodeGenOpts.OptRecordFile,
+ EC, sys::fs::F_None);
+ if (EC) {
+ Diags.Report(diag::err_cannot_open_file) <<
+ CodeGenOpts.OptRecordFile << EC.message();
+ return;
+ }
+
+ Ctx.setDiagnosticsOutputFile(
+ llvm::make_unique<yaml::Output>(OptRecordFile->os()));
+
+ if (CodeGenOpts.getProfileUse() != CodeGenOptions::ProfileNone)
+ Ctx.setDiagnosticHotnessRequested(true);
+ }
// Link LinkModule into this module if present, preserving its validity.
for (auto &I : LinkModules) {
@@ -183,6 +232,9 @@ namespace clang {
Ctx.setInlineAsmDiagnosticHandler(OldHandler, OldContext);
Ctx.setDiagnosticHandler(OldDiagnosticHandler, OldDiagnosticContext);
+
+ if (OptRecordFile)
+ OptRecordFile->keep();
}
void HandleTagDeclDefinition(TagDecl *D) override {
@@ -245,16 +297,13 @@ namespace clang {
/// them.
void EmitOptimizationMessage(const llvm::DiagnosticInfoOptimizationBase &D,
unsigned DiagID);
- void
- OptimizationRemarkHandler(const llvm::DiagnosticInfoOptimizationRemark &D);
- void OptimizationRemarkHandler(
- const llvm::DiagnosticInfoOptimizationRemarkMissed &D);
- void OptimizationRemarkHandler(
- const llvm::DiagnosticInfoOptimizationRemarkAnalysis &D);
+ void OptimizationRemarkHandler(const llvm::OptimizationRemark &D);
+ void OptimizationRemarkHandler(const llvm::OptimizationRemarkMissed &D);
+ void OptimizationRemarkHandler(const llvm::OptimizationRemarkAnalysis &D);
void OptimizationRemarkHandler(
- const llvm::DiagnosticInfoOptimizationRemarkAnalysisFPCommute &D);
+ const llvm::OptimizationRemarkAnalysisFPCommute &D);
void OptimizationRemarkHandler(
- const llvm::DiagnosticInfoOptimizationRemarkAnalysisAliasing &D);
+ const llvm::OptimizationRemarkAnalysisAliasing &D);
void OptimizationFailureHandler(
const llvm::DiagnosticInfoOptimizationFailure &D);
};
@@ -497,9 +546,16 @@ void BackendConsumer::EmitOptimizationMessage(
FullSourceLoc Loc = getBestLocationFromDebugLoc(D, BadDebugInfo, Filename,
Line, Column);
+ std::string Msg;
+ raw_string_ostream MsgStream(Msg);
+ MsgStream << D.getMsg();
+
+ if (D.getHotness())
+ MsgStream << " (hotness: " << *D.getHotness() << ")";
+
Diags.Report(Loc, DiagID)
- << AddFlagValue(D.getPassName() ? D.getPassName() : "")
- << D.getMsg().str();
+ << AddFlagValue(D.getPassName())
+ << MsgStream.str();
if (BadDebugInfo)
// If we were not able to translate the file:line:col information
@@ -511,7 +567,7 @@ void BackendConsumer::EmitOptimizationMessage(
}
void BackendConsumer::OptimizationRemarkHandler(
- const llvm::DiagnosticInfoOptimizationRemark &D) {
+ const llvm::OptimizationRemark &D) {
// Optimization remarks are active only if the -Rpass flag has a regular
// expression that matches the name of the pass name in \p D.
if (CodeGenOpts.OptimizationRemarkPattern &&
@@ -520,7 +576,7 @@ void BackendConsumer::OptimizationRemarkHandler(
}
void BackendConsumer::OptimizationRemarkHandler(
- const llvm::DiagnosticInfoOptimizationRemarkMissed &D) {
+ const llvm::OptimizationRemarkMissed &D) {
// Missed optimization remarks are active only if the -Rpass-missed
// flag has a regular expression that matches the name of the pass
// name in \p D.
@@ -531,7 +587,7 @@ void BackendConsumer::OptimizationRemarkHandler(
}
void BackendConsumer::OptimizationRemarkHandler(
- const llvm::DiagnosticInfoOptimizationRemarkAnalysis &D) {
+ const llvm::OptimizationRemarkAnalysis &D) {
// Optimization analysis remarks are active if the pass name is set to
// llvm::DiagnosticInfo::AlwasyPrint or if the -Rpass-analysis flag has a
// regular expression that matches the name of the pass name in \p D.
@@ -544,7 +600,7 @@ void BackendConsumer::OptimizationRemarkHandler(
}
void BackendConsumer::OptimizationRemarkHandler(
- const llvm::DiagnosticInfoOptimizationRemarkAnalysisFPCommute &D) {
+ const llvm::OptimizationRemarkAnalysisFPCommute &D) {
// Optimization analysis remarks are active if the pass name is set to
// llvm::DiagnosticInfo::AlwasyPrint or if the -Rpass-analysis flag has a
// regular expression that matches the name of the pass name in \p D.
@@ -557,7 +613,7 @@ void BackendConsumer::OptimizationRemarkHandler(
}
void BackendConsumer::OptimizationRemarkHandler(
- const llvm::DiagnosticInfoOptimizationRemarkAnalysisAliasing &D) {
+ const llvm::OptimizationRemarkAnalysisAliasing &D) {
// Optimization analysis remarks are active if the pass name is set to
// llvm::DiagnosticInfo::AlwasyPrint or if the -Rpass-analysis flag has a
// regular expression that matches the name of the pass name in \p D.
@@ -601,30 +657,27 @@ void BackendConsumer::DiagnosticHandlerImpl(const DiagnosticInfo &DI) {
case llvm::DK_OptimizationRemark:
// Optimization remarks are always handled completely by this
// handler. There is no generic way of emitting them.
- OptimizationRemarkHandler(cast<DiagnosticInfoOptimizationRemark>(DI));
+ OptimizationRemarkHandler(cast<OptimizationRemark>(DI));
return;
case llvm::DK_OptimizationRemarkMissed:
// Optimization remarks are always handled completely by this
// handler. There is no generic way of emitting them.
- OptimizationRemarkHandler(cast<DiagnosticInfoOptimizationRemarkMissed>(DI));
+ OptimizationRemarkHandler(cast<OptimizationRemarkMissed>(DI));
return;
case llvm::DK_OptimizationRemarkAnalysis:
// Optimization remarks are always handled completely by this
// handler. There is no generic way of emitting them.
- OptimizationRemarkHandler(
- cast<DiagnosticInfoOptimizationRemarkAnalysis>(DI));
+ OptimizationRemarkHandler(cast<OptimizationRemarkAnalysis>(DI));
return;
case llvm::DK_OptimizationRemarkAnalysisFPCommute:
// Optimization remarks are always handled completely by this
// handler. There is no generic way of emitting them.
- OptimizationRemarkHandler(
- cast<DiagnosticInfoOptimizationRemarkAnalysisFPCommute>(DI));
+ OptimizationRemarkHandler(cast<OptimizationRemarkAnalysisFPCommute>(DI));
return;
case llvm::DK_OptimizationRemarkAnalysisAliasing:
// Optimization remarks are always handled completely by this
// handler. There is no generic way of emitting them.
- OptimizationRemarkHandler(
- cast<DiagnosticInfoOptimizationRemarkAnalysisAliasing>(DI));
+ OptimizationRemarkHandler(cast<OptimizationRemarkAnalysisAliasing>(DI));
return;
case llvm::DK_OptimizationFailure:
// Optimization failures are always handled completely by this
@@ -732,11 +785,13 @@ CodeGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
return nullptr;
}
- ErrorOr<std::unique_ptr<llvm::Module>> ModuleOrErr =
- getLazyBitcodeModule(std::move(*BCBuf), *VMContext);
- if (std::error_code EC = ModuleOrErr.getError()) {
- CI.getDiagnostics().Report(diag::err_cannot_open_file) << LinkBCFile
- << EC.message();
+ Expected<std::unique_ptr<llvm::Module>> ModuleOrErr =
+ getOwningLazyBitcodeModule(std::move(*BCBuf), *VMContext);
+ if (!ModuleOrErr) {
+ handleAllErrors(ModuleOrErr.takeError(), [&](ErrorInfoBase &EIB) {
+ CI.getDiagnostics().Report(diag::err_cannot_open_file)
+ << LinkBCFile << EIB.message();
+ });
LinkModules.clear();
return nullptr;
}
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index 11e4ad9ecefa..a954f487d1e4 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -38,20 +38,35 @@
using namespace clang;
using namespace CodeGen;
+/// shouldEmitLifetimeMarkers - Decide whether we need emit the life-time
+/// markers.
+static bool shouldEmitLifetimeMarkers(const CodeGenOptions &CGOpts,
+ const LangOptions &LangOpts) {
+ // Asan uses markers for use-after-scope checks.
+ if (CGOpts.SanitizeAddressUseAfterScope)
+ return true;
+
+ // Disable lifetime markers in msan builds.
+ // FIXME: Remove this when msan works with lifetime markers.
+ if (LangOpts.Sanitize.has(SanitizerKind::Memory))
+ return false;
+
+ // For now, only in optimized builds.
+ return CGOpts.OptimizationLevel != 0;
+}
+
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()),
+ 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),
@@ -60,7 +75,9 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext)
CXXStructorImplicitParamDecl(nullptr),
CXXStructorImplicitParamValue(nullptr), OutermostConditional(nullptr),
CurLexicalScope(nullptr), TerminateLandingPad(nullptr),
- TerminateHandler(nullptr), TrapBB(nullptr) {
+ TerminateHandler(nullptr), TrapBB(nullptr),
+ ShouldEmitLifetimeMarkers(
+ shouldEmitLifetimeMarkers(CGM.getCodeGenOpts(), CGM.getLangOpts())) {
if (!suppressNewContext)
CGM.getCXXABI().getMangleContext().startNewFunction();
@@ -429,12 +446,24 @@ void CodeGenFunction::EmitFunctionInstrumentation(const char *Fn) {
EmitNounwindRuntimeCall(F, args);
}
-void CodeGenFunction::EmitMCountInstrumentation() {
- llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
-
- llvm::Constant *MCountFn =
- CGM.CreateRuntimeFunction(FTy, getTarget().getMCountName());
- EmitNounwindRuntimeCall(MCountFn);
+static void removeImageAccessQualifier(std::string& TyName) {
+ std::string ReadOnlyQual("__read_only");
+ std::string::size_type ReadOnlyPos = TyName.find(ReadOnlyQual);
+ if (ReadOnlyPos != std::string::npos)
+ // "+ 1" for the space after access qualifier.
+ TyName.erase(ReadOnlyPos, ReadOnlyQual.size() + 1);
+ else {
+ std::string WriteOnlyQual("__write_only");
+ std::string::size_type WriteOnlyPos = TyName.find(WriteOnlyQual);
+ if (WriteOnlyPos != std::string::npos)
+ TyName.erase(WriteOnlyPos, WriteOnlyQual.size() + 1);
+ else {
+ std::string ReadWriteQual("__read_write");
+ std::string::size_type ReadWritePos = TyName.find(ReadWriteQual);
+ if (ReadWritePos != std::string::npos)
+ TyName.erase(ReadWritePos, ReadWriteQual.size() + 1);
+ }
+ }
}
// Returns the address space id that should be produced to the
@@ -549,8 +578,6 @@ static void GenOpenCLArgMetadata(const FunctionDecl *FD, llvm::Function *Fn,
if (ty.isCanonical() && pos != std::string::npos)
typeName.erase(pos+1, 8);
- argTypeNames.push_back(llvm::MDString::get(Context, typeName));
-
std::string baseTypeName;
if (isPipe)
baseTypeName = ty.getCanonicalType()->getAs<PipeType>()
@@ -560,6 +587,17 @@ static void GenOpenCLArgMetadata(const FunctionDecl *FD, llvm::Function *Fn,
baseTypeName =
ty.getUnqualifiedType().getCanonicalType().getAsString(Policy);
+ // Remove access qualifiers on images
+ // (as they are inseparable from type in clang implementation,
+ // but OpenCL spec provides a special query to get access qualifier
+ // via clGetKernelArgInfo with CL_KERNEL_ARG_ACCESS_QUALIFIER):
+ if (ty->isImageType()) {
+ removeImageAccessQualifier(typeName);
+ removeImageAccessQualifier(baseTypeName);
+ }
+
+ argTypeNames.push_back(llvm::MDString::get(Context, typeName));
+
// Turn "unsigned type" to "utype"
pos = baseTypeName.find("unsigned");
if (pos != std::string::npos)
@@ -709,6 +747,20 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
if (SanOpts.has(SanitizerKind::SafeStack))
Fn->addFnAttr(llvm::Attribute::SafeStack);
+ // Ignore TSan memory acesses from within ObjC/ObjC++ dealloc, initialize,
+ // .cxx_destruct and all of their calees at run time.
+ if (SanOpts.has(SanitizerKind::Thread)) {
+ if (const auto *OMD = dyn_cast_or_null<ObjCMethodDecl>(D)) {
+ IdentifierInfo *II = OMD->getSelector().getIdentifierInfoForSlot(0);
+ if (OMD->getMethodFamily() == OMF_dealloc ||
+ OMD->getMethodFamily() == OMF_initialize ||
+ (OMD->getSelector().isUnarySelector() && II->isStr(".cxx_destruct"))) {
+ Fn->addFnAttr("sanitize_thread_no_checking_at_run_time");
+ Fn->removeFnAttr(llvm::Attribute::SanitizeThread);
+ }
+ }
+ }
+
// Apply xray attributes to the function (as a string, for now)
if (D && ShouldXRayInstrumentFunction()) {
if (const auto *XRayAttr = D->getAttr<XRayInstrumentAttr>()) {
@@ -723,27 +775,9 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
}
}
- // Pass inline keyword to optimizer if it appears explicitly on any
- // declaration. Also, in the case of -fno-inline attach NoInline
- // attribute to all functions that are not marked AlwaysInline, or
- // to all functions that are not marked inline or implicitly inline
- // in the case of -finline-hint-functions.
- if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
- const CodeGenOptions& CodeGenOpts = CGM.getCodeGenOpts();
- if (!CodeGenOpts.NoInline) {
- for (auto RI : FD->redecls())
- if (RI->isInlineSpecified()) {
- Fn->addFnAttr(llvm::Attribute::InlineHint);
- break;
- }
- if (CodeGenOpts.getInlining() == CodeGenOptions::OnlyHintInlining &&
- !FD->isInlined() && !Fn->hasFnAttribute(llvm::Attribute::InlineHint))
- Fn->addFnAttr(llvm::Attribute::NoInline);
- } else if (!FD->hasAttr<AlwaysInlineAttr>())
- Fn->addFnAttr(llvm::Attribute::NoInline);
+ if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D))
if (CGM.getLangOpts().OpenMP && FD->hasAttr<OMPDeclareSimdDeclAttr>())
CGM.getOpenMPRuntime().emitDeclareSimdFunction(FD, Fn);
- }
// Add no-jump-tables value.
Fn->addFnAttr("no-jump-tables",
@@ -778,7 +812,7 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D))
if (FD->isMain())
Fn->addFnAttr(llvm::Attribute::NoRecurse);
-
+
llvm::BasicBlock *EntryBB = createBasicBlock("entry", CurFn);
// Create a marker to make it easy to insert allocas into the entryblock
@@ -811,8 +845,12 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
if (ShouldInstrumentFunction())
EmitFunctionInstrumentation("__cyg_profile_func_enter");
+ // Since emitting the mcount call here impacts optimizations such as function
+ // inlining, we just add an attribute to insert a mcount call in backend.
+ // The attribute "counting-function" is set to mcount function name which is
+ // architecture dependent.
if (CGM.getCodeGenOpts().InstrumentForProfiling)
- EmitMCountInstrumentation();
+ Fn->addFnAttr("counting-function", getTarget().getMCountName());
if (RetTy->isVoidType()) {
// Void type; nothing to return.
@@ -1040,6 +1078,13 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
if (SpecDecl->hasBody(SpecDecl))
Loc = SpecDecl->getLocation();
+ Stmt *Body = FD->getBody();
+
+ // Initialize helper which will detect jumps which can cause invalid lifetime
+ // markers.
+ if (Body && ShouldEmitLifetimeMarkers)
+ Bypasses.Init(Body);
+
// Emit the standard function prologue.
StartFunction(GD, ResTy, Fn, FnInfo, Args, Loc, BodyRange.getBegin());
@@ -1069,7 +1114,7 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
// Implicit copy-assignment gets the same special treatment as implicit
// copy-constructors.
emitImplicitAssignmentOperatorBody(Args);
- } else if (Stmt *Body = FD->getBody()) {
+ } else if (Body) {
EmitFunctionBody(Args, Body);
} else
llvm_unreachable("no definition for emitted function");
@@ -1086,8 +1131,8 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
SanitizerScope SanScope(this);
llvm::Value *IsFalse = Builder.getFalse();
EmitCheck(std::make_pair(IsFalse, SanitizerKind::Return),
- "missing_return", EmitCheckSourceLocation(FD->getLocation()),
- None);
+ SanitizerHandler::MissingReturn,
+ EmitCheckSourceLocation(FD->getLocation()), None);
} else if (CGM.getCodeGenOpts().OptimizationLevel == 0) {
EmitTrapCall(llvm::Intrinsic::trap);
}
@@ -1731,6 +1776,7 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) {
case Type::Enum:
case Type::Elaborated:
case Type::TemplateSpecialization:
+ case Type::ObjCTypeParam:
case Type::ObjCObject:
case Type::ObjCInterface:
case Type::ObjCObjectPointer:
@@ -1794,7 +1840,7 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) {
};
EmitCheck(std::make_pair(Builder.CreateICmpSGT(Size, Zero),
SanitizerKind::VLABound),
- "vla_bound_not_positive", StaticArgs, Size);
+ SanitizerHandler::VLABoundNotPositive, StaticArgs, Size);
}
// Always zexting here would be wrong if it weren't
@@ -1854,8 +1900,8 @@ Address CodeGenFunction::EmitMSVAListRef(const Expr *E) {
}
void CodeGenFunction::EmitDeclRefExprDbgValue(const DeclRefExpr *E,
- llvm::Constant *Init) {
- assert (Init && "Invalid DeclRefExpr initializer!");
+ const APValue &Init) {
+ assert(!Init.isUninit() && "Invalid DeclRefExpr initializer!");
if (CGDebugInfo *Dbg = getDebugInfo())
if (CGM.getCodeGenOpts().getDebugInfo() >= codegenoptions::LimitedDebugInfo)
Dbg->EmitGlobalVariable(E->getDecl(), Init);
@@ -2046,3 +2092,10 @@ void CodeGenFunction::EmitSanitizerStatReport(llvm::SanitizerStatKind SSK) {
IRB.SetCurrentDebugLocation(Builder.getCurrentDebugLocation());
CGM.getSanStats().create(IRB, SSK);
}
+
+llvm::DebugLoc CodeGenFunction::SourceLocToDebugLoc(SourceLocation Location) {
+ if (CGDebugInfo *DI = getDebugInfo())
+ return DI->SourceLocToDebugLoc(Location);
+
+ return llvm::DebugLoc();
+}
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index fb19a2657c9c..222d0e97968a 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -21,6 +21,7 @@
#include "CodeGenModule.h"
#include "CodeGenPGO.h"
#include "EHScopeStack.h"
+#include "VarBypassDetector.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
@@ -77,6 +78,7 @@ class ObjCAutoreleasePoolStmt;
namespace CodeGen {
class CodeGenTypes;
+class CGCallee;
class CGFunctionInfo;
class CGRecordLayout;
class CGBlockInfo;
@@ -88,6 +90,7 @@ class BlockFieldFlags;
class RegionCodeGenTy;
class TargetCodeGenInfo;
struct OMPTaskDataTy;
+struct CGCoroData;
/// The kind of evaluation to perform on values of a particular
/// type. Basically, is the code in CGExprScalar, CGExprComplex, or
@@ -100,6 +103,32 @@ enum TypeEvaluationKind {
TEK_Aggregate
};
+#define LIST_SANITIZER_CHECKS \
+ SANITIZER_CHECK(AddOverflow, add_overflow, 0) \
+ SANITIZER_CHECK(BuiltinUnreachable, builtin_unreachable, 0) \
+ SANITIZER_CHECK(CFICheckFail, cfi_check_fail, 0) \
+ SANITIZER_CHECK(DivremOverflow, divrem_overflow, 0) \
+ SANITIZER_CHECK(DynamicTypeCacheMiss, dynamic_type_cache_miss, 0) \
+ SANITIZER_CHECK(FloatCastOverflow, float_cast_overflow, 0) \
+ SANITIZER_CHECK(FunctionTypeMismatch, function_type_mismatch, 0) \
+ SANITIZER_CHECK(LoadInvalidValue, load_invalid_value, 0) \
+ SANITIZER_CHECK(MissingReturn, missing_return, 0) \
+ SANITIZER_CHECK(MulOverflow, mul_overflow, 0) \
+ SANITIZER_CHECK(NegateOverflow, negate_overflow, 0) \
+ SANITIZER_CHECK(NonnullArg, nonnull_arg, 0) \
+ SANITIZER_CHECK(NonnullReturn, nonnull_return, 0) \
+ SANITIZER_CHECK(OutOfBounds, out_of_bounds, 0) \
+ SANITIZER_CHECK(ShiftOutOfBounds, shift_out_of_bounds, 0) \
+ SANITIZER_CHECK(SubOverflow, sub_overflow, 0) \
+ SANITIZER_CHECK(TypeMismatch, type_mismatch, 0) \
+ SANITIZER_CHECK(VLABoundNotPositive, vla_bound_not_positive, 0)
+
+enum SanitizerHandler {
+#define SANITIZER_CHECK(Enum, Name, Version) Enum,
+ LIST_SANITIZER_CHECKS
+#undef SANITIZER_CHECK
+};
+
/// CodeGenFunction - This class organizes the per-function state that is used
/// while generating LLVM code.
class CodeGenFunction : public CodeGenTypeCache {
@@ -140,6 +169,10 @@ public:
LoopInfoStack LoopStack;
CGBuilderTy Builder;
+ // Stores variables for which we can't generate correct lifetime markers
+ // because of jumps.
+ VarBypassDetector Bypasses;
+
/// \brief CGBuilder insert helper. This function is called after an
/// instruction is created using Builder.
void InsertHelper(llvm::Instruction *I, const llvm::Twine &Name,
@@ -155,6 +188,16 @@ public:
QualType FnRetTy;
llvm::Function *CurFn;
+ // 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
+ // in this header.
+ struct CGCoroInfo {
+ std::unique_ptr<CGCoroData> Data;
+ CGCoroInfo();
+ ~CGCoroInfo();
+ };
+ CGCoroInfo CurCoro;
+
/// CurGD - The GlobalDecl for the current function being compiled.
GlobalDecl CurGD;
@@ -430,7 +473,7 @@ public:
LifetimeExtendedCleanupStack.resize(
LifetimeExtendedCleanupStack.size() + sizeof(Header) + Header.Size);
- static_assert(sizeof(Header) % llvm::AlignOf<T>::Alignment == 0,
+ static_assert(sizeof(Header) % alignof(T) == 0,
"Cleanup will be allocated on misaligned address");
char *Buffer = &LifetimeExtendedCleanupStack[OldSize];
new (Buffer) LifetimeExtendedCleanupHeader(Header);
@@ -901,6 +944,17 @@ public:
e->getCommon());
}
+ /// Build the opaque value mapping for an OpaqueValueExpr whose source
+ /// expression is set to the expression the OVE represents.
+ OpaqueValueMapping(CodeGenFunction &CGF, const OpaqueValueExpr *OV)
+ : CGF(CGF) {
+ if (OV) {
+ assert(OV->getSourceExpr() && "wrong form of OpaqueValueMapping used "
+ "for OVE with no source expression");
+ Data = OpaqueValueMappingData::bind(CGF, OV, OV->getSourceExpr());
+ }
+ }
+
OpaqueValueMapping(CodeGenFunction &CGF,
const OpaqueValueExpr *opaqueValue,
LValue lvalue)
@@ -1166,6 +1220,23 @@ public:
CharUnits OldCXXThisAlignment;
};
+ /// The scope of an ArrayInitLoopExpr. Within this scope, the value of the
+ /// current loop index is overridden.
+ class ArrayInitLoopExprScope {
+ public:
+ ArrayInitLoopExprScope(CodeGenFunction &CGF, llvm::Value *Index)
+ : CGF(CGF), OldArrayInitIndex(CGF.ArrayInitIndex) {
+ CGF.ArrayInitIndex = Index;
+ }
+ ~ArrayInitLoopExprScope() {
+ CGF.ArrayInitIndex = OldArrayInitIndex;
+ }
+
+ private:
+ CodeGenFunction &CGF;
+ llvm::Value *OldArrayInitIndex;
+ };
+
class InlinedInheritingConstructorScope {
public:
InlinedInheritingConstructorScope(CodeGenFunction &CGF, GlobalDecl GD)
@@ -1234,6 +1305,10 @@ private:
/// this expression.
Address CXXDefaultInitExprThis = Address::invalid();
+ /// The current array initialization index when evaluating an
+ /// ArrayInitIndexExpr within an ArrayInitLoopExpr.
+ llvm::Value *ArrayInitIndex = nullptr;
+
/// The values of function arguments to use when evaluating
/// CXXInheritedCtorInitExprs within this context.
CallArgList CXXInheritedCtorInitExprArgs;
@@ -1263,6 +1338,9 @@ private:
llvm::BasicBlock *TerminateHandler;
llvm::BasicBlock *TrapBB;
+ /// True if we need emit the life-time markers.
+ const bool ShouldEmitLifetimeMarkers;
+
/// Add a kernel metadata node to the named metadata node 'opencl.kernels'.
/// In the kernel metadata node, reference the kernel function and metadata
/// nodes for its optional attribute qualifiers (OpenCL 1.1 6.7.2):
@@ -1421,7 +1499,6 @@ public:
//===--------------------------------------------------------------------===//
llvm::Value *EmitBlockLiteral(const BlockExpr *);
- llvm::Value *EmitBlockLiteral(const CGBlockInfo &Info);
static void destroyBlockInfos(CGBlockInfo *info);
llvm::Function *GenerateBlockFunction(GlobalDecl GD,
@@ -1503,7 +1580,8 @@ public:
void StartThunk(llvm::Function *Fn, GlobalDecl GD,
const CGFunctionInfo &FnInfo);
- void EmitCallAndReturnForThunk(llvm::Value *Callee, const ThunkInfo *Thunk);
+ void EmitCallAndReturnForThunk(llvm::Constant *Callee,
+ const ThunkInfo *Thunk);
void FinishThunk();
@@ -1522,8 +1600,7 @@ public:
void EmitCtorPrologue(const CXXConstructorDecl *CD, CXXCtorType Type,
FunctionArgList &Args);
- void EmitInitializerForField(FieldDecl *Field, LValue LHS, Expr *Init,
- ArrayRef<VarDecl *> ArrayIndexes);
+ void EmitInitializerForField(FieldDecl *Field, LValue LHS, Expr *Init);
/// Struct with all informations about dynamic [sub]class needed to set vptr.
struct VPtr {
@@ -1932,6 +2009,9 @@ public:
return it->second;
}
+ /// Get the index of the current ArrayInitLoopExpr, if any.
+ llvm::Value *getArrayInitIndex() { return ArrayInitIndex; }
+
/// getAccessedFieldNo - Given an encoded value and a result number, return
/// the input field number being accessed.
static unsigned getAccessedFieldNo(unsigned Idx, const llvm::Constant *Elts);
@@ -2110,7 +2190,8 @@ public:
void EmitCXXDeleteExpr(const CXXDeleteExpr *E);
void EmitDeleteCall(const FunctionDecl *DeleteFD, llvm::Value *Ptr,
- QualType DeleteTy);
+ QualType DeleteTy, llvm::Value *NumElements = nullptr,
+ CharUnits CookieSize = CharUnits());
RValue EmitBuiltinNewDeleteCall(const FunctionProtoType *Type,
const Expr *Arg, bool IsDelete);
@@ -2179,6 +2260,10 @@ public:
OffsetValue);
}
+ /// Converts Location to a DebugLoc, if debug information is enabled.
+ llvm::DebugLoc SourceLocToDebugLoc(SourceLocation Location);
+
+
//===--------------------------------------------------------------------===//
// Declaration Emission
//===--------------------------------------------------------------------===//
@@ -2195,7 +2280,6 @@ public:
void EmitScalarInit(const Expr *init, const ValueDecl *D, LValue lvalue,
bool capturedByInit);
- void EmitScalarInit(llvm::Value *init, LValue lvalue);
typedef void SpecialInitFn(CodeGenFunction &Init, const VarDecl &D,
llvm::Value *Address);
@@ -2378,6 +2462,9 @@ public:
void EmitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt &S);
void EmitObjCAutoreleasePoolStmt(const ObjCAutoreleasePoolStmt &S);
+ void EmitCoroutineBody(const CoroutineBodyStmt &S);
+ RValue EmitCoroutineIntrinsic(const CallExpr *E, unsigned int IID);
+
void EnterCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock = false);
void ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock = false);
@@ -2480,6 +2567,9 @@ public:
OMPPrivateScope &PrivateScope);
void EmitOMPPrivateClause(const OMPExecutableDirective &D,
OMPPrivateScope &PrivateScope);
+ 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
/// generated at the start of outlined functions for directives:
/// \code
@@ -2596,6 +2686,19 @@ public:
void EmitOMPDistributeSimdDirective(const OMPDistributeSimdDirective &S);
void EmitOMPTargetParallelForSimdDirective(
const OMPTargetParallelForSimdDirective &S);
+ void EmitOMPTargetSimdDirective(const OMPTargetSimdDirective &S);
+ void EmitOMPTeamsDistributeDirective(const OMPTeamsDistributeDirective &S);
+ void
+ EmitOMPTeamsDistributeSimdDirective(const OMPTeamsDistributeSimdDirective &S);
+ void EmitOMPTeamsDistributeParallelForSimdDirective(
+ const OMPTeamsDistributeParallelForSimdDirective &S);
+ void EmitOMPTeamsDistributeParallelForDirective(
+ const OMPTeamsDistributeParallelForDirective &S);
+ void EmitOMPTargetTeamsDirective(const OMPTargetTeamsDirective &S);
+ void EmitOMPTargetTeamsDistributeDirective(
+ const OMPTargetTeamsDistributeDirective &S);
+ void EmitOMPTargetTeamsDistributeParallelForDirective(
+ const OMPTargetTeamsDistributeParallelForDirective &S);
/// Emit outlined function for the target directive.
static std::pair<llvm::Function * /*OutlinedFn*/,
@@ -2626,6 +2729,9 @@ public:
OMPPrivateScope &LoopScope);
private:
+ /// Helpers for blocks
+ llvm::Value *EmitBlockLiteral(const CGBlockInfo &Info);
+
/// Helpers for the OpenMP loop directives.
void EmitOMPLoopBody(const OMPLoopDirective &D, JumpDest LoopExit);
void EmitOMPSimdInit(const OMPLoopDirective &D, bool IsMonotonic = false);
@@ -2893,7 +2999,7 @@ public:
LValue EmitStmtExprLValue(const StmtExpr *E);
LValue EmitPointerToDataMemberBinaryExpr(const BinaryOperator *E);
LValue EmitObjCSelectorLValue(const ObjCSelectorExpr *E);
- void EmitDeclRefExprDbgValue(const DeclRefExpr *E, llvm::Constant *Init);
+ void EmitDeclRefExprDbgValue(const DeclRefExpr *E, const APValue &Init);
//===--------------------------------------------------------------------===//
// Scalar Expression Emission
@@ -2902,17 +3008,17 @@ public:
/// EmitCall - Generate a call of the given function, expecting the given
/// result type, and using the given argument list which specifies both the
/// LLVM arguments and the types they were derived from.
- RValue EmitCall(const CGFunctionInfo &FnInfo, llvm::Value *Callee,
+ RValue EmitCall(const CGFunctionInfo &CallInfo, const CGCallee &Callee,
ReturnValueSlot ReturnValue, const CallArgList &Args,
- CGCalleeInfo CalleeInfo = CGCalleeInfo(),
llvm::Instruction **callOrInvoke = nullptr);
- RValue EmitCall(QualType FnType, llvm::Value *Callee, const CallExpr *E,
+ RValue EmitCall(QualType FnType, const CGCallee &Callee, const CallExpr *E,
ReturnValueSlot ReturnValue,
- CGCalleeInfo CalleeInfo = CGCalleeInfo(),
llvm::Value *Chain = nullptr);
RValue EmitCallExpr(const CallExpr *E,
ReturnValueSlot ReturnValue = ReturnValueSlot());
+ RValue EmitSimpleCallExpr(const CallExpr *E, ReturnValueSlot ReturnValue);
+ CGCallee EmitCallee(const Expr *E);
void checkTargetFeatures(const CallExpr *E, const FunctionDecl *TargetDecl);
@@ -2938,20 +3044,23 @@ public:
void EmitNoreturnRuntimeCallOrInvoke(llvm::Value *callee,
ArrayRef<llvm::Value*> args);
- llvm::Value *BuildAppleKextVirtualCall(const CXXMethodDecl *MD,
- NestedNameSpecifier *Qual,
- llvm::Type *Ty);
+ CGCallee BuildAppleKextVirtualCall(const CXXMethodDecl *MD,
+ NestedNameSpecifier *Qual,
+ llvm::Type *Ty);
- llvm::Value *BuildAppleKextVirtualDestructorCall(const CXXDestructorDecl *DD,
- CXXDtorType Type,
- const CXXRecordDecl *RD);
+ CGCallee BuildAppleKextVirtualDestructorCall(const CXXDestructorDecl *DD,
+ CXXDtorType Type,
+ const CXXRecordDecl *RD);
RValue
- EmitCXXMemberOrOperatorCall(const CXXMethodDecl *MD, llvm::Value *Callee,
+ EmitCXXMemberOrOperatorCall(const CXXMethodDecl *Method,
+ const CGCallee &Callee,
ReturnValueSlot ReturnValue, llvm::Value *This,
llvm::Value *ImplicitParam,
- QualType ImplicitParamTy, const CallExpr *E);
- RValue EmitCXXDestructorCall(const CXXDestructorDecl *DD, llvm::Value *Callee,
+ QualType ImplicitParamTy, const CallExpr *E,
+ CallArgList *RtlArgs);
+ RValue EmitCXXDestructorCall(const CXXDestructorDecl *DD,
+ const CGCallee &Callee,
llvm::Value *This, llvm::Value *ImplicitParam,
QualType ImplicitParamTy, const CallExpr *E,
StructorType Type);
@@ -2974,6 +3083,7 @@ public:
RValue EmitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E,
const CXXMethodDecl *MD,
ReturnValueSlot ReturnValue);
+ RValue EmitCXXPseudoDestructorExpr(const CXXPseudoDestructorExpr *E);
RValue EmitCUDAKernelCallExpr(const CUDAKernelCallExpr *E,
ReturnValueSlot ReturnValue);
@@ -3029,6 +3139,12 @@ public:
llvm::Value *EmitWebAssemblyBuiltinExpr(unsigned BuiltinID,
const CallExpr *E);
+private:
+ enum class MSVCIntrin;
+
+public:
+ llvm::Value *EmitMSVCBuiltinExpr(MSVCIntrin BuiltinID, const CallExpr *E);
+
llvm::Value *EmitObjCProtocolExpr(const ObjCProtocolExpr *E);
llvm::Value *EmitObjCStringLiteral(const ObjCStringLiteral *E);
llvm::Value *EmitObjCBoxedExpr(const ObjCBoxedExpr *E);
@@ -3292,7 +3408,7 @@ public:
/// sanitizer runtime with the provided arguments, and create a conditional
/// branch to it.
void EmitCheck(ArrayRef<std::pair<llvm::Value *, SanitizerMask>> Checked,
- StringRef CheckName, ArrayRef<llvm::Constant *> StaticArgs,
+ SanitizerHandler Check, ArrayRef<llvm::Constant *> StaticArgs,
ArrayRef<llvm::Value *> DynamicArgs);
/// \brief Emit a slow path cross-DSO CFI check which calls __cfi_slowpath
@@ -3400,12 +3516,22 @@ public:
static bool isObjCMethodWithTypeParams(const T *) { return false; }
#endif
+ enum class EvaluationOrder {
+ ///! No language constraints on evaluation order.
+ Default,
+ ///! Language semantics require left-to-right evaluation.
+ ForceLeftToRight,
+ ///! Language semantics require right-to-left evaluation.
+ ForceRightToLeft
+ };
+
/// EmitCallArgs - Emit call arguments for a function.
template <typename T>
void EmitCallArgs(CallArgList &Args, const T *CallArgTypeInfo,
llvm::iterator_range<CallExpr::const_arg_iterator> ArgRange,
const FunctionDecl *CalleeDecl = nullptr,
- unsigned ParamsToSkip = 0) {
+ unsigned ParamsToSkip = 0,
+ EvaluationOrder Order = EvaluationOrder::Default) {
SmallVector<QualType, 16> ArgTypes;
CallExpr::const_arg_iterator Arg = ArgRange.begin();
@@ -3445,13 +3571,14 @@ public:
for (auto *A : llvm::make_range(Arg, ArgRange.end()))
ArgTypes.push_back(getVarArgType(A));
- EmitCallArgs(Args, ArgTypes, ArgRange, CalleeDecl, ParamsToSkip);
+ EmitCallArgs(Args, ArgTypes, ArgRange, CalleeDecl, ParamsToSkip, Order);
}
void EmitCallArgs(CallArgList &Args, ArrayRef<QualType> ArgTypes,
llvm::iterator_range<CallExpr::const_arg_iterator> ArgRange,
const FunctionDecl *CalleeDecl = nullptr,
- unsigned ParamsToSkip = 0);
+ unsigned ParamsToSkip = 0,
+ EvaluationOrder Order = EvaluationOrder::Default);
/// EmitPointerWithAlignment - Given an expression with a pointer
/// type, emit the value and compute our best estimate of the
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 0161cfb611ca..ab29d2dbb566 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -24,6 +24,7 @@
#include "CodeGenFunction.h"
#include "CodeGenPGO.h"
#include "CodeGenTBAA.h"
+#include "ConstantBuilder.h"
#include "CoverageMappingGen.h"
#include "TargetInfo.h"
#include "clang/AST/ASTContext.h"
@@ -43,7 +44,6 @@
#include "clang/Basic/Version.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "clang/Sema/SemaDiagnostic.h"
-#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/Triple.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/CallingConv.h"
@@ -102,10 +102,13 @@ CodeGenModule::CodeGenModule(ASTContext &C, const HeaderSearchOptions &HSO,
PointerWidthInBits = C.getTargetInfo().getPointerWidth(0);
PointerAlignInBytes =
C.toCharUnitsFromBits(C.getTargetInfo().getPointerAlign(0)).getQuantity();
+ SizeSizeInBytes =
+ C.toCharUnitsFromBits(C.getTargetInfo().getMaxPointerWidth()).getQuantity();
IntAlignInBytes =
C.toCharUnitsFromBits(C.getTargetInfo().getIntAlign()).getQuantity();
IntTy = llvm::IntegerType::get(LLVMContext, C.getTargetInfo().getIntWidth());
- IntPtrTy = llvm::IntegerType::get(LLVMContext, PointerWidthInBits);
+ IntPtrTy = llvm::IntegerType::get(LLVMContext,
+ C.getTargetInfo().getMaxPointerWidth());
Int8PtrTy = Int8Ty->getPointerTo(0);
Int8PtrPtrTy = Int8PtrTy->getPointerTo(0);
@@ -187,8 +190,7 @@ void CodeGenModule::createOpenCLRuntime() {
void CodeGenModule::createOpenMPRuntime() {
// Select a specialized code generation class based on the target, if any.
// If it does not exist use the default implementation.
- switch (getTarget().getTriple().getArch()) {
-
+ switch (getTriple().getArch()) {
case llvm::Triple::nvptx:
case llvm::Triple::nvptx64:
assert(getLangOpts().OpenMPIsDevice &&
@@ -469,7 +471,7 @@ void CodeGenModule::Release() {
getModule().addModuleFlag(llvm::Module::Override, "Cross-DSO CFI", 1);
}
- if (LangOpts.CUDAIsDevice && getTarget().getTriple().isNVPTX()) {
+ 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.)
@@ -672,7 +674,16 @@ StringRef CodeGenModule::getMangledName(GlobalDecl GD) {
} else {
IdentifierInfo *II = ND->getIdentifier();
assert(II && "Attempt to mangle unnamed decl.");
- Str = II->getName();
+ const auto *FD = dyn_cast<FunctionDecl>(ND);
+
+ if (FD &&
+ FD->getType()->castAs<FunctionType>()->getCallConv() == CC_X86RegCall) {
+ llvm::raw_svector_ostream Out(Buffer);
+ Out << "__regcall3__" << II->getName();
+ Str = Out.str();
+ } else {
+ Str = II->getName();
+ }
}
// Keep the first result in the case of a mangling collision.
@@ -720,7 +731,9 @@ void CodeGenModule::AddGlobalDtor(llvm::Function *Dtor, int Priority) {
GlobalDtors.push_back(Structor(Priority, Dtor, nullptr));
}
-void CodeGenModule::EmitCtorList(const CtorList &Fns, const char *GlobalName) {
+void CodeGenModule::EmitCtorList(CtorList &Fns, const char *GlobalName) {
+ if (Fns.empty()) return;
+
// Ctor function type is void()*.
llvm::FunctionType* CtorFTy = llvm::FunctionType::get(VoidTy, false);
llvm::Type *CtorPFTy = llvm::PointerType::getUnqual(CtorFTy);
@@ -730,24 +743,29 @@ void CodeGenModule::EmitCtorList(const CtorList &Fns, const char *GlobalName) {
Int32Ty, llvm::PointerType::getUnqual(CtorFTy), VoidPtrTy, nullptr);
// Construct the constructor and destructor arrays.
- SmallVector<llvm::Constant *, 8> Ctors;
+ ConstantInitBuilder builder(*this);
+ auto ctors = builder.beginArray(CtorStructTy);
for (const auto &I : Fns) {
- llvm::Constant *S[] = {
- llvm::ConstantInt::get(Int32Ty, I.Priority, false),
- llvm::ConstantExpr::getBitCast(I.Initializer, CtorPFTy),
- (I.AssociatedData
- ? llvm::ConstantExpr::getBitCast(I.AssociatedData, VoidPtrTy)
- : llvm::Constant::getNullValue(VoidPtrTy))};
- Ctors.push_back(llvm::ConstantStruct::get(CtorStructTy, S));
+ auto ctor = ctors.beginStruct(CtorStructTy);
+ ctor.addInt(Int32Ty, I.Priority);
+ ctor.add(llvm::ConstantExpr::getBitCast(I.Initializer, CtorPFTy));
+ if (I.AssociatedData)
+ ctor.add(llvm::ConstantExpr::getBitCast(I.AssociatedData, VoidPtrTy));
+ else
+ ctor.addNullPointer(VoidPtrTy);
+ ctor.finishAndAddTo(ctors);
}
- if (!Ctors.empty()) {
- llvm::ArrayType *AT = llvm::ArrayType::get(CtorStructTy, Ctors.size());
- new llvm::GlobalVariable(TheModule, AT, false,
- llvm::GlobalValue::AppendingLinkage,
- llvm::ConstantArray::get(AT, Ctors),
- GlobalName);
- }
+ auto list =
+ ctors.finishAndCreateGlobal(GlobalName, getPointerAlign(),
+ /*constant*/ false,
+ llvm::GlobalValue::AppendingLinkage);
+
+ // The LTO linker doesn't seem to like it when we set an alignment
+ // on appending variables. Take it off as a workaround.
+ list->setAlignment(0);
+
+ Fns.clear();
}
llvm::GlobalValue::LinkageTypes
@@ -800,14 +818,7 @@ llvm::ConstantInt *CodeGenModule::CreateCrossDsoCfiTypeId(llvm::Metadata *MD) {
llvm::MDString *MDS = dyn_cast<llvm::MDString>(MD);
if (!MDS) return nullptr;
- llvm::MD5 md5;
- llvm::MD5::MD5Result result;
- md5.update(MDS->getString());
- md5.final(result);
- uint64_t id = 0;
- for (int i = 0; i < 8; ++i)
- id |= static_cast<uint64_t>(result[i]) << (i * 8);
- return llvm::ConstantInt::get(Int64Ty, id);
+ return llvm::ConstantInt::get(Int64Ty, llvm::MD5Hash(MDS->getString()));
}
void CodeGenModule::setFunctionDefinitionAttributes(const FunctionDecl *D,
@@ -864,6 +875,13 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
B.addAttribute(llvm::Attribute::StackProtectReq);
if (!D) {
+ // If we don't have a declaration to control inlining, the function isn't
+ // explicitly marked as alwaysinline for semantic reasons, and inlining is
+ // disabled, mark the function as noinline.
+ if (!F->hasFnAttribute(llvm::Attribute::AlwaysInline) &&
+ CodeGenOpts.getInlining() == CodeGenOptions::OnlyAlwaysInlining)
+ B.addAttribute(llvm::Attribute::NoInline);
+
F->addAttributes(llvm::AttributeSet::FunctionIndex,
llvm::AttributeSet::get(
F->getContext(),
@@ -871,7 +889,23 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
return;
}
- if (D->hasAttr<NakedAttr>()) {
+ if (D->hasAttr<OptimizeNoneAttr>()) {
+ B.addAttribute(llvm::Attribute::OptimizeNone);
+
+ // OptimizeNone implies noinline; we should not be inlining such functions.
+ B.addAttribute(llvm::Attribute::NoInline);
+ assert(!F->hasFnAttribute(llvm::Attribute::AlwaysInline) &&
+ "OptimizeNone and AlwaysInline on same function!");
+
+ // We still need to handle naked functions even though optnone subsumes
+ // much of their semantics.
+ if (D->hasAttr<NakedAttr>())
+ B.addAttribute(llvm::Attribute::Naked);
+
+ // OptimizeNone wins over OptimizeForSize and MinSize.
+ F->removeFnAttr(llvm::Attribute::OptimizeForSize);
+ F->removeFnAttr(llvm::Attribute::MinSize);
+ } else if (D->hasAttr<NakedAttr>()) {
// Naked implies noinline: we should not be inlining such functions.
B.addAttribute(llvm::Attribute::Naked);
B.addAttribute(llvm::Attribute::NoInline);
@@ -880,41 +914,47 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
} else if (D->hasAttr<NoInlineAttr>()) {
B.addAttribute(llvm::Attribute::NoInline);
} else if (D->hasAttr<AlwaysInlineAttr>() &&
- !F->getAttributes().hasAttribute(llvm::AttributeSet::FunctionIndex,
- llvm::Attribute::NoInline)) {
+ !F->hasFnAttribute(llvm::Attribute::NoInline)) {
// (noinline wins over always_inline, and we can't specify both in IR)
B.addAttribute(llvm::Attribute::AlwaysInline);
+ } else if (CodeGenOpts.getInlining() == CodeGenOptions::OnlyAlwaysInlining) {
+ // If we're not inlining, then force everything that isn't always_inline to
+ // carry an explicit noinline attribute.
+ if (!F->hasFnAttribute(llvm::Attribute::AlwaysInline))
+ B.addAttribute(llvm::Attribute::NoInline);
+ } else {
+ // Otherwise, propagate the inline hint attribute and potentially use its
+ // absence to mark things as noinline.
+ if (auto *FD = dyn_cast<FunctionDecl>(D)) {
+ if (any_of(FD->redecls(), [&](const FunctionDecl *Redecl) {
+ return Redecl->isInlineSpecified();
+ })) {
+ B.addAttribute(llvm::Attribute::InlineHint);
+ } else if (CodeGenOpts.getInlining() ==
+ CodeGenOptions::OnlyHintInlining &&
+ !FD->isInlined() &&
+ !F->hasFnAttribute(llvm::Attribute::AlwaysInline)) {
+ B.addAttribute(llvm::Attribute::NoInline);
+ }
+ }
}
- if (D->hasAttr<ColdAttr>()) {
- if (!D->hasAttr<OptimizeNoneAttr>())
+ // Add other optimization related attributes if we are optimizing this
+ // function.
+ if (!D->hasAttr<OptimizeNoneAttr>()) {
+ if (D->hasAttr<ColdAttr>()) {
B.addAttribute(llvm::Attribute::OptimizeForSize);
- B.addAttribute(llvm::Attribute::Cold);
- }
+ B.addAttribute(llvm::Attribute::Cold);
+ }
- if (D->hasAttr<MinSizeAttr>())
- B.addAttribute(llvm::Attribute::MinSize);
+ if (D->hasAttr<MinSizeAttr>())
+ B.addAttribute(llvm::Attribute::MinSize);
+ }
F->addAttributes(llvm::AttributeSet::FunctionIndex,
llvm::AttributeSet::get(
F->getContext(), llvm::AttributeSet::FunctionIndex, B));
- if (D->hasAttr<OptimizeNoneAttr>()) {
- // OptimizeNone implies noinline; we should not be inlining such functions.
- F->addFnAttr(llvm::Attribute::OptimizeNone);
- F->addFnAttr(llvm::Attribute::NoInline);
-
- // OptimizeNone wins over OptimizeForSize, MinSize, AlwaysInline.
- F->removeFnAttr(llvm::Attribute::OptimizeForSize);
- F->removeFnAttr(llvm::Attribute::MinSize);
- assert(!F->hasFnAttribute(llvm::Attribute::AlwaysInline) &&
- "OptimizeNone and AlwaysInline on same function!");
-
- // Attribute 'inlinehint' has no effect on 'optnone' functions.
- // Explicitly remove it from the set of function attributes.
- F->removeFnAttr(llvm::Attribute::InlineHint);
- }
-
unsigned alignment = D->getMaxAlignment() / Context.getCharWidth();
if (alignment)
F->setAlignment(alignment);
@@ -927,6 +967,11 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
if (F->getAlignment() < 2 && isa<CXXMethodDecl>(D))
F->setAlignment(2);
}
+
+ // 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);
}
void CodeGenModule::SetCommonAttributes(const Decl *D,
@@ -1009,10 +1054,6 @@ void CodeGenModule::CreateFunctionTypeMetadata(const FunctionDecl *FD,
// Additionally, if building with cross-DSO support...
if (CodeGenOpts.SanitizeCfiCrossDso) {
- // Don't emit entries for function declarations. In cross-DSO mode these are
- // handled with better precision at run time.
- if (!FD->hasBody())
- return;
// Skip available_externally functions. They won't be codegen'ed in the
// current module anyway.
if (getContext().GetGVALinkageForFunction(FD) == GVA_AvailableExternally)
@@ -1047,8 +1088,7 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F,
// where substantial code, including the libstdc++ dylib, was compiled with
// GCC and does not actually return "this".
if (!IsThunk && getCXXABI().HasThisReturn(GD) &&
- !(getTarget().getTriple().isiOS() &&
- getTarget().getTriple().isOSVersionLT(6))) {
+ !(getTriple().isiOS() && getTriple().isOSVersionLT(6))) {
assert(!F->arg_empty() &&
F->arg_begin()->getType()
->canLosslesslyBitCastTo(F->getReturnType()) &&
@@ -1086,7 +1126,10 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F,
if (MD->isVirtual())
F->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
- CreateFunctionTypeMetadata(FD, 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);
}
void CodeGenModule::addUsedGlobal(llvm::GlobalValue *GV) {
@@ -1282,7 +1325,7 @@ void CodeGenModule::EmitDeferred() {
// might had been created for another decl with the same mangled name but
// different type.
llvm::GlobalValue *GV = dyn_cast<llvm::GlobalValue>(
- GetAddrOfGlobal(D, /*IsForDefinition=*/true));
+ GetAddrOfGlobal(D, ForDefinition));
// In case of different address spaces, we may still get a cast, even with
// IsForDefinition equal to true. Query mangled names table to get
@@ -1681,6 +1724,8 @@ namespace {
: public RecursiveASTVisitor<DLLImportFunctionVisitor> {
bool SafeToInline = true;
+ bool shouldVisitImplicitCode() const { return true; }
+
bool VisitVarDecl(VarDecl *VD) {
// A thread-local variable cannot be imported.
SafeToInline = !VD->getTLSKind();
@@ -1696,6 +1741,10 @@ namespace {
SafeToInline = !V->hasGlobalStorage() || V->hasAttr<DLLImportAttr>();
return SafeToInline;
}
+ bool VisitCXXConstructExpr(CXXConstructExpr *E) {
+ SafeToInline = E->getConstructor()->hasAttr<DLLImportAttr>();
+ return SafeToInline;
+ }
bool VisitCXXDeleteExpr(CXXDeleteExpr *E) {
SafeToInline = E->getOperatorDelete()->hasAttr<DLLImportAttr>();
return SafeToInline;
@@ -1728,8 +1777,17 @@ CodeGenModule::isTriviallyRecursive(const FunctionDecl *FD) {
return Walker.Result;
}
-bool
-CodeGenModule::shouldEmitFunction(GlobalDecl GD) {
+// Check if T is a class type with a destructor that's not dllimport.
+static bool HasNonDllImportDtor(QualType T) {
+ if (const RecordType *RT = dyn_cast<RecordType>(T))
+ if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl()))
+ if (RD->getDestructor() && !RD->getDestructor()->hasAttr<DLLImportAttr>())
+ return true;
+
+ return false;
+}
+
+bool CodeGenModule::shouldEmitFunction(GlobalDecl GD) {
if (getFunctionLinkage(GD) != llvm::Function::AvailableExternallyLinkage)
return true;
const auto *F = cast<FunctionDecl>(GD.getDecl());
@@ -1742,6 +1800,18 @@ CodeGenModule::shouldEmitFunction(GlobalDecl GD) {
Visitor.TraverseFunctionDecl(const_cast<FunctionDecl*>(F));
if (!Visitor.SafeToInline)
return false;
+
+ if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(F)) {
+ // Implicit destructor invocations aren't captured in the AST, so the
+ // check above can't see them. Check for them manually here.
+ for (const Decl *Member : Dtor->getParent()->decls())
+ if (isa<FieldDecl>(Member))
+ if (HasNonDllImportDtor(cast<FieldDecl>(Member)->getType()))
+ return false;
+ for (const CXXBaseSpecifier &B : Dtor->getParent()->bases())
+ if (HasNonDllImportDtor(B.getType()))
+ return false;
+ }
}
// PR9614. Avoid cases where the source code is lying to us. An available
@@ -1823,7 +1893,7 @@ CodeGenModule::GetOrCreateLLVMFunction(StringRef MangledName,
GlobalDecl GD, bool ForVTable,
bool DontDefer, bool IsThunk,
llvm::AttributeSet ExtraAttrs,
- bool IsForDefinition) {
+ ForDefinition_t IsForDefinition) {
const Decl *D = GD.getDecl();
// Lookup the entry, lazily creating it if necessary.
@@ -1983,7 +2053,7 @@ llvm::Constant *CodeGenModule::GetAddrOfFunction(GlobalDecl GD,
llvm::Type *Ty,
bool ForVTable,
bool DontDefer,
- bool IsForDefinition) {
+ ForDefinition_t IsForDefinition) {
// If there was no specific requested type, just convert it now.
if (!Ty) {
const auto *FD = cast<FunctionDecl>(GD.getDecl());
@@ -1997,18 +2067,70 @@ llvm::Constant *CodeGenModule::GetAddrOfFunction(GlobalDecl GD,
IsForDefinition);
}
+static const FunctionDecl *
+GetRuntimeFunctionDecl(ASTContext &C, StringRef Name) {
+ TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl();
+ DeclContext *DC = TranslationUnitDecl::castToDeclContext(TUDecl);
+
+ IdentifierInfo &CII = C.Idents.get(Name);
+ for (const auto &Result : DC->lookup(&CII))
+ if (const auto FD = dyn_cast<FunctionDecl>(Result))
+ return FD;
+
+ if (!C.getLangOpts().CPlusPlus)
+ return nullptr;
+
+ // Demangle the premangled name from getTerminateFn()
+ IdentifierInfo &CXXII =
+ (Name == "_ZSt9terminatev" || Name == "\01?terminate@@YAXXZ")
+ ? C.Idents.get("terminate")
+ : C.Idents.get(Name);
+
+ for (const auto &N : {"__cxxabiv1", "std"}) {
+ IdentifierInfo &NS = C.Idents.get(N);
+ for (const auto &Result : DC->lookup(&NS)) {
+ NamespaceDecl *ND = dyn_cast<NamespaceDecl>(Result);
+ if (auto LSD = dyn_cast<LinkageSpecDecl>(Result))
+ for (const auto &Result : LSD->lookup(&NS))
+ if ((ND = dyn_cast<NamespaceDecl>(Result)))
+ break;
+
+ if (ND)
+ for (const auto &Result : ND->lookup(&CXXII))
+ if (const auto *FD = dyn_cast<FunctionDecl>(Result))
+ return FD;
+ }
+ }
+
+ return nullptr;
+}
+
/// CreateRuntimeFunction - Create a new runtime function with the specified
/// type and name.
llvm::Constant *
-CodeGenModule::CreateRuntimeFunction(llvm::FunctionType *FTy,
- StringRef Name,
- llvm::AttributeSet ExtraAttrs) {
+CodeGenModule::CreateRuntimeFunction(llvm::FunctionType *FTy, StringRef Name,
+ llvm::AttributeSet ExtraAttrs,
+ bool Local) {
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())
+ /*DontDefer=*/false, /*IsThunk=*/false,
+ ExtraAttrs);
+
+ if (auto *F = dyn_cast<llvm::Function>(C)) {
+ if (F->empty()) {
F->setCallingConv(getRuntimeCC());
+
+ if (!Local && getTriple().isOSBinFormatCOFF() &&
+ !getCodeGenOpts().LTOVisibilityPublicStd) {
+ const FunctionDecl *FD = GetRuntimeFunctionDecl(Context, Name);
+ if (!FD || FD->hasAttr<DLLImportAttr>()) {
+ F->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
+ F->setLinkage(llvm::GlobalValue::ExternalLinkage);
+ }
+ }
+ }
+ }
+
return C;
}
@@ -2062,7 +2184,7 @@ llvm::Constant *
CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName,
llvm::PointerType *Ty,
const VarDecl *D,
- bool IsForDefinition) {
+ ForDefinition_t IsForDefinition) {
// Lookup the entry, lazily creating it if necessary.
llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
if (Entry) {
@@ -2162,7 +2284,7 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName,
}
// Handle XCore specific ABI requirements.
- if (getTarget().getTriple().getArch() == llvm::Triple::xcore &&
+ if (getTriple().getArch() == llvm::Triple::xcore &&
D->getLanguageLinkage() == CLanguageLinkage &&
D->getType().isConstant(Context) &&
isExternallyVisible(D->getLinkageAndVisibility().getLinkage()))
@@ -2177,30 +2299,31 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName,
llvm::Constant *
CodeGenModule::GetAddrOfGlobal(GlobalDecl GD,
- bool IsForDefinition) {
- if (isa<CXXConstructorDecl>(GD.getDecl()))
- return getAddrOfCXXStructor(cast<CXXConstructorDecl>(GD.getDecl()),
+ ForDefinition_t IsForDefinition) {
+ const Decl *D = GD.getDecl();
+ if (isa<CXXConstructorDecl>(D))
+ return getAddrOfCXXStructor(cast<CXXConstructorDecl>(D),
getFromCtorType(GD.getCtorType()),
/*FnInfo=*/nullptr, /*FnType=*/nullptr,
/*DontDefer=*/false, IsForDefinition);
- else if (isa<CXXDestructorDecl>(GD.getDecl()))
- return getAddrOfCXXStructor(cast<CXXDestructorDecl>(GD.getDecl()),
+ else if (isa<CXXDestructorDecl>(D))
+ return getAddrOfCXXStructor(cast<CXXDestructorDecl>(D),
getFromDtorType(GD.getDtorType()),
/*FnInfo=*/nullptr, /*FnType=*/nullptr,
/*DontDefer=*/false, IsForDefinition);
- else if (isa<CXXMethodDecl>(GD.getDecl())) {
+ else if (isa<CXXMethodDecl>(D)) {
auto FInfo = &getTypes().arrangeCXXMethodDeclaration(
- cast<CXXMethodDecl>(GD.getDecl()));
+ cast<CXXMethodDecl>(D));
auto Ty = getTypes().GetFunctionType(*FInfo);
return GetAddrOfFunction(GD, Ty, /*ForVTable=*/false, /*DontDefer=*/false,
IsForDefinition);
- } else if (isa<FunctionDecl>(GD.getDecl())) {
+ } else if (isa<FunctionDecl>(D)) {
const CGFunctionInfo &FI = getTypes().arrangeGlobalDeclaration(GD);
llvm::FunctionType *Ty = getTypes().GetFunctionType(FI);
return GetAddrOfFunction(GD, Ty, /*ForVTable=*/false, /*DontDefer=*/false,
IsForDefinition);
} else
- return GetAddrOfGlobalVar(cast<VarDecl>(GD.getDecl()), /*Ty=*/nullptr,
+ return GetAddrOfGlobalVar(cast<VarDecl>(D), /*Ty=*/nullptr,
IsForDefinition);
}
@@ -2254,7 +2377,7 @@ CodeGenModule::CreateOrReplaceCXXRuntimeVariable(StringRef Name,
/// variable with the same mangled name but some other type.
llvm::Constant *CodeGenModule::GetAddrOfGlobalVar(const VarDecl *D,
llvm::Type *Ty,
- bool IsForDefinition) {
+ ForDefinition_t IsForDefinition) {
assert(D->hasGlobalStorage() && "Not a global variable");
QualType ASTTy = D->getType();
if (!Ty)
@@ -2385,8 +2508,13 @@ void CodeGenModule::maybeSetTrivialComdat(const Decl &D,
/// Pass IsTentative as true if you want to create a tentative definition.
void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D,
bool IsTentative) {
- llvm::Constant *Init = nullptr;
+ // OpenCL global variables of sampler type are translated to function calls,
+ // therefore no need to be translated.
QualType ASTTy = D->getType();
+ if (getLangOpts().OpenCL && ASTTy->isSamplerT())
+ return;
+
+ llvm::Constant *Init = nullptr;
CXXRecordDecl *RD = ASTTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl();
bool NeedsGlobalCtor = false;
bool NeedsGlobalDtor = RD && !RD->hasTrivialDestructor();
@@ -2439,7 +2567,7 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D,
llvm::Type* InitType = Init->getType();
llvm::Constant *Entry =
- GetAddrOfGlobalVar(D, InitType, /*IsForDefinition=*/!IsTentative);
+ GetAddrOfGlobalVar(D, InitType, ForDefinition_t(!IsTentative));
// Strip off a bitcast if we got one back.
if (auto *CE = dyn_cast<llvm::ConstantExpr>(Entry)) {
@@ -2472,7 +2600,7 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D,
// Make a new global with the correct type, this is now guaranteed to work.
GV = cast<llvm::GlobalVariable>(
- GetAddrOfGlobalVar(D, InitType, /*IsForDefinition=*/!IsTentative));
+ GetAddrOfGlobalVar(D, InitType, ForDefinition_t(!IsTentative)));
// Replace all uses of the old global with the new global
llvm::Constant *NewPtrForOldDecl =
@@ -2565,9 +2693,16 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D,
else
GV->setDLLStorageClass(llvm::GlobalVariable::DefaultStorageClass);
- if (Linkage == llvm::GlobalVariable::CommonLinkage)
+ if (Linkage == llvm::GlobalVariable::CommonLinkage) {
// common vars aren't constant even if declared const.
GV->setConstant(false);
+ // Tentative definition of global variables may be initialized with
+ // non-zero null pointers. In this case they should have weak linkage
+ // since common linkage must have zero initializer and must not have
+ // explicit section therefore cannot have non-zero initial value.
+ if (!GV->getInitializer()->isNullValue())
+ GV->setLinkage(llvm::GlobalVariable::WeakAnyLinkage);
+ }
setNonAliasAttributes(D, GV);
@@ -2876,7 +3011,7 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD,
if (!GV || (GV->getType()->getElementType() != Ty))
GV = cast<llvm::GlobalValue>(GetAddrOfFunction(GD, Ty, /*ForVTable=*/false,
/*DontDefer=*/true,
- /*IsForDefinition=*/true));
+ ForDefinition));
// Already emitted.
if (!GV->isDeclaration())
@@ -3067,13 +3202,12 @@ GetConstantCFStringEntry(llvm::StringMap<llvm::GlobalVariable *> &Map,
// Otherwise, convert the UTF8 literals into a string of shorts.
IsUTF16 = true;
- SmallVector<UTF16, 128> ToBuf(NumBytes + 1); // +1 for ending nulls.
- const UTF8 *FromPtr = (const UTF8 *)String.data();
- UTF16 *ToPtr = &ToBuf[0];
+ SmallVector<llvm::UTF16, 128> ToBuf(NumBytes + 1); // +1 for ending nulls.
+ const llvm::UTF8 *FromPtr = (const llvm::UTF8 *)String.data();
+ llvm::UTF16 *ToPtr = &ToBuf[0];
- (void)ConvertUTF8toUTF16(&FromPtr, FromPtr + NumBytes,
- &ToPtr, ToPtr + NumBytes,
- strictConversion);
+ (void)llvm::ConvertUTF8toUTF16(&FromPtr, FromPtr + NumBytes, &ToPtr,
+ ToPtr + NumBytes, llvm::strictConversion);
// ConvertUTF8toUTF16 returns the length in ToPtr.
StringLength = ToPtr - &ToBuf[0];
@@ -3086,14 +3220,6 @@ GetConstantCFStringEntry(llvm::StringMap<llvm::GlobalVariable *> &Map,
nullptr)).first;
}
-static llvm::StringMapEntry<llvm::GlobalVariable *> &
-GetConstantStringEntry(llvm::StringMap<llvm::GlobalVariable *> &Map,
- const StringLiteral *Literal, unsigned &StringLength) {
- StringRef String = Literal->getString();
- StringLength = String.size();
- return *Map.insert(std::make_pair(String, nullptr)).first;
-}
-
ConstantAddress
CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) {
unsigned StringLength = 0;
@@ -3108,7 +3234,6 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) {
llvm::Constant *Zero = llvm::Constant::getNullValue(Int32Ty);
llvm::Constant *Zeros[] = { Zero, Zero };
- llvm::Value *V;
// If we don't already have it, get __CFConstantStringClassReference.
if (!CFConstantStringClassRef) {
@@ -3117,7 +3242,7 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) {
llvm::Constant *GV =
CreateRuntimeVariable(Ty, "__CFConstantStringClassReference");
- if (getTarget().getTriple().isOSBinFormatCOFF()) {
+ if (getTriple().isOSBinFormatCOFF()) {
IdentifierInfo &II = getContext().Idents.get(GV->getName());
TranslationUnitDecl *TUDecl = getContext().getTranslationUnitDecl();
DeclContext *DC = TranslationUnitDecl::castToDeclContext(TUDecl);
@@ -3138,25 +3263,22 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) {
}
// Decay array -> ptr
- V = llvm::ConstantExpr::getGetElementPtr(Ty, GV, Zeros);
- CFConstantStringClassRef = V;
- } else {
- V = CFConstantStringClassRef;
+ CFConstantStringClassRef =
+ llvm::ConstantExpr::getGetElementPtr(Ty, GV, Zeros);
}
QualType CFTy = getContext().getCFConstantStringType();
auto *STy = cast<llvm::StructType>(getTypes().ConvertType(CFTy));
- llvm::Constant *Fields[4];
+ ConstantInitBuilder Builder(*this);
+ auto Fields = Builder.beginStruct(STy);
// Class pointer.
- Fields[0] = cast<llvm::ConstantExpr>(V);
+ Fields.add(cast<llvm::ConstantExpr>(CFConstantStringClassRef));
// Flags.
- llvm::Type *Ty = getTypes().ConvertType(getContext().UnsignedIntTy);
- Fields[1] = isUTF16 ? llvm::ConstantInt::get(Ty, 0x07d0)
- : llvm::ConstantInt::get(Ty, 0x07C8);
+ Fields.addInt(IntTy, isUTF16 ? 0x07d0 : 0x07C8);
// String pointer.
llvm::Constant *C = nullptr;
@@ -3185,31 +3307,30 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) {
// FIXME: We set the section explicitly to avoid a bug in ld64 224.1.
// Without it LLVM can merge the string with a non unnamed_addr one during
// LTO. Doing that changes the section it ends in, which surprises ld64.
- if (getTarget().getTriple().isOSBinFormatMachO())
+ if (getTriple().isOSBinFormatMachO())
GV->setSection(isUTF16 ? "__TEXT,__ustring"
: "__TEXT,__cstring,cstring_literals");
// String.
- Fields[2] =
+ llvm::Constant *Str =
llvm::ConstantExpr::getGetElementPtr(GV->getValueType(), GV, Zeros);
if (isUTF16)
// Cast the UTF16 string to the correct type.
- Fields[2] = llvm::ConstantExpr::getBitCast(Fields[2], Int8PtrTy);
+ Str = llvm::ConstantExpr::getBitCast(Str, Int8PtrTy);
+ Fields.add(Str);
// String length.
- Ty = getTypes().ConvertType(getContext().LongTy);
- Fields[3] = llvm::ConstantInt::get(Ty, StringLength);
+ auto Ty = getTypes().ConvertType(getContext().LongTy);
+ Fields.addInt(cast<llvm::IntegerType>(Ty), StringLength);
CharUnits Alignment = getPointerAlign();
// The struct.
- C = llvm::ConstantStruct::get(STy, Fields);
- GV = new llvm::GlobalVariable(getModule(), C->getType(), true,
- llvm::GlobalVariable::PrivateLinkage, C,
- "_unnamed_cfstring_");
- GV->setAlignment(Alignment.getQuantity());
- switch (getTarget().getTriple().getObjectFormat()) {
+ GV = Fields.finishAndCreateGlobal("_unnamed_cfstring_", Alignment,
+ /*isConstant=*/false,
+ llvm::GlobalVariable::PrivateLinkage);
+ switch (getTriple().getObjectFormat()) {
case llvm::Triple::UnknownObjectFormat:
llvm_unreachable("unknown file format");
case llvm::Triple::COFF:
@@ -3225,124 +3346,6 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) {
return ConstantAddress(GV, Alignment);
}
-ConstantAddress
-CodeGenModule::GetAddrOfConstantString(const StringLiteral *Literal) {
- unsigned StringLength = 0;
- llvm::StringMapEntry<llvm::GlobalVariable *> &Entry =
- GetConstantStringEntry(CFConstantStringMap, Literal, StringLength);
-
- if (auto *C = Entry.second)
- return ConstantAddress(C, CharUnits::fromQuantity(C->getAlignment()));
-
- llvm::Constant *Zero = llvm::Constant::getNullValue(Int32Ty);
- llvm::Constant *Zeros[] = { Zero, Zero };
- llvm::Value *V;
- // If we don't already have it, get _NSConstantStringClassReference.
- if (!ConstantStringClassRef) {
- std::string StringClass(getLangOpts().ObjCConstantStringClass);
- llvm::Type *Ty = getTypes().ConvertType(getContext().IntTy);
- llvm::Constant *GV;
- if (LangOpts.ObjCRuntime.isNonFragile()) {
- std::string str =
- StringClass.empty() ? "OBJC_CLASS_$_NSConstantString"
- : "OBJC_CLASS_$_" + StringClass;
- GV = getObjCRuntime().GetClassGlobal(str);
- // Make sure the result is of the correct type.
- llvm::Type *PTy = llvm::PointerType::getUnqual(Ty);
- V = llvm::ConstantExpr::getBitCast(GV, PTy);
- ConstantStringClassRef = V;
- } else {
- std::string str =
- StringClass.empty() ? "_NSConstantStringClassReference"
- : "_" + StringClass + "ClassReference";
- llvm::Type *PTy = llvm::ArrayType::get(Ty, 0);
- GV = CreateRuntimeVariable(PTy, str);
- // Decay array -> ptr
- V = llvm::ConstantExpr::getGetElementPtr(PTy, GV, Zeros);
- ConstantStringClassRef = V;
- }
- } else
- V = ConstantStringClassRef;
-
- if (!NSConstantStringType) {
- // Construct the type for a constant NSString.
- RecordDecl *D = Context.buildImplicitRecord("__builtin_NSString");
- D->startDefinition();
-
- QualType FieldTypes[3];
-
- // const int *isa;
- FieldTypes[0] = Context.getPointerType(Context.IntTy.withConst());
- // const char *str;
- FieldTypes[1] = Context.getPointerType(Context.CharTy.withConst());
- // unsigned int length;
- FieldTypes[2] = Context.UnsignedIntTy;
-
- // Create fields
- for (unsigned i = 0; i < 3; ++i) {
- FieldDecl *Field = FieldDecl::Create(Context, D,
- SourceLocation(),
- SourceLocation(), nullptr,
- FieldTypes[i], /*TInfo=*/nullptr,
- /*BitWidth=*/nullptr,
- /*Mutable=*/false,
- ICIS_NoInit);
- Field->setAccess(AS_public);
- D->addDecl(Field);
- }
-
- D->completeDefinition();
- QualType NSTy = Context.getTagDeclType(D);
- NSConstantStringType = cast<llvm::StructType>(getTypes().ConvertType(NSTy));
- }
-
- llvm::Constant *Fields[3];
-
- // Class pointer.
- Fields[0] = cast<llvm::ConstantExpr>(V);
-
- // String pointer.
- llvm::Constant *C =
- llvm::ConstantDataArray::getString(VMContext, Entry.first());
-
- llvm::GlobalValue::LinkageTypes Linkage;
- bool isConstant;
- Linkage = llvm::GlobalValue::PrivateLinkage;
- isConstant = !LangOpts.WritableStrings;
-
- auto *GV = new llvm::GlobalVariable(getModule(), C->getType(), isConstant,
- Linkage, C, ".str");
- GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
- // Don't enforce the target's minimum global alignment, since the only use
- // of the string is via this class initializer.
- CharUnits Align = getContext().getTypeAlignInChars(getContext().CharTy);
- GV->setAlignment(Align.getQuantity());
- Fields[1] =
- llvm::ConstantExpr::getGetElementPtr(GV->getValueType(), GV, Zeros);
-
- // String length.
- llvm::Type *Ty = getTypes().ConvertType(getContext().UnsignedIntTy);
- Fields[2] = llvm::ConstantInt::get(Ty, StringLength);
-
- // The struct.
- CharUnits Alignment = getPointerAlign();
- C = llvm::ConstantStruct::get(NSConstantStringType, Fields);
- GV = new llvm::GlobalVariable(getModule(), C->getType(), true,
- llvm::GlobalVariable::PrivateLinkage, C,
- "_unnamed_nsstring_");
- GV->setAlignment(Alignment.getQuantity());
- const char *NSStringSection = "__OBJC,__cstring_object,regular,no_dead_strip";
- const char *NSStringNonFragileABISection =
- "__DATA,__objc_stringobj,regular,no_dead_strip";
- // FIXME. Fix section.
- GV->setSection(LangOpts.ObjCRuntime.isNonFragile()
- ? NSStringNonFragileABISection
- : NSStringSection);
- Entry.second = GV;
-
- return ConstantAddress(GV, Alignment);
-}
-
QualType CodeGenModule::getObjCFastEnumerationStateType() {
if (ObjCFastEnumerationStateType.isNull()) {
RecordDecl *D = Context.buildImplicitRecord("__objcFastEnumerationState");
@@ -3710,17 +3713,6 @@ void CodeGenModule::EmitObjCIvarInitializations(ObjCImplementationDecl *D) {
D->setHasNonZeroConstructors(true);
}
-/// EmitNamespace - Emit all declarations in a namespace.
-void CodeGenModule::EmitNamespace(const NamespaceDecl *ND) {
- for (auto *I : ND->decls()) {
- if (const auto *VD = dyn_cast<VarDecl>(I))
- if (VD->getTemplateSpecializationKind() != TSK_ExplicitSpecialization &&
- VD->getTemplateSpecializationKind() != TSK_Undeclared)
- continue;
- EmitTopLevelDecl(I);
- }
-}
-
// EmitLinkageSpec - Emit all declarations in a linkage spec.
void CodeGenModule::EmitLinkageSpec(const LinkageSpecDecl *LSD) {
if (LSD->getLanguage() != LinkageSpecDecl::lang_c &&
@@ -3729,13 +3721,21 @@ void CodeGenModule::EmitLinkageSpec(const LinkageSpecDecl *LSD) {
return;
}
- for (auto *I : LSD->decls()) {
- // Meta-data for ObjC class includes references to implemented methods.
- // Generate class's method definitions first.
+ EmitDeclContext(LSD);
+}
+
+void CodeGenModule::EmitDeclContext(const DeclContext *DC) {
+ for (auto *I : DC->decls()) {
+ // Unlike other DeclContexts, the contents of an ObjCImplDecl at TU scope
+ // are themselves considered "top-level", so EmitTopLevelDecl on an
+ // ObjCImplDecl does not recursively visit them. We need to do that in
+ // case they're nested inside another construct (LinkageSpecDecl /
+ // ExportDecl) that does stop them from being considered "top-level".
if (auto *OID = dyn_cast<ObjCImplDecl>(I)) {
for (auto *M : OID->methods())
EmitTopLevelDecl(M);
}
+
EmitTopLevelDecl(I);
}
}
@@ -3762,11 +3762,16 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
break;
case Decl::Var:
+ case Decl::Decomposition:
// Skip variable templates
if (cast<VarDecl>(D)->getDescribedVarTemplate())
return;
case Decl::VarTemplateSpecialization:
EmitGlobal(cast<VarDecl>(D));
+ if (auto *DD = dyn_cast<DecompositionDecl>(D))
+ for (auto *B : DD->bindings())
+ if (auto *HD = B->getHoldingVar())
+ EmitGlobal(HD);
break;
// Indirect fields from global anonymous structs and unions can be
@@ -3776,7 +3781,7 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
// C++ Decls
case Decl::Namespace:
- EmitNamespace(cast<NamespaceDecl>(D));
+ EmitDeclContext(cast<NamespaceDecl>(D));
break;
case Decl::CXXRecord:
// Emit any static data members, they may be definitions.
@@ -3911,16 +3916,50 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
case Decl::Import: {
auto *Import = cast<ImportDecl>(D);
- // Ignore import declarations that come from imported modules.
- if (Import->getImportedOwningModule())
+ // If we've already imported this module, we're done.
+ if (!ImportedModules.insert(Import->getImportedModule()))
break;
- if (CGDebugInfo *DI = getModuleDebugInfo())
- DI->EmitImportDecl(*Import);
- ImportedModules.insert(Import->getImportedModule());
+ // Emit debug information for direct imports.
+ if (!Import->getImportedOwningModule()) {
+ if (CGDebugInfo *DI = getModuleDebugInfo())
+ DI->EmitImportDecl(*Import);
+ }
+
+ // Find all of the submodules and emit the module initializers.
+ llvm::SmallPtrSet<clang::Module *, 16> Visited;
+ SmallVector<clang::Module *, 16> Stack;
+ Visited.insert(Import->getImportedModule());
+ Stack.push_back(Import->getImportedModule());
+
+ while (!Stack.empty()) {
+ clang::Module *Mod = Stack.pop_back_val();
+ if (!EmittedModuleInitializers.insert(Mod).second)
+ continue;
+
+ for (auto *D : Context.getModuleInitializers(Mod))
+ EmitTopLevelDecl(D);
+
+ // Visit the submodules of this module.
+ for (clang::Module::submodule_iterator Sub = Mod->submodule_begin(),
+ SubEnd = Mod->submodule_end();
+ Sub != SubEnd; ++Sub) {
+ // Skip explicit children; they need to be explicitly imported to emit
+ // the initializers.
+ if ((*Sub)->IsExplicit)
+ continue;
+
+ if (Visited.insert(*Sub).second)
+ Stack.push_back(*Sub);
+ }
+ }
break;
}
+ case Decl::Export:
+ EmitDeclContext(cast<ExportDecl>(D));
+ break;
+
case Decl::OMPThreadPrivate:
EmitOMPThreadPrivateDecl(cast<OMPThreadPrivateDecl>(D));
break;
@@ -4153,18 +4192,24 @@ void CodeGenModule::EmitTargetMetadata() {
}
void CodeGenModule::EmitCoverageFile() {
- if (!getCodeGenOpts().CoverageFile.empty()) {
- if (llvm::NamedMDNode *CUNode = TheModule.getNamedMetadata("llvm.dbg.cu")) {
- llvm::NamedMDNode *GCov = TheModule.getOrInsertNamedMetadata("llvm.gcov");
- llvm::LLVMContext &Ctx = TheModule.getContext();
- llvm::MDString *CoverageFile =
- llvm::MDString::get(Ctx, getCodeGenOpts().CoverageFile);
- for (int i = 0, e = CUNode->getNumOperands(); i != e; ++i) {
- llvm::MDNode *CU = CUNode->getOperand(i);
- llvm::Metadata *Elts[] = {CoverageFile, CU};
- GCov->addOperand(llvm::MDNode::get(Ctx, Elts));
- }
- }
+ if (getCodeGenOpts().CoverageDataFile.empty() &&
+ getCodeGenOpts().CoverageNotesFile.empty())
+ return;
+
+ llvm::NamedMDNode *CUNode = TheModule.getNamedMetadata("llvm.dbg.cu");
+ if (!CUNode)
+ return;
+
+ llvm::NamedMDNode *GCov = TheModule.getOrInsertNamedMetadata("llvm.gcov");
+ llvm::LLVMContext &Ctx = TheModule.getContext();
+ auto *CoverageDataFile =
+ llvm::MDString::get(Ctx, getCodeGenOpts().CoverageDataFile);
+ auto *CoverageNotesFile =
+ llvm::MDString::get(Ctx, getCodeGenOpts().CoverageNotesFile);
+ for (int i = 0, e = CUNode->getNumOperands(); i != e; ++i) {
+ llvm::MDNode *CU = CUNode->getOperand(i);
+ llvm::Metadata *Elts[] = {CoverageNotesFile, CoverageDataFile, CU};
+ GCov->addOperand(llvm::MDNode::get(Ctx, Elts));
}
}
@@ -4311,3 +4356,13 @@ llvm::SanitizerStatReport &CodeGenModule::getSanStats() {
return *SanStats;
}
+llvm::Value *
+CodeGenModule::createOpenCLIntToSamplerConversion(const Expr *E,
+ CodeGenFunction &CGF) {
+ llvm::Constant *C = EmitConstantExpr(E, E->getType(), &CGF);
+ auto SamplerT = getOpenCLRuntime().getSamplerType();
+ auto FTy = llvm::FunctionType::get(SamplerT, {C->getType()}, false);
+ return CGF.Builder.CreateCall(CreateRuntimeFunction(FTy,
+ "__translate_sampler_initializer"),
+ {C});
+}
diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h
index 94904997d629..1d72b4edeb13 100644
--- a/lib/CodeGen/CodeGenModule.h
+++ b/lib/CodeGen/CodeGenModule.h
@@ -94,6 +94,11 @@ class FunctionArgList;
class CoverageMappingModuleGen;
class TargetCodeGenInfo;
+enum ForDefinition_t : bool {
+ NotForDefinition = false,
+ ForDefinition = true
+};
+
struct OrderGlobalInits {
unsigned int priority;
unsigned int lex_order;
@@ -420,6 +425,10 @@ private:
/// \brief The complete set of modules that has been imported.
llvm::SetVector<clang::Module *> ImportedModules;
+ /// \brief The set of modules for which the module initializers
+ /// have been emitted.
+ llvm::SmallPtrSet<clang::Module *, 16> EmittedModuleInitializers;
+
/// \brief A vector of metadata strings.
SmallVector<llvm::Metadata *, 16> LinkerOptionsMetadata;
@@ -430,13 +439,6 @@ private:
/// int * but is actually an Obj-C class pointer.
llvm::WeakVH CFConstantStringClassRef;
- /// Cached reference to the class for constant strings. This value has type
- /// int * but is actually an Obj-C class pointer.
- llvm::WeakVH ConstantStringClassRef;
-
- /// \brief The LLVM type corresponding to NSConstantString.
- llvm::StructType *NSConstantStringType = nullptr;
-
/// \brief The type used to describe the state of a fast enumeration in
/// Objective-C's for..in loop.
QualType ObjCFastEnumerationStateType;
@@ -453,6 +455,14 @@ private:
bool isTriviallyRecursive(const FunctionDecl *F);
bool shouldEmitFunction(GlobalDecl GD);
+ /// Map used to be sure we don't emit the same CompoundLiteral twice.
+ llvm::DenseMap<const CompoundLiteralExpr *, llvm::GlobalVariable *>
+ EmittedCompoundLiterals;
+
+ /// Map of the global blocks we've emitted, so that we don't have to re-emit
+ /// them if the constexpr evaluator gets aggressive.
+ llvm::DenseMap<const BlockExpr *, llvm::Constant *> EmittedGlobalBlocks;
+
/// @name Cache for Blocks Runtime Globals
/// @{
@@ -610,7 +620,7 @@ public:
return TheModule.getDataLayout();
}
const TargetInfo &getTarget() const { return Target; }
- const llvm::Triple &getTriple() const;
+ const llvm::Triple &getTriple() const { return Target.getTriple(); }
bool supportsCOMDAT() const;
void maybeSetTrivialComdat(const Decl &D, llvm::GlobalObject &GO);
@@ -679,7 +689,9 @@ public:
llvm_unreachable("unknown visibility!");
}
- llvm::Constant *GetAddrOfGlobal(GlobalDecl GD, bool IsForDefinition = false);
+ llvm::Constant *GetAddrOfGlobal(GlobalDecl GD,
+ ForDefinition_t IsForDefinition
+ = NotForDefinition);
/// Will return a global variable of the given type. If a variable with a
/// different type already exists then a new variable with the right type
@@ -709,14 +721,16 @@ public:
/// the same mangled name but some other type.
llvm::Constant *GetAddrOfGlobalVar(const VarDecl *D,
llvm::Type *Ty = nullptr,
- bool IsForDefinition = false);
+ ForDefinition_t IsForDefinition
+ = NotForDefinition);
/// 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,
bool ForVTable = false,
bool DontDefer = false,
- bool IsForDefinition = false);
+ ForDefinition_t IsForDefinition
+ = NotForDefinition);
/// Get the address of the RTTI descriptor for the given type.
llvm::Constant *GetAddrOfRTTIDescriptor(QualType Ty, bool ForEH = false);
@@ -769,7 +783,17 @@ public:
llvm::Type *getGenericBlockLiteralType();
/// Gets the address of a block which requires no captures.
- llvm::Constant *GetAddrOfGlobalBlock(const BlockExpr *BE, const char *);
+ llvm::Constant *GetAddrOfGlobalBlock(const BlockExpr *BE, StringRef Name);
+
+ /// Returns the address of a block which requires no caputres, or null if
+ /// we've yet to emit the block for BE.
+ llvm::Constant *getAddrOfGlobalBlockIfEmitted(const BlockExpr *BE) {
+ return EmittedGlobalBlocks.lookup(BE);
+ }
+
+ /// Notes that BE's global block is available via Addr. Asserts that BE
+ /// isn't already emitted.
+ void setAddrOfGlobalBlock(const BlockExpr *BE, llvm::Constant *Addr);
/// Return a pointer to a constant CFString object for the given string.
ConstantAddress GetAddrOfConstantCFString(const StringLiteral *Literal);
@@ -804,6 +828,16 @@ public:
/// compound literal expression.
ConstantAddress GetAddrOfConstantCompoundLiteral(const CompoundLiteralExpr*E);
+ /// If it's been emitted already, returns the GlobalVariable corresponding to
+ /// a compound literal. Otherwise, returns null.
+ llvm::GlobalVariable *
+ getAddrOfConstantCompoundLiteralIfEmitted(const CompoundLiteralExpr *E);
+
+ /// Notes that CLE's GlobalVariable is GV. Asserts that CLE isn't already
+ /// emitted.
+ void setAddrOfConstantCompoundLiteral(const CompoundLiteralExpr *CLE,
+ llvm::GlobalVariable *GV);
+
/// \brief Returns a pointer to a global variable representing a temporary
/// with static or thread storage duration.
ConstantAddress GetAddrOfGlobalTemporary(const MaterializeTemporaryExpr *E,
@@ -824,12 +858,13 @@ public:
getAddrOfCXXStructor(const CXXMethodDecl *MD, StructorType Type,
const CGFunctionInfo *FnInfo = nullptr,
llvm::FunctionType *FnType = nullptr,
- bool DontDefer = false, bool IsForDefinition = false);
+ bool DontDefer = false,
+ ForDefinition_t IsForDefinition = NotForDefinition);
/// Given a builtin id for a function like "__builtin_fabsf", return a
/// Function* for "fabsf".
- llvm::Value *getBuiltinLibFunction(const FunctionDecl *FD,
- unsigned BuiltinID);
+ llvm::Constant *getBuiltinLibFunction(const FunctionDecl *FD,
+ unsigned BuiltinID);
llvm::Function *getIntrinsic(unsigned IID, ArrayRef<llvm::Type*> Tys = None);
@@ -869,10 +904,11 @@ public:
}
/// Create a new runtime function with the specified type and name.
- llvm::Constant *CreateRuntimeFunction(llvm::FunctionType *Ty,
- StringRef Name,
- llvm::AttributeSet ExtraAttrs =
- llvm::AttributeSet());
+ llvm::Constant *
+ CreateRuntimeFunction(llvm::FunctionType *Ty, StringRef Name,
+ llvm::AttributeSet ExtraAttrs = llvm::AttributeSet(),
+ bool Local = false);
+
/// Create a new compiler builtin function with the specified type and name.
llvm::Constant *CreateBuiltinFunction(llvm::FunctionType *Ty,
StringRef Name,
@@ -1145,18 +1181,27 @@ public:
llvm::SanitizerStatReport &getSanStats();
+ llvm::Value *
+ createOpenCLIntToSamplerConversion(const Expr *E, CodeGenFunction &CGF);
+
+ /// Get target specific null pointer.
+ /// \param T is the LLVM type of the null pointer.
+ /// \param QT is the clang QualType of the null pointer.
+ llvm::Constant *getNullPointer(llvm::PointerType *T, QualType QT);
+
private:
llvm::Constant *
GetOrCreateLLVMFunction(StringRef MangledName, llvm::Type *Ty, GlobalDecl D,
bool ForVTable, bool DontDefer = false,
bool IsThunk = false,
llvm::AttributeSet ExtraAttrs = llvm::AttributeSet(),
- bool IsForDefinition = false);
+ ForDefinition_t IsForDefinition = NotForDefinition);
llvm::Constant *GetOrCreateLLVMGlobal(StringRef MangledName,
llvm::PointerType *PTy,
const VarDecl *D,
- bool IsForDefinition = false);
+ ForDefinition_t IsForDefinition
+ = NotForDefinition);
void setNonAliasAttributes(const Decl *D, llvm::GlobalObject *GO);
@@ -1175,7 +1220,7 @@ private:
// C++ related functions.
- void EmitNamespace(const NamespaceDecl *D);
+ void EmitDeclContext(const DeclContext *DC);
void EmitLinkageSpec(const LinkageSpecDecl *D);
void CompleteDIClassType(const CXXMethodDecl* D);
@@ -1202,10 +1247,10 @@ private:
llvm::Constant *AssociatedData = nullptr);
void AddGlobalDtor(llvm::Function *Dtor, int Priority = 65535);
- /// Generates a global array of functions and priorities using the given list
- /// and name. This array will have appending linkage and is suitable for use
- /// as a LLVM constructor or destructor array.
- void EmitCtorList(const CtorList &Fns, const char *GlobalName);
+ /// EmitCtorList - Generates a global array of functions and priorities using
+ /// the given list and name. This array will have appending linkage and is
+ /// suitable for use as a LLVM constructor or destructor array. Clears Fns.
+ void EmitCtorList(CtorList &Fns, const char *GlobalName);
/// Emit any needed decls for which code generation was deferred.
void EmitDeferred();
diff --git a/lib/CodeGen/CodeGenPGO.cpp b/lib/CodeGen/CodeGenPGO.cpp
index 4eefdd72b7e4..c6c3fa41e628 100644
--- a/lib/CodeGen/CodeGenPGO.cpp
+++ b/lib/CodeGen/CodeGenPGO.cpp
@@ -458,6 +458,8 @@ struct ComputeRegionCounts : public ConstStmtVisitor<ComputeRegionCounts> {
void VisitSwitchStmt(const SwitchStmt *S) {
RecordStmtCount(S);
+ if (S->getInit())
+ Visit(S->getInit());
Visit(S->getCond());
CurrentCount = 0;
BreakContinueStack.push_back(BreakContinue());
@@ -488,6 +490,8 @@ struct ComputeRegionCounts : public ConstStmtVisitor<ComputeRegionCounts> {
void VisitIfStmt(const IfStmt *S) {
RecordStmtCount(S);
uint64_t ParentCount = CurrentCount;
+ if (S->getInit())
+ Visit(S->getInit());
Visit(S->getCond());
// Counter tracks the "then" part of an if statement. The count for
diff --git a/lib/CodeGen/CodeGenPGO.h b/lib/CodeGen/CodeGenPGO.h
index d03f23535bb9..4f229cde63b0 100644
--- a/lib/CodeGen/CodeGenPGO.h
+++ b/lib/CodeGen/CodeGenPGO.h
@@ -18,9 +18,7 @@
#include "CodeGenModule.h"
#include "CodeGenTypes.h"
#include "clang/Frontend/CodeGenOptions.h"
-#include "llvm/ADT/StringMap.h"
#include "llvm/ProfileData/InstrProfReader.h"
-#include "llvm/Support/MemoryBuffer.h"
#include <array>
#include <memory>
diff --git a/lib/CodeGen/CodeGenTypeCache.h b/lib/CodeGen/CodeGenTypeCache.h
index c32b66d129da..47e26bcaa1b6 100644
--- a/lib/CodeGen/CodeGenTypeCache.h
+++ b/lib/CodeGen/CodeGenTypeCache.h
@@ -80,9 +80,14 @@ struct CodeGenTypeCache {
union {
unsigned char PointerAlignInBytes;
unsigned char PointerSizeInBytes;
+ };
+
+ /// The size and alignment of size_t.
+ union {
unsigned char SizeSizeInBytes; // sizeof(size_t)
unsigned char SizeAlignInBytes;
};
+
CharUnits getSizeSize() const {
return CharUnits::fromQuantity(SizeSizeInBytes);
}
diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp
index ebe55c70d817..b95b4fff5734 100644
--- a/lib/CodeGen/CodeGenTypes.cpp
+++ b/lib/CodeGen/CodeGenTypes.cpp
@@ -286,21 +286,21 @@ void CodeGenTypes::RefreshTypeCacheForClass(const CXXRecordDecl *RD) {
static llvm::Type *getTypeForFormat(llvm::LLVMContext &VMContext,
const llvm::fltSemantics &format,
bool UseNativeHalf = false) {
- if (&format == &llvm::APFloat::IEEEhalf) {
+ if (&format == &llvm::APFloat::IEEEhalf()) {
if (UseNativeHalf)
return llvm::Type::getHalfTy(VMContext);
else
return llvm::Type::getInt16Ty(VMContext);
}
- if (&format == &llvm::APFloat::IEEEsingle)
+ if (&format == &llvm::APFloat::IEEEsingle())
return llvm::Type::getFloatTy(VMContext);
- if (&format == &llvm::APFloat::IEEEdouble)
+ if (&format == &llvm::APFloat::IEEEdouble())
return llvm::Type::getDoubleTy(VMContext);
- if (&format == &llvm::APFloat::IEEEquad)
+ if (&format == &llvm::APFloat::IEEEquad())
return llvm::Type::getFP128Ty(VMContext);
- if (&format == &llvm::APFloat::PPCDoubleDouble)
+ if (&format == &llvm::APFloat::PPCDoubleDouble())
return llvm::Type::getPPC_FP128Ty(VMContext);
- if (&format == &llvm::APFloat::x87DoubleExtended)
+ if (&format == &llvm::APFloat::x87DoubleExtended())
return llvm::Type::getX86_FP80Ty(VMContext);
llvm_unreachable("Unknown float format!");
}
@@ -736,10 +736,14 @@ CodeGenTypes::getCGRecordLayout(const RecordDecl *RD) {
return *Layout;
}
+bool CodeGenTypes::isPointerZeroInitializable(QualType T) {
+ assert (T->isAnyPointerType() && "Invalid type");
+ return isZeroInitializable(T);
+}
+
bool CodeGenTypes::isZeroInitializable(QualType T) {
- // No need to check for member pointers when not compiling C++.
- if (!Context.getLangOpts().CPlusPlus)
- return true;
+ if (T->getAs<PointerType>())
+ return Context.getTargetNullPointerValue(T) == 0;
if (const auto *AT = Context.getAsArrayType(T)) {
if (isa<IncompleteArrayType>(AT))
@@ -753,7 +757,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>()) {
- const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ auto RD = cast<RecordDecl>(RT->getDecl());
return isZeroInitializable(RD);
}
diff --git a/lib/CodeGen/CodeGenTypes.h b/lib/CodeGen/CodeGenTypes.h
index 5796ab8fe5aa..2ce6591e4eb7 100644
--- a/lib/CodeGen/CodeGenTypes.h
+++ b/lib/CodeGen/CodeGenTypes.h
@@ -15,15 +15,14 @@
#define LLVM_CLANG_LIB_CODEGEN_CODEGENTYPES_H
#include "CGCall.h"
-#include "clang/AST/GlobalDecl.h"
+#include "clang/Basic/ABI.h"
#include "clang/CodeGen/CGFunctionInfo.h"
+#include "clang/Sema/Sema.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/IR/Module.h"
-#include <vector>
namespace llvm {
class FunctionType;
-class Module;
class DataLayout;
class Type;
class LLVMContext;
@@ -48,6 +47,7 @@ class TagDecl;
class TargetInfo;
class Type;
typedef CanQual<Type> CanQualType;
+class GlobalDecl;
namespace CodeGen {
class ABIInfo;
@@ -352,6 +352,10 @@ public: // These are internal details of CGT that shouldn't be used externally.
/// zero-initialized (in the C++ sense) with an LLVM zeroinitializer.
bool isZeroInitializable(QualType T);
+ /// Check if the pointer type can be zero-initialized (in the C++ sense)
+ /// with an LLVM zeroinitializer.
+ bool isPointerZeroInitializable(QualType T);
+
/// IsZeroInitializable - Return whether a record type can be
/// zero-initialized (in the C++ sense) with an LLVM zeroinitializer.
bool isZeroInitializable(const RecordDecl *RD);
diff --git a/lib/CodeGen/ConstantBuilder.h b/lib/CodeGen/ConstantBuilder.h
new file mode 100644
index 000000000000..40b34a9d61c8
--- /dev/null
+++ b/lib/CodeGen/ConstantBuilder.h
@@ -0,0 +1,444 @@
+//===----- ConstantBuilder.h - Builder for LLVM IR constants ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This class provides a convenient interface for building complex
+// global initializers.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_CODEGEN_CONSTANTBUILDER_H
+#define LLVM_CLANG_LIB_CODEGEN_CONSTANTBUILDER_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/IR/Constants.h"
+
+#include "CodeGenModule.h"
+
+#include <vector>
+
+namespace clang {
+namespace CodeGen {
+
+class ConstantStructBuilder;
+class ConstantArrayBuilder;
+
+/// A convenience builder class for complex constant initializers,
+/// especially for anonymous global structures used by various language
+/// runtimes.
+///
+/// The basic usage pattern is expected to be something like:
+/// ConstantInitBuilder builder(CGM);
+/// auto toplevel = builder.beginStruct();
+/// toplevel.addInt(CGM.SizeTy, widgets.size());
+/// auto widgetArray = builder.beginArray();
+/// for (auto &widget : widgets) {
+/// auto widgetDesc = widgetArray.beginStruct();
+/// widgetDesc.addInt(CGM.SizeTy, widget.getPower());
+/// widgetDesc.add(CGM.GetAddrOfConstantString(widget.getName()));
+/// widgetDesc.add(CGM.GetAddrOfGlobal(widget.getInitializerDecl()));
+/// widgetArray.add(widgetDesc.finish());
+/// }
+/// toplevel.add(widgetArray.finish());
+/// auto global = toplevel.finishAndCreateGlobal("WIDGET_LIST", Align,
+/// /*constant*/ true);
+class ConstantInitBuilder {
+ struct SelfReference {
+ llvm::GlobalVariable *Dummy;
+ llvm::SmallVector<llvm::Constant*, 4> Indices;
+
+ SelfReference(llvm::GlobalVariable *dummy) : Dummy(dummy) {}
+ };
+ CodeGenModule &CGM;
+ llvm::SmallVector<llvm::Constant*, 16> Buffer;
+ std::vector<SelfReference> SelfReferences;
+ bool Frozen = false;
+
+public:
+ explicit ConstantInitBuilder(CodeGenModule &CGM) : CGM(CGM) {}
+
+ ~ConstantInitBuilder() {
+ assert(Buffer.empty() && "didn't claim all values out of buffer");
+ }
+
+ class AggregateBuilderBase {
+ protected:
+ ConstantInitBuilder &Builder;
+ AggregateBuilderBase *Parent;
+ size_t Begin;
+ bool Finished = false;
+ bool Frozen = false;
+
+ llvm::SmallVectorImpl<llvm::Constant*> &getBuffer() {
+ return Builder.Buffer;
+ }
+
+ const llvm::SmallVectorImpl<llvm::Constant*> &getBuffer() const {
+ return Builder.Buffer;
+ }
+
+ AggregateBuilderBase(ConstantInitBuilder &builder,
+ AggregateBuilderBase *parent)
+ : Builder(builder), Parent(parent), Begin(builder.Buffer.size()) {
+ if (parent) {
+ assert(!parent->Frozen && "parent already has child builder active");
+ parent->Frozen = true;
+ } else {
+ assert(!builder.Frozen && "builder already has child builder active");
+ builder.Frozen = true;
+ }
+ }
+
+ ~AggregateBuilderBase() {
+ assert(Finished && "didn't finish aggregate builder");
+ }
+
+ void markFinished() {
+ assert(!Frozen && "child builder still active");
+ assert(!Finished && "builder already finished");
+ Finished = true;
+ if (Parent) {
+ assert(Parent->Frozen &&
+ "parent not frozen while child builder active");
+ Parent->Frozen = false;
+ } else {
+ assert(Builder.Frozen &&
+ "builder not frozen while child builder active");
+ Builder.Frozen = false;
+ }
+ }
+
+ public:
+ // Not copyable.
+ AggregateBuilderBase(const AggregateBuilderBase &) = delete;
+ AggregateBuilderBase &operator=(const AggregateBuilderBase &) = delete;
+
+ // Movable, mostly to allow returning. But we have to write this out
+ // properly to satisfy the assert in the destructor.
+ AggregateBuilderBase(AggregateBuilderBase &&other)
+ : Builder(other.Builder), Parent(other.Parent), Begin(other.Begin),
+ Finished(other.Finished), Frozen(other.Frozen) {
+ other.Finished = false;
+ }
+ AggregateBuilderBase &operator=(AggregateBuilderBase &&other) = delete;
+
+ /// Abandon this builder completely.
+ void abandon() {
+ markFinished();
+ auto &buffer = Builder.Buffer;
+ buffer.erase(buffer.begin() + Begin, buffer.end());
+ }
+
+ /// Add a new value to this initializer.
+ void add(llvm::Constant *value) {
+ assert(value && "adding null value to constant initializer");
+ assert(!Finished && "cannot add more values after finishing builder");
+ assert(!Frozen && "cannot add values while subbuilder is active");
+ Builder.Buffer.push_back(value);
+ }
+
+ /// Add an integer value of type size_t.
+ void addSize(CharUnits size) {
+ add(Builder.CGM.getSize(size));
+ }
+
+ /// Add an integer value of a specific type.
+ void addInt(llvm::IntegerType *intTy, uint64_t value,
+ bool isSigned = false) {
+ add(llvm::ConstantInt::get(intTy, value, isSigned));
+ }
+
+ /// Add a null pointer of a specific type.
+ void addNullPointer(llvm::PointerType *ptrTy) {
+ add(llvm::ConstantPointerNull::get(ptrTy));
+ }
+
+ /// Add a bitcast of a value to a specific type.
+ void addBitCast(llvm::Constant *value, llvm::Type *type) {
+ add(llvm::ConstantExpr::getBitCast(value, type));
+ }
+
+ /// Add a bunch of new values to this initializer.
+ void addAll(ArrayRef<llvm::Constant *> values) {
+ assert(!Finished && "cannot add more values after finishing builder");
+ assert(!Frozen && "cannot add values while subbuilder is active");
+ Builder.Buffer.append(values.begin(), values.end());
+ }
+
+ /// An opaque class to hold the abstract position of a placeholder.
+ class PlaceholderPosition {
+ size_t Index;
+ friend class AggregateBuilderBase;
+ PlaceholderPosition(size_t index) : Index(index) {}
+ };
+
+ /// Add a placeholder value to the structure. The returned position
+ /// can be used to set the value later; it will not be invalidated by
+ /// any intermediate operations except (1) filling the same position or
+ /// (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
+ /// of the data. By emitting a placeholder first, the structure can
+ /// be emitted eagerly.
+ PlaceholderPosition addPlaceholder() {
+ assert(!Finished && "cannot add more values after finishing builder");
+ assert(!Frozen && "cannot add values while subbuilder is active");
+ Builder.Buffer.push_back(nullptr);
+ return Builder.Buffer.size() - 1;
+ }
+
+ /// Fill a previously-added placeholder.
+ void fillPlaceholderWithInt(PlaceholderPosition position,
+ llvm::IntegerType *type, uint64_t value,
+ bool isSigned = false) {
+ fillPlaceholder(position, llvm::ConstantInt::get(type, value, isSigned));
+ }
+
+ /// Fill a previously-added placeholder.
+ void fillPlaceholder(PlaceholderPosition position, llvm::Constant *value) {
+ assert(!Finished && "cannot change values after finishing builder");
+ assert(!Frozen && "cannot add values while subbuilder is active");
+ llvm::Constant *&slot = Builder.Buffer[position.Index];
+ assert(slot == nullptr && "placeholder already filled");
+ slot = value;
+ }
+
+ /// Produce an address which will eventually point to the the next
+ /// position to be filled. This is computed with an indexed
+ /// getelementptr rather than by computing offsets.
+ ///
+ /// The returned pointer will have type T*, where T is the given
+ /// position.
+ llvm::Constant *getAddrOfCurrentPosition(llvm::Type *type) {
+ // Make a global variable. We will replace this with a GEP to this
+ // position after installing the initializer.
+ auto dummy =
+ new llvm::GlobalVariable(Builder.CGM.getModule(), type, true,
+ llvm::GlobalVariable::PrivateLinkage,
+ nullptr, "");
+ Builder.SelfReferences.emplace_back(dummy);
+ auto &entry = Builder.SelfReferences.back();
+ (void) getGEPIndicesToCurrentPosition(entry.Indices);
+ return dummy;
+ }
+
+ ArrayRef<llvm::Constant*> getGEPIndicesToCurrentPosition(
+ llvm::SmallVectorImpl<llvm::Constant*> &indices) {
+ getGEPIndicesTo(indices, Builder.Buffer.size());
+ return indices;
+ }
+
+ ConstantArrayBuilder beginArray(llvm::Type *eltTy = nullptr);
+ ConstantStructBuilder beginStruct(llvm::StructType *structTy = nullptr);
+
+ private:
+ void getGEPIndicesTo(llvm::SmallVectorImpl<llvm::Constant*> &indices,
+ size_t position) const {
+ // Recurse on the parent builder if present.
+ if (Parent) {
+ Parent->getGEPIndicesTo(indices, Begin);
+
+ // Otherwise, add an index to drill into the first level of pointer.
+ } else {
+ assert(indices.empty());
+ indices.push_back(llvm::ConstantInt::get(Builder.CGM.Int32Ty, 0));
+ }
+
+ assert(position >= Begin);
+ // We have to use i32 here because struct GEPs demand i32 indices.
+ // It's rather unlikely to matter in practice.
+ indices.push_back(llvm::ConstantInt::get(Builder.CGM.Int32Ty,
+ position - Begin));
+ }
+ };
+
+ template <class Impl>
+ class AggregateBuilder : public AggregateBuilderBase {
+ protected:
+ AggregateBuilder(ConstantInitBuilder &builder,
+ AggregateBuilderBase *parent)
+ : AggregateBuilderBase(builder, parent) {}
+
+ Impl &asImpl() { return *static_cast<Impl*>(this); }
+
+ public:
+ /// Given that this builder was created by beginning an array or struct
+ /// component on the given parent builder, finish the array/struct
+ /// component and add it to the parent.
+ ///
+ /// It is an intentional choice that the parent is passed in explicitly
+ /// despite it being redundant with information already kept in the
+ /// builder. This aids in readability by making it easier to find the
+ /// places that add components to a builder, as well as "bookending"
+ /// the sub-builder more explicitly.
+ void finishAndAddTo(AggregateBuilderBase &parent) {
+ assert(Parent == &parent && "adding to non-parent builder");
+ parent.add(asImpl().finishImpl());
+ }
+
+ /// Given that this builder was created by beginning an array or struct
+ /// directly on a ConstantInitBuilder, finish the array/struct and
+ /// create a global variable with it as the initializer.
+ template <class... As>
+ llvm::GlobalVariable *finishAndCreateGlobal(As &&...args) {
+ assert(!Parent && "finishing non-root builder");
+ return Builder.createGlobal(asImpl().finishImpl(),
+ std::forward<As>(args)...);
+ }
+
+ /// Given that this builder was created by beginning an array or struct
+ /// directly on a ConstantInitBuilder, finish the array/struct and
+ /// set it as the initializer of the given global variable.
+ void finishAndSetAsInitializer(llvm::GlobalVariable *global) {
+ assert(!Parent && "finishing non-root builder");
+ return Builder.setGlobalInitializer(global, asImpl().finishImpl());
+ }
+ };
+
+ ConstantArrayBuilder beginArray(llvm::Type *eltTy = nullptr);
+
+ ConstantStructBuilder beginStruct(llvm::StructType *structTy = nullptr);
+
+private:
+ llvm::GlobalVariable *createGlobal(llvm::Constant *initializer,
+ const llvm::Twine &name,
+ CharUnits alignment,
+ bool constant = false,
+ llvm::GlobalValue::LinkageTypes linkage
+ = llvm::GlobalValue::InternalLinkage,
+ unsigned addressSpace = 0) {
+ auto GV = new llvm::GlobalVariable(CGM.getModule(),
+ initializer->getType(),
+ constant,
+ linkage,
+ initializer,
+ name,
+ /*insert before*/ nullptr,
+ llvm::GlobalValue::NotThreadLocal,
+ addressSpace);
+ GV->setAlignment(alignment.getQuantity());
+ resolveSelfReferences(GV);
+ return GV;
+ }
+
+ void setGlobalInitializer(llvm::GlobalVariable *GV,
+ llvm::Constant *initializer) {
+ GV->setInitializer(initializer);
+ resolveSelfReferences(GV);
+ }
+
+ void resolveSelfReferences(llvm::GlobalVariable *GV) {
+ for (auto &entry : SelfReferences) {
+ llvm::Constant *resolvedReference =
+ llvm::ConstantExpr::getInBoundsGetElementPtr(
+ GV->getValueType(), GV, entry.Indices);
+ entry.Dummy->replaceAllUsesWith(resolvedReference);
+ entry.Dummy->eraseFromParent();
+ }
+ }
+};
+
+/// A helper class of ConstantInitBuilder, used for building constant
+/// array initializers.
+class ConstantArrayBuilder
+ : public ConstantInitBuilder::AggregateBuilder<ConstantArrayBuilder> {
+ llvm::Type *EltTy;
+ friend class ConstantInitBuilder;
+ template <class Impl> friend class ConstantInitBuilder::AggregateBuilder;
+ ConstantArrayBuilder(ConstantInitBuilder &builder,
+ AggregateBuilderBase *parent, llvm::Type *eltTy)
+ : AggregateBuilder(builder, parent), EltTy(eltTy) {}
+public:
+ size_t size() const {
+ assert(!Finished);
+ assert(!Frozen);
+ assert(Begin <= getBuffer().size());
+ return getBuffer().size() - Begin;
+ }
+
+ bool empty() const {
+ return size() == 0;
+ }
+
+private:
+ /// Form an array constant from the values that have been added to this
+ /// builder.
+ llvm::Constant *finishImpl() {
+ markFinished();
+
+ auto &buffer = getBuffer();
+ assert((Begin < buffer.size() ||
+ (Begin == buffer.size() && EltTy))
+ && "didn't add any array elements without element type");
+ auto elts = llvm::makeArrayRef(buffer).slice(Begin);
+ auto eltTy = EltTy ? EltTy : elts[0]->getType();
+ auto type = llvm::ArrayType::get(eltTy, elts.size());
+ auto constant = llvm::ConstantArray::get(type, elts);
+ buffer.erase(buffer.begin() + Begin, buffer.end());
+ return constant;
+ }
+};
+
+inline ConstantArrayBuilder
+ConstantInitBuilder::beginArray(llvm::Type *eltTy) {
+ return ConstantArrayBuilder(*this, nullptr, eltTy);
+}
+
+inline ConstantArrayBuilder
+ConstantInitBuilder::AggregateBuilderBase::beginArray(llvm::Type *eltTy) {
+ return ConstantArrayBuilder(Builder, this, eltTy);
+}
+
+/// A helper class of ConstantInitBuilder, used for building constant
+/// struct initializers.
+class ConstantStructBuilder
+ : public ConstantInitBuilder::AggregateBuilder<ConstantStructBuilder> {
+ llvm::StructType *Ty;
+ friend class ConstantInitBuilder;
+ template <class Impl> friend class ConstantInitBuilder::AggregateBuilder;
+ ConstantStructBuilder(ConstantInitBuilder &builder,
+ AggregateBuilderBase *parent, llvm::StructType *ty)
+ : AggregateBuilder(builder, parent), Ty(ty) {}
+
+ /// Finish the struct.
+ llvm::Constant *finishImpl() {
+ markFinished();
+
+ auto &buffer = getBuffer();
+ assert(Begin < buffer.size() && "didn't add any struct elements?");
+ auto elts = llvm::makeArrayRef(buffer).slice(Begin);
+
+ llvm::Constant *constant;
+ if (Ty) {
+ constant = llvm::ConstantStruct::get(Ty, elts);
+ } else {
+ constant = llvm::ConstantStruct::getAnon(elts, /*packed*/ false);
+ }
+
+ buffer.erase(buffer.begin() + Begin, buffer.end());
+ return constant;
+ }
+};
+
+inline ConstantStructBuilder
+ConstantInitBuilder::beginStruct(llvm::StructType *structTy) {
+ return ConstantStructBuilder(*this, nullptr, structTy);
+}
+
+inline ConstantStructBuilder
+ConstantInitBuilder::AggregateBuilderBase::beginStruct(
+ llvm::StructType *structTy) {
+ return ConstantStructBuilder(Builder, this, structTy);
+}
+
+} // end namespace CodeGen
+} // end namespace clang
+
+#endif
diff --git a/lib/CodeGen/CoverageMappingGen.cpp b/lib/CodeGen/CoverageMappingGen.cpp
index b011a0f319e3..5bc9e5011aa8 100644
--- a/lib/CodeGen/CoverageMappingGen.cpp
+++ b/lib/CodeGen/CoverageMappingGen.cpp
@@ -23,6 +23,7 @@
#include "llvm/ProfileData/Coverage/CoverageMappingWriter.h"
#include "llvm/ProfileData/InstrProfReader.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
using namespace clang;
using namespace CodeGen;
@@ -91,6 +92,14 @@ public:
/// \brief The source mapping regions for this function.
std::vector<SourceMappingRegion> SourceRegions;
+ /// \brief 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
+ /// the same area is covered by expansion regions.
+ typedef llvm::SmallSet<std::pair<SourceLocation, SourceLocation>, 8>
+ SourceRegionFilter;
+
CoverageMappingBuilder(CoverageMappingModuleGen &CVM, SourceManager &SM,
const LangOptions &LangOpts)
: CVM(CVM), SM(SM), LangOpts(LangOpts) {}
@@ -127,7 +136,7 @@ public:
/// \brief Return true if \c Loc is a location in a built-in macro.
bool isInBuiltin(SourceLocation Loc) {
- return strcmp(SM.getBufferName(SM.getSpellingLoc(Loc)), "<built-in>") == 0;
+ return SM.getBufferName(SM.getSpellingLoc(Loc)) == "<built-in>";
}
/// \brief Check whether \c Loc is included or expanded from \c Parent.
@@ -248,7 +257,7 @@ public:
/// \brief Generate the coverage counter mapping regions from collected
/// source regions.
- void emitSourceRegions() {
+ void emitSourceRegions(const SourceRegionFilter &Filter) {
for (const auto &Region : SourceRegions) {
assert(Region.hasEndLoc() && "incomplete region");
@@ -268,6 +277,13 @@ public:
assert(SM.isWrittenInSameFile(LocStart, LocEnd) &&
"region spans multiple files");
+ // Don't add code regions for the area covered by expansion regions.
+ // This not only suppresses redundant regions, but sometimes prevents
+ // creating regions with wrong counters if, for example, a statement's
+ // body ends at the end of a nested macro.
+ if (Filter.count(std::make_pair(LocStart, LocEnd)))
+ continue;
+
// Find the spilling locations for the mapping region.
unsigned LineStart = SM.getSpellingLineNumber(LocStart);
unsigned ColumnStart = SM.getSpellingColumnNumber(LocStart);
@@ -282,7 +298,8 @@ public:
}
/// \brief Generate expansion regions for each virtual file we've seen.
- void emitExpansionRegions() {
+ SourceRegionFilter emitExpansionRegions() {
+ SourceRegionFilter Filter;
for (const auto &FM : FileIDMapping) {
SourceLocation ExpandedLoc = FM.second.second;
SourceLocation ParentLoc = getIncludeOrExpansionLoc(ExpandedLoc);
@@ -298,6 +315,7 @@ public:
SourceLocation LocEnd = getPreciseTokenLocEnd(ParentLoc);
assert(SM.isWrittenInSameFile(ParentLoc, LocEnd) &&
"region spans multiple files");
+ Filter.insert(std::make_pair(ParentLoc, LocEnd));
unsigned LineStart = SM.getSpellingLineNumber(ParentLoc);
unsigned ColumnStart = SM.getSpellingColumnNumber(ParentLoc);
@@ -308,6 +326,7 @@ public:
*ParentFileID, *ExpandedFileID, LineStart, ColumnStart, LineEnd,
ColumnEnd));
}
+ return Filter;
}
};
@@ -349,7 +368,7 @@ struct EmptyCoverageMappingBuilder : public CoverageMappingBuilder {
void write(llvm::raw_ostream &OS) {
SmallVector<unsigned, 16> FileIDMapping;
gatherFileIDs(FileIDMapping);
- emitSourceRegions();
+ emitSourceRegions(SourceRegionFilter());
if (MappingRegions.empty())
return;
@@ -431,7 +450,8 @@ struct CounterCoverageMappingBuilder
SourceLocation NestedLoc = getStartOfFileOrMacro(EndLoc);
assert(SM.isWrittenInSameFile(NestedLoc, EndLoc));
- SourceRegions.emplace_back(Region.getCounter(), NestedLoc, EndLoc);
+ if (!isRegionAlreadyAdded(NestedLoc, EndLoc))
+ SourceRegions.emplace_back(Region.getCounter(), NestedLoc, EndLoc);
EndLoc = getPreciseTokenLocEnd(getIncludeOrExpansionLoc(EndLoc));
if (EndLoc.isInvalid())
@@ -603,8 +623,8 @@ struct CounterCoverageMappingBuilder
void write(llvm::raw_ostream &OS) {
llvm::SmallVector<unsigned, 8> VirtualFileMapping;
gatherFileIDs(VirtualFileMapping);
- emitSourceRegions();
- emitExpansionRegions();
+ SourceRegionFilter Filter = emitExpansionRegions();
+ emitSourceRegions(Filter);
gatherSkippedRegions();
if (MappingRegions.empty())
@@ -793,6 +813,8 @@ struct CounterCoverageMappingBuilder
void VisitSwitchStmt(const SwitchStmt *S) {
extendRegion(S);
+ if (S->getInit())
+ Visit(S->getInit());
Visit(S->getCond());
BreakContinueStack.push_back(BreakContinue());
@@ -822,7 +844,11 @@ struct CounterCoverageMappingBuilder
Counter ExitCount = getRegionCounter(S);
SourceLocation ExitLoc = getEnd(S);
- pushRegion(ExitCount, getStart(S), ExitLoc);
+ pushRegion(ExitCount);
+
+ // Ensure that handleFileExit recognizes when the end location is located
+ // in a different file.
+ MostRecentLocation = getStart(S);
handleFileExit(ExitLoc);
}
@@ -849,6 +875,9 @@ struct CounterCoverageMappingBuilder
void VisitIfStmt(const IfStmt *S) {
extendRegion(S);
+ if (S->getInit())
+ Visit(S->getInit());
+
// Extend into the condition before we propagate through it below - this is
// needed to handle macros that generate the "if" but not the condition.
extendRegion(S->getCond());
@@ -931,16 +960,24 @@ struct CounterCoverageMappingBuilder
// propagate counts into them.
}
};
-}
-static bool isMachO(const CodeGenModule &CGM) {
+bool isMachO(const CodeGenModule &CGM) {
return CGM.getTarget().getTriple().isOSBinFormatMachO();
}
-static StringRef getCoverageSection(const CodeGenModule &CGM) {
+StringRef getCoverageSection(const CodeGenModule &CGM) {
return llvm::getInstrProfCoverageSectionName(isMachO(CGM));
}
+std::string normalizeFilename(StringRef Filename) {
+ llvm::SmallString<256> Path(Filename);
+ llvm::sys::fs::make_absolute(Path);
+ llvm::sys::path::remove_dots(Path, /*remove_dot_dots=*/true);
+ return Path.str().str();
+}
+
+} // end anonymous namespace
+
static void dump(llvm::raw_ostream &OS, StringRef FunctionName,
ArrayRef<CounterExpression> Expressions,
ArrayRef<CounterMappingRegion> Regions) {
@@ -1002,10 +1039,15 @@ void CoverageMappingModuleGen::addFunctionMappingRecord(
std::vector<StringRef> Filenames;
std::vector<CounterExpression> Expressions;
std::vector<CounterMappingRegion> Regions;
+ llvm::SmallVector<std::string, 16> FilenameStrs;
llvm::SmallVector<StringRef, 16> FilenameRefs;
+ FilenameStrs.resize(FileEntries.size());
FilenameRefs.resize(FileEntries.size());
- for (const auto &Entry : FileEntries)
- FilenameRefs[Entry.second] = Entry.first->getName();
+ for (const auto &Entry : FileEntries) {
+ auto I = Entry.second;
+ FilenameStrs[I] = normalizeFilename(Entry.first->getName());
+ FilenameRefs[I] = FilenameStrs[I];
+ }
RawCoverageMappingReader Reader(CoverageMapping, FilenameRefs, Filenames,
Expressions, Regions);
if (Reader.read())
@@ -1026,11 +1068,8 @@ void CoverageMappingModuleGen::emit() {
FilenameStrs.resize(FileEntries.size());
FilenameRefs.resize(FileEntries.size());
for (const auto &Entry : FileEntries) {
- llvm::SmallString<256> Path(Entry.first->getName());
- llvm::sys::fs::make_absolute(Path);
-
auto I = Entry.second;
- FilenameStrs[I] = std::string(Path.begin(), Path.end());
+ FilenameStrs[I] = normalizeFilename(Entry.first->getName());
FilenameRefs[I] = FilenameStrs[I];
}
diff --git a/lib/CodeGen/CoverageMappingGen.h b/lib/CodeGen/CoverageMappingGen.h
index c202fe899343..b6789c2a79f1 100644
--- a/lib/CodeGen/CoverageMappingGen.h
+++ b/lib/CodeGen/CoverageMappingGen.h
@@ -19,7 +19,6 @@
#include "clang/Frontend/CodeGenOptions.h"
#include "clang/Lex/PPCallbacks.h"
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/StringMap.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/Support/raw_ostream.h"
diff --git a/lib/CodeGen/EHScopeStack.h b/lib/CodeGen/EHScopeStack.h
index 4717a667d2d2..243583038558 100644
--- a/lib/CodeGen/EHScopeStack.h
+++ b/lib/CodeGen/EHScopeStack.h
@@ -271,7 +271,7 @@ public:
/// Push a lazily-created cleanup on the stack.
template <class T, class... As> void pushCleanup(CleanupKind Kind, As... A) {
- static_assert(llvm::AlignOf<T>::Alignment <= ScopeStackAlignment,
+ static_assert(alignof(T) <= ScopeStackAlignment,
"Cleanup's alignment is too large.");
void *Buffer = pushCleanup(Kind, sizeof(T));
Cleanup *Obj = new (Buffer) T(A...);
@@ -281,7 +281,7 @@ public:
/// Push a lazily-created cleanup on the stack. Tuple version.
template <class T, class... As>
void pushCleanupTuple(CleanupKind Kind, std::tuple<As...> A) {
- static_assert(llvm::AlignOf<T>::Alignment <= ScopeStackAlignment,
+ static_assert(alignof(T) <= ScopeStackAlignment,
"Cleanup's alignment is too large.");
void *Buffer = pushCleanup(Kind, sizeof(T));
Cleanup *Obj = new (Buffer) T(std::move(A));
@@ -303,7 +303,7 @@ public:
/// stack is modified.
template <class T, class... As>
T *pushCleanupWithExtra(CleanupKind Kind, size_t N, As... A) {
- static_assert(llvm::AlignOf<T>::Alignment <= ScopeStackAlignment,
+ static_assert(alignof(T) <= ScopeStackAlignment,
"Cleanup's alignment is too large.");
void *Buffer = pushCleanup(Kind, sizeof(T) + T::getExtraSize(N));
return new (Buffer) T(N, A...);
diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp
index 6051594fb001..b5d90ea59a49 100644
--- a/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/lib/CodeGen/ItaniumCXXABI.cpp
@@ -24,6 +24,7 @@
#include "CGVTables.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
+#include "ConstantBuilder.h"
#include "TargetInfo.h"
#include "clang/AST/Mangle.h"
#include "clang/AST/Type.h"
@@ -45,6 +46,7 @@ class ItaniumCXXABI : public CodeGen::CGCXXABI {
protected:
bool UseARMMethodPtrABI;
bool UseARMGuardVarABI;
+ bool Use32BitVTableOffsetABI;
ItaniumMangleContext &getMangleContext() {
return cast<ItaniumMangleContext>(CodeGen::CGCXXABI::getMangleContext());
@@ -55,7 +57,8 @@ public:
bool UseARMMethodPtrABI = false,
bool UseARMGuardVarABI = false) :
CGCXXABI(CGM), UseARMMethodPtrABI(UseARMMethodPtrABI),
- UseARMGuardVarABI(UseARMGuardVarABI) { }
+ UseARMGuardVarABI(UseARMGuardVarABI),
+ Use32BitVTableOffsetABI(false) { }
bool classifyReturnType(CGFunctionInfo &FI) const override;
@@ -112,7 +115,7 @@ public:
llvm::Type *ConvertMemberPointerType(const MemberPointerType *MPT) override;
- llvm::Value *
+ CGCallee
EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
const Expr *E,
Address This,
@@ -168,8 +171,8 @@ public:
emitTerminateForUnexpectedException(CodeGenFunction &CGF,
llvm::Value *Exn) override;
- void EmitFundamentalRTTIDescriptor(QualType Type);
- void EmitFundamentalRTTIDescriptors();
+ void EmitFundamentalRTTIDescriptor(QualType Type, bool DLLExport);
+ void EmitFundamentalRTTIDescriptors(bool DLLExport);
llvm::Constant *getAddrOfRTTIDescriptor(QualType Ty) override;
CatchTypeInfo
getAddrOfCXXCatchHandlerType(QualType Ty,
@@ -261,9 +264,9 @@ public:
llvm::GlobalVariable *getAddrOfVTable(const CXXRecordDecl *RD,
CharUnits VPtrOffset) override;
- llvm::Value *getVirtualFunctionPointer(CodeGenFunction &CGF, GlobalDecl GD,
- Address This, llvm::Type *Ty,
- SourceLocation Loc) override;
+ CGCallee getVirtualFunctionPointer(CodeGenFunction &CGF, GlobalDecl GD,
+ Address This, llvm::Type *Ty,
+ SourceLocation Loc) override;
llvm::Value *EmitVirtualDestructorCall(CodeGenFunction &CGF,
const CXXDestructorDecl *Dtor,
@@ -363,11 +366,12 @@ public:
void emitCXXStructor(const CXXMethodDecl *MD, StructorType Type) override;
private:
- bool hasAnyUsedVirtualInlineFunction(const CXXRecordDecl *RD) const {
+ bool hasAnyVirtualInlineFunction(const CXXRecordDecl *RD) const {
const auto &VtableLayout =
CGM.getItaniumVTableContext().getVTableLayout(RD);
for (const auto &VtableComponent : VtableLayout.vtable_components()) {
+ // Skip empty slot.
if (!VtableComponent.isUsedFunctionPointerKind())
continue;
@@ -425,7 +429,9 @@ public:
class iOS64CXXABI : public ARMCXXABI {
public:
- iOS64CXXABI(CodeGen::CodeGenModule &CGM) : ARMCXXABI(CGM) {}
+ iOS64CXXABI(CodeGen::CodeGenModule &CGM) : ARMCXXABI(CGM) {
+ Use32BitVTableOffsetABI = true;
+ }
// ARM64 libraries are prepared for non-unique RTTI.
bool shouldRTTIBeUnique() const override { return false; }
@@ -516,7 +522,7 @@ ItaniumCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) {
///
/// If the member is non-virtual, memptr.ptr is the address of
/// the function to call.
-llvm::Value *ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
+CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
CodeGenFunction &CGF, const Expr *E, Address ThisAddr,
llvm::Value *&ThisPtrForCall,
llvm::Value *MemFnPtr, const MemberPointerType *MPT) {
@@ -579,9 +585,15 @@ llvm::Value *ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
CGF.GetVTablePtr(Address(This, VTablePtrAlign), VTableTy, RD);
// Apply the offset.
+ // On ARM64, to reserve extra space in virtual member function pointers,
+ // we only pay attention to the low 32 bits of the offset.
llvm::Value *VTableOffset = FnAsInt;
if (!UseARMMethodPtrABI)
VTableOffset = Builder.CreateSub(VTableOffset, ptrdiff_1);
+ if (Use32BitVTableOffsetABI) {
+ VTableOffset = Builder.CreateTrunc(VTableOffset, CGF.Int32Ty);
+ VTableOffset = Builder.CreateZExt(VTableOffset, CGM.PtrDiffTy);
+ }
VTable = Builder.CreateGEP(VTable, VTableOffset);
// Load the virtual function to call.
@@ -599,9 +611,11 @@ llvm::Value *ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
// We're done.
CGF.EmitBlock(FnEnd);
- llvm::PHINode *Callee = Builder.CreatePHI(FTy->getPointerTo(), 2);
- Callee->addIncoming(VirtualFn, FnVirtual);
- Callee->addIncoming(NonVirtualFn, FnNonVirtual);
+ llvm::PHINode *CalleePtr = Builder.CreatePHI(FTy->getPointerTo(), 2);
+ CalleePtr->addIncoming(VirtualFn, FnVirtual);
+ CalleePtr->addIncoming(NonVirtualFn, FnNonVirtual);
+
+ CGCallee Callee(FPT, CalleePtr);
return Callee;
}
@@ -1390,6 +1404,10 @@ void ItaniumCXXABI::addImplicitStructorParams(CodeGenFunction &CGF,
}
void ItaniumCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
+ // Naked functions have no prolog.
+ if (CGF.CurFuncDecl && CGF.CurFuncDecl->hasAttr<NakedAttr>())
+ return;
+
/// Initialize the 'this' slot.
EmitThisParam(CGF);
@@ -1434,15 +1452,18 @@ void ItaniumCXXABI::EmitDestructorCall(CodeGenFunction &CGF,
llvm::Value *VTT = CGF.GetVTTParameter(GD, ForVirtualBase, Delegating);
QualType VTTTy = getContext().getPointerType(getContext().VoidPtrTy);
- llvm::Value *Callee = nullptr;
- if (getContext().getLangOpts().AppleKext)
+ CGCallee Callee;
+ if (getContext().getLangOpts().AppleKext &&
+ Type != Dtor_Base && DD->isVirtual())
Callee = CGF.BuildAppleKextVirtualDestructorCall(DD, Type, DD->getParent());
-
- if (!Callee)
- Callee = CGM.getAddrOfCXXStructor(DD, getFromDtorType(Type));
+ else
+ Callee =
+ CGCallee::forDirect(CGM.getAddrOfCXXStructor(DD, getFromDtorType(Type)),
+ DD);
CGF.EmitCXXMemberOrOperatorCall(DD, Callee, ReturnValueSlot(),
- This.getPointer(), VTT, VTTTy, nullptr);
+ This.getPointer(), VTT, VTTTy,
+ nullptr, nullptr);
}
void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,
@@ -1458,10 +1479,10 @@ void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,
CGM.GetAddrOfRTTIDescriptor(CGM.getContext().getTagDeclType(RD));
// Create and set the initializer.
- llvm::Constant *Init = CGVT.CreateVTableInitializer(
- RD, VTLayout.vtable_component_begin(), VTLayout.getNumVTableComponents(),
- VTLayout.vtable_thunk_begin(), VTLayout.getNumVTableThunks(), RTTI);
- VTable->setInitializer(Init);
+ ConstantInitBuilder Builder(CGM);
+ auto Components = Builder.beginStruct();
+ CGVT.createVTableInitializer(Components, VTLayout, RTTI);
+ Components.finishAndSetAsInitializer(VTable);
// Set the correct linkage.
VTable->setLinkage(Linkage);
@@ -1487,7 +1508,7 @@ void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,
isa<NamespaceDecl>(DC) && cast<NamespaceDecl>(DC)->getIdentifier() &&
cast<NamespaceDecl>(DC)->getIdentifier()->isStr("__cxxabiv1") &&
DC->getParent()->isTranslationUnit())
- EmitFundamentalRTTIDescriptors();
+ EmitFundamentalRTTIDescriptors(RD->hasAttr<DLLExportAttr>());
if (!VTable->isDeclarationForLinker())
CGM.EmitVTableTypeMetadata(VTable, VTLayout);
@@ -1517,17 +1538,21 @@ ItaniumCXXABI::getVTableAddressPoint(BaseSubobject Base,
const CXXRecordDecl *VTableClass) {
llvm::GlobalValue *VTable = getAddrOfVTable(VTableClass, CharUnits());
- // Find the appropriate vtable within the vtable group.
- uint64_t AddressPoint = CGM.getItaniumVTableContext()
- .getVTableLayout(VTableClass)
- .getAddressPoint(Base);
+ // Find the appropriate vtable within the vtable group, and the address point
+ // within that vtable.
+ VTableLayout::AddressPointLocation AddressPoint =
+ CGM.getItaniumVTableContext()
+ .getVTableLayout(VTableClass)
+ .getAddressPoint(Base);
llvm::Value *Indices[] = {
llvm::ConstantInt::get(CGM.Int32Ty, 0),
- llvm::ConstantInt::get(CGM.Int32Ty, AddressPoint)
+ llvm::ConstantInt::get(CGM.Int32Ty, AddressPoint.VTableIndex),
+ llvm::ConstantInt::get(CGM.Int32Ty, AddressPoint.AddressPointIndex),
};
- return llvm::ConstantExpr::getInBoundsGetElementPtr(VTable->getValueType(),
- VTable, Indices);
+ return llvm::ConstantExpr::getGetElementPtr(VTable->getValueType(), VTable,
+ Indices, /*InBounds=*/true,
+ /*InRangeIndex=*/1);
}
llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructorWithVTT(
@@ -1569,12 +1594,12 @@ llvm::GlobalVariable *ItaniumCXXABI::getAddrOfVTable(const CXXRecordDecl *RD,
llvm::raw_svector_ostream Out(Name);
getMangleContext().mangleCXXVTable(RD, Out);
- ItaniumVTableContext &VTContext = CGM.getItaniumVTableContext();
- llvm::ArrayType *ArrayType = llvm::ArrayType::get(
- CGM.Int8PtrTy, VTContext.getVTableLayout(RD).getNumVTableComponents());
+ const VTableLayout &VTLayout =
+ CGM.getItaniumVTableContext().getVTableLayout(RD);
+ llvm::Type *VTableType = CGM.getVTables().getVTableType(VTLayout);
VTable = CGM.CreateOrReplaceCXXRuntimeVariable(
- Name, ArrayType, llvm::GlobalValue::ExternalLinkage);
+ Name, VTableType, llvm::GlobalValue::ExternalLinkage);
VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
if (RD->hasAttr<DLLImportAttr>())
@@ -1585,19 +1610,20 @@ llvm::GlobalVariable *ItaniumCXXABI::getAddrOfVTable(const CXXRecordDecl *RD,
return VTable;
}
-llvm::Value *ItaniumCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
- GlobalDecl GD,
- Address This,
- llvm::Type *Ty,
- SourceLocation Loc) {
+CGCallee ItaniumCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
+ GlobalDecl GD,
+ 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());
uint64_t VTableIndex = CGM.getItaniumVTableContext().getMethodVTableIndex(GD);
+ llvm::Value *VFunc;
if (CGF.ShouldEmitVTableTypeCheckedLoad(MethodDecl->getParent())) {
- return CGF.EmitVTableTypeCheckedLoad(
+ VFunc = CGF.EmitVTableTypeCheckedLoad(
MethodDecl->getParent(), VTable,
VTableIndex * CGM.getContext().getTargetInfo().getPointerWidth(0) / 8);
} else {
@@ -1605,8 +1631,26 @@ llvm::Value *ItaniumCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
llvm::Value *VFuncPtr =
CGF.Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfn");
- return CGF.Builder.CreateAlignedLoad(VFuncPtr, CGF.getPointerAlign());
- }
+ auto *VFuncLoad =
+ CGF.Builder.CreateAlignedLoad(VFuncPtr, CGF.getPointerAlign());
+
+ // Add !invariant.load md to virtual function load to indicate that
+ // function didn't change inside vtable.
+ // It's safe to add it without -fstrict-vtable-pointers, but it would not
+ // help in devirtualization because it will only matter if we will have 2
+ // the same virtual function loads from the same vtable load, which won't
+ // happen without enabled devirtualization with -fstrict-vtable-pointers.
+ if (CGM.getCodeGenOpts().OptimizationLevel > 0 &&
+ CGM.getCodeGenOpts().StrictVTablePointers)
+ VFuncLoad->setMetadata(
+ llvm::LLVMContext::MD_invariant_load,
+ llvm::MDNode::get(CGM.getLLVMContext(),
+ llvm::ArrayRef<llvm::Metadata *>()));
+ VFunc = VFuncLoad;
+ }
+
+ CGCallee Callee(MethodDecl, VFunc);
+ return Callee;
}
llvm::Value *ItaniumCXXABI::EmitVirtualDestructorCall(
@@ -1618,13 +1662,13 @@ llvm::Value *ItaniumCXXABI::EmitVirtualDestructorCall(
const CGFunctionInfo *FInfo = &CGM.getTypes().arrangeCXXStructorDeclaration(
Dtor, getFromDtorType(DtorType));
llvm::Type *Ty = CGF.CGM.getTypes().GetFunctionType(*FInfo);
- llvm::Value *Callee =
+ CGCallee Callee =
getVirtualFunctionPointer(CGF, GlobalDecl(Dtor, DtorType), This, Ty,
CE ? CE->getLocStart() : SourceLocation());
CGF.EmitCXXMemberOrOperatorCall(Dtor, Callee, ReturnValueSlot(),
This.getPointer(), /*ImplicitParam=*/nullptr,
- QualType(), CE);
+ QualType(), CE, nullptr);
return nullptr;
}
@@ -1644,7 +1688,7 @@ bool ItaniumCXXABI::canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const {
// then we are safe to emit 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 !hasAnyUsedVirtualInlineFunction(RD) && !isVTableHidden(RD);
+ return !hasAnyVirtualInlineFunction(RD) && !isVTableHidden(RD);
}
static llvm::Value *performTypeAdjustment(CodeGenFunction &CGF,
Address InitialPtr,
@@ -2342,8 +2386,7 @@ LValue ItaniumCXXABI::EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF,
llvm::Function *Wrapper = getOrCreateThreadLocalWrapper(VD, Val);
llvm::CallInst *CallVal = CGF.Builder.CreateCall(Wrapper);
- if (isThreadWrapperReplaceable(VD, CGF.CGM))
- CallVal->setCallingConv(llvm::CallingConv::CXX_FAST_TLS);
+ CallVal->setCallingConv(Wrapper->getCallingConv());
LValue LV;
if (VD->getType()->isReferenceType())
@@ -2436,7 +2479,13 @@ public:
/// PTI_ContainingClassIncomplete - Containing class is incomplete.
/// (in pointer to member).
- PTI_ContainingClassIncomplete = 0x10
+ PTI_ContainingClassIncomplete = 0x10,
+
+ /// PTI_TransactionSafe - Pointee is transaction_safe function (C++ TM TS).
+ //PTI_TransactionSafe = 0x20,
+
+ /// PTI_Noexcept - Pointee is noexcept function (C++1z).
+ PTI_Noexcept = 0x40,
};
// VMI type info flags.
@@ -2460,7 +2509,9 @@ public:
/// BuildTypeInfo - Build the RTTI type info struct for the given type.
///
/// \param Force - true to force the creation of this RTTI value
- llvm::Constant *BuildTypeInfo(QualType Ty, bool Force = false);
+ /// \param DLLExport - true to mark the RTTI value as DLLExport
+ llvm::Constant *BuildTypeInfo(QualType Ty, bool Force = false,
+ bool DLLExport = false);
};
}
@@ -2865,16 +2916,18 @@ static llvm::GlobalVariable::LinkageTypes getTypeInfoLinkage(CodeGenModule &CGM,
case VisibleNoLinkage:
case ExternalLinkage:
- if (!CGM.getLangOpts().RTTI) {
- // RTTI is not enabled, which means that this type info struct is going
- // to be used for exception handling. Give it linkonce_odr linkage.
+ // RTTI is not enabled, which means that this type info struct is going
+ // to be used for exception handling. Give it linkonce_odr linkage.
+ if (!CGM.getLangOpts().RTTI)
return llvm::GlobalValue::LinkOnceODRLinkage;
- }
if (const RecordType *Record = dyn_cast<RecordType>(Ty)) {
const CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl());
if (RD->hasAttr<WeakAttr>())
return llvm::GlobalValue::WeakODRLinkage;
+ if (CGM.getTriple().isWindowsItaniumEnvironment())
+ if (RD->hasAttr<DLLImportAttr>())
+ return llvm::GlobalValue::ExternalLinkage;
if (RD->isDynamicClass()) {
llvm::GlobalValue::LinkageTypes LT = CGM.getVTableLinkage(RD);
// MinGW won't export the RTTI information when there is a key function.
@@ -2892,7 +2945,8 @@ static llvm::GlobalVariable::LinkageTypes getTypeInfoLinkage(CodeGenModule &CGM,
llvm_unreachable("Invalid linkage!");
}
-llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty, bool Force) {
+llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty, bool Force,
+ bool DLLExport) {
// We want to operate on the canonical type.
Ty = Ty.getCanonicalType();
@@ -3075,25 +3129,28 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty, bool Force) {
llvmVisibility = llvm::GlobalValue::HiddenVisibility;
else
llvmVisibility = CodeGenModule::GetLLVMVisibility(Ty->getVisibility());
+
TypeName->setVisibility(llvmVisibility);
GV->setVisibility(llvmVisibility);
- return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy);
-}
-
-/// ComputeQualifierFlags - Compute the pointer type info flags from the
-/// given qualifier.
-static unsigned ComputeQualifierFlags(Qualifiers Quals) {
- unsigned Flags = 0;
-
- if (Quals.hasConst())
- Flags |= ItaniumRTTIBuilder::PTI_Const;
- if (Quals.hasVolatile())
- Flags |= ItaniumRTTIBuilder::PTI_Volatile;
- if (Quals.hasRestrict())
- Flags |= ItaniumRTTIBuilder::PTI_Restrict;
+ 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 (CGM.getLangOpts().RTTI && RD && RD->hasAttr<DLLImportAttr>()) {
+ 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);
+ }
+ }
- return Flags;
+ return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy);
}
/// BuildObjCObjectTypeInfo - Build the appropriate kind of type_info
@@ -3214,9 +3271,6 @@ void ItaniumRTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) {
if (!RD->getNumBases())
return;
- llvm::Type *LongLTy =
- CGM.getTypes().ConvertType(CGM.getContext().LongTy);
-
// Now add the base class descriptions.
// Itanium C++ ABI 2.9.5p6c:
@@ -3234,6 +3288,19 @@ void ItaniumRTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) {
// __offset_shift = 8
// };
// };
+
+ // If we're in mingw and 'long' isn't wide enough for a pointer, use 'long
+ // long' instead of 'long' for __offset_flags. libstdc++abi uses long long on
+ // LLP64 platforms.
+ // FIXME: Consider updating libc++abi to match, and extend this logic to all
+ // LLP64 platforms.
+ QualType OffsetFlagsTy = CGM.getContext().LongTy;
+ const TargetInfo &TI = CGM.getContext().getTargetInfo();
+ if (TI.getTriple().isOSCygMing() && TI.getPointerWidth(0) > TI.getLongWidth())
+ OffsetFlagsTy = CGM.getContext().LongLongTy;
+ llvm::Type *OffsetFlagsLTy =
+ CGM.getTypes().ConvertType(OffsetFlagsTy);
+
for (const auto &Base : RD->bases()) {
// The __base_type member points to the RTTI for the base type.
Fields.push_back(ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(Base.getType()));
@@ -3265,27 +3332,48 @@ void ItaniumRTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) {
if (Base.getAccessSpecifier() == AS_public)
OffsetFlags |= BCTI_Public;
- Fields.push_back(llvm::ConstantInt::get(LongLTy, OffsetFlags));
+ Fields.push_back(llvm::ConstantInt::get(OffsetFlagsLTy, OffsetFlags));
+ }
+}
+
+/// Compute the flags for a __pbase_type_info, and remove the corresponding
+/// pieces from \p Type.
+static unsigned extractPBaseFlags(ASTContext &Ctx, QualType &Type) {
+ unsigned Flags = 0;
+
+ if (Type.isConstQualified())
+ Flags |= ItaniumRTTIBuilder::PTI_Const;
+ if (Type.isVolatileQualified())
+ Flags |= ItaniumRTTIBuilder::PTI_Volatile;
+ if (Type.isRestrictQualified())
+ Flags |= ItaniumRTTIBuilder::PTI_Restrict;
+ Type = Type.getUnqualifiedType();
+
+ // Itanium C++ ABI 2.9.5p7:
+ // When the abi::__pbase_type_info is for a direct or indirect pointer to an
+ // incomplete class type, the incomplete target type flag is set.
+ if (ContainsIncompleteClassType(Type))
+ Flags |= ItaniumRTTIBuilder::PTI_Incomplete;
+
+ if (auto *Proto = Type->getAs<FunctionProtoType>()) {
+ if (Proto->isNothrow(Ctx)) {
+ Flags |= ItaniumRTTIBuilder::PTI_Noexcept;
+ Type = Ctx.getFunctionType(
+ Proto->getReturnType(), Proto->getParamTypes(),
+ Proto->getExtProtoInfo().withExceptionSpec(EST_None));
+ }
}
+
+ return Flags;
}
/// BuildPointerTypeInfo - Build an abi::__pointer_type_info struct,
/// used for pointer types.
void ItaniumRTTIBuilder::BuildPointerTypeInfo(QualType PointeeTy) {
- Qualifiers Quals;
- QualType UnqualifiedPointeeTy =
- CGM.getContext().getUnqualifiedArrayType(PointeeTy, Quals);
-
// Itanium C++ ABI 2.9.5p7:
// __flags is a flag word describing the cv-qualification and other
// attributes of the type pointed to
- unsigned Flags = ComputeQualifierFlags(Quals);
-
- // Itanium C++ ABI 2.9.5p7:
- // When the abi::__pbase_type_info is for a direct or indirect pointer to an
- // incomplete class type, the incomplete target type flag is set.
- if (ContainsIncompleteClassType(UnqualifiedPointeeTy))
- Flags |= PTI_Incomplete;
+ unsigned Flags = extractPBaseFlags(CGM.getContext(), PointeeTy);
llvm::Type *UnsignedIntLTy =
CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy);
@@ -3295,7 +3383,7 @@ void ItaniumRTTIBuilder::BuildPointerTypeInfo(QualType PointeeTy) {
// __pointee is a pointer to the std::type_info derivation for the
// unqualified type being pointed to.
llvm::Constant *PointeeTypeInfo =
- ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(UnqualifiedPointeeTy);
+ ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(PointeeTy);
Fields.push_back(PointeeTypeInfo);
}
@@ -3305,23 +3393,12 @@ void
ItaniumRTTIBuilder::BuildPointerToMemberTypeInfo(const MemberPointerType *Ty) {
QualType PointeeTy = Ty->getPointeeType();
- Qualifiers Quals;
- QualType UnqualifiedPointeeTy =
- CGM.getContext().getUnqualifiedArrayType(PointeeTy, Quals);
-
// Itanium C++ ABI 2.9.5p7:
// __flags is a flag word describing the cv-qualification and other
// attributes of the type pointed to.
- unsigned Flags = ComputeQualifierFlags(Quals);
+ unsigned Flags = extractPBaseFlags(CGM.getContext(), PointeeTy);
const RecordType *ClassType = cast<RecordType>(Ty->getClass());
-
- // Itanium C++ ABI 2.9.5p7:
- // When the abi::__pbase_type_info is for a direct or indirect pointer to an
- // incomplete class type, the incomplete target type flag is set.
- if (ContainsIncompleteClassType(UnqualifiedPointeeTy))
- Flags |= PTI_Incomplete;
-
if (IsIncompleteClassType(ClassType))
Flags |= PTI_ContainingClassIncomplete;
@@ -3333,7 +3410,7 @@ ItaniumRTTIBuilder::BuildPointerToMemberTypeInfo(const MemberPointerType *Ty) {
// __pointee is a pointer to the std::type_info derivation for the
// unqualified type being pointed to.
llvm::Constant *PointeeTypeInfo =
- ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(UnqualifiedPointeeTy);
+ ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(PointeeTy);
Fields.push_back(PointeeTypeInfo);
// Itanium C++ ABI 2.9.5p9:
@@ -3348,15 +3425,18 @@ llvm::Constant *ItaniumCXXABI::getAddrOfRTTIDescriptor(QualType Ty) {
return ItaniumRTTIBuilder(*this).BuildTypeInfo(Ty);
}
-void ItaniumCXXABI::EmitFundamentalRTTIDescriptor(QualType Type) {
+void ItaniumCXXABI::EmitFundamentalRTTIDescriptor(QualType Type,
+ bool DLLExport) {
QualType PointerType = getContext().getPointerType(Type);
QualType PointerTypeConst = getContext().getPointerType(Type.withConst());
- ItaniumRTTIBuilder(*this).BuildTypeInfo(Type, true);
- ItaniumRTTIBuilder(*this).BuildTypeInfo(PointerType, true);
- ItaniumRTTIBuilder(*this).BuildTypeInfo(PointerTypeConst, true);
+ ItaniumRTTIBuilder(*this).BuildTypeInfo(Type, /*Force=*/true, DLLExport);
+ ItaniumRTTIBuilder(*this).BuildTypeInfo(PointerType, /*Force=*/true,
+ DLLExport);
+ ItaniumRTTIBuilder(*this).BuildTypeInfo(PointerTypeConst, /*Force=*/true,
+ DLLExport);
}
-void ItaniumCXXABI::EmitFundamentalRTTIDescriptors() {
+void ItaniumCXXABI::EmitFundamentalRTTIDescriptors(bool DLLExport) {
// Types added here must also be added to TypeInfoIsInStandardLibrary.
QualType FundamentalTypes[] = {
getContext().VoidTy, getContext().NullPtrTy,
@@ -3373,7 +3453,7 @@ void ItaniumCXXABI::EmitFundamentalRTTIDescriptors() {
getContext().Char16Ty, getContext().Char32Ty
};
for (const QualType &FundamentalType : FundamentalTypes)
- EmitFundamentalRTTIDescriptor(FundamentalType);
+ EmitFundamentalRTTIDescriptor(FundamentalType, DLLExport);
}
/// What sort of uniqueness rules should we use for the RTTI for the
@@ -3820,7 +3900,8 @@ static llvm::Constant *getClangCallTerminateFn(CodeGenModule &CGM) {
llvm::FunctionType *fnTy =
llvm::FunctionType::get(CGM.VoidTy, CGM.Int8PtrTy, /*IsVarArgs=*/false);
llvm::Constant *fnRef =
- CGM.CreateRuntimeFunction(fnTy, "__clang_call_terminate");
+ CGM.CreateRuntimeFunction(fnTy, "__clang_call_terminate",
+ llvm::AttributeSet(), /*Local=*/true);
llvm::Function *fn = dyn_cast<llvm::Function>(fnRef);
if (fn && fn->empty()) {
diff --git a/lib/CodeGen/MicrosoftCXXABI.cpp b/lib/CodeGen/MicrosoftCXXABI.cpp
index 41cd53c2215f..38df455011e3 100644
--- a/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -19,6 +19,7 @@
#include "CGVTables.h"
#include "CodeGenModule.h"
#include "CodeGenTypes.h"
+#include "ConstantBuilder.h"
#include "TargetInfo.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
@@ -96,9 +97,9 @@ public:
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
const VBTableGlobals &VBGlobals = enumerateVBTables(RD);
- for (const VPtrInfo *VBT : *VBGlobals.VBTables) {
+ for (const std::unique_ptr<VPtrInfo> &VBT : *VBGlobals.VBTables) {
const ASTRecordLayout &SubobjectLayout =
- Context.getASTRecordLayout(VBT->BaseWithVPtr);
+ Context.getASTRecordLayout(VBT->IntroducingObject);
CharUnits Offs = VBT->NonVirtualOffset;
Offs += SubobjectLayout.getVBPtrOffset();
if (VBT->getVBaseWithVPtr())
@@ -122,7 +123,7 @@ public:
void emitBeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *C) override;
llvm::GlobalVariable *getMSCompleteObjectLocator(const CXXRecordDecl *RD,
- const VPtrInfo *Info);
+ const VPtrInfo &Info);
llvm::Constant *getAddrOfRTTIDescriptor(QualType Ty) override;
CatchTypeInfo
@@ -164,6 +165,9 @@ public:
llvm::BasicBlock *
EmitCtorCompleteObjectHandler(CodeGenFunction &CGF,
const CXXRecordDecl *RD) override;
+
+ llvm::BasicBlock *
+ EmitDtorCompleteObjectHandler(CodeGenFunction &CGF);
void initializeHiddenVirtualInheritanceMembers(CodeGenFunction &CGF,
const CXXRecordDecl *RD) override;
@@ -254,7 +258,7 @@ public:
CXXDtorType Type, bool ForVirtualBase,
bool Delegating, Address This) override;
- void emitVTableTypeMetadata(VPtrInfo *Info, const CXXRecordDecl *RD,
+ void emitVTableTypeMetadata(const VPtrInfo &Info, const CXXRecordDecl *RD,
llvm::GlobalVariable *VTable);
void emitVTableDefinitions(CodeGenVTables &CGVT,
@@ -284,9 +288,9 @@ public:
llvm::GlobalVariable *getAddrOfVTable(const CXXRecordDecl *RD,
CharUnits VPtrOffset) override;
- llvm::Value *getVirtualFunctionPointer(CodeGenFunction &CGF, GlobalDecl GD,
- Address This, llvm::Type *Ty,
- SourceLocation Loc) override;
+ CGCallee getVirtualFunctionPointer(CodeGenFunction &CGF, GlobalDecl GD,
+ Address This, llvm::Type *Ty,
+ SourceLocation Loc) override;
llvm::Value *EmitVirtualDestructorCall(CodeGenFunction &CGF,
const CXXDestructorDecl *Dtor,
@@ -660,7 +664,7 @@ public:
CastKind CK, CastExpr::path_const_iterator PathBegin,
CastExpr::path_const_iterator PathEnd, llvm::Constant *Src);
- llvm::Value *
+ CGCallee
EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF, const Expr *E,
Address This, llvm::Value *&ThisPtrForCall,
llvm::Value *MemPtr,
@@ -794,6 +798,12 @@ MicrosoftCXXABI::getRecordArgABI(const CXXRecordDecl *RD) const {
// FIXME: Implement for other architectures.
return RAA_Default;
+ case llvm::Triple::thumb:
+ // Use the simple Itanium rules for now.
+ // FIXME: This is incompatible with MSVC for arguments with a dtor and no
+ // copy ctor.
+ return !canCopyArgument(RD) ? RAA_Indirect : RAA_Default;
+
case llvm::Triple::x86:
// All record arguments are passed in memory on x86. Decide whether to
// construct the object directly in argument memory, or to construct the
@@ -824,25 +834,32 @@ MicrosoftCXXABI::getRecordArgABI(const CXXRecordDecl *RD) const {
getContext().getTypeSize(RD->getTypeForDecl()) > 64)
return RAA_Indirect;
- // We have a trivial copy constructor or no copy constructors, but we have
- // to make sure it isn't deleted.
- bool CopyDeleted = false;
+ // If this is true, the implicit copy constructor that Sema would have
+ // created would not be deleted. FIXME: We should provide a more direct way
+ // for CodeGen to ask whether the constructor was deleted.
+ if (!RD->hasUserDeclaredCopyConstructor() &&
+ !RD->hasUserDeclaredMoveConstructor() &&
+ !RD->needsOverloadResolutionForMoveConstructor() &&
+ !RD->hasUserDeclaredMoveAssignment() &&
+ !RD->needsOverloadResolutionForMoveAssignment())
+ return RAA_Default;
+
+ // Otherwise, Sema should have created an implicit copy constructor if
+ // needed.
+ assert(!RD->needsImplicitCopyConstructor());
+
+ // We have to make sure the trivial copy constructor isn't deleted.
for (const CXXConstructorDecl *CD : RD->ctors()) {
if (CD->isCopyConstructor()) {
assert(CD->isTrivial());
// We had at least one undeleted trivial copy ctor. Return directly.
if (!CD->isDeleted())
return RAA_Default;
- CopyDeleted = true;
}
}
// The trivial copy constructor was deleted. Return indirectly.
- if (CopyDeleted)
- return RAA_Indirect;
-
- // There were no copy ctors. Return in RAX.
- return RAA_Default;
+ return RAA_Indirect;
}
llvm_unreachable("invalid enum");
@@ -1121,6 +1138,25 @@ MicrosoftCXXABI::EmitCtorCompleteObjectHandler(CodeGenFunction &CGF,
return SkipVbaseCtorsBB;
}
+llvm::BasicBlock *
+MicrosoftCXXABI::EmitDtorCompleteObjectHandler(CodeGenFunction &CGF) {
+ llvm::Value *IsMostDerivedClass = getStructorImplicitParamValue(CGF);
+ assert(IsMostDerivedClass &&
+ "ctor for a class with virtual bases must have an implicit parameter");
+ llvm::Value *IsCompleteObject =
+ CGF.Builder.CreateIsNotNull(IsMostDerivedClass, "is_complete_object");
+
+ llvm::BasicBlock *CallVbaseDtorsBB = CGF.createBasicBlock("Dtor.dtor_vbases");
+ llvm::BasicBlock *SkipVbaseDtorsBB = CGF.createBasicBlock("Dtor.skip_vbases");
+ CGF.Builder.CreateCondBr(IsCompleteObject,
+ CallVbaseDtorsBB, SkipVbaseDtorsBB);
+
+ CGF.EmitBlock(CallVbaseDtorsBB);
+ // CGF will put the base dtor calls in this basic block for us later.
+
+ return SkipVbaseDtorsBB;
+}
+
void MicrosoftCXXABI::initializeHiddenVirtualInheritanceMembers(
CodeGenFunction &CGF, const CXXRecordDecl *RD) {
// In most cases, an override for a vbase virtual method can adjust
@@ -1208,10 +1244,10 @@ void MicrosoftCXXABI::EmitVBPtrStores(CodeGenFunction &CGF,
const VBTableGlobals &VBGlobals = enumerateVBTables(RD);
for (unsigned I = 0, E = VBGlobals.VBTables->size(); I != E; ++I) {
- const VPtrInfo *VBT = (*VBGlobals.VBTables)[I];
+ const std::unique_ptr<VPtrInfo> &VBT = (*VBGlobals.VBTables)[I];
llvm::GlobalVariable *GV = VBGlobals.Globals[I];
const ASTRecordLayout &SubobjectLayout =
- Context.getASTRecordLayout(VBT->BaseWithVPtr);
+ Context.getASTRecordLayout(VBT->IntroducingObject);
CharUnits Offs = VBT->NonVirtualOffset;
Offs += SubobjectLayout.getVBPtrOffset();
if (VBT->getVBaseWithVPtr())
@@ -1220,7 +1256,7 @@ void MicrosoftCXXABI::EmitVBPtrStores(CodeGenFunction &CGF,
llvm::Value *GVPtr =
CGF.Builder.CreateConstInBoundsGEP2_32(GV->getValueType(), GV, 0, 0);
VBPtr = CGF.Builder.CreateElementBitCast(VBPtr, GVPtr->getType(),
- "vbptr." + VBT->ReusingBase->getName());
+ "vbptr." + VBT->ObjectWithVPtr->getName());
CGF.Builder.CreateStore(GVPtr, VBPtr);
}
}
@@ -1417,6 +1453,10 @@ llvm::Value *MicrosoftCXXABI::adjustThisParameterInVirtualFunctionPrologue(
}
void MicrosoftCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
+ // Naked functions have no prolog.
+ if (CGF.CurFuncDecl && CGF.CurFuncDecl->hasAttr<NakedAttr>())
+ return;
+
EmitThisParam(CGF);
/// If this is a function that the ABI specifies returns 'this', initialize
@@ -1484,7 +1524,9 @@ void MicrosoftCXXABI::EmitDestructorCall(CodeGenFunction &CGF,
const CXXDestructorDecl *DD,
CXXDtorType Type, bool ForVirtualBase,
bool Delegating, Address This) {
- llvm::Value *Callee = CGM.getAddrOfCXXStructor(DD, getFromDtorType(Type));
+ CGCallee Callee = CGCallee::forDirect(
+ CGM.getAddrOfCXXStructor(DD, getFromDtorType(Type)),
+ DD);
if (DD->isVirtual()) {
assert(Type != CXXDtorType::Dtor_Deleting &&
@@ -1492,14 +1534,24 @@ void MicrosoftCXXABI::EmitDestructorCall(CodeGenFunction &CGF,
This = adjustThisArgumentForVirtualFunctionCall(CGF, GlobalDecl(DD, Type),
This, false);
}
+
+ llvm::BasicBlock *BaseDtorEndBB = nullptr;
+ if (ForVirtualBase && isa<CXXConstructorDecl>(CGF.CurCodeDecl)) {
+ BaseDtorEndBB = EmitDtorCompleteObjectHandler(CGF);
+ }
CGF.EmitCXXDestructorCall(DD, Callee, This.getPointer(),
/*ImplicitParam=*/nullptr,
/*ImplicitParamTy=*/QualType(), nullptr,
getFromDtorType(Type));
+ if (BaseDtorEndBB) {
+ // Complete object handler should continue to be the remaining
+ CGF.Builder.CreateBr(BaseDtorEndBB);
+ CGF.EmitBlock(BaseDtorEndBB);
+ }
}
-void MicrosoftCXXABI::emitVTableTypeMetadata(VPtrInfo *Info,
+void MicrosoftCXXABI::emitVTableTypeMetadata(const VPtrInfo &Info,
const CXXRecordDecl *RD,
llvm::GlobalVariable *VTable) {
if (!CGM.getCodeGenOpts().PrepareForLTO)
@@ -1514,20 +1566,20 @@ void MicrosoftCXXABI::emitVTableTypeMetadata(VPtrInfo *Info,
getContext().getTargetInfo().getPointerWidth(0))
: CharUnits::Zero();
- if (Info->PathToBaseWithVPtr.empty()) {
+ if (Info.PathToIntroducingObject.empty()) {
CGM.AddVTableTypeMetadata(VTable, AddressPoint, RD);
return;
}
// Add a bitset entry for the least derived base belonging to this vftable.
CGM.AddVTableTypeMetadata(VTable, AddressPoint,
- Info->PathToBaseWithVPtr.back());
+ Info.PathToIntroducingObject.back());
// Add a bitset entry for each derived class that is laid out at the same
// offset as the least derived base.
- for (unsigned I = Info->PathToBaseWithVPtr.size() - 1; I != 0; --I) {
- const CXXRecordDecl *DerivedRD = Info->PathToBaseWithVPtr[I - 1];
- const CXXRecordDecl *BaseRD = Info->PathToBaseWithVPtr[I];
+ for (unsigned I = Info.PathToIntroducingObject.size() - 1; I != 0; --I) {
+ const CXXRecordDecl *DerivedRD = Info.PathToIntroducingObject[I - 1];
+ const CXXRecordDecl *BaseRD = Info.PathToIntroducingObject[I];
const ASTRecordLayout &Layout =
getContext().getASTRecordLayout(DerivedRD);
@@ -1543,7 +1595,7 @@ void MicrosoftCXXABI::emitVTableTypeMetadata(VPtrInfo *Info,
}
// Finally do the same for the most derived class.
- if (Info->FullOffsetInMDC.isZero())
+ if (Info.FullOffsetInMDC.isZero())
CGM.AddVTableTypeMetadata(VTable, AddressPoint, RD);
}
@@ -1552,7 +1604,7 @@ void MicrosoftCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,
MicrosoftVTableContext &VFTContext = CGM.getMicrosoftVTableContext();
const VPtrInfoVector &VFPtrs = VFTContext.getVFPtrOffsets(RD);
- for (VPtrInfo *Info : VFPtrs) {
+ for (const std::unique_ptr<VPtrInfo>& Info : VFPtrs) {
llvm::GlobalVariable *VTable = getAddrOfVTable(RD, Info->FullOffsetInMDC);
if (VTable->hasInitializer())
continue;
@@ -1563,16 +1615,14 @@ void MicrosoftCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,
llvm::Constant *RTTI = nullptr;
if (any_of(VTLayout.vtable_components(),
[](const VTableComponent &VTC) { return VTC.isRTTIKind(); }))
- RTTI = getMSCompleteObjectLocator(RD, Info);
+ RTTI = getMSCompleteObjectLocator(RD, *Info);
- llvm::Constant *Init = CGVT.CreateVTableInitializer(
- RD, VTLayout.vtable_component_begin(),
- VTLayout.getNumVTableComponents(), VTLayout.vtable_thunk_begin(),
- VTLayout.getNumVTableThunks(), RTTI);
+ ConstantInitBuilder Builder(CGM);
+ auto Components = Builder.beginStruct();
+ CGVT.createVTableInitializer(Components, VTLayout, RTTI);
+ Components.finishAndSetAsInitializer(VTable);
- VTable->setInitializer(Init);
-
- emitVTableTypeMetadata(Info, RD, VTable);
+ emitVTableTypeMetadata(*Info, RD, VTable);
}
}
@@ -1593,10 +1643,10 @@ llvm::Value *MicrosoftCXXABI::getVTableAddressPointInStructor(
}
static void mangleVFTableName(MicrosoftMangleContext &MangleContext,
- const CXXRecordDecl *RD, const VPtrInfo *VFPtr,
+ const CXXRecordDecl *RD, const VPtrInfo &VFPtr,
SmallString<256> &Name) {
llvm::raw_svector_ostream Out(Name);
- MangleContext.mangleCXXVFTable(RD, VFPtr->MangledPath, Out);
+ MangleContext.mangleCXXVFTable(RD, VFPtr.MangledPath, Out);
}
llvm::Constant *
@@ -1643,25 +1693,25 @@ llvm::GlobalVariable *MicrosoftCXXABI::getAddrOfVTable(const CXXRecordDecl *RD,
llvm::StringSet<> ObservedMangledNames;
for (size_t J = 0, F = VFPtrs.size(); J != F; ++J) {
SmallString<256> Name;
- mangleVFTableName(getMangleContext(), RD, VFPtrs[J], Name);
+ mangleVFTableName(getMangleContext(), RD, *VFPtrs[J], Name);
if (!ObservedMangledNames.insert(Name.str()).second)
llvm_unreachable("Already saw this mangling before?");
}
#endif
}
- VPtrInfo *const *VFPtrI =
- std::find_if(VFPtrs.begin(), VFPtrs.end(), [&](VPtrInfo *VPI) {
+ const std::unique_ptr<VPtrInfo> *VFPtrI = std::find_if(
+ VFPtrs.begin(), VFPtrs.end(), [&](const std::unique_ptr<VPtrInfo>& VPI) {
return VPI->FullOffsetInMDC == VPtrOffset;
});
if (VFPtrI == VFPtrs.end()) {
VFTablesMap[ID] = nullptr;
return nullptr;
}
- VPtrInfo *VFPtr = *VFPtrI;
+ const std::unique_ptr<VPtrInfo> &VFPtr = *VFPtrI;
SmallString<256> VFTableName;
- mangleVFTableName(getMangleContext(), RD, VFPtr, VFTableName);
+ mangleVFTableName(getMangleContext(), RD, *VFPtr, VFTableName);
// Classes marked __declspec(dllimport) need vftables generated on the
// import-side in order to support features like constexpr. No other
@@ -1689,16 +1739,14 @@ llvm::GlobalVariable *MicrosoftCXXABI::getAddrOfVTable(const CXXRecordDecl *RD,
return VTable;
}
- uint64_t NumVTableSlots =
- VTContext.getVFTableLayout(RD, VFPtr->FullOffsetInMDC)
- .getNumVTableComponents();
+ const VTableLayout &VTLayout =
+ VTContext.getVFTableLayout(RD, VFPtr->FullOffsetInMDC);
llvm::GlobalValue::LinkageTypes VTableLinkage =
VTableAliasIsRequred ? llvm::GlobalValue::PrivateLinkage : VFTableLinkage;
StringRef VTableName = VTableAliasIsRequred ? StringRef() : VFTableName.str();
- llvm::ArrayType *VTableType =
- llvm::ArrayType::get(CGM.Int8PtrTy, NumVTableSlots);
+ llvm::Type *VTableType = CGM.getVTables().getVTableType(VTLayout);
// Create a backing variable for the contents of VTable. The VTable may
// or may not include space for a pointer to RTTI data.
@@ -1719,8 +1767,9 @@ llvm::GlobalVariable *MicrosoftCXXABI::getAddrOfVTable(const CXXRecordDecl *RD,
// importing it. We never reference the RTTI data directly so there is no
// need to make room for it.
if (VTableAliasIsRequred) {
- llvm::Value *GEPIndices[] = {llvm::ConstantInt::get(CGM.IntTy, 0),
- llvm::ConstantInt::get(CGM.IntTy, 1)};
+ llvm::Value *GEPIndices[] = {llvm::ConstantInt::get(CGM.Int32Ty, 0),
+ llvm::ConstantInt::get(CGM.Int32Ty, 0),
+ llvm::ConstantInt::get(CGM.Int32Ty, 1)};
// Create a GEP which points just after the first entry in the VFTable,
// this should be the location of the first virtual method.
llvm::Constant *VTableGEP = llvm::ConstantExpr::getInBoundsGetElementPtr(
@@ -1752,54 +1801,11 @@ llvm::GlobalVariable *MicrosoftCXXABI::getAddrOfVTable(const CXXRecordDecl *RD,
return VTable;
}
-// Compute the identity of the most derived class whose virtual table is located
-// at the given offset into RD.
-static const CXXRecordDecl *getClassAtVTableLocation(ASTContext &Ctx,
- const CXXRecordDecl *RD,
- CharUnits Offset) {
- if (Offset.isZero())
- return RD;
-
- const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD);
- const CXXRecordDecl *MaxBase = nullptr;
- CharUnits MaxBaseOffset;
- for (auto &&B : RD->bases()) {
- const CXXRecordDecl *Base = B.getType()->getAsCXXRecordDecl();
- CharUnits BaseOffset = Layout.getBaseClassOffset(Base);
- if (BaseOffset <= Offset && BaseOffset >= MaxBaseOffset) {
- MaxBase = Base;
- MaxBaseOffset = BaseOffset;
- }
- }
- for (auto &&B : RD->vbases()) {
- const CXXRecordDecl *Base = B.getType()->getAsCXXRecordDecl();
- CharUnits BaseOffset = Layout.getVBaseClassOffset(Base);
- if (BaseOffset <= Offset && BaseOffset >= MaxBaseOffset) {
- MaxBase = Base;
- MaxBaseOffset = BaseOffset;
- }
- }
- assert(MaxBase);
- return getClassAtVTableLocation(Ctx, MaxBase, Offset - MaxBaseOffset);
-}
-
-// Compute the identity of the most derived class whose virtual table is located
-// at the MethodVFTableLocation ML.
-static const CXXRecordDecl *
-getClassAtVTableLocation(ASTContext &Ctx, GlobalDecl GD,
- MicrosoftVTableContext::MethodVFTableLocation &ML) {
- const CXXRecordDecl *RD = ML.VBase;
- if (!RD)
- RD = cast<CXXMethodDecl>(GD.getDecl())->getParent();
-
- return getClassAtVTableLocation(Ctx, RD, ML.VFPtrOffset);
-}
-
-llvm::Value *MicrosoftCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
- GlobalDecl GD,
- Address This,
- llvm::Type *Ty,
- SourceLocation Loc) {
+CGCallee MicrosoftCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
+ GlobalDecl GD,
+ Address This,
+ llvm::Type *Ty,
+ SourceLocation Loc) {
GD = GD.getCanonicalDecl();
CGBuilderTy &Builder = CGF.Builder;
@@ -1810,22 +1816,38 @@ llvm::Value *MicrosoftCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
auto *MethodDecl = cast<CXXMethodDecl>(GD.getDecl());
llvm::Value *VTable = CGF.GetVTablePtr(VPtr, Ty, MethodDecl->getParent());
+ MicrosoftVTableContext &VFTContext = CGM.getMicrosoftVTableContext();
MicrosoftVTableContext::MethodVFTableLocation ML =
- CGM.getMicrosoftVTableContext().getMethodVFTableLocation(GD);
+ VFTContext.getMethodVFTableLocation(GD);
+
+ // Compute the identity of the most derived class whose virtual table is
+ // located at the MethodVFTableLocation ML.
+ auto getObjectWithVPtr = [&] {
+ return llvm::find_if(VFTContext.getVFPtrOffsets(
+ ML.VBase ? ML.VBase : MethodDecl->getParent()),
+ [&](const std::unique_ptr<VPtrInfo> &Info) {
+ return Info->FullOffsetInMDC == ML.VFPtrOffset;
+ })
+ ->get()
+ ->ObjectWithVPtr;
+ };
+ llvm::Value *VFunc;
if (CGF.ShouldEmitVTableTypeCheckedLoad(MethodDecl->getParent())) {
- return CGF.EmitVTableTypeCheckedLoad(
- getClassAtVTableLocation(getContext(), GD, ML), VTable,
+ VFunc = CGF.EmitVTableTypeCheckedLoad(
+ getObjectWithVPtr(), VTable,
ML.Index * CGM.getContext().getTargetInfo().getPointerWidth(0) / 8);
} else {
if (CGM.getCodeGenOpts().PrepareForLTO)
- CGF.EmitTypeMetadataCodeForVCall(
- getClassAtVTableLocation(getContext(), GD, ML), VTable, Loc);
+ CGF.EmitTypeMetadataCodeForVCall(getObjectWithVPtr(), VTable, Loc);
llvm::Value *VFuncPtr =
Builder.CreateConstInBoundsGEP1_64(VTable, ML.Index, "vfn");
- return Builder.CreateAlignedLoad(VFuncPtr, CGF.getPointerAlign());
+ VFunc = Builder.CreateAlignedLoad(VFuncPtr, CGF.getPointerAlign());
}
+
+ CGCallee Callee(MethodDecl, VFunc);
+ return Callee;
}
llvm::Value *MicrosoftCXXABI::EmitVirtualDestructorCall(
@@ -1840,7 +1862,7 @@ llvm::Value *MicrosoftCXXABI::EmitVirtualDestructorCall(
const CGFunctionInfo *FInfo = &CGM.getTypes().arrangeCXXStructorDeclaration(
Dtor, StructorType::Deleting);
llvm::Type *Ty = CGF.CGM.getTypes().GetFunctionType(*FInfo);
- llvm::Value *Callee = getVirtualFunctionPointer(
+ CGCallee Callee = getVirtualFunctionPointer(
CGF, GD, This, Ty, CE ? CE->getLocStart() : SourceLocation());
ASTContext &Context = getContext();
@@ -1956,7 +1978,7 @@ llvm::Function *MicrosoftCXXABI::EmitVirtualMemPtrThunk(
void MicrosoftCXXABI::emitVirtualInheritanceTables(const CXXRecordDecl *RD) {
const VBTableGlobals &VBGlobals = enumerateVBTables(RD);
for (unsigned I = 0, E = VBGlobals.VBTables->size(); I != E; ++I) {
- const VPtrInfo *VBT = (*VBGlobals.VBTables)[I];
+ const std::unique_ptr<VPtrInfo>& VBT = (*VBGlobals.VBTables)[I];
llvm::GlobalVariable *GV = VBGlobals.Globals[I];
if (GV->isDeclaration())
emitVBTableDefinition(*VBT, RD, GV);
@@ -1972,7 +1994,7 @@ MicrosoftCXXABI::getAddrOfVBTable(const VPtrInfo &VBT, const CXXRecordDecl *RD,
StringRef Name = OutName.str();
llvm::ArrayType *VBTableType =
- llvm::ArrayType::get(CGM.IntTy, 1 + VBT.ReusingBase->getNumVBases());
+ llvm::ArrayType::get(CGM.IntTy, 1 + VBT.ObjectWithVPtr->getNumVBases());
assert(!CGM.getModule().getNamedGlobal(Name) &&
"vbtable with this name already exists: mangling bug?");
@@ -1994,24 +2016,24 @@ MicrosoftCXXABI::getAddrOfVBTable(const VPtrInfo &VBT, const CXXRecordDecl *RD,
void MicrosoftCXXABI::emitVBTableDefinition(const VPtrInfo &VBT,
const CXXRecordDecl *RD,
llvm::GlobalVariable *GV) const {
- const CXXRecordDecl *ReusingBase = VBT.ReusingBase;
+ const CXXRecordDecl *ObjectWithVPtr = VBT.ObjectWithVPtr;
- assert(RD->getNumVBases() && ReusingBase->getNumVBases() &&
+ assert(RD->getNumVBases() && ObjectWithVPtr->getNumVBases() &&
"should only emit vbtables for classes with vbtables");
const ASTRecordLayout &BaseLayout =
- getContext().getASTRecordLayout(VBT.BaseWithVPtr);
+ getContext().getASTRecordLayout(VBT.IntroducingObject);
const ASTRecordLayout &DerivedLayout = getContext().getASTRecordLayout(RD);
- SmallVector<llvm::Constant *, 4> Offsets(1 + ReusingBase->getNumVBases(),
+ SmallVector<llvm::Constant *, 4> Offsets(1 + ObjectWithVPtr->getNumVBases(),
nullptr);
- // The offset from ReusingBase's vbptr to itself always leads.
+ // The offset from ObjectWithVPtr's vbptr to itself always leads.
CharUnits VBPtrOffset = BaseLayout.getVBPtrOffset();
Offsets[0] = llvm::ConstantInt::get(CGM.IntTy, -VBPtrOffset.getQuantity());
MicrosoftVTableContext &Context = CGM.getMicrosoftVTableContext();
- for (const auto &I : ReusingBase->vbases()) {
+ for (const auto &I : ObjectWithVPtr->vbases()) {
const CXXRecordDecl *VBase = I.getType()->getAsCXXRecordDecl();
CharUnits Offset = DerivedLayout.getVBaseClassOffset(VBase);
assert(!Offset.isNegative());
@@ -2023,7 +2045,7 @@ void MicrosoftCXXABI::emitVBTableDefinition(const VPtrInfo &VBT,
DerivedLayout.getVBaseClassOffset(VBT.getVBaseWithVPtr());
Offset -= CompleteVBPtrOffset;
- unsigned VBIndex = Context.getVBTableIndex(ReusingBase, VBase);
+ unsigned VBIndex = Context.getVBTableIndex(ObjectWithVPtr, VBase);
assert(Offsets[VBIndex] == nullptr && "The same vbindex seen twice?");
Offsets[VBIndex] = llvm::ConstantInt::get(CGM.IntTy, Offset.getQuantity());
}
@@ -2182,7 +2204,8 @@ static void emitGlobalDtorWithTLRegDtor(CodeGenFunction &CGF, const VarDecl &VD,
CGF.IntTy, DtorStub->getType(), /*IsVarArg=*/false);
llvm::Constant *TLRegDtor =
- CGF.CGM.CreateRuntimeFunction(TLRegDtorTy, "__tlregdtor");
+ CGF.CGM.CreateRuntimeFunction(TLRegDtorTy, "__tlregdtor",
+ llvm::AttributeSet(), /*Local=*/true);
if (llvm::Function *TLRegDtorFn = dyn_cast<llvm::Function>(TLRegDtor))
TLRegDtorFn->setDoesNotThrow();
@@ -2203,6 +2226,14 @@ void MicrosoftCXXABI::EmitThreadLocalInitFuncs(
CodeGenModule &CGM, ArrayRef<const VarDecl *> CXXThreadLocals,
ArrayRef<llvm::Function *> CXXThreadLocalInits,
ArrayRef<const VarDecl *> CXXThreadLocalInitVars) {
+ if (CXXThreadLocalInits.empty())
+ return;
+
+ CGM.AppendLinkerOptions(CGM.getTarget().getTriple().getArch() ==
+ llvm::Triple::x86
+ ? "/include:___dyn_tls_init@12"
+ : "/include:__dyn_tls_init");
+
// This will create a GV in the .CRT$XDU section. It will point to our
// initialization function. The CRT will call all of these function
// pointers at start-up time and, eventually, at thread-creation time.
@@ -2272,7 +2303,8 @@ static llvm::Constant *getInitThreadHeaderFn(CodeGenModule &CGM) {
FTy, "_Init_thread_header",
llvm::AttributeSet::get(CGM.getLLVMContext(),
llvm::AttributeSet::FunctionIndex,
- llvm::Attribute::NoUnwind));
+ llvm::Attribute::NoUnwind),
+ /*Local=*/true);
}
static llvm::Constant *getInitThreadFooterFn(CodeGenModule &CGM) {
@@ -2283,7 +2315,8 @@ static llvm::Constant *getInitThreadFooterFn(CodeGenModule &CGM) {
FTy, "_Init_thread_footer",
llvm::AttributeSet::get(CGM.getLLVMContext(),
llvm::AttributeSet::FunctionIndex,
- llvm::Attribute::NoUnwind));
+ llvm::Attribute::NoUnwind),
+ /*Local=*/true);
}
static llvm::Constant *getInitThreadAbortFn(CodeGenModule &CGM) {
@@ -2294,7 +2327,8 @@ static llvm::Constant *getInitThreadAbortFn(CodeGenModule &CGM) {
FTy, "_Init_thread_abort",
llvm::AttributeSet::get(CGM.getLLVMContext(),
llvm::AttributeSet::FunctionIndex,
- llvm::Attribute::NoUnwind));
+ llvm::Attribute::NoUnwind),
+ /*Local=*/true);
}
namespace {
@@ -3222,7 +3256,7 @@ llvm::Constant *MicrosoftCXXABI::EmitMemberPointerConversion(
return Dst;
}
-llvm::Value *MicrosoftCXXABI::EmitLoadOfMemberFunctionPointer(
+CGCallee MicrosoftCXXABI::EmitLoadOfMemberFunctionPointer(
CodeGenFunction &CGF, const Expr *E, Address This,
llvm::Value *&ThisPtrForCall, llvm::Value *MemPtr,
const MemberPointerType *MPT) {
@@ -3269,7 +3303,10 @@ llvm::Value *MicrosoftCXXABI::EmitLoadOfMemberFunctionPointer(
"this.adjusted");
}
- return Builder.CreateBitCast(FunctionPointer, FTy->getPointerTo());
+ FunctionPointer =
+ Builder.CreateBitCast(FunctionPointer, FTy->getPointerTo());
+ CGCallee Callee(FPT, FunctionPointer);
+ return Callee;
}
CGCXXABI *clang::CodeGen::CreateMicrosoftCXXABI(CodeGenModule &CGM) {
@@ -3410,7 +3447,7 @@ struct MSRTTIBuilder {
llvm::GlobalVariable *
getBaseClassArray(SmallVectorImpl<MSRTTIClass> &Classes);
llvm::GlobalVariable *getClassHierarchyDescriptor();
- llvm::GlobalVariable *getCompleteObjectLocator(const VPtrInfo *Info);
+ llvm::GlobalVariable *getCompleteObjectLocator(const VPtrInfo &Info);
CodeGenModule &CGM;
ASTContext &Context;
@@ -3499,7 +3536,7 @@ llvm::GlobalVariable *MSRTTIBuilder::getClassHierarchyDescriptor() {
// Initialize the base class ClassHierarchyDescriptor.
llvm::Constant *Fields[] = {
- llvm::ConstantInt::get(CGM.IntTy, 0), // Unknown
+ llvm::ConstantInt::get(CGM.IntTy, 0), // reserved by the runtime
llvm::ConstantInt::get(CGM.IntTy, Flags),
llvm::ConstantInt::get(CGM.IntTy, Classes.size()),
ABI.getImageRelativeConstant(llvm::ConstantExpr::getInBoundsGetElementPtr(
@@ -3592,11 +3629,11 @@ MSRTTIBuilder::getBaseClassDescriptor(const MSRTTIClass &Class) {
}
llvm::GlobalVariable *
-MSRTTIBuilder::getCompleteObjectLocator(const VPtrInfo *Info) {
+MSRTTIBuilder::getCompleteObjectLocator(const VPtrInfo &Info) {
SmallString<256> MangledName;
{
llvm::raw_svector_ostream Out(MangledName);
- ABI.getMangleContext().mangleCXXRTTICompleteObjectLocator(RD, Info->MangledPath, Out);
+ ABI.getMangleContext().mangleCXXRTTICompleteObjectLocator(RD, Info.MangledPath, Out);
}
// Check to see if we've already computed this complete object locator.
@@ -3604,15 +3641,15 @@ MSRTTIBuilder::getCompleteObjectLocator(const VPtrInfo *Info) {
return COL;
// Compute the fields of the complete object locator.
- int OffsetToTop = Info->FullOffsetInMDC.getQuantity();
+ int OffsetToTop = Info.FullOffsetInMDC.getQuantity();
int VFPtrOffset = 0;
// The offset includes the vtordisp if one exists.
- if (const CXXRecordDecl *VBase = Info->getVBaseWithVPtr())
+ if (const CXXRecordDecl *VBase = Info.getVBaseWithVPtr())
if (Context.getASTRecordLayout(RD)
.getVBaseOffsetsMap()
.find(VBase)
->second.hasVtorDisp())
- VFPtrOffset = Info->NonVirtualOffset.getQuantity() + 4;
+ VFPtrOffset = Info.NonVirtualOffset.getQuantity() + 4;
// Forward-declare the complete object locator.
llvm::StructType *Type = ABI.getCompleteObjectLocatorType();
@@ -3740,7 +3777,7 @@ llvm::Constant *MicrosoftCXXABI::getAddrOfRTTIDescriptor(QualType Type) {
/// \brief Gets or a creates a Microsoft CompleteObjectLocator.
llvm::GlobalVariable *
MicrosoftCXXABI::getMSCompleteObjectLocator(const CXXRecordDecl *RD,
- const VPtrInfo *Info) {
+ const VPtrInfo &Info) {
return MSRTTIBuilder(*this, RD).getCompleteObjectLocator(Info);
}
@@ -3846,8 +3883,11 @@ MicrosoftCXXABI::getAddrOfCXXCtorClosure(const CXXConstructorDecl *CD,
FunctionArgs.push_back(&IsMostDerived);
// Start defining the function.
+ auto NL = ApplyDebugLocation::CreateEmpty(CGF);
CGF.StartFunction(GlobalDecl(), FnInfo.getReturnType(), ThunkFn, FnInfo,
FunctionArgs, CD->getLocation(), SourceLocation());
+ // Create a scope with an artificial location for the body of this function.
+ auto AL = ApplyDebugLocation::CreateArtificial(CGF);
EmitThisParam(CGF);
llvm::Value *This = getThisValue(CGF);
@@ -3865,11 +3905,11 @@ MicrosoftCXXABI::getAddrOfCXXCtorClosure(const CXXConstructorDecl *CD,
Args.add(RValue::get(SrcVal), SrcParam.getType());
// Add the rest of the default arguments.
- std::vector<Stmt *> ArgVec;
- for (unsigned I = IsCopy ? 1 : 0, E = CD->getNumParams(); I != E; ++I) {
- Stmt *DefaultArg = getContext().getDefaultArgExprForConstructor(CD, I);
- assert(DefaultArg && "sema forgot to instantiate default args");
- ArgVec.push_back(DefaultArg);
+ SmallVector<const Stmt *, 4> ArgVec;
+ ArrayRef<ParmVarDecl *> params = CD->parameters().drop_front(IsCopy ? 1 : 0);
+ for (const ParmVarDecl *PD : params) {
+ assert(PD->hasDefaultArg() && "ctor closure lacks default args");
+ ArgVec.push_back(PD->getDefaultArg());
}
CodeGenFunction::RunCleanupsScope Cleanups(CGF);
@@ -3883,10 +3923,12 @@ MicrosoftCXXABI::getAddrOfCXXCtorClosure(const CXXConstructorDecl *CD,
/*Delegating=*/false, Args);
// Call the destructor with our arguments.
- llvm::Value *CalleeFn = CGM.getAddrOfCXXStructor(CD, StructorType::Complete);
+ llvm::Constant *CalleePtr =
+ CGM.getAddrOfCXXStructor(CD, StructorType::Complete);
+ CGCallee Callee = CGCallee::forDirect(CalleePtr, CD);
const CGFunctionInfo &CalleeInfo = CGM.getTypes().arrangeCXXConstructorCall(
Args, CD, Ctor_Complete, ExtraArgs);
- CGF.EmitCall(CalleeInfo, CalleeFn, ReturnValueSlot(), Args, CD);
+ CGF.EmitCall(CalleeInfo, Callee, ReturnValueSlot(), Args);
Cleanups.ForceCleanup();
diff --git a/lib/CodeGen/ModuleBuilder.cpp b/lib/CodeGen/ModuleBuilder.cpp
index 952d1627fa84..f925c2549175 100644
--- a/lib/CodeGen/ModuleBuilder.cpp
+++ b/lib/CodeGen/ModuleBuilder.cpp
@@ -112,7 +112,7 @@ namespace {
}
llvm::Constant *GetAddrOfGlobal(GlobalDecl global, bool isForDefinition) {
- return Builder->GetAddrOfGlobal(global, isForDefinition);
+ return Builder->GetAddrOfGlobal(global, ForDefinition_t(isForDefinition));
}
void Initialize(ASTContext &Context) override {
diff --git a/lib/CodeGen/ObjectFilePCHContainerOperations.cpp b/lib/CodeGen/ObjectFilePCHContainerOperations.cpp
index de40e4121124..baf7811eedaf 100644
--- a/lib/CodeGen/ObjectFilePCHContainerOperations.cpp
+++ b/lib/CodeGen/ObjectFilePCHContainerOperations.cpp
@@ -312,27 +312,30 @@ ObjectFilePCHContainerWriter::CreatePCHContainerGenerator(
CI, MainFileName, OutputFileName, std::move(OS), Buffer);
}
-void ObjectFilePCHContainerReader::ExtractPCH(
- llvm::MemoryBufferRef Buffer, llvm::BitstreamReader &StreamFile) const {
- if (auto OF = llvm::object::ObjectFile::createObjectFile(Buffer)) {
- auto *Obj = OF.get().get();
- bool IsCOFF = isa<llvm::object::COFFObjectFile>(Obj);
+StringRef
+ObjectFilePCHContainerReader::ExtractPCH(llvm::MemoryBufferRef Buffer) const {
+ StringRef PCH;
+ auto OFOrErr = llvm::object::ObjectFile::createObjectFile(Buffer);
+ if (OFOrErr) {
+ auto &OF = OFOrErr.get();
+ bool IsCOFF = isa<llvm::object::COFFObjectFile>(*OF);
// Find the clang AST section in the container.
- for (auto &Section : OF->get()->sections()) {
+ for (auto &Section : OF->sections()) {
StringRef Name;
Section.getName(Name);
- if ((!IsCOFF && Name == "__clangast") ||
- ( IsCOFF && Name == "clangast")) {
- StringRef Buf;
- Section.getContents(Buf);
- StreamFile.init((const unsigned char *)Buf.begin(),
- (const unsigned char *)Buf.end());
- return;
+ if ((!IsCOFF && Name == "__clangast") || (IsCOFF && Name == "clangast")) {
+ Section.getContents(PCH);
+ return PCH;
}
}
}
-
- // As a fallback, treat the buffer as a raw AST.
- StreamFile.init((const unsigned char *)Buffer.getBufferStart(),
- (const unsigned char *)Buffer.getBufferEnd());
+ handleAllErrors(OFOrErr.takeError(), [&](const llvm::ErrorInfoBase &EIB) {
+ if (EIB.convertToErrorCode() ==
+ llvm::object::object_error::invalid_file_type)
+ // As a fallback, treat the buffer as a raw AST.
+ PCH = Buffer.getBuffer();
+ else
+ EIB.log(llvm::errs());
+ });
+ return PCH;
}
diff --git a/lib/CodeGen/SanitizerMetadata.cpp b/lib/CodeGen/SanitizerMetadata.cpp
index 2a338bac4b41..9848e3e452f4 100644
--- a/lib/CodeGen/SanitizerMetadata.cpp
+++ b/lib/CodeGen/SanitizerMetadata.cpp
@@ -63,7 +63,13 @@ void SanitizerMetadata::reportGlobalToASan(llvm::GlobalVariable *GV,
std::string QualName;
llvm::raw_string_ostream OS(QualName);
D.printQualifiedName(OS);
- reportGlobalToASan(GV, D.getLocation(), OS.str(), D.getType(), IsDynInit);
+
+ bool IsBlacklisted = false;
+ for (auto Attr : D.specific_attrs<NoSanitizeAttr>())
+ if (Attr->getMask() & SanitizerKind::Address)
+ IsBlacklisted = true;
+ reportGlobalToASan(GV, D.getLocation(), OS.str(), D.getType(), IsDynInit,
+ IsBlacklisted);
}
void SanitizerMetadata::disableSanitizerForGlobal(llvm::GlobalVariable *GV) {
diff --git a/lib/CodeGen/SwiftCallingConv.cpp b/lib/CodeGen/SwiftCallingConv.cpp
index 6c20f8c9d3e9..0bfe30a32c80 100644
--- a/lib/CodeGen/SwiftCallingConv.cpp
+++ b/lib/CodeGen/SwiftCallingConv.cpp
@@ -384,7 +384,7 @@ void SwiftAggLowering::splitVectorEntry(unsigned index) {
auto eltTy = split.first;
CharUnits eltSize = getTypeStoreSize(CGM, eltTy);
auto numElts = split.second;
- Entries.insert(&Entries[index + 1], numElts - 1, StorageEntry());
+ Entries.insert(Entries.begin() + index + 1, numElts - 1, StorageEntry());
CharUnits begin = Entries[index].Begin;
for (unsigned i = 0; i != numElts; ++i) {
@@ -506,7 +506,7 @@ void SwiftAggLowering::enumerateComponents(EnumerationCallback callback) const {
assert(Finished && "haven't yet finished lowering");
for (auto &entry : Entries) {
- callback(entry.Begin, entry.Type);
+ callback(entry.Begin, entry.End, entry.Type);
}
}
@@ -828,3 +828,8 @@ void swiftcall::computeABIInfo(CodeGenModule &CGM, CGFunctionInfo &FI) {
argInfo.info = classifyArgumentType(CGM, argInfo.type);
}
}
+
+// Is swifterror lowered to a register by the target ABI.
+bool swiftcall::isSwiftErrorLoweredInRegister(CodeGenModule &CGM) {
+ return getSwiftABIInfo(CGM).isSwiftErrorInRegister();
+}
diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp
index aa67e71284ae..391eb53d2500 100644
--- a/lib/CodeGen/TargetInfo.cpp
+++ b/lib/CodeGen/TargetInfo.cpp
@@ -31,6 +31,31 @@
using namespace clang;
using namespace CodeGen;
+// Helper for coercing an aggregate argument or return value into an integer
+// array of the same size (including padding) and alignment. This alternate
+// coercion happens only for the RenderScript ABI and can be removed after
+// runtimes that rely on it are no longer supported.
+//
+// RenderScript assumes that the size of the argument / return value in the IR
+// is the same as the size of the corresponding qualified type. This helper
+// coerces the aggregate type into an array of the same size (including
+// padding). This coercion is used in lieu of expansion of struct members or
+// other canonical coercions that return a coerced-type of larger size.
+//
+// Ty - The argument / return value type
+// Context - The associated ASTContext
+// LLVMContext - The associated LLVMContext
+static ABIArgInfo coerceToIntArray(QualType Ty,
+ ASTContext &Context,
+ llvm::LLVMContext &LLVMContext) {
+ // Alignment and Size are measured in bits.
+ const uint64_t Size = Context.getTypeSize(Ty);
+ const uint64_t Alignment = Context.getTypeAlign(Ty);
+ llvm::Type *IntType = llvm::Type::getIntNTy(LLVMContext, Alignment);
+ const uint64_t NumElements = (Size + Alignment - 1) / Alignment;
+ return ABIArgInfo::getDirect(llvm::ArrayType::get(IntType, NumElements));
+}
+
static void AssignToArrayRange(CodeGen::CGBuilderTy &Builder,
llvm::Value *Array,
llvm::Value *Value,
@@ -375,6 +400,21 @@ TargetCodeGenInfo::getDependentLibraryOption(llvm::StringRef Lib,
unsigned TargetCodeGenInfo::getOpenCLKernelCallingConv() const {
return llvm::CallingConv::C;
}
+
+llvm::Constant *TargetCodeGenInfo::getNullPointer(const CodeGen::CodeGenModule &CGM,
+ llvm::PointerType *T, QualType QT) const {
+ return llvm::ConstantPointerNull::get(T);
+}
+
+llvm::Value *TargetCodeGenInfo::performAddrSpaceCast(
+ CodeGen::CodeGenFunction &CGF, llvm::Value *Src, QualType SrcTy,
+ QualType DestTy) const {
+ // Since target may map different address spaces in AST to the same address
+ // space, an address space conversion may end up as a bitcast.
+ return CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Src,
+ CGF.ConvertType(DestTy));
+}
+
static bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays);
/// isEmptyField - Return true iff a the field is "empty", that is it
@@ -932,6 +972,11 @@ public:
// scalar registers.
return occupiesMoreThan(CGT, scalars, /*total*/ 3);
}
+
+ bool isSwiftErrorInRegister() const override {
+ // x86-32 lowering does not support passing swifterror in a register.
+ return false;
+ }
};
class X86_32TargetCodeGenInfo : public TargetCodeGenInfo {
@@ -1203,7 +1248,8 @@ ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy,
const Type *Base = nullptr;
uint64_t NumElts = 0;
- if (State.CC == llvm::CallingConv::X86_VectorCall &&
+ if ((State.CC == llvm::CallingConv::X86_VectorCall ||
+ State.CC == llvm::CallingConv::X86_RegCall) &&
isHomogeneousAggregate(RetTy, Base, NumElts)) {
// The LLVM struct type for such an aggregate should lower properly.
return ABIArgInfo::getDirect();
@@ -1417,7 +1463,8 @@ bool X86_32ABIInfo::shouldAggregateUseDirect(QualType Ty, CCState &State,
return true;
if (State.CC == llvm::CallingConv::X86_FastCall ||
- State.CC == llvm::CallingConv::X86_VectorCall) {
+ State.CC == llvm::CallingConv::X86_VectorCall ||
+ State.CC == llvm::CallingConv::X86_RegCall) {
if (getContext().getTypeSize(Ty) <= 32 && State.FreeRegs)
NeedsPadding = true;
@@ -1435,7 +1482,8 @@ bool X86_32ABIInfo::shouldPrimitiveUseInReg(QualType Ty, CCState &State) const {
return false;
if (State.CC == llvm::CallingConv::X86_FastCall ||
- State.CC == llvm::CallingConv::X86_VectorCall) {
+ State.CC == llvm::CallingConv::X86_VectorCall ||
+ State.CC == llvm::CallingConv::X86_RegCall) {
if (getContext().getTypeSize(Ty) > 32)
return false;
@@ -1468,7 +1516,8 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
// to other targets.
const Type *Base = nullptr;
uint64_t NumElts = 0;
- if (State.CC == llvm::CallingConv::X86_VectorCall &&
+ if ((State.CC == llvm::CallingConv::X86_VectorCall ||
+ State.CC == llvm::CallingConv::X86_RegCall) &&
isHomogeneousAggregate(Ty, Base, NumElts)) {
if (State.FreeSSERegs >= NumElts) {
State.FreeSSERegs -= NumElts;
@@ -1514,7 +1563,8 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
(!IsMCUABI || State.FreeRegs == 0) && canExpandIndirectArgument(Ty))
return ABIArgInfo::getExpandWithPadding(
State.CC == llvm::CallingConv::X86_FastCall ||
- State.CC == llvm::CallingConv::X86_VectorCall,
+ State.CC == llvm::CallingConv::X86_VectorCall ||
+ State.CC == llvm::CallingConv::X86_RegCall,
PaddingType);
return getIndirectResult(Ty, true, State);
@@ -1565,7 +1615,10 @@ void X86_32ABIInfo::computeInfo(CGFunctionInfo &FI) const {
State.FreeSSERegs = 6;
} else if (FI.getHasRegParm())
State.FreeRegs = FI.getRegParm();
- else
+ else if (State.CC == llvm::CallingConv::X86_RegCall) {
+ State.FreeRegs = 5;
+ State.FreeSSERegs = 8;
+ } else
State.FreeRegs = DefaultNumRegisterParameters;
if (!getCXXABI().classifyReturnType(FI)) {
@@ -1906,12 +1959,16 @@ class X86_64ABIInfo : public SwiftABIInfo {
ABIArgInfo classifyReturnType(QualType RetTy) const;
- ABIArgInfo classifyArgumentType(QualType Ty,
- unsigned freeIntRegs,
- unsigned &neededInt,
- unsigned &neededSSE,
+ ABIArgInfo classifyArgumentType(QualType Ty, unsigned freeIntRegs,
+ unsigned &neededInt, unsigned &neededSSE,
bool isNamedArg) const;
+ ABIArgInfo classifyRegCallStructType(QualType Ty, unsigned &NeededInt,
+ unsigned &NeededSSE) const;
+
+ ABIArgInfo classifyRegCallStructTypeImpl(QualType Ty, unsigned &NeededInt,
+ unsigned &NeededSSE) const;
+
bool IsIllegalVectorType(QualType Ty) const;
/// The 0.98 ABI revision clarified a lot of ambiguities,
@@ -1974,13 +2031,16 @@ public:
bool asReturnValue) const override {
return occupiesMoreThan(CGT, scalars, /*total*/ 4);
}
+ bool isSwiftErrorInRegister() const override {
+ return true;
+ }
};
/// WinX86_64ABIInfo - The Windows X86_64 ABI information.
-class WinX86_64ABIInfo : public ABIInfo {
+class WinX86_64ABIInfo : public SwiftABIInfo {
public:
WinX86_64ABIInfo(CodeGen::CodeGenTypes &CGT)
- : ABIInfo(CGT),
+ : SwiftABIInfo(CGT),
IsMingw64(getTarget().getTriple().isWindowsGNUEnvironment()) {}
void computeInfo(CGFunctionInfo &FI) const override;
@@ -1999,6 +2059,16 @@ public:
return isX86VectorCallAggregateSmallEnough(NumMembers);
}
+ bool shouldPassIndirectlyForSwift(CharUnits totalSize,
+ ArrayRef<llvm::Type *> scalars,
+ bool asReturnValue) const override {
+ return occupiesMoreThan(CGT, scalars, /*total*/ 4);
+ }
+
+ bool isSwiftErrorInRegister() const override {
+ return true;
+ }
+
private:
ABIArgInfo classify(QualType Ty, unsigned &FreeSSERegs,
bool IsReturnType) const;
@@ -2315,13 +2385,13 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase,
Current = SSE;
} else if (k == BuiltinType::LongDouble) {
const llvm::fltSemantics *LDF = &getTarget().getLongDoubleFormat();
- if (LDF == &llvm::APFloat::IEEEquad) {
+ if (LDF == &llvm::APFloat::IEEEquad()) {
Lo = SSE;
Hi = SSEUp;
- } else if (LDF == &llvm::APFloat::x87DoubleExtended) {
+ } else if (LDF == &llvm::APFloat::x87DoubleExtended()) {
Lo = X87;
Hi = X87Up;
- } else if (LDF == &llvm::APFloat::IEEEdouble) {
+ } else if (LDF == &llvm::APFloat::IEEEdouble()) {
Current = SSE;
} else
llvm_unreachable("unexpected long double representation!");
@@ -2440,11 +2510,11 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase,
Lo = Hi = SSE;
} else if (ET == getContext().LongDoubleTy) {
const llvm::fltSemantics *LDF = &getTarget().getLongDoubleFormat();
- if (LDF == &llvm::APFloat::IEEEquad)
+ if (LDF == &llvm::APFloat::IEEEquad())
Current = Memory;
- else if (LDF == &llvm::APFloat::x87DoubleExtended)
+ else if (LDF == &llvm::APFloat::x87DoubleExtended())
Current = ComplexX87;
- else if (LDF == &llvm::APFloat::IEEEdouble)
+ else if (LDF == &llvm::APFloat::IEEEdouble())
Lo = Hi = SSE;
else
llvm_unreachable("unexpected long double representation!");
@@ -2466,8 +2536,8 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase,
uint64_t Size = getContext().getTypeSize(Ty);
// AMD64-ABI 3.2.3p2: Rule 1. If the size of an object is larger
- // than four eightbytes, ..., it has class MEMORY.
- if (Size > 256)
+ // than eight eightbytes, ..., it has class MEMORY.
+ if (Size > 512)
return;
// AMD64-ABI 3.2.3p2: Rule 1. If ..., or it contains unaligned
@@ -2486,7 +2556,9 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase,
// The only case a 256-bit wide vector could be used is when the array
// contains a single 256-bit element. Since Lo and Hi logic isn't extended
// to work for sizes wider than 128, early check and fallback to memory.
- if (Size > 128 && EltSize != 256)
+ //
+ if (Size > 128 &&
+ (Size != EltSize || Size > getNativeVectorSizeForAVXABI(AVXLevel)))
return;
for (uint64_t i=0, Offset=OffsetBase; i<ArraySize; ++i, Offset += EltSize) {
@@ -2507,8 +2579,8 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase,
uint64_t Size = getContext().getTypeSize(Ty);
// AMD64-ABI 3.2.3p2: Rule 1. If the size of an object is larger
- // than four eightbytes, ..., it has class MEMORY.
- if (Size > 256)
+ // than eight eightbytes, ..., it has class MEMORY.
+ if (Size > 512)
return;
// AMD64-ABI 3.2.3p2: Rule 2. If a C++ object has either a non-trivial
@@ -2561,6 +2633,10 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase,
uint64_t Offset = OffsetBase + Layout.getFieldOffset(idx);
bool BitField = i->isBitField();
+ // Ignore padding bit-fields.
+ if (BitField && i->isUnnamedBitfield())
+ continue;
+
// AMD64-ABI 3.2.3p2: Rule 1. If the size of an object is larger than
// four eightbytes, or it contains unaligned fields, it has class MEMORY.
//
@@ -2568,7 +2644,8 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase,
// contains a single 256-bit element. Since Lo and Hi logic isn't extended
// to work for sizes wider than 128, early check and fallback to memory.
//
- if (Size > 128 && getContext().getTypeSize(i->getType()) != 256) {
+ if (Size > 128 && (Size != getContext().getTypeSize(i->getType()) ||
+ Size > getNativeVectorSizeForAVXABI(AVXLevel))) {
Lo = Memory;
postMerge(Size, Lo, Hi);
return;
@@ -2592,10 +2669,7 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase,
// structure to be passed in memory even if unaligned, and
// therefore they can straddle an eightbyte.
if (BitField) {
- // Ignore padding bit-fields.
- if (i->isUnnamedBitfield())
- continue;
-
+ assert(!i->isUnnamedBitfield());
uint64_t Offset = OffsetBase + Layout.getFieldOffset(idx);
uint64_t Size = i->getBitWidthValue(getContext());
@@ -2723,7 +2797,7 @@ llvm::Type *X86_64ABIInfo::GetByteVectorType(QualType Ty) const {
// We couldn't find the preferred IR vector type for 'Ty'.
uint64_t Size = getContext().getTypeSize(Ty);
- assert((Size == 128 || Size == 256) && "Invalid type found!");
+ assert((Size == 128 || Size == 256 || Size == 512) && "Invalid type found!");
// Return a LLVM IR vector type based on the size of 'Ty'.
return llvm::VectorType::get(llvm::Type::getDoubleTy(getVMContext()),
@@ -3247,22 +3321,94 @@ ABIArgInfo X86_64ABIInfo::classifyArgumentType(
return ABIArgInfo::getDirect(ResType);
}
+ABIArgInfo
+X86_64ABIInfo::classifyRegCallStructTypeImpl(QualType Ty, unsigned &NeededInt,
+ unsigned &NeededSSE) const {
+ auto RT = Ty->getAs<RecordType>();
+ assert(RT && "classifyRegCallStructType only valid with struct types");
+
+ if (RT->getDecl()->hasFlexibleArrayMember())
+ return getIndirectReturnResult(Ty);
+
+ // Sum up bases
+ if (auto CXXRD = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
+ if (CXXRD->isDynamicClass()) {
+ NeededInt = NeededSSE = 0;
+ return getIndirectReturnResult(Ty);
+ }
+
+ for (const auto &I : CXXRD->bases())
+ if (classifyRegCallStructTypeImpl(I.getType(), NeededInt, NeededSSE)
+ .isIndirect()) {
+ NeededInt = NeededSSE = 0;
+ return getIndirectReturnResult(Ty);
+ }
+ }
+
+ // Sum up members
+ for (const auto *FD : RT->getDecl()->fields()) {
+ if (FD->getType()->isRecordType() && !FD->getType()->isUnionType()) {
+ if (classifyRegCallStructTypeImpl(FD->getType(), NeededInt, NeededSSE)
+ .isIndirect()) {
+ NeededInt = NeededSSE = 0;
+ return getIndirectReturnResult(Ty);
+ }
+ } else {
+ unsigned LocalNeededInt, LocalNeededSSE;
+ if (classifyArgumentType(FD->getType(), UINT_MAX, LocalNeededInt,
+ LocalNeededSSE, true)
+ .isIndirect()) {
+ NeededInt = NeededSSE = 0;
+ return getIndirectReturnResult(Ty);
+ }
+ NeededInt += LocalNeededInt;
+ NeededSSE += LocalNeededSSE;
+ }
+ }
+
+ return ABIArgInfo::getDirect();
+}
+
+ABIArgInfo X86_64ABIInfo::classifyRegCallStructType(QualType Ty,
+ unsigned &NeededInt,
+ unsigned &NeededSSE) const {
+
+ NeededInt = 0;
+ NeededSSE = 0;
+
+ return classifyRegCallStructTypeImpl(Ty, NeededInt, NeededSSE);
+}
+
void X86_64ABIInfo::computeInfo(CGFunctionInfo &FI) const {
- if (!getCXXABI().classifyReturnType(FI))
- FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+ bool IsRegCall = FI.getCallingConvention() == llvm::CallingConv::X86_RegCall;
// Keep track of the number of assigned registers.
- unsigned freeIntRegs = 6, freeSSERegs = 8;
+ unsigned FreeIntRegs = IsRegCall ? 11 : 6;
+ unsigned FreeSSERegs = IsRegCall ? 16 : 8;
+ unsigned NeededInt, NeededSSE;
+
+ if (IsRegCall && FI.getReturnType()->getTypePtr()->isRecordType() &&
+ !FI.getReturnType()->getTypePtr()->isUnionType()) {
+ FI.getReturnInfo() =
+ classifyRegCallStructType(FI.getReturnType(), NeededInt, NeededSSE);
+ if (FreeIntRegs >= NeededInt && FreeSSERegs >= NeededSSE) {
+ FreeIntRegs -= NeededInt;
+ FreeSSERegs -= NeededSSE;
+ } else {
+ FI.getReturnInfo() = getIndirectReturnResult(FI.getReturnType());
+ }
+ } else if (!getCXXABI().classifyReturnType(FI))
+ FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
// If the return value is indirect, then the hidden argument is consuming one
// integer register.
if (FI.getReturnInfo().isIndirect())
- --freeIntRegs;
+ --FreeIntRegs;
// The chain argument effectively gives us another free register.
if (FI.isChainCall())
- ++freeIntRegs;
+ ++FreeIntRegs;
unsigned NumRequiredArgs = FI.getNumRequiredArgs();
// AMD64-ABI 3.2.3p3: Once arguments are classified, the registers
@@ -3272,19 +3418,21 @@ void X86_64ABIInfo::computeInfo(CGFunctionInfo &FI) const {
it != ie; ++it, ++ArgNo) {
bool IsNamedArg = ArgNo < NumRequiredArgs;
- unsigned neededInt, neededSSE;
- it->info = classifyArgumentType(it->type, freeIntRegs, neededInt,
- neededSSE, IsNamedArg);
+ if (IsRegCall && it->type->isStructureOrClassType())
+ it->info = classifyRegCallStructType(it->type, NeededInt, NeededSSE);
+ else
+ it->info = classifyArgumentType(it->type, FreeIntRegs, NeededInt,
+ NeededSSE, IsNamedArg);
// AMD64-ABI 3.2.3p3: If there are no registers available for any
// eightbyte of an argument, the whole argument is passed on the
// stack. If registers have already been assigned for some
// eightbytes of such an argument, the assignments get reverted.
- if (freeIntRegs >= neededInt && freeSSERegs >= neededSSE) {
- freeIntRegs -= neededInt;
- freeSSERegs -= neededSSE;
+ if (FreeIntRegs >= NeededInt && FreeSSERegs >= NeededSSE) {
+ FreeIntRegs -= NeededInt;
+ FreeSSERegs -= NeededSSE;
} else {
- it->info = getIndirectResult(it->type, freeIntRegs);
+ it->info = getIndirectResult(it->type, FreeIntRegs);
}
}
}
@@ -3426,15 +3574,17 @@ Address X86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
llvm::Value *RegHiAddr = TyLo->isFPOrFPVectorTy() ? GPAddr : FPAddr;
// Copy the first element.
- llvm::Value *V =
- CGF.Builder.CreateDefaultAlignedLoad(
- CGF.Builder.CreateBitCast(RegLoAddr, PTyLo));
+ // FIXME: Our choice of alignment here and below is probably pessimistic.
+ llvm::Value *V = CGF.Builder.CreateAlignedLoad(
+ TyLo, CGF.Builder.CreateBitCast(RegLoAddr, PTyLo),
+ CharUnits::fromQuantity(getDataLayout().getABITypeAlignment(TyLo)));
CGF.Builder.CreateStore(V,
CGF.Builder.CreateStructGEP(Tmp, 0, CharUnits::Zero()));
// Copy the second element.
- V = CGF.Builder.CreateDefaultAlignedLoad(
- CGF.Builder.CreateBitCast(RegHiAddr, PTyHi));
+ V = CGF.Builder.CreateAlignedLoad(
+ TyHi, CGF.Builder.CreateBitCast(RegHiAddr, PTyHi),
+ CharUnits::fromQuantity(getDataLayout().getABITypeAlignment(TyHi)));
CharUnits Offset = CharUnits::fromQuantity(
getDataLayout().getStructLayout(ST)->getElementOffset(1));
CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 1, Offset));
@@ -3597,7 +3747,7 @@ ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty, unsigned &FreeSSERegs,
// passes them indirectly through memory.
if (IsMingw64 && BT && BT->getKind() == BuiltinType::LongDouble) {
const llvm::fltSemantics *LDF = &getTarget().getLongDoubleFormat();
- if (LDF == &llvm::APFloat::x87DoubleExtended)
+ if (LDF == &llvm::APFloat::x87DoubleExtended())
return ABIArgInfo::getIndirect(Align, /*ByVal=*/false);
}
@@ -3607,21 +3757,44 @@ ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty, unsigned &FreeSSERegs,
void WinX86_64ABIInfo::computeInfo(CGFunctionInfo &FI) const {
bool IsVectorCall =
FI.getCallingConvention() == llvm::CallingConv::X86_VectorCall;
+ bool IsRegCall = FI.getCallingConvention() == llvm::CallingConv::X86_RegCall;
+
+ unsigned FreeSSERegs = 0;
+ if (IsVectorCall) {
+ // We can use up to 4 SSE return registers with vectorcall.
+ FreeSSERegs = 4;
+ } else if (IsRegCall) {
+ // RegCall gives us 16 SSE registers.
+ FreeSSERegs = 16;
+ }
- // We can use up to 4 SSE return registers with vectorcall.
- unsigned FreeSSERegs = IsVectorCall ? 4 : 0;
if (!getCXXABI().classifyReturnType(FI))
FI.getReturnInfo() = classify(FI.getReturnType(), FreeSSERegs, true);
- // We can use up to 6 SSE register parameters with vectorcall.
- FreeSSERegs = IsVectorCall ? 6 : 0;
+ if (IsVectorCall) {
+ // We can use up to 6 SSE register parameters with vectorcall.
+ FreeSSERegs = 6;
+ } else if (IsRegCall) {
+ FreeSSERegs = 16;
+ }
+
for (auto &I : FI.arguments())
I.info = classify(I.type, FreeSSERegs, false);
}
Address WinX86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
QualType Ty) const {
- return emitVoidPtrVAArg(CGF, VAListAddr, Ty, /*indirect*/ false,
+
+ bool IsIndirect = false;
+
+ // MS x64 ABI requirement: "Any argument that doesn't fit in 8 bytes, or is
+ // not 1, 2, 4, or 8 bytes, must be passed by reference."
+ if (isAggregateTypeForABI(Ty) || Ty->isMemberPointerType()) {
+ uint64_t Width = getContext().getTypeSize(Ty);
+ IsIndirect = Width > 64 || !llvm::isPowerOf2_64(Width);
+ }
+
+ return emitVoidPtrVAArg(CGF, VAListAddr, Ty, IsIndirect,
CGF.getContext().getTypeInfoInChars(Ty),
CharUnits::fromQuantity(8),
/*allowHigherAlign*/ false);
@@ -3859,6 +4032,7 @@ private:
static const unsigned GPRBits = 64;
ABIKind Kind;
bool HasQPX;
+ bool IsSoftFloatABI;
// A vector of float or double will be promoted to <4 x f32> or <4 x f64> and
// will be passed in a QPX register.
@@ -3889,8 +4063,10 @@ private:
}
public:
- PPC64_SVR4_ABIInfo(CodeGen::CodeGenTypes &CGT, ABIKind Kind, bool HasQPX)
- : ABIInfo(CGT), Kind(Kind), HasQPX(HasQPX) {}
+ PPC64_SVR4_ABIInfo(CodeGen::CodeGenTypes &CGT, ABIKind Kind, bool HasQPX,
+ bool SoftFloatABI)
+ : ABIInfo(CGT), Kind(Kind), HasQPX(HasQPX),
+ IsSoftFloatABI(SoftFloatABI) {}
bool isPromotableTypeForABI(QualType Ty) const;
CharUnits getParamTypeAlignment(QualType Ty) const;
@@ -3938,8 +4114,10 @@ class PPC64_SVR4_TargetCodeGenInfo : public TargetCodeGenInfo {
public:
PPC64_SVR4_TargetCodeGenInfo(CodeGenTypes &CGT,
- PPC64_SVR4_ABIInfo::ABIKind Kind, bool HasQPX)
- : TargetCodeGenInfo(new PPC64_SVR4_ABIInfo(CGT, Kind, HasQPX)) {}
+ PPC64_SVR4_ABIInfo::ABIKind Kind, bool HasQPX,
+ bool SoftFloatABI)
+ : TargetCodeGenInfo(new PPC64_SVR4_ABIInfo(CGT, Kind, HasQPX,
+ SoftFloatABI)) {}
int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const override {
// This is recovered from gcc output.
@@ -4157,8 +4335,11 @@ 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) {
+ if (IsSoftFloatABI)
+ return false;
return true;
+ }
}
if (const VectorType *VT = Ty->getAs<VectorType>()) {
if (getContext().getTypeSize(VT) == 128 || IsQPXVectorTy(Ty))
@@ -4373,14 +4554,17 @@ PPC64_initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
// 32-63: fp0-31, the 8-byte floating-point registers
AssignToArrayRange(Builder, Address, Eight8, 32, 63);
- // 64-76 are various 4-byte special-purpose registers:
+ // 64-67 are various 8-byte special-purpose registers:
// 64: mq
// 65: lr
// 66: ctr
// 67: ap
+ AssignToArrayRange(Builder, Address, Eight8, 64, 67);
+
+ // 68-76 are various 4-byte special-purpose registers:
// 68-75 cr0-7
// 76: xer
- AssignToArrayRange(Builder, Address, Four8, 64, 76);
+ AssignToArrayRange(Builder, Address, Four8, 68, 76);
// 77-108: v0-31, the 16-byte vector registers
AssignToArrayRange(Builder, Address, Sixteen8, 77, 108);
@@ -4390,7 +4574,10 @@ PPC64_initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
// 111: spe_acc
// 112: spefscr
// 113: sfp
- AssignToArrayRange(Builder, Address, Four8, 109, 113);
+ // 114: tfhar
+ // 115: tfiar
+ // 116: texasr
+ AssignToArrayRange(Builder, Address, Eight8, 109, 116);
return false;
}
@@ -4467,6 +4654,9 @@ private:
bool asReturnValue) const override {
return occupiesMoreThan(CGT, scalars, /*total*/ 4);
}
+ bool isSwiftErrorInRegister() const override {
+ return true;
+ }
};
class AArch64TargetCodeGenInfo : public TargetCodeGenInfo {
@@ -4551,6 +4741,11 @@ ABIArgInfo AArch64ABIInfo::classifyArgumentType(QualType Ty) const {
// Aggregates <= 16 bytes are passed directly in registers or on the stack.
uint64_t Size = getContext().getTypeSize(Ty);
if (Size <= 128) {
+ // On RenderScript, coerce Aggregates <= 16 bytes to an integer array of
+ // same size and alignment.
+ if (getTarget().isRenderScriptTarget()) {
+ return coerceToIntArray(Ty, getContext(), getVMContext());
+ }
unsigned Alignment = getContext().getTypeAlign(Ty);
Size = 64 * ((Size + 63) / 64); // round up to multiple of 8 bytes
@@ -4596,6 +4791,11 @@ ABIArgInfo AArch64ABIInfo::classifyReturnType(QualType RetTy) const {
// Aggregates <= 16 bytes are returned directly in registers or on the stack.
uint64_t Size = getContext().getTypeSize(RetTy);
if (Size <= 128) {
+ // On RenderScript, coerce Aggregates <= 16 bytes to an integer array of
+ // same size and alignment.
+ if (getTarget().isRenderScriptTarget()) {
+ return coerceToIntArray(RetTy, getContext(), getVMContext());
+ }
unsigned Alignment = getContext().getTypeAlign(RetTy);
Size = 64 * ((Size + 63) / 64); // round up to multiple of 8 bytes
@@ -5010,6 +5210,9 @@ private:
bool asReturnValue) const override {
return occupiesMoreThan(CGT, scalars, /*total*/ 4);
}
+ bool isSwiftErrorInRegister() const override {
+ return true;
+ }
};
class ARMTargetCodeGenInfo : public TargetCodeGenInfo {
@@ -5286,6 +5489,12 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty,
/*Realign=*/TyAlign > ABIAlign);
}
+ // On RenderScript, coerce Aggregates <= 64 bytes to an integer array of
+ // same size and alignment.
+ if (getTarget().isRenderScriptTarget()) {
+ return coerceToIntArray(Ty, getContext(), getVMContext());
+ }
+
// Otherwise, pass by coercing to a structure of the appropriate size.
llvm::Type* ElemTy;
unsigned SizeRegs;
@@ -5467,6 +5676,11 @@ ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy,
// are returned indirectly.
uint64_t Size = getContext().getTypeSize(RetTy);
if (Size <= 32) {
+ // On RenderScript, coerce Aggregates <= 4 bytes to an integer array of
+ // same size and alignment.
+ if (getTarget().isRenderScriptTarget()) {
+ return coerceToIntArray(RetTy, getContext(), getVMContext());
+ }
if (getDataLayout().isBigEndian())
// Return in 32 bit integer integer type (as if loaded by LDR, AAPCS 5.4)
return ABIArgInfo::getDirect(llvm::Type::getInt32Ty(getVMContext()));
@@ -5767,6 +5981,9 @@ public:
bool asReturnValue) const override {
return occupiesMoreThan(CGT, scalars, /*total*/ 4);
}
+ bool isSwiftErrorInRegister() const override {
+ return true;
+ }
};
class SystemZTargetCodeGenInfo : public TargetCodeGenInfo {
@@ -6825,45 +7042,138 @@ public:
namespace {
+class AMDGPUABIInfo final : public DefaultABIInfo {
+public:
+ explicit AMDGPUABIInfo(CodeGen::CodeGenTypes &CGT) : DefaultABIInfo(CGT) {}
+
+private:
+ ABIArgInfo classifyArgumentType(QualType Ty) const;
+
+ void computeInfo(CGFunctionInfo &FI) const override;
+};
+
+void AMDGPUABIInfo::computeInfo(CGFunctionInfo &FI) const {
+ if (!getCXXABI().classifyReturnType(FI))
+ FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+
+ unsigned CC = FI.getCallingConvention();
+ for (auto &Arg : FI.arguments())
+ if (CC == llvm::CallingConv::AMDGPU_KERNEL)
+ Arg.info = classifyArgumentType(Arg.type);
+ else
+ Arg.info = DefaultABIInfo::classifyArgumentType(Arg.type);
+}
+
+/// \brief Classify argument of given type \p Ty.
+ABIArgInfo AMDGPUABIInfo::classifyArgumentType(QualType Ty) const {
+ llvm::StructType *StrTy = dyn_cast<llvm::StructType>(CGT.ConvertType(Ty));
+ if (!StrTy) {
+ return DefaultABIInfo::classifyArgumentType(Ty);
+ }
+
+ // Coerce single element structs to its element.
+ if (StrTy->getNumElements() == 1) {
+ return ABIArgInfo::getDirect();
+ }
+
+ // If we set CanBeFlattened to true, CodeGen will expand the struct to its
+ // individual elements, which confuses the Clover OpenCL backend; therefore we
+ // have to set it to false here. Other args of getDirect() are just defaults.
+ return ABIArgInfo::getDirect(nullptr, 0, nullptr, false);
+}
+
class AMDGPUTargetCodeGenInfo : public TargetCodeGenInfo {
public:
AMDGPUTargetCodeGenInfo(CodeGenTypes &CGT)
- : TargetCodeGenInfo(new DefaultABIInfo(CGT)) {}
+ : TargetCodeGenInfo(new AMDGPUABIInfo(CGT)) {}
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
CodeGen::CodeGenModule &M) const override;
unsigned getOpenCLKernelCallingConv() const override;
-};
+ llvm::Constant *getNullPointer(const CodeGen::CodeGenModule &CGM,
+ llvm::PointerType *T, QualType QT) const override;
+};
}
+static void appendOpenCLVersionMD (CodeGen::CodeGenModule &CGM);
+
void AMDGPUTargetCodeGenInfo::setTargetAttributes(
- const Decl *D,
- llvm::GlobalValue *GV,
- CodeGen::CodeGenModule &M) const {
+ const Decl *D,
+ llvm::GlobalValue *GV,
+ CodeGen::CodeGenModule &M) const {
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
if (!FD)
return;
- if (const auto Attr = FD->getAttr<AMDGPUNumVGPRAttr>()) {
- llvm::Function *F = cast<llvm::Function>(GV);
- uint32_t NumVGPR = Attr->getNumVGPR();
- if (NumVGPR != 0)
- F->addFnAttr("amdgpu_num_vgpr", llvm::utostr(NumVGPR));
+ llvm::Function *F = cast<llvm::Function>(GV);
+
+ if (const auto *Attr = FD->getAttr<AMDGPUFlatWorkGroupSizeAttr>()) {
+ unsigned Min = Attr->getMin();
+ unsigned Max = Attr->getMax();
+
+ if (Min != 0) {
+ assert(Min <= Max && "Min must be less than or equal Max");
+
+ std::string AttrVal = llvm::utostr(Min) + "," + llvm::utostr(Max);
+ F->addFnAttr("amdgpu-flat-work-group-size", AttrVal);
+ } else
+ assert(Max == 0 && "Max must be zero");
}
- if (const auto Attr = FD->getAttr<AMDGPUNumSGPRAttr>()) {
- llvm::Function *F = cast<llvm::Function>(GV);
+ if (const auto *Attr = FD->getAttr<AMDGPUWavesPerEUAttr>()) {
+ unsigned Min = Attr->getMin();
+ unsigned Max = Attr->getMax();
+
+ if (Min != 0) {
+ assert((Max == 0 || Min <= Max) && "Min must be less than or equal Max");
+
+ std::string AttrVal = llvm::utostr(Min);
+ if (Max != 0)
+ AttrVal = AttrVal + "," + llvm::utostr(Max);
+ F->addFnAttr("amdgpu-waves-per-eu", AttrVal);
+ } else
+ assert(Max == 0 && "Max must be zero");
+ }
+
+ if (const auto *Attr = FD->getAttr<AMDGPUNumSGPRAttr>()) {
unsigned NumSGPR = Attr->getNumSGPR();
+
if (NumSGPR != 0)
- F->addFnAttr("amdgpu_num_sgpr", llvm::utostr(NumSGPR));
+ F->addFnAttr("amdgpu-num-sgpr", llvm::utostr(NumSGPR));
}
-}
+ if (const auto *Attr = FD->getAttr<AMDGPUNumVGPRAttr>()) {
+ uint32_t NumVGPR = Attr->getNumVGPR();
+
+ if (NumVGPR != 0)
+ F->addFnAttr("amdgpu-num-vgpr", llvm::utostr(NumVGPR));
+ }
+
+ appendOpenCLVersionMD(M);
+}
unsigned AMDGPUTargetCodeGenInfo::getOpenCLKernelCallingConv() const {
return llvm::CallingConv::AMDGPU_KERNEL;
}
+// Currently LLVM assumes null pointers always have value 0,
+// which results in incorrectly transformed IR. Therefore, instead of
+// emitting null pointers in private and local address spaces, a null
+// pointer in generic address space is emitted which is casted to a
+// pointer in local or private address space.
+llvm::Constant *AMDGPUTargetCodeGenInfo::getNullPointer(
+ const CodeGen::CodeGenModule &CGM, llvm::PointerType *PT,
+ QualType QT) const {
+ if (CGM.getContext().getTargetNullPointerValue(QT) == 0)
+ return llvm::ConstantPointerNull::get(PT);
+
+ auto &Ctx = CGM.getContext();
+ auto NPT = llvm::PointerType::get(PT->getElementType(),
+ Ctx.getTargetAddressSpace(LangAS::opencl_generic));
+ return llvm::ConstantExpr::getAddrSpaceCast(
+ llvm::ConstantPointerNull::get(NPT), PT);
+}
+
//===----------------------------------------------------------------------===//
// SPARC v8 ABI Implementation.
// Based on the SPARC Compliance Definition version 2.4.1.
@@ -7303,7 +7613,7 @@ class FieldEncoding {
std::string Enc;
public:
FieldEncoding(bool b, SmallStringEnc &e) : HasName(b), Enc(e.c_str()) {}
- StringRef str() {return Enc.c_str();}
+ StringRef str() { return Enc; }
bool operator<(const FieldEncoding &rhs) const {
if (HasName != rhs.HasName) return HasName;
return Enc < rhs.Enc;
@@ -7469,7 +7779,7 @@ StringRef TypeStringCache::lookupStr(const IdentifierInfo *ID) {
E.State = IncompleteUsed;
++IncompleteUsedCount;
}
- return E.Str.c_str();
+ return E.Str;
}
/// The XCore ABI includes a type information section that communicates symbol
@@ -7525,11 +7835,20 @@ void SPIRTargetCodeGenInfo::emitTargetMD(const Decl *D, llvm::GlobalValue *GV,
// SPIR v2.0 s2.12 - The SPIR version used by the module is stored in the
// opencl.spir.version named metadata.
llvm::Metadata *SPIRVerElts[] = {
- llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(Int32Ty, 2)),
- llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(Int32Ty, 0))};
+ llvm::ConstantAsMetadata::get(
+ llvm::ConstantInt::get(Int32Ty, CGM.getLangOpts().OpenCLVersion / 100)),
+ llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
+ Int32Ty, (CGM.getLangOpts().OpenCLVersion / 100 > 1) ? 0 : 2))};
llvm::NamedMDNode *SPIRVerMD =
M.getOrInsertNamedMetadata("opencl.spir.version");
SPIRVerMD->addOperand(llvm::MDNode::get(Ctx, SPIRVerElts));
+ appendOpenCLVersionMD(CGM);
+}
+
+static void appendOpenCLVersionMD(CodeGen::CodeGenModule &CGM) {
+ llvm::LLVMContext &Ctx = CGM.getModule().getContext();
+ llvm::Type *Int32Ty = llvm::Type::getInt32Ty(Ctx);
+ llvm::Module &M = CGM.getModule();
// SPIR v2.0 s2.13 - The OpenCL version used by the module is stored in the
// opencl.ocl.version named metadata node.
llvm::Metadata *OCLVerElts[] = {
@@ -7882,10 +8201,6 @@ static bool getTypeString(SmallStringEnc &Enc, const Decl *D,
// Driver code
//===----------------------------------------------------------------------===//
-const llvm::Triple &CodeGenModule::getTriple() const {
- return getTarget().getTriple();
-}
-
bool CodeGenModule::supportsCOMDAT() const {
return getTriple().supportsCOMDAT();
}
@@ -7964,8 +8279,10 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() {
if (getTarget().getABI() == "elfv2")
Kind = PPC64_SVR4_ABIInfo::ELFv2;
bool HasQPX = getTarget().getABI() == "elfv1-qpx";
+ bool IsSoftFloat = CodeGenOpts.FloatABI == "soft";
- return SetCGInfo(new PPC64_SVR4_TargetCodeGenInfo(Types, Kind, HasQPX));
+ return SetCGInfo(new PPC64_SVR4_TargetCodeGenInfo(Types, Kind, HasQPX,
+ IsSoftFloat));
} else
return SetCGInfo(new PPC64TargetCodeGenInfo(Types));
case llvm::Triple::ppc64le: {
@@ -7974,8 +8291,10 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() {
if (getTarget().getABI() == "elfv1" || getTarget().getABI() == "elfv1-qpx")
Kind = PPC64_SVR4_ABIInfo::ELFv1;
bool HasQPX = getTarget().getABI() == "elfv1-qpx";
+ bool IsSoftFloat = CodeGenOpts.FloatABI == "soft";
- return SetCGInfo(new PPC64_SVR4_TargetCodeGenInfo(Types, Kind, HasQPX));
+ return SetCGInfo(new PPC64_SVR4_TargetCodeGenInfo(Types, Kind, HasQPX,
+ IsSoftFloat));
}
case llvm::Triple::nvptx:
@@ -7991,6 +8310,7 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() {
}
case llvm::Triple::tce:
+ case llvm::Triple::tcele:
return SetCGInfo(new TCETargetCodeGenInfo(Types));
case llvm::Triple::x86: {
diff --git a/lib/CodeGen/TargetInfo.h b/lib/CodeGen/TargetInfo.h
index e46382596af7..223d6d047af7 100644
--- a/lib/CodeGen/TargetInfo.h
+++ b/lib/CodeGen/TargetInfo.h
@@ -220,6 +220,22 @@ public:
/// Get LLVM calling convention for OpenCL kernel.
virtual unsigned getOpenCLKernelCallingConv() const;
+
+ /// Get target specific null pointer.
+ /// \param T is the LLVM type of the null pointer.
+ /// \param QT is the clang QualType of the null pointer.
+ /// \return ConstantPointerNull with the given type \p T.
+ /// Each target can override it to return its own desired constant value.
+ virtual llvm::Constant *getNullPointer(const CodeGen::CodeGenModule &CGM,
+ llvm::PointerType *T, QualType QT) const;
+
+ /// Perform address space cast of an expression of pointer type.
+ /// \param V is the LLVM value to be casted to another address space.
+ /// \param SrcTy is the QualType of \p V.
+ /// \param DestTy is the destination QualType.
+ virtual llvm::Value *performAddrSpaceCast(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *V, QualType SrcTy, QualType DestTy) const;
+
};
} // namespace CodeGen
diff --git a/lib/CodeGen/VarBypassDetector.cpp b/lib/CodeGen/VarBypassDetector.cpp
new file mode 100644
index 000000000000..cfb93d6a9fcc
--- /dev/null
+++ b/lib/CodeGen/VarBypassDetector.cpp
@@ -0,0 +1,168 @@
+//===--- VarBypassDetector.h - Bypass jumps detector --------------*- C++ -*-=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "VarBypassDetector.h"
+
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/Stmt.h"
+
+using namespace clang;
+using namespace CodeGen;
+
+/// Clear the object and pre-process for the given statement, usually function
+/// body statement.
+void VarBypassDetector::Init(const Stmt *Body) {
+ FromScopes.clear();
+ ToScopes.clear();
+ Bypasses.clear();
+ Scopes = {{~0U, nullptr}};
+ unsigned ParentScope = 0;
+ AlwaysBypassed = !BuildScopeInformation(Body, ParentScope);
+ if (!AlwaysBypassed)
+ Detect();
+}
+
+/// Build scope information for a declaration that is part of a DeclStmt.
+/// Returns false if we failed to build scope information and can't tell for
+/// which vars are being bypassed.
+bool VarBypassDetector::BuildScopeInformation(const Decl *D,
+ unsigned &ParentScope) {
+ const VarDecl *VD = dyn_cast<VarDecl>(D);
+ if (VD && VD->hasLocalStorage()) {
+ Scopes.push_back({ParentScope, VD});
+ ParentScope = Scopes.size() - 1;
+ }
+
+ if (const VarDecl *VD = dyn_cast<VarDecl>(D))
+ if (const Expr *Init = VD->getInit())
+ return BuildScopeInformation(Init, ParentScope);
+
+ return true;
+}
+
+/// Walk through the statements, adding any labels or gotos to
+/// LabelAndGotoScopes and recursively walking the AST as needed.
+/// Returns false if we failed to build scope information and can't tell for
+/// which vars are being bypassed.
+bool VarBypassDetector::BuildScopeInformation(const Stmt *S,
+ unsigned &origParentScope) {
+ // If this is a statement, rather than an expression, scopes within it don't
+ // propagate out into the enclosing scope. Otherwise we have to worry about
+ // block literals, which have the lifetime of their enclosing statement.
+ unsigned independentParentScope = origParentScope;
+ unsigned &ParentScope =
+ ((isa<Expr>(S) && !isa<StmtExpr>(S)) ? origParentScope
+ : independentParentScope);
+
+ unsigned StmtsToSkip = 0u;
+
+ switch (S->getStmtClass()) {
+ case Stmt::IndirectGotoStmtClass:
+ return false;
+
+ case Stmt::SwitchStmtClass:
+ if (const Stmt *Init = cast<SwitchStmt>(S)->getInit()) {
+ if (!BuildScopeInformation(Init, ParentScope))
+ return false;
+ ++StmtsToSkip;
+ }
+ if (const VarDecl *Var = cast<SwitchStmt>(S)->getConditionVariable()) {
+ if (!BuildScopeInformation(Var, ParentScope))
+ return false;
+ ++StmtsToSkip;
+ }
+ // Fall through
+
+ case Stmt::GotoStmtClass:
+ FromScopes.push_back({S, ParentScope});
+ break;
+
+ case Stmt::DeclStmtClass: {
+ const DeclStmt *DS = cast<DeclStmt>(S);
+ for (auto *I : DS->decls())
+ if (!BuildScopeInformation(I, origParentScope))
+ return false;
+ return true;
+ }
+
+ case Stmt::CaseStmtClass:
+ case Stmt::DefaultStmtClass:
+ case Stmt::LabelStmtClass:
+ llvm_unreachable("the loop bellow handles labels and cases");
+ break;
+
+ default:
+ break;
+ }
+
+ for (const Stmt *SubStmt : S->children()) {
+ if (!SubStmt)
+ continue;
+ if (StmtsToSkip) {
+ --StmtsToSkip;
+ continue;
+ }
+
+ // Cases, labels, and defaults aren't "scope parents". It's also
+ // important to handle these iteratively instead of recursively in
+ // order to avoid blowing out the stack.
+ while (true) {
+ const Stmt *Next;
+ if (const SwitchCase *SC = dyn_cast<SwitchCase>(SubStmt))
+ Next = SC->getSubStmt();
+ else if (const LabelStmt *LS = dyn_cast<LabelStmt>(SubStmt))
+ Next = LS->getSubStmt();
+ else
+ break;
+
+ ToScopes[SubStmt] = ParentScope;
+ SubStmt = Next;
+ }
+
+ // Recursively walk the AST.
+ if (!BuildScopeInformation(SubStmt, ParentScope))
+ return false;
+ }
+ return true;
+}
+
+/// Checks each jump and stores each variable declaration they bypass.
+void VarBypassDetector::Detect() {
+ for (const auto &S : FromScopes) {
+ const Stmt *St = S.first;
+ unsigned from = S.second;
+ if (const GotoStmt *GS = dyn_cast<GotoStmt>(St)) {
+ if (const LabelStmt *LS = GS->getLabel()->getStmt())
+ Detect(from, ToScopes[LS]);
+ } else if (const SwitchStmt *SS = dyn_cast<SwitchStmt>(St)) {
+ for (const SwitchCase *SC = SS->getSwitchCaseList(); SC;
+ SC = SC->getNextSwitchCase()) {
+ Detect(from, ToScopes[SC]);
+ }
+ } else {
+ llvm_unreachable("goto or switch was expected");
+ }
+ }
+}
+
+/// Checks the jump and stores each variable declaration it bypasses.
+void VarBypassDetector::Detect(unsigned From, unsigned To) {
+ while (From != To) {
+ if (From < To) {
+ assert(Scopes[To].first < To);
+ const auto &ScopeTo = Scopes[To];
+ To = ScopeTo.first;
+ Bypasses.insert(ScopeTo.second);
+ } else {
+ assert(Scopes[From].first < From);
+ From = Scopes[From].first;
+ }
+ }
+}
diff --git a/lib/CodeGen/VarBypassDetector.h b/lib/CodeGen/VarBypassDetector.h
new file mode 100644
index 000000000000..f50baf4bab9f
--- /dev/null
+++ b/lib/CodeGen/VarBypassDetector.h
@@ -0,0 +1,70 @@
+//===--- VarBypassDetector.cpp - Bypass jumps detector ------------*- C++ -*-=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains VarBypassDetector class, which is used to detect
+// local variable declarations which can be bypassed by jumps.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_CODEGEN_VARBYPASSDETECTOR_H
+#define LLVM_CLANG_LIB_CODEGEN_VARBYPASSDETECTOR_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SmallVector.h"
+
+namespace clang {
+
+class Decl;
+class Stmt;
+class VarDecl;
+
+namespace CodeGen {
+
+/// The class detects jumps which bypass local variables declaration:
+/// goto L;
+/// int a;
+/// L:
+///
+/// This is simplified version of JumpScopeChecker. Primary differences:
+/// * Detects only jumps into the scope local variables.
+/// * Does not detect jumps out of the scope of local variables.
+/// * Not limited to variables with initializers, JumpScopeChecker is limited.
+class VarBypassDetector {
+ // Scope information. Contains a parent scope and related variable
+ // declaration.
+ llvm::SmallVector<std::pair<unsigned, const VarDecl *>, 48> Scopes;
+ // List of jumps with scopes.
+ llvm::SmallVector<std::pair<const Stmt *, unsigned>, 16> FromScopes;
+ // Lookup map to find scope for destinations.
+ llvm::DenseMap<const Stmt *, unsigned> ToScopes;
+ // Set of variables which were bypassed by some jump.
+ llvm::DenseSet<const VarDecl *> Bypasses;
+ // If true assume that all variables are being bypassed.
+ bool AlwaysBypassed = false;
+
+public:
+ void Init(const Stmt *Body);
+
+ /// Returns true if the variable declaration was by bypassed by any goto or
+ /// switch statement.
+ bool IsBypassed(const VarDecl *D) const {
+ return AlwaysBypassed || Bypasses.find(D) != Bypasses.end();
+ }
+
+private:
+ bool BuildScopeInformation(const Decl *D, unsigned &ParentScope);
+ bool BuildScopeInformation(const Stmt *S, unsigned &origParentScope);
+ void Detect();
+ void Detect(unsigned From, unsigned To);
+};
+}
+}
+
+#endif
diff --git a/lib/Driver/Action.cpp b/lib/Driver/Action.cpp
index 29a46794d4b9..85e466a4409d 100644
--- a/lib/Driver/Action.cpp
+++ b/lib/Driver/Action.cpp
@@ -9,6 +9,7 @@
#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"
@@ -36,6 +37,10 @@ const char *Action::getClassName(ActionClass AC) {
case DsymutilJobClass: return "dsymutil";
case VerifyDebugInfoJobClass: return "verify-debug-info";
case VerifyPCHJobClass: return "verify-pch";
+ case OffloadBundlingJobClass:
+ return "clang-offload-bundler";
+ case OffloadUnbundlingJobClass:
+ return "clang-offload-unbundler";
}
llvm_unreachable("invalid class");
@@ -45,6 +50,9 @@ void Action::propagateDeviceOffloadInfo(OffloadKind OKind, const char *OArch) {
// Offload action set its own kinds on their dependences.
if (Kind == OffloadClass)
return;
+ // Unbundling actions use the host kinds.
+ if (Kind == OffloadUnbundlingJobClass)
+ return;
assert((OffloadingDeviceKind == OKind || OffloadingDeviceKind == OFK_None) &&
"Setting device kind to a different device??");
@@ -87,6 +95,8 @@ std::string Action::getOffloadingKindPrefix() const {
break;
case OFK_Cuda:
return "device-cuda";
+ case OFK_OpenMP:
+ return "device-openmp";
// TODO: Add other programming models here.
}
@@ -97,26 +107,49 @@ std::string Action::getOffloadingKindPrefix() const {
std::string Res("host");
if (ActiveOffloadKindMask & OFK_Cuda)
Res += "-cuda";
+ if (ActiveOffloadKindMask & OFK_OpenMP)
+ Res += "-openmp";
// TODO: Add other programming models here.
return Res;
}
+/// Return a string that can be used as prefix in order to generate unique files
+/// for each offloading kind.
std::string
-Action::getOffloadingFileNamePrefix(llvm::StringRef NormalizedTriple) const {
- // A file prefix is only generated for device actions and consists of the
- // offload kind and triple.
- if (!OffloadingDeviceKind)
+Action::GetOffloadingFileNamePrefix(OffloadKind Kind,
+ llvm::StringRef NormalizedTriple,
+ bool CreatePrefixForHost) {
+ // Don't generate prefix for host actions unless required.
+ if (!CreatePrefixForHost && (Kind == OFK_None || Kind == OFK_Host))
return "";
std::string Res("-");
- Res += getOffloadingKindPrefix();
+ Res += GetOffloadKindName(Kind);
Res += "-";
Res += NormalizedTriple;
return Res;
}
+/// Return a string with the offload kind name. If that is not defined, we
+/// assume 'host'.
+llvm::StringRef Action::GetOffloadKindName(OffloadKind Kind) {
+ switch (Kind) {
+ case OFK_None:
+ case OFK_Host:
+ return "host";
+ case OFK_Cuda:
+ return "cuda";
+ case OFK_OpenMP:
+ return "openmp";
+
+ // TODO: Add other programming models here.
+ }
+
+ llvm_unreachable("invalid offload kind");
+}
+
void InputAction::anchor() {}
InputAction::InputAction(const Arg &_Input, types::ID _Type)
@@ -125,8 +158,8 @@ InputAction::InputAction(const Arg &_Input, types::ID _Type)
void BindArchAction::anchor() {}
-BindArchAction::BindArchAction(Action *Input, const char *_ArchName)
- : Action(BindArchClass, Input), ArchName(_ArchName) {}
+BindArchAction::BindArchAction(Action *Input, llvm::StringRef ArchName)
+ : Action(BindArchClass, Input), ArchName(ArchName) {}
void OffloadAction::anchor() {}
@@ -342,3 +375,13 @@ void VerifyPCHJobAction::anchor() {}
VerifyPCHJobAction::VerifyPCHJobAction(Action *Input, types::ID Type)
: VerifyJobAction(VerifyPCHJobClass, Input, Type) {}
+
+void OffloadBundlingJobAction::anchor() {}
+
+OffloadBundlingJobAction::OffloadBundlingJobAction(ActionList &Inputs)
+ : JobAction(OffloadBundlingJobClass, Inputs, Inputs.front()->getType()) {}
+
+void OffloadUnbundlingJobAction::anchor() {}
+
+OffloadUnbundlingJobAction::OffloadUnbundlingJobAction(Action *Input)
+ : JobAction(OffloadUnbundlingJobClass, Input, Input->getType()) {}
diff --git a/lib/Driver/CMakeLists.txt b/lib/Driver/CMakeLists.txt
index 5b8422ed550c..3ebd1c4f891e 100644
--- a/lib/Driver/CMakeLists.txt
+++ b/lib/Driver/CMakeLists.txt
@@ -12,6 +12,7 @@ add_clang_library(clangDriver
Action.cpp
Compilation.cpp
CrossWindowsToolChain.cpp
+ Distro.cpp
Driver.cpp
DriverOptions.cpp
Job.cpp
diff --git a/lib/Driver/Compilation.cpp b/lib/Driver/Compilation.cpp
index 6a2616f0c2a4..5c13e59a0d73 100644
--- a/lib/Driver/Compilation.cpp
+++ b/lib/Driver/Compilation.cpp
@@ -37,11 +37,9 @@ Compilation::~Compilation() {
delete Args;
// Free any derived arg lists.
- for (llvm::DenseMap<std::pair<const ToolChain*, const char*>,
- DerivedArgList*>::iterator it = TCArgs.begin(),
- ie = TCArgs.end(); it != ie; ++it)
- if (it->second != TranslatedArgs)
- delete it->second;
+ for (auto Arg : TCArgs)
+ if (Arg.second != TranslatedArgs)
+ delete Arg.second;
// Free redirections of stdout/stderr.
if (Redirects) {
@@ -52,14 +50,15 @@ Compilation::~Compilation() {
}
}
-const DerivedArgList &Compilation::getArgsForToolChain(const ToolChain *TC,
- const char *BoundArch) {
+const DerivedArgList &
+Compilation::getArgsForToolChain(const ToolChain *TC, StringRef BoundArch,
+ Action::OffloadKind DeviceOffloadKind) {
if (!TC)
TC = &DefaultToolChain;
- DerivedArgList *&Entry = TCArgs[std::make_pair(TC, BoundArch)];
+ DerivedArgList *&Entry = TCArgs[{TC, BoundArch, DeviceOffloadKind}];
if (!Entry) {
- Entry = TC->TranslateArgs(*TranslatedArgs, BoundArch);
+ Entry = TC->TranslateArgs(*TranslatedArgs, BoundArch, DeviceOffloadKind);
if (!Entry)
Entry = TranslatedArgs;
}
diff --git a/lib/Driver/CrossWindowsToolChain.cpp b/lib/Driver/CrossWindowsToolChain.cpp
index 4ebbc533232f..28036ea51cff 100644
--- a/lib/Driver/CrossWindowsToolChain.cpp
+++ b/lib/Driver/CrossWindowsToolChain.cpp
@@ -11,6 +11,7 @@
#include "clang/Driver/Driver.h"
#include "clang/Driver/Options.h"
#include "llvm/Option/ArgList.h"
+#include "llvm/Support/Path.h"
using namespace clang::driver;
using namespace clang::driver::toolchains;
diff --git a/lib/Driver/Distro.cpp b/lib/Driver/Distro.cpp
new file mode 100644
index 000000000000..d305b179449f
--- /dev/null
+++ b/lib/Driver/Distro.cpp
@@ -0,0 +1,134 @@
+//===--- Distro.cpp - Linux distribution detection support ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/Distro.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/MemoryBuffer.h"
+
+using namespace clang::driver;
+using namespace clang;
+
+static Distro::DistroType DetectDistro(vfs::FileSystem &VFS) {
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> File =
+ VFS.getBufferForFile("/etc/lsb-release");
+ if (File) {
+ StringRef Data = File.get()->getBuffer();
+ SmallVector<StringRef, 16> Lines;
+ Data.split(Lines, "\n");
+ 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))
+ .Case("hardy", Distro::UbuntuHardy)
+ .Case("intrepid", Distro::UbuntuIntrepid)
+ .Case("jaunty", Distro::UbuntuJaunty)
+ .Case("karmic", Distro::UbuntuKarmic)
+ .Case("lucid", Distro::UbuntuLucid)
+ .Case("maverick", Distro::UbuntuMaverick)
+ .Case("natty", Distro::UbuntuNatty)
+ .Case("oneiric", Distro::UbuntuOneiric)
+ .Case("precise", Distro::UbuntuPrecise)
+ .Case("quantal", Distro::UbuntuQuantal)
+ .Case("raring", Distro::UbuntuRaring)
+ .Case("saucy", Distro::UbuntuSaucy)
+ .Case("trusty", Distro::UbuntuTrusty)
+ .Case("utopic", Distro::UbuntuUtopic)
+ .Case("vivid", Distro::UbuntuVivid)
+ .Case("wily", Distro::UbuntuWily)
+ .Case("xenial", Distro::UbuntuXenial)
+ .Case("yakkety", Distro::UbuntuYakkety)
+ .Case("zesty", Distro::UbuntuZesty)
+ .Default(Distro::UnknownDistro);
+ if (Version != Distro::UnknownDistro)
+ return Version;
+ }
+
+ File = VFS.getBufferForFile("/etc/redhat-release");
+ if (File) {
+ StringRef Data = File.get()->getBuffer();
+ if (Data.startswith("Fedora release"))
+ return Distro::Fedora;
+ if (Data.startswith("Red Hat Enterprise Linux") ||
+ Data.startswith("CentOS") ||
+ Data.startswith("Scientific Linux")) {
+ if (Data.find("release 7") != StringRef::npos)
+ return Distro::RHEL7;
+ else if (Data.find("release 6") != StringRef::npos)
+ return Distro::RHEL6;
+ else if (Data.find("release 5") != StringRef::npos)
+ return Distro::RHEL5;
+ }
+ return Distro::UnknownDistro;
+ }
+
+ File = VFS.getBufferForFile("/etc/debian_version");
+ if (File) {
+ StringRef Data = File.get()->getBuffer();
+ // Contents: < major.minor > or < codename/sid >
+ int MajorVersion;
+ if (!Data.split('.').first.getAsInteger(10, MajorVersion)) {
+ switch (MajorVersion) {
+ case 5:
+ return Distro::DebianLenny;
+ case 6:
+ return Distro::DebianSqueeze;
+ case 7:
+ return Distro::DebianWheezy;
+ case 8:
+ return Distro::DebianJessie;
+ case 9:
+ return Distro::DebianStretch;
+ default:
+ return Distro::UnknownDistro;
+ }
+ }
+ return llvm::StringSwitch<Distro::DistroType>(Data.split("\n").first)
+ .Case("squeeze/sid", Distro::DebianSqueeze)
+ .Case("wheezy/sid", Distro::DebianWheezy)
+ .Case("jessie/sid", Distro::DebianJessie)
+ .Case("stretch/sid", Distro::DebianStretch)
+ .Default(Distro::UnknownDistro);
+ }
+
+ File = VFS.getBufferForFile("/etc/SuSE-release");
+ if (File) {
+ StringRef Data = File.get()->getBuffer();
+ SmallVector<StringRef, 8> Lines;
+ Data.split(Lines, "\n");
+ for (const StringRef& Line : Lines) {
+ if (!Line.trim().startswith("VERSION"))
+ continue;
+ std::pair<StringRef, StringRef> SplitLine = Line.split('=');
+ // Old versions have split VERSION and PATCHLEVEL
+ // Newer versions use VERSION = x.y
+ std::pair<StringRef, StringRef> SplitVer = SplitLine.second.trim().split('.');
+ int Version;
+
+ // OpenSUSE/SLES 10 and older are not supported and not compatible
+ // with our rules, so just treat them as Distro::UnknownDistro.
+ if (!SplitVer.first.getAsInteger(10, Version) && Version > 10)
+ return Distro::OpenSUSE;
+ return Distro::UnknownDistro;
+ }
+ return Distro::UnknownDistro;
+ }
+
+ if (VFS.exists("/etc/exherbo-release"))
+ return Distro::Exherbo;
+
+ if (VFS.exists("/etc/arch-release"))
+ return Distro::ArchLinux;
+
+ return Distro::UnknownDistro;
+}
+
+Distro::Distro(vfs::FileSystem &VFS) : DistroVal(DetectDistro(VFS)) {}
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index 02f4a9997711..7bd43ac9da2f 100644
--- a/lib/Driver/Driver.cpp
+++ b/lib/Driver/Driver.cpp
@@ -32,7 +32,6 @@
#include "llvm/Option/OptSpecifier.h"
#include "llvm/Option/OptTable.h"
#include "llvm/Option/Option.h"
-#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
@@ -43,6 +42,9 @@
#include <map>
#include <memory>
#include <utility>
+#if LLVM_ON_UNIX
+#include <unistd.h> // getpid
+#endif
using namespace clang::driver;
using namespace clang;
@@ -55,12 +57,12 @@ Driver::Driver(StringRef ClangExecutable, StringRef DefaultTargetTriple,
Mode(GCCMode), SaveTemps(SaveTempsNone), BitcodeEmbed(EmbedNone),
LTOMode(LTOK_None), ClangExecutable(ClangExecutable),
SysRoot(DEFAULT_SYSROOT), UseStdLib(true),
- DefaultTargetTriple(DefaultTargetTriple),
DriverTitle("clang LLVM compiler"), CCPrintOptionsFilename(nullptr),
CCPrintHeadersFilename(nullptr), CCLogDiagnosticsFilename(nullptr),
CCCPrintBindings(false), CCPrintHeaders(false), CCLogDiagnostics(false),
- CCGenDiagnostics(false), CCCGenericGCCName(""), CheckInputsExist(true),
- CCCUsePCH(true), SuppressMissingInputWarning(false) {
+ CCGenDiagnostics(false), DefaultTargetTriple(DefaultTargetTriple),
+ CCCGenericGCCName(""), CheckInputsExist(true), CCCUsePCH(true),
+ SuppressMissingInputWarning(false) {
// Provide a sane fallback if no VFS is specified.
if (!this->VFS)
@@ -89,31 +91,39 @@ Driver::~Driver() {
llvm::DeleteContainerSeconds(ToolChains);
}
-void Driver::ParseDriverMode(ArrayRef<const char *> Args) {
- const std::string OptName =
- getOpts().getOption(options::OPT_driver_mode).getPrefixedName();
+void Driver::ParseDriverMode(StringRef ProgramName,
+ ArrayRef<const char *> Args) {
+ auto Default = ToolChain::getTargetAndModeFromProgramName(ProgramName);
+ StringRef DefaultMode(Default.second);
+ setDriverModeFromOption(DefaultMode);
for (const char *ArgPtr : Args) {
// Ingore nullptrs, they are response file's EOL markers
if (ArgPtr == nullptr)
continue;
const StringRef Arg = ArgPtr;
- if (!Arg.startswith(OptName))
- continue;
+ setDriverModeFromOption(Arg);
+ }
+}
- const StringRef Value = Arg.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);
+void Driver::setDriverModeFromOption(StringRef Opt) {
+ const std::string OptName =
+ getOpts().getOption(options::OPT_driver_mode).getPrefixedName();
+ if (!Opt.startswith(OptName))
+ return;
+ StringRef Value = Opt.drop_front(OptName.size());
- if (M != ~0U)
- Mode = static_cast<DriverMode>(M);
- else
- Diag(diag::err_drv_unsupported_option_argument) << OptName << Value;
- }
+ 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);
+ else
+ Diag(diag::err_drv_unsupported_option_argument) << OptName << Value;
}
InputArgList Driver::ParseArgStrings(ArrayRef<const char *> ArgStrings) {
@@ -170,6 +180,10 @@ phases::ID Driver::getFinalPhase(const DerivedArgList &DAL,
(PhaseArg = DAL.getLastArg(options::OPT__SLASH_P))) {
FinalPhase = phases::Preprocess;
+ // --precompile only runs up to precompilation.
+ } else if ((PhaseArg = DAL.getLastArg(options::OPT__precompile))) {
+ FinalPhase = phases::Precompile;
+
// -{fsyntax-only,-analyze,emit-ast} only run up to the compiler.
} else if ((PhaseArg = DAL.getLastArg(options::OPT_fsyntax_only)) ||
(PhaseArg = DAL.getLastArg(options::OPT_module_file_info)) ||
@@ -423,6 +437,32 @@ void Driver::setLTOMode(const llvm::opt::ArgList &Args) {
}
}
+/// Compute the desired OpenMP runtime from the flags provided.
+Driver::OpenMPRuntimeKind Driver::getOpenMPRuntime(const ArgList &Args) const {
+ StringRef RuntimeName(CLANG_DEFAULT_OPENMP_RUNTIME);
+
+ const Arg *A = Args.getLastArg(options::OPT_fopenmp_EQ);
+ if (A)
+ RuntimeName = A->getValue();
+
+ auto RT = llvm::StringSwitch<OpenMPRuntimeKind>(RuntimeName)
+ .Case("libomp", OMPRT_OMP)
+ .Case("libgomp", OMPRT_GOMP)
+ .Case("libiomp5", OMPRT_IOMP5)
+ .Default(OMPRT_Unknown);
+
+ if (RT == OMPRT_Unknown) {
+ if (A)
+ Diag(diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << A->getValue();
+ else
+ // FIXME: We could use a nicer diagnostic here.
+ Diag(diag::err_drv_unsupported_opt) << "-fopenmp";
+ }
+
+ return RT;
+}
+
void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
InputList &Inputs) {
@@ -433,14 +473,71 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
if (llvm::any_of(Inputs, [](std::pair<types::ID, const llvm::opt::Arg *> &I) {
return types::isCuda(I.first);
})) {
- const ToolChain &TC = getToolChain(
- C.getInputArgs(),
- llvm::Triple(C.getSingleOffloadToolChain<Action::OFK_Host>()
- ->getTriple()
- .isArch64Bit()
- ? "nvptx64-nvidia-cuda"
- : "nvptx-nvidia-cuda"));
- C.addOffloadDeviceToolChain(&TC, Action::OFK_Cuda);
+ 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.
+ ToolChain *&CudaTC = ToolChains[CudaTriple.str() + "/" + HostTriple.str()];
+ if (!CudaTC) {
+ CudaTC = new toolchains::CudaToolChain(*this, CudaTriple, *HostTC,
+ C.getInputArgs());
+ }
+ C.addOffloadDeviceToolChain(CudaTC, Action::OFK_Cuda);
+ }
+
+ //
+ // OpenMP
+ //
+ // We need to generate an OpenMP toolchain if the user specified targets with
+ // the -fopenmp-targets option.
+ if (Arg *OpenMPTargets =
+ C.getInputArgs().getLastArg(options::OPT_fopenmp_targets_EQ)) {
+ if (OpenMPTargets->getNumValues()) {
+ // We expect that -fopenmp-targets is always used in conjunction with the
+ // option -fopenmp specifying a valid runtime with offloading support,
+ // i.e. libomp or libiomp.
+ bool HasValidOpenMPRuntime = C.getInputArgs().hasFlag(
+ options::OPT_fopenmp, options::OPT_fopenmp_EQ,
+ options::OPT_fno_openmp, false);
+ if (HasValidOpenMPRuntime) {
+ OpenMPRuntimeKind OpenMPKind = getOpenMPRuntime(C.getInputArgs());
+ HasValidOpenMPRuntime =
+ OpenMPKind == OMPRT_OMP || OpenMPKind == OMPRT_IOMP5;
+ }
+
+ if (HasValidOpenMPRuntime) {
+ llvm::StringMap<const char *> FoundNormalizedTriples;
+ for (const char *Val : OpenMPTargets->getValues()) {
+ llvm::Triple TT(Val);
+ std::string NormalizedName = TT.normalize();
+
+ // Make sure we don't have a duplicate triple.
+ auto Duplicate = FoundNormalizedTriples.find(NormalizedName);
+ if (Duplicate != FoundNormalizedTriples.end()) {
+ Diag(clang::diag::warn_drv_omp_offload_target_duplicate)
+ << Val << Duplicate->second;
+ continue;
+ }
+
+ // Store the current triple so that we can check for duplicates in the
+ // following iterations.
+ FoundNormalizedTriples[NormalizedName] = Val;
+
+ // If the specified target is invalid, emit a diagnostic.
+ if (TT.getArch() == llvm::Triple::UnknownArch)
+ Diag(clang::diag::err_drv_invalid_omp_target) << Val;
+ else {
+ const ToolChain &TC = getToolChain(C.getInputArgs(), TT);
+ C.addOffloadDeviceToolChain(&TC, Action::OFK_OpenMP);
+ }
+ }
+ } else
+ Diag(clang::diag::err_drv_expecting_fopenmp_with_fopenmp_targets);
+ } else
+ Diag(clang::diag::warn_drv_empty_joined_argument)
+ << OpenMPTargets->getAsString(C.getInputArgs());
}
//
@@ -456,8 +553,9 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
// FIXME: Handle environment options which affect driver behavior, somewhere
// (client?). GCC_EXEC_PREFIX, LPATH, CC_PRINT_OPTIONS.
- if (char *env = ::getenv("COMPILER_PATH")) {
- StringRef CompilerPath = env;
+ if (Optional<std::string> CompilerPathValue =
+ llvm::sys::Process::GetEnv("COMPILER_PATH")) {
+ StringRef CompilerPath = *CompilerPathValue;
while (!CompilerPath.empty()) {
std::pair<StringRef, StringRef> Split =
CompilerPath.split(llvm::sys::EnvPathSeparator);
@@ -468,7 +566,7 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
// We look for the driver mode option early, because the mode can affect
// how other options are parsed.
- ParseDriverMode(ArgList.slice(1));
+ ParseDriverMode(ClangExecutable, ArgList.slice(1));
// FIXME: What are we going to do with -V and -b?
@@ -535,26 +633,20 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
setLTOMode(Args);
- // Ignore -fembed-bitcode options with LTO
- // since the output will be bitcode anyway.
- if (getLTOMode() == LTOK_None) {
- if (Arg *A = Args.getLastArg(options::OPT_fembed_bitcode_EQ)) {
- StringRef Name = A->getValue();
- unsigned Model = llvm::StringSwitch<unsigned>(Name)
- .Case("off", EmbedNone)
- .Case("all", EmbedBitcode)
- .Case("bitcode", EmbedBitcode)
- .Case("marker", EmbedMarker)
- .Default(~0U);
- if (Model == ~0U) {
- Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args)
- << Name;
- } else
- BitcodeEmbed = static_cast<BitcodeEmbedMode>(Model);
- }
- } else {
- // claim the bitcode option under LTO so no warning is issued.
- Args.ClaimAllArgs(options::OPT_fembed_bitcode_EQ);
+ // Process -fembed-bitcode= flags.
+ if (Arg *A = Args.getLastArg(options::OPT_fembed_bitcode_EQ)) {
+ StringRef Name = A->getValue();
+ unsigned Model = llvm::StringSwitch<unsigned>(Name)
+ .Case("off", EmbedNone)
+ .Case("all", EmbedBitcode)
+ .Case("bitcode", EmbedBitcode)
+ .Case("marker", EmbedMarker)
+ .Default(~0U);
+ if (Model == ~0U) {
+ Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args)
+ << Name;
+ } else
+ BitcodeEmbed = static_cast<BitcodeEmbedMode>(Model);
}
std::unique_ptr<llvm::opt::InputArgList> UArgs =
@@ -610,6 +702,95 @@ static void printArgList(raw_ostream &OS, const llvm::opt::ArgList &Args) {
OS << '\n';
}
+bool Driver::getCrashDiagnosticFile(StringRef ReproCrashFilename,
+ SmallString<128> &CrashDiagDir) {
+ using namespace llvm::sys;
+ assert(llvm::Triple(llvm::sys::getProcessTriple()).isOSDarwin() &&
+ "Only knows about .crash files on Darwin");
+
+ // The .crash file can be found on at ~/Library/Logs/DiagnosticReports/
+ // (or /Library/Logs/DiagnosticReports for root) and has the filename pattern
+ // clang-<VERSION>_<YYYY-MM-DD-HHMMSS>_<hostname>.crash.
+ path::home_directory(CrashDiagDir);
+ if (CrashDiagDir.startswith("/var/root"))
+ CrashDiagDir = "/";
+ path::append(CrashDiagDir, "Library/Logs/DiagnosticReports");
+ int PID =
+#if LLVM_ON_UNIX
+ getpid();
+#else
+ 0;
+#endif
+ std::error_code EC;
+ fs::file_status FileStatus;
+ TimePoint<> LastAccessTime;
+ SmallString<128> CrashFilePath;
+ // Lookup the .crash files and get the one generated by a subprocess spawned
+ // by this driver invocation.
+ for (fs::directory_iterator File(CrashDiagDir, EC), FileEnd;
+ File != FileEnd && !EC; File.increment(EC)) {
+ StringRef FileName = path::filename(File->path());
+ if (!FileName.startswith(Name))
+ continue;
+ if (fs::status(File->path(), FileStatus))
+ continue;
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> CrashFile =
+ llvm::MemoryBuffer::getFile(File->path());
+ if (!CrashFile)
+ continue;
+ // The first line should start with "Process:", otherwise this isn't a real
+ // .crash file.
+ StringRef Data = CrashFile.get()->getBuffer();
+ if (!Data.startswith("Process:"))
+ continue;
+ // Parse parent process pid line, e.g: "Parent Process: clang-4.0 [79141]"
+ size_t ParentProcPos = Data.find("Parent Process:");
+ if (ParentProcPos == StringRef::npos)
+ continue;
+ size_t LineEnd = Data.find_first_of("\n", ParentProcPos);
+ if (LineEnd == StringRef::npos)
+ continue;
+ StringRef ParentProcess = Data.slice(ParentProcPos+15, LineEnd).trim();
+ int OpenBracket = -1, CloseBracket = -1;
+ for (size_t i = 0, e = ParentProcess.size(); i < e; ++i) {
+ if (ParentProcess[i] == '[')
+ OpenBracket = i;
+ if (ParentProcess[i] == ']')
+ CloseBracket = i;
+ }
+ // Extract the parent process PID from the .crash file and check whether
+ // it matches this driver invocation pid.
+ int CrashPID;
+ if (OpenBracket < 0 || CloseBracket < 0 ||
+ ParentProcess.slice(OpenBracket + 1, CloseBracket)
+ .getAsInteger(10, CrashPID) || CrashPID != PID) {
+ continue;
+ }
+
+ // Found a .crash file matching the driver pid. To avoid getting an older
+ // and misleading crash file, continue looking for the most recent.
+ // FIXME: the driver can dispatch multiple cc1 invocations, leading to
+ // multiple crashes poiting to the same parent process. Since the driver
+ // does not collect pid information for the dispatched invocation there's
+ // currently no way to distinguish among them.
+ const auto FileAccessTime = FileStatus.getLastModificationTime();
+ if (FileAccessTime > LastAccessTime) {
+ CrashFilePath.assign(File->path());
+ LastAccessTime = FileAccessTime;
+ }
+ }
+
+ // If found, copy it over to the location of other reproducer files.
+ if (!CrashFilePath.empty()) {
+ EC = fs::copy_file(CrashFilePath, ReproCrashFilename);
+ if (EC)
+ return false;
+ return true;
+ }
+
+ return false;
+}
+
// 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.
@@ -737,8 +918,13 @@ void Driver::generateCompilationDiagnostics(Compilation &C,
"Preprocessed source(s) and associated run script(s) are located at:";
SmallString<128> VFS;
+ SmallString<128> ReproCrashFilename;
for (const char *TempFile : TempFiles) {
Diag(clang::diag::note_drv_command_failed_diag_msg) << TempFile;
+ if (ReproCrashFilename.empty()) {
+ ReproCrashFilename = TempFile;
+ llvm::sys::path::replace_extension(ReproCrashFilename, ".crash");
+ }
if (StringRef(TempFile).endswith(".cache")) {
// In some cases (modules) we'll dump extra data to help with reproducing
// the crash into a directory next to the output.
@@ -766,6 +952,24 @@ void Driver::generateCompilationDiagnostics(Compilation &C,
Diag(clang::diag::note_drv_command_failed_diag_msg) << Script;
}
+ // On darwin, provide information about the .crash diagnostic report.
+ if (llvm::Triple(llvm::sys::getProcessTriple()).isOSDarwin()) {
+ SmallString<128> CrashDiagDir;
+ if (getCrashDiagnosticFile(ReproCrashFilename, CrashDiagDir)) {
+ Diag(clang::diag::note_drv_command_failed_diag_msg)
+ << ReproCrashFilename.str();
+ } else { // Suggest a directory for the user to look for .crash files.
+ llvm::sys::path::append(CrashDiagDir, Name);
+ CrashDiagDir += "_<YYYY-MM-DD-HHMMSS>_<hostname>.crash";
+ Diag(clang::diag::note_drv_command_failed_diag_msg)
+ << "Crash backtrace is located in";
+ Diag(clang::diag::note_drv_command_failed_diag_msg)
+ << CrashDiagDir.str();
+ Diag(clang::diag::note_drv_command_failed_diag_msg)
+ << "(choose the .crash file that corresponds to your crash)";
+ }
+ }
+
for (const auto &A : C.getArgs().filtered(options::OPT_frewrite_map_file,
options::OPT_frewrite_map_file_EQ))
Diag(clang::diag::note_drv_command_failed_diag_msg) << A->getValue();
@@ -783,8 +987,7 @@ void Driver::setUpResponseFiles(Compilation &C, Command &Cmd) {
return;
std::string TmpName = GetTemporaryPath("response", "txt");
- Cmd.setResponseFile(
- C.addTempFile(C.getArgs().MakeArgString(TmpName.c_str())));
+ Cmd.setResponseFile(C.addTempFile(C.getArgs().MakeArgString(TmpName)));
}
int Driver::ExecuteCompilation(
@@ -982,7 +1185,15 @@ bool Driver::HandleImmediateArgs(const Compilation &C) {
}
if (C.getArgs().hasArg(options::OPT_print_libgcc_file_name)) {
- llvm::outs() << GetFilePath("libgcc.a", TC) << "\n";
+ ToolChain::RuntimeLibType RLT = TC.GetRuntimeLibType(C.getArgs());
+ switch (RLT) {
+ case ToolChain::RLT_CompilerRT:
+ llvm::outs() << TC.getCompilerRT(C.getArgs(), "builtins") << "\n";
+ break;
+ case ToolChain::RLT_Libgcc:
+ llvm::outs() << GetFilePath("libgcc.a", TC) << "\n";
+ break;
+ }
return false;
}
@@ -1388,132 +1599,745 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args,
}
}
-// For each unique --cuda-gpu-arch= argument creates a TY_CUDA_DEVICE
-// input action and then wraps each in CudaDeviceAction paired with
-// appropriate GPU arch name. In case of partial (i.e preprocessing
-// only) or device-only compilation, each device action is added to /p
-// Actions and /p Current is released. Otherwise the function creates
-// and returns a new CudaHostAction which wraps /p Current and device
-// side actions.
-static Action *buildCudaActions(Compilation &C, DerivedArgList &Args,
- const Arg *InputArg, Action *HostAction,
- ActionList &Actions) {
- Arg *PartialCompilationArg = Args.getLastArg(
- options::OPT_cuda_host_only, options::OPT_cuda_device_only,
- options::OPT_cuda_compile_host_device);
- bool CompileHostOnly =
- PartialCompilationArg &&
- PartialCompilationArg->getOption().matches(options::OPT_cuda_host_only);
- bool CompileDeviceOnly =
- PartialCompilationArg &&
- PartialCompilationArg->getOption().matches(options::OPT_cuda_device_only);
-
- if (CompileHostOnly) {
+namespace {
+/// Provides a convenient interface for different programming models to generate
+/// the required device actions.
+class OffloadingActionBuilder final {
+ /// Flag used to trace errors in the builder.
+ bool IsValid = false;
+
+ /// The compilation that is using this builder.
+ Compilation &C;
+
+ /// Map between an input argument and the offload kinds used to process it.
+ std::map<const Arg *, unsigned> InputArgToOffloadKindMap;
+
+ /// Builder interface. It doesn't build anything or keep any state.
+ class DeviceActionBuilder {
+ public:
+ typedef llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> PhasesTy;
+
+ enum ActionBuilderReturnCode {
+ // The builder acted successfully on the current action.
+ ABRT_Success,
+ // The builder didn't have to act on the current action.
+ ABRT_Inactive,
+ // The builder was successful and requested the host action to not be
+ // generated.
+ ABRT_Ignore_Host,
+ };
+
+ protected:
+ /// Compilation associated with this builder.
+ Compilation &C;
+
+ /// Tool chains associated with this builder. The same programming
+ /// model may have associated one or more tool chains.
+ SmallVector<const ToolChain *, 2> ToolChains;
+
+ /// The derived arguments associated with this builder.
+ DerivedArgList &Args;
+
+ /// The inputs associated with this builder.
+ const Driver::InputList &Inputs;
+
+ /// The associated offload kind.
+ Action::OffloadKind AssociatedOffloadKind = Action::OFK_None;
+
+ public:
+ DeviceActionBuilder(Compilation &C, DerivedArgList &Args,
+ const Driver::InputList &Inputs,
+ Action::OffloadKind AssociatedOffloadKind)
+ : C(C), Args(Args), Inputs(Inputs),
+ AssociatedOffloadKind(AssociatedOffloadKind) {}
+ virtual ~DeviceActionBuilder() {}
+
+ /// Fill up the array \a DA with all the device dependences that should be
+ /// added to the provided host action \a HostAction. By default it is
+ /// inactive.
+ virtual ActionBuilderReturnCode
+ getDeviceDependences(OffloadAction::DeviceDependences &DA,
+ phases::ID CurPhase, phases::ID FinalPhase,
+ PhasesTy &Phases) {
+ return ABRT_Inactive;
+ }
+
+ /// Update the state to include the provided host action \a HostAction as a
+ /// dependency of the current device action. By default it is inactive.
+ virtual ActionBuilderReturnCode addDeviceDepences(Action *HostAction) {
+ return ABRT_Inactive;
+ }
+
+ /// Append top level actions generated by the builder. Return true if errors
+ /// were found.
+ virtual void appendTopLevelActions(ActionList &AL) {}
+
+ /// Append linker actions generated by the builder. Return true if errors
+ /// were found.
+ virtual void appendLinkDependences(OffloadAction::DeviceDependences &DA) {}
+
+ /// Initialize the builder. Return true if any initialization errors are
+ /// found.
+ virtual bool initialize() { return false; }
+
+ /// Return true if the builder can use bundling/unbundling.
+ virtual bool canUseBundlerUnbundler() const { return false; }
+
+ /// Return true if this builder is valid. We have a valid builder if we have
+ /// associated device tool chains.
+ bool isValid() { return !ToolChains.empty(); }
+
+ /// Return the associated offload kind.
+ Action::OffloadKind getAssociatedOffloadKind() {
+ return AssociatedOffloadKind;
+ }
+ };
+
+ /// \brief CUDA action builder. It injects device code in the host backend
+ /// action.
+ class CudaActionBuilder final : public DeviceActionBuilder {
+ /// Flags to signal if the user requested host-only or device-only
+ /// compilation.
+ bool CompileHostOnly = false;
+ bool CompileDeviceOnly = false;
+
+ /// List of GPU architectures to use in this compilation.
+ SmallVector<CudaArch, 4> GpuArchList;
+
+ /// The CUDA actions for the current input.
+ ActionList CudaDeviceActions;
+
+ /// The CUDA fat binary if it was generated for the current input.
+ Action *CudaFatBinary = nullptr;
+
+ /// 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;
+ }
+
+ ActionBuilderReturnCode addDeviceDepences(Action *HostAction) override {
+ // While generating code for CUDA, we only depend on the host input action
+ // to trigger the creation of all the CUDA device actions.
+
+ // If we are dealing with an input action, replicate it for each GPU
+ // architecture. If we are in host-only mode we return 'success' so that
+ // the host uses the CUDA offload kind.
+ if (auto *IA = dyn_cast<InputAction>(HostAction)) {
+ 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) {
+ // The builder will ignore this input.
+ IsActive = false;
+ return ABRT_Inactive;
+ }
+
+ // Set the flag to true, so that the builder acts on the current input.
+ IsActive = true;
+
+ if (CompileHostOnly)
+ 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));
+
+ return ABRT_Success;
+ }
+
+ return IsActive ? ABRT_Success : ABRT_Inactive;
+ }
+
+ void appendTopLevelActions(ActionList &AL) override {
+ // Utility to append actions to the top level list.
+ auto AddTopLevel = [&](Action *A, CudaArch BoundArch) {
+ OffloadAction::DeviceDependences Dep;
+ Dep.add(*A, *ToolChains.front(), CudaArchToString(BoundArch),
+ Action::OFK_Cuda);
+ AL.push_back(C.MakeAction<OffloadAction>(Dep, A->getType()));
+ };
+
+ // If we have a fat binary, add it to the list.
+ if (CudaFatBinary) {
+ AddTopLevel(CudaFatBinary, CudaArch::UNKNOWN);
+ CudaDeviceActions.clear();
+ CudaFatBinary = nullptr;
+ return;
+ }
+
+ if (CudaDeviceActions.empty())
+ return;
+
+ // If we have CUDA actions at this point, that's because we have a have
+ // partial compilation, so we should have an action for each GPU
+ // architecture.
+ assert(CudaDeviceActions.size() == GpuArchList.size() &&
+ "Expecting one action per GPU architecture.");
+ assert(ToolChains.size() == 1 &&
+ "Expecting to have a sing CUDA toolchain.");
+ for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I)
+ AddTopLevel(CudaDeviceActions[I], GpuArchList[I]);
+
+ CudaDeviceActions.clear();
+ }
+
+ bool initialize() override {
+ // We don't need to support CUDA.
+ if (!C.hasOffloadToolChain<Action::OFK_Cuda>())
+ 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
+ // 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);
+ return true;
+ }
+
+ ToolChains.push_back(C.getSingleOffloadToolChain<Action::OFK_Cuda>());
+
+ Arg *PartialCompilationArg = Args.getLastArg(
+ options::OPT_cuda_host_only, options::OPT_cuda_device_only,
+ options::OPT_cuda_compile_host_device);
+ CompileHostOnly = PartialCompilationArg &&
+ PartialCompilationArg->getOption().matches(
+ options::OPT_cuda_host_only);
+ CompileDeviceOnly = PartialCompilationArg &&
+ PartialCompilationArg->getOption().matches(
+ options::OPT_cuda_device_only);
+
+ // Collect all cuda_gpu_arch parameters, removing duplicates.
+ std::set<CudaArch> GpuArchs;
+ bool Error = false;
+ for (Arg *A : Args) {
+ if (!(A->getOption().matches(options::OPT_cuda_gpu_arch_EQ) ||
+ A->getOption().matches(options::OPT_no_cuda_gpu_arch_EQ)))
+ continue;
+ A->claim();
+
+ const StringRef ArchStr = A->getValue();
+ if (A->getOption().matches(options::OPT_no_cuda_gpu_arch_EQ) &&
+ ArchStr == "all") {
+ GpuArchs.clear();
+ continue;
+ }
+ CudaArch Arch = StringToCudaArch(ArchStr);
+ if (Arch == CudaArch::UNKNOWN) {
+ C.getDriver().Diag(clang::diag::err_drv_cuda_bad_gpu_arch) << ArchStr;
+ Error = true;
+ } else if (A->getOption().matches(options::OPT_cuda_gpu_arch_EQ))
+ GpuArchs.insert(Arch);
+ else if (A->getOption().matches(options::OPT_no_cuda_gpu_arch_EQ))
+ GpuArchs.erase(Arch);
+ else
+ llvm_unreachable("Unexpected option.");
+ }
+
+ // Collect list of GPUs remaining in the set.
+ for (CudaArch Arch : GpuArchs)
+ GpuArchList.push_back(Arch);
+
+ // Default to sm_20 which is the lowest common denominator for
+ // supported GPUs. sm_20 code should work correctly, if
+ // suboptimally, on all newer GPUs.
+ if (GpuArchList.empty())
+ GpuArchList.push_back(CudaArch::SM_20);
+
+ return Error;
+ }
+ };
+
+ /// 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 {
+ /// The OpenMP actions for the current input.
+ ActionList OpenMPDeviceActions;
+
+ /// The linker inputs obtained for each toolchain.
+ SmallVector<ActionList, 8> DeviceLinkerInputs;
+
+ public:
+ OpenMPActionBuilder(Compilation &C, DerivedArgList &Args,
+ const Driver::InputList &Inputs)
+ : DeviceActionBuilder(C, Args, Inputs, Action::OFK_OpenMP) {}
+
+ ActionBuilderReturnCode
+ getDeviceDependences(OffloadAction::DeviceDependences &DA,
+ phases::ID CurPhase, phases::ID FinalPhase,
+ PhasesTy &Phases) override {
+
+ // We should always have an action for each input.
+ assert(OpenMPDeviceActions.size() == ToolChains.size() &&
+ "Number of OpenMP actions and toolchains do not match.");
+
+ // The host only depends on device action in the linking phase, when all
+ // the device images have to be embedded in the host image.
+ if (CurPhase == phases::Link) {
+ assert(ToolChains.size() == DeviceLinkerInputs.size() &&
+ "Toolchains and linker inputs sizes do not match.");
+ auto LI = DeviceLinkerInputs.begin();
+ for (auto *A : OpenMPDeviceActions) {
+ LI->push_back(A);
+ ++LI;
+ }
+
+ // We passed the device action as a host dependence, so we don't need to
+ // do anything else with them.
+ OpenMPDeviceActions.clear();
+ return ABRT_Success;
+ }
+
+ // By default, we produce an action for each device arch.
+ for (Action *&A : OpenMPDeviceActions)
+ A = C.getDriver().ConstructPhaseAction(C, Args, CurPhase, A);
+
+ return ABRT_Success;
+ }
+
+ ActionBuilderReturnCode addDeviceDepences(Action *HostAction) override {
+
+ // If this is an input action replicate it for each OpenMP toolchain.
+ if (auto *IA = dyn_cast<InputAction>(HostAction)) {
+ OpenMPDeviceActions.clear();
+ for (unsigned I = 0; I < ToolChains.size(); ++I)
+ OpenMPDeviceActions.push_back(
+ C.MakeAction<InputAction>(IA->getInputArg(), IA->getType()));
+ return ABRT_Success;
+ }
+
+ // If this is an unbundling action use it as is for each OpenMP toolchain.
+ if (auto *UA = dyn_cast<OffloadUnbundlingJobAction>(HostAction)) {
+ OpenMPDeviceActions.clear();
+ for (unsigned I = 0; I < ToolChains.size(); ++I) {
+ OpenMPDeviceActions.push_back(UA);
+ UA->registerDependentActionInfo(
+ ToolChains[I], /*BoundArch=*/StringRef(), Action::OFK_OpenMP);
+ }
+ return ABRT_Success;
+ }
+
+ // When generating code for OpenMP we use the host compile phase result as
+ // a dependence to the device compile phase so that it can learn what
+ // declarations should be emitted. However, this is not the only use for
+ // the host action, so we prevent it from being collapsed.
+ if (isa<CompileJobAction>(HostAction)) {
+ HostAction->setCannotBeCollapsedWithNextDependentAction();
+ assert(ToolChains.size() == OpenMPDeviceActions.size() &&
+ "Toolchains and device action sizes do not match.");
+ OffloadAction::HostDependence HDep(
+ *HostAction, *C.getSingleOffloadToolChain<Action::OFK_Host>(),
+ /*BoundArch=*/nullptr, Action::OFK_OpenMP);
+ auto TC = ToolChains.begin();
+ for (Action *&A : OpenMPDeviceActions) {
+ assert(isa<CompileJobAction>(A));
+ OffloadAction::DeviceDependences DDep;
+ DDep.add(*A, **TC, /*BoundArch=*/nullptr, Action::OFK_OpenMP);
+ A = C.MakeAction<OffloadAction>(HDep, DDep);
+ ++TC;
+ }
+ }
+ return ABRT_Success;
+ }
+
+ void appendTopLevelActions(ActionList &AL) override {
+ if (OpenMPDeviceActions.empty())
+ return;
+
+ // We should always have an action for each input.
+ assert(OpenMPDeviceActions.size() == ToolChains.size() &&
+ "Number of OpenMP actions and toolchains do not match.");
+
+ // Append all device actions followed by the proper offload action.
+ auto TI = ToolChains.begin();
+ for (auto *A : OpenMPDeviceActions) {
+ OffloadAction::DeviceDependences Dep;
+ Dep.add(*A, **TI, /*BoundArch=*/nullptr, Action::OFK_OpenMP);
+ AL.push_back(C.MakeAction<OffloadAction>(Dep, A->getType()));
+ ++TI;
+ }
+ // We no longer need the action stored in this builder.
+ OpenMPDeviceActions.clear();
+ }
+
+ void appendLinkDependences(OffloadAction::DeviceDependences &DA) override {
+ assert(ToolChains.size() == DeviceLinkerInputs.size() &&
+ "Toolchains and linker inputs sizes do not match.");
+
+ // Append a new link action for each device.
+ auto TC = ToolChains.begin();
+ for (auto &LI : DeviceLinkerInputs) {
+ auto *DeviceLinkAction =
+ C.MakeAction<LinkJobAction>(LI, types::TY_Image);
+ DA.add(*DeviceLinkAction, **TC, /*BoundArch=*/nullptr,
+ Action::OFK_OpenMP);
+ ++TC;
+ }
+ }
+
+ bool initialize() override {
+ // Get the OpenMP toolchains. If we don't get any, the action builder will
+ // know there is nothing to do related to OpenMP offloading.
+ auto OpenMPTCRange = C.getOffloadToolChains<Action::OFK_OpenMP>();
+ for (auto TI = OpenMPTCRange.first, TE = OpenMPTCRange.second; TI != TE;
+ ++TI)
+ ToolChains.push_back(TI->second);
+
+ DeviceLinkerInputs.resize(ToolChains.size());
+ return false;
+ }
+
+ bool canUseBundlerUnbundler() const override {
+ // OpenMP should use bundled files whenever possible.
+ return true;
+ }
+ };
+
+ ///
+ /// TODO: Add the implementation for other specialized builders here.
+ ///
+
+ /// Specialized builders being used by this offloading action builder.
+ SmallVector<DeviceActionBuilder *, 4> SpecializedBuilders;
+
+ /// Flag set to true if all valid builders allow file bundling/unbundling.
+ bool CanUseBundler;
+
+public:
+ OffloadingActionBuilder(Compilation &C, DerivedArgList &Args,
+ const Driver::InputList &Inputs)
+ : C(C) {
+ // Create a specialized builder for each device toolchain.
+
+ IsValid = true;
+
+ // Create a specialized builder for CUDA.
+ SpecializedBuilders.push_back(new CudaActionBuilder(C, Args, Inputs));
+
+ // Create a specialized builder for OpenMP.
+ SpecializedBuilders.push_back(new OpenMPActionBuilder(C, Args, Inputs));
+
+ //
+ // TODO: Build other specialized builders here.
+ //
+
+ // Initialize all the builders, keeping track of errors. If all valid
+ // builders agree that we can use bundling, set the flag to true.
+ unsigned ValidBuilders = 0u;
+ unsigned ValidBuildersSupportingBundling = 0u;
+ for (auto *SB : SpecializedBuilders) {
+ IsValid = IsValid && !SB->initialize();
+
+ // Update the counters if the builder is valid.
+ if (SB->isValid()) {
+ ++ValidBuilders;
+ if (SB->canUseBundlerUnbundler())
+ ++ValidBuildersSupportingBundling;
+ }
+ }
+ CanUseBundler =
+ ValidBuilders && ValidBuilders == ValidBuildersSupportingBundling;
+ }
+
+ ~OffloadingActionBuilder() {
+ for (auto *SB : SpecializedBuilders)
+ delete SB;
+ }
+
+ /// Generate an action that adds device dependences (if any) to a host action.
+ /// If no device dependence actions exist, just return the host action \a
+ /// HostAction. If an error is found or if no builder requires the host action
+ /// to be generated, return nullptr.
+ Action *
+ addDeviceDependencesToHostAction(Action *HostAction, const Arg *InputArg,
+ phases::ID CurPhase, phases::ID FinalPhase,
+ DeviceActionBuilder::PhasesTy &Phases) {
+ if (!IsValid)
+ return nullptr;
+
+ if (SpecializedBuilders.empty())
+ return HostAction;
+
+ assert(HostAction && "Invalid host action!");
+
+ OffloadAction::DeviceDependences DDeps;
+ // Check if all the programming models agree we should not emit the host
+ // action. Also, keep track of the offloading kinds employed.
+ auto &OffloadKind = InputArgToOffloadKindMap[InputArg];
+ unsigned InactiveBuilders = 0u;
+ unsigned IgnoringBuilders = 0u;
+ for (auto *SB : SpecializedBuilders) {
+ if (!SB->isValid()) {
+ ++InactiveBuilders;
+ continue;
+ }
+
+ auto RetCode =
+ SB->getDeviceDependences(DDeps, CurPhase, FinalPhase, Phases);
+
+ // If the builder explicitly says the host action should be ignored,
+ // we need to increment the variable that tracks the builders that request
+ // the host object to be ignored.
+ if (RetCode == DeviceActionBuilder::ABRT_Ignore_Host)
+ ++IgnoringBuilders;
+
+ // Unless the builder was inactive for this action, we have to record the
+ // offload kind because the host will have to use it.
+ if (RetCode != DeviceActionBuilder::ABRT_Inactive)
+ OffloadKind |= SB->getAssociatedOffloadKind();
+ }
+
+ // If all builders agree that the host object should be ignored, just return
+ // nullptr.
+ if (IgnoringBuilders &&
+ SpecializedBuilders.size() == (InactiveBuilders + IgnoringBuilders))
+ return nullptr;
+
+ if (DDeps.getActions().empty())
+ return HostAction;
+
+ // We have dependences we need to bundle together. We use an offload action
+ // for that.
OffloadAction::HostDependence HDep(
*HostAction, *C.getSingleOffloadToolChain<Action::OFK_Host>(),
- /*BoundArch=*/nullptr, Action::OFK_Cuda);
- return C.MakeAction<OffloadAction>(HDep);
+ /*BoundArch=*/nullptr, DDeps);
+ return C.MakeAction<OffloadAction>(HDep, DDeps);
}
- // Collect all cuda_gpu_arch parameters, removing duplicates.
- SmallVector<CudaArch, 4> GpuArchList;
- llvm::SmallSet<CudaArch, 4> GpuArchs;
- for (Arg *A : Args) {
- if (!A->getOption().matches(options::OPT_cuda_gpu_arch_EQ))
- continue;
- A->claim();
+ /// Generate an action that adds a host dependence to a device action. The
+ /// results will be kept in this action builder. Return true if an error was
+ /// found.
+ bool addHostDependenceToDeviceActions(Action *&HostAction,
+ const Arg *InputArg) {
+ if (!IsValid)
+ return true;
- const auto &ArchStr = A->getValue();
- CudaArch Arch = StringToCudaArch(ArchStr);
- if (Arch == CudaArch::UNKNOWN)
- C.getDriver().Diag(clang::diag::err_drv_cuda_bad_gpu_arch) << ArchStr;
- else if (GpuArchs.insert(Arch).second)
- GpuArchList.push_back(Arch);
- }
-
- // Default to sm_20 which is the lowest common denominator for supported GPUs.
- // sm_20 code should work correctly, if suboptimally, on all newer GPUs.
- if (GpuArchList.empty())
- GpuArchList.push_back(CudaArch::SM_20);
-
- // Replicate inputs for each GPU architecture.
- Driver::InputList CudaDeviceInputs;
- for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I)
- CudaDeviceInputs.push_back(std::make_pair(types::TY_CUDA_DEVICE, InputArg));
-
- // Build actions for all device inputs.
- ActionList CudaDeviceActions;
- C.getDriver().BuildActions(C, Args, CudaDeviceInputs, CudaDeviceActions);
- assert(GpuArchList.size() == CudaDeviceActions.size() &&
- "Failed to create actions for all devices");
-
- // Check whether any of device actions stopped before they could generate PTX.
- bool PartialCompilation =
- llvm::any_of(CudaDeviceActions, [](const Action *a) {
- return a->getKind() != Action::AssembleJobClass;
- });
+ // If we are supporting bundling/unbundling and the current action is an
+ // input action of non-source file, we replace the host action by the
+ // unbundling action. The bundler tool has the logic to detect if an input
+ // is a bundle or not and if the input is not a bundle it assumes it is a
+ // host file. Therefore it is safe to create an unbundling action even if
+ // the input is not a bundle.
+ if (CanUseBundler && isa<InputAction>(HostAction) &&
+ InputArg->getOption().getKind() == llvm::opt::Option::InputClass &&
+ !types::isSrcFile(HostAction->getType())) {
+ auto UnbundlingHostAction =
+ C.MakeAction<OffloadUnbundlingJobAction>(HostAction);
+ UnbundlingHostAction->registerDependentActionInfo(
+ C.getSingleOffloadToolChain<Action::OFK_Host>(),
+ /*BoundArch=*/StringRef(), Action::OFK_Host);
+ HostAction = UnbundlingHostAction;
+ }
- const ToolChain *CudaTC = C.getSingleOffloadToolChain<Action::OFK_Cuda>();
+ assert(HostAction && "Invalid host action!");
- // Figure out what to do with device actions -- pass them as inputs to the
- // host action or run each of them independently.
- if (PartialCompilation || CompileDeviceOnly) {
- // In case of partial or device-only compilation results of device actions
- // are not consumed by the host action device actions have to be added to
- // top-level actions list with AtTopLevel=true and run independently.
+ // Register the offload kinds that are used.
+ auto &OffloadKind = InputArgToOffloadKindMap[InputArg];
+ for (auto *SB : SpecializedBuilders) {
+ if (!SB->isValid())
+ continue;
- // -o is ambiguous if we have more than one top-level action.
- if (Args.hasArg(options::OPT_o) &&
- (!CompileDeviceOnly || GpuArchList.size() > 1)) {
- C.getDriver().Diag(
- clang::diag::err_drv_output_argument_with_multiple_files);
- return nullptr;
+ auto RetCode = SB->addDeviceDepences(HostAction);
+
+ // Host dependences for device actions are not compatible with that same
+ // action being ignored.
+ assert(RetCode != DeviceActionBuilder::ABRT_Ignore_Host &&
+ "Host dependence not expected to be ignored.!");
+
+ // Unless the builder was inactive for this action, we have to record the
+ // offload kind because the host will have to use it.
+ if (RetCode != DeviceActionBuilder::ABRT_Inactive)
+ OffloadKind |= SB->getAssociatedOffloadKind();
}
- for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) {
- OffloadAction::DeviceDependences DDep;
- DDep.add(*CudaDeviceActions[I], *CudaTC, CudaArchToString(GpuArchList[I]),
- Action::OFK_Cuda);
- Actions.push_back(
- C.MakeAction<OffloadAction>(DDep, CudaDeviceActions[I]->getType()));
+ return false;
+ }
+
+ /// Add the offloading top level actions to the provided action list. This
+ /// function can replace the host action by a bundling action if the
+ /// programming models allow it.
+ bool appendTopLevelActions(ActionList &AL, Action *HostAction,
+ const Arg *InputArg) {
+ // Get the device actions to be appended.
+ ActionList OffloadAL;
+ for (auto *SB : SpecializedBuilders) {
+ if (!SB->isValid())
+ continue;
+ SB->appendTopLevelActions(OffloadAL);
}
- // Kill host action in case of device-only compilation.
- if (CompileDeviceOnly)
- return nullptr;
- return HostAction;
- }
-
- // If we're not a partial or device-only compilation, 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 compilation.
- ActionList DeviceActions;
- for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) {
- 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, *CudaTC, CudaArchToString(GpuArchList[I]), Action::OFK_Cuda);
- DeviceActions.push_back(C.MakeAction<OffloadAction>(DDep, A->getType()));
- }
- }
- auto FatbinAction =
- C.MakeAction<LinkJobAction>(DeviceActions, types::TY_CUDA_FATBIN);
-
- // Return a new host action that incorporates original host action and all
- // device actions.
- OffloadAction::HostDependence HDep(
- *HostAction, *C.getSingleOffloadToolChain<Action::OFK_Host>(),
- /*BoundArch=*/nullptr, Action::OFK_Cuda);
- OffloadAction::DeviceDependences DDep;
- DDep.add(*FatbinAction, *CudaTC, /*BoundArch=*/nullptr, Action::OFK_Cuda);
- return C.MakeAction<OffloadAction>(HDep, DDep);
-}
+
+ // If we can use the bundler, replace the host action by the bundling one in
+ // the resulting list. Otherwise, just append the device actions.
+ if (CanUseBundler && !OffloadAL.empty()) {
+ // Add the host action to the list in order to create the bundling action.
+ OffloadAL.push_back(HostAction);
+
+ // We expect that the host action was just appended to the action list
+ // before this method was called.
+ assert(HostAction == AL.back() && "Host action not in the list??");
+ HostAction = C.MakeAction<OffloadBundlingJobAction>(OffloadAL);
+ AL.back() = HostAction;
+ } else
+ AL.append(OffloadAL.begin(), OffloadAL.end());
+
+ // Propagate to the current host action (if any) the offload information
+ // associated with the current input.
+ if (HostAction)
+ HostAction->propagateHostOffloadInfo(InputArgToOffloadKindMap[InputArg],
+ /*BoundArch=*/nullptr);
+ return false;
+ }
+
+ /// Processes the host linker action. This currently consists of replacing it
+ /// with an offload action if there are device link objects and propagate to
+ /// the host action all the offload kinds used in the current compilation. The
+ /// resulting action is returned.
+ Action *processHostLinkAction(Action *HostAction) {
+ // Add all the dependences from the device linking actions.
+ OffloadAction::DeviceDependences DDeps;
+ for (auto *SB : SpecializedBuilders) {
+ if (!SB->isValid())
+ continue;
+
+ SB->appendLinkDependences(DDeps);
+ }
+
+ // Calculate all the offload kinds used in the current compilation.
+ unsigned ActiveOffloadKinds = 0u;
+ for (auto &I : InputArgToOffloadKindMap)
+ ActiveOffloadKinds |= I.second;
+
+ // If we don't have device dependencies, we don't have to create an offload
+ // action.
+ if (DDeps.getActions().empty()) {
+ // Propagate all the active kinds to host action. Given that it is a link
+ // action it is assumed to depend on all actions generated so far.
+ HostAction->propagateHostOffloadInfo(ActiveOffloadKinds,
+ /*BoundArch=*/nullptr);
+ return HostAction;
+ }
+
+ // Create the offload action with all dependences. When an offload action
+ // is created the kinds are propagated to the host action, so we don't have
+ // to do that explicitly here.
+ OffloadAction::HostDependence HDep(
+ *HostAction, *C.getSingleOffloadToolChain<Action::OFK_Host>(),
+ /*BoundArch*/ nullptr, ActiveOffloadKinds);
+ return C.MakeAction<OffloadAction>(HDep, DDeps);
+ }
+};
+} // anonymous namespace.
void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
const InputList &Inputs, ActionList &Actions) const {
@@ -1621,8 +2445,8 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
YcArg = YuArg = nullptr;
}
- // Track the host offload kinds used on this compilation.
- unsigned CompilationActiveOffloadHostKinds = 0u;
+ // Builder to be used to build offloading actions.
+ OffloadingActionBuilder OffloadBuilder(C, Args, Inputs);
// Construct the actions to perform.
ActionList LinkerInputs;
@@ -1670,12 +2494,14 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
if (YcArg) {
// Add a separate precompile phase for the compile phase.
if (FinalPhase >= phases::Compile) {
+ const types::ID HeaderType = lookupHeaderTypeForSourceType(InputType);
llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> PCHPL;
- types::getCompilationPhases(types::TY_CXXHeader, 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, InputType);
+ Action *ClangClPch =
+ C.MakeAction<InputAction>(*PchInputArg, HeaderType);
for (phases::ID Phase : PCHPL)
ClangClPch = ConstructPhaseAction(C, Args, Phase, ClangClPch);
assert(ClangClPch);
@@ -1686,17 +2512,14 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
}
}
- phases::ID CudaInjectionPhase =
- (phases::Compile < FinalPhase &&
- llvm::find(PL, phases::Compile) != PL.end())
- ? phases::Compile
- : FinalPhase;
-
- // Track the host offload kinds used on this input.
- unsigned InputActiveOffloadHostKinds = 0u;
-
// Build the pipeline for this file.
Action *Current = C.MakeAction<InputAction>(*InputArg, InputType);
+
+ // Use the current host action in any of the offloading actions, if
+ // required.
+ if (OffloadBuilder.addHostDependenceToDeviceActions(Current, InputArg))
+ break;
+
for (SmallVectorImpl<phases::ID>::iterator i = PL.begin(), e = PL.end();
i != e; ++i) {
phases::ID Phase = *i;
@@ -1705,6 +2528,12 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
if (Phase > FinalPhase)
break;
+ // Add any offload action the host action depends on.
+ Current = OffloadBuilder.addDeviceDependencesToHostAction(
+ Current, InputArg, Phase, FinalPhase, PL);
+ if (!Current)
+ break;
+
// Queue linker inputs.
if (Phase == phases::Link) {
assert((i + 1) == e && "linking must be final compilation step.");
@@ -1713,48 +2542,37 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
break;
}
- // Some types skip the assembler phase (e.g., llvm-bc), but we can't
- // encode this in the steps because the intermediate type depends on
- // arguments. Just special case here.
- if (Phase == phases::Assemble && Current->getType() != types::TY_PP_Asm)
- continue;
-
// Otherwise construct the appropriate action.
- Current = ConstructPhaseAction(C, Args, Phase, Current);
+ auto *NewCurrent = ConstructPhaseAction(C, Args, Phase, Current);
- if (InputType == types::TY_CUDA && Phase == CudaInjectionPhase) {
- Current = buildCudaActions(C, Args, InputArg, Current, Actions);
- if (!Current)
- break;
+ // We didn't create a new action, so we will just move to the next phase.
+ if (NewCurrent == Current)
+ continue;
- // We produced a CUDA action for this input, so the host has to support
- // CUDA.
- InputActiveOffloadHostKinds |= Action::OFK_Cuda;
- CompilationActiveOffloadHostKinds |= Action::OFK_Cuda;
- }
+ Current = NewCurrent;
+
+ // Use the current host action in any of the offloading actions, if
+ // required.
+ if (OffloadBuilder.addHostDependenceToDeviceActions(Current, InputArg))
+ break;
if (Current->getType() == types::TY_Nothing)
break;
}
- // If we ended with something, add to the output list. Also, propagate the
- // offload information to the top-level host action related with the current
- // input.
- if (Current) {
- if (InputActiveOffloadHostKinds)
- Current->propagateHostOffloadInfo(InputActiveOffloadHostKinds,
- /*BoundArch=*/nullptr);
+ // If we ended with something, add to the output list.
+ if (Current)
Actions.push_back(Current);
- }
+
+ // Add any top level actions generated for offloading.
+ OffloadBuilder.appendTopLevelActions(Actions, Current, InputArg);
}
- // Add a link action if necessary and propagate the offload information for
- // the current compilation.
+ // Add a link action if necessary.
if (!LinkerInputs.empty()) {
- Actions.push_back(
- C.MakeAction<LinkJobAction>(LinkerInputs, types::TY_Image));
- Actions.back()->propagateHostOffloadInfo(CompilationActiveOffloadHostKinds,
- /*BoundArch=*/nullptr);
+ Action *LA = C.MakeAction<LinkJobAction>(LinkerInputs, types::TY_Image);
+ LA = OffloadBuilder.processHostLinkAction(LA);
+ Actions.push_back(LA);
}
// If we are linking, claim any options which are obviously only used for
@@ -1776,6 +2594,13 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
Action *Driver::ConstructPhaseAction(Compilation &C, const ArgList &Args,
phases::ID Phase, Action *Input) const {
llvm::PrettyStackTraceString CrashInfo("Constructing phase actions");
+
+ // Some types skip the assembler phase (e.g., llvm-bc), but we can't
+ // encode this in the steps because the intermediate type depends on
+ // arguments. Just special case here.
+ if (Phase == phases::Assemble && Input->getType() != types::TY_PP_Asm)
+ return Input;
+
// Build the appropriate action.
switch (Phase) {
case phases::Link:
@@ -1797,7 +2622,9 @@ Action *Driver::ConstructPhaseAction(Compilation &C, const ArgList &Args,
return C.MakeAction<PreprocessJobAction>(Input, OutputTy);
}
case phases::Precompile: {
- types::ID OutputTy = types::TY_PCH;
+ types::ID OutputTy = getPrecompiledType(Input->getType());
+ assert(OutputTy != types::TY_INVALID &&
+ "Cannot precompile this input type!");
if (Args.hasArg(options::OPT_fsyntax_only)) {
// Syntax checks should not emit a PCH file
OutputTy = types::TY_Nothing;
@@ -1888,11 +2715,11 @@ void Driver::BuildJobs(Compilation &C) const {
}
BuildJobsForAction(C, A, &C.getDefaultToolChain(),
- /*BoundArch*/ nullptr,
+ /*BoundArch*/ StringRef(),
/*AtTopLevel*/ true,
/*MultipleArchs*/ ArchNames.size() > 1,
/*LinkingOutput*/ LinkingOutput, CachedResults,
- /*BuildForOffloadDevice*/ false);
+ /*TargetDeviceOffloadKind*/ Action::OFK_None);
}
// If the user passed -Qunused-arguments or there were errors, don't warn
@@ -1941,177 +2768,335 @@ void Driver::BuildJobs(Compilation &C) const {
}
}
}
-/// Collapse an offloading action looking for a job of the given type. The input
-/// action is changed to the input of the collapsed sequence. If we effectively
-/// had a collapse return the corresponding offloading action, otherwise return
-/// null.
-template <typename T>
-static OffloadAction *collapseOffloadingAction(Action *&CurAction) {
- if (!CurAction)
- return nullptr;
- if (auto *OA = dyn_cast<OffloadAction>(CurAction)) {
- if (OA->hasHostDependence())
- if (auto *HDep = dyn_cast<T>(OA->getHostDependence())) {
- CurAction = HDep;
- return OA;
- }
- if (OA->hasSingleDeviceDependence())
- if (auto *DDep = dyn_cast<T>(OA->getSingleDeviceDependence())) {
- CurAction = DDep;
- return OA;
+
+namespace {
+/// Utility class to control the collapse of dependent actions and select the
+/// tools accordingly.
+class ToolSelector final {
+ /// The tool chain this selector refers to.
+ const ToolChain &TC;
+
+ /// The compilation this selector refers to.
+ const Compilation &C;
+
+ /// The base action this selector refers to.
+ const JobAction *BaseAction;
+
+ /// Set to true if the current toolchain refers to host actions.
+ bool IsHostSelector;
+
+ /// Set to true if save-temps and embed-bitcode functionalities are active.
+ bool SaveTemps;
+ bool EmbedBitcode;
+
+ /// Get previous dependent action or null if that does not exist. If
+ /// \a CanBeCollapsed is false, that action must be legal to collapse or
+ /// null will be returned.
+ const JobAction *getPrevDependentAction(const ActionList &Inputs,
+ ActionList &SavedOffloadAction,
+ bool CanBeCollapsed = true) {
+ // An option can be collapsed only if it has a single input.
+ if (Inputs.size() != 1)
+ return nullptr;
+
+ Action *CurAction = *Inputs.begin();
+ if (CanBeCollapsed &&
+ !CurAction->isCollapsingWithNextDependentActionLegal())
+ return nullptr;
+
+ // If the input action is an offload action. Look through it and save any
+ // offload action that can be dropped in the event of a collapse.
+ if (auto *OA = dyn_cast<OffloadAction>(CurAction)) {
+ // If the dependent action is a device action, we will attempt to collapse
+ // only with other device actions. Otherwise, we would do the same but
+ // with host actions only.
+ if (!IsHostSelector) {
+ if (OA->hasSingleDeviceDependence(/*DoNotConsiderHostActions=*/true)) {
+ CurAction =
+ OA->getSingleDeviceDependence(/*DoNotConsiderHostActions=*/true);
+ if (CanBeCollapsed &&
+ !CurAction->isCollapsingWithNextDependentActionLegal())
+ return nullptr;
+ SavedOffloadAction.push_back(OA);
+ return dyn_cast<JobAction>(CurAction);
+ }
+ } else if (OA->hasHostDependence()) {
+ CurAction = OA->getHostDependence();
+ if (CanBeCollapsed &&
+ !CurAction->isCollapsingWithNextDependentActionLegal())
+ return nullptr;
+ SavedOffloadAction.push_back(OA);
+ return dyn_cast<JobAction>(CurAction);
}
- }
- return nullptr;
-}
-// Returns a Tool for a given JobAction. In case the action and its
-// predecessors can be combined, updates Inputs with the inputs of the
-// first combined action. If one of the collapsed actions is a
-// CudaHostAction, updates CollapsedCHA with the pointer to it so the
-// caller can deal with extra handling such action requires.
-static const Tool *selectToolForJob(Compilation &C, bool SaveTemps,
- bool EmbedBitcode, const ToolChain *TC,
- const JobAction *JA,
- const ActionList *&Inputs,
- ActionList &CollapsedOffloadAction) {
- const Tool *ToolForJob = nullptr;
- CollapsedOffloadAction.clear();
-
- // See if we should look for a compiler with an integrated assembler. We match
- // bottom up, so what we are actually looking for is an assembler job with a
- // compiler input.
-
- // Look through offload actions between assembler and backend actions.
- Action *BackendJA = (isa<AssembleJobAction>(JA) && Inputs->size() == 1)
- ? *Inputs->begin()
- : nullptr;
- auto *BackendOA = collapseOffloadingAction<BackendJobAction>(BackendJA);
-
- if (TC->useIntegratedAs() && !SaveTemps &&
- !C.getArgs().hasArg(options::OPT_via_file_asm) &&
- !C.getArgs().hasArg(options::OPT__SLASH_FA) &&
- !C.getArgs().hasArg(options::OPT__SLASH_Fa) && BackendJA &&
- isa<BackendJobAction>(BackendJA)) {
- // A BackendJob is always preceded by a CompileJob, and without -save-temps
- // or -fembed-bitcode, they will always get combined together, so instead of
- // checking the backend tool, check if the tool for the CompileJob has an
- // integrated assembler. For -fembed-bitcode, CompileJob is still used to
- // look up tools for BackendJob, but they need to match before we can split
- // them.
-
- // Look through offload actions between backend and compile actions.
- Action *CompileJA = *BackendJA->getInputs().begin();
- auto *CompileOA = collapseOffloadingAction<CompileJobAction>(CompileJA);
-
- assert(CompileJA && isa<CompileJobAction>(CompileJA) &&
- "Backend job is not preceeded by compile job.");
- const Tool *Compiler = TC->SelectTool(*cast<CompileJobAction>(CompileJA));
- if (!Compiler)
return nullptr;
+ }
+
+ return dyn_cast<JobAction>(CurAction);
+ }
+
+ /// Return true if an assemble action can be collapsed.
+ bool canCollapseAssembleAction() const {
+ return TC.useIntegratedAs() && !SaveTemps &&
+ !C.getArgs().hasArg(options::OPT_via_file_asm) &&
+ !C.getArgs().hasArg(options::OPT__SLASH_FA) &&
+ !C.getArgs().hasArg(options::OPT__SLASH_Fa);
+ }
+
+ /// Return true if a preprocessor action can be collapsed.
+ bool canCollapsePreprocessorAction() const {
+ return !C.getArgs().hasArg(options::OPT_no_integrated_cpp) &&
+ !C.getArgs().hasArg(options::OPT_traditional_cpp) && !SaveTemps &&
+ !C.getArgs().hasArg(options::OPT_rewrite_objc);
+ }
+
+ /// Struct that relates an action with the offload actions that would be
+ /// collapsed with it.
+ struct JobActionInfo final {
+ /// The action this info refers to.
+ const JobAction *JA = nullptr;
+ /// The offload actions we need to take care off if this action is
+ /// collapsed.
+ ActionList SavedOffloadAction;
+ };
+
+ /// Append collapsed offload actions from the give nnumber of elements in the
+ /// action info array.
+ static void AppendCollapsedOffloadAction(ActionList &CollapsedOffloadAction,
+ ArrayRef<JobActionInfo> &ActionInfo,
+ unsigned ElementNum) {
+ assert(ElementNum <= ActionInfo.size() && "Invalid number of elements.");
+ for (unsigned I = 0; I < ElementNum; ++I)
+ CollapsedOffloadAction.append(ActionInfo[I].SavedOffloadAction.begin(),
+ ActionInfo[I].SavedOffloadAction.end());
+ }
+
+ /// Functions that attempt to perform the combining. They detect if that is
+ /// legal, and if so they update the inputs \a Inputs and the offload action
+ /// that were collapsed in \a CollapsedOffloadAction. A tool that deals with
+ /// the combined action is returned. If the combining is not legal or if the
+ /// tool does not exist, null is returned.
+ /// Currently three kinds of collapsing are supported:
+ /// - Assemble + Backend + Compile;
+ /// - Assemble + Backend ;
+ /// - Backend + Compile.
+ const Tool *
+ combineAssembleBackendCompile(ArrayRef<JobActionInfo> ActionInfo,
+ const ActionList *&Inputs,
+ ActionList &CollapsedOffloadAction) {
+ if (ActionInfo.size() < 3 || !canCollapseAssembleAction())
+ return nullptr;
+ auto *AJ = dyn_cast<AssembleJobAction>(ActionInfo[0].JA);
+ auto *BJ = dyn_cast<BackendJobAction>(ActionInfo[1].JA);
+ auto *CJ = dyn_cast<CompileJobAction>(ActionInfo[2].JA);
+ if (!AJ || !BJ || !CJ)
+ return nullptr;
+
+ // Get compiler tool.
+ const Tool *T = TC.SelectTool(*CJ);
+ if (!T)
+ return nullptr;
+
// When using -fembed-bitcode, it is required to have the same tool (clang)
// for both CompilerJA and BackendJA. Otherwise, combine two stages.
if (EmbedBitcode) {
- JobAction *InputJA = cast<JobAction>(*Inputs->begin());
- const Tool *BackendTool = TC->SelectTool(*InputJA);
- if (BackendTool == Compiler)
- CompileJA = InputJA;
- }
- if (Compiler->hasIntegratedAssembler()) {
- Inputs = &CompileJA->getInputs();
- ToolForJob = Compiler;
- // Save the collapsed offload actions because they may still contain
- // device actions.
- if (CompileOA)
- CollapsedOffloadAction.push_back(CompileOA);
- if (BackendOA)
- CollapsedOffloadAction.push_back(BackendOA);
- }
- }
-
- // A backend job should always be combined with the preceding compile job
- // unless OPT_save_temps or OPT_fembed_bitcode is enabled and the compiler is
- // capable of emitting LLVM IR as an intermediate output.
- if (isa<BackendJobAction>(JA)) {
- // Check if the compiler supports emitting LLVM IR.
- assert(Inputs->size() == 1);
-
- // Look through offload actions between backend and compile actions.
- Action *CompileJA = *JA->getInputs().begin();
- auto *CompileOA = collapseOffloadingAction<CompileJobAction>(CompileJA);
-
- assert(CompileJA && isa<CompileJobAction>(CompileJA) &&
- "Backend job is not preceeded by compile job.");
- const Tool *Compiler = TC->SelectTool(*cast<CompileJobAction>(CompileJA));
- if (!Compiler)
+ const Tool *BT = TC.SelectTool(*BJ);
+ if (BT == T)
+ return nullptr;
+ }
+
+ if (!T->hasIntegratedAssembler())
return nullptr;
- if (!Compiler->canEmitIR() ||
- (!SaveTemps && !EmbedBitcode)) {
- Inputs = &CompileJA->getInputs();
- ToolForJob = Compiler;
- if (CompileOA)
- CollapsedOffloadAction.push_back(CompileOA);
- }
+ Inputs = &CJ->getInputs();
+ AppendCollapsedOffloadAction(CollapsedOffloadAction, ActionInfo,
+ /*NumElements=*/3);
+ return T;
}
+ const Tool *combineAssembleBackend(ArrayRef<JobActionInfo> ActionInfo,
+ const ActionList *&Inputs,
+ ActionList &CollapsedOffloadAction) {
+ if (ActionInfo.size() < 2 || !canCollapseAssembleAction())
+ return nullptr;
+ auto *AJ = dyn_cast<AssembleJobAction>(ActionInfo[0].JA);
+ auto *BJ = dyn_cast<BackendJobAction>(ActionInfo[1].JA);
+ if (!AJ || !BJ)
+ return nullptr;
- // Otherwise use the tool for the current job.
- if (!ToolForJob)
- ToolForJob = TC->SelectTool(*JA);
+ // Retrieve the compile job, backend action must always be preceded by one.
+ ActionList CompileJobOffloadActions;
+ auto *CJ = getPrevDependentAction(BJ->getInputs(), CompileJobOffloadActions,
+ /*CanBeCollapsed=*/false);
+ if (!AJ || !BJ || !CJ)
+ return nullptr;
- // See if we should use an integrated preprocessor. We do so when we have
- // exactly one input, since this is the only use case we care about
- // (irrelevant since we don't support combine yet).
+ assert(isa<CompileJobAction>(CJ) &&
+ "Expecting compile job preceding backend job.");
- // Look through offload actions after preprocessing.
- Action *PreprocessJA = (Inputs->size() == 1) ? *Inputs->begin() : nullptr;
- auto *PreprocessOA =
- collapseOffloadingAction<PreprocessJobAction>(PreprocessJA);
+ // Get compiler tool.
+ const Tool *T = TC.SelectTool(*CJ);
+ if (!T)
+ return nullptr;
+
+ if (!T->hasIntegratedAssembler())
+ return nullptr;
- if (PreprocessJA && isa<PreprocessJobAction>(PreprocessJA) &&
- !C.getArgs().hasArg(options::OPT_no_integrated_cpp) &&
- !C.getArgs().hasArg(options::OPT_traditional_cpp) && !SaveTemps &&
- !C.getArgs().hasArg(options::OPT_rewrite_objc) &&
- ToolForJob->hasIntegratedCPP()) {
- Inputs = &PreprocessJA->getInputs();
- if (PreprocessOA)
- CollapsedOffloadAction.push_back(PreprocessOA);
+ Inputs = &BJ->getInputs();
+ AppendCollapsedOffloadAction(CollapsedOffloadAction, ActionInfo,
+ /*NumElements=*/2);
+ return T;
}
+ const Tool *combineBackendCompile(ArrayRef<JobActionInfo> ActionInfo,
+ const ActionList *&Inputs,
+ ActionList &CollapsedOffloadAction) {
+ if (ActionInfo.size() < 2 || !canCollapsePreprocessorAction())
+ return nullptr;
+ auto *BJ = dyn_cast<BackendJobAction>(ActionInfo[0].JA);
+ auto *CJ = dyn_cast<CompileJobAction>(ActionInfo[1].JA);
+ if (!BJ || !CJ)
+ return nullptr;
+
+ // Get compiler tool.
+ const Tool *T = TC.SelectTool(*CJ);
+ if (!T)
+ return nullptr;
+
+ if (T->canEmitIR() && (SaveTemps || EmbedBitcode))
+ return nullptr;
+
+ Inputs = &CJ->getInputs();
+ AppendCollapsedOffloadAction(CollapsedOffloadAction, ActionInfo,
+ /*NumElements=*/2);
+ return T;
+ }
+
+ /// Updates the inputs if the obtained tool supports combining with
+ /// preprocessor action, and the current input is indeed a preprocessor
+ /// action. If combining results in the collapse of offloading actions, those
+ /// are appended to \a CollapsedOffloadAction.
+ void combineWithPreprocessor(const Tool *T, const ActionList *&Inputs,
+ ActionList &CollapsedOffloadAction) {
+ if (!T || !canCollapsePreprocessorAction() || !T->hasIntegratedCPP())
+ return;
+
+ // Attempt to get a preprocessor action dependence.
+ ActionList PreprocessJobOffloadActions;
+ auto *PJ = getPrevDependentAction(*Inputs, PreprocessJobOffloadActions);
+ if (!PJ || !isa<PreprocessJobAction>(PJ))
+ return;
+
+ // This is legal to combine. Append any offload action we found and set the
+ // current inputs to preprocessor inputs.
+ CollapsedOffloadAction.append(PreprocessJobOffloadActions.begin(),
+ PreprocessJobOffloadActions.end());
+ Inputs = &PJ->getInputs();
+ }
+
+public:
+ ToolSelector(const JobAction *BaseAction, const ToolChain &TC,
+ const Compilation &C, bool SaveTemps, bool EmbedBitcode)
+ : TC(TC), C(C), BaseAction(BaseAction), SaveTemps(SaveTemps),
+ EmbedBitcode(EmbedBitcode) {
+ assert(BaseAction && "Invalid base action.");
+ IsHostSelector = BaseAction->getOffloadingDeviceKind() == Action::OFK_None;
+ }
+
+ /// Check if a chain of actions can be combined and return the tool that can
+ /// handle the combination of actions. The pointer to the current inputs \a
+ /// Inputs and the list of offload actions \a CollapsedOffloadActions
+ /// connected to collapsed actions are updated accordingly. The latter enables
+ /// the caller of the selector to process them afterwards instead of just
+ /// dropping them. If no suitable tool is found, null will be returned.
+ const Tool *getTool(const ActionList *&Inputs,
+ ActionList &CollapsedOffloadAction) {
+ //
+ // Get the largest chain of actions that we could combine.
+ //
+
+ SmallVector<JobActionInfo, 5> ActionChain(1);
+ ActionChain.back().JA = BaseAction;
+ while (ActionChain.back().JA) {
+ const Action *CurAction = ActionChain.back().JA;
+
+ // Grow the chain by one element.
+ ActionChain.resize(ActionChain.size() + 1);
+ JobActionInfo &AI = ActionChain.back();
+
+ // Attempt to fill it with the
+ AI.JA =
+ getPrevDependentAction(CurAction->getInputs(), AI.SavedOffloadAction);
+ }
+
+ // Pop the last action info as it could not be filled.
+ ActionChain.pop_back();
- return ToolForJob;
+ //
+ // Attempt to combine actions. If all combining attempts failed, just return
+ // the tool of the provided action. At the end we attempt to combine the
+ // action with any preprocessor action it may depend on.
+ //
+
+ const Tool *T = combineAssembleBackendCompile(ActionChain, Inputs,
+ CollapsedOffloadAction);
+ if (!T)
+ T = combineAssembleBackend(ActionChain, Inputs, CollapsedOffloadAction);
+ if (!T)
+ T = combineBackendCompile(ActionChain, Inputs, CollapsedOffloadAction);
+ if (!T) {
+ Inputs = &BaseAction->getInputs();
+ T = TC.SelectTool(*BaseAction);
+ }
+
+ combineWithPreprocessor(T, Inputs, CollapsedOffloadAction);
+ return T;
+ }
+};
}
-InputInfo Driver::BuildJobsForAction(
- Compilation &C, const Action *A, const ToolChain *TC, const char *BoundArch,
- bool AtTopLevel, bool MultipleArchs, const char *LinkingOutput,
- std::map<std::pair<const Action *, std::string>, InputInfo> &CachedResults,
- bool BuildForOffloadDevice) const {
- // The bound arch is not necessarily represented in the toolchain's triple --
- // for example, armv7 and armv7s both map to the same triple -- so we need
- // both in our map.
+/// Return a string that uniquely identifies the result of a job. The bound arch
+/// is not necessarily represented in the toolchain's triple -- for example,
+/// armv7 and armv7s both map to the same triple -- so we need both in our map.
+/// Also, we need to add the offloading device kind, as the same tool chain can
+/// be used for host and device for some programming models, e.g. OpenMP.
+static std::string GetTriplePlusArchString(const ToolChain *TC,
+ StringRef BoundArch,
+ Action::OffloadKind OffloadKind) {
std::string TriplePlusArch = TC->getTriple().normalize();
- if (BoundArch) {
+ if (!BoundArch.empty()) {
TriplePlusArch += "-";
TriplePlusArch += BoundArch;
}
- std::pair<const Action *, std::string> ActionTC = {A, TriplePlusArch};
+ TriplePlusArch += "-";
+ TriplePlusArch += Action::GetOffloadKindName(OffloadKind);
+ return TriplePlusArch;
+}
+
+InputInfo Driver::BuildJobsForAction(
+ Compilation &C, const Action *A, const ToolChain *TC, StringRef BoundArch,
+ bool AtTopLevel, bool MultipleArchs, const char *LinkingOutput,
+ std::map<std::pair<const Action *, std::string>, InputInfo> &CachedResults,
+ Action::OffloadKind TargetDeviceOffloadKind) const {
+ std::pair<const Action *, std::string> ActionTC = {
+ A, GetTriplePlusArchString(TC, BoundArch, TargetDeviceOffloadKind)};
auto CachedResult = CachedResults.find(ActionTC);
if (CachedResult != CachedResults.end()) {
return CachedResult->second;
}
InputInfo Result = BuildJobsForActionNoCache(
C, A, TC, BoundArch, AtTopLevel, MultipleArchs, LinkingOutput,
- CachedResults, BuildForOffloadDevice);
+ CachedResults, TargetDeviceOffloadKind);
CachedResults[ActionTC] = Result;
return Result;
}
InputInfo Driver::BuildJobsForActionNoCache(
- Compilation &C, const Action *A, const ToolChain *TC, const char *BoundArch,
+ Compilation &C, const Action *A, const ToolChain *TC, StringRef BoundArch,
bool AtTopLevel, bool MultipleArchs, const char *LinkingOutput,
std::map<std::pair<const Action *, std::string>, InputInfo> &CachedResults,
- bool BuildForOffloadDevice) const {
+ Action::OffloadKind TargetDeviceOffloadKind) const {
llvm::PrettyStackTraceString CrashInfo("Building compilation jobs");
InputInfoList OffloadDependencesInputInfo;
+ bool BuildingForOffloadDevice = TargetDeviceOffloadKind != Action::OFK_None;
if (const OffloadAction *OA = dyn_cast<OffloadAction>(A)) {
// The offload action is expected to be used in four different situations.
//
@@ -2121,7 +3106,7 @@ InputInfo Driver::BuildJobsForActionNoCache(
// b) Set a toolchain/architecture/kind for a device action;
// Device Action 1 -> OffloadAction -> Device Action 2
//
- // c) Specify a device dependences to a host action;
+ // c) Specify a device dependence to a host action;
// Device Action 1 _
// \
// Host Action 1 ---> OffloadAction -> Host Action 2
@@ -2144,7 +3129,7 @@ InputInfo Driver::BuildJobsForActionNoCache(
DevA =
BuildJobsForAction(C, DepA, DepTC, DepBoundArch, AtTopLevel,
/*MultipleArchs*/ !!DepBoundArch, LinkingOutput,
- CachedResults, /*BuildForOffloadDevice=*/true);
+ CachedResults, DepA->getOffloadingDeviceKind());
});
return DevA;
}
@@ -2154,16 +3139,15 @@ InputInfo Driver::BuildJobsForActionNoCache(
// generate the host dependences and override the action with the device
// dependence. The dependences can't therefore be a top-level action.
OA->doOnEachDependence(
- /*IsHostDependence=*/BuildForOffloadDevice,
+ /*IsHostDependence=*/BuildingForOffloadDevice,
[&](Action *DepA, const ToolChain *DepTC, const char *DepBoundArch) {
OffloadDependencesInputInfo.push_back(BuildJobsForAction(
C, DepA, DepTC, DepBoundArch, /*AtTopLevel=*/false,
/*MultipleArchs*/ !!DepBoundArch, LinkingOutput, CachedResults,
- /*BuildForOffloadDevice=*/DepA->getOffloadingDeviceKind() !=
- Action::OFK_None));
+ DepA->getOffloadingDeviceKind()));
});
- A = BuildForOffloadDevice
+ A = BuildingForOffloadDevice
? OA->getSingleDeviceDependence(/*DoNotConsiderHostActions=*/true)
: OA->getHostDependence();
}
@@ -2182,9 +3166,9 @@ InputInfo Driver::BuildJobsForActionNoCache(
if (const BindArchAction *BAA = dyn_cast<BindArchAction>(A)) {
const ToolChain *TC;
- const char *ArchName = BAA->getArchName();
+ StringRef ArchName = BAA->getArchName();
- if (ArchName)
+ if (!ArchName.empty())
TC = &getToolChain(C.getArgs(),
computeTargetTriple(*this, DefaultTargetTriple,
C.getArgs(), ArchName));
@@ -2193,7 +3177,7 @@ InputInfo Driver::BuildJobsForActionNoCache(
return BuildJobsForAction(C, *BAA->input_begin(), TC, ArchName, AtTopLevel,
MultipleArchs, LinkingOutput, CachedResults,
- BuildForOffloadDevice);
+ TargetDeviceOffloadKind);
}
@@ -2202,9 +3186,9 @@ InputInfo Driver::BuildJobsForActionNoCache(
const JobAction *JA = cast<JobAction>(A);
ActionList CollapsedOffloadActions;
- const Tool *T =
- selectToolForJob(C, isSaveTempsEnabled(), embedBitcodeEnabled(), TC, JA,
- Inputs, CollapsedOffloadActions);
+ ToolSelector TS(JA, *TC, C, isSaveTempsEnabled(), embedBitcodeInObject());
+ const Tool *T = TS.getTool(Inputs, CollapsedOffloadActions);
+
if (!T)
return InputInfo();
@@ -2212,13 +3196,12 @@ InputInfo Driver::BuildJobsForActionNoCache(
// need to build jobs for host/device-side inputs it may have held.
for (const auto *OA : CollapsedOffloadActions)
cast<OffloadAction>(OA)->doOnEachDependence(
- /*IsHostDependence=*/BuildForOffloadDevice,
+ /*IsHostDependence=*/BuildingForOffloadDevice,
[&](Action *DepA, const ToolChain *DepTC, const char *DepBoundArch) {
OffloadDependencesInputInfo.push_back(BuildJobsForAction(
- C, DepA, DepTC, DepBoundArch, AtTopLevel,
+ C, DepA, DepTC, DepBoundArch, /* AtTopLevel */ false,
/*MultipleArchs=*/!!DepBoundArch, LinkingOutput, CachedResults,
- /*BuildForOffloadDevice=*/DepA->getOffloadingDeviceKind() !=
- Action::OFK_None));
+ DepA->getOffloadingDeviceKind()));
});
// Only use pipes when there is exactly one input.
@@ -2231,7 +3214,7 @@ InputInfo Driver::BuildJobsForActionNoCache(
AtTopLevel && (isa<DsymutilJobAction>(A) || isa<VerifyJobAction>(A));
InputInfos.push_back(BuildJobsForAction(
C, Input, TC, BoundArch, SubJobAtTopLevel, MultipleArchs, LinkingOutput,
- CachedResults, BuildForOffloadDevice));
+ CachedResults, A->getOffloadingDeviceKind()));
}
// Always use the first input as the base input.
@@ -2247,15 +3230,75 @@ InputInfo Driver::BuildJobsForActionNoCache(
InputInfos.append(OffloadDependencesInputInfo.begin(),
OffloadDependencesInputInfo.end());
+ // Set the effective triple of the toolchain for the duration of this job.
+ llvm::Triple EffectiveTriple;
+ const ToolChain &ToolTC = T->getToolChain();
+ const ArgList &Args =
+ C.getArgsForToolChain(TC, BoundArch, A->getOffloadingDeviceKind());
+ if (InputInfos.size() != 1) {
+ EffectiveTriple = llvm::Triple(ToolTC.ComputeEffectiveClangTriple(Args));
+ } else {
+ // Pass along the input type if it can be unambiguously determined.
+ EffectiveTriple = llvm::Triple(
+ ToolTC.ComputeEffectiveClangTriple(Args, InputInfos[0].getType()));
+ }
+ RegisterEffectiveTriple TripleRAII(ToolTC, EffectiveTriple);
+
// Determine the place to write output to, if any.
InputInfo Result;
- if (JA->getType() == types::TY_Nothing)
+ InputInfoList UnbundlingResults;
+ if (auto *UA = dyn_cast<OffloadUnbundlingJobAction>(JA)) {
+ // If we have an unbundling job, we need to create results for all the
+ // outputs. We also update the results cache so that other actions using
+ // this unbundling action can get the right results.
+ for (auto &UI : UA->getDependentActionsInfo()) {
+ assert(UI.DependentOffloadKind != Action::OFK_None &&
+ "Unbundling with no offloading??");
+
+ // Unbundling actions are never at the top level. When we generate the
+ // offloading prefix, we also do that for the host file because the
+ // unbundling action does not change the type of the output which can
+ // cause a overwrite.
+ std::string OffloadingPrefix = Action::GetOffloadingFileNamePrefix(
+ UI.DependentOffloadKind,
+ UI.DependentToolChain->getTriple().normalize(),
+ /*CreatePrefixForHost=*/true);
+ auto CurI = InputInfo(
+ UA, GetNamedOutputPath(C, *UA, BaseInput, UI.DependentBoundArch,
+ /*AtTopLevel=*/false, MultipleArchs,
+ 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, UI.DependentBoundArch,
+ UI.DependentOffloadKind)}] = CurI;
+ }
+
+ // Now that we have all the results generated, select the one that should be
+ // returned for the current depending action.
+ std::pair<const Action *, std::string> ActionTC = {
+ A, GetTriplePlusArchString(TC, BoundArch, TargetDeviceOffloadKind)};
+ assert(CachedResults.find(ActionTC) != CachedResults.end() &&
+ "Result does not exist??");
+ Result = CachedResults[ActionTC];
+ } else if (JA->getType() == types::TY_Nothing)
Result = InputInfo(A, BaseInput);
- else
+ else {
+ // We only have to generate a prefix for the host if this is not a top-level
+ // action.
+ std::string OffloadingPrefix = Action::GetOffloadingFileNamePrefix(
+ A->getOffloadingDeviceKind(), TC->getTriple().normalize(),
+ /*CreatePrefixForHost=*/!!A->getOffloadingHostActiveKinds() &&
+ !AtTopLevel);
Result = InputInfo(A, GetNamedOutputPath(C, *JA, BaseInput, BoundArch,
AtTopLevel, MultipleArchs,
- TC->getTriple().normalize()),
+ OffloadingPrefix),
BaseInput);
+ }
if (CCCPrintBindings && !CCGenDiagnostics) {
llvm::errs() << "# \"" << T->getToolChain().getTripleString() << '"'
@@ -2265,10 +3308,28 @@ InputInfo Driver::BuildJobsForActionNoCache(
if (i + 1 != e)
llvm::errs() << ", ";
}
- llvm::errs() << "], output: " << Result.getAsString() << "\n";
+ if (UnbundlingResults.empty())
+ llvm::errs() << "], output: " << Result.getAsString() << "\n";
+ else {
+ llvm::errs() << "], outputs: [";
+ for (unsigned i = 0, e = UnbundlingResults.size(); i != e; ++i) {
+ llvm::errs() << UnbundlingResults[i].getAsString();
+ if (i + 1 != e)
+ llvm::errs() << ", ";
+ }
+ llvm::errs() << "] \n";
+ }
} else {
- T->ConstructJob(C, *JA, Result, InputInfos,
- C.getArgsForToolChain(TC, BoundArch), LinkingOutput);
+ if (UnbundlingResults.empty())
+ T->ConstructJob(
+ C, *JA, Result, InputInfos,
+ C.getArgsForToolChain(TC, BoundArch, JA->getOffloadingDeviceKind()),
+ LinkingOutput);
+ else
+ T->ConstructJobMultipleOutputs(
+ C, *JA, UnbundlingResults, InputInfos,
+ C.getArgsForToolChain(TC, BoundArch, JA->getOffloadingDeviceKind()),
+ LinkingOutput);
}
return Result;
}
@@ -2313,9 +3374,9 @@ static const char *MakeCLOutputFilename(const ArgList &Args, StringRef ArgValue,
const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA,
const char *BaseInput,
- const char *BoundArch, bool AtTopLevel,
+ StringRef BoundArch, bool AtTopLevel,
bool MultipleArchs,
- StringRef NormalizedTriple) const {
+ StringRef OffloadingPrefix) const {
llvm::PrettyStackTraceString CrashInfo("Computing output path");
// Output to a user requested destination?
if (AtTopLevel && !isa<DsymutilJobAction>(JA) && !isa<VerifyJobAction>(JA)) {
@@ -2360,7 +3421,7 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA,
std::pair<StringRef, StringRef> Split = Name.split('.');
std::string TmpName = GetTemporaryPath(
Split.first, types::getTypeTempSuffix(JA.getType(), IsCLMode()));
- return C.addTempFile(C.getArgs().MakeArgString(TmpName.c_str()));
+ return C.addTempFile(C.getArgs().MakeArgString(TmpName));
}
SmallString<128> BasePath(BaseInput);
@@ -2375,7 +3436,7 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA,
// Determine what the derived output name should be.
const char *NamedOutput;
- if (JA.getType() == types::TY_Object &&
+ if ((JA.getType() == types::TY_Object || JA.getType() == types::TY_LTO_BC) &&
C.getArgs().hasArg(options::OPT__SLASH_Fo, options::OPT__SLASH_o)) {
// The /Fo or /o flag decides the object filename.
StringRef Val =
@@ -2399,17 +3460,17 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA,
// clang-cl uses BaseName for the executable name.
NamedOutput =
MakeCLOutputFilename(C.getArgs(), "", BaseName, types::TY_Image);
- } else if (MultipleArchs && BoundArch) {
+ } else {
SmallString<128> Output(getDefaultImageName());
- Output += JA.getOffloadingFileNamePrefix(NormalizedTriple);
- Output += "-";
- Output.append(BoundArch);
+ Output += OffloadingPrefix;
+ if (MultipleArchs && !BoundArch.empty()) {
+ Output += "-";
+ Output.append(BoundArch);
+ }
NamedOutput = C.getArgs().MakeArgString(Output.c_str());
- } else {
- NamedOutput = getDefaultImageName();
}
} else if (JA.getType() == types::TY_PCH && IsCLMode()) {
- NamedOutput = C.getArgs().MakeArgString(GetClPchPath(C, BaseName).c_str());
+ NamedOutput = C.getArgs().MakeArgString(GetClPchPath(C, BaseName));
} else {
const char *Suffix = types::getTypeTempSuffix(JA.getType(), IsCLMode());
assert(Suffix && "All types used for output should have a suffix.");
@@ -2418,8 +3479,8 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA,
if (!types::appendSuffixForType(JA.getType()))
End = BaseName.rfind('.');
SmallString<128> Suffixed(BaseName.substr(0, End));
- Suffixed += JA.getOffloadingFileNamePrefix(NormalizedTriple);
- if (MultipleArchs && BoundArch) {
+ Suffixed += OffloadingPrefix;
+ if (MultipleArchs && !BoundArch.empty()) {
Suffixed += "-";
Suffixed.append(BoundArch);
}
@@ -2459,7 +3520,7 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA,
std::pair<StringRef, StringRef> Split = Name.split('.');
std::string TmpName = GetTemporaryPath(
Split.first, types::getTypeTempSuffix(JA.getType(), IsCLMode()));
- return C.addTempFile(C.getArgs().MakeArgString(TmpName.c_str()));
+ return C.addTempFile(C.getArgs().MakeArgString(TmpName));
}
}
@@ -2476,7 +3537,7 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA,
}
}
-std::string Driver::GetFilePath(const char *Name, const ToolChain &TC) const {
+std::string Driver::GetFilePath(StringRef Name, const ToolChain &TC) const {
// Respect a limited subset of the '-Bprefix' functionality in GCC by
// attempting to use this prefix when looking for file paths.
for (const std::string &Dir : PrefixDirs) {
@@ -2506,16 +3567,16 @@ std::string Driver::GetFilePath(const char *Name, const ToolChain &TC) const {
}
void Driver::generatePrefixedToolNames(
- const char *Tool, const ToolChain &TC,
+ StringRef Tool, const ToolChain &TC,
SmallVectorImpl<std::string> &Names) const {
// FIXME: Needs a better variable than DefaultTargetTriple
- Names.emplace_back(DefaultTargetTriple + "-" + Tool);
+ Names.emplace_back((DefaultTargetTriple + "-" + 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);
+ Names.emplace_back((LLVMDefaultTargetTriple + "-" + Tool).str());
}
static bool ScanDirForExecutable(SmallString<128> &Dir,
@@ -2529,8 +3590,7 @@ static bool ScanDirForExecutable(SmallString<128> &Dir,
return false;
}
-std::string Driver::GetProgramPath(const char *Name,
- const ToolChain &TC) const {
+std::string Driver::GetProgramPath(StringRef Name, const ToolChain &TC) const {
SmallVector<std::string, 2> TargetSpecificExecutables;
generatePrefixedToolNames(Name, TC, TargetSpecificExecutables);
@@ -2542,7 +3602,7 @@ std::string Driver::GetProgramPath(const char *Name,
if (ScanDirForExecutable(P, TargetSpecificExecutables))
return P.str();
} else {
- SmallString<128> P(PrefixDir + Name);
+ SmallString<128> P((PrefixDir + Name).str());
if (llvm::sys::fs::can_execute(Twine(P)))
return P.str();
}
@@ -2564,8 +3624,7 @@ std::string Driver::GetProgramPath(const char *Name,
return Name;
}
-std::string Driver::GetTemporaryPath(StringRef Prefix,
- const char *Suffix) const {
+std::string Driver::GetTemporaryPath(StringRef Prefix, StringRef Suffix) const {
SmallString<128> Path;
std::error_code EC = llvm::sys::fs::createTemporaryFile(Prefix, Suffix, Path);
if (EC) {
@@ -2645,6 +3704,9 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
case llvm::Triple::NaCl:
TC = new toolchains::NaClToolChain(*this, Target, Args);
break;
+ case llvm::Triple::Fuchsia:
+ TC = new toolchains::Fuchsia(*this, Target, Args);
+ break;
case llvm::Triple::Solaris:
TC = new toolchains::Solaris(*this, Target, Args);
break;
@@ -2673,12 +3735,12 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
break;
}
break;
- case llvm::Triple::CUDA:
- TC = new toolchains::CudaToolChain(*this, Target, Args);
- break;
case llvm::Triple::PS4:
TC = new toolchains::PS4CPU(*this, Target, Args);
break;
+ case llvm::Triple::Contiki:
+ TC = new toolchains::Contiki(*this, Target, Args);
+ break;
default:
// Of these targets, Hexagon is the only one that might have
// an OS of Linux, in which case it got handled above already.
@@ -2686,6 +3748,9 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
case llvm::Triple::tce:
TC = new toolchains::TCEToolChain(*this, Target, Args);
break;
+ case llvm::Triple::tcele:
+ TC = new toolchains::TCELEToolChain(*this, Target, Args);
+ break;
case llvm::Triple::hexagon:
TC = new toolchains::HexagonToolChain(*this, Target, Args);
break;
@@ -2711,6 +3776,12 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
}
}
}
+
+ // Intentionally omitted from the switch above: llvm::Triple::CUDA. CUDA
+ // compiles always need two toolchains, the CUDA toolchain and the host
+ // toolchain. So the only valid way to create a CUDA toolchain is via
+ // CreateOffloadingDeviceToolChains.
+
return *TC;
}
@@ -2733,36 +3804,35 @@ bool Driver::ShouldUseClangCompiler(const JobAction &JA) const {
///
/// \return True if the entire string was parsed (9.2), or all groups were
/// parsed (10.3.5extrastuff).
-bool Driver::GetReleaseVersion(const char *Str, unsigned &Major,
- unsigned &Minor, unsigned &Micro,
- bool &HadExtra) {
+bool Driver::GetReleaseVersion(StringRef Str, unsigned &Major, unsigned &Minor,
+ unsigned &Micro, bool &HadExtra) {
HadExtra = false;
Major = Minor = Micro = 0;
- if (*Str == '\0')
+ if (Str.empty())
return false;
- char *End;
- Major = (unsigned)strtol(Str, &End, 10);
- if (*Str != '\0' && *End == '\0')
+ if (Str.consumeInteger(10, Major))
+ return false;
+ if (Str.empty())
return true;
- if (*End != '.')
+ if (Str[0] != '.')
return false;
- Str = End + 1;
- Minor = (unsigned)strtol(Str, &End, 10);
- if (*Str != '\0' && *End == '\0')
+ Str = Str.drop_front(1);
+
+ if (Str.consumeInteger(10, Minor))
+ return false;
+ if (Str.empty())
return true;
- if (*End != '.')
+ if (Str[0] != '.')
return false;
+ Str = Str.drop_front(1);
- Str = End + 1;
- Micro = (unsigned)strtol(Str, &End, 10);
- if (*Str != '\0' && *End == '\0')
- return true;
- if (Str == End)
+ if (Str.consumeInteger(10, Micro))
return false;
- HadExtra = true;
+ if (!Str.empty())
+ HadExtra = true;
return true;
}
@@ -2772,21 +3842,22 @@ bool Driver::GetReleaseVersion(const char *Str, unsigned &Major,
///
/// \return True if the entire string was parsed and there are
/// no extra characters remaining at the end.
-bool Driver::GetReleaseVersion(const char *Str,
+bool Driver::GetReleaseVersion(StringRef Str,
MutableArrayRef<unsigned> Digits) {
- if (*Str == '\0')
+ if (Str.empty())
return false;
- char *End;
unsigned CurDigit = 0;
while (CurDigit < Digits.size()) {
- unsigned Digit = (unsigned)strtol(Str, &End, 10);
+ unsigned Digit;
+ if (Str.consumeInteger(10, Digit))
+ return false;
Digits[CurDigit] = Digit;
- if (*Str != '\0' && *End == '\0')
+ if (Str.empty())
return true;
- if (*End != '.' || Str == End)
+ if (Str[0] != '.')
return false;
- Str = End + 1;
+ Str = Str.drop_front(1);
CurDigit++;
}
diff --git a/lib/Driver/Job.cpp b/lib/Driver/Job.cpp
index 2d99b1f22385..9fd8808af302 100644
--- a/lib/Driver/Job.cpp
+++ b/lib/Driver/Job.cpp
@@ -7,18 +7,20 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/Driver/Job.h"
#include "InputInfo.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
-#include "clang/Driver/Job.h"
#include "clang/Driver/Tool.h"
#include "clang/Driver/ToolChain.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
@@ -37,50 +39,62 @@ Command::Command(const Action &Source, const Tool &Creator,
InputFilenames.push_back(II.getFilename());
}
-static int skipArgs(const char *Flag, bool HaveCrashVFS) {
+/// @brief 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,
+ bool &IsInclude) {
+ SkipNum = 2;
// These flags are all of the form -Flag <Arg> and are treated as two
// arguments. Therefore, we need to skip the flag and the next argument.
- bool Res = llvm::StringSwitch<bool>(Flag)
+ bool ShouldSkip = llvm::StringSwitch<bool>(Flag)
.Cases("-MF", "-MT", "-MQ", "-serialize-diagnostic-file", true)
.Cases("-o", "-coverage-file", "-dependency-file", true)
- .Cases("-fdebug-compilation-dir", "-idirafter", true)
- .Cases("-include", "-include-pch", "-internal-isystem", true)
- .Cases("-internal-externc-isystem", "-iprefix", "-iwithprefix", true)
- .Cases("-iwithprefixbefore", "-isystem", "-iquote", true)
+ .Cases("-fdebug-compilation-dir", "-diagnostic-log-file", true)
.Cases("-dwarf-debug-flags", "-ivfsoverlay", true)
- .Cases("-header-include-file", "-diagnostic-log-file", true)
- // Some include flags shouldn't be skipped if we have a crash VFS
- .Cases("-isysroot", "-I", "-F", "-resource-dir", !HaveCrashVFS)
.Default(false);
-
- // Match found.
- if (Res)
- return 2;
+ if (ShouldSkip)
+ return true;
+
+ // Some include flags shouldn't be skipped if we have a crash VFS
+ IsInclude = llvm::StringSwitch<bool>(Flag)
+ .Cases("-include", "-header-include-file", true)
+ .Cases("-idirafter", "-internal-isystem", "-iwithprefix", true)
+ .Cases("-internal-externc-isystem", "-iprefix", true)
+ .Cases("-iwithprefixbefore", "-isystem", "-iquote", true)
+ .Cases("-isysroot", "-I", "-F", "-resource-dir", true)
+ .Cases("-iframework", "-include-pch", true)
+ .Default(false);
+ if (IsInclude)
+ return HaveCrashVFS ? false : true;
// The remaining flags are treated as a single argument.
// These flags are all of the form -Flag and have no second argument.
- Res = llvm::StringSwitch<bool>(Flag)
+ ShouldSkip = llvm::StringSwitch<bool>(Flag)
.Cases("-M", "-MM", "-MG", "-MP", "-MD", true)
.Case("-MMD", true)
.Default(false);
// Match found.
- if (Res)
- return 1;
+ SkipNum = 1;
+ if (ShouldSkip)
+ return true;
// These flags are treated as a single argument (e.g., -F<Dir>).
StringRef FlagRef(Flag);
- if ((!HaveCrashVFS &&
- (FlagRef.startswith("-F") || FlagRef.startswith("-I"))) ||
- FlagRef.startswith("-fmodules-cache-path="))
- return 1;
-
- return 0;
+ IsInclude = FlagRef.startswith("-F") || FlagRef.startswith("-I");
+ if (IsInclude)
+ return HaveCrashVFS ? false : true;
+ if (FlagRef.startswith("-fmodules-cache-path="))
+ return true;
+
+ SkipNum = 0;
+ return false;
}
-void Command::printArg(raw_ostream &OS, const char *Arg, bool Quote) {
- const bool Escape = std::strpbrk(Arg, "\"\\$");
+void Command::printArg(raw_ostream &OS, StringRef Arg, bool Quote) {
+ const bool Escape = Arg.find_first_of("\"\\$") != StringRef::npos;
if (!Quote && !Escape) {
OS << Arg;
@@ -89,7 +103,7 @@ void Command::printArg(raw_ostream &OS, const char *Arg, bool Quote) {
// Quote and escape. This isn't really complete, but good enough.
OS << '"';
- while (const char c = *Arg++) {
+ for (const char c : Arg) {
if (c == '"' || c == '\\' || c == '$')
OS << '\\';
OS << c;
@@ -152,6 +166,45 @@ void Command::buildArgvForResponseFile(
}
}
+/// @brief 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;
+ std::error_code EC = fs::current_path(OutInc);
+ if (EC)
+ return false;
+ path::append(OutInc, InInc);
+ return true;
+ };
+
+ SmallString<128> NewInc;
+ if (NumArgs == 1) {
+ StringRef FlagRef(Args[Idx + NumArgs - 1]);
+ assert((FlagRef.startswith("-F") || FlagRef.startswith("-I")) &&
+ "Expecting -I or -F");
+ StringRef Inc = FlagRef.slice(2, StringRef::npos);
+ if (getAbsPath(Inc, NewInc)) {
+ SmallString<128> NewArg(FlagRef.slice(0, 2));
+ NewArg += NewInc;
+ IncFlags.push_back(std::move(NewArg));
+ }
+ return;
+ }
+
+ assert(NumArgs == 2 && "Not expecting more than two arguments");
+ StringRef Inc(Args[Idx + NumArgs - 1]);
+ if (!getAbsPath(Inc, NewInc))
+ return;
+ IncFlags.push_back(SmallString<128>(Args[Idx]));
+ IncFlags.push_back(std::move(NewInc));
+}
+
void Command::Print(raw_ostream &OS, const char *Terminator, bool Quote,
CrashReportInfo *CrashInfo) const {
// Always quote the exe.
@@ -170,10 +223,27 @@ void Command::Print(raw_ostream &OS, const char *Terminator, bool Quote,
const char *const Arg = Args[i];
if (CrashInfo) {
- if (int Skip = skipArgs(Arg, HaveCrashVFS)) {
- i += Skip - 1;
+ int NumArgs = 0;
+ bool IsInclude = false;
+ if (skipArgs(Arg, HaveCrashVFS, NumArgs, IsInclude)) {
+ i += NumArgs - 1;
continue;
}
+
+ // Relative includes need to be expanded to absolute paths.
+ if (HaveCrashVFS && IsInclude) {
+ SmallVector<SmallString<128>, 2> NewIncFlags;
+ rewriteIncludes(Args, i, NumArgs, NewIncFlags);
+ if (!NewIncFlags.empty()) {
+ for (auto &F : NewIncFlags) {
+ OS << ' ';
+ printArg(OS, F.c_str(), Quote);
+ }
+ i += NumArgs - 1;
+ continue;
+ }
+ }
+
auto Found = std::find_if(InputFilenames.begin(), InputFilenames.end(),
[&Arg](StringRef IF) { return IF == Arg; });
if (Found != InputFilenames.end() &&
@@ -181,7 +251,7 @@ void Command::Print(raw_ostream &OS, const char *Terminator, bool Quote,
// Replace the input file name with the crashinfo's file name.
OS << ' ';
StringRef ShortName = llvm::sys::path::filename(CrashInfo->Filename);
- printArg(OS, ShortName.str().c_str(), Quote);
+ printArg(OS, ShortName.str(), Quote);
continue;
}
}
@@ -194,19 +264,22 @@ void Command::Print(raw_ostream &OS, const char *Terminator, bool Quote,
OS << ' ';
printArg(OS, "-ivfsoverlay", Quote);
OS << ' ';
- printArg(OS, CrashInfo->VFSPath.str().c_str(), Quote);
+ printArg(OS, CrashInfo->VFSPath.str(), Quote);
- // Insert -fmodules-cache-path and use the relative module directory
- // <name>.cache/vfs/modules where we already dumped the modules.
+ // The leftover modules from the crash are stored in
+ // <name>.cache/vfs/modules
+ // Leave it untouched for pcm inspection and provide a clean/empty dir
+ // path to contain the future generated module cache:
+ // <name>.cache/vfs/repro-modules
SmallString<128> RelModCacheDir = llvm::sys::path::parent_path(
llvm::sys::path::parent_path(CrashInfo->VFSPath));
- llvm::sys::path::append(RelModCacheDir, "modules");
+ llvm::sys::path::append(RelModCacheDir, "repro-modules");
std::string ModCachePath = "-fmodules-cache-path=";
ModCachePath.append(RelModCacheDir.c_str());
OS << ' ';
- printArg(OS, ModCachePath.c_str(), Quote);
+ printArg(OS, ModCachePath, Quote);
}
if (ResponseFile != nullptr) {
diff --git a/lib/Driver/MSVCToolChain.cpp b/lib/Driver/MSVCToolChain.cpp
index b8de5ad49182..95cf056f7a74 100644
--- a/lib/Driver/MSVCToolChain.cpp
+++ b/lib/Driver/MSVCToolChain.cpp
@@ -16,12 +16,14 @@
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.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"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include <cstdio>
@@ -113,6 +115,9 @@ static bool readFullStringValue(HKEY hkey, const char *valueName,
if (result == ERROR_SUCCESS) {
std::wstring WideValue(reinterpret_cast<const wchar_t *>(buffer.data()),
valueSize / sizeof(wchar_t));
+ if (valueSize && WideValue.back() == L'\0') {
+ WideValue.pop_back();
+ }
// The destination buffer must be empty as an invariant of the conversion
// function; but this function is sometimes called in a loop that passes in
// the same buffer, however. Simply clear it out so we can overwrite it.
@@ -190,8 +195,7 @@ static bool getSystemRegistryString(const char *keyPath, const char *valueName,
lResult = RegOpenKeyExA(hTopKey, bestName.c_str(), 0,
KEY_READ | KEY_WOW64_32KEY, &hKey);
if (lResult == ERROR_SUCCESS) {
- lResult = readFullStringValue(hKey, valueName, value);
- if (lResult == ERROR_SUCCESS) {
+ if (readFullStringValue(hKey, valueName, value)) {
bestValue = dvalue;
if (phValue)
*phValue = bestName;
@@ -208,8 +212,7 @@ static bool getSystemRegistryString(const char *keyPath, const char *valueName,
lResult =
RegOpenKeyExA(hRootKey, keyPath, 0, KEY_READ | KEY_WOW64_32KEY, &hKey);
if (lResult == ERROR_SUCCESS) {
- lResult = readFullStringValue(hKey, valueName, value);
- if (lResult == ERROR_SUCCESS)
+ if (readFullStringValue(hKey, valueName, value))
returnValue = true;
if (phValue)
phValue->clear();
@@ -470,6 +473,14 @@ bool MSVCToolChain::getVisualStudioBinariesFolder(const char *clangProgramPath,
return true;
}
+VersionTuple MSVCToolChain::getMSVCVersionFromTriple() const {
+ unsigned Major, Minor, Micro;
+ getTriple().getEnvironmentVersion(Major, Minor, Micro);
+ if (Major || Minor || Micro)
+ return VersionTuple(Major, Minor, Micro);
+ return VersionTuple();
+}
+
VersionTuple MSVCToolChain::getMSVCVersionFromExe() const {
VersionTuple Version;
#ifdef USE_WIN32
@@ -512,9 +523,9 @@ VersionTuple MSVCToolChain::getMSVCVersionFromExe() const {
// Get Visual Studio installation directory.
bool MSVCToolChain::getVisualStudioInstallDir(std::string &path) const {
// First check the environment variables that vsvars32.bat sets.
- const char *vcinstalldir = getenv("VCINSTALLDIR");
- if (vcinstalldir) {
- path = vcinstalldir;
+ if (llvm::Optional<std::string> VcInstallDir =
+ llvm::sys::Process::GetEnv("VCINSTALLDIR")) {
+ path = std::move(*VcInstallDir);
path = path.substr(0, path.find("\\VC"));
return true;
}
@@ -540,26 +551,26 @@ bool MSVCToolChain::getVisualStudioInstallDir(std::string &path) const {
}
// Try the environment.
- const char *vs120comntools = getenv("VS120COMNTOOLS");
- const char *vs100comntools = getenv("VS100COMNTOOLS");
- const char *vs90comntools = getenv("VS90COMNTOOLS");
- const char *vs80comntools = getenv("VS80COMNTOOLS");
-
- const char *vscomntools = nullptr;
-
- // Find any version we can
- if (vs120comntools)
- vscomntools = vs120comntools;
- else if (vs100comntools)
- vscomntools = vs100comntools;
- else if (vs90comntools)
- vscomntools = vs90comntools;
- else if (vs80comntools)
- vscomntools = vs80comntools;
-
- if (vscomntools && *vscomntools) {
- const char *p = strstr(vscomntools, "\\Common7\\Tools");
- path = p ? std::string(vscomntools, p) : vscomntools;
+ std::string vcomntools;
+ if (llvm::Optional<std::string> vs120comntools =
+ llvm::sys::Process::GetEnv("VS120COMNTOOLS"))
+ vcomntools = std::move(*vs120comntools);
+ else if (llvm::Optional<std::string> vs100comntools =
+ llvm::sys::Process::GetEnv("VS100COMNTOOLS"))
+ vcomntools = std::move(*vs100comntools);
+ else if (llvm::Optional<std::string> vs90comntools =
+ llvm::sys::Process::GetEnv("VS90COMNTOOLS"))
+ vcomntools = std::move(*vs90comntools);
+ else if (llvm::Optional<std::string> vs80comntools =
+ llvm::sys::Process::GetEnv("VS80COMNTOOLS"))
+ vcomntools = std::move(*vs80comntools);
+
+ // Find any version we can.
+ if (!vcomntools.empty()) {
+ size_t p = vcomntools.find("\\Common7\\Tools");
+ if (p != std::string::npos)
+ vcomntools.resize(p);
+ path = std::move(vcomntools);
return true;
}
return false;
@@ -592,9 +603,10 @@ void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
return;
// Honor %INCLUDE%. It should know essential search paths with vcvarsall.bat.
- if (const char *cl_include_dir = getenv("INCLUDE")) {
+ if (llvm::Optional<std::string> cl_include_dir =
+ llvm::sys::Process::GetEnv("INCLUDE")) {
SmallVector<StringRef, 8> Dirs;
- StringRef(cl_include_dir)
+ StringRef(*cl_include_dir)
.split(Dirs, ";", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
for (StringRef Dir : Dirs)
addSystemInclude(DriverArgs, CC1Args, Dir);
@@ -646,6 +658,7 @@ void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
return;
}
+#if defined(LLVM_ON_WIN32)
// As a fallback, select default install paths.
// FIXME: Don't guess drives and paths like this on Windows.
const StringRef Paths[] = {
@@ -656,6 +669,7 @@ void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
"C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include"
};
addSystemIncludes(DriverArgs, CC1Args, Paths);
+#endif
}
void MSVCToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
@@ -663,21 +677,34 @@ void MSVCToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
// FIXME: There should probably be logic here to find libc++ on Windows.
}
+VersionTuple MSVCToolChain::computeMSVCVersion(const Driver *D,
+ const ArgList &Args) const {
+ bool IsWindowsMSVC = getTriple().isWindowsMSVCEnvironment();
+ VersionTuple MSVT = ToolChain::computeMSVCVersion(D, Args);
+ if (MSVT.empty()) MSVT = getMSVCVersionFromTriple();
+ if (MSVT.empty() && IsWindowsMSVC) MSVT = getMSVCVersionFromExe();
+ if (MSVT.empty() &&
+ Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
+ IsWindowsMSVC)) {
+ // -fms-compatibility-version=18.00 is default.
+ // FIXME: Consider bumping this to 19 (MSVC2015) soon.
+ MSVT = VersionTuple(18);
+ }
+ return MSVT;
+}
+
std::string
MSVCToolChain::ComputeEffectiveClangTriple(const ArgList &Args,
types::ID InputType) const {
- std::string TripleStr =
- ToolChain::ComputeEffectiveClangTriple(Args, InputType);
- llvm::Triple Triple(TripleStr);
- VersionTuple MSVT =
- tools::visualstudio::getMSVCVersion(/*D=*/nullptr, *this, Triple, Args,
- /*IsWindowsMSVC=*/true);
- if (MSVT.empty())
- return TripleStr;
-
+ // The MSVC version doesn't care about the architecture, even though it
+ // may look at the triple internally.
+ VersionTuple MSVT = computeMSVCVersion(/*D=*/nullptr, Args);
MSVT = VersionTuple(MSVT.getMajor(), MSVT.getMinor().getValueOr(0),
MSVT.getSubminor().getValueOr(0));
+ // For the rest of the triple, however, a computed architecture name may
+ // be needed.
+ llvm::Triple Triple(ToolChain::ComputeEffectiveClangTriple(Args, InputType));
if (Triple.getEnvironment() == llvm::Triple::MSVC) {
StringRef ObjFmt = Triple.getEnvironmentName().split('-').second;
if (ObjFmt.empty())
@@ -806,7 +833,7 @@ static void TranslateDArg(Arg *A, llvm::opt::DerivedArgList &DAL,
llvm::opt::DerivedArgList *
MSVCToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
- const char *BoundArch) const {
+ StringRef BoundArch, Action::OffloadKind) const {
DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
const OptTable &Opts = getDriver().getOpts();
diff --git a/lib/Driver/Multilib.cpp b/lib/Driver/Multilib.cpp
index 34ad6a7efb24..a88edf7f04e3 100644
--- a/lib/Driver/Multilib.cpp
+++ b/lib/Driver/Multilib.cpp
@@ -13,12 +13,10 @@
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
-#include "llvm/ADT/Triple.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/OptTable.h"
#include "llvm/Option/Option.h"
-#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Regex.h"
#include "llvm/Support/YAMLParser.h"
diff --git a/lib/Driver/SanitizerArgs.cpp b/lib/Driver/SanitizerArgs.cpp
index 30cc3f45c9e0..f4f6dad9f287 100644
--- a/lib/Driver/SanitizerArgs.cpp
+++ b/lib/Driver/SanitizerArgs.cpp
@@ -49,8 +49,11 @@ enum CoverageFeature {
CoverageIndirCall = 1 << 3,
CoverageTraceBB = 1 << 4,
CoverageTraceCmp = 1 << 5,
- Coverage8bitCounters = 1 << 6,
- CoverageTracePC = 1 << 7,
+ CoverageTraceDiv = 1 << 6,
+ CoverageTraceGep = 1 << 7,
+ Coverage8bitCounters = 1 << 8,
+ CoverageTracePC = 1 << 9,
+ CoverageTracePCGuard = 1 << 10,
};
/// Parse a -fsanitize= or -fno-sanitize= argument's values, diagnosing any
@@ -162,7 +165,8 @@ bool SanitizerArgs::needsUbsanRt() const {
return ((Sanitizers.Mask & NeedsUbsanRt & ~TrapSanitizers.Mask) ||
CoverageFeatures) &&
!Sanitizers.has(Address) && !Sanitizers.has(Memory) &&
- !Sanitizers.has(Thread) && !Sanitizers.has(DataFlow) && !CfiCrossDso;
+ !Sanitizers.has(Thread) && !Sanitizers.has(DataFlow) &&
+ !Sanitizers.has(Leak) && !CfiCrossDso;
}
bool SanitizerArgs::needsCfiRt() const {
@@ -434,6 +438,18 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
TC.getTriple().getArch() == llvm::Triple::x86_64);
}
+ if (AllAddedKinds & Thread) {
+ TsanMemoryAccess = Args.hasFlag(options::OPT_fsanitize_thread_memory_access,
+ options::OPT_fno_sanitize_thread_memory_access,
+ TsanMemoryAccess);
+ TsanFuncEntryExit = Args.hasFlag(options::OPT_fsanitize_thread_func_entry_exit,
+ options::OPT_fno_sanitize_thread_func_entry_exit,
+ TsanFuncEntryExit);
+ TsanAtomics = Args.hasFlag(options::OPT_fsanitize_thread_atomics,
+ options::OPT_fno_sanitize_thread_atomics,
+ TsanAtomics);
+ }
+
if (AllAddedKinds & CFI) {
CfiCrossDso = Args.hasFlag(options::OPT_fsanitize_cfi_cross_dso,
options::OPT_fno_sanitize_cfi_cross_dso, false);
@@ -524,7 +540,7 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
<< "-fsanitize-coverage=8bit-counters"
<< "-fsanitize-coverage=(func|bb|edge)";
// trace-pc w/o func/bb/edge implies edge.
- if ((CoverageFeatures & CoverageTracePC) &&
+ if ((CoverageFeatures & (CoverageTracePC | CoverageTracePCGuard)) &&
!(CoverageFeatures & CoverageTypes))
CoverageFeatures |= CoverageEdge;
@@ -556,14 +572,13 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
D.Diag(clang::diag::note_drv_address_sanitizer_debug_runtime);
}
}
- }
- AsanUseAfterScope =
- Args.hasArg(options::OPT_fsanitize_address_use_after_scope);
- if (AsanUseAfterScope && !(AllAddedKinds & Address)) {
- D.Diag(clang::diag::err_drv_argument_only_allowed_with)
- << "-fsanitize-address-use-after-scope"
- << "-fsanitize=address";
+ if (Arg *A = Args.getLastArg(
+ options::OPT_fsanitize_address_use_after_scope,
+ options::OPT_fno_sanitize_address_use_after_scope)) {
+ AsanUseAfterScope = A->getOption().getID() ==
+ options::OPT_fsanitize_address_use_after_scope;
+ }
}
// Parse -link-cxx-sanitizer flag.
@@ -605,6 +620,12 @@ static void addIncludeLinkerOption(const ToolChain &TC,
void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs,
types::ID InputType) const {
+ // NVPTX doesn't currently support sanitizers. Bailing out here means that
+ // e.g. -fsanitize=address applies only to host code, which is what we want
+ // for now.
+ if (TC.getTriple().isNVPTX())
+ return;
+
// Translate available CoverageFeatures to corresponding clang-cc1 flags.
// Do it even if Sanitizers.empty() since some forms of coverage don't require
// sanitizers.
@@ -615,8 +636,11 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
std::make_pair(CoverageIndirCall, "-fsanitize-coverage-indirect-calls"),
std::make_pair(CoverageTraceBB, "-fsanitize-coverage-trace-bb"),
std::make_pair(CoverageTraceCmp, "-fsanitize-coverage-trace-cmp"),
+ std::make_pair(CoverageTraceDiv, "-fsanitize-coverage-trace-div"),
+ std::make_pair(CoverageTraceGep, "-fsanitize-coverage-trace-gep"),
std::make_pair(Coverage8bitCounters, "-fsanitize-coverage-8bit-counters"),
- std::make_pair(CoverageTracePC, "-fsanitize-coverage-trace-pc")};
+ std::make_pair(CoverageTracePC, "-fsanitize-coverage-trace-pc"),
+ std::make_pair(CoverageTracePCGuard, "-fsanitize-coverage-trace-pc-guard")};
for (auto F : CoverageFlags) {
if (CoverageFeatures & F.first)
CmdArgs.push_back(Args.MakeArgString(F.second));
@@ -674,6 +698,22 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
if (MsanUseAfterDtor)
CmdArgs.push_back(Args.MakeArgString("-fsanitize-memory-use-after-dtor"));
+ // FIXME: Pass these parameters as function attributes, not as -llvm flags.
+ if (!TsanMemoryAccess) {
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back("-tsan-instrument-memory-accesses=0");
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back("-tsan-instrument-memintrinsics=0");
+ }
+ if (!TsanFuncEntryExit) {
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back("-tsan-instrument-func-entry-exit=0");
+ }
+ if (!TsanAtomics) {
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back("-tsan-instrument-atomics=0");
+ }
+
if (CfiCrossDso)
CmdArgs.push_back(Args.MakeArgString("-fsanitize-cfi-cross-dso"));
@@ -752,8 +792,11 @@ int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A) {
.Case("indirect-calls", CoverageIndirCall)
.Case("trace-bb", CoverageTraceBB)
.Case("trace-cmp", CoverageTraceCmp)
+ .Case("trace-div", CoverageTraceDiv)
+ .Case("trace-gep", CoverageTraceGep)
.Case("8bit-counters", Coverage8bitCounters)
.Case("trace-pc", CoverageTracePC)
+ .Case("trace-pc-guard", CoverageTracePCGuard)
.Default(0);
if (F == 0)
D.Diag(clang::diag::err_drv_unsupported_option_argument)
diff --git a/lib/Driver/Tool.cpp b/lib/Driver/Tool.cpp
index 7142e822f16e..818494662179 100644
--- a/lib/Driver/Tool.cpp
+++ b/lib/Driver/Tool.cpp
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Driver/Tool.h"
+#include "InputInfo.h"
using namespace clang::driver;
@@ -21,3 +22,12 @@ Tool::Tool(const char *_Name, const char *_ShortName, const ToolChain &TC,
Tool::~Tool() {
}
+
+void Tool::ConstructJobMultipleOutputs(Compilation &C, const JobAction &JA,
+ const InputInfoList &Outputs,
+ const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const {
+ assert(Outputs.size() == 1 && "Expected only one output by default!");
+ ConstructJob(C, JA, Outputs.front(), Inputs, TCArgs, LinkingOutput);
+}
diff --git a/lib/Driver/ToolChain.cpp b/lib/Driver/ToolChain.cpp
index e96688cbaf81..6adc0386ee7b 100644
--- a/lib/Driver/ToolChain.cpp
+++ b/lib/Driver/ToolChain.cpp
@@ -7,6 +7,7 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/Driver/ToolChain.h"
#include "Tools.h"
#include "clang/Basic/ObjCRuntime.h"
#include "clang/Config/config.h"
@@ -15,16 +16,15 @@
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/SanitizerArgs.h"
-#include "clang/Driver/ToolChain.h"
#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/StringSwitch.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/Option.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Support/Path.h"
#include "llvm/Support/TargetParser.h"
+#include "llvm/Support/TargetRegistry.h"
using namespace clang::driver;
using namespace clang::driver::tools;
@@ -68,7 +68,8 @@ static ToolChain::RTTIMode CalculateRTTIMode(const ArgList &Args,
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)) {
+ CachedRTTIMode(CalculateRTTIMode(Args, Triple, CachedRTTIArg)),
+ EffectiveTriple() {
if (Arg *A = Args.getLastArg(options::OPT_mthread_model))
if (!isThreadModelSupported(A->getValue()))
D.Diag(diag::err_drv_invalid_thread_model_for_target)
@@ -238,6 +239,12 @@ Tool *ToolChain::getLink() const {
return Link.get();
}
+Tool *ToolChain::getOffloadBundler() const {
+ if (!OffloadBundler)
+ OffloadBundler.reset(new tools::OffloadBundler(*this));
+ return OffloadBundler.get();
+}
+
Tool *ToolChain::getTool(Action::ActionClass AC) const {
switch (AC) {
case Action::AssembleJobClass:
@@ -262,6 +269,10 @@ Tool *ToolChain::getTool(Action::ActionClass AC) const {
case Action::VerifyPCHJobClass:
case Action::BackendJobClass:
return getClang();
+
+ case Action::OffloadBundlingJobClass:
+ case Action::OffloadUnbundlingJobClass:
+ return getOffloadBundler();
}
llvm_unreachable("Invalid tool kind.");
@@ -340,36 +351,34 @@ std::string ToolChain::GetProgramPath(const char *Name) const {
}
std::string ToolChain::GetLinkerPath() const {
- if (Arg *A = Args.getLastArg(options::OPT_fuse_ld_EQ)) {
- StringRef UseLinker = A->getValue();
-
- if (llvm::sys::path::is_absolute(UseLinker)) {
- // If we're passed -fuse-ld= with what looks like an absolute path,
- // don't attempt to second-guess that.
- if (llvm::sys::fs::exists(UseLinker))
- return UseLinker;
- } else {
- // If we're passed -fuse-ld= with no argument, or with the argument ld,
- // then use whatever the default system linker is.
- if (UseLinker.empty() || UseLinker == "ld")
- return GetProgramPath("ld");
-
- llvm::SmallString<8> LinkerName("ld.");
- LinkerName.append(UseLinker);
-
- std::string LinkerPath(GetProgramPath(LinkerName.c_str()));
- if (llvm::sys::fs::exists(LinkerPath))
- return LinkerPath;
- }
+ const Arg* A = Args.getLastArg(options::OPT_fuse_ld_EQ);
+ StringRef UseLinker = A ? A->getValue() : CLANG_DEFAULT_LINKER;
+
+ 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))
+ return UseLinker;
+ } else if (UseLinker.empty() || UseLinker == "ld") {
+ // If we're passed -fuse-ld= with no argument, or with the argument ld,
+ // then use whatever the default system linker is.
+ return GetProgramPath(getDefaultLinker());
+ } else {
+ llvm::SmallString<8> LinkerName("ld.");
+ LinkerName.append(UseLinker);
+
+ std::string LinkerPath(GetProgramPath(LinkerName.c_str()));
+ if (llvm::sys::fs::exists(LinkerPath))
+ return LinkerPath;
+ }
+ if (A)
getDriver().Diag(diag::err_drv_invalid_linker_name) << A->getAsString(Args);
- return "";
- }
- return GetProgramPath(DefaultLinker);
+ return GetProgramPath(getDefaultLinker());
}
-types::ID ToolChain::LookupTypeForExtension(const char *Ext) const {
+types::ID ToolChain::LookupTypeForExtension(StringRef Ext) const {
return types::lookupTypeForExtension(Ext);
}
@@ -487,8 +496,10 @@ std::string ToolChain::ComputeLLVMTriple(const ArgList &Args,
ArchName = "arm";
// Assembly files should start in ARM mode, unless arch is M-profile.
+ // Windows is always thumb.
if ((InputType != types::TY_PP_Asm && Args.hasFlag(options::OPT_mthumb,
- options::OPT_mno_thumb, ThumbDefault)) || IsMProfile) {
+ options::OPT_mno_thumb, ThumbDefault)) || IsMProfile ||
+ getTriple().isOSWindows()) {
if (IsBigEndian)
ArchName = "thumbeb";
else
@@ -526,54 +537,39 @@ void ToolChain::addProfileRTLibs(const llvm::opt::ArgList &Args,
ToolChain::RuntimeLibType ToolChain::GetRuntimeLibType(
const ArgList &Args) const {
- if (Arg *A = Args.getLastArg(options::OPT_rtlib_EQ)) {
- StringRef Value = A->getValue();
- if (Value == "compiler-rt")
- return ToolChain::RLT_CompilerRT;
- if (Value == "libgcc")
- return ToolChain::RLT_Libgcc;
- getDriver().Diag(diag::err_drv_invalid_rtlib_name)
- << A->getAsString(Args);
- }
+ const Arg* A = Args.getLastArg(options::OPT_rtlib_EQ);
+ StringRef LibName = A ? A->getValue() : CLANG_DEFAULT_RTLIB;
- return GetDefaultRuntimeLibType();
-}
+ // Only use "platform" in tests to override CLANG_DEFAULT_RTLIB!
+ if (LibName == "compiler-rt")
+ return ToolChain::RLT_CompilerRT;
+ else if (LibName == "libgcc")
+ return ToolChain::RLT_Libgcc;
+ else if (LibName == "platform")
+ return GetDefaultRuntimeLibType();
-static bool ParseCXXStdlibType(const StringRef& Name,
- ToolChain::CXXStdlibType& Type) {
- if (Name == "libc++")
- Type = ToolChain::CST_Libcxx;
- else if (Name == "libstdc++")
- Type = ToolChain::CST_Libstdcxx;
- else
- return false;
+ if (A)
+ getDriver().Diag(diag::err_drv_invalid_rtlib_name) << A->getAsString(Args);
- return true;
+ return GetDefaultRuntimeLibType();
}
ToolChain::CXXStdlibType ToolChain::GetCXXStdlibType(const ArgList &Args) const{
- ToolChain::CXXStdlibType Type;
- bool HasValidType = false;
- bool ForcePlatformDefault = false;
-
const Arg *A = Args.getLastArg(options::OPT_stdlib_EQ);
- if (A) {
- StringRef Value = A->getValue();
- HasValidType = ParseCXXStdlibType(Value, Type);
-
- // Only use in tests to override CLANG_DEFAULT_CXX_STDLIB!
- if (Value == "platform")
- ForcePlatformDefault = true;
- else if (!HasValidType)
- getDriver().Diag(diag::err_drv_invalid_stdlib_name)
- << A->getAsString(Args);
- }
+ StringRef LibName = A ? A->getValue() : CLANG_DEFAULT_CXX_STDLIB;
+
+ // Only use "platform" in tests to override CLANG_DEFAULT_CXX_STDLIB!
+ if (LibName == "libc++")
+ return ToolChain::CST_Libcxx;
+ else if (LibName == "libstdc++")
+ return ToolChain::CST_Libstdcxx;
+ else if (LibName == "platform")
+ return GetDefaultCXXStdlibType();
- if (!HasValidType && (ForcePlatformDefault ||
- !ParseCXXStdlibType(CLANG_DEFAULT_CXX_STDLIB, Type)))
- Type = GetDefaultCXXStdlibType();
+ if (A)
+ getDriver().Diag(diag::err_drv_invalid_stdlib_name) << A->getAsString(Args);
- return Type;
+ return GetDefaultCXXStdlibType();
}
/// \brief Utility function to add a system include directory to CC1 arguments.
@@ -688,7 +684,11 @@ SanitizerMask ToolChain::getSupportedSanitizers() const {
SanitizerMask Res = (Undefined & ~Vptr & ~Function) | (CFI & ~CFIICall) |
CFICastStrict | UnsignedIntegerOverflow | LocalBounds;
if (getTriple().getArch() == llvm::Triple::x86 ||
- getTriple().getArch() == llvm::Triple::x86_64)
+ getTriple().getArch() == llvm::Triple::x86_64 ||
+ getTriple().getArch() == llvm::Triple::arm ||
+ getTriple().getArch() == llvm::Triple::aarch64 ||
+ getTriple().getArch() == llvm::Triple::wasm32 ||
+ getTriple().getArch() == llvm::Triple::wasm64)
Res |= CFIICall;
return Res;
}
@@ -698,3 +698,57 @@ void ToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs,
void ToolChain::AddIAMCUIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {}
+
+static VersionTuple separateMSVCFullVersion(unsigned Version) {
+ if (Version < 100)
+ return VersionTuple(Version);
+
+ if (Version < 10000)
+ return VersionTuple(Version / 100, Version % 100);
+
+ unsigned Build = 0, Factor = 1;
+ for (; Version > 10000; Version = Version / 10, Factor = Factor * 10)
+ Build = Build + (Version % 10) * Factor;
+ return VersionTuple(Version / 100, Version % 100, Build);
+}
+
+VersionTuple
+ToolChain::computeMSVCVersion(const Driver *D,
+ const llvm::opt::ArgList &Args) const {
+ const Arg *MSCVersion = Args.getLastArg(options::OPT_fmsc_version);
+ const Arg *MSCompatibilityVersion =
+ Args.getLastArg(options::OPT_fms_compatibility_version);
+
+ if (MSCVersion && MSCompatibilityVersion) {
+ if (D)
+ D->Diag(diag::err_drv_argument_not_allowed_with)
+ << MSCVersion->getAsString(Args)
+ << MSCompatibilityVersion->getAsString(Args);
+ return VersionTuple();
+ }
+
+ if (MSCompatibilityVersion) {
+ VersionTuple MSVT;
+ if (MSVT.tryParse(MSCompatibilityVersion->getValue())) {
+ if (D)
+ D->Diag(diag::err_drv_invalid_value)
+ << MSCompatibilityVersion->getAsString(Args)
+ << MSCompatibilityVersion->getValue();
+ } else {
+ return MSVT;
+ }
+ }
+
+ if (MSCVersion) {
+ unsigned Version = 0;
+ if (StringRef(MSCVersion->getValue()).getAsInteger(10, Version)) {
+ if (D)
+ D->Diag(diag::err_drv_invalid_value)
+ << MSCVersion->getAsString(Args) << MSCVersion->getValue();
+ } else {
+ return separateMSVCFullVersion(Version);
+ }
+ }
+
+ return VersionTuple();
+}
diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp
index 1b02f467c141..968b0cb4724a 100644
--- a/lib/Driver/ToolChains.cpp
+++ b/lib/Driver/ToolChains.cpp
@@ -14,6 +14,7 @@
#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Config/config.h" // for GCC_INSTALL_PREFIX
#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"
@@ -52,9 +53,10 @@ MachO::MachO(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
/// Darwin - Darwin tool chain for i386 and x86_64.
Darwin::Darwin(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
- : MachO(D, Triple, Args), TargetInitialized(false) {}
+ : MachO(D, Triple, Args), TargetInitialized(false),
+ CudaInstallation(D, Triple, Args) {}
-types::ID MachO::LookupTypeForExtension(const char *Ext) const {
+types::ID MachO::LookupTypeForExtension(StringRef Ext) const {
types::ID Ty = types::lookupTypeForExtension(Ext);
// Darwin always preprocesses assembly files (unless -x is used explicitly).
@@ -99,6 +101,11 @@ bool Darwin::hasBlocksRuntime() const {
}
}
+void Darwin::AddCudaIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args);
+}
+
// This is just a MachO name translation routine and there's no
// way to join this into ARMTargetParser without breaking all
// other assumptions. Maybe MachO should consider standardising
@@ -176,13 +183,6 @@ Darwin::~Darwin() {}
MachO::~MachO() {}
-std::string MachO::ComputeEffectiveClangTriple(const ArgList &Args,
- types::ID InputType) const {
- llvm::Triple Triple(ComputeLLVMTriple(Args, InputType));
-
- return Triple.getTriple();
-}
-
std::string Darwin::ComputeEffectiveClangTriple(const ArgList &Args,
types::ID InputType) const {
llvm::Triple Triple(ComputeLLVMTriple(Args, InputType));
@@ -296,6 +296,14 @@ void DarwinClang::AddLinkARCArgs(const ArgList &Args,
CmdArgs.push_back(Args.MakeArgString(P));
}
+unsigned DarwinClang::GetDefaultDwarfVersion() const {
+ // Default to use DWARF 2 on OS X 10.10 / iOS 8 and lower.
+ if ((isTargetMacOS() && isMacosxVersionLT(10, 11)) ||
+ (isTargetIOSBased() && isIPhoneOSVersionLT(9)))
+ return 2;
+ return 4;
+}
+
void MachO::AddLinkRuntimeLib(const ArgList &Args, ArgStringList &CmdArgs,
StringRef DarwinLibName, bool AlwaysLink,
bool IsEmbedded, bool AddRPath) const {
@@ -400,17 +408,22 @@ void DarwinClang::AddLinkSanitizerLibArgs(const ArgList &Args,
/*AddRPath*/ true);
}
+ToolChain::RuntimeLibType DarwinClang::GetRuntimeLibType(
+ const ArgList &Args) const {
+ if (Arg* A = Args.getLastArg(options::OPT_rtlib_EQ)) {
+ StringRef Value = A->getValue();
+ if (Value != "compiler-rt")
+ getDriver().Diag(diag::err_drv_unsupported_rtlib_for_platform)
+ << Value << "darwin";
+ }
+
+ return ToolChain::RLT_CompilerRT;
+}
+
void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
- // Darwin only supports the compiler-rt based runtime libraries.
- switch (GetRuntimeLibType(Args)) {
- case ToolChain::RLT_CompilerRT:
- break;
- default:
- getDriver().Diag(diag::err_drv_unsupported_rtlib_for_platform)
- << Args.getLastArg(options::OPT_rtlib_EQ)->getValue() << "darwin";
- return;
- }
+ // Call once to ensure diagnostic is printed if wrong value was specified
+ GetRuntimeLibType(Args);
// Darwin doesn't support real static executables, don't link any runtime
// libraries with -static.
@@ -803,7 +816,8 @@ void DarwinClang::AddCCKextLibArgs(const ArgList &Args,
}
DerivedArgList *MachO::TranslateArgs(const DerivedArgList &Args,
- const char *BoundArch) const {
+ StringRef BoundArch,
+ Action::OffloadKind) const {
DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
const OptTable &Opts = getDriver().getOpts();
@@ -821,7 +835,7 @@ DerivedArgList *MachO::TranslateArgs(const DerivedArgList &Args,
llvm::Triple::ArchType XarchArch =
tools::darwin::getArchTypeForMachOArchName(A->getValue(0));
if (!(XarchArch == getArch() ||
- (BoundArch &&
+ (!BoundArch.empty() &&
XarchArch ==
tools::darwin::getArchTypeForMachOArchName(BoundArch))))
continue;
@@ -937,7 +951,7 @@ DerivedArgList *MachO::TranslateArgs(const DerivedArgList &Args,
// Add the arch options based on the particular spelling of -arch, to match
// how the driver driver works.
- if (BoundArch) {
+ if (!BoundArch.empty()) {
StringRef Name = BoundArch;
const Option MCpu = Opts.getOption(options::OPT_mcpu_EQ);
const Option MArch = Opts.getOption(options::OPT_march_EQ);
@@ -1032,14 +1046,16 @@ void MachO::AddLinkRuntimeLibArgs(const ArgList &Args,
AddLinkRuntimeLib(Args, CmdArgs, CompilerRT, false, true);
}
-DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args,
- const char *BoundArch) const {
+DerivedArgList *
+Darwin::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch,
+ Action::OffloadKind DeviceOffloadKind) const {
// First get the generic Apple args, before moving onto Darwin-specific ones.
- DerivedArgList *DAL = MachO::TranslateArgs(Args, BoundArch);
+ DerivedArgList *DAL =
+ MachO::TranslateArgs(Args, BoundArch, DeviceOffloadKind);
const OptTable &Opts = getDriver().getOpts();
// If no architecture is bound, none of the translations here are relevant.
- if (!BoundArch)
+ if (BoundArch.empty())
return DAL;
// Add an explicit version min argument for the deployment target. We do this
@@ -1087,6 +1103,18 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args,
}
}
+ auto Arch = tools::darwin::getArchTypeForMachOArchName(BoundArch);
+ if ((Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb)) {
+ if (Args.hasFlag(options::OPT_fomit_frame_pointer,
+ options::OPT_fno_omit_frame_pointer, false))
+ getDriver().Diag(clang::diag::warn_drv_unsupported_opt_for_target)
+ << "-fomit-frame-pointer" << BoundArch;
+ if (Args.hasFlag(options::OPT_momit_leaf_frame_pointer,
+ options::OPT_mno_omit_leaf_frame_pointer, false))
+ getDriver().Diag(clang::diag::warn_drv_unsupported_opt_for_target)
+ << "-momit-leaf-frame-pointer" << BoundArch;
+ }
+
return DAL;
}
@@ -1275,6 +1303,10 @@ SanitizerMask Darwin::getSupportedSanitizers() const {
return Res;
}
+void Darwin::printVerboseInfo(raw_ostream &OS) const {
+ CudaInstallation.print(OS);
+}
+
/// Generic_GCC - A tool chain using the 'gcc' command to perform
/// all subcommands; this relies on gcc translating the majority of
/// command line options.
@@ -1420,6 +1452,25 @@ void Generic_GCC::GCCInstallationDetector::init(
}
}
+ // Try to respect gcc-config on Gentoo. However, do that only
+ // if --gcc-toolchain is not provided or equal to the Gentoo install
+ // 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;
+ }
+ }
+
// Loop over the various components which exist and select the best GCC
// installation available. GCC installs are ranked by version number.
Version = GCCVersion::Parse("0.0.0");
@@ -1518,8 +1569,8 @@ bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const {
"mips-mti-linux-gnu",
"mips-img-linux-gnu"};
static const char *const MIPSELLibDirs[] = {"/lib"};
- static const char *const MIPSELTriples[] = {
- "mipsel-linux-gnu", "mipsel-linux-android", "mips-img-linux-gnu"};
+ static const char *const MIPSELTriples[] = {"mipsel-linux-gnu",
+ "mips-img-linux-gnu"};
static const char *const MIPS64LibDirs[] = {"/lib64", "/lib"};
static const char *const MIPS64Triples[] = {
@@ -1528,7 +1579,15 @@ bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const {
static const char *const MIPS64ELLibDirs[] = {"/lib64", "/lib"};
static const char *const MIPS64ELTriples[] = {
"mips64el-linux-gnu", "mips-mti-linux-gnu", "mips-img-linux-gnu",
- "mips64el-linux-android", "mips64el-linux-gnuabi64"};
+ "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[] = {
@@ -1630,11 +1689,22 @@ bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const {
BiarchTripleAliases.append(begin(MIPS64Triples), end(MIPS64Triples));
break;
case llvm::Triple::mipsel:
- 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));
+ 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));
+ }
break;
case llvm::Triple::mips64:
LibDirs.append(begin(MIPS64LibDirs), end(MIPS64LibDirs));
@@ -1643,11 +1713,23 @@ bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const {
BiarchTripleAliases.append(begin(MIPSTriples), end(MIPSTriples));
break;
case llvm::Triple::mips64el:
- 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));
+ 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));
+ }
break;
case llvm::Triple::ppc:
LibDirs.append(begin(PPCLibDirs), end(PPCLibDirs));
@@ -1706,8 +1788,8 @@ static CudaVersion ParseCudaVersionFile(llvm::StringRef V) {
int Major = -1, Minor = -1;
auto First = V.split('.');
auto Second = First.second.split('.');
- if (!First.first.getAsInteger(10, Major) ||
- !Second.first.getAsInteger(10, Minor))
+ if (First.first.getAsInteger(10, Major) ||
+ Second.first.getAsInteger(10, Minor))
return CudaVersion::UNKNOWN;
if (Major == 7 && Minor == 0) {
@@ -1722,10 +1804,10 @@ static CudaVersion ParseCudaVersionFile(llvm::StringRef V) {
return CudaVersion::UNKNOWN;
}
-// \brief -- try common CUDA installation paths looking for files we need for
-// CUDA compilation.
-void Generic_GCC::CudaInstallationDetector::init(
- const llvm::Triple &TargetTriple, const llvm::opt::ArgList &Args) {
+CudaInstallationDetector::CudaInstallationDetector(
+ const Driver &D, const llvm::Triple &TargetTriple,
+ const llvm::opt::ArgList &Args)
+ : D(D) {
SmallVector<std::string, 4> CudaPathCandidates;
if (Args.hasArg(options::OPT_cuda_path_EQ))
@@ -1733,8 +1815,7 @@ void Generic_GCC::CudaInstallationDetector::init(
Args.getLastArgValue(options::OPT_cuda_path_EQ));
else {
CudaPathCandidates.push_back(D.SysRoot + "/usr/local/cuda");
- // FIXME: Uncomment this once we can compile the cuda 8 headers.
- // CudaPathCandidates.push_back(D.SysRoot + "/usr/local/cuda-8.0");
+ CudaPathCandidates.push_back(D.SysRoot + "/usr/local/cuda-8.0");
CudaPathCandidates.push_back(D.SysRoot + "/usr/local/cuda-7.5");
CudaPathCandidates.push_back(D.SysRoot + "/usr/local/cuda-7.0");
}
@@ -1747,13 +1828,35 @@ void Generic_GCC::CudaInstallationDetector::init(
BinPath = CudaPath + "/bin";
IncludePath = InstallPath + "/include";
LibDevicePath = InstallPath + "/nvvm/libdevice";
- LibPath = InstallPath + (TargetTriple.isArch64Bit() ? "/lib64" : "/lib");
auto &FS = D.getVFS();
- if (!(FS.exists(IncludePath) && FS.exists(BinPath) && FS.exists(LibPath) &&
+ if (!(FS.exists(IncludePath) && FS.exists(BinPath) &&
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.
+ //
+ // It's sufficient for our purposes to be flexible: If both lib and lib64
+ // exist, we choose whichever one matches our triple. Otherwise, if only
+ // lib exists, we use it.
+ if (TargetTriple.isArch64Bit() && FS.exists(InstallPath + "/lib64"))
+ LibPath = InstallPath + "/lib64";
+ else if (FS.exists(InstallPath + "/lib"))
+ LibPath = InstallPath + "/lib";
+ else
+ continue;
+
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> VersionFile =
+ FS.getBufferForFile(InstallPath + "/version.txt");
+ if (!VersionFile) {
+ // CUDA 7.0 doesn't have a version.txt, so guess that's our version if
+ // version.txt isn't present.
+ Version = CudaVersion::CUDA_70;
+ } else {
+ Version = ParseCudaVersionFile((*VersionFile)->getBuffer());
+ }
+
std::error_code EC;
for (llvm::sys::fs::directory_iterator LI(LibDevicePath, EC), LE;
!EC && LI != LE; LI = LI.increment(EC)) {
@@ -1766,42 +1869,67 @@ void Generic_GCC::CudaInstallationDetector::init(
StringRef GpuArch = FileName.slice(
LibDeviceName.size(), FileName.find('.', LibDeviceName.size()));
LibDeviceMap[GpuArch] = FilePath.str();
- // Insert map entries for specifc devices with this compute capability.
+ // Insert map entries for specifc devices with this compute
+ // capability. NVCC's choice of the libdevice library version is
+ // rather peculiar and depends on the CUDA version.
if (GpuArch == "compute_20") {
LibDeviceMap["sm_20"] = FilePath;
LibDeviceMap["sm_21"] = FilePath;
+ LibDeviceMap["sm_32"] = FilePath;
} else if (GpuArch == "compute_30") {
LibDeviceMap["sm_30"] = FilePath;
- LibDeviceMap["sm_32"] = FilePath;
+ if (Version < CudaVersion::CUDA_80) {
+ LibDeviceMap["sm_50"] = FilePath;
+ LibDeviceMap["sm_52"] = FilePath;
+ LibDeviceMap["sm_53"] = FilePath;
+ }
+ LibDeviceMap["sm_60"] = FilePath;
+ LibDeviceMap["sm_61"] = FilePath;
+ LibDeviceMap["sm_62"] = FilePath;
} else if (GpuArch == "compute_35") {
LibDeviceMap["sm_35"] = FilePath;
LibDeviceMap["sm_37"] = FilePath;
} else if (GpuArch == "compute_50") {
- LibDeviceMap["sm_50"] = FilePath;
- LibDeviceMap["sm_52"] = FilePath;
- LibDeviceMap["sm_53"] = FilePath;
- LibDeviceMap["sm_60"] = FilePath;
- LibDeviceMap["sm_61"] = FilePath;
- LibDeviceMap["sm_62"] = FilePath;
+ if (Version >= CudaVersion::CUDA_80) {
+ LibDeviceMap["sm_50"] = FilePath;
+ LibDeviceMap["sm_52"] = FilePath;
+ LibDeviceMap["sm_53"] = FilePath;
+ }
}
}
- llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> VersionFile =
- FS.getBufferForFile(InstallPath + "/version.txt");
- if (!VersionFile) {
- // CUDA 7.0 doesn't have a version.txt, so guess that's our version if
- // version.txt isn't present.
- Version = CudaVersion::CUDA_70;
- } else {
- Version = ParseCudaVersionFile((*VersionFile)->getBuffer());
- }
-
IsValid = true;
break;
}
}
-void Generic_GCC::CudaInstallationDetector::CheckCudaVersionSupportsArch(
+void CudaInstallationDetector::AddCudaIncludeArgs(
+ const ArgList &DriverArgs, ArgStringList &CC1Args) const {
+ if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
+ // Add cuda_wrappers/* to our system include path. This lets us wrap
+ // standard library headers.
+ SmallString<128> P(D.ResourceDir);
+ llvm::sys::path::append(P, "include");
+ llvm::sys::path::append(P, "cuda_wrappers");
+ CC1Args.push_back("-internal-isystem");
+ CC1Args.push_back(DriverArgs.MakeArgString(P));
+ }
+
+ if (DriverArgs.hasArg(options::OPT_nocudainc))
+ return;
+
+ if (!isValid()) {
+ D.Diag(diag::err_drv_no_cuda_installation);
+ return;
+ }
+
+ CC1Args.push_back("-internal-isystem");
+ CC1Args.push_back(DriverArgs.MakeArgString(getIncludePath()));
+ CC1Args.push_back("-include");
+ CC1Args.push_back("__clang_cuda_runtime_wrapper.h");
+}
+
+void CudaInstallationDetector::CheckCudaVersionSupportsArch(
CudaArch Arch) const {
if (Arch == CudaArch::UNKNOWN || Version == CudaVersion::UNKNOWN ||
ArchsWithVersionTooLowErrors.count(Arch) > 0)
@@ -1816,7 +1944,7 @@ void Generic_GCC::CudaInstallationDetector::CheckCudaVersionSupportsArch(
}
}
-void Generic_GCC::CudaInstallationDetector::print(raw_ostream &OS) const {
+void CudaInstallationDetector::print(raw_ostream &OS) const {
if (isValid())
OS << "Found CUDA installation: " << InstallPath << ", version "
<< CudaVersionToString(Version) << "\n";
@@ -1985,7 +2113,8 @@ static bool findMipsCsMultilibs(const Multilib::flags_list &Flags,
return false;
}
-static bool findMipsAndroidMultilibs(const Multilib::flags_list &Flags,
+static bool findMipsAndroidMultilibs(vfs::FileSystem &VFS, StringRef Path,
+ const Multilib::flags_list &Flags,
FilterNonExistent &NonExistent,
DetectedMultilibs &Result) {
@@ -1995,8 +2124,29 @@ static bool findMipsAndroidMultilibs(const Multilib::flags_list &Flags,
.Maybe(Multilib("/mips-r6").flag("+march=mips32r6"))
.FilterOut(NonExistent);
- if (AndroidMipsMultilibs.select(Flags, Result.SelectedMultilib)) {
- Result.Multilibs = AndroidMipsMultilibs;
+ MultilibSet AndroidMipselMultilibs =
+ MultilibSet()
+ .Either(Multilib().flag("+march=mips32"),
+ Multilib("/mips-r2", "", "/mips-r2").flag("+march=mips32r2"),
+ Multilib("/mips-r6", "", "/mips-r6").flag("+march=mips32r6"))
+ .FilterOut(NonExistent);
+
+ MultilibSet AndroidMips64elMultilibs =
+ MultilibSet()
+ .Either(
+ Multilib().flag("+march=mips64r6"),
+ Multilib("/32/mips-r1", "", "/mips-r1").flag("+march=mips32"),
+ Multilib("/32/mips-r2", "", "/mips-r2").flag("+march=mips32r2"),
+ Multilib("/32/mips-r6", "", "/mips-r6").flag("+march=mips32r6"))
+ .FilterOut(NonExistent);
+
+ MultilibSet *MS = &AndroidMipsMultilibs;
+ if (VFS.exists(Path + "/mips-r6"))
+ MS = &AndroidMipselMultilibs;
+ else if (VFS.exists(Path + "/32"))
+ MS = &AndroidMips64elMultilibs;
+ if (MS->select(Flags, Result.SelectedMultilib)) {
+ Result.Multilibs = *MS;
return true;
}
return false;
@@ -2323,6 +2473,7 @@ static bool findMIPSMultilibs(const Driver &D, const llvm::Triple &TargetTriple,
addMultilibFlag(CPUName == "mips64r2" || CPUName == "mips64r3" ||
CPUName == "mips64r5" || CPUName == "octeon",
"march=mips64r2", Flags);
+ addMultilibFlag(CPUName == "mips64r6", "march=mips64r6", Flags);
addMultilibFlag(isMicroMips(Args), "mmicromips", Flags);
addMultilibFlag(tools::mips::isUCLibc(Args), "muclibc", Flags);
addMultilibFlag(tools::mips::isNaN2008(Args, TargetTriple), "mnan=2008",
@@ -2335,7 +2486,8 @@ static bool findMIPSMultilibs(const Driver &D, const llvm::Triple &TargetTriple,
addMultilibFlag(!isMipsEL(TargetArch), "EB", Flags);
if (TargetTriple.isAndroid())
- return findMipsAndroidMultilibs(Flags, NonExistent, Result);
+ return findMipsAndroidMultilibs(D.getVFS(), Path, Flags, NonExistent,
+ Result);
if (TargetTriple.getVendor() == llvm::Triple::MipsTechnologies &&
TargetTriple.getOS() == llvm::Triple::Linux &&
@@ -2546,6 +2698,33 @@ void Generic_GCC::GCCInstallationDetector::scanLibDirForGCCTripleSolaris(
}
}
+bool Generic_GCC::GCCInstallationDetector::ScanGCCForMultilibs(
+ const llvm::Triple &TargetTriple, const ArgList &Args,
+ StringRef Path, bool NeedsBiarchSuffix) {
+ llvm::Triple::ArchType TargetArch = TargetTriple.getArch();
+ DetectedMultilibs Detected;
+
+ // Android standalone toolchain could have multilibs for ARM and Thumb.
+ // Debian mips multilibs behave more like the rest of the biarch ones,
+ // so handle them there
+ if (isArmOrThumbArch(TargetArch) && TargetTriple.isAndroid()) {
+ // It should also work without multilibs in a simplified toolchain.
+ findAndroidArmMultilibs(D, TargetTriple, Path, Args, Detected);
+ } else if (isMipsArch(TargetArch)) {
+ if (!findMIPSMultilibs(D, TargetTriple, Path, Args, Detected))
+ return false;
+ } else if (!findBiarchMultilibs(D, TargetTriple, Path, Args,
+ NeedsBiarchSuffix, Detected)) {
+ return false;
+ }
+
+ Multilibs = Detected.Multilibs;
+ SelectedMultilib = Detected.SelectedMultilib;
+ BiarchSibling = Detected.BiarchSibling;
+
+ return true;
+}
+
void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
const llvm::Triple &TargetTriple, const ArgList &Args,
const std::string &LibDir, StringRef CandidateTriple,
@@ -2601,25 +2780,10 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
if (CandidateVersion <= Version)
continue;
- DetectedMultilibs Detected;
-
- // Android standalone toolchain could have multilibs for ARM and Thumb.
- // Debian mips multilibs behave more like the rest of the biarch ones,
- // so handle them there
- if (isArmOrThumbArch(TargetArch) && TargetTriple.isAndroid()) {
- // It should also work without multilibs in a simplified toolchain.
- findAndroidArmMultilibs(D, TargetTriple, LI->getName(), Args, Detected);
- } else if (isMipsArch(TargetArch)) {
- if (!findMIPSMultilibs(D, TargetTriple, LI->getName(), Args, Detected))
- continue;
- } else if (!findBiarchMultilibs(D, TargetTriple, LI->getName(), Args,
- NeedsBiarchSuffix, Detected)) {
+ if (!ScanGCCForMultilibs(TargetTriple, Args, LI->getName(),
+ NeedsBiarchSuffix))
continue;
- }
- Multilibs = Detected.Multilibs;
- SelectedMultilib = Detected.SelectedMultilib;
- BiarchSibling = Detected.BiarchSibling;
Version = CandidateVersion;
GCCTriple.setTriple(CandidateTriple);
// FIXME: We hack together the directory name here instead of
@@ -2633,9 +2797,49 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
}
}
+bool Generic_GCC::GCCInstallationDetector::ScanGentooGccConfig(
+ const llvm::Triple &TargetTriple, const ArgList &Args,
+ StringRef CandidateTriple, bool NeedsBiarchSuffix) {
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> File =
+ D.getVFS().getBufferForFile(D.SysRoot + "/etc/env.d/gcc/config-" +
+ CandidateTriple.str());
+ if (File) {
+ SmallVector<StringRef, 2> Lines;
+ File.get()->getBuffer().split(Lines, "\n");
+ for (StringRef Line : Lines) {
+ // 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 (D.getVFS().exists(GentooPath + "/crtbegin.o")) {
+ if (!ScanGCCForMultilibs(TargetTriple, Args, GentooPath,
+ NeedsBiarchSuffix))
+ return false;
+
+ Version = GCCVersion::Parse(ActiveVersion.second);
+ GCCInstallPath = GentooPath;
+ GCCParentLibPath = GentooPath + "/../../..";
+ GCCTriple.setTriple(ActiveVersion.first);
+ IsValid = true;
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
Generic_GCC::Generic_GCC(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
- : ToolChain(D, Triple, Args), GCCInstallation(D), CudaInstallation(D) {
+ : ToolChain(D, Triple, Args), GCCInstallation(D),
+ CudaInstallation(D, Triple, Args) {
getProgramPaths().push_back(getDriver().getInstalledDir());
if (getDriver().getInstalledDir() != getDriver().Dir)
getProgramPaths().push_back(getDriver().Dir);
@@ -2675,7 +2879,15 @@ bool Generic_GCC::IsUnwindTablesDefault() const {
}
bool Generic_GCC::isPICDefault() const {
- return getArch() == llvm::Triple::x86_64 && getTriple().isOSWindows();
+ switch (getArch()) {
+ case llvm::Triple::x86_64:
+ return getTriple().isOSWindows();
+ case llvm::Triple::ppc64:
+ case llvm::Triple::ppc64le:
+ return !getTriple().isOSBinFormatMachO() && !getTriple().isMacOSX();
+ default:
+ return false;
+ }
}
bool Generic_GCC::isPIEDefault() const { return false; }
@@ -2703,11 +2915,50 @@ bool Generic_GCC::IsIntegratedAssemblerDefault() const {
case llvm::Triple::mips:
case llvm::Triple::mipsel:
return true;
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el:
+ // Enabled for Debian mips64/mips64el only. Other targets are unable to
+ // distinguish N32 from N64.
+ if (getTriple().getEnvironment() == llvm::Triple::GNUABI64)
+ return true;
+ return false;
default:
return false;
}
}
+void Generic_GCC::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
+ DriverArgs.hasArg(options::OPT_nostdincxx))
+ return;
+
+ switch (GetCXXStdlibType(DriverArgs)) {
+ case ToolChain::CST_Libcxx: {
+ std::string Path = findLibCxxIncludePath();
+ if (!Path.empty())
+ addSystemInclude(DriverArgs, CC1Args, Path);
+ break;
+ }
+
+ case ToolChain::CST_Libstdcxx:
+ addLibStdCxxIncludePaths(DriverArgs, CC1Args);
+ break;
+ }
+}
+
+std::string Generic_GCC::findLibCxxIncludePath() const {
+ // FIXME: The Linux behavior would probaby be a better approach here.
+ return getDriver().SysRoot + "/usr/include/c++/v1";
+}
+
+void
+Generic_GCC::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const {
+ // By default, we don't assume we know where libstdc++ might be installed.
+ // FIXME: If we have a valid GCCInstallation, use it.
+}
+
/// \brief Helper to add the variant paths of a libstdc++ installation.
bool Generic_GCC::addLibStdCXXIncludePaths(
Twine Base, Twine Suffix, StringRef GCCTriple, StringRef GCCMultiarchTriple,
@@ -2741,6 +2992,49 @@ bool Generic_GCC::addLibStdCXXIncludePaths(
return true;
}
+llvm::opt::DerivedArgList *
+Generic_GCC::TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef,
+ Action::OffloadKind DeviceOffloadKind) const {
+
+ // If this tool chain is used for an OpenMP offloading device we have to make
+ // sure we always generate a shared library regardless of the commands the
+ // user passed to the host. This is required because the runtime library
+ // is required to load the device image dynamically at run time.
+ if (DeviceOffloadKind == Action::OFK_OpenMP) {
+ DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
+ const OptTable &Opts = getDriver().getOpts();
+
+ // Request the shared library. Given that these options are decided
+ // implicitly, they do not refer to any base argument.
+ DAL->AddFlagArg(/*BaseArg=*/nullptr, Opts.getOption(options::OPT_shared));
+ DAL->AddFlagArg(/*BaseArg=*/nullptr, Opts.getOption(options::OPT_fPIC));
+
+ // Filter all the arguments we don't care passing to the offloading
+ // toolchain as they can mess up with the creation of a shared library.
+ for (auto *A : Args) {
+ switch ((options::ID)A->getOption().getID()) {
+ default:
+ DAL->append(A);
+ break;
+ case options::OPT_shared:
+ case options::OPT_dynamic:
+ case options::OPT_static:
+ case options::OPT_fPIC:
+ case options::OPT_fno_PIC:
+ case options::OPT_fpic:
+ case options::OPT_fno_pic:
+ case options::OPT_fPIE:
+ case options::OPT_fno_PIE:
+ case options::OPT_fpie:
+ case options::OPT_fno_pie:
+ break;
+ }
+ }
+ return DAL;
+ }
+ return nullptr;
+}
+
void Generic_ELF::addClangTargetOptions(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
const Generic_GCC::GCCVersion &V = GCCInstallation.getVersion();
@@ -2773,9 +3067,6 @@ MipsLLVMToolChain::MipsLLVMToolChain(const Driver &D,
LibSuffix = tools::mips::getMipsABILibSuffix(Args, Triple);
getFilePaths().clear();
getFilePaths().push_back(computeSysRoot() + "/usr/lib" + LibSuffix);
-
- // Use LLD by default.
- DefaultLinker = "lld";
}
void MipsLLVMToolChain::AddClangSystemIncludeArgs(
@@ -2832,25 +3123,16 @@ MipsLLVMToolChain::GetCXXStdlibType(const ArgList &Args) const {
return ToolChain::CST_Libcxx;
}
-void MipsLLVMToolChain::AddClangCXXStdlibIncludeArgs(
- const ArgList &DriverArgs, ArgStringList &CC1Args) const {
- if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
- DriverArgs.hasArg(options::OPT_nostdincxx))
- return;
-
- assert((GetCXXStdlibType(DriverArgs) == ToolChain::CST_Libcxx) &&
- "Only -lc++ (aka libcxx) is suported in this toolchain.");
-
- const auto &Callback = Multilibs.includeDirsCallback();
- if (Callback) {
+std::string MipsLLVMToolChain::findLibCxxIncludePath() 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)) {
- addSystemInclude(DriverArgs, CC1Args, Path);
- break;
+ return Path;
}
}
}
+ return "";
}
void MipsLLVMToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
@@ -2890,7 +3172,7 @@ std::string HexagonToolChain::getHexagonTargetDir(
if (getVFS().exists(InstallRelDir = InstalledDir + "/../target"))
return InstallRelDir;
- return InstallRelDir;
+ return InstalledDir;
}
Optional<unsigned> HexagonToolChain::getSmallDataThreshold(
@@ -2997,15 +3279,14 @@ void HexagonToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
addExternCSystemInclude(DriverArgs, CC1Args, TargetDir + "/hexagon/include");
}
-void HexagonToolChain::AddClangCXXStdlibIncludeArgs(
- const ArgList &DriverArgs, ArgStringList &CC1Args) const {
- if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
- DriverArgs.hasArg(options::OPT_nostdincxx))
- return;
+void HexagonToolChain::addLibStdCxxIncludePaths(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const {
const Driver &D = getDriver();
std::string TargetDir = getHexagonTargetDir(D.InstalledDir, D.PrefixDirs);
- addSystemInclude(DriverArgs, CC1Args, TargetDir + "/hexagon/include/c++");
+ addLibStdCXXIncludePaths(TargetDir, "/hexagon/include/c++", "", "", "", "",
+ DriverArgs, CC1Args);
}
ToolChain::CXXStdlibType
@@ -3163,37 +3444,25 @@ void NaClToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
CmdArgs.push_back("-lc++");
}
-void NaClToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
- ArgStringList &CC1Args) const {
+std::string NaClToolChain::findLibCxxIncludePath() const {
const Driver &D = getDriver();
- if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
- DriverArgs.hasArg(options::OPT_nostdincxx))
- return;
-
- // Check for -stdlib= flags. We only support libc++ but this consumes the arg
- // if the value is libc++, and emits an error for other values.
- GetCXXStdlibType(DriverArgs);
SmallString<128> P(D.Dir + "/../");
switch (getTriple().getArch()) {
case llvm::Triple::arm:
llvm::sys::path::append(P, "arm-nacl/include/c++/v1");
- addSystemInclude(DriverArgs, CC1Args, P.str());
- break;
+ return P.str();
case llvm::Triple::x86:
llvm::sys::path::append(P, "x86_64-nacl/include/c++/v1");
- addSystemInclude(DriverArgs, CC1Args, P.str());
- break;
+ return P.str();
case llvm::Triple::x86_64:
llvm::sys::path::append(P, "x86_64-nacl/include/c++/v1");
- addSystemInclude(DriverArgs, CC1Args, P.str());
- break;
+ return P.str();
case llvm::Triple::mipsel:
llvm::sys::path::append(P, "mipsel-nacl/include/c++/v1");
- addSystemInclude(DriverArgs, CC1Args, P.str());
- break;
+ return P.str();
default:
- break;
+ return "";
}
}
@@ -3254,6 +3523,13 @@ bool TCEToolChain::isPIEDefault() const { return false; }
bool TCEToolChain::isPICDefaultForced() const { return false; }
+TCELEToolChain::TCELEToolChain(const Driver &D, const llvm::Triple& Triple,
+ const ArgList &Args)
+ : TCEToolChain(D, Triple, Args) {
+}
+
+TCELEToolChain::~TCELEToolChain() {}
+
// CloudABI - CloudABI tool chain which can call ld(1) directly.
CloudABI::CloudABI(const Driver &D, const llvm::Triple &Triple,
@@ -3264,15 +3540,10 @@ CloudABI::CloudABI(const Driver &D, const llvm::Triple &Triple,
getFilePaths().push_back(P.str());
}
-void CloudABI::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
- ArgStringList &CC1Args) const {
- if (DriverArgs.hasArg(options::OPT_nostdlibinc) &&
- DriverArgs.hasArg(options::OPT_nostdincxx))
- return;
-
+std::string CloudABI::findLibCxxIncludePath() const {
SmallString<128> P(getDriver().Dir);
llvm::sys::path::append(P, "..", getTriple().str(), "include/c++/v1");
- addSystemInclude(DriverArgs, CC1Args, P.str());
+ return P.str();
}
void CloudABI::AddCXXStdlibLibArgs(const ArgList &Args,
@@ -3316,29 +3587,14 @@ Haiku::Haiku(const Driver &D, const llvm::Triple& Triple, const ArgList &Args)
}
-void Haiku::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
- ArgStringList &CC1Args) const {
- if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
- DriverArgs.hasArg(options::OPT_nostdincxx))
- return;
-
- switch (GetCXXStdlibType(DriverArgs)) {
- case ToolChain::CST_Libcxx:
- addSystemInclude(DriverArgs, CC1Args,
- getDriver().SysRoot + "/system/develop/headers/c++/v1");
- break;
- case ToolChain::CST_Libstdcxx:
- addSystemInclude(DriverArgs, CC1Args,
- getDriver().SysRoot + "/system/develop/headers/c++");
- addSystemInclude(DriverArgs, CC1Args,
- getDriver().SysRoot + "/system/develop/headers/c++/backward");
+std::string Haiku::findLibCxxIncludePath() const {
+ return getDriver().SysRoot + "/system/develop/headers/c++/v1";
+}
- StringRef Triple = getTriple().str();
- addSystemInclude(DriverArgs, CC1Args,
- getDriver().SysRoot + "/system/develop/headers/c++/" +
- Triple);
- break;
- }
+void Haiku::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const {
+ addLibStdCXXIncludePaths(getDriver().SysRoot, "/system/develop/headers/c++",
+ getTriple().str(), "", "", "", DriverArgs, CC1Args);
}
/// OpenBSD - OpenBSD tool chain which can call as(1) and ld(1) directly.
@@ -3374,34 +3630,13 @@ ToolChain::CXXStdlibType Bitrig::GetDefaultCXXStdlibType() const {
return ToolChain::CST_Libcxx;
}
-void Bitrig::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
- ArgStringList &CC1Args) const {
- if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
- DriverArgs.hasArg(options::OPT_nostdincxx))
- return;
-
- switch (GetCXXStdlibType(DriverArgs)) {
- case ToolChain::CST_Libcxx:
- addSystemInclude(DriverArgs, CC1Args,
- getDriver().SysRoot + "/usr/include/c++/v1");
- break;
- case ToolChain::CST_Libstdcxx:
- addSystemInclude(DriverArgs, CC1Args,
- getDriver().SysRoot + "/usr/include/c++/stdc++");
- addSystemInclude(DriverArgs, CC1Args,
- getDriver().SysRoot + "/usr/include/c++/stdc++/backward");
-
- StringRef Triple = getTriple().str();
- if (Triple.startswith("amd64"))
- addSystemInclude(DriverArgs, CC1Args,
- getDriver().SysRoot + "/usr/include/c++/stdc++/x86_64" +
- Triple.substr(5));
- else
- addSystemInclude(DriverArgs, CC1Args, getDriver().SysRoot +
- "/usr/include/c++/stdc++/" +
- Triple);
- break;
- }
+void Bitrig::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const {
+ std::string Triple = getTriple().str();
+ if (StringRef(Triple).startswith("amd64"))
+ Triple = "x86_64" + Triple.substr(5);
+ addLibStdCXXIncludePaths(getDriver().SysRoot, "/usr/include/c++/stdc++",
+ Triple, "", "", "", DriverArgs, CC1Args);
}
void Bitrig::AddCXXStdlibLibArgs(const ArgList &Args,
@@ -3440,24 +3675,11 @@ ToolChain::CXXStdlibType FreeBSD::GetDefaultCXXStdlibType() const {
return ToolChain::CST_Libstdcxx;
}
-void FreeBSD::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
- ArgStringList &CC1Args) const {
- if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
- DriverArgs.hasArg(options::OPT_nostdincxx))
- return;
-
- switch (GetCXXStdlibType(DriverArgs)) {
- case ToolChain::CST_Libcxx:
- addSystemInclude(DriverArgs, CC1Args,
- getDriver().SysRoot + "/usr/include/c++/v1");
- break;
- case ToolChain::CST_Libstdcxx:
- addSystemInclude(DriverArgs, CC1Args,
- getDriver().SysRoot + "/usr/include/c++/4.2");
- addSystemInclude(DriverArgs, CC1Args,
- getDriver().SysRoot + "/usr/include/c++/4.2/backward");
- break;
- }
+void FreeBSD::addLibStdCxxIncludePaths(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const {
+ addLibStdCXXIncludePaths(getDriver().SysRoot, "/usr/include/c++/4.2", "", "",
+ "", "", DriverArgs, CC1Args);
}
void FreeBSD::AddCXXStdlibLibArgs(const ArgList &Args,
@@ -3602,24 +3824,14 @@ ToolChain::CXXStdlibType NetBSD::GetDefaultCXXStdlibType() const {
return ToolChain::CST_Libstdcxx;
}
-void NetBSD::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
- ArgStringList &CC1Args) const {
- if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
- DriverArgs.hasArg(options::OPT_nostdincxx))
- return;
+std::string NetBSD::findLibCxxIncludePath() const {
+ return getDriver().SysRoot + "/usr/include/c++/";
+}
- switch (GetCXXStdlibType(DriverArgs)) {
- case ToolChain::CST_Libcxx:
- addSystemInclude(DriverArgs, CC1Args,
- getDriver().SysRoot + "/usr/include/c++/");
- break;
- case ToolChain::CST_Libstdcxx:
- addSystemInclude(DriverArgs, CC1Args,
- getDriver().SysRoot + "/usr/include/g++");
- addSystemInclude(DriverArgs, CC1Args,
- getDriver().SysRoot + "/usr/include/g++/backward");
- break;
- }
+void NetBSD::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const {
+ addLibStdCXXIncludePaths(getDriver().SysRoot, "/usr/include/g++", "", "", "",
+ "", DriverArgs, CC1Args);
}
/// Minix - Minix tool chain which can call as(1) and ld(1) directly.
@@ -3692,6 +3904,9 @@ void Solaris::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
// 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");
if (GCCInstallation.isValid()) {
@@ -3709,137 +3924,6 @@ void Solaris::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
}
}
-/// Distribution (very bare-bones at the moment).
-
-enum Distro {
- // NB: Releases of a particular Linux distro should be kept together
- // in this enum, because some tests are done by integer comparison against
- // the first and last known member in the family, e.g. IsRedHat().
- ArchLinux,
- DebianLenny,
- DebianSqueeze,
- DebianWheezy,
- DebianJessie,
- DebianStretch,
- Exherbo,
- RHEL5,
- RHEL6,
- RHEL7,
- Fedora,
- OpenSUSE,
- UbuntuHardy,
- UbuntuIntrepid,
- UbuntuJaunty,
- UbuntuKarmic,
- UbuntuLucid,
- UbuntuMaverick,
- UbuntuNatty,
- UbuntuOneiric,
- UbuntuPrecise,
- UbuntuQuantal,
- UbuntuRaring,
- UbuntuSaucy,
- UbuntuTrusty,
- UbuntuUtopic,
- UbuntuVivid,
- UbuntuWily,
- UbuntuXenial,
- UnknownDistro
-};
-
-static bool IsRedhat(enum Distro Distro) {
- return Distro == Fedora || (Distro >= RHEL5 && Distro <= RHEL7);
-}
-
-static bool IsOpenSUSE(enum Distro Distro) { return Distro == OpenSUSE; }
-
-static bool IsDebian(enum Distro Distro) {
- return Distro >= DebianLenny && Distro <= DebianStretch;
-}
-
-static bool IsUbuntu(enum Distro Distro) {
- return Distro >= UbuntuHardy && Distro <= UbuntuXenial;
-}
-
-static Distro DetectDistro(const Driver &D, llvm::Triple::ArchType Arch) {
- llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> File =
- llvm::MemoryBuffer::getFile("/etc/lsb-release");
- if (File) {
- StringRef Data = File.get()->getBuffer();
- SmallVector<StringRef, 16> Lines;
- Data.split(Lines, "\n");
- Distro Version = UnknownDistro;
- for (StringRef Line : Lines)
- if (Version == UnknownDistro && Line.startswith("DISTRIB_CODENAME="))
- Version = llvm::StringSwitch<Distro>(Line.substr(17))
- .Case("hardy", UbuntuHardy)
- .Case("intrepid", UbuntuIntrepid)
- .Case("jaunty", UbuntuJaunty)
- .Case("karmic", UbuntuKarmic)
- .Case("lucid", UbuntuLucid)
- .Case("maverick", UbuntuMaverick)
- .Case("natty", UbuntuNatty)
- .Case("oneiric", UbuntuOneiric)
- .Case("precise", UbuntuPrecise)
- .Case("quantal", UbuntuQuantal)
- .Case("raring", UbuntuRaring)
- .Case("saucy", UbuntuSaucy)
- .Case("trusty", UbuntuTrusty)
- .Case("utopic", UbuntuUtopic)
- .Case("vivid", UbuntuVivid)
- .Case("wily", UbuntuWily)
- .Case("xenial", UbuntuXenial)
- .Default(UnknownDistro);
- if (Version != UnknownDistro)
- return Version;
- }
-
- File = llvm::MemoryBuffer::getFile("/etc/redhat-release");
- if (File) {
- StringRef Data = File.get()->getBuffer();
- if (Data.startswith("Fedora release"))
- return Fedora;
- if (Data.startswith("Red Hat Enterprise Linux") ||
- Data.startswith("CentOS") ||
- Data.startswith("Scientific Linux")) {
- if (Data.find("release 7") != StringRef::npos)
- return RHEL7;
- else if (Data.find("release 6") != StringRef::npos)
- return RHEL6;
- else if (Data.find("release 5") != StringRef::npos)
- return RHEL5;
- }
- return UnknownDistro;
- }
-
- File = llvm::MemoryBuffer::getFile("/etc/debian_version");
- if (File) {
- StringRef Data = File.get()->getBuffer();
- if (Data[0] == '5')
- return DebianLenny;
- else if (Data.startswith("squeeze/sid") || Data[0] == '6')
- return DebianSqueeze;
- else if (Data.startswith("wheezy/sid") || Data[0] == '7')
- return DebianWheezy;
- else if (Data.startswith("jessie/sid") || Data[0] == '8')
- return DebianJessie;
- else if (Data.startswith("stretch/sid") || Data[0] == '9')
- return DebianStretch;
- return UnknownDistro;
- }
-
- if (D.getVFS().exists("/etc/SuSE-release"))
- return OpenSUSE;
-
- if (D.getVFS().exists("/etc/exherbo-release"))
- return Exherbo;
-
- if (D.getVFS().exists("/etc/arch-release"))
- return ArchLinux;
-
- return UnknownDistro;
-}
-
/// \brief Get our best guess at the multiarch triple for a target.
///
/// Debian-based systems are starting to use a multiarch setup where they use
@@ -3952,6 +4036,15 @@ static std::string getMultiarchTriple(const Driver &D,
static StringRef getOSLibDir(const llvm::Triple &Triple, const ArgList &Args) {
if (isMipsArch(Triple.getArch())) {
+ if (Triple.isAndroid()) {
+ StringRef CPUName;
+ StringRef ABIName;
+ tools::mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName);
+ if (CPUName == "mips32r6")
+ return "libr6";
+ if (CPUName == "mips32r2")
+ return "libr2";
+ }
// lib32 directory has a special meaning on MIPS targets.
// It contains N32 ABI binaries. Use this folder if produce
// code for N32 ABI only.
@@ -3992,7 +4085,6 @@ static void addMultilibsFilePaths(const Driver &D, const MultilibSet &Multilibs,
Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
: Generic_ELF(D, Triple, Args) {
GCCInstallation.init(Triple, Args);
- CudaInstallation.init(Triple, Args);
Multilibs = GCCInstallation.getMultilibs();
llvm::Triple::ArchType Arch = Triple.getArch();
std::string SysRoot = computeSysRoot();
@@ -4010,9 +4102,9 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
GCCInstallation.getTriple().str() + "/bin")
.str());
- Distro Distro = DetectDistro(D, Arch);
+ Distro Distro(D.getVFS());
- if (IsOpenSUSE(Distro) || IsUbuntu(Distro)) {
+ if (Distro.IsOpenSUSE() || Distro.IsUbuntu()) {
ExtraOpts.push_back("-z");
ExtraOpts.push_back("relro");
}
@@ -4032,23 +4124,23 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
// ABI requires a mapping between the GOT and the symbol table.
// Android loader does not support .gnu.hash.
if (!IsMips && !IsAndroid) {
- if (IsRedhat(Distro) || IsOpenSUSE(Distro) ||
- (IsUbuntu(Distro) && Distro >= UbuntuMaverick))
+ if (Distro.IsRedhat() || Distro.IsOpenSUSE() ||
+ (Distro.IsUbuntu() && Distro >= Distro::UbuntuMaverick))
ExtraOpts.push_back("--hash-style=gnu");
- if (IsDebian(Distro) || IsOpenSUSE(Distro) || Distro == UbuntuLucid ||
- Distro == UbuntuJaunty || Distro == UbuntuKarmic)
+ if (Distro.IsDebian() || Distro.IsOpenSUSE() || Distro == Distro::UbuntuLucid ||
+ Distro == Distro::UbuntuJaunty || Distro == Distro::UbuntuKarmic)
ExtraOpts.push_back("--hash-style=both");
}
- if (IsRedhat(Distro) && Distro != RHEL5 && Distro != RHEL6)
+ if (Distro.IsRedhat() && Distro != Distro::RHEL5 && Distro != Distro::RHEL6)
ExtraOpts.push_back("--no-add-needed");
#ifdef ENABLE_LINKER_BUILD_ID
ExtraOpts.push_back("--build-id");
#endif
- if (IsOpenSUSE(Distro))
+ if (Distro.IsOpenSUSE())
ExtraOpts.push_back("--enable-new-dtags");
// The selection of paths to try here is designed to match the patterns which
@@ -4214,23 +4306,32 @@ std::string Linux::getDynamicLinker(const ArgList &Args) const {
const llvm::Triple::ArchType Arch = getArch();
const llvm::Triple &Triple = getTriple();
- const enum Distro Distro = DetectDistro(getDriver(), Arch);
+ const Distro Distro(getDriver().getVFS());
if (Triple.isAndroid())
return Triple.isArch64Bit() ? "/system/bin/linker64" : "/system/bin/linker";
- else if (Triple.isMusl()) {
+
+ if (Triple.isMusl()) {
std::string ArchName;
+ bool IsArm = false;
+
switch (Arch) {
+ case llvm::Triple::arm:
case llvm::Triple::thumb:
ArchName = "arm";
+ IsArm = true;
break;
+ case llvm::Triple::armeb:
case llvm::Triple::thumbeb:
ArchName = "armeb";
+ IsArm = true;
break;
default:
ArchName = Triple.getArchName().str();
}
- if (Triple.getEnvironment() == llvm::Triple::MuslEABIHF)
+ if (IsArm &&
+ (Triple.getEnvironment() == llvm::Triple::MuslEABIHF ||
+ tools::arm::getARMFloatABI(*this, Args) == tools::arm::FloatABI::Hard))
ArchName += "hf";
return "/lib/ld-musl-" + ArchName + ".so.1";
@@ -4323,8 +4424,8 @@ std::string Linux::getDynamicLinker(const ArgList &Args) const {
}
}
- if (Distro == Exherbo && (Triple.getVendor() == llvm::Triple::UnknownVendor ||
- Triple.getVendor() == llvm::Triple::PC))
+ if (Distro == Distro::Exherbo && (Triple.getVendor() == llvm::Triple::UnknownVendor ||
+ Triple.getVendor() == llvm::Triple::PC))
return "/usr/" + Triple.str() + "/lib/" + Loader;
return "/" + LibDir + "/" + Loader;
}
@@ -4517,33 +4618,27 @@ static std::string DetectLibcxxIncludePath(StringRef base) {
return MaxVersion ? (base + "/" + MaxVersionString).str() : "";
}
-void Linux::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
- ArgStringList &CC1Args) const {
- if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
- DriverArgs.hasArg(options::OPT_nostdincxx))
- return;
-
- // Check if libc++ has been enabled and provide its include paths if so.
- if (GetCXXStdlibType(DriverArgs) == ToolChain::CST_Libcxx) {
- const std::string LibCXXIncludePathCandidates[] = {
- 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++") };
- for (const auto &IncludePath : LibCXXIncludePathCandidates) {
- if (IncludePath.empty() || !getVFS().exists(IncludePath))
- continue;
- // Add the first candidate that exists.
- addSystemInclude(DriverArgs, CC1Args, IncludePath);
- break;
- }
- return;
+std::string Linux::findLibCxxIncludePath() const {
+ const std::string LibCXXIncludePathCandidates[] = {
+ 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++") };
+ for (const auto &IncludePath : LibCXXIncludePathCandidates) {
+ if (IncludePath.empty() || !getVFS().exists(IncludePath))
+ continue;
+ // Use the first candidate that exists.
+ return IncludePath;
}
+ return "";
+}
+void Linux::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const {
// We need a detected GCC installation on Linux to provide libstdc++'s
- // headers. We handled the libc++ case above.
+ // headers.
if (!GCCInstallation.isValid())
return;
@@ -4594,17 +4689,7 @@ void Linux::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
void Linux::AddCudaIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
- if (DriverArgs.hasArg(options::OPT_nocudainc))
- return;
-
- if (!CudaInstallation.isValid()) {
- getDriver().Diag(diag::err_drv_no_cuda_installation);
- return;
- }
-
- addSystemInclude(DriverArgs, CC1Args, CudaInstallation.getIncludePath());
- CC1Args.push_back("-include");
- CC1Args.push_back("__clang_cuda_runtime_wrapper.h");
+ CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args);
}
void Linux::AddIAMCUIncludeArgs(const ArgList &DriverArgs,
@@ -4641,7 +4726,7 @@ SanitizerMask Linux::getSupportedSanitizers() const {
Res |= SanitizerKind::Thread;
if (IsX86_64 || IsMIPS64 || IsPowerPC64 || IsAArch64)
Res |= SanitizerKind::Memory;
- if (IsX86_64)
+ if (IsX86_64 || IsMIPS64)
Res |= SanitizerKind::Efficiency;
if (IsX86 || IsX86_64) {
Res |= SanitizerKind::Function;
@@ -4661,6 +4746,99 @@ void Linux::addProfileRTLibs(const llvm::opt::ArgList &Args,
ToolChain::addProfileRTLibs(Args, CmdArgs);
}
+/// Fuchsia - Fuchsia tool chain which can call as(1) and ld(1) directly.
+
+Fuchsia::Fuchsia(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args)
+ : Generic_ELF(D, Triple, Args) {
+
+ getFilePaths().push_back(D.SysRoot + "/lib");
+ getFilePaths().push_back(D.ResourceDir + "/lib/fuchsia");
+}
+
+Tool *Fuchsia::buildAssembler() const {
+ return new tools::gnutools::Assembler(*this);
+}
+
+Tool *Fuchsia::buildLinker() const {
+ return new tools::fuchsia::Linker(*this);
+}
+
+ToolChain::RuntimeLibType Fuchsia::GetRuntimeLibType(
+ const ArgList &Args) const {
+ if (Arg *A = Args.getLastArg(options::OPT_rtlib_EQ)) {
+ StringRef Value = A->getValue();
+ if (Value != "compiler-rt")
+ getDriver().Diag(diag::err_drv_invalid_rtlib_name)
+ << A->getAsString(Args);
+ }
+
+ return ToolChain::RLT_CompilerRT;
+}
+
+ToolChain::CXXStdlibType
+Fuchsia::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;
+}
+
+void Fuchsia::addClangTargetOptions(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ if (DriverArgs.hasFlag(options::OPT_fuse_init_array,
+ options::OPT_fno_use_init_array, true))
+ CC1Args.push_back("-fuse-init-array");
+}
+
+void Fuchsia::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ const Driver &D = getDriver();
+
+ if (DriverArgs.hasArg(options::OPT_nostdinc))
+ return;
+
+ 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;
+
+ // 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;
+ }
+
+ addExternCSystemInclude(DriverArgs, CC1Args, D.SysRoot + "/include");
+}
+
+std::string Fuchsia::findLibCxxIncludePath() const {
+ return getDriver().SysRoot + "/include/c++/v1";
+}
+
+void Fuchsia::AddCXXStdlibLibArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ (void) GetCXXStdlibType(Args);
+ CmdArgs.push_back("-lc++");
+ CmdArgs.push_back("-lc++abi");
+ CmdArgs.push_back("-lunwind");
+}
+
/// DragonFly - DragonFly tool chain which can call as(1) and ld(1) directly.
DragonFly::DragonFly(const Driver &D, const llvm::Triple &Triple,
@@ -4690,16 +4868,18 @@ Tool *DragonFly::buildLinker() const {
/// together object files from the assembler into a single blob.
CudaToolChain::CudaToolChain(const Driver &D, const llvm::Triple &Triple,
- const ArgList &Args)
- : Linux(D, Triple, Args) {
+ const ToolChain &HostTC, const ArgList &Args)
+ : ToolChain(D, Triple, Args), HostTC(HostTC),
+ CudaInstallation(D, Triple, Args) {
if (CudaInstallation.isValid())
getProgramPaths().push_back(CudaInstallation.getBinPath());
}
-void
-CudaToolChain::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args) const {
- Linux::addClangTargetOptions(DriverArgs, CC1Args);
+void CudaToolChain::addClangTargetOptions(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const {
+ HostTC.addClangTargetOptions(DriverArgs, CC1Args);
+
CC1Args.push_back("-fcuda-is-device");
if (DriverArgs.hasFlag(options::OPT_fcuda_flush_denormals_to_zero,
@@ -4713,18 +4893,23 @@ CudaToolChain::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
if (DriverArgs.hasArg(options::OPT_nocudalib))
return;
- std::string LibDeviceFile = CudaInstallation.getLibDeviceFile(
- DriverArgs.getLastArgValue(options::OPT_march_EQ));
- if (!LibDeviceFile.empty()) {
- CC1Args.push_back("-mlink-cuda-bitcode");
- CC1Args.push_back(DriverArgs.MakeArgString(LibDeviceFile));
-
- // Libdevice in CUDA-7.0 requires PTX version that's more recent
- // than LLVM defaults to. Use PTX4.2 which is the PTX version that
- // came with CUDA-7.0.
- CC1Args.push_back("-target-feature");
- CC1Args.push_back("+ptx42");
+ StringRef GpuArch = DriverArgs.getLastArgValue(options::OPT_march_EQ);
+ assert(!GpuArch.empty() && "Must have an explicit GPU arch.");
+ std::string LibDeviceFile = CudaInstallation.getLibDeviceFile(GpuArch);
+
+ if (LibDeviceFile.empty()) {
+ getDriver().Diag(diag::err_drv_no_cuda_libdevice) << GpuArch;
+ return;
}
+
+ CC1Args.push_back("-mlink-cuda-bitcode");
+ CC1Args.push_back(DriverArgs.MakeArgString(LibDeviceFile));
+
+ // Libdevice in CUDA-7.0 requires PTX version that's more recent
+ // than LLVM defaults to. Use PTX4.2 which is the PTX version that
+ // came with CUDA-7.0.
+ CC1Args.push_back("-target-feature");
+ CC1Args.push_back("+ptx42");
}
void CudaToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs,
@@ -4736,19 +4921,24 @@ void CudaToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs,
assert(!Arch.empty() && "Must have an explicit GPU arch.");
CudaInstallation.CheckCudaVersionSupportsArch(StringToCudaArch(Arch));
}
- Linux::AddCudaIncludeArgs(DriverArgs, CC1Args);
+ CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args);
}
llvm::opt::DerivedArgList *
CudaToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
- const char *BoundArch) const {
- DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
+ 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 || A->getValue(0) != StringRef(BoundArch))
+ if (BoundArch.empty() || A->getValue(0) != BoundArch)
continue;
unsigned Index = Args.getBaseArgs().MakeIndex(A->getValue(1));
@@ -4779,7 +4969,7 @@ CudaToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
DAL->append(A);
}
- if (BoundArch) {
+ if (!BoundArch.empty()) {
DAL->eraseArg(options::OPT_march_EQ);
DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_march_EQ), BoundArch);
}
@@ -4794,6 +4984,43 @@ Tool *CudaToolChain::buildLinker() const {
return new tools::NVPTX::Linker(*this);
}
+void CudaToolChain::addClangWarningOptions(ArgStringList &CC1Args) const {
+ HostTC.addClangWarningOptions(CC1Args);
+}
+
+ToolChain::CXXStdlibType
+CudaToolChain::GetCXXStdlibType(const ArgList &Args) const {
+ return HostTC.GetCXXStdlibType(Args);
+}
+
+void CudaToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ HostTC.AddClangSystemIncludeArgs(DriverArgs, CC1Args);
+}
+
+void CudaToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &Args,
+ ArgStringList &CC1Args) const {
+ HostTC.AddClangCXXStdlibIncludeArgs(Args, CC1Args);
+}
+
+void CudaToolChain::AddIAMCUIncludeArgs(const ArgList &Args,
+ ArgStringList &CC1Args) const {
+ HostTC.AddIAMCUIncludeArgs(Args, CC1Args);
+}
+
+SanitizerMask CudaToolChain::getSupportedSanitizers() const {
+ // The CudaToolChain only supports sanitizers in the sense that it allows
+ // sanitizer arguments on the command line if they are supported by the host
+ // toolchain. The CudaToolChain 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();
+}
+
/// XCore tool chain
XCoreToolChain::XCoreToolChain(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
@@ -4878,24 +5105,13 @@ MyriadToolChain::MyriadToolChain(const Driver &D, const llvm::Triple &Triple,
}
if (GCCInstallation.isValid()) {
- // The contents of LibDir are independent of the version of gcc.
- // This contains libc, libg (a superset of libc), libm, libstdc++, libssp.
- SmallString<128> LibDir(GCCInstallation.getParentLibPath());
- if (Triple.getArch() == llvm::Triple::sparcel)
- llvm::sys::path::append(LibDir, "../sparc-myriad-elf/lib/le");
- else
- llvm::sys::path::append(LibDir, "../sparc-myriad-elf/lib");
- addPathIfExists(D, LibDir, getFilePaths());
-
// This directory contains crt{i,n,begin,end}.o as well as libgcc.
// These files are tied to a particular version of gcc.
SmallString<128> CompilerSupportDir(GCCInstallation.getInstallPath());
- // There are actually 4 choices: {le,be} x {fpu,nofpu}
- // but as this toolchain is for LEON sparc, it can assume FPU.
- if (Triple.getArch() == llvm::Triple::sparcel)
- llvm::sys::path::append(CompilerSupportDir, "le");
addPathIfExists(D, CompilerSupportDir, getFilePaths());
}
+ // libstd++ and libc++ must both be found in this one place.
+ addPathIfExists(D, D.Dir + "/../sparc-myriad-elf/lib", getFilePaths());
}
MyriadToolChain::~MyriadToolChain() {}
@@ -4906,18 +5122,18 @@ void MyriadToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
addSystemInclude(DriverArgs, CC1Args, getDriver().SysRoot + "/include");
}
-void MyriadToolChain::AddClangCXXStdlibIncludeArgs(
- const ArgList &DriverArgs, ArgStringList &CC1Args) const {
- if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
- DriverArgs.hasArg(options::OPT_nostdincxx))
- return;
+std::string MyriadToolChain::findLibCxxIncludePath() const {
+ std::string Path(getDriver().getInstalledDir());
+ return Path + "/../include/c++/v1";
+}
- // Only libstdc++, for now.
+void MyriadToolChain::addLibStdCxxIncludePaths(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const {
StringRef LibDir = GCCInstallation.getParentLibPath();
const GCCVersion &Version = GCCInstallation.getVersion();
StringRef TripleStr = GCCInstallation.getTriple().str();
const Multilib &Multilib = GCCInstallation.getMultilib();
-
addLibStdCXXIncludePaths(
LibDir.str() + "/../" + TripleStr.str() + "/include/c++/" + Version.Text,
"", TripleStr, "", "", Multilib.includeSuffix(), DriverArgs, CC1Args);
@@ -4948,6 +5164,10 @@ Tool *MyriadToolChain::buildLinker() const {
return new tools::Myriad::Linker(*this);
}
+SanitizerMask MyriadToolChain::getSupportedSanitizers() const {
+ return SanitizerKind::Address;
+}
+
WebAssembly::WebAssembly(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args)
: ToolChain(D, Triple, Args) {
@@ -4955,9 +5175,6 @@ WebAssembly::WebAssembly(const Driver &D, const llvm::Triple &Triple,
assert(Triple.isArch32Bit() != Triple.isArch64Bit());
getFilePaths().push_back(
getDriver().SysRoot + "/lib" + (Triple.isArch32Bit() ? "32" : "64"));
-
- // Use LLD by default.
- DefaultLinker = "lld";
}
bool WebAssembly::IsMathErrnoDefault() const { return false; }
@@ -5005,9 +5222,8 @@ void WebAssembly::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
addSystemInclude(DriverArgs, CC1Args, getDriver().SysRoot + "/include");
}
-void WebAssembly::AddClangCXXStdlibIncludeArgs(
- const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args) const {
+void WebAssembly::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
if (!DriverArgs.hasArg(options::OPT_nostdlibinc) &&
!DriverArgs.hasArg(options::OPT_nostdincxx))
addSystemInclude(DriverArgs, CC1Args,
@@ -5091,3 +5307,14 @@ SanitizerMask PS4CPU::getSupportedSanitizers() const {
Res |= SanitizerKind::Vptr;
return Res;
}
+
+Contiki::Contiki(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
+ : Generic_ELF(D, Triple, Args) {}
+
+SanitizerMask Contiki::getSupportedSanitizers() const {
+ const bool IsX86 = getTriple().getArch() == llvm::Triple::x86;
+ SanitizerMask Res = ToolChain::getSupportedSanitizers();
+ if (IsX86)
+ Res |= SanitizerKind::SafeStack;
+ return Res;
+}
diff --git a/lib/Driver/ToolChains.h b/lib/Driver/ToolChains.h
index 369712fa934b..7dab08915d48 100644
--- a/lib/Driver/ToolChains.h
+++ b/lib/Driver/ToolChains.h
@@ -16,7 +16,6 @@
#include "clang/Driver/Action.h"
#include "clang/Driver/Multilib.h"
#include "clang/Driver/ToolChain.h"
-#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/Support/Compiler.h"
@@ -25,6 +24,60 @@
namespace clang {
namespace driver {
+
+/// A class to find a viable CUDA installation
+class CudaInstallationDetector {
+private:
+ const Driver &D;
+ bool IsValid = false;
+ CudaVersion Version = CudaVersion::UNKNOWN;
+ std::string InstallPath;
+ std::string BinPath;
+ std::string LibPath;
+ std::string LibDevicePath;
+ std::string IncludePath;
+ llvm::StringMap<std::string> LibDeviceMap;
+
+ // CUDA architectures for which we have raised an error in
+ // CheckCudaVersionSupportsArch.
+ mutable llvm::SmallSet<CudaArch, 4> ArchsWithVersionTooLowErrors;
+
+public:
+ CudaInstallationDetector(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+
+ void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const;
+
+ /// \brief 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.
+ bool isValid() const { return IsValid; }
+ /// \brief Print information about the detected CUDA installation.
+ void print(raw_ostream &OS) const;
+
+ /// \brief Get the detected Cuda install's version.
+ CudaVersion version() const { return Version; }
+ /// \brief Get the detected Cuda installation path.
+ StringRef getInstallPath() const { return InstallPath; }
+ /// \brief Get the detected path to Cuda's bin directory.
+ StringRef getBinPath() const { return BinPath; }
+ /// \brief Get the detected Cuda Include path.
+ StringRef getIncludePath() const { return IncludePath; }
+ /// \brief Get the detected Cuda library path.
+ StringRef getLibPath() const { return LibPath; }
+ /// \brief Get the detected Cuda device library path.
+ StringRef getLibDevicePath() const { return LibDevicePath; }
+ /// \brief Get libdevice file for given architecture
+ std::string getLibDeviceFile(StringRef Gpu) const {
+ return LibDeviceMap.lookup(Gpu);
+ }
+};
+
namespace toolchains {
/// Generic_GCC - A tool chain using the 'gcc' command to perform
@@ -143,6 +196,11 @@ public:
SmallVectorImpl<StringRef> &BiarchLibDirs,
SmallVectorImpl<StringRef> &BiarchTripleAliases);
+ bool ScanGCCForMultilibs(const llvm::Triple &TargetTriple,
+ const llvm::opt::ArgList &Args,
+ StringRef Path,
+ bool NeedsBiarchSuffix = false);
+
void ScanLibDirForGCCTriple(const llvm::Triple &TargetArch,
const llvm::opt::ArgList &Args,
const std::string &LibDir,
@@ -154,61 +212,15 @@ public:
const std::string &LibDir,
StringRef CandidateTriple,
bool NeedsBiarchSuffix = false);
+
+ bool ScanGentooGccConfig(const llvm::Triple &TargetTriple,
+ const llvm::opt::ArgList &Args,
+ StringRef CandidateTriple,
+ bool NeedsBiarchSuffix = false);
};
protected:
GCCInstallationDetector GCCInstallation;
-
- // \brief A class to find a viable CUDA installation
- class CudaInstallationDetector {
- private:
- const Driver &D;
- bool IsValid = false;
- CudaVersion Version = CudaVersion::UNKNOWN;
- std::string InstallPath;
- std::string BinPath;
- std::string LibPath;
- std::string LibDevicePath;
- std::string IncludePath;
- llvm::StringMap<std::string> LibDeviceMap;
-
- // CUDA architectures for which we have raised an error in
- // CheckCudaVersionSupportsArch.
- mutable llvm::SmallSet<CudaArch, 4> ArchsWithVersionTooLowErrors;
-
- public:
- CudaInstallationDetector(const Driver &D) : D(D) {}
- void init(const llvm::Triple &TargetTriple, const llvm::opt::ArgList &Args);
-
- /// \brief 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.
- bool isValid() const { return IsValid; }
- /// \brief Print information about the detected CUDA installation.
- void print(raw_ostream &OS) const;
-
- /// \brief Get the deteced Cuda install's version.
- CudaVersion version() const { return Version; }
- /// \brief Get the detected Cuda installation path.
- StringRef getInstallPath() const { return InstallPath; }
- /// \brief Get the detected path to Cuda's bin directory.
- StringRef getBinPath() const { return BinPath; }
- /// \brief Get the detected Cuda Include path.
- StringRef getIncludePath() const { return IncludePath; }
- /// \brief Get the detected Cuda library path.
- StringRef getLibPath() const { return LibPath; }
- /// \brief Get the detected Cuda device library path.
- StringRef getLibDevicePath() const { return LibDevicePath; }
- /// \brief Get libdevice file for given architecture
- std::string getLibDeviceFile(StringRef Gpu) const {
- return LibDeviceMap.lookup(Gpu);
- }
- };
-
CudaInstallationDetector CudaInstallation;
public:
@@ -223,6 +235,9 @@ public:
bool isPIEDefault() const override;
bool isPICDefaultForced() const override;
bool IsIntegratedAssemblerDefault() const override;
+ llvm::opt::DerivedArgList *
+ TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
+ Action::OffloadKind DeviceOffloadKind) const override;
protected:
Tool *getTool(Action::ActionClass AC) const override;
@@ -238,6 +253,17 @@ protected:
/// \brief 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.
+ void AddClangCXXStdlibIncludeArgs(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+
+ virtual std::string findLibCxxIncludePath() const;
+ virtual void
+ addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const;
+
bool addLibStdCXXIncludePaths(Twine Base, Twine Suffix, StringRef GCCTriple,
StringRef GCCMultiarchTriple,
StringRef TargetMultiarchTriple,
@@ -313,16 +339,13 @@ public:
/// @name ToolChain Implementation
/// {
- std::string ComputeEffectiveClangTriple(const llvm::opt::ArgList &Args,
- types::ID InputType) const override;
-
- types::ID LookupTypeForExtension(const char *Ext) const override;
+ types::ID LookupTypeForExtension(StringRef Ext) const override;
bool HasNativeLLVMSupport() const override;
llvm::opt::DerivedArgList *
- TranslateArgs(const llvm::opt::DerivedArgList &Args,
- const char *BoundArch) const override;
+ TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
+ Action::OffloadKind DeviceOffloadKind) const override;
bool IsBlocksDefault() const override {
// Always allow blocks on Apple; users interested in versioning are
@@ -393,6 +416,8 @@ public:
/// The OS version we are targeting.
mutable VersionTuple TargetVersion;
+ CudaInstallationDetector CudaInstallation;
+
private:
void AddDeploymentTarget(llvm::opt::DerivedArgList &Args) const;
@@ -526,13 +551,16 @@ public:
bool isCrossCompiling() const override { return false; }
llvm::opt::DerivedArgList *
- TranslateArgs(const llvm::opt::DerivedArgList &Args,
- const char *BoundArch) const override;
+ TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
+ Action::OffloadKind DeviceOffloadKind) const override;
CXXStdlibType GetDefaultCXXStdlibType() const override;
ObjCRuntime getDefaultObjCRuntime(bool isNonFragile) const override;
bool hasBlocksRuntime() const override;
+ void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+
bool UseObjCMixedDispatch() const override {
// This is only used with the non-fragile ABI and non-legacy dispatch.
@@ -562,6 +590,8 @@ public:
bool SupportsEmbeddedBitcode() const override;
SanitizerMask getSupportedSanitizers() const override;
+
+ void printVerboseInfo(raw_ostream &OS) const override;
};
/// DarwinClang - The Darwin toolchain used by Clang.
@@ -573,6 +603,8 @@ public:
/// @name Apple ToolChain Implementation
/// {
+ RuntimeLibType GetRuntimeLibType(const llvm::opt::ArgList &Args) const override;
+
void AddLinkRuntimeLibArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const override;
@@ -587,7 +619,7 @@ public:
void AddLinkARCArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const override;
- unsigned GetDefaultDwarfVersion() const override { return 2; }
+ unsigned GetDefaultDwarfVersion() const override;
// Until dtrace (via CTF) and LLDB can deal with distributed debug info,
// Darwin defaults to standalone/full debug info.
bool GetDefaultStandaloneDebug() const override { return true; }
@@ -628,9 +660,7 @@ public:
GetCXXStdlibType(const llvm::opt::ArgList &Args) const override {
return ToolChain::CST_Libcxx;
}
- void AddClangCXXStdlibIncludeArgs(
- const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args) const override;
+ std::string findLibCxxIncludePath() const override;
void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const override;
@@ -699,11 +729,14 @@ public:
Haiku(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);
- bool isPIEDefault() const override { return getTriple().getArch() == llvm::Triple::x86_64; }
+ bool isPIEDefault() const override {
+ return getTriple().getArch() == llvm::Triple::x86_64;
+ }
- void
- AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args) const override;
+ std::string findLibCxxIncludePath() const override;
+ void addLibStdCxxIncludePaths(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
};
class LLVM_LIBRARY_VISIBILITY OpenBSD : public Generic_ELF {
@@ -734,7 +767,7 @@ public:
bool IsObjCNonFragileABIDefault() const override { return true; }
CXXStdlibType GetDefaultCXXStdlibType() const override;
- void AddClangCXXStdlibIncludeArgs(
+ void addLibStdCxxIncludePaths(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
@@ -758,7 +791,7 @@ public:
bool IsObjCNonFragileABIDefault() const override { return true; }
CXXStdlibType GetDefaultCXXStdlibType() const override;
- void AddClangCXXStdlibIncludeArgs(
+ void addLibStdCxxIncludePaths(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
@@ -787,9 +820,11 @@ public:
CXXStdlibType GetDefaultCXXStdlibType() const override;
- void AddClangCXXStdlibIncludeArgs(
+ std::string findLibCxxIncludePath() const override;
+ void addLibStdCxxIncludePaths(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
+
bool IsUnwindTablesDefault() const override { return true; }
protected:
@@ -829,7 +864,8 @@ public:
void
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
- void AddClangCXXStdlibIncludeArgs(
+ std::string findLibCxxIncludePath() const override;
+ void addLibStdCxxIncludePaths(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs,
@@ -851,30 +887,45 @@ protected:
Tool *buildLinker() const override;
};
-class LLVM_LIBRARY_VISIBILITY CudaToolChain : public Linux {
+class LLVM_LIBRARY_VISIBILITY CudaToolChain : public ToolChain {
public:
CudaToolChain(const Driver &D, const llvm::Triple &Triple,
- const llvm::opt::ArgList &Args);
+ const ToolChain &HostTC, const llvm::opt::ArgList &Args);
llvm::opt::DerivedArgList *
- TranslateArgs(const llvm::opt::DerivedArgList &Args,
- const char *BoundArch) const override;
+ TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
+ Action::OffloadKind DeviceOffloadKind) const override;
void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
// Never try to use the integrated assembler with CUDA; always fork out to
// ptxas.
bool useIntegratedAs() const override { return false; }
+ 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 SupportsObjCGC() const override { return false; }
void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
- const Generic_GCC::CudaInstallationDetector &cudaInstallation() const {
- return CudaInstallation;
- }
- Generic_GCC::CudaInstallationDetector &cudaInstallation() {
- return CudaInstallation;
- }
+ 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;
+
+ const ToolChain &HostTC;
+ CudaInstallationDetector CudaInstallation;
protected:
Tool *buildAssembler() const override; // ptxas
@@ -895,9 +946,7 @@ public:
CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override;
- void AddClangCXXStdlibIncludeArgs(
- const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args) const override;
+ std::string findLibCxxIncludePath() const override;
void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const override;
@@ -912,6 +961,10 @@ public:
: RuntimeLibType::RLT_CompilerRT;
}
+ const char *getDefaultLinker() const override {
+ return "lld";
+ }
+
private:
Multilib SelectedMultilib;
std::string LibSuffix;
@@ -922,6 +975,13 @@ public:
LanaiToolChain(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args)
: Generic_ELF(D, Triple, Args) {}
+
+ // No support for finding a C++ standard library yet.
+ std::string findLibCxxIncludePath() const override { return ""; }
+ void addLibStdCxxIncludePaths(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override {}
+
bool IsIntegratedAssemblerDefault() const override { return true; }
};
@@ -939,7 +999,7 @@ public:
void
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
- void AddClangCXXStdlibIncludeArgs(
+ void addLibStdCxxIncludePaths(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override;
@@ -981,9 +1041,7 @@ public:
void
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
- void AddClangCXXStdlibIncludeArgs(
- const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args) const override;
+ std::string findLibCxxIncludePath() const override;
CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override;
@@ -1010,6 +1068,41 @@ private:
std::string NaClArmMacrosPath;
};
+class LLVM_LIBRARY_VISIBILITY Fuchsia : public Generic_ELF {
+public:
+ Fuchsia(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+
+ bool isPIEDefault() const override { return true; }
+ bool HasNativeLLVMSupport() const override { return true; }
+ bool IsIntegratedAssemblerDefault() const override { return true; }
+ llvm::DebuggerKind getDefaultDebuggerTuning() const override {
+ return llvm::DebuggerKind::GDB;
+ }
+
+ RuntimeLibType
+ GetRuntimeLibType(const llvm::opt::ArgList &Args) const override;
+ CXXStdlibType
+ GetCXXStdlibType(const llvm::opt::ArgList &Args) const override;
+
+ void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+ void
+ AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+ std::string findLibCxxIncludePath() const override;
+ void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const override;
+
+ const char *getDefaultLinker() const override {
+ return "lld";
+ }
+
+protected:
+ Tool *buildAssembler() const override;
+ Tool *buildLinker() const override;
+};
+
/// TCEToolChain - A tool chain using the llvm bitcode tools to perform
/// all subcommands. See http://tce.cs.tut.fi for our peculiar target.
class LLVM_LIBRARY_VISIBILITY TCEToolChain : public ToolChain {
@@ -1024,14 +1117,22 @@ public:
bool isPICDefaultForced() const override;
};
+/// Toolchain for little endian TCE cores.
+class LLVM_LIBRARY_VISIBILITY TCELEToolChain : public TCEToolChain {
+public:
+ TCELEToolChain(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+ ~TCELEToolChain() override;
+};
+
class LLVM_LIBRARY_VISIBILITY MSVCToolChain : public ToolChain {
public:
MSVCToolChain(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);
llvm::opt::DerivedArgList *
- TranslateArgs(const llvm::opt::DerivedArgList &Args,
- const char *BoundArch) const override;
+ TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
+ Action::OffloadKind DeviceOffloadKind) const override;
bool IsIntegratedAssemblerDefault() const override;
bool IsUnwindTablesDefault() const override;
@@ -1057,7 +1158,9 @@ public:
bool getVisualStudioInstallDir(std::string &path) const;
bool getVisualStudioBinariesFolder(const char *clangProgramPath,
std::string &path) const;
- VersionTuple getMSVCVersionFromExe() const override;
+ VersionTuple
+ computeMSVCVersion(const Driver *D,
+ const llvm::opt::ArgList &Args) const override;
std::string ComputeEffectiveClangTriple(const llvm::opt::ArgList &Args,
types::ID InputType) const override;
@@ -1073,6 +1176,9 @@ protected:
Tool *buildLinker() const override;
Tool *buildAssembler() const override;
+private:
+ VersionTuple getMSVCVersionFromTriple() const;
+ VersionTuple getMSVCVersionFromExe() const;
};
class LLVM_LIBRARY_VISIBILITY CrossWindowsToolChain : public Generic_GCC {
@@ -1144,11 +1250,13 @@ public:
void
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
- void AddClangCXXStdlibIncludeArgs(
+ std::string findLibCxxIncludePath() const override;
+ void addLibStdCxxIncludePaths(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
Tool *SelectTool(const JobAction &JA) const override;
unsigned GetDefaultDwarfVersion() const override { return 2; }
+ SanitizerMask getSupportedSanitizers() const override;
protected:
Tool *buildLinker() const override;
@@ -1189,6 +1297,10 @@ private:
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
+ const char *getDefaultLinker() const override {
+ return "lld";
+ }
+
Tool *buildLinker() const override;
};
@@ -1197,6 +1309,12 @@ public:
PS4CPU(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);
+ // No support for finding a C++ standard library yet.
+ std::string findLibCxxIncludePath() const override { return ""; }
+ void addLibStdCxxIncludePaths(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override {}
+
bool IsMathErrnoDefault() const override { return false; }
bool IsObjCNonFragileABIDefault() const override { return true; }
bool HasNativeLLVMSupport() const override;
@@ -1217,6 +1335,20 @@ protected:
Tool *buildLinker() const override;
};
+class LLVM_LIBRARY_VISIBILITY Contiki : public Generic_ELF {
+public:
+ Contiki(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+
+ // No support for finding a C++ standard library yet.
+ std::string findLibCxxIncludePath() const override { return ""; }
+ void addLibStdCxxIncludePaths(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override {}
+
+ SanitizerMask getSupportedSanitizers() const override;
+};
+
} // end namespace toolchains
} // end namespace driver
} // end namespace clang
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index 270ed0a4e756..2a367bb29aa5 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -40,8 +40,9 @@
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Program.h"
-#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/ScopedPrinter.h"
#include "llvm/Support/TargetParser.h"
+#include "llvm/Support/YAMLParser.h"
#ifdef LLVM_ON_UNIX
#include <unistd.h> // For getuid().
@@ -53,7 +54,7 @@ using namespace clang;
using namespace llvm::opt;
static void handleTargetFeaturesGroup(const ArgList &Args,
- std::vector<const char *> &Features,
+ std::vector<StringRef> &Features,
OptSpecifier Group) {
for (const Arg *A : Args.filtered(Group)) {
StringRef Name = A->getOption().getName();
@@ -108,8 +109,6 @@ static const char *getSparcAsmModeForCPU(StringRef Name,
}
}
-/// CheckPreprocessingOptions - Perform some validation of preprocessing
-/// arguments that is shared with gcc.
static void CheckPreprocessingOptions(const Driver &D, const ArgList &Args) {
if (Arg *A = Args.getLastArg(options::OPT_C, options::OPT_CC)) {
if (!Args.hasArg(options::OPT_E) && !Args.hasArg(options::OPT__SLASH_P) &&
@@ -121,8 +120,6 @@ static void CheckPreprocessingOptions(const Driver &D, const ArgList &Args) {
}
}
-/// CheckCodeGenerationOptions - Perform some validation of code generation
-/// arguments that is shared with gcc.
static void CheckCodeGenerationOptions(const Driver &D, const ArgList &Args) {
// In gcc, only ARM checks this, but it seems reasonable to check universally.
if (Args.hasArg(options::OPT_static))
@@ -233,7 +230,8 @@ static void addDirectoryList(const ArgList &Args, ArgStringList &CmdArgs,
}
static void AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs,
- const ArgList &Args, ArgStringList &CmdArgs) {
+ const ArgList &Args, ArgStringList &CmdArgs,
+ const JobAction &JA) {
const Driver &D = TC.getDriver();
// Add extra linker input arguments which are not treated as inputs
@@ -241,6 +239,14 @@ static void 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 (auto *IA = II.getAction())
+ if (JA.isHostOffloading(Action::OFK_OpenMP) &&
+ IA->isDeviceOffloading(Action::OFK_OpenMP))
+ continue;
+
if (!TC.HasNativeLLVMSupport() && types::isLLVMIR(II.getType()))
// Don't try to pass LLVM inputs unless we have native support.
D.Diag(diag::err_drv_no_linker_llvm_support) << TC.getTripleString();
@@ -274,6 +280,131 @@ static void AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs,
addDirectoryList(Args, CmdArgs, "-L", "LIBRARY_PATH");
}
+/// Add OpenMP linker script arguments at the end of the argument list so that
+/// the fat binary is built by embedding each of the device images into the
+/// host. The linker script also defines a few symbols required by the code
+/// generation so that the images can be easily retrieved at runtime by the
+/// offloading library. This should be used only in tool chains that support
+/// linker scripts.
+static void AddOpenMPLinkerScript(const ToolChain &TC, Compilation &C,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args, ArgStringList &CmdArgs,
+ const JobAction &JA) {
+
+ // If this is not an OpenMP host toolchain, we don't need to do anything.
+ if (!JA.isHostOffloading(Action::OFK_OpenMP))
+ return;
+
+ // Create temporary linker script. Keep it if save-temps is enabled.
+ const char *LKS;
+ SmallString<256> Name = llvm::sys::path::filename(Output.getFilename());
+ if (C.getDriver().isSaveTempsEnabled()) {
+ llvm::sys::path::replace_extension(Name, "lk");
+ LKS = C.getArgs().MakeArgString(Name.c_str());
+ } else {
+ llvm::sys::path::replace_extension(Name, "");
+ Name = C.getDriver().GetTemporaryPath(Name, "lk");
+ LKS = C.addTempFile(C.getArgs().MakeArgString(Name.c_str()));
+ }
+
+ // Add linker script option to the command.
+ CmdArgs.push_back("-T");
+ CmdArgs.push_back(LKS);
+
+ // Create a buffer to write the contents of the linker script.
+ std::string LksBuffer;
+ llvm::raw_string_ostream LksStream(LksBuffer);
+
+ // Get the OpenMP offload tool chains so that we can extract the triple
+ // associated with each device input.
+ auto OpenMPToolChains = C.getOffloadToolChains<Action::OFK_OpenMP>();
+ assert(OpenMPToolChains.first != OpenMPToolChains.second &&
+ "No OpenMP toolchains??");
+
+ // Track the input file name and device triple in order to build the script,
+ // inserting binaries in the designated sections.
+ SmallVector<std::pair<std::string, const char *>, 8> InputBinaryInfo;
+
+ // Add commands to embed target binaries. We ensure that each section and
+ // image is 16-byte aligned. This is not mandatory, but increases the
+ // likelihood of data to be aligned with a cache block in several main host
+ // machines.
+ LksStream << "/*\n";
+ LksStream << " OpenMP Offload Linker Script\n";
+ LksStream << " *** Automatically generated by Clang ***\n";
+ LksStream << "*/\n";
+ LksStream << "TARGET(binary)\n";
+ auto DTC = OpenMPToolChains.first;
+ for (auto &II : Inputs) {
+ const Action *A = II.getAction();
+ // Is this a device linking action?
+ if (A && isa<LinkJobAction>(A) &&
+ A->isDeviceOffloading(Action::OFK_OpenMP)) {
+ assert(DTC != OpenMPToolChains.second &&
+ "More device inputs than device toolchains??");
+ InputBinaryInfo.push_back(std::make_pair(
+ DTC->second->getTriple().normalize(), II.getFilename()));
+ ++DTC;
+ LksStream << "INPUT(" << II.getFilename() << ")\n";
+ }
+ }
+
+ assert(DTC == OpenMPToolChains.second &&
+ "Less device inputs than device toolchains??");
+
+ LksStream << "SECTIONS\n";
+ LksStream << "{\n";
+ LksStream << " .omp_offloading :\n";
+ LksStream << " ALIGN(0x10)\n";
+ LksStream << " {\n";
+
+ for (auto &BI : InputBinaryInfo) {
+ LksStream << " . = ALIGN(0x10);\n";
+ LksStream << " PROVIDE_HIDDEN(.omp_offloading.img_start." << BI.first
+ << " = .);\n";
+ LksStream << " " << BI.second << "\n";
+ LksStream << " PROVIDE_HIDDEN(.omp_offloading.img_end." << BI.first
+ << " = .);\n";
+ }
+
+ LksStream << " }\n";
+ // Add commands to define host entries begin and end. We use 1-byte subalign
+ // so that the linker does not add any padding and the elements in this
+ // section form an array.
+ LksStream << " .omp_offloading.entries :\n";
+ LksStream << " ALIGN(0x10)\n";
+ LksStream << " SUBALIGN(0x01)\n";
+ LksStream << " {\n";
+ LksStream << " PROVIDE_HIDDEN(.omp_offloading.entries_begin = .);\n";
+ LksStream << " *(.omp_offloading.entries)\n";
+ LksStream << " PROVIDE_HIDDEN(.omp_offloading.entries_end = .);\n";
+ LksStream << " }\n";
+ LksStream << "}\n";
+ LksStream << "INSERT BEFORE .data\n";
+ LksStream.flush();
+
+ // Dump the contents of the linker script if the user requested that. We
+ // support this option to enable testing of behavior with -###.
+ if (C.getArgs().hasArg(options::OPT_fopenmp_dump_offload_linker_script))
+ llvm::errs() << LksBuffer;
+
+ // If this is a dry run, do not create the linker script file.
+ if (C.getArgs().hasArg(options::OPT__HASH_HASH_HASH))
+ return;
+
+ // Open script file and write the contents.
+ std::error_code EC;
+ llvm::raw_fd_ostream Lksf(LKS, EC, llvm::sys::fs::F_None);
+
+ if (EC) {
+ C.getDriver().Diag(clang::diag::err_unable_to_make_temp) << EC.message();
+ return;
+ }
+
+ Lksf << LksBuffer;
+}
+
/// \brief Determine whether Objective-C automated reference counting is
/// enabled.
static bool isObjCAutoRefCount(const ArgList &Args) {
@@ -296,38 +427,25 @@ static bool forwardToGCC(const Option &O) {
!O.hasFlag(options::DriverOption) && !O.hasFlag(options::LinkerInput);
}
-/// Add the C++ include args of other offloading toolchains. If this is a host
-/// job, the device toolchains are added. If this is a device job, the host
-/// toolchains will be added.
-static void addExtraOffloadCXXStdlibIncludeArgs(Compilation &C,
- const JobAction &JA,
- const ArgList &Args,
- ArgStringList &CmdArgs) {
-
- if (JA.isHostOffloading(Action::OFK_Cuda))
- C.getSingleOffloadToolChain<Action::OFK_Cuda>()
- ->AddClangCXXStdlibIncludeArgs(Args, CmdArgs);
- else if (JA.isDeviceOffloading(Action::OFK_Cuda))
- C.getSingleOffloadToolChain<Action::OFK_Host>()
- ->AddClangCXXStdlibIncludeArgs(Args, CmdArgs);
-
- // TODO: Add support for other programming models here.
-}
-
-/// Add the include args that are specific of each offloading programming model.
-static void addExtraOffloadSpecificIncludeArgs(Compilation &C,
- const JobAction &JA,
- const ArgList &Args,
- ArgStringList &CmdArgs) {
-
+/// Apply \a Work on the current tool chain \a RegularToolChain and any other
+/// offloading tool chain that is associated with the current action \a JA.
+static void
+forAllAssociatedToolChains(Compilation &C, const JobAction &JA,
+ const ToolChain &RegularToolChain,
+ llvm::function_ref<void(const ToolChain &)> Work) {
+ // Apply Work on the current/regular tool chain.
+ Work(RegularToolChain);
+
+ // Apply Work on all the offloading tool chains associated with the current
+ // action.
if (JA.isHostOffloading(Action::OFK_Cuda))
- C.getSingleOffloadToolChain<Action::OFK_Host>()->AddCudaIncludeArgs(
- Args, CmdArgs);
+ Work(*C.getSingleOffloadToolChain<Action::OFK_Cuda>());
else if (JA.isDeviceOffloading(Action::OFK_Cuda))
- C.getSingleOffloadToolChain<Action::OFK_Cuda>()->AddCudaIncludeArgs(
- Args, CmdArgs);
+ Work(*C.getSingleOffloadToolChain<Action::OFK_Host>());
- // TODO: Add support for other programming models here.
+ //
+ // TODO: Add support for other offloading programming models here.
+ //
}
void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA,
@@ -423,6 +541,13 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA,
}
}
+ // Add offload include arguments specific for CUDA. This must happen before
+ // we -I or -include anything else, because we must pick up the CUDA headers
+ // from the particular CUDA installation, rather than from e.g.
+ // /usr/local/include.
+ if (JA.isOffloading(Action::OFK_Cuda))
+ getToolChain().AddCudaIncludeArgs(Args, CmdArgs);
+
// Add -i* options, and automatically translate to
// -include-pch/-include-pth for transparent PCH support. It's
// wonky, but we include looking for .gch so we can support seamless
@@ -604,22 +729,22 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA,
// of an offloading programming model.
// Add C++ include arguments, if needed.
- if (types::isCXX(Inputs[0].getType())) {
- getToolChain().AddClangCXXStdlibIncludeArgs(Args, CmdArgs);
- addExtraOffloadCXXStdlibIncludeArgs(C, JA, Args, CmdArgs);
- }
+ if (types::isCXX(Inputs[0].getType()))
+ forAllAssociatedToolChains(C, JA, getToolChain(),
+ [&Args, &CmdArgs](const ToolChain &TC) {
+ TC.AddClangCXXStdlibIncludeArgs(Args, CmdArgs);
+ });
// Add system include arguments for all targets but IAMCU.
- if (!IsIAMCU) {
- getToolChain().AddClangSystemIncludeArgs(Args, CmdArgs);
- addExtraOffloadCXXStdlibIncludeArgs(C, JA, Args, CmdArgs);
- } else {
+ if (!IsIAMCU)
+ forAllAssociatedToolChains(C, JA, getToolChain(),
+ [&Args, &CmdArgs](const ToolChain &TC) {
+ TC.AddClangSystemIncludeArgs(Args, CmdArgs);
+ });
+ else {
// For IAMCU add special include arguments.
getToolChain().AddIAMCUIncludeArgs(Args, CmdArgs);
}
-
- // Add offload include arguments, if needed.
- addExtraOffloadSpecificIncludeArgs(C, JA, Args, CmdArgs);
}
// FIXME: Move to target hook.
@@ -703,7 +828,7 @@ static void getARMArchCPUFromArgs(const ArgList &Args, llvm::StringRef &Arch,
// FIXME: Use ARMTargetParser.
static void getARMHWDivFeatures(const Driver &D, const Arg *A,
const ArgList &Args, StringRef HWDiv,
- std::vector<const char *> &Features) {
+ std::vector<StringRef> &Features) {
unsigned HWDivID = llvm::ARM::parseHWDiv(HWDiv);
if (!llvm::ARM::getHWDivFeatures(HWDivID, Features))
D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
@@ -712,7 +837,7 @@ static void getARMHWDivFeatures(const Driver &D, const Arg *A,
// Handle -mfpu=.
static void getARMFPUFeatures(const Driver &D, const Arg *A,
const ArgList &Args, StringRef FPU,
- std::vector<const char *> &Features) {
+ std::vector<StringRef> &Features) {
unsigned FPUID = llvm::ARM::parseFPU(FPU);
if (!llvm::ARM::getFPUFeatures(FPUID, Features))
D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
@@ -720,13 +845,13 @@ static void getARMFPUFeatures(const Driver &D, const Arg *A,
// Decode ARM features from string like +[no]featureA+[no]featureB+...
static bool DecodeARMFeatures(const Driver &D, StringRef text,
- std::vector<const char *> &Features) {
+ std::vector<StringRef> &Features) {
SmallVector<StringRef, 8> Split;
text.split(Split, StringRef("+"), -1, false);
for (StringRef Feature : Split) {
- const char *FeatureName = llvm::ARM::getArchExtFeature(Feature);
- if (FeatureName)
+ StringRef FeatureName = llvm::ARM::getArchExtFeature(Feature);
+ if (!FeatureName.empty())
Features.push_back(FeatureName);
else
return false;
@@ -739,7 +864,7 @@ static bool DecodeARMFeatures(const Driver &D, StringRef text,
// to handle -march=native correctly.
static void checkARMArchName(const Driver &D, const Arg *A, const ArgList &Args,
llvm::StringRef ArchName,
- std::vector<const char *> &Features,
+ std::vector<StringRef> &Features,
const llvm::Triple &Triple) {
std::pair<StringRef, StringRef> Split = ArchName.split("+");
@@ -752,7 +877,7 @@ static void checkARMArchName(const Driver &D, const Arg *A, const ArgList &Args,
// Check -mcpu=. Needs ArchName to handle -mcpu=generic.
static void checkARMCPUName(const Driver &D, const Arg *A, const ArgList &Args,
llvm::StringRef CPUName, llvm::StringRef ArchName,
- std::vector<const char *> &Features,
+ std::vector<StringRef> &Features,
const llvm::Triple &Triple) {
std::pair<StringRef, StringRef> Split = CPUName.split("+");
@@ -773,7 +898,7 @@ static bool useAAPCSForMachO(const llvm::Triple &T) {
// -mfloat-abi=.
arm::FloatABI arm::getARMFloatABI(const ToolChain &TC, const ArgList &Args) {
const Driver &D = TC.getDriver();
- const llvm::Triple Triple(TC.ComputeEffectiveClangTriple(Args));
+ const llvm::Triple &Triple = TC.getEffectiveTriple();
auto SubArch = getARMSubArchVersionNumber(Triple);
arm::FloatABI ABI = FloatABI::Invalid;
if (Arg *A =
@@ -876,7 +1001,8 @@ arm::FloatABI arm::getARMFloatABI(const ToolChain &TC, const ArgList &Args) {
static void getARMTargetFeatures(const ToolChain &TC,
const llvm::Triple &Triple,
const ArgList &Args,
- std::vector<const char *> &Features,
+ ArgStringList &CmdArgs,
+ std::vector<StringRef> &Features,
bool ForAS) {
const Driver &D = TC.getDriver();
@@ -1014,6 +1140,29 @@ static void getARMTargetFeatures(const ToolChain &TC,
Features.push_back("+long-calls");
}
+ // Generate execute-only output (no data access to code sections).
+ // Supported only on ARMv6T2 and ARMv7 and above.
+ // Cannot be combined with -mno-movt or -mlong-calls
+ if (Arg *A = Args.getLastArg(options::OPT_mexecute_only, options::OPT_mno_execute_only)) {
+ if (A->getOption().matches(options::OPT_mexecute_only)) {
+ if (getARMSubArchVersionNumber(Triple) < 7 &&
+ llvm::ARM::parseArch(Triple.getArchName()) != llvm::ARM::AK_ARMV6T2)
+ D.Diag(diag::err_target_unsupported_execute_only) << Triple.getArchName();
+ else if (Arg *B = Args.getLastArg(options::OPT_mno_movt))
+ D.Diag(diag::err_opt_not_valid_with_opt) << A->getAsString(Args) << B->getAsString(Args);
+ // Long calls create constant pool entries and have not yet been fixed up
+ // to play nicely with execute-only. Hence, they cannot be used in
+ // execute-only code for now
+ else if (Arg *B = Args.getLastArg(options::OPT_mlong_calls, options::OPT_mno_long_calls)) {
+ if (B->getOption().matches(options::OPT_mlong_calls))
+ D.Diag(diag::err_opt_not_valid_with_opt) << A->getAsString(Args) << B->getAsString(Args);
+ }
+
+ CmdArgs.push_back("-backend-option");
+ CmdArgs.push_back("-arm-execute-only");
+ }
+ }
+
// Kernel code has more strict alignment requirements.
if (KernelOrKext)
Features.push_back("+strict-align");
@@ -1146,9 +1295,9 @@ void Clang::AddARMTargetArgs(const llvm::Triple &Triple, const ArgList &Args,
// ARM tools end.
/// getAArch64TargetCPU - Get the (LLVM) name of the AArch64 cpu we are
-/// targeting.
-static std::string getAArch64TargetCPU(const ArgList &Args) {
- Arg *A;
+/// targeting. Set \p A to the Arg corresponding to the -mcpu or -mtune
+/// arguments if they are provided, or to nullptr otherwise.
+static std::string getAArch64TargetCPU(const ArgList &Args, Arg *&A) {
std::string CPU;
// If we have -mtune or -mcpu, use that.
if ((A = Args.getLastArg(options::OPT_mtune_EQ))) {
@@ -1174,8 +1323,7 @@ static std::string getAArch64TargetCPU(const ArgList &Args) {
void Clang::AddAArch64TargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
- std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args);
- llvm::Triple Triple(TripleStr);
+ const llvm::Triple &Triple = getToolChain().getEffectiveTriple();
if (!Args.hasFlag(options::OPT_mred_zone, options::OPT_mno_red_zone, true) ||
Args.hasArg(options::OPT_mkernel) ||
@@ -1373,7 +1521,7 @@ static mips::FloatABI getMipsFloatABI(const Driver &D, const ArgList &Args) {
}
static void AddTargetFeature(const ArgList &Args,
- std::vector<const char *> &Features,
+ std::vector<StringRef> &Features,
OptSpecifier OnOpt, OptSpecifier OffOpt,
StringRef FeatureName) {
if (Arg *A = Args.getLastArg(OnOpt, OffOpt)) {
@@ -1386,7 +1534,7 @@ static void AddTargetFeature(const ArgList &Args,
static void getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args,
- std::vector<const char *> &Features) {
+ std::vector<StringRef> &Features) {
StringRef CPUName;
StringRef ABIName;
mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName);
@@ -1597,19 +1745,12 @@ static std::string getPPCTargetCPU(const ArgList &Args) {
static void getPPCTargetFeatures(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args,
- std::vector<const char *> &Features) {
+ std::vector<StringRef> &Features) {
handleTargetFeaturesGroup(Args, Features, options::OPT_m_ppc_Features_Group);
ppc::FloatABI FloatABI = ppc::getPPCFloatABI(D, Args);
- if (FloatABI == ppc::FloatABI::Soft &&
- !(Triple.getArch() == llvm::Triple::ppc64 ||
- Triple.getArch() == llvm::Triple::ppc64le))
- Features.push_back("+soft-float");
- else if (FloatABI == ppc::FloatABI::Soft &&
- (Triple.getArch() == llvm::Triple::ppc64 ||
- Triple.getArch() == llvm::Triple::ppc64le))
- D.Diag(diag::err_drv_invalid_mfloat_abi)
- << "soft float is not supported for ppc64";
+ if (FloatABI == ppc::FloatABI::Soft)
+ Features.push_back("-hard-float");
// Altivec is a bit weird, allow overriding of the Altivec feature here.
AddTargetFeature(Args, Features, options::OPT_faltivec,
@@ -1767,7 +1908,7 @@ sparc::FloatABI sparc::getSparcFloatABI(const Driver &D,
}
static void getSparcTargetFeatures(const Driver &D, const ArgList &Args,
- std::vector<const char *> &Features) {
+ std::vector<StringRef> &Features) {
sparc::FloatABI FloatABI = sparc::getSparcFloatABI(D, Args);
if (FloatABI == sparc::FloatABI::Soft)
Features.push_back("+soft-float");
@@ -1804,7 +1945,7 @@ static const char *getSystemZTargetCPU(const ArgList &Args) {
}
static void getSystemZTargetFeatures(const ArgList &Args,
- std::vector<const char *> &Features) {
+ std::vector<StringRef> &Features) {
// -m(no-)htm overrides use of the transactional-execution facility.
if (Arg *A = Args.getLastArg(options::OPT_mhtm, options::OPT_mno_htm)) {
if (A->getOption().matches(options::OPT_mhtm))
@@ -1875,6 +2016,11 @@ static const char *getX86TargetCPU(const ArgList &Args,
if (Triple.isOSDarwin()) {
if (Triple.getArchName() == "x86_64h")
return "core-avx2";
+ // macosx10.12 drops support for all pre-Penryn Macs.
+ // Simulators can still run on 10.11 though, like Xcode.
+ if (Triple.isMacOSX() && !Triple.isOSVersionLT(10, 12))
+ return "penryn";
+ // The oldest x86_64 Macs have core2/Merom; the oldest x86 Macs have Yonah.
return Is64Bit ? "core2" : "yonah";
}
@@ -1926,13 +2072,15 @@ static StringRef getWebAssemblyTargetCPU(const ArgList &Args) {
static std::string getCPUName(const ArgList &Args, const llvm::Triple &T,
bool FromAs = false) {
+ Arg *A;
+
switch (T.getArch()) {
default:
return "";
case llvm::Triple::aarch64:
case llvm::Triple::aarch64_be:
- return getAArch64TargetCPU(Args);
+ return getAArch64TargetCPU(Args, A);
case llvm::Triple::arm:
case llvm::Triple::armeb:
@@ -2007,8 +2155,27 @@ static std::string getCPUName(const ArgList &Args, const llvm::Triple &T,
}
}
+static unsigned getLTOParallelism(const ArgList &Args, const Driver &D) {
+ unsigned Parallelism = 0;
+ Arg *LtoJobsArg = Args.getLastArg(options::OPT_flto_jobs_EQ);
+ if (LtoJobsArg &&
+ StringRef(LtoJobsArg->getValue()).getAsInteger(10, Parallelism))
+ D.Diag(diag::err_drv_invalid_int_value) << LtoJobsArg->getAsString(Args)
+ << LtoJobsArg->getValue();
+ return Parallelism;
+}
+
+// CloudABI and WebAssembly use -ffunction-sections and -fdata-sections by
+// default.
+static bool isUseSeparateSections(const llvm::Triple &Triple) {
+ return Triple.getOS() == llvm::Triple::CloudABI ||
+ Triple.getArch() == llvm::Triple::wasm32 ||
+ Triple.getArch() == llvm::Triple::wasm64;
+}
+
static void AddGoldPlugin(const ToolChain &ToolChain, const ArgList &Args,
- ArgStringList &CmdArgs, bool IsThinLTO) {
+ ArgStringList &CmdArgs, bool IsThinLTO,
+ const Driver &D) {
// 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.
@@ -2041,6 +2208,10 @@ static void AddGoldPlugin(const ToolChain &ToolChain, const ArgList &Args,
if (IsThinLTO)
CmdArgs.push_back("-plugin-opt=thinlto");
+ if (unsigned Parallelism = getLTOParallelism(Args, D))
+ CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=jobs=") +
+ llvm::to_string(Parallelism)));
+
// If an explicit debugger tuning argument appeared, pass it along.
if (Arg *A = Args.getLastArg(options::OPT_gTune_Group,
options::OPT_ggdbN_Group)) {
@@ -2051,6 +2222,19 @@ static void AddGoldPlugin(const ToolChain &ToolChain, const ArgList &Args,
else
CmdArgs.push_back("-plugin-opt=-debugger-tune=gdb");
}
+
+ bool UseSeparateSections =
+ isUseSeparateSections(ToolChain.getEffectiveTriple());
+
+ if (Args.hasFlag(options::OPT_ffunction_sections,
+ options::OPT_fno_function_sections, UseSeparateSections)) {
+ CmdArgs.push_back("-plugin-opt=-function-sections");
+ }
+
+ if (Args.hasFlag(options::OPT_fdata_sections, options::OPT_fno_data_sections,
+ UseSeparateSections)) {
+ CmdArgs.push_back("-plugin-opt=-data-sections");
+ }
}
/// This is a helper function for validating the optional refinement step
@@ -2186,7 +2370,7 @@ static void ParseMRecip(const Driver &D, const ArgList &Args,
static void getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args,
- std::vector<const char *> &Features) {
+ std::vector<StringRef> &Features) {
// If -march=native, autodetect the feature list.
if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
if (StringRef(A->getValue()) == "native") {
@@ -2345,29 +2529,14 @@ void Clang::AddWebAssemblyTargetArgs(const ArgList &Args,
// Decode AArch64 features from string like +[no]featureA+[no]featureB+...
static bool DecodeAArch64Features(const Driver &D, StringRef text,
- std::vector<const char *> &Features) {
+ std::vector<StringRef> &Features) {
SmallVector<StringRef, 8> Split;
text.split(Split, StringRef("+"), -1, false);
for (StringRef Feature : Split) {
- const char *result = llvm::StringSwitch<const char *>(Feature)
- .Case("fp", "+fp-armv8")
- .Case("simd", "+neon")
- .Case("crc", "+crc")
- .Case("crypto", "+crypto")
- .Case("fp16", "+fullfp16")
- .Case("profile", "+spe")
- .Case("ras", "+ras")
- .Case("nofp", "-fp-armv8")
- .Case("nosimd", "-neon")
- .Case("nocrc", "-crc")
- .Case("nocrypto", "-crypto")
- .Case("nofp16", "-fullfp16")
- .Case("noprofile", "-spe")
- .Case("noras", "-ras")
- .Default(nullptr);
- if (result)
- Features.push_back(result);
+ StringRef FeatureName = llvm::AArch64::getArchExtFeature(Feature);
+ if (!FeatureName.empty())
+ Features.push_back(FeatureName);
else if (Feature == "neon" || Feature == "noneon")
D.Diag(diag::err_drv_no_neon_modifier);
else
@@ -2379,23 +2548,21 @@ static bool DecodeAArch64Features(const Driver &D, StringRef text,
// Check if the CPU name and feature modifiers in -mcpu are legal. If yes,
// decode CPU and feature.
static bool DecodeAArch64Mcpu(const Driver &D, StringRef Mcpu, StringRef &CPU,
- std::vector<const char *> &Features) {
+ std::vector<StringRef> &Features) {
std::pair<StringRef, StringRef> Split = Mcpu.split("+");
CPU = Split.first;
- if (CPU == "cortex-a53" || CPU == "cortex-a57" ||
- CPU == "cortex-a72" || CPU == "cortex-a35" || CPU == "exynos-m1" ||
- CPU == "kryo" || CPU == "cortex-a73" || CPU == "vulcan") {
- Features.push_back("+neon");
- Features.push_back("+crc");
- Features.push_back("+crypto");
- } else if (CPU == "cyclone") {
- Features.push_back("+neon");
- Features.push_back("+crypto");
- } else if (CPU == "generic") {
+
+ if (CPU == "generic") {
Features.push_back("+neon");
} else {
- return false;
- }
+ unsigned ArchKind = llvm::AArch64::parseCPUArch(CPU);
+ if (!llvm::AArch64::getArchFeatures(ArchKind, Features))
+ return false;
+
+ unsigned Extension = llvm::AArch64::getDefaultExtensions(CPU, ArchKind);
+ if (!llvm::AArch64::getExtensionFeatures(Extension, Features))
+ return false;
+ }
if (Split.second.size() && !DecodeAArch64Features(D, Split.second, Features))
return false;
@@ -2406,21 +2573,14 @@ static bool DecodeAArch64Mcpu(const Driver &D, StringRef Mcpu, StringRef &CPU,
static bool
getAArch64ArchFeaturesFromMarch(const Driver &D, StringRef March,
const ArgList &Args,
- std::vector<const char *> &Features) {
+ std::vector<StringRef> &Features) {
std::string MarchLowerCase = March.lower();
std::pair<StringRef, StringRef> Split = StringRef(MarchLowerCase).split("+");
- if (Split.first == "armv8-a" || Split.first == "armv8a") {
- // ok, no additional features.
- } else if (Split.first == "armv8.1-a" || Split.first == "armv8.1a") {
- Features.push_back("+v8.1a");
- } else if (Split.first == "armv8.2-a" || Split.first == "armv8.2a" ) {
- Features.push_back("+v8.2a");
- } else {
- return false;
- }
-
- if (Split.second.size() && !DecodeAArch64Features(D, Split.second, Features))
+ unsigned ArchKind = llvm::AArch64::parseArch(Split.first);
+ if (ArchKind == static_cast<unsigned>(llvm::AArch64::ArchKind::AK_INVALID) ||
+ !llvm::AArch64::getArchFeatures(ArchKind, Features) ||
+ (Split.second.size() && !DecodeAArch64Features(D, Split.second, Features)))
return false;
return true;
@@ -2429,7 +2589,7 @@ getAArch64ArchFeaturesFromMarch(const Driver &D, StringRef March,
static bool
getAArch64ArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu,
const ArgList &Args,
- std::vector<const char *> &Features) {
+ std::vector<StringRef> &Features) {
StringRef CPU;
std::string McpuLowerCase = Mcpu.lower();
if (!DecodeAArch64Mcpu(D, McpuLowerCase, CPU, Features))
@@ -2441,7 +2601,7 @@ getAArch64ArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu,
static bool
getAArch64MicroArchFeaturesFromMtune(const Driver &D, StringRef Mtune,
const ArgList &Args,
- std::vector<const char *> &Features) {
+ std::vector<StringRef> &Features) {
std::string MtuneLowerCase = Mtune.lower();
// Handle CPU name is 'native'.
if (MtuneLowerCase == "native")
@@ -2456,9 +2616,9 @@ getAArch64MicroArchFeaturesFromMtune(const Driver &D, StringRef Mtune,
static bool
getAArch64MicroArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu,
const ArgList &Args,
- std::vector<const char *> &Features) {
+ std::vector<StringRef> &Features) {
StringRef CPU;
- std::vector<const char *> DecodedFeature;
+ std::vector<StringRef> DecodedFeature;
std::string McpuLowerCase = Mcpu.lower();
if (!DecodeAArch64Mcpu(D, McpuLowerCase, CPU, DecodedFeature))
return false;
@@ -2467,7 +2627,7 @@ getAArch64MicroArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu,
}
static void getAArch64TargetFeatures(const Driver &D, const ArgList &Args,
- std::vector<const char *> &Features) {
+ std::vector<StringRef> &Features) {
Arg *A;
bool success = true;
// Enable NEON by default.
@@ -2477,8 +2637,8 @@ static void getAArch64TargetFeatures(const Driver &D, const ArgList &Args,
else if ((A = Args.getLastArg(options::OPT_mcpu_EQ)))
success = getAArch64ArchFeaturesFromMcpu(D, A->getValue(), Args, Features);
else if (Args.hasArg(options::OPT_arch))
- success = getAArch64ArchFeaturesFromMcpu(D, getAArch64TargetCPU(Args), Args,
- Features);
+ success = getAArch64ArchFeaturesFromMcpu(D, getAArch64TargetCPU(Args, A),
+ Args, Features);
if (success && (A = Args.getLastArg(options::OPT_mtune_EQ)))
success =
@@ -2486,9 +2646,9 @@ static void getAArch64TargetFeatures(const Driver &D, const ArgList &Args,
else if (success && (A = Args.getLastArg(options::OPT_mcpu_EQ)))
success =
getAArch64MicroArchFeaturesFromMcpu(D, A->getValue(), Args, Features);
- else if (Args.hasArg(options::OPT_arch))
- success = getAArch64MicroArchFeaturesFromMcpu(D, getAArch64TargetCPU(Args),
- Args, Features);
+ else if (success && Args.hasArg(options::OPT_arch))
+ success = getAArch64MicroArchFeaturesFromMcpu(
+ D, getAArch64TargetCPU(Args, A), Args, Features);
if (!success)
D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
@@ -2517,38 +2677,27 @@ static void getAArch64TargetFeatures(const Driver &D, const ArgList &Args,
}
static void getHexagonTargetFeatures(const ArgList &Args,
- std::vector<const char *> &Features) {
- bool HasHVX = false, HasHVXD = false;
-
- // FIXME: This should be able to use handleTargetFeaturesGroup except it is
- // doing dependent option handling here rather than in initFeatureMap or a
- // similar handler.
- for (auto &A : Args) {
- auto &Opt = A->getOption();
- if (Opt.matches(options::OPT_mhexagon_hvx))
- HasHVX = true;
- else if (Opt.matches(options::OPT_mno_hexagon_hvx))
- HasHVXD = HasHVX = false;
- else if (Opt.matches(options::OPT_mhexagon_hvx_double))
- HasHVXD = HasHVX = true;
- else if (Opt.matches(options::OPT_mno_hexagon_hvx_double))
- HasHVXD = false;
- else
- continue;
- A->claim();
+ std::vector<StringRef> &Features) {
+ handleTargetFeaturesGroup(Args, Features,
+ options::OPT_m_hexagon_Features_Group);
+
+ bool UseLongCalls = false;
+ if (Arg *A = Args.getLastArg(options::OPT_mlong_calls,
+ options::OPT_mno_long_calls)) {
+ if (A->getOption().matches(options::OPT_mlong_calls))
+ UseLongCalls = true;
}
- Features.push_back(HasHVX ? "+hvx" : "-hvx");
- Features.push_back(HasHVXD ? "+hvx-double" : "-hvx-double");
+ Features.push_back(UseLongCalls ? "+long-calls" : "-long-calls");
}
static void getWebAssemblyTargetFeatures(const ArgList &Args,
- std::vector<const char *> &Features) {
+ std::vector<StringRef> &Features) {
handleTargetFeaturesGroup(Args, Features, options::OPT_m_wasm_Features_Group);
}
static void getAMDGPUTargetFeatures(const Driver &D, const ArgList &Args,
- std::vector<const char *> &Features) {
+ std::vector<StringRef> &Features) {
if (const Arg *dAbi = Args.getLastArg(options::OPT_mamdgpu_debugger_abi)) {
StringRef value = dAbi->getValue();
if (value == "1.0") {
@@ -2568,7 +2717,7 @@ static void getTargetFeatures(const ToolChain &TC, const llvm::Triple &Triple,
const ArgList &Args, ArgStringList &CmdArgs,
bool ForAS) {
const Driver &D = TC.getDriver();
- std::vector<const char *> Features;
+ std::vector<StringRef> Features;
switch (Triple.getArch()) {
default:
break;
@@ -2583,7 +2732,7 @@ static void getTargetFeatures(const ToolChain &TC, const llvm::Triple &Triple,
case llvm::Triple::armeb:
case llvm::Triple::thumb:
case llvm::Triple::thumbeb:
- getARMTargetFeatures(TC, Triple, Args, Features, ForAS);
+ getARMTargetFeatures(TC, Triple, Args, CmdArgs, Features, ForAS);
break;
case llvm::Triple::ppc:
@@ -2608,7 +2757,7 @@ static void getTargetFeatures(const ToolChain &TC, const llvm::Triple &Triple,
case llvm::Triple::wasm32:
case llvm::Triple::wasm64:
getWebAssemblyTargetFeatures(Args, Features);
- break;
+ break;
case llvm::Triple::sparc:
case llvm::Triple::sparcel:
case llvm::Triple::sparcv9:
@@ -2623,22 +2772,22 @@ static void getTargetFeatures(const ToolChain &TC, const llvm::Triple &Triple,
// Find the last of each feature.
llvm::StringMap<unsigned> LastOpt;
for (unsigned I = 0, N = Features.size(); I < N; ++I) {
- const char *Name = Features[I];
+ StringRef Name = Features[I];
assert(Name[0] == '-' || Name[0] == '+');
- LastOpt[Name + 1] = I;
+ LastOpt[Name.drop_front(1)] = I;
}
for (unsigned I = 0, N = Features.size(); I < N; ++I) {
// If this feature was overridden, ignore it.
- const char *Name = Features[I];
- llvm::StringMap<unsigned>::iterator LastI = LastOpt.find(Name + 1);
+ StringRef Name = Features[I];
+ llvm::StringMap<unsigned>::iterator LastI = LastOpt.find(Name.drop_front(1));
assert(LastI != LastOpt.end());
unsigned Last = LastI->second;
if (Last != I)
continue;
CmdArgs.push_back("-target-feature");
- CmdArgs.push_back(Name);
+ CmdArgs.push_back(Name.data());
}
}
@@ -2864,6 +3013,27 @@ static void CollectArgsForIntegratedAssembler(Compilation &C,
DefaultIncrementalLinkerCompatible))
CmdArgs.push_back("-mincremental-linker-compatible");
+ switch (C.getDefaultToolChain().getArch()) {
+ case llvm::Triple::arm:
+ case llvm::Triple::armeb:
+ case llvm::Triple::thumb:
+ case llvm::Triple::thumbeb:
+ if (Arg *A = Args.getLastArg(options::OPT_mimplicit_it_EQ)) {
+ StringRef Value = A->getValue();
+ if (Value == "always" || Value == "never" || Value == "arm" ||
+ Value == "thumb") {
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back(Args.MakeArgString("-arm-implicit-it=" + Value));
+ } else {
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << Value;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
// When passing -I arguments to the assembler we sometimes need to
// unconditionally take the next argument. For example, when parsing
// '-Wa,-I -Wa,foo' we need to accept the -Wa,foo arg after seeing the
@@ -2976,6 +3146,27 @@ static void CollectArgsForIntegratedAssembler(Compilation &C,
} else if (Value.startswith("-mcpu") || Value.startswith("-mfpu") ||
Value.startswith("-mhwdiv") || Value.startswith("-march")) {
// Do nothing, we'll validate it later.
+ } else if (Value == "-defsym") {
+ if (A->getNumValues() != 2) {
+ D.Diag(diag::err_drv_defsym_invalid_format) << Value;
+ break;
+ }
+ const char *S = A->getValue(1);
+ auto Pair = StringRef(S).split('=');
+ auto Sym = Pair.first;
+ auto SVal = Pair.second;
+
+ if (Sym.empty() || SVal.empty()) {
+ D.Diag(diag::err_drv_defsym_invalid_format) << S;
+ break;
+ }
+ int64_t IVal;
+ if (SVal.getAsInteger(0, IVal)) {
+ D.Diag(diag::err_drv_defsym_invalid_symval) << SVal;
+ break;
+ }
+ CmdArgs.push_back(Value.data());
+ TakeNextArg = true;
} else {
D.Diag(diag::err_drv_unsupported_option_argument)
<< A->getOption().getName() << Value;
@@ -3004,72 +3195,23 @@ static void addClangRT(const ToolChain &TC, const ArgList &Args,
CmdArgs.push_back(TC.getCompilerRTArgString(Args, "builtins"));
}
-namespace {
-enum OpenMPRuntimeKind {
- /// An unknown OpenMP runtime. We can't generate effective OpenMP code
- /// without knowing what runtime to target.
- OMPRT_Unknown,
-
- /// The LLVM OpenMP runtime. When completed and integrated, this will become
- /// the default for Clang.
- OMPRT_OMP,
-
- /// The GNU OpenMP runtime. Clang doesn't support generating OpenMP code for
- /// this runtime but can swallow the pragmas, and find and link against the
- /// runtime library itself.
- OMPRT_GOMP,
-
- /// The legacy name for the LLVM OpenMP runtime from when it was the Intel
- /// OpenMP runtime. We support this mode for users with existing dependencies
- /// on this runtime library name.
- OMPRT_IOMP5
-};
-}
-
-/// Compute the desired OpenMP runtime from the flag provided.
-static OpenMPRuntimeKind getOpenMPRuntime(const ToolChain &TC,
- const ArgList &Args) {
- StringRef RuntimeName(CLANG_DEFAULT_OPENMP_RUNTIME);
-
- const Arg *A = Args.getLastArg(options::OPT_fopenmp_EQ);
- if (A)
- RuntimeName = A->getValue();
-
- auto RT = llvm::StringSwitch<OpenMPRuntimeKind>(RuntimeName)
- .Case("libomp", OMPRT_OMP)
- .Case("libgomp", OMPRT_GOMP)
- .Case("libiomp5", OMPRT_IOMP5)
- .Default(OMPRT_Unknown);
-
- if (RT == OMPRT_Unknown) {
- if (A)
- TC.getDriver().Diag(diag::err_drv_unsupported_option_argument)
- << A->getOption().getName() << A->getValue();
- else
- // FIXME: We could use a nicer diagnostic here.
- TC.getDriver().Diag(diag::err_drv_unsupported_opt) << "-fopenmp";
- }
-
- return RT;
-}
-
static void addOpenMPRuntime(ArgStringList &CmdArgs, const ToolChain &TC,
const ArgList &Args) {
if (!Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
options::OPT_fno_openmp, false))
return;
- switch (getOpenMPRuntime(TC, Args)) {
- case OMPRT_OMP:
+ switch (TC.getDriver().getOpenMPRuntime(Args)) {
+ case Driver::OMPRT_OMP:
CmdArgs.push_back("-lomp");
break;
- case OMPRT_GOMP:
+ case Driver::OMPRT_GOMP:
CmdArgs.push_back("-lgomp");
break;
- case OMPRT_IOMP5:
+ case Driver::OMPRT_IOMP5:
CmdArgs.push_back("-liomp5");
break;
- case OMPRT_Unknown:
+ case Driver::OMPRT_Unknown:
// Already diagnosed.
break;
}
@@ -3103,11 +3245,15 @@ static void 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");
- CmdArgs.push_back("-lpthread");
- CmdArgs.push_back("-lrt");
+ // There's no libpthread or librt on RTEMS.
+ if (TC.getTriple().getOS() != llvm::Triple::RTEMS) {
+ CmdArgs.push_back("-lpthread");
+ CmdArgs.push_back("-lrt");
+ }
CmdArgs.push_back("-lm");
- // There's no libdl on FreeBSD.
- if (TC.getTriple().getOS() != llvm::Triple::FreeBSD)
+ // There's no libdl on FreeBSD or RTEMS.
+ if (TC.getTriple().getOS() != llvm::Triple::FreeBSD &&
+ TC.getTriple().getOS() != llvm::Triple::RTEMS)
CmdArgs.push_back("-ldl");
}
@@ -3207,6 +3353,11 @@ static bool addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
// to be dynamic to be sure we export sanitizer interface functions.
if (AddExportDynamic)
CmdArgs.push_back("-export-dynamic");
+
+ const SanitizerArgs &SanArgs = TC.getSanitizerArgs();
+ if (SanArgs.hasCrossDsoCfi() && !AddExportDynamic)
+ CmdArgs.push_back("-export-dynamic-symbol=__cfi_check");
+
return !StaticRuntimes.empty();
}
@@ -3245,8 +3396,20 @@ static bool areOptimizationsEnabled(const ArgList &Args) {
return false;
}
-static bool shouldUseFramePointerForTarget(const ArgList &Args,
- const llvm::Triple &Triple) {
+static bool mustUseFramePointerForTarget(const llvm::Triple &Triple) {
+ switch (Triple.getArch()){
+ default:
+ return false;
+ case llvm::Triple::arm:
+ case llvm::Triple::thumb:
+ // ARM Darwin targets require a frame pointer to be always present to aid
+ // offline debugging via backtraces.
+ return Triple.isOSDarwin();
+ }
+}
+
+static bool useFramePointerForTargetByDefault(const ArgList &Args,
+ const llvm::Triple &Triple) {
switch (Triple.getArch()) {
case llvm::Triple::xcore:
case llvm::Triple::wasm32:
@@ -3298,25 +3461,29 @@ static bool shouldUseFramePointer(const ArgList &Args,
const llvm::Triple &Triple) {
if (Arg *A = Args.getLastArg(options::OPT_fno_omit_frame_pointer,
options::OPT_fomit_frame_pointer))
- return A->getOption().matches(options::OPT_fno_omit_frame_pointer);
+ return A->getOption().matches(options::OPT_fno_omit_frame_pointer) ||
+ mustUseFramePointerForTarget(Triple);
+
if (Args.hasArg(options::OPT_pg))
return true;
- return shouldUseFramePointerForTarget(Args, Triple);
+ return useFramePointerForTargetByDefault(Args, Triple);
}
static bool shouldUseLeafFramePointer(const ArgList &Args,
const llvm::Triple &Triple) {
if (Arg *A = Args.getLastArg(options::OPT_mno_omit_leaf_frame_pointer,
options::OPT_momit_leaf_frame_pointer))
- return A->getOption().matches(options::OPT_mno_omit_leaf_frame_pointer);
+ return A->getOption().matches(options::OPT_mno_omit_leaf_frame_pointer) ||
+ mustUseFramePointerForTarget(Triple);
+
if (Args.hasArg(options::OPT_pg))
return true;
if (Triple.isPS4CPU())
return false;
- return shouldUseFramePointerForTarget(Args, Triple);
+ return useFramePointerForTargetByDefault(Args, Triple);
}
/// Add a CC1 option to specify the debug compilation directory.
@@ -3416,19 +3583,6 @@ static void addDashXForInput(const ArgList &Args, const InputInfo &Input,
CmdArgs.push_back(types::getTypeName(Input.getType()));
}
-static VersionTuple getMSCompatibilityVersion(unsigned Version) {
- if (Version < 100)
- return VersionTuple(Version);
-
- if (Version < 10000)
- return VersionTuple(Version / 100, Version % 100);
-
- unsigned Build = 0, Factor = 1;
- for (; Version > 10000; Version = Version / 10, Factor = Factor * 10)
- Build = Build + (Version % 10) * Factor;
- return VersionTuple(Version / 100, Version % 100, Build);
-}
-
// Claim options we don't want to warn if they are unused. We do this for
// options that build systems might add but are unused when assembling or only
// running the preprocessor for example.
@@ -3472,58 +3626,17 @@ static void appendUserToPath(SmallVectorImpl<char> &Result) {
Result.append(UID.begin(), UID.end());
}
-VersionTuple visualstudio::getMSVCVersion(const Driver *D, const ToolChain &TC,
- const llvm::Triple &Triple,
- const llvm::opt::ArgList &Args,
- bool IsWindowsMSVC) {
- if (Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
- IsWindowsMSVC) ||
- Args.hasArg(options::OPT_fmsc_version) ||
- Args.hasArg(options::OPT_fms_compatibility_version)) {
- const Arg *MSCVersion = Args.getLastArg(options::OPT_fmsc_version);
- const Arg *MSCompatibilityVersion =
- Args.getLastArg(options::OPT_fms_compatibility_version);
-
- if (MSCVersion && MSCompatibilityVersion) {
- if (D)
- D->Diag(diag::err_drv_argument_not_allowed_with)
- << MSCVersion->getAsString(Args)
- << MSCompatibilityVersion->getAsString(Args);
- return VersionTuple();
- }
-
- if (MSCompatibilityVersion) {
- VersionTuple MSVT;
- if (MSVT.tryParse(MSCompatibilityVersion->getValue()) && D)
- D->Diag(diag::err_drv_invalid_value)
- << MSCompatibilityVersion->getAsString(Args)
- << MSCompatibilityVersion->getValue();
- return MSVT;
- }
-
- if (MSCVersion) {
- unsigned Version = 0;
- if (StringRef(MSCVersion->getValue()).getAsInteger(10, Version) && D)
- D->Diag(diag::err_drv_invalid_value) << MSCVersion->getAsString(Args)
- << MSCVersion->getValue();
- return getMSCompatibilityVersion(Version);
- }
-
- unsigned Major, Minor, Micro;
- Triple.getEnvironmentVersion(Major, Minor, Micro);
- if (Major || Minor || Micro)
- return VersionTuple(Major, Minor, Micro);
+static Arg *getLastProfileUseArg(const ArgList &Args) {
+ auto *ProfileUseArg = Args.getLastArg(
+ options::OPT_fprofile_instr_use, options::OPT_fprofile_instr_use_EQ,
+ options::OPT_fprofile_use, options::OPT_fprofile_use_EQ,
+ options::OPT_fno_profile_instr_use);
- if (IsWindowsMSVC) {
- VersionTuple MSVT = TC.getMSVCVersionFromExe();
- if (!MSVT.empty())
- return MSVT;
+ if (ProfileUseArg &&
+ ProfileUseArg->getOption().matches(options::OPT_fno_profile_instr_use))
+ ProfileUseArg = nullptr;
- // FIXME: Consider bumping this to 19 (MSVC2015) soon.
- return VersionTuple(18);
- }
- }
- return VersionTuple();
+ return ProfileUseArg;
}
static void addPGOAndCoverageFlags(Compilation &C, const Driver &D,
@@ -3550,13 +3663,7 @@ static void addPGOAndCoverageFlags(Compilation &C, const Driver &D,
D.Diag(diag::err_drv_argument_not_allowed_with)
<< PGOGenerateArg->getSpelling() << ProfileGenerateArg->getSpelling();
- auto *ProfileUseArg = Args.getLastArg(
- options::OPT_fprofile_instr_use, options::OPT_fprofile_instr_use_EQ,
- options::OPT_fprofile_use, options::OPT_fprofile_use_EQ,
- options::OPT_fno_profile_instr_use);
- if (ProfileUseArg &&
- ProfileUseArg->getOption().matches(options::OPT_fno_profile_instr_use))
- ProfileUseArg = nullptr;
+ auto *ProfileUseArg = getLastProfileUseArg(Args);
if (PGOGenerateArg && ProfileUseArg)
D.Diag(diag::err_drv_argument_not_allowed_with)
@@ -3580,7 +3687,7 @@ static void addPGOAndCoverageFlags(Compilation &C, const Driver &D,
if (PGOGenerateArg->getOption().matches(
options::OPT_fprofile_generate_EQ)) {
SmallString<128> Path(PGOGenerateArg->getValue());
- llvm::sys::path::append(Path, "default.profraw");
+ llvm::sys::path::append(Path, "default_%m.profraw");
CmdArgs.push_back(
Args.MakeArgString(Twine("-fprofile-instrument-path=") + Path));
}
@@ -3625,13 +3732,13 @@ static void addPGOAndCoverageFlags(Compilation &C, const Driver &D,
if (C.getArgs().hasArg(options::OPT_c) ||
C.getArgs().hasArg(options::OPT_S)) {
if (Output.isFilename()) {
- CmdArgs.push_back("-coverage-file");
- SmallString<128> CoverageFilename;
- if (Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o)) {
- CoverageFilename = FinalOutput->getValue();
- } else {
- CoverageFilename = llvm::sys::path::filename(Output.getBaseInput());
- }
+ CmdArgs.push_back("-coverage-notes-file");
+ SmallString<128> OutputFilename;
+ if (Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o))
+ OutputFilename = FinalOutput->getValue();
+ else
+ OutputFilename = llvm::sys::path::filename(Output.getBaseInput());
+ SmallString<128> CoverageFilename = OutputFilename;
if (llvm::sys::path::is_relative(CoverageFilename)) {
SmallString<128> Pwd;
if (!llvm::sys::fs::current_path(Pwd)) {
@@ -3639,7 +3746,23 @@ static void addPGOAndCoverageFlags(Compilation &C, const Driver &D,
CoverageFilename.swap(Pwd);
}
}
+ llvm::sys::path::replace_extension(CoverageFilename, "gcno");
CmdArgs.push_back(Args.MakeArgString(CoverageFilename));
+
+ // Leave -fprofile-dir= an unused argument unless .gcda emission is
+ // enabled. To be polite, with '-fprofile-arcs -fno-profile-arcs' consider
+ // the flag used. There is no -fno-profile-dir, so the user has no
+ // targeted way to suppress the warning.
+ if (Args.hasArg(options::OPT_fprofile_arcs) ||
+ Args.hasArg(options::OPT_coverage)) {
+ CmdArgs.push_back("-coverage-data-file");
+ if (Arg *FProfileDir = Args.getLastArg(options::OPT_fprofile_dir)) {
+ CoverageFilename = FProfileDir->getValue();
+ llvm::sys::path::append(CoverageFilename, OutputFilename);
+ }
+ llvm::sys::path::replace_extension(CoverageFilename, "gcda");
+ CmdArgs.push_back(Args.MakeArgString(CoverageFilename));
+ }
}
}
}
@@ -3666,15 +3789,14 @@ static void addPS4ProfileRTArgs(const ToolChain &TC, const ArgList &Args,
/// this compile should be using PIC mode or not. Returns a tuple of
/// (RelocationModel, PICLevel, IsPIE).
static std::tuple<llvm::Reloc::Model, unsigned, bool>
-ParsePICArgs(const ToolChain &ToolChain, const llvm::Triple &Triple,
- const ArgList &Args) {
- // FIXME: why does this code...and so much everywhere else, use both
- // ToolChain.getTriple() and Triple?
+ParsePICArgs(const ToolChain &ToolChain, const ArgList &Args) {
+ const llvm::Triple &EffectiveTriple = ToolChain.getEffectiveTriple();
+ const llvm::Triple &Triple = ToolChain.getTriple();
+
bool PIE = ToolChain.isPIEDefault();
bool PIC = PIE || ToolChain.isPICDefault();
// The Darwin/MachO default to use PIC does not apply when using -static.
- if (ToolChain.getTriple().isOSBinFormatMachO() &&
- Args.hasArg(options::OPT_static))
+ if (Triple.isOSBinFormatMachO() && Args.hasArg(options::OPT_static))
PIE = PIC = false;
bool IsPICLevelTwo = PIC;
@@ -3682,8 +3804,8 @@ ParsePICArgs(const ToolChain &ToolChain, const llvm::Triple &Triple,
Args.hasArg(options::OPT_mkernel, options::OPT_fapple_kext);
// Android-specific defaults for PIC/PIE
- if (ToolChain.getTriple().isAndroid()) {
- switch (ToolChain.getArch()) {
+ if (Triple.isAndroid()) {
+ switch (Triple.getArch()) {
case llvm::Triple::arm:
case llvm::Triple::armeb:
case llvm::Triple::thumb:
@@ -3708,7 +3830,7 @@ ParsePICArgs(const ToolChain &ToolChain, const llvm::Triple &Triple,
}
// OpenBSD-specific defaults for PIE
- if (ToolChain.getTriple().getOS() == llvm::Triple::OpenBSD) {
+ if (Triple.getOS() == llvm::Triple::OpenBSD) {
switch (ToolChain.getArch()) {
case llvm::Triple::mips64:
case llvm::Triple::mips64el:
@@ -3737,6 +3859,17 @@ ParsePICArgs(const ToolChain &ToolChain, const llvm::Triple &Triple,
options::OPT_fpic, options::OPT_fno_pic,
options::OPT_fPIE, options::OPT_fno_PIE,
options::OPT_fpie, options::OPT_fno_pie);
+ if (Triple.isOSWindows() && LastPICArg &&
+ LastPICArg ==
+ Args.getLastArg(options::OPT_fPIC, options::OPT_fpic,
+ options::OPT_fPIE, options::OPT_fpie)) {
+ ToolChain.getDriver().Diag(diag::err_drv_unsupported_opt_for_target)
+ << LastPICArg->getSpelling() << Triple.str();
+ if (Triple.getArch() == llvm::Triple::x86_64)
+ return std::make_tuple(llvm::Reloc::PIC_, 2U, false);
+ return std::make_tuple(llvm::Reloc::Static, 0U, false);
+ }
+
// Check whether the tool chain trumps the PIC-ness decision. If the PIC-ness
// is forced, then neither PIC nor PIE flags will have no effect.
if (!ToolChain.isPICDefaultForced()) {
@@ -3751,7 +3884,7 @@ ParsePICArgs(const ToolChain &ToolChain, const llvm::Triple &Triple,
O.matches(options::OPT_fPIE) || O.matches(options::OPT_fPIC);
} else {
PIE = PIC = false;
- if (Triple.isPS4CPU()) {
+ if (EffectiveTriple.isPS4CPU()) {
Arg *ModelArg = Args.getLastArg(options::OPT_mcmodel_EQ);
StringRef Model = ModelArg ? ModelArg->getValue() : "";
if (Model != "kernel") {
@@ -3767,21 +3900,22 @@ ParsePICArgs(const ToolChain &ToolChain, const llvm::Triple &Triple,
// Introduce a Darwin and PS4-specific hack. If the default is PIC, but the
// PIC level would've been set to level 1, force it back to level 2 PIC
// instead.
- if (PIC && (ToolChain.getTriple().isOSDarwin() || Triple.isPS4CPU()))
+ if (PIC && (Triple.isOSDarwin() || EffectiveTriple.isPS4CPU()))
IsPICLevelTwo |= ToolChain.isPICDefault();
// This kernel flags are a trump-card: they will disable PIC/PIE
// generation, independent of the argument order.
- if (KernelOrKext && ((!Triple.isiOS() || Triple.isOSVersionLT(6)) &&
- !Triple.isWatchOS()))
+ if (KernelOrKext &&
+ ((!EffectiveTriple.isiOS() || EffectiveTriple.isOSVersionLT(6)) &&
+ !EffectiveTriple.isWatchOS()))
PIC = PIE = false;
if (Arg *A = Args.getLastArg(options::OPT_mdynamic_no_pic)) {
// This is a very special mode. It trumps the other modes, almost no one
// uses it, and it isn't even valid on any OS but Darwin.
- if (!ToolChain.getTriple().isOSDarwin())
+ if (!Triple.isOSDarwin())
ToolChain.getDriver().Diag(diag::err_drv_unsupported_opt_for_target)
- << A->getSpelling() << ToolChain.getTriple().str();
+ << A->getSpelling() << Triple.str();
// FIXME: Warn when this flag trumps some other PIC or PIE flag.
@@ -3790,13 +3924,54 @@ ParsePICArgs(const ToolChain &ToolChain, const llvm::Triple &Triple,
// match that of llvm-gcc and Apple GCC before that.
PIC = ToolChain.isPICDefault() && ToolChain.isPICDefaultForced();
- return std::make_tuple(llvm::Reloc::DynamicNoPIC, PIC ? 2 : 0, false);
+ return std::make_tuple(llvm::Reloc::DynamicNoPIC, PIC ? 2U : 0U, false);
}
+ bool EmbeddedPISupported;
+ switch (Triple.getArch()) {
+ case llvm::Triple::arm:
+ case llvm::Triple::armeb:
+ case llvm::Triple::thumb:
+ case llvm::Triple::thumbeb:
+ EmbeddedPISupported = true;
+ break;
+ default:
+ EmbeddedPISupported = false;
+ break;
+ }
+
+ bool ROPI = false, RWPI = false;
+ Arg* LastROPIArg = Args.getLastArg(options::OPT_fropi, options::OPT_fno_ropi);
+ if (LastROPIArg && LastROPIArg->getOption().matches(options::OPT_fropi)) {
+ if (!EmbeddedPISupported)
+ ToolChain.getDriver().Diag(diag::err_drv_unsupported_opt_for_target)
+ << LastROPIArg->getSpelling() << Triple.str();
+ ROPI = true;
+ }
+ Arg *LastRWPIArg = Args.getLastArg(options::OPT_frwpi, options::OPT_fno_rwpi);
+ if (LastRWPIArg && LastRWPIArg->getOption().matches(options::OPT_frwpi)) {
+ if (!EmbeddedPISupported)
+ ToolChain.getDriver().Diag(diag::err_drv_unsupported_opt_for_target)
+ << LastRWPIArg->getSpelling() << Triple.str();
+ RWPI = true;
+ }
+
+ // ROPI and RWPI are not comaptible with PIC or PIE.
+ if ((ROPI || RWPI) && (PIC || PIE))
+ ToolChain.getDriver().Diag(diag::err_drv_ropi_rwpi_incompatible_with_pic);
+
if (PIC)
- return std::make_tuple(llvm::Reloc::PIC_, IsPICLevelTwo ? 2 : 1, PIE);
+ return std::make_tuple(llvm::Reloc::PIC_, IsPICLevelTwo ? 2U : 1U, PIE);
+
+ llvm::Reloc::Model RelocM = llvm::Reloc::Static;
+ if (ROPI && RWPI)
+ RelocM = llvm::Reloc::ROPI_RWPI;
+ else if (ROPI)
+ RelocM = llvm::Reloc::ROPI;
+ else if (RWPI)
+ RelocM = llvm::Reloc::RWPI;
- return std::make_tuple(llvm::Reloc::Static, 0, false);
+ return std::make_tuple(RelocM, 0U, false);
}
static const char *RelocationModelName(llvm::Reloc::Model Model) {
@@ -3807,6 +3982,12 @@ static const char *RelocationModelName(llvm::Reloc::Model Model) {
return "pic";
case llvm::Reloc::DynamicNoPIC:
return "dynamic-no-pic";
+ case llvm::Reloc::ROPI:
+ return "ropi";
+ case llvm::Reloc::RWPI:
+ return "rwpi";
+ case llvm::Reloc::ROPI_RWPI:
+ return "ropi-rwpi";
}
llvm_unreachable("Unknown Reloc::Model kind");
}
@@ -3816,18 +3997,76 @@ static void AddAssemblerKPIC(const ToolChain &ToolChain, const ArgList &Args,
llvm::Reloc::Model RelocationModel;
unsigned PICLevel;
bool IsPIE;
- std::tie(RelocationModel, PICLevel, IsPIE) =
- ParsePICArgs(ToolChain, ToolChain.getTriple(), Args);
+ std::tie(RelocationModel, PICLevel, IsPIE) = ParsePICArgs(ToolChain, Args);
if (RelocationModel != llvm::Reloc::Static)
CmdArgs.push_back("-KPIC");
}
+void Clang::DumpCompilationDatabase(Compilation &C, StringRef Filename,
+ StringRef Target, const InputInfo &Output,
+ const InputInfo &Input, const ArgList &Args) const {
+ // If this is a dry run, do not create the compilation database file.
+ if (C.getArgs().hasArg(options::OPT__HASH_HASH_HASH))
+ return;
+
+ using llvm::yaml::escape;
+ const Driver &D = getToolChain().getDriver();
+
+ if (!CompilationDatabase) {
+ std::error_code EC;
+ auto File = llvm::make_unique<llvm::raw_fd_ostream>(Filename, EC, llvm::sys::fs::F_Text);
+ if (EC) {
+ D.Diag(clang::diag::err_drv_compilationdatabase) << Filename
+ << EC.message();
+ return;
+ }
+ CompilationDatabase = std::move(File);
+ }
+ auto &CDB = *CompilationDatabase;
+ SmallString<128> Buf;
+ if (llvm::sys::fs::current_path(Buf))
+ Buf = ".";
+ CDB << "{ \"directory\": \"" << escape(Buf) << "\"";
+ CDB << ", \"file\": \"" << escape(Input.getFilename()) << "\"";
+ CDB << ", \"output\": \"" << escape(Output.getFilename()) << "\"";
+ CDB << ", \"arguments\": [\"" << escape(D.ClangExecutable) << "\"";
+ Buf = "-x";
+ Buf += types::getTypeName(Input.getType());
+ CDB << ", \"" << escape(Buf) << "\"";
+ if (!D.SysRoot.empty() && !Args.hasArg(options::OPT__sysroot_EQ)) {
+ Buf = "--sysroot=";
+ Buf += D.SysRoot;
+ CDB << ", \"" << escape(Buf) << "\"";
+ }
+ CDB << ", \"" << escape(Input.getFilename()) << "\"";
+ for (auto &A: Args) {
+ auto &O = A->getOption();
+ // Skip language selection, which is positional.
+ if (O.getID() == options::OPT_x)
+ continue;
+ // Skip writing dependency output and the compilation database itself.
+ if (O.getGroup().isValid() && O.getGroup().getID() == options::OPT_M_Group)
+ continue;
+ // Skip inputs.
+ if (O.getKind() == Option::InputClass)
+ continue;
+ // All other arguments are quoted and appended.
+ ArgStringList ASL;
+ A->render(Args, ASL);
+ for (auto &it: ASL)
+ CDB << ", \"" << escape(it) << "\"";
+ }
+ Buf = "--target=";
+ Buf += Target;
+ CDB << ", \"" << escape(Buf) << "\"]},\n";
+}
+
void Clang::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output, const InputInfoList &Inputs,
const ArgList &Args, const char *LinkingOutput) const {
- std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args);
- const llvm::Triple Triple(TripleStr);
+ const llvm::Triple &Triple = getToolChain().getEffectiveTriple();
+ const std::string &TripleStr = Triple.getTriple();
bool KernelOrKext =
Args.hasArg(options::OPT_mkernel, options::OPT_fapple_kext);
@@ -3845,10 +4084,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
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
- // device-side compilations). All other jobs are expected to have exactly one
+ // 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);
- assert((IsCuda || Inputs.size() == 1) && "Unable to handle multiple inputs.");
+ bool IsOpenMPDevice = JA.isDeviceOffloading(Action::OFK_OpenMP);
+ assert((IsCuda || (IsOpenMPDevice && Inputs.size() == 2) ||
+ Inputs.size() == 1) &&
+ "Unable to handle multiple inputs.");
// C++ is not supported for IAMCU.
if (IsIAMCU && types::isCXX(Input.getType()))
@@ -3863,6 +4106,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-triple");
CmdArgs.push_back(Args.MakeArgString(TripleStr));
+ if (const Arg *MJ = Args.getLastArg(options::OPT_MJ)) {
+ DumpCompilationDatabase(C, MJ->getValue(), TripleStr, Output, Input, Args);
+ 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.
@@ -3925,6 +4173,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (JA.getType() == types::TY_Nothing)
CmdArgs.push_back("-fsyntax-only");
+ else if (JA.getType() == types::TY_ModuleFile)
+ CmdArgs.push_back("-emit-module-interface");
else if (UsePCH)
CmdArgs.push_back("-emit-pch");
else
@@ -3977,12 +4227,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
// Embed-bitcode option.
- if (C.getDriver().embedBitcodeEnabled() &&
+ if (C.getDriver().embedBitcodeInObject() &&
(isa<BackendJobAction>(JA) || isa<AssembleJobAction>(JA))) {
// Add flags implied by -fembed-bitcode.
Args.AddLastArg(CmdArgs, options::OPT_fembed_bitcode_EQ);
// Disable all llvm IR level optimizations.
- CmdArgs.push_back("-disable-llvm-optzns");
+ CmdArgs.push_back("-disable-llvm-passes");
}
if (C.getDriver().embedBitcodeMarkerOnly())
CmdArgs.push_back("-fembed-bitcode=marker");
@@ -4022,6 +4272,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Add default argument set.
if (!Args.hasArg(options::OPT__analyzer_no_default_checks)) {
CmdArgs.push_back("-analyzer-checker=core");
+ CmdArgs.push_back("-analyzer-checker=apiModeling");
if (!IsWindowsMSVC) {
CmdArgs.push_back("-analyzer-checker=unix");
@@ -4088,9 +4339,16 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
unsigned PICLevel;
bool IsPIE;
std::tie(RelocationModel, PICLevel, IsPIE) =
- ParsePICArgs(getToolChain(), Triple, Args);
+ ParsePICArgs(getToolChain(), Args);
const char *RMName = RelocationModelName(RelocationModel);
+
+ if ((RelocationModel == llvm::Reloc::ROPI ||
+ RelocationModel == llvm::Reloc::ROPI_RWPI) &&
+ types::isCXX(Input.getType()) &&
+ !Args.hasArg(options::OPT_fallow_unsupported))
+ D.Diag(diag::err_drv_ropi_incompatible_with_cxx);
+
if (RMName) {
CmdArgs.push_back("-mrelocation-model");
CmdArgs.push_back(RMName);
@@ -4125,9 +4383,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.hasArg(options::OPT_frewrite_map_file_EQ)) {
for (const Arg *A : Args.filtered(options::OPT_frewrite_map_file,
options::OPT_frewrite_map_file_EQ)) {
- CmdArgs.push_back("-frewrite-map-file");
- CmdArgs.push_back(A->getValue());
- A->claim();
+ StringRef Map = A->getValue();
+ if (!llvm::sys::fs::exists(Map)) {
+ D.Diag(diag::err_drv_no_such_file) << Map;
+ } else {
+ CmdArgs.push_back("-frewrite-map-file");
+ CmdArgs.push_back(A->getValue());
+ A->claim();
+ }
}
}
@@ -4142,6 +4405,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
true))
CmdArgs.push_back("-fno-jump-tables");
+ if (!Args.hasFlag(options::OPT_fpreserve_as_comments,
+ options::OPT_fno_preserve_as_comments, true))
+ CmdArgs.push_back("-fno-preserve-as-comments");
+
if (Arg *A = Args.getLastArg(options::OPT_mregparm_EQ)) {
CmdArgs.push_back("-mregparm");
CmdArgs.push_back(A->getValue());
@@ -4300,6 +4567,19 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (ReciprocalMath)
CmdArgs.push_back("-freciprocal-math");
+ if (!TrappingMath)
+ CmdArgs.push_back("-fno-trapping-math");
+
+
+ if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
+ options::OPT_fno_fast_math,
+ options::OPT_funsafe_math_optimizations,
+ options::OPT_fno_unsafe_math_optimizations,
+ options::OPT_fdenormal_fp_math_EQ))
+ if (A->getOption().getID() != options::OPT_fno_fast_math &&
+ A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations)
+ Args.AddLastArg(CmdArgs, options::OPT_fdenormal_fp_math_EQ);
+
// Validate and pass through -fp-contract option.
if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
options::OPT_fno_fast_math,
@@ -4374,6 +4654,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-mms-bitfields");
}
+ if (Args.hasFlag(options::OPT_mpie_copy_relocations,
+ options::OPT_mno_pie_copy_relocations,
+ false)) {
+ CmdArgs.push_back("-mpie-copy-relocations");
+ }
+
// This is a coarse approximation of what llvm-gcc actually does, both
// -fasynchronous-unwind-tables and -fnon-call-exceptions interact in more
// complicated ways.
@@ -4535,6 +4821,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
: "-");
}
+ bool splitDwarfInlining =
+ Args.hasFlag(options::OPT_fsplit_dwarf_inlining,
+ options::OPT_fno_split_dwarf_inlining, true);
+
Args.ClaimAllArgs(options::OPT_g_Group);
Arg *SplitDwarfArg = Args.getLastArg(options::OPT_gsplit_dwarf);
if (Arg *A = Args.getLastArg(options::OPT_g_Group)) {
@@ -4544,9 +4834,20 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// If you say "-gsplit-dwarf -gline-tables-only", -gsplit-dwarf loses.
// But -gsplit-dwarf is not a g_group option, hence we have to check the
// order explicitly. (If -gsplit-dwarf wins, we fix DebugInfoKind later.)
- if (SplitDwarfArg && DebugInfoKind < codegenoptions::LimitedDebugInfo &&
- A->getIndex() > SplitDwarfArg->getIndex())
- SplitDwarfArg = nullptr;
+ // This gets a bit more complicated if you've disabled inline info in the
+ // skeleton CUs (splitDwarfInlining) - then there's value in composing
+ // split-dwarf and line-tables-only, so let those compose naturally in
+ // that case.
+ // And if you just turned off debug info, (-gsplit-dwarf -g0) - do that.
+ if (SplitDwarfArg) {
+ if (A->getIndex() > SplitDwarfArg->getIndex()) {
+ if (DebugInfoKind == codegenoptions::NoDebugInfo ||
+ (DebugInfoKind == codegenoptions::DebugLineTablesOnly &&
+ splitDwarfInlining))
+ SplitDwarfArg = nullptr;
+ } else if (splitDwarfInlining)
+ DebugInfoKind = codegenoptions::NoDebugInfo;
+ }
} else
// For any other 'g' option, use Limited.
DebugInfoKind = codegenoptions::LimitedDebugInfo;
@@ -4581,13 +4882,19 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// We ignore flags -gstrict-dwarf and -grecord-gcc-switches for now.
Args.ClaimAllArgs(options::OPT_g_flags_Group);
- // PS4 defaults to no column info
+ // Column info is included by default for everything except PS4 and CodeView.
+ // Clang doesn't track end columns, just starting columns, which, in theory,
+ // is fine for CodeView (and PDB). In practice, however, the Microsoft
+ // debuggers don't handle missing end columns well, so it's better not to
+ // include any column info.
if (Args.hasFlag(options::OPT_gcolumn_info, options::OPT_gno_column_info,
- /*Default=*/ !IsPS4CPU))
+ /*Default=*/ !IsPS4CPU && !(IsWindowsMSVC && EmitCodeView)))
CmdArgs.push_back("-dwarf-column-info");
// FIXME: Move backend command line options to the module.
- if (Args.hasArg(options::OPT_gmodules)) {
+ // If -gline-tables-only is the last option it wins.
+ if (DebugInfoKind != codegenoptions::DebugLineTablesOnly &&
+ Args.hasArg(options::OPT_gmodules)) {
DebugInfoKind = codegenoptions::LimitedDebugInfo;
CmdArgs.push_back("-dwarf-ext-refs");
CmdArgs.push_back("-fmodule-format=obj");
@@ -4597,7 +4904,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// splitting and extraction.
// FIXME: Currently only works on Linux.
if (getToolChain().getTriple().isOSLinux() && SplitDwarfArg) {
- DebugInfoKind = codegenoptions::LimitedDebugInfo;
+ if (!splitDwarfInlining)
+ CmdArgs.push_back("-fno-split-dwarf-inlining");
+ if (DebugInfoKind == codegenoptions::NoDebugInfo)
+ DebugInfoKind = codegenoptions::LimitedDebugInfo;
CmdArgs.push_back("-backend-option");
CmdArgs.push_back("-split-dwarf=Enable");
}
@@ -4635,11 +4945,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-generate-type-units");
}
- // CloudABI and WebAssembly use -ffunction-sections and -fdata-sections by
- // default.
- bool UseSeparateSections = Triple.getOS() == llvm::Triple::CloudABI ||
- Triple.getArch() == llvm::Triple::wasm32 ||
- Triple.getArch() == llvm::Triple::wasm64;
+ bool UseSeparateSections = isUseSeparateSections(Triple);
if (Args.hasFlag(options::OPT_ffunction_sections,
options::OPT_fno_function_sections, UseSeparateSections)) {
@@ -4659,7 +4965,22 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasFlag(options::OPT_fxray_instrument,
options::OPT_fnoxray_instrument, false)) {
- CmdArgs.push_back("-fxray-instrument");
+ const char *const XRayInstrumentOption = "-fxray-instrument";
+ if (Triple.getOS() == llvm::Triple::Linux)
+ switch (Triple.getArch()) {
+ case llvm::Triple::x86_64:
+ case llvm::Triple::arm:
+ case llvm::Triple::aarch64:
+ // Supported.
+ break;
+ default:
+ 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");
+ CmdArgs.push_back(XRayInstrumentOption);
if (const Arg *A =
Args.getLastArg(options::OPT_fxray_instruction_threshold_,
options::OPT_fxray_instruction_threshold_EQ)) {
@@ -4794,6 +5115,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
claimNoWarnArgs(Args);
Args.AddAllArgs(CmdArgs, options::OPT_R_Group);
+
Args.AddAllArgs(CmdArgs, options::OPT_W_Group);
if (Args.hasFlag(options::OPT_pedantic, options::OPT_no_pedantic, false))
CmdArgs.push_back("-pedantic");
@@ -4998,9 +5320,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_ftlsmodel_EQ);
// -fhosted is default.
+ bool IsHosted = true;
if (Args.hasFlag(options::OPT_ffreestanding, options::OPT_fhosted, false) ||
- KernelOrKext)
+ KernelOrKext) {
CmdArgs.push_back("-ffreestanding");
+ IsHosted = false;
+ }
// Forward -f (flag) options which we can pass directly.
Args.AddLastArg(CmdArgs, options::OPT_femit_all_decls);
@@ -5021,15 +5346,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_fno_elide_type);
// Forward flags for OpenMP. We don't do this if the current action is an
- // device offloading action.
- //
- // TODO: Allow OpenMP offload actions when they become available.
+ // device offloading action other than OpenMP.
if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
options::OPT_fno_openmp, false) &&
- JA.isDeviceOffloading(Action::OFK_None)) {
- switch (getOpenMPRuntime(getToolChain(), Args)) {
- case OMPRT_OMP:
- case OMPRT_IOMP5:
+ (JA.isDeviceOffloading(Action::OFK_None) ||
+ JA.isDeviceOffloading(Action::OFK_OpenMP))) {
+ switch (getToolChain().getDriver().getOpenMPRuntime(Args)) {
+ case Driver::OMPRT_OMP:
+ case Driver::OMPRT_IOMP5:
// Clang can generate useful OpenMP code for these two runtime libraries.
CmdArgs.push_back("-fopenmp");
@@ -5134,6 +5458,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
} else {
StackProtectorLevel =
getToolChain().GetDefaultStackProtectorLevel(KernelOrKext);
+ // Only use a default stack protector on Darwin in case -ffreestanding
+ // is not specified.
+ if (Triple.isOSDarwin() && !IsHosted)
+ StackProtectorLevel = 0;
}
if (StackProtectorLevel) {
CmdArgs.push_back("-stack-protector");
@@ -5239,6 +5567,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.getLastArg(options::OPT_cl_denorms_are_zero)) {
CmdArgs.push_back("-cl-denorms-are-zero");
}
+ if (Args.getLastArg(options::OPT_cl_fp32_correctly_rounded_divide_sqrt)) {
+ CmdArgs.push_back("-cl-fp32-correctly-rounded-divide-sqrt");
+ }
// Forward -f options with positive and negative forms; we translate
// these by hand.
@@ -5294,23 +5625,35 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-fblocks-runtime-optional");
}
+ if (Args.hasFlag(options::OPT_fcoroutines_ts, options::OPT_fno_coroutines_ts,
+ false) &&
+ types::isCXX(InputType)) {
+ CmdArgs.push_back("-fcoroutines-ts");
+ }
+
// -fmodules enables the use of precompiled modules (off by default).
// Users can pass -fno-cxx-modules to turn off modules support for
// C++/Objective-C++ programs.
- bool HaveModules = false;
+ bool HaveClangModules = false;
if (Args.hasFlag(options::OPT_fmodules, options::OPT_fno_modules, false)) {
bool AllowedInCXX = Args.hasFlag(options::OPT_fcxx_modules,
options::OPT_fno_cxx_modules, true);
if (AllowedInCXX || !types::isCXX(InputType)) {
CmdArgs.push_back("-fmodules");
- HaveModules = true;
+ HaveClangModules = true;
}
}
+ bool HaveAnyModules = HaveClangModules;
+ if (Args.hasArg(options::OPT_fmodules_ts)) {
+ CmdArgs.push_back("-fmodules-ts");
+ HaveAnyModules = true;
+ }
+
// -fmodule-maps enables implicit reading of module map files. By default,
- // this is enabled if we are using precompiled modules.
+ // this is enabled if we are using Clang's flavor of precompiled modules.
if (Args.hasFlag(options::OPT_fimplicit_module_maps,
- options::OPT_fno_implicit_module_maps, HaveModules)) {
+ options::OPT_fno_implicit_module_maps, HaveClangModules)) {
CmdArgs.push_back("-fimplicit-module-maps");
}
@@ -5330,9 +5673,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// -fno-implicit-modules turns off implicitly compiling modules on demand.
if (!Args.hasFlag(options::OPT_fimplicit_modules,
- options::OPT_fno_implicit_modules)) {
- CmdArgs.push_back("-fno-implicit-modules");
- } else if (HaveModules) {
+ options::OPT_fno_implicit_modules, HaveClangModules)) {
+ if (HaveAnyModules)
+ CmdArgs.push_back("-fno-implicit-modules");
+ } else if (HaveAnyModules) {
// -fmodule-cache-path specifies where our implicitly-built module files
// should be written.
SmallString<128> Path;
@@ -5356,6 +5700,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString(Path));
}
+ if (HaveAnyModules) {
+ // -fprebuilt-module-path specifies where to load the prebuilt module files.
+ for (const Arg *A : Args.filtered(options::OPT_fprebuilt_module_path))
+ CmdArgs.push_back(Args.MakeArgString(
+ std::string("-fprebuilt-module-path=") + A->getValue()));
+ }
+
// -fmodule-name specifies the module that is currently being built (or
// used for header checking by -fmodule-maps).
Args.AddLastArg(CmdArgs, options::OPT_fmodule_name_EQ);
@@ -5364,15 +5715,27 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// definitions.
Args.AddAllArgs(CmdArgs, options::OPT_fmodule_map_file);
+ // -fbuiltin-module-map can be used to load the clang
+ // builtin headers modulemap file.
+ if (Args.hasArg(options::OPT_fbuiltin_module_map)) {
+ SmallString<128> BuiltinModuleMap(getToolChain().getDriver().ResourceDir);
+ llvm::sys::path::append(BuiltinModuleMap, "include");
+ llvm::sys::path::append(BuiltinModuleMap, "module.modulemap");
+ if (llvm::sys::fs::exists(BuiltinModuleMap)) {
+ CmdArgs.push_back(Args.MakeArgString("-fmodule-map-file=" +
+ BuiltinModuleMap));
+ }
+ }
+
// -fmodule-file can be used to specify files containing precompiled modules.
- if (HaveModules)
+ if (HaveAnyModules)
Args.AddAllArgs(CmdArgs, options::OPT_fmodule_file);
else
Args.ClaimAllArgs(options::OPT_fmodule_file);
// When building modules and generating crashdumps, we need to dump a module
// dependency VFS alongside the output.
- if (HaveModules && C.isForDiagnostics()) {
+ if (HaveClangModules && C.isForDiagnostics()) {
SmallString<128> VFSDir(Output.getFilename());
llvm::sys::path::replace_extension(VFSDir, ".cache");
// Add the cache directory as a temp so the crash diagnostics pick it up.
@@ -5383,7 +5746,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString(VFSDir));
}
- if (HaveModules)
+ if (HaveClangModules)
Args.AddLastArg(CmdArgs, options::OPT_fmodules_user_build_path);
// Pass through all -fmodules-ignore-macro arguments.
@@ -5401,9 +5764,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
llvm::sys::fs::file_status Status;
if (llvm::sys::fs::status(A->getValue(), Status))
D.Diag(diag::err_drv_no_such_file) << A->getValue();
- CmdArgs.push_back(Args.MakeArgString(
- "-fbuild-session-timestamp=" +
- Twine((uint64_t)Status.getLastModificationTime().toEpochTime())));
+ CmdArgs.push_back(
+ Args.MakeArgString("-fbuild-session-timestamp=" +
+ Twine((uint64_t)Status.getLastModificationTime()
+ .time_since_epoch()
+ .count())));
}
if (Args.getLastArg(options::OPT_fmodules_validate_once_per_build_session)) {
@@ -5416,6 +5781,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
Args.AddLastArg(CmdArgs, options::OPT_fmodules_validate_system_headers);
+ Args.AddLastArg(CmdArgs, options::OPT_fmodules_disable_diagnostic_validation);
// -faccess-control is default.
if (Args.hasFlag(options::OPT_fno_access_control,
@@ -5482,9 +5848,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fno_ms_extensions, true))))
CmdArgs.push_back("-fms-compatibility");
- // -fms-compatibility-version=18.00 is default.
- VersionTuple MSVT = visualstudio::getMSVCVersion(
- &D, getToolChain(), getToolChain().getTriple(), Args, IsWindowsMSVC);
+ VersionTuple MSVT =
+ getToolChain().computeMSVCVersion(&getToolChain().getDriver(), Args);
if (!MSVT.empty())
CmdArgs.push_back(
Args.MakeArgString("-fms-compatibility-version=" + MSVT.getAsString()));
@@ -5555,10 +5920,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fno_inline_functions))
InlineArg->render(Args, CmdArgs);
+ Args.AddLastArg(CmdArgs, options::OPT_fexperimental_new_pass_manager,
+ options::OPT_fno_experimental_new_pass_manager);
+
ObjCRuntime objcRuntime = AddObjCRuntimeArgs(Args, CmdArgs, rewriteKind);
// -fobjc-dispatch-method is only relevant with the nonfragile-abi, and
- // legacy is the default. Except for deployment taget of 10.5,
+ // legacy is the default. Except for deployment target of 10.5,
// next runtime is always legacy dispatch and -fno-objc-legacy-dispatch
// gets ignored silently.
if (objcRuntime.isNonFragile()) {
@@ -5620,31 +5988,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (rewriteKind != RK_None)
CmdArgs.push_back("-fno-objc-infer-related-result-type");
- // Handle -fobjc-gc and -fobjc-gc-only. They are exclusive, and -fobjc-gc-only
- // takes precedence.
- const Arg *GCArg = Args.getLastArg(options::OPT_fobjc_gc_only);
- if (!GCArg)
- GCArg = Args.getLastArg(options::OPT_fobjc_gc);
- if (GCArg) {
- if (ARC) {
- D.Diag(diag::err_drv_objc_gc_arr) << GCArg->getAsString(Args);
- } else if (getToolChain().SupportsObjCGC()) {
- GCArg->render(Args, CmdArgs);
- } else {
- // FIXME: We should move this to a hard error.
- D.Diag(diag::warn_drv_objc_gc_unsupported) << GCArg->getAsString(Args);
- }
- }
-
// Pass down -fobjc-weak or -fno-objc-weak if present.
if (types::isObjC(InputType)) {
auto WeakArg = Args.getLastArg(options::OPT_fobjc_weak,
options::OPT_fno_objc_weak);
if (!WeakArg) {
// nothing to do
- } else if (GCArg) {
- if (WeakArg->getOption().matches(options::OPT_fobjc_weak))
- D.Diag(diag::err_objc_weak_with_gc);
} else if (!objcRuntime.allowsWeak()) {
if (WeakArg->getOption().matches(options::OPT_fobjc_weak))
D.Diag(diag::err_objc_weak_unsupported);
@@ -5671,12 +6020,37 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fno_assume_sane_operator_new))
CmdArgs.push_back("-fno-assume-sane-operator-new");
+ // -frelaxed-template-template-args is off by default, as it is a severe
+ // breaking change until a corresponding change to template partial ordering
+ // is provided.
+ if (Args.hasFlag(options::OPT_frelaxed_template_template_args,
+ options::OPT_fno_relaxed_template_template_args, false))
+ CmdArgs.push_back("-frelaxed-template-template-args");
+
// -fsized-deallocation is off by default, as it is an ABI-breaking change for
// most platforms.
if (Args.hasFlag(options::OPT_fsized_deallocation,
options::OPT_fno_sized_deallocation, false))
CmdArgs.push_back("-fsized-deallocation");
+ // -faligned-allocation is on by default in C++17 onwards and otherwise off
+ // by default.
+ if (Arg *A = Args.getLastArg(options::OPT_faligned_allocation,
+ options::OPT_fno_aligned_allocation,
+ options::OPT_faligned_new_EQ)) {
+ if (A->getOption().matches(options::OPT_fno_aligned_allocation))
+ CmdArgs.push_back("-fno-aligned-allocation");
+ else
+ CmdArgs.push_back("-faligned-allocation");
+ }
+
+ // The default new alignment can be specified using a dedicated option or via
+ // a GCC-compatible option that also turns on aligned allocation.
+ if (Arg *A = Args.getLastArg(options::OPT_fnew_alignment_EQ,
+ options::OPT_faligned_new_EQ))
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine("-fnew-alignment=") + A->getValue()));
+
// -fconstant-cfstrings is default, and may be subject to argument translation
// on Darwin.
if (!Args.hasFlag(options::OPT_fconstant_cfstrings,
@@ -5744,7 +6118,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// -finput_charset=UTF-8 is default. Reject others
if (Arg *inputCharset = Args.getLastArg(options::OPT_finput_charset_EQ)) {
StringRef value = inputCharset->getValue();
- if (value != "UTF-8")
+ if (!value.equals_lower("utf-8"))
D.Diag(diag::err_drv_invalid_value) << inputCharset->getAsString(Args)
<< value;
}
@@ -5752,7 +6126,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// -fexec_charset=UTF-8 is default. Reject others
if (Arg *execCharset = Args.getLastArg(options::OPT_fexec_charset_EQ)) {
StringRef value = execCharset->getValue();
- if (value != "UTF-8")
+ if (!value.equals_lower("utf-8"))
D.Diag(diag::err_drv_invalid_value) << execCharset->getAsString(Args)
<< value;
}
@@ -5778,6 +6152,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(A->getValue());
}
+ if (Args.hasFlag(options::OPT_fdiagnostics_show_hotness,
+ options::OPT_fno_diagnostics_show_hotness, false))
+ CmdArgs.push_back("-fdiagnostics-show-hotness");
+
if (const Arg *A = Args.getLastArg(options::OPT_fdiagnostics_format_EQ)) {
CmdArgs.push_back("-fdiagnostics-format");
CmdArgs.push_back(A->getValue());
@@ -5823,6 +6201,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fno_show_source_location))
CmdArgs.push_back("-fno-show-source-location");
+ if (Args.hasArg(options::OPT_fdiagnostics_absolute_paths))
+ CmdArgs.push_back("-fdiagnostics-absolute-paths");
+
if (!Args.hasFlag(options::OPT_fshow_column, options::OPT_fno_show_column,
true))
CmdArgs.push_back("-fno-show-column");
@@ -5900,6 +6281,40 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-fno-math-builtin");
}
+ if (Args.hasFlag(options::OPT_fsave_optimization_record,
+ options::OPT_fno_save_optimization_record, false)) {
+ CmdArgs.push_back("-opt-record-file");
+
+ const Arg *A = Args.getLastArg(options::OPT_foptimization_record_file_EQ);
+ if (A) {
+ CmdArgs.push_back(A->getValue());
+ } else {
+ SmallString<128> F;
+ if (Output.isFilename() && (Args.hasArg(options::OPT_c) ||
+ Args.hasArg(options::OPT_S))) {
+ F = Output.getFilename();
+ } else {
+ // Use the input filename.
+ F = llvm::sys::path::stem(Input.getBaseInput());
+
+ // If we're compiling for an offload architecture (i.e. a CUDA device),
+ // we need to make the file name for the device compilation different
+ // from the host compilation.
+ if (!JA.isDeviceOffloading(Action::OFK_None) &&
+ !JA.isDeviceOffloading(Action::OFK_Host)) {
+ llvm::sys::path::replace_extension(F, "");
+ F += Action::GetOffloadingFileNamePrefix(JA.getOffloadingDeviceKind(),
+ Triple.normalize());
+ F += "-";
+ F += JA.getOffloadingArch();
+ }
+ }
+
+ llvm::sys::path::replace_extension(F, "opt.yaml");
+ CmdArgs.push_back(Args.MakeArgString(F));
+ }
+ }
+
// Default to -fno-builtin-str{cat,cpy} on Darwin for ARM.
//
// FIXME: Now that PR4941 has been fixed this can be enabled.
@@ -5920,7 +6335,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// nice to enable this when doing a crashdump for modules as well.
if (Args.hasFlag(options::OPT_frewrite_includes,
options::OPT_fno_rewrite_includes, false) ||
- (C.isForDiagnostics() && !HaveModules))
+ (C.isForDiagnostics() && !HaveAnyModules))
CmdArgs.push_back("-frewrite-includes");
// Only allow -traditional or -traditional-cpp outside in preprocessing modes.
@@ -5956,6 +6371,33 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
A->claim();
}
+ // 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));
+ }
+ }
+
// Forward -Xclang arguments to -cc1, and -mllvm arguments to the LLVM option
// parser.
Args.AddAllArgValues(CmdArgs, options::OPT_Xclang);
@@ -5964,8 +6406,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// We translate this by hand to the -cc1 argument, since nightly test uses
// it and developers have been trained to spell it with -mllvm.
- if (StringRef(A->getValue(0)) == "-disable-llvm-optzns") {
- CmdArgs.push_back("-disable-llvm-optzns");
+ if (StringRef(A->getValue(0)) == "-disable-llvm-passes") {
+ CmdArgs.push_back("-disable-llvm-passes");
} else
A->render(Args, CmdArgs);
}
@@ -5979,7 +6421,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// pristine IR generated by the frontend. Ideally, a new compile action should
// be added so both IR can be captured.
if (C.getDriver().isSaveTempsEnabled() &&
- !C.getDriver().embedBitcodeEnabled() && isa<CompileJobAction>(JA))
+ !C.getDriver().embedBitcodeInObject() && isa<CompileJobAction>(JA))
CmdArgs.push_back("-disable-llvm-passes");
if (Output.getType() == types::TY_Dependencies) {
@@ -6041,6 +6483,36 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(I->getFilename());
}
+ // 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
+ // along to tell the frontend that it is generating code for a device, so that
+ // only the relevant declarations are emitted.
+ if (IsOpenMPDevice && Inputs.size() == 2) {
+ CmdArgs.push_back("-fopenmp-is-device");
+ CmdArgs.push_back("-fopenmp-host-ir-file-path");
+ CmdArgs.push_back(Args.MakeArgString(Inputs.back().getFilename()));
+ }
+
+ // 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)) {
+ SmallString<128> TargetInfo("-fopenmp-targets=");
+
+ Arg *Tgts = Args.getLastArg(options::OPT_fopenmp_targets_EQ);
+ assert(Tgts && Tgts->getNumValues() &&
+ "OpenMP offloading has to have targets specified.");
+ for (unsigned i = 0; i < Tgts->getNumValues(); ++i) {
+ if (i)
+ TargetInfo += ',';
+ // We need to get the string from the triple because it may be not exactly
+ // the same as the one we get directly from the arguments.
+ llvm::Triple T(Tgts->getValue(i));
+ TargetInfo += T.getTriple();
+ }
+ CmdArgs.push_back(Args.MakeArgString(TargetInfo.str()));
+ }
+
bool WholeProgramVTables =
Args.hasFlag(options::OPT_fwhole_program_vtables,
options::OPT_fno_whole_program_vtables, false);
@@ -6465,6 +6937,20 @@ void ClangAs::AddMIPSTargetArgs(const ArgList &Args,
CmdArgs.push_back(ABIName.data());
}
+void ClangAs::AddX86TargetArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ if (Arg *A = Args.getLastArg(options::OPT_masm_EQ)) {
+ StringRef Value = A->getValue();
+ if (Value == "intel" || Value == "att") {
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back(Args.MakeArgString("-x86-asm-syntax=" + Value));
+ } else {
+ getToolChain().getDriver().Diag(diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << Value;
+ }
+ }
+}
+
void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output, const InputInfoList &Inputs,
const ArgList &Args,
@@ -6474,9 +6960,8 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
assert(Inputs.size() == 1 && "Unexpected number of inputs.");
const InputInfo &Input = Inputs[0];
- std::string TripleStr =
- getToolChain().ComputeEffectiveClangTriple(Args, Input.getType());
- const llvm::Triple Triple(TripleStr);
+ const llvm::Triple &Triple = getToolChain().getEffectiveTriple();
+ const std::string &TripleStr = Triple.getTriple();
// Don't warn about "clang -w -c foo.s"
Args.ClaimAllArgs(options::OPT_w);
@@ -6571,7 +7056,7 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
unsigned PICLevel;
bool IsPIE;
std::tie(RelocationModel, PICLevel, IsPIE) =
- ParsePICArgs(getToolChain(), Triple, Args);
+ ParsePICArgs(getToolChain(), Args);
const char *RMName = RelocationModelName(RelocationModel);
if (RMName) {
@@ -6612,6 +7097,11 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
case llvm::Triple::mips64el:
AddMIPSTargetArgs(Args, CmdArgs);
break;
+
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ AddX86TargetArgs(Args, CmdArgs);
+ break;
}
// Consume all the warning flags. Usually this would be handled more
@@ -6645,6 +7135,134 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
SplitDebugName(Args, Input));
}
+void OffloadBundler::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const {
+ // The version with only one output is expected to refer to a bundling job.
+ assert(isa<OffloadBundlingJobAction>(JA) && "Expecting bundling job!");
+
+ // The bundling command looks like this:
+ // clang-offload-bundler -type=bc
+ // -targets=host-triple,openmp-triple1,openmp-triple2
+ // -outputs=input_file
+ // -inputs=unbundle_file_host,unbundle_file_tgt1,unbundle_file_tgt2"
+
+ ArgStringList CmdArgs;
+
+ // Get the type.
+ CmdArgs.push_back(TCArgs.MakeArgString(
+ Twine("-type=") + types::getTypeTempSuffix(Output.getType())));
+
+ assert(JA.getInputs().size() == Inputs.size() &&
+ "Not have inputs for all dependence actions??");
+
+ // Get the targets.
+ SmallString<128> Triples;
+ Triples += "-targets=";
+ for (unsigned I = 0; I < Inputs.size(); ++I) {
+ if (I)
+ Triples += ',';
+
+ Action::OffloadKind CurKind = Action::OFK_Host;
+ const ToolChain *CurTC = &getToolChain();
+ const Action *CurDep = JA.getInputs()[I];
+
+ if (const auto *OA = dyn_cast<OffloadAction>(CurDep)) {
+ OA->doOnEachDependence([&](Action *A, const ToolChain *TC, const char *) {
+ CurKind = A->getOffloadingDeviceKind();
+ CurTC = TC;
+ });
+ }
+ Triples += Action::GetOffloadKindName(CurKind);
+ Triples += '-';
+ Triples += CurTC->getTriple().normalize();
+ }
+ CmdArgs.push_back(TCArgs.MakeArgString(Triples));
+
+ // Get bundled file command.
+ CmdArgs.push_back(
+ TCArgs.MakeArgString(Twine("-outputs=") + Output.getFilename()));
+
+ // Get unbundled files command.
+ SmallString<128> UB;
+ UB += "-inputs=";
+ for (unsigned I = 0; I < Inputs.size(); ++I) {
+ if (I)
+ UB += ',';
+ UB += Inputs[I].getFilename();
+ }
+ CmdArgs.push_back(TCArgs.MakeArgString(UB));
+
+ // All the inputs are encoded as commands.
+ C.addCommand(llvm::make_unique<Command>(
+ JA, *this,
+ TCArgs.MakeArgString(getToolChain().GetProgramPath(getShortName())),
+ CmdArgs, None));
+}
+
+void OffloadBundler::ConstructJobMultipleOutputs(
+ Compilation &C, const JobAction &JA, const InputInfoList &Outputs,
+ const InputInfoList &Inputs, const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const {
+ // The version with multiple outputs is expected to refer to a unbundling job.
+ auto &UA = cast<OffloadUnbundlingJobAction>(JA);
+
+ // The unbundling command looks like this:
+ // clang-offload-bundler -type=bc
+ // -targets=host-triple,openmp-triple1,openmp-triple2
+ // -inputs=input_file
+ // -outputs=unbundle_file_host,unbundle_file_tgt1,unbundle_file_tgt2"
+ // -unbundle
+
+ ArgStringList CmdArgs;
+
+ assert(Inputs.size() == 1 && "Expecting to unbundle a single file!");
+ InputInfo Input = Inputs.front();
+
+ // Get the type.
+ CmdArgs.push_back(TCArgs.MakeArgString(
+ Twine("-type=") + types::getTypeTempSuffix(Input.getType())));
+
+ // Get the targets.
+ SmallString<128> Triples;
+ Triples += "-targets=";
+ auto DepInfo = UA.getDependentActionsInfo();
+ for (unsigned I = 0; I < DepInfo.size(); ++I) {
+ if (I)
+ Triples += ',';
+
+ auto &Dep = DepInfo[I];
+ Triples += Action::GetOffloadKindName(Dep.DependentOffloadKind);
+ Triples += '-';
+ Triples += Dep.DependentToolChain->getTriple().normalize();
+ }
+
+ CmdArgs.push_back(TCArgs.MakeArgString(Triples));
+
+ // Get bundled file command.
+ CmdArgs.push_back(
+ TCArgs.MakeArgString(Twine("-inputs=") + Input.getFilename()));
+
+ // Get unbundled files command.
+ SmallString<128> UB;
+ UB += "-outputs=";
+ for (unsigned I = 0; I < Outputs.size(); ++I) {
+ if (I)
+ UB += ',';
+ UB += Outputs[I].getFilename();
+ }
+ CmdArgs.push_back(TCArgs.MakeArgString(UB));
+ CmdArgs.push_back("-unbundle");
+
+ // All the inputs are encoded as commands.
+ C.addCommand(llvm::make_unique<Command>(
+ JA, *this,
+ TCArgs.MakeArgString(getToolChain().GetProgramPath(getShortName())),
+ CmdArgs, None));
+}
+
void GnuTool::anchor() {}
void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
@@ -7022,7 +7640,7 @@ constructHexagonLinkArgs(Compilation &C, const JobAction &JA,
{options::OPT_T_Group, options::OPT_e, options::OPT_s,
options::OPT_t, options::OPT_u_Group});
- AddLinkerInputs(HTC, Inputs, Args, CmdArgs);
+ AddLinkerInputs(HTC, Inputs, Args, CmdArgs, JA);
//----------------------------------------------------------------------------
// Libraries
@@ -7081,7 +7699,7 @@ void amdgpu::Linker::ConstructJob(Compilation &C, const JobAction &JA,
std::string Linker = getToolChain().GetProgramPath(getShortName());
ArgStringList CmdArgs;
- AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+ AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
CmdArgs.push_back("-shared");
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
@@ -7144,7 +7762,7 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));
}
- AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);
+ AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
if (D.CCCIsCXX())
@@ -7397,11 +8015,14 @@ llvm::Triple::ArchType darwin::getArchTypeForMachOArchName(StringRef Str) {
void darwin::setTripleTypeForMachOArchName(llvm::Triple &T, StringRef Str) {
const llvm::Triple::ArchType Arch = getArchTypeForMachOArchName(Str);
+ unsigned ArchKind = llvm::ARM::parseArch(Str);
T.setArch(Arch);
if (Str == "x86_64h")
T.setArchName(Str);
- else if (Str == "armv6m" || Str == "armv7m" || Str == "armv7em") {
+ else if (ArchKind == llvm::ARM::AK_ARMV6M ||
+ ArchKind == llvm::ARM::AK_ARMV7M ||
+ ArchKind == llvm::ARM::AK_ARMV7EM) {
T.setOS(llvm::Triple::UnknownOS);
T.setObjectFormat(llvm::Triple::MachO);
}
@@ -7488,9 +8109,9 @@ void cloudabi::Linker::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_t, options::OPT_Z_Flag, options::OPT_r});
if (D.isUsingLTO())
- AddGoldPlugin(ToolChain, Args, CmdArgs, D.getLTOMode() == LTOK_Thin);
+ AddGoldPlugin(ToolChain, Args, CmdArgs, D.getLTOMode() == LTOK_Thin, D);
- AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);
+ AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
if (D.CCCIsCXX())
@@ -7600,6 +8221,29 @@ bool darwin::Linker::NeedsTempPath(const InputInfoList &Inputs) const {
return false;
}
+/// \brief 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)
+///
+/// Also do *not* add -no_deduplicate when no -O option is specified and this
+/// is just a link (we can't imply -O0)
+static bool shouldLinkerNotDedup(bool IsLinkerOnlyAction, const ArgList &Args) {
+ if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
+ if (A->getOption().matches(options::OPT_O0))
+ return true;
+ if (A->getOption().matches(options::OPT_O))
+ return llvm::StringSwitch<bool>(A->getValue())
+ .Case("1", true)
+ .Default(false);
+ return false; // OPT_Ofast & OPT_O4
+ }
+
+ if (!IsLinkerOnlyAction) // Implicit -O0 for compile+linker only.
+ return true;
+ return false;
+}
+
void darwin::Linker::AddLinkArgs(Compilation &C, const ArgList &Args,
ArgStringList &CmdArgs,
const InputInfoList &Inputs) const {
@@ -7656,6 +8300,10 @@ void darwin::Linker::AddLinkArgs(Compilation &C, const ArgList &Args,
CmdArgs.push_back(C.getArgs().MakeArgString(LibLTOPath));
}
+ // ld64 version 262 and above run the deduplicate pass by default.
+ if (Version[0] >= 262 && shouldLinkerNotDedup(C.getJobs().empty(), Args))
+ CmdArgs.push_back("-no_deduplicate");
+
// Derived from the "link" spec.
Args.AddAllArgs(CmdArgs, options::OPT_static);
if (!Args.hasArg(options::OPT_static))
@@ -7742,9 +8390,9 @@ void darwin::Linker::AddLinkArgs(Compilation &C, const ArgList &Args,
else
CmdArgs.push_back("-no_pie");
}
+
// for embed-bitcode, use -bitcode_bundle in linker command
- if (C.getDriver().embedBitcodeEnabled() ||
- C.getDriver().embedBitcodeMarkerOnly()) {
+ if (C.getDriver().embedBitcodeEnabled()) {
// Check if the toolchain supports bitcode build flow.
if (MachOTC.SupportsEmbeddedBitcode())
CmdArgs.push_back("-bitcode_bundle");
@@ -7837,6 +8485,24 @@ 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.
+ if (Args.hasFlag(options::OPT_fsave_optimization_record,
+ options::OPT_fno_save_optimization_record, false)) {
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back("-lto-pass-remarks-output");
+ CmdArgs.push_back("-mllvm");
+
+ SmallString<128> F;
+ F = Output.getFilename();
+ F += ".opt.yaml";
+ CmdArgs.push_back(Args.MakeArgString(F));
+
+ if (getLastProfileUseArg(Args)) {
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back("-lto-pass-remarks-with-hotness");
+ }
+ }
+
// It seems that the 'e' option is completely ignored for dynamic executables
// (the default), and with static executables, the last one wins, as expected.
Args.AddAllArgs(CmdArgs, {options::OPT_d_Flag, options::OPT_s, options::OPT_t,
@@ -7866,7 +8532,7 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_L);
- AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+ AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
// Build the input file for -filelist (list of linker input files) in case we
// need it later
for (const auto &II : Inputs) {
@@ -7909,6 +8575,13 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
getMachOToolChain().addProfileRTLibs(Args, CmdArgs);
+ if (unsigned Parallelism =
+ getLTOParallelism(Args, getToolChain().getDriver())) {
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine("-threads=") + llvm::to_string(Parallelism)));
+ }
+
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
if (getToolChain().getDriver().CCCIsCXX())
getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
@@ -8084,7 +8757,7 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group,
options::OPT_e, options::OPT_r});
- AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+ AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
if (getToolChain().getDriver().CCCIsCXX())
@@ -8257,7 +8930,7 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_e, options::OPT_s, options::OPT_t,
options::OPT_Z_Flag, options::OPT_r});
- AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+ AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
if (D.CCCIsCXX()) {
@@ -8376,7 +9049,7 @@ void bitrig::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs,
{options::OPT_L, options::OPT_T_Group, options::OPT_e});
- AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+ AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
if (D.CCCIsCXX()) {
@@ -8639,10 +9312,10 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_r);
if (D.isUsingLTO())
- AddGoldPlugin(ToolChain, Args, CmdArgs, D.getLTOMode() == LTOK_Thin);
+ AddGoldPlugin(ToolChain, Args, CmdArgs, D.getLTOMode() == LTOK_Thin, D);
bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
- AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);
+ AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
addOpenMPRuntime(CmdArgs, ToolChain, Args);
@@ -8849,9 +9522,7 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
break;
case llvm::Triple::armeb:
case llvm::Triple::thumbeb:
- arm::appendEBLinkFlags(
- Args, CmdArgs,
- llvm::Triple(getToolChain().ComputeEffectiveClangTriple(Args)));
+ arm::appendEBLinkFlags(Args, CmdArgs, getToolChain().getEffectiveTriple());
CmdArgs.push_back("-m");
switch (getToolChain().getTriple().getEnvironment()) {
case llvm::Triple::EABI:
@@ -8939,7 +9610,7 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag);
Args.AddAllArgs(CmdArgs, options::OPT_r);
- AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+ AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
unsigned Major, Minor, Micro;
getToolChain().getTriple().getOSVersion(Major, Minor, Micro);
@@ -9015,16 +9686,13 @@ void gnutools::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
const char *LinkingOutput) const {
claimNoWarnArgs(Args);
- std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args);
- llvm::Triple Triple = llvm::Triple(TripleStr);
-
ArgStringList CmdArgs;
llvm::Reloc::Model RelocationModel;
unsigned PICLevel;
bool IsPIE;
std::tie(RelocationModel, PICLevel, IsPIE) =
- ParsePICArgs(getToolChain(), Triple, Args);
+ ParsePICArgs(getToolChain(), Args);
switch (getToolChain().getArch()) {
default:
@@ -9107,7 +9775,7 @@ void gnutools::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
// march from being picked in the absence of a cpu flag.
Arg *A;
if ((A = Args.getLastArg(options::OPT_mcpu_EQ)) &&
- StringRef(A->getValue()).lower() == "krait")
+ StringRef(A->getValue()).equals_lower("krait"))
CmdArgs.push_back("-mcpu=cortex-a15");
else
Args.AddLastArg(CmdArgs, options::OPT_mcpu_EQ);
@@ -9273,6 +9941,7 @@ static void AddRunTimeLibs(const ToolChain &TC, const Driver &D,
llvm_unreachable("unsupported OS");
case llvm::Triple::Win32:
case llvm::Triple::Linux:
+ case llvm::Triple::Fuchsia:
addClangRT(TC, Args, CmdArgs);
break;
}
@@ -9338,7 +10007,7 @@ static const char *getLDMOption(const llvm::Triple &T, const ArgList &Args) {
return "elf32_x86_64";
return "elf_x86_64";
default:
- llvm_unreachable("Unexpected arch");
+ return nullptr;
}
}
@@ -9351,8 +10020,7 @@ void gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
static_cast<const toolchains::Linux &>(getToolChain());
const Driver &D = ToolChain.getDriver();
- std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args);
- llvm::Triple Triple = llvm::Triple(TripleStr);
+ const llvm::Triple &Triple = getToolChain().getEffectiveTriple();
const llvm::Triple::ArchType Arch = ToolChain.getArch();
const bool isAndroid = ToolChain.getTriple().isAndroid();
@@ -9397,6 +10065,14 @@ void gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (Arch == llvm::Triple::armeb || Arch == llvm::Triple::thumbeb)
arm::appendEBLinkFlags(Args, CmdArgs, Triple);
+ // Most Android ARM64 targets should enable the linker fix for erratum
+ // 843419. Only non-Cortex-A53 devices are allowed to skip this flag.
+ if (Arch == llvm::Triple::aarch64 && isAndroid) {
+ std::string CPU = getCPUName(Args, Triple);
+ if (CPU.empty() || CPU == "generic" || CPU == "cortex-a53")
+ CmdArgs.push_back("--fix-cortex-a53-843419");
+ }
+
for (const auto &Opt : ToolChain.ExtraOpts)
CmdArgs.push_back(Opt.c_str());
@@ -9404,8 +10080,13 @@ void gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("--eh-frame-hdr");
}
- CmdArgs.push_back("-m");
- CmdArgs.push_back(getLDMOption(ToolChain.getTriple(), Args));
+ if (const char *LDMOption = getLDMOption(ToolChain.getTriple(), Args)) {
+ CmdArgs.push_back("-m");
+ CmdArgs.push_back(LDMOption);
+ } else {
+ D.Diag(diag::err_target_unknown_triple) << Triple.str();
+ return;
+ }
if (Args.hasArg(options::OPT_static)) {
if (Arch == llvm::Triple::arm || Arch == llvm::Triple::armeb ||
@@ -9476,14 +10157,14 @@ void gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
ToolChain.AddFilePathLibArgs(Args, CmdArgs);
if (D.isUsingLTO())
- AddGoldPlugin(ToolChain, Args, CmdArgs, D.getLTOMode() == LTOK_Thin);
+ AddGoldPlugin(ToolChain, Args, CmdArgs, D.getLTOMode() == LTOK_Thin, D);
if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
CmdArgs.push_back("--no-demangle");
bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs);
- AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);
+ AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
// The profile runtime also needs access to system libraries.
getToolChain().addProfileRTLibs(Args, CmdArgs);
@@ -9522,24 +10203,26 @@ void gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
WantPthread = true;
// Also link the particular OpenMP runtimes.
- switch (getOpenMPRuntime(ToolChain, Args)) {
- case OMPRT_OMP:
+ switch (ToolChain.getDriver().getOpenMPRuntime(Args)) {
+ case Driver::OMPRT_OMP:
CmdArgs.push_back("-lomp");
break;
- case OMPRT_GOMP:
+ case Driver::OMPRT_GOMP:
CmdArgs.push_back("-lgomp");
// FIXME: Exclude this for platforms with libgomp that don't require
// librt. Most modern Linux platforms require it, but some may not.
CmdArgs.push_back("-lrt");
break;
- case OMPRT_IOMP5:
+ case Driver::OMPRT_IOMP5:
CmdArgs.push_back("-liomp5");
break;
- case OMPRT_Unknown:
+ case Driver::OMPRT_Unknown:
// Already diagnosed.
break;
}
+ if (JA.isHostOffloading(Action::OFK_OpenMP))
+ CmdArgs.push_back("-lomptarget");
}
AddRunTimeLibs(ToolChain, D, CmdArgs, Args);
@@ -9585,6 +10268,9 @@ void gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
}
+ // Add OpenMP offloading linker script args if required.
+ AddOpenMPLinkerScript(getToolChain(), C, Output, Inputs, Args, CmdArgs, JA);
+
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
@@ -9694,7 +10380,7 @@ void nacltools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
CmdArgs.push_back("--no-demangle");
- AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);
+ AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
if (D.CCCIsCXX() &&
!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
@@ -9760,6 +10446,112 @@ void nacltools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
+void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ const toolchains::Fuchsia &ToolChain =
+ static_cast<const toolchains::Fuchsia &>(getToolChain());
+ const Driver &D = ToolChain.getDriver();
+
+ ArgStringList CmdArgs;
+
+ // Silence warning for "clang -g foo.o -o foo"
+ Args.ClaimAllArgs(options::OPT_g_Group);
+ // and "clang -emit-llvm foo.o -o foo"
+ Args.ClaimAllArgs(options::OPT_emit_llvm);
+ // and for "clang -w foo.o -o foo". Other warning options are already
+ // handled somewhere else.
+ Args.ClaimAllArgs(options::OPT_w);
+
+ const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
+ if (llvm::sys::path::stem(Exec).equals_lower("lld")) {
+ CmdArgs.push_back("-flavor");
+ CmdArgs.push_back("gnu");
+ }
+
+ if (!D.SysRoot.empty())
+ CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
+
+ if (!Args.hasArg(options::OPT_shared) && !Args.hasArg(options::OPT_r))
+ CmdArgs.push_back("-pie");
+
+ if (Args.hasArg(options::OPT_rdynamic))
+ CmdArgs.push_back("-export-dynamic");
+
+ if (Args.hasArg(options::OPT_s))
+ CmdArgs.push_back("-s");
+
+ if (Args.hasArg(options::OPT_r))
+ CmdArgs.push_back("-r");
+ else
+ CmdArgs.push_back("--build-id");
+
+ if (!Args.hasArg(options::OPT_static))
+ CmdArgs.push_back("--eh-frame-hdr");
+
+ if (Args.hasArg(options::OPT_static))
+ CmdArgs.push_back("-Bstatic");
+ else if (Args.hasArg(options::OPT_shared))
+ CmdArgs.push_back("-shared");
+
+ if (!Args.hasArg(options::OPT_static)) {
+ if (Args.hasArg(options::OPT_rdynamic))
+ CmdArgs.push_back("-export-dynamic");
+
+ if (!Args.hasArg(options::OPT_shared)) {
+ CmdArgs.push_back("-dynamic-linker");
+ CmdArgs.push_back(Args.MakeArgString(D.DyldPrefix + "ld.so.1"));
+ }
+ }
+
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_shared)) {
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("Scrt1.o")));
+ }
+ }
+
+ Args.AddAllArgs(CmdArgs, options::OPT_L);
+ Args.AddAllArgs(CmdArgs, options::OPT_u);
+
+ ToolChain.AddFilePathLibArgs(Args, CmdArgs);
+
+ AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
+
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
+ if (Args.hasArg(options::OPT_static))
+ CmdArgs.push_back("-Bdynamic");
+
+ if (D.CCCIsCXX()) {
+ bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) &&
+ !Args.hasArg(options::OPT_static);
+ if (OnlyLibstdcxxStatic)
+ CmdArgs.push_back("-Bstatic");
+ ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
+ if (OnlyLibstdcxxStatic)
+ CmdArgs.push_back("-Bdynamic");
+ CmdArgs.push_back("-lm");
+ }
+
+ AddRunTimeLibs(ToolChain, D, CmdArgs, Args);
+
+ if (Args.hasArg(options::OPT_pthread) ||
+ Args.hasArg(options::OPT_pthreads))
+ CmdArgs.push_back("-lpthread");
+
+ if (Args.hasArg(options::OPT_fsplit_stack))
+ CmdArgs.push_back("--wrap=pthread_create");
+
+ CmdArgs.push_back("-lc");
+ }
+
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+}
+
void minix::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
@@ -9806,7 +10598,7 @@ void minix::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs,
{options::OPT_L, options::OPT_T_Group, options::OPT_e});
- AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+ AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
getToolChain().addProfileRTLibs(Args, CmdArgs);
@@ -9927,7 +10719,7 @@ void dragonfly::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs,
{options::OPT_L, options::OPT_T_Group, options::OPT_e});
- AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+ AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
CmdArgs.push_back("-L/usr/lib/gcc50");
@@ -10050,14 +10842,14 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
std::string UniversalCRTLibPath;
if (MSVC.getUniversalCRTLibraryPath(UniversalCRTLibPath))
CmdArgs.push_back(Args.MakeArgString(std::string("-libpath:") +
- UniversalCRTLibPath.c_str()));
+ UniversalCRTLibPath));
}
}
std::string WindowsSdkLibPath;
if (MSVC.getWindowsSDKLibraryPath(WindowsSdkLibPath))
- CmdArgs.push_back(Args.MakeArgString(std::string("-libpath:") +
- WindowsSdkLibPath.c_str()));
+ CmdArgs.push_back(
+ Args.MakeArgString(std::string("-libpath:") + WindowsSdkLibPath));
}
if (!C.getDriver().IsCLMode() && Args.hasArg(options::OPT_L))
@@ -10083,12 +10875,16 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (TC.getSanitizerArgs().needsAsanRt()) {
CmdArgs.push_back(Args.MakeArgString("-debug"));
CmdArgs.push_back(Args.MakeArgString("-incremental:no"));
- if (Args.hasArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd)) {
+ if (TC.getSanitizerArgs().needsSharedAsanRt() ||
+ Args.hasArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd)) {
for (const auto &Lib : {"asan_dynamic", "asan_dynamic_runtime_thunk"})
CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib));
// Make sure the dynamic runtime thunk is not optimized out at link time
// to ensure proper SEH handling.
- CmdArgs.push_back(Args.MakeArgString("-include:___asan_seh_interceptor"));
+ CmdArgs.push_back(Args.MakeArgString(
+ TC.getArch() == llvm::Triple::x86
+ ? "-include:___asan_seh_interceptor"
+ : "-include:__asan_seh_interceptor"));
} else if (DLL) {
CmdArgs.push_back(TC.getCompilerRTArgString(Args, "asan_dll_thunk"));
} else {
@@ -10105,16 +10901,16 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-nodefaultlib:vcompd.lib");
CmdArgs.push_back(Args.MakeArgString(std::string("-libpath:") +
TC.getDriver().Dir + "/../lib"));
- switch (getOpenMPRuntime(getToolChain(), Args)) {
- case OMPRT_OMP:
+ switch (TC.getDriver().getOpenMPRuntime(Args)) {
+ case Driver::OMPRT_OMP:
CmdArgs.push_back("-defaultlib:libomp.lib");
break;
- case OMPRT_IOMP5:
+ case Driver::OMPRT_IOMP5:
CmdArgs.push_back("-defaultlib:libiomp5md.lib");
break;
- case OMPRT_GOMP:
+ case Driver::OMPRT_GOMP:
break;
- case OMPRT_Unknown:
+ case Driver::OMPRT_Unknown:
// Already diagnosed.
break;
}
@@ -10272,6 +11068,14 @@ std::unique_ptr<Command> visualstudio::Compiler::GetCommand(
options::OPT__SLASH_MT, options::OPT__SLASH_MTd))
A->render(Args, CmdArgs);
+ // Use MSVC's default threadsafe statics behaviour unless there was a flag.
+ if (Arg *A = Args.getLastArg(options::OPT_fthreadsafe_statics,
+ options::OPT_fno_threadsafe_statics)) {
+ CmdArgs.push_back(A->getOption().getID() == options::OPT_fthreadsafe_statics
+ ? "/Zc:threadSafeInit"
+ : "/Zc:threadSafeInit-");
+ }
+
// Pass through all unknown arguments so that the fallback command can see
// them too.
Args.AddAllArgs(CmdArgs, options::OPT_UNKNOWN);
@@ -10454,7 +11258,7 @@ void MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_L);
TC.AddFilePathLibArgs(Args, CmdArgs);
- AddLinkerInputs(TC, Inputs, Args, CmdArgs);
+ AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA);
// TODO: Add ASan stuff here
@@ -10578,7 +11382,7 @@ void XCore::Linker::ConstructJob(Compilation &C, const JobAction &JA,
false))
CmdArgs.push_back("-fexceptions");
- AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+ AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("xcc"));
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
@@ -10732,7 +11536,7 @@ void CrossWindows::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_L);
TC.AddFilePathLibArgs(Args, CmdArgs);
- AddLinkerInputs(TC, Inputs, Args, CmdArgs);
+ AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA);
if (D.CCCIsCXX() && !Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nodefaultlibs)) {
@@ -10798,12 +11602,14 @@ void tools::SHAVE::Compiler::ConstructJob(Compilation &C, const JobAction &JA,
// Append all -I, -iquote, -isystem paths, defines/undefines,
// 'f' flags, optimize flags, and warning options.
// These are spelled the same way in clang and moviCompile.
- Args.AddAllArgs(CmdArgs, {options::OPT_I_Group, options::OPT_clang_i_Group,
- options::OPT_std_EQ, options::OPT_D, options::OPT_U,
- options::OPT_f_Group, options::OPT_f_clang_Group,
- options::OPT_g_Group, options::OPT_M_Group,
- options::OPT_O_Group, options::OPT_W_Group,
- options::OPT_mcpu_EQ});
+ Args.AddAllArgsExcept(
+ CmdArgs,
+ {options::OPT_I_Group, options::OPT_clang_i_Group, options::OPT_std_EQ,
+ options::OPT_D, options::OPT_U, options::OPT_f_Group,
+ options::OPT_f_clang_Group, options::OPT_g_Group, options::OPT_M_Group,
+ options::OPT_O_Group, options::OPT_W_Group, options::OPT_mcpu_EQ},
+ {options::OPT_fno_split_dwarf_inlining});
+ Args.hasArg(options::OPT_fno_split_dwarf_inlining); // Claim it if present.
// If we're producing a dependency file, and assembly is the final action,
// then the name of the target in the dependency file should be the '.o'
@@ -10879,6 +11685,8 @@ void tools::Myriad::Linker::ConstructJob(Compilation &C, const JobAction &JA,
!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles);
bool UseDefaultLibs =
!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs);
+ // Silence warning if the args contain both -nostdlib and -stdlib=.
+ Args.getLastArg(options::OPT_stdlib_EQ);
if (T.getArch() == llvm::Triple::sparc)
CmdArgs.push_back("-EB");
@@ -10913,22 +11721,31 @@ void tools::Myriad::Linker::ConstructJob(Compilation &C, const JobAction &JA,
TC.AddFilePathLibArgs(Args, CmdArgs);
- AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+ bool NeedsSanitizerDeps = addSanitizerRuntimes(TC, Args, CmdArgs);
+ AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
if (UseDefaultLibs) {
- if (C.getDriver().CCCIsCXX())
- CmdArgs.push_back("-lstdc++");
+ if (NeedsSanitizerDeps)
+ linkSanitizerRuntimeDeps(TC, CmdArgs);
+ if (C.getDriver().CCCIsCXX()) {
+ if (TC.GetCXXStdlibType(Args) == ToolChain::CST_Libcxx) {
+ CmdArgs.push_back("-lc++");
+ CmdArgs.push_back("-lc++abi");
+ } else
+ CmdArgs.push_back("-lstdc++");
+ }
if (T.getOS() == llvm::Triple::RTEMS) {
CmdArgs.push_back("--start-group");
CmdArgs.push_back("-lc");
+ CmdArgs.push_back("-lgcc"); // circularly dependent on rtems
// You must provide your own "-L" option to enable finding these.
CmdArgs.push_back("-lrtemscpu");
CmdArgs.push_back("-lrtemsbsp");
CmdArgs.push_back("--end-group");
} else {
CmdArgs.push_back("-lc");
+ CmdArgs.push_back("-lgcc");
}
- CmdArgs.push_back("-lgcc");
}
if (UseStartfiles) {
CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtend.o")));
@@ -11022,7 +11839,7 @@ static void ConstructPS4LinkJob(const Tool &T, Compilation &C,
if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
CmdArgs.push_back("--no-demangle");
- AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);
+ AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
if (Args.hasArg(options::OPT_pthread)) {
CmdArgs.push_back("-lpthread");
@@ -11118,7 +11935,7 @@ static void ConstructGoldLinkJob(const Tool &T, Compilation &C,
if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
CmdArgs.push_back("--no-demangle");
- AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);
+ AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
// For PS4, we always want to pass libm, libstdc++ and libkernel
@@ -11254,7 +12071,7 @@ void NVPTX::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
// Check that our installation's ptxas supports gpu_arch.
if (!Args.hasArg(options::OPT_no_cuda_version_check)) {
- TC.cudaInstallation().CheckCudaVersionSupportsArch(gpu_arch);
+ TC.CudaInstallation.CheckCudaVersionSupportsArch(gpu_arch);
}
ArgStringList CmdArgs;
@@ -11307,7 +12124,11 @@ 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));
- const char *Exec = Args.MakeArgString(TC.GetProgramPath("ptxas"));
+ const char *Exec;
+ if (Arg *A = Args.getLastArg(options::OPT_ptxas_path_EQ))
+ Exec = A->getValue();
+ else
+ Exec = Args.MakeArgString(TC.GetProgramPath("ptxas"));
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
diff --git a/lib/Driver/Tools.h b/lib/Driver/Tools.h
index 02bdb8e5e2d2..98dcf841169e 100644
--- a/lib/Driver/Tools.h
+++ b/lib/Driver/Tools.h
@@ -17,6 +17,7 @@
#include "clang/Driver/Util.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Option/Option.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Compiler.h"
namespace clang {
@@ -101,6 +102,12 @@ private:
mutable std::unique_ptr<visualstudio::Compiler> CLFallback;
+ mutable std::unique_ptr<llvm::raw_fd_ostream> CompilationDatabase = nullptr;
+ void DumpCompilationDatabase(Compilation &C, StringRef Filename,
+ StringRef Target,
+ const InputInfo &Output, const InputInfo &Input,
+ const llvm::opt::ArgList &Args) const;
+
public:
// CAUTION! The first constructor argument ("clang") is not arbitrary,
// as it is for other tools. Some operations on a Tool actually test
@@ -125,6 +132,8 @@ public:
: Tool("clang::as", "clang integrated assembler", TC, RF_Full) {}
void AddMIPSTargetArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const;
+ void AddX86TargetArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
bool hasGoodDiagnostics() const override { return true; }
bool hasIntegratedAssembler() const override { return false; }
bool hasIntegratedCPP() const override { return false; }
@@ -135,6 +144,24 @@ public:
const char *LinkingOutput) const override;
};
+/// Offload bundler tool.
+class LLVM_LIBRARY_VISIBILITY OffloadBundler final : public Tool {
+public:
+ OffloadBundler(const ToolChain &TC)
+ : Tool("offload bundler", "clang-offload-bundler", 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;
+ void ConstructJobMultipleOutputs(Compilation &C, const JobAction &JA,
+ const InputInfoList &Outputs,
+ const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
+
/// \brief 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 {
@@ -594,6 +621,21 @@ public:
};
} // end namespace nacltools
+namespace fuchsia {
+class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
+public:
+ Linker(const ToolChain &TC) : GnuTool("fuchsia::Linker", "ld.lld", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+ bool isLinkJob() const override { return true; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
+} // end namespace fuchsia
+
/// minix -- Directly call GNU Binutils assembler and linker
namespace minix {
class LLVM_LIBRARY_VISIBILITY Assembler : public GnuTool {
@@ -683,10 +725,6 @@ public:
/// Visual studio tools.
namespace visualstudio {
-VersionTuple getMSVCVersion(const Driver *D, const ToolChain &TC,
- const llvm::Triple &Triple,
- const llvm::opt::ArgList &Args, bool IsWindowsMSVC);
-
class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
public:
Linker(const ToolChain &TC)
diff --git a/lib/Driver/Types.cpp b/lib/Driver/Types.cpp
index f8e1e40dc6bf..ab63f0e81b12 100644
--- a/lib/Driver/Types.cpp
+++ b/lib/Driver/Types.cpp
@@ -44,13 +44,28 @@ types::ID types::getPreprocessedType(ID Id) {
return getInfo(Id).PreprocessedType;
}
+types::ID types::getPrecompiledType(ID Id) {
+ if (strchr(getInfo(Id).Flags, 'm'))
+ return TY_ModuleFile;
+ if (onlyPrecompileType(Id))
+ return TY_PCH;
+ return TY_INVALID;
+}
+
const char *types::getTypeTempSuffix(ID Id, bool CLMode) {
- if (Id == TY_Object && CLMode)
- return "obj";
- if (Id == TY_Image && CLMode)
- return "exe";
- if (Id == TY_PP_Asm && CLMode)
- return "asm";
+ if (CLMode) {
+ switch (Id) {
+ case TY_Object:
+ case TY_LTO_BC:
+ return "obj";
+ case TY_Image:
+ return "exe";
+ case TY_PP_Asm:
+ return "asm";
+ default:
+ break;
+ }
+ }
return getInfo(Id).TempSuffix;
}
@@ -95,6 +110,7 @@ bool types::isAcceptedByClang(ID Id) {
case TY_ObjCHeader: case TY_PP_ObjCHeader:
case TY_CXXHeader: case TY_PP_CXXHeader:
case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader:
+ case TY_CXXModule: case TY_PP_CXXModule:
case TY_AST: case TY_ModuleFile:
case TY_LLVM_IR: case TY_LLVM_BC:
return true;
@@ -123,6 +139,7 @@ bool types::isCXX(ID Id) {
case TY_ObjCXX: case TY_PP_ObjCXX: case TY_PP_ObjCXX_Alias:
case TY_CXXHeader: case TY_PP_CXXHeader:
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:
return true;
}
@@ -153,58 +170,67 @@ bool types::isCuda(ID Id) {
}
}
-types::ID types::lookupTypeForExtension(const char *Ext) {
+bool types::isSrcFile(ID Id) {
+ return Id != TY_Object && getPreprocessedType(Id) != TY_INVALID;
+}
+
+types::ID types::lookupTypeForExtension(llvm::StringRef Ext) {
return llvm::StringSwitch<types::ID>(Ext)
.Case("c", TY_C)
+ .Case("C", TY_CXX)
+ .Case("F", TY_Fortran)
+ .Case("f", TY_PP_Fortran)
+ .Case("h", TY_CHeader)
+ .Case("H", TY_CXXHeader)
.Case("i", TY_PP_C)
.Case("m", TY_ObjC)
.Case("M", TY_ObjCXX)
- .Case("h", TY_CHeader)
- .Case("C", TY_CXX)
- .Case("H", TY_CXXHeader)
- .Case("f", TY_PP_Fortran)
- .Case("F", TY_Fortran)
- .Case("s", TY_PP_Asm)
- .Case("asm", TY_PP_Asm)
- .Case("S", TY_Asm)
.Case("o", TY_Object)
- .Case("obj", TY_Object)
- .Case("lib", TY_Object)
- .Case("ii", TY_PP_CXX)
- .Case("mi", TY_PP_ObjC)
- .Case("mm", TY_ObjCXX)
+ .Case("S", TY_Asm)
+ .Case("s", TY_PP_Asm)
.Case("bc", TY_LLVM_BC)
.Case("cc", TY_CXX)
.Case("CC", TY_CXX)
.Case("cl", TY_CL)
.Case("cp", TY_CXX)
.Case("cu", TY_CUDA)
- .Case("cui", TY_PP_CUDA)
.Case("hh", TY_CXXHeader)
+ .Case("ii", TY_PP_CXX)
.Case("ll", TY_LLVM_IR)
- .Case("hpp", TY_CXXHeader)
- .Case("ads", TY_Ada)
+ .Case("mi", TY_PP_ObjC)
+ .Case("mm", TY_ObjCXX)
+ .Case("rs", TY_RenderScript)
.Case("adb", TY_Ada)
+ .Case("ads", TY_Ada)
+ .Case("asm", TY_PP_Asm)
.Case("ast", TY_AST)
+ .Case("ccm", TY_CXXModule)
+ .Case("cpp", TY_CXX)
+ .Case("CPP", TY_CXX)
.Case("c++", TY_CXX)
.Case("C++", TY_CXX)
+ .Case("cui", TY_PP_CUDA)
.Case("cxx", TY_CXX)
- .Case("cpp", TY_CXX)
- .Case("CPP", TY_CXX)
.Case("CXX", TY_CXX)
+ .Case("F90", TY_Fortran)
+ .Case("f90", TY_PP_Fortran)
+ .Case("F95", TY_Fortran)
+ .Case("f95", TY_PP_Fortran)
.Case("for", TY_PP_Fortran)
.Case("FOR", TY_PP_Fortran)
.Case("fpp", TY_Fortran)
.Case("FPP", TY_Fortran)
- .Case("f90", TY_PP_Fortran)
- .Case("f95", TY_PP_Fortran)
- .Case("F90", TY_Fortran)
- .Case("F95", TY_Fortran)
+ .Case("gch", TY_PCH)
+ .Case("hpp", TY_CXXHeader)
+ .Case("iim", TY_PP_CXXModule)
+ .Case("lib", TY_Object)
.Case("mii", TY_PP_ObjCXX)
- .Case("pcm", TY_ModuleFile)
+ .Case("obj", TY_Object)
.Case("pch", TY_PCH)
- .Case("gch", TY_PCH)
- .Case("rs", TY_RenderScript)
+ .Case("pcm", TY_ModuleFile)
+ .Case("c++m", TY_CXXModule)
+ .Case("cppm", TY_CXXModule)
+ .Case("cxxm", TY_CXXModule)
.Default(TY_INVALID);
}
@@ -226,9 +252,11 @@ void types::getCompilationPhases(ID Id, llvm::SmallVectorImpl<phases::ID> &P) {
P.push_back(phases::Preprocess);
}
- if (onlyPrecompileType(Id)) {
+ if (getPrecompiledType(Id) != TY_INVALID) {
P.push_back(phases::Precompile);
- } else {
+ }
+
+ if (!onlyPrecompileType(Id)) {
if (!onlyAssembleType(Id)) {
P.push_back(phases::Compile);
P.push_back(phases::Backend);
@@ -237,7 +265,7 @@ void types::getCompilationPhases(ID Id, llvm::SmallVectorImpl<phases::ID> &P) {
}
}
- if (!onlyPrecompileType(Id) && Id != TY_CUDA_DEVICE) {
+ if (!onlyPrecompileType(Id)) {
P.push_back(phases::Link);
}
assert(0 < P.size() && "Not enough phases in list");
@@ -259,3 +287,21 @@ ID types::lookupCXXTypeForCType(ID Id) {
return types::TY_PP_CXXHeader;
}
}
+
+ID types::lookupHeaderTypeForSourceType(ID Id) {
+ switch (Id) {
+ default:
+ return Id;
+
+ case types::TY_C:
+ return types::TY_CHeader;
+ case types::TY_CXX:
+ return types::TY_CXXHeader;
+ case types::TY_ObjC:
+ return types::TY_ObjCHeader;
+ case types::TY_ObjCXX:
+ return types::TY_ObjCXXHeader;
+ case types::TY_CL:
+ return types::TY_CLHeader;
+ }
+}
diff --git a/lib/Edit/RewriteObjCFoundationAPI.cpp b/lib/Edit/RewriteObjCFoundationAPI.cpp
index 482c0f6f8568..2148316532de 100644
--- a/lib/Edit/RewriteObjCFoundationAPI.cpp
+++ b/lib/Edit/RewriteObjCFoundationAPI.cpp
@@ -1076,6 +1076,8 @@ static bool rewriteToNumericBoxedExpression(const ObjCMessageExpr *Msg,
case CK_CopyAndAutoreleaseBlockObject:
case CK_BuiltinFnToFnPtr:
case CK_ZeroToOCLEvent:
+ case CK_ZeroToOCLQueue:
+ case CK_IntToOCLSampler:
return false;
case CK_BooleanToSignedIntegral:
diff --git a/lib/Format/BreakableToken.cpp b/lib/Format/BreakableToken.cpp
index 36a8c4d8da6d..6363f895f95b 100644
--- a/lib/Format/BreakableToken.cpp
+++ b/lib/Format/BreakableToken.cpp
@@ -14,6 +14,7 @@
//===----------------------------------------------------------------------===//
#include "BreakableToken.h"
+#include "Comments.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Format/Format.h"
#include "llvm/ADT/STLExtras.h"
@@ -182,21 +183,6 @@ void BreakableStringLiteral::insertBreak(unsigned LineIndex,
Prefix, InPPDirective, 1, IndentLevel, LeadingSpaces);
}
-static StringRef getLineCommentIndentPrefix(StringRef Comment) {
- static const char *const KnownPrefixes[] = {"///", "//", "//!"};
- StringRef LongestPrefix;
- for (StringRef KnownPrefix : KnownPrefixes) {
- if (Comment.startswith(KnownPrefix)) {
- size_t PrefixLength = KnownPrefix.size();
- while (PrefixLength < Comment.size() && Comment[PrefixLength] == ' ')
- ++PrefixLength;
- if (PrefixLength > LongestPrefix.size())
- LongestPrefix = Comment.substr(0, PrefixLength);
- }
- }
- return LongestPrefix;
-}
-
BreakableLineComment::BreakableLineComment(
const FormatToken &Token, unsigned IndentLevel, unsigned StartColumn,
bool InPPDirective, encoding::Encoding Encoding, const FormatStyle &Style)
diff --git a/lib/Format/CMakeLists.txt b/lib/Format/CMakeLists.txt
index cb46b9f255d2..c977c2d3c5fa 100644
--- a/lib/Format/CMakeLists.txt
+++ b/lib/Format/CMakeLists.txt
@@ -3,6 +3,7 @@ set(LLVM_LINK_COMPONENTS support)
add_clang_library(clangFormat
AffectedRangeManager.cpp
BreakableToken.cpp
+ Comments.cpp
ContinuationIndenter.cpp
Format.cpp
FormatToken.cpp
diff --git a/lib/Format/Comments.cpp b/lib/Format/Comments.cpp
new file mode 100644
index 000000000000..1b27f5b30a60
--- /dev/null
+++ b/lib/Format/Comments.cpp
@@ -0,0 +1,36 @@
+//===--- Comments.cpp - Comment Manipulation -------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Implements comment manipulation.
+///
+//===----------------------------------------------------------------------===//
+
+#include "Comments.h"
+
+namespace clang {
+namespace format {
+
+StringRef getLineCommentIndentPrefix(StringRef Comment) {
+ static const char *const KnownPrefixes[] = {"///", "//", "//!"};
+ StringRef LongestPrefix;
+ for (StringRef KnownPrefix : KnownPrefixes) {
+ if (Comment.startswith(KnownPrefix)) {
+ size_t PrefixLength = KnownPrefix.size();
+ while (PrefixLength < Comment.size() && Comment[PrefixLength] == ' ')
+ ++PrefixLength;
+ if (PrefixLength > LongestPrefix.size())
+ LongestPrefix = Comment.substr(0, PrefixLength);
+ }
+ }
+ return LongestPrefix;
+}
+
+} // namespace format
+} // namespace clang
diff --git a/lib/Format/Comments.h b/lib/Format/Comments.h
new file mode 100644
index 000000000000..59f0596361a5
--- /dev/null
+++ b/lib/Format/Comments.h
@@ -0,0 +1,33 @@
+//===--- Comments.cpp - Comment manipulation -----------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Declares comment manipulation functionality.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_FORMAT_COMMENTS_H
+#define LLVM_CLANG_LIB_FORMAT_COMMENTS_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace clang {
+namespace format {
+
+/// \brief Returns the comment prefix of the line comment \p Comment.
+///
+/// The comment prefix consists of a leading known prefix, like "//" or "///",
+/// together with the following whitespace.
+StringRef getLineCommentIndentPrefix(StringRef Comment);
+
+} // namespace format
+} // namespace clang
+
+#endif
diff --git a/lib/Format/ContinuationIndenter.cpp b/lib/Format/ContinuationIndenter.cpp
index 322969e4bb71..bf075ab6d53e 100644
--- a/lib/Format/ContinuationIndenter.cpp
+++ b/lib/Format/ContinuationIndenter.cpp
@@ -19,7 +19,6 @@
#include "clang/Basic/SourceManager.h"
#include "clang/Format/Format.h"
#include "llvm/Support/Debug.h"
-#include <string>
#define DEBUG_TYPE "format-formatter"
@@ -178,6 +177,9 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
((Style.AllowShortFunctionsOnASingleLine != FormatStyle::SFS_All) ||
Style.BreakConstructorInitializersBeforeComma || Style.ColumnLimit != 0))
return true;
+ 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 &&
State.Stack.back().BreakBeforeParameter)
return true;
@@ -458,7 +460,7 @@ unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State,
Penalty += State.NextToken->SplitPenalty;
// Breaking before the first "<<" is generally not desirable if the LHS is
- // short. Also always add the penalty if the LHS is split over mutliple lines
+ // short. Also always add the penalty if the LHS is split over multiple lines
// to avoid unnecessary line breaks that just work around this penalty.
if (NextNonComment->is(tok::lessless) &&
State.Stack.back().FirstLessLess == 0 &&
@@ -521,7 +523,8 @@ unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State,
Style.ContinuationIndentWidth;
}
- if ((Previous.isOneOf(tok::comma, tok::semi) &&
+ if ((PreviousNonComment &&
+ PreviousNonComment->isOneOf(tok::comma, tok::semi) &&
!State.Stack.back().AvoidBinPacking) ||
Previous.is(TT_BinaryOperator))
State.Stack.back().BreakBeforeParameter = false;
@@ -557,6 +560,7 @@ unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State,
// and we need to avoid bin packing there.
bool NestedBlockSpecialCase =
Style.Language != FormatStyle::LK_Cpp &&
+ Style.Language != FormatStyle::LK_ObjC &&
Current.is(tok::r_brace) && State.Stack.size() > 1 &&
State.Stack[State.Stack.size() - 2].NestedBlockInlined;
if (!NestedBlockSpecialCase)
@@ -672,6 +676,8 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
return State.Stack.back().ColonPos - NextNonComment->ColumnWidth;
return State.Stack.back().Indent;
}
+ if (NextNonComment->is(tok::colon) && NextNonComment->is(TT_ObjCMethodExpr))
+ return State.Stack.back().ColonPos;
if (NextNonComment->is(TT_ArraySubscriptLSquare)) {
if (State.Stack.back().StartOfArraySubscripts != 0)
return State.Stack.back().StartOfArraySubscripts;
@@ -861,7 +867,7 @@ void ContinuationIndenter::moveStatePastFakeLParens(LineState &State,
// Exclude relational operators, as there, it is always more desirable to
// have the LHS 'left' of the RHS.
if (Previous && Previous->getPrecedence() != prec::Assignment &&
- Previous->isOneOf(TT_BinaryOperator, TT_ConditionalExpr) &&
+ Previous->isOneOf(TT_BinaryOperator, TT_ConditionalExpr, tok::comma) &&
Previous->getPrecedence() != prec::Relational) {
bool BreakBeforeOperator =
Previous->is(tok::lessless) ||
diff --git a/lib/Format/Encoding.h b/lib/Format/Encoding.h
index 148f7fd0e91b..3339597b4edd 100644
--- a/lib/Format/Encoding.h
+++ b/lib/Format/Encoding.h
@@ -33,32 +33,13 @@ enum Encoding {
/// \brief 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 UTF8 *Ptr = reinterpret_cast<const UTF8 *>(Text.begin());
- const UTF8 *BufEnd = reinterpret_cast<const UTF8 *>(Text.end());
- if (::isLegalUTF8String(&Ptr, BufEnd))
+ const llvm::UTF8 *Ptr = reinterpret_cast<const llvm::UTF8 *>(Text.begin());
+ const llvm::UTF8 *BufEnd = reinterpret_cast<const llvm::UTF8 *>(Text.end());
+ if (llvm::isLegalUTF8String(&Ptr, BufEnd))
return Encoding_UTF8;
return Encoding_Unknown;
}
-inline unsigned getCodePointCountUTF8(StringRef Text) {
- unsigned CodePoints = 0;
- for (size_t i = 0, e = Text.size(); i < e; i += getNumBytesForUTF8(Text[i])) {
- ++CodePoints;
- }
- return CodePoints;
-}
-
-/// \brief Gets the number of code points in the Text using the specified
-/// Encoding.
-inline unsigned getCodePointCount(StringRef Text, Encoding Encoding) {
- switch (Encoding) {
- case Encoding_UTF8:
- return getCodePointCountUTF8(Text);
- default:
- return Text.size();
- }
-}
-
/// \brief 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.
@@ -97,7 +78,7 @@ inline unsigned columnWidthWithTabs(StringRef Text, unsigned StartColumn,
inline unsigned getCodePointNumBytes(char FirstChar, Encoding Encoding) {
switch (Encoding) {
case Encoding_UTF8:
- return getNumBytesForUTF8(FirstChar);
+ return llvm::getNumBytesForUTF8(FirstChar);
default:
return 1;
}
@@ -136,7 +117,7 @@ inline unsigned getEscapeSequenceLength(StringRef Text) {
++I;
return I;
}
- return 1 + getNumBytesForUTF8(Text[1]);
+ return 1 + llvm::getNumBytesForUTF8(Text[1]);
}
}
diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp
index 32d6bb855ad6..70b90d6fa14e 100644
--- a/lib/Format/Format.cpp
+++ b/lib/Format/Format.cpp
@@ -36,7 +36,6 @@
#include "llvm/Support/YAMLTraits.h"
#include <algorithm>
#include <memory>
-#include <queue>
#include <string>
#define DEBUG_TYPE "format-formatter"
@@ -53,6 +52,7 @@ template <> struct ScalarEnumerationTraits<FormatStyle::LanguageKind> {
IO.enumCase(Value, "Cpp", FormatStyle::LK_Cpp);
IO.enumCase(Value, "Java", FormatStyle::LK_Java);
IO.enumCase(Value, "JavaScript", FormatStyle::LK_JavaScript);
+ IO.enumCase(Value, "ObjC", FormatStyle::LK_ObjC);
IO.enumCase(Value, "Proto", FormatStyle::LK_Proto);
IO.enumCase(Value, "TableGen", FormatStyle::LK_TableGen);
}
@@ -339,6 +339,7 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("ReflowComments", Style.ReflowComments);
IO.mapOptional("SortIncludes", Style.SortIncludes);
IO.mapOptional("SpaceAfterCStyleCast", Style.SpaceAfterCStyleCast);
+ IO.mapOptional("SpaceAfterTemplateKeyword", Style.SpaceAfterTemplateKeyword);
IO.mapOptional("SpaceBeforeAssignmentOperators",
Style.SpaceBeforeAssignmentOperators);
IO.mapOptional("SpaceBeforeParens", Style.SpaceBeforeParens);
@@ -420,7 +421,7 @@ std::error_code make_error_code(ParseError e) {
return std::error_code(static_cast<int>(e), getParseCategory());
}
-const char *ParseErrorCategory::name() const LLVM_NOEXCEPT {
+const char *ParseErrorCategory::name() const noexcept {
return "clang-format.parse_error";
}
@@ -553,6 +554,7 @@ FormatStyle getLLVMStyle() {
LLVMStyle.SpacesInContainerLiterals = true;
LLVMStyle.SpacesInCStyleCastParentheses = false;
LLVMStyle.SpaceAfterCStyleCast = false;
+ LLVMStyle.SpaceAfterTemplateKeyword = true;
LLVMStyle.SpaceBeforeParens = FormatStyle::SBPO_ControlStatements;
LLVMStyle.SpaceBeforeAssignmentOperators = true;
LLVMStyle.SpacesInAngles = false;
@@ -609,10 +611,11 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
} else if (Language == FormatStyle::LK_JavaScript) {
GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak;
GoogleStyle.AlignOperands = false;
- GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
+ GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
GoogleStyle.BreakBeforeTernaryOperators = false;
- GoogleStyle.CommentPragmas = "@(export|requirecss|return|see|visibility) ";
+ GoogleStyle.CommentPragmas =
+ "(taze:|@(export|requirecss|return|returns|see|visibility)) ";
GoogleStyle.MaxEmptyLinesToKeep = 3;
GoogleStyle.NamespaceIndentation = FormatStyle::NI_All;
GoogleStyle.SpacesInContainerLiterals = false;
@@ -621,6 +624,8 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
} else if (Language == FormatStyle::LK_Proto) {
GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
GoogleStyle.SpacesInContainerLiterals = false;
+ } else if (Language == FormatStyle::LK_ObjC) {
+ GoogleStyle.ColumnLimit = 100;
}
return GoogleStyle;
@@ -650,10 +655,12 @@ FormatStyle getMozillaStyle() {
MozillaStyle.AllowAllParametersOfDeclarationOnNextLine = false;
MozillaStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
MozillaStyle.AlwaysBreakAfterReturnType =
- FormatStyle::RTBS_TopLevelDefinitions;
+ FormatStyle::RTBS_TopLevel;
MozillaStyle.AlwaysBreakAfterDefinitionReturnType =
FormatStyle::DRTBS_TopLevel;
MozillaStyle.AlwaysBreakTemplateDeclarations = true;
+ MozillaStyle.BinPackParameters = false;
+ MozillaStyle.BinPackArguments = false;
MozillaStyle.BreakBeforeBraces = FormatStyle::BS_Mozilla;
MozillaStyle.BreakConstructorInitializersBeforeComma = true;
MozillaStyle.ConstructorInitializerIndentWidth = 2;
@@ -664,6 +671,7 @@ FormatStyle getMozillaStyle() {
MozillaStyle.ObjCSpaceBeforeProtocolList = false;
MozillaStyle.PenaltyReturnTypeOnItsOwnLine = 200;
MozillaStyle.PointerAlignment = FormatStyle::PAS_Left;
+ MozillaStyle.SpaceAfterTemplateKeyword = false;
return MozillaStyle;
}
@@ -683,7 +691,6 @@ FormatStyle getWebKitStyle() {
Style.ObjCBlockIndentWidth = 4;
Style.ObjCSpaceAfterProperty = true;
Style.PointerAlignment = FormatStyle::PAS_Left;
- Style.Standard = FormatStyle::LS_Cpp03;
return Style;
}
@@ -791,46 +798,25 @@ std::string configurationAsText(const FormatStyle &Style) {
namespace {
-class Formatter : public TokenAnalyzer {
+class JavaScriptRequoter : public TokenAnalyzer {
public:
- Formatter(const Environment &Env, const FormatStyle &Style,
- bool *IncompleteFormat)
- : TokenAnalyzer(Env, Style), IncompleteFormat(IncompleteFormat) {}
+ JavaScriptRequoter(const Environment &Env, const FormatStyle &Style)
+ : TokenAnalyzer(Env, Style) {}
tooling::Replacements
analyze(TokenAnnotator &Annotator,
SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
- FormatTokenLexer &Tokens, tooling::Replacements &Result) override {
- deriveLocalStyle(AnnotatedLines);
+ FormatTokenLexer &Tokens) override {
AffectedRangeMgr.computeAffectedLines(AnnotatedLines.begin(),
AnnotatedLines.end());
-
- if (Style.Language == FormatStyle::LK_JavaScript &&
- Style.JavaScriptQuotes != FormatStyle::JSQS_Leave)
- requoteJSStringLiteral(AnnotatedLines, Result);
-
- for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
- Annotator.calculateFormattingInformation(*AnnotatedLines[i]);
- }
-
- Annotator.setCommentLineLevels(AnnotatedLines);
-
- WhitespaceManager Whitespaces(
- Env.getSourceManager(), Style,
- inputUsesCRLF(Env.getSourceManager().getBufferData(Env.getFileID())));
- ContinuationIndenter Indenter(Style, Tokens.getKeywords(),
- Env.getSourceManager(), Whitespaces, Encoding,
- BinPackInconclusiveFunctions);
- UnwrappedLineFormatter(&Indenter, &Whitespaces, Style, Tokens.getKeywords(),
- IncompleteFormat)
- .format(AnnotatedLines);
- return Whitespaces.generateReplacements();
+ tooling::Replacements Result;
+ requoteJSStringLiteral(AnnotatedLines, Result);
+ return Result;
}
private:
- // If the last token is a double/single-quoted string literal, generates a
- // replacement with a single/double quoted string literal, re-escaping the
- // contents in the process.
+ // Replaces double/single-quoted string literal as appropriate, re-escaping
+ // the contents in the process.
void requoteJSStringLiteral(SmallVectorImpl<AnnotatedLine *> &Lines,
tooling::Replacements &Result) {
for (AnnotatedLine *Line : Lines) {
@@ -842,8 +828,7 @@ private:
StringRef Input = FormatTok->TokenText;
if (FormatTok->Finalized || !FormatTok->isStringLiteral() ||
// NB: testing for not starting with a double quote to avoid
- // breaking
- // `template strings`.
+ // breaking `template strings`.
(Style.JavaScriptQuotes == FormatStyle::JSQS_Single &&
!Input.startswith("\"")) ||
(Style.JavaScriptQuotes == FormatStyle::JSQS_Double &&
@@ -855,15 +840,20 @@ private:
SourceLocation Start = FormatTok->Tok.getLocation();
auto Replace = [&](SourceLocation Start, unsigned Length,
StringRef ReplacementText) {
- Result.insert(tooling::Replacement(Env.getSourceManager(), Start,
- Length, ReplacementText));
+ auto Err = Result.add(tooling::Replacement(
+ Env.getSourceManager(), Start, Length, ReplacementText));
+ // FIXME: handle error. For now, print error message and skip the
+ // replacement for release version.
+ if (Err) {
+ llvm::errs() << llvm::toString(std::move(Err)) << "\n";
+ assert(false);
+ }
};
Replace(Start, 1, IsSingle ? "'" : "\"");
Replace(FormatTok->Tok.getEndLoc().getLocWithOffset(-1), 1,
IsSingle ? "'" : "\"");
// Escape internal quotes.
- size_t ColumnWidth = FormatTok->TokenText.size();
bool Escaped = false;
for (size_t i = 1; i < Input.size() - 1; i++) {
switch (Input[i]) {
@@ -873,7 +863,6 @@ private:
(!IsSingle && Input[i + 1] == '\''))) {
// Remove this \, it's escaping a " or ' that no longer needs
// escaping
- ColumnWidth--;
Replace(Start.getLocWithOffset(i), 1, "");
continue;
}
@@ -884,7 +873,6 @@ private:
if (!Escaped && IsSingle == (Input[i] == '\'')) {
// Escape the quote.
Replace(Start.getLocWithOffset(i), 0, "\\");
- ColumnWidth++;
}
Escaped = false;
break;
@@ -893,16 +881,46 @@ private:
break;
}
}
-
- // For formatting, count the number of non-escaped single quotes in them
- // and adjust ColumnWidth to take the added escapes into account.
- // FIXME(martinprobst): this might conflict with code breaking a long
- // string literal (which clang-format doesn't do, yet). For that to
- // work, this code would have to modify TokenText directly.
- FormatTok->ColumnWidth = ColumnWidth;
}
}
}
+};
+
+class Formatter : public TokenAnalyzer {
+public:
+ Formatter(const Environment &Env, const FormatStyle &Style,
+ bool *IncompleteFormat)
+ : TokenAnalyzer(Env, Style), IncompleteFormat(IncompleteFormat) {}
+
+ tooling::Replacements
+ analyze(TokenAnnotator &Annotator,
+ SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
+ FormatTokenLexer &Tokens) override {
+ tooling::Replacements Result;
+ deriveLocalStyle(AnnotatedLines);
+ AffectedRangeMgr.computeAffectedLines(AnnotatedLines.begin(),
+ AnnotatedLines.end());
+ for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
+ Annotator.calculateFormattingInformation(*AnnotatedLines[i]);
+ }
+ Annotator.setCommentLineLevels(AnnotatedLines);
+
+ WhitespaceManager Whitespaces(
+ Env.getSourceManager(), Style,
+ inputUsesCRLF(Env.getSourceManager().getBufferData(Env.getFileID())));
+ ContinuationIndenter Indenter(Style, Tokens.getKeywords(),
+ Env.getSourceManager(), Whitespaces, Encoding,
+ BinPackInconclusiveFunctions);
+ UnwrappedLineFormatter(&Indenter, &Whitespaces, Style, Tokens.getKeywords(),
+ IncompleteFormat)
+ .format(AnnotatedLines);
+ for (const auto &R : Whitespaces.generateReplacements())
+ if (Result.add(R))
+ return Result;
+ return Result;
+ }
+
+private:
static bool inputUsesCRLF(StringRef Text) {
return Text.count('\r') * 2 > Text.count('\n');
@@ -991,7 +1009,7 @@ public:
tooling::Replacements
analyze(TokenAnnotator &Annotator,
SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
- FormatTokenLexer &Tokens, tooling::Replacements &Result) override {
+ FormatTokenLexer &Tokens) override {
// FIXME: in the current implementation the granularity of affected range
// is an annotated line. However, this is not sufficient. Furthermore,
// redundant code introduced by replacements does not necessarily
@@ -1008,8 +1026,11 @@ public:
if (Line->Affected) {
cleanupRight(Line->First, tok::comma, tok::comma);
cleanupRight(Line->First, TT_CtorInitializerColon, tok::comma);
+ cleanupRight(Line->First, tok::l_paren, tok::comma);
+ cleanupLeft(Line->First, tok::comma, tok::r_paren);
cleanupLeft(Line->First, TT_CtorInitializerComma, tok::l_brace);
cleanupLeft(Line->First, TT_CtorInitializerColon, tok::l_brace);
+ cleanupLeft(Line->First, TT_CtorInitializerColon, tok::equal);
}
}
@@ -1027,11 +1048,12 @@ private:
// Iterate through all lines and remove any empty (nested) namespaces.
void checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
+ std::set<unsigned> DeletedLines;
for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
auto &Line = *AnnotatedLines[i];
if (Line.startsWith(tok::kw_namespace) ||
Line.startsWith(tok::kw_inline, tok::kw_namespace)) {
- checkEmptyNamespace(AnnotatedLines, i, i);
+ checkEmptyNamespace(AnnotatedLines, i, i, DeletedLines);
}
}
@@ -1049,7 +1071,8 @@ private:
// sets \p NewLine to the last line checked.
// Returns true if the current namespace is empty.
bool checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
- unsigned CurrentLine, unsigned &NewLine) {
+ unsigned CurrentLine, unsigned &NewLine,
+ std::set<unsigned> &DeletedLines) {
unsigned InitLine = CurrentLine, End = AnnotatedLines.size();
if (Style.BraceWrapping.AfterNamespace) {
// If the left brace is in a new line, we should consume it first so that
@@ -1069,7 +1092,8 @@ private:
if (AnnotatedLines[CurrentLine]->startsWith(tok::kw_namespace) ||
AnnotatedLines[CurrentLine]->startsWith(tok::kw_inline,
tok::kw_namespace)) {
- if (!checkEmptyNamespace(AnnotatedLines, CurrentLine, NewLine))
+ if (!checkEmptyNamespace(AnnotatedLines, CurrentLine, NewLine,
+ DeletedLines))
return false;
CurrentLine = NewLine;
continue;
@@ -1121,6 +1145,8 @@ private:
break;
if (Left->is(LK) && Right->is(RK)) {
deleteToken(DeleteLeft ? Left : Right);
+ for (auto *Tok = Left->Next; Tok && Tok != Right; Tok = Tok->Next)
+ deleteToken(Tok);
// If the right token is deleted, we should keep the left token
// unchanged and pair it with the new right token.
if (!DeleteLeft)
@@ -1164,7 +1190,14 @@ private:
}
auto SR = CharSourceRange::getCharRange(Tokens[St]->Tok.getLocation(),
Tokens[End]->Tok.getEndLoc());
- Fixes.insert(tooling::Replacement(Env.getSourceManager(), SR, ""));
+ auto Err =
+ Fixes.add(tooling::Replacement(Env.getSourceManager(), SR, ""));
+ // FIXME: better error handling. for now just print error message and skip
+ // for the release version.
+ if (Err) {
+ llvm::errs() << llvm::toString(std::move(Err)) << "\n";
+ assert(false && "Fixes must not conflict!");
+ }
Idx = End + 1;
}
@@ -1186,8 +1219,6 @@ private:
// Tokens to be deleted.
std::set<FormatToken *, FormatTokenLess> DeletedTokens;
- // The line numbers of lines to be deleted.
- std::set<unsigned> DeletedLines;
};
struct IncludeDirective {
@@ -1210,15 +1241,50 @@ static bool affectsRange(ArrayRef<tooling::Range> Ranges, unsigned Start,
return false;
}
-// Sorts a block of includes given by 'Includes' alphabetically adding the
-// necessary replacement to 'Replaces'. 'Includes' must be in strict source
-// order.
+// Returns a pair (Index, OffsetToEOL) describing the position of the cursor
+// before sorting/deduplicating. Index is the index of the include under the
+// cursor in the original set of includes. If this include has duplicates, it is
+// the index of the first of the duplicates as the others are going to be
+// removed. OffsetToEOL describes the cursor's position relative to the end of
+// its current line.
+// If `Cursor` is not on any #include, `Index` will be UINT_MAX.
+static std::pair<unsigned, unsigned>
+FindCursorIndex(const SmallVectorImpl<IncludeDirective> &Includes,
+ const SmallVectorImpl<unsigned> &Indices, unsigned Cursor) {
+ unsigned CursorIndex = UINT_MAX;
+ unsigned OffsetToEOL = 0;
+ for (int i = 0, e = Includes.size(); i != e; ++i) {
+ unsigned Start = Includes[Indices[i]].Offset;
+ unsigned End = Start + Includes[Indices[i]].Text.size();
+ if (!(Cursor >= Start && Cursor < End))
+ continue;
+ CursorIndex = Indices[i];
+ OffsetToEOL = End - Cursor;
+ // Put the cursor on the only remaining #include among the duplicate
+ // #includes.
+ while (--i >= 0 && Includes[CursorIndex].Text == Includes[Indices[i]].Text)
+ CursorIndex = i;
+ break;
+ }
+ return std::make_pair(CursorIndex, OffsetToEOL);
+}
+
+// Sorts and deduplicate a block of includes given by 'Includes' alphabetically
+// adding the necessary replacement to 'Replaces'. 'Includes' must be in strict
+// source order.
+// #include directives with the same text will be deduplicated, and only the
+// first #include in the duplicate #includes remains. If the `Cursor` is
+// provided and put on a deleted #include, it will be moved to the remaining
+// #include in the duplicate #includes.
static void sortCppIncludes(const FormatStyle &Style,
- const SmallVectorImpl<IncludeDirective> &Includes,
- ArrayRef<tooling::Range> Ranges, StringRef FileName,
- tooling::Replacements &Replaces, unsigned *Cursor) {
- if (!affectsRange(Ranges, Includes.front().Offset,
- Includes.back().Offset + Includes.back().Text.size()))
+ const SmallVectorImpl<IncludeDirective> &Includes,
+ ArrayRef<tooling::Range> Ranges, StringRef FileName,
+ tooling::Replacements &Replaces, unsigned *Cursor) {
+ unsigned IncludesBeginOffset = Includes.front().Offset;
+ unsigned IncludesEndOffset =
+ Includes.back().Offset + Includes.back().Text.size();
+ unsigned IncludesBlockSize = IncludesEndOffset - IncludesBeginOffset;
+ if (!affectsRange(Ranges, IncludesBeginOffset, IncludesEndOffset))
return;
SmallVector<unsigned, 16> Indices;
for (unsigned i = 0, e = Includes.size(); i != e; ++i)
@@ -1228,37 +1294,45 @@ static void sortCppIncludes(const FormatStyle &Style,
return std::tie(Includes[LHSI].Category, Includes[LHSI].Filename) <
std::tie(Includes[RHSI].Category, Includes[RHSI].Filename);
});
+ // The index of the include on which the cursor will be put after
+ // sorting/deduplicating.
+ unsigned CursorIndex;
+ // The offset from cursor to the end of line.
+ unsigned CursorToEOLOffset;
+ if (Cursor)
+ std::tie(CursorIndex, CursorToEOLOffset) =
+ FindCursorIndex(Includes, Indices, *Cursor);
+
+ // Deduplicate #includes.
+ Indices.erase(std::unique(Indices.begin(), Indices.end(),
+ [&](unsigned LHSI, unsigned RHSI) {
+ return Includes[LHSI].Text == Includes[RHSI].Text;
+ }),
+ Indices.end());
// If the #includes are out of order, we generate a single replacement fixing
// the entire block. Otherwise, no replacement is generated.
- if (std::is_sorted(Indices.begin(), Indices.end()))
+ if (Indices.size() == Includes.size() &&
+ std::is_sorted(Indices.begin(), Indices.end()))
return;
std::string result;
- bool CursorMoved = false;
for (unsigned Index : Indices) {
if (!result.empty())
result += "\n";
result += Includes[Index].Text;
-
- if (Cursor && !CursorMoved) {
- unsigned Start = Includes[Index].Offset;
- unsigned End = Start + Includes[Index].Text.size();
- if (*Cursor >= Start && *Cursor < End) {
- *Cursor = Includes.front().Offset + result.size() + *Cursor - End;
- CursorMoved = true;
- }
- }
+ if (Cursor && CursorIndex == Index)
+ *Cursor = IncludesBeginOffset + result.size() - CursorToEOLOffset;
}
- // Sorting #includes shouldn't change their total number of characters.
- // This would otherwise mess up 'Ranges'.
- assert(result.size() ==
- Includes.back().Offset + Includes.back().Text.size() -
- Includes.front().Offset);
-
- Replaces.insert(tooling::Replacement(FileName, Includes.front().Offset,
- result.size(), result));
+ auto Err = Replaces.add(tooling::Replacement(
+ FileName, Includes.front().Offset, IncludesBlockSize, result));
+ // FIXME: better error handling. For now, just skip the replacement for the
+ // release version.
+ if (Err) {
+ llvm::errs() << llvm::toString(std::move(Err)) << "\n";
+ assert(false);
+ }
}
namespace {
@@ -1403,14 +1477,13 @@ processReplacements(T ProcessFunc, StringRef Code,
auto NewCode = applyAllReplacements(Code, Replaces);
if (!NewCode)
return NewCode.takeError();
- std::vector<tooling::Range> ChangedRanges =
- tooling::calculateChangedRanges(Replaces);
+ std::vector<tooling::Range> ChangedRanges = Replaces.getAffectedRanges();
StringRef FileName = Replaces.begin()->getFilePath();
tooling::Replacements FormatReplaces =
ProcessFunc(Style, *NewCode, ChangedRanges, FileName);
- return mergeReplacements(Replaces, FormatReplaces);
+ return Replaces.merge(FormatReplaces);
}
llvm::Expected<tooling::Replacements>
@@ -1441,14 +1514,31 @@ formatReplacements(StringRef Code, const tooling::Replacements &Replaces,
namespace {
inline bool isHeaderInsertion(const tooling::Replacement &Replace) {
- return Replace.getOffset() == UINT_MAX &&
+ return Replace.getOffset() == UINT_MAX && Replace.getLength() == 0 &&
llvm::Regex(IncludeRegexPattern).match(Replace.getReplacementText());
}
-void skipComments(Lexer &Lex, Token &Tok) {
- while (Tok.is(tok::comment))
- if (Lex.LexFromRawLexer(Tok))
- return;
+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,
+ std::function<unsigned(const SourceManager &, Lexer &, Token &)>
+ GetOffsetAfterSequense) {
+ 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 GetOffsetAfterSequense(SourceMgr, Lex, Tok);
}
// Check if a sequence of tokens is like "#<Name> <raw_identifier>". If it is,
@@ -1464,32 +1554,90 @@ bool checkAndConsumeDirectiveWithName(Lexer &Lex, StringRef Name, Token &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) {
- 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);
- skipComments(Lex, Tok);
- unsigned AfterComments = SourceMgr.getFileOffset(Tok.getLocation());
- if (checkAndConsumeDirectiveWithName(Lex, "ifndef", Tok)) {
- skipComments(Lex, Tok);
- if (checkAndConsumeDirectiveWithName(Lex, "define", Tok))
- return SourceMgr.getFileOffset(Tok.getLocation());
+ 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 AfterComments;
+ 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: we also need to insert a '\n' at the end of the code if we have an
-// insertion with offset Code.size(), and there is no '\n' at the end of the
-// code.
-// FIXME: do not insert headers into conditional #include blocks, e.g. #includes
-// surrounded by compile condition "#if...".
// FIXME: insert empty lines between newly created blocks.
tooling::Replacements
fixCppIncludeInsertions(StringRef Code, const tooling::Replacements &Replaces,
@@ -1498,20 +1646,25 @@ fixCppIncludeInsertions(StringRef Code, const tooling::Replacements &Replaces,
return Replaces;
tooling::Replacements HeaderInsertions;
+ std::set<llvm::StringRef> HeadersToDelete;
+ tooling::Replacements Result;
for (const auto &R : Replaces) {
- if (isHeaderInsertion(R))
- HeaderInsertions.insert(R);
- else if (R.getOffset() == UINT_MAX)
+ if (isHeaderInsertion(R)) {
+ // Replacements from \p Replaces must be conflict-free already, so we can
+ // simply consume the error.
+ llvm::consumeError(HeaderInsertions.add(R));
+ } else if (isHeaderDeletion(R)) {
+ HeadersToDelete.insert(R.getReplacementText());
+ } else if (R.getOffset() == UINT_MAX) {
llvm::errs() << "Insertions other than header #include insertion are "
"not supported! "
<< R.getReplacementText() << "\n";
+ } else {
+ llvm::consumeError(Result.add(R));
+ }
}
- if (HeaderInsertions.empty())
+ if (HeaderInsertions.empty() && HeadersToDelete.empty())
return Replaces;
- tooling::Replacements Result;
- std::set_difference(Replaces.begin(), Replaces.end(),
- HeaderInsertions.begin(), HeaderInsertions.end(),
- std::inserter(Result, Result.begin()));
llvm::Regex IncludeRegex(IncludeRegexPattern);
llvm::Regex DefineRegex(R"(^[\t\ ]*#[\t\ ]*define[\t\ ]*[^\\]*$)");
@@ -1532,6 +1685,10 @@ fixCppIncludeInsertions(StringRef Code, const tooling::Replacements &Replaces,
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;
@@ -1540,13 +1697,30 @@ fixCppIncludeInsertions(StringRef Code, const tooling::Replacements &Replaces,
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);
- int Category = Categories.getIncludePriority(
- IncludeName, /*CheckMainHeader=*/FirstIncludeOffset < 0);
- CategoryEndOffsets[Category] = NextLineOffset;
- if (FirstIncludeOffset < 0)
- FirstIncludeOffset = Offset;
+ // 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";
+ }
+ }
}
Offset = NextLineOffset;
}
@@ -1570,6 +1744,7 @@ fixCppIncludeInsertions(StringRef Code, const tooling::Replacements &Replaces,
if (CategoryEndOffsets.find(*I) == CategoryEndOffsets.end())
CategoryEndOffsets[*I] = CategoryEndOffsets[*std::prev(I)];
+ bool NeedNewLineAtEnd = !Code.empty() && Code.back() != '\n';
for (const auto &R : HeaderInsertions) {
auto IncludeDirective = R.getReplacementText();
bool Matched = IncludeRegex.match(IncludeDirective, &Matches);
@@ -1588,7 +1763,20 @@ fixCppIncludeInsertions(StringRef Code, const tooling::Replacements &Replaces,
std::string NewInclude = !IncludeDirective.endswith("\n")
? (IncludeDirective + "\n").str()
: IncludeDirective.str();
- Result.insert(tooling::Replacement(FileName, Offset, 0, NewInclude));
+ // 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));
+ }
}
return Result;
}
@@ -1611,18 +1799,6 @@ cleanupAroundReplacements(StringRef Code, const tooling::Replacements &Replaces,
return processReplacements(Cleanup, Code, NewReplaces, Style);
}
-tooling::Replacements reformat(const FormatStyle &Style, SourceManager &SM,
- FileID ID, ArrayRef<CharSourceRange> Ranges,
- bool *IncompleteFormat) {
- FormatStyle Expanded = expandPresets(Style);
- if (Expanded.DisableFormat)
- return tooling::Replacements();
-
- Environment Env(SM, ID, Ranges);
- Formatter Format(Env, Expanded, IncompleteFormat);
- return Format.process();
-}
-
tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
ArrayRef<tooling::Range> Ranges,
StringRef FileName, bool *IncompleteFormat) {
@@ -1630,19 +1806,28 @@ tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
if (Expanded.DisableFormat)
return tooling::Replacements();
- std::unique_ptr<Environment> Env =
- Environment::CreateVirtualEnvironment(Code, FileName, Ranges);
+ auto Env = Environment::CreateVirtualEnvironment(Code, FileName, Ranges);
+
+ if (Style.Language == FormatStyle::LK_JavaScript &&
+ Style.JavaScriptQuotes != FormatStyle::JSQS_Leave) {
+ JavaScriptRequoter Requoter(*Env, Expanded);
+ tooling::Replacements Requotes = Requoter.process();
+ if (!Requotes.empty()) {
+ auto NewCode = applyAllReplacements(Code, Requotes);
+ if (NewCode) {
+ auto NewEnv = Environment::CreateVirtualEnvironment(
+ *NewCode, FileName,
+ tooling::calculateRangesAfterReplacements(Requotes, Ranges));
+ Formatter Format(*NewEnv, Expanded, IncompleteFormat);
+ return Requotes.merge(Format.process());
+ }
+ }
+ }
+
Formatter Format(*Env, Expanded, IncompleteFormat);
return Format.process();
}
-tooling::Replacements cleanup(const FormatStyle &Style, SourceManager &SM,
- FileID ID, ArrayRef<CharSourceRange> Ranges) {
- Environment Env(SM, ID, Ranges);
- Cleaner Clean(Env, Style);
- return Clean.process();
-}
-
tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code,
ArrayRef<tooling::Range> Ranges,
StringRef FileName) {
@@ -1684,6 +1869,8 @@ static FormatStyle::LanguageKind getLanguageByFileName(StringRef FileName) {
return FormatStyle::LK_Java;
if (FileName.endswith_lower(".js") || FileName.endswith_lower(".ts"))
return FormatStyle::LK_JavaScript; // JavaScript or TypeScript.
+ if (FileName.endswith(".m") || FileName.endswith(".mm"))
+ return FormatStyle::LK_ObjC;
if (FileName.endswith_lower(".proto") ||
FileName.endswith_lower(".protodevel"))
return FormatStyle::LK_Proto;
@@ -1693,12 +1880,21 @@ static FormatStyle::LanguageKind getLanguageByFileName(StringRef FileName) {
}
FormatStyle getStyle(StringRef StyleName, StringRef FileName,
- StringRef FallbackStyle, vfs::FileSystem *FS) {
+ StringRef FallbackStyle, StringRef Code,
+ vfs::FileSystem *FS) {
if (!FS) {
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+ (")))
+ Style.Language = FormatStyle::LK_ObjC;
+
if (!getPredefinedStyle(FallbackStyle, Style.Language, &Style)) {
llvm::errs() << "Invalid fallback style \"" << FallbackStyle
<< "\" using LLVM style\n";
@@ -1724,7 +1920,11 @@ FormatStyle getStyle(StringRef StyleName, StringRef FileName,
// Look for .clang-format/_clang-format file in the file's parent directories.
SmallString<128> UnsuitableConfigFiles;
SmallString<128> Path(FileName);
- llvm::sys::fs::make_absolute(Path);
+ if (std::error_code EC = FS->makeAbsolute(Path)) {
+ llvm::errs() << EC.message() << "\n";
+ return Style;
+ }
+
for (StringRef Directory = Path; !Directory.empty();
Directory = llvm::sys::path::parent_path(Directory)) {
diff --git a/lib/Format/FormatToken.cpp b/lib/Format/FormatToken.cpp
index 2ae4ddcfd08a..ba5bf03a6346 100644
--- a/lib/Format/FormatToken.cpp
+++ b/lib/Format/FormatToken.cpp
@@ -13,9 +13,8 @@
///
//===----------------------------------------------------------------------===//
-#include "ContinuationIndenter.h"
#include "FormatToken.h"
-#include "clang/Format/Format.h"
+#include "ContinuationIndenter.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Debug.h"
#include <climits>
@@ -78,6 +77,9 @@ unsigned CommaSeparatedList::formatAfterToken(LineState &State,
if (State.NextToken == nullptr || !State.NextToken->Previous)
return 0;
+ if (Formats.size() == 1)
+ return 0; // Handled by formatFromToken
+
// Ensure that we start on the opening brace.
const FormatToken *LBrace =
State.NextToken->Previous->getPreviousNonComment();
@@ -93,6 +95,7 @@ unsigned CommaSeparatedList::formatAfterToken(LineState &State,
// Find the best ColumnFormat, i.e. the best number of columns to use.
const ColumnFormat *Format = getColumnFormat(RemainingCodePoints);
+
// If no ColumnFormat can be used, the braced list would generally be
// bin-packed. Add a severe penalty to this so that column layouts are
// preferred if possible.
@@ -130,7 +133,9 @@ unsigned CommaSeparatedList::formatAfterToken(LineState &State,
unsigned CommaSeparatedList::formatFromToken(LineState &State,
ContinuationIndenter *Indenter,
bool DryRun) {
- if (HasNestedBracedList)
+ // Formatting with 1 Column isn't really a column layout, so we don't need the
+ // special logic here. We can just avoid bin packing any of the parameters.
+ if (Formats.size() == 1 || HasNestedBracedList)
State.Stack.back().AvoidBinPacking = true;
return 0;
}
@@ -274,7 +279,7 @@ void CommaSeparatedList::precomputeFormattingInfos(const FormatToken *Token) {
continue;
// Ignore layouts that are bound to violate the column limit.
- if (Format.TotalWidth > Style.ColumnLimit)
+ if (Format.TotalWidth > Style.ColumnLimit && Columns > 1)
continue;
Formats.push_back(Format);
@@ -288,7 +293,7 @@ CommaSeparatedList::getColumnFormat(unsigned RemainingCharacters) const {
I = Formats.rbegin(),
E = Formats.rend();
I != E; ++I) {
- if (I->TotalWidth <= RemainingCharacters) {
+ if (I->TotalWidth <= RemainingCharacters || I->Columns == 1) {
if (BestFormat && I->LineCount > BestFormat->LineCount)
break;
BestFormat = &*I;
diff --git a/lib/Format/FormatToken.h b/lib/Format/FormatToken.h
index 43b162513620..ea3bbe368d5b 100644
--- a/lib/Format/FormatToken.h
+++ b/lib/Format/FormatToken.h
@@ -396,6 +396,21 @@ struct FormatToken {
}
}
+ /// \brief 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))
+ return false;
+ StringRef Content = TokenText;
+ if (Content.startswith("\"") || Content.startswith("'"))
+ Content = Content.drop_front(1);
+ if (Content.endswith("\"") || Content.endswith("'"))
+ Content = Content.drop_back(1);
+ Content = Content.trim();
+ return Content.size() > 1 &&
+ (Content.back() == ':' || Content.back() == '=');
+ }
+
/// \brief Returns actual token start location without leading escaped
/// newlines and whitespace.
///
@@ -580,12 +595,14 @@ struct AdditionalKeywords {
kw_as = &IdentTable.get("as");
kw_async = &IdentTable.get("async");
kw_await = &IdentTable.get("await");
+ kw_declare = &IdentTable.get("declare");
kw_finally = &IdentTable.get("finally");
kw_from = &IdentTable.get("from");
kw_function = &IdentTable.get("function");
kw_import = &IdentTable.get("import");
kw_is = &IdentTable.get("is");
kw_let = &IdentTable.get("let");
+ kw_module = &IdentTable.get("module");
kw_type = &IdentTable.get("type");
kw_var = &IdentTable.get("var");
kw_yield = &IdentTable.get("yield");
@@ -632,12 +649,14 @@ struct AdditionalKeywords {
IdentifierInfo *kw_as;
IdentifierInfo *kw_async;
IdentifierInfo *kw_await;
+ IdentifierInfo *kw_declare;
IdentifierInfo *kw_finally;
IdentifierInfo *kw_from;
IdentifierInfo *kw_function;
IdentifierInfo *kw_import;
IdentifierInfo *kw_is;
IdentifierInfo *kw_let;
+ IdentifierInfo *kw_module;
IdentifierInfo *kw_type;
IdentifierInfo *kw_var;
IdentifierInfo *kw_yield;
diff --git a/lib/Format/FormatTokenLexer.cpp b/lib/Format/FormatTokenLexer.cpp
index 9778f84732d6..46a32a917dd9 100644
--- a/lib/Format/FormatTokenLexer.cpp
+++ b/lib/Format/FormatTokenLexer.cpp
@@ -26,12 +26,11 @@ namespace format {
FormatTokenLexer::FormatTokenLexer(const SourceManager &SourceMgr, FileID ID,
const FormatStyle &Style,
encoding::Encoding Encoding)
- : FormatTok(nullptr), IsFirstToken(true), GreaterStashed(false),
- LessStashed(false), Column(0), TrailingWhitespace(0),
- SourceMgr(SourceMgr), ID(ID), Style(Style),
- IdentTable(getFormattingLangOpts(Style)), Keywords(IdentTable),
- Encoding(Encoding), FirstInLineIndex(0), FormattingDisabled(false),
- MacroBlockBeginRegex(Style.MacroBlockBegin),
+ : FormatTok(nullptr), IsFirstToken(true), StateStack({LexerState::NORMAL}),
+ Column(0), TrailingWhitespace(0), SourceMgr(SourceMgr), ID(ID),
+ Style(Style), IdentTable(getFormattingLangOpts(Style)),
+ Keywords(IdentTable), Encoding(Encoding), FirstInLineIndex(0),
+ FormattingDisabled(false), MacroBlockBeginRegex(Style.MacroBlockBegin),
MacroBlockEndRegex(Style.MacroBlockEnd) {
Lex.reset(new Lexer(ID, SourceMgr.getBuffer(ID), SourceMgr,
getFormattingLangOpts(Style)));
@@ -49,7 +48,7 @@ ArrayRef<FormatToken *> FormatTokenLexer::lex() {
Tokens.push_back(getNextToken());
if (Style.Language == FormatStyle::LK_JavaScript) {
tryParseJSRegexLiteral();
- tryParseTemplateString();
+ handleTemplateStrings();
}
tryMergePreviousTokens();
if (Tokens.back()->NewlinesBefore > 0 || Tokens.back()->IsMultiline)
@@ -228,17 +227,44 @@ void FormatTokenLexer::tryParseJSRegexLiteral() {
resetLexer(SourceMgr.getFileOffset(Lex->getSourceLocation(Offset)));
}
-void FormatTokenLexer::tryParseTemplateString() {
+void FormatTokenLexer::handleTemplateStrings() {
FormatToken *BacktickToken = Tokens.back();
- if (!BacktickToken->is(tok::unknown) || BacktickToken->TokenText != "`")
+
+ if (BacktickToken->is(tok::l_brace)) {
+ StateStack.push(LexerState::NORMAL);
return;
+ }
+ if (BacktickToken->is(tok::r_brace)) {
+ if (StateStack.size() == 1)
+ return;
+ StateStack.pop();
+ if (StateStack.top() != LexerState::TEMPLATE_STRING)
+ return;
+ // If back in TEMPLATE_STRING, fallthrough and continue parsing the
+ } else if (BacktickToken->is(tok::unknown) &&
+ BacktickToken->TokenText == "`") {
+ StateStack.push(LexerState::TEMPLATE_STRING);
+ } else {
+ return; // Not actually a template
+ }
// 'Manually' lex ahead in the current file buffer.
const char *Offset = Lex->getBufferLocation();
const char *TmplBegin = Offset - BacktickToken->TokenText.size(); // at "`"
- for (; Offset != Lex->getBuffer().end() && *Offset != '`'; ++Offset) {
- if (*Offset == '\\')
+ for (; Offset != Lex->getBuffer().end(); ++Offset) {
+ if (Offset[0] == '`') {
+ StateStack.pop();
+ break;
+ }
+ if (Offset[0] == '\\') {
++Offset; // Skip the escaped character.
+ } else if (Offset + 1 < Lex->getBuffer().end() && Offset[0] == '$' &&
+ Offset[1] == '{') {
+ // '${' introduces an expression interpolation in the template string.
+ StateStack.push(LexerState::NORMAL);
+ ++Offset;
+ break;
+ }
}
StringRef LiteralText(TmplBegin, Offset - TmplBegin + 1);
@@ -262,7 +288,10 @@ void FormatTokenLexer::tryParseTemplateString() {
Style.TabWidth, Encoding);
}
- resetLexer(SourceMgr.getFileOffset(Lex->getSourceLocation(Offset + 1)));
+ SourceLocation loc = Offset < Lex->getBuffer().end()
+ ? Lex->getSourceLocation(Offset + 1)
+ : SourceMgr.getLocForEndOfFile(ID);
+ resetLexer(SourceMgr.getFileOffset(loc));
}
bool FormatTokenLexer::tryMerge_TMacro() {
@@ -384,12 +413,8 @@ FormatToken *FormatTokenLexer::getStashedToken() {
}
FormatToken *FormatTokenLexer::getNextToken() {
- if (GreaterStashed) {
- GreaterStashed = false;
- return getStashedToken();
- }
- if (LessStashed) {
- LessStashed = false;
+ if (StateStack.top() == LexerState::TOKEN_STASHED) {
+ StateStack.pop();
return getStashedToken();
}
@@ -500,11 +525,13 @@ FormatToken *FormatTokenLexer::getNextToken() {
} else if (FormatTok->Tok.is(tok::greatergreater)) {
FormatTok->Tok.setKind(tok::greater);
FormatTok->TokenText = FormatTok->TokenText.substr(0, 1);
- GreaterStashed = true;
+ ++Column;
+ StateStack.push(LexerState::TOKEN_STASHED);
} else if (FormatTok->Tok.is(tok::lessless)) {
FormatTok->Tok.setKind(tok::less);
FormatTok->TokenText = FormatTok->TokenText.substr(0, 1);
- LessStashed = true;
+ ++Column;
+ StateStack.push(LexerState::TOKEN_STASHED);
}
// Now FormatTok is the next non-whitespace token.
@@ -531,7 +558,8 @@ FormatToken *FormatTokenLexer::getNextToken() {
Column = FormatTok->LastLineColumnWidth;
}
- if (Style.Language == FormatStyle::LK_Cpp) {
+ if (Style.Language == FormatStyle::LK_Cpp ||
+ Style.Language == FormatStyle::LK_ObjC) {
if (!(Tokens.size() > 0 && Tokens.back()->Tok.getIdentifierInfo() &&
Tokens.back()->Tok.getIdentifierInfo()->getPPKeywordID() ==
tok::pp_define) &&
diff --git a/lib/Format/FormatTokenLexer.h b/lib/Format/FormatTokenLexer.h
index fa8c8882574f..c47b0e725d36 100644
--- a/lib/Format/FormatTokenLexer.h
+++ b/lib/Format/FormatTokenLexer.h
@@ -23,9 +23,17 @@
#include "clang/Format/Format.h"
#include "llvm/Support/Regex.h"
+#include <stack>
+
namespace clang {
namespace format {
+enum LexerState {
+ NORMAL,
+ TEMPLATE_STRING,
+ TOKEN_STASHED,
+};
+
class FormatTokenLexer {
public:
FormatTokenLexer(const SourceManager &SourceMgr, FileID ID,
@@ -53,7 +61,16 @@ private:
// its text if successful.
void tryParseJSRegexLiteral();
- void tryParseTemplateString();
+ // Handles JavaScript template strings.
+ //
+ // JavaScript template strings use backticks ('`') as delimiters, and allow
+ // embedding expressions nested in ${expr-here}. Template strings can be
+ // nested recursively, i.e. expressions can contain template strings in turn.
+ //
+ // The code below parses starting from a backtick, up to a closing backtick or
+ // an opening ${. It also maintains a stack of lexing contexts to handle
+ // nested template parts by balancing curly braces.
+ void handleTemplateStrings();
bool tryMerge_TMacro();
@@ -65,7 +82,7 @@ private:
FormatToken *FormatTok;
bool IsFirstToken;
- bool GreaterStashed, LessStashed;
+ std::stack<LexerState> StateStack;
unsigned Column;
unsigned TrailingWhitespace;
std::unique_ptr<Lexer> Lex;
diff --git a/lib/Format/SortJavaScriptImports.cpp b/lib/Format/SortJavaScriptImports.cpp
index 32d5d756a3f0..e73695ca8477 100644
--- a/lib/Format/SortJavaScriptImports.cpp
+++ b/lib/Format/SortJavaScriptImports.cpp
@@ -1,4 +1,4 @@
-//===--- SortJavaScriptImports.h - Sort ES6 Imports -------------*- C++ -*-===//
+//===--- SortJavaScriptImports.cpp - Sort ES6 Imports -----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,7 +13,6 @@
//===----------------------------------------------------------------------===//
#include "SortJavaScriptImports.h"
-#include "SortJavaScriptImports.h"
#include "TokenAnalyzer.h"
#include "TokenAnnotator.h"
#include "clang/Basic/Diagnostic.h"
@@ -127,7 +126,8 @@ public:
tooling::Replacements
analyze(TokenAnnotator &Annotator,
SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
- FormatTokenLexer &Tokens, tooling::Replacements &Result) override {
+ FormatTokenLexer &Tokens) override {
+ tooling::Replacements Result;
AffectedRangeMgr.computeAffectedLines(AnnotatedLines.begin(),
AnnotatedLines.end());
@@ -192,9 +192,15 @@ public:
DEBUG(llvm::dbgs() << "Replacing imports:\n"
<< getSourceText(InsertionPoint) << "\nwith:\n"
<< ReferencesText << "\n");
- Result.insert(tooling::Replacement(
+ auto Err = Result.add(tooling::Replacement(
Env.getSourceManager(), CharSourceRange::getCharRange(InsertionPoint),
ReferencesText));
+ // FIXME: better error handling. For now, just print error message and skip
+ // the replacement for the release version.
+ if (Err) {
+ llvm::errs() << llvm::toString(std::move(Err)) << "\n";
+ assert(false);
+ }
return Result;
}
@@ -276,16 +282,9 @@ private:
SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
SmallVector<JsModuleReference, 16> References;
SourceLocation Start;
- bool FoundLines = false;
AnnotatedLine *FirstNonImportLine = nullptr;
+ bool AnyImportAffected = false;
for (auto Line : AnnotatedLines) {
- if (!Line->Affected) {
- // Only sort the first contiguous block of affected lines.
- if (FoundLines)
- break;
- else
- continue;
- }
Current = Line->First;
LineEnd = Line->Last;
skipComments();
@@ -294,15 +293,20 @@ private:
// of the import that immediately follows them by using the previously
// set Start.
Start = Line->First->Tok.getLocation();
- if (!Current)
- continue; // Only comments on this line.
- FoundLines = true;
+ if (!Current) {
+ // Only comments on this line. Could be the first non-import line.
+ FirstNonImportLine = Line;
+ continue;
+ }
JsModuleReference Reference;
Reference.Range.setBegin(Start);
if (!parseModuleReference(Keywords, Reference)) {
- FirstNonImportLine = Line;
+ if (!FirstNonImportLine)
+ FirstNonImportLine = Line; // if no comment before.
break;
}
+ FirstNonImportLine = nullptr;
+ AnyImportAffected = AnyImportAffected || Line->Affected;
Reference.Range.setEnd(LineEnd->Tok.getEndLoc());
DEBUG({
llvm::dbgs() << "JsModuleReference: {"
@@ -319,6 +323,9 @@ private:
References.push_back(Reference);
Start = SourceLocation();
}
+ // Sort imports if any import line was affected.
+ if (!AnyImportAffected)
+ References.clear();
return std::make_pair(References, FirstNonImportLine);
}
@@ -342,7 +349,6 @@ private:
if (!parseModuleBindings(Keywords, Reference))
return false;
- nextToken();
if (Current->is(Keywords.kw_from)) {
// imports have a 'from' clause, exports might not.
@@ -385,19 +391,28 @@ private:
if (Current->isNot(tok::identifier))
return false;
Reference.Prefix = Current->TokenText;
+ nextToken();
return true;
}
bool parseNamedBindings(const AdditionalKeywords &Keywords,
JsModuleReference &Reference) {
+ if (Current->is(tok::identifier)) {
+ nextToken();
+ if (Current->is(Keywords.kw_from))
+ return true;
+ if (Current->isNot(tok::comma))
+ return false;
+ nextToken(); // eat comma.
+ }
if (Current->isNot(tok::l_brace))
return false;
// {sym as alias, sym2 as ...} from '...';
- nextToken();
- while (true) {
+ while (Current->isNot(tok::r_brace)) {
+ nextToken();
if (Current->is(tok::r_brace))
- return true;
+ break;
if (Current->isNot(tok::identifier))
return false;
@@ -418,12 +433,11 @@ private:
Symbol.Range.setEnd(Current->Tok.getLocation());
Reference.Symbols.push_back(Symbol);
- if (Current->is(tok::r_brace))
- return true;
- if (Current->isNot(tok::comma))
+ if (!Current->isOneOf(tok::r_brace, tok::comma))
return false;
- nextToken();
}
+ nextToken(); // consume r_brace
+ return true;
}
};
diff --git a/lib/Format/TokenAnalyzer.cpp b/lib/Format/TokenAnalyzer.cpp
index 89ac35f3e842..f2e4e8ef0819 100644
--- a/lib/Format/TokenAnalyzer.cpp
+++ b/lib/Format/TokenAnalyzer.cpp
@@ -107,12 +107,12 @@ tooling::Replacements TokenAnalyzer::process() {
}
tooling::Replacements RunResult =
- analyze(Annotator, AnnotatedLines, Tokens, Result);
+ analyze(Annotator, AnnotatedLines, Tokens);
DEBUG({
llvm::dbgs() << "Replacements for run " << Run << ":\n";
- for (tooling::Replacements::iterator I = RunResult.begin(),
- E = RunResult.end();
+ for (tooling::Replacements::const_iterator I = RunResult.begin(),
+ E = RunResult.end();
I != E; ++I) {
llvm::dbgs() << I->toString() << "\n";
}
@@ -120,7 +120,15 @@ tooling::Replacements TokenAnalyzer::process() {
for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
delete AnnotatedLines[i];
}
- Result.insert(RunResult.begin(), RunResult.end());
+ for (const auto &R : RunResult) {
+ auto Err = Result.add(R);
+ // FIXME: better error handling here. For now, simply return an empty
+ // Replacements to indicate failure.
+ if (Err) {
+ llvm::errs() << llvm::toString(std::move(Err)) << "\n";
+ return tooling::Replacements();
+ }
+ }
}
return Result;
}
diff --git a/lib/Format/TokenAnalyzer.h b/lib/Format/TokenAnalyzer.h
index c1aa9c594fc3..78a3d1bc8d9e 100644
--- a/lib/Format/TokenAnalyzer.h
+++ b/lib/Format/TokenAnalyzer.h
@@ -31,8 +31,6 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Debug.h"
-#define DEBUG_TYPE "format-formatter"
-
namespace clang {
namespace format {
@@ -57,15 +55,12 @@ public:
FileID getFileID() const { return ID; }
- StringRef getFileName() const { return FileName; }
-
ArrayRef<CharSourceRange> getCharRanges() const { return CharRanges; }
const SourceManager &getSourceManager() const { return SM; }
private:
FileID ID;
- StringRef FileName;
SmallVector<CharSourceRange, 8> CharRanges;
SourceManager &SM;
@@ -87,7 +82,7 @@ protected:
virtual tooling::Replacements
analyze(TokenAnnotator &Annotator,
SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
- FormatTokenLexer &Tokens, tooling::Replacements &Result) = 0;
+ FormatTokenLexer &Tokens) = 0;
void consumeUnwrappedLine(const UnwrappedLine &TheLine) override;
diff --git a/lib/Format/TokenAnnotator.cpp b/lib/Format/TokenAnnotator.cpp
index 4a90522e6e31..cf6373f45657 100644
--- a/lib/Format/TokenAnnotator.cpp
+++ b/lib/Format/TokenAnnotator.cpp
@@ -273,8 +273,9 @@ private:
!CurrentToken->Next->HasUnescapedNewline &&
!CurrentToken->Next->isTrailingComment())
HasMultipleParametersOnALine = true;
- if (CurrentToken->isOneOf(tok::kw_const, tok::kw_auto) ||
- CurrentToken->isSimpleTypeSpecifier())
+ if ((CurrentToken->Previous->isOneOf(tok::kw_const, tok::kw_auto) ||
+ CurrentToken->Previous->isSimpleTypeSpecifier()) &&
+ !CurrentToken->is(tok::l_brace))
Contexts.back().IsExpression = false;
if (CurrentToken->isOneOf(tok::semi, tok::colon))
MightBeObjCForRangeLoop = false;
@@ -305,8 +306,19 @@ private:
FormatToken *Left = CurrentToken->Previous;
Left->ParentBracket = Contexts.back().ContextKind;
FormatToken *Parent = Left->getPreviousNonComment();
+
+ // Cases where '>' is followed by '['.
+ // In C++, this can happen either in array of templates (foo<int>[10])
+ // or when array is a nested template type (unique_ptr<type1<type2>[]>).
+ bool CppArrayTemplates =
+ Style.Language == FormatStyle::LK_Cpp && Parent &&
+ Parent->is(TT_TemplateCloser) &&
+ (Contexts.back().CanBeExpression || Contexts.back().IsExpression ||
+ Contexts.back().InTemplateArgument);
+
bool StartsObjCMethodExpr =
- Style.Language == FormatStyle::LK_Cpp &&
+ !CppArrayTemplates && (Style.Language == FormatStyle::LK_Cpp ||
+ Style.Language == FormatStyle::LK_ObjC) &&
Contexts.back().CanBeExpression && Left->isNot(TT_LambdaLSquare) &&
CurrentToken->isNot(tok::l_brace) &&
(!Parent ||
@@ -326,7 +338,7 @@ private:
Parent->isOneOf(tok::l_brace, tok::comma)) {
Left->Type = TT_JsComputedPropertyName;
} else if (Style.Language == FormatStyle::LK_Proto ||
- (Parent &&
+ (!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,
@@ -422,7 +434,8 @@ private:
FormatToken *Previous = CurrentToken->getPreviousNonComment();
if (((CurrentToken->is(tok::colon) &&
(!Contexts.back().ColonIsDictLiteral ||
- Style.Language != FormatStyle::LK_Cpp)) ||
+ (Style.Language != FormatStyle::LK_Cpp &&
+ Style.Language != FormatStyle::LK_ObjC))) ||
Style.Language == FormatStyle::LK_Proto) &&
(Previous->Tok.getIdentifierInfo() ||
Previous->is(tok::string_literal)))
@@ -431,6 +444,9 @@ private:
Style.Language == FormatStyle::LK_JavaScript)
Left->Type = TT_DictLiteral;
}
+ if (CurrentToken->is(tok::comma) &&
+ Style.Language == FormatStyle::LK_JavaScript)
+ Left->Type = TT_DictLiteral;
if (!consumeToken())
return false;
}
@@ -508,19 +524,29 @@ private:
} else if (Contexts.back().ColonIsObjCMethodExpr ||
Line.startsWith(TT_ObjCMethodSpecifier)) {
Tok->Type = TT_ObjCMethodExpr;
- 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;
+ const FormatToken *BeforePrevious = Tok->Previous->Previous;
+ if (!BeforePrevious ||
+ !(BeforePrevious->is(TT_CastRParen) ||
+ (BeforePrevious->is(TT_ObjCMethodExpr) &&
+ BeforePrevious->is(tok::colon))) ||
+ BeforePrevious->is(tok::r_square) ||
+ Contexts.back().LongestObjCSelectorName == 0) {
+ 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 (Contexts.back().ColonIsForRangeExpr) {
Tok->Type = TT_RangeBasedForLoopColon;
} else if (CurrentToken && CurrentToken->is(tok::numeric_constant)) {
Tok->Type = TT_BitFieldColon;
} else if (Contexts.size() == 1 &&
!Line.First->isOneOf(tok::kw_enum, tok::kw_case)) {
- if (Tok->Previous->isOneOf(tok::r_paren, tok::kw_noexcept))
+ if (Tok->getPreviousNonComment()->isOneOf(tok::r_paren,
+ tok::kw_noexcept))
Tok->Type = TT_CtorInitializerColon;
else
Tok->Type = TT_InheritanceColon;
@@ -858,7 +884,8 @@ private:
if (!CurrentToken->isOneOf(TT_LambdaLSquare, TT_ForEachMacro,
TT_FunctionLBrace, TT_ImplicitStringLiteral,
TT_InlineASMBrace, TT_JsFatArrow, TT_LambdaArrow,
- TT_RegexLiteral))
+ TT_OverloadedOperator, TT_RegexLiteral,
+ TT_TemplateString))
CurrentToken->Type = TT_Unknown;
CurrentToken->Role.reset();
CurrentToken->MatchingParen = nullptr;
@@ -1037,12 +1064,17 @@ private:
!Current.Next->isBinaryOperator() &&
!Current.Next->isOneOf(tok::semi, tok::colon, tok::l_brace,
tok::period, tok::arrow, tok::coloncolon))
- if (FormatToken *BeforeParen = Current.MatchingParen->Previous)
- if (BeforeParen->is(tok::identifier) &&
- BeforeParen->TokenText == BeforeParen->TokenText.upper() &&
- (!BeforeParen->Previous ||
- BeforeParen->Previous->ClosesTemplateDeclaration))
- Current.Type = TT_FunctionAnnotationRParen;
+ if (FormatToken *AfterParen = Current.MatchingParen->Next) {
+ // Make sure this isn't the return type of an Obj-C block declaration
+ if (AfterParen->Tok.isNot(tok::caret)) {
+ if (FormatToken *BeforeParen = Current.MatchingParen->Previous)
+ if (BeforeParen->is(tok::identifier) &&
+ BeforeParen->TokenText == BeforeParen->TokenText.upper() &&
+ (!BeforeParen->Previous ||
+ BeforeParen->Previous->ClosesTemplateDeclaration))
+ Current.Type = TT_FunctionAnnotationRParen;
+ }
+ }
} else if (Current.is(tok::at) && Current.Next) {
if (Current.Next->isStringLiteral()) {
Current.Type = TT_ObjCStringLiteral;
@@ -1144,6 +1176,7 @@ private:
bool rParenEndsCast(const FormatToken &Tok) {
// C-style casts are only used in C++ and Java.
if (Style.Language != FormatStyle::LK_Cpp &&
+ Style.Language != FormatStyle::LK_ObjC &&
Style.Language != FormatStyle::LK_Java)
return false;
@@ -1206,6 +1239,13 @@ private:
if (!LeftOfParens)
return false;
+ // Certain token types inside the parentheses mean that this can't be a
+ // cast.
+ for (const FormatToken *Token = Tok.MatchingParen->Next; Token != &Tok;
+ Token = Token->Next)
+ if (Token->is(TT_BinaryOperator))
+ return false;
+
// If the following token is an identifier or 'this', this is a cast. All
// cases where this can be something else are handled above.
if (Tok.Next->isOneOf(tok::identifier, tok::kw_this))
@@ -1243,7 +1283,7 @@ private:
const FormatToken *NextToken = Tok.getNextNonComment();
if (!NextToken ||
- NextToken->isOneOf(tok::arrow, Keywords.kw_final,
+ NextToken->isOneOf(tok::arrow, Keywords.kw_final, tok::equal,
Keywords.kw_override) ||
(NextToken->is(tok::l_brace) && !NextToken->getNextNonComment()))
return TT_PointerOrReference;
@@ -1303,7 +1343,13 @@ private:
TokenType determinePlusMinusCaretUsage(const FormatToken &Tok) {
const FormatToken *PrevToken = Tok.getPreviousNonComment();
- if (!PrevToken || PrevToken->is(TT_CastRParen))
+ 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.
return TT_UnaryOperator;
// Use heuristics to recognize unary operators.
@@ -1560,6 +1606,13 @@ void TokenAnnotator::setCommentLineLevels(
}
}
+static unsigned maxNestingDepth(const AnnotatedLine &Line) {
+ unsigned Result = 0;
+ for (const auto* Tok = Line.First; Tok != nullptr; Tok = Tok->Next)
+ Result = std::max(Result, Tok->NestingLevel);
+ return Result;
+}
+
void TokenAnnotator::annotate(AnnotatedLine &Line) {
for (SmallVectorImpl<AnnotatedLine *>::iterator I = Line.Children.begin(),
E = Line.Children.end();
@@ -1568,6 +1621,14 @@ void TokenAnnotator::annotate(AnnotatedLine &Line) {
}
AnnotatingParser Parser(Style, Line, Keywords);
Line.Type = Parser.parseLine();
+
+ // With very deep nesting, ExpressionParser uses lots of stack and the
+ // formatting algorithm is very slow. We're not going to do a good job here
+ // anyway - it's probably generated code being formatted by mistake.
+ // Just skip the whole line.
+ if (maxNestingDepth(Line) > 50)
+ Line.Type = LT_Invalid;
+
if (Line.Type == LT_Invalid)
return;
@@ -1816,10 +1877,12 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
return 100;
if (Left.is(TT_JsTypeColon))
return 35;
+ if ((Left.is(TT_TemplateString) && Left.TokenText.endswith("${")) ||
+ (Right.is(TT_TemplateString) && Right.TokenText.startswith("}")))
+ return 100;
}
- if (Left.is(tok::comma) || (Right.is(tok::identifier) && Right.Next &&
- Right.Next->is(TT_DictLiteral)))
+ if (Right.is(tok::identifier) && Right.Next && Right.Next->is(TT_DictLiteral))
return 1;
if (Right.is(tok::l_square)) {
if (Style.Language == FormatStyle::LK_Proto)
@@ -1935,20 +1998,24 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
if (Left.is(TT_JavaAnnotation))
return 50;
+ if (Left.isOneOf(tok::plus, tok::comma) && Left.Previous &&
+ Left.Previous->isLabelString() &&
+ (Left.NextOperator || Left.OperatorIndex != 0))
+ return 45;
+ if (Right.is(tok::plus) && Left.isLabelString() &&
+ (Right.NextOperator || Right.OperatorIndex != 0))
+ return 25;
+ if (Left.is(tok::comma))
+ return 1;
+ if (Right.is(tok::lessless) && Left.isLabelString() &&
+ (Right.NextOperator || Right.OperatorIndex != 1))
+ return 25;
if (Right.is(tok::lessless)) {
- if (Left.is(tok::string_literal) &&
- (Right.NextOperator || Right.OperatorIndex != 1)) {
- StringRef Content = Left.TokenText;
- if (Content.startswith("\""))
- Content = Content.drop_front(1);
- if (Content.endswith("\""))
- Content = Content.drop_back(1);
- Content = Content.trim();
- if (Content.size() > 1 &&
- (Content.back() == ':' || Content.back() == '='))
- return 25;
- }
- return 1; // Breaking at a << is really cheap.
+ // Breaking at a << is really cheap.
+ if (!Left.is(tok::r_paren) || Right.OperatorIndex > 0)
+ // Slightly prefer to break before the first one in log-like statements.
+ return 2;
+ return 1;
}
if (Left.is(TT_ConditionalExpr))
return prec::Conditional;
@@ -1984,9 +2051,10 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
if (Right.isOneOf(tok::semi, tok::comma))
return false;
if (Right.is(tok::less) &&
- (Left.is(tok::kw_template) ||
- (Line.Type == LT_ObjCDecl && Style.ObjCSpaceBeforeProtocolList)))
+ Line.Type == LT_ObjCDecl && Style.ObjCSpaceBeforeProtocolList)
return true;
+ if (Right.is(tok::less) && Left.is(tok::kw_template))
+ return Style.SpaceAfterTemplateKeyword;
if (Left.isOneOf(tok::exclaim, tok::tilde))
return false;
if (Left.is(tok::at) &&
@@ -2011,7 +2079,9 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
Left.Previous->is(tok::r_paren)) ||
(!Left.isOneOf(TT_PointerOrReference, tok::l_paren) &&
(Style.PointerAlignment != FormatStyle::PAS_Left ||
- Line.IsMultiVariableDeclStmt)));
+ (Line.IsMultiVariableDeclStmt &&
+ (Left.NestingLevel == 0 ||
+ (Left.NestingLevel == 1 && Line.First->is(tok::kw_for)))))));
if (Right.is(TT_FunctionTypeLParen) && Left.isNot(tok::l_paren) &&
(!Left.is(TT_PointerOrReference) ||
(Style.PointerAlignment != FormatStyle::PAS_Right &&
@@ -2113,13 +2183,31 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
} else if (Style.Language == FormatStyle::LK_JavaScript) {
if (Left.is(TT_JsFatArrow))
return true;
+ if ((Left.is(TT_TemplateString) && Left.TokenText.endswith("${")) ||
+ (Right.is(TT_TemplateString) && Right.TokenText.startswith("}")))
+ return false;
+ if (Left.is(tok::identifier) && Right.is(TT_TemplateString))
+ return false;
if (Right.is(tok::star) &&
Left.isOneOf(Keywords.kw_function, Keywords.kw_yield))
return false;
+ if (Right.isOneOf(tok::l_brace, tok::l_square) &&
+ Left.isOneOf(Keywords.kw_function, Keywords.kw_yield))
+ return true;
+ // JS methods can use some keywords as names (e.g. `delete()`).
+ if (Right.is(tok::l_paren) && Line.MustBeDeclaration &&
+ Left.Tok.getIdentifierInfo())
+ return false;
if (Left.isOneOf(Keywords.kw_let, Keywords.kw_var, Keywords.kw_in,
Keywords.kw_of, tok::kw_const) &&
(!Left.Previous || !Left.Previous->is(tok::period)))
return true;
+ if (Left.isOneOf(tok::kw_for, Keywords.kw_as) && Left.Previous &&
+ Left.Previous->is(tok::period) && Right.is(tok::l_paren))
+ return false;
+ if (Left.is(Keywords.kw_as) &&
+ Right.isOneOf(tok::l_square, tok::l_brace, tok::l_paren))
+ return true;
if (Left.is(tok::kw_default) && Left.Previous &&
Left.Previous->is(tok::kw_export))
return true;
@@ -2146,6 +2234,8 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
tok::r_square, tok::r_brace) ||
Left.Tok.isLiteral()))
return false;
+ if (Left.is(tok::exclaim) && Right.is(Keywords.kw_as))
+ return true; // "x! as string"
} else if (Style.Language == FormatStyle::LK_Java) {
if (Left.is(tok::r_square) && Right.is(tok::l_brace))
return true;
@@ -2369,7 +2459,12 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
Keywords.kw_implements))
return true;
} else if (Style.Language == FormatStyle::LK_JavaScript) {
- if (Left.is(tok::kw_return))
+ const FormatToken *NonComment = Right.getPreviousNonComment();
+ if (Left.isOneOf(tok::kw_return, tok::kw_continue, tok::kw_break,
+ tok::kw_throw) ||
+ (NonComment &&
+ NonComment->isOneOf(tok::kw_return, tok::kw_continue, tok::kw_break,
+ tok::kw_throw)))
return false; // Otherwise a semicolon is inserted.
if (Left.is(TT_JsFatArrow) && Right.is(tok::l_brace))
return false;
@@ -2383,6 +2478,18 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
return Style.BreakBeforeBinaryOperators != FormatStyle::BOS_None;
if (Right.is(Keywords.kw_as))
return false; // must not break before as in 'x as type' casts
+ if (Left.is(Keywords.kw_declare) &&
+ Right.isOneOf(Keywords.kw_module, tok::kw_namespace,
+ Keywords.kw_function, tok::kw_class, tok::kw_enum,
+ Keywords.kw_interface, Keywords.kw_type, Keywords.kw_var,
+ Keywords.kw_let, tok::kw_const))
+ // See grammar for 'declare' statements at:
+ // https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md#A.10
+ return false;
+ if (Left.isOneOf(Keywords.kw_module, tok::kw_namespace) &&
+ Right.isOneOf(tok::identifier, tok::string_literal)) {
+ return false; // must not break in "module foo { ...}"
+ }
}
if (Left.is(tok::at))
@@ -2415,10 +2522,13 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
return !Style.BreakBeforeTernaryOperators;
if (Right.is(TT_InheritanceColon))
return true;
+ 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))
return true;
if (Right.is(TT_SelectorName) || (Right.is(tok::identifier) && Right.Next &&
Right.Next->is(TT_ObjCMethodExpr)))
@@ -2434,6 +2544,8 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
return true;
if (Right.is(TT_RangeBasedForLoopColon))
return false;
+ if (Left.is(TT_TemplateCloser) && Right.is(TT_TemplateOpener))
+ return true;
if (Left.isOneOf(TT_TemplateCloser, TT_UnaryOperator) ||
Left.is(tok::kw_operator))
return false;
@@ -2522,7 +2634,8 @@ void TokenAnnotator::printDebugInfo(const AnnotatedLine &Line) {
<< " FakeLParens=";
for (unsigned i = 0, e = Tok->FakeLParens.size(); i != e; ++i)
llvm::errs() << Tok->FakeLParens[i] << "/";
- llvm::errs() << " FakeRParens=" << Tok->FakeRParens << "\n";
+ llvm::errs() << " FakeRParens=" << Tok->FakeRParens;
+ llvm::errs() << " Text='" << Tok->TokenText << "'\n";
if (!Tok->Next)
assert(Tok == Line.Last);
Tok = Tok->Next;
diff --git a/lib/Format/TokenAnnotator.h b/lib/Format/TokenAnnotator.h
index baa68ded9740..97daaf44ba99 100644
--- a/lib/Format/TokenAnnotator.h
+++ b/lib/Format/TokenAnnotator.h
@@ -18,7 +18,6 @@
#include "UnwrappedLineParser.h"
#include "clang/Format/Format.h"
-#include <string>
namespace clang {
class SourceManager;
diff --git a/lib/Format/UnwrappedLineFormatter.cpp b/lib/Format/UnwrappedLineFormatter.cpp
index 35035ea8afba..d7f1c4232d86 100644
--- a/lib/Format/UnwrappedLineFormatter.cpp
+++ b/lib/Format/UnwrappedLineFormatter.cpp
@@ -10,6 +10,7 @@
#include "UnwrappedLineFormatter.h"
#include "WhitespaceManager.h"
#include "llvm/Support/Debug.h"
+#include <queue>
#define DEBUG_TYPE "format-formatter"
@@ -150,7 +151,7 @@ public:
MergedLines = 0;
if (!DryRun)
for (unsigned i = 0; i < MergedLines; ++i)
- join(*Next[i], *Next[i + 1]);
+ join(*Next[0], *Next[i + 1]);
Next = Next + MergedLines + 1;
return Current;
}
diff --git a/lib/Format/UnwrappedLineFormatter.h b/lib/Format/UnwrappedLineFormatter.h
index 478617d6a88e..7bcead9d25e1 100644
--- a/lib/Format/UnwrappedLineFormatter.h
+++ b/lib/Format/UnwrappedLineFormatter.h
@@ -19,8 +19,6 @@
#include "ContinuationIndenter.h"
#include "clang/Format/Format.h"
#include <map>
-#include <queue>
-#include <string>
namespace clang {
namespace format {
diff --git a/lib/Format/UnwrappedLineParser.cpp b/lib/Format/UnwrappedLineParser.cpp
index 2fe72987bc7c..84e06d05c739 100644
--- a/lib/Format/UnwrappedLineParser.cpp
+++ b/lib/Format/UnwrappedLineParser.cpp
@@ -360,14 +360,15 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
// BlockKind later if we parse a braced list (where all blocks
// inside are by default braced lists), or when we explicitly detect
// blocks (for example while parsing lambdas).
- //
- // We exclude + and - as they can be ObjC visibility modifiers.
ProbablyBracedList =
(Style.Language == FormatStyle::LK_JavaScript &&
- NextTok->isOneOf(Keywords.kw_of, Keywords.kw_in)) ||
+ NextTok->isOneOf(Keywords.kw_of, Keywords.kw_in,
+ Keywords.kw_as)) ||
NextTok->isOneOf(tok::comma, tok::period, tok::colon,
tok::r_paren, tok::r_square, tok::l_brace,
tok::l_square, tok::l_paren, 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);
@@ -668,19 +669,21 @@ static bool mustBeJSIdent(const AdditionalKeywords &Keywords,
// FIXME: This returns true for C/C++ keywords like 'struct'.
return FormatTok->is(tok::identifier) &&
(FormatTok->Tok.getIdentifierInfo() == nullptr ||
- !FormatTok->isOneOf(Keywords.kw_in, Keywords.kw_of, Keywords.kw_as,
- Keywords.kw_async, Keywords.kw_await,
- Keywords.kw_yield, Keywords.kw_finally,
- Keywords.kw_function, Keywords.kw_import,
- Keywords.kw_is, Keywords.kw_let, Keywords.kw_var,
- Keywords.kw_abstract, Keywords.kw_extends,
- Keywords.kw_implements, Keywords.kw_instanceof,
- Keywords.kw_interface, Keywords.kw_throws));
+ !FormatTok->isOneOf(
+ Keywords.kw_in, Keywords.kw_of, Keywords.kw_as, Keywords.kw_async,
+ Keywords.kw_await, Keywords.kw_yield, Keywords.kw_finally,
+ Keywords.kw_function, Keywords.kw_import, Keywords.kw_is,
+ Keywords.kw_let, Keywords.kw_var, tok::kw_const,
+ Keywords.kw_abstract, Keywords.kw_extends, Keywords.kw_implements,
+ Keywords.kw_instanceof, Keywords.kw_interface,
+ Keywords.kw_throws));
}
static bool mustBeJSIdentOrValue(const AdditionalKeywords &Keywords,
const FormatToken *FormatTok) {
- return FormatTok->Tok.isLiteral() || mustBeJSIdent(Keywords, FormatTok);
+ return FormatTok->Tok.isLiteral() ||
+ FormatTok->isOneOf(tok::kw_true, tok::kw_false) ||
+ mustBeJSIdent(Keywords, FormatTok);
}
// isJSDeclOrStmt returns true if |FormatTok| starts a declaration or statement
@@ -724,6 +727,8 @@ void UnwrappedLineParser::readTokenWithJavaScriptASI() {
return;
bool PreviousMustBeValue = mustBeJSIdentOrValue(Keywords, Previous);
+ bool PreviousStartsTemplateExpr =
+ Previous->is(TT_TemplateString) && Previous->TokenText.endswith("${");
if (PreviousMustBeValue && Line && Line->Tokens.size() > 1) {
// If the token before the previous one is an '@', the previous token is an
// annotation and can precede another identifier/value.
@@ -734,9 +739,12 @@ void UnwrappedLineParser::readTokenWithJavaScriptASI() {
if (Next->is(tok::exclaim) && PreviousMustBeValue)
addUnwrappedLine();
bool NextMustBeValue = mustBeJSIdentOrValue(Keywords, Next);
- if (NextMustBeValue && (PreviousMustBeValue ||
- Previous->isOneOf(tok::r_square, tok::r_paren,
- tok::plusplus, tok::minusminus)))
+ bool NextEndsTemplateExpr =
+ Next->is(TT_TemplateString) && Next->TokenText.startswith("}");
+ if (NextMustBeValue && !NextEndsTemplateExpr && !PreviousStartsTemplateExpr &&
+ (PreviousMustBeValue ||
+ Previous->isOneOf(tok::r_square, tok::r_paren, tok::plusplus,
+ tok::minusminus)))
addUnwrappedLine();
if (PreviousMustBeValue && isJSDeclOrStmt(Keywords, Next))
addUnwrappedLine();
@@ -906,8 +914,8 @@ void UnwrappedLineParser::parseStructuralElement() {
if (FormatTok->is(tok::colon)) {
nextToken();
addUnwrappedLine();
+ return;
}
- return;
}
// In all other cases, parse the declaration.
break;
@@ -1222,9 +1230,11 @@ void UnwrappedLineParser::tryToParseJSFunction() {
// Consume "function".
nextToken();
- // Consume * (generator function).
- if (FormatTok->is(tok::star))
+ // Consume * (generator function). Treat it like C++'s overloaded operators.
+ if (FormatTok->is(tok::star)) {
+ FormatTok->Type = TT_OverloadedOperator;
nextToken();
+ }
// Consume function name.
if (FormatTok->is(tok::identifier))
diff --git a/lib/Format/WhitespaceManager.cpp b/lib/Format/WhitespaceManager.cpp
index 9cdba9df10a9..b64506f39035 100644
--- a/lib/Format/WhitespaceManager.cpp
+++ b/lib/Format/WhitespaceManager.cpp
@@ -42,11 +42,6 @@ WhitespaceManager::Change::Change(
TokenLength(0), PreviousEndOfTokenColumn(0), EscapedNewlineColumn(0),
StartOfBlockComment(nullptr), IndentationOffset(0) {}
-void WhitespaceManager::reset() {
- Changes.clear();
- Replaces.clear();
-}
-
void WhitespaceManager::replaceWhitespace(FormatToken &Tok, unsigned Newlines,
unsigned IndentLevel, unsigned Spaces,
unsigned StartOfTokenColumn,
@@ -432,7 +427,7 @@ void WhitespaceManager::alignTrailingComments(unsigned Start, unsigned End,
}
assert(Shift >= 0);
Changes[i].Spaces += Shift;
- if (i + 1 != End)
+ if (i + 1 != Changes.size())
Changes[i + 1].PreviousEndOfTokenColumn += Shift;
Changes[i].StartOfTokenColumn += Shift;
}
@@ -502,8 +497,14 @@ void WhitespaceManager::storeReplacement(SourceRange Range,
if (StringRef(SourceMgr.getCharacterData(Range.getBegin()),
WhitespaceLength) == Text)
return;
- Replaces.insert(tooling::Replacement(
+ auto Err = Replaces.add(tooling::Replacement(
SourceMgr, CharSourceRange::getCharRange(Range), Text));
+ // FIXME: better error handling. For now, just print an error message in the
+ // release version.
+ if (Err) {
+ llvm::errs() << llvm::toString(std::move(Err)) << "\n";
+ assert(false);
+ }
}
void WhitespaceManager::appendNewlineText(std::string &Text,
diff --git a/lib/Format/WhitespaceManager.h b/lib/Format/WhitespaceManager.h
index 3562347a0e60..f42e371830b3 100644
--- a/lib/Format/WhitespaceManager.h
+++ b/lib/Format/WhitespaceManager.h
@@ -41,9 +41,6 @@ public:
bool UseCRLF)
: SourceMgr(SourceMgr), Style(Style), UseCRLF(UseCRLF) {}
- /// \brief Prepares the \c WhitespaceManager for another run.
- void reset();
-
/// \brief Replaces the whitespace in front of \p Tok. Only call once for
/// each \c AnnotatedToken.
void replaceWhitespace(FormatToken &Tok, unsigned Newlines,
diff --git a/lib/Frontend/ASTConsumers.cpp b/lib/Frontend/ASTConsumers.cpp
index de72ea57e35b..bd2ee06d1653 100644
--- a/lib/Frontend/ASTConsumers.cpp
+++ b/lib/Frontend/ASTConsumers.cpp
@@ -19,7 +19,6 @@
#include "clang/AST/RecordLayout.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Basic/Diagnostic.h"
-#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Timer.h"
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
index 76fd00a132b4..32ce966f798e 100644
--- a/lib/Frontend/ASTUnit.cpp
+++ b/lib/Frontend/ASTUnit.cpp
@@ -41,7 +41,6 @@
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Mutex.h"
#include "llvm/Support/MutexGuard.h"
-#include "llvm/Support/Path.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
#include <atomic>
@@ -926,7 +925,7 @@ public:
PrecompilePreambleConsumer(ASTUnit &Unit, PrecompilePreambleAction *Action,
const Preprocessor &PP, StringRef isysroot,
std::unique_ptr<raw_ostream> Out)
- : PCHGenerator(PP, "", nullptr, isysroot, std::make_shared<PCHBuffer>(),
+ : PCHGenerator(PP, "", isysroot, std::make_shared<PCHBuffer>(),
ArrayRef<llvm::IntrusiveRefCntPtr<ModuleFileExtension>>(),
/*AllowASTWithErrors=*/true),
Unit(Unit), Hash(Unit.getCurrentTopLevelHashValue()), Action(Action),
@@ -1393,7 +1392,8 @@ ASTUnit::getMainBufferWithPrecompiledPreamble(
}
OverriddenFiles[Status.getUniqueID()] = PreambleFileHash::createForFile(
- Status.getSize(), Status.getLastModificationTime().toEpochTime());
+ Status.getSize(),
+ llvm::sys::toTimeT(Status.getLastModificationTime()));
}
for (const auto &RB : PreprocessorOpts.RemappedFileBuffers) {
@@ -1434,8 +1434,8 @@ ASTUnit::getMainBufferWithPrecompiledPreamble(
// The file was not remapped; check whether it has changed on disk.
if (Status.getSize() != uint64_t(F->second.Size) ||
- Status.getLastModificationTime().toEpochTime() !=
- uint64_t(F->second.ModTime))
+ llvm::sys::toTimeT(Status.getLastModificationTime()) !=
+ F->second.ModTime)
AnyFileChanged = true;
}
@@ -2806,6 +2806,7 @@ const FileEntry *ASTUnit::getPCHFile() {
switch (M.Kind) {
case serialization::MK_ImplicitModule:
case serialization::MK_ExplicitModule:
+ case serialization::MK_PrebuiltModule:
return true; // skip dependencies.
case serialization::MK_PCH:
Mod = &M;
@@ -2825,7 +2826,7 @@ const FileEntry *ASTUnit::getPCHFile() {
}
bool ASTUnit::isModuleFile() {
- return isMainFileAST() && ASTFileLangOpts.CompilingModule;
+ return isMainFileAST() && ASTFileLangOpts.isCompilingModule();
}
void ASTUnit::PreambleData::countLines() const {
diff --git a/lib/Frontend/CacheTokens.cpp b/lib/Frontend/CacheTokens.cpp
index 15b0adab7c5e..72e8f68dc051 100644
--- a/lib/Frontend/CacheTokens.cpp
+++ b/lib/Frontend/CacheTokens.cpp
@@ -12,12 +12,12 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Frontend/Utils.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/FileSystemStatCache.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Frontend/Utils.h"
#include "clang/Lex/Lexer.h"
#include "clang/Lex/PTHManager.h"
#include "clang/Lex/Preprocessor.h"
@@ -28,7 +28,6 @@
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/OnDiskHashTable.h"
#include "llvm/Support/Path.h"
-#include "llvm/Support/raw_ostream.h"
// FIXME: put this somewhere else?
#ifndef S_ISDIR
@@ -59,23 +58,30 @@ public:
class PTHEntryKeyVariant {
- union { const FileEntry* FE; const char* Path; };
+ union {
+ const FileEntry *FE;
+ // FIXME: Use "StringRef Path;" when MSVC 2013 is dropped.
+ const char *PathPtr;
+ };
+ size_t PathSize;
enum { IsFE = 0x1, IsDE = 0x2, IsNoExist = 0x0 } Kind;
FileData *Data;
public:
PTHEntryKeyVariant(const FileEntry *fe) : FE(fe), Kind(IsFE), Data(nullptr) {}
- PTHEntryKeyVariant(FileData *Data, const char *path)
- : Path(path), Kind(IsDE), Data(new FileData(*Data)) {}
+ PTHEntryKeyVariant(FileData *Data, StringRef Path)
+ : PathPtr(Path.data()), PathSize(Path.size()), Kind(IsDE),
+ Data(new FileData(*Data)) {}
- explicit PTHEntryKeyVariant(const char *path)
- : Path(path), Kind(IsNoExist), Data(nullptr) {}
+ explicit PTHEntryKeyVariant(StringRef Path)
+ : PathPtr(Path.data()), PathSize(Path.size()), Kind(IsNoExist),
+ Data(nullptr) {}
bool isFile() const { return Kind == IsFE; }
StringRef getString() const {
- return Kind == IsFE ? FE->getName() : Path;
+ return Kind == IsFE ? FE->getName() : StringRef(PathPtr, PathSize);
}
unsigned getKind() const { return (unsigned) Kind; }
@@ -183,14 +189,14 @@ class PTHWriter {
typedef llvm::DenseMap<const IdentifierInfo*,uint32_t> IDMap;
typedef llvm::StringMap<OffsetOpt, llvm::BumpPtrAllocator> CachedStrsTy;
- IDMap IM;
raw_pwrite_stream &Out;
Preprocessor& PP;
- uint32_t idcount;
+ IDMap IM;
+ std::vector<llvm::StringMapEntry<OffsetOpt>*> StrEntries;
PTHMap PM;
CachedStrsTy CachedStrs;
+ uint32_t idcount;
Offset CurStrOffset;
- std::vector<llvm::StringMapEntry<OffsetOpt>*> StrEntries;
//// Get the persistent id for the given IdentifierInfo*.
uint32_t ResolveID(const IdentifierInfo* II);
@@ -550,7 +556,7 @@ public:
StatListener(PTHMap &pm) : PM(pm) {}
~StatListener() override {}
- LookupResult getStat(const char *Path, FileData &Data, bool isFile,
+ LookupResult getStat(StringRef Path, FileData &Data, bool isFile,
std::unique_ptr<vfs::File> *F,
vfs::FileSystem &FS) override {
LookupResult Result = statChained(Path, Data, isFile, F, FS);
diff --git a/lib/Frontend/ChainedIncludesSource.cpp b/lib/Frontend/ChainedIncludesSource.cpp
index 3f126615b1eb..c5b77ee90e56 100644
--- a/lib/Frontend/ChainedIncludesSource.cpp
+++ b/lib/Frontend/ChainedIncludesSource.cpp
@@ -17,6 +17,7 @@
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Parse/ParseAST.h"
#include "clang/Sema/MultiplexExternalSemaSource.h"
#include "clang/Serialization/ASTReader.h"
@@ -160,7 +161,7 @@ IntrusiveRefCntPtr<ExternalSemaSource> clang::createChainedIncludesSource(
auto Buffer = std::make_shared<PCHBuffer>();
ArrayRef<llvm::IntrusiveRefCntPtr<ModuleFileExtension>> Extensions;
auto consumer = llvm::make_unique<PCHGenerator>(
- Clang->getPreprocessor(), "-", nullptr, /*isysroot=*/"", Buffer,
+ Clang->getPreprocessor(), "-", /*isysroot=*/"", Buffer,
Extensions, /*AllowASTWithErrors=*/true);
Clang->getASTContext().setASTMutationListener(
consumer->GetASTMutationListener());
diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp
index 8b00a3d00879..ccddd14f0f34 100644
--- a/lib/Frontend/CompilerInstance.cpp
+++ b/lib/Frontend/CompilerInstance.cpp
@@ -29,6 +29,7 @@
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/PTHManager.h"
#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Sema/CodeCompleteConsumer.h"
#include "clang/Sema/Sema.h"
#include "clang/Serialization/ASTReader.h"
@@ -140,6 +141,66 @@ void CompilerInstance::setModuleDepCollector(
ModuleDepCollector = std::move(Collector);
}
+static void collectHeaderMaps(const HeaderSearch &HS,
+ std::shared_ptr<ModuleDependencyCollector> MDC) {
+ SmallVector<std::string, 4> HeaderMapFileNames;
+ HS.getHeaderMapFileNames(HeaderMapFileNames);
+ for (auto &Name : HeaderMapFileNames)
+ MDC->addFile(Name);
+}
+
+static void collectIncludePCH(CompilerInstance &CI,
+ std::shared_ptr<ModuleDependencyCollector> MDC) {
+ const PreprocessorOptions &PPOpts = CI.getPreprocessorOpts();
+ if (PPOpts.ImplicitPCHInclude.empty())
+ return;
+
+ StringRef PCHInclude = PPOpts.ImplicitPCHInclude;
+ FileManager &FileMgr = CI.getFileManager();
+ const DirectoryEntry *PCHDir = FileMgr.getDirectory(PCHInclude);
+ if (!PCHDir) {
+ MDC->addFile(PCHInclude);
+ return;
+ }
+
+ std::error_code EC;
+ SmallString<128> DirNative;
+ llvm::sys::path::native(PCHDir->getName(), DirNative);
+ vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem();
+ SimpleASTReaderListener Validator(CI.getPreprocessor());
+ for (vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), DirEnd;
+ Dir != DirEnd && !EC; Dir.increment(EC)) {
+ // Check whether this is an AST file. ASTReader::isAcceptableASTFile is not
+ // used here since we're not interested in validating the PCH at this time,
+ // but only to check whether this is a file containing an AST.
+ if (!ASTReader::readASTFileControlBlock(
+ Dir->getName(), FileMgr, CI.getPCHContainerReader(),
+ /*FindModuleFileExtensions=*/false, Validator,
+ /*ValidateDiagnosticOptions=*/false))
+ MDC->addFile(Dir->getName());
+ }
+}
+
+static void collectVFSEntries(CompilerInstance &CI,
+ std::shared_ptr<ModuleDependencyCollector> MDC) {
+ if (CI.getHeaderSearchOpts().VFSOverlayFiles.empty())
+ return;
+
+ // Collect all VFS found.
+ SmallVector<vfs::YAMLVFSEntry, 16> VFSEntries;
+ for (const std::string &VFSFile : CI.getHeaderSearchOpts().VFSOverlayFiles) {
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buffer =
+ llvm::MemoryBuffer::getFile(VFSFile);
+ if (!Buffer)
+ return;
+ vfs::collectVFSFromYAML(std::move(Buffer.get()), /*DiagHandler*/ nullptr,
+ VFSFile, VFSEntries);
+ }
+
+ for (auto &E : VFSEntries)
+ MDC->addFile(E.VPath, E.RPath);
+}
+
// Diagnostics
static void SetUpDiagnosticLog(DiagnosticOptions *DiagOpts,
const CodeGenOptions *CodeGenOpts,
@@ -333,9 +394,16 @@ void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) {
InitializePreprocessor(*PP, PPOpts, getPCHContainerReader(),
getFrontendOpts());
- // Initialize the header search object.
+ // Initialize the header search object. In CUDA compilations, we use the aux
+ // triple (the host triple) to initialize our header search, since we need to
+ // find the host headers in order to compile the CUDA code.
+ const llvm::Triple *HeaderSearchTriple = &PP->getTargetInfo().getTriple();
+ if (PP->getTargetInfo().getTriple().getOS() == llvm::Triple::CUDA &&
+ PP->getAuxTargetInfo())
+ HeaderSearchTriple = &PP->getAuxTargetInfo()->getTriple();
+
ApplyHeaderSearchOptions(PP->getHeaderSearchInfo(), getHeaderSearchOpts(),
- PP->getLangOpts(), PP->getTargetInfo().getTriple());
+ PP->getLangOpts(), *HeaderSearchTriple);
PP->setPreprocessedOutput(getPreprocessorOutputOpts().ShowCPP);
@@ -358,8 +426,14 @@ void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) {
DepOpts.ModuleDependencyOutputDir);
}
- if (ModuleDepCollector)
+ // If there is a module dep collector, register with other dep collectors
+ // and also (a) collect header maps and (b) TODO: input vfs overlay files.
+ if (ModuleDepCollector) {
addDependencyCollector(ModuleDepCollector);
+ collectHeaderMaps(PP->getHeaderSearchInfo(), ModuleDepCollector);
+ collectIncludePCH(*this, ModuleDepCollector);
+ collectVFSEntries(*this, ModuleDepCollector);
+ }
for (auto &Listener : DependencyCollectors)
Listener->attachToPreprocessor(*PP);
@@ -514,9 +588,11 @@ void CompilerInstance::createCodeCompletionConsumer() {
}
void CompilerInstance::createFrontendTimer() {
- FrontendTimerGroup.reset(new llvm::TimerGroup("Clang front-end time report"));
+ FrontendTimerGroup.reset(
+ new llvm::TimerGroup("frontend", "Clang front-end time report"));
FrontendTimer.reset(
- new llvm::Timer("Clang front-end timer", *FrontendTimerGroup));
+ new llvm::Timer("frontend", "Clang front-end timer",
+ *FrontendTimerGroup));
}
CodeCompleteConsumer *
@@ -537,6 +613,11 @@ void CompilerInstance::createSema(TranslationUnitKind TUKind,
CodeCompleteConsumer *CompletionConsumer) {
TheSema.reset(new Sema(getPreprocessor(), getASTContext(), getASTConsumer(),
TUKind, CompletionConsumer));
+ // Attach the external sema source if there is any.
+ if (ExternalSemaSrc) {
+ TheSema->addExternalSource(ExternalSemaSrc.get());
+ ExternalSemaSrc->InitializeSema(*TheSema);
+ }
}
// Output Files
@@ -841,6 +922,9 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) {
// created. This complexity should be lifted elsewhere.
getTarget().adjust(getLangOpts());
+ // Adjust target options based on codegen options.
+ getTarget().adjustTargetOptions(getCodeGenOpts(), getTargetOpts());
+
// rewriter project will change target built-in bool type from its default.
if (getFrontendOpts().ProgramAction == frontend::RewriteObjC)
getTarget().noSignedCharForObjCBool();
@@ -854,8 +938,8 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) {
if (getFrontendOpts().ShowTimers)
createFrontendTimer();
- if (getFrontendOpts().ShowStats)
- llvm::EnableStatistics();
+ if (getFrontendOpts().ShowStats || !getFrontendOpts().StatsFile.empty())
+ llvm::EnableStatistics(false);
for (const FrontendInputFile &FIF : getFrontendOpts().Inputs) {
// Reset the ID tables if we are reusing the SourceManager and parsing
@@ -888,9 +972,24 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) {
OS << " generated.\n";
}
- if (getFrontendOpts().ShowStats && hasFileManager()) {
- getFileManager().PrintStats();
- OS << "\n";
+ if (getFrontendOpts().ShowStats) {
+ if (hasFileManager()) {
+ getFileManager().PrintStats();
+ OS << '\n';
+ }
+ llvm::PrintStatistics(OS);
+ }
+ StringRef StatsFile = getFrontendOpts().StatsFile;
+ if (!StatsFile.empty()) {
+ std::error_code EC;
+ auto StatS = llvm::make_unique<llvm::raw_fd_ostream>(StatsFile, EC,
+ llvm::sys::fs::F_Text);
+ if (EC) {
+ getDiagnostics().Report(diag::warn_fe_unable_to_open_stats_file)
+ << StatsFile << EC.message();
+ } else {
+ llvm::PrintStatisticsJSON(*StatS);
+ }
}
return !getDiagnostics().getClient()->getNumErrors();
@@ -936,7 +1035,8 @@ static bool compileModuleImpl(CompilerInstance &ImportingInstance,
std::remove_if(PPOpts.Macros.begin(), PPOpts.Macros.end(),
[&HSOpts](const std::pair<std::string, bool> &def) {
StringRef MacroDef = def.first;
- return HSOpts.ModulesIgnoreMacros.count(MacroDef.split('=').first) > 0;
+ return HSOpts.ModulesIgnoreMacros.count(
+ llvm::CachedHashString(MacroDef.split('=').first)) > 0;
}),
PPOpts.Macros.end());
@@ -1022,7 +1122,7 @@ static bool compileModuleImpl(CompilerInstance &ImportingInstance,
// Construct a module-generating action. Passing through the module map is
// safe because the FileManager is shared between the compiler instances.
- GenerateModuleAction CreateModuleAction(
+ GenerateModuleFromModuleMapAction CreateModuleAction(
ModMap.getModuleMapFileForUniquing(Module), Module->IsSystem);
ImportingInstance.getDiagnostics().Report(ImportLoc,
@@ -1292,7 +1392,8 @@ void CompilerInstance::createModuleManager() {
const PreprocessorOptions &PPOpts = getPreprocessorOpts();
std::unique_ptr<llvm::Timer> ReadTimer;
if (FrontendTimerGroup)
- ReadTimer = llvm::make_unique<llvm::Timer>("Reading modules",
+ ReadTimer = llvm::make_unique<llvm::Timer>("reading_modules",
+ "Reading modules",
*FrontendTimerGroup);
ModuleManager = new ASTReader(
getPreprocessor(), getASTContext(), getPCHContainerReader(),
@@ -1325,7 +1426,8 @@ void CompilerInstance::createModuleManager() {
bool CompilerInstance::loadModuleFile(StringRef FileName) {
llvm::Timer Timer;
if (FrontendTimerGroup)
- Timer.init("Preloading " + FileName.str(), *FrontendTimerGroup);
+ Timer.init("preloading." + FileName.str(), "Preloading " + FileName.str(),
+ *FrontendTimerGroup);
llvm::TimeRegion TimeLoading(FrontendTimerGroup ? &Timer : nullptr);
// Helper to recursively read the module names for all modules we're adding.
@@ -1357,8 +1459,21 @@ bool CompilerInstance::loadModuleFile(StringRef FileName) {
if (Module *M = CI.getPreprocessor()
.getHeaderSearchInfo()
.getModuleMap()
- .findModule(II->getName()))
+ .findModule(II->getName())) {
M->HasIncompatibleModuleFile = true;
+
+ // Mark module as available if the only reason it was unavailable
+ // was missing headers.
+ SmallVector<Module *, 2> Stack;
+ Stack.push_back(M);
+ while (!Stack.empty()) {
+ Module *Current = Stack.pop_back_val();
+ if (Current->IsMissingRequirement) continue;
+ Current->IsAvailable = true;
+ Stack.insert(Stack.end(),
+ Current->submodule_begin(), Current->submodule_end());
+ }
+ }
}
LoadedModules.clear();
}
@@ -1432,7 +1547,25 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
} else {
// Search for a module with the given name.
Module = PP->getHeaderSearchInfo().lookupModule(ModuleName);
- if (!Module) {
+ HeaderSearchOptions &HSOpts =
+ PP->getHeaderSearchInfo().getHeaderSearchOpts();
+
+ std::string ModuleFileName;
+ bool LoadFromPrebuiltModulePath = false;
+ // We try to load the module from the prebuilt module paths. If not
+ // successful, we then try to find it in the module cache.
+ if (!HSOpts.PrebuiltModulePaths.empty()) {
+ // Load the module from the prebuilt module path.
+ ModuleFileName = PP->getHeaderSearchInfo().getModuleFileName(
+ ModuleName, "", /*UsePrebuiltPath*/ true);
+ if (!ModuleFileName.empty())
+ LoadFromPrebuiltModulePath = true;
+ }
+ if (!LoadFromPrebuiltModulePath && Module) {
+ // Load the module from the module cache.
+ ModuleFileName = PP->getHeaderSearchInfo().getModuleFileName(Module);
+ } else if (!LoadFromPrebuiltModulePath) {
+ // We can't find a module, error out here.
getDiagnostics().Report(ModuleNameLoc, diag::err_module_not_found)
<< ModuleName
<< SourceRange(ImportLoc, ModuleNameLoc);
@@ -1440,13 +1573,11 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
return ModuleLoadResult();
}
- std::string ModuleFileName =
- PP->getHeaderSearchInfo().getModuleFileName(Module);
if (ModuleFileName.empty()) {
- if (Module->HasIncompatibleModuleFile) {
+ if (Module && Module->HasIncompatibleModuleFile) {
// We tried and failed to load a module file for this module. Fall
// back to textual inclusion for its headers.
- return ModuleLoadResult(nullptr, /*missingExpected*/true);
+ return ModuleLoadResult::ConfigMismatch;
}
getDiagnostics().Report(ModuleNameLoc, diag::err_module_build_disabled)
@@ -1461,19 +1592,50 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
llvm::Timer Timer;
if (FrontendTimerGroup)
- Timer.init("Loading " + ModuleFileName, *FrontendTimerGroup);
+ Timer.init("loading." + ModuleFileName, "Loading " + ModuleFileName,
+ *FrontendTimerGroup);
llvm::TimeRegion TimeLoading(FrontendTimerGroup ? &Timer : nullptr);
- // Try to load the module file.
- unsigned ARRFlags = ASTReader::ARR_OutOfDate | ASTReader::ARR_Missing;
+ // Try to load the module file. If we are trying to load from the prebuilt
+ // module path, we don't have the module map files and don't know how to
+ // rebuild modules.
+ unsigned ARRFlags = LoadFromPrebuiltModulePath ?
+ ASTReader::ARR_ConfigurationMismatch :
+ ASTReader::ARR_OutOfDate | ASTReader::ARR_Missing;
switch (ModuleManager->ReadAST(ModuleFileName,
+ LoadFromPrebuiltModulePath ?
+ serialization::MK_PrebuiltModule :
serialization::MK_ImplicitModule,
- ImportLoc, ARRFlags)) {
- case ASTReader::Success:
+ ImportLoc,
+ ARRFlags)) {
+ case ASTReader::Success: {
+ if (LoadFromPrebuiltModulePath && !Module) {
+ Module = PP->getHeaderSearchInfo().lookupModule(ModuleName);
+ if (!Module || !Module->getASTFile() ||
+ FileMgr->getFile(ModuleFileName) != Module->getASTFile()) {
+ // Error out if Module does not refer to the file in the prebuilt
+ // module path.
+ getDiagnostics().Report(ModuleNameLoc, diag::err_module_prebuilt)
+ << ModuleName;
+ ModuleBuildFailed = true;
+ KnownModules[Path[0].first] = nullptr;
+ return ModuleLoadResult();
+ }
+ }
break;
+ }
case ASTReader::OutOfDate:
case ASTReader::Missing: {
+ if (LoadFromPrebuiltModulePath) {
+ // We can't rebuild the module without a module map. Since ReadAST
+ // already produces diagnostics for these two cases, we simply
+ // error out here.
+ ModuleBuildFailed = true;
+ KnownModules[Path[0].first] = nullptr;
+ return ModuleLoadResult();
+ }
+
// The module file is missing or out-of-date. Build it.
assert(Module && "missing module file");
// Check whether there is a cycle in the module graph.
@@ -1524,8 +1686,13 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
break;
}
- case ASTReader::VersionMismatch:
case ASTReader::ConfigurationMismatch:
+ if (LoadFromPrebuiltModulePath)
+ getDiagnostics().Report(SourceLocation(),
+ diag::warn_module_config_mismatch)
+ << ModuleFileName;
+ // Fall through to error out.
+ case ASTReader::VersionMismatch:
case ASTReader::HadErrors:
ModuleLoader::HadFatalFailure = true;
// FIXME: The ASTReader will already have complained, but can we shoehorn
@@ -1617,7 +1784,7 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
<< Module->getFullModuleName()
<< SourceRange(Path.front().second, Path.back().second);
- return ModuleLoadResult(nullptr, true);
+ return ModuleLoadResult::MissingExpected;
}
// Check whether this module is available.
@@ -1651,7 +1818,7 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
}
LastModuleImportLoc = ImportLoc;
- LastModuleImportResult = ModuleLoadResult(Module, false);
+ LastModuleImportResult = ModuleLoadResult(Module);
return LastModuleImportResult;
}
@@ -1749,3 +1916,8 @@ CompilerInstance::lookupMissingImports(StringRef Name,
return false;
}
void CompilerInstance::resetAndLeakSema() { BuryPointer(takeSema()); }
+
+void CompilerInstance::setExternalSemaSource(
+ IntrusiveRefCntPtr<ExternalSemaSource> ESS) {
+ ExternalSemaSrc = std::move(ESS);
+}
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index c6948ebfc4b4..a0682e26e702 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -7,6 +7,7 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/Frontend/CompilerInvocation.h"
#include "TestModuleFileExtension.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/FileManager.h"
@@ -15,11 +16,11 @@
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/Util.h"
-#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/LangStandard.h"
#include "clang/Frontend/Utils.h"
#include "clang/Lex/HeaderSearchOptions.h"
+#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Serialization/ASTReader.h"
#include "clang/Serialization/ModuleFileExtension.h"
#include "llvm/ADT/Hashing.h"
@@ -97,6 +98,9 @@ static unsigned getOptimizationLevel(ArgList &Args, InputKind IK,
if (S == "s" || S == "z" || S.empty())
return 2;
+ if (S == "g")
+ return 1;
+
return getLastArgIntValue(Args, OPT_O, DefaultOpt, Diags);
}
@@ -237,6 +241,7 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
}
Opts.ShowCheckerHelp = Args.hasArg(OPT_analyzer_checker_help);
+ Opts.ShowEnabledCheckerList = Args.hasArg(OPT_analyzer_list_enabled_checkers);
Opts.DisableAllChecks = Args.hasArg(OPT_analyzer_disable_all_checks);
Opts.visualizeExplodedGraphWithGraphViz =
@@ -436,28 +441,37 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
}
Opts.OptimizationLevel = OptimizationLevel;
- // We must always run at least the always inlining pass.
- Opts.setInlining(
- (Opts.OptimizationLevel > 1) ? CodeGenOptions::NormalInlining
- : CodeGenOptions::OnlyAlwaysInlining);
- // -fno-inline-functions overrides OptimizationLevel > 1.
- Opts.NoInline = Args.hasArg(OPT_fno_inline);
- if (Arg* InlineArg = Args.getLastArg(options::OPT_finline_functions,
- options::OPT_finline_hint_functions,
- options::OPT_fno_inline_functions)) {
- const Option& InlineOpt = InlineArg->getOption();
- if (InlineOpt.matches(options::OPT_finline_functions))
- Opts.setInlining(CodeGenOptions::NormalInlining);
- else if (InlineOpt.matches(options::OPT_finline_hint_functions))
- Opts.setInlining(CodeGenOptions::OnlyHintInlining);
- else
- Opts.setInlining(CodeGenOptions::OnlyAlwaysInlining);
+ // At O0 we want to fully disable inlining outside of cases marked with
+ // 'alwaysinline' that are required for correctness.
+ Opts.setInlining((Opts.OptimizationLevel == 0)
+ ? CodeGenOptions::OnlyAlwaysInlining
+ : CodeGenOptions::NormalInlining);
+ // Explicit inlining flags can disable some or all inlining even at
+ // optimization levels above zero.
+ if (Arg *InlineArg = Args.getLastArg(
+ options::OPT_finline_functions, options::OPT_finline_hint_functions,
+ options::OPT_fno_inline_functions, options::OPT_fno_inline)) {
+ if (Opts.OptimizationLevel > 0) {
+ const Option &InlineOpt = InlineArg->getOption();
+ if (InlineOpt.matches(options::OPT_finline_functions))
+ Opts.setInlining(CodeGenOptions::NormalInlining);
+ else if (InlineOpt.matches(options::OPT_finline_hint_functions))
+ Opts.setInlining(CodeGenOptions::OnlyHintInlining);
+ else
+ Opts.setInlining(CodeGenOptions::OnlyAlwaysInlining);
+ }
}
+ Opts.ExperimentalNewPassManager = Args.hasFlag(
+ OPT_fexperimental_new_pass_manager, OPT_fno_experimental_new_pass_manager,
+ /* Default */ false);
+
if (Arg *A = Args.getLastArg(OPT_fveclib)) {
StringRef Name = A->getValue();
if (Name == "Accelerate")
Opts.setVecLib(CodeGenOptions::Accelerate);
+ else if (Name == "SVML")
+ Opts.setVecLib(CodeGenOptions::SVML);
else if (Name == "none")
Opts.setVecLib(CodeGenOptions::NoLibrary);
else
@@ -495,6 +509,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.WholeProgramVTables = Args.hasArg(OPT_fwhole_program_vtables);
Opts.LTOVisibilityPublicStd = Args.hasArg(OPT_flto_visibility_public_std);
Opts.SplitDwarfFile = Args.getLastArgValue(OPT_split_dwarf_file);
+ Opts.SplitDwarfInlining = !Args.hasArg(OPT_fno_split_dwarf_inlining);
Opts.DebugTypeExtRefs = Args.hasArg(OPT_dwarf_ext_refs);
Opts.DebugExplicitImport = Triple.isPS4CPU();
@@ -505,7 +520,6 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Args.getLastArg(OPT_emit_llvm_uselists, OPT_no_emit_llvm_uselists))
Opts.EmitLLVMUseLists = A->getOption().getID() == OPT_emit_llvm_uselists;
- Opts.DisableLLVMOpts = Args.hasArg(OPT_disable_llvm_optzns);
Opts.DisableLLVMPasses = Args.hasArg(OPT_disable_llvm_passes);
Opts.DisableRedZone = Args.hasArg(OPT_disable_red_zone);
Opts.ForbidGuardVariables = Args.hasArg(OPT_fforbid_guard_variables);
@@ -543,6 +557,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Args.hasFlag(OPT_fcoverage_mapping, OPT_fno_coverage_mapping, false);
Opts.DumpCoverageMapping = Args.hasArg(OPT_dump_coverage_mapping);
Opts.AsmVerbose = Args.hasArg(OPT_masm_verbose);
+ Opts.PreserveAsmComments = !Args.hasArg(OPT_fno_preserve_as_comments);
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);
@@ -566,7 +581,11 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Args.hasArg(OPT_cl_fast_relaxed_math));
Opts.NoSignedZeros = (Args.hasArg(OPT_fno_signed_zeros) ||
Args.hasArg(OPT_cl_no_signed_zeros));
+ Opts.FlushDenorm = Args.hasArg(OPT_cl_denorms_are_zero);
+ Opts.CorrectlyRoundedDivSqrt =
+ Args.hasArg(OPT_cl_fp32_correctly_rounded_divide_sqrt);
Opts.ReciprocalMath = Args.hasArg(OPT_freciprocal_math);
+ Opts.NoTrappingMath = Args.hasArg(OPT_fno_trapping_math);
Opts.NoZeroInitializedInBSS = Args.hasArg(OPT_mno_zero_initialized_in_bss);
Opts.BackendOptions = Args.getAllArgValues(OPT_backend_option);
Opts.NumRegisterParameters = getLastArgIntValue(Args, OPT_mregparm, 0, Diags);
@@ -576,6 +595,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.RelaxAll = Args.hasArg(OPT_mrelax_all);
Opts.IncrementalLinkerCompatible =
Args.hasArg(OPT_mincremental_linker_compatible);
+ Opts.PIECopyRelocations =
+ Args.hasArg(OPT_mpie_copy_relocations);
Opts.OmitLeafFramePointer = Args.hasArg(OPT_momit_leaf_frame_pointer);
Opts.SaveTempLabels = Args.hasArg(OPT_msave_temp_labels);
Opts.NoDwarfDirectoryAsm = Args.hasArg(OPT_fno_dwarf_directory_asm);
@@ -629,7 +650,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.EmitGcovArcs = Args.hasArg(OPT_femit_coverage_data);
Opts.EmitGcovNotes = Args.hasArg(OPT_femit_coverage_notes);
if (Opts.EmitGcovArcs || Opts.EmitGcovNotes) {
- Opts.CoverageFile = Args.getLastArgValue(OPT_coverage_file);
+ Opts.CoverageDataFile = Args.getLastArgValue(OPT_coverage_data_file);
+ Opts.CoverageNotesFile = Args.getLastArgValue(OPT_coverage_notes_file);
Opts.CoverageExtraChecksum = Args.hasArg(OPT_coverage_cfg_checksum);
Opts.CoverageNoFunctionNamesInData =
Args.hasArg(OPT_coverage_no_function_names_in_data);
@@ -708,17 +730,24 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Args.hasArg(OPT_fsanitize_coverage_indirect_calls);
Opts.SanitizeCoverageTraceBB = Args.hasArg(OPT_fsanitize_coverage_trace_bb);
Opts.SanitizeCoverageTraceCmp = Args.hasArg(OPT_fsanitize_coverage_trace_cmp);
+ Opts.SanitizeCoverageTraceDiv = Args.hasArg(OPT_fsanitize_coverage_trace_div);
+ Opts.SanitizeCoverageTraceGep = Args.hasArg(OPT_fsanitize_coverage_trace_gep);
Opts.SanitizeCoverage8bitCounters =
Args.hasArg(OPT_fsanitize_coverage_8bit_counters);
Opts.SanitizeCoverageTracePC = Args.hasArg(OPT_fsanitize_coverage_trace_pc);
+ Opts.SanitizeCoverageTracePCGuard =
+ Args.hasArg(OPT_fsanitize_coverage_trace_pc_guard);
Opts.SanitizeMemoryTrackOrigins =
getLastArgIntValue(Args, OPT_fsanitize_memory_track_origins_EQ, 0, Diags);
Opts.SanitizeMemoryUseAfterDtor =
Args.hasArg(OPT_fsanitize_memory_use_after_dtor);
Opts.SanitizeCfiCrossDso = Args.hasArg(OPT_fsanitize_cfi_cross_dso);
Opts.SanitizeStats = Args.hasArg(OPT_fsanitize_stats);
- Opts.SanitizeAddressUseAfterScope =
- Args.hasArg(OPT_fsanitize_address_use_after_scope);
+ if (Arg *A = Args.getLastArg(OPT_fsanitize_address_use_after_scope,
+ OPT_fno_sanitize_address_use_after_scope)) {
+ Opts.SanitizeAddressUseAfterScope =
+ A->getOption().getID() == OPT_fsanitize_address_use_after_scope;
+ }
Opts.SSPBufferSize =
getLastArgIntValue(Args, OPT_stack_protector_buffer_size, 8, Diags);
Opts.StackRealignment = Args.hasArg(OPT_mstackrealign);
@@ -783,6 +812,18 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val;
}
+ if (Arg *A = Args.getLastArg(OPT_fdenormal_fp_math_EQ)) {
+ StringRef Val = A->getValue();
+ if (Val == "ieee")
+ Opts.FPDenormalMode = "ieee";
+ else if (Val == "preserve-sign")
+ Opts.FPDenormalMode = "preserve-sign";
+ else if (Val == "positive-zero")
+ Opts.FPDenormalMode = "positive-zero";
+ else
+ Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val;
+ }
+
if (Arg *A = Args.getLastArg(OPT_fpcc_struct_return, OPT_freg_struct_return)) {
if (A->getOption().matches(OPT_fpcc_struct_return)) {
Opts.setStructReturnConvention(CodeGenOptions::SRCK_OnStack);
@@ -796,6 +837,10 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.LinkerOptions = Args.getAllArgValues(OPT_linker_option);
bool NeedLocTracking = false;
+ Opts.OptRecordFile = Args.getLastArgValue(OPT_opt_record_file);
+ if (!Opts.OptRecordFile.empty())
+ NeedLocTracking = true;
+
if (Arg *A = Args.getLastArg(OPT_Rpass_EQ)) {
Opts.OptimizationRemarkPattern =
GenerateOptimizationRemarkRegex(Diags, Args, A);
@@ -814,6 +859,12 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
NeedLocTracking = true;
}
+ Opts.DiagnosticsWithHotness =
+ Args.hasArg(options::OPT_fdiagnostics_show_hotness);
+ if (Opts.DiagnosticsWithHotness &&
+ Opts.getProfileUse() == CodeGenOptions::ProfileNone)
+ Diags.Report(diag::warn_drv_fdiagnostics_show_hotness_requires_pgo);
+
// If the user requested to use a sample profile for PGO, then the
// backend will need to track source location information so the profile
// can be incorporated into the IR.
@@ -885,21 +936,13 @@ static bool parseShowColorsArgs(const ArgList &Args, bool DefaultColor) {
} ShowColors = DefaultColor ? Colors_Auto : Colors_Off;
for (Arg *A : Args) {
const Option &O = A->getOption();
- if (!O.matches(options::OPT_fcolor_diagnostics) &&
- !O.matches(options::OPT_fdiagnostics_color) &&
- !O.matches(options::OPT_fno_color_diagnostics) &&
- !O.matches(options::OPT_fno_diagnostics_color) &&
- !O.matches(options::OPT_fdiagnostics_color_EQ))
- continue;
-
if (O.matches(options::OPT_fcolor_diagnostics) ||
O.matches(options::OPT_fdiagnostics_color)) {
ShowColors = Colors_On;
} else if (O.matches(options::OPT_fno_color_diagnostics) ||
O.matches(options::OPT_fno_diagnostics_color)) {
ShowColors = Colors_Off;
- } else {
- assert(O.matches(options::OPT_fdiagnostics_color_EQ));
+ } else if (O.matches(options::OPT_fdiagnostics_color_EQ)) {
StringRef Value(A->getValue());
if (Value == "always")
ShowColors = Colors_On;
@@ -909,15 +952,14 @@ static bool parseShowColorsArgs(const ArgList &Args, bool DefaultColor) {
ShowColors = Colors_Auto;
}
}
- if (ShowColors == Colors_On ||
- (ShowColors == Colors_Auto && llvm::sys::Process::StandardErrHasColors()))
- return true;
- return false;
+ return ShowColors == Colors_On ||
+ (ShowColors == Colors_Auto &&
+ llvm::sys::Process::StandardErrHasColors());
}
bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
DiagnosticsEngine *Diags,
- bool DefaultDiagColor) {
+ bool DefaultDiagColor, bool DefaultShowOpt) {
using namespace options;
bool Success = true;
@@ -936,7 +978,10 @@ bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
/*Default=*/true);
Opts.ShowFixits = !Args.hasArg(OPT_fno_diagnostics_fixit_info);
Opts.ShowLocation = !Args.hasArg(OPT_fno_show_source_location);
- Opts.ShowOptionNames = Args.hasArg(OPT_fdiagnostics_show_option);
+ Opts.AbsolutePath = Args.hasArg(OPT_fdiagnostics_absolute_paths);
+ Opts.ShowOptionNames =
+ Args.hasFlag(OPT_fdiagnostics_show_option,
+ OPT_fno_diagnostics_show_option, DefaultShowOpt);
llvm::sys::Process::UseANSIEscapeCodes(Args.hasArg(OPT_fansi_escape_codes));
@@ -1066,7 +1111,8 @@ static bool parseTestModuleFileExtensionArg(StringRef Arg,
}
static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
- DiagnosticsEngine &Diags) {
+ DiagnosticsEngine &Diags,
+ bool &IsHeaderFile) {
using namespace options;
Opts.ProgramAction = frontend::ParseSyntaxOnly;
if (const Arg *A = Args.getLastArg(OPT_Action_Group)) {
@@ -1107,6 +1153,8 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
Opts.ProgramAction = frontend::FixIt; break;
case OPT_emit_module:
Opts.ProgramAction = frontend::GenerateModule; break;
+ case OPT_emit_module_interface:
+ Opts.ProgramAction = frontend::GenerateModuleInterface; break;
case OPT_emit_pch:
Opts.ProgramAction = frontend::GeneratePCH; break;
case OPT_emit_pth:
@@ -1216,6 +1264,7 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
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,
OPT_arcmt_modify,
@@ -1286,11 +1335,13 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
.Case("cl", IK_OpenCL)
.Case("cuda", IK_CUDA)
.Case("c++", IK_CXX)
+ .Case("c++-module", IK_CXX)
.Case("objective-c", IK_ObjC)
.Case("objective-c++", IK_ObjCXX)
.Case("cpp-output", IK_PreprocessedC)
.Case("assembler-with-cpp", IK_Asm)
.Case("c++-cpp-output", IK_PreprocessedCXX)
+ .Case("c++-module-cpp-output", IK_PreprocessedCXX)
.Case("cuda-cpp-output", IK_PreprocessedCuda)
.Case("objective-c-cpp-output", IK_PreprocessedObjC)
.Case("objc-cpp-output", IK_PreprocessedObjC)
@@ -1308,6 +1359,13 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
if (DashX == IK_None)
Diags.Report(diag::err_drv_invalid_value)
<< A->getAsString(Args) << A->getValue();
+ IsHeaderFile = llvm::StringSwitch<bool>(A->getValue())
+ .Case("c-header", true)
+ .Case("cl-header", true)
+ .Case("objective-c-header", true)
+ .Case("c++-header", true)
+ .Case("objective-c++-header", true)
+ .Default(false);
}
// '-' is the default input if none is given.
@@ -1360,7 +1418,11 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) {
Opts.ResourceDir = Args.getLastArgValue(OPT_resource_dir);
Opts.ModuleCachePath = Args.getLastArgValue(OPT_fmodules_cache_path);
Opts.ModuleUserBuildPath = Args.getLastArgValue(OPT_fmodules_user_build_path);
+ for (const Arg *A : Args.filtered(OPT_fprebuilt_module_path))
+ Opts.AddPrebuiltModulePath(A->getValue());
Opts.DisableModuleHash = Args.hasArg(OPT_fdisable_module_hash);
+ Opts.ModulesValidateDiagnosticOptions =
+ !Args.hasArg(OPT_fmodules_disable_diagnostic_validation);
Opts.ImplicitModuleMaps = Args.hasArg(OPT_fimplicit_module_maps);
Opts.ModuleMapFileHomeIsCwd = Args.hasArg(OPT_fmodule_map_file_home_is_cwd);
Opts.ModuleCachePruneInterval =
@@ -1378,7 +1440,8 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) {
for (const Arg *A : Args.filtered(OPT_fmodules_ignore_macro)) {
StringRef MacroDef = A->getValue();
- Opts.ModulesIgnoreMacros.insert(MacroDef.split('=').first);
+ Opts.ModulesIgnoreMacros.insert(
+ llvm::CachedHashString(MacroDef.split('=').first));
}
// Add -I..., -F..., and -index-header-map options in order.
@@ -1405,7 +1468,7 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) {
Path = Buffer.str();
}
- Opts.AddPath(Path.c_str(), Group, IsFramework,
+ Opts.AddPath(Path, Group, IsFramework,
/*IgnoreSysroot*/ true);
IsIndexHeaderMap = false;
}
@@ -1461,7 +1524,7 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) {
Opts.AddVFSOverlayFile(A->getValue());
}
-bool isOpenCL(LangStandard::Kind LangStd) {
+static bool isOpenCL(LangStandard::Kind LangStd) {
return LangStd == LangStandard::lang_opencl ||
LangStd == LangStandard::lang_opencl11 ||
LangStd == LangStandard::lang_opencl12 ||
@@ -1501,14 +1564,16 @@ void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK,
case IK_Asm:
case IK_C:
case IK_PreprocessedC:
- case IK_ObjC:
- case IK_PreprocessedObjC:
// The PS4 uses C99 as the default C standard.
if (T.isPS4())
LangStd = LangStandard::lang_gnu99;
else
LangStd = LangStandard::lang_gnu11;
break;
+ case IK_ObjC:
+ case IK_PreprocessedObjC:
+ LangStd = LangStandard::lang_gnu11;
+ break;
case IK_CXX:
case IK_PreprocessedCXX:
case IK_ObjCXX:
@@ -1582,6 +1647,8 @@ void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK,
Opts.GNUKeywords = Opts.GNUMode;
Opts.CXXOperatorNames = Opts.CPlusPlus;
+ Opts.AlignedAllocation = Opts.CPlusPlus1z;
+
Opts.DollarIdents = !Opts.AsmPreprocessor;
}
@@ -1871,13 +1938,14 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.Blocks = Args.hasArg(OPT_fblocks) || (Opts.OpenCL
&& Opts.OpenCLVersion >= 200);
Opts.BlocksRuntimeOptional = Args.hasArg(OPT_fblocks_runtime_optional);
- Opts.Coroutines = Args.hasArg(OPT_fcoroutines);
- Opts.Modules = Args.hasArg(OPT_fmodules);
+ Opts.CoroutinesTS = Args.hasArg(OPT_fcoroutines_ts);
+ Opts.ModulesTS = Args.hasArg(OPT_fmodules_ts);
+ Opts.Modules = Args.hasArg(OPT_fmodules) || Opts.ModulesTS;
Opts.ModulesStrictDeclUse = Args.hasArg(OPT_fmodules_strict_decluse);
Opts.ModulesDeclUse =
Args.hasArg(OPT_fmodules_decluse) || Opts.ModulesStrictDeclUse;
Opts.ModulesLocalVisibility =
- Args.hasArg(OPT_fmodules_local_submodule_visibility);
+ Args.hasArg(OPT_fmodules_local_submodule_visibility) || Opts.ModulesTS;
Opts.ModulesSearchAll = Opts.Modules &&
!Args.hasArg(OPT_fno_modules_search_all) &&
Args.hasArg(OPT_fmodules_search_all);
@@ -1892,14 +1960,27 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
if (!Opts.NoBuiltin)
getAllNoBuiltinFuncValues(Args, Opts.NoBuiltinFuncs);
Opts.NoMathBuiltin = Args.hasArg(OPT_fno_math_builtin);
+ Opts.RelaxedTemplateTemplateArgs =
+ Args.hasArg(OPT_frelaxed_template_template_args);
Opts.SizedDeallocation = Args.hasArg(OPT_fsized_deallocation);
+ Opts.AlignedAllocation =
+ Args.hasFlag(OPT_faligned_allocation, OPT_fno_aligned_allocation,
+ Opts.AlignedAllocation);
+ Opts.NewAlignOverride =
+ getLastArgIntValue(Args, OPT_fnew_alignment_EQ, 0, Diags);
+ if (Opts.NewAlignOverride && !llvm::isPowerOf2_32(Opts.NewAlignOverride)) {
+ Arg *A = Args.getLastArg(OPT_fnew_alignment_EQ);
+ Diags.Report(diag::err_fe_invalid_alignment) << A->getAsString(Args)
+ << A->getValue();
+ Opts.NewAlignOverride = 0;
+ }
Opts.ConceptsTS = Args.hasArg(OPT_fconcepts_ts);
Opts.HeinousExtensions = Args.hasArg(OPT_fheinous_gnu_extensions);
Opts.AccessControl = !Args.hasArg(OPT_fno_access_control);
Opts.ElideConstructors = !Args.hasArg(OPT_fno_elide_constructors);
Opts.MathErrno = !Opts.OpenCL && Args.hasArg(OPT_fmath_errno);
Opts.InstantiationDepth =
- getLastArgIntValue(Args, OPT_ftemplate_depth, 256, Diags);
+ getLastArgIntValue(Args, OPT_ftemplate_depth, 1024, Diags);
Opts.ArrowDepth =
getLastArgIntValue(Args, OPT_foperator_arrow_depth, 256, Diags);
Opts.ConstexprCallDepth =
@@ -1955,9 +2036,10 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
// enabled for Microsoft Extensions or Borland Extensions, here.
//
// FIXME: __declspec is also currently enabled for CUDA, but isn't really a
- // CUDA extension, however it is required for supporting cuda_builtin_vars.h,
- // which uses __declspec(property). Once that has been rewritten in terms of
- // something more generic, remove the Opts.CUDA term here.
+ // CUDA extension. However, it is required for supporting
+ // __clang_cuda_builtin_vars.h, which uses __declspec(property). Once that has
+ // been rewritten in terms of something more generic, remove the Opts.CUDA
+ // term here.
Opts.DeclSpecKeyword =
Args.hasFlag(OPT_fdeclspec, OPT_fno_declspec,
(Opts.MicrosoftExt || Opts.Borland || Opts.CUDA));
@@ -2115,7 +2197,12 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
// This is the __NO_INLINE__ define, which just depends on things like the
// optimization level and -fno-inline, not actually whether the backend has
// inlining enabled.
- Opts.NoInlineDefine = !Opt || Args.hasArg(OPT_fno_inline);
+ Opts.NoInlineDefine = !Opts.Optimize;
+ if (Arg *InlineArg = Args.getLastArg(
+ options::OPT_finline_functions, options::OPT_finline_hint_functions,
+ options::OPT_fno_inline_functions, options::OPT_fno_inline))
+ if (InlineArg->getOption().matches(options::OPT_fno_inline))
+ Opts.NoInlineDefine = true;
Opts.FastMath = Args.hasArg(OPT_ffast_math) ||
Args.hasArg(OPT_cl_fast_relaxed_math);
@@ -2245,6 +2332,7 @@ static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts,
case frontend::EmitObj:
case frontend::FixIt:
case frontend::GenerateModule:
+ case frontend::GenerateModuleInterface:
case frontend::GeneratePCH:
case frontend::GeneratePTH:
case frontend::ParseSyntaxOnly:
@@ -2274,6 +2362,7 @@ static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts,
Opts.ShowLineMarkers = !Args.hasArg(OPT_P);
Opts.ShowMacroComments = Args.hasArg(OPT_CC);
Opts.ShowMacros = Args.hasArg(OPT_dM) || Args.hasArg(OPT_dD);
+ Opts.ShowIncludeDirectives = Args.hasArg(OPT_dI);
Opts.RewriteIncludes = Args.hasArg(OPT_frewrite_includes);
Opts.UseLineDirectives = Args.hasArg(OPT_fuse_line_directives);
}
@@ -2305,6 +2394,7 @@ static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args,
// Use the default target triple if unspecified.
if (Opts.Triple.empty())
Opts.Triple = llvm::sys::getDefaultTargetTriple();
+ Opts.OpenCLExtensionsAsWritten = Args.getAllArgValues(OPT_cl_ext_EQ);
}
bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
@@ -2338,12 +2428,14 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
Success &= ParseAnalyzerArgs(*Res.getAnalyzerOpts(), Args, Diags);
Success &= ParseMigratorArgs(Res.getMigratorOpts(), Args);
ParseDependencyOutputArgs(Res.getDependencyOutputOpts(), Args);
- Success &= ParseDiagnosticArgs(Res.getDiagnosticOpts(), Args, &Diags,
- false /*DefaultDiagColor*/);
+ Success &=
+ ParseDiagnosticArgs(Res.getDiagnosticOpts(), Args, &Diags,
+ false /*DefaultDiagColor*/, false /*DefaultShowOpt*/);
ParseCommentArgs(LangOpts.CommentOpts, Args);
ParseFileSystemArgs(Res.getFileSystemOpts(), Args);
// FIXME: We shouldn't have to pass the DashX option around here
- InputKind DashX = ParseFrontendArgs(Res.getFrontendOpts(), Args, Diags);
+ InputKind DashX = ParseFrontendArgs(Res.getFrontendOpts(), Args, Diags,
+ LangOpts.IsHeaderFile);
ParseTargetArgs(Res.getTargetOpts(), Args, Diags);
Success &= ParseCodeGenArgs(Res.getCodeGenOpts(), Args, DashX, Diags,
Res.getTargetOpts());
@@ -2394,6 +2486,13 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
ParsePreprocessorArgs(Res.getPreprocessorOpts(), Args, FileMgr, Diags);
ParsePreprocessorOutputArgs(Res.getPreprocessorOutputOpts(), Args,
Res.getFrontendOpts().ProgramAction);
+
+ // Turn on -Wspir-compat for SPIR target.
+ llvm::Triple T(Res.getTargetOpts().Triple);
+ auto Arch = T.getArch();
+ if (Arch == llvm::Triple::spir || Arch == llvm::Triple::spir64) {
+ Res.getDiagnosticOpts().Warnings.push_back("spir-compat");
+ }
return Success;
}
@@ -2441,7 +2540,8 @@ std::string CompilerInvocation::getModuleHash() const {
if (!hsOpts.ModulesIgnoreMacros.empty()) {
// Check whether we're ignoring this macro.
StringRef MacroDef = I->first;
- if (hsOpts.ModulesIgnoreMacros.count(MacroDef.split('=').first))
+ if (hsOpts.ModulesIgnoreMacros.count(
+ llvm::CachedHashString(MacroDef.split('=').first)))
continue;
}
@@ -2455,7 +2555,8 @@ std::string CompilerInvocation::getModuleHash() const {
hsOpts.UseBuiltinIncludes,
hsOpts.UseStandardSystemIncludes,
hsOpts.UseStandardCXXIncludes,
- hsOpts.UseLibcxx);
+ hsOpts.UseLibcxx,
+ hsOpts.ModulesValidateDiagnosticOptions);
code = hash_combine(code, hsOpts.ResourceDir);
// Extend the signature with the user build path.
diff --git a/lib/Frontend/DependencyFile.cpp b/lib/Frontend/DependencyFile.cpp
index a9b61282378d..059f116a3c31 100644
--- a/lib/Frontend/DependencyFile.cpp
+++ b/lib/Frontend/DependencyFile.cpp
@@ -409,9 +409,8 @@ void DFGImpl::OutputDependencyFile() {
const unsigned MaxColumns = 75;
unsigned Columns = 0;
- for (std::vector<std::string>::iterator
- I = Targets.begin(), E = Targets.end(); I != E; ++I) {
- unsigned N = I->length();
+ for (StringRef Target : Targets) {
+ unsigned N = Target.size();
if (Columns == 0) {
Columns += N;
} else if (Columns + N + 2 > MaxColumns) {
@@ -422,7 +421,7 @@ void DFGImpl::OutputDependencyFile() {
OS << ' ';
}
// Targets already quoted as needed.
- OS << *I;
+ OS << Target;
}
OS << ':';
@@ -430,18 +429,17 @@ void DFGImpl::OutputDependencyFile() {
// Now add each dependency in the order it was seen, but avoiding
// duplicates.
- for (std::vector<std::string>::iterator I = Files.begin(),
- E = Files.end(); I != E; ++I) {
+ for (StringRef File : Files) {
// Start a new line if this would exceed the column limit. Make
// sure to leave space for a trailing " \" in case we need to
// break the line on the next iteration.
- unsigned N = I->length();
+ unsigned N = File.size();
if (Columns + (N + 1) + 2 > MaxColumns) {
OS << " \\\n ";
Columns = 2;
}
OS << ' ';
- PrintFilename(OS, *I, OutputFormat);
+ PrintFilename(OS, File, OutputFormat);
Columns += N + 1;
}
OS << '\n';
@@ -449,10 +447,9 @@ void DFGImpl::OutputDependencyFile() {
// Create phony targets if requested.
if (PhonyTarget && !Files.empty()) {
// Skip the first entry, this is always the input file itself.
- for (std::vector<std::string>::iterator I = Files.begin() + 1,
- E = Files.end(); I != E; ++I) {
+ for (StringRef File : Files) {
OS << '\n';
- PrintFilename(OS, *I, OutputFormat);
+ PrintFilename(OS, File, OutputFormat);
OS << ":\n";
}
}
diff --git a/lib/Frontend/DiagnosticRenderer.cpp b/lib/Frontend/DiagnosticRenderer.cpp
index 586d2e6167b3..177feac97441 100644
--- a/lib/Frontend/DiagnosticRenderer.cpp
+++ b/lib/Frontend/DiagnosticRenderer.cpp
@@ -9,7 +9,6 @@
#include "clang/Frontend/DiagnosticRenderer.h"
#include "clang/Basic/DiagnosticOptions.h"
-#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Edit/Commit.h"
#include "clang/Edit/EditedSource.h"
@@ -18,7 +17,6 @@
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
using namespace clang;
diff --git a/lib/Frontend/FrontendAction.cpp b/lib/Frontend/FrontendAction.cpp
index d514d406d8b6..e871b310302d 100644
--- a/lib/Frontend/FrontendAction.cpp
+++ b/lib/Frontend/FrontendAction.cpp
@@ -20,19 +20,20 @@
#include "clang/Frontend/Utils.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Parse/ParseAST.h"
#include "clang/Serialization/ASTDeserializationListener.h"
#include "clang/Serialization/ASTReader.h"
#include "clang/Serialization/GlobalModuleIndex.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
#include <system_error>
using namespace clang;
-template class llvm::Registry<clang::PluginASTAction>;
+LLVM_INSTANTIATE_REGISTRY(FrontendPluginRegistry)
namespace {
@@ -287,14 +288,15 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
SmallString<128> DirNative;
llvm::sys::path::native(PCHDir->getName(), DirNative);
bool Found = false;
- for (llvm::sys::fs::directory_iterator Dir(DirNative, EC), DirEnd;
+ vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem();
+ for (vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), DirEnd;
Dir != DirEnd && !EC; Dir.increment(EC)) {
// Check whether this is an acceptable AST file.
if (ASTReader::isAcceptableASTFile(
- Dir->path(), FileMgr, CI.getPCHContainerReader(),
+ Dir->getName(), FileMgr, CI.getPCHContainerReader(),
CI.getLangOpts(), CI.getTargetOpts(), CI.getPreprocessorOpts(),
SpecificModuleCachePath)) {
- PPOpts.ImplicitPCHInclude = Dir->path();
+ PPOpts.ImplicitPCHInclude = Dir->getName();
Found = true;
break;
}
diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp
index b1e806add8cc..eb91940cbbfc 100644
--- a/lib/Frontend/FrontendActions.cpp
+++ b/lib/Frontend/FrontendActions.cpp
@@ -11,19 +11,18 @@
#include "clang/AST/ASTConsumer.h"
#include "clang/Basic/FileManager.h"
#include "clang/Frontend/ASTConsumers.h"
-#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/MultiplexConsumer.h"
#include "clang/Frontend/Utils.h"
#include "clang/Lex/HeaderSearch.h"
-#include "clang/Lex/Pragma.h"
#include "clang/Lex/Preprocessor.h"
-#include "clang/Parse/Parser.h"
+#include "clang/Lex/PreprocessorOptions.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 <memory>
#include <system_error>
@@ -92,7 +91,7 @@ GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
auto Buffer = std::make_shared<PCHBuffer>();
std::vector<std::unique_ptr<ASTConsumer>> Consumers;
Consumers.push_back(llvm::make_unique<PCHGenerator>(
- CI.getPreprocessor(), OutputFile, nullptr, Sysroot,
+ CI.getPreprocessor(), OutputFile, Sysroot,
Buffer, CI.getFrontendOpts().ModuleFileExtensions,
/*AllowASTWithErrors*/false,
/*IncludeTimestamps*/
@@ -131,18 +130,18 @@ GeneratePCHAction::ComputeASTConsumerArguments(CompilerInstance &CI,
std::unique_ptr<ASTConsumer>
GenerateModuleAction::CreateASTConsumer(CompilerInstance &CI,
StringRef InFile) {
- std::string Sysroot;
- std::string OutputFile;
- std::unique_ptr<raw_pwrite_stream> OS =
- ComputeASTConsumerArguments(CI, InFile, Sysroot, OutputFile);
+ std::unique_ptr<raw_pwrite_stream> OS = CreateOutputFile(CI, InFile);
if (!OS)
return nullptr;
+ std::string OutputFile = CI.getFrontendOpts().OutputFile;
+ std::string Sysroot;
+
auto Buffer = std::make_shared<PCHBuffer>();
std::vector<std::unique_ptr<ASTConsumer>> Consumers;
Consumers.push_back(llvm::make_unique<PCHGenerator>(
- CI.getPreprocessor(), OutputFile, Module, Sysroot,
+ CI.getPreprocessor(), OutputFile, Sysroot,
Buffer, CI.getFrontendOpts().ModuleFileExtensions,
/*AllowASTWithErrors=*/false,
/*IncludeTimestamps=*/
@@ -152,6 +151,23 @@ GenerateModuleAction::CreateASTConsumer(CompilerInstance &CI,
return llvm::make_unique<MultiplexConsumer>(std::move(Consumers));
}
+bool GenerateModuleAction::BeginSourceFileAction(CompilerInstance &CI,
+ StringRef Filename) {
+ // Set up embedding for any specified files. Do this before we load any
+ // source files, including the primary module map for the compilation.
+ for (const auto &F : CI.getFrontendOpts().ModulesEmbedFiles) {
+ if (const auto *FE = CI.getFileManager().getFile(F, /*openFile*/true))
+ CI.getSourceManager().setFileIsTransient(FE);
+ else
+ CI.getDiagnostics().Report(diag::err_modules_embed_file_not_found) << F;
+ }
+ if (CI.getFrontendOpts().ModulesEmbedAllFiles)
+ CI.getSourceManager().setAllFilesAreTransient(true);
+
+ return true;
+}
+
+
static SmallVectorImpl<char> &
operator+=(SmallVectorImpl<char> &Includes, StringRef RHS) {
Includes.append(RHS.begin(), RHS.end());
@@ -267,9 +283,12 @@ collectModuleHeaderIncludes(const LangOptions &LangOpts, FileManager &FileMgr,
return std::error_code();
}
-bool GenerateModuleAction::BeginSourceFileAction(CompilerInstance &CI,
- StringRef Filename) {
- CI.getLangOpts().CompilingModule = true;
+bool GenerateModuleFromModuleMapAction::BeginSourceFileAction(
+ CompilerInstance &CI, StringRef Filename) {
+ CI.getLangOpts().setCompilingModule(LangOptions::CMK_ModuleMap);
+
+ if (!GenerateModuleAction::BeginSourceFileAction(CI, Filename))
+ return false;
// Find the module map file.
const FileEntry *ModuleMap =
@@ -280,17 +299,6 @@ bool GenerateModuleAction::BeginSourceFileAction(CompilerInstance &CI,
return false;
}
- // Set up embedding for any specified files. Do this before we load any
- // source files, including the primary module map for the compilation.
- for (const auto &F : CI.getFrontendOpts().ModulesEmbedFiles) {
- if (const auto *FE = CI.getFileManager().getFile(F, /*openFile*/true))
- CI.getSourceManager().setFileIsTransient(FE);
- else
- CI.getDiagnostics().Report(diag::err_modules_embed_file_not_found) << F;
- }
- if (CI.getFrontendOpts().ModulesEmbedAllFiles)
- CI.getSourceManager().setAllFilesAreTransient(true);
-
// Parse the module map file.
HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo();
if (HS.loadModuleMapFile(ModuleMap, IsSystem))
@@ -382,32 +390,43 @@ bool GenerateModuleAction::BeginSourceFileAction(CompilerInstance &CI,
}
std::unique_ptr<raw_pwrite_stream>
-GenerateModuleAction::ComputeASTConsumerArguments(CompilerInstance &CI,
- StringRef InFile,
- std::string &Sysroot,
- std::string &OutputFile) {
+GenerateModuleFromModuleMapAction::CreateOutputFile(CompilerInstance &CI,
+ StringRef InFile) {
// If no output file was provided, figure out where this module would go
// in the module cache.
if (CI.getFrontendOpts().OutputFile.empty()) {
HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo();
CI.getFrontendOpts().OutputFile =
HS.getModuleFileName(CI.getLangOpts().CurrentModule,
- ModuleMapForUniquing->getName());
+ ModuleMapForUniquing->getName(),
+ /*UsePrebuiltPath=*/false);
}
// We use createOutputFile here because this is exposed via libclang, and we
// must disable the RemoveFileOnSignal behavior.
// We use a temporary to avoid race conditions.
- std::unique_ptr<raw_pwrite_stream> OS =
- CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true,
- /*RemoveFileOnSignal=*/false, InFile,
- /*Extension=*/"", /*useTemporary=*/true,
- /*CreateMissingDirectories=*/true);
- if (!OS)
- return nullptr;
+ return CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true,
+ /*RemoveFileOnSignal=*/false, InFile,
+ /*Extension=*/"", /*useTemporary=*/true,
+ /*CreateMissingDirectories=*/true);
+}
- OutputFile = CI.getFrontendOpts().OutputFile;
- return OS;
+bool GenerateModuleInterfaceAction::BeginSourceFileAction(CompilerInstance &CI,
+ StringRef Filename) {
+ if (!CI.getLangOpts().ModulesTS) {
+ CI.getDiagnostics().Report(diag::err_module_interface_requires_modules_ts);
+ return false;
+ }
+
+ CI.getLangOpts().setCompilingModule(LangOptions::CMK_ModuleInterface);
+
+ return GenerateModuleAction::BeginSourceFileAction(CI, Filename);
+}
+
+std::unique_ptr<raw_pwrite_stream>
+GenerateModuleInterfaceAction::CreateOutputFile(CompilerInstance &CI,
+ StringRef InFile) {
+ return CI.createDefaultOutputFile(/*Binary=*/true, InFile, "pcm");
}
SyntaxOnlyAction::~SyntaxOnlyAction() {
@@ -597,6 +616,13 @@ namespace {
};
}
+bool DumpModuleInfoAction::BeginInvocation(CompilerInstance &CI) {
+ // The Object file reader also supports raw ast files and there is no point in
+ // being strict about the module file format in -module-file-info mode.
+ CI.getHeaderSearchOpts().ModuleFormat = "obj";
+ return true;
+}
+
void DumpModuleInfoAction::ExecuteAction() {
// Set up the output file.
std::unique_ptr<llvm::raw_fd_ostream> OutFile;
@@ -609,11 +635,21 @@ void DumpModuleInfoAction::ExecuteAction() {
llvm::raw_ostream &Out = OutFile.get()? *OutFile.get() : llvm::outs();
Out << "Information for module file '" << getCurrentFile() << "':\n";
+ auto &FileMgr = getCompilerInstance().getFileManager();
+ auto Buffer = FileMgr.getBufferForFile(getCurrentFile());
+ StringRef Magic = (*Buffer)->getMemBufferRef().getBuffer();
+ bool IsRaw = (Magic.size() >= 4 && Magic[0] == 'C' && Magic[1] == 'P' &&
+ Magic[2] == 'C' && Magic[3] == 'H');
+ Out << " Module format: " << (IsRaw ? "raw" : "obj") << "\n";
+
+ Preprocessor &PP = getCompilerInstance().getPreprocessor();
DumpModuleInfoListener Listener(Out);
+ HeaderSearchOptions &HSOpts =
+ PP.getHeaderSearchInfo().getHeaderSearchOpts();
ASTReader::readASTFileControlBlock(
- getCurrentFile(), getCompilerInstance().getFileManager(),
- getCompilerInstance().getPCHContainerReader(),
- /*FindModuleFileExtensions=*/true, Listener);
+ getCurrentFile(), FileMgr, getCompilerInstance().getPCHContainerReader(),
+ /*FindModuleFileExtensions=*/true, Listener,
+ HSOpts.ModulesValidateDiagnosticOptions);
}
//===----------------------------------------------------------------------===//
diff --git a/lib/Frontend/FrontendOptions.cpp b/lib/Frontend/FrontendOptions.cpp
index 9ede674e47ea..6a82084aff1b 100644
--- a/lib/Frontend/FrontendOptions.cpp
+++ b/lib/Frontend/FrontendOptions.cpp
@@ -25,6 +25,8 @@ InputKind FrontendOptions::getInputKindForExtension(StringRef Extension) {
.Case("mii", IK_PreprocessedObjCXX)
.Cases("C", "cc", "cp", IK_CXX)
.Cases("cpp", "CPP", "c++", "cxx", "hpp", IK_CXX)
+ .Case("cppm", IK_CXX)
+ .Case("iim", IK_PreprocessedCXX)
.Case("cl", IK_OpenCL)
.Case("cu", IK_CUDA)
.Cases("ll", "bc", IK_LLVM_IR)
diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp
index 1b5c760f01b5..d50fb6d788a4 100644
--- a/lib/Frontend/InitHeaderSearch.cpp
+++ b/lib/Frontend/InitHeaderSearch.cpp
@@ -11,10 +11,10 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Frontend/Utils.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Config/config.h" // C_INCLUDE_DIRS
+#include "clang/Frontend/Utils.h"
#include "clang/Lex/HeaderMap.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/HeaderSearchOptions.h"
@@ -25,7 +25,6 @@
#include "llvm/ADT/Triple.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
@@ -527,7 +526,7 @@ static unsigned RemoveDuplicates(std::vector<DirectoryLookup> &SearchList,
if (CurEntry.getDirCharacteristic() != SrcMgr::C_User) {
// Find the dir that this is the same of.
unsigned FirstDir;
- for (FirstDir = 0; ; ++FirstDir) {
+ for (FirstDir = First;; ++FirstDir) {
assert(FirstDir != i && "Didn't find dupe?");
const DirectoryLookup &SearchEntry = SearchList[FirstDir];
@@ -626,7 +625,7 @@ void InitHeaderSearch::Realize(const LangOptions &Lang) {
for (unsigned i = 0, e = SearchList.size(); i != e; ++i) {
if (i == NumQuoted)
llvm::errs() << "#include <...> search starts here:\n";
- const char *Name = SearchList[i].getName();
+ StringRef Name = SearchList[i].getName();
const char *Suffix;
if (SearchList[i].isNormalDir())
Suffix = "";
diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp
index 6b93c697d9b1..17603ada11d1 100644
--- a/lib/Frontend/InitPreprocessor.cpp
+++ b/lib/Frontend/InitPreprocessor.cpp
@@ -11,7 +11,6 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Frontend/Utils.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/MacroBuilder.h"
#include "clang/Basic/SourceManager.h"
@@ -19,15 +18,13 @@
#include "clang/Basic/Version.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/FrontendOptions.h"
+#include "clang/Frontend/Utils.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/PTHManager.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Serialization/ASTReader.h"
#include "llvm/ADT/APFloat.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/Path.h"
using namespace clang;
static bool MacroBodyEndsInBackslash(StringRef MacroBody) {
@@ -115,15 +112,15 @@ template <typename T>
static T PickFP(const llvm::fltSemantics *Sem, T IEEESingleVal,
T IEEEDoubleVal, T X87DoubleExtendedVal, T PPCDoubleDoubleVal,
T IEEEQuadVal) {
- if (Sem == (const llvm::fltSemantics*)&llvm::APFloat::IEEEsingle)
+ if (Sem == (const llvm::fltSemantics*)&llvm::APFloat::IEEEsingle())
return IEEESingleVal;
- if (Sem == (const llvm::fltSemantics*)&llvm::APFloat::IEEEdouble)
+ if (Sem == (const llvm::fltSemantics*)&llvm::APFloat::IEEEdouble())
return IEEEDoubleVal;
- if (Sem == (const llvm::fltSemantics*)&llvm::APFloat::x87DoubleExtended)
+ if (Sem == (const llvm::fltSemantics*)&llvm::APFloat::x87DoubleExtended())
return X87DoubleExtendedVal;
- if (Sem == (const llvm::fltSemantics*)&llvm::APFloat::PPCDoubleDouble)
+ if (Sem == (const llvm::fltSemantics*)&llvm::APFloat::PPCDoubleDouble())
return PPCDoubleDoubleVal;
- assert(Sem == (const llvm::fltSemantics*)&llvm::APFloat::IEEEquad);
+ assert(Sem == (const llvm::fltSemantics*)&llvm::APFloat::IEEEquad());
return IEEEQuadVal;
}
@@ -395,6 +392,15 @@ static void InitializeStandardPredefinedMacros(const TargetInfo &TI,
// C++ translation unit.
else
Builder.defineMacro("__cplusplus", "199711L");
+
+ // C++1z [cpp.predefined]p1:
+ // An integer literal of type std::size_t whose value is the alignment
+ // guaranteed by a call to operator new(std::size_t)
+ //
+ // We provide this in all language modes, since it seems generally useful.
+ Builder.defineMacro("__STDCPP_DEFAULT_NEW_ALIGNMENT__",
+ Twine(TI.getNewAlign() / TI.getCharWidth()) +
+ TI.getTypeConstantSuffix(TI.getSizeType()));
}
// In C11 these are environment macros. In C++11 they are only defined
@@ -438,6 +444,9 @@ static void InitializeStandardPredefinedMacros(const TargetInfo &TI,
Builder.defineMacro("CL_VERSION_1_2", "120");
Builder.defineMacro("CL_VERSION_2_0", "200");
+ if (TI.isLittleEndian())
+ Builder.defineMacro("__ENDIAN_LITTLE__");
+
if (LangOpts.FastRelaxedMath)
Builder.defineMacro("__FAST_RELAXED_MATH__");
}
@@ -467,8 +476,10 @@ static void InitializeCPlusPlusFeatureTestMacros(const LangOptions &LangOpts,
Builder.defineMacro("__cpp_lambdas", "200907");
Builder.defineMacro("__cpp_constexpr",
LangOpts.CPlusPlus14 ? "201304" : "200704");
- Builder.defineMacro("__cpp_range_based_for", "200907");
- Builder.defineMacro("__cpp_static_assert", "200410");
+ Builder.defineMacro("__cpp_range_based_for",
+ LangOpts.CPlusPlus1z ? "201603" : "200907");
+ Builder.defineMacro("__cpp_static_assert",
+ LangOpts.CPlusPlus1z ? "201411" : "200410");
Builder.defineMacro("__cpp_decltype", "200707");
Builder.defineMacro("__cpp_attributes", "200809");
Builder.defineMacro("__cpp_rvalue_references", "200610");
@@ -476,7 +487,7 @@ static void InitializeCPlusPlusFeatureTestMacros(const LangOptions &LangOpts,
Builder.defineMacro("__cpp_initializer_lists", "200806");
Builder.defineMacro("__cpp_delegating_constructors", "200604");
Builder.defineMacro("__cpp_nsdmi", "200809");
- Builder.defineMacro("__cpp_inheriting_constructors", "200802");
+ Builder.defineMacro("__cpp_inheriting_constructors", "201511");
Builder.defineMacro("__cpp_ref_qualifiers", "200710");
Builder.defineMacro("__cpp_alias_templates", "200704");
}
@@ -494,9 +505,31 @@ static void InitializeCPlusPlusFeatureTestMacros(const LangOptions &LangOpts,
}
if (LangOpts.SizedDeallocation)
Builder.defineMacro("__cpp_sized_deallocation", "201309");
+
+ // C++17 features.
+ if (LangOpts.CPlusPlus1z) {
+ 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_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");
+ }
+ if (LangOpts.AlignedAllocation)
+ Builder.defineMacro("__cpp_aligned_new", "201606");
+
+ // TS features.
if (LangOpts.ConceptsTS)
Builder.defineMacro("__cpp_experimental_concepts", "1");
- if (LangOpts.Coroutines)
+ if (LangOpts.CoroutinesTS)
Builder.defineMacro("__cpp_coroutines", "1");
}
@@ -511,16 +544,12 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
#define TOSTR(X) TOSTR2(X)
Builder.defineMacro("__clang_major__", TOSTR(CLANG_VERSION_MAJOR));
Builder.defineMacro("__clang_minor__", TOSTR(CLANG_VERSION_MINOR));
-#ifdef CLANG_VERSION_PATCHLEVEL
Builder.defineMacro("__clang_patchlevel__", TOSTR(CLANG_VERSION_PATCHLEVEL));
-#else
- Builder.defineMacro("__clang_patchlevel__", "0");
-#endif
+#undef TOSTR
+#undef TOSTR2
Builder.defineMacro("__clang_version__",
"\"" CLANG_VERSION_STRING " "
+ getClangFullRepositoryVersion() + "\"");
-#undef TOSTR
-#undef TOSTR2
if (!LangOpts.MSVCCompat) {
// Currently claim to be compatible with GCC 4.2.1-5621, but only if we're
// not compiling for MSVC compatibility
@@ -564,6 +593,9 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
Builder.defineMacro("OBJC_ZEROCOST_EXCEPTIONS");
}
+ Builder.defineMacro("__OBJC_BOOL_IS_BOOL",
+ Twine(TI.useSignedCharForObjCBool() ? "0" : "1"));
+
if (LangOpts.getGC() != LangOptions::NonGC)
Builder.defineMacro("__OBJC_GC__");
@@ -677,7 +709,7 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
// Define type sizing macros based on the target properties.
assert(TI.getCharWidth() == 8 && "Only support 8-bit char so far");
- Builder.defineMacro("__CHAR_BIT__", "8");
+ Builder.defineMacro("__CHAR_BIT__", Twine(TI.getCharWidth()));
DefineTypeSize("__SCHAR_MAX__", TargetInfo::SignedChar, TI, Builder);
DefineTypeSize("__SHRT_MAX__", TargetInfo::SignedShort, TI, Builder);
@@ -958,12 +990,20 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
// OpenCL definitions.
if (LangOpts.OpenCL) {
#define OPENCLEXT(Ext) \
- if (TI.getSupportedOpenCLOpts().is_##Ext##_supported( \
+ if (TI.getSupportedOpenCLOpts().isSupported(#Ext, \
LangOpts.OpenCLVersion)) \
Builder.defineMacro(#Ext);
#include "clang/Basic/OpenCLExtensions.def"
}
+ if (TI.hasInt128Type() && LangOpts.CPlusPlus && LangOpts.GNUMode) {
+ // For each extended integer type, g++ defines a macro mapping the
+ // index of the type (0 in this case) in some list of extended types
+ // to the type.
+ Builder.defineMacro("__GLIBCXX_TYPE_INT_N_0", "__int128");
+ Builder.defineMacro("__GLIBCXX_BITSIZE_INT_N_0", "128");
+ }
+
// Get other target #defines.
TI.getTargetDefines(LangOpts, Builder);
}
diff --git a/lib/Frontend/ModuleDependencyCollector.cpp b/lib/Frontend/ModuleDependencyCollector.cpp
index ca11f9b863bb..9b34d4211353 100644
--- a/lib/Frontend/ModuleDependencyCollector.cpp
+++ b/lib/Frontend/ModuleDependencyCollector.cpp
@@ -15,7 +15,6 @@
#include "clang/Frontend/Utils.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Serialization/ASTReader.h"
-#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
@@ -39,6 +38,24 @@ public:
}
};
+struct ModuleDependencyPPCallbacks : public PPCallbacks {
+ ModuleDependencyCollector &Collector;
+ SourceManager &SM;
+ ModuleDependencyPPCallbacks(ModuleDependencyCollector &Collector,
+ SourceManager &SM)
+ : Collector(Collector), SM(SM) {}
+
+ void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
+ StringRef FileName, bool IsAngled,
+ CharSourceRange FilenameRange, const FileEntry *File,
+ StringRef SearchPath, StringRef RelativePath,
+ const Module *Imported) override {
+ if (!File)
+ return;
+ Collector.addFile(File->getName());
+ }
+};
+
struct ModuleDependencyMMCallbacks : public ModuleMapCallbacks {
ModuleDependencyCollector &Collector;
ModuleDependencyMMCallbacks(ModuleDependencyCollector &Collector)
@@ -103,6 +120,8 @@ void ModuleDependencyCollector::attachToASTReader(ASTReader &R) {
}
void ModuleDependencyCollector::attachToPreprocessor(Preprocessor &PP) {
+ PP.addPPCallbacks(llvm::make_unique<ModuleDependencyPPCallbacks>(
+ *this, PP.getSourceManager()));
PP.getHeaderSearchInfo().getModuleMap().addModuleMapCallbacks(
llvm::make_unique<ModuleDependencyMMCallbacks>(*this));
}
@@ -135,6 +154,10 @@ void ModuleDependencyCollector::writeFileMap() {
// allows crash reproducer scripts to work across machines.
VFSWriter.setOverlayDir(VFSDir);
+ // Do not ignore non existent contents otherwise we might skip something
+ // that should have been collected here.
+ VFSWriter.setIgnoreNonExistentContents(false);
+
// Explicitly set case sensitivity for the YAML writer. For that, find out
// the sensitivity at the path where the headers all collected to.
VFSWriter.setCaseSensitivity(isCaseSensitivePath(VFSDir));
@@ -178,7 +201,8 @@ bool ModuleDependencyCollector::getRealPath(StringRef SrcPath,
return true;
}
-std::error_code ModuleDependencyCollector::copyToRoot(StringRef Src) {
+std::error_code ModuleDependencyCollector::copyToRoot(StringRef Src,
+ StringRef Dst) {
using namespace llvm::sys;
// We need an absolute src path to append to the root.
@@ -190,23 +214,35 @@ std::error_code ModuleDependencyCollector::copyToRoot(StringRef Src) {
AbsoluteSrc = path::remove_leading_dotslash(AbsoluteSrc);
// Canonicalize the source path by removing "..", "." components.
- SmallString<256> CanonicalPath = AbsoluteSrc;
- path::remove_dots(CanonicalPath, /*remove_dot_dot=*/true);
+ SmallString<256> VirtualPath = AbsoluteSrc;
+ path::remove_dots(VirtualPath, /*remove_dot_dot=*/true);
// If a ".." component is present after a symlink component, remove_dots may
// lead to the wrong real destination path. Let the source be canonicalized
// like that but make sure we always use the real path for the destination.
- SmallString<256> RealPath;
- if (!getRealPath(AbsoluteSrc, RealPath))
- RealPath = CanonicalPath;
- SmallString<256> Dest = getDest();
- path::append(Dest, path::relative_path(RealPath));
+ SmallString<256> CopyFrom;
+ if (!getRealPath(AbsoluteSrc, CopyFrom))
+ CopyFrom = VirtualPath;
+ SmallString<256> CacheDst = getDest();
+
+ if (Dst.empty()) {
+ // The common case is to map the virtual path to the same path inside the
+ // cache.
+ path::append(CacheDst, path::relative_path(CopyFrom));
+ } else {
+ // When collecting entries from input vfsoverlays, copy the external
+ // contents into the cache but still map from the source.
+ if (!fs::exists(Dst))
+ return std::error_code();
+ path::append(CacheDst, Dst);
+ CopyFrom = Dst;
+ }
// Copy the file into place.
- if (std::error_code EC = fs::create_directories(path::parent_path(Dest),
- /*IgnoreExisting=*/true))
+ if (std::error_code EC = fs::create_directories(path::parent_path(CacheDst),
+ /*IgnoreExisting=*/true))
return EC;
- if (std::error_code EC = fs::copy_file(RealPath, Dest))
+ if (std::error_code EC = fs::copy_file(CopyFrom, CacheDst))
return EC;
// Always map a canonical src path to its real path into the YAML, by doing
@@ -214,12 +250,12 @@ std::error_code ModuleDependencyCollector::copyToRoot(StringRef Src) {
// overlay, which is a way to emulate symlink inside the VFS; this is also
// needed for correctness, not doing that can lead to module redifinition
// errors.
- addFileMapping(CanonicalPath, Dest);
+ addFileMapping(VirtualPath, CacheDst);
return std::error_code();
}
-void ModuleDependencyCollector::addFile(StringRef Filename) {
+void ModuleDependencyCollector::addFile(StringRef Filename, StringRef FileDst) {
if (insertSeen(Filename))
- if (copyToRoot(Filename))
+ if (copyToRoot(Filename, FileDst))
HasErrors = true;
}
diff --git a/lib/Frontend/MultiplexConsumer.cpp b/lib/Frontend/MultiplexConsumer.cpp
index 17cdaee4be05..8ef6df5e740d 100644
--- a/lib/Frontend/MultiplexConsumer.cpp
+++ b/lib/Frontend/MultiplexConsumer.cpp
@@ -120,6 +120,7 @@ public:
void CompletedImplicitDefinition(const FunctionDecl *D) override;
void StaticDataMemberInstantiated(const VarDecl *D) override;
void DefaultArgumentInstantiated(const ParmVarDecl *D) override;
+ void DefaultMemberInitializerInstantiated(const FieldDecl *D) override;
void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
const ObjCInterfaceDecl *IFD) override;
void FunctionDefinitionInstantiated(const FunctionDecl *D) override;
@@ -201,6 +202,11 @@ void MultiplexASTMutationListener::DefaultArgumentInstantiated(
for (size_t i = 0, e = Listeners.size(); i != e; ++i)
Listeners[i]->DefaultArgumentInstantiated(D);
}
+void MultiplexASTMutationListener::DefaultMemberInitializerInstantiated(
+ const FieldDecl *D) {
+ for (size_t i = 0, e = Listeners.size(); i != e; ++i)
+ Listeners[i]->DefaultMemberInitializerInstantiated(D);
+}
void MultiplexASTMutationListener::AddedObjCCategoryToInterface(
const ObjCCategoryDecl *CatD,
const ObjCInterfaceDecl *IFD) {
diff --git a/lib/Frontend/PCHContainerOperations.cpp b/lib/Frontend/PCHContainerOperations.cpp
index 2d4edde43280..eebebf327a19 100644
--- a/lib/Frontend/PCHContainerOperations.cpp
+++ b/lib/Frontend/PCHContainerOperations.cpp
@@ -58,10 +58,9 @@ std::unique_ptr<ASTConsumer> RawPCHContainerWriter::CreatePCHContainerGenerator(
return llvm::make_unique<RawPCHContainerGenerator>(std::move(OS), Buffer);
}
-void RawPCHContainerReader::ExtractPCH(
- llvm::MemoryBufferRef Buffer, llvm::BitstreamReader &StreamFile) const {
- StreamFile.init((const unsigned char *)Buffer.getBufferStart(),
- (const unsigned char *)Buffer.getBufferEnd());
+StringRef
+RawPCHContainerReader::ExtractPCH(llvm::MemoryBufferRef Buffer) const {
+ return Buffer.getBuffer();
}
PCHContainerOperations::PCHContainerOperations() {
diff --git a/lib/Frontend/PrintPreprocessedOutput.cpp b/lib/Frontend/PrintPreprocessedOutput.cpp
index 77b80e612fbf..d48b952ef203 100644
--- a/lib/Frontend/PrintPreprocessedOutput.cpp
+++ b/lib/Frontend/PrintPreprocessedOutput.cpp
@@ -93,13 +93,16 @@ private:
bool Initialized;
bool DisableLineMarkers;
bool DumpDefines;
+ bool DumpIncludeDirectives;
bool UseLineDirectives;
bool IsFirstFileEntered;
public:
PrintPPOutputPPCallbacks(Preprocessor &pp, raw_ostream &os, bool lineMarkers,
- bool defines, bool UseLineDirectives)
+ bool defines, bool DumpIncludeDirectives,
+ bool UseLineDirectives)
: PP(pp), SM(PP.getSourceManager()), ConcatInfo(PP), OS(os),
DisableLineMarkers(lineMarkers), DumpDefines(defines),
+ DumpIncludeDirectives(DumpIncludeDirectives),
UseLineDirectives(UseLineDirectives) {
CurLine = 0;
CurFilename += "<uninit>";
@@ -320,10 +323,10 @@ void PrintPPOutputPPCallbacks::InclusionDirective(SourceLocation HashLoc,
StringRef SearchPath,
StringRef RelativePath,
const Module *Imported) {
- // When preprocessing, turn implicit imports into @imports.
- // FIXME: This is a stop-gap until a more comprehensive "preprocessing with
- // modules" solution is introduced.
if (Imported) {
+ // When preprocessing, turn implicit imports into @imports.
+ // FIXME: This is a stop-gap until a more comprehensive "preprocessing with
+ // modules" solution is introduced.
startNewLineIfNeeded();
MoveToLine(HashLoc);
if (PP.getLangOpts().ObjC2) {
@@ -331,9 +334,9 @@ void PrintPPOutputPPCallbacks::InclusionDirective(SourceLocation HashLoc,
<< " /* clang -E: implicit import for \"" << File->getName()
<< "\" */";
} else {
- // FIXME: Preseve whether this was a
- // #include/#include_next/#include_macros/#import.
- OS << "#include "
+ const std::string TokenText = PP.getSpelling(IncludeTok);
+ assert(!TokenText.empty());
+ OS << "#" << TokenText << " "
<< (IsAngled ? '<' : '"')
<< FileName
<< (IsAngled ? '>' : '"')
@@ -344,6 +347,20 @@ void PrintPPOutputPPCallbacks::InclusionDirective(SourceLocation HashLoc,
// line immediately.
EmittedTokensOnThisLine = true;
startNewLineIfNeeded();
+ } else {
+ // Not a module import; it's a more vanilla inclusion of some file using one
+ // of: #include, #import, #include_next, #include_macros.
+ if (DumpIncludeDirectives) {
+ startNewLineIfNeeded();
+ MoveToLine(HashLoc);
+ const std::string TokenText = PP.getSpelling(IncludeTok);
+ assert(!TokenText.empty());
+ OS << "#" << TokenText << " "
+ << (IsAngled ? '<' : '"') << FileName << (IsAngled ? '>' : '"')
+ << " /* clang -E -dI */";
+ setEmittedDirectiveOnThisLine();
+ startNewLineIfNeeded();
+ }
}
}
@@ -751,7 +768,8 @@ void clang::DoPrintPreprocessedInput(Preprocessor &PP, raw_ostream *OS,
PP.SetCommentRetentionState(Opts.ShowComments, Opts.ShowMacroComments);
PrintPPOutputPPCallbacks *Callbacks = new PrintPPOutputPPCallbacks(
- PP, *OS, !Opts.ShowLineMarkers, Opts.ShowMacros, Opts.UseLineDirectives);
+ PP, *OS, !Opts.ShowLineMarkers, Opts.ShowMacros,
+ Opts.ShowIncludeDirectives, Opts.UseLineDirectives);
// Expand macros in pragmas with -fms-extensions. The assumption is that
// the majority of pragmas in such a file will be Microsoft pragmas.
diff --git a/lib/Frontend/Rewrite/FrontendActions.cpp b/lib/Frontend/Rewrite/FrontendActions.cpp
index 13d410e21381..2e76e2e3151e 100644
--- a/lib/Frontend/Rewrite/FrontendActions.cpp
+++ b/lib/Frontend/Rewrite/FrontendActions.cpp
@@ -9,13 +9,12 @@
#include "clang/Rewrite/Frontend/FrontendActions.h"
#include "clang/AST/ASTConsumer.h"
-#include "clang/Basic/FileManager.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/Utils.h"
#include "clang/Lex/Preprocessor.h"
-#include "clang/Parse/Parser.h"
+#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Rewrite/Frontend/ASTConsumers.h"
#include "clang/Rewrite/Frontend/FixItRewriter.h"
#include "clang/Rewrite/Frontend/Rewriters.h"
diff --git a/lib/Frontend/Rewrite/HTMLPrint.cpp b/lib/Frontend/Rewrite/HTMLPrint.cpp
index f5fad346124a..11e431de0a31 100644
--- a/lib/Frontend/Rewrite/HTMLPrint.cpp
+++ b/lib/Frontend/Rewrite/HTMLPrint.cpp
@@ -11,7 +11,6 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Rewrite/Frontend/ASTConsumers.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
@@ -21,7 +20,7 @@
#include "clang/Lex/Preprocessor.h"
#include "clang/Rewrite/Core/HTMLRewrite.h"
#include "clang/Rewrite/Core/Rewriter.h"
-#include "llvm/Support/MemoryBuffer.h"
+#include "clang/Rewrite/Frontend/ASTConsumers.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
@@ -65,7 +64,7 @@ void HTMLPrinter::HandleTranslationUnit(ASTContext &Ctx) {
// Format the file.
FileID FID = R.getSourceMgr().getMainFileID();
const FileEntry* Entry = R.getSourceMgr().getFileEntryForID(FID);
- const char* Name;
+ StringRef Name;
// In some cases, in particular the case where the input is from stdin,
// there is no entry. Fall back to the memory buffer for a name in those
// cases.
diff --git a/lib/Frontend/Rewrite/InclusionRewriter.cpp b/lib/Frontend/Rewrite/InclusionRewriter.cpp
index b761c34fcbde..d953da2e4fd2 100644
--- a/lib/Frontend/Rewrite/InclusionRewriter.cpp
+++ b/lib/Frontend/Rewrite/InclusionRewriter.cpp
@@ -68,7 +68,7 @@ private:
CharSourceRange FilenameRange, const FileEntry *File,
StringRef SearchPath, StringRef RelativePath,
const Module *Imported) override;
- void WriteLineInfo(const char *Filename, int Line,
+ void WriteLineInfo(StringRef Filename, int Line,
SrcMgr::CharacteristicKind FileType,
StringRef Extra = StringRef());
void WriteImplicitModuleImport(const Module *Mod);
@@ -102,7 +102,7 @@ InclusionRewriter::InclusionRewriter(Preprocessor &PP, raw_ostream &OS,
/// markers depending on what mode we're in, including the \p Filename and
/// \p Line we are located at, using the specified \p EOL line separator, and
/// any \p Extra context specifiers in GNU line directives.
-void InclusionRewriter::WriteLineInfo(const char *Filename, int Line,
+void InclusionRewriter::WriteLineInfo(StringRef Filename, int Line,
SrcMgr::CharacteristicKind FileType,
StringRef Extra) {
if (!ShowLineMarkers)
@@ -406,7 +406,7 @@ bool InclusionRewriter::Process(FileID FileId,
bool Invalid;
const MemoryBuffer &FromFile = *SM.getBuffer(FileId, &Invalid);
assert(!Invalid && "Attempting to process invalid inclusion");
- const char *FileName = FromFile.getBufferIdentifier();
+ StringRef FileName = FromFile.getBufferIdentifier();
Lexer RawLex(FileId, &FromFile, PP.getSourceManager(), PP.getLangOpts());
RawLex.SetCommentRetentionState(false);
diff --git a/lib/Frontend/Rewrite/RewriteModernObjC.cpp b/lib/Frontend/Rewrite/RewriteModernObjC.cpp
index ad217517d7d7..e7bfcedd2176 100644
--- a/lib/Frontend/Rewrite/RewriteModernObjC.cpp
+++ b/lib/Frontend/Rewrite/RewriteModernObjC.cpp
@@ -863,9 +863,9 @@ RewriteModernObjC::getIvarAccessString(ObjCIvarDecl *D) {
CDecl = CatDecl->getClassInterface();
std::string RecName = CDecl->getName();
RecName += "_IMPL";
- RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl,
- SourceLocation(), SourceLocation(),
- &Context->Idents.get(RecName.c_str()));
+ RecordDecl *RD =
+ RecordDecl::Create(*Context, TTK_Struct, TUDecl, SourceLocation(),
+ SourceLocation(), &Context->Idents.get(RecName));
QualType PtrStructIMPL = Context->getPointerType(Context->getTagDeclType(RD));
unsigned UnsignedIntSize =
static_cast<unsigned>(Context->getTypeSize(Context->UnsignedIntTy));
@@ -5301,11 +5301,9 @@ Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,
// Initialize the block descriptor.
std::string DescData = "__" + FuncName + "_block_desc_" + BlockNumber + "_DATA";
- VarDecl *NewVD = VarDecl::Create(*Context, TUDecl,
- SourceLocation(), SourceLocation(),
- &Context->Idents.get(DescData.c_str()),
- Context->VoidPtrTy, nullptr,
- SC_Static);
+ VarDecl *NewVD = VarDecl::Create(
+ *Context, TUDecl, SourceLocation(), SourceLocation(),
+ &Context->Idents.get(DescData), Context->VoidPtrTy, nullptr, SC_Static);
UnaryOperator *DescRefExpr =
new (Context) UnaryOperator(new (Context) DeclRefExpr(NewVD, false,
Context->VoidPtrTy,
@@ -6350,8 +6348,7 @@ static void Write_method_list_t_initializer(RewriteModernObjC &RewriteObj,
Result += "\t{(struct objc_selector *)\"";
Result += (MD)->getSelector().getAsString(); Result += "\"";
Result += ", ";
- std::string MethodTypeString;
- Context->getObjCEncodingForMethodDecl(MD, MethodTypeString);
+ std::string MethodTypeString = Context->getObjCEncodingForMethodDecl(MD);
Result += "\""; Result += MethodTypeString; Result += "\"";
Result += ", ";
if (!MethodImpl)
@@ -6390,8 +6387,9 @@ static void Write_prop_list_t_initializer(RewriteModernObjC &RewriteObj,
else
Result += "\t{\"";
Result += PropDecl->getName(); Result += "\",";
- std::string PropertyTypeString, QuotePropertyTypeString;
- Context->getObjCEncodingForPropertyDecl(PropDecl, Container, PropertyTypeString);
+ std::string PropertyTypeString =
+ Context->getObjCEncodingForPropertyDecl(PropDecl, Container);
+ std::string QuotePropertyTypeString;
RewriteObj.QuoteDoublequotes(PropertyTypeString, QuotePropertyTypeString);
Result += "\""; Result += QuotePropertyTypeString; Result += "\"";
if (i == e-1)
@@ -6720,8 +6718,9 @@ static void Write__extendedMethodTypes_initializer(RewriteModernObjC &RewriteObj
Result += "{\n";
for (unsigned i = 0, e = Methods.size(); i < e; i++) {
ObjCMethodDecl *MD = Methods[i];
- std::string MethodTypeString, QuoteMethodTypeString;
- Context->getObjCEncodingForMethodDecl(MD, MethodTypeString, true);
+ std::string MethodTypeString =
+ Context->getObjCEncodingForMethodDecl(MD, true);
+ std::string QuoteMethodTypeString;
RewriteObj.QuoteDoublequotes(MethodTypeString, QuoteMethodTypeString);
Result += "\t\""; Result += QuoteMethodTypeString; Result += "\"";
if (i == e-1)
@@ -7522,9 +7521,9 @@ Stmt *RewriteModernObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) {
CDecl = CatDecl->getClassInterface();
std::string RecName = CDecl->getName();
RecName += "_IMPL";
- RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl,
- SourceLocation(), SourceLocation(),
- &Context->Idents.get(RecName.c_str()));
+ RecordDecl *RD = RecordDecl::Create(
+ *Context, TTK_Struct, TUDecl, SourceLocation(), SourceLocation(),
+ &Context->Idents.get(RecName));
QualType PtrStructIMPL = Context->getPointerType(Context->getTagDeclType(RD));
unsigned UnsignedIntSize =
static_cast<unsigned>(Context->getTypeSize(Context->UnsignedIntTy));
diff --git a/lib/Frontend/Rewrite/RewriteObjC.cpp b/lib/Frontend/Rewrite/RewriteObjC.cpp
index 5967e40bfed9..e842e592cbbe 100644
--- a/lib/Frontend/Rewrite/RewriteObjC.cpp
+++ b/lib/Frontend/Rewrite/RewriteObjC.cpp
@@ -4426,11 +4426,9 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
// Initialize the block descriptor.
std::string DescData = "__" + FuncName + "_block_desc_" + BlockNumber + "_DATA";
- VarDecl *NewVD = VarDecl::Create(*Context, TUDecl,
- SourceLocation(), SourceLocation(),
- &Context->Idents.get(DescData.c_str()),
- Context->VoidPtrTy, nullptr,
- SC_Static);
+ VarDecl *NewVD = VarDecl::Create(
+ *Context, TUDecl, SourceLocation(), SourceLocation(),
+ &Context->Idents.get(DescData), Context->VoidPtrTy, nullptr, SC_Static);
UnaryOperator *DescRefExpr =
new (Context) UnaryOperator(new (Context) DeclRefExpr(NewVD, false,
Context->VoidPtrTy,
@@ -5126,8 +5124,7 @@ void RewriteObjCFragileABI::RewriteObjCProtocolMetaData(
else
Result += "\t ,{(struct objc_selector *)\"";
Result += (*I)->getSelector().getAsString();
- std::string MethodTypeString;
- Context->getObjCEncodingForMethodDecl((*I), MethodTypeString);
+ std::string MethodTypeString = Context->getObjCEncodingForMethodDecl(*I);
Result += "\", \"";
Result += MethodTypeString;
Result += "\"}\n";
@@ -5164,8 +5161,7 @@ void RewriteObjCFragileABI::RewriteObjCProtocolMetaData(
else
Result += "\t ,{(struct objc_selector *)\"";
Result += (*I)->getSelector().getAsString();
- std::string MethodTypeString;
- Context->getObjCEncodingForMethodDecl((*I), MethodTypeString);
+ std::string MethodTypeString = Context->getObjCEncodingForMethodDecl(*I);
Result += "\", \"";
Result += MethodTypeString;
Result += "\"}\n";
@@ -5650,14 +5646,12 @@ void RewriteObjCFragileABI::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *ID
InstanceMethods.push_back(Setter);
}
RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(),
- true, "CATEGORY_", FullCategoryName.c_str(),
- Result);
-
+ true, "CATEGORY_", FullCategoryName, Result);
+
// Build _objc_method_list for class's class methods if needed
RewriteObjCMethodsMetaData(IDecl->classmeth_begin(), IDecl->classmeth_end(),
- false, "CATEGORY_", FullCategoryName.c_str(),
- Result);
-
+ false, "CATEGORY_", FullCategoryName, Result);
+
// Protocols referenced in class declaration?
// Null CDecl is case of a category implementation with no category interface
if (CDecl)
@@ -5776,9 +5770,9 @@ void RewriteObjCFragileABI::RewriteObjCMethodsMetaData(MethodIterator MethodBegi
Result += "{\n\t0, " + utostr(NumMethods) + "\n";
Result += "\t,{{(SEL)\"";
- Result += (*MethodBegin)->getSelector().getAsString().c_str();
- std::string MethodTypeString;
- Context->getObjCEncodingForMethodDecl(*MethodBegin, MethodTypeString);
+ Result += (*MethodBegin)->getSelector().getAsString();
+ std::string MethodTypeString =
+ Context->getObjCEncodingForMethodDecl(*MethodBegin);
Result += "\", \"";
Result += MethodTypeString;
Result += "\", (void *)";
@@ -5786,9 +5780,9 @@ void RewriteObjCFragileABI::RewriteObjCMethodsMetaData(MethodIterator MethodBegi
Result += "}\n";
for (++MethodBegin; MethodBegin != MethodEnd; ++MethodBegin) {
Result += "\t ,{(SEL)\"";
- Result += (*MethodBegin)->getSelector().getAsString().c_str();
- std::string MethodTypeString;
- Context->getObjCEncodingForMethodDecl(*MethodBegin, MethodTypeString);
+ Result += (*MethodBegin)->getSelector().getAsString();
+ std::string MethodTypeString =
+ Context->getObjCEncodingForMethodDecl(*MethodBegin);
Result += "\", \"";
Result += MethodTypeString;
Result += "\", (void *)";
diff --git a/lib/Frontend/Rewrite/RewriteTest.cpp b/lib/Frontend/Rewrite/RewriteTest.cpp
index 722c5e80b443..b0791f4cddd7 100644
--- a/lib/Frontend/Rewrite/RewriteTest.cpp
+++ b/lib/Frontend/Rewrite/RewriteTest.cpp
@@ -11,12 +11,12 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Rewrite/Frontend/Rewriters.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Rewrite/Core/TokenRewriter.h"
+#include "clang/Rewrite/Frontend/Rewriters.h"
#include "llvm/Support/raw_ostream.h"
-void clang::DoRewriteTest(Preprocessor &PP, raw_ostream* OS) {
+void clang::DoRewriteTest(Preprocessor &PP, raw_ostream *OS) {
SourceManager &SM = PP.getSourceManager();
const LangOptions &LangOpts = PP.getLangOpts();
diff --git a/lib/Frontend/SerializedDiagnosticPrinter.cpp b/lib/Frontend/SerializedDiagnosticPrinter.cpp
index 5c42406876b6..1ea5a342e1d8 100644
--- a/lib/Frontend/SerializedDiagnosticPrinter.cpp
+++ b/lib/Frontend/SerializedDiagnosticPrinter.cpp
@@ -10,9 +10,7 @@
#include "clang/Frontend/SerializedDiagnosticPrinter.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticOptions.h"
-#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
-#include "clang/Basic/Version.h"
#include "clang/Frontend/DiagnosticRenderer.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/SerializedDiagnosticReader.h"
@@ -25,7 +23,6 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/raw_ostream.h"
#include <utility>
-#include <vector>
using namespace clang;
using namespace clang::serialized_diags;
@@ -439,7 +436,7 @@ static void AddRangeLocationAbbrev(llvm::BitCodeAbbrev *Abbrev) {
}
void SDiagsWriter::EmitBlockInfoBlock() {
- State->Stream.EnterBlockInfoBlock(3);
+ State->Stream.EnterBlockInfoBlock();
using namespace llvm;
llvm::BitstreamWriter &Stream = State->Stream;
diff --git a/lib/Frontend/SerializedDiagnosticReader.cpp b/lib/Frontend/SerializedDiagnosticReader.cpp
index 0ebbd22af274..c4461d452e7b 100644
--- a/lib/Frontend/SerializedDiagnosticReader.cpp
+++ b/lib/Frontend/SerializedDiagnosticReader.cpp
@@ -11,7 +11,6 @@
#include "clang/Basic/FileManager.h"
#include "clang/Frontend/SerializedDiagnostics.h"
#include "llvm/Support/ManagedStatic.h"
-#include "llvm/Support/MemoryBuffer.h"
using namespace clang;
using namespace clang::serialized_diags;
@@ -25,11 +24,8 @@ std::error_code SerializedDiagnosticReader::readDiagnostics(StringRef File) {
if (!Buffer)
return SDError::CouldNotLoad;
- llvm::BitstreamReader StreamFile;
- StreamFile.init((const unsigned char *)(*Buffer)->getBufferStart(),
- (const unsigned char *)(*Buffer)->getBufferEnd());
-
- llvm::BitstreamCursor Stream(StreamFile);
+ llvm::BitstreamCursor Stream(**Buffer);
+ Optional<llvm::BitstreamBlockInfo> BlockInfo;
// Sniff for the signature.
if (Stream.Read(8) != 'D' ||
@@ -45,10 +41,13 @@ std::error_code SerializedDiagnosticReader::readDiagnostics(StringRef File) {
std::error_code EC;
switch (Stream.ReadSubBlockID()) {
- case llvm::bitc::BLOCKINFO_BLOCK_ID:
- if (Stream.ReadBlockInfoBlock())
+ 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;
@@ -251,7 +250,7 @@ SerializedDiagnosticReader::readDiagnosticBlock(llvm::BitstreamCursor &Stream) {
namespace {
class SDErrorCategoryType final : public std::error_category {
- const char *name() const LLVM_NOEXCEPT override {
+ const char *name() const noexcept override {
return "clang.serialized_diags";
}
std::string message(int IE) const override {
diff --git a/lib/Frontend/TextDiagnostic.cpp b/lib/Frontend/TextDiagnostic.cpp
index 977af079a77a..a4937386b93f 100644
--- a/lib/Frontend/TextDiagnostic.cpp
+++ b/lib/Frontend/TextDiagnostic.cpp
@@ -18,7 +18,7 @@
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Locale.h"
-#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
@@ -119,16 +119,17 @@ printableTextForNextCharacter(StringRef SourceLine, size_t *i,
begin = reinterpret_cast<unsigned char const *>(&*(SourceLine.begin() + *i));
end = begin + (SourceLine.size() - *i);
- if (isLegalUTF8Sequence(begin, end)) {
- UTF32 c;
- UTF32 *cptr = &c;
+ if (llvm::isLegalUTF8Sequence(begin, end)) {
+ llvm::UTF32 c;
+ llvm::UTF32 *cptr = &c;
unsigned char const *original_begin = begin;
- unsigned char const *cp_end = begin+getNumBytesForUTF8(SourceLine[*i]);
+ unsigned char const *cp_end =
+ begin + llvm::getNumBytesForUTF8(SourceLine[*i]);
- ConversionResult res = ConvertUTF8toUTF32(&begin, cp_end, &cptr, cptr+1,
- strictConversion);
+ llvm::ConversionResult res = llvm::ConvertUTF8toUTF32(
+ &begin, cp_end, &cptr, cptr + 1, llvm::strictConversion);
(void)res;
- assert(conversionOK==res);
+ assert(llvm::conversionOK == res);
assert(0 < begin-original_begin
&& "we must be further along in the string now");
*i += begin-original_begin;
@@ -764,6 +765,22 @@ void TextDiagnostic::printDiagnosticMessage(raw_ostream &OS,
OS << '\n';
}
+void TextDiagnostic::emitFilename(StringRef Filename, const SourceManager &SM) {
+ SmallVector<char, 128> AbsoluteFilename;
+ if (DiagOpts->AbsolutePath) {
+ const DirectoryEntry *Dir = SM.getFileManager().getDirectory(
+ llvm::sys::path::parent_path(Filename));
+ if (Dir) {
+ StringRef DirName = SM.getFileManager().getCanonicalName(Dir);
+ llvm::sys::path::append(AbsoluteFilename, DirName,
+ llvm::sys::path::filename(Filename));
+ Filename = StringRef(AbsoluteFilename.data(), AbsoluteFilename.size());
+ }
+ }
+
+ OS << Filename;
+}
+
/// \brief Print out the file/line/column information and include trace.
///
/// This method handlen the emission of the diagnostic location information.
@@ -780,7 +797,7 @@ void TextDiagnostic::emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
if (FID.isValid()) {
const FileEntry* FE = SM.getFileEntryForID(FID);
if (FE && FE->isValid()) {
- OS << FE->getName();
+ emitFilename(FE->getName(), SM);
if (FE->isInPCH())
OS << " (in PCH)";
OS << ": ";
@@ -796,7 +813,7 @@ void TextDiagnostic::emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
if (DiagOpts->ShowColors)
OS.changeColor(savedColor, true);
- OS << PLoc.getFilename();
+ emitFilename(PLoc.getFilename(), SM);
switch (DiagOpts->getFormat()) {
case DiagnosticOptions::Clang: OS << ':' << LineNo; break;
case DiagnosticOptions::MSVC: OS << '(' << LineNo; break;
diff --git a/lib/Frontend/TextDiagnosticPrinter.cpp b/lib/Frontend/TextDiagnosticPrinter.cpp
index 66b46b7814eb..17646b48e23d 100644
--- a/lib/Frontend/TextDiagnosticPrinter.cpp
+++ b/lib/Frontend/TextDiagnosticPrinter.cpp
@@ -13,13 +13,11 @@
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Basic/DiagnosticOptions.h"
-#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Frontend/TextDiagnostic.h"
#include "clang/Lex/Lexer.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
using namespace clang;
diff --git a/lib/Frontend/VerifyDiagnosticConsumer.cpp b/lib/Frontend/VerifyDiagnosticConsumer.cpp
index 7331d77d1c18..ae16ea177ffe 100644
--- a/lib/Frontend/VerifyDiagnosticConsumer.cpp
+++ b/lib/Frontend/VerifyDiagnosticConsumer.cpp
@@ -43,7 +43,8 @@ VerifyDiagnosticConsumer::~VerifyDiagnosticConsumer() {
assert(!CurrentPreprocessor && "CurrentPreprocessor should be invalid!");
SrcManager = nullptr;
CheckDiagnostics();
- Diags.takeClient().release();
+ assert(!Diags.ownsClient() &&
+ "The VerifyDiagnosticConsumer takes over ownership of the client!");
}
#ifndef NDEBUG
diff --git a/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/lib/FrontendTool/ExecuteCompilerInvocation.cpp
index 509c326d1597..187a6e76245d 100644
--- a/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ b/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -52,7 +52,10 @@ CreateFrontendBaseAction(CompilerInstance &CI) {
case EmitCodeGenOnly: return llvm::make_unique<EmitCodeGenOnlyAction>();
case EmitObj: return llvm::make_unique<EmitObjAction>();
case FixIt: return llvm::make_unique<FixItAction>();
- case GenerateModule: return llvm::make_unique<GenerateModuleAction>();
+ case GenerateModule:
+ return llvm::make_unique<GenerateModuleFromModuleMapAction>();
+ case GenerateModuleInterface:
+ return llvm::make_unique<GenerateModuleInterfaceAction>();
case GeneratePCH: return llvm::make_unique<GeneratePCHAction>();
case GeneratePTH: return llvm::make_unique<GeneratePTHAction>();
case InitOnly: return llvm::make_unique<InitOnlyAction>();
@@ -229,6 +232,11 @@ bool clang::ExecuteCompilerInvocation(CompilerInstance *Clang) {
ento::printCheckerHelp(llvm::outs(), Clang->getFrontendOpts().Plugins);
return true;
}
+ if (Clang->getAnalyzerOpts()->ShowEnabledCheckerList) {
+ ento::printEnabledCheckerList(llvm::outs(),
+ Clang->getFrontendOpts().Plugins,
+ *Clang->getAnalyzerOpts());
+ }
#endif
// If there were errors in processing arguments, don't do anything else.
diff --git a/lib/Headers/CMakeLists.txt b/lib/Headers/CMakeLists.txt
index fa2d2107781b..efc4dd0971b6 100644
--- a/lib/Headers/CMakeLists.txt
+++ b/lib/Headers/CMakeLists.txt
@@ -3,6 +3,7 @@ set(files
altivec.h
ammintrin.h
arm_acle.h
+ armintr.h
avx2intrin.h
avx512bwintrin.h
avx512cdintrin.h
@@ -21,12 +22,13 @@ set(files
avxintrin.h
bmi2intrin.h
bmiintrin.h
+ __clang_cuda_builtin_vars.h
__clang_cuda_cmath.h
+ __clang_cuda_complex_builtins.h
__clang_cuda_intrinsics.h
__clang_cuda_math_forward_declares.h
__clang_cuda_runtime_wrapper.h
cpuid.h
- cuda_builtin_vars.h
clflushoptintrin.h
emmintrin.h
f16cintrin.h
@@ -88,6 +90,12 @@ set(files
xtestintrin.h
)
+set(cuda_wrapper_files
+ cuda_wrappers/algorithm
+ cuda_wrappers/complex
+ cuda_wrappers/new
+)
+
set(output_dir ${LLVM_LIBRARY_OUTPUT_INTDIR}/clang/${CLANG_VERSION}/include)
# Generate arm_neon.h
@@ -95,7 +103,7 @@ clang_tablegen(arm_neon.h -gen-arm-neon
SOURCE ${CLANG_SOURCE_DIR}/include/clang/Basic/arm_neon.td)
set(out_files)
-foreach( f ${files} )
+foreach( f ${files} ${cuda_wrapper_files} )
set( src ${CMAKE_CURRENT_SOURCE_DIR}/${f} )
set( dst ${output_dir}/${f} )
add_custom_command(OUTPUT ${dst}
@@ -120,6 +128,12 @@ install(
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
+ DESTINATION lib${LLVM_LIBDIR_SUFFIX}/clang/${CLANG_VERSION}/include/cuda_wrappers)
+
if (NOT CMAKE_CONFIGURATION_TYPES) # don't add this for IDE's.
add_custom_target(install-clang-headers
DEPENDS clang-headers
diff --git a/lib/Headers/cuda_builtin_vars.h b/lib/Headers/__clang_cuda_builtin_vars.h
index 6f5eb9c78d85..6f5eb9c78d85 100644
--- a/lib/Headers/cuda_builtin_vars.h
+++ b/lib/Headers/__clang_cuda_builtin_vars.h
diff --git a/lib/Headers/__clang_cuda_cmath.h b/lib/Headers/__clang_cuda_cmath.h
index ae7ff2f8d306..0eaa08b30cab 100644
--- a/lib/Headers/__clang_cuda_cmath.h
+++ b/lib/Headers/__clang_cuda_cmath.h
@@ -26,13 +26,15 @@
#error "This file is for CUDA compilation only."
#endif
+#include <limits>
+
// CUDA lets us use various std math functions on the device side. This file
// works in concert with __clang_cuda_math_forward_declares.h to make this work.
//
// Specifically, the forward-declares header declares __device__ overloads for
// these functions in the global namespace, then pulls them into namespace std
// with 'using' statements. Then this file implements those functions, after
-// the implementations have been pulled in.
+// their implementations have been pulled in.
//
// It's important that we declare the functions in the global namespace and pull
// them into namespace std with using statements, as opposed to simply declaring
@@ -73,7 +75,10 @@ __DEVICE__ float frexp(float __arg, int *__exp) {
__DEVICE__ bool isinf(float __x) { return ::__isinff(__x); }
__DEVICE__ bool isinf(double __x) { return ::__isinf(__x); }
__DEVICE__ bool isfinite(float __x) { return ::__finitef(__x); }
-__DEVICE__ bool isfinite(double __x) { return ::__finite(__x); }
+// For inscrutable reasons, __finite(), the double-precision version of
+// __finitef, does not exist when compiling for MacOS. __isfinited is available
+// everywhere and is just as good.
+__DEVICE__ bool isfinite(double __x) { return ::__isfinited(__x); }
__DEVICE__ bool isgreater(float __x, float __y) {
return __builtin_isgreater(__x, __y);
}
@@ -120,12 +125,15 @@ __DEVICE__ float ldexp(float __arg, int __exp) {
__DEVICE__ float log(float __x) { return ::logf(__x); }
__DEVICE__ float log10(float __x) { return ::log10f(__x); }
__DEVICE__ float modf(float __x, float *__iptr) { return ::modff(__x, __iptr); }
-__DEVICE__ float nexttoward(float __from, float __to) {
+__DEVICE__ float nexttoward(float __from, double __to) {
return __builtin_nexttowardf(__from, __to);
}
__DEVICE__ double nexttoward(double __from, double __to) {
return __builtin_nexttoward(__from, __to);
}
+__DEVICE__ float nexttowardf(float __from, double __to) {
+ return __builtin_nexttowardf(__from, __to);
+}
__DEVICE__ float pow(float __base, float __exp) {
return ::powf(__base, __exp);
}
@@ -136,13 +144,338 @@ __DEVICE__ double pow(double __base, int __iexp) {
return ::powi(__base, __iexp);
}
__DEVICE__ bool signbit(float __x) { return ::__signbitf(__x); }
-__DEVICE__ bool signbit(double __x) { return ::__signbit(__x); }
+__DEVICE__ bool signbit(double __x) { return ::__signbitd(__x); }
__DEVICE__ float sin(float __x) { return ::sinf(__x); }
__DEVICE__ float sinh(float __x) { return ::sinhf(__x); }
__DEVICE__ float sqrt(float __x) { return ::sqrtf(__x); }
__DEVICE__ float tan(float __x) { return ::tanf(__x); }
__DEVICE__ float tanh(float __x) { return ::tanhf(__x); }
+// Now we've defined everything we promised we'd define in
+// __clang_cuda_math_forward_declares.h. We need to do two additional things to
+// fix up our math functions.
+//
+// 1) Define __device__ overloads for e.g. sin(int). The CUDA headers define
+// only sin(float) and sin(double), which means that e.g. sin(0) is
+// ambiguous.
+//
+// 2) Pull the __device__ overloads of "foobarf" math functions into namespace
+// std. These are defined in the CUDA headers in the global namespace,
+// independent of everything else we've done here.
+
+// We can't use std::enable_if, because we want to be pre-C++11 compatible. But
+// we go ahead and unconditionally define functions that are only available when
+// compiling for C++11 to match the behavior of the CUDA headers.
+template<bool __B, class __T = void>
+struct __clang_cuda_enable_if {};
+
+template <class __T> struct __clang_cuda_enable_if<true, __T> {
+ typedef __T type;
+};
+
+// Defines an overload of __fn that accepts one integral argument, calls
+// __fn((double)x), and returns __retty.
+#define __CUDA_CLANG_FN_INTEGER_OVERLOAD_1(__retty, __fn) \
+ template <typename __T> \
+ __DEVICE__ \
+ typename __clang_cuda_enable_if<std::numeric_limits<__T>::is_integer, \
+ __retty>::type \
+ __fn(__T __x) { \
+ return ::__fn((double)__x); \
+ }
+
+// Defines an overload of __fn that accepts one two arithmetic arguments, calls
+// __fn((double)x, (double)y), and returns a double.
+//
+// Note this is different from OVERLOAD_1, which generates an overload that
+// accepts only *integral* arguments.
+#define __CUDA_CLANG_FN_INTEGER_OVERLOAD_2(__retty, __fn) \
+ template <typename __T1, typename __T2> \
+ __DEVICE__ typename __clang_cuda_enable_if< \
+ std::numeric_limits<__T1>::is_specialized && \
+ std::numeric_limits<__T2>::is_specialized, \
+ __retty>::type \
+ __fn(__T1 __x, __T2 __y) { \
+ return __fn((double)__x, (double)__y); \
+ }
+
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_1(double, acos)
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_1(double, acosh)
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_1(double, asin)
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_1(double, asinh)
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_1(double, atan)
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_2(double, atan2);
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_1(double, atanh)
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_1(double, cbrt)
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_1(double, ceil)
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_2(double, copysign);
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_1(double, cos)
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_1(double, cosh)
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_1(double, erf)
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_1(double, erfc)
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_1(double, exp)
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_1(double, exp2)
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_1(double, expm1)
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_1(double, fabs)
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_2(double, fdim);
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_1(double, floor)
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_2(double, fmax);
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_2(double, fmin);
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_2(double, fmod);
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_1(int, fpclassify)
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_2(double, hypot);
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_1(int, ilogb)
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_1(bool, isfinite)
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_2(bool, isgreater);
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_2(bool, isgreaterequal);
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_1(bool, isinf);
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_2(bool, isless);
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_2(bool, islessequal);
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_2(bool, islessgreater);
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_1(bool, isnan);
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_1(bool, isnormal)
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_2(bool, isunordered);
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_1(double, lgamma)
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_1(double, log)
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_1(double, log10)
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_1(double, log1p)
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_1(double, log2)
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_1(double, logb)
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_1(long long, llrint)
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_1(long long, llround)
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_1(long, lrint)
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_1(long, lround)
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_1(double, nearbyint);
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_2(double, nextafter);
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_2(double, pow);
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_2(double, remainder);
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_1(double, rint);
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_1(double, round);
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_1(bool, signbit)
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_1(double, sin)
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_1(double, sinh)
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_1(double, sqrt)
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_1(double, tan)
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_1(double, tanh)
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_1(double, tgamma)
+__CUDA_CLANG_FN_INTEGER_OVERLOAD_1(double, trunc);
+
+#undef __CUDA_CLANG_FN_INTEGER_OVERLOAD_1
+#undef __CUDA_CLANG_FN_INTEGER_OVERLOAD_2
+
+// Overloads for functions that don't match the patterns expected by
+// __CUDA_CLANG_FN_INTEGER_OVERLOAD_{1,2}.
+template <typename __T1, typename __T2, typename __T3>
+__DEVICE__ typename __clang_cuda_enable_if<
+ std::numeric_limits<__T1>::is_specialized &&
+ std::numeric_limits<__T2>::is_specialized &&
+ std::numeric_limits<__T3>::is_specialized,
+ double>::type
+fma(__T1 __x, __T2 __y, __T3 __z) {
+ return std::fma((double)__x, (double)__y, (double)__z);
+}
+
+template <typename __T>
+__DEVICE__ typename __clang_cuda_enable_if<std::numeric_limits<__T>::is_integer,
+ double>::type
+frexp(__T __x, int *__exp) {
+ return std::frexp((double)__x, __exp);
+}
+
+template <typename __T>
+__DEVICE__ typename __clang_cuda_enable_if<std::numeric_limits<__T>::is_integer,
+ double>::type
+ldexp(__T __x, int __exp) {
+ return std::ldexp((double)__x, __exp);
+}
+
+template <typename __T>
+__DEVICE__ typename __clang_cuda_enable_if<std::numeric_limits<__T>::is_integer,
+ double>::type
+nexttoward(__T __from, double __to) {
+ return std::nexttoward((double)__from, __to);
+}
+
+template <typename __T1, typename __T2>
+__DEVICE__ typename __clang_cuda_enable_if<
+ std::numeric_limits<__T1>::is_specialized &&
+ std::numeric_limits<__T2>::is_specialized,
+ double>::type
+remquo(__T1 __x, __T2 __y, int *__quo) {
+ return std::remquo((double)__x, (double)__y, __quo);
+}
+
+template <typename __T>
+__DEVICE__ typename __clang_cuda_enable_if<std::numeric_limits<__T>::is_integer,
+ double>::type
+scalbln(__T __x, long __exp) {
+ return std::scalbln((double)__x, __exp);
+}
+
+template <typename __T>
+__DEVICE__ typename __clang_cuda_enable_if<std::numeric_limits<__T>::is_integer,
+ double>::type
+scalbn(__T __x, int __exp) {
+ return std::scalbn((double)__x, __exp);
+}
+
+// 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
+// <complex>). Thus the ugliness below.
+#ifdef _LIBCPP_BEGIN_NAMESPACE_STD
+_LIBCPP_BEGIN_NAMESPACE_STD
+#else
+namespace std {
+#ifdef _GLIBCXX_BEGIN_NAMESPACE_VERSION
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+#endif
+#endif
+
+// Pull the new overloads we defined above into namespace std.
+using ::acos;
+using ::acosh;
+using ::asin;
+using ::asinh;
+using ::atan;
+using ::atan2;
+using ::atanh;
+using ::cbrt;
+using ::ceil;
+using ::copysign;
+using ::cos;
+using ::cosh;
+using ::erf;
+using ::erfc;
+using ::exp;
+using ::exp2;
+using ::expm1;
+using ::fabs;
+using ::fdim;
+using ::floor;
+using ::fma;
+using ::fmax;
+using ::fmin;
+using ::fmod;
+using ::fpclassify;
+using ::frexp;
+using ::hypot;
+using ::ilogb;
+using ::isfinite;
+using ::isgreater;
+using ::isgreaterequal;
+using ::isless;
+using ::islessequal;
+using ::islessgreater;
+using ::isnormal;
+using ::isunordered;
+using ::ldexp;
+using ::lgamma;
+using ::llrint;
+using ::llround;
+using ::log;
+using ::log10;
+using ::log1p;
+using ::log2;
+using ::logb;
+using ::lrint;
+using ::lround;
+using ::nearbyint;
+using ::nextafter;
+using ::nexttoward;
+using ::pow;
+using ::remainder;
+using ::remquo;
+using ::rint;
+using ::round;
+using ::scalbln;
+using ::scalbn;
+using ::signbit;
+using ::sin;
+using ::sinh;
+using ::sqrt;
+using ::tan;
+using ::tanh;
+using ::tgamma;
+using ::trunc;
+
+// Well this is fun: We need to pull these symbols in for libc++, but we can't
+// pull them in with libstdc++, because its ::isinf and ::isnan are different
+// than its std::isinf and std::isnan.
+#ifndef __GLIBCXX__
+using ::isinf;
+using ::isnan;
+#endif
+
+// Finally, pull the "foobarf" functions that CUDA defines in its headers into
+// namespace std.
+using ::acosf;
+using ::acoshf;
+using ::asinf;
+using ::asinhf;
+using ::atan2f;
+using ::atanf;
+using ::atanhf;
+using ::cbrtf;
+using ::ceilf;
+using ::copysignf;
+using ::cosf;
+using ::coshf;
+using ::erfcf;
+using ::erff;
+using ::exp2f;
+using ::expf;
+using ::expm1f;
+using ::fabsf;
+using ::fdimf;
+using ::floorf;
+using ::fmaf;
+using ::fmaxf;
+using ::fminf;
+using ::fmodf;
+using ::frexpf;
+using ::hypotf;
+using ::ilogbf;
+using ::ldexpf;
+using ::lgammaf;
+using ::llrintf;
+using ::llroundf;
+using ::log10f;
+using ::log1pf;
+using ::log2f;
+using ::logbf;
+using ::logf;
+using ::lrintf;
+using ::lroundf;
+using ::modff;
+using ::nearbyintf;
+using ::nextafterf;
+using ::nexttowardf;
+using ::nexttowardf;
+using ::powf;
+using ::remainderf;
+using ::remquof;
+using ::rintf;
+using ::roundf;
+using ::scalblnf;
+using ::scalbnf;
+using ::sinf;
+using ::sinhf;
+using ::sqrtf;
+using ::tanf;
+using ::tanhf;
+using ::tgammaf;
+using ::truncf;
+
+#ifdef _LIBCPP_END_NAMESPACE_STD
+_LIBCPP_END_NAMESPACE_STD
+#else
+#ifdef _GLIBCXX_BEGIN_NAMESPACE_VERSION
+_GLIBCXX_END_NAMESPACE_VERSION
+#endif
+} // namespace std
+#endif
+
#undef __DEVICE__
#endif
diff --git a/lib/Headers/__clang_cuda_complex_builtins.h b/lib/Headers/__clang_cuda_complex_builtins.h
new file mode 100644
index 000000000000..beef7deff87f
--- /dev/null
+++ b/lib/Headers/__clang_cuda_complex_builtins.h
@@ -0,0 +1,203 @@
+/*===-- __clang_cuda_complex_builtins - CUDA impls of runtime complex fns ---===
+ *
+ * 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_COMPLEX_BUILTINS
+#define __CLANG_CUDA_COMPLEX_BUILTINS
+
+// This header defines __muldc3, __mulsc3, __divdc3, and __divsc3. These are
+// libgcc functions that clang assumes are available when compiling c99 complex
+// operations. (These implementations come from libc++, and have been modified
+// to work with CUDA.)
+
+extern "C" inline __device__ double _Complex __muldc3(double __a, double __b,
+ double __c, double __d) {
+ double __ac = __a * __c;
+ double __bd = __b * __d;
+ double __ad = __a * __d;
+ double __bc = __b * __c;
+ double _Complex z;
+ __real__(z) = __ac - __bd;
+ __imag__(z) = __ad + __bc;
+ if (std::isnan(__real__(z)) && std::isnan(__imag__(z))) {
+ int __recalc = 0;
+ if (std::isinf(__a) || std::isinf(__b)) {
+ __a = std::copysign(std::isinf(__a) ? 1 : 0, __a);
+ __b = std::copysign(std::isinf(__b) ? 1 : 0, __b);
+ if (std::isnan(__c))
+ __c = std::copysign(0, __c);
+ if (std::isnan(__d))
+ __d = std::copysign(0, __d);
+ __recalc = 1;
+ }
+ if (std::isinf(__c) || std::isinf(__d)) {
+ __c = std::copysign(std::isinf(__c) ? 1 : 0, __c);
+ __d = std::copysign(std::isinf(__d) ? 1 : 0, __d);
+ if (std::isnan(__a))
+ __a = std::copysign(0, __a);
+ if (std::isnan(__b))
+ __b = std::copysign(0, __b);
+ __recalc = 1;
+ }
+ if (!__recalc && (std::isinf(__ac) || std::isinf(__bd) ||
+ std::isinf(__ad) || std::isinf(__bc))) {
+ if (std::isnan(__a))
+ __a = std::copysign(0, __a);
+ if (std::isnan(__b))
+ __b = std::copysign(0, __b);
+ if (std::isnan(__c))
+ __c = std::copysign(0, __c);
+ if (std::isnan(__d))
+ __d = std::copysign(0, __d);
+ __recalc = 1;
+ }
+ if (__recalc) {
+ // Can't use std::numeric_limits<double>::infinity() -- that doesn't have
+ // a device overload (and isn't constexpr before C++11, naturally).
+ __real__(z) = __builtin_huge_valf() * (__a * __c - __b * __d);
+ __imag__(z) = __builtin_huge_valf() * (__a * __d + __b * __c);
+ }
+ }
+ return z;
+}
+
+extern "C" inline __device__ float _Complex __mulsc3(float __a, float __b,
+ float __c, float __d) {
+ float __ac = __a * __c;
+ float __bd = __b * __d;
+ float __ad = __a * __d;
+ float __bc = __b * __c;
+ float _Complex z;
+ __real__(z) = __ac - __bd;
+ __imag__(z) = __ad + __bc;
+ if (std::isnan(__real__(z)) && std::isnan(__imag__(z))) {
+ int __recalc = 0;
+ if (std::isinf(__a) || std::isinf(__b)) {
+ __a = std::copysign(std::isinf(__a) ? 1 : 0, __a);
+ __b = std::copysign(std::isinf(__b) ? 1 : 0, __b);
+ if (std::isnan(__c))
+ __c = std::copysign(0, __c);
+ if (std::isnan(__d))
+ __d = std::copysign(0, __d);
+ __recalc = 1;
+ }
+ if (std::isinf(__c) || std::isinf(__d)) {
+ __c = std::copysign(std::isinf(__c) ? 1 : 0, __c);
+ __d = std::copysign(std::isinf(__d) ? 1 : 0, __d);
+ if (std::isnan(__a))
+ __a = std::copysign(0, __a);
+ if (std::isnan(__b))
+ __b = std::copysign(0, __b);
+ __recalc = 1;
+ }
+ if (!__recalc && (std::isinf(__ac) || std::isinf(__bd) ||
+ std::isinf(__ad) || std::isinf(__bc))) {
+ if (std::isnan(__a))
+ __a = std::copysign(0, __a);
+ if (std::isnan(__b))
+ __b = std::copysign(0, __b);
+ if (std::isnan(__c))
+ __c = std::copysign(0, __c);
+ if (std::isnan(__d))
+ __d = std::copysign(0, __d);
+ __recalc = 1;
+ }
+ if (__recalc) {
+ __real__(z) = __builtin_huge_valf() * (__a * __c - __b * __d);
+ __imag__(z) = __builtin_huge_valf() * (__a * __d + __b * __c);
+ }
+ }
+ return z;
+}
+
+extern "C" inline __device__ double _Complex __divdc3(double __a, double __b,
+ double __c, double __d) {
+ int __ilogbw = 0;
+ // Can't use std::max, because that's defined in <algorithm>, and we don't
+ // want to pull that in for every compile. The CUDA headers define
+ // ::max(float, float) and ::max(double, double), which is sufficient for us.
+ double __logbw = std::logb(max(std::abs(__c), std::abs(__d)));
+ if (std::isfinite(__logbw)) {
+ __ilogbw = (int)__logbw;
+ __c = std::scalbn(__c, -__ilogbw);
+ __d = std::scalbn(__d, -__ilogbw);
+ }
+ double __denom = __c * __c + __d * __d;
+ double _Complex z;
+ __real__(z) = std::scalbn((__a * __c + __b * __d) / __denom, -__ilogbw);
+ __imag__(z) = std::scalbn((__b * __c - __a * __d) / __denom, -__ilogbw);
+ if (std::isnan(__real__(z)) && std::isnan(__imag__(z))) {
+ if ((__denom == 0.0) && (!std::isnan(__a) || !std::isnan(__b))) {
+ __real__(z) = std::copysign(__builtin_huge_valf(), __c) * __a;
+ __imag__(z) = std::copysign(__builtin_huge_valf(), __c) * __b;
+ } else if ((std::isinf(__a) || std::isinf(__b)) && std::isfinite(__c) &&
+ std::isfinite(__d)) {
+ __a = std::copysign(std::isinf(__a) ? 1.0 : 0.0, __a);
+ __b = std::copysign(std::isinf(__b) ? 1.0 : 0.0, __b);
+ __real__(z) = __builtin_huge_valf() * (__a * __c + __b * __d);
+ __imag__(z) = __builtin_huge_valf() * (__b * __c - __a * __d);
+ } else if (std::isinf(__logbw) && __logbw > 0.0 && std::isfinite(__a) &&
+ std::isfinite(__b)) {
+ __c = std::copysign(std::isinf(__c) ? 1.0 : 0.0, __c);
+ __d = std::copysign(std::isinf(__d) ? 1.0 : 0.0, __d);
+ __real__(z) = 0.0 * (__a * __c + __b * __d);
+ __imag__(z) = 0.0 * (__b * __c - __a * __d);
+ }
+ }
+ return z;
+}
+
+extern "C" inline __device__ float _Complex __divsc3(float __a, float __b,
+ float __c, float __d) {
+ int __ilogbw = 0;
+ float __logbw = std::logb(max(std::abs(__c), std::abs(__d)));
+ if (std::isfinite(__logbw)) {
+ __ilogbw = (int)__logbw;
+ __c = std::scalbn(__c, -__ilogbw);
+ __d = std::scalbn(__d, -__ilogbw);
+ }
+ float __denom = __c * __c + __d * __d;
+ float _Complex z;
+ __real__(z) = std::scalbn((__a * __c + __b * __d) / __denom, -__ilogbw);
+ __imag__(z) = std::scalbn((__b * __c - __a * __d) / __denom, -__ilogbw);
+ if (std::isnan(__real__(z)) && std::isnan(__imag__(z))) {
+ if ((__denom == 0) && (!std::isnan(__a) || !std::isnan(__b))) {
+ __real__(z) = std::copysign(__builtin_huge_valf(), __c) * __a;
+ __imag__(z) = std::copysign(__builtin_huge_valf(), __c) * __b;
+ } else if ((std::isinf(__a) || std::isinf(__b)) && std::isfinite(__c) &&
+ std::isfinite(__d)) {
+ __a = std::copysign(std::isinf(__a) ? 1 : 0, __a);
+ __b = std::copysign(std::isinf(__b) ? 1 : 0, __b);
+ __real__(z) = __builtin_huge_valf() * (__a * __c + __b * __d);
+ __imag__(z) = __builtin_huge_valf() * (__b * __c - __a * __d);
+ } else if (std::isinf(__logbw) && __logbw > 0 && std::isfinite(__a) &&
+ std::isfinite(__b)) {
+ __c = std::copysign(std::isinf(__c) ? 1 : 0, __c);
+ __d = std::copysign(std::isinf(__d) ? 1 : 0, __d);
+ __real__(z) = 0 * (__a * __c + __b * __d);
+ __imag__(z) = 0 * (__b * __c - __a * __d);
+ }
+ }
+ return z;
+}
+
+#endif // __CLANG_CUDA_COMPLEX_BUILTINS
diff --git a/lib/Headers/__clang_cuda_math_forward_declares.h b/lib/Headers/__clang_cuda_math_forward_declares.h
index 3f2834d95000..49c805151d65 100644
--- a/lib/Headers/__clang_cuda_math_forward_declares.h
+++ b/lib/Headers/__clang_cuda_math_forward_declares.h
@@ -140,6 +140,7 @@ __DEVICE__ long lrint(double);
__DEVICE__ long lrint(float);
__DEVICE__ long lround(double);
__DEVICE__ long lround(float);
+__DEVICE__ long long llround(float); // No llround(double).
__DEVICE__ double modf(double, double *);
__DEVICE__ float modf(float, float *);
__DEVICE__ double nan(const char *);
@@ -149,7 +150,8 @@ __DEVICE__ float nearbyint(float);
__DEVICE__ double nextafter(double, double);
__DEVICE__ float nextafter(float, float);
__DEVICE__ double nexttoward(double, double);
-__DEVICE__ float nexttoward(float, float);
+__DEVICE__ float nexttoward(float, double);
+__DEVICE__ float nexttowardf(float, double);
__DEVICE__ double pow(double, double);
__DEVICE__ double pow(double, int);
__DEVICE__ float pow(float, float);
@@ -183,7 +185,19 @@ __DEVICE__ float tgamma(float);
__DEVICE__ double trunc(double);
__DEVICE__ float trunc(float);
+// 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
+// <complex>). Thus the ugliness below.
+#ifdef _LIBCPP_BEGIN_NAMESPACE_STD
+_LIBCPP_BEGIN_NAMESPACE_STD
+#else
namespace std {
+#ifdef _GLIBCXX_BEGIN_NAMESPACE_VERSION
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+#endif
+#endif
+
using ::abs;
using ::acos;
using ::acosh;
@@ -235,6 +249,7 @@ using ::log2;
using ::logb;
using ::lrint;
using ::lround;
+using ::llround;
using ::modf;
using ::nan;
using ::nanf;
@@ -256,7 +271,15 @@ using ::tan;
using ::tanh;
using ::tgamma;
using ::trunc;
+
+#ifdef _LIBCPP_END_NAMESPACE_STD
+_LIBCPP_END_NAMESPACE_STD
+#else
+#ifdef _GLIBCXX_BEGIN_NAMESPACE_VERSION
+_GLIBCXX_END_NAMESPACE_VERSION
+#endif
} // namespace std
+#endif
#pragma pop_macro("__DEVICE__")
diff --git a/lib/Headers/__clang_cuda_runtime_wrapper.h b/lib/Headers/__clang_cuda_runtime_wrapper.h
index 6445f9b76b8f..205e15b40b5d 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 > 7050
+#elif CUDA_VERSION < 7000 || CUDA_VERSION > 8000
#error "Unsupported CUDA version!"
#endif
@@ -72,9 +72,9 @@
#define __CUDA_ARCH__ 350
#endif
-#include "cuda_builtin_vars.h"
+#include "__clang_cuda_builtin_vars.h"
-// No need for device_launch_parameters.h as cuda_builtin_vars.h above
+// No need for device_launch_parameters.h as __clang_cuda_builtin_vars.h above
// has taken care of builtin variables declared in the file.
#define __DEVICE_LAUNCH_PARAMETERS_H__
@@ -113,6 +113,7 @@
#undef __cxa_vec_ctor
#undef __cxa_vec_cctor
#undef __cxa_vec_dtor
+#undef __cxa_vec_new
#undef __cxa_vec_new2
#undef __cxa_vec_new3
#undef __cxa_vec_delete2
@@ -120,6 +121,15 @@
#undef __cxa_vec_delete3
#undef __cxa_pure_virtual
+// math_functions.hpp expects this host function be defined on MacOS, but it
+// ends up not being there because of the games we play here. Just define it
+// ourselves; it's simple enough.
+#ifdef __APPLE__
+inline __host__ double __signbitd(double x) {
+ return std::signbit(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__
@@ -135,6 +145,21 @@
// the headers we're about to include.
#define __host__ UNEXPECTED_HOST_ATTRIBUTE
+// 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.
+// CU_DEVICE_INVALID macro is only defined in 8.0.41, so we use it
+// here to detect the switch.
+
+#if defined(CU_DEVICE_INVALID)
+#if !defined(__USE_FAST_MATH__)
+#define __USE_FAST_MATH__ 0
+#endif
+
+#if !defined(__CUDA_PREC_DIV)
+#define __CUDA_PREC_DIV 0
+#endif
+#endif
+
// device_functions.hpp and math_functions*.hpp use 'static
// __forceinline__' (with no __device__) for definitions of device
// functions. Temporarily redefine __forceinline__ to include
@@ -151,7 +176,7 @@
// slow divides), so we need to scope our define carefully here.
#pragma push_macro("__USE_FAST_MATH__")
#if defined(__CLANG_CUDA_APPROX_TRANSCENDENTALS__)
-#define __USE_FAST_MATH__
+#define __USE_FAST_MATH__ 1
#endif
#include "math_functions.hpp"
#pragma pop_macro("__USE_FAST_MATH__")
@@ -267,8 +292,8 @@ __device__ static inline void *malloc(size_t __size) {
}
} // namespace std
-// Out-of-line implementations from cuda_builtin_vars.h. These need to come
-// after we've pulled in the definition of uint3 and dim3.
+// Out-of-line implementations from __clang_cuda_builtin_vars.h. These need to
+// come after we've pulled in the definition of uint3 and dim3.
__device__ inline __cuda_builtin_threadIdx_t::operator uint3() const {
uint3 ret;
@@ -296,13 +321,14 @@ __device__ inline __cuda_builtin_gridDim_t::operator dim3() const {
#include <__clang_cuda_cmath.h>
#include <__clang_cuda_intrinsics.h>
+#include <__clang_cuda_complex_builtins.h>
// curand_mtgp32_kernel helpfully redeclares blockDim and threadIdx in host
// mode, giving them their "proper" types of dim3 and uint3. This is
-// incompatible with the types we give in cuda_builtin_vars.h. As as hack,
-// force-include the header (nvcc doesn't include it by default) but redefine
-// dim3 and uint3 to our builtin types. (Thankfully dim3 and uint3 are only
-// used here for the redeclarations of blockDim and threadIdx.)
+// incompatible with the types we give in __clang_cuda_builtin_vars.h. As as
+// hack, force-include the header (nvcc doesn't include it by default) but
+// redefine dim3 and uint3 to our builtin types. (Thankfully dim3 and uint3 are
+// only used here for the redeclarations of blockDim and threadIdx.)
#pragma push_macro("dim3")
#pragma push_macro("uint3")
#define dim3 __cuda_builtin_blockDim_t
diff --git a/lib/Headers/__wmmintrin_aes.h b/lib/Headers/__wmmintrin_aes.h
index 211518eb2884..3a2ee1b2ef2e 100644
--- a/lib/Headers/__wmmintrin_aes.h
+++ b/lib/Headers/__wmmintrin_aes.h
@@ -35,7 +35,7 @@
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VAESENC instruction.
+/// This intrinsic corresponds to the <c> VAESENC </c> instruction.
///
/// \param __V
/// A 128-bit integer vector containing the state value.
@@ -55,7 +55,7 @@ _mm_aesenc_si128(__m128i __V, __m128i __R)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VAESENCLAST instruction.
+/// This intrinsic corresponds to the <c> VAESENCLAST </c> instruction.
///
/// \param __V
/// A 128-bit integer vector containing the state value.
@@ -75,7 +75,7 @@ _mm_aesenclast_si128(__m128i __V, __m128i __R)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VAESDEC instruction.
+/// This intrinsic corresponds to the <c> VAESDEC </c> instruction.
///
/// \param __V
/// A 128-bit integer vector containing the state value.
@@ -95,7 +95,7 @@ _mm_aesdec_si128(__m128i __V, __m128i __R)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VAESDECLAST instruction.
+/// This intrinsic corresponds to the <c> VAESDECLAST </c> instruction.
///
/// \param __V
/// A 128-bit integer vector containing the state value.
@@ -114,7 +114,7 @@ _mm_aesdeclast_si128(__m128i __V, __m128i __R)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VAESIMC instruction.
+/// This intrinsic corresponds to the <c> VAESIMC </c> instruction.
///
/// \param __V
/// A 128-bit integer vector containing the expanded key.
@@ -136,7 +136,7 @@ _mm_aesimc_si128(__m128i __V)
/// __m128i _mm_aeskeygenassist_si128(__m128i C, const int R);
/// \endcode
///
-/// This intrinsic corresponds to the \c AESKEYGENASSIST instruction.
+/// This intrinsic corresponds to the <c> AESKEYGENASSIST </c> instruction.
///
/// \param C
/// A 128-bit integer vector that is used to generate the AES encryption key.
diff --git a/lib/Headers/__wmmintrin_pclmul.h b/lib/Headers/__wmmintrin_pclmul.h
index d4e073f40688..e9c6a9f6d415 100644
--- a/lib/Headers/__wmmintrin_pclmul.h
+++ b/lib/Headers/__wmmintrin_pclmul.h
@@ -34,7 +34,7 @@
/// __m128i _mm_clmulepi64_si128(__m128i __X, __m128i __Y, const int __I);
/// \endcode
///
-/// This intrinsic corresponds to the \c VPCLMULQDQ instruction.
+/// This intrinsic corresponds to the <c> VPCLMULQDQ </c> instruction.
///
/// \param __X
/// A 128-bit vector of [2 x i64] containing one of the source operands.
@@ -42,13 +42,12 @@
/// A 128-bit vector of [2 x i64] containing one of the source operands.
/// \param __I
/// An immediate value specifying which 64-bit values to select from the
-/// operands.
-/// Bit 0 is used to select a value from operand __X,
-/// and bit 4 is used to select a value from operand __Y:
-/// Bit[0]=0 indicates that bits[63:0] of operand __X are used.
-/// Bit[0]=1 indicates that bits[127:64] of operand __X are used.
-/// Bit[4]=0 indicates that bits[63:0] of operand __Y are used.
-/// Bit[4]=1 indicates that bits[127:64] of operand __Y are used.
+/// operands. Bit 0 is used to select a value from operand \a __X, and bit
+/// 4 is used to select a value from operand \a __Y: \n
+/// Bit[0]=0 indicates that bits[63:0] of operand \a __X are used. \n
+/// Bit[0]=1 indicates that bits[127:64] of operand \a __X are used. \n
+/// Bit[4]=0 indicates that bits[63:0] of operand \a __Y are used. \n
+/// 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) \
diff --git a/lib/Headers/altivec.h b/lib/Headers/altivec.h
index 74a1914ce83b..d1d1d8026325 100644
--- a/lib/Headers/altivec.h
+++ b/lib/Headers/altivec.h
@@ -34,8 +34,31 @@
#define __CR6_LT 2
#define __CR6_LT_REV 3
+/* Constants for vec_test_data_class */
+#define __VEC_CLASS_FP_SUBNORMAL_N (1 << 0)
+#define __VEC_CLASS_FP_SUBNORMAL_P (1 << 1)
+#define __VEC_CLASS_FP_SUBNORMAL (__VEC_CLASS_FP_SUBNORMAL_P | \
+ __VEC_CLASS_FP_SUBNORMAL_N)
+#define __VEC_CLASS_FP_ZERO_N (1<<2)
+#define __VEC_CLASS_FP_ZERO_P (1<<3)
+#define __VEC_CLASS_FP_ZERO (__VEC_CLASS_FP_ZERO_P | \
+ __VEC_CLASS_FP_ZERO_N)
+#define __VEC_CLASS_FP_INFINITY_N (1<<4)
+#define __VEC_CLASS_FP_INFINITY_P (1<<5)
+#define __VEC_CLASS_FP_INFINITY (__VEC_CLASS_FP_INFINITY_P | \
+ __VEC_CLASS_FP_INFINITY_N)
+#define __VEC_CLASS_FP_NAN (1<<6)
+#define __VEC_CLASS_FP_NOT_NORMAL (__VEC_CLASS_FP_NAN | \
+ __VEC_CLASS_FP_SUBNORMAL | \
+ __VEC_CLASS_FP_ZERO | \
+ __VEC_CLASS_FP_INFINITY)
+
#define __ATTRS_o_ai __attribute__((__overloadable__, __always_inline__))
+#ifdef __POWER9_VECTOR__
+#include <stddef.h>
+#endif
+
static __inline__ vector signed char __ATTRS_o_ai vec_perm(
vector signed char __a, vector signed char __b, vector unsigned char __c);
@@ -134,7 +157,7 @@ static __inline__ vector float __ATTRS_o_ai vec_abs(vector float __a) {
#endif
}
-#if defined(__POWER8_VECTOR__) && defined(__powerpc64__)
+#ifdef __VSX__
static __inline__ vector double __ATTRS_o_ai vec_abs(vector double __a) {
return __builtin_vsx_xvabsdp(__a);
}
@@ -163,6 +186,26 @@ vec_abss(vector signed int __a) {
__a, __builtin_altivec_vsubsws((vector signed int)(0), __a));
}
+/* vec_absd */
+#if defined(__POWER9_VECTOR__)
+
+static __inline__ vector unsigned char __ATTRS_o_ai
+vec_absd(vector unsigned char __a, vector unsigned char __b) {
+ return __builtin_altivec_vabsdub(__a, __b);
+}
+
+static __inline__ vector unsigned short __ATTRS_o_ai
+vec_absd(vector unsigned short __a, vector unsigned short __b) {
+ return __builtin_altivec_vabsduh(__a, __b);
+}
+
+static __inline__ vector unsigned int __ATTRS_o_ai
+vec_absd(vector unsigned int __a, vector unsigned int __b) {
+ return __builtin_altivec_vabsduw(__a, __b);
+}
+
+#endif /* End __POWER9_VECTOR__ */
+
/* vec_add */
static __inline__ vector signed char __ATTRS_o_ai
@@ -305,6 +348,22 @@ vec_adde(vector unsigned __int128 __a, vector unsigned __int128 __b,
}
#endif
+static __inline__ vector signed int __ATTRS_o_ai
+vec_adde(vector signed int __a, vector signed int __b,
+ vector signed int __c) {
+ vector signed int __mask = {1, 1, 1, 1};
+ vector signed int __carry = __c & __mask;
+ return vec_add(vec_add(__a, __b), __carry);
+}
+
+static __inline__ vector unsigned int __ATTRS_o_ai
+vec_adde(vector unsigned int __a, vector unsigned int __b,
+ vector unsigned int __c) {
+ vector unsigned int __mask = {1, 1, 1, 1};
+ vector unsigned int __carry = __c & __mask;
+ return vec_add(vec_add(__a, __b), __carry);
+}
+
/* vec_addec */
#if defined(__POWER8_VECTOR__) && defined(__powerpc64__)
@@ -319,6 +378,50 @@ vec_addec(vector unsigned __int128 __a, vector unsigned __int128 __b,
vector unsigned __int128 __c) {
return __builtin_altivec_vaddecuq(__a, __b, __c);
}
+
+static __inline__ vector signed int __ATTRS_o_ai
+vec_addec(vector signed int __a, vector signed int __b,
+ vector signed int __c) {
+
+ signed int __result[4];
+ for (int i = 0; i < 4; i++) {
+ unsigned int __tempa = (unsigned int) __a[i];
+ unsigned int __tempb = (unsigned int) __b[i];
+ unsigned int __tempc = (unsigned int) __c[i];
+ __tempc = __tempc & 0x00000001;
+ unsigned long long __longa = (unsigned long long) __tempa;
+ unsigned long long __longb = (unsigned long long) __tempb;
+ unsigned long long __longc = (unsigned long long) __tempc;
+ unsigned long long __sum = __longa + __longb + __longc;
+ unsigned long long __res = (__sum >> 32) & 0x01;
+ unsigned long long __tempres = (unsigned int) __res;
+ __result[i] = (signed int) __tempres;
+ }
+
+ vector signed int ret = { __result[0], __result[1], __result[2], __result[3] };
+ return ret;
+}
+
+static __inline__ vector unsigned int __ATTRS_o_ai
+vec_addec(vector unsigned int __a, vector unsigned int __b,
+ vector unsigned int __c) {
+
+ unsigned int __result[4];
+ for (int i = 0; i < 4; i++) {
+ unsigned int __tempc = __c[i] & 1;
+ unsigned long long __longa = (unsigned long long) __a[i];
+ unsigned long long __longb = (unsigned long long) __b[i];
+ unsigned long long __longc = (unsigned long long) __tempc;
+ unsigned long long __sum = __longa + __longb + __longc;
+ unsigned long long __res = (__sum >> 32) & 0x01;
+ unsigned long long __tempres = (unsigned int) __res;
+ __result[i] = (signed int) __tempres;
+ }
+
+ vector unsigned int ret = { __result[0], __result[1], __result[2], __result[3] };
+ return ret;
+}
+
#endif
/* vec_vaddubm */
@@ -1544,6 +1647,12 @@ vec_cmpeq(vector unsigned char __a, vector unsigned char __b) {
(vector char)__b);
}
+static __inline__ vector bool char __ATTRS_o_ai
+vec_cmpeq(vector bool char __a, vector bool char __b) {
+ return (vector bool char)__builtin_altivec_vcmpequb((vector char)__a,
+ (vector char)__b);
+}
+
static __inline__ vector bool short __ATTRS_o_ai vec_cmpeq(vector short __a,
vector short __b) {
return (vector bool short)__builtin_altivec_vcmpequh(__a, __b);
@@ -1555,6 +1664,12 @@ vec_cmpeq(vector unsigned short __a, vector unsigned short __b) {
(vector short)__b);
}
+static __inline__ vector bool short __ATTRS_o_ai
+vec_cmpeq(vector bool short __a, vector bool short __b) {
+ return (vector bool short)__builtin_altivec_vcmpequh((vector short)__a,
+ (vector short)__b);
+}
+
static __inline__ vector bool int __ATTRS_o_ai vec_cmpeq(vector int __a,
vector int __b) {
return (vector bool int)__builtin_altivec_vcmpequw(__a, __b);
@@ -1566,6 +1681,12 @@ vec_cmpeq(vector unsigned int __a, vector unsigned int __b) {
(vector int)__b);
}
+static __inline__ vector bool int __ATTRS_o_ai vec_cmpeq(vector bool int __a,
+ vector bool int __b) {
+ return (vector bool int)__builtin_altivec_vcmpequw((vector int)__a,
+ (vector int)__b);
+}
+
#ifdef __POWER8_VECTOR__
static __inline__ vector bool long long __ATTRS_o_ai
vec_cmpeq(vector signed long long __a, vector signed long long __b) {
@@ -1577,6 +1698,13 @@ vec_cmpeq(vector unsigned long long __a, vector unsigned long long __b) {
return (vector bool long long)__builtin_altivec_vcmpequd(
(vector long long)__a, (vector long long)__b);
}
+
+static __inline__ vector bool long long __ATTRS_o_ai
+vec_cmpeq(vector bool long long __a, vector bool long long __b) {
+ return (vector bool long long)__builtin_altivec_vcmpequd(
+ (vector long long)__a, (vector long long)__b);
+}
+
#endif
static __inline__ vector bool int __ATTRS_o_ai vec_cmpeq(vector float __a,
@@ -1595,6 +1723,199 @@ vec_cmpeq(vector double __a, vector double __b) {
}
#endif
+#ifdef __POWER9_VECTOR__
+/* vec_cmpne */
+
+static __inline__ vector bool char __ATTRS_o_ai
+vec_cmpne(vector bool char __a, vector bool char __b) {
+ return (vector bool char)__builtin_altivec_vcmpneb((vector char)__a,
+ (vector char)__b);
+}
+
+static __inline__ vector bool char __ATTRS_o_ai
+vec_cmpne(vector signed char __a, vector signed char __b) {
+ return (vector bool char)__builtin_altivec_vcmpneb((vector char)__a,
+ (vector char)__b);
+}
+
+static __inline__ vector bool char __ATTRS_o_ai
+vec_cmpne(vector unsigned char __a, vector unsigned char __b) {
+ return (vector bool char)__builtin_altivec_vcmpneb((vector char)__a,
+ (vector char)__b);
+}
+
+static __inline__ vector bool short __ATTRS_o_ai
+vec_cmpne(vector bool short __a, vector bool short __b) {
+ return (vector bool short)__builtin_altivec_vcmpneh((vector short)__a,
+ (vector short)__b);
+}
+
+static __inline__ vector bool short __ATTRS_o_ai
+vec_cmpne(vector signed short __a, vector signed short __b) {
+ return (vector bool short)__builtin_altivec_vcmpneh((vector short)__a,
+ (vector short)__b);
+}
+
+static __inline__ vector bool short __ATTRS_o_ai
+vec_cmpne(vector unsigned short __a, vector unsigned short __b) {
+ return (vector bool short)__builtin_altivec_vcmpneh((vector short)__a,
+ (vector short)__b);
+}
+
+static __inline__ vector bool int __ATTRS_o_ai
+vec_cmpne(vector bool int __a, vector bool int __b) {
+ return (vector bool int)__builtin_altivec_vcmpnew((vector int)__a,
+ (vector int)__b);
+}
+
+static __inline__ vector bool int __ATTRS_o_ai
+vec_cmpne(vector signed int __a, vector signed int __b) {
+ return (vector bool int)__builtin_altivec_vcmpnew((vector int)__a,
+ (vector int)__b);
+}
+
+static __inline__ vector bool int __ATTRS_o_ai
+vec_cmpne(vector unsigned int __a, vector unsigned int __b) {
+ return (vector bool int)__builtin_altivec_vcmpnew((vector int)__a,
+ (vector int)__b);
+}
+
+static __inline__ vector bool long long __ATTRS_o_ai
+vec_cmpne(vector bool long long __a, vector bool long long __b) {
+ return (vector bool long long)
+ ~(__builtin_altivec_vcmpequd((vector long long)__a, (vector long long)__b));
+}
+
+static __inline__ vector bool long long __ATTRS_o_ai
+vec_cmpne(vector signed long long __a, vector signed long long __b) {
+ return (vector bool long long)
+ ~(__builtin_altivec_vcmpequd((vector long long)__a, (vector long long)__b));
+}
+
+static __inline__ vector bool long long __ATTRS_o_ai
+vec_cmpne(vector unsigned long long __a, vector unsigned long long __b) {
+ return (vector bool long long)
+ ~(__builtin_altivec_vcmpequd((vector long long)__a, (vector long long)__b));
+}
+
+static __inline__ vector bool int __ATTRS_o_ai
+vec_cmpne(vector float __a, vector float __b) {
+ return (vector bool int)__builtin_altivec_vcmpnew((vector int)__a,
+ (vector int)__b);
+}
+
+static __inline__ vector bool long long __ATTRS_o_ai
+vec_cmpne(vector double __a, vector double __b) {
+ return (vector bool long long)
+ ~(__builtin_altivec_vcmpequd((vector long long)__a, (vector long long)__b));
+}
+
+/* vec_cmpnez */
+
+static __inline__ vector bool char __ATTRS_o_ai
+vec_cmpnez(vector signed char __a, vector signed char __b) {
+ return (vector bool char)__builtin_altivec_vcmpnezb((vector char)__a,
+ (vector char)__b);
+}
+
+static __inline__ vector bool char __ATTRS_o_ai
+vec_cmpnez(vector unsigned char __a, vector unsigned char __b) {
+ return (vector bool char)__builtin_altivec_vcmpnezb((vector char)__a,
+ (vector char)__b);
+}
+
+static __inline__ vector bool short __ATTRS_o_ai
+vec_cmpnez(vector signed short __a, vector signed short __b) {
+ return (vector bool short)__builtin_altivec_vcmpnezh((vector short)__a,
+ (vector short)__b);
+}
+
+static __inline__ vector bool short __ATTRS_o_ai
+vec_cmpnez(vector unsigned short __a, vector unsigned short __b) {
+ return (vector bool short)__builtin_altivec_vcmpnezh((vector short)__a,
+ (vector short)__b);
+}
+
+static __inline__ vector bool int __ATTRS_o_ai
+vec_cmpnez(vector signed int __a, vector signed int __b) {
+ return (vector bool int)__builtin_altivec_vcmpnezw((vector int)__a,
+ (vector int)__b);
+}
+
+static __inline__ vector bool int __ATTRS_o_ai
+vec_cmpnez(vector unsigned int __a, vector unsigned int __b) {
+ return (vector bool int)__builtin_altivec_vcmpnezw((vector int)__a,
+ (vector int)__b);
+}
+
+static __inline__ signed int __ATTRS_o_ai
+vec_cntlz_lsbb(vector signed char __a) {
+#ifdef __LITTLE_ENDIAN__
+ return __builtin_altivec_vctzlsbb(__a);
+#else
+ return __builtin_altivec_vclzlsbb(__a);
+#endif
+}
+
+static __inline__ signed int __ATTRS_o_ai
+vec_cntlz_lsbb(vector unsigned char __a) {
+#ifdef __LITTLE_ENDIAN__
+ return __builtin_altivec_vctzlsbb(__a);
+#else
+ return __builtin_altivec_vclzlsbb(__a);
+#endif
+}
+
+static __inline__ signed int __ATTRS_o_ai
+vec_cnttz_lsbb(vector signed char __a) {
+#ifdef __LITTLE_ENDIAN__
+ return __builtin_altivec_vclzlsbb(__a);
+#else
+ return __builtin_altivec_vctzlsbb(__a);
+#endif
+}
+
+static __inline__ signed int __ATTRS_o_ai
+vec_cnttz_lsbb(vector unsigned char __a) {
+#ifdef __LITTLE_ENDIAN__
+ return __builtin_altivec_vclzlsbb(__a);
+#else
+ return __builtin_altivec_vctzlsbb(__a);
+#endif
+}
+
+static __inline__ vector unsigned int __ATTRS_o_ai
+vec_parity_lsbb(vector unsigned int __a) {
+ return __builtin_altivec_vprtybw(__a);
+}
+
+static __inline__ vector unsigned int __ATTRS_o_ai
+vec_parity_lsbb(vector signed int __a) {
+ return __builtin_altivec_vprtybw(__a);
+}
+
+static __inline__ vector unsigned __int128 __ATTRS_o_ai
+vec_parity_lsbb(vector unsigned __int128 __a) {
+ return __builtin_altivec_vprtybq(__a);
+}
+
+static __inline__ vector unsigned __int128 __ATTRS_o_ai
+vec_parity_lsbb(vector signed __int128 __a) {
+ return __builtin_altivec_vprtybq(__a);
+}
+
+static __inline__ vector unsigned long long __ATTRS_o_ai
+vec_parity_lsbb(vector unsigned long long __a) {
+ return __builtin_altivec_vprtybd(__a);
+}
+
+static __inline__ vector unsigned long long __ATTRS_o_ai
+vec_parity_lsbb(vector signed long long __a) {
+ return __builtin_altivec_vprtybd(__a);
+}
+
+#endif
+
/* vec_cmpgt */
static __inline__ vector bool char __ATTRS_o_ai
@@ -1882,6 +2203,41 @@ vec_cmplt(vector unsigned long long __a, vector unsigned long long __b) {
return vec_cmpgt(__b, __a);
}
+/* vec_popcnt */
+
+static __inline__ vector signed char __ATTRS_o_ai
+vec_popcnt(vector signed char __a) {
+ return __builtin_altivec_vpopcntb(__a);
+}
+static __inline__ vector unsigned char __ATTRS_o_ai
+vec_popcnt(vector unsigned char __a) {
+ return __builtin_altivec_vpopcntb(__a);
+}
+static __inline__ vector signed short __ATTRS_o_ai
+vec_popcnt(vector signed short __a) {
+ return __builtin_altivec_vpopcnth(__a);
+}
+static __inline__ vector unsigned short __ATTRS_o_ai
+vec_popcnt(vector unsigned short __a) {
+ return __builtin_altivec_vpopcnth(__a);
+}
+static __inline__ vector signed int __ATTRS_o_ai
+vec_popcnt(vector signed int __a) {
+ return __builtin_altivec_vpopcntw(__a);
+}
+static __inline__ vector unsigned int __ATTRS_o_ai
+vec_popcnt(vector unsigned int __a) {
+ return __builtin_altivec_vpopcntw(__a);
+}
+static __inline__ vector signed long long __ATTRS_o_ai
+vec_popcnt(vector signed long long __a) {
+ return __builtin_altivec_vpopcntd(__a);
+}
+static __inline__ vector unsigned long long __ATTRS_o_ai
+vec_popcnt(vector unsigned long long __a) {
+ return __builtin_altivec_vpopcntd(__a);
+}
+
/* vec_cntlz */
static __inline__ vector signed char __ATTRS_o_ai
@@ -1918,6 +2274,603 @@ vec_cntlz(vector unsigned long long __a) {
}
#endif
+#ifdef __POWER9_VECTOR__
+
+/* vec_cnttz */
+
+static __inline__ vector signed char __ATTRS_o_ai
+vec_cnttz(vector signed char __a) {
+ return __builtin_altivec_vctzb(__a);
+}
+static __inline__ vector unsigned char __ATTRS_o_ai
+vec_cnttz(vector unsigned char __a) {
+ return __builtin_altivec_vctzb(__a);
+}
+static __inline__ vector signed short __ATTRS_o_ai
+vec_cnttz(vector signed short __a) {
+ return __builtin_altivec_vctzh(__a);
+}
+static __inline__ vector unsigned short __ATTRS_o_ai
+vec_cnttz(vector unsigned short __a) {
+ return __builtin_altivec_vctzh(__a);
+}
+static __inline__ vector signed int __ATTRS_o_ai
+vec_cnttz(vector signed int __a) {
+ return __builtin_altivec_vctzw(__a);
+}
+static __inline__ vector unsigned int __ATTRS_o_ai
+vec_cnttz(vector unsigned int __a) {
+ return __builtin_altivec_vctzw(__a);
+}
+static __inline__ vector signed long long __ATTRS_o_ai
+vec_cnttz(vector signed long long __a) {
+ return __builtin_altivec_vctzd(__a);
+}
+static __inline__ vector unsigned long long __ATTRS_o_ai
+vec_cnttz(vector unsigned long long __a) {
+ return __builtin_altivec_vctzd(__a);
+}
+
+/* vec_first_match_index */
+
+static __inline__ unsigned __ATTRS_o_ai
+vec_first_match_index(vector signed char __a, vector signed char __b) {
+ vector unsigned long long __res =
+#ifdef __LITTLE_ENDIAN__
+ vec_cnttz((vector unsigned long long)vec_cmpeq(__a, __b));
+#else
+ vec_cntlz((vector unsigned long long)vec_cmpeq(__a, __b));
+#endif
+ if (__res[0] == 64) {
+ return (__res[1] + 64) >> 3;
+ }
+ return __res[0] >> 3;
+}
+
+static __inline__ unsigned __ATTRS_o_ai
+vec_first_match_index(vector unsigned char __a, vector unsigned char __b) {
+ vector unsigned long long __res =
+#ifdef __LITTLE_ENDIAN__
+ vec_cnttz((vector unsigned long long)vec_cmpeq(__a, __b));
+#else
+ vec_cntlz((vector unsigned long long)vec_cmpeq(__a, __b));
+#endif
+ if (__res[0] == 64) {
+ return (__res[1] + 64) >> 3;
+ }
+ return __res[0] >> 3;
+}
+
+static __inline__ unsigned __ATTRS_o_ai
+vec_first_match_index(vector signed short __a, vector signed short __b) {
+ vector unsigned long long __res =
+#ifdef __LITTLE_ENDIAN__
+ vec_cnttz((vector unsigned long long)vec_cmpeq(__a, __b));
+#else
+ vec_cntlz((vector unsigned long long)vec_cmpeq(__a, __b));
+#endif
+ if (__res[0] == 64) {
+ return (__res[1] + 64) >> 4;
+ }
+ return __res[0] >> 4;
+}
+
+static __inline__ unsigned __ATTRS_o_ai
+vec_first_match_index(vector unsigned short __a, vector unsigned short __b) {
+ vector unsigned long long __res =
+#ifdef __LITTLE_ENDIAN__
+ vec_cnttz((vector unsigned long long)vec_cmpeq(__a, __b));
+#else
+ vec_cntlz((vector unsigned long long)vec_cmpeq(__a, __b));
+#endif
+ if (__res[0] == 64) {
+ return (__res[1] + 64) >> 4;
+ }
+ return __res[0] >> 4;
+}
+
+static __inline__ unsigned __ATTRS_o_ai
+vec_first_match_index(vector signed int __a, vector signed int __b) {
+ vector unsigned long long __res =
+#ifdef __LITTLE_ENDIAN__
+ vec_cnttz((vector unsigned long long)vec_cmpeq(__a, __b));
+#else
+ vec_cntlz((vector unsigned long long)vec_cmpeq(__a, __b));
+#endif
+ if (__res[0] == 64) {
+ return (__res[1] + 64) >> 5;
+ }
+ return __res[0] >> 5;
+}
+
+static __inline__ unsigned __ATTRS_o_ai
+vec_first_match_index(vector unsigned int __a, vector unsigned int __b) {
+ vector unsigned long long __res =
+#ifdef __LITTLE_ENDIAN__
+ vec_cnttz((vector unsigned long long)vec_cmpeq(__a, __b));
+#else
+ vec_cntlz((vector unsigned long long)vec_cmpeq(__a, __b));
+#endif
+ if (__res[0] == 64) {
+ return (__res[1] + 64) >> 5;
+ }
+ return __res[0] >> 5;
+}
+
+/* vec_first_match_or_eos_index */
+
+static __inline__ unsigned __ATTRS_o_ai
+vec_first_match_or_eos_index(vector signed char __a, vector signed char __b) {
+ /* Compare the result of the comparison of two vectors with either and OR the
+ result. Either the elements are equal or one will equal the comparison
+ result if either is zero.
+ */
+ vector bool char __tmp1 = vec_cmpeq(__a, __b);
+ vector bool char __tmp2 = __tmp1 |
+ vec_cmpeq((vector signed char)__tmp1, __a) |
+ vec_cmpeq((vector signed char)__tmp1, __b);
+
+ vector unsigned long long __res =
+#ifdef __LITTLE_ENDIAN__
+ vec_cnttz((vector unsigned long long)__tmp2);
+#else
+ vec_cntlz((vector unsigned long long)__tmp2);
+#endif
+ if (__res[0] == 64) {
+ return (__res[1] + 64) >> 3;
+ }
+ return __res[0] >> 3;
+}
+
+static __inline__ unsigned __ATTRS_o_ai
+vec_first_match_or_eos_index(vector unsigned char __a,
+ vector unsigned char __b) {
+ vector bool char __tmp1 = vec_cmpeq(__a, __b);
+ vector bool char __tmp2 = __tmp1 |
+ vec_cmpeq((vector unsigned char)__tmp1, __a) |
+ vec_cmpeq((vector unsigned char)__tmp1, __b);
+
+ vector unsigned long long __res =
+#ifdef __LITTLE_ENDIAN__
+ vec_cnttz((vector unsigned long long)__tmp2);
+#else
+ vec_cntlz((vector unsigned long long)__tmp2);
+#endif
+ if (__res[0] == 64) {
+ return (__res[1] + 64) >> 3;
+ }
+ return __res[0] >> 3;
+}
+
+static __inline__ unsigned __ATTRS_o_ai
+vec_first_match_or_eos_index(vector signed short __a, vector signed short __b) {
+ vector bool short __tmp1 = vec_cmpeq(__a, __b);
+ vector bool short __tmp2 = __tmp1 |
+ vec_cmpeq((vector signed short)__tmp1, __a) |
+ vec_cmpeq((vector signed short)__tmp1, __b);
+
+ vector unsigned long long __res =
+#ifdef __LITTLE_ENDIAN__
+ vec_cnttz((vector unsigned long long)__tmp2);
+#else
+ vec_cntlz((vector unsigned long long)__tmp2);
+#endif
+ if (__res[0] == 64) {
+ return (__res[1] + 64) >> 4;
+ }
+ return __res[0] >> 4;
+}
+
+static __inline__ unsigned __ATTRS_o_ai
+vec_first_match_or_eos_index(vector unsigned short __a,
+ vector unsigned short __b) {
+ vector bool short __tmp1 = vec_cmpeq(__a, __b);
+ vector bool short __tmp2 = __tmp1 |
+ vec_cmpeq((vector unsigned short)__tmp1, __a) |
+ vec_cmpeq((vector unsigned short)__tmp1, __b);
+
+ vector unsigned long long __res =
+#ifdef __LITTLE_ENDIAN__
+ vec_cnttz((vector unsigned long long)__tmp2);
+#else
+ vec_cntlz((vector unsigned long long)__tmp2);
+#endif
+ if (__res[0] == 64) {
+ return (__res[1] + 64) >> 4;
+ }
+ return __res[0] >> 4;
+}
+
+static __inline__ unsigned __ATTRS_o_ai
+vec_first_match_or_eos_index(vector signed int __a, vector signed int __b) {
+ vector bool int __tmp1 = vec_cmpeq(__a, __b);
+ vector bool int __tmp2 = __tmp1 | vec_cmpeq((vector signed int)__tmp1, __a) |
+ vec_cmpeq((vector signed int)__tmp1, __b);
+
+ vector unsigned long long __res =
+#ifdef __LITTLE_ENDIAN__
+ vec_cnttz((vector unsigned long long)__tmp2);
+#else
+ vec_cntlz((vector unsigned long long)__tmp2);
+#endif
+ if (__res[0] == 64) {
+ return (__res[1] + 64) >> 5;
+ }
+ return __res[0] >> 5;
+}
+
+static __inline__ unsigned __ATTRS_o_ai
+vec_first_match_or_eos_index(vector unsigned int __a, vector unsigned int __b) {
+ vector bool int __tmp1 = vec_cmpeq(__a, __b);
+ vector bool int __tmp2 = __tmp1 |
+ vec_cmpeq((vector unsigned int)__tmp1, __a) |
+ vec_cmpeq((vector unsigned int)__tmp1, __b);
+
+ vector unsigned long long __res =
+#ifdef __LITTLE_ENDIAN__
+ vec_cnttz((vector unsigned long long)__tmp2);
+#else
+ vec_cntlz((vector unsigned long long)__tmp2);
+#endif
+ if (__res[0] == 64) {
+ return (__res[1] + 64) >> 5;
+ }
+ return __res[0] >> 5;
+}
+
+/* vec_first_mismatch_index */
+
+static __inline__ unsigned __ATTRS_o_ai
+vec_first_mismatch_index(vector signed char __a, vector signed char __b) {
+ vector unsigned long long __res =
+#ifdef __LITTLE_ENDIAN__
+ vec_cnttz((vector unsigned long long)vec_cmpne(__a, __b));
+#else
+ vec_cntlz((vector unsigned long long)vec_cmpne(__a, __b));
+#endif
+ if (__res[0] == 64) {
+ return (__res[1] + 64) >> 3;
+ }
+ return __res[0] >> 3;
+}
+
+static __inline__ unsigned __ATTRS_o_ai
+vec_first_mismatch_index(vector unsigned char __a, vector unsigned char __b) {
+ vector unsigned long long __res =
+#ifdef __LITTLE_ENDIAN__
+ vec_cnttz((vector unsigned long long)vec_cmpne(__a, __b));
+#else
+ vec_cntlz((vector unsigned long long)vec_cmpne(__a, __b));
+#endif
+ if (__res[0] == 64) {
+ return (__res[1] + 64) >> 3;
+ }
+ return __res[0] >> 3;
+}
+
+static __inline__ unsigned __ATTRS_o_ai
+vec_first_mismatch_index(vector signed short __a, vector signed short __b) {
+ vector unsigned long long __res =
+#ifdef __LITTLE_ENDIAN__
+ vec_cnttz((vector unsigned long long)vec_cmpne(__a, __b));
+#else
+ vec_cntlz((vector unsigned long long)vec_cmpne(__a, __b));
+#endif
+ if (__res[0] == 64) {
+ return (__res[1] + 64) >> 4;
+ }
+ return __res[0] >> 4;
+}
+
+static __inline__ unsigned __ATTRS_o_ai
+vec_first_mismatch_index(vector unsigned short __a, vector unsigned short __b) {
+ vector unsigned long long __res =
+#ifdef __LITTLE_ENDIAN__
+ vec_cnttz((vector unsigned long long)vec_cmpne(__a, __b));
+#else
+ vec_cntlz((vector unsigned long long)vec_cmpne(__a, __b));
+#endif
+ if (__res[0] == 64) {
+ return (__res[1] + 64) >> 4;
+ }
+ return __res[0] >> 4;
+}
+
+static __inline__ unsigned __ATTRS_o_ai
+vec_first_mismatch_index(vector signed int __a, vector signed int __b) {
+ vector unsigned long long __res =
+#ifdef __LITTLE_ENDIAN__
+ vec_cnttz((vector unsigned long long)vec_cmpne(__a, __b));
+#else
+ vec_cntlz((vector unsigned long long)vec_cmpne(__a, __b));
+#endif
+ if (__res[0] == 64) {
+ return (__res[1] + 64) >> 5;
+ }
+ return __res[0] >> 5;
+}
+
+static __inline__ unsigned __ATTRS_o_ai
+vec_first_mismatch_index(vector unsigned int __a, vector unsigned int __b) {
+ vector unsigned long long __res =
+#ifdef __LITTLE_ENDIAN__
+ vec_cnttz((vector unsigned long long)vec_cmpne(__a, __b));
+#else
+ vec_cntlz((vector unsigned long long)vec_cmpne(__a, __b));
+#endif
+ if (__res[0] == 64) {
+ return (__res[1] + 64) >> 5;
+ }
+ return __res[0] >> 5;
+}
+
+/* vec_first_mismatch_or_eos_index */
+
+static __inline__ unsigned __ATTRS_o_ai
+vec_first_mismatch_or_eos_index(vector signed char __a,
+ vector signed char __b) {
+ vector unsigned long long __res =
+#ifdef __LITTLE_ENDIAN__
+ vec_cnttz((vector unsigned long long)vec_cmpnez(__a, __b));
+#else
+ vec_cntlz((vector unsigned long long)vec_cmpnez(__a, __b));
+#endif
+ if (__res[0] == 64) {
+ return (__res[1] + 64) >> 3;
+ }
+ return __res[0] >> 3;
+}
+
+static __inline__ unsigned __ATTRS_o_ai
+vec_first_mismatch_or_eos_index(vector unsigned char __a,
+ vector unsigned char __b) {
+ vector unsigned long long __res =
+#ifdef __LITTLE_ENDIAN__
+ vec_cnttz((vector unsigned long long)vec_cmpnez(__a, __b));
+#else
+ vec_cntlz((vector unsigned long long)vec_cmpnez(__a, __b));
+#endif
+ if (__res[0] == 64) {
+ return (__res[1] + 64) >> 3;
+ }
+ return __res[0] >> 3;
+}
+
+static __inline__ unsigned __ATTRS_o_ai
+vec_first_mismatch_or_eos_index(vector signed short __a,
+ vector signed short __b) {
+ vector unsigned long long __res =
+#ifdef __LITTLE_ENDIAN__
+ vec_cnttz((vector unsigned long long)vec_cmpnez(__a, __b));
+#else
+ vec_cntlz((vector unsigned long long)vec_cmpnez(__a, __b));
+#endif
+ if (__res[0] == 64) {
+ return (__res[1] + 64) >> 4;
+ }
+ return __res[0] >> 4;
+}
+
+static __inline__ unsigned __ATTRS_o_ai
+vec_first_mismatch_or_eos_index(vector unsigned short __a,
+ vector unsigned short __b) {
+ vector unsigned long long __res =
+#ifdef __LITTLE_ENDIAN__
+ vec_cnttz((vector unsigned long long)vec_cmpnez(__a, __b));
+#else
+ vec_cntlz((vector unsigned long long)vec_cmpnez(__a, __b));
+#endif
+ if (__res[0] == 64) {
+ return (__res[1] + 64) >> 4;
+ }
+ return __res[0] >> 4;
+}
+
+static __inline__ unsigned __ATTRS_o_ai
+vec_first_mismatch_or_eos_index(vector signed int __a, vector signed int __b) {
+ vector unsigned long long __res =
+#ifdef __LITTLE_ENDIAN__
+ vec_cnttz((vector unsigned long long)vec_cmpnez(__a, __b));
+#else
+ vec_cntlz((vector unsigned long long)vec_cmpnez(__a, __b));
+#endif
+ if (__res[0] == 64) {
+ return (__res[1] + 64) >> 5;
+ }
+ return __res[0] >> 5;
+}
+
+static __inline__ unsigned __ATTRS_o_ai
+vec_first_mismatch_or_eos_index(vector unsigned int __a,
+ vector unsigned int __b) {
+ vector unsigned long long __res =
+#ifdef __LITTLE_ENDIAN__
+ vec_cnttz((vector unsigned long long)vec_cmpnez(__a, __b));
+#else
+ vec_cntlz((vector unsigned long long)vec_cmpnez(__a, __b));
+#endif
+ if (__res[0] == 64) {
+ return (__res[1] + 64) >> 5;
+ }
+ return __res[0] >> 5;
+}
+
+static __inline__ vector double __ATTRS_o_ai
+vec_insert_exp(vector double __a, vector unsigned long long __b) {
+ return __builtin_vsx_xviexpdp((vector unsigned long long)__a,__b);
+}
+
+static __inline__ vector double __ATTRS_o_ai
+vec_insert_exp(vector unsigned long long __a, vector unsigned long long __b) {
+ return __builtin_vsx_xviexpdp(__a,__b);
+}
+
+static __inline__ vector float __ATTRS_o_ai
+vec_insert_exp(vector float __a, vector unsigned int __b) {
+ return __builtin_vsx_xviexpsp((vector unsigned int)__a,__b);
+}
+
+static __inline__ vector float __ATTRS_o_ai
+vec_insert_exp(vector unsigned int __a, vector unsigned int __b) {
+ return __builtin_vsx_xviexpsp(__a,__b);
+}
+
+#if defined(__powerpc64__)
+static __inline__ vector signed char __ATTRS_o_ai vec_xl_len(signed char *__a,
+ size_t __b) {
+ return (vector signed char)__builtin_vsx_lxvl(__a, (__b << 56));
+}
+
+static __inline__ vector unsigned char __ATTRS_o_ai
+vec_xl_len(unsigned char *__a, size_t __b) {
+ return (vector unsigned char)__builtin_vsx_lxvl(__a, (__b << 56));
+}
+
+static __inline__ vector signed short __ATTRS_o_ai vec_xl_len(signed short *__a,
+ size_t __b) {
+ return (vector signed short)__builtin_vsx_lxvl(__a, (__b << 56));
+}
+
+static __inline__ vector unsigned short __ATTRS_o_ai
+vec_xl_len(unsigned short *__a, size_t __b) {
+ return (vector unsigned short)__builtin_vsx_lxvl(__a, (__b << 56));
+}
+
+static __inline__ vector signed int __ATTRS_o_ai vec_xl_len(signed int *__a,
+ size_t __b) {
+ return (vector signed int)__builtin_vsx_lxvl(__a, (__b << 56));
+}
+
+static __inline__ vector unsigned int __ATTRS_o_ai vec_xl_len(unsigned int *__a,
+ size_t __b) {
+ return (vector unsigned int)__builtin_vsx_lxvl(__a, (__b << 56));
+}
+
+static __inline__ vector float __ATTRS_o_ai vec_xl_len(float *__a, size_t __b) {
+ return (vector float)__builtin_vsx_lxvl(__a, (__b << 56));
+}
+
+static __inline__ vector signed __int128 __ATTRS_o_ai
+vec_xl_len(signed __int128 *__a, size_t __b) {
+ return (vector signed __int128)__builtin_vsx_lxvl(__a, (__b << 56));
+}
+
+static __inline__ vector unsigned __int128 __ATTRS_o_ai
+vec_xl_len(unsigned __int128 *__a, size_t __b) {
+ return (vector unsigned __int128)__builtin_vsx_lxvl(__a, (__b << 56));
+}
+
+static __inline__ vector signed long long __ATTRS_o_ai
+vec_xl_len(signed long long *__a, size_t __b) {
+ return (vector signed long long)__builtin_vsx_lxvl(__a, (__b << 56));
+}
+
+static __inline__ vector unsigned long long __ATTRS_o_ai
+vec_xl_len(unsigned long long *__a, size_t __b) {
+ return (vector unsigned long long)__builtin_vsx_lxvl(__a, (__b << 56));
+}
+
+static __inline__ vector double __ATTRS_o_ai vec_xl_len(double *__a,
+ size_t __b) {
+ return (vector double)__builtin_vsx_lxvl(__a, (__b << 56));
+}
+
+static __inline__ vector double __ATTRS_o_ai vec_xl_len_r(unsigned char *__a,
+ size_t __b) {
+ vector unsigned char __res =
+ (vector unsigned char)__builtin_vsx_lxvll(__a, (__b << 56));
+#ifdef __LITTLE_ENDIAN__
+ vector unsigned char __mask =
+ (vector unsigned char)__builtin_altivec_lvsr(16 - __b, (int *)NULL);
+ __res = (vector unsigned char)__builtin_altivec_vperm_4si(
+ (vector int)__res, (vector int)__res, __mask);
+#endif
+ return __res;
+}
+
+// vec_xst_len
+static __inline__ void __ATTRS_o_ai vec_xst_len(vector unsigned char __a,
+ unsigned char *__b,
+ size_t __c) {
+ return __builtin_vsx_stxvl((vector int)__a, __b, (__c << 56));
+}
+
+static __inline__ void __ATTRS_o_ai vec_xst_len(vector signed char __a,
+ signed char *__b, size_t __c) {
+ return __builtin_vsx_stxvl((vector int)__a, __b, (__c << 56));
+}
+
+static __inline__ void __ATTRS_o_ai vec_xst_len(vector signed short __a,
+ signed short *__b, size_t __c) {
+ return __builtin_vsx_stxvl((vector int)__a, __b, (__c << 56));
+}
+
+static __inline__ void __ATTRS_o_ai vec_xst_len(vector unsigned short __a,
+ unsigned short *__b,
+ size_t __c) {
+ return __builtin_vsx_stxvl((vector int)__a, __b, (__c << 56));
+}
+
+static __inline__ void __ATTRS_o_ai vec_xst_len(vector signed int __a,
+ signed int *__b, size_t __c) {
+ return __builtin_vsx_stxvl((vector int)__a, __b, (__c << 56));
+}
+
+static __inline__ void __ATTRS_o_ai vec_xst_len(vector unsigned int __a,
+ unsigned int *__b, size_t __c) {
+ return __builtin_vsx_stxvl((vector int)__a, __b, (__c << 56));
+}
+
+static __inline__ void __ATTRS_o_ai vec_xst_len(vector float __a, float *__b,
+ size_t __c) {
+ return __builtin_vsx_stxvl((vector int)__a, __b, (__c << 56));
+}
+
+static __inline__ void __ATTRS_o_ai vec_xst_len(vector signed __int128 __a,
+ signed __int128 *__b,
+ size_t __c) {
+ return __builtin_vsx_stxvl((vector int)__a, __b, (__c << 56));
+}
+
+static __inline__ void __ATTRS_o_ai vec_xst_len(vector unsigned __int128 __a,
+ unsigned __int128 *__b,
+ size_t __c) {
+ return __builtin_vsx_stxvl((vector int)__a, __b, (__c << 56));
+}
+
+static __inline__ void __ATTRS_o_ai vec_xst_len(vector signed long long __a,
+ signed long long *__b,
+ size_t __c) {
+ return __builtin_vsx_stxvl((vector int)__a, __b, (__c << 56));
+}
+
+static __inline__ void __ATTRS_o_ai vec_xst_len(vector unsigned long long __a,
+ unsigned long long *__b,
+ size_t __c) {
+ return __builtin_vsx_stxvl((vector int)__a, __b, (__c << 56));
+}
+
+static __inline__ void __ATTRS_o_ai vec_xst_len(vector double __a, double *__b,
+ size_t __c) {
+ return __builtin_vsx_stxvl((vector int)__a, __b, (__c << 56));
+}
+
+static __inline__ void __ATTRS_o_ai vec_xst_len_r(vector unsigned char __a,
+ unsigned char *__b,
+ size_t __c) {
+#ifdef __LITTLE_ENDIAN__
+ vector unsigned char __mask =
+ (vector unsigned char)__builtin_altivec_lvsl(16 - __c, (int *)NULL);
+ vector unsigned char __res =
+ __builtin_altivec_vperm_4si((vector int)__a, (vector int)__a, __mask);
+ return __builtin_vsx_stxvll((vector int)__res, __b, (__c << 56));
+#else
+ return __builtin_vsx_stxvll((vector int)__a, __b, (__c << 56));
+#endif
+}
+#endif
+#endif
+
/* vec_cpsgn */
#ifdef __VSX__
@@ -2016,20 +2969,284 @@ vec_vctuxs(vector float __a, int __b) {
return __builtin_altivec_vctuxs(__a, __b);
}
+/* vec_signed */
+
+static __inline__ vector signed int __ATTRS_o_ai
+vec_sld(vector signed int, vector signed int, unsigned const int __c);
+
+static __inline__ vector signed int __ATTRS_o_ai
+vec_signed(vector float __a) {
+ return __builtin_convertvector(__a, vector signed int);
+}
+
+#ifdef __VSX__
+static __inline__ vector signed long long __ATTRS_o_ai
+vec_signed(vector double __a) {
+ return __builtin_convertvector(__a, vector signed long long);
+}
+
+static __inline__ vector signed int __attribute__((__always_inline__))
+vec_signed2(vector double __a, vector double __b) {
+ return (vector signed int) { __a[0], __a[1], __b[0], __b[1] };
+}
+
+static __inline__ vector signed int __ATTRS_o_ai
+vec_signede(vector double __a) {
+#ifdef __LITTLE_ENDIAN__
+ vector signed int __ret = __builtin_vsx_xvcvdpsxws(__a);
+ return vec_sld(__ret, __ret, 12);
+#else
+ return __builtin_vsx_xvcvdpsxws(__a);
+#endif
+}
+
+static __inline__ vector signed int __ATTRS_o_ai
+vec_signedo(vector double __a) {
+#ifdef __LITTLE_ENDIAN__
+ return __builtin_vsx_xvcvdpsxws(__a);
+#else
+ vector signed int __ret = __builtin_vsx_xvcvdpsxws(__a);
+ return vec_sld(__ret, __ret, 12);
+#endif
+}
+#endif
+
+/* vec_unsigned */
+
+static __inline__ vector unsigned int __ATTRS_o_ai
+vec_sld(vector unsigned int, vector unsigned int, unsigned const int __c);
+
+static __inline__ vector unsigned int __ATTRS_o_ai
+vec_unsigned(vector float __a) {
+ return __builtin_convertvector(__a, vector unsigned int);
+}
+
+#ifdef __VSX__
+static __inline__ vector unsigned long long __ATTRS_o_ai
+vec_unsigned(vector double __a) {
+ return __builtin_convertvector(__a, vector unsigned long long);
+}
+
+static __inline__ vector unsigned int __attribute__((__always_inline__))
+vec_unsigned2(vector double __a, vector double __b) {
+ return (vector unsigned int) { __a[0], __a[1], __b[0], __b[1] };
+}
+
+static __inline__ vector unsigned int __ATTRS_o_ai
+vec_unsignede(vector double __a) {
+#ifdef __LITTLE_ENDIAN__
+ vector unsigned int __ret = __builtin_vsx_xvcvdpuxws(__a);
+ return vec_sld(__ret, __ret, 12);
+#else
+ return __builtin_vsx_xvcvdpuxws(__a);
+#endif
+}
+
+static __inline__ vector unsigned int __ATTRS_o_ai
+vec_unsignedo(vector double __a) {
+#ifdef __LITTLE_ENDIAN__
+ return __builtin_vsx_xvcvdpuxws(__a);
+#else
+ vector unsigned int __ret = __builtin_vsx_xvcvdpuxws(__a);
+ return vec_sld(__ret, __ret, 12);
+#endif
+}
+#endif
+
+/* vec_float */
+
+static __inline__ vector float __ATTRS_o_ai
+vec_sld(vector float, vector float, unsigned const int __c);
+
+static __inline__ vector float __ATTRS_o_ai
+vec_float(vector signed int __a) {
+ return __builtin_convertvector(__a, vector float);
+}
+
+static __inline__ vector float __ATTRS_o_ai
+vec_float(vector unsigned int __a) {
+ return __builtin_convertvector(__a, vector float);
+}
+
+#ifdef __VSX__
+static __inline__ vector float __ATTRS_o_ai
+vec_float2(vector signed long long __a, vector signed long long __b) {
+ return (vector float) { __a[0], __a[1], __b[0], __b[1] };
+}
+
+static __inline__ vector float __ATTRS_o_ai
+vec_float2(vector unsigned long long __a, vector unsigned long long __b) {
+ return (vector float) { __a[0], __a[1], __b[0], __b[1] };
+}
+
+static __inline__ vector float __ATTRS_o_ai
+vec_float2(vector double __a, vector double __b) {
+ return (vector float) { __a[0], __a[1], __b[0], __b[1] };
+}
+
+static __inline__ vector float __ATTRS_o_ai
+vec_floate(vector signed long long __a) {
+#ifdef __LITTLE_ENDIAN__
+ vector float __ret = __builtin_vsx_xvcvsxdsp(__a);
+ return vec_sld(__ret, __ret, 12);
+#else
+ return __builtin_vsx_xvcvsxdsp(__a);
+#endif
+}
+
+static __inline__ vector float __ATTRS_o_ai
+vec_floate(vector unsigned long long __a) {
+#ifdef __LITTLE_ENDIAN__
+ vector float __ret = __builtin_vsx_xvcvuxdsp(__a);
+ return vec_sld(__ret, __ret, 12);
+#else
+ return __builtin_vsx_xvcvuxdsp(__a);
+#endif
+}
+
+static __inline__ vector float __ATTRS_o_ai
+vec_floate(vector double __a) {
+#ifdef __LITTLE_ENDIAN__
+ vector float __ret = __builtin_vsx_xvcvdpsp(__a);
+ return vec_sld(__ret, __ret, 12);
+#else
+ return __builtin_vsx_xvcvdpsp(__a);
+#endif
+}
+
+static __inline__ vector float __ATTRS_o_ai
+vec_floato(vector signed long long __a) {
+#ifdef __LITTLE_ENDIAN__
+ return __builtin_vsx_xvcvsxdsp(__a);
+#else
+ vector float __ret = __builtin_vsx_xvcvsxdsp(__a);
+ return vec_sld(__ret, __ret, 12);
+#endif
+}
+
+static __inline__ vector float __ATTRS_o_ai
+vec_floato(vector unsigned long long __a) {
+#ifdef __LITTLE_ENDIAN__
+ return __builtin_vsx_xvcvuxdsp(__a);
+#else
+ vector float __ret = __builtin_vsx_xvcvuxdsp(__a);
+ return vec_sld(__ret, __ret, 12);
+#endif
+}
+
+static __inline__ vector float __ATTRS_o_ai
+vec_floato(vector double __a) {
+#ifdef __LITTLE_ENDIAN__
+ return __builtin_vsx_xvcvdpsp(__a);
+#else
+ vector float __ret = __builtin_vsx_xvcvdpsp(__a);
+ return vec_sld(__ret, __ret, 12);
+#endif
+}
+#endif
+
/* vec_double */
#ifdef __VSX__
static __inline__ vector double __ATTRS_o_ai
vec_double(vector signed long long __a) {
+ return __builtin_convertvector(__a, vector double);
+}
+
+static __inline__ vector double __ATTRS_o_ai
+vec_double(vector unsigned long long __a) {
+ return __builtin_convertvector(__a, vector double);
+}
+
+static __inline__ vector double __ATTRS_o_ai
+vec_doublee(vector signed int __a) {
+#ifdef __LITTLE_ENDIAN__
+ return __builtin_vsx_xvcvsxwdp(vec_sld(__a, __a, 4));
+#else
+ return __builtin_vsx_xvcvsxwdp(__a);
+#endif
+}
+
+static __inline__ vector double __ATTRS_o_ai
+vec_doublee(vector unsigned int __a) {
+#ifdef __LITTLE_ENDIAN__
+ return __builtin_vsx_xvcvuxwdp(vec_sld(__a, __a, 4));
+#else
+ return __builtin_vsx_xvcvuxwdp(__a);
+#endif
+}
+
+static __inline__ vector double __ATTRS_o_ai
+vec_doublee(vector float __a) {
+#ifdef __LITTLE_ENDIAN__
+ return __builtin_vsx_xvcvspdp(vec_sld(__a, __a, 4));
+#else
+ return __builtin_vsx_xvcvspdp(__a);
+#endif
+}
+
+static __inline__ vector double __ATTRS_o_ai
+vec_doubleh(vector signed int __a) {
vector double __ret = {__a[0], __a[1]};
return __ret;
}
static __inline__ vector double __ATTRS_o_ai
-vec_double(vector unsigned long long __a) {
+vec_doubleh(vector unsigned int __a) {
vector double __ret = {__a[0], __a[1]};
return __ret;
}
+
+static __inline__ vector double __ATTRS_o_ai
+vec_doubleh(vector float __a) {
+ vector double __ret = {__a[0], __a[1]};
+ return __ret;
+}
+
+static __inline__ vector double __ATTRS_o_ai
+vec_doublel(vector signed int __a) {
+ vector double __ret = {__a[2], __a[3]};
+ return __ret;
+}
+
+static __inline__ vector double __ATTRS_o_ai
+vec_doublel(vector unsigned int __a) {
+ vector double __ret = {__a[2], __a[3]};
+ return __ret;
+}
+
+static __inline__ vector double __ATTRS_o_ai
+vec_doublel(vector float __a) {
+ vector double __ret = {__a[2], __a[3]};
+ return __ret;
+}
+
+static __inline__ vector double __ATTRS_o_ai
+vec_doubleo(vector signed int __a) {
+#ifdef __LITTLE_ENDIAN__
+ return __builtin_vsx_xvcvsxwdp(__a);
+#else
+ return __builtin_vsx_xvcvsxwdp(vec_sld(__a, __a, 4));
+#endif
+}
+
+static __inline__ vector double __ATTRS_o_ai
+vec_doubleo(vector unsigned int __a) {
+#ifdef __LITTLE_ENDIAN__
+ return __builtin_vsx_xvcvuxwdp(__a);
+#else
+ return __builtin_vsx_xvcvuxwdp(vec_sld(__a, __a, 4));
+#endif
+}
+
+static __inline__ vector double __ATTRS_o_ai
+vec_doubleo(vector float __a) {
+#ifdef __LITTLE_ENDIAN__
+ return __builtin_vsx_xvcvspdp(__a);
+#else
+ return __builtin_vsx_xvcvspdp(vec_sld(__a, __a, 4));
+#endif
+}
#endif
/* vec_div */
@@ -3835,6 +5052,34 @@ vec_mergee(vector unsigned int __a, vector unsigned int __b) {
0x18, 0x19, 0x1A, 0x1B));
}
+static __inline__ vector bool long long __ATTRS_o_ai
+vec_mergee(vector bool long long __a, vector bool long long __b) {
+ return vec_mergeh(__a, __b);
+}
+
+static __inline__ vector signed long long __ATTRS_o_ai
+vec_mergee(vector signed long long __a, vector signed long long __b) {
+ return vec_mergeh(__a, __b);
+}
+
+static __inline__ vector unsigned long long __ATTRS_o_ai
+vec_mergee(vector unsigned long long __a, vector unsigned long long __b) {
+ return vec_mergeh(__a, __b);
+}
+
+static __inline__ vector float __ATTRS_o_ai
+vec_mergee(vector float __a, vector float __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x00, 0x01, 0x02, 0x03, 0x10, 0x11,
+ 0x12, 0x13, 0x08, 0x09, 0x0A, 0x0B,
+ 0x18, 0x19, 0x1A, 0x1B));
+}
+
+static __inline__ vector double __ATTRS_o_ai
+vec_mergee(vector double __a, vector double __b) {
+ return vec_mergeh(__a, __b);
+}
+
/* vec_mergeo */
static __inline__ vector bool int __ATTRS_o_ai vec_mergeo(vector bool int __a,
@@ -3861,6 +5106,34 @@ vec_mergeo(vector unsigned int __a, vector unsigned int __b) {
0x1C, 0x1D, 0x1E, 0x1F));
}
+static __inline__ vector bool long long __ATTRS_o_ai
+vec_mergeo(vector bool long long __a, vector bool long long __b) {
+ return vec_mergel(__a, __b);
+}
+
+static __inline__ vector signed long long __ATTRS_o_ai
+vec_mergeo(vector signed long long __a, vector signed long long __b) {
+ return vec_mergel(__a, __b);
+}
+
+static __inline__ vector unsigned long long __ATTRS_o_ai
+vec_mergeo(vector unsigned long long __a, vector unsigned long long __b) {
+ return vec_mergel(__a, __b);
+}
+
+static __inline__ vector float __ATTRS_o_ai
+vec_mergeo(vector float __a, vector float __b) {
+ return vec_perm(__a, __b,
+ (vector unsigned char)(0x04, 0x05, 0x06, 0x07, 0x14, 0x15,
+ 0x16, 0x17, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x1C, 0x1D, 0x1E, 0x1F));
+}
+
+static __inline__ vector double __ATTRS_o_ai
+vec_mergeo(vector double __a, vector double __b) {
+ return vec_mergel(__a, __b);
+}
+
#endif
/* vec_mfvscr */
@@ -4689,6 +5962,12 @@ static __inline__ vector bool int __ATTRS_o_ai vec_nand(vector bool int __a,
return ~(__a & __b);
}
+static __inline__ vector float __ATTRS_o_ai
+vec_nand(vector float __a, vector float __b) {
+ return (vector float)(~((vector unsigned int)__a &
+ (vector unsigned int)__b));
+}
+
static __inline__ vector signed long long __ATTRS_o_ai
vec_nand(vector signed long long __a, vector signed long long __b) {
return ~(__a & __b);
@@ -4724,6 +6003,12 @@ vec_nand(vector bool long long __a, vector bool long long __b) {
return ~(__a & __b);
}
+static __inline__ vector double __ATTRS_o_ai
+vec_nand(vector double __a, vector double __b) {
+ return (vector double)(~((vector unsigned long long)__a &
+ (vector unsigned long long)__b));
+}
+
#endif
/* vec_nmadd */
@@ -5195,6 +6480,16 @@ static __inline__ vector bool int __ATTRS_o_ai vec_orc(vector bool int __a,
return __a | ~__b;
}
+static __inline__ vector float __ATTRS_o_ai
+vec_orc(vector bool int __a, vector float __b) {
+ return (vector float)(__a | ~(vector unsigned int)__b);
+}
+
+static __inline__ vector float __ATTRS_o_ai
+vec_orc(vector float __a, vector bool int __b) {
+ return (vector float)((vector unsigned int)__a | ~__b);
+}
+
static __inline__ vector signed long long __ATTRS_o_ai
vec_orc(vector signed long long __a, vector signed long long __b) {
return __a | ~__b;
@@ -5229,6 +6524,16 @@ static __inline__ vector bool long long __ATTRS_o_ai
vec_orc(vector bool long long __a, vector bool long long __b) {
return __a | ~__b;
}
+
+static __inline__ vector double __ATTRS_o_ai
+vec_orc(vector double __a, vector bool long long __b) {
+ return (vector double)((vector unsigned long long)__a | ~__b);
+}
+
+static __inline__ vector double __ATTRS_o_ai
+vec_orc(vector bool long long __a, vector double __b) {
+ return (vector double)(__a | ~(vector unsigned long long)__b);
+}
#endif
/* vec_vor */
@@ -5536,8 +6841,25 @@ vec_pack(vector bool long long __a, vector bool long long __b) {
#endif
}
+static __inline__ vector float __ATTRS_o_ai
+vec_pack(vector double __a, vector double __b) {
+ return (vector float) (__a[0], __a[1], __b[0], __b[1]);
+}
#endif
+#ifdef __POWER9_VECTOR__
+static __inline__ vector unsigned short __ATTRS_o_ai
+vec_pack_to_short_fp32(vector float __a, vector float __b) {
+ vector float __resa = __builtin_vsx_xvcvsphp(__a);
+ vector float __resb = __builtin_vsx_xvcvsphp(__b);
+#ifdef __LITTLE_ENDIAN__
+ return (vector unsigned short)vec_mergee(__resa, __resb);
+#else
+ return (vector unsigned short)vec_mergeo(__resa, __resb);
+#endif
+}
+
+#endif
/* vec_vpkuhum */
#define __builtin_altivec_vpkuhum vec_vpkuhum
@@ -6324,6 +7646,34 @@ vec_rl(vector unsigned long long __a, vector unsigned long long __b) {
}
#endif
+/* vec_rlmi */
+#ifdef __POWER9_VECTOR__
+static __inline__ vector unsigned int __ATTRS_o_ai
+vec_rlmi(vector unsigned int __a, vector unsigned int __b,
+ vector unsigned int __c) {
+ return __builtin_altivec_vrlwmi(__a, __c, __b);
+}
+
+static __inline__ vector unsigned long long __ATTRS_o_ai
+vec_rlmi(vector unsigned long long __a, vector unsigned long long __b,
+ vector unsigned long long __c) {
+ return __builtin_altivec_vrldmi(__a, __c, __b);
+}
+
+/* vec_rlnm */
+static __inline__ vector unsigned int __ATTRS_o_ai
+vec_rlnm(vector unsigned int __a, vector unsigned int __b,
+ vector unsigned int __c) {
+ return __builtin_altivec_vrlwnm(__a, __b) & __c;
+}
+
+static __inline__ vector unsigned long long __ATTRS_o_ai
+vec_rlnm(vector unsigned long long __a, vector unsigned long long __b,
+ vector unsigned long long __c) {
+ return __builtin_altivec_vrldnm(__a, __b) & __c;
+}
+#endif
+
/* vec_vrlb */
static __inline__ vector signed char __ATTRS_o_ai
@@ -6984,6 +8334,145 @@ static __inline__ vector float __ATTRS_o_ai vec_sld(vector float __a,
#endif
}
+#ifdef __VSX__
+static __inline__ vector bool long long __ATTRS_o_ai
+vec_sld(vector bool long long __a, vector bool long long __b,
+ unsigned const int __c) {
+ unsigned char __d = __c & 0x0F;
+#ifdef __LITTLE_ENDIAN__
+ return vec_perm(
+ __b, __a, (vector unsigned char)(16 - __d, 17 - __d, 18 - __d, 19 - __d,
+ 20 - __d, 21 - __d, 22 - __d, 23 - __d,
+ 24 - __d, 25 - __d, 26 - __d, 27 - __d,
+ 28 - __d, 29 - __d, 30 - __d, 31 - __d));
+#else
+ return vec_perm(
+ __a, __b,
+ (vector unsigned char)(__d, __d + 1, __d + 2, __d + 3, __d + 4, __d + 5,
+ __d + 6, __d + 7, __d + 8, __d + 9, __d + 10,
+ __d + 11, __d + 12, __d + 13, __d + 14, __d + 15));
+#endif
+}
+
+static __inline__ vector signed long long __ATTRS_o_ai
+vec_sld(vector signed long long __a, vector signed long long __b,
+ unsigned const int __c) {
+ unsigned char __d = __c & 0x0F;
+#ifdef __LITTLE_ENDIAN__
+ return vec_perm(
+ __b, __a, (vector unsigned char)(16 - __d, 17 - __d, 18 - __d, 19 - __d,
+ 20 - __d, 21 - __d, 22 - __d, 23 - __d,
+ 24 - __d, 25 - __d, 26 - __d, 27 - __d,
+ 28 - __d, 29 - __d, 30 - __d, 31 - __d));
+#else
+ return vec_perm(
+ __a, __b,
+ (vector unsigned char)(__d, __d + 1, __d + 2, __d + 3, __d + 4, __d + 5,
+ __d + 6, __d + 7, __d + 8, __d + 9, __d + 10,
+ __d + 11, __d + 12, __d + 13, __d + 14, __d + 15));
+#endif
+}
+
+static __inline__ vector unsigned long long __ATTRS_o_ai
+vec_sld(vector unsigned long long __a, vector unsigned long long __b,
+ unsigned const int __c) {
+ unsigned char __d = __c & 0x0F;
+#ifdef __LITTLE_ENDIAN__
+ return vec_perm(
+ __b, __a, (vector unsigned char)(16 - __d, 17 - __d, 18 - __d, 19 - __d,
+ 20 - __d, 21 - __d, 22 - __d, 23 - __d,
+ 24 - __d, 25 - __d, 26 - __d, 27 - __d,
+ 28 - __d, 29 - __d, 30 - __d, 31 - __d));
+#else
+ return vec_perm(
+ __a, __b,
+ (vector unsigned char)(__d, __d + 1, __d + 2, __d + 3, __d + 4, __d + 5,
+ __d + 6, __d + 7, __d + 8, __d + 9, __d + 10,
+ __d + 11, __d + 12, __d + 13, __d + 14, __d + 15));
+#endif
+}
+
+static __inline__ vector double __ATTRS_o_ai vec_sld(vector double __a,
+ vector double __b,
+ unsigned const int __c) {
+ unsigned char __d = __c & 0x0F;
+#ifdef __LITTLE_ENDIAN__
+ return vec_perm(
+ __b, __a, (vector unsigned char)(16 - __d, 17 - __d, 18 - __d, 19 - __d,
+ 20 - __d, 21 - __d, 22 - __d, 23 - __d,
+ 24 - __d, 25 - __d, 26 - __d, 27 - __d,
+ 28 - __d, 29 - __d, 30 - __d, 31 - __d));
+#else
+ return vec_perm(
+ __a, __b,
+ (vector unsigned char)(__d, __d + 1, __d + 2, __d + 3, __d + 4, __d + 5,
+ __d + 6, __d + 7, __d + 8, __d + 9, __d + 10,
+ __d + 11, __d + 12, __d + 13, __d + 14, __d + 15));
+#endif
+}
+#endif
+
+/* vec_sldw */
+static __inline__ vector signed char __ATTRS_o_ai vec_sldw(
+ vector signed char __a, vector signed char __b, unsigned const int __c) {
+ return vec_sld(__a, __b, ((__c << 2) & 0x0F));
+}
+
+static __inline__ vector unsigned char __ATTRS_o_ai
+vec_sldw(vector unsigned char __a, vector unsigned char __b,
+ unsigned const int __c) {
+ return vec_sld(__a, __b, ((__c << 2) & 0x0F));
+}
+
+static __inline__ vector signed short __ATTRS_o_ai vec_sldw(
+ vector signed short __a, vector signed short __b, unsigned const int __c) {
+ return vec_sld(__a, __b, ((__c << 2) & 0x0F));
+}
+
+static __inline__ vector unsigned short __ATTRS_o_ai
+vec_sldw(vector unsigned short __a, vector unsigned short __b,
+ unsigned const int __c) {
+ return vec_sld(__a, __b, ((__c << 2) & 0x0F));
+}
+
+static __inline__ vector signed int __ATTRS_o_ai
+vec_sldw(vector signed int __a, vector signed int __b, unsigned const int __c) {
+ return vec_sld(__a, __b, ((__c << 2) & 0x0F));
+}
+
+static __inline__ vector unsigned int __ATTRS_o_ai vec_sldw(
+ vector unsigned int __a, vector unsigned int __b, unsigned const int __c) {
+ return vec_sld(__a, __b, ((__c << 2) & 0x0F));
+}
+
+#ifdef __VSX__
+static __inline__ vector signed long long __ATTRS_o_ai
+vec_sldw(vector signed long long __a, vector signed long long __b,
+ unsigned const int __c) {
+ return vec_sld(__a, __b, ((__c << 2) & 0x0F));
+}
+
+static __inline__ vector unsigned long long __ATTRS_o_ai
+vec_sldw(vector unsigned long long __a, vector unsigned long long __b,
+ unsigned const int __c) {
+ return vec_sld(__a, __b, ((__c << 2) & 0x0F));
+}
+#endif
+
+#ifdef __POWER9_VECTOR__
+/* vec_slv */
+static __inline__ vector unsigned char __ATTRS_o_ai
+vec_slv(vector unsigned char __a, vector unsigned char __b) {
+ return __builtin_altivec_vslv(__a, __b);
+}
+
+/* vec_srv */
+static __inline__ vector unsigned char __ATTRS_o_ai
+vec_srv(vector unsigned char __a, vector unsigned char __b) {
+ return __builtin_altivec_vsrv(__a, __b);
+}
+#endif
+
/* vec_vsldoi */
static __inline__ vector signed char __ATTRS_o_ai
@@ -7307,6 +8796,20 @@ vec_sll(vector bool int __a, vector unsigned int __b) {
(vector int)__b);
}
+#ifdef __VSX__
+static __inline__ vector signed long long __ATTRS_o_ai
+vec_sll(vector signed long long __a, vector unsigned char __b) {
+ return (vector signed long long)__builtin_altivec_vsl((vector int)__a,
+ (vector int)__b);
+}
+
+static __inline__ vector unsigned long long __ATTRS_o_ai
+vec_sll(vector unsigned long long __a, vector unsigned char __b) {
+ return (vector unsigned long long)__builtin_altivec_vsl((vector int)__a,
+ (vector int)__b);
+}
+#endif
+
/* vec_vsl */
static __inline__ vector signed char __ATTRS_o_ai
@@ -7570,6 +9073,32 @@ static __inline__ vector float __ATTRS_o_ai vec_slo(vector float __a,
return (vector float)__builtin_altivec_vslo((vector int)__a, (vector int)__b);
}
+#ifdef __VSX__
+static __inline__ vector signed long long __ATTRS_o_ai
+vec_slo(vector signed long long __a, vector signed char __b) {
+ return (vector signed long long)__builtin_altivec_vslo((vector int)__a,
+ (vector int)__b);
+}
+
+static __inline__ vector signed long long __ATTRS_o_ai
+vec_slo(vector signed long long __a, vector unsigned char __b) {
+ return (vector signed long long)__builtin_altivec_vslo((vector int)__a,
+ (vector int)__b);
+}
+
+static __inline__ vector unsigned long long __ATTRS_o_ai
+vec_slo(vector unsigned long long __a, vector signed char __b) {
+ return (vector unsigned long long)__builtin_altivec_vslo((vector int)__a,
+ (vector int)__b);
+}
+
+static __inline__ vector unsigned long long __ATTRS_o_ai
+vec_slo(vector unsigned long long __a, vector unsigned char __b) {
+ return (vector unsigned long long)__builtin_altivec_vslo((vector int)__a,
+ (vector int)__b);
+}
+#endif
+
/* vec_vslo */
static __inline__ vector signed char __ATTRS_o_ai
@@ -8304,6 +9833,20 @@ vec_srl(vector bool int __a, vector unsigned int __b) {
(vector int)__b);
}
+#ifdef __VSX__
+static __inline__ vector signed long long __ATTRS_o_ai
+vec_srl(vector signed long long __a, vector unsigned char __b) {
+ return (vector signed long long)__builtin_altivec_vsr((vector int)__a,
+ (vector int)__b);
+}
+
+static __inline__ vector unsigned long long __ATTRS_o_ai
+vec_srl(vector unsigned long long __a, vector unsigned char __b) {
+ return (vector unsigned long long)__builtin_altivec_vsr((vector int)__a,
+ (vector int)__b);
+}
+#endif
+
/* vec_vsr */
static __inline__ vector signed char __ATTRS_o_ai
@@ -8567,6 +10110,32 @@ static __inline__ vector float __ATTRS_o_ai vec_sro(vector float __a,
return (vector float)__builtin_altivec_vsro((vector int)__a, (vector int)__b);
}
+#ifdef __VSX__
+static __inline__ vector signed long long __ATTRS_o_ai
+vec_sro(vector signed long long __a, vector signed char __b) {
+ return (vector signed long long)__builtin_altivec_vsro((vector int)__a,
+ (vector int)__b);
+}
+
+static __inline__ vector signed long long __ATTRS_o_ai
+vec_sro(vector signed long long __a, vector unsigned char __b) {
+ return (vector signed long long)__builtin_altivec_vsro((vector int)__a,
+ (vector int)__b);
+}
+
+static __inline__ vector unsigned long long __ATTRS_o_ai
+vec_sro(vector unsigned long long __a, vector signed char __b) {
+ return (vector unsigned long long)__builtin_altivec_vsro((vector int)__a,
+ (vector int)__b);
+}
+
+static __inline__ vector unsigned long long __ATTRS_o_ai
+vec_sro(vector unsigned long long __a, vector unsigned char __b) {
+ return (vector unsigned long long)__builtin_altivec_vsro((vector int)__a,
+ (vector int)__b);
+}
+#endif
+
/* vec_vsro */
static __inline__ vector signed char __ATTRS_o_ai
@@ -9580,6 +11149,12 @@ vec_vsubfp(vector float __a, vector float __b) {
/* vec_subc */
+static __inline__ vector signed int __ATTRS_o_ai
+vec_subc(vector signed int __a, vector signed int __b) {
+ return (vector signed int)__builtin_altivec_vsubcuw((vector unsigned int)__a,
+ (vector unsigned int) __b);
+}
+
static __inline__ vector unsigned int __ATTRS_o_ai
vec_subc(vector unsigned int __a, vector unsigned int __b) {
return __builtin_altivec_vsubcuw(__a, __b);
@@ -9813,6 +11388,7 @@ vec_vsubuqm(vector unsigned __int128 __a, vector unsigned __int128 __b) {
/* vec_vsubeuqm */
+
static __inline__ vector signed __int128 __ATTRS_o_ai
vec_vsubeuqm(vector signed __int128 __a, vector signed __int128 __b,
vector signed __int128 __c) {
@@ -9825,6 +11401,18 @@ vec_vsubeuqm(vector unsigned __int128 __a, vector unsigned __int128 __b,
return __builtin_altivec_vsubeuqm(__a, __b, __c);
}
+static __inline__ vector signed __int128 __ATTRS_o_ai
+vec_sube(vector signed __int128 __a, vector signed __int128 __b,
+ vector signed __int128 __c) {
+ return __builtin_altivec_vsubeuqm(__a, __b, __c);
+}
+
+static __inline__ vector unsigned __int128 __ATTRS_o_ai
+vec_sube(vector unsigned __int128 __a, vector unsigned __int128 __b,
+ vector unsigned __int128 __c) {
+ return __builtin_altivec_vsubeuqm(__a, __b, __c);
+}
+
/* vec_vsubcuq */
static __inline__ vector signed __int128 __ATTRS_o_ai
@@ -9850,8 +11438,47 @@ vec_vsubecuq(vector unsigned __int128 __a, vector unsigned __int128 __b,
vector unsigned __int128 __c) {
return __builtin_altivec_vsubecuq(__a, __b, __c);
}
+
+static __inline__ vector signed int __ATTRS_o_ai
+vec_subec(vector signed int __a, vector signed int __b,
+ vector signed int __c) {
+ return vec_addec(__a, ~__b, __c);
+}
+
+static __inline__ vector unsigned int __ATTRS_o_ai
+vec_subec(vector unsigned int __a, vector unsigned int __b,
+ vector unsigned int __c) {
+ return vec_addec(__a, ~__b, __c);
+}
+
+static __inline__ vector signed __int128 __ATTRS_o_ai
+vec_subec(vector signed __int128 __a, vector signed __int128 __b,
+ vector signed __int128 __c) {
+ return __builtin_altivec_vsubecuq(__a, __b, __c);
+}
+
+static __inline__ vector unsigned __int128 __ATTRS_o_ai
+vec_subec(vector unsigned __int128 __a, vector unsigned __int128 __b,
+ vector unsigned __int128 __c) {
+ return __builtin_altivec_vsubecuq(__a, __b, __c);
+}
#endif // defined(__POWER8_VECTOR__) && defined(__powerpc64__)
+static __inline__ vector signed int __ATTRS_o_ai
+vec_sube(vector signed int __a, vector signed int __b,
+ vector signed int __c) {
+ vector signed int __mask = {1, 1, 1, 1};
+ vector signed int __carry = __c & __mask;
+ return vec_adde(__a, ~__b, __carry);
+}
+
+static __inline__ vector unsigned int __ATTRS_o_ai
+vec_sube(vector unsigned int __a, vector unsigned int __b,
+ vector unsigned int __c) {
+ vector unsigned int __mask = {1, 1, 1, 1};
+ vector unsigned int __carry = __c & __mask;
+ return vec_adde(__a, ~__b, __carry);
+}
/* vec_sum4s */
static __inline__ vector int __ATTRS_o_ai vec_sum4s(vector signed char __a,
@@ -10051,6 +11678,11 @@ vec_unpackh(vector bool int __a) {
return (vector bool long long)__builtin_altivec_vupkhsw((vector int)__a);
#endif
}
+
+static __inline__ vector double __ATTRS_o_ai
+vec_unpackh(vector float __a) {
+ return (vector double)(__a[0], __a[1]);
+}
#endif
/* vec_vupkhsb */
@@ -10185,6 +11817,11 @@ vec_unpackl(vector bool int __a) {
return (vector bool long long)__builtin_altivec_vupklsw((vector int)__a);
#endif
}
+
+static __inline__ vector double __ATTRS_o_ai
+vec_unpackl(vector float __a) {
+ return (vector double)(__a[2], __a[3]);
+}
#endif
/* vec_vupklsb */
@@ -10935,6 +12572,55 @@ static __inline__ float __ATTRS_o_ai vec_extract(vector float __a, int __b) {
return __a[__b];
}
+#ifdef __POWER9_VECTOR__
+
+/* vec_extract_exp */
+
+static __inline__ vector unsigned int __ATTRS_o_ai
+vec_extract_exp(vector float __a) {
+ return __builtin_vsx_xvxexpsp(__a);
+}
+
+static __inline__ vector unsigned long long __ATTRS_o_ai
+vec_extract_exp(vector double __a) {
+ return __builtin_vsx_xvxexpdp(__a);
+}
+
+/* vec_extract_sig */
+
+static __inline__ vector unsigned int __ATTRS_o_ai
+vec_extract_sig(vector float __a) {
+ return __builtin_vsx_xvxsigsp(__a);
+}
+
+static __inline__ vector unsigned long long __ATTRS_o_ai
+vec_extract_sig (vector double __a) {
+ return __builtin_vsx_xvxsigdp(__a);
+}
+
+static __inline__ vector float __ATTRS_o_ai
+vec_extract_fp32_from_shorth(vector unsigned short __a) {
+ vector unsigned short __b =
+#ifdef __LITTLE_ENDIAN__
+ __builtin_shufflevector(__a, __a, 0, -1, 1, -1, 2, -1, 3, -1);
+#else
+ __builtin_shufflevector(__a, __a, -1, 0, -1, 1, -1, 2, -1, 3);
+#endif
+ return __builtin_vsx_xvcvhpsp(__b);
+}
+
+static __inline__ vector float __ATTRS_o_ai
+vec_extract_fp32_from_shortl(vector unsigned short __a) {
+ vector unsigned short __b =
+#ifdef __LITTLE_ENDIAN__
+ __builtin_shufflevector(__a, __a, 4, -1, 5, -1, 6, -1, 7, -1);
+#else
+ __builtin_shufflevector(__a, __a, -1, 4, -1, 5, -1, 6, -1, 7);
+#endif
+ return __builtin_vsx_xvcvhpsp(__b);
+}
+#endif /* __POWER9_VECTOR__ */
+
/* vec_insert */
static __inline__ vector signed char __ATTRS_o_ai
@@ -14369,6 +16055,24 @@ __builtin_crypto_vncipherlast(vector unsigned long long __a,
#endif
#ifdef __POWER8_VECTOR__
+static __inline__ vector bool char __ATTRS_o_ai
+vec_permxor(vector bool char __a, vector bool char __b,
+ vector bool char __c) {
+ return __builtin_altivec_crypto_vpermxor(__a, __b, __c);
+}
+
+static __inline__ vector signed char __ATTRS_o_ai
+vec_permxor(vector signed char __a, vector signed char __b,
+ vector signed char __c) {
+ return __builtin_altivec_crypto_vpermxor(__a, __b, __c);
+}
+
+static __inline__ vector unsigned char __ATTRS_o_ai
+vec_permxor(vector unsigned char __a, vector unsigned char __b,
+ vector unsigned char __c) {
+ return __builtin_altivec_crypto_vpermxor(__a, __b, __c);
+}
+
static __inline__ vector unsigned char __ATTRS_o_ai
__builtin_crypto_vpermxor(vector unsigned char __a, vector unsigned char __b,
vector unsigned char __c) {
@@ -14453,6 +16157,572 @@ vec_bperm(vector unsigned __int128 __a, vector unsigned char __b) {
#endif
#endif
+
+/* vec_reve */
+
+static inline __ATTRS_o_ai vector bool char vec_reve(vector bool char __a) {
+ return __builtin_shufflevector(__a, __a, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6,
+ 5, 4, 3, 2, 1, 0);
+}
+
+static inline __ATTRS_o_ai vector signed char vec_reve(vector signed char __a) {
+ return __builtin_shufflevector(__a, __a, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6,
+ 5, 4, 3, 2, 1, 0);
+}
+
+static inline __ATTRS_o_ai vector unsigned char
+vec_reve(vector unsigned char __a) {
+ return __builtin_shufflevector(__a, __a, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6,
+ 5, 4, 3, 2, 1, 0);
+}
+
+static inline __ATTRS_o_ai vector bool int vec_reve(vector bool int __a) {
+ return __builtin_shufflevector(__a, __a, 3, 2, 1, 0);
+}
+
+static inline __ATTRS_o_ai vector signed int vec_reve(vector signed int __a) {
+ return __builtin_shufflevector(__a, __a, 3, 2, 1, 0);
+}
+
+static inline __ATTRS_o_ai vector unsigned int
+vec_reve(vector unsigned int __a) {
+ return __builtin_shufflevector(__a, __a, 3, 2, 1, 0);
+}
+
+static inline __ATTRS_o_ai vector bool short vec_reve(vector bool short __a) {
+ return __builtin_shufflevector(__a, __a, 7, 6, 5, 4, 3, 2, 1, 0);
+}
+
+static inline __ATTRS_o_ai vector signed short
+vec_reve(vector signed short __a) {
+ return __builtin_shufflevector(__a, __a, 7, 6, 5, 4, 3, 2, 1, 0);
+}
+
+static inline __ATTRS_o_ai vector unsigned short
+vec_reve(vector unsigned short __a) {
+ return __builtin_shufflevector(__a, __a, 7, 6, 5, 4, 3, 2, 1, 0);
+}
+
+static inline __ATTRS_o_ai vector float vec_reve(vector float __a) {
+ return __builtin_shufflevector(__a, __a, 3, 2, 1, 0);
+}
+
+#ifdef __VSX__
+static inline __ATTRS_o_ai vector bool long long
+vec_reve(vector bool long long __a) {
+ return __builtin_shufflevector(__a, __a, 1, 0);
+}
+
+static inline __ATTRS_o_ai vector signed long long
+vec_reve(vector signed long long __a) {
+ return __builtin_shufflevector(__a, __a, 1, 0);
+}
+
+static inline __ATTRS_o_ai vector unsigned long long
+vec_reve(vector unsigned long long __a) {
+ return __builtin_shufflevector(__a, __a, 1, 0);
+}
+
+static inline __ATTRS_o_ai vector double vec_reve(vector double __a) {
+ return __builtin_shufflevector(__a, __a, 1, 0);
+}
+#endif
+
+/* vec_revb */
+static __inline__ vector bool char __ATTRS_o_ai
+vec_revb(vector bool char __a) {
+ return __a;
+}
+
+static __inline__ vector signed char __ATTRS_o_ai
+vec_revb(vector signed char __a) {
+ return __a;
+}
+
+static __inline__ vector unsigned char __ATTRS_o_ai
+vec_revb(vector unsigned char __a) {
+ return __a;
+}
+
+static __inline__ vector bool short __ATTRS_o_ai
+vec_revb(vector bool short __a) {
+ vector unsigned char __indices =
+ { 1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14 };
+ return vec_perm(__a, __a, __indices);
+}
+
+static __inline__ vector signed short __ATTRS_o_ai
+vec_revb(vector signed short __a) {
+ vector unsigned char __indices =
+ { 1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14 };
+ return vec_perm(__a, __a, __indices);
+}
+
+static __inline__ vector unsigned short __ATTRS_o_ai
+vec_revb(vector unsigned short __a) {
+ vector unsigned char __indices =
+ { 1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14 };
+ return vec_perm(__a, __a, __indices);
+}
+
+static __inline__ vector bool int __ATTRS_o_ai
+vec_revb(vector bool int __a) {
+ vector unsigned char __indices =
+ { 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12 };
+ return vec_perm(__a, __a, __indices);
+}
+
+static __inline__ vector signed int __ATTRS_o_ai
+vec_revb(vector signed int __a) {
+ vector unsigned char __indices =
+ { 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12 };
+ return vec_perm(__a, __a, __indices);
+}
+
+static __inline__ vector unsigned int __ATTRS_o_ai
+vec_revb(vector unsigned int __a) {
+ vector unsigned char __indices =
+ { 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12 };
+ return vec_perm(__a, __a, __indices);
+}
+
+static __inline__ vector float __ATTRS_o_ai
+vec_revb(vector float __a) {
+ vector unsigned char __indices =
+ { 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12 };
+ return vec_perm(__a, __a, __indices);
+}
+
+#ifdef __VSX__
+static __inline__ vector bool long long __ATTRS_o_ai
+vec_revb(vector bool long long __a) {
+ vector unsigned char __indices =
+ { 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8 };
+ return vec_perm(__a, __a, __indices);
+}
+
+static __inline__ vector signed long long __ATTRS_o_ai
+vec_revb(vector signed long long __a) {
+ vector unsigned char __indices =
+ { 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8 };
+ return vec_perm(__a, __a, __indices);
+}
+
+static __inline__ vector unsigned long long __ATTRS_o_ai
+vec_revb(vector unsigned long long __a) {
+ vector unsigned char __indices =
+ { 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8 };
+ return vec_perm(__a, __a, __indices);
+}
+
+static __inline__ vector double __ATTRS_o_ai
+vec_revb(vector double __a) {
+ vector unsigned char __indices =
+ { 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8 };
+ return vec_perm(__a, __a, __indices);
+}
+#endif /* End __VSX__ */
+
+#if defined(__POWER8_VECTOR__) && defined(__powerpc64__)
+static __inline__ vector signed __int128 __ATTRS_o_ai
+vec_revb(vector signed __int128 __a) {
+ vector unsigned char __indices =
+ { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
+ return (vector signed __int128)vec_perm((vector signed int)__a,
+ (vector signed int)__a,
+ __indices);
+}
+
+static __inline__ vector unsigned __int128 __ATTRS_o_ai
+vec_revb(vector unsigned __int128 __a) {
+ vector unsigned char __indices =
+ { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
+ return (vector unsigned __int128)vec_perm((vector signed int)__a,
+ (vector signed int)__a,
+ __indices);
+}
+#endif /* END __POWER8_VECTOR__ && __powerpc64__ */
+
+/* vec_xl */
+
+static inline __ATTRS_o_ai vector signed char vec_xl(signed long long __offset,
+ signed char *__ptr) {
+ return *(vector signed char *)(__ptr + __offset);
+}
+
+static inline __ATTRS_o_ai vector unsigned char
+vec_xl(signed long long __offset, unsigned char *__ptr) {
+ return *(vector unsigned char *)(__ptr + __offset);
+}
+
+static inline __ATTRS_o_ai vector signed short vec_xl(signed long long __offset,
+ signed short *__ptr) {
+ return *(vector signed short *)(__ptr + __offset);
+}
+
+static inline __ATTRS_o_ai vector unsigned short
+vec_xl(signed long long __offset, unsigned short *__ptr) {
+ return *(vector unsigned short *)(__ptr + __offset);
+}
+
+static inline __ATTRS_o_ai vector signed int vec_xl(signed long long __offset,
+ signed int *__ptr) {
+ return *(vector signed int *)(__ptr + __offset);
+}
+
+static inline __ATTRS_o_ai vector unsigned int vec_xl(signed long long __offset,
+ unsigned int *__ptr) {
+ return *(vector unsigned int *)(__ptr + __offset);
+}
+
+static inline __ATTRS_o_ai vector float vec_xl(signed long long __offset,
+ float *__ptr) {
+ return *(vector float *)(__ptr + __offset);
+}
+
+#ifdef __VSX__
+static inline __ATTRS_o_ai vector signed long long
+vec_xl(signed long long __offset, signed long long *__ptr) {
+ return *(vector signed long long *)(__ptr + __offset);
+}
+
+static inline __ATTRS_o_ai vector unsigned long long
+vec_xl(signed long long __offset, unsigned long long *__ptr) {
+ return *(vector unsigned long long *)(__ptr + __offset);
+}
+
+static inline __ATTRS_o_ai vector double vec_xl(signed long long __offset,
+ double *__ptr) {
+ return *(vector double *)(__ptr + __offset);
+}
+#endif
+
+#if defined(__POWER8_VECTOR__) && defined(__powerpc64__)
+static inline __ATTRS_o_ai vector signed __int128
+vec_xl(signed long long __offset, signed __int128 *__ptr) {
+ return *(vector signed __int128 *)(__ptr + __offset);
+}
+
+static inline __ATTRS_o_ai vector unsigned __int128
+vec_xl(signed long long __offset, unsigned __int128 *__ptr) {
+ return *(vector unsigned __int128 *)(__ptr + __offset);
+}
+#endif
+
+/* vec_xl_be */
+
+#ifdef __LITTLE_ENDIAN__
+static __inline__ vector signed char __ATTRS_o_ai
+vec_xl_be(signed long long __offset, signed char *__ptr) {
+ vector signed char __vec = __builtin_vsx_lxvd2x_be(__offset, __ptr);
+ return __builtin_shufflevector(__vec, __vec, 7, 6, 5, 4, 3, 2, 1, 0, 15, 14,
+ 13, 12, 11, 10, 9, 8);
+}
+
+static __inline__ vector unsigned char __ATTRS_o_ai
+vec_xl_be(signed long long __offset, unsigned char *__ptr) {
+ vector unsigned char __vec = __builtin_vsx_lxvd2x_be(__offset, __ptr);
+ return __builtin_shufflevector(__vec, __vec, 7, 6, 5, 4, 3, 2, 1, 0, 15, 14,
+ 13, 12, 11, 10, 9, 8);
+}
+
+static __inline__ vector signed short __ATTRS_o_ai
+vec_xl_be(signed long long __offset, signed short *__ptr) {
+ vector signed short __vec = __builtin_vsx_lxvd2x_be(__offset, __ptr);
+ return __builtin_shufflevector(__vec, __vec, 3, 2, 1, 0, 7, 6, 5, 4);
+}
+
+static __inline__ vector unsigned short __ATTRS_o_ai
+vec_xl_be(signed long long __offset, unsigned short *__ptr) {
+ vector unsigned short __vec = __builtin_vsx_lxvd2x_be(__offset, __ptr);
+ return __builtin_shufflevector(__vec, __vec, 3, 2, 1, 0, 7, 6, 5, 4);
+}
+
+static __inline__ vector signed int __ATTRS_o_ai
+vec_xl_be(signed long long __offset, signed int *__ptr) {
+ return (vector signed int)__builtin_vsx_lxvw4x_be(__offset, __ptr);
+}
+
+static __inline__ vector unsigned int __ATTRS_o_ai
+vec_xl_be(signed long long __offset, unsigned int *__ptr) {
+ return (vector unsigned int)__builtin_vsx_lxvw4x_be(__offset, __ptr);
+}
+
+static __inline__ vector float __ATTRS_o_ai
+vec_xl_be(signed long long __offset, float *__ptr) {
+ return (vector float)__builtin_vsx_lxvw4x_be(__offset, __ptr);
+}
+
+#ifdef __VSX__
+static __inline__ vector signed long long __ATTRS_o_ai
+vec_xl_be(signed long long __offset, signed long long *__ptr) {
+ return (vector signed long long)__builtin_vsx_lxvd2x_be(__offset, __ptr);
+}
+
+static __inline__ vector unsigned long long __ATTRS_o_ai
+vec_xl_be(signed long long __offset, unsigned long long *__ptr) {
+ return (vector unsigned long long)__builtin_vsx_lxvd2x_be(__offset, __ptr);
+}
+
+static __inline__ vector double __ATTRS_o_ai
+vec_xl_be(signed long long __offset, double *__ptr) {
+ return (vector double)__builtin_vsx_lxvd2x_be(__offset, __ptr);
+}
+#endif
+
+#if defined(__POWER8_VECTOR__) && defined(__powerpc64__)
+static __inline__ vector signed __int128 __ATTRS_o_ai
+vec_xl_be(signed long long __offset, signed __int128 *__ptr) {
+ return vec_xl(__offset, __ptr);
+}
+
+static __inline__ vector unsigned __int128 __ATTRS_o_ai
+vec_xl_be(signed long long __offset, unsigned __int128 *__ptr) {
+ return vec_xl(__offset, __ptr);
+}
+#endif
+#else
+ #define vec_xl_be vec_xl
+#endif
+
+/* vec_xst */
+
+static inline __ATTRS_o_ai void vec_xst(vector signed char __vec,
+ signed long long __offset,
+ signed char *__ptr) {
+ *(vector signed char *)(__ptr + __offset) = __vec;
+}
+
+static inline __ATTRS_o_ai void vec_xst(vector unsigned char __vec,
+ signed long long __offset,
+ unsigned char *__ptr) {
+ *(vector unsigned char *)(__ptr + __offset) = __vec;
+}
+
+static inline __ATTRS_o_ai void vec_xst(vector signed short __vec,
+ signed long long __offset,
+ signed short *__ptr) {
+ *(vector signed short *)(__ptr + __offset) = __vec;
+}
+
+static inline __ATTRS_o_ai void vec_xst(vector unsigned short __vec,
+ signed long long __offset,
+ unsigned short *__ptr) {
+ *(vector unsigned short *)(__ptr + __offset) = __vec;
+}
+
+static inline __ATTRS_o_ai void vec_xst(vector signed int __vec,
+ signed long long __offset,
+ signed int *__ptr) {
+ *(vector signed int *)(__ptr + __offset) = __vec;
+}
+
+static inline __ATTRS_o_ai void vec_xst(vector unsigned int __vec,
+ signed long long __offset,
+ unsigned int *__ptr) {
+ *(vector unsigned int *)(__ptr + __offset) = __vec;
+}
+
+static inline __ATTRS_o_ai void vec_xst(vector float __vec,
+ signed long long __offset,
+ float *__ptr) {
+ *(vector float *)(__ptr + __offset) = __vec;
+}
+
+#ifdef __VSX__
+static inline __ATTRS_o_ai void vec_xst(vector signed long long __vec,
+ signed long long __offset,
+ signed long long *__ptr) {
+ *(vector signed long long *)(__ptr + __offset) = __vec;
+}
+
+static inline __ATTRS_o_ai void vec_xst(vector unsigned long long __vec,
+ signed long long __offset,
+ unsigned long long *__ptr) {
+ *(vector unsigned long long *)(__ptr + __offset) = __vec;
+}
+
+static inline __ATTRS_o_ai void vec_xst(vector double __vec,
+ signed long long __offset,
+ double *__ptr) {
+ *(vector double *)(__ptr + __offset) = __vec;
+}
+#endif
+
+#if defined(__POWER8_VECTOR__) && defined(__powerpc64__)
+static inline __ATTRS_o_ai void vec_xst(vector signed __int128 __vec,
+ signed long long __offset,
+ signed __int128 *__ptr) {
+ *(vector signed __int128 *)(__ptr + __offset) = __vec;
+}
+
+static inline __ATTRS_o_ai void vec_xst(vector unsigned __int128 __vec,
+ signed long long __offset,
+ unsigned __int128 *__ptr) {
+ *(vector unsigned __int128 *)(__ptr + __offset) = __vec;
+}
+#endif
+
+/* vec_xst_be */
+
+#ifdef __LITTLE_ENDIAN__
+static __inline__ void __ATTRS_o_ai vec_xst_be(vector signed char __vec,
+ signed long long __offset,
+ signed char *__ptr) {
+ vector signed char __tmp =
+ __builtin_shufflevector(__vec, __vec, 7, 6, 5, 4, 3, 2, 1, 0, 15, 14,
+ 13, 12, 11, 10, 9, 8);
+ __builtin_vsx_stxvd2x_be(__tmp, __offset, __ptr);
+}
+
+static __inline__ void __ATTRS_o_ai vec_xst_be(vector unsigned char __vec,
+ signed long long __offset,
+ unsigned char *__ptr) {
+ vector unsigned char __tmp =
+ __builtin_shufflevector(__vec, __vec, 7, 6, 5, 4, 3, 2, 1, 0, 15, 14,
+ 13, 12, 11, 10, 9, 8);
+ __builtin_vsx_stxvd2x_be(__tmp, __offset, __ptr);
+}
+
+static __inline__ void __ATTRS_o_ai vec_xst_be(vector signed short __vec,
+ signed long long __offset,
+ signed short *__ptr) {
+ vector signed short __tmp =
+ __builtin_shufflevector(__vec, __vec, 3, 2, 1, 0, 7, 6, 5, 4);
+ __builtin_vsx_stxvd2x_be(__tmp, __offset, __ptr);
+}
+
+static __inline__ void __ATTRS_o_ai vec_xst_be(vector unsigned short __vec,
+ signed long long __offset,
+ unsigned short *__ptr) {
+ vector unsigned short __tmp =
+ __builtin_shufflevector(__vec, __vec, 3, 2, 1, 0, 7, 6, 5, 4);
+ __builtin_vsx_stxvd2x_be(__tmp, __offset, __ptr);
+}
+
+static __inline__ void __ATTRS_o_ai vec_xst_be(vector signed int __vec,
+ signed long long __offset,
+ signed int *__ptr) {
+ __builtin_vsx_stxvw4x_be(__vec, __offset, __ptr);
+}
+
+static __inline__ void __ATTRS_o_ai vec_xst_be(vector unsigned int __vec,
+ signed long long __offset,
+ unsigned int *__ptr) {
+ __builtin_vsx_stxvw4x_be(__vec, __offset, __ptr);
+}
+
+static __inline__ void __ATTRS_o_ai vec_xst_be(vector float __vec,
+ signed long long __offset,
+ float *__ptr) {
+ __builtin_vsx_stxvw4x_be(__vec, __offset, __ptr);
+}
+
+#ifdef __VSX__
+static __inline__ void __ATTRS_o_ai vec_xst_be(vector signed long long __vec,
+ signed long long __offset,
+ signed long long *__ptr) {
+ __builtin_vsx_stxvd2x_be(__vec, __offset, __ptr);
+}
+
+static __inline__ void __ATTRS_o_ai vec_xst_be(vector unsigned long long __vec,
+ signed long long __offset,
+ unsigned long long *__ptr) {
+ __builtin_vsx_stxvd2x_be(__vec, __offset, __ptr);
+}
+
+static __inline__ void __ATTRS_o_ai vec_xst_be(vector double __vec,
+ signed long long __offset,
+ double *__ptr) {
+ __builtin_vsx_stxvd2x_be(__vec, __offset, __ptr);
+}
+#endif
+
+#if defined(__POWER8_VECTOR__) && defined(__powerpc64__)
+static __inline__ void __ATTRS_o_ai vec_xst_be(vector signed __int128 __vec,
+ signed long long __offset,
+ signed __int128 *__ptr) {
+ vec_xst(__vec, __offset, __ptr);
+}
+
+static __inline__ void __ATTRS_o_ai vec_xst_be(vector unsigned __int128 __vec,
+ signed long long __offset,
+ unsigned __int128 *__ptr) {
+ vec_xst(__vec, __offset, __ptr);
+}
+#endif
+#else
+ #define vec_xst_be vec_xst
+#endif
+
+#ifdef __POWER9_VECTOR__
+#define vec_test_data_class(__a, __b) \
+ _Generic((__a), \
+ vector float: \
+ (vector bool int)__builtin_vsx_xvtstdcsp((__a), (__b)), \
+ vector double: \
+ (vector bool long long)__builtin_vsx_xvtstdcdp((__a), (__b)) \
+ )
+
+#endif /* #ifdef __POWER9_VECTOR__ */
+
+static vector float __ATTRS_o_ai vec_neg(vector float __a) {
+ return -__a;
+}
+
+#ifdef __VSX__
+static vector double __ATTRS_o_ai vec_neg(vector double __a) {
+ return -__a;
+}
+
+#endif
+
+#if defined(__POWER8_VECTOR__) && defined(__powerpc64__)
+static vector long long __ATTRS_o_ai vec_neg(vector long long __a) {
+ return -__a;
+}
+#endif
+
+static vector signed int __ATTRS_o_ai vec_neg(vector signed int __a) {
+ return -__a;
+}
+
+static vector signed short __ATTRS_o_ai vec_neg(vector signed short __a) {
+ return -__a;
+}
+
+static vector signed char __ATTRS_o_ai vec_neg(vector signed char __a) {
+ return -__a;
+}
+
+static vector float __ATTRS_o_ai vec_nabs(vector float __a) {
+ return - vec_abs(__a);
+}
+
+#ifdef __VSX__
+static vector double __ATTRS_o_ai vec_nabs(vector double __a) {
+ return - vec_abs(__a);
+}
+
+#endif
+
+#if defined(__POWER8_VECTOR__) && defined(__powerpc64__)
+static vector long long __ATTRS_o_ai vec_nabs(vector long long __a) {
+ return __builtin_altivec_vminsd(__a, -__a);
+}
+#endif
+
+static vector signed int __ATTRS_o_ai vec_nabs(vector signed int __a) {
+ return __builtin_altivec_vminsw(__a, -__a);
+}
+
+static vector signed short __ATTRS_o_ai vec_nabs(vector signed short __a) {
+ return __builtin_altivec_vminsh(__a, -__a);
+}
+
+static vector signed char __ATTRS_o_ai vec_nabs(vector signed char __a) {
+ return __builtin_altivec_vminsb(__a, -__a);
+}
#undef __ATTRS_o_ai
#endif /* __ALTIVEC_H */
diff --git a/lib/Headers/ammintrin.h b/lib/Headers/ammintrin.h
index 8985bb404f47..2843a7a2677f 100644
--- a/lib/Headers/ammintrin.h
+++ b/lib/Headers/ammintrin.h
@@ -30,7 +30,7 @@
#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("sse4a")))
/// \brief Extracts the specified bits from the lower 64 bits of the 128-bit
-/// integer vector operand at the index idx and of the length len.
+/// integer vector operand at the index \a idx and of the length \a len.
///
/// \headerfile <x86intrin.h>
///
@@ -38,7 +38,7 @@
/// __m128i _mm_extracti_si64(__m128i x, const int len, const int idx);
/// \endcode
///
-/// This intrinsic corresponds to the \c EXTRQ instruction.
+/// This intrinsic corresponds to the <c> EXTRQ </c> instruction.
///
/// \param x
/// The value from which bits are extracted.
@@ -49,8 +49,8 @@
/// Bits [5:0] specify the index of the least significant bit; the other
/// bits are ignored. If the sum of the index and length is greater than 64,
/// the result is undefined. If the length and index are both zero, bits
-/// [63:0] of parameter x are extracted. If the length is zero but the index
-/// is non-zero, the result is undefined.
+/// [63:0] of parameter \a x are extracted. If the length is zero but the
+/// index is non-zero, the result is undefined.
/// \returns A 128-bit integer vector whose lower 64 bits contain the bits
/// extracted from the source operand.
#define _mm_extracti_si64(x, len, idx) \
@@ -58,11 +58,12 @@
(char)(len), (char)(idx)))
/// \brief 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 __y.
+/// integer vector operand at the index and of the length specified by
+/// \a __y.
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c EXTRQ instruction.
+/// This intrinsic corresponds to the <c> EXTRQ </c> instruction.
///
/// \param __x
/// The value from which bits are extracted.
@@ -71,8 +72,8 @@
/// length at [5:0]; all other bits are ignored. If bits [5:0] are zero, the
/// length is interpreted as 64. If the sum of the index and length is
/// greater than 64, the result is undefined. If the length and index are
-/// both zero, bits [63:0] of parameter __x are extracted. If the length is
-/// zero but the index is non-zero, the result is undefined.
+/// both zero, bits [63:0] of parameter \a __x are extracted. If the length
+/// is zero but the index is non-zero, the result is undefined.
/// \returns A 128-bit vector whose lower 64 bits contain the bits extracted
/// from the source operand.
static __inline__ __m128i __DEFAULT_FN_ATTRS
@@ -81,9 +82,9 @@ _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 y
-/// into the lower 64 bits of the destination integer vector x at the index
-/// idx and of the length len.
+/// \brief 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.
///
/// \headerfile <x86intrin.h>
///
@@ -92,15 +93,15 @@ _mm_extract_si64(__m128i __x, __m128i __y)
/// const int idx);
/// \endcode
///
-/// This intrinsic corresponds to the \c INSERTQ instruction.
+/// This intrinsic corresponds to the <c> INSERTQ </c> instruction.
///
/// \param x
/// The destination operand where bits will be inserted. The inserted bits
-/// are defined by the length len and by the index idx specifying the least
-/// significant bit.
+/// are defined by the length \a len and by the index \a idx specifying the
+/// least significant bit.
/// \param y
/// The source operand containing the bits to be extracted. The extracted
-/// bits are the least significant bits of operand y of length len.
+/// bits are the least significant bits of operand \a y of length \a len.
/// \param len
/// Bits [5:0] specify the length; the other bits are ignored. If bits [5:0]
/// are zero, the length is interpreted as 64.
@@ -108,45 +109,43 @@ _mm_extract_si64(__m128i __x, __m128i __y)
/// Bits [5:0] specify the index of the least significant bit; the other
/// bits are ignored. If the sum of the index and length is greater than 64,
/// the result is undefined. If the length and index are both zero, bits
-/// [63:0] of parameter y are inserted into parameter x. If the length is
-/// zero but the index is non-zero, the result is undefined.
+/// [63:0] of parameter \a y are inserted into parameter \a x. If the length
+/// is zero but the index is non-zero, the result is undefined.
/// \returns A 128-bit integer vector containing the original lower 64-bits of
-/// destination operand x with the specified bitfields replaced by the lower
-/// bits of source operand y. The upper 64 bits of the return value are
-/// undefined.
-
+/// destination operand \a x with the specified bitfields replaced by the
+/// lower bits of source operand \a y. The upper 64 bits of the return value
+/// are undefined.
#define _mm_inserti_si64(x, y, len, idx) \
((__m128i)__builtin_ia32_insertqi((__v2di)(__m128i)(x), \
(__v2di)(__m128i)(y), \
(char)(len), (char)(idx)))
/// \brief Inserts bits of a specified length from the source integer vector
-/// __y into the lower 64 bits of the destination integer vector __x at the
-/// index and of the length specified by __y.
+/// \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.
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c INSERTQ instruction.
+/// This intrinsic corresponds to the <c> INSERTQ </c> instruction.
///
/// \param __x
/// The destination operand where bits will be inserted. The inserted bits
/// are defined by the length and by the index of the least significant bit
-/// specified by operand __y.
+/// specified by operand \a __y.
/// \param __y
/// The source operand containing the bits to be extracted. The extracted
-/// bits are the least significant bits of operand __y with length specified
-/// by bits [69:64]. These are inserted into the destination at the index
-/// specified by bits [77:72]; all other bits are ignored. If bits [69:64]
-/// are zero, the length is interpreted as 64. If the sum of the index and
-/// length is greater than 64, the result is undefined. If the length and
-/// index are both zero, bits [63:0] of parameter __y are inserted into
-/// parameter __x. If the length is zero but the index is non-zero, the
-/// result is undefined.
+/// bits are the least significant bits of operand \a __y with length
+/// specified by bits [69:64]. These are inserted into the destination at the
+/// index specified by bits [77:72]; all other bits are ignored. If bits
+/// [69:64] are zero, the length is interpreted as 64. If the sum of the
+/// index and length is greater than 64, the result is undefined. If the
+/// length and index are both zero, bits [63:0] of parameter \a __y are
+/// inserted into parameter \a __x. If the length is zero but the index is
+/// non-zero, the result is undefined.
/// \returns A 128-bit integer vector containing the original lower 64-bits of
-/// destination operand __x with the specified bitfields replaced by the
-/// lower bits of source operand __y. The upper 64 bits of the return value
-/// are undefined.
-
+/// destination operand \a __x with the specified bitfields replaced by the
+/// lower bits of source operand \a __y. The upper 64 bits of the return
+/// value are undefined.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_insert_si64(__m128i __x, __m128i __y)
{
@@ -159,7 +158,7 @@ _mm_insert_si64(__m128i __x, __m128i __y)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c MOVNTSD instruction.
+/// This intrinsic corresponds to the <c> MOVNTSD </c> instruction.
///
/// \param __p
/// The 64-bit memory location used to store the register value.
@@ -177,7 +176,7 @@ _mm_stream_sd(double *__p, __m128d __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c MOVNTSS instruction.
+/// This intrinsic corresponds to the <c> MOVNTSS </c> instruction.
///
/// \param __p
/// The 32-bit memory location used to store the register value.
diff --git a/lib/Headers/armintr.h b/lib/Headers/armintr.h
new file mode 100644
index 000000000000..933afcbb91b6
--- /dev/null
+++ b/lib/Headers/armintr.h
@@ -0,0 +1,45 @@
+/*===---- armintr.h - ARM Windows intrinsics -------------------------------===
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+/* Only include this if we're compiling for the windows platform. */
+#ifndef _MSC_VER
+#include_next <armintr.h>
+#else
+
+#ifndef __ARMINTR_H
+#define __ARMINTR_H
+
+typedef enum
+{
+ _ARM_BARRIER_SY = 0xF,
+ _ARM_BARRIER_ST = 0xE,
+ _ARM_BARRIER_ISH = 0xB,
+ _ARM_BARRIER_ISHST = 0xA,
+ _ARM_BARRIER_NSH = 0x7,
+ _ARM_BARRIER_NSHST = 0x6,
+ _ARM_BARRIER_OSH = 0x3,
+ _ARM_BARRIER_OSHST = 0x2
+} _ARMINTR_BARRIER_TYPE;
+
+#endif /* __ARMINTR_H */
+#endif /* _MSC_VER */
diff --git a/lib/Headers/avx512bwintrin.h b/lib/Headers/avx512bwintrin.h
index d3c5a6c96446..629dc8611a7f 100644
--- a/lib/Headers/avx512bwintrin.h
+++ b/lib/Headers/avx512bwintrin.h
@@ -350,19 +350,17 @@ _mm512_add_epi8 (__m512i __A, __m512i __B) {
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_add_epi8 (__m512i __W, __mmask64 __U, __m512i __A, __m512i __B) {
- return (__m512i) __builtin_ia32_paddb512_mask ((__v64qi) __A,
- (__v64qi) __B,
- (__v64qi) __W,
- (__mmask64) __U);
+_mm512_mask_add_epi8(__m512i __W, __mmask64 __U, __m512i __A, __m512i __B) {
+ return (__m512i)__builtin_ia32_selectb_512((__mmask64)__U,
+ (__v64qi)_mm512_add_epi8(__A, __B),
+ (__v64qi)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_add_epi8 (__mmask64 __U, __m512i __A, __m512i __B) {
- return (__m512i) __builtin_ia32_paddb512_mask ((__v64qi) __A,
- (__v64qi) __B,
- (__v64qi) _mm512_setzero_qi(),
- (__mmask64) __U);
+_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());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
@@ -371,19 +369,17 @@ _mm512_sub_epi8 (__m512i __A, __m512i __B) {
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_sub_epi8 (__m512i __W, __mmask64 __U, __m512i __A, __m512i __B) {
- return (__m512i) __builtin_ia32_psubb512_mask ((__v64qi) __A,
- (__v64qi) __B,
- (__v64qi) __W,
- (__mmask64) __U);
+_mm512_mask_sub_epi8(__m512i __W, __mmask64 __U, __m512i __A, __m512i __B) {
+ return (__m512i)__builtin_ia32_selectb_512((__mmask64)__U,
+ (__v64qi)_mm512_sub_epi8(__A, __B),
+ (__v64qi)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_sub_epi8 (__mmask64 __U, __m512i __A, __m512i __B) {
- return (__m512i) __builtin_ia32_psubb512_mask ((__v64qi) __A,
- (__v64qi) __B,
- (__v64qi) _mm512_setzero_qi(),
- (__mmask64) __U);
+_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());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
@@ -392,19 +388,17 @@ _mm512_add_epi16 (__m512i __A, __m512i __B) {
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_add_epi16 (__m512i __W, __mmask32 __U, __m512i __A, __m512i __B) {
- return (__m512i) __builtin_ia32_paddw512_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi) __W,
- (__mmask32) __U);
+_mm512_mask_add_epi16(__m512i __W, __mmask32 __U, __m512i __A, __m512i __B) {
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
+ (__v32hi)_mm512_add_epi16(__A, __B),
+ (__v32hi)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_add_epi16 (__mmask32 __U, __m512i __A, __m512i __B) {
- return (__m512i) __builtin_ia32_paddw512_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi) _mm512_setzero_hi(),
- (__mmask32) __U);
+_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());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
@@ -413,19 +407,17 @@ _mm512_sub_epi16 (__m512i __A, __m512i __B) {
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_sub_epi16 (__m512i __W, __mmask32 __U, __m512i __A, __m512i __B) {
- return (__m512i) __builtin_ia32_psubw512_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi) __W,
- (__mmask32) __U);
+_mm512_mask_sub_epi16(__m512i __W, __mmask32 __U, __m512i __A, __m512i __B) {
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
+ (__v32hi)_mm512_sub_epi16(__A, __B),
+ (__v32hi)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_sub_epi16 (__mmask32 __U, __m512i __A, __m512i __B) {
- return (__m512i) __builtin_ia32_psubw512_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi) _mm512_setzero_hi(),
- (__mmask32) __U);
+_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());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
@@ -434,19 +426,17 @@ _mm512_mullo_epi16 (__m512i __A, __m512i __B) {
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_mullo_epi16 (__m512i __W, __mmask32 __U, __m512i __A, __m512i __B) {
- return (__m512i) __builtin_ia32_pmullw512_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi) __W,
- (__mmask32) __U);
+_mm512_mask_mullo_epi16(__m512i __W, __mmask32 __U, __m512i __A, __m512i __B) {
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
+ (__v32hi)_mm512_mullo_epi16(__A, __B),
+ (__v32hi)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_mullo_epi16 (__mmask32 __U, __m512i __A, __m512i __B) {
- return (__m512i) __builtin_ia32_pmullw512_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi) _mm512_setzero_hi(),
- (__mmask32) __U);
+_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());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
@@ -1018,31 +1008,25 @@ _mm512_mask_min_epu16 (__m512i __W, __mmask32 __M, __m512i __A,
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_shuffle_epi8 (__m512i __A, __m512i __B)
+_mm512_shuffle_epi8(__m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pshufb512_mask ((__v64qi) __A,
- (__v64qi) __B,
- (__v64qi) _mm512_setzero_qi(),
- (__mmask64) -1);
+ return (__m512i)__builtin_ia32_pshufb512((__v64qi)__A,(__v64qi)__B);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_shuffle_epi8 (__m512i __W, __mmask64 __U, __m512i __A,
- __m512i __B)
+_mm512_mask_shuffle_epi8(__m512i __W, __mmask64 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pshufb512_mask ((__v64qi) __A,
- (__v64qi) __B,
- (__v64qi) __W,
- (__mmask64) __U);
+ return (__m512i)__builtin_ia32_selectb_512((__mmask64)__U,
+ (__v64qi)_mm512_shuffle_epi8(__A, __B),
+ (__v64qi)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_shuffle_epi8 (__mmask64 __U, __m512i __A, __m512i __B)
+_mm512_maskz_shuffle_epi8(__mmask64 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pshufb512_mask ((__v64qi) __A,
- (__v64qi) __B,
- (__v64qi) _mm512_setzero_qi(),
- (__mmask64) __U);
+ return (__m512i)__builtin_ia32_selectb_512((__mmask64)__U,
+ (__v64qi)_mm512_shuffle_epi8(__A, __B),
+ (__v64qi)_mm512_setzero_qi());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
@@ -1537,55 +1521,49 @@ _mm512_maskz_unpacklo_epi16(__mmask32 __U, __m512i __A, __m512i __B) {
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_cvtepi8_epi16 (__m256i __A)
+_mm512_cvtepi8_epi16(__m256i __A)
{
- return (__m512i) __builtin_ia32_pmovsxbw512_mask ((__v32qi) __A,
- (__v32hi)
- _mm512_setzero_hi (),
- (__mmask32) -1);
+ /* This function always performs a signed extension, but __v32qi is a char
+ which may be signed or unsigned, so use __v32qs. */
+ return (__m512i)__builtin_convertvector((__v32qs)__A, __v32hi);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_cvtepi8_epi16 (__m512i __W, __mmask32 __U, __m256i __A)
+_mm512_mask_cvtepi8_epi16(__m512i __W, __mmask32 __U, __m256i __A)
{
- return (__m512i) __builtin_ia32_pmovsxbw512_mask ((__v32qi) __A,
- (__v32hi) __W,
- (__mmask32) __U);
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
+ (__v32hi)_mm512_cvtepi8_epi16(__A),
+ (__v32hi)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_cvtepi8_epi16 (__mmask32 __U, __m256i __A)
+_mm512_maskz_cvtepi8_epi16(__mmask32 __U, __m256i __A)
{
- return (__m512i) __builtin_ia32_pmovsxbw512_mask ((__v32qi) __A,
- (__v32hi)
- _mm512_setzero_hi(),
- (__mmask32) __U);
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
+ (__v32hi)_mm512_cvtepi8_epi16(__A),
+ (__v32hi)_mm512_setzero_hi());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_cvtepu8_epi16 (__m256i __A)
+_mm512_cvtepu8_epi16(__m256i __A)
{
- return (__m512i) __builtin_ia32_pmovzxbw512_mask ((__v32qi) __A,
- (__v32hi)
- _mm512_setzero_hi (),
- (__mmask32) -1);
+ return (__m512i)__builtin_convertvector((__v32qu)__A, __v32hi);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_cvtepu8_epi16 (__m512i __W, __mmask32 __U, __m256i __A)
+_mm512_mask_cvtepu8_epi16(__m512i __W, __mmask32 __U, __m256i __A)
{
- return (__m512i) __builtin_ia32_pmovzxbw512_mask ((__v32qi) __A,
- (__v32hi) __W,
- (__mmask32) __U);
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
+ (__v32hi)_mm512_cvtepu8_epi16(__A),
+ (__v32hi)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_cvtepu8_epi16 (__mmask32 __U, __m256i __A)
+_mm512_maskz_cvtepu8_epi16(__mmask32 __U, __m256i __A)
{
- return (__m512i) __builtin_ia32_pmovzxbw512_mask ((__v32qi) __A,
- (__v32hi)
- _mm512_setzero_hi(),
- (__mmask32) __U);
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
+ (__v32hi)_mm512_cvtepu8_epi16(__A),
+ (__v32hi)_mm512_setzero_hi());
}
@@ -1704,79 +1682,70 @@ _mm512_maskz_cvtepu8_epi16 (__mmask32 __U, __m256i __A)
(__v32hi)_mm512_setzero_hi()); })
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_sllv_epi16 (__m512i __A, __m512i __B)
+_mm512_sllv_epi16(__m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_psllv32hi_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi)
- _mm512_setzero_hi (),
- (__mmask32) -1);
+ return (__m512i)__builtin_ia32_psllv32hi((__v32hi) __A, (__v32hi) __B);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_sllv_epi16 (__m512i __W, __mmask32 __U, __m512i __A,
- __m512i __B)
+_mm512_mask_sllv_epi16 (__m512i __W, __mmask32 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_psllv32hi_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi) __W,
- (__mmask32) __U);
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
+ (__v32hi)_mm512_sllv_epi16(__A, __B),
+ (__v32hi)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_sllv_epi16 (__mmask32 __U, __m512i __A, __m512i __B)
+_mm512_maskz_sllv_epi16(__mmask32 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_psllv32hi_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi)
- _mm512_setzero_hi (),
- (__mmask32) __U);
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
+ (__v32hi)_mm512_sllv_epi16(__A, __B),
+ (__v32hi)_mm512_setzero_hi());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_sll_epi16 (__m512i __A, __m128i __B)
+_mm512_sll_epi16(__m512i __A, __m128i __B)
{
- return (__m512i) __builtin_ia32_psllw512_mask ((__v32hi) __A,
- (__v8hi) __B,
- (__v32hi)
- _mm512_setzero_hi (),
- (__mmask32) -1);
+ return (__m512i)__builtin_ia32_psllw512((__v32hi) __A, (__v8hi) __B);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_sll_epi16 (__m512i __W, __mmask32 __U, __m512i __A,
- __m128i __B)
+_mm512_mask_sll_epi16(__m512i __W, __mmask32 __U, __m512i __A, __m128i __B)
{
- return (__m512i) __builtin_ia32_psllw512_mask ((__v32hi) __A,
- (__v8hi) __B,
- (__v32hi) __W,
- (__mmask32) __U);
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
+ (__v32hi)_mm512_sll_epi16(__A, __B),
+ (__v32hi)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_sll_epi16 (__mmask32 __U, __m512i __A, __m128i __B)
+_mm512_maskz_sll_epi16(__mmask32 __U, __m512i __A, __m128i __B)
{
- return (__m512i) __builtin_ia32_psllw512_mask ((__v32hi) __A,
- (__v8hi) __B,
- (__v32hi)
- _mm512_setzero_hi (),
- (__mmask32) __U);
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
+ (__v32hi)_mm512_sll_epi16(__A, __B),
+ (__v32hi)_mm512_setzero_hi());
}
-#define _mm512_slli_epi16(A, B) __extension__ ({ \
- (__m512i)__builtin_ia32_psllwi512_mask((__v32hi)(__m512i)(A), (int)(B), \
- (__v32hi)_mm512_setzero_hi(), \
- (__mmask32)-1); })
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_slli_epi16(__m512i __A, int __B)
+{
+ return (__m512i)__builtin_ia32_psllwi512((__v32hi)__A, __B);
+}
-#define _mm512_mask_slli_epi16(W, U, A, B) __extension__ ({ \
- (__m512i)__builtin_ia32_psllwi512_mask((__v32hi)(__m512i)(A), (int)(B), \
- (__v32hi)(__m512i)(W), \
- (__mmask32)(U)); })
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_slli_epi16(__m512i __W, __mmask32 __U, __m512i __A, int __B)
+{
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
+ (__v32hi)_mm512_slli_epi16(__A, __B),
+ (__v32hi)__W);
+}
-#define _mm512_maskz_slli_epi16(U, A, B) __extension__ ({ \
- (__m512i)__builtin_ia32_psllwi512_mask((__v32hi)(__m512i)(A), (int)(B), \
- (__v32hi)_mm512_setzero_hi(), \
- (__mmask32)(U)); })
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_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( \
@@ -1848,155 +1817,136 @@ _mm512_maskz_sll_epi16 (__mmask32 __U, __m512i __A, __m128i __B)
((char)(imm)&0xF0) ? 63 : ((char)(imm)>0xF ? 79 : 127) - (char)(imm)); })
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_srlv_epi16 (__m512i __A, __m512i __B)
+_mm512_srlv_epi16(__m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_psrlv32hi_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi)
- _mm512_setzero_hi (),
- (__mmask32) -1);
+ return (__m512i)__builtin_ia32_psrlv32hi((__v32hi)__A, (__v32hi)__B);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_srlv_epi16 (__m512i __W, __mmask32 __U, __m512i __A,
- __m512i __B)
+_mm512_mask_srlv_epi16(__m512i __W, __mmask32 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_psrlv32hi_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi) __W,
- (__mmask32) __U);
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
+ (__v32hi)_mm512_srlv_epi16(__A, __B),
+ (__v32hi)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_srlv_epi16 (__mmask32 __U, __m512i __A, __m512i __B)
+_mm512_maskz_srlv_epi16(__mmask32 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_psrlv32hi_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi)
- _mm512_setzero_hi (),
- (__mmask32) __U);
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
+ (__v32hi)_mm512_srlv_epi16(__A, __B),
+ (__v32hi)_mm512_setzero_hi());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_srav_epi16 (__m512i __A, __m512i __B)
+_mm512_srav_epi16(__m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_psrav32hi_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi)
- _mm512_setzero_hi (),
- (__mmask32) -1);
+ return (__m512i)__builtin_ia32_psrav32hi((__v32hi)__A, (__v32hi)__B);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_srav_epi16 (__m512i __W, __mmask32 __U, __m512i __A,
- __m512i __B)
+_mm512_mask_srav_epi16(__m512i __W, __mmask32 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_psrav32hi_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi) __W,
- (__mmask32) __U);
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
+ (__v32hi)_mm512_srav_epi16(__A, __B),
+ (__v32hi)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_srav_epi16 (__mmask32 __U, __m512i __A, __m512i __B)
+_mm512_maskz_srav_epi16(__mmask32 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_psrav32hi_mask ((__v32hi) __A,
- (__v32hi) __B,
- (__v32hi)
- _mm512_setzero_hi (),
- (__mmask32) __U);
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
+ (__v32hi)_mm512_srav_epi16(__A, __B),
+ (__v32hi)_mm512_setzero_hi());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_sra_epi16 (__m512i __A, __m128i __B)
+_mm512_sra_epi16(__m512i __A, __m128i __B)
{
- return (__m512i) __builtin_ia32_psraw512_mask ((__v32hi) __A,
- (__v8hi) __B,
- (__v32hi)
- _mm512_setzero_hi (),
- (__mmask32) -1);
+ return (__m512i)__builtin_ia32_psraw512((__v32hi) __A, (__v8hi) __B);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_sra_epi16 (__m512i __W, __mmask32 __U, __m512i __A,
- __m128i __B)
+_mm512_mask_sra_epi16(__m512i __W, __mmask32 __U, __m512i __A, __m128i __B)
{
- return (__m512i) __builtin_ia32_psraw512_mask ((__v32hi) __A,
- (__v8hi) __B,
- (__v32hi) __W,
- (__mmask32) __U);
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
+ (__v32hi)_mm512_sra_epi16(__A, __B),
+ (__v32hi)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_sra_epi16 (__mmask32 __U, __m512i __A, __m128i __B)
+_mm512_maskz_sra_epi16(__mmask32 __U, __m512i __A, __m128i __B)
{
- return (__m512i) __builtin_ia32_psraw512_mask ((__v32hi) __A,
- (__v8hi) __B,
- (__v32hi)
- _mm512_setzero_hi (),
- (__mmask32) __U);
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
+ (__v32hi)_mm512_sra_epi16(__A, __B),
+ (__v32hi)_mm512_setzero_hi());
}
-#define _mm512_srai_epi16(A, B) __extension__ ({ \
- (__m512i)__builtin_ia32_psrawi512_mask((__v32hi)(__m512i)(A), (int)(B), \
- (__v32hi)_mm512_setzero_hi(), \
- (__mmask32)-1); })
-
-#define _mm512_mask_srai_epi16(W, U, A, B) __extension__ ({ \
- (__m512i)__builtin_ia32_psrawi512_mask((__v32hi)(__m512i)(A), (int)(B), \
- (__v32hi)(__m512i)(W), \
- (__mmask32)(U)); })
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_srai_epi16(__m512i __A, int __B)
+{
+ return (__m512i)__builtin_ia32_psrawi512((__v32hi)__A, __B);
+}
-#define _mm512_maskz_srai_epi16(U, A, B) __extension__ ({ \
- (__m512i)__builtin_ia32_psrawi512_mask((__v32hi)(__m512i)(A), (int)(B), \
- (__v32hi)_mm512_setzero_hi(), \
- (__mmask32)(U)); })
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_srai_epi16(__m512i __W, __mmask32 __U, __m512i __A, int __B)
+{
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
+ (__v32hi)_mm512_srai_epi16(__A, __B),
+ (__v32hi)__W);
+}
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_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());
+}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_srl_epi16 (__m512i __A, __m128i __B)
+_mm512_srl_epi16(__m512i __A, __m128i __B)
{
- return (__m512i) __builtin_ia32_psrlw512_mask ((__v32hi) __A,
- (__v8hi) __B,
- (__v32hi)
- _mm512_setzero_hi (),
- (__mmask32) -1);
+ return (__m512i)__builtin_ia32_psrlw512((__v32hi) __A, (__v8hi) __B);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_srl_epi16 (__m512i __W, __mmask32 __U, __m512i __A,
- __m128i __B)
+_mm512_mask_srl_epi16(__m512i __W, __mmask32 __U, __m512i __A, __m128i __B)
{
- return (__m512i) __builtin_ia32_psrlw512_mask ((__v32hi) __A,
- (__v8hi) __B,
- (__v32hi) __W,
- (__mmask32) __U);
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
+ (__v32hi)_mm512_srl_epi16(__A, __B),
+ (__v32hi)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_srl_epi16 (__mmask32 __U, __m512i __A, __m128i __B)
+_mm512_maskz_srl_epi16(__mmask32 __U, __m512i __A, __m128i __B)
{
- return (__m512i) __builtin_ia32_psrlw512_mask ((__v32hi) __A,
- (__v8hi) __B,
- (__v32hi)
- _mm512_setzero_hi (),
- (__mmask32) __U);
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
+ (__v32hi)_mm512_srl_epi16(__A, __B),
+ (__v32hi)_mm512_setzero_hi());
}
-#define _mm512_srli_epi16(A, imm) __extension__ ({ \
- (__m512i)__builtin_ia32_psrlwi512_mask((__v32hi)(__m512i)(A), (int)(imm), \
- (__v32hi)_mm512_setzero_hi(), \
- (__mmask32)-1); })
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_srli_epi16(__m512i __A, int __B)
+{
+ return (__m512i)__builtin_ia32_psrlwi512((__v32hi)__A, __B);
+}
-#define _mm512_mask_srli_epi16(W, U, A, imm) __extension__ ({ \
- (__m512i)__builtin_ia32_psrlwi512_mask((__v32hi)(__m512i)(A), (int)(imm), \
- (__v32hi)(__m512i)(W), \
- (__mmask32)(U)); })
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_srli_epi16(__m512i __W, __mmask32 __U, __m512i __A, int __B)
+{
+ return (__m512i)__builtin_ia32_selectw_512((__mmask32)__U,
+ (__v32hi)_mm512_srli_epi16(__A, __B),
+ (__v32hi)__W);
+}
-#define _mm512_maskz_srli_epi16(U, A, imm) __extension__ ({ \
- (__m512i)__builtin_ia32_psrlwi512_mask((__v32hi)(__m512i)(A), (int)(imm), \
- (__v32hi)_mm512_setzero_hi(), \
- (__mmask32)(U)); })
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_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( \
diff --git a/lib/Headers/avx512dqintrin.h b/lib/Headers/avx512dqintrin.h
index 13665e4c6668..ae44b98a9495 100644
--- a/lib/Headers/avx512dqintrin.h
+++ b/lib/Headers/avx512dqintrin.h
@@ -37,204 +37,169 @@ _mm512_mullo_epi64 (__m512i __A, __m512i __B) {
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_mullo_epi64 (__m512i __W, __mmask8 __U, __m512i __A, __m512i __B) {
- return (__m512i) __builtin_ia32_pmullq512_mask ((__v8di) __A,
- (__v8di) __B,
- (__v8di) __W,
- (__mmask8) __U);
+_mm512_mask_mullo_epi64(__m512i __W, __mmask8 __U, __m512i __A, __m512i __B) {
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
+ (__v8di)_mm512_mullo_epi64(__A, __B),
+ (__v8di)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_mullo_epi64 (__mmask8 __U, __m512i __A, __m512i __B) {
- return (__m512i) __builtin_ia32_pmullq512_mask ((__v8di) __A,
- (__v8di) __B,
- (__v8di)
- _mm512_setzero_si512 (),
- (__mmask8) __U);
+_mm512_maskz_mullo_epi64(__mmask8 __U, __m512i __A, __m512i __B) {
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
+ (__v8di)_mm512_mullo_epi64(__A, __B),
+ (__v8di)_mm512_setzero_si512());
}
static __inline__ __m512d __DEFAULT_FN_ATTRS
-_mm512_xor_pd (__m512d __A, __m512d __B) {
- return (__m512d) ((__v8du) __A ^ (__v8du) __B);
+_mm512_xor_pd(__m512d __A, __m512d __B) {
+ return (__m512d)((__v8du)__A ^ (__v8du)__B);
}
static __inline__ __m512d __DEFAULT_FN_ATTRS
-_mm512_mask_xor_pd (__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) {
- return (__m512d) __builtin_ia32_xorpd512_mask ((__v8df) __A,
- (__v8df) __B,
- (__v8df) __W,
- (__mmask8) __U);
+_mm512_mask_xor_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) {
+ return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
+ (__v8df)_mm512_xor_pd(__A, __B),
+ (__v8df)__W);
}
static __inline__ __m512d __DEFAULT_FN_ATTRS
-_mm512_maskz_xor_pd (__mmask8 __U, __m512d __A, __m512d __B) {
- return (__m512d) __builtin_ia32_xorpd512_mask ((__v8df) __A,
- (__v8df) __B,
- (__v8df)
- _mm512_setzero_pd (),
- (__mmask8) __U);
+_mm512_maskz_xor_pd(__mmask8 __U, __m512d __A, __m512d __B) {
+ return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
+ (__v8df)_mm512_xor_pd(__A, __B),
+ (__v8df)_mm512_setzero_pd());
}
static __inline__ __m512 __DEFAULT_FN_ATTRS
_mm512_xor_ps (__m512 __A, __m512 __B) {
- return (__m512) ((__v16su) __A ^ (__v16su) __B);
+ return (__m512)((__v16su)__A ^ (__v16su)__B);
}
static __inline__ __m512 __DEFAULT_FN_ATTRS
-_mm512_mask_xor_ps (__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) {
- return (__m512) __builtin_ia32_xorps512_mask ((__v16sf) __A,
- (__v16sf) __B,
- (__v16sf) __W,
- (__mmask16) __U);
+_mm512_mask_xor_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) {
+ return (__m512)__builtin_ia32_selectps_512((__mmask16)__U,
+ (__v16sf)_mm512_xor_ps(__A, __B),
+ (__v16sf)__W);
}
static __inline__ __m512 __DEFAULT_FN_ATTRS
-_mm512_maskz_xor_ps (__mmask16 __U, __m512 __A, __m512 __B) {
- return (__m512) __builtin_ia32_xorps512_mask ((__v16sf) __A,
- (__v16sf) __B,
- (__v16sf)
- _mm512_setzero_ps (),
- (__mmask16) __U);
+_mm512_maskz_xor_ps(__mmask16 __U, __m512 __A, __m512 __B) {
+ return (__m512)__builtin_ia32_selectps_512((__mmask16)__U,
+ (__v16sf)_mm512_xor_ps(__A, __B),
+ (__v16sf)_mm512_setzero_ps());
}
static __inline__ __m512d __DEFAULT_FN_ATTRS
-_mm512_or_pd (__m512d __A, __m512d __B) {
- return (__m512d) ((__v8du) __A | (__v8du) __B);
+_mm512_or_pd(__m512d __A, __m512d __B) {
+ return (__m512d)((__v8du)__A | (__v8du)__B);
}
static __inline__ __m512d __DEFAULT_FN_ATTRS
-_mm512_mask_or_pd (__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) {
- return (__m512d) __builtin_ia32_orpd512_mask ((__v8df) __A,
- (__v8df) __B,
- (__v8df) __W,
- (__mmask8) __U);
+_mm512_mask_or_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) {
+ return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
+ (__v8df)_mm512_or_pd(__A, __B),
+ (__v8df)__W);
}
static __inline__ __m512d __DEFAULT_FN_ATTRS
-_mm512_maskz_or_pd (__mmask8 __U, __m512d __A, __m512d __B) {
- return (__m512d) __builtin_ia32_orpd512_mask ((__v8df) __A,
- (__v8df) __B,
- (__v8df)
- _mm512_setzero_pd (),
- (__mmask8) __U);
+_mm512_maskz_or_pd(__mmask8 __U, __m512d __A, __m512d __B) {
+ return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
+ (__v8df)_mm512_or_pd(__A, __B),
+ (__v8df)_mm512_setzero_pd());
}
static __inline__ __m512 __DEFAULT_FN_ATTRS
-_mm512_or_ps (__m512 __A, __m512 __B) {
- return (__m512) ((__v16su) __A | (__v16su) __B);
+_mm512_or_ps(__m512 __A, __m512 __B) {
+ return (__m512)((__v16su)__A | (__v16su)__B);
}
static __inline__ __m512 __DEFAULT_FN_ATTRS
-_mm512_mask_or_ps (__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) {
- return (__m512) __builtin_ia32_orps512_mask ((__v16sf) __A,
- (__v16sf) __B,
- (__v16sf) __W,
- (__mmask16) __U);
+_mm512_mask_or_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) {
+ return (__m512)__builtin_ia32_selectps_512((__mmask16)__U,
+ (__v16sf)_mm512_or_ps(__A, __B),
+ (__v16sf)__W);
}
static __inline__ __m512 __DEFAULT_FN_ATTRS
-_mm512_maskz_or_ps (__mmask16 __U, __m512 __A, __m512 __B) {
- return (__m512) __builtin_ia32_orps512_mask ((__v16sf) __A,
- (__v16sf) __B,
- (__v16sf)
- _mm512_setzero_ps (),
- (__mmask16) __U);
+_mm512_maskz_or_ps(__mmask16 __U, __m512 __A, __m512 __B) {
+ return (__m512)__builtin_ia32_selectps_512((__mmask16)__U,
+ (__v16sf)_mm512_or_ps(__A, __B),
+ (__v16sf)_mm512_setzero_ps());
}
static __inline__ __m512d __DEFAULT_FN_ATTRS
-_mm512_and_pd (__m512d __A, __m512d __B) {
- return (__m512d) ((__v8du) __A & (__v8du) __B);
+_mm512_and_pd(__m512d __A, __m512d __B) {
+ return (__m512d)((__v8du)__A & (__v8du)__B);
}
static __inline__ __m512d __DEFAULT_FN_ATTRS
-_mm512_mask_and_pd (__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) {
- return (__m512d) __builtin_ia32_andpd512_mask ((__v8df) __A,
- (__v8df) __B,
- (__v8df) __W,
- (__mmask8) __U);
+_mm512_mask_and_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) {
+ return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
+ (__v8df)_mm512_and_pd(__A, __B),
+ (__v8df)__W);
}
static __inline__ __m512d __DEFAULT_FN_ATTRS
-_mm512_maskz_and_pd (__mmask8 __U, __m512d __A, __m512d __B) {
- return (__m512d) __builtin_ia32_andpd512_mask ((__v8df) __A,
- (__v8df) __B,
- (__v8df)
- _mm512_setzero_pd (),
- (__mmask8) __U);
+_mm512_maskz_and_pd(__mmask8 __U, __m512d __A, __m512d __B) {
+ return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
+ (__v8df)_mm512_and_pd(__A, __B),
+ (__v8df)_mm512_setzero_pd());
}
static __inline__ __m512 __DEFAULT_FN_ATTRS
-_mm512_and_ps (__m512 __A, __m512 __B) {
- return (__m512) ((__v16su) __A & (__v16su) __B);
+_mm512_and_ps(__m512 __A, __m512 __B) {
+ return (__m512)((__v16su)__A & (__v16su)__B);
}
static __inline__ __m512 __DEFAULT_FN_ATTRS
-_mm512_mask_and_ps (__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) {
- return (__m512) __builtin_ia32_andps512_mask ((__v16sf) __A,
- (__v16sf) __B,
- (__v16sf) __W,
- (__mmask16) __U);
+_mm512_mask_and_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) {
+ return (__m512)__builtin_ia32_selectps_512((__mmask16)__U,
+ (__v16sf)_mm512_and_ps(__A, __B),
+ (__v16sf)__W);
}
static __inline__ __m512 __DEFAULT_FN_ATTRS
-_mm512_maskz_and_ps (__mmask16 __U, __m512 __A, __m512 __B) {
- return (__m512) __builtin_ia32_andps512_mask ((__v16sf) __A,
- (__v16sf) __B,
- (__v16sf)
- _mm512_setzero_ps (),
- (__mmask16) __U);
+_mm512_maskz_and_ps(__mmask16 __U, __m512 __A, __m512 __B) {
+ return (__m512)__builtin_ia32_selectps_512((__mmask16)__U,
+ (__v16sf)_mm512_and_ps(__A, __B),
+ (__v16sf)_mm512_setzero_ps());
}
static __inline__ __m512d __DEFAULT_FN_ATTRS
-_mm512_andnot_pd (__m512d __A, __m512d __B) {
- return (__m512d) __builtin_ia32_andnpd512_mask ((__v8df) __A,
- (__v8df) __B,
- (__v8df)
- _mm512_setzero_pd (),
- (__mmask8) -1);
+_mm512_andnot_pd(__m512d __A, __m512d __B) {
+ return (__m512d)(~(__v8du)__A & (__v8du)__B);
}
static __inline__ __m512d __DEFAULT_FN_ATTRS
-_mm512_mask_andnot_pd (__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) {
- return (__m512d) __builtin_ia32_andnpd512_mask ((__v8df) __A,
- (__v8df) __B,
- (__v8df) __W,
- (__mmask8) __U);
+_mm512_mask_andnot_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) {
+ return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
+ (__v8df)_mm512_andnot_pd(__A, __B),
+ (__v8df)__W);
}
static __inline__ __m512d __DEFAULT_FN_ATTRS
-_mm512_maskz_andnot_pd (__mmask8 __U, __m512d __A, __m512d __B) {
- return (__m512d) __builtin_ia32_andnpd512_mask ((__v8df) __A,
- (__v8df) __B,
- (__v8df)
- _mm512_setzero_pd (),
- (__mmask8) __U);
+_mm512_maskz_andnot_pd(__mmask8 __U, __m512d __A, __m512d __B) {
+ return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
+ (__v8df)_mm512_andnot_pd(__A, __B),
+ (__v8df)_mm512_setzero_pd());
}
static __inline__ __m512 __DEFAULT_FN_ATTRS
-_mm512_andnot_ps (__m512 __A, __m512 __B) {
- return (__m512) __builtin_ia32_andnps512_mask ((__v16sf) __A,
- (__v16sf) __B,
- (__v16sf)
- _mm512_setzero_ps (),
- (__mmask16) -1);
+_mm512_andnot_ps(__m512 __A, __m512 __B) {
+ return (__m512)(~(__v16su)__A & (__v16su)__B);
}
static __inline__ __m512 __DEFAULT_FN_ATTRS
-_mm512_mask_andnot_ps (__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) {
- return (__m512) __builtin_ia32_andnps512_mask ((__v16sf) __A,
- (__v16sf) __B,
- (__v16sf) __W,
- (__mmask16) __U);
+_mm512_mask_andnot_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) {
+ return (__m512)__builtin_ia32_selectps_512((__mmask16)__U,
+ (__v16sf)_mm512_andnot_ps(__A, __B),
+ (__v16sf)__W);
}
static __inline__ __m512 __DEFAULT_FN_ATTRS
-_mm512_maskz_andnot_ps (__mmask16 __U, __m512 __A, __m512 __B) {
- return (__m512) __builtin_ia32_andnps512_mask ((__v16sf) __A,
- (__v16sf) __B,
- (__v16sf)
- _mm512_setzero_ps (),
- (__mmask16) __U);
+_mm512_maskz_andnot_ps(__mmask16 __U, __m512 __A, __m512 __B) {
+ return (__m512)__builtin_ia32_selectps_512((__mmask16)__U,
+ (__v16sf)_mm512_andnot_ps(__A, __B),
+ (__v16sf)_mm512_setzero_ps());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
@@ -1151,148 +1116,184 @@ _mm512_maskz_broadcast_i64x2 (__mmask8 __M, __m128i __A)
}
#define _mm512_extractf32x8_ps(A, imm) __extension__ ({ \
- (__m256)__builtin_ia32_extractf32x8_mask((__v16sf)(__m512)(A), (int)(imm), \
- (__v8sf)_mm256_setzero_ps(), \
- (__mmask8)-1); })
+ (__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_extractf32x8_mask((__v16sf)(__m512)(A), (int)(imm), \
- (__v8sf)(__m256)(W), \
- (__mmask8)(U)); })
+ (__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_extractf32x8_mask((__v16sf)(__m512)(A), (int)(imm), \
- (__v8sf)_mm256_setzero_ps(), \
- (__mmask8)(U)); })
+ (__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_ia32_extractf64x2_512_mask((__v8df)(__m512d)(A), \
- (int)(imm), \
- (__v2df)_mm_setzero_pd(), \
- (__mmask8)-1); })
+ (__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_extractf64x2_512_mask((__v8df)(__m512d)(A), \
- (int)(imm), \
- (__v2df)(__m128d)(W), \
- (__mmask8)(U)); })
+ (__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_extractf64x2_512_mask((__v8df)(__m512d)(A), \
- (int)(imm), \
- (__v2df)_mm_setzero_pd(), \
- (__mmask8)(U)); })
+ (__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_ia32_extracti32x8_mask((__v16si)(__m512i)(A), (int)(imm), \
- (__v8si)_mm256_setzero_si256(), \
- (__mmask8)-1); })
+ (__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_extracti32x8_mask((__v16si)(__m512i)(A), (int)(imm), \
- (__v8si)(__m256i)(W), \
- (__mmask8)(U)); })
+ (__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_extracti32x8_mask((__v16si)(__m512i)(A), (int)(imm), \
- (__v8si)_mm256_setzero_si256(), \
- (__mmask8)(U)); })
+ (__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_ia32_extracti64x2_512_mask((__v8di)(__m512i)(A), \
- (int)(imm), \
- (__v2di)_mm_setzero_di(), \
- (__mmask8)-1); })
+ (__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__ ({ \
- (__m128i)__builtin_ia32_extracti64x2_512_mask((__v8di)(__m512i)(A), \
- (int)(imm), \
- (__v2di)(__m128i)(W), \
- (__mmask8)(U)); })
+ (__m128d)__builtin_ia32_selectq_128((__mmask8)(U), \
+ (__v2di)_mm512_extracti64x2_epi64((A), (imm)), \
+ (__v2di)(W)); })
#define _mm512_maskz_extracti64x2_epi64(U, A, imm) __extension__ ({ \
- (__m128i)__builtin_ia32_extracti64x2_512_mask((__v8di)(__m512i)(A), \
- (int)(imm), \
- (__v2di)_mm_setzero_di(), \
- (__mmask8)(U)); })
+ (__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_ia32_insertf32x8_mask((__v16sf)(__m512)(A), \
- (__v8sf)(__m256)(B), (int)(imm), \
- (__v16sf)_mm512_setzero_ps(), \
- (__mmask16)-1); })
+ (__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__ ({ \
- (__m512)__builtin_ia32_insertf32x8_mask((__v16sf)(__m512)(A), \
- (__v8sf)(__m256)(B), (int)(imm), \
- (__v16sf)(__m512)(W), \
- (__mmask16)(U)); })
+ (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \
+ (__v16sf)_mm512_insertf32x8((A), (B), (imm)), \
+ (__v16sf)(W)); })
#define _mm512_maskz_insertf32x8(U, A, B, imm) __extension__ ({ \
- (__m512)__builtin_ia32_insertf32x8_mask((__v16sf)(__m512)(A), \
- (__v8sf)(__m256)(B), (int)(imm), \
- (__v16sf)_mm512_setzero_ps(), \
- (__mmask16)(U)); })
+ (__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_ia32_insertf64x2_512_mask((__v8df)(__m512d)(A), \
- (__v2df)(__m128d)(B), \
- (int)(imm), \
- (__v8df)_mm512_setzero_pd(), \
- (__mmask8)-1); })
+ (__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__ ({ \
- (__m512d)__builtin_ia32_insertf64x2_512_mask((__v8df)(__m512d)(A), \
- (__v2df)(__m128d)(B), \
- (int)(imm), \
- (__v8df)(__m512d)(W), \
- (__mmask8)(U)); })
+ (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \
+ (__v8df)_mm512_insertf64x2((A), (B), (imm)), \
+ (__v8df)(W)); })
#define _mm512_maskz_insertf64x2(U, A, B, imm) __extension__ ({ \
- (__m512d)__builtin_ia32_insertf64x2_512_mask((__v8df)(__m512d)(A), \
- (__v2df)(__m128d)(B), \
- (int)(imm), \
- (__v8df)_mm512_setzero_pd(), \
- (__mmask8)(U)); })
+ (__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_ia32_inserti32x8_mask((__v16si)(__m512i)(A), \
- (__v8si)(__m256i)(B), (int)(imm), \
- (__v16si)_mm512_setzero_si512(), \
- (__mmask16)-1); })
+ (__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__ ({ \
- (__m512i)__builtin_ia32_inserti32x8_mask((__v16si)(__m512i)(A), \
- (__v8si)(__m256i)(B), (int)(imm), \
- (__v16si)(__m512i)(W), \
- (__mmask16)(U)); })
+ (__m512i)__builtin_ia32_selectd_512((__mmask16)(U), \
+ (__v16si)_mm512_inserti32x8((A), (B), (imm)), \
+ (__v16si)(W)); })
#define _mm512_maskz_inserti32x8(U, A, B, imm) __extension__ ({ \
- (__m512i)__builtin_ia32_inserti32x8_mask((__v16si)(__m512i)(A), \
- (__v8si)(__m256i)(B), (int)(imm), \
- (__v16si)_mm512_setzero_si512(), \
- (__mmask16)(U)); })
+ (__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_ia32_inserti64x2_512_mask((__v8di)(__m512i)(A), \
- (__v2di)(__m128i)(B), \
- (int)(imm), \
- (__v8di)_mm512_setzero_si512(), \
- (__mmask8)-1); })
+ (__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__ ({ \
- (__m512i)__builtin_ia32_inserti64x2_512_mask((__v8di)(__m512i)(A), \
- (__v2di)(__m128i)(B), \
- (int)(imm), \
- (__v8di)(__m512i)(W), \
- (__mmask8)(U)); })
+ (__m512i)__builtin_ia32_selectq_512((__mmask8)(U), \
+ (__v8di)_mm512_inserti64x2((A), (B), (imm)), \
+ (__v8di)(W)); })
#define _mm512_maskz_inserti64x2(U, A, B, imm) __extension__ ({ \
- (__m512i)__builtin_ia32_inserti64x2_512_mask((__v8di)(__m512i)(A), \
- (__v2di)(__m128i)(B), \
- (int)(imm), \
- (__v8di)_mm512_setzero_si512(), \
- (__mmask8)(U)); })
+ (__m512i)__builtin_ia32_selectq_512((__mmask8)(U), \
+ (__v8di)_mm512_inserti64x2((A), (B), (imm)), \
+ (__v8di)_mm512_setzero_si512()); })
#define _mm512_mask_fpclass_ps_mask(U, A, imm) __extension__ ({ \
(__mmask16)__builtin_ia32_fpclassps512_mask((__v16sf)(__m512)(A), \
diff --git a/lib/Headers/avx512fintrin.h b/lib/Headers/avx512fintrin.h
index 0bf6582345d4..e6a7217c8967 100644
--- a/lib/Headers/avx512fintrin.h
+++ b/lib/Headers/avx512fintrin.h
@@ -54,6 +54,19 @@ typedef unsigned short __mmask16;
#define _MM_FROUND_TO_ZERO 0x03
#define _MM_FROUND_CUR_DIRECTION 0x04
+/* Constants for integer comparison predicates */
+typedef enum {
+ _MM_CMPINT_EQ, /* Equal */
+ _MM_CMPINT_LT, /* Less than */
+ _MM_CMPINT_LE, /* Less than or Equal */
+ _MM_CMPINT_UNUSED,
+ _MM_CMPINT_NE, /* Not Equal */
+ _MM_CMPINT_NLT, /* Not Less than */
+#define _MM_CMPINT_GE _MM_CMPINT_NLT /* Greater than or Equal */
+ _MM_CMPINT_NLE /* Not Less than or Equal */
+#define _MM_CMPINT_GT _MM_CMPINT_NLE /* Greater than */
+} _MM_CMPINT_ENUM;
+
typedef enum
{
_MM_PERM_AAAA = 0x00, _MM_PERM_AAAB = 0x01, _MM_PERM_AAAC = 0x02,
@@ -503,6 +516,18 @@ _mm512_castsi512_si256 (__m512i __A)
return (__m256i)__builtin_shufflevector(__A, __A , 0, 1, 2, 3);
}
+static __inline__ __mmask16 __DEFAULT_FN_ATTRS
+_mm512_int2mask(int __a)
+{
+ return (__mmask16)__a;
+}
+
+static __inline__ int __DEFAULT_FN_ATTRS
+_mm512_mask2int(__mmask16 __a)
+{
+ return (int)__a;
+}
+
/* Bitwise operators */
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_and_epi32(__m512i __a, __m512i __b)
@@ -737,22 +762,19 @@ _mm512_add_epi64 (__m512i __A, __m512i __B)
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_add_epi64 (__m512i __W, __mmask8 __U, __m512i __A, __m512i __B)
+_mm512_mask_add_epi64(__m512i __W, __mmask8 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_paddq512_mask ((__v8di) __A,
- (__v8di) __B,
- (__v8di) __W,
- (__mmask8) __U);
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
+ (__v8di)_mm512_add_epi64(__A, __B),
+ (__v8di)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_add_epi64 (__mmask8 __U, __m512i __A, __m512i __B)
+_mm512_maskz_add_epi64(__mmask8 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_paddq512_mask ((__v8di) __A,
- (__v8di) __B,
- (__v8di)
- _mm512_setzero_si512 (),
- (__mmask8) __U);
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
+ (__v8di)_mm512_add_epi64(__A, __B),
+ (__v8di)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
@@ -762,22 +784,19 @@ _mm512_sub_epi64 (__m512i __A, __m512i __B)
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_sub_epi64 (__m512i __W, __mmask8 __U, __m512i __A, __m512i __B)
+_mm512_mask_sub_epi64(__m512i __W, __mmask8 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_psubq512_mask ((__v8di) __A,
- (__v8di) __B,
- (__v8di) __W,
- (__mmask8) __U);
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
+ (__v8di)_mm512_sub_epi64(__A, __B),
+ (__v8di)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_sub_epi64 (__mmask8 __U, __m512i __A, __m512i __B)
+_mm512_maskz_sub_epi64(__mmask8 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_psubq512_mask ((__v8di) __A,
- (__v8di) __B,
- (__v8di)
- _mm512_setzero_si512 (),
- (__mmask8) __U);
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
+ (__v8di)_mm512_sub_epi64(__A, __B),
+ (__v8di)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
@@ -787,22 +806,19 @@ _mm512_add_epi32 (__m512i __A, __m512i __B)
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_add_epi32 (__m512i __W, __mmask16 __U, __m512i __A, __m512i __B)
+_mm512_mask_add_epi32(__m512i __W, __mmask16 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_paddd512_mask ((__v16si) __A,
- (__v16si) __B,
- (__v16si) __W,
- (__mmask16) __U);
+ return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
+ (__v16si)_mm512_add_epi32(__A, __B),
+ (__v16si)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_maskz_add_epi32 (__mmask16 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_paddd512_mask ((__v16si) __A,
- (__v16si) __B,
- (__v16si)
- _mm512_setzero_si512 (),
- (__mmask16) __U);
+ return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
+ (__v16si)_mm512_add_epi32(__A, __B),
+ (__v16si)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
@@ -812,22 +828,19 @@ _mm512_sub_epi32 (__m512i __A, __m512i __B)
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_sub_epi32 (__m512i __W, __mmask16 __U, __m512i __A, __m512i __B)
+_mm512_mask_sub_epi32(__m512i __W, __mmask16 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_psubd512_mask ((__v16si) __A,
- (__v16si) __B,
- (__v16si) __W,
- (__mmask16) __U);
+ return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
+ (__v16si)_mm512_sub_epi32(__A, __B),
+ (__v16si)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_sub_epi32 (__mmask16 __U, __m512i __A, __m512i __B)
+_mm512_maskz_sub_epi32(__mmask16 __U, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_psubd512_mask ((__v16si) __A,
- (__v16si) __B,
- (__v16si)
- _mm512_setzero_si512 (),
- (__mmask16) __U);
+ return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
+ (__v16si)_mm512_sub_epi32(__A, __B),
+ (__v16si)_mm512_setzero_si512());
}
#define _mm512_mask_max_round_pd(W, U, A, B, R) __extension__ ({ \
@@ -1403,57 +1416,45 @@ _mm512_maskz_min_epu64 (__mmask8 __M, __m512i __A, __m512i __B)
static __inline __m512i __DEFAULT_FN_ATTRS
_mm512_mul_epi32(__m512i __X, __m512i __Y)
{
- return (__m512i) __builtin_ia32_pmuldq512_mask ((__v16si) __X,
- (__v16si) __Y,
- (__v8di)
- _mm512_setzero_si512 (),
- (__mmask8) -1);
+ return (__m512i)__builtin_ia32_pmuldq512((__v16si)__X, (__v16si) __Y);
}
static __inline __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_mul_epi32 (__m512i __W, __mmask8 __M, __m512i __X, __m512i __Y)
+_mm512_mask_mul_epi32(__m512i __W, __mmask8 __M, __m512i __X, __m512i __Y)
{
- return (__m512i) __builtin_ia32_pmuldq512_mask ((__v16si) __X,
- (__v16si) __Y,
- (__v8di) __W, __M);
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__M,
+ (__v8di)_mm512_mul_epi32(__X, __Y),
+ (__v8di)__W);
}
static __inline __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_mul_epi32 (__mmask8 __M, __m512i __X, __m512i __Y)
+_mm512_maskz_mul_epi32(__mmask8 __M, __m512i __X, __m512i __Y)
{
- return (__m512i) __builtin_ia32_pmuldq512_mask ((__v16si) __X,
- (__v16si) __Y,
- (__v8di)
- _mm512_setzero_si512 (),
- __M);
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__M,
+ (__v8di)_mm512_mul_epi32(__X, __Y),
+ (__v8di)_mm512_setzero_si512 ());
}
static __inline __m512i __DEFAULT_FN_ATTRS
_mm512_mul_epu32(__m512i __X, __m512i __Y)
{
- return (__m512i) __builtin_ia32_pmuludq512_mask ((__v16si) __X,
- (__v16si) __Y,
- (__v8di)
- _mm512_setzero_si512 (),
- (__mmask8) -1);
+ return (__m512i)__builtin_ia32_pmuludq512((__v16si)__X, (__v16si)__Y);
}
static __inline __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_mul_epu32 (__m512i __W, __mmask8 __M, __m512i __X, __m512i __Y)
+_mm512_mask_mul_epu32(__m512i __W, __mmask8 __M, __m512i __X, __m512i __Y)
{
- return (__m512i) __builtin_ia32_pmuludq512_mask ((__v16si) __X,
- (__v16si) __Y,
- (__v8di) __W, __M);
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__M,
+ (__v8di)_mm512_mul_epu32(__X, __Y),
+ (__v8di)__W);
}
static __inline __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_mul_epu32 (__mmask8 __M, __m512i __X, __m512i __Y)
+_mm512_maskz_mul_epu32(__mmask8 __M, __m512i __X, __m512i __Y)
{
- return (__m512i) __builtin_ia32_pmuludq512_mask ((__v16si) __X,
- (__v16si) __Y,
- (__v8di)
- _mm512_setzero_si512 (),
- __M);
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__M,
+ (__v8di)_mm512_mul_epu32(__X, __Y),
+ (__v8di)_mm512_setzero_si512 ());
}
static __inline __m512i __DEFAULT_FN_ATTRS
@@ -1463,21 +1464,19 @@ _mm512_mullo_epi32 (__m512i __A, __m512i __B)
}
static __inline __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_mullo_epi32 (__mmask16 __M, __m512i __A, __m512i __B)
+_mm512_maskz_mullo_epi32(__mmask16 __M, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pmulld512_mask ((__v16si) __A,
- (__v16si) __B,
- (__v16si)
- _mm512_setzero_si512 (),
- __M);
+ return (__m512i)__builtin_ia32_selectd_512((__mmask16)__M,
+ (__v16si)_mm512_mullo_epi32(__A, __B),
+ (__v16si)_mm512_setzero_si512());
}
static __inline __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_mullo_epi32 (__m512i __W, __mmask16 __M, __m512i __A, __m512i __B)
+_mm512_mask_mullo_epi32(__m512i __W, __mmask16 __M, __m512i __A, __m512i __B)
{
- return (__m512i) __builtin_ia32_pmulld512_mask ((__v16si) __A,
- (__v16si) __B,
- (__v16si) __W, __M);
+ return (__m512i)__builtin_ia32_selectd_512((__mmask16)__M,
+ (__v16si)_mm512_mullo_epi32(__A, __B),
+ (__v16si)__W);
}
#define _mm512_mask_sqrt_round_pd(W, U, A, R) __extension__ ({ \
@@ -1977,38 +1976,30 @@ _mm_maskz_add_sd(__mmask8 __U,__m128d __A, __m128d __B) {
static __inline__ __m512d __DEFAULT_FN_ATTRS
_mm512_mask_add_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) {
- return (__m512d) __builtin_ia32_addpd512_mask ((__v8df) __A,
- (__v8df) __B,
- (__v8df) __W,
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
+ (__v8df)_mm512_add_pd(__A, __B),
+ (__v8df)__W);
}
static __inline__ __m512d __DEFAULT_FN_ATTRS
_mm512_maskz_add_pd(__mmask8 __U, __m512d __A, __m512d __B) {
- return (__m512d) __builtin_ia32_addpd512_mask ((__v8df) __A,
- (__v8df) __B,
- (__v8df) _mm512_setzero_pd (),
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
+ (__v8df)_mm512_add_pd(__A, __B),
+ (__v8df)_mm512_setzero_pd());
}
static __inline__ __m512 __DEFAULT_FN_ATTRS
_mm512_mask_add_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) {
- return (__m512) __builtin_ia32_addps512_mask ((__v16sf) __A,
- (__v16sf) __B,
- (__v16sf) __W,
- (__mmask16) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512)__builtin_ia32_selectps_512((__mmask16)__U,
+ (__v16sf)_mm512_add_ps(__A, __B),
+ (__v16sf)__W);
}
static __inline__ __m512 __DEFAULT_FN_ATTRS
_mm512_maskz_add_ps(__mmask16 __U, __m512 __A, __m512 __B) {
- return (__m512) __builtin_ia32_addps512_mask ((__v16sf) __A,
- (__v16sf) __B,
- (__v16sf) _mm512_setzero_ps (),
- (__mmask16) __U,
- _MM_FROUND_CUR_DIRECTION);
+ 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__ ({ \
@@ -2120,40 +2111,30 @@ _mm_maskz_sub_sd(__mmask8 __U,__m128d __A, __m128d __B) {
static __inline__ __m512d __DEFAULT_FN_ATTRS
_mm512_mask_sub_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) {
- return (__m512d) __builtin_ia32_subpd512_mask ((__v8df) __A,
- (__v8df) __B,
- (__v8df) __W,
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
+ (__v8df)_mm512_sub_pd(__A, __B),
+ (__v8df)__W);
}
static __inline__ __m512d __DEFAULT_FN_ATTRS
_mm512_maskz_sub_pd(__mmask8 __U, __m512d __A, __m512d __B) {
- return (__m512d) __builtin_ia32_subpd512_mask ((__v8df) __A,
- (__v8df) __B,
- (__v8df)
- _mm512_setzero_pd (),
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
+ (__v8df)_mm512_sub_pd(__A, __B),
+ (__v8df)_mm512_setzero_pd());
}
static __inline__ __m512 __DEFAULT_FN_ATTRS
_mm512_mask_sub_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) {
- return (__m512) __builtin_ia32_subps512_mask ((__v16sf) __A,
- (__v16sf) __B,
- (__v16sf) __W,
- (__mmask16) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512)__builtin_ia32_selectps_512((__mmask16)__U,
+ (__v16sf)_mm512_sub_ps(__A, __B),
+ (__v16sf)__W);
}
static __inline__ __m512 __DEFAULT_FN_ATTRS
_mm512_maskz_sub_ps(__mmask16 __U, __m512 __A, __m512 __B) {
- return (__m512) __builtin_ia32_subps512_mask ((__v16sf) __A,
- (__v16sf) __B,
- (__v16sf)
- _mm512_setzero_ps (),
- (__mmask16) __U,
- _MM_FROUND_CUR_DIRECTION);
+ 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__ ({ \
@@ -2265,40 +2246,30 @@ _mm_maskz_mul_sd(__mmask8 __U,__m128d __A, __m128d __B) {
static __inline__ __m512d __DEFAULT_FN_ATTRS
_mm512_mask_mul_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) {
- return (__m512d) __builtin_ia32_mulpd512_mask ((__v8df) __A,
- (__v8df) __B,
- (__v8df) __W,
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
+ (__v8df)_mm512_mul_pd(__A, __B),
+ (__v8df)__W);
}
static __inline__ __m512d __DEFAULT_FN_ATTRS
_mm512_maskz_mul_pd(__mmask8 __U, __m512d __A, __m512d __B) {
- return (__m512d) __builtin_ia32_mulpd512_mask ((__v8df) __A,
- (__v8df) __B,
- (__v8df)
- _mm512_setzero_pd (),
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
+ (__v8df)_mm512_mul_pd(__A, __B),
+ (__v8df)_mm512_setzero_pd());
}
static __inline__ __m512 __DEFAULT_FN_ATTRS
_mm512_mask_mul_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) {
- return (__m512) __builtin_ia32_mulps512_mask ((__v16sf) __A,
- (__v16sf) __B,
- (__v16sf) __W,
- (__mmask16) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512)__builtin_ia32_selectps_512((__mmask16)__U,
+ (__v16sf)_mm512_mul_ps(__A, __B),
+ (__v16sf)__W);
}
static __inline__ __m512 __DEFAULT_FN_ATTRS
_mm512_maskz_mul_ps(__mmask16 __U, __m512 __A, __m512 __B) {
- return (__m512) __builtin_ia32_mulps512_mask ((__v16sf) __A,
- (__v16sf) __B,
- (__v16sf)
- _mm512_setzero_ps (),
- (__mmask16) __U,
- _MM_FROUND_CUR_DIRECTION);
+ 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__ ({ \
@@ -2417,21 +2388,16 @@ _mm512_div_pd(__m512d __a, __m512d __b)
static __inline__ __m512d __DEFAULT_FN_ATTRS
_mm512_mask_div_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) {
- return (__m512d) __builtin_ia32_divpd512_mask ((__v8df) __A,
- (__v8df) __B,
- (__v8df) __W,
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
+ (__v8df)_mm512_div_pd(__A, __B),
+ (__v8df)__W);
}
static __inline__ __m512d __DEFAULT_FN_ATTRS
_mm512_maskz_div_pd(__mmask8 __U, __m512d __A, __m512d __B) {
- return (__m512d) __builtin_ia32_divpd512_mask ((__v8df) __A,
- (__v8df) __B,
- (__v8df)
- _mm512_setzero_pd (),
- (__mmask8) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
+ (__v8df)_mm512_div_pd(__A, __B),
+ (__v8df)_mm512_setzero_pd());
}
static __inline __m512 __DEFAULT_FN_ATTRS
@@ -2442,21 +2408,16 @@ _mm512_div_ps(__m512 __a, __m512 __b)
static __inline__ __m512 __DEFAULT_FN_ATTRS
_mm512_mask_div_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) {
- return (__m512) __builtin_ia32_divps512_mask ((__v16sf) __A,
- (__v16sf) __B,
- (__v16sf) __W,
- (__mmask16) __U,
- _MM_FROUND_CUR_DIRECTION);
+ return (__m512)__builtin_ia32_selectps_512((__mmask16)__U,
+ (__v16sf)_mm512_div_ps(__A, __B),
+ (__v16sf)__W);
}
static __inline__ __m512 __DEFAULT_FN_ATTRS
_mm512_maskz_div_ps(__mmask16 __U, __m512 __A, __m512 __B) {
- return (__m512) __builtin_ia32_divps512_mask ((__v16sf) __A,
- (__v16sf) __B,
- (__v16sf)
- _mm512_setzero_ps (),
- (__mmask16) __U,
- _MM_FROUND_CUR_DIRECTION);
+ 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__ ({ \
@@ -3443,71 +3404,94 @@ _mm512_maskz_permutex2var_epi64 (__mmask8 __U, __m512i __A,
}
#define _mm512_alignr_epi64(A, B, I) __extension__ ({ \
- (__m512i)__builtin_ia32_alignq512_mask((__v8di)(__m512i)(A), \
- (__v8di)(__m512i)(B), (int)(I), \
- (__v8di)_mm512_setzero_si512(), \
- (__mmask8)-1); })
+ (__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_mask_alignr_epi64(W, U, A, B, imm) __extension__({\
- (__m512i)__builtin_ia32_alignq512_mask((__v8di)(__m512i)(A), \
- (__v8di)(__m512i)(B), (int)(imm), \
- (__v8di)(__m512i)(W), \
- (__mmask8)(U)); })
+ (__m512i)__builtin_ia32_selectq_512((__mmask8)(U), \
+ (__v8di)_mm512_alignr_epi64((A), (B), (imm)), \
+ (__v8di)(__m512i)(W)); })
#define _mm512_maskz_alignr_epi64(U, A, B, imm) __extension__({\
- (__m512i)__builtin_ia32_alignq512_mask((__v8di)(__m512i)(A), \
- (__v8di)(__m512i)(B), (int)(imm), \
- (__v8di)_mm512_setzero_si512(), \
- (__mmask8)(U)); })
+ (__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_ia32_alignd512_mask((__v16si)(__m512i)(A), \
- (__v16si)(__m512i)(B), (int)(I), \
- (__v16si)_mm512_setzero_si512(), \
- (__mmask16)-1); })
+ (__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__ ({\
- (__m512i)__builtin_ia32_alignd512_mask((__v16si)(__m512i)(A), \
- (__v16si)(__m512i)(B), (int)(imm), \
- (__v16si)(__m512i)(W), \
- (__mmask16)(U)); })
+ (__m512i)__builtin_ia32_selectd_512((__mmask16)(U), \
+ (__v16si)_mm512_alignr_epi32((A), (B), (imm)), \
+ (__v16si)(__m512i)(W)); })
#define _mm512_maskz_alignr_epi32(U, A, B, imm) __extension__({\
- (__m512i)__builtin_ia32_alignd512_mask((__v16si)(__m512i)(A), \
- (__v16si)(__m512i)(B), (int)(imm), \
- (__v16si)_mm512_setzero_si512(), \
- (__mmask16)(U)); })
+ (__m512i)__builtin_ia32_selectd_512((__mmask16)(U), \
+ (__v16si)_mm512_alignr_epi32((A), (B), (imm)), \
+ (__v16si)_mm512_setzero_si512()); })
/* Vector Extract */
-#define _mm512_extractf64x4_pd(A, I) __extension__ ({ \
- (__m256d)__builtin_ia32_extractf64x4_mask((__v8df)(__m512d)(A), (int)(I), \
- (__v4df)_mm256_setzero_si256(), \
- (__mmask8)-1); })
+#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_extractf64x4_mask((__v8df)(__m512d)(A), (int)(imm), \
- (__v4df)(__m256d)(W), \
- (__mmask8)(U)); })
+ (__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_extractf64x4_mask((__v8df)(__m512d)(A), (int)(imm), \
- (__v4df)_mm256_setzero_pd(), \
- (__mmask8)(U)); })
+ (__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_ia32_extractf32x4_mask((__v16sf)(__m512)(A), (int)(I), \
- (__v4sf)_mm_setzero_ps(), \
- (__mmask8)-1); })
+#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_extractf32x4_mask((__v16sf)(__m512)(A), (int)(imm), \
- (__v4sf)(__m128)(W), \
- (__mmask8)(U)); })
+ (__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_extractf32x4_mask((__v16sf)(__m512)(A), (int)(imm), \
- (__v4sf)_mm_setzero_ps(), \
- (__mmask8)(U)); })
+ (__m128)__builtin_ia32_selectps_128((__mmask8)(U), \
+ (__v4sf)_mm512_extractf32x4_ps((A), (imm)), \
+ (__v4sf)_mm_setzero_ps()); })
+
/* Vector Blend */
static __inline __m512d __DEFAULT_FN_ATTRS
@@ -3556,10 +3540,49 @@ _mm512_mask_blend_epi32(__mmask16 __U, __m512i __A, __m512i __W)
#define _mm512_cmp_ps_mask(A, B, P) \
_mm512_cmp_round_ps_mask((A), (B), (P), _MM_FROUND_CUR_DIRECTION)
-
#define _mm512_mask_cmp_ps_mask(U, A, B, P) \
_mm512_mask_cmp_round_ps_mask((U), (A), (B), (P), _MM_FROUND_CUR_DIRECTION)
+#define _mm512_cmpeq_ps_mask(A, B) \
+ _mm512_cmp_ps_mask((A), (B), _CMP_EQ_OQ)
+#define _mm512_mask_cmpeq_ps_mask(k, A, B) \
+ _mm512_mask_cmp_ps_mask((k), (A), (B), _CMP_EQ_OQ)
+
+#define _mm512_cmplt_ps_mask(A, B) \
+ _mm512_cmp_ps_mask((A), (B), _CMP_LT_OS)
+#define _mm512_mask_cmplt_ps_mask(k, A, B) \
+ _mm512_mask_cmp_ps_mask((k), (A), (B), _CMP_LT_OS)
+
+#define _mm512_cmple_ps_mask(A, B) \
+ _mm512_cmp_ps_mask((A), (B), _CMP_LE_OS)
+#define _mm512_mask_cmple_ps_mask(k, A, B) \
+ _mm512_mask_cmp_ps_mask((k), (A), (B), _CMP_LE_OS)
+
+#define _mm512_cmpunord_ps_mask(A, B) \
+ _mm512_cmp_ps_mask((A), (B), _CMP_UNORD_Q)
+#define _mm512_mask_cmpunord_ps_mask(k, A, B) \
+ _mm512_mask_cmp_ps_mask((k), (A), (B), _CMP_UNORD_Q)
+
+#define _mm512_cmpneq_ps_mask(A, B) \
+ _mm512_cmp_ps_mask((A), (B), _CMP_NEQ_UQ)
+#define _mm512_mask_cmpneq_ps_mask(k, A, B) \
+ _mm512_mask_cmp_ps_mask((k), (A), (B), _CMP_NEQ_UQ)
+
+#define _mm512_cmpnlt_ps_mask(A, B) \
+ _mm512_cmp_ps_mask((A), (B), _CMP_NLT_US)
+#define _mm512_mask_cmpnlt_ps_mask(k, A, B) \
+ _mm512_mask_cmp_ps_mask((k), (A), (B), _CMP_NLT_US)
+
+#define _mm512_cmpnle_ps_mask(A, B) \
+ _mm512_cmp_ps_mask((A), (B), _CMP_NLE_US)
+#define _mm512_mask_cmpnle_ps_mask(k, A, B) \
+ _mm512_mask_cmp_ps_mask((k), (A), (B), _CMP_NLE_US)
+
+#define _mm512_cmpord_ps_mask(A, B) \
+ _mm512_cmp_ps_mask((A), (B), _CMP_ORD_Q)
+#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__ ({ \
(__mmask8)__builtin_ia32_cmppd512_mask((__v8df)(__m512d)(A), \
(__v8df)(__m512d)(B), (int)(P), \
@@ -3572,10 +3595,49 @@ _mm512_mask_blend_epi32(__mmask16 __U, __m512i __A, __m512i __W)
#define _mm512_cmp_pd_mask(A, B, P) \
_mm512_cmp_round_pd_mask((A), (B), (P), _MM_FROUND_CUR_DIRECTION)
-
#define _mm512_mask_cmp_pd_mask(U, A, B, P) \
_mm512_mask_cmp_round_pd_mask((U), (A), (B), (P), _MM_FROUND_CUR_DIRECTION)
+#define _mm512_cmpeq_pd_mask(A, B) \
+ _mm512_cmp_pd_mask((A), (B), _CMP_EQ_OQ)
+#define _mm512_mask_cmpeq_pd_mask(k, A, B) \
+ _mm512_mask_cmp_pd_mask((k), (A), (B), _CMP_EQ_OQ)
+
+#define _mm512_cmplt_pd_mask(A, B) \
+ _mm512_cmp_pd_mask((A), (B), _CMP_LT_OS)
+#define _mm512_mask_cmplt_pd_mask(k, A, B) \
+ _mm512_mask_cmp_pd_mask((k), (A), (B), _CMP_LT_OS)
+
+#define _mm512_cmple_pd_mask(A, B) \
+ _mm512_cmp_pd_mask((A), (B), _CMP_LE_OS)
+#define _mm512_mask_cmple_pd_mask(k, A, B) \
+ _mm512_mask_cmp_pd_mask((k), (A), (B), _CMP_LE_OS)
+
+#define _mm512_cmpunord_pd_mask(A, B) \
+ _mm512_cmp_pd_mask((A), (B), _CMP_UNORD_Q)
+#define _mm512_mask_cmpunord_pd_mask(k, A, B) \
+ _mm512_mask_cmp_pd_mask((k), (A), (B), _CMP_UNORD_Q)
+
+#define _mm512_cmpneq_pd_mask(A, B) \
+ _mm512_cmp_pd_mask((A), (B), _CMP_NEQ_UQ)
+#define _mm512_mask_cmpneq_pd_mask(k, A, B) \
+ _mm512_mask_cmp_pd_mask((k), (A), (B), _CMP_NEQ_UQ)
+
+#define _mm512_cmpnlt_pd_mask(A, B) \
+ _mm512_cmp_pd_mask((A), (B), _CMP_NLT_US)
+#define _mm512_mask_cmpnlt_pd_mask(k, A, B) \
+ _mm512_mask_cmp_pd_mask((k), (A), (B), _CMP_NLT_US)
+
+#define _mm512_cmpnle_pd_mask(A, B) \
+ _mm512_cmp_pd_mask((A), (B), _CMP_NLE_US)
+#define _mm512_mask_cmpnle_pd_mask(k, A, B) \
+ _mm512_mask_cmp_pd_mask((k), (A), (B), _CMP_NLE_US)
+
+#define _mm512_cmpord_pd_mask(A, B) \
+ _mm512_cmp_pd_mask((A), (B), _CMP_ORD_Q)
+#define _mm512_mask_cmpord_pd_mask(k, A, B) \
+ _mm512_mask_cmp_pd_mask((k), (A), (B), _CMP_ORD_Q)
+
/* Conversion */
#define _mm512_cvtt_roundps_epu32(A, R) __extension__ ({ \
@@ -3682,26 +3744,35 @@ _mm512_maskz_cvtepu32_ps (__mmask16 __U, __m512i __A)
static __inline __m512d __DEFAULT_FN_ATTRS
_mm512_cvtepi32_pd(__m256i __A)
{
- return (__m512d) __builtin_ia32_cvtdq2pd512_mask ((__v8si) __A,
- (__v8df)
- _mm512_setzero_pd (),
- (__mmask8) -1);
+ return (__m512d)__builtin_convertvector((__v8si)__A, __v8df);
}
static __inline__ __m512d __DEFAULT_FN_ATTRS
_mm512_mask_cvtepi32_pd (__m512d __W, __mmask8 __U, __m256i __A)
{
- return (__m512d) __builtin_ia32_cvtdq2pd512_mask ((__v8si) __A,
- (__v8df) __W,
- (__mmask8) __U);
+ return (__m512d)__builtin_ia32_selectpd_512((__mmask8) __U,
+ (__v8df)_mm512_cvtepi32_pd(__A),
+ (__v8df)__W);
}
static __inline__ __m512d __DEFAULT_FN_ATTRS
_mm512_maskz_cvtepi32_pd (__mmask8 __U, __m256i __A)
{
- return (__m512d) __builtin_ia32_cvtdq2pd512_mask ((__v8si) __A,
- (__v8df) _mm512_setzero_pd (),
- (__mmask8) __U);
+ return (__m512d)__builtin_ia32_selectpd_512((__mmask8) __U,
+ (__v8df)_mm512_cvtepi32_pd(__A),
+ (__v8df)_mm512_setzero_pd());
+}
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_cvtepi32lo_pd(__m512i __A)
+{
+ return (__m512d) _mm512_cvtepi32_pd(_mm512_castsi512_si256(__A));
+}
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_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
@@ -3734,26 +3805,35 @@ _mm512_maskz_cvtepi32_ps (__mmask16 __U, __m512i __A)
static __inline __m512d __DEFAULT_FN_ATTRS
_mm512_cvtepu32_pd(__m256i __A)
{
- return (__m512d) __builtin_ia32_cvtudq2pd512_mask ((__v8si) __A,
- (__v8df)
- _mm512_setzero_pd (),
- (__mmask8) -1);
+ return (__m512d)__builtin_convertvector((__v8su)__A, __v8df);
}
static __inline__ __m512d __DEFAULT_FN_ATTRS
_mm512_mask_cvtepu32_pd (__m512d __W, __mmask8 __U, __m256i __A)
{
- return (__m512d) __builtin_ia32_cvtudq2pd512_mask ((__v8si) __A,
- (__v8df) __W,
- (__mmask8) __U);
+ return (__m512d)__builtin_ia32_selectpd_512((__mmask8) __U,
+ (__v8df)_mm512_cvtepu32_pd(__A),
+ (__v8df)__W);
}
static __inline__ __m512d __DEFAULT_FN_ATTRS
_mm512_maskz_cvtepu32_pd (__mmask8 __U, __m256i __A)
{
- return (__m512d) __builtin_ia32_cvtudq2pd512_mask ((__v8si) __A,
- (__v8df) _mm512_setzero_pd (),
- (__mmask8) __U);
+ return (__m512d)__builtin_ia32_selectpd_512((__mmask8) __U,
+ (__v8df)_mm512_cvtepu32_pd(__A),
+ (__v8df)_mm512_setzero_pd());
+}
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_mm512_cvtepu32lo_pd(__m512i __A)
+{
+ return (__m512d) _mm512_cvtepu32_pd(_mm512_castsi512_si256(__A));
+}
+
+static __inline__ __m512d __DEFAULT_FN_ATTRS
+_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__ ({ \
@@ -3798,6 +3878,24 @@ _mm512_maskz_cvtpd_ps (__mmask8 __U, __m512d __A)
_MM_FROUND_CUR_DIRECTION);
}
+static __inline__ __m512 __DEFAULT_FN_ATTRS
+_mm512_cvtpd_pslo (__m512d __A)
+{
+ return (__m512) __builtin_shufflevector((__v8sf) _mm512_cvtpd_ps(__A),
+ (__v8sf) _mm256_setzero_ps (),
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
+}
+
+static __inline__ __m512 __DEFAULT_FN_ATTRS
+_mm512_mask_cvtpd_pslo (__m512 __W, __mmask8 __U,__m512d __A)
+{
+ return (__m512) __builtin_shufflevector (
+ (__v8sf) _mm512_mask_cvtpd_ps (_mm512_castps512_ps256(__W),
+ __U, __A),
+ (__v8sf) _mm256_setzero_ps (),
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
+}
+
#define _mm512_cvt_roundps_ph(A, I) __extension__ ({ \
(__m256i)__builtin_ia32_vcvtps2ph512_mask((__v16sf)(__m512)(A), (int)(I), \
(__v16hi)_mm256_undefined_si256(), \
@@ -4919,263 +5017,227 @@ _mm512_mask_cmpneq_epu64_mask(__mmask8 __u, __m512i __a, __m512i __b) {
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_cvtepi8_epi32 (__m128i __A)
+_mm512_cvtepi8_epi32(__m128i __A)
{
- return (__m512i) __builtin_ia32_pmovsxbd512_mask ((__v16qi) __A,
- (__v16si)
- _mm512_setzero_si512 (),
- (__mmask16) -1);
+ /* This function always performs a signed extension, but __v16qi is a char
+ which may be signed or unsigned, so use __v16qs. */
+ return (__m512i)__builtin_convertvector((__v16qs)__A, __v16si);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_cvtepi8_epi32 (__m512i __W, __mmask16 __U, __m128i __A)
+_mm512_mask_cvtepi8_epi32(__m512i __W, __mmask16 __U, __m128i __A)
{
- return (__m512i) __builtin_ia32_pmovsxbd512_mask ((__v16qi) __A,
- (__v16si) __W,
- (__mmask16) __U);
+ return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
+ (__v16si)_mm512_cvtepi8_epi32(__A),
+ (__v16si)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_cvtepi8_epi32 (__mmask16 __U, __m128i __A)
+_mm512_maskz_cvtepi8_epi32(__mmask16 __U, __m128i __A)
{
- return (__m512i) __builtin_ia32_pmovsxbd512_mask ((__v16qi) __A,
- (__v16si)
- _mm512_setzero_si512 (),
- (__mmask16) __U);
+ return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
+ (__v16si)_mm512_cvtepi8_epi32(__A),
+ (__v16si)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_cvtepi8_epi64 (__m128i __A)
+_mm512_cvtepi8_epi64(__m128i __A)
{
- return (__m512i) __builtin_ia32_pmovsxbq512_mask ((__v16qi) __A,
- (__v8di)
- _mm512_setzero_si512 (),
- (__mmask8) -1);
+ /* This function always performs a signed extension, but __v16qi is a char
+ which may be signed or unsigned, so use __v16qs. */
+ 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
-_mm512_mask_cvtepi8_epi64 (__m512i __W, __mmask8 __U, __m128i __A)
+_mm512_mask_cvtepi8_epi64(__m512i __W, __mmask8 __U, __m128i __A)
{
- return (__m512i) __builtin_ia32_pmovsxbq512_mask ((__v16qi) __A,
- (__v8di) __W,
- (__mmask8) __U);
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
+ (__v8di)_mm512_cvtepi8_epi64(__A),
+ (__v8di)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_cvtepi8_epi64 (__mmask8 __U, __m128i __A)
+_mm512_maskz_cvtepi8_epi64(__mmask8 __U, __m128i __A)
{
- return (__m512i) __builtin_ia32_pmovsxbq512_mask ((__v16qi) __A,
- (__v8di)
- _mm512_setzero_si512 (),
- (__mmask8) __U);
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
+ (__v8di)_mm512_cvtepi8_epi64(__A),
+ (__v8di)_mm512_setzero_si512 ());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_cvtepi32_epi64 (__m256i __X)
+_mm512_cvtepi32_epi64(__m256i __X)
{
- return (__m512i) __builtin_ia32_pmovsxdq512_mask ((__v8si) __X,
- (__v8di)
- _mm512_setzero_si512 (),
- (__mmask8) -1);
+ return (__m512i)__builtin_convertvector((__v8si)__X, __v8di);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_cvtepi32_epi64 (__m512i __W, __mmask8 __U, __m256i __X)
+_mm512_mask_cvtepi32_epi64(__m512i __W, __mmask8 __U, __m256i __X)
{
- return (__m512i) __builtin_ia32_pmovsxdq512_mask ((__v8si) __X,
- (__v8di) __W,
- (__mmask8) __U);
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
+ (__v8di)_mm512_cvtepi32_epi64(__X),
+ (__v8di)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_cvtepi32_epi64 (__mmask8 __U, __m256i __X)
+_mm512_maskz_cvtepi32_epi64(__mmask8 __U, __m256i __X)
{
- return (__m512i) __builtin_ia32_pmovsxdq512_mask ((__v8si) __X,
- (__v8di)
- _mm512_setzero_si512 (),
- (__mmask8) __U);
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
+ (__v8di)_mm512_cvtepi32_epi64(__X),
+ (__v8di)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_cvtepi16_epi32 (__m256i __A)
+_mm512_cvtepi16_epi32(__m256i __A)
{
- return (__m512i) __builtin_ia32_pmovsxwd512_mask ((__v16hi) __A,
- (__v16si)
- _mm512_setzero_si512 (),
- (__mmask16) -1);
+ return (__m512i)__builtin_convertvector((__v16hi)__A, __v16si);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_cvtepi16_epi32 (__m512i __W, __mmask16 __U, __m256i __A)
+_mm512_mask_cvtepi16_epi32(__m512i __W, __mmask16 __U, __m256i __A)
{
- return (__m512i) __builtin_ia32_pmovsxwd512_mask ((__v16hi) __A,
- (__v16si) __W,
- (__mmask16) __U);
+ return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
+ (__v16si)_mm512_cvtepi16_epi32(__A),
+ (__v16si)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_cvtepi16_epi32 (__mmask16 __U, __m256i __A)
+_mm512_maskz_cvtepi16_epi32(__mmask16 __U, __m256i __A)
{
- return (__m512i) __builtin_ia32_pmovsxwd512_mask ((__v16hi) __A,
- (__v16si)
- _mm512_setzero_si512 (),
- (__mmask16) __U);
+ return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
+ (__v16si)_mm512_cvtepi16_epi32(__A),
+ (__v16si)_mm512_setzero_si512 ());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_cvtepi16_epi64 (__m128i __A)
+_mm512_cvtepi16_epi64(__m128i __A)
{
- return (__m512i) __builtin_ia32_pmovsxwq512_mask ((__v8hi) __A,
- (__v8di)
- _mm512_setzero_si512 (),
- (__mmask8) -1);
+ return (__m512i)__builtin_convertvector((__v8hi)__A, __v8di);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_cvtepi16_epi64 (__m512i __W, __mmask8 __U, __m128i __A)
+_mm512_mask_cvtepi16_epi64(__m512i __W, __mmask8 __U, __m128i __A)
{
- return (__m512i) __builtin_ia32_pmovsxwq512_mask ((__v8hi) __A,
- (__v8di) __W,
- (__mmask8) __U);
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
+ (__v8di)_mm512_cvtepi16_epi64(__A),
+ (__v8di)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_cvtepi16_epi64 (__mmask8 __U, __m128i __A)
+_mm512_maskz_cvtepi16_epi64(__mmask8 __U, __m128i __A)
{
- return (__m512i) __builtin_ia32_pmovsxwq512_mask ((__v8hi) __A,
- (__v8di)
- _mm512_setzero_si512 (),
- (__mmask8) __U);
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
+ (__v8di)_mm512_cvtepi16_epi64(__A),
+ (__v8di)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_cvtepu8_epi32 (__m128i __A)
+_mm512_cvtepu8_epi32(__m128i __A)
{
- return (__m512i) __builtin_ia32_pmovzxbd512_mask ((__v16qi) __A,
- (__v16si)
- _mm512_setzero_si512 (),
- (__mmask16) -1);
+ return (__m512i)__builtin_convertvector((__v16qu)__A, __v16si);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_cvtepu8_epi32 (__m512i __W, __mmask16 __U, __m128i __A)
+_mm512_mask_cvtepu8_epi32(__m512i __W, __mmask16 __U, __m128i __A)
{
- return (__m512i) __builtin_ia32_pmovzxbd512_mask ((__v16qi) __A,
- (__v16si) __W,
- (__mmask16) __U);
+ return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
+ (__v16si)_mm512_cvtepu8_epi32(__A),
+ (__v16si)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_cvtepu8_epi32 (__mmask16 __U, __m128i __A)
+_mm512_maskz_cvtepu8_epi32(__mmask16 __U, __m128i __A)
{
- return (__m512i) __builtin_ia32_pmovzxbd512_mask ((__v16qi) __A,
- (__v16si)
- _mm512_setzero_si512 (),
- (__mmask16) __U);
+ return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
+ (__v16si)_mm512_cvtepu8_epi32(__A),
+ (__v16si)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_cvtepu8_epi64 (__m128i __A)
+_mm512_cvtepu8_epi64(__m128i __A)
{
- return (__m512i) __builtin_ia32_pmovzxbq512_mask ((__v16qi) __A,
- (__v8di)
- _mm512_setzero_si512 (),
- (__mmask8) -1);
+ 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
-_mm512_mask_cvtepu8_epi64 (__m512i __W, __mmask8 __U, __m128i __A)
+_mm512_mask_cvtepu8_epi64(__m512i __W, __mmask8 __U, __m128i __A)
{
- return (__m512i) __builtin_ia32_pmovzxbq512_mask ((__v16qi) __A,
- (__v8di) __W,
- (__mmask8) __U);
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
+ (__v8di)_mm512_cvtepu8_epi64(__A),
+ (__v8di)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_cvtepu8_epi64 (__mmask8 __U, __m128i __A)
+_mm512_maskz_cvtepu8_epi64(__mmask8 __U, __m128i __A)
{
- return (__m512i) __builtin_ia32_pmovzxbq512_mask ((__v16qi) __A,
- (__v8di)
- _mm512_setzero_si512 (),
- (__mmask8) __U);
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
+ (__v8di)_mm512_cvtepu8_epi64(__A),
+ (__v8di)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_cvtepu32_epi64 (__m256i __X)
+_mm512_cvtepu32_epi64(__m256i __X)
{
- return (__m512i) __builtin_ia32_pmovzxdq512_mask ((__v8si) __X,
- (__v8di)
- _mm512_setzero_si512 (),
- (__mmask8) -1);
+ return (__m512i)__builtin_convertvector((__v8su)__X, __v8di);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_cvtepu32_epi64 (__m512i __W, __mmask8 __U, __m256i __X)
+_mm512_mask_cvtepu32_epi64(__m512i __W, __mmask8 __U, __m256i __X)
{
- return (__m512i) __builtin_ia32_pmovzxdq512_mask ((__v8si) __X,
- (__v8di) __W,
- (__mmask8) __U);
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
+ (__v8di)_mm512_cvtepu32_epi64(__X),
+ (__v8di)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_cvtepu32_epi64 (__mmask8 __U, __m256i __X)
+_mm512_maskz_cvtepu32_epi64(__mmask8 __U, __m256i __X)
{
- return (__m512i) __builtin_ia32_pmovzxdq512_mask ((__v8si) __X,
- (__v8di)
- _mm512_setzero_si512 (),
- (__mmask8) __U);
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
+ (__v8di)_mm512_cvtepu32_epi64(__X),
+ (__v8di)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_cvtepu16_epi32 (__m256i __A)
+_mm512_cvtepu16_epi32(__m256i __A)
{
- return (__m512i) __builtin_ia32_pmovzxwd512_mask ((__v16hi) __A,
- (__v16si)
- _mm512_setzero_si512 (),
- (__mmask16) -1);
+ return (__m512i)__builtin_convertvector((__v16hu)__A, __v16si);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_cvtepu16_epi32 (__m512i __W, __mmask16 __U, __m256i __A)
+_mm512_mask_cvtepu16_epi32(__m512i __W, __mmask16 __U, __m256i __A)
{
- return (__m512i) __builtin_ia32_pmovzxwd512_mask ((__v16hi) __A,
- (__v16si) __W,
- (__mmask16) __U);
+ return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
+ (__v16si)_mm512_cvtepu16_epi32(__A),
+ (__v16si)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_cvtepu16_epi32 (__mmask16 __U, __m256i __A)
+_mm512_maskz_cvtepu16_epi32(__mmask16 __U, __m256i __A)
{
- return (__m512i) __builtin_ia32_pmovzxwd512_mask ((__v16hi) __A,
- (__v16si)
- _mm512_setzero_si512 (),
- (__mmask16) __U);
+ return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
+ (__v16si)_mm512_cvtepu16_epi32(__A),
+ (__v16si)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_cvtepu16_epi64 (__m128i __A)
+_mm512_cvtepu16_epi64(__m128i __A)
{
- return (__m512i) __builtin_ia32_pmovzxwq512_mask ((__v8hi) __A,
- (__v8di)
- _mm512_setzero_si512 (),
- (__mmask8) -1);
+ return (__m512i)__builtin_convertvector((__v8hu)__A, __v8di);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_cvtepu16_epi64 (__m512i __W, __mmask8 __U, __m128i __A)
+_mm512_mask_cvtepu16_epi64(__m512i __W, __mmask8 __U, __m128i __A)
{
- return (__m512i) __builtin_ia32_pmovzxwq512_mask ((__v8hi) __A,
- (__v8di) __W,
- (__mmask8) __U);
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
+ (__v8di)_mm512_cvtepu16_epi64(__A),
+ (__v8di)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_cvtepu16_epi64 (__mmask8 __U, __m128i __A)
+_mm512_maskz_cvtepu16_epi64(__mmask8 __U, __m128i __A)
{
- return (__m512i) __builtin_ia32_pmovzxwq512_mask ((__v8hi) __A,
- (__v8di)
- _mm512_setzero_si512 (),
- (__mmask8) __U);
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
+ (__v8di)_mm512_cvtepu16_epi64(__A),
+ (__v8di)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
@@ -5393,67 +5455,91 @@ _mm512_maskz_rolv_epi64 (__mmask8 __U, __m512i __A, __m512i __B)
(__v8di)_mm512_setzero_si512(), \
(__mmask8)(U)); })
-#define _mm512_slli_epi32(A, B) __extension__ ({ \
- (__m512i)__builtin_ia32_pslldi512_mask((__v16si)(__m512i)(A), (int)(B), \
- (__v16si)_mm512_setzero_si512(), \
- (__mmask16)-1); })
-
-#define _mm512_mask_slli_epi32(W, U, A, B) __extension__ ({ \
- (__m512i)__builtin_ia32_pslldi512_mask((__v16si)(__m512i)(A), (int)(B), \
- (__v16si)(__m512i)(W), \
- (__mmask16)(U)); })
-
-#define _mm512_maskz_slli_epi32(U, A, B) __extension__ ({ \
- (__m512i)__builtin_ia32_pslldi512_mask((__v16si)(__m512i)(A), (int)(B), \
- (__v16si)_mm512_setzero_si512(), \
- (__mmask16)(U)); })
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_slli_epi32(__m512i __A, int __B)
+{
+ return (__m512i)__builtin_ia32_pslldi512((__v16si)__A, __B);
+}
-#define _mm512_slli_epi64(A, B) __extension__ ({ \
- (__m512i)__builtin_ia32_psllqi512_mask((__v8di)(__m512i)(A), (int)(B), \
- (__v8di)_mm512_setzero_si512(), \
- (__mmask8)-1); })
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_slli_epi32(__m512i __W, __mmask16 __U, __m512i __A, int __B)
+{
+ return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
+ (__v16si)_mm512_slli_epi32(__A, __B),
+ (__v16si)__W);
+}
-#define _mm512_mask_slli_epi64(W, U, A, B) __extension__ ({ \
- (__m512i)__builtin_ia32_psllqi512_mask((__v8di)(__m512i)(A), (int)(B), \
- (__v8di)(__m512i)(W), \
- (__mmask8)(U)); })
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_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());
+}
-#define _mm512_maskz_slli_epi64(U, A, B) __extension__ ({ \
- (__m512i)__builtin_ia32_psllqi512_mask((__v8di)(__m512i)(A), (int)(B), \
- (__v8di)_mm512_setzero_si512(), \
- (__mmask8)(U)); })
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_slli_epi64(__m512i __A, int __B)
+{
+ return (__m512i)__builtin_ia32_psllqi512((__v8di)__A, __B);
+}
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_slli_epi64(__m512i __W, __mmask8 __U, __m512i __A, int __B)
+{
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
+ (__v8di)_mm512_slli_epi64(__A, __B),
+ (__v8di)__W);
+}
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_slli_epi64(__mmask8 __U, __m512i __A, int __B)
+{
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
+ (__v8di)_mm512_slli_epi64(__A, __B),
+ (__v8di)_mm512_setzero_si512());
+}
-#define _mm512_srli_epi32(A, B) __extension__ ({ \
- (__m512i)__builtin_ia32_psrldi512_mask((__v16si)(__m512i)(A), (int)(B), \
- (__v16si)_mm512_setzero_si512(), \
- (__mmask16)-1); })
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_srli_epi32(__m512i __A, int __B)
+{
+ return (__m512i)__builtin_ia32_psrldi512((__v16si)__A, __B);
+}
-#define _mm512_mask_srli_epi32(W, U, A, B) __extension__ ({ \
- (__m512i)__builtin_ia32_psrldi512_mask((__v16si)(__m512i)(A), (int)(B), \
- (__v16si)(__m512i)(W), \
- (__mmask16)(U)); })
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_srli_epi32(__m512i __W, __mmask16 __U, __m512i __A, int __B)
+{
+ return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
+ (__v16si)_mm512_srli_epi32(__A, __B),
+ (__v16si)__W);
+}
-#define _mm512_maskz_srli_epi32(U, A, B) __extension__ ({ \
- (__m512i)__builtin_ia32_psrldi512_mask((__v16si)(__m512i)(A), (int)(B), \
- (__v16si)_mm512_setzero_si512(), \
- (__mmask16)(U)); })
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_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());
+}
-#define _mm512_srli_epi64(A, B) __extension__ ({ \
- (__m512i)__builtin_ia32_psrlqi512_mask((__v8di)(__m512i)(A), (int)(B), \
- (__v8di)_mm512_setzero_si512(), \
- (__mmask8)-1); })
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_srli_epi64(__m512i __A, int __B)
+{
+ return (__m512i)__builtin_ia32_psrlqi512((__v8di)__A, __B);
+}
-#define _mm512_mask_srli_epi64(W, U, A, B) __extension__ ({ \
- (__m512i)__builtin_ia32_psrlqi512_mask((__v8di)(__m512i)(A), (int)(B), \
- (__v8di)(__m512i)(W), \
- (__mmask8)(U)); })
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_mask_srli_epi64(__m512i __W, __mmask8 __U, __m512i __A, int __B)
+{
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
+ (__v8di)_mm512_srli_epi64(__A, __B),
+ (__v8di)__W);
+}
-#define _mm512_maskz_srli_epi64(U, A, B) __extension__ ({ \
- (__m512i)__builtin_ia32_psrlqi512_mask((__v8di)(__m512i)(A), (int)(B), \
- (__v8di)_mm512_setzero_si512(), \
- (__mmask8)(U)); })
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_srli_epi64(__mmask8 __U, __m512i __A, int __B)
+{
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
+ (__v8di)_mm512_srli_epi64(__A, __B),
+ (__v8di)_mm512_setzero_si512());
+}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_mask_load_epi32 (__m512i __W, __mmask16 __U, void const *__P)
@@ -5911,8 +5997,10 @@ _mm512_kmov (__mmask16 __A)
(int)__builtin_ia32_vcomiss((__v4sf)(__m128)(A), (__v4sf)(__m128)(B), \
(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)); })
+#endif
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_mask2_permutex2var_epi32 (__m512i __A, __m512i __I,
@@ -5926,351 +6014,267 @@ _mm512_mask2_permutex2var_epi32 (__m512i __A, __m512i __I,
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_sll_epi32 (__m512i __A, __m128i __B)
+_mm512_sll_epi32(__m512i __A, __m128i __B)
{
- return (__m512i) __builtin_ia32_pslld512_mask ((__v16si) __A,
- (__v4si) __B,
- (__v16si)
- _mm512_setzero_si512 (),
- (__mmask16) -1);
+ return (__m512i)__builtin_ia32_pslld512((__v16si) __A, (__v4si)__B);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_sll_epi32 (__m512i __W, __mmask16 __U, __m512i __A, __m128i __B)
+_mm512_mask_sll_epi32(__m512i __W, __mmask16 __U, __m512i __A, __m128i __B)
{
- return (__m512i) __builtin_ia32_pslld512_mask ((__v16si) __A,
- (__v4si) __B,
- (__v16si) __W,
- (__mmask16) __U);
+ return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
+ (__v16si)_mm512_sll_epi32(__A, __B),
+ (__v16si)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_sll_epi32 (__mmask16 __U, __m512i __A, __m128i __B)
+_mm512_maskz_sll_epi32(__mmask16 __U, __m512i __A, __m128i __B)
{
- return (__m512i) __builtin_ia32_pslld512_mask ((__v16si) __A,
- (__v4si) __B,
- (__v16si)
- _mm512_setzero_si512 (),
- (__mmask16) __U);
+ return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
+ (__v16si)_mm512_sll_epi32(__A, __B),
+ (__v16si)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_sll_epi64 (__m512i __A, __m128i __B)
+_mm512_sll_epi64(__m512i __A, __m128i __B)
{
- return (__m512i) __builtin_ia32_psllq512_mask ((__v8di) __A,
- (__v2di) __B,
- (__v8di)
- _mm512_setzero_si512 (),
- (__mmask8) -1);
+ return (__m512i)__builtin_ia32_psllq512((__v8di)__A, (__v2di)__B);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_sll_epi64 (__m512i __W, __mmask8 __U, __m512i __A, __m128i __B)
+_mm512_mask_sll_epi64(__m512i __W, __mmask8 __U, __m512i __A, __m128i __B)
{
- return (__m512i) __builtin_ia32_psllq512_mask ((__v8di) __A,
- (__v2di) __B,
- (__v8di) __W,
- (__mmask8) __U);
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
+ (__v8di)_mm512_sll_epi64(__A, __B),
+ (__v8di)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_sll_epi64 (__mmask8 __U, __m512i __A, __m128i __B)
+_mm512_maskz_sll_epi64(__mmask8 __U, __m512i __A, __m128i __B)
{
- return (__m512i) __builtin_ia32_psllq512_mask ((__v8di) __A,
- (__v2di) __B,
- (__v8di)
- _mm512_setzero_si512 (),
- (__mmask8) __U);
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
+ (__v8di)_mm512_sll_epi64(__A, __B),
+ (__v8di)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_sllv_epi32 (__m512i __X, __m512i __Y)
+_mm512_sllv_epi32(__m512i __X, __m512i __Y)
{
- return (__m512i) __builtin_ia32_psllv16si_mask ((__v16si) __X,
- (__v16si) __Y,
- (__v16si)
- _mm512_setzero_si512 (),
- (__mmask16) -1);
+ return (__m512i)__builtin_ia32_psllv16si((__v16si)__X, (__v16si)__Y);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_sllv_epi32 (__m512i __W, __mmask16 __U, __m512i __X, __m512i __Y)
+_mm512_mask_sllv_epi32(__m512i __W, __mmask16 __U, __m512i __X, __m512i __Y)
{
- return (__m512i) __builtin_ia32_psllv16si_mask ((__v16si) __X,
- (__v16si) __Y,
- (__v16si) __W,
- (__mmask16) __U);
+ return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
+ (__v16si)_mm512_sllv_epi32(__X, __Y),
+ (__v16si)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_sllv_epi32 (__mmask16 __U, __m512i __X, __m512i __Y)
+_mm512_maskz_sllv_epi32(__mmask16 __U, __m512i __X, __m512i __Y)
{
- return (__m512i) __builtin_ia32_psllv16si_mask ((__v16si) __X,
- (__v16si) __Y,
- (__v16si)
- _mm512_setzero_si512 (),
- (__mmask16) __U);
+ return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
+ (__v16si)_mm512_sllv_epi32(__X, __Y),
+ (__v16si)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_sllv_epi64 (__m512i __X, __m512i __Y)
+_mm512_sllv_epi64(__m512i __X, __m512i __Y)
{
- return (__m512i) __builtin_ia32_psllv8di_mask ((__v8di) __X,
- (__v8di) __Y,
- (__v8di)
- _mm512_undefined_pd (),
- (__mmask8) -1);
+ return (__m512i)__builtin_ia32_psllv8di((__v8di)__X, (__v8di)__Y);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_sllv_epi64 (__m512i __W, __mmask8 __U, __m512i __X, __m512i __Y)
+_mm512_mask_sllv_epi64(__m512i __W, __mmask8 __U, __m512i __X, __m512i __Y)
{
- return (__m512i) __builtin_ia32_psllv8di_mask ((__v8di) __X,
- (__v8di) __Y,
- (__v8di) __W,
- (__mmask8) __U);
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
+ (__v8di)_mm512_sllv_epi64(__X, __Y),
+ (__v8di)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_sllv_epi64 (__mmask8 __U, __m512i __X, __m512i __Y)
+_mm512_maskz_sllv_epi64(__mmask8 __U, __m512i __X, __m512i __Y)
{
- return (__m512i) __builtin_ia32_psllv8di_mask ((__v8di) __X,
- (__v8di) __Y,
- (__v8di)
- _mm512_setzero_si512 (),
- (__mmask8) __U);
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
+ (__v8di)_mm512_sllv_epi64(__X, __Y),
+ (__v8di)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_sra_epi32 (__m512i __A, __m128i __B)
+_mm512_sra_epi32(__m512i __A, __m128i __B)
{
- return (__m512i) __builtin_ia32_psrad512_mask ((__v16si) __A,
- (__v4si) __B,
- (__v16si)
- _mm512_setzero_si512 (),
- (__mmask16) -1);
+ return (__m512i)__builtin_ia32_psrad512((__v16si) __A, (__v4si)__B);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_sra_epi32 (__m512i __W, __mmask16 __U, __m512i __A, __m128i __B)
+_mm512_mask_sra_epi32(__m512i __W, __mmask16 __U, __m512i __A, __m128i __B)
{
- return (__m512i) __builtin_ia32_psrad512_mask ((__v16si) __A,
- (__v4si) __B,
- (__v16si) __W,
- (__mmask16) __U);
+ return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
+ (__v16si)_mm512_sra_epi32(__A, __B),
+ (__v16si)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_sra_epi32 (__mmask16 __U, __m512i __A, __m128i __B)
+_mm512_maskz_sra_epi32(__mmask16 __U, __m512i __A, __m128i __B)
{
- return (__m512i) __builtin_ia32_psrad512_mask ((__v16si) __A,
- (__v4si) __B,
- (__v16si)
- _mm512_setzero_si512 (),
- (__mmask16) __U);
+ return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
+ (__v16si)_mm512_sra_epi32(__A, __B),
+ (__v16si)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_sra_epi64 (__m512i __A, __m128i __B)
+_mm512_sra_epi64(__m512i __A, __m128i __B)
{
- return (__m512i) __builtin_ia32_psraq512_mask ((__v8di) __A,
- (__v2di) __B,
- (__v8di)
- _mm512_setzero_si512 (),
- (__mmask8) -1);
+ return (__m512i)__builtin_ia32_psraq512((__v8di)__A, (__v2di)__B);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_sra_epi64 (__m512i __W, __mmask8 __U, __m512i __A, __m128i __B)
+_mm512_mask_sra_epi64(__m512i __W, __mmask8 __U, __m512i __A, __m128i __B)
{
- return (__m512i) __builtin_ia32_psraq512_mask ((__v8di) __A,
- (__v2di) __B,
- (__v8di) __W,
- (__mmask8) __U);
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
+ (__v8di)_mm512_sra_epi64(__A, __B),
+ (__v8di)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_sra_epi64 (__mmask8 __U, __m512i __A, __m128i __B)
+_mm512_maskz_sra_epi64(__mmask8 __U, __m512i __A, __m128i __B)
{
- return (__m512i) __builtin_ia32_psraq512_mask ((__v8di) __A,
- (__v2di) __B,
- (__v8di)
- _mm512_setzero_si512 (),
- (__mmask8) __U);
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
+ (__v8di)_mm512_sra_epi64(__A, __B),
+ (__v8di)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_srav_epi32 (__m512i __X, __m512i __Y)
+_mm512_srav_epi32(__m512i __X, __m512i __Y)
{
- return (__m512i) __builtin_ia32_psrav16si_mask ((__v16si) __X,
- (__v16si) __Y,
- (__v16si)
- _mm512_setzero_si512 (),
- (__mmask16) -1);
+ return (__m512i)__builtin_ia32_psrav16si((__v16si)__X, (__v16si)__Y);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_srav_epi32 (__m512i __W, __mmask16 __U, __m512i __X, __m512i __Y)
+_mm512_mask_srav_epi32(__m512i __W, __mmask16 __U, __m512i __X, __m512i __Y)
{
- return (__m512i) __builtin_ia32_psrav16si_mask ((__v16si) __X,
- (__v16si) __Y,
- (__v16si) __W,
- (__mmask16) __U);
+ return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
+ (__v16si)_mm512_srav_epi32(__X, __Y),
+ (__v16si)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_srav_epi32 (__mmask16 __U, __m512i __X, __m512i __Y)
+_mm512_maskz_srav_epi32(__mmask16 __U, __m512i __X, __m512i __Y)
{
- return (__m512i) __builtin_ia32_psrav16si_mask ((__v16si) __X,
- (__v16si) __Y,
- (__v16si)
- _mm512_setzero_si512 (),
- (__mmask16) __U);
+ return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
+ (__v16si)_mm512_srav_epi32(__X, __Y),
+ (__v16si)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_srav_epi64 (__m512i __X, __m512i __Y)
+_mm512_srav_epi64(__m512i __X, __m512i __Y)
{
- return (__m512i) __builtin_ia32_psrav8di_mask ((__v8di) __X,
- (__v8di) __Y,
- (__v8di)
- _mm512_setzero_si512 (),
- (__mmask8) -1);
+ return (__m512i)__builtin_ia32_psrav8di((__v8di)__X, (__v8di)__Y);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_srav_epi64 (__m512i __W, __mmask8 __U, __m512i __X, __m512i __Y)
+_mm512_mask_srav_epi64(__m512i __W, __mmask8 __U, __m512i __X, __m512i __Y)
{
- return (__m512i) __builtin_ia32_psrav8di_mask ((__v8di) __X,
- (__v8di) __Y,
- (__v8di) __W,
- (__mmask8) __U);
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
+ (__v8di)_mm512_srav_epi64(__X, __Y),
+ (__v8di)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_srav_epi64 (__mmask8 __U, __m512i __X, __m512i __Y)
+_mm512_maskz_srav_epi64(__mmask8 __U, __m512i __X, __m512i __Y)
{
- return (__m512i) __builtin_ia32_psrav8di_mask ((__v8di) __X,
- (__v8di) __Y,
- (__v8di)
- _mm512_setzero_si512 (),
- (__mmask8) __U);
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
+ (__v8di)_mm512_srav_epi64(__X, __Y),
+ (__v8di)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_srl_epi32 (__m512i __A, __m128i __B)
+_mm512_srl_epi32(__m512i __A, __m128i __B)
{
- return (__m512i) __builtin_ia32_psrld512_mask ((__v16si) __A,
- (__v4si) __B,
- (__v16si)
- _mm512_setzero_si512 (),
- (__mmask16) -1);
+ return (__m512i)__builtin_ia32_psrld512((__v16si) __A, (__v4si)__B);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_srl_epi32 (__m512i __W, __mmask16 __U, __m512i __A, __m128i __B)
+_mm512_mask_srl_epi32(__m512i __W, __mmask16 __U, __m512i __A, __m128i __B)
{
- return (__m512i) __builtin_ia32_psrld512_mask ((__v16si) __A,
- (__v4si) __B,
- (__v16si) __W,
- (__mmask16) __U);
+ return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
+ (__v16si)_mm512_srl_epi32(__A, __B),
+ (__v16si)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_srl_epi32 (__mmask16 __U, __m512i __A, __m128i __B)
+_mm512_maskz_srl_epi32(__mmask16 __U, __m512i __A, __m128i __B)
{
- return (__m512i) __builtin_ia32_psrld512_mask ((__v16si) __A,
- (__v4si) __B,
- (__v16si)
- _mm512_setzero_si512 (),
- (__mmask16) __U);
+ return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
+ (__v16si)_mm512_srl_epi32(__A, __B),
+ (__v16si)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_srl_epi64 (__m512i __A, __m128i __B)
+_mm512_srl_epi64(__m512i __A, __m128i __B)
{
- return (__m512i) __builtin_ia32_psrlq512_mask ((__v8di) __A,
- (__v2di) __B,
- (__v8di)
- _mm512_setzero_si512 (),
- (__mmask8) -1);
+ return (__m512i)__builtin_ia32_psrlq512((__v8di)__A, (__v2di)__B);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_srl_epi64 (__m512i __W, __mmask8 __U, __m512i __A, __m128i __B)
+_mm512_mask_srl_epi64(__m512i __W, __mmask8 __U, __m512i __A, __m128i __B)
{
- return (__m512i) __builtin_ia32_psrlq512_mask ((__v8di) __A,
- (__v2di) __B,
- (__v8di) __W,
- (__mmask8) __U);
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
+ (__v8di)_mm512_srl_epi64(__A, __B),
+ (__v8di)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_srl_epi64 (__mmask8 __U, __m512i __A, __m128i __B)
+_mm512_maskz_srl_epi64(__mmask8 __U, __m512i __A, __m128i __B)
{
- return (__m512i) __builtin_ia32_psrlq512_mask ((__v8di) __A,
- (__v2di) __B,
- (__v8di)
- _mm512_setzero_si512 (),
- (__mmask8) __U);
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
+ (__v8di)_mm512_srl_epi64(__A, __B),
+ (__v8di)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_srlv_epi32 (__m512i __X, __m512i __Y)
+_mm512_srlv_epi32(__m512i __X, __m512i __Y)
{
- return (__m512i) __builtin_ia32_psrlv16si_mask ((__v16si) __X,
- (__v16si) __Y,
- (__v16si)
- _mm512_setzero_si512 (),
- (__mmask16) -1);
+ return (__m512i)__builtin_ia32_psrlv16si((__v16si)__X, (__v16si)__Y);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_srlv_epi32 (__m512i __W, __mmask16 __U, __m512i __X, __m512i __Y)
+_mm512_mask_srlv_epi32(__m512i __W, __mmask16 __U, __m512i __X, __m512i __Y)
{
- return (__m512i) __builtin_ia32_psrlv16si_mask ((__v16si) __X,
- (__v16si) __Y,
- (__v16si) __W,
- (__mmask16) __U);
+ return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
+ (__v16si)_mm512_srlv_epi32(__X, __Y),
+ (__v16si)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_srlv_epi32 (__mmask16 __U, __m512i __X, __m512i __Y)
+_mm512_maskz_srlv_epi32(__mmask16 __U, __m512i __X, __m512i __Y)
{
- return (__m512i) __builtin_ia32_psrlv16si_mask ((__v16si) __X,
- (__v16si) __Y,
- (__v16si)
- _mm512_setzero_si512 (),
- (__mmask16) __U);
+ return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U,
+ (__v16si)_mm512_srlv_epi32(__X, __Y),
+ (__v16si)_mm512_setzero_si512());
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_srlv_epi64 (__m512i __X, __m512i __Y)
{
- return (__m512i) __builtin_ia32_psrlv8di_mask ((__v8di) __X,
- (__v8di) __Y,
- (__v8di)
- _mm512_setzero_si512 (),
- (__mmask8) -1);
+ return (__m512i)__builtin_ia32_psrlv8di((__v8di)__X, (__v8di)__Y);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_mask_srlv_epi64 (__m512i __W, __mmask8 __U, __m512i __X, __m512i __Y)
+_mm512_mask_srlv_epi64(__m512i __W, __mmask8 __U, __m512i __X, __m512i __Y)
{
- return (__m512i) __builtin_ia32_psrlv8di_mask ((__v8di) __X,
- (__v8di) __Y,
- (__v8di) __W,
- (__mmask8) __U);
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
+ (__v8di)_mm512_srlv_epi64(__X, __Y),
+ (__v8di)__W);
}
static __inline__ __m512i __DEFAULT_FN_ATTRS
-_mm512_maskz_srlv_epi64 (__mmask8 __U, __m512i __X, __m512i __Y)
+_mm512_maskz_srlv_epi64(__mmask8 __U, __m512i __X, __m512i __Y)
{
- return (__m512i) __builtin_ia32_psrlv8di_mask ((__v8di) __X,
- (__v8di) __Y,
- (__v8di)
- _mm512_setzero_si512 (),
- (__mmask8) __U);
+ return (__m512i)__builtin_ia32_selectq_512((__mmask8)__U,
+ (__v8di)_mm512_srlv_epi64(__X, __Y),
+ (__v8di)_mm512_setzero_si512());
}
#define _mm512_ternarylogic_epi32(A, B, C, imm) __extension__ ({ \
@@ -6309,8 +6313,10 @@ _mm512_maskz_srlv_epi64 (__mmask8 __U, __m512i __X, __m512i __Y)
(__v8di)(__m512i)(C), (int)(imm), \
(__mmask8)(U)); })
+#ifdef __x86_64__
#define _mm_cvt_roundsd_i64(A, R) __extension__ ({ \
(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)); })
@@ -6328,6 +6334,7 @@ _mm_cvtsd_u32 (__m128d __A)
_MM_FROUND_CUR_DIRECTION);
}
+#ifdef __x86_64__
#define _mm_cvt_roundsd_u64(A, R) __extension__ ({ \
(unsigned long long)__builtin_ia32_vcvtsd2usi64((__v2df)(__m128d)(A), \
(int)(R)); })
@@ -6339,6 +6346,7 @@ _mm_cvtsd_u64 (__m128d __A)
__A,
_MM_FROUND_CUR_DIRECTION);
}
+#endif
#define _mm_cvt_roundss_si32(A, R) __extension__ ({ \
(int)__builtin_ia32_vcvtss2si32((__v4sf)(__m128)(A), (int)(R)); })
@@ -6346,11 +6354,13 @@ _mm_cvtsd_u64 (__m128d __A)
#define _mm_cvt_roundss_i32(A, R) __extension__ ({ \
(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_i64(A, R) __extension__ ({ \
(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)); })
@@ -6362,6 +6372,7 @@ _mm_cvtss_u32 (__m128 __A)
_MM_FROUND_CUR_DIRECTION);
}
+#ifdef __x86_64__
#define _mm_cvt_roundss_u64(A, R) __extension__ ({ \
(unsigned long long)__builtin_ia32_vcvtss2usi64((__v4sf)(__m128)(A), \
(int)(R)); })
@@ -6373,6 +6384,7 @@ _mm_cvtss_u64 (__m128 __A)
__A,
_MM_FROUND_CUR_DIRECTION);
}
+#endif
#define _mm_cvtt_roundsd_i32(A, R) __extension__ ({ \
(int)__builtin_ia32_vcvttsd2si32((__v2df)(__m128d)(A), (int)(R)); })
@@ -6387,6 +6399,7 @@ _mm_cvttsd_i32 (__m128d __A)
_MM_FROUND_CUR_DIRECTION);
}
+#ifdef __x86_64__
#define _mm_cvtt_roundsd_si64(A, R) __extension__ ({ \
(long long)__builtin_ia32_vcvttsd2si64((__v2df)(__m128d)(A), (int)(R)); })
@@ -6399,6 +6412,7 @@ _mm_cvttsd_i64 (__m128d __A)
return (long long) __builtin_ia32_vcvttsd2si64 ((__v2df) __A,
_MM_FROUND_CUR_DIRECTION);
}
+#endif
#define _mm_cvtt_roundsd_u32(A, R) __extension__ ({ \
(unsigned int)__builtin_ia32_vcvttsd2usi32((__v2df)(__m128d)(A), (int)(R)); })
@@ -6410,6 +6424,7 @@ _mm_cvttsd_u32 (__m128d __A)
_MM_FROUND_CUR_DIRECTION);
}
+#ifdef __x86_64__
#define _mm_cvtt_roundsd_u64(A, R) __extension__ ({ \
(unsigned long long)__builtin_ia32_vcvttsd2usi64((__v2df)(__m128d)(A), \
(int)(R)); })
@@ -6421,6 +6436,7 @@ _mm_cvttsd_u64 (__m128d __A)
__A,
_MM_FROUND_CUR_DIRECTION);
}
+#endif
#define _mm_cvtt_roundss_i32(A, R) __extension__ ({ \
(int)__builtin_ia32_vcvttss2si32((__v4sf)(__m128)(A), (int)(R)); })
@@ -6435,6 +6451,7 @@ _mm_cvttss_i32 (__m128 __A)
_MM_FROUND_CUR_DIRECTION);
}
+#ifdef __x86_64__
#define _mm_cvtt_roundss_i64(A, R) __extension__ ({ \
(long long)__builtin_ia32_vcvttss2si64((__v4sf)(__m128)(A), (int)(R)); })
@@ -6447,6 +6464,7 @@ _mm_cvttss_i64 (__m128 __A)
return (long long) __builtin_ia32_vcvttss2si64 ((__v4sf) __A,
_MM_FROUND_CUR_DIRECTION);
}
+#endif
#define _mm_cvtt_roundss_u32(A, R) __extension__ ({ \
(unsigned int)__builtin_ia32_vcvttss2usi32((__v4sf)(__m128)(A), (int)(R)); })
@@ -6458,6 +6476,7 @@ _mm_cvttss_u32 (__m128 __A)
_MM_FROUND_CUR_DIRECTION);
}
+#ifdef __x86_64__
#define _mm_cvtt_roundss_u64(A, R) __extension__ ({ \
(unsigned long long)__builtin_ia32_vcvttss2usi64((__v4sf)(__m128)(A), \
(int)(R)); })
@@ -6469,6 +6488,7 @@ _mm_cvttss_u64 (__m128 __A)
__A,
_MM_FROUND_CUR_DIRECTION);
}
+#endif
static __inline__ __m512d __DEFAULT_FN_ATTRS
_mm512_mask2_permutex2var_pd (__m512d __A, __m512i __I, __mmask8 __U,
@@ -6556,61 +6576,47 @@ _mm512_mask2_permutex2var_epi64 (__m512i __A, __m512i __I,
(__v16sf)_mm512_setzero_ps()); })
static __inline__ __m512d __DEFAULT_FN_ATTRS
-_mm512_permutevar_pd (__m512d __A, __m512i __C)
+_mm512_permutevar_pd(__m512d __A, __m512i __C)
{
- return (__m512d) __builtin_ia32_vpermilvarpd512_mask ((__v8df) __A,
- (__v8di) __C,
- (__v8df)
- _mm512_undefined_pd (),
- (__mmask8) -1);
+ return (__m512d)__builtin_ia32_vpermilvarpd512((__v8df)__A, (__v8di)__C);
}
static __inline__ __m512d __DEFAULT_FN_ATTRS
-_mm512_mask_permutevar_pd (__m512d __W, __mmask8 __U, __m512d __A, __m512i __C)
+_mm512_mask_permutevar_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512i __C)
{
- return (__m512d) __builtin_ia32_vpermilvarpd512_mask ((__v8df) __A,
- (__v8di) __C,
- (__v8df) __W,
- (__mmask8) __U);
+ return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
+ (__v8df)_mm512_permutevar_pd(__A, __C),
+ (__v8df)__W);
}
static __inline__ __m512d __DEFAULT_FN_ATTRS
-_mm512_maskz_permutevar_pd (__mmask8 __U, __m512d __A, __m512i __C)
+_mm512_maskz_permutevar_pd(__mmask8 __U, __m512d __A, __m512i __C)
{
- return (__m512d) __builtin_ia32_vpermilvarpd512_mask ((__v8df) __A,
- (__v8di) __C,
- (__v8df)
- _mm512_setzero_pd (),
- (__mmask8) __U);
+ return (__m512d)__builtin_ia32_selectpd_512((__mmask8)__U,
+ (__v8df)_mm512_permutevar_pd(__A, __C),
+ (__v8df)_mm512_setzero_pd());
}
static __inline__ __m512 __DEFAULT_FN_ATTRS
-_mm512_permutevar_ps (__m512 __A, __m512i __C)
+_mm512_permutevar_ps(__m512 __A, __m512i __C)
{
- return (__m512) __builtin_ia32_vpermilvarps512_mask ((__v16sf) __A,
- (__v16si) __C,
- (__v16sf)
- _mm512_undefined_ps (),
- (__mmask16) -1);
+ return (__m512)__builtin_ia32_vpermilvarps512((__v16sf)__A, (__v16si)__C);
}
static __inline__ __m512 __DEFAULT_FN_ATTRS
-_mm512_mask_permutevar_ps (__m512 __W, __mmask16 __U, __m512 __A, __m512i __C)
+_mm512_mask_permutevar_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512i __C)
{
- return (__m512) __builtin_ia32_vpermilvarps512_mask ((__v16sf) __A,
- (__v16si) __C,
- (__v16sf) __W,
- (__mmask16) __U);
+ return (__m512)__builtin_ia32_selectps_512((__mmask16)__U,
+ (__v16sf)_mm512_permutevar_ps(__A, __C),
+ (__v16sf)__W);
}
static __inline__ __m512 __DEFAULT_FN_ATTRS
-_mm512_maskz_permutevar_ps (__mmask16 __U, __m512 __A, __m512i __C)
+_mm512_maskz_permutevar_ps(__mmask16 __U, __m512 __A, __m512i __C)
{
- return (__m512) __builtin_ia32_vpermilvarps512_mask ((__v16sf) __A,
- (__v16si) __C,
- (__v16sf)
- _mm512_setzero_ps (),
- (__mmask16) __U);
+ return (__m512)__builtin_ia32_selectps_512((__mmask16)__U,
+ (__v16sf)_mm512_permutevar_ps(__A, __C),
+ (__v16sf)_mm512_setzero_ps());
}
static __inline __m512d __DEFAULT_FN_ATTRS
@@ -7028,35 +7034,48 @@ _mm_maskz_scalef_ss (__mmask8 __U, __m128 __A, __m128 __B)
(__mmask8)(U), \
_MM_FROUND_CUR_DIRECTION); })
-#define _mm512_srai_epi32(A, B) __extension__ ({ \
- (__m512i)__builtin_ia32_psradi512_mask((__v16si)(__m512i)(A), (int)(B), \
- (__v16si)_mm512_setzero_si512(), \
- (__mmask16)-1); })
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_srai_epi32(__m512i __A, int __B)
+{
+ return (__m512i)__builtin_ia32_psradi512((__v16si)__A, __B);
+}
-#define _mm512_mask_srai_epi32(W, U, A, B) __extension__ ({ \
- (__m512i)__builtin_ia32_psradi512_mask((__v16si)(__m512i)(A), (int)(B), \
- (__v16si)(__m512i)(W), \
- (__mmask16)(U)); })
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_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), \
+ (__v16si)__W);
+}
-#define _mm512_maskz_srai_epi32(U, A, B) __extension__ ({ \
- (__m512i)__builtin_ia32_psradi512_mask((__v16si)(__m512i)(A), (int)(B), \
- (__v16si)_mm512_setzero_si512(), \
- (__mmask16)(U)); })
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_srai_epi32(__mmask16 __U, __m512i __A, int __B) {
+ return (__m512i)__builtin_ia32_selectd_512((__mmask16)__U, \
+ (__v16si)_mm512_srai_epi32(__A, __B), \
+ (__v16si)_mm512_setzero_si512());
+}
-#define _mm512_srai_epi64(A, B) __extension__ ({ \
- (__m512i)__builtin_ia32_psraqi512_mask((__v8di)(__m512i)(A), (int)(B), \
- (__v8di)_mm512_setzero_si512(), \
- (__mmask8)-1); })
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_srai_epi64(__m512i __A, int __B)
+{
+ return (__m512i)__builtin_ia32_psraqi512((__v8di)__A, __B);
+}
-#define _mm512_mask_srai_epi64(W, U, A, B) __extension__ ({ \
- (__m512i)__builtin_ia32_psraqi512_mask((__v8di)(__m512i)(A), (int)(B), \
- (__v8di)(__m512i)(W), \
- (__mmask8)(U)); })
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_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), \
+ (__v8di)__W);
+}
-#define _mm512_maskz_srai_epi64(U, A, B) __extension__ ({ \
- (__m512i)__builtin_ia32_psraqi512_mask((__v8di)(__m512i)(A), (int)(B), \
- (__v8di)_mm512_setzero_si512(), \
- (__mmask8)(U)); })
+static __inline__ __m512i __DEFAULT_FN_ATTRS
+_mm512_maskz_srai_epi64(__mmask8 __U, __m512i __A, int __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_ia32_shuf_f32x4_mask((__v16sf)(__m512)(A), \
@@ -7832,107 +7851,145 @@ _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_ia32_extracti32x4_mask((__v16si)(__m512i)(A), (int)(imm), \
- (__v4si)_mm_undefined_si128(), \
- (__mmask8)-1); })
+#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_extracti32x4_mask((__v16si)(__m512i)(A), (int)(imm), \
- (__v4si)(__m128i)(W), \
- (__mmask8)(U)); })
+ (__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_extracti32x4_mask((__v16si)(__m512i)(A), (int)(imm), \
- (__v4si)_mm_setzero_si128(), \
- (__mmask8)(U)); })
+ (__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_ia32_extracti64x4_mask((__v8di)(__m512i)(A), (int)(imm), \
- (__v4di)_mm256_undefined_si256(), \
- (__mmask8)-1); })
+#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_extracti64x4_mask((__v8di)(__m512i)(A), (int)(imm), \
- (__v4di)(__m256i)(W), \
- (__mmask8)(U)); })
+ (__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_extracti64x4_mask((__v8di)(__m512i)(A), (int)(imm), \
- (__v4di)_mm256_setzero_si256(), \
- (__mmask8)(U)); })
+ (__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_ia32_insertf64x4_mask((__v8df)(__m512d)(A), \
- (__v4df)(__m256d)(B), (int)(imm), \
- (__v8df)_mm512_undefined_pd(), \
- (__mmask8)-1); })
+ (__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__ ({ \
- (__m512d)__builtin_ia32_insertf64x4_mask((__v8df)(__m512d)(A), \
- (__v4df)(__m256d)(B), (int)(imm), \
- (__v8df)(__m512d)(W), \
- (__mmask8)(U)); })
+ (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \
+ (__v8df)_mm512_insertf64x4((A), (B), (imm)), \
+ (__v8df)(W)); })
#define _mm512_maskz_insertf64x4(U, A, B, imm) __extension__ ({ \
- (__m512d)__builtin_ia32_insertf64x4_mask((__v8df)(__m512d)(A), \
- (__v4df)(__m256d)(B), (int)(imm), \
- (__v8df)_mm512_setzero_pd(), \
- (__mmask8)(U)); })
+ (__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_ia32_inserti64x4_mask((__v8di)(__m512i)(A), \
- (__v4di)(__m256i)(B), (int)(imm), \
- (__v8di)_mm512_setzero_si512(), \
- (__mmask8)-1); })
+ (__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__ ({ \
- (__m512i)__builtin_ia32_inserti64x4_mask((__v8di)(__m512i)(A), \
- (__v4di)(__m256i)(B), (int)(imm), \
- (__v8di)(__m512i)(W), \
- (__mmask8)(U)); })
+ (__m512i)__builtin_ia32_selectq_512((__mmask8)(U), \
+ (__v8di)_mm512_inserti64x4((A), (B), (imm)), \
+ (__v8di)(W)); })
#define _mm512_maskz_inserti64x4(U, A, B, imm) __extension__ ({ \
- (__m512i)__builtin_ia32_inserti64x4_mask((__v8di)(__m512i)(A), \
- (__v4di)(__m256i)(B), (int)(imm), \
- (__v8di)_mm512_setzero_si512(), \
- (__mmask8)(U)); })
+ (__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_ia32_insertf32x4_mask((__v16sf)(__m512)(A), \
- (__v4sf)(__m128)(B), (int)(imm), \
- (__v16sf)_mm512_undefined_ps(), \
- (__mmask16)-1); })
+ (__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__ ({ \
- (__m512)__builtin_ia32_insertf32x4_mask((__v16sf)(__m512)(A), \
- (__v4sf)(__m128)(B), (int)(imm), \
- (__v16sf)(__m512)(W), \
- (__mmask16)(U)); })
+ (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \
+ (__v16sf)_mm512_insertf32x4((A), (B), (imm)), \
+ (__v16sf)(W)); })
#define _mm512_maskz_insertf32x4(U, A, B, imm) __extension__ ({ \
- (__m512)__builtin_ia32_insertf32x4_mask((__v16sf)(__m512)(A), \
- (__v4sf)(__m128)(B), (int)(imm), \
- (__v16sf)_mm512_setzero_ps(), \
- (__mmask16)(U)); })
+ (__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_ia32_inserti32x4_mask((__v16si)(__m512i)(A), \
- (__v4si)(__m128i)(B), (int)(imm), \
- (__v16si)_mm512_setzero_si512(), \
- (__mmask16)-1); })
+ (__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__ ({ \
- (__m512i)__builtin_ia32_inserti32x4_mask((__v16si)(__m512i)(A), \
- (__v4si)(__m128i)(B), (int)(imm), \
- (__v16si)(__m512i)(W), \
- (__mmask16)(U)); })
+ (__m512i)__builtin_ia32_selectd_512((__mmask16)(U), \
+ (__v16si)_mm512_inserti32x4((A), (B), (imm)), \
+ (__v16si)(W)); })
#define _mm512_maskz_inserti32x4(U, A, B, imm) __extension__ ({ \
- (__m512i)__builtin_ia32_inserti32x4_mask((__v16si)(__m512i)(A), \
- (__v4si)(__m128i)(B), (int)(imm), \
- (__v16si)_mm512_setzero_si512(), \
- (__mmask16)(U)); })
+ (__m512i)__builtin_ia32_selectd_512((__mmask16)(U), \
+ (__v16si)_mm512_inserti32x4((A), (B), (imm)), \
+ (__v16si)_mm512_setzero_si512()); })
#define _mm512_getmant_round_pd(A, B, C, R) __extension__ ({ \
(__m512d)__builtin_ia32_getmantpd512_mask((__v8df)(__m512d)(A), \
@@ -8275,17 +8332,17 @@ __builtin_ia32_gatherdiv16sf ((__v8sf) __v1_old,\
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_mask_fmadd_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B)
{
- return (__m128) __builtin_ia32_vfmaddss3_mask ((__v4sf) __A,
+ return (__m128) __builtin_ia32_vfmaddss3_mask ((__v4sf) __W,
+ (__v4sf) __A,
(__v4sf) __B,
- (__v4sf) __W,
(__mmask8) __U,
_MM_FROUND_CUR_DIRECTION);
}
#define _mm_mask_fmadd_round_ss(W, U, A, B, R) __extension__({\
- (__m128)__builtin_ia32_vfmaddss3_mask((__v4sf)(__m128)(A), \
- (__v4sf)(__m128)(B), \
- (__v4sf)(__m128)(W), (__mmask8)(U), \
+ (__m128)__builtin_ia32_vfmaddss3_mask((__v4sf)(__m128)(W), \
+ (__v4sf)(__m128)(A), \
+ (__v4sf)(__m128)(B), (__mmask8)(U), \
(int)(R)); })
static __inline__ __m128 __DEFAULT_FN_ATTRS
@@ -8323,17 +8380,17 @@ _mm_mask3_fmadd_ss (__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U)
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_mask_fmsub_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B)
{
- return (__m128) __builtin_ia32_vfmaddss3_mask ((__v4sf) __A,
+ return (__m128) __builtin_ia32_vfmaddss3_mask ((__v4sf) __W,
+ (__v4sf) __A,
-(__v4sf) __B,
- (__v4sf) __W,
(__mmask8) __U,
_MM_FROUND_CUR_DIRECTION);
}
#define _mm_mask_fmsub_round_ss(W, U, A, B, R) __extension__ ({\
- (__m128)__builtin_ia32_vfmaddss3_mask((__v4sf)(__m128)(A), \
- -(__v4sf)(__m128)(B), \
- (__v4sf)(__m128)(W), (__mmask8)(U), \
+ (__m128)__builtin_ia32_vfmaddss3_mask((__v4sf)(__m128)(W), \
+ (__v4sf)(__m128)(A), \
+ (__v4sf)(__m128)(B), (__mmask8)(U), \
(int)(R)); })
static __inline__ __m128 __DEFAULT_FN_ATTRS
@@ -8355,33 +8412,33 @@ _mm_maskz_fmsub_ss (__mmask8 __U, __m128 __A, __m128 __B, __m128 __C)
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_mask3_fmsub_ss (__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U)
{
- return (__m128) __builtin_ia32_vfmaddss3_mask3 ((__v4sf) __W,
+ return (__m128) __builtin_ia32_vfmsubss3_mask3 ((__v4sf) __W,
(__v4sf) __X,
- -(__v4sf) __Y,
+ (__v4sf) __Y,
(__mmask8) __U,
_MM_FROUND_CUR_DIRECTION);
}
#define _mm_mask3_fmsub_round_ss(W, X, Y, U, R) __extension__ ({\
- (__m128)__builtin_ia32_vfmaddss3_mask3((__v4sf)(__m128)(W), \
+ (__m128)__builtin_ia32_vfmsubss3_mask3((__v4sf)(__m128)(W), \
(__v4sf)(__m128)(X), \
- -(__v4sf)(__m128)(Y), (__mmask8)(U), \
+ (__v4sf)(__m128)(Y), (__mmask8)(U), \
(int)(R)); })
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_mask_fnmadd_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B)
{
- return (__m128) __builtin_ia32_vfmaddss3_mask (-(__v4sf) __A,
+ return (__m128) __builtin_ia32_vfmaddss3_mask ((__v4sf) __W,
+ -(__v4sf) __A,
(__v4sf) __B,
- (__v4sf) __W,
(__mmask8) __U,
_MM_FROUND_CUR_DIRECTION);
}
#define _mm_mask_fnmadd_round_ss(W, U, A, B, R) __extension__ ({\
- (__m128)__builtin_ia32_vfmaddss3_mask(-(__v4sf)(__m128)(A), \
- (__v4sf)(__m128)(B), \
- (__v4sf)(__m128)(W), (__mmask8)(U), \
+ (__m128)__builtin_ia32_vfmaddss3_mask((__v4sf)(__m128)(W), \
+ -(__v4sf)(__m128)(A), \
+ (__v4sf)(__m128)(B), (__mmask8)(U), \
(int)(R)); })
static __inline__ __m128 __DEFAULT_FN_ATTRS
@@ -8419,17 +8476,17 @@ _mm_mask3_fnmadd_ss (__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U)
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_mask_fnmsub_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B)
{
- return (__m128) __builtin_ia32_vfmaddss3_mask (-(__v4sf) __A,
+ return (__m128) __builtin_ia32_vfmaddss3_mask ((__v4sf) __W,
+ -(__v4sf) __A,
-(__v4sf) __B,
- (__v4sf) __W,
(__mmask8) __U,
_MM_FROUND_CUR_DIRECTION);
}
#define _mm_mask_fnmsub_round_ss(W, U, A, B, R) __extension__ ({\
- (__m128)__builtin_ia32_vfmaddss3_mask(-(__v4sf)(__m128)(A), \
- -(__v4sf)(__m128)(B), \
- (__v4sf)(__m128)(W), (__mmask8)(U), \
+ (__m128)__builtin_ia32_vfmaddss3_mask((__v4sf)(__m128)(W), \
+ -(__v4sf)(__m128)(A), \
+ -(__v4sf)(__m128)(B), (__mmask8)(U), \
(int)(R)); })
static __inline__ __m128 __DEFAULT_FN_ATTRS
@@ -8451,33 +8508,33 @@ _mm_maskz_fnmsub_ss (__mmask8 __U, __m128 __A, __m128 __B, __m128 __C)
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_mask3_fnmsub_ss (__m128 __W, __m128 __X, __m128 __Y, __mmask8 __U)
{
- return (__m128) __builtin_ia32_vfmaddss3_mask3 (-(__v4sf) __W,
+ return (__m128) __builtin_ia32_vfnmsubss3_mask3 ((__v4sf) __W,
(__v4sf) __X,
- -(__v4sf) __Y,
+ (__v4sf) __Y,
(__mmask8) __U,
_MM_FROUND_CUR_DIRECTION);
}
#define _mm_mask3_fnmsub_round_ss(W, X, Y, U, R) __extension__({\
- (__m128)__builtin_ia32_vfmaddss3_mask3(-(__v4sf)(__m128)(W), \
+ (__m128)__builtin_ia32_vfnmsubss3_mask3((__v4sf)(__m128)(W), \
(__v4sf)(__m128)(X), \
- -(__v4sf)(__m128)(Y), (__mmask8)(U), \
+ (__v4sf)(__m128)(Y), (__mmask8)(U), \
(int)(R)); })
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_mask_fmadd_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B)
{
- return (__m128d) __builtin_ia32_vfmaddsd3_mask ( (__v2df) __A,
+ return (__m128d) __builtin_ia32_vfmaddsd3_mask ( (__v2df) __W,
+ (__v2df) __A,
(__v2df) __B,
- (__v2df) __W,
(__mmask8) __U,
_MM_FROUND_CUR_DIRECTION);
}
#define _mm_mask_fmadd_round_sd(W, U, A, B, R) __extension__({\
- (__m128d)__builtin_ia32_vfmaddsd3_mask((__v2df)(__m128d)(A), \
- (__v2df)(__m128d)(B), \
- (__v2df)(__m128d)(W), (__mmask8)(U), \
+ (__m128d)__builtin_ia32_vfmaddsd3_mask((__v2df)(__m128d)(W), \
+ (__v2df)(__m128d)(A), \
+ (__v2df)(__m128d)(B), (__mmask8)(U), \
(int)(R)); })
static __inline__ __m128d __DEFAULT_FN_ATTRS
@@ -8515,17 +8572,17 @@ _mm_mask3_fmadd_sd (__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U)
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_mask_fmsub_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B)
{
- return (__m128d) __builtin_ia32_vfmaddsd3_mask ( (__v2df) __A,
+ return (__m128d) __builtin_ia32_vfmaddsd3_mask ( (__v2df) __W,
+ (__v2df) __A,
-(__v2df) __B,
- (__v2df) __W,
(__mmask8) __U,
_MM_FROUND_CUR_DIRECTION);
}
#define _mm_mask_fmsub_round_sd(W, U, A, B, R) __extension__ ({\
- (__m128d)__builtin_ia32_vfmaddsd3_mask((__v2df)(__m128d)(A), \
- -(__v2df)(__m128d)(B), \
- (__v2df)(__m128d)(W), (__mmask8)(U), \
+ (__m128d)__builtin_ia32_vfmaddsd3_mask((__v2df)(__m128d)(W), \
+ (__v2df)(__m128d)(A), \
+ -(__v2df)(__m128d)(B), (__mmask8)(U), \
(int)(R)); })
static __inline__ __m128d __DEFAULT_FN_ATTRS
@@ -8547,33 +8604,33 @@ _mm_maskz_fmsub_sd (__mmask8 __U, __m128d __A, __m128d __B, __m128d __C)
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_mask3_fmsub_sd (__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U)
{
- return (__m128d) __builtin_ia32_vfmaddsd3_mask3 ((__v2df) __W,
+ return (__m128d) __builtin_ia32_vfmsubsd3_mask3 ((__v2df) __W,
(__v2df) __X,
- -(__v2df) __Y,
+ (__v2df) __Y,
(__mmask8) __U,
_MM_FROUND_CUR_DIRECTION);
}
#define _mm_mask3_fmsub_round_sd(W, X, Y, U, R) __extension__ ({\
- (__m128d)__builtin_ia32_vfmaddsd3_mask3((__v2df)(__m128d)(W), \
+ (__m128d)__builtin_ia32_vfmsubsd3_mask3((__v2df)(__m128d)(W), \
(__v2df)(__m128d)(X), \
- -(__v2df)(__m128d)(Y), \
+ (__v2df)(__m128d)(Y), \
(__mmask8)(U), (int)(R)); })
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_mask_fnmadd_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B)
{
- return (__m128d) __builtin_ia32_vfmaddsd3_mask ( -(__v2df) __A,
+ return (__m128d) __builtin_ia32_vfmaddsd3_mask ( (__v2df) __W,
+ -(__v2df) __A,
(__v2df) __B,
- (__v2df) __W,
(__mmask8) __U,
_MM_FROUND_CUR_DIRECTION);
}
#define _mm_mask_fnmadd_round_sd(W, U, A, B, R) __extension__ ({\
- (__m128d)__builtin_ia32_vfmaddsd3_mask(-(__v2df)(__m128d)(A), \
- (__v2df)(__m128d)(B), \
- (__v2df)(__m128d)(W), (__mmask8)(U), \
+ (__m128d)__builtin_ia32_vfmaddsd3_mask((__v2df)(__m128d)(W), \
+ -(__v2df)(__m128d)(A), \
+ (__v2df)(__m128d)(B), (__mmask8)(U), \
(int)(R)); })
static __inline__ __m128d __DEFAULT_FN_ATTRS
@@ -8611,17 +8668,17 @@ _mm_mask3_fnmadd_sd (__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U)
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_mask_fnmsub_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B)
{
- return (__m128d) __builtin_ia32_vfmaddsd3_mask ( -(__v2df) __A,
+ return (__m128d) __builtin_ia32_vfmaddsd3_mask ( (__v2df) __W,
+ -(__v2df) __A,
-(__v2df) __B,
- (__v2df) __W,
(__mmask8) __U,
_MM_FROUND_CUR_DIRECTION);
}
#define _mm_mask_fnmsub_round_sd(W, U, A, B, R) __extension__ ({\
- (__m128d)__builtin_ia32_vfmaddsd3_mask(-(__v2df)(__m128d)(A), \
- -(__v2df)(__m128d)(B), \
- (__v2df)(__m128d)(W), (__mmask8)(U), \
+ (__m128d)__builtin_ia32_vfmaddsd3_mask((__v2df)(__m128d)(W), \
+ -(__v2df)(__m128d)(A), \
+ -(__v2df)(__m128d)(B), (__mmask8)(U), \
(int)(R)); })
static __inline__ __m128d __DEFAULT_FN_ATTRS
@@ -8644,17 +8701,17 @@ _mm_maskz_fnmsub_sd (__mmask8 __U, __m128d __A, __m128d __B, __m128d __C)
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_mask3_fnmsub_sd (__m128d __W, __m128d __X, __m128d __Y, __mmask8 __U)
{
- return (__m128d) __builtin_ia32_vfmaddsd3_mask3 (-(__v2df) (__W),
+ return (__m128d) __builtin_ia32_vfnmsubsd3_mask3 ((__v2df) (__W),
(__v2df) __X,
- -(__v2df) (__Y),
+ (__v2df) (__Y),
(__mmask8) __U,
_MM_FROUND_CUR_DIRECTION);
}
#define _mm_mask3_fnmsub_round_sd(W, X, Y, U, R) __extension__({\
- (__m128d)__builtin_ia32_vfmaddsd3_mask3(-(__v2df)(__m128d)(W), \
+ (__m128d)__builtin_ia32_vfnmsubsd3_mask3((__v2df)(__m128d)(W), \
(__v2df)(__m128d)(X), \
- -(__v2df)(__m128d)(Y), \
+ (__v2df)(__m128d)(Y), \
(__mmask8)(U), (int)(R)); })
#define _mm512_permutex_pd(X, C) __extension__ ({ \
@@ -9041,6 +9098,101 @@ _mm512_maskz_moveldup_ps (__mmask16 __U, __m512 __A)
(__v16sf)_mm512_setzero_ps());
}
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_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;
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_mm_maskz_move_ss (__mmask8 __U, __m128 __A, __m128 __B)
+{
+ __m128 res = __A;
+ res[0] = (__U & 1) ? __B[0] : 0;
+ return res;
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_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;
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_mm_maskz_move_sd (__mmask8 __U, __m128d __A, __m128d __B)
+{
+ __m128d res = __A;
+ res[0] = (__U & 1) ? __B[0] : 0;
+ return res;
+}
+
+static __inline__ void __DEFAULT_FN_ATTRS
+_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);
+}
+
+static __inline__ void __DEFAULT_FN_ATTRS
+_mm_mask_store_sd (double * __W, __mmask8 __U, __m128d __A)
+{
+ __builtin_ia32_storesd128_mask ((__v8df *)__W,
+ (__v8df) _mm512_castpd128_pd512(__A),
+ (__mmask8) __U & 1);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_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},
+ 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);
+}
+
+static __inline__ __m128 __DEFAULT_FN_ATTRS
+_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);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_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);
+
+ return (__m128d) __builtin_shufflevector(
+ __builtin_ia32_loadsd128_mask ((__v8df *) __A,
+ (__v8df) _mm512_castpd128_pd512(src),
+ (__mmask8) __U & 1),
+ _mm512_undefined_pd(), 0, 1);
+}
+
+static __inline__ __m128d __DEFAULT_FN_ATTRS
+_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(), \
@@ -9243,6 +9395,18 @@ _mm512_maskz_cvtps_pd (__mmask8 __U, __m256 __A)
_MM_FROUND_CUR_DIRECTION);
}
+static __inline__ __m512 __DEFAULT_FN_ATTRS
+_mm512_cvtpslo_pd (__m512 __A)
+{
+ return (__m512) _mm512_cvtps_pd(_mm512_castps512_ps256(__A));
+}
+
+static __inline__ __m512 __DEFAULT_FN_ATTRS
+_mm512_mask_cvtpslo_pd (__m512d __W, __mmask8 __U, __m512 __A)
+{
+ return (__m512) _mm512_mask_cvtps_pd(__W, __U, _mm512_castps512_ps256(__A));
+}
+
static __inline__ __m512d __DEFAULT_FN_ATTRS
_mm512_mask_mov_pd (__m512d __W, __mmask8 __U, __m512d __A)
{
@@ -9340,14 +9504,17 @@ _mm_maskz_cvtsd_ss (__mmask8 __U, __m128 __A, __m128d __B)
}
#define _mm_cvtss_i32 _mm_cvtss_si32
-#define _mm_cvtss_i64 _mm_cvtss_si64
#define _mm_cvtsd_i32 _mm_cvtsd_si32
-#define _mm_cvtsd_i64 _mm_cvtsd_si64
#define _mm_cvti32_sd _mm_cvtsi32_sd
-#define _mm_cvti64_sd _mm_cvtsi64_sd
#define _mm_cvti32_ss _mm_cvtsi32_ss
+#ifdef __x86_64__
+#define _mm_cvtss_i64 _mm_cvtss_si64
+#define _mm_cvtsd_i64 _mm_cvtsd_si64
+#define _mm_cvti64_sd _mm_cvtsi64_sd
#define _mm_cvti64_ss _mm_cvtsi64_ss
+#endif
+#ifdef __x86_64__
#define _mm_cvt_roundi64_sd(A, B, R) __extension__ ({ \
(__m128d)__builtin_ia32_cvtsi2sd64((__v2df)(__m128d)(A), (long long)(B), \
(int)(R)); })
@@ -9355,6 +9522,7 @@ _mm_maskz_cvtsd_ss (__mmask8 __U, __m128 __A, __m128d __B)
#define _mm_cvt_roundsi64_sd(A, B, R) __extension__ ({ \
(__m128d)__builtin_ia32_cvtsi2sd64((__v2df)(__m128d)(A), (long long)(B), \
(int)(R)); })
+#endif
#define _mm_cvt_roundsi32_ss(A, B, R) __extension__ ({ \
(__m128)__builtin_ia32_cvtsi2ss32((__v4sf)(__m128)(A), (int)(B), (int)(R)); })
@@ -9362,6 +9530,7 @@ _mm_maskz_cvtsd_ss (__mmask8 __U, __m128 __A, __m128d __B)
#define _mm_cvt_roundi32_ss(A, B, R) __extension__ ({ \
(__m128)__builtin_ia32_cvtsi2ss32((__v4sf)(__m128)(A), (int)(B), (int)(R)); })
+#ifdef __x86_64__
#define _mm_cvt_roundsi64_ss(A, B, R) __extension__ ({ \
(__m128)__builtin_ia32_cvtsi2ss64((__v4sf)(__m128)(A), (long long)(B), \
(int)(R)); })
@@ -9369,6 +9538,7 @@ _mm_maskz_cvtsd_ss (__mmask8 __U, __m128 __A, __m128d __B)
#define _mm_cvt_roundi64_ss(A, B, R) __extension__ ({ \
(__m128)__builtin_ia32_cvtsi2ss64((__v4sf)(__m128)(A), (long long)(B), \
(int)(R)); })
+#endif
#define _mm_cvt_roundss_sd(A, B, R) __extension__ ({ \
(__m128d)__builtin_ia32_cvtss2sd_round_mask((__v2df)(__m128d)(A), \
@@ -9412,6 +9582,7 @@ _mm_cvtu32_sd (__m128d __A, unsigned __B)
return (__m128d) __builtin_ia32_cvtusi2sd32 ((__v2df) __A, __B);
}
+#ifdef __x86_64__
#define _mm_cvt_roundu64_sd(A, B, R) __extension__ ({ \
(__m128d)__builtin_ia32_cvtusi2sd64((__v2df)(__m128d)(A), \
(unsigned long long)(B), (int)(R)); })
@@ -9422,6 +9593,7 @@ _mm_cvtu64_sd (__m128d __A, unsigned long long __B)
return (__m128d) __builtin_ia32_cvtusi2sd64 ((__v2df) __A, __B,
_MM_FROUND_CUR_DIRECTION);
}
+#endif
#define _mm_cvt_roundu32_ss(A, B, R) __extension__ ({ \
(__m128)__builtin_ia32_cvtusi2ss32((__v4sf)(__m128)(A), (unsigned int)(B), \
@@ -9434,6 +9606,7 @@ _mm_cvtu32_ss (__m128 __A, unsigned __B)
_MM_FROUND_CUR_DIRECTION);
}
+#ifdef __x86_64__
#define _mm_cvt_roundu64_ss(A, B, R) __extension__ ({ \
(__m128)__builtin_ia32_cvtusi2ss64((__v4sf)(__m128)(A), \
(unsigned long long)(B), (int)(R)); })
@@ -9444,6 +9617,7 @@ _mm_cvtu64_ss (__m128 __A, unsigned long long __B)
return (__m128) __builtin_ia32_cvtusi2ss64 ((__v4sf) __A, __B,
_MM_FROUND_CUR_DIRECTION);
}
+#endif
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_mask_set1_epi32 (__m512i __O, __mmask16 __M, int __A)
@@ -9452,12 +9626,14 @@ _mm512_mask_set1_epi32 (__m512i __O, __mmask16 __M, int __A)
__M);
}
+#ifdef __x86_64__
static __inline__ __m512i __DEFAULT_FN_ATTRS
_mm512_mask_set1_epi64 (__m512i __O, __mmask8 __M, long long __A)
{
return (__m512i) __builtin_ia32_pbroadcastq512_gpr_mask (__A, (__v8di) __O,
__M);
}
+#endif
static __inline __m512i __DEFAULT_FN_ATTRS
_mm512_set_epi32 (int __A, int __B, int __C, int __D,
@@ -9514,27 +9690,553 @@ _mm512_set_ps (float __A, float __B, float __C, float __D,
(e4),(e3),(e2),(e1),(e0))
static __inline__ __m512 __DEFAULT_FN_ATTRS
-_mm512_abs_ps(__m512 A)
+_mm512_abs_ps(__m512 __A)
{
- return (__m512)_mm512_and_epi32(_mm512_set1_epi32(0x7FFFFFFF),(__m512i)A) ;
+ return (__m512)_mm512_and_epi32(_mm512_set1_epi32(0x7FFFFFFF),(__m512i)__A) ;
}
static __inline__ __m512 __DEFAULT_FN_ATTRS
-_mm512_mask_abs_ps(__m512 W, __mmask16 K, __m512 A)
+_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) ;
+ return (__m512)_mm512_mask_and_epi32((__m512i)__W, __K, _mm512_set1_epi32(0x7FFFFFFF),(__m512i)__A) ;
}
static __inline__ __m512d __DEFAULT_FN_ATTRS
-_mm512_abs_pd(__m512d A)
+_mm512_abs_pd(__m512d __A)
{
- return (__m512d)_mm512_and_epi64(_mm512_set1_epi64(0x7FFFFFFFFFFFFFFF),(__v8di)A) ;
+ return (__m512d)_mm512_and_epi64(_mm512_set1_epi64(0x7FFFFFFFFFFFFFFF),(__v8di)__A) ;
}
static __inline__ __m512d __DEFAULT_FN_ATTRS
-_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);
+_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
+_mm512_mask_reduce_add_epi64(__mmask8 __M, __m512i __W) {
+ _mm512_mask_reduce_operator_64bit(__W, _mm512_set1_epi64(0), +, __M, i, i, q);
+}
+
+static __inline__ long long __DEFAULT_FN_ATTRS
+_mm512_mask_reduce_mul_epi64(__mmask8 __M, __m512i __W) {
+ _mm512_mask_reduce_operator_64bit(__W, _mm512_set1_epi64(1), *, __M, i, i, q);
+}
+
+static __inline__ long long __DEFAULT_FN_ATTRS
+_mm512_mask_reduce_and_epi64(__mmask8 __M, __m512i __W) {
+ _mm512_mask_reduce_operator_64bit(__W, _mm512_set1_epi64(0xFFFFFFFFFFFFFFFF),
+ &, __M, i, i, q);
+}
+
+static __inline__ long long __DEFAULT_FN_ATTRS
+_mm512_mask_reduce_or_epi64(__mmask8 __M, __m512i __W) {
+ _mm512_mask_reduce_operator_64bit(__W, _mm512_set1_epi64(0), |, __M,
+ i, i, q);
+}
+
+static __inline__ double __DEFAULT_FN_ATTRS
+_mm512_mask_reduce_add_pd(__mmask8 __M, __m512d __W) {
+ _mm512_mask_reduce_operator_64bit(__W, _mm512_set1_pd(0), +, __M,
+ f, d, pd);
+}
+
+static __inline__ double __DEFAULT_FN_ATTRS
+_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
+_mm512_reduce_add_epi32(__m512i __W) {
+ _mm512_reduce_operator_32bit(__W, +, i, i);
+}
+
+static __inline__ int __DEFAULT_FN_ATTRS
+_mm512_reduce_mul_epi32(__m512i __W) {
+ _mm512_reduce_operator_32bit(__W, *, i, i);
+}
+
+static __inline__ int __DEFAULT_FN_ATTRS
+_mm512_reduce_and_epi32(__m512i __W) {
+ _mm512_reduce_operator_32bit(__W, &, i, i);
+}
+
+static __inline__ int __DEFAULT_FN_ATTRS
+_mm512_reduce_or_epi32(__m512i __W) {
+ _mm512_reduce_operator_32bit(__W, |, i, i);
+}
+
+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
+_mm512_mask_reduce_add_epi32( __mmask16 __M, __m512i __W) {
+ _mm512_mask_reduce_operator_32bit(__W, _mm512_set1_epi32(0), +, __M, i, i, d);
+}
+
+static __inline__ int __DEFAULT_FN_ATTRS
+_mm512_mask_reduce_mul_epi32( __mmask16 __M, __m512i __W) {
+ _mm512_mask_reduce_operator_32bit(__W, _mm512_set1_epi32(1), *, __M, i, i, d);
+}
+
+static __inline__ int __DEFAULT_FN_ATTRS
+_mm512_mask_reduce_and_epi32( __mmask16 __M, __m512i __W) {
+ _mm512_mask_reduce_operator_32bit(__W, _mm512_set1_epi32(0xFFFFFFFF), &, __M,
+ i, i, d);
+}
+
+static __inline__ int __DEFAULT_FN_ATTRS
+_mm512_mask_reduce_or_epi32(__mmask16 __M, __m512i __W) {
+ _mm512_mask_reduce_operator_32bit(__W, _mm512_set1_epi32(0), |, __M, i, i, d);
+}
+
+static __inline__ float __DEFAULT_FN_ATTRS
+_mm512_mask_reduce_add_ps(__mmask16 __M, __m512 __W) {
+ _mm512_mask_reduce_operator_32bit(__W, _mm512_set1_ps(0), +, __M, f, , ps);
+}
+
+static __inline__ float __DEFAULT_FN_ATTRS
+_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);
+}
+
+static __inline__ unsigned long long __DEFAULT_FN_ATTRS
+_mm512_reduce_max_epu64(__m512i __V) {
+ _mm512_reduce_maxMin_64bit(__V, max_epu64, i, i);
+}
+
+static __inline__ double __DEFAULT_FN_ATTRS
+_mm512_reduce_max_pd(__m512d __V) {
+ _mm512_reduce_maxMin_64bit(__V, max_pd, d, f);
+}
+
+static __inline__ long long __DEFAULT_FN_ATTRS _mm512_reduce_min_epi64
+(__m512i __V) {
+ _mm512_reduce_maxMin_64bit(__V, min_epi64, i, i);
+}
+
+static __inline__ unsigned long long __DEFAULT_FN_ATTRS
+_mm512_reduce_min_epu64(__m512i __V) {
+ _mm512_reduce_maxMin_64bit(__V, min_epu64, i, i);
+}
+
+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
+_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);
+}
+
+static __inline__ unsigned long long __DEFAULT_FN_ATTRS
+_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);
+}
+
+static __inline__ long long __DEFAULT_FN_ATTRS
+_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);
+}
+
+static __inline__ unsigned long long __DEFAULT_FN_ATTRS
+_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);
+}
+
+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);
+}
+
+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__ 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_ATTRS
+_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);
+}
+
+static __inline__ unsigned int __DEFAULT_FN_ATTRS
+_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);
+}
+
+static __inline__ float __DEFAULT_FN_ATTRS
+_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);
}
#undef __DEFAULT_FN_ATTRS
diff --git a/lib/Headers/avx512vlbwintrin.h b/lib/Headers/avx512vlbwintrin.h
index 990e992a113f..3b58d043395a 100644
--- a/lib/Headers/avx512vlbwintrin.h
+++ b/lib/Headers/avx512vlbwintrin.h
@@ -615,172 +615,143 @@ _mm256_mask_cmpneq_epu16_mask(__mmask16 __u, __m256i __a, __m256i __b) {
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_add_epi8 (__m256i __W, __mmask32 __U, __m256i __A, __m256i __B){
- return (__m256i) __builtin_ia32_paddb256_mask ((__v32qi) __A,
- (__v32qi) __B,
- (__v32qi) __W,
- (__mmask32) __U);
+_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
-_mm256_maskz_add_epi8 (__mmask32 __U, __m256i __A, __m256i __B) {
- return (__m256i) __builtin_ia32_paddb256_mask ((__v32qi) __A,
- (__v32qi) __B,
- (__v32qi)
- _mm256_setzero_si256 (),
- (__mmask32) __U);
+_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
-_mm256_mask_add_epi16 (__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) {
- return (__m256i) __builtin_ia32_paddw256_mask ((__v16hi) __A,
- (__v16hi) __B,
- (__v16hi) __W,
- (__mmask16) __U);
+_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
-_mm256_maskz_add_epi16 (__mmask16 __U, __m256i __A, __m256i __B) {
- return (__m256i) __builtin_ia32_paddw256_mask ((__v16hi) __A,
- (__v16hi) __B,
- (__v16hi)
- _mm256_setzero_si256 (),
- (__mmask16) __U);
+_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
-_mm256_mask_sub_epi8 (__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) {
- return (__m256i) __builtin_ia32_psubb256_mask ((__v32qi) __A,
- (__v32qi) __B,
- (__v32qi) __W,
- (__mmask32) __U);
+_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
-_mm256_maskz_sub_epi8 (__mmask32 __U, __m256i __A, __m256i __B) {
- return (__m256i) __builtin_ia32_psubb256_mask ((__v32qi) __A,
- (__v32qi) __B,
- (__v32qi)
- _mm256_setzero_si256 (),
- (__mmask32) __U);
+_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
-_mm256_mask_sub_epi16 (__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) {
- return (__m256i) __builtin_ia32_psubw256_mask ((__v16hi) __A,
- (__v16hi) __B,
- (__v16hi) __W,
- (__mmask16) __U);
+_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
-_mm256_maskz_sub_epi16 (__mmask16 __U, __m256i __A, __m256i __B) {
- return (__m256i) __builtin_ia32_psubw256_mask ((__v16hi) __A,
- (__v16hi) __B,
- (__v16hi)
- _mm256_setzero_si256 (),
- (__mmask16) __U);
+_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
-_mm_mask_add_epi8 (__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) {
- return (__m128i) __builtin_ia32_paddb128_mask ((__v16qi) __A,
- (__v16qi) __B,
- (__v16qi) __W,
- (__mmask16) __U);
+_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
-_mm_maskz_add_epi8 (__mmask16 __U, __m128i __A, __m128i __B) {
- return (__m128i) __builtin_ia32_paddb128_mask ((__v16qi) __A,
- (__v16qi) __B,
- (__v16qi)
- _mm_setzero_si128 (),
- (__mmask16) __U);
+_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
-_mm_mask_add_epi16 (__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
- return (__m128i) __builtin_ia32_paddw128_mask ((__v8hi) __A,
- (__v8hi) __B,
- (__v8hi) __W,
- (__mmask8) __U);
+_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
-_mm_maskz_add_epi16 (__mmask8 __U, __m128i __A, __m128i __B) {
- return (__m128i) __builtin_ia32_paddw128_mask ((__v8hi) __A,
- (__v8hi) __B,
- (__v8hi)
- _mm_setzero_si128 (),
- (__mmask8) __U);
+_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
-_mm_mask_sub_epi8 (__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) {
- return (__m128i) __builtin_ia32_psubb128_mask ((__v16qi) __A,
- (__v16qi) __B,
- (__v16qi) __W,
- (__mmask16) __U);
+_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
-_mm_maskz_sub_epi8 (__mmask16 __U, __m128i __A, __m128i __B) {
- return (__m128i) __builtin_ia32_psubb128_mask ((__v16qi) __A,
- (__v16qi) __B,
- (__v16qi)
- _mm_setzero_si128 (),
- (__mmask16) __U);
+_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
-_mm_mask_sub_epi16 (__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
- return (__m128i) __builtin_ia32_psubw128_mask ((__v8hi) __A,
- (__v8hi) __B,
- (__v8hi) __W,
- (__mmask8) __U);
+_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
-_mm_maskz_sub_epi16 (__mmask8 __U, __m128i __A, __m128i __B) {
- return (__m128i) __builtin_ia32_psubw128_mask ((__v8hi) __A,
- (__v8hi) __B,
- (__v8hi)
- _mm_setzero_si128 (),
- (__mmask8) __U);
+_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
-_mm256_mask_mullo_epi16 (__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) {
- return (__m256i) __builtin_ia32_pmullw256_mask ((__v16hi) __A,
- (__v16hi) __B,
- (__v16hi) __W,
- (__mmask16) __U);
+_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
-_mm256_maskz_mullo_epi16 (__mmask16 __U, __m256i __A, __m256i __B) {
- return (__m256i) __builtin_ia32_pmullw256_mask ((__v16hi) __A,
- (__v16hi) __B,
- (__v16hi)
- _mm256_setzero_si256 (),
- (__mmask16) __U);
+_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
-_mm_mask_mullo_epi16 (__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
- return (__m128i) __builtin_ia32_pmullw128_mask ((__v8hi) __A,
- (__v8hi) __B,
- (__v8hi) __W,
- (__mmask8) __U);
+_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
-_mm_maskz_mullo_epi16 (__mmask8 __U, __m128i __A, __m128i __B) {
- return (__m128i) __builtin_ia32_pmullw128_mask ((__v8hi) __A,
- (__v8hi) __B,
- (__v8hi)
- _mm_setzero_si128 (),
- (__mmask8) __U);
+_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
@@ -816,937 +787,802 @@ _mm256_mask_blend_epi16 (__mmask16 __U, __m256i __A, __m256i __W)
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_abs_epi8 (__m128i __W, __mmask16 __U, __m128i __A)
+_mm_mask_abs_epi8(__m128i __W, __mmask16 __U, __m128i __A)
{
- return (__m128i) __builtin_ia32_pabsb128_mask ((__v16qi) __A,
- (__v16qi) __W,
- (__mmask16) __U);
+ return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U,
+ (__v16qi)_mm_abs_epi8(__A),
+ (__v16qi)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_abs_epi8 (__mmask16 __U, __m128i __A)
+_mm_maskz_abs_epi8(__mmask16 __U, __m128i __A)
{
- return (__m128i) __builtin_ia32_pabsb128_mask ((__v16qi) __A,
- (__v16qi) _mm_setzero_si128 (),
- (__mmask16) __U);
+ return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U,
+ (__v16qi)_mm_abs_epi8(__A),
+ (__v16qi)_mm_setzero_si128());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_abs_epi8 (__m256i __W, __mmask32 __U, __m256i __A)
+_mm256_mask_abs_epi8(__m256i __W, __mmask32 __U, __m256i __A)
{
- return (__m256i) __builtin_ia32_pabsb256_mask ((__v32qi) __A,
- (__v32qi) __W,
- (__mmask32) __U);
+ return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U,
+ (__v32qi)_mm256_abs_epi8(__A),
+ (__v32qi)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_maskz_abs_epi8 (__mmask32 __U, __m256i __A)
{
- return (__m256i) __builtin_ia32_pabsb256_mask ((__v32qi) __A,
- (__v32qi) _mm256_setzero_si256 (),
- (__mmask32) __U);
+ return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U,
+ (__v32qi)_mm256_abs_epi8(__A),
+ (__v32qi)_mm256_setzero_si256());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_abs_epi16 (__m128i __W, __mmask8 __U, __m128i __A)
+_mm_mask_abs_epi16(__m128i __W, __mmask8 __U, __m128i __A)
{
- return (__m128i) __builtin_ia32_pabsw128_mask ((__v8hi) __A,
- (__v8hi) __W,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
+ (__v8hi)_mm_abs_epi16(__A),
+ (__v8hi)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_abs_epi16 (__mmask8 __U, __m128i __A)
+_mm_maskz_abs_epi16(__mmask8 __U, __m128i __A)
{
- return (__m128i) __builtin_ia32_pabsw128_mask ((__v8hi) __A,
- (__v8hi) _mm_setzero_si128 (),
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
+ (__v8hi)_mm_abs_epi16(__A),
+ (__v8hi)_mm_setzero_si128());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_abs_epi16 (__m256i __W, __mmask16 __U, __m256i __A)
+_mm256_mask_abs_epi16(__m256i __W, __mmask16 __U, __m256i __A)
{
- return (__m256i) __builtin_ia32_pabsw256_mask ((__v16hi) __A,
- (__v16hi) __W,
- (__mmask16) __U);
+ return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
+ (__v16hi)_mm256_abs_epi16(__A),
+ (__v16hi)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_abs_epi16 (__mmask16 __U, __m256i __A)
+_mm256_maskz_abs_epi16(__mmask16 __U, __m256i __A)
{
- return (__m256i) __builtin_ia32_pabsw256_mask ((__v16hi) __A,
- (__v16hi) _mm256_setzero_si256 (),
- (__mmask16) __U);
+ return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
+ (__v16hi)_mm256_abs_epi16(__A),
+ (__v16hi)_mm256_setzero_si256());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_packs_epi32 (__mmask8 __M, __m128i __A, __m128i __B)
-{
- return (__m128i) __builtin_ia32_packssdw128_mask ((__v4si) __A,
- (__v4si) __B,
- (__v8hi) _mm_setzero_si128 (), __M);
+_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)
+_mm_mask_packs_epi32(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_packssdw128_mask ((__v4si) __A,
- (__v4si) __B,
- (__v8hi) __W, __M);
+ return (__m128i)__builtin_ia32_selectw_128((__mmask8)__M,
+ (__v8hi)_mm_packs_epi32(__A, __B),
+ (__v8hi)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_packs_epi32 (__mmask16 __M, __m256i __A, __m256i __B)
+_mm256_maskz_packs_epi32(__mmask16 __M, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_packssdw256_mask ((__v8si) __A,
- (__v8si) __B,
- (__v16hi) _mm256_setzero_si256 (),
- __M);
+ return (__m256i)__builtin_ia32_selectw_256((__mmask16)__M,
+ (__v16hi)_mm256_packs_epi32(__A, __B),
+ (__v16hi)_mm256_setzero_si256());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_packs_epi32 (__m256i __W, __mmask16 __M, __m256i __A,
- __m256i __B)
+_mm256_mask_packs_epi32(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_packssdw256_mask ((__v8si) __A,
- (__v8si) __B,
- (__v16hi) __W, __M);
+ return (__m256i)__builtin_ia32_selectw_256((__mmask16)__M,
+ (__v16hi)_mm256_packs_epi32(__A, __B),
+ (__v16hi)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_packs_epi16 (__mmask16 __M, __m128i __A, __m128i __B)
+_mm_maskz_packs_epi16(__mmask16 __M, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_packsswb128_mask ((__v8hi) __A,
- (__v8hi) __B,
- (__v16qi) _mm_setzero_si128 (),
- __M);
+ return (__m128i)__builtin_ia32_selectb_128((__mmask16)__M,
+ (__v16qi)_mm_packs_epi16(__A, __B),
+ (__v16qi)_mm_setzero_si128());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_packs_epi16 (__m128i __W, __mmask16 __M, __m128i __A,
- __m128i __B)
+_mm_mask_packs_epi16(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_packsswb128_mask ((__v8hi) __A,
- (__v8hi) __B,
- (__v16qi) __W,
- __M);
+ return (__m128i)__builtin_ia32_selectb_128((__mmask16)__M,
+ (__v16qi)_mm_packs_epi16(__A, __B),
+ (__v16qi)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_packs_epi16 (__mmask32 __M, __m256i __A, __m256i __B)
+_mm256_maskz_packs_epi16(__mmask32 __M, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_packsswb256_mask ((__v16hi) __A,
- (__v16hi) __B,
- (__v32qi) _mm256_setzero_si256 (),
- __M);
+ return (__m256i)__builtin_ia32_selectb_256((__mmask32)__M,
+ (__v32qi)_mm256_packs_epi16(__A, __B),
+ (__v32qi)_mm256_setzero_si256());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_packs_epi16 (__m256i __W, __mmask32 __M, __m256i __A,
- __m256i __B)
+_mm256_mask_packs_epi16(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_packsswb256_mask ((__v16hi) __A,
- (__v16hi) __B,
- (__v32qi) __W,
- __M);
+ return (__m256i)__builtin_ia32_selectb_256((__mmask32)__M,
+ (__v32qi)_mm256_packs_epi16(__A, __B),
+ (__v32qi)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_packus_epi32 (__mmask8 __M, __m128i __A, __m128i __B)
+_mm_maskz_packus_epi32(__mmask8 __M, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_packusdw128_mask ((__v4si) __A,
- (__v4si) __B,
- (__v8hi) _mm_setzero_si128 (),
- __M);
+ return (__m128i)__builtin_ia32_selectw_128((__mmask8)__M,
+ (__v8hi)_mm_packus_epi32(__A, __B),
+ (__v8hi)_mm_setzero_si128());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_packus_epi32 (__m128i __W, __mmask16 __M, __m128i __A,
- __m128i __B)
+_mm_mask_packus_epi32(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_packusdw128_mask ((__v4si) __A,
- (__v4si) __B,
- (__v8hi) __W, __M);
+ return (__m128i)__builtin_ia32_selectw_128((__mmask8)__M,
+ (__v8hi)_mm_packus_epi32(__A, __B),
+ (__v8hi)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_packus_epi32 (__mmask16 __M, __m256i __A, __m256i __B)
+_mm256_maskz_packus_epi32(__mmask16 __M, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_packusdw256_mask ((__v8si) __A,
- (__v8si) __B,
- (__v16hi) _mm256_setzero_si256 (),
- __M);
+ return (__m256i)__builtin_ia32_selectw_256((__mmask16)__M,
+ (__v16hi)_mm256_packus_epi32(__A, __B),
+ (__v16hi)_mm256_setzero_si256());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_packus_epi32 (__m256i __W, __mmask16 __M, __m256i __A,
- __m256i __B)
+_mm256_mask_packus_epi32(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_packusdw256_mask ((__v8si) __A,
- (__v8si) __B,
- (__v16hi) __W,
- __M);
+ return (__m256i)__builtin_ia32_selectw_256((__mmask16)__M,
+ (__v16hi)_mm256_packus_epi32(__A, __B),
+ (__v16hi)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_packus_epi16 (__mmask16 __M, __m128i __A, __m128i __B)
+_mm_maskz_packus_epi16(__mmask16 __M, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_packuswb128_mask ((__v8hi) __A,
- (__v8hi) __B,
- (__v16qi) _mm_setzero_si128 (),
- __M);
+ return (__m128i)__builtin_ia32_selectb_128((__mmask16)__M,
+ (__v16qi)_mm_packus_epi16(__A, __B),
+ (__v16qi)_mm_setzero_si128());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_packus_epi16 (__m128i __W, __mmask16 __M, __m128i __A,
- __m128i __B)
+_mm_mask_packus_epi16(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_packuswb128_mask ((__v8hi) __A,
- (__v8hi) __B,
- (__v16qi) __W,
- __M);
+ return (__m128i)__builtin_ia32_selectb_128((__mmask16)__M,
+ (__v16qi)_mm_packus_epi16(__A, __B),
+ (__v16qi)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_packus_epi16 (__mmask32 __M, __m256i __A, __m256i __B)
+_mm256_maskz_packus_epi16(__mmask32 __M, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_packuswb256_mask ((__v16hi) __A,
- (__v16hi) __B,
- (__v32qi) _mm256_setzero_si256 (),
- __M);
+ return (__m256i)__builtin_ia32_selectb_256((__mmask32)__M,
+ (__v32qi)_mm256_packus_epi16(__A, __B),
+ (__v32qi)_mm256_setzero_si256());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_packus_epi16 (__m256i __W, __mmask32 __M, __m256i __A,
- __m256i __B)
+_mm256_mask_packus_epi16(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_packuswb256_mask ((__v16hi) __A,
- (__v16hi) __B,
- (__v32qi) __W,
- __M);
+ return (__m256i)__builtin_ia32_selectb_256((__mmask32)__M,
+ (__v32qi)_mm256_packus_epi16(__A, __B),
+ (__v32qi)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_adds_epi8 (__m128i __W, __mmask16 __U, __m128i __A,
- __m128i __B)
+_mm_mask_adds_epi8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_paddsb128_mask ((__v16qi) __A,
- (__v16qi) __B,
- (__v16qi) __W,
- (__mmask16) __U);
+ return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U,
+ (__v16qi)_mm_adds_epi8(__A, __B),
+ (__v16qi)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_adds_epi8 (__mmask16 __U, __m128i __A, __m128i __B)
+_mm_maskz_adds_epi8(__mmask16 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_paddsb128_mask ((__v16qi) __A,
- (__v16qi) __B,
- (__v16qi) _mm_setzero_si128 (),
- (__mmask16) __U);
+ return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U,
+ (__v16qi)_mm_adds_epi8(__A, __B),
+ (__v16qi)_mm_setzero_si128());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_adds_epi8 (__m256i __W, __mmask32 __U, __m256i __A,
- __m256i __B)
+_mm256_mask_adds_epi8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_paddsb256_mask ((__v32qi) __A,
- (__v32qi) __B,
- (__v32qi) __W,
- (__mmask32) __U);
+ return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U,
+ (__v32qi)_mm256_adds_epi8(__A, __B),
+ (__v32qi)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_adds_epi8 (__mmask32 __U, __m256i __A, __m256i __B)
+_mm256_maskz_adds_epi8(__mmask32 __U, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_paddsb256_mask ((__v32qi) __A,
- (__v32qi) __B,
- (__v32qi) _mm256_setzero_si256 (),
- (__mmask32) __U);
+ return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U,
+ (__v32qi)_mm256_adds_epi8(__A, __B),
+ (__v32qi)_mm256_setzero_si256());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_adds_epi16 (__m128i __W, __mmask8 __U, __m128i __A,
- __m128i __B)
+_mm_mask_adds_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_paddsw128_mask ((__v8hi) __A,
- (__v8hi) __B,
- (__v8hi) __W,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
+ (__v8hi)_mm_adds_epi16(__A, __B),
+ (__v8hi)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_adds_epi16 (__mmask8 __U, __m128i __A, __m128i __B)
+_mm_maskz_adds_epi16(__mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_paddsw128_mask ((__v8hi) __A,
- (__v8hi) __B,
- (__v8hi) _mm_setzero_si128 (),
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
+ (__v8hi)_mm_adds_epi16(__A, __B),
+ (__v8hi)_mm_setzero_si128());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_adds_epi16 (__m256i __W, __mmask16 __U, __m256i __A,
- __m256i __B)
+_mm256_mask_adds_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_paddsw256_mask ((__v16hi) __A,
- (__v16hi) __B,
- (__v16hi) __W,
- (__mmask16) __U);
+ return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
+ (__v16hi)_mm256_adds_epi16(__A, __B),
+ (__v16hi)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_adds_epi16 (__mmask16 __U, __m256i __A, __m256i __B)
+_mm256_maskz_adds_epi16(__mmask16 __U, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_paddsw256_mask ((__v16hi) __A,
- (__v16hi) __B,
- (__v16hi) _mm256_setzero_si256 (),
- (__mmask16) __U);
+ return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
+ (__v16hi)_mm256_adds_epi16(__A, __B),
+ (__v16hi)_mm256_setzero_si256());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_adds_epu8 (__m128i __W, __mmask16 __U, __m128i __A,
- __m128i __B)
+_mm_mask_adds_epu8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_paddusb128_mask ((__v16qi) __A,
- (__v16qi) __B,
- (__v16qi) __W,
- (__mmask16) __U);
+ return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U,
+ (__v16qi)_mm_adds_epu8(__A, __B),
+ (__v16qi)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_adds_epu8 (__mmask16 __U, __m128i __A, __m128i __B)
+_mm_maskz_adds_epu8(__mmask16 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_paddusb128_mask ((__v16qi) __A,
- (__v16qi) __B,
- (__v16qi) _mm_setzero_si128 (),
- (__mmask16) __U);
+ return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U,
+ (__v16qi)_mm_adds_epu8(__A, __B),
+ (__v16qi)_mm_setzero_si128());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_adds_epu8 (__m256i __W, __mmask32 __U, __m256i __A,
- __m256i __B)
+_mm256_mask_adds_epu8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_paddusb256_mask ((__v32qi) __A,
- (__v32qi) __B,
- (__v32qi) __W,
- (__mmask32) __U);
+ return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U,
+ (__v32qi)_mm256_adds_epu8(__A, __B),
+ (__v32qi)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_adds_epu8 (__mmask32 __U, __m256i __A, __m256i __B)
+_mm256_maskz_adds_epu8(__mmask32 __U, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_paddusb256_mask ((__v32qi) __A,
- (__v32qi) __B,
- (__v32qi) _mm256_setzero_si256 (),
- (__mmask32) __U);
+ return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U,
+ (__v32qi)_mm256_adds_epu8(__A, __B),
+ (__v32qi)_mm256_setzero_si256());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_adds_epu16 (__m128i __W, __mmask8 __U, __m128i __A,
- __m128i __B)
+_mm_mask_adds_epu16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_paddusw128_mask ((__v8hi) __A,
- (__v8hi) __B,
- (__v8hi) __W,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
+ (__v8hi)_mm_adds_epu16(__A, __B),
+ (__v8hi)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_adds_epu16 (__mmask8 __U, __m128i __A, __m128i __B)
+_mm_maskz_adds_epu16(__mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_paddusw128_mask ((__v8hi) __A,
- (__v8hi) __B,
- (__v8hi) _mm_setzero_si128 (),
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
+ (__v8hi)_mm_adds_epu16(__A, __B),
+ (__v8hi)_mm_setzero_si128());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_adds_epu16 (__m256i __W, __mmask16 __U, __m256i __A,
- __m256i __B)
+_mm256_mask_adds_epu16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_paddusw256_mask ((__v16hi) __A,
- (__v16hi) __B,
- (__v16hi) __W,
- (__mmask16) __U);
+ return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
+ (__v16hi)_mm256_adds_epu16(__A, __B),
+ (__v16hi)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_adds_epu16 (__mmask16 __U, __m256i __A, __m256i __B)
+_mm256_maskz_adds_epu16(__mmask16 __U, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_paddusw256_mask ((__v16hi) __A,
- (__v16hi) __B,
- (__v16hi) _mm256_setzero_si256 (),
- (__mmask16) __U);
+ return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
+ (__v16hi)_mm256_adds_epu16(__A, __B),
+ (__v16hi)_mm256_setzero_si256());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_avg_epu8 (__m128i __W, __mmask16 __U, __m128i __A,
- __m128i __B)
+_mm_mask_avg_epu8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_pavgb128_mask ((__v16qi) __A,
- (__v16qi) __B,
- (__v16qi) __W,
- (__mmask16) __U);
+ return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U,
+ (__v16qi)_mm_avg_epu8(__A, __B),
+ (__v16qi)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_avg_epu8 (__mmask16 __U, __m128i __A, __m128i __B)
+_mm_maskz_avg_epu8(__mmask16 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_pavgb128_mask ((__v16qi) __A,
- (__v16qi) __B,
- (__v16qi) _mm_setzero_si128 (),
- (__mmask16) __U);
+ return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U,
+ (__v16qi)_mm_avg_epu8(__A, __B),
+ (__v16qi)_mm_setzero_si128());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_avg_epu8 (__m256i __W, __mmask32 __U, __m256i __A,
- __m256i __B)
+_mm256_mask_avg_epu8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_pavgb256_mask ((__v32qi) __A,
- (__v32qi) __B,
- (__v32qi) __W,
- (__mmask32) __U);
+ return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U,
+ (__v32qi)_mm256_avg_epu8(__A, __B),
+ (__v32qi)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_avg_epu8 (__mmask32 __U, __m256i __A, __m256i __B)
+_mm256_maskz_avg_epu8(__mmask32 __U, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_pavgb256_mask ((__v32qi) __A,
- (__v32qi) __B,
- (__v32qi) _mm256_setzero_si256 (),
- (__mmask32) __U);
+ return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U,
+ (__v32qi)_mm256_avg_epu8(__A, __B),
+ (__v32qi)_mm256_setzero_si256());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_avg_epu16 (__m128i __W, __mmask8 __U, __m128i __A,
- __m128i __B)
+_mm_mask_avg_epu16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_pavgw128_mask ((__v8hi) __A,
- (__v8hi) __B,
- (__v8hi) __W,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
+ (__v8hi)_mm_avg_epu16(__A, __B),
+ (__v8hi)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_avg_epu16 (__mmask8 __U, __m128i __A, __m128i __B)
+_mm_maskz_avg_epu16(__mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_pavgw128_mask ((__v8hi) __A,
- (__v8hi) __B,
- (__v8hi) _mm_setzero_si128 (),
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
+ (__v8hi)_mm_avg_epu16(__A, __B),
+ (__v8hi)_mm_setzero_si128());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_avg_epu16 (__m256i __W, __mmask16 __U, __m256i __A,
- __m256i __B)
+_mm256_mask_avg_epu16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_pavgw256_mask ((__v16hi) __A,
- (__v16hi) __B,
- (__v16hi) __W,
- (__mmask16) __U);
+ return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
+ (__v16hi)_mm256_avg_epu16(__A, __B),
+ (__v16hi)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_avg_epu16 (__mmask16 __U, __m256i __A, __m256i __B)
+_mm256_maskz_avg_epu16(__mmask16 __U, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_pavgw256_mask ((__v16hi) __A,
- (__v16hi) __B,
- (__v16hi) _mm256_setzero_si256 (),
- (__mmask16) __U);
+ return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
+ (__v16hi)_mm256_avg_epu16(__A, __B),
+ (__v16hi)_mm256_setzero_si256());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_max_epi8 (__mmask16 __M, __m128i __A, __m128i __B)
+_mm_maskz_max_epi8(__mmask16 __M, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_pmaxsb128_mask ((__v16qi) __A,
- (__v16qi) __B,
- (__v16qi) _mm_setzero_si128 (),
- (__mmask16) __M);
+ return (__m128i)__builtin_ia32_selectb_128((__mmask16)__M,
+ (__v16qi)_mm_max_epi8(__A, __B),
+ (__v16qi)_mm_setzero_si128());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_max_epi8 (__m128i __W, __mmask16 __M, __m128i __A,
- __m128i __B)
+_mm_mask_max_epi8(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_pmaxsb128_mask ((__v16qi) __A,
- (__v16qi) __B,
- (__v16qi) __W,
- (__mmask16) __M);
+ return (__m128i)__builtin_ia32_selectb_128((__mmask16)__M,
+ (__v16qi)_mm_max_epi8(__A, __B),
+ (__v16qi)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_max_epi8 (__mmask32 __M, __m256i __A, __m256i __B)
+_mm256_maskz_max_epi8(__mmask32 __M, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_pmaxsb256_mask ((__v32qi) __A,
- (__v32qi) __B,
- (__v32qi) _mm256_setzero_si256 (),
- (__mmask32) __M);
+ return (__m256i)__builtin_ia32_selectb_256((__mmask32)__M,
+ (__v32qi)_mm256_max_epi8(__A, __B),
+ (__v32qi)_mm256_setzero_si256());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_max_epi8 (__m256i __W, __mmask32 __M, __m256i __A,
- __m256i __B)
+_mm256_mask_max_epi8(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_pmaxsb256_mask ((__v32qi) __A,
- (__v32qi) __B,
- (__v32qi) __W,
- (__mmask32) __M);
+ return (__m256i)__builtin_ia32_selectb_256((__mmask32)__M,
+ (__v32qi)_mm256_max_epi8(__A, __B),
+ (__v32qi)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_max_epi16 (__mmask8 __M, __m128i __A, __m128i __B)
+_mm_maskz_max_epi16(__mmask8 __M, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_pmaxsw128_mask ((__v8hi) __A,
- (__v8hi) __B,
- (__v8hi) _mm_setzero_si128 (),
- (__mmask8) __M);
+ return (__m128i)__builtin_ia32_selectw_128((__mmask8)__M,
+ (__v8hi)_mm_max_epi16(__A, __B),
+ (__v8hi)_mm_setzero_si128());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_max_epi16 (__m128i __W, __mmask8 __M, __m128i __A,
- __m128i __B)
+_mm_mask_max_epi16(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_pmaxsw128_mask ((__v8hi) __A,
- (__v8hi) __B,
- (__v8hi) __W,
- (__mmask8) __M);
+ return (__m128i)__builtin_ia32_selectw_128((__mmask8)__M,
+ (__v8hi)_mm_max_epi16(__A, __B),
+ (__v8hi)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_max_epi16 (__mmask16 __M, __m256i __A, __m256i __B)
+_mm256_maskz_max_epi16(__mmask16 __M, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_pmaxsw256_mask ((__v16hi) __A,
- (__v16hi) __B,
- (__v16hi) _mm256_setzero_si256 (),
- (__mmask16) __M);
+ return (__m256i)__builtin_ia32_selectw_256((__mmask16)__M,
+ (__v16hi)_mm256_max_epi16(__A, __B),
+ (__v16hi)_mm256_setzero_si256());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_max_epi16 (__m256i __W, __mmask16 __M, __m256i __A,
- __m256i __B)
+_mm256_mask_max_epi16(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_pmaxsw256_mask ((__v16hi) __A,
- (__v16hi) __B,
- (__v16hi) __W,
- (__mmask16) __M);
+ return (__m256i)__builtin_ia32_selectw_256((__mmask16)__M,
+ (__v16hi)_mm256_max_epi16(__A, __B),
+ (__v16hi)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_max_epu8 (__mmask16 __M, __m128i __A, __m128i __B)
+_mm_maskz_max_epu8(__mmask16 __M, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_pmaxub128_mask ((__v16qi) __A,
- (__v16qi) __B,
- (__v16qi) _mm_setzero_si128 (),
- (__mmask16) __M);
+ return (__m128i)__builtin_ia32_selectb_128((__mmask16)__M,
+ (__v16qi)_mm_max_epu8(__A, __B),
+ (__v16qi)_mm_setzero_si128());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_max_epu8 (__m128i __W, __mmask16 __M, __m128i __A,
- __m128i __B)
+_mm_mask_max_epu8(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_pmaxub128_mask ((__v16qi) __A,
- (__v16qi) __B,
- (__v16qi) __W,
- (__mmask16) __M);
+ return (__m128i)__builtin_ia32_selectb_128((__mmask16)__M,
+ (__v16qi)_mm_max_epu8(__A, __B),
+ (__v16qi)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_maskz_max_epu8 (__mmask32 __M, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_pmaxub256_mask ((__v32qi) __A,
- (__v32qi) __B,
- (__v32qi) _mm256_setzero_si256 (),
- (__mmask32) __M);
+ return (__m256i)__builtin_ia32_selectb_256((__mmask32)__M,
+ (__v32qi)_mm256_max_epu8(__A, __B),
+ (__v32qi)_mm256_setzero_si256());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_max_epu8 (__m256i __W, __mmask32 __M, __m256i __A,
- __m256i __B)
+_mm256_mask_max_epu8(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_pmaxub256_mask ((__v32qi) __A,
- (__v32qi) __B,
- (__v32qi) __W,
- (__mmask32) __M);
+ return (__m256i)__builtin_ia32_selectb_256((__mmask32)__M,
+ (__v32qi)_mm256_max_epu8(__A, __B),
+ (__v32qi)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_max_epu16 (__mmask8 __M, __m128i __A, __m128i __B)
+_mm_maskz_max_epu16(__mmask8 __M, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_pmaxuw128_mask ((__v8hi) __A,
- (__v8hi) __B,
- (__v8hi) _mm_setzero_si128 (),
- (__mmask8) __M);
+ return (__m128i)__builtin_ia32_selectw_128((__mmask8)__M,
+ (__v8hi)_mm_max_epu16(__A, __B),
+ (__v8hi)_mm_setzero_si128());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_max_epu16 (__m128i __W, __mmask8 __M, __m128i __A,
- __m128i __B)
+_mm_mask_max_epu16(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_pmaxuw128_mask ((__v8hi) __A,
- (__v8hi) __B,
- (__v8hi) __W,
- (__mmask8) __M);
+ return (__m128i)__builtin_ia32_selectw_128((__mmask8)__M,
+ (__v8hi)_mm_max_epu16(__A, __B),
+ (__v8hi)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_max_epu16 (__mmask16 __M, __m256i __A, __m256i __B)
+_mm256_maskz_max_epu16(__mmask16 __M, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_pmaxuw256_mask ((__v16hi) __A,
- (__v16hi) __B,
- (__v16hi) _mm256_setzero_si256 (),
- (__mmask16) __M);
+ return (__m256i)__builtin_ia32_selectw_256((__mmask16)__M,
+ (__v16hi)_mm256_max_epu16(__A, __B),
+ (__v16hi)_mm256_setzero_si256());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_max_epu16 (__m256i __W, __mmask16 __M, __m256i __A,
- __m256i __B)
+_mm256_mask_max_epu16(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_pmaxuw256_mask ((__v16hi) __A,
- (__v16hi) __B,
- (__v16hi) __W,
- (__mmask16) __M);
+ return (__m256i)__builtin_ia32_selectw_256((__mmask16)__M,
+ (__v16hi)_mm256_max_epu16(__A, __B),
+ (__v16hi)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_min_epi8 (__mmask16 __M, __m128i __A, __m128i __B)
+_mm_maskz_min_epi8(__mmask16 __M, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_pminsb128_mask ((__v16qi) __A,
- (__v16qi) __B,
- (__v16qi) _mm_setzero_si128 (),
- (__mmask16) __M);
+ return (__m128i)__builtin_ia32_selectb_128((__mmask16)__M,
+ (__v16qi)_mm_min_epi8(__A, __B),
+ (__v16qi)_mm_setzero_si128());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_min_epi8 (__m128i __W, __mmask16 __M, __m128i __A,
- __m128i __B)
+_mm_mask_min_epi8(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_pminsb128_mask ((__v16qi) __A,
- (__v16qi) __B,
- (__v16qi) __W,
- (__mmask16) __M);
+ return (__m128i)__builtin_ia32_selectb_128((__mmask16)__M,
+ (__v16qi)_mm_min_epi8(__A, __B),
+ (__v16qi)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_min_epi8 (__mmask32 __M, __m256i __A, __m256i __B)
+_mm256_maskz_min_epi8(__mmask32 __M, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_pminsb256_mask ((__v32qi) __A,
- (__v32qi) __B,
- (__v32qi) _mm256_setzero_si256 (),
- (__mmask32) __M);
+ return (__m256i)__builtin_ia32_selectb_256((__mmask32)__M,
+ (__v32qi)_mm256_min_epi8(__A, __B),
+ (__v32qi)_mm256_setzero_si256());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_min_epi8 (__m256i __W, __mmask32 __M, __m256i __A,
- __m256i __B)
+_mm256_mask_min_epi8(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_pminsb256_mask ((__v32qi) __A,
- (__v32qi) __B,
- (__v32qi) __W,
- (__mmask32) __M);
+ return (__m256i)__builtin_ia32_selectb_256((__mmask32)__M,
+ (__v32qi)_mm256_min_epi8(__A, __B),
+ (__v32qi)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_min_epi16 (__mmask8 __M, __m128i __A, __m128i __B)
+_mm_maskz_min_epi16(__mmask8 __M, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_pminsw128_mask ((__v8hi) __A,
- (__v8hi) __B,
- (__v8hi) _mm_setzero_si128 (),
- (__mmask8) __M);
+ return (__m128i)__builtin_ia32_selectw_128((__mmask8)__M,
+ (__v8hi)_mm_min_epi16(__A, __B),
+ (__v8hi)_mm_setzero_si128());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_min_epi16 (__m128i __W, __mmask8 __M, __m128i __A,
- __m128i __B)
+_mm_mask_min_epi16(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_pminsw128_mask ((__v8hi) __A,
- (__v8hi) __B,
- (__v8hi) __W,
- (__mmask8) __M);
+ return (__m128i)__builtin_ia32_selectw_128((__mmask8)__M,
+ (__v8hi)_mm_min_epi16(__A, __B),
+ (__v8hi)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_min_epi16 (__mmask16 __M, __m256i __A, __m256i __B)
+_mm256_maskz_min_epi16(__mmask16 __M, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_pminsw256_mask ((__v16hi) __A,
- (__v16hi) __B,
- (__v16hi) _mm256_setzero_si256 (),
- (__mmask16) __M);
+ return (__m256i)__builtin_ia32_selectw_256((__mmask16)__M,
+ (__v16hi)_mm256_min_epi16(__A, __B),
+ (__v16hi)_mm256_setzero_si256());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_min_epi16 (__m256i __W, __mmask16 __M, __m256i __A,
- __m256i __B)
+_mm256_mask_min_epi16(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_pminsw256_mask ((__v16hi) __A,
- (__v16hi) __B,
- (__v16hi) __W,
- (__mmask16) __M);
+ return (__m256i)__builtin_ia32_selectw_256((__mmask16)__M,
+ (__v16hi)_mm256_min_epi16(__A, __B),
+ (__v16hi)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_min_epu8 (__mmask16 __M, __m128i __A, __m128i __B)
+_mm_maskz_min_epu8(__mmask16 __M, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_pminub128_mask ((__v16qi) __A,
- (__v16qi) __B,
- (__v16qi) _mm_setzero_si128 (),
- (__mmask16) __M);
+ return (__m128i)__builtin_ia32_selectb_128((__mmask16)__M,
+ (__v16qi)_mm_min_epu8(__A, __B),
+ (__v16qi)_mm_setzero_si128());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_min_epu8 (__m128i __W, __mmask16 __M, __m128i __A,
- __m128i __B)
+_mm_mask_min_epu8(__m128i __W, __mmask16 __M, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_pminub128_mask ((__v16qi) __A,
- (__v16qi) __B,
- (__v16qi) __W,
- (__mmask16) __M);
+ return (__m128i)__builtin_ia32_selectb_128((__mmask16)__M,
+ (__v16qi)_mm_min_epu8(__A, __B),
+ (__v16qi)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_maskz_min_epu8 (__mmask32 __M, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_pminub256_mask ((__v32qi) __A,
- (__v32qi) __B,
- (__v32qi) _mm256_setzero_si256 (),
- (__mmask32) __M);
+ return (__m256i)__builtin_ia32_selectb_256((__mmask32)__M,
+ (__v32qi)_mm256_min_epu8(__A, __B),
+ (__v32qi)_mm256_setzero_si256());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_min_epu8 (__m256i __W, __mmask32 __M, __m256i __A,
- __m256i __B)
+_mm256_mask_min_epu8(__m256i __W, __mmask32 __M, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_pminub256_mask ((__v32qi) __A,
- (__v32qi) __B,
- (__v32qi) __W,
- (__mmask32) __M);
+ return (__m256i)__builtin_ia32_selectb_256((__mmask32)__M,
+ (__v32qi)_mm256_min_epu8(__A, __B),
+ (__v32qi)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_min_epu16 (__mmask8 __M, __m128i __A, __m128i __B)
+_mm_maskz_min_epu16(__mmask8 __M, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_pminuw128_mask ((__v8hi) __A,
- (__v8hi) __B,
- (__v8hi) _mm_setzero_si128 (),
- (__mmask8) __M);
+ return (__m128i)__builtin_ia32_selectw_128((__mmask8)__M,
+ (__v8hi)_mm_min_epu16(__A, __B),
+ (__v8hi)_mm_setzero_si128());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_min_epu16 (__m128i __W, __mmask8 __M, __m128i __A,
- __m128i __B)
+_mm_mask_min_epu16(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_pminuw128_mask ((__v8hi) __A,
- (__v8hi) __B,
- (__v8hi) __W,
- (__mmask8) __M);
+ return (__m128i)__builtin_ia32_selectw_128((__mmask8)__M,
+ (__v8hi)_mm_min_epu16(__A, __B),
+ (__v8hi)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_min_epu16 (__mmask16 __M, __m256i __A, __m256i __B)
+_mm256_maskz_min_epu16(__mmask16 __M, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_pminuw256_mask ((__v16hi) __A,
- (__v16hi) __B,
- (__v16hi) _mm256_setzero_si256 (),
- (__mmask16) __M);
+ return (__m256i)__builtin_ia32_selectw_256((__mmask16)__M,
+ (__v16hi)_mm256_min_epu16(__A, __B),
+ (__v16hi)_mm256_setzero_si256());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_min_epu16 (__m256i __W, __mmask16 __M, __m256i __A,
- __m256i __B)
+_mm256_mask_min_epu16(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_pminuw256_mask ((__v16hi) __A,
- (__v16hi) __B,
- (__v16hi) __W,
- (__mmask16) __M);
+ return (__m256i)__builtin_ia32_selectw_256((__mmask16)__M,
+ (__v16hi)_mm256_min_epu16(__A, __B),
+ (__v16hi)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_shuffle_epi8 (__m128i __W, __mmask16 __U, __m128i __A,
- __m128i __B)
+_mm_mask_shuffle_epi8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_pshufb128_mask ((__v16qi) __A,
- (__v16qi) __B,
- (__v16qi) __W,
- (__mmask16) __U);
+ return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U,
+ (__v16qi)_mm_shuffle_epi8(__A, __B),
+ (__v16qi)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_shuffle_epi8 (__mmask16 __U, __m128i __A, __m128i __B)
+_mm_maskz_shuffle_epi8(__mmask16 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_pshufb128_mask ((__v16qi) __A,
- (__v16qi) __B,
- (__v16qi) _mm_setzero_si128 (),
- (__mmask16) __U);
+ return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U,
+ (__v16qi)_mm_shuffle_epi8(__A, __B),
+ (__v16qi)_mm_setzero_si128());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_shuffle_epi8 (__m256i __W, __mmask32 __U, __m256i __A,
- __m256i __B)
+_mm256_mask_shuffle_epi8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_pshufb256_mask ((__v32qi) __A,
- (__v32qi) __B,
- (__v32qi) __W,
- (__mmask32) __U);
+ return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U,
+ (__v32qi)_mm256_shuffle_epi8(__A, __B),
+ (__v32qi)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_shuffle_epi8 (__mmask32 __U, __m256i __A, __m256i __B)
+_mm256_maskz_shuffle_epi8(__mmask32 __U, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_pshufb256_mask ((__v32qi) __A,
- (__v32qi) __B,
- (__v32qi) _mm256_setzero_si256 (),
- (__mmask32) __U);
+ return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U,
+ (__v32qi)_mm256_shuffle_epi8(__A, __B),
+ (__v32qi)_mm256_setzero_si256());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_subs_epi8 (__m128i __W, __mmask16 __U, __m128i __A,
- __m128i __B)
+_mm_mask_subs_epi8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_psubsb128_mask ((__v16qi) __A,
- (__v16qi) __B,
- (__v16qi) __W,
- (__mmask16) __U);
+ return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U,
+ (__v16qi)_mm_subs_epi8(__A, __B),
+ (__v16qi)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_subs_epi8 (__mmask16 __U, __m128i __A, __m128i __B)
+_mm_maskz_subs_epi8(__mmask16 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_psubsb128_mask ((__v16qi) __A,
- (__v16qi) __B,
- (__v16qi) _mm_setzero_si128 (),
- (__mmask16) __U);
+ return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U,
+ (__v16qi)_mm_subs_epi8(__A, __B),
+ (__v16qi)_mm_setzero_si128());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_subs_epi8 (__m256i __W, __mmask32 __U, __m256i __A,
- __m256i __B)
+_mm256_mask_subs_epi8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_psubsb256_mask ((__v32qi) __A,
- (__v32qi) __B,
- (__v32qi) __W,
- (__mmask32) __U);
+ return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U,
+ (__v32qi)_mm256_subs_epi8(__A, __B),
+ (__v32qi)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_subs_epi8 (__mmask32 __U, __m256i __A, __m256i __B)
+_mm256_maskz_subs_epi8(__mmask32 __U, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_psubsb256_mask ((__v32qi) __A,
- (__v32qi) __B,
- (__v32qi) _mm256_setzero_si256 (),
- (__mmask32) __U);
+ return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U,
+ (__v32qi)_mm256_subs_epi8(__A, __B),
+ (__v32qi)_mm256_setzero_si256());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_subs_epi16 (__m128i __W, __mmask8 __U, __m128i __A,
- __m128i __B)
+_mm_mask_subs_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_psubsw128_mask ((__v8hi) __A,
- (__v8hi) __B,
- (__v8hi) __W,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
+ (__v8hi)_mm_subs_epi16(__A, __B),
+ (__v8hi)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_subs_epi16 (__mmask8 __U, __m128i __A, __m128i __B)
+_mm_maskz_subs_epi16(__mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_psubsw128_mask ((__v8hi) __A,
- (__v8hi) __B,
- (__v8hi) _mm_setzero_si128 (),
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
+ (__v8hi)_mm_subs_epi16(__A, __B),
+ (__v8hi)_mm_setzero_si128());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_subs_epi16 (__m256i __W, __mmask16 __U, __m256i __A,
- __m256i __B)
+_mm256_mask_subs_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_psubsw256_mask ((__v16hi) __A,
- (__v16hi) __B,
- (__v16hi) __W,
- (__mmask16) __U);
+ return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
+ (__v16hi)_mm256_subs_epi16(__A, __B),
+ (__v16hi)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_subs_epi16 (__mmask16 __U, __m256i __A, __m256i __B)
+_mm256_maskz_subs_epi16(__mmask16 __U, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_psubsw256_mask ((__v16hi) __A,
- (__v16hi) __B,
- (__v16hi) _mm256_setzero_si256 (),
- (__mmask16) __U);
+ return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
+ (__v16hi)_mm256_subs_epi16(__A, __B),
+ (__v16hi)_mm256_setzero_si256());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_subs_epu8 (__m128i __W, __mmask16 __U, __m128i __A,
- __m128i __B)
+_mm_mask_subs_epu8(__m128i __W, __mmask16 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_psubusb128_mask ((__v16qi) __A,
- (__v16qi) __B,
- (__v16qi) __W,
- (__mmask16) __U);
+ return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U,
+ (__v16qi)_mm_subs_epu8(__A, __B),
+ (__v16qi)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_subs_epu8 (__mmask16 __U, __m128i __A, __m128i __B)
+_mm_maskz_subs_epu8(__mmask16 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_psubusb128_mask ((__v16qi) __A,
- (__v16qi) __B,
- (__v16qi) _mm_setzero_si128 (),
- (__mmask16) __U);
+ return (__m128i)__builtin_ia32_selectb_128((__mmask16)__U,
+ (__v16qi)_mm_subs_epu8(__A, __B),
+ (__v16qi)_mm_setzero_si128());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_subs_epu8 (__m256i __W, __mmask32 __U, __m256i __A,
- __m256i __B)
+_mm256_mask_subs_epu8(__m256i __W, __mmask32 __U, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_psubusb256_mask ((__v32qi) __A,
- (__v32qi) __B,
- (__v32qi) __W,
- (__mmask32) __U);
+ return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U,
+ (__v32qi)_mm256_subs_epu8(__A, __B),
+ (__v32qi)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_subs_epu8 (__mmask32 __U, __m256i __A, __m256i __B)
+_mm256_maskz_subs_epu8(__mmask32 __U, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_psubusb256_mask ((__v32qi) __A,
- (__v32qi) __B,
- (__v32qi) _mm256_setzero_si256 (),
- (__mmask32) __U);
+ return (__m256i)__builtin_ia32_selectb_256((__mmask32)__U,
+ (__v32qi)_mm256_subs_epu8(__A, __B),
+ (__v32qi)_mm256_setzero_si256());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_subs_epu16 (__m128i __W, __mmask8 __U, __m128i __A,
- __m128i __B)
+_mm_mask_subs_epu16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_psubusw128_mask ((__v8hi) __A,
- (__v8hi) __B,
- (__v8hi) __W,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
+ (__v8hi)_mm_subs_epu16(__A, __B),
+ (__v8hi)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_subs_epu16 (__mmask8 __U, __m128i __A, __m128i __B)
+_mm_maskz_subs_epu16(__mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_psubusw128_mask ((__v8hi) __A,
- (__v8hi) __B,
- (__v8hi) _mm_setzero_si128 (),
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
+ (__v8hi)_mm_subs_epu16(__A, __B),
+ (__v8hi)_mm_setzero_si128());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_subs_epu16 (__m256i __W, __mmask16 __U, __m256i __A,
- __m256i __B)
-{
- return (__m256i) __builtin_ia32_psubusw256_mask ((__v16hi) __A,
- (__v16hi) __B,
- (__v16hi) __W,
- (__mmask16) __U);
+_mm256_mask_subs_epu16(__m256i __W, __mmask16 __U, __m256i __A,
+ __m256i __B) {
+ return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
+ (__v16hi)_mm256_subs_epu16(__A, __B),
+ (__v16hi)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_subs_epu16 (__mmask16 __U, __m256i __A, __m256i __B)
+_mm256_maskz_subs_epu16(__mmask16 __U, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_psubusw256_mask ((__v16hi) __A,
- (__v16hi) __B,
- (__v16hi) _mm256_setzero_si256 (),
- (__mmask16) __U);
+ return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
+ (__v16hi)_mm256_subs_epu16(__A, __B),
+ (__v16hi)_mm256_setzero_si256());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
@@ -1828,69 +1664,60 @@ _mm256_maskz_permutex2var_epi16 (__mmask16 __U, __m256i __A,
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_maddubs_epi16 (__m128i __W, __mmask8 __U, __m128i __X, __m128i __Y) {
- return (__m128i) __builtin_ia32_pmaddubsw128_mask ((__v16qi) __X,
- (__v16qi) __Y,
- (__v8hi) __W,
- (__mmask8) __U);
+_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
-_mm_maskz_maddubs_epi16 (__mmask8 __U, __m128i __X, __m128i __Y) {
- return (__m128i) __builtin_ia32_pmaddubsw128_mask ((__v16qi) __X,
- (__v16qi) __Y,
- (__v8hi) _mm_setzero_si128(),
- (__mmask8) __U);
+_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
-_mm256_mask_maddubs_epi16 (__m256i __W, __mmask16 __U, __m256i __X,
- __m256i __Y) {
- return (__m256i) __builtin_ia32_pmaddubsw256_mask ((__v32qi) __X,
- (__v32qi) __Y,
- (__v16hi) __W,
- (__mmask16) __U);
+_mm256_mask_maddubs_epi16(__m256i __W, __mmask16 __U, __m256i __X,
+ __m256i __Y) {
+ return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
+ (__v16hi)_mm256_maddubs_epi16(__X, __Y),
+ (__v16hi)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_maddubs_epi16 (__mmask16 __U, __m256i __X, __m256i __Y) {
- return (__m256i) __builtin_ia32_pmaddubsw256_mask ((__v32qi) __X,
- (__v32qi) __Y,
- (__v16hi) _mm256_setzero_si256(),
- (__mmask16) __U);
+_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
-_mm_mask_madd_epi16 (__m128i __W, __mmask8 __U, __m128i __A,
- __m128i __B) {
- return (__m128i) __builtin_ia32_pmaddwd128_mask ((__v8hi) __A,
- (__v8hi) __B,
- (__v4si) __W,
- (__mmask8) __U);
+_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
-_mm_maskz_madd_epi16 (__mmask8 __U, __m128i __A, __m128i __B) {
- return (__m128i) __builtin_ia32_pmaddwd128_mask ((__v8hi) __A,
- (__v8hi) __B,
- (__v4si) _mm_setzero_si128(),
- (__mmask8) __U);
+_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
-_mm256_mask_madd_epi16 (__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) {
- return (__m256i) __builtin_ia32_pmaddwd256_mask ((__v16hi) __A,
- (__v16hi) __B,
- (__v8si) __W,
- (__mmask8) __U);
+_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
-_mm256_maskz_madd_epi16 (__mmask8 __U, __m256i __A, __m256i __B) {
- return (__m256i) __builtin_ia32_pmaddwd256_mask ((__v16hi) __A,
- (__v16hi) __B,
- (__v8si) _mm256_setzero_si256(),
- (__mmask8) __U);
+_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
@@ -2056,104 +1883,89 @@ _mm256_mask_cvtusepi16_storeu_epi8 (void * __P, __mmask8 __M, __m256i __A)
{
__builtin_ia32_pmovuswb256mem_mask ((__v16qi*) __P, (__v16hi) __A, __M);
}
+
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_mulhrs_epi16 (__m128i __W, __mmask8 __U, __m128i __X, __m128i __Y) {
- return (__m128i) __builtin_ia32_pmulhrsw128_mask ((__v8hi) __X,
- (__v8hi) __Y,
- (__v8hi) __W,
- (__mmask8) __U);
+_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
-_mm_maskz_mulhrs_epi16 (__mmask8 __U, __m128i __X, __m128i __Y) {
- return (__m128i) __builtin_ia32_pmulhrsw128_mask ((__v8hi) __X,
- (__v8hi) __Y,
- (__v8hi) _mm_setzero_si128(),
- (__mmask8) __U);
+_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
-_mm256_mask_mulhrs_epi16 (__m256i __W, __mmask16 __U, __m256i __X, __m256i __Y) {
- return (__m256i) __builtin_ia32_pmulhrsw256_mask ((__v16hi) __X,
- (__v16hi) __Y,
- (__v16hi) __W,
- (__mmask16) __U);
+_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
-_mm256_maskz_mulhrs_epi16 (__mmask16 __U, __m256i __X, __m256i __Y) {
- return (__m256i) __builtin_ia32_pmulhrsw256_mask ((__v16hi) __X,
- (__v16hi) __Y,
- (__v16hi) _mm256_setzero_si256(),
- (__mmask16) __U);
+_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
-_mm_mask_mulhi_epu16 (__m128i __W, __mmask8 __U, __m128i __A,
- __m128i __B) {
- return (__m128i) __builtin_ia32_pmulhuw128_mask ((__v8hi) __A,
- (__v8hi) __B,
- (__v8hi) __W,
- (__mmask8) __U);
+_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
-_mm_maskz_mulhi_epu16 (__mmask8 __U, __m128i __A, __m128i __B) {
- return (__m128i) __builtin_ia32_pmulhuw128_mask ((__v8hi) __A,
- (__v8hi) __B,
- (__v8hi) _mm_setzero_si128(),
- (__mmask8) __U);
+_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
-_mm256_mask_mulhi_epu16 (__m256i __W, __mmask16 __U, __m256i __A,
- __m256i __B) {
- return (__m256i) __builtin_ia32_pmulhuw256_mask ((__v16hi) __A,
- (__v16hi) __B,
- (__v16hi) __W,
- (__mmask16) __U);
+_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
-_mm256_maskz_mulhi_epu16 (__mmask16 __U, __m256i __A, __m256i __B) {
- return (__m256i) __builtin_ia32_pmulhuw256_mask ((__v16hi) __A,
- (__v16hi) __B,
- (__v16hi) _mm256_setzero_si256(),
- (__mmask16) __U);
+_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
-_mm_mask_mulhi_epi16 (__m128i __W, __mmask8 __U, __m128i __A,
- __m128i __B) {
- return (__m128i) __builtin_ia32_pmulhw128_mask ((__v8hi) __A,
- (__v8hi) __B,
- (__v8hi) __W,
- (__mmask8) __U);
+_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
-_mm_maskz_mulhi_epi16 (__mmask8 __U, __m128i __A, __m128i __B) {
- return (__m128i) __builtin_ia32_pmulhw128_mask ((__v8hi) __A,
- (__v8hi) __B,
- (__v8hi) _mm_setzero_si128(),
- (__mmask8) __U);
+_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
-_mm256_mask_mulhi_epi16 (__m256i __W, __mmask16 __U, __m256i __A,
- __m256i __B) {
- return (__m256i) __builtin_ia32_pmulhw256_mask ((__v16hi) __A,
- (__v16hi) __B,
- (__v16hi) __W,
- (__mmask16) __U);
+_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
-_mm256_maskz_mulhi_epi16 (__mmask16 __U, __m256i __A, __m256i __B) {
- return (__m256i) __builtin_ia32_pmulhw256_mask ((__v16hi) __A,
- (__v16hi) __B,
- (__v16hi) _mm256_setzero_si256(),
- (__mmask16) __U);
+_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
@@ -2269,72 +2081,68 @@ _mm256_maskz_unpacklo_epi16(__mmask16 __U, __m256i __A, __m256i __B) {
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_cvtepi8_epi16 (__m128i __W, __mmask32 __U, __m128i __A)
+_mm_mask_cvtepi8_epi16(__m128i __W, __mmask8 __U, __m128i __A)
{
- return (__m128i) __builtin_ia32_pmovsxbw128_mask ((__v16qi) __A,
- (__v8hi) __W,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
+ (__v8hi)_mm_cvtepi8_epi16(__A),
+ (__v8hi)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_cvtepi8_epi16 (__mmask8 __U, __m128i __A)
+_mm_maskz_cvtepi8_epi16(__mmask8 __U, __m128i __A)
{
- return (__m128i) __builtin_ia32_pmovsxbw128_mask ((__v16qi) __A,
- (__v8hi)
- _mm_setzero_si128 (),
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
+ (__v8hi)_mm_cvtepi8_epi16(__A),
+ (__v8hi)_mm_setzero_si128());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_cvtepi8_epi16 (__m256i __W, __mmask32 __U, __m128i __A)
+_mm256_mask_cvtepi8_epi16(__m256i __W, __mmask16 __U, __m128i __A)
{
- return (__m256i) __builtin_ia32_pmovsxbw256_mask ((__v16qi) __A,
- (__v16hi) __W,
- (__mmask16) __U);
+ return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
+ (__v16hi)_mm256_cvtepi8_epi16(__A),
+ (__v16hi)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_cvtepi8_epi16 (__mmask16 __U, __m128i __A)
+_mm256_maskz_cvtepi8_epi16(__mmask16 __U, __m128i __A)
{
- return (__m256i) __builtin_ia32_pmovsxbw256_mask ((__v16qi) __A,
- (__v16hi)
- _mm256_setzero_si256 (),
- (__mmask16) __U);
+ return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
+ (__v16hi)_mm256_cvtepi8_epi16(__A),
+ (__v16hi)_mm256_setzero_si256());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_cvtepu8_epi16 (__m128i __W, __mmask32 __U, __m128i __A)
+_mm_mask_cvtepu8_epi16(__m128i __W, __mmask8 __U, __m128i __A)
{
- return (__m128i) __builtin_ia32_pmovzxbw128_mask ((__v16qi) __A,
- (__v8hi) __W,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
+ (__v8hi)_mm_cvtepu8_epi16(__A),
+ (__v8hi)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_cvtepu8_epi16 (__mmask8 __U, __m128i __A)
+_mm_maskz_cvtepu8_epi16(__mmask8 __U, __m128i __A)
{
- return (__m128i) __builtin_ia32_pmovzxbw128_mask ((__v16qi) __A,
- (__v8hi)
- _mm_setzero_si128 (),
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
+ (__v8hi)_mm_cvtepu8_epi16(__A),
+ (__v8hi)_mm_setzero_si128());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_cvtepu8_epi16 (__m256i __W, __mmask32 __U, __m128i __A)
+_mm256_mask_cvtepu8_epi16(__m256i __W, __mmask16 __U, __m128i __A)
{
- return (__m256i) __builtin_ia32_pmovzxbw256_mask ((__v16qi) __A,
- (__v16hi) __W,
- (__mmask16) __U);
+ return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
+ (__v16hi)_mm256_cvtepu8_epi16(__A),
+ (__v16hi)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_maskz_cvtepu8_epi16 (__mmask16 __U, __m128i __A)
{
- return (__m256i) __builtin_ia32_pmovzxbw256_mask ((__v16qi) __A,
- (__v16hi)
- _mm256_setzero_si256 (),
- (__mmask16) __U);
+ return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
+ (__v16hi)_mm256_cvtepu8_epi16(__A),
+ (__v16hi)_mm256_setzero_si256());
}
@@ -2461,366 +2269,328 @@ _mm256_maskz_cvtepu8_epi16 (__mmask16 __U, __m128i __A)
(__v16hi)_mm256_setzero_si256()); })
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_sllv_epi16 (__m256i __A, __m256i __B)
+_mm256_sllv_epi16(__m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_psllv16hi_mask ((__v16hi) __A,
- (__v16hi) __B,
- (__v16hi)
- _mm256_setzero_si256 (),
- (__mmask16) -1);
+ return (__m256i)__builtin_ia32_psllv16hi((__v16hi)__A, (__v16hi)__B);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_sllv_epi16 (__m256i __W, __mmask16 __U, __m256i __A,
- __m256i __B)
+_mm256_mask_sllv_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_psllv16hi_mask ((__v16hi) __A,
- (__v16hi) __B,
- (__v16hi) __W,
- (__mmask16) __U);
+ return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
+ (__v16hi)_mm256_sllv_epi16(__A, __B),
+ (__v16hi)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_sllv_epi16 (__mmask16 __U, __m256i __A, __m256i __B)
+_mm256_maskz_sllv_epi16(__mmask16 __U, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_psllv16hi_mask ((__v16hi) __A,
- (__v16hi) __B,
- (__v16hi)
- _mm256_setzero_si256 (),
- (__mmask16) __U);
+ return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
+ (__v16hi)_mm256_sllv_epi16(__A, __B),
+ (__v16hi)_mm256_setzero_si256());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_sllv_epi16 (__m128i __A, __m128i __B)
+_mm_sllv_epi16(__m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_psllv8hi_mask ((__v8hi) __A,
- (__v8hi) __B,
- (__v8hi)
- _mm_setzero_hi (),
- (__mmask8) -1);
+ return (__m128i)__builtin_ia32_psllv8hi((__v8hi)__A, (__v8hi)__B);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_sllv_epi16 (__m128i __W, __mmask8 __U, __m128i __A,
- __m128i __B)
+_mm_mask_sllv_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_psllv8hi_mask ((__v8hi) __A,
- (__v8hi) __B,
- (__v8hi) __W,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
+ (__v8hi)_mm_sllv_epi16(__A, __B),
+ (__v8hi)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_sllv_epi16 (__mmask8 __U, __m128i __A, __m128i __B)
+_mm_maskz_sllv_epi16(__mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_psllv8hi_mask ((__v8hi) __A,
- (__v8hi) __B,
- (__v8hi)
- _mm_setzero_si128 (),
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
+ (__v8hi)_mm_sllv_epi16(__A, __B),
+ (__v8hi)_mm_setzero_si128());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_sll_epi16 (__m128i __W, __mmask8 __U, __m128i __A,
- __m128i __B)
+_mm_mask_sll_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_psllw128_mask ((__v8hi) __A,
- (__v8hi) __B,
- (__v8hi) __W,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
+ (__v8hi)_mm_sll_epi16(__A, __B),
+ (__v8hi)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_maskz_sll_epi16 (__mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_psllw128_mask ((__v8hi) __A,
- (__v8hi) __B,
- (__v8hi)
- _mm_setzero_si128 (),
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
+ (__v8hi)_mm_sll_epi16(__A, __B),
+ (__v8hi)_mm_setzero_si128());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_sll_epi16 (__m256i __W, __mmask16 __U, __m256i __A,
- __m128i __B)
+_mm256_mask_sll_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m128i __B)
{
- return (__m256i) __builtin_ia32_psllw256_mask ((__v16hi) __A,
- (__v8hi) __B,
- (__v16hi) __W,
- (__mmask16) __U);
+ return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
+ (__v16hi)_mm256_sll_epi16(__A, __B),
+ (__v16hi)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_sll_epi16 (__mmask16 __U, __m256i __A, __m128i __B)
+_mm256_maskz_sll_epi16(__mmask16 __U, __m256i __A, __m128i __B)
{
- return (__m256i) __builtin_ia32_psllw256_mask ((__v16hi) __A,
- (__v8hi) __B,
- (__v16hi)
- _mm256_setzero_si256 (),
- (__mmask16) __U);
+ return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
+ (__v16hi)_mm256_sll_epi16(__A, __B),
+ (__v16hi)_mm256_setzero_si256());
}
-#define _mm_mask_slli_epi16(W, U, A, B) __extension__ ({ \
- (__m128i)__builtin_ia32_psllwi128_mask((__v8hi)(__m128i)(A), (int)(B), \
- (__v8hi)(__m128i)(W), \
- (__mmask8)(U)); })
-
-#define _mm_maskz_slli_epi16(U, A, B) __extension__ ({ \
- (__m128i)__builtin_ia32_psllwi128_mask((__v8hi)(__m128i)(A), (int)(B), \
- (__v8hi)_mm_setzero_si128(), \
- (__mmask8)(U)); })
-
-#define _mm256_mask_slli_epi16(W, U, A, B) __extension__ ({ \
- (__m256i)__builtin_ia32_psllwi256_mask((__v16hi)(__m256i)(A), (int)(B), \
- (__v16hi)(__m256i)(W), \
- (__mmask16)(U)); })
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_slli_epi16(__m128i __W, __mmask8 __U, __m128i __A, int __B)
+{
+ return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
+ (__v8hi)_mm_slli_epi16(__A, __B),
+ (__v8hi)__W);
+}
-#define _mm256_maskz_slli_epi16(U, A, B) __extension__ ({ \
- (__m256i)__builtin_ia32_psllwi256_mask((__v16hi)(__m256i)(A), (int)(B), \
- (__v16hi)_mm256_setzero_si256(), \
- (__mmask16)(U)); })
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_slli_epi16 (__mmask8 __U, __m128i __A, int __B)
+{
+ return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
+ (__v8hi)_mm_slli_epi16(__A, __B),
+ (__v8hi)_mm_setzero_si128());
+}
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_slli_epi16(__m256i __W, __mmask16 __U, __m256i __A, int __B)
+{
+ return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
+ (__v16hi)_mm256_slli_epi16(__A, __B),
+ (__v16hi)__W);
+}
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_slli_epi16(__mmask16 __U, __m256i __A, int __B)
+{
+ return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
+ (__v16hi)_mm256_slli_epi16(__A, __B),
+ (__v16hi)_mm256_setzero_si256());
+}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_srlv_epi16 (__m256i __A, __m256i __B)
+_mm256_srlv_epi16(__m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_psrlv16hi_mask ((__v16hi) __A,
- (__v16hi) __B,
- (__v16hi)
- _mm256_setzero_si256 (),
- (__mmask16) -1);
+ return (__m256i)__builtin_ia32_psrlv16hi((__v16hi)__A, (__v16hi)__B);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_srlv_epi16 (__m256i __W, __mmask16 __U, __m256i __A,
- __m256i __B)
+_mm256_mask_srlv_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_psrlv16hi_mask ((__v16hi) __A,
- (__v16hi) __B,
- (__v16hi) __W,
- (__mmask16) __U);
+ return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
+ (__v16hi)_mm256_srlv_epi16(__A, __B),
+ (__v16hi)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_srlv_epi16 (__mmask16 __U, __m256i __A, __m256i __B)
+_mm256_maskz_srlv_epi16(__mmask16 __U, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_psrlv16hi_mask ((__v16hi) __A,
- (__v16hi) __B,
- (__v16hi)
- _mm256_setzero_si256 (),
- (__mmask16) __U);
+ return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
+ (__v16hi)_mm256_srlv_epi16(__A, __B),
+ (__v16hi)_mm256_setzero_si256());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_srlv_epi16 (__m128i __A, __m128i __B)
+_mm_srlv_epi16(__m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_psrlv8hi_mask ((__v8hi) __A,
- (__v8hi) __B,
- (__v8hi)
- _mm_setzero_hi (),
- (__mmask8) -1);
+ return (__m128i)__builtin_ia32_psrlv8hi((__v8hi)__A, (__v8hi)__B);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_srlv_epi16 (__m128i __W, __mmask8 __U, __m128i __A,
- __m128i __B)
+_mm_mask_srlv_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_psrlv8hi_mask ((__v8hi) __A,
- (__v8hi) __B,
- (__v8hi) __W,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
+ (__v8hi)_mm_srlv_epi16(__A, __B),
+ (__v8hi)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_srlv_epi16 (__mmask8 __U, __m128i __A, __m128i __B)
+_mm_maskz_srlv_epi16(__mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_psrlv8hi_mask ((__v8hi) __A,
- (__v8hi) __B,
- (__v8hi)
- _mm_setzero_si128 (),
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
+ (__v8hi)_mm_srlv_epi16(__A, __B),
+ (__v8hi)_mm_setzero_si128());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_srav_epi16 (__m256i __A, __m256i __B)
+_mm256_srav_epi16(__m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_psrav16hi_mask ((__v16hi) __A,
- (__v16hi) __B,
- (__v16hi)
- _mm256_setzero_si256 (),
- (__mmask16) -1);
+ return (__m256i)__builtin_ia32_psrav16hi((__v16hi)__A, (__v16hi)__B);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_srav_epi16 (__m256i __W, __mmask16 __U, __m256i __A,
- __m256i __B)
+_mm256_mask_srav_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_psrav16hi_mask ((__v16hi) __A,
- (__v16hi) __B,
- (__v16hi) __W,
- (__mmask16) __U);
+ return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
+ (__v16hi)_mm256_srav_epi16(__A, __B),
+ (__v16hi)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_srav_epi16 (__mmask16 __U, __m256i __A, __m256i __B)
+_mm256_maskz_srav_epi16(__mmask16 __U, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_psrav16hi_mask ((__v16hi) __A,
- (__v16hi) __B,
- (__v16hi)
- _mm256_setzero_si256 (),
- (__mmask16) __U);
+ return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
+ (__v16hi)_mm256_srav_epi16(__A, __B),
+ (__v16hi)_mm256_setzero_si256());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_srav_epi16 (__m128i __A, __m128i __B)
+_mm_srav_epi16(__m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_psrav8hi_mask ((__v8hi) __A,
- (__v8hi) __B,
- (__v8hi)
- _mm_setzero_hi (),
- (__mmask8) -1);
+ return (__m128i)__builtin_ia32_psrav8hi((__v8hi)__A, (__v8hi)__B);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_srav_epi16 (__m128i __W, __mmask8 __U, __m128i __A,
- __m128i __B)
+_mm_mask_srav_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_psrav8hi_mask ((__v8hi) __A,
- (__v8hi) __B,
- (__v8hi) __W,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
+ (__v8hi)_mm_srav_epi16(__A, __B),
+ (__v8hi)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_srav_epi16 (__mmask8 __U, __m128i __A, __m128i __B)
+_mm_maskz_srav_epi16(__mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_psrav8hi_mask ((__v8hi) __A,
- (__v8hi) __B,
- (__v8hi)
- _mm_setzero_si128 (),
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
+ (__v8hi)_mm_srav_epi16(__A, __B),
+ (__v8hi)_mm_setzero_si128());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_sra_epi16 (__m128i __W, __mmask8 __U, __m128i __A,
- __m128i __B)
+_mm_mask_sra_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_psraw128_mask ((__v8hi) __A,
- (__v8hi) __B,
- (__v8hi) __W,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
+ (__v8hi)_mm_sra_epi16(__A, __B),
+ (__v8hi)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_sra_epi16 (__mmask8 __U, __m128i __A, __m128i __B)
+_mm_maskz_sra_epi16(__mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_psraw128_mask ((__v8hi) __A,
- (__v8hi) __B,
- (__v8hi)
- _mm_setzero_si128 (),
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
+ (__v8hi)_mm_sra_epi16(__A, __B),
+ (__v8hi)_mm_setzero_si128());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_sra_epi16 (__m256i __W, __mmask16 __U, __m256i __A,
- __m128i __B)
+_mm256_mask_sra_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m128i __B)
{
- return (__m256i) __builtin_ia32_psraw256_mask ((__v16hi) __A,
- (__v8hi) __B,
- (__v16hi) __W,
- (__mmask16) __U);
+ return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
+ (__v16hi)_mm256_sra_epi16(__A, __B),
+ (__v16hi)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_sra_epi16 (__mmask16 __U, __m256i __A, __m128i __B)
+_mm256_maskz_sra_epi16(__mmask16 __U, __m256i __A, __m128i __B)
{
- return (__m256i) __builtin_ia32_psraw256_mask ((__v16hi) __A,
- (__v8hi) __B,
- (__v16hi)
- _mm256_setzero_si256 (),
- (__mmask16) __U);
+ return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
+ (__v16hi)_mm256_sra_epi16(__A, __B),
+ (__v16hi)_mm256_setzero_si256());
}
-#define _mm_mask_srai_epi16(W, U, A, imm) __extension__ ({ \
- (__m128i)__builtin_ia32_psrawi128_mask((__v8hi)(__m128i)(A), (int)(imm), \
- (__v8hi)(__m128i)(W), \
- (__mmask8)(U)); })
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_srai_epi16(__m128i __W, __mmask8 __U, __m128i __A, int __B)
+{
+ return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
+ (__v8hi)_mm_srai_epi16(__A, __B),
+ (__v8hi)__W);
+}
-#define _mm_maskz_srai_epi16(U, A, imm) __extension__ ({ \
- (__m128i)__builtin_ia32_psrawi128_mask((__v8hi)(__m128i)(A), (int)(imm), \
- (__v8hi)_mm_setzero_si128(), \
- (__mmask8)(U)); })
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_srai_epi16(__mmask8 __U, __m128i __A, int __B)
+{
+ return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
+ (__v8hi)_mm_srai_epi16(__A, __B),
+ (__v8hi)_mm_setzero_si128());
+}
-#define _mm256_mask_srai_epi16(W, U, A, imm) __extension__ ({ \
- (__m256i)__builtin_ia32_psrawi256_mask((__v16hi)(__m256i)(A), (int)(imm), \
- (__v16hi)(__m256i)(W), \
- (__mmask16)(U)); })
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_srai_epi16(__m256i __W, __mmask16 __U, __m256i __A, int __B)
+{
+ return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
+ (__v16hi)_mm256_srai_epi16(__A, __B),
+ (__v16hi)__W);
+}
-#define _mm256_maskz_srai_epi16(U, A, imm) __extension__ ({ \
- (__m256i)__builtin_ia32_psrawi256_mask((__v16hi)(__m256i)(A), (int)(imm), \
- (__v16hi)_mm256_setzero_si256(), \
- (__mmask16)(U)); })
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_srai_epi16(__mmask16 __U, __m256i __A, int __B)
+{
+ return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
+ (__v16hi)_mm256_srai_epi16(__A, __B),
+ (__v16hi)_mm256_setzero_si256());
+}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_srl_epi16 (__m128i __W, __mmask8 __U, __m128i __A,
- __m128i __B)
+_mm_mask_srl_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_psrlw128_mask ((__v8hi) __A,
- (__v8hi) __B,
- (__v8hi) __W,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
+ (__v8hi)_mm_srl_epi16(__A, __B),
+ (__v8hi)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_maskz_srl_epi16 (__mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_psrlw128_mask ((__v8hi) __A,
- (__v8hi) __B,
- (__v8hi)
- _mm_setzero_si128 (),
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
+ (__v8hi)_mm_srl_epi16(__A, __B),
+ (__v8hi)_mm_setzero_si128());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_srl_epi16 (__m256i __W, __mmask16 __U, __m256i __A,
- __m128i __B)
+_mm256_mask_srl_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m128i __B)
{
- return (__m256i) __builtin_ia32_psrlw256_mask ((__v16hi) __A,
- (__v8hi) __B,
- (__v16hi) __W,
- (__mmask16) __U);
+ return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
+ (__v16hi)_mm256_srl_epi16(__A, __B),
+ (__v16hi)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_srl_epi16 (__mmask16 __U, __m256i __A, __m128i __B)
+_mm256_maskz_srl_epi16(__mmask16 __U, __m256i __A, __m128i __B)
{
- return (__m256i) __builtin_ia32_psrlw256_mask ((__v16hi) __A,
- (__v8hi) __B,
- (__v16hi)
- _mm256_setzero_si256 (),
- (__mmask16) __U);
+ return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
+ (__v16hi)_mm256_srl_epi16(__A, __B),
+ (__v16hi)_mm256_setzero_si256());
}
-#define _mm_mask_srli_epi16(W, U, A, imm) __extension__ ({ \
- (__m128i)__builtin_ia32_psrlwi128_mask((__v8hi)(__m128i)(A), (int)(imm), \
- (__v8hi)(__m128i)(W), \
- (__mmask8)(U)); })
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_srli_epi16(__m128i __W, __mmask8 __U, __m128i __A, int __B)
+{
+ return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
+ (__v8hi)_mm_srli_epi16(__A, __B),
+ (__v8hi)__W);
+}
-#define _mm_maskz_srli_epi16(U, A, imm) __extension__ ({ \
- (__m128i)__builtin_ia32_psrlwi128_mask((__v8hi)(__m128i)(A), (int)(imm), \
- (__v8hi)_mm_setzero_si128(), \
- (__mmask8)(U)); })
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_srli_epi16 (__mmask8 __U, __m128i __A, int __B)
+{
+ return (__m128i)__builtin_ia32_selectw_128((__mmask8)__U,
+ (__v8hi)_mm_srli_epi16(__A, __B),
+ (__v8hi)_mm_setzero_si128());
+}
-#define _mm256_mask_srli_epi16(W, U, A, imm) __extension__ ({ \
- (__m256i)__builtin_ia32_psrlwi256_mask((__v16hi)(__m256i)(A), (int)(imm), \
- (__v16hi)(__m256i)(W), \
- (__mmask16)(U)); })
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_srli_epi16(__m256i __W, __mmask16 __U, __m256i __A, int __B)
+{
+ return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
+ (__v16hi)_mm256_srli_epi16(__A, __B),
+ (__v16hi)__W);
+}
-#define _mm256_maskz_srli_epi16(U, A, imm) __extension__ ({ \
- (__m256i)__builtin_ia32_psrlwi256_mask((__v16hi)(__m256i)(A), (int)(imm), \
- (__v16hi)_mm256_setzero_si256(), \
- (__mmask16)(U)); })
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_srli_epi16(__mmask16 __U, __m256i __A, int __B)
+{
+ return (__m256i)__builtin_ia32_selectw_256((__mmask16)__U,
+ (__v16hi)_mm256_srli_epi16(__A, __B),
+ (__v16hi)_mm256_setzero_si256());
+}
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_mask_mov_epi16 (__m128i __W, __mmask8 __U, __m128i __A)
@@ -3342,28 +3112,24 @@ _mm256_mask_permutexvar_epi16 (__m256i __W, __mmask16 __M, __m256i __A,
}
#define _mm_mask_alignr_epi8(W, U, A, B, N) __extension__ ({ \
- (__m128i)__builtin_ia32_palignr128_mask((__v16qi)(__m128i)(A), \
- (__v16qi)(__m128i)(B), (int)(N), \
- (__v16qi)(__m128i)(W), \
- (__mmask16)(U)); })
+ (__m128i)__builtin_ia32_selectb_128((__mmask16)(U), \
+ (__v16qi)_mm_alignr_epi8((A), (B), (int)(N)), \
+ (__v16qi)(__m128i)(W)); })
#define _mm_maskz_alignr_epi8(U, A, B, N) __extension__ ({ \
- (__m128i)__builtin_ia32_palignr128_mask((__v16qi)(__m128i)(A), \
- (__v16qi)(__m128i)(B), (int)(N), \
- (__v16qi)_mm_setzero_si128(), \
- (__mmask16)(U)); })
+ (__m128i)__builtin_ia32_selectb_128((__mmask16)(U), \
+ (__v16qi)_mm_alignr_epi8((A), (B), (int)(N)), \
+ (__v16qi)_mm_setzero_si128()); })
#define _mm256_mask_alignr_epi8(W, U, A, B, N) __extension__ ({ \
- (__m256i)__builtin_ia32_palignr256_mask((__v32qi)(__m256i)(A), \
- (__v32qi)(__m256i)(B), (int)(N), \
- (__v32qi)(__m256i)(W), \
- (__mmask32)(U)); })
+ (__m256i)__builtin_ia32_selectb_256((__mmask32)(U), \
+ (__v32qi)_mm256_alignr_epi8((A), (B), (int)(N)), \
+ (__v32qi)(__m256i)(W)); })
#define _mm256_maskz_alignr_epi8(U, A, B, N) __extension__ ({ \
- (__m256i)__builtin_ia32_palignr256_mask((__v32qi)(__m256i)(A), \
- (__v32qi)(__m256i)(B), (int)(N), \
- (__v32qi)_mm256_setzero_si256(), \
- (__mmask32)(U)); })
+ (__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), \
diff --git a/lib/Headers/avx512vldqintrin.h b/lib/Headers/avx512vldqintrin.h
index 8187bcd6b28e..cd9da4370564 100644
--- a/lib/Headers/avx512vldqintrin.h
+++ b/lib/Headers/avx512vldqintrin.h
@@ -37,20 +37,17 @@ _mm256_mullo_epi64 (__m256i __A, __m256i __B) {
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_mullo_epi64 (__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) {
- return (__m256i) __builtin_ia32_pmullq256_mask ((__v4di) __A,
- (__v4di) __B,
- (__v4di) __W,
- (__mmask8) __U);
+_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
-_mm256_maskz_mullo_epi64 (__mmask8 __U, __m256i __A, __m256i __B) {
- return (__m256i) __builtin_ia32_pmullq256_mask ((__v4di) __A,
- (__v4di) __B,
- (__v4di)
- _mm256_setzero_si256 (),
- (__mmask8) __U);
+_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
@@ -59,293 +56,241 @@ _mm_mullo_epi64 (__m128i __A, __m128i __B) {
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_mullo_epi64 (__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
- return (__m128i) __builtin_ia32_pmullq128_mask ((__v2di) __A,
- (__v2di) __B,
- (__v2di) __W,
- (__mmask8) __U);
+_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
-_mm_maskz_mullo_epi64 (__mmask8 __U, __m128i __A, __m128i __B) {
- return (__m128i) __builtin_ia32_pmullq128_mask ((__v2di) __A,
- (__v2di) __B,
- (__v2di)
- _mm_setzero_si128 (),
- (__mmask8) __U);
+_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
-_mm256_mask_andnot_pd (__m256d __W, __mmask8 __U, __m256d __A, __m256d __B) {
- return (__m256d) __builtin_ia32_andnpd256_mask ((__v4df) __A,
- (__v4df) __B,
- (__v4df) __W,
- (__mmask8) __U);
+_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
-_mm256_maskz_andnot_pd (__mmask8 __U, __m256d __A, __m256d __B) {
- return (__m256d) __builtin_ia32_andnpd256_mask ((__v4df) __A,
- (__v4df) __B,
- (__v4df)
- _mm256_setzero_pd (),
- (__mmask8) __U);
+_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
-_mm_mask_andnot_pd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
- return (__m128d) __builtin_ia32_andnpd128_mask ((__v2df) __A,
- (__v2df) __B,
- (__v2df) __W,
- (__mmask8) __U);
+_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
-_mm_maskz_andnot_pd (__mmask8 __U, __m128d __A, __m128d __B) {
- return (__m128d) __builtin_ia32_andnpd128_mask ((__v2df) __A,
- (__v2df) __B,
- (__v2df)
- _mm_setzero_pd (),
- (__mmask8) __U);
+_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
-_mm256_mask_andnot_ps (__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) {
- return (__m256) __builtin_ia32_andnps256_mask ((__v8sf) __A,
- (__v8sf) __B,
- (__v8sf) __W,
- (__mmask8) __U);
+_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
-_mm256_maskz_andnot_ps (__mmask8 __U, __m256 __A, __m256 __B) {
- return (__m256) __builtin_ia32_andnps256_mask ((__v8sf) __A,
- (__v8sf) __B,
- (__v8sf)
- _mm256_setzero_ps (),
- (__mmask8) __U);
+_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
-_mm_mask_andnot_ps (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
- return (__m128) __builtin_ia32_andnps128_mask ((__v4sf) __A,
- (__v4sf) __B,
- (__v4sf) __W,
- (__mmask8) __U);
+_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
-_mm_maskz_andnot_ps (__mmask8 __U, __m128 __A, __m128 __B) {
- return (__m128) __builtin_ia32_andnps128_mask ((__v4sf) __A,
- (__v4sf) __B,
- (__v4sf)
- _mm_setzero_ps (),
- (__mmask8) __U);
+_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
-_mm256_mask_and_pd (__m256d __W, __mmask8 __U, __m256d __A, __m256d __B) {
- return (__m256d) __builtin_ia32_andpd256_mask ((__v4df) __A,
- (__v4df) __B,
- (__v4df) __W,
- (__mmask8) __U);
+_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
-_mm256_maskz_and_pd (__mmask8 __U, __m256d __A, __m256d __B) {
- return (__m256d) __builtin_ia32_andpd256_mask ((__v4df) __A,
- (__v4df) __B,
- (__v4df)
- _mm256_setzero_pd (),
- (__mmask8) __U);
+_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
-_mm_mask_and_pd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
- return (__m128d) __builtin_ia32_andpd128_mask ((__v2df) __A,
- (__v2df) __B,
- (__v2df) __W,
- (__mmask8) __U);
+_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
-_mm_maskz_and_pd (__mmask8 __U, __m128d __A, __m128d __B) {
- return (__m128d) __builtin_ia32_andpd128_mask ((__v2df) __A,
- (__v2df) __B,
- (__v2df)
- _mm_setzero_pd (),
- (__mmask8) __U);
+_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
-_mm256_mask_and_ps (__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) {
- return (__m256) __builtin_ia32_andps256_mask ((__v8sf) __A,
- (__v8sf) __B,
- (__v8sf) __W,
- (__mmask8) __U);
+_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
-_mm256_maskz_and_ps (__mmask8 __U, __m256 __A, __m256 __B) {
- return (__m256) __builtin_ia32_andps256_mask ((__v8sf) __A,
- (__v8sf) __B,
- (__v8sf)
- _mm256_setzero_ps (),
- (__mmask8) __U);
+_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
-_mm_mask_and_ps (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
- return (__m128) __builtin_ia32_andps128_mask ((__v4sf) __A,
- (__v4sf) __B,
- (__v4sf) __W,
- (__mmask8) __U);
+_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
-_mm_maskz_and_ps (__mmask8 __U, __m128 __A, __m128 __B) {
- return (__m128) __builtin_ia32_andps128_mask ((__v4sf) __A,
- (__v4sf) __B,
- (__v4sf)
- _mm_setzero_ps (),
- (__mmask8) __U);
+_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
-_mm256_mask_xor_pd (__m256d __W, __mmask8 __U, __m256d __A,
- __m256d __B) {
- return (__m256d) __builtin_ia32_xorpd256_mask ((__v4df) __A,
- (__v4df) __B,
- (__v4df) __W,
- (__mmask8) __U);
+_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
-_mm256_maskz_xor_pd (__mmask8 __U, __m256d __A, __m256d __B) {
- return (__m256d) __builtin_ia32_xorpd256_mask ((__v4df) __A,
- (__v4df) __B,
- (__v4df)
- _mm256_setzero_pd (),
- (__mmask8) __U);
+_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
-_mm_mask_xor_pd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
- return (__m128d) __builtin_ia32_xorpd128_mask ((__v2df) __A,
- (__v2df) __B,
- (__v2df) __W,
- (__mmask8) __U);
+_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
_mm_maskz_xor_pd (__mmask8 __U, __m128d __A, __m128d __B) {
- return (__m128d) __builtin_ia32_xorpd128_mask ((__v2df) __A,
- (__v2df) __B,
- (__v2df)
- _mm_setzero_pd (),
- (__mmask8) __U);
+ return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U,
+ (__v2df)_mm_xor_pd(__A, __B),
+ (__v2df)_mm_setzero_pd());
}
static __inline__ __m256 __DEFAULT_FN_ATTRS
-_mm256_mask_xor_ps (__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) {
- return (__m256) __builtin_ia32_xorps256_mask ((__v8sf) __A,
- (__v8sf) __B,
- (__v8sf) __W,
- (__mmask8) __U);
+_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
-_mm256_maskz_xor_ps (__mmask8 __U, __m256 __A, __m256 __B) {
- return (__m256) __builtin_ia32_xorps256_mask ((__v8sf) __A,
- (__v8sf) __B,
- (__v8sf)
- _mm256_setzero_ps (),
- (__mmask8) __U);
+_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
-_mm_mask_xor_ps (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
- return (__m128) __builtin_ia32_xorps128_mask ((__v4sf) __A,
- (__v4sf) __B,
- (__v4sf) __W,
- (__mmask8) __U);
+_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
-_mm_maskz_xor_ps (__mmask8 __U, __m128 __A, __m128 __B) {
- return (__m128) __builtin_ia32_xorps128_mask ((__v4sf) __A,
- (__v4sf) __B,
- (__v4sf)
- _mm_setzero_ps (),
- (__mmask8) __U);
+_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
-_mm256_mask_or_pd (__m256d __W, __mmask8 __U, __m256d __A, __m256d __B) {
- return (__m256d) __builtin_ia32_orpd256_mask ((__v4df) __A,
- (__v4df) __B,
- (__v4df) __W,
- (__mmask8) __U);
+_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
-_mm256_maskz_or_pd (__mmask8 __U, __m256d __A, __m256d __B) {
- return (__m256d) __builtin_ia32_orpd256_mask ((__v4df) __A,
- (__v4df) __B,
- (__v4df)
- _mm256_setzero_pd (),
- (__mmask8) __U);
+_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
-_mm_mask_or_pd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
- return (__m128d) __builtin_ia32_orpd128_mask ((__v2df) __A,
- (__v2df) __B,
- (__v2df) __W,
- (__mmask8) __U);
+_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
-_mm_maskz_or_pd (__mmask8 __U, __m128d __A, __m128d __B) {
- return (__m128d) __builtin_ia32_orpd128_mask ((__v2df) __A,
- (__v2df) __B,
- (__v2df)
- _mm_setzero_pd (),
- (__mmask8) __U);
+_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
-_mm256_mask_or_ps (__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) {
- return (__m256) __builtin_ia32_orps256_mask ((__v8sf) __A,
- (__v8sf) __B,
- (__v8sf) __W,
- (__mmask8) __U);
+_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
-_mm256_maskz_or_ps (__mmask8 __U, __m256 __A, __m256 __B) {
- return (__m256) __builtin_ia32_orps256_mask ((__v8sf) __A,
- (__v8sf) __B,
- (__v8sf)
- _mm256_setzero_ps (),
- (__mmask8) __U);
+_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
-_mm_mask_or_ps (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
- return (__m128) __builtin_ia32_orps128_mask ((__v4sf) __A,
- (__v4sf) __B,
- (__v4sf) __W,
- (__mmask8) __U);
+_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
-_mm_maskz_or_ps (__mmask8 __U, __m128 __A, __m128 __B) {
- return (__m128) __builtin_ia32_orps128_mask ((__v4sf) __A,
- (__v4sf) __B,
- (__v4sf)
- _mm_setzero_ps (),
- (__mmask8) __U);
+_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
@@ -1151,82 +1096,72 @@ _mm256_maskz_broadcast_i64x2 (__mmask8 __M, __m128i __A)
}
#define _mm256_extractf64x2_pd(A, imm) __extension__ ({ \
- (__m128d)__builtin_ia32_extractf64x2_256_mask((__v4df)(__m256d)(A), \
- (int)(imm), \
- (__v2df)_mm_setzero_pd(), \
- (__mmask8)-1); })
+ (__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_extractf64x2_256_mask((__v4df)(__m256d)(A), \
- (int)(imm), \
- (__v2df)(__m128d)(W), \
- (__mmask8)(U)); })
+ (__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_extractf64x2_256_mask((__v4df)(__m256d)(A), \
- (int)(imm), \
- (__v2df)_mm_setzero_pd(), \
- (__mmask8)(U)); })
+ (__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_ia32_extracti64x2_256_mask((__v4di)(__m256i)(A), \
- (int)(imm), \
- (__v2di)_mm_setzero_di(), \
- (__mmask8)-1); })
+ (__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_extracti64x2_256_mask((__v4di)(__m256i)(A), \
- (int)(imm), \
- (__v2di)(__m128i)(W), \
- (__mmask8)(U)); })
+ (__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_extracti64x2_256_mask((__v4di)(__m256i)(A), \
- (int)(imm), \
- (__v2di)_mm_setzero_di(), \
- (__mmask8)(U)); })
+ (__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_ia32_insertf64x2_256_mask((__v4df)(__m256d)(A), \
- (__v2df)(__m128d)(B), \
- (int)(imm), \
- (__v4df)_mm256_setzero_pd(), \
- (__mmask8)-1); })
+ (__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__ ({ \
- (__m256d)__builtin_ia32_insertf64x2_256_mask((__v4df)(__m256d)(A), \
- (__v2df)(__m128d)(B), \
- (int)(imm), \
- (__v4df)(__m256d)(W), \
- (__mmask8)(U)); })
+ (__m256d)__builtin_ia32_selectpd_256((__mmask8)(U), \
+ (__v4df)_mm256_insertf64x2((A), (B), (imm)), \
+ (__v4df)(W)); })
#define _mm256_maskz_insertf64x2(U, A, B, imm) __extension__ ({ \
- (__m256d)__builtin_ia32_insertf64x2_256_mask((__v4df)(__m256d)(A), \
- (__v2df)(__m128d)(B), \
- (int)(imm), \
- (__v4df)_mm256_setzero_pd(), \
- (__mmask8)(U)); })
+ (__m256d)__builtin_ia32_selectpd_256((__mmask8)(U), \
+ (__v4df)_mm256_insertf64x2((A), (B), (imm)), \
+ (__v4df)_mm256_setzero_pd()); })
#define _mm256_inserti64x2(A, B, imm) __extension__ ({ \
- (__m256i)__builtin_ia32_inserti64x2_256_mask((__v4di)(__m256i)(A), \
- (__v2di)(__m128i)(B), \
- (int)(imm), \
- (__v4di)_mm256_setzero_si256(), \
- (__mmask8)-1); })
+ (__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_mask_inserti64x2(W, U, A, B, imm) __extension__ ({ \
- (__m256i)__builtin_ia32_inserti64x2_256_mask((__v4di)(__m256i)(A), \
- (__v2di)(__m128i)(B), \
- (int)(imm), \
- (__v4di)(__m256i)(W), \
- (__mmask8)(U)); })
+ (__m256i)__builtin_ia32_selectq_256((__mmask8)(U), \
+ (__v4di)_mm256_inserti64x2((A), (B), (imm)), \
+ (__v4di)(W)); })
#define _mm256_maskz_inserti64x2(U, A, B, imm) __extension__ ({ \
- (__m256i)__builtin_ia32_inserti64x2_256_mask((__v4di)(__m256i)(A), \
- (__v2di)(__m128i)(B), \
- (int)(imm), \
- (__v4di)_mm256_setzero_si256(), \
- (__mmask8)(U)); })
+ (__m256i)__builtin_ia32_selectq_256((__mmask8)(U), \
+ (__v4di)_mm256_inserti64x2((A), (B), (imm)), \
+ (__v4di)_mm256_setzero_si256()); })
#define _mm_mask_fpclass_pd_mask(U, A, imm) __extension__ ({ \
(__mmask8)__builtin_ia32_fpclasspd128_mask((__v2df)(__m128d)(A), (int)(imm), \
diff --git a/lib/Headers/avx512vlintrin.h b/lib/Headers/avx512vlintrin.h
index 295ce291f7ce..f3744da6ab8a 100644
--- a/lib/Headers/avx512vlintrin.h
+++ b/lib/Headers/avx512vlintrin.h
@@ -616,277 +616,227 @@ _mm256_mask_cmpneq_epu64_mask(__mmask8 __u, __m256i __a, __m256i __b) {
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_add_epi32 (__m256i __W, __mmask8 __U, __m256i __A,
- __m256i __B)
+_mm256_mask_add_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_paddd256_mask ((__v8si) __A,
- (__v8si) __B,
- (__v8si) __W,
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
+ (__v8si)_mm256_add_epi32(__A, __B),
+ (__v8si)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_add_epi32 (__mmask8 __U, __m256i __A, __m256i __B)
+_mm256_maskz_add_epi32(__mmask8 __U, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_paddd256_mask ((__v8si) __A,
- (__v8si) __B,
- (__v8si)
- _mm256_setzero_si256 (),
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
+ (__v8si)_mm256_add_epi32(__A, __B),
+ (__v8si)_mm256_setzero_si256());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_add_epi64 (__m256i __W, __mmask8 __U, __m256i __A,
- __m256i __B)
+_mm256_mask_add_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_paddq256_mask ((__v4di) __A,
- (__v4di) __B,
- (__v4di) __W,
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
+ (__v4di)_mm256_add_epi64(__A, __B),
+ (__v4di)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_add_epi64 (__mmask8 __U, __m256i __A, __m256i __B)
+_mm256_maskz_add_epi64(__mmask8 __U, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_paddq256_mask ((__v4di) __A,
- (__v4di) __B,
- (__v4di)
- _mm256_setzero_si256 (),
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
+ (__v4di)_mm256_add_epi64(__A, __B),
+ (__v4di)_mm256_setzero_si256());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_sub_epi32 (__m256i __W, __mmask8 __U, __m256i __A,
- __m256i __B)
+_mm256_mask_sub_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_psubd256_mask ((__v8si) __A,
- (__v8si) __B,
- (__v8si) __W,
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
+ (__v8si)_mm256_sub_epi32(__A, __B),
+ (__v8si)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_sub_epi32 (__mmask8 __U, __m256i __A, __m256i __B)
+_mm256_maskz_sub_epi32(__mmask8 __U, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_psubd256_mask ((__v8si) __A,
- (__v8si) __B,
- (__v8si)
- _mm256_setzero_si256 (),
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
+ (__v8si)_mm256_sub_epi32(__A, __B),
+ (__v8si)_mm256_setzero_si256());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_sub_epi64 (__m256i __W, __mmask8 __U, __m256i __A,
- __m256i __B)
+_mm256_mask_sub_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_psubq256_mask ((__v4di) __A,
- (__v4di) __B,
- (__v4di) __W,
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
+ (__v4di)_mm256_sub_epi64(__A, __B),
+ (__v4di)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_sub_epi64 (__mmask8 __U, __m256i __A, __m256i __B)
+_mm256_maskz_sub_epi64(__mmask8 __U, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_psubq256_mask ((__v4di) __A,
- (__v4di) __B,
- (__v4di)
- _mm256_setzero_si256 (),
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
+ (__v4di)_mm256_sub_epi64(__A, __B),
+ (__v4di)_mm256_setzero_si256());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_add_epi32 (__m128i __W, __mmask8 __U, __m128i __A,
- __m128i __B)
+_mm_mask_add_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_paddd128_mask ((__v4si) __A,
- (__v4si) __B,
- (__v4si) __W,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
+ (__v4si)_mm_add_epi32(__A, __B),
+ (__v4si)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_add_epi32 (__mmask8 __U, __m128i __A, __m128i __B)
+_mm_maskz_add_epi32(__mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_paddd128_mask ((__v4si) __A,
- (__v4si) __B,
- (__v4si)
- _mm_setzero_si128 (),
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
+ (__v4si)_mm_add_epi32(__A, __B),
+ (__v4si)_mm_setzero_si128());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_add_epi64 (__m128i __W, __mmask8 __U, __m128i __A,
- __m128i __B)
+_mm_mask_add_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_paddq128_mask ((__v2di) __A,
- (__v2di) __B,
- (__v2di) __W,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
+ (__v2di)_mm_add_epi64(__A, __B),
+ (__v2di)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_add_epi64 (__mmask8 __U, __m128i __A, __m128i __B)
+_mm_maskz_add_epi64(__mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_paddq128_mask ((__v2di) __A,
- (__v2di) __B,
- (__v2di)
- _mm_setzero_si128 (),
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
+ (__v2di)_mm_add_epi64(__A, __B),
+ (__v2di)_mm_setzero_si128());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_sub_epi32 (__m128i __W, __mmask8 __U, __m128i __A,
- __m128i __B)
+_mm_mask_sub_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_psubd128_mask ((__v4si) __A,
- (__v4si) __B,
- (__v4si) __W,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
+ (__v4si)_mm_sub_epi32(__A, __B),
+ (__v4si)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_sub_epi32 (__mmask8 __U, __m128i __A, __m128i __B)
+_mm_maskz_sub_epi32(__mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_psubd128_mask ((__v4si) __A,
- (__v4si) __B,
- (__v4si)
- _mm_setzero_si128 (),
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
+ (__v4si)_mm_sub_epi32(__A, __B),
+ (__v4si)_mm_setzero_si128());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_sub_epi64 (__m128i __W, __mmask8 __U, __m128i __A,
- __m128i __B)
+_mm_mask_sub_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_psubq128_mask ((__v2di) __A,
- (__v2di) __B,
- (__v2di) __W,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
+ (__v2di)_mm_sub_epi64(__A, __B),
+ (__v2di)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_sub_epi64 (__mmask8 __U, __m128i __A, __m128i __B)
+_mm_maskz_sub_epi64(__mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_psubq128_mask ((__v2di) __A,
- (__v2di) __B,
- (__v2di)
- _mm_setzero_si128 (),
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
+ (__v2di)_mm_sub_epi64(__A, __B),
+ (__v2di)_mm_setzero_si128());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_mul_epi32 (__m256i __W, __mmask8 __M, __m256i __X,
- __m256i __Y)
+_mm256_mask_mul_epi32(__m256i __W, __mmask8 __M, __m256i __X, __m256i __Y)
{
- return (__m256i) __builtin_ia32_pmuldq256_mask ((__v8si) __X,
- (__v8si) __Y,
- (__v4di) __W, __M);
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__M,
+ (__v4di)_mm256_mul_epi32(__X, __Y),
+ (__v4di)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_mul_epi32 (__mmask8 __M, __m256i __X, __m256i __Y)
+_mm256_maskz_mul_epi32(__mmask8 __M, __m256i __X, __m256i __Y)
{
- return (__m256i) __builtin_ia32_pmuldq256_mask ((__v8si) __X,
- (__v8si) __Y,
- (__v4di)
- _mm256_setzero_si256 (),
- __M);
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__M,
+ (__v4di)_mm256_mul_epi32(__X, __Y),
+ (__v4di)_mm256_setzero_si256());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_mul_epi32 (__m128i __W, __mmask8 __M, __m128i __X,
- __m128i __Y)
+_mm_mask_mul_epi32(__m128i __W, __mmask8 __M, __m128i __X, __m128i __Y)
{
- return (__m128i) __builtin_ia32_pmuldq128_mask ((__v4si) __X,
- (__v4si) __Y,
- (__v2di) __W, __M);
+ return (__m128i)__builtin_ia32_selectq_128((__mmask8)__M,
+ (__v2di)_mm_mul_epi32(__X, __Y),
+ (__v2di)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_mul_epi32 (__mmask8 __M, __m128i __X, __m128i __Y)
+_mm_maskz_mul_epi32(__mmask8 __M, __m128i __X, __m128i __Y)
{
- return (__m128i) __builtin_ia32_pmuldq128_mask ((__v4si) __X,
- (__v4si) __Y,
- (__v2di)
- _mm_setzero_si128 (),
- __M);
+ return (__m128i)__builtin_ia32_selectq_128((__mmask8)__M,
+ (__v2di)_mm_mul_epi32(__X, __Y),
+ (__v2di)_mm_setzero_si128());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_mul_epu32 (__m256i __W, __mmask8 __M, __m256i __X,
- __m256i __Y)
+_mm256_mask_mul_epu32(__m256i __W, __mmask8 __M, __m256i __X, __m256i __Y)
{
- return (__m256i) __builtin_ia32_pmuludq256_mask ((__v8si) __X,
- (__v8si) __Y,
- (__v4di) __W, __M);
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__M,
+ (__v4di)_mm256_mul_epu32(__X, __Y),
+ (__v4di)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_mul_epu32 (__mmask8 __M, __m256i __X, __m256i __Y)
+_mm256_maskz_mul_epu32(__mmask8 __M, __m256i __X, __m256i __Y)
{
- return (__m256i) __builtin_ia32_pmuludq256_mask ((__v8si) __X,
- (__v8si) __Y,
- (__v4di)
- _mm256_setzero_si256 (),
- __M);
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__M,
+ (__v4di)_mm256_mul_epu32(__X, __Y),
+ (__v4di)_mm256_setzero_si256());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_mul_epu32 (__m128i __W, __mmask8 __M, __m128i __X,
- __m128i __Y)
+_mm_mask_mul_epu32(__m128i __W, __mmask8 __M, __m128i __X, __m128i __Y)
{
- return (__m128i) __builtin_ia32_pmuludq128_mask ((__v4si) __X,
- (__v4si) __Y,
- (__v2di) __W, __M);
+ return (__m128i)__builtin_ia32_selectq_128((__mmask8)__M,
+ (__v2di)_mm_mul_epu32(__X, __Y),
+ (__v2di)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_mul_epu32 (__mmask8 __M, __m128i __X, __m128i __Y)
+_mm_maskz_mul_epu32(__mmask8 __M, __m128i __X, __m128i __Y)
{
- return (__m128i) __builtin_ia32_pmuludq128_mask ((__v4si) __X,
- (__v4si) __Y,
- (__v2di)
- _mm_setzero_si128 (),
- __M);
+ return (__m128i)__builtin_ia32_selectq_128((__mmask8)__M,
+ (__v2di)_mm_mul_epu32(__X, __Y),
+ (__v2di)_mm_setzero_si128());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_mullo_epi32 (__mmask8 __M, __m256i __A, __m256i __B)
+_mm256_maskz_mullo_epi32(__mmask8 __M, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_pmulld256_mask ((__v8si) __A,
- (__v8si) __B,
- (__v8si)
- _mm256_setzero_si256 (),
- __M);
+ return (__m256i)__builtin_ia32_selectd_256((__mmask8)__M,
+ (__v8si)_mm256_mullo_epi32(__A, __B),
+ (__v8si)_mm256_setzero_si256());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_mullo_epi32 (__m256i __W, __mmask8 __M, __m256i __A,
- __m256i __B)
+_mm256_mask_mullo_epi32(__m256i __W, __mmask8 __M, __m256i __A, __m256i __B)
{
- return (__m256i) __builtin_ia32_pmulld256_mask ((__v8si) __A,
- (__v8si) __B,
- (__v8si) __W, __M);
+ return (__m256i)__builtin_ia32_selectd_256((__mmask8)__M,
+ (__v8si)_mm256_mullo_epi32(__A, __B),
+ (__v8si)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_mullo_epi32 (__mmask8 __M, __m128i __A, __m128i __B)
+_mm_maskz_mullo_epi32(__mmask8 __M, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_pmulld128_mask ((__v4si) __A,
- (__v4si) __B,
- (__v4si)
- _mm_setzero_si128 (),
- __M);
+ return (__m128i)__builtin_ia32_selectd_128((__mmask8)__M,
+ (__v4si)_mm_mullo_epi32(__A, __B),
+ (__v4si)_mm_setzero_si128());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_mullo_epi32 (__m128i __W, __mmask16 __M, __m128i __A,
- __m128i __B)
+_mm_mask_mullo_epi32(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_pmulld128_mask ((__v4si) __A,
- (__v4si) __B,
- (__v4si) __W, __M);
+ return (__m128i)__builtin_ia32_selectd_128((__mmask8)__M,
+ (__v4si)_mm_mullo_epi32(__A, __B),
+ (__v4si)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
@@ -1895,71 +1845,59 @@ _mm256_mask3_fnmsub_ps(__m256 __A, __m256 __B, __m256 __C, __mmask8 __U)
}
static __inline__ __m128d __DEFAULT_FN_ATTRS
-_mm_mask_add_pd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
- return (__m128d) __builtin_ia32_addpd128_mask ((__v2df) __A,
- (__v2df) __B,
- (__v2df) __W,
- (__mmask8) __U);
+_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
-_mm_maskz_add_pd (__mmask8 __U, __m128d __A, __m128d __B) {
- return (__m128d) __builtin_ia32_addpd128_mask ((__v2df) __A,
- (__v2df) __B,
- (__v2df)
- _mm_setzero_pd (),
- (__mmask8) __U);
+_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
-_mm256_mask_add_pd (__m256d __W, __mmask8 __U, __m256d __A, __m256d __B) {
- return (__m256d) __builtin_ia32_addpd256_mask ((__v4df) __A,
- (__v4df) __B,
- (__v4df) __W,
- (__mmask8) __U);
+_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
-_mm256_maskz_add_pd (__mmask8 __U, __m256d __A, __m256d __B) {
- return (__m256d) __builtin_ia32_addpd256_mask ((__v4df) __A,
- (__v4df) __B,
- (__v4df)
- _mm256_setzero_pd (),
- (__mmask8) __U);
+_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
-_mm_mask_add_ps (__m128 __W, __mmask16 __U, __m128 __A, __m128 __B) {
- return (__m128) __builtin_ia32_addps128_mask ((__v4sf) __A,
- (__v4sf) __B,
- (__v4sf) __W,
- (__mmask8) __U);
+_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
-_mm_maskz_add_ps (__mmask16 __U, __m128 __A, __m128 __B) {
- return (__m128) __builtin_ia32_addps128_mask ((__v4sf) __A,
- (__v4sf) __B,
- (__v4sf)
- _mm_setzero_ps (),
- (__mmask8) __U);
+_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
-_mm256_mask_add_ps (__m256 __W, __mmask16 __U, __m256 __A, __m256 __B) {
- return (__m256) __builtin_ia32_addps256_mask ((__v8sf) __A,
- (__v8sf) __B,
- (__v8sf) __W,
- (__mmask8) __U);
+_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
-_mm256_maskz_add_ps (__mmask16 __U, __m256 __A, __m256 __B) {
- return (__m256) __builtin_ia32_addps256_mask ((__v8sf) __A,
- (__v8sf) __B,
- (__v8sf)
- _mm256_setzero_ps (),
- (__mmask8) __U);
+_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
@@ -2196,32 +2134,30 @@ _mm256_mask_compressstoreu_epi32 (void *__P, __mmask8 __U, __m256i __A) {
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_mask_cvtepi32_pd (__m128d __W, __mmask8 __U, __m128i __A) {
- return (__m128d) __builtin_ia32_cvtdq2pd128_mask ((__v4si) __A,
- (__v2df) __W,
- (__mmask8) __U);
+ return (__m128d)__builtin_ia32_selectpd_128((__mmask8) __U,
+ (__v2df)_mm_cvtepi32_pd(__A),
+ (__v2df)__W);
}
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_maskz_cvtepi32_pd (__mmask8 __U, __m128i __A) {
- return (__m128d) __builtin_ia32_cvtdq2pd128_mask ((__v4si) __A,
- (__v2df)
- _mm_setzero_pd (),
- (__mmask8) __U);
+ return (__m128d)__builtin_ia32_selectpd_128((__mmask8) __U,
+ (__v2df)_mm_cvtepi32_pd(__A),
+ (__v2df)_mm_setzero_pd());
}
static __inline__ __m256d __DEFAULT_FN_ATTRS
_mm256_mask_cvtepi32_pd (__m256d __W, __mmask8 __U, __m128i __A) {
- return (__m256d) __builtin_ia32_cvtdq2pd256_mask ((__v4si) __A,
- (__v4df) __W,
- (__mmask8) __U);
+ return (__m256d)__builtin_ia32_selectpd_256((__mmask8) __U,
+ (__v4df)_mm256_cvtepi32_pd(__A),
+ (__v4df)__W);
}
static __inline__ __m256d __DEFAULT_FN_ATTRS
_mm256_maskz_cvtepi32_pd (__mmask8 __U, __m128i __A) {
- return (__m256d) __builtin_ia32_cvtdq2pd256_mask ((__v4si) __A,
- (__v4df)
- _mm256_setzero_pd (),
- (__mmask8) __U);
+ return (__m256d)__builtin_ia32_selectpd_256((__mmask8) __U,
+ (__v4df)_mm256_cvtepi32_pd(__A),
+ (__v4df)_mm256_setzero_pd());
}
static __inline__ __m128 __DEFAULT_FN_ATTRS
@@ -2620,48 +2556,41 @@ _mm256_maskz_cvttps_epu32 (__mmask8 __U, __m256 __A) {
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_cvtepu32_pd (__m128i __A) {
- return (__m128d) __builtin_ia32_cvtudq2pd128_mask ((__v4si) __A,
- (__v2df)
- _mm_setzero_pd (),
- (__mmask8) -1);
+ return (__m128d) __builtin_convertvector(
+ __builtin_shufflevector((__v4su)__A, (__v4su)__A, 0, 1), __v2df);
}
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_mask_cvtepu32_pd (__m128d __W, __mmask8 __U, __m128i __A) {
- return (__m128d) __builtin_ia32_cvtudq2pd128_mask ((__v4si) __A,
- (__v2df) __W,
- (__mmask8) __U);
+ return (__m128d)__builtin_ia32_selectpd_128((__mmask8) __U,
+ (__v2df)_mm_cvtepu32_pd(__A),
+ (__v2df)__W);
}
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_maskz_cvtepu32_pd (__mmask8 __U, __m128i __A) {
- return (__m128d) __builtin_ia32_cvtudq2pd128_mask ((__v4si) __A,
- (__v2df)
- _mm_setzero_pd (),
- (__mmask8) __U);
+ return (__m128d)__builtin_ia32_selectpd_128((__mmask8) __U,
+ (__v2df)_mm_cvtepu32_pd(__A),
+ (__v2df)_mm_setzero_pd());
}
static __inline__ __m256d __DEFAULT_FN_ATTRS
_mm256_cvtepu32_pd (__m128i __A) {
- return (__m256d) __builtin_ia32_cvtudq2pd256_mask ((__v4si) __A,
- (__v4df)
- _mm256_setzero_pd (),
- (__mmask8) -1);
+ return (__m256d)__builtin_convertvector((__v4su)__A, __v4df);
}
static __inline__ __m256d __DEFAULT_FN_ATTRS
_mm256_mask_cvtepu32_pd (__m256d __W, __mmask8 __U, __m128i __A) {
- return (__m256d) __builtin_ia32_cvtudq2pd256_mask ((__v4si) __A,
- (__v4df) __W,
- (__mmask8) __U);
+ return (__m256d)__builtin_ia32_selectpd_256((__mmask8) __U,
+ (__v4df)_mm256_cvtepu32_pd(__A),
+ (__v4df)__W);
}
static __inline__ __m256d __DEFAULT_FN_ATTRS
_mm256_maskz_cvtepu32_pd (__mmask8 __U, __m128i __A) {
- return (__m256d) __builtin_ia32_cvtudq2pd256_mask ((__v4si) __A,
- (__v4df)
- _mm256_setzero_pd (),
- (__mmask8) __U);
+ return (__m256d)__builtin_ia32_selectpd_256((__mmask8) __U,
+ (__v4df)_mm256_cvtepu32_pd(__A),
+ (__v4df)_mm256_setzero_pd());
}
static __inline__ __m128 __DEFAULT_FN_ATTRS
@@ -2711,72 +2640,59 @@ _mm256_maskz_cvtepu32_ps (__mmask8 __U, __m256i __A) {
}
static __inline__ __m128d __DEFAULT_FN_ATTRS
-_mm_mask_div_pd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
- return (__m128d) __builtin_ia32_divpd_mask ((__v2df) __A,
- (__v2df) __B,
- (__v2df) __W,
- (__mmask8) __U);
+_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
-_mm_maskz_div_pd (__mmask8 __U, __m128d __A, __m128d __B) {
- return (__m128d) __builtin_ia32_divpd_mask ((__v2df) __A,
- (__v2df) __B,
- (__v2df)
- _mm_setzero_pd (),
- (__mmask8) __U);
+_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
-_mm256_mask_div_pd (__m256d __W, __mmask8 __U, __m256d __A,
- __m256d __B) {
- return (__m256d) __builtin_ia32_divpd256_mask ((__v4df) __A,
- (__v4df) __B,
- (__v4df) __W,
- (__mmask8) __U);
+_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
-_mm256_maskz_div_pd (__mmask8 __U, __m256d __A, __m256d __B) {
- return (__m256d) __builtin_ia32_divpd256_mask ((__v4df) __A,
- (__v4df) __B,
- (__v4df)
- _mm256_setzero_pd (),
- (__mmask8) __U);
+_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
-_mm_mask_div_ps (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
- return (__m128) __builtin_ia32_divps_mask ((__v4sf) __A,
- (__v4sf) __B,
- (__v4sf) __W,
- (__mmask8) __U);
+_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
-_mm_maskz_div_ps (__mmask8 __U, __m128 __A, __m128 __B) {
- return (__m128) __builtin_ia32_divps_mask ((__v4sf) __A,
- (__v4sf) __B,
- (__v4sf)
- _mm_setzero_ps (),
- (__mmask8) __U);
+_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
-_mm256_mask_div_ps (__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) {
- return (__m256) __builtin_ia32_divps256_mask ((__v8sf) __A,
- (__v8sf) __B,
- (__v8sf) __W,
- (__mmask8) __U);
+_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
-_mm256_maskz_div_ps (__mmask8 __U, __m256 __A, __m256 __B) {
- return (__m256) __builtin_ia32_divps256_mask ((__v8sf) __A,
- (__v8sf) __B,
- (__v8sf)
- _mm256_setzero_ps (),
- (__mmask8) __U);
+_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
@@ -3127,240 +3043,199 @@ _mm256_maskz_getexp_ps (__mmask8 __U, __m256 __A) {
}
static __inline__ __m128d __DEFAULT_FN_ATTRS
-_mm_mask_max_pd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
- return (__m128d) __builtin_ia32_maxpd_mask ((__v2df) __A,
- (__v2df) __B,
- (__v2df) __W,
- (__mmask8) __U);
+_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
-_mm_maskz_max_pd (__mmask8 __U, __m128d __A, __m128d __B) {
- return (__m128d) __builtin_ia32_maxpd_mask ((__v2df) __A,
- (__v2df) __B,
- (__v2df)
- _mm_setzero_pd (),
- (__mmask8) __U);
+_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
-_mm256_mask_max_pd (__m256d __W, __mmask8 __U, __m256d __A,
- __m256d __B) {
- return (__m256d) __builtin_ia32_maxpd256_mask ((__v4df) __A,
- (__v4df) __B,
- (__v4df) __W,
- (__mmask8) __U);
+_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
-_mm256_maskz_max_pd (__mmask8 __U, __m256d __A, __m256d __B) {
- return (__m256d) __builtin_ia32_maxpd256_mask ((__v4df) __A,
- (__v4df) __B,
- (__v4df)
- _mm256_setzero_pd (),
- (__mmask8) __U);
+_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
-_mm_mask_max_ps (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
- return (__m128) __builtin_ia32_maxps_mask ((__v4sf) __A,
- (__v4sf) __B,
- (__v4sf) __W,
- (__mmask8) __U);
+_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
-_mm_maskz_max_ps (__mmask8 __U, __m128 __A, __m128 __B) {
- return (__m128) __builtin_ia32_maxps_mask ((__v4sf) __A,
- (__v4sf) __B,
- (__v4sf)
- _mm_setzero_ps (),
- (__mmask8) __U);
+_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
-_mm256_mask_max_ps (__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) {
- return (__m256) __builtin_ia32_maxps256_mask ((__v8sf) __A,
- (__v8sf) __B,
- (__v8sf) __W,
- (__mmask8) __U);
+_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
-_mm256_maskz_max_ps (__mmask8 __U, __m256 __A, __m256 __B) {
- return (__m256) __builtin_ia32_maxps256_mask ((__v8sf) __A,
- (__v8sf) __B,
- (__v8sf)
- _mm256_setzero_ps (),
- (__mmask8) __U);
+_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
-_mm_mask_min_pd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
- return (__m128d) __builtin_ia32_minpd_mask ((__v2df) __A,
- (__v2df) __B,
- (__v2df) __W,
- (__mmask8) __U);
+_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
-_mm_maskz_min_pd (__mmask8 __U, __m128d __A, __m128d __B) {
- return (__m128d) __builtin_ia32_minpd_mask ((__v2df) __A,
- (__v2df) __B,
- (__v2df)
- _mm_setzero_pd (),
- (__mmask8) __U);
+_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
-_mm256_mask_min_pd (__m256d __W, __mmask8 __U, __m256d __A,
- __m256d __B) {
- return (__m256d) __builtin_ia32_minpd256_mask ((__v4df) __A,
- (__v4df) __B,
- (__v4df) __W,
- (__mmask8) __U);
+_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
-_mm256_maskz_min_pd (__mmask8 __U, __m256d __A, __m256d __B) {
- return (__m256d) __builtin_ia32_minpd256_mask ((__v4df) __A,
- (__v4df) __B,
- (__v4df)
- _mm256_setzero_pd (),
- (__mmask8) __U);
+_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
-_mm_mask_min_ps (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
- return (__m128) __builtin_ia32_minps_mask ((__v4sf) __A,
- (__v4sf) __B,
- (__v4sf) __W,
- (__mmask8) __U);
+_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
-_mm_maskz_min_ps (__mmask8 __U, __m128 __A, __m128 __B) {
- return (__m128) __builtin_ia32_minps_mask ((__v4sf) __A,
- (__v4sf) __B,
- (__v4sf)
- _mm_setzero_ps (),
- (__mmask8) __U);
+_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
-_mm256_mask_min_ps (__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) {
- return (__m256) __builtin_ia32_minps256_mask ((__v8sf) __A,
- (__v8sf) __B,
- (__v8sf) __W,
- (__mmask8) __U);
+_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
-_mm256_maskz_min_ps (__mmask8 __U, __m256 __A, __m256 __B) {
- return (__m256) __builtin_ia32_minps256_mask ((__v8sf) __A,
- (__v8sf) __B,
- (__v8sf)
- _mm256_setzero_ps (),
- (__mmask8) __U);
+_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
-_mm_mask_mul_pd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
- return (__m128d) __builtin_ia32_mulpd_mask ((__v2df) __A,
- (__v2df) __B,
- (__v2df) __W,
- (__mmask8) __U);
+_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
-_mm_maskz_mul_pd (__mmask8 __U, __m128d __A, __m128d __B) {
- return (__m128d) __builtin_ia32_mulpd_mask ((__v2df) __A,
- (__v2df) __B,
- (__v2df)
- _mm_setzero_pd (),
- (__mmask8) __U);
+_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
-_mm256_mask_mul_pd (__m256d __W, __mmask8 __U, __m256d __A,
- __m256d __B) {
- return (__m256d) __builtin_ia32_mulpd256_mask ((__v4df) __A,
- (__v4df) __B,
- (__v4df) __W,
- (__mmask8) __U);
+_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
-_mm256_maskz_mul_pd (__mmask8 __U, __m256d __A, __m256d __B) {
- return (__m256d) __builtin_ia32_mulpd256_mask ((__v4df) __A,
- (__v4df) __B,
- (__v4df)
- _mm256_setzero_pd (),
- (__mmask8) __U);
+_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
-_mm_mask_mul_ps (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
- return (__m128) __builtin_ia32_mulps_mask ((__v4sf) __A,
- (__v4sf) __B,
- (__v4sf) __W,
- (__mmask8) __U);
+_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
-_mm_maskz_mul_ps (__mmask8 __U, __m128 __A, __m128 __B) {
- return (__m128) __builtin_ia32_mulps_mask ((__v4sf) __A,
- (__v4sf) __B,
- (__v4sf)
- _mm_setzero_ps (),
- (__mmask8) __U);
+_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
-_mm256_mask_mul_ps (__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) {
- return (__m256) __builtin_ia32_mulps256_mask ((__v8sf) __A,
- (__v8sf) __B,
- (__v8sf) __W,
- (__mmask8) __U);
+_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
-_mm256_maskz_mul_ps (__mmask8 __U, __m256 __A, __m256 __B) {
- return (__m256) __builtin_ia32_mulps256_mask ((__v8sf) __A,
- (__v8sf) __B,
- (__v8sf)
- _mm256_setzero_ps (),
- (__mmask8) __U);
+_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
-_mm_mask_abs_epi32 (__m128i __W, __mmask8 __U, __m128i __A) {
- return (__m128i) __builtin_ia32_pabsd128_mask ((__v4si) __A,
- (__v4si) __W,
- (__mmask8) __U);
+_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
-_mm_maskz_abs_epi32 (__mmask8 __U, __m128i __A) {
- return (__m128i) __builtin_ia32_pabsd128_mask ((__v4si) __A,
- (__v4si)
- _mm_setzero_si128 (),
- (__mmask8) __U);
+_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
-_mm256_mask_abs_epi32 (__m256i __W, __mmask8 __U, __m256i __A) {
- return (__m256i) __builtin_ia32_pabsd256_mask ((__v8si) __A,
- (__v8si) __W,
- (__mmask8) __U);
+_mm256_mask_abs_epi32(__m256i __W, __mmask8 __U, __m256i __A) {
+ return (__m256i)__builtin_ia32_selectd_256((__mmask16)__U,
+ (__v8si)_mm256_abs_epi32(__A),
+ (__v8si)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_abs_epi32 (__mmask8 __U, __m256i __A) {
- return (__m256i) __builtin_ia32_pabsd256_mask ((__v8si) __A,
- (__v8si)
- _mm256_setzero_si256 (),
- (__mmask8) __U);
+_mm256_maskz_abs_epi32(__mmask8 __U, __m256i __A) {
+ return (__m256i)__builtin_ia32_selectd_256((__mmask16)__U,
+ (__v8si)_mm256_abs_epi32(__A),
+ (__v8si)_mm256_setzero_si256());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
@@ -3410,37 +3285,31 @@ _mm256_maskz_abs_epi64 (__mmask8 __U, __m256i __A) {
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_max_epi32 (__mmask8 __M, __m128i __A, __m128i __B) {
- return (__m128i) __builtin_ia32_pmaxsd128_mask ((__v4si) __A,
- (__v4si) __B,
- (__v4si)
- _mm_setzero_si128 (),
- __M);
+_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
-_mm_mask_max_epi32 (__m128i __W, __mmask8 __M, __m128i __A,
- __m128i __B) {
- return (__m128i) __builtin_ia32_pmaxsd128_mask ((__v4si) __A,
- (__v4si) __B,
- (__v4si) __W, __M);
+_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
-_mm256_maskz_max_epi32 (__mmask8 __M, __m256i __A, __m256i __B) {
- return (__m256i) __builtin_ia32_pmaxsd256_mask ((__v8si) __A,
- (__v8si) __B,
- (__v8si)
- _mm256_setzero_si256 (),
- __M);
+_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
-_mm256_mask_max_epi32 (__m256i __W, __mmask8 __M, __m256i __A,
- __m256i __B) {
- return (__m256i) __builtin_ia32_pmaxsd256_mask ((__v8si) __A,
- (__v8si) __B,
- (__v8si) __W, __M);
+_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
@@ -3496,37 +3365,31 @@ _mm256_max_epi64 (__m256i __A, __m256i __B) {
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_max_epu32 (__mmask8 __M, __m128i __A, __m128i __B) {
- return (__m128i) __builtin_ia32_pmaxud128_mask ((__v4si) __A,
- (__v4si) __B,
- (__v4si)
- _mm_setzero_si128 (),
- __M);
+_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
-_mm_mask_max_epu32 (__m128i __W, __mmask8 __M, __m128i __A,
- __m128i __B) {
- return (__m128i) __builtin_ia32_pmaxud128_mask ((__v4si) __A,
- (__v4si) __B,
- (__v4si) __W, __M);
+_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
-_mm256_maskz_max_epu32 (__mmask8 __M, __m256i __A, __m256i __B) {
- return (__m256i) __builtin_ia32_pmaxud256_mask ((__v8si) __A,
- (__v8si) __B,
- (__v8si)
- _mm256_setzero_si256 (),
- __M);
+_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
-_mm256_mask_max_epu32 (__m256i __W, __mmask8 __M, __m256i __A,
- __m256i __B) {
- return (__m256i) __builtin_ia32_pmaxud256_mask ((__v8si) __A,
- (__v8si) __B,
- (__v8si) __W, __M);
+_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
@@ -3582,37 +3445,31 @@ _mm256_mask_max_epu64 (__m256i __W, __mmask8 __M, __m256i __A,
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_min_epi32 (__mmask8 __M, __m128i __A, __m128i __B) {
- return (__m128i) __builtin_ia32_pminsd128_mask ((__v4si) __A,
- (__v4si) __B,
- (__v4si)
- _mm_setzero_si128 (),
- __M);
+_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
-_mm_mask_min_epi32 (__m128i __W, __mmask8 __M, __m128i __A,
- __m128i __B) {
- return (__m128i) __builtin_ia32_pminsd128_mask ((__v4si) __A,
- (__v4si) __B,
- (__v4si) __W, __M);
+_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
-_mm256_maskz_min_epi32 (__mmask8 __M, __m256i __A, __m256i __B) {
- return (__m256i) __builtin_ia32_pminsd256_mask ((__v8si) __A,
- (__v8si) __B,
- (__v8si)
- _mm256_setzero_si256 (),
- __M);
+_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
-_mm256_mask_min_epi32 (__m256i __W, __mmask8 __M, __m256i __A,
- __m256i __B) {
- return (__m256i) __builtin_ia32_pminsd256_mask ((__v8si) __A,
- (__v8si) __B,
- (__v8si) __W, __M);
+_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
@@ -3668,37 +3525,31 @@ _mm256_maskz_min_epi64 (__mmask8 __M, __m256i __A, __m256i __B) {
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_min_epu32 (__mmask8 __M, __m128i __A, __m128i __B) {
- return (__m128i) __builtin_ia32_pminud128_mask ((__v4si) __A,
- (__v4si) __B,
- (__v4si)
- _mm_setzero_si128 (),
- __M);
+_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
-_mm_mask_min_epu32 (__m128i __W, __mmask8 __M, __m128i __A,
- __m128i __B) {
- return (__m128i) __builtin_ia32_pminud128_mask ((__v4si) __A,
- (__v4si) __B,
- (__v4si) __W, __M);
+_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
-_mm256_maskz_min_epu32 (__mmask8 __M, __m256i __A, __m256i __B) {
- return (__m256i) __builtin_ia32_pminud256_mask ((__v8si) __A,
- (__v8si) __B,
- (__v8si)
- _mm256_setzero_si256 (),
- __M);
+_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
-_mm256_mask_min_epu32 (__m256i __W, __mmask8 __M, __m256i __A,
- __m256i __B) {
- return (__m256i) __builtin_ia32_pminud256_mask ((__v8si) __A,
- (__v8si) __B,
- (__v8si) __W, __M);
+_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
@@ -4095,132 +3946,115 @@ _mm256_maskz_scalef_ps (__mmask8 __U, __m256 __A, __m256 __B) {
(__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_sqrtpd128_mask ((__v2df) __A,
- (__v2df) __W,
- (__mmask8) __U);
+_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_sqrtpd128_mask ((__v2df) __A,
- (__v2df)
- _mm_setzero_pd (),
- (__mmask8) __U);
+_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_sqrtpd256_mask ((__v4df) __A,
- (__v4df) __W,
- (__mmask8) __U);
+_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_sqrtpd256_mask ((__v4df) __A,
- (__v4df)
- _mm256_setzero_pd (),
- (__mmask8) __U);
+_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_sqrtps128_mask ((__v4sf) __A,
- (__v4sf) __W,
- (__mmask8) __U);
+_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_sqrtps128_mask ((__v4sf) __A,
- (__v4sf)
- _mm_setzero_ps (),
- (__mmask8) __U);
+_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_sqrtps256_mask ((__v8sf) __A,
- (__v8sf) __W,
- (__mmask8) __U);
+_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_sqrtps256_mask ((__v8sf) __A,
- (__v8sf)
- _mm256_setzero_ps (),
- (__mmask8) __U);
+_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_subpd128_mask ((__v2df) __A,
- (__v2df) __B,
- (__v2df) __W,
- (__mmask8) __U);
+_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_subpd128_mask ((__v2df) __A,
- (__v2df) __B,
- (__v2df)
- _mm_setzero_pd (),
- (__mmask8) __U);
+_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_subpd256_mask ((__v4df) __A,
- (__v4df) __B,
- (__v4df) __W,
- (__mmask8) __U);
+_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_subpd256_mask ((__v4df) __A,
- (__v4df) __B,
- (__v4df)
- _mm256_setzero_pd (),
- (__mmask8) __U);
+_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, __mmask16 __U, __m128 __A, __m128 __B) {
- return (__m128) __builtin_ia32_subps128_mask ((__v4sf) __A,
- (__v4sf) __B,
- (__v4sf) __W,
- (__mmask8) __U);
+_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 (__mmask16 __U, __m128 __A, __m128 __B) {
- return (__m128) __builtin_ia32_subps128_mask ((__v4sf) __A,
- (__v4sf) __B,
- (__v4sf)
- _mm_setzero_ps (),
- (__mmask8) __U);
+_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, __mmask16 __U, __m256 __A, __m256 __B) {
- return (__m256) __builtin_ia32_subps256_mask ((__v8sf) __A,
- (__v8sf) __B,
- (__v8sf) __W,
- (__mmask8) __U);
+_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 (__mmask16 __U, __m256 __A, __m256 __B) {
- return (__m256) __builtin_ia32_subps256_mask ((__v8sf) __A,
- (__v8sf) __B,
- (__v8sf)
- _mm256_setzero_ps (),
- (__mmask8) __U);
+_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
@@ -4551,344 +4385,324 @@ _mm256_maskz_permutex2var_epi64 (__mmask8 __U, __m256i __A,
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_cvtepi8_epi32 (__m128i __W, __mmask8 __U, __m128i __A)
+_mm_mask_cvtepi8_epi32(__m128i __W, __mmask8 __U, __m128i __A)
{
- return (__m128i) __builtin_ia32_pmovsxbd128_mask ((__v16qi) __A,
- (__v4si) __W,
- (__mmask8) __U);
+ 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)
+_mm_maskz_cvtepi8_epi32(__mmask8 __U, __m128i __A)
{
- return (__m128i) __builtin_ia32_pmovsxbd128_mask ((__v16qi) __A,
- (__v4si)
- _mm_setzero_si128 (),
- (__mmask8) __U);
+ 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_pmovsxbd256_mask ((__v16qi) __A,
- (__v8si) __W,
- (__mmask8) __U);
+ 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_pmovsxbd256_mask ((__v16qi) __A,
- (__v8si)
- _mm256_setzero_si256 (),
- (__mmask8) __U);
+ 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)
+_mm_mask_cvtepi8_epi64(__m128i __W, __mmask8 __U, __m128i __A)
{
- return (__m128i) __builtin_ia32_pmovsxbq128_mask ((__v16qi) __A,
- (__v2di) __W,
- (__mmask8) __U);
+ 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)
+_mm_maskz_cvtepi8_epi64(__mmask8 __U, __m128i __A)
{
- return (__m128i) __builtin_ia32_pmovsxbq128_mask ((__v16qi) __A,
- (__v2di)
- _mm_setzero_si128 (),
- (__mmask8) __U);
+ 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)
+_mm256_mask_cvtepi8_epi64(__m256i __W, __mmask8 __U, __m128i __A)
{
- return (__m256i) __builtin_ia32_pmovsxbq256_mask ((__v16qi) __A,
- (__v4di) __W,
- (__mmask8) __U);
+ 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)
+_mm256_maskz_cvtepi8_epi64(__mmask8 __U, __m128i __A)
{
- return (__m256i) __builtin_ia32_pmovsxbq256_mask ((__v16qi) __A,
- (__v4di)
- _mm256_setzero_si256 (),
- (__mmask8) __U);
+ 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)
+_mm_mask_cvtepi32_epi64(__m128i __W, __mmask8 __U, __m128i __X)
{
- return (__m128i) __builtin_ia32_pmovsxdq128_mask ((__v4si) __X,
- (__v2di) __W,
- (__mmask8) __U);
+ 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)
+_mm_maskz_cvtepi32_epi64(__mmask8 __U, __m128i __X)
{
- return (__m128i) __builtin_ia32_pmovsxdq128_mask ((__v4si) __X,
- (__v2di)
- _mm_setzero_si128 (),
- (__mmask8) __U);
+ 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)
+_mm256_mask_cvtepi32_epi64(__m256i __W, __mmask8 __U, __m128i __X)
{
- return (__m256i) __builtin_ia32_pmovsxdq256_mask ((__v4si) __X,
- (__v4di) __W,
- (__mmask8) __U);
+ 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)
+_mm256_maskz_cvtepi32_epi64(__mmask8 __U, __m128i __X)
{
- return (__m256i) __builtin_ia32_pmovsxdq256_mask ((__v4si) __X,
- (__v4di)
- _mm256_setzero_si256 (),
- (__mmask8) __U);
+ 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)
+_mm_mask_cvtepi16_epi32(__m128i __W, __mmask8 __U, __m128i __A)
{
- return (__m128i) __builtin_ia32_pmovsxwd128_mask ((__v8hi) __A,
- (__v4si) __W,
- (__mmask8) __U);
+ 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)
+_mm_maskz_cvtepi16_epi32(__mmask8 __U, __m128i __A)
{
- return (__m128i) __builtin_ia32_pmovsxwd128_mask ((__v8hi) __A,
- (__v4si)
- _mm_setzero_si128 (),
- (__mmask8) __U);
+ 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)
+_mm256_mask_cvtepi16_epi32(__m256i __W, __mmask8 __U, __m128i __A)
{
- return (__m256i) __builtin_ia32_pmovsxwd256_mask ((__v8hi) __A,
- (__v8si) __W,
- (__mmask8) __U);
+ 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_pmovsxwd256_mask ((__v8hi) __A,
- (__v8si)
- _mm256_setzero_si256 (),
- (__mmask8) __U);
+ 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)
+_mm_mask_cvtepi16_epi64(__m128i __W, __mmask8 __U, __m128i __A)
{
- return (__m128i) __builtin_ia32_pmovsxwq128_mask ((__v8hi) __A,
- (__v2di) __W,
- (__mmask8) __U);
+ 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)
+_mm_maskz_cvtepi16_epi64(__mmask8 __U, __m128i __A)
{
- return (__m128i) __builtin_ia32_pmovsxwq128_mask ((__v8hi) __A,
- (__v2di)
- _mm_setzero_si128 (),
- (__mmask8) __U);
+ 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)
+_mm256_mask_cvtepi16_epi64(__m256i __W, __mmask8 __U, __m128i __A)
{
- return (__m256i) __builtin_ia32_pmovsxwq256_mask ((__v8hi) __A,
- (__v4di) __W,
- (__mmask8) __U);
+ 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)
+_mm256_maskz_cvtepi16_epi64(__mmask8 __U, __m128i __A)
{
- return (__m256i) __builtin_ia32_pmovsxwq256_mask ((__v8hi) __A,
- (__v4di)
- _mm256_setzero_si256 (),
- (__mmask8) __U);
+ 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)
+_mm_mask_cvtepu8_epi32(__m128i __W, __mmask8 __U, __m128i __A)
{
- return (__m128i) __builtin_ia32_pmovzxbd128_mask ((__v16qi) __A,
- (__v4si) __W,
- (__mmask8) __U);
+ 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)
+_mm_maskz_cvtepu8_epi32(__mmask8 __U, __m128i __A)
{
- return (__m128i) __builtin_ia32_pmovzxbd128_mask ((__v16qi) __A,
- (__v4si)
- _mm_setzero_si128 (),
- (__mmask8) __U);
+ 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)
+_mm256_mask_cvtepu8_epi32(__m256i __W, __mmask8 __U, __m128i __A)
{
- return (__m256i) __builtin_ia32_pmovzxbd256_mask ((__v16qi) __A,
- (__v8si) __W,
- (__mmask8) __U);
+ 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)
+_mm256_maskz_cvtepu8_epi32(__mmask8 __U, __m128i __A)
{
- return (__m256i) __builtin_ia32_pmovzxbd256_mask ((__v16qi) __A,
- (__v8si)
- _mm256_setzero_si256 (),
- (__mmask8) __U);
+ 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)
+_mm_mask_cvtepu8_epi64(__m128i __W, __mmask8 __U, __m128i __A)
{
- return (__m128i) __builtin_ia32_pmovzxbq128_mask ((__v16qi) __A,
- (__v2di) __W,
- (__mmask8) __U);
+ 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)
+_mm_maskz_cvtepu8_epi64(__mmask8 __U, __m128i __A)
{
- return (__m128i) __builtin_ia32_pmovzxbq128_mask ((__v16qi) __A,
- (__v2di)
- _mm_setzero_si128 (),
- (__mmask8) __U);
+ 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)
+_mm256_mask_cvtepu8_epi64(__m256i __W, __mmask8 __U, __m128i __A)
{
- return (__m256i) __builtin_ia32_pmovzxbq256_mask ((__v16qi) __A,
- (__v4di) __W,
- (__mmask8) __U);
+ 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_pmovzxbq256_mask ((__v16qi) __A,
- (__v4di)
- _mm256_setzero_si256 (),
- (__mmask8) __U);
+ 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)
+_mm_mask_cvtepu32_epi64(__m128i __W, __mmask8 __U, __m128i __X)
{
- return (__m128i) __builtin_ia32_pmovzxdq128_mask ((__v4si) __X,
- (__v2di) __W,
- (__mmask8) __U);
+ 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)
+_mm_maskz_cvtepu32_epi64(__mmask8 __U, __m128i __X)
{
- return (__m128i) __builtin_ia32_pmovzxdq128_mask ((__v4si) __X,
- (__v2di)
- _mm_setzero_si128 (),
- (__mmask8) __U);
+ 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)
+_mm256_mask_cvtepu32_epi64(__m256i __W, __mmask8 __U, __m128i __X)
{
- return (__m256i) __builtin_ia32_pmovzxdq256_mask ((__v4si) __X,
- (__v4di) __W,
- (__mmask8) __U);
+ 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)
+_mm256_maskz_cvtepu32_epi64(__mmask8 __U, __m128i __X)
{
- return (__m256i) __builtin_ia32_pmovzxdq256_mask ((__v4si) __X,
- (__v4di)
- _mm256_setzero_si256 (),
- (__mmask8) __U);
+ 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)
+_mm_mask_cvtepu16_epi32(__m128i __W, __mmask8 __U, __m128i __A)
{
- return (__m128i) __builtin_ia32_pmovzxwd128_mask ((__v8hi) __A,
- (__v4si) __W,
- (__mmask8) __U);
+ 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)
+_mm_maskz_cvtepu16_epi32(__mmask8 __U, __m128i __A)
{
- return (__m128i) __builtin_ia32_pmovzxwd128_mask ((__v8hi) __A,
- (__v4si)
- _mm_setzero_si128 (),
- (__mmask8) __U);
+ 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)
+_mm256_mask_cvtepu16_epi32(__m256i __W, __mmask8 __U, __m128i __A)
{
- return (__m256i) __builtin_ia32_pmovzxwd256_mask ((__v8hi) __A,
- (__v8si) __W,
- (__mmask8) __U);
+ 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)
+_mm256_maskz_cvtepu16_epi32(__mmask8 __U, __m128i __A)
{
- return (__m256i) __builtin_ia32_pmovzxwd256_mask ((__v8hi) __A,
- (__v8si)
- _mm256_setzero_si256 (),
- (__mmask8) __U);
+ 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)
+_mm_mask_cvtepu16_epi64(__m128i __W, __mmask8 __U, __m128i __A)
{
- return (__m128i) __builtin_ia32_pmovzxwq128_mask ((__v8hi) __A,
- (__v2di) __W,
- (__mmask8) __U);
+ 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)
+_mm_maskz_cvtepu16_epi64(__mmask8 __U, __m128i __A)
{
- return (__m128i) __builtin_ia32_pmovzxwq128_mask ((__v8hi) __A,
- (__v2di)
- _mm_setzero_si128 (),
- (__mmask8) __U);
+ 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)
+_mm256_mask_cvtepu16_epi64(__m256i __W, __mmask8 __U, __m128i __A)
{
- return (__m256i) __builtin_ia32_pmovzxwq256_mask ((__v8hi) __A,
- (__v4di) __W,
- (__mmask8) __U);
+ 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)
+_mm256_maskz_cvtepu16_epi64(__mmask8 __U, __m128i __A)
{
- return (__m256i) __builtin_ia32_pmovzxwq256_mask ((__v8hi) __A,
- (__v4di)
- _mm256_setzero_si256 (),
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
+ (__v4di)_mm256_cvtepu16_epi64(__A),
+ (__v4di)_mm256_setzero_si256());
}
@@ -5125,125 +4939,132 @@ _mm256_maskz_rolv_epi64 (__mmask8 __U, __m256i __A, __m256i __B)
(__mmask8)(U)); })
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_sll_epi32 (__m128i __W, __mmask8 __U, __m128i __A,
- __m128i __B)
+_mm_mask_sll_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_pslld128_mask ((__v4si) __A,
- (__v4si) __B,
- (__v4si) __W,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
+ (__v4si)_mm_sll_epi32(__A, __B),
+ (__v4si)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_sll_epi32 (__mmask8 __U, __m128i __A, __m128i __B)
+_mm_maskz_sll_epi32(__mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_pslld128_mask ((__v4si) __A,
- (__v4si) __B,
- (__v4si)
- _mm_setzero_si128 (),
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
+ (__v4si)_mm_sll_epi32(__A, __B),
+ (__v4si)_mm_setzero_si128());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_sll_epi32 (__m256i __W, __mmask8 __U, __m256i __A,
- __m128i __B)
+_mm256_mask_sll_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m128i __B)
{
- return (__m256i) __builtin_ia32_pslld256_mask ((__v8si) __A,
- (__v4si) __B,
- (__v8si) __W,
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
+ (__v8si)_mm256_sll_epi32(__A, __B),
+ (__v8si)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_sll_epi32 (__mmask8 __U, __m256i __A, __m128i __B)
+_mm256_maskz_sll_epi32(__mmask8 __U, __m256i __A, __m128i __B)
{
- return (__m256i) __builtin_ia32_pslld256_mask ((__v8si) __A,
- (__v4si) __B,
- (__v8si)
- _mm256_setzero_si256 (),
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
+ (__v8si)_mm256_sll_epi32(__A, __B),
+ (__v8si)_mm256_setzero_si256());
}
-#define _mm_mask_slli_epi32(W, U, A, B) __extension__ ({ \
- (__m128i)__builtin_ia32_pslldi128_mask((__v4si)(__m128i)(A), (int)(B), \
- (__v4si)(__m128i)(W), \
- (__mmask8)(U)); })
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_slli_epi32(__m128i __W, __mmask8 __U, __m128i __A, int __B)
+{
+ return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
+ (__v4si)_mm_slli_epi32(__A, __B),
+ (__v4si)__W);
+}
-#define _mm_maskz_slli_epi32(U, A, B) __extension__ ({ \
- (__m128i)__builtin_ia32_pslldi128_mask((__v4si)(__m128i)(A), (int)(B), \
- (__v4si)_mm_setzero_si128(), \
- (__mmask8)(U)); })
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_slli_epi32(__mmask8 __U, __m128i __A, int __B)
+{
+ return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
+ (__v4si)_mm_slli_epi32(__A, __B),
+ (__v4si)_mm_setzero_si128());
+}
-#define _mm256_mask_slli_epi32(W, U, A, B) __extension__ ({ \
- (__m256i)__builtin_ia32_pslldi256_mask((__v8si)(__m256i)(A), (int)(B), \
- (__v8si)(__m256i)(W), \
- (__mmask8)(U)); })
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_slli_epi32(__m256i __W, __mmask8 __U, __m256i __A, int __B)
+{
+ return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
+ (__v8si)_mm256_slli_epi32(__A, __B),
+ (__v8si)__W);
+}
-#define _mm256_maskz_slli_epi32(U, A, B) __extension__ ({ \
- (__m256i)__builtin_ia32_pslldi256_mask((__v8si)(__m256i)(A), (int)(B), \
- (__v8si)_mm256_setzero_si256(), \
- (__mmask8)(U)); })
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_slli_epi32(__mmask8 __U, __m256i __A, int __B)
+{
+ return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
+ (__v8si)_mm256_slli_epi32(__A, __B),
+ (__v8si)_mm256_setzero_si256());
+}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_sll_epi64 (__m128i __W, __mmask8 __U, __m128i __A,
- __m128i __B)
+_mm_mask_sll_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_psllq128_mask ((__v2di) __A,
- (__v2di) __B,
- (__v2di) __W,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
+ (__v2di)_mm_sll_epi64(__A, __B),
+ (__v2di)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_sll_epi64 (__mmask8 __U, __m128i __A, __m128i __B)
+_mm_maskz_sll_epi64(__mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_psllq128_mask ((__v2di) __A,
- (__v2di) __B,
- (__v2di)
- _mm_setzero_di (),
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
+ (__v2di)_mm_sll_epi64(__A, __B),
+ (__v2di)_mm_setzero_di());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_sll_epi64 (__m256i __W, __mmask8 __U, __m256i __A,
- __m128i __B)
+_mm256_mask_sll_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m128i __B)
{
- return (__m256i) __builtin_ia32_psllq256_mask ((__v4di) __A,
- (__v2di) __B,
- (__v4di) __W,
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
+ (__v4di)_mm256_sll_epi64(__A, __B),
+ (__v4di)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_sll_epi64 (__mmask8 __U, __m256i __A, __m128i __B)
+_mm256_maskz_sll_epi64(__mmask8 __U, __m256i __A, __m128i __B)
{
- return (__m256i) __builtin_ia32_psllq256_mask ((__v4di) __A,
- (__v2di) __B,
- (__v4di)
- _mm256_setzero_si256 (),
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
+ (__v4di)_mm256_sll_epi64(__A, __B),
+ (__v4di)_mm256_setzero_si256());
}
-#define _mm_mask_slli_epi64(W, U, A, B) __extension__ ({ \
- (__m128i)__builtin_ia32_psllqi128_mask((__v2di)(__m128i)(A), (int)(B), \
- (__v2di)(__m128i)(W), \
- (__mmask8)(U)); })
-
-#define _mm_maskz_slli_epi64(U, A, B) __extension__ ({ \
- (__m128i)__builtin_ia32_psllqi128_mask((__v2di)(__m128i)(A), (int)(B), \
- (__v2di)_mm_setzero_di(), \
- (__mmask8)(U)); })
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_slli_epi64(__m128i __W, __mmask8 __U, __m128i __A, int __B)
+{
+ return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
+ (__v2di)_mm_slli_epi64(__A, __B),
+ (__v2di)__W);
+}
-#define _mm256_mask_slli_epi64(W, U, A, B) __extension__ ({ \
- (__m256i)__builtin_ia32_psllqi256_mask((__v4di)(__m256i)(A), (int)(B), \
- (__v4di)(__m256i)(W), \
- (__mmask8)(U)); })
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_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());
+}
-#define _mm256_maskz_slli_epi64(U, A, B) __extension__ ({ \
- (__m256i)__builtin_ia32_psllqi256_mask((__v4di)(__m256i)(A), (int)(B), \
- (__v4di)_mm256_setzero_si256(), \
- (__mmask8)(U)); })
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_slli_epi64(__m256i __W, __mmask8 __U, __m256i __A, int __B)
+{
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
+ (__v4di)_mm256_slli_epi64(__A, __B),
+ (__v4di)__W);
+}
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_slli_epi64(__mmask8 __U, __m256i __A, int __B)
+{
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
+ (__v4di)_mm256_slli_epi64(__A, __B),
+ (__v4di)_mm256_setzero_si256());
+}
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_rorv_epi32 (__m128i __A, __m128i __B)
@@ -5366,387 +5187,335 @@ _mm256_maskz_rorv_epi64 (__mmask8 __U, __m256i __A, __m256i __B)
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_sllv_epi64 (__m128i __W, __mmask8 __U, __m128i __X,
- __m128i __Y)
+_mm_mask_sllv_epi64(__m128i __W, __mmask8 __U, __m128i __X, __m128i __Y)
{
- return (__m128i) __builtin_ia32_psllv2di_mask ((__v2di) __X,
- (__v2di) __Y,
- (__v2di) __W,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
+ (__v2di)_mm_sllv_epi64(__X, __Y),
+ (__v2di)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_sllv_epi64 (__mmask8 __U, __m128i __X, __m128i __Y)
+_mm_maskz_sllv_epi64(__mmask8 __U, __m128i __X, __m128i __Y)
{
- return (__m128i) __builtin_ia32_psllv2di_mask ((__v2di) __X,
- (__v2di) __Y,
- (__v2di)
- _mm_setzero_di (),
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
+ (__v2di)_mm_sllv_epi64(__X, __Y),
+ (__v2di)_mm_setzero_di());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_sllv_epi64 (__m256i __W, __mmask8 __U, __m256i __X,
- __m256i __Y)
+_mm256_mask_sllv_epi64(__m256i __W, __mmask8 __U, __m256i __X, __m256i __Y)
{
- return (__m256i) __builtin_ia32_psllv4di_mask ((__v4di) __X,
- (__v4di) __Y,
- (__v4di) __W,
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
+ (__v4di)_mm256_sllv_epi64(__X, __Y),
+ (__v4di)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_sllv_epi64 (__mmask8 __U, __m256i __X, __m256i __Y)
+_mm256_maskz_sllv_epi64(__mmask8 __U, __m256i __X, __m256i __Y)
{
- return (__m256i) __builtin_ia32_psllv4di_mask ((__v4di) __X,
- (__v4di) __Y,
- (__v4di)
- _mm256_setzero_si256 (),
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
+ (__v4di)_mm256_sllv_epi64(__X, __Y),
+ (__v4di)_mm256_setzero_si256());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_sllv_epi32 (__m128i __W, __mmask8 __U, __m128i __X,
- __m128i __Y)
+_mm_mask_sllv_epi32(__m128i __W, __mmask8 __U, __m128i __X, __m128i __Y)
{
- return (__m128i) __builtin_ia32_psllv4si_mask ((__v4si) __X,
- (__v4si) __Y,
- (__v4si) __W,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
+ (__v4si)_mm_sllv_epi32(__X, __Y),
+ (__v4si)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_sllv_epi32 (__mmask8 __U, __m128i __X, __m128i __Y)
+_mm_maskz_sllv_epi32(__mmask8 __U, __m128i __X, __m128i __Y)
{
- return (__m128i) __builtin_ia32_psllv4si_mask ((__v4si) __X,
- (__v4si) __Y,
- (__v4si)
- _mm_setzero_si128 (),
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
+ (__v4si)_mm_sllv_epi32(__X, __Y),
+ (__v4si)_mm_setzero_si128());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_sllv_epi32 (__m256i __W, __mmask8 __U, __m256i __X,
- __m256i __Y)
+_mm256_mask_sllv_epi32(__m256i __W, __mmask8 __U, __m256i __X, __m256i __Y)
{
- return (__m256i) __builtin_ia32_psllv8si_mask ((__v8si) __X,
- (__v8si) __Y,
- (__v8si) __W,
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
+ (__v8si)_mm256_sllv_epi32(__X, __Y),
+ (__v8si)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_sllv_epi32 (__mmask8 __U, __m256i __X, __m256i __Y)
+_mm256_maskz_sllv_epi32(__mmask8 __U, __m256i __X, __m256i __Y)
{
- return (__m256i) __builtin_ia32_psllv8si_mask ((__v8si) __X,
- (__v8si) __Y,
- (__v8si)
- _mm256_setzero_si256 (),
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
+ (__v8si)_mm256_sllv_epi32(__X, __Y),
+ (__v8si)_mm256_setzero_si256());
}
-
-
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_srlv_epi64 (__m128i __W, __mmask8 __U, __m128i __X,
- __m128i __Y)
+_mm_mask_srlv_epi64(__m128i __W, __mmask8 __U, __m128i __X, __m128i __Y)
{
- return (__m128i) __builtin_ia32_psrlv2di_mask ((__v2di) __X,
- (__v2di) __Y,
- (__v2di) __W,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
+ (__v2di)_mm_srlv_epi64(__X, __Y),
+ (__v2di)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_srlv_epi64 (__mmask8 __U, __m128i __X, __m128i __Y)
+_mm_maskz_srlv_epi64(__mmask8 __U, __m128i __X, __m128i __Y)
{
- return (__m128i) __builtin_ia32_psrlv2di_mask ((__v2di) __X,
- (__v2di) __Y,
- (__v2di)
- _mm_setzero_di (),
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
+ (__v2di)_mm_srlv_epi64(__X, __Y),
+ (__v2di)_mm_setzero_di());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_srlv_epi64 (__m256i __W, __mmask8 __U, __m256i __X,
- __m256i __Y)
+_mm256_mask_srlv_epi64(__m256i __W, __mmask8 __U, __m256i __X, __m256i __Y)
{
- return (__m256i) __builtin_ia32_psrlv4di_mask ((__v4di) __X,
- (__v4di) __Y,
- (__v4di) __W,
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
+ (__v4di)_mm256_srlv_epi64(__X, __Y),
+ (__v4di)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_srlv_epi64 (__mmask8 __U, __m256i __X, __m256i __Y)
+_mm256_maskz_srlv_epi64(__mmask8 __U, __m256i __X, __m256i __Y)
{
- return (__m256i) __builtin_ia32_psrlv4di_mask ((__v4di) __X,
- (__v4di) __Y,
- (__v4di)
- _mm256_setzero_si256 (),
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
+ (__v4di)_mm256_srlv_epi64(__X, __Y),
+ (__v4di)_mm256_setzero_si256());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_srlv_epi32 (__m128i __W, __mmask8 __U, __m128i __X,
- __m128i __Y)
+_mm_mask_srlv_epi32(__m128i __W, __mmask8 __U, __m128i __X, __m128i __Y)
{
- return (__m128i) __builtin_ia32_psrlv4si_mask ((__v4si) __X,
- (__v4si) __Y,
- (__v4si) __W,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
+ (__v4si)_mm_srlv_epi32(__X, __Y),
+ (__v4si)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_srlv_epi32 (__mmask8 __U, __m128i __X, __m128i __Y)
+_mm_maskz_srlv_epi32(__mmask8 __U, __m128i __X, __m128i __Y)
{
- return (__m128i) __builtin_ia32_psrlv4si_mask ((__v4si) __X,
- (__v4si) __Y,
- (__v4si)
- _mm_setzero_si128 (),
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
+ (__v4si)_mm_srlv_epi32(__X, __Y),
+ (__v4si)_mm_setzero_si128());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_srlv_epi32 (__m256i __W, __mmask8 __U, __m256i __X,
- __m256i __Y)
+_mm256_mask_srlv_epi32(__m256i __W, __mmask8 __U, __m256i __X, __m256i __Y)
{
- return (__m256i) __builtin_ia32_psrlv8si_mask ((__v8si) __X,
- (__v8si) __Y,
- (__v8si) __W,
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
+ (__v8si)_mm256_srlv_epi32(__X, __Y),
+ (__v8si)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_srlv_epi32 (__mmask8 __U, __m256i __X, __m256i __Y)
+_mm256_maskz_srlv_epi32(__mmask8 __U, __m256i __X, __m256i __Y)
{
- return (__m256i) __builtin_ia32_psrlv8si_mask ((__v8si) __X,
- (__v8si) __Y,
- (__v8si)
- _mm256_setzero_si256 (),
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
+ (__v8si)_mm256_srlv_epi32(__X, __Y),
+ (__v8si)_mm256_setzero_si256());
}
-
-
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_srl_epi32 (__m128i __W, __mmask8 __U, __m128i __A,
- __m128i __B)
+_mm_mask_srl_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_psrld128_mask ((__v4si) __A,
- (__v4si) __B,
- (__v4si) __W,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
+ (__v4si)_mm_srl_epi32(__A, __B),
+ (__v4si)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_srl_epi32 (__mmask8 __U, __m128i __A, __m128i __B)
+_mm_maskz_srl_epi32(__mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_psrld128_mask ((__v4si) __A,
- (__v4si) __B,
- (__v4si)
- _mm_setzero_si128 (),
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
+ (__v4si)_mm_srl_epi32(__A, __B),
+ (__v4si)_mm_setzero_si128());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_srl_epi32 (__m256i __W, __mmask8 __U, __m256i __A,
- __m128i __B)
+_mm256_mask_srl_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m128i __B)
{
- return (__m256i) __builtin_ia32_psrld256_mask ((__v8si) __A,
- (__v4si) __B,
- (__v8si) __W,
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
+ (__v8si)_mm256_srl_epi32(__A, __B),
+ (__v8si)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_srl_epi32 (__mmask8 __U, __m256i __A, __m128i __B)
+_mm256_maskz_srl_epi32(__mmask8 __U, __m256i __A, __m128i __B)
{
- return (__m256i) __builtin_ia32_psrld256_mask ((__v8si) __A,
- (__v4si) __B,
- (__v8si)
- _mm256_setzero_si256 (),
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
+ (__v8si)_mm256_srl_epi32(__A, __B),
+ (__v8si)_mm256_setzero_si256());
}
-#define _mm_mask_srli_epi32(W, U, A, imm) __extension__ ({ \
- (__m128i)__builtin_ia32_psrldi128_mask((__v4si)(__m128i)(A), (int)(imm), \
- (__v4si)(__m128i)(W), \
- (__mmask8)(U)); })
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_srli_epi32(__m128i __W, __mmask8 __U, __m128i __A, int __B)
+{
+ return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
+ (__v4si)_mm_srli_epi32(__A, __B),
+ (__v4si)__W);
+}
-#define _mm_maskz_srli_epi32(U, A, imm) __extension__ ({ \
- (__m128i)__builtin_ia32_psrldi128_mask((__v4si)(__m128i)(A), (int)(imm), \
- (__v4si)_mm_setzero_si128(), \
- (__mmask8)(U)); })
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_srli_epi32(__mmask8 __U, __m128i __A, int __B)
+{
+ return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
+ (__v4si)_mm_srli_epi32(__A, __B),
+ (__v4si)_mm_setzero_si128());
+}
-#define _mm256_mask_srli_epi32(W, U, A, imm) __extension__ ({ \
- (__m256i)__builtin_ia32_psrldi256_mask((__v8si)(__m256i)(A), (int)(imm), \
- (__v8si)(__m256i)(W), \
- (__mmask8)(U)); })
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_srli_epi32(__m256i __W, __mmask8 __U, __m256i __A, int __B)
+{
+ return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
+ (__v8si)_mm256_srli_epi32(__A, __B),
+ (__v8si)__W);
+}
-#define _mm256_maskz_srli_epi32(U, A, imm) __extension__ ({ \
- (__m256i)__builtin_ia32_psrldi256_mask((__v8si)(__m256i)(A), (int)(imm), \
- (__v8si)_mm256_setzero_si256(), \
- (__mmask8)(U)); })
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_srli_epi32(__mmask8 __U, __m256i __A, int __B)
+{
+ return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
+ (__v8si)_mm256_srli_epi32(__A, __B),
+ (__v8si)_mm256_setzero_si256());
+}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_srl_epi64 (__m128i __W, __mmask8 __U, __m128i __A,
- __m128i __B)
+_mm_mask_srl_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_psrlq128_mask ((__v2di) __A,
- (__v2di) __B,
- (__v2di) __W,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
+ (__v2di)_mm_srl_epi64(__A, __B),
+ (__v2di)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_srl_epi64 (__mmask8 __U, __m128i __A, __m128i __B)
+_mm_maskz_srl_epi64(__mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_psrlq128_mask ((__v2di) __A,
- (__v2di) __B,
- (__v2di)
- _mm_setzero_di (),
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
+ (__v2di)_mm_srl_epi64(__A, __B),
+ (__v2di)_mm_setzero_di());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_srl_epi64 (__m256i __W, __mmask8 __U, __m256i __A,
- __m128i __B)
+_mm256_mask_srl_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m128i __B)
{
- return (__m256i) __builtin_ia32_psrlq256_mask ((__v4di) __A,
- (__v2di) __B,
- (__v4di) __W,
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
+ (__v4di)_mm256_srl_epi64(__A, __B),
+ (__v4di)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_srl_epi64 (__mmask8 __U, __m256i __A, __m128i __B)
+_mm256_maskz_srl_epi64(__mmask8 __U, __m256i __A, __m128i __B)
{
- return (__m256i) __builtin_ia32_psrlq256_mask ((__v4di) __A,
- (__v2di) __B,
- (__v4di)
- _mm256_setzero_si256 (),
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
+ (__v4di)_mm256_srl_epi64(__A, __B),
+ (__v4di)_mm256_setzero_si256());
}
-#define _mm_mask_srli_epi64(W, U, A, imm) __extension__ ({ \
- (__m128i)__builtin_ia32_psrlqi128_mask((__v2di)(__m128i)(A), (int)(imm), \
- (__v2di)(__m128i)(W), \
- (__mmask8)(U)); })
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_srli_epi64(__m128i __W, __mmask8 __U, __m128i __A, int __B)
+{
+ return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
+ (__v2di)_mm_srli_epi64(__A, __B),
+ (__v2di)__W);
+}
-#define _mm_maskz_srli_epi64(U, A, imm) __extension__ ({ \
- (__m128i)__builtin_ia32_psrlqi128_mask((__v2di)(__m128i)(A), (int)(imm), \
- (__v2di)_mm_setzero_si128(), \
- (__mmask8)(U)); })
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_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());
+}
-#define _mm256_mask_srli_epi64(W, U, A, imm) __extension__ ({ \
- (__m256i)__builtin_ia32_psrlqi256_mask((__v4di)(__m256i)(A), (int)(imm), \
- (__v4di)(__m256i)(W), \
- (__mmask8)(U)); })
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_srli_epi64(__m256i __W, __mmask8 __U, __m256i __A, int __B)
+{
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
+ (__v4di)_mm256_srli_epi64(__A, __B),
+ (__v4di)__W);
+}
-#define _mm256_maskz_srli_epi64(U, A, imm) __extension__ ({ \
- (__m256i)__builtin_ia32_psrlqi256_mask((__v4di)(__m256i)(A), (int)(imm), \
- (__v4di)_mm256_setzero_si256(), \
- (__mmask8)(U)); })
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_srli_epi64(__mmask8 __U, __m256i __A, int __B)
+{
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
+ (__v4di)_mm256_srli_epi64(__A, __B),
+ (__v4di)_mm256_setzero_si256());
+}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_srav_epi32 (__m128i __W, __mmask8 __U, __m128i __X,
- __m128i __Y)
+_mm_mask_srav_epi32(__m128i __W, __mmask8 __U, __m128i __X, __m128i __Y)
{
- return (__m128i) __builtin_ia32_psrav4si_mask ((__v4si) __X,
- (__v4si) __Y,
- (__v4si) __W,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
+ (__v4si)_mm_srav_epi32(__X, __Y),
+ (__v4si)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_srav_epi32 (__mmask8 __U, __m128i __X, __m128i __Y)
+_mm_maskz_srav_epi32(__mmask8 __U, __m128i __X, __m128i __Y)
{
- return (__m128i) __builtin_ia32_psrav4si_mask ((__v4si) __X,
- (__v4si) __Y,
- (__v4si)
- _mm_setzero_si128 (),
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
+ (__v4si)_mm_srav_epi32(__X, __Y),
+ (__v4si)_mm_setzero_si128());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_srav_epi32 (__m256i __W, __mmask8 __U, __m256i __X,
- __m256i __Y)
+_mm256_mask_srav_epi32(__m256i __W, __mmask8 __U, __m256i __X, __m256i __Y)
{
- return (__m256i) __builtin_ia32_psrav8si_mask ((__v8si) __X,
- (__v8si) __Y,
- (__v8si) __W,
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
+ (__v8si)_mm256_srav_epi32(__X, __Y),
+ (__v8si)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_srav_epi32 (__mmask8 __U, __m256i __X, __m256i __Y)
+_mm256_maskz_srav_epi32(__mmask8 __U, __m256i __X, __m256i __Y)
{
- return (__m256i) __builtin_ia32_psrav8si_mask ((__v8si) __X,
- (__v8si) __Y,
- (__v8si)
- _mm256_setzero_si256 (),
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
+ (__v8si)_mm256_srav_epi32(__X, __Y),
+ (__v8si)_mm256_setzero_si256());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_srav_epi64 (__m128i __X, __m128i __Y)
+_mm_srav_epi64(__m128i __X, __m128i __Y)
{
- return (__m128i) __builtin_ia32_psravq128_mask ((__v2di) __X,
- (__v2di) __Y,
- (__v2di)
- _mm_setzero_di (),
- (__mmask8) -1);
+ return (__m128i)__builtin_ia32_psravq128((__v2di)__X, (__v2di)__Y);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_srav_epi64 (__m128i __W, __mmask8 __U, __m128i __X,
- __m128i __Y)
+_mm_mask_srav_epi64(__m128i __W, __mmask8 __U, __m128i __X, __m128i __Y)
{
- return (__m128i) __builtin_ia32_psravq128_mask ((__v2di) __X,
- (__v2di) __Y,
- (__v2di) __W,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
+ (__v2di)_mm_srav_epi64(__X, __Y),
+ (__v2di)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_srav_epi64 (__mmask8 __U, __m128i __X, __m128i __Y)
+_mm_maskz_srav_epi64(__mmask8 __U, __m128i __X, __m128i __Y)
{
- return (__m128i) __builtin_ia32_psravq128_mask ((__v2di) __X,
- (__v2di) __Y,
- (__v2di)
- _mm_setzero_di (),
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U,
+ (__v2di)_mm_srav_epi64(__X, __Y),
+ (__v2di)_mm_setzero_di());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_srav_epi64 (__m256i __X, __m256i __Y)
+_mm256_srav_epi64(__m256i __X, __m256i __Y)
{
- return (__m256i) __builtin_ia32_psravq256_mask ((__v4di) __X,
- (__v4di) __Y,
- (__v4di)
- _mm256_setzero_si256 (),
- (__mmask8) -1);
+ return (__m256i)__builtin_ia32_psravq256((__v4di)__X, (__v4di) __Y);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_srav_epi64 (__m256i __W, __mmask8 __U, __m256i __X,
- __m256i __Y)
+_mm256_mask_srav_epi64(__m256i __W, __mmask8 __U, __m256i __X, __m256i __Y)
{
- return (__m256i) __builtin_ia32_psravq256_mask ((__v4di) __X,
- (__v4di) __Y,
- (__v4di) __W,
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
+ (__v4di)_mm256_srav_epi64(__X, __Y),
+ (__v4di)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_maskz_srav_epi64 (__mmask8 __U, __m256i __X, __m256i __Y)
{
- return (__m256i) __builtin_ia32_psravq256_mask ((__v4di) __X,
- (__v4di) __Y,
- (__v4di)
- _mm256_setzero_si256 (),
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U,
+ (__v4di)_mm256_srav_epi64(__X, __Y),
+ (__v4di)_mm256_setzero_si256());
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
@@ -5975,6 +5744,7 @@ _mm256_maskz_movedup_pd (__mmask8 __U, __m256d __A)
(__v8si)_mm256_setzero_si256(), \
(__mmask8)(M)); })
+#ifdef __x86_64__
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_mask_set1_epi64 (__m128i __O, __mmask8 __M, long long __A)
{
@@ -6006,6 +5776,7 @@ _mm256_maskz_set1_epi64 (__mmask8 __M, long long __A)
_mm256_setzero_si256 (),
__M);
}
+#endif
#define _mm_fixupimm_pd(A, B, C, imm) __extension__ ({ \
(__m128d)__builtin_ia32_fixupimmpd128_mask((__v2df)(__m128d)(A), \
@@ -6653,85 +6424,67 @@ _mm256_maskz_rcp14_ps (__mmask8 __U, __m256 __A)
(__v8sf)_mm256_setzero_ps()); })
static __inline__ __m128d __DEFAULT_FN_ATTRS
-_mm_mask_permutevar_pd (__m128d __W, __mmask8 __U, __m128d __A,
- __m128i __C)
+_mm_mask_permutevar_pd(__m128d __W, __mmask8 __U, __m128d __A, __m128i __C)
{
- return (__m128d) __builtin_ia32_vpermilvarpd_mask ((__v2df) __A,
- (__v2di) __C,
- (__v2df) __W,
- (__mmask8) __U);
+ return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U,
+ (__v2df)_mm_permutevar_pd(__A, __C),
+ (__v2df)__W);
}
static __inline__ __m128d __DEFAULT_FN_ATTRS
-_mm_maskz_permutevar_pd (__mmask8 __U, __m128d __A, __m128i __C)
+_mm_maskz_permutevar_pd(__mmask8 __U, __m128d __A, __m128i __C)
{
- return (__m128d) __builtin_ia32_vpermilvarpd_mask ((__v2df) __A,
- (__v2di) __C,
- (__v2df)
- _mm_setzero_pd (),
- (__mmask8) __U);
+ return (__m128d)__builtin_ia32_selectpd_128((__mmask8)__U,
+ (__v2df)_mm_permutevar_pd(__A, __C),
+ (__v2df)_mm_setzero_pd());
}
static __inline__ __m256d __DEFAULT_FN_ATTRS
-_mm256_mask_permutevar_pd (__m256d __W, __mmask8 __U, __m256d __A,
- __m256i __C)
+_mm256_mask_permutevar_pd(__m256d __W, __mmask8 __U, __m256d __A, __m256i __C)
{
- return (__m256d) __builtin_ia32_vpermilvarpd256_mask ((__v4df) __A,
- (__v4di) __C,
- (__v4df) __W,
- (__mmask8)
- __U);
+ return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U,
+ (__v4df)_mm256_permutevar_pd(__A, __C),
+ (__v4df)__W);
}
static __inline__ __m256d __DEFAULT_FN_ATTRS
-_mm256_maskz_permutevar_pd (__mmask8 __U, __m256d __A, __m256i __C)
+_mm256_maskz_permutevar_pd(__mmask8 __U, __m256d __A, __m256i __C)
{
- return (__m256d) __builtin_ia32_vpermilvarpd256_mask ((__v4df) __A,
- (__v4di) __C,
- (__v4df)
- _mm256_setzero_pd (),
- (__mmask8)
- __U);
+ return (__m256d)__builtin_ia32_selectpd_256((__mmask8)__U,
+ (__v4df)_mm256_permutevar_pd(__A, __C),
+ (__v4df)_mm256_setzero_pd());
}
static __inline__ __m128 __DEFAULT_FN_ATTRS
-_mm_mask_permutevar_ps (__m128 __W, __mmask8 __U, __m128 __A,
- __m128i __C)
+_mm_mask_permutevar_ps(__m128 __W, __mmask8 __U, __m128 __A, __m128i __C)
{
- return (__m128) __builtin_ia32_vpermilvarps_mask ((__v4sf) __A,
- (__v4si) __C,
- (__v4sf) __W,
- (__mmask8) __U);
+ return (__m128)__builtin_ia32_selectps_128((__mmask8)__U,
+ (__v4sf)_mm_permutevar_ps(__A, __C),
+ (__v4sf)__W);
}
static __inline__ __m128 __DEFAULT_FN_ATTRS
-_mm_maskz_permutevar_ps (__mmask8 __U, __m128 __A, __m128i __C)
+_mm_maskz_permutevar_ps(__mmask8 __U, __m128 __A, __m128i __C)
{
- return (__m128) __builtin_ia32_vpermilvarps_mask ((__v4sf) __A,
- (__v4si) __C,
- (__v4sf)
- _mm_setzero_ps (),
- (__mmask8) __U);
+ return (__m128)__builtin_ia32_selectps_128((__mmask8)__U,
+ (__v4sf)_mm_permutevar_ps(__A, __C),
+ (__v4sf)_mm_setzero_ps());
}
static __inline__ __m256 __DEFAULT_FN_ATTRS
-_mm256_mask_permutevar_ps (__m256 __W, __mmask8 __U, __m256 __A,
- __m256i __C)
+_mm256_mask_permutevar_ps(__m256 __W, __mmask8 __U, __m256 __A, __m256i __C)
{
- return (__m256) __builtin_ia32_vpermilvarps256_mask ((__v8sf) __A,
- (__v8si) __C,
- (__v8sf) __W,
- (__mmask8) __U);
+ return (__m256)__builtin_ia32_selectps_256((__mmask8)__U,
+ (__v8sf)_mm256_permutevar_ps(__A, __C),
+ (__v8sf)__W);
}
static __inline__ __m256 __DEFAULT_FN_ATTRS
-_mm256_maskz_permutevar_ps (__mmask8 __U, __m256 __A, __m256i __C)
+_mm256_maskz_permutevar_ps(__mmask8 __U, __m256 __A, __m256i __C)
{
- return (__m256) __builtin_ia32_vpermilvarps256_mask ((__v8sf) __A,
- (__v8si) __C,
- (__v8sf)
- _mm256_setzero_ps (),
- (__mmask8) __U);
+ return (__m256)__builtin_ia32_selectps_256((__mmask8)__U,
+ (__v8sf)_mm256_permutevar_ps(__A, __C),
+ (__v8sf)_mm256_setzero_ps());
}
static __inline__ __mmask8 __DEFAULT_FN_ATTRS
@@ -6985,154 +6738,156 @@ _mm256_maskz_unpacklo_epi64(__mmask8 __U, __m256i __A, __m256i __B)
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_sra_epi32 (__m128i __W, __mmask8 __U, __m128i __A,
- __m128i __B)
+_mm_mask_sra_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_psrad128_mask ((__v4si) __A,
- (__v4si) __B,
- (__v4si) __W,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
+ (__v4si)_mm_sra_epi32(__A, __B),
+ (__v4si)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_sra_epi32 (__mmask8 __U, __m128i __A, __m128i __B)
+_mm_maskz_sra_epi32(__mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_psrad128_mask ((__v4si) __A,
- (__v4si) __B,
- (__v4si)
- _mm_setzero_si128 (),
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
+ (__v4si)_mm_sra_epi32(__A, __B),
+ (__v4si)_mm_setzero_si128());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_sra_epi32 (__m256i __W, __mmask8 __U, __m256i __A,
- __m128i __B)
+_mm256_mask_sra_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m128i __B)
{
- return (__m256i) __builtin_ia32_psrad256_mask ((__v8si) __A,
- (__v4si) __B,
- (__v8si) __W,
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
+ (__v8si)_mm256_sra_epi32(__A, __B),
+ (__v8si)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_sra_epi32 (__mmask8 __U, __m256i __A, __m128i __B)
+_mm256_maskz_sra_epi32(__mmask8 __U, __m256i __A, __m128i __B)
{
- return (__m256i) __builtin_ia32_psrad256_mask ((__v8si) __A,
- (__v4si) __B,
- (__v8si)
- _mm256_setzero_si256 (),
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
+ (__v8si)_mm256_sra_epi32(__A, __B),
+ (__v8si)_mm256_setzero_si256());
}
-#define _mm_mask_srai_epi32(W, U, A, imm) __extension__ ({ \
- (__m128i)__builtin_ia32_psradi128_mask((__v4si)(__m128i)(A), (int)(imm), \
- (__v4si)(__m128i)(W), \
- (__mmask8)(U)); })
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_srai_epi32(__m128i __W, __mmask8 __U, __m128i __A, int __B)
+{
+ return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
+ (__v4si)_mm_srai_epi32(__A, __B),
+ (__v4si)__W);
+}
-#define _mm_maskz_srai_epi32(U, A, imm) __extension__ ({ \
- (__m128i)__builtin_ia32_psradi128_mask((__v4si)(__m128i)(A), (int)(imm), \
- (__v4si)_mm_setzero_si128(), \
- (__mmask8)(U)); })
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_maskz_srai_epi32(__mmask8 __U, __m128i __A, int __B)
+{
+ return (__m128i)__builtin_ia32_selectd_128((__mmask8)__U,
+ (__v4si)_mm_srai_epi32(__A, __B),
+ (__v4si)_mm_setzero_si128());
+}
-#define _mm256_mask_srai_epi32(W, U, A, imm) __extension__ ({ \
- (__m256i)__builtin_ia32_psradi256_mask((__v8si)(__m256i)(A), (int)(imm), \
- (__v8si)(__m256i)(W), \
- (__mmask8)(U)); })
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_srai_epi32(__m256i __W, __mmask8 __U, __m256i __A, int __B)
+{
+ return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
+ (__v8si)_mm256_srai_epi32(__A, __B),
+ (__v8si)__W);
+}
-#define _mm256_maskz_srai_epi32(U, A, imm) __extension__ ({ \
- (__m256i)__builtin_ia32_psradi256_mask((__v8si)(__m256i)(A), (int)(imm), \
- (__v8si)_mm256_setzero_si256(), \
- (__mmask8)(U)); })
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_srai_epi32(__mmask8 __U, __m256i __A, int __B)
+{
+ return (__m256i)__builtin_ia32_selectd_256((__mmask8)__U,
+ (__v8si)_mm256_srai_epi32(__A, __B),
+ (__v8si)_mm256_setzero_si256());
+}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_sra_epi64 (__m128i __A, __m128i __B)
+_mm_sra_epi64(__m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_psraq128_mask ((__v2di) __A,
- (__v2di) __B,
- (__v2di)
- _mm_setzero_di (),
- (__mmask8) -1);
+ return (__m128i)__builtin_ia32_psraq128((__v2di)__A, (__v2di)__B);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_mask_sra_epi64 (__m128i __W, __mmask8 __U, __m128i __A,
- __m128i __B)
+_mm_mask_sra_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_psraq128_mask ((__v2di) __A,
- (__v2di) __B,
- (__v2di) __W,
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, \
+ (__v2di)_mm_sra_epi64(__A, __B), \
+ (__v2di)__W);
}
static __inline__ __m128i __DEFAULT_FN_ATTRS
-_mm_maskz_sra_epi64 (__mmask8 __U, __m128i __A, __m128i __B)
+_mm_maskz_sra_epi64(__mmask8 __U, __m128i __A, __m128i __B)
{
- return (__m128i) __builtin_ia32_psraq128_mask ((__v2di) __A,
- (__v2di) __B,
- (__v2di)
- _mm_setzero_di (),
- (__mmask8) __U);
+ return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, \
+ (__v2di)_mm_sra_epi64(__A, __B), \
+ (__v2di)_mm_setzero_di());
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_sra_epi64 (__m256i __A, __m128i __B)
+_mm256_sra_epi64(__m256i __A, __m128i __B)
{
- return (__m256i) __builtin_ia32_psraq256_mask ((__v4di) __A,
- (__v2di) __B,
- (__v4di)
- _mm256_setzero_si256 (),
- (__mmask8) -1);
+ return (__m256i)__builtin_ia32_psraq256((__v4di) __A, (__v2di) __B);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_mask_sra_epi64 (__m256i __W, __mmask8 __U, __m256i __A,
- __m128i __B)
+_mm256_mask_sra_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m128i __B)
{
- return (__m256i) __builtin_ia32_psraq256_mask ((__v4di) __A,
- (__v2di) __B,
- (__v4di) __W,
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, \
+ (__v4di)_mm256_sra_epi64(__A, __B), \
+ (__v4di)__W);
}
static __inline__ __m256i __DEFAULT_FN_ATTRS
-_mm256_maskz_sra_epi64 (__mmask8 __U, __m256i __A, __m128i __B)
+_mm256_maskz_sra_epi64(__mmask8 __U, __m256i __A, __m128i __B)
{
- return (__m256i) __builtin_ia32_psraq256_mask ((__v4di) __A,
- (__v2di) __B,
- (__v4di)
- _mm256_setzero_si256 (),
- (__mmask8) __U);
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, \
+ (__v4di)_mm256_sra_epi64(__A, __B), \
+ (__v4di)_mm256_setzero_si256());
}
-#define _mm_srai_epi64(A, imm) __extension__ ({ \
- (__m128i)__builtin_ia32_psraqi128_mask((__v2di)(__m128i)(A), (int)(imm), \
- (__v2di)_mm_setzero_di(), \
- (__mmask8)-1); })
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_srai_epi64(__m128i __A, int __imm)
+{
+ return (__m128i)__builtin_ia32_psraqi128((__v2di)__A, __imm);
+}
-#define _mm_mask_srai_epi64(W, U, A, imm) __extension__ ({ \
- (__m128i)__builtin_ia32_psraqi128_mask((__v2di)(__m128i)(A), (int)(imm), \
- (__v2di)(__m128i)(W), \
- (__mmask8)(U)); })
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_mm_mask_srai_epi64(__m128i __W, __mmask8 __U, __m128i __A, int __imm)
+{
+ return (__m128i)__builtin_ia32_selectq_128((__mmask8)__U, \
+ (__v2di)_mm_srai_epi64(__A, __imm), \
+ (__v2di)__W);
+}
-#define _mm_maskz_srai_epi64(U, A, imm) __extension__ ({ \
- (__m128i)__builtin_ia32_psraqi128_mask((__v2di)(__m128i)(A), (int)(imm), \
- (__v2di)_mm_setzero_si128(), \
- (__mmask8)(U)); })
+static __inline__ __m128i __DEFAULT_FN_ATTRS
+_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());
+}
-#define _mm256_srai_epi64(A, imm) __extension__ ({ \
- (__m256i)__builtin_ia32_psraqi256_mask((__v4di)(__m256i)(A), (int)(imm), \
- (__v4di)_mm256_setzero_si256(), \
- (__mmask8)-1); })
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_srai_epi64(__m256i __A, int __imm)
+{
+ return (__m256i)__builtin_ia32_psraqi256((__v4di)__A, __imm);
+}
-#define _mm256_mask_srai_epi64(W, U, A, imm) __extension__ ({ \
- (__m256i)__builtin_ia32_psraqi256_mask((__v4di)(__m256i)(A), (int)(imm), \
- (__v4di)(__m256i)(W), \
- (__mmask8)(U)); })
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_mask_srai_epi64(__m256i __W, __mmask8 __U, __m256i __A, int __imm)
+{
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, \
+ (__v4di)_mm256_srai_epi64(__A, __imm), \
+ (__v4di)__W);
+}
-#define _mm256_maskz_srai_epi64(U, A, imm) __extension__ ({ \
- (__m256i)__builtin_ia32_psraqi256_mask((__v4di)(__m256i)(A), (int)(imm), \
- (__v4di)_mm256_setzero_si256(), \
- (__mmask8)(U)); })
+static __inline__ __m256i __DEFAULT_FN_ATTRS
+_mm256_maskz_srai_epi64(__mmask8 __U, __m256i __A, int __imm)
+{
+ return (__m256i)__builtin_ia32_selectq_256((__mmask8)__U, \
+ (__v4di)_mm256_srai_epi64(__A, __imm), \
+ (__v4di)_mm256_setzero_si256());
+}
#define _mm_ternarylogic_epi32(A, B, C, imm) __extension__ ({ \
(__m128i)__builtin_ia32_pternlogd128_mask((__v4si)(__m128i)(A), \
@@ -8473,79 +8228,84 @@ _mm256_mask_cvtepi64_storeu_epi16 (void * __P, __mmask8 __M, __m256i __A)
}
#define _mm256_extractf32x4_ps(A, imm) __extension__ ({ \
- (__m128)__builtin_ia32_extractf32x4_256_mask((__v8sf)(__m256)(A), \
- (int)(imm), \
- (__v4sf)_mm_setzero_ps(), \
- (__mmask8)-1); })
+ (__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_extractf32x4_256_mask((__v8sf)(__m256)(A), \
- (int)(imm), \
- (__v4sf)(__m128)(W), \
- (__mmask8)(U)); })
+ (__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_extractf32x4_256_mask((__v8sf)(__m256)(A), \
- (int)(imm), \
- (__v4sf)_mm_setzero_ps(), \
- (__mmask8)(U)); })
+ (__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_ia32_extracti32x4_256_mask((__v8si)(__m256i)(A), \
- (int)(imm), \
- (__v4si)_mm_setzero_si128(), \
- (__mmask8)-1); })
+ (__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_extracti32x4_256_mask((__v8si)(__m256i)(A), \
- (int)(imm), \
- (__v4si)(__m128i)(W), \
- (__mmask8)(U)); })
+ (__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_extracti32x4_256_mask((__v8si)(__m256i)(A), \
- (int)(imm), \
- (__v4si)_mm_setzero_si128(), \
- (__mmask8)(U)); })
+ (__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_ia32_insertf32x4_256_mask((__v8sf)(__m256)(A), \
- (__v4sf)(__m128)(B), (int)(imm), \
- (__v8sf)_mm256_setzero_ps(), \
- (__mmask8)-1); })
+ (__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__ ({ \
- (__m256)__builtin_ia32_insertf32x4_256_mask((__v8sf)(__m256)(A), \
- (__v4sf)(__m128)(B), (int)(imm), \
- (__v8sf)(__m256)(W), \
- (__mmask8)(U)); })
+ (__m256)__builtin_ia32_selectps_256((__mmask8)(U), \
+ (__v8sf)_mm256_insertf32x4((A), (B), (imm)), \
+ (__v8sf)(W)); })
#define _mm256_maskz_insertf32x4(U, A, B, imm) __extension__ ({ \
- (__m256)__builtin_ia32_insertf32x4_256_mask((__v8sf)(__m256)(A), \
- (__v4sf)(__m128)(B), (int)(imm), \
- (__v8sf)_mm256_setzero_ps(), \
- (__mmask8)(U)); })
+ (__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_ia32_inserti32x4_256_mask((__v8si)(__m256i)(A), \
- (__v4si)(__m128i)(B), \
- (int)(imm), \
- (__v8si)_mm256_setzero_si256(), \
- (__mmask8)-1); })
+ (__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__ ({ \
- (__m256i)__builtin_ia32_inserti32x4_256_mask((__v8si)(__m256i)(A), \
- (__v4si)(__m128i)(B), \
- (int)(imm), \
- (__v8si)(__m256i)(W), \
- (__mmask8)(U)); })
+ (__m256i)__builtin_ia32_selectd_256((__mmask8)(U), \
+ (__v8si)_mm256_inserti32x4((A), (B), (imm)), \
+ (__v8si)(W)); })
#define _mm256_maskz_inserti32x4(U, A, B, imm) __extension__ ({ \
- (__m256i)__builtin_ia32_inserti32x4_256_mask((__v8si)(__m256i)(A), \
- (__v4si)(__m128i)(B), \
- (int)(imm), \
- (__v8si)_mm256_setzero_si256(), \
- (__mmask8)(U)); })
+ (__m256i)__builtin_ia32_selectd_256((__mmask8)(U), \
+ (__v8si)_mm256_inserti32x4((A), (B), (imm)), \
+ (__v8si)_mm256_setzero_si256()); })
#define _mm_getmant_pd(A, B, C) __extension__({\
(__m128d)__builtin_ia32_getmantpd128_mask((__v2df)(__m128d)(A), \
@@ -8860,76 +8620,78 @@ _mm256_permutexvar_epi32 (__m256i __X, __m256i __Y)
}
#define _mm_alignr_epi32(A, B, imm) __extension__ ({ \
- (__m128i)__builtin_ia32_alignd128_mask((__v4si)(__m128i)(A), \
- (__v4si)(__m128i)(B), (int)(imm), \
- (__v4si)_mm_undefined_si128(), \
- (__mmask8)-1); })
+ (__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_mask_alignr_epi32(W, U, A, B, imm) __extension__ ({ \
- (__m128i)__builtin_ia32_alignd128_mask((__v4si)(__m128i)(A), \
- (__v4si)(__m128i)(B), (int)(imm), \
- (__v4si)(__m128i)(W), \
- (__mmask8)(U)); })
+ (__m128i)__builtin_ia32_selectd_128((__mmask8)(U), \
+ (__v4si)_mm_alignr_epi32((A), (B), (imm)), \
+ (__v4si)(__m128i)(W)); })
#define _mm_maskz_alignr_epi32(U, A, B, imm) __extension__ ({ \
- (__m128i)__builtin_ia32_alignd128_mask((__v4si)(__m128i)(A), \
- (__v4si)(__m128i)(B), (int)(imm), \
- (__v4si)_mm_setzero_si128(), \
- (__mmask8)(U)); })
+ (__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_ia32_alignd256_mask((__v8si)(__m256i)(A), \
- (__v8si)(__m256i)(B), (int)(imm), \
- (__v8si)_mm256_undefined_si256(), \
- (__mmask8)-1); })
+ (__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__ ({ \
- (__m256i)__builtin_ia32_alignd256_mask((__v8si)(__m256i)(A), \
- (__v8si)(__m256i)(B), (int)(imm), \
- (__v8si)(__m256i)(W), \
- (__mmask8)(U)); })
+ (__m256i)__builtin_ia32_selectd_256((__mmask8)(U), \
+ (__v8si)_mm256_alignr_epi32((A), (B), (imm)), \
+ (__v8si)(__m256i)(W)); })
#define _mm256_maskz_alignr_epi32(U, A, B, imm) __extension__ ({ \
- (__m256i)__builtin_ia32_alignd256_mask((__v8si)(__m256i)(A), \
- (__v8si)(__m256i)(B), (int)(imm), \
- (__v8si)_mm256_setzero_si256(), \
- (__mmask8)(U)); })
+ (__m256i)__builtin_ia32_selectd_256((__mmask8)(U), \
+ (__v8si)_mm256_alignr_epi32((A), (B), (imm)), \
+ (__v8si)_mm256_setzero_si256()); })
#define _mm_alignr_epi64(A, B, imm) __extension__ ({ \
- (__m128i)__builtin_ia32_alignq128_mask((__v2di)(__m128i)(A), \
- (__v2di)(__m128i)(B), (int)(imm), \
- (__v2di)_mm_setzero_di(), \
- (__mmask8)-1); })
+ (__m128i)__builtin_shufflevector((__v2di)(__m128i)(B), \
+ (__v2di)(__m128i)(A), \
+ ((int)(imm) & 0x1) + 0, \
+ ((int)(imm) & 0x1) + 1); })
#define _mm_mask_alignr_epi64(W, U, A, B, imm) __extension__ ({ \
- (__m128i)__builtin_ia32_alignq128_mask((__v2di)(__m128i)(A), \
- (__v2di)(__m128i)(B), (int)(imm), \
- (__v2di)(__m128i)(W), \
- (__mmask8)(U)); })
+ (__m128i)__builtin_ia32_selectq_128((__mmask8)(U), \
+ (__v2di)_mm_alignr_epi64((A), (B), (imm)), \
+ (__v2di)(__m128i)(W)); })
#define _mm_maskz_alignr_epi64(U, A, B, imm) __extension__ ({ \
- (__m128i)__builtin_ia32_alignq128_mask((__v2di)(__m128i)(A), \
- (__v2di)(__m128i)(B), (int)(imm), \
- (__v2di)_mm_setzero_di(), \
- (__mmask8)(U)); })
+ (__m128i)__builtin_ia32_selectq_128((__mmask8)(U), \
+ (__v2di)_mm_alignr_epi64((A), (B), (imm)), \
+ (__v2di)_mm_setzero_di()); })
#define _mm256_alignr_epi64(A, B, imm) __extension__ ({ \
- (__m256i)__builtin_ia32_alignq256_mask((__v4di)(__m256i)(A), \
- (__v4di)(__m256i)(B), (int)(imm), \
- (__v4di)_mm256_undefined_pd(), \
- (__mmask8)-1); })
+ (__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_mask_alignr_epi64(W, U, A, B, imm) __extension__ ({ \
- (__m256i)__builtin_ia32_alignq256_mask((__v4di)(__m256i)(A), \
- (__v4di)(__m256i)(B), (int)(imm), \
- (__v4di)(__m256i)(W), \
- (__mmask8)(U)); })
+ (__m256i)__builtin_ia32_selectq_256((__mmask8)(U), \
+ (__v4di)_mm256_alignr_epi64((A), (B), (imm)), \
+ (__v4di)(__m256i)(W)); })
#define _mm256_maskz_alignr_epi64(U, A, B, imm) __extension__ ({ \
- (__m256i)__builtin_ia32_alignq256_mask((__v4di)(__m256i)(A), \
- (__v4di)(__m256i)(B), (int)(imm), \
- (__v4di)_mm256_setzero_si256(), \
- (__mmask8)(U)); })
+ (__m256i)__builtin_ia32_selectq_256((__mmask8)(U), \
+ (__v4di)_mm256_alignr_epi64((A), (B), (imm)), \
+ (__v4di)_mm256_setzero_si256()); })
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_mask_movehdup_ps (__m128 __W, __mmask8 __U, __m128 __A)
diff --git a/lib/Headers/avxintrin.h b/lib/Headers/avxintrin.h
index 32e8546817b3..be03ba346031 100644
--- a/lib/Headers/avxintrin.h
+++ b/lib/Headers/avxintrin.h
@@ -57,7 +57,7 @@ typedef long long __m256i __attribute__((__vector_size__(32)));
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VADDPD / ADDPD instruction.
+/// This intrinsic corresponds to the <c> VADDPD </c> instruction.
///
/// \param __a
/// A 256-bit vector of [4 x double] containing one of the source operands.
@@ -75,7 +75,7 @@ _mm256_add_pd(__m256d __a, __m256d __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VADDPS / ADDPS instruction.
+/// This intrinsic corresponds to the <c> VADDPS </c> instruction.
///
/// \param __a
/// A 256-bit vector of [8 x float] containing one of the source operands.
@@ -93,7 +93,7 @@ _mm256_add_ps(__m256 __a, __m256 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VSUBPD / SUBPD instruction.
+/// This intrinsic corresponds to the <c> VSUBPD </c> instruction.
///
/// \param __a
/// A 256-bit vector of [4 x double] containing the minuend.
@@ -111,7 +111,7 @@ _mm256_sub_pd(__m256d __a, __m256d __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VSUBPS / SUBPS instruction.
+/// This intrinsic corresponds to the <c> VSUBPS </c> instruction.
///
/// \param __a
/// A 256-bit vector of [8 x float] containing the minuend.
@@ -130,7 +130,7 @@ _mm256_sub_ps(__m256 __a, __m256 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VADDSUBPD / ADDSUBPD instruction.
+/// This intrinsic corresponds to the <c> VADDSUBPD </c> instruction.
///
/// \param __a
/// A 256-bit vector of [4 x double] containing the left source operand.
@@ -149,7 +149,7 @@ _mm256_addsub_pd(__m256d __a, __m256d __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VADDSUBPS / ADDSUBPS instruction.
+/// This intrinsic corresponds to the <c> VADDSUBPS </c> instruction.
///
/// \param __a
/// A 256-bit vector of [8 x float] containing the left source operand.
@@ -167,7 +167,7 @@ _mm256_addsub_ps(__m256 __a, __m256 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VDIVPD / DIVPD instruction.
+/// This intrinsic corresponds to the <c> VDIVPD </c> instruction.
///
/// \param __a
/// A 256-bit vector of [4 x double] containing the dividend.
@@ -185,7 +185,7 @@ _mm256_div_pd(__m256d __a, __m256d __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VDIVPS / DIVPS instruction.
+/// This intrinsic corresponds to the <c> VDIVPS </c> instruction.
///
/// \param __a
/// A 256-bit vector of [8 x float] containing the dividend.
@@ -204,7 +204,7 @@ _mm256_div_ps(__m256 __a, __m256 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VMAXPD / MAXPD instruction.
+/// This intrinsic corresponds to the <c> VMAXPD </c> instruction.
///
/// \param __a
/// A 256-bit vector of [4 x double] containing one of the operands.
@@ -223,7 +223,7 @@ _mm256_max_pd(__m256d __a, __m256d __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VMAXPS / MAXPS instruction.
+/// This intrinsic corresponds to the <c> VMAXPS </c> instruction.
///
/// \param __a
/// A 256-bit vector of [8 x float] containing one of the operands.
@@ -242,7 +242,7 @@ _mm256_max_ps(__m256 __a, __m256 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VMINPD / MINPD instruction.
+/// This intrinsic corresponds to the <c> VMINPD </c> instruction.
///
/// \param __a
/// A 256-bit vector of [4 x double] containing one of the operands.
@@ -261,7 +261,7 @@ _mm256_min_pd(__m256d __a, __m256d __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VMINPS / MINPS instruction.
+/// This intrinsic corresponds to the <c> VMINPS </c> instruction.
///
/// \param __a
/// A 256-bit vector of [8 x float] containing one of the operands.
@@ -279,7 +279,7 @@ _mm256_min_ps(__m256 __a, __m256 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VMULPD / MULPD instruction.
+/// This intrinsic corresponds to the <c> VMULPD </c> instruction.
///
/// \param __a
/// A 256-bit vector of [4 x double] containing one of the operands.
@@ -297,7 +297,7 @@ _mm256_mul_pd(__m256d __a, __m256d __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VMULPS / MULPS instruction.
+/// This intrinsic corresponds to the <c> VMULPS </c> instruction.
///
/// \param __a
/// A 256-bit vector of [8 x float] containing one of the operands.
@@ -316,7 +316,7 @@ _mm256_mul_ps(__m256 __a, __m256 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VSQRTPD / SQRTPD instruction.
+/// This intrinsic corresponds to the <c> VSQRTPD </c> instruction.
///
/// \param __a
/// A 256-bit vector of [4 x double].
@@ -333,7 +333,7 @@ _mm256_sqrt_pd(__m256d __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VSQRTPS / SQRTPS instruction.
+/// This intrinsic corresponds to the <c> VSQRTPS </c> instruction.
///
/// \param __a
/// A 256-bit vector of [8 x float].
@@ -350,7 +350,7 @@ _mm256_sqrt_ps(__m256 __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VRSQRTPS / RSQRTPS instruction.
+/// This intrinsic corresponds to the <c> VRSQRTPS </c> instruction.
///
/// \param __a
/// A 256-bit vector of [8 x float].
@@ -367,7 +367,7 @@ _mm256_rsqrt_ps(__m256 __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VRCPPS / RCPPS instruction.
+/// This intrinsic corresponds to the <c> VRCPPS </c> instruction.
///
/// \param __a
/// A 256-bit vector of [8 x float].
@@ -389,24 +389,24 @@ _mm256_rcp_ps(__m256 __a)
/// __m256d _mm256_round_pd(__m256d V, const int M);
/// \endcode
///
-/// This intrinsic corresponds to the \c VROUNDPD / ROUNDPD instruction.
+/// This intrinsic corresponds to the <c> VROUNDPD </c> instruction.
///
/// \param V
/// A 256-bit vector of [4 x double].
/// \param M
-/// An integer value that specifies the rounding operation.
-/// Bits [7:4] are reserved.
-/// Bit [3] is a precision exception value:
-/// 0: A normal PE exception is used.
-/// 1: The PE field is not updated.
-/// Bit [2] is the rounding control source:
-/// 0: Use bits [1:0] of M.
-/// 1: Use the current MXCSR setting.
-/// Bits [1:0] contain the rounding control definition:
-/// 00: Nearest.
-/// 01: Downward (toward negative infinity).
-/// 10: Upward (toward positive infinity).
-/// 11: Truncated.
+/// An integer value that specifies the rounding operation. \n
+/// Bits [7:4] are reserved. \n
+/// Bit [3] is a precision exception value: \n
+/// 0: A normal PE exception is used. \n
+/// 1: The PE field is not updated. \n
+/// Bit [2] is the rounding control source: \n
+/// 0: Use bits [1:0] of \a M. \n
+/// 1: Use the current MXCSR setting. \n
+/// Bits [1:0] contain the rounding control definition: \n
+/// 00: Nearest. \n
+/// 01: Downward (toward negative infinity). \n
+/// 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)); })
@@ -421,24 +421,24 @@ _mm256_rcp_ps(__m256 __a)
/// __m256 _mm256_round_ps(__m256 V, const int M);
/// \endcode
///
-/// This intrinsic corresponds to the \c VROUNDPS / ROUNDPS instruction.
+/// This intrinsic corresponds to the <c> VROUNDPS </c> instruction.
///
/// \param V
/// A 256-bit vector of [8 x float].
/// \param M
-/// An integer value that specifies the rounding operation.
-/// Bits [7:4] are reserved.
-/// Bit [3] is a precision exception value:
-/// 0: A normal PE exception is used.
-/// 1: The PE field is not updated.
-/// Bit [2] is the rounding control source:
-/// 0: Use bits [1:0] of M.
-/// 1: Use the current MXCSR setting.
-/// Bits [1:0] contain the rounding control definition:
-/// 00: Nearest.
-/// 01: Downward (toward negative infinity).
-/// 10: Upward (toward positive infinity).
-/// 11: Truncated.
+/// An integer value that specifies the rounding operation. \n
+/// Bits [7:4] are reserved. \n
+/// Bit [3] is a precision exception value: \n
+/// 0: A normal PE exception is used. \n
+/// 1: The PE field is not updated. \n
+/// Bit [2] is the rounding control source: \n
+/// 0: Use bits [1:0] of \a M. \n
+/// 1: Use the current MXCSR setting. \n
+/// Bits [1:0] contain the rounding control definition: \n
+/// 00: Nearest. \n
+/// 01: Downward (toward negative infinity). \n
+/// 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)); })
@@ -453,7 +453,7 @@ _mm256_rcp_ps(__m256 __a)
/// __m256d _mm256_ceil_pd(__m256d V);
/// \endcode
///
-/// This intrinsic corresponds to the \c VROUNDPD / ROUNDPD instruction.
+/// This intrinsic corresponds to the <c> VROUNDPD </c> instruction.
///
/// \param V
/// A 256-bit vector of [4 x double].
@@ -470,7 +470,7 @@ _mm256_rcp_ps(__m256 __a)
/// __m256d _mm256_floor_pd(__m256d V);
/// \endcode
///
-/// This intrinsic corresponds to the \c VROUNDPD / ROUNDPD instruction.
+/// This intrinsic corresponds to the <c> VROUNDPD </c> instruction.
///
/// \param V
/// A 256-bit vector of [4 x double].
@@ -488,7 +488,7 @@ _mm256_rcp_ps(__m256 __a)
/// __m256 _mm256_ceil_ps(__m256 V);
/// \endcode
///
-/// This intrinsic corresponds to the \c VROUNDPS / ROUNDPS instruction.
+/// This intrinsic corresponds to the <c> VROUNDPS </c> instruction.
///
/// \param V
/// A 256-bit vector of [8 x float].
@@ -505,7 +505,7 @@ _mm256_rcp_ps(__m256 __a)
/// __m256 _mm256_floor_ps(__m256 V);
/// \endcode
///
-/// This intrinsic corresponds to the \c VROUNDPS / ROUNDPS instruction.
+/// This intrinsic corresponds to the <c> VROUNDPS </c> instruction.
///
/// \param V
/// A 256-bit vector of [8 x float].
@@ -517,7 +517,7 @@ _mm256_rcp_ps(__m256 __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VANDPD / ANDPD instruction.
+/// This intrinsic corresponds to the <c> VANDPD </c> instruction.
///
/// \param __a
/// A 256-bit vector of [4 x double] containing one of the source operands.
@@ -535,7 +535,7 @@ _mm256_and_pd(__m256d __a, __m256d __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VANDPS / ANDPS instruction.
+/// This intrinsic corresponds to the <c> VANDPS </c> instruction.
///
/// \param __a
/// A 256-bit vector of [8 x float] containing one of the source operands.
@@ -554,7 +554,7 @@ _mm256_and_ps(__m256 __a, __m256 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VANDNPD / ANDNPD instruction.
+/// This intrinsic corresponds to the <c> VANDNPD </c> instruction.
///
/// \param __a
/// A 256-bit vector of [4 x double] containing the left source operand. The
@@ -575,7 +575,7 @@ _mm256_andnot_pd(__m256d __a, __m256d __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VANDNPS / ANDNPS instruction.
+/// This intrinsic corresponds to the <c> VANDNPS </c> instruction.
///
/// \param __a
/// A 256-bit vector of [8 x float] containing the left source operand. The
@@ -595,7 +595,7 @@ _mm256_andnot_ps(__m256 __a, __m256 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VORPD / ORPD instruction.
+/// This intrinsic corresponds to the <c> VORPD </c> instruction.
///
/// \param __a
/// A 256-bit vector of [4 x double] containing one of the source operands.
@@ -613,7 +613,7 @@ _mm256_or_pd(__m256d __a, __m256d __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VORPS / ORPS instruction.
+/// This intrinsic corresponds to the <c> VORPS </c> instruction.
///
/// \param __a
/// A 256-bit vector of [8 x float] containing one of the source operands.
@@ -631,7 +631,7 @@ _mm256_or_ps(__m256 __a, __m256 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VXORPD / XORPD instruction.
+/// This intrinsic corresponds to the <c> VXORPD </c> instruction.
///
/// \param __a
/// A 256-bit vector of [4 x double] containing one of the source operands.
@@ -649,7 +649,7 @@ _mm256_xor_pd(__m256d __a, __m256d __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VXORPS / XORPS instruction.
+/// This intrinsic corresponds to the <c> VXORPS </c> instruction.
///
/// \param __a
/// A 256-bit vector of [8 x float] containing one of the source operands.
@@ -669,7 +669,7 @@ _mm256_xor_ps(__m256 __a, __m256 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VHADDPD / HADDPD instruction.
+/// This intrinsic corresponds to the <c> VHADDPD </c> instruction.
///
/// \param __a
/// A 256-bit vector of [4 x double] containing one of the source operands.
@@ -692,7 +692,7 @@ _mm256_hadd_pd(__m256d __a, __m256d __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VHADDPS / HADDPS instruction.
+/// This intrinsic corresponds to the <c> VHADDPS </c> instruction.
///
/// \param __a
/// A 256-bit vector of [8 x float] containing one of the source operands.
@@ -715,7 +715,7 @@ _mm256_hadd_ps(__m256 __a, __m256 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VHSUBPD / HSUBPD instruction.
+/// This intrinsic corresponds to the <c> VHSUBPD </c> instruction.
///
/// \param __a
/// A 256-bit vector of [4 x double] containing one of the source operands.
@@ -738,7 +738,7 @@ _mm256_hsub_pd(__m256d __a, __m256d __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VHSUBPS / HSUBPS instruction.
+/// This intrinsic corresponds to the <c> VHSUBPS </c> instruction.
///
/// \param __a
/// A 256-bit vector of [8 x float] containing one of the source operands.
@@ -762,23 +762,23 @@ _mm256_hsub_ps(__m256 __a, __m256 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPERMILPD / PERMILPD instruction.
+/// This intrinsic corresponds to the <c> VPERMILPD </c> instruction.
///
/// \param __a
/// A 128-bit vector of [2 x double].
/// \param __c
/// A 128-bit integer vector operand specifying how the values are to be
-/// copied.
-/// Bit [1]:
-/// 0: Bits [63:0] of the source are copied to bits [63:0] of the
-/// returned vector.
-/// 1: Bits [127:64] of the source are copied to bits [63:0] of the
-/// returned vector.
-/// Bit [65]:
-/// 0: Bits [63:0] of the source are copied to bits [127:64] of the
-/// returned vector.
-/// 1: Bits [127:64] of the source are copied to bits [127:64] of the
-/// returned vector.
+/// copied. \n
+/// Bit [1]: \n
+/// 0: Bits [63:0] of the source are copied to bits [63:0] of the returned
+/// vector. \n
+/// 1: Bits [127:64] of the source are copied to bits [63:0] of the
+/// returned vector. \n
+/// Bit [65]: \n
+/// 0: Bits [63:0] of the source are copied to bits [127:64] of the
+/// returned vector. \n
+/// 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
_mm_permutevar_pd(__m128d __a, __m128i __c)
@@ -786,37 +786,37 @@ _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 by the 256-bit integer vector operand.
+/// \brief Copies the values in a 256-bit vector of [4 x double] as specified
+/// by the 256-bit integer vector operand.
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPERMILPD / PERMILPD instruction.
+/// This intrinsic corresponds to the <c> VPERMILPD </c> instruction.
///
/// \param __a
/// A 256-bit vector of [4 x double].
/// \param __c
/// A 256-bit integer vector operand specifying how the values are to be
-/// copied.
-/// Bit [1]:
-/// 0: Bits [63:0] of the source are copied to bits [63:0] of the
-/// returned vector.
-/// 1: Bits [127:64] of the source are copied to bits [63:0] of the
-/// returned vector.
-/// Bit [65]:
-/// 0: Bits [63:0] of the source are copied to bits [127:64] of the
-/// returned vector.
-/// 1: Bits [127:64] of the source are copied to bits [127:64] of the
-/// returned vector.
-/// Bit [129]:
-/// 0: Bits [191:128] of the source are copied to bits [191:128] of the
-/// returned vector.
-/// 1: Bits [255:192] of the source are copied to bits [191:128] of the
-/// returned vector.
-/// Bit [193]:
-/// 0: Bits [191:128] of the source are copied to bits [255:192] of the
-/// returned vector.
-/// 1: Bits [255:192] of the source are copied to bits [255:192] of the
+/// copied. \n
+/// Bit [1]: \n
+/// 0: Bits [63:0] of the source are copied to bits [63:0] of the returned
+/// vector. \n
+/// 1: Bits [127:64] of the source are copied to bits [63:0] of the
+/// returned vector. \n
+/// Bit [65]: \n
+/// 0: Bits [63:0] of the source are copied to bits [127:64] of the
+/// returned vector. \n
+/// 1: Bits [127:64] of the source are copied to bits [127:64] of the
+/// returned vector. \n
+/// Bit [129]: \n
+/// 0: Bits [191:128] of the source are copied to bits [191:128] of the
+/// returned vector. \n
+/// 1: Bits [255:192] of the source are copied to bits [191:128] of the
+/// returned vector. \n
+/// Bit [193]: \n
+/// 0: Bits [191:128] of the source are copied to bits [255:192] of the
+/// returned vector. \n
+/// 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.
static __inline __m256d __DEFAULT_FN_ATTRS
@@ -827,52 +827,51 @@ _mm256_permutevar_pd(__m256d __a, __m256i __c)
/// \brief 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>
///
-/// This intrinsic corresponds to the \c VPERMILPS / PERMILPS instruction.
+/// This intrinsic corresponds to the <c> VPERMILPS </c> instruction.
///
/// \param __a
/// A 128-bit vector of [4 x float].
/// \param __c
/// A 128-bit integer vector operand specifying how the values are to be
-/// copied.
-/// Bits [1:0]:
-/// 00: Bits [31:0] of the source are copied to bits [31:0] of the
-/// returned vector.
-/// 01: Bits [63:32] of the source are copied to bits [31:0] of the
-/// returned vector.
-/// 10: Bits [95:64] of the source are copied to bits [31:0] of the
-/// returned vector.
-/// 11: Bits [127:96] of the source are copied to bits [31:0] of the
-/// returned vector.
-/// Bits [33:32]:
-/// 00: Bits [31:0] of the source are copied to bits [63:32] of the
-/// returned vector.
-/// 01: Bits [63:32] of the source are copied to bits [63:32] of the
-/// returned vector.
-/// 10: Bits [95:64] of the source are copied to bits [63:32] of the
-/// returned vector.
-/// 11: Bits [127:96] of the source are copied to bits [63:32] of the
-/// returned vector.
-/// Bits [65:64]:
-/// 00: Bits [31:0] of the source are copied to bits [95:64] of the
-/// returned vector.
-/// 01: Bits [63:32] of the source are copied to bits [95:64] of the
-/// returned vector.
-/// 10: Bits [95:64] of the source are copied to bits [95:64] of the
-/// returned vector.
-/// 11: Bits [127:96] of the source are copied to bits [95:64] of the
-/// returned vector.
-/// Bits [97:96]:
-/// 00: Bits [31:0] of the source are copied to bits [127:96] of the
-/// returned vector.
-/// 01: Bits [63:32] of the source are copied to bits [127:96] of the
-/// returned vector.
-/// 10: Bits [95:64] of the source are copied to bits [127:96] of the
-/// returned vector.
-/// 11: Bits [127:96] of the source are copied to bits [127:96] of the
-/// returned vector.
+/// copied. \n
+/// Bits [1:0]: \n
+/// 00: Bits [31:0] of the source are copied to bits [31:0] of the
+/// returned vector. \n
+/// 01: Bits [63:32] of the source are copied to bits [31:0] of the
+/// returned vector. \n
+/// 10: Bits [95:64] of the source are copied to bits [31:0] of the
+/// returned vector. \n
+/// 11: Bits [127:96] of the source are copied to bits [31:0] of the
+/// returned vector. \n
+/// Bits [33:32]: \n
+/// 00: Bits [31:0] of the source are copied to bits [63:32] of the
+/// returned vector. \n
+/// 01: Bits [63:32] of the source are copied to bits [63:32] of the
+/// returned vector. \n
+/// 10: Bits [95:64] of the source are copied to bits [63:32] of the
+/// returned vector. \n
+/// 11: Bits [127:96] of the source are copied to bits [63:32] of the
+/// returned vector. \n
+/// Bits [65:64]: \n
+/// 00: Bits [31:0] of the source are copied to bits [95:64] of the
+/// returned vector. \n
+/// 01: Bits [63:32] of the source are copied to bits [95:64] of the
+/// returned vector. \n
+/// 10: Bits [95:64] of the source are copied to bits [95:64] of the
+/// returned vector. \n
+/// 11: Bits [127:96] of the source are copied to bits [95:64] of the
+/// returned vector. \n
+/// Bits [97:96]: \n
+/// 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
+/// 10: Bits [95:64] of the source are copied to bits [127:96] of the
+/// returned vector. \n
+/// 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
_mm_permutevar_ps(__m128 __a, __m128i __c)
@@ -885,85 +884,85 @@ _mm_permutevar_ps(__m128 __a, __m128i __c)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPERMILPS / PERMILPS instruction.
+/// This intrinsic corresponds to the <c> VPERMILPS </c> instruction.
///
/// \param __a
/// A 256-bit vector of [8 x float].
/// \param __c
/// A 256-bit integer vector operand specifying how the values are to be
-/// copied.
-/// Bits [1:0]:
-/// 00: Bits [31:0] of the source are copied to bits [31:0] of the
-/// returned vector.
-/// 01: Bits [63:32] of the source are copied to bits [31:0] of the
-/// returned vector.
-/// 10: Bits [95:64] of the source are copied to bits [31:0] of the
-/// returned vector.
-/// 11: Bits [127:96] of the source are copied to bits [31:0] of the
-/// returned vector.
-/// Bits [33:32]:
-/// 00: Bits [31:0] of the source are copied to bits [63:32] of the
-/// returned vector.
-/// 01: Bits [63:32] of the source are copied to bits [63:32] of the
-/// returned vector.
-/// 10: Bits [95:64] of the source are copied to bits [63:32] of the
-/// returned vector.
-/// 11: Bits [127:96] of the source are copied to bits [63:32] of the
-/// returned vector.
-/// Bits [65:64]:
-/// 00: Bits [31:0] of the source are copied to bits [95:64] of the
-/// returned vector.
-/// 01: Bits [63:32] of the source are copied to bits [95:64] of the
-/// returned vector.
-/// 10: Bits [95:64] of the source are copied to bits [95:64] of the
-/// returned vector.
-/// 11: Bits [127:96] of the source are copied to bits [95:64] of the
-/// returned vector.
-/// Bits [97:96]:
-/// 00: Bits [31:0] of the source are copied to bits [127:96] of the
-/// returned vector.
-/// 01: Bits [63:32] of the source are copied to bits [127:96] of the
-/// returned vector.
-/// 10: Bits [95:64] of the source are copied to bits [127:96] of the
-/// returned vector.
-/// 11: Bits [127:96] of the source are copied to bits [127:96] of the
-/// returned vector.
-/// Bits [129:128]:
-/// 00: Bits [159:128] of the source are copied to bits [159:128] of the
-/// returned vector.
-/// 01: Bits [191:160] of the source are copied to bits [159:128] of the
-/// returned vector.
-/// 10: Bits [223:192] of the source are copied to bits [159:128] of the
-/// returned vector.
-/// 11: Bits [255:224] of the source are copied to bits [159:128] of the
-/// returned vector.
-/// Bits [161:160]:
-/// 00: Bits [159:128] of the source are copied to bits [191:160] of the
-/// returned vector.
-/// 01: Bits [191:160] of the source are copied to bits [191:160] of the
-/// returned vector.
-/// 10: Bits [223:192] of the source are copied to bits [191:160] of the
-/// returned vector.
-/// 11: Bits [255:224] of the source are copied to bits [191:160] of the
-/// returned vector.
-/// Bits [193:192]:
-/// 00: Bits [159:128] of the source are copied to bits [223:192] of the
-/// returned vector.
-/// 01: Bits [191:160] of the source are copied to bits [223:192] of the
-/// returned vector.
-/// 10: Bits [223:192] of the source are copied to bits [223:192] of the
-/// returned vector.
-/// 11: Bits [255:224] of the source are copied to bits [223:192] of the
-/// returned vector.
-/// Bits [225:224]:
-/// 00: Bits [159:128] of the source are copied to bits [255:224] of the
-/// returned vector.
-/// 01: Bits [191:160] of the source are copied to bits [255:224] of the
-/// returned vector.
-/// 10: Bits [223:192] of the source are copied to bits [255:224] of the
-/// returned vector.
-/// 11: Bits [255:224] of the source are copied to bits [255:224] of the
-/// returned vector.
+/// copied. \n
+/// Bits [1:0]: \n
+/// 00: Bits [31:0] of the source are copied to bits [31:0] of the
+/// returned vector. \n
+/// 01: Bits [63:32] of the source are copied to bits [31:0] of the
+/// returned vector. \n
+/// 10: Bits [95:64] of the source are copied to bits [31:0] of the
+/// returned vector. \n
+/// 11: Bits [127:96] of the source are copied to bits [31:0] of the
+/// returned vector. \n
+/// Bits [33:32]: \n
+/// 00: Bits [31:0] of the source are copied to bits [63:32] of the
+/// returned vector. \n
+/// 01: Bits [63:32] of the source are copied to bits [63:32] of the
+/// returned vector. \n
+/// 10: Bits [95:64] of the source are copied to bits [63:32] of the
+/// returned vector. \n
+/// 11: Bits [127:96] of the source are copied to bits [63:32] of the
+/// returned vector. \n
+/// Bits [65:64]: \n
+/// 00: Bits [31:0] of the source are copied to bits [95:64] of the
+/// returned vector. \n
+/// 01: Bits [63:32] of the source are copied to bits [95:64] of the
+/// returned vector. \n
+/// 10: Bits [95:64] of the source are copied to bits [95:64] of the
+/// returned vector. \n
+/// 11: Bits [127:96] of the source are copied to bits [95:64] of the
+/// returned vector. \n
+/// Bits [97:96]: \n
+/// 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
+/// 10: Bits [95:64] of the source are copied to bits [127:96] of the
+/// returned vector. \n
+/// 11: Bits [127:96] of the source are copied to bits [127:96] of the
+/// returned vector. \n
+/// Bits [129:128]: \n
+/// 00: Bits [159:128] of the source are copied to bits [159:128] of the
+/// returned vector. \n
+/// 01: Bits [191:160] of the source are copied to bits [159:128] of the
+/// returned vector. \n
+/// 10: Bits [223:192] of the source are copied to bits [159:128] of the
+/// returned vector. \n
+/// 11: Bits [255:224] of the source are copied to bits [159:128] of the
+/// returned vector. \n
+/// Bits [161:160]: \n
+/// 00: Bits [159:128] of the source are copied to bits [191:160] of the
+/// returned vector. \n
+/// 01: Bits [191:160] of the source are copied to bits [191:160] of the
+/// returned vector. \n
+/// 10: Bits [223:192] of the source are copied to bits [191:160] of the
+/// returned vector. \n
+/// 11: Bits [255:224] of the source are copied to bits [191:160] of the
+/// returned vector. \n
+/// Bits [193:192]: \n
+/// 00: Bits [159:128] of the source are copied to bits [223:192] of the
+/// returned vector. \n
+/// 01: Bits [191:160] of the source are copied to bits [223:192] of the
+/// returned vector. \n
+/// 10: Bits [223:192] of the source are copied to bits [223:192] of the
+/// returned vector. \n
+/// 11: Bits [255:224] of the source are copied to bits [223:192] of the
+/// returned vector. \n
+/// Bits [225:224]: \n
+/// 00: Bits [159:128] of the source are copied to bits [255:224] of the
+/// returned vector. \n
+/// 01: Bits [191:160] of the source are copied to bits [255:224] of the
+/// returned vector. \n
+/// 10: Bits [223:192] of the source are copied to bits [255:224] of the
+/// returned vector. \n
+/// 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.
static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_permutevar_ps(__m256 __a, __m256i __c)
@@ -971,8 +970,8 @@ _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 by the immediate integer operand.
+/// \brief Copies the values in a 128-bit vector of [2 x double] as specified
+/// by the immediate integer operand.
///
/// \headerfile <x86intrin.h>
///
@@ -980,30 +979,31 @@ _mm256_permutevar_ps(__m256 __a, __m256i __c)
/// __m128d _mm_permute_pd(__m128d A, const int C);
/// \endcode
///
-/// This intrinsic corresponds to the \c VPERMILPD / PERMILPD instruction.
+/// This intrinsic corresponds to the <c> VPERMILPD </c> instruction.
///
/// \param A
/// A 128-bit vector of [2 x double].
/// \param C
-/// An immediate integer operand specifying how the values are to be copied.
-/// Bit [0]:
-/// 0: Bits [63:0] of the source are copied to bits [63:0] of the
-/// returned vector.
-/// 1: Bits [127:64] of the source are copied to bits [63:0] of the
-/// returned vector.
-/// Bit [1]:
-/// 0: Bits [63:0] of the source are copied to bits [127:64] of the
-/// returned vector.
-/// 1: Bits [127:64] of the source are copied to bits [127:64] of the
-/// returned vector.
+/// An immediate integer operand specifying how the values are to be
+/// copied. \n
+/// Bit [0]: \n
+/// 0: Bits [63:0] of the source are copied to bits [63:0] of the returned
+/// vector. \n
+/// 1: Bits [127:64] of the source are copied to bits [63:0] of the
+/// returned vector. \n
+/// Bit [1]: \n
+/// 0: Bits [63:0] of the source are copied to bits [127:64] of the
+/// returned vector. \n
+/// 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); })
-/// \brief Copies the values in a 256-bit vector of [4 x double] as
-/// specified by the immediate integer operand.
+/// \brief Copies the values in a 256-bit vector of [4 x double] as specified by
+/// the immediate integer operand.
///
/// \headerfile <x86intrin.h>
///
@@ -1011,32 +1011,33 @@ _mm256_permutevar_ps(__m256 __a, __m256i __c)
/// __m256d _mm256_permute_pd(__m256d A, const int C);
/// \endcode
///
-/// This intrinsic corresponds to the \c VPERMILPD / PERMILPD instruction.
+/// This intrinsic corresponds to the <c> VPERMILPD </c> instruction.
///
/// \param A
/// A 256-bit vector of [4 x double].
/// \param C
-/// An immediate integer operand specifying how the values are to be copied.
-/// Bit [0]:
-/// 0: Bits [63:0] of the source are copied to bits [63:0] of the
-/// returned vector.
-/// 1: Bits [127:64] of the source are copied to bits [63:0] of the
-/// returned vector.
-/// Bit [1]:
-/// 0: Bits [63:0] of the source are copied to bits [127:64] of the
-/// returned vector.
-/// 1: Bits [127:64] of the source are copied to bits [127:64] of the
-/// returned vector.
-/// Bit [2]:
-/// 0: Bits [191:128] of the source are copied to bits [191:128] of the
-/// returned vector.
-/// 1: Bits [255:192] of the source are copied to bits [191:128] of the
-/// returned vector.
-/// Bit [3]:
-/// 0: Bits [191:128] of the source are copied to bits [255:192] of the
-/// returned vector.
-/// 1: Bits [255:192] of the source are copied to bits [255:192] of the
-/// returned vector.
+/// An immediate integer operand specifying how the values are to be
+/// copied. \n
+/// Bit [0]: \n
+/// 0: Bits [63:0] of the source are copied to bits [63:0] of the returned
+/// vector. \n
+/// 1: Bits [127:64] of the source are copied to bits [63:0] of the
+/// returned vector. \n
+/// Bit [1]: \n
+/// 0: Bits [63:0] of the source are copied to bits [127:64] of the
+/// returned vector. \n
+/// 1: Bits [127:64] of the source are copied to bits [127:64] of the
+/// returned vector. \n
+/// Bit [2]: \n
+/// 0: Bits [191:128] of the source are copied to bits [191:128] of the
+/// returned vector. \n
+/// 1: Bits [255:192] of the source are copied to bits [191:128] of the
+/// returned vector. \n
+/// Bit [3]: \n
+/// 0: Bits [191:128] of the source are copied to bits [255:192] of the
+/// returned vector. \n
+/// 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), \
@@ -1046,8 +1047,8 @@ _mm256_permutevar_ps(__m256 __a, __m256i __c)
2 + (((C) >> 2) & 0x1), \
2 + (((C) >> 3) & 0x1)); })
-/// \brief Copies the values in a 128-bit vector of [4 x float] as
-/// specified by the immediate integer operand.
+/// \brief Copies the values in a 128-bit vector of [4 x float] as specified by
+/// the immediate integer operand.
///
/// \headerfile <x86intrin.h>
///
@@ -1055,48 +1056,49 @@ _mm256_permutevar_ps(__m256 __a, __m256i __c)
/// __m128 _mm_permute_ps(__m128 A, const int C);
/// \endcode
///
-/// This intrinsic corresponds to the \c VPERMILPS / PERMILPS instruction.
+/// This intrinsic corresponds to the <c> VPERMILPS </c> instruction.
///
/// \param A
/// A 128-bit vector of [4 x float].
/// \param C
-/// An immediate integer operand specifying how the values are to be copied.
-/// Bits [1:0]:
-/// 00: Bits [31:0] of the source are copied to bits [31:0] of the
-/// returned vector.
-/// 01: Bits [63:32] of the source are copied to bits [31:0] of the
-/// returned vector.
-/// 10: Bits [95:64] of the source are copied to bits [31:0] of the
-/// returned vector.
-/// 11: Bits [127:96] of the source are copied to bits [31:0] of the
-/// returned vector.
-/// Bits [3:2]:
-/// 00: Bits [31:0] of the source are copied to bits [63:32] of the
-/// returned vector.
-/// 01: Bits [63:32] of the source are copied to bits [63:32] of the
-/// returned vector.
-/// 10: Bits [95:64] of the source are copied to bits [63:32] of the
-/// returned vector.
-/// 11: Bits [127:96] of the source are copied to bits [63:32] of the
-/// returned vector.
-/// Bits [5:4]:
-/// 00: Bits [31:0] of the source are copied to bits [95:64] of the
-/// returned vector.
-/// 01: Bits [63:32] of the source are copied to bits [95:64] of the
-/// returned vector.
-/// 10: Bits [95:64] of the source are copied to bits [95:64] of the
-/// returned vector.
-/// 11: Bits [127:96] of the source are copied to bits [95:64] of the
-/// returned vector.
-/// Bits [7:6]:
-/// 00: Bits [31:0] of the source are copied to bits [127:96] of the
-/// returned vector.
-/// 01: Bits [63:32] of the source are copied to bits [127:96] of the
-/// returned vector.
-/// 10: Bits [95:64] of the source are copied to bits [127:96] of the
-/// returned vector.
-/// 11: Bits [127:96] of the source are copied to bits [127:96] of the
-/// returned vector.
+/// 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
+/// returned vector. \n
+/// 01: Bits [63:32] of the source are copied to bits [31:0] of the
+/// returned vector. \n
+/// 10: Bits [95:64] of the source are copied to bits [31:0] of the
+/// returned vector. \n
+/// 11: Bits [127:96] of the source are copied to bits [31:0] of the
+/// returned vector. \n
+/// Bits [3:2]: \n
+/// 00: Bits [31:0] of the source are copied to bits [63:32] of the
+/// returned vector. \n
+/// 01: Bits [63:32] of the source are copied to bits [63:32] of the
+/// returned vector. \n
+/// 10: Bits [95:64] of the source are copied to bits [63:32] of the
+/// returned vector. \n
+/// 11: Bits [127:96] of the source are copied to bits [63:32] of the
+/// returned vector. \n
+/// Bits [5:4]: \n
+/// 00: Bits [31:0] of the source are copied to bits [95:64] of the
+/// returned vector. \n
+/// 01: Bits [63:32] of the source are copied to bits [95:64] of the
+/// returned vector. \n
+/// 10: Bits [95:64] of the source are copied to bits [95:64] of the
+/// returned vector. \n
+/// 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: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
+/// 10: Bits [95:64] of the source are copied to bits [127:96] of the
+/// returned vector. \n
+/// 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), \
@@ -1104,8 +1106,8 @@ _mm256_permutevar_ps(__m256 __a, __m256i __c)
((C) >> 0) & 0x3, ((C) >> 2) & 0x3, \
((C) >> 4) & 0x3, ((C) >> 6) & 0x3); })
-/// \brief Copies the values in a 256-bit vector of [8 x float] as
-/// specified by the immediate integer operand.
+/// \brief Copies the values in a 256-bit vector of [8 x float] as specified by
+/// the immediate integer operand.
///
/// \headerfile <x86intrin.h>
///
@@ -1113,84 +1115,85 @@ _mm256_permutevar_ps(__m256 __a, __m256i __c)
/// __m256 _mm256_permute_ps(__m256 A, const int C);
/// \endcode
///
-/// This intrinsic corresponds to the \c VPERMILPS / PERMILPS instruction.
+/// This intrinsic corresponds to the <c> VPERMILPS </c> instruction.
///
/// \param A
/// A 256-bit vector of [8 x float].
/// \param C
-/// An immediate integer operand specifying how the values are to be copied.
-/// Bits [1:0]:
-/// 00: Bits [31:0] of the source are copied to bits [31:0] of the
-/// returned vector.
-/// 01: Bits [63:32] of the source are copied to bits [31:0] of the
-/// returned vector.
-/// 10: Bits [95:64] of the source are copied to bits [31:0] of the
-/// returned vector.
-/// 11: Bits [127:96] of the source are copied to bits [31:0] of the
-/// returned vector.
-/// Bits [3:2]:
-/// 00: Bits [31:0] of the source are copied to bits [63:32] of the
-/// returned vector.
-/// 01: Bits [63:32] of the source are copied to bits [63:32] of the
-/// returned vector.
-/// 10: Bits [95:64] of the source are copied to bits [63:32] of the
-/// returned vector.
-/// 11: Bits [127:96] of the source are copied to bits [63:32] of the
-/// returned vector.
-/// Bits [5:4]:
-/// 00: Bits [31:0] of the source are copied to bits [95:64] of the
-/// returned vector.
-/// 01: Bits [63:32] of the source are copied to bits [95:64] of the
-/// returned vector.
-/// 10: Bits [95:64] of the source are copied to bits [95:64] of the
-/// returned vector.
-/// 11: Bits [127:96] of the source are copied to bits [95:64] of the
-/// returned vector.
-/// Bits [7:6]:
-/// 00: Bits [31:0] of the source are copied to bits [127:96] of the
-/// returned vector.
-/// 01: Bits [63:32] of the source are copied to bits [127:96] of the
-/// returned vector.
-/// 10: Bits [95:64] of the source are copied to bits [127:96] of the
-/// returned vector.
-/// 11: Bits [127:96] of the source are copied to bits [127:96] of the
-/// returned vector.
-/// Bits [1:0]:
-/// 00: Bits [159:128] of the source are copied to bits [159:128] of the
-/// returned vector.
-/// 01: Bits [191:160] of the source are copied to bits [159:128] of the
-/// returned vector.
-/// 10: Bits [223:192] of the source are copied to bits [159:128] of the
-/// returned vector.
-/// 11: Bits [255:224] of the source are copied to bits [159:128] of the
-/// returned vector.
-/// Bits [3:2]:
-/// 00: Bits [159:128] of the source are copied to bits [191:160] of the
-/// returned vector.
-/// 01: Bits [191:160] of the source are copied to bits [191:160] of the
-/// returned vector.
-/// 10: Bits [223:192] of the source are copied to bits [191:160] of the
-/// returned vector.
-/// 11: Bits [255:224] of the source are copied to bits [191:160] of the
-/// returned vector.
-/// Bits [5:4]:
-/// 00: Bits [159:128] of the source are copied to bits [223:192] of the
-/// returned vector.
-/// 01: Bits [191:160] of the source are copied to bits [223:192] of the
-/// returned vector.
-/// 10: Bits [223:192] of the source are copied to bits [223:192] of the
-/// returned vector.
-/// 11: Bits [255:224] of the source are copied to bits [223:192] of the
-/// returned vector.
-/// Bits [7:6]:
-/// 00: Bits [159:128] of the source are copied to bits [255:224] of the
-/// returned vector.
-/// 01: Bits [191:160] of the source are copied to bits [255:224] of the
-/// returned vector.
-/// 10: Bits [223:192] of the source are copied to bits [255:224] of the
-/// returned vector.
-/// 11: Bits [255:224] of the source are copied to bits [255:224] of the
-/// returned vector.
+/// An immediate integer operand specifying how the values are to be \n
+/// copied. \n
+/// Bits [1:0]: \n
+/// 00: Bits [31:0] of the source are copied to bits [31:0] of the
+/// returned vector. \n
+/// 01: Bits [63:32] of the source are copied to bits [31:0] of the
+/// returned vector. \n
+/// 10: Bits [95:64] of the source are copied to bits [31:0] of the
+/// returned vector. \n
+/// 11: Bits [127:96] of the source are copied to bits [31:0] of the
+/// returned vector. \n
+/// Bits [3:2]: \n
+/// 00: Bits [31:0] of the source are copied to bits [63:32] of the
+/// returned vector. \n
+/// 01: Bits [63:32] of the source are copied to bits [63:32] of the
+/// returned vector. \n
+/// 10: Bits [95:64] of the source are copied to bits [63:32] of the
+/// returned vector. \n
+/// 11: Bits [127:96] of the source are copied to bits [63:32] of the
+/// returned vector. \n
+/// Bits [5:4]: \n
+/// 00: Bits [31:0] of the source are copied to bits [95:64] of the
+/// returned vector. \n
+/// 01: Bits [63:32] of the source are copied to bits [95:64] of the
+/// returned vector. \n
+/// 10: Bits [95:64] of the source are copied to bits [95:64] of the
+/// returned vector. \n
+/// 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
+/// returned vector. \n
+/// 01: Bits [63:32] of the source are copied to bits [127:96] of the
+/// returned vector. \n
+/// 10: Bits [95:64] of the source are copied to bits [127:96] of the
+/// returned vector. \n
+/// 11: Bits [127:96] of the source are copied to bits [127:96] of the
+/// returned vector. \n
+/// Bits [1:0]: \n
+/// 00: Bits [159:128] of the source are copied to bits [159:128] of the
+/// returned vector. \n
+/// 01: Bits [191:160] of the source are copied to bits [159:128] of the
+/// returned vector. \n
+/// 10: Bits [223:192] of the source are copied to bits [159:128] of the
+/// returned vector. \n
+/// 11: Bits [255:224] of the source are copied to bits [159:128] of the
+/// returned vector. \n
+/// Bits [3:2]: \n
+/// 00: Bits [159:128] of the source are copied to bits [191:160] of the
+/// returned vector. \n
+/// 01: Bits [191:160] of the source are copied to bits [191:160] of the
+/// returned vector. \n
+/// 10: Bits [223:192] of the source are copied to bits [191:160] of the
+/// returned vector. \n
+/// 11: Bits [255:224] of the source are copied to bits [191:160] of the
+/// returned vector. \n
+/// Bits [5:4]: \n
+/// 00: Bits [159:128] of the source are copied to bits [223:192] of the
+/// returned vector. \n
+/// 01: Bits [191:160] of the source are copied to bits [223:192] of the
+/// returned vector. \n
+/// 10: Bits [223:192] of the source are copied to bits [223:192] of the
+/// returned vector. \n
+/// 11: Bits [255:224] of the source are copied to bits [223:192] of the
+/// returned vector. \n
+/// Bits [7:6]: \n
+/// 00: Bits [159:128] of the source are copied to bits [255:224] of the
+/// returned vector. \n
+/// 01: Bits [191:160] of the source are copied to bits [255:224] of the
+/// returned vector. \n
+/// 10: Bits [223:192] of the source are copied to bits [255:224] of the
+/// returned vector. \n
+/// 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), \
@@ -1213,7 +1216,7 @@ _mm256_permutevar_ps(__m256 __a, __m256i __c)
/// __m256d _mm256_permute2f128_pd(__m256d V1, __m256d V2, const int M);
/// \endcode
///
-/// This intrinsic corresponds to the \c VPERM2F128 / PERM2F128 instruction.
+/// This intrinsic corresponds to the <c> VPERM2F128 </c> instruction.
///
/// \param V1
/// A 256-bit vector of [4 x double].
@@ -1221,25 +1224,25 @@ _mm256_permutevar_ps(__m256 __a, __m256i __c)
/// A 256-bit vector of [4 x double.
/// \param M
/// An immediate integer operand specifying how the values are to be
-/// permuted.
-/// Bits [1:0]:
-/// 00: Bits [127:0] of operand V1 are copied to bits [127:0] of the
-/// destination.
-/// 01: Bits [255:128] of operand V1 are copied to bits [127:0] of the
-/// destination.
-/// 10: Bits [127:0] of operand V2 are copied to bits [127:0] of the
-/// destination.
-/// 11: Bits [255:128] of operand V2 are copied to bits [127:0] of the
-/// destination.
-/// Bits [5:4]:
-/// 00: Bits [127:0] of operand V1 are copied to bits [255:128] of the
-/// destination.
-/// 01: Bits [255:128] of operand V1 are copied to bits [255:128] of the
-/// destination.
-/// 10: Bits [127:0] of operand V2 are copied to bits [255:128] of the
-/// destination.
-/// 11: Bits [255:128] of operand V2 are copied to bits [255:128] of the
-/// destination.
+/// permuted. \n
+/// Bits [1:0]: \n
+/// 00: Bits [127:0] of operand \a V1 are copied to bits [127:0] of the
+/// destination. \n
+/// 01: Bits [255:128] of operand \a V1 are copied to bits [127:0] of the
+/// destination. \n
+/// 10: Bits [127:0] of operand \a V2 are copied to bits [127:0] of the
+/// destination. \n
+/// 11: Bits [255:128] of operand \a V2 are copied to bits [127:0] of the
+/// destination. \n
+/// Bits [5:4]: \n
+/// 00: Bits [127:0] of operand \a V1 are copied to bits [255:128] of the
+/// destination. \n
+/// 01: Bits [255:128] of operand \a V1 are copied to bits [255:128] of the
+/// destination. \n
+/// 10: Bits [127:0] of operand \a V2 are copied to bits [255:128] of the
+/// destination. \n
+/// 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__ ({ \
(__m256d)__builtin_ia32_vperm2f128_pd256((__v4df)(__m256d)(V1), \
@@ -1254,7 +1257,7 @@ _mm256_permutevar_ps(__m256 __a, __m256i __c)
/// __m256 _mm256_permute2f128_ps(__m256 V1, __m256 V2, const int M);
/// \endcode
///
-/// This intrinsic corresponds to the \c VPERM2F128 / PERM2F128 instruction.
+/// This intrinsic corresponds to the <c> VPERM2F128 </c> instruction.
///
/// \param V1
/// A 256-bit vector of [8 x float].
@@ -1262,24 +1265,24 @@ _mm256_permutevar_ps(__m256 __a, __m256i __c)
/// A 256-bit vector of [8 x float].
/// \param M
/// An immediate integer operand specifying how the values are to be
-/// permuted.
-/// Bits [1:0]:
-/// 00: Bits [127:0] of operand V1 are copied to bits [127:0] of the
-/// destination.
-/// 01: Bits [255:128] of operand V1 are copied to bits [127:0] of the
-/// destination.
-/// 10: Bits [127:0] of operand V2 are copied to bits [127:0] of the
-/// destination.
-/// 11: Bits [255:128] of operand V2 are copied to bits [127:0] of the
-/// destination.
-/// Bits [5:4]:
-/// 00: Bits [127:0] of operand V1 are copied to bits [255:128] of the
-/// destination.
-/// 01: Bits [255:128] of operand V1 are copied to bits [255:128] of the
-/// destination.
-/// 10: Bits [127:0] of operand V2 are copied to bits [255:128] of the
-/// destination.
-/// 11: Bits [255:128] of operand V2 are copied to bits [255:128] of the
+/// permuted. \n
+/// Bits [1:0]: \n
+/// 00: Bits [127:0] of operand \a V1 are copied to bits [127:0] of the
+/// destination. \n
+/// 01: Bits [255:128] of operand \a V1 are copied to bits [127:0] of the
+/// destination. \n
+/// 10: Bits [127:0] of operand \a V2 are copied to bits [127:0] of the
+/// destination. \n
+/// 11: Bits [255:128] of operand \a V2 are copied to bits [127:0] of the
+/// destination. \n
+/// Bits [5:4]: \n
+/// 00: Bits [127:0] of operand \a V1 are copied to bits [255:128] of the
+/// destination. \n
+/// 01: Bits [255:128] of operand \a V1 are copied to bits [255:128] of the
+/// destination. \n
+/// 10: Bits [127:0] of operand \a V2 are copied to bits [255:128] of the
+/// destination. \n
+/// 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__ ({ \
@@ -1295,7 +1298,7 @@ _mm256_permutevar_ps(__m256 __a, __m256i __c)
/// __m256i _mm256_permute2f128_si256(__m256i V1, __m256i V2, const int M);
/// \endcode
///
-/// This intrinsic corresponds to the \c VPERM2F128 / PERM2F128 instruction.
+/// This intrinsic corresponds to the <c> VPERM2F128 </c> instruction.
///
/// \param V1
/// A 256-bit integer vector.
@@ -1303,23 +1306,23 @@ _mm256_permutevar_ps(__m256 __a, __m256i __c)
/// A 256-bit integer vector.
/// \param M
/// An immediate integer operand specifying how the values are to be copied.
-/// Bits [1:0]:
-/// 00: Bits [127:0] of operand V1 are copied to bits [127:0] of the
-/// destination.
-/// 01: Bits [255:128] of operand V1 are copied to bits [127:0] of the
-/// destination.
-/// 10: Bits [127:0] of operand V2 are copied to bits [127:0] of the
-/// destination.
-/// 11: Bits [255:128] of operand V2 are copied to bits [127:0] of the
-/// destination.
-/// Bits [5:4]:
-/// 00: Bits [127:0] of operand V1 are copied to bits [255:128] of the
-/// destination.
-/// 01: Bits [255:128] of operand V1 are copied to bits [255:128] of the
-/// destination.
-/// 10: Bits [127:0] of operand V2 are copied to bits [255:128] of the
-/// destination.
-/// 11: Bits [255:128] of operand V2 are copied to bits [255:128] of the
+/// Bits [1:0]: \n
+/// 00: Bits [127:0] of operand \a V1 are copied to bits [127:0] of the
+/// destination. \n
+/// 01: Bits [255:128] of operand \a V1 are copied to bits [127:0] of the
+/// destination. \n
+/// 10: Bits [127:0] of operand \a V2 are copied to bits [127:0] of the
+/// destination. \n
+/// 11: Bits [255:128] of operand \a V2 are copied to bits [127:0] of the
+/// destination. \n
+/// Bits [5:4]: \n
+/// 00: Bits [127:0] of operand \a V1 are copied to bits [255:128] of the
+/// destination. \n
+/// 01: Bits [255:128] of operand \a V1 are copied to bits [255:128] of the
+/// destination. \n
+/// 10: Bits [127:0] of operand \a V2 are copied to bits [255:128] of the
+/// destination. \n
+/// 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__ ({ \
@@ -1337,7 +1340,7 @@ _mm256_permutevar_ps(__m256 __a, __m256i __c)
/// __m256d _mm256_blend_pd(__m256d V1, __m256d V2, const int M);
/// \endcode
///
-/// This intrinsic corresponds to the \c VBLENDPD / BLENDPD instruction.
+/// This intrinsic corresponds to the <c> VBLENDPD </c> instruction.
///
/// \param V1
/// A 256-bit vector of [4 x double].
@@ -1347,9 +1350,9 @@ _mm256_permutevar_ps(__m256 __a, __m256i __c)
/// An immediate integer operand, with mask bits [3:0] specifying how the
/// values are to be copied. The position of the mask bit corresponds to the
/// index of a copied value. When a mask bit is 0, the corresponding 64-bit
-/// element in operand V1 is copied to the same position in the destination.
-/// When a mask bit is 1, the corresponding 64-bit element in operand V2 is
-/// copied to the same position in the destination.
+/// element in operand \a V1 is copied to the same position in the
+/// 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), \
@@ -1369,7 +1372,7 @@ _mm256_permutevar_ps(__m256 __a, __m256i __c)
/// __m256 _mm256_blend_ps(__m256 V1, __m256 V2, const int M);
/// \endcode
///
-/// This intrinsic corresponds to the \c VBLENDPS / BLENDPS instruction.
+/// This intrinsic corresponds to the <c> VBLENDPS </c> instruction.
///
/// \param V1
/// A 256-bit vector of [8 x float].
@@ -1379,9 +1382,9 @@ _mm256_permutevar_ps(__m256 __a, __m256i __c)
/// An immediate integer operand, with mask bits [7:0] specifying how the
/// values are to be copied. The position of the mask bit corresponds to the
/// index of a copied value. When a mask bit is 0, the corresponding 32-bit
-/// element in operand V1 is copied to the same position in the destination.
-/// When a mask bit is 1, the corresponding 32-bit element in operand V2 is
-/// copied to the same position in the destination.
+/// element in operand \a V1 is copied to the same position in the
+/// 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), \
@@ -1401,7 +1404,7 @@ _mm256_permutevar_ps(__m256 __a, __m256i __c)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VBLENDVPD / BLENDVPD instruction.
+/// This intrinsic corresponds to the <c> VBLENDVPD </c> instruction.
///
/// \param __a
/// A 256-bit vector of [4 x double].
@@ -1411,9 +1414,9 @@ _mm256_permutevar_ps(__m256 __a, __m256i __c)
/// A 256-bit vector operand, with mask bits 255, 191, 127, and 63 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 64-bit element in operand __a is copied to the same
+/// corresponding 64-bit element in operand \a __a is copied to the same
/// position in the destination. When a mask bit is 1, the corresponding
-/// 64-bit element in operand __b is copied to the same position in the
+/// 64-bit element in operand \a __b is copied to the same position in the
/// destination.
/// \returns A 256-bit vector of [4 x double] containing the copied values.
static __inline __m256d __DEFAULT_FN_ATTRS
@@ -1429,7 +1432,7 @@ _mm256_blendv_pd(__m256d __a, __m256d __b, __m256d __c)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VBLENDVPS / BLENDVPS instruction.
+/// This intrinsic corresponds to the <c> VBLENDVPS </c> instruction.
///
/// \param __a
/// A 256-bit vector of [8 x float].
@@ -1439,9 +1442,9 @@ _mm256_blendv_pd(__m256d __a, __m256d __b, __m256d __c)
/// A 256-bit vector operand, with mask bits 255, 223, 191, 159, 127, 95, 63,
/// and 31 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 32-bit element in operand __a is
+/// a mask bit is 0, the corresponding 32-bit element in operand \a __a is
/// copied to the same position in the destination. When a mask bit is 1, the
-/// corresponding 32-bit element in operand __b is copied to the same
+/// corresponding 32-bit element in operand \a __b is copied to the same
/// position in the destination.
/// \returns A 256-bit vector of [8 x float] containing the copied values.
static __inline __m256 __DEFAULT_FN_ATTRS
@@ -1455,12 +1458,12 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c)
/// \brief 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. The immediate integer operand controls which
-/// input elements will contribute to the dot product, and where the final
-/// results are returned. In general, for each dot product, the four
-/// corresponding elements of the input vectors are multiplied; the first
-/// two and second two products are summed, then the two sums are added to
-/// form the final result.
+/// [8 x float] result. The immediate integer operand controls which input
+/// elements will contribute to the dot product, and where the final results
+/// are returned. In general, for each dot product, the four corresponding
+/// elements of the input vectors are multiplied; the first two and second
+/// two products are summed, then the two sums are added to form the final
+/// result.
///
/// \headerfile <x86intrin.h>
///
@@ -1468,7 +1471,7 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c)
/// __m256 _mm256_dp_ps(__m256 V1, __m256 V2, const int M);
/// \endcode
///
-/// This intrinsic corresponds to the \c VDPPS / DPPS instruction.
+/// This intrinsic corresponds to the <c> VDPPS </c> instruction.
///
/// \param V1
/// A vector of [8 x float] values, treated as two [4 x float] vectors.
@@ -1510,7 +1513,7 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c)
/// __m256 _mm256_shuffle_ps(__m256 a, __m256 b, const int mask);
/// \endcode
///
-/// This intrinsic corresponds to the \c VSHUFPS / SHUFPS instruction.
+/// This intrinsic corresponds to the <c> VSHUFPS </c> instruction.
///
/// \param a
/// A 256-bit vector of [8 x float]. The four selected elements in this
@@ -1522,22 +1525,23 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c)
/// destination, according to the bits specified in the immediate operand.
/// \param mask
/// An immediate value containing an 8-bit value specifying which elements to
-/// copy from a and b. Bits [3:0] specify the values copied from operand a.
-/// Bits [7:4] specify the values copied from operand b.
+/// copy from \a a and \a b \n.
+/// Bits [3:0] specify the values copied from operand \a a. \n
+/// Bits [7:4] specify the values copied from operand \a b. \n
/// The destinations within the 256-bit destination are assigned values as
-/// follows, according to the bit value assignments described below:
+/// follows, according to the bit value assignments described below: \n
/// Bits [1:0] are used to assign values to bits [31:0] and [159:128] in the
-/// destination.
+/// destination. \n
/// Bits [3:2] are used to assign values to bits [63:32] and [191:160] in the
-/// destination.
+/// destination. \n
/// Bits [5:4] are used to assign values to bits [95:64] and [223:192] in the
-/// destination.
+/// destination. \n
/// Bits [7:6] are used to assign values to bits [127:96] and [255:224] in
-/// the destination.
-/// Bit value assignments:
-/// 00: Bits [31:0] and [159:128] are copied from the selected operand.
-/// 01: Bits [63:32] and [191:160] are copied from the selected operand.
-/// 10: Bits [95:64] and [223:192] are copied from the selected operand.
+/// the destination. \n
+/// Bit value assignments: \n
+/// 00: Bits [31:0] and [159:128] are copied from the selected operand. \n
+/// 01: Bits [63:32] and [191:160] are copied from the selected operand. \n
+/// 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__ ({ \
@@ -1567,7 +1571,7 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c)
/// __m256d _mm256_shuffle_pd(__m256d a, __m256d b, const int mask);
/// \endcode
///
-/// This intrinsic corresponds to the \c VSHUFPD / SHUFPD instruction.
+/// This intrinsic corresponds to the <c> VSHUFPD </c> instruction.
///
/// \param a
/// A 256-bit vector of [4 x double].
@@ -1575,22 +1579,22 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c)
/// A 256-bit vector of [4 x double].
/// \param mask
/// An immediate value containing 8-bit values specifying which elements to
-/// copy from a and b:
-/// Bit [0]=0: Bits [63:0] are copied from a to bits [63:0] of the
-/// destination.
-/// Bit [0]=1: Bits [127:64] are copied from a to bits [63:0] of the
-/// destination.
-/// Bit [1]=0: Bits [63:0] are copied from b to bits [127:64] of the
-/// destination.
-/// Bit [1]=1: Bits [127:64] are copied from b to bits [127:64] of the
-/// destination.
-/// Bit [2]=0: Bits [191:128] are copied from a to bits [191:128] of the
-/// destination.
-/// Bit [2]=1: Bits [255:192] are copied from a to bits [191:128] of the
-/// destination.
-/// Bit [3]=0: Bits [191:128] are copied from b to bits [255:192] of the
-/// destination.
-/// Bit [3]=1: Bits [255:192] are copied from b to bits [255:192] of the
+/// copy from \a a and \a b: \n
+/// Bit [0]=0: Bits [63:0] are copied from \a a to bits [63:0] of the
+/// destination. \n
+/// Bit [0]=1: Bits [127:64] are copied from \a a to bits [63:0] of the
+/// destination. \n
+/// Bit [1]=0: Bits [63:0] are copied from \a b to bits [127:64] of the
+/// destination. \n
+/// Bit [1]=1: Bits [127:64] are copied from \a b to bits [127:64] of the
+/// destination. \n
+/// Bit [2]=0: Bits [191:128] are copied from \a a to bits [191:128] of the
+/// destination. \n
+/// Bit [2]=1: Bits [255:192] are copied from \a a to bits [191:128] of the
+/// destination. \n
+/// Bit [3]=0: Bits [191:128] are copied from \a b to bits [255:192] of the
+/// destination. \n
+/// 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__ ({ \
@@ -1647,7 +1651,7 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c)
/// __m128d _mm_cmp_pd(__m128d a, __m128d b, const int c);
/// \endcode
///
-/// This intrinsic corresponds to the \c VCMPPD / CMPPD instruction.
+/// This intrinsic corresponds to the <c> VCMPPD </c> instruction.
///
/// \param a
/// A 128-bit vector of [2 x double].
@@ -1655,16 +1659,17 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c)
/// A 128-bit vector of [2 x double].
/// \param c
/// An immediate integer operand, with bits [4:0] specifying which comparison
-/// operation to use:
-/// 00h, 08h, 10h, 18h: Equal
-/// 01h, 09h, 11h, 19h: Less than
-/// 02h, 0Ah, 12h, 1Ah: Less than or equal / Greater than or equal (swapped
-/// operands)
-/// 03h, 0Bh, 13h, 1Bh: Unordered
-/// 04h, 0Ch, 14h, 1Ch: Not equal
-/// 05h, 0Dh, 15h, 1Dh: Not less than / Not greater than (swapped operands)
+/// operation to use: \n
+/// 00h, 08h, 10h, 18h: Equal \n
+/// 01h, 09h, 11h, 19h: Less than \n
+/// 02h, 0Ah, 12h, 1Ah: Less than or equal / Greater than or equal
+/// (swapped operands) \n
+/// 03h, 0Bh, 13h, 1Bh: Unordered \n
+/// 04h, 0Ch, 14h, 1Ch: Not equal \n
+/// 05h, 0Dh, 15h, 1Dh: Not less than / Not greater than
+/// (swapped operands) \n
/// 06h, 0Eh, 16h, 1Eh: Not less than or equal / Not greater than or equal
-/// (swapped operands)
+/// (swapped operands) \n
/// 07h, 0Fh, 17h, 1Fh: Ordered
/// \returns A 128-bit vector of [2 x double] containing the comparison results.
#define _mm_cmp_pd(a, b, c) __extension__ ({ \
@@ -1683,7 +1688,7 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c)
/// __m128 _mm_cmp_ps(__m128 a, __m128 b, const int c);
/// \endcode
///
-/// This intrinsic corresponds to the \c VCMPPS / CMPPS instruction.
+/// This intrinsic corresponds to the <c> VCMPPS </c> instruction.
///
/// \param a
/// A 128-bit vector of [4 x float].
@@ -1691,16 +1696,17 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c)
/// A 128-bit vector of [4 x float].
/// \param c
/// An immediate integer operand, with bits [4:0] specifying which comparison
-/// operation to use:
-/// 00h, 08h, 10h, 18h: Equal
-/// 01h, 09h, 11h, 19h: Less than
-/// 02h, 0Ah, 12h, 1Ah: Less than or equal / Greater than or equal (swapped
-/// operands)
-/// 03h, 0Bh, 13h, 1Bh: Unordered
-/// 04h, 0Ch, 14h, 1Ch: Not equal
-/// 05h, 0Dh, 15h, 1Dh: Not less than / Not greater than (swapped operands)
+/// operation to use: \n
+/// 00h, 08h, 10h, 18h: Equal \n
+/// 01h, 09h, 11h, 19h: Less than \n
+/// 02h, 0Ah, 12h, 1Ah: Less than or equal / Greater than or equal
+/// (swapped operands) \n
+/// 03h, 0Bh, 13h, 1Bh: Unordered \n
+/// 04h, 0Ch, 14h, 1Ch: Not equal \n
+/// 05h, 0Dh, 15h, 1Dh: Not less than / Not greater than
+/// (swapped operands) \n
/// 06h, 0Eh, 16h, 1Eh: Not less than or equal / Not greater than or equal
-/// (swapped operands)
+/// (swapped operands) \n
/// 07h, 0Fh, 17h, 1Fh: Ordered
/// \returns A 128-bit vector of [4 x float] containing the comparison results.
#define _mm_cmp_ps(a, b, c) __extension__ ({ \
@@ -1719,7 +1725,7 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c)
/// __m256d _mm256_cmp_pd(__m256d a, __m256d b, const int c);
/// \endcode
///
-/// This intrinsic corresponds to the \c VCMPPD / CMPPD instruction.
+/// This intrinsic corresponds to the <c> VCMPPD </c> instruction.
///
/// \param a
/// A 256-bit vector of [4 x double].
@@ -1727,16 +1733,17 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c)
/// A 256-bit vector of [4 x double].
/// \param c
/// An immediate integer operand, with bits [4:0] specifying which comparison
-/// operation to use:
-/// 00h, 08h, 10h, 18h: Equal
-/// 01h, 09h, 11h, 19h: Less than
-/// 02h, 0Ah, 12h, 1Ah: Less than or equal / Greater than or equal (swapped
-/// operands)
-/// 03h, 0Bh, 13h, 1Bh: Unordered
-/// 04h, 0Ch, 14h, 1Ch: Not equal
-/// 05h, 0Dh, 15h, 1Dh: Not less than / Not greater than (swapped operands)
+/// operation to use: \n
+/// 00h, 08h, 10h, 18h: Equal \n
+/// 01h, 09h, 11h, 19h: Less than \n
+/// 02h, 0Ah, 12h, 1Ah: Less than or equal / Greater than or equal
+/// (swapped operands) \n
+/// 03h, 0Bh, 13h, 1Bh: Unordered \n
+/// 04h, 0Ch, 14h, 1Ch: Not equal \n
+/// 05h, 0Dh, 15h, 1Dh: Not less than / Not greater than
+/// (swapped operands) \n
/// 06h, 0Eh, 16h, 1Eh: Not less than or equal / Not greater than or equal
-/// (swapped operands)
+/// (swapped operands) \n
/// 07h, 0Fh, 17h, 1Fh: Ordered
/// \returns A 256-bit vector of [4 x double] containing the comparison results.
#define _mm256_cmp_pd(a, b, c) __extension__ ({ \
@@ -1755,7 +1762,7 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c)
/// __m256 _mm256_cmp_ps(__m256 a, __m256 b, const int c);
/// \endcode
///
-/// This intrinsic corresponds to the \c VCMPPS / CMPPS instruction.
+/// This intrinsic corresponds to the <c> VCMPPS </c> instruction.
///
/// \param a
/// A 256-bit vector of [8 x float].
@@ -1763,16 +1770,17 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c)
/// A 256-bit vector of [8 x float].
/// \param c
/// An immediate integer operand, with bits [4:0] specifying which comparison
-/// operation to use:
-/// 00h, 08h, 10h, 18h: Equal
-/// 01h, 09h, 11h, 19h: Less than
-/// 02h, 0Ah, 12h, 1Ah: Less than or equal / Greater than or equal (swapped
-/// operands)
-/// 03h, 0Bh, 13h, 1Bh: Unordered
-/// 04h, 0Ch, 14h, 1Ch: Not equal
-/// 05h, 0Dh, 15h, 1Dh: Not less than / Not greater than (swapped operands)
+/// operation to use: \n
+/// 00h, 08h, 10h, 18h: Equal \n
+/// 01h, 09h, 11h, 19h: Less than \n
+/// 02h, 0Ah, 12h, 1Ah: Less than or equal / Greater than or equal
+/// (swapped operands) \n
+/// 03h, 0Bh, 13h, 1Bh: Unordered \n
+/// 04h, 0Ch, 14h, 1Ch: Not equal \n
+/// 05h, 0Dh, 15h, 1Dh: Not less than / Not greater than
+/// (swapped operands) \n
/// 06h, 0Eh, 16h, 1Eh: Not less than or equal / Not greater than or equal
-/// (swapped operands)
+/// (swapped operands) \n
/// 07h, 0Fh, 17h, 1Fh: Ordered
/// \returns A 256-bit vector of [8 x float] containing the comparison results.
#define _mm256_cmp_ps(a, b, c) __extension__ ({ \
@@ -1790,7 +1798,7 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c)
/// __m128d _mm_cmp_sd(__m128d a, __m128d b, const int c);
/// \endcode
///
-/// This intrinsic corresponds to the \c VCMPSD / CMPSD instruction.
+/// This intrinsic corresponds to the <c> VCMPSD </c> instruction.
///
/// \param a
/// A 128-bit vector of [2 x double].
@@ -1798,16 +1806,17 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c)
/// A 128-bit vector of [2 x double].
/// \param c
/// An immediate integer operand, with bits [4:0] specifying which comparison
-/// operation to use:
-/// 00h, 08h, 10h, 18h: Equal
-/// 01h, 09h, 11h, 19h: Less than
-/// 02h, 0Ah, 12h, 1Ah: Less than or equal / Greater than or equal (swapped
-/// operands)
-/// 03h, 0Bh, 13h, 1Bh: Unordered
-/// 04h, 0Ch, 14h, 1Ch: Not equal
-/// 05h, 0Dh, 15h, 1Dh: Not less than / Not greater than (swapped operands)
+/// operation to use: \n
+/// 00h, 08h, 10h, 18h: Equal \n
+/// 01h, 09h, 11h, 19h: Less than \n
+/// 02h, 0Ah, 12h, 1Ah: Less than or equal / Greater than or equal
+/// (swapped operands) \n
+/// 03h, 0Bh, 13h, 1Bh: Unordered \n
+/// 04h, 0Ch, 14h, 1Ch: Not equal \n
+/// 05h, 0Dh, 15h, 1Dh: Not less than / Not greater than
+/// (swapped operands) \n
/// 06h, 0Eh, 16h, 1Eh: Not less than or equal / Not greater than or equal
-/// (swapped operands)
+/// (swapped operands) \n
/// 07h, 0Fh, 17h, 1Fh: Ordered
/// \returns A 128-bit vector of [2 x double] containing the comparison results.
#define _mm_cmp_sd(a, b, c) __extension__ ({ \
@@ -1825,7 +1834,7 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c)
/// __m128 _mm_cmp_ss(__m128 a, __m128 b, const int c);
/// \endcode
///
-/// This intrinsic corresponds to the \c VCMPSS / CMPSS instruction.
+/// This intrinsic corresponds to the <c> VCMPSS </c> instruction.
///
/// \param a
/// A 128-bit vector of [4 x float].
@@ -1833,16 +1842,17 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c)
/// A 128-bit vector of [4 x float].
/// \param c
/// An immediate integer operand, with bits [4:0] specifying which comparison
-/// operation to use:
-/// 00h, 08h, 10h, 18h: Equal
-/// 01h, 09h, 11h, 19h: Less than
-/// 02h, 0Ah, 12h, 1Ah: Less than or equal / Greater than or equal (swapped
-/// operands)
-/// 03h, 0Bh, 13h, 1Bh: Unordered
-/// 04h, 0Ch, 14h, 1Ch: Not equal
-/// 05h, 0Dh, 15h, 1Dh: Not less than / Not greater than (swapped operands)
+/// operation to use: \n
+/// 00h, 08h, 10h, 18h: Equal \n
+/// 01h, 09h, 11h, 19h: Less than \n
+/// 02h, 0Ah, 12h, 1Ah: Less than or equal / Greater than or equal
+/// (swapped operands) \n
+/// 03h, 0Bh, 13h, 1Bh: Unordered \n
+/// 04h, 0Ch, 14h, 1Ch: Not equal \n
+/// 05h, 0Dh, 15h, 1Dh: Not less than / Not greater than
+/// (swapped operands) \n
/// 06h, 0Eh, 16h, 1Eh: Not less than or equal / Not greater than or equal
-/// (swapped operands)
+/// (swapped operands) \n
/// 07h, 0Fh, 17h, 1Fh: Ordered
/// \returns A 128-bit vector of [4 x float] containing the comparison results.
#define _mm_cmp_ss(a, b, c) __extension__ ({ \
@@ -1854,8 +1864,8 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VEXTRACTF128+COMPOSITE /
-/// EXTRACTF128+COMPOSITE instruction.
+/// This intrinsic corresponds to the <c> VEXTRACTF128+COMPOSITE </c>
+/// instruction.
///
/// \param __a
/// A 256-bit vector of [8 x i32].
@@ -1876,8 +1886,8 @@ _mm256_extract_epi32(__m256i __a, const int __imm)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VEXTRACTF128+COMPOSITE /
-/// EXTRACTF128+COMPOSITE instruction.
+/// This intrinsic corresponds to the <c> VEXTRACTF128+COMPOSITE </c>
+/// instruction.
///
/// \param __a
/// A 256-bit integer vector of [16 x i16].
@@ -1898,8 +1908,8 @@ _mm256_extract_epi16(__m256i __a, const int __imm)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VEXTRACTF128+COMPOSITE /
-/// EXTRACTF128+COMPOSITE instruction.
+/// This intrinsic corresponds to the <c> VEXTRACTF128+COMPOSITE </c>
+/// instruction.
///
/// \param __a
/// A 256-bit integer vector of [32 x i8].
@@ -1921,8 +1931,8 @@ _mm256_extract_epi8(__m256i __a, const int __imm)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VEXTRACTF128+COMPOSITE /
-/// EXTRACTF128+COMPOSITE instruction.
+/// This intrinsic corresponds to the <c> VEXTRACTF128+COMPOSITE </c>
+/// instruction.
///
/// \param __a
/// A 256-bit integer vector of [4 x i64].
@@ -1945,8 +1955,8 @@ _mm256_extract_epi64(__m256i __a, const int __imm)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VINSERTF128+COMPOSITE /
-/// INSERTF128+COMPOSITE instruction.
+/// This intrinsic corresponds to the <c> VINSERTF128+COMPOSITE </c>
+/// instruction.
///
/// \param __a
/// A vector of [8 x i32] to be used by the insert operation.
@@ -1955,8 +1965,8 @@ _mm256_extract_epi64(__m256i __a, const int __imm)
/// \param __imm
/// An immediate integer specifying the index of the vector element to be
/// replaced.
-/// \returns A copy of vector __a, after replacing its element indexed by __imm
-/// with __b.
+/// \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)
{
@@ -1972,8 +1982,8 @@ _mm256_insert_epi32(__m256i __a, int __b, int const __imm)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VINSERTF128+COMPOSITE /
-/// INSERTF128+COMPOSITE instruction.
+/// This intrinsic corresponds to the <c> VINSERTF128+COMPOSITE </c>
+/// instruction.
///
/// \param __a
/// A vector of [16 x i16] to be used by the insert operation.
@@ -1982,8 +1992,8 @@ _mm256_insert_epi32(__m256i __a, int __b, int const __imm)
/// \param __imm
/// An immediate integer specifying the index of the vector element to be
/// replaced.
-/// \returns A copy of vector __a, after replacing its element indexed by __imm
-/// with __b.
+/// \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)
{
@@ -1998,8 +2008,8 @@ _mm256_insert_epi16(__m256i __a, int __b, int const __imm)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VINSERTF128+COMPOSITE /
-/// INSERTF128+COMPOSITE instruction.
+/// This intrinsic corresponds to the <c> VINSERTF128+COMPOSITE </c>
+/// instruction.
///
/// \param __a
/// A vector of [32 x i8] to be used by the insert operation.
@@ -2008,8 +2018,8 @@ _mm256_insert_epi16(__m256i __a, int __b, int const __imm)
/// \param __imm
/// An immediate integer specifying the index of the vector element to be
/// replaced.
-/// \returns A copy of vector __a, after replacing its element indexed by __imm
-/// with __b.
+/// \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)
{
@@ -2025,8 +2035,8 @@ _mm256_insert_epi8(__m256i __a, int __b, int const __imm)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VINSERTF128+COMPOSITE /
-/// INSERTF128+COMPOSITE instruction.
+/// This intrinsic corresponds to the <c> VINSERTF128+COMPOSITE </c>
+/// instruction.
///
/// \param __a
/// A vector of [4 x i64] to be used by the insert operation.
@@ -2035,8 +2045,8 @@ _mm256_insert_epi8(__m256i __a, int __b, int const __imm)
/// \param __imm
/// An immediate integer specifying the index of the vector element to be
/// replaced.
-/// \returns A copy of vector __a, after replacing its element indexed by __imm
-/// with __b.
+/// \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)
{
@@ -2051,7 +2061,7 @@ _mm256_insert_epi64(__m256i __a, long long __b, int const __imm)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCVTDQ2PD / CVTDQ2PD instruction.
+/// This intrinsic corresponds to the <c> VCVTDQ2PD </c> instruction.
///
/// \param __a
/// A 128-bit integer vector of [4 x i32].
@@ -2066,7 +2076,7 @@ _mm256_cvtepi32_pd(__m128i __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCVTDQ2PS / CVTDQ2PS instruction.
+/// This intrinsic corresponds to the <c> VCVTDQ2PS </c> instruction.
///
/// \param __a
/// A 256-bit integer vector.
@@ -2082,7 +2092,7 @@ _mm256_cvtepi32_ps(__m256i __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCVTPD2PS / CVTPD2PS instruction.
+/// This intrinsic corresponds to the <c> VCVTPD2PS </c> instruction.
///
/// \param __a
/// A 256-bit vector of [4 x double].
@@ -2097,7 +2107,7 @@ _mm256_cvtpd_ps(__m256d __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCVTPS2DQ / CVTPS2DQ instruction.
+/// This intrinsic corresponds to the <c> VCVTPS2DQ </c> instruction.
///
/// \param __a
/// A 256-bit vector of [8 x float].
@@ -2108,24 +2118,66 @@ _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
+/// x double].
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VCVTPS2PD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [4 x float].
+/// \returns A 256-bit vector of [4 x double] containing the converted values.
static __inline __m256d __DEFAULT_FN_ATTRS
_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
+/// x i32], truncating the result by rounding towards zero when it is
+/// inexact.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VCVTTPD2DQ </c> instruction.
+///
+/// \param __a
+/// A 256-bit vector of [4 x double].
+/// \returns A 128-bit integer vector containing the converted values.
static __inline __m128i __DEFAULT_FN_ATTRS
_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
+/// x i32]. When a conversion is inexact, the value returned is rounded
+/// according to the rounding control bits in the MXCSR register.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VCVTPD2DQ </c> instruction.
+///
+/// \param __a
+/// A 256-bit vector of [4 x double].
+/// \returns A 128-bit integer vector containing the converted values.
static __inline __m128i __DEFAULT_FN_ATTRS
_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],
+/// truncating the result by rounding towards zero when it is inexact.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VCVTTPS2DQ </c> instruction.
+///
+/// \param __a
+/// A 256-bit vector of [8 x float].
+/// \returns A 256-bit integer vector containing the converted values.
static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_cvttps_epi32(__m256 __a)
{
@@ -2152,18 +2204,73 @@ _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].
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMOVSHDUP </c> instruction.
+///
+/// \param __a
+/// A 256-bit vector of [8 x float]. \n
+/// Bits [255:224] of \a __a are written to bits [255:224] and [223:192] of
+/// the return value. \n
+/// Bits [191:160] of \a __a are written to bits [191:160] and [159:128] of
+/// the return value. \n
+/// Bits [127:96] of \a __a are written to bits [127:96] and [95:64] of the
+/// return value. \n
+/// Bits [63:32] of \a __a are written to bits [63:32] and [31:0] of the
+/// return value.
+/// \returns A 256-bit vector of [8 x float] containing the moved and duplicated
+/// values.
static __inline __m256 __DEFAULT_FN_ATTRS
_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].
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMOVSLDUP </c> instruction.
+///
+/// \param __a
+/// A 256-bit vector of [8 x float]. \n
+/// Bits [223:192] of \a __a are written to bits [255:224] and [223:192] of
+/// the return value. \n
+/// Bits [159:128] of \a __a are written to bits [191:160] and [159:128] of
+/// the return value. \n
+/// Bits [95:64] of \a __a are written to bits [127:96] and [95:64] of the
+/// return value. \n
+/// Bits [31:0] of \a __a are written to bits [63:32] and [31:0] of the
+/// return value.
+/// \returns A 256-bit vector of [8 x float] containing the moved and duplicated
+/// values.
static __inline __m256 __DEFAULT_FN_ATTRS
_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
+/// 256-bit vector of [4 x double] to double-precision values in a 256-bit
+/// vector of [4 x double].
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMOVDDUP </c> instruction.
+///
+/// \param __a
+/// A 256-bit vector of [4 x double]. \n
+/// Bits [63:0] of \a __a are written to bits [127:64] and [63:0] of the
+/// return value. \n
+/// Bits [191:128] of \a __a are written to bits [255:192] and [191:128] of
+/// the return value.
+/// \returns A 256-bit vector of [4 x double] containing the moved and
+/// duplicated values.
static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_movedup_pd(__m256d __a)
{
@@ -2171,24 +2278,98 @@ _mm256_movedup_pd(__m256d __a)
}
/* Unpack and Interleave */
+/// \brief 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>
+///
+/// This intrinsic corresponds to the <c> VUNPCKHPD </c> instruction.
+///
+/// \param __a
+/// A 256-bit floating-point vector of [4 x double]. \n
+/// Bits [127:64] are written to bits [63:0] of the return value. \n
+/// Bits [255:192] are written to bits [191:128] of the return value. \n
+/// \param __b
+/// A 256-bit floating-point vector of [4 x double]. \n
+/// Bits [127:64] are written to bits [127:64] of the return value. \n
+/// Bits [255:192] are written to bits [255:192] of the return value. \n
+/// \returns A 256-bit vector of [4 x double] containing the interleaved values.
static __inline __m256d __DEFAULT_FN_ATTRS
_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
+/// [4 x double] and interleaves them into a 256-bit vector of [4 x double].
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VUNPCKLPD </c> instruction.
+///
+/// \param __a
+/// A 256-bit floating-point vector of [4 x double]. \n
+/// Bits [63:0] are written to bits [63:0] of the return value. \n
+/// Bits [191:128] are written to bits [191:128] of the return value.
+/// \param __b
+/// A 256-bit floating-point vector of [4 x double]. \n
+/// Bits [63:0] are written to bits [127:64] of the return value. \n
+/// Bits [191:128] are written to bits [255:192] of the return value. \n
+/// \returns A 256-bit vector of [4 x double] containing the interleaved values.
static __inline __m256d __DEFAULT_FN_ATTRS
_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
+/// two 256-bit vectors of [8 x float] and interleaves them into a 256-bit
+/// vector of [8 x float].
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VUNPCKHPS </c> instruction.
+///
+/// \param __a
+/// A 256-bit vector of [8 x float]. \n
+/// Bits [95:64] are written to bits [31:0] of the return value. \n
+/// Bits [127:96] are written to bits [95:64] of the return value. \n
+/// Bits [223:192] are written to bits [159:128] of the return value. \n
+/// Bits [255:224] are written to bits [223:192] of the return value.
+/// \param __b
+/// A 256-bit vector of [8 x float]. \n
+/// Bits [95:64] are written to bits [63:32] of the return value. \n
+/// Bits [127:96] are written to bits [127:96] of the return value. \n
+/// Bits [223:192] are written to bits [191:160] of the return value. \n
+/// Bits [255:224] are written to bits [255:224] of the return value.
+/// \returns A 256-bit vector of [8 x float] containing the interleaved values.
static __inline __m256 __DEFAULT_FN_ATTRS
_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
+/// two 256-bit vectors of [8 x float] and interleaves them into a 256-bit
+/// vector of [8 x float].
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VUNPCKLPS </c> instruction.
+///
+/// \param __a
+/// A 256-bit vector of [8 x float]. \n
+/// Bits [31:0] are written to bits [31:0] of the return value. \n
+/// Bits [63:32] are written to bits [95:64] of the return value. \n
+/// Bits [159:128] are written to bits [159:128] of the return value. \n
+/// Bits [191:160] are written to bits [223:192] of the return value.
+/// \param __b
+/// A 256-bit vector of [8 x float]. \n
+/// Bits [31:0] are written to bits [63:32] of the return value. \n
+/// Bits [63:32] are written to bits [127:96] of the return value. \n
+/// Bits [159:128] are written to bits [191:160] of the return value. \n
+/// Bits [191:160] are written to bits [255:224] of the return value.
+/// \returns A 256-bit vector of [8 x float] containing the interleaved values.
static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_unpacklo_ps(__m256 __a, __m256 __b)
{
@@ -2196,90 +2377,401 @@ _mm256_unpacklo_ps(__m256 __a, __m256 __b)
}
/* Bit Test */
+/// \brief 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. The EFLAGS register is updated as follows: \n
+/// If there is at least one pair of double-precision elements where the
+/// sign-bits of both elements are 1, the ZF flag is set to 0. Otherwise the
+/// ZF flag is set to 1. \n
+/// If there is at least one pair of double-precision elements where the
+/// sign-bit of the first element is 0 and the sign-bit of the second element
+/// is 1, the CF flag is set to 0. Otherwise the CF flag is set to 1. \n
+/// This intrinsic returns the value of the ZF flag.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VTESTPD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double].
+/// \param __b
+/// A 128-bit vector of [2 x double].
+/// \returns the ZF flag in the EFLAGS register.
static __inline int __DEFAULT_FN_ATTRS
_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
+/// element-by-element comparison of the double-precision element in the
+/// first source vector and the corresponding element in the second source
+/// vector. The EFLAGS register is updated as follows: \n
+/// If there is at least one pair of double-precision elements where the
+/// sign-bits of both elements are 1, the ZF flag is set to 0. Otherwise the
+/// ZF flag is set to 1. \n
+/// If there is at least one pair of double-precision elements where the
+/// sign-bit of the first element is 0 and the sign-bit of the second element
+/// is 1, the CF flag is set to 0. Otherwise the CF flag is set to 1. \n
+/// This intrinsic returns the value of the CF flag.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VTESTPD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double].
+/// \param __b
+/// A 128-bit vector of [2 x double].
+/// \returns the CF flag in the EFLAGS register.
static __inline int __DEFAULT_FN_ATTRS
_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
+/// element-by-element comparison of the double-precision element in the
+/// first source vector and the corresponding element in the second source
+/// vector. The EFLAGS register is updated as follows: \n
+/// If there is at least one pair of double-precision elements where the
+/// sign-bits of both elements are 1, the ZF flag is set to 0. Otherwise the
+/// ZF flag is set to 1. \n
+/// If there is at least one pair of double-precision elements where the
+/// sign-bit of the first element is 0 and the sign-bit of the second element
+/// is 1, the CF flag is set to 0. Otherwise the CF flag is set to 1. \n
+/// This intrinsic returns 1 if both the ZF and CF flags are set to 0,
+/// otherwise it returns 0.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VTESTPD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double].
+/// \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
_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
+/// element-by-element comparison of the single-precision element in the
+/// first source vector and the corresponding element in the second source
+/// vector. The EFLAGS register is updated as follows: \n
+/// If there is at least one pair of single-precision elements where the
+/// sign-bits of both elements are 1, the ZF flag is set to 0. Otherwise the
+/// ZF flag is set to 1. \n
+/// If there is at least one pair of single-precision elements where the
+/// sign-bit of the first element is 0 and the sign-bit of the second element
+/// is 1, the CF flag is set to 0. Otherwise the CF flag is set to 1. \n
+/// This intrinsic returns the value of the ZF flag.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VTESTPS </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [4 x float].
+/// \param __b
+/// A 128-bit vector of [4 x float].
+/// \returns the ZF flag.
static __inline int __DEFAULT_FN_ATTRS
_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
+/// element-by-element comparison of the single-precision element in the
+/// first source vector and the corresponding element in the second source
+/// vector. The EFLAGS register is updated as follows: \n
+/// If there is at least one pair of single-precision elements where the
+/// sign-bits of both elements are 1, the ZF flag is set to 0. Otherwise the
+/// ZF flag is set to 1. \n
+/// If there is at least one pair of single-precision elements where the
+/// sign-bit of the first element is 0 and the sign-bit of the second element
+/// is 1, the CF flag is set to 0. Otherwise the CF flag is set to 1. \n
+/// This intrinsic returns the value of the CF flag.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VTESTPS </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [4 x float].
+/// \param __b
+/// A 128-bit vector of [4 x float].
+/// \returns the CF flag.
static __inline int __DEFAULT_FN_ATTRS
_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
+/// element-by-element comparison of the single-precision element in the
+/// first source vector and the corresponding element in the second source
+/// vector. The EFLAGS register is updated as follows: \n
+/// If there is at least one pair of single-precision elements where the
+/// sign-bits of both elements are 1, the ZF flag is set to 0. Otherwise the
+/// ZF flag is set to 1. \n
+/// If there is at least one pair of single-precision elements where the
+/// sign-bit of the first element is 0 and the sign-bit of the second element
+/// is 1, the CF flag is set to 0. Otherwise the CF flag is set to 1. \n
+/// This intrinsic returns 1 if both the ZF and CF flags are set to 0,
+/// otherwise it returns 0.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VTESTPS </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [4 x float].
+/// \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
_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
+/// element-by-element comparison of the double-precision elements in the
+/// first source vector and the corresponding elements in the second source
+/// vector. The EFLAGS register is updated as follows: \n
+/// If there is at least one pair of double-precision elements where the
+/// sign-bits of both elements are 1, the ZF flag is set to 0. Otherwise the
+/// ZF flag is set to 1. \n
+/// If there is at least one pair of double-precision elements where the
+/// sign-bit of the first element is 0 and the sign-bit of the second element
+/// is 1, the CF flag is set to 0. Otherwise the CF flag is set to 1. \n
+/// This intrinsic returns the value of the ZF flag.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VTESTPD </c> instruction.
+///
+/// \param __a
+/// A 256-bit vector of [4 x double].
+/// \param __b
+/// A 256-bit vector of [4 x double].
+/// \returns the ZF flag.
static __inline int __DEFAULT_FN_ATTRS
_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
+/// element-by-element comparison of the double-precision elements in the
+/// first source vector and the corresponding elements in the second source
+/// vector. The EFLAGS register is updated as follows: \n
+/// If there is at least one pair of double-precision elements where the
+/// sign-bits of both elements are 1, the ZF flag is set to 0. Otherwise the
+/// ZF flag is set to 1. \n
+/// If there is at least one pair of double-precision elements where the
+/// sign-bit of the first element is 0 and the sign-bit of the second element
+/// is 1, the CF flag is set to 0. Otherwise the CF flag is set to 1. \n
+/// This intrinsic returns the value of the CF flag.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VTESTPD </c> instruction.
+///
+/// \param __a
+/// A 256-bit vector of [4 x double].
+/// \param __b
+/// A 256-bit vector of [4 x double].
+/// \returns the CF flag.
static __inline int __DEFAULT_FN_ATTRS
_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
+/// element-by-element comparison of the double-precision elements in the
+/// first source vector and the corresponding elements in the second source
+/// vector. The EFLAGS register is updated as follows: \n
+/// If there is at least one pair of double-precision elements where the
+/// sign-bits of both elements are 1, the ZF flag is set to 0. Otherwise the
+/// ZF flag is set to 1. \n
+/// If there is at least one pair of double-precision elements where the
+/// sign-bit of the first element is 0 and the sign-bit of the second element
+/// is 1, the CF flag is set to 0. Otherwise the CF flag is set to 1. \n
+/// This intrinsic returns 1 if both the ZF and CF flags are set to 0,
+/// otherwise it returns 0.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VTESTPD </c> instruction.
+///
+/// \param __a
+/// A 256-bit vector of [4 x double].
+/// \param __b
+/// A 256-bit vector of [4 x double].
+/// \returns 1 if both the ZF and CF flags are set to 0, otherwise returns 0.
static __inline int __DEFAULT_FN_ATTRS
_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
+/// element-by-element comparison of the single-precision element in the
+/// first source vector and the corresponding element in the second source
+/// vector. The EFLAGS register is updated as follows: \n
+/// If there is at least one pair of single-precision elements where the
+/// sign-bits of both elements are 1, the ZF flag is set to 0. Otherwise the
+/// ZF flag is set to 1. \n
+/// If there is at least one pair of single-precision elements where the
+/// sign-bit of the first element is 0 and the sign-bit of the second element
+/// is 1, the CF flag is set to 0. Otherwise the CF flag is set to 1. \n
+/// This intrinsic returns the value of the ZF flag.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VTESTPS </c> instruction.
+///
+/// \param __a
+/// A 256-bit vector of [8 x float].
+/// \param __b
+/// A 256-bit vector of [8 x float].
+/// \returns the ZF flag.
static __inline int __DEFAULT_FN_ATTRS
_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
+/// element-by-element comparison of the single-precision element in the
+/// first source vector and the corresponding element in the second source
+/// vector. The EFLAGS register is updated as follows: \n
+/// If there is at least one pair of single-precision elements where the
+/// sign-bits of both elements are 1, the ZF flag is set to 0. Otherwise the
+/// ZF flag is set to 1. \n
+/// If there is at least one pair of single-precision elements where the
+/// sign-bit of the first element is 0 and the sign-bit of the second element
+/// is 1, the CF flag is set to 0. Otherwise the CF flag is set to 1. \n
+/// This intrinsic returns the value of the CF flag.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VTESTPS </c> instruction.
+///
+/// \param __a
+/// A 256-bit vector of [8 x float].
+/// \param __b
+/// A 256-bit vector of [8 x float].
+/// \returns the CF flag.
static __inline int __DEFAULT_FN_ATTRS
_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
+/// element-by-element comparison of the single-precision elements in the
+/// first source vector and the corresponding elements in the second source
+/// vector. The EFLAGS register is updated as follows: \n
+/// If there is at least one pair of single-precision elements where the
+/// sign-bits of both elements are 1, the ZF flag is set to 0. Otherwise the
+/// ZF flag is set to 1. \n
+/// If there is at least one pair of single-precision elements where the
+/// sign-bit of the first element is 0 and the sign-bit of the second element
+/// is 1, the CF flag is set to 0. Otherwise the CF flag is set to 1. \n
+/// This intrinsic returns 1 if both the ZF and CF flags are set to 0,
+/// otherwise it returns 0.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VTESTPS </c> instruction.
+///
+/// \param __a
+/// A 256-bit vector of [8 x float].
+/// \param __b
+/// A 256-bit vector of [8 x float].
+/// \returns 1 if both the ZF and CF flags are set to 0, otherwise returns 0.
static __inline int __DEFAULT_FN_ATTRS
_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
+/// of the two source vectors and update the EFLAGS register as follows: \n
+/// If there is at least one pair of bits where both bits are 1, the ZF flag
+/// is set to 0. Otherwise the ZF flag is set to 1. \n
+/// If there is at least one pair of bits where the bit from the first source
+/// vector is 0 and the bit from the second source vector is 1, the CF flag
+/// is set to 0. Otherwise the CF flag is set to 1. \n
+/// This intrinsic returns the value of the ZF flag.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VPTEST </c> instruction.
+///
+/// \param __a
+/// A 256-bit integer vector.
+/// \param __b
+/// A 256-bit integer vector.
+/// \returns the ZF flag.
static __inline int __DEFAULT_FN_ATTRS
_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
+/// of the two source vectors and update the EFLAGS register as follows: \n
+/// If there is at least one pair of bits where both bits are 1, the ZF flag
+/// is set to 0. Otherwise the ZF flag is set to 1. \n
+/// If there is at least one pair of bits where the bit from the first source
+/// vector is 0 and the bit from the second source vector is 1, the CF flag
+/// is set to 0. Otherwise the CF flag is set to 1. \n
+/// This intrinsic returns the value of the CF flag.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VPTEST </c> instruction.
+///
+/// \param __a
+/// A 256-bit integer vector.
+/// \param __b
+/// A 256-bit integer vector.
+/// \returns the CF flag.
static __inline int __DEFAULT_FN_ATTRS
_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
+/// of the two source vectors and update the EFLAGS register as follows: \n
+/// If there is at least one pair of bits where both bits are 1, the ZF flag
+/// is set to 0. Otherwise the ZF flag is set to 1. \n
+/// If there is at least one pair of bits where the bit from the first source
+/// vector is 0 and the bit from the second source vector is 1, the CF flag
+/// is set to 0. Otherwise the CF flag is set to 1. \n
+/// This intrinsic returns 1 if both the ZF and CF flags are set to 0,
+/// otherwise it returns 0.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VPTEST </c> instruction.
+///
+/// \param __a
+/// A 256-bit integer vector.
+/// \param __b
+/// A 256-bit integer vector.
+/// \returns 1 if both the ZF and CF flags are set to 0, otherwise returns 0.
static __inline int __DEFAULT_FN_ATTRS
_mm256_testnzc_si256(__m256i __a, __m256i __b)
{
@@ -2287,12 +2779,36 @@ _mm256_testnzc_si256(__m256i __a, __m256i __b)
}
/* Vector extract sign mask */
+/// \brief 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMOVMSKPD </c> instruction.
+///
+/// \param __a
+/// A 256-bit vector of [4 x double] containing the double-precision
+/// floating point values with sign bits to be extracted.
+/// \returns The sign bits from the operand, written to bits [3:0].
static __inline int __DEFAULT_FN_ATTRS
_mm256_movemask_pd(__m256d __a)
{
return __builtin_ia32_movmskpd256((__v4df)__a);
}
+/// \brief Extracts the sign bits of double-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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMOVMSKPS </c> instruction.
+///
+/// \param __a
+/// A 256-bit vector of [8 x float] containing the double-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
_mm256_movemask_ps(__m256 __a)
{
@@ -2300,12 +2816,22 @@ _mm256_movemask_ps(__m256 __a)
}
/* Vector __zero */
+/// \brief 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
_mm256_zeroall(void)
{
__builtin_ia32_vzeroall();
}
+/// \brief 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
_mm256_zeroupper(void)
{
@@ -2313,6 +2839,18 @@ _mm256_zeroupper(void)
}
/* Vector load with broadcast */
+/// \brief 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VBROADCASTSS </c> instruction.
+///
+/// \param __a
+/// 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
_mm_broadcast_ss(float const *__a)
{
@@ -2320,6 +2858,18 @@ _mm_broadcast_ss(float const *__a)
return (__m128)(__v4sf){ __f, __f, __f, __f };
}
+/// \brief 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VBROADCASTSD </c> instruction.
+///
+/// \param __a
+/// The double-precision floating point value to be broadcast.
+/// \returns A 256-bit vector of [4 x double] whose 64-bit elements are set
+/// equal to the broadcast value.
static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_broadcast_sd(double const *__a)
{
@@ -2327,6 +2877,18 @@ _mm256_broadcast_sd(double const *__a)
return (__m256d)(__v4df){ __d, __d, __d, __d };
}
+/// \brief 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VBROADCASTSS </c> instruction.
+///
+/// \param __a
+/// The single-precision floating point value to be broadcast.
+/// \returns A 256-bit vector of [8 x float] whose 32-bit elements are set
+/// equal to the broadcast value.
static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_broadcast_ss(float const *__a)
{
@@ -2334,12 +2896,36 @@ _mm256_broadcast_ss(float const *__a)
return (__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
+/// specified address pointed to by \a __a and broadcasts it to 128-bit
+/// elements in a 256-bit vector of [4 x double].
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VBROADCASTF128 </c> instruction.
+///
+/// \param __a
+/// The 128-bit vector of [2 x double] to be broadcast.
+/// \returns A 256-bit vector of [4 x double] whose 128-bit elements are set
+/// equal to the broadcast value.
static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_broadcast_pd(__m128d const *__a)
{
return (__m256d)__builtin_ia32_vbroadcastf128_pd256((__v2df const *)__a);
}
+/// \brief 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].
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VBROADCASTF128 </c> instruction.
+///
+/// \param __a
+/// The 128-bit vector of [4 x float] to be broadcast.
+/// \returns A 256-bit vector of [8 x float] whose 128-bit elements are set
+/// equal to the broadcast value.
static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_broadcast_ps(__m128 const *__a)
{
@@ -2347,18 +2933,50 @@ _mm256_broadcast_ps(__m128 const *__a)
}
/* SIMD load ops */
+/// \brief 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>
+///
+/// This intrinsic corresponds to the <c> VMOVAPD </c> instruction.
+///
+/// \param __p
+/// A 32-byte aligned pointer to a memory location containing
+/// double-precision floating point values.
+/// \returns A 256-bit vector of [4 x double] containing the moved values.
static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_load_pd(double const *__p)
{
return *(__m256d *)__p;
}
+/// \brief 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>
+///
+/// This intrinsic corresponds to the <c> VMOVAPS </c> instruction.
+///
+/// \param __p
+/// A 32-byte aligned pointer to a memory location containing float values.
+/// \returns A 256-bit vector of [8 x float] containing the moved values.
static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_load_ps(float const *__p)
{
return *(__m256 *)__p;
}
+/// \brief 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>
+///
+/// This intrinsic corresponds to the <c> VMOVUPD </c> instruction.
+///
+/// \param __p
+/// A pointer to a memory location containing double-precision floating
+/// point values.
+/// \returns A 256-bit vector of [4 x double] containing the moved values.
static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_loadu_pd(double const *__p)
{
@@ -2368,6 +2986,17 @@ _mm256_loadu_pd(double const *__p)
return ((struct __loadu_pd*)__p)->__v;
}
+/// \brief 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>
+///
+/// This intrinsic corresponds to the <c> VMOVUPS </c> instruction.
+///
+/// \param __p
+/// A pointer to a memory location containing single-precision floating
+/// point values.
+/// \returns A 256-bit vector of [8 x float] containing the moved values.
static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_loadu_ps(float const *__p)
{
@@ -2377,12 +3006,33 @@ _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
+/// location pointed to by \a __p into elements of a 256-bit integer vector.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMOVDQA </c> instruction.
+///
+/// \param __p
+/// A 32-byte aligned pointer to a 256-bit integer vector containing integer
+/// values.
+/// \returns A 256-bit integer vector containing the moved values.
static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_load_si256(__m256i const *__p)
{
return *__p;
}
+/// \brief 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>
+///
+/// This intrinsic corresponds to the <c> VMOVDQU </c> instruction.
+///
+/// \param __p
+/// A pointer to a 256-bit integer vector containing integer values.
+/// \returns A 256-bit integer vector containing the moved values.
static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_loadu_si256(__m256i const *__p)
{
@@ -2392,6 +3042,18 @@ _mm256_loadu_si256(__m256i const *__p)
return ((struct __loadu_si256*)__p)->__v;
}
+/// \brief 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VLDDQU </c> instruction.
+///
+/// \param __p
+/// A pointer to a 256-bit integer vector containing integer values.
+/// \returns A 256-bit integer vector containing the moved values.
static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_lddqu_si256(__m256i const *__p)
{
@@ -2399,18 +3061,55 @@ _mm256_lddqu_si256(__m256i const *__p)
}
/* SIMD store ops */
+/// \brief 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMOVAPD </c> instruction.
+///
+/// \param __p
+/// A 32-byte aligned pointer to a memory location that will receive the
+/// double-precision floaing point values.
+/// \param __a
+/// A 256-bit vector of [4 x double] containing the values to be moved.
static __inline void __DEFAULT_FN_ATTRS
_mm256_store_pd(double *__p, __m256d __a)
{
*(__m256d *)__p = __a;
}
+/// \brief 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>
+///
+/// This intrinsic corresponds to the <c> VMOVAPS </c> instruction.
+///
+/// \param __p
+/// A 32-byte aligned pointer to a memory location that will receive the
+/// float values.
+/// \param __a
+/// A 256-bit vector of [8 x float] containing the values to be moved.
static __inline void __DEFAULT_FN_ATTRS
_mm256_store_ps(float *__p, __m256 __a)
{
*(__m256 *)__p = __a;
}
+/// \brief 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>
+///
+/// This intrinsic corresponds to the <c> VMOVUPD </c> instruction.
+///
+/// \param __p
+/// A pointer to a memory location that will receive the double-precision
+/// floating point values.
+/// \param __a
+/// A 256-bit vector of [4 x double] containing the values to be moved.
static __inline void __DEFAULT_FN_ATTRS
_mm256_storeu_pd(double *__p, __m256d __a)
{
@@ -2420,6 +3119,17 @@ _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
+/// of [8 x float] to an unaligned memory location pointed to by \a __p.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMOVUPS </c> instruction.
+///
+/// \param __p
+/// A pointer to a memory location that will receive the float values.
+/// \param __a
+/// A 256-bit vector of [8 x float] containing the values to be moved.
static __inline void __DEFAULT_FN_ATTRS
_mm256_storeu_ps(float *__p, __m256 __a)
{
@@ -2429,12 +3139,35 @@ _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
+/// aligned memory location pointed to by \a __p.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMOVDQA </c> instruction.
+///
+/// \param __p
+/// A 32-byte aligned pointer to a memory location that will receive the
+/// integer values.
+/// \param __a
+/// A 256-bit integer vector containing the values to be moved.
static __inline void __DEFAULT_FN_ATTRS
_mm256_store_si256(__m256i *__p, __m256i __a)
{
*__p = __a;
}
+/// \brief Stores integer values from a 256-bit integer vector to an unaligned
+/// memory location pointed to by \a __p.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMOVDQU </c> instruction.
+///
+/// \param __p
+/// A pointer to a memory location that will receive the integer values.
+/// \param __a
+/// A 256-bit integer vector containing the values to be moved.
static __inline void __DEFAULT_FN_ATTRS
_mm256_storeu_si256(__m256i *__p, __m256i __a)
{
@@ -2445,12 +3178,48 @@ _mm256_storeu_si256(__m256i *__p, __m256i __a)
}
/* Conditional load ops */
+/// \brief 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMASKMOVPD </c> instruction.
+///
+/// \param __p
+/// A pointer to a memory location that contains the double-precision
+/// floating point values.
+/// \param __m
+/// A 128-bit integer vector containing the mask. The most significant bit of
+/// each data element represents the mask bits. If a mask bit is zero, the
+/// 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
_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
+/// 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMASKMOVPD </c> instruction.
+///
+/// \param __p
+/// A pointer to a memory location that contains the double-precision
+/// floating point values.
+/// \param __m
+/// A 256-bit integer vector of [4 x quadword] containing the mask. The most
+/// significant bit of each quadword element represents the mask bits. If a
+/// mask bit is zero, the corresponding value in the memory location is not
+/// loaded and the corresponding field in the return value is set to zero.
+/// \returns A 256-bit vector of [4 x double] containing the loaded values.
static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_maskload_pd(double const *__p, __m256i __m)
{
@@ -2458,12 +3227,48 @@ _mm256_maskload_pd(double const *__p, __m256i __m)
(__v4di)__m);
}
+/// \brief 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMASKMOVPS </c> instruction.
+///
+/// \param __p
+/// A pointer to a memory location that contains the single-precision
+/// floating point values.
+/// \param __m
+/// A 128-bit integer vector containing the mask. The most significant bit of
+/// each data element represents the mask bits. If a mask bit is zero, the
+/// 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
_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
+/// 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMASKMOVPS </c> instruction.
+///
+/// \param __p
+/// A pointer to a memory location that contains the single-precision
+/// floating point values.
+/// \param __m
+/// A 256-bit integer vector of [8 x dword] containing the mask. The most
+/// significant bit of each dword element represents the mask bits. If a mask
+/// bit is zero, the corresponding value in the memory location is not loaded
+/// and the corresponding field in the return value is set to zero.
+/// \returns A 256-bit vector of [8 x float] containing the loaded values.
static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_maskload_ps(float const *__p, __m256i __m)
{
@@ -2471,24 +3276,96 @@ _mm256_maskload_ps(float const *__p, __m256i __m)
}
/* Conditional store ops */
+/// \brief 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMASKMOVPS </c> instruction.
+///
+/// \param __p
+/// A pointer to a memory location that will receive the float values.
+/// \param __m
+/// A 256-bit integer vector of [8 x dword] containing the mask. The most
+/// significant bit of each dword element in the mask vector represents the
+/// mask bits. If a mask bit is zero, the corresponding value from vector
+/// \a __a is not stored and the corresponding field in the memory location
+/// pointed to by \a __p is not changed.
+/// \param __a
+/// A 256-bit vector of [8 x float] containing the values to be stored.
static __inline void __DEFAULT_FN_ATTRS
_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]
+/// to a memory location pointed to by \a __p, according to the specified
+/// mask.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMASKMOVPD </c> instruction.
+///
+/// \param __p
+/// A pointer to a memory location that will receive the float values.
+/// \param __m
+/// A 128-bit integer vector containing the mask. The most significant bit of
+/// each field in the mask vector represents the mask bits. If a mask bit is
+/// zero, the corresponding value from vector \a __a is not stored and the
+/// corresponding field in the memory location pointed to by \a __p is not
+/// changed.
+/// \param __a
+/// A 128-bit vector of [2 x double] containing the values to be stored.
static __inline void __DEFAULT_FN_ATTRS
_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]
+/// to a memory location pointed to by \a __p, according to the specified
+/// mask.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMASKMOVPD </c> instruction.
+///
+/// \param __p
+/// A pointer to a memory location that will receive the float values.
+/// \param __m
+/// A 256-bit integer vector of [4 x quadword] containing the mask. The most
+/// significant bit of each quadword element in the mask vector represents
+/// the mask bits. If a mask bit is zero, the corresponding value from vector
+/// __a is not stored and the corresponding field in the memory location
+/// pointed to by \a __p is not changed.
+/// \param __a
+/// A 256-bit vector of [4 x double] containing the values to be stored.
static __inline void __DEFAULT_FN_ATTRS
_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
+/// of [4 x float] to a memory location pointed to by \a __p, according to
+/// the specified mask.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMASKMOVPS </c> instruction.
+///
+/// \param __p
+/// A pointer to a memory location that will receive the float values.
+/// \param __m
+/// A 128-bit integer vector containing the mask. The most significant bit of
+/// each field in the mask vector represents the mask bits. If a mask bit is
+/// zero, the corresponding value from vector __a is not stored and the
+/// corresponding field in the memory location pointed to by \a __p is not
+/// changed.
+/// \param __a
+/// A 128-bit vector of [4 x float] containing the values to be stored.
static __inline void __DEFAULT_FN_ATTRS
_mm_maskstore_ps(float *__p, __m128i __m, __m128 __a)
{
@@ -2496,18 +3373,58 @@ _mm_maskstore_ps(float *__p, __m128i __m, __m128 __a)
}
/* Cacheability support ops */
+/// \brief 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).
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMOVNTDQ </c> instruction.
+///
+/// \param __a
+/// A pointer to a 32-byte aligned memory location that will receive the
+/// integer values.
+/// \param __b
+/// A 256-bit integer vector containing the values to be moved.
static __inline void __DEFAULT_FN_ATTRS
_mm256_stream_si256(__m256i *__a, __m256i __b)
{
__builtin_nontemporal_store((__v4di)__b, (__v4di*)__a);
}
+/// \brief 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).
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMOVNTPD </c> instruction.
+///
+/// \param __a
+/// A pointer to a 32-byte aligned memory location that will receive the
+/// integer values.
+/// \param __b
+/// A 256-bit vector of [4 x double] containing the values to be moved.
static __inline void __DEFAULT_FN_ATTRS
_mm256_stream_pd(double *__a, __m256d __b)
{
__builtin_nontemporal_store((__v4df)__b, (__v4df*)__a);
}
+/// \brief 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).
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMOVNTPS </c> instruction.
+///
+/// \param __p
+/// A pointer to a 32-byte aligned memory location that will receive the
+/// single-precision floating point values.
+/// \param __a
+/// A 256-bit vector of [8 x float] containing the values to be moved.
static __inline void __DEFAULT_FN_ATTRS
_mm256_stream_ps(float *__p, __m256 __a)
{
@@ -2515,30 +3432,105 @@ _mm256_stream_ps(float *__p, __m256 __a)
}
/* Create vectors */
+/// \brief Create a 256-bit vector of [4 x double] with undefined values.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic has no corresponding instruction.
+///
+/// \returns A 256-bit vector of [4 x double] containing undefined values.
static __inline__ __m256d __DEFAULT_FN_ATTRS
_mm256_undefined_pd(void)
{
return (__m256d)__builtin_ia32_undef256();
}
+/// \brief Create a 256-bit vector of [8 x float] with undefined values.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic has no corresponding instruction.
+///
+/// \returns A 256-bit vector of [8 x float] containing undefined values.
static __inline__ __m256 __DEFAULT_FN_ATTRS
_mm256_undefined_ps(void)
{
return (__m256)__builtin_ia32_undef256();
}
+/// \brief Create a 256-bit integer vector with undefined values.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic has no corresponding instruction.
+///
+/// \returns A 256-bit integer vector containing undefined values.
static __inline__ __m256i __DEFAULT_FN_ATTRS
_mm256_undefined_si256(void)
{
return (__m256i)__builtin_ia32_undef256();
}
+/// \brief Constructs a 256-bit floating-point vector of [4 x double]
+/// initialized with the specified double-precision floating-point values.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VUNPCKLPD+VINSERTF128 </c>
+/// instruction.
+///
+/// \param __a
+/// A double-precision floating-point value used to initialize bits [255:192]
+/// of the result.
+/// \param __b
+/// A double-precision floating-point value used to initialize bits [191:128]
+/// of the result.
+/// \param __c
+/// A double-precision floating-point value used to initialize bits [127:64]
+/// of the result.
+/// \param __d
+/// A double-precision floating-point value used to initialize bits [63:0]
+/// of the result.
+/// \returns An initialized 256-bit floating-point vector of [4 x double].
static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_set_pd(double __a, double __b, double __c, double __d)
{
return (__m256d){ __d, __c, __b, __a };
}
+/// \brief Constructs a 256-bit floating-point vector of [8 x float] initialized
+/// with the specified single-precision floating-point values.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic is a utility function and does not correspond to a specific
+/// instruction.
+///
+/// \param __a
+/// A single-precision floating-point value used to initialize bits [255:224]
+/// of the result.
+/// \param __b
+/// A single-precision floating-point value used to initialize bits [223:192]
+/// of the result.
+/// \param __c
+/// A single-precision floating-point value used to initialize bits [191:160]
+/// of the result.
+/// \param __d
+/// A single-precision floating-point value used to initialize bits [159:128]
+/// of the result.
+/// \param __e
+/// A single-precision floating-point value used to initialize bits [127:96]
+/// of the result.
+/// \param __f
+/// A single-precision floating-point value used to initialize bits [95:64]
+/// of the result.
+/// \param __g
+/// A single-precision floating-point value used to initialize bits [63:32]
+/// of the result.
+/// \param __h
+/// A single-precision floating-point value used to initialize bits [31:0]
+/// of the result.
+/// \returns An initialized 256-bit floating-point vector of [8 x float].
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)
@@ -2546,6 +3538,31 @@ _mm256_set_ps(float __a, float __b, float __c, float __d,
return (__m256){ __h, __g, __f, __e, __d, __c, __b, __a };
}
+/// \brief Constructs a 256-bit integer vector initialized with the specified
+/// 32-bit integral values.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic is a utility function and does not correspond to a specific
+/// instruction.
+///
+/// \param __i0
+/// A 32-bit integral value used to initialize bits [255:224] of the result.
+/// \param __i1
+/// A 32-bit integral value used to initialize bits [223:192] of the result.
+/// \param __i2
+/// A 32-bit integral value used to initialize bits [191:160] of the result.
+/// \param __i3
+/// A 32-bit integral value used to initialize bits [159:128] of the result.
+/// \param __i4
+/// A 32-bit integral value used to initialize bits [127:96] of the result.
+/// \param __i5
+/// A 32-bit integral value used to initialize bits [95:64] of the result.
+/// \param __i6
+/// A 32-bit integral value used to initialize bits [63:32] of the result.
+/// \param __i7
+/// A 32-bit integral value used to initialize bits [31:0] of the result.
+/// \returns An initialized 256-bit integer vector.
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)
@@ -2553,6 +3570,47 @@ _mm256_set_epi32(int __i0, int __i1, int __i2, int __i3,
return (__m256i)(__v8si){ __i7, __i6, __i5, __i4, __i3, __i2, __i1, __i0 };
}
+/// \brief Constructs a 256-bit integer vector initialized with the specified
+/// 16-bit integral values.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic is a utility function and does not correspond to a specific
+/// instruction.
+///
+/// \param __w15
+/// A 16-bit integral value used to initialize bits [255:240] of the result.
+/// \param __w14
+/// A 16-bit integral value used to initialize bits [239:224] of the result.
+/// \param __w13
+/// A 16-bit integral value used to initialize bits [223:208] of the result.
+/// \param __w12
+/// A 16-bit integral value used to initialize bits [207:192] of the result.
+/// \param __w11
+/// A 16-bit integral value used to initialize bits [191:176] of the result.
+/// \param __w10
+/// A 16-bit integral value used to initialize bits [175:160] of the result.
+/// \param __w09
+/// A 16-bit integral value used to initialize bits [159:144] of the result.
+/// \param __w08
+/// A 16-bit integral value used to initialize bits [143:128] of the result.
+/// \param __w07
+/// A 16-bit integral value used to initialize bits [127:112] of the result.
+/// \param __w06
+/// A 16-bit integral value used to initialize bits [111:96] of the result.
+/// \param __w05
+/// A 16-bit integral value used to initialize bits [95:80] of the result.
+/// \param __w04
+/// A 16-bit integral value used to initialize bits [79:64] of the result.
+/// \param __w03
+/// A 16-bit integral value used to initialize bits [63:48] of the result.
+/// \param __w02
+/// A 16-bit integral value used to initialize bits [47:32] of the result.
+/// \param __w01
+/// A 16-bit integral value used to initialize bits [31:16] of the result.
+/// \param __w00
+/// A 16-bit integral value used to initialize bits [15:0] of the result.
+/// \returns An initialized 256-bit integer vector.
static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_set_epi16(short __w15, short __w14, short __w13, short __w12,
short __w11, short __w10, short __w09, short __w08,
@@ -2563,6 +3621,79 @@ _mm256_set_epi16(short __w15, short __w14, short __w13, short __w12,
__w07, __w08, __w09, __w10, __w11, __w12, __w13, __w14, __w15 };
}
+/// \brief Constructs a 256-bit integer vector initialized with the specified
+/// 8-bit integral values.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic is a utility function and does not correspond to a specific
+/// instruction.
+///
+/// \param __b31
+/// An 8-bit integral value used to initialize bits [255:248] of the result.
+/// \param __b30
+/// An 8-bit integral value used to initialize bits [247:240] of the result.
+/// \param __b29
+/// An 8-bit integral value used to initialize bits [239:232] of the result.
+/// \param __b28
+/// An 8-bit integral value used to initialize bits [231:224] of the result.
+/// \param __b27
+/// An 8-bit integral value used to initialize bits [223:216] of the result.
+/// \param __b26
+/// An 8-bit integral value used to initialize bits [215:208] of the result.
+/// \param __b25
+/// An 8-bit integral value used to initialize bits [207:200] of the result.
+/// \param __b24
+/// An 8-bit integral value used to initialize bits [199:192] of the result.
+/// \param __b23
+/// An 8-bit integral value used to initialize bits [191:184] of the result.
+/// \param __b22
+/// An 8-bit integral value used to initialize bits [183:176] of the result.
+/// \param __b21
+/// An 8-bit integral value used to initialize bits [175:168] of the result.
+/// \param __b20
+/// An 8-bit integral value used to initialize bits [167:160] of the result.
+/// \param __b19
+/// An 8-bit integral value used to initialize bits [159:152] of the result.
+/// \param __b18
+/// An 8-bit integral value used to initialize bits [151:144] of the result.
+/// \param __b17
+/// An 8-bit integral value used to initialize bits [143:136] of the result.
+/// \param __b16
+/// An 8-bit integral value used to initialize bits [135:128] of the result.
+/// \param __b15
+/// An 8-bit integral value used to initialize bits [127:120] of the result.
+/// \param __b14
+/// An 8-bit integral value used to initialize bits [119:112] of the result.
+/// \param __b13
+/// An 8-bit integral value used to initialize bits [111:104] of the result.
+/// \param __b12
+/// An 8-bit integral value used to initialize bits [103:96] of the result.
+/// \param __b11
+/// An 8-bit integral value used to initialize bits [95:88] of the result.
+/// \param __b10
+/// An 8-bit integral value used to initialize bits [87:80] of the result.
+/// \param __b09
+/// An 8-bit integral value used to initialize bits [79:72] of the result.
+/// \param __b08
+/// An 8-bit integral value used to initialize bits [71:64] of the result.
+/// \param __b07
+/// An 8-bit integral value used to initialize bits [63:56] of the result.
+/// \param __b06
+/// An 8-bit integral value used to initialize bits [55:48] of the result.
+/// \param __b05
+/// An 8-bit integral value used to initialize bits [47:40] of the result.
+/// \param __b04
+/// An 8-bit integral value used to initialize bits [39:32] of the result.
+/// \param __b03
+/// An 8-bit integral value used to initialize bits [31:24] of the result.
+/// \param __b02
+/// An 8-bit integral value used to initialize bits [23:16] of the result.
+/// \param __b01
+/// An 8-bit integral value used to initialize bits [15:8] of the result.
+/// \param __b00
+/// An 8-bit integral value used to initialize bits [7:0] of the result.
+/// \returns An initialized 256-bit integer vector.
static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_set_epi8(char __b31, char __b30, char __b29, char __b28,
char __b27, char __b26, char __b25, char __b24,
@@ -2581,6 +3712,23 @@ _mm256_set_epi8(char __b31, char __b30, char __b29, char __b28,
};
}
+/// \brief Constructs a 256-bit integer vector initialized with the specified
+/// 64-bit integral values.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VPUNPCKLQDQ+VINSERTF128 </c>
+/// instruction.
+///
+/// \param __a
+/// A 64-bit integral value used to initialize bits [255:192] of the result.
+/// \param __b
+/// A 64-bit integral value used to initialize bits [191:128] of the result.
+/// \param __c
+/// A 64-bit integral value used to initialize bits [127:64] of the result.
+/// \param __d
+/// A 64-bit integral value used to initialize bits [63:0] of the result.
+/// \returns An initialized 256-bit integer vector.
static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_set_epi64x(long long __a, long long __b, long long __c, long long __d)
{
@@ -2588,12 +3736,68 @@ _mm256_set_epi64x(long long __a, long long __b, long long __c, long long __d)
}
/* Create vectors with elements in reverse order */
+/// \brief Constructs a 256-bit floating-point vector of [4 x double],
+/// initialized in reverse order with the specified double-precision
+/// floating-point values.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VUNPCKLPD+VINSERTF128 </c>
+/// instruction.
+///
+/// \param __a
+/// A double-precision floating-point value used to initialize bits [63:0]
+/// of the result.
+/// \param __b
+/// A double-precision floating-point value used to initialize bits [127:64]
+/// of the result.
+/// \param __c
+/// A double-precision floating-point value used to initialize bits [191:128]
+/// of the result.
+/// \param __d
+/// A double-precision floating-point value used to initialize bits [255:192]
+/// of the result.
+/// \returns An initialized 256-bit floating-point vector of [4 x double].
static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_setr_pd(double __a, double __b, double __c, double __d)
{
return (__m256d){ __a, __b, __c, __d };
}
+/// \brief Constructs a 256-bit floating-point vector of [8 x float],
+/// initialized in reverse order with the specified single-precision
+/// float-point values.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic is a utility function and does not correspond to a specific
+/// instruction.
+///
+/// \param __a
+/// A single-precision floating-point value used to initialize bits [31:0]
+/// of the result.
+/// \param __b
+/// A single-precision floating-point value used to initialize bits [63:32]
+/// of the result.
+/// \param __c
+/// A single-precision floating-point value used to initialize bits [95:64]
+/// of the result.
+/// \param __d
+/// A single-precision floating-point value used to initialize bits [127:96]
+/// of the result.
+/// \param __e
+/// A single-precision floating-point value used to initialize bits [159:128]
+/// of the result.
+/// \param __f
+/// A single-precision floating-point value used to initialize bits [191:160]
+/// of the result.
+/// \param __g
+/// A single-precision floating-point value used to initialize bits [223:192]
+/// of the result.
+/// \param __h
+/// A single-precision floating-point value used to initialize bits [255:224]
+/// of the result.
+/// \returns An initialized 256-bit floating-point vector of [8 x float].
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)
@@ -2601,6 +3805,31 @@ _mm256_setr_ps(float __a, float __b, float __c, float __d,
return (__m256){ __a, __b, __c, __d, __e, __f, __g, __h };
}
+/// \brief Constructs a 256-bit integer vector, initialized in reverse order
+/// with the specified 32-bit integral values.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic is a utility function and does not correspond to a specific
+/// instruction.
+///
+/// \param __i0
+/// A 32-bit integral value used to initialize bits [31:0] of the result.
+/// \param __i1
+/// A 32-bit integral value used to initialize bits [63:32] of the result.
+/// \param __i2
+/// A 32-bit integral value used to initialize bits [95:64] of the result.
+/// \param __i3
+/// A 32-bit integral value used to initialize bits [127:96] of the result.
+/// \param __i4
+/// A 32-bit integral value used to initialize bits [159:128] of the result.
+/// \param __i5
+/// A 32-bit integral value used to initialize bits [191:160] of the result.
+/// \param __i6
+/// A 32-bit integral value used to initialize bits [223:192] of the result.
+/// \param __i7
+/// A 32-bit integral value used to initialize bits [255:224] of the result.
+/// \returns An initialized 256-bit integer vector.
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)
@@ -2608,6 +3837,47 @@ _mm256_setr_epi32(int __i0, int __i1, int __i2, int __i3,
return (__m256i)(__v8si){ __i0, __i1, __i2, __i3, __i4, __i5, __i6, __i7 };
}
+/// \brief Constructs a 256-bit integer vector, initialized in reverse order
+/// with the specified 16-bit integral values.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic is a utility function and does not correspond to a specific
+/// instruction.
+///
+/// \param __w15
+/// A 16-bit integral value used to initialize bits [15:0] of the result.
+/// \param __w14
+/// A 16-bit integral value used to initialize bits [31:16] of the result.
+/// \param __w13
+/// A 16-bit integral value used to initialize bits [47:32] of the result.
+/// \param __w12
+/// A 16-bit integral value used to initialize bits [63:48] of the result.
+/// \param __w11
+/// A 16-bit integral value used to initialize bits [79:64] of the result.
+/// \param __w10
+/// A 16-bit integral value used to initialize bits [95:80] of the result.
+/// \param __w09
+/// A 16-bit integral value used to initialize bits [111:96] of the result.
+/// \param __w08
+/// A 16-bit integral value used to initialize bits [127:112] of the result.
+/// \param __w07
+/// A 16-bit integral value used to initialize bits [143:128] of the result.
+/// \param __w06
+/// A 16-bit integral value used to initialize bits [159:144] of the result.
+/// \param __w05
+/// A 16-bit integral value used to initialize bits [175:160] of the result.
+/// \param __w04
+/// A 16-bit integral value used to initialize bits [191:176] of the result.
+/// \param __w03
+/// A 16-bit integral value used to initialize bits [207:192] of the result.
+/// \param __w02
+/// A 16-bit integral value used to initialize bits [223:208] of the result.
+/// \param __w01
+/// A 16-bit integral value used to initialize bits [239:224] of the result.
+/// \param __w00
+/// A 16-bit integral value used to initialize bits [255:240] of the result.
+/// \returns An initialized 256-bit integer vector.
static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_setr_epi16(short __w15, short __w14, short __w13, short __w12,
short __w11, short __w10, short __w09, short __w08,
@@ -2618,6 +3888,79 @@ _mm256_setr_epi16(short __w15, short __w14, short __w13, short __w12,
__w08, __w07, __w06, __w05, __w04, __w03, __w02, __w01, __w00 };
}
+/// \brief Constructs a 256-bit integer vector, initialized in reverse order
+/// with the specified 8-bit integral values.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic is a utility function and does not correspond to a specific
+/// instruction.
+///
+/// \param __b31
+/// An 8-bit integral value used to initialize bits [7:0] of the result.
+/// \param __b30
+/// An 8-bit integral value used to initialize bits [15:8] of the result.
+/// \param __b29
+/// An 8-bit integral value used to initialize bits [23:16] of the result.
+/// \param __b28
+/// An 8-bit integral value used to initialize bits [31:24] of the result.
+/// \param __b27
+/// An 8-bit integral value used to initialize bits [39:32] of the result.
+/// \param __b26
+/// An 8-bit integral value used to initialize bits [47:40] of the result.
+/// \param __b25
+/// An 8-bit integral value used to initialize bits [55:48] of the result.
+/// \param __b24
+/// An 8-bit integral value used to initialize bits [63:56] of the result.
+/// \param __b23
+/// An 8-bit integral value used to initialize bits [71:64] of the result.
+/// \param __b22
+/// An 8-bit integral value used to initialize bits [79:72] of the result.
+/// \param __b21
+/// An 8-bit integral value used to initialize bits [87:80] of the result.
+/// \param __b20
+/// An 8-bit integral value used to initialize bits [95:88] of the result.
+/// \param __b19
+/// An 8-bit integral value used to initialize bits [103:96] of the result.
+/// \param __b18
+/// An 8-bit integral value used to initialize bits [111:104] of the result.
+/// \param __b17
+/// An 8-bit integral value used to initialize bits [119:112] of the result.
+/// \param __b16
+/// An 8-bit integral value used to initialize bits [127:120] of the result.
+/// \param __b15
+/// An 8-bit integral value used to initialize bits [135:128] of the result.
+/// \param __b14
+/// An 8-bit integral value used to initialize bits [143:136] of the result.
+/// \param __b13
+/// An 8-bit integral value used to initialize bits [151:144] of the result.
+/// \param __b12
+/// An 8-bit integral value used to initialize bits [159:152] of the result.
+/// \param __b11
+/// An 8-bit integral value used to initialize bits [167:160] of the result.
+/// \param __b10
+/// An 8-bit integral value used to initialize bits [175:168] of the result.
+/// \param __b09
+/// An 8-bit integral value used to initialize bits [183:176] of the result.
+/// \param __b08
+/// An 8-bit integral value used to initialize bits [191:184] of the result.
+/// \param __b07
+/// An 8-bit integral value used to initialize bits [199:192] of the result.
+/// \param __b06
+/// An 8-bit integral value used to initialize bits [207:200] of the result.
+/// \param __b05
+/// An 8-bit integral value used to initialize bits [215:208] of the result.
+/// \param __b04
+/// An 8-bit integral value used to initialize bits [223:216] of the result.
+/// \param __b03
+/// An 8-bit integral value used to initialize bits [231:224] of the result.
+/// \param __b02
+/// An 8-bit integral value used to initialize bits [239:232] of the result.
+/// \param __b01
+/// An 8-bit integral value used to initialize bits [247:240] of the result.
+/// \param __b00
+/// An 8-bit integral value used to initialize bits [255:248] of the result.
+/// \returns An initialized 256-bit integer vector.
static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_setr_epi8(char __b31, char __b30, char __b29, char __b28,
char __b27, char __b26, char __b25, char __b24,
@@ -2635,6 +3978,23 @@ _mm256_setr_epi8(char __b31, char __b30, char __b29, char __b28,
__b07, __b06, __b05, __b04, __b03, __b02, __b01, __b00 };
}
+/// \brief Constructs a 256-bit integer vector, initialized in reverse order
+/// with the specified 64-bit integral values.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VPUNPCKLQDQ+VINSERTF128 </c>
+/// instruction.
+///
+/// \param __a
+/// A 64-bit integral value used to initialize bits [63:0] of the result.
+/// \param __b
+/// A 64-bit integral value used to initialize bits [127:64] of the result.
+/// \param __c
+/// A 64-bit integral value used to initialize bits [191:128] of the result.
+/// \param __d
+/// A 64-bit integral value used to initialize bits [255:192] of the result.
+/// \returns An initialized 256-bit integer vector.
static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_setr_epi64x(long long __a, long long __b, long long __c, long long __d)
{
@@ -2642,24 +4002,74 @@ _mm256_setr_epi64x(long long __a, long long __b, long long __c, long long __d)
}
/* Create vectors with repeated elements */
+/// \brief 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMOVDDUP+VINSERTF128 </c> instruction.
+///
+/// \param __w
+/// A double-precision floating-point value used to initialize each vector
+/// element of the result.
+/// \returns An initialized 256-bit floating-point vector of [4 x double].
static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_set1_pd(double __w)
{
return (__m256d){ __w, __w, __w, __w };
}
+/// \brief 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VPERMILPS+VINSERTF128 </c>
+/// instruction.
+///
+/// \param __w
+/// A single-precision floating-point value used to initialize each vector
+/// element of the result.
+/// \returns An initialized 256-bit floating-point vector of [8 x float].
static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_set1_ps(float __w)
{
return (__m256){ __w, __w, __w, __w, __w, __w, __w, __w };
}
+/// \brief 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VPERMILPS+VINSERTF128 </c>
+/// instruction.
+///
+/// \param __i
+/// A 32-bit integral value used to initialize each vector element of the
+/// result.
+/// \returns An initialized 256-bit integer vector of [8 x i32].
static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_set1_epi32(int __i)
{
return (__m256i)(__v8si){ __i, __i, __i, __i, __i, __i, __i, __i };
}
+/// \brief 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VPSHUFB+VINSERTF128 </c> instruction.
+///
+/// \param __w
+/// A 16-bit integral value used to initialize each vector element of the
+/// result.
+/// \returns An initialized 256-bit integer vector of [16 x i16].
static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_set1_epi16(short __w)
{
@@ -2667,6 +4077,17 @@ _mm256_set1_epi16(short __w)
__w, __w, __w, __w, __w, __w };
}
+/// \brief 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>
+///
+/// This intrinsic corresponds to the <c> VPSHUFB+VINSERTF128 </c> instruction.
+///
+/// \param __b
+/// An 8-bit integral value used to initialize each vector element of the
+/// result.
+/// \returns An initialized 256-bit integer vector of [32 x i8].
static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_set1_epi8(char __b)
{
@@ -2675,6 +4096,18 @@ _mm256_set1_epi8(char __b)
__b, __b, __b, __b, __b, __b, __b };
}
+/// \brief 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMOVDDUP+VINSERTF128 </c> instruction.
+///
+/// \param __q
+/// A 64-bit integral value used to initialize each vector element of the
+/// result.
+/// \returns An initialized 256-bit integer vector of [4 x i64].
static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_set1_epi64x(long long __q)
{
@@ -2682,18 +4115,41 @@ _mm256_set1_epi64x(long long __q)
}
/* Create __zeroed vectors */
+/// \brief Constructs a 256-bit floating-point vector of [4 x double] with all
+/// vector elements initialized to zero.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VXORPS </c> instruction.
+///
+/// \returns A 256-bit vector of [4 x double] with all elements set to zero.
static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_setzero_pd(void)
{
return (__m256d){ 0, 0, 0, 0 };
}
+/// \brief Constructs a 256-bit floating-point vector of [8 x float] with all
+/// vector elements initialized to zero.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VXORPS </c> instruction.
+///
+/// \returns A 256-bit vector of [8 x float] with all elements set to zero.
static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_setzero_ps(void)
{
return (__m256){ 0, 0, 0, 0, 0, 0, 0, 0 };
}
+/// \brief Constructs a 256-bit integer vector initialized to zero.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VXORPS </c> instruction.
+///
+/// \returns A 256-bit integer vector initialized to zero.
static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_setzero_si256(void)
{
@@ -2701,72 +4157,210 @@ _mm256_setzero_si256(void)
}
/* Cast between vector types */
+/// \brief 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>
+///
+/// This intrinsic has no corresponding instruction.
+///
+/// \param __a
+/// A 256-bit floating-point vector of [4 x double].
+/// \returns A 256-bit floating-point vector of [8 x float] containing the same
+/// bitwise pattern as the parameter.
static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_castpd_ps(__m256d __a)
{
return (__m256)__a;
}
+/// \brief Casts a 256-bit floating-point vector of [4 x double] into a 256-bit
+/// integer vector.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic has no corresponding instruction.
+///
+/// \param __a
+/// A 256-bit floating-point vector of [4 x double].
+/// \returns A 256-bit integer vector containing the same bitwise pattern as the
+/// parameter.
static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_castpd_si256(__m256d __a)
{
return (__m256i)__a;
}
+/// \brief 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>
+///
+/// This intrinsic has no corresponding instruction.
+///
+/// \param __a
+/// A 256-bit floating-point vector of [8 x float].
+/// \returns A 256-bit floating-point vector of [4 x double] containing the same
+/// bitwise pattern as the parameter.
static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_castps_pd(__m256 __a)
{
return (__m256d)__a;
}
+/// \brief Casts a 256-bit floating-point vector of [8 x float] into a 256-bit
+/// integer vector.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic has no corresponding instruction.
+///
+/// \param __a
+/// A 256-bit floating-point vector of [8 x float].
+/// \returns A 256-bit integer vector containing the same bitwise pattern as the
+/// parameter.
static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_castps_si256(__m256 __a)
{
return (__m256i)__a;
}
+/// \brief Casts a 256-bit integer vector into a 256-bit floating-point vector
+/// of [8 x float].
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic has no corresponding instruction.
+///
+/// \param __a
+/// A 256-bit integer vector.
+/// \returns A 256-bit floating-point vector of [8 x float] containing the same
+/// bitwise pattern as the parameter.
static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_castsi256_ps(__m256i __a)
{
return (__m256)__a;
}
+/// \brief Casts a 256-bit integer vector into a 256-bit floating-point vector
+/// of [4 x double].
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic has no corresponding instruction.
+///
+/// \param __a
+/// A 256-bit integer vector.
+/// \returns A 256-bit floating-point vector of [4 x double] containing the same
+/// bitwise pattern as the parameter.
static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_castsi256_pd(__m256i __a)
{
return (__m256d)__a;
}
+/// \brief 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>
+///
+/// This intrinsic has no corresponding instruction.
+///
+/// \param __a
+/// A 256-bit floating-point vector of [4 x double].
+/// \returns A 128-bit floating-point vector of [2 x double] containing the
+/// lower 128 bits of the parameter.
static __inline __m128d __DEFAULT_FN_ATTRS
_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
+/// [8 x float] as a 128-bit floating-point vector of [4 x float].
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic has no corresponding instruction.
+///
+/// \param __a
+/// A 256-bit floating-point vector of [8 x float].
+/// \returns A 128-bit floating-point vector of [4 x float] containing the
+/// lower 128 bits of the parameter.
static __inline __m128 __DEFAULT_FN_ATTRS
_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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic has no corresponding instruction.
+///
+/// \param __a
+/// A 256-bit integer vector.
+/// \returns A 128-bit integer vector containing the lower 128 bits of the
+/// parameter.
static __inline __m128i __DEFAULT_FN_ATTRS
_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
+/// 128-bit floating-point vector of [2 x double]. The lower 128 bits
+/// contain the value of the source vector. The contents of the upper 128
+/// bits are undefined.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic has no corresponding instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double].
+/// \returns A 256-bit floating-point vector of [4 x double]. The lower 128 bits
+/// contain the value of the parameter. The contents of the upper 128 bits
+/// are undefined.
static __inline __m256d __DEFAULT_FN_ATTRS
_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
+/// 128-bit floating-point vector of [4 x float]. The lower 128 bits contain
+/// the value of the source vector. The contents of the upper 128 bits are
+/// undefined.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic has no corresponding instruction.
+///
+/// \param __a
+/// A 128-bit vector of [4 x float].
+/// \returns A 256-bit floating-point vector of [8 x float]. The lower 128 bits
+/// contain the value of the parameter. The contents of the upper 128 bits
+/// are undefined.
static __inline __m256 __DEFAULT_FN_ATTRS
_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.
+/// The lower 128 bits contain the value of the source vector. The contents
+/// of the upper 128 bits are undefined.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic has no corresponding instruction.
+///
+/// \param __a
+/// A 128-bit integer vector.
+/// \returns A 256-bit integer vector. The lower 128 bits contain the value of
+/// the parameter. The contents of the upper 128 bits are undefined.
static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_castsi128_si256(__m128i __a)
{
@@ -2778,6 +4372,38 @@ _mm256_castsi128_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
+/// 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. The immediate
+/// integer parameter determines between the upper or the lower 128 bits.
+///
+/// \headerfile <x86intrin.h>
+///
+/// \code
+/// __m256 _mm256_insertf128_ps(__m256 V1, __m128 V2, const int M);
+/// \endcode
+///
+/// This intrinsic corresponds to the <c> VINSERTF128 </c> instruction.
+///
+/// \param V1
+/// A 256-bit vector of [8 x float]. This vector is copied to the result
+/// first, and then either the upper or the lower 128 bits of the result will
+/// be replaced by the contents of \a V2.
+/// \param V2
+/// A 128-bit vector of [4 x float]. The contents of this parameter are
+/// written to either the upper or the lower 128 bits of the result depending
+/// on the value of parameter \a M.
+/// \param M
+/// An immediate integer. The least significant bit determines how the values
+/// from the two parameters are interleaved: \n
+/// If bit [0] of \a M is 0, \a V2 are copied to bits [127:0] of the result,
+/// and bits [255:128] of \a V1 are copied to bits [255:128] of the
+/// result. \n
+/// If bit [0] of \a M is 1, \a V2 are copied to bits [255:128] of the
+/// 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), \
@@ -2791,6 +4417,38 @@ _mm256_castsi128_si256(__m128i __a)
(((M) & 1) ? 10 : 6), \
(((M) & 1) ? 11 : 7) );})
+/// \brief 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. The immediate
+/// integer parameter determines between the upper or the lower 128 bits.
+///
+/// \headerfile <x86intrin.h>
+///
+/// \code
+/// __m256d _mm256_insertf128_pd(__m256d V1, __m128d V2, const int M);
+/// \endcode
+///
+/// This intrinsic corresponds to the <c> VINSERTF128 </c> instruction.
+///
+/// \param V1
+/// A 256-bit vector of [4 x double]. This vector is copied to the result
+/// first, and then either the upper or the lower 128 bits of the result will
+/// be replaced by the contents of \a V2.
+/// \param V2
+/// A 128-bit vector of [2 x double]. The contents of this parameter are
+/// written to either the upper or the lower 128 bits of the result depending
+/// on the value of parameter \a M.
+/// \param M
+/// An immediate integer. The least significant bit determines how the values
+/// from the two parameters are interleaved: \n
+/// If bit [0] of \a M is 0, \a V2 are copied to bits [127:0] of the result,
+/// and bits [255:128] of \a V1 are copied to bits [255:128] of the
+/// result. \n
+/// If bit [0] of \a M is 1, \a V2 are copied to bits [255:128] of the
+/// 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), \
@@ -2800,6 +4458,38 @@ _mm256_castsi128_si256(__m128i __a)
(((M) & 1) ? 4 : 2), \
(((M) & 1) ? 5 : 3) );})
+/// \brief 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. The immediate integer parameter
+/// determines between the upper or the lower 128 bits.
+///
+/// \headerfile <x86intrin.h>
+///
+/// \code
+/// __m256i _mm256_insertf128_si256(__m256i V1, __m128i V2, const int M);
+/// \endcode
+///
+/// This intrinsic corresponds to the <c> VINSERTF128 </c> instruction.
+///
+/// \param V1
+/// A 256-bit integer vector. This vector is copied to the result first, and
+/// then either the upper or the lower 128 bits of the result will be
+/// replaced by the contents of \a V2.
+/// \param V2
+/// A 128-bit integer vector. The contents of this parameter are written to
+/// either the upper or the lower 128 bits of the result depending on the
+/// value of parameter \a M.
+/// \param M
+/// An immediate integer. The least significant bit determines how the values
+/// from the two parameters are interleaved: \n
+/// If bit [0] of \a M is 0, \a V2 are copied to bits [127:0] of the result,
+/// and bits [255:128] of \a V1 are copied to bits [255:128] of the
+/// result. \n
+/// If bit [0] of \a M is 1, \a V2 are copied to bits [255:128] of the
+/// 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), \
@@ -2814,6 +4504,27 @@ _mm256_castsi128_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 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].
+///
+/// \headerfile <x86intrin.h>
+///
+/// \code
+/// __m128 _mm256_extractf128_ps(__m256 V, const int M);
+/// \endcode
+///
+/// This intrinsic corresponds to the <c> VEXTRACTF128 </c> instruction.
+///
+/// \param V
+/// A 256-bit vector of [8 x float].
+/// \param M
+/// An immediate integer. The least significant bit determines which bits are
+/// extracted from the first parameter: \n
+/// If bit [0] of \a M is 0, bits [127:0] of \a V are copied to the
+/// 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), \
@@ -2823,6 +4534,27 @@ _mm256_castsi128_si256(__m128i __a)
(((M) & 1) ? 6 : 2), \
(((M) & 1) ? 7 : 3) );})
+/// \brief 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].
+///
+/// \headerfile <x86intrin.h>
+///
+/// \code
+/// __m128d _mm256_extractf128_pd(__m256d V, const int M);
+/// \endcode
+///
+/// This intrinsic corresponds to the <c> VEXTRACTF128 </c> instruction.
+///
+/// \param V
+/// A 256-bit vector of [4 x double].
+/// \param M
+/// An immediate integer. The least significant bit determines which bits are
+/// extracted from the first parameter: \n
+/// If bit [0] of \a M is 0, bits [127:0] of \a V are copied to the
+/// 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), \
@@ -2830,6 +4562,27 @@ _mm256_castsi128_si256(__m128i __a)
(((M) & 1) ? 2 : 0), \
(((M) & 1) ? 3 : 1) );})
+/// \brief 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// \code
+/// __m128i _mm256_extractf128_si256(__m256i V, const int M);
+/// \endcode
+///
+/// This intrinsic corresponds to the <c> VEXTRACTF128 </c> instruction.
+///
+/// \param V
+/// A 256-bit integer vector.
+/// \param M
+/// An immediate integer. The least significant bit determines which bits are
+/// extracted from the first parameter: \n
+/// If bit [0] of \a M is 0, bits [127:0] of \a V are copied to the
+/// 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), \
@@ -2838,6 +4591,27 @@ _mm256_castsi128_si256(__m128i __a)
(((M) & 1) ? 3 : 1) );})
/* SIMD load ops (unaligned) */
+/// \brief 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to load instructions followed by the
+/// <c> VINSERTF128 </c> instruction.
+///
+/// \param __addr_hi
+/// A pointer to a 128-bit memory location containing 4 consecutive
+/// single-precision floating-point values. These values are to be copied to
+/// bits[255:128] of the result. The address of the memory location does not
+/// have to be aligned.
+/// \param __addr_lo
+/// A pointer to a 128-bit memory location containing 4 consecutive
+/// single-precision floating-point values. These values are to be copied to
+/// bits[127:0] of the result. The address of the memory location does not
+/// have to be aligned.
+/// \returns A 256-bit floating-point vector of [8 x float] containing the
+/// concatenated result.
static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_loadu2_m128(float const *__addr_hi, float const *__addr_lo)
{
@@ -2845,6 +4619,27 @@ _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
+/// unaligned memory locations and constructs a 256-bit floating-point vector
+/// of [4 x double] by concatenating the two 128-bit vectors.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to load instructions followed by the
+/// <c> VINSERTF128 </c> instruction.
+///
+/// \param __addr_hi
+/// A pointer to a 128-bit memory location containing two consecutive
+/// double-precision floating-point values. These values are to be copied to
+/// bits[255:128] of the result. The address of the memory location does not
+/// have to be aligned.
+/// \param __addr_lo
+/// A pointer to a 128-bit memory location containing two consecutive
+/// double-precision floating-point values. These values are to be copied to
+/// bits[127:0] of the result. The address of the memory location does not
+/// have to be aligned.
+/// \returns A 256-bit floating-point vector of [4 x double] containing the
+/// concatenated result.
static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_loadu2_m128d(double const *__addr_hi, double const *__addr_lo)
{
@@ -2852,6 +4647,24 @@ _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
+/// constructs a 256-bit integer vector by concatenating the two 128-bit
+/// vectors.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to load instructions followed by the
+/// <c> VINSERTF128 </c> instruction.
+///
+/// \param __addr_hi
+/// A pointer to a 128-bit memory location containing a 128-bit integer
+/// vector. This vector is to be copied to bits[255:128] of the result. The
+/// address of the memory location does not have to be aligned.
+/// \param __addr_lo
+/// A pointer to a 128-bit memory location containing a 128-bit integer
+/// vector. This vector is to be copied to bits[127:0] of the result. The
+/// address of the memory location does not have to be aligned.
+/// \returns A 256-bit integer vector containing the concatenated result.
static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_loadu2_m128i(__m128i const *__addr_hi, __m128i const *__addr_lo)
{
@@ -2860,6 +4673,24 @@ _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
+/// vector of [8 x float] into two different unaligned memory locations.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VEXTRACTF128 </c> instruction and the
+/// store instructions.
+///
+/// \param __addr_hi
+/// A pointer to a 128-bit memory location. Bits[255:128] of \a __a are to be
+/// copied to this memory location. The address of this memory location does
+/// not have to be aligned.
+/// \param __addr_lo
+/// A pointer to a 128-bit memory location. Bits[127:0] of \a __a are to be
+/// copied to this memory location. The address of this memory location does
+/// not have to be aligned.
+/// \param __a
+/// A 256-bit floating-point vector of [8 x float].
static __inline void __DEFAULT_FN_ATTRS
_mm256_storeu2_m128(float *__addr_hi, float *__addr_lo, __m256 __a)
{
@@ -2871,6 +4702,24 @@ _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
+/// vector of [4 x double] into two different unaligned memory locations.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VEXTRACTF128 </c> instruction and the
+/// store instructions.
+///
+/// \param __addr_hi
+/// A pointer to a 128-bit memory location. Bits[255:128] of \a __a are to be
+/// copied to this memory location. The address of this memory location does
+/// not have to be aligned.
+/// \param __addr_lo
+/// A pointer to a 128-bit memory location. Bits[127:0] of \a __a are to be
+/// copied to this memory location. The address of this memory location does
+/// not have to be aligned.
+/// \param __a
+/// A 256-bit floating-point vector of [4 x double].
static __inline void __DEFAULT_FN_ATTRS
_mm256_storeu2_m128d(double *__addr_hi, double *__addr_lo, __m256d __a)
{
@@ -2882,6 +4731,24 @@ _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
+/// two different unaligned memory locations.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VEXTRACTF128 </c> instruction and the
+/// store instructions.
+///
+/// \param __addr_hi
+/// A pointer to a 128-bit memory location. Bits[255:128] of \a __a are to be
+/// copied to this memory location. The address of this memory location does
+/// not have to be aligned.
+/// \param __addr_lo
+/// A pointer to a 128-bit memory location. Bits[127:0] of \a __a are to be
+/// copied to this memory location. The address of this memory location does
+/// not have to be aligned.
+/// \param __a
+/// A 256-bit integer vector.
static __inline void __DEFAULT_FN_ATTRS
_mm256_storeu2_m128i(__m128i *__addr_hi, __m128i *__addr_lo, __m256i __a)
{
@@ -2893,33 +4760,132 @@ _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
+/// concatenating two 128-bit floating-point vectors of [4 x float].
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VINSERTF128 </c> instruction.
+///
+/// \param __hi
+/// A 128-bit floating-point vector of [4 x float] to be copied to the upper
+/// 128 bits of the result.
+/// \param __lo
+/// A 128-bit floating-point vector of [4 x float] to be copied to the lower
+/// 128 bits of the result.
+/// \returns A 256-bit floating-point vector of [8 x float] containing the
+/// concatenated result.
static __inline __m256 __DEFAULT_FN_ATTRS
-_mm256_set_m128 (__m128 __hi, __m128 __lo) {
+_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
+/// concatenating two 128-bit floating-point vectors of [2 x double].
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VINSERTF128 </c> instruction.
+///
+/// \param __hi
+/// A 128-bit floating-point vector of [2 x double] to be copied to the upper
+/// 128 bits of the result.
+/// \param __lo
+/// A 128-bit floating-point vector of [2 x double] to be copied to the lower
+/// 128 bits of the result.
+/// \returns A 256-bit floating-point vector of [4 x double] containing the
+/// concatenated result.
static __inline __m256d __DEFAULT_FN_ATTRS
-_mm256_set_m128d (__m128d __hi, __m128d __lo) {
+_mm256_set_m128d (__m128d __hi, __m128d __lo)
+{
return (__m256d)_mm256_set_m128((__m128)__hi, (__m128)__lo);
}
+/// \brief Constructs a 256-bit integer vector by concatenating two 128-bit
+/// integer vectors.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VINSERTF128 </c> instruction.
+///
+/// \param __hi
+/// A 128-bit integer vector to be copied to the upper 128 bits of the
+/// result.
+/// \param __lo
+/// A 128-bit integer vector to be copied to the lower 128 bits of the
+/// result.
+/// \returns A 256-bit integer vector containing the concatenated result.
static __inline __m256i __DEFAULT_FN_ATTRS
-_mm256_set_m128i (__m128i __hi, __m128i __lo) {
+_mm256_set_m128i (__m128i __hi, __m128i __lo)
+{
return (__m256i)_mm256_set_m128((__m128)__hi, (__m128)__lo);
}
+/// \brief 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VINSERTF128 </c> instruction.
+///
+/// \param __lo
+/// A 128-bit floating-point vector of [4 x float] to be copied to the lower
+/// 128 bits of the result.
+/// \param __hi
+/// A 128-bit floating-point vector of [4 x float] to be copied to the upper
+/// 128 bits of the result.
+/// \returns A 256-bit floating-point vector of [8 x float] containing the
+/// concatenated result.
static __inline __m256 __DEFAULT_FN_ATTRS
-_mm256_setr_m128 (__m128 __lo, __m128 __hi) {
+_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
+/// 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VINSERTF128 </c> instruction.
+///
+/// \param __lo
+/// A 128-bit floating-point vector of [2 x double] to be copied to the lower
+/// 128 bits of the result.
+/// \param __hi
+/// A 128-bit floating-point vector of [2 x double] to be copied to the upper
+/// 128 bits of the result.
+/// \returns A 256-bit floating-point vector of [4 x double] containing the
+/// concatenated result.
static __inline __m256d __DEFAULT_FN_ATTRS
-_mm256_setr_m128d (__m128d __lo, __m128d __hi) {
+_mm256_setr_m128d (__m128d __lo, __m128d __hi)
+{
return (__m256d)_mm256_set_m128((__m128)__hi, (__m128)__lo);
}
+/// \brief 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VINSERTF128 </c> instruction.
+///
+/// \param __lo
+/// A 128-bit integer vector to be copied to the lower 128 bits of the
+/// result.
+/// \param __hi
+/// A 128-bit integer vector to be copied to the upper 128 bits of the
+/// result.
+/// \returns A 256-bit integer vector containing the concatenated result.
static __inline __m256i __DEFAULT_FN_ATTRS
-_mm256_setr_m128i (__m128i __lo, __m128i __hi) {
+_mm256_setr_m128i (__m128i __lo, __m128i __hi)
+{
return (__m256i)_mm256_set_m128((__m128)__hi, (__m128)__lo);
}
diff --git a/lib/Headers/bmiintrin.h b/lib/Headers/bmiintrin.h
index 30acfaeb9f3b..488eb2dbd3d4 100644
--- a/lib/Headers/bmiintrin.h
+++ b/lib/Headers/bmiintrin.h
@@ -36,7 +36,7 @@
/// unsigned short _tzcnt_u16(unsigned short a);
/// \endcode
///
-/// This intrinsic corresponds to the \c TZCNT instruction.
+/// This intrinsic corresponds to the <c> TZCNT </c> instruction.
///
/// \param a
/// An unsigned 16-bit integer whose trailing zeros are to be counted.
@@ -53,7 +53,7 @@
/// unsigned int _andn_u32(unsigned int a, unsigned int b);
/// \endcode
///
-/// This intrinsic corresponds to the \c ANDN instruction.
+/// This intrinsic corresponds to the <c> ANDN </c> instruction.
///
/// \param a
/// An unsigned integer containing one of the operands.
@@ -73,7 +73,7 @@
/// unsigned int _blsi_u32(unsigned int a);
/// \endcode
///
-/// This intrinsic corresponds to the \c BLSI instruction.
+/// This intrinsic corresponds to the <c> BLSI </c> instruction.
///
/// \param a
/// An unsigned integer whose bits are to be cleared.
@@ -91,7 +91,7 @@
/// unsigned int _blsmsk_u32(unsigned int a);
/// \endcode
///
-/// This intrinsic corresponds to the \c BLSMSK instruction.
+/// This intrinsic corresponds to the <c> BLSMSK </c> instruction.
///
/// \param a
/// An unsigned integer used to create the mask.
@@ -107,7 +107,7 @@
/// unsigned int _blsr_u32(unsigned int a);
/// \endcode
///
-/// This intrinsic corresponds to the \c BLSR instruction.
+/// This intrinsic corresponds to the <c> BLSR </c> instruction.
///
/// \param a
/// An unsigned integer containing the operand to be cleared.
@@ -123,7 +123,7 @@
/// unsigned int _tzcnt_u32(unsigned int a);
/// \endcode
///
-/// This intrinsic corresponds to the \c TZCNT instruction.
+/// This intrinsic corresponds to the <c> TZCNT </c> instruction.
///
/// \param a
/// An unsigned 32-bit integer whose trailing zeros are to be counted.
@@ -143,7 +143,7 @@
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c TZCNT instruction.
+/// This intrinsic corresponds to the <c> TZCNT </c> instruction.
///
/// \param __X
/// An unsigned 16-bit integer whose trailing zeros are to be counted.
@@ -160,7 +160,7 @@ __tzcnt_u16(unsigned short __X)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c ANDN instruction.
+/// This intrinsic corresponds to the <c> ANDN </c> instruction.
///
/// \param __X
/// An unsigned integer containing one of the operands.
@@ -180,7 +180,7 @@ __andn_u32(unsigned int __X, unsigned int __Y)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c BEXTR instruction.
+/// This intrinsic corresponds to the <c> BEXTR </c> instruction.
///
/// \param __X
/// An unsigned integer whose bits are to be extracted.
@@ -202,7 +202,7 @@ __bextr_u32(unsigned int __X, unsigned int __Y)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c BEXTR instruction.
+/// This intrinsic corresponds to the <c> BEXTR </c> instruction.
///
/// \param __X
/// An unsigned integer whose bits are to be extracted.
@@ -225,7 +225,7 @@ _bextr_u32(unsigned int __X, unsigned int __Y, unsigned int __Z)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c BLSI instruction.
+/// This intrinsic corresponds to the <c> BLSI </c> instruction.
///
/// \param __X
/// An unsigned integer whose bits are to be cleared.
@@ -243,7 +243,7 @@ __blsi_u32(unsigned int __X)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c BLSMSK instruction.
+/// This intrinsic corresponds to the <c> BLSMSK </c> instruction.
///
/// \param __X
/// An unsigned integer used to create the mask.
@@ -259,7 +259,7 @@ __blsmsk_u32(unsigned int __X)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c BLSR instruction.
+/// This intrinsic corresponds to the <c> BLSR </c> instruction.
///
/// \param __X
/// An unsigned integer containing the operand to be cleared.
@@ -275,7 +275,7 @@ __blsr_u32(unsigned int __X)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c TZCNT instruction.
+/// This intrinsic corresponds to the <c> TZCNT </c> instruction.
///
/// \param __X
/// An unsigned 32-bit integer whose trailing zeros are to be counted.
@@ -291,12 +291,12 @@ __tzcnt_u32(unsigned int __X)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c TZCNT instruction.
+/// This intrinsic corresponds to the <c> TZCNT </c> instruction.
///
/// \param __X
/// An unsigned 32-bit integer whose trailing zeros are to be counted.
-/// \returns An 32-bit integer containing the number of trailing zero
-/// bits in the operand.
+/// \returns An 32-bit integer containing the number of trailing zero bits in
+/// the operand.
static __inline__ int __RELAXED_FN_ATTRS
_mm_tzcnt_32(unsigned int __X)
{
@@ -314,7 +314,7 @@ _mm_tzcnt_32(unsigned int __X)
/// unsigned long long _andn_u64 (unsigned long long a, unsigned long long b);
/// \endcode
///
-/// This intrinsic corresponds to the \c ANDN instruction.
+/// This intrinsic corresponds to the <c> ANDN </c> instruction.
///
/// \param a
/// An unsigned 64-bit integer containing one of the operands.
@@ -334,7 +334,7 @@ _mm_tzcnt_32(unsigned int __X)
/// unsigned long long _blsi_u64(unsigned long long a);
/// \endcode
///
-/// This intrinsic corresponds to the \c BLSI instruction.
+/// This intrinsic corresponds to the <c> BLSI </c> instruction.
///
/// \param a
/// An unsigned 64-bit integer whose bits are to be cleared.
@@ -352,7 +352,7 @@ _mm_tzcnt_32(unsigned int __X)
/// unsigned long long _blsmsk_u64(unsigned long long a);
/// \endcode
///
-/// This intrinsic corresponds to the \c BLSMSK instruction.
+/// This intrinsic corresponds to the <c> BLSMSK </c> instruction.
///
/// \param a
/// An unsigned 64-bit integer used to create the mask.
@@ -368,7 +368,7 @@ _mm_tzcnt_32(unsigned int __X)
/// unsigned long long _blsr_u64(unsigned long long a);
/// \endcode
///
-/// This intrinsic corresponds to the \c BLSR instruction.
+/// This intrinsic corresponds to the <c> BLSR </c> instruction.
///
/// \param a
/// An unsigned 64-bit integer containing the operand to be cleared.
@@ -384,7 +384,7 @@ _mm_tzcnt_32(unsigned int __X)
/// unsigned long long _tzcnt_u64(unsigned long long a);
/// \endcode
///
-/// This intrinsic corresponds to the \c TZCNT instruction.
+/// This intrinsic corresponds to the <c> TZCNT </c> instruction.
///
/// \param a
/// An unsigned 64-bit integer whose trailing zeros are to be counted.
@@ -397,7 +397,7 @@ _mm_tzcnt_32(unsigned int __X)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c ANDN instruction.
+/// This intrinsic corresponds to the <c> ANDN </c> instruction.
///
/// \param __X
/// An unsigned 64-bit integer containing one of the operands.
@@ -417,7 +417,7 @@ __andn_u64 (unsigned long long __X, unsigned long long __Y)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c BEXTR instruction.
+/// This intrinsic corresponds to the <c> BEXTR </c> instruction.
///
/// \param __X
/// An unsigned 64-bit integer whose bits are to be extracted.
@@ -439,7 +439,7 @@ __bextr_u64(unsigned long long __X, unsigned long long __Y)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c BEXTR instruction.
+/// This intrinsic corresponds to the <c> BEXTR </c> instruction.
///
/// \param __X
/// An unsigned 64-bit integer whose bits are to be extracted.
@@ -462,7 +462,7 @@ _bextr_u64(unsigned long long __X, unsigned int __Y, unsigned int __Z)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c BLSI instruction.
+/// This intrinsic corresponds to the <c> BLSI </c> instruction.
///
/// \param __X
/// An unsigned 64-bit integer whose bits are to be cleared.
@@ -480,7 +480,7 @@ __blsi_u64(unsigned long long __X)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c BLSMSK instruction.
+/// This intrinsic corresponds to the <c> BLSMSK </c> instruction.
///
/// \param __X
/// An unsigned 64-bit integer used to create the mask.
@@ -496,7 +496,7 @@ __blsmsk_u64(unsigned long long __X)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c BLSR instruction.
+/// This intrinsic corresponds to the <c> BLSR </c> instruction.
///
/// \param __X
/// An unsigned 64-bit integer containing the operand to be cleared.
@@ -512,7 +512,7 @@ __blsr_u64(unsigned long long __X)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c TZCNT instruction.
+/// This intrinsic corresponds to the <c> TZCNT </c> instruction.
///
/// \param __X
/// An unsigned 64-bit integer whose trailing zeros are to be counted.
@@ -528,12 +528,12 @@ __tzcnt_u64(unsigned long long __X)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c TZCNT instruction.
+/// This intrinsic corresponds to the <c> TZCNT </c> instruction.
///
/// \param __X
/// An unsigned 64-bit integer whose trailing zeros are to be counted.
-/// \returns An 64-bit integer containing the number of trailing zero
-/// bits in the operand.
+/// \returns An 64-bit integer containing the number of trailing zero bits in
+/// the operand.
static __inline__ long long __RELAXED_FN_ATTRS
_mm_tzcnt_64(unsigned long long __X)
{
diff --git a/lib/Headers/cuda_wrappers/algorithm b/lib/Headers/cuda_wrappers/algorithm
new file mode 100644
index 000000000000..95d9beb73c68
--- /dev/null
+++ b/lib/Headers/cuda_wrappers/algorithm
@@ -0,0 +1,96 @@
+/*===---- complex - CUDA wrapper for <algorithm> ----------------------------===
+ *
+ * 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_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__.
+//
+// We don't support the initializer_list overloads because
+// initializer_list::begin() and end() are not __host__ __device__ functions.
+//
+// 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>.
+
+#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
+// <complex>). Thus the ugliness below.
+#ifdef _LIBCPP_BEGIN_NAMESPACE_STD
+_LIBCPP_BEGIN_NAMESPACE_STD
+#else
+namespace std {
+#ifdef _GLIBCXX_BEGIN_NAMESPACE_VERSION
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+#endif
+#endif
+
+template <class __T, class __Cmp>
+inline __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 &
+max(const __T &__a, const __T &__b) {
+ return __a < __b ? __b : __a;
+}
+
+template <class __T, class __Cmp>
+inline __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 &
+min(const __T &__a, const __T &__b) {
+ return __a < __b ? __b : __a;
+}
+
+#ifdef _LIBCPP_END_NAMESPACE_STD
+_LIBCPP_END_NAMESPACE_STD
+#else
+#ifdef _GLIBCXX_BEGIN_NAMESPACE_VERSION
+_GLIBCXX_END_NAMESPACE_VERSION
+#endif
+} // namespace std
+#endif
+
+#endif // __cplusplus <= 201103L
+#endif // __CLANG_CUDA_WRAPPERS_ALGORITHM
diff --git a/lib/Headers/cuda_wrappers/complex b/lib/Headers/cuda_wrappers/complex
new file mode 100644
index 000000000000..11d40a82a8f6
--- /dev/null
+++ b/lib/Headers/cuda_wrappers/complex
@@ -0,0 +1,82 @@
+/*===---- complex - CUDA wrapper for <complex> ------------------------------===
+ *
+ * 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_WRAPPERS_COMPLEX
+#define __CLANG_CUDA_WRAPPERS_COMPLEX
+
+// Wrapper around <complex> that forces its functions to be __host__
+// __device__.
+
+// First, include host-only headers we think are likely to be included by
+// <complex>, so that the pragma below only applies to <complex> itself.
+#if __cplusplus >= 201103L
+#include <type_traits>
+#endif
+#include <stdexcept>
+#include <cmath>
+#include <sstream>
+
+// Next, include our <algorithm> wrapper, to ensure that device overloads of
+// std::min/max are available.
+#include <algorithm>
+
+#pragma clang force_cuda_host_device begin
+
+// When compiling for device, ask libstdc++ to use its own implements of
+// complex functions, rather than calling builtins (which resolve to library
+// functions that don't exist when compiling CUDA device code).
+//
+// This is a little dicey, because it causes libstdc++ to define a different
+// set of overloads on host and device.
+//
+// // Present only when compiling for host.
+// __host__ __device__ void complex<float> sin(const complex<float>& x) {
+// return __builtin_csinf(x);
+// }
+//
+// // Present when compiling for host and for device.
+// template <typename T>
+// void __host__ __device__ complex<T> sin(const complex<T>& x) {
+// return complex<T>(sin(x.real()) * cosh(x.imag()),
+// cos(x.real()), sinh(x.imag()));
+// }
+//
+// This is safe because when compiling for device, all function calls in
+// __host__ code to sin() will still resolve to *something*, even if they don't
+// resolve to the same function as they resolve to when compiling for host. We
+// don't care that they don't resolve to the right function because we won't
+// codegen this host code when compiling for device.
+
+#pragma push_macro("_GLIBCXX_USE_C99_COMPLEX")
+#pragma push_macro("_GLIBCXX_USE_C99_COMPLEX_TR1")
+#define _GLIBCXX_USE_C99_COMPLEX 0
+#define _GLIBCXX_USE_C99_COMPLEX_TR1 0
+
+#include_next <complex>
+
+#pragma pop_macro("_GLIBCXX_USE_C99_COMPLEX_TR1")
+#pragma pop_macro("_GLIBCXX_USE_C99_COMPLEX")
+
+#pragma clang force_cuda_host_device end
+
+#endif // include guard
diff --git a/lib/Headers/cuda_wrappers/new b/lib/Headers/cuda_wrappers/new
new file mode 100644
index 000000000000..b77131af0e5b
--- /dev/null
+++ b/lib/Headers/cuda_wrappers/new
@@ -0,0 +1,47 @@
+/*===---- complex - CUDA wrapper for <new> ------------------------------===
+ *
+ * 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_WRAPPERS_NEW
+#define __CLANG_CUDA_WRAPPERS_NEW
+
+#include_next <new>
+
+// Device overrides for placement new and delete.
+#pragma push_macro("CUDA_NOEXCEPT")
+#if __cplusplus >= 201103L
+#define CUDA_NOEXCEPT noexcept
+#else
+#define CUDA_NOEXCEPT
+#endif
+
+__device__ inline void *operator new(__SIZE_TYPE__, void *__ptr) CUDA_NOEXCEPT {
+ return __ptr;
+}
+__device__ inline void *operator new[](__SIZE_TYPE__, void *__ptr) CUDA_NOEXCEPT {
+ return __ptr;
+}
+__device__ inline void operator delete(void *, void *) CUDA_NOEXCEPT {}
+__device__ inline void operator delete[](void *, void *) CUDA_NOEXCEPT {}
+#pragma pop_macro("CUDA_NOEXCEPT")
+
+#endif // include guard
diff --git a/lib/Headers/emmintrin.h b/lib/Headers/emmintrin.h
index 70d6d726110a..1512f9f0b47b 100644
--- a/lib/Headers/emmintrin.h
+++ b/lib/Headers/emmintrin.h
@@ -49,6 +49,21 @@ typedef signed char __v16qs __attribute__((__vector_size__(16)));
/* Define the default attributes for the functions in this file. */
#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("sse2")))
+/// \brief 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VADDSD / ADDSD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double] containing one of the source operands.
+/// \param __b
+/// A 128-bit vector of [2 x double] containing one of the source operands.
+/// \returns A 128-bit vector of [2 x double] whose lower 64 bits contain the
+/// sum of the lower 64 bits of both operands. The upper 64 bits are copied
+/// from the upper 64 bits of the first source operand.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_add_sd(__m128d __a, __m128d __b)
{
@@ -56,12 +71,41 @@ _mm_add_sd(__m128d __a, __m128d __b)
return __a;
}
+/// \brief Adds two 128-bit vectors of [2 x double].
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VADDPD / ADDPD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double] containing one of the source operands.
+/// \param __b
+/// A 128-bit vector of [2 x double] containing one of the source operands.
+/// \returns A 128-bit vector of [2 x double] containing the sums of both
+/// operands.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_add_pd(__m128d __a, __m128d __b)
{
return (__m128d)((__v2df)__a + (__v2df)__b);
}
+/// \brief 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
+/// operand.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VSUBSD / SUBSD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double] containing the minuend.
+/// \param __b
+/// A 128-bit vector of [2 x double] containing the subtrahend.
+/// \returns A 128-bit vector of [2 x double] whose lower 64 bits contain the
+/// difference of the lower 64 bits of both operands. The upper 64 bits are
+/// copied from the upper 64 bits of the first source operand.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_sub_sd(__m128d __a, __m128d __b)
{
@@ -69,12 +113,40 @@ _mm_sub_sd(__m128d __a, __m128d __b)
return __a;
}
+/// \brief Subtracts two 128-bit vectors of [2 x double].
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VSUBPD / SUBPD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double] containing the minuend.
+/// \param __b
+/// A 128-bit vector of [2 x double] containing the subtrahend.
+/// \returns A 128-bit vector of [2 x double] containing the differences between
+/// both operands.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_sub_pd(__m128d __a, __m128d __b)
{
return (__m128d)((__v2df)__a - (__v2df)__b);
}
+/// \brief 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMULSD / MULSD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double] containing one of the source operands.
+/// \param __b
+/// A 128-bit vector of [2 x double] containing one of the source operands.
+/// \returns A 128-bit vector of [2 x double] whose lower 64 bits contain the
+/// product of the lower 64 bits of both operands. The upper 64 bits are
+/// copied from the upper 64 bits of the first source operand.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_mul_sd(__m128d __a, __m128d __b)
{
@@ -82,12 +154,41 @@ _mm_mul_sd(__m128d __a, __m128d __b)
return __a;
}
+/// \brief Multiplies two 128-bit vectors of [2 x double].
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMULPD / MULPD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double] containing one of the operands.
+/// \param __b
+/// A 128-bit vector of [2 x double] containing one of the operands.
+/// \returns A 128-bit vector of [2 x double] containing the products of both
+/// operands.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_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
+/// 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
+/// operand.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VDIVSD / DIVSD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double] containing the dividend.
+/// \param __b
+/// A 128-bit vector of [2 x double] containing divisor.
+/// \returns A 128-bit vector of [2 x double] whose lower 64 bits contain the
+/// quotient of the lower 64 bits of both operands. The upper 64 bits are
+/// copied from the upper 64 bits of the first source operand.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_div_sd(__m128d __a, __m128d __b)
{
@@ -95,12 +196,44 @@ _mm_div_sd(__m128d __a, __m128d __b)
return __a;
}
+/// \brief Performs an element-by-element division of two 128-bit vectors of
+/// [2 x double].
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VDIVPD / DIVPD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double] containing the dividend.
+/// \param __b
+/// A 128-bit vector of [2 x double] containing the divisor.
+/// \returns A 128-bit vector of [2 x double] containing the quotients of both
+/// operands.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_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
+/// 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VSQRTSD / SQRTSD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double] containing one of the operands. The
+/// upper 64 bits of this operand are copied to the upper 64 bits of the
+/// result.
+/// \param __b
+/// A 128-bit vector of [2 x double] containing one of the operands. The
+/// square root is calculated using the lower 64 bits of this operand.
+/// \returns A 128-bit vector of [2 x double] whose lower 64 bits contain the
+/// square root of the lower 64 bits of operand \a __b, and whose upper 64
+/// bits are copied from the upper 64 bits of operand \a __a.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_sqrt_sd(__m128d __a, __m128d __b)
{
@@ -108,150 +241,518 @@ _mm_sqrt_sd(__m128d __a, __m128d __b)
return (__m128d) { __c[0], __a[1] };
}
+/// \brief Calculates the square root of the each of two values stored in a
+/// 128-bit vector of [2 x double].
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VSQRTPD / SQRTPD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double].
+/// \returns A 128-bit vector of [2 x double] containing the square roots of the
+/// values in the operand.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_sqrt_pd(__m128d __a)
{
return __builtin_ia32_sqrtpd((__v2df)__a);
}
+/// \brief 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMINSD / MINSD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double] containing one of the operands. The
+/// lower 64 bits of this operand are used in the comparison.
+/// \param __b
+/// A 128-bit vector of [2 x double] containing one of the operands. The
+/// lower 64 bits of this operand are used in the comparison.
+/// \returns A 128-bit vector of [2 x double] whose lower 64 bits contain the
+/// minimum value between both operands. The upper 64 bits are copied from
+/// the upper 64 bits of the first source operand.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_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
+/// [2 x double] and returns the vector containing the lesser of each pair of
+/// values.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMINPD / MINPD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double] containing one of the operands.
+/// \param __b
+/// A 128-bit vector of [2 x double] containing one of the operands.
+/// \returns A 128-bit vector of [2 x double] containing the minimum values
+/// between both operands.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_min_pd(__m128d __a, __m128d __b)
{
return __builtin_ia32_minpd((__v2df)__a, (__v2df)__b);
}
+/// \brief Compares lower 64-bits 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMAXSD / MAXSD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double] containing one of the operands. The
+/// lower 64 bits of this operand are used in the comparison.
+/// \param __b
+/// A 128-bit vector of [2 x double] containing one of the operands. The
+/// lower 64 bits of this operand are used in the comparison.
+/// \returns A 128-bit vector of [2 x double] whose lower 64 bits contain the
+/// maximum value between both operands. The upper 64 bits are copied from
+/// the upper 64 bits of the first source operand.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_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
+/// [2 x double] and returns the vector containing the greater of each pair
+/// of values.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMAXPD / MAXPD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double] containing one of the operands.
+/// \param __b
+/// A 128-bit vector of [2 x double] containing one of the operands.
+/// \returns A 128-bit vector of [2 x double] containing the maximum values
+/// between both operands.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_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].
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VPAND / PAND </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double] containing one of the source operands.
+/// \param __b
+/// A 128-bit vector of [2 x double] containing one of the source operands.
+/// \returns A 128-bit vector of [2 x double] containing the bitwise AND of the
+/// values between both operands.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_and_pd(__m128d __a, __m128d __b)
{
- return (__m128d)((__v4su)__a & (__v4su)__b);
+ return (__m128d)((__v2du)__a & (__v2du)__b);
}
+/// \brief 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>
+///
+/// This intrinsic corresponds to the <c> VPANDN / PANDN </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double] containing the left source operand. The
+/// one's complement of this value is used in the bitwise AND.
+/// \param __b
+/// A 128-bit vector of [2 x double] containing the right source operand.
+/// \returns A 128-bit vector of [2 x double] containing the bitwise AND of the
+/// values in the second operand and the one's complement of the first
+/// operand.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_andnot_pd(__m128d __a, __m128d __b)
{
- return (__m128d)(~(__v4su)__a & (__v4su)__b);
+ return (__m128d)(~(__v2du)__a & (__v2du)__b);
}
+/// \brief Performs a bitwise OR of two 128-bit vectors of [2 x double].
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VPOR / POR </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double] containing one of the source operands.
+/// \param __b
+/// A 128-bit vector of [2 x double] containing one of the source operands.
+/// \returns A 128-bit vector of [2 x double] containing the bitwise OR of the
+/// values between both operands.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_or_pd(__m128d __a, __m128d __b)
{
- return (__m128d)((__v4su)__a | (__v4su)__b);
+ return (__m128d)((__v2du)__a | (__v2du)__b);
}
+/// \brief Performs a bitwise XOR of two 128-bit vectors of [2 x double].
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VPXOR / PXOR </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double] containing one of the source operands.
+/// \param __b
+/// A 128-bit vector of [2 x double] containing one of the source operands.
+/// \returns A 128-bit vector of [2 x double] containing the bitwise XOR of the
+/// values between both operands.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_xor_pd(__m128d __a, __m128d __b)
{
- return (__m128d)((__v4su)__a ^ (__v4su)__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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VCMPEQPD / CMPEQPD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double].
+/// \param __b
+/// A 128-bit vector of [2 x double].
+/// \returns A 128-bit vector containing the comparison results.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_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
+/// 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VCMPLTPD / CMPLTPD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double].
+/// \param __b
+/// A 128-bit vector of [2 x double].
+/// \returns A 128-bit vector containing the comparison results.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_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
+/// 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VCMPLEPD / CMPLEPD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double].
+/// \param __b
+/// A 128-bit vector of [2 x double].
+/// \returns A 128-bit vector containing the comparison results.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_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
+/// 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VCMPLTPD / CMPLTPD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double].
+/// \param __b
+/// A 128-bit vector of [2 x double].
+/// \returns A 128-bit vector containing the comparison results.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_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
+/// 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VCMPLEPD / CMPLEPD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double].
+/// \param __b
+/// A 128-bit vector of [2 x double].
+/// \returns A 128-bit vector containing the comparison results.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_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
+/// 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VCMPORDPD / CMPORDPD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double].
+/// \param __b
+/// A 128-bit vector of [2 x double].
+/// \returns A 128-bit vector containing the comparison results.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_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
+/// 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VCMPUNORDPD / CMPUNORDPD </c>
+/// instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double].
+/// \param __b
+/// A 128-bit vector of [2 x double].
+/// \returns A 128-bit vector containing the comparison results.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_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
+/// 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VCMPNEQPD / CMPNEQPD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double].
+/// \param __b
+/// A 128-bit vector of [2 x double].
+/// \returns A 128-bit vector containing the comparison results.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_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
+/// 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VCMPNLTPD / CMPNLTPD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double].
+/// \param __b
+/// A 128-bit vector of [2 x double].
+/// \returns A 128-bit vector containing the comparison results.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_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
+/// 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VCMPNLEPD / CMPNLEPD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double].
+/// \param __b
+/// A 128-bit vector of [2 x double].
+/// \returns A 128-bit vector containing the comparison results.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_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
+/// 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VCMPNLTPD / CMPNLTPD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double].
+/// \param __b
+/// A 128-bit vector of [2 x double].
+/// \returns A 128-bit vector containing the comparison results.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_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
+/// 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VCMPNLEPD / CMPNLEPD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double].
+/// \param __b
+/// A 128-bit vector of [2 x double].
+/// \returns A 128-bit vector containing the comparison results.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_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
+/// the two 128-bit floating-point vectors of [2 x double] for equality. The
+/// comparison yields 0h for false, FFFFFFFFFFFFFFFFh for true.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VCMPEQSD / CMPEQSD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double]. The lower double-precision value is
+/// compared to the lower double-precision value of \a __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 A 128-bit vector. The lower 64 bits contains the comparison
+/// results. The upper 64 bits are copied from the upper 64 bits of \a __a.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_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
+/// 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VCMPLTSD / CMPLTSD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double]. The lower double-precision value is
+/// compared to the lower double-precision value of \a __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 A 128-bit vector. The lower 64 bits contains the comparison
+/// results. The upper 64 bits are copied from the upper 64 bits of \a __a.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_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
+/// 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VCMPLESD / CMPLESD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double]. The lower double-precision value is
+/// compared to the lower double-precision value of \a __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 A 128-bit vector. The lower 64 bits contains the comparison
+/// results. The upper 64 bits are copied from the upper 64 bits of \a __a.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_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
+/// 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VCMPLTSD / CMPLTSD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double]. The lower double-precision value is
+/// compared to the lower double-precision value of \a __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 A 128-bit vector. The lower 64 bits contains the comparison
+/// results. The upper 64 bits are copied from the upper 64 bits of \a __a.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_cmpgt_sd(__m128d __a, __m128d __b)
{
@@ -259,6 +760,24 @@ _mm_cmpgt_sd(__m128d __a, __m128d __b)
return (__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] 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VCMPLESD / CMPLESD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double]. The lower double-precision value is
+/// compared to the lower double-precision value of \a __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 A 128-bit vector. The lower 64 bits contains the comparison
+/// results. The upper 64 bits are copied from the upper 64 bits of \a __a.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_cmpge_sd(__m128d __a, __m128d __b)
{
@@ -266,36 +785,147 @@ _mm_cmpge_sd(__m128d __a, __m128d __b)
return (__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] 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 neither value is a NaN.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VCMPORDSD / CMPORDSD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double]. The lower double-precision value is
+/// compared to the lower double-precision value of \a __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 A 128-bit vector. The lower 64 bits contains the comparison
+/// results. The upper 64 bits are copied from the upper 64 bits of \a __a.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_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
+/// 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VCMPUNORDSD / CMPUNORDSD </c>
+/// instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double]. The lower double-precision value is
+/// compared to the lower double-precision value of \a __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 A 128-bit vector. The lower 64 bits contains the comparison
+/// results. The upper 64 bits are copied from the upper 64 bits of \a __a.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_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
+/// 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VCMPNEQSD / CMPNEQSD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double]. The lower double-precision value is
+/// compared to the lower double-precision value of \a __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 A 128-bit vector. The lower 64 bits contains the comparison
+/// results. The upper 64 bits are copied from the upper 64 bits of \a __a.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_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
+/// 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VCMPNLTSD / CMPNLTSD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double]. The lower double-precision value is
+/// compared to the lower double-precision value of \a __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 A 128-bit vector. The lower 64 bits contains the comparison
+/// results. The upper 64 bits are copied from the upper 64 bits of \a __a.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_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
+/// 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VCMPNLESD / CMPNLESD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double]. The lower double-precision value is
+/// compared to the lower double-precision value of \a __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 A 128-bit vector. The lower 64 bits contains the comparison
+/// results. The upper 64 bits are copied from the upper 64 bits of \a __a.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_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
+/// 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VCMPNLTSD / CMPNLTSD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double]. The lower double-precision value is
+/// compared to the lower double-precision value of \a __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 A 128-bit vector. The lower 64 bits contains the comparison
+/// results. The upper 64 bits are copied from the upper 64 bits of \a __a.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_cmpngt_sd(__m128d __a, __m128d __b)
{
@@ -303,6 +933,24 @@ _mm_cmpngt_sd(__m128d __a, __m128d __b)
return (__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] 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VCMPNLESD / CMPNLESD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double]. The lower double-precision value is
+/// compared to the lower double-precision value of \a __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 A 128-bit vector. The lower 64 bits contains the comparison
+/// results. The upper 64 bits are copied from the upper 64 bits of \a __a.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_cmpnge_sd(__m128d __a, __m128d __b)
{
@@ -310,84 +958,317 @@ _mm_cmpnge_sd(__m128d __a, __m128d __b)
return (__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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VCOMISD / COMISD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double]. The lower double-precision value is
+/// compared to the lower double-precision value of \a __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.
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
+/// 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VCOMISD / COMISD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double]. The lower double-precision value is
+/// compared to the lower double-precision value of \a __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.
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
+/// 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VCOMISD / COMISD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double]. The lower double-precision value is
+/// compared to the lower double-precision value of \a __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.
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
+/// 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VCOMISD / COMISD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double]. The lower double-precision value is
+/// compared to the lower double-precision value of \a __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.
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
+/// 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VCOMISD / COMISD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double]. The lower double-precision value is
+/// compared to the lower double-precision value of \a __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.
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
+/// 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VCOMISD / COMISD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double]. The lower double-precision value is
+/// compared to the lower double-precision value of \a __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.
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
+/// 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VUCOMISD / UCOMISD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double]. The lower double-precision value is
+/// compared to the lower double-precision value of \a __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. If either of the two
+/// lower double-precision values is NaN, 1 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
+/// 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VUCOMISD / UCOMISD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double]. The lower double-precision value is
+/// compared to the lower double-precision value of \a __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. If either of the two
+/// lower double-precision values is NaN, 1 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
+/// 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VUCOMISD / UCOMISD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double]. The lower double-precision value is
+/// compared to the lower double-precision value of \a __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. If either of the two
+/// lower double-precision values is NaN, 1 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
+/// 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.
+/// If either of the two lower double-precision values is NaN, 0 is returned.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VUCOMISD / UCOMISD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double]. The lower double-precision value is
+/// compared to the lower double-precision value of \a __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. If either of the two
+/// lower double-precision values is NaN, 0 is returned.
static __inline__ int __DEFAULT_FN_ATTRS
_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
+/// 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. If either of the two lower double-precision values
+/// is NaN, 0 is returned.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VUCOMISD / UCOMISD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double]. The lower double-precision value is
+/// compared to the lower double-precision value of \a __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. If either of the two
+/// lower double-precision values is NaN, 0 is returned.
static __inline__ int __DEFAULT_FN_ATTRS
_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
+/// 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VUCOMISD / UCOMISD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double]. The lower double-precision value is
+/// compared to the lower double-precision value of \a __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 result. If either of the two
+/// lower double-precision values is NaN, 0 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
+/// 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VCVTPD2PS / CVTPD2PS </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double].
+/// \returns A 128-bit vector of [4 x float] whose lower 64 bits contain the
+/// converted values. The upper 64 bits are set to zero.
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_cvtpd_ps(__m128d __a)
{
return __builtin_ia32_cvtpd2ps((__v2df)__a);
}
+/// \brief 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VCVTPS2PD / CVTPS2PD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [4 x float]. The lower two single-precision
+/// floating-point elements are converted to double-precision values. The
+/// upper two elements are unused.
+/// \returns A 128-bit vector of [2 x double] containing the converted values.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_cvtps_pd(__m128 __a)
{
@@ -395,6 +1276,19 @@ _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
+/// [4 x i32] 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VCVTDQ2PD / CVTDQ2PD </c> instruction.
+///
+/// \param __a
+/// A 128-bit integer vector of [4 x i32]. The lower two integer elements are
+/// converted to double-precision values. The upper two elements are unused.
+/// \returns A 128-bit vector of [2 x double] containing the converted values.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_cvtepi32_pd(__m128i __a)
{
@@ -402,24 +1296,84 @@ _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
+/// 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VCVTPD2DQ / CVTPD2DQ </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double].
+/// \returns A 128-bit vector of [4 x i32] whose lower 64 bits contain the
+/// converted values. The upper 64 bits are set to zero.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_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]
+/// into a 32-bit signed integer value.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VCVTSD2SI / CVTSD2SI </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double]. The lower 64 bits are used in the
+/// conversion.
+/// \returns A 32-bit signed integer containing the converted value.
static __inline__ int __DEFAULT_FN_ATTRS
_mm_cvtsd_si32(__m128d __a)
{
return __builtin_ia32_cvtsd2si((__v2df)__a);
}
+/// \brief 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
+/// copied from the upper 96 bits of the first parameter.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VCVTSD2SS / CVTSD2SS </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [4 x float]. The upper 96 bits of this parameter are
+/// copied to the upper 96 bits of the result.
+/// \param __b
+/// A 128-bit vector of [2 x double]. The lower double-precision
+/// floating-point element is used in the conversion.
+/// \returns A 128-bit vector of [4 x float]. The lower 32 bits contain the
+/// converted value from the second parameter. The upper 96 bits are copied
+/// from the upper 96 bits of the first parameter.
static __inline__ __m128 __DEFAULT_FN_ATTRS
_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
+/// 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VCVTSI2SD / CVTSI2SD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double]. The upper 64 bits of this parameter are
+/// copied to the upper 64 bits of the result.
+/// \param __b
+/// A 32-bit signed integer containing the value to be converted.
+/// \returns A 128-bit vector of [2 x double]. The lower 64 bits contain the
+/// converted value from the second parameter. The upper 64 bits are copied
+/// from the upper 64 bits of the first parameter.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_cvtsi32_sd(__m128d __a, int __b)
{
@@ -427,6 +1381,25 @@ _mm_cvtsi32_sd(__m128d __a, int __b)
return __a;
}
+/// \brief 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
+/// are copied from the upper 64 bits of the first parameter.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VCVTSS2SD / CVTSS2SD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double]. The upper 64 bits of this parameter are
+/// copied to the upper 64 bits of the result.
+/// \param __b
+/// A 128-bit vector of [4 x float]. The lower single-precision
+/// floating-point element is used in the conversion.
+/// \returns A 128-bit vector of [2 x double]. The lower 64 bits contain the
+/// converted value from the second parameter. The upper 64 bits are copied
+/// from the upper 64 bits of the first parameter.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_cvtss_sd(__m128d __a, __m128 __b)
{
@@ -434,48 +1407,145 @@ _mm_cvtss_sd(__m128d __a, __m128 __b)
return __a;
}
+/// \brief 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]. If the
+/// result of either conversion is inexact, the result is truncated (rounded
+/// towards zero) regardless of the current MXCSR setting. The upper 64 bits
+/// of the result vector are set to zero.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VCVTTPD2DQ / CVTTPD2DQ </c>
+/// instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double].
+/// \returns A 128-bit vector of [4 x i32] whose lower 64 bits contain the
+/// converted values. The upper 64 bits are set to zero.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_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
+/// signed integer value, truncating the result when it is inexact.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VCVTTSD2SI / CVTTSD2SI </c>
+/// instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double]. The lower 64 bits are used in the
+/// conversion.
+/// \returns A 32-bit signed integer containing the converted value.
static __inline__ int __DEFAULT_FN_ATTRS
_mm_cvttsd_si32(__m128d __a)
{
return __builtin_ia32_cvttsd2si((__v2df)__a);
}
+/// \brief 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].
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> CVTPD2PI </c> instruction.
+///
+/// \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
_mm_cvtpd_pi32(__m128d __a)
{
return (__m64)__builtin_ia32_cvtpd2pi((__v2df)__a);
}
+/// \brief 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]. If the result of either
+/// conversion is inexact, the result is truncated (rounded towards zero)
+/// regardless of the current MXCSR setting.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> CVTTPD2PI </c> instruction.
+///
+/// \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
_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
+/// [2 x i32] into two double-precision floating-point values, returned in a
+/// 128-bit vector of [2 x double].
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> CVTPI2PD </c> instruction.
+///
+/// \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
_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
+/// a double-precision floating-point value.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic has no corresponding instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double]. The lower 64 bits are returned.
+/// \returns A double-precision floating-point value copied from the lower 64
+/// bits of \a __a.
static __inline__ double __DEFAULT_FN_ATTRS
_mm_cvtsd_f64(__m128d __a)
{
return __a[0];
}
+/// \brief Loads a 128-bit floating-point vector of [2 x double] from an aligned
+/// memory location.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMOVAPD / MOVAPD </c> instruction.
+///
+/// \param __dp
+/// A pointer to a 128-bit memory location. The address of the memory
+/// location has to be 16-byte aligned.
+/// \returns A 128-bit vector of [2 x double] containing the loaded values.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_load_pd(double const *__dp)
{
return *(__m128d*)__dp;
}
+/// \brief 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].
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMOVDDUP / MOVDDUP </c> instruction.
+///
+/// \param __dp
+/// A pointer to a memory location containing a double-precision value.
+/// \returns A 128-bit vector of [2 x double] containing the loaded and
+/// duplicated values.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_load1_pd(double const *__dp)
{
@@ -488,6 +1558,20 @@ _mm_load1_pd(double const *__dp)
#define _mm_load_pd1(dp) _mm_load1_pd(dp)
+/// \brief 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>
+///
+/// This intrinsic corresponds to the <c> VMOVAPD / MOVAPD </c> instruction +
+/// needed shuffling instructions. In AVX mode, the shuffling may be combined
+/// with the \c VMOVAPD, resulting in only a \c VPERMILPD instruction.
+///
+/// \param __dp
+/// A 16-byte aligned pointer to an array of double-precision values to be
+/// loaded in reverse order.
+/// \returns A 128-bit vector of [2 x double] containing the reversed loaded
+/// values.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_loadr_pd(double const *__dp)
{
@@ -495,6 +1579,17 @@ _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
+/// unaligned memory location.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMOVUPD / MOVUPD </c> instruction.
+///
+/// \param __dp
+/// A pointer to a 128-bit memory location. The address of the memory
+/// location does not have to be aligned.
+/// \returns A 128-bit vector of [2 x double] containing the loaded values.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_loadu_pd(double const *__dp)
{
@@ -524,6 +1619,23 @@ _mm_load_sd(double const *__dp)
return (__m128d){ __u, 0 };
}
+/// \brief 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMOVHPD / MOVHPD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double]. \n
+/// Bits [63:0] are written to bits [63:0] of the result.
+/// \param __dp
+/// A pointer to a 64-bit memory location containing a double-precision
+/// floating-point value that is loaded. The loaded value is written to bits
+/// [127:64] of the result. The address of the memory location does not have
+/// to be aligned.
+/// \returns A 128-bit vector of [2 x double] containing the moved values.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_loadh_pd(__m128d __a, double const *__dp)
{
@@ -534,6 +1646,23 @@ _mm_loadh_pd(__m128d __a, double const *__dp)
return (__m128d){ __a[0], __u };
}
+/// \brief 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMOVLPD / MOVLPD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double]. \n
+/// Bits [127:64] are written to bits [127:64] of the result.
+/// \param __dp
+/// A pointer to a 64-bit memory location containing a double-precision
+/// floating-point value that is loaded. The loaded value is written to bits
+/// [63:0] of the result. The address of the memory location does not have to
+/// be aligned.
+/// \returns A 128-bit vector of [2 x double] containing the moved values.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_loadl_pd(__m128d __a, double const *__dp)
{
@@ -544,48 +1673,149 @@ _mm_loadl_pd(__m128d __a, double const *__dp)
return (__m128d){ __u, __a[1] };
}
+/// \brief 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic has no corresponding instruction.
+///
+/// \returns A 128-bit floating-point vector of [2 x double] with unspecified
+/// content.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_undefined_pd(void)
{
return (__m128d)__builtin_ia32_undef128();
}
+/// \brief 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMOVQ / MOVQ </c> instruction.
+///
+/// \param __w
+/// A double-precision floating-point value used to initialize the lower 64
+/// bits of the result.
+/// \returns An initialized 128-bit floating-point vector of [2 x double]. The
+/// lower 64 bits contain the value of the parameter. The upper 64 bits are
+/// set to zero.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_set_sd(double __w)
{
return (__m128d){ __w, 0 };
}
+/// \brief 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMOVDDUP / MOVLHPS </c> instruction.
+///
+/// \param __w
+/// A double-precision floating-point value used to initialize each vector
+/// element of the result.
+/// \returns An initialized 128-bit floating-point vector of [2 x double].
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_set1_pd(double __w)
{
return (__m128d){ __w, __w };
}
+/// \brief Constructs a 128-bit floating-point vector of [2 x double]
+/// initialized with the specified double-precision floating-point values.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VUNPCKLPD / UNPCKLPD </c> instruction.
+///
+/// \param __w
+/// A double-precision floating-point value used to initialize the upper 64
+/// bits of the result.
+/// \param __x
+/// A double-precision floating-point value used to initialize the lower 64
+/// bits of the result.
+/// \returns An initialized 128-bit floating-point vector of [2 x double].
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_set_pd(double __w, double __x)
{
return (__m128d){ __x, __w };
}
+/// \brief Constructs a 128-bit floating-point vector of [2 x double],
+/// initialized in reverse order with the specified double-precision
+/// floating-point values.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VUNPCKLPD / UNPCKLPD </c> instruction.
+///
+/// \param __w
+/// A double-precision floating-point value used to initialize the lower 64
+/// bits of the result.
+/// \param __x
+/// A double-precision floating-point value used to initialize the upper 64
+/// bits of the result.
+/// \returns An initialized 128-bit floating-point vector of [2 x double].
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_setr_pd(double __w, double __x)
{
return (__m128d){ __w, __x };
}
+/// \brief Constructs a 128-bit floating-point vector of [2 x double]
+/// initialized to zero.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VXORPS / XORPS </c> instruction.
+///
+/// \returns An initialized 128-bit floating-point vector of [2 x double] with
+/// all elements set to zero.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_setzero_pd(void)
{
return (__m128d){ 0, 0 };
}
+/// \brief 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.
+//
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VBLENDPD / BLENDPD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double]. The upper 64 bits are written to the
+/// upper 64 bits of the result.
+/// \param __b
+/// A 128-bit vector of [2 x double]. The lower 64 bits are written to the
+/// lower 64 bits of the result.
+/// \returns A 128-bit vector of [2 x double] containing the moved values.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_move_sd(__m128d __a, __m128d __b)
{
return (__m128d){ __b[0], __a[1] };
}
+/// \brief Stores the lower 64 bits of a 128-bit vector of [2 x double] to a
+/// memory location.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMOVSD / MOVSD </c> instruction.
+///
+/// \param __dp
+/// A pointer to a 64-bit memory location.
+/// \param __a
+/// A 128-bit vector of [2 x double] containing the value to be stored.
static __inline__ void __DEFAULT_FN_ATTRS
_mm_store_sd(double *__dp, __m128d __a)
{
@@ -608,12 +1838,36 @@ _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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMOVAPD / MOVAPD </c> instruction.
+///
+/// \param __dp
+/// A pointer to a 128-bit memory location. The address of the memory
+/// location has to be 16-byte aligned.
+/// \param __a
+/// A 128-bit vector of [2 x double] containing the values to be stored.
static __inline__ void __DEFAULT_FN_ATTRS
_mm_store_pd1(double *__dp, __m128d __a)
{
return _mm_store1_pd(__dp, __a);
}
+/// \brief Stores a 128-bit vector of [2 x double] into an unaligned memory
+/// location.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMOVUPD / MOVUPD </c> instruction.
+///
+/// \param __dp
+/// A pointer to a 128-bit memory location. The address of the memory
+/// location does not have to be aligned.
+/// \param __a
+/// A 128-bit vector of [2 x double] containing the values to be stored.
static __inline__ void __DEFAULT_FN_ATTRS
_mm_storeu_pd(double *__dp, __m128d __a)
{
@@ -623,6 +1877,20 @@ _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
+/// vector of [2 x double] to a 16-byte aligned memory location.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to a shuffling instruction followed by a
+/// <c> VMOVAPD / MOVAPD </c> instruction.
+///
+/// \param __dp
+/// A pointer to a 16-byte aligned memory location that can store two
+/// double-precision values.
+/// \param __a
+/// A 128-bit vector of [2 x double] containing the values to be reversed and
+/// stored.
static __inline__ void __DEFAULT_FN_ATTRS
_mm_storer_pd(double *__dp, __m128d __a)
{
@@ -630,6 +1898,17 @@ _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
+/// memory location.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMOVHPD / MOVHPD </c> instruction.
+///
+/// \param __dp
+/// A pointer to a 64-bit memory location.
+/// \param __a
+/// A 128-bit vector of [2 x double] containing the value to be stored.
static __inline__ void __DEFAULT_FN_ATTRS
_mm_storeh_pd(double *__dp, __m128d __a)
{
@@ -639,6 +1918,17 @@ _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
+/// memory location.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMOVLPD / MOVLPD </c> instruction.
+///
+/// \param __dp
+/// A pointer to a 64-bit memory location.
+/// \param __a
+/// A 128-bit vector of [2 x double] containing the value to be stored.
static __inline__ void __DEFAULT_FN_ATTRS
_mm_storel_pd(double *__dp, __m128d __a)
{
@@ -648,127 +1938,391 @@ _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],
+/// saving the lower 8 bits of each sum in the corresponding element of a
+/// 128-bit result vector of [16 x i8]. The integer elements of both
+/// parameters can be either signed or unsigned.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VPADDB / PADDB </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [16 x i8].
+/// \param __b
+/// A 128-bit vector of [16 x i8].
+/// \returns A 128-bit vector of [16 x i8] containing the sums of both
+/// parameters.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_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],
+/// saving the lower 16 bits of each sum in the corresponding element of a
+/// 128-bit result vector of [8 x i16]. The integer elements of both
+/// parameters can be either signed or unsigned.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VPADDW / PADDW </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [8 x i16].
+/// \param __b
+/// A 128-bit vector of [8 x i16].
+/// \returns A 128-bit vector of [8 x i16] containing the sums of both
+/// parameters.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_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],
+/// saving the lower 32 bits of each sum in the corresponding element of a
+/// 128-bit result vector of [4 x i32]. The integer elements of both
+/// parameters can be either signed or unsigned.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VPADDD / PADDD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [4 x i32].
+/// \param __b
+/// A 128-bit vector of [4 x i32].
+/// \returns A 128-bit vector of [4 x i32] containing the sums of both
+/// parameters.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_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
+/// lower 64 bits of the sum.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> PADDQ </c> instruction.
+///
+/// \param __a
+/// A 64-bit integer.
+/// \param __b
+/// A 64-bit integer.
+/// \returns A 64-bit integer containing the sum of both parameters.
static __inline__ __m64 __DEFAULT_FN_ATTRS
_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],
+/// saving the lower 64 bits of each sum in the corresponding element of a
+/// 128-bit result vector of [2 x i64]. The integer elements of both
+/// parameters can be either signed or unsigned.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VPADDQ / PADDQ </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x i64].
+/// \param __b
+/// A 128-bit vector of [2 x i64].
+/// \returns A 128-bit vector of [2 x i64] containing the sums of both
+/// parameters.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_add_epi64(__m128i __a, __m128i __b)
{
return (__m128i)((__v2du)__a + (__v2du)__b);
}
+/// \brief 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VPADDSB / PADDSB </c> instruction.
+///
+/// \param __a
+/// A 128-bit signed [16 x i8] vector.
+/// \param __b
+/// A 128-bit signed [16 x i8] vector.
+/// \returns A 128-bit signed [16 x i8] vector containing the saturated sums of
+/// both parameters.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_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
+/// 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VPADDSW / PADDSW </c> instruction.
+///
+/// \param __a
+/// A 128-bit signed [8 x i16] vector.
+/// \param __b
+/// A 128-bit signed [8 x i16] vector.
+/// \returns A 128-bit signed [8 x i16] vector containing the saturated sums of
+/// both parameters.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_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
+/// 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VPADDUSB / PADDUSB </c> instruction.
+///
+/// \param __a
+/// A 128-bit unsigned [16 x i8] vector.
+/// \param __b
+/// A 128-bit unsigned [16 x i8] vector.
+/// \returns A 128-bit unsigned [16 x i8] vector containing the saturated sums
+/// of both parameters.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_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
+/// 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VPADDUSB / PADDUSB </c> instruction.
+///
+/// \param __a
+/// A 128-bit unsigned [8 x i16] vector.
+/// \param __b
+/// A 128-bit unsigned [8 x i16] vector.
+/// \returns A 128-bit unsigned [8 x i16] vector containing the saturated sums
+/// of both parameters.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_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
+/// 128-bit unsigned [16 x i8] vectors, saving each result in the
+/// corresponding element of a 128-bit result vector of [16 x i8].
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VPAVGB / PAVGB </c> instruction.
+///
+/// \param __a
+/// A 128-bit unsigned [16 x i8] vector.
+/// \param __b
+/// A 128-bit unsigned [16 x i8] vector.
+/// \returns A 128-bit unsigned [16 x i8] vector containing the rounded
+/// averages of both parameters.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_avg_epu8(__m128i __a, __m128i __b)
{
return (__m128i)__builtin_ia32_pavgb128((__v16qi)__a, (__v16qi)__b);
}
+/// \brief 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].
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VPAVGW / PAVGW </c> instruction.
+///
+/// \param __a
+/// A 128-bit unsigned [8 x i16] vector.
+/// \param __b
+/// A 128-bit unsigned [8 x i16] vector.
+/// \returns A 128-bit unsigned [8 x i16] vector containing the rounded
+/// averages of both parameters.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_avg_epu16(__m128i __a, __m128i __b)
{
return (__m128i)__builtin_ia32_pavgw128((__v8hi)__a, (__v8hi)__b);
}
+/// \brief 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. For example, bits [15:0] of both parameters are
+/// multiplied producing a 32-bit product, bits [31:16] of both parameters
+/// are multiplied producing a 32-bit product, and the sum of those two
+/// products becomes bits [31:0] of the result.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VPMADDWD / PMADDWD </c> instruction.
+///
+/// \param __a
+/// A 128-bit signed [8 x i16] vector.
+/// \param __b
+/// A 128-bit signed [8 x i16] vector.
+/// \returns A 128-bit signed [4 x i32] vector containing the sums of products
+/// of both parameters.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_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]
+/// vectors, saving the greater value from each comparison in the
+/// corresponding element of a 128-bit result vector of [8 x i16].
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VPMAXSW / PMAXSW </c> instruction.
+///
+/// \param __a
+/// A 128-bit signed [8 x i16] vector.
+/// \param __b
+/// A 128-bit signed [8 x i16] vector.
+/// \returns A 128-bit signed [8 x i16] vector containing the greater value of
+/// each comparison.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_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]
+/// vectors, saving the greater value from each comparison in the
+/// corresponding element of a 128-bit result vector of [16 x i8].
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VPMAXUB / PMAXUB </c> instruction.
+///
+/// \param __a
+/// A 128-bit unsigned [16 x i8] vector.
+/// \param __b
+/// A 128-bit unsigned [16 x i8] vector.
+/// \returns A 128-bit unsigned [16 x i8] vector containing the greater value of
+/// each comparison.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_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]
+/// vectors, saving the smaller value from each comparison in the
+/// corresponding element of a 128-bit result vector of [8 x i16].
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VPMINSW / PMINSW </c> instruction.
+///
+/// \param __a
+/// A 128-bit signed [8 x i16] vector.
+/// \param __b
+/// A 128-bit signed [8 x i16] vector.
+/// \returns A 128-bit signed [8 x i16] vector containing the smaller value of
+/// each comparison.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_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]
+/// vectors, saving the smaller value from each comparison in the
+/// corresponding element of a 128-bit result vector of [16 x i8].
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VPMINUB / PMINUB </c> instruction.
+///
+/// \param __a
+/// A 128-bit unsigned [16 x i8] vector.
+/// \param __b
+/// A 128-bit unsigned [16 x i8] vector.
+/// \returns A 128-bit unsigned [16 x i8] vector containing the smaller value of
+/// each comparison.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_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]
+/// 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VPMULHW / PMULHW </c> instruction.
+///
+/// \param __a
+/// A 128-bit signed [8 x i16] vector.
+/// \param __b
+/// A 128-bit signed [8 x i16] vector.
+/// \returns A 128-bit signed [8 x i16] vector containing the upper 16 bits of
+/// each of the eight 32-bit products.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_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]
+/// 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VPMULHUW / PMULHUW </c> instruction.
+///
+/// \param __a
+/// A 128-bit unsigned [8 x i16] vector.
+/// \param __b
+/// A 128-bit unsigned [8 x i16] vector.
+/// \returns A 128-bit unsigned [8 x i16] vector containing the upper 16 bits
+/// of each of the eight 32-bit products.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_mulhi_epu16(__m128i __a, __m128i __b)
{
return (__m128i)__builtin_ia32_pmulhuw128((__v8hi)__a, (__v8hi)__b);
}
-/// \brief Multiplies the corresponding elements of two [8 x short] vectors and
-/// returns a vector containing the low-order 16 bits of each 32-bit product
-/// in the corresponding element.
+/// \brief 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.
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPMULLW / PMULLW instruction.
+/// This intrinsic corresponds to the <c> VPMULLW / PMULLW </c> instruction.
///
/// \param __a
-/// A 128-bit integer vector containing one of the source operands.
+/// A 128-bit signed [8 x i16] vector.
/// \param __b
-/// A 128-bit integer vector containing one of the source operands.
-/// \returns A 128-bit integer vector containing the products of both operands.
+/// A 128-bit signed [8 x i16] vector.
+/// \returns A 128-bit signed [8 x i16] vector containing the lower 16 bits of
+/// each of the eight 32-bit products.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_mullo_epi16(__m128i __a, __m128i __b)
{
@@ -781,7 +2335,7 @@ _mm_mullo_epi16(__m128i __a, __m128i __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PMULUDQ instruction.
+/// This intrinsic corresponds to the <c> PMULUDQ </c> instruction.
///
/// \param __a
/// A 64-bit integer containing one of the source operands.
@@ -800,7 +2354,7 @@ _mm_mul_su32(__m64 __a, __m64 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPMULUDQ / PMULUDQ instruction.
+/// This intrinsic corresponds to the <c> VPMULUDQ / PMULUDQ </c> instruction.
///
/// \param __a
/// A [2 x i64] vector containing one of the source operands.
@@ -821,7 +2375,7 @@ _mm_mul_epu32(__m128i __a, __m128i __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPSADBW / PSADBW instruction.
+/// This intrinsic corresponds to the <c> VPSADBW / PSADBW </c> instruction.
///
/// \param __a
/// A 128-bit integer vector containing one of the source operands.
@@ -839,7 +2393,7 @@ _mm_sad_epu8(__m128i __a, __m128i __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPSUBB / PSUBB instruction.
+/// This intrinsic corresponds to the <c> VPSUBB / PSUBB </c> instruction.
///
/// \param __a
/// A 128-bit integer vector containing the minuends.
@@ -857,7 +2411,7 @@ _mm_sub_epi8(__m128i __a, __m128i __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPSUBW / PSUBW instruction.
+/// This intrinsic corresponds to the <c> VPSUBW / PSUBW </c> instruction.
///
/// \param __a
/// A 128-bit integer vector containing the minuends.
@@ -875,7 +2429,7 @@ _mm_sub_epi16(__m128i __a, __m128i __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPSUBD / PSUBD instruction.
+/// This intrinsic corresponds to the <c> VPSUBD / PSUBD </c> instruction.
///
/// \param __a
/// A 128-bit integer vector containing the minuends.
@@ -894,7 +2448,7 @@ _mm_sub_epi32(__m128i __a, __m128i __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PSUBQ instruction.
+/// This intrinsic corresponds to the <c> PSUBQ </c> instruction.
///
/// \param __a
/// A 64-bit integer vector containing the minuend.
@@ -912,7 +2466,7 @@ _mm_sub_si64(__m64 __a, __m64 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPSUBQ / PSUBQ instruction.
+/// This intrinsic corresponds to the <c> VPSUBQ / PSUBQ </c> instruction.
///
/// \param __a
/// A 128-bit integer vector containing the minuends.
@@ -933,7 +2487,7 @@ _mm_sub_epi64(__m128i __a, __m128i __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPSUBSB / PSUBSB instruction.
+/// This intrinsic corresponds to the <c> VPSUBSB / PSUBSB </c> instruction.
///
/// \param __a
/// A 128-bit integer vector containing the minuends.
@@ -954,7 +2508,7 @@ _mm_subs_epi8(__m128i __a, __m128i __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPSUBSW / PSUBSW instruction.
+/// This intrinsic corresponds to the <c> VPSUBSW / PSUBSW </c> instruction.
///
/// \param __a
/// A 128-bit integer vector containing the minuends.
@@ -974,7 +2528,7 @@ _mm_subs_epi16(__m128i __a, __m128i __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPSUBUSB / PSUBUSB instruction.
+/// This intrinsic corresponds to the <c> VPSUBUSB / PSUBUSB </c> instruction.
///
/// \param __a
/// A 128-bit integer vector containing the minuends.
@@ -994,7 +2548,7 @@ _mm_subs_epu8(__m128i __a, __m128i __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPSUBUSW / PSUBUSW instruction.
+/// This intrinsic corresponds to the <c> VPSUBUSW / PSUBUSW </c> instruction.
///
/// \param __a
/// A 128-bit integer vector containing the minuends.
@@ -1012,7 +2566,7 @@ _mm_subs_epu16(__m128i __a, __m128i __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPAND / PAND instruction.
+/// This intrinsic corresponds to the <c> VPAND / PAND </c> instruction.
///
/// \param __a
/// A 128-bit integer vector containing one of the source operands.
@@ -1031,7 +2585,7 @@ _mm_and_si128(__m128i __a, __m128i __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPANDN / PANDN instruction.
+/// This intrinsic corresponds to the <c> VPANDN / PANDN </c> instruction.
///
/// \param __a
/// A 128-bit vector containing the left source operand. The one's complement
@@ -1049,7 +2603,7 @@ _mm_andnot_si128(__m128i __a, __m128i __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPOR / POR instruction.
+/// This intrinsic corresponds to the <c> VPOR / POR </c> instruction.
///
/// \param __a
/// A 128-bit integer vector containing one of the source operands.
@@ -1067,7 +2621,7 @@ _mm_or_si128(__m128i __a, __m128i __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPXOR / PXOR instruction.
+/// This intrinsic corresponds to the <c> VPXOR / PXOR </c> instruction.
///
/// \param __a
/// A 128-bit integer vector containing one of the source operands.
@@ -1090,13 +2644,13 @@ _mm_xor_si128(__m128i __a, __m128i __b)
/// __m128i _mm_slli_si128(__m128i a, const int imm);
/// \endcode
///
-/// This intrinsic corresponds to the \c VPSLLDQ / PSLLDQ instruction.
+/// This intrinsic corresponds to the <c> VPSLLDQ / PSLLDQ </c> instruction.
///
/// \param a
/// A 128-bit integer vector containing the source operand.
/// \param imm
-/// An immediate value specifying the number of bytes to left-shift
-/// operand a.
+/// 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( \
@@ -1127,13 +2681,13 @@ _mm_xor_si128(__m128i __a, __m128i __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPSLLW / PSLLW instruction.
+/// This intrinsic corresponds to the <c> VPSLLW / PSLLW </c> instruction.
///
/// \param __a
/// A 128-bit integer vector containing the source operand.
/// \param __count
/// An integer value specifying the number of bits to left-shift each value
-/// in operand __a.
+/// in operand \a __a.
/// \returns A 128-bit integer vector containing the left-shifted values.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_slli_epi16(__m128i __a, int __count)
@@ -1146,13 +2700,13 @@ _mm_slli_epi16(__m128i __a, int __count)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPSLLW / PSLLW instruction.
+/// This intrinsic corresponds to the <c> VPSLLW / PSLLW </c> instruction.
///
/// \param __a
/// A 128-bit integer vector containing the source operand.
/// \param __count
/// A 128-bit integer vector in which bits [63:0] specify the number of bits
-/// to left-shift each value in operand __a.
+/// to left-shift each value in operand \a __a.
/// \returns A 128-bit integer vector containing the left-shifted values.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_sll_epi16(__m128i __a, __m128i __count)
@@ -1165,13 +2719,13 @@ _mm_sll_epi16(__m128i __a, __m128i __count)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPSLLD / PSLLD instruction.
+/// This intrinsic corresponds to the <c> VPSLLD / PSLLD </c> instruction.
///
/// \param __a
/// A 128-bit integer vector containing the source operand.
/// \param __count
/// An integer value specifying the number of bits to left-shift each value
-/// in operand __a.
+/// in operand \a __a.
/// \returns A 128-bit integer vector containing the left-shifted values.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_slli_epi32(__m128i __a, int __count)
@@ -1184,13 +2738,13 @@ _mm_slli_epi32(__m128i __a, int __count)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPSLLD / PSLLD instruction.
+/// This intrinsic corresponds to the <c> VPSLLD / PSLLD </c> instruction.
///
/// \param __a
/// A 128-bit integer vector containing the source operand.
/// \param __count
/// A 128-bit integer vector in which bits [63:0] specify the number of bits
-/// to left-shift each value in operand __a.
+/// to left-shift each value in operand \a __a.
/// \returns A 128-bit integer vector containing the left-shifted values.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_sll_epi32(__m128i __a, __m128i __count)
@@ -1203,13 +2757,13 @@ _mm_sll_epi32(__m128i __a, __m128i __count)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPSLLQ / PSLLQ instruction.
+/// This intrinsic corresponds to the <c> VPSLLQ / PSLLQ </c> instruction.
///
/// \param __a
/// A 128-bit integer vector containing the source operand.
/// \param __count
/// An integer value specifying the number of bits to left-shift each value
-/// in operand __a.
+/// in operand \a __a.
/// \returns A 128-bit integer vector containing the left-shifted values.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_slli_epi64(__m128i __a, int __count)
@@ -1222,13 +2776,13 @@ _mm_slli_epi64(__m128i __a, int __count)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPSLLQ / PSLLQ instruction.
+/// This intrinsic corresponds to the <c> VPSLLQ / PSLLQ </c> instruction.
///
/// \param __a
/// A 128-bit integer vector containing the source operand.
/// \param __count
/// A 128-bit integer vector in which bits [63:0] specify the number of bits
-/// to left-shift each value in operand __a.
+/// to left-shift each value in operand \a __a.
/// \returns A 128-bit integer vector containing the left-shifted values.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_sll_epi64(__m128i __a, __m128i __count)
@@ -1242,13 +2796,13 @@ _mm_sll_epi64(__m128i __a, __m128i __count)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPSRAW / PSRAW instruction.
+/// This intrinsic corresponds to the <c> VPSRAW / PSRAW </c> instruction.
///
/// \param __a
/// A 128-bit integer vector containing the source operand.
/// \param __count
/// An integer value specifying the number of bits to right-shift each value
-/// in operand __a.
+/// in operand \a __a.
/// \returns A 128-bit integer vector containing the right-shifted values.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_srai_epi16(__m128i __a, int __count)
@@ -1262,13 +2816,13 @@ _mm_srai_epi16(__m128i __a, int __count)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPSRAW / PSRAW instruction.
+/// This intrinsic corresponds to the <c> VPSRAW / PSRAW </c> instruction.
///
/// \param __a
/// A 128-bit integer vector containing the source operand.
/// \param __count
/// A 128-bit integer vector in which bits [63:0] specify the number of bits
-/// to right-shift each value in operand __a.
+/// to right-shift each value in operand \a __a.
/// \returns A 128-bit integer vector containing the right-shifted values.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_sra_epi16(__m128i __a, __m128i __count)
@@ -1282,13 +2836,13 @@ _mm_sra_epi16(__m128i __a, __m128i __count)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPSRAD / PSRAD instruction.
+/// This intrinsic corresponds to the <c> VPSRAD / PSRAD </c> instruction.
///
/// \param __a
/// A 128-bit integer vector containing the source operand.
/// \param __count
/// An integer value specifying the number of bits to right-shift each value
-/// in operand __a.
+/// in operand \a __a.
/// \returns A 128-bit integer vector containing the right-shifted values.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_srai_epi32(__m128i __a, int __count)
@@ -1302,13 +2856,13 @@ _mm_srai_epi32(__m128i __a, int __count)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPSRAD / PSRAD instruction.
+/// This intrinsic corresponds to the <c> VPSRAD / PSRAD </c> instruction.
///
/// \param __a
/// A 128-bit integer vector containing the source operand.
/// \param __count
/// A 128-bit integer vector in which bits [63:0] specify the number of bits
-/// to right-shift each value in operand __a.
+/// to right-shift each value in operand \a __a.
/// \returns A 128-bit integer vector containing the right-shifted values.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_sra_epi32(__m128i __a, __m128i __count)
@@ -1325,13 +2879,13 @@ _mm_sra_epi32(__m128i __a, __m128i __count)
/// __m128i _mm_srli_si128(__m128i a, const int imm);
/// \endcode
///
-/// This intrinsic corresponds to the \c VPSRLDQ / PSRLDQ instruction.
+/// This intrinsic corresponds to the <c> VPSRLDQ / PSRLDQ </c> instruction.
///
/// \param a
/// A 128-bit integer vector containing the source operand.
/// \param imm
/// An immediate value specifying the number of bytes to right-shift operand
-/// a.
+/// \a a.
/// \returns A 128-bit integer vector containing the right-shifted value.
#define _mm_srli_si128(a, imm) __extension__ ({ \
(__m128i)__builtin_shufflevector( \
@@ -1362,13 +2916,13 @@ _mm_sra_epi32(__m128i __a, __m128i __count)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPSRLW / PSRLW instruction.
+/// This intrinsic corresponds to the <c> VPSRLW / PSRLW </c> instruction.
///
/// \param __a
/// A 128-bit integer vector containing the source operand.
/// \param __count
/// An integer value specifying the number of bits to right-shift each value
-/// in operand __a.
+/// in operand \a __a.
/// \returns A 128-bit integer vector containing the right-shifted values.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_srli_epi16(__m128i __a, int __count)
@@ -1381,13 +2935,13 @@ _mm_srli_epi16(__m128i __a, int __count)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPSRLW / PSRLW instruction.
+/// This intrinsic corresponds to the <c> VPSRLW / PSRLW </c> instruction.
///
/// \param __a
/// A 128-bit integer vector containing the source operand.
/// \param __count
/// A 128-bit integer vector in which bits [63:0] specify the number of bits
-/// to right-shift each value in operand __a.
+/// to right-shift each value in operand \a __a.
/// \returns A 128-bit integer vector containing the right-shifted values.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_srl_epi16(__m128i __a, __m128i __count)
@@ -1400,13 +2954,13 @@ _mm_srl_epi16(__m128i __a, __m128i __count)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPSRLD / PSRLD instruction.
+/// This intrinsic corresponds to the <c> VPSRLD / PSRLD </c> instruction.
///
/// \param __a
/// A 128-bit integer vector containing the source operand.
/// \param __count
/// An integer value specifying the number of bits to right-shift each value
-/// in operand __a.
+/// in operand \a __a.
/// \returns A 128-bit integer vector containing the right-shifted values.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_srli_epi32(__m128i __a, int __count)
@@ -1419,13 +2973,13 @@ _mm_srli_epi32(__m128i __a, int __count)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPSRLD / PSRLD instruction.
+/// This intrinsic corresponds to the <c> VPSRLD / PSRLD </c> instruction.
///
/// \param __a
/// A 128-bit integer vector containing the source operand.
/// \param __count
/// A 128-bit integer vector in which bits [63:0] specify the number of bits
-/// to right-shift each value in operand __a.
+/// to right-shift each value in operand \a __a.
/// \returns A 128-bit integer vector containing the right-shifted values.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_srl_epi32(__m128i __a, __m128i __count)
@@ -1438,13 +2992,13 @@ _mm_srl_epi32(__m128i __a, __m128i __count)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPSRLQ / PSRLQ instruction.
+/// This intrinsic corresponds to the <c> VPSRLQ / PSRLQ </c> instruction.
///
/// \param __a
/// A 128-bit integer vector containing the source operand.
/// \param __count
/// An integer value specifying the number of bits to right-shift each value
-/// in operand __a.
+/// in operand \a __a.
/// \returns A 128-bit integer vector containing the right-shifted values.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_srli_epi64(__m128i __a, int __count)
@@ -1457,13 +3011,13 @@ _mm_srli_epi64(__m128i __a, int __count)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPSRLQ / PSRLQ instruction.
+/// This intrinsic corresponds to the <c> VPSRLQ / PSRLQ </c> instruction.
///
/// \param __a
/// A 128-bit integer vector containing the source operand.
/// \param __count
/// A 128-bit integer vector in which bits [63:0] specify the number of bits
-/// to right-shift each value in operand __a.
+/// to right-shift each value in operand \a __a.
/// \returns A 128-bit integer vector containing the right-shifted values.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_srl_epi64(__m128i __a, __m128i __count)
@@ -1477,7 +3031,7 @@ _mm_srl_epi64(__m128i __a, __m128i __count)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPCMPEQB / PCMPEQB instruction.
+/// This intrinsic corresponds to the <c> VPCMPEQB / PCMPEQB </c> instruction.
///
/// \param __a
/// A 128-bit integer vector.
@@ -1496,7 +3050,7 @@ _mm_cmpeq_epi8(__m128i __a, __m128i __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPCMPEQW / PCMPEQW instruction.
+/// This intrinsic corresponds to the <c> VPCMPEQW / PCMPEQW </c> instruction.
///
/// \param __a
/// A 128-bit integer vector.
@@ -1515,7 +3069,7 @@ _mm_cmpeq_epi16(__m128i __a, __m128i __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPCMPEQD / PCMPEQD instruction.
+/// This intrinsic corresponds to the <c> VPCMPEQD / PCMPEQD </c> instruction.
///
/// \param __a
/// A 128-bit integer vector.
@@ -1535,7 +3089,7 @@ _mm_cmpeq_epi32(__m128i __a, __m128i __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPCMPGTB / PCMPGTB instruction.
+/// This intrinsic corresponds to the <c> VPCMPGTB / PCMPGTB </c> instruction.
///
/// \param __a
/// A 128-bit integer vector.
@@ -1557,7 +3111,7 @@ _mm_cmpgt_epi8(__m128i __a, __m128i __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPCMPGTW / PCMPGTW instruction.
+/// This intrinsic corresponds to the <c> VPCMPGTW / PCMPGTW </c> instruction.
///
/// \param __a
/// A 128-bit integer vector.
@@ -1577,7 +3131,7 @@ _mm_cmpgt_epi16(__m128i __a, __m128i __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPCMPGTD / PCMPGTD instruction.
+/// This intrinsic corresponds to the <c> VPCMPGTD / PCMPGTD </c> instruction.
///
/// \param __a
/// A 128-bit integer vector.
@@ -1597,7 +3151,7 @@ _mm_cmpgt_epi32(__m128i __a, __m128i __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPCMPGTB / PCMPGTB instruction.
+/// This intrinsic corresponds to the <c> VPCMPGTB / PCMPGTB </c> instruction.
///
/// \param __a
/// A 128-bit integer vector.
@@ -1617,7 +3171,7 @@ _mm_cmplt_epi8(__m128i __a, __m128i __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPCMPGTW / PCMPGTW instruction.
+/// This intrinsic corresponds to the <c> VPCMPGTW / PCMPGTW </c> instruction.
///
/// \param __a
/// A 128-bit integer vector.
@@ -1637,7 +3191,7 @@ _mm_cmplt_epi16(__m128i __a, __m128i __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPCMPGTD / PCMPGTD instruction.
+/// This intrinsic corresponds to the <c> VPCMPGTD / PCMPGTD </c> instruction.
///
/// \param __a
/// A 128-bit integer vector.
@@ -1658,7 +3212,7 @@ _mm_cmplt_epi32(__m128i __a, __m128i __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCVTSI2SD / CVTSI2SD instruction.
+/// This intrinsic corresponds to the <c> VCVTSI2SD / CVTSI2SD </c> instruction.
///
/// \param __a
/// A 128-bit vector of [2 x double]. The upper 64 bits of this operand are
@@ -1680,7 +3234,7 @@ _mm_cvtsi64_sd(__m128d __a, long long __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCVTSD2SI / CVTSD2SI instruction.
+/// This intrinsic corresponds to the <c> VCVTSD2SI / CVTSD2SI </c> instruction.
///
/// \param __a
/// A 128-bit vector of [2 x double]. The lower 64 bits are used in the
@@ -1697,7 +3251,8 @@ _mm_cvtsd_si64(__m128d __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCVTTSD2SI / CVTTSD2SI instruction.
+/// This intrinsic corresponds to the <c> VCVTTSD2SI / CVTTSD2SI </c>
+/// instruction.
///
/// \param __a
/// A 128-bit vector of [2 x double]. The lower 64 bits are used in the
@@ -1714,7 +3269,7 @@ _mm_cvttsd_si64(__m128d __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCVTDQ2PS / CVTDQ2PS instruction.
+/// This intrinsic corresponds to the <c> VCVTDQ2PS / CVTDQ2PS </c> instruction.
///
/// \param __a
/// A 128-bit integer vector.
@@ -1729,7 +3284,7 @@ _mm_cvtepi32_ps(__m128i __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCVTPS2DQ / CVTPS2DQ instruction.
+/// This intrinsic corresponds to the <c> VCVTPS2DQ / CVTPS2DQ </c> instruction.
///
/// \param __a
/// A 128-bit vector of [4 x float].
@@ -1746,7 +3301,8 @@ _mm_cvtps_epi32(__m128 __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCVTTPS2DQ / CVTTPS2DQ instruction.
+/// This intrinsic corresponds to the <c> VCVTTPS2DQ / CVTTPS2DQ </c>
+/// instruction.
///
/// \param __a
/// A 128-bit vector of [4 x float].
@@ -1762,7 +3318,7 @@ _mm_cvttps_epi32(__m128 __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VMOVD / MOVD instruction.
+/// This intrinsic corresponds to the <c> VMOVD / MOVD </c> instruction.
///
/// \param __a
/// A 32-bit signed integer operand.
@@ -1779,7 +3335,7 @@ _mm_cvtsi32_si128(int __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VMOVQ / MOVQ instruction.
+/// This intrinsic corresponds to the <c> VMOVQ / MOVQ </c> instruction.
///
/// \param __a
/// A 64-bit signed integer operand containing the value to be converted.
@@ -1796,7 +3352,7 @@ _mm_cvtsi64_si128(long long __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VMOVD / MOVD instruction.
+/// This intrinsic corresponds to the <c> VMOVD / MOVD </c> instruction.
///
/// \param __a
/// A vector of [4 x i32]. The least significant 32 bits are moved to the
@@ -1815,7 +3371,7 @@ _mm_cvtsi128_si32(__m128i __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VMOVQ / MOVQ instruction.
+/// This intrinsic corresponds to the <c> VMOVQ / MOVQ </c> instruction.
///
/// \param __a
/// A vector of [2 x i64]. The least significant 64 bits are moved to the
@@ -1833,7 +3389,7 @@ _mm_cvtsi128_si64(__m128i __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VMOVDQA / MOVDQA instruction.
+/// This intrinsic corresponds to the <c> VMOVDQA / MOVDQA </c> instruction.
///
/// \param __p
/// An aligned pointer to a memory location containing integer values.
@@ -1849,7 +3405,7 @@ _mm_load_si128(__m128i const *__p)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VMOVDQU / MOVDQU instruction.
+/// This intrinsic corresponds to the <c> VMOVDQU / MOVDQU </c> instruction.
///
/// \param __p
/// A pointer to a memory location containing integer values.
@@ -1868,7 +3424,7 @@ _mm_loadu_si128(__m128i const *__p)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VMOVQ / MOVQ instruction.
+/// This intrinsic corresponds to the <c> VMOVQ / MOVQ </c> instruction.
///
/// \param __p
/// A 128-bit vector of [2 x i64]. Bits [63:0] are written to bits [63:0] of
@@ -2154,42 +3710,170 @@ _mm_set1_epi8(char __b)
return (__m128i)(__v16qi){ __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
+/// with the specified 64-bit integral values.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VPUNPCKLQDQ / PUNPCKLQDQ </c>
+/// instruction.
+///
+/// \param __q0
+/// A 64-bit integral value used to initialize the lower 64 bits of the
+/// result.
+/// \param __q1
+/// A 64-bit integral value used to initialize the upper 64 bits of the
+/// result.
+/// \returns An initialized 128-bit integer vector.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_setr_epi64(__m64 __q0, __m64 __q1)
{
return (__m128i){ (long long)__q0, (long long)__q1 };
}
+/// \brief Constructs a 128-bit integer vector, initialized in reverse order
+/// with the specified 32-bit integral values.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic is a utility function and does not correspond to a specific
+/// instruction.
+///
+/// \param __i0
+/// A 32-bit integral value used to initialize bits [31:0] of the result.
+/// \param __i1
+/// A 32-bit integral value used to initialize bits [63:32] of the result.
+/// \param __i2
+/// A 32-bit integral value used to initialize bits [95:64] of the result.
+/// \param __i3
+/// A 32-bit integral value used to initialize bits [127:96] of the result.
+/// \returns An initialized 128-bit integer vector.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_setr_epi32(int __i0, int __i1, int __i2, int __i3)
{
return (__m128i)(__v4si){ __i0, __i1, __i2, __i3};
}
+/// \brief Constructs a 128-bit integer vector, initialized in reverse order
+/// with the specified 16-bit integral values.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic is a utility function and does not correspond to a specific
+/// instruction.
+///
+/// \param __w0
+/// A 16-bit integral value used to initialize bits [15:0] of the result.
+/// \param __w1
+/// A 16-bit integral value used to initialize bits [31:16] of the result.
+/// \param __w2
+/// A 16-bit integral value used to initialize bits [47:32] of the result.
+/// \param __w3
+/// A 16-bit integral value used to initialize bits [63:48] of the result.
+/// \param __w4
+/// A 16-bit integral value used to initialize bits [79:64] of the result.
+/// \param __w5
+/// A 16-bit integral value used to initialize bits [95:80] of the result.
+/// \param __w6
+/// A 16-bit integral value used to initialize bits [111:96] of the result.
+/// \param __w7
+/// A 16-bit integral value used to initialize bits [127:112] of the result.
+/// \returns An initialized 128-bit integer vector.
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 };
}
+/// \brief Constructs a 128-bit integer vector, initialized in reverse order
+/// with the specified 8-bit integral values.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic is a utility function and does not correspond to a specific
+/// instruction.
+///
+/// \param __b0
+/// An 8-bit integral value used to initialize bits [7:0] of the result.
+/// \param __b1
+/// An 8-bit integral value used to initialize bits [15:8] of the result.
+/// \param __b2
+/// An 8-bit integral value used to initialize bits [23:16] of the result.
+/// \param __b3
+/// An 8-bit integral value used to initialize bits [31:24] of the result.
+/// \param __b4
+/// An 8-bit integral value used to initialize bits [39:32] of the result.
+/// \param __b5
+/// An 8-bit integral value used to initialize bits [47:40] of the result.
+/// \param __b6
+/// An 8-bit integral value used to initialize bits [55:48] of the result.
+/// \param __b7
+/// An 8-bit integral value used to initialize bits [63:56] of the result.
+/// \param __b8
+/// An 8-bit integral value used to initialize bits [71:64] of the result.
+/// \param __b9
+/// An 8-bit integral value used to initialize bits [79:72] of the result.
+/// \param __b10
+/// An 8-bit integral value used to initialize bits [87:80] of the result.
+/// \param __b11
+/// An 8-bit integral value used to initialize bits [95:88] of the result.
+/// \param __b12
+/// An 8-bit integral value used to initialize bits [103:96] of the result.
+/// \param __b13
+/// An 8-bit integral value used to initialize bits [111:104] of the result.
+/// \param __b14
+/// An 8-bit integral value used to initialize bits [119:112] of the result.
+/// \param __b15
+/// An 8-bit integral value used to initialize bits [127:120] of the result.
+/// \returns An initialized 128-bit integer vector.
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 };
}
+/// \brief Creates a 128-bit integer vector initialized to zero.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VXORPS / XORPS </c> instruction.
+///
+/// \returns An initialized 128-bit integer vector with all elements set to
+/// zero.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_setzero_si128(void)
{
return (__m128i){ 0LL, 0LL };
}
+/// \brief Stores a 128-bit integer vector to a memory location aligned on a
+/// 128-bit boundary.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMOVAPS / MOVAPS </c> instruction.
+///
+/// \param __p
+/// A pointer to an aligned memory location that will receive the integer
+/// values.
+/// \param __b
+/// A 128-bit integer vector containing the values to be moved.
static __inline__ void __DEFAULT_FN_ATTRS
_mm_store_si128(__m128i *__p, __m128i __b)
{
*__p = __b;
}
+/// \brief Stores a 128-bit integer vector to an unaligned memory location.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMOVUPS / MOVUPS </c> instruction.
+///
+/// \param __p
+/// A pointer to a memory location that will receive the integer values.
+/// \param __b
+/// A 128-bit integer vector containing the values to be moved.
static __inline__ void __DEFAULT_FN_ATTRS
_mm_storeu_si128(__m128i *__p, __m128i __b)
{
@@ -2199,12 +3883,45 @@ _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
+/// 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 used again
+/// soon). Exception and trap behavior for elements not selected for storage
+/// to memory are implementation dependent.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMASKMOVDQU / MASKMOVDQU </c>
+/// instruction.
+///
+/// \param __d
+/// A 128-bit integer vector containing the values to be moved.
+/// \param __n
+/// A 128-bit integer vector containing the mask. The most significant bit of
+/// each byte represents the mask bits.
+/// \param __p
+/// A pointer to an unaligned 128-bit memory location where the specified
+/// values are moved.
static __inline__ void __DEFAULT_FN_ATTRS
_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
+/// a memory location.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMOVLPS / MOVLPS </c> instruction.
+///
+/// \param __p
+/// A pointer to a 64-bit memory location that will receive the lower 64 bits
+/// of the integer vector parameter.
+/// \param __a
+/// A 128-bit integer vector of [2 x i64]. The lower 64 bits contain the
+/// value to be stored.
static __inline__ void __DEFAULT_FN_ATTRS
_mm_storel_epi64(__m128i *__p, __m128i __a)
{
@@ -2214,18 +3931,54 @@ _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
+/// aligned memory location. To minimize caching, the data is flagged as
+/// non-temporal (unlikely to be used again soon).
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMOVNTPS / MOVNTPS </c> instruction.
+///
+/// \param __p
+/// A pointer to the 128-bit aligned memory location used to store the value.
+/// \param __a
+/// A vector of [2 x double] containing the 64-bit values to be stored.
static __inline__ void __DEFAULT_FN_ATTRS
_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.
+/// To minimize caching, the data is flagged as non-temporal (unlikely to be
+/// used again soon).
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMOVNTPS / MOVNTPS </c> instruction.
+///
+/// \param __p
+/// A pointer to the 128-bit aligned memory location used to store the value.
+/// \param __a
+/// A 128-bit integer vector containing the values to be stored.
static __inline__ void __DEFAULT_FN_ATTRS
_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. To
+/// minimize caching, the data is flagged as non-temporal (unlikely to be
+/// used again soon).
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> MOVNTI </c> instruction.
+///
+/// \param __p
+/// 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
_mm_stream_si32(int *__p, int __a)
{
@@ -2233,6 +3986,18 @@ _mm_stream_si32(int *__p, int __a)
}
#ifdef __x86_64__
+/// \brief 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).
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> MOVNTIQ </c> instruction.
+///
+/// \param __p
+/// 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
_mm_stream_si64(long long *__p, long long __a)
{
@@ -2240,42 +4005,154 @@ _mm_stream_si64(long long *__p, long long __a)
}
#endif
-static __inline__ void __DEFAULT_FN_ATTRS
-_mm_clflush(void const *__p)
-{
- __builtin_ia32_clflush(__p);
-}
+#if defined(__cplusplus)
+extern "C" {
+#endif
-static __inline__ void __DEFAULT_FN_ATTRS
-_mm_lfence(void)
-{
- __builtin_ia32_lfence();
-}
+/// \brief The cache line containing \a __p is flushed and invalidated from all
+/// caches in the coherency domain.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> CLFLUSH </c> instruction.
+///
+/// \param __p
+/// A pointer to the memory location used to identify the cache line to be
+/// flushed.
+void _mm_clflush(void const *);
-static __inline__ void __DEFAULT_FN_ATTRS
-_mm_mfence(void)
-{
- __builtin_ia32_mfence();
-}
+/// \brief 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> LFENCE </c> instruction.
+///
+void _mm_lfence(void);
+/// \brief 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> MFENCE </c> instruction.
+///
+void _mm_mfence(void);
+
+#if defined(__cplusplus)
+} // extern "C"
+#endif
+
+/// \brief 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VPACKSSWB / PACKSSWB </c> instruction.
+///
+/// \param __a
+/// A 128-bit integer vector of [8 x i16]. Each 16-bit element is treated as
+/// a signed integer and is converted to a 8-bit signed integer with
+/// saturation. Values greater than 0x7F are saturated to 0x7F. Values less
+/// than 0x80 are saturated to 0x80. The converted [8 x i8] values are
+/// written to the lower 64 bits of the result.
+/// \param __b
+/// A 128-bit integer vector of [8 x i16]. Each 16-bit element is treated as
+/// a signed integer and is converted to a 8-bit signed integer with
+/// saturation. Values greater than 0x7F are saturated to 0x7F. Values less
+/// than 0x80 are saturated to 0x80. The converted [8 x i8] values are
+/// written to the higher 64 bits of the result.
+/// \returns A 128-bit vector of [16 x i8] containing the converted values.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_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
+/// 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VPACKSSDW / PACKSSDW </c> instruction.
+///
+/// \param __a
+/// A 128-bit integer vector of [4 x i32]. Each 32-bit element is treated as
+/// a signed integer and is converted to a 16-bit signed integer with
+/// saturation. Values greater than 0x7FFF are saturated to 0x7FFF. Values
+/// less than 0x8000 are saturated to 0x8000. The converted [4 x i16] values
+/// are written to the lower 64 bits of the result.
+/// \param __b
+/// A 128-bit integer vector of [4 x i32]. Each 32-bit element is treated as
+/// a signed integer and is converted to a 16-bit signed integer with
+/// saturation. Values greater than 0x7FFF are saturated to 0x7FFF. Values
+/// less than 0x8000 are saturated to 0x8000. The converted [4 x i16] values
+/// are written to the higher 64 bits of the result.
+/// \returns A 128-bit vector of [8 x i16] containing the converted values.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_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
+/// 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VPACKUSWB / PACKUSWB </c> instruction.
+///
+/// \param __a
+/// A 128-bit integer vector of [8 x i16]. Each 16-bit element is treated as
+/// a signed integer and is converted to an 8-bit unsigned integer with
+/// saturation. Values greater than 0xFF are saturated to 0xFF. Values less
+/// than 0x00 are saturated to 0x00. The converted [8 x i8] values are
+/// written to the lower 64 bits of the result.
+/// \param __b
+/// A 128-bit integer vector of [8 x i16]. Each 16-bit element is treated as
+/// a signed integer and is converted to an 8-bit unsigned integer with
+/// saturation. Values greater than 0xFF are saturated to 0xFF. Values less
+/// than 0x00 are saturated to 0x00. The converted [8 x i8] values are
+/// written to the higher 64 bits of the result.
+/// \returns A 128-bit vector of [16 x i8] containing the converted values.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_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
+/// the immediate-value parameter as a selector.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VPEXTRW / PEXTRW </c> instruction.
+///
+/// \param __a
+/// A 128-bit integer vector.
+/// \param __imm
+/// An immediate value. Bits [3:0] selects values from \a __a to be assigned
+/// to bits[15:0] of the result. \n
+/// 000: assign values from bits [15:0] of \a __a. \n
+/// 001: assign values from bits [31:16] of \a __a. \n
+/// 010: assign values from bits [47:32] of \a __a. \n
+/// 011: assign values from bits [63:48] of \a __a. \n
+/// 100: assign values from bits [79:64] of \a __a. \n
+/// 101: assign values from bits [95:80] of \a __a. \n
+/// 110: assign values from bits [111:96] of \a __a. \n
+/// 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)
{
@@ -2283,6 +4160,26 @@ _mm_extract_epi16(__m128i __a, int __imm)
return (unsigned short)__b[__imm & 7];
}
+/// \brief 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VPINSRW / PINSRW </c> instruction.
+///
+/// \param __a
+/// A 128-bit integer vector of [8 x i16]. This vector is copied to the
+/// result and then one of the eight elements in the result is replaced by
+/// the lower 16 bits of \a __b.
+/// \param __b
+/// An integer. The lower 16 bits of this parameter are written to the
+/// result beginning at an offset specified by \a __imm.
+/// \param __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)
{
@@ -2291,18 +4188,85 @@ _mm_insert_epi16(__m128i __a, int __b, int __imm)
return (__m128i)__c;
}
+/// \brief 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VPMOVMSKB / PMOVMSKB </c> instruction.
+///
+/// \param __a
+/// A 128-bit integer vector containing the values with bits to be extracted.
+/// \returns The most significant bits from each 8-bit element in \a __a,
+/// written to bits [15:0]. The other bits are assigned zeros.
static __inline__ int __DEFAULT_FN_ATTRS
_mm_movemask_epi8(__m128i __a)
{
return __builtin_ia32_pmovmskb128((__v16qi)__a);
}
+/// \brief 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// \code
+/// __m128i _mm_shuffle_epi32(__m128i a, const int imm);
+/// \endcode
+///
+/// This intrinsic corresponds to the <c> VPSHUFD / PSHUFD </c> instruction.
+///
+/// \param a
+/// A 128-bit integer vector containing the values to be copied.
+/// \param imm
+/// An immediate value containing an 8-bit value specifying which elements to
+/// copy from a. The destinations within the 128-bit destination are assigned
+/// values as follows: \n
+/// Bits [1:0] are used to assign values to bits [31:0] of the result. \n
+/// Bits [3:2] are used to assign values to bits [63:32] of the result. \n
+/// Bits [5:4] are used to assign values to bits [95:64] of the result. \n
+/// Bits [7:6] are used to assign values to bits [127:96] of the result. \n
+/// Bit value assignments: \n
+/// 00: assign values from bits [31:0] of \a a. \n
+/// 01: assign values from bits [63:32] of \a a. \n
+/// 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); })
+/// \brief 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// \code
+/// __m128i _mm_shufflelo_epi16(__m128i a, const int imm);
+/// \endcode
+///
+/// This intrinsic corresponds to the <c> VPSHUFLW / PSHUFLW </c> instruction.
+///
+/// \param a
+/// A 128-bit integer vector of [8 x i16]. Bits [127:64] are copied to bits
+/// [127:64] of the result.
+/// \param imm
+/// An 8-bit immediate value specifying which elements to copy from \a a. \n
+/// Bits[1:0] are used to assign values to bits [15:0] of the result. \n
+/// Bits[3:2] are used to assign values to bits [31:16] of the result. \n
+/// Bits[5:4] are used to assign values to bits [47:32] of the result. \n
+/// Bits[7:6] are used to assign values to bits [63:48] of the result. \n
+/// Bit value assignments: \n
+/// 00: assign values from bits [15:0] of \a a. \n
+/// 01: assign values from bits [31:16] of \a a. \n
+/// 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(), \
@@ -2310,6 +4274,33 @@ _mm_movemask_epi8(__m128i __a)
((imm) >> 4) & 0x3, ((imm) >> 6) & 0x3, \
4, 5, 6, 7); })
+/// \brief 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// \code
+/// __m128i _mm_shufflehi_epi16(__m128i a, const int imm);
+/// \endcode
+///
+/// This intrinsic corresponds to the <c> VPSHUFHW / PSHUFHW </c> instruction.
+///
+/// \param a
+/// A 128-bit integer vector of [8 x i16]. Bits [63:0] are copied to bits
+/// [63:0] of the result.
+/// \param imm
+/// An 8-bit immediate value specifying which elements to copy from \a a. \n
+/// Bits[1:0] are used to assign values to bits [79:64] of the result. \n
+/// Bits[3:2] are used to assign values to bits [95:80] of the result. \n
+/// Bits[5:4] are used to assign values to bits [111:96] of the result. \n
+/// Bits[7:6] are used to assign values to bits [127:112] of the result. \n
+/// Bit value assignments: \n
+/// 00: assign values from bits [79:64] of \a a. \n
+/// 01: assign values from bits [95:80] of \a a. \n
+/// 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(), \
@@ -2319,137 +4310,480 @@ _mm_movemask_epi8(__m128i __a)
4 + (((imm) >> 4) & 0x3), \
4 + (((imm) >> 6) & 0x3)); })
+/// \brief 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>
+///
+/// This intrinsic corresponds to the <c> VPUNPCKHBW / PUNPCKHBW </c>
+/// instruction.
+///
+/// \param __a
+/// A 128-bit vector of [16 x i8].
+/// Bits [71:64] are written to bits [7:0] of the result. \n
+/// Bits [79:72] are written to bits [23:16] of the result. \n
+/// Bits [87:80] are written to bits [39:32] of the result. \n
+/// Bits [95:88] are written to bits [55:48] of the result. \n
+/// Bits [103:96] are written to bits [71:64] of the result. \n
+/// Bits [111:104] are written to bits [87:80] of the result. \n
+/// Bits [119:112] are written to bits [103:96] of the result. \n
+/// Bits [127:120] are written to bits [119:112] of the result.
+/// \param __b
+/// A 128-bit vector of [16 x i8]. \n
+/// Bits [71:64] are written to bits [15:8] of the result. \n
+/// Bits [79:72] are written to bits [31:24] of the result. \n
+/// Bits [87:80] are written to bits [47:40] of the result. \n
+/// Bits [95:88] are written to bits [63:56] of the result. \n
+/// Bits [103:96] are written to bits [79:72] of the result. \n
+/// Bits [111:104] are written to bits [95:88] of the result. \n
+/// Bits [119:112] are written to bits [111:104] of the result. \n
+/// Bits [127:120] are written to bits [127:120] of the result.
+/// \returns A 128-bit vector of [16 x i8] containing the interleaved values.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_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
+/// [8 x i16] and interleaves them into a 128-bit vector of [8 x i16].
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VPUNPCKHWD / PUNPCKHWD </c>
+/// instruction.
+///
+/// \param __a
+/// A 128-bit vector of [8 x i16].
+/// Bits [79:64] are written to bits [15:0] of the result. \n
+/// Bits [95:80] are written to bits [47:32] of the result. \n
+/// Bits [111:96] are written to bits [79:64] of the result. \n
+/// Bits [127:112] are written to bits [111:96] of the result.
+/// \param __b
+/// A 128-bit vector of [8 x i16].
+/// Bits [79:64] are written to bits [31:16] of the result. \n
+/// Bits [95:80] are written to bits [63:48] of the result. \n
+/// Bits [111:96] are written to bits [95:80] of the result. \n
+/// Bits [127:112] are written to bits [127:112] of the result.
+/// \returns A 128-bit vector of [8 x i16] containing the interleaved values.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_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
+/// [4 x i32] and interleaves them into a 128-bit vector of [4 x i32].
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VPUNPCKHDQ / PUNPCKHDQ </c>
+/// instruction.
+///
+/// \param __a
+/// A 128-bit vector of [4 x i32]. \n
+/// Bits [95:64] are written to bits [31:0] of the destination. \n
+/// Bits [127:96] are written to bits [95:64] of the destination.
+/// \param __b
+/// A 128-bit vector of [4 x i32]. \n
+/// Bits [95:64] are written to bits [64:32] of the destination. \n
+/// Bits [127:96] are written to bits [127:96] of the destination.
+/// \returns A 128-bit vector of [4 x i32] containing the interleaved values.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_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].
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VPUNPCKHQDQ / PUNPCKHQDQ </c>
+/// instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x i64]. \n
+/// Bits [127:64] are written to bits [63:0] of the destination.
+/// \param __b
+/// A 128-bit vector of [2 x i64]. \n
+/// Bits [127:64] are written to bits [127:64] of the destination.
+/// \returns A 128-bit vector of [2 x i64] containing the interleaved values.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_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
+/// [16 x i8] and interleaves them into a 128-bit vector of [16 x i8].
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VPUNPCKLBW / PUNPCKLBW </c>
+/// instruction.
+///
+/// \param __a
+/// A 128-bit vector of [16 x i8]. \n
+/// Bits [7:0] are written to bits [7:0] of the result. \n
+/// Bits [15:8] are written to bits [23:16] of the result. \n
+/// Bits [23:16] are written to bits [39:32] of the result. \n
+/// Bits [31:24] are written to bits [55:48] of the result. \n
+/// Bits [39:32] are written to bits [71:64] of the result. \n
+/// Bits [47:40] are written to bits [87:80] of the result. \n
+/// Bits [55:48] are written to bits [103:96] of the result. \n
+/// Bits [63:56] are written to bits [119:112] of the result.
+/// \param __b
+/// A 128-bit vector of [16 x i8].
+/// Bits [7:0] are written to bits [15:8] of the result. \n
+/// Bits [15:8] are written to bits [31:24] of the result. \n
+/// Bits [23:16] are written to bits [47:40] of the result. \n
+/// Bits [31:24] are written to bits [63:56] of the result. \n
+/// Bits [39:32] are written to bits [79:72] of the result. \n
+/// Bits [47:40] are written to bits [95:88] of the result. \n
+/// Bits [55:48] are written to bits [111:104] of the result. \n
+/// Bits [63:56] are written to bits [127:120] of the result.
+/// \returns A 128-bit vector of [16 x i8] containing the interleaved values.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_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
+/// vectors of [8 x i16] and interleaves them into a 128-bit vector of
+/// [8 x i16].
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VPUNPCKLWD / PUNPCKLWD </c>
+/// instruction.
+///
+/// \param __a
+/// A 128-bit vector of [8 x i16].
+/// Bits [15:0] are written to bits [15:0] of the result. \n
+/// Bits [31:16] are written to bits [47:32] of the result. \n
+/// Bits [47:32] are written to bits [79:64] of the result. \n
+/// Bits [63:48] are written to bits [111:96] of the result.
+/// \param __b
+/// A 128-bit vector of [8 x i16].
+/// Bits [15:0] are written to bits [31:16] of the result. \n
+/// Bits [31:16] are written to bits [63:48] of the result. \n
+/// Bits [47:32] are written to bits [95:80] of the result. \n
+/// Bits [63:48] are written to bits [127:112] of the result.
+/// \returns A 128-bit vector of [8 x i16] containing the interleaved values.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_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
+/// [4 x i32] and interleaves them into a 128-bit vector of [4 x i32].
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VPUNPCKLDQ / PUNPCKLDQ </c>
+/// instruction.
+///
+/// \param __a
+/// A 128-bit vector of [4 x i32]. \n
+/// Bits [31:0] are written to bits [31:0] of the destination. \n
+/// Bits [63:32] are written to bits [95:64] of the destination.
+/// \param __b
+/// A 128-bit vector of [4 x i32]. \n
+/// Bits [31:0] are written to bits [64:32] of the destination. \n
+/// Bits [63:32] are written to bits [127:96] of the destination.
+/// \returns A 128-bit vector of [4 x i32] containing the interleaved values.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_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
+/// [2 x i64] and interleaves them into a 128-bit vector of [2 x i64].
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VPUNPCKLQDQ / PUNPCKLQDQ </c>
+/// instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x i64]. \n
+/// Bits [63:0] are written to bits [63:0] of the destination. \n
+/// \param __b
+/// A 128-bit vector of [2 x i64]. \n
+/// Bits [63:0] are written to bits [127:64] of the destination. \n
+/// \returns A 128-bit vector of [2 x i64] containing the interleaved values.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_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
+/// integer.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic has no corresponding instruction.
+///
+/// \param __a
+/// A 128-bit integer vector operand. The lower 64 bits are moved to the
+/// destination.
+/// \returns A 64-bit integer containing the lower 64 bits of the parameter.
static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_movepi64_pi64(__m128i __a)
{
return (__m64)__a[0];
}
+/// \brief 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.
+///
+/// \param __a
+/// A 64-bit value.
+/// \returns A 128-bit integer vector. The lower 64 bits contain the value from
+/// the operand. The upper 64 bits are assigned zeros.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_movpi64_epi64(__m64 __a)
{
return (__m128i){ (long long)__a, 0 };
}
+/// \brief Moves the lower 64 bits of a 128-bit integer vector to a 128-bit
+/// integer vector, zeroing the upper bits.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMOVQ / MOVQ </c> instruction.
+///
+/// \param __a
+/// A 128-bit integer vector operand. The lower 64 bits are moved to the
+/// destination.
+/// \returns A 128-bit integer vector. The lower 64 bits contain the value from
+/// the operand. The upper 64 bits are assigned zeros.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_move_epi64(__m128i __a)
{
return __builtin_shufflevector((__v2di)__a, (__m128i){ 0 }, 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
+/// double].
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VUNPCKHPD / UNPCKHPD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double]. \n
+/// Bits [127:64] are written to bits [63:0] of the destination.
+/// \param __b
+/// A 128-bit vector of [2 x double]. \n
+/// Bits [127:64] are written to bits [127:64] of the destination.
+/// \returns A 128-bit vector of [2 x double] containing the interleaved values.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_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
+/// of [2 x double] and interleaves them into a 128-bit vector of [2 x
+/// double].
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VUNPCKLPD / UNPCKLPD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double]. \n
+/// Bits [63:0] are written to bits [63:0] of the destination.
+/// \param __b
+/// A 128-bit vector of [2 x double]. \n
+/// Bits [63:0] are written to bits [127:64] of the destination.
+/// \returns A 128-bit vector of [2 x double] containing the interleaved values.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_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
+/// vector of [2 x double], zero-extends the value, and writes it to the
+/// low-order bits of the destination.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> VMOVMSKPD / MOVMSKPD </c> instruction.
+///
+/// \param __a
+/// A 128-bit vector of [2 x double] containing the values with sign bits to
+/// be extracted.
+/// \returns The sign bits from each of the double-precision elements in \a __a,
+/// written to bits [1:0]. The remaining bits are assigned values of zero.
static __inline__ int __DEFAULT_FN_ATTRS
_mm_movemask_pd(__m128d __a)
{
return __builtin_ia32_movmskpd((__v2df)__a);
}
+
+/// \brief 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// \code
+/// __m128d _mm_shuffle_pd(__m128d a, __m128d b, const int i);
+/// \endcode
+///
+/// This intrinsic corresponds to the <c> VSHUFPD / SHUFPD </c> instruction.
+///
+/// \param a
+/// A 128-bit vector of [2 x double].
+/// \param b
+/// 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
+/// 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)); })
+/// \brief 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>
+///
+/// This intrinsic has no corresponding instruction.
+///
+/// \param __a
+/// A 128-bit floating-point vector of [2 x double].
+/// \returns A 128-bit floating-point vector of [4 x float] containing the same
+/// bitwise pattern as the parameter.
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_castpd_ps(__m128d __a)
{
return (__m128)__a;
}
+/// \brief Casts a 128-bit floating-point vector of [2 x double] into a 128-bit
+/// integer vector.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic has no corresponding instruction.
+///
+/// \param __a
+/// A 128-bit floating-point vector of [2 x double].
+/// \returns A 128-bit integer vector containing the same bitwise pattern as the
+/// parameter.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_castpd_si128(__m128d __a)
{
return (__m128i)__a;
}
+/// \brief 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>
+///
+/// This intrinsic has no corresponding instruction.
+///
+/// \param __a
+/// A 128-bit floating-point vector of [4 x float].
+/// \returns A 128-bit floating-point vector of [2 x double] containing the same
+/// bitwise pattern as the parameter.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_castps_pd(__m128 __a)
{
return (__m128d)__a;
}
+/// \brief Casts a 128-bit floating-point vector of [4 x float] into a 128-bit
+/// integer vector.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic has no corresponding instruction.
+///
+/// \param __a
+/// A 128-bit floating-point vector of [4 x float].
+/// \returns A 128-bit integer vector containing the same bitwise pattern as the
+/// parameter.
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_castps_si128(__m128 __a)
{
return (__m128i)__a;
}
+/// \brief Casts a 128-bit integer vector into a 128-bit floating-point vector
+/// of [4 x float].
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic has no corresponding instruction.
+///
+/// \param __a
+/// A 128-bit integer vector.
+/// \returns A 128-bit floating-point vector of [4 x float] containing the same
+/// bitwise pattern as the parameter.
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_castsi128_ps(__m128i __a)
{
return (__m128)__a;
}
+/// \brief Casts a 128-bit integer vector into a 128-bit floating-point vector
+/// of [2 x double].
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic has no corresponding instruction.
+///
+/// \param __a
+/// A 128-bit integer vector.
+/// \returns A 128-bit floating-point vector of [2 x double] containing the same
+/// bitwise pattern as the parameter.
static __inline__ __m128d __DEFAULT_FN_ATTRS
_mm_castsi128_pd(__m128i __a)
{
return (__m128d)__a;
}
-static __inline__ void __DEFAULT_FN_ATTRS
-_mm_pause(void)
-{
- __builtin_ia32_pause();
-}
+#if defined(__cplusplus)
+extern "C" {
+#endif
+/// \brief Indicates that a spin loop is being executed for the purposes of
+/// optimizing power consumption during the loop.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> PAUSE </c> instruction.
+///
+void _mm_pause(void);
+
+#if defined(__cplusplus)
+} // extern "C"
+#endif
#undef __DEFAULT_FN_ATTRS
#define _MM_SHUFFLE2(x, y) (((x) << 1) | (y))
diff --git a/lib/Headers/f16cintrin.h b/lib/Headers/f16cintrin.h
index 415bf732fb9f..180712ffc680 100644
--- a/lib/Headers/f16cintrin.h
+++ b/lib/Headers/f16cintrin.h
@@ -37,7 +37,7 @@
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCVTPH2PS instruction.
+/// This intrinsic corresponds to the <c> VCVTPH2PS </c> instruction.
///
/// \param __a
/// A 16-bit half-precision float value.
@@ -59,17 +59,17 @@ _cvtsh_ss(unsigned short __a)
/// unsigned short _cvtss_sh(float a, const int imm);
/// \endcode
///
-/// This intrinsic corresponds to the \c VCVTPS2PH instruction.
+/// This intrinsic corresponds to the <c> VCVTPS2PH </c> instruction.
///
/// \param a
/// A 32-bit single-precision float value to be converted to a 16-bit
/// half-precision float value.
/// \param imm
-/// An immediate value controlling rounding using bits [2:0]:
-/// 000: Nearest
-/// 001: Down
-/// 010: Up
-/// 011: Truncate
+/// 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 The converted 16-bit half-precision float value.
#define _cvtss_sh(a, imm) \
@@ -85,16 +85,16 @@ _cvtsh_ss(unsigned short __a)
/// __m128i _mm_cvtps_ph(__m128 a, const int imm);
/// \endcode
///
-/// This intrinsic corresponds to the \c VCVTPS2PH instruction.
+/// This intrinsic corresponds to the <c> VCVTPS2PH </c> instruction.
///
/// \param a
/// A 128-bit vector containing 32-bit float values.
/// \param imm
-/// An immediate value controlling rounding using bits [2:0]:
-/// 000: Nearest
-/// 001: Down
-/// 010: Up
-/// 011: Truncate
+/// 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 converted 16-bit half-precision float
/// values. The lower 64 bits are used to store the converted 16-bit
@@ -107,7 +107,7 @@ _cvtsh_ss(unsigned short __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCVTPH2PS instruction.
+/// This intrinsic corresponds to the <c> VCVTPH2PS </c> instruction.
///
/// \param __a
/// A 128-bit vector containing 16-bit half-precision float values. The lower
diff --git a/lib/Headers/float.h b/lib/Headers/float.h
index a28269ebebbe..0f453d87cbcb 100644
--- a/lib/Headers/float.h
+++ b/lib/Headers/float.h
@@ -27,9 +27,12 @@
/* If we're on MinGW, fall back to the system's float.h, which might have
* additional definitions provided for Windows.
* For more details see http://msdn.microsoft.com/en-us/library/y0ybw9fy.aspx
+ *
+ * Also fall back on Darwin to allow additional definitions and
+ * implementation-defined values.
*/
-#if (defined(__MINGW32__) || defined(_MSC_VER)) && __STDC_HOSTED__ && \
- __has_include_next(<float.h>)
+#if (defined(__APPLE__) || (defined(__MINGW32__) || defined(_MSC_VER))) && \
+ __STDC_HOSTED__ && __has_include_next(<float.h>)
# include_next <float.h>
/* Undefine anything that we'll be redefining below. */
diff --git a/lib/Headers/fxsrintrin.h b/lib/Headers/fxsrintrin.h
index ac6026aa5ba2..786081ca8eab 100644
--- a/lib/Headers/fxsrintrin.h
+++ b/lib/Headers/fxsrintrin.h
@@ -30,25 +30,75 @@
#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("fxsr")))
+/// \brief 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>
+///
+/// This intrinsic corresponds to the <c> FXSAVE </c> instruction.
+///
+/// \param __p
+/// A pointer to a 512-byte memory region. The beginning of this memory
+/// region should be aligned on a 16-byte boundary.
static __inline__ void __DEFAULT_FN_ATTRS
-_fxsave(void *__p) {
+_fxsave(void *__p)
+{
return __builtin_ia32_fxsave(__p);
}
+/// \brief 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> FXRSTOR </c> instruction.
+///
+/// \param __p
+/// A pointer to a 512-byte memory region. The beginning of this memory
+/// region should be aligned on a 16-byte boundary.
static __inline__ void __DEFAULT_FN_ATTRS
-_fxsave64(void *__p) {
- return __builtin_ia32_fxsave64(__p);
+_fxrstor(void *__p)
+{
+ return __builtin_ia32_fxrstor(__p);
}
+#ifdef __x86_64__
+/// \brief 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>
+///
+/// This intrinsic corresponds to the <c> FXSAVE64 </c> instruction.
+///
+/// \param __p
+/// A pointer to a 512-byte memory region. The beginning of this memory
+/// region should be aligned on a 16-byte boundary.
static __inline__ void __DEFAULT_FN_ATTRS
-_fxrstor(void *__p) {
- return __builtin_ia32_fxrstor(__p);
+_fxsave64(void *__p)
+{
+ return __builtin_ia32_fxsave64(__p);
}
+/// \brief 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the <c> FXRSTOR64 </c> instruction.
+///
+/// \param __p
+/// A pointer to a 512-byte memory region. The beginning of this memory
+/// region should be aligned on a 16-byte boundary.
static __inline__ void __DEFAULT_FN_ATTRS
-_fxrstor64(void *__p) {
+_fxrstor64(void *__p)
+{
return __builtin_ia32_fxrstor64(__p);
}
+#endif
#undef __DEFAULT_FN_ATTRS
diff --git a/lib/Headers/ia32intrin.h b/lib/Headers/ia32intrin.h
index 397f3fd13e01..4928300103ad 100644
--- a/lib/Headers/ia32intrin.h
+++ b/lib/Headers/ia32intrin.h
@@ -60,12 +60,6 @@ __rdpmc(int __A) {
return __builtin_ia32_rdpmc(__A);
}
-/* __rdtsc */
-static __inline__ unsigned long long __attribute__((__always_inline__, __nodebug__))
-__rdtsc(void) {
- return __builtin_ia32_rdtsc();
-}
-
/* __rdtscp */
static __inline__ unsigned long long __attribute__((__always_inline__, __nodebug__))
__rdtscp(unsigned int *__A) {
diff --git a/lib/Headers/immintrin.h b/lib/Headers/immintrin.h
index 4b2752353d6f..7f91d49fbcec 100644
--- a/lib/Headers/immintrin.h
+++ b/lib/Headers/immintrin.h
@@ -69,9 +69,44 @@
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)
{
diff --git a/lib/Headers/intrin.h b/lib/Headers/intrin.h
index f18711ad1ecf..7c91ebaee8cb 100644
--- a/lib/Headers/intrin.h
+++ b/lib/Headers/intrin.h
@@ -34,6 +34,10 @@
#include <x86intrin.h>
#endif
+#if defined(__arm__)
+#include <armintr.h>
+#endif
+
/* For the definition of jmp_buf. */
#if __STDC_HOSTED__
#include <setjmp.h>
@@ -62,7 +66,9 @@ void __cpuid(int[4], int);
static __inline__
void __cpuidex(int[4], int, int);
void __debugbreak(void);
+static __inline__
__int64 __emul(int, int);
+static __inline__
unsigned __int64 __emulu(unsigned int, unsigned int);
void __cdecl __fastfail(unsigned int);
unsigned int __getcallerseflags(void);
@@ -93,6 +99,7 @@ static __inline__
void __movsd(unsigned long *, unsigned long const *, size_t);
static __inline__
void __movsw(unsigned short *, unsigned short const *, size_t);
+static __inline__
void __nop(void);
void __nvreg_restore_fence(void);
void __nvreg_save_fence(void);
@@ -249,10 +256,12 @@ static __inline__
unsigned long __cdecl _lrotl(unsigned long, int);
static __inline__
unsigned long __cdecl _lrotr(unsigned long, int);
-static __inline__
-void _ReadBarrier(void);
-static __inline__
-void _ReadWriteBarrier(void);
+static __inline__ void
+__attribute__((__deprecated__("use other intrinsics or C++11 atomics instead")))
+_ReadBarrier(void);
+static __inline__ void
+__attribute__((__deprecated__("use other intrinsics or C++11 atomics instead")))
+_ReadWriteBarrier(void);
static __inline__
void *_ReturnAddress(void);
unsigned int _rorx_u32(unsigned int, const unsigned int);
@@ -281,8 +290,9 @@ unsigned int _shrx_u32(unsigned int, unsigned int);
void _Store_HLERelease(long volatile *, long);
void _Store64_HLERelease(__int64 volatile *, __int64);
void _StorePointer_HLERelease(void *volatile *, void *);
-static __inline__
-void _WriteBarrier(void);
+static __inline__ void
+__attribute__((__deprecated__("use other intrinsics or C++11 atomics instead")))
+_WriteBarrier(void);
unsigned __int32 xbegin(void);
void _xend(void);
static __inline__
@@ -307,7 +317,6 @@ void __lwpval64(unsigned __int64, unsigned int, unsigned int);
unsigned __int64 __lzcnt64(unsigned __int64);
static __inline__
void __movsq(unsigned long long *, unsigned long long const *, size_t);
-__int64 __mulh(__int64, __int64);
static __inline__
unsigned __int64 __popcnt64(unsigned __int64);
static __inline__
@@ -378,30 +387,15 @@ void *_InterlockedCompareExchangePointer(void *volatile *_Destination,
void *_Exchange, void *_Comparand);
void *_InterlockedCompareExchangePointer_np(void *volatile *_Destination,
void *_Exchange, void *_Comparand);
-static __inline__
-__int64 _InterlockedDecrement64(__int64 volatile *_Addend);
-static __inline__
-__int64 _InterlockedExchange64(__int64 volatile *_Target, __int64 _Value);
-static __inline__
-__int64 _InterlockedExchangeAdd64(__int64 volatile *_Addend, __int64 _Value);
void *_InterlockedExchangePointer(void *volatile *_Target, void *_Value);
-static __inline__
-__int64 _InterlockedIncrement64(__int64 volatile *_Addend);
long _InterlockedOr_np(long volatile *_Value, long _Mask);
short _InterlockedOr16_np(short volatile *_Value, short _Mask);
-static __inline__
-__int64 _InterlockedOr64(__int64 volatile *_Value, __int64 _Mask);
__int64 _InterlockedOr64_np(__int64 volatile *_Value, __int64 _Mask);
char _InterlockedOr8_np(char volatile *_Value, char _Mask);
long _InterlockedXor_np(long volatile *_Value, long _Mask);
short _InterlockedXor16_np(short volatile *_Value, short _Mask);
-static __inline__
-__int64 _InterlockedXor64(__int64 volatile *_Value, __int64 _Mask);
__int64 _InterlockedXor64_np(__int64 volatile *_Value, __int64 _Mask);
char _InterlockedXor8_np(char volatile *_Value, char _Mask);
-static __inline__
-__int64 _mul128(__int64 _Multiplier, __int64 _Multiplicand,
- __int64 *_HighProduct);
unsigned __int64 _rorx_u64(unsigned __int64, const unsigned int);
__int64 _sarx_i64(__int64, unsigned int);
#if __STDC_HOSTED__
@@ -409,119 +403,44 @@ int __cdecl _setjmpex(jmp_buf);
#endif
unsigned __int64 _shlx_u64(unsigned __int64, unsigned int);
unsigned __int64 _shrx_u64(unsigned __int64, unsigned int);
-/*
- * Multiply two 64-bit integers and obtain a 64-bit result.
- * The low-half is returned directly and the high half is in an out parameter.
- */
-static __inline__ unsigned __int64 __DEFAULT_FN_ATTRS
-_umul128(unsigned __int64 _Multiplier, unsigned __int64 _Multiplicand,
- unsigned __int64 *_HighProduct) {
- unsigned __int128 _FullProduct =
- (unsigned __int128)_Multiplier * (unsigned __int128)_Multiplicand;
- *_HighProduct = _FullProduct >> 64;
- return _FullProduct;
-}
-static __inline__ unsigned __int64 __DEFAULT_FN_ATTRS
-__umulh(unsigned __int64 _Multiplier, unsigned __int64 _Multiplicand) {
- unsigned __int128 _FullProduct =
- (unsigned __int128)_Multiplier * (unsigned __int128)_Multiplicand;
- return _FullProduct >> 64;
-}
+static __inline__
+__int64 __mulh(__int64, __int64);
+static __inline__
+unsigned __int64 __umulh(unsigned __int64, unsigned __int64);
+static __inline__
+__int64 _mul128(__int64, __int64, __int64*);
+static __inline__
+unsigned __int64 _umul128(unsigned __int64,
+ unsigned __int64,
+ unsigned __int64*);
#endif /* __x86_64__ */
-/*----------------------------------------------------------------------------*\
-|* Multiplication
-\*----------------------------------------------------------------------------*/
-static __inline__ __int64 __DEFAULT_FN_ATTRS
-__emul(int __in1, int __in2) {
- return (__int64)__in1 * (__int64)__in2;
-}
-static __inline__ unsigned __int64 __DEFAULT_FN_ATTRS
-__emulu(unsigned int __in1, unsigned int __in2) {
- return (unsigned __int64)__in1 * (unsigned __int64)__in2;
-}
-/*----------------------------------------------------------------------------*\
-|* Bit Twiddling
-\*----------------------------------------------------------------------------*/
-static __inline__ unsigned char __DEFAULT_FN_ATTRS
-_rotl8(unsigned char _Value, unsigned char _Shift) {
- _Shift &= 0x7;
- return _Shift ? (_Value << _Shift) | (_Value >> (8 - _Shift)) : _Value;
-}
-static __inline__ unsigned char __DEFAULT_FN_ATTRS
-_rotr8(unsigned char _Value, unsigned char _Shift) {
- _Shift &= 0x7;
- return _Shift ? (_Value >> _Shift) | (_Value << (8 - _Shift)) : _Value;
-}
-static __inline__ unsigned short __DEFAULT_FN_ATTRS
-_rotl16(unsigned short _Value, unsigned char _Shift) {
- _Shift &= 0xf;
- return _Shift ? (_Value << _Shift) | (_Value >> (16 - _Shift)) : _Value;
-}
-static __inline__ unsigned short __DEFAULT_FN_ATTRS
-_rotr16(unsigned short _Value, unsigned char _Shift) {
- _Shift &= 0xf;
- return _Shift ? (_Value >> _Shift) | (_Value << (16 - _Shift)) : _Value;
-}
-static __inline__ unsigned int __DEFAULT_FN_ATTRS
-_rotl(unsigned int _Value, int _Shift) {
- _Shift &= 0x1f;
- return _Shift ? (_Value << _Shift) | (_Value >> (32 - _Shift)) : _Value;
-}
-static __inline__ unsigned int __DEFAULT_FN_ATTRS
-_rotr(unsigned int _Value, int _Shift) {
- _Shift &= 0x1f;
- return _Shift ? (_Value >> _Shift) | (_Value << (32 - _Shift)) : _Value;
-}
-static __inline__ unsigned long __DEFAULT_FN_ATTRS
-_lrotl(unsigned long _Value, int _Shift) {
- _Shift &= 0x1f;
- return _Shift ? (_Value << _Shift) | (_Value >> (32 - _Shift)) : _Value;
-}
-static __inline__ unsigned long __DEFAULT_FN_ATTRS
-_lrotr(unsigned long _Value, int _Shift) {
- _Shift &= 0x1f;
- return _Shift ? (_Value >> _Shift) | (_Value << (32 - _Shift)) : _Value;
-}
-static
-__inline__ unsigned __int64 __DEFAULT_FN_ATTRS
-_rotl64(unsigned __int64 _Value, int _Shift) {
- _Shift &= 0x3f;
- return _Shift ? (_Value << _Shift) | (_Value >> (64 - _Shift)) : _Value;
-}
-static
-__inline__ unsigned __int64 __DEFAULT_FN_ATTRS
-_rotr64(unsigned __int64 _Value, int _Shift) {
- _Shift &= 0x3f;
- return _Shift ? (_Value >> _Shift) | (_Value << (64 - _Shift)) : _Value;
-}
+#if defined(__x86_64__) || defined(__arm__)
+
+static __inline__
+__int64 _InterlockedDecrement64(__int64 volatile *_Addend);
+static __inline__
+__int64 _InterlockedExchange64(__int64 volatile *_Target, __int64 _Value);
+static __inline__
+__int64 _InterlockedExchangeAdd64(__int64 volatile *_Addend, __int64 _Value);
+static __inline__
+__int64 _InterlockedExchangeSub64(__int64 volatile *_Subend, __int64 _Value);
+static __inline__
+__int64 _InterlockedIncrement64(__int64 volatile *_Addend);
+static __inline__
+__int64 _InterlockedOr64(__int64 volatile *_Value, __int64 _Mask);
+static __inline__
+__int64 _InterlockedXor64(__int64 volatile *_Value, __int64 _Mask);
+static __inline__
+__int64 _InterlockedAnd64(__int64 volatile *_Value, __int64 _Mask);
+
+#endif
+
/*----------------------------------------------------------------------------*\
|* Bit Counting and Testing
\*----------------------------------------------------------------------------*/
static __inline__ unsigned char __DEFAULT_FN_ATTRS
-_BitScanForward(unsigned long *_Index, unsigned long _Mask) {
- if (!_Mask)
- return 0;
- *_Index = __builtin_ctzl(_Mask);
- return 1;
-}
-static __inline__ unsigned char __DEFAULT_FN_ATTRS
-_BitScanReverse(unsigned long *_Index, unsigned long _Mask) {
- if (!_Mask)
- return 0;
- *_Index = 31 - __builtin_clzl(_Mask);
- return 1;
-}
-static __inline__ unsigned short __DEFAULT_FN_ATTRS
-__popcnt16(unsigned short _Value) {
- return __builtin_popcount((int)_Value);
-}
-static __inline__ unsigned int __DEFAULT_FN_ATTRS
-__popcnt(unsigned int _Value) {
- return __builtin_popcount(_Value);
-}
-static __inline__ unsigned char __DEFAULT_FN_ATTRS
_bittest(long const *_BitBase, long _BitPos) {
return (*_BitBase >> _BitPos) & 1;
}
@@ -548,26 +467,24 @@ _interlockedbittestandset(long volatile *_BitBase, long _BitPos) {
long _PrevVal = __atomic_fetch_or(_BitBase, 1l << _BitPos, __ATOMIC_SEQ_CST);
return (_PrevVal >> _BitPos) & 1;
}
-#ifdef __x86_64__
+#if defined(__arm__) || defined(__aarch64__)
static __inline__ unsigned char __DEFAULT_FN_ATTRS
-_BitScanForward64(unsigned long *_Index, unsigned __int64 _Mask) {
- if (!_Mask)
- return 0;
- *_Index = __builtin_ctzll(_Mask);
- return 1;
+_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
-_BitScanReverse64(unsigned long *_Index, unsigned __int64 _Mask) {
- if (!_Mask)
- return 0;
- *_Index = 63 - __builtin_clzll(_Mask);
- return 1;
+_interlockedbittestandset_nf(long volatile *_BitBase, long _BitPos) {
+ long _PrevVal = __atomic_fetch_or(_BitBase, 1l << _BitPos, __ATOMIC_RELAXED);
+ return (_PrevVal >> _BitPos) & 1;
}
-static __inline__
-unsigned __int64 __DEFAULT_FN_ATTRS
-__popcnt64(unsigned __int64 _Value) {
- return __builtin_popcountll(_Value);
+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;
@@ -600,196 +517,449 @@ _interlockedbittestandset64(__int64 volatile *_BitBase, __int64 _BitPos) {
/*----------------------------------------------------------------------------*\
|* Interlocked Exchange Add
\*----------------------------------------------------------------------------*/
+#if defined(__arm__) || defined(__aarch64__)
static __inline__ char __DEFAULT_FN_ATTRS
-_InterlockedExchangeAdd8(char volatile *_Addend, char _Value) {
- return __atomic_fetch_add(_Addend, _Value, __ATOMIC_SEQ_CST);
+_InterlockedExchangeAdd8_acq(char volatile *_Addend, char _Value) {
+ return __atomic_fetch_add(_Addend, _Value, __ATOMIC_ACQUIRE);
}
-static __inline__ short __DEFAULT_FN_ATTRS
-_InterlockedExchangeAdd16(short volatile *_Addend, short _Value) {
- return __atomic_fetch_add(_Addend, _Value, __ATOMIC_SEQ_CST);
-}
-#ifdef __x86_64__
-static __inline__ __int64 __DEFAULT_FN_ATTRS
-_InterlockedExchangeAdd64(__int64 volatile *_Addend, __int64 _Value) {
- return __atomic_fetch_add(_Addend, _Value, __ATOMIC_SEQ_CST);
+static __inline__ char __DEFAULT_FN_ATTRS
+_InterlockedExchangeAdd8_nf(char volatile *_Addend, char _Value) {
+ return __atomic_fetch_add(_Addend, _Value, __ATOMIC_RELAXED);
}
-#endif
-/*----------------------------------------------------------------------------*\
-|* Interlocked Exchange Sub
-\*----------------------------------------------------------------------------*/
static __inline__ char __DEFAULT_FN_ATTRS
-_InterlockedExchangeSub8(char volatile *_Subend, char _Value) {
- return __atomic_fetch_sub(_Subend, _Value, __ATOMIC_SEQ_CST);
+_InterlockedExchangeAdd8_rel(char volatile *_Addend, char _Value) {
+ return __atomic_fetch_add(_Addend, _Value, __ATOMIC_RELAXED);
+}
+static __inline__ short __DEFAULT_FN_ATTRS
+_InterlockedExchangeAdd16_acq(short volatile *_Addend, short _Value) {
+ return __atomic_fetch_add(_Addend, _Value, __ATOMIC_ACQUIRE);
+}
+static __inline__ short __DEFAULT_FN_ATTRS
+_InterlockedExchangeAdd16_nf(short volatile *_Addend, short _Value) {
+ return __atomic_fetch_add(_Addend, _Value, __ATOMIC_RELAXED);
}
static __inline__ short __DEFAULT_FN_ATTRS
-_InterlockedExchangeSub16(short volatile *_Subend, short _Value) {
- return __atomic_fetch_sub(_Subend, _Value, __ATOMIC_SEQ_CST);
+_InterlockedExchangeAdd16_rel(short volatile *_Addend, short _Value) {
+ return __atomic_fetch_add(_Addend, _Value, __ATOMIC_RELEASE);
}
static __inline__ long __DEFAULT_FN_ATTRS
-_InterlockedExchangeSub(long volatile *_Subend, long _Value) {
- return __atomic_fetch_sub(_Subend, _Value, __ATOMIC_SEQ_CST);
+_InterlockedExchangeAdd_acq(long volatile *_Addend, long _Value) {
+ return __atomic_fetch_add(_Addend, _Value, __ATOMIC_ACQUIRE);
+}
+static __inline__ long __DEFAULT_FN_ATTRS
+_InterlockedExchangeAdd_nf(long volatile *_Addend, long _Value) {
+ return __atomic_fetch_add(_Addend, _Value, __ATOMIC_RELAXED);
+}
+static __inline__ long __DEFAULT_FN_ATTRS
+_InterlockedExchangeAdd_rel(long volatile *_Addend, long _Value) {
+ return __atomic_fetch_add(_Addend, _Value, __ATOMIC_RELEASE);
}
-#ifdef __x86_64__
static __inline__ __int64 __DEFAULT_FN_ATTRS
-_InterlockedExchangeSub64(__int64 volatile *_Subend, __int64 _Value) {
- return __atomic_fetch_sub(_Subend, _Value, __ATOMIC_SEQ_CST);
+_InterlockedExchangeAdd64_acq(__int64 volatile *_Addend, __int64 _Value) {
+ return __atomic_fetch_add(_Addend, _Value, __ATOMIC_ACQUIRE);
+}
+static __inline__ __int64 __DEFAULT_FN_ATTRS
+_InterlockedExchangeAdd64_nf(__int64 volatile *_Addend, __int64 _Value) {
+ return __atomic_fetch_add(_Addend, _Value, __ATOMIC_RELAXED);
+}
+static __inline__ __int64 __DEFAULT_FN_ATTRS
+_InterlockedExchangeAdd64_rel(__int64 volatile *_Addend, __int64 _Value) {
+ return __atomic_fetch_add(_Addend, _Value, __ATOMIC_RELEASE);
}
#endif
/*----------------------------------------------------------------------------*\
|* Interlocked Increment
\*----------------------------------------------------------------------------*/
+#if defined(__arm__) || defined(__aarch64__)
static __inline__ short __DEFAULT_FN_ATTRS
-_InterlockedIncrement16(short volatile *_Value) {
- return __atomic_add_fetch(_Value, 1, __ATOMIC_SEQ_CST);
+_InterlockedIncrement16_acq(short volatile *_Value) {
+ return __atomic_add_fetch(_Value, 1, __ATOMIC_ACQUIRE);
+}
+static __inline__ short __DEFAULT_FN_ATTRS
+_InterlockedIncrement16_nf(short volatile *_Value) {
+ return __atomic_add_fetch(_Value, 1, __ATOMIC_RELAXED);
+}
+static __inline__ short __DEFAULT_FN_ATTRS
+_InterlockedIncrement16_rel(short volatile *_Value) {
+ return __atomic_add_fetch(_Value, 1, __ATOMIC_RELEASE);
+}
+static __inline__ long __DEFAULT_FN_ATTRS
+_InterlockedIncrement_acq(long volatile *_Value) {
+ return __atomic_add_fetch(_Value, 1, __ATOMIC_ACQUIRE);
+}
+static __inline__ long __DEFAULT_FN_ATTRS
+_InterlockedIncrement_nf(long volatile *_Value) {
+ return __atomic_add_fetch(_Value, 1, __ATOMIC_RELAXED);
+}
+static __inline__ long __DEFAULT_FN_ATTRS
+_InterlockedIncrement_rel(long volatile *_Value) {
+ return __atomic_add_fetch(_Value, 1, __ATOMIC_RELEASE);
}
-#ifdef __x86_64__
static __inline__ __int64 __DEFAULT_FN_ATTRS
-_InterlockedIncrement64(__int64 volatile *_Value) {
- return __atomic_add_fetch(_Value, 1, __ATOMIC_SEQ_CST);
+_InterlockedIncrement64_acq(__int64 volatile *_Value) {
+ return __atomic_add_fetch(_Value, 1, __ATOMIC_ACQUIRE);
+}
+static __inline__ __int64 __DEFAULT_FN_ATTRS
+_InterlockedIncrement64_nf(__int64 volatile *_Value) {
+ return __atomic_add_fetch(_Value, 1, __ATOMIC_RELAXED);
+}
+static __inline__ __int64 __DEFAULT_FN_ATTRS
+_InterlockedIncrement64_rel(__int64 volatile *_Value) {
+ return __atomic_add_fetch(_Value, 1, __ATOMIC_RELEASE);
}
#endif
/*----------------------------------------------------------------------------*\
|* Interlocked Decrement
\*----------------------------------------------------------------------------*/
+#if defined(__arm__) || defined(__aarch64__)
static __inline__ short __DEFAULT_FN_ATTRS
-_InterlockedDecrement16(short volatile *_Value) {
- return __atomic_sub_fetch(_Value, 1, __ATOMIC_SEQ_CST);
+_InterlockedDecrement16_acq(short volatile *_Value) {
+ return __atomic_sub_fetch(_Value, 1, __ATOMIC_ACQUIRE);
+}
+static __inline__ short __DEFAULT_FN_ATTRS
+_InterlockedDecrement16_nf(short volatile *_Value) {
+ return __atomic_sub_fetch(_Value, 1, __ATOMIC_RELAXED);
+}
+static __inline__ short __DEFAULT_FN_ATTRS
+_InterlockedDecrement16_rel(short volatile *_Value) {
+ return __atomic_sub_fetch(_Value, 1, __ATOMIC_RELEASE);
+}
+static __inline__ long __DEFAULT_FN_ATTRS
+_InterlockedDecrement_acq(long volatile *_Value) {
+ return __atomic_sub_fetch(_Value, 1, __ATOMIC_ACQUIRE);
+}
+static __inline__ long __DEFAULT_FN_ATTRS
+_InterlockedDecrement_nf(long volatile *_Value) {
+ return __atomic_sub_fetch(_Value, 1, __ATOMIC_RELAXED);
+}
+static __inline__ long __DEFAULT_FN_ATTRS
+_InterlockedDecrement_rel(long volatile *_Value) {
+ return __atomic_sub_fetch(_Value, 1, __ATOMIC_RELEASE);
+}
+static __inline__ __int64 __DEFAULT_FN_ATTRS
+_InterlockedDecrement64_acq(__int64 volatile *_Value) {
+ return __atomic_sub_fetch(_Value, 1, __ATOMIC_ACQUIRE);
}
-#ifdef __x86_64__
static __inline__ __int64 __DEFAULT_FN_ATTRS
-_InterlockedDecrement64(__int64 volatile *_Value) {
- return __atomic_sub_fetch(_Value, 1, __ATOMIC_SEQ_CST);
+_InterlockedDecrement64_nf(__int64 volatile *_Value) {
+ return __atomic_sub_fetch(_Value, 1, __ATOMIC_RELAXED);
+}
+static __inline__ __int64 __DEFAULT_FN_ATTRS
+_InterlockedDecrement64_rel(__int64 volatile *_Value) {
+ return __atomic_sub_fetch(_Value, 1, __ATOMIC_RELEASE);
}
#endif
/*----------------------------------------------------------------------------*\
|* Interlocked And
\*----------------------------------------------------------------------------*/
+#if defined(__arm__) || defined(__aarch64__)
static __inline__ char __DEFAULT_FN_ATTRS
-_InterlockedAnd8(char volatile *_Value, char _Mask) {
- return __atomic_fetch_and(_Value, _Mask, __ATOMIC_SEQ_CST);
+_InterlockedAnd8_acq(char volatile *_Value, char _Mask) {
+ return __atomic_fetch_and(_Value, _Mask, __ATOMIC_ACQUIRE);
+}
+static __inline__ char __DEFAULT_FN_ATTRS
+_InterlockedAnd8_nf(char volatile *_Value, char _Mask) {
+ return __atomic_fetch_and(_Value, _Mask, __ATOMIC_RELAXED);
+}
+static __inline__ char __DEFAULT_FN_ATTRS
+_InterlockedAnd8_rel(char volatile *_Value, char _Mask) {
+ return __atomic_fetch_and(_Value, _Mask, __ATOMIC_RELEASE);
+}
+static __inline__ short __DEFAULT_FN_ATTRS
+_InterlockedAnd16_acq(short volatile *_Value, short _Mask) {
+ return __atomic_fetch_and(_Value, _Mask, __ATOMIC_ACQUIRE);
+}
+static __inline__ short __DEFAULT_FN_ATTRS
+_InterlockedAnd16_nf(short volatile *_Value, short _Mask) {
+ return __atomic_fetch_and(_Value, _Mask, __ATOMIC_RELAXED);
}
static __inline__ short __DEFAULT_FN_ATTRS
-_InterlockedAnd16(short volatile *_Value, short _Mask) {
- return __atomic_fetch_and(_Value, _Mask, __ATOMIC_SEQ_CST);
+_InterlockedAnd16_rel(short volatile *_Value, short _Mask) {
+ return __atomic_fetch_and(_Value, _Mask, __ATOMIC_RELEASE);
}
static __inline__ long __DEFAULT_FN_ATTRS
-_InterlockedAnd(long volatile *_Value, long _Mask) {
- return __atomic_fetch_and(_Value, _Mask, __ATOMIC_SEQ_CST);
+_InterlockedAnd_acq(long volatile *_Value, long _Mask) {
+ return __atomic_fetch_and(_Value, _Mask, __ATOMIC_ACQUIRE);
+}
+static __inline__ long __DEFAULT_FN_ATTRS
+_InterlockedAnd_nf(long volatile *_Value, long _Mask) {
+ return __atomic_fetch_and(_Value, _Mask, __ATOMIC_RELAXED);
+}
+static __inline__ long __DEFAULT_FN_ATTRS
+_InterlockedAnd_rel(long volatile *_Value, long _Mask) {
+ return __atomic_fetch_and(_Value, _Mask, __ATOMIC_RELEASE);
+}
+static __inline__ __int64 __DEFAULT_FN_ATTRS
+_InterlockedAnd64_acq(__int64 volatile *_Value, __int64 _Mask) {
+ return __atomic_fetch_and(_Value, _Mask, __ATOMIC_ACQUIRE);
}
-#ifdef __x86_64__
static __inline__ __int64 __DEFAULT_FN_ATTRS
-_InterlockedAnd64(__int64 volatile *_Value, __int64 _Mask) {
- return __atomic_fetch_and(_Value, _Mask, __ATOMIC_SEQ_CST);
+_InterlockedAnd64_nf(__int64 volatile *_Value, __int64 _Mask) {
+ return __atomic_fetch_and(_Value, _Mask, __ATOMIC_RELAXED);
+}
+static __inline__ __int64 __DEFAULT_FN_ATTRS
+_InterlockedAnd64_rel(__int64 volatile *_Value, __int64 _Mask) {
+ return __atomic_fetch_and(_Value, _Mask, __ATOMIC_RELEASE);
}
#endif
/*----------------------------------------------------------------------------*\
|* Interlocked Or
\*----------------------------------------------------------------------------*/
+#if defined(__arm__) || defined(__aarch64__)
+static __inline__ char __DEFAULT_FN_ATTRS
+_InterlockedOr8_acq(char volatile *_Value, char _Mask) {
+ return __atomic_fetch_or(_Value, _Mask, __ATOMIC_ACQUIRE);
+}
+static __inline__ char __DEFAULT_FN_ATTRS
+_InterlockedOr8_nf(char volatile *_Value, char _Mask) {
+ return __atomic_fetch_or(_Value, _Mask, __ATOMIC_RELAXED);
+}
static __inline__ char __DEFAULT_FN_ATTRS
-_InterlockedOr8(char volatile *_Value, char _Mask) {
- return __atomic_fetch_or(_Value, _Mask, __ATOMIC_SEQ_CST);
+_InterlockedOr8_rel(char volatile *_Value, char _Mask) {
+ return __atomic_fetch_or(_Value, _Mask, __ATOMIC_RELEASE);
+}
+static __inline__ short __DEFAULT_FN_ATTRS
+_InterlockedOr16_acq(short volatile *_Value, short _Mask) {
+ return __atomic_fetch_or(_Value, _Mask, __ATOMIC_ACQUIRE);
+}
+static __inline__ short __DEFAULT_FN_ATTRS
+_InterlockedOr16_nf(short volatile *_Value, short _Mask) {
+ return __atomic_fetch_or(_Value, _Mask, __ATOMIC_RELAXED);
}
static __inline__ short __DEFAULT_FN_ATTRS
-_InterlockedOr16(short volatile *_Value, short _Mask) {
- return __atomic_fetch_or(_Value, _Mask, __ATOMIC_SEQ_CST);
+_InterlockedOr16_rel(short volatile *_Value, short _Mask) {
+ return __atomic_fetch_or(_Value, _Mask, __ATOMIC_RELEASE);
}
static __inline__ long __DEFAULT_FN_ATTRS
-_InterlockedOr(long volatile *_Value, long _Mask) {
- return __atomic_fetch_or(_Value, _Mask, __ATOMIC_SEQ_CST);
+_InterlockedOr_acq(long volatile *_Value, long _Mask) {
+ return __atomic_fetch_or(_Value, _Mask, __ATOMIC_ACQUIRE);
+}
+static __inline__ long __DEFAULT_FN_ATTRS
+_InterlockedOr_nf(long volatile *_Value, long _Mask) {
+ return __atomic_fetch_or(_Value, _Mask, __ATOMIC_RELAXED);
+}
+static __inline__ long __DEFAULT_FN_ATTRS
+_InterlockedOr_rel(long volatile *_Value, long _Mask) {
+ return __atomic_fetch_or(_Value, _Mask, __ATOMIC_RELEASE);
+}
+static __inline__ __int64 __DEFAULT_FN_ATTRS
+_InterlockedOr64_acq(__int64 volatile *_Value, __int64 _Mask) {
+ return __atomic_fetch_or(_Value, _Mask, __ATOMIC_ACQUIRE);
+}
+static __inline__ __int64 __DEFAULT_FN_ATTRS
+_InterlockedOr64_nf(__int64 volatile *_Value, __int64 _Mask) {
+ return __atomic_fetch_or(_Value, _Mask, __ATOMIC_RELAXED);
}
-#ifdef __x86_64__
static __inline__ __int64 __DEFAULT_FN_ATTRS
-_InterlockedOr64(__int64 volatile *_Value, __int64 _Mask) {
- return __atomic_fetch_or(_Value, _Mask, __ATOMIC_SEQ_CST);
+_InterlockedOr64_rel(__int64 volatile *_Value, __int64 _Mask) {
+ return __atomic_fetch_or(_Value, _Mask, __ATOMIC_RELEASE);
}
#endif
/*----------------------------------------------------------------------------*\
|* Interlocked Xor
\*----------------------------------------------------------------------------*/
+#if defined(__arm__) || defined(__aarch64__)
+static __inline__ char __DEFAULT_FN_ATTRS
+_InterlockedXor8_acq(char volatile *_Value, char _Mask) {
+ return __atomic_fetch_xor(_Value, _Mask, __ATOMIC_ACQUIRE);
+}
+static __inline__ char __DEFAULT_FN_ATTRS
+_InterlockedXor8_nf(char volatile *_Value, char _Mask) {
+ return __atomic_fetch_xor(_Value, _Mask, __ATOMIC_RELAXED);
+}
static __inline__ char __DEFAULT_FN_ATTRS
-_InterlockedXor8(char volatile *_Value, char _Mask) {
- return __atomic_fetch_xor(_Value, _Mask, __ATOMIC_SEQ_CST);
+_InterlockedXor8_rel(char volatile *_Value, char _Mask) {
+ return __atomic_fetch_xor(_Value, _Mask, __ATOMIC_RELEASE);
+}
+static __inline__ short __DEFAULT_FN_ATTRS
+_InterlockedXor16_acq(short volatile *_Value, short _Mask) {
+ return __atomic_fetch_xor(_Value, _Mask, __ATOMIC_ACQUIRE);
+}
+static __inline__ short __DEFAULT_FN_ATTRS
+_InterlockedXor16_nf(short volatile *_Value, short _Mask) {
+ return __atomic_fetch_xor(_Value, _Mask, __ATOMIC_RELAXED);
}
static __inline__ short __DEFAULT_FN_ATTRS
-_InterlockedXor16(short volatile *_Value, short _Mask) {
- return __atomic_fetch_xor(_Value, _Mask, __ATOMIC_SEQ_CST);
+_InterlockedXor16_rel(short volatile *_Value, short _Mask) {
+ return __atomic_fetch_xor(_Value, _Mask, __ATOMIC_RELEASE);
}
static __inline__ long __DEFAULT_FN_ATTRS
-_InterlockedXor(long volatile *_Value, long _Mask) {
- return __atomic_fetch_xor(_Value, _Mask, __ATOMIC_SEQ_CST);
+_InterlockedXor_acq(long volatile *_Value, long _Mask) {
+ return __atomic_fetch_xor(_Value, _Mask, __ATOMIC_ACQUIRE);
+}
+static __inline__ long __DEFAULT_FN_ATTRS
+_InterlockedXor_nf(long volatile *_Value, long _Mask) {
+ return __atomic_fetch_xor(_Value, _Mask, __ATOMIC_RELAXED);
+}
+static __inline__ long __DEFAULT_FN_ATTRS
+_InterlockedXor_rel(long volatile *_Value, long _Mask) {
+ return __atomic_fetch_xor(_Value, _Mask, __ATOMIC_RELEASE);
+}
+static __inline__ __int64 __DEFAULT_FN_ATTRS
+_InterlockedXor64_acq(__int64 volatile *_Value, __int64 _Mask) {
+ return __atomic_fetch_xor(_Value, _Mask, __ATOMIC_ACQUIRE);
+}
+static __inline__ __int64 __DEFAULT_FN_ATTRS
+_InterlockedXor64_nf(__int64 volatile *_Value, __int64 _Mask) {
+ return __atomic_fetch_xor(_Value, _Mask, __ATOMIC_RELAXED);
}
-#ifdef __x86_64__
static __inline__ __int64 __DEFAULT_FN_ATTRS
-_InterlockedXor64(__int64 volatile *_Value, __int64 _Mask) {
- return __atomic_fetch_xor(_Value, _Mask, __ATOMIC_SEQ_CST);
+_InterlockedXor64_rel(__int64 volatile *_Value, __int64 _Mask) {
+ return __atomic_fetch_xor(_Value, _Mask, __ATOMIC_RELEASE);
}
#endif
/*----------------------------------------------------------------------------*\
|* Interlocked Exchange
\*----------------------------------------------------------------------------*/
+#if defined(__arm__) || defined(__aarch64__)
static __inline__ char __DEFAULT_FN_ATTRS
-_InterlockedExchange8(char volatile *_Target, char _Value) {
- __atomic_exchange(_Target, &_Value, &_Value, __ATOMIC_SEQ_CST);
+_InterlockedExchange8_acq(char volatile *_Target, char _Value) {
+ __atomic_exchange(_Target, &_Value, &_Value, __ATOMIC_ACQUIRE);
+ return _Value;
+}
+static __inline__ char __DEFAULT_FN_ATTRS
+_InterlockedExchange8_nf(char volatile *_Target, char _Value) {
+ __atomic_exchange(_Target, &_Value, &_Value, __ATOMIC_RELAXED);
+ return _Value;
+}
+static __inline__ char __DEFAULT_FN_ATTRS
+_InterlockedExchange8_rel(char volatile *_Target, char _Value) {
+ __atomic_exchange(_Target, &_Value, &_Value, __ATOMIC_RELEASE);
return _Value;
}
static __inline__ short __DEFAULT_FN_ATTRS
-_InterlockedExchange16(short volatile *_Target, short _Value) {
- __atomic_exchange(_Target, &_Value, &_Value, __ATOMIC_SEQ_CST);
+_InterlockedExchange16_acq(short volatile *_Target, short _Value) {
+ __atomic_exchange(_Target, &_Value, &_Value, __ATOMIC_ACQUIRE);
+ return _Value;
+}
+static __inline__ short __DEFAULT_FN_ATTRS
+_InterlockedExchange16_nf(short volatile *_Target, short _Value) {
+ __atomic_exchange(_Target, &_Value, &_Value, __ATOMIC_RELAXED);
+ return _Value;
+}
+static __inline__ short __DEFAULT_FN_ATTRS
+_InterlockedExchange16_rel(short volatile *_Target, short _Value) {
+ __atomic_exchange(_Target, &_Value, &_Value, __ATOMIC_RELEASE);
+ return _Value;
+}
+static __inline__ long __DEFAULT_FN_ATTRS
+_InterlockedExchange_acq(long volatile *_Target, long _Value) {
+ __atomic_exchange(_Target, &_Value, &_Value, __ATOMIC_ACQUIRE);
+ return _Value;
+}
+static __inline__ long __DEFAULT_FN_ATTRS
+_InterlockedExchange_nf(long volatile *_Target, long _Value) {
+ __atomic_exchange(_Target, &_Value, &_Value, __ATOMIC_RELAXED);
+ return _Value;
+}
+static __inline__ long __DEFAULT_FN_ATTRS
+_InterlockedExchange_rel(long volatile *_Target, long _Value) {
+ __atomic_exchange(_Target, &_Value, &_Value, __ATOMIC_RELEASE);
+ return _Value;
+}
+static __inline__ __int64 __DEFAULT_FN_ATTRS
+_InterlockedExchange64_acq(__int64 volatile *_Target, __int64 _Value) {
+ __atomic_exchange(_Target, &_Value, &_Value, __ATOMIC_ACQUIRE);
+ return _Value;
+}
+static __inline__ __int64 __DEFAULT_FN_ATTRS
+_InterlockedExchange64_nf(__int64 volatile *_Target, __int64 _Value) {
+ __atomic_exchange(_Target, &_Value, &_Value, __ATOMIC_RELAXED);
return _Value;
}
-#ifdef __x86_64__
static __inline__ __int64 __DEFAULT_FN_ATTRS
-_InterlockedExchange64(__int64 volatile *_Target, __int64 _Value) {
- __atomic_exchange(_Target, &_Value, &_Value, __ATOMIC_SEQ_CST);
+_InterlockedExchange64_rel(__int64 volatile *_Target, __int64 _Value) {
+ __atomic_exchange(_Target, &_Value, &_Value, __ATOMIC_RELEASE);
return _Value;
}
#endif
/*----------------------------------------------------------------------------*\
|* Interlocked Compare Exchange
\*----------------------------------------------------------------------------*/
+#if defined(__arm__) || defined(__aarch64__)
static __inline__ char __DEFAULT_FN_ATTRS
-_InterlockedCompareExchange8(char volatile *_Destination,
+_InterlockedCompareExchange8_acq(char volatile *_Destination,
char _Exchange, char _Comparand) {
__atomic_compare_exchange(_Destination, &_Comparand, &_Exchange, 0,
- __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
+ __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
+ return _Comparand;
+}
+static __inline__ char __DEFAULT_FN_ATTRS
+_InterlockedCompareExchange8_nf(char volatile *_Destination,
+ char _Exchange, char _Comparand) {
+ __atomic_compare_exchange(_Destination, &_Comparand, &_Exchange, 0,
+ __ATOMIC_SEQ_CST, __ATOMIC_RELAXED);
+ return _Comparand;
+}
+static __inline__ char __DEFAULT_FN_ATTRS
+_InterlockedCompareExchange8_rel(char volatile *_Destination,
+ char _Exchange, char _Comparand) {
+ __atomic_compare_exchange(_Destination, &_Comparand, &_Exchange, 0,
+ __ATOMIC_SEQ_CST, __ATOMIC_RELEASE);
return _Comparand;
}
static __inline__ short __DEFAULT_FN_ATTRS
-_InterlockedCompareExchange16(short volatile *_Destination,
+_InterlockedCompareExchange16_acq(short volatile *_Destination,
short _Exchange, short _Comparand) {
__atomic_compare_exchange(_Destination, &_Comparand, &_Exchange, 0,
- __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
+ __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
return _Comparand;
}
-static __inline__ __int64 __DEFAULT_FN_ATTRS
-_InterlockedCompareExchange64(__int64 volatile *_Destination,
- __int64 _Exchange, __int64 _Comparand) {
+static __inline__ short __DEFAULT_FN_ATTRS
+_InterlockedCompareExchange16_nf(short volatile *_Destination,
+ short _Exchange, short _Comparand) {
__atomic_compare_exchange(_Destination, &_Comparand, &_Exchange, 0,
- __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
+ __ATOMIC_SEQ_CST, __ATOMIC_RELAXED);
return _Comparand;
}
-/*----------------------------------------------------------------------------*\
-|* Barriers
-\*----------------------------------------------------------------------------*/
-static __inline__ void __DEFAULT_FN_ATTRS
-__attribute__((__deprecated__("use other intrinsics or C++11 atomics instead")))
-_ReadWriteBarrier(void) {
- __atomic_signal_fence(__ATOMIC_SEQ_CST);
+static __inline__ short __DEFAULT_FN_ATTRS
+_InterlockedCompareExchange16_rel(short volatile *_Destination,
+ short _Exchange, short _Comparand) {
+ __atomic_compare_exchange(_Destination, &_Comparand, &_Exchange, 0,
+ __ATOMIC_SEQ_CST, __ATOMIC_RELEASE);
+ return _Comparand;
}
-static __inline__ void __DEFAULT_FN_ATTRS
-__attribute__((__deprecated__("use other intrinsics or C++11 atomics instead")))
-_ReadBarrier(void) {
- __atomic_signal_fence(__ATOMIC_SEQ_CST);
+static __inline__ long __DEFAULT_FN_ATTRS
+_InterlockedCompareExchange_acq(long volatile *_Destination,
+ long _Exchange, long _Comparand) {
+ __atomic_compare_exchange(_Destination, &_Comparand, &_Exchange, 0,
+ __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
+ return _Comparand;
}
-static __inline__ void __DEFAULT_FN_ATTRS
-__attribute__((__deprecated__("use other intrinsics or C++11 atomics instead")))
-_WriteBarrier(void) {
- __atomic_signal_fence(__ATOMIC_SEQ_CST);
+static __inline__ long __DEFAULT_FN_ATTRS
+_InterlockedCompareExchange_nf(long volatile *_Destination,
+ long _Exchange, long _Comparand) {
+ __atomic_compare_exchange(_Destination, &_Comparand, &_Exchange, 0,
+ __ATOMIC_SEQ_CST, __ATOMIC_RELAXED);
+ return _Comparand;
}
-#ifdef __x86_64__
-static __inline__ void __DEFAULT_FN_ATTRS
-__faststorefence(void) {
- __atomic_thread_fence(__ATOMIC_SEQ_CST);
+static __inline__ short __DEFAULT_FN_ATTRS
+_InterlockedCompareExchange_rel(long volatile *_Destination,
+ long _Exchange, long _Comparand) {
+ __atomic_compare_exchange(_Destination, &_Comparand, &_Exchange, 0,
+ __ATOMIC_SEQ_CST, __ATOMIC_RELEASE);
+ return _Comparand;
+}
+static __inline__ __int64 __DEFAULT_FN_ATTRS
+_InterlockedCompareExchange64_acq(__int64 volatile *_Destination,
+ __int64 _Exchange, __int64 _Comparand) {
+ __atomic_compare_exchange(_Destination, &_Comparand, &_Exchange, 0,
+ __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
+ return _Comparand;
+}
+static __inline__ __int64 __DEFAULT_FN_ATTRS
+_InterlockedCompareExchange64_nf(__int64 volatile *_Destination,
+ __int64 _Exchange, __int64 _Comparand) {
+ __atomic_compare_exchange(_Destination, &_Comparand, &_Exchange, 0,
+ __ATOMIC_SEQ_CST, __ATOMIC_RELAXED);
+ return _Comparand;
+}
+static __inline__ __int64 __DEFAULT_FN_ATTRS
+_InterlockedCompareExchange64_rel(__int64 volatile *_Destination,
+ __int64 _Exchange, __int64 _Comparand) {
+ __atomic_compare_exchange(_Destination, &_Comparand, &_Exchange, 0,
+ __ATOMIC_SEQ_CST, __ATOMIC_RELEASE);
+ return _Comparand;
}
#endif
/*----------------------------------------------------------------------------*\
@@ -840,59 +1010,39 @@ __readgsqword(unsigned long __offset) {
#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)
- : "%edi", "%esi", "%ecx");
+ __asm__("rep movsb" : : "D"(__dst), "S"(__src), "c"(__n));
}
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)
- : "%edi", "%esi", "%ecx");
+ __asm__("rep movsl" : : "D"(__dst), "S"(__src), "c"(__n));
}
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)
- : "%edi", "%esi", "%ecx");
-}
-static __inline__ void __DEFAULT_FN_ATTRS
-__stosb(unsigned char *__dst, unsigned char __x, size_t __n) {
- __asm__("rep stosb" : : "D"(__dst), "a"(__x), "c"(__n)
- : "%edi", "%ecx");
+ __asm__("rep movsw" : : "D"(__dst), "S"(__src), "c"(__n));
}
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)
- : "%edi", "%ecx");
+ __asm__("rep stosl" : : "D"(__dst), "a"(__x), "c"(__n));
}
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)
- : "%edi", "%ecx");
+ __asm__("rep stosw" : : "D"(__dst), "a"(__x), "c"(__n));
}
#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)
- : "%edi", "%esi", "%ecx");
+ __asm__("rep movsq" : : "D"(__dst), "S"(__src), "c"(__n));
}
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)
- : "%edi", "%ecx");
+ __asm__("rep stosq" : : "D"(__dst), "a"(__x), "c"(__n));
}
#endif
/*----------------------------------------------------------------------------*\
|* Misc
\*----------------------------------------------------------------------------*/
-static __inline__ void * __DEFAULT_FN_ATTRS
-_AddressOfReturnAddress(void) {
- return (void*)((char*)__builtin_frame_address(0) + sizeof(void*));
-}
-static __inline__ void * __DEFAULT_FN_ATTRS
-_ReturnAddress(void) {
- return __builtin_return_address(0);
-}
#if defined(__i386__) || defined(__x86_64__)
static __inline__ void __DEFAULT_FN_ATTRS
__cpuid(int __info[4], int __level) {
@@ -914,6 +1064,10 @@ static __inline__ void __DEFAULT_FN_ATTRS
__halt(void) {
__asm__ volatile ("hlt");
}
+static __inline__ void __DEFAULT_FN_ATTRS
+__nop(void) {
+ __asm__ volatile ("nop");
+}
#endif
/*----------------------------------------------------------------------------*\
diff --git a/lib/Headers/lzcntintrin.h b/lib/Headers/lzcntintrin.h
index 4c00e42ac3a9..3d2769da3bae 100644
--- a/lib/Headers/lzcntintrin.h
+++ b/lib/Headers/lzcntintrin.h
@@ -31,18 +31,48 @@
/* 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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the \c LZCNT instruction.
+///
+/// \param __X
+/// An unsigned 16-bit integer whose leading zeros are to be counted.
+/// \returns An unsigned 16-bit integer containing the number of leading zero
+/// bits in the operand.
static __inline__ unsigned short __DEFAULT_FN_ATTRS
__lzcnt16(unsigned short __X)
{
return __X ? __builtin_clzs(__X) : 16;
}
+/// \brief Counts the number of leading zero bits in the operand.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the \c LZCNT instruction.
+///
+/// \param __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.
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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the \c LZCNT instruction.
+///
+/// \param __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.
static __inline__ unsigned int __DEFAULT_FN_ATTRS
_lzcnt_u32(unsigned int __X)
{
@@ -50,12 +80,32 @@ _lzcnt_u32(unsigned int __X)
}
#ifdef __x86_64__
+/// \brief Counts the number of leading zero bits in the operand.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the \c LZCNT instruction.
+///
+/// \param __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.
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.
+///
+/// \headerfile <x86intrin.h>
+///
+/// This intrinsic corresponds to the \c LZCNT instruction.
+///
+/// \param __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.
static __inline__ unsigned long long __DEFAULT_FN_ATTRS
_lzcnt_u64(unsigned long long __X)
{
diff --git a/lib/Headers/mmintrin.h b/lib/Headers/mmintrin.h
index cefd6053aa80..e0c277a65a33 100644
--- a/lib/Headers/mmintrin.h
+++ b/lib/Headers/mmintrin.h
@@ -39,7 +39,7 @@ typedef char __v8qi __attribute__((__vector_size__(8)));
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c EMMS instruction.
+/// This intrinsic corresponds to the <c> EMMS </c> instruction.
///
static __inline__ void __DEFAULT_FN_ATTRS
_mm_empty(void)
@@ -52,7 +52,7 @@ _mm_empty(void)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VMOVD / MOVD instruction.
+/// This intrinsic corresponds to the <c> VMOVD / MOVD </c> instruction.
///
/// \param __i
/// A 32-bit integer value.
@@ -69,7 +69,7 @@ _mm_cvtsi32_si64(int __i)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VMOVD / MOVD instruction.
+/// This intrinsic corresponds to the <c> VMOVD / MOVD </c> instruction.
///
/// \param __m
/// A 64-bit integer vector.
@@ -85,7 +85,7 @@ _mm_cvtsi64_si32(__m64 __m)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VMOVQ / MOVD instruction.
+/// This intrinsic corresponds to the <c> VMOVQ / MOVD </c> instruction.
///
/// \param __i
/// A 64-bit signed integer.
@@ -101,7 +101,7 @@ _mm_cvtsi64_m64(long long __i)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VMOVQ / MOVD instruction.
+/// This intrinsic corresponds to the <c> VMOVQ / MOVD </c> instruction.
///
/// \param __m
/// A 64-bit integer vector.
@@ -121,7 +121,7 @@ _mm_cvtm64_si64(__m64 __m)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PACKSSWB instruction.
+/// This intrinsic corresponds to the <c> PACKSSWB </c> instruction.
///
/// \param __m1
/// A 64-bit integer vector of [4 x i16]. Each 16-bit element is treated as a
@@ -151,7 +151,7 @@ _mm_packs_pi16(__m64 __m1, __m64 __m2)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PACKSSDW instruction.
+/// This intrinsic corresponds to the <c> PACKSSDW </c> instruction.
///
/// \param __m1
/// A 64-bit integer vector of [2 x i32]. Each 32-bit element is treated as a
@@ -181,7 +181,7 @@ _mm_packs_pi32(__m64 __m1, __m64 __m2)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PACKUSWB instruction.
+/// This intrinsic corresponds to the <c> PACKUSWB </c> instruction.
///
/// \param __m1
/// A 64-bit integer vector of [4 x i16]. Each 16-bit element is treated as a
@@ -208,19 +208,19 @@ _mm_packs_pu16(__m64 __m1, __m64 __m2)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PUNPCKHBW instruction.
+/// This intrinsic corresponds to the <c> PUNPCKHBW </c> instruction.
///
/// \param __m1
-/// A 64-bit integer vector of [8 x i8].
-/// Bits [39:32] are written to bits [7:0] of the result.
-/// Bits [47:40] are written to bits [23:16] of the result.
-/// Bits [55:48] are written to bits [39:32] of the result.
+/// A 64-bit integer vector of [8 x i8]. \n
+/// Bits [39:32] are written to bits [7:0] of the result. \n
+/// Bits [47:40] are written to bits [23:16] of the result. \n
+/// Bits [55:48] are written to bits [39:32] of the result. \n
/// Bits [63:56] are written to bits [55:48] of the result.
/// \param __m2
/// A 64-bit integer vector of [8 x i8].
-/// Bits [39:32] are written to bits [15:8] of the result.
-/// Bits [47:40] are written to bits [31:24] of the result.
-/// Bits [55:48] are written to bits [47:40] of the result.
+/// Bits [39:32] are written to bits [15:8] of the result. \n
+/// Bits [47:40] are written to bits [31:24] of the result. \n
+/// Bits [55:48] are written to bits [47:40] of the result. \n
/// Bits [63:56] are written to bits [63:56] of the result.
/// \returns A 64-bit integer vector of [8 x i8] containing the interleaved
/// values.
@@ -235,15 +235,15 @@ _mm_unpackhi_pi8(__m64 __m1, __m64 __m2)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PUNPCKHWD instruction.
+/// This intrinsic corresponds to the <c> PUNPCKHWD </c> instruction.
///
/// \param __m1
/// A 64-bit integer vector of [4 x i16].
-/// Bits [47:32] are written to bits [15:0] of the result.
+/// Bits [47:32] are written to bits [15:0] of the result. \n
/// Bits [63:48] are written to bits [47:32] of the result.
/// \param __m2
/// A 64-bit integer vector of [4 x i16].
-/// Bits [47:32] are written to bits [31:16] of the result.
+/// Bits [47:32] are written to bits [31:16] of the result. \n
/// Bits [63:48] are written to bits [63:48] of the result.
/// \returns A 64-bit integer vector of [4 x i16] containing the interleaved
/// values.
@@ -258,7 +258,7 @@ _mm_unpackhi_pi16(__m64 __m1, __m64 __m2)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PUNPCKHDQ instruction.
+/// This intrinsic corresponds to the <c> PUNPCKHDQ </c> instruction.
///
/// \param __m1
/// A 64-bit integer vector of [2 x i32]. The upper 32 bits are written to
@@ -279,19 +279,19 @@ _mm_unpackhi_pi32(__m64 __m1, __m64 __m2)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PUNPCKLBW instruction.
+/// This intrinsic corresponds to the <c> PUNPCKLBW </c> instruction.
///
/// \param __m1
/// A 64-bit integer vector of [8 x i8].
-/// Bits [7:0] are written to bits [7:0] of the result.
-/// Bits [15:8] are written to bits [23:16] of the result.
-/// Bits [23:16] are written to bits [39:32] of the result.
+/// Bits [7:0] are written to bits [7:0] of the result. \n
+/// Bits [15:8] are written to bits [23:16] of the result. \n
+/// Bits [23:16] are written to bits [39:32] of the result. \n
/// Bits [31:24] are written to bits [55:48] of the result.
/// \param __m2
/// A 64-bit integer vector of [8 x i8].
-/// Bits [7:0] are written to bits [15:8] of the result.
-/// Bits [15:8] are written to bits [31:24] of the result.
-/// Bits [23:16] are written to bits [47:40] of the result.
+/// Bits [7:0] are written to bits [15:8] of the result. \n
+/// Bits [15:8] are written to bits [31:24] of the result. \n
+/// Bits [23:16] are written to bits [47:40] of the result. \n
/// Bits [31:24] are written to bits [63:56] of the result.
/// \returns A 64-bit integer vector of [8 x i8] containing the interleaved
/// values.
@@ -306,15 +306,15 @@ _mm_unpacklo_pi8(__m64 __m1, __m64 __m2)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PUNPCKLWD instruction.
+/// This intrinsic corresponds to the <c> PUNPCKLWD </c> instruction.
///
/// \param __m1
/// A 64-bit integer vector of [4 x i16].
-/// Bits [15:0] are written to bits [15:0] of the result.
+/// Bits [15:0] are written to bits [15:0] of the result. \n
/// Bits [31:16] are written to bits [47:32] of the result.
/// \param __m2
/// A 64-bit integer vector of [4 x i16].
-/// Bits [15:0] are written to bits [31:16] of the result.
+/// Bits [15:0] are written to bits [31:16] of the result. \n
/// Bits [31:16] are written to bits [63:48] of the result.
/// \returns A 64-bit integer vector of [4 x i16] containing the interleaved
/// values.
@@ -329,7 +329,7 @@ _mm_unpacklo_pi16(__m64 __m1, __m64 __m2)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PUNPCKLDQ instruction.
+/// This intrinsic corresponds to the <c> PUNPCKLDQ </c> instruction.
///
/// \param __m1
/// A 64-bit integer vector of [2 x i32]. The lower 32 bits are written to
@@ -352,7 +352,7 @@ _mm_unpacklo_pi32(__m64 __m1, __m64 __m2)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PADDB instruction.
+/// This intrinsic corresponds to the <c> PADDB </c> instruction.
///
/// \param __m1
/// A 64-bit integer vector of [8 x i8].
@@ -373,7 +373,7 @@ _mm_add_pi8(__m64 __m1, __m64 __m2)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PADDW instruction.
+/// This intrinsic corresponds to the <c> PADDW </c> instruction.
///
/// \param __m1
/// A 64-bit integer vector of [4 x i16].
@@ -394,7 +394,7 @@ _mm_add_pi16(__m64 __m1, __m64 __m2)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PADDD instruction.
+/// This intrinsic corresponds to the <c> PADDD </c> instruction.
///
/// \param __m1
/// A 64-bit integer vector of [2 x i32].
@@ -416,7 +416,7 @@ _mm_add_pi32(__m64 __m1, __m64 __m2)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PADDSB instruction.
+/// This intrinsic corresponds to the <c> PADDSB </c> instruction.
///
/// \param __m1
/// A 64-bit integer vector of [8 x i8].
@@ -439,7 +439,7 @@ _mm_adds_pi8(__m64 __m1, __m64 __m2)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PADDSW instruction.
+/// This intrinsic corresponds to the <c> PADDSW </c> instruction.
///
/// \param __m1
/// A 64-bit integer vector of [4 x i16].
@@ -461,7 +461,7 @@ _mm_adds_pi16(__m64 __m1, __m64 __m2)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PADDUSB instruction.
+/// This intrinsic corresponds to the <c> PADDUSB </c> instruction.
///
/// \param __m1
/// A 64-bit integer vector of [8 x i8].
@@ -483,7 +483,7 @@ _mm_adds_pu8(__m64 __m1, __m64 __m2)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PADDUSW instruction.
+/// This intrinsic corresponds to the <c> PADDUSW </c> instruction.
///
/// \param __m1
/// A 64-bit integer vector of [4 x i16].
@@ -504,7 +504,7 @@ _mm_adds_pu16(__m64 __m1, __m64 __m2)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PSUBB instruction.
+/// This intrinsic corresponds to the <c> PSUBB </c> instruction.
///
/// \param __m1
/// A 64-bit integer vector of [8 x i8] containing the minuends.
@@ -525,7 +525,7 @@ _mm_sub_pi8(__m64 __m1, __m64 __m2)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PSUBW instruction.
+/// This intrinsic corresponds to the <c> PSUBW </c> instruction.
///
/// \param __m1
/// A 64-bit integer vector of [4 x i16] containing the minuends.
@@ -546,7 +546,7 @@ _mm_sub_pi16(__m64 __m1, __m64 __m2)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PSUBD instruction.
+/// This intrinsic corresponds to the <c> PSUBD </c> instruction.
///
/// \param __m1
/// A 64-bit integer vector of [2 x i32] containing the minuends.
@@ -569,7 +569,7 @@ _mm_sub_pi32(__m64 __m1, __m64 __m2)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PSUBSB instruction.
+/// This intrinsic corresponds to the <c> PSUBSB </c> instruction.
///
/// \param __m1
/// A 64-bit integer vector of [8 x i8] containing the minuends.
@@ -592,7 +592,7 @@ _mm_subs_pi8(__m64 __m1, __m64 __m2)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PSUBSW instruction.
+/// This intrinsic corresponds to the <c> PSUBSW </c> instruction.
///
/// \param __m1
/// A 64-bit integer vector of [4 x i16] containing the minuends.
@@ -615,7 +615,7 @@ _mm_subs_pi16(__m64 __m1, __m64 __m2)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PSUBUSB instruction.
+/// This intrinsic corresponds to the <c> PSUBUSB </c> instruction.
///
/// \param __m1
/// A 64-bit integer vector of [8 x i8] containing the minuends.
@@ -638,7 +638,7 @@ _mm_subs_pu8(__m64 __m1, __m64 __m2)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PSUBUSW instruction.
+/// This intrinsic corresponds to the <c> PSUBUSW </c> instruction.
///
/// \param __m1
/// A 64-bit integer vector of [4 x i16] containing the minuends.
@@ -663,7 +663,7 @@ _mm_subs_pu16(__m64 __m1, __m64 __m2)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PMADDWD instruction.
+/// This intrinsic corresponds to the <c> PMADDWD </c> instruction.
///
/// \param __m1
/// A 64-bit integer vector of [4 x i16].
@@ -684,7 +684,7 @@ _mm_madd_pi16(__m64 __m1, __m64 __m2)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PMULHW instruction.
+/// This intrinsic corresponds to the <c> PMULHW </c> instruction.
///
/// \param __m1
/// A 64-bit integer vector of [4 x i16].
@@ -705,7 +705,7 @@ _mm_mulhi_pi16(__m64 __m1, __m64 __m2)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PMULLW instruction.
+/// This intrinsic corresponds to the <c> PMULLW </c> instruction.
///
/// \param __m1
/// A 64-bit integer vector of [4 x i16].
@@ -727,14 +727,15 @@ _mm_mullo_pi16(__m64 __m1, __m64 __m2)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PSLLW instruction.
+/// This intrinsic corresponds to the <c> PSLLW </c> instruction.
///
/// \param __m
/// A 64-bit integer vector of [4 x i16].
/// \param __count
/// A 64-bit integer vector interpreted as a single 64-bit integer.
/// \returns A 64-bit integer vector of [4 x i16] containing the left-shifted
-/// values. If __count is greater or equal to 16, the result is set to all 0.
+/// values. If \a __count is greater or equal to 16, the result is set to all
+/// 0.
static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_sll_pi16(__m64 __m, __m64 __count)
{
@@ -748,14 +749,15 @@ _mm_sll_pi16(__m64 __m, __m64 __count)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PSLLW instruction.
+/// This intrinsic corresponds to the <c> PSLLW </c> instruction.
///
/// \param __m
/// A 64-bit integer vector of [4 x i16].
/// \param __count
/// A 32-bit integer value.
/// \returns A 64-bit integer vector of [4 x i16] containing the left-shifted
-/// values. If __count is greater or equal to 16, the result is set to all 0.
+/// values. If \a __count is greater or equal to 16, the result is set to all
+/// 0.
static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_slli_pi16(__m64 __m, int __count)
{
@@ -770,14 +772,15 @@ _mm_slli_pi16(__m64 __m, int __count)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PSLLD instruction.
+/// This intrinsic corresponds to the <c> PSLLD </c> instruction.
///
/// \param __m
/// A 64-bit integer vector of [2 x i32].
/// \param __count
/// A 64-bit integer vector interpreted as a single 64-bit integer.
/// \returns A 64-bit integer vector of [2 x i32] containing the left-shifted
-/// values. If __count is greater or equal to 32, the result is set to all 0.
+/// values. If \a __count is greater or equal to 32, the result is set to all
+/// 0.
static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_sll_pi32(__m64 __m, __m64 __count)
{
@@ -791,14 +794,15 @@ _mm_sll_pi32(__m64 __m, __m64 __count)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PSLLD instruction.
+/// This intrinsic corresponds to the <c> PSLLD </c> instruction.
///
/// \param __m
/// A 64-bit integer vector of [2 x i32].
/// \param __count
/// A 32-bit integer value.
/// \returns A 64-bit integer vector of [2 x i32] containing the left-shifted
-/// values. If __count is greater or equal to 32, the result is set to all 0.
+/// values. If \a __count is greater or equal to 32, the result is set to all
+/// 0.
static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_slli_pi32(__m64 __m, int __count)
{
@@ -811,14 +815,14 @@ _mm_slli_pi32(__m64 __m, int __count)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PSLLQ instruction.
+/// This intrinsic corresponds to the <c> PSLLQ </c> instruction.
///
/// \param __m
/// A 64-bit integer vector interpreted as a single 64-bit integer.
/// \param __count
/// A 64-bit integer vector interpreted as a single 64-bit integer.
/// \returns A 64-bit integer vector containing the left-shifted value. If
-/// __count is greater or equal to 64, the result is set to 0.
+/// \a __count is greater or equal to 64, the result is set to 0.
static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_sll_si64(__m64 __m, __m64 __count)
{
@@ -831,14 +835,14 @@ _mm_sll_si64(__m64 __m, __m64 __count)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PSLLQ instruction.
+/// This intrinsic corresponds to the <c> PSLLQ </c> instruction.
///
/// \param __m
/// A 64-bit integer vector interpreted as a single 64-bit integer.
/// \param __count
/// A 32-bit integer value.
/// \returns A 64-bit integer vector containing the left-shifted value. If
-/// __count is greater or equal to 64, the result is set to 0.
+/// \a __count is greater or equal to 64, the result is set to 0.
static __inline__ __m64 __DEFAULT_FN_ATTRS
_mm_slli_si64(__m64 __m, int __count)
{
@@ -854,7 +858,7 @@ _mm_slli_si64(__m64 __m, int __count)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PSRAW instruction.
+/// This intrinsic corresponds to the <c> PSRAW </c> instruction.
///
/// \param __m
/// A 64-bit integer vector of [4 x i16].
@@ -876,7 +880,7 @@ _mm_sra_pi16(__m64 __m, __m64 __count)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PSRAW instruction.
+/// This intrinsic corresponds to the <c> PSRAW </c> instruction.
///
/// \param __m
/// A 64-bit integer vector of [4 x i16].
@@ -899,7 +903,7 @@ _mm_srai_pi16(__m64 __m, int __count)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PSRAD instruction.
+/// This intrinsic corresponds to the <c> PSRAD </c> instruction.
///
/// \param __m
/// A 64-bit integer vector of [2 x i32].
@@ -921,7 +925,7 @@ _mm_sra_pi32(__m64 __m, __m64 __count)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PSRAD instruction.
+/// This intrinsic corresponds to the <c> PSRAD </c> instruction.
///
/// \param __m
/// A 64-bit integer vector of [2 x i32].
@@ -943,7 +947,7 @@ _mm_srai_pi32(__m64 __m, int __count)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PSRLW instruction.
+/// This intrinsic corresponds to the <c> PSRLW </c> instruction.
///
/// \param __m
/// A 64-bit integer vector of [4 x i16].
@@ -964,7 +968,7 @@ _mm_srl_pi16(__m64 __m, __m64 __count)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PSRLW instruction.
+/// This intrinsic corresponds to the <c> PSRLW </c> instruction.
///
/// \param __m
/// A 64-bit integer vector of [4 x i16].
@@ -986,7 +990,7 @@ _mm_srli_pi16(__m64 __m, int __count)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PSRLD instruction.
+/// This intrinsic corresponds to the <c> PSRLD </c> instruction.
///
/// \param __m
/// A 64-bit integer vector of [2 x i32].
@@ -1007,7 +1011,7 @@ _mm_srl_pi32(__m64 __m, __m64 __count)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PSRLD instruction.
+/// This intrinsic corresponds to the <c> PSRLD </c> instruction.
///
/// \param __m
/// A 64-bit integer vector of [2 x i32].
@@ -1027,7 +1031,7 @@ _mm_srli_pi32(__m64 __m, int __count)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PSRLQ instruction.
+/// This intrinsic corresponds to the <c> PSRLQ </c> instruction.
///
/// \param __m
/// A 64-bit integer vector interpreted as a single 64-bit integer.
@@ -1046,7 +1050,7 @@ _mm_srl_si64(__m64 __m, __m64 __count)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PSRLQ instruction.
+/// This intrinsic corresponds to the <c> PSRLQ </c> instruction.
///
/// \param __m
/// A 64-bit integer vector interpreted as a single 64-bit integer.
@@ -1063,7 +1067,7 @@ _mm_srli_si64(__m64 __m, int __count)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PAND instruction.
+/// This intrinsic corresponds to the <c> PAND </c> instruction.
///
/// \param __m1
/// A 64-bit integer vector.
@@ -1083,7 +1087,7 @@ _mm_and_si64(__m64 __m1, __m64 __m2)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PANDN instruction.
+/// This intrinsic corresponds to the <c> PANDN </c> instruction.
///
/// \param __m1
/// A 64-bit integer vector. The one's complement of this parameter is used
@@ -1102,7 +1106,7 @@ _mm_andnot_si64(__m64 __m1, __m64 __m2)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c POR instruction.
+/// This intrinsic corresponds to the <c> POR </c> instruction.
///
/// \param __m1
/// A 64-bit integer vector.
@@ -1120,7 +1124,7 @@ _mm_or_si64(__m64 __m1, __m64 __m2)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PXOR instruction.
+/// This intrinsic corresponds to the <c> PXOR </c> instruction.
///
/// \param __m1
/// A 64-bit integer vector.
@@ -1141,7 +1145,7 @@ _mm_xor_si64(__m64 __m1, __m64 __m2)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PCMPEQB instruction.
+/// This intrinsic corresponds to the <c> PCMPEQB </c> instruction.
///
/// \param __m1
/// A 64-bit integer vector of [8 x i8].
@@ -1162,7 +1166,7 @@ _mm_cmpeq_pi8(__m64 __m1, __m64 __m2)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PCMPEQW instruction.
+/// This intrinsic corresponds to the <c> PCMPEQW </c> instruction.
///
/// \param __m1
/// A 64-bit integer vector of [4 x i16].
@@ -1183,7 +1187,7 @@ _mm_cmpeq_pi16(__m64 __m1, __m64 __m2)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PCMPEQD instruction.
+/// This intrinsic corresponds to the <c> PCMPEQD </c> instruction.
///
/// \param __m1
/// A 64-bit integer vector of [2 x i32].
@@ -1204,7 +1208,7 @@ _mm_cmpeq_pi32(__m64 __m1, __m64 __m2)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PCMPGTB instruction.
+/// This intrinsic corresponds to the <c> PCMPGTB </c> instruction.
///
/// \param __m1
/// A 64-bit integer vector of [8 x i8].
@@ -1225,7 +1229,7 @@ _mm_cmpgt_pi8(__m64 __m1, __m64 __m2)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PCMPGTW instruction.
+/// This intrinsic corresponds to the <c> PCMPGTW </c> instruction.
///
/// \param __m1
/// A 64-bit integer vector of [4 x i16].
@@ -1246,7 +1250,7 @@ _mm_cmpgt_pi16(__m64 __m1, __m64 __m2)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PCMPGTD instruction.
+/// This intrinsic corresponds to the <c> PCMPGTD </c> instruction.
///
/// \param __m1
/// A 64-bit integer vector of [2 x i32].
@@ -1264,7 +1268,7 @@ _mm_cmpgt_pi32(__m64 __m1, __m64 __m2)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the the \c VXORPS / XORPS instruction.
+/// This intrinsic corresponds to the the <c> VXORPS / XORPS </c> instruction.
///
/// \returns An initialized 64-bit integer vector with all elements set to zero.
static __inline__ __m64 __DEFAULT_FN_ATTRS
@@ -1356,7 +1360,7 @@ _mm_set_pi8(char __b7, char __b6, char __b5, char __b4, char __b3, char __b2,
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPSHUFD / PSHUFD instruction.
+/// This intrinsic corresponds to the <c> VPSHUFD / PSHUFD </c> instruction.
///
/// \param __i
/// A 32-bit integer value used to initialize each vector element of the
@@ -1374,7 +1378,7 @@ _mm_set1_pi32(int __i)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPSHUFLW / PSHUFLW instruction.
+/// This intrinsic corresponds to the <c> VPSHUFLW / PSHUFLW </c> instruction.
///
/// \param __w
/// A 16-bit integer value used to initialize each vector element of the
@@ -1391,8 +1395,8 @@ _mm_set1_pi16(short __w)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPUNPCKLBW + VPSHUFLW / \c PUNPCKLBW +
-/// PSHUFLW instruction.
+/// This intrinsic corresponds to the <c> VPUNPCKLBW + VPSHUFLW / PUNPCKLBW +
+/// PSHUFLW </c> instruction.
///
/// \param __b
/// An 8-bit integer value used to initialize each vector element of the
diff --git a/lib/Headers/module.modulemap b/lib/Headers/module.modulemap
index 3e40d2c08d8c..11ef2f902945 100644
--- a/lib/Headers/module.modulemap
+++ b/lib/Headers/module.modulemap
@@ -63,11 +63,13 @@ module _Builtin_intrinsics [system] [extern_c] {
textual header "mwaitxintrin.h"
explicit module mm_malloc {
+ requires !freestanding
header "mm_malloc.h"
export * // note: for <stdlib.h> dependency
}
explicit module cpuid {
+ requires gnuinlineasm
header "cpuid.h"
}
diff --git a/lib/Headers/opencl-c.h b/lib/Headers/opencl-c.h
index 802927490e7f..0c25d312709d 100644
--- a/lib/Headers/opencl-c.h
+++ b/lib/Headers/opencl-c.h
@@ -17,6 +17,7 @@
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
#define __ovld __attribute__((overloadable))
+#define __conv __attribute__((convergent))
// Optimizations
#define __purefn __attribute__((pure))
@@ -9810,14 +9811,6 @@ float3 __ovld __cnfn native_cos(float3 x);
float4 __ovld __cnfn native_cos(float4 x);
float8 __ovld __cnfn native_cos(float8 x);
float16 __ovld __cnfn native_cos(float16 x);
-#ifdef cl_khr_fp64
-double __ovld __cnfn native_cos(double x);
-double2 __ovld __cnfn native_cos(double2 x);
-double3 __ovld __cnfn native_cos(double3 x);
-double4 __ovld __cnfn native_cos(double4 x);
-double8 __ovld __cnfn native_cos(double8 x);
-double16 __ovld __cnfn native_cos(double16 x);
-#endif //cl_khr_fp64
/**
* Compute x / y over an implementation-defined range.
@@ -9829,14 +9822,6 @@ float3 __ovld __cnfn native_divide(float3 x, float3 y);
float4 __ovld __cnfn native_divide(float4 x, float4 y);
float8 __ovld __cnfn native_divide(float8 x, float8 y);
float16 __ovld __cnfn native_divide(float16 x, float16 y);
-#ifdef cl_khr_fp64
-double __ovld __cnfn native_divide(double x, double y);
-double2 __ovld __cnfn native_divide(double2 x, double2 y);
-double3 __ovld __cnfn native_divide(double3 x, double3 y);
-double4 __ovld __cnfn native_divide(double4 x, double4 y);
-double8 __ovld __cnfn native_divide(double8 x, double8 y);
-double16 __ovld __cnfn native_divide(double16 x, double16 y);
-#endif //cl_khr_fp64
/**
* Compute the base- e exponential of x over an
@@ -9849,14 +9834,6 @@ float3 __ovld __cnfn native_exp(float3 x);
float4 __ovld __cnfn native_exp(float4 x);
float8 __ovld __cnfn native_exp(float8 x);
float16 __ovld __cnfn native_exp(float16 x);
-#ifdef cl_khr_fp64
-double __ovld __cnfn native_exp(double x);
-double2 __ovld __cnfn native_exp(double2 x);
-double3 __ovld __cnfn native_exp(double3 x);
-double4 __ovld __cnfn native_exp(double4 x);
-double8 __ovld __cnfn native_exp(double8 x);
-double16 __ovld __cnfn native_exp(double16 x);
-#endif //cl_khr_fp64
/**
* Compute the base- 2 exponential of x over an
@@ -9869,14 +9846,6 @@ float3 __ovld __cnfn native_exp2(float3 x);
float4 __ovld __cnfn native_exp2(float4 x);
float8 __ovld __cnfn native_exp2(float8 x);
float16 __ovld __cnfn native_exp2(float16 x);
-#ifdef cl_khr_fp64
-double __ovld __cnfn native_exp2(double x);
-double2 __ovld __cnfn native_exp2(double2 x);
-double3 __ovld __cnfn native_exp2(double3 x);
-double4 __ovld __cnfn native_exp2(double4 x);
-double8 __ovld __cnfn native_exp2(double8 x);
-double16 __ovld __cnfn native_exp2(double16 x);
-#endif //cl_khr_fp64
/**
* Compute the base- 10 exponential of x over an
@@ -9889,14 +9858,6 @@ float3 __ovld __cnfn native_exp10(float3 x);
float4 __ovld __cnfn native_exp10(float4 x);
float8 __ovld __cnfn native_exp10(float8 x);
float16 __ovld __cnfn native_exp10(float16 x);
-#ifdef cl_khr_fp64
-double __ovld __cnfn native_exp10(double x);
-double2 __ovld __cnfn native_exp10(double2 x);
-double3 __ovld __cnfn native_exp10(double3 x);
-double4 __ovld __cnfn native_exp10(double4 x);
-double8 __ovld __cnfn native_exp10(double8 x);
-double16 __ovld __cnfn native_exp10(double16 x);
-#endif //cl_khr_fp64
/**
* Compute natural logarithm over an implementationdefined
@@ -9909,14 +9870,6 @@ float3 __ovld __cnfn native_log(float3 x);
float4 __ovld __cnfn native_log(float4 x);
float8 __ovld __cnfn native_log(float8 x);
float16 __ovld __cnfn native_log(float16 x);
-#ifdef cl_khr_fp64
-double __ovld __cnfn native_log(double x);
-double2 __ovld __cnfn native_log(double2 x);
-double3 __ovld __cnfn native_log(double3 x);
-double4 __ovld __cnfn native_log(double4 x);
-double8 __ovld __cnfn native_log(double8 x);
-double16 __ovld __cnfn native_log(double16 x);
-#endif //cl_khr_fp64
/**
* Compute a base 2 logarithm over an implementationdefined
@@ -9928,14 +9881,6 @@ float3 __ovld __cnfn native_log2(float3 x);
float4 __ovld __cnfn native_log2(float4 x);
float8 __ovld __cnfn native_log2(float8 x);
float16 __ovld __cnfn native_log2(float16 x);
-#ifdef cl_khr_fp64
-double __ovld __cnfn native_log2(double x);
-double2 __ovld __cnfn native_log2(double2 x);
-double3 __ovld __cnfn native_log2(double3 x);
-double4 __ovld __cnfn native_log2(double4 x);
-double8 __ovld __cnfn native_log2(double8 x);
-double16 __ovld __cnfn native_log2(double16 x);
-#endif //cl_khr_fp64
/**
* Compute a base 10 logarithm over an implementationdefined
@@ -9947,14 +9892,6 @@ float3 __ovld __cnfn native_log10(float3 x);
float4 __ovld __cnfn native_log10(float4 x);
float8 __ovld __cnfn native_log10(float8 x);
float16 __ovld __cnfn native_log10(float16 x);
-#ifdef cl_khr_fp64
-double __ovld __cnfn native_log10(double x);
-double2 __ovld __cnfn native_log10(double2 x);
-double3 __ovld __cnfn native_log10(double3 x);
-double4 __ovld __cnfn native_log10(double4 x);
-double8 __ovld __cnfn native_log10(double8 x);
-double16 __ovld __cnfn native_log10(double16 x);
-#endif //cl_khr_fp64
/**
* Compute x to the power y, where x is >= 0. The range of
@@ -9967,14 +9904,6 @@ float3 __ovld __cnfn native_powr(float3 x, float3 y);
float4 __ovld __cnfn native_powr(float4 x, float4 y);
float8 __ovld __cnfn native_powr(float8 x, float8 y);
float16 __ovld __cnfn native_powr(float16 x, float16 y);
-#ifdef cl_khr_fp64
-double __ovld __cnfn native_powr(double x, double y);
-double2 __ovld __cnfn native_powr(double2 x, double2 y);
-double3 __ovld __cnfn native_powr(double3 x, double3 y);
-double4 __ovld __cnfn native_powr(double4 x, double4 y);
-double8 __ovld __cnfn native_powr(double8 x, double8 y);
-double16 __ovld __cnfn native_powr(double16 x, double16 y);
-#endif //cl_khr_fp64
/**
* Compute reciprocal over an implementation-defined
@@ -9986,14 +9915,6 @@ float3 __ovld __cnfn native_recip(float3 x);
float4 __ovld __cnfn native_recip(float4 x);
float8 __ovld __cnfn native_recip(float8 x);
float16 __ovld __cnfn native_recip(float16 x);
-#ifdef cl_khr_fp64
-double __ovld __cnfn native_recip(double x);
-double2 __ovld __cnfn native_recip(double2 x);
-double3 __ovld __cnfn native_recip(double3 x);
-double4 __ovld __cnfn native_recip(double4 x);
-double8 __ovld __cnfn native_recip(double8 x);
-double16 __ovld __cnfn native_recip(double16 x);
-#endif //cl_khr_fp64
/**
* Compute inverse square root over an implementationdefined
@@ -10005,14 +9926,6 @@ float3 __ovld __cnfn native_rsqrt(float3 x);
float4 __ovld __cnfn native_rsqrt(float4 x);
float8 __ovld __cnfn native_rsqrt(float8 x);
float16 __ovld __cnfn native_rsqrt(float16 x);
-#ifdef cl_khr_fp64
-double __ovld __cnfn native_rsqrt(double x);
-double2 __ovld __cnfn native_rsqrt(double2 x);
-double3 __ovld __cnfn native_rsqrt(double3 x);
-double4 __ovld __cnfn native_rsqrt(double4 x);
-double8 __ovld __cnfn native_rsqrt(double8 x);
-double16 __ovld __cnfn native_rsqrt(double16 x);
-#endif //cl_khr_fp64
/**
* Compute sine over an implementation-defined range.
@@ -10024,14 +9937,6 @@ float3 __ovld __cnfn native_sin(float3 x);
float4 __ovld __cnfn native_sin(float4 x);
float8 __ovld __cnfn native_sin(float8 x);
float16 __ovld __cnfn native_sin(float16 x);
-#ifdef cl_khr_fp64
-double __ovld __cnfn native_sin(double x);
-double2 __ovld __cnfn native_sin(double2 x);
-double3 __ovld __cnfn native_sin(double3 x);
-double4 __ovld __cnfn native_sin(double4 x);
-double8 __ovld __cnfn native_sin(double8 x);
-double16 __ovld __cnfn native_sin(double16 x);
-#endif //cl_khr_fp64
/**
* Compute square root over an implementation-defined
@@ -10043,14 +9948,6 @@ float3 __ovld __cnfn native_sqrt(float3 x);
float4 __ovld __cnfn native_sqrt(float4 x);
float8 __ovld __cnfn native_sqrt(float8 x);
float16 __ovld __cnfn native_sqrt(float16 x);
-#ifdef cl_khr_fp64
-double __ovld __cnfn native_sqrt(double x);
-double2 __ovld __cnfn native_sqrt(double2 x);
-double3 __ovld __cnfn native_sqrt(double3 x);
-double4 __ovld __cnfn native_sqrt(double4 x);
-double8 __ovld __cnfn native_sqrt(double8 x);
-double16 __ovld __cnfn native_sqrt(double16 x);
-#endif //cl_khr_fp64
/**
* Compute tangent over an implementation-defined range.
@@ -10062,14 +9959,6 @@ float3 __ovld __cnfn native_tan(float3 x);
float4 __ovld __cnfn native_tan(float4 x);
float8 __ovld __cnfn native_tan(float8 x);
float16 __ovld __cnfn native_tan(float16 x);
-#ifdef cl_khr_fp64
-double __ovld __cnfn native_tan(double x);
-double2 __ovld __cnfn native_tan(double2 x);
-double3 __ovld __cnfn native_tan(double3 x);
-double4 __ovld __cnfn native_tan(double4 x);
-double8 __ovld __cnfn native_tan(double8 x);
-double16 __ovld __cnfn native_tan(double16 x);
-#endif //cl_khr_fp64
// OpenCL v1.1 s6.11.3, v1.2 s6.12.3, v2.0 s6.13.3 - Integer Functions
@@ -13934,7 +13823,7 @@ typedef uint cl_mem_fence_flags;
* image objects and then want to read the updated data.
*/
-void __ovld barrier(cl_mem_fence_flags flags);
+void __ovld __conv barrier(cl_mem_fence_flags flags);
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
@@ -13947,8 +13836,8 @@ typedef enum memory_scope
memory_scope_sub_group
} memory_scope;
-void __ovld work_group_barrier(cl_mem_fence_flags flags, memory_scope scope);
-void __ovld work_group_barrier(cl_mem_fence_flags flags);
+void __ovld __conv work_group_barrier(cl_mem_fence_flags flags, memory_scope scope);
+void __ovld __conv work_group_barrier(cl_mem_fence_flags flags);
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
// OpenCL v1.1 s6.11.9, v1.2 s6.12.9 - Explicit Memory Fence Functions
@@ -14728,6 +14617,13 @@ int __ovld atom_xor(volatile __local int *p, int val);
unsigned int __ovld atom_xor(volatile __local unsigned int *p, unsigned int val);
#endif
+#if defined(cl_khr_int64_extended_atomics)
+long __ovld atom_xor(volatile __global long *p, long val);
+unsigned long __ovld atom_xor(volatile __global unsigned long *p, unsigned long val);
+long __ovld atom_xor(volatile __local long *p, long val);
+unsigned long __ovld atom_xor(volatile __local unsigned long *p, unsigned long val);
+#endif
+
#if defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics)
#pragma OPENCL EXTENSION cl_khr_int64_base_atomics : disable
#pragma OPENCL EXTENSION cl_khr_int64_extended_atomics : disable
@@ -15564,9 +15460,11 @@ half16 __ovld __cnfn shuffle2(half8 x, half8 y, ushort16 mask);
half16 __ovld __cnfn shuffle2(half16 x, half16 y, ushort16 mask);
#endif //cl_khr_fp16
+#if __OPENCL_C_VERSION__ >= CL_VERSION_1_2
// OpenCL v1.2 s6.12.13, v2.0 s6.13.13 - printf
int printf(__constant const char* st, ...);
+#endif
// OpenCL v1.1 s6.11.3, v1.2 s6.12.14, v2.0 s6.13.14 - Image Read and Write Functions
@@ -15592,6 +15490,10 @@ int printf(__constant const char* st, ...);
#define CLK_FILTER_NEAREST 0x10
#define CLK_FILTER_LINEAR 0x20
+#ifdef cl_khr_gl_msaa_sharing
+#pragma OPENCL EXTENSION cl_khr_gl_msaa_sharing : enable
+#endif //cl_khr_gl_msaa_sharing
+
/**
* Use the coordinate (coord.xy) to do an element lookup in
* the 2D image object specified by image.
@@ -16493,6 +16395,7 @@ int __ovld __cnfn get_image_channel_data_type(read_write image2d_array_msaa_dept
#define CLK_sRGBA 0x10C1
#define CLK_sRGBx 0x10C0
#define CLK_sBGRA 0x10C2
+#define CLK_ABGR 0x10C3
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
int __ovld __cnfn get_image_channel_order(read_only image1d_t image);
@@ -16670,101 +16573,101 @@ int __ovld get_image_num_samples(read_write image2d_array_msaa_depth_t image);
// OpenCL v2.0 s6.13.15 - Work-group Functions
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
-int __ovld work_group_all(int predicate);
-int __ovld work_group_any(int predicate);
+int __ovld __conv work_group_all(int predicate);
+int __ovld __conv work_group_any(int predicate);
#ifdef cl_khr_fp16
-half __ovld work_group_broadcast(half a, size_t local_id);
-half __ovld work_group_broadcast(half a, size_t x, size_t y);
-half __ovld work_group_broadcast(half a, size_t x, size_t y, size_t z);
+half __ovld __conv work_group_broadcast(half a, size_t local_id);
+half __ovld __conv work_group_broadcast(half a, size_t x, size_t y);
+half __ovld __conv work_group_broadcast(half a, size_t x, size_t y, size_t z);
#endif
-int __ovld work_group_broadcast(int a, size_t local_id);
-int __ovld work_group_broadcast(int a, size_t x, size_t y);
-int __ovld work_group_broadcast(int a, size_t x, size_t y, size_t z);
-uint __ovld work_group_broadcast(uint a, size_t local_id);
-uint __ovld work_group_broadcast(uint a, size_t x, size_t y);
-uint __ovld work_group_broadcast(uint a, size_t x, size_t y, size_t z);
-long __ovld work_group_broadcast(long a, size_t local_id);
-long __ovld work_group_broadcast(long a, size_t x, size_t y);
-long __ovld work_group_broadcast(long a, size_t x, size_t y, size_t z);
-ulong __ovld work_group_broadcast(ulong a, size_t local_id);
-ulong __ovld work_group_broadcast(ulong a, size_t x, size_t y);
-ulong __ovld work_group_broadcast(ulong a, size_t x, size_t y, size_t z);
-float __ovld work_group_broadcast(float a, size_t local_id);
-float __ovld work_group_broadcast(float a, size_t x, size_t y);
-float __ovld work_group_broadcast(float a, size_t x, size_t y, size_t z);
+int __ovld __conv work_group_broadcast(int a, size_t local_id);
+int __ovld __conv work_group_broadcast(int a, size_t x, size_t y);
+int __ovld __conv work_group_broadcast(int a, size_t x, size_t y, size_t z);
+uint __ovld __conv work_group_broadcast(uint a, size_t local_id);
+uint __ovld __conv work_group_broadcast(uint a, size_t x, size_t y);
+uint __ovld __conv work_group_broadcast(uint a, size_t x, size_t y, size_t z);
+long __ovld __conv work_group_broadcast(long a, size_t local_id);
+long __ovld __conv work_group_broadcast(long a, size_t x, size_t y);
+long __ovld __conv work_group_broadcast(long a, size_t x, size_t y, size_t z);
+ulong __ovld __conv work_group_broadcast(ulong a, size_t local_id);
+ulong __ovld __conv work_group_broadcast(ulong a, size_t x, size_t y);
+ulong __ovld __conv work_group_broadcast(ulong a, size_t x, size_t y, size_t z);
+float __ovld __conv work_group_broadcast(float a, size_t local_id);
+float __ovld __conv work_group_broadcast(float a, size_t x, size_t y);
+float __ovld __conv work_group_broadcast(float a, size_t x, size_t y, size_t z);
#ifdef cl_khr_fp64
-double __ovld work_group_broadcast(double a, size_t local_id);
-double __ovld work_group_broadcast(double a, size_t x, size_t y);
-double __ovld work_group_broadcast(double a, size_t x, size_t y, size_t z);
+double __ovld __conv work_group_broadcast(double a, size_t local_id);
+double __ovld __conv work_group_broadcast(double a, size_t x, size_t y);
+double __ovld __conv work_group_broadcast(double a, size_t x, size_t y, size_t z);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
-half __ovld work_group_reduce_add(half x);
-half __ovld work_group_reduce_min(half x);
-half __ovld work_group_reduce_max(half x);
-half __ovld work_group_scan_exclusive_add(half x);
-half __ovld work_group_scan_exclusive_min(half x);
-half __ovld work_group_scan_exclusive_max(half x);
-half __ovld work_group_scan_inclusive_add(half x);
-half __ovld work_group_scan_inclusive_min(half x);
-half __ovld work_group_scan_inclusive_max(half x);
+half __ovld __conv work_group_reduce_add(half x);
+half __ovld __conv work_group_reduce_min(half x);
+half __ovld __conv work_group_reduce_max(half x);
+half __ovld __conv work_group_scan_exclusive_add(half x);
+half __ovld __conv work_group_scan_exclusive_min(half x);
+half __ovld __conv work_group_scan_exclusive_max(half x);
+half __ovld __conv work_group_scan_inclusive_add(half x);
+half __ovld __conv work_group_scan_inclusive_min(half x);
+half __ovld __conv work_group_scan_inclusive_max(half x);
#endif
-int __ovld work_group_reduce_add(int x);
-int __ovld work_group_reduce_min(int x);
-int __ovld work_group_reduce_max(int x);
-int __ovld work_group_scan_exclusive_add(int x);
-int __ovld work_group_scan_exclusive_min(int x);
-int __ovld work_group_scan_exclusive_max(int x);
-int __ovld work_group_scan_inclusive_add(int x);
-int __ovld work_group_scan_inclusive_min(int x);
-int __ovld work_group_scan_inclusive_max(int x);
-uint __ovld work_group_reduce_add(uint x);
-uint __ovld work_group_reduce_min(uint x);
-uint __ovld work_group_reduce_max(uint x);
-uint __ovld work_group_scan_exclusive_add(uint x);
-uint __ovld work_group_scan_exclusive_min(uint x);
-uint __ovld work_group_scan_exclusive_max(uint x);
-uint __ovld work_group_scan_inclusive_add(uint x);
-uint __ovld work_group_scan_inclusive_min(uint x);
-uint __ovld work_group_scan_inclusive_max(uint x);
-long __ovld work_group_reduce_add(long x);
-long __ovld work_group_reduce_min(long x);
-long __ovld work_group_reduce_max(long x);
-long __ovld work_group_scan_exclusive_add(long x);
-long __ovld work_group_scan_exclusive_min(long x);
-long __ovld work_group_scan_exclusive_max(long x);
-long __ovld work_group_scan_inclusive_add(long x);
-long __ovld work_group_scan_inclusive_min(long x);
-long __ovld work_group_scan_inclusive_max(long x);
-ulong __ovld work_group_reduce_add(ulong x);
-ulong __ovld work_group_reduce_min(ulong x);
-ulong __ovld work_group_reduce_max(ulong x);
-ulong __ovld work_group_scan_exclusive_add(ulong x);
-ulong __ovld work_group_scan_exclusive_min(ulong x);
-ulong __ovld work_group_scan_exclusive_max(ulong x);
-ulong __ovld work_group_scan_inclusive_add(ulong x);
-ulong __ovld work_group_scan_inclusive_min(ulong x);
-ulong __ovld work_group_scan_inclusive_max(ulong x);
-float __ovld work_group_reduce_add(float x);
-float __ovld work_group_reduce_min(float x);
-float __ovld work_group_reduce_max(float x);
-float __ovld work_group_scan_exclusive_add(float x);
-float __ovld work_group_scan_exclusive_min(float x);
-float __ovld work_group_scan_exclusive_max(float x);
-float __ovld work_group_scan_inclusive_add(float x);
-float __ovld work_group_scan_inclusive_min(float x);
-float __ovld work_group_scan_inclusive_max(float x);
+int __ovld __conv work_group_reduce_add(int x);
+int __ovld __conv work_group_reduce_min(int x);
+int __ovld __conv work_group_reduce_max(int x);
+int __ovld __conv work_group_scan_exclusive_add(int x);
+int __ovld __conv work_group_scan_exclusive_min(int x);
+int __ovld __conv work_group_scan_exclusive_max(int x);
+int __ovld __conv work_group_scan_inclusive_add(int x);
+int __ovld __conv work_group_scan_inclusive_min(int x);
+int __ovld __conv work_group_scan_inclusive_max(int x);
+uint __ovld __conv work_group_reduce_add(uint x);
+uint __ovld __conv work_group_reduce_min(uint x);
+uint __ovld __conv work_group_reduce_max(uint x);
+uint __ovld __conv work_group_scan_exclusive_add(uint x);
+uint __ovld __conv work_group_scan_exclusive_min(uint x);
+uint __ovld __conv work_group_scan_exclusive_max(uint x);
+uint __ovld __conv work_group_scan_inclusive_add(uint x);
+uint __ovld __conv work_group_scan_inclusive_min(uint x);
+uint __ovld __conv work_group_scan_inclusive_max(uint x);
+long __ovld __conv work_group_reduce_add(long x);
+long __ovld __conv work_group_reduce_min(long x);
+long __ovld __conv work_group_reduce_max(long x);
+long __ovld __conv work_group_scan_exclusive_add(long x);
+long __ovld __conv work_group_scan_exclusive_min(long x);
+long __ovld __conv work_group_scan_exclusive_max(long x);
+long __ovld __conv work_group_scan_inclusive_add(long x);
+long __ovld __conv work_group_scan_inclusive_min(long x);
+long __ovld __conv work_group_scan_inclusive_max(long x);
+ulong __ovld __conv work_group_reduce_add(ulong x);
+ulong __ovld __conv work_group_reduce_min(ulong x);
+ulong __ovld __conv work_group_reduce_max(ulong x);
+ulong __ovld __conv work_group_scan_exclusive_add(ulong x);
+ulong __ovld __conv work_group_scan_exclusive_min(ulong x);
+ulong __ovld __conv work_group_scan_exclusive_max(ulong x);
+ulong __ovld __conv work_group_scan_inclusive_add(ulong x);
+ulong __ovld __conv work_group_scan_inclusive_min(ulong x);
+ulong __ovld __conv work_group_scan_inclusive_max(ulong x);
+float __ovld __conv work_group_reduce_add(float x);
+float __ovld __conv work_group_reduce_min(float x);
+float __ovld __conv work_group_reduce_max(float x);
+float __ovld __conv work_group_scan_exclusive_add(float x);
+float __ovld __conv work_group_scan_exclusive_min(float x);
+float __ovld __conv work_group_scan_exclusive_max(float x);
+float __ovld __conv work_group_scan_inclusive_add(float x);
+float __ovld __conv work_group_scan_inclusive_min(float x);
+float __ovld __conv work_group_scan_inclusive_max(float x);
#ifdef cl_khr_fp64
-double __ovld work_group_reduce_add(double x);
-double __ovld work_group_reduce_min(double x);
-double __ovld work_group_reduce_max(double x);
-double __ovld work_group_scan_exclusive_add(double x);
-double __ovld work_group_scan_exclusive_min(double x);
-double __ovld work_group_scan_exclusive_max(double x);
-double __ovld work_group_scan_inclusive_add(double x);
-double __ovld work_group_scan_inclusive_min(double x);
-double __ovld work_group_scan_inclusive_max(double x);
+double __ovld __conv work_group_reduce_add(double x);
+double __ovld __conv work_group_reduce_min(double x);
+double __ovld __conv work_group_reduce_max(double x);
+double __ovld __conv work_group_scan_exclusive_add(double x);
+double __ovld __conv work_group_scan_exclusive_min(double x);
+double __ovld __conv work_group_scan_exclusive_max(double x);
+double __ovld __conv work_group_scan_inclusive_add(double x);
+double __ovld __conv work_group_scan_inclusive_min(double x);
+double __ovld __conv work_group_scan_inclusive_max(double x);
#endif //cl_khr_fp64
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
@@ -16840,11 +16743,11 @@ void __ovld retain_event(clk_event_t);
void __ovld release_event(clk_event_t);
-clk_event_t create_user_event(void);
+clk_event_t __ovld create_user_event(void);
void __ovld set_user_event_status(clk_event_t e, int state);
-bool is_valid_event (clk_event_t event);
+bool __ovld is_valid_event (clk_event_t event);
void __ovld capture_event_profiling_info(clk_event_t, clk_profiling_info, __global void* value);
@@ -16864,96 +16767,286 @@ uint __ovld get_enqueued_num_sub_groups(void);
uint __ovld get_sub_group_id(void);
uint __ovld get_sub_group_local_id(void);
-void __ovld sub_group_barrier(cl_mem_fence_flags flags);
+void __ovld __conv sub_group_barrier(cl_mem_fence_flags flags);
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
-void __ovld sub_group_barrier(cl_mem_fence_flags flags, memory_scope scope);
+void __ovld __conv sub_group_barrier(cl_mem_fence_flags flags, memory_scope scope);
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
-int __ovld sub_group_all(int predicate);
-int __ovld sub_group_any(int predicate);
-
-int __ovld sub_group_broadcast(int x, uint sub_group_local_id);
-uint __ovld sub_group_broadcast(uint x, uint sub_group_local_id);
-long __ovld sub_group_broadcast(long x, uint sub_group_local_id);
-ulong __ovld sub_group_broadcast(ulong x, uint sub_group_local_id);
-float __ovld sub_group_broadcast(float x, uint sub_group_local_id);
-
-int __ovld sub_group_reduce_add(int x);
-uint __ovld sub_group_reduce_add(uint x);
-long __ovld sub_group_reduce_add(long x);
-ulong __ovld sub_group_reduce_add(ulong x);
-float __ovld sub_group_reduce_add(float x);
-int __ovld sub_group_reduce_min(int x);
-uint __ovld sub_group_reduce_min(uint x);
-long __ovld sub_group_reduce_min(long x);
-ulong __ovld sub_group_reduce_min(ulong x);
-float __ovld sub_group_reduce_min(float x);
-int __ovld sub_group_reduce_max(int x);
-uint __ovld sub_group_reduce_max(uint x);
-long __ovld sub_group_reduce_max(long x);
-ulong __ovld sub_group_reduce_max(ulong x);
-float __ovld sub_group_reduce_max(float x);
-
-int __ovld sub_group_scan_exclusive_add(int x);
-uint __ovld sub_group_scan_exclusive_add(uint x);
-long __ovld sub_group_scan_exclusive_add(long x);
-ulong __ovld sub_group_scan_exclusive_add(ulong x);
-float __ovld sub_group_scan_exclusive_add(float x);
-int __ovld sub_group_scan_exclusive_min(int x);
-uint __ovld sub_group_scan_exclusive_min(uint x);
-long __ovld sub_group_scan_exclusive_min(long x);
-ulong __ovld sub_group_scan_exclusive_min(ulong x);
-float __ovld sub_group_scan_exclusive_min(float x);
-int __ovld sub_group_scan_exclusive_max(int x);
-uint __ovld sub_group_scan_exclusive_max(uint x);
-long __ovld sub_group_scan_exclusive_max(long x);
-ulong __ovld sub_group_scan_exclusive_max(ulong x);
-float __ovld sub_group_scan_exclusive_max(float x);
-
-int __ovld sub_group_scan_inclusive_add(int x);
-uint __ovld sub_group_scan_inclusive_add(uint x);
-long __ovld sub_group_scan_inclusive_add(long x);
-ulong __ovld sub_group_scan_inclusive_add(ulong x);
-float __ovld sub_group_scan_inclusive_add(float x);
-int __ovld sub_group_scan_inclusive_min(int x);
-uint __ovld sub_group_scan_inclusive_min(uint x);
-long __ovld sub_group_scan_inclusive_min(long x);
-ulong __ovld sub_group_scan_inclusive_min(ulong x);
-float __ovld sub_group_scan_inclusive_min(float x);
-int __ovld sub_group_scan_inclusive_max(int x);
-uint __ovld sub_group_scan_inclusive_max(uint x);
-long __ovld sub_group_scan_inclusive_max(long x);
-ulong __ovld sub_group_scan_inclusive_max(ulong x);
-float __ovld sub_group_scan_inclusive_max(float x);
+int __ovld __conv sub_group_all(int predicate);
+int __ovld __conv sub_group_any(int predicate);
+
+int __ovld __conv sub_group_broadcast(int x, uint sub_group_local_id);
+uint __ovld __conv sub_group_broadcast(uint x, uint sub_group_local_id);
+long __ovld __conv sub_group_broadcast(long x, uint sub_group_local_id);
+ulong __ovld __conv sub_group_broadcast(ulong x, uint sub_group_local_id);
+float __ovld __conv sub_group_broadcast(float x, uint sub_group_local_id);
+
+int __ovld __conv sub_group_reduce_add(int x);
+uint __ovld __conv sub_group_reduce_add(uint x);
+long __ovld __conv sub_group_reduce_add(long x);
+ulong __ovld __conv sub_group_reduce_add(ulong x);
+float __ovld __conv sub_group_reduce_add(float x);
+int __ovld __conv sub_group_reduce_min(int x);
+uint __ovld __conv sub_group_reduce_min(uint x);
+long __ovld __conv sub_group_reduce_min(long x);
+ulong __ovld __conv sub_group_reduce_min(ulong x);
+float __ovld __conv sub_group_reduce_min(float x);
+int __ovld __conv sub_group_reduce_max(int x);
+uint __ovld __conv sub_group_reduce_max(uint x);
+long __ovld __conv sub_group_reduce_max(long x);
+ulong __ovld __conv sub_group_reduce_max(ulong x);
+float __ovld __conv sub_group_reduce_max(float x);
+
+int __ovld __conv sub_group_scan_exclusive_add(int x);
+uint __ovld __conv sub_group_scan_exclusive_add(uint x);
+long __ovld __conv sub_group_scan_exclusive_add(long x);
+ulong __ovld __conv sub_group_scan_exclusive_add(ulong x);
+float __ovld __conv sub_group_scan_exclusive_add(float x);
+int __ovld __conv sub_group_scan_exclusive_min(int x);
+uint __ovld __conv sub_group_scan_exclusive_min(uint x);
+long __ovld __conv sub_group_scan_exclusive_min(long x);
+ulong __ovld __conv sub_group_scan_exclusive_min(ulong x);
+float __ovld __conv sub_group_scan_exclusive_min(float x);
+int __ovld __conv sub_group_scan_exclusive_max(int x);
+uint __ovld __conv sub_group_scan_exclusive_max(uint x);
+long __ovld __conv sub_group_scan_exclusive_max(long x);
+ulong __ovld __conv sub_group_scan_exclusive_max(ulong x);
+float __ovld __conv sub_group_scan_exclusive_max(float x);
+
+int __ovld __conv sub_group_scan_inclusive_add(int x);
+uint __ovld __conv sub_group_scan_inclusive_add(uint x);
+long __ovld __conv sub_group_scan_inclusive_add(long x);
+ulong __ovld __conv sub_group_scan_inclusive_add(ulong x);
+float __ovld __conv sub_group_scan_inclusive_add(float x);
+int __ovld __conv sub_group_scan_inclusive_min(int x);
+uint __ovld __conv sub_group_scan_inclusive_min(uint x);
+long __ovld __conv sub_group_scan_inclusive_min(long x);
+ulong __ovld __conv sub_group_scan_inclusive_min(ulong x);
+float __ovld __conv sub_group_scan_inclusive_min(float x);
+int __ovld __conv sub_group_scan_inclusive_max(int x);
+uint __ovld __conv sub_group_scan_inclusive_max(uint x);
+long __ovld __conv sub_group_scan_inclusive_max(long x);
+ulong __ovld __conv sub_group_scan_inclusive_max(ulong x);
+float __ovld __conv sub_group_scan_inclusive_max(float x);
#ifdef cl_khr_fp16
-half __ovld sub_group_broadcast(half x, uint sub_group_local_id);
-half __ovld sub_group_reduce_add(half x);
-half __ovld sub_group_reduce_min(half x);
-half __ovld sub_group_reduce_max(half x);
-half __ovld sub_group_scan_exclusive_add(half x);
-half __ovld sub_group_scan_exclusive_min(half x);
-half __ovld sub_group_scan_exclusive_max(half x);
-half __ovld sub_group_scan_inclusive_add(half x);
-half __ovld sub_group_scan_inclusive_min(half x);
-half __ovld sub_group_scan_inclusive_max(half x);
+half __ovld __conv sub_group_broadcast(half x, uint sub_group_local_id);
+half __ovld __conv sub_group_reduce_add(half x);
+half __ovld __conv sub_group_reduce_min(half x);
+half __ovld __conv sub_group_reduce_max(half x);
+half __ovld __conv sub_group_scan_exclusive_add(half x);
+half __ovld __conv sub_group_scan_exclusive_min(half x);
+half __ovld __conv sub_group_scan_exclusive_max(half x);
+half __ovld __conv sub_group_scan_inclusive_add(half x);
+half __ovld __conv sub_group_scan_inclusive_min(half x);
+half __ovld __conv sub_group_scan_inclusive_max(half x);
#endif //cl_khr_fp16
#ifdef cl_khr_fp64
-double __ovld sub_group_broadcast(double x, uint sub_group_local_id);
-double __ovld sub_group_reduce_add(double x);
-double __ovld sub_group_reduce_min(double x);
-double __ovld sub_group_reduce_max(double x);
-double __ovld sub_group_scan_exclusive_add(double x);
-double __ovld sub_group_scan_exclusive_min(double x);
-double __ovld sub_group_scan_exclusive_max(double x);
-double __ovld sub_group_scan_inclusive_add(double x);
-double __ovld sub_group_scan_inclusive_min(double x);
-double __ovld sub_group_scan_inclusive_max(double x);
+double __ovld __conv sub_group_broadcast(double x, uint sub_group_local_id);
+double __ovld __conv sub_group_reduce_add(double x);
+double __ovld __conv sub_group_reduce_min(double x);
+double __ovld __conv sub_group_reduce_max(double x);
+double __ovld __conv sub_group_scan_exclusive_add(double x);
+double __ovld __conv sub_group_scan_exclusive_min(double x);
+double __ovld __conv sub_group_scan_exclusive_max(double x);
+double __ovld __conv sub_group_scan_inclusive_add(double x);
+double __ovld __conv sub_group_scan_inclusive_min(double x);
+double __ovld __conv sub_group_scan_inclusive_max(double x);
#endif //cl_khr_fp64
#endif //cl_khr_subgroups cl_intel_subgroups
+#ifdef cl_amd_media_ops
+uint __ovld amd_bitalign(uint a, uint b, uint c);
+uint2 __ovld amd_bitalign(uint2 a, uint2 b, uint2 c);
+uint3 __ovld amd_bitalign(uint3 a, uint3 b, uint3 c);
+uint4 __ovld amd_bitalign(uint4 a, uint4 b, uint4 c);
+uint8 __ovld amd_bitalign(uint8 a, uint8 b, uint8 c);
+uint16 __ovld amd_bitalign(uint16 a, uint16 b, uint16 c);
+
+uint __ovld amd_bytealign(uint a, uint b, uint c);
+uint2 __ovld amd_bytealign(uint2 a, uint2 b, uint2 c);
+uint3 __ovld amd_bytealign(uint3 a, uint3 b, uint3 c);
+uint4 __ovld amd_bytealign(uint4 a, uint4 b, uint4 c);
+uint8 __ovld amd_bytealign(uint8 a, uint8 b, uint8 c);
+uint16 __ovld amd_bytealign(uint16 a, uint16 b, uint16 c);
+
+uint __ovld amd_lerp(uint a, uint b, uint c);
+uint2 __ovld amd_lerp(uint2 a, uint2 b, uint2 c);
+uint3 __ovld amd_lerp(uint3 a, uint3 b, uint3 c);
+uint4 __ovld amd_lerp(uint4 a, uint4 b, uint4 c);
+uint8 __ovld amd_lerp(uint8 a, uint8 b, uint8 c);
+uint16 __ovld amd_lerp(uint16 a, uint16 b, uint16 c);
+
+uint __ovld amd_pack(float4 v);
+
+uint __ovld amd_sad4(uint4 x, uint4 y, uint z);
+
+uint __ovld amd_sadhi(uint a, uint b, uint c);
+uint2 __ovld amd_sadhi(uint2 a, uint2 b, uint2 c);
+uint3 __ovld amd_sadhi(uint3 a, uint3 b, uint3 c);
+uint4 __ovld amd_sadhi(uint4 a, uint4 b, uint4 c);
+uint8 __ovld amd_sadhi(uint8 a, uint8 b, uint8 c);
+uint16 __ovld amd_sadhi(uint16 a, uint16 b, uint16 c);
+
+uint __ovld amd_sad(uint a, uint b, uint c);
+uint2 __ovld amd_sad(uint2 a, uint2 b, uint2 c);
+uint3 __ovld amd_sad(uint3 a, uint3 b, uint3 c);
+uint4 __ovld amd_sad(uint4 a, uint4 b, uint4 c);
+uint8 __ovld amd_sad(uint8 a, uint8 b, uint8 c);
+uint16 __ovld amd_sad(uint16 a, uint16 b, uint16 c);
+
+float __ovld amd_unpack0(uint a);
+float2 __ovld amd_unpack0(uint2 a);
+float3 __ovld amd_unpack0(uint3 a);
+float4 __ovld amd_unpack0(uint4 a);
+float8 __ovld amd_unpack0(uint8 a);
+float16 __ovld amd_unpack0(uint16 a);
+
+float __ovld amd_unpack1(uint a);
+float2 __ovld amd_unpack1(uint2 a);
+float3 __ovld amd_unpack1(uint3 a);
+float4 __ovld amd_unpack1(uint4 a);
+float8 __ovld amd_unpack1(uint8 a);
+float16 __ovld amd_unpack1(uint16 a);
+
+float __ovld amd_unpack2(uint a);
+float2 __ovld amd_unpack2(uint2 a);
+float3 __ovld amd_unpack2(uint3 a);
+float4 __ovld amd_unpack2(uint4 a);
+float8 __ovld amd_unpack2(uint8 a);
+float16 __ovld amd_unpack2(uint16 a);
+
+float __ovld amd_unpack3(uint a);
+float2 __ovld amd_unpack3(uint2 a);
+float3 __ovld amd_unpack3(uint3 a);
+float4 __ovld amd_unpack3(uint4 a);
+float8 __ovld amd_unpack3(uint8 a);
+float16 __ovld amd_unpack3(uint16 a);
+#endif // cl_amd_media_ops
+
+#ifdef cl_amd_media_ops2
+int __ovld amd_bfe(int src0, uint src1, uint src2);
+int2 __ovld amd_bfe(int2 src0, uint2 src1, uint2 src2);
+int3 __ovld amd_bfe(int3 src0, uint3 src1, uint3 src2);
+int4 __ovld amd_bfe(int4 src0, uint4 src1, uint4 src2);
+int8 __ovld amd_bfe(int8 src0, uint8 src1, uint8 src2);
+int16 __ovld amd_bfe(int16 src0, uint16 src1, uint16 src2);
+
+uint __ovld amd_bfe(uint src0, uint src1, uint src2);
+uint2 __ovld amd_bfe(uint2 src0, uint2 src1, uint2 src2);
+uint3 __ovld amd_bfe(uint3 src0, uint3 src1, uint3 src2);
+uint4 __ovld amd_bfe(uint4 src0, uint4 src1, uint4 src2);
+uint8 __ovld amd_bfe(uint8 src0, uint8 src1, uint8 src2);
+uint16 __ovld amd_bfe(uint16 src0, uint16 src1, uint16 src2);
+
+uint __ovld amd_bfm(uint src0, uint src1);
+uint2 __ovld amd_bfm(uint2 src0, uint2 src1);
+uint3 __ovld amd_bfm(uint3 src0, uint3 src1);
+uint4 __ovld amd_bfm(uint4 src0, uint4 src1);
+uint8 __ovld amd_bfm(uint8 src0, uint8 src1);
+uint16 __ovld amd_bfm(uint16 src0, uint16 src1);
+
+float __ovld amd_max3(float src0, float src1, float src2);
+float2 __ovld amd_max3(float2 src0, float2 src1, float2 src2);
+float3 __ovld amd_max3(float3 src0, float3 src1, float3 src2);
+float4 __ovld amd_max3(float4 src0, float4 src1, float4 src2);
+float8 __ovld amd_max3(float8 src0, float8 src1, float8 src2);
+float16 __ovld amd_max3(float16 src0, float16 src1, float16 src2);
+
+int __ovld amd_max3(int src0, int src1, int src2);
+int2 __ovld amd_max3(int2 src0, int2 src1, int2 src2);
+int3 __ovld amd_max3(int3 src0, int3 src1, int3 src2);
+int4 __ovld amd_max3(int4 src0, int4 src1, int4 src2);
+int8 __ovld amd_max3(int8 src0, int8 src1, int8 src2);
+int16 __ovld amd_max3(int16 src0, int16 src1, int16 src2);
+
+uint __ovld amd_max3(uint src0, uint src1, uint src2);
+uint2 __ovld amd_max3(uint2 src0, uint2 src1, uint2 src2);
+uint3 __ovld amd_max3(uint3 src0, uint3 src1, uint3 src2);
+uint4 __ovld amd_max3(uint4 src0, uint4 src1, uint4 src2);
+uint8 __ovld amd_max3(uint8 src0, uint8 src1, uint8 src2);
+uint16 __ovld amd_max3(uint16 src0, uint16 src1, uint16 src2);
+
+float __ovld amd_median3(float src0, float src1, float src2);
+float2 __ovld amd_median3(float2 src0, float2 src1, float2 src2);
+float3 __ovld amd_median3(float3 src0, float3 src1, float3 src2);
+float4 __ovld amd_median3(float4 src0, float4 src1, float4 src2);
+float8 __ovld amd_median3(float8 src0, float8 src1, float8 src2);
+float16 __ovld amd_median3(float16 src0, float16 src1, float16 src2);
+
+int __ovld amd_median3(int src0, int src1, int src2);
+int2 __ovld amd_median3(int2 src0, int2 src1, int2 src2);
+int3 __ovld amd_median3(int3 src0, int3 src1, int3 src2);
+int4 __ovld amd_median3(int4 src0, int4 src1, int4 src2);
+int8 __ovld amd_median3(int8 src0, int8 src1, int8 src2);
+int16 __ovld amd_median3(int16 src0, int16 src1, int16 src2);
+
+uint __ovld amd_median3(uint src0, uint src1, uint src2);
+uint2 __ovld amd_median3(uint2 src0, uint2 src1, uint2 src2);
+uint3 __ovld amd_median3(uint3 src0, uint3 src1, uint3 src2);
+uint4 __ovld amd_median3(uint4 src0, uint4 src1, uint4 src2);
+uint8 __ovld amd_median3(uint8 src0, uint8 src1, uint8 src2);
+uint16 __ovld amd_median3(uint16 src0, uint16 src1, uint16 src2);
+
+float __ovld amd_min3(float src0, float src1, float src);
+float2 __ovld amd_min3(float2 src0, float2 src1, float2 src);
+float3 __ovld amd_min3(float3 src0, float3 src1, float3 src);
+float4 __ovld amd_min3(float4 src0, float4 src1, float4 src);
+float8 __ovld amd_min3(float8 src0, float8 src1, float8 src);
+float16 __ovld amd_min3(float16 src0, float16 src1, float16 src);
+
+int __ovld amd_min3(int src0, int src1, int src2);
+int2 __ovld amd_min3(int2 src0, int2 src1, int2 src2);
+int3 __ovld amd_min3(int3 src0, int3 src1, int3 src2);
+int4 __ovld amd_min3(int4 src0, int4 src1, int4 src2);
+int8 __ovld amd_min3(int8 src0, int8 src1, int8 src2);
+int16 __ovld amd_min3(int16 src0, int16 src1, int16 src2);
+
+uint __ovld amd_min3(uint src0, uint src1, uint src2);
+uint2 __ovld amd_min3(uint2 src0, uint2 src1, uint2 src2);
+uint3 __ovld amd_min3(uint3 src0, uint3 src1, uint3 src2);
+uint4 __ovld amd_min3(uint4 src0, uint4 src1, uint4 src2);
+uint8 __ovld amd_min3(uint8 src0, uint8 src1, uint8 src2);
+uint16 __ovld amd_min3(uint16 src0, uint16 src1, uint16 src2);
+
+ulong __ovld amd_mqsad(ulong src0, uint src1, ulong src2);
+ulong2 __ovld amd_mqsad(ulong2 src0, uint2 src1, ulong2 src2);
+ulong3 __ovld amd_mqsad(ulong3 src0, uint3 src1, ulong3 src2);
+ulong4 __ovld amd_mqsad(ulong4 src0, uint4 src1, ulong4 src2);
+ulong8 __ovld amd_mqsad(ulong8 src0, uint8 src1, ulong8 src2);
+ulong16 __ovld amd_mqsad(ulong16 src0, uint16 src1, ulong16 src2);
+
+ulong __ovld amd_qsad(ulong src0, uint src1, ulong src2);
+ulong2 __ovld amd_qsad(ulong2 src0, uint2 src1, ulong2 src2);
+ulong3 __ovld amd_qsad(ulong3 src0, uint3 src1, ulong3 src2);
+ulong4 __ovld amd_qsad(ulong4 src0, uint4 src1, ulong4 src2);
+ulong8 __ovld amd_qsad(ulong8 src0, uint8 src1, ulong8 src2);
+ulong16 __ovld amd_qsad(ulong16 src0, uint16 src1, ulong16 src2);
+
+uint __ovld amd_msad(uint src0, uint src1, uint src2);
+uint2 __ovld amd_msad(uint2 src0, uint2 src1, uint2 src2);
+uint3 __ovld amd_msad(uint3 src0, uint3 src1, uint3 src2);
+uint4 __ovld amd_msad(uint4 src0, uint4 src1, uint4 src2);
+uint8 __ovld amd_msad(uint8 src0, uint8 src1, uint8 src2);
+uint16 __ovld amd_msad(uint16 src0, uint16 src1, uint16 src2);
+
+uint __ovld amd_sadd(uint src0, uint src1, uint src2);
+uint2 __ovld amd_sadd(uint2 src0, uint2 src1, uint2 src2);
+uint3 __ovld amd_sadd(uint3 src0, uint3 src1, uint3 src2);
+uint4 __ovld amd_sadd(uint4 src0, uint4 src1, uint4 src2);
+uint8 __ovld amd_sadd(uint8 src0, uint8 src1, uint8 src2);
+uint16 __ovld amd_sadd(uint16 src0, uint16 src1, uint16 src2);
+
+uint __ovld amd_sadw(uint src0, uint src1, uint src2);
+uint2 __ovld amd_sadw(uint2 src0, uint2 src1, uint2 src2);
+uint3 __ovld amd_sadw(uint3 src0, uint3 src1, uint3 src2);
+uint4 __ovld amd_sadw(uint4 src0, uint4 src1, uint4 src2);
+uint8 __ovld amd_sadw(uint8 src0, uint8 src1, uint8 src2);
+uint16 __ovld amd_sadw(uint16 src0, uint16 src1, uint16 src2);
+#endif // cl_amd_media_ops2
+
// Disable any extensions we may have enabled previously.
#pragma OPENCL EXTENSION all : disable
diff --git a/lib/Headers/pmmintrin.h b/lib/Headers/pmmintrin.h
index 5b1058069c44..d4f6487af179 100644
--- a/lib/Headers/pmmintrin.h
+++ b/lib/Headers/pmmintrin.h
@@ -37,7 +37,7 @@
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VLDDQU instruction.
+/// This intrinsic corresponds to the <c> VLDDQU </c> instruction.
///
/// \param __p
/// A pointer to a 128-bit integer vector containing integer values.
@@ -53,7 +53,7 @@ _mm_lddqu_si128(__m128i const *__p)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VADDSUBPS instruction.
+/// This intrinsic corresponds to the <c> VADDSUBPS </c> instruction.
///
/// \param __a
/// A 128-bit vector of [4 x float] containing the left source operand.
@@ -72,7 +72,7 @@ _mm_addsub_ps(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VHADDPS instruction.
+/// This intrinsic corresponds to the <c> VHADDPS </c> instruction.
///
/// \param __a
/// A 128-bit vector of [4 x float] containing one of the source operands.
@@ -95,7 +95,7 @@ _mm_hadd_ps(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VHSUBPS instruction.
+/// This intrinsic corresponds to the <c> VHSUBPS </c> instruction.
///
/// \param __a
/// A 128-bit vector of [4 x float] containing one of the source operands.
@@ -115,18 +115,18 @@ _mm_hsub_ps(__m128 __a, __m128 __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
-/// [4 x float].
-/// Bits [127:96] of the source are written to bits [127:96] and [95:64] of
-/// the destination.
-/// Bits [63:32] of the source are written to bits [63:32] and [31:0] of the
-/// destination.
+/// [4 x float].
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VMOVSHDUP instruction.
+/// This intrinsic corresponds to the <c> VMOVSHDUP </c> instruction.
///
/// \param __a
-/// A 128-bit vector of [4 x float].
+/// A 128-bit vector of [4 x float]. \n
+/// Bits [127:96] of the source are written to bits [127:96] and [95:64] of
+/// the destination. \n
+/// Bits [63:32] of the source are written to bits [63:32] and [31:0] of the
+/// destination.
/// \returns A 128-bit vector of [4 x float] containing the moved and duplicated
/// values.
static __inline__ __m128 __DEFAULT_FN_ATTRS
@@ -135,20 +135,19 @@ _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 [4 x float] to float values stored in a 128-bit vector of
-/// [4 x float].
-/// Bits [95:64] of the source are written to bits [127:96] and [95:64] of
-/// the destination.
-/// Bits [31:0] of the source are written to bits [63:32] and [31:0] of the
-/// destination.
+/// \brief Duplicates low-order (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>
///
-/// This intrinsic corresponds to the \c VMOVSLDUP instruction.
+/// This intrinsic corresponds to the <c> VMOVSLDUP </c> instruction.
///
/// \param __a
-/// A 128-bit vector of [4 x float].
+/// A 128-bit vector of [4 x float] \n
+/// Bits [95:64] of the source are written to bits [127:96] and [95:64] of
+/// the destination. \n
+/// Bits [31:0] of the source are written to bits [63:32] and [31:0] of the
+/// destination.
/// \returns A 128-bit vector of [4 x float] containing the moved and duplicated
/// values.
static __inline__ __m128 __DEFAULT_FN_ATTRS
@@ -162,7 +161,7 @@ _mm_moveldup_ps(__m128 __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VADDSUBPD instruction.
+/// This intrinsic corresponds to the <c> VADDSUBPD </c> instruction.
///
/// \param __a
/// A 128-bit vector of [2 x double] containing the left source operand.
@@ -181,7 +180,7 @@ _mm_addsub_pd(__m128d __a, __m128d __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VHADDPD instruction.
+/// This intrinsic corresponds to the <c> VHADDPD </c> instruction.
///
/// \param __a
/// A 128-bit vector of [2 x double] containing one of the source operands.
@@ -204,7 +203,7 @@ _mm_hadd_pd(__m128d __a, __m128d __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VHSUBPD instruction.
+/// This intrinsic corresponds to the <c> VHSUBPD </c> instruction.
///
/// \param __a
/// A 128-bit vector of [2 x double] containing one of the source operands.
@@ -231,7 +230,7 @@ _mm_hsub_pd(__m128d __a, __m128d __b)
/// __m128d _mm_loaddup_pd(double const * dp);
/// \endcode
///
-/// This intrinsic corresponds to the \c VMOVDDUP instruction.
+/// This intrinsic corresponds to the <c> VMOVDDUP </c> instruction.
///
/// \param dp
/// A pointer to a double-precision value to be moved and duplicated.
@@ -245,7 +244,7 @@ _mm_hsub_pd(__m128d __a, __m128d __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VMOVDDUP instruction.
+/// This intrinsic corresponds to the <c> VMOVDDUP </c> instruction.
///
/// \param __a
/// A 128-bit vector of [2 x double]. Bits [63:0] are written to bits
@@ -272,7 +271,7 @@ _mm_movedup_pd(__m128d __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c MONITOR instruction.
+/// This intrinsic corresponds to the <c> MONITOR </c> instruction.
///
/// \param __p
/// The memory range to be monitored. The size of the range is determined by
@@ -293,7 +292,7 @@ _mm_monitor(void const *__p, unsigned __extensions, unsigned __hints)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c MWAIT instruction.
+/// This intrinsic corresponds to the <c> MWAIT </c> instruction.
///
/// \param __extensions
/// Optional extensions for the monitoring state, which may vary by
diff --git a/lib/Headers/popcntintrin.h b/lib/Headers/popcntintrin.h
index 7e2f1670805f..0b4793e58bcb 100644
--- a/lib/Headers/popcntintrin.h
+++ b/lib/Headers/popcntintrin.h
@@ -31,7 +31,7 @@
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c POPCNT instruction.
+/// This intrinsic corresponds to the <c> POPCNT </c> instruction.
///
/// \param __A
/// An unsigned 32-bit integer operand.
@@ -47,7 +47,7 @@ _mm_popcnt_u32(unsigned int __A)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c POPCNT instruction.
+/// This intrinsic corresponds to the <c> POPCNT </c> instruction.
///
/// \param __A
/// A signed 32-bit integer operand.
@@ -64,7 +64,7 @@ _popcnt32(int __A)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c POPCNT instruction.
+/// This intrinsic corresponds to the <c> POPCNT </c> instruction.
///
/// \param __A
/// An unsigned 64-bit integer operand.
@@ -80,7 +80,7 @@ _mm_popcnt_u64(unsigned long long __A)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c POPCNT instruction.
+/// This intrinsic corresponds to the <c> POPCNT </c> instruction.
///
/// \param __A
/// A signed 64-bit integer operand.
diff --git a/lib/Headers/stdatomic.h b/lib/Headers/stdatomic.h
index e03798766014..23bb3a357768 100644
--- a/lib/Headers/stdatomic.h
+++ b/lib/Headers/stdatomic.h
@@ -45,11 +45,11 @@ extern "C" {
#define ATOMIC_CHAR16_T_LOCK_FREE __GCC_ATOMIC_CHAR16_T_LOCK_FREE
#define ATOMIC_CHAR32_T_LOCK_FREE __GCC_ATOMIC_CHAR32_T_LOCK_FREE
#define ATOMIC_WCHAR_T_LOCK_FREE __GCC_ATOMIC_WCHAR_T_LOCK_FREE
-#define ATOMIC_SHORT_T_LOCK_FREE __GCC_ATOMIC_SHORT_T_LOCK_FREE
-#define ATOMIC_INT_T_LOCK_FREE __GCC_ATOMIC_INT_T_LOCK_FREE
-#define ATOMIC_LONG_T_LOCK_FREE __GCC_ATOMIC_LONG_T_LOCK_FREE
-#define ATOMIC_LLONG_T_LOCK_FREE __GCC_ATOMIC_LLONG_T_LOCK_FREE
-#define ATOMIC_POINTER_T_LOCK_FREE __GCC_ATOMIC_POINTER_T_LOCK_FREE
+#define ATOMIC_SHORT_LOCK_FREE __GCC_ATOMIC_SHORT_LOCK_FREE
+#define ATOMIC_INT_LOCK_FREE __GCC_ATOMIC_INT_LOCK_FREE
+#define ATOMIC_LONG_LOCK_FREE __GCC_ATOMIC_LONG_LOCK_FREE
+#define ATOMIC_LLONG_LOCK_FREE __GCC_ATOMIC_LLONG_LOCK_FREE
+#define ATOMIC_POINTER_LOCK_FREE __GCC_ATOMIC_POINTER_LOCK_FREE
/* 7.17.2 Initialization */
diff --git a/lib/Headers/tmmintrin.h b/lib/Headers/tmmintrin.h
index a72796ba4a68..80664043a06f 100644
--- a/lib/Headers/tmmintrin.h
+++ b/lib/Headers/tmmintrin.h
@@ -483,15 +483,15 @@ _mm_hsubs_pi16(__m64 __a, __m64 __b)
/// \param __b
/// A 128-bit integer vector containing the second source operand.
/// \returns A 128-bit integer vector containing the sums of products of both
-/// operands:
-/// R0 := (__a0 * __b0) + (__a1 * __b1)
-/// R1 := (__a2 * __b2) + (__a3 * __b3)
-/// R2 := (__a4 * __b4) + (__a5 * __b5)
-/// R3 := (__a6 * __b6) + (__a7 * __b7)
-/// R4 := (__a8 * __b8) + (__a9 * __b9)
-/// R5 := (__a10 * __b10) + (__a11 * __b11)
-/// R6 := (__a12 * __b12) + (__a13 * __b13)
-/// R7 := (__a14 * __b14) + (__a15 * __b15)
+/// operands: \n
+/// \a R0 := (\a __a0 * \a __b0) + (\a __a1 * \a __b1) \n
+/// \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) \n
+/// \a R4 := (\a __a8 * \a __b8) + (\a __a9 * \a __b9) \n
+/// \a R5 := (\a __a10 * \a __b10) + (\a __a11 * \a __b11) \n
+/// \a R6 := (\a __a12 * \a __b12) + (\a __a13 * \a __b13) \n
+/// \a R7 := (\a __a14 * \a __b14) + (\a __a15 * \a __b15)
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_maddubs_epi16(__m128i __a, __m128i __b)
{
@@ -516,11 +516,11 @@ _mm_maddubs_epi16(__m128i __a, __m128i __b)
/// \param __b
/// A 64-bit integer vector containing the second source operand.
/// \returns A 64-bit integer vector containing the sums of products of both
-/// operands:
-/// R0 := (__a0 * __b0) + (__a1 * __b1)
-/// R1 := (__a2 * __b2) + (__a3 * __b3)
-/// R2 := (__a4 * __b4) + (__a5 * __b5)
-/// R3 := (__a6 * __b6) + (__a7 * __b7)
+/// operands: \n
+/// \a R0 := (\a __a0 * \a __b0) + (\a __a1 * \a __b1) \n
+/// \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
_mm_maddubs_pi16(__m64 __a, __m64 __b)
{
@@ -580,11 +580,11 @@ _mm_mulhrs_pi16(__m64 __a, __m64 __b)
/// \param __b
/// A 128-bit integer vector containing control bytes corresponding to
/// positions in the destination:
-/// Bit 7:
-/// 1: Clear the corresponding byte in the destination.
+/// Bit 7: \n
+/// 1: Clear the corresponding byte in the destination. \n
/// 0: Copy the selected source byte to the corresponding byte in the
-/// destination.
-/// Bits [6:4] Reserved.
+/// destination. \n
+/// Bits [6:4] Reserved. \n
/// Bits [3:0] select the source byte to be copied.
/// \returns A 128-bit integer vector containing the copied or cleared values.
static __inline__ __m128i __DEFAULT_FN_ATTRS
@@ -606,10 +606,10 @@ _mm_shuffle_epi8(__m128i __a, __m128i __b)
/// \param __b
/// A 64-bit integer vector containing control bytes corresponding to
/// positions in the destination:
-/// Bit 7:
-/// 1: Clear the corresponding byte in the destination.
+/// Bit 7: \n
+/// 1: Clear the corresponding byte in the destination. \n
/// 0: Copy the selected source byte to the corresponding byte in the
-/// destination.
+/// 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
diff --git a/lib/Headers/xmmintrin.h b/lib/Headers/xmmintrin.h
index 99cddb0fac82..dc31b85cfd7c 100644
--- a/lib/Headers/xmmintrin.h
+++ b/lib/Headers/xmmintrin.h
@@ -46,7 +46,7 @@ typedef unsigned int __v4su __attribute__((__vector_size__(16)));
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VADDSS / ADDSS instructions.
+/// This intrinsic corresponds to the <c> VADDSS / ADDSS </c> instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float] containing one of the source operands.
@@ -69,7 +69,7 @@ _mm_add_ss(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VADDPS / ADDPS instructions.
+/// This intrinsic corresponds to the <c> VADDPS / ADDPS </c> instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float] containing one of the source operands.
@@ -88,7 +88,7 @@ _mm_add_ps(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VSUBSS / SUBSS instructions.
+/// This intrinsic corresponds to the <c> VSUBSS / SUBSS </c> instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float] containing the minuend. The lower 32 bits
@@ -112,7 +112,7 @@ _mm_sub_ss(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VSUBPS / SUBPS instructions.
+/// This intrinsic corresponds to the <c> VSUBPS / SUBPS </c> instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float] containing the minuend.
@@ -131,7 +131,7 @@ _mm_sub_ps(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VMULSS / MULSS instructions.
+/// This intrinsic corresponds to the <c> VMULSS / MULSS </c> instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float] containing one of the source operands.
@@ -154,7 +154,7 @@ _mm_mul_ss(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VMULPS / MULPS instructions.
+/// This intrinsic corresponds to the <c> VMULPS / MULPS </c> instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float] containing one of the source operands.
@@ -173,7 +173,7 @@ _mm_mul_ps(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VDIVSS / DIVSS instructions.
+/// This intrinsic corresponds to the <c> VDIVSS / DIVSS </c> instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float] containing the dividend. The lower 32
@@ -195,7 +195,7 @@ _mm_div_ss(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VDIVPS / DIVPS instructions.
+/// This intrinsic corresponds to the <c> VDIVPS / DIVPS </c> instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float] containing the dividend.
@@ -214,7 +214,7 @@ _mm_div_ps(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VSQRTSS / SQRTSS instructions.
+/// This intrinsic corresponds to the <c> VSQRTSS / SQRTSS </c> instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float]. The lower 32 bits of this operand are
@@ -233,7 +233,7 @@ _mm_sqrt_ss(__m128 __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VSQRTPS / SQRTPS instructions.
+/// This intrinsic corresponds to the <c> VSQRTPS / SQRTPS </c> instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float].
@@ -250,7 +250,7 @@ _mm_sqrt_ps(__m128 __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VRCPSS / RCPSS instructions.
+/// This intrinsic corresponds to the <c> VRCPSS / RCPSS </c> instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float]. The lower 32 bits of this operand are
@@ -269,7 +269,7 @@ _mm_rcp_ss(__m128 __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VRCPPS / RCPPS instructions.
+/// This intrinsic corresponds to the <c> VRCPPS / RCPPS </c> instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float].
@@ -286,7 +286,7 @@ _mm_rcp_ps(__m128 __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VRSQRTSS / RSQRTSS instructions.
+/// This intrinsic corresponds to the <c> VRSQRTSS / RSQRTSS </c> instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float]. The lower 32 bits of this operand are
@@ -306,7 +306,7 @@ _mm_rsqrt_ss(__m128 __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VRSQRTPS / RSQRTPS instructions.
+/// This intrinsic corresponds to the <c> VRSQRTPS / RSQRTPS </c> instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float].
@@ -324,7 +324,7 @@ _mm_rsqrt_ps(__m128 __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VMINSS / MINSS instructions.
+/// This intrinsic corresponds to the <c> VMINSS / MINSS </c> instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float] containing one of the operands. The lower
@@ -341,12 +341,12 @@ _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 of each pair of values.
+/// \brief Compares two 128-bit vectors of [4 x float] and returns the lesser
+/// of each pair of values.
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VMINPS / MINPS instructions.
+/// This intrinsic corresponds to the <c> VMINPS / MINPS </c> instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float] containing one of the operands.
@@ -361,12 +361,12 @@ _mm_min_ps(__m128 __a, __m128 __b)
}
/// \brief 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 vector [4 x float].
+/// operands and returns the greater value in the low-order bits of a 128-bit
+/// vector of [4 x float].
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VMAXSS / MAXSS instructions.
+/// This intrinsic corresponds to the <c> VMAXSS / MAXSS </c> instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float] containing one of the operands. The lower
@@ -388,7 +388,7 @@ _mm_max_ss(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VMAXPS / MAXPS instructions.
+/// This intrinsic corresponds to the <c> VMAXPS / MAXPS </c> instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float] containing one of the operands.
@@ -406,7 +406,7 @@ _mm_max_ps(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VANDPS / ANDPS instructions.
+/// This intrinsic corresponds to the <c> VANDPS / ANDPS </c> instructions.
///
/// \param __a
/// A 128-bit vector containing one of the source operands.
@@ -426,7 +426,7 @@ _mm_and_ps(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VANDNPS / ANDNPS instructions.
+/// This intrinsic corresponds to the <c> VANDNPS / ANDNPS </c> instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float] containing the first source operand. The
@@ -446,7 +446,7 @@ _mm_andnot_ps(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VORPS / ORPS instructions.
+/// This intrinsic corresponds to the <c> VORPS / ORPS </c> instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float] containing one of the source operands.
@@ -465,7 +465,7 @@ _mm_or_ps(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VXORPS / XORPS instructions.
+/// This intrinsic corresponds to the <c> VXORPS / XORPS </c> instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float] containing one of the source operands.
@@ -485,7 +485,7 @@ _mm_xor_ps(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCMPEQSS / CMPEQSS instructions.
+/// This intrinsic corresponds to the <c> VCMPEQSS / CMPEQSS </c> instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float] containing one of the operands. The lower
@@ -506,7 +506,7 @@ _mm_cmpeq_ss(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCMPEQPS / CMPEQPS instructions.
+/// This intrinsic corresponds to the <c> VCMPEQPS / CMPEQPS </c> instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float].
@@ -526,7 +526,7 @@ _mm_cmpeq_ps(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCMPLTSS / CMPLTSS instructions.
+/// This intrinsic corresponds to the <c> VCMPLTSS / CMPLTSS </c> instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float] containing one of the operands. The lower
@@ -548,7 +548,7 @@ _mm_cmplt_ss(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCMPLTPS / CMPLTPS instructions.
+/// This intrinsic corresponds to the <c> VCMPLTPS / CMPLTPS </c> instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float].
@@ -569,7 +569,7 @@ _mm_cmplt_ps(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCMPLESS / CMPLESS instructions.
+/// This intrinsic corresponds to the <c> VCMPLESS / CMPLESS </c> instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float] containing one of the operands. The lower
@@ -591,7 +591,7 @@ _mm_cmple_ss(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCMPLEPS / CMPLEPS instructions.
+/// This intrinsic corresponds to the <c> VCMPLEPS / CMPLEPS </c> instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float].
@@ -611,7 +611,7 @@ _mm_cmple_ps(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCMPLTSS / CMPLTSS instructions.
+/// This intrinsic corresponds to the <c> VCMPLTSS / CMPLTSS </c> instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float] containing one of the operands. The lower
@@ -635,7 +635,7 @@ _mm_cmpgt_ss(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCMPLTPS / CMPLTPS instructions.
+/// This intrinsic corresponds to the <c> VCMPLTPS / CMPLTPS </c> instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float].
@@ -656,7 +656,7 @@ _mm_cmpgt_ps(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCMPLESS / CMPLESS instructions.
+/// This intrinsic corresponds to the <c> VCMPLESS / CMPLESS </c> instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float] containing one of the operands. The lower
@@ -680,7 +680,7 @@ _mm_cmpge_ss(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCMPLEPS / CMPLEPS instructions.
+/// This intrinsic corresponds to the <c> VCMPLEPS / CMPLEPS </c> instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float].
@@ -699,7 +699,8 @@ _mm_cmpge_ps(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCMPNEQSS / CMPNEQSS instructions.
+/// This intrinsic corresponds to the <c> VCMPNEQSS / CMPNEQSS </c>
+/// instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float] containing one of the operands. The lower
@@ -720,7 +721,8 @@ _mm_cmpneq_ss(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCMPNEQPS / CMPNEQPS instructions.
+/// This intrinsic corresponds to the <c> VCMPNEQPS / CMPNEQPS </c>
+/// instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float].
@@ -740,7 +742,8 @@ _mm_cmpneq_ps(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCMPNLTSS / CMPNLTSS instructions.
+/// This intrinsic corresponds to the <c> VCMPNLTSS / CMPNLTSS </c>
+/// instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float] containing one of the operands. The lower
@@ -762,7 +765,8 @@ _mm_cmpnlt_ss(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCMPNLTPS / CMPNLTPS instructions.
+/// This intrinsic corresponds to the <c> VCMPNLTPS / CMPNLTPS </c>
+/// instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float].
@@ -783,7 +787,8 @@ _mm_cmpnlt_ps(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCMPNLESS / CMPNLESS instructions.
+/// This intrinsic corresponds to the <c> VCMPNLESS / CMPNLESS </c>
+/// instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float] containing one of the operands. The lower
@@ -805,7 +810,8 @@ _mm_cmpnle_ss(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCMPNLEPS / CMPNLEPS instructions.
+/// This intrinsic corresponds to the <c> VCMPNLEPS / CMPNLEPS </c>
+/// instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float].
@@ -826,7 +832,8 @@ _mm_cmpnle_ps(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCMPNLTSS / CMPNLTSS instructions.
+/// This intrinsic corresponds to the <c> VCMPNLTSS / CMPNLTSS </c>
+/// instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float] containing one of the operands. The lower
@@ -850,7 +857,8 @@ _mm_cmpngt_ss(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCMPNLTPS / CMPNLTPS instructions.
+/// This intrinsic corresponds to the <c> VCMPNLTPS / CMPNLTPS </c>
+/// instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float].
@@ -871,7 +879,8 @@ _mm_cmpngt_ps(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCMPNLESS / CMPNLESS instructions.
+/// This intrinsic corresponds to the <c> VCMPNLESS / CMPNLESS </c>
+/// instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float] containing one of the operands. The lower
@@ -895,7 +904,8 @@ _mm_cmpnge_ss(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCMPNLEPS / CMPNLEPS instructions.
+/// This intrinsic corresponds to the <c> VCMPNLEPS / CMPNLEPS </c>
+/// instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float].
@@ -916,7 +926,8 @@ _mm_cmpnge_ps(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCMPORDSS / CMPORDSS instructions.
+/// This intrinsic corresponds to the <c> VCMPORDSS / CMPORDSS </c>
+/// instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float] containing one of the operands. The lower
@@ -938,7 +949,8 @@ _mm_cmpord_ss(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCMPORDPS / CMPORDPS instructions.
+/// This intrinsic corresponds to the <c> VCMPORDPS / CMPORDPS </c>
+/// instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float].
@@ -959,7 +971,8 @@ _mm_cmpord_ps(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCMPUNORDSS / CMPUNORDSS instructions.
+/// This intrinsic corresponds to the <c> VCMPUNORDSS / CMPUNORDSS </c>
+/// instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float] containing one of the operands. The lower
@@ -981,7 +994,8 @@ _mm_cmpunord_ss(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCMPUNORDPS / CMPUNORDPS instructions.
+/// This intrinsic corresponds to the <c> VCMPUNORDPS / CMPUNORDPS </c>
+/// instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float].
@@ -999,7 +1013,8 @@ _mm_cmpunord_ps(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCOMISS / COMISS instructions.
+/// This intrinsic corresponds to the <c> VCOMISS / COMISS </c>
+/// instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float]. The lower 32 bits of this operand are
@@ -1020,7 +1035,8 @@ _mm_comieq_ss(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCOMISS / COMISS instructions.
+/// This intrinsic corresponds to the <c> VCOMISS / COMISS </c>
+/// instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float]. The lower 32 bits of this operand are
@@ -1041,7 +1057,7 @@ _mm_comilt_ss(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCOMISS / COMISS instructions.
+/// This intrinsic corresponds to the <c> VCOMISS / COMISS </c> instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float]. The lower 32 bits of this operand are
@@ -1062,7 +1078,7 @@ _mm_comile_ss(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCOMISS / COMISS instructions.
+/// This intrinsic corresponds to the <c> VCOMISS / COMISS </c> instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float]. The lower 32 bits of this operand are
@@ -1083,7 +1099,7 @@ _mm_comigt_ss(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCOMISS / COMISS instructions.
+/// This intrinsic corresponds to the <c> VCOMISS / COMISS </c> instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float]. The lower 32 bits of this operand are
@@ -1104,7 +1120,7 @@ _mm_comige_ss(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCOMISS / COMISS instructions.
+/// This intrinsic corresponds to the <c> VCOMISS / COMISS </c> instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float]. The lower 32 bits of this operand are
@@ -1125,7 +1141,7 @@ _mm_comineq_ss(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VUCOMISS / UCOMISS instructions.
+/// This intrinsic corresponds to the <c> VUCOMISS / UCOMISS </c> instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float]. The lower 32 bits of this operand are
@@ -1146,7 +1162,7 @@ _mm_ucomieq_ss(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VUCOMISS / UCOMISS instructions.
+/// This intrinsic corresponds to the <c> VUCOMISS / UCOMISS </c> instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float]. The lower 32 bits of this operand are
@@ -1162,13 +1178,13 @@ _mm_ucomilt_ss(__m128 __a, __m128 __b)
}
/// \brief 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.
+/// 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.
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VUCOMISS / UCOMISS instructions.
+/// This intrinsic corresponds to the <c> VUCOMISS / UCOMISS </c> instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float]. The lower 32 bits of this operand are
@@ -1184,13 +1200,13 @@ _mm_ucomile_ss(__m128 __a, __m128 __b)
}
/// \brief 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
+/// 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.
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VUCOMISS / UCOMISS instructions.
+/// This intrinsic corresponds to the <c> VUCOMISS / UCOMISS </c> instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float]. The lower 32 bits of this operand are
@@ -1212,7 +1228,7 @@ _mm_ucomigt_ss(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VUCOMISS / UCOMISS instructions.
+/// This intrinsic corresponds to the <c> VUCOMISS / UCOMISS </c> instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float]. The lower 32 bits of this operand are
@@ -1233,7 +1249,7 @@ _mm_ucomige_ss(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VUCOMISS / UCOMISS instructions.
+/// This intrinsic corresponds to the <c> VUCOMISS / UCOMISS </c> instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float]. The lower 32 bits of this operand are
@@ -1253,7 +1269,8 @@ _mm_ucomineq_ss(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCVTSS2SI / CVTSS2SI instructions.
+/// This intrinsic corresponds to the <c> VCVTSS2SI / CVTSS2SI </c>
+/// instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float]. The lower 32 bits of this operand are
@@ -1270,7 +1287,8 @@ _mm_cvtss_si32(__m128 __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCVTSS2SI / CVTSS2SI instructions.
+/// This intrinsic corresponds to the <c> VCVTSS2SI / CVTSS2SI </c>
+/// instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float]. The lower 32 bits of this operand are
@@ -1289,7 +1307,8 @@ _mm_cvt_ss2si(__m128 __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCVTSS2SI / CVTSS2SI instructions.
+/// This intrinsic corresponds to the <c> VCVTSS2SI / CVTSS2SI </c>
+/// instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float]. The lower 32 bits of this operand are
@@ -1308,7 +1327,7 @@ _mm_cvtss_si64(__m128 __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c CVTPS2PI instruction.
+/// This intrinsic corresponds to the <c> CVTPS2PI </c> instruction.
///
/// \param __a
/// A 128-bit vector of [4 x float].
@@ -1324,7 +1343,7 @@ _mm_cvtps_pi32(__m128 __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c CVTPS2PI instruction.
+/// This intrinsic corresponds to the <c> CVTPS2PI </c> instruction.
///
/// \param __a
/// A 128-bit vector of [4 x float].
@@ -1341,7 +1360,8 @@ _mm_cvt_ps2pi(__m128 __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCVTTSS2SI / CVTTSS2SI instructions.
+/// This intrinsic corresponds to the <c> VCVTTSS2SI / CVTTSS2SI </c>
+/// instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float]. The lower 32 bits of this operand are
@@ -1359,7 +1379,8 @@ _mm_cvttss_si32(__m128 __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCVTTSS2SI / CVTTSS2SI instructions.
+/// This intrinsic corresponds to the <c> VCVTTSS2SI / CVTTSS2SI </c>
+/// instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float]. The lower 32 bits of this operand are
@@ -1371,13 +1392,15 @@ _mm_cvtt_ss2si(__m128 __a)
return _mm_cvttss_si32(__a);
}
+#ifdef __x86_64__
/// \brief 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.
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCVTTSS2SI / CVTTSS2SI instructions.
+/// This intrinsic corresponds to the <c> VCVTTSS2SI / CVTTSS2SI </c>
+/// instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float]. The lower 32 bits of this operand are
@@ -1388,6 +1411,7 @@ _mm_cvttss_si64(__m128 __a)
{
return __builtin_ia32_cvttss2si64((__v4sf)__a);
}
+#endif
/// \brief 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
@@ -1395,7 +1419,8 @@ _mm_cvttss_si64(__m128 __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c CVTTPS2PI / VTTPS2PI instructions.
+/// This intrinsic corresponds to the <c> CVTTPS2PI / VTTPS2PI </c>
+/// instructions.
///
/// \param __a
/// A 128-bit vector of [4 x float].
@@ -1412,7 +1437,7 @@ _mm_cvttps_pi32(__m128 __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c CVTTPS2PI instruction.
+/// This intrinsic corresponds to the <c> CVTTPS2PI </c> instruction.
///
/// \param __a
/// A 128-bit vector of [4 x float].
@@ -1430,7 +1455,7 @@ _mm_cvtt_ps2pi(__m128 __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCVTSI2SS / CVTSI2SS instruction.
+/// This intrinsic corresponds to the <c> VCVTSI2SS / CVTSI2SS </c> instruction.
///
/// \param __a
/// A 128-bit vector of [4 x float].
@@ -1453,7 +1478,7 @@ _mm_cvtsi32_ss(__m128 __a, int __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCVTSI2SS / CVTSI2SS instruction.
+/// This intrinsic corresponds to the <c> VCVTSI2SS / CVTSI2SS </c> instruction.
///
/// \param __a
/// A 128-bit vector of [4 x float].
@@ -1477,7 +1502,7 @@ _mm_cvt_si2ss(__m128 __a, int __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VCVTSI2SS / CVTSI2SS instruction.
+/// This intrinsic corresponds to the <c> VCVTSI2SS / CVTSI2SS </c> instruction.
///
/// \param __a
/// A 128-bit vector of [4 x float].
@@ -1502,7 +1527,7 @@ _mm_cvtsi64_ss(__m128 __a, long long __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c CVTPI2PS instruction.
+/// This intrinsic corresponds to the <c> CVTPI2PS </c> instruction.
///
/// \param __a
/// A 128-bit vector of [4 x float].
@@ -1525,7 +1550,7 @@ _mm_cvtpi32_ps(__m128 __a, __m64 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c CVTPI2PS instruction.
+/// This intrinsic corresponds to the <c> CVTPI2PS </c> instruction.
///
/// \param __a
/// A 128-bit vector of [4 x float].
@@ -1546,7 +1571,7 @@ _mm_cvt_pi2ps(__m128 __a, __m64 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VMOVSS / MOVSS instruction.
+/// This intrinsic corresponds to the <c> VMOVSS / MOVSS </c> instruction.
///
/// \param __a
/// A 128-bit vector of [4 x float]. The lower 32 bits of this operand are
@@ -1558,13 +1583,13 @@ _mm_cvtss_f32(__m128 __a)
return __a[0];
}
-/// \brief Loads two packed float values from the address __p into the
+/// \brief 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.
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VMOVHPD / MOVHPD instruction.
+/// This intrinsic corresponds to the <c> VMOVHPD / MOVHPD </c> instruction.
///
/// \param __a
/// A 128-bit vector of [4 x float]. Bits [63:0] are written to bits [63:0]
@@ -1585,13 +1610,13 @@ _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 __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.
+/// \brief 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.
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VMOVLPD / MOVLPD instruction.
+/// This intrinsic corresponds to the <c> VMOVLPD / MOVLPD </c> instruction.
///
/// \param __a
/// A 128-bit vector of [4 x float]. Bits [127:64] are written to bits
@@ -1619,7 +1644,7 @@ _mm_loadl_pi(__m128 __a, const __m64 *__p)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VMOVSS / MOVSS instruction.
+/// This intrinsic corresponds to the <c> VMOVSS / MOVSS </c> instruction.
///
/// \param __p
/// A pointer to a 32-bit memory location containing a single-precision
@@ -1642,13 +1667,13 @@ _mm_load_ss(const float *__p)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VMOVSS / MOVSS + \c shuffling
+/// This intrinsic corresponds to the <c> VMOVSS / MOVSS + shuffling </c>
/// instruction.
///
/// \param __p
/// A pointer to a float value to be loaded and duplicated.
-/// \returns A 128-bit vector of [4 x float] containing the loaded
-/// and duplicated values.
+/// \returns A 128-bit vector of [4 x float] containing the loaded and
+/// duplicated values.
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_load1_ps(const float *__p)
{
@@ -1666,7 +1691,7 @@ _mm_load1_ps(const float *__p)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VMOVAPS / MOVAPS instruction.
+/// This intrinsic corresponds to the <c> VMOVAPS / MOVAPS </c> instruction.
///
/// \param __p
/// A pointer to a 128-bit memory location. The address of the memory
@@ -1683,7 +1708,7 @@ _mm_load_ps(const float *__p)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VMOVUPS / MOVUPS instruction.
+/// This intrinsic corresponds to the <c> VMOVUPS / MOVUPS </c> instruction.
///
/// \param __p
/// A pointer to a 128-bit memory location. The address of the memory
@@ -1703,7 +1728,7 @@ _mm_loadu_ps(const float *__p)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VMOVAPS / MOVAPS + \c shuffling
+/// This intrinsic corresponds to the <c> VMOVAPS / MOVAPS + shuffling </c>
/// instruction.
///
/// \param __p
@@ -1725,7 +1750,6 @@ _mm_loadr_ps(const float *__p)
/// This intrinsic has no corresponding instruction.
///
/// \returns A 128-bit vector of [4 x float] containing undefined values.
-
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_undefined_ps(void)
{
@@ -1738,7 +1762,7 @@ _mm_undefined_ps(void)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VMOVSS / MOVSS instruction.
+/// This intrinsic corresponds to the <c> VMOVSS / MOVSS </c> instruction.
///
/// \param __w
/// A single-precision floating-point value used to initialize the lower 32
@@ -1758,7 +1782,7 @@ _mm_set_ss(float __w)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPERMILPS / PERMILPS instruction.
+/// This intrinsic corresponds to the <c> VPERMILPS / PERMILPS </c> instruction.
///
/// \param __w
/// A single-precision floating-point value used to initialize each vector
@@ -1777,7 +1801,7 @@ _mm_set1_ps(float __w)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPERMILPS / PERMILPS instruction.
+/// This intrinsic corresponds to the <c> VPERMILPS / PERMILPS </c> instruction.
///
/// \param __w
/// A single-precision floating-point value used to initialize each vector
@@ -1849,7 +1873,7 @@ _mm_setr_ps(float __z, float __y, float __x, float __w)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VXORPS / XORPS instruction.
+/// This intrinsic corresponds to the <c> VXORPS / XORPS </c> instruction.
///
/// \returns An initialized 128-bit floating-point vector of [4 x float] with
/// all elements set to zero.
@@ -1864,7 +1888,7 @@ _mm_setzero_ps(void)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPEXTRQ / MOVQ instruction.
+/// This intrinsic corresponds to the <c> VPEXTRQ / MOVQ </c> instruction.
///
/// \param __p
/// A pointer to a 64-bit memory location.
@@ -1881,7 +1905,7 @@ _mm_storeh_pi(__m64 *__p, __m128 __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VMOVLPS / MOVLPS instruction.
+/// This intrinsic corresponds to the <c> VMOVLPS / MOVLPS </c> instruction.
///
/// \param __p
/// A pointer to a memory location that will receive the float values.
@@ -1898,7 +1922,7 @@ _mm_storel_pi(__m64 *__p, __m128 __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VMOVSS / MOVSS instruction.
+/// This intrinsic corresponds to the <c> VMOVSS / MOVSS </c> instruction.
///
/// \param __p
/// A pointer to a 32-bit memory location.
@@ -1913,12 +1937,12 @@ _mm_store_ss(float *__p, __m128 __a)
((struct __mm_store_ss_struct*)__p)->__u = __a[0];
}
-/// \brief Stores float values from a 128-bit vector of [4 x float] to an
-/// unaligned memory location.
+/// \brief Stores a 128-bit vector of [4 x float] to an unaligned memory
+/// location.
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VMOVUPS / MOVUPS instruction.
+/// This intrinsic corresponds to the <c> VMOVUPS / MOVUPS </c> instruction.
///
/// \param __p
/// A pointer to a 128-bit memory location. The address of the memory
@@ -1934,19 +1958,18 @@ _mm_storeu_ps(float *__p, __m128 __a)
((struct __storeu_ps*)__p)->__v = __a;
}
-/// \brief Stores the lower 32 bits of a 128-bit vector of [4 x float] into
-/// four contiguous elements in an aligned memory location.
+/// \brief Stores a 128-bit vector of [4 x float] into an aligned memory
+/// location.
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to \c VMOVAPS / MOVAPS + \c shuffling
-/// instruction.
+/// This intrinsic corresponds to the <c> VMOVAPS / MOVAPS </c> instruction.
///
/// \param __p
-/// A pointer to a 128-bit memory location.
+/// A pointer to a 128-bit memory location. The address of the memory
+/// location has to be 16-byte aligned.
/// \param __a
-/// A 128-bit vector of [4 x float] whose lower 32 bits are stored to each
-/// of the four contiguous elements pointed by __p.
+/// A 128-bit vector of [4 x float] containing the values to be stored.
static __inline__ void __DEFAULT_FN_ATTRS
_mm_store_ps(float *__p, __m128 __a)
{
@@ -1958,14 +1981,14 @@ _mm_store_ps(float *__p, __m128 __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to \c VMOVAPS / MOVAPS + \c shuffling
+/// This intrinsic corresponds to <c> VMOVAPS / MOVAPS + shuffling </c>
/// instruction.
///
/// \param __p
/// A pointer to a 128-bit memory location.
/// \param __a
/// A 128-bit vector of [4 x float] whose lower 32 bits are stored to each
-/// of the four contiguous elements pointed by __p.
+/// of the four contiguous elements pointed by \a __p.
static __inline__ void __DEFAULT_FN_ATTRS
_mm_store1_ps(float *__p, __m128 __a)
{
@@ -1973,18 +1996,19 @@ _mm_store1_ps(float *__p, __m128 __a)
_mm_store_ps(__p, __a);
}
-/// \brief Stores float values from a 128-bit vector of [4 x float] to an
-/// aligned memory location.
+/// \brief 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>
///
-/// This intrinsic corresponds to the \c VMOVAPS / MOVAPS instruction.
+/// This intrinsic corresponds to <c> VMOVAPS / MOVAPS + shuffling </c>
+/// instruction.
///
/// \param __p
-/// A pointer to a 128-bit memory location. The address of the memory
-/// location has to be 128-bit aligned.
+/// A pointer to a 128-bit memory location.
/// \param __a
-/// A 128-bit vector of [4 x float] containing the values to be stored.
+/// A 128-bit vector of [4 x float] whose lower 32 bits are stored to each
+/// of the four contiguous elements pointed by \a __p.
static __inline__ void __DEFAULT_FN_ATTRS
_mm_store_ps1(float *__p, __m128 __a)
{
@@ -1996,7 +2020,7 @@ _mm_store_ps1(float *__p, __m128 __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VMOVAPS / MOVAPS + \c shuffling
+/// This intrinsic corresponds to the <c> VMOVAPS / MOVAPS + shuffling </c>
/// instruction.
///
/// \param __p
@@ -2029,20 +2053,21 @@ _mm_storer_ps(float *__p, __m128 __a)
/// void _mm_prefetch(const void * a, const int sel);
/// \endcode
///
-/// This intrinsic corresponds to the \c PREFETCHNTA instruction.
+/// This intrinsic corresponds to the <c> PREFETCHNTA </c> instruction.
///
/// \param a
/// A pointer to a memory location containing a cache line of data.
/// \param sel
-/// A predefined integer constant specifying the type of prefetch operation:
-/// _MM_HINT_NTA: Move data using the non-temporal access (NTA) hint.
-/// The PREFETCHNTA instruction will be generated.
+/// A predefined integer constant specifying the type of prefetch
+/// operation: \n
+/// _MM_HINT_NTA: Move data using the non-temporal access (NTA) hint. The
+/// PREFETCHNTA instruction will be generated. \n
/// _MM_HINT_T0: Move data using the T0 hint. The PREFETCHT0 instruction will
-/// be generated.
+/// be generated. \n
/// _MM_HINT_T1: Move data using the T1 hint. The PREFETCHT1 instruction will
-/// be generated.
+/// be generated. \n
/// _MM_HINT_T2: Move data using the T2 hint. The PREFETCHT2 instruction will
-/// be generated.
+/// be generated.
#define _mm_prefetch(a, sel) (__builtin_prefetch((void *)(a), 0, (sel)))
#endif
@@ -2052,7 +2077,7 @@ _mm_storer_ps(float *__p, __m128 __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c MOVNTQ instruction.
+/// This intrinsic corresponds to the <c> MOVNTQ </c> instruction.
///
/// \param __p
/// A pointer to an aligned memory location used to store the register value.
@@ -2070,7 +2095,7 @@ _mm_stream_pi(__m64 *__p, __m64 __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VMOVNTPS / MOVNTPS instruction.
+/// This intrinsic corresponds to the <c> VMOVNTPS / MOVNTPS </c> instruction.
///
/// \param __p
/// A pointer to a 128-bit aligned memory location that will receive the
@@ -2083,6 +2108,10 @@ _mm_stream_ps(float *__p, __m128 __a)
__builtin_nontemporal_store((__v4sf)__a, (__v4sf*)__p);
}
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
/// \brief Forces strong memory ordering (serialization) between store
/// instructions preceding this instruction and store instructions following
/// this instruction, ensuring the system completes all previous stores
@@ -2090,28 +2119,32 @@ _mm_stream_ps(float *__p, __m128 __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c SFENCE instruction.
+/// This intrinsic corresponds to the <c> SFENCE </c> instruction.
///
-static __inline__ void __DEFAULT_FN_ATTRS
-_mm_sfence(void)
-{
- __builtin_ia32_sfence();
-}
+void _mm_sfence(void);
+
+#if defined(__cplusplus)
+} // extern "C"
+#endif
/// \brief 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>
///
-/// This intrinsic corresponds to the \c VPEXTRW / PEXTRW instruction.
+/// \code
+/// void _mm_extract_pi(__m64 a, int n);
+/// \endcode
///
-/// \param __a
+/// This intrinsic corresponds to the <c> VPEXTRW / PEXTRW </c> instruction.
+///
+/// \param a
/// A 64-bit vector of [4 x i16].
-/// \param __n
-/// An immediate integer operand that determines which bits are extracted:
-/// 0: Bits [15:0] are copied to the destination.
-/// 1: Bits [31:16] are copied to the destination.
-/// 2: Bits [47:32] are copied to the destination.
+/// \param n
+/// An immediate integer operand that determines which bits are extracted: \n
+/// 0: Bits [15:0] are copied to the destination. \n
+/// 1: Bits [31:16] are copied to the destination. \n
+/// 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__ ({ \
@@ -2119,26 +2152,30 @@ _mm_sfence(void)
/// \brief 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 __n.
+/// specified by the immediate operand \a n.
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VPINSRW / PINSRW instruction.
+/// \code
+/// void _mm_insert_pi(__m64 a, int d, int n);
+/// \endcode
///
-/// \param __a
+/// This intrinsic corresponds to the <c> VPINSRW / PINSRW </c> instruction.
+///
+/// \param a
/// A 64-bit vector of [4 x i16].
-/// \param __d
+/// \param d
/// An integer. The lower 16-bit value from this operand is written to the
-/// destination at the offset specified by operand __n.
-/// \param __n
+/// destination at the offset specified by operand \a n.
+/// \param n
/// An immediate integer operant that determines which the bits to be used
-/// in the destination.
-/// 0: Bits [15:0] are copied to the destination.
-/// 1: Bits [31:16] are copied to the destination.
-/// 2: Bits [47:32] are copied to the destination.
-/// 3: Bits [63:48] are copied to the destination.
+/// in the destination. \n
+/// 0: Bits [15:0] are copied to the destination. \n
+/// 1: Bits [31:16] are copied to the destination. \n
+/// 2: Bits [47:32] are copied to the destination. \n
+/// 3: Bits [63:48] are copied to the destination. \n
/// The remaining bits in the destination are copied from the corresponding
-/// bits in operand __a.
+/// 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__ ({ \
@@ -2150,7 +2187,7 @@ _mm_sfence(void)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PMAXSW instruction.
+/// This intrinsic corresponds to the <c> PMAXSW </c> instruction.
///
/// \param __a
/// A 64-bit integer vector containing one of the source operands.
@@ -2169,7 +2206,7 @@ _mm_max_pi16(__m64 __a, __m64 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PMAXUB instruction.
+/// This intrinsic corresponds to the <c> PMAXUB </c> instruction.
///
/// \param __a
/// A 64-bit integer vector containing one of the source operands.
@@ -2188,7 +2225,7 @@ _mm_max_pu8(__m64 __a, __m64 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PMINSW instruction.
+/// This intrinsic corresponds to the <c> PMINSW </c> instruction.
///
/// \param __a
/// A 64-bit integer vector containing one of the source operands.
@@ -2207,7 +2244,7 @@ _mm_min_pi16(__m64 __a, __m64 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PMINUB instruction.
+/// This intrinsic corresponds to the <c> PMINUB </c> instruction.
///
/// \param __a
/// A 64-bit integer vector containing one of the source operands.
@@ -2226,7 +2263,7 @@ _mm_min_pu8(__m64 __a, __m64 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PMOVMSKB instruction.
+/// This intrinsic corresponds to the <c> PMOVMSKB </c> instruction.
///
/// \param __a
/// A 64-bit integer vector containing the values with bits to be extracted.
@@ -2244,7 +2281,7 @@ _mm_movemask_pi8(__m64 __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PMULHUW instruction.
+/// This intrinsic corresponds to the <c> PMULHUW </c> instruction.
///
/// \param __a
/// A 64-bit integer vector containing one of the source operands.
@@ -2262,27 +2299,31 @@ _mm_mulhi_pu16(__m64 __a, __m64 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PSHUFW instruction.
-///
/// \code
/// __m64 _mm_shuffle_pi16(__m64 a, const int n);
/// \endcode
///
+/// This intrinsic corresponds to the <c> PSHUFW </c> instruction.
+///
/// \param a
/// A 64-bit integer vector containing the values to be shuffled.
/// \param n
/// An immediate value containing an 8-bit value specifying which elements to
-/// copy from a. The destinations within the 64-bit destination are assigned
-/// values as follows:
-/// Bits [1:0] are used to assign values to bits [15:0] in the destination.
-/// Bits [3:2] are used to assign values to bits [31:16] in the destination.
-/// Bits [5:4] are used to assign values to bits [47:32] in the destination.
-/// Bits [7:6] are used to assign values to bits [63:48] in the destination.
-/// Bit value assignments:
-/// 00: assigned from bits [15:0] of a.
-/// 01: assigned from bits [31:16] of a.
-/// 10: assigned from bits [47:32] of a.
-/// 11: assigned from bits [63:48] of a.
+/// copy from \a a. The destinations within the 64-bit destination are
+/// assigned values as follows: \n
+/// Bits [1:0] are used to assign values to bits [15:0] in the
+/// destination. \n
+/// Bits [3:2] are used to assign values to bits [31:16] in the
+/// destination. \n
+/// Bits [5:4] are used to assign values to bits [47:32] in the
+/// destination. \n
+/// Bits [7:6] are used to assign values to bits [63:48] in the
+/// destination. \n
+/// Bit value assignments: \n
+/// 00: assigned from bits [15:0] of \a a. \n
+/// 01: assigned from bits [31:16] of \a a. \n
+/// 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)); })
@@ -2295,15 +2336,15 @@ _mm_mulhi_pu16(__m64 __a, __m64 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c MASKMOVQ instruction.
+/// This intrinsic corresponds to the <c> MASKMOVQ </c> instruction.
///
/// \param __d
/// A 64-bit integer vector containing the values with elements to be copied.
/// \param __n
/// A 64-bit integer vector operand. The most significant bit from each 8-bit
-/// element determines whether the corresponding element in operand __d is
-/// copied. If the most significant bit of a given element is 1, the
-/// corresponding element in operand __d is copied.
+/// element determines whether the corresponding element in operand \a __d
+/// is copied. If the most significant bit of a given element is 1, the
+/// corresponding element in operand \a __d is copied.
/// \param __p
/// 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
@@ -2320,7 +2361,7 @@ _mm_maskmove_si64(__m64 __d, __m64 __n, char *__p)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PAVGB instruction.
+/// This intrinsic corresponds to the <c> PAVGB </c> instruction.
///
/// \param __a
/// A 64-bit integer vector containing one of the source operands.
@@ -2339,7 +2380,7 @@ _mm_avg_pu8(__m64 __a, __m64 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PAVGW instruction.
+/// This intrinsic corresponds to the <c> PAVGW </c> instruction.
///
/// \param __a
/// A 64-bit integer vector containing one of the source operands.
@@ -2359,7 +2400,7 @@ _mm_avg_pu16(__m64 __a, __m64 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c PSADBW instruction.
+/// This intrinsic corresponds to the <c> PSADBW </c> instruction.
///
/// \param __a
/// A 64-bit integer vector containing one of the source operands.
@@ -2374,24 +2415,42 @@ _mm_sad_pu8(__m64 __a, __m64 __b)
return (__m64)__builtin_ia32_psadbw((__v8qi)__a, (__v8qi)__b);
}
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
/// \brief Returns the contents of the MXCSR register as a 32-bit unsigned
-/// integer value. There are several groups of macros associated with this
+/// integer value.
+///
+/// There are several groups of macros associated with this
/// intrinsic, including:
-/// * For checking exception states: _MM_EXCEPT_INVALID, _MM_EXCEPT_DIV_ZERO,
+/// <ul>
+/// <li>
+/// For checking exception states: _MM_EXCEPT_INVALID, _MM_EXCEPT_DIV_ZERO,
/// _MM_EXCEPT_DENORM, _MM_EXCEPT_OVERFLOW, _MM_EXCEPT_UNDERFLOW,
/// _MM_EXCEPT_INEXACT. There is a convenience wrapper
/// _MM_GET_EXCEPTION_STATE().
-/// * For checking exception masks: _MM_MASK_UNDERFLOW, _MM_MASK_OVERFLOW,
+/// </li>
+/// <li>
+/// For checking exception masks: _MM_MASK_UNDERFLOW, _MM_MASK_OVERFLOW,
/// _MM_MASK_INVALID, _MM_MASK_DENORM, _MM_MASK_DIV_ZERO, _MM_MASK_INEXACT.
/// There is a convenience wrapper _MM_GET_EXCEPTION_MASK().
-/// * For checking rounding modes: _MM_ROUND_NEAREST, _MM_ROUND_DOWN,
+/// </li>
+/// <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.
-/// * For checking flush-to-zero mode: _MM_FLUSH_ZERO_ON, _MM_FLUSH_ZERO_OFF.
+/// </li>
+/// <li>
+/// For checking flush-to-zero mode: _MM_FLUSH_ZERO_ON, _MM_FLUSH_ZERO_OFF.
/// There is a convenience wrapper _MM_GET_FLUSH_ZERO_MODE().
-/// * For checking denormals-are-zero mode: _MM_DENORMALS_ZERO_ON,
+/// </li>
+/// <li>
+/// For checking denormals-are-zero mode: _MM_DENORMALS_ZERO_ON,
/// _MM_DENORMALS_ZERO_OFF. There is a convenience wrapper
/// _MM_GET_DENORMALS_ZERO_MODE().
+/// </li>
+/// </ul>
///
/// For example, the expression below checks if an overflow exception has
/// occurred:
@@ -2402,35 +2461,45 @@ _mm_sad_pu8(__m64 __a, __m64 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VSTMXCSR / STMXCSR instruction.
+/// This intrinsic corresponds to the <c> VSTMXCSR / STMXCSR </c> instruction.
///
/// \returns A 32-bit unsigned integer containing the contents of the MXCSR
/// register.
-static __inline__ unsigned int __DEFAULT_FN_ATTRS
-_mm_getcsr(void)
-{
- return __builtin_ia32_stmxcsr();
-}
-
-/// \brief Sets the MXCSR register with the 32-bit unsigned integer value. There
-/// are several groups of macros associated with this intrinsic, including:
-/// * For setting exception states: _MM_EXCEPT_INVALID, _MM_EXCEPT_DIV_ZERO,
+unsigned int _mm_getcsr(void);
+
+/// \brief Sets the MXCSR register with the 32-bit unsigned integer value.
+///
+/// There are several groups of macros associated with this intrinsic,
+/// including:
+/// <ul>
+/// <li>
+/// For setting exception states: _MM_EXCEPT_INVALID, _MM_EXCEPT_DIV_ZERO,
/// _MM_EXCEPT_DENORM, _MM_EXCEPT_OVERFLOW, _MM_EXCEPT_UNDERFLOW,
/// _MM_EXCEPT_INEXACT. There is a convenience wrapper
/// _MM_SET_EXCEPTION_STATE(x) where x is one of these macros.
-/// * For setting exception masks: _MM_MASK_UNDERFLOW, _MM_MASK_OVERFLOW,
+/// </li>
+/// <li>
+/// For setting exception masks: _MM_MASK_UNDERFLOW, _MM_MASK_OVERFLOW,
/// _MM_MASK_INVALID, _MM_MASK_DENORM, _MM_MASK_DIV_ZERO, _MM_MASK_INEXACT.
/// There is a convenience wrapper _MM_SET_EXCEPTION_MASK(x) where x is one
/// of these macros.
-/// * For setting rounding modes: _MM_ROUND_NEAREST, _MM_ROUND_DOWN,
+/// </li>
+/// <li>
+/// For setting rounding modes: _MM_ROUND_NEAREST, _MM_ROUND_DOWN,
/// _MM_ROUND_UP, _MM_ROUND_TOWARD_ZERO. There is a convenience wrapper
/// _MM_SET_ROUNDING_MODE(x) where x is one of these macros.
-/// * For setting flush-to-zero mode: _MM_FLUSH_ZERO_ON, _MM_FLUSH_ZERO_OFF.
+/// </li>
+/// <li>
+/// For setting flush-to-zero mode: _MM_FLUSH_ZERO_ON, _MM_FLUSH_ZERO_OFF.
/// There is a convenience wrapper _MM_SET_FLUSH_ZERO_MODE(x) where x is
/// one of these macros.
-/// * For setting denormals-are-zero mode: _MM_DENORMALS_ZERO_ON,
+/// </li>
+/// <li>
+/// For setting denormals-are-zero mode: _MM_DENORMALS_ZERO_ON,
/// _MM_DENORMALS_ZERO_OFF. There is a convenience wrapper
/// _MM_SET_DENORMALS_ZERO_MODE(x) where x is one of these macros.
+/// </li>
+/// </ul>
///
/// For example, the following expression causes subsequent floating-point
/// operations to round up:
@@ -2444,15 +2513,15 @@ _mm_getcsr(void)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VLDMXCSR / LDMXCSR instruction.
+/// This intrinsic corresponds to the <c> VLDMXCSR / LDMXCSR </c> instruction.
///
/// \param __i
/// A 32-bit unsigned integer value to be written to the MXCSR register.
-static __inline__ void __DEFAULT_FN_ATTRS
-_mm_setcsr(unsigned int __i)
-{
- __builtin_ia32_ldmxcsr(__i);
-}
+void _mm_setcsr(unsigned int);
+
+#if defined(__cplusplus)
+} // extern "C"
+#endif
/// \brief Selects 4 float values from the 128-bit operands of [4 x float], as
/// specified by the immediate value operand.
@@ -2463,7 +2532,7 @@ _mm_setcsr(unsigned int __i)
/// __m128 _mm_shuffle_ps(__m128 a, __m128 b, const int mask);
/// \endcode
///
-/// This intrinsic corresponds to the \c VSHUFPS / SHUFPS instruction.
+/// This intrinsic corresponds to the <c> VSHUFPS / SHUFPS </c> instruction.
///
/// \param a
/// A 128-bit vector of [4 x float].
@@ -2471,18 +2540,23 @@ _mm_setcsr(unsigned int __i)
/// A 128-bit vector of [4 x float].
/// \param mask
/// An immediate value containing an 8-bit value specifying which elements to
-/// copy from a and b.
-/// Bits [3:0] specify the values copied from operand a.
-/// Bits [7:4] specify the values copied from operand b. The destinations
-/// within the 128-bit destination are assigned values as follows:
-/// Bits [1:0] are used to assign values to bits [31:0] in the destination.
-/// Bits [3:2] are used to assign values to bits [63:32] in the destination.
-/// Bits [5:4] are used to assign values to bits [95:64] in the destination.
-/// Bits [7:6] are used to assign values to bits [127:96] in the destination.
-/// Bit value assignments:
-/// 00: Bits [31:0] copied from the specified operand.
-/// 01: Bits [63:32] copied from the specified operand.
-/// 10: Bits [95:64] copied from the specified operand.
+/// copy from \ a and \a b. \n
+/// Bits [3:0] specify the values copied from operand \a a. \n
+/// Bits [7:4] specify the values copied from operand \a b. \n
+/// The destinations within the 128-bit destination are assigned values as
+/// follows: \n
+/// Bits [1:0] are used to assign values to bits [31:0] in the
+/// destination. \n
+/// Bits [3:2] are used to assign values to bits [63:32] in the
+/// destination. \n
+/// Bits [5:4] are used to assign values to bits [95:64] in the
+/// destination. \n
+/// Bits [7:6] are used to assign values to bits [127:96] in the
+/// destination. \n
+/// Bit value assignments: \n
+/// 00: Bits [31:0] copied from the specified operand. \n
+/// 01: Bits [63:32] copied from the specified operand. \n
+/// 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__ ({ \
@@ -2493,20 +2567,19 @@ _mm_setcsr(unsigned int __i)
4 + (((mask) >> 6) & 0x3)); })
/// \brief 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].
+/// [4 x float] and interleaves them into a 128-bit vector of [4 x float].
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VUNPCKHPS / UNPCKHPS instruction.
+/// This intrinsic corresponds to the <c> VUNPCKHPS / UNPCKHPS </c> instruction.
///
/// \param __a
-/// A 128-bit vector of [4 x float].
-/// Bits [95:64] are written to bits [31:0] of the destination.
+/// A 128-bit vector of [4 x float]. \n
+/// Bits [95:64] are written to bits [31:0] of the destination. \n
/// Bits [127:96] are written to bits [95:64] of the destination.
/// \param __b
/// A 128-bit vector of [4 x float].
-/// Bits [95:64] are written to bits [63:32] of the destination.
+/// Bits [95:64] are written to bits [63:32] of the destination. \n
/// Bits [127:96] are written to bits [127:96] of the destination.
/// \returns A 128-bit vector of [4 x float] containing the interleaved values.
static __inline__ __m128 __DEFAULT_FN_ATTRS
@@ -2516,20 +2589,19 @@ _mm_unpackhi_ps(__m128 __a, __m128 __b)
}
/// \brief 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].
+/// [4 x float] and interleaves them into a 128-bit vector of [4 x float].
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VUNPCKLPS / UNPCKLPS instruction.
+/// This intrinsic corresponds to the <c> VUNPCKLPS / UNPCKLPS </c> instruction.
///
/// \param __a
-/// A 128-bit vector of [4 x float].
-/// Bits [31:0] are written to bits [31:0] of the destination.
+/// A 128-bit vector of [4 x float]. \n
+/// Bits [31:0] are written to bits [31:0] of the destination. \n
/// Bits [63:32] are written to bits [95:64] of the destination.
/// \param __b
-/// A 128-bit vector of [4 x float].
-/// Bits [31:0] are written to bits [63:32] of the destination.
+/// A 128-bit vector of [4 x float]. \n
+/// Bits [31:0] are written to bits [63:32] of the destination. \n
/// Bits [63:32] are written to bits [127:96] of the destination.
/// \returns A 128-bit vector of [4 x float] containing the interleaved values.
static __inline__ __m128 __DEFAULT_FN_ATTRS
@@ -2544,7 +2616,7 @@ _mm_unpacklo_ps(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VMOVSS / MOVSS instruction.
+/// This intrinsic corresponds to the <c> VMOVSS / MOVSS </c> instruction.
///
/// \param __a
/// A 128-bit floating-point vector of [4 x float]. The upper 96 bits are
@@ -2565,7 +2637,7 @@ _mm_move_ss(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VUNPCKHPD / UNPCKHPD instruction.
+/// This intrinsic corresponds to the <c> VUNPCKHPD / UNPCKHPD </c> instruction.
///
/// \param __a
/// A 128-bit floating-point vector of [4 x float]. The upper 64 bits are
@@ -2586,7 +2658,7 @@ _mm_movehl_ps(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VUNPCKLPD / UNPCKLPD instruction.
+/// This intrinsic corresponds to the <c> VUNPCKLPD / UNPCKLPD </c> instruction.
///
/// \param __a
/// A 128-bit floating-point vector of [4 x float]. The lower 64 bits are
@@ -2606,7 +2678,8 @@ _mm_movelh_ps(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c CVTPI2PS + \c COMPOSITE instruction.
+/// This intrinsic corresponds to the <c> CVTPI2PS + \c COMPOSITE </c>
+/// instruction.
///
/// \param __a
/// A 64-bit vector of [4 x i16]. The elements of the destination are copied
@@ -2636,7 +2709,8 @@ _mm_cvtpi16_ps(__m64 __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c CVTPI2PS + \c COMPOSITE instruction.
+/// This intrinsic corresponds to the <c> CVTPI2PS + \c COMPOSITE </c>
+/// instruction.
///
/// \param __a
/// A 64-bit vector of 16-bit unsigned integer values. The elements of the
@@ -2665,7 +2739,8 @@ _mm_cvtpu16_ps(__m64 __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c CVTPI2PS + \c COMPOSITE instruction.
+/// This intrinsic corresponds to the <c> CVTPI2PS + \c COMPOSITE </c>
+/// instruction.
///
/// \param __a
/// A 64-bit vector of [8 x i8]. The elements of the destination are copied
@@ -2689,7 +2764,8 @@ _mm_cvtpi8_ps(__m64 __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c CVTPI2PS + \c COMPOSITE instruction.
+/// This intrinsic corresponds to the <c> CVTPI2PS + \c COMPOSITE </c>
+/// instruction.
///
/// \param __a
/// A 64-bit vector of unsigned 8-bit integer values. The elements of the
@@ -2713,7 +2789,8 @@ _mm_cvtpu8_ps(__m64 __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c CVTPI2PS + \c COMPOSITE instruction.
+/// This intrinsic corresponds to the <c> CVTPI2PS + \c COMPOSITE </c>
+/// instruction.
///
/// \param __a
/// A 64-bit vector of [2 x i32]. The lower elements of the destination are
@@ -2741,12 +2818,13 @@ _mm_cvtpi32x2_ps(__m64 __a, __m64 __b)
/// packs the results into a 64-bit integer vector of [4 x i16]. If the
/// floating-point element is NaN or infinity, or if the floating-point
/// element is greater than 0x7FFFFFFF or less than -0x8000, it is converted
-/// to 0x8000. Otherwise if the floating-point element is greater
-/// than 0x7FFF, it is converted to 0x7FFF.
+/// to 0x8000. Otherwise if the floating-point element is greater than
+/// 0x7FFF, it is converted to 0x7FFF.
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c CVTPS2PI + \c COMPOSITE instruction.
+/// This intrinsic corresponds to the <c> CVTPS2PI + \c COMPOSITE </c>
+/// instruction.
///
/// \param __a
/// A 128-bit floating-point vector of [4 x float].
@@ -2770,12 +2848,13 @@ _mm_cvtps_pi16(__m128 __a)
/// [8 x i8]. The upper 32 bits of the vector are set to 0. If the
/// floating-point element is NaN or infinity, or if the floating-point
/// element is greater than 0x7FFFFFFF or less than -0x80, it is converted
-/// to 0x80. Otherwise if the floating-point element is greater
-/// than 0x7F, it is converted to 0x7F.
+/// to 0x80. Otherwise if the floating-point element is greater than 0x7F,
+/// it is converted to 0x7F.
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c CVTPS2PI + \c COMPOSITE instruction.
+/// This intrinsic corresponds to the <c> CVTPS2PI + \c COMPOSITE </c>
+/// instruction.
///
/// \param __a
/// 128-bit floating-point vector of [4 x float].
@@ -2799,7 +2878,7 @@ _mm_cvtps_pi8(__m128 __a)
///
/// \headerfile <x86intrin.h>
///
-/// This intrinsic corresponds to the \c VMOVMSKPS / MOVMSKPS instruction.
+/// This intrinsic corresponds to the <c> VMOVMSKPS / MOVMSKPS </c> instruction.
///
/// \param __a
/// A 128-bit floating-point vector of [4 x float].
diff --git a/lib/Index/CommentToXML.cpp b/lib/Index/CommentToXML.cpp
index c4beef249466..ee066cc6d985 100644
--- a/lib/Index/CommentToXML.cpp
+++ b/lib/Index/CommentToXML.cpp
@@ -8,7 +8,6 @@
//===----------------------------------------------------------------------===//
#include "clang/Index/CommentToXML.h"
-#include "SimpleFormatContext.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Comment.h"
@@ -531,12 +530,8 @@ public:
CommentASTToXMLConverter(const FullComment *FC,
SmallVectorImpl<char> &Str,
const CommandTraits &Traits,
- const SourceManager &SM,
- SimpleFormatContext &SFC,
- unsigned FUID) :
- FC(FC), Result(Str), Traits(Traits), SM(SM),
- FormatRewriterContext(SFC),
- FormatInMemoryUniqueId(FUID) { }
+ const SourceManager &SM) :
+ FC(FC), Result(Str), Traits(Traits), SM(SM) { }
// Inline content.
void visitTextComment(const TextComment *C);
@@ -574,8 +569,6 @@ private:
const CommandTraits &Traits;
const SourceManager &SM;
- SimpleFormatContext &FormatRewriterContext;
- unsigned FormatInMemoryUniqueId;
};
void getSourceTextOfDeclaration(const DeclInfo *ThisDecl,
@@ -596,21 +589,17 @@ void CommentASTToXMLConverter::formatTextOfDeclaration(
StringRef StringDecl(Declaration.c_str(), Declaration.size());
// Formatter specific code.
- // Form a unique in memory buffer name.
- SmallString<128> filename;
- filename += "xmldecl";
- filename += llvm::utostr(FormatInMemoryUniqueId);
- filename += ".xd";
- FileID ID = FormatRewriterContext.createInMemoryFile(filename, StringDecl);
- SourceLocation Start = FormatRewriterContext.Sources.getLocForStartOfFile(ID)
- .getLocWithOffset(0);
+ unsigned Offset = 0;
unsigned Length = Declaration.size();
- tooling::Replacements Replace = reformat(
- format::getLLVMStyle(), FormatRewriterContext.Sources, ID,
- CharSourceRange::getCharRange(Start, Start.getLocWithOffset(Length)));
- applyAllReplacements(Replace, FormatRewriterContext.Rewrite);
- Declaration = FormatRewriterContext.getRewrittenText(ID);
+ bool IncompleteFormat = false;
+ tooling::Replacements Replaces =
+ reformat(format::getLLVMStyle(), StringDecl,
+ tooling::Range(Offset, Length), "xmldecl.xd", &IncompleteFormat);
+ auto FormattedStringDecl = applyAllReplacements(StringDecl, Replaces);
+ if (static_cast<bool>(FormattedStringDecl)) {
+ Declaration = *FormattedStringDecl;
+ }
}
} // end unnamed namespace
@@ -1126,7 +1115,7 @@ void CommentASTToXMLConverter::appendToResultWithCDATAEscaping(StringRef S) {
Result << "]]>";
}
-CommentToXMLConverter::CommentToXMLConverter() : FormatInMemoryUniqueId(0) {}
+CommentToXMLConverter::CommentToXMLConverter() {}
CommentToXMLConverter::~CommentToXMLConverter() {}
void CommentToXMLConverter::convertCommentToHTML(const FullComment *FC,
@@ -1148,15 +1137,7 @@ void CommentToXMLConverter::convertHTMLTagNodeToText(
void CommentToXMLConverter::convertCommentToXML(const FullComment *FC,
SmallVectorImpl<char> &XML,
const ASTContext &Context) {
- if (!FormatContext || (FormatInMemoryUniqueId % 1000) == 0) {
- // Create a new format context, or re-create it after some number of
- // iterations, so the buffers don't grow too large.
- FormatContext.reset(new SimpleFormatContext(Context.getLangOpts()));
- }
-
CommentASTToXMLConverter Converter(FC, XML, Context.getCommentCommandTraits(),
- Context.getSourceManager(), *FormatContext,
- FormatInMemoryUniqueId++);
+ Context.getSourceManager());
Converter.visit(FC);
}
-
diff --git a/lib/Index/IndexBody.cpp b/lib/Index/IndexBody.cpp
index 4908d852e896..3aa0152ec996 100644
--- a/lib/Index/IndexBody.cpp
+++ b/lib/Index/IndexBody.cpp
@@ -148,7 +148,7 @@ public:
bool VisitDesignatedInitExpr(DesignatedInitExpr *E) {
for (DesignatedInitExpr::Designator &D : llvm::reverse(E->designators())) {
- if (D.isFieldDesignator())
+ if (D.isFieldDesignator() && D.getField())
return IndexCtx.handleReference(D.getField(), D.getFieldLoc(), Parent,
ParentDC, SymbolRoleSet(), {}, E);
}
@@ -276,7 +276,8 @@ public:
return true;
}
- bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C) {
+ bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C,
+ Expr *Init) {
if (C->capturesThis() || C->capturesVLAType())
return true;
@@ -293,31 +294,6 @@ public:
// Also visit things that are in the syntactic form but not the semantic one,
// for example the indices in DesignatedInitExprs.
bool TraverseInitListExpr(InitListExpr *S, DataRecursionQueue *Q = nullptr) {
-
- class SyntacticFormIndexer :
- public RecursiveASTVisitor<SyntacticFormIndexer> {
- IndexingContext &IndexCtx;
- const NamedDecl *Parent;
- const DeclContext *ParentDC;
-
- public:
- SyntacticFormIndexer(IndexingContext &indexCtx,
- const NamedDecl *Parent, const DeclContext *DC)
- : IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) { }
-
- bool shouldWalkTypesOfTypeLocs() const { return false; }
-
- bool VisitDesignatedInitExpr(DesignatedInitExpr *E) {
- for (DesignatedInitExpr::Designator &D : llvm::reverse(E->designators())) {
- if (D.isFieldDesignator())
- return IndexCtx.handleReference(D.getField(), D.getFieldLoc(),
- Parent, ParentDC, SymbolRoleSet(),
- {}, E);
- }
- return true;
- }
- };
-
auto visitForm = [&](InitListExpr *Form) {
for (Stmt *SubStmt : Form->children()) {
if (!TraverseStmt(SubStmt, Q))
@@ -326,13 +302,26 @@ public:
return true;
};
+ auto visitSyntacticDesignatedInitExpr = [&](DesignatedInitExpr *E) -> bool {
+ for (DesignatedInitExpr::Designator &D : llvm::reverse(E->designators())) {
+ if (D.isFieldDesignator())
+ return IndexCtx.handleReference(D.getField(), D.getFieldLoc(),
+ Parent, ParentDC, SymbolRoleSet(),
+ {}, E);
+ }
+ return true;
+ };
+
InitListExpr *SemaForm = S->isSemanticForm() ? S : S->getSemanticForm();
InitListExpr *SyntaxForm = S->isSemanticForm() ? S->getSyntacticForm() : S;
if (SemaForm) {
// Visit things present in syntactic form but not the semantic form.
if (SyntaxForm) {
- SyntacticFormIndexer(IndexCtx, Parent, ParentDC).TraverseStmt(SyntaxForm);
+ for (Expr *init : SyntaxForm->inits()) {
+ if (auto *DIE = dyn_cast<DesignatedInitExpr>(init))
+ visitSyntacticDesignatedInitExpr(DIE);
+ }
}
return visitForm(SemaForm);
}
diff --git a/lib/Index/IndexDecl.cpp b/lib/Index/IndexDecl.cpp
index eb3e15114735..1225391dc2a6 100644
--- a/lib/Index/IndexDecl.cpp
+++ b/lib/Index/IndexDecl.cpp
@@ -75,8 +75,21 @@ public:
}
}
- bool handleObjCMethod(const ObjCMethodDecl *D) {
- if (!IndexCtx.handleDecl(D, (unsigned)SymbolRole::Dynamic))
+ bool handleObjCMethod(const ObjCMethodDecl *D,
+ const ObjCPropertyDecl *AssociatedProp = nullptr) {
+ SmallVector<SymbolRelation, 4> Relations;
+ SmallVector<const ObjCMethodDecl*, 4> Overriden;
+
+ D->getOverriddenMethods(Overriden);
+ for(auto overridden: Overriden) {
+ Relations.emplace_back((unsigned) SymbolRole::RelationOverrideOf,
+ overridden);
+ }
+ if (AssociatedProp)
+ Relations.emplace_back((unsigned)SymbolRole::RelationAccessorOf,
+ AssociatedProp);
+
+ if (!IndexCtx.handleDecl(D, (unsigned)SymbolRole::Dynamic, Relations))
return false;
IndexCtx.indexTypeSourceInfo(D->getReturnTypeSourceInfo(), D);
for (const auto *I : D->parameters())
@@ -269,9 +282,18 @@ public:
}
bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
- if (!IndexCtx.handleDecl(D))
- return false;
- IndexCtx.indexDeclContext(D);
+ const ObjCInterfaceDecl *C = D->getClassInterface();
+ if (C)
+ TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D,
+ SymbolRoleSet(), SymbolRelation{
+ (unsigned)SymbolRole::RelationExtendedBy, D
+ }));
+ SourceLocation CategoryLoc = D->getCategoryNameLoc();
+ if (!CategoryLoc.isValid())
+ CategoryLoc = D->getLocation();
+ TRY_TO(IndexCtx.handleDecl(D, CategoryLoc));
+ TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D));
+ TRY_TO(IndexCtx.indexDeclContext(D));
return true;
}
@@ -279,8 +301,14 @@ public:
const ObjCCategoryDecl *Cat = D->getCategoryDecl();
if (!Cat)
return true;
-
- if (!IndexCtx.handleDecl(D))
+ const ObjCInterfaceDecl *C = D->getClassInterface();
+ if (C)
+ TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D,
+ SymbolRoleSet()));
+ SourceLocation CategoryLoc = D->getCategoryNameLoc();
+ if (!CategoryLoc.isValid())
+ CategoryLoc = D->getLocation();
+ if (!IndexCtx.handleDecl(D, CategoryLoc))
return false;
IndexCtx.indexDeclContext(D);
return true;
@@ -299,10 +327,10 @@ public:
bool VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
if (ObjCMethodDecl *MD = D->getGetterMethodDecl())
if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())
- handleObjCMethod(MD);
+ handleObjCMethod(MD, D);
if (ObjCMethodDecl *MD = D->getSetterMethodDecl())
if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())
- handleObjCMethod(MD);
+ handleObjCMethod(MD, D);
if (!IndexCtx.handleDecl(D))
return false;
IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
diff --git a/lib/Index/IndexSymbol.cpp b/lib/Index/IndexSymbol.cpp
index 13a845230072..b2342453a916 100644
--- a/lib/Index/IndexSymbol.cpp
+++ b/lib/Index/IndexSymbol.cpp
@@ -40,12 +40,12 @@ static bool isUnitTest(const ObjCMethodDecl *D) {
return isUnitTestCase(D->getClassInterface());
}
-static void checkForIBOutlets(const Decl *D, SymbolSubKindSet &SubKindSet) {
+static void checkForIBOutlets(const Decl *D, SymbolPropertySet &PropSet) {
if (D->hasAttr<IBOutletAttr>()) {
- SubKindSet |= (unsigned)SymbolSubKind::IBAnnotated;
+ PropSet |= (unsigned)SymbolProperty::IBAnnotated;
} else if (D->hasAttr<IBOutletCollectionAttr>()) {
- SubKindSet |= (unsigned)SymbolSubKind::IBAnnotated;
- SubKindSet |= (unsigned)SymbolSubKind::IBOutletCollection;
+ PropSet |= (unsigned)SymbolProperty::IBAnnotated;
+ PropSet |= (unsigned)SymbolProperty::IBOutletCollection;
}
}
@@ -53,7 +53,7 @@ SymbolInfo index::getSymbolInfo(const Decl *D) {
assert(D);
SymbolInfo Info;
Info.Kind = SymbolKind::Unknown;
- Info.SubKinds = SymbolSubKindSet();
+ Info.Properties = SymbolPropertySet();
Info.Lang = SymbolLanguage::C;
if (const TagDecl *TD = dyn_cast<TagDecl>(D)) {
@@ -74,16 +74,40 @@ SymbolInfo index::getSymbolInfo(const Decl *D) {
Info.Kind = SymbolKind::Enum; break;
}
- if (const CXXRecordDecl *CXXRec = dyn_cast<CXXRecordDecl>(D))
- if (!CXXRec->isCLike())
+ if (const CXXRecordDecl *CXXRec = dyn_cast<CXXRecordDecl>(D)) {
+ if (!CXXRec->isCLike()) {
Info.Lang = SymbolLanguage::CXX;
+ if (CXXRec->getDescribedClassTemplate()) {
+ Info.Properties |= (unsigned)SymbolProperty::Generic;
+ }
+ }
+ }
if (isa<ClassTemplatePartialSpecializationDecl>(D)) {
- Info.SubKinds |= (unsigned)SymbolSubKind::Generic;
- Info.SubKinds |= (unsigned)SymbolSubKind::TemplatePartialSpecialization;
+ Info.Properties |= (unsigned)SymbolProperty::Generic;
+ Info.Properties |= (unsigned)SymbolProperty::TemplatePartialSpecialization;
} else if (isa<ClassTemplateSpecializationDecl>(D)) {
- Info.SubKinds |= (unsigned)SymbolSubKind::Generic;
- Info.SubKinds |= (unsigned)SymbolSubKind::TemplateSpecialization;
+ Info.Properties |= (unsigned)SymbolProperty::Generic;
+ Info.Properties |= (unsigned)SymbolProperty::TemplateSpecialization;
+ }
+
+ } else if (auto *VD = dyn_cast<VarDecl>(D)) {
+ Info.Kind = SymbolKind::Variable;
+ if (isa<CXXRecordDecl>(D->getDeclContext())) {
+ Info.Kind = SymbolKind::StaticProperty;
+ Info.Lang = SymbolLanguage::CXX;
+ }
+ if (isa<VarTemplatePartialSpecializationDecl>(D)) {
+ Info.Lang = SymbolLanguage::CXX;
+ Info.Properties |= (unsigned)SymbolProperty::Generic;
+ Info.Properties |= (unsigned)SymbolProperty::TemplatePartialSpecialization;
+ } else if (isa<VarTemplateSpecializationDecl>(D)) {
+ Info.Lang = SymbolLanguage::CXX;
+ Info.Properties |= (unsigned)SymbolProperty::Generic;
+ Info.Properties |= (unsigned)SymbolProperty::TemplateSpecialization;
+ } else if (VD->getDescribedVarTemplate()) {
+ Info.Lang = SymbolLanguage::CXX;
+ Info.Properties |= (unsigned)SymbolProperty::Generic;
}
} else {
@@ -96,16 +120,6 @@ SymbolInfo index::getSymbolInfo(const Decl *D) {
case Decl::Function:
Info.Kind = SymbolKind::Function;
break;
- case Decl::ParmVar:
- Info.Kind = SymbolKind::Variable;
- break;
- case Decl::Var:
- Info.Kind = SymbolKind::Variable;
- if (isa<CXXRecordDecl>(D->getDeclContext())) {
- Info.Kind = SymbolKind::StaticProperty;
- Info.Lang = SymbolLanguage::CXX;
- }
- break;
case Decl::Field:
Info.Kind = SymbolKind::Field;
if (const CXXRecordDecl *
@@ -124,7 +138,7 @@ SymbolInfo index::getSymbolInfo(const Decl *D) {
if (!ClsD)
ClsD = cast<ObjCImplementationDecl>(D)->getClassInterface();
if (isUnitTestCase(ClsD))
- Info.SubKinds |= (unsigned)SymbolSubKind::UnitTest;
+ Info.Properties |= (unsigned)SymbolProperty::UnitTest;
break;
}
case Decl::ObjCProtocol:
@@ -143,19 +157,23 @@ SymbolInfo index::getSymbolInfo(const Decl *D) {
Info.Kind = SymbolKind::ClassMethod;
Info.Lang = SymbolLanguage::ObjC;
if (isUnitTest(cast<ObjCMethodDecl>(D)))
- Info.SubKinds |= (unsigned)SymbolSubKind::UnitTest;
+ Info.Properties |= (unsigned)SymbolProperty::UnitTest;
if (D->hasAttr<IBActionAttr>())
- Info.SubKinds |= (unsigned)SymbolSubKind::IBAnnotated;
+ Info.Properties |= (unsigned)SymbolProperty::IBAnnotated;
break;
case Decl::ObjCProperty:
Info.Kind = SymbolKind::InstanceProperty;
Info.Lang = SymbolLanguage::ObjC;
- checkForIBOutlets(D, Info.SubKinds);
+ checkForIBOutlets(D, Info.Properties);
+ if (auto *Annot = D->getAttr<AnnotateAttr>()) {
+ if (Annot->getAnnotation() == "gk_inspectable")
+ Info.Properties |= (unsigned)SymbolProperty::GKInspectable;
+ }
break;
case Decl::ObjCIvar:
Info.Kind = SymbolKind::Field;
Info.Lang = SymbolLanguage::ObjC;
- checkForIBOutlets(D, Info.SubKinds);
+ checkForIBOutlets(D, Info.Properties);
break;
case Decl::Namespace:
Info.Kind = SymbolKind::Namespace;
@@ -188,12 +206,12 @@ SymbolInfo index::getSymbolInfo(const Decl *D) {
}
case Decl::ClassTemplate:
Info.Kind = SymbolKind::Class;
- Info.SubKinds |= (unsigned)SymbolSubKind::Generic;
+ Info.Properties |= (unsigned)SymbolProperty::Generic;
Info.Lang = SymbolLanguage::CXX;
break;
case Decl::FunctionTemplate:
Info.Kind = SymbolKind::Function;
- Info.SubKinds |= (unsigned)SymbolSubKind::Generic;
+ Info.Properties |= (unsigned)SymbolProperty::Generic;
Info.Lang = SymbolLanguage::CXX;
if (const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(
cast<FunctionTemplateDecl>(D)->getTemplatedDecl())) {
@@ -214,7 +232,7 @@ SymbolInfo index::getSymbolInfo(const Decl *D) {
case Decl::TypeAliasTemplate:
Info.Kind = SymbolKind::TypeAlias;
Info.Lang = SymbolLanguage::CXX;
- Info.SubKinds |= (unsigned)SymbolSubKind::Generic;
+ Info.Properties |= (unsigned)SymbolProperty::Generic;
break;
case Decl::TypeAlias:
Info.Kind = SymbolKind::TypeAlias;
@@ -231,12 +249,12 @@ SymbolInfo index::getSymbolInfo(const Decl *D) {
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
if (FD->getTemplatedKind() ==
FunctionDecl::TK_FunctionTemplateSpecialization) {
- Info.SubKinds |= (unsigned)SymbolSubKind::Generic;
- Info.SubKinds |= (unsigned)SymbolSubKind::TemplateSpecialization;
+ Info.Properties |= (unsigned)SymbolProperty::Generic;
+ Info.Properties |= (unsigned)SymbolProperty::TemplateSpecialization;
}
}
- if (Info.SubKinds & (unsigned)SymbolSubKind::Generic)
+ if (Info.Properties & (unsigned)SymbolProperty::Generic)
Info.Lang = SymbolLanguage::CXX;
return Info;
@@ -262,6 +280,8 @@ void index::applyForEachSymbolRole(SymbolRoleSet Roles,
APPLY_FOR_ROLE(RelationOverrideOf);
APPLY_FOR_ROLE(RelationReceivedBy);
APPLY_FOR_ROLE(RelationCalledBy);
+ APPLY_FOR_ROLE(RelationExtendedBy);
+ APPLY_FOR_ROLE(RelationAccessorOf);
#undef APPLY_FOR_ROLE
}
@@ -288,6 +308,8 @@ void index::printSymbolRoles(SymbolRoleSet Roles, raw_ostream &OS) {
case SymbolRole::RelationOverrideOf: OS << "RelOver"; break;
case SymbolRole::RelationReceivedBy: OS << "RelRec"; break;
case SymbolRole::RelationCalledBy: OS << "RelCall"; break;
+ case SymbolRole::RelationExtendedBy: OS << "RelExt"; break;
+ case SymbolRole::RelationAccessorOf: OS << "RelAcc"; break;
}
});
}
@@ -350,36 +372,38 @@ StringRef index::getSymbolLanguageString(SymbolLanguage K) {
llvm_unreachable("invalid symbol language kind");
}
-void index::applyForEachSymbolSubKind(SymbolSubKindSet SubKinds,
- llvm::function_ref<void(SymbolSubKind)> Fn) {
-#define APPLY_FOR_SUBKIND(K) \
- if (SubKinds & (unsigned)SymbolSubKind::K) \
- Fn(SymbolSubKind::K)
+void index::applyForEachSymbolProperty(SymbolPropertySet Props,
+ llvm::function_ref<void(SymbolProperty)> Fn) {
+#define APPLY_FOR_PROPERTY(K) \
+ if (Props & (unsigned)SymbolProperty::K) \
+ Fn(SymbolProperty::K)
- APPLY_FOR_SUBKIND(Generic);
- APPLY_FOR_SUBKIND(TemplatePartialSpecialization);
- APPLY_FOR_SUBKIND(TemplateSpecialization);
- APPLY_FOR_SUBKIND(UnitTest);
- APPLY_FOR_SUBKIND(IBAnnotated);
- APPLY_FOR_SUBKIND(IBOutletCollection);
+ APPLY_FOR_PROPERTY(Generic);
+ APPLY_FOR_PROPERTY(TemplatePartialSpecialization);
+ APPLY_FOR_PROPERTY(TemplateSpecialization);
+ APPLY_FOR_PROPERTY(UnitTest);
+ APPLY_FOR_PROPERTY(IBAnnotated);
+ APPLY_FOR_PROPERTY(IBOutletCollection);
+ APPLY_FOR_PROPERTY(GKInspectable);
-#undef APPLY_FOR_SUBKIND
+#undef APPLY_FOR_PROPERTY
}
-void index::printSymbolSubKinds(SymbolSubKindSet SubKinds, raw_ostream &OS) {
+void index::printSymbolProperties(SymbolPropertySet Props, raw_ostream &OS) {
bool VisitedOnce = false;
- applyForEachSymbolSubKind(SubKinds, [&](SymbolSubKind SubKind) {
+ applyForEachSymbolProperty(Props, [&](SymbolProperty Prop) {
if (VisitedOnce)
OS << ',';
else
VisitedOnce = true;
- switch (SubKind) {
- case SymbolSubKind::Generic: OS << "Gen"; break;
- case SymbolSubKind::TemplatePartialSpecialization: OS << "TPS"; break;
- case SymbolSubKind::TemplateSpecialization: OS << "TS"; break;
- case SymbolSubKind::UnitTest: OS << "test"; break;
- case SymbolSubKind::IBAnnotated: OS << "IB"; break;
- case SymbolSubKind::IBOutletCollection: OS << "IBColl"; break;
+ switch (Prop) {
+ case SymbolProperty::Generic: OS << "Gen"; break;
+ case SymbolProperty::TemplatePartialSpecialization: OS << "TPS"; break;
+ case SymbolProperty::TemplateSpecialization: OS << "TS"; break;
+ case SymbolProperty::UnitTest: OS << "test"; break;
+ case SymbolProperty::IBAnnotated: OS << "IB"; break;
+ case SymbolProperty::IBOutletCollection: OS << "IBColl"; break;
+ case SymbolProperty::GKInspectable: OS << "GKI"; break;
}
});
}
diff --git a/lib/Index/IndexingContext.cpp b/lib/Index/IndexingContext.cpp
index bcc367c6626d..e623a495b47b 100644
--- a/lib/Index/IndexingContext.cpp
+++ b/lib/Index/IndexingContext.cpp
@@ -130,9 +130,10 @@ bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) {
if (const ClassTemplateSpecializationDecl *
SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
TKind = SD->getSpecializationKind();
- }
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
TKind = FD->getTemplateSpecializationKind();
+ } else if (auto *VD = dyn_cast<VarDecl>(D)) {
+ TKind = VD->getTemplateSpecializationKind();
}
switch (TKind) {
case TSK_Undeclared:
@@ -164,9 +165,10 @@ static const Decl *adjustTemplateImplicitInstantiation(const Decl *D) {
if (const ClassTemplateSpecializationDecl *
SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
return SD->getTemplateInstantiationPattern();
- }
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
return FD->getTemplateInstantiationPattern();
+ } else if (auto *VD = dyn_cast<VarDecl>(D)) {
+ return VD->getTemplateInstantiationPattern();
}
return nullptr;
}
@@ -290,19 +292,9 @@ bool IndexingContext::handleDeclOccurrence(const Decl *D, SourceLocation Loc,
Roles |= (unsigned)SymbolRole::Declaration;
D = getCanonicalDecl(D);
- if (D->isImplicit() && !isa<ObjCMethodDecl>(D) &&
- !(isa<FunctionDecl>(D) && cast<FunctionDecl>(D)->getBuiltinID())) {
- // operator new declarations will link to the implicit one as canonical.
- return true;
- }
Parent = adjustParent(Parent);
if (Parent)
Parent = getCanonicalDecl(Parent);
- assert((!Parent || !Parent->isImplicit() ||
- (isa<FunctionDecl>(Parent) &&
- cast<FunctionDecl>(Parent)->getBuiltinID()) ||
- isa<ObjCInterfaceDecl>(Parent) || isa<ObjCMethodDecl>(Parent)) &&
- "unexpected implicit parent!");
SmallVector<SymbolRelation, 6> FinalRelations;
FinalRelations.reserve(Relations.size()+1);
diff --git a/lib/Index/USRGeneration.cpp b/lib/Index/USRGeneration.cpp
index 30f1add249b1..58f61c3c65b7 100644
--- a/lib/Index/USRGeneration.cpp
+++ b/lib/Index/USRGeneration.cpp
@@ -12,7 +12,6 @@
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DeclVisitor.h"
#include "clang/Lex/PreprocessingRecord.h"
-#include "llvm/ADT/SmallString.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
@@ -174,8 +173,11 @@ bool USRGenerator::ShouldGenerateLocation(const NamedDecl *D) {
return false;
if (D->getParentFunctionOrMethod())
return true;
+ SourceLocation Loc = D->getLocation();
+ if (Loc.isInvalid())
+ return false;
const SourceManager &SM = Context->getSourceManager();
- return !SM.isInSystemHeader(D->getLocation());
+ return !SM.isInSystemHeader(Loc);
}
void USRGenerator::VisitDeclContext(const DeclContext *DC) {
@@ -284,6 +286,15 @@ void USRGenerator::VisitVarDecl(const VarDecl *D) {
VisitDeclContext(D->getDeclContext());
+ if (VarTemplateDecl *VarTmpl = D->getDescribedVarTemplate()) {
+ Out << "@VT";
+ VisitTemplateParameterList(VarTmpl->getTemplateParameters());
+ } else if (const VarTemplatePartialSpecializationDecl *PartialSpec
+ = dyn_cast<VarTemplatePartialSpecializationDecl>(D)) {
+ Out << "@VP";
+ VisitTemplateParameterList(PartialSpec->getTemplateParameters());
+ }
+
// Variables always have simple names.
StringRef s = D->getName();
@@ -295,6 +306,17 @@ void USRGenerator::VisitVarDecl(const VarDecl *D) {
IgnoreResults = true;
else
Out << '@' << s;
+
+ // For a template specialization, mangle the template arguments.
+ if (const VarTemplateSpecializationDecl *Spec
+ = dyn_cast<VarTemplateSpecializationDecl>(D)) {
+ const TemplateArgumentList &Args = Spec->getTemplateInstantiationArgs();
+ Out << '>';
+ for (unsigned I = 0, N = Args.size(); I != N; ++I) {
+ Out << '#';
+ VisitTemplateArgument(Args.get(I));
+ }
+ }
}
void USRGenerator::VisitNonTypeTemplateParmDecl(
@@ -875,9 +897,11 @@ void clang::index::generateUSRForObjCProtocol(StringRef Prot, raw_ostream &OS) {
bool clang::index::generateUSRForDecl(const Decl *D,
SmallVectorImpl<char> &Buf) {
- // Don't generate USRs for things with invalid locations.
- if (!D || D->getLocStart().isInvalid())
+ if (!D)
return true;
+ // We don't ignore decls with invalid source locations. Implicit decls, like
+ // C++'s operator new function, can have invalid locations but it is fine to
+ // create USRs that can identify them.
USRGenerator UG(&D->getASTContext(), Buf);
UG.Visit(D);
diff --git a/lib/Lex/HeaderMap.cpp b/lib/Lex/HeaderMap.cpp
index 4cace5b00245..24a14b6cdb57 100644
--- a/lib/Lex/HeaderMap.cpp
+++ b/lib/Lex/HeaderMap.cpp
@@ -106,7 +106,7 @@ bool HeaderMapImpl::checkHeader(const llvm::MemoryBuffer &File,
/// getFileName - Return the filename of the headermap.
-const char *HeaderMapImpl::getFileName() const {
+StringRef HeaderMapImpl::getFileName() const {
return FileBuffer->getBufferIdentifier();
}
diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp
index e5cc30e41c57..b5228fc6c8cb 100644
--- a/lib/Lex/HeaderSearch.cpp
+++ b/lib/Lex/HeaderSearch.cpp
@@ -26,7 +26,6 @@
#include "llvm/Support/Capacity.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
-#include "llvm/Support/raw_ostream.h"
#include <cstdio>
#include <utility>
#if defined(LLVM_ON_UNIX)
@@ -37,9 +36,12 @@ using namespace clang;
const IdentifierInfo *
HeaderFileInfo::getControllingMacro(ExternalPreprocessorSource *External) {
if (ControllingMacro) {
- if (ControllingMacro->isOutOfDate())
+ if (ControllingMacro->isOutOfDate()) {
+ assert(External && "We must have an external source if we have a "
+ "controlling macro that is out of date.");
External->updateOutOfDateIdentifier(
*const_cast<IdentifierInfo *>(ControllingMacro));
+ }
return ControllingMacro;
}
@@ -119,14 +121,39 @@ const HeaderMap *HeaderSearch::CreateHeaderMap(const FileEntry *FE) {
return nullptr;
}
+/// \brief Get filenames for all registered header maps.
+void HeaderSearch::getHeaderMapFileNames(
+ SmallVectorImpl<std::string> &Names) const {
+ for (auto &HM : HeaderMaps)
+ Names.push_back(HM.first->getName());
+}
+
std::string HeaderSearch::getModuleFileName(Module *Module) {
const FileEntry *ModuleMap =
getModuleMap().getModuleMapFileForUniquing(Module);
- return getModuleFileName(Module->Name, ModuleMap->getName());
+ return getModuleFileName(Module->Name, ModuleMap->getName(),
+ /*UsePrebuiltPath*/false);
}
std::string HeaderSearch::getModuleFileName(StringRef ModuleName,
- StringRef ModuleMapPath) {
+ StringRef ModuleMapPath,
+ bool UsePrebuiltPath) {
+ if (UsePrebuiltPath) {
+ if (HSOpts->PrebuiltModulePaths.empty())
+ return std::string();
+
+ // Go though each prebuilt module path and try to find the pcm file.
+ for (const std::string &Dir : HSOpts->PrebuiltModulePaths) {
+ SmallString<256> Result(Dir);
+ llvm::sys::fs::make_absolute(Result);
+
+ llvm::sys::path::append(Result, ModuleName + ".pcm");
+ if (getFileMgr().getFile(Result.str()))
+ return Result.str().str();
+ }
+ return std::string();
+ }
+
// If we don't have a module cache path or aren't supposed to use one, we
// can't do anything.
if (getModuleCachePath().empty())
@@ -167,16 +194,36 @@ Module *HeaderSearch::lookupModule(StringRef ModuleName, bool AllowSearch) {
Module *Module = ModMap.findModule(ModuleName);
if (Module || !AllowSearch || !HSOpts->ImplicitModuleMaps)
return Module;
-
+
+ StringRef SearchName = ModuleName;
+ Module = lookupModule(ModuleName, SearchName);
+
+ // The facility for "private modules" -- adjacent, optional module maps named
+ // module.private.modulemap that are supposed to define private submodules --
+ // is sometimes misused by frameworks that name their associated private
+ // module FooPrivate, rather than as a submodule named Foo.Private as
+ // intended. Here we compensate for such cases by looking in directories named
+ // Foo.framework, when we previously looked and failed to find a
+ // FooPrivate.framework.
+ if (!Module && SearchName.consume_back("Private"))
+ Module = lookupModule(ModuleName, SearchName);
+ return Module;
+}
+
+Module *HeaderSearch::lookupModule(StringRef ModuleName, StringRef SearchName) {
+ Module *Module = nullptr;
+
// Look through the various header search paths to load any available module
// maps, searching for a module map that describes this module.
for (unsigned Idx = 0, N = SearchDirs.size(); Idx != N; ++Idx) {
if (SearchDirs[Idx].isFramework()) {
- // Search for or infer a module map for a framework.
+ // Search for or infer a module map for a framework. Here we use
+ // SearchName rather than ModuleName, to permit finding private modules
+ // named FooPrivate in buggy frameworks named Foo.
SmallString<128> FrameworkDirName;
FrameworkDirName += SearchDirs[Idx].getFrameworkDir()->getName();
- llvm::sys::path::append(FrameworkDirName, ModuleName + ".framework");
- if (const DirectoryEntry *FrameworkDir
+ llvm::sys::path::append(FrameworkDirName, SearchName + ".framework");
+ if (const DirectoryEntry *FrameworkDir
= FileMgr.getDirectory(FrameworkDirName)) {
bool IsSystem
= SearchDirs[Idx].getDirCharacteristic() != SrcMgr::C_User;
@@ -240,7 +287,7 @@ Module *HeaderSearch::lookupModule(StringRef ModuleName, bool AllowSearch) {
/// getName - Return the directory or filename corresponding to this lookup
/// object.
-const char *DirectoryLookup::getName() const {
+StringRef DirectoryLookup::getName() const {
if (isNormalDir())
return getDir()->getName();
if (isFramework())
@@ -396,6 +443,12 @@ getTopFrameworkDir(FileManager &FileMgr, StringRef DirName,
return TopFrameworkDir;
}
+static bool needModuleLookup(Module *RequestingModule,
+ bool HasSuggestedModule) {
+ return HasSuggestedModule ||
+ (RequestingModule && RequestingModule->NoUndeclaredIncludes);
+}
+
/// DoFrameworkLookup - Do a lookup of the specified file in the current
/// DirectoryLookup, which is a framework directory.
const FileEntry *DirectoryLookup::DoFrameworkLookup(
@@ -491,7 +544,7 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(
}
// If we found the header and are allowed to suggest a module, do so now.
- if (FE && SuggestedModule) {
+ if (FE && needModuleLookup(RequestingModule, SuggestedModule)) {
// Find the framework in which this header occurs.
StringRef FrameworkPath = FE->getDir()->getName();
bool FoundFramework = false;
@@ -830,17 +883,19 @@ LookupSubframeworkHeader(StringRef Filename,
if (SlashPos == StringRef::npos) return nullptr;
// Look up the base framework name of the ContextFileEnt.
- const char *ContextName = ContextFileEnt->getName();
+ StringRef ContextName = ContextFileEnt->getName();
// If the context info wasn't a framework, couldn't be a subframework.
const unsigned DotFrameworkLen = 10;
- const char *FrameworkPos = strstr(ContextName, ".framework");
- if (FrameworkPos == nullptr ||
- (FrameworkPos[DotFrameworkLen] != '/' &&
- FrameworkPos[DotFrameworkLen] != '\\'))
+ auto FrameworkPos = ContextName.find(".framework");
+ if (FrameworkPos == StringRef::npos ||
+ (ContextName[FrameworkPos + DotFrameworkLen] != '/' &&
+ ContextName[FrameworkPos + DotFrameworkLen] != '\\'))
return nullptr;
- SmallString<1024> FrameworkName(ContextName, FrameworkPos+DotFrameworkLen+1);
+ SmallString<1024> FrameworkName(ContextName.data(), ContextName.data() +
+ FrameworkPos +
+ DotFrameworkLen + 1);
// Append Frameworks/HIToolbox.framework/
FrameworkName += "Frameworks/";
@@ -1139,22 +1194,45 @@ bool HeaderSearch::hasModuleMap(StringRef FileName,
}
ModuleMap::KnownHeader
-HeaderSearch::findModuleForHeader(const FileEntry *File) const {
+HeaderSearch::findModuleForHeader(const FileEntry *File,
+ bool AllowTextual) const {
if (ExternalSource) {
// Make sure the external source has handled header info about this file,
// which includes whether the file is part of a module.
(void)getExistingFileInfo(File);
}
- return ModMap.findModuleForHeader(File);
+ return ModMap.findModuleForHeader(File, AllowTextual);
+}
+
+static bool suggestModule(HeaderSearch &HS, const FileEntry *File,
+ Module *RequestingModule,
+ ModuleMap::KnownHeader *SuggestedModule) {
+ ModuleMap::KnownHeader Module =
+ HS.findModuleForHeader(File, /*AllowTextual*/true);
+ if (SuggestedModule)
+ *SuggestedModule = (Module.getRole() & ModuleMap::TextualHeader)
+ ? ModuleMap::KnownHeader()
+ : Module;
+
+ // If this module specifies [no_undeclared_includes], we cannot find any
+ // file that's in a non-dependency module.
+ if (RequestingModule && Module && RequestingModule->NoUndeclaredIncludes) {
+ HS.getModuleMap().resolveUses(RequestingModule, /*Complain*/false);
+ if (!RequestingModule->directlyUses(Module.getModule())) {
+ return false;
+ }
+ }
+
+ return true;
}
bool HeaderSearch::findUsableModuleForHeader(
const FileEntry *File, const DirectoryEntry *Root, Module *RequestingModule,
ModuleMap::KnownHeader *SuggestedModule, bool IsSystemHeaderDir) {
- if (File && SuggestedModule) {
+ if (File && needModuleLookup(RequestingModule, SuggestedModule)) {
// If there is a module that corresponds to this header, suggest it.
hasModuleMap(File->getName(), Root, IsSystemHeaderDir);
- *SuggestedModule = findModuleForHeader(File);
+ return suggestModule(*this, File, RequestingModule, SuggestedModule);
}
return true;
}
@@ -1163,7 +1241,7 @@ bool HeaderSearch::findUsableModuleForFrameworkHeader(
const FileEntry *File, StringRef FrameworkName, Module *RequestingModule,
ModuleMap::KnownHeader *SuggestedModule, bool IsSystemFramework) {
// If we're supposed to suggest a module, look for one now.
- if (SuggestedModule) {
+ if (needModuleLookup(RequestingModule, SuggestedModule)) {
// Find the top-level framework based on this framework.
SmallVector<std::string, 4> SubmodulePath;
const DirectoryEntry *TopFrameworkDir
@@ -1180,7 +1258,7 @@ bool HeaderSearch::findUsableModuleForFrameworkHeader(
// important so that we're consistent about whether this header
// corresponds to a module. Possibly we should lock down framework modules
// so that this is not possible.
- *SuggestedModule = findModuleForHeader(File);
+ return suggestModule(*this, File, RequestingModule, SuggestedModule);
}
return true;
}
@@ -1432,7 +1510,7 @@ std::string HeaderSearch::suggestPathToFileForDiagnostics(const FileEntry *File,
// 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).
- const char *Name = File->getName();
+ StringRef Name = File->getName();
unsigned BestPrefixLength = 0;
unsigned BestSearchDir;
@@ -1442,7 +1520,7 @@ std::string HeaderSearch::suggestPathToFileForDiagnostics(const FileEntry *File,
if (!SearchDirs[I].isNormalDir())
continue;
- const char *Dir = SearchDirs[I].getDir()->getName();
+ 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),
@@ -1475,5 +1553,5 @@ std::string HeaderSearch::suggestPathToFileForDiagnostics(const FileEntry *File,
if (IsSystem)
*IsSystem = BestPrefixLength ? BestSearchDir >= SystemDirIdx : false;
- return Name + BestPrefixLength;
+ return Name.drop_front(BestPrefixLength);
}
diff --git a/lib/Lex/Lexer.cpp b/lib/Lex/Lexer.cpp
index 9c2a0163acea..6025a6675125 100644
--- a/lib/Lex/Lexer.cpp
+++ b/lib/Lex/Lexer.cpp
@@ -14,18 +14,27 @@
#include "clang/Lex/Lexer.h"
#include "UnicodeCharSets.h"
#include "clang/Basic/CharInfo.h"
+#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/SourceManager.h"
-#include "clang/Lex/CodeCompletionHandler.h"
#include "clang/Lex/LexDiagnostic.h"
#include "clang/Lex/LiteralSupport.h"
#include "clang/Lex/Preprocessor.h"
-#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ConvertUTF.h"
+#include "llvm/Support/MathExtras.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/UnicodeCharRanges.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
#include <cstring>
+#include <string>
+#include <tuple>
+#include <utility>
+
using namespace clang;
//===----------------------------------------------------------------------===//
@@ -45,7 +54,6 @@ tok::ObjCKeywordKind Token::getObjCKeywordID() const {
return specId ? specId->getObjCKeywordID() : tok::objc_not_keyword;
}
-
//===----------------------------------------------------------------------===//
// Lexer Class Implementation
//===----------------------------------------------------------------------===//
@@ -196,7 +204,6 @@ Lexer *Lexer::Create_PragmaLexer(SourceLocation SpellingLoc,
return L;
}
-
/// Stringify - Convert the specified string into a C string, with surrounding
/// ""'s, and with escaped \ and " characters.
std::string Lexer::Stringify(StringRef Str, bool Charify) {
@@ -398,7 +405,6 @@ unsigned Lexer::getSpelling(const Token &Tok, const char *&Buffer,
return getSpellingSlow(Tok, TokStart, LangOpts, const_cast<char*>(Buffer));
}
-
/// MeasureTokenLength - Relex the token at the specified location and return
/// its length in bytes in the input file. If the token needs cleaning (e.g.
/// includes a trigraph or an escaped newline) then this count includes bytes
@@ -526,13 +532,15 @@ SourceLocation Lexer::GetBeginningOfToken(SourceLocation Loc,
}
namespace {
+
enum PreambleDirectiveKind {
PDK_Skipped,
PDK_StartIf,
PDK_EndIf,
PDK_Unknown
};
-}
+
+} // end anonymous namespace
std::pair<unsigned, bool> Lexer::ComputePreamble(StringRef Buffer,
const LangOptions &LangOpts,
@@ -694,7 +702,6 @@ std::pair<unsigned, bool> 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,
@@ -961,7 +968,7 @@ StringRef Lexer::getImmediateMacroName(SourceLocation Loc,
assert(Loc.isMacroID() && "Only reasonble to call this on macros");
// Find the location of the immediate macro expansion.
- while (1) {
+ while (true) {
FileID FID = SM.getFileID(Loc);
const SrcMgr::SLocEntry *E = &SM.getSLocEntry(FID);
const SrcMgr::ExpansionInfo &Expansion = E->getExpansion();
@@ -1031,7 +1038,6 @@ bool Lexer::isIdentifierBodyChar(char c, const LangOptions &LangOpts) {
return isIdentifierBody(c, LangOpts.DollarIdents);
}
-
//===----------------------------------------------------------------------===//
// Diagnostics forwarding code.
//===----------------------------------------------------------------------===//
@@ -1157,7 +1163,7 @@ unsigned Lexer::getEscapedNewLineSize(const char *Ptr) {
/// them), skip over them and return the first non-escaped-newline found,
/// otherwise return P.
const char *Lexer::SkipEscapedNewLines(const char *P) {
- while (1) {
+ while (true) {
const char *AfterEscape;
if (*P == '\\') {
AfterEscape = P+1;
@@ -1310,7 +1316,6 @@ Slash:
return *Ptr;
}
-
/// getCharAndSizeSlowNoWarn - Handle the slow/uncommon case of the
/// getCharAndSizeNoWarn method. Here we know that we can accumulate into Size,
/// and that we have already incremented Ptr by Size bytes.
@@ -1480,13 +1485,13 @@ bool Lexer::tryConsumeIdentifierUCN(const char *&CurPtr, unsigned Size,
bool Lexer::tryConsumeIdentifierUTF8Char(const char *&CurPtr) {
const char *UnicodePtr = CurPtr;
- UTF32 CodePoint;
- ConversionResult Result =
- llvm::convertUTF8Sequence((const UTF8 **)&UnicodePtr,
- (const UTF8 *)BufferEnd,
+ llvm::UTF32 CodePoint;
+ llvm::ConversionResult Result =
+ llvm::convertUTF8Sequence((const llvm::UTF8 **)&UnicodePtr,
+ (const llvm::UTF8 *)BufferEnd,
&CodePoint,
- strictConversion);
- if (Result != conversionOK ||
+ llvm::strictConversion);
+ if (Result != llvm::conversionOK ||
!isAllowedIDChar(static_cast<uint32_t>(CodePoint), LangOpts))
return false;
@@ -1533,14 +1538,22 @@ FinishIdentifier:
// 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;
}
// Otherwise, $,\,? in identifier found. Enter slower path.
C = getCharAndSize(CurPtr, Size);
- while (1) {
+ while (true) {
if (C == '$') {
// If we hit a $ and they are not supported in identifiers, we are done.
if (!LangOpts.DollarIdents) goto FinishIdentifier;
@@ -1700,9 +1713,9 @@ const char *Lexer::LexUDSuffix(Token &Result, const char *CurPtr,
getLangOpts());
if (!isIdentifierBody(Next)) {
// End of suffix. Check whether this is on the whitelist.
- IsUDSuffix = (Chars == 1 && Buffer[0] == 's') ||
- NumericLiteralParser::isValidUDSuffix(
- getLangOpts(), StringRef(Buffer, Chars));
+ const StringRef CompleteSuffix(Buffer, Chars);
+ IsUDSuffix = StringLiteralParser::isValidUDSuffix(getLangOpts(),
+ CompleteSuffix);
break;
}
@@ -1829,7 +1842,7 @@ bool Lexer::LexRawStringLiteral(Token &Result, const char *CurPtr,
// Search for the next '"' in hopes of salvaging the lexer. Unfortunately,
// it's possible the '"' was intended to be part of the raw string, but
// there's not much we can do about that.
- while (1) {
+ while (true) {
char C = *CurPtr++;
if (C == '"')
@@ -1848,7 +1861,7 @@ bool Lexer::LexRawStringLiteral(Token &Result, const char *CurPtr,
const char *Prefix = CurPtr;
CurPtr += PrefixLen + 1; // skip over prefix and '('
- while (1) {
+ while (true) {
char C = *CurPtr++;
if (C == ')') {
@@ -1913,7 +1926,6 @@ bool Lexer::LexAngledStringLiteral(Token &Result, const char *CurPtr) {
return true;
}
-
/// LexCharConstant - Lex the remainder of a character constant, after having
/// lexed either ' or L' or u8' or u' or U'.
bool Lexer::LexCharConstant(Token &Result, const char *CurPtr,
@@ -1992,7 +2004,7 @@ bool Lexer::SkipWhitespace(Token &Result, const char *CurPtr,
unsigned char Char = *CurPtr;
// Skip consecutive spaces efficiently.
- while (1) {
+ while (true) {
// Skip horizontal whitespace very aggressively.
while (isHorizontalWhitespace(Char))
Char = *++CurPtr;
@@ -2315,7 +2327,7 @@ bool Lexer::SkipBlockComment(Token &Result, const char *CurPtr,
if (C == '/')
C = *CurPtr++;
- while (1) {
+ while (true) {
// Skip over all non-interesting characters until we find end of buffer or a
// (probably ending) '/' character.
if (CurPtr + 24 < BufferEnd &&
@@ -2456,7 +2468,7 @@ void Lexer::ReadToEndOfLine(SmallVectorImpl<char> *Result) {
// CurPtr - Cache BufferPtr in an automatic variable.
const char *CurPtr = BufferPtr;
- while (1) {
+ while (true) {
char Char = getAndAdvanceChar(CurPtr, Tmp);
switch (Char) {
default:
@@ -2669,7 +2681,6 @@ bool Lexer::IsStartOfConflictMarker(const char *CurPtr) {
return false;
}
-
/// HandleEndOfConflictMarker - If this is a '====' or '||||' or '>>>>', or if
/// it is '<<<<' and the conflict marker started with a '>>>>' marker, then it
/// is the end of a conflict marker. Handle it by ignoring up until the end of
@@ -3498,7 +3509,6 @@ LexNextToken:
CurPtr = ConsumeChar(CurPtr, SizeTmp, Result);
Kind = tok::greatergreater;
}
-
} else {
Kind = tok::greater;
}
@@ -3615,17 +3625,17 @@ LexNextToken:
break;
}
- UTF32 CodePoint;
+ llvm::UTF32 CodePoint;
// We can't just reset CurPtr to BufferPtr because BufferPtr may point to
// an escaped newline.
--CurPtr;
- ConversionResult Status =
- llvm::convertUTF8Sequence((const UTF8 **)&CurPtr,
- (const UTF8 *)BufferEnd,
+ llvm::ConversionResult Status =
+ llvm::convertUTF8Sequence((const llvm::UTF8 **)&CurPtr,
+ (const llvm::UTF8 *)BufferEnd,
&CodePoint,
- strictConversion);
- if (Status == conversionOK) {
+ llvm::strictConversion);
+ if (Status == llvm::conversionOK) {
if (CheckUnicodeWhitespace(Result, CodePoint, CurPtr)) {
if (SkipWhitespace(Result, CurPtr, TokAtPhysicalStartOfLine))
return true; // KeepWhitespaceMode
diff --git a/lib/Lex/LiteralSupport.cpp b/lib/Lex/LiteralSupport.cpp
index e68b82fb499a..fbfd3fe5cce0 100644
--- a/lib/Lex/LiteralSupport.cpp
+++ b/lib/Lex/LiteralSupport.cpp
@@ -14,12 +14,25 @@
#include "clang/Lex/LiteralSupport.h"
#include "clang/Basic/CharInfo.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/LexDiagnostic.h"
+#include "clang/Lex/Lexer.h"
#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/Token.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/ErrorHandling.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+#include <string>
using namespace clang;
@@ -134,7 +147,7 @@ static unsigned ProcessCharEscape(const char *ThisTokBegin,
if (Diags)
Diag(Diags, Features, Loc, ThisTokBegin, EscapeBegin, ThisTokBuf,
diag::err_hex_escape_no_digits) << "x";
- HadError = 1;
+ HadError = true;
break;
}
@@ -389,7 +402,7 @@ static void EncodeUCNEscape(const char *ThisTokBegin, const char *&ThisTokBuf,
if (CharByteWidth == 4) {
// FIXME: Make the type of the result buffer correct instead of
// using reinterpret_cast.
- UTF32 *ResultPtr = reinterpret_cast<UTF32*>(ResultBuf);
+ llvm::UTF32 *ResultPtr = reinterpret_cast<llvm::UTF32*>(ResultBuf);
*ResultPtr = UcnVal;
ResultBuf += 4;
return;
@@ -398,7 +411,7 @@ static void EncodeUCNEscape(const char *ThisTokBegin, const char *&ThisTokBuf,
if (CharByteWidth == 2) {
// FIXME: Make the type of the result buffer correct instead of
// using reinterpret_cast.
- UTF16 *ResultPtr = reinterpret_cast<UTF16*>(ResultBuf);
+ llvm::UTF16 *ResultPtr = reinterpret_cast<llvm::UTF16*>(ResultBuf);
if (UcnVal <= (UTF32)0xFFFF) {
*ResultPtr = UcnVal;
@@ -452,7 +465,6 @@ static void EncodeUCNEscape(const char *ThisTokBegin, const char *&ThisTokBuf,
ResultBuf += bytesToWrite;
}
-
/// integer-constant: [C99 6.4.4.1]
/// decimal-constant integer-suffix
/// octal-constant integer-suffix
@@ -985,7 +997,6 @@ NumericLiteralParser::GetFloatValue(llvm::APFloat &Result) {
return Result.convertFromString(Str, APFloat::rmNearestTiesToEven);
}
-
/// \verbatim
/// user-defined-character-literal: [C++11 lex.ext]
/// character-literal ud-suffix
@@ -1103,11 +1114,11 @@ CharLiteralParser::CharLiteralParser(const char *begin, const char *end,
char const *tmp_in_start = start;
uint32_t *tmp_out_start = buffer_begin;
- ConversionResult res =
- ConvertUTF8toUTF32(reinterpret_cast<UTF8 const **>(&start),
- reinterpret_cast<UTF8 const *>(begin),
- &buffer_begin, buffer_end, strictConversion);
- if (res != conversionOK) {
+ llvm::ConversionResult res =
+ llvm::ConvertUTF8toUTF32(reinterpret_cast<llvm::UTF8 const **>(&start),
+ reinterpret_cast<llvm::UTF8 const *>(begin),
+ &buffer_begin, buffer_end, llvm::strictConversion);
+ if (res != llvm::conversionOK) {
// If we see bad encoding for unprefixed character literals, warn and
// simply copy the byte values, for compatibility with gcc and
// older versions of clang.
@@ -1499,13 +1510,13 @@ void StringLiteralParser::init(ArrayRef<Token> StringToks){
if (CharByteWidth == 4) {
// FIXME: Make the type of the result buffer correct instead of
// using reinterpret_cast.
- UTF32 *ResultWidePtr = reinterpret_cast<UTF32*>(ResultPtr);
+ llvm::UTF32 *ResultWidePtr = reinterpret_cast<llvm::UTF32*>(ResultPtr);
*ResultWidePtr = ResultChar;
ResultPtr += 4;
} else if (CharByteWidth == 2) {
// FIXME: Make the type of the result buffer correct instead of
// using reinterpret_cast.
- UTF16 *ResultWidePtr = reinterpret_cast<UTF16*>(ResultPtr);
+ llvm::UTF16 *ResultWidePtr = reinterpret_cast<llvm::UTF16*>(ResultPtr);
*ResultWidePtr = ResultChar & 0xFFFF;
ResultPtr += 2;
} else {
@@ -1520,12 +1531,12 @@ void StringLiteralParser::init(ArrayRef<Token> StringToks){
if (CharByteWidth == 4) {
// FIXME: Make the type of the result buffer correct instead of
// using reinterpret_cast.
- UTF32 *ResultWidePtr = reinterpret_cast<UTF32*>(ResultBuf.data());
+ llvm::UTF32 *ResultWidePtr = reinterpret_cast<llvm::UTF32*>(ResultBuf.data());
ResultWidePtr[0] = GetNumStringChars() - 1;
} else if (CharByteWidth == 2) {
// FIXME: Make the type of the result buffer correct instead of
// using reinterpret_cast.
- UTF16 *ResultWidePtr = reinterpret_cast<UTF16*>(ResultBuf.data());
+ llvm::UTF16 *ResultWidePtr = reinterpret_cast<llvm::UTF16*>(ResultBuf.data());
ResultWidePtr[0] = GetNumStringChars() - 1;
} else {
assert(CharByteWidth == 1 && "Unexpected char width");
@@ -1559,7 +1570,7 @@ void StringLiteralParser::init(ArrayRef<Token> StringToks){
static const char *resyncUTF8(const char *Err, const char *End) {
if (Err == End)
return End;
- End = Err + std::min<unsigned>(getNumBytesForUTF8(*Err), End-Err);
+ End = Err + std::min<unsigned>(llvm::getNumBytesForUTF8(*Err), End-Err);
while (++Err != End && (*Err & 0xC0) == 0x80)
;
return Err;
@@ -1571,7 +1582,7 @@ static const char *resyncUTF8(const char *Err, const char *End) {
bool StringLiteralParser::CopyStringFragment(const Token &Tok,
const char *TokBegin,
StringRef Fragment) {
- const UTF8 *ErrorPtrTmp;
+ const llvm::UTF8 *ErrorPtrTmp;
if (ConvertUTF8toWide(CharByteWidth, Fragment, ResultPtr, ErrorPtrTmp))
return false;
@@ -1697,3 +1708,12 @@ unsigned StringLiteralParser::getOffsetOfStringByte(const Token &Tok,
return SpellingPtr-SpellingStart;
}
+
+/// Determine whether a suffix is a valid ud-suffix. We avoid treating reserved
+/// suffixes as ud-suffixes, because the diagnostic experience is better if we
+/// treat it as an invalid suffix.
+bool StringLiteralParser::isValidUDSuffix(const LangOptions &LangOpts,
+ StringRef Suffix) {
+ return NumericLiteralParser::isValidUDSuffix(LangOpts, Suffix) ||
+ Suffix == "sv";
+}
diff --git a/lib/Lex/MacroInfo.cpp b/lib/Lex/MacroInfo.cpp
index 2ef4387b99ba..924613dcb840 100644
--- a/lib/Lex/MacroInfo.cpp
+++ b/lib/Lex/MacroInfo.cpp
@@ -240,6 +240,6 @@ ModuleMacro *ModuleMacro::create(Preprocessor &PP, Module *OwningModule,
ArrayRef<ModuleMacro *> Overrides) {
void *Mem = PP.getPreprocessorAllocator().Allocate(
sizeof(ModuleMacro) + sizeof(ModuleMacro *) * Overrides.size(),
- llvm::alignOf<ModuleMacro>());
+ alignof(ModuleMacro));
return new (Mem) ModuleMacro(OwningModule, II, Macro, Overrides);
}
diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp
index 3e3215dee82a..9d0f2eb2fa79 100644
--- a/lib/Lex/ModuleMap.cpp
+++ b/lib/Lex/ModuleMap.cpp
@@ -297,11 +297,14 @@ void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule,
if (LangOpts.ModulesStrictDeclUse) {
Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
<< RequestingModule->getFullModuleName() << Filename;
- } else if (RequestingModule && RequestingModuleIsModuleInterface) {
+ } else if (RequestingModule && RequestingModuleIsModuleInterface &&
+ LangOpts.isCompilingModule()) {
+ // Do not diagnose when we are not compiling a module.
diag::kind DiagID = RequestingModule->getTopLevelModule()->IsFramework ?
diag::warn_non_modular_include_in_framework_module :
diag::warn_non_modular_include_in_module;
- Diags.Report(FilenameLoc, DiagID) << RequestingModule->getFullModuleName();
+ Diags.Report(FilenameLoc, DiagID) << RequestingModule->getFullModuleName()
+ << File->getName();
}
}
@@ -325,9 +328,10 @@ static bool isBetterKnownHeader(const ModuleMap::KnownHeader &New,
return false;
}
-ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File) {
+ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File,
+ bool AllowTextual) {
auto MakeResult = [&](ModuleMap::KnownHeader R) -> ModuleMap::KnownHeader {
- if (R.getRole() & ModuleMap::TextualHeader)
+ if (!AllowTextual && R.getRole() & ModuleMap::TextualHeader)
return ModuleMap::KnownHeader();
return R;
};
@@ -558,6 +562,25 @@ ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework,
return std::make_pair(Result, true);
}
+Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc,
+ StringRef Name) {
+ assert(LangOpts.CurrentModule == Name && "module name mismatch");
+ assert(!Modules[Name] && "redefining existing module");
+
+ auto *Result =
+ new Module(Name, Loc, nullptr, /*IsFramework*/ false,
+ /*IsExplicit*/ false, NumCreatedModules++);
+ Modules[Name] = SourceModule = Result;
+
+ // Mark the main source file as being within the newly-created module so that
+ // declarations and macros are properly visibility-restricted to it.
+ auto *MainFile = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
+ assert(MainFile && "no input file for module interface");
+ Headers[MainFile].push_back(KnownHeader(Result, PrivateHeader));
+
+ return Result;
+}
+
/// \brief For a framework module, infer the framework against which we
/// should link.
static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir,
@@ -573,8 +596,7 @@ static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir,
// The library name of a framework has more than one possible extension since
// the introduction of the text-based dynamic library format. We need to check
// for both before we give up.
- static const char *frameworkExtensions[] = {"", ".tbd"};
- for (const auto *extension : frameworkExtensions) {
+ for (const char *extension : {"", ".tbd"}) {
llvm::sys::path::replace_extension(LibName, extension);
if (FileMgr.getFile(LibName)) {
Mod->LinkLibraries.push_back(Module::LinkLibrary(Mod->Name,
@@ -653,6 +675,8 @@ Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
Attrs.IsSystem |= inferred->second.Attrs.IsSystem;
Attrs.IsExternC |= inferred->second.Attrs.IsExternC;
Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive;
+ Attrs.NoUndeclaredIncludes |=
+ inferred->second.Attrs.NoUndeclaredIncludes;
ModuleMapFile = inferred->second.ModuleMapFile;
}
}
@@ -690,6 +714,7 @@ Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
Result->IsSystem |= Attrs.IsSystem;
Result->IsExternC |= Attrs.IsExternC;
Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive;
+ Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes;
Result->Directory = FrameworkDir;
// umbrella header "umbrella-header-name"
@@ -802,10 +827,10 @@ void ModuleMap::addHeader(Module *Mod, Module::Header Header,
return;
HeaderList.push_back(KH);
- Mod->Headers[headerRoleToKind(Role)].push_back(std::move(Header));
+ Mod->Headers[headerRoleToKind(Role)].push_back(Header);
bool isCompilingModuleHeader =
- LangOpts.CompilingModule && Mod->getTopLevelModule() == SourceModule;
+ LangOpts.isCompilingModule() && Mod->getTopLevelModule() == SourceModule;
if (!Imported || isCompilingModuleHeader) {
// When we import HeaderFileInfo, the external source is expected to
// set the isModuleHeader flag itself.
@@ -1288,7 +1313,9 @@ namespace {
/// \brief The 'extern_c' attribute.
AT_extern_c,
/// \brief The 'exhaustive' attribute.
- AT_exhaustive
+ AT_exhaustive,
+ /// \brief The 'no_undeclared_includes' attribute.
+ AT_no_undeclared_includes
};
}
@@ -1458,8 +1485,47 @@ void ModuleMapParser::parseModuleDecl() {
ActiveModule->IsSystem = true;
if (Attrs.IsExternC)
ActiveModule->IsExternC = true;
+ if (Attrs.NoUndeclaredIncludes ||
+ (!ActiveModule->Parent && ModuleName == "Darwin"))
+ ActiveModule->NoUndeclaredIncludes = true;
ActiveModule->Directory = Directory;
+ if (!ActiveModule->Parent) {
+ StringRef MapFileName(ModuleMapFile->getName());
+ if (MapFileName.endswith("module.private.modulemap") ||
+ MapFileName.endswith("module_private.map")) {
+ // Adding a top-level module from a private modulemap is likely a
+ // user error; we check to see if there's another top-level module
+ // defined in the non-private map in the same dir, and if so emit a
+ // warning.
+ for (auto E = Map.module_begin(); E != Map.module_end(); ++E) {
+ auto const *M = E->getValue();
+ if (!M->Parent &&
+ M->Directory == ActiveModule->Directory &&
+ M->Name != ActiveModule->Name) {
+ Diags.Report(ActiveModule->DefinitionLoc,
+ diag::warn_mmap_mismatched_top_level_private)
+ << ActiveModule->Name << M->Name;
+ // The pattern we're defending against here is typically due to
+ // a module named FooPrivate which is supposed to be a submodule
+ // called Foo.Private. Emit a fixit in that case.
+ auto D =
+ Diags.Report(ActiveModule->DefinitionLoc,
+ diag::note_mmap_rename_top_level_private_as_submodule);
+ D << ActiveModule->Name << M->Name;
+ StringRef Bad(ActiveModule->Name);
+ if (Bad.consume_back("Private")) {
+ SmallString<128> Fixed = Bad;
+ Fixed.append(".Private");
+ D << FixItHint::CreateReplacement(ActiveModule->DefinitionLoc,
+ Fixed);
+ }
+ break;
+ }
+ }
+ }
+ }
+
bool Done = false;
do {
switch (Tok.Kind) {
@@ -1624,15 +1690,12 @@ void ModuleMapParser::parseExternModuleDecl() {
/// was never correct and causes issues now that we check it, so drop it.
static bool shouldAddRequirement(Module *M, StringRef Feature,
bool &IsRequiresExcludedHack) {
- static const StringRef DarwinCExcluded[] = {"Darwin", "C", "excluded"};
- static const StringRef TclPrivate[] = {"Tcl", "Private"};
- static const StringRef IOKitAVC[] = {"IOKit", "avc"};
-
- if (Feature == "excluded" && (M->fullModuleNameIs(DarwinCExcluded) ||
- M->fullModuleNameIs(TclPrivate))) {
+ if (Feature == "excluded" &&
+ (M->fullModuleNameIs({"Darwin", "C", "excluded"}) ||
+ M->fullModuleNameIs({"Tcl", "Private"}))) {
IsRequiresExcludedHack = true;
return false;
- } else if (Feature == "cplusplus" && M->fullModuleNameIs(IOKitAVC)) {
+ } else if (Feature == "cplusplus" && M->fullModuleNameIs({"IOKit", "avc"})) {
return false;
}
@@ -1824,13 +1887,7 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
// If Clang supplies this header but the underlying system does not,
// just silently swap in our builtin version. Otherwise, we'll end
// up adding both (later).
- //
- // For local visibility, entirely replace the system file with our
- // one and textually include the system one. We need to pass macros
- // from our header to the system one if we #include_next it.
- //
- // FIXME: Can we do this in all cases?
- if (BuiltinFile && (!File || Map.LangOpts.ModulesLocalVisibility)) {
+ if (BuiltinFile && !File) {
File = BuiltinFile;
RelativePathName = BuiltinPathName;
BuiltinFile = nullptr;
@@ -1856,15 +1913,20 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
Module::Header H = {RelativePathName.str(), File};
Map.excludeHeader(ActiveModule, H);
} else {
- // If there is a builtin counterpart to this file, add it now, before
- // the "real" header, so we build the built-in one first when building
- // the module.
+ // If there is a builtin counterpart to this file, add it now so it can
+ // wrap the system header.
if (BuiltinFile) {
// FIXME: Taking the name from the FileEntry is unstable and can give
// different results depending on how we've previously named that file
// in this build.
Module::Header H = { BuiltinFile->getName(), BuiltinFile };
Map.addHeader(ActiveModule, H, Role);
+
+ // If we have both a builtin and system version of the file, the
+ // builtin version may want to inject macros into the system header, so
+ // force the system header to be treated as a textual header in this
+ // case.
+ Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
}
// Record this header.
@@ -2354,6 +2416,7 @@ bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
= llvm::StringSwitch<AttributeKind>(Tok.getString())
.Case("exhaustive", AT_exhaustive)
.Case("extern_c", AT_extern_c)
+ .Case("no_undeclared_includes", AT_no_undeclared_includes)
.Case("system", AT_system)
.Default(AT_unknown);
switch (Attribute) {
@@ -2373,6 +2436,10 @@ bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
case AT_exhaustive:
Attrs.IsExhaustive = true;
break;
+
+ case AT_no_undeclared_includes:
+ Attrs.NoUndeclaredIncludes = true;
+ break;
}
consumeToken();
diff --git a/lib/Lex/PPCaching.cpp b/lib/Lex/PPCaching.cpp
index 4742aae5c123..45bdce32062a 100644
--- a/lib/Lex/PPCaching.cpp
+++ b/lib/Lex/PPCaching.cpp
@@ -86,7 +86,7 @@ void Preprocessor::EnterCachingLexMode() {
const Token &Preprocessor::PeekAhead(unsigned N) {
assert(CachedLexPos + N > CachedTokens.size() && "Confused caching.");
ExitCachingLexMode();
- for (unsigned C = CachedLexPos + N - CachedTokens.size(); C > 0; --C) {
+ for (size_t C = CachedLexPos + N - CachedTokens.size(); C > 0; --C) {
CachedTokens.push_back(Token());
Lex(CachedTokens.back());
}
@@ -105,7 +105,7 @@ void Preprocessor::AnnotatePreviousCachedTokens(const Token &Tok) {
for (CachedTokensTy::size_type i = CachedLexPos; i != 0; --i) {
CachedTokensTy::iterator AnnotBegin = CachedTokens.begin() + i-1;
if (AnnotBegin->getLocation() == Tok.getLocation()) {
- assert((BacktrackPositions.empty() || BacktrackPositions.back() < i) &&
+ assert((BacktrackPositions.empty() || BacktrackPositions.back() <= i) &&
"The backtrack pos points inside the annotated tokens!");
// Replace the cached tokens with the single annotation token.
if (i < CachedLexPos)
diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp
index 77f118fd3ccb..85504de3d15d 100644
--- a/lib/Lex/PPDirectives.cpp
+++ b/lib/Lex/PPDirectives.cpp
@@ -12,25 +12,41 @@
///
//===----------------------------------------------------------------------===//
-#include "clang/Lex/Preprocessor.h"
+#include "clang/Basic/CharInfo.h"
#include "clang/Basic/FileManager.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/Module.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TokenKinds.h"
#include "clang/Lex/CodeCompletionHandler.h"
#include "clang/Lex/HeaderSearch.h"
-#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Lex/LexDiagnostic.h"
#include "clang/Lex/LiteralSupport.h"
#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/ModuleLoader.h"
+#include "clang/Lex/ModuleMap.h"
+#include "clang/Lex/PPCallbacks.h"
#include "clang/Lex/Pragma.h"
-#include "llvm/ADT/APInt.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/PTHLexer.h"
+#include "clang/Lex/Token.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
-#include "llvm/ADT/iterator_range.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/AlignOf.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Path.h"
-#include "llvm/Support/SaveAndRestore.h"
+#include <algorithm>
+#include <cassert>
+#include <cstring>
+#include <new>
+#include <string>
+#include <utility>
using namespace clang;
@@ -53,7 +69,7 @@ MacroInfo *Preprocessor::AllocateMacroInfo(SourceLocation L) {
MacroInfo *Preprocessor::AllocateDeserializedMacroInfo(SourceLocation L,
unsigned SubModuleID) {
- static_assert(llvm::AlignOf<MacroInfo>::Alignment >= sizeof(SubModuleID),
+ static_assert(alignof(MacroInfo) >= sizeof(SubModuleID),
"alignment for MacroInfo is less than the ID");
DeserializedMacroInfoChain *MIChain =
BP.Allocate<DeserializedMacroInfoChain>();
@@ -268,7 +284,7 @@ bool Preprocessor::CheckMacroName(Token &MacroNameTok, MacroUse isDefineUndef,
if (ShadowFlag)
*ShadowFlag = false;
if (!SourceMgr.isInSystemHeader(MacroNameLoc) &&
- (strcmp(SourceMgr.getBufferName(MacroNameLoc), "<built-in>") != 0)) {
+ (SourceMgr.getBufferName(MacroNameLoc) != "<built-in>")) {
MacroDiag D = MD_NoWarn;
if (isDefineUndef == MU_Define) {
D = shouldWarnOnMacroDef(*this, II);
@@ -382,7 +398,7 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation IfTokenLoc,
// disabling warnings, etc.
CurPPLexer->LexingRawMode = true;
Token Tok;
- while (1) {
+ while (true) {
CurLexer->Lex(Tok);
if (Tok.is(tok::code_completion)) {
@@ -455,7 +471,7 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation IfTokenLoc,
Directive = RI;
} else {
std::string DirectiveStr = getSpelling(Tok);
- unsigned IdLen = DirectiveStr.size();
+ size_t IdLen = DirectiveStr.size();
if (IdLen >= 20) {
CurPPLexer->ParsingPreprocessorDirective = false;
// Restore comment saving mode.
@@ -578,7 +594,7 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation IfTokenLoc,
}
void Preprocessor::PTHSkipExcludedConditionalBlock() {
- while (1) {
+ while (true) {
assert(CurPTHLexer);
assert(CurPTHLexer->LexingRawMode == false);
@@ -785,8 +801,7 @@ const FileEntry *Preprocessor::LookupFile(
// headers included by quoted include directives.
// See: http://msdn.microsoft.com/en-us/library/36k2cdd4.aspx
if (LangOpts.MSVCCompat && !isAngled) {
- for (unsigned i = 0, e = IncludeMacroStack.size(); i != e; ++i) {
- IncludeStackInfo &ISEntry = IncludeMacroStack[e - i - 1];
+ for (IncludeStackInfo &ISEntry : llvm::reverse(IncludeMacroStack)) {
if (IsFileLexer(ISEntry))
if ((FileEnt = ISEntry.ThePPLexer->getFileEntry()))
Includers.push_back(std::make_pair(FileEnt, FileEnt->getDir()));
@@ -849,8 +864,7 @@ const FileEntry *Preprocessor::LookupFile(
}
}
- for (unsigned i = 0, e = IncludeMacroStack.size(); i != e; ++i) {
- IncludeStackInfo &ISEntry = IncludeMacroStack[e-i-1];
+ for (IncludeStackInfo &ISEntry : llvm::reverse(IncludeMacroStack)) {
if (IsFileLexer(ISEntry)) {
if ((CurFileEnt = ISEntry.ThePPLexer->getFileEntry())) {
if ((FE = HeaderInfo.LookupSubframeworkHeader(
@@ -998,11 +1012,11 @@ void Preprocessor::HandleDirective(Token &Result) {
case tok::pp_define:
return HandleDefineDirective(Result, ImmediatelyAfterTopLevelIfndef);
case tok::pp_undef:
- return HandleUndefDirective(Result);
+ return HandleUndefDirective();
// C99 6.10.4 - Line Control.
case tok::pp_line:
- return HandleLineDirective(Result);
+ return HandleLineDirective();
// C99 6.10.5 - Error Directive.
case tok::pp_error:
@@ -1039,7 +1053,7 @@ void Preprocessor::HandleDirective(Token &Result) {
case tok::pp___private_macro:
if (getLangOpts().Modules)
- return HandleMacroPrivateDirective(Result);
+ return HandleMacroPrivateDirective();
break;
}
break;
@@ -1137,7 +1151,7 @@ static bool GetLineValue(Token &DigitTok, unsigned &Val,
/// # line digit-sequence
/// # line digit-sequence "s-char-sequence"
/// \endverbatim
-void Preprocessor::HandleLineDirective(Token &Tok) {
+void Preprocessor::HandleLineDirective() {
// Read the line # and string argument. Per C99 6.10.4p5, these tokens are
// expanded.
Token DigitTok;
@@ -1442,7 +1456,7 @@ void Preprocessor::HandleMacroPublicDirective(Token &Tok) {
}
/// \brief Handle a #private directive.
-void Preprocessor::HandleMacroPrivateDirective(Token &Tok) {
+void Preprocessor::HandleMacroPrivateDirective() {
Token MacroNameTok;
ReadMacroName(MacroNameTok, MU_Undef);
@@ -1551,7 +1565,7 @@ bool Preprocessor::ConcatenateIncludeName(SmallString<128> &FilenameBuffer,
FilenameBuffer.push_back(' ');
// Get the spelling of the token, directly into FilenameBuffer if possible.
- unsigned PreAppendSize = FilenameBuffer.size();
+ size_t PreAppendSize = FilenameBuffer.size();
FilenameBuffer.resize(PreAppendSize+CurTok.getLength());
const char *BufPtr = &FilenameBuffer[PreAppendSize];
@@ -1602,7 +1616,7 @@ static void diagnoseAutoModuleImport(
assert(PP.getLangOpts().ObjC2 && "no import syntax available");
SmallString<128> PathString;
- for (unsigned I = 0, N = Path.size(); I != N; ++I) {
+ for (size_t I = 0, N = Path.size(); I != N; ++I) {
if (I)
PathString += '.';
PathString += Path[I].first->getName();
@@ -1831,7 +1845,8 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
// If the file is still not found, just go with the vanilla diagnostic
if (!File)
- Diag(FilenameTok, diag::err_pp_file_not_found) << Filename;
+ Diag(FilenameTok, diag::err_pp_file_not_found) << Filename
+ << FilenameRange;
}
}
@@ -1851,12 +1866,9 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
// unavailable, diagnose the situation and bail out.
// FIXME: Remove this; loadModule does the same check (but produces
// slightly worse diagnostics).
- if (!SuggestedModule.getModule()->isAvailable() &&
- !SuggestedModule.getModule()
- ->getTopLevelModule()
- ->HasIncompatibleModuleFile) {
- clang::Module::Requirement Requirement;
- clang::Module::UnresolvedHeaderDirective MissingHeader;
+ if (!SuggestedModule.getModule()->isAvailable()) {
+ Module::Requirement Requirement;
+ Module::UnresolvedHeaderDirective MissingHeader;
Module *M = SuggestedModule.getModule();
// Identify the cause.
(void)M->isAvailable(getLangOpts(), getTargetInfo(), Requirement,
@@ -1903,9 +1915,12 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
else if (Imported.isMissingExpected()) {
// We failed to find a submodule that we assumed would exist (because it
// was in the directory of an umbrella header, for instance), but no
- // actual module exists for it (because the umbrella header is
+ // actual module containing it exists (because the umbrella header is
// incomplete). Treat this as a textual inclusion.
SuggestedModule = ModuleMap::KnownHeader();
+ } else if (Imported.isConfigMismatch()) {
+ // On a configuration mismatch, enter the header textually. We still know
+ // that it's part of the corresponding module.
} else {
// We hit an error processing the import. Bail out.
if (hadModuleLoaderFatalFailure()) {
@@ -2043,7 +2058,11 @@ void Preprocessor::HandleIncludeNextDirective(SourceLocation HashLoc,
// diagnostic.
const DirectoryLookup *Lookup = CurDirLookup;
const FileEntry *LookupFromFile = nullptr;
- if (isInPrimaryFile()) {
+ if (isInPrimaryFile() && LangOpts.IsHeaderFile) {
+ // If the main file is a header, then it's either for PCH/AST generation,
+ // or libclang opened it. Either way, handle it as a normal include below
+ // and do not complain about include_next.
+ } else if (isInPrimaryFile()) {
Lookup = nullptr;
Diag(IncludeNextTok, diag::pp_include_next_in_primary);
} else if (CurSubmodule) {
@@ -2098,7 +2117,7 @@ void Preprocessor::HandleIncludeMacrosDirective(SourceLocation HashLoc,
// This directive should only occur in the predefines buffer. If not, emit an
// error and reject it.
SourceLocation Loc = IncludeMacrosTok.getLocation();
- if (strcmp(SourceMgr.getBufferName(Loc), "<built-in>") != 0) {
+ if (SourceMgr.getBufferName(Loc) != "<built-in>") {
Diag(IncludeMacrosTok.getLocation(),
diag::pp_include_macros_out_of_predefines);
DiscardUntilEndOfDirective();
@@ -2127,7 +2146,7 @@ void Preprocessor::HandleIncludeMacrosDirective(SourceLocation HashLoc,
bool Preprocessor::ReadMacroDefinitionArgList(MacroInfo *MI, Token &Tok) {
SmallVector<IdentifierInfo*, 32> Arguments;
- while (1) {
+ while (true) {
LexUnexpandedToken(Tok);
switch (Tok.getKind()) {
case tok::r_paren:
@@ -2536,7 +2555,7 @@ void Preprocessor::HandleDefineDirective(Token &DefineTok,
/// HandleUndefDirective - Implements \#undef.
///
-void Preprocessor::HandleUndefDirective(Token &UndefTok) {
+void Preprocessor::HandleUndefDirective() {
++NumUndefined;
Token MacroNameTok;
diff --git a/lib/Lex/PPExpressions.cpp b/lib/Lex/PPExpressions.cpp
index 94075ece35ca..862a4713e4bc 100644
--- a/lib/Lex/PPExpressions.cpp
+++ b/lib/Lex/PPExpressions.cpp
@@ -17,14 +17,24 @@
//===----------------------------------------------------------------------===//
#include "clang/Lex/Preprocessor.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TokenKinds.h"
#include "clang/Lex/CodeCompletionHandler.h"
#include "clang/Lex/LexDiagnostic.h"
#include "clang/Lex/LiteralSupport.h"
#include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/PPCallbacks.h"
+#include "clang/Lex/Token.h"
#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/SaveAndRestore.h"
+#include <cassert>
+
using namespace clang;
namespace {
@@ -34,6 +44,7 @@ namespace {
class PPValue {
SourceRange Range;
IdentifierInfo *II;
+
public:
llvm::APSInt Val;
@@ -58,7 +69,7 @@ public:
void setEnd(SourceLocation L) { Range.setEnd(L); }
};
-}
+} // end anonymous namespace
static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec,
Token &PeekTok, bool ValueLive,
@@ -469,8 +480,6 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
}
}
-
-
/// getPrecedence - Return the precedence of the specified binary operator
/// token. This returns:
/// ~0 - Invalid token.
@@ -531,7 +540,7 @@ static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec,
return true;
}
- while (1) {
+ while (true) {
// If this token has a lower precedence than we are allowed to parse, return
// it so that higher levels of the recursion can parse it.
if (PeekPrec < MinPrec)
diff --git a/lib/Lex/PPLexerChange.cpp b/lib/Lex/PPLexerChange.cpp
index e2eceafd983b..4db17c344b67 100644
--- a/lib/Lex/PPLexerChange.cpp
+++ b/lib/Lex/PPLexerChange.cpp
@@ -40,10 +40,10 @@ bool Preprocessor::isInPrimaryFile() const {
// If there are any stacked lexers, we're in a #include.
assert(IsFileLexer(IncludeMacroStack[0]) &&
"Top level include stack isn't our primary lexer?");
- for (unsigned i = 1, e = IncludeMacroStack.size(); i != e; ++i)
- if (IsFileLexer(IncludeMacroStack[i]))
- return false;
- return true;
+ return std::none_of(IncludeMacroStack.begin() + 1, IncludeMacroStack.end(),
+ [this](const IncludeStackInfo &ISI) -> bool {
+ return IsFileLexer(ISI);
+ });
}
/// getCurrentLexer - Return the current file lexer being lexed from. Note
@@ -54,8 +54,7 @@ PreprocessorLexer *Preprocessor::getCurrentFileLexer() const {
return CurPPLexer;
// Look for a stacked lexer.
- for (unsigned i = IncludeMacroStack.size(); i != 0; --i) {
- const IncludeStackInfo& ISI = IncludeMacroStack[i-1];
+ for (const IncludeStackInfo &ISI : llvm::reverse(IncludeMacroStack)) {
if (IsFileLexer(ISI))
return ISI.ThePPLexer;
}
@@ -566,8 +565,7 @@ void Preprocessor::HandleMicrosoftCommentPaste(Token &Tok) {
// explicit EOD token.
PreprocessorLexer *FoundLexer = nullptr;
bool LexerWasInPPMode = false;
- for (unsigned i = 0, e = IncludeMacroStack.size(); i != e; ++i) {
- IncludeStackInfo &ISI = *(IncludeMacroStack.end()-i-1);
+ for (const IncludeStackInfo &ISI : llvm::reverse(IncludeMacroStack)) {
if (ISI.ThePPLexer == nullptr) continue; // Scan for a real lexer.
// Once we find a real lexer, mark it as raw mode (disabling macro
@@ -685,7 +683,7 @@ bool Preprocessor::needModuleMacros() const {
return true;
// Otherwise, we only need module macros if we're actually compiling a module
// interface.
- return getLangOpts().CompilingModule;
+ return getLangOpts().isCompilingModule();
}
void Preprocessor::LeaveSubmodule() {
diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp
index 2ade6df9456a..aebebaac46ac 100644
--- a/lib/Lex/PPMacroExpansion.cpp
+++ b/lib/Lex/PPMacroExpansion.cpp
@@ -12,25 +12,49 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Lex/Preprocessor.h"
#include "clang/Basic/Attributes.h"
#include "clang/Basic/FileManager.h"
-#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/ObjCRuntime.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/CodeCompletionHandler.h"
+#include "clang/Lex/DirectoryLookup.h"
#include "clang/Lex/ExternalPreprocessorSource.h"
#include "clang/Lex/LexDiagnostic.h"
#include "clang/Lex/MacroArgs.h"
#include "clang/Lex/MacroInfo.h"
-#include "llvm/ADT/STLExtras.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/PreprocessorLexer.h"
+#include "clang/Lex/PTHLexer.h"
+#include "clang/Lex/Token.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#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"
#include "llvm/Support/raw_ostream.h"
-#include <cstdio>
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstring>
#include <ctime>
+#include <string>
+#include <tuple>
+#include <utility>
+
using namespace clang;
MacroDirective *
@@ -68,12 +92,35 @@ void Preprocessor::appendMacroDirective(IdentifierInfo *II, MacroDirective *MD){
}
void Preprocessor::setLoadedMacroDirective(IdentifierInfo *II,
+ MacroDirective *ED,
MacroDirective *MD) {
+ // Normally, when a macro is defined, it goes through appendMacroDirective()
+ // above, which chains a macro to previous defines, undefs, etc.
+ // However, in a pch, the whole macro history up to the end of the pch is
+ // stored, so ASTReader goes through this function instead.
+ // However, built-in macros are already registered in the Preprocessor
+ // ctor, and ASTWriter stops writing the macro chain at built-in macros,
+ // so in that case the chain from the pch needs to be spliced to the existing
+ // built-in.
+
assert(II && MD);
MacroState &StoredMD = CurSubmoduleState->Macros[II];
- assert(!StoredMD.getLatest() &&
- "the macro history was modified before initializing it from a pch");
- StoredMD = MD;
+
+ if (auto *OldMD = StoredMD.getLatest()) {
+ // shouldIgnoreMacro() in ASTWriter also stops at macros from the
+ // predefines buffer in module builds. However, in module builds, modules
+ // are loaded completely before predefines are processed, so StoredMD
+ // will be nullptr for them when they're loaded. StoredMD should only be
+ // non-nullptr for builtins read from a pch file.
+ assert(OldMD->getMacroInfo()->isBuiltinMacro() &&
+ "only built-ins should have an entry here");
+ assert(!OldMD->getPrevious() && "builtin should only have a single entry");
+ ED->setPrevious(OldMD);
+ StoredMD.setLatest(MD);
+ } else {
+ StoredMD = MD;
+ }
+
// Setup the identifier as having associated macro history.
II->setHasMacroDefinition(true);
if (!MD->isDefined() && LeafModuleMacros.find(II) == LeafModuleMacros.end())
@@ -286,7 +333,6 @@ static IdentifierInfo *RegisterBuiltinMacro(Preprocessor &PP, const char *Name){
return Id;
}
-
/// RegisterBuiltinMacros - Register builtin macros, such as __LINE__ with the
/// identifier table.
void Preprocessor::RegisterBuiltinMacros() {
@@ -367,10 +413,8 @@ static bool isTrivialSingleTokenExpansion(const MacroInfo *MI,
// If this is a function-like macro invocation, it's safe to trivially expand
// as long as the identifier is not a macro argument.
return std::find(MI->arg_begin(), MI->arg_end(), II) == MI->arg_end();
-
}
-
/// isNextPPTokenLParen - Determine whether the next preprocessor token to be
/// lexed is a '('. If so, consume the token and return true, if not, this
/// method should have no observable side-effect on the lexed tokens.
@@ -390,8 +434,7 @@ bool Preprocessor::isNextPPTokenLParen() {
// macro stack.
if (CurPPLexer)
return false;
- for (unsigned i = IncludeMacroStack.size(); i != 0; --i) {
- IncludeStackInfo &Entry = IncludeMacroStack[i-1];
+ for (const IncludeStackInfo &Entry : llvm::reverse(IncludeMacroStack)) {
if (Entry.TheLexer)
Val = Entry.TheLexer->isNextPPTokenLParen();
else if (Entry.ThePTHLexer)
@@ -480,8 +523,7 @@ bool Preprocessor::HandleMacroExpandedIdentifier(Token &Identifier,
} else {
Callbacks->MacroExpands(Identifier, M, ExpansionRange, Args);
if (!DelayedMacroExpandsCallbacks.empty()) {
- for (unsigned i=0, e = DelayedMacroExpandsCallbacks.size(); i!=e; ++i) {
- MacroExpandsInfo &Info = DelayedMacroExpandsCallbacks[i];
+ for (const MacroExpandsInfo &Info : DelayedMacroExpandsCallbacks) {
// FIXME: We lose macro args info with delayed callback.
Callbacks->MacroExpands(Info.Tok, Info.MD, Info.Range,
/*Args=*/nullptr);
@@ -735,14 +777,14 @@ MacroArgs *Preprocessor::ReadFunctionLikeMacroArgs(Token &MacroName,
assert(Tok.isOneOf(tok::l_paren, tok::comma) &&
"only expect argument separators here");
- unsigned ArgTokenStart = ArgTokens.size();
+ size_t ArgTokenStart = ArgTokens.size();
SourceLocation ArgStartLoc = Tok.getLocation();
// C99 6.10.3p11: Keep track of the number of l_parens we have seen. Note
// that we already consumed the first one.
unsigned NumParens = 0;
- while (1) {
+ while (true) {
// Read arguments as unexpanded tokens. This avoids issues, e.g., where
// an argument value in a macro could expand to ',' or '(' or ')'.
LexUnexpandedToken(Tok);
@@ -987,10 +1029,10 @@ Token *Preprocessor::cacheMacroExpandedTokens(TokenLexer *tokLexer,
if (cacheNeedsToGrow) {
// Go through all the TokenLexers whose 'Tokens' pointer points in the
// buffer and update the pointers to the (potential) new buffer array.
- for (unsigned i = 0, e = MacroExpandingLexersStack.size(); i != e; ++i) {
+ for (const auto &Lexer : MacroExpandingLexersStack) {
TokenLexer *prevLexer;
size_t tokIndex;
- std::tie(prevLexer, tokIndex) = MacroExpandingLexersStack[i];
+ std::tie(prevLexer, tokIndex) = Lexer;
prevLexer->Tokens = MacroExpandedTokens.data() + tokIndex;
}
}
@@ -1043,7 +1085,6 @@ static void ComputeDATE_TIME(SourceLocation &DATELoc, SourceLocation &TIMELoc,
}
}
-
/// HasFeature - Return true if we recognize and implement the feature
/// specified by the identifier as a standard language feature.
static bool HasFeature(const Preprocessor &PP, StringRef Feature) {
@@ -1090,6 +1131,7 @@ static bool HasFeature(const Preprocessor &PP, StringRef Feature) {
.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))
@@ -1171,7 +1213,7 @@ static bool HasFeature(const Preprocessor &PP, StringRef Feature) {
.Case("cxx_unrestricted_unions", LangOpts.CPlusPlus11)
.Case("cxx_user_literals", LangOpts.CPlusPlus11)
.Case("cxx_variadic_templates", LangOpts.CPlusPlus11)
- // C++1y features
+ // C++14 features
.Case("cxx_aggregate_nsdmi", LangOpts.CPlusPlus14)
.Case("cxx_binary_literals", LangOpts.CPlusPlus14)
.Case("cxx_contextual_conversions", LangOpts.CPlusPlus14)
@@ -1181,6 +1223,9 @@ static bool HasFeature(const Preprocessor &PP, StringRef Feature) {
.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)
@@ -1264,7 +1309,7 @@ static bool HasExtension(const Preprocessor &PP, StringRef Extension) {
.Case("cxx_reference_qualified_functions", LangOpts.CPlusPlus)
.Case("cxx_rvalue_references", LangOpts.CPlusPlus)
.Case("cxx_variadic_templates", LangOpts.CPlusPlus)
- // C++1y features supported by other languages as extensions.
+ // 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)
@@ -1400,7 +1445,11 @@ static bool EvaluateHasIncludeNext(Token &Tok,
// Preprocessor::HandleIncludeNextDirective.
const DirectoryLookup *Lookup = PP.GetCurDirLookup();
const FileEntry *LookupFromFile = nullptr;
- if (PP.isInPrimaryFile()) {
+ if (PP.isInPrimaryFile() && PP.getLangOpts().IsHeaderFile) {
+ // If the main file is a header, then it's either for PCH/AST generation,
+ // or libclang opened it. Either way, handle it as a normal include below
+ // and do not complain about __has_include_next.
+ } else if (PP.isInPrimaryFile()) {
Lookup = nullptr;
PP.Diag(Tok, diag::pp_include_next_in_primary);
} else if (PP.getCurrentSubmodule()) {
@@ -1796,7 +1845,7 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
[this](Token &Tok, bool &HasLexedNextToken) -> int {
IdentifierInfo *II = ExpectFeatureIdentifierInfo(Tok, *this,
diag::err_expected_id_building_module);
- return getLangOpts().CompilingModule && II &&
+ return getLangOpts().isCompilingModule() && II &&
(II->getName() == getLangOpts().CurrentModule);
});
} else if (II == Ident__MODULE__) {
diff --git a/lib/Lex/PTHLexer.cpp b/lib/Lex/PTHLexer.cpp
index 5f63d35c5be7..ec806e844531 100644
--- a/lib/Lex/PTHLexer.cpp
+++ b/lib/Lex/PTHLexer.cpp
@@ -21,7 +21,6 @@
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/Token.h"
#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/StringMap.h"
#include "llvm/Support/EndianStream.h"
#include "llvm/Support/MemoryBuffer.h"
#include <memory>
@@ -318,7 +317,7 @@ public:
class PTHFileLookupCommonTrait {
public:
- typedef std::pair<unsigned char, const char*> internal_key_type;
+ typedef std::pair<unsigned char, StringRef> internal_key_type;
typedef unsigned hash_value_type;
typedef unsigned offset_type;
@@ -353,7 +352,7 @@ public:
}
static bool EqualKey(internal_key_type a, internal_key_type b) {
- return a.first == b.first && strcmp(a.second, b.second) == 0;
+ return a.first == b.first && a.second == b.second;
}
static PTHFileData ReadData(const internal_key_type& k,
@@ -629,15 +628,15 @@ PTHLexer *PTHManager::CreateLexer(FileID FID) {
namespace {
class PTHStatData {
public:
- const bool HasData;
uint64_t Size;
time_t ModTime;
llvm::sys::fs::UniqueID UniqueID;
+ const bool HasData;
bool IsDirectory;
PTHStatData(uint64_t Size, time_t ModTime, llvm::sys::fs::UniqueID UniqueID,
bool IsDirectory)
- : HasData(true), Size(Size), ModTime(ModTime), UniqueID(UniqueID),
+ : Size(Size), ModTime(ModTime), UniqueID(UniqueID), HasData(true),
IsDirectory(IsDirectory) {}
PTHStatData() : HasData(false) {}
@@ -645,10 +644,10 @@ public:
class PTHStatLookupTrait : public PTHFileLookupCommonTrait {
public:
- typedef const char* external_key_type; // const char*
+ typedef StringRef external_key_type; // const char*
typedef PTHStatData data_type;
- static internal_key_type GetInternalKey(const char *path) {
+ static internal_key_type GetInternalKey(StringRef path) {
// The key 'kind' doesn't matter here because it is ignored in EqualKey.
return std::make_pair((unsigned char) 0x0, path);
}
@@ -656,7 +655,7 @@ public:
static bool EqualKey(internal_key_type a, internal_key_type b) {
// When doing 'stat' lookups we don't care about the kind of 'a' and 'b',
// just the paths.
- return strcmp(a.second, b.second) == 0;
+ return a.second == b.second;
}
static data_type ReadData(const internal_key_type& k, const unsigned char* d,
@@ -695,7 +694,7 @@ public:
: Cache(FL.getNumBuckets(), FL.getNumEntries(), FL.getBuckets(),
FL.getBase()) {}
- LookupResult getStat(const char *Path, FileData &Data, bool isFile,
+ LookupResult getStat(StringRef Path, FileData &Data, bool isFile,
std::unique_ptr<vfs::File> *F,
vfs::FileSystem &FS) override {
// Do the lookup for the file's data in the PTH file.
diff --git a/lib/Lex/Pragma.cpp b/lib/Lex/Pragma.cpp
index 3bdd31b26ff8..100da514144a 100644
--- a/lib/Lex/Pragma.cpp
+++ b/lib/Lex/Pragma.cpp
@@ -14,21 +14,36 @@
#include "clang/Lex/Pragma.h"
#include "clang/Basic/FileManager.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TokenKinds.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/LexDiagnostic.h"
-#include "clang/Lex/LiteralSupport.h"
#include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/PPCallbacks.h"
#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/PreprocessorLexer.h"
+#include "clang/Lex/PTHLexer.h"
+#include "clang/Lex/Token.h"
+#include "clang/Lex/TokenLexer.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringSwitch.h"
-#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/CrashRecoveryContext.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include <algorithm>
-using namespace clang;
+#include <cassert>
+#include <cstdint>
+#include <limits>
+#include <string>
+#include <vector>
-#include "llvm/Support/raw_ostream.h"
+using namespace clang;
// Out-of-line destructor to provide a home for the class.
PragmaHandler::~PragmaHandler() {
@@ -123,6 +138,7 @@ void Preprocessor::HandlePragmaDirective(SourceLocation IntroducerLoc,
}
namespace {
+
/// \brief Helper class for \see Preprocessor::Handle_Pragma.
class LexingFor_PragmaRAII {
Preprocessor &PP;
@@ -157,7 +173,8 @@ public:
Failed = true;
}
};
-}
+
+} // end anonymous namespace
/// Handle_Pragma - Read a _Pragma directive, slice it up, process it, then
/// return the first token after the directive. The _Pragma token has just
@@ -264,7 +281,7 @@ void Preprocessor::Handle_Pragma(Token &Tok) {
// Remove escaped quotes and escapes.
unsigned ResultPos = 1;
- for (unsigned i = 1, e = StrVal.size() - 1; i != e; ++i) {
+ for (size_t i = 1, e = StrVal.size() - 1; i != e; ++i) {
// Skip escapes. \\ -> '\' and \" -> '"'.
if (StrVal[i] == '\\' && i + 1 < e &&
(StrVal[i + 1] == '\\' || StrVal[i + 1] == '"'))
@@ -355,8 +372,10 @@ void Preprocessor::HandleMicrosoft__pragma(Token &Tok) {
///
void Preprocessor::HandlePragmaOnce(Token &OnceTok) {
// Don't honor the 'once' when handling the primary source file, unless
- // this is a prefix to a TU, which indicates we're generating a PCH file.
- if (isInPrimaryFile() && TUKind != TU_Prefix) {
+ // this is a prefix to a TU, which indicates we're generating a PCH file, or
+ // when the main file is a header (e.g. when -xc-header is provided on the
+ // commandline).
+ if (isInPrimaryFile() && TUKind != TU_Prefix && !getLangOpts().IsHeaderFile) {
Diag(OnceTok, diag::pp_pragma_once_in_main_file);
return;
}
@@ -374,13 +393,12 @@ void Preprocessor::HandlePragmaMark() {
CurPTHLexer->DiscardToEndOfLine();
}
-
/// HandlePragmaPoison - Handle \#pragma GCC poison. PoisonTok is the 'poison'.
///
-void Preprocessor::HandlePragmaPoison(Token &PoisonTok) {
+void Preprocessor::HandlePragmaPoison() {
Token Tok;
- while (1) {
+ while (true) {
// Read the next token to poison. While doing this, pretend that we are
// skipping while reading the identifier to poison.
// This avoids errors on code like:
@@ -612,7 +630,7 @@ void Preprocessor::HandlePragmaPopMacro(Token &PopMacroTok) {
// Pop PragmaPushMacroInfo stack.
iter->second.pop_back();
- if (iter->second.size() == 0)
+ if (iter->second.empty())
PragmaPushMacroInfo.erase(iter);
} else {
Diag(MessageLoc, diag::warn_pragma_pop_macro_no_push)
@@ -809,6 +827,7 @@ bool Preprocessor::LexOnOffSwitch(tok::OnOffSwitch &Result) {
}
namespace {
+
/// PragmaOnceHandler - "\#pragma once" marks the file as atomically included.
struct PragmaOnceHandler : public PragmaHandler {
PragmaOnceHandler() : PragmaHandler("once") {}
@@ -823,6 +842,7 @@ struct PragmaOnceHandler : public PragmaHandler {
/// rest of the line is not lexed.
struct PragmaMarkHandler : public PragmaHandler {
PragmaMarkHandler() : PragmaHandler("mark") {}
+
void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
Token &MarkTok) override {
PP.HandlePragmaMark();
@@ -832,9 +852,10 @@ struct PragmaMarkHandler : public PragmaHandler {
/// PragmaPoisonHandler - "\#pragma poison x" marks x as not usable.
struct PragmaPoisonHandler : public PragmaHandler {
PragmaPoisonHandler() : PragmaHandler("poison") {}
+
void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
Token &PoisonTok) override {
- PP.HandlePragmaPoison(PoisonTok);
+ PP.HandlePragmaPoison();
}
};
@@ -842,14 +863,17 @@ struct PragmaPoisonHandler : public PragmaHandler {
/// as a system header, which silences warnings in it.
struct PragmaSystemHeaderHandler : public PragmaHandler {
PragmaSystemHeaderHandler() : PragmaHandler("system_header") {}
+
void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
Token &SHToken) override {
PP.HandlePragmaSystemHeader(SHToken);
PP.CheckEndOfDirective("pragma");
}
};
+
struct PragmaDependencyHandler : public PragmaHandler {
PragmaDependencyHandler() : PragmaHandler("dependency") {}
+
void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
Token &DepToken) override {
PP.HandlePragmaDependency(DepToken);
@@ -858,6 +882,7 @@ struct PragmaDependencyHandler : public PragmaHandler {
struct PragmaDebugHandler : public PragmaHandler {
PragmaDebugHandler() : PragmaHandler("__debug") {}
+
void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
Token &DepToken) override {
Token Tok;
@@ -967,9 +992,11 @@ struct PragmaDebugHandler : public PragmaHandler {
struct PragmaDiagnosticHandler : public PragmaHandler {
private:
const char *Namespace;
+
public:
explicit PragmaDiagnosticHandler(const char *NS) :
PragmaHandler("diagnostic"), Namespace(NS) {}
+
void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
Token &DiagToken) override {
SourceLocation DiagLoc = DiagToken.getLocation();
@@ -1142,7 +1169,7 @@ struct PragmaWarningHandler : public PragmaHandler {
while (Tok.is(tok::numeric_constant)) {
uint64_t Value;
if (!PP.parseSimpleIntegerLiteral(Tok, Value) || Value == 0 ||
- Value > INT_MAX) {
+ Value > std::numeric_limits<int>::max()) {
PP.Diag(Tok, diag::warn_pragma_warning_expected_number);
return;
}
@@ -1267,17 +1294,18 @@ public:
/// macro on the top of the stack.
struct PragmaPushMacroHandler : public PragmaHandler {
PragmaPushMacroHandler() : PragmaHandler("push_macro") {}
+
void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
Token &PushMacroTok) override {
PP.HandlePragmaPushMacro(PushMacroTok);
}
};
-
/// PragmaPopMacroHandler - "\#pragma pop_macro" sets the value of the
/// macro to the value on the top of the stack.
struct PragmaPopMacroHandler : public PragmaHandler {
PragmaPopMacroHandler() : PragmaHandler("pop_macro") {}
+
void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
Token &PopMacroTok) override {
PP.HandlePragmaPopMacro(PopMacroTok);
@@ -1289,6 +1317,7 @@ struct PragmaPopMacroHandler : public PragmaHandler {
/// 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;
@@ -1303,6 +1332,7 @@ struct PragmaSTDC_FENV_ACCESSHandler : public PragmaHandler {
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;
@@ -1313,6 +1343,7 @@ struct PragmaSTDC_CX_LIMITED_RANGEHandler : public PragmaHandler {
/// PragmaSTDC_UnknownHandler - "\#pragma STDC ...".
struct PragmaSTDC_UnknownHandler : public PragmaHandler {
PragmaSTDC_UnknownHandler() {}
+
void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
Token &UnknownTok) override {
// C99 6.10.6p2, unknown forms are not allowed.
@@ -1324,6 +1355,7 @@ struct PragmaSTDC_UnknownHandler : public PragmaHandler {
/// \#pragma clang arc_cf_code_audited begin/end
struct PragmaARCCFCodeAuditedHandler : public PragmaHandler {
PragmaARCCFCodeAuditedHandler() : PragmaHandler("arc_cf_code_audited") {}
+
void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
Token &NameTok) override {
SourceLocation Loc = NameTok.getLocation();
@@ -1378,6 +1410,7 @@ struct PragmaARCCFCodeAuditedHandler : public PragmaHandler {
/// \#pragma clang assume_nonnull begin/end
struct PragmaAssumeNonNullHandler : public PragmaHandler {
PragmaAssumeNonNullHandler() : PragmaHandler("assume_nonnull") {}
+
void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
Token &NameTok) override {
SourceLocation Loc = NameTok.getLocation();
@@ -1451,8 +1484,7 @@ struct PragmaRegionHandler : public PragmaHandler {
}
};
-} // end anonymous namespace
-
+} // end anonymous namespace
/// RegisterBuiltinPragmas - Install the standard preprocessor pragmas:
/// \#pragma GCC poison/system_header/dependency and \#pragma once.
diff --git a/lib/Lex/PreprocessingRecord.cpp b/lib/Lex/PreprocessingRecord.cpp
index 32e6de69f0db..13e15f3c943b 100644
--- a/lib/Lex/PreprocessingRecord.cpp
+++ b/lib/Lex/PreprocessingRecord.cpp
@@ -21,18 +21,13 @@ using namespace clang;
ExternalPreprocessingRecordSource::~ExternalPreprocessingRecordSource() { }
-
InclusionDirective::InclusionDirective(PreprocessingRecord &PPRec,
- InclusionKind Kind,
- StringRef FileName,
+ InclusionKind Kind, StringRef FileName,
bool InQuotes, bool ImportedModule,
- const FileEntry *File,
- SourceRange Range)
- : PreprocessingDirective(InclusionDirectiveKind, Range),
- InQuotes(InQuotes), Kind(Kind), ImportedModule(ImportedModule), File(File)
-{
- char *Memory
- = (char*)PPRec.Allocate(FileName.size() + 1, llvm::alignOf<char>());
+ const FileEntry *File, SourceRange Range)
+ : PreprocessingDirective(InclusionDirectiveKind, Range), InQuotes(InQuotes),
+ Kind(Kind), ImportedModule(ImportedModule), File(File) {
+ char *Memory = (char *)PPRec.Allocate(FileName.size() + 1, alignof(char));
memcpy(Memory, FileName.data(), FileName.size());
Memory[FileName.size()] = 0;
this->FileName = StringRef(Memory, FileName.size());
diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp
index 78179dd7988d..0f7473b8c1ff 100644
--- a/lib/Lex/Preprocessor.cpp
+++ b/lib/Lex/Preprocessor.cpp
@@ -43,18 +43,27 @@
#include "clang/Lex/PreprocessingRecord.h"
#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Lex/ScratchBuffer.h"
-#include "llvm/ADT/APFloat.h"
-#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/Capacity.h"
-#include "llvm/Support/ConvertUTF.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cassert>
+#include <memory>
+#include <string>
#include <utility>
+#include <vector>
+
using namespace clang;
-template class llvm::Registry<clang::PragmaHandler>;
+LLVM_INSTANTIATE_REGISTRY(PragmaHandlerRegistry)
//===----------------------------------------------------------------------===//
ExternalPreprocessorSource::~ExternalPreprocessorSource() { }
@@ -74,11 +83,12 @@ Preprocessor::Preprocessor(IntrusiveRefCntPtr<PreprocessorOptions> PPOpts,
IncrementalProcessing(false), TUKind(TUKind), CodeComplete(nullptr),
CodeCompletionFile(nullptr), CodeCompletionOffset(0),
LastTokenWasAt(false), ModuleImportExpectsIdentifier(false),
- CodeCompletionReached(0), MainFileDir(nullptr),
- SkipMainFilePreamble(0, true), CurPPLexer(nullptr), CurDirLookup(nullptr),
- CurLexerKind(CLK_Lexer), CurSubmodule(nullptr), Callbacks(nullptr),
- CurSubmoduleState(&NullSubmoduleState), MacroArgCache(nullptr),
- Record(nullptr), MIChainHead(nullptr), DeserialMIChainHead(nullptr) {
+ CodeCompletionReached(false), CodeCompletionII(nullptr),
+ MainFileDir(nullptr), SkipMainFilePreamble(0, true), CurPPLexer(nullptr),
+ CurDirLookup(nullptr), CurLexerKind(CLK_Lexer), CurSubmodule(nullptr),
+ Callbacks(nullptr), CurSubmoduleState(&NullSubmoduleState),
+ MacroArgCache(nullptr), Record(nullptr), MIChainHead(nullptr),
+ DeserialMIChainHead(nullptr) {
OwnsHeaderSearch = OwnsHeaders;
CounterValue = 0; // __COUNTER__ starts at 0.
@@ -480,7 +490,7 @@ void Preprocessor::CreateString(StringRef Str, Token &Tok,
}
Module *Preprocessor::getCurrentModule() {
- if (!getLangOpts().CompilingModule)
+ if (!getLangOpts().isCompilingModule())
return nullptr;
return getHeaderSearchInfo().lookupModule(getLangOpts().CurrentModule);
@@ -490,7 +500,6 @@ Module *Preprocessor::getCurrentModule() {
// Preprocessor Initialization Methods
//===----------------------------------------------------------------------===//
-
/// EnterMainSourceFile - Enter the specified FileID as the main source file,
/// which implicitly adds the builtin defines etc.
void Preprocessor::EnterMainSourceFile() {
@@ -618,6 +627,11 @@ static diag::kind getFutureCompatDiagKind(const IdentifierInfo &II,
"Keyword not known to come from a newer Standard or proposed Standard");
}
+void Preprocessor::updateOutOfDateIdentifier(IdentifierInfo &II) const {
+ assert(II.isOutOfDate() && "not out of date");
+ getExternalSource()->updateOutOfDateIdentifier(II);
+}
+
/// HandleIdentifier - This callback is invoked when the lexer reads an
/// identifier. This callback looks up the identifier in the map and/or
/// potentially macro expands it or turns it into a named token (like 'for').
@@ -642,7 +656,7 @@ bool Preprocessor::HandleIdentifier(Token &Identifier) {
if (&II == Ident__VA_ARGS__)
CurrentIsPoisoned = Ident__VA_ARGS__->isPoisoned();
- ExternalSource->updateOutOfDateIdentifier(II);
+ updateOutOfDateIdentifier(II);
Identifier.setKind(II.getTokenID());
if (&II == Ident__VA_ARGS__)
@@ -707,9 +721,12 @@ bool Preprocessor::HandleIdentifier(Token &Identifier) {
// Note that we do not treat 'import' as a contextual
// keyword when we're in a caching lexer, because caching lexers only get
// used in contexts where import declarations are disallowed.
- if (LastTokenWasAt && II.isModulesImport() && !InMacroArgs &&
- !DisableMacroExpansion &&
- (getLangOpts().Modules || getLangOpts().DebuggerSupport) &&
+ //
+ // Likewise if this is the C++ Modules TS import keyword.
+ if (((LastTokenWasAt && II.isModulesImport()) ||
+ Identifier.is(tok::kw_import)) &&
+ !InMacroArgs && !DisableMacroExpansion &&
+ (getLangOpts().Modules || getLangOpts().DebuggerSupport) &&
CurLexerKind != CLK_CachingLexer) {
ModuleImportLoc = Identifier.getLocation();
ModuleImportPath.clear();
@@ -744,10 +761,12 @@ void Preprocessor::Lex(Token &Result) {
}
} while (!ReturnedToken);
+ if (Result.is(tok::code_completion))
+ setCodeCompletionIdentifierInfo(Result.getIdentifierInfo());
+
LastTokenWasAt = Result.is(tok::at);
}
-
/// \brief Lex a token following the 'import' contextual keyword.
///
void Preprocessor::LexAfterModuleImport(Token &Result) {
@@ -774,7 +793,8 @@ void Preprocessor::LexAfterModuleImport(Token &Result) {
}
// If we're expecting a '.' or a ';', and we got a '.', then wait until we
- // see the next identifier.
+ // see the next identifier. (We can also see a '[[' that begins an
+ // attribute-specifier-seq here under the C++ Modules TS.)
if (!ModuleImportExpectsIdentifier && Result.getKind() == tok::period) {
ModuleImportExpectsIdentifier = true;
CurLexerKind = CLK_LexAfterModuleImport;
@@ -783,6 +803,23 @@ void Preprocessor::LexAfterModuleImport(Token &Result) {
// If we have a non-empty module path, load the named module.
if (!ModuleImportPath.empty()) {
+ // Under the Modules TS, the dot is just part of the module name, and not
+ // a real hierarachy separator. Flatten such module names now.
+ //
+ // FIXME: Is this the right level to be performing this transformation?
+ std::string FlatModuleName;
+ if (getLangOpts().ModulesTS) {
+ for (auto &Piece : ModuleImportPath) {
+ if (!FlatModuleName.empty())
+ FlatModuleName += ".";
+ FlatModuleName += Piece.first->getName();
+ }
+ SourceLocation FirstPathLoc = ModuleImportPath[0].second;
+ ModuleImportPath.clear();
+ ModuleImportPath.push_back(
+ std::make_pair(getIdentifierInfo(FlatModuleName), FirstPathLoc));
+ }
+
Module *Imported = nullptr;
if (getLangOpts().Modules) {
Imported = TheModuleLoader.loadModule(ModuleImportLoc,
diff --git a/lib/Lex/TokenConcatenation.cpp b/lib/Lex/TokenConcatenation.cpp
index 27b4eab1a28d..d1facd9c6879 100644
--- a/lib/Lex/TokenConcatenation.cpp
+++ b/lib/Lex/TokenConcatenation.cpp
@@ -232,7 +232,7 @@ bool TokenConcatenation::AvoidConcat(const Token &PrevPrevTok,
// it as an identifier.
if (!PrevTok.hasUDSuffix())
return false;
- // FALL THROUGH.
+ LLVM_FALLTHROUGH;
case tok::identifier: // id+id or id+number or id+L"foo".
// id+'.'... will not append.
if (Tok.is(tok::numeric_constant))
diff --git a/lib/Lex/TokenLexer.cpp b/lib/Lex/TokenLexer.cpp
index 994bae632aec..a53c8014ebaf 100644
--- a/lib/Lex/TokenLexer.cpp
+++ b/lib/Lex/TokenLexer.cpp
@@ -275,7 +275,7 @@ void TokenLexer::ExpandFunctionArguments() {
// If the arg token expanded into anything, append it.
if (ResultArgToks->isNot(tok::eof)) {
- unsigned FirstResult = ResultToks.size();
+ size_t FirstResult = ResultToks.size();
unsigned NumToks = MacroArgs::getArgLength(ResultArgToks);
ResultToks.append(ResultArgToks, ResultArgToks+NumToks);
@@ -289,8 +289,8 @@ void TokenLexer::ExpandFunctionArguments() {
// If the '##' came from expanding an argument, turn it into 'unknown'
// to avoid pasting.
- for (unsigned i = FirstResult, e = ResultToks.size(); i != e; ++i) {
- Token &Tok = ResultToks[i];
+ for (Token &Tok : llvm::make_range(ResultToks.begin() + FirstResult,
+ ResultToks.end())) {
if (Tok.is(tok::hashhash))
Tok.setKind(tok::unknown);
}
@@ -333,9 +333,8 @@ void TokenLexer::ExpandFunctionArguments() {
// If the '##' came from expanding an argument, turn it into 'unknown'
// to avoid pasting.
- for (unsigned i = ResultToks.size() - NumToks, e = ResultToks.size();
- i != e; ++i) {
- Token &Tok = ResultToks[i];
+ for (Token &Tok : llvm::make_range(ResultToks.end() - NumToks,
+ ResultToks.end())) {
if (Tok.is(tok::hashhash))
Tok.setKind(tok::unknown);
}
diff --git a/lib/Parse/ParseAST.cpp b/lib/Parse/ParseAST.cpp
index 1fb57a08c433..d018d4c08ed9 100644
--- a/lib/Parse/ParseAST.cpp
+++ b/lib/Parse/ParseAST.cpp
@@ -138,26 +138,18 @@ void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) {
S.getPreprocessor().EnterMainSourceFile();
P.Initialize();
- // C11 6.9p1 says translation units must have at least one top-level
- // declaration. C++ doesn't have this restriction. We also don't want to
- // complain if we have a precompiled header, although technically if the PCH
- // is empty we should still emit the (pedantic) diagnostic.
Parser::DeclGroupPtrTy ADecl;
ExternalASTSource *External = S.getASTContext().getExternalSource();
if (External)
External->StartTranslationUnit(Consumer);
- if (P.ParseTopLevelDecl(ADecl)) {
- if (!External && !S.getLangOpts().CPlusPlus)
- P.Diag(diag::ext_empty_translation_unit);
- } else {
- do {
- // If we got a null return and something *was* parsed, ignore it. This
- // is due to a top-level semicolon, an action override, or a parse error
- // skipping something.
- if (ADecl && !Consumer->HandleTopLevelDecl(ADecl.get()))
- return;
- } while (!P.ParseTopLevelDecl(ADecl));
+ for (bool AtEOF = P.ParseFirstTopLevelDecl(ADecl); !AtEOF;
+ AtEOF = P.ParseTopLevelDecl(ADecl)) {
+ // If we got a null return and something *was* parsed, ignore it. This
+ // is due to a top-level semicolon, an action override, or a parse error
+ // skipping something.
+ if (ADecl && !Consumer->HandleTopLevelDecl(ADecl.get()))
+ return;
}
// Process any TopLevelDecls generated by #pragma weak.
diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp
index 39fcc8270419..c52b61e7e983 100644
--- a/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/lib/Parse/ParseCXXInlineMethods.cpp
@@ -319,7 +319,8 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
// Introduce the parameter into scope.
bool HasUnparsed = Param->hasUnparsedDefaultArg();
Actions.ActOnDelayedCXXMethodParameter(getCurScope(), Param);
- if (CachedTokens *Toks = LM.DefaultArgs[I].Toks) {
+ std::unique_ptr<CachedTokens> Toks = std::move(LM.DefaultArgs[I].Toks);
+ if (Toks) {
// Mark the end of the default argument so that we know when to stop when
// we parse it later on.
Token LastDefaultArgToken = Toks->back();
@@ -377,9 +378,6 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
if (Tok.is(tok::eof) && Tok.getEofData() == Param)
ConsumeAnyToken();
-
- delete Toks;
- LM.DefaultArgs[I].Toks = nullptr;
} else if (HasUnparsed) {
assert(Param->hasInheritedDefaultArg());
FunctionDecl *Old = cast<FunctionDecl>(LM.Method)->getPreviousDecl();
@@ -832,22 +830,30 @@ bool Parser::ConsumeAndStoreFunctionPrologue(CachedTokens &Toks) {
}
}
- if (Tok.isOneOf(tok::identifier, tok::kw_template)) {
+ if (Tok.is(tok::identifier)) {
Toks.push_back(Tok);
ConsumeToken();
- } else if (Tok.is(tok::code_completion)) {
- Toks.push_back(Tok);
- ConsumeCodeCompletionToken();
- // Consume the rest of the initializers permissively.
- // FIXME: We should be able to perform code-completion here even if
- // there isn't a subsequent '{' token.
- MightBeTemplateArgument = true;
- break;
} else {
break;
}
} while (Tok.is(tok::coloncolon));
+ if (Tok.is(tok::code_completion)) {
+ Toks.push_back(Tok);
+ ConsumeCodeCompletionToken();
+ if (Tok.isOneOf(tok::identifier, tok::coloncolon, tok::kw_decltype)) {
+ // Could be the start of another member initializer (the ',' has not
+ // been written yet)
+ continue;
+ }
+ }
+
+ if (Tok.is(tok::comma)) {
+ // The initialization is missing, we'll diagnose it later.
+ Toks.push_back(Tok);
+ ConsumeToken();
+ continue;
+ }
if (Tok.is(tok::less))
MightBeTemplateArgument = true;
@@ -888,6 +894,26 @@ bool Parser::ConsumeAndStoreFunctionPrologue(CachedTokens &Toks) {
// means the initializer is malformed; we'll diagnose it later.
if (!getLangOpts().CPlusPlus11)
return false;
+
+ const Token &PreviousToken = Toks[Toks.size() - 2];
+ if (!MightBeTemplateArgument &&
+ !PreviousToken.isOneOf(tok::identifier, tok::greater,
+ tok::greatergreater)) {
+ // If the opening brace is not preceded by one of these tokens, we are
+ // missing the mem-initializer-id. In order to recover better, we need
+ // to use heuristics to determine if this '{' is most likely the
+ // begining of a brace-init-list or the function body.
+ // Check the token after the corresponding '}'.
+ TentativeParsingAction PA(*this);
+ if (SkipUntil(tok::r_brace) &&
+ !Tok.isOneOf(tok::comma, tok::ellipsis, tok::l_brace)) {
+ // Consider there was a malformed initializer and this is the start
+ // of the function body. We'll diagnose it later.
+ PA.Revert();
+ return false;
+ }
+ PA.Revert();
+ }
}
// Grab the initializer (or the subexpression of the template argument).
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 45e1c3e465ce..ad4005747310 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -25,6 +25,7 @@
#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"
@@ -301,10 +302,10 @@ unsigned Parser::ParseAttributeArgsCommon(
// Parse the non-empty comma-separated list of expressions.
do {
- std::unique_ptr<EnterExpressionEvaluationContext> Unevaluated;
- if (attributeParsedArgsUnevaluated(*AttrName))
- Unevaluated.reset(
- new EnterExpressionEvaluationContext(Actions, Sema::Unevaluated));
+ bool ShouldEnter = attributeParsedArgsUnevaluated(*AttrName);
+ EnterExpressionEvaluationContext Unevaluated(
+ Actions, Sema::Unevaluated, /*LambdaContextDecl=*/nullptr,
+ /*IsDecltype=*/false, ShouldEnter);
ExprResult ArgExpr(
Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()));
@@ -366,13 +367,13 @@ void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName,
// These may refer to the function arguments, but need to be parsed early to
// participate in determining whether it's a redeclaration.
- std::unique_ptr<ParseScope> PrototypeScope;
+ llvm::Optional<ParseScope> PrototypeScope;
if (normalizeAttrName(AttrName->getName()) == "enable_if" &&
D && D->isFunctionDeclarator()) {
DeclaratorChunk::FunctionTypeInfo FTI = D->getFunctionTypeInfo();
- PrototypeScope.reset(new ParseScope(this, Scope::FunctionPrototypeScope |
- Scope::FunctionDeclarationScope |
- Scope::DeclScope));
+ PrototypeScope.emplace(this, Scope::FunctionPrototypeScope |
+ Scope::FunctionDeclarationScope |
+ Scope::DeclScope);
for (unsigned i = 0; i != FTI.NumParams; ++i) {
ParmVarDecl *Param = cast<ParmVarDecl>(FTI.Params[i].Param);
Actions.ActOnReenterCXXMethodParameter(getCurScope(), Param);
@@ -605,6 +606,7 @@ void Parser::ParseMicrosoftTypeAttributes(ParsedAttributes &attrs) {
case tok::kw___fastcall:
case tok::kw___stdcall:
case tok::kw___thiscall:
+ case tok::kw___regcall:
case tok::kw___cdecl:
case tok::kw___vectorcall:
case tok::kw___ptr64:
@@ -1407,39 +1409,53 @@ void Parser::DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs) {
<< attrs.Range;
}
-void Parser::ProhibitCXX11Attributes(ParsedAttributesWithRange &attrs) {
- AttributeList *AttrList = attrs.getList();
- while (AttrList) {
- if (AttrList->isCXX11Attribute()) {
- Diag(AttrList->getLoc(), diag::err_attribute_not_type_attr)
- << AttrList->getName();
- AttrList->setInvalid();
+void Parser::ProhibitCXX11Attributes(ParsedAttributesWithRange &Attrs,
+ unsigned DiagID) {
+ for (AttributeList *Attr = Attrs.getList(); Attr; Attr = Attr->getNext()) {
+ if (!Attr->isCXX11Attribute())
+ continue;
+ if (Attr->getKind() == AttributeList::UnknownAttribute)
+ Diag(Attr->getLoc(), diag::warn_unknown_attribute_ignored)
+ << Attr->getName();
+ else {
+ Diag(Attr->getLoc(), DiagID)
+ << Attr->getName();
+ Attr->setInvalid();
}
- AttrList = AttrList->getNext();
}
}
+// Usually, `__attribute__((attrib)) class Foo {} var` means that attribute
+// applies to var, not the type Foo.
// As an exception to the rule, __declspec(align(...)) before the
// class-key affects the type instead of the variable.
-void Parser::handleDeclspecAlignBeforeClassKey(ParsedAttributesWithRange &Attrs,
- DeclSpec &DS,
- Sema::TagUseKind TUK) {
+// Also, Microsoft-style [attributes] seem to affect the type instead of the
+// variable.
+// This function moves attributes that should apply to the type off DS to Attrs.
+void Parser::stripTypeAttributesOffDeclSpec(ParsedAttributesWithRange &Attrs,
+ DeclSpec &DS,
+ Sema::TagUseKind TUK) {
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();
- // We only consider attributes using the appropriate '__declspec' spelling.
- // This behavior doesn't extend to any other spellings.
- if (AL->getKind() == AttributeList::AT_Aligned &&
- AL->isDeclspecAttribute()) {
+ if ((AL->getKind() == AttributeList::AT_Aligned &&
+ AL->isDeclspecAttribute()) ||
+ AL->isMicrosoftAttribute()) {
// Stitch the attribute into the tag's attribute list.
- AL->setNext(nullptr);
- Attrs.add(AL);
+ if (TypeAttrTail)
+ TypeAttrTail->setNext(AL);
+ else
+ TypeAttrHead = AL;
+ TypeAttrTail = AL;
+ TypeAttrTail->setNext(nullptr);
// Remove the attribute from the variable's attribute list.
if (Prev) {
@@ -1457,6 +1473,12 @@ void Parser::handleDeclspecAlignBeforeClassKey(ParsedAttributesWithRange &Attrs,
AL = Next;
}
+
+ // 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);
}
/// ParseDeclaration - Parse a full 'declaration', which consists of
@@ -1484,7 +1506,6 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context,
ObjCDeclContextSwitch ObjCDC(*this);
Decl *SingleDecl = nullptr;
- Decl *OwnedType = nullptr;
switch (Tok.getKind()) {
case tok::kw_template:
case tok::kw_export:
@@ -1504,9 +1525,8 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context,
ProhibitAttributes(attrs);
return ParseNamespace(Context, DeclEnd);
case tok::kw_using:
- SingleDecl = ParseUsingDirectiveOrDeclaration(Context, ParsedTemplateInfo(),
- DeclEnd, attrs, &OwnedType);
- break;
+ return ParseUsingDirectiveOrDeclaration(Context, ParsedTemplateInfo(),
+ DeclEnd, attrs);
case tok::kw_static_assert:
case tok::kw__Static_assert:
ProhibitAttributes(attrs);
@@ -1517,9 +1537,8 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context,
}
// This routine returns a DeclGroup, if the thing we parsed only contains a
- // single decl, convert it now. Alias declarations can also declare a type;
- // include that too if it is present.
- return Actions.ConvertDeclToDeclGroup(SingleDecl, OwnedType);
+ // single decl, convert it now.
+ return Actions.ConvertDeclToDeclGroup(SingleDecl);
}
/// simple-declaration: [C99 6.7: declaration] [C++ 7p1: dcl.dcl]
@@ -2717,7 +2736,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// Reject C++11 attributes that appertain to decl specifiers as
// we don't support any C++11 attributes that appertain to decl
// specifiers. This also conforms to what g++ 4.8 is doing.
- ProhibitCXX11Attributes(attrs);
+ ProhibitCXX11Attributes(attrs, diag::err_attribute_not_type_attr);
DS.takeAttributesFrom(attrs);
}
@@ -3117,6 +3136,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
case tok::kw___stdcall:
case tok::kw___fastcall:
case tok::kw___thiscall:
+ case tok::kw___regcall:
case tok::kw___vectorcall:
ParseMicrosoftTypeAttributes(DS.getAttributes());
continue;
@@ -4067,7 +4087,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
return;
}
- handleDeclspecAlignBeforeClassKey(attrs, DS, TUK);
+ stripTypeAttributesOffDeclSpec(attrs, DS, TUK);
Sema::SkipBodyInfo SkipBody;
if (!Name && TUK == Sema::TUK_Definition && Tok.is(tok::l_brace) &&
@@ -4169,7 +4189,7 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) {
// C does not allow an empty enumerator-list, C++ does [dcl.enum].
if (Tok.is(tok::r_brace) && !getLangOpts().CPlusPlus)
- Diag(Tok, diag::error_empty_enum);
+ Diag(Tok, diag::err_empty_enum);
SmallVector<Decl *, 32> EnumConstantDecls;
SmallVector<SuppressAccessChecks, 32> EnumAvailabilityDiags;
@@ -4224,7 +4244,7 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) {
if (Tok.is(tok::identifier)) {
// We're missing a comma between enumerators.
- SourceLocation Loc = PP.getLocForEndOfToken(PrevTokLocation);
+ SourceLocation Loc = getEndOfPreviousToken();
Diag(Loc, diag::err_enumerator_list_missing_comma)
<< FixItHint::CreateInsertion(Loc, ", ");
continue;
@@ -4434,6 +4454,7 @@ bool Parser::isTypeSpecifierQualifier() {
case tok::kw___stdcall:
case tok::kw___fastcall:
case tok::kw___thiscall:
+ case tok::kw___regcall:
case tok::kw___vectorcall:
case tok::kw___w64:
case tok::kw___ptr64:
@@ -4618,6 +4639,7 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
case tok::kw___stdcall:
case tok::kw___fastcall:
case tok::kw___thiscall:
+ case tok::kw___regcall:
case tok::kw___vectorcall:
case tok::kw___w64:
case tok::kw___sptr:
@@ -4856,6 +4878,7 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, unsigned AttrReqs,
case tok::kw___stdcall:
case tok::kw___fastcall:
case tok::kw___thiscall:
+ case tok::kw___regcall:
case tok::kw___vectorcall:
if (AttrReqs & AR_DeclspecAttributesParsed) {
ParseMicrosoftTypeAttributes(DS.getAttributes());
@@ -5200,12 +5223,22 @@ static SourceLocation getMissingDeclaratorIdLoc(Declarator &D,
/// '~' class-name
/// template-id
///
+/// C++17 adds the following, which we also handle here:
+///
+/// simple-declaration:
+/// <decl-spec> '[' identifier-list ']' brace-or-equal-initializer ';'
+///
/// Note, any additional constructs added here may need corresponding changes
/// in isConstructorDeclarator.
void Parser::ParseDirectDeclarator(Declarator &D) {
DeclaratorScopeObj DeclScopeObj(*this, D.getCXXScopeSpec());
if (getLangOpts().CPlusPlus && D.mayHaveIdentifier()) {
+ // This might be a C++17 structured binding.
+ if (Tok.is(tok::l_square) && !D.mayOmitIdentifier() &&
+ D.getCXXScopeSpec().isEmpty())
+ return ParseDecompositionDeclarator(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.
@@ -5228,6 +5261,14 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
// Change the declaration context for name lookup, until this function
// is exited (and the declarator has been parsed).
DeclScopeObj.EnterDeclaratorScope();
+ else if (getObjCDeclContext()) {
+ // Ensure that we don't interpret the next token as an identifier when
+ // dealing with declarations in an Objective-C container.
+ D.SetIdentifier(nullptr, Tok.getLocation());
+ D.setInvalidType(true);
+ ConsumeToken();
+ goto PastIdentifier;
+ }
}
// C++0x [dcl.fct]p14:
@@ -5435,6 +5476,70 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
}
}
+void Parser::ParseDecompositionDeclarator(Declarator &D) {
+ assert(Tok.is(tok::l_square));
+
+ // If this doesn't look like a structured binding, maybe it's a misplaced
+ // array declarator.
+ // FIXME: Consume the l_square first so we don't need extra lookahead for
+ // this.
+ if (!(NextToken().is(tok::identifier) &&
+ GetLookAheadToken(2).isOneOf(tok::comma, tok::r_square)) &&
+ !(NextToken().is(tok::r_square) &&
+ GetLookAheadToken(2).isOneOf(tok::equal, tok::l_brace)))
+ return ParseMisplacedBracketDeclarator(D);
+
+ BalancedDelimiterTracker T(*this, tok::l_square);
+ T.consumeOpen();
+
+ SmallVector<DecompositionDeclarator::Binding, 32> Bindings;
+ while (Tok.isNot(tok::r_square)) {
+ if (!Bindings.empty()) {
+ if (Tok.is(tok::comma))
+ ConsumeToken();
+ else {
+ if (Tok.is(tok::identifier)) {
+ SourceLocation EndLoc = getEndOfPreviousToken();
+ Diag(EndLoc, diag::err_expected)
+ << tok::comma << FixItHint::CreateInsertion(EndLoc, ",");
+ } else {
+ Diag(Tok, diag::err_expected_comma_or_rsquare);
+ }
+
+ SkipUntil(tok::r_square, tok::comma, tok::identifier,
+ StopAtSemi | StopBeforeMatch);
+ if (Tok.is(tok::comma))
+ ConsumeToken();
+ else if (Tok.isNot(tok::identifier))
+ break;
+ }
+ }
+
+ if (Tok.isNot(tok::identifier)) {
+ Diag(Tok, diag::err_expected) << tok::identifier;
+ break;
+ }
+
+ Bindings.push_back({Tok.getIdentifierInfo(), Tok.getLocation()});
+ ConsumeToken();
+ }
+
+ if (Tok.isNot(tok::r_square))
+ // We've already diagnosed a problem here.
+ T.skipToEnd();
+ else {
+ // C++17 does not allow the identifier-list in a structured binding
+ // to be empty.
+ if (Bindings.empty())
+ Diag(Tok.getLocation(), diag::ext_decomp_decl_empty);
+
+ T.consumeClose();
+ }
+
+ return D.setDecompositionBindings(T.getOpenLocation(), Bindings,
+ T.getCloseLocation());
+}
+
/// ParseParenDeclarator - We parsed the declarator D up to a paren. This is
/// only called before the identifier, so these are most likely just grouping
/// parens for precedence. If we find that these are actually function
@@ -5719,6 +5824,21 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
}
}
+ // Collect non-parameter declarations from the prototype if this is a function
+ // declaration. They will be moved into the scope of the function. Only do
+ // this in C and not C++, where the decls will continue to live in the
+ // surrounding context.
+ SmallVector<NamedDecl *, 0> DeclsInPrototype;
+ if (getCurScope()->getFlags() & Scope::FunctionDeclarationScope &&
+ !getLangOpts().CPlusPlus) {
+ for (Decl *D : getCurScope()->decls()) {
+ NamedDecl *ND = dyn_cast<NamedDecl>(D);
+ if (!ND || isa<ParmVarDecl>(ND))
+ continue;
+ DeclsInPrototype.push_back(ND);
+ }
+ }
+
// Remember that we parsed a function type, and remember the attributes.
D.AddTypeInfo(DeclaratorChunk::getFunction(HasProto,
IsAmbiguous,
@@ -5738,6 +5858,7 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
NoexceptExpr.isUsable() ?
NoexceptExpr.get() : nullptr,
ExceptionSpecTokens,
+ DeclsInPrototype,
StartLoc, LocalEndLoc, D,
TrailingReturnType),
FnAttrs, EndLoc);
@@ -5783,7 +5904,8 @@ bool Parser::isFunctionDeclaratorIdentifierList() {
// To handle this, we check to see if the token after the first
// identifier is a "," or ")". Only then do we parse it as an
// identifier list.
- && (NextToken().is(tok::comma) || NextToken().is(tok::r_paren));
+ && (!Tok.is(tok::eof) &&
+ (NextToken().is(tok::comma) || NextToken().is(tok::r_paren)));
}
/// ParseFunctionDeclaratorIdentifierList - While parsing a function declarator
@@ -5921,7 +6043,7 @@ void Parser::ParseParameterDeclarationClause(
// DefArgToks is used when the parsing of default arguments needs
// to be delayed.
- CachedTokens *DefArgToks = nullptr;
+ std::unique_ptr<CachedTokens> DefArgToks;
// If no parameter was specified, verify that *something* was specified,
// otherwise we have a missing type and identifier.
@@ -5957,13 +6079,11 @@ void Parser::ParseParameterDeclarationClause(
// 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.
- // FIXME: Can we use a smart pointer for Toks?
- DefArgToks = new CachedTokens;
+ DefArgToks.reset(new CachedTokens);
SourceLocation ArgStartLoc = NextToken().getLocation();
if (!ConsumeAndStoreInitializer(*DefArgToks, CIK_DefaultArgument)) {
- delete DefArgToks;
- DefArgToks = nullptr;
+ DefArgToks.reset();
Actions.ActOnParamDefaultArgumentError(Param, EqualLoc);
} else {
Actions.ActOnParamUnparsedDefaultArgument(Param, EqualLoc,
@@ -5999,7 +6119,7 @@ void Parser::ParseParameterDeclarationClause(
ParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII,
ParmDeclarator.getIdentifierLoc(),
- Param, DefArgToks));
+ Param, std::move(DefArgToks)));
}
if (TryConsumeToken(tok::ellipsis, EllipsisLoc)) {
@@ -6149,8 +6269,7 @@ void Parser::ParseBracketDeclarator(Declarator &D) {
T.consumeClose();
- ParsedAttributes attrs(AttrFactory);
- MaybeParseCXX11Attributes(attrs);
+ MaybeParseCXX11Attributes(DS.getAttributes());
// Remember that we parsed a array type, and remember its features.
D.AddTypeInfo(DeclaratorChunk::getArray(DS.getTypeQualifiers(),
@@ -6158,7 +6277,7 @@ void Parser::ParseBracketDeclarator(Declarator &D) {
NumElements.get(),
T.getOpenLocation(),
T.getCloseLocation()),
- attrs, T.getCloseLocation());
+ DS.getAttributes(), T.getCloseLocation());
}
/// Diagnose brackets before an identifier.
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 6436e3dfc763..4002b09d2bc4 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -217,7 +217,6 @@ void Parser::ParseInnerNamespace(std::vector<SourceLocation> &IdentLoc,
Tok.isNot(tok::eof)) {
ParsedAttributesWithRange attrs(AttrFactory);
MaybeParseCXX11Attributes(attrs);
- MaybeParseMicrosoftAttributes(attrs);
ParseExternalDeclaration(attrs);
}
@@ -310,7 +309,6 @@ Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, unsigned Context) {
ParsedAttributesWithRange attrs(AttrFactory);
MaybeParseCXX11Attributes(attrs);
- MaybeParseMicrosoftAttributes(attrs);
if (Tok.isNot(tok::l_brace)) {
// Reset the source range in DS, as the leading "extern"
@@ -361,7 +359,6 @@ Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, unsigned Context) {
default:
ParsedAttributesWithRange attrs(AttrFactory);
MaybeParseCXX11Attributes(attrs);
- MaybeParseMicrosoftAttributes(attrs);
ParseExternalDeclaration(attrs);
continue;
}
@@ -375,13 +372,60 @@ Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, unsigned Context) {
: nullptr;
}
+/// Parse a C++ Modules TS export-declaration.
+///
+/// export-declaration:
+/// 'export' declaration
+/// 'export' '{' declaration-seq[opt] '}'
+///
+Decl *Parser::ParseExportDeclaration() {
+ assert(Tok.is(tok::kw_export));
+ SourceLocation ExportLoc = ConsumeToken();
+
+ ParseScope ExportScope(this, Scope::DeclScope);
+ Decl *ExportDecl = Actions.ActOnStartExportDecl(
+ getCurScope(), ExportLoc,
+ Tok.is(tok::l_brace) ? Tok.getLocation() : SourceLocation());
+
+ if (Tok.isNot(tok::l_brace)) {
+ // FIXME: Factor out a ParseExternalDeclarationWithAttrs.
+ ParsedAttributesWithRange Attrs(AttrFactory);
+ MaybeParseCXX11Attributes(Attrs);
+ MaybeParseMicrosoftAttributes(Attrs);
+ ParseExternalDeclaration(Attrs);
+ return Actions.ActOnFinishExportDecl(getCurScope(), ExportDecl,
+ SourceLocation());
+ }
+
+ BalancedDelimiterTracker T(*this, tok::l_brace);
+ T.consumeOpen();
+
+ // The Modules TS draft says "An export-declaration shall declare at least one
+ // entity", but the intent is that it shall contain at least one declaration.
+ if (Tok.is(tok::r_brace))
+ Diag(ExportLoc, diag::err_export_empty)
+ << SourceRange(ExportLoc, Tok.getLocation());
+
+ while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) &&
+ Tok.isNot(tok::eof)) {
+ ParsedAttributesWithRange Attrs(AttrFactory);
+ MaybeParseCXX11Attributes(Attrs);
+ MaybeParseMicrosoftAttributes(Attrs);
+ ParseExternalDeclaration(Attrs);
+ }
+
+ T.consumeClose();
+ return Actions.ActOnFinishExportDecl(getCurScope(), ExportDecl,
+ T.getCloseLocation());
+}
+
/// ParseUsingDirectiveOrDeclaration - Parse C++ using using-declaration or
/// using-directive. Assumes that current token is 'using'.
-Decl *Parser::ParseUsingDirectiveOrDeclaration(unsigned Context,
+Parser::DeclGroupPtrTy
+Parser::ParseUsingDirectiveOrDeclaration(unsigned Context,
const ParsedTemplateInfo &TemplateInfo,
- SourceLocation &DeclEnd,
- ParsedAttributesWithRange &attrs,
- Decl **OwnedType) {
+ SourceLocation &DeclEnd,
+ ParsedAttributesWithRange &attrs) {
assert(Tok.is(tok::kw_using) && "Not using token");
ObjCDeclContextSwitch ObjCDC(*this);
@@ -403,7 +447,8 @@ Decl *Parser::ParseUsingDirectiveOrDeclaration(unsigned Context,
<< 0 /* directive */ << R << FixItHint::CreateRemoval(R);
}
- return ParseUsingDirective(Context, UsingLoc, DeclEnd, attrs);
+ Decl *UsingDir = ParseUsingDirective(Context, UsingLoc, DeclEnd, attrs);
+ return Actions.ConvertDeclToDeclGroup(UsingDir);
}
// Otherwise, it must be a using-declaration or an alias-declaration.
@@ -412,7 +457,7 @@ Decl *Parser::ParseUsingDirectiveOrDeclaration(unsigned Context,
ProhibitAttributes(attrs);
return ParseUsingDeclaration(Context, TemplateInfo, UsingLoc, DeclEnd,
- AS_none, OwnedType);
+ AS_none);
}
/// ParseUsingDirective - Parse C++ using-directive, assumes
@@ -478,58 +523,31 @@ Decl *Parser::ParseUsingDirective(unsigned Context,
IdentLoc, NamespcName, attrs.getList());
}
-/// ParseUsingDeclaration - Parse C++ using-declaration or alias-declaration.
-/// Assumes that 'using' was already seen.
-///
-/// using-declaration: [C++ 7.3.p3: namespace.udecl]
-/// 'using' 'typename'[opt] ::[opt] nested-name-specifier
-/// unqualified-id
-/// 'using' :: unqualified-id
+/// Parse a using-declarator (or the identifier in a C++11 alias-declaration).
///
-/// alias-declaration: C++11 [dcl.dcl]p1
-/// 'using' identifier attribute-specifier-seq[opt] = type-id ;
+/// using-declarator:
+/// 'typename'[opt] nested-name-specifier unqualified-id
///
-Decl *Parser::ParseUsingDeclaration(unsigned Context,
- const ParsedTemplateInfo &TemplateInfo,
- SourceLocation UsingLoc,
- SourceLocation &DeclEnd,
- AccessSpecifier AS,
- Decl **OwnedType) {
- CXXScopeSpec SS;
- SourceLocation TypenameLoc;
- bool HasTypenameKeyword = false;
-
- // Check for misplaced attributes before the identifier in an
- // alias-declaration.
- ParsedAttributesWithRange MisplacedAttrs(AttrFactory);
- MaybeParseCXX11Attributes(MisplacedAttrs);
+bool Parser::ParseUsingDeclarator(unsigned Context, UsingDeclarator &D) {
+ D.clear();
// Ignore optional 'typename'.
// FIXME: This is wrong; we should parse this as a typename-specifier.
- if (TryConsumeToken(tok::kw_typename, TypenameLoc))
- HasTypenameKeyword = true;
+ TryConsumeToken(tok::kw_typename, D.TypenameLoc);
if (Tok.is(tok::kw___super)) {
Diag(Tok.getLocation(), diag::err_super_in_using_declaration);
- SkipUntil(tok::semi);
- return nullptr;
+ return true;
}
// Parse nested-name-specifier.
IdentifierInfo *LastII = nullptr;
- ParseOptionalCXXScopeSpecifier(SS, nullptr, /*EnteringContext=*/false,
+ ParseOptionalCXXScopeSpecifier(D.SS, nullptr, /*EnteringContext=*/false,
/*MayBePseudoDtor=*/nullptr,
/*IsTypename=*/false,
/*LastII=*/&LastII);
-
- // Check nested-name specifier.
- if (SS.isInvalid()) {
- SkipUntil(tok::semi);
- return nullptr;
- }
-
- SourceLocation TemplateKWLoc;
- UnqualifiedId Name;
+ if (D.SS.isInvalid())
+ return true;
// Parse the unqualified-id. We allow parsing of both constructor and
// destructor names and allow the action module to diagnose any semantic
@@ -542,32 +560,74 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context,
// nested-name-specifier, the name is [...] considered to name the
// constructor.
if (getLangOpts().CPlusPlus11 && Context == Declarator::MemberContext &&
- Tok.is(tok::identifier) && NextToken().is(tok::semi) &&
- SS.isNotEmpty() && LastII == Tok.getIdentifierInfo() &&
- !SS.getScopeRep()->getAsNamespace() &&
- !SS.getScopeRep()->getAsNamespaceAlias()) {
+ Tok.is(tok::identifier) &&
+ (NextToken().is(tok::semi) || NextToken().is(tok::comma) ||
+ NextToken().is(tok::ellipsis)) &&
+ D.SS.isNotEmpty() && LastII == Tok.getIdentifierInfo() &&
+ !D.SS.getScopeRep()->getAsNamespace() &&
+ !D.SS.getScopeRep()->getAsNamespaceAlias()) {
SourceLocation IdLoc = ConsumeToken();
- ParsedType Type = Actions.getInheritingConstructorName(SS, IdLoc, *LastII);
- Name.setConstructorName(Type, IdLoc, IdLoc);
- } else if (ParseUnqualifiedId(
- SS, /*EnteringContext=*/false,
- /*AllowDestructorName=*/true,
- /*AllowConstructorName=*/!(Tok.is(tok::identifier) &&
- NextToken().is(tok::equal)),
- nullptr, TemplateKWLoc, Name)) {
- SkipUntil(tok::semi);
- return nullptr;
+ ParsedType Type =
+ Actions.getInheritingConstructorName(D.SS, IdLoc, *LastII);
+ D.Name.setConstructorName(Type, IdLoc, IdLoc);
+ } else {
+ if (ParseUnqualifiedId(
+ D.SS, /*EnteringContext=*/false,
+ /*AllowDestructorName=*/true,
+ /*AllowConstructorName=*/!(Tok.is(tok::identifier) &&
+ NextToken().is(tok::equal)),
+ nullptr, D.TemplateKWLoc, D.Name))
+ return true;
}
+ if (TryConsumeToken(tok::ellipsis, D.EllipsisLoc))
+ Diag(Tok.getLocation(), getLangOpts().CPlusPlus1z ?
+ diag::warn_cxx1z_compat_using_declaration_pack :
+ diag::ext_using_declaration_pack);
+
+ return false;
+}
+
+/// ParseUsingDeclaration - Parse C++ using-declaration or alias-declaration.
+/// Assumes that 'using' was already seen.
+///
+/// using-declaration: [C++ 7.3.p3: namespace.udecl]
+/// 'using' using-declarator-list[opt] ;
+///
+/// using-declarator-list: [C++1z]
+/// using-declarator '...'[opt]
+/// using-declarator-list ',' using-declarator '...'[opt]
+///
+/// using-declarator-list: [C++98-14]
+/// using-declarator
+///
+/// alias-declaration: C++11 [dcl.dcl]p1
+/// 'using' identifier attribute-specifier-seq[opt] = type-id ;
+///
+Parser::DeclGroupPtrTy
+Parser::ParseUsingDeclaration(unsigned Context,
+ const ParsedTemplateInfo &TemplateInfo,
+ SourceLocation UsingLoc, SourceLocation &DeclEnd,
+ AccessSpecifier AS) {
+ // Check for misplaced attributes before the identifier in an
+ // alias-declaration.
+ ParsedAttributesWithRange MisplacedAttrs(AttrFactory);
+ MaybeParseCXX11Attributes(MisplacedAttrs);
+
+ UsingDeclarator D;
+ bool InvalidDeclarator = ParseUsingDeclarator(Context, D);
+
ParsedAttributesWithRange Attrs(AttrFactory);
MaybeParseGNUAttributes(Attrs);
MaybeParseCXX11Attributes(Attrs);
// Maybe this is an alias-declaration.
- TypeResult TypeAlias;
- bool IsAliasDecl = Tok.is(tok::equal);
- Decl *DeclFromDeclSpec = nullptr;
- if (IsAliasDecl) {
+ if (Tok.is(tok::equal)) {
+ if (InvalidDeclarator) {
+ SkipUntil(tok::semi);
+ return nullptr;
+ }
+
// If we had any misplaced attributes from earlier, this is where they
// should have been written.
if (MisplacedAttrs.Range.isValid()) {
@@ -579,109 +639,156 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context,
Attrs.takeAllFrom(MisplacedAttrs);
}
- ConsumeToken();
+ Decl *DeclFromDeclSpec = nullptr;
+ Decl *AD = ParseAliasDeclarationAfterDeclarator(
+ TemplateInfo, UsingLoc, D, DeclEnd, AS, Attrs, &DeclFromDeclSpec);
+ return Actions.ConvertDeclToDeclGroup(AD, DeclFromDeclSpec);
+ }
- Diag(Tok.getLocation(), getLangOpts().CPlusPlus11 ?
- diag::warn_cxx98_compat_alias_declaration :
- diag::ext_alias_declaration);
-
- // Type alias templates cannot be specialized.
- int SpecKind = -1;
- if (TemplateInfo.Kind == ParsedTemplateInfo::Template &&
- Name.getKind() == UnqualifiedId::IK_TemplateId)
- SpecKind = 0;
- if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitSpecialization)
- SpecKind = 1;
- if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation)
- SpecKind = 2;
- if (SpecKind != -1) {
- SourceRange Range;
- if (SpecKind == 0)
- Range = SourceRange(Name.TemplateId->LAngleLoc,
- Name.TemplateId->RAngleLoc);
- else
- Range = TemplateInfo.getSourceRange();
- Diag(Range.getBegin(), diag::err_alias_declaration_specialization)
- << SpecKind << Range;
- SkipUntil(tok::semi);
- return nullptr;
- }
+ // C++11 attributes are not allowed on a using-declaration, but GNU ones
+ // are.
+ ProhibitAttributes(MisplacedAttrs);
+ ProhibitAttributes(Attrs);
- // Name must be an identifier.
- if (Name.getKind() != UnqualifiedId::IK_Identifier) {
- Diag(Name.StartLocation, diag::err_alias_declaration_not_identifier);
- // No removal fixit: can't recover from this.
- SkipUntil(tok::semi);
- return nullptr;
- } else if (HasTypenameKeyword)
- Diag(TypenameLoc, diag::err_alias_declaration_not_identifier)
- << FixItHint::CreateRemoval(SourceRange(TypenameLoc,
- SS.isNotEmpty() ? SS.getEndLoc() : TypenameLoc));
- else if (SS.isNotEmpty())
- Diag(SS.getBeginLoc(), diag::err_alias_declaration_not_identifier)
- << FixItHint::CreateRemoval(SS.getRange());
+ // Diagnose an attempt to declare a templated using-declaration.
+ // In C++11, alias-declarations can be templates:
+ // template <...> using id = type;
+ if (TemplateInfo.Kind) {
+ SourceRange R = TemplateInfo.getSourceRange();
+ Diag(UsingLoc, diag::err_templated_using_directive_declaration)
+ << 1 /* declaration */ << R << FixItHint::CreateRemoval(R);
- TypeAlias = ParseTypeName(nullptr, TemplateInfo.Kind
- ? Declarator::AliasTemplateContext
- : Declarator::AliasDeclContext,
- AS, &DeclFromDeclSpec, &Attrs);
- if (OwnedType)
- *OwnedType = DeclFromDeclSpec;
- } else {
- // C++11 attributes are not allowed on a using-declaration, but GNU ones
- // are.
- ProhibitAttributes(MisplacedAttrs);
- ProhibitAttributes(Attrs);
+ // Unfortunately, we have to bail out instead of recovering by
+ // ignoring the parameters, just in case the nested name specifier
+ // depends on the parameters.
+ return nullptr;
+ }
+ SmallVector<Decl *, 8> DeclsInGroup;
+ while (true) {
// Parse (optional) attributes (most likely GNU strong-using extension).
MaybeParseGNUAttributes(Attrs);
+
+ if (InvalidDeclarator)
+ SkipUntil(tok::comma, tok::semi, StopBeforeMatch);
+ else {
+ // "typename" keyword is allowed for identifiers only,
+ // because it may be a type definition.
+ if (D.TypenameLoc.isValid() &&
+ D.Name.getKind() != UnqualifiedId::IK_Identifier) {
+ Diag(D.Name.getSourceRange().getBegin(),
+ diag::err_typename_identifiers_only)
+ << FixItHint::CreateRemoval(SourceRange(D.TypenameLoc));
+ // Proceed parsing, but discard the typename keyword.
+ D.TypenameLoc = SourceLocation();
+ }
+
+ Decl *UD = Actions.ActOnUsingDeclaration(getCurScope(), AS, UsingLoc,
+ D.TypenameLoc, D.SS, D.Name,
+ D.EllipsisLoc, Attrs.getList());
+ if (UD)
+ DeclsInGroup.push_back(UD);
+ }
+
+ if (!TryConsumeToken(tok::comma))
+ break;
+
+ // Parse another using-declarator.
+ Attrs.clear();
+ InvalidDeclarator = ParseUsingDeclarator(Context, D);
}
+ if (DeclsInGroup.size() > 1)
+ Diag(Tok.getLocation(), getLangOpts().CPlusPlus1z ?
+ diag::warn_cxx1z_compat_multi_using_declaration :
+ diag::ext_multi_using_declaration);
+
// Eat ';'.
DeclEnd = Tok.getLocation();
if (ExpectAndConsume(tok::semi, diag::err_expected_after,
!Attrs.empty() ? "attributes list"
- : IsAliasDecl ? "alias declaration"
- : "using declaration"))
+ : "using declaration"))
SkipUntil(tok::semi);
- // Diagnose an attempt to declare a templated using-declaration.
- // In C++11, alias-declarations can be templates:
- // template <...> using id = type;
- if (TemplateInfo.Kind && !IsAliasDecl) {
- SourceRange R = TemplateInfo.getSourceRange();
- Diag(UsingLoc, diag::err_templated_using_directive_declaration)
- << 1 /* declaration */ << R << FixItHint::CreateRemoval(R);
+ return Actions.BuildDeclaratorGroup(DeclsInGroup, /*MayContainAuto*/false);
+}
- // Unfortunately, we have to bail out instead of recovering by
- // ignoring the parameters, just in case the nested name specifier
- // depends on the parameters.
+Decl *Parser::ParseAliasDeclarationAfterDeclarator(
+ const ParsedTemplateInfo &TemplateInfo, SourceLocation UsingLoc,
+ UsingDeclarator &D, SourceLocation &DeclEnd, AccessSpecifier AS,
+ ParsedAttributes &Attrs, Decl **OwnedType) {
+ if (ExpectAndConsume(tok::equal)) {
+ SkipUntil(tok::semi);
return nullptr;
}
- // "typename" keyword is allowed for identifiers only,
- // because it may be a type definition.
- if (HasTypenameKeyword && Name.getKind() != UnqualifiedId::IK_Identifier) {
- Diag(Name.getSourceRange().getBegin(), diag::err_typename_identifiers_only)
- << FixItHint::CreateRemoval(SourceRange(TypenameLoc));
- // Proceed parsing, but reset the HasTypenameKeyword flag.
- HasTypenameKeyword = false;
+ Diag(Tok.getLocation(), getLangOpts().CPlusPlus11 ?
+ diag::warn_cxx98_compat_alias_declaration :
+ diag::ext_alias_declaration);
+
+ // Type alias templates cannot be specialized.
+ int SpecKind = -1;
+ if (TemplateInfo.Kind == ParsedTemplateInfo::Template &&
+ D.Name.getKind() == UnqualifiedId::IK_TemplateId)
+ SpecKind = 0;
+ if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitSpecialization)
+ SpecKind = 1;
+ if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation)
+ SpecKind = 2;
+ if (SpecKind != -1) {
+ SourceRange Range;
+ if (SpecKind == 0)
+ Range = SourceRange(D.Name.TemplateId->LAngleLoc,
+ D.Name.TemplateId->RAngleLoc);
+ else
+ Range = TemplateInfo.getSourceRange();
+ Diag(Range.getBegin(), diag::err_alias_declaration_specialization)
+ << SpecKind << Range;
+ SkipUntil(tok::semi);
+ return nullptr;
}
- if (IsAliasDecl) {
- TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams;
- MultiTemplateParamsArg TemplateParamsArg(
- TemplateParams ? TemplateParams->data() : nullptr,
- TemplateParams ? TemplateParams->size() : 0);
- return Actions.ActOnAliasDeclaration(getCurScope(), AS, TemplateParamsArg,
- UsingLoc, Name, Attrs.getList(),
- TypeAlias, DeclFromDeclSpec);
- }
+ // Name must be an identifier.
+ if (D.Name.getKind() != UnqualifiedId::IK_Identifier) {
+ Diag(D.Name.StartLocation, diag::err_alias_declaration_not_identifier);
+ // No removal fixit: can't recover from this.
+ SkipUntil(tok::semi);
+ return nullptr;
+ } else if (D.TypenameLoc.isValid())
+ Diag(D.TypenameLoc, diag::err_alias_declaration_not_identifier)
+ << FixItHint::CreateRemoval(SourceRange(
+ D.TypenameLoc,
+ D.SS.isNotEmpty() ? D.SS.getEndLoc() : D.TypenameLoc));
+ else if (D.SS.isNotEmpty())
+ Diag(D.SS.getBeginLoc(), diag::err_alias_declaration_not_identifier)
+ << FixItHint::CreateRemoval(D.SS.getRange());
+ if (D.EllipsisLoc.isValid())
+ Diag(D.EllipsisLoc, diag::err_alias_declaration_pack_expansion)
+ << FixItHint::CreateRemoval(SourceRange(D.EllipsisLoc));
+
+ Decl *DeclFromDeclSpec = nullptr;
+ TypeResult TypeAlias =
+ ParseTypeName(nullptr,
+ TemplateInfo.Kind ? Declarator::AliasTemplateContext
+ : Declarator::AliasDeclContext,
+ AS, &DeclFromDeclSpec, &Attrs);
+ if (OwnedType)
+ *OwnedType = DeclFromDeclSpec;
- return Actions.ActOnUsingDeclaration(getCurScope(), AS,
- /* HasUsingKeyword */ true, UsingLoc,
- SS, Name, Attrs.getList(),
- HasTypenameKeyword, TypenameLoc);
+ // Eat ';'.
+ DeclEnd = Tok.getLocation();
+ if (ExpectAndConsume(tok::semi, diag::err_expected_after,
+ !Attrs.empty() ? "attributes list"
+ : "alias declaration"))
+ SkipUntil(tok::semi);
+
+ TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams;
+ MultiTemplateParamsArg TemplateParamsArg(
+ TemplateParams ? TemplateParams->data() : nullptr,
+ TemplateParams ? TemplateParams->size() : 0);
+ return Actions.ActOnAliasDeclaration(getCurScope(), AS, TemplateParamsArg,
+ UsingLoc, D.Name, Attrs.getList(),
+ TypeAlias, DeclFromDeclSpec);
}
/// ParseStaticAssertDeclaration - Parse C++0x or C11 static_assert-declaration.
@@ -1742,7 +1849,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
TParams =
MultiTemplateParamsArg(&(*TemplateParams)[0], TemplateParams->size());
- handleDeclspecAlignBeforeClassKey(attrs, DS, TUK);
+ stripTypeAttributesOffDeclSpec(attrs, DS, TUK);
// Declaration or definition of a class type
TagOrTempResult = Actions.ActOnTag(getCurScope(), TagType, TUK, StartLoc,
@@ -1995,7 +2102,8 @@ void Parser::HandleMemberFunctionDeclDelays(Declarator& DeclaratorInfo,
LateMethod->DefaultArgs.reserve(FTI.NumParams);
for (unsigned ParamIdx = 0; ParamIdx < FTI.NumParams; ++ParamIdx)
LateMethod->DefaultArgs.push_back(LateParsedDefaultArgument(
- FTI.Params[ParamIdx].Param, FTI.Params[ParamIdx].DefaultArgTokens));
+ FTI.Params[ParamIdx].Param,
+ std::move(FTI.Params[ParamIdx].DefaultArgTokens)));
}
}
@@ -2005,6 +2113,7 @@ void Parser::HandleMemberFunctionDeclDelays(Declarator& DeclaratorInfo,
/// virt-specifier:
/// override
/// final
+/// __final
VirtSpecifiers::Specifier Parser::isCXX11VirtSpecifier(const Token &Tok) const {
if (!getLangOpts().CPlusPlus || Tok.isNot(tok::identifier))
return VirtSpecifiers::VS_None;
@@ -2014,6 +2123,8 @@ VirtSpecifiers::Specifier Parser::isCXX11VirtSpecifier(const Token &Tok) const {
// Initialize the contextual keywords.
if (!Ident_final) {
Ident_final = &PP.getIdentifierTable().get("final");
+ if (getLangOpts().GNUKeywords)
+ Ident_GNU_final = &PP.getIdentifierTable().get("__final");
if (getLangOpts().MicrosoftExt)
Ident_sealed = &PP.getIdentifierTable().get("sealed");
Ident_override = &PP.getIdentifierTable().get("override");
@@ -2028,6 +2139,9 @@ VirtSpecifiers::Specifier Parser::isCXX11VirtSpecifier(const Token &Tok) const {
if (II == Ident_final)
return VirtSpecifiers::VS_Final;
+ if (II == Ident_GNU_final)
+ return VirtSpecifiers::VS_GNU_Final;
+
return VirtSpecifiers::VS_None;
}
@@ -2067,6 +2181,8 @@ void Parser::ParseOptionalCXX11VirtSpecifierSeq(VirtSpecifiers &VS,
<< VirtSpecifiers::getSpecifierName(Specifier);
} else if (Specifier == VirtSpecifiers::VS_Sealed) {
Diag(Tok.getLocation(), diag::ext_ms_sealed_keyword);
+ } else if (Specifier == VirtSpecifiers::VS_GNU_Final) {
+ Diag(Tok.getLocation(), diag::ext_warn_gnu_final);
} else {
Diag(Tok.getLocation(),
getLangOpts().CPlusPlus11
@@ -2083,6 +2199,7 @@ void Parser::ParseOptionalCXX11VirtSpecifierSeq(VirtSpecifiers &VS,
bool Parser::isCXX11FinalKeyword() const {
VirtSpecifiers::Specifier Specifier = isCXX11VirtSpecifier();
return Specifier == VirtSpecifiers::VS_Final ||
+ Specifier == VirtSpecifiers::VS_GNU_Final ||
Specifier == VirtSpecifiers::VS_Sealed;
}
@@ -2181,7 +2298,7 @@ void Parser::MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(
if (!(Function.TypeQuals & TypeQual)) {
std::string Name(FixItName);
Name += " ";
- Insertion = FixItHint::CreateInsertion(VS.getFirstLocation(), Name.c_str());
+ Insertion = FixItHint::CreateInsertion(VS.getFirstLocation(), Name);
Function.TypeQuals |= TypeQual;
*QualifierLoc = SpecLoc.getRawEncoding();
}
@@ -2322,10 +2439,9 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
}
return DeclGroupPtrTy::make(DeclGroupRef(Actions.ActOnUsingDeclaration(
- getCurScope(), AS,
- /* HasUsingKeyword */ false, SourceLocation(), SS, Name,
- /* AttrList */ nullptr,
- /* HasTypenameKeyword */ false, SourceLocation())));
+ getCurScope(), AS, /*UsingLoc*/ SourceLocation(),
+ /*TypenameLoc*/ SourceLocation(), SS, Name,
+ /*EllipsisLoc*/ SourceLocation(), /*AttrList*/ nullptr)));
}
}
@@ -2380,8 +2496,8 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
}
SourceLocation DeclEnd;
// Otherwise, it must be a using-declaration or an alias-declaration.
- return DeclGroupPtrTy::make(DeclGroupRef(ParseUsingDeclaration(
- Declarator::MemberContext, TemplateInfo, UsingLoc, DeclEnd, AS)));
+ return ParseUsingDeclaration(Declarator::MemberContext, TemplateInfo,
+ UsingLoc, DeclEnd, AS);
}
// Hold late-parsed attributes so we can attach a Decl to them later.
@@ -2996,6 +3112,7 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
if (getLangOpts().CPlusPlus && Tok.is(tok::identifier)) {
VirtSpecifiers::Specifier Specifier = isCXX11VirtSpecifier(Tok);
assert((Specifier == VirtSpecifiers::VS_Final ||
+ Specifier == VirtSpecifiers::VS_GNU_Final ||
Specifier == VirtSpecifiers::VS_Sealed) &&
"not a class definition");
FinalLoc = ConsumeToken();
@@ -3011,6 +3128,8 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
<< VirtSpecifiers::getSpecifierName(Specifier);
else if (Specifier == VirtSpecifiers::VS_Sealed)
Diag(FinalLoc, diag::ext_ms_sealed_keyword);
+ else if (Specifier == VirtSpecifiers::VS_GNU_Final)
+ Diag(FinalLoc, diag::ext_warn_gnu_final);
// Parse any C++11 attributes after 'final' keyword.
// These attributes are not allowed to appear here,
@@ -3456,7 +3575,11 @@ static void diagnoseDynamicExceptionSpecification(
Parser &P, SourceRange Range, bool IsNoexcept) {
if (P.getLangOpts().CPlusPlus11) {
const char *Replacement = IsNoexcept ? "noexcept" : "noexcept(false)";
- P.Diag(Range.getBegin(), diag::warn_exception_spec_deprecated) << Range;
+ P.Diag(Range.getBegin(),
+ P.getLangOpts().CPlusPlus1z && !IsNoexcept
+ ? diag::ext_dynamic_exception_spec
+ : diag::warn_exception_spec_deprecated)
+ << Range;
P.Diag(Range.getBegin(), diag::note_exception_spec_deprecated)
<< Replacement << FixItHint::CreateReplacement(Range, Replacement);
}
@@ -3655,8 +3778,8 @@ static bool IsBuiltInOrStandardCXX11Attribute(IdentifierInfo *AttrName,
return true;
case AttributeList::AT_WarnUnusedResult:
return !ScopeName && AttrName->getName().equals("nodiscard");
- case AttributeList::AT_Unused:
- return !ScopeName && AttrName->getName().equals("maybe_unused");
+ case AttributeList::AT_Unused:
+ return !ScopeName && AttrName->getName().equals("maybe_unused");
default:
return false;
}
@@ -3913,6 +4036,93 @@ SourceLocation Parser::SkipCXX11Attributes() {
return EndLoc;
}
+/// Parse uuid() attribute when it appears in a [] Microsoft attribute.
+void Parser::ParseMicrosoftUuidAttributeArgs(ParsedAttributes &Attrs) {
+ assert(Tok.is(tok::identifier) && "Not a Microsoft attribute list");
+ IdentifierInfo *UuidIdent = Tok.getIdentifierInfo();
+ assert(UuidIdent->getName() == "uuid" && "Not a Microsoft attribute list");
+
+ SourceLocation UuidLoc = Tok.getLocation();
+ ConsumeToken();
+
+ // Ignore the left paren location for now.
+ BalancedDelimiterTracker T(*this, tok::l_paren);
+ if (T.consumeOpen()) {
+ Diag(Tok, diag::err_expected) << tok::l_paren;
+ return;
+ }
+
+ ArgsVector ArgExprs;
+ if (Tok.is(tok::string_literal)) {
+ // Easy case: uuid("...") -- quoted string.
+ ExprResult StringResult = ParseStringLiteralExpression();
+ if (StringResult.isInvalid())
+ return;
+ ArgExprs.push_back(StringResult.get());
+ } else {
+ // something like uuid({000000A0-0000-0000-C000-000000000049}) -- no
+ // quotes in the parens. Just append the spelling of all tokens encountered
+ // until the closing paren.
+
+ SmallString<42> StrBuffer; // 2 "", 36 bytes UUID, 2 optional {}, 1 nul
+ StrBuffer += "\"";
+
+ // Since none of C++'s keywords match [a-f]+, accepting just tok::l_brace,
+ // tok::r_brace, tok::minus, tok::identifier (think C000) and
+ // tok::numeric_constant (0000) should be enough. But the spelling of the
+ // uuid argument is checked later anyways, so there's no harm in accepting
+ // almost anything here.
+ // cl is very strict about whitespace in this form and errors out if any
+ // is present, so check the space flags on the tokens.
+ SourceLocation StartLoc = Tok.getLocation();
+ while (Tok.isNot(tok::r_paren)) {
+ if (Tok.hasLeadingSpace() || Tok.isAtStartOfLine()) {
+ Diag(Tok, diag::err_attribute_uuid_malformed_guid);
+ SkipUntil(tok::r_paren, StopAtSemi);
+ return;
+ }
+ SmallString<16> SpellingBuffer;
+ SpellingBuffer.resize(Tok.getLength() + 1);
+ bool Invalid = false;
+ StringRef TokSpelling = PP.getSpelling(Tok, SpellingBuffer, &Invalid);
+ if (Invalid) {
+ SkipUntil(tok::r_paren, StopAtSemi);
+ return;
+ }
+ StrBuffer += TokSpelling;
+ ConsumeAnyToken();
+ }
+ StrBuffer += "\"";
+
+ if (Tok.hasLeadingSpace() || Tok.isAtStartOfLine()) {
+ Diag(Tok, diag::err_attribute_uuid_malformed_guid);
+ ConsumeParen();
+ return;
+ }
+
+ // Pretend the user wrote the appropriate string literal here.
+ // ActOnStringLiteral() copies the string data into the literal, so it's
+ // ok that the Token points to StrBuffer.
+ Token Toks[1];
+ Toks[0].startToken();
+ Toks[0].setKind(tok::string_literal);
+ Toks[0].setLocation(StartLoc);
+ Toks[0].setLiteralData(StrBuffer.data());
+ Toks[0].setLength(StrBuffer.size());
+ StringLiteral *UuidString =
+ cast<StringLiteral>(Actions.ActOnStringLiteral(Toks, nullptr).get());
+ ArgExprs.push_back(UuidString);
+ }
+
+ if (!T.consumeClose()) {
+ // FIXME: Warn that this syntax is deprecated, with a Fix-It suggesting
+ // using __declspec(uuid()) instead.
+ Attrs.addNew(UuidIdent, SourceRange(UuidLoc, T.getCloseLocation()), nullptr,
+ SourceLocation(), ArgExprs.data(), ArgExprs.size(),
+ AttributeList::AS_Microsoft);
+ }
+}
+
/// ParseMicrosoftAttributes - Parse Microsoft attributes [Attr]
///
/// [MS] ms-attribute:
@@ -3929,7 +4139,18 @@ void Parser::ParseMicrosoftAttributes(ParsedAttributes &attrs,
// FIXME: If this is actually a C++11 attribute, parse it as one.
BalancedDelimiterTracker T(*this, tok::l_square);
T.consumeOpen();
- SkipUntil(tok::r_square, StopAtSemi | StopBeforeMatch);
+
+ // Skip most ms attributes except for a whitelist.
+ while (true) {
+ SkipUntil(tok::r_square, tok::identifier, StopAtSemi | StopBeforeMatch);
+ if (Tok.isNot(tok::identifier)) // ']', but also eof
+ break;
+ if (Tok.getIdentifierInfo()->getName() == "uuid")
+ ParseMicrosoftUuidAttributeArgs(attrs);
+ else
+ ConsumeToken();
+ }
+
T.consumeClose();
if (endLoc)
*endLoc = T.getCloseLocation();
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 3e87a73aafe8..caf2320f8fc1 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -21,15 +21,14 @@
///
//===----------------------------------------------------------------------===//
-#include "clang/Parse/Parser.h"
#include "RAIIObjectsForParser.h"
#include "clang/AST/ASTContext.h"
#include "clang/Basic/PrettyStackTrace.h"
+#include "clang/Parse/Parser.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/TypoCorrection.h"
-#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
using namespace clang;
@@ -886,7 +885,13 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
// Allow the base to be 'super' if in an objc-method.
(&II == Ident_super && getCurScope()->isInObjcMethodScope()))) {
ConsumeToken();
-
+
+ if (Tok.is(tok::code_completion) && &II != Ident_super) {
+ Actions.CodeCompleteObjCClassPropertyRefExpr(
+ getCurScope(), II, ILoc, ExprStatementTokLoc == ILoc);
+ cutOffParsing();
+ return ExprError();
+ }
// Allow either an identifier or the keyword 'class' (in C++).
if (Tok.isNot(tok::identifier) &&
!(getLangOpts().CPlusPlus && Tok.is(tok::kw_class))) {
@@ -1647,9 +1652,10 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
if (Tok.is(tok::code_completion)) {
// Code completion for a member access expression.
- Actions.CodeCompleteMemberReferenceExpr(getCurScope(), LHS.get(),
- OpLoc, OpKind == tok::arrow);
-
+ Actions.CodeCompleteMemberReferenceExpr(
+ getCurScope(), LHS.get(), OpLoc, OpKind == tok::arrow,
+ ExprStatementTokLoc == LHS.get()->getLocStart());
+
cutOffParsing();
return ExprError();
}
@@ -2836,6 +2842,7 @@ ExprResult Parser::ParseBlockLiteralExpression() {
/*NumExceptions=*/0,
/*NoexceptExpr=*/nullptr,
/*ExceptionSpecTokens=*/nullptr,
+ /*DeclsInPrototype=*/None,
CaretLoc, CaretLoc,
ParamInfo),
attrs, CaretLoc);
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 85c1301fc967..ca1b3b1ad01b 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -100,48 +100,6 @@ void Parser::CheckForTemplateAndDigraph(Token &Next, ParsedType ObjectType,
/*AtDigraph*/false);
}
-/// \brief Emits an error for a left parentheses after a double colon.
-///
-/// When a '(' is found after a '::', emit an error. Attempt to fix the token
-/// stream by removing the '(', and the matching ')' if found.
-void Parser::CheckForLParenAfterColonColon() {
- if (!Tok.is(tok::l_paren))
- return;
-
- Token LParen = Tok;
- Token NextTok = GetLookAheadToken(1);
- Token StarTok = NextTok;
- // Check for (identifier or (*identifier
- Token IdentifierTok = StarTok.is(tok::star) ? GetLookAheadToken(2) : StarTok;
- if (IdentifierTok.isNot(tok::identifier))
- return;
- // Eat the '('.
- ConsumeParen();
- Token RParen;
- RParen.setLocation(SourceLocation());
- // Do we have a ')' ?
- NextTok = StarTok.is(tok::star) ? GetLookAheadToken(2) : GetLookAheadToken(1);
- if (NextTok.is(tok::r_paren)) {
- RParen = NextTok;
- // Eat the '*' if it is present.
- if (StarTok.is(tok::star))
- ConsumeToken();
- // Eat the identifier.
- ConsumeToken();
- // Add the identifier token back.
- PP.EnterToken(IdentifierTok);
- // Add the '*' back if it was present.
- if (StarTok.is(tok::star))
- PP.EnterToken(StarTok);
- // Eat the ')'.
- ConsumeParen();
- }
-
- Diag(LParen.getLocation(), diag::err_paren_after_colon_colon)
- << FixItHint::CreateRemoval(LParen.getLocation())
- << FixItHint::CreateRemoval(RParen.getLocation());
-}
-
/// \brief Parse global scope or nested-name-specifier if present.
///
/// Parses a C++ global scope specifier ('::') or nested-name-specifier (which
@@ -237,8 +195,6 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
if (Actions.ActOnCXXGlobalScopeSpecifier(ConsumeToken(), SS))
return true;
- CheckForLParenAfterColonColon();
-
HasScopeSpecifier = true;
}
}
@@ -427,13 +383,13 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
// namespace-name '::'
// nested-name-specifier identifier '::'
Token Next = NextToken();
-
+ Sema::NestedNameSpecInfo IdInfo(&II, Tok.getLocation(), Next.getLocation(),
+ ObjectType);
+
// If we get foo:bar, this is almost certainly a typo for foo::bar. Recover
// and emit a fixit hint for it.
if (Next.is(tok::colon) && !ColonIsSacred) {
- if (Actions.IsInvalidUnlessNestedName(getCurScope(), SS, II,
- Tok.getLocation(),
- Next.getLocation(), ObjectType,
+ if (Actions.IsInvalidUnlessNestedName(getCurScope(), SS, IdInfo,
EnteringContext) &&
// If the token after the colon isn't an identifier, it's still an
// error, but they probably meant something else strange so don't
@@ -459,8 +415,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
if (Next.is(tok::coloncolon)) {
if (CheckForDestructor && GetLookAheadToken(2).is(tok::tilde) &&
- !Actions.isNonTypeNestedNameSpecifier(
- getCurScope(), SS, Tok.getLocation(), II, ObjectType)) {
+ !Actions.isNonTypeNestedNameSpecifier(getCurScope(), SS, IdInfo)) {
*MayBePseudoDestructor = true;
return false;
}
@@ -492,12 +447,10 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
Token ColonColon = Tok;
SourceLocation CCLoc = ConsumeToken();
- CheckForLParenAfterColonColon();
-
bool IsCorrectedToColon = false;
bool *CorrectionFlagPtr = ColonIsSacred ? &IsCorrectedToColon : nullptr;
- if (Actions.ActOnCXXNestedNameSpecifier(getCurScope(), II, IdLoc, CCLoc,
- ObjectType, EnteringContext, SS,
+ if (Actions.ActOnCXXNestedNameSpecifier(getCurScope(), IdInfo,
+ EnteringContext, SS,
false, CorrectionFlagPtr)) {
// Identifier is not recognized as a nested name, but we can have
// mistyped '::' instead of ':'.
@@ -949,6 +902,8 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
SourceLocation StartLoc = Tok.getLocation();
InMessageExpressionRAIIObject MaybeInMessageExpression(*this, true);
Init = ParseInitializer();
+ if (!Init.isInvalid())
+ Init = Actions.CorrectDelayedTyposInExpr(Init.get());
if (Tok.getLocation() != StartLoc) {
// Back out the lexing of the token after the initializer.
@@ -1003,6 +958,7 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
// return y;
// }
// };
+ // }
// If x was not const, the second use would require 'L' to capture, and
// that would be an error.
@@ -1053,6 +1009,58 @@ bool Parser::TryParseLambdaIntroducer(LambdaIntroducer &Intro) {
return false;
}
+static void
+tryConsumeMutableOrConstexprToken(Parser &P, SourceLocation &MutableLoc,
+ SourceLocation &ConstexprLoc,
+ SourceLocation &DeclEndLoc) {
+ assert(MutableLoc.isInvalid());
+ assert(ConstexprLoc.isInvalid());
+ // Consume constexpr-opt mutable-opt in any sequence, and set the DeclEndLoc
+ // to the final of those locations. Emit an error if we have multiple
+ // copies of those keywords and recover.
+
+ while (true) {
+ switch (P.getCurToken().getKind()) {
+ case tok::kw_mutable: {
+ if (MutableLoc.isValid()) {
+ P.Diag(P.getCurToken().getLocation(),
+ diag::err_lambda_decl_specifier_repeated)
+ << 0 << FixItHint::CreateRemoval(P.getCurToken().getLocation());
+ }
+ MutableLoc = P.ConsumeToken();
+ DeclEndLoc = MutableLoc;
+ break /*switch*/;
+ }
+ case tok::kw_constexpr:
+ if (ConstexprLoc.isValid()) {
+ P.Diag(P.getCurToken().getLocation(),
+ diag::err_lambda_decl_specifier_repeated)
+ << 1 << FixItHint::CreateRemoval(P.getCurToken().getLocation());
+ }
+ ConstexprLoc = P.ConsumeToken();
+ DeclEndLoc = ConstexprLoc;
+ break /*switch*/;
+ default:
+ return;
+ }
+ }
+}
+
+static void
+addConstexprToLambdaDeclSpecifier(Parser &P, SourceLocation ConstexprLoc,
+ DeclSpec &DS) {
+ if (ConstexprLoc.isValid()) {
+ P.Diag(ConstexprLoc, !P.getLangOpts().CPlusPlus1z
+ ? diag::ext_constexpr_on_lambda_cxx1z
+ : diag::warn_cxx14_compat_constexpr_on_lambda);
+ const char *PrevSpec = nullptr;
+ unsigned DiagID = 0;
+ DS.SetConstexprSpec(ConstexprLoc, PrevSpec, DiagID);
+ assert(PrevSpec == nullptr && DiagID == 0 &&
+ "Constexpr cannot have been set previously!");
+ }
+}
+
/// ParseLambdaExpressionAfterIntroducer - Parse the rest of a lambda
/// expression.
ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
@@ -1072,7 +1080,27 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
DeclSpec DS(AttrFactory);
Declarator D(DS, Declarator::LambdaExprContext);
TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth);
- Actions.PushLambdaScope();
+ Actions.PushLambdaScope();
+
+ ParsedAttributes Attr(AttrFactory);
+ SourceLocation DeclLoc = Tok.getLocation();
+ if (getLangOpts().CUDA) {
+ // In CUDA code, GNU attributes are allowed to appear immediately after the
+ // "[...]", even if there is no "(...)" before the lambda body.
+ MaybeParseGNUAttributes(D);
+ }
+
+ // Helper to emit a warning if we see a CUDA host/device/global attribute
+ // 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();
+ };
TypeResult TrailingReturnType;
if (Tok.is(tok::l_paren)) {
@@ -1081,13 +1109,11 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
Scope::FunctionDeclarationScope |
Scope::DeclScope);
- SourceLocation DeclEndLoc;
BalancedDelimiterTracker T(*this, tok::l_paren);
T.consumeOpen();
SourceLocation LParenLoc = T.getOpenLocation();
// Parse parameter-declaration-clause.
- ParsedAttributes Attr(AttrFactory);
SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo;
SourceLocation EllipsisLoc;
@@ -1101,7 +1127,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
}
T.consumeClose();
SourceLocation RParenLoc = T.getCloseLocation();
- DeclEndLoc = RParenLoc;
+ SourceLocation DeclEndLoc = RParenLoc;
// GNU-style attributes must be parsed before the mutable specifier to be
// compatible with GCC.
@@ -1111,10 +1137,13 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
// compatible with MSVC.
MaybeParseMicrosoftDeclSpecs(Attr, &DeclEndLoc);
- // Parse 'mutable'[opt].
+ // Parse mutable-opt and/or constexpr-opt, and update the DeclEndLoc.
SourceLocation MutableLoc;
- if (TryConsumeToken(tok::kw_mutable, MutableLoc))
- DeclEndLoc = MutableLoc;
+ SourceLocation ConstexprLoc;
+ tryConsumeMutableOrConstexprToken(*this, MutableLoc, ConstexprLoc,
+ DeclEndLoc);
+
+ addConstexprToLambdaDeclSpecifier(*this, ConstexprLoc, DS);
// Parse exception-specification[opt].
ExceptionSpecificationType ESpecType = EST_None;
@@ -1149,6 +1178,8 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
PrototypeScope.Exit();
+ WarnIfHasCUDATargetAttr();
+
SourceLocation NoLoc;
D.AddTypeInfo(DeclaratorChunk::getFunction(/*hasProto=*/true,
/*isAmbiguous=*/false,
@@ -1169,10 +1200,12 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
NoexceptExpr.isUsable() ?
NoexceptExpr.get() : nullptr,
/*ExceptionSpecTokens*/nullptr,
+ /*DeclsInPrototype=*/None,
LParenLoc, FunLocalRangeEnd, D,
TrailingReturnType),
Attr, DeclEndLoc);
- } else if (Tok.isOneOf(tok::kw_mutable, tok::arrow, tok::kw___attribute) ||
+ } 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))) {
// It's common to forget that one needs '()' before 'mutable', an attribute
// specifier, or the result type. Deal with this.
@@ -1182,18 +1215,17 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
case tok::arrow: TokKind = 1; break;
case tok::kw___attribute:
case tok::l_square: TokKind = 2; break;
+ case tok::kw_constexpr: TokKind = 3; break;
default: llvm_unreachable("Unknown token kind");
}
Diag(Tok, diag::err_lambda_missing_parens)
<< TokKind
<< FixItHint::CreateInsertion(Tok.getLocation(), "() ");
- SourceLocation DeclLoc = Tok.getLocation();
SourceLocation DeclEndLoc = DeclLoc;
// GNU-style attributes must be parsed before the mutable specifier to be
// compatible with GCC.
- ParsedAttributes Attr(AttrFactory);
MaybeParseGNUAttributes(Attr, &DeclEndLoc);
// Parse 'mutable', if it's there.
@@ -1214,6 +1246,8 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
DeclEndLoc = Range.getEnd();
}
+ WarnIfHasCUDATargetAttr();
+
SourceLocation NoLoc;
D.AddTypeInfo(DeclaratorChunk::getFunction(/*hasProto=*/true,
/*isAmbiguous=*/false,
@@ -1236,11 +1270,11 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
/*NumExceptions=*/0,
/*NoexceptExpr=*/nullptr,
/*ExceptionSpecTokens=*/nullptr,
+ /*DeclsInPrototype=*/None,
DeclLoc, DeclEndLoc, D,
TrailingReturnType),
Attr, DeclEndLoc);
}
-
// FIXME: Rename BlockScope -> ClosureScope if we decide to continue using
// it.
@@ -1711,6 +1745,10 @@ Sema::ConditionResult Parser::ParseCXXCondition(StmtResult *InitStmt,
}
case ConditionOrInitStatement::InitStmtDecl: {
+ Diag(Tok.getLocation(), getLangOpts().CPlusPlus1z
+ ? diag::warn_cxx14_compat_init_statement
+ : diag::ext_init_statement)
+ << (CK == Sema::ConditionKind::Switch);
SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
DeclGroupPtrTy DG = ParseSimpleDeclaration(
Declarator::InitStmtContext, DeclEnd, attrs, /*RequireSemi=*/true);
diff --git a/lib/Parse/ParseInit.cpp b/lib/Parse/ParseInit.cpp
index 2cdb9d3a22a6..4a68942f6d2c 100644
--- a/lib/Parse/ParseInit.cpp
+++ b/lib/Parse/ParseInit.cpp
@@ -11,13 +11,12 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Parse/Parser.h"
#include "RAIIObjectsForParser.h"
#include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Parse/Parser.h"
#include "clang/Sema/Designator.h"
#include "clang/Sema/Scope.h"
#include "llvm/ADT/SmallString.h"
-#include "llvm/Support/raw_ostream.h"
using namespace clang;
diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp
index 67abe5839bfe..81761bf8d2d8 100644
--- a/lib/Parse/ParseObjc.cpp
+++ b/lib/Parse/ParseObjc.cpp
@@ -344,9 +344,11 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
protocols, protocolLocs, EndProtoLoc,
/*consumeLastToken=*/true,
/*warnOnIncompleteProtocols=*/true);
+ if (Tok.is(tok::eof))
+ return nullptr;
}
}
-
+
// Next, we need to check for any protocol references.
if (LAngleLoc.isValid()) {
if (!ProtocolIdents.empty()) {
@@ -367,7 +369,8 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
}
if (Tok.isNot(tok::less))
- Actions.ActOnTypedefedProtocols(protocols, superClassId, superClassLoc);
+ Actions.ActOnTypedefedProtocols(protocols, protocolLocs,
+ superClassId, superClassLoc);
Decl *ClsType =
Actions.ActOnStartClassInterface(getCurScope(), AtLoc, nameId, nameLoc,
@@ -1034,7 +1037,7 @@ IdentifierInfo *Parser::ParseObjCSelectorPiece(SourceLocation &SelectorLoc) {
case tok::caretequal: {
std::string ThisTok(PP.getSpelling(Tok));
if (isLetter(ThisTok[0])) {
- IdentifierInfo *II = &PP.getIdentifierTable().get(ThisTok.data());
+ IdentifierInfo *II = &PP.getIdentifierTable().get(ThisTok);
Tok.setKind(tok::identifier);
SelectorLoc = ConsumeToken();
return II;
@@ -1814,6 +1817,8 @@ void Parser::parseObjCTypeArgsAndProtocolQualifiers(
protocolRAngleLoc,
consumeLastToken,
/*warnOnIncompleteProtocols=*/false);
+ if (Tok.is(tok::eof)) // Nothing else to do here...
+ return;
// An Objective-C object pointer followed by type arguments
// can then be followed again by a set of protocol references, e.g.,
@@ -1862,6 +1867,9 @@ TypeResult Parser::parseObjCTypeArgsAndProtocolQualifiers(
protocols, protocolLocs,
protocolRAngleLoc, consumeLastToken);
+ if (Tok.is(tok::eof))
+ return true; // Invalid type result.
+
// Compute the location of the last token.
if (consumeLastToken)
endLoc = PrevTokLocation;
@@ -2238,7 +2246,6 @@ Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc) {
while (!ObjCImplParsing.isFinished() && !isEofOrEom()) {
ParsedAttributesWithRange attrs(AttrFactory);
MaybeParseCXX11Attributes(attrs);
- MaybeParseMicrosoftAttributes(attrs);
if (DeclGroupPtrTy DGP = ParseExternalDeclaration(attrs)) {
DeclGroupRef DG = DGP.get();
DeclsInGroup.append(DG.begin(), DG.end());
@@ -2766,6 +2773,7 @@ StmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc) {
return Actions.ActOnNullStmt(Tok.getLocation());
}
+ ExprStatementTokLoc = AtLoc;
ExprResult Res(ParseExpressionWithLeadingAt(AtLoc));
if (Res.isInvalid()) {
// If the expression is invalid, skip ahead to the next semicolon. Not
@@ -2862,7 +2870,11 @@ ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) {
return ParseAvailabilityCheckExpr(AtLoc);
default: {
const char *str = nullptr;
- if (GetLookAheadToken(1).is(tok::l_brace)) {
+ // Only provide the @try/@finally/@autoreleasepool fixit when we're sure
+ // that this is a proper statement where such directives could actually
+ // occur.
+ if (GetLookAheadToken(1).is(tok::l_brace) &&
+ ExprStatementTokLoc == AtLoc) {
char ch = Tok.getIdentifierInfo()->getNameStart()[0];
str =
ch == 't' ? "try"
@@ -3416,6 +3428,7 @@ ExprResult Parser::ParseObjCArrayLiteral(SourceLocation AtLoc) {
ExprVector ElementExprs; // array elements.
ConsumeBracket(); // consume the l_square.
+ bool HasInvalidEltExpr = false;
while (Tok.isNot(tok::r_square)) {
// Parse list of array element expressions (all must be id types).
ExprResult Res(ParseAssignmentExpression());
@@ -3427,11 +3440,15 @@ ExprResult Parser::ParseObjCArrayLiteral(SourceLocation AtLoc) {
return Res;
}
+ Res = Actions.CorrectDelayedTyposInExpr(Res.get());
+ if (Res.isInvalid())
+ HasInvalidEltExpr = true;
+
// Parse the ellipsis that indicates a pack expansion.
if (Tok.is(tok::ellipsis))
Res = Actions.ActOnPackExpansion(Res.get(), ConsumeToken());
if (Res.isInvalid())
- return true;
+ HasInvalidEltExpr = true;
ElementExprs.push_back(Res.get());
@@ -3442,6 +3459,10 @@ ExprResult Parser::ParseObjCArrayLiteral(SourceLocation AtLoc) {
<< tok::comma);
}
SourceLocation EndLoc = ConsumeBracket(); // location of ']'
+
+ if (HasInvalidEltExpr)
+ return ExprError();
+
MultiExprArg Args(ElementExprs);
return Actions.BuildObjCArrayLiteral(SourceRange(AtLoc, EndLoc), Args);
}
@@ -3449,6 +3470,7 @@ ExprResult Parser::ParseObjCArrayLiteral(SourceLocation AtLoc) {
ExprResult Parser::ParseObjCDictionaryLiteral(SourceLocation AtLoc) {
SmallVector<ObjCDictionaryElement, 4> Elements; // dictionary elements.
ConsumeBrace(); // consume the l_square.
+ bool HasInvalidEltExpr = false;
while (Tok.isNot(tok::r_brace)) {
// Parse the comma separated key : value expressions.
ExprResult KeyExpr;
@@ -3478,7 +3500,15 @@ ExprResult Parser::ParseObjCDictionaryLiteral(SourceLocation AtLoc) {
return ValueExpr;
}
- // Parse the ellipsis that designates this as a pack expansion.
+ // Check the key and value for possible typos
+ KeyExpr = Actions.CorrectDelayedTyposInExpr(KeyExpr.get());
+ ValueExpr = Actions.CorrectDelayedTyposInExpr(ValueExpr.get());
+ if (KeyExpr.isInvalid() || ValueExpr.isInvalid())
+ HasInvalidEltExpr = true;
+
+ // Parse the ellipsis that designates this as a pack expansion. Do not
+ // ActOnPackExpansion here, leave it to template instantiation time where
+ // we can get better diagnostics.
SourceLocation EllipsisLoc;
if (getLangOpts().CPlusPlus)
TryConsumeToken(tok::ellipsis, EllipsisLoc);
@@ -3495,6 +3525,9 @@ ExprResult Parser::ParseObjCDictionaryLiteral(SourceLocation AtLoc) {
<< tok::comma);
}
SourceLocation EndLoc = ConsumeBrace();
+
+ if (HasInvalidEltExpr)
+ return ExprError();
// Create the ObjCDictionaryLiteral.
return Actions.BuildObjCDictionaryLiteral(SourceRange(AtLoc, EndLoc),
diff --git a/lib/Parse/ParseOpenMP.cpp b/lib/Parse/ParseOpenMP.cpp
index df7d9bc0d8c8..061721dfb8da 100644
--- a/lib/Parse/ParseOpenMP.cpp
+++ b/lib/Parse/ParseOpenMP.cpp
@@ -12,7 +12,6 @@
//===----------------------------------------------------------------------===//
#include "RAIIObjectsForParser.h"
-#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/StmtOpenMP.h"
#include "clang/Parse/ParseDiagnostic.h"
@@ -40,7 +39,9 @@ enum OpenMPDirectiveKindEx {
OMPD_target_enter,
OMPD_target_exit,
OMPD_update,
- OMPD_distribute_parallel
+ OMPD_distribute_parallel,
+ OMPD_teams_distribute_parallel,
+ OMPD_target_teams_distribute_parallel
};
class ThreadprivateListParserHelper final {
@@ -107,8 +108,18 @@ static OpenMPDirectiveKind ParseOpenMPDirectiveKind(Parser &P) {
{ 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_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_parallel, OMPD_for, OMPD_target_teams_distribute_parallel_for }
};
enum { CancellationPoint = 0, DeclareReduction = 1, TargetData = 2 };
auto Tok = P.getCurToken();
@@ -609,7 +620,6 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
if (AS == AS_none) {
assert(TagType == DeclSpec::TST_unspecified);
MaybeParseCXX11Attributes(Attrs);
- MaybeParseMicrosoftAttributes(Attrs);
ParsingDeclSpec PDS(*this);
Ptr = ParseExternalDeclaration(Attrs, &PDS);
} else {
@@ -671,7 +681,6 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
Tok.isNot(tok::eof) && Tok.isNot(tok::r_brace)) {
ParsedAttributesWithRange attrs(AttrFactory);
MaybeParseCXX11Attributes(attrs);
- MaybeParseMicrosoftAttributes(attrs);
ParseExternalDeclaration(attrs);
if (Tok.isAnnotation() && Tok.is(tok::annot_pragma_openmp)) {
TentativeParsingAction TPA(*this);
@@ -741,6 +750,14 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
case OMPD_distribute_parallel_for_simd:
case OMPD_distribute_simd:
case OMPD_target_parallel_for_simd:
+ case OMPD_target_simd:
+ case OMPD_teams_distribute:
+ case OMPD_teams_distribute_simd:
+ case OMPD_teams_distribute_parallel_for_simd:
+ case OMPD_teams_distribute_parallel_for:
+ case OMPD_target_teams:
+ case OMPD_target_teams_distribute:
+ case OMPD_target_teams_distribute_parallel_for:
Diag(Tok, diag::err_omp_unexpected_directive)
<< getOpenMPDirectiveName(DKind);
break;
@@ -774,7 +791,12 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
/// 'target parallel' | 'target parallel for' |
/// 'target update' | 'distribute parallel for' |
/// 'distribute paralle for simd' | 'distribute simd' |
-/// 'target parallel for simd' {clause}
+/// 'target parallel for simd' | 'target simd' |
+/// 'teams distribute' | 'teams distribute simd' |
+/// 'teams distribute parallel for simd' |
+/// 'teams distribute parallel for' | 'target teams' |
+/// 'target teams distribute' |
+/// 'target teams distribute parallel for' {clause}
/// annot_pragma_openmp_end
///
StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
@@ -882,7 +904,15 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
case OMPD_distribute_parallel_for:
case OMPD_distribute_parallel_for_simd:
case OMPD_distribute_simd:
- case OMPD_target_parallel_for_simd: {
+ case OMPD_target_parallel_for_simd:
+ case OMPD_target_simd:
+ case OMPD_teams_distribute:
+ case OMPD_teams_distribute_simd:
+ case OMPD_teams_distribute_parallel_for_simd:
+ case OMPD_teams_distribute_parallel_for:
+ case OMPD_target_teams:
+ case OMPD_target_teams_distribute:
+ case OMPD_target_teams_distribute_parallel_for: {
ConsumeToken();
// Parse directive name of the 'critical' directive if any.
if (DKind == OMPD_critical) {
@@ -1441,15 +1471,19 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind) {
} else {
assert(Kind == OMPC_if);
KLoc.push_back(Tok.getLocation());
+ TentativeParsingAction TPA(*this);
Arg.push_back(ParseOpenMPDirectiveKind(*this));
if (Arg.back() != OMPD_unknown) {
ConsumeToken();
- if (Tok.is(tok::colon))
+ if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) {
+ TPA.Commit();
DelimLoc = ConsumeToken();
- else
- Diag(Tok, diag::warn_pragma_expected_colon)
- << "directive name modifier";
- }
+ } else {
+ TPA.Revert();
+ Arg.back() = OMPD_unknown;
+ }
+ } else
+ TPA.Revert();
}
bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) ||
diff --git a/lib/Parse/ParsePragma.cpp b/lib/Parse/ParsePragma.cpp
index bff5d1170fe0..2dc6a0739bc8 100644
--- a/lib/Parse/ParsePragma.cpp
+++ b/lib/Parse/ParsePragma.cpp
@@ -161,6 +161,22 @@ struct PragmaMSRuntimeChecksHandler : public EmptyPragmaHandler {
PragmaMSRuntimeChecksHandler() : EmptyPragmaHandler("runtime_checks") {}
};
+struct PragmaMSIntrinsicHandler : public PragmaHandler {
+ PragmaMSIntrinsicHandler() : PragmaHandler("intrinsic") {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+struct PragmaForceCUDAHostDeviceHandler : public PragmaHandler {
+ PragmaForceCUDAHostDeviceHandler(Sema &Actions)
+ : PragmaHandler("force_cuda_host_device"), Actions(Actions) {}
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+
+private:
+ Sema &Actions;
+};
+
} // end namespace
void Parser::initializePragmaHandlers() {
@@ -229,6 +245,14 @@ void Parser::initializePragmaHandlers() {
PP.AddPragmaHandler(MSSection.get());
MSRuntimeChecks.reset(new PragmaMSRuntimeChecksHandler());
PP.AddPragmaHandler(MSRuntimeChecks.get());
+ MSIntrinsic.reset(new PragmaMSIntrinsicHandler());
+ PP.AddPragmaHandler(MSIntrinsic.get());
+ }
+
+ if (getLangOpts().CUDA) {
+ CUDAForceHostDeviceHandler.reset(
+ new PragmaForceCUDAHostDeviceHandler(Actions));
+ PP.AddPragmaHandler("clang", CUDAForceHostDeviceHandler.get());
}
OptimizeHandler.reset(new PragmaOptimizeHandler(Actions));
@@ -297,6 +321,13 @@ void Parser::resetPragmaHandlers() {
MSSection.reset();
PP.RemovePragmaHandler(MSRuntimeChecks.get());
MSRuntimeChecks.reset();
+ PP.RemovePragmaHandler(MSIntrinsic.get());
+ MSIntrinsic.reset();
+ }
+
+ if (getLangOpts().CUDA) {
+ PP.RemovePragmaHandler("clang", CUDAForceHostDeviceHandler.get());
+ CUDAForceHostDeviceHandler.reset();
}
PP.RemovePragmaHandler("STDC", FPContractHandler.get());
@@ -455,42 +486,48 @@ StmtResult Parser::HandlePragmaCaptured()
}
namespace {
- typedef llvm::PointerIntPair<IdentifierInfo *, 1, bool> OpenCLExtData;
+ enum OpenCLExtState : char {
+ Disable, Enable, Begin, End
+ };
+ typedef std::pair<const IdentifierInfo *, OpenCLExtState> OpenCLExtData;
}
void Parser::HandlePragmaOpenCLExtension() {
assert(Tok.is(tok::annot_pragma_opencl_extension));
- OpenCLExtData data =
- OpenCLExtData::getFromOpaqueValue(Tok.getAnnotationValue());
- unsigned state = data.getInt();
- IdentifierInfo *ename = data.getPointer();
+ OpenCLExtData *Data = static_cast<OpenCLExtData*>(Tok.getAnnotationValue());
+ auto State = Data->second;
+ auto Ident = Data->first;
SourceLocation NameLoc = Tok.getLocation();
ConsumeToken(); // The annotation token.
- OpenCLOptions &f = Actions.getOpenCLOptions();
- auto CLVer = getLangOpts().OpenCLVersion;
- auto &Supp = getTargetInfo().getSupportedOpenCLOpts();
+ auto &Opt = Actions.getOpenCLOptions();
+ auto Name = Ident->getName();
// OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
// overriding all previously issued extension directives, but only if the
// behavior is set to disable."
- if (state == 0 && ename->isStr("all")) {
-#define OPENCLEXT(nm) \
- if (Supp.is_##nm##_supported_extension(CLVer)) \
- f.nm = 0;
-#include "clang/Basic/OpenCLExtensions.def"
- }
-#define OPENCLEXT(nm) else if (ename->isStr(#nm)) \
- if (Supp.is_##nm##_supported_extension(CLVer)) \
- f.nm = state; \
- else if (Supp.is_##nm##_supported_core(CLVer)) \
- PP.Diag(NameLoc, diag::warn_pragma_extension_is_core) << ename; \
- else \
- PP.Diag(NameLoc, diag::warn_pragma_unsupported_extension) << ename;
-#include "clang/Basic/OpenCLExtensions.def"
- else {
- PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << ename;
- return;
- }
+ if (Name == "all") {
+ if (State == Disable)
+ Opt.disableAll();
+ else
+ PP.Diag(NameLoc, diag::warn_pragma_expected_predicate) << 1;
+ } else if (State == Begin) {
+ if (!Opt.isKnown(Name) ||
+ !Opt.isSupported(Name, getLangOpts().OpenCLVersion)) {
+ Opt.support(Name);
+ }
+ Actions.setCurrentOpenCLExtension(Name);
+ } else if (State == End) {
+ if (Name != Actions.getCurrentOpenCLExtension())
+ PP.Diag(NameLoc, diag::warn_pragma_begin_end_mismatch);
+ Actions.setCurrentOpenCLExtension("");
+ } else if (!Opt.isKnown(Name))
+ PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << Ident;
+ else if (Opt.isSupportedExtension(Name, getLangOpts().OpenCLVersion))
+ Opt.enable(Name, State == Enable);
+ else if (Opt.isSupportedCore(Name, getLangOpts().OpenCLVersion))
+ PP.Diag(NameLoc, diag::warn_pragma_extension_is_core) << Ident;
+ else
+ PP.Diag(NameLoc, diag::warn_pragma_unsupported_extension) << Ident;
}
void Parser::HandlePragmaMSPointersToMembers() {
@@ -1410,29 +1447,34 @@ PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
"OPENCL";
return;
}
- IdentifierInfo *ename = Tok.getIdentifierInfo();
+ IdentifierInfo *Ext = Tok.getIdentifierInfo();
SourceLocation NameLoc = Tok.getLocation();
PP.Lex(Tok);
if (Tok.isNot(tok::colon)) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << ename;
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << Ext;
return;
}
PP.Lex(Tok);
if (Tok.isNot(tok::identifier)) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate) << 0;
return;
}
- IdentifierInfo *op = Tok.getIdentifierInfo();
-
- unsigned state;
- if (op->isStr("enable")) {
- state = 1;
- } else if (op->isStr("disable")) {
- state = 0;
- } else {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
+ IdentifierInfo *Pred = Tok.getIdentifierInfo();
+
+ OpenCLExtState State;
+ if (Pred->isStr("enable")) {
+ State = Enable;
+ } else if (Pred->isStr("disable")) {
+ State = Disable;
+ } else if (Pred->isStr("begin"))
+ State = Begin;
+ else if (Pred->isStr("end"))
+ State = End;
+ else {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate)
+ << Ext->isStr("all");
return;
}
SourceLocation StateLoc = Tok.getLocation();
@@ -1444,19 +1486,21 @@ PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
return;
}
- OpenCLExtData data(ename, state);
+ auto Info = PP.getPreprocessorAllocator().Allocate<OpenCLExtData>(1);
+ Info->first = Ext;
+ Info->second = State;
MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1);
Toks[0].startToken();
Toks[0].setKind(tok::annot_pragma_opencl_extension);
Toks[0].setLocation(NameLoc);
- Toks[0].setAnnotationValue(data.getOpaqueValue());
+ Toks[0].setAnnotationValue(static_cast<void*>(Info));
Toks[0].setAnnotationEndLoc(StateLoc);
PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
if (PP.getPPCallbacks())
- PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, ename,
- StateLoc, state);
+ PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, Ext,
+ StateLoc, State);
}
/// \brief Handle '#pragma omp ...' when OpenMP is disabled.
@@ -2127,3 +2171,76 @@ void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP,
PP.EnterTokenStream(std::move(TokenArray), 1,
/*DisableMacroExpansion=*/false);
}
+
+/// \brief Handle the Microsoft \#pragma intrinsic extension.
+///
+/// The syntax is:
+/// \code
+/// #pragma intrinsic(memset)
+/// #pragma intrinsic(strlen, memcpy)
+/// \endcode
+///
+/// Pragma intrisic tells the compiler to use a builtin version of the
+/// function. Clang does it anyway, so the pragma doesn't really do anything.
+/// Anyway, we emit a warning if the function specified in \#pragma intrinsic
+/// isn't an intrinsic in clang and suggest to include intrin.h.
+void PragmaMSIntrinsicHandler::HandlePragma(Preprocessor &PP,
+ PragmaIntroducerKind Introducer,
+ Token &Tok) {
+ PP.Lex(Tok);
+
+ if (Tok.isNot(tok::l_paren)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
+ << "intrinsic";
+ return;
+ }
+ PP.Lex(Tok);
+
+ bool SuggestIntrinH = !PP.isMacroDefined("__INTRIN_H");
+
+ while (Tok.is(tok::identifier)) {
+ IdentifierInfo *II = Tok.getIdentifierInfo();
+ if (!II->getBuiltinID())
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_intrinsic_builtin)
+ << II << SuggestIntrinH;
+
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::comma))
+ break;
+ PP.Lex(Tok);
+ }
+
+ if (Tok.isNot(tok::r_paren)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
+ << "intrinsic";
+ return;
+ }
+ PP.Lex(Tok);
+
+ if (Tok.isNot(tok::eod))
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
+ << "intrinsic";
+}
+void PragmaForceCUDAHostDeviceHandler::HandlePragma(
+ Preprocessor &PP, PragmaIntroducerKind Introducer, Token &Tok) {
+ Token FirstTok = Tok;
+
+ PP.Lex(Tok);
+ IdentifierInfo *Info = Tok.getIdentifierInfo();
+ if (!Info || (!Info->isStr("begin") && !Info->isStr("end"))) {
+ PP.Diag(FirstTok.getLocation(),
+ diag::warn_pragma_force_cuda_host_device_bad_arg);
+ return;
+ }
+
+ if (Info->isStr("begin"))
+ Actions.PushForceCUDAHostDevice();
+ else if (!Actions.PopForceCUDAHostDevice())
+ PP.Diag(FirstTok.getLocation(),
+ diag::err_pragma_cannot_end_force_cuda_host_device);
+
+ PP.Lex(Tok);
+ if (!Tok.is(tok::eod))
+ PP.Diag(FirstTok.getLocation(),
+ diag::warn_pragma_force_cuda_host_device_bad_arg);
+}
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index fa8eb12044be..30e392fa3c94 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -12,18 +12,15 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Parse/Parser.h"
#include "RAIIObjectsForParser.h"
-#include "clang/AST/ASTContext.h"
#include "clang/Basic/Attributes.h"
-#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/PrettyStackTrace.h"
+#include "clang/Parse/Parser.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"
-#include "llvm/ADT/SmallString.h"
using namespace clang;
//===----------------------------------------------------------------------===//
@@ -209,7 +206,8 @@ Retry:
}
default: {
- if ((getLangOpts().CPlusPlus || Allowed == ACK_Any) &&
+ if ((getLangOpts().CPlusPlus || getLangOpts().MicrosoftExt ||
+ Allowed == ACK_Any) &&
isDeclarationStatement()) {
SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
DeclGroupPtrTy Decl = ParseDeclaration(Declarator::BlockContext,
@@ -398,6 +396,8 @@ StmtResult Parser::ParseExprStatement() {
// If a case keyword is missing, this is where it should be inserted.
Token OldToken = Tok;
+ ExprStatementTokLoc = Tok.getLocation();
+
// expression[opt] ';'
ExprResult Expr(ParseExpression());
if (Expr.isInvalid()) {
diff --git a/lib/Parse/ParseStmtAsm.cpp b/lib/Parse/ParseStmtAsm.cpp
index 1f63dc257b86..293de78505ef 100644
--- a/lib/Parse/ParseStmtAsm.cpp
+++ b/lib/Parse/ParseStmtAsm.cpp
@@ -681,12 +681,12 @@ StmtResult Parser::ParseAsmStatement(bool &msAsm) {
// GNU asms accept, but warn, about type-qualifiers other than volatile.
if (DS.getTypeQualifiers() & DeclSpec::TQ_const)
- Diag(Loc, diag::w_asm_qualifier_ignored) << "const";
+ Diag(Loc, diag::warn_asm_qualifier_ignored) << "const";
if (DS.getTypeQualifiers() & DeclSpec::TQ_restrict)
- Diag(Loc, diag::w_asm_qualifier_ignored) << "restrict";
+ Diag(Loc, diag::warn_asm_qualifier_ignored) << "restrict";
// FIXME: Once GCC supports _Atomic, check whether it permits it here.
if (DS.getTypeQualifiers() & DeclSpec::TQ_atomic)
- Diag(Loc, diag::w_asm_qualifier_ignored) << "_Atomic";
+ Diag(Loc, diag::warn_asm_qualifier_ignored) << "_Atomic";
// Remember if this was a volatile asm.
bool isVolatile = DS.getTypeQualifiers() & DeclSpec::TQ_volatile;
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp
index 6cf7b6d3dc55..6a09ea7abca0 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/lib/Parse/ParseTemplate.cpp
@@ -11,12 +11,11 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Parse/Parser.h"
#include "RAIIObjectsForParser.h"
-#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Parse/Parser.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/Scope.h"
@@ -197,9 +196,12 @@ Parser::ParseSingleDeclarationAfterTemplate(
ParsedAttributesWithRange prefixAttrs(AttrFactory);
MaybeParseCXX11Attributes(prefixAttrs);
- if (Tok.is(tok::kw_using))
- return ParseUsingDirectiveOrDeclaration(Context, TemplateInfo, DeclEnd,
- prefixAttrs);
+ if (Tok.is(tok::kw_using)) {
+ // FIXME: We should return the DeclGroup to the caller.
+ ParseUsingDirectiveOrDeclaration(Context, TemplateInfo, DeclEnd,
+ prefixAttrs);
+ return nullptr;
+ }
// Parse the declaration specifiers, stealing any diagnostics from
// the template parameters.
diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp
index 7703c33b8780..0ea3f8d95179 100644
--- a/lib/Parse/ParseTentative.cpp
+++ b/lib/Parse/ParseTentative.cpp
@@ -74,11 +74,18 @@ bool Parser::isCXXDeclarationStatement() {
///
/// simple-declaration:
/// decl-specifier-seq init-declarator-list[opt] ';'
+/// decl-specifier-seq ref-qualifier[opt] '[' identifier-list ']'
+/// brace-or-equal-initializer ';' [C++17]
///
/// (if AllowForRangeDecl specified)
/// for ( for-range-declaration : for-range-initializer ) statement
+///
/// for-range-declaration:
-/// attribute-specifier-seqopt type-specifier-seq declarator
+/// decl-specifier-seq declarator
+/// decl-specifier-seq ref-qualifier[opt] '[' identifier-list ']'
+///
+/// In any of the above cases there can be a preceding attribute-specifier-seq,
+/// but the caller is expected to handle that.
bool Parser::isCXXSimpleDeclaration(bool AllowForRangeDecl) {
// C++ 6.8p1:
// There is an ambiguity in the grammar involving expression-statements and
@@ -902,7 +909,7 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
// '(' abstract-declarator ')'
if (Tok.isOneOf(tok::kw___attribute, tok::kw___declspec, tok::kw___cdecl,
tok::kw___stdcall, tok::kw___fastcall, tok::kw___thiscall,
- tok::kw___vectorcall))
+ tok::kw___regcall, tok::kw___vectorcall))
return TPResult::True; // attributes indicate declaration
TPResult TPR = TryParseDeclarator(mayBeAbstract, mayHaveIdentifier);
if (TPR != TPResult::Ambiguous)
@@ -1051,6 +1058,7 @@ Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) {
case tok::kw___stdcall:
case tok::kw___fastcall:
case tok::kw___thiscall:
+ case tok::kw___regcall:
case tok::kw___vectorcall:
case tok::kw___unaligned:
case tok::kw___vector:
@@ -1344,6 +1352,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
case tok::kw___stdcall:
case tok::kw___fastcall:
case tok::kw___thiscall:
+ case tok::kw___regcall:
case tok::kw___vectorcall:
case tok::kw___w64:
case tok::kw___sptr:
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index f968f995d53f..d8a4ea63153a 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -20,7 +20,6 @@
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/Scope.h"
-#include "llvm/Support/raw_ostream.h"
using namespace clang;
@@ -78,7 +77,6 @@ Parser::Parser(Preprocessor &pp, Sema &actions, bool skipFunctionBodies)
Tok.setKind(tok::eof);
Actions.CurScope = nullptr;
NumCachedScopes = 0;
- ParenCount = BracketCount = BraceCount = 0;
CurParsedObjCImpl = nullptr;
// Add #pragma handlers. These are removed and destroyed in the
@@ -474,6 +472,7 @@ void Parser::Initialize() {
Ident_final = nullptr;
Ident_sealed = nullptr;
Ident_override = nullptr;
+ Ident_GNU_final = nullptr;
Ident_super = &PP.getIdentifierTable().get("super");
@@ -537,6 +536,36 @@ void Parser::LateTemplateParserCleanupCallback(void *P) {
DestroyTemplateIdAnnotationsRAIIObj CleanupRAII(((Parser *)P)->TemplateIds);
}
+bool Parser::ParseFirstTopLevelDecl(DeclGroupPtrTy &Result) {
+ // C++ Modules TS: module-declaration must be the first declaration in the
+ // file. (There can be no preceding preprocessor directives, but we expect
+ // the lexer to check that.)
+ if (Tok.is(tok::kw_module)) {
+ Result = ParseModuleDecl();
+ return false;
+ } else if (getLangOpts().getCompilingModule() ==
+ LangOptions::CMK_ModuleInterface) {
+ // FIXME: We avoid providing this diagnostic when generating an object file
+ // from an existing PCM file. This is not a good way to detect this
+ // condition; we should provide a mechanism to indicate whether we've
+ // already parsed a declaration in this translation unit and avoid calling
+ // ParseFirstTopLevelDecl in that case.
+ if (Actions.TUKind == TU_Module)
+ Diag(Tok, diag::err_expected_module_interface_decl);
+ }
+
+ // C11 6.9p1 says translation units must have at least one top-level
+ // declaration. C++ doesn't have this restriction. We also don't want to
+ // complain if we have a precompiled header, although technically if the PCH
+ // is empty we should still emit the (pedantic) diagnostic.
+ bool NoTopLevelDecls = ParseTopLevelDecl(Result);
+ if (NoTopLevelDecls && !Actions.getASTContext().getExternalSource() &&
+ !getLangOpts().CPlusPlus)
+ Diag(diag::ext_empty_translation_unit);
+
+ return NoTopLevelDecls;
+}
+
/// ParseTopLevelDecl - Parse one top-level declaration, return whatever the
/// action tells us to. This returns true if the EOF was encountered.
bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) {
@@ -553,6 +582,10 @@ bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) {
HandlePragmaUnused();
return false;
+ case tok::kw_import:
+ Result = ParseModuleImport(SourceLocation());
+ return false;
+
case tok::annot_module_include:
Actions.ActOnModuleInclude(Tok.getLocation(),
reinterpret_cast<Module *>(
@@ -590,7 +623,6 @@ bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) {
ParsedAttributesWithRange attrs(AttrFactory);
MaybeParseCXX11Attributes(attrs);
- MaybeParseMicrosoftAttributes(attrs);
Result = ParseExternalDeclaration(attrs);
return false;
@@ -737,11 +769,17 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
: Sema::PCC_Namespace);
cutOffParsing();
return nullptr;
+ case tok::kw_export:
+ if (getLangOpts().ModulesTS) {
+ SingleDecl = ParseExportDeclaration();
+ break;
+ }
+ // This must be 'export template'. Parse it so we can diagnose our lack
+ // of support.
case tok::kw_using:
case tok::kw_namespace:
case tok::kw_typedef:
case tok::kw_template:
- case tok::kw_export: // As in 'export template'
case tok::kw_static_assert:
case tok::kw__Static_assert:
// A function definition cannot start with any of these keywords.
@@ -802,6 +840,11 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
ParseMicrosoftIfExistsExternalDeclaration();
return nullptr;
+ case tok::kw_module:
+ Diag(Tok, diag::err_unexpected_module_decl);
+ SkipUntil(tok::semi);
+ return nullptr;
+
default:
dont_know:
// We can't tell whether this is a function-definition or declaration yet.
@@ -853,11 +896,10 @@ bool Parser::isStartOfFunctionDefinition(const ParsingDeclarator &Declarator) {
Tok.is(tok::kw_try); // X() try { ... }
}
-/// ParseDeclarationOrFunctionDefinition - Parse either a function-definition or
-/// a declaration. We can't tell which we have until we read up to the
-/// compound-statement in function-definition. TemplateParams, if
-/// non-NULL, provides the template parameters when we're parsing a
-/// C++ template-declaration.
+/// Parse either a function-definition or a declaration. We can't tell which
+/// we have until we read up to the compound-statement in function-definition.
+/// TemplateParams, if non-NULL, provides the template parameters when we're
+/// parsing a C++ template-declaration.
///
/// function-definition: [C99 6.9.1]
/// decl-specs declarator declaration-list[opt] compound-statement
@@ -873,6 +915,7 @@ Parser::DeclGroupPtrTy
Parser::ParseDeclOrFunctionDefInternal(ParsedAttributesWithRange &attrs,
ParsingDeclSpec &DS,
AccessSpecifier AS) {
+ MaybeParseMicrosoftAttributes(DS.getAttributes());
// Parse the common declaration-specifiers piece.
ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS, DSC_top_level);
@@ -891,6 +934,8 @@ Parser::ParseDeclOrFunctionDefInternal(ParsedAttributesWithRange &attrs,
Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS_none,
DS, AnonRecord);
DS.complete(TheDecl);
+ if (getLangOpts().OpenCL)
+ Actions.setCurrentOpenCLExtensionForDecl(TheDecl);
if (AnonRecord) {
Decl* decls[] = {AnonRecord, TheDecl};
return Actions.BuildDeclaratorGroup(decls, /*TypeMayContainAuto=*/false);
@@ -952,7 +997,7 @@ Parser::ParseDeclarationOrFunctionDefinition(ParsedAttributesWithRange &attrs,
// parsing c constructs and re-enter objc container scope
// afterwards.
ObjCDeclContextSwitch ObjCDC(*this);
-
+
return ParseDeclOrFunctionDefInternal(attrs, PDS, AS);
}
}
@@ -1495,6 +1540,8 @@ Parser::TryAnnotateName(bool IsAddressOfOperand,
NewEndLoc);
if (NewType.isUsable())
Ty = NewType.get();
+ else if (Tok.is(tok::eof)) // Nothing to do here, bail out...
+ return ANK_Error;
}
Tok.setKind(tok::annot_typename);
@@ -1726,6 +1773,8 @@ bool Parser::TryAnnotateTypeOrScopeTokenAfterScopeSpec(bool EnteringContext,
NewEndLoc);
if (NewType.isUsable())
Ty = NewType.get();
+ else if (Tok.is(tok::eof)) // Nothing to do here, bail out...
+ return false;
}
// This is a typename. Replace the current token in-place with an
@@ -1988,7 +2037,6 @@ void Parser::ParseMicrosoftIfExistsExternalDeclaration() {
while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
ParsedAttributesWithRange attrs(AttrFactory);
MaybeParseCXX11Attributes(attrs);
- MaybeParseMicrosoftAttributes(attrs);
DeclGroupPtrTy Result = ParseExternalDeclaration(attrs);
if (Result && !getCurScope()->getParent())
Actions.getASTConsumer().HandleTopLevelDecl(Result.get());
@@ -1996,51 +2044,122 @@ void Parser::ParseMicrosoftIfExistsExternalDeclaration() {
Braces.consumeClose();
}
+/// Parse a C++ Modules TS module declaration, which appears at the beginning
+/// of a module interface, module partition, or module implementation file.
+///
+/// module-declaration: [Modules TS + P0273R0]
+/// 'module' module-kind[opt] module-name attribute-specifier-seq[opt] ';'
+/// module-kind:
+/// 'implementation'
+/// 'partition'
+///
+/// Note that the module-kind values are context-sensitive keywords.
+Parser::DeclGroupPtrTy Parser::ParseModuleDecl() {
+ assert(Tok.is(tok::kw_module) && getLangOpts().ModulesTS &&
+ "should not be parsing a module declaration");
+ SourceLocation ModuleLoc = ConsumeToken();
+
+ // Check for a module-kind.
+ Sema::ModuleDeclKind MDK = Sema::ModuleDeclKind::Module;
+ if (Tok.is(tok::identifier) && NextToken().is(tok::identifier)) {
+ if (Tok.getIdentifierInfo()->isStr("implementation"))
+ MDK = Sema::ModuleDeclKind::Implementation;
+ else if (Tok.getIdentifierInfo()->isStr("partition"))
+ MDK = Sema::ModuleDeclKind::Partition;
+ else {
+ Diag(Tok, diag::err_unexpected_module_kind) << Tok.getIdentifierInfo();
+ SkipUntil(tok::semi);
+ return nullptr;
+ }
+ ConsumeToken();
+ }
+
+ SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> Path;
+ if (ParseModuleName(ModuleLoc, Path, /*IsImport*/false))
+ return nullptr;
+
+ ParsedAttributesWithRange Attrs(AttrFactory);
+ MaybeParseCXX11Attributes(Attrs);
+ // We don't support any module attributes yet.
+ ProhibitCXX11Attributes(Attrs, diag::err_attribute_not_module_attr);
+
+ ExpectAndConsumeSemi(diag::err_module_expected_semi);
+
+ return Actions.ActOnModuleDecl(ModuleLoc, MDK, Path);
+}
+
+/// Parse a module import declaration. This is essentially the same for
+/// Objective-C and the C++ Modules TS, except for the leading '@' (in ObjC)
+/// and the trailing optional attributes (in C++).
+///
+/// [ObjC] @import declaration:
+/// '@' 'import' module-name ';'
+/// [ModTS] module-import-declaration:
+/// 'import' module-name attribute-specifier-seq[opt] ';'
Parser::DeclGroupPtrTy Parser::ParseModuleImport(SourceLocation AtLoc) {
- assert(Tok.isObjCAtKeyword(tok::objc_import) &&
+ assert((AtLoc.isInvalid() ? Tok.is(tok::kw_import)
+ : Tok.isObjCAtKeyword(tok::objc_import)) &&
"Improper start to module import");
SourceLocation ImportLoc = ConsumeToken();
+ SourceLocation StartLoc = AtLoc.isInvalid() ? ImportLoc : AtLoc;
SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> Path;
-
+ if (ParseModuleName(ImportLoc, Path, /*IsImport*/true))
+ return nullptr;
+
+ ParsedAttributesWithRange Attrs(AttrFactory);
+ MaybeParseCXX11Attributes(Attrs);
+ // We don't support any module import attributes yet.
+ ProhibitCXX11Attributes(Attrs, diag::err_attribute_not_import_attr);
+
+ if (PP.hadModuleLoaderFatalFailure()) {
+ // With a fatal failure in the module loader, we abort parsing.
+ cutOffParsing();
+ return nullptr;
+ }
+
+ DeclResult Import = Actions.ActOnModuleImport(StartLoc, ImportLoc, Path);
+ ExpectAndConsumeSemi(diag::err_module_expected_semi);
+ if (Import.isInvalid())
+ return nullptr;
+
+ return Actions.ConvertDeclToDeclGroup(Import.get());
+}
+
+/// Parse a C++ Modules TS / Objective-C module name (both forms use the same
+/// grammar).
+///
+/// module-name:
+/// module-name-qualifier[opt] identifier
+/// module-name-qualifier:
+/// module-name-qualifier[opt] identifier '.'
+bool Parser::ParseModuleName(
+ SourceLocation UseLoc,
+ SmallVectorImpl<std::pair<IdentifierInfo *, SourceLocation>> &Path,
+ bool IsImport) {
// Parse the module path.
- do {
+ while (true) {
if (!Tok.is(tok::identifier)) {
if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteModuleImport(ImportLoc, Path);
+ Actions.CodeCompleteModuleImport(UseLoc, Path);
cutOffParsing();
- return nullptr;
+ return true;
}
- Diag(Tok, diag::err_module_expected_ident);
+ Diag(Tok, diag::err_module_expected_ident) << IsImport;
SkipUntil(tok::semi);
- return nullptr;
+ return true;
}
// Record this part of the module path.
Path.push_back(std::make_pair(Tok.getIdentifierInfo(), Tok.getLocation()));
ConsumeToken();
-
- if (Tok.is(tok::period)) {
- ConsumeToken();
- continue;
- }
-
- break;
- } while (true);
- if (PP.hadModuleLoaderFatalFailure()) {
- // With a fatal failure in the module loader, we abort parsing.
- cutOffParsing();
- return nullptr;
- }
-
- DeclResult Import = Actions.ActOnModuleImport(AtLoc, ImportLoc, Path);
- ExpectAndConsumeSemi(diag::err_module_expected_semi);
- if (Import.isInvalid())
- return nullptr;
+ if (Tok.isNot(tok::period))
+ return false;
- return Actions.ConvertDeclToDeclGroup(Import.get());
+ ConsumeToken();
+ }
}
/// \brief Try recover parser when module annotation appears where it must not
@@ -2051,19 +2170,35 @@ bool Parser::parseMisplacedModuleImport() {
while (true) {
switch (Tok.getKind()) {
case tok::annot_module_end:
+ // If we recovered from a misplaced module begin, we expect to hit a
+ // misplaced module end too. Stay in the current context when this
+ // happens.
+ if (MisplacedModuleBeginCount) {
+ --MisplacedModuleBeginCount;
+ Actions.ActOnModuleEnd(Tok.getLocation(),
+ reinterpret_cast<Module *>(
+ Tok.getAnnotationValue()));
+ ConsumeToken();
+ continue;
+ }
// Inform caller that recovery failed, the error must be handled at upper
- // level.
+ // level. This will generate the desired "missing '}' at end of module"
+ // diagnostics on the way out.
return true;
case tok::annot_module_begin:
- Actions.diagnoseMisplacedModuleImport(reinterpret_cast<Module *>(
- Tok.getAnnotationValue()), Tok.getLocation());
- return true;
+ // Recover by entering the module (Sema will diagnose).
+ Actions.ActOnModuleBegin(Tok.getLocation(),
+ reinterpret_cast<Module *>(
+ Tok.getAnnotationValue()));
+ ConsumeToken();
+ ++MisplacedModuleBeginCount;
+ continue;
case tok::annot_module_include:
// Module import found where it should not be, for instance, inside a
// namespace. Recover by importing the module.
Actions.ActOnModuleInclude(Tok.getLocation(),
reinterpret_cast<Module *>(
- Tok.getAnnotationValue()));
+ Tok.getAnnotationValue()));
ConsumeToken();
// If there is another module import, process it.
continue;
diff --git a/lib/Rewrite/HTMLRewrite.cpp b/lib/Rewrite/HTMLRewrite.cpp
index 2d82d8fd4bd1..27bb976a6e1a 100644
--- a/lib/Rewrite/HTMLRewrite.cpp
+++ b/lib/Rewrite/HTMLRewrite.cpp
@@ -267,8 +267,8 @@ void html::AddLineNumbers(Rewriter& R, FileID FID) {
RB.InsertTextAfter(FileEnd - FileBeg, "</table>");
}
-void html::AddHeaderFooterInternalBuiltinCSS(Rewriter& R, FileID FID,
- const char *title) {
+void html::AddHeaderFooterInternalBuiltinCSS(Rewriter &R, FileID FID,
+ StringRef title) {
const llvm::MemoryBuffer *Buf = R.getSourceMgr().getBuffer(FID);
const char* FileStart = Buf->getBufferStart();
@@ -282,7 +282,7 @@ void html::AddHeaderFooterInternalBuiltinCSS(Rewriter& R, FileID FID,
os << "<!doctype html>\n" // Use HTML 5 doctype
"<html>\n<head>\n";
- if (title)
+ if (!title.empty())
os << "<title>" << html::EscapeText(title) << "</title>\n";
os << "<style type=\"text/css\">\n"
@@ -301,6 +301,7 @@ void html::AddHeaderFooterInternalBuiltinCSS(Rewriter& R, FileID FID,
" .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.
@@ -311,7 +312,9 @@ void html::AddHeaderFooterInternalBuiltinCSS(Rewriter& R, FileID FID,
" .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"
@@ -321,11 +324,13 @@ void html::AddHeaderFooterInternalBuiltinCSS(Rewriter& R, FileID FID,
" .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"
@@ -339,8 +344,12 @@ void html::AddHeaderFooterInternalBuiltinCSS(Rewriter& R, FileID FID,
" border-collapse: collapse; border-spacing: 0px;\n"
" }\n"
" td.rowname {\n"
- " text-align:right; font-weight:bold; color:#444444;\n"
- " padding-right:2ex; }\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>";
// Generate header
diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp
index 67762bde3439..5953d020b4fb 100644
--- a/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/lib/Sema/AnalysisBasedWarnings.cpp
@@ -37,12 +37,8 @@
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaInternal.h"
-#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/BitVector.h"
-#include "llvm/ADT/FoldingSet.h"
-#include "llvm/ADT/ImmutableMap.h"
#include "llvm/ADT/MapVector.h"
-#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
@@ -50,7 +46,6 @@
#include <algorithm>
#include <deque>
#include <iterator>
-#include <vector>
using namespace clang;
@@ -370,7 +365,7 @@ static ControlFlowKind CheckFallThrough(AnalysisDeclContext &AC) {
CFGStmt CS = ri->castAs<CFGStmt>();
const Stmt *S = CS.getStmt();
- if (isa<ReturnStmt>(S)) {
+ if (isa<ReturnStmt>(S) || isa<CoreturnStmt>(S)) {
HasLiveReturn = true;
continue;
}
@@ -421,7 +416,7 @@ struct CheckFallThroughDiagnostics {
unsigned diag_AlwaysFallThrough_HasNoReturn;
unsigned diag_AlwaysFallThrough_ReturnsNonVoid;
unsigned diag_NeverFallThroughOrReturn;
- enum { Function, Block, Lambda } funMode;
+ enum { Function, Block, Lambda, Coroutine } funMode;
SourceLocation FuncLoc;
static CheckFallThroughDiagnostics MakeForFunction(const Decl *Func) {
@@ -457,6 +452,19 @@ struct CheckFallThroughDiagnostics {
return D;
}
+ static CheckFallThroughDiagnostics MakeForCoroutine(const Decl *Func) {
+ CheckFallThroughDiagnostics D;
+ D.FuncLoc = Func->getLocation();
+ D.diag_MaybeFallThrough_HasNoReturn = 0;
+ D.diag_MaybeFallThrough_ReturnsNonVoid =
+ diag::warn_maybe_falloff_nonvoid_coroutine;
+ D.diag_AlwaysFallThrough_HasNoReturn = 0;
+ D.diag_AlwaysFallThrough_ReturnsNonVoid =
+ diag::warn_falloff_nonvoid_coroutine;
+ D.funMode = Coroutine;
+ return D;
+ }
+
static CheckFallThroughDiagnostics MakeForBlock() {
CheckFallThroughDiagnostics D;
D.diag_MaybeFallThrough_HasNoReturn =
@@ -499,7 +507,13 @@ struct CheckFallThroughDiagnostics {
(!ReturnsVoid ||
D.isIgnored(diag::warn_suggest_noreturn_block, FuncLoc));
}
-
+ if (funMode == Coroutine) {
+ return (ReturnsVoid ||
+ D.isIgnored(diag::warn_maybe_falloff_nonvoid_function, FuncLoc) ||
+ D.isIgnored(diag::warn_maybe_falloff_nonvoid_coroutine,
+ FuncLoc)) &&
+ (!HasNoReturn);
+ }
// For blocks / lambdas.
return ReturnsVoid && !HasNoReturn;
}
@@ -519,11 +533,14 @@ static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body,
bool ReturnsVoid = false;
bool HasNoReturn = false;
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
- ReturnsVoid = FD->getReturnType()->isVoidType();
+ if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
+ if (const auto *CBody = dyn_cast<CoroutineBodyStmt>(Body))
+ ReturnsVoid = CBody->getFallthroughHandler() != nullptr;
+ else
+ ReturnsVoid = FD->getReturnType()->isVoidType();
HasNoReturn = FD->isNoReturn();
}
- else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
+ else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
ReturnsVoid = MD->getReturnType()->isVoidType();
HasNoReturn = MD->hasAttr<NoReturnAttr>();
}
@@ -1991,13 +2008,22 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
// Warning: check missing 'return'
if (P.enableCheckFallThrough) {
+ auto IsCoro = [&]() {
+ if (auto *FD = dyn_cast<FunctionDecl>(D))
+ if (FD->getBody() && isa<CoroutineBodyStmt>(FD->getBody()))
+ return true;
+ return false;
+ };
const CheckFallThroughDiagnostics &CD =
- (isa<BlockDecl>(D) ? CheckFallThroughDiagnostics::MakeForBlock()
- : (isa<CXXMethodDecl>(D) &&
- cast<CXXMethodDecl>(D)->getOverloadedOperator() == OO_Call &&
- cast<CXXMethodDecl>(D)->getParent()->isLambda())
- ? CheckFallThroughDiagnostics::MakeForLambda()
- : CheckFallThroughDiagnostics::MakeForFunction(D));
+ (isa<BlockDecl>(D)
+ ? CheckFallThroughDiagnostics::MakeForBlock()
+ : (isa<CXXMethodDecl>(D) &&
+ cast<CXXMethodDecl>(D)->getOverloadedOperator() == OO_Call &&
+ cast<CXXMethodDecl>(D)->getParent()->isLambda())
+ ? CheckFallThroughDiagnostics::MakeForLambda()
+ : (IsCoro()
+ ? CheckFallThroughDiagnostics::MakeForCoroutine(D)
+ : CheckFallThroughDiagnostics::MakeForFunction(D)));
CheckFallThroughForBody(S, D, Body, blkExpr, CD, AC);
}
diff --git a/lib/Sema/AttributeList.cpp b/lib/Sema/AttributeList.cpp
index cae9393f9f3a..55e9601bf5e5 100644
--- a/lib/Sema/AttributeList.cpp
+++ b/lib/Sema/AttributeList.cpp
@@ -20,7 +20,6 @@
#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/SemaInternal.h"
#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/StringSwitch.h"
using namespace clang;
IdentifierLoc *IdentifierLoc::create(ASTContext &Ctx, SourceLocation Loc,
@@ -63,7 +62,7 @@ void *AttributeFactory::allocate(size_t size) {
}
// Otherwise, allocate something new.
- return Alloc.Allocate(size, llvm::AlignOf<AttributeFactory>::Alignment);
+ return Alloc.Allocate(size, alignof(AttributeFactory));
}
void AttributeFactory::reclaimPool(AttributeList *cur) {
diff --git a/lib/Sema/CodeCompleteConsumer.cpp b/lib/Sema/CodeCompleteConsumer.cpp
index 9a4f0d921bf4..f5b0104462f7 100644
--- a/lib/Sema/CodeCompleteConsumer.cpp
+++ b/lib/Sema/CodeCompleteConsumer.cpp
@@ -17,6 +17,7 @@
#include "clang/AST/DeclTemplate.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/Sema.h"
+#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Twine.h"
@@ -327,9 +328,9 @@ StringRef CodeCompletionTUInfo::getParentName(const DeclContext *DC) {
CodeCompletionString *CodeCompletionBuilder::TakeString() {
void *Mem = getAllocator().Allocate(
- sizeof(CodeCompletionString) + sizeof(Chunk) * Chunks.size()
- + sizeof(const char *) * Annotations.size(),
- llvm::alignOf<CodeCompletionString>());
+ sizeof(CodeCompletionString) + sizeof(Chunk) * Chunks.size() +
+ sizeof(const char *) * Annotations.size(),
+ alignof(CodeCompletionString));
CodeCompletionString *Result
= new (Mem) CodeCompletionString(Chunks.data(), Chunks.size(),
Priority, Availability,
@@ -428,6 +429,26 @@ CodeCompleteConsumer::OverloadCandidate::getFunctionType() const {
CodeCompleteConsumer::~CodeCompleteConsumer() { }
+bool PrintingCodeCompleteConsumer::isResultFilteredOut(StringRef Filter,
+ CodeCompletionResult Result) {
+ switch (Result.Kind) {
+ case CodeCompletionResult::RK_Declaration: {
+ return !(Result.Declaration->getIdentifier() &&
+ Result.Declaration->getIdentifier()->getName().startswith(Filter));
+ }
+ case CodeCompletionResult::RK_Keyword: {
+ return !StringRef(Result.Keyword).startswith(Filter);
+ }
+ case CodeCompletionResult::RK_Macro: {
+ return !Result.Macro->getName().startswith(Filter);
+ }
+ case CodeCompletionResult::RK_Pattern: {
+ return !StringRef(Result.Pattern->getAsString()).startswith(Filter);
+ }
+ }
+ llvm_unreachable("Unknown code completion result Kind.");
+}
+
void
PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
CodeCompletionContext Context,
@@ -435,8 +456,12 @@ PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
unsigned NumResults) {
std::stable_sort(Results, Results + NumResults);
+ StringRef Filter = SemaRef.getPreprocessor().getCodeCompletionFilter();
+
// Print the results.
for (unsigned I = 0; I != NumResults; ++I) {
+ if(!Filter.empty() && isResultFilteredOut(Filter, Results[I]))
+ continue;
OS << "COMPLETION: ";
switch (Results[I].Kind) {
case CodeCompletionResult::RK_Declaration:
diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp
index b9d2843b0558..a55cdcccee5d 100644
--- a/lib/Sema/DeclSpec.cpp
+++ b/lib/Sema/DeclSpec.cpp
@@ -173,6 +173,8 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto,
unsigned NumExceptions,
Expr *NoexceptExpr,
CachedTokens *ExceptionSpecTokens,
+ ArrayRef<NamedDecl*>
+ DeclsInPrototype,
SourceLocation LocalRangeBegin,
SourceLocation LocalRangeEnd,
Declarator &TheDeclarator,
@@ -204,7 +206,7 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto,
I.Fun.ExceptionSpecType = ESpecType;
I.Fun.ExceptionSpecLocBeg = ESpecRange.getBegin().getRawEncoding();
I.Fun.ExceptionSpecLocEnd = ESpecRange.getEnd().getRawEncoding();
- I.Fun.NumExceptions = 0;
+ I.Fun.NumExceptionsOrDecls = 0;
I.Fun.Exceptions = nullptr;
I.Fun.NoexceptExpr = nullptr;
I.Fun.HasTrailingReturnType = TrailingReturnType.isUsable() ||
@@ -220,16 +222,18 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto,
// parameter list there (in an effort to avoid new/delete traffic). If it
// is already used (consider a function returning a function pointer) or too
// small (function with too many parameters), go to the heap.
- if (!TheDeclarator.InlineParamsUsed &&
+ if (!TheDeclarator.InlineStorageUsed &&
NumParams <= llvm::array_lengthof(TheDeclarator.InlineParams)) {
I.Fun.Params = TheDeclarator.InlineParams;
+ new (I.Fun.Params) ParamInfo[NumParams];
I.Fun.DeleteParams = false;
- TheDeclarator.InlineParamsUsed = true;
+ TheDeclarator.InlineStorageUsed = true;
} else {
I.Fun.Params = new DeclaratorChunk::ParamInfo[NumParams];
I.Fun.DeleteParams = true;
}
- memcpy(I.Fun.Params, Params, sizeof(Params[0]) * NumParams);
+ for (unsigned i = 0; i < NumParams; i++)
+ I.Fun.Params[i] = std::move(Params[i]);
}
// Check what exception specification information we should actually store.
@@ -238,7 +242,7 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto,
case EST_Dynamic:
// new[] an exception array if needed
if (NumExceptions) {
- I.Fun.NumExceptions = NumExceptions;
+ I.Fun.NumExceptionsOrDecls = NumExceptions;
I.Fun.Exceptions = new DeclaratorChunk::TypeAndRange[NumExceptions];
for (unsigned i = 0; i != NumExceptions; ++i) {
I.Fun.Exceptions[i].Ty = Exceptions[i];
@@ -255,9 +259,52 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto,
I.Fun.ExceptionSpecTokens = ExceptionSpecTokens;
break;
}
+
+ if (!DeclsInPrototype.empty()) {
+ assert(ESpecType == EST_None && NumExceptions == 0 &&
+ "cannot have exception specifiers and decls in prototype");
+ I.Fun.NumExceptionsOrDecls = DeclsInPrototype.size();
+ // Copy the array of decls into stable heap storage.
+ I.Fun.DeclsInPrototype = new NamedDecl *[DeclsInPrototype.size()];
+ for (size_t J = 0; J < DeclsInPrototype.size(); ++J)
+ I.Fun.DeclsInPrototype[J] = DeclsInPrototype[J];
+ }
+
return I;
}
+void Declarator::setDecompositionBindings(
+ SourceLocation LSquareLoc,
+ ArrayRef<DecompositionDeclarator::Binding> Bindings,
+ SourceLocation RSquareLoc) {
+ assert(!hasName() && "declarator given multiple names!");
+
+ BindingGroup.LSquareLoc = LSquareLoc;
+ BindingGroup.RSquareLoc = RSquareLoc;
+ BindingGroup.NumBindings = Bindings.size();
+ Range.setEnd(RSquareLoc);
+
+ // We're now past the identifier.
+ SetIdentifier(nullptr, LSquareLoc);
+ Name.EndLocation = RSquareLoc;
+
+ // Allocate storage for bindings and stash them away.
+ if (Bindings.size()) {
+ if (!InlineStorageUsed &&
+ Bindings.size() <= llvm::array_lengthof(InlineBindings)) {
+ BindingGroup.Bindings = InlineBindings;
+ BindingGroup.DeleteBindings = false;
+ InlineStorageUsed = true;
+ } else {
+ BindingGroup.Bindings =
+ new DecompositionDeclarator::Binding[Bindings.size()];
+ BindingGroup.DeleteBindings = true;
+ }
+ std::uninitialized_copy(Bindings.begin(), Bindings.end(),
+ BindingGroup.Bindings);
+ }
+}
+
bool Declarator::isDeclarationOfFunction() const {
for (unsigned i = 0, i_end = DeclTypeInfo.size(); i < i_end; ++i) {
switch (DeclTypeInfo[i].Kind) {
@@ -511,7 +558,7 @@ bool DeclSpec::SetStorageClassSpec(Sema &S, SCS SC, SourceLocation Loc,
// OpenCL v1.2 s6.8 changes this to "The auto and register storage-class
// specifiers are not supported."
if (S.getLangOpts().OpenCL &&
- !S.getOpenCLOptions().cl_clang_storage_class_specifiers) {
+ !S.getOpenCLOptions().isEnabled("cl_clang_storage_class_specifiers")) {
switch (SC) {
case SCS_extern:
case SCS_private_extern:
@@ -578,14 +625,16 @@ bool DeclSpec::SetTypeSpecWidth(TSW W, SourceLocation Loc,
const char *&PrevSpec,
unsigned &DiagID,
const PrintingPolicy &Policy) {
- // Overwrite TSWLoc only if TypeSpecWidth was unspecified, so that
+ // Overwrite TSWRange.Begin only if TypeSpecWidth was unspecified, so that
// for 'long long' we will keep the source location of the first 'long'.
if (TypeSpecWidth == TSW_unspecified)
- TSWLoc = Loc;
+ TSWRange.setBegin(Loc);
// Allow turning long -> long long.
else if (W != TSW_longlong || TypeSpecWidth != TSW_long)
return BadSpecifier(W, (TSW)TypeSpecWidth, PrevSpec, DiagID);
TypeSpecWidth = W;
+ // Remember location of the last 'long'
+ TSWRange.setEnd(Loc);
return false;
}
@@ -965,9 +1014,9 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
TypeQualifiers)) {
const unsigned NumLocs = 9;
SourceLocation ExtraLocs[NumLocs] = {
- TSWLoc, TSCLoc, TSSLoc, AltiVecLoc,
- TQ_constLoc, TQ_restrictLoc, TQ_volatileLoc, TQ_atomicLoc, TQ_unalignedLoc
- };
+ TSWRange.getBegin(), TSCLoc, TSSLoc,
+ AltiVecLoc, TQ_constLoc, TQ_restrictLoc,
+ TQ_volatileLoc, TQ_atomicLoc, TQ_unalignedLoc};
FixItHint Hints[NumLocs];
SourceLocation FirstLoc;
for (unsigned I = 0; I != NumLocs; ++I) {
@@ -1009,8 +1058,8 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
// Only 'short' and 'long long' are valid with vector bool. (PIM 2.1)
if ((TypeSpecWidth != TSW_unspecified) && (TypeSpecWidth != TSW_short) &&
(TypeSpecWidth != TSW_longlong))
- S.Diag(TSWLoc, diag::err_invalid_vector_bool_decl_spec)
- << getSpecifierName((TSW)TypeSpecWidth);
+ S.Diag(TSWRange.getBegin(), diag::err_invalid_vector_bool_decl_spec)
+ << getSpecifierName((TSW)TypeSpecWidth);
// vector bool long long requires VSX support or ZVector.
if ((TypeSpecWidth == TSW_longlong) &&
@@ -1027,7 +1076,8 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
// vector long double and vector long long double are never allowed.
// vector double is OK for Power7 and later, and ZVector.
if (TypeSpecWidth == TSW_long || TypeSpecWidth == TSW_longlong)
- S.Diag(TSWLoc, diag::err_invalid_vector_long_double_decl_spec);
+ S.Diag(TSWRange.getBegin(),
+ diag::err_invalid_vector_long_double_decl_spec);
else if (!S.Context.getTargetInfo().hasFeature("vsx") &&
!S.getLangOpts().ZVector)
S.Diag(TSTLoc, diag::err_invalid_vector_double_decl_spec);
@@ -1038,10 +1088,11 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
} else if (TypeSpecWidth == TSW_long) {
// vector long is unsupported for ZVector and deprecated for AltiVec.
if (S.getLangOpts().ZVector)
- S.Diag(TSWLoc, diag::err_invalid_vector_long_decl_spec);
+ S.Diag(TSWRange.getBegin(), diag::err_invalid_vector_long_decl_spec);
else
- S.Diag(TSWLoc, diag::warn_vector_long_decl_spec_combination)
- << getSpecifierName((TST)TypeSpecType, Policy);
+ S.Diag(TSWRange.getBegin(),
+ diag::warn_vector_long_decl_spec_combination)
+ << getSpecifierName((TST)TypeSpecType, Policy);
}
if (TypeAltiVecPixel) {
@@ -1074,8 +1125,8 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
if (TypeSpecType == TST_unspecified)
TypeSpecType = TST_int; // short -> short int, long long -> long long int.
else if (TypeSpecType != TST_int) {
- S.Diag(TSWLoc, diag::err_invalid_width_spec) << (int)TypeSpecWidth
- << getSpecifierName((TST)TypeSpecType, Policy);
+ S.Diag(TSWRange.getBegin(), diag::err_invalid_width_spec)
+ << (int)TypeSpecWidth << getSpecifierName((TST)TypeSpecType, Policy);
TypeSpecType = TST_int;
TypeSpecOwned = false;
}
@@ -1084,8 +1135,8 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
if (TypeSpecType == TST_unspecified)
TypeSpecType = TST_int; // long -> long int.
else if (TypeSpecType != TST_int && TypeSpecType != TST_double) {
- S.Diag(TSWLoc, diag::err_invalid_width_spec) << (int)TypeSpecWidth
- << getSpecifierName((TST)TypeSpecType, Policy);
+ S.Diag(TSWRange.getBegin(), diag::err_invalid_width_spec)
+ << (int)TypeSpecWidth << getSpecifierName((TST)TypeSpecType, Policy);
TypeSpecType = TST_int;
TypeSpecOwned = false;
}
@@ -1267,6 +1318,7 @@ bool VirtSpecifiers::SetSpecifier(Specifier VS, SourceLocation Loc,
switch (VS) {
default: llvm_unreachable("Unknown specifier!");
case VS_Override: VS_overrideLoc = Loc; break;
+ case VS_GNU_Final:
case VS_Sealed:
case VS_Final: VS_finalLoc = Loc; break;
}
@@ -1279,6 +1331,7 @@ const char *VirtSpecifiers::getSpecifierName(Specifier VS) {
default: llvm_unreachable("Unknown specifier");
case VS_Override: return "override";
case VS_Final: return "final";
+ case VS_GNU_Final: return "__final";
case VS_Sealed: return "sealed";
}
}
diff --git a/lib/Sema/DelayedDiagnostic.cpp b/lib/Sema/DelayedDiagnostic.cpp
index ceea04f276c9..2fa5718d4e9b 100644
--- a/lib/Sema/DelayedDiagnostic.cpp
+++ b/lib/Sema/DelayedDiagnostic.cpp
@@ -20,7 +20,7 @@ using namespace clang;
using namespace sema;
DelayedDiagnostic
-DelayedDiagnostic::makeAvailability(Sema::AvailabilityDiagnostic AD,
+DelayedDiagnostic::makeAvailability(AvailabilityResult AR,
SourceLocation Loc,
const NamedDecl *D,
const ObjCInterfaceDecl *UnknownObjCClass,
@@ -28,42 +28,33 @@ DelayedDiagnostic::makeAvailability(Sema::AvailabilityDiagnostic AD,
StringRef Msg,
bool ObjCPropertyAccess) {
DelayedDiagnostic DD;
- switch (AD) {
- case Sema::AD_Deprecation:
- DD.Kind = Deprecation;
- break;
- case Sema::AD_Unavailable:
- DD.Kind = Unavailable;
- break;
- case Sema::AD_Partial:
- llvm_unreachable("AD_Partial diags should not be delayed");
- }
+ DD.Kind = Availability;
DD.Triggered = false;
DD.Loc = Loc;
- DD.DeprecationData.Decl = D;
- DD.DeprecationData.UnknownObjCClass = UnknownObjCClass;
- DD.DeprecationData.ObjCProperty = ObjCProperty;
+ DD.AvailabilityData.Decl = D;
+ DD.AvailabilityData.UnknownObjCClass = UnknownObjCClass;
+ DD.AvailabilityData.ObjCProperty = ObjCProperty;
char *MessageData = nullptr;
if (Msg.size()) {
MessageData = new char [Msg.size()];
memcpy(MessageData, Msg.data(), Msg.size());
}
- DD.DeprecationData.Message = MessageData;
- DD.DeprecationData.MessageLen = Msg.size();
- DD.DeprecationData.ObjCPropertyAccess = ObjCPropertyAccess;
+ DD.AvailabilityData.Message = MessageData;
+ DD.AvailabilityData.MessageLen = Msg.size();
+ DD.AvailabilityData.AR = AR;
+ DD.AvailabilityData.ObjCPropertyAccess = ObjCPropertyAccess;
return DD;
}
void DelayedDiagnostic::Destroy() {
- switch (static_cast<DDKind>(Kind)) {
+ switch (Kind) {
case Access:
getAccessData().~AccessedEntity();
break;
- case Deprecation:
- case Unavailable:
- delete [] DeprecationData.Message;
+ case Availability:
+ delete[] AvailabilityData.Message;
break;
case ForbiddenType:
diff --git a/lib/Sema/JumpDiagnostics.cpp b/lib/Sema/JumpDiagnostics.cpp
index bdbe06c4969d..899d3fa83cc3 100644
--- a/lib/Sema/JumpDiagnostics.cpp
+++ b/lib/Sema/JumpDiagnostics.cpp
@@ -325,30 +325,27 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S,
case Stmt::IfStmtClass: {
IfStmt *IS = cast<IfStmt>(S);
- if (!IS->isConstexpr())
+ if (!(IS->isConstexpr() || IS->isObjCAvailabilityCheck()))
break;
+ unsigned Diag = IS->isConstexpr() ? diag::note_protected_by_constexpr_if
+ : diag::note_protected_by_if_available;
+
if (VarDecl *Var = IS->getConditionVariable())
BuildScopeInformation(Var, ParentScope);
// Cannot jump into the middle of the condition.
unsigned NewParentScope = Scopes.size();
- Scopes.push_back(GotoScope(ParentScope,
- diag::note_protected_by_constexpr_if, 0,
- IS->getLocStart()));
+ Scopes.push_back(GotoScope(ParentScope, Diag, 0, IS->getLocStart()));
BuildScopeInformation(IS->getCond(), NewParentScope);
// Jumps into either arm of an 'if constexpr' are not allowed.
NewParentScope = Scopes.size();
- Scopes.push_back(GotoScope(ParentScope,
- diag::note_protected_by_constexpr_if, 0,
- IS->getLocStart()));
+ Scopes.push_back(GotoScope(ParentScope, Diag, 0, IS->getLocStart()));
BuildScopeInformation(IS->getThen(), NewParentScope);
if (Stmt *Else = IS->getElse()) {
NewParentScope = Scopes.size();
- Scopes.push_back(GotoScope(ParentScope,
- diag::note_protected_by_constexpr_if, 0,
- IS->getLocStart()));
+ Scopes.push_back(GotoScope(ParentScope, Diag, 0, IS->getLocStart()));
BuildScopeInformation(Else, NewParentScope);
}
return;
@@ -553,10 +550,8 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S,
// order to avoid blowing out the stack.
while (true) {
Stmt *Next;
- if (CaseStmt *CS = dyn_cast<CaseStmt>(SubStmt))
- Next = CS->getSubStmt();
- else if (DefaultStmt *DS = dyn_cast<DefaultStmt>(SubStmt))
- Next = DS->getSubStmt();
+ if (SwitchCase *SC = dyn_cast<SwitchCase>(SubStmt))
+ Next = SC->getSubStmt();
else if (LabelStmt *LS = dyn_cast<LabelStmt>(SubStmt))
Next = LS->getSubStmt();
else
diff --git a/lib/Sema/MultiplexExternalSemaSource.cpp b/lib/Sema/MultiplexExternalSemaSource.cpp
index eee4c00324ba..077a56ff8e7f 100644
--- a/lib/Sema/MultiplexExternalSemaSource.cpp
+++ b/lib/Sema/MultiplexExternalSemaSource.cpp
@@ -285,7 +285,8 @@ void MultiplexExternalSemaSource::ReadPendingInstantiations(
}
void MultiplexExternalSemaSource::ReadLateParsedTemplates(
- llvm::MapVector<const FunctionDecl *, LateParsedTemplate *> &LPTMap) {
+ llvm::MapVector<const FunctionDecl *, std::unique_ptr<LateParsedTemplate>>
+ &LPTMap) {
for (size_t i = 0; i < Sources.size(); ++i)
Sources[i]->ReadLateParsedTemplates(LPTMap);
}
diff --git a/lib/Sema/ScopeInfo.cpp b/lib/Sema/ScopeInfo.cpp
index 4b2e13e20deb..3970b4136982 100644
--- a/lib/Sema/ScopeInfo.cpp
+++ b/lib/Sema/ScopeInfo.cpp
@@ -29,6 +29,8 @@ void FunctionScopeInfo::Clear() {
HasIndirectGoto = false;
HasDroppedStmt = false;
HasOMPDeclareReductionCombiner = false;
+ HasFallthroughStmt = false;
+ HasPotentialAvailabilityViolations = false;
ObjCShouldCallSuper = false;
ObjCIsDesignatedInit = false;
ObjCWarnForNoDesignatedInitChain = false;
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index 777747606304..412f944f89c0 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -12,7 +12,6 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Sema/SemaInternal.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTDiagnostic.h"
#include "clang/AST/DeclCXX.h"
@@ -22,7 +21,6 @@
#include "clang/AST/ExprCXX.h"
#include "clang/AST/StmtCXX.h"
#include "clang/Basic/DiagnosticOptions.h"
-#include "clang/Basic/FileManager.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/HeaderSearch.h"
@@ -30,14 +28,15 @@
#include "clang/Sema/CXXFieldCollector.h"
#include "clang/Sema/DelayedDiagnostic.h"
#include "clang/Sema/ExternalSemaSource.h"
+#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 "llvm/ADT/APFloat.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallSet.h"
using namespace clang;
@@ -89,15 +88,14 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
VisContext(nullptr),
IsBuildingRecoveryCallExpr(false),
Cleanup{}, LateTemplateParser(nullptr),
- LateTemplateParserCleanup(nullptr),
- OpaqueParser(nullptr), IdResolver(pp), StdInitializerList(nullptr),
+ LateTemplateParserCleanup(nullptr), OpaqueParser(nullptr), IdResolver(pp),
+ StdExperimentalNamespaceCache(nullptr), StdInitializerList(nullptr),
CXXTypeInfoDecl(nullptr), MSVCGuidDecl(nullptr),
NSNumberDecl(nullptr), NSValueDecl(nullptr),
NSStringDecl(nullptr), StringWithUTF8StringMethod(nullptr),
ValueWithBytesObjCTypeMethod(nullptr),
NSArrayDecl(nullptr), ArrayWithObjectsMethod(nullptr),
NSDictionaryDecl(nullptr), DictionaryWithObjectsMethod(nullptr),
- MSAsmLabelNameCounter(0),
GlobalNewDeleteDeclared(false),
TUKind(TUKind),
NumSFINAEErrors(0),
@@ -209,14 +207,11 @@ void Sema::Initialize() {
addImplicitTypedef("size_t", Context.getSizeType());
}
- // Initialize predefined OpenCL types and supported optional core features.
+ // Initialize predefined OpenCL types and supported extensions and (optional)
+ // core features.
if (getLangOpts().OpenCL) {
-#define OPENCLEXT(Ext) \
- if (Context.getTargetInfo().getSupportedOpenCLOpts().is_##Ext##_supported_core( \
- getLangOpts().OpenCLVersion)) \
- getOpenCLOptions().Ext = 1;
-#include "clang/Basic/OpenCLExtensions.def"
-
+ getOpenCLOptions().addSupport(Context.getTargetInfo().getSupportedOpenCLOpts());
+ getOpenCLOptions().enableSupportedCore(getLangOpts().OpenCLVersion);
addImplicitTypedef("sampler_t", Context.OCLSamplerTy);
addImplicitTypedef("event_t", Context.OCLEventTy);
if (getLangOpts().OpenCLVersion >= 200) {
@@ -227,26 +222,60 @@ void Sema::Initialize() {
addImplicitTypedef("atomic_int", Context.getAtomicType(Context.IntTy));
addImplicitTypedef("atomic_uint",
Context.getAtomicType(Context.UnsignedIntTy));
- addImplicitTypedef("atomic_long", Context.getAtomicType(Context.LongTy));
- addImplicitTypedef("atomic_ulong",
- Context.getAtomicType(Context.UnsignedLongTy));
+ auto AtomicLongT = Context.getAtomicType(Context.LongTy);
+ addImplicitTypedef("atomic_long", AtomicLongT);
+ auto AtomicULongT = Context.getAtomicType(Context.UnsignedLongTy);
+ addImplicitTypedef("atomic_ulong", AtomicULongT);
addImplicitTypedef("atomic_float",
Context.getAtomicType(Context.FloatTy));
- addImplicitTypedef("atomic_double",
- Context.getAtomicType(Context.DoubleTy));
+ auto AtomicDoubleT = Context.getAtomicType(Context.DoubleTy);
+ addImplicitTypedef("atomic_double", AtomicDoubleT);
// OpenCLC v2.0, s6.13.11.6 requires that atomic_flag is implemented as
// 32-bit integer and OpenCLC v2.0, s6.1.1 int is always 32-bit wide.
addImplicitTypedef("atomic_flag", Context.getAtomicType(Context.IntTy));
- addImplicitTypedef("atomic_intptr_t",
- Context.getAtomicType(Context.getIntPtrType()));
- addImplicitTypedef("atomic_uintptr_t",
- Context.getAtomicType(Context.getUIntPtrType()));
- addImplicitTypedef("atomic_size_t",
- Context.getAtomicType(Context.getSizeType()));
- addImplicitTypedef("atomic_ptrdiff_t",
- Context.getAtomicType(Context.getPointerDiffType()));
+ auto AtomicIntPtrT = Context.getAtomicType(Context.getIntPtrType());
+ addImplicitTypedef("atomic_intptr_t", AtomicIntPtrT);
+ auto AtomicUIntPtrT = Context.getAtomicType(Context.getUIntPtrType());
+ addImplicitTypedef("atomic_uintptr_t", AtomicUIntPtrT);
+ auto AtomicSizeT = Context.getAtomicType(Context.getSizeType());
+ addImplicitTypedef("atomic_size_t", AtomicSizeT);
+ auto AtomicPtrDiffT = Context.getAtomicType(Context.getPointerDiffType());
+ addImplicitTypedef("atomic_ptrdiff_t", AtomicPtrDiffT);
+
+ // OpenCL v2.0 s6.13.11.6:
+ // - The atomic_long and atomic_ulong types are supported if the
+ // cl_khr_int64_base_atomics and cl_khr_int64_extended_atomics
+ // extensions are supported.
+ // - The atomic_double type is only supported if double precision
+ // is supported and the cl_khr_int64_base_atomics and
+ // cl_khr_int64_extended_atomics extensions are supported.
+ // - If the device address space is 64-bits, the data types
+ // atomic_intptr_t, atomic_uintptr_t, atomic_size_t and
+ // atomic_ptrdiff_t are supported if the cl_khr_int64_base_atomics and
+ // cl_khr_int64_extended_atomics extensions are supported.
+ std::vector<QualType> Atomic64BitTypes;
+ Atomic64BitTypes.push_back(AtomicLongT);
+ Atomic64BitTypes.push_back(AtomicULongT);
+ Atomic64BitTypes.push_back(AtomicDoubleT);
+ if (Context.getTypeSize(AtomicSizeT) == 64) {
+ Atomic64BitTypes.push_back(AtomicSizeT);
+ Atomic64BitTypes.push_back(AtomicIntPtrT);
+ Atomic64BitTypes.push_back(AtomicUIntPtrT);
+ Atomic64BitTypes.push_back(AtomicPtrDiffT);
+ }
+ for (auto &I : Atomic64BitTypes)
+ setOpenCLExtensionForType(I,
+ "cl_khr_int64_base_atomics cl_khr_int64_extended_atomics");
+
+ setOpenCLExtensionForType(AtomicDoubleT, "cl_khr_fp64");
}
- }
+
+ setOpenCLExtensionForType(Context.DoubleTy, "cl_khr_fp64");
+
+#define GENERIC_IMAGE_TYPE_EXT(Type, Id, Ext) \
+ setOpenCLExtensionForType(Context.Id, Ext);
+#include "clang/Basic/OpenCLImageTypes.def"
+ };
if (Context.getTargetInfo().hasBuiltinMSVaList()) {
DeclarationName MSVaList = &Context.Idents.get("__builtin_ms_va_list");
@@ -260,7 +289,6 @@ void Sema::Initialize() {
}
Sema::~Sema() {
- llvm::DeleteContainerSeconds(LateParsedTemplateMap);
if (VisContext) FreeVisContext();
// Kill all the active scopes.
for (unsigned I = 1, E = FunctionScopes.size(); I != E; ++I)
@@ -393,6 +421,18 @@ ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty,
if (ExprTy == TypeTy)
return E;
+ // C++1z [conv.array]: The temporary materialization conversion is applied.
+ // We also use this to fuel C++ DR1213, which applies to C++11 onwards.
+ if (Kind == CK_ArrayToPointerDecay && getLangOpts().CPlusPlus &&
+ E->getValueKind() == VK_RValue) {
+ // The temporary is an lvalue in C++98 and an xvalue otherwise.
+ ExprResult Materialized = CreateMaterializeTemporaryExpr(
+ E->getType(), E, !getLangOpts().CPlusPlus11);
+ if (Materialized.isInvalid())
+ return ExprError();
+ E = Materialized.get();
+ }
+
if (ImplicitCastExpr *ImpCast = dyn_cast<ImplicitCastExpr>(E)) {
if (ImpCast->getCastKind() == Kind && (!BasePath || BasePath->empty())) {
ImpCast->setType(Ty);
@@ -710,7 +750,8 @@ void Sema::ActOnEndOfTranslationUnit() {
if (TUKind == TU_Prefix) {
// Translation unit prefixes don't need any of the checking below.
- TUScope = nullptr;
+ if (!PP.isIncrementalProcessingEnabled())
+ TUScope = nullptr;
return;
}
@@ -811,6 +852,7 @@ void Sema::ActOnEndOfTranslationUnit() {
diag::err_tentative_def_incomplete_type))
VD->setInvalidDecl();
+ // No initialization is performed for a tentative definition.
CheckCompleteVariableDeclaration(VD);
// Notify the consumer that we've completed a tentative definition.
@@ -865,8 +907,11 @@ void Sema::ActOnEndOfTranslationUnit() {
Diag(DiagD->getLocation(), diag::warn_unneeded_internal_decl)
<< /*variable*/1 << DiagD->getDeclName();
} else if (DiagD->getType().isConstQualified()) {
- Diag(DiagD->getLocation(), diag::warn_unused_const_variable)
- << DiagD->getDeclName();
+ const SourceManager &SM = SourceMgr;
+ if (SM.getMainFileID() != SM.getFileID(DiagD->getLocation()) ||
+ !PP.getLangOpts().IsHeaderFile)
+ Diag(DiagD->getLocation(), diag::warn_unused_const_variable)
+ << DiagD->getDeclName();
} else {
Diag(DiagD->getLocation(), diag::warn_unused_variable)
<< DiagD->getDeclName();
@@ -909,7 +954,8 @@ void Sema::ActOnEndOfTranslationUnit() {
assert(ParsingInitForAutoVars.empty() &&
"Didn't unmark var as having its initializer parsed");
- TUScope = nullptr;
+ if (!PP.isIncrementalProcessingEnabled())
+ TUScope = nullptr;
}
@@ -1527,3 +1573,85 @@ const llvm::MapVector<FieldDecl *, Sema::DeleteLocs> &
Sema::getMismatchingDeleteExpressions() const {
return DeleteExprs;
}
+
+void Sema::setOpenCLExtensionForType(QualType T, llvm::StringRef ExtStr) {
+ if (ExtStr.empty())
+ return;
+ llvm::SmallVector<StringRef, 1> Exts;
+ ExtStr.split(Exts, " ", /* limit */ -1, /* keep empty */ false);
+ auto CanT = T.getCanonicalType().getTypePtr();
+ for (auto &I : Exts)
+ OpenCLTypeExtMap[CanT].insert(I.str());
+}
+
+void Sema::setOpenCLExtensionForDecl(Decl *FD, StringRef ExtStr) {
+ llvm::SmallVector<StringRef, 1> Exts;
+ ExtStr.split(Exts, " ", /* limit */ -1, /* keep empty */ false);
+ if (Exts.empty())
+ return;
+ for (auto &I : Exts)
+ OpenCLDeclExtMap[FD].insert(I.str());
+}
+
+void Sema::setCurrentOpenCLExtensionForType(QualType T) {
+ if (CurrOpenCLExtension.empty())
+ return;
+ setOpenCLExtensionForType(T, CurrOpenCLExtension);
+}
+
+void Sema::setCurrentOpenCLExtensionForDecl(Decl *D) {
+ if (CurrOpenCLExtension.empty())
+ return;
+ setOpenCLExtensionForDecl(D, CurrOpenCLExtension);
+}
+
+bool Sema::isOpenCLDisabledDecl(Decl *FD) {
+ auto Loc = OpenCLDeclExtMap.find(FD);
+ if (Loc == OpenCLDeclExtMap.end())
+ return false;
+ for (auto &I : Loc->second) {
+ if (!getOpenCLOptions().isEnabled(I))
+ return true;
+ }
+ return false;
+}
+
+template <typename T, typename DiagLocT, typename DiagInfoT, typename MapT>
+bool Sema::checkOpenCLDisabledTypeOrDecl(T D, DiagLocT DiagLoc,
+ DiagInfoT DiagInfo, MapT &Map,
+ unsigned Selector,
+ SourceRange SrcRange) {
+ auto Loc = Map.find(D);
+ if (Loc == Map.end())
+ return false;
+ bool Disabled = false;
+ for (auto &I : Loc->second) {
+ if (I != CurrOpenCLExtension && !getOpenCLOptions().isEnabled(I)) {
+ Diag(DiagLoc, diag::err_opencl_requires_extension) << Selector << DiagInfo
+ << I << SrcRange;
+ Disabled = true;
+ }
+ }
+ return Disabled;
+}
+
+bool Sema::checkOpenCLDisabledTypeDeclSpec(const DeclSpec &DS, QualType QT) {
+ // Check extensions for declared types.
+ Decl *Decl = nullptr;
+ if (auto TypedefT = dyn_cast<TypedefType>(QT.getTypePtr()))
+ Decl = TypedefT->getDecl();
+ if (auto TagT = dyn_cast<TagType>(QT.getCanonicalType().getTypePtr()))
+ Decl = TagT->getDecl();
+ auto Loc = DS.getTypeSpecTypeLoc();
+ if (checkOpenCLDisabledTypeOrDecl(Decl, Loc, QT, OpenCLDeclExtMap))
+ return true;
+
+ // Check extensions for builtin types.
+ return checkOpenCLDisabledTypeOrDecl(QT.getCanonicalType().getTypePtr(), Loc,
+ QT, OpenCLTypeExtMap);
+}
+
+bool Sema::checkOpenCLDisabledDecl(const Decl &D, const Expr &E) {
+ return checkOpenCLDisabledTypeOrDecl(&D, E.getLocStart(), "",
+ OpenCLDeclExtMap, 1, D.getSourceRange());
+}
diff --git a/lib/Sema/SemaAttr.cpp b/lib/Sema/SemaAttr.cpp
index 0d7fba5c6709..bad9e7024267 100644
--- a/lib/Sema/SemaAttr.cpp
+++ b/lib/Sema/SemaAttr.cpp
@@ -12,13 +12,13 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Sema/SemaInternal.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Expr.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Lookup.h"
+#include "clang/Sema/SemaInternal.h"
using namespace clang;
//===----------------------------------------------------------------------===//
diff --git a/lib/Sema/SemaCUDA.cpp b/lib/Sema/SemaCUDA.cpp
index 90af6d5a927f..6f272ec839f5 100644
--- a/lib/Sema/SemaCUDA.cpp
+++ b/lib/Sema/SemaCUDA.cpp
@@ -18,11 +18,25 @@
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Sema.h"
#include "clang/Sema/SemaDiagnostic.h"
+#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Template.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
using namespace clang;
+void Sema::PushForceCUDAHostDevice() {
+ assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
+ ForceCUDAHostDeviceDepth++;
+}
+
+bool Sema::PopForceCUDAHostDevice() {
+ assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
+ if (ForceCUDAHostDeviceDepth == 0)
+ return false;
+ ForceCUDAHostDeviceDepth--;
+ return true;
+}
+
ExprResult Sema::ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc,
MultiExprArg ExecConfig,
SourceLocation GGGLoc) {
@@ -40,21 +54,73 @@ ExprResult Sema::ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc,
/*IsExecConfig=*/true);
}
+Sema::CUDAFunctionTarget Sema::IdentifyCUDATarget(const AttributeList *Attr) {
+ bool HasHostAttr = false;
+ bool HasDeviceAttr = false;
+ bool HasGlobalAttr = false;
+ bool HasInvalidTargetAttr = false;
+ while (Attr) {
+ switch(Attr->getKind()){
+ case AttributeList::AT_CUDAGlobal:
+ HasGlobalAttr = true;
+ break;
+ case AttributeList::AT_CUDAHost:
+ HasHostAttr = true;
+ break;
+ case AttributeList::AT_CUDADevice:
+ HasDeviceAttr = true;
+ break;
+ case AttributeList::AT_CUDAInvalidTarget:
+ HasInvalidTargetAttr = true;
+ break;
+ default:
+ break;
+ }
+ Attr = Attr->getNext();
+ }
+ if (HasInvalidTargetAttr)
+ return CFT_InvalidTarget;
+
+ if (HasGlobalAttr)
+ return CFT_Global;
+
+ if (HasHostAttr && HasDeviceAttr)
+ return CFT_HostDevice;
+
+ if (HasDeviceAttr)
+ return CFT_Device;
+
+ return CFT_Host;
+}
+
+template <typename A>
+static bool hasAttr(const FunctionDecl *D, bool IgnoreImplicitAttr) {
+ return D->hasAttrs() && llvm::any_of(D->getAttrs(), [&](Attr *Attribute) {
+ return isa<A>(Attribute) &&
+ !(IgnoreImplicitAttr && Attribute->isImplicit());
+ });
+}
+
/// IdentifyCUDATarget - Determine the CUDA compilation target for this function
-Sema::CUDAFunctionTarget Sema::IdentifyCUDATarget(const FunctionDecl *D) {
+Sema::CUDAFunctionTarget Sema::IdentifyCUDATarget(const FunctionDecl *D,
+ bool IgnoreImplicitHDAttr) {
+ // Code that lives outside a function is run on the host.
+ if (D == nullptr)
+ return CFT_Host;
+
if (D->hasAttr<CUDAInvalidTargetAttr>())
return CFT_InvalidTarget;
if (D->hasAttr<CUDAGlobalAttr>())
return CFT_Global;
- if (D->hasAttr<CUDADeviceAttr>()) {
- if (D->hasAttr<CUDAHostAttr>())
+ if (hasAttr<CUDADeviceAttr>(D, IgnoreImplicitHDAttr)) {
+ if (hasAttr<CUDAHostAttr>(D, IgnoreImplicitHDAttr))
return CFT_HostDevice;
return CFT_Device;
- } else if (D->hasAttr<CUDAHostAttr>()) {
+ } else if (hasAttr<CUDAHostAttr>(D, IgnoreImplicitHDAttr)) {
return CFT_Host;
- } else if (D->isImplicit()) {
+ } else if (D->isImplicit() && !IgnoreImplicitHDAttr) {
// Some implicit declarations (like intrinsic functions) are not marked.
// Set the most lenient target on them for maximal flexibility.
return CFT_HostDevice;
@@ -95,9 +161,8 @@ Sema::CUDAFunctionPreference
Sema::IdentifyCUDAPreference(const FunctionDecl *Caller,
const FunctionDecl *Callee) {
assert(Callee && "Callee must be valid.");
+ CUDAFunctionTarget CallerTarget = IdentifyCUDATarget(Caller);
CUDAFunctionTarget CalleeTarget = IdentifyCUDATarget(Callee);
- CUDAFunctionTarget CallerTarget =
- (Caller != nullptr) ? IdentifyCUDATarget(Caller) : Sema::CFT_Host;
// If one of the targets is invalid, the check always fails, no matter what
// the other target is.
@@ -107,8 +172,7 @@ Sema::IdentifyCUDAPreference(const FunctionDecl *Caller,
// (a) Can't call global from some contexts until we support CUDA's
// dynamic parallelism.
if (CalleeTarget == CFT_Global &&
- (CallerTarget == CFT_Global || CallerTarget == CFT_Device ||
- (CallerTarget == CFT_HostDevice && getLangOpts().CUDAIsDevice)))
+ (CallerTarget == CFT_Global || CallerTarget == CFT_Device))
return CFP_Never;
// (b) Calling HostDevice is OK for everyone.
@@ -145,54 +209,31 @@ Sema::IdentifyCUDAPreference(const FunctionDecl *Caller,
llvm_unreachable("All cases should've been handled by now.");
}
-template <typename T>
-static void EraseUnwantedCUDAMatchesImpl(
- Sema &S, const FunctionDecl *Caller, llvm::SmallVectorImpl<T> &Matches,
- std::function<const FunctionDecl *(const T &)> FetchDecl) {
+void Sema::EraseUnwantedCUDAMatches(
+ const FunctionDecl *Caller,
+ SmallVectorImpl<std::pair<DeclAccessPair, FunctionDecl *>> &Matches) {
if (Matches.size() <= 1)
return;
+ using Pair = std::pair<DeclAccessPair, FunctionDecl*>;
+
// Gets the CUDA function preference for a call from Caller to Match.
- auto GetCFP = [&](const T &Match) {
- return S.IdentifyCUDAPreference(Caller, FetchDecl(Match));
+ auto GetCFP = [&](const Pair &Match) {
+ return IdentifyCUDAPreference(Caller, Match.second);
};
// Find the best call preference among the functions in Matches.
- Sema::CUDAFunctionPreference BestCFP = GetCFP(*std::max_element(
+ CUDAFunctionPreference BestCFP = GetCFP(*std::max_element(
Matches.begin(), Matches.end(),
- [&](const T &M1, const T &M2) { return GetCFP(M1) < GetCFP(M2); }));
+ [&](const Pair &M1, const Pair &M2) { return GetCFP(M1) < GetCFP(M2); }));
// Erase all functions with lower priority.
Matches.erase(
- llvm::remove_if(Matches,
- [&](const T &Match) { return GetCFP(Match) < BestCFP; }),
+ llvm::remove_if(
+ Matches, [&](const Pair &Match) { return GetCFP(Match) < BestCFP; }),
Matches.end());
}
-void Sema::EraseUnwantedCUDAMatches(const FunctionDecl *Caller,
- SmallVectorImpl<FunctionDecl *> &Matches){
- EraseUnwantedCUDAMatchesImpl<FunctionDecl *>(
- *this, Caller, Matches, [](const FunctionDecl *item) { return item; });
-}
-
-void Sema::EraseUnwantedCUDAMatches(const FunctionDecl *Caller,
- SmallVectorImpl<DeclAccessPair> &Matches) {
- EraseUnwantedCUDAMatchesImpl<DeclAccessPair>(
- *this, Caller, Matches, [](const DeclAccessPair &item) {
- return dyn_cast<FunctionDecl>(item.getDecl());
- });
-}
-
-void Sema::EraseUnwantedCUDAMatches(
- const FunctionDecl *Caller,
- SmallVectorImpl<std::pair<DeclAccessPair, FunctionDecl *>> &Matches){
- EraseUnwantedCUDAMatchesImpl<std::pair<DeclAccessPair, FunctionDecl *>>(
- *this, Caller, Matches,
- [](const std::pair<DeclAccessPair, FunctionDecl *> &item) {
- return dyn_cast<FunctionDecl>(item.second);
- });
-}
-
/// When an implicitly-declared special member has to invoke more than one
/// base/field special member, conflicts may occur in the targets of these
/// members. For example, if one base's member __host__ and another's is
@@ -441,9 +482,23 @@ bool Sema::isEmptyCudaDestructor(SourceLocation Loc, CXXDestructorDecl *DD) {
// * a __device__ function with this signature was already declared, in which
// case in which case we output an error, unless the __device__ decl is in a
// system header, in which case we leave the constexpr function unattributed.
-void Sema::maybeAddCUDAHostDeviceAttrs(Scope *S, FunctionDecl *NewD,
+//
+// In addition, all function decls are treated as __host__ __device__ when
+// ForceCUDAHostDeviceDepth > 0 (corresponding to code within a
+// #pragma clang force_cuda_host_device_begin/end
+// pair).
+void Sema::maybeAddCUDAHostDeviceAttrs(FunctionDecl *NewD,
const LookupResult &Previous) {
- assert(getLangOpts().CUDA && "May be called only for CUDA compilations.");
+ assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
+
+ if (ForceCUDAHostDeviceDepth > 0) {
+ if (!NewD->hasAttr<CUDAHostAttr>())
+ NewD->addAttr(CUDAHostAttr::CreateImplicit(Context));
+ if (!NewD->hasAttr<CUDADeviceAttr>())
+ NewD->addAttr(CUDADeviceAttr::CreateImplicit(Context));
+ return;
+ }
+
if (!getLangOpts().CUDAHostDeviceConstexpr || !NewD->isConstexpr() ||
NewD->isVariadic() || NewD->hasAttr<CUDAHostAttr>() ||
NewD->hasAttr<CUDADeviceAttr>() || NewD->hasAttr<CUDAGlobalAttr>())
@@ -480,3 +535,378 @@ void Sema::maybeAddCUDAHostDeviceAttrs(Scope *S, FunctionDecl *NewD,
NewD->addAttr(CUDAHostAttr::CreateImplicit(Context));
NewD->addAttr(CUDADeviceAttr::CreateImplicit(Context));
}
+
+// In CUDA, there are some constructs which may appear in semantically-valid
+// code, but trigger errors if we ever generate code for the function in which
+// they appear. Essentially every construct you're not allowed to use on the
+// device falls into this category, because you are allowed to use these
+// constructs in a __host__ __device__ function, but only if that function is
+// never codegen'ed on the device.
+//
+// To handle semantic checking for these constructs, we keep track of the set of
+// functions we know will be emitted, either because we could tell a priori that
+// they would be emitted, or because they were transitively called by a
+// known-emitted function.
+//
+// We also keep a partial call graph of which not-known-emitted functions call
+// which other not-known-emitted functions.
+//
+// When we see something which is illegal if the current function is emitted
+// (usually by way of CUDADiagIfDeviceCode, CUDADiagIfHostCode, or
+// CheckCUDACall), we first check if the current function is known-emitted. If
+// so, we immediately output the diagnostic.
+//
+// Otherwise, we "defer" the diagnostic. It sits in Sema::CUDADeferredDiags
+// until we discover that the function is known-emitted, at which point we take
+// it out of this map and emit the diagnostic.
+
+Sema::CUDADiagBuilder::CUDADiagBuilder(Kind K, SourceLocation Loc,
+ unsigned DiagID, FunctionDecl *Fn,
+ Sema &S)
+ : S(S), Loc(Loc), DiagID(DiagID), Fn(Fn),
+ ShowCallStack(K == K_ImmediateWithCallStack || K == K_Deferred) {
+ switch (K) {
+ case K_Nop:
+ break;
+ case K_Immediate:
+ case K_ImmediateWithCallStack:
+ ImmediateDiag.emplace(S.Diag(Loc, DiagID));
+ break;
+ case K_Deferred:
+ assert(Fn && "Must have a function to attach the deferred diag to.");
+ PartialDiag.emplace(S.PDiag(DiagID));
+ break;
+ }
+}
+
+// Print notes showing how we can reach FD starting from an a priori
+// known-callable function.
+static void EmitCallStackNotes(Sema &S, FunctionDecl *FD) {
+ auto FnIt = S.CUDAKnownEmittedFns.find(FD);
+ while (FnIt != S.CUDAKnownEmittedFns.end()) {
+ DiagnosticBuilder Builder(
+ S.Diags.Report(FnIt->second.Loc, diag::note_called_by));
+ Builder << FnIt->second.FD;
+ Builder.setForceEmit();
+
+ FnIt = S.CUDAKnownEmittedFns.find(FnIt->second.FD);
+ }
+}
+
+Sema::CUDADiagBuilder::~CUDADiagBuilder() {
+ if (ImmediateDiag) {
+ // Emit our diagnostic and, if it was a warning or error, output a callstack
+ // if Fn isn't a priori known-emitted.
+ bool IsWarningOrError = S.getDiagnostics().getDiagnosticLevel(
+ DiagID, Loc) >= DiagnosticsEngine::Warning;
+ ImmediateDiag.reset(); // Emit the immediate diag.
+ if (IsWarningOrError && ShowCallStack)
+ EmitCallStackNotes(S, Fn);
+ } else if (PartialDiag) {
+ assert(ShowCallStack && "Must always show call stack for deferred diags.");
+ S.CUDADeferredDiags[Fn].push_back({Loc, std::move(*PartialDiag)});
+ }
+}
+
+// Do we know that we will eventually codegen the given function?
+static bool IsKnownEmitted(Sema &S, FunctionDecl *FD) {
+ // Templates are emitted when they're instantiated.
+ if (FD->isDependentContext())
+ return false;
+
+ // When compiling for device, host functions are never emitted. Similarly,
+ // when compiling for host, device and global functions are never emitted.
+ // (Technically, we do emit a host-side stub for global functions, but this
+ // doesn't count for our purposes here.)
+ Sema::CUDAFunctionTarget T = S.IdentifyCUDATarget(FD);
+ if (S.getLangOpts().CUDAIsDevice && T == Sema::CFT_Host)
+ return false;
+ if (!S.getLangOpts().CUDAIsDevice &&
+ (T == Sema::CFT_Device || T == Sema::CFT_Global))
+ return false;
+
+ // Check whether this function is externally visible -- if so, it's
+ // known-emitted.
+ //
+ // We have to check the GVA linkage of the function's *definition* -- if we
+ // only have a declaration, we don't know whether or not the function will be
+ // emitted, because (say) the definition could include "inline".
+ FunctionDecl *Def = FD->getDefinition();
+
+ // We may currently be parsing the body of FD, in which case
+ // FD->getDefinition() will be null, but we still want to treat FD as though
+ // it's a definition.
+ if (!Def && FD->willHaveBody())
+ Def = FD;
+
+ if (Def &&
+ !isDiscardableGVALinkage(S.getASTContext().GetGVALinkageForFunction(Def)))
+ return true;
+
+ // Otherwise, the function is known-emitted if it's in our set of
+ // known-emitted functions.
+ return S.CUDAKnownEmittedFns.count(FD) > 0;
+}
+
+Sema::CUDADiagBuilder Sema::CUDADiagIfDeviceCode(SourceLocation Loc,
+ unsigned DiagID) {
+ assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
+ CUDADiagBuilder::Kind DiagKind = [&] {
+ switch (CurrentCUDATarget()) {
+ case CFT_Global:
+ case CFT_Device:
+ return CUDADiagBuilder::K_Immediate;
+ case CFT_HostDevice:
+ // An HD function counts as host code if we're compiling for host, and
+ // device code if we're compiling for device. Defer any errors in device
+ // mode until the function is known-emitted.
+ if (getLangOpts().CUDAIsDevice) {
+ return IsKnownEmitted(*this, dyn_cast<FunctionDecl>(CurContext))
+ ? CUDADiagBuilder::K_ImmediateWithCallStack
+ : CUDADiagBuilder::K_Deferred;
+ }
+ return CUDADiagBuilder::K_Nop;
+
+ default:
+ return CUDADiagBuilder::K_Nop;
+ }
+ }();
+ return CUDADiagBuilder(DiagKind, Loc, DiagID,
+ dyn_cast<FunctionDecl>(CurContext), *this);
+}
+
+Sema::CUDADiagBuilder Sema::CUDADiagIfHostCode(SourceLocation Loc,
+ unsigned DiagID) {
+ assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
+ CUDADiagBuilder::Kind DiagKind = [&] {
+ switch (CurrentCUDATarget()) {
+ case CFT_Host:
+ return CUDADiagBuilder::K_Immediate;
+ case CFT_HostDevice:
+ // An HD function counts as host code if we're compiling for host, and
+ // device code if we're compiling for device. Defer any errors in device
+ // mode until the function is known-emitted.
+ if (getLangOpts().CUDAIsDevice)
+ return CUDADiagBuilder::K_Nop;
+
+ return IsKnownEmitted(*this, dyn_cast<FunctionDecl>(CurContext))
+ ? CUDADiagBuilder::K_ImmediateWithCallStack
+ : CUDADiagBuilder::K_Deferred;
+ default:
+ return CUDADiagBuilder::K_Nop;
+ }
+ }();
+ return CUDADiagBuilder(DiagKind, Loc, DiagID,
+ dyn_cast<FunctionDecl>(CurContext), *this);
+}
+
+// Emit any deferred diagnostics for FD and erase them from the map in which
+// they're stored.
+static void EmitDeferredDiags(Sema &S, FunctionDecl *FD) {
+ auto It = S.CUDADeferredDiags.find(FD);
+ if (It == S.CUDADeferredDiags.end())
+ return;
+ bool HasWarningOrError = false;
+ for (PartialDiagnosticAt &PDAt : It->second) {
+ const SourceLocation &Loc = PDAt.first;
+ const PartialDiagnostic &PD = PDAt.second;
+ HasWarningOrError |= S.getDiagnostics().getDiagnosticLevel(
+ PD.getDiagID(), Loc) >= DiagnosticsEngine::Warning;
+ DiagnosticBuilder Builder(S.Diags.Report(Loc, PD.getDiagID()));
+ Builder.setForceEmit();
+ PD.Emit(Builder);
+ }
+ S.CUDADeferredDiags.erase(It);
+
+ // FIXME: Should this be called after every warning/error emitted in the loop
+ // above, instead of just once per function? That would be consistent with
+ // how we handle immediate errors, but it also seems like a bit much.
+ if (HasWarningOrError)
+ EmitCallStackNotes(S, FD);
+}
+
+// Indicate that this function (and thus everything it transtively calls) will
+// be codegen'ed, and emit any deferred diagnostics on this function and its
+// (transitive) callees.
+static void MarkKnownEmitted(Sema &S, FunctionDecl *OrigCaller,
+ FunctionDecl *OrigCallee, SourceLocation OrigLoc) {
+ // Nothing to do if we already know that FD is emitted.
+ if (IsKnownEmitted(S, OrigCallee)) {
+ assert(!S.CUDACallGraph.count(OrigCallee));
+ return;
+ }
+
+ // We've just discovered that OrigCallee is known-emitted. Walk our call
+ // graph to see what else we can now discover also must be emitted.
+
+ struct CallInfo {
+ FunctionDecl *Caller;
+ FunctionDecl *Callee;
+ SourceLocation Loc;
+ };
+ llvm::SmallVector<CallInfo, 4> Worklist = {{OrigCaller, OrigCallee, OrigLoc}};
+ llvm::SmallSet<CanonicalDeclPtr<FunctionDecl>, 4> Seen;
+ Seen.insert(OrigCallee);
+ while (!Worklist.empty()) {
+ CallInfo C = Worklist.pop_back_val();
+ assert(!IsKnownEmitted(S, C.Callee) &&
+ "Worklist should not contain known-emitted functions.");
+ S.CUDAKnownEmittedFns[C.Callee] = {C.Caller, C.Loc};
+ EmitDeferredDiags(S, C.Callee);
+
+ // If this is a template instantiation, explore its callgraph as well:
+ // Non-dependent calls are part of the template's callgraph, while dependent
+ // calls are part of to the instantiation's call graph.
+ if (auto *Templ = C.Callee->getPrimaryTemplate()) {
+ FunctionDecl *TemplFD = Templ->getAsFunction();
+ if (!Seen.count(TemplFD) && !S.CUDAKnownEmittedFns.count(TemplFD)) {
+ Seen.insert(TemplFD);
+ Worklist.push_back(
+ {/* Caller = */ C.Caller, /* Callee = */ TemplFD, C.Loc});
+ }
+ }
+
+ // Add all functions called by Callee to our worklist.
+ auto CGIt = S.CUDACallGraph.find(C.Callee);
+ if (CGIt == S.CUDACallGraph.end())
+ continue;
+
+ for (std::pair<CanonicalDeclPtr<FunctionDecl>, SourceLocation> FDLoc :
+ CGIt->second) {
+ FunctionDecl *NewCallee = FDLoc.first;
+ SourceLocation CallLoc = FDLoc.second;
+ if (Seen.count(NewCallee) || IsKnownEmitted(S, NewCallee))
+ continue;
+ Seen.insert(NewCallee);
+ Worklist.push_back(
+ {/* Caller = */ C.Callee, /* Callee = */ NewCallee, CallLoc});
+ }
+
+ // C.Callee is now known-emitted, so we no longer need to maintain its list
+ // of callees in CUDACallGraph.
+ S.CUDACallGraph.erase(CGIt);
+ }
+}
+
+bool Sema::CheckCUDACall(SourceLocation Loc, FunctionDecl *Callee) {
+ assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
+ assert(Callee && "Callee may not be null.");
+ // FIXME: Is bailing out early correct here? Should we instead assume that
+ // the caller is a global initializer?
+ FunctionDecl *Caller = dyn_cast<FunctionDecl>(CurContext);
+ if (!Caller)
+ return true;
+
+ // 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 we have
+ // host fn calls kernel fn calls host+device,
+ // the HD function does not get instantiated on the host. We model this by
+ // omitting at the call to the kernel from the callgraph. This ensures
+ // that, when compiling for host, only HD functions actually called from the
+ // host get marked as known-emitted.
+ if (getLangOpts().CUDAIsDevice || IdentifyCUDATarget(Callee) != CFT_Global)
+ CUDACallGraph[Caller].insert({Callee, Loc});
+ }
+
+ CUDADiagBuilder::Kind DiagKind = [&] {
+ switch (IdentifyCUDAPreference(Caller, Callee)) {
+ case CFP_Never:
+ return CUDADiagBuilder::K_Immediate;
+ case CFP_WrongSide:
+ assert(Caller && "WrongSide calls require a non-null caller");
+ // If we know the caller will be emitted, we know this wrong-side call
+ // will be emitted, so it's an immediate error. Otherwise, defer the
+ // error until we know the caller is emitted.
+ return CallerKnownEmitted ? CUDADiagBuilder::K_ImmediateWithCallStack
+ : CUDADiagBuilder::K_Deferred;
+ default:
+ return CUDADiagBuilder::K_Nop;
+ }
+ }();
+
+ if (DiagKind == CUDADiagBuilder::K_Nop)
+ return true;
+
+ // Avoid emitting this error twice for the same location. Using a hashtable
+ // like this is unfortunate, but because we must continue parsing as normal
+ // after encountering a deferred error, it's otherwise very tricky for us to
+ // ensure that we only emit this deferred error once.
+ if (!LocsWithCUDACallDiags.insert({Caller, Loc}).second)
+ return true;
+
+ CUDADiagBuilder(DiagKind, Loc, diag::err_ref_bad_target, Caller, *this)
+ << IdentifyCUDATarget(Callee) << Callee << IdentifyCUDATarget(Caller);
+ CUDADiagBuilder(DiagKind, Callee->getLocation(), diag::note_previous_decl,
+ Caller, *this)
+ << Callee;
+ return DiagKind != CUDADiagBuilder::K_Immediate &&
+ DiagKind != CUDADiagBuilder::K_ImmediateWithCallStack;
+}
+
+void Sema::CUDASetLambdaAttrs(CXXMethodDecl *Method) {
+ assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
+ if (Method->hasAttr<CUDAHostAttr>() || Method->hasAttr<CUDADeviceAttr>())
+ return;
+ FunctionDecl *CurFn = dyn_cast<FunctionDecl>(CurContext);
+ if (!CurFn)
+ return;
+ CUDAFunctionTarget Target = IdentifyCUDATarget(CurFn);
+ if (Target == CFT_Global || Target == CFT_Device) {
+ Method->addAttr(CUDADeviceAttr::CreateImplicit(Context));
+ } else if (Target == CFT_HostDevice) {
+ Method->addAttr(CUDADeviceAttr::CreateImplicit(Context));
+ Method->addAttr(CUDAHostAttr::CreateImplicit(Context));
+ }
+}
+
+void Sema::checkCUDATargetOverload(FunctionDecl *NewFD,
+ const LookupResult &Previous) {
+ assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
+ CUDAFunctionTarget NewTarget = IdentifyCUDATarget(NewFD);
+ for (NamedDecl *OldND : Previous) {
+ FunctionDecl *OldFD = OldND->getAsFunction();
+ if (!OldFD)
+ continue;
+
+ CUDAFunctionTarget OldTarget = IdentifyCUDATarget(OldFD);
+ // Don't allow HD and global functions to overload other functions with the
+ // same signature. We allow overloading based on CUDA attributes so that
+ // functions can have different implementations on the host and device, but
+ // HD/global functions "exist" in some sense on both the host and device, so
+ // should have the same implementation on both sides.
+ if (NewTarget != OldTarget &&
+ ((NewTarget == CFT_HostDevice) || (OldTarget == CFT_HostDevice) ||
+ (NewTarget == CFT_Global) || (OldTarget == CFT_Global)) &&
+ !IsOverload(NewFD, OldFD, /* UseMemberUsingDeclRules = */ false,
+ /* ConsiderCudaAttrs = */ false)) {
+ Diag(NewFD->getLocation(), diag::err_cuda_ovl_target)
+ << NewTarget << NewFD->getDeclName() << OldTarget << OldFD;
+ Diag(OldFD->getLocation(), diag::note_previous_declaration);
+ NewFD->setInvalidDecl();
+ break;
+ }
+ }
+}
+
+template <typename AttrTy>
+static void copyAttrIfPresent(Sema &S, FunctionDecl *FD,
+ const FunctionDecl &TemplateFD) {
+ if (AttrTy *Attribute = TemplateFD.getAttr<AttrTy>()) {
+ AttrTy *Clone = Attribute->clone(S.Context);
+ Clone->setInherited(true);
+ FD->addAttr(Clone);
+ }
+}
+
+void Sema::inheritCUDATargetAttrs(FunctionDecl *FD,
+ const FunctionTemplateDecl &TD) {
+ const FunctionDecl &TemplateFD = *TD.getTemplatedDecl();
+ copyAttrIfPresent<CUDAGlobalAttr>(*this, FD, TemplateFD);
+ copyAttrIfPresent<CUDAHostAttr>(*this, FD, TemplateFD);
+ copyAttrIfPresent<CUDADeviceAttr>(*this, FD, TemplateFD);
+}
diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp
index 949263d24897..d8971c0d37eb 100644
--- a/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/lib/Sema/SemaCXXScopeSpec.cpp
@@ -11,7 +11,6 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Sema/SemaInternal.h"
#include "TypeLocBuilder.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclTemplate.h"
@@ -20,9 +19,9 @@
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/Lookup.h"
+#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Template.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/Support/raw_ostream.h"
using namespace clang;
/// \brief Find the current instantiation that associated with the given type.
@@ -381,12 +380,11 @@ NamedDecl *Sema::FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS) {
}
bool Sema::isNonTypeNestedNameSpecifier(Scope *S, CXXScopeSpec &SS,
- SourceLocation IdLoc,
- IdentifierInfo &II,
- ParsedType ObjectTypePtr) {
- QualType ObjectType = GetTypeFromParser(ObjectTypePtr);
- LookupResult Found(*this, &II, IdLoc, LookupNestedNameSpecifierName);
-
+ NestedNameSpecInfo &IdInfo) {
+ QualType ObjectType = GetTypeFromParser(IdInfo.ObjectType);
+ LookupResult Found(*this, IdInfo.Identifier, IdInfo.IdentifierLoc,
+ LookupNestedNameSpecifierName);
+
// Determine where to perform name lookup
DeclContext *LookupCtx = nullptr;
bool isDependent = false;
@@ -449,11 +447,8 @@ class NestedNameSpecifierValidatorCCC : public CorrectionCandidateCallback {
/// by ActOnCXXNestedNameSpecifier.
///
/// \param S Scope in which the nested-name-specifier occurs.
-/// \param Identifier Identifier in the sequence "identifier" "::".
-/// \param IdentifierLoc Location of the \p Identifier.
-/// \param CCLoc Location of "::" following Identifier.
-/// \param ObjectType Type of postfix expression if the nested-name-specifier
-/// occurs in construct like: <tt>ptr->nns::f</tt>.
+/// \param IdInfo Parser information about an identifier in the
+/// nested-name-spec.
/// \param EnteringContext If true, enter the context specified by the
/// nested-name-specifier.
/// \param SS Optional nested name specifier preceding the identifier.
@@ -479,17 +474,15 @@ class NestedNameSpecifierValidatorCCC : public CorrectionCandidateCallback {
/// dependent context, for example. Nor will it extend \p SS with the scope
/// specifier.
bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
- IdentifierInfo &Identifier,
- SourceLocation IdentifierLoc,
- SourceLocation CCLoc,
- QualType ObjectType,
+ NestedNameSpecInfo &IdInfo,
bool EnteringContext,
CXXScopeSpec &SS,
NamedDecl *ScopeLookupResult,
bool ErrorRecoveryLookup,
bool *IsCorrectedToColon) {
- LookupResult Found(*this, &Identifier, IdentifierLoc,
+ LookupResult Found(*this, IdInfo.Identifier, IdInfo.IdentifierLoc,
LookupNestedNameSpecifierName);
+ QualType ObjectType = GetTypeFromParser(IdInfo.ObjectType);
// Determine where to perform name lookup
DeclContext *LookupCtx = nullptr;
@@ -574,7 +567,7 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
// base object type or prior nested-name-specifier, so this
// nested-name-specifier refers to an unknown specialization. Just build
// a dependent nested-name-specifier.
- SS.Extend(Context, &Identifier, IdentifierLoc, CCLoc);
+ SS.Extend(Context, IdInfo.Identifier, IdInfo.IdentifierLoc, IdInfo.CCLoc);
return false;
}
@@ -593,18 +586,19 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
// allowed, suggest replacement to ':'.
if (IsCorrectedToColon) {
*IsCorrectedToColon = true;
- Diag(CCLoc, diag::err_nested_name_spec_is_not_class)
- << &Identifier << getLangOpts().CPlusPlus
- << FixItHint::CreateReplacement(CCLoc, ":");
+ Diag(IdInfo.CCLoc, diag::err_nested_name_spec_is_not_class)
+ << IdInfo.Identifier << getLangOpts().CPlusPlus
+ << FixItHint::CreateReplacement(IdInfo.CCLoc, ":");
if (NamedDecl *ND = R.getAsSingle<NamedDecl>())
Diag(ND->getLocation(), diag::note_declared_at);
return true;
}
// Replacement '::' -> ':' is not allowed, just issue respective error.
Diag(R.getNameLoc(), diag::err_expected_class_or_namespace)
- << &Identifier << getLangOpts().CPlusPlus;
+ << IdInfo.Identifier << getLangOpts().CPlusPlus;
if (NamedDecl *ND = R.getAsSingle<NamedDecl>())
- Diag(ND->getLocation(), diag::note_entity_declared_at) << &Identifier;
+ Diag(ND->getLocation(), diag::note_entity_declared_at)
+ << IdInfo.Identifier;
return true;
}
}
@@ -639,7 +633,7 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
Found.addDecl(ND);
Found.setLookupName(Corrected.getCorrection());
} else {
- Found.setLookupName(&Identifier);
+ Found.setLookupName(IdInfo.Identifier);
}
}
@@ -649,7 +643,7 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
bool AcceptSpec = isAcceptableNestedNameSpecifier(SD, &IsExtension);
if (!AcceptSpec && IsExtension) {
AcceptSpec = true;
- Diag(IdentifierLoc, diag::ext_nested_name_spec_is_enum);
+ Diag(IdInfo.IdentifierLoc, diag::ext_nested_name_spec_is_enum);
}
if (AcceptSpec) {
if (!ObjectType.isNull() && !ObjectTypeSearchedInScope &&
@@ -666,7 +660,7 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
// Note that C++11 does *not* perform this redundant lookup.
NamedDecl *OuterDecl;
if (S) {
- LookupResult FoundOuter(*this, &Identifier, IdentifierLoc,
+ LookupResult FoundOuter(*this, IdInfo.Identifier, IdInfo.IdentifierLoc,
LookupNestedNameSpecifierName);
LookupName(FoundOuter, S);
OuterDecl = FoundOuter.getAsSingle<NamedDecl>();
@@ -682,9 +676,9 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
if (ErrorRecoveryLookup)
return true;
- Diag(IdentifierLoc,
+ Diag(IdInfo.IdentifierLoc,
diag::err_nested_name_member_ref_lookup_ambiguous)
- << &Identifier;
+ << IdInfo.Identifier;
Diag(SD->getLocation(), diag::note_ambig_member_ref_object_type)
<< ObjectType;
Diag(OuterDecl->getLocation(), diag::note_ambig_member_ref_scope);
@@ -703,16 +697,15 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
return false;
// The use of a nested name specifier may trigger deprecation warnings.
- DiagnoseUseOfDecl(SD, CCLoc);
+ DiagnoseUseOfDecl(SD, IdInfo.CCLoc);
-
if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(SD)) {
- SS.Extend(Context, Namespace, IdentifierLoc, CCLoc);
+ SS.Extend(Context, Namespace, IdInfo.IdentifierLoc, IdInfo.CCLoc);
return false;
}
if (NamespaceAliasDecl *Alias = dyn_cast<NamespaceAliasDecl>(SD)) {
- SS.Extend(Context, Alias, IdentifierLoc, CCLoc);
+ SS.Extend(Context, Alias, IdInfo.IdentifierLoc, IdInfo.CCLoc);
return false;
}
@@ -722,41 +715,41 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
if (isa<InjectedClassNameType>(T)) {
InjectedClassNameTypeLoc InjectedTL
= TLB.push<InjectedClassNameTypeLoc>(T);
- InjectedTL.setNameLoc(IdentifierLoc);
+ InjectedTL.setNameLoc(IdInfo.IdentifierLoc);
} else if (isa<RecordType>(T)) {
RecordTypeLoc RecordTL = TLB.push<RecordTypeLoc>(T);
- RecordTL.setNameLoc(IdentifierLoc);
+ RecordTL.setNameLoc(IdInfo.IdentifierLoc);
} else if (isa<TypedefType>(T)) {
TypedefTypeLoc TypedefTL = TLB.push<TypedefTypeLoc>(T);
- TypedefTL.setNameLoc(IdentifierLoc);
+ TypedefTL.setNameLoc(IdInfo.IdentifierLoc);
} else if (isa<EnumType>(T)) {
EnumTypeLoc EnumTL = TLB.push<EnumTypeLoc>(T);
- EnumTL.setNameLoc(IdentifierLoc);
+ EnumTL.setNameLoc(IdInfo.IdentifierLoc);
} else if (isa<TemplateTypeParmType>(T)) {
TemplateTypeParmTypeLoc TemplateTypeTL
= TLB.push<TemplateTypeParmTypeLoc>(T);
- TemplateTypeTL.setNameLoc(IdentifierLoc);
+ TemplateTypeTL.setNameLoc(IdInfo.IdentifierLoc);
} else if (isa<UnresolvedUsingType>(T)) {
UnresolvedUsingTypeLoc UnresolvedTL
= TLB.push<UnresolvedUsingTypeLoc>(T);
- UnresolvedTL.setNameLoc(IdentifierLoc);
+ UnresolvedTL.setNameLoc(IdInfo.IdentifierLoc);
} else if (isa<SubstTemplateTypeParmType>(T)) {
SubstTemplateTypeParmTypeLoc TL
= TLB.push<SubstTemplateTypeParmTypeLoc>(T);
- TL.setNameLoc(IdentifierLoc);
+ TL.setNameLoc(IdInfo.IdentifierLoc);
} else if (isa<SubstTemplateTypeParmPackType>(T)) {
SubstTemplateTypeParmPackTypeLoc TL
= TLB.push<SubstTemplateTypeParmPackTypeLoc>(T);
- TL.setNameLoc(IdentifierLoc);
+ TL.setNameLoc(IdInfo.IdentifierLoc);
} else {
llvm_unreachable("Unhandled TypeDecl node in nested-name-specifier");
}
if (T->isEnumeralType())
- Diag(IdentifierLoc, diag::warn_cxx98_compat_enum_nested_name_spec);
+ Diag(IdInfo.IdentifierLoc, diag::warn_cxx98_compat_enum_nested_name_spec);
SS.Extend(Context, SourceLocation(), TLB.getTypeLocInContext(Context, T),
- CCLoc);
+ IdInfo.CCLoc);
return false;
}
@@ -795,9 +788,11 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
if (DC->isDependentContext() && DC->isFunctionOrMethod()) {
CXXRecordDecl *ContainingClass = dyn_cast<CXXRecordDecl>(DC->getParent());
if (ContainingClass && ContainingClass->hasAnyDependentBases()) {
- Diag(IdentifierLoc, diag::ext_undeclared_unqual_id_with_dependent_base)
- << &Identifier << ContainingClass;
- SS.Extend(Context, &Identifier, IdentifierLoc, CCLoc);
+ Diag(IdInfo.IdentifierLoc,
+ diag::ext_undeclared_unqual_id_with_dependent_base)
+ << IdInfo.Identifier << ContainingClass;
+ SS.Extend(Context, IdInfo.Identifier, IdInfo.IdentifierLoc,
+ IdInfo.CCLoc);
return false;
}
}
@@ -805,28 +800,27 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
if (!Found.empty()) {
if (TypeDecl *TD = Found.getAsSingle<TypeDecl>())
- Diag(IdentifierLoc, diag::err_expected_class_or_namespace)
+ Diag(IdInfo.IdentifierLoc, diag::err_expected_class_or_namespace)
<< Context.getTypeDeclType(TD) << getLangOpts().CPlusPlus;
else {
- Diag(IdentifierLoc, diag::err_expected_class_or_namespace)
- << &Identifier << getLangOpts().CPlusPlus;
+ Diag(IdInfo.IdentifierLoc, diag::err_expected_class_or_namespace)
+ << IdInfo.Identifier << getLangOpts().CPlusPlus;
if (NamedDecl *ND = Found.getAsSingle<NamedDecl>())
- Diag(ND->getLocation(), diag::note_entity_declared_at) << &Identifier;
+ Diag(ND->getLocation(), diag::note_entity_declared_at)
+ << IdInfo.Identifier;
}
} else if (SS.isSet())
- Diag(IdentifierLoc, diag::err_no_member) << &Identifier << LookupCtx
- << SS.getRange();
+ Diag(IdInfo.IdentifierLoc, diag::err_no_member) << IdInfo.Identifier
+ << LookupCtx << SS.getRange();
else
- Diag(IdentifierLoc, diag::err_undeclared_var_use) << &Identifier;
+ Diag(IdInfo.IdentifierLoc, diag::err_undeclared_var_use)
+ << IdInfo.Identifier;
return true;
}
bool Sema::ActOnCXXNestedNameSpecifier(Scope *S,
- IdentifierInfo &Identifier,
- SourceLocation IdentifierLoc,
- SourceLocation CCLoc,
- ParsedType ObjectType,
+ NestedNameSpecInfo &IdInfo,
bool EnteringContext,
CXXScopeSpec &SS,
bool ErrorRecoveryLookup,
@@ -834,9 +828,8 @@ bool Sema::ActOnCXXNestedNameSpecifier(Scope *S,
if (SS.isInvalid())
return true;
- return BuildCXXNestedNameSpecifier(S, Identifier, IdentifierLoc, CCLoc,
- GetTypeFromParser(ObjectType),
- EnteringContext, SS,
+ return BuildCXXNestedNameSpecifier(S, IdInfo,
+ EnteringContext, SS,
/*ScopeLookupResult=*/nullptr, false,
IsCorrectedToColon);
}
@@ -871,17 +864,12 @@ bool Sema::ActOnCXXNestedNameSpecifierDecltype(CXXScopeSpec &SS,
///
/// The arguments are the same as those passed to ActOnCXXNestedNameSpecifier.
bool Sema::IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS,
- IdentifierInfo &Identifier,
- SourceLocation IdentifierLoc,
- SourceLocation ColonLoc,
- ParsedType ObjectType,
+ NestedNameSpecInfo &IdInfo,
bool EnteringContext) {
if (SS.isInvalid())
return false;
- return !BuildCXXNestedNameSpecifier(S, Identifier, IdentifierLoc, ColonLoc,
- GetTypeFromParser(ObjectType),
- EnteringContext, SS,
+ return !BuildCXXNestedNameSpecifier(S, IdInfo, EnteringContext, SS,
/*ScopeLookupResult=*/nullptr, true);
}
@@ -987,9 +975,9 @@ void *Sema::SaveNestedNameSpecifierAnnotation(CXXScopeSpec &SS) {
if (SS.isEmpty() || SS.isInvalid())
return nullptr;
- void *Mem = Context.Allocate((sizeof(NestedNameSpecifierAnnotation) +
- SS.location_size()),
- llvm::alignOf<NestedNameSpecifierAnnotation>());
+ void *Mem = Context.Allocate(
+ (sizeof(NestedNameSpecifierAnnotation) + SS.location_size()),
+ alignof(NestedNameSpecifierAnnotation));
NestedNameSpecifierAnnotation *Annotation
= new (Mem) NestedNameSpecifierAnnotation;
Annotation->NNS = SS.getScopeRep();
@@ -1013,6 +1001,11 @@ void Sema::RestoreNestedNameSpecifierAnnotation(void *AnnotationPtr,
bool Sema::ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
assert(SS.isSet() && "Parser passed invalid CXXScopeSpec.");
+ // Don't enter a declarator context when the current context is an Objective-C
+ // declaration.
+ if (isa<ObjCContainerDecl>(CurContext) || isa<ObjCMethodDecl>(CurContext))
+ return false;
+
NestedNameSpecifier *Qualifier = SS.getScopeRep();
// There are only two places a well-formed program may qualify a
diff --git a/lib/Sema/SemaCast.cpp b/lib/Sema/SemaCast.cpp
index e83dd0716780..6222e4cec47a 100644
--- a/lib/Sema/SemaCast.cpp
+++ b/lib/Sema/SemaCast.cpp
@@ -256,6 +256,7 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
Op.CheckConstCast();
if (Op.SrcExpr.isInvalid())
return ExprError();
+ DiscardMisalignedMemberAddress(DestType.getTypePtr(), E);
}
return Op.complete(CXXConstCastExpr::Create(Context, Op.ResultType,
Op.ValueKind, Op.SrcExpr.get(), DestTInfo,
@@ -279,6 +280,7 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
Op.CheckReinterpretCast();
if (Op.SrcExpr.isInvalid())
return ExprError();
+ DiscardMisalignedMemberAddress(DestType.getTypePtr(), E);
}
return Op.complete(CXXReinterpretCastExpr::Create(Context, Op.ResultType,
Op.ValueKind, Op.Kind, Op.SrcExpr.get(),
@@ -291,6 +293,7 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
Op.CheckStaticCast();
if (Op.SrcExpr.isInvalid())
return ExprError();
+ DiscardMisalignedMemberAddress(DestType.getTypePtr(), E);
}
return Op.complete(CXXStaticCastExpr::Create(Context, Op.ResultType,
@@ -980,7 +983,7 @@ static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr,
// C++11 [expr.static.cast]p3:
// A glvalue of type "cv1 T1" can be cast to type "rvalue reference to cv2
// T2" if "cv2 T2" is reference-compatible with "cv1 T1".
- tcr = TryLValueToRValueCast(Self, SrcExpr.get(), DestType, CStyle, Kind,
+ tcr = TryLValueToRValueCast(Self, SrcExpr.get(), DestType, CStyle, Kind,
BasePath, msg);
if (tcr != TC_NotApplicable)
return tcr;
@@ -1131,12 +1134,12 @@ static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr,
}
/// Tests whether a conversion according to N2844 is valid.
-TryCastResult
-TryLValueToRValueCast(Sema &Self, Expr *SrcExpr, QualType DestType,
- bool CStyle, CastKind &Kind, CXXCastPath &BasePath,
- unsigned &msg) {
+TryCastResult TryLValueToRValueCast(Sema &Self, Expr *SrcExpr,
+ QualType DestType, bool CStyle,
+ CastKind &Kind, CXXCastPath &BasePath,
+ unsigned &msg) {
// C++11 [expr.static.cast]p3:
- // A glvalue of type "cv1 T1" can be cast to type "rvalue reference to
+ // A glvalue of type "cv1 T1" can be cast to type "rvalue reference to
// cv2 T2" if "cv2 T2" is reference-compatible with "cv1 T1".
const RValueReferenceType *R = DestType->getAs<RValueReferenceType>();
if (!R)
@@ -1157,15 +1160,18 @@ TryLValueToRValueCast(Sema &Self, Expr *SrcExpr, QualType DestType,
FromType = FromType.getUnqualifiedType();
ToType = ToType.getUnqualifiedType();
}
-
- if (Self.CompareReferenceRelationship(SrcExpr->getLocStart(),
- ToType, FromType,
- DerivedToBase, ObjCConversion,
- ObjCLifetimeConversion)
- < Sema::Ref_Compatible_With_Added_Qualification) {
- if (CStyle)
+
+ Sema::ReferenceCompareResult RefResult = Self.CompareReferenceRelationship(
+ SrcExpr->getLocStart(), ToType, FromType, DerivedToBase, ObjCConversion,
+ ObjCLifetimeConversion);
+ if (RefResult != Sema::Ref_Compatible) {
+ if (CStyle || RefResult == Sema::Ref_Incompatible)
return TC_NotApplicable;
- msg = diag::err_bad_lvalue_to_rvalue_cast;
+ // Diagnose types which are reference-related but not compatible here since
+ // we can provide better diagnostics. In these cases forwarding to
+ // [expr.static.cast]p4 should never result in a well-formed cast.
+ msg = SrcExpr->isLValue() ? diag::err_bad_lvalue_to_rvalue_cast
+ : diag::err_bad_rvalue_to_rvalue_cast;
return TC_Failed;
}
@@ -1511,6 +1517,9 @@ TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
? InitializationKind::CreateFunctionalCast(OpRange, ListInitialization)
: InitializationKind::CreateCast(OpRange);
Expr *SrcExprRaw = SrcExpr.get();
+ // FIXME: Per DR242, we should check for an implicit conversion sequence
+ // or for a constructor that could be invoked by direct-initialization
+ // here, not for an initialization sequence.
InitializationSequence InitSeq(Self, Entity, InitKind, SrcExprRaw);
// At this point of CheckStaticCast, if the destination is a reference,
@@ -1646,7 +1655,8 @@ static TryCastResult TryConstCast(Sema &Self, ExprResult &SrcExpr,
if (NeedToMaterializeTemporary)
// This is a const_cast from a class prvalue to an rvalue reference type.
// Materialize a temporary to store the result of the conversion.
- SrcExpr = Self.CreateMaterializeTemporaryExpr(SrcType, SrcExpr.get(),
+ SrcExpr = Self.CreateMaterializeTemporaryExpr(SrcExpr.get()->getType(),
+ SrcExpr.get(),
/*IsLValueReference*/ false);
return TC_Success;
@@ -1910,7 +1920,10 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
switch (SrcExpr.get()->getObjectKind()) {
case OK_Ordinary:
break;
- case OK_BitField: inappropriate = "bit-field"; break;
+ case OK_BitField:
+ msg = diag::err_bad_cxx_cast_bitfield;
+ return TC_NotApplicable;
+ // FIXME: Use a specific diagnostic for the rest of these cases.
case OK_VectorComponent: inappropriate = "vector element"; break;
case OK_ObjCProperty: inappropriate = "property expression"; break;
case OK_ObjCSubscript: inappropriate = "container subscripting expression";
@@ -2435,7 +2448,7 @@ void CastOperation::CheckCStyleCast() {
return;
}
Self.Diag(OpRange.getBegin(),
- diag::error_opencl_cast_non_zero_to_event_t)
+ diag::err_opencl_cast_non_zero_to_event_t)
<< CastInt.toString(10) << SrcExpr.get()->getSourceRange();
SrcExpr = ExprError();
return;
@@ -2516,7 +2529,8 @@ void CastOperation::CheckCStyleCast() {
}
}
- if (Self.getLangOpts().OpenCL && !Self.getOpenCLOptions().cl_khr_fp16) {
+ if (Self.getLangOpts().OpenCL &&
+ !Self.getOpenCLOptions().isEnabled("cl_khr_fp16")) {
if (DestType->isHalfType()) {
Self.Diag(SrcExpr.get()->getLocStart(), diag::err_opencl_cast_to_half)
<< DestType << SrcExpr.get()->getSourceRange();
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index 7f7dbe8873d4..9c902959233f 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -12,7 +12,6 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Sema/SemaInternal.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/DeclCXX.h"
@@ -33,14 +32,14 @@
#include "clang/Sema/Lookup.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/Sema.h"
+#include "clang/Sema/SemaInternal.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallBitVector.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/Locale.h"
-#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/raw_ostream.h"
-#include <limits>
using namespace clang;
using namespace sema;
@@ -316,8 +315,18 @@ static bool SemaOpenCLBuiltinKernelWorkGroupSize(Sema &S, CallExpr *TheCall) {
return checkOpenCLBlockArgs(S, BlockArg);
}
+/// Diagnose integer type and any valid implicit convertion to it.
+static bool checkOpenCLEnqueueIntType(Sema &S, Expr *E,
+ const QualType &IntType);
+
static bool checkOpenCLEnqueueLocalSizeArgs(Sema &S, CallExpr *TheCall,
- unsigned Start, unsigned End);
+ unsigned Start, unsigned End) {
+ bool IllegalParams = false;
+ for (unsigned I = Start; I <= End; ++I)
+ IllegalParams |= checkOpenCLEnqueueIntType(S, TheCall->getArg(I),
+ S.Context.getSizeType());
+ return IllegalParams;
+}
/// OpenCL v2.0, s6.13.17.1 - Check that sizes are provided for all
/// 'local void*' parameter of passed block.
@@ -452,16 +461,20 @@ static bool SemaOpenCLBuiltinEnqueueKernel(Sema &S, CallExpr *TheCall) {
Expr *Arg4 = TheCall->getArg(4);
Expr *Arg5 = TheCall->getArg(5);
- // Fith argument is always passed as pointers to clk_event_t.
- if (!Arg4->getType()->getPointeeOrArrayElementType()->isClkEventT()) {
+ // Fifth argument is always passed as a pointer to clk_event_t.
+ if (!Arg4->isNullPointerConstant(S.Context,
+ Expr::NPC_ValueDependentIsNotNull) &&
+ !Arg4->getType()->getPointeeOrArrayElementType()->isClkEventT()) {
S.Diag(TheCall->getArg(4)->getLocStart(),
diag::err_opencl_enqueue_kernel_expected_type)
<< S.Context.getPointerType(S.Context.OCLClkEventTy);
return true;
}
- // Sixth argument is always passed as pointers to clk_event_t.
- if (!(Arg5->getType()->isPointerType() &&
+ // Sixth argument is always passed as a pointer to clk_event_t.
+ if (!Arg5->isNullPointerConstant(S.Context,
+ Expr::NPC_ValueDependentIsNotNull) &&
+ !(Arg5->getType()->isPointerType() &&
Arg5->getType()->getPointeeType()->isClkEventT())) {
S.Diag(TheCall->getArg(5)->getLocStart(),
diag::err_opencl_enqueue_kernel_expected_type)
@@ -792,6 +805,10 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
if (SemaBuiltinPrefetch(TheCall))
return ExprError();
break;
+ case Builtin::BI__builtin_alloca_with_align:
+ if (SemaBuiltinAllocaWithAlign(TheCall))
+ return ExprError();
+ break;
case Builtin::BI__assume:
case Builtin::BI__builtin_assume:
if (SemaBuiltinAssume(TheCall))
@@ -1021,6 +1038,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
// check for the argument.
if (SemaBuiltinRWPipe(*this, TheCall))
return ExprError();
+ TheCall->setType(Context.IntTy);
break;
case Builtin::BIreserve_read_pipe:
case Builtin::BIreserve_write_pipe:
@@ -1048,6 +1066,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
case Builtin::BIget_pipe_max_packets:
if (SemaBuiltinPipePackets(*this, TheCall))
return ExprError();
+ TheCall->setType(Context.UnsignedIntTy);
break;
case Builtin::BIto_global:
case Builtin::BIto_local:
@@ -1064,6 +1083,13 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
case Builtin::BIget_kernel_preferred_work_group_size_multiple:
if (SemaOpenCLBuiltinKernelWorkGroupSize(*this, TheCall))
return ExprError();
+ break;
+ case Builtin::BI__builtin_os_log_format:
+ case Builtin::BI__builtin_os_log_format_buffer_size:
+ if (SemaBuiltinOSLogFormat(TheCall)) {
+ return ExprError();
+ }
+ break;
}
// Since the target specific builtins for each arch overlap, only check those
@@ -1757,51 +1783,237 @@ static bool SemaBuiltinCpuSupports(Sema &S, CallExpr *TheCall) {
return false;
}
-bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
- int i = 0, l = 0, u = 0;
+// Check if the rounding mode is legal.
+bool Sema::CheckX86BuiltinRoundingOrSAE(unsigned BuiltinID, CallExpr *TheCall) {
+ // Indicates if this instruction has rounding control or just SAE.
+ bool HasRC = false;
+
+ unsigned ArgNum = 0;
switch (BuiltinID) {
default:
return false;
- case X86::BI__builtin_cpu_supports:
+ case X86::BI__builtin_ia32_vcvttsd2si32:
+ case X86::BI__builtin_ia32_vcvttsd2si64:
+ case X86::BI__builtin_ia32_vcvttsd2usi32:
+ case X86::BI__builtin_ia32_vcvttsd2usi64:
+ case X86::BI__builtin_ia32_vcvttss2si32:
+ case X86::BI__builtin_ia32_vcvttss2si64:
+ case X86::BI__builtin_ia32_vcvttss2usi32:
+ case X86::BI__builtin_ia32_vcvttss2usi64:
+ ArgNum = 1;
+ break;
+ case X86::BI__builtin_ia32_cvtps2pd512_mask:
+ case X86::BI__builtin_ia32_cvttpd2dq512_mask:
+ case X86::BI__builtin_ia32_cvttpd2qq512_mask:
+ case X86::BI__builtin_ia32_cvttpd2udq512_mask:
+ case X86::BI__builtin_ia32_cvttpd2uqq512_mask:
+ case X86::BI__builtin_ia32_cvttps2dq512_mask:
+ case X86::BI__builtin_ia32_cvttps2qq512_mask:
+ case X86::BI__builtin_ia32_cvttps2udq512_mask:
+ case X86::BI__builtin_ia32_cvttps2uqq512_mask:
+ case X86::BI__builtin_ia32_exp2pd_mask:
+ case X86::BI__builtin_ia32_exp2ps_mask:
+ case X86::BI__builtin_ia32_getexppd512_mask:
+ case X86::BI__builtin_ia32_getexpps512_mask:
+ case X86::BI__builtin_ia32_rcp28pd_mask:
+ case X86::BI__builtin_ia32_rcp28ps_mask:
+ case X86::BI__builtin_ia32_rsqrt28pd_mask:
+ case X86::BI__builtin_ia32_rsqrt28ps_mask:
+ case X86::BI__builtin_ia32_vcomisd:
+ case X86::BI__builtin_ia32_vcomiss:
+ case X86::BI__builtin_ia32_vcvtph2ps512_mask:
+ ArgNum = 3;
+ break;
+ case X86::BI__builtin_ia32_cmppd512_mask:
+ case X86::BI__builtin_ia32_cmpps512_mask:
+ case X86::BI__builtin_ia32_cmpsd_mask:
+ case X86::BI__builtin_ia32_cmpss_mask:
+ 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:
+ case X86::BI__builtin_ia32_rcp28ss_round_mask:
+ case X86::BI__builtin_ia32_reducepd512_mask:
+ case X86::BI__builtin_ia32_reduceps512_mask:
+ case X86::BI__builtin_ia32_rndscalepd_mask:
+ case X86::BI__builtin_ia32_rndscaleps_mask:
+ case X86::BI__builtin_ia32_rsqrt28sd_round_mask:
+ case X86::BI__builtin_ia32_rsqrt28ss_round_mask:
+ ArgNum = 4;
+ break;
+ case X86::BI__builtin_ia32_fixupimmpd512_mask:
+ case X86::BI__builtin_ia32_fixupimmpd512_maskz:
+ case X86::BI__builtin_ia32_fixupimmps512_mask:
+ case X86::BI__builtin_ia32_fixupimmps512_maskz:
+ case X86::BI__builtin_ia32_fixupimmsd_mask:
+ case X86::BI__builtin_ia32_fixupimmsd_maskz:
+ case X86::BI__builtin_ia32_fixupimmss_mask:
+ case X86::BI__builtin_ia32_fixupimmss_maskz:
+ case X86::BI__builtin_ia32_rangepd512_mask:
+ case X86::BI__builtin_ia32_rangeps512_mask:
+ case X86::BI__builtin_ia32_rangesd128_round_mask:
+ case X86::BI__builtin_ia32_rangess128_round_mask:
+ case X86::BI__builtin_ia32_reducesd_mask:
+ case X86::BI__builtin_ia32_reducess_mask:
+ case X86::BI__builtin_ia32_rndscalesd_round_mask:
+ case X86::BI__builtin_ia32_rndscaless_round_mask:
+ ArgNum = 5;
+ break;
+ case X86::BI__builtin_ia32_vcvtsd2si64:
+ case X86::BI__builtin_ia32_vcvtsd2si32:
+ case X86::BI__builtin_ia32_vcvtsd2usi32:
+ case X86::BI__builtin_ia32_vcvtsd2usi64:
+ case X86::BI__builtin_ia32_vcvtss2si32:
+ case X86::BI__builtin_ia32_vcvtss2si64:
+ case X86::BI__builtin_ia32_vcvtss2usi32:
+ case X86::BI__builtin_ia32_vcvtss2usi64:
+ ArgNum = 1;
+ HasRC = true;
+ break;
+ case X86::BI__builtin_ia32_cvtsi2sd64:
+ case X86::BI__builtin_ia32_cvtsi2ss32:
+ case X86::BI__builtin_ia32_cvtsi2ss64:
+ case X86::BI__builtin_ia32_cvtusi2sd64:
+ case X86::BI__builtin_ia32_cvtusi2ss32:
+ case X86::BI__builtin_ia32_cvtusi2ss64:
+ ArgNum = 2;
+ HasRC = true;
+ break;
+ case X86::BI__builtin_ia32_cvtdq2ps512_mask:
+ case X86::BI__builtin_ia32_cvtudq2ps512_mask:
+ case X86::BI__builtin_ia32_cvtpd2ps512_mask:
+ case X86::BI__builtin_ia32_cvtpd2qq512_mask:
+ case X86::BI__builtin_ia32_cvtpd2uqq512_mask:
+ case X86::BI__builtin_ia32_cvtps2qq512_mask:
+ case X86::BI__builtin_ia32_cvtps2uqq512_mask:
+ case X86::BI__builtin_ia32_cvtqq2pd512_mask:
+ 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:
+ case X86::BI__builtin_ia32_divsd_round_mask:
+ case X86::BI__builtin_ia32_mulss_round_mask:
+ case X86::BI__builtin_ia32_mulsd_round_mask:
+ case X86::BI__builtin_ia32_subss_round_mask:
+ case X86::BI__builtin_ia32_subsd_round_mask:
+ case X86::BI__builtin_ia32_scalefpd512_mask:
+ case X86::BI__builtin_ia32_scalefps512_mask:
+ case X86::BI__builtin_ia32_scalefsd_round_mask:
+ case X86::BI__builtin_ia32_scalefss_round_mask:
+ case X86::BI__builtin_ia32_getmantpd512_mask:
+ case X86::BI__builtin_ia32_getmantps512_mask:
+ 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_vfmaddpd512_mask:
+ case X86::BI__builtin_ia32_vfmaddpd512_mask3:
+ case X86::BI__builtin_ia32_vfmaddpd512_maskz:
+ 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_vfmaddsubpd512_mask:
+ case X86::BI__builtin_ia32_vfmaddsubpd512_mask3:
+ case X86::BI__builtin_ia32_vfmaddsubpd512_maskz:
+ 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_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;
+ case X86::BI__builtin_ia32_getmantsd_round_mask:
+ case X86::BI__builtin_ia32_getmantss_round_mask:
+ ArgNum = 5;
+ HasRC = true;
+ break;
+ }
+
+ llvm::APSInt Result;
+
+ // We can't check the value of a dependent argument.
+ Expr *Arg = TheCall->getArg(ArgNum);
+ if (Arg->isTypeDependent() || Arg->isValueDependent())
+ return false;
+
+ // Check constant-ness first.
+ if (SemaBuiltinConstantArg(TheCall, ArgNum, Result))
+ return true;
+
+ // Make sure rounding mode is either ROUND_CUR_DIRECTION or ROUND_NO_EXC bit
+ // is set. If the intrinsic has rounding control(bits 1:0), make sure its only
+ // combined with ROUND_NO_EXC.
+ if (Result == 4/*ROUND_CUR_DIRECTION*/ ||
+ Result == 8/*ROUND_NO_EXC*/ ||
+ (HasRC && Result.getZExtValue() >= 8 && Result.getZExtValue() <= 11))
+ return false;
+
+ return Diag(TheCall->getLocStart(), diag::err_x86_builtin_invalid_rounding)
+ << Arg->getSourceRange();
+}
+
+bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
+ if (BuiltinID == X86::BI__builtin_cpu_supports)
return SemaBuiltinCpuSupports(*this, TheCall);
- case X86::BI__builtin_ms_va_start:
+
+ if (BuiltinID == X86::BI__builtin_ms_va_start)
return SemaBuiltinMSVAStart(TheCall);
- 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;
+
+ // If the intrinsic has rounding or SAE make sure its valid.
+ if (CheckX86BuiltinRoundingOrSAE(BuiltinID, TheCall))
+ return true;
+
+ // For intrinsics which take an immediate value as part of the instruction,
+ // range check them here.
+ int i = 0, l = 0, u = 0;
+ switch (BuiltinID) {
+ default:
+ return false;
case X86::BI_mm_prefetch:
- 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__builtin_ia32_insertf32x8_mask:
- case X86::BI__builtin_ia32_inserti32x8_mask:
- case X86::BI__builtin_ia32_insertf64x4_mask:
- case X86::BI__builtin_ia32_inserti64x4_mask:
- case X86::BI__builtin_ia32_insertf64x2_256_mask:
- case X86::BI__builtin_ia32_inserti64x2_256_mask:
- case X86::BI__builtin_ia32_insertf32x4_256_mask:
- case X86::BI__builtin_ia32_inserti32x4_256_mask:
- i = 2; l = 0; u = 1;
- 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_insertf64x2_512_mask:
- case X86::BI__builtin_ia32_inserti64x2_512_mask:
- case X86::BI__builtin_ia32_insertf32x4_mask:
- case X86::BI__builtin_ia32_inserti32x4_mask:
i = 2; l = 0; u = 3;
break;
case X86::BI__builtin_ia32_vpermil2pd:
@@ -1909,33 +2121,6 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
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_psllwi512_mask:
- case X86::BI__builtin_ia32_psllwi128_mask:
- case X86::BI__builtin_ia32_psllwi256_mask:
- case X86::BI__builtin_ia32_psrldi128_mask:
- case X86::BI__builtin_ia32_psrldi256_mask:
- case X86::BI__builtin_ia32_psrldi512_mask:
- case X86::BI__builtin_ia32_psrlqi128_mask:
- case X86::BI__builtin_ia32_psrlqi256_mask:
- case X86::BI__builtin_ia32_psrlqi512_mask:
- case X86::BI__builtin_ia32_psrawi512_mask:
- case X86::BI__builtin_ia32_psrawi128_mask:
- case X86::BI__builtin_ia32_psrawi256_mask:
- case X86::BI__builtin_ia32_psrlwi512_mask:
- case X86::BI__builtin_ia32_psrlwi128_mask:
- case X86::BI__builtin_ia32_psrlwi256_mask:
- case X86::BI__builtin_ia32_psradi128_mask:
- case X86::BI__builtin_ia32_psradi256_mask:
- case X86::BI__builtin_ia32_psradi512_mask:
- case X86::BI__builtin_ia32_psraqi128_mask:
- case X86::BI__builtin_ia32_psraqi256_mask:
- case X86::BI__builtin_ia32_psraqi512_mask:
- case X86::BI__builtin_ia32_pslldi128_mask:
- case X86::BI__builtin_ia32_pslldi256_mask:
- case X86::BI__builtin_ia32_pslldi512_mask:
- case X86::BI__builtin_ia32_psllqi128_mask:
- case X86::BI__builtin_ia32_psllqi256_mask:
- case X86::BI__builtin_ia32_psllqi512_mask:
case X86::BI__builtin_ia32_fpclasspd128_mask:
case X86::BI__builtin_ia32_fpclasspd256_mask:
case X86::BI__builtin_ia32_fpclassps128_mask:
@@ -1969,15 +2154,7 @@ bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
break;
case X86::BI__builtin_ia32_palignr128:
case X86::BI__builtin_ia32_palignr256:
- case X86::BI__builtin_ia32_palignr128_mask:
- case X86::BI__builtin_ia32_palignr256_mask:
case X86::BI__builtin_ia32_palignr512_mask:
- case X86::BI__builtin_ia32_alignq512_mask:
- case X86::BI__builtin_ia32_alignd512_mask:
- case X86::BI__builtin_ia32_alignd128_mask:
- case X86::BI__builtin_ia32_alignd256_mask:
- case X86::BI__builtin_ia32_alignq128_mask:
- case X86::BI__builtin_ia32_alignq256_mask:
case X86::BI__builtin_ia32_vcomisd:
case X86::BI__builtin_ia32_vcomiss:
case X86::BI__builtin_ia32_shuf_f32x4_mask:
@@ -2271,7 +2448,9 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto,
// Refuse POD arguments that weren't caught by the format string
// checks above.
- if (CallType != VariadicDoesNotApply) {
+ auto *FD = dyn_cast_or_null<FunctionDecl>(FDecl);
+ if (CallType != VariadicDoesNotApply &&
+ (!FD || FD->getBuiltinID() != Builtin::BI__noop)) {
unsigned NumParams = Proto ? Proto->getNumParams()
: FDecl && isa<FunctionDecl>(FDecl)
? cast<FunctionDecl>(FDecl)->getNumParams()
@@ -2340,7 +2519,9 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall,
if (!FnInfo)
return false;
- CheckAbsoluteValueFunction(TheCall, FDecl, FnInfo);
+ CheckAbsoluteValueFunction(TheCall, FDecl);
+ CheckMaxUnsignedZero(TheCall, FDecl);
+
if (getLangOpts().ObjC1)
DiagnoseCStringFormatDirectiveInCFAPI(*this, FDecl, Args, NumArgs);
@@ -2691,6 +2872,9 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
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.
+ CheckNonNullArgument(*this, ValArg, DRE->getLocStart());
unsigned AS = 0;
// Keep address space of non-atomic pointer type.
if (const PointerType *PtrTy =
@@ -3267,21 +3451,46 @@ bool Sema::CheckObjCString(Expr *Arg) {
if (Literal->containsNonAsciiOrNull()) {
StringRef String = Literal->getString();
unsigned NumBytes = String.size();
- SmallVector<UTF16, 128> ToBuf(NumBytes);
- const UTF8 *FromPtr = (const UTF8 *)String.data();
- UTF16 *ToPtr = &ToBuf[0];
-
- ConversionResult Result = ConvertUTF8toUTF16(&FromPtr, FromPtr + NumBytes,
- &ToPtr, ToPtr + NumBytes,
- strictConversion);
+ SmallVector<llvm::UTF16, 128> ToBuf(NumBytes);
+ const llvm::UTF8 *FromPtr = (const llvm::UTF8 *)String.data();
+ llvm::UTF16 *ToPtr = &ToBuf[0];
+
+ llvm::ConversionResult Result =
+ llvm::ConvertUTF8toUTF16(&FromPtr, FromPtr + NumBytes, &ToPtr,
+ ToPtr + NumBytes, llvm::strictConversion);
// Check for conversion failure.
- if (Result != conversionOK)
+ if (Result != llvm::conversionOK)
Diag(Arg->getLocStart(),
diag::warn_cfstring_truncated) << Arg->getSourceRange();
}
return false;
}
+/// CheckObjCString - Checks that the format string argument to the os_log()
+/// and os_trace() functions is correct, and converts it to const char *.
+ExprResult Sema::CheckOSLogFormatStringArg(Expr *Arg) {
+ Arg = Arg->IgnoreParenCasts();
+ auto *Literal = dyn_cast<StringLiteral>(Arg);
+ if (!Literal) {
+ if (auto *ObjcLiteral = dyn_cast<ObjCStringLiteral>(Arg)) {
+ Literal = ObjcLiteral->getString();
+ }
+ }
+
+ if (!Literal || (!Literal->isAscii() && !Literal->isUTF8())) {
+ return ExprError(
+ Diag(Arg->getLocStart(), diag::err_os_log_format_not_string_constant)
+ << Arg->getSourceRange());
+ }
+
+ ExprResult Result(Literal);
+ QualType ResultTy = Context.getPointerType(Context.CharTy.withConst());
+ InitializedEntity Entity =
+ InitializedEntity::InitializeParameter(Context, ResultTy, false);
+ Result = PerformCopyInitialization(Entity, SourceLocation(), Result);
+ return Result;
+}
+
/// Check the arguments to '__builtin_va_start' or '__builtin_ms_va_start'
/// for validity. Emit an error and return true on failure; return false
/// on success.
@@ -3357,8 +3566,17 @@ bool Sema::SemaBuiltinVAStartImpl(CallExpr *TheCall) {
Diag(TheCall->getArg(1)->getLocStart(),
diag::warn_second_arg_of_va_start_not_last_named_param);
else if (IsCRegister || Type->isReferenceType() ||
- Type->isPromotableIntegerType() ||
- Type->isSpecificBuiltinType(BuiltinType::Float)) {
+ Type->isSpecificBuiltinType(BuiltinType::Float) || [=] {
+ // Promotable integers are UB, but enumerations need a bit of
+ // extra checking to see what their promotable type actually is.
+ if (!Type->isPromotableIntegerType())
+ return false;
+ if (!Type->isEnumeralType())
+ return true;
+ const EnumDecl *ED = Type->getAs<EnumType>()->getDecl();
+ return !(ED &&
+ Context.typesAreCompatible(ED->getPromotionType(), Type));
+ }()) {
unsigned Reason = 0;
if (Type->isReferenceType()) Reason = 1;
else if (IsCRegister) Reason = 2;
@@ -3532,14 +3750,18 @@ 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 -> double, remove it.
+ // If this is an implicit conversion from float -> float or double, remove it.
if (ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(OrigArg)) {
- Expr *CastArg = Cast->getSubExpr();
- if (CastArg->getType()->isSpecificBuiltinType(BuiltinType::Float)) {
- assert(Cast->getType()->isSpecificBuiltinType(BuiltinType::Double) &&
- "promotion from float to double is the only expected cast here");
- Cast->setSubExpr(nullptr);
- TheCall->setArg(NumArgs-1, CastArg);
+ // 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");
+ Cast->setSubExpr(nullptr);
+ TheCall->setArg(NumArgs-1, CastArg);
+ }
}
}
@@ -3696,6 +3918,42 @@ bool Sema::SemaBuiltinAssume(CallExpr *TheCall) {
return false;
}
+/// Handle __builtin_alloca_with_align. This is declared
+/// as (size_t, size_t) where the second size_t must be a power of 2 greater
+/// than 8.
+bool Sema::SemaBuiltinAllocaWithAlign(CallExpr *TheCall) {
+ // The alignment must be a constant integer.
+ Expr *Arg = TheCall->getArg(1);
+
+ // We can't check the value of a dependent argument.
+ if (!Arg->isTypeDependent() && !Arg->isValueDependent()) {
+ if (const auto *UE =
+ dyn_cast<UnaryExprOrTypeTraitExpr>(Arg->IgnoreParenImpCasts()))
+ if (UE->getKind() == UETT_AlignOf)
+ Diag(TheCall->getLocStart(), diag::warn_alloca_align_alignof)
+ << Arg->getSourceRange();
+
+ llvm::APSInt Result = Arg->EvaluateKnownConstInt(Context);
+
+ if (!Result.isPowerOf2())
+ return Diag(TheCall->getLocStart(),
+ diag::err_alignment_not_power_of_two)
+ << Arg->getSourceRange();
+
+ if (Result < Context.getCharWidth())
+ return Diag(TheCall->getLocStart(), diag::err_alignment_too_small)
+ << (unsigned)Context.getCharWidth()
+ << Arg->getSourceRange();
+
+ if (Result > INT32_MAX)
+ return Diag(TheCall->getLocStart(), diag::err_alignment_too_big)
+ << INT32_MAX
+ << Arg->getSourceRange();
+ }
+
+ return false;
+}
+
/// Handle __builtin_assume_aligned. This is declared
/// as (const void*, size_t, ...) and can take one optional constant int arg.
bool Sema::SemaBuiltinAssumeAligned(CallExpr *TheCall) {
@@ -3734,6 +3992,86 @@ bool Sema::SemaBuiltinAssumeAligned(CallExpr *TheCall) {
return false;
}
+bool Sema::SemaBuiltinOSLogFormat(CallExpr *TheCall) {
+ unsigned BuiltinID =
+ cast<FunctionDecl>(TheCall->getCalleeDecl())->getBuiltinID();
+ bool IsSizeCall = BuiltinID == Builtin::BI__builtin_os_log_format_buffer_size;
+
+ unsigned NumArgs = TheCall->getNumArgs();
+ unsigned NumRequiredArgs = IsSizeCall ? 1 : 2;
+ if (NumArgs < NumRequiredArgs) {
+ return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args)
+ << 0 /* function call */ << NumRequiredArgs << NumArgs
+ << TheCall->getSourceRange();
+ }
+ if (NumArgs >= NumRequiredArgs + 0x100) {
+ return Diag(TheCall->getLocEnd(),
+ diag::err_typecheck_call_too_many_args_at_most)
+ << 0 /* function call */ << (NumRequiredArgs + 0xff) << NumArgs
+ << TheCall->getSourceRange();
+ }
+ unsigned i = 0;
+
+ // For formatting call, check buffer arg.
+ if (!IsSizeCall) {
+ ExprResult Arg(TheCall->getArg(i));
+ InitializedEntity Entity = InitializedEntity::InitializeParameter(
+ Context, Context.VoidPtrTy, false);
+ Arg = PerformCopyInitialization(Entity, SourceLocation(), Arg);
+ if (Arg.isInvalid())
+ return true;
+ TheCall->setArg(i, Arg.get());
+ i++;
+ }
+
+ // Check string literal arg.
+ unsigned FormatIdx = i;
+ {
+ ExprResult Arg = CheckOSLogFormatStringArg(TheCall->getArg(i));
+ if (Arg.isInvalid())
+ return true;
+ TheCall->setArg(i, Arg.get());
+ i++;
+ }
+
+ // Make sure variadic args are scalar.
+ unsigned FirstDataArg = i;
+ while (i < NumArgs) {
+ ExprResult Arg = DefaultVariadicArgumentPromotion(
+ TheCall->getArg(i), VariadicFunction, nullptr);
+ if (Arg.isInvalid())
+ return true;
+ CharUnits ArgSize = Context.getTypeSizeInChars(Arg.get()->getType());
+ if (ArgSize.getQuantity() >= 0x100) {
+ return Diag(Arg.get()->getLocEnd(), diag::err_os_log_argument_too_big)
+ << i << (int)ArgSize.getQuantity() << 0xff
+ << TheCall->getSourceRange();
+ }
+ TheCall->setArg(i, Arg.get());
+ i++;
+ }
+
+ // Check formatting specifiers. NOTE: We're only doing this for the non-size
+ // call to avoid duplicate diagnostics.
+ if (!IsSizeCall) {
+ llvm::SmallBitVector CheckedVarArgs(NumArgs, false);
+ ArrayRef<const Expr *> Args(TheCall->getArgs(), TheCall->getNumArgs());
+ bool Success = CheckFormatArguments(
+ Args, /*HasVAListArg*/ false, FormatIdx, FirstDataArg, FST_OSLog,
+ VariadicFunction, TheCall->getLocStart(), SourceRange(),
+ CheckedVarArgs);
+ if (!Success)
+ return true;
+ }
+
+ if (IsSizeCall) {
+ TheCall->setType(Context.getSizeType());
+ } else {
+ TheCall->setType(Context.VoidPtrTy);
+ }
+ return false;
+}
+
/// SemaBuiltinConstantArg - Handle a check if argument ArgNum of CallExpr
/// TheCall is a constant expression.
bool Sema::SemaBuiltinConstantArg(CallExpr *TheCall, int ArgNum,
@@ -3861,7 +4199,7 @@ bool Sema::SemaBuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall,
SmallVector<int, 5> Ranges;
if (FiveFields)
- Ranges.append({IsAArch64Builtin ? 1 : 15, 7, 7, 15, 15});
+ Ranges.append({IsAArch64Builtin ? 1 : 15, 7, 15, 15, 7});
else
Ranges.append({15, 7, 15});
@@ -3980,7 +4318,95 @@ enum StringLiteralCheckType {
};
} // end anonymous namespace
-static void CheckFormatString(Sema &S, const StringLiteral *FExpr,
+static void sumOffsets(llvm::APSInt &Offset, llvm::APSInt Addend,
+ BinaryOperatorKind BinOpKind,
+ bool AddendIsRight) {
+ unsigned BitWidth = Offset.getBitWidth();
+ unsigned AddendBitWidth = Addend.getBitWidth();
+ // There might be negative interim results.
+ if (Addend.isUnsigned()) {
+ Addend = Addend.zext(++AddendBitWidth);
+ Addend.setIsSigned(true);
+ }
+ // Adjust the bit width of the APSInts.
+ if (AddendBitWidth > BitWidth) {
+ Offset = Offset.sext(AddendBitWidth);
+ BitWidth = AddendBitWidth;
+ } else if (BitWidth > AddendBitWidth) {
+ Addend = Addend.sext(BitWidth);
+ }
+
+ bool Ov = false;
+ llvm::APSInt ResOffset = Offset;
+ if (BinOpKind == BO_Add)
+ ResOffset = Offset.sadd_ov(Addend, Ov);
+ else {
+ assert(AddendIsRight && BinOpKind == BO_Sub &&
+ "operator must be add or sub with addend on the right");
+ ResOffset = Offset.ssub_ov(Addend, Ov);
+ }
+
+ // We add an offset to a pointer here so we should support an offset as big as
+ // possible.
+ if (Ov) {
+ assert(BitWidth <= UINT_MAX / 2 && "index (intermediate) result too big");
+ Offset = Offset.sext(2 * BitWidth);
+ sumOffsets(Offset, Addend, BinOpKind, AddendIsRight);
+ return;
+ }
+
+ Offset = ResOffset;
+}
+
+namespace {
+// This is a wrapper class around StringLiteral to support offsetted string
+// literals as format strings. It takes the offset into account when returning
+// the string and its length or the source locations to display notes correctly.
+class FormatStringLiteral {
+ const StringLiteral *FExpr;
+ int64_t Offset;
+
+ public:
+ FormatStringLiteral(const StringLiteral *fexpr, int64_t Offset = 0)
+ : FExpr(fexpr), Offset(Offset) {}
+
+ StringRef getString() const {
+ return FExpr->getString().drop_front(Offset);
+ }
+
+ unsigned getByteLength() const {
+ return FExpr->getByteLength() - getCharByteWidth() * Offset;
+ }
+ unsigned getLength() const { return FExpr->getLength() - Offset; }
+ unsigned getCharByteWidth() const { return FExpr->getCharByteWidth(); }
+
+ StringLiteral::StringKind getKind() const { return FExpr->getKind(); }
+
+ QualType getType() const { return FExpr->getType(); }
+
+ bool isAscii() const { return FExpr->isAscii(); }
+ bool isWide() const { return FExpr->isWide(); }
+ bool isUTF8() const { return FExpr->isUTF8(); }
+ bool isUTF16() const { return FExpr->isUTF16(); }
+ bool isUTF32() const { return FExpr->isUTF32(); }
+ bool isPascal() const { return FExpr->isPascal(); }
+
+ SourceLocation getLocationOfByte(
+ unsigned ByteNo, const SourceManager &SM, const LangOptions &Features,
+ const TargetInfo &Target, unsigned *StartToken = nullptr,
+ unsigned *StartTokenByteOffset = nullptr) const {
+ return FExpr->getLocationOfByte(ByteNo + Offset, SM, Features, Target,
+ StartToken, StartTokenByteOffset);
+ }
+
+ SourceLocation getLocStart() const LLVM_READONLY {
+ return FExpr->getLocStart().getLocWithOffset(Offset);
+ }
+ SourceLocation getLocEnd() const LLVM_READONLY { return FExpr->getLocEnd(); }
+};
+} // end anonymous namespace
+
+static void CheckFormatString(Sema &S, const FormatStringLiteral *FExpr,
const Expr *OrigFormatExpr,
ArrayRef<const Expr *> Args,
bool HasVAListArg, unsigned format_idx,
@@ -4001,8 +4427,11 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args,
unsigned firstDataArg, Sema::FormatStringType Type,
Sema::VariadicCallType CallType, bool InFunctionCall,
llvm::SmallBitVector &CheckedVarArgs,
- UncoveredArgHandler &UncoveredArg) {
+ UncoveredArgHandler &UncoveredArg,
+ llvm::APSInt Offset) {
tryAgain:
+ assert(Offset.isSigned() && "invalid offset");
+
if (E->isTypeDependent() || E->isValueDependent())
return SLCT_NotALiteral;
@@ -4036,6 +4465,10 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args,
CheckLeft = false;
}
+ // We need to maintain the offsets for the right and the left hand side
+ // separately to check if every possible indexed expression is a valid
+ // string literal. They might have different offsets for different string
+ // literals in the end.
StringLiteralCheckType Left;
if (!CheckLeft)
Left = SLCT_UncheckedLiteral;
@@ -4043,16 +4476,17 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args,
Left = checkFormatStringExpr(S, C->getTrueExpr(), Args,
HasVAListArg, format_idx, firstDataArg,
Type, CallType, InFunctionCall,
- CheckedVarArgs, UncoveredArg);
- if (Left == SLCT_NotALiteral || !CheckRight)
+ CheckedVarArgs, UncoveredArg, Offset);
+ if (Left == SLCT_NotALiteral || !CheckRight) {
return Left;
+ }
}
StringLiteralCheckType Right =
checkFormatStringExpr(S, C->getFalseExpr(), Args,
HasVAListArg, format_idx, firstDataArg,
Type, CallType, InFunctionCall, CheckedVarArgs,
- UncoveredArg);
+ UncoveredArg, Offset);
return (CheckLeft && Left < Right) ? Left : Right;
}
@@ -4105,8 +4539,8 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args,
return checkFormatStringExpr(S, Init, Args,
HasVAListArg, format_idx,
firstDataArg, Type, CallType,
- /*InFunctionCall*/false, CheckedVarArgs,
- UncoveredArg);
+ /*InFunctionCall*/ false, CheckedVarArgs,
+ UncoveredArg, Offset);
}
}
@@ -4161,7 +4595,7 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args,
return checkFormatStringExpr(S, Arg, Args,
HasVAListArg, format_idx, firstDataArg,
Type, CallType, InFunctionCall,
- CheckedVarArgs, UncoveredArg);
+ CheckedVarArgs, UncoveredArg, Offset);
} else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
unsigned BuiltinID = FD->getBuiltinID();
if (BuiltinID == Builtin::BI__builtin___CFStringMakeConstantString ||
@@ -4171,13 +4605,27 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args,
HasVAListArg, format_idx,
firstDataArg, Type, CallType,
InFunctionCall, CheckedVarArgs,
- UncoveredArg);
+ UncoveredArg, Offset);
}
}
}
return SLCT_NotALiteral;
}
+ case Stmt::ObjCMessageExprClass: {
+ 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);
+ return checkFormatStringExpr(
+ S, Arg, Args, HasVAListArg, format_idx, firstDataArg, Type,
+ CallType, InFunctionCall, CheckedVarArgs, UncoveredArg, Offset);
+ }
+ }
+
+ return SLCT_NotALiteral;
+ }
case Stmt::ObjCStringLiteralClass:
case Stmt::StringLiteralClass: {
const StringLiteral *StrE = nullptr;
@@ -4188,7 +4636,13 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args,
StrE = cast<StringLiteral>(E);
if (StrE) {
- CheckFormatString(S, StrE, E, Args, HasVAListArg, format_idx,
+ if (Offset.isNegative() || Offset > StrE->getLength()) {
+ // TODO: It would be better to have an explicit warning for out of
+ // bounds literals.
+ return SLCT_NotALiteral;
+ }
+ FormatStringLiteral FStr(StrE, Offset.sextOrTrunc(64).getSExtValue());
+ CheckFormatString(S, &FStr, E, Args, HasVAListArg, format_idx,
firstDataArg, Type, InFunctionCall, CallType,
CheckedVarArgs, UncoveredArg);
return SLCT_CheckedLiteral;
@@ -4196,6 +4650,50 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args,
return SLCT_NotALiteral;
}
+ case Stmt::BinaryOperatorClass: {
+ llvm::APSInt LResult;
+ llvm::APSInt RResult;
+
+ const BinaryOperator *BinOp = cast<BinaryOperator>(E);
+
+ // A string literal + an int offset is still a string literal.
+ if (BinOp->isAdditiveOp()) {
+ bool LIsInt = BinOp->getLHS()->EvaluateAsInt(LResult, S.Context);
+ bool RIsInt = BinOp->getRHS()->EvaluateAsInt(RResult, S.Context);
+
+ if (LIsInt != RIsInt) {
+ BinaryOperatorKind BinOpKind = BinOp->getOpcode();
+
+ if (LIsInt) {
+ if (BinOpKind == BO_Add) {
+ sumOffsets(Offset, LResult, BinOpKind, RIsInt);
+ E = BinOp->getRHS();
+ goto tryAgain;
+ }
+ } else {
+ sumOffsets(Offset, RResult, BinOpKind, RIsInt);
+ E = BinOp->getLHS();
+ goto tryAgain;
+ }
+ }
+ }
+
+ return SLCT_NotALiteral;
+ }
+ case Stmt::UnaryOperatorClass: {
+ const UnaryOperator *UnaOp = cast<UnaryOperator>(E);
+ auto ASE = dyn_cast<ArraySubscriptExpr>(UnaOp->getSubExpr());
+ if (UnaOp->getOpcode() == clang::UO_AddrOf && ASE) {
+ llvm::APSInt IndexResult;
+ if (ASE->getRHS()->EvaluateAsInt(IndexResult, S.Context)) {
+ sumOffsets(Offset, IndexResult, BO_Add, /*RHS is int*/ true);
+ E = ASE->getBase();
+ goto tryAgain;
+ }
+ }
+
+ return SLCT_NotALiteral;
+ }
default:
return SLCT_NotALiteral;
@@ -4204,15 +4702,16 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args,
Sema::FormatStringType Sema::GetFormatStringType(const FormatAttr *Format) {
return llvm::StringSwitch<FormatStringType>(Format->getType()->getName())
- .Case("scanf", FST_Scanf)
- .Cases("printf", "printf0", FST_Printf)
- .Cases("NSString", "CFString", FST_NSString)
- .Case("strftime", FST_Strftime)
- .Case("strfmon", FST_Strfmon)
- .Cases("kprintf", "cmn_err", "vcmn_err", "zcmn_err", FST_Kprintf)
- .Case("freebsd_kprintf", FST_FreeBSDKPrintf)
- .Case("os_trace", FST_OSTrace)
- .Default(FST_Unknown);
+ .Case("scanf", FST_Scanf)
+ .Cases("printf", "printf0", FST_Printf)
+ .Cases("NSString", "CFString", FST_NSString)
+ .Case("strftime", FST_Strftime)
+ .Case("strfmon", FST_Strfmon)
+ .Cases("kprintf", "cmn_err", "vcmn_err", "zcmn_err", FST_Kprintf)
+ .Case("freebsd_kprintf", FST_FreeBSDKPrintf)
+ .Case("os_trace", FST_OSLog)
+ .Case("os_log", FST_OSLog)
+ .Default(FST_Unknown);
}
/// CheckFormatArguments - Check calls to printf and scanf (and similar
@@ -4262,8 +4761,9 @@ bool Sema::CheckFormatArguments(ArrayRef<const Expr *> Args,
StringLiteralCheckType CT =
checkFormatStringExpr(*this, OrigFormatExpr, Args, HasVAListArg,
format_idx, firstDataArg, Type, CallType,
- /*IsFunctionCall*/true, CheckedVarArgs,
- UncoveredArg);
+ /*IsFunctionCall*/ true, CheckedVarArgs,
+ UncoveredArg,
+ /*no string offset*/ llvm::APSInt(64, false) = 0);
// Generate a diagnostic where an uncovered argument is detected.
if (UncoveredArg.hasUncoveredArg()) {
@@ -4319,8 +4819,9 @@ namespace {
class CheckFormatHandler : public analyze_format_string::FormatStringHandler {
protected:
Sema &S;
- const StringLiteral *FExpr;
+ const FormatStringLiteral *FExpr;
const Expr *OrigFormatExpr;
+ const Sema::FormatStringType FSType;
const unsigned FirstDataArg;
const unsigned NumDataArgs;
const char *Beg; // Start of format string.
@@ -4336,21 +4837,20 @@ protected:
UncoveredArgHandler &UncoveredArg;
public:
- CheckFormatHandler(Sema &s, const StringLiteral *fexpr,
- const Expr *origFormatExpr, unsigned firstDataArg,
+ CheckFormatHandler(Sema &s, const FormatStringLiteral *fexpr,
+ const Expr *origFormatExpr,
+ const Sema::FormatStringType type, unsigned firstDataArg,
unsigned numDataArgs, const char *beg, bool hasVAListArg,
- ArrayRef<const Expr *> Args,
- unsigned formatIdx, bool inFunctionCall,
- Sema::VariadicCallType callType,
+ ArrayRef<const Expr *> Args, unsigned formatIdx,
+ bool inFunctionCall, Sema::VariadicCallType callType,
llvm::SmallBitVector &CheckedVarArgs,
UncoveredArgHandler &UncoveredArg)
- : S(s), FExpr(fexpr), OrigFormatExpr(origFormatExpr),
- FirstDataArg(firstDataArg), NumDataArgs(numDataArgs),
- Beg(beg), HasVAListArg(hasVAListArg),
- Args(Args), FormatIdx(formatIdx),
- usesPositionalArgs(false), atFirstArg(true),
- inFunctionCall(inFunctionCall), CallType(callType),
- CheckedVarArgs(CheckedVarArgs), UncoveredArg(UncoveredArg) {
+ : S(s), FExpr(fexpr), OrigFormatExpr(origFormatExpr), FSType(type),
+ FirstDataArg(firstDataArg), NumDataArgs(numDataArgs), Beg(beg),
+ HasVAListArg(hasVAListArg), Args(Args), FormatIdx(formatIdx),
+ usesPositionalArgs(false), atFirstArg(true),
+ inFunctionCall(inFunctionCall), CallType(callType),
+ CheckedVarArgs(CheckedVarArgs), UncoveredArg(UncoveredArg) {
CoveredArgs.resize(numDataArgs);
CoveredArgs.reset();
}
@@ -4436,7 +4936,8 @@ getSpecifierRange(const char *startSpecifier, unsigned specifierLen) {
}
SourceLocation CheckFormatHandler::getLocationOfByte(const char *x) {
- return S.getLocationOfStringLiteralByte(FExpr, x - Beg);
+ return FExpr->getLocationOfByte(x - Beg, S.getSourceManager(),
+ S.getLangOpts(), S.Context.getTargetInfo());
}
void CheckFormatHandler::HandleIncompleteSpecifier(const char *startSpecifier,
@@ -4647,16 +5148,16 @@ CheckFormatHandler::HandleInvalidConversionSpecifier(unsigned argIndex,
// hex value.
std::string CodePointStr;
if (!llvm::sys::locale::isPrint(*csStart)) {
- UTF32 CodePoint;
- const UTF8 **B = reinterpret_cast<const UTF8 **>(&csStart);
- const UTF8 *E =
- reinterpret_cast<const UTF8 *>(csStart + csLen);
- ConversionResult Result =
- llvm::convertUTF8Sequence(B, E, &CodePoint, strictConversion);
-
- if (Result != conversionOK) {
+ llvm::UTF32 CodePoint;
+ const llvm::UTF8 **B = reinterpret_cast<const llvm::UTF8 **>(&csStart);
+ const llvm::UTF8 *E =
+ reinterpret_cast<const llvm::UTF8 *>(csStart + csLen);
+ llvm::ConversionResult Result =
+ llvm::convertUTF8Sequence(B, E, &CodePoint, llvm::strictConversion);
+
+ if (Result != llvm::conversionOK) {
unsigned char FirstChar = *csStart;
- CodePoint = (UTF32)FirstChar;
+ CodePoint = (llvm::UTF32)FirstChar;
}
llvm::raw_string_ostream OS(CodePointStr);
@@ -4772,24 +5273,28 @@ void CheckFormatHandler::EmitFormatDiagnostic(
namespace {
class CheckPrintfHandler : public CheckFormatHandler {
- bool ObjCContext;
-
public:
- CheckPrintfHandler(Sema &s, const StringLiteral *fexpr,
- const Expr *origFormatExpr, unsigned firstDataArg,
- unsigned numDataArgs, bool isObjC,
- const char *beg, bool hasVAListArg,
- ArrayRef<const Expr *> Args,
+ CheckPrintfHandler(Sema &s, const FormatStringLiteral *fexpr,
+ const Expr *origFormatExpr,
+ const Sema::FormatStringType type, unsigned firstDataArg,
+ unsigned numDataArgs, bool isObjC, const char *beg,
+ bool hasVAListArg, ArrayRef<const Expr *> Args,
unsigned formatIdx, bool inFunctionCall,
Sema::VariadicCallType CallType,
llvm::SmallBitVector &CheckedVarArgs,
UncoveredArgHandler &UncoveredArg)
- : CheckFormatHandler(s, fexpr, origFormatExpr, firstDataArg,
- numDataArgs, beg, hasVAListArg, Args,
- formatIdx, inFunctionCall, CallType, CheckedVarArgs,
- UncoveredArg),
- ObjCContext(isObjC)
- {}
+ : CheckFormatHandler(s, fexpr, origFormatExpr, type, firstDataArg,
+ numDataArgs, beg, hasVAListArg, Args, formatIdx,
+ inFunctionCall, CallType, CheckedVarArgs,
+ UncoveredArg) {}
+
+ bool isObjCContext() const { return FSType == Sema::FST_NSString; }
+
+ /// Returns true if '%@' specifiers are allowed in the format string.
+ bool allowsObjCArg() const {
+ return FSType == Sema::FST_NSString || FSType == Sema::FST_OSLog ||
+ FSType == Sema::FST_OSTrace;
+ }
bool HandleInvalidPrintfConversionSpecifier(
const analyze_printf::PrintfSpecifier &FS,
@@ -5143,11 +5648,54 @@ CheckPrintfHandler::HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier
// Check for using an Objective-C specific conversion specifier
// in a non-ObjC literal.
- if (!ObjCContext && CS.isObjCArg()) {
+ if (!allowsObjCArg() && CS.isObjCArg()) {
+ return HandleInvalidPrintfConversionSpecifier(FS, startSpecifier,
+ specifierLen);
+ }
+
+ // %P can only be used with os_log.
+ if (FSType != Sema::FST_OSLog && CS.getKind() == ConversionSpecifier::PArg) {
return HandleInvalidPrintfConversionSpecifier(FS, startSpecifier,
specifierLen);
}
+ // %n is not allowed with os_log.
+ if (FSType == Sema::FST_OSLog && CS.getKind() == ConversionSpecifier::nArg) {
+ EmitFormatDiagnostic(S.PDiag(diag::warn_os_log_format_narg),
+ getLocationOfByte(CS.getStart()),
+ /*IsStringLocation*/ false,
+ getSpecifierRange(startSpecifier, specifierLen));
+
+ return true;
+ }
+
+ // Only scalars are allowed for os_trace.
+ if (FSType == Sema::FST_OSTrace &&
+ (CS.getKind() == ConversionSpecifier::PArg ||
+ CS.getKind() == ConversionSpecifier::sArg ||
+ CS.getKind() == ConversionSpecifier::ObjCObjArg)) {
+ return HandleInvalidPrintfConversionSpecifier(FS, startSpecifier,
+ specifierLen);
+ }
+
+ // Check for use of public/private annotation outside of os_log().
+ if (FSType != Sema::FST_OSLog) {
+ if (FS.isPublic().isSet()) {
+ EmitFormatDiagnostic(S.PDiag(diag::warn_format_invalid_annotation)
+ << "public",
+ getLocationOfByte(FS.isPublic().getPosition()),
+ /*IsStringLocation*/ false,
+ getSpecifierRange(startSpecifier, specifierLen));
+ }
+ if (FS.isPrivate().isSet()) {
+ EmitFormatDiagnostic(S.PDiag(diag::warn_format_invalid_annotation)
+ << "private",
+ getLocationOfByte(FS.isPrivate().getPosition()),
+ /*IsStringLocation*/ false,
+ getSpecifierRange(startSpecifier, specifierLen));
+ }
+ }
+
// Check for invalid use of field width
if (!FS.hasValidFieldWidth()) {
HandleInvalidAmount(FS, FS.getFieldWidth(), /* field width */ 0,
@@ -5160,6 +5708,15 @@ CheckPrintfHandler::HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier
startSpecifier, specifierLen);
}
+ // Precision is mandatory for %P specifier.
+ if (CS.getKind() == ConversionSpecifier::PArg &&
+ FS.getPrecision().getHowSpecified() == OptionalAmount::NotSpecified) {
+ EmitFormatDiagnostic(S.PDiag(diag::warn_format_P_no_precision),
+ getLocationOfByte(startSpecifier),
+ /*IsStringLocation*/ false,
+ getSpecifierRange(startSpecifier, specifierLen));
+ }
+
// Check each flag does not conflict with any other component.
if (!FS.hasValidThousandsGroupingPrefix())
HandleFlag(FS, FS.hasThousandsGrouping(), startSpecifier, specifierLen);
@@ -5309,8 +5866,7 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
using namespace analyze_printf;
// Now type check the data expression that matches the
// format specifier.
- const analyze_printf::ArgType &AT = FS.getArgType(S.Context,
- ObjCContext);
+ const analyze_printf::ArgType &AT = FS.getArgType(S.Context, isObjCContext());
if (!AT.isValid())
return true;
@@ -5365,7 +5921,7 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
// If the argument is an integer of some kind, believe the %C and suggest
// a cast instead of changing the conversion specifier.
QualType IntendedTy = ExprTy;
- if (ObjCContext &&
+ if (isObjCContext() &&
FS.getConversionSpecifier().getKind() == ConversionSpecifier::CArg) {
if (ExprTy->isIntegralOrUnscopedEnumerationType() &&
!ExprTy->isCharType()) {
@@ -5406,8 +5962,8 @@ 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 = fixedFS.fixType(IntendedTy, S.getLangOpts(),
- S.Context, ObjCContext);
+ bool success =
+ fixedFS.fixType(IntendedTy, S.getLangOpts(), S.Context, isObjCContext());
if (success) {
// Get the fix string from the fixed format specifier
@@ -5562,20 +6118,19 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
namespace {
class CheckScanfHandler : public CheckFormatHandler {
public:
- CheckScanfHandler(Sema &s, const StringLiteral *fexpr,
- const Expr *origFormatExpr, unsigned firstDataArg,
- unsigned numDataArgs, const char *beg, bool hasVAListArg,
- ArrayRef<const Expr *> Args,
- unsigned formatIdx, bool inFunctionCall,
- Sema::VariadicCallType CallType,
+ CheckScanfHandler(Sema &s, const FormatStringLiteral *fexpr,
+ const Expr *origFormatExpr, Sema::FormatStringType type,
+ unsigned firstDataArg, unsigned numDataArgs,
+ const char *beg, bool hasVAListArg,
+ ArrayRef<const Expr *> Args, unsigned formatIdx,
+ bool inFunctionCall, Sema::VariadicCallType CallType,
llvm::SmallBitVector &CheckedVarArgs,
UncoveredArgHandler &UncoveredArg)
- : CheckFormatHandler(s, fexpr, origFormatExpr, firstDataArg,
- numDataArgs, beg, hasVAListArg,
- Args, formatIdx, inFunctionCall, CallType,
- CheckedVarArgs, UncoveredArg)
- {}
-
+ : CheckFormatHandler(s, fexpr, origFormatExpr, type, firstDataArg,
+ numDataArgs, beg, hasVAListArg, Args, formatIdx,
+ inFunctionCall, CallType, CheckedVarArgs,
+ UncoveredArg) {}
+
bool HandleScanfSpecifier(const analyze_scanf::ScanfSpecifier &FS,
const char *startSpecifier,
unsigned specifierLen) override;
@@ -5733,7 +6288,7 @@ bool CheckScanfHandler::HandleScanfSpecifier(
return true;
}
-static void CheckFormatString(Sema &S, const StringLiteral *FExpr,
+static void CheckFormatString(Sema &S, const FormatStringLiteral *FExpr,
const Expr *OrigFormatExpr,
ArrayRef<const Expr *> Args,
bool HasVAListArg, unsigned format_idx,
@@ -5785,13 +6340,13 @@ static void CheckFormatString(Sema &S, const StringLiteral *FExpr,
}
if (Type == Sema::FST_Printf || Type == Sema::FST_NSString ||
- Type == Sema::FST_FreeBSDKPrintf || Type == Sema::FST_OSTrace) {
- CheckPrintfHandler H(S, FExpr, OrigFormatExpr, firstDataArg,
- numDataArgs, (Type == Sema::FST_NSString ||
- Type == Sema::FST_OSTrace),
- Str, HasVAListArg, Args, format_idx,
- inFunctionCall, CallType, CheckedVarArgs,
- UncoveredArg);
+ Type == Sema::FST_FreeBSDKPrintf || Type == Sema::FST_OSLog ||
+ Type == Sema::FST_OSTrace) {
+ CheckPrintfHandler H(
+ S, FExpr, OrigFormatExpr, Type, firstDataArg, numDataArgs,
+ (Type == Sema::FST_NSString || Type == Sema::FST_OSTrace), Str,
+ HasVAListArg, Args, format_idx, inFunctionCall, CallType,
+ CheckedVarArgs, UncoveredArg);
if (!analyze_format_string::ParsePrintfString(H, Str, Str + StrLen,
S.getLangOpts(),
@@ -5799,10 +6354,9 @@ static void CheckFormatString(Sema &S, const StringLiteral *FExpr,
Type == Sema::FST_FreeBSDKPrintf))
H.DoneProcessing();
} else if (Type == Sema::FST_Scanf) {
- CheckScanfHandler H(S, FExpr, OrigFormatExpr, firstDataArg, numDataArgs,
- Str, HasVAListArg, Args, format_idx,
- inFunctionCall, CallType, CheckedVarArgs,
- UncoveredArg);
+ CheckScanfHandler H(S, FExpr, OrigFormatExpr, Type, firstDataArg,
+ numDataArgs, Str, HasVAListArg, Args, format_idx,
+ inFunctionCall, CallType, CheckedVarArgs, UncoveredArg);
if (!analyze_format_string::ParseScanfString(H, Str, Str + StrLen,
S.getLangOpts(),
@@ -6118,23 +6672,14 @@ static void emitReplacement(Sema &S, SourceLocation Loc, SourceRange Range,
<< FunctionName;
}
-static bool IsFunctionStdAbs(const FunctionDecl *FDecl) {
+template <std::size_t StrLen>
+static bool IsStdFunction(const FunctionDecl *FDecl,
+ const char (&Str)[StrLen]) {
if (!FDecl)
return false;
-
- if (!FDecl->getIdentifier() || !FDecl->getIdentifier()->isStr("abs"))
- return false;
-
- const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(FDecl->getDeclContext());
-
- while (ND && ND->isInlineNamespace()) {
- ND = dyn_cast<NamespaceDecl>(ND->getDeclContext());
- }
-
- if (!ND || !ND->getIdentifier() || !ND->getIdentifier()->isStr("std"))
+ if (!FDecl->getIdentifier() || !FDecl->getIdentifier()->isStr(Str))
return false;
-
- if (!isa<TranslationUnitDecl>(ND->getDeclContext()))
+ if (!FDecl->isInStdNamespace())
return false;
return true;
@@ -6142,13 +6687,12 @@ static bool IsFunctionStdAbs(const FunctionDecl *FDecl) {
// Warn when using the wrong abs() function.
void Sema::CheckAbsoluteValueFunction(const CallExpr *Call,
- const FunctionDecl *FDecl,
- IdentifierInfo *FnInfo) {
+ const FunctionDecl *FDecl) {
if (Call->getNumArgs() != 1)
return;
unsigned AbsKind = getAbsoluteValueFunctionKind(FDecl);
- bool IsStdAbs = IsFunctionStdAbs(FDecl);
+ bool IsStdAbs = IsStdFunction(FDecl, "abs");
if (AbsKind == 0 && !IsStdAbs)
return;
@@ -6221,6 +6765,69 @@ void Sema::CheckAbsoluteValueFunction(const CallExpr *Call,
Call->getCallee()->getSourceRange(), NewAbsKind, ArgType);
}
+//===--- CHECK: Warn on use of std::max and unsigned zero. r---------------===//
+void Sema::CheckMaxUnsignedZero(const CallExpr *Call,
+ const FunctionDecl *FDecl) {
+ if (!Call || !FDecl) return;
+
+ // Ignore template specializations and macros.
+ if (!ActiveTemplateInstantiations.empty()) return;
+ if (Call->getExprLoc().isMacroID()) return;
+
+ // Only care about the one template argument, two function parameter std::max
+ if (Call->getNumArgs() != 2) return;
+ if (!IsStdFunction(FDecl, "max")) return;
+ const auto * ArgList = FDecl->getTemplateSpecializationArgs();
+ if (!ArgList) return;
+ if (ArgList->size() != 1) return;
+
+ // Check that template type argument is unsigned integer.
+ const auto& TA = ArgList->get(0);
+ if (TA.getKind() != TemplateArgument::Type) return;
+ QualType ArgType = TA.getAsType();
+ if (!ArgType->isUnsignedIntegerType()) return;
+
+ // See if either argument is a literal zero.
+ auto IsLiteralZeroArg = [](const Expr* E) -> bool {
+ const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E);
+ if (!MTE) return false;
+ const auto *Num = dyn_cast<IntegerLiteral>(MTE->GetTemporaryExpr());
+ if (!Num) return false;
+ if (Num->getValue() != 0) return false;
+ return true;
+ };
+
+ const Expr *FirstArg = Call->getArg(0);
+ const Expr *SecondArg = Call->getArg(1);
+ const bool IsFirstArgZero = IsLiteralZeroArg(FirstArg);
+ const bool IsSecondArgZero = IsLiteralZeroArg(SecondArg);
+
+ // Only warn when exactly one argument is zero.
+ if (IsFirstArgZero == IsSecondArgZero) return;
+
+ SourceRange FirstRange = FirstArg->getSourceRange();
+ SourceRange SecondRange = SecondArg->getSourceRange();
+
+ SourceRange ZeroRange = IsFirstArgZero ? FirstRange : SecondRange;
+
+ Diag(Call->getExprLoc(), diag::warn_max_unsigned_zero)
+ << IsFirstArgZero << Call->getCallee()->getSourceRange() << ZeroRange;
+
+ // Deduce what parts to remove so that "std::max(0u, foo)" becomes "(foo)".
+ SourceRange RemovalRange;
+ if (IsFirstArgZero) {
+ RemovalRange = SourceRange(FirstRange.getBegin(),
+ SecondRange.getBegin().getLocWithOffset(-1));
+ } else {
+ RemovalRange = SourceRange(getLocForEndOfToken(FirstRange.getEnd()),
+ SecondRange.getEnd());
+ }
+
+ Diag(Call->getExprLoc(), diag::note_remove_max_call)
+ << FixItHint::CreateRemoval(Call->getCallee()->getSourceRange())
+ << FixItHint::CreateRemoval(RemovalRange);
+}
+
//===--- CHECK: Standard memory functions ---------------------------------===//
/// \brief Takes the expression passed to the size_t parameter of functions
@@ -6320,13 +6927,15 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call,
// It is possible to have a non-standard definition of memset. Validate
// we have enough arguments, and if not, abort further checking.
- unsigned ExpectedNumArgs = (BId == Builtin::BIstrndup ? 2 : 3);
+ unsigned ExpectedNumArgs =
+ (BId == Builtin::BIstrndup || BId == Builtin::BIbzero ? 2 : 3);
if (Call->getNumArgs() < ExpectedNumArgs)
return;
- unsigned LastArg = (BId == Builtin::BImemset ||
+ unsigned LastArg = (BId == Builtin::BImemset || BId == Builtin::BIbzero ||
BId == Builtin::BIstrndup ? 1 : 2);
- unsigned LenArg = (BId == Builtin::BIstrndup ? 1 : 2);
+ unsigned LenArg =
+ (BId == Builtin::BIbzero || BId == Builtin::BIstrndup ? 1 : 2);
const Expr *LenExpr = Call->getArg(LenArg)->IgnoreParenImpCasts();
if (CheckMemorySizeofForComparison(*this, LenExpr, FnName,
@@ -6338,6 +6947,13 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call,
const Expr *SizeOfArg = getSizeOfExprArg(LenExpr);
llvm::FoldingSetNodeID SizeOfArgID;
+ // Although widely used, 'bzero' is not a standard function. Be more strict
+ // with the argument types before allowing diagnostics and only allow the
+ // form bzero(ptr, sizeof(...)).
+ QualType FirstArgTy = Call->getArg(0)->IgnoreParenImpCasts()->getType();
+ if (BId == Builtin::BIbzero && !FirstArgTy->getAs<PointerType>())
+ return;
+
for (unsigned ArgIdx = 0; ArgIdx != LastArg; ++ArgIdx) {
const Expr *Dest = Call->getArg(ArgIdx)->IgnoreParenImpCasts();
SourceRange ArgRange = Call->getArg(ArgIdx)->getSourceRange();
@@ -7960,6 +8576,24 @@ bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init,
return false;
// White-list bool bitfields.
+ QualType BitfieldType = Bitfield->getType();
+ if (BitfieldType->isBooleanType())
+ return false;
+
+ if (BitfieldType->isEnumeralType()) {
+ EnumDecl *BitfieldEnumDecl = BitfieldType->getAs<EnumType>()->getDecl();
+ // If the underlying enum type was not explicitly specified as an unsigned
+ // type and the enum contain only positive values, MSVC++ will cause an
+ // inconsistency by storing this as a signed type.
+ if (S.getLangOpts().CPlusPlus11 &&
+ !BitfieldEnumDecl->getIntegerTypeSourceInfo() &&
+ BitfieldEnumDecl->getNumPositiveBits() > 0 &&
+ BitfieldEnumDecl->getNumNegativeBits() == 0) {
+ S.Diag(InitLoc, diag::warn_no_underlying_type_specified_for_enum_bitfield)
+ << BitfieldEnumDecl->getNameAsString();
+ }
+ }
+
if (Bitfield->getType()->isBooleanType())
return false;
@@ -7979,18 +8613,17 @@ bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init,
unsigned OriginalWidth = Value.getBitWidth();
unsigned FieldWidth = Bitfield->getBitWidthValue(S.Context);
- if (Value.isSigned() && Value.isNegative())
+ if (!Value.isSigned() || Value.isNegative())
if (UnaryOperator *UO = dyn_cast<UnaryOperator>(OriginalInit))
- if (UO->getOpcode() == UO_Minus)
- if (isa<IntegerLiteral>(UO->getSubExpr()))
- OriginalWidth = Value.getMinSignedBits();
+ if (UO->getOpcode() == UO_Minus || UO->getOpcode() == UO_Not)
+ OriginalWidth = Value.getMinSignedBits();
if (OriginalWidth <= FieldWidth)
return false;
// Compute the value which the bitfield will contain.
llvm::APSInt TruncatedValue = Value.trunc(FieldWidth);
- TruncatedValue.setIsSigned(Bitfield->getType()->isSignedIntegerType());
+ TruncatedValue.setIsSigned(BitfieldType->isSignedIntegerType());
// Check whether the stored value is equal to the original value.
TruncatedValue = TruncatedValue.extend(OriginalWidth);
@@ -8515,6 +9148,8 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
DiagnoseNullConversion(S, E, T, CC);
+ S.DiscardMisalignedMemberAddress(Target, E);
+
if (!Source->isIntegerType() || !Target->isIntegerType())
return;
@@ -8776,25 +9411,19 @@ void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC) {
} // end anonymous namespace
-static bool checkOpenCLEnqueueLocalSizeArgs(Sema &S, CallExpr *TheCall,
- unsigned Start, unsigned End) {
- bool IllegalParams = false;
- for (unsigned I = Start; I <= End; ++I) {
- QualType Ty = TheCall->getArg(I)->getType();
- // Taking into account implicit conversions,
- // allow any integer within 32 bits range
- if (!Ty->isIntegerType() ||
- S.Context.getTypeSizeInChars(Ty).getQuantity() > 4) {
- S.Diag(TheCall->getArg(I)->getLocStart(),
- diag::err_opencl_enqueue_kernel_invalid_local_size_type);
- IllegalParams = true;
- }
- // Potentially emit standard warnings for implicit conversions if enabled
- // using -Wconversion.
- CheckImplicitConversion(S, TheCall->getArg(I), S.Context.UnsignedIntTy,
- TheCall->getArg(I)->getLocStart());
+/// Diagnose integer type and any valid implicit convertion to it.
+static bool checkOpenCLEnqueueIntType(Sema &S, Expr *E, const QualType &IntT) {
+ // Taking into account implicit conversions,
+ // allow any integer.
+ if (!E->getType()->isIntegerType()) {
+ S.Diag(E->getLocStart(),
+ diag::err_opencl_enqueue_kernel_invalid_local_size_type);
+ return true;
}
- return IllegalParams;
+ // Potentially emit standard warnings for implicit conversions if enabled
+ // using -Wconversion.
+ CheckImplicitConversion(S, E, IntT, E->getLocStart());
+ return false;
}
// Helper function for Sema::DiagnoseAlwaysNonNullPointer.
@@ -9585,6 +10214,7 @@ void Sema::CheckCompletedExpr(Expr *E, SourceLocation CheckLoc,
CheckUnsequencedOperations(E);
if (!IsConstexpr && !E->isValueDependent())
CheckForIntOverflow(E);
+ DiagnoseMisalignedMembers();
}
void Sema::CheckBitFieldInitialization(SourceLocation InitLoc,
@@ -9695,6 +10325,19 @@ bool Sema::CheckParmsForFunctionDef(ArrayRef<ParmVarDecl *> Parameters,
return HasInvalidParm;
}
+/// A helper function to get the alignment of a Decl referred to by DeclRefExpr
+/// or MemberExpr.
+static CharUnits getDeclAlign(Expr *E, CharUnits TypeAlign,
+ ASTContext &Context) {
+ if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
+ return Context.getDeclAlign(DRE->getDecl());
+
+ if (const auto *ME = dyn_cast<MemberExpr>(E))
+ return Context.getDeclAlign(ME->getMemberDecl());
+
+ return TypeAlign;
+}
+
/// CheckCastAlign - Implements -Wcast-align, which warns when a
/// pointer cast increases the alignment requirements.
void Sema::CheckCastAlign(Expr *Op, QualType T, SourceRange TRange) {
@@ -9729,6 +10372,15 @@ void Sema::CheckCastAlign(Expr *Op, QualType T, SourceRange TRange) {
if (SrcPointee->isIncompleteType()) return;
CharUnits SrcAlign = Context.getTypeAlignInChars(SrcPointee);
+
+ if (auto *CE = dyn_cast<CastExpr>(Op)) {
+ if (CE->getCastKind() == CK_ArrayToPointerDecay)
+ SrcAlign = getDeclAlign(CE->getSubExpr(), SrcAlign, Context);
+ } else if (auto *UO = dyn_cast<UnaryOperator>(Op)) {
+ if (UO->getOpcode() == UO_AddrOf)
+ SrcAlign = getDeclAlign(UO->getSubExpr(), SrcAlign, Context);
+ }
+
if (SrcAlign >= DestAlign) return;
Diag(TRange.getBegin(), diag::warn_cast_align)
@@ -11130,3 +11782,151 @@ void Sema::CheckArgumentWithTypeTag(const ArgumentWithTypeTagAttr *Attr,
<< ArgumentExpr->getSourceRange()
<< TypeTagExpr->getSourceRange();
}
+
+void Sema::AddPotentialMisalignedMembers(Expr *E, RecordDecl *RD, ValueDecl *MD,
+ CharUnits Alignment) {
+ MisalignedMembers.emplace_back(E, RD, MD, Alignment);
+}
+
+void Sema::DiagnoseMisalignedMembers() {
+ for (MisalignedMember &m : MisalignedMembers) {
+ const NamedDecl *ND = m.RD;
+ if (ND->getName().empty()) {
+ if (const TypedefNameDecl *TD = m.RD->getTypedefNameForAnonDecl())
+ ND = TD;
+ }
+ Diag(m.E->getLocStart(), diag::warn_taking_address_of_packed_member)
+ << m.MD << ND << m.E->getSourceRange();
+ }
+ MisalignedMembers.clear();
+}
+
+void Sema::DiscardMisalignedMemberAddress(const Type *T, Expr *E) {
+ E = E->IgnoreParens();
+ if (!T->isPointerType() && !T->isIntegerType())
+ return;
+ if (isa<UnaryOperator>(E) &&
+ cast<UnaryOperator>(E)->getOpcode() == UO_AddrOf) {
+ auto *Op = cast<UnaryOperator>(E)->getSubExpr()->IgnoreParens();
+ if (isa<MemberExpr>(Op)) {
+ auto MA = std::find(MisalignedMembers.begin(), MisalignedMembers.end(),
+ MisalignedMember(Op));
+ if (MA != MisalignedMembers.end() &&
+ (T->isIntegerType() ||
+ (T->isPointerType() &&
+ Context.getTypeAlignInChars(T->getPointeeType()) <= MA->Alignment)))
+ MisalignedMembers.erase(MA);
+ }
+ }
+}
+
+void Sema::RefersToMemberWithReducedAlignment(
+ Expr *E,
+ llvm::function_ref<void(Expr *, RecordDecl *, FieldDecl *, CharUnits)>
+ Action) {
+ const auto *ME = dyn_cast<MemberExpr>(E);
+ if (!ME)
+ return;
+
+ // For a chain of MemberExpr like "a.b.c.d" this list
+ // will keep FieldDecl's like [d, c, b].
+ SmallVector<FieldDecl *, 4> ReverseMemberChain;
+ const MemberExpr *TopME = nullptr;
+ bool AnyIsPacked = false;
+ do {
+ QualType BaseType = ME->getBase()->getType();
+ if (ME->isArrow())
+ BaseType = BaseType->getPointeeType();
+ RecordDecl *RD = BaseType->getAs<RecordType>()->getDecl();
+
+ ValueDecl *MD = ME->getMemberDecl();
+ auto *FD = dyn_cast<FieldDecl>(MD);
+ // We do not care about non-data members.
+ if (!FD || FD->isInvalidDecl())
+ return;
+
+ AnyIsPacked =
+ AnyIsPacked || (RD->hasAttr<PackedAttr>() || MD->hasAttr<PackedAttr>());
+ ReverseMemberChain.push_back(FD);
+
+ TopME = ME;
+ ME = dyn_cast<MemberExpr>(ME->getBase()->IgnoreParens());
+ } while (ME);
+ assert(TopME && "We did not compute a topmost MemberExpr!");
+
+ // Not the scope of this diagnostic.
+ if (!AnyIsPacked)
+ return;
+
+ const Expr *TopBase = TopME->getBase()->IgnoreParenImpCasts();
+ const auto *DRE = dyn_cast<DeclRefExpr>(TopBase);
+ // TODO: The innermost base of the member expression may be too complicated.
+ // For now, just disregard these cases. This is left for future
+ // improvement.
+ if (!DRE && !isa<CXXThisExpr>(TopBase))
+ return;
+
+ // Alignment expected by the whole expression.
+ CharUnits ExpectedAlignment = Context.getTypeAlignInChars(E->getType());
+
+ // No need to do anything else with this case.
+ if (ExpectedAlignment.isOne())
+ return;
+
+ // Synthesize offset of the whole access.
+ CharUnits Offset;
+ for (auto I = ReverseMemberChain.rbegin(); I != ReverseMemberChain.rend();
+ I++) {
+ Offset += Context.toCharUnitsFromBits(Context.getFieldOffset(*I));
+ }
+
+ // Compute the CompleteObjectAlignment as the alignment of the whole chain.
+ CharUnits CompleteObjectAlignment = Context.getTypeAlignInChars(
+ ReverseMemberChain.back()->getParent()->getTypeForDecl());
+
+ // The base expression of the innermost MemberExpr may give
+ // stronger guarantees than the class containing the member.
+ if (DRE && !TopME->isArrow()) {
+ const ValueDecl *VD = DRE->getDecl();
+ if (!VD->getType()->isReferenceType())
+ CompleteObjectAlignment =
+ std::max(CompleteObjectAlignment, Context.getDeclAlign(VD));
+ }
+
+ // Check if the synthesized offset fulfills the alignment.
+ if (Offset % ExpectedAlignment != 0 ||
+ // It may fulfill the offset it but the effective alignment may still be
+ // lower than the expected expression alignment.
+ CompleteObjectAlignment < ExpectedAlignment) {
+ // If this happens, we want to determine a sensible culprit of this.
+ // Intuitively, watching the chain of member expressions from right to
+ // left, we start with the required alignment (as required by the field
+ // type) but some packed attribute in that chain has reduced the alignment.
+ // It may happen that another packed structure increases it again. But if
+ // we are here such increase has not been enough. So pointing the first
+ // FieldDecl that either is packed or else its RecordDecl is,
+ // seems reasonable.
+ FieldDecl *FD = nullptr;
+ CharUnits Alignment;
+ for (FieldDecl *FDI : ReverseMemberChain) {
+ if (FDI->hasAttr<PackedAttr>() ||
+ FDI->getParent()->hasAttr<PackedAttr>()) {
+ FD = FDI;
+ Alignment = std::min(
+ Context.getTypeAlignInChars(FD->getType()),
+ Context.getTypeAlignInChars(FD->getParent()->getTypeForDecl()));
+ break;
+ }
+ }
+ assert(FD && "We did not find a packed FieldDecl!");
+ Action(E, FD->getParent(), FD, Alignment);
+ }
+}
+
+void Sema::CheckAddressOfPackedMember(Expr *rhs) {
+ using namespace std::placeholders;
+ RefersToMemberWithReducedAlignment(
+ rhs, std::bind(&Sema::AddPotentialMisalignedMembers, std::ref(*this), _1,
+ _2, _3, _4));
+}
+
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index 36babc4bc0cd..d76bde574677 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -2162,6 +2162,60 @@ static std::string formatObjCParamQualifiers(unsigned ObjCQuals,
return Result;
}
+/// \brief 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
+/// present the most relevant and accurate block placeholders in code completion
+/// results.
+static void findTypeLocationForBlockDecl(const TypeSourceInfo *TSInfo,
+ FunctionTypeLoc &Block,
+ FunctionProtoTypeLoc &BlockProto,
+ bool SuppressBlock = false) {
+ if (!TSInfo)
+ return;
+ TypeLoc TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
+ while (true) {
+ // Look through typedefs.
+ if (!SuppressBlock) {
+ if (TypedefTypeLoc TypedefTL = TL.getAs<TypedefTypeLoc>()) {
+ if (TypeSourceInfo *InnerTSInfo =
+ TypedefTL.getTypedefNameDecl()->getTypeSourceInfo()) {
+ TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
+ continue;
+ }
+ }
+
+ // Look through qualified types
+ if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>()) {
+ TL = QualifiedTL.getUnqualifiedLoc();
+ continue;
+ }
+
+ if (AttributedTypeLoc AttrTL = TL.getAs<AttributedTypeLoc>()) {
+ TL = AttrTL.getModifiedLoc();
+ continue;
+ }
+ }
+
+ // Try to get the function prototype behind the block pointer type,
+ // then we're done.
+ if (BlockPointerTypeLoc BlockPtr = TL.getAs<BlockPointerTypeLoc>()) {
+ TL = BlockPtr.getPointeeLoc().IgnoreParens();
+ Block = TL.getAs<FunctionTypeLoc>();
+ BlockProto = TL.getAs<FunctionProtoTypeLoc>();
+ }
+ break;
+ }
+}
+
+static std::string
+formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl,
+ FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto,
+ bool SuppressBlockName = false,
+ bool SuppressBlock = false,
+ Optional<ArrayRef<QualType>> ObjCSubsts = None);
+
static std::string FormatFunctionParameter(const PrintingPolicy &Policy,
const ParmVarDecl *Param,
bool SuppressName = false,
@@ -2192,47 +2246,13 @@ static std::string FormatFunctionParameter(const PrintingPolicy &Policy,
}
return Result;
}
-
+
// The argument for a block pointer parameter is a block literal with
// the appropriate type.
FunctionTypeLoc Block;
FunctionProtoTypeLoc BlockProto;
- TypeLoc TL;
- if (TypeSourceInfo *TSInfo = Param->getTypeSourceInfo()) {
- TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
- while (true) {
- // Look through typedefs.
- if (!SuppressBlock) {
- if (TypedefTypeLoc TypedefTL = TL.getAs<TypedefTypeLoc>()) {
- if (TypeSourceInfo *InnerTSInfo =
- TypedefTL.getTypedefNameDecl()->getTypeSourceInfo()) {
- TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
- continue;
- }
- }
-
- // Look through qualified types
- if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>()) {
- TL = QualifiedTL.getUnqualifiedLoc();
- continue;
- }
-
- if (AttributedTypeLoc AttrTL = TL.getAs<AttributedTypeLoc>()) {
- TL = AttrTL.getModifiedLoc();
- continue;
- }
- }
-
- // Try to get the function prototype behind the block pointer type,
- // then we're done.
- if (BlockPointerTypeLoc BlockPtr = TL.getAs<BlockPointerTypeLoc>()) {
- TL = BlockPtr.getPointeeLoc().IgnoreParens();
- Block = TL.getAs<FunctionTypeLoc>();
- BlockProto = TL.getAs<FunctionProtoTypeLoc>();
- }
- break;
- }
- }
+ findTypeLocationForBlockDecl(Param->getTypeSourceInfo(), Block, BlockProto,
+ SuppressBlock);
if (!Block) {
// We were unable to find a FunctionProtoTypeLoc with parameter names
@@ -2244,9 +2264,13 @@ static std::string FormatFunctionParameter(const PrintingPolicy &Policy,
QualType Type = Param->getType().getUnqualifiedType();
if (ObjCMethodParam) {
- Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier(),
- Type);
- Result += Type.getAsString(Policy) + Result + ")";
+ Result = Type.getAsString(Policy);
+ std::string Quals =
+ formatObjCParamQualifiers(Param->getObjCDeclQualifier(), Type);
+ if (!Quals.empty())
+ Result = "(" + Quals + " " + Result + ")";
+ if (Result.back() != ')')
+ Result += " ";
if (Param->getIdentifier())
Result += Param->getIdentifier()->getName();
} else {
@@ -2255,15 +2279,34 @@ static std::string FormatFunctionParameter(const PrintingPolicy &Policy,
return Result;
}
-
+
// We have the function prototype behind the block pointer type, as it was
// written in the source.
+ return formatBlockPlaceholder(Policy, Param, Block, BlockProto,
+ /*SuppressBlockName=*/false, SuppressBlock,
+ ObjCSubsts);
+}
+
+/// \brief 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
+/// declaration is included in the resulting string.
+static std::string
+formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl,
+ FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto,
+ bool SuppressBlockName, bool SuppressBlock,
+ Optional<ArrayRef<QualType>> ObjCSubsts) {
std::string Result;
QualType ResultType = Block.getTypePtr()->getReturnType();
if (ObjCSubsts)
- ResultType = ResultType.substObjCTypeArgs(Param->getASTContext(),
- *ObjCSubsts,
- ObjCSubstitutionContext::Result);
+ ResultType =
+ ResultType.substObjCTypeArgs(BlockDecl->getASTContext(), *ObjCSubsts,
+ ObjCSubstitutionContext::Result);
if (!ResultType->isVoidType() || SuppressBlock)
ResultType.getAsStringInternal(Result, Policy);
@@ -2281,31 +2324,30 @@ static std::string FormatFunctionParameter(const PrintingPolicy &Policy,
Params += ", ";
Params += FormatFunctionParameter(Policy, Block.getParam(I),
/*SuppressName=*/false,
- /*SuppressBlock=*/true,
- ObjCSubsts);
+ /*SuppressBlock=*/true, ObjCSubsts);
if (I == N - 1 && BlockProto.getTypePtr()->isVariadic())
Params += ", ...";
}
Params += ")";
}
-
+
if (SuppressBlock) {
// Format as a parameter.
Result = Result + " (^";
- if (Param->getIdentifier())
- Result += Param->getIdentifier()->getName();
+ if (!SuppressBlockName && BlockDecl->getIdentifier())
+ Result += BlockDecl->getIdentifier()->getName();
Result += ")";
Result += Params;
} else {
// Format as a block literal argument.
Result = '^' + Result;
Result += Params;
-
- if (Param->getIdentifier())
- Result += Param->getIdentifier()->getName();
+
+ if (!SuppressBlockName && BlockDecl->getIdentifier())
+ Result += BlockDecl->getIdentifier()->getName();
}
-
+
return Result;
}
@@ -3062,6 +3104,7 @@ CXCursorKind clang::getCursorKindForDecl(const Decl *D) {
return CXCursor_ClassTemplatePartialSpecialization;
case Decl::UsingDirective: return CXCursor_UsingDirective;
case Decl::StaticAssert: return CXCursor_StaticAssert;
+ case Decl::Friend: return CXCursor_FriendDecl;
case Decl::TranslationUnit: return CXCursor_TranslationUnit;
case Decl::Using:
@@ -3573,82 +3616,204 @@ static ObjCContainerDecl *getContainerDef(ObjCContainerDecl *Container) {
return Container;
}
-static void AddObjCProperties(const CodeCompletionContext &CCContext,
- ObjCContainerDecl *Container,
- bool AllowCategories,
- bool AllowNullaryMethods,
- DeclContext *CurContext,
- AddedPropertiesSet &AddedProperties,
- ResultBuilder &Results) {
+/// \brief Adds a block invocation code completion result for the given block
+/// declaration \p BD.
+static void AddObjCBlockCall(ASTContext &Context, const PrintingPolicy &Policy,
+ CodeCompletionBuilder &Builder,
+ const NamedDecl *BD,
+ const FunctionTypeLoc &BlockLoc,
+ const FunctionProtoTypeLoc &BlockProtoLoc) {
+ Builder.AddResultTypeChunk(
+ GetCompletionTypeString(BlockLoc.getReturnLoc().getType(), Context,
+ Policy, Builder.getAllocator()));
+
+ AddTypedNameChunk(Context, Policy, BD, Builder);
+ Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+
+ if (BlockProtoLoc && BlockProtoLoc.getTypePtr()->isVariadic()) {
+ Builder.AddPlaceholderChunk("...");
+ } else {
+ for (unsigned I = 0, N = BlockLoc.getNumParams(); I != N; ++I) {
+ if (I)
+ Builder.AddChunk(CodeCompletionString::CK_Comma);
+
+ // Format the placeholder string.
+ std::string PlaceholderStr =
+ FormatFunctionParameter(Policy, BlockLoc.getParam(I));
+
+ if (I == N - 1 && BlockProtoLoc &&
+ BlockProtoLoc.getTypePtr()->isVariadic())
+ PlaceholderStr += ", ...";
+
+ // Add the placeholder string.
+ Builder.AddPlaceholderChunk(
+ Builder.getAllocator().CopyString(PlaceholderStr));
+ }
+ }
+
+ Builder.AddChunk(CodeCompletionString::CK_RightParen);
+}
+
+static void AddObjCProperties(
+ const CodeCompletionContext &CCContext, ObjCContainerDecl *Container,
+ bool AllowCategories, bool AllowNullaryMethods, DeclContext *CurContext,
+ AddedPropertiesSet &AddedProperties, ResultBuilder &Results,
+ bool IsBaseExprStatement = false, bool IsClassProperty = false) {
typedef CodeCompletionResult Result;
// Retrieve the definition.
Container = getContainerDef(Container);
// Add properties in this container.
- for (const auto *P : Container->instance_properties())
- if (AddedProperties.insert(P->getIdentifier()).second)
+ const auto AddProperty = [&](const ObjCPropertyDecl *P) {
+ if (!AddedProperties.insert(P->getIdentifier()).second)
+ return;
+
+ // FIXME: Provide block invocation completion for non-statement
+ // expressions.
+ if (!P->getType().getTypePtr()->isBlockPointerType() ||
+ !IsBaseExprStatement) {
+ Results.MaybeAddResult(Result(P, Results.getBasePriority(P), nullptr),
+ CurContext);
+ return;
+ }
+
+ // Block setter and invocation completion is provided only when we are able
+ // to find the FunctionProtoTypeLoc with parameter names for the block.
+ FunctionTypeLoc BlockLoc;
+ FunctionProtoTypeLoc BlockProtoLoc;
+ findTypeLocationForBlockDecl(P->getTypeSourceInfo(), BlockLoc,
+ BlockProtoLoc);
+ if (!BlockLoc) {
Results.MaybeAddResult(Result(P, Results.getBasePriority(P), nullptr),
CurContext);
+ return;
+ }
- // Add nullary methods
+ // The default completion result for block properties should be the block
+ // invocation completion when the base expression is a statement.
+ CodeCompletionBuilder Builder(Results.getAllocator(),
+ Results.getCodeCompletionTUInfo());
+ AddObjCBlockCall(Container->getASTContext(),
+ getCompletionPrintingPolicy(Results.getSema()), Builder, P,
+ BlockLoc, BlockProtoLoc);
+ Results.MaybeAddResult(
+ Result(Builder.TakeString(), P, Results.getBasePriority(P)),
+ CurContext);
+
+ // Provide additional block setter completion iff the base expression is a
+ // statement and the block property is mutable.
+ if (!P->isReadOnly()) {
+ CodeCompletionBuilder Builder(Results.getAllocator(),
+ Results.getCodeCompletionTUInfo());
+ AddResultTypeChunk(Container->getASTContext(),
+ getCompletionPrintingPolicy(Results.getSema()), P,
+ CCContext.getBaseType(), Builder);
+ Builder.AddTypedTextChunk(
+ Results.getAllocator().CopyString(P->getName()));
+ Builder.AddChunk(CodeCompletionString::CK_Equal);
+
+ std::string PlaceholderStr = formatBlockPlaceholder(
+ getCompletionPrintingPolicy(Results.getSema()), P, BlockLoc,
+ BlockProtoLoc, /*SuppressBlockName=*/true);
+ // Add the placeholder string.
+ Builder.AddPlaceholderChunk(
+ Builder.getAllocator().CopyString(PlaceholderStr));
+
+ Results.MaybeAddResult(
+ Result(Builder.TakeString(), P,
+ Results.getBasePriority(P) + CCD_BlockPropertySetter),
+ CurContext);
+ }
+ };
+
+ if (IsClassProperty) {
+ for (const auto *P : Container->class_properties())
+ AddProperty(P);
+ } else {
+ for (const auto *P : Container->instance_properties())
+ AddProperty(P);
+ }
+
+ // Add nullary methods or implicit class properties
if (AllowNullaryMethods) {
ASTContext &Context = Container->getASTContext();
PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
- for (auto *M : Container->methods()) {
- if (M->getSelector().isUnarySelector())
- if (IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0))
- if (AddedProperties.insert(Name).second) {
- CodeCompletionBuilder Builder(Results.getAllocator(),
- Results.getCodeCompletionTUInfo());
- AddResultTypeChunk(Context, Policy, M, CCContext.getBaseType(),
- Builder);
- Builder.AddTypedTextChunk(
- Results.getAllocator().CopyString(Name->getName()));
-
- Results.MaybeAddResult(Result(Builder.TakeString(), M,
- CCP_MemberDeclaration + CCD_MethodAsProperty),
- CurContext);
- }
+ // Adds a method result
+ const auto AddMethod = [&](const ObjCMethodDecl *M) {
+ IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0);
+ if (!Name)
+ return;
+ if (!AddedProperties.insert(Name).second)
+ return;
+ CodeCompletionBuilder Builder(Results.getAllocator(),
+ Results.getCodeCompletionTUInfo());
+ AddResultTypeChunk(Context, Policy, M, CCContext.getBaseType(), Builder);
+ Builder.AddTypedTextChunk(
+ Results.getAllocator().CopyString(Name->getName()));
+ Results.MaybeAddResult(
+ Result(Builder.TakeString(), M,
+ CCP_MemberDeclaration + CCD_MethodAsProperty),
+ CurContext);
+ };
+
+ if (IsClassProperty) {
+ for (const auto *M : Container->methods()) {
+ // Gather the class method that can be used as implicit property
+ // getters. Methods with arguments or methods that return void aren't
+ // added to the results as they can't be used as a getter.
+ if (!M->getSelector().isUnarySelector() ||
+ M->getReturnType()->isVoidType() || M->isInstanceMethod())
+ continue;
+ AddMethod(M);
+ }
+ } else {
+ for (auto *M : Container->methods()) {
+ if (M->getSelector().isUnarySelector())
+ AddMethod(M);
+ }
}
}
-
// Add properties in referenced protocols.
if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
for (auto *P : Protocol->protocols())
AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
- CurContext, AddedProperties, Results);
+ CurContext, AddedProperties, Results,
+ IsBaseExprStatement, IsClassProperty);
} else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){
if (AllowCategories) {
// Look through categories.
for (auto *Cat : IFace->known_categories())
AddObjCProperties(CCContext, Cat, AllowCategories, AllowNullaryMethods,
- CurContext, AddedProperties, Results);
+ CurContext, AddedProperties, Results,
+ IsBaseExprStatement, IsClassProperty);
}
// Look through protocols.
for (auto *I : IFace->all_referenced_protocols())
AddObjCProperties(CCContext, I, AllowCategories, AllowNullaryMethods,
- CurContext, AddedProperties, Results);
-
+ CurContext, AddedProperties, Results,
+ IsBaseExprStatement, IsClassProperty);
+
// Look in the superclass.
if (IFace->getSuperClass())
AddObjCProperties(CCContext, IFace->getSuperClass(), AllowCategories,
- AllowNullaryMethods, CurContext,
- AddedProperties, Results);
+ AllowNullaryMethods, CurContext, AddedProperties,
+ Results, IsBaseExprStatement, IsClassProperty);
} else if (const ObjCCategoryDecl *Category
= dyn_cast<ObjCCategoryDecl>(Container)) {
// Look through protocols.
for (auto *P : Category->protocols())
AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
- CurContext, AddedProperties, Results);
+ CurContext, AddedProperties, Results,
+ IsBaseExprStatement, IsClassProperty);
}
}
void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
- SourceLocation OpLoc,
- bool IsArrow) {
+ SourceLocation OpLoc, bool IsArrow,
+ bool IsBaseExprStatement) {
if (!Base || !CodeCompleter)
return;
@@ -3720,22 +3885,24 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
Results.AddResult(Result("template"));
}
}
- } else if (!IsArrow && BaseType->getAsObjCInterfacePointerType()) {
+ } else if (!IsArrow && BaseType->isObjCObjectPointerType()) {
// Objective-C property reference.
AddedPropertiesSet AddedProperties;
-
- // Add property results based on our interface.
- const ObjCObjectPointerType *ObjCPtr
- = BaseType->getAsObjCInterfacePointerType();
- assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
- AddObjCProperties(CCContext, ObjCPtr->getInterfaceDecl(), true,
- /*AllowNullaryMethods=*/true, CurContext,
- AddedProperties, Results);
-
+
+ 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 : ObjCPtr->quals())
+ for (auto *I : BaseType->getAs<ObjCObjectPointerType>()->quals())
AddObjCProperties(CCContext, I, true, /*AllowNullaryMethods=*/true,
- CurContext, AddedProperties, Results);
+ CurContext, AddedProperties, Results,
+ IsBaseExprStatement);
} else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
(!IsArrow && BaseType->isObjCObjectType())) {
// Objective-C instance variable access.
@@ -3765,6 +3932,30 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
Results.data(),Results.size());
}
+void Sema::CodeCompleteObjCClassPropertyRefExpr(Scope *S,
+ IdentifierInfo &ClassName,
+ SourceLocation ClassNameLoc,
+ bool IsBaseExprStatement) {
+ IdentifierInfo *ClassNamePtr = &ClassName;
+ ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(ClassNamePtr, ClassNameLoc);
+ if (!IFace)
+ return;
+ CodeCompletionContext CCContext(
+ CodeCompletionContext::CCC_ObjCPropertyAccess);
+ ResultBuilder Results(*this, CodeCompleter->getAllocator(),
+ CodeCompleter->getCodeCompletionTUInfo(), CCContext,
+ &ResultBuilder::IsMember);
+ Results.EnterNewScope();
+ AddedPropertiesSet AddedProperties;
+ AddObjCProperties(CCContext, IFace, true,
+ /*AllowNullaryMethods=*/true, CurContext, AddedProperties,
+ Results, IsBaseExprStatement,
+ /*IsClassProperty=*/true);
+ Results.ExitScope();
+ HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
+ Results.data(), Results.size());
+}
+
void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
if (!CodeCompleter)
return;
@@ -5952,7 +6143,7 @@ void Sema::CodeCompleteObjCProtocolReferences(
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_ObjCProtocolName);
- if (CodeCompleter && CodeCompleter->includeGlobals()) {
+ if (CodeCompleter->includeGlobals()) {
Results.EnterNewScope();
// Tell the result set to ignore all of the protocols we have
@@ -5980,7 +6171,7 @@ void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_ObjCProtocolName);
- if (CodeCompleter && CodeCompleter->includeGlobals()) {
+ if (CodeCompleter->includeGlobals()) {
Results.EnterNewScope();
// Add all protocols.
@@ -7008,7 +7199,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
.second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
- Builder.AddTextChunk("NSSet *");
+ Builder.AddTextChunk("NSSet<NSString *> *");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
diff --git a/lib/Sema/SemaCoroutine.cpp b/lib/Sema/SemaCoroutine.cpp
index c8715fff4159..3109358df464 100644
--- a/lib/Sema/SemaCoroutine.cpp
+++ b/lib/Sema/SemaCoroutine.cpp
@@ -26,15 +26,15 @@ using namespace sema;
static QualType lookupPromiseType(Sema &S, const FunctionProtoType *FnType,
SourceLocation Loc) {
// FIXME: Cache std::coroutine_traits once we've found it.
- NamespaceDecl *Std = S.getStdNamespace();
- if (!Std) {
+ NamespaceDecl *StdExp = S.lookupStdExperimentalNamespace();
+ if (!StdExp) {
S.Diag(Loc, diag::err_implied_std_coroutine_traits_not_found);
return QualType();
}
LookupResult Result(S, &S.PP.getIdentifierTable().get("coroutine_traits"),
Loc, Sema::LookupOrdinaryName);
- if (!S.LookupQualifiedName(Result, Std)) {
+ if (!S.LookupQualifiedName(Result, StdExp)) {
S.Diag(Loc, diag::err_implied_std_coroutine_traits_not_found);
return QualType();
}
@@ -78,7 +78,7 @@ static QualType lookupPromiseType(Sema &S, const FunctionProtoType *FnType,
auto *Promise = R.getAsSingle<TypeDecl>();
if (!Promise) {
S.Diag(Loc, diag::err_implied_std_coroutine_traits_promise_type_not_found)
- << RD;
+ << RD;
return QualType();
}
@@ -86,75 +86,131 @@ static QualType lookupPromiseType(Sema &S, const FunctionProtoType *FnType,
QualType PromiseType = S.Context.getTypeDeclType(Promise);
if (!PromiseType->getAsCXXRecordDecl()) {
// Use the fully-qualified name of the type.
- auto *NNS = NestedNameSpecifier::Create(S.Context, nullptr, Std);
+ auto *NNS = NestedNameSpecifier::Create(S.Context, nullptr, StdExp);
NNS = NestedNameSpecifier::Create(S.Context, NNS, false,
CoroTrait.getTypePtr());
PromiseType = S.Context.getElaboratedType(ETK_None, NNS, PromiseType);
S.Diag(Loc, diag::err_implied_std_coroutine_traits_promise_type_not_class)
- << PromiseType;
+ << PromiseType;
return QualType();
}
return PromiseType;
}
-/// Check that this is a context in which a coroutine suspension can appear.
-static FunctionScopeInfo *
-checkCoroutineContext(Sema &S, SourceLocation Loc, StringRef Keyword) {
+static bool isValidCoroutineContext(Sema &S, SourceLocation Loc,
+ StringRef Keyword) {
// 'co_await' and 'co_yield' are not permitted in unevaluated operands.
if (S.isUnevaluatedContext()) {
S.Diag(Loc, diag::err_coroutine_unevaluated_context) << Keyword;
- return nullptr;
+ return false;
}
// Any other usage must be within a function.
- // FIXME: Reject a coroutine with a deduced return type.
auto *FD = dyn_cast<FunctionDecl>(S.CurContext);
if (!FD) {
S.Diag(Loc, isa<ObjCMethodDecl>(S.CurContext)
? diag::err_coroutine_objc_method
: diag::err_coroutine_outside_function) << Keyword;
- } else if (isa<CXXConstructorDecl>(FD) || isa<CXXDestructorDecl>(FD)) {
- // Coroutines TS [special]/6:
- // A special member function shall not be a coroutine.
- //
- // FIXME: We assume that this really means that a coroutine cannot
- // be a constructor or destructor.
- S.Diag(Loc, diag::err_coroutine_ctor_dtor)
- << isa<CXXDestructorDecl>(FD) << Keyword;
- } else if (FD->isConstexpr()) {
- S.Diag(Loc, diag::err_coroutine_constexpr) << Keyword;
- } else if (FD->isVariadic()) {
- S.Diag(Loc, diag::err_coroutine_varargs) << Keyword;
- } else {
- auto *ScopeInfo = S.getCurFunction();
- assert(ScopeInfo && "missing function scope for function");
-
- // If we don't have a promise variable, build one now.
- if (!ScopeInfo->CoroutinePromise) {
- QualType T =
- FD->getType()->isDependentType()
- ? S.Context.DependentTy
- : lookupPromiseType(S, FD->getType()->castAs<FunctionProtoType>(),
- Loc);
- if (T.isNull())
- return nullptr;
-
- // Create and default-initialize the promise.
- ScopeInfo->CoroutinePromise =
- VarDecl::Create(S.Context, FD, FD->getLocation(), FD->getLocation(),
- &S.PP.getIdentifierTable().get("__promise"), T,
- S.Context.getTrivialTypeSourceInfo(T, Loc), SC_None);
- S.CheckVariableDeclarationType(ScopeInfo->CoroutinePromise);
- if (!ScopeInfo->CoroutinePromise->isInvalidDecl())
- S.ActOnUninitializedDecl(ScopeInfo->CoroutinePromise, false);
- }
+ return false;
+ }
- return ScopeInfo;
+ // An enumeration for mapping the diagnostic type to the correct diagnostic
+ // selection index.
+ enum InvalidFuncDiag {
+ DiagCtor = 0,
+ DiagDtor,
+ DiagCopyAssign,
+ DiagMoveAssign,
+ DiagMain,
+ DiagConstexpr,
+ DiagAutoRet,
+ DiagVarargs,
+ };
+ bool Diagnosed = false;
+ auto DiagInvalid = [&](InvalidFuncDiag ID) {
+ S.Diag(Loc, diag::err_coroutine_invalid_func_context) << ID << Keyword;
+ Diagnosed = true;
+ return false;
+ };
+
+ // Diagnose when a constructor, destructor, copy/move assignment operator,
+ // or the function 'main' are declared as a coroutine.
+ auto *MD = dyn_cast<CXXMethodDecl>(FD);
+ if (MD && isa<CXXConstructorDecl>(MD))
+ return DiagInvalid(DiagCtor);
+ else if (MD && isa<CXXDestructorDecl>(MD))
+ return DiagInvalid(DiagDtor);
+ else if (MD && MD->isCopyAssignmentOperator())
+ return DiagInvalid(DiagCopyAssign);
+ else if (MD && MD->isMoveAssignmentOperator())
+ return DiagInvalid(DiagMoveAssign);
+ else if (FD->isMain())
+ return DiagInvalid(DiagMain);
+
+ // Emit a diagnostics for each of the following conditions which is not met.
+ if (FD->isConstexpr())
+ DiagInvalid(DiagConstexpr);
+ if (FD->getReturnType()->isUndeducedType())
+ DiagInvalid(DiagAutoRet);
+ if (FD->isVariadic())
+ DiagInvalid(DiagVarargs);
+
+ return !Diagnosed;
+}
+
+/// Check that this is a context in which a coroutine suspension can appear.
+static FunctionScopeInfo *checkCoroutineContext(Sema &S, SourceLocation Loc,
+ StringRef Keyword) {
+ if (!isValidCoroutineContext(S, Loc, Keyword))
+ return nullptr;
+
+ assert(isa<FunctionDecl>(S.CurContext) && "not in a function scope");
+ auto *FD = cast<FunctionDecl>(S.CurContext);
+ auto *ScopeInfo = S.getCurFunction();
+ assert(ScopeInfo && "missing function scope for function");
+
+ // If we don't have a promise variable, build one now.
+ if (!ScopeInfo->CoroutinePromise) {
+ QualType T = FD->getType()->isDependentType()
+ ? S.Context.DependentTy
+ : lookupPromiseType(
+ S, FD->getType()->castAs<FunctionProtoType>(), Loc);
+ if (T.isNull())
+ return nullptr;
+
+ // Create and default-initialize the promise.
+ ScopeInfo->CoroutinePromise =
+ VarDecl::Create(S.Context, FD, FD->getLocation(), FD->getLocation(),
+ &S.PP.getIdentifierTable().get("__promise"), T,
+ S.Context.getTrivialTypeSourceInfo(T, Loc), SC_None);
+ S.CheckVariableDeclarationType(ScopeInfo->CoroutinePromise);
+ if (!ScopeInfo->CoroutinePromise->isInvalidDecl())
+ S.ActOnUninitializedDecl(ScopeInfo->CoroutinePromise, false);
}
- return nullptr;
+ return ScopeInfo;
+}
+
+static Expr *buildBuiltinCall(Sema &S, SourceLocation Loc, Builtin::ID Id,
+ MutableArrayRef<Expr *> CallArgs) {
+ StringRef Name = S.Context.BuiltinInfo.getName(Id);
+ LookupResult R(S, &S.Context.Idents.get(Name), Loc, Sema::LookupOrdinaryName);
+ S.LookupName(R, S.TUScope, /*AllowBuiltinCreation=*/true);
+
+ auto *BuiltInDecl = R.getAsSingle<FunctionDecl>();
+ assert(BuiltInDecl && "failed to find builtin declaration");
+
+ ExprResult DeclRef =
+ S.BuildDeclRefExpr(BuiltInDecl, BuiltInDecl->getType(), VK_LValue, Loc);
+ assert(DeclRef.isUsable() && "Builtin reference cannot fail");
+
+ ExprResult Call =
+ S.ActOnCallExpr(/*Scope=*/nullptr, DeclRef.get(), Loc, CallArgs, Loc);
+
+ assert(!Call.isInvalid() && "Call to builtin cannot fail!");
+ return Call.get();
}
/// Build a call to 'operator co_await' if there is a suitable operator for
@@ -199,7 +255,7 @@ static ReadySuspendResumeResult buildCoawaitCalls(Sema &S, SourceLocation Loc,
const StringRef Funcs[] = {"await_ready", "await_suspend", "await_resume"};
for (size_t I = 0, N = llvm::array_lengthof(Funcs); I != N; ++I) {
Expr *Operand = new (S.Context) OpaqueValueExpr(
- Loc, E->getType(), VK_LValue, E->getObjectKind(), E);
+ Loc, E->getType(), VK_LValue, E->getObjectKind(), E);
// FIXME: Pass coroutine handle to await_suspend.
ExprResult Result = buildMemberCall(S, Operand, Loc, Funcs[I], None);
@@ -213,6 +269,11 @@ static ReadySuspendResumeResult buildCoawaitCalls(Sema &S, SourceLocation Loc,
}
ExprResult Sema::ActOnCoawaitExpr(Scope *S, SourceLocation Loc, Expr *E) {
+ auto *Coroutine = checkCoroutineContext(*this, Loc, "co_await");
+ if (!Coroutine) {
+ CorrectDelayedTyposInExpr(E);
+ return ExprError();
+ }
if (E->getType()->isPlaceholderType()) {
ExprResult R = CheckPlaceholderExpr(E);
if (R.isInvalid()) return ExprError();
@@ -222,6 +283,7 @@ ExprResult Sema::ActOnCoawaitExpr(Scope *S, SourceLocation Loc, Expr *E) {
ExprResult Awaitable = buildOperatorCoawaitCall(*this, S, Loc, E);
if (Awaitable.isInvalid())
return ExprError();
+
return BuildCoawaitExpr(Loc, Awaitable.get());
}
ExprResult Sema::BuildCoawaitExpr(SourceLocation Loc, Expr *E) {
@@ -275,8 +337,10 @@ static ExprResult buildPromiseCall(Sema &S, FunctionScopeInfo *Coroutine,
ExprResult Sema::ActOnCoyieldExpr(Scope *S, SourceLocation Loc, Expr *E) {
auto *Coroutine = checkCoroutineContext(*this, Loc, "co_yield");
- if (!Coroutine)
+ if (!Coroutine) {
+ CorrectDelayedTyposInExpr(E);
return ExprError();
+ }
// Build yield_value call.
ExprResult Awaitable =
@@ -325,8 +389,14 @@ ExprResult Sema::BuildCoyieldExpr(SourceLocation Loc, Expr *E) {
}
StmtResult Sema::ActOnCoreturnStmt(SourceLocation Loc, Expr *E) {
+ auto *Coroutine = checkCoroutineContext(*this, Loc, "co_return");
+ if (!Coroutine) {
+ CorrectDelayedTyposInExpr(E);
+ return StmtError();
+ }
return BuildCoreturnStmt(Loc, E);
}
+
StmtResult Sema::BuildCoreturnStmt(SourceLocation Loc, Expr *E) {
auto *Coroutine = checkCoroutineContext(*this, Loc, "co_return");
if (!Coroutine)
@@ -343,7 +413,7 @@ StmtResult Sema::BuildCoreturnStmt(SourceLocation Loc, Expr *E) {
// of scope, we should treat the operand as an xvalue for this overload
// resolution.
ExprResult PC;
- if (E && !E->getType()->isVoidType()) {
+ if (E && (isa<InitListExpr>(E) || !E->getType()->isVoidType())) {
PC = buildPromiseCall(*this, Coroutine, Loc, "return_value", E);
} else {
E = MakeFullDiscardedValueExpr(E).get();
@@ -359,6 +429,141 @@ StmtResult Sema::BuildCoreturnStmt(SourceLocation Loc, Expr *E) {
return Res;
}
+static ExprResult buildStdCurrentExceptionCall(Sema &S, SourceLocation Loc) {
+ NamespaceDecl *Std = S.getStdNamespace();
+ if (!Std) {
+ S.Diag(Loc, diag::err_implied_std_current_exception_not_found);
+ return ExprError();
+ }
+ LookupResult Result(S, &S.PP.getIdentifierTable().get("current_exception"),
+ Loc, Sema::LookupOrdinaryName);
+ if (!S.LookupQualifiedName(Result, Std)) {
+ S.Diag(Loc, diag::err_implied_std_current_exception_not_found);
+ return ExprError();
+ }
+
+ // FIXME The STL is free to provide more than one overload.
+ FunctionDecl *FD = Result.getAsSingle<FunctionDecl>();
+ if (!FD) {
+ S.Diag(Loc, diag::err_malformed_std_current_exception);
+ return ExprError();
+ }
+ ExprResult Res = S.BuildDeclRefExpr(FD, FD->getType(), VK_LValue, Loc);
+ Res = S.ActOnCallExpr(/*Scope*/ nullptr, Res.get(), Loc, None, Loc);
+ if (Res.isInvalid()) {
+ S.Diag(Loc, diag::err_malformed_std_current_exception);
+ return ExprError();
+ }
+ return Res;
+}
+
+// Find an appropriate delete for the promise.
+static FunctionDecl *findDeleteForPromise(Sema &S, SourceLocation Loc,
+ QualType PromiseType) {
+ FunctionDecl *OperatorDelete = nullptr;
+
+ DeclarationName DeleteName =
+ S.Context.DeclarationNames.getCXXOperatorName(OO_Delete);
+
+ auto *PointeeRD = PromiseType->getAsCXXRecordDecl();
+ assert(PointeeRD && "PromiseType must be a CxxRecordDecl type");
+
+ if (S.FindDeallocationFunction(Loc, PointeeRD, DeleteName, OperatorDelete))
+ return nullptr;
+
+ if (!OperatorDelete) {
+ // Look for a global declaration.
+ const bool CanProvideSize = S.isCompleteType(Loc, PromiseType);
+ const bool Overaligned = false;
+ OperatorDelete = S.FindUsualDeallocationFunction(Loc, CanProvideSize,
+ Overaligned, DeleteName);
+ }
+ S.MarkFunctionReferenced(Loc, OperatorDelete);
+ return OperatorDelete;
+}
+
+// Builds allocation and deallocation for the coroutine. Returns false on
+// failure.
+static bool buildAllocationAndDeallocation(Sema &S, SourceLocation Loc,
+ FunctionScopeInfo *Fn,
+ Expr *&Allocation,
+ Stmt *&Deallocation) {
+ TypeSourceInfo *TInfo = Fn->CoroutinePromise->getTypeSourceInfo();
+ QualType PromiseType = TInfo->getType();
+ if (PromiseType->isDependentType())
+ return true;
+
+ if (S.RequireCompleteType(Loc, PromiseType, diag::err_incomplete_type))
+ return false;
+
+ // FIXME: Add support for get_return_object_on_allocation failure.
+ // FIXME: Add support for stateful allocators.
+
+ FunctionDecl *OperatorNew = nullptr;
+ FunctionDecl *OperatorDelete = nullptr;
+ FunctionDecl *UnusedResult = nullptr;
+ bool PassAlignment = false;
+
+ S.FindAllocationFunctions(Loc, SourceRange(),
+ /*UseGlobal*/ false, PromiseType,
+ /*isArray*/ false, PassAlignment,
+ /*PlacementArgs*/ None, OperatorNew, UnusedResult);
+
+ OperatorDelete = findDeleteForPromise(S, Loc, PromiseType);
+
+ if (!OperatorDelete || !OperatorNew)
+ return false;
+
+ Expr *FramePtr =
+ buildBuiltinCall(S, Loc, Builtin::BI__builtin_coro_frame, {});
+
+ Expr *FrameSize =
+ buildBuiltinCall(S, Loc, Builtin::BI__builtin_coro_size, {});
+
+ // Make new call.
+
+ ExprResult NewRef =
+ S.BuildDeclRefExpr(OperatorNew, OperatorNew->getType(), VK_LValue, Loc);
+ if (NewRef.isInvalid())
+ return false;
+
+ ExprResult NewExpr =
+ S.ActOnCallExpr(S.getCurScope(), NewRef.get(), Loc, FrameSize, Loc);
+ if (NewExpr.isInvalid())
+ return false;
+
+ Allocation = NewExpr.get();
+
+ // Make delete call.
+
+ QualType OpDeleteQualType = OperatorDelete->getType();
+
+ ExprResult DeleteRef =
+ S.BuildDeclRefExpr(OperatorDelete, OpDeleteQualType, VK_LValue, Loc);
+ if (DeleteRef.isInvalid())
+ return false;
+
+ Expr *CoroFree =
+ buildBuiltinCall(S, Loc, Builtin::BI__builtin_coro_free, {FramePtr});
+
+ SmallVector<Expr *, 2> DeleteArgs{CoroFree};
+
+ // Check if we need to pass the size.
+ const auto *OpDeleteType =
+ OpDeleteQualType.getTypePtr()->getAs<FunctionProtoType>();
+ if (OpDeleteType->getNumParams() > 1)
+ DeleteArgs.push_back(FrameSize);
+
+ ExprResult DeleteExpr =
+ S.ActOnCallExpr(S.getCurScope(), DeleteRef.get(), Loc, DeleteArgs, Loc);
+ if (DeleteExpr.isInvalid())
+ return false;
+
+ Deallocation = DeleteExpr.get();
+
+ return true;
+}
+
void Sema::CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body) {
FunctionScopeInfo *Fn = getCurFunction();
assert(Fn && !Fn->CoroutineStmts.empty() && "not a coroutine");
@@ -369,8 +574,8 @@ void Sema::CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body) {
Diag(Fn->FirstReturnLoc, diag::err_return_in_coroutine);
auto *First = Fn->CoroutineStmts[0];
Diag(First->getLocStart(), diag::note_declared_coroutine_here)
- << (isa<CoawaitExpr>(First) ? 0 :
- isa<CoyieldExpr>(First) ? 1 : 2);
+ << (isa<CoawaitExpr>(First) ? 0 :
+ isa<CoyieldExpr>(First) ? 1 : 2);
}
bool AnyCoawaits = false;
@@ -413,15 +618,69 @@ void Sema::CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body) {
if (FinalSuspend.isInvalid())
return FD->setInvalidDecl();
- // FIXME: Perform analysis of set_exception call.
+ // Form and check allocation and deallocation calls.
+ Expr *Allocation = nullptr;
+ Stmt *Deallocation = nullptr;
+ if (!buildAllocationAndDeallocation(*this, Loc, Fn, Allocation, Deallocation))
+ return FD->setInvalidDecl();
- // FIXME: Try to form 'p.return_void();' expression statement to handle
// control flowing off the end of the coroutine.
+ // Also try to form 'p.set_exception(std::current_exception());' to handle
+ // uncaught exceptions.
+ ExprResult SetException;
+ StmtResult Fallthrough;
+ if (Fn->CoroutinePromise &&
+ !Fn->CoroutinePromise->getType()->isDependentType()) {
+ CXXRecordDecl *RD = Fn->CoroutinePromise->getType()->getAsCXXRecordDecl();
+ assert(RD && "Type should have already been checked");
+ // [dcl.fct.def.coroutine]/4
+ // The unqualified-ids 'return_void' and 'return_value' are looked up in
+ // the scope of class P. If both are found, the program is ill-formed.
+ DeclarationName RVoidDN = PP.getIdentifierInfo("return_void");
+ LookupResult RVoidResult(*this, RVoidDN, Loc, Sema::LookupMemberName);
+ const bool HasRVoid = LookupQualifiedName(RVoidResult, RD);
+
+ DeclarationName RValueDN = PP.getIdentifierInfo("return_value");
+ LookupResult RValueResult(*this, RValueDN, Loc, Sema::LookupMemberName);
+ const bool HasRValue = LookupQualifiedName(RValueResult, RD);
+
+ if (HasRVoid && HasRValue) {
+ // FIXME Improve this diagnostic
+ Diag(FD->getLocation(), diag::err_coroutine_promise_return_ill_formed)
+ << RD;
+ return FD->setInvalidDecl();
+ } else if (HasRVoid) {
+ // If the unqualified-id return_void is found, flowing off the end of a
+ // coroutine is equivalent to a co_return with no operand. Otherwise,
+ // flowing off the end of a coroutine results in undefined behavior.
+ Fallthrough = BuildCoreturnStmt(FD->getLocation(), nullptr);
+ Fallthrough = ActOnFinishFullStmt(Fallthrough.get());
+ if (Fallthrough.isInvalid())
+ return FD->setInvalidDecl();
+ }
+
+ // [dcl.fct.def.coroutine]/3
+ // The unqualified-id set_exception is found in the scope of P by class
+ // member access lookup (3.4.5).
+ DeclarationName SetExDN = PP.getIdentifierInfo("set_exception");
+ LookupResult SetExResult(*this, SetExDN, Loc, Sema::LookupMemberName);
+ if (LookupQualifiedName(SetExResult, RD)) {
+ // Form the call 'p.set_exception(std::current_exception())'
+ SetException = buildStdCurrentExceptionCall(*this, Loc);
+ if (SetException.isInvalid())
+ return FD->setInvalidDecl();
+ Expr *E = SetException.get();
+ SetException = buildPromiseCall(*this, Fn, Loc, "set_exception", E);
+ SetException = ActOnFinishFullExpr(SetException.get(), Loc);
+ if (SetException.isInvalid())
+ return FD->setInvalidDecl();
+ }
+ }
// Build implicit 'p.get_return_object()' expression and form initialization
// of return type from it.
ExprResult ReturnObject =
- buildPromiseCall(*this, Fn, Loc, "get_return_object", None);
+ buildPromiseCall(*this, Fn, Loc, "get_return_object", None);
if (ReturnObject.isInvalid())
return FD->setInvalidDecl();
QualType RetType = FD->getReturnType();
@@ -443,6 +702,6 @@ void Sema::CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body) {
// Build body for the coroutine wrapper statement.
Body = new (Context) CoroutineBodyStmt(
Body, PromiseStmt.get(), InitialSuspend.get(), FinalSuspend.get(),
- /*SetException*/nullptr, /*Fallthrough*/nullptr,
+ SetException.get(), Fallthrough.get(), Allocation, Deallocation,
ReturnObject.get(), ParamMoves);
}
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 41719d4e7b08..c32757565dd1 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -11,7 +11,6 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Sema/SemaInternal.h"
#include "TypeLocBuilder.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
@@ -41,6 +40,7 @@
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
+#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Template.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Triple.h"
@@ -780,8 +780,8 @@ Sema::ClassifyName(Scope *S, CXXScopeSpec &SS, IdentifierInfo *&Name,
ObjCMethodDecl *CurMethod = getCurMethodDecl();
if (NextToken.is(tok::coloncolon)) {
- BuildCXXNestedNameSpecifier(S, *Name, NameLoc, NextToken.getLocation(),
- QualType(), false, SS, nullptr, false);
+ NestedNameSpecInfo IdInfo(Name, NameLoc, NextToken.getLocation());
+ BuildCXXNestedNameSpecifier(S, IdInfo, false, SS, nullptr, false);
}
LookupResult Result(*this, Name, NameLoc, LookupOrdinaryName);
@@ -1522,7 +1522,7 @@ static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) {
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
// White-list anything with an __attribute__((unused)) type.
- QualType Ty = VD->getType();
+ const auto *Ty = VD->getType().getTypePtr();
// Only look at the outermost level of typedef.
if (const TypedefType *TT = Ty->getAs<TypedefType>()) {
@@ -1535,6 +1535,10 @@ static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) {
if (Ty->isIncompleteType() || Ty->isDependentType())
return false;
+ // Look at the element type to ensure that the warning behaviour is
+ // consistent for both scalars and arrays.
+ Ty = Ty->getBaseElementTypeUnsafe();
+
if (const TagType *TT = Ty->getAs<TagType>()) {
const TagDecl *Tag = TT->getDecl();
if (Tag->hasAttr<UnusedAttr>())
@@ -1791,7 +1795,9 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID,
return nullptr;
}
- if (!ForRedeclaration && Context.BuiltinInfo.isPredefinedLibFunction(ID)) {
+ if (!ForRedeclaration &&
+ (Context.BuiltinInfo.isPredefinedLibFunction(ID) ||
+ Context.BuiltinInfo.isHeaderDependentFunction(ID))) {
Diag(Loc, diag::ext_implicit_lib_function_decl)
<< Context.BuiltinInfo.getName(ID) << R;
if (Context.BuiltinInfo.getHeaderName(ID) &&
@@ -2246,6 +2252,13 @@ static bool mergeAlignedAttrs(Sema &S, NamedDecl *New, Decl *Old) {
static bool mergeDeclAttribute(Sema &S, NamedDecl *D,
const InheritableAttr *Attr,
Sema::AvailabilityMergeKind AMK) {
+ // This function copies an attribute Attr from a previous declaration to the
+ // new declaration D if the new declaration doesn't itself have that attribute
+ // yet or if that attribute allows duplicates.
+ // If you're adding a new attribute that requires logic different from
+ // "use explicit attribute on decl if present, else use attribute from
+ // previous decl", for example if the attribute needs to be consistent
+ // between redeclarations, you need to call a custom merge function here.
InheritableAttr *NewAttr = nullptr;
unsigned AttrSpellingListIndex = Attr->getSpellingListIndex();
if (const auto *AA = dyn_cast<AvailabilityAttr>(Attr))
@@ -2283,7 +2296,13 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D,
NewAttr = S.mergeAlwaysInlineAttr(D, AA->getRange(),
&S.Context.Idents.get(AA->getSpelling()),
AttrSpellingListIndex);
- else if (const auto *MA = dyn_cast<MinSizeAttr>(Attr))
+ else if (S.getLangOpts().CUDA && isa<FunctionDecl>(D) &&
+ (isa<CUDAHostAttr>(Attr) || isa<CUDADeviceAttr>(Attr) ||
+ isa<CUDAGlobalAttr>(Attr))) {
+ // CUDA target attributes are part of function signature for
+ // overloading purposes and must not be merged.
+ return false;
+ } else if (const auto *MA = dyn_cast<MinSizeAttr>(Attr))
NewAttr = S.mergeMinSizeAttr(D, MA->getRange(), AttrSpellingListIndex);
else if (const auto *OA = dyn_cast<OptimizeNoneAttr>(Attr))
NewAttr = S.mergeOptimizeNoneAttr(D, OA->getRange(), AttrSpellingListIndex);
@@ -2304,6 +2323,9 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D,
(AMK == Sema::AMK_Override ||
AMK == Sema::AMK_ProtocolImplementation))
NewAttr = nullptr;
+ 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))
NewAttr = cast<InheritableAttr>(Attr->clone(S.Context));
@@ -2915,10 +2937,20 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD,
}
if (getLangOpts().CPlusPlus) {
- // (C++98 13.1p2):
+ // C++1z [over.load]p2
// Certain function declarations cannot be overloaded:
- // -- Function declarations that differ only in the return type
- // cannot be overloaded.
+ // -- Function declarations that differ only in the return type,
+ // the exception specification, or both cannot be overloaded.
+
+ // Check the exception specifications match. This may recompute the type of
+ // both Old and New if it resolved exception specifications, so grab the
+ // types again after this. Because this updates the type, we do this before
+ // any of the other checks below, which may update the "de facto" NewQType
+ // but do not necessarily update the type of New.
+ if (CheckEquivalentExceptionSpec(Old, New))
+ return true;
+ OldQType = Context.getCanonicalType(Old->getType());
+ NewQType = Context.getCanonicalType(New->getType());
// Go back to the type source info to compare the declared return types,
// per C++1y [dcl.type.auto]p13:
@@ -2933,10 +2965,10 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD,
(New->getTypeSourceInfo()
? New->getTypeSourceInfo()->getType()->castAs<FunctionType>()
: NewType)->getReturnType();
- QualType ResQT;
if (!Context.hasSameType(OldDeclaredReturnType, NewDeclaredReturnType) &&
!((NewQType->isDependentType() || OldQType->isDependentType()) &&
New->isLocalExternDecl())) {
+ QualType ResQT;
if (NewDeclaredReturnType->isObjCObjectPointerType() &&
OldDeclaredReturnType->isObjCObjectPointerType())
ResQT = Context.mergeObjCGCQualifiers(NewQType, OldQType);
@@ -3074,7 +3106,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD,
// noreturn should now match unless the old type info didn't have it.
QualType OldQTypeForComparison = OldQType;
if (!OldTypeInfo.getNoReturn() && NewTypeInfo.getNoReturn()) {
- assert(OldQType == QualType(OldType, 0));
+ auto *OldType = OldQType->castAs<FunctionProtoType>();
const FunctionType *OldTypeForComparison
= Context.adjustFunctionType(OldType, OldTypeInfo.withNoReturn(true));
OldQTypeForComparison = QualType(OldTypeForComparison, 0);
@@ -3367,11 +3399,11 @@ void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old,
// We are merging a variable declaration New into Old. If it has an array
// bound, and that bound differs from Old's bound, we should diagnose the
// mismatch.
- if (!NewArray->isIncompleteArrayType()) {
+ if (!NewArray->isIncompleteArrayType() && !NewArray->isDependentType()) {
for (VarDecl *PrevVD = Old->getMostRecentDecl(); PrevVD;
PrevVD = PrevVD->getPreviousDecl()) {
const ArrayType *PrevVDTy = Context.getAsArrayType(PrevVD->getType());
- if (PrevVDTy->isIncompleteArrayType())
+ if (PrevVDTy->isIncompleteArrayType() || PrevVDTy->isDependentType())
continue;
if (!Context.hasSameType(NewArray, PrevVDTy))
@@ -3657,29 +3689,16 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
}
// C++ doesn't have tentative definitions, so go right ahead and check here.
- VarDecl *Def;
if (getLangOpts().CPlusPlus &&
- New->isThisDeclarationADefinition() == VarDecl::Definition &&
- (Def = Old->getDefinition())) {
- NamedDecl *Hidden = nullptr;
- if (!hasVisibleDefinition(Def, &Hidden) &&
- (New->getFormalLinkage() == InternalLinkage ||
- New->getDescribedVarTemplate() ||
- New->getNumTemplateParameterLists() ||
- New->getDeclContext()->isDependentContext())) {
- // The previous definition is hidden, and multiple definitions are
- // permitted (in separate TUs). Form another definition of it.
- } else if (Old->isStaticDataMember() &&
- Old->getCanonicalDecl()->isInline() &&
- Old->getCanonicalDecl()->isConstexpr()) {
+ New->isThisDeclarationADefinition() == VarDecl::Definition) {
+ if (Old->isStaticDataMember() && Old->getCanonicalDecl()->isInline() &&
+ Old->getCanonicalDecl()->isConstexpr()) {
// This definition won't be a definition any more once it's been merged.
Diag(New->getLocation(),
diag::warn_deprecated_redundant_constexpr_static_def);
- } else {
- Diag(New->getLocation(), diag::err_redefinition) << New;
- Diag(Def->getLocation(), diag::note_previous_definition);
- New->setInvalidDecl();
- return;
+ } else if (VarDecl *Def = Old->getDefinition()) {
+ if (checkVarDeclRedefinition(Def, New))
+ return;
}
}
@@ -3708,6 +3727,32 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
New->setImplicitlyInline();
}
+/// We've just determined that \p Old and \p New both appear to be definitions
+/// of the same variable. Either diagnose or fix the problem.
+bool Sema::checkVarDeclRedefinition(VarDecl *Old, VarDecl *New) {
+ if (!hasVisibleDefinition(Old) &&
+ (New->getFormalLinkage() == InternalLinkage ||
+ New->isInline() ||
+ New->getDescribedVarTemplate() ||
+ New->getNumTemplateParameterLists() ||
+ New->getDeclContext()->isDependentContext())) {
+ // The previous definition is hidden, and multiple definitions are
+ // permitted (in separate TUs). Demote this to a declaration.
+ New->demoteThisDefinitionToDeclaration();
+
+ // Make the canonical definition visible.
+ if (auto *OldTD = Old->getDescribedVarTemplate())
+ makeMergedDefinitionVisible(OldTD, New->getLocation());
+ makeMergedDefinitionVisible(Old, New->getLocation());
+ return false;
+ } else {
+ Diag(New->getLocation(), diag::err_redefinition) << New;
+ Diag(Old->getLocation(), diag::note_previous_definition);
+ New->setInvalidDecl();
+ return true;
+ }
+}
+
/// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with
/// no declarator (e.g. "struct foo;") is parsed.
Decl *
@@ -4793,6 +4838,9 @@ Decl *Sema::ActOnDeclarator(Scope *S, Declarator &D) {
Dcl && Dcl->getDeclContext()->isFileContext())
Dcl->setTopLevelDeclInObjCContainer();
+ if (getLangOpts().OpenCL)
+ setCurrentOpenCLExtensionForDecl(Dcl);
+
return Dcl;
}
@@ -4921,7 +4969,9 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D,
// All of these full declarators require an identifier. If it doesn't have
// one, the ParsedFreeStandingDeclSpec action should be used.
- if (!Name) {
+ if (D.isDecompositionDeclarator()) {
+ return ActOnDecompositionDeclarator(S, D, TemplateParamLists);
+ } else if (!Name) {
if (!D.isInvalidType()) // Reject this if we think it is valid.
Diag(D.getDeclSpec().getLocStart(),
diag::err_declarator_need_ident)
@@ -5595,6 +5645,9 @@ static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl,
NamedDecl *NewDecl,
bool IsSpecialization,
bool IsDefinition) {
+ if (OldDecl->isInvalidDecl())
+ return;
+
if (TemplateDecl *OldTD = dyn_cast<TemplateDecl>(OldDecl)) {
OldDecl = OldTD->getTemplatedDecl();
if (!IsSpecialization)
@@ -5715,23 +5768,7 @@ static bool isFunctionDefinitionDiscarded(Sema &S, FunctionDecl *FD) {
return false;
// Okay, go ahead and call the relatively-more-expensive function.
-
-#ifndef NDEBUG
- // AST quite reasonably asserts that it's working on a function
- // definition. We don't really have a way to tell it that we're
- // currently defining the function, so just lie to it in +Asserts
- // builds. This is an awful hack.
- FD->setLazyBody(1);
-#endif
-
- bool isC99Inline =
- S.Context.GetGVALinkageForFunction(FD) == GVA_AvailableExternally;
-
-#ifndef NDEBUG
- FD->setLazyBody(0);
-#endif
-
- return isC99Inline;
+ return S.Context.GetGVALinkageForFunction(FD) == GVA_AvailableExternally;
}
/// Determine whether a variable is extern "C" prior to attaching
@@ -5845,40 +5882,55 @@ static bool isDeclExternC(const Decl *D) {
llvm_unreachable("Unknown type of decl!");
}
-NamedDecl *
-Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
- TypeSourceInfo *TInfo, LookupResult &Previous,
- MultiTemplateParamsArg TemplateParamLists,
- bool &AddToScope) {
+NamedDecl *Sema::ActOnVariableDeclarator(
+ Scope *S, Declarator &D, DeclContext *DC, TypeSourceInfo *TInfo,
+ LookupResult &Previous, MultiTemplateParamsArg TemplateParamLists,
+ bool &AddToScope, ArrayRef<BindingDecl *> Bindings) {
QualType R = TInfo->getType();
DeclarationName Name = GetNameForDeclarator(D).getName();
- // OpenCL v2.0 s6.9.b - Image type can only be used as a function argument.
- // OpenCL v2.0 s6.13.16.1 - Pipe type can only be used as a function
- // argument.
- if (getLangOpts().OpenCL && (R->isImageType() || R->isPipeType())) {
- Diag(D.getIdentifierLoc(),
- diag::err_opencl_type_can_only_be_used_as_function_parameter)
- << R;
- D.setInvalidType();
+ IdentifierInfo *II = Name.getAsIdentifierInfo();
+
+ if (D.isDecompositionDeclarator()) {
+ AddToScope = false;
+ // Take the name of the first declarator as our name for diagnostic
+ // purposes.
+ auto &Decomp = D.getDecompositionDeclarator();
+ if (!Decomp.bindings().empty()) {
+ II = Decomp.bindings()[0].Name;
+ Name = II;
+ }
+ } else if (!II) {
+ Diag(D.getIdentifierLoc(), diag::err_bad_variable_name)
+ << Name;
return nullptr;
}
- DeclSpec::SCS SCSpec = D.getDeclSpec().getStorageClassSpec();
- StorageClass SC = StorageClassSpecToVarDeclStorageClass(D.getDeclSpec());
-
- // 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))
- SC = SC_Extern;
+ if (getLangOpts().OpenCL) {
+ // OpenCL v2.0 s6.9.b - Image type can only be used as a function argument.
+ // OpenCL v2.0 s6.13.16.1 - Pipe type can only be used as a function
+ // argument.
+ if (R->isImageType() || R->isPipeType()) {
+ Diag(D.getIdentifierLoc(),
+ diag::err_opencl_type_can_only_be_used_as_function_parameter)
+ << R;
+ D.setInvalidType();
+ return nullptr;
+ }
- DeclContext *OriginalDC = DC;
- bool IsLocalExternDecl = SC == SC_Extern &&
- adjustContextForLocalExternDecl(DC);
+ // OpenCL v1.2 s6.9.r:
+ // The event type cannot be used to declare a program scope variable.
+ // OpenCL v2.0 s6.9.q:
+ // The clk_event_t and reserve_id_t types cannot be declared in program scope.
+ if (NULL == S->getParent()) {
+ if (R->isReserveIDT() || R->isClkEventT() || R->isEventT()) {
+ Diag(D.getIdentifierLoc(),
+ diag::err_invalid_type_for_program_scope_var) << R;
+ D.setInvalidType();
+ return nullptr;
+ }
+ }
- if (getLangOpts().OpenCL) {
// OpenCL v1.0 s6.8.a.3: Pointers to functions are not allowed.
QualType NR = R;
while (NR->isPointerType()) {
@@ -5890,7 +5942,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
NR = NR->getPointeeType();
}
- if (!getOpenCLOptions().cl_khr_fp16) {
+ if (!getOpenCLOptions().isEnabled("cl_khr_fp16")) {
// OpenCL v1.2 s6.1.1.1: reject declaring variables of the half and
// half array type (unless the cl_khr_fp16 extension is enabled).
if (Context.getBaseElementType(R)->isHalfType()) {
@@ -5898,8 +5950,40 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
D.setInvalidType();
}
}
+
+ // OpenCL v1.2 s6.9.b p4:
+ // The sampler type cannot be used with the __local and __global address
+ // space qualifiers.
+ if (R->isSamplerT() && (R.getAddressSpace() == LangAS::opencl_local ||
+ R.getAddressSpace() == LangAS::opencl_global)) {
+ Diag(D.getIdentifierLoc(), diag::err_wrong_sampler_addressspace);
+ }
+
+ // OpenCL v1.2 s6.9.r:
+ // The event type cannot be used with the __local, __constant and __global
+ // address space qualifiers.
+ if (R->isEventT()) {
+ if (R.getAddressSpace()) {
+ Diag(D.getLocStart(), diag::err_event_t_addr_space_qual);
+ D.setInvalidType();
+ }
+ }
}
+ DeclSpec::SCS SCSpec = D.getDeclSpec().getStorageClassSpec();
+ StorageClass SC = StorageClassSpecToVarDeclStorageClass(D.getDeclSpec());
+
+ // 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))
+ SC = SC_Extern;
+
+ DeclContext *OriginalDC = DC;
+ bool IsLocalExternDecl = SC == SC_Extern &&
+ adjustContextForLocalExternDecl(DC);
+
if (SCSpec == DeclSpec::SCS_mutable) {
// mutable can only appear on non-static class members, so it's always
// an error here
@@ -5920,13 +6004,6 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
<< FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
}
- IdentifierInfo *II = Name.getAsIdentifierInfo();
- if (!II) {
- Diag(D.getIdentifierLoc(), diag::err_bad_variable_name)
- << Name;
- return nullptr;
- }
-
DiagnoseFunctionSpecifiers(D.getDeclSpec());
if (!DC->isRecord() && S->getFnParent() == nullptr) {
@@ -5939,32 +6016,6 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
}
}
- if (getLangOpts().OpenCL) {
- // OpenCL v1.2 s6.9.b p4:
- // The sampler type cannot be used with the __local and __global address
- // space qualifiers.
- if (R->isSamplerT() && (R.getAddressSpace() == LangAS::opencl_local ||
- R.getAddressSpace() == LangAS::opencl_global)) {
- Diag(D.getIdentifierLoc(), diag::err_wrong_sampler_addressspace);
- }
-
- // OpenCL 1.2 spec, p6.9 r:
- // The event type cannot be used to declare a program scope variable.
- // The event type cannot be used with the __local, __constant and __global
- // address space qualifiers.
- if (R->isEventT()) {
- if (S->getParent() == nullptr) {
- Diag(D.getLocStart(), diag::err_event_t_global_var);
- D.setInvalidType();
- }
-
- if (R.getAddressSpace()) {
- Diag(D.getLocStart(), diag::err_event_t_addr_space_qual);
- D.setInvalidType();
- }
- }
- }
-
bool IsExplicitSpecialization = false;
bool IsVariableTemplateSpecialization = false;
bool IsPartialSpecialization = false;
@@ -6095,6 +6146,10 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
return nullptr;
NewVD = cast<VarDecl>(Res.get());
AddToScope = false;
+ } else if (D.isDecompositionDeclarator()) {
+ NewVD = DecompositionDecl::Create(Context, DC, D.getLocStart(),
+ D.getIdentifierLoc(), R, TInfo, SC,
+ Bindings);
} else
NewVD = VarDecl::Create(Context, DC, D.getLocStart(),
D.getIdentifierLoc(), II, R, TInfo, SC);
@@ -6200,8 +6255,13 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
if (NewTemplate)
NewTemplate->setLexicalDeclContext(CurContext);
- if (IsLocalExternDecl)
- NewVD->setLocalExternDecl();
+ if (IsLocalExternDecl) {
+ if (D.isDecompositionDeclarator())
+ for (auto *B : Bindings)
+ B->setLocalExternDecl();
+ else
+ NewVD->setLocalExternDecl();
+ }
bool EmitTLSUnsupportedError = false;
if (DeclSpec::TSCS TSCS = D.getDeclSpec().getThreadStorageClassSpec()) {
@@ -6273,6 +6333,8 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
NewVD->setModulePrivate();
if (NewTemplate)
NewTemplate->setModulePrivate();
+ for (auto *B : Bindings)
+ B->setModulePrivate();
}
}
@@ -6480,7 +6542,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
}
// Special handling of variable named 'main'.
- if (Name.isIdentifier() && Name.getAsIdentifierInfo()->isStr("main") &&
+ if (Name.getAsIdentifierInfo() && Name.getAsIdentifierInfo()->isStr("main") &&
NewVD->getDeclContext()->getRedeclContext()->isTranslationUnit() &&
!getLangOpts().Freestanding && !NewVD->getDescribedVarTemplate()) {
@@ -6522,6 +6584,17 @@ static ShadowedDeclKind computeShadowedDeclKind(const NamedDecl *ShadowedDecl,
return OldDC->isFileContext() ? SDK_Global : SDK_Local;
}
+/// Return the location of the capture if the given lambda captures the given
+/// 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) {
+ if (Capture.isVariableCapture() && Capture.getVariable() == VD)
+ return Capture.getLocation();
+ }
+ return SourceLocation();
+}
+
/// \brief Diagnose variable or built-in function shadowing. Implements
/// -Wshadow.
///
@@ -6580,6 +6653,29 @@ void Sema::CheckShadow(Scope *S, VarDecl *D, const LookupResult& R) {
DeclContext *OldDC = ShadowedDecl->getDeclContext();
+ unsigned WarningDiag = diag::warn_decl_shadow;
+ SourceLocation CaptureLoc;
+ if (isa<VarDecl>(ShadowedDecl) && NewDC && isa<CXXMethodDecl>(NewDC)) {
+ if (const auto *RD = dyn_cast<CXXRecordDecl>(NewDC->getParent())) {
+ if (RD->isLambda() && OldDC->Encloses(NewDC->getLexicalParent())) {
+ if (RD->getLambdaCaptureDefault() == LCD_None) {
+ // Try to avoid warnings for lambdas with an explicit capture list.
+ const auto *LSI = cast<LambdaScopeInfo>(getCurFunction());
+ // Warn only when the lambda captures the shadowed decl explicitly.
+ CaptureLoc = getCaptureLocation(LSI, cast<VarDecl>(ShadowedDecl));
+ if (CaptureLoc.isInvalid())
+ WarningDiag = diag::warn_decl_shadow_uncaptured_local;
+ } else {
+ // Remember that this was shadowed so we can avoid the warning if the
+ // shadowed decl isn't captured and the warning settings allow it.
+ cast<LambdaScopeInfo>(getCurFunction())
+ ->ShadowingDecls.push_back({D, cast<VarDecl>(ShadowedDecl)});
+ return;
+ }
+ }
+ }
+ }
+
// Only warn about certain kinds of shadowing for class members.
if (NewDC && NewDC->isRecord()) {
// In particular, don't warn about shadowing non-class members.
@@ -6601,10 +6697,33 @@ void Sema::CheckShadow(Scope *S, VarDecl *D, const LookupResult& R) {
if (getSourceManager().isInSystemMacro(R.getNameLoc()))
return;
ShadowedDeclKind Kind = computeShadowedDeclKind(ShadowedDecl, OldDC);
- Diag(R.getNameLoc(), diag::warn_decl_shadow) << Name << Kind << OldDC;
+ Diag(R.getNameLoc(), WarningDiag) << Name << Kind << OldDC;
+ if (!CaptureLoc.isInvalid())
+ Diag(CaptureLoc, diag::note_var_explicitly_captured_here)
+ << Name << /*explicitly*/ 1;
Diag(ShadowedDecl->getLocation(), diag::note_previous_declaration);
}
+/// Diagnose shadowing for variables shadowed in the lambda record \p LambdaRD
+/// when these variables are captured by the lambda.
+void Sema::DiagnoseShadowingLambdaDecls(const LambdaScopeInfo *LSI) {
+ for (const auto &Shadow : LSI->ShadowingDecls) {
+ const VarDecl *ShadowedDecl = Shadow.ShadowedDecl;
+ // Try to avoid the warning when the shadowed decl isn't captured.
+ SourceLocation CaptureLoc = getCaptureLocation(LSI, ShadowedDecl);
+ const DeclContext *OldDC = ShadowedDecl->getDeclContext();
+ Diag(Shadow.VD->getLocation(), CaptureLoc.isInvalid()
+ ? diag::warn_decl_shadow_uncaptured_local
+ : diag::warn_decl_shadow)
+ << Shadow.VD->getDeclName()
+ << computeShadowedDeclKind(ShadowedDecl, OldDC) << OldDC;
+ if (!CaptureLoc.isInvalid())
+ Diag(CaptureLoc, diag::note_var_explicitly_captured_here)
+ << Shadow.VD->getDeclName() << /*explicitly*/ 0;
+ Diag(ShadowedDecl->getLocation(), diag::note_previous_declaration);
+ }
+}
+
/// \brief 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()))
@@ -6793,7 +6912,7 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
// OpenCL v1.2 s6.8 - The static qualifier is valid only in program
// scope.
if (getLangOpts().OpenCLVersion == 120 &&
- !getOpenCLOptions().cl_clang_storage_class_specifiers &&
+ !getOpenCLOptions().isEnabled("cl_clang_storage_class_specifiers") &&
NewVD->isStaticLocal()) {
Diag(NewVD->getLocation(), diag::err_static_function_scope);
NewVD->setInvalidDecl();
@@ -6821,17 +6940,6 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
NewVD->setInvalidDecl();
return;
}
- // OpenCL v2.0 s6.12.5 - Blocks with variadic arguments are not supported.
- // TODO: this check is not enough as it doesn't diagnose the typedef
- const BlockPointerType *BlkTy = T->getAs<BlockPointerType>();
- const FunctionProtoType *FTy =
- BlkTy->getPointeeType()->getAs<FunctionProtoType>();
- if (FTy && FTy->isVariadic()) {
- Diag(NewVD->getLocation(), diag::err_opencl_block_proto_variadic)
- << T << NewVD->getSourceRange();
- NewVD->setInvalidDecl();
- return;
- }
}
// OpenCL v1.2 s6.5 - All program scope variables must be declared in the
// __constant address space.
@@ -7481,18 +7589,20 @@ enum OpenCLParamType {
ValidKernelParam,
PtrPtrKernelParam,
PtrKernelParam,
- PrivatePtrKernelParam,
+ InvalidAddrSpacePtrKernelParam,
InvalidKernelParam,
RecordKernelParam
};
-static OpenCLParamType getOpenCLKernelParameterType(QualType PT) {
+static OpenCLParamType getOpenCLKernelParameterType(Sema &S, QualType PT) {
if (PT->isPointerType()) {
QualType PointeeType = PT->getPointeeType();
if (PointeeType->isPointerType())
return PtrPtrKernelParam;
- return PointeeType.getAddressSpace() == 0 ? PrivatePtrKernelParam
- : PtrKernelParam;
+ if (PointeeType.getAddressSpace() == LangAS::opencl_generic ||
+ PointeeType.getAddressSpace() == 0)
+ return InvalidAddrSpacePtrKernelParam;
+ return PtrKernelParam;
}
// TODO: Forbid the other integer types (size_t, ptrdiff_t...) when they can
@@ -7507,7 +7617,10 @@ static OpenCLParamType getOpenCLKernelParameterType(QualType PT) {
if (PT->isEventT())
return InvalidKernelParam;
- if (PT->isHalfType())
+ // OpenCL extension spec v1.2 s9.5:
+ // This extension adds support for half scalar and vector types as built-in
+ // types that can be used for arithmetic operations, conversions etc.
+ if (!S.getOpenCLOptions().isEnabled("cl_khr_fp16") && PT->isHalfType())
return InvalidKernelParam;
if (PT->isRecordType())
@@ -7528,7 +7641,7 @@ static void checkIsValidOpenCLKernelParameter(
if (ValidTypes.count(PT.getTypePtr()))
return;
- switch (getOpenCLKernelParameterType(PT)) {
+ switch (getOpenCLKernelParameterType(S, PT)) {
case PtrPtrKernelParam:
// OpenCL v1.2 s6.9.a:
// A kernel function argument cannot be declared as a
@@ -7537,11 +7650,12 @@ static void checkIsValidOpenCLKernelParameter(
D.setInvalidType();
return;
- case PrivatePtrKernelParam:
- // OpenCL v1.2 s6.9.a:
- // A kernel function argument cannot be declared as a
- // pointer to the private address space.
- S.Diag(Param->getLocation(), diag::err_opencl_private_ptr_kernel_param);
+ case InvalidAddrSpacePtrKernelParam:
+ // OpenCL v1.0 s6.5:
+ // __kernel function arguments declared to be a pointer of a type can point
+ // to one of the following address spaces only : __global, __local or
+ // __constant.
+ S.Diag(Param->getLocation(), diag::err_kernel_arg_address_space);
D.setInvalidType();
return;
@@ -7555,7 +7669,10 @@ static void checkIsValidOpenCLKernelParameter(
// OpenCL v1.2 s6.8 n:
// A kernel function argument cannot be declared
// of event_t type.
- S.Diag(Param->getLocation(), diag::err_bad_kernel_param_type) << PT;
+ // Do not diagnose half type since it is diagnosed as invalid argument
+ // type for any function elsewhere.
+ if (!PT->isHalfType())
+ S.Diag(Param->getLocation(), diag::err_bad_kernel_param_type) << PT;
D.setInvalidType();
return;
@@ -7611,7 +7728,7 @@ static void checkIsValidOpenCLKernelParameter(
if (ValidTypes.count(QT.getTypePtr()))
continue;
- OpenCLParamType ParamType = getOpenCLKernelParameterType(QT);
+ OpenCLParamType ParamType = getOpenCLKernelParameterType(S, QT);
if (ParamType == ValidKernelParam)
continue;
@@ -7625,7 +7742,7 @@ static void checkIsValidOpenCLKernelParameter(
// do not allow OpenCL objects to be passed as elements of the struct or
// union.
if (ParamType == PtrKernelParam || ParamType == PtrPtrKernelParam ||
- ParamType == PrivatePtrKernelParam) {
+ ParamType == InvalidAddrSpacePtrKernelParam) {
S.Diag(Param->getLocation(),
diag::err_record_with_pointers_kernel_param)
<< PT->isUnionType()
@@ -7657,6 +7774,28 @@ static void checkIsValidOpenCLKernelParameter(
} while (!VisitStack.empty());
}
+/// Find the DeclContext in which a tag is implicitly declared if we see an
+/// elaborated type specifier in the specified context, and lookup finds
+/// nothing.
+static DeclContext *getTagInjectionContext(DeclContext *DC) {
+ while (!DC->isFileContext() && !DC->isFunctionOrMethod())
+ DC = DC->getParent();
+ return DC;
+}
+
+/// Find the Scope in which a tag is implicitly declared if we see an
+/// elaborated type specifier in the specified context, and lookup finds
+/// nothing.
+static Scope *getTagInjectionScope(Scope *S, const LangOptions &LangOpts) {
+ while (S->isClassScope() ||
+ (LangOpts.CPlusPlus &&
+ S->isFunctionPrototypeScope()) ||
+ ((S->getFlags() & Scope::DeclScope) == 0) ||
+ (S->getEntity() && S->getEntity()->isTransparentContext()))
+ S = S->getParent();
+ return S;
+}
+
NamedDecl*
Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
TypeSourceInfo *TInfo, LookupResult &Previous,
@@ -8111,8 +8250,9 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// Copy the parameter declarations from the declarator D to the function
// declaration NewFD, if they are available. First scavenge them into Params.
SmallVector<ParmVarDecl*, 16> Params;
- if (D.isFunctionDeclarator()) {
- DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
+ unsigned FTIIdx;
+ if (D.isFunctionDeclarator(FTIIdx)) {
+ DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(FTIIdx).Fun;
// Check for C99 6.7.5.3p10 - foo(void) is a non-varargs
// function that takes no arguments, not a function that takes a
@@ -8130,6 +8270,41 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
NewFD->setInvalidDecl();
}
}
+
+ if (!getLangOpts().CPlusPlus) {
+ // In C, find all the tag declarations from the prototype and move them
+ // into the function DeclContext. Remove them from the surrounding tag
+ // injection context of the function, which is typically but not always
+ // the TU.
+ DeclContext *PrototypeTagContext =
+ getTagInjectionContext(NewFD->getLexicalDeclContext());
+ for (NamedDecl *NonParmDecl : FTI.getDeclsInPrototype()) {
+ auto *TD = dyn_cast<TagDecl>(NonParmDecl);
+
+ // We don't want to reparent enumerators. Look at their parent enum
+ // instead.
+ if (!TD) {
+ if (auto *ECD = dyn_cast<EnumConstantDecl>(NonParmDecl))
+ TD = cast<EnumDecl>(ECD->getDeclContext());
+ }
+ if (!TD)
+ continue;
+ DeclContext *TagDC = TD->getLexicalDeclContext();
+ if (!TagDC->containsDecl(TD))
+ continue;
+ TagDC->removeDecl(TD);
+ TD->setDeclContext(NewFD);
+ NewFD->addDecl(TD);
+
+ // Preserve the lexical DeclContext if it is not the surrounding tag
+ // injection context of the FD. In this example, the semantic context of
+ // E will be f and the lexical context will be S, while both the
+ // semantic and lexical contexts of S will be f:
+ // void f(struct S { enum E { a } f; } s);
+ if (TagDC != PrototypeTagContext)
+ TD->setLexicalDeclContext(TagDC);
+ }
+ }
} else if (const FunctionProtoType *FT = R->getAs<FunctionProtoType>()) {
// When we're declaring a function with a typedef, typeof, etc as in the
// following example, we'll need to synthesize (unnamed)
@@ -8155,15 +8330,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// Finally, we know we have the right number of parameters, install them.
NewFD->setParams(Params);
- // Find all anonymous symbols defined during the declaration of this function
- // and add to NewFD. This lets us track decls such 'enum Y' in:
- //
- // void f(enum Y {AA} x) {}
- //
- // which would otherwise incorrectly end up in the translation unit scope.
- NewFD->setDeclsInPrototypeScope(DeclsInPrototypeScope);
- DeclsInPrototypeScope.clear();
-
if (D.getDeclSpec().isNoreturnSpecified())
NewFD->addAttr(
::new(Context) C11NoReturnAttr(D.getDeclSpec().getNoreturnSpecLoc(),
@@ -8194,9 +8360,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// Handle attributes.
ProcessDeclAttributes(S, NewFD, D);
- if (getLangOpts().CUDA)
- maybeAddCUDAHostDeviceAttrs(S, NewFD, Previous);
-
if (getLangOpts().OpenCL) {
// OpenCL v1.1 s6.5: Using an address space qualifier in a function return
// type declaration will generate a compilation error.
@@ -8299,6 +8462,15 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
TemplateArgs.setRAngleLoc(D.getIdentifierLoc());
}
+ // We do not add HD attributes to specializations here because
+ // they may have different constexpr-ness compared to their
+ // templates and, after maybeAddCUDAHostDeviceAttrs() is applied,
+ // may end up with different effective targets. Instead, a
+ // specialization inherits its target attributes from its template
+ // in the CheckFunctionTemplateSpecialization() call below.
+ if (getLangOpts().CUDA & !isFunctionTemplateSpecialization)
+ maybeAddCUDAHostDeviceAttrs(NewFD, Previous);
+
// If it's a friend (and only if it's a friend), it's possible
// that either the specialized function type or the specialized
// template is dependent, and therefore matching will fail. In
@@ -8376,7 +8548,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
? cast<NamedDecl>(FunctionTemplate)
: NewFD);
- if (isFriend && D.isRedeclaration()) {
+ if (isFriend && NewFD->getPreviousDecl()) {
AccessSpecifier Access = AS_public;
if (!NewFD->isInvalidDecl())
Access = NewFD->getPreviousDecl()->getAccess();
@@ -8618,6 +8790,32 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
return NewFD;
}
+/// \brief 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.
+/// \param PrevDecl Previous declaration found with proper lookup method for the
+/// same declaration name.
+/// \returns True if D must be added to the redeclaration chain which PrevDecl
+/// belongs to.
+///
+bool Sema::shouldLinkDependentDeclWithPrevious(Decl *D, Decl *PrevDecl) {
+ // Any declarations should be put into redeclaration chains except for
+ // friend declaration in a dependent context that names a function in
+ // namespace scope.
+ //
+ // This allows to compile code like:
+ //
+ // void func();
+ // template<typename T> class C1 { friend void func() { } };
+ // template<typename T> class C2 { friend void func() { } };
+ //
+ // This code snippet is a valid code unless both templates are instantiated.
+ return !(D->getLexicalDeclContext()->isDependentContext() &&
+ D->getDeclContext()->isFileContext() &&
+ D->getFriendObjectKind() != Decl::FOK_None);
+}
+
/// \brief Perform semantic checking of a new function declaration.
///
/// Performs semantic analysis of the new function declaration
@@ -8801,11 +8999,12 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
}
} else {
- // This needs to happen first so that 'inline' propagates.
- NewFD->setPreviousDeclaration(cast<FunctionDecl>(OldDecl));
-
- if (isa<CXXMethodDecl>(NewFD))
- NewFD->setAccess(OldDecl->getAccess());
+ if (shouldLinkDependentDeclWithPrevious(NewFD, OldDecl)) {
+ // This needs to happen first so that 'inline' propagates.
+ NewFD->setPreviousDeclaration(cast<FunctionDecl>(OldDecl));
+ if (isa<CXXMethodDecl>(NewFD))
+ NewFD->setAccess(OldDecl->getAccess());
+ }
}
}
@@ -8880,11 +9079,16 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
ASTContext::GetBuiltinTypeError Error;
LookupPredefedObjCSuperType(*this, S, NewFD->getIdentifier());
QualType T = Context.GetBuiltinType(BuiltinID, Error);
- if (!T.isNull() && !Context.hasSameType(T, NewFD->getType())) {
+ // If the type of the builtin differs only in its exception
+ // specification, that's OK.
+ // FIXME: If the types do differ in this way, it would be better to
+ // retain the 'noexcept' form of the type.
+ if (!T.isNull() &&
+ !Context.hasSameFunctionTypeIgnoringExceptionSpec(T,
+ NewFD->getType()))
// The type of this function differs from the type of the builtin,
// so forget about the builtin entirely.
Context.BuiltinInfo.forgetBuiltin(BuiltinID, Context.Idents);
- }
}
// If this function is declared as being extern "C", then check to see if
@@ -8900,6 +9104,45 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
!R->isObjCObjectPointerType())
Diag(NewFD->getLocation(), diag::warn_return_value_udt) << NewFD << R;
}
+
+ // C++1z [dcl.fct]p6:
+ // [...] whether the function has a non-throwing exception-specification
+ // [is] part of the function type
+ //
+ // This results in an ABI break between C++14 and C++17 for functions whose
+ // declared type includes an exception-specification in a parameter or
+ // return type. (Exception specifications on the function itself are OK in
+ // most cases, and exception specifications are not permitted in most other
+ // contexts where they could make it into a mangling.)
+ if (!getLangOpts().CPlusPlus1z && !NewFD->getPrimaryTemplate()) {
+ auto HasNoexcept = [&](QualType T) -> bool {
+ // Strip off declarator chunks that could be between us and a function
+ // type. We don't need to look far, exception specifications are very
+ // restricted prior to C++17.
+ if (auto *RT = T->getAs<ReferenceType>())
+ T = RT->getPointeeType();
+ else if (T->isAnyPointerType())
+ T = T->getPointeeType();
+ else if (auto *MPT = T->getAs<MemberPointerType>())
+ T = MPT->getPointeeType();
+ if (auto *FPT = T->getAs<FunctionProtoType>())
+ if (FPT->isNothrow(Context))
+ return true;
+ return false;
+ };
+
+ auto *FPT = NewFD->getType()->castAs<FunctionProtoType>();
+ bool AnyNoexcept = HasNoexcept(FPT->getReturnType());
+ for (QualType T : FPT->param_types())
+ AnyNoexcept |= HasNoexcept(T);
+ if (AnyNoexcept)
+ Diag(NewFD->getLocation(),
+ diag::warn_cxx1z_compat_exception_spec_in_signature)
+ << NewFD;
+ }
+
+ if (!Redeclaration && LangOpts.CUDA)
+ checkCUDATargetOverload(NewFD, Previous);
}
return Redeclaration;
}
@@ -9421,6 +9664,20 @@ namespace {
}
} // end anonymous namespace
+namespace {
+ // Simple wrapper to add the name of a variable or (if no variable is
+ // available) a DeclarationName into a diagnostic.
+ struct VarDeclOrName {
+ VarDecl *VDecl;
+ DeclarationName Name;
+
+ friend const Sema::SemaDiagnosticBuilder &
+ operator<<(const Sema::SemaDiagnosticBuilder &Diag, VarDeclOrName VN) {
+ return VN.VDecl ? Diag << VN.VDecl : Diag << VN.Name;
+ }
+ };
+} // end anonymous namespace
+
QualType Sema::deduceVarTypeFromInitializer(VarDecl *VDecl,
DeclarationName Name, QualType Type,
TypeSourceInfo *TSI,
@@ -9430,6 +9687,8 @@ QualType Sema::deduceVarTypeFromInitializer(VarDecl *VDecl,
assert((!VDecl || !VDecl->isInitCapture()) &&
"init captures are expected to be deduced prior to initialization");
+ VarDeclOrName VN{VDecl, Name};
+
ArrayRef<Expr *> DeduceInits = Init;
if (DirectInit) {
if (auto *PL = dyn_cast<ParenListExpr>(Init))
@@ -9445,7 +9704,7 @@ QualType Sema::deduceVarTypeFromInitializer(VarDecl *VDecl,
Diag(Init->getLocStart(), IsInitCapture
? diag::err_init_capture_no_expression
: diag::err_auto_var_init_no_expression)
- << Name << Type << Range;
+ << VN << Type << Range;
return QualType();
}
@@ -9453,7 +9712,7 @@ QualType Sema::deduceVarTypeFromInitializer(VarDecl *VDecl,
Diag(DeduceInits[1]->getLocStart(),
IsInitCapture ? diag::err_init_capture_multiple_expressions
: diag::err_auto_var_init_multiple_expressions)
- << Name << Type << Range;
+ << VN << Type << Range;
return QualType();
}
@@ -9462,7 +9721,7 @@ QualType Sema::deduceVarTypeFromInitializer(VarDecl *VDecl,
Diag(Init->getLocStart(), IsInitCapture
? diag::err_init_capture_paren_braces
: diag::err_auto_var_init_paren_braces)
- << isa<InitListExpr>(Init) << Name << Type << Range;
+ << isa<InitListExpr>(Init) << VN << Type << Range;
return QualType();
}
@@ -9478,6 +9737,15 @@ QualType Sema::deduceVarTypeFromInitializer(VarDecl *VDecl,
DefaultedAnyToId = true;
}
+ // C++ [dcl.decomp]p1:
+ // If the assignment-expression [...] has array type A and no ref-qualifier
+ // is present, e has type cv A
+ if (VDecl && isa<DecompositionDecl>(VDecl) &&
+ Context.hasSameUnqualifiedType(Type, Context.getAutoDeductType()) &&
+ DeduceInit->getType()->isConstantArrayType())
+ return Context.getQualifiedType(DeduceInit->getType(),
+ Type.getQualifiers());
+
QualType DeducedType;
if (DeduceAutoType(TSI, DeduceInit, DeducedType) == DAR_Failed) {
if (!IsInitCapture)
@@ -9485,13 +9753,13 @@ QualType Sema::deduceVarTypeFromInitializer(VarDecl *VDecl,
else if (isa<InitListExpr>(Init))
Diag(Range.getBegin(),
diag::err_init_capture_deduction_failure_from_init_list)
- << Name
+ << VN
<< (DeduceInit->getType().isNull() ? TSI->getType()
: DeduceInit->getType())
<< DeduceInit->getSourceRange();
else
Diag(Range.getBegin(), diag::err_init_capture_deduction_failure)
- << Name << TSI->getType()
+ << VN << TSI->getType()
<< (DeduceInit->getType().isNull() ? TSI->getType()
: DeduceInit->getType())
<< DeduceInit->getSourceRange();
@@ -9505,7 +9773,7 @@ QualType Sema::deduceVarTypeFromInitializer(VarDecl *VDecl,
if (ActiveTemplateInstantiations.empty() && !DefaultedAnyToId &&
!IsInitCapture && !DeducedType.isNull() && DeducedType->isObjCIdType()) {
SourceLocation Loc = TSI->getTypeLoc().getBeginLoc();
- Diag(Loc, diag::warn_auto_var_is_id) << Name << Range;
+ Diag(Loc, diag::warn_auto_var_is_id) << VN << Range;
}
return DeducedType;
@@ -9614,25 +9882,15 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
VDecl->setInvalidDecl();
}
+ // If adding the initializer will turn this declaration into a definition,
+ // and we already have a definition for this variable, diagnose or otherwise
+ // handle the situation.
VarDecl *Def;
if ((Def = VDecl->getDefinition()) && Def != VDecl &&
- (!VDecl->isStaticDataMember() || VDecl->isOutOfLine())) {
- NamedDecl *Hidden = nullptr;
- if (!hasVisibleDefinition(Def, &Hidden) &&
- (VDecl->getFormalLinkage() == InternalLinkage ||
- VDecl->getDescribedVarTemplate() ||
- VDecl->getNumTemplateParameterLists() ||
- VDecl->getDeclContext()->isDependentContext())) {
- // The previous definition is hidden, and multiple definitions are
- // permitted (in separate TUs). Form another definition of it.
- } else {
- Diag(VDecl->getLocation(), diag::err_redefinition)
- << VDecl->getDeclName();
- Diag(Def->getLocation(), diag::note_previous_definition);
- VDecl->setInvalidDecl();
- return;
- }
- }
+ (!VDecl->isStaticDataMember() || VDecl->isOutOfLine()) &&
+ !VDecl->isThisDeclarationADemotedDefinition() &&
+ checkVarDeclRedefinition(Def, VDecl))
+ return;
if (getLangOpts().CPlusPlus) {
// C++ [class.static.data]p4
@@ -9692,6 +9950,18 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
// Perform the initialization.
ParenListExpr *CXXDirectInit = dyn_cast<ParenListExpr>(Init);
if (!VDecl->isInvalidDecl()) {
+ // Handle errors like: int a({0})
+ if (CXXDirectInit && CXXDirectInit->getNumExprs() == 1 &&
+ !canInitializeWithParenthesizedList(VDecl->getType()))
+ if (auto IList = dyn_cast<InitListExpr>(CXXDirectInit->getExpr(0))) {
+ Diag(VDecl->getLocation(), diag::err_list_init_in_parens)
+ << VDecl->getType() << CXXDirectInit->getSourceRange()
+ << FixItHint::CreateRemoval(CXXDirectInit->getLocStart())
+ << FixItHint::CreateRemoval(CXXDirectInit->getLocEnd());
+ Init = IList;
+ CXXDirectInit = nullptr;
+ }
+
InitializedEntity Entity = InitializedEntity::InitializeVariable(VDecl);
InitializationKind Kind =
DirectInit
@@ -9909,10 +10179,17 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
VDecl->setInvalidDecl();
}
} 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.
+ // 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
+ // C++ rules.
if (VDecl->getStorageClass() == SC_Extern &&
- (!getLangOpts().CPlusPlus ||
- !(Context.getBaseElementType(VDecl->getType()).isConstQualified() ||
- VDecl->isExternC())) &&
+ ((!getLangOpts().CPlusPlus && !VDecl->hasAttr<SelectAnyAttr>()) ||
+ !Context.getBaseElementType(VDecl->getType()).isConstQualified()) &&
+ !(getLangOpts().CPlusPlus && VDecl->isExternC()) &&
!isTemplateInstantiation(VDecl->getTemplateSpecializationKind()))
Diag(VDecl->getLocation(), diag::warn_extern_init);
@@ -9957,6 +10234,11 @@ void Sema::ActOnInitializerError(Decl *D) {
VarDecl *VD = dyn_cast<VarDecl>(D);
if (!VD) return;
+ // Bindings are not usable if we can't make sense of the initializer.
+ if (auto *DD = dyn_cast<DecompositionDecl>(D))
+ for (auto *BD : DD->bindings())
+ BD->setInvalidDecl();
+
// Auto types are meaningless if we can't make sense of the initializer.
if (ParsingInitForAutoVars.count(D)) {
D->setInvalidDecl();
@@ -9986,6 +10268,18 @@ void Sema::ActOnInitializerError(Decl *D) {
// though.
}
+/// Checks if an object of the given type can be initialized with parenthesized
+/// init-list.
+///
+/// \param TargetType Type of object being initialized.
+///
+/// The function is used to detect wrong initializations, such as 'int({0})'.
+///
+bool Sema::canInitializeWithParenthesizedList(QualType TargetType) {
+ return TargetType->isDependentType() || TargetType->isRecordType() ||
+ TargetType->getContainedAutoType();
+}
+
void Sema::ActOnUninitializedDecl(Decl *RealDecl,
bool TypeMayContainAuto) {
// If there is no declaration, there was an error parsing it. Just ignore it.
@@ -9995,6 +10289,13 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl,
if (VarDecl *Var = dyn_cast<VarDecl>(RealDecl)) {
QualType Type = Var->getType();
+ // C++1z [dcl.dcl]p1 grammar implies that an initializer is mandatory.
+ if (isa<DecompositionDecl>(RealDecl)) {
+ Diag(Var->getLocation(), diag::err_decomp_decl_requires_init) << Var;
+ Var->setInvalidDecl();
+ return;
+ }
+
// C++11 [dcl.spec.auto]p3
if (TypeMayContainAuto && Type->getContainedAutoType()) {
Diag(Var->getLocation(), diag::err_auto_var_requires_init)
@@ -10009,7 +10310,8 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl,
// C++11 [dcl.constexpr]p1: The constexpr specifier shall be applied only to
// the definition of a variable [...] or the declaration of a static data
// member.
- if (Var->isConstexpr() && !Var->isThisDeclarationADefinition()) {
+ if (Var->isConstexpr() && !Var->isThisDeclarationADefinition() &&
+ !Var->isThisDeclarationADemotedDefinition()) {
if (Var->isStaticDataMember()) {
// C++1z removes the relevant rule; the in-class declaration is always
// a definition there.
@@ -10344,8 +10646,17 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
Diag(var->getLocation(), diag::warn_missing_variable_declarations) << var;
}
+ // Cache the result of checking for constant initialization.
+ Optional<bool> CacheHasConstInit;
+ const Expr *CacheCulprit;
+ auto checkConstInit = [&]() mutable {
+ if (!CacheHasConstInit)
+ CacheHasConstInit = var->getInit()->isConstantInitializer(
+ Context, var->getType()->isReferenceType(), &CacheCulprit);
+ return *CacheHasConstInit;
+ };
+
if (var->getTLSKind() == VarDecl::TLS_Static) {
- const Expr *Culprit;
if (var->getType().isDestructedType()) {
// GNU C++98 edits for __thread, [basic.start.term]p3:
// The type of an object with thread storage duration shall not
@@ -10353,17 +10664,17 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
Diag(var->getLocation(), diag::err_thread_nontrivial_dtor);
if (getLangOpts().CPlusPlus11)
Diag(var->getLocation(), diag::note_use_thread_local);
- } else if (getLangOpts().CPlusPlus && var->hasInit() &&
- !var->getInit()->isConstantInitializer(
- Context, var->getType()->isReferenceType(), &Culprit)) {
- // GNU C++98 edits for __thread, [basic.start.init]p4:
- // An object of thread storage duration shall not require dynamic
- // initialization.
- // FIXME: Need strict checking here.
- Diag(Culprit->getExprLoc(), diag::err_thread_dynamic_init)
- << Culprit->getSourceRange();
- if (getLangOpts().CPlusPlus11)
- Diag(var->getLocation(), diag::note_use_thread_local);
+ } else if (getLangOpts().CPlusPlus && var->hasInit()) {
+ if (!checkConstInit()) {
+ // GNU C++98 edits for __thread, [basic.start.init]p4:
+ // An object of thread storage duration shall not require dynamic
+ // initialization.
+ // FIXME: Need strict checking here.
+ Diag(CacheCulprit->getExprLoc(), diag::err_thread_dynamic_init)
+ << CacheCulprit->getSourceRange();
+ if (getLangOpts().CPlusPlus11)
+ Diag(var->getLocation(), diag::note_use_thread_local);
+ }
}
}
@@ -10400,7 +10711,16 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
}
// All the following checks are C++ only.
- if (!getLangOpts().CPlusPlus) return;
+ if (!getLangOpts().CPlusPlus) {
+ // If this variable must be emitted, add it as an initializer for the
+ // current module.
+ if (Context.DeclMustBeEmitted(var) && !ModuleScopes.empty())
+ Context.addModuleInitializer(ModuleScopes.back().Module, var);
+ return;
+ }
+
+ if (auto *DD = dyn_cast<DecompositionDecl>(var))
+ CheckCompleteDecompositionDeclaration(DD);
QualType type = var->getType();
if (type->isDependentType()) return;
@@ -10434,18 +10754,6 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
if (!var->getDeclContext()->isDependentContext() &&
Init && !Init->isValueDependent()) {
- if (IsGlobal && !var->isConstexpr() &&
- !getDiagnostics().isIgnored(diag::warn_global_constructor,
- var->getLocation())) {
- // Warn about globals which don't have a constant initializer. Don't
- // warn about globals with a non-trivial destructor because we already
- // warned about them.
- CXXRecordDecl *RD = baseType->getAsCXXRecordDecl();
- if (!(RD && !RD->hasTrivialDestructor()) &&
- !Init->isConstantInitializer(Context, baseType->isReferenceType()))
- Diag(var->getLocation(), diag::warn_global_constructor)
- << Init->getSourceRange();
- }
if (var->isConstexpr()) {
SmallVector<PartialDiagnosticAt, 8> Notes;
@@ -10469,11 +10777,45 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
// initialized by a constant expression if we check later.
var->checkInitIsICE();
}
+
+ // Don't emit further diagnostics about constexpr globals since they
+ // were just diagnosed.
+ if (!var->isConstexpr() && GlobalStorage &&
+ var->hasAttr<RequireConstantInitAttr>()) {
+ // FIXME: Need strict checking in C++03 here.
+ bool DiagErr = getLangOpts().CPlusPlus11
+ ? !var->checkInitIsICE() : !checkConstInit();
+ if (DiagErr) {
+ auto attr = var->getAttr<RequireConstantInitAttr>();
+ Diag(var->getLocation(), diag::err_require_constant_init_failed)
+ << Init->getSourceRange();
+ Diag(attr->getLocation(), diag::note_declared_required_constant_init_here)
+ << attr->getRange();
+ }
+ }
+ else if (!var->isConstexpr() && IsGlobal &&
+ !getDiagnostics().isIgnored(diag::warn_global_constructor,
+ var->getLocation())) {
+ // Warn about globals which don't have a constant initializer. Don't
+ // warn about globals with a non-trivial destructor because we already
+ // warned about them.
+ CXXRecordDecl *RD = baseType->getAsCXXRecordDecl();
+ if (!(RD && !RD->hasTrivialDestructor())) {
+ if (!checkConstInit())
+ Diag(var->getLocation(), diag::warn_global_constructor)
+ << Init->getSourceRange();
+ }
+ }
}
// Require the destructor.
if (const RecordType *recordType = baseType->getAs<RecordType>())
FinalizeVarWithDestructor(var, recordType);
+
+ // If this variable must be emitted, add it as an initializer for the current
+ // module.
+ if (Context.DeclMustBeEmitted(var) && !ModuleScopes.empty())
+ Context.addModuleInitializer(ModuleScopes.back().Module, var);
}
/// \brief Determines if a variable's alignment is dependent.
@@ -10497,6 +10839,12 @@ Sema::FinalizeDeclaration(Decl *ThisDecl) {
if (!VD)
return;
+ if (auto *DD = dyn_cast<DecompositionDecl>(ThisDecl)) {
+ for (auto *BD : DD->bindings()) {
+ FinalizeDeclaration(BD);
+ }
+ }
+
checkAttributesAfterMerging(*this, *VD);
// Perform TLS alignment check here after attributes attached to the variable
@@ -10527,12 +10875,11 @@ Sema::FinalizeDeclaration(Decl *ThisDecl) {
// CUDA E.2.9.4: Within the body of a __device__ or __global__
// function, only __shared__ variables may be declared with
// static storage class.
- if (getLangOpts().CUDA && getLangOpts().CUDAIsDevice &&
- (FD->hasAttr<CUDADeviceAttr>() || FD->hasAttr<CUDAGlobalAttr>()) &&
- !VD->hasAttr<CUDASharedAttr>()) {
- Diag(VD->getLocation(), diag::err_device_static_local_var);
+ if (getLangOpts().CUDA && !VD->hasAttr<CUDASharedAttr>() &&
+ CUDADiagIfDeviceCode(VD->getLocation(),
+ diag::err_device_static_local_var)
+ << CurrentCUDATarget())
VD->setInvalidDecl();
- }
}
}
@@ -10541,36 +10888,55 @@ 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 && getLangOpts().CUDAIsDevice) {
+ if (getLangOpts().CUDA) {
const Expr *Init = VD->getInit();
- if (Init && VD->hasGlobalStorage() &&
- (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())
+ 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 =
- 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();
+ 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();
+ }
+ }
}
}
}
@@ -10675,13 +11041,36 @@ Sema::DeclGroupPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
Decls.push_back(DS.getRepAsDecl());
DeclaratorDecl *FirstDeclaratorInGroup = nullptr;
- for (unsigned i = 0, e = Group.size(); i != e; ++i)
+ DecompositionDecl *FirstDecompDeclaratorInGroup = nullptr;
+ bool DiagnosedMultipleDecomps = false;
+
+ for (unsigned i = 0, e = Group.size(); i != e; ++i) {
if (Decl *D = Group[i]) {
- if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D))
- if (!FirstDeclaratorInGroup)
- FirstDeclaratorInGroup = DD;
+ auto *DD = dyn_cast<DeclaratorDecl>(D);
+ if (DD && !FirstDeclaratorInGroup)
+ FirstDeclaratorInGroup = DD;
+
+ auto *Decomp = dyn_cast<DecompositionDecl>(D);
+ if (Decomp && !FirstDecompDeclaratorInGroup)
+ FirstDecompDeclaratorInGroup = Decomp;
+
+ // A decomposition declaration cannot be combined with any other
+ // declaration in the same group.
+ auto *OtherDD = FirstDeclaratorInGroup;
+ if (OtherDD == FirstDecompDeclaratorInGroup)
+ OtherDD = DD;
+ if (OtherDD && FirstDecompDeclaratorInGroup &&
+ OtherDD != FirstDecompDeclaratorInGroup &&
+ !DiagnosedMultipleDecomps) {
+ Diag(FirstDecompDeclaratorInGroup->getLocation(),
+ diag::err_decomp_decl_not_alone)
+ << OtherDD->getSourceRange();
+ DiagnosedMultipleDecomps = true;
+ }
+
Decls.push_back(D);
}
+ }
if (DeclSpec::isDeclRep(DS.getTypeSpecType())) {
if (TagDecl *Tag = dyn_cast_or_null<TagDecl>(DS.getRepAsDecl())) {
@@ -11168,9 +11557,8 @@ Sema::CheckForFunctionRedefinition(FunctionDecl *FD,
SkipBody->ShouldSkip = true;
if (auto *TD = Definition->getDescribedFunctionTemplate())
makeMergedDefinitionVisible(TD, FD->getLocation());
- else
- makeMergedDefinitionVisible(const_cast<FunctionDecl*>(Definition),
- FD->getLocation());
+ makeMergedDefinitionVisible(const_cast<FunctionDecl*>(Definition),
+ FD->getLocation());
return;
}
@@ -11256,6 +11644,11 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D,
return D;
}
+ // Mark this function as "will have a body eventually". This lets users to
+ // call e.g. isInlineDefinitionExternallyVisible while we're still parsing
+ // this function.
+ FD->setWillHaveBody();
+
// If we are instantiating a generic lambda call operator, push
// a LambdaScopeInfo onto the function stack. But use the information
// that's already been calculated (ActOnLambdaExpr) to prime the current
@@ -11300,6 +11693,29 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D,
CheckParmsForFunctionDef(FD->parameters(),
/*CheckParameterNames=*/true);
+ // Add non-parameter declarations already in the function to the current
+ // scope.
+ if (FnBodyScope) {
+ for (Decl *NPD : FD->decls()) {
+ auto *NonParmDecl = dyn_cast<NamedDecl>(NPD);
+ if (!NonParmDecl)
+ continue;
+ assert(!isa<ParmVarDecl>(NonParmDecl) &&
+ "parameters should not be in newly created FD yet");
+
+ // If the decl has a name, make it accessible in the current scope.
+ if (NonParmDecl->getDeclName())
+ PushOnScopeChains(NonParmDecl, FnBodyScope, /*AddToContext=*/false);
+
+ // Similarly, dive into enums and fish their constants out, making them
+ // accessible in this scope.
+ if (auto *ED = dyn_cast<EnumDecl>(NonParmDecl)) {
+ for (auto *EI : ED->enumerators())
+ PushOnScopeChains(EI, FnBodyScope, /*AddToContext=*/false);
+ }
+ }
+ }
+
// Introduce our parameters into the function scope
for (auto Param : FD->parameters()) {
Param->setOwningFunction(FD);
@@ -11312,39 +11728,6 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D,
}
}
- // If we had any tags defined in the function prototype,
- // introduce them into the function scope.
- if (FnBodyScope) {
- for (ArrayRef<NamedDecl *>::iterator
- I = FD->getDeclsInPrototypeScope().begin(),
- E = FD->getDeclsInPrototypeScope().end();
- I != E; ++I) {
- NamedDecl *D = *I;
-
- // Some of these decls (like enums) may have been pinned to the
- // translation unit for lack of a real context earlier. If so, remove
- // from the translation unit and reattach to the current context.
- if (D->getLexicalDeclContext() == Context.getTranslationUnitDecl()) {
- // Is the decl actually in the context?
- if (Context.getTranslationUnitDecl()->containsDecl(D))
- Context.getTranslationUnitDecl()->removeDecl(D);
- // Either way, reassign the lexical decl context to our FunctionDecl.
- D->setLexicalDeclContext(CurContext);
- }
-
- // If the decl has a non-null name, make accessible in the current scope.
- if (!D->getName().empty())
- PushOnScopeChains(D, FnBodyScope, /*AddToContext=*/false);
-
- // Similarly, dive into enums and fish their constants out, making them
- // accessible in this scope.
- if (auto *ED = dyn_cast<EnumDecl>(D)) {
- for (auto *EI : ED->enumerators())
- PushOnScopeChains(EI, FnBodyScope, /*AddToContext=*/false);
- }
- }
- }
-
// Ensure that the function's exception specification is instantiated.
if (const FunctionProtoType *FPT = FD->getType()->getAs<FunctionProtoType>())
ResolveExceptionSpec(D->getLocation(), FPT);
@@ -11446,7 +11829,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
sema::AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy();
sema::AnalysisBasedWarnings::Policy *ActivePolicy = nullptr;
- if (getLangOpts().Coroutines && !getCurFunction()->CoroutineStmts.empty())
+ if (getLangOpts().CoroutinesTS && !getCurFunction()->CoroutineStmts.empty())
CheckCompletedCoroutineBody(FD, Body);
if (FD) {
@@ -11555,6 +11938,21 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
<< FixItHint::CreateInsertion(FTL.getRParenLoc(), "void");
}
}
+
+ // GNU warning -Wstrict-prototypes
+ // Warn if K&R function is defined without a previous declaration.
+ // This warning is issued only if the definition itself does not provide
+ // a prototype. Only K&R definitions do not provide a prototype.
+ // An empty list in a function declarator that is part of a definition
+ // of that function specifies that the function has no parameters
+ // (C99 6.7.5.3p14)
+ if (!FD->hasWrittenPrototype() && FD->getNumParams() > 0 &&
+ !LangOpts.CPlusPlus) {
+ TypeSourceInfo *TI = FD->getTypeSourceInfo();
+ TypeLoc TL = TI->getTypeLoc();
+ FunctionTypeLoc FTL = TL.castAs<FunctionTypeLoc>();
+ Diag(FTL.getLParenLoc(), diag::warn_strict_prototypes) << 1;
+ }
}
if (auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
@@ -11637,6 +12035,9 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
return nullptr;
}
+ if (Body && getCurFunction()->HasPotentialAvailabilityViolations)
+ DiagnoseUnguardedAvailabilityViolations(dcl);
+
assert(!getCurFunction()->ObjCShouldCallSuper &&
"This should only be set for ObjC methods, which should have been "
"handled in the block above.");
@@ -11683,6 +12084,21 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
if (FD && FD->hasAttr<NakedAttr>()) {
for (const Stmt *S : Body->children()) {
+ // Allow local register variables without initializer as they don't
+ // require prologue.
+ bool RegisterVariables = false;
+ if (auto *DS = dyn_cast<DeclStmt>(S)) {
+ for (const auto *Decl : DS->decls()) {
+ if (const auto *Var = dyn_cast<VarDecl>(Decl)) {
+ RegisterVariables =
+ Var->hasAttr<AsmLabelAttr>() && !Var->hasInit();
+ if (!RegisterVariables)
+ break;
+ }
+ }
+ }
+ if (RegisterVariables)
+ continue;
if (!isa<AsmStmt>(S) && !isa<NullStmt>(S)) {
Diag(S->getLocStart(), diag::err_non_asm_stmt_in_naked_function);
Diag(FD->getAttr<NakedAttr>()->getLocation(), diag::note_attribute);
@@ -11796,6 +12212,7 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
/*NumExceptions=*/0,
/*NoexceptExpr=*/nullptr,
/*ExceptionSpecTokens=*/nullptr,
+ /*DeclsInPrototype=*/None,
Loc, Loc, D),
DS.getAttributes(),
SourceLocation());
@@ -12069,6 +12486,31 @@ static bool isClassCompatTagKind(TagTypeKind Tag)
return Tag == TTK_Struct || Tag == TTK_Class || Tag == TTK_Interface;
}
+Sema::NonTagKind Sema::getNonTagTypeDeclKind(const Decl *PrevDecl,
+ TagTypeKind TTK) {
+ if (isa<TypedefDecl>(PrevDecl))
+ return NTK_Typedef;
+ else if (isa<TypeAliasDecl>(PrevDecl))
+ return NTK_TypeAlias;
+ else if (isa<ClassTemplateDecl>(PrevDecl))
+ return NTK_Template;
+ else if (isa<TypeAliasTemplateDecl>(PrevDecl))
+ return NTK_TypeAliasTemplate;
+ else if (isa<TemplateTemplateParmDecl>(PrevDecl))
+ return NTK_TemplateTemplateArgument;
+ switch (TTK) {
+ case TTK_Struct:
+ case TTK_Interface:
+ case TTK_Class:
+ return getLangOpts().CPlusPlus ? NTK_NonClass : NTK_NonStruct;
+ case TTK_Union:
+ return NTK_NonUnion;
+ case TTK_Enum:
+ return NTK_NonEnum;
+ }
+ llvm_unreachable("invalid TTK");
+}
+
/// \brief Determine whether a tag with a given kind is acceptable
/// as a redeclaration of the given tag declaration.
///
@@ -12226,28 +12668,6 @@ static bool isAcceptableTagRedeclContext(Sema &S, DeclContext *OldDC,
return false;
}
-/// Find the DeclContext in which a tag is implicitly declared if we see an
-/// elaborated type specifier in the specified context, and lookup finds
-/// nothing.
-static DeclContext *getTagInjectionContext(DeclContext *DC) {
- while (!DC->isFileContext() && !DC->isFunctionOrMethod())
- DC = DC->getParent();
- return DC;
-}
-
-/// Find the Scope in which a tag is implicitly declared if we see an
-/// elaborated type specifier in the specified context, and lookup finds
-/// nothing.
-static Scope *getTagInjectionScope(Scope *S, const LangOptions &LangOpts) {
- while (S->isClassScope() ||
- (LangOpts.CPlusPlus &&
- S->isFunctionPrototypeScope()) ||
- ((S->getFlags() & Scope::DeclScope) == 0) ||
- (S->getEntity() && S->getEntity()->isTransparentContext()))
- S = S->getParent();
- return S;
-}
-
/// \brief 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
@@ -12361,6 +12781,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
DeclContext *SearchDC = CurContext;
DeclContext *DC = CurContext;
bool isStdBadAlloc = false;
+ bool isStdAlignValT = false;
RedeclarationKind Redecl = ForRedeclaration;
if (TUK == TUK_Friend || TUK == TUK_Reference)
@@ -12515,15 +12936,20 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
}
if (getLangOpts().CPlusPlus && Name && DC && StdNamespace &&
- DC->Equals(getStdNamespace()) && Name->isStr("bad_alloc")) {
- // This is a declaration of or a reference to "std::bad_alloc".
- isStdBadAlloc = true;
+ DC->Equals(getStdNamespace())) {
+ if (Name->isStr("bad_alloc")) {
+ // This is a declaration of or a reference to "std::bad_alloc".
+ isStdBadAlloc = true;
- if (Previous.empty() && StdBadAlloc) {
- // std::bad_alloc has been implicitly declared (but made invisible to
- // name lookup). Fill in this implicit declaration as the previous
+ // If std::bad_alloc has been implicitly declared (but made invisible to
+ // name lookup), fill in this implicit declaration as the previous
// declaration, so that the declarations get chained appropriately.
- Previous.addDecl(getStdBadAlloc());
+ if (Previous.empty() && StdBadAlloc)
+ Previous.addDecl(getStdBadAlloc());
+ } else if (Name->isStr("align_val_t")) {
+ isStdAlignValT = true;
+ if (Previous.empty() && StdAlignValT)
+ Previous.addDecl(getStdAlignValT());
}
}
@@ -12843,11 +13269,9 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// (non-redeclaration) lookup.
if ((TUK == TUK_Reference || TUK == TUK_Friend) &&
!Previous.isForRedeclaration()) {
- unsigned Kind = 0;
- if (isa<TypedefDecl>(PrevDecl)) Kind = 1;
- else if (isa<TypeAliasDecl>(PrevDecl)) Kind = 2;
- else if (isa<ClassTemplateDecl>(PrevDecl)) Kind = 3;
- Diag(NameLoc, diag::err_tag_reference_non_tag) << Kind;
+ NonTagKind NTK = getNonTagTypeDeclKind(PrevDecl, Kind);
+ Diag(NameLoc, diag::err_tag_reference_non_tag) << PrevDecl << NTK
+ << Kind;
Diag(PrevDecl->getLocation(), diag::note_declared_at);
Invalid = true;
@@ -12858,11 +13282,8 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// Diagnose implicit declarations introduced by elaborated types.
} else if (TUK == TUK_Reference || TUK == TUK_Friend) {
- unsigned Kind = 0;
- if (isa<TypedefDecl>(PrevDecl)) Kind = 1;
- else if (isa<TypeAliasDecl>(PrevDecl)) Kind = 2;
- else if (isa<ClassTemplateDecl>(PrevDecl)) Kind = 3;
- Diag(NameLoc, diag::err_tag_reference_conflict) << Kind;
+ NonTagKind NTK = getNonTagTypeDeclKind(PrevDecl, Kind);
+ Diag(NameLoc, diag::err_tag_reference_conflict) << NTK;
Diag(PrevDecl->getLocation(), diag::note_previous_decl) << PrevDecl;
Invalid = true;
@@ -12915,6 +13336,10 @@ CreateNewDecl:
New = EnumDecl::Create(Context, SearchDC, KWLoc, Loc, Name,
cast_or_null<EnumDecl>(PrevDecl), ScopedEnum,
ScopedEnumUsesClassTag, !EnumUnderlying.isNull());
+
+ if (isStdAlignValT && (!StdAlignValT || getStdAlignValT()->isImplicit()))
+ StdAlignValT = cast<EnumDecl>(New);
+
// If this is an undefined enum, warn.
if (TUK != TUK_Definition && !Invalid) {
TagDecl *Def;
@@ -13047,7 +13472,6 @@ CreateNewDecl:
} else if (!PrevDecl) {
Diag(Loc, diag::warn_decl_in_param_list) << Context.getTagDeclType(New);
}
- DeclsInPrototypeScope.push_back(New);
}
if (Invalid)
@@ -13112,7 +13536,14 @@ CreateNewDecl:
OwnedDecl = true;
// In C++, don't return an invalid declaration. We can't recover well from
// the cases where we make the type anonymous.
- return (Invalid && getLangOpts().CPlusPlus) ? nullptr : New;
+ if (Invalid && getLangOpts().CPlusPlus) {
+ if (New->isBeingDefined())
+ if (auto RD = dyn_cast<RecordDecl>(New))
+ RD->completeDefinition();
+ return nullptr;
+ } else {
+ return New;
+ }
}
void Sema::ActOnTagStartDefinition(Scope *S, Decl *TagD) {
@@ -13347,6 +13778,13 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record,
Declarator &D, Expr *BitWidth,
InClassInitStyle InitStyle,
AccessSpecifier AS) {
+ if (D.isDecompositionDeclarator()) {
+ const DecompositionDeclarator &Decomp = D.getDecompositionDeclarator();
+ Diag(Decomp.getLSquareLoc(), diag::err_decomp_decl_context)
+ << Decomp.getSourceRange();
+ return nullptr;
+ }
+
IdentifierInfo *II = D.getIdentifier();
SourceLocation Loc = DeclStart;
if (II) Loc = D.getIdentifierLoc();
@@ -14140,6 +14578,14 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
if (!Completed)
Record->completeDefinition();
+ // We may have deferred checking for a deleted destructor. Check now.
+ if (CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(Record)) {
+ auto *Dtor = CXXRecord->getDestructor();
+ if (Dtor && Dtor->isImplicit() &&
+ ShouldDeleteSpecialMember(Dtor, CXXDestructor))
+ SetDeclDeleted(Dtor, CXXRecord->getLocation());
+ }
+
if (Record->hasAttrs()) {
CheckAlignasUnderalignment(Record);
@@ -15054,15 +15500,97 @@ static void checkModuleImportContext(Sema &S, Module *M,
} else if (!M->IsExternC && ExternCLoc.isValid()) {
S.Diag(ImportLoc, diag::ext_module_import_in_extern_c)
<< M->getFullModuleName();
- S.Diag(ExternCLoc, diag::note_module_import_in_extern_c);
+ S.Diag(ExternCLoc, diag::note_extern_c_begins_here);
+ }
+}
+
+Sema::DeclGroupPtrTy Sema::ActOnModuleDecl(SourceLocation ModuleLoc,
+ ModuleDeclKind MDK,
+ ModuleIdPath Path) {
+ // 'module implementation' requires that we are not compiling a module of any
+ // kind. 'module' and 'module partition' require that we are compiling a
+ // module inteface (not a module map).
+ auto CMK = getLangOpts().getCompilingModule();
+ if (MDK == ModuleDeclKind::Implementation
+ ? CMK != LangOptions::CMK_None
+ : CMK != LangOptions::CMK_ModuleInterface) {
+ Diag(ModuleLoc, diag::err_module_interface_implementation_mismatch)
+ << (unsigned)MDK;
+ return nullptr;
+ }
+
+ // FIXME: Create a ModuleDecl and return it.
+
+ // FIXME: Most of this work should be done by the preprocessor rather than
+ // here, in case we look ahead across something where the current
+ // module matters (eg a #include).
+
+ // The dots in a module name in the Modules TS are a lie. Unlike Clang's
+ // hierarchical module map modules, the dots here are just another character
+ // that can appear in a module name. Flatten down to the actual module name.
+ std::string ModuleName;
+ for (auto &Piece : Path) {
+ if (!ModuleName.empty())
+ ModuleName += ".";
+ ModuleName += Piece.first->getName();
+ }
+
+ // If a module name was explicitly specified on the command line, it must be
+ // correct.
+ if (!getLangOpts().CurrentModule.empty() &&
+ getLangOpts().CurrentModule != ModuleName) {
+ Diag(Path.front().second, diag::err_current_module_name_mismatch)
+ << SourceRange(Path.front().second, Path.back().second)
+ << getLangOpts().CurrentModule;
+ return nullptr;
+ }
+ const_cast<LangOptions&>(getLangOpts()).CurrentModule = ModuleName;
+
+ auto &Map = PP.getHeaderSearchInfo().getModuleMap();
+
+ switch (MDK) {
+ case ModuleDeclKind::Module: {
+ // FIXME: Check we're not in a submodule.
+
+ // We can't have imported a definition of this module or parsed a module
+ // map defining it already.
+ if (auto *M = Map.findModule(ModuleName)) {
+ Diag(Path[0].second, diag::err_module_redefinition) << ModuleName;
+ if (M->DefinitionLoc.isValid())
+ Diag(M->DefinitionLoc, diag::note_prev_module_definition);
+ else if (const auto *FE = M->getASTFile())
+ Diag(M->DefinitionLoc, diag::note_prev_module_definition_from_ast_file)
+ << FE->getName();
+ return nullptr;
+ }
+
+ // Create a Module for the module that we're defining.
+ Module *Mod = Map.createModuleForInterfaceUnit(ModuleLoc, ModuleName);
+ assert(Mod && "module creation should not fail");
+
+ // Enter the semantic scope of the module.
+ ActOnModuleBegin(ModuleLoc, Mod);
+ return nullptr;
+ }
+
+ case ModuleDeclKind::Partition:
+ // FIXME: Check we are in a submodule of the named module.
+ return nullptr;
+
+ case ModuleDeclKind::Implementation:
+ std::pair<IdentifierInfo *, SourceLocation> ModuleNameLoc(
+ PP.getIdentifierInfo(ModuleName), Path[0].second);
+
+ DeclResult Import = ActOnModuleImport(ModuleLoc, ModuleLoc, ModuleNameLoc);
+ if (Import.isInvalid())
+ return nullptr;
+ return ConvertDeclToDeclGroup(Import.get());
}
-}
-void Sema::diagnoseMisplacedModuleImport(Module *M, SourceLocation ImportLoc) {
- return checkModuleImportContext(*this, M, ImportLoc, CurContext);
+ llvm_unreachable("unexpected module decl kind");
}
-DeclResult Sema::ActOnModuleImport(SourceLocation AtLoc,
+DeclResult Sema::ActOnModuleImport(SourceLocation StartLoc,
SourceLocation ImportLoc,
ModuleIdPath Path) {
Module *Mod =
@@ -15078,8 +15606,11 @@ DeclResult Sema::ActOnModuleImport(SourceLocation AtLoc,
// FIXME: we should support importing a submodule within a different submodule
// of the same top-level module. Until we do, make it an error rather than
// silently ignoring the import.
- if (Mod->getTopLevelModuleName() == getLangOpts().CurrentModule)
- Diag(ImportLoc, getLangOpts().CompilingModule
+ // Import-from-implementation is valid in the Modules TS. FIXME: Should we
+ // warn on a redundant import of the current module?
+ if (Mod->getTopLevelModuleName() == getLangOpts().CurrentModule &&
+ (getLangOpts().isCompilingModule() || !getLangOpts().ModulesTS))
+ Diag(ImportLoc, getLangOpts().isCompilingModule()
? diag::err_module_self_import
: diag::err_module_import_in_implementation)
<< Mod->getFullModuleName() << getLangOpts().CurrentModule;
@@ -15096,17 +15627,21 @@ DeclResult Sema::ActOnModuleImport(SourceLocation AtLoc,
IdentifierLocs.push_back(Path[I].second);
}
- ImportDecl *Import = ImportDecl::Create(Context,
- Context.getTranslationUnitDecl(),
- AtLoc.isValid()? AtLoc : ImportLoc,
+ TranslationUnitDecl *TU = getASTContext().getTranslationUnitDecl();
+ ImportDecl *Import = ImportDecl::Create(Context, TU, StartLoc,
Mod, IdentifierLocs);
- Context.getTranslationUnitDecl()->addDecl(Import);
+ if (!ModuleScopes.empty())
+ Context.addModuleInitializer(ModuleScopes.back().Module, Import);
+ TU->addDecl(Import);
return Import;
}
void Sema::ActOnModuleInclude(SourceLocation DirectiveLoc, Module *Mod) {
checkModuleImportContext(*this, Mod, DirectiveLoc, CurContext, true);
+ BuildModuleInclude(DirectiveLoc, Mod);
+}
+void Sema::BuildModuleInclude(SourceLocation DirectiveLoc, Module *Mod) {
// Determine whether we're in the #include buffer for a module. The #includes
// in that buffer do not qualify as module imports; they're just an
// implementation detail of us building the module.
@@ -15116,13 +15651,7 @@ void Sema::ActOnModuleInclude(SourceLocation DirectiveLoc, Module *Mod) {
TUKind == TU_Module &&
getSourceManager().isWrittenInMainFile(DirectiveLoc);
- // Similarly, if we're in the implementation of a module, don't
- // synthesize an illegal module import. FIXME: Why not?
- bool ShouldAddImport =
- !IsInModuleIncludes &&
- (getLangOpts().CompilingModule ||
- getLangOpts().CurrentModule.empty() ||
- getLangOpts().CurrentModule != Mod->getTopLevelModuleName());
+ bool ShouldAddImport = !IsInModuleIncludes;
// If this module import was due to an inclusion directive, create an
// implicit import declaration to capture it in the AST.
@@ -15131,6 +15660,8 @@ void Sema::ActOnModuleInclude(SourceLocation DirectiveLoc, Module *Mod) {
ImportDecl *ImportD = ImportDecl::CreateImplicit(getASTContext(), TU,
DirectiveLoc, Mod,
DirectiveLoc);
+ if (!ModuleScopes.empty())
+ Context.addModuleInitializer(ModuleScopes.back().Module, ImportD);
TU->addDecl(ImportD);
Consumer.HandleImplicitImportDecl(ImportD);
}
@@ -15140,24 +15671,35 @@ void Sema::ActOnModuleInclude(SourceLocation DirectiveLoc, Module *Mod) {
}
void Sema::ActOnModuleBegin(SourceLocation DirectiveLoc, Module *Mod) {
- checkModuleImportContext(*this, Mod, DirectiveLoc, CurContext);
+ checkModuleImportContext(*this, Mod, DirectiveLoc, CurContext, true);
+ ModuleScopes.push_back({});
+ ModuleScopes.back().Module = Mod;
if (getLangOpts().ModulesLocalVisibility)
- VisibleModulesStack.push_back(std::move(VisibleModules));
+ ModuleScopes.back().OuterVisibleModules = std::move(VisibleModules);
+
VisibleModules.setVisible(Mod, DirectiveLoc);
}
-void Sema::ActOnModuleEnd(SourceLocation DirectiveLoc, Module *Mod) {
- checkModuleImportContext(*this, Mod, DirectiveLoc, CurContext);
-
+void Sema::ActOnModuleEnd(SourceLocation EofLoc, Module *Mod) {
if (getLangOpts().ModulesLocalVisibility) {
- VisibleModules = std::move(VisibleModulesStack.back());
- VisibleModulesStack.pop_back();
- VisibleModules.setVisible(Mod, DirectiveLoc);
+ VisibleModules = std::move(ModuleScopes.back().OuterVisibleModules);
// Leaving a module hides namespace names, so our visible namespace cache
// is now out of date.
VisibleNamespaceCache.clear();
}
+
+ assert(!ModuleScopes.empty() && ModuleScopes.back().Module == Mod &&
+ "left the wrong module scope");
+ ModuleScopes.pop_back();
+
+ // We got to the end of processing a #include of a local module. Create an
+ // ImportDecl as we would for an imported module.
+ FileID File = getSourceManager().getFileID(EofLoc);
+ assert(File != getSourceManager().getMainFileID() &&
+ "end of submodule in main source file");
+ SourceLocation DirectiveLoc = getSourceManager().getIncludeLoc(File);
+ BuildModuleInclude(DirectiveLoc, Mod);
}
void Sema::createImplicitModuleImportForErrorRecovery(SourceLocation Loc,
@@ -15178,6 +15720,39 @@ void Sema::createImplicitModuleImportForErrorRecovery(SourceLocation Loc,
VisibleModules.setVisible(Mod, Loc);
}
+/// We have parsed the start of an export declaration, including the '{'
+/// (if present).
+Decl *Sema::ActOnStartExportDecl(Scope *S, SourceLocation ExportLoc,
+ SourceLocation LBraceLoc) {
+ ExportDecl *D = ExportDecl::Create(Context, CurContext, ExportLoc);
+
+ // C++ Modules TS draft:
+ // An export-declaration [...] shall not contain more than one
+ // export keyword.
+ //
+ // The intent here is that an export-declaration cannot appear within another
+ // export-declaration.
+ if (D->isExported())
+ Diag(ExportLoc, diag::err_export_within_export);
+
+ CurContext->addDecl(D);
+ PushDeclContext(S, D);
+ return D;
+}
+
+/// Complete the definition of an export declaration.
+Decl *Sema::ActOnFinishExportDecl(Scope *S, Decl *D, SourceLocation RBraceLoc) {
+ auto *ED = cast<ExportDecl>(D);
+ if (RBraceLoc.isValid())
+ ED->setRBraceLoc(RBraceLoc);
+
+ // FIXME: Diagnose export of internal-linkage declaration (including
+ // anonymous namespace).
+
+ PopDeclContext();
+ return D;
+}
+
void Sema::ActOnPragmaRedefineExtname(IdentifierInfo* Name,
IdentifierInfo* AliasName,
SourceLocation PragmaLoc,
@@ -15239,29 +15814,3 @@ void Sema::ActOnPragmaWeakAlias(IdentifierInfo* Name,
Decl *Sema::getObjCDeclContext() const {
return (dyn_cast_or_null<ObjCContainerDecl>(CurContext));
}
-
-AvailabilityResult Sema::getCurContextAvailability() const {
- const Decl *D = cast_or_null<Decl>(getCurObjCLexicalContext());
- if (!D)
- return AR_Available;
-
- // If we are within an Objective-C method, we should consult
- // both the availability of the method as well as the
- // enclosing class. If the class is (say) deprecated,
- // the entire method is considered deprecated from the
- // purpose of checking if the current context is deprecated.
- if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
- AvailabilityResult R = MD->getAvailability();
- if (R != AR_Available)
- return R;
- D = MD->getClassInterface();
- }
- // If we are within an Objective-c @implementation, it
- // gets the same availability context as the @interface.
- else if (const ObjCImplementationDecl *ID =
- dyn_cast<ObjCImplementationDecl>(D)) {
- D = ID->getClassInterface();
- }
- // Recover from user error.
- return D ? D->getAvailability() : AR_Available;
-}
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index a5780a7d71fb..f9b6a91a300f 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -11,9 +11,9 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Sema/SemaInternal.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
@@ -21,7 +21,7 @@
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/Mangle.h"
-#include "clang/AST/ASTMutationListener.h"
+#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
@@ -31,6 +31,7 @@
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Scope.h"
+#include "clang/Sema/SemaInternal.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/MathExtras.h"
@@ -245,6 +246,28 @@ static bool checkUInt32Argument(Sema &S, const AttributeList &Attr,
return true;
}
+/// \brief 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.
+static bool checkPositiveIntArgument(Sema &S, const AttributeList &Attr,
+ const Expr *Expr, int &Val,
+ unsigned Idx = UINT_MAX) {
+ uint32_t UVal;
+ if (!checkUInt32Argument(S, Attr, Expr, UVal, Idx))
+ return false;
+
+ if (UVal > (uint32_t)std::numeric_limits<int>::max()) {
+ llvm::APSInt I(32); // for toString
+ I = UVal;
+ S.Diag(Expr->getExprLoc(), diag::err_ice_too_large)
+ << I.toString(10, false) << 32 << /* Unsigned */ 0;
+ return false;
+ }
+
+ Val = UVal;
+ return true;
+}
+
/// \brief Diagnose mutually exclusive attributes when present on a given
/// declaration. Returns true if diagnosed.
template <typename AttrTy>
@@ -729,6 +752,69 @@ static void handleAssertExclusiveLockAttr(Sema &S, Decl *D,
Attr.getAttributeSpellingListIndex()));
}
+/// \brief Checks to be sure that the given parameter number is inbounds, and is
+/// an some 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) {
+ assert(Attr.isArgExpr(AttrArgNo) && "Expected expression argument");
+ uint64_t Idx;
+ if (!checkFunctionOrMethodParameterIndex(S, FD, Attr, FuncParamNo,
+ Attr.getArgAsExpr(AttrArgNo), Idx))
+ return false;
+
+ const ParmVarDecl *Param = FD->getParamDecl(Idx);
+ if (!Param->getType()->isIntegerType() && !Param->getType()->isCharType()) {
+ SourceLocation SrcLoc = Attr.getArgAsExpr(AttrArgNo)->getLocStart();
+ S.Diag(SrcLoc, diag::err_attribute_integers_only)
+ << Attr.getName() << Param->getSourceRange();
+ return false;
+ }
+ return true;
+}
+
+static void handleAllocSizeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+ if (!checkAttributeAtLeastNumArgs(S, Attr, 1) ||
+ !checkAttributeAtMostNumArgs(S, Attr, 2))
+ return;
+
+ const auto *FD = cast<FunctionDecl>(D);
+ if (!FD->getReturnType()->isPointerType()) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_return_pointers_only)
+ << Attr.getName();
+ return;
+ }
+
+ const Expr *SizeExpr = Attr.getArgAsExpr(0);
+ int SizeArgNo;
+ // Paramater indices are 1-indexed, hence Index=1
+ if (!checkPositiveIntArgument(S, Attr, SizeExpr, SizeArgNo, /*Index=*/1))
+ return;
+
+ if (!checkParamIsIntegerType(S, FD, Attr, SizeArgNo, /*AttrArgNo=*/0))
+ return;
+
+ // 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);
+ // Paramater indices are 1-based, hence Index=2
+ if (!checkPositiveIntArgument(S, Attr, NumberExpr, NumberArgNo,
+ /*Index=*/2))
+ return;
+
+ if (!checkParamIsIntegerType(S, FD, Attr, NumberArgNo, /*AttrArgNo=*/1))
+ return;
+ }
+
+ D->addAttr(::new (S.Context) AllocSizeAttr(
+ Attr.getRange(), S.Context, SizeArgNo, NumberArgNo,
+ Attr.getAttributeSpellingListIndex()));
+}
static bool checkTryLockFunAttrCommon(Sema &S, Decl *D,
const AttributeList &Attr,
@@ -824,8 +910,8 @@ static void handleEnableIfAttr(Sema &S, Decl *D, const AttributeList &Attr) {
!Expr::isPotentialConstantExprUnevaluated(Cond, cast<FunctionDecl>(D),
Diags)) {
S.Diag(Attr.getLoc(), diag::err_enable_if_never_constant_expr);
- for (int I = 0, N = Diags.size(); I != N; ++I)
- S.Diag(Diags[I].first, Diags[I].second);
+ for (const PartialDiagnosticAt &PDiag : Diags)
+ S.Diag(PDiag.first, PDiag.second);
return;
}
@@ -2803,20 +2889,21 @@ enum FormatAttrKind {
/// types.
static FormatAttrKind getFormatAttrKind(StringRef Format) {
return llvm::StringSwitch<FormatAttrKind>(Format)
- // Check for formats that get handled specially.
- .Case("NSString", NSStringFormat)
- .Case("CFString", CFStringFormat)
- .Case("strftime", StrftimeFormat)
+ // Check for formats that get handled specially.
+ .Case("NSString", NSStringFormat)
+ .Case("CFString", CFStringFormat)
+ .Case("strftime", StrftimeFormat)
- // Otherwise, check for supported formats.
- .Cases("scanf", "printf", "printf0", "strfmon", SupportedFormat)
- .Cases("cmn_err", "vcmn_err", "zcmn_err", SupportedFormat)
- .Case("kprintf", SupportedFormat) // OpenBSD.
- .Case("freebsd_kprintf", SupportedFormat) // FreeBSD.
- .Case("os_trace", SupportedFormat)
+ // Otherwise, check for supported formats.
+ .Cases("scanf", "printf", "printf0", "strfmon", SupportedFormat)
+ .Cases("cmn_err", "vcmn_err", "zcmn_err", SupportedFormat)
+ .Case("kprintf", SupportedFormat) // OpenBSD.
+ .Case("freebsd_kprintf", SupportedFormat) // FreeBSD.
+ .Case("os_trace", SupportedFormat)
+ .Case("os_log", SupportedFormat)
- .Cases("gcc_diag", "gcc_cdiag", "gcc_cxxdiag", "gcc_tdiag", IgnoredFormat)
- .Default(InvalidFormat);
+ .Cases("gcc_diag", "gcc_cdiag", "gcc_cxxdiag", "gcc_tdiag", IgnoredFormat)
+ .Default(InvalidFormat);
}
/// Handle __attribute__((init_priority(priority))) attributes based on
@@ -3043,10 +3130,14 @@ static void handleTransparentUnionAttr(Sema &S, Decl *D,
return;
}
+ if (FirstType->isIncompleteType())
+ return;
uint64_t FirstSize = S.Context.getTypeSize(FirstType);
uint64_t FirstAlign = S.Context.getTypeAlign(FirstType);
for (; Field != FieldEnd; ++Field) {
QualType FieldType = Field->getType();
+ if (FieldType->isIncompleteType())
+ return;
// FIXME: this isn't fully correct; we also need to test whether the
// members of the union would all have the same calling convention as the
// first member of the union. Checking just the size and alignment isn't
@@ -3695,6 +3786,38 @@ static void handleOptimizeNoneAttr(Sema &S, Decl *D,
D->addAttr(Optnone);
}
+static void handleConstantAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+ if (checkAttrMutualExclusion<CUDASharedAttr>(S, D, Attr.getRange(),
+ Attr.getName()))
+ return;
+ auto *VD = cast<VarDecl>(D);
+ if (!VD->hasGlobalStorage()) {
+ S.Diag(Attr.getLoc(), diag::err_cuda_nonglobal_constant);
+ return;
+ }
+ D->addAttr(::new (S.Context) CUDAConstantAttr(
+ Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+}
+
+static void handleSharedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+ if (checkAttrMutualExclusion<CUDAConstantAttr>(S, D, Attr.getRange(),
+ Attr.getName()))
+ return;
+ 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;
+ return;
+ }
+ if (S.getLangOpts().CUDA && VD->hasLocalStorage() &&
+ S.CUDADiagIfHostCode(Attr.getLoc(), diag::err_cuda_host_shared)
+ << S.CurrentCUDATarget())
+ return;
+ D->addAttr(::new (S.Context) CUDASharedAttr(
+ Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+}
+
static void handleGlobalAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (checkAttrMutualExclusion<CUDADeviceAttr>(S, D, Attr.getRange(),
Attr.getName()) ||
@@ -3801,6 +3924,10 @@ static void handleCallConvAttr(Sema &S, Decl *D, const AttributeList &Attr) {
SysVABIAttr(Attr.getRange(), S.Context,
Attr.getAttributeSpellingListIndex()));
return;
+ case AttributeList::AT_RegCall:
+ D->addAttr(::new (S.Context) RegCallAttr(
+ Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex()));
+ return;
case AttributeList::AT_Pcs: {
PcsAttr::PCSType PCS;
switch (CC) {
@@ -3862,6 +3989,7 @@ bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC,
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:
CC = Context.getTargetInfo().getTriple().isOSWindows() ? CC_C :
CC_X86_64Win64;
@@ -4603,6 +4731,19 @@ static void handleObjCPreciseLifetimeAttr(Sema &S, Decl *D,
// Microsoft specific attribute handlers.
//===----------------------------------------------------------------------===//
+UuidAttr *Sema::mergeUuidAttr(Decl *D, SourceRange Range,
+ unsigned AttrSpellingListIndex, StringRef Uuid) {
+ if (const auto *UA = D->getAttr<UuidAttr>()) {
+ if (UA->getGuid().equals_lower(Uuid))
+ return nullptr;
+ Diag(UA->getLocation(), diag::err_mismatched_uuid);
+ Diag(Range.getBegin(), diag::note_previous_uuid);
+ D->dropAttr<UuidAttr>();
+ }
+
+ return ::new (Context) UuidAttr(Range, Context, Uuid, AttrSpellingListIndex);
+}
+
static void handleUuidAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (!S.LangOpts.CPlusPlus) {
S.Diag(Attr.getLoc(), diag::err_attribute_not_supported_in_lang)
@@ -4610,12 +4751,6 @@ static void handleUuidAttr(Sema &S, Decl *D, const AttributeList &Attr) {
return;
}
- if (!isa<CXXRecordDecl>(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << ExpectedClass;
- return;
- }
-
StringRef StrRef;
SourceLocation LiteralLoc;
if (!S.checkStringLiteralArgumentAttr(Attr, 0, StrRef, &LiteralLoc))
@@ -4644,8 +4779,10 @@ static void handleUuidAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
}
- D->addAttr(::new (S.Context) UuidAttr(Attr.getRange(), S.Context, StrRef,
- Attr.getAttributeSpellingListIndex()));
+ UuidAttr *UA = S.mergeUuidAttr(D, Attr.getRange(),
+ Attr.getAttributeSpellingListIndex(), StrRef);
+ if (UA)
+ D->addAttr(UA);
}
static void handleMSInheritanceAttr(Sema &S, Decl *D, const AttributeList &Attr) {
@@ -4925,29 +5062,85 @@ static void handleInterruptAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
}
-static void handleAMDGPUNumVGPRAttr(Sema &S, Decl *D,
+static void handleAMDGPUFlatWorkGroupSizeAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ uint32_t Min = 0;
+ Expr *MinExpr = Attr.getArgAsExpr(0);
+ if (!checkUInt32Argument(S, Attr, MinExpr, Min))
+ return;
+
+ uint32_t Max = 0;
+ Expr *MaxExpr = Attr.getArgAsExpr(1);
+ if (!checkUInt32Argument(S, Attr, MaxExpr, Max))
+ return;
+
+ if (Min == 0 && Max != 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_invalid)
+ << Attr.getName() << 0;
+ return;
+ }
+ if (Min > Max) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_invalid)
+ << Attr.getName() << 1;
+ return;
+ }
+
+ D->addAttr(::new (S.Context)
+ AMDGPUFlatWorkGroupSizeAttr(Attr.getLoc(), S.Context, Min, Max,
+ Attr.getAttributeSpellingListIndex()));
+}
+
+static void handleAMDGPUWavesPerEUAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ uint32_t Min = 0;
+ Expr *MinExpr = Attr.getArgAsExpr(0);
+ if (!checkUInt32Argument(S, Attr, MinExpr, Min))
+ return;
+
+ uint32_t Max = 0;
+ if (Attr.getNumArgs() == 2) {
+ Expr *MaxExpr = Attr.getArgAsExpr(1);
+ if (!checkUInt32Argument(S, Attr, MaxExpr, Max))
+ return;
+ }
+
+ if (Min == 0 && Max != 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_invalid)
+ << Attr.getName() << 0;
+ return;
+ }
+ if (Max != 0 && Min > Max) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_invalid)
+ << Attr.getName() << 1;
+ return;
+ }
+
+ D->addAttr(::new (S.Context)
+ AMDGPUWavesPerEUAttr(Attr.getLoc(), S.Context, Min, Max,
+ Attr.getAttributeSpellingListIndex()));
+}
+
+static void handleAMDGPUNumSGPRAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
- uint32_t NumRegs;
- Expr *NumRegsExpr = static_cast<Expr *>(Attr.getArgAsExpr(0));
- if (!checkUInt32Argument(S, Attr, NumRegsExpr, NumRegs))
+ uint32_t NumSGPR = 0;
+ Expr *NumSGPRExpr = Attr.getArgAsExpr(0);
+ if (!checkUInt32Argument(S, Attr, NumSGPRExpr, NumSGPR))
return;
D->addAttr(::new (S.Context)
- AMDGPUNumVGPRAttr(Attr.getLoc(), S.Context,
- NumRegs,
+ AMDGPUNumSGPRAttr(Attr.getLoc(), S.Context, NumSGPR,
Attr.getAttributeSpellingListIndex()));
}
-static void handleAMDGPUNumSGPRAttr(Sema &S, Decl *D,
+static void handleAMDGPUNumVGPRAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
- uint32_t NumRegs;
- Expr *NumRegsExpr = static_cast<Expr *>(Attr.getArgAsExpr(0));
- if (!checkUInt32Argument(S, Attr, NumRegsExpr, NumRegs))
+ uint32_t NumVGPR = 0;
+ Expr *NumVGPRExpr = Attr.getArgAsExpr(0);
+ if (!checkUInt32Argument(S, Attr, NumVGPRExpr, NumVGPR))
return;
D->addAttr(::new (S.Context)
- AMDGPUNumSGPRAttr(Attr.getLoc(), S.Context,
- NumRegs,
+ AMDGPUNumVGPRAttr(Attr.getLoc(), S.Context, NumVGPR,
Attr.getAttributeSpellingListIndex()));
}
@@ -5205,9 +5398,15 @@ static void handleDeprecatedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
!(Attr.hasScope() && Attr.getScopeName()->isStr("gnu")))
S.Diag(Attr.getLoc(), diag::ext_cxx14_attr) << Attr.getName();
- D->addAttr(::new (S.Context) DeprecatedAttr(Attr.getRange(), S.Context, Str,
- Replacement,
- Attr.getAttributeSpellingListIndex()));
+ D->addAttr(::new (S.Context)
+ DeprecatedAttr(Attr.getRange(), S.Context, Str, Replacement,
+ Attr.getAttributeSpellingListIndex()));
+}
+
+static bool isGlobalVar(const Decl *D) {
+ if (const auto *S = dyn_cast<VarDecl>(D))
+ return S->hasGlobalStorage();
+ return false;
}
static void handleNoSanitizeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
@@ -5225,7 +5424,9 @@ static void handleNoSanitizeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
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;
Sanitizers.push_back(SanitizerName);
}
@@ -5238,12 +5439,14 @@ static void handleNoSanitizeSpecificAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
StringRef AttrName = Attr.getName()->getName();
normalizeName(AttrName);
- StringRef SanitizerName =
- llvm::StringSwitch<StringRef>(AttrName)
- .Case("no_address_safety_analysis", "address")
- .Case("no_sanitize_address", "address")
- .Case("no_sanitize_thread", "thread")
- .Case("no_sanitize_memory", "memory");
+ StringRef SanitizerName = llvm::StringSwitch<StringRef>(AttrName)
+ .Case("no_address_safety_analysis", "address")
+ .Case("no_sanitize_address", "address")
+ .Case("no_sanitize_thread", "thread")
+ .Case("no_sanitize_memory", "memory");
+ if (isGlobalVar(D) && SanitizerName != "address")
+ S.Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)
+ << Attr.getName() << ExpectedFunction;
D->addAttr(::new (S.Context)
NoSanitizeAttr(Attr.getRange(), S.Context, &SanitizerName, 1,
Attr.getAttributeSpellingListIndex()));
@@ -5401,12 +5604,18 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case AttributeList::AT_NoMips16:
handleSimpleAttribute<NoMips16Attr>(S, D, Attr);
break;
- case AttributeList::AT_AMDGPUNumVGPR:
- handleAMDGPUNumVGPRAttr(S, D, Attr);
+ case AttributeList::AT_AMDGPUFlatWorkGroupSize:
+ handleAMDGPUFlatWorkGroupSizeAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_AMDGPUWavesPerEU:
+ handleAMDGPUWavesPerEUAttr(S, D, Attr);
break;
case AttributeList::AT_AMDGPUNumSGPR:
handleAMDGPUNumSGPRAttr(S, D, Attr);
break;
+ case AttributeList::AT_AMDGPUNumVGPR:
+ handleAMDGPUNumVGPRAttr(S, D, Attr);
+ break;
case AttributeList::AT_IBAction:
handleSimpleAttribute<IBActionAttr>(S, D, Attr);
break;
@@ -5428,6 +5637,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case AttributeList::AT_AlignValue:
handleAlignValueAttr(S, D, Attr);
break;
+ case AttributeList::AT_AllocSize:
+ handleAllocSizeAttr(S, D, Attr);
+ break;
case AttributeList::AT_AlwaysInline:
handleAlwaysInlineAttr(S, D, Attr);
break;
@@ -5450,8 +5662,7 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
handleCommonAttr(S, D, Attr);
break;
case AttributeList::AT_CUDAConstant:
- handleSimpleAttributeWithExclusions<CUDAConstantAttr, CUDASharedAttr>(S, D,
- Attr);
+ handleConstantAttr(S, D, Attr);
break;
case AttributeList::AT_PassObjectSize:
handlePassObjectSizeAttr(S, D, Attr);
@@ -5561,8 +5772,7 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
handleSimpleAttribute<NoThrowAttr>(S, D, Attr);
break;
case AttributeList::AT_CUDAShared:
- handleSimpleAttributeWithExclusions<CUDASharedAttr, CUDAConstantAttr>(S, D,
- Attr);
+ handleSharedAttr(S, D, Attr);
break;
case AttributeList::AT_VecReturn:
handleVecReturnAttr(S, D, Attr);
@@ -5629,6 +5839,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case AttributeList::AT_VecTypeHint:
handleVecTypeHint(S, D, Attr);
break;
+ case AttributeList::AT_RequireConstantInit:
+ handleSimpleAttribute<RequireConstantInitAttr>(S, D, Attr);
+ break;
case AttributeList::AT_InitPriority:
handleInitPriorityAttr(S, D, Attr);
break;
@@ -5650,6 +5863,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case AttributeList::AT_ObjCRootClass:
handleSimpleAttribute<ObjCRootClassAttr>(S, D, Attr);
break;
+ case AttributeList::AT_ObjCSubclassingRestricted:
+ handleSimpleAttribute<ObjCSubclassingRestrictedAttr>(S, D, Attr);
+ break;
case AttributeList::AT_ObjCExplicitProtocolImpl:
handleObjCSuppresProtocolAttr(S, D, Attr);
break;
@@ -5728,6 +5944,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case AttributeList::AT_NoDuplicate:
handleSimpleAttribute<NoDuplicateAttr>(S, D, Attr);
break;
+ case AttributeList::AT_Convergent:
+ handleSimpleAttribute<ConvergentAttr>(S, D, Attr);
+ break;
case AttributeList::AT_NoInline:
handleSimpleAttribute<NoInlineAttr>(S, D, Attr);
break;
@@ -5739,6 +5958,7 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
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:
@@ -5955,7 +6175,11 @@ void Sema::ProcessDeclAttributeList(Scope *S, Decl *D,
} else if (Attr *A = D->getAttr<VecTypeHintAttr>()) {
Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A;
D->setInvalidDecl();
- } else if (Attr *A = D->getAttr<AMDGPUNumVGPRAttr>()) {
+ } 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();
@@ -5963,6 +6187,10 @@ void Sema::ProcessDeclAttributeList(Scope *S, Decl *D,
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();
}
}
}
@@ -6194,30 +6422,6 @@ static void handleDelayedForbiddenType(Sema &S, DelayedDiagnostic &diag,
diag.Triggered = true;
}
-static bool isDeclDeprecated(Decl *D) {
- do {
- if (D->isDeprecated())
- return true;
- // A category implicitly has the availability of the interface.
- if (const ObjCCategoryDecl *CatD = dyn_cast<ObjCCategoryDecl>(D))
- if (const ObjCInterfaceDecl *Interface = CatD->getClassInterface())
- return Interface->isDeprecated();
- } while ((D = cast_or_null<Decl>(D->getDeclContext())));
- return false;
-}
-
-static bool isDeclUnavailable(Decl *D) {
- do {
- if (D->isUnavailable())
- return true;
- // A category implicitly has the availability of the interface.
- if (const ObjCCategoryDecl *CatD = dyn_cast<ObjCCategoryDecl>(D))
- if (const ObjCInterfaceDecl *Interface = CatD->getClassInterface())
- return Interface->isUnavailable();
- } while ((D = cast_or_null<Decl>(D->getDeclContext())));
- return false;
-}
-
static const AvailabilityAttr *getAttrForPlatform(ASTContext &Context,
const Decl *D) {
// Check each AvailabilityAttr to find the one for this platform.
@@ -6246,7 +6450,72 @@ static const AvailabilityAttr *getAttrForPlatform(ASTContext &Context,
return nullptr;
}
-static void DoEmitAvailabilityWarning(Sema &S, Sema::AvailabilityDiagnostic K,
+/// \brief 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,
+ VersionTuple DeclVersion,
+ Decl *Ctx) {
+ assert(K != AR_Available && "Expected an unavailable declaration here!");
+
+ // Checks if we should emit the availability diagnostic in the context of C.
+ auto CheckContext = [&](const Decl *C) {
+ if (K == AR_NotYetIntroduced) {
+ if (const AvailabilityAttr *AA = getAttrForPlatform(S.Context, C))
+ if (AA->getIntroduced() >= DeclVersion)
+ return true;
+ } else if (K == AR_Deprecated)
+ if (C->isDeprecated())
+ return true;
+
+ if (C->isUnavailable())
+ return true;
+ 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)) {
+ 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))
+ if (const ObjCInterfaceDecl *Interface = CatD->getClassInterface())
+ if (CheckContext(Interface))
+ return false;
+ } while ((Ctx = cast_or_null<Decl>(Ctx->getDeclContext())));
+
+ return true;
+}
+
+static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
Decl *Ctx, const NamedDecl *D,
StringRef Message, SourceLocation Loc,
const ObjCInterfaceDecl *UnknownObjCClass,
@@ -6262,11 +6531,15 @@ static void DoEmitAvailabilityWarning(Sema &S, Sema::AvailabilityDiagnostic K,
// Matches diag::note_availability_specified_here.
unsigned available_here_select_kind;
- // Don't warn if our current context is deprecated or unavailable.
+ VersionTuple DeclVersion;
+ if (const AvailabilityAttr *AA = getAttrForPlatform(S.Context, D))
+ DeclVersion = AA->getIntroduced();
+
+ if (!ShouldDiagnoseAvailabilityInContext(S, K, DeclVersion, Ctx))
+ return;
+
switch (K) {
- case Sema::AD_Deprecation:
- if (isDeclDeprecated(Ctx) || isDeclUnavailable(Ctx))
- return;
+ case AR_Deprecated:
diag = !ObjCPropertyAccess ? diag::warn_deprecated
: diag::warn_property_method_deprecated;
diag_message = diag::warn_deprecated_message;
@@ -6275,9 +6548,7 @@ static void DoEmitAvailabilityWarning(Sema &S, Sema::AvailabilityDiagnostic K,
available_here_select_kind = /* deprecated */ 2;
break;
- case Sema::AD_Unavailable:
- if (isDeclUnavailable(Ctx))
- return;
+ case AR_Unavailable:
diag = !ObjCPropertyAccess ? diag::err_unavailable
: diag::err_property_method_unavailable;
diag_message = diag::err_unavailable_message;
@@ -6329,18 +6600,21 @@ static void DoEmitAvailabilityWarning(Sema &S, Sema::AvailabilityDiagnostic K,
}
break;
- case Sema::AD_Partial:
+ case AR_NotYetIntroduced:
diag = diag::warn_partial_availability;
diag_message = diag::warn_partial_message;
diag_fwdclass_message = diag::warn_partial_fwdclass_message;
property_note_select = /* partial */ 2;
available_here_select_kind = /* partial */ 3;
break;
+
+ case AR_Available:
+ llvm_unreachable("Warning for availability of available declaration?");
}
CharSourceRange UseRange;
StringRef Replacement;
- if (K == Sema::AD_Deprecation) {
+ if (K == AR_Deprecated) {
if (auto attr = D->getAttr<DeprecatedAttr>())
Replacement = attr->getReplacement();
if (auto attr = getAttrForPlatform(S.Context, D))
@@ -6393,21 +6667,20 @@ static void DoEmitAvailabilityWarning(Sema &S, Sema::AvailabilityDiagnostic K,
S.Diag(D->getLocation(), diag_available_here)
<< D << available_here_select_kind;
- if (K == Sema::AD_Partial)
+ if (K == AR_NotYetIntroduced)
S.Diag(Loc, diag::note_partial_availability_silence) << D;
}
static void handleDelayedAvailabilityCheck(Sema &S, DelayedDiagnostic &DD,
Decl *Ctx) {
- assert(DD.Kind == DelayedDiagnostic::Deprecation ||
- DD.Kind == DelayedDiagnostic::Unavailable);
- Sema::AvailabilityDiagnostic AD = DD.Kind == DelayedDiagnostic::Deprecation
- ? Sema::AD_Deprecation
- : Sema::AD_Unavailable;
+ assert(DD.Kind == DelayedDiagnostic::Availability &&
+ "Expected an availability diagnostic here");
+
DD.Triggered = true;
DoEmitAvailabilityWarning(
- S, AD, Ctx, DD.getDeprecationDecl(), DD.getDeprecationMessage(), DD.Loc,
- DD.getUnknownObjCClass(), DD.getObjCProperty(), false);
+ S, DD.getAvailabilityResult(), Ctx, DD.getAvailabilityDecl(),
+ DD.getAvailabilityMessage(), DD.Loc, DD.getUnknownObjCClass(),
+ DD.getObjCProperty(), false);
}
void Sema::PopParsingDeclaration(ParsingDeclState state, Decl *decl) {
@@ -6437,8 +6710,7 @@ void Sema::PopParsingDeclaration(ParsingDeclState state, Decl *decl) {
continue;
switch (diag.Kind) {
- case DelayedDiagnostic::Deprecation:
- case DelayedDiagnostic::Unavailable:
+ case DelayedDiagnostic::Availability:
// Don't bother giving deprecation/unavailable diagnostics if
// the decl is invalid.
if (!decl->isInvalidDecl())
@@ -6466,21 +6738,173 @@ void Sema::redelayDiagnostics(DelayedDiagnosticPool &pool) {
curPool->steal(pool);
}
-void Sema::EmitAvailabilityWarning(AvailabilityDiagnostic AD,
+void Sema::EmitAvailabilityWarning(AvailabilityResult AR,
NamedDecl *D, StringRef Message,
SourceLocation Loc,
const ObjCInterfaceDecl *UnknownObjCClass,
const ObjCPropertyDecl *ObjCProperty,
bool ObjCPropertyAccess) {
// Delay if we're currently parsing a declaration.
- if (DelayedDiagnostics.shouldDelayDiagnostics() && AD != AD_Partial) {
+ if (DelayedDiagnostics.shouldDelayDiagnostics()) {
DelayedDiagnostics.add(DelayedDiagnostic::makeAvailability(
- AD, Loc, D, UnknownObjCClass, ObjCProperty, Message,
+ AR, Loc, D, UnknownObjCClass, ObjCProperty, Message,
ObjCPropertyAccess));
return;
}
Decl *Ctx = cast<Decl>(getCurLexicalContext());
- DoEmitAvailabilityWarning(*this, AD, Ctx, D, Message, Loc, UnknownObjCClass,
+ DoEmitAvailabilityWarning(*this, AR, Ctx, D, Message, Loc, UnknownObjCClass,
ObjCProperty, ObjCPropertyAccess);
}
+
+namespace {
+
+/// \brief 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
+/// form: \c if(@available(...)), we use the version from the condition to visit
+/// the then statement.
+class DiagnoseUnguardedAvailability
+ : public RecursiveASTVisitor<DiagnoseUnguardedAvailability> {
+ typedef RecursiveASTVisitor<DiagnoseUnguardedAvailability> Base;
+
+ Sema &SemaRef;
+ Decl *Ctx;
+
+ /// Stack of potentially nested 'if (@available(...))'s.
+ SmallVector<VersionTuple, 8> AvailabilityStack;
+
+ void DiagnoseDeclAvailability(NamedDecl *D, SourceRange Range);
+
+public:
+ DiagnoseUnguardedAvailability(Sema &SemaRef, Decl *Ctx)
+ : SemaRef(SemaRef), Ctx(Ctx) {
+ AvailabilityStack.push_back(
+ SemaRef.Context.getTargetInfo().getPlatformMinVersion());
+ }
+
+ void IssueDiagnostics(Stmt *S) { TraverseStmt(S); }
+
+ bool TraverseIfStmt(IfStmt *If);
+
+ bool VisitObjCMessageExpr(ObjCMessageExpr *Msg) {
+ if (ObjCMethodDecl *D = Msg->getMethodDecl())
+ DiagnoseDeclAvailability(
+ D, SourceRange(Msg->getSelectorStartLoc(), Msg->getLocEnd()));
+ return true;
+ }
+
+ bool VisitDeclRefExpr(DeclRefExpr *DRE) {
+ DiagnoseDeclAvailability(DRE->getDecl(),
+ SourceRange(DRE->getLocStart(), DRE->getLocEnd()));
+ return true;
+ }
+
+ bool VisitMemberExpr(MemberExpr *ME) {
+ DiagnoseDeclAvailability(ME->getMemberDecl(),
+ SourceRange(ME->getLocStart(), ME->getLocEnd()));
+ return true;
+ }
+
+ bool VisitTypeLoc(TypeLoc Ty);
+};
+
+void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability(
+ NamedDecl *D, SourceRange Range) {
+
+ VersionTuple ContextVersion = AvailabilityStack.back();
+ if (AvailabilityResult Result =
+ SemaRef.ShouldDiagnoseAvailabilityOfDecl(D, nullptr)) {
+ // All other diagnostic kinds have already been handled in
+ // DiagnoseAvailabilityOfDecl.
+ if (Result != AR_NotYetIntroduced)
+ return;
+
+ const AvailabilityAttr *AA = getAttrForPlatform(SemaRef.getASTContext(), D);
+ VersionTuple Introduced = AA->getIntroduced();
+
+ if (ContextVersion >= Introduced)
+ return;
+
+ // If the context of this function is less available than D, we should not
+ // emit a diagnostic.
+ if (!ShouldDiagnoseAvailabilityInContext(SemaRef, Result, Introduced, Ctx))
+ return;
+
+ SemaRef.Diag(Range.getBegin(), diag::warn_unguarded_availability)
+ << Range << D
+ << AvailabilityAttr::getPrettyPlatformName(
+ SemaRef.getASTContext().getTargetInfo().getPlatformName())
+ << Introduced.getAsString();
+
+ SemaRef.Diag(D->getLocation(), diag::note_availability_specified_here)
+ << D << /* partial */ 3;
+
+ // FIXME: Replace this with a fixit diagnostic.
+ SemaRef.Diag(Range.getBegin(), diag::note_unguarded_available_silence)
+ << Range << D;
+ }
+}
+
+bool DiagnoseUnguardedAvailability::VisitTypeLoc(TypeLoc Ty) {
+ const Type *TyPtr = Ty.getTypePtr();
+ SourceRange Range{Ty.getBeginLoc(), Ty.getEndLoc()};
+
+ if (const TagType *TT = dyn_cast<TagType>(TyPtr)) {
+ TagDecl *TD = TT->getDecl();
+ DiagnoseDeclAvailability(TD, Range);
+
+ } else if (const TypedefType *TD = dyn_cast<TypedefType>(TyPtr)) {
+ TypedefNameDecl *D = TD->getDecl();
+ DiagnoseDeclAvailability(D, Range);
+
+ } else if (const auto *ObjCO = dyn_cast<ObjCObjectType>(TyPtr)) {
+ if (NamedDecl *D = ObjCO->getInterface())
+ DiagnoseDeclAvailability(D, Range);
+ }
+
+ return true;
+}
+
+bool DiagnoseUnguardedAvailability::TraverseIfStmt(IfStmt *If) {
+ VersionTuple CondVersion;
+ if (auto *E = dyn_cast<ObjCAvailabilityCheckExpr>(If->getCond())) {
+ CondVersion = E->getVersion();
+
+ // If we're using the '*' case here or if this check is redundant, then we
+ // use the enclosing version to check both branches.
+ if (CondVersion.empty() || CondVersion <= AvailabilityStack.back())
+ return Base::TraverseStmt(If->getThen()) &&
+ Base::TraverseStmt(If->getElse());
+ } else {
+ // This isn't an availability checking 'if', we can just continue.
+ return Base::TraverseIfStmt(If);
+ }
+
+ AvailabilityStack.push_back(CondVersion);
+ bool ShouldContinue = TraverseStmt(If->getThen());
+ AvailabilityStack.pop_back();
+
+ return ShouldContinue && TraverseStmt(If->getElse());
+}
+
+} // end anonymous namespace
+
+void Sema::DiagnoseUnguardedAvailabilityViolations(Decl *D) {
+ Stmt *Body = nullptr;
+
+ if (auto *FD = D->getAsFunction()) {
+ // FIXME: We only examine the pattern decl for availability violations now,
+ // but we should also examine instantiated templates.
+ if (FD->isTemplateInstantiation())
+ return;
+
+ Body = FD->getBody();
+ } else if (auto *MD = dyn_cast<ObjCMethodDecl>(D))
+ Body = MD->getBody();
+
+ assert(Body && "Need a body here!");
+
+ DiagnoseUnguardedAvailability(*this, D).IssueDiagnostics(Body);
+}
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index e161c87f1739..084bd4c45eda 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -11,7 +11,6 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Sema/SemaInternal.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTLambda.h"
@@ -36,9 +35,11 @@
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
+#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Template.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
#include <map>
#include <set>
@@ -394,7 +395,8 @@ void Sema::CheckExtraCXXDefaultArguments(Declarator &D) {
++argIdx) {
ParmVarDecl *Param = cast<ParmVarDecl>(chunk.Fun.Params[argIdx].Param);
if (Param->hasUnparsedDefaultArg()) {
- CachedTokens *Toks = chunk.Fun.Params[argIdx].DefaultArgTokens;
+ std::unique_ptr<CachedTokens> Toks =
+ std::move(chunk.Fun.Params[argIdx].DefaultArgTokens);
SourceRange SR;
if (Toks->size() > 1)
SR = SourceRange((*Toks)[1].getLocation(),
@@ -403,8 +405,6 @@ void Sema::CheckExtraCXXDefaultArguments(Declarator &D) {
SR = UnparsedDefaultArgLocs[Param];
Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc)
<< SR;
- delete Toks;
- chunk.Fun.Params[argIdx].DefaultArgTokens = nullptr;
} else if (Param->getDefaultArg()) {
Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc)
<< Param->getDefaultArg()->getSourceRange();
@@ -658,12 +658,773 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old,
Invalid = true;
}
- if (CheckEquivalentExceptionSpec(Old, New))
- Invalid = true;
-
return Invalid;
}
+NamedDecl *
+Sema::ActOnDecompositionDeclarator(Scope *S, Declarator &D,
+ MultiTemplateParamsArg TemplateParamLists) {
+ assert(D.isDecompositionDeclarator());
+ const DecompositionDeclarator &Decomp = D.getDecompositionDeclarator();
+
+ // The syntax only allows a decomposition declarator as a simple-declaration
+ // or a for-range-declaration, but we parse it in more cases than that.
+ if (!D.mayHaveDecompositionDeclarator()) {
+ Diag(Decomp.getLSquareLoc(), diag::err_decomp_decl_context)
+ << Decomp.getSourceRange();
+ return nullptr;
+ }
+
+ if (!TemplateParamLists.empty()) {
+ // FIXME: There's no rule against this, but there are also no rules that
+ // would actually make it usable, so we reject it for now.
+ Diag(TemplateParamLists.front()->getTemplateLoc(),
+ diag::err_decomp_decl_template);
+ return nullptr;
+ }
+
+ Diag(Decomp.getLSquareLoc(), getLangOpts().CPlusPlus1z
+ ? diag::warn_cxx14_compat_decomp_decl
+ : diag::ext_decomp_decl)
+ << Decomp.getSourceRange();
+
+ // The semantic context is always just the current context.
+ DeclContext *const DC = CurContext;
+
+ // C++1z [dcl.dcl]/8:
+ // The decl-specifier-seq shall contain only the type-specifier auto
+ // and cv-qualifiers.
+ auto &DS = D.getDeclSpec();
+ {
+ SmallVector<StringRef, 8> BadSpecifiers;
+ SmallVector<SourceLocation, 8> BadSpecifierLocs;
+ if (auto SCS = DS.getStorageClassSpec()) {
+ BadSpecifiers.push_back(DeclSpec::getSpecifierName(SCS));
+ BadSpecifierLocs.push_back(DS.getStorageClassSpecLoc());
+ }
+ if (auto TSCS = DS.getThreadStorageClassSpec()) {
+ BadSpecifiers.push_back(DeclSpec::getSpecifierName(TSCS));
+ BadSpecifierLocs.push_back(DS.getThreadStorageClassSpecLoc());
+ }
+ if (DS.isConstexprSpecified()) {
+ BadSpecifiers.push_back("constexpr");
+ BadSpecifierLocs.push_back(DS.getConstexprSpecLoc());
+ }
+ if (DS.isInlineSpecified()) {
+ BadSpecifiers.push_back("inline");
+ BadSpecifierLocs.push_back(DS.getInlineSpecLoc());
+ }
+ if (!BadSpecifiers.empty()) {
+ auto &&Err = Diag(BadSpecifierLocs.front(), diag::err_decomp_decl_spec);
+ Err << (int)BadSpecifiers.size()
+ << llvm::join(BadSpecifiers.begin(), BadSpecifiers.end(), " ");
+ // Don't add FixItHints to remove the specifiers; we do still respect
+ // them when building the underlying variable.
+ for (auto Loc : BadSpecifierLocs)
+ Err << SourceRange(Loc, Loc);
+ }
+ // We can't recover from it being declared as a typedef.
+ if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef)
+ return nullptr;
+ }
+
+ TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
+ QualType R = TInfo->getType();
+
+ if (DiagnoseUnexpandedParameterPack(D.getIdentifierLoc(), TInfo,
+ UPPC_DeclarationType))
+ D.setInvalidType();
+
+ // The syntax only allows a single ref-qualifier prior to the decomposition
+ // declarator. No other declarator chunks are permitted. Also check the type
+ // specifier here.
+ if (DS.getTypeSpecType() != DeclSpec::TST_auto ||
+ D.hasGroupingParens() || D.getNumTypeObjects() > 1 ||
+ (D.getNumTypeObjects() == 1 &&
+ D.getTypeObject(0).Kind != DeclaratorChunk::Reference)) {
+ Diag(Decomp.getLSquareLoc(),
+ (D.hasGroupingParens() ||
+ (D.getNumTypeObjects() &&
+ D.getTypeObject(0).Kind == DeclaratorChunk::Paren))
+ ? diag::err_decomp_decl_parens
+ : diag::err_decomp_decl_type)
+ << R;
+
+ // In most cases, there's no actual problem with an explicitly-specified
+ // type, but a function type won't work here, and ActOnVariableDeclarator
+ // shouldn't be called for such a type.
+ if (R->isFunctionType())
+ D.setInvalidType();
+ }
+
+ // Build the BindingDecls.
+ SmallVector<BindingDecl*, 8> Bindings;
+
+ // Build the BindingDecls.
+ for (auto &B : D.getDecompositionDeclarator().bindings()) {
+ // Check for name conflicts.
+ DeclarationNameInfo NameInfo(B.Name, B.NameLoc);
+ LookupResult Previous(*this, NameInfo, LookupOrdinaryName,
+ ForRedeclaration);
+ LookupName(Previous, S,
+ /*CreateBuiltins*/DC->getRedeclContext()->isTranslationUnit());
+
+ // It's not permitted to shadow a template parameter name.
+ if (Previous.isSingleResult() &&
+ Previous.getFoundDecl()->isTemplateParameter()) {
+ DiagnoseTemplateParameterShadow(D.getIdentifierLoc(),
+ Previous.getFoundDecl());
+ Previous.clear();
+ }
+
+ bool ConsiderLinkage = DC->isFunctionOrMethod() &&
+ DS.getStorageClassSpec() == DeclSpec::SCS_extern;
+ FilterLookupForScope(Previous, DC, S, ConsiderLinkage,
+ /*AllowInlineNamespace*/false);
+ if (!Previous.empty()) {
+ auto *Old = Previous.getRepresentativeDecl();
+ Diag(B.NameLoc, diag::err_redefinition) << B.Name;
+ Diag(Old->getLocation(), diag::note_previous_definition);
+ }
+
+ auto *BD = BindingDecl::Create(Context, DC, B.NameLoc, B.Name);
+ PushOnScopeChains(BD, S, true);
+ Bindings.push_back(BD);
+ ParsingInitForAutoVars.insert(BD);
+ }
+
+ // There are no prior lookup results for the variable itself, because it
+ // is unnamed.
+ DeclarationNameInfo NameInfo((IdentifierInfo *)nullptr,
+ Decomp.getLSquareLoc());
+ LookupResult Previous(*this, NameInfo, LookupOrdinaryName, ForRedeclaration);
+
+ // Build the variable that holds the non-decomposed object.
+ bool AddToScope = true;
+ NamedDecl *New =
+ ActOnVariableDeclarator(S, D, DC, TInfo, Previous,
+ MultiTemplateParamsArg(), AddToScope, Bindings);
+ CurContext->addHiddenDecl(New);
+
+ if (isInOpenMPDeclareTargetContext())
+ checkDeclIsAllowedInOpenMPTarget(nullptr, New);
+
+ return New;
+}
+
+static bool checkSimpleDecomposition(
+ Sema &S, ArrayRef<BindingDecl *> Bindings, ValueDecl *Src,
+ QualType DecompType, const llvm::APSInt &NumElems, QualType ElemType,
+ llvm::function_ref<ExprResult(SourceLocation, Expr *, unsigned)> GetInit) {
+ if ((int64_t)Bindings.size() != NumElems) {
+ S.Diag(Src->getLocation(), diag::err_decomp_decl_wrong_number_bindings)
+ << DecompType << (unsigned)Bindings.size() << NumElems.toString(10)
+ << (NumElems < Bindings.size());
+ return true;
+ }
+
+ unsigned I = 0;
+ for (auto *B : Bindings) {
+ SourceLocation Loc = B->getLocation();
+ ExprResult E = S.BuildDeclRefExpr(Src, DecompType, VK_LValue, Loc);
+ if (E.isInvalid())
+ return true;
+ E = GetInit(Loc, E.get(), I++);
+ if (E.isInvalid())
+ return true;
+ B->setBinding(ElemType, E.get());
+ }
+
+ return false;
+}
+
+static bool checkArrayLikeDecomposition(Sema &S,
+ ArrayRef<BindingDecl *> Bindings,
+ ValueDecl *Src, QualType DecompType,
+ const llvm::APSInt &NumElems,
+ QualType ElemType) {
+ return checkSimpleDecomposition(
+ S, Bindings, Src, DecompType, NumElems, ElemType,
+ [&](SourceLocation Loc, Expr *Base, unsigned I) -> ExprResult {
+ ExprResult E = S.ActOnIntegerConstant(Loc, I);
+ if (E.isInvalid())
+ return ExprError();
+ return S.CreateBuiltinArraySubscriptExpr(Base, Loc, E.get(), Loc);
+ });
+}
+
+static bool checkArrayDecomposition(Sema &S, ArrayRef<BindingDecl*> Bindings,
+ ValueDecl *Src, QualType DecompType,
+ const ConstantArrayType *CAT) {
+ return checkArrayLikeDecomposition(S, Bindings, Src, DecompType,
+ llvm::APSInt(CAT->getSize()),
+ CAT->getElementType());
+}
+
+static bool checkVectorDecomposition(Sema &S, ArrayRef<BindingDecl*> Bindings,
+ ValueDecl *Src, QualType DecompType,
+ const VectorType *VT) {
+ return checkArrayLikeDecomposition(
+ S, Bindings, Src, DecompType, llvm::APSInt::get(VT->getNumElements()),
+ S.Context.getQualifiedType(VT->getElementType(),
+ DecompType.getQualifiers()));
+}
+
+static bool checkComplexDecomposition(Sema &S,
+ ArrayRef<BindingDecl *> Bindings,
+ ValueDecl *Src, QualType DecompType,
+ const ComplexType *CT) {
+ return checkSimpleDecomposition(
+ S, Bindings, Src, DecompType, llvm::APSInt::get(2),
+ S.Context.getQualifiedType(CT->getElementType(),
+ DecompType.getQualifiers()),
+ [&](SourceLocation Loc, Expr *Base, unsigned I) -> ExprResult {
+ return S.CreateBuiltinUnaryOp(Loc, I ? UO_Imag : UO_Real, Base);
+ });
+}
+
+static std::string printTemplateArgs(const PrintingPolicy &PrintingPolicy,
+ TemplateArgumentListInfo &Args) {
+ SmallString<128> SS;
+ llvm::raw_svector_ostream OS(SS);
+ bool First = true;
+ for (auto &Arg : Args.arguments()) {
+ if (!First)
+ OS << ", ";
+ Arg.getArgument().print(PrintingPolicy, OS);
+ First = false;
+ }
+ return OS.str();
+}
+
+static bool lookupStdTypeTraitMember(Sema &S, LookupResult &TraitMemberLookup,
+ SourceLocation Loc, StringRef Trait,
+ TemplateArgumentListInfo &Args,
+ unsigned DiagID) {
+ auto DiagnoseMissing = [&] {
+ if (DiagID)
+ S.Diag(Loc, DiagID) << printTemplateArgs(S.Context.getPrintingPolicy(),
+ Args);
+ return true;
+ };
+
+ // FIXME: Factor out duplication with lookupPromiseType in SemaCoroutine.
+ NamespaceDecl *Std = S.getStdNamespace();
+ if (!Std)
+ return DiagnoseMissing();
+
+ // Look up the trait itself, within namespace std. We can diagnose various
+ // problems with this lookup even if we've been asked to not diagnose a
+ // missing specialization, because this can only fail if the user has been
+ // declaring their own names in namespace std or we don't support the
+ // standard library implementation in use.
+ LookupResult Result(S, &S.PP.getIdentifierTable().get(Trait),
+ Loc, Sema::LookupOrdinaryName);
+ if (!S.LookupQualifiedName(Result, Std))
+ return DiagnoseMissing();
+ if (Result.isAmbiguous())
+ return true;
+
+ ClassTemplateDecl *TraitTD = Result.getAsSingle<ClassTemplateDecl>();
+ if (!TraitTD) {
+ Result.suppressDiagnostics();
+ NamedDecl *Found = *Result.begin();
+ S.Diag(Loc, diag::err_std_type_trait_not_class_template) << Trait;
+ S.Diag(Found->getLocation(), diag::note_declared_at);
+ return true;
+ }
+
+ // Build the template-id.
+ QualType TraitTy = S.CheckTemplateIdType(TemplateName(TraitTD), Loc, Args);
+ if (TraitTy.isNull())
+ return true;
+ if (!S.isCompleteType(Loc, TraitTy)) {
+ if (DiagID)
+ S.RequireCompleteType(
+ Loc, TraitTy, DiagID,
+ printTemplateArgs(S.Context.getPrintingPolicy(), Args));
+ return true;
+ }
+
+ CXXRecordDecl *RD = TraitTy->getAsCXXRecordDecl();
+ assert(RD && "specialization of class template is not a class?");
+
+ // Look up the member of the trait type.
+ S.LookupQualifiedName(TraitMemberLookup, RD);
+ return TraitMemberLookup.isAmbiguous();
+}
+
+static TemplateArgumentLoc
+getTrivialIntegralTemplateArgument(Sema &S, SourceLocation Loc, QualType T,
+ uint64_t I) {
+ TemplateArgument Arg(S.Context, S.Context.MakeIntValue(I, T), T);
+ return S.getTrivialTemplateArgumentLoc(Arg, T, Loc);
+}
+
+static TemplateArgumentLoc
+getTrivialTypeTemplateArgument(Sema &S, SourceLocation Loc, QualType T) {
+ return S.getTrivialTemplateArgumentLoc(TemplateArgument(T), QualType(), Loc);
+}
+
+namespace { enum class IsTupleLike { TupleLike, NotTupleLike, Error }; }
+
+static IsTupleLike isTupleLike(Sema &S, SourceLocation Loc, QualType T,
+ llvm::APSInt &Size) {
+ EnterExpressionEvaluationContext ContextRAII(S, Sema::ConstantEvaluated);
+
+ DeclarationName Value = S.PP.getIdentifierInfo("value");
+ LookupResult R(S, Value, Loc, Sema::LookupOrdinaryName);
+
+ // Form template argument list for tuple_size<T>.
+ TemplateArgumentListInfo Args(Loc, Loc);
+ Args.addArgument(getTrivialTypeTemplateArgument(S, Loc, T));
+
+ // If there's no tuple_size specialization, it's not tuple-like.
+ if (lookupStdTypeTraitMember(S, R, Loc, "tuple_size", Args, /*DiagID*/0))
+ return IsTupleLike::NotTupleLike;
+
+ // If we get this far, we've committed to the tuple interpretation, but
+ // we can still fail if there actually isn't a usable ::value.
+
+ struct ICEDiagnoser : Sema::VerifyICEDiagnoser {
+ LookupResult &R;
+ TemplateArgumentListInfo &Args;
+ ICEDiagnoser(LookupResult &R, TemplateArgumentListInfo &Args)
+ : R(R), Args(Args) {}
+ void diagnoseNotICE(Sema &S, SourceLocation Loc, SourceRange SR) {
+ S.Diag(Loc, diag::err_decomp_decl_std_tuple_size_not_constant)
+ << printTemplateArgs(S.Context.getPrintingPolicy(), Args);
+ }
+ } Diagnoser(R, Args);
+
+ if (R.empty()) {
+ Diagnoser.diagnoseNotICE(S, Loc, SourceRange());
+ return IsTupleLike::Error;
+ }
+
+ ExprResult E =
+ S.BuildDeclarationNameExpr(CXXScopeSpec(), R, /*NeedsADL*/false);
+ if (E.isInvalid())
+ return IsTupleLike::Error;
+
+ E = S.VerifyIntegerConstantExpression(E.get(), &Size, Diagnoser, false);
+ if (E.isInvalid())
+ return IsTupleLike::Error;
+
+ return IsTupleLike::TupleLike;
+}
+
+/// \return std::tuple_element<I, T>::type.
+static QualType getTupleLikeElementType(Sema &S, SourceLocation Loc,
+ unsigned I, QualType T) {
+ // Form template argument list for tuple_element<I, T>.
+ TemplateArgumentListInfo Args(Loc, Loc);
+ Args.addArgument(
+ getTrivialIntegralTemplateArgument(S, Loc, S.Context.getSizeType(), I));
+ Args.addArgument(getTrivialTypeTemplateArgument(S, Loc, T));
+
+ DeclarationName TypeDN = S.PP.getIdentifierInfo("type");
+ LookupResult R(S, TypeDN, Loc, Sema::LookupOrdinaryName);
+ if (lookupStdTypeTraitMember(
+ S, R, Loc, "tuple_element", Args,
+ diag::err_decomp_decl_std_tuple_element_not_specialized))
+ return QualType();
+
+ auto *TD = R.getAsSingle<TypeDecl>();
+ if (!TD) {
+ R.suppressDiagnostics();
+ S.Diag(Loc, diag::err_decomp_decl_std_tuple_element_not_specialized)
+ << printTemplateArgs(S.Context.getPrintingPolicy(), Args);
+ if (!R.empty())
+ S.Diag(R.getRepresentativeDecl()->getLocation(), diag::note_declared_at);
+ return QualType();
+ }
+
+ return S.Context.getTypeDeclType(TD);
+}
+
+namespace {
+struct BindingDiagnosticTrap {
+ Sema &S;
+ DiagnosticErrorTrap Trap;
+ BindingDecl *BD;
+
+ BindingDiagnosticTrap(Sema &S, BindingDecl *BD)
+ : S(S), Trap(S.Diags), BD(BD) {}
+ ~BindingDiagnosticTrap() {
+ if (Trap.hasErrorOccurred())
+ S.Diag(BD->getLocation(), diag::note_in_binding_decl_init) << BD;
+ }
+};
+}
+
+static bool checkTupleLikeDecomposition(Sema &S,
+ ArrayRef<BindingDecl *> Bindings,
+ VarDecl *Src, QualType DecompType,
+ const llvm::APSInt &TupleSize) {
+ if ((int64_t)Bindings.size() != TupleSize) {
+ S.Diag(Src->getLocation(), diag::err_decomp_decl_wrong_number_bindings)
+ << DecompType << (unsigned)Bindings.size() << TupleSize.toString(10)
+ << (TupleSize < Bindings.size());
+ return true;
+ }
+
+ if (Bindings.empty())
+ return false;
+
+ DeclarationName GetDN = S.PP.getIdentifierInfo("get");
+
+ // [dcl.decomp]p3:
+ // The unqualified-id get is looked up in the scope of E by class member
+ // access lookup
+ LookupResult MemberGet(S, GetDN, Src->getLocation(), Sema::LookupMemberName);
+ bool UseMemberGet = false;
+ if (S.isCompleteType(Src->getLocation(), DecompType)) {
+ if (auto *RD = DecompType->getAsCXXRecordDecl())
+ S.LookupQualifiedName(MemberGet, RD);
+ if (MemberGet.isAmbiguous())
+ return true;
+ UseMemberGet = !MemberGet.empty();
+ S.FilterAcceptableTemplateNames(MemberGet);
+ }
+
+ unsigned I = 0;
+ for (auto *B : Bindings) {
+ BindingDiagnosticTrap Trap(S, B);
+ SourceLocation Loc = B->getLocation();
+
+ ExprResult E = S.BuildDeclRefExpr(Src, DecompType, VK_LValue, Loc);
+ if (E.isInvalid())
+ return true;
+
+ // e is an lvalue if the type of the entity is an lvalue reference and
+ // an xvalue otherwise
+ if (!Src->getType()->isLValueReferenceType())
+ E = ImplicitCastExpr::Create(S.Context, E.get()->getType(), CK_NoOp,
+ E.get(), nullptr, VK_XValue);
+
+ TemplateArgumentListInfo Args(Loc, Loc);
+ Args.addArgument(
+ getTrivialIntegralTemplateArgument(S, Loc, S.Context.getSizeType(), I));
+
+ if (UseMemberGet) {
+ // if [lookup of member get] finds at least one declaration, the
+ // initializer is e.get<i-1>().
+ E = S.BuildMemberReferenceExpr(E.get(), DecompType, Loc, false,
+ CXXScopeSpec(), SourceLocation(), nullptr,
+ MemberGet, &Args, nullptr);
+ if (E.isInvalid())
+ return true;
+
+ E = S.ActOnCallExpr(nullptr, E.get(), Loc, None, Loc);
+ } else {
+ // Otherwise, the initializer is get<i-1>(e), where get is looked up
+ // in the associated namespaces.
+ Expr *Get = UnresolvedLookupExpr::Create(
+ S.Context, nullptr, NestedNameSpecifierLoc(), SourceLocation(),
+ DeclarationNameInfo(GetDN, Loc), /*RequiresADL*/true, &Args,
+ UnresolvedSetIterator(), UnresolvedSetIterator());
+
+ Expr *Arg = E.get();
+ E = S.ActOnCallExpr(nullptr, Get, Loc, Arg, Loc);
+ }
+ if (E.isInvalid())
+ return true;
+ Expr *Init = E.get();
+
+ // Given the type T designated by std::tuple_element<i - 1, E>::type,
+ QualType T = getTupleLikeElementType(S, Loc, I, DecompType);
+ if (T.isNull())
+ return true;
+
+ // each vi is a variable of type "reference to T" initialized with the
+ // initializer, where the reference is an lvalue reference if the
+ // initializer is an lvalue and an rvalue reference otherwise
+ QualType RefType =
+ S.BuildReferenceType(T, E.get()->isLValue(), Loc, B->getDeclName());
+ if (RefType.isNull())
+ return true;
+ auto *RefVD = VarDecl::Create(
+ S.Context, Src->getDeclContext(), Loc, Loc,
+ B->getDeclName().getAsIdentifierInfo(), RefType,
+ S.Context.getTrivialTypeSourceInfo(T, Loc), Src->getStorageClass());
+ RefVD->setLexicalDeclContext(Src->getLexicalDeclContext());
+ RefVD->setTSCSpec(Src->getTSCSpec());
+ RefVD->setImplicit();
+ if (Src->isInlineSpecified())
+ RefVD->setInlineSpecified();
+ RefVD->getLexicalDeclContext()->addHiddenDecl(RefVD);
+
+ InitializedEntity Entity = InitializedEntity::InitializeBinding(RefVD);
+ InitializationKind Kind = InitializationKind::CreateCopy(Loc, Loc);
+ InitializationSequence Seq(S, Entity, Kind, Init);
+ E = Seq.Perform(S, Entity, Kind, Init);
+ if (E.isInvalid())
+ return true;
+ E = S.ActOnFinishFullExpr(E.get(), Loc);
+ if (E.isInvalid())
+ return true;
+ RefVD->setInit(E.get());
+ RefVD->checkInitIsICE();
+
+ E = S.BuildDeclarationNameExpr(CXXScopeSpec(),
+ DeclarationNameInfo(B->getDeclName(), Loc),
+ RefVD);
+ if (E.isInvalid())
+ return true;
+
+ B->setBinding(T, E.get());
+ I++;
+ }
+
+ return false;
+}
+
+/// Find the base class to decompose in a built-in decomposition of a class type.
+/// This base class search is, unfortunately, not quite like any other that we
+/// perform anywhere else in C++.
+static const CXXRecordDecl *findDecomposableBaseClass(Sema &S,
+ SourceLocation Loc,
+ const CXXRecordDecl *RD,
+ CXXCastPath &BasePath) {
+ auto BaseHasFields = [](const CXXBaseSpecifier *Specifier,
+ CXXBasePath &Path) {
+ return Specifier->getType()->getAsCXXRecordDecl()->hasDirectFields();
+ };
+
+ const CXXRecordDecl *ClassWithFields = nullptr;
+ if (RD->hasDirectFields())
+ // [dcl.decomp]p4:
+ // Otherwise, all of E's non-static data members shall be public direct
+ // members of E ...
+ ClassWithFields = RD;
+ else {
+ // ... or of ...
+ CXXBasePaths Paths;
+ Paths.setOrigin(const_cast<CXXRecordDecl*>(RD));
+ if (!RD->lookupInBases(BaseHasFields, Paths)) {
+ // If no classes have fields, just decompose RD itself. (This will work
+ // if and only if zero bindings were provided.)
+ return RD;
+ }
+
+ CXXBasePath *BestPath = nullptr;
+ for (auto &P : Paths) {
+ if (!BestPath)
+ BestPath = &P;
+ else if (!S.Context.hasSameType(P.back().Base->getType(),
+ BestPath->back().Base->getType())) {
+ // ... the same ...
+ S.Diag(Loc, diag::err_decomp_decl_multiple_bases_with_members)
+ << false << RD << BestPath->back().Base->getType()
+ << P.back().Base->getType();
+ return nullptr;
+ } else if (P.Access < BestPath->Access) {
+ BestPath = &P;
+ }
+ }
+
+ // ... unambiguous ...
+ QualType BaseType = BestPath->back().Base->getType();
+ if (Paths.isAmbiguous(S.Context.getCanonicalType(BaseType))) {
+ S.Diag(Loc, diag::err_decomp_decl_ambiguous_base)
+ << RD << BaseType << S.getAmbiguousPathsDisplayString(Paths);
+ return nullptr;
+ }
+
+ // ... public base class of E.
+ if (BestPath->Access != AS_public) {
+ S.Diag(Loc, diag::err_decomp_decl_non_public_base)
+ << RD << BaseType;
+ for (auto &BS : *BestPath) {
+ if (BS.Base->getAccessSpecifier() != AS_public) {
+ S.Diag(BS.Base->getLocStart(), diag::note_access_constrained_by_path)
+ << (BS.Base->getAccessSpecifier() == AS_protected)
+ << (BS.Base->getAccessSpecifierAsWritten() == AS_none);
+ break;
+ }
+ }
+ return nullptr;
+ }
+
+ ClassWithFields = BaseType->getAsCXXRecordDecl();
+ S.BuildBasePathArray(Paths, BasePath);
+ }
+
+ // The above search did not check whether the selected class itself has base
+ // classes with fields, so check that now.
+ CXXBasePaths Paths;
+ if (ClassWithFields->lookupInBases(BaseHasFields, Paths)) {
+ S.Diag(Loc, diag::err_decomp_decl_multiple_bases_with_members)
+ << (ClassWithFields == RD) << RD << ClassWithFields
+ << Paths.front().back().Base->getType();
+ return nullptr;
+ }
+
+ return ClassWithFields;
+}
+
+static bool checkMemberDecomposition(Sema &S, ArrayRef<BindingDecl*> Bindings,
+ ValueDecl *Src, QualType DecompType,
+ const CXXRecordDecl *RD) {
+ CXXCastPath BasePath;
+ RD = findDecomposableBaseClass(S, Src->getLocation(), RD, BasePath);
+ if (!RD)
+ return true;
+ QualType BaseType = S.Context.getQualifiedType(S.Context.getRecordType(RD),
+ DecompType.getQualifiers());
+
+ auto DiagnoseBadNumberOfBindings = [&]() -> bool {
+ unsigned NumFields =
+ std::count_if(RD->field_begin(), RD->field_end(),
+ [](FieldDecl *FD) { return !FD->isUnnamedBitfield(); });
+ assert(Bindings.size() != NumFields);
+ S.Diag(Src->getLocation(), diag::err_decomp_decl_wrong_number_bindings)
+ << DecompType << (unsigned)Bindings.size() << NumFields
+ << (NumFields < Bindings.size());
+ return true;
+ };
+
+ // all of E's non-static data members shall be public [...] members,
+ // E shall not have an anonymous union member, ...
+ unsigned I = 0;
+ for (auto *FD : RD->fields()) {
+ if (FD->isUnnamedBitfield())
+ continue;
+
+ if (FD->isAnonymousStructOrUnion()) {
+ S.Diag(Src->getLocation(), diag::err_decomp_decl_anon_union_member)
+ << DecompType << FD->getType()->isUnionType();
+ S.Diag(FD->getLocation(), diag::note_declared_at);
+ return true;
+ }
+
+ // We have a real field to bind.
+ if (I >= Bindings.size())
+ return DiagnoseBadNumberOfBindings();
+ auto *B = Bindings[I++];
+
+ SourceLocation Loc = B->getLocation();
+ if (FD->getAccess() != AS_public) {
+ S.Diag(Loc, diag::err_decomp_decl_non_public_member) << FD << DecompType;
+
+ // Determine whether the access specifier was explicit.
+ bool Implicit = true;
+ for (const auto *D : RD->decls()) {
+ if (declaresSameEntity(D, FD))
+ break;
+ if (isa<AccessSpecDecl>(D)) {
+ Implicit = false;
+ break;
+ }
+ }
+
+ S.Diag(FD->getLocation(), diag::note_access_natural)
+ << (FD->getAccess() == AS_protected) << Implicit;
+ return true;
+ }
+
+ // Initialize the binding to Src.FD.
+ ExprResult E = S.BuildDeclRefExpr(Src, DecompType, VK_LValue, Loc);
+ if (E.isInvalid())
+ return true;
+ E = S.ImpCastExprToType(E.get(), BaseType, CK_UncheckedDerivedToBase,
+ VK_LValue, &BasePath);
+ if (E.isInvalid())
+ return true;
+ E = S.BuildFieldReferenceExpr(E.get(), /*IsArrow*/ false, Loc,
+ CXXScopeSpec(), FD,
+ DeclAccessPair::make(FD, FD->getAccess()),
+ DeclarationNameInfo(FD->getDeclName(), Loc));
+ if (E.isInvalid())
+ return true;
+
+ // If the type of the member is T, the referenced type is cv T, where cv is
+ // the cv-qualification of the decomposition expression.
+ //
+ // FIXME: We resolve a defect here: if the field is mutable, we do not add
+ // 'const' to the type of the field.
+ Qualifiers Q = DecompType.getQualifiers();
+ if (FD->isMutable())
+ Q.removeConst();
+ B->setBinding(S.BuildQualifiedType(FD->getType(), Loc, Q), E.get());
+ }
+
+ if (I != Bindings.size())
+ return DiagnoseBadNumberOfBindings();
+
+ return false;
+}
+
+void Sema::CheckCompleteDecompositionDeclaration(DecompositionDecl *DD) {
+ QualType DecompType = DD->getType();
+
+ // If the type of the decomposition is dependent, then so is the type of
+ // each binding.
+ if (DecompType->isDependentType()) {
+ for (auto *B : DD->bindings())
+ B->setType(Context.DependentTy);
+ return;
+ }
+
+ DecompType = DecompType.getNonReferenceType();
+ ArrayRef<BindingDecl*> Bindings = DD->bindings();
+
+ // C++1z [dcl.decomp]/2:
+ // If E is an array type [...]
+ // As an extension, we also support decomposition of built-in complex and
+ // vector types.
+ if (auto *CAT = Context.getAsConstantArrayType(DecompType)) {
+ if (checkArrayDecomposition(*this, Bindings, DD, DecompType, CAT))
+ DD->setInvalidDecl();
+ return;
+ }
+ if (auto *VT = DecompType->getAs<VectorType>()) {
+ if (checkVectorDecomposition(*this, Bindings, DD, DecompType, VT))
+ DD->setInvalidDecl();
+ return;
+ }
+ if (auto *CT = DecompType->getAs<ComplexType>()) {
+ if (checkComplexDecomposition(*this, Bindings, DD, DecompType, CT))
+ DD->setInvalidDecl();
+ return;
+ }
+
+ // C++1z [dcl.decomp]/3:
+ // if the expression std::tuple_size<E>::value is a well-formed integral
+ // constant expression, [...]
+ llvm::APSInt TupleSize(32);
+ switch (isTupleLike(*this, DD->getLocation(), DecompType, TupleSize)) {
+ case IsTupleLike::Error:
+ DD->setInvalidDecl();
+ return;
+
+ case IsTupleLike::TupleLike:
+ if (checkTupleLikeDecomposition(*this, Bindings, DD, DecompType, TupleSize))
+ DD->setInvalidDecl();
+ return;
+
+ case IsTupleLike::NotTupleLike:
+ break;
+ }
+
+ // C++1z [dcl.dcl]/8:
+ // [E shall be of array or non-union class type]
+ CXXRecordDecl *RD = DecompType->getAsCXXRecordDecl();
+ if (!RD || RD->isUnion()) {
+ Diag(DD->getLocation(), diag::err_decomp_decl_unbindable_type)
+ << DD << !RD << DecompType;
+ DD->setInvalidDecl();
+ return;
+ }
+
+ // C++1z [dcl.decomp]/4:
+ // all of E's non-static data members shall be [...] direct members of
+ // E or of the same unambiguous public base class of E, ...
+ if (checkMemberDecomposition(*this, Bindings, DD, DecompType, RD))
+ DD->setInvalidDecl();
+}
+
/// \brief Merge the exception specifications of two variable declarations.
///
/// This is called when there's a redeclaration of a VarDecl. The function
@@ -912,7 +1673,8 @@ static bool CheckConstexprDeclStmt(Sema &SemaRef, const FunctionDecl *Dcl,
// C++11 and permitted in C++1y, so ignore them.
continue;
- case Decl::Var: {
+ case Decl::Var:
+ case Decl::Decomposition: {
// C++1y [dcl.constexpr]p3 allows anything except:
// a definition of a variable of non-literal type or of static or
// thread storage duration or for which no initialization is performed.
@@ -2192,7 +2954,8 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
} else {
Member = HandleField(S, cast<CXXRecordDecl>(CurContext), Loc, D,
BitWidth, InitStyle, AS);
- assert(Member && "HandleField never returns null");
+ if (!Member)
+ return nullptr;
}
} else {
Member = HandleDeclarator(S, D, TemplateParameterLists);
@@ -3483,98 +4246,30 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
CtorArg = CastForMoving(SemaRef, CtorArg.get());
}
- // When the field we are copying is an array, create index variables for
- // each dimension of the array. We use these index variables to subscript
- // the source array, and other clients (e.g., CodeGen) will perform the
- // necessary iteration with these index variables.
- SmallVector<VarDecl *, 4> IndexVariables;
- QualType BaseType = Field->getType();
- QualType SizeType = SemaRef.Context.getSizeType();
- bool InitializingArray = false;
- while (const ConstantArrayType *Array
- = SemaRef.Context.getAsConstantArrayType(BaseType)) {
- InitializingArray = true;
- // Create the iteration variable for this array index.
- IdentifierInfo *IterationVarName = nullptr;
- {
- SmallString<8> Str;
- llvm::raw_svector_ostream OS(Str);
- OS << "__i" << IndexVariables.size();
- IterationVarName = &SemaRef.Context.Idents.get(OS.str());
- }
- VarDecl *IterationVar
- = VarDecl::Create(SemaRef.Context, SemaRef.CurContext, Loc, Loc,
- IterationVarName, SizeType,
- SemaRef.Context.getTrivialTypeSourceInfo(SizeType, Loc),
- SC_None);
- IndexVariables.push_back(IterationVar);
-
- // Create a reference to the iteration variable.
- ExprResult IterationVarRef
- = SemaRef.BuildDeclRefExpr(IterationVar, SizeType, VK_LValue, Loc);
- assert(!IterationVarRef.isInvalid() &&
- "Reference to invented variable cannot fail!");
- IterationVarRef = SemaRef.DefaultLvalueConversion(IterationVarRef.get());
- assert(!IterationVarRef.isInvalid() &&
- "Conversion of invented variable cannot fail!");
-
- // Subscript the array with this iteration variable.
- CtorArg = SemaRef.CreateBuiltinArraySubscriptExpr(CtorArg.get(), Loc,
- IterationVarRef.get(),
- Loc);
- if (CtorArg.isInvalid())
- return true;
+ InitializedEntity Entity =
+ Indirect ? InitializedEntity::InitializeMember(Indirect, nullptr,
+ /*Implicit*/ true)
+ : InitializedEntity::InitializeMember(Field, nullptr,
+ /*Implicit*/ true);
- BaseType = Array->getElementType();
- }
-
- // The array subscript expression is an lvalue, which is wrong for moving.
- if (Moving && InitializingArray)
- CtorArg = CastForMoving(SemaRef, CtorArg.get());
-
- // Construct the entity that we will be initializing. For an array, this
- // will be first element in the array, which may require several levels
- // of array-subscript entities.
- SmallVector<InitializedEntity, 4> Entities;
- Entities.reserve(1 + IndexVariables.size());
- if (Indirect)
- Entities.push_back(InitializedEntity::InitializeMember(Indirect));
- else
- Entities.push_back(InitializedEntity::InitializeMember(Field));
- for (unsigned I = 0, N = IndexVariables.size(); I != N; ++I)
- Entities.push_back(InitializedEntity::InitializeElement(SemaRef.Context,
- 0,
- Entities.back()));
-
// Direct-initialize to use the copy constructor.
InitializationKind InitKind =
InitializationKind::CreateDirect(Loc, SourceLocation(), SourceLocation());
Expr *CtorArgE = CtorArg.getAs<Expr>();
- InitializationSequence InitSeq(SemaRef, Entities.back(), InitKind,
- CtorArgE);
-
- ExprResult MemberInit
- = InitSeq.Perform(SemaRef, Entities.back(), InitKind,
- MultiExprArg(&CtorArgE, 1));
+ InitializationSequence InitSeq(SemaRef, Entity, InitKind, CtorArgE);
+ ExprResult MemberInit =
+ InitSeq.Perform(SemaRef, Entity, InitKind, MultiExprArg(&CtorArgE, 1));
MemberInit = SemaRef.MaybeCreateExprWithCleanups(MemberInit);
if (MemberInit.isInvalid())
return true;
- if (Indirect) {
- assert(IndexVariables.size() == 0 &&
- "Indirect field improperly initialized");
- CXXMemberInit
- = new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context, Indirect,
- Loc, Loc,
- MemberInit.getAs<Expr>(),
- Loc);
- } else
- CXXMemberInit = CXXCtorInitializer::Create(SemaRef.Context, Field, Loc,
- Loc, MemberInit.getAs<Expr>(),
- Loc,
- IndexVariables.data(),
- IndexVariables.size());
+ if (Indirect)
+ CXXMemberInit = new (SemaRef.Context) CXXCtorInitializer(
+ SemaRef.Context, Indirect, Loc, Loc, MemberInit.getAs<Expr>(), Loc);
+ else
+ CXXMemberInit = new (SemaRef.Context) CXXCtorInitializer(
+ SemaRef.Context, Field, Loc, Loc, MemberInit.getAs<Expr>(), Loc);
return false;
}
@@ -3585,9 +4280,11 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
SemaRef.Context.getBaseElementType(Field->getType());
if (FieldBaseElementType->isRecordType()) {
- InitializedEntity InitEntity
- = Indirect? InitializedEntity::InitializeMember(Indirect)
- : InitializedEntity::InitializeMember(Field);
+ InitializedEntity InitEntity =
+ Indirect ? InitializedEntity::InitializeMember(Indirect, nullptr,
+ /*Implicit*/ true)
+ : InitializedEntity::InitializeMember(Field, nullptr,
+ /*Implicit*/ true);
InitializationKind InitKind =
InitializationKind::CreateDefault(Loc);
@@ -4778,7 +5475,8 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) {
if (MD->isInlined()) {
// MinGW does not import or export inline methods.
- if (!Context.getTargetInfo().getCXXABI().isMicrosoft())
+ if (!Context.getTargetInfo().getCXXABI().isMicrosoft() &&
+ !Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment())
continue;
// MSVC versions before 2015 don't export the move assignment operators
@@ -5333,7 +6031,8 @@ void Sema::EvaluateImplicitExceptionSpec(SourceLocation Loc, CXXMethodDecl *MD)
return;
// Evaluate the exception specification.
- auto ESI = computeImplicitExceptionSpec(*this, Loc, MD).getExceptionSpec();
+ auto IES = computeImplicitExceptionSpec(*this, Loc, MD);
+ auto ESI = IES.getExceptionSpec();
// Update the type of the special member to use it.
UpdateExceptionSpec(MD, ESI);
@@ -5531,8 +6230,8 @@ void Sema::CheckExplicitlyDefaultedMemberExceptionSpec(
CallingConv CC = Context.getDefaultCallingConvention(/*IsVariadic=*/false,
/*IsCXXMethod=*/true);
FunctionProtoType::ExtProtoInfo EPI(CC);
- EPI.ExceptionSpec = computeImplicitExceptionSpec(*this, MD->getLocation(), MD)
- .getExceptionSpec();
+ auto IES = computeImplicitExceptionSpec(*this, MD->getLocation(), MD);
+ EPI.ExceptionSpec = IES.getExceptionSpec();
const FunctionProtoType *ImplicitType = cast<FunctionProtoType>(
Context.getFunctionType(Context.VoidTy, None, EPI));
@@ -5889,8 +6588,13 @@ bool SpecialMemberDeletionInfo::shouldDeleteForField(FieldDecl *FD) {
bool SpecialMemberDeletionInfo::shouldDeleteForAllConstMembers() {
// This is a silly definition, because it gives an empty union a deleted
// default constructor. Don't do that.
- if (CSM == Sema::CXXDefaultConstructor && inUnion() && AllFieldsAreConst &&
- !MD->getParent()->field_empty()) {
+ if (CSM == Sema::CXXDefaultConstructor && inUnion() && AllFieldsAreConst) {
+ bool AnyFields = false;
+ for (auto *F : MD->getParent()->fields())
+ if ((AnyFields = !F->isUnnamedBitfield()))
+ break;
+ if (!AnyFields)
+ return false;
if (Diagnose)
S.Diag(MD->getParent()->getLocation(),
diag::note_deleted_default_ctor_all_const)
@@ -5939,10 +6643,15 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM,
(CSM == CXXCopyConstructor || CSM == CXXCopyAssignment)) {
CXXMethodDecl *UserDeclaredMove = nullptr;
- // In Microsoft mode, a user-declared move only causes the deletion of the
- // corresponding copy operation, not both copy operations.
+ // In Microsoft mode up to MSVC 2013, a user-declared move only causes the
+ // deletion of the corresponding copy operation, not both copy operations.
+ // MSVC 2015 has adopted the standards conforming behavior.
+ bool DeletesOnlyMatchingCopy =
+ getLangOpts().MSVCCompat &&
+ !getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015);
+
if (RD->hasUserDeclaredMoveConstructor() &&
- (!getLangOpts().MSVCCompat || CSM == CXXCopyConstructor)) {
+ (!DeletesOnlyMatchingCopy || CSM == CXXCopyConstructor)) {
if (!Diagnose) return true;
// Find any user-declared move constructor.
@@ -5954,7 +6663,7 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM,
}
assert(UserDeclaredMove);
} else if (RD->hasUserDeclaredMoveAssignment() &&
- (!getLangOpts().MSVCCompat || CSM == CXXCopyAssignment)) {
+ (!DeletesOnlyMatchingCopy || CSM == CXXCopyAssignment)) {
if (!Diagnose) return true;
// Find any user-declared move assignment operator.
@@ -5987,7 +6696,7 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM,
DeclarationName Name =
Context.DeclarationNames.getCXXOperatorName(OO_Delete);
if (FindDeallocationFunction(MD->getLocation(), MD->getParent(), Name,
- OperatorDelete, false)) {
+ OperatorDelete, /*Diagnose*/false)) {
if (Diagnose)
Diag(RD->getLocation(), diag::note_deleted_dtor_no_operator_delete);
return true;
@@ -5997,13 +6706,14 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM,
SpecialMemberDeletionInfo SMI(*this, MD, CSM, ICI, Diagnose);
for (auto &BI : RD->bases())
- if (!BI.isVirtual() &&
+ if ((SMI.IsAssignment || !BI.isVirtual()) &&
SMI.shouldDeleteForBase(&BI))
return true;
// Per DR1611, do not consider virtual bases of constructors of abstract
- // classes, since we are not going to construct them.
- if (!RD->isAbstract() || !SMI.IsConstructor) {
+ // classes, since we are not going to construct them. For assignment
+ // operators, we only assign (and thus only consider) direct bases.
+ if ((!RD->isAbstract() || !SMI.IsConstructor) && !SMI.IsAssignment) {
for (auto &BI : RD->vbases())
if (SMI.shouldDeleteForBase(&BI))
return true;
@@ -6618,6 +7328,17 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) {
if (ClassDecl->needsOverloadResolutionForCopyConstructor() ||
ClassDecl->hasInheritedConstructor())
DeclareImplicitCopyConstructor(ClassDecl);
+ // For the MS ABI we need to know whether the copy ctor is deleted. A
+ // prerequisite for deleting the implicit copy ctor is that the class has a
+ // move ctor or move assignment that is either user-declared or whose
+ // semantics are inherited from a subobject. FIXME: We should provide a more
+ // direct way for CodeGen to ask whether the constructor was deleted.
+ else if (Context.getTargetInfo().getCXXABI().isMicrosoft() &&
+ (ClassDecl->hasUserDeclaredMoveConstructor() ||
+ ClassDecl->needsOverloadResolutionForMoveConstructor() ||
+ ClassDecl->hasUserDeclaredMoveAssignment() ||
+ ClassDecl->needsOverloadResolutionForMoveAssignment()))
+ DeclareImplicitCopyConstructor(ClassDecl);
}
if (getLangOpts().CPlusPlus11 && ClassDecl->needsImplicitMoveConstructor()) {
@@ -6926,19 +7647,11 @@ bool Sema::CheckDestructor(CXXDestructorDecl *Destructor) {
Loc = RD->getLocation();
// If we have a virtual destructor, look up the deallocation function
- FunctionDecl *OperatorDelete = nullptr;
- DeclarationName Name =
- Context.DeclarationNames.getCXXOperatorName(OO_Delete);
- if (FindDeallocationFunction(Loc, RD, Name, OperatorDelete))
- return true;
- // If there's no class-specific operator delete, look up the global
- // non-array delete.
- if (!OperatorDelete)
- OperatorDelete = FindUsualDeallocationFunction(Loc, true, Name);
-
- MarkFunctionReferenced(Loc, OperatorDelete);
-
- Destructor->setOperatorDelete(OperatorDelete);
+ if (FunctionDecl *OperatorDelete =
+ FindDeallocationFunctionForDestructor(Loc, RD)) {
+ MarkFunctionReferenced(Loc, OperatorDelete);
+ Destructor->setOperatorDelete(OperatorDelete);
+ }
}
return false;
@@ -7320,7 +8033,7 @@ static void DiagnoseNamespaceInlineMismatch(Sema &S, SourceLocation KeywordLoc,
S.Diag(Loc, diag::warn_inline_namespace_reopened_noninline)
<< FixItHint::CreateInsertion(KeywordLoc, "inline ");
else
- S.Diag(Loc, diag::err_inline_namespace_mismatch) << *IsInline;
+ S.Diag(Loc, diag::err_inline_namespace_mismatch);
S.Diag(PrevNS->getLocation(), diag::note_previous_definition);
*IsInline = PrevNS->isInline();
@@ -7497,11 +8210,29 @@ CXXRecordDecl *Sema::getStdBadAlloc() const {
StdBadAlloc.get(Context.getExternalSource()));
}
+EnumDecl *Sema::getStdAlignValT() const {
+ return cast_or_null<EnumDecl>(StdAlignValT.get(Context.getExternalSource()));
+}
+
NamespaceDecl *Sema::getStdNamespace() const {
return cast_or_null<NamespaceDecl>(
StdNamespace.get(Context.getExternalSource()));
}
+NamespaceDecl *Sema::lookupStdExperimentalNamespace() {
+ if (!StdExperimentalNamespaceCache) {
+ if (auto Std = getStdNamespace()) {
+ LookupResult Result(*this, &PP.getIdentifierTable().get("experimental"),
+ SourceLocation(), LookupNamespaceName);
+ if (!LookupQualifiedName(Result, Std) ||
+ !(StdExperimentalNamespaceCache =
+ Result.getAsSingle<NamespaceDecl>()))
+ Result.suppressDiagnostics();
+ }
+ }
+ return StdExperimentalNamespaceCache;
+}
+
/// \brief Retrieve the special "std" namespace, which may require us to
/// implicitly define the namespace.
NamespaceDecl *Sema::getOrCreateStdNamespace() {
@@ -7801,15 +8532,19 @@ void Sema::PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir) {
Decl *Sema::ActOnUsingDeclaration(Scope *S,
AccessSpecifier AS,
- bool HasUsingKeyword,
SourceLocation UsingLoc,
+ SourceLocation TypenameLoc,
CXXScopeSpec &SS,
UnqualifiedId &Name,
- AttributeList *AttrList,
- bool HasTypenameKeyword,
- SourceLocation TypenameLoc) {
+ SourceLocation EllipsisLoc,
+ AttributeList *AttrList) {
assert(S->getFlags() & Scope::DeclScope && "Invalid Scope.");
+ if (SS.isEmpty()) {
+ Diag(Name.getLocStart(), diag::err_using_requires_qualname);
+ return nullptr;
+ }
+
switch (Name.getKind()) {
case UnqualifiedId::IK_ImplicitSelfParam:
case UnqualifiedId::IK_Identifier:
@@ -7848,21 +8583,30 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S,
return nullptr;
// Warn about access declarations.
- if (!HasUsingKeyword) {
+ if (UsingLoc.isInvalid()) {
Diag(Name.getLocStart(),
getLangOpts().CPlusPlus11 ? diag::err_access_decl
: diag::warn_access_decl_deprecated)
<< FixItHint::CreateInsertion(SS.getRange().getBegin(), "using ");
}
- if (DiagnoseUnexpandedParameterPack(SS, UPPC_UsingDeclaration) ||
- DiagnoseUnexpandedParameterPack(TargetNameInfo, UPPC_UsingDeclaration))
- return nullptr;
+ if (EllipsisLoc.isInvalid()) {
+ if (DiagnoseUnexpandedParameterPack(SS, UPPC_UsingDeclaration) ||
+ DiagnoseUnexpandedParameterPack(TargetNameInfo, UPPC_UsingDeclaration))
+ return nullptr;
+ } else {
+ if (!SS.getScopeRep()->containsUnexpandedParameterPack() &&
+ !TargetNameInfo.containsUnexpandedParameterPack()) {
+ Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
+ << SourceRange(SS.getBeginLoc(), TargetNameInfo.getEndLoc());
+ EllipsisLoc = SourceLocation();
+ }
+ }
- NamedDecl *UD = BuildUsingDeclaration(S, AS, UsingLoc, SS,
- TargetNameInfo, AttrList,
- /* IsInstantiation */ false,
- HasTypenameKeyword, TypenameLoc);
+ NamedDecl *UD =
+ BuildUsingDeclaration(S, AS, UsingLoc, TypenameLoc.isValid(), TypenameLoc,
+ SS, TargetNameInfo, EllipsisLoc, AttrList,
+ /*IsInstantiation*/false);
if (UD)
PushOnScopeChains(UD, S, /*AddToContext*/ false);
@@ -7925,6 +8669,7 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
diag::err_using_decl_nested_name_specifier_is_current_class)
<< Using->getQualifierLoc().getSourceRange();
Diag(Orig->getLocation(), diag::note_using_decl_target);
+ Using->setInvalidDecl();
return true;
}
@@ -7934,6 +8679,7 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
<< cast<CXXRecordDecl>(CurContext)
<< Using->getQualifierLoc().getSourceRange();
Diag(Orig->getLocation(), diag::note_using_decl_target);
+ Using->setInvalidDecl();
return true;
}
}
@@ -7957,7 +8703,7 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
// We can have UsingDecls in our Previous results because we use the same
// LookupResult for checking whether the UsingDecl itself is a valid
// redeclaration.
- if (isa<UsingDecl>(D))
+ if (isa<UsingDecl>(D) || isa<UsingPackDecl>(D))
continue;
if (IsEquivalentForUsingDecl(Context, D, Target)) {
@@ -8003,6 +8749,7 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
Diag(Target->getLocation(), diag::note_using_decl_target);
Diag(OldDecl->getLocation(), diag::note_using_decl_conflict);
+ Using->setInvalidDecl();
return true;
}
@@ -8015,6 +8762,7 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
Diag(Using->getLocation(), diag::err_using_decl_conflict);
Diag(Target->getLocation(), diag::note_using_decl_target);
Diag(Tag->getLocation(), diag::note_using_decl_conflict);
+ Using->setInvalidDecl();
return true;
}
@@ -8024,6 +8772,7 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
Diag(Using->getLocation(), diag::err_using_decl_conflict);
Diag(Target->getLocation(), diag::note_using_decl_target);
Diag(NonTag->getLocation(), diag::note_using_decl_conflict);
+ Using->setInvalidDecl();
return true;
}
@@ -8231,23 +8980,19 @@ private:
/// 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,
- bool HasTypenameKeyword,
- SourceLocation TypenameLoc) {
+ bool IsInstantiation) {
assert(!SS.isInvalid() && "Invalid CXXScopeSpec.");
SourceLocation IdentLoc = NameInfo.getLoc();
assert(IdentLoc.isValid() && "Invalid TargetName location.");
// FIXME: We ignore attributes for now.
- if (SS.isEmpty()) {
- Diag(IdentLoc, diag::err_using_requires_qualname);
- return nullptr;
- }
-
// For an inheriting constructor declaration, the name of the using
// declaration is the name of a constructor in this class, not in the
// base class.
@@ -8281,8 +9026,23 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
F.done();
} else {
assert(IsInstantiation && "no scope in non-instantiation");
- assert(CurContext->isRecord() && "scope not record in instantiation");
- LookupQualifiedName(Previous, CurContext);
+ if (CurContext->isRecord())
+ LookupQualifiedName(Previous, CurContext);
+ else {
+ // No redeclaration check is needed here; in non-member contexts we
+ // diagnosed all possible conflicts with other using-declarations when
+ // building the template:
+ //
+ // For a dependent non-type using declaration, the only valid case is
+ // if we instantiate to a single enumerator. We check for conflicts
+ // between shadow declarations we introduce, and we check in the template
+ // definition for conflicts between a non-type using declaration and any
+ // other declaration, which together covers all cases.
+ //
+ // A dependent typename using declaration will never successfully
+ // instantiate, since it will always name a class member, so we reject
+ // that in the template definition.
+ }
}
// Check for invalid redeclarations.
@@ -8291,22 +9051,24 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
return nullptr;
// Check for bad qualifiers.
- if (CheckUsingDeclQualifier(UsingLoc, SS, NameInfo, IdentLoc))
+ if (CheckUsingDeclQualifier(UsingLoc, HasTypenameKeyword, SS, NameInfo,
+ IdentLoc))
return nullptr;
DeclContext *LookupContext = computeDeclContext(SS);
NamedDecl *D;
NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context);
- if (!LookupContext) {
+ if (!LookupContext || EllipsisLoc.isValid()) {
if (HasTypenameKeyword) {
// FIXME: not all declaration name kinds are legal here
D = UnresolvedUsingTypenameDecl::Create(Context, CurContext,
UsingLoc, TypenameLoc,
QualifierLoc,
- IdentLoc, NameInfo.getName());
+ IdentLoc, NameInfo.getName(),
+ EllipsisLoc);
} else {
D = UnresolvedUsingValueDecl::Create(Context, CurContext, UsingLoc,
- QualifierLoc, NameInfo);
+ QualifierLoc, NameInfo, EllipsisLoc);
}
D->setAccess(AS);
CurContext->addDecl(D);
@@ -8466,6 +9228,19 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
return UD;
}
+NamedDecl *Sema::BuildUsingPackDecl(NamedDecl *InstantiatedFrom,
+ ArrayRef<NamedDecl *> Expansions) {
+ assert(isa<UnresolvedUsingValueDecl>(InstantiatedFrom) ||
+ isa<UnresolvedUsingTypenameDecl>(InstantiatedFrom) ||
+ isa<UsingPackDecl>(InstantiatedFrom));
+
+ auto *UPD =
+ UsingPackDecl::Create(Context, CurContext, InstantiatedFrom, Expansions);
+ UPD->setAccess(InstantiatedFrom->getAccess());
+ CurContext->addDecl(UPD);
+ return UPD;
+}
+
/// Additional checks for a using declaration referring to a constructor name.
bool Sema::CheckInheritingConstructorUsingDecl(UsingDecl *UD) {
assert(!UD->hasTypename() && "expecting a constructor name");
@@ -8502,6 +9277,8 @@ bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc,
const CXXScopeSpec &SS,
SourceLocation NameLoc,
const LookupResult &Prev) {
+ NestedNameSpecifier *Qual = SS.getScopeRep();
+
// C++03 [namespace.udecl]p8:
// C++0x [namespace.udecl]p10:
// A using-declaration is a declaration and can therefore be used
@@ -8509,10 +9286,28 @@ bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc,
// allowed.
//
// That's in non-member contexts.
- if (!CurContext->getRedeclContext()->isRecord())
+ if (!CurContext->getRedeclContext()->isRecord()) {
+ // A dependent qualifier outside a class can only ever resolve to an
+ // enumeration type. Therefore it conflicts with any other non-type
+ // declaration in the same scope.
+ // FIXME: How should we check for dependent type-type conflicts at block
+ // scope?
+ if (Qual->isDependent() && !HasTypenameKeyword) {
+ for (auto *D : Prev) {
+ if (!isa<TypeDecl>(D) && !isa<UsingDecl>(D) && !isa<UsingPackDecl>(D)) {
+ bool OldCouldBeEnumerator =
+ isa<UnresolvedUsingValueDecl>(D) || isa<EnumConstantDecl>(D);
+ Diag(NameLoc,
+ OldCouldBeEnumerator ? diag::err_redefinition
+ : diag::err_redefinition_different_kind)
+ << Prev.getLookupName();
+ Diag(D->getLocation(), diag::note_previous_definition);
+ return true;
+ }
+ }
+ }
return false;
-
- NestedNameSpecifier *Qual = SS.getScopeRep();
+ }
for (LookupResult::iterator I = Prev.begin(), E = Prev.end(); I != E; ++I) {
NamedDecl *D = *I;
@@ -8556,6 +9351,7 @@ bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc,
/// in the current context is appropriately related to the current
/// scope. If an error is found, diagnoses it and returns true.
bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc,
+ bool HasTypename,
const CXXScopeSpec &SS,
const DeclarationNameInfo &NameInfo,
SourceLocation NameLoc) {
@@ -8566,9 +9362,11 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc,
// C++0x [namespace.udecl]p8:
// A using-declaration for a class member shall be a member-declaration.
- // If we weren't able to compute a valid scope, it must be a
- // dependent class scope.
- if (!NamedContext || NamedContext->getRedeclContext()->isRecord()) {
+ // If we weren't able to compute a valid scope, it might validly be a
+ // dependent class scope or a dependent enumeration unscoped scope. If
+ // we have a 'typename' keyword, the scope must resolve to a class type.
+ if ((HasTypename && !NamedContext) ||
+ (NamedContext && NamedContext->getRedeclContext()->isRecord())) {
auto *RD = NamedContext
? cast<CXXRecordDecl>(NamedContext->getRedeclContext())
: nullptr;
@@ -8628,7 +9426,8 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc,
if (getLangOpts().CPlusPlus11) {
// Convert 'using X::Y;' to 'auto &Y = X::Y;'.
FixIt = FixItHint::CreateReplacement(
- UsingLoc, "constexpr auto " + NameInfo.getName().getAsString() + " = ");
+ UsingLoc,
+ "constexpr auto " + NameInfo.getName().getAsString() + " = ");
}
Diag(UsingLoc, diag::note_using_decl_class_member_workaround)
@@ -8638,7 +9437,7 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc,
return true;
}
- // Otherwise, everything is known to be fine.
+ // Otherwise, this might be valid.
return false;
}
@@ -8683,11 +9482,13 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc,
return true;
}
- Diag(SS.getRange().getBegin(),
- diag::err_using_decl_nested_name_specifier_is_not_base_class)
- << SS.getScopeRep()
- << cast<CXXRecordDecl>(CurContext)
- << SS.getRange();
+ if (!cast<CXXRecordDecl>(NamedContext)->isInvalidDecl()) {
+ Diag(SS.getRange().getBegin(),
+ diag::err_using_decl_nested_name_specifier_is_not_base_class)
+ << SS.getScopeRep()
+ << cast<CXXRecordDecl>(CurContext)
+ << SS.getRange();
+ }
return true;
}
@@ -9493,7 +10294,11 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) {
Scope *S = getScopeForContext(ClassDecl);
CheckImplicitSpecialMemberDeclaration(S, Destructor);
- if (ShouldDeleteSpecialMember(Destructor, CXXDestructor))
+ // We can't check whether an implicit destructor is deleted before we complete
+ // the definition of the class, because its validity depends on the alignment
+ // of the class. We'll check this from ActOnFields once the class is complete.
+ if (ClassDecl->isCompleteDefinition() &&
+ ShouldDeleteSpecialMember(Destructor, CXXDestructor))
SetDeclDeleted(Destructor, ClassLoc);
// Introduce this destructor into its scope.
@@ -9560,7 +10365,7 @@ void Sema::ActOnFinishCXXMemberDecls() {
}
}
-static void getDefaultArgExprsForConstructors(Sema &S, CXXRecordDecl *Class) {
+static void checkDefaultArgExprsForConstructors(Sema &S, CXXRecordDecl *Class) {
// Don't do anything for template patterns.
if (Class->getDescribedClassTemplate())
return;
@@ -9574,7 +10379,7 @@ static void getDefaultArgExprsForConstructors(Sema &S, CXXRecordDecl *Class) {
if (!CD) {
// Recurse on nested classes.
if (auto *NestedRD = dyn_cast<CXXRecordDecl>(Member))
- getDefaultArgExprsForConstructors(S, NestedRD);
+ checkDefaultArgExprsForConstructors(S, NestedRD);
continue;
} else if (!CD->isDefaultConstructor() || !CD->hasAttr<DLLExportAttr>()) {
continue;
@@ -9599,14 +10404,9 @@ static void getDefaultArgExprsForConstructors(Sema &S, CXXRecordDecl *Class) {
LastExportedDefaultCtor = CD;
for (unsigned I = 0; I != NumParams; ++I) {
- // Skip any default arguments that we've already instantiated.
- if (S.Context.getDefaultArgExprForConstructor(CD, I))
- continue;
-
- Expr *DefaultArg = S.BuildCXXDefaultArgExpr(Class->getLocation(), CD,
- CD->getParamDecl(I)).get();
+ (void)S.CheckCXXDefaultArgExpr(Class->getLocation(), CD,
+ CD->getParamDecl(I));
S.DiscardCleanupsInEvaluationContext();
- S.Context.addDefaultArgExprForConstructor(CD, I, DefaultArg);
}
}
}
@@ -9618,7 +10418,7 @@ void Sema::ActOnFinishCXXNonNestedClass(Decl *D) {
// have default arguments or don't use the standard calling convention are
// wrapped with a thunk called the default constructor closure.
if (RD && Context.getTargetInfo().getCXXABI().isMicrosoft())
- getDefaultArgExprsForConstructors(*this, RD);
+ checkDefaultArgExprsForConstructors(*this, RD);
referenceDLLExportedClassMethods();
}
@@ -11506,6 +12306,8 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
DeclInitType->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) &&
"given constructor for wrong type");
MarkFunctionReferenced(ConstructLoc, Constructor);
+ if (getLangOpts().CUDA && !CheckCUDACall(ConstructLoc, Constructor))
+ return ExprError();
return CXXConstructExpr::Create(
Context, DeclInitType, ConstructLoc, Constructor, Elidable,
@@ -11534,13 +12336,20 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) {
// Lookup can return at most two results: the pattern for the field, or the
// injected class name of the parent record. No other member can have the
// same name as the field.
- assert(!Lookup.empty() && Lookup.size() <= 2 &&
+ // In modules mode, lookup can return multiple results (coming from
+ // different modules).
+ assert((getLangOpts().Modules || (!Lookup.empty() && Lookup.size() <= 2)) &&
"more than two lookup results for field name");
FieldDecl *Pattern = dyn_cast<FieldDecl>(Lookup[0]);
if (!Pattern) {
assert(isa<CXXRecordDecl>(Lookup[0]) &&
"cannot have other non-field member with same name");
- Pattern = cast<FieldDecl>(Lookup[1]);
+ for (auto L : Lookup)
+ if (isa<FieldDecl>(L)) {
+ Pattern = cast<FieldDecl>(L);
+ break;
+ }
+ assert(Pattern && "We must have set the Pattern!");
}
if (InstantiateInClassInitializer(Loc, Field, Pattern,
@@ -11564,14 +12373,9 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) {
// constructor before the initializer is lexically complete will ultimately
// come here at which point we can diagnose it.
RecordDecl *OutermostClass = ParentRD->getOuterLexicalRecordContext();
- if (OutermostClass == ParentRD) {
- Diag(Field->getLocEnd(), diag::err_in_class_initializer_not_yet_parsed)
- << ParentRD << Field;
- } else {
- Diag(Field->getLocEnd(),
- diag::err_in_class_initializer_not_yet_parsed_outer_class)
- << ParentRD << OutermostClass << Field;
- }
+ Diag(Loc, diag::err_in_class_initializer_not_yet_parsed)
+ << OutermostClass << Field;
+ Diag(Field->getLocEnd(), diag::note_in_class_initializer_not_yet_parsed);
return ExprError();
}
@@ -11963,6 +12767,9 @@ bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) {
if (FnDecl->isExternC()) {
Diag(FnDecl->getLocation(), diag::err_literal_operator_extern_c);
+ if (const LinkageSpecDecl *LSD =
+ FnDecl->getDeclContext()->getExternCContext())
+ Diag(LSD->getExternLoc(), diag::note_extern_c_begins_here);
return true;
}
@@ -12106,7 +12913,7 @@ bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) {
// Literal suffix identifiers that do not start with an underscore
// are reserved for future standardization.
Diag(FnDecl->getLocation(), diag::warn_user_literal_reserved)
- << NumericLiteralParser::isValidUDSuffix(getLangOpts(), LiteralName);
+ << StringLiteralParser::isValidUDSuffix(getLangOpts(), LiteralName);
}
return false;
@@ -12997,9 +13804,13 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
// and shall be the only declaration of the function or function
// template in the translation unit.
if (functionDeclHasDefaultArgument(FD)) {
- if (FunctionDecl *OldFD = FD->getPreviousDecl()) {
+ // We can't look at FD->getPreviousDecl() because it may not have been set
+ // if we're in a dependent context. If the function is known to be a
+ // redeclaration, we will have narrowed Previous down to the right decl.
+ if (D.isRedeclaration()) {
Diag(FD->getLocation(), diag::err_friend_decl_with_def_arg_redeclared);
- Diag(OldFD->getLocation(), diag::note_previous_declaration);
+ Diag(Previous.getRepresentativeDecl()->getLocation(),
+ diag::note_previous_declaration);
} else if (!D.isFunctionDefinition())
Diag(FD->getLocation(), diag::err_friend_decl_with_def_arg_must_be_def);
}
@@ -13052,7 +13863,7 @@ void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) {
// See if we're deleting a function which is already known to override a
// non-deleted virtual function.
- if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Fn)) {
+ if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Fn)) {
bool IssuedDiagnostic = false;
for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
E = MD->end_overridden_methods();
@@ -13065,6 +13876,11 @@ void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) {
Diag((*I)->getLocation(), diag::note_overridden_virtual_function);
}
}
+ // If this function was implicitly deleted because it was defaulted,
+ // explain why it was deleted.
+ if (IssuedDiagnostic && MD->isDefaulted())
+ ShouldDeleteSpecialMember(MD, getSpecialMember(MD), nullptr,
+ /*Diagnose*/true);
}
// C++11 [basic.start.main]p3:
@@ -13072,6 +13888,9 @@ void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) {
if (Fn->isMain())
Diag(DelLoc, diag::err_deleted_main);
+ // C++11 [dcl.fct.def.delete]p4:
+ // A deleted function is implicitly inline.
+ Fn->setImplicitlyInline();
Fn->setDeletedAsWritten();
}
@@ -13461,6 +14280,8 @@ bool Sema::DefineUsedVTables() {
CXXRecordDecl *Class = VTableUses[I].first->getDefinition();
if (!Class)
continue;
+ TemplateSpecializationKind ClassTSK =
+ Class->getTemplateSpecializationKind();
SourceLocation Loc = VTableUses[I].second;
@@ -13484,9 +14305,8 @@ bool Sema::DefineUsedVTables() {
// of an explicit instantiation declaration, suppress the
// vtable; it will live with the explicit instantiation
// definition.
- bool IsExplicitInstantiationDeclaration
- = Class->getTemplateSpecializationKind()
- == TSK_ExplicitInstantiationDeclaration;
+ bool IsExplicitInstantiationDeclaration =
+ ClassTSK == TSK_ExplicitInstantiationDeclaration;
for (auto R : Class->redecls()) {
TemplateSpecializationKind TSK
= cast<CXXRecordDecl>(R)->getTemplateSpecializationKind();
@@ -13519,17 +14339,20 @@ bool Sema::DefineUsedVTables() {
if (VTablesUsed[Canonical])
Consumer.HandleVTable(Class);
- // Optionally warn if we're emitting a weak vtable.
- if (Class->isExternallyVisible() &&
- Class->getTemplateSpecializationKind() != TSK_ImplicitInstantiation) {
+ // Warn if we're emitting a weak vtable. The vtable will be weak if there is
+ // no key function or the key function is inlined. Don't warn in C++ ABIs
+ // that lack key functions, since the user won't be able to make one.
+ if (Context.getTargetInfo().getCXXABI().hasKeyFunctions() &&
+ Class->isExternallyVisible() && ClassTSK != TSK_ImplicitInstantiation) {
const FunctionDecl *KeyFunctionDef = nullptr;
- if (!KeyFunction ||
- (KeyFunction->hasBody(KeyFunctionDef) &&
- KeyFunctionDef->isInlined()))
- Diag(Class->getLocation(), Class->getTemplateSpecializationKind() ==
- TSK_ExplicitInstantiationDefinition
- ? diag::warn_weak_template_vtable : diag::warn_weak_vtable)
- << Class;
+ if (!KeyFunction || (KeyFunction->hasBody(KeyFunctionDef) &&
+ KeyFunctionDef->isInlined())) {
+ Diag(Class->getLocation(),
+ ClassTSK == TSK_ExplicitInstantiationDefinition
+ ? diag::warn_weak_template_vtable
+ : diag::warn_weak_vtable)
+ << Class;
+ }
}
}
VTableUses.clear();
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index 738de77cecb7..d172c951e749 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -11,22 +11,22 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Sema/SemaInternal.h"
+#include "TypeLocBuilder.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTMutationListener.h"
-#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprObjC.h"
+#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
+#include "clang/Sema/SemaInternal.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
-#include "TypeLocBuilder.h"
using namespace clang;
@@ -209,11 +209,11 @@ bool Sema::CheckARCMethodDecl(ObjCMethodDecl *method) {
if (!Context.hasSameType(method->getReturnType(), Context.VoidTy)) {
SourceRange ResultTypeRange = method->getReturnTypeSourceRange();
if (ResultTypeRange.isInvalid())
- Diag(method->getLocation(), diag::error_dealloc_bad_result_type)
+ Diag(method->getLocation(), diag::err_dealloc_bad_result_type)
<< method->getReturnType()
<< FixItHint::CreateInsertion(method->getSelectorLoc(0), "(void)");
else
- Diag(method->getLocation(), diag::error_dealloc_bad_result_type)
+ Diag(method->getLocation(), diag::err_dealloc_bad_result_type)
<< method->getReturnType()
<< FixItHint::CreateReplacement(ResultTypeRange, "void");
return true;
@@ -1028,6 +1028,7 @@ ActOnStartClassInterface(Scope *S, SourceLocation AtInterfaceLoc,
/// typedef'ed use for a qualified super class and adds them to the list
/// of the protocols.
void Sema::ActOnTypedefedProtocols(SmallVectorImpl<Decl *> &ProtocolRefs,
+ SmallVectorImpl<SourceLocation> &ProtocolLocs,
IdentifierInfo *SuperName,
SourceLocation SuperLoc) {
if (!SuperName)
@@ -1040,8 +1041,14 @@ void Sema::ActOnTypedefedProtocols(SmallVectorImpl<Decl *> &ProtocolRefs,
if (const TypedefNameDecl *TDecl = dyn_cast_or_null<TypedefNameDecl>(IDecl)) {
QualType T = TDecl->getUnderlyingType();
if (T->isObjCObjectType())
- if (const ObjCObjectType *OPT = T->getAs<ObjCObjectType>())
+ if (const ObjCObjectType *OPT = T->getAs<ObjCObjectType>()) {
ProtocolRefs.append(OPT->qual_begin(), OPT->qual_end());
+ // FIXME: Consider whether this should be an invalid loc since the loc
+ // is not actually pointing to a protocol name reference but to the
+ // typedef reference. Note that the base class name loc is also pointing
+ // at the typedef.
+ ProtocolLocs.append(OPT->getNumProtocols(), SuperLoc);
+ }
}
}
@@ -2353,7 +2360,7 @@ static bool CheckMethodOverrideParam(Sema &S,
}
if (S.Context.hasSameUnqualifiedType(ImplTy, IfaceTy))
return true;
-
+
if (!Warn)
return false;
unsigned DiagID =
@@ -2741,7 +2748,7 @@ void Sema::MatchAllMethodDeclarations(const SelectorSet &InsMap,
} else {
ObjCMethodDecl *ImpMethodDecl =
IMPDecl->getInstanceMethod(I->getSelector());
- assert(CDecl->getInstanceMethod(I->getSelector()) &&
+ assert(CDecl->getInstanceMethod(I->getSelector(), true/*AllowHidden*/) &&
"Expected to find the method through lookup as well");
// ImpMethodDecl may be null as in a @dynamic property.
if (ImpMethodDecl) {
@@ -2767,7 +2774,7 @@ void Sema::MatchAllMethodDeclarations(const SelectorSet &InsMap,
} else {
ObjCMethodDecl *ImpMethodDecl =
IMPDecl->getClassMethod(I->getSelector());
- assert(CDecl->getClassMethod(I->getSelector()) &&
+ assert(CDecl->getClassMethod(I->getSelector(), true/*AllowHidden*/) &&
"Expected to find the method through lookup as well");
// ImpMethodDecl may be null as in a @dynamic property.
if (ImpMethodDecl) {
@@ -3217,7 +3224,7 @@ void Sema::addMethodToGlobalList(ObjCMethodList *List,
ObjCMethodList *ListWithSameDeclaration = nullptr;
for (; List; Previous = List, List = List->getNext()) {
// If we are building a module, keep all of the methods.
- if (getLangOpts().CompilingModule)
+ if (getLangOpts().isCompilingModule())
continue;
bool SameDeclaration = MatchTwoMethodDeclarations(Method,
@@ -3853,6 +3860,18 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef<Decl *> allMethods,
Diag(IDecl->getLocation(), diag::err_objc_root_class_subclass);
}
+ if (const ObjCInterfaceDecl *Super = IDecl->getSuperClass()) {
+ // An interface can subclass another interface with a
+ // objc_subclassing_restricted attribute when it has that attribute as
+ // well (because of interfaces imported from Swift). Therefore we have
+ // to check if we can subclass in the implementation as well.
+ if (IDecl->hasAttr<ObjCSubclassingRestrictedAttr>() &&
+ Super->hasAttr<ObjCSubclassingRestrictedAttr>()) {
+ Diag(IC->getLocation(), diag::err_restricted_superclass_mismatch);
+ Diag(Super->getLocation(), diag::note_class_declared);
+ }
+ }
+
if (LangOpts.ObjCRuntime.isNonFragile()) {
while (IDecl->getSuperClass()) {
DiagnoseDuplicateIvars(IDecl, IDecl->getSuperClass());
@@ -3873,6 +3892,14 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef<Decl *> allMethods,
ImplMethodsVsClassMethods(S, CatImplClass, Cat);
}
}
+ } else if (const auto *IntfDecl = dyn_cast<ObjCInterfaceDecl>(ClassDecl)) {
+ if (const ObjCInterfaceDecl *Super = IntfDecl->getSuperClass()) {
+ if (!IntfDecl->hasAttr<ObjCSubclassingRestrictedAttr>() &&
+ Super->hasAttr<ObjCSubclassingRestrictedAttr>()) {
+ Diag(IntfDecl->getLocation(), diag::err_restricted_superclass_mismatch);
+ Diag(Super->getLocation(), diag::note_class_declared);
+ }
+ }
}
if (isInterfaceDeclKind) {
// Reject invalid vardecls.
@@ -4290,7 +4317,7 @@ Decl *Sema::ActOnMethodDeclaration(
bool isVariadic, bool MethodDefinition) {
// Make sure we can establish a context for the method.
if (!CurContext->isObjCContainer()) {
- Diag(MethodLoc, diag::error_missing_method_context);
+ Diag(MethodLoc, diag::err_missing_method_context);
return nullptr;
}
ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
diff --git a/lib/Sema/SemaExceptionSpec.cpp b/lib/Sema/SemaExceptionSpec.cpp
index 4a21eb308fe5..2ac2aca6f660 100644
--- a/lib/Sema/SemaExceptionSpec.cpp
+++ b/lib/Sema/SemaExceptionSpec.cpp
@@ -43,22 +43,36 @@ bool Sema::isLibstdcxxEagerExceptionSpecHack(const Declarator &D) {
auto *RD = dyn_cast<CXXRecordDecl>(CurContext);
// All the problem cases are member functions named "swap" within class
- // templates declared directly within namespace std.
- if (!RD || RD->getEnclosingNamespaceContext() != getStdNamespace() ||
- !RD->getIdentifier() || !RD->getDescribedClassTemplate() ||
+ // templates declared directly within namespace std or std::__debug or
+ // std::__profile.
+ if (!RD || !RD->getIdentifier() || !RD->getDescribedClassTemplate() ||
!D.getIdentifier() || !D.getIdentifier()->isStr("swap"))
return false;
+ auto *ND = dyn_cast<NamespaceDecl>(RD->getDeclContext());
+ if (!ND)
+ return false;
+
+ bool IsInStd = ND->isStdNamespace();
+ if (!IsInStd) {
+ // This isn't a direct member of namespace std, but it might still be
+ // libstdc++'s std::__debug::array or std::__profile::array.
+ IdentifierInfo *II = ND->getIdentifier();
+ if (!II || !(II->isStr("__debug") || II->isStr("__profile")) ||
+ !ND->isInStdNamespace())
+ return false;
+ }
+
// Only apply this hack within a system header.
if (!Context.getSourceManager().isInSystemHeader(D.getLocStart()))
return false;
return llvm::StringSwitch<bool>(RD->getIdentifier()->getName())
.Case("array", true)
- .Case("pair", true)
- .Case("priority_queue", true)
- .Case("stack", true)
- .Case("queue", true)
+ .Case("pair", IsInStd)
+ .Case("priority_queue", IsInStd)
+ .Case("stack", IsInStd)
+ .Case("queue", IsInStd)
.Default(false);
}
@@ -129,6 +143,11 @@ bool Sema::CheckSpecifiedExceptionType(QualType &T, SourceRange Range) {
/// to member to a function with an exception specification. This means that
/// it is invalid to add another level of indirection.
bool Sema::CheckDistantExceptionSpec(QualType T) {
+ // C++17 removes this rule in favor of putting exception specifications into
+ // the type system.
+ if (getLangOpts().CPlusPlus1z)
+ return false;
+
if (const PointerType *PT = T->getAs<PointerType>())
T = PT->getPointeeType();
else if (const MemberPointerType *PT = T->getAs<MemberPointerType>())
@@ -188,6 +207,14 @@ Sema::UpdateExceptionSpec(FunctionDecl *FD,
Context.adjustExceptionSpec(cast<FunctionDecl>(Redecl), ESI);
}
+static bool CheckEquivalentExceptionSpecImpl(
+ Sema &S, const PartialDiagnostic &DiagID, const PartialDiagnostic &NoteID,
+ const FunctionProtoType *Old, SourceLocation OldLoc,
+ const FunctionProtoType *New, SourceLocation NewLoc,
+ bool *MissingExceptionSpecification = nullptr,
+ bool *MissingEmptyExceptionSpecification = nullptr,
+ bool AllowNoexceptAllMatchWithNoSpec = false, bool IsOperatorNew = false);
+
/// Determine whether a function has an implicitly-generated exception
/// specification.
static bool hasImplicitExceptionSpec(FunctionDecl *Decl) {
@@ -210,6 +237,12 @@ static bool hasImplicitExceptionSpec(FunctionDecl *Decl) {
}
bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
+ // Just completely ignore this under -fno-exceptions prior to C++1z.
+ // In C++1z onwards, the exception specification is part of the type and
+ // we will diagnose mismatches anyway, so it's better to check for them here.
+ if (!getLangOpts().CXXExceptions && !getLangOpts().CPlusPlus1z)
+ return false;
+
OverloadedOperatorKind OO = New->getDeclName().getCXXOverloadedOperator();
bool IsOperatorNew = OO == OO_New || OO == OO_Array_New;
bool MissingExceptionSpecification = false;
@@ -224,8 +257,8 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
// Check the types as written: they must match before any exception
// specification adjustment is applied.
- if (!CheckEquivalentExceptionSpec(
- PDiag(DiagID), PDiag(diag::note_previous_declaration),
+ if (!CheckEquivalentExceptionSpecImpl(
+ *this, PDiag(DiagID), PDiag(diag::note_previous_declaration),
Old->getType()->getAs<FunctionProtoType>(), Old->getLocation(),
New->getType()->getAs<FunctionProtoType>(), New->getLocation(),
&MissingExceptionSpecification, &MissingEmptyExceptionSpecification,
@@ -234,7 +267,7 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
// If a declaration of a function has an implicit
// exception-specification, other declarations of the function shall
// not specify an exception-specification.
- if (getLangOpts().CPlusPlus11 &&
+ if (getLangOpts().CPlusPlus11 && getLangOpts().CXXExceptions &&
hasImplicitExceptionSpec(Old) != hasImplicitExceptionSpec(New)) {
Diag(New->getLocation(), diag::ext_implicit_exception_spec_mismatch)
<< hasImplicitExceptionSpec(Old);
@@ -255,14 +288,15 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
// The new function declaration is only missing an empty exception
// specification "throw()". If the throw() specification came from a
// function in a system header that has C linkage, just add an empty
- // exception specification to the "new" declaration. This is an
- // egregious workaround for glibc, which adds throw() specifications
- // to many libc functions as an optimization. Unfortunately, that
- // optimization isn't permitted by the C++ standard, so we're forced
- // to work around it here.
+ // exception specification to the "new" declaration. Note that C library
+ // implementations are permitted to add these nothrow exception
+ // specifications.
+ //
+ // Likewise if the old function is a builtin.
if (MissingEmptyExceptionSpecification && NewProto &&
(Old->getLocation().isInvalid() ||
- Context.getSourceManager().isInSystemHeader(Old->getLocation())) &&
+ Context.getSourceManager().isInSystemHeader(Old->getLocation()) ||
+ Old->getBuiltinID()) &&
Old->isExternC()) {
New->setType(Context.getFunctionType(
NewProto->getReturnType(), NewProto->getParamTypes(),
@@ -376,11 +410,15 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
bool Sema::CheckEquivalentExceptionSpec(
const FunctionProtoType *Old, SourceLocation OldLoc,
const FunctionProtoType *New, SourceLocation NewLoc) {
+ if (!getLangOpts().CXXExceptions)
+ return false;
+
unsigned DiagID = diag::err_mismatched_exception_spec;
if (getLangOpts().MicrosoftExt)
DiagID = diag::ext_mismatched_exception_spec;
- bool Result = CheckEquivalentExceptionSpec(PDiag(DiagID),
- PDiag(diag::note_previous_declaration), Old, OldLoc, New, NewLoc);
+ bool Result = CheckEquivalentExceptionSpecImpl(
+ *this, PDiag(DiagID), PDiag(diag::note_previous_declaration),
+ Old, OldLoc, New, NewLoc);
// In Microsoft mode, mismatching exception specifications just cause a warning.
if (getLangOpts().MicrosoftExt)
@@ -394,30 +432,23 @@ bool Sema::CheckEquivalentExceptionSpec(
/// \return \c false if the exception specifications match, \c true if there is
/// a problem. If \c true is returned, either a diagnostic has already been
/// produced or \c *MissingExceptionSpecification is set to \c true.
-bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,
- const PartialDiagnostic & NoteID,
- const FunctionProtoType *Old,
- SourceLocation OldLoc,
- const FunctionProtoType *New,
- SourceLocation NewLoc,
- bool *MissingExceptionSpecification,
- bool*MissingEmptyExceptionSpecification,
- bool AllowNoexceptAllMatchWithNoSpec,
- bool IsOperatorNew) {
- // Just completely ignore this under -fno-exceptions.
- if (!getLangOpts().CXXExceptions)
- return false;
-
+static bool CheckEquivalentExceptionSpecImpl(
+ Sema &S, const PartialDiagnostic &DiagID, const PartialDiagnostic &NoteID,
+ const FunctionProtoType *Old, SourceLocation OldLoc,
+ const FunctionProtoType *New, SourceLocation NewLoc,
+ bool *MissingExceptionSpecification,
+ bool *MissingEmptyExceptionSpecification,
+ bool AllowNoexceptAllMatchWithNoSpec, bool IsOperatorNew) {
if (MissingExceptionSpecification)
*MissingExceptionSpecification = false;
if (MissingEmptyExceptionSpecification)
*MissingEmptyExceptionSpecification = false;
- Old = ResolveExceptionSpec(NewLoc, Old);
+ Old = S.ResolveExceptionSpec(NewLoc, Old);
if (!Old)
return false;
- New = ResolveExceptionSpec(NewLoc, New);
+ New = S.ResolveExceptionSpec(NewLoc, New);
if (!New)
return false;
@@ -451,8 +482,8 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,
if (OldEST == EST_None && NewEST == EST_None)
return false;
- FunctionProtoType::NoexceptResult OldNR = Old->getNoexceptSpec(Context);
- FunctionProtoType::NoexceptResult NewNR = New->getNoexceptSpec(Context);
+ FunctionProtoType::NoexceptResult OldNR = Old->getNoexceptSpec(S.Context);
+ FunctionProtoType::NoexceptResult NewNR = New->getNoexceptSpec(S.Context);
if (OldNR == FunctionProtoType::NR_BadNoexcept ||
NewNR == FunctionProtoType::NR_BadNoexcept)
return false;
@@ -467,9 +498,9 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,
if (OldNR != NewNR &&
OldNR != FunctionProtoType::NR_NoNoexcept &&
NewNR != FunctionProtoType::NR_NoNoexcept) {
- Diag(NewLoc, DiagID);
+ S.Diag(NewLoc, DiagID);
if (NoteID.getDiagID() != 0 && OldLoc.isValid())
- Diag(OldLoc, NoteID);
+ S.Diag(OldLoc, NoteID);
return true;
}
@@ -507,7 +538,7 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,
// 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.
- if (getLangOpts().CPlusPlus11 && IsOperatorNew) {
+ if (S.getLangOpts().CPlusPlus11 && IsOperatorNew) {
const FunctionProtoType *WithExceptions = nullptr;
if (OldEST == EST_None && NewEST == EST_Dynamic)
WithExceptions = New;
@@ -548,9 +579,9 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,
return true;
}
- Diag(NewLoc, DiagID);
+ S.Diag(NewLoc, DiagID);
if (NoteID.getDiagID() != 0 && OldLoc.isValid())
- Diag(OldLoc, NoteID);
+ S.Diag(OldLoc, NoteID);
return true;
}
@@ -562,11 +593,11 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,
// to the second.
llvm::SmallPtrSet<CanQualType, 8> OldTypes, NewTypes;
for (const auto &I : Old->exceptions())
- OldTypes.insert(Context.getCanonicalType(I).getUnqualifiedType());
+ OldTypes.insert(S.Context.getCanonicalType(I).getUnqualifiedType());
for (const auto &I : New->exceptions()) {
- CanQualType TypePtr = Context.getCanonicalType(I).getUnqualifiedType();
- if(OldTypes.count(TypePtr))
+ CanQualType TypePtr = S.Context.getCanonicalType(I).getUnqualifiedType();
+ if (OldTypes.count(TypePtr))
NewTypes.insert(TypePtr);
else
Success = false;
@@ -577,19 +608,34 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,
if (Success) {
return false;
}
- Diag(NewLoc, DiagID);
+ S.Diag(NewLoc, DiagID);
if (NoteID.getDiagID() != 0 && OldLoc.isValid())
- Diag(OldLoc, NoteID);
+ S.Diag(OldLoc, NoteID);
return true;
}
+bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,
+ const PartialDiagnostic &NoteID,
+ const FunctionProtoType *Old,
+ SourceLocation OldLoc,
+ const FunctionProtoType *New,
+ SourceLocation NewLoc) {
+ if (!getLangOpts().CXXExceptions)
+ return false;
+ return CheckEquivalentExceptionSpecImpl(*this, DiagID, NoteID, Old, OldLoc,
+ New, NewLoc);
+}
+
/// 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.
-bool Sema::CheckExceptionSpecSubset(
- const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID,
- const FunctionProtoType *Superset, SourceLocation SuperLoc,
- const FunctionProtoType *Subset, SourceLocation SubLoc) {
+bool Sema::CheckExceptionSpecSubset(const PartialDiagnostic &DiagID,
+ const PartialDiagnostic &NestedDiagID,
+ const PartialDiagnostic &NoteID,
+ const FunctionProtoType *Superset,
+ SourceLocation SuperLoc,
+ const FunctionProtoType *Subset,
+ SourceLocation SubLoc) {
// Just auto-succeed under -fno-exceptions.
if (!getLangOpts().CXXExceptions)
@@ -613,7 +659,8 @@ bool Sema::CheckExceptionSpecSubset(
// If superset contains everything, we're done.
if (SuperEST == EST_None || SuperEST == EST_MSAny)
- return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc);
+ 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
@@ -628,7 +675,8 @@ bool Sema::CheckExceptionSpecSubset(
// Another case of the superset containing everything.
if (SuperNR == FunctionProtoType::NR_Throw)
- return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc);
+ return CheckParamExceptionSpec(NestedDiagID, NoteID, Superset, SuperLoc,
+ Subset, SubLoc);
ExceptionSpecificationType SubEST = Subset->getExceptionSpecType();
@@ -659,7 +707,8 @@ bool Sema::CheckExceptionSpecSubset(
// If the subset contains nothing, we're done.
if (SubEST == EST_DynamicNone || SubNR == FunctionProtoType::NR_Nothrow)
- return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc);
+ 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) {
@@ -751,14 +800,15 @@ bool Sema::CheckExceptionSpecSubset(
}
}
// We've run half the gauntlet.
- return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc);
+ return CheckParamExceptionSpec(NestedDiagID, NoteID, Superset, SuperLoc,
+ Subset, SubLoc);
}
-static bool CheckSpecForTypesEquivalent(Sema &S,
- const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID,
- QualType Target, SourceLocation TargetLoc,
- QualType Source, SourceLocation SourceLoc)
-{
+static bool
+CheckSpecForTypesEquivalent(Sema &S, const PartialDiagnostic &DiagID,
+ const PartialDiagnostic &NoteID, QualType Target,
+ SourceLocation TargetLoc, QualType Source,
+ SourceLocation SourceLoc) {
const FunctionProtoType *TFunc = GetUnderlyingFunction(Target);
if (!TFunc)
return false;
@@ -775,13 +825,16 @@ static bool CheckSpecForTypesEquivalent(Sema &S,
/// assignment and override compatibility check. We do not check the parameters
/// of parameter function pointers recursively, as no sane programmer would
/// even be able to write such a function type.
-bool Sema::CheckParamExceptionSpec(const PartialDiagnostic &NoteID,
+bool Sema::CheckParamExceptionSpec(const PartialDiagnostic &DiagID,
+ const PartialDiagnostic &NoteID,
const FunctionProtoType *Target,
SourceLocation TargetLoc,
const FunctionProtoType *Source,
SourceLocation SourceLoc) {
+ auto RetDiag = DiagID;
+ RetDiag << 0;
if (CheckSpecForTypesEquivalent(
- *this, PDiag(diag::err_deep_exception_specs_differ) << 0, PDiag(),
+ *this, RetDiag, PDiag(),
Target->getReturnType(), TargetLoc, Source->getReturnType(),
SourceLoc))
return true;
@@ -791,8 +844,10 @@ bool Sema::CheckParamExceptionSpec(const PartialDiagnostic &NoteID,
assert(Target->getNumParams() == Source->getNumParams() &&
"Functions have different argument counts.");
for (unsigned i = 0, E = Target->getNumParams(); i != E; ++i) {
+ auto ParamDiag = DiagID;
+ ParamDiag << 1;
if (CheckSpecForTypesEquivalent(
- *this, PDiag(diag::err_deep_exception_specs_differ) << 1, PDiag(),
+ *this, ParamDiag, PDiag(),
Target->getParamType(i), TargetLoc, Source->getParamType(i),
SourceLoc))
return true;
@@ -812,6 +867,16 @@ bool Sema::CheckExceptionSpecCompatibility(Expr *From, QualType ToType) {
if (!FromFunc || FromFunc->hasDependentExceptionSpec())
return false;
+ unsigned DiagID = diag::err_incompatible_exception_specs;
+ unsigned NestedDiagID = diag::err_deep_exception_specs_differ;
+ // This is not an error in C++17 onwards, unless the noexceptness doesn't
+ // match, but in that case we have a full-on type mismatch, not just a
+ // type sugar mismatch.
+ if (getLangOpts().CPlusPlus1z) {
+ DiagID = diag::warn_incompatible_exception_specs;
+ NestedDiagID = diag::warn_deep_exception_specs_differ;
+ }
+
// Now we've got the correct types on both sides, check their compatibility.
// This means that the source of the conversion can only throw a subset of
// the exceptions of the target, and any exception specs on arguments or
@@ -824,10 +889,10 @@ bool Sema::CheckExceptionSpecCompatibility(Expr *From, QualType ToType) {
// void (*q)(void (*) throw(int)) = p;
// }
// ... because it might be instantiated with T=int.
- return CheckExceptionSpecSubset(PDiag(diag::err_incompatible_exception_specs),
- PDiag(), ToFunc,
- From->getSourceRange().getBegin(),
- FromFunc, SourceLocation());
+ return CheckExceptionSpecSubset(PDiag(DiagID), PDiag(NestedDiagID), PDiag(),
+ ToFunc, From->getSourceRange().getBegin(),
+ FromFunc, SourceLocation()) &&
+ !getLangOpts().CPlusPlus1z;
}
bool Sema::CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New,
@@ -861,6 +926,7 @@ bool Sema::CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New,
if (getLangOpts().MicrosoftExt)
DiagID = diag::ext_override_exception_spec;
return CheckExceptionSpecSubset(PDiag(DiagID),
+ PDiag(diag::err_deep_exception_specs_differ),
PDiag(diag::note_overridden_virtual_function),
Old->getType()->getAs<FunctionProtoType>(),
Old->getLocation(),
@@ -879,19 +945,37 @@ static CanThrowResult canSubExprsThrow(Sema &S, const Expr *E) {
}
static CanThrowResult canCalleeThrow(Sema &S, const Expr *E, const Decl *D) {
- assert(D && "Expected decl");
-
- // See if we can get a function type from the decl somehow.
- const ValueDecl *VD = dyn_cast<ValueDecl>(D);
- if (!VD) // If we have no clue what we're calling, assume the worst.
- return CT_Can;
-
// As an extension, we assume that __attribute__((nothrow)) functions don't
// throw.
- if (isa<FunctionDecl>(D) && D->hasAttr<NoThrowAttr>())
+ if (D && isa<FunctionDecl>(D) && D->hasAttr<NoThrowAttr>())
return CT_Cannot;
- QualType T = VD->getType();
+ QualType T;
+
+ // In C++1z, just look at the function type of the callee.
+ if (S.getLangOpts().CPlusPlus1z && isa<CallExpr>(E)) {
+ E = cast<CallExpr>(E)->getCallee();
+ T = E->getType();
+ if (T->isSpecificPlaceholderType(BuiltinType::BoundMember)) {
+ // Sadly we don't preserve the actual type as part of the "bound member"
+ // placeholder, so we need to reconstruct it.
+ E = E->IgnoreParenImpCasts();
+
+ // Could be a call to a pointer-to-member or a plain member access.
+ if (auto *Op = dyn_cast<BinaryOperator>(E)) {
+ assert(Op->getOpcode() == BO_PtrMemD || Op->getOpcode() == BO_PtrMemI);
+ T = Op->getRHS()->getType()
+ ->castAs<MemberPointerType>()->getPointeeType();
+ } else {
+ T = cast<MemberExpr>(E)->getMemberDecl()->getType();
+ }
+ }
+ } else if (const ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D))
+ T = VD->getType();
+ else
+ // If we have no clue what we're calling, assume the worst.
+ return CT_Can;
+
const FunctionProtoType *FT;
if ((FT = T->getAs<FunctionProtoType>())) {
} else if (const PointerType *PT = T->getAs<PointerType>())
@@ -983,10 +1067,8 @@ CanThrowResult Sema::canThrow(const Expr *E) {
CT = CT_Dependent;
else if (isa<CXXPseudoDestructorExpr>(CE->getCallee()->IgnoreParens()))
CT = CT_Cannot;
- else if (CE->getCalleeDecl())
- CT = canCalleeThrow(*this, E, CE->getCalleeDecl());
else
- CT = CT_Can;
+ CT = canCalleeThrow(*this, E, CE->getCalleeDecl());
if (CT == CT_Can)
return CT;
return mergeCanThrow(CT, canSubExprsThrow(*this, E));
@@ -1085,6 +1167,7 @@ CanThrowResult Sema::canThrow(const Expr *E) {
case Expr::ExprWithCleanupsClass:
case Expr::ExtVectorElementExprClass:
case Expr::InitListExprClass:
+ case Expr::ArrayInitLoopExprClass:
case Expr::MemberExprClass:
case Expr::ObjCIsaExprClass:
case Expr::ObjCIvarRefExprClass:
@@ -1178,6 +1261,7 @@ CanThrowResult Sema::canThrow(const Expr *E) {
case Expr::ImaginaryLiteralClass:
case Expr::ImplicitValueInitExprClass:
case Expr::IntegerLiteralClass:
+ case Expr::ArrayInitIndexExprClass:
case Expr::NoInitExprClass:
case Expr::ObjCEncodeExprClass:
case Expr::ObjCStringLiteralClass:
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 719e1e3502ca..3c554c9a5244 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -11,7 +11,6 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Sema/SemaInternal.h"
#include "TreeTransform.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
@@ -42,6 +41,7 @@
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaFixItUtils.h"
+#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Template.h"
#include "llvm/Support/ConvertUTF.h"
using namespace clang;
@@ -103,13 +103,9 @@ static bool HasRedeclarationWithoutAvailabilityInCategory(const Decl *D) {
return false;
}
-static AvailabilityResult
-DiagnoseAvailabilityOfDecl(Sema &S, NamedDecl *D, SourceLocation Loc,
- const ObjCInterfaceDecl *UnknownObjCClass,
- bool ObjCPropertyAccess) {
- // See if this declaration is unavailable or deprecated.
- std::string Message;
- AvailabilityResult Result = D->getAvailability(&Message);
+AvailabilityResult
+Sema::ShouldDiagnoseAvailabilityOfDecl(NamedDecl *&D, std::string *Message) {
+ AvailabilityResult Result = D->getAvailability(Message);
// For typedefs, if the typedef declaration appears available look
// to the underlying type to see if it is more restrictive.
@@ -117,18 +113,18 @@ DiagnoseAvailabilityOfDecl(Sema &S, NamedDecl *D, SourceLocation Loc,
if (Result == AR_Available) {
if (const TagType *TT = TD->getUnderlyingType()->getAs<TagType>()) {
D = TT->getDecl();
- Result = D->getAvailability(&Message);
+ Result = D->getAvailability(Message);
continue;
}
}
break;
}
-
+
// Forward class declarations get their attributes from their definition.
if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(D)) {
if (IDecl->getDefinition()) {
D = IDecl->getDefinition();
- Result = D->getAvailability(&Message);
+ Result = D->getAvailability(Message);
}
}
@@ -136,12 +132,51 @@ DiagnoseAvailabilityOfDecl(Sema &S, NamedDecl *D, SourceLocation Loc,
if (Result == AR_Available) {
const DeclContext *DC = ECD->getDeclContext();
if (const EnumDecl *TheEnumDecl = dyn_cast<EnumDecl>(DC))
- Result = TheEnumDecl->getAvailability(&Message);
+ Result = TheEnumDecl->getAvailability(Message);
+ }
+
+ if (Result == AR_NotYetIntroduced) {
+ // Don't do this for enums, they can't be redeclared.
+ if (isa<EnumConstantDecl>(D) || isa<EnumDecl>(D))
+ return AR_Available;
+
+ bool Warn = !D->getAttr<AvailabilityAttr>()->isInherited();
+ // Objective-C method declarations in categories are not modelled as
+ // redeclarations, so manually look for a redeclaration in a category
+ // if necessary.
+ if (Warn && HasRedeclarationWithoutAvailabilityInCategory(D))
+ Warn = false;
+ // In general, D will point to the most recent redeclaration. However,
+ // for `@class A;` decls, this isn't true -- manually go through the
+ // redecl chain in that case.
+ if (Warn && isa<ObjCInterfaceDecl>(D))
+ for (Decl *Redecl = D->getMostRecentDecl(); Redecl && Warn;
+ Redecl = Redecl->getPreviousDecl())
+ if (!Redecl->hasAttr<AvailabilityAttr>() ||
+ Redecl->getAttr<AvailabilityAttr>()->isInherited())
+ Warn = false;
+
+ return Warn ? AR_NotYetIntroduced : AR_Available;
+ }
+
+ return Result;
+}
+
+static void
+DiagnoseAvailabilityOfDecl(Sema &S, NamedDecl *D, SourceLocation Loc,
+ const ObjCInterfaceDecl *UnknownObjCClass,
+ bool ObjCPropertyAccess) {
+ std::string Message;
+ // See if this declaration is unavailable, deprecated, or partial.
+ if (AvailabilityResult Result =
+ S.ShouldDiagnoseAvailabilityOfDecl(D, &Message)) {
+
+ if (Result == AR_NotYetIntroduced && S.getCurFunctionOrMethodDecl()) {
+ S.getEnclosingFunction()->HasPotentialAvailabilityViolations = true;
+ return;
}
- const ObjCPropertyDecl *ObjCPDecl = nullptr;
- if (Result == AR_Deprecated || Result == AR_Unavailable ||
- Result == AR_NotYetIntroduced) {
+ const ObjCPropertyDecl *ObjCPDecl = nullptr;
if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
if (const ObjCPropertyDecl *PD = MD->findPropertyDecl()) {
AvailabilityResult PDeclResult = PD->getAvailability(nullptr);
@@ -149,56 +184,10 @@ DiagnoseAvailabilityOfDecl(Sema &S, NamedDecl *D, SourceLocation Loc,
ObjCPDecl = PD;
}
}
- }
-
- switch (Result) {
- case AR_Available:
- break;
-
- case AR_Deprecated:
- if (S.getCurContextAvailability() != AR_Deprecated)
- S.EmitAvailabilityWarning(Sema::AD_Deprecation,
- D, Message, Loc, UnknownObjCClass, ObjCPDecl,
- ObjCPropertyAccess);
- break;
-
- case AR_NotYetIntroduced: {
- // Don't do this for enums, they can't be redeclared.
- if (isa<EnumConstantDecl>(D) || isa<EnumDecl>(D))
- break;
-
- bool Warn = !D->getAttr<AvailabilityAttr>()->isInherited();
- // Objective-C method declarations in categories are not modelled as
- // redeclarations, so manually look for a redeclaration in a category
- // if necessary.
- if (Warn && HasRedeclarationWithoutAvailabilityInCategory(D))
- Warn = false;
- // In general, D will point to the most recent redeclaration. However,
- // for `@class A;` decls, this isn't true -- manually go through the
- // redecl chain in that case.
- if (Warn && isa<ObjCInterfaceDecl>(D))
- for (Decl *Redecl = D->getMostRecentDecl(); Redecl && Warn;
- Redecl = Redecl->getPreviousDecl())
- if (!Redecl->hasAttr<AvailabilityAttr>() ||
- Redecl->getAttr<AvailabilityAttr>()->isInherited())
- Warn = false;
-
- if (Warn)
- S.EmitAvailabilityWarning(Sema::AD_Partial, D, Message, Loc,
- UnknownObjCClass, ObjCPDecl,
- ObjCPropertyAccess);
- break;
- }
- case AR_Unavailable:
- if (S.getCurContextAvailability() != AR_Unavailable)
- S.EmitAvailabilityWarning(Sema::AD_Unavailable,
- D, Message, Loc, UnknownObjCClass, ObjCPDecl,
- ObjCPropertyAccess);
- break;
-
- }
- return Result;
+ S.EmitAvailabilityWarning(Result, D, Message, Loc, UnknownObjCClass,
+ ObjCPDecl, ObjCPropertyAccess);
+ }
}
/// \brief Emit a note explaining that this function is deleted.
@@ -340,10 +329,15 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
// See if this is an auto-typed variable whose initializer we are parsing.
if (ParsingInitForAutoVars.count(D)) {
- const AutoType *AT = cast<VarDecl>(D)->getType()->getContainedAutoType();
+ if (isa<BindingDecl>(D)) {
+ Diag(Loc, diag::err_binding_cannot_appear_in_own_initializer)
+ << D->getDeclName();
+ } else {
+ const AutoType *AT = cast<VarDecl>(D)->getType()->getContainedAutoType();
- Diag(Loc, diag::err_auto_variable_cannot_appear_in_own_initializer)
- << D->getDeclName() << (unsigned)AT->getKeyword();
+ Diag(Loc, diag::err_auto_variable_cannot_appear_in_own_initializer)
+ << D->getDeclName() << (unsigned)AT->getKeyword();
+ }
return true;
}
@@ -366,6 +360,9 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
if (getLangOpts().CPlusPlus14 && FD->getReturnType()->isUndeducedType() &&
DeduceReturnType(FD, Loc))
return true;
+
+ if (getLangOpts().CUDA && !CheckCUDACall(Loc, FD))
+ return true;
}
// [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions
@@ -660,7 +657,7 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) {
return E;
// OpenCL usually rejects direct accesses to values of 'half' type.
- if (getLangOpts().OpenCL && !getOpenCLOptions().cl_khr_fp16 &&
+ if (getLangOpts().OpenCL && !getOpenCLOptions().isEnabled("cl_khr_fp16") &&
T->isHalfType()) {
Diag(E->getExprLoc(), diag::err_opencl_half_load_store)
<< 0 << T;
@@ -820,8 +817,16 @@ ExprResult Sema::DefaultArgumentPromotion(Expr *E) {
// double.
const BuiltinType *BTy = Ty->getAs<BuiltinType>();
if (BTy && (BTy->getKind() == BuiltinType::Half ||
- BTy->getKind() == BuiltinType::Float))
- E = ImpCastExprToType(E, Context.DoubleTy, CK_FloatingCast).get();
+ BTy->getKind() == BuiltinType::Float)) {
+ if (getLangOpts().OpenCL &&
+ !getOpenCLOptions().isEnabled("cl_khr_fp64")) {
+ if (BTy->getKind() == BuiltinType::Half) {
+ E = ImpCastExprToType(E, Context.FloatTy, CK_FloatingCast).get();
+ }
+ } else {
+ E = ImpCastExprToType(E, Context.DoubleTy, CK_FloatingCast).get();
+ }
+ }
// C++ performs lvalue-to-rvalue conversion as a default argument
// promotion, even on class types, but note:
@@ -1189,7 +1194,7 @@ static bool unsupportedTypeConversion(const Sema &S, QualType LHSType,
*/
return Float128AndLongDouble &&
(&S.Context.getFloatTypeSemantics(S.Context.LongDoubleTy) !=
- &llvm::APFloat::IEEEdouble);
+ &llvm::APFloat::IEEEdouble());
}
typedef ExprResult PerformCastFn(Sema &S, Expr *operand, QualType toType);
@@ -1735,19 +1740,6 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
const DeclarationNameInfo &NameInfo,
const CXXScopeSpec *SS, NamedDecl *FoundD,
const TemplateArgumentListInfo *TemplateArgs) {
- if (getLangOpts().CUDA)
- if (const FunctionDecl *Caller = dyn_cast<FunctionDecl>(CurContext))
- if (const FunctionDecl *Callee = dyn_cast<FunctionDecl>(D)) {
- if (CheckCUDATarget(Caller, Callee)) {
- Diag(NameInfo.getLoc(), diag::err_ref_bad_target)
- << IdentifyCUDATarget(Callee) << D->getIdentifier()
- << IdentifyCUDATarget(Caller);
- Diag(D->getLocation(), diag::note_previous_decl)
- << D->getIdentifier();
- return ExprError();
- }
- }
-
bool RefersToCapturedVariable =
isa<VarDecl>(D) &&
NeedToCaptureVariable(cast<VarDecl>(D), NameInfo.getLoc());
@@ -1785,6 +1777,12 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
E->setObjectKind(OK_BitField);
}
+ // C++ [expr.prim]/8: The expression [...] is a bit-field if the identifier
+ // designates a bit-field.
+ if (auto *BD = dyn_cast<BindingDecl>(D))
+ if (auto *BE = BD->getBinding())
+ E->setObjectKind(BE->getObjectKind());
+
return E;
}
@@ -2462,7 +2460,7 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
if (IFace && (IV = IFace->lookupInstanceVariable(II, ClassDeclared))) {
// Diagnose using an ivar in a class method.
if (IsClassMethod)
- return ExprError(Diag(Loc, diag::error_ivar_use_in_class_method)
+ return ExprError(Diag(Loc, diag::err_ivar_use_in_class_method)
<< IV->getDeclName());
// If we're referencing an invalid decl, just return this as a silent
@@ -2478,7 +2476,7 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
if (IV->getAccessControl() == ObjCIvarDecl::Private &&
!declaresSameEntity(ClassDeclared, IFace) &&
!getLangOpts().DebuggerSupport)
- Diag(Loc, diag::error_private_ivar_access) << IV->getDeclName();
+ Diag(Loc, diag::err_private_ivar_access) << IV->getDeclName();
// FIXME: This should use a new expr for a direct reference, don't
// turn this into Self->ivar, just return a BareIVarExpr or something.
@@ -2534,7 +2532,7 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod()) {
// If accessing a stand-alone ivar in a class method, this is an error.
if (const ObjCIvarDecl *IV = dyn_cast<ObjCIvarDecl>(Lookup.getFoundDecl()))
- return ExprError(Diag(Loc, diag::error_ivar_use_in_class_method)
+ return ExprError(Diag(Loc, diag::err_ivar_use_in_class_method)
<< IV->getDeclName());
}
@@ -2829,6 +2827,10 @@ ExprResult Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
return ULE;
}
+static void
+diagnoseUncapturableValueReference(Sema &S, SourceLocation loc,
+ ValueDecl *var, DeclContext *DC);
+
/// \brief Complete semantic analysis for a reference to the given declaration.
ExprResult Sema::BuildDeclarationNameExpr(
const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, NamedDecl *D,
@@ -2881,6 +2883,14 @@ ExprResult Sema::BuildDeclarationNameExpr(
{
QualType type = VD->getType();
+ if (auto *FPT = type->getAs<FunctionProtoType>()) {
+ // C++ [except.spec]p17:
+ // An exception-specification is considered to be needed when:
+ // - in an expression, the function is the unique lookup result or
+ // the selected member of a set of overloaded functions.
+ ResolveExceptionSpec(Loc, FPT);
+ type = VD->getType();
+ }
ExprValueKind valueKind = VK_RValue;
switch (D->getKind()) {
@@ -2939,6 +2949,7 @@ ExprResult Sema::BuildDeclarationNameExpr(
case Decl::Var:
case Decl::VarTemplateSpecialization:
case Decl::VarTemplatePartialSpecialization:
+ case Decl::Decomposition:
case Decl::OMPCapturedExpr:
// In C, "extern void blah;" is valid and is an r-value.
if (!getLangOpts().CPlusPlus &&
@@ -2966,6 +2977,19 @@ ExprResult Sema::BuildDeclarationNameExpr(
break;
}
+
+ case Decl::Binding: {
+ // These are always lvalues.
+ valueKind = VK_LValue;
+ type = type.getNonReferenceType();
+ // FIXME: Support lambda-capture of BindingDecls, once CWG actually
+ // decides how that's supposed to work.
+ auto *BD = cast<BindingDecl>(VD);
+ if (BD->getDeclContext()->isFunctionOrMethod() &&
+ BD->getDeclContext() != CurContext)
+ diagnoseUncapturableValueReference(*this, Loc, BD, CurContext);
+ break;
+ }
case Decl::Function: {
if (unsigned BID = cast<FunctionDecl>(VD)->getBuiltinID()) {
@@ -3046,8 +3070,9 @@ static void ConvertUTF8ToWideString(unsigned CharByteWidth, StringRef Source,
SmallString<32> &Target) {
Target.resize(CharByteWidth * (Source.size() + 1));
char *ResultPtr = &Target[0];
- const UTF8 *ErrorPtr;
- bool success = ConvertUTF8toWide(CharByteWidth, Source, ResultPtr, ErrorPtr);
+ const llvm::UTF8 *ErrorPtr;
+ bool success =
+ llvm::ConvertUTF8toWide(CharByteWidth, Source, ResultPtr, ErrorPtr);
(void)success;
assert(success);
Target.resize(ResultPtr - &Target[0]);
@@ -3361,7 +3386,7 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
if (Literal.isFloatingLiteral()) {
QualType Ty;
if (Literal.isHalf){
- if (getOpenCLOptions().cl_khr_fp16)
+ if (getOpenCLOptions().isEnabled("cl_khr_fp16"))
Ty = Context.HalfTy;
else {
Diag(Tok.getLocation(), diag::err_half_const_requires_fp16);
@@ -3380,10 +3405,13 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
if (Ty == Context.DoubleTy) {
if (getLangOpts().SinglePrecisionConstants) {
- Res = ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast).get();
+ const BuiltinType *BTy = Ty->getAs<BuiltinType>();
+ if (BTy->getKind() != BuiltinType::Float) {
+ Res = ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast).get();
+ }
} else if (getLangOpts().OpenCL &&
- !((getLangOpts().OpenCLVersion >= 120) ||
- getOpenCLOptions().cl_khr_fp64)) {
+ !getOpenCLOptions().isEnabled("cl_khr_fp64")) {
+ // Impose single-precision float type when cl_khr_fp64 is not enabled.
Diag(Tok.getLocation(), diag::warn_double_const_requires_fp64);
Res = ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast).get();
}
@@ -3493,7 +3521,7 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
// To be compatible with MSVC, hex integer literals ending with the
// LL or i64 suffix are always signed in Microsoft mode.
if (!Literal.isUnsigned && (ResultVal[LongLongSize-1] == 0 ||
- (getLangOpts().MicrosoftExt && Literal.isLongLong)))
+ (getLangOpts().MSVCCompat && Literal.isLongLong)))
Ty = Context.LongLongTy;
else if (AllowUnsigned)
Ty = Context.UnsignedLongLongTy;
@@ -3852,6 +3880,7 @@ static void captureVariablyModifiedType(ASTContext &Context, QualType T,
case Type::ObjCObject:
case Type::ObjCInterface:
case Type::ObjCObjectPointer:
+ case Type::ObjCTypeParam:
case Type::Pipe:
llvm_unreachable("type class is never variably-modified!");
case Type::Adjusted:
@@ -4304,14 +4333,13 @@ ExprResult Sema::ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc,
diag::err_omp_section_incomplete_type, Base))
return ExprError();
- if (LowerBound) {
+ if (LowerBound && !OriginalTy->isAnyPointerType()) {
llvm::APSInt LowerBoundValue;
if (LowerBound->EvaluateAsInt(LowerBoundValue, Context)) {
- // OpenMP 4.0, [2.4 Array Sections]
- // The lower-bound and length must evaluate to non-negative integers.
+ // OpenMP 4.5, [2.4 Array Sections]
+ // The array section must be a subset of the original array.
if (LowerBoundValue.isNegative()) {
- Diag(LowerBound->getExprLoc(), diag::err_omp_section_negative)
- << 0 << LowerBoundValue.toString(/*Radix=*/10, /*Signed=*/true)
+ Diag(LowerBound->getExprLoc(), diag::err_omp_section_not_subset_of_array)
<< LowerBound->getSourceRange();
return ExprError();
}
@@ -4321,11 +4349,11 @@ ExprResult Sema::ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc,
if (Length) {
llvm::APSInt LengthValue;
if (Length->EvaluateAsInt(LengthValue, Context)) {
- // OpenMP 4.0, [2.4 Array Sections]
- // The lower-bound and length must evaluate to non-negative integers.
+ // OpenMP 4.5, [2.4 Array Sections]
+ // The length must evaluate to non-negative integers.
if (LengthValue.isNegative()) {
- Diag(Length->getExprLoc(), diag::err_omp_section_negative)
- << 1 << LengthValue.toString(/*Radix=*/10, /*Signed=*/true)
+ Diag(Length->getExprLoc(), diag::err_omp_section_length_negative)
+ << LengthValue.toString(/*Radix=*/10, /*Signed=*/true)
<< Length->getSourceRange();
return ExprError();
}
@@ -4333,7 +4361,7 @@ ExprResult Sema::ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc,
} else if (ColonLoc.isValid() &&
(OriginalTy.isNull() || (!OriginalTy->isConstantArrayType() &&
!OriginalTy->isVariableArrayType()))) {
- // OpenMP 4.0, [2.4 Array Sections]
+ // OpenMP 4.5, [2.4 Array Sections]
// When the size of the array dimension is not known, the length must be
// specified explicitly.
Diag(ColonLoc, diag::err_omp_section_length_undefined)
@@ -4359,6 +4387,16 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
Expr *LHSExp = Base;
Expr *RHSExp = Idx;
+ ExprValueKind VK = VK_LValue;
+ ExprObjectKind OK = OK_Ordinary;
+
+ // 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;
+
// Perform default conversions.
if (!LHSExp->getType()->getAs<VectorType>()) {
ExprResult Result = DefaultFunctionArrayLvalueConversion(LHSExp);
@@ -4372,8 +4410,6 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
RHSExp = Result.get();
QualType LHSTy = LHSExp->getType(), RHSTy = RHSExp->getType();
- ExprValueKind VK = VK_LValue;
- ExprObjectKind OK = OK_Ordinary;
// C99 6.5.2.1p2: the expression e1[e2] is by definition precisely equivalent
// to the expression *((e1)+(e2)). This means the array "Base" may actually be
@@ -4496,16 +4532,15 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
ArraySubscriptExpr(LHSExp, RHSExp, ResultType, VK, OK, RLoc);
}
-ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
- FunctionDecl *FD,
- ParmVarDecl *Param) {
+bool Sema::CheckCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD,
+ ParmVarDecl *Param) {
if (Param->hasUnparsedDefaultArg()) {
Diag(CallLoc,
diag::err_use_of_default_argument_to_function_declared_later) <<
FD << cast<CXXRecordDecl>(FD->getDeclContext())->getDeclName();
Diag(UnparsedDefaultArgLocs[Param],
diag::note_default_argument_declared_here);
- return ExprError();
+ return true;
}
if (Param->hasUninstantiatedDefaultArg()) {
@@ -4521,11 +4556,11 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
InstantiatingTemplate Inst(*this, CallLoc, Param,
MutiLevelArgList.getInnermost());
if (Inst.isInvalid())
- return ExprError();
+ return true;
if (Inst.isAlreadyInstantiating()) {
Diag(Param->getLocStart(), diag::err_recursive_default_argument) << FD;
Param->setInvalidDecl();
- return ExprError();
+ return true;
}
ExprResult Result;
@@ -4536,10 +4571,11 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
// default argument expression appears.
ContextRAII SavedContext(*this, FD);
LocalInstantiationScope Local(*this);
- Result = SubstExpr(UninstExpr, MutiLevelArgList);
+ Result = SubstInitializer(UninstExpr, MutiLevelArgList,
+ /*DirectInit*/false);
}
if (Result.isInvalid())
- return ExprError();
+ return true;
// Check the expression as an initializer for the parameter.
InitializedEntity Entity
@@ -4552,12 +4588,12 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
InitializationSequence InitSeq(*this, Entity, Kind, ResultE);
Result = InitSeq.Perform(*this, Entity, Kind, ResultE);
if (Result.isInvalid())
- return ExprError();
+ return true;
Result = ActOnFinishFullExpr(Result.getAs<Expr>(),
Param->getOuterLocStart());
if (Result.isInvalid())
- return ExprError();
+ return true;
// Remember the instantiated default argument.
Param->setDefaultArg(Result.getAs<Expr>());
@@ -4570,7 +4606,7 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
if (!Param->hasInit()) {
Diag(Param->getLocStart(), diag::err_recursive_default_argument) << FD;
Param->setInvalidDecl();
- return ExprError();
+ return true;
}
// If the default expression creates temporaries, we need to
@@ -4597,9 +4633,15 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
// as being "referenced".
MarkDeclarationsReferencedInExpr(Param->getDefaultArg(),
/*SkipLocalVariables=*/true);
- return CXXDefaultArgExpr::Create(Context, CallLoc, Param);
+ return false;
}
+ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
+ FunctionDecl *FD, ParmVarDecl *Param) {
+ if (CheckCXXDefaultArgExpr(CallLoc, FD, Param))
+ return ExprError();
+ return CXXDefaultArgExpr::Create(Context, CallLoc, Param);
+}
Sema::VariadicCallType
Sema::getVariadicCallType(FunctionDecl *FDecl, const FunctionProtoType *Proto,
@@ -5057,7 +5099,11 @@ static FunctionDecl *rewriteBuiltinFunctionDecl(Sema *Sema, ASTContext &Context,
for (QualType ParamType : FT->param_types()) {
// Convert array arguments to pointer to simplify type lookup.
- Expr *Arg = Sema->DefaultFunctionArrayLvalueConversion(ArgExprs[i++]).get();
+ ExprResult ArgRes =
+ Sema->DefaultFunctionArrayLvalueConversion(ArgExprs[i++]);
+ if (ArgRes.isInvalid())
+ return nullptr;
+ Expr *Arg = ArgRes.get();
QualType ArgType = Arg->getType();
if (!ParamType->isPointerType() ||
ParamType.getQualifiers().hasAddressSpace() ||
@@ -5116,12 +5162,11 @@ static bool isNumberOfArgsValidForCall(Sema &S, const FunctionDecl *Callee,
/// ActOnCallExpr - Handle a call to Fn with the specified array of arguments.
/// This provides the location of the left/right parens and a list of comma
/// locations.
-ExprResult
-Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
- MultiExprArg ArgExprs, SourceLocation RParenLoc,
- Expr *ExecConfig, bool IsExecConfig) {
+ExprResult Sema::ActOnCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
+ MultiExprArg ArgExprs, SourceLocation RParenLoc,
+ Expr *ExecConfig, bool IsExecConfig) {
// Since this might be a postfix expression, get rid of ParenListExprs.
- ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Fn);
+ ExprResult Result = MaybeConvertParenListExprToParenExpr(Scope, Fn);
if (Result.isInvalid()) return ExprError();
Fn = Result.get();
@@ -5134,9 +5179,9 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
if (!ArgExprs.empty()) {
// Pseudo-destructor calls should not have any arguments.
Diag(Fn->getLocStart(), diag::err_pseudo_dtor_call_with_args)
- << FixItHint::CreateRemoval(
- SourceRange(ArgExprs.front()->getLocStart(),
- ArgExprs.back()->getLocEnd()));
+ << FixItHint::CreateRemoval(
+ SourceRange(ArgExprs.front()->getLocStart(),
+ ArgExprs.back()->getLocEnd()));
}
return new (Context)
@@ -5169,7 +5214,7 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
// Determine whether this is a call to an object (C++ [over.call.object]).
if (Fn->getType()->isRecordType())
- return BuildCallToObjectOfClassType(S, Fn, LParenLoc, ArgExprs,
+ return BuildCallToObjectOfClassType(Scope, Fn, LParenLoc, ArgExprs,
RParenLoc);
if (Fn->getType() == Context.UnknownAnyTy) {
@@ -5179,7 +5224,8 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
}
if (Fn->getType() == Context.BoundMemberTy) {
- return BuildCallToMemberFunction(S, Fn, LParenLoc, ArgExprs, RParenLoc);
+ return BuildCallToMemberFunction(Scope, Fn, LParenLoc, ArgExprs,
+ RParenLoc);
}
}
@@ -5187,15 +5233,16 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
if (Fn->getType() == Context.OverloadTy) {
OverloadExpr::FindResult find = OverloadExpr::find(Fn);
- // We aren't supposed to apply this logic for if there's an '&' involved.
+ // We aren't supposed to apply this logic for if there'Scope an '&'
+ // involved.
if (!find.HasFormOfMemberPointer) {
OverloadExpr *ovl = find.Expression;
if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(ovl))
- return BuildOverloadedCallExpr(S, Fn, ULE, LParenLoc, ArgExprs,
- RParenLoc, ExecConfig,
- /*AllowTypoCorrection=*/true,
- find.IsAddressOfOperand);
- return BuildCallToMemberFunction(S, Fn, LParenLoc, ArgExprs, RParenLoc);
+ return BuildOverloadedCallExpr(
+ Scope, Fn, ULE, LParenLoc, ArgExprs, RParenLoc, ExecConfig,
+ /*AllowTypoCorrection=*/true, find.IsAddressOfOperand);
+ return BuildCallToMemberFunction(Scope, Fn, LParenLoc, ArgExprs,
+ RParenLoc);
}
}
@@ -5225,12 +5272,12 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
// Rewrite the function decl for this builtin by replacing parameters
// with no explicit address space with the address space of the arguments
// in ArgExprs.
- if ((FDecl = rewriteBuiltinFunctionDecl(this, Context, FDecl, ArgExprs))) {
+ if ((FDecl =
+ rewriteBuiltinFunctionDecl(this, Context, FDecl, ArgExprs))) {
NDecl = FDecl;
- Fn = DeclRefExpr::Create(Context, FDecl->getQualifierLoc(),
- SourceLocation(), FDecl, false,
- SourceLocation(), FDecl->getType(),
- Fn->getValueKind(), FDecl);
+ Fn = DeclRefExpr::Create(
+ Context, FDecl->getQualifierLoc(), SourceLocation(), FDecl, false,
+ SourceLocation(), FDecl->getType(), Fn->getValueKind(), FDecl);
}
}
} else if (isa<MemberExpr>(NakedFn))
@@ -5242,6 +5289,9 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
Fn->getLocStart()))
return ExprError();
+ if (getLangOpts().OpenCL && checkOpenCLDisabledDecl(*FD, *Fn))
+ return ExprError();
+
// CheckEnableIf assumes that the we're passing in a sane number of args for
// FD, but that doesn't always hold true here. This is because, in some
// cases, we'll emit a diag about an ill-formed function call, but then
@@ -5252,10 +5302,10 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
isNumberOfArgsValidForCall(*this, FD, ArgExprs.size())) {
if (const EnableIfAttr *Attr = CheckEnableIf(FD, ArgExprs, true)) {
Diag(Fn->getLocStart(),
- isa<CXXMethodDecl>(FD) ?
- diag::err_ovl_no_viable_member_function_in_call :
- diag::err_ovl_no_viable_function_in_call)
- << FD << FD->getSourceRange();
+ isa<CXXMethodDecl>(FD)
+ ? diag::err_ovl_no_viable_member_function_in_call
+ : diag::err_ovl_no_viable_function_in_call)
+ << FD << FD->getSourceRange();
Diag(FD->getLocation(),
diag::note_ovl_candidate_disabled_by_enable_if_attr)
<< Attr->getCond()->getSourceRange() << Attr->getMessage();
@@ -5549,7 +5599,7 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo,
return ExprError();
LiteralExpr = Result.get();
- bool isFileScope = getCurFunctionOrMethodDecl() == nullptr;
+ bool isFileScope = !CurContext->isFunctionOrMethod();
if (isFileScope &&
!LiteralExpr->isTypeDependent() &&
!LiteralExpr->isValueDependent() &&
@@ -5559,11 +5609,31 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo,
}
// In C, compound literals are l-values for some reason.
- ExprValueKind VK = getLangOpts().CPlusPlus ? VK_RValue : VK_LValue;
+ // For GCC compatibility, in C++, file-scope array compound literals with
+ // constant initializers are also l-values, and compound literals are
+ // otherwise prvalues.
+ //
+ // (GCC also treats C++ list-initialized file-scope array prvalues with
+ // constant initializers as l-values, but that's non-conforming, so we don't
+ // follow it there.)
+ //
+ // FIXME: It would be better to handle the lvalue cases as materializing and
+ // lifetime-extending a temporary object, but our materialized temporaries
+ // representation only supports lifetime extension from a variable, not "out
+ // of thin air".
+ // FIXME: For C++, we might want to instead lifetime-extend only if a pointer
+ // is bound to the result of applying array-to-pointer decay to the compound
+ // literal.
+ // FIXME: GCC supports compound literals of reference type, which should
+ // obviously have a value kind derived from the kind of reference involved.
+ ExprValueKind VK =
+ (getLangOpts().CPlusPlus && !(isFileScope && literalType->isArrayType()))
+ ? VK_RValue
+ : VK_LValue;
return MaybeBindToTemporary(
- new (Context) CompoundLiteralExpr(LParenLoc, TInfo, literalType,
- VK, LiteralExpr, isFileScope));
+ new (Context) CompoundLiteralExpr(LParenLoc, TInfo, literalType,
+ VK, LiteralExpr, isFileScope));
}
ExprResult
@@ -6006,7 +6076,9 @@ Sema::ActOnCastExpr(Scope *S, SourceLocation LParenLoc,
CheckTollFreeBridgeCast(castType, CastExpr);
CheckObjCBridgeRelatedCast(castType, CastExpr);
-
+
+ DiscardMisalignedMemberAddress(castType.getTypePtr(), CastExpr);
+
return BuildCStyleCastExpr(LParenLoc, castTInfo, RParenLoc, CastExpr);
}
@@ -7007,6 +7079,55 @@ static void DiagnoseConditionalPrecedence(Sema &Self,
SourceRange(CondRHS->getLocStart(), RHSExpr->getLocEnd()));
}
+/// Compute the nullability of a conditional expression.
+static QualType computeConditionalNullability(QualType ResTy, bool IsBin,
+ QualType LHSTy, QualType RHSTy,
+ ASTContext &Ctx) {
+ if (!ResTy->isAnyPointerType())
+ return ResTy;
+
+ auto GetNullability = [&Ctx](QualType Ty) {
+ Optional<NullabilityKind> Kind = Ty->getNullability(Ctx);
+ if (Kind)
+ return *Kind;
+ return NullabilityKind::Unspecified;
+ };
+
+ auto LHSKind = GetNullability(LHSTy), RHSKind = GetNullability(RHSTy);
+ NullabilityKind MergedKind;
+
+ // Compute nullability of a binary conditional expression.
+ if (IsBin) {
+ if (LHSKind == NullabilityKind::NonNull)
+ MergedKind = NullabilityKind::NonNull;
+ else
+ MergedKind = RHSKind;
+ // Compute nullability of a normal conditional expression.
+ } else {
+ if (LHSKind == NullabilityKind::Nullable ||
+ RHSKind == NullabilityKind::Nullable)
+ MergedKind = NullabilityKind::Nullable;
+ else if (LHSKind == NullabilityKind::NonNull)
+ MergedKind = RHSKind;
+ else if (RHSKind == NullabilityKind::NonNull)
+ MergedKind = LHSKind;
+ else
+ MergedKind = NullabilityKind::Unspecified;
+ }
+
+ // Return if ResTy already has the correct nullability.
+ if (GetNullability(ResTy) == MergedKind)
+ return ResTy;
+
+ // Strip all nullability from ResTy.
+ while (ResTy->getNullability(Ctx))
+ ResTy = ResTy.getSingleStepDesugaredType(Ctx);
+
+ // Create a new AttributedType with the new nullability kind.
+ auto NewAttr = AttributedType::getNullabilityAttrKind(MergedKind);
+ return Ctx.getAttributedType(NewAttr, ResTy, ResTy);
+}
+
/// ActOnConditionalOp - Parse a ?: operation. Note that 'LHS' may be null
/// in the case of a the GNU conditional expr extension.
ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc,
@@ -7074,6 +7195,7 @@ ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc,
LHSExpr = CondExpr = opaqueValue;
}
+ QualType LHSTy = LHSExpr->getType(), RHSTy = RHSExpr->getType();
ExprValueKind VK = VK_RValue;
ExprObjectKind OK = OK_Ordinary;
ExprResult Cond = CondExpr, LHS = LHSExpr, RHS = RHSExpr;
@@ -7088,6 +7210,9 @@ ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc,
CheckBoolLikeConversion(Cond.get(), QuestionLoc);
+ result = computeConditionalNullability(result, commonExpr, LHSTy, RHSTy,
+ Context);
+
if (!commonExpr)
return new (Context)
ConditionalOperator(Cond.get(), QuestionLoc, LHS.get(), ColonLoc,
@@ -7218,7 +7343,7 @@ checkPointerTypesForAssignment(Sema &S, QualType LHSType, QualType RHSType) {
return Sema::IncompatiblePointer;
}
if (!S.getLangOpts().CPlusPlus &&
- S.IsNoReturnConversion(ltrans, rtrans, ltrans))
+ S.IsFunctionConversion(ltrans, rtrans, ltrans))
return Sema::IncompatiblePointer;
return ConvTy;
}
@@ -7603,6 +7728,11 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS,
}
}
+ if (LHSType->isSamplerT() && RHSType->isIntegerType()) {
+ Kind = CK_IntToOCLSampler;
+ return Compatible;
+ }
+
return Incompatible;
}
@@ -7683,6 +7813,10 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &CallerRHS,
bool Diagnose,
bool DiagnoseCFAudited,
bool ConvertRHS) {
+ // We need to be able to tell the caller whether we diagnosed a problem, if
+ // they ask us to issue diagnostics.
+ assert((ConvertRHS || !Diagnose) && "can't indicate whether we diagnosed");
+
// If ConvertRHS is false, we want to leave the caller's RHS untouched. Sadly,
// we can't avoid *all* modifications at the moment, so we need some somewhere
// to put the updated value.
@@ -7694,9 +7828,9 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &CallerRHS,
// C++ 5.17p3: If the left operand is not of class type, the
// expression is implicitly converted (C++ 4) to the
// cv-unqualified type of the left operand.
- ExprResult Res;
+ QualType RHSType = RHS.get()->getType();
if (Diagnose) {
- Res = PerformImplicitConversion(RHS.get(), LHSType.getUnqualifiedType(),
+ RHS = PerformImplicitConversion(RHS.get(), LHSType.getUnqualifiedType(),
AA_Assigning);
} else {
ImplicitConversionSequence ICS =
@@ -7708,17 +7842,15 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &CallerRHS,
/*AllowObjCWritebackConversion=*/false);
if (ICS.isFailure())
return Incompatible;
- Res = PerformImplicitConversion(RHS.get(), LHSType.getUnqualifiedType(),
+ RHS = PerformImplicitConversion(RHS.get(), LHSType.getUnqualifiedType(),
ICS, AA_Assigning);
}
- if (Res.isInvalid())
+ if (RHS.isInvalid())
return Incompatible;
Sema::AssignConvertType result = Compatible;
if (getLangOpts().ObjCAutoRefCount &&
- !CheckObjCARCUnavailableWeakConversion(LHSType,
- RHS.get()->getType()))
+ !CheckObjCARCUnavailableWeakConversion(LHSType, RHSType))
result = IncompatibleObjCWeakRef;
- RHS = Res;
return result;
}
@@ -7942,6 +8074,7 @@ QualType Sema::CheckVectorOperands(ExprResult &LHS, ExprResult &RHS,
// If there's an ext-vector type and a scalar, try to convert the scalar to
// the vector element type and splat.
+ // FIXME: this should also work for regular vector types as supported in GCC.
if (!RHSVecType && isa<ExtVectorType>(LHSVecType)) {
if (!tryVectorConvertAndSplat(*this, &RHS, RHSType,
LHSVecType->getElementType(), LHSType))
@@ -7954,16 +8087,31 @@ QualType Sema::CheckVectorOperands(ExprResult &LHS, ExprResult &RHS,
return RHSType;
}
- // If we're allowing lax vector conversions, only the total (data) size needs
- // to be the same. If one of the types is scalar, the result is always the
- // vector type. Don't allow this if the scalar operand is an lvalue.
+ // FIXME: The code below also handles convertion between vectors and
+ // non-scalars, we should break this down into fine grained specific checks
+ // and emit proper diagnostics.
QualType VecType = LHSVecType ? LHSType : RHSType;
- QualType ScalarType = LHSVecType ? RHSType : LHSType;
- ExprResult *ScalarExpr = LHSVecType ? &RHS : &LHS;
- if (isLaxVectorConversion(ScalarType, VecType) &&
- !ScalarExpr->get()->isLValue()) {
- *ScalarExpr = ImpCastExprToType(ScalarExpr->get(), VecType, CK_BitCast);
- return VecType;
+ const VectorType *VT = LHSVecType ? LHSVecType : RHSVecType;
+ QualType OtherType = LHSVecType ? RHSType : LHSType;
+ ExprResult *OtherExpr = LHSVecType ? &RHS : &LHS;
+ if (isLaxVectorConversion(OtherType, VecType)) {
+ // If we're allowing lax vector conversions, only the total (data) size
+ // needs to be the same. For non compound assignment, if one of the types is
+ // scalar, the result is always the vector type.
+ if (!IsCompAssign) {
+ *OtherExpr = ImpCastExprToType(OtherExpr->get(), VecType, CK_BitCast);
+ return VecType;
+ // In a compound assignment, lhs += rhs, 'lhs' is a lvalue src, forbidding
+ // any implicit cast. Here, the 'rhs' should be implicit casted to 'lhs'
+ // type. Note that this is already done by non-compound assignments in
+ // CheckAssignmentConstraints. If it's a scalar type, only bitcast for
+ // <1 x T> -> T. The result is also a vector type.
+ } else if (OtherType->isExtVectorType() ||
+ (OtherType->isScalarType() && VT->getNumElements() == 1)) {
+ ExprResult *RHSExpr = &RHS;
+ *RHSExpr = ImpCastExprToType(RHSExpr->get(), LHSType, CK_BitCast);
+ return VecType;
+ }
}
// Okay, the expression is invalid.
@@ -8608,13 +8756,13 @@ static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS,
<< RHS.get()->getSourceRange();
}
-/// \brief Return the resulting type when an OpenCL vector is shifted
+/// \brief Return the resulting type when a vector is shifted
/// by a scalar or vector shift amount.
-static QualType checkOpenCLVectorShift(Sema &S,
- ExprResult &LHS, ExprResult &RHS,
- SourceLocation Loc, bool IsCompAssign) {
+static QualType checkVectorShift(Sema &S, ExprResult &LHS, ExprResult &RHS,
+ SourceLocation Loc, bool IsCompAssign) {
// OpenCL v1.1 s6.3.j says RHS can be a vector only if LHS is a vector.
- if (!LHS.get()->getType()->isVectorType()) {
+ if ((S.LangOpts.OpenCL || S.LangOpts.ZVector) &&
+ !LHS.get()->getType()->isVectorType()) {
S.Diag(Loc, diag::err_shift_rhs_only_vector)
<< RHS.get()->getType() << LHS.get()->getType()
<< LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
@@ -8630,15 +8778,17 @@ static QualType checkOpenCLVectorShift(Sema &S,
if (RHS.isInvalid()) return QualType();
QualType LHSType = LHS.get()->getType();
- const VectorType *LHSVecTy = LHSType->castAs<VectorType>();
- QualType LHSEleType = LHSVecTy->getElementType();
+ // Note that LHS might be a scalar because the routine calls not only in
+ // OpenCL case.
+ const VectorType *LHSVecTy = LHSType->getAs<VectorType>();
+ QualType LHSEleType = LHSVecTy ? LHSVecTy->getElementType() : LHSType;
// Note that RHS might not be a vector.
QualType RHSType = RHS.get()->getType();
const VectorType *RHSVecTy = RHSType->getAs<VectorType>();
QualType RHSEleType = RHSVecTy ? RHSVecTy->getElementType() : RHSType;
- // OpenCL v1.1 s6.3.j says that the operands need to be integers.
+ // The operands need to be integers.
if (!LHSEleType->isIntegerType()) {
S.Diag(Loc, diag::err_typecheck_expect_int)
<< LHS.get()->getType() << LHS.get()->getSourceRange();
@@ -8651,7 +8801,19 @@ static QualType checkOpenCLVectorShift(Sema &S,
return QualType();
}
- if (RHSVecTy) {
+ if (!LHSVecTy) {
+ assert(RHSVecTy);
+ if (IsCompAssign)
+ return RHSType;
+ if (LHSEleType != RHSEleType) {
+ LHS = S.ImpCastExprToType(LHS.get(),RHSEleType, CK_IntegralCast);
+ LHSEleType = RHSEleType;
+ }
+ QualType VecTy =
+ S.Context.getExtVectorType(LHSEleType, RHSVecTy->getNumElements());
+ LHS = S.ImpCastExprToType(LHS.get(), VecTy, CK_VectorSplat);
+ LHSType = VecTy;
+ } else if (RHSVecTy) {
// OpenCL v1.1 s6.3.j says that for vector types, the operators
// are applied component-wise. So if RHS is a vector, then ensure
// that the number of elements is the same as LHS...
@@ -8661,6 +8823,16 @@ static QualType checkOpenCLVectorShift(Sema &S,
<< LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
return QualType();
}
+ if (!S.LangOpts.OpenCL && !S.LangOpts.ZVector) {
+ const BuiltinType *LHSBT = LHSEleType->getAs<clang::BuiltinType>();
+ const BuiltinType *RHSBT = RHSEleType->getAs<clang::BuiltinType>();
+ if (LHSBT != RHSBT &&
+ S.Context.getTypeSize(LHSBT) != S.Context.getTypeSize(RHSBT)) {
+ S.Diag(Loc, diag::warn_typecheck_vector_element_sizes_not_equal)
+ << LHS.get()->getType() << RHS.get()->getType()
+ << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
+ }
+ }
} else {
// ...else expand RHS to match the number of elements in LHS.
QualType VecTy =
@@ -8680,11 +8852,9 @@ QualType Sema::CheckShiftOperands(ExprResult &LHS, ExprResult &RHS,
// Vector shifts promote their scalar inputs to vector type.
if (LHS.get()->getType()->isVectorType() ||
RHS.get()->getType()->isVectorType()) {
- if (LangOpts.OpenCL)
- return checkOpenCLVectorShift(*this, LHS, RHS, Loc, IsCompAssign);
if (LangOpts.ZVector) {
// The shift operators for the z vector extensions work basically
- // like OpenCL shifts, except that neither the LHS nor the RHS is
+ // like general shifts, except that neither the LHS nor the RHS is
// allowed to be a "vector bool".
if (auto LHSVecType = LHS.get()->getType()->getAs<VectorType>())
if (LHSVecType->getVectorKind() == VectorType::AltiVecBool)
@@ -8692,11 +8862,8 @@ QualType Sema::CheckShiftOperands(ExprResult &LHS, ExprResult &RHS,
if (auto RHSVecType = RHS.get()->getType()->getAs<VectorType>())
if (RHSVecType->getVectorKind() == VectorType::AltiVecBool)
return InvalidOperands(Loc, LHS, RHS);
- return checkOpenCLVectorShift(*this, LHS, RHS, Loc, IsCompAssign);
}
- return CheckVectorOperands(LHS, RHS, Loc, IsCompAssign,
- /*AllowBothBool*/true,
- /*AllowBoolConversions*/false);
+ return checkVectorShift(*this, LHS, RHS, Loc, IsCompAssign);
}
// Shifts don't perform usual arithmetic conversions, they just do integer
@@ -8795,35 +8962,21 @@ static bool convertPointersToCompositeType(Sema &S, SourceLocation Loc,
// C++ [expr.eq]p1 uses the same notion for (in)equality
// comparisons of pointers.
- // C++ [expr.eq]p2:
- // In addition, pointers to members can be compared, or a pointer to
- // member and a null pointer constant. Pointer to member conversions
- // (4.11) and qualification conversions (4.4) are performed to bring
- // them to a common type. If one operand is a null pointer constant,
- // the common type is the type of the other operand. Otherwise, the
- // common type is a pointer to member type similar (4.4) to the type
- // of one of the operands, with a cv-qualification signature (4.4)
- // that is the union of the cv-qualification signatures of the operand
- // types.
-
QualType LHSType = LHS.get()->getType();
QualType RHSType = RHS.get()->getType();
- assert((LHSType->isPointerType() && RHSType->isPointerType()) ||
- (LHSType->isMemberPointerType() && RHSType->isMemberPointerType()));
+ assert(LHSType->isPointerType() || RHSType->isPointerType() ||
+ LHSType->isMemberPointerType() || RHSType->isMemberPointerType());
- bool NonStandardCompositeType = false;
- bool *BoolPtr = S.isSFINAEContext() ? nullptr : &NonStandardCompositeType;
- QualType T = S.FindCompositePointerType(Loc, LHS, RHS, BoolPtr);
+ QualType T = S.FindCompositePointerType(Loc, LHS, RHS);
if (T.isNull()) {
- diagnoseDistinctPointerComparison(S, Loc, LHS, RHS, /*isError*/true);
+ if ((LHSType->isPointerType() || LHSType->isMemberPointerType()) &&
+ (RHSType->isPointerType() || RHSType->isMemberPointerType()))
+ diagnoseDistinctPointerComparison(S, Loc, LHS, RHS, /*isError*/true);
+ else
+ S.InvalidOperands(Loc, LHS, RHS);
return true;
}
- if (NonStandardCompositeType)
- S.Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers_nonstandard)
- << LHSType << RHSType << T << LHS.get()->getSourceRange()
- << RHS.get()->getSourceRange();
-
LHS = S.ImpCastExprToType(LHS.get(), T, CK_BitCast);
RHS = S.ImpCastExprToType(RHS.get(), T, CK_BitCast);
return false;
@@ -8989,10 +9142,10 @@ static void diagnoseObjCLiteralComparison(Sema &S, SourceLocation Loc,
}
}
-static void diagnoseLogicalNotOnLHSofComparison(Sema &S, ExprResult &LHS,
- ExprResult &RHS,
- SourceLocation Loc,
- BinaryOperatorKind Opc) {
+/// Warns on !x < y, !x & y where !(x < y), !(x & y) was probably intended.
+static void diagnoseLogicalNotOnLHSofCheck(Sema &S, ExprResult &LHS,
+ ExprResult &RHS, SourceLocation Loc,
+ BinaryOperatorKind Opc) {
// Check that left hand side is !something.
UnaryOperator *UO = dyn_cast<UnaryOperator>(LHS.get()->IgnoreImpCasts());
if (!UO || UO->getOpcode() != UO_LNot) return;
@@ -9005,8 +9158,9 @@ static void diagnoseLogicalNotOnLHSofComparison(Sema &S, ExprResult &LHS,
if (SubExpr->isKnownToHaveBooleanValue()) return;
// Emit warning.
- S.Diag(UO->getOperatorLoc(), diag::warn_logical_not_on_lhs_of_comparison)
- << Loc;
+ bool IsBitwiseOp = Opc == BO_And || Opc == BO_Or || Opc == BO_Xor;
+ S.Diag(UO->getOperatorLoc(), diag::warn_logical_not_on_lhs_of_check)
+ << Loc << IsBitwiseOp;
// First note suggest !(x < y)
SourceLocation FirstOpen = SubExpr->getLocStart();
@@ -9015,6 +9169,7 @@ static void diagnoseLogicalNotOnLHSofComparison(Sema &S, ExprResult &LHS,
if (FirstClose.isInvalid())
FirstOpen = SourceLocation();
S.Diag(UO->getOperatorLoc(), diag::note_logical_not_fix)
+ << IsBitwiseOp
<< FixItHint::CreateInsertion(FirstOpen, "(")
<< FixItHint::CreateInsertion(FirstClose, ")");
@@ -9063,7 +9218,7 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
Expr *RHSStripped = RHS.get()->IgnoreParenImpCasts();
checkEnumComparison(*this, Loc, LHS.get(), RHS.get());
- diagnoseLogicalNotOnLHSofComparison(*this, LHS, RHS, Loc, Opc);
+ diagnoseLogicalNotOnLHSofCheck(*this, LHS, RHS, Loc, Opc);
if (!LHSType->hasFloatingRepresentation() &&
!(LHSType->isBlockPointerType() && IsRelational) &&
@@ -9180,41 +9335,53 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
LHS.get()->getSourceRange());
}
- // All of the following pointer-related warnings are GCC extensions, except
- // when handling null pointer constants.
- if (LHSType->isPointerType() && RHSType->isPointerType()) { // C99 6.5.8p2
- QualType LCanPointeeTy =
- LHSType->castAs<PointerType>()->getPointeeType().getCanonicalType();
- QualType RCanPointeeTy =
- RHSType->castAs<PointerType>()->getPointeeType().getCanonicalType();
-
- if (getLangOpts().CPlusPlus) {
- if (LCanPointeeTy == RCanPointeeTy)
- return ResultTy;
- if (!IsRelational &&
- (LCanPointeeTy->isVoidType() || RCanPointeeTy->isVoidType())) {
- // Valid unless comparison between non-null pointer and function pointer
- // This is a gcc extension compatibility comparison.
- // In a SFINAE context, we treat this as a hard error to maintain
- // conformance with the C++ standard.
- if ((LCanPointeeTy->isFunctionType() || RCanPointeeTy->isFunctionType())
- && !LHSIsNull && !RHSIsNull) {
- diagnoseFunctionPointerToVoidComparison(
- *this, Loc, LHS, RHS, /*isError*/ (bool)isSFINAEContext());
-
- if (isSFINAEContext())
- return QualType();
-
- RHS = ImpCastExprToType(RHS.get(), LHSType, CK_BitCast);
- return ResultTy;
- }
- }
+ if ((LHSType->isIntegerType() && !LHSIsNull) ||
+ (RHSType->isIntegerType() && !RHSIsNull)) {
+ // Skip normal pointer conversion checks in this case; we have better
+ // diagnostics for this below.
+ } else if (getLangOpts().CPlusPlus) {
+ // Equality comparison of a function pointer to a void pointer is invalid,
+ // but we allow it as an extension.
+ // FIXME: If we really want to allow this, should it be part of composite
+ // pointer type computation so it works in conditionals too?
+ if (!IsRelational &&
+ ((LHSType->isFunctionPointerType() && RHSType->isVoidPointerType()) ||
+ (RHSType->isFunctionPointerType() && LHSType->isVoidPointerType()))) {
+ // This is a gcc extension compatibility comparison.
+ // In a SFINAE context, we treat this as a hard error to maintain
+ // 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;
+ }
+ // C++ [expr.eq]p2:
+ // If at least one operand is a pointer [...] 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)) {
if (convertPointersToCompositeType(*this, Loc, LHS, RHS))
return QualType();
else
return ResultTy;
}
+ } else if (LHSType->isPointerType() &&
+ RHSType->isPointerType()) { // C99 6.5.8p2
+ // All of the following pointer-related warnings are GCC extensions, except
+ // when handling null pointer constants.
+ QualType LCanPointeeTy =
+ LHSType->castAs<PointerType>()->getPointeeType().getCanonicalType();
+ QualType RCanPointeeTy =
+ RHSType->castAs<PointerType>()->getPointeeType().getCanonicalType();
+
// C99 6.5.9p2 and C99 6.5.8p2
if (Context.typesAreCompatible(LCanPointeeTy.getUnqualifiedType(),
RCanPointeeTy.getUnqualifiedType())) {
@@ -9259,36 +9426,63 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
}
if (getLangOpts().CPlusPlus) {
- // Comparison of nullptr_t with itself.
- if (LHSType->isNullPtrType() && RHSType->isNullPtrType())
- return ResultTy;
-
- // Comparison of pointers with null pointer constants and equality
- // comparisons of member pointers to null pointer constants.
- if (RHSIsNull &&
- ((LHSType->isAnyPointerType() || LHSType->isNullPtrType()) ||
- (!IsRelational &&
- (LHSType->isMemberPointerType() || LHSType->isBlockPointerType())))) {
- RHS = ImpCastExprToType(RHS.get(), LHSType,
- LHSType->isMemberPointerType()
- ? CK_NullToMemberPointer
- : CK_NullToPointer);
+ // C++ [expr.eq]p4:
+ // Two operands of type std::nullptr_t or one operand of type
+ // std::nullptr_t and the other a null pointer constant compare equal.
+ if (!IsRelational && LHSIsNull && RHSIsNull) {
+ if (LHSType->isNullPtrType()) {
+ RHS = ImpCastExprToType(RHS.get(), LHSType, CK_NullToPointer);
+ return ResultTy;
+ }
+ if (RHSType->isNullPtrType()) {
+ LHS = ImpCastExprToType(LHS.get(), RHSType, CK_NullToPointer);
+ return ResultTy;
+ }
+ }
+
+ // Comparison of Objective-C pointers and block pointers against nullptr_t.
+ // These aren't covered by the composite pointer type rules.
+ if (!IsRelational && RHSType->isNullPtrType() &&
+ (LHSType->isObjCObjectPointerType() || LHSType->isBlockPointerType())) {
+ RHS = ImpCastExprToType(RHS.get(), LHSType, CK_NullToPointer);
return ResultTy;
}
- if (LHSIsNull &&
- ((RHSType->isAnyPointerType() || RHSType->isNullPtrType()) ||
- (!IsRelational &&
- (RHSType->isMemberPointerType() || RHSType->isBlockPointerType())))) {
- LHS = ImpCastExprToType(LHS.get(), RHSType,
- RHSType->isMemberPointerType()
- ? CK_NullToMemberPointer
- : CK_NullToPointer);
+ if (!IsRelational && LHSType->isNullPtrType() &&
+ (RHSType->isObjCObjectPointerType() || RHSType->isBlockPointerType())) {
+ LHS = ImpCastExprToType(LHS.get(), RHSType, CK_NullToPointer);
return ResultTy;
}
- // Comparison of member pointers.
+ if (IsRelational &&
+ ((LHSType->isNullPtrType() && RHSType->isPointerType()) ||
+ (RHSType->isNullPtrType() && LHSType->isPointerType()))) {
+ // HACK: Relational comparison of nullptr_t against a pointer type is
+ // invalid per DR583, but we allow it within std::less<> and friends,
+ // since otherwise common uses of it break.
+ // FIXME: Consider removing this hack once LWG fixes std::less<> and
+ // friends to have std::nullptr_t overload candidates.
+ DeclContext *DC = CurContext;
+ if (isa<FunctionDecl>(DC))
+ DC = DC->getParent();
+ if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(DC)) {
+ if (CTSD->isInStdNamespace() &&
+ llvm::StringSwitch<bool>(CTSD->getName())
+ .Cases("less", "less_equal", "greater", "greater_equal", true)
+ .Default(false)) {
+ if (RHSType->isNullPtrType())
+ RHS = ImpCastExprToType(RHS.get(), LHSType, CK_NullToPointer);
+ else
+ LHS = ImpCastExprToType(LHS.get(), RHSType, CK_NullToPointer);
+ return ResultTy;
+ }
+ }
+ }
+
+ // C++ [expr.eq]p2:
+ // If at least one operand is a pointer to member, [...] bring them to
+ // their composite pointer type.
if (!IsRelational &&
- LHSType->isMemberPointerType() && RHSType->isMemberPointerType()) {
+ (LHSType->isMemberPointerType() || RHSType->isMemberPointerType())) {
if (convertPointersToCompositeType(*this, Loc, LHS, RHS))
return QualType();
else
@@ -9397,15 +9591,19 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
// Under a debugger, allow the comparison of pointers to integers,
// since users tend to want to compare addresses.
} else if ((LHSIsNull && LHSType->isIntegerType()) ||
- (RHSIsNull && RHSType->isIntegerType())) {
- if (IsRelational && !getLangOpts().CPlusPlus)
- DiagID = diag::ext_typecheck_ordered_comparison_of_pointer_and_zero;
- } else if (IsRelational && !getLangOpts().CPlusPlus)
- DiagID = diag::ext_typecheck_ordered_comparison_of_pointer_integer;
- else if (getLangOpts().CPlusPlus) {
+ (RHSIsNull && RHSType->isIntegerType())) {
+ if (IsRelational) {
+ isError = getLangOpts().CPlusPlus;
+ DiagID =
+ isError ? diag::err_typecheck_ordered_comparison_of_pointer_and_zero
+ : diag::ext_typecheck_ordered_comparison_of_pointer_and_zero;
+ }
+ } else if (getLangOpts().CPlusPlus) {
DiagID = diag::err_typecheck_comparison_of_pointer_integer;
isError = true;
- } else
+ } else if (IsRelational)
+ DiagID = diag::ext_typecheck_ordered_comparison_of_pointer_integer;
+ else
DiagID = diag::ext_typecheck_comparison_of_pointer_integer;
if (DiagID) {
@@ -9437,6 +9635,18 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
return ResultTy;
}
+ if (getLangOpts().OpenCLVersion >= 200) {
+ if (LHSIsNull && RHSType->isQueueT()) {
+ LHS = ImpCastExprToType(LHS.get(), RHSType, CK_NullToPointer);
+ return ResultTy;
+ }
+
+ if (LHSType->isQueueT() && RHSIsNull) {
+ RHS = ImpCastExprToType(RHS.get(), LHSType, CK_NullToPointer);
+ return ResultTy;
+ }
+ }
+
return InvalidOperands(Loc, LHS, RHS);
}
@@ -9526,10 +9736,14 @@ QualType Sema::CheckVectorLogicalOperands(ExprResult &LHS, ExprResult &RHS,
return GetSignedVectorType(LHS.get()->getType());
}
-inline QualType Sema::CheckBitwiseOperands(
- ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, bool IsCompAssign) {
+inline QualType Sema::CheckBitwiseOperands(ExprResult &LHS, ExprResult &RHS,
+ SourceLocation Loc,
+ BinaryOperatorKind Opc) {
checkArithmeticNull(*this, LHS, RHS, Loc, /*isCompare=*/false);
+ bool IsCompAssign =
+ Opc == BO_AndAssign || Opc == BO_OrAssign || Opc == BO_XorAssign;
+
if (LHS.get()->getType()->isVectorType() ||
RHS.get()->getType()->isVectorType()) {
if (LHS.get()->getType()->hasIntegerRepresentation() &&
@@ -9540,6 +9754,9 @@ inline QualType Sema::CheckBitwiseOperands(
return InvalidOperands(Loc, LHS, RHS);
}
+ if (Opc == BO_And)
+ diagnoseLogicalNotOnLHSofCheck(*this, LHS, RHS, Loc, Opc);
+
ExprResult LHSResult = LHS, RHSResult = RHS;
QualType compType = UsualArithmeticConversions(LHSResult, RHSResult,
IsCompAssign);
@@ -9647,8 +9864,8 @@ static bool IsReadonlyMessage(Expr *E, Sema &S) {
const MemberExpr *ME = dyn_cast<MemberExpr>(E);
if (!ME) return false;
if (!isa<FieldDecl>(ME->getMemberDecl())) return false;
- ObjCMessageExpr *Base =
- dyn_cast<ObjCMessageExpr>(ME->getBase()->IgnoreParenImpCasts());
+ ObjCMessageExpr *Base = dyn_cast<ObjCMessageExpr>(
+ ME->getBase()->IgnoreImplicit()->IgnoreParenImpCasts());
if (!Base) return false;
return Base->getMethodDecl() != nullptr;
}
@@ -9722,17 +9939,16 @@ static void DiagnoseConstAssignment(Sema &S, const Expr *E,
// a note to the error.
bool DiagnosticEmitted = false;
- // Track if the current expression is the result of a derefence, and if the
- // next checked expression is the result of a derefence.
+ // Track if the current expression is the result of a dereference, and if the
+ // next checked expression is the result of a dereference.
bool IsDereference = false;
bool NextIsDereference = false;
// Loop to process MemberExpr chains.
while (true) {
IsDereference = NextIsDereference;
- NextIsDereference = false;
- E = E->IgnoreParenImpCasts();
+ E = E->IgnoreImplicit()->IgnoreParenImpCasts();
if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
NextIsDereference = ME->isArrow();
const ValueDecl *VD = ME->getMemberDecl();
@@ -9930,10 +10146,10 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
case Expr::MLV_NoSetterProperty:
llvm_unreachable("readonly properties should be processed differently");
case Expr::MLV_InvalidMessageExpression:
- DiagID = diag::error_readonly_message_assignment;
+ DiagID = diag::err_readonly_message_assignment;
break;
case Expr::MLV_SubObjCPropertySetting:
- DiagID = diag::error_no_subobject_property_setting;
+ DiagID = diag::err_no_subobject_property_setting;
break;
}
@@ -9982,6 +10198,16 @@ QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS,
QualType LHSType = LHSExpr->getType();
QualType RHSType = CompoundType.isNull() ? RHS.get()->getType() :
CompoundType;
+ // OpenCL v1.2 s6.1.1.1 p2:
+ // The half data type can only be used to declare a pointer to a buffer that
+ // contains half values
+ if (getLangOpts().OpenCL && !getOpenCLOptions().isEnabled("cl_khr_fp16") &&
+ LHSType->isHalfType()) {
+ Diag(Loc, diag::err_opencl_half_load_store) << 1
+ << LHSType.getUnqualifiedType();
+ return QualType();
+ }
+
AssignConvertType ConvTy;
if (CompoundType.isNull()) {
Expr *RHSCheck = RHS.get();
@@ -10519,7 +10745,8 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
return MPTy;
}
}
- } else if (!isa<FunctionDecl>(dcl) && !isa<NonTypeTemplateParmDecl>(dcl))
+ } else if (!isa<FunctionDecl>(dcl) && !isa<NonTypeTemplateParmDecl>(dcl) &&
+ !isa<BindingDecl>(dcl))
llvm_unreachable("Unknown/unexpected decl type");
}
@@ -10539,6 +10766,8 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
if (op->getType()->isObjCObjectType())
return Context.getObjCObjectPointerType(op->getType());
+ CheckAddressOfPackedMember(op);
+
return Context.getPointerType(op->getType());
}
@@ -10895,7 +11124,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
checkObjCPointerIntrospection(*this, LHS, RHS, OpLoc);
case BO_Xor:
case BO_Or:
- ResultTy = CheckBitwiseOperands(LHS, RHS, OpLoc);
+ ResultTy = CheckBitwiseOperands(LHS, RHS, OpLoc, Opc);
break;
case BO_LAnd:
case BO_LOr:
@@ -10936,7 +11165,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
case BO_OrAssign: // fallthrough
DiagnoseSelfAssignment(*this, LHS.get(), RHS.get(), OpLoc);
case BO_XorAssign:
- CompResultTy = CheckBitwiseOperands(LHS, RHS, OpLoc, true);
+ CompResultTy = CheckBitwiseOperands(LHS, RHS, OpLoc, Opc);
CompLHSTy = CompResultTy;
if (!CompResultTy.isNull() && !LHS.isInvalid() && !RHS.isInvalid())
ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, CompResultTy);
@@ -12428,10 +12657,14 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
MayHaveConvFixit = true;
break;
case IncompatiblePointer:
- DiagKind =
- (Action == AA_Passing_CFAudited ?
- diag::err_arc_typecheck_convert_incompatible_pointer :
- diag::ext_typecheck_convert_incompatible_pointer);
+ if (Action == AA_Passing_CFAudited)
+ DiagKind = diag::err_arc_typecheck_convert_incompatible_pointer;
+ else if (SrcType->isFunctionPointerType() &&
+ DstType->isFunctionPointerType())
+ DiagKind = diag::ext_typecheck_convert_incompatible_function_pointer;
+ else
+ DiagKind = diag::ext_typecheck_convert_incompatible_pointer;
+
CheckInferredResultType = DstType->isObjCObjectPointerType() &&
SrcType->isObjCObjectPointerType();
if (Hint.isNull() && !CheckInferredResultType) {
@@ -12582,7 +12815,7 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
Diag(Loc, FDiag);
if (DiagKind == diag::warn_incompatible_qualified_id &&
PDecl && IFace && !IFace->hasDefinition())
- Diag(IFace->getLocation(), diag::not_incomplete_class_and_qualified_id)
+ Diag(IFace->getLocation(), diag::note_incomplete_class_and_qualified_id)
<< IFace->getName() << PDecl->getName();
if (SecondType == Context.OverloadTy)
@@ -13005,6 +13238,19 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func,
Func->getMemberSpecializationInfo()))
checkSpecializationVisibility(Loc, Func);
+ // C++14 [except.spec]p17:
+ // An exception-specification is considered to be needed when:
+ // - the function is odr-used or, if it appears in an unevaluated operand,
+ // would be odr-used if the expression were potentially-evaluated;
+ //
+ // Note, we do this even if MightBeOdrUse is false. That indicates that the
+ // function is a pure virtual function we're calling, and in that case the
+ // function was selected by overload resolution and we need to resolve its
+ // exception specification for a different reason.
+ const FunctionProtoType *FPT = Func->getType()->getAs<FunctionProtoType>();
+ if (FPT && isUnresolvedExceptionSpec(FPT->getExceptionSpecType()))
+ ResolveExceptionSpec(Loc, FPT);
+
// If we don't need to mark the function as used, and we don't need to
// try to provide a definition, there's nothing more to do.
if ((Func->isUsed(/*CheckUsedAttr=*/false) || !OdrUse) &&
@@ -13063,12 +13309,6 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func,
// FIXME: Is this really right?
if (CurContext == Func) return;
- // Resolve the exception specification for any function which is
- // used: CodeGen will need it.
- const FunctionProtoType *FPT = Func->getType()->getAs<FunctionProtoType>();
- if (FPT && isUnresolvedExceptionSpec(FPT->getExceptionSpecType()))
- ResolveExceptionSpec(Loc, FPT);
-
// Implicit instantiation of function templates and member functions of
// class templates.
if (Func->isImplicitlyInstantiable()) {
@@ -13137,7 +13377,7 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func,
static void
diagnoseUncapturableValueReference(Sema &S, SourceLocation loc,
- VarDecl *var, DeclContext *DC) {
+ ValueDecl *var, DeclContext *DC) {
DeclContext *VarDC = var->getDeclContext();
// If the parameter still belongs to the translation unit, then
@@ -13157,25 +13397,21 @@ diagnoseUncapturableValueReference(Sema &S, SourceLocation loc,
if (!S.getLangOpts().CPlusPlus && !S.CurContext->isFunctionOrMethod())
return;
+ unsigned ValueKind = isa<BindingDecl>(var) ? 1 : 0;
+ unsigned ContextKind = 3; // unknown
if (isa<CXXMethodDecl>(VarDC) &&
cast<CXXRecordDecl>(VarDC->getParent())->isLambda()) {
- S.Diag(loc, diag::err_reference_to_local_var_in_enclosing_lambda)
- << var->getIdentifier();
- } else if (FunctionDecl *fn = dyn_cast<FunctionDecl>(VarDC)) {
- S.Diag(loc, diag::err_reference_to_local_var_in_enclosing_function)
- << var->getIdentifier() << fn->getDeclName();
+ ContextKind = 2;
+ } else if (isa<FunctionDecl>(VarDC)) {
+ ContextKind = 0;
} else if (isa<BlockDecl>(VarDC)) {
- S.Diag(loc, diag::err_reference_to_local_var_in_enclosing_block)
- << var->getIdentifier();
- } else {
- // FIXME: Is there any other context where a local variable can be
- // declared?
- S.Diag(loc, diag::err_reference_to_local_var_in_enclosing_context)
- << var->getIdentifier();
+ ContextKind = 1;
}
+ S.Diag(loc, diag::err_reference_to_local_in_enclosing_context)
+ << var << ValueKind << ContextKind << VarDC;
S.Diag(var->getLocation(), diag::note_entity_declared_at)
- << var->getIdentifier();
+ << var;
// FIXME: Add additional diagnostic info about class etc. which prevents
// capture.
@@ -13319,6 +13555,23 @@ static bool captureInBlock(BlockScopeInfo *BSI, VarDecl *Var,
}
return false;
}
+
+ // Warn about implicitly autoreleasing indirect parameters captured by blocks.
+ if (auto *PT = dyn_cast<PointerType>(CaptureType)) {
+ QualType PointeeTy = PT->getPointeeType();
+ if (isa<ObjCObjectPointerType>(PointeeTy.getCanonicalType()) &&
+ PointeeTy.getObjCLifetime() == Qualifiers::OCL_Autoreleasing &&
+ !isa<AttributedType>(PointeeTy)) {
+ if (BuildAndDiagnose) {
+ SourceLocation VarLoc = Var->getLocation();
+ S.Diag(Loc, diag::warn_block_capture_autoreleasing);
+ S.Diag(VarLoc, diag::note_declare_parameter_autoreleasing) <<
+ FixItHint::CreateInsertion(VarLoc, "__autoreleasing");
+ S.Diag(VarLoc, diag::note_declare_parameter_strong);
+ }
+ }
+ }
+
const bool HasBlocksAttr = Var->hasAttr<BlocksAttr>();
if (HasBlocksAttr || CaptureType->isReferenceType() ||
(S.getLangOpts().OpenMP && S.IsOpenMPCapturedDecl(Var))) {
@@ -13539,7 +13792,7 @@ static bool captureInLambda(LambdaScopeInfo *LSI,
// C++ [expr.prim.lambda]p5:
// The closure type for a lambda-expression has a public inline
// function call operator [...]. This function call operator is
- // declared const (9.3.1) if and only if the lambda-expression’s
+ // declared const (9.3.1) if and only if the lambda-expression's
// parameter-declaration-clause is not followed by mutable.
DeclRefType = CaptureType.getNonReferenceType();
if (!LSI->Mutable && !CaptureType->isReferenceType())
@@ -14580,6 +14833,13 @@ namespace {
<< E->getSourceRange();
return ExprError();
}
+
+ if (isa<CallExpr>(E->getSubExpr())) {
+ S.Diag(E->getOperatorLoc(), diag::err_unknown_any_addrof_call)
+ << E->getSourceRange();
+ return ExprError();
+ }
+
assert(E->getValueKind() == VK_RValue);
assert(E->getObjectKind() == OK_Ordinary);
E->setType(DestType);
@@ -15104,11 +15364,6 @@ ExprResult Sema::ActOnObjCAvailabilityCheckExpr(
VersionTuple Version;
if (Spec != AvailSpecs.end())
Version = Spec->getVersion();
- else
- // This is the '*' case in @available. We should diagnose this; the
- // programmer should explicitly account for this case if they target this
- // platform.
- Diag(AtLoc, diag::warn_available_using_star_case) << RParen << Platform;
return new (Context)
ObjCAvailabilityCheckExpr(Version, AtLoc, RParen, Context.BoolTy);
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index dfdd36752bf6..5f769cc40ded 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -292,7 +292,7 @@ ParsedType Sema::getDestructorName(SourceLocation TildeLoc,
if (isDependent) {
// We didn't find our type, but that's okay: it's dependent
// anyway.
-
+
// FIXME: What if we have no nested-name-specifier?
QualType T = CheckTypenameType(ETK_None, SourceLocation(),
SS.getWithLocInContext(Context),
@@ -326,14 +326,14 @@ ParsedType Sema::getDestructorName(SourceLocation TildeLoc,
ParsedType Sema::getDestructorType(const DeclSpec& DS, ParsedType ObjectType) {
if (DS.getTypeSpecType() == DeclSpec::TST_error || !ObjectType)
return nullptr;
- assert(DS.getTypeSpecType() == DeclSpec::TST_decltype
+ assert(DS.getTypeSpecType() == DeclSpec::TST_decltype
&& "only get destructor types from declspecs");
QualType T = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc());
QualType SearchType = GetTypeFromParser(ObjectType);
if (SearchType->isDependentType() || Context.hasSameUnqualifiedType(SearchType, T)) {
return ParsedType::make(T);
}
-
+
Diag(DS.getTypeSpecTypeLoc(), diag::err_destructor_expr_type_mismatch)
<< T << SearchType;
return nullptr;
@@ -520,17 +520,17 @@ getUuidAttrOfType(Sema &SemaRef, QualType QT,
else if (QT->isArrayType())
Ty = Ty->getBaseElementTypeUnsafe();
- const auto *RD = Ty->getAsCXXRecordDecl();
- if (!RD)
+ const auto *TD = Ty->getAsTagDecl();
+ if (!TD)
return;
- if (const auto *Uuid = RD->getMostRecentDecl()->getAttr<UuidAttr>()) {
+ if (const auto *Uuid = TD->getMostRecentDecl()->getAttr<UuidAttr>()) {
UuidAttrs.insert(Uuid);
return;
}
// __uuidof can grab UUIDs from template arguments.
- if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD)) {
+ if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(TD)) {
const TemplateArgumentList &TAL = CTSD->getTemplateArgs();
for (const TemplateArgument &TA : TAL.asArray()) {
const UuidAttr *UuidForTA = nullptr;
@@ -662,7 +662,7 @@ Sema::ActOnCXXThrow(Scope *S, SourceLocation OpLoc, Expr *Ex) {
IsThrownVarInScope = true;
break;
}
-
+
if (S->getFlags() &
(Scope::FnScope | Scope::ClassScope | Scope::BlockScope |
Scope::FunctionPrototypeScope | Scope::ObjCMethodScope |
@@ -672,17 +672,22 @@ Sema::ActOnCXXThrow(Scope *S, SourceLocation OpLoc, Expr *Ex) {
}
}
}
-
+
return BuildCXXThrow(OpLoc, Ex, IsThrownVarInScope);
}
-ExprResult Sema::BuildCXXThrow(SourceLocation OpLoc, Expr *Ex,
+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))
Diag(OpLoc, diag::err_exceptions_disabled) << "throw";
+ // Exceptions aren't allowed in CUDA device code.
+ if (getLangOpts().CUDA)
+ CUDADiagIfDeviceCode(OpLoc, diag::err_cuda_device_exceptions)
+ << "throw" << CurrentCUDATarget();
+
if (getCurScope() && getCurScope()->isOpenMPSimdDirectiveScope())
Diag(OpLoc, diag::err_omp_simd_region_cannot_use_stmt) << "throw";
@@ -858,13 +863,8 @@ bool Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc,
// We don't keep the instantiated default argument expressions around so
// we must rebuild them here.
for (unsigned I = 1, E = CD->getNumParams(); I != E; ++I) {
- // Skip any default arguments that we've already instantiated.
- if (Context.getDefaultArgExprForConstructor(CD, I))
- continue;
-
- Expr *DefaultArg =
- BuildCXXDefaultArgExpr(ThrowLoc, CD, CD->getParamDecl(I)).get();
- Context.addDefaultArgExprForConstructor(CD, I, DefaultArg);
+ if (CheckCXXDefaultArgExpr(ThrowLoc, CD, CD->getParamDecl(I)))
+ return true;
}
}
}
@@ -903,10 +903,10 @@ static QualType adjustCVQualifiersForCXXThisWithinLambda(
I-- && isa<LambdaScopeInfo>(FunctionScopes[I]);
CurDC = getLambdaAwareParentOfDeclContext(CurDC)) {
CurLSI = cast<LambdaScopeInfo>(FunctionScopes[I]);
-
- if (!CurLSI->isCXXThisCaptured())
+
+ if (!CurLSI->isCXXThisCaptured())
continue;
-
+
auto C = CurLSI->getCXXThisCapture();
if (C.isCopyCapture()) {
@@ -922,7 +922,7 @@ static QualType adjustCVQualifiersForCXXThisWithinLambda(
assert(CurLSI);
assert(isGenericLambdaCallOperatorSpecialization(CurLSI->CallOperator));
assert(CurDC == getLambdaAwareParentOfDeclContext(CurLSI->CallOperator));
-
+
auto IsThisCaptured =
[](CXXRecordDecl *Closure, bool &IsByCopy, bool &IsConst) {
IsConst = false;
@@ -992,10 +992,10 @@ QualType Sema::getCurrentThisType() {
return ThisTy;
}
-Sema::CXXThisScopeRAII::CXXThisScopeRAII(Sema &S,
+Sema::CXXThisScopeRAII::CXXThisScopeRAII(Sema &S,
Decl *ContextDecl,
unsigned CXXThisTypeQuals,
- bool Enabled)
+ bool Enabled)
: S(S), OldCXXThisTypeOverride(S.CXXThisTypeOverride), Enabled(false)
{
if (!Enabled || !ContextDecl)
@@ -1006,13 +1006,13 @@ Sema::CXXThisScopeRAII::CXXThisScopeRAII(Sema &S,
Record = Template->getTemplatedDecl();
else
Record = cast<CXXRecordDecl>(ContextDecl);
-
+
// We care only for CVR qualifiers here, so cut everything else.
CXXThisTypeQuals &= Qualifiers::FastMask;
S.CXXThisTypeOverride
= S.Context.getPointerType(
S.Context.getRecordType(Record).withCVRQualifiers(CXXThisTypeQuals));
-
+
this->Enabled = true;
}
@@ -1026,7 +1026,7 @@ Sema::CXXThisScopeRAII::~CXXThisScopeRAII() {
static Expr *captureThis(Sema &S, ASTContext &Context, RecordDecl *RD,
QualType ThisTy, SourceLocation Loc,
const bool ByCopy) {
-
+
QualType AdjustedThisTy = ThisTy;
// The type of the corresponding data member (not a 'this' pointer if 'by
// copy').
@@ -1039,7 +1039,7 @@ static Expr *captureThis(Sema &S, ASTContext &Context, RecordDecl *RD,
CaptureThisFieldTy.removeLocalCVRQualifiers(Qualifiers::CVRMask);
AdjustedThisTy = Context.getPointerType(CaptureThisFieldTy);
}
-
+
FieldDecl *Field = FieldDecl::Create(
Context, RD, Loc, Loc, nullptr, CaptureThisFieldTy,
Context.getTrivialTypeSourceInfo(CaptureThisFieldTy, Loc), nullptr, false,
@@ -1065,24 +1065,24 @@ static Expr *captureThis(Sema &S, ASTContext &Context, RecordDecl *RD,
return This;
}
-bool Sema::CheckCXXThisCapture(SourceLocation Loc, const bool Explicit,
+bool Sema::CheckCXXThisCapture(SourceLocation Loc, const bool Explicit,
bool BuildAndDiagnose, const unsigned *const FunctionScopeIndexToStopAt,
const bool ByCopy) {
// We don't need to capture this in an unevaluated context.
if (isUnevaluatedContext() && !Explicit)
return true;
-
+
assert((!ByCopy || Explicit) && "cannot implicitly capture *this by value");
const unsigned 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
- // MaxFunctionScopesIndex-deep on the FunctionScopes stack.
+ // by the capturing-entity/closure (lambda/block/etc) at
+ // MaxFunctionScopesIndex-deep on the FunctionScopes stack.
- // Note: The *enclosing object* can only be captured by-value by a
- // closure that is a lambda, using the explicit notation:
+ // Note: The *enclosing object* can only be captured by-value by a
+ // closure that is a lambda, using the explicit notation:
// [*this] { ... }.
// Every other capture of the *enclosing object* results in its by-reference
// capture.
@@ -1091,15 +1091,15 @@ bool Sema::CheckCXXThisCapture(SourceLocation Loc, const bool Explicit,
// stack), we can capture the *enclosing object* only if:
// - 'L' has an explicit byref or byval capture of the *enclosing object*
// - or, 'L' has an implicit capture.
- // AND
+ // AND
// -- there is no enclosing closure
- // -- or, there is some enclosing closure 'E' that has already captured the
- // *enclosing object*, and every intervening closure (if any) between 'E'
+ // -- or, there is some enclosing closure 'E' that has already captured the
+ // *enclosing object*, and every intervening closure (if any) between 'E'
// and 'L' can implicitly capture the *enclosing object*.
- // -- or, every enclosing closure can implicitly capture the
+ // -- or, every enclosing closure can implicitly capture the
// *enclosing object*
-
-
+
+
unsigned NumCapturingClosures = 0;
for (unsigned idx = MaxFunctionScopesIndex; idx != 0; idx--) {
if (CapturingScopeInfo *CSI =
@@ -1145,7 +1145,7 @@ bool Sema::CheckCXXThisCapture(SourceLocation Loc, const bool Explicit,
// In the loop below, respect the ByCopy flag only for the closure requesting
// the capture (i.e. first iteration through the loop below). Ignore it for
- // all enclosing closure's upto NumCapturingClosures (since they must be
+ // all enclosing closure's up to NumCapturingClosures (since they must be
// implicitly capturing the *enclosing object* by reference (see loop
// above)).
assert((!ByCopy ||
@@ -1155,18 +1155,18 @@ 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;
+ for (unsigned idx = MaxFunctionScopesIndex; NumCapturingClosures;
--idx, --NumCapturingClosures) {
CapturingScopeInfo *CSI = cast<CapturingScopeInfo>(FunctionScopes[idx]);
Expr *ThisExpr = nullptr;
-
+
if (LambdaScopeInfo *LSI = dyn_cast<LambdaScopeInfo>(CSI)) {
// For lambda expressions, build a field and an initializing expression,
// and capture the *enclosing object* by copy only if this is the first
// iteration.
ThisExpr = captureThis(*this, Context, LSI->Lambda, ThisTy, Loc,
ByCopy && idx == MaxFunctionScopesIndex);
-
+
} else if (CapturedRegionScopeInfo *RSI
= dyn_cast<CapturedRegionScopeInfo>(FunctionScopes[idx]))
ThisExpr =
@@ -1196,7 +1196,7 @@ bool Sema::isThisOutsideMemberFunctionBody(QualType BaseType) {
// type for 'this'.
if (CXXThisTypeOverride.isNull())
return false;
-
+
// Determine whether we're looking into a class that's currently being
// defined.
CXXRecordDecl *Class = BaseType->getAsCXXRecordDecl();
@@ -1216,6 +1216,17 @@ Sema::ActOnCXXTypeConstructExpr(ParsedType TypeRep,
if (!TInfo)
TInfo = Context.getTrivialTypeSourceInfo(Ty, SourceLocation());
+ // Handle errors like: int({0})
+ if (exprs.size() == 1 && !canInitializeWithParenthesizedList(Ty) &&
+ LParenLoc.isValid() && RParenLoc.isValid())
+ if (auto IList = dyn_cast<InitListExpr>(exprs[0])) {
+ Diag(TInfo->getTypeLoc().getLocStart(), diag::err_list_init_in_parens)
+ << Ty << IList->getSourceRange()
+ << FixItHint::CreateRemoval(LParenLoc)
+ << FixItHint::CreateRemoval(RParenLoc);
+ LParenLoc = RParenLoc = SourceLocation();
+ }
+
auto Result = BuildCXXTypeConstructExpr(TInfo, LParenLoc, exprs, RParenLoc);
// Avoid creating a non-type-dependent expression that contains typos.
// Non-type-dependent expressions are liable to be discarded without
@@ -1280,10 +1291,6 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo,
diag::err_invalid_incomplete_type_use, FullRange))
return ExprError();
- if (RequireNonAbstractType(TyBeginLoc, Ty,
- diag::err_allocation_of_abstract_type))
- return ExprError();
-
InitializedEntity Entity = InitializedEntity::InitializeTemporary(TInfo);
InitializationKind Kind =
Exprs.size() ? ListInitialization
@@ -1317,8 +1324,133 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo,
return Result;
}
-/// doesUsualArrayDeleteWantSize - Answers whether the usual
-/// operator delete[] for the given type has a size_t parameter.
+/// \brief Determine whether the given function is a non-placement
+/// deallocation function.
+static bool isNonPlacementDeallocationFunction(Sema &S, FunctionDecl *FD) {
+ if (FD->isInvalidDecl())
+ return false;
+
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FD))
+ return Method->isUsualDeallocationFunction();
+
+ if (FD->getOverloadedOperator() != OO_Delete &&
+ FD->getOverloadedOperator() != OO_Array_Delete)
+ return false;
+
+ unsigned UsualParams = 1;
+
+ if (S.getLangOpts().SizedDeallocation && UsualParams < FD->getNumParams() &&
+ S.Context.hasSameUnqualifiedType(
+ FD->getParamDecl(UsualParams)->getType(),
+ S.Context.getSizeType()))
+ ++UsualParams;
+
+ if (S.getLangOpts().AlignedAllocation && UsualParams < FD->getNumParams() &&
+ S.Context.hasSameUnqualifiedType(
+ FD->getParamDecl(UsualParams)->getType(),
+ S.Context.getTypeDeclType(S.getStdAlignValT())))
+ ++UsualParams;
+
+ return UsualParams == FD->getNumParams();
+}
+
+namespace {
+ struct UsualDeallocFnInfo {
+ UsualDeallocFnInfo() : Found(), FD(nullptr) {}
+ UsualDeallocFnInfo(Sema &S, DeclAccessPair Found)
+ : Found(Found), FD(dyn_cast<FunctionDecl>(Found->getUnderlyingDecl())),
+ HasSizeT(false), HasAlignValT(false), CUDAPref(Sema::CFP_Native) {
+ // A function template declaration is never a usual deallocation function.
+ if (!FD)
+ return;
+ if (FD->getNumParams() == 3)
+ HasAlignValT = HasSizeT = true;
+ else if (FD->getNumParams() == 2) {
+ HasSizeT = FD->getParamDecl(1)->getType()->isIntegerType();
+ HasAlignValT = !HasSizeT;
+ }
+
+ // In CUDA, determine how much we'd like / dislike to call this.
+ if (S.getLangOpts().CUDA)
+ if (auto *Caller = dyn_cast<FunctionDecl>(S.CurContext))
+ CUDAPref = S.IdentifyCUDAPreference(Caller, FD);
+ }
+
+ operator bool() const { return FD; }
+
+ bool isBetterThan(const UsualDeallocFnInfo &Other, bool WantSize,
+ bool WantAlign) const {
+ // C++17 [expr.delete]p10:
+ // If the type has new-extended alignment, a function with a parameter
+ // of type std::align_val_t is preferred; otherwise a function without
+ // such a parameter is preferred
+ if (HasAlignValT != Other.HasAlignValT)
+ return HasAlignValT == WantAlign;
+
+ if (HasSizeT != Other.HasSizeT)
+ return HasSizeT == WantSize;
+
+ // Use CUDA call preference as a tiebreaker.
+ return CUDAPref > Other.CUDAPref;
+ }
+
+ DeclAccessPair Found;
+ FunctionDecl *FD;
+ bool HasSizeT, HasAlignValT;
+ Sema::CUDAFunctionPreference CUDAPref;
+ };
+}
+
+/// Determine whether a type has new-extended alignment. This may be called when
+/// the type is incomplete (for a delete-expression with an incomplete pointee
+/// type), in which case it will conservatively return false if the alignment is
+/// not known.
+static bool hasNewExtendedAlignment(Sema &S, QualType AllocType) {
+ return S.getLangOpts().AlignedAllocation &&
+ S.getASTContext().getTypeAlignIfKnown(AllocType) >
+ S.getASTContext().getTargetInfo().getNewAlign();
+}
+
+/// Select the correct "usual" deallocation function to use from a selection of
+/// deallocation functions (either global or class-scope).
+static UsualDeallocFnInfo resolveDeallocationOverload(
+ Sema &S, LookupResult &R, bool WantSize, bool WantAlign,
+ llvm::SmallVectorImpl<UsualDeallocFnInfo> *BestFns = nullptr) {
+ UsualDeallocFnInfo Best;
+
+ for (auto I = R.begin(), E = R.end(); I != E; ++I) {
+ UsualDeallocFnInfo Info(S, I.getPair());
+ if (!Info || !isNonPlacementDeallocationFunction(S, Info.FD) ||
+ Info.CUDAPref == Sema::CFP_Never)
+ continue;
+
+ if (!Best) {
+ Best = Info;
+ if (BestFns)
+ BestFns->push_back(Info);
+ continue;
+ }
+
+ if (Best.isBetterThan(Info, WantSize, WantAlign))
+ continue;
+
+ // If more than one preferred function is found, all non-preferred
+ // functions are eliminated from further consideration.
+ if (BestFns && Info.isBetterThan(Best, WantSize, WantAlign))
+ BestFns->clear();
+
+ Best = Info;
+ if (BestFns)
+ BestFns->push_back(Info);
+ }
+
+ return Best;
+}
+
+/// Determine whether a given type is a class for which 'delete[]' would call
+/// a member 'operator delete[]' with a 'size_t' parameter. This implies that
+/// we need to store the array size (even if the type is
+/// trivially-destructible).
static bool doesUsualArrayDeleteWantSize(Sema &S, SourceLocation loc,
QualType allocType) {
const RecordType *record =
@@ -1342,35 +1474,13 @@ static bool doesUsualArrayDeleteWantSize(Sema &S, SourceLocation loc,
// on this thing, so it doesn't matter if we allocate extra space or not.
if (ops.isAmbiguous()) return false;
- LookupResult::Filter filter = ops.makeFilter();
- while (filter.hasNext()) {
- NamedDecl *del = filter.next()->getUnderlyingDecl();
-
- // C++0x [basic.stc.dynamic.deallocation]p2:
- // A template instance is never a usual deallocation function,
- // regardless of its signature.
- if (isa<FunctionTemplateDecl>(del)) {
- filter.erase();
- continue;
- }
-
- // C++0x [basic.stc.dynamic.deallocation]p2:
- // If class T does not declare [an operator delete[] with one
- // parameter] but does declare a member deallocation function
- // named operator delete[] with exactly two parameters, the
- // second of which has type std::size_t, then this function
- // is a usual deallocation function.
- if (!cast<CXXMethodDecl>(del)->isUsualDeallocationFunction()) {
- filter.erase();
- continue;
- }
- }
- filter.done();
-
- if (!ops.isSingleResult()) return false;
-
- const FunctionDecl *del = cast<FunctionDecl>(ops.getFoundDecl());
- return (del->getNumParams() == 2);
+ // C++17 [expr.delete]p10:
+ // If the deallocation functions have class scope, the one without a
+ // parameter of type std::size_t is selected.
+ auto Best = resolveDeallocationOverload(
+ S, ops, /*WantSize*/false,
+ /*WantAlign*/hasNewExtendedAlignment(S, allocType));
+ return Best && Best.HasSizeT;
}
/// \brief Parsed a C++ 'new' expression (C++ 5.3.4).
@@ -1454,8 +1564,20 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
return ExprError();
SourceRange DirectInitRange;
- if (ParenListExpr *List = dyn_cast_or_null<ParenListExpr>(Initializer))
+ if (ParenListExpr *List = dyn_cast_or_null<ParenListExpr>(Initializer)) {
DirectInitRange = List->getSourceRange();
+ // Handle errors like: new int a({0})
+ if (List->getNumExprs() == 1 &&
+ !canInitializeWithParenthesizedList(AllocType))
+ if (auto IList = dyn_cast<InitListExpr>(List->getExpr(0))) {
+ Diag(TInfo->getTypeLoc().getLocStart(), diag::err_list_init_in_parens)
+ << AllocType << List->getSourceRange()
+ << FixItHint::CreateRemoval(List->getLocStart())
+ << FixItHint::CreateRemoval(List->getLocEnd());
+ DirectInitRange = SourceRange();
+ Initializer = IList;
+ }
+ }
return BuildCXXNew(SourceRange(StartLoc, D.getLocEnd()), UseGlobal,
PlacementLParen,
@@ -1574,7 +1696,7 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
<< /*at end of FE*/0 << Inits[0]->getSourceRange();
}
- // In ARC, infer 'retaining' for the allocated
+ // In ARC, infer 'retaining' for the allocated
if (getLangOpts().ObjCAutoRefCount &&
AllocType.getObjCLifetime() == Qualifiers::OCL_None &&
AllocType->isObjCLifetimeType()) {
@@ -1583,7 +1705,7 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
}
QualType ResultType = Context.getPointerType(AllocType);
-
+
if (ArraySize && ArraySize->getType()->isNonOverloadPlaceholderType()) {
ExprResult result = CheckPlaceholderExpr(ArraySize);
if (result.isInvalid()) return ExprError();
@@ -1596,6 +1718,7 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
// conversion function to integral or unscoped enumeration type exists.
// C++1y [expr.new]p6: The expression [...] is implicitly converted to
// std::size_t.
+ llvm::Optional<uint64_t> KnownArraySize;
if (ArraySize && !ArraySize->isTypeDependent()) {
ExprResult ConvertedSize;
if (getLangOpts().CPlusPlus14) {
@@ -1604,7 +1727,7 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
ConvertedSize = PerformImplicitConversion(ArraySize, Context.getSizeType(),
AA_Converting);
- if (!ConvertedSize.isInvalid() &&
+ if (!ConvertedSize.isInvalid() &&
ArraySize->getType()->getAs<RecordType>())
// Diagnose the compatibility of this conversion.
Diag(StartLoc, diag::warn_cxx98_compat_array_size_conversion)
@@ -1613,7 +1736,7 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
class SizeConvertDiagnoser : public ICEConvertDiagnoser {
protected:
Expr *ArraySize;
-
+
public:
SizeConvertDiagnoser(Expr *ArraySize)
: ICEConvertDiagnoser(/*AllowScopedEnumerations*/false, false, false),
@@ -1680,44 +1803,34 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
// The expression in a direct-new-declarator shall have integral type
// with a non-negative value.
//
- // Let's see if this is a constant < 0. If so, we reject it out of
- // hand. Otherwise, if it's not a constant, we must have an unparenthesized
- // array type.
- //
- // Note: such a construct has well-defined semantics in C++11: it throws
- // std::bad_array_new_length.
+ // Let's see if this is a constant < 0. If so, we reject it out of hand,
+ // per CWG1464. Otherwise, if it's not a constant, we must have an
+ // unparenthesized array type.
if (!ArraySize->isValueDependent()) {
llvm::APSInt Value;
// We've already performed any required implicit conversion to integer or
// unscoped enumeration type.
+ // FIXME: Per CWG1464, we are required to check the value prior to
+ // converting to size_t. This will never find a negative array size in
+ // C++14 onwards, because Value is always unsigned here!
if (ArraySize->isIntegerConstantExpr(Value, Context)) {
- if (Value < llvm::APSInt(
- llvm::APInt::getNullValue(Value.getBitWidth()),
- Value.isUnsigned())) {
- if (getLangOpts().CPlusPlus11)
- Diag(ArraySize->getLocStart(),
- diag::warn_typecheck_negative_array_new_size)
- << ArraySize->getSourceRange();
- else
- return ExprError(Diag(ArraySize->getLocStart(),
- diag::err_typecheck_negative_array_size)
- << ArraySize->getSourceRange());
- } else if (!AllocType->isDependentType()) {
+ if (Value.isSigned() && Value.isNegative()) {
+ return ExprError(Diag(ArraySize->getLocStart(),
+ diag::err_typecheck_negative_array_size)
+ << ArraySize->getSourceRange());
+ }
+
+ if (!AllocType->isDependentType()) {
unsigned ActiveSizeBits =
ConstantArrayType::getNumAddressingBits(Context, AllocType, Value);
- if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context)) {
- if (getLangOpts().CPlusPlus11)
- Diag(ArraySize->getLocStart(),
- diag::warn_array_new_too_large)
- << Value.toString(10)
- << ArraySize->getSourceRange();
- else
- return ExprError(Diag(ArraySize->getLocStart(),
- diag::err_array_too_large)
- << Value.toString(10)
- << ArraySize->getSourceRange());
- }
+ if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context))
+ return ExprError(Diag(ArraySize->getLocStart(),
+ diag::err_array_too_large)
+ << Value.toString(10)
+ << ArraySize->getSourceRange());
}
+
+ KnownArraySize = Value.getZExtValue();
} else if (TypeIdParens.isValid()) {
// Can't have dynamic array size when the type-id is in parentheses.
Diag(ArraySize->getLocStart(), diag::ext_new_paren_array_nonconst)
@@ -1735,21 +1848,26 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
FunctionDecl *OperatorNew = nullptr;
FunctionDecl *OperatorDelete = nullptr;
+ unsigned Alignment =
+ AllocType->isDependentType() ? 0 : Context.getTypeAlign(AllocType);
+ unsigned NewAlignment = Context.getTargetInfo().getNewAlign();
+ bool PassAlignment = getLangOpts().AlignedAllocation &&
+ Alignment > NewAlignment;
if (!AllocType->isDependentType() &&
!Expr::hasAnyTypeDependentArguments(PlacementArgs) &&
FindAllocationFunctions(StartLoc,
SourceRange(PlacementLParen, PlacementRParen),
- UseGlobal, AllocType, ArraySize, PlacementArgs,
- OperatorNew, OperatorDelete))
+ UseGlobal, AllocType, ArraySize, PassAlignment,
+ PlacementArgs, OperatorNew, OperatorDelete))
return ExprError();
// If this is an array allocation, compute whether the usual array
// deallocation function for the type has a size_t parameter.
bool UsualArrayDeleteWantsSize = false;
if (ArraySize && !AllocType->isDependentType())
- UsualArrayDeleteWantsSize
- = doesUsualArrayDeleteWantSize(*this, StartLoc, AllocType);
+ UsualArrayDeleteWantsSize =
+ doesUsualArrayDeleteWantSize(*this, StartLoc, AllocType);
SmallVector<Expr *, 8> AllPlaceArgs;
if (OperatorNew) {
@@ -1760,9 +1878,11 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
// We've already converted the placement args, just fill in any default
// arguments. Skip the first parameter because we don't have a corresponding
- // argument.
- if (GatherArgumentsForCall(PlacementLParen, OperatorNew, Proto, 1,
- PlacementArgs, AllPlaceArgs, CallType))
+ // argument. Skip the second parameter too if we're passing in the
+ // alignment; we've already filled it in.
+ if (GatherArgumentsForCall(PlacementLParen, OperatorNew, Proto,
+ PassAlignment ? 2 : 1, PlacementArgs,
+ AllPlaceArgs, CallType))
return ExprError();
if (!AllPlaceArgs.empty())
@@ -1772,44 +1892,29 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
DiagnoseSentinelCalls(OperatorNew, PlacementLParen, PlacementArgs);
// FIXME: Missing call to CheckFunctionCall or equivalent
- }
- // Warn if the type is over-aligned and is being allocated by global operator
- // new.
- if (PlacementArgs.empty() && OperatorNew &&
- (OperatorNew->isImplicit() ||
- (OperatorNew->getLocStart().isValid() &&
- getSourceManager().isInSystemHeader(OperatorNew->getLocStart())))) {
- if (unsigned Align = Context.getPreferredTypeAlign(AllocType.getTypePtr())){
- unsigned SuitableAlign = Context.getTargetInfo().getSuitableAlign();
- if (Align > SuitableAlign)
+ // Warn if the type is over-aligned and is being allocated by (unaligned)
+ // global operator new.
+ if (PlacementArgs.empty() && !PassAlignment &&
+ (OperatorNew->isImplicit() ||
+ (OperatorNew->getLocStart().isValid() &&
+ getSourceManager().isInSystemHeader(OperatorNew->getLocStart())))) {
+ if (Alignment > NewAlignment)
Diag(StartLoc, diag::warn_overaligned_type)
<< AllocType
- << unsigned(Align / Context.getCharWidth())
- << unsigned(SuitableAlign / Context.getCharWidth());
+ << unsigned(Alignment / Context.getCharWidth())
+ << unsigned(NewAlignment / Context.getCharWidth());
}
}
- QualType InitType = AllocType;
// Array 'new' can't have any initializers except empty parentheses.
// Initializer lists are also allowed, in C++11. Rely on the parser for the
// dialect distinction.
- if (ResultType->isArrayType() || ArraySize) {
- if (!isLegalArrayNewInitializer(initStyle, Initializer)) {
- SourceRange InitRange(Inits[0]->getLocStart(),
- Inits[NumInits - 1]->getLocEnd());
- Diag(StartLoc, diag::err_new_array_init_args) << InitRange;
- return ExprError();
- }
- if (InitListExpr *ILE = dyn_cast_or_null<InitListExpr>(Initializer)) {
- // We do the initialization typechecking against the array type
- // corresponding to the number of initializers + 1 (to also check
- // default-initialization).
- unsigned NumElements = ILE->getNumInits() + 1;
- InitType = Context.getConstantArrayType(AllocType,
- llvm::APInt(Context.getTypeSize(Context.getSizeType()), NumElements),
- ArrayType::Normal, 0);
- }
+ if (ArraySize && !isLegalArrayNewInitializer(initStyle, Initializer)) {
+ SourceRange InitRange(Inits[0]->getLocStart(),
+ Inits[NumInits - 1]->getLocEnd());
+ Diag(StartLoc, diag::err_new_array_init_args) << InitRange;
+ return ExprError();
}
// If we can perform the initialization, and we've not already done so,
@@ -1817,6 +1922,19 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
if (!AllocType->isDependentType() &&
!Expr::hasAnyTypeDependentArguments(
llvm::makeArrayRef(Inits, NumInits))) {
+ // The type we initialize is the complete type, including the array bound.
+ QualType InitType;
+ if (KnownArraySize)
+ InitType = Context.getConstantArrayType(
+ AllocType, llvm::APInt(Context.getTypeSize(Context.getSizeType()),
+ *KnownArraySize),
+ ArrayType::Normal, 0);
+ else if (ArraySize)
+ InitType =
+ Context.getIncompleteArrayType(AllocType, ArrayType::Normal, 0);
+ else
+ InitType = AllocType;
+
// C++11 [expr.new]p15:
// A new-expression that creates an object of type T initializes that
// object as follows:
@@ -1836,7 +1954,8 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
InitializedEntity Entity
= InitializedEntity::InitializeNew(StartLoc, InitType);
- InitializationSequence InitSeq(*this, Entity, Kind, MultiExprArg(Inits, NumInits));
+ InitializationSequence InitSeq(*this, Entity, Kind,
+ MultiExprArg(Inits, NumInits));
ExprResult FullInit = InitSeq.Perform(*this, Entity, Kind,
MultiExprArg(Inits, NumInits));
if (FullInit.isInvalid())
@@ -1844,6 +1963,7 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
// FullInit is our initializer; strip off CXXBindTemporaryExprs, because
// we don't want the initialized object to be destructed.
+ // FIXME: We should not create these in the first place.
if (CXXBindTemporaryExpr *Binder =
dyn_cast_or_null<CXXBindTemporaryExpr>(FullInit.get()))
FullInit = Binder->getSubExpr();
@@ -1872,7 +1992,7 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
if (CXXDestructorDecl *dtor = LookupDestructor(
cast<CXXRecordDecl>(BaseRecordType->getDecl()))) {
MarkFunctionReferenced(StartLoc, dtor);
- CheckDestructorAccess(StartLoc, dtor,
+ CheckDestructorAccess(StartLoc, dtor,
PDiag(diag::err_access_dtor)
<< BaseAllocType);
if (DiagnoseUseOfDecl(dtor, StartLoc))
@@ -1882,7 +2002,7 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
}
return new (Context)
- CXXNewExpr(Context, UseGlobal, OperatorNew, OperatorDelete,
+ CXXNewExpr(Context, UseGlobal, OperatorNew, OperatorDelete, PassAlignment,
UsualArrayDeleteWantsSize, PlacementArgs, TypeIdParens,
ArraySize, initStyle, Initializer, ResultType, AllocTypeInfo,
Range, DirectInitRange);
@@ -1921,36 +2041,132 @@ bool Sema::CheckAllocatedType(QualType AllocType, SourceLocation Loc,
<< BaseAllocType;
}
}
-
+
return false;
}
-/// \brief Determine whether the given function is a non-placement
-/// deallocation function.
-static bool isNonPlacementDeallocationFunction(Sema &S, FunctionDecl *FD) {
- if (FD->isInvalidDecl())
- return false;
+static bool
+resolveAllocationOverload(Sema &S, LookupResult &R, SourceRange Range,
+ SmallVectorImpl<Expr *> &Args, bool &PassAlignment,
+ FunctionDecl *&Operator,
+ OverloadCandidateSet *AlignedCandidates = nullptr,
+ Expr *AlignArg = nullptr) {
+ OverloadCandidateSet Candidates(R.getNameLoc(),
+ OverloadCandidateSet::CSK_Normal);
+ for (LookupResult::iterator Alloc = R.begin(), AllocEnd = R.end();
+ Alloc != AllocEnd; ++Alloc) {
+ // Even member operator new/delete are implicitly treated as
+ // static, so don't use AddMemberCandidate.
+ NamedDecl *D = (*Alloc)->getUnderlyingDecl();
- if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FD))
- return Method->isUsualDeallocationFunction();
+ if (FunctionTemplateDecl *FnTemplate = dyn_cast<FunctionTemplateDecl>(D)) {
+ S.AddTemplateOverloadCandidate(FnTemplate, Alloc.getPair(),
+ /*ExplicitTemplateArgs=*/nullptr, Args,
+ Candidates,
+ /*SuppressUserConversions=*/false);
+ continue;
+ }
- if (FD->getOverloadedOperator() != OO_Delete &&
- FD->getOverloadedOperator() != OO_Array_Delete)
+ FunctionDecl *Fn = cast<FunctionDecl>(D);
+ S.AddOverloadCandidate(Fn, Alloc.getPair(), Args, Candidates,
+ /*SuppressUserConversions=*/false);
+ }
+
+ // Do the resolution.
+ OverloadCandidateSet::iterator Best;
+ switch (Candidates.BestViableFunction(S, R.getNameLoc(), Best)) {
+ case OR_Success: {
+ // Got one!
+ FunctionDecl *FnDecl = Best->Function;
+ if (S.CheckAllocationAccess(R.getNameLoc(), Range, R.getNamingClass(),
+ Best->FoundDecl) == Sema::AR_inaccessible)
+ return true;
+
+ Operator = FnDecl;
return false;
+ }
+
+ case OR_No_Viable_Function:
+ // C++17 [expr.new]p13:
+ // If no matching function is found and the allocated object type has
+ // new-extended alignment, the alignment argument is removed from the
+ // argument list, and overload resolution is performed again.
+ if (PassAlignment) {
+ PassAlignment = false;
+ AlignArg = Args[1];
+ Args.erase(Args.begin() + 1);
+ return resolveAllocationOverload(S, R, Range, Args, PassAlignment,
+ Operator, &Candidates, AlignArg);
+ }
- if (FD->getNumParams() == 1)
+ // MSVC will fall back on trying to find a matching global operator new
+ // if operator new[] cannot be found. Also, MSVC will leak by not
+ // generating a call to operator delete or operator delete[], but we
+ // will not replicate that bug.
+ // FIXME: Find out how this interacts with the std::align_val_t fallback
+ // once MSVC implements it.
+ if (R.getLookupName().getCXXOverloadedOperator() == OO_Array_New &&
+ S.Context.getLangOpts().MSVCCompat) {
+ R.clear();
+ R.setLookupName(S.Context.DeclarationNames.getCXXOperatorName(OO_New));
+ 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);
+ }
+
+ 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);
return true;
- return S.getLangOpts().SizedDeallocation && FD->getNumParams() == 2 &&
- S.Context.hasSameUnqualifiedType(FD->getParamDecl(1)->getType(),
- S.Context.getSizeType());
+ 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");
}
+
/// 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, MultiExprArg PlaceArgs,
+ bool IsArray, bool &PassAlignment,
+ MultiExprArg PlaceArgs,
FunctionDecl *&OperatorNew,
FunctionDecl *&OperatorDelete) {
// --- Choosing an allocation function ---
@@ -1962,16 +2178,29 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
// 3) The first argument is always size_t. Append the arguments from the
// placement form.
- SmallVector<Expr*, 8> AllocArgs(1 + PlaceArgs.size());
- // We don't care about the actual value of this argument.
+ SmallVector<Expr*, 8> AllocArgs;
+ AllocArgs.reserve((PassAlignment ? 2 : 1) + PlaceArgs.size());
+
+ // We don't care about the actual value of these arguments.
// FIXME: Should the Sema create the expression and embed it in the syntax
// tree? Or should the consumer just recalculate the value?
+ // FIXME: Using a dummy value will interact poorly with attribute enable_if.
IntegerLiteral Size(Context, llvm::APInt::getNullValue(
Context.getTargetInfo().getPointerWidth(0)),
Context.getSizeType(),
SourceLocation());
- AllocArgs[0] = &Size;
- std::copy(PlaceArgs.begin(), PlaceArgs.end(), AllocArgs.begin() + 1);
+ AllocArgs.push_back(&Size);
+
+ QualType AlignValT = Context.VoidTy;
+ if (PassAlignment) {
+ DeclareGlobalNewDelete();
+ AlignValT = Context.getTypeDeclType(getStdAlignValT());
+ }
+ CXXScalarValueInitExpr Align(AlignValT, nullptr, SourceLocation());
+ if (PassAlignment)
+ AllocArgs.push_back(&Align);
+
+ AllocArgs.insert(AllocArgs.end(), PlaceArgs.begin(), PlaceArgs.end());
// C++ [expr.new]p8:
// If the allocated type is a non-array type, the allocation
@@ -1980,50 +2209,57 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
// type, the allocation function's name is operator new[] and the
// deallocation function's name is operator delete[].
DeclarationName NewName = Context.DeclarationNames.getCXXOperatorName(
- IsArray ? OO_Array_New : OO_New);
- DeclarationName DeleteName = Context.DeclarationNames.getCXXOperatorName(
- IsArray ? OO_Array_Delete : OO_Delete);
+ IsArray ? OO_Array_New : OO_New);
QualType AllocElemType = Context.getBaseElementType(AllocType);
- if (AllocElemType->isRecordType() && !UseGlobal) {
- CXXRecordDecl *Record
- = cast<CXXRecordDecl>(AllocElemType->getAs<RecordType>()->getDecl());
- if (FindAllocationOverload(StartLoc, Range, NewName, AllocArgs, Record,
- /*AllowMissing=*/true, OperatorNew))
+ // Find the allocation function.
+ {
+ LookupResult R(*this, NewName, StartLoc, LookupOrdinaryName);
+
+ // C++1z [expr.new]p9:
+ // If the new-expression begins with a unary :: operator, the allocation
+ // 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)
+ LookupQualifiedName(R, AllocElemType->getAsCXXRecordDecl());
+
+ // We can see ambiguity here if the allocation function is found in
+ // multiple base classes.
+ if (R.isAmbiguous())
return true;
- }
- if (!OperatorNew) {
- // Didn't find a member overload. Look for a global one.
- DeclareGlobalNewDelete();
- DeclContext *TUDecl = Context.getTranslationUnitDecl();
- bool FallbackEnabled = IsArray && Context.getLangOpts().MSVCCompat;
- if (FindAllocationOverload(StartLoc, Range, NewName, AllocArgs, TUDecl,
- /*AllowMissing=*/FallbackEnabled, OperatorNew,
- /*Diagnose=*/!FallbackEnabled)) {
- if (!FallbackEnabled)
- return true;
+ // 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())
+ LookupQualifiedName(R, Context.getTranslationUnitDecl());
+
+ assert(!R.empty() && "implicitly declared allocation functions not found");
+ assert(!R.isAmbiguous() && "global allocation functions are ambiguous");
- // MSVC will fall back on trying to find a matching global operator new
- // if operator new[] cannot be found. Also, MSVC will leak by not
- // generating a call to operator delete or operator delete[], but we
- // will not replicate that bug.
- NewName = Context.DeclarationNames.getCXXOperatorName(OO_New);
- DeleteName = Context.DeclarationNames.getCXXOperatorName(OO_Delete);
- if (FindAllocationOverload(StartLoc, Range, NewName, AllocArgs, TUDecl,
- /*AllowMissing=*/false, OperatorNew))
+ // We do our own custom access checks below.
+ R.suppressDiagnostics();
+
+ if (resolveAllocationOverload(*this, R, Range, AllocArgs, PassAlignment,
+ OperatorNew))
return true;
- }
}
- // We don't need an operator delete if we're running under
- // -fno-exceptions.
+ // We don't need an operator delete if we're running under -fno-exceptions.
if (!getLangOpts().Exceptions) {
OperatorDelete = nullptr;
return false;
}
+ // Note, the name of OperatorNew might have been changed from array to
+ // non-array by resolveAllocationOverload.
+ DeclarationName DeleteName = Context.DeclarationNames.getCXXOperatorName(
+ OperatorNew->getDeclName().getCXXOverloadedOperator() == OO_Array_New
+ ? OO_Array_Delete
+ : OO_Delete);
+
// C++ [expr.new]p19:
//
// If the new-expression begins with a unary :: operator, the
@@ -2042,6 +2278,7 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
if (FoundDelete.isAmbiguous())
return true; // FIXME: clean up expressions?
+ bool FoundGlobalDelete = FoundDelete.empty();
if (FoundDelete.empty()) {
DeclareGlobalNewDelete();
LookupQualifiedName(FoundDelete, Context.getTranslationUnitDecl());
@@ -2056,7 +2293,16 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
// we had explicit placement arguments. This matters for things like
// struct A { void *operator new(size_t, int = 0); ... };
// A *a = new A()
- bool isPlacementNew = (!PlaceArgs.empty() || OperatorNew->param_size() != 1);
+ //
+ // We don't have any definition for what a "placement allocation function"
+ // is, but we assume it's any allocation function whose
+ // parameter-declaration-clause is anything other than (size_t).
+ //
+ // FIXME: Should (size_t, std::align_val_t) also be considered non-placement?
+ // This affects whether an exception from the constructor of an overaligned
+ // type uses the sized or non-sized form of aligned operator delete.
+ bool isPlacementNew = !PlaceArgs.empty() || OperatorNew->param_size() != 1 ||
+ OperatorNew->isVariadic();
if (isPlacementNew) {
// C++ [expr.new]p20:
@@ -2069,8 +2315,6 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
// To perform this comparison, we compute the function type that
// the deallocation function should have, and use that type both
// for template argument deduction and for comparison purposes.
- //
- // FIXME: this comparison should ignore CC and the like.
QualType ExpectedFunctionType;
{
const FunctionProtoType *Proto
@@ -2082,6 +2326,7 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
ArgTypes.push_back(Proto->getParamType(I));
FunctionProtoType::ExtProtoInfo EPI;
+ // FIXME: This is not part of the standard's rule.
EPI.Variadic = Proto->isVariadic();
ExpectedFunctionType
@@ -2092,8 +2337,8 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
DEnd = FoundDelete.end();
D != DEnd; ++D) {
FunctionDecl *Fn = nullptr;
- if (FunctionTemplateDecl *FnTmpl
- = dyn_cast<FunctionTemplateDecl>((*D)->getUnderlyingDecl())) {
+ if (FunctionTemplateDecl *FnTmpl =
+ dyn_cast<FunctionTemplateDecl>((*D)->getUnderlyingDecl())) {
// Perform template argument deduction to try to match the
// expected function type.
TemplateDeductionInfo Info(StartLoc);
@@ -2103,38 +2348,35 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
} else
Fn = cast<FunctionDecl>((*D)->getUnderlyingDecl());
- if (Context.hasSameType(Fn->getType(), ExpectedFunctionType))
+ if (Context.hasSameType(adjustCCAndNoReturn(Fn->getType(),
+ ExpectedFunctionType,
+ /*AdjustExcpetionSpec*/true),
+ ExpectedFunctionType))
Matches.push_back(std::make_pair(D.getPair(), Fn));
}
- } else {
- // C++ [expr.new]p20:
- // [...] Any non-placement deallocation function matches a
- // non-placement allocation function. [...]
- for (LookupResult::iterator D = FoundDelete.begin(),
- DEnd = FoundDelete.end();
- D != DEnd; ++D) {
- if (FunctionDecl *Fn = dyn_cast<FunctionDecl>((*D)->getUnderlyingDecl()))
- if (isNonPlacementDeallocationFunction(*this, Fn))
- Matches.push_back(std::make_pair(D.getPair(), Fn));
- }
+ if (getLangOpts().CUDA)
+ EraseUnwantedCUDAMatches(dyn_cast<FunctionDecl>(CurContext), Matches);
+ } else {
// C++1y [expr.new]p22:
// For a non-placement allocation function, the normal deallocation
// function lookup is used
- // C++1y [expr.delete]p?:
- // If [...] deallocation function lookup finds both a usual deallocation
- // function with only a pointer parameter and a usual deallocation
- // function with both a pointer parameter and a size parameter, then the
- // selected deallocation function shall be the one with two parameters.
- // Otherwise, the selected deallocation function shall be the function
- // with one parameter.
- if (getLangOpts().SizedDeallocation && Matches.size() == 2) {
- if (Matches[0].second->getNumParams() == 1)
- Matches.erase(Matches.begin());
- else
- Matches.erase(Matches.begin() + 1);
- assert(Matches[0].second->getNumParams() == 2 &&
- "found an unexpected usual deallocation function");
+ //
+ // Per [expr.delete]p10, this lookup prefers a member operator delete
+ // without a size_t argument, but prefers a non-member operator delete
+ // with a size_t where possible (which it always is in this case).
+ llvm::SmallVector<UsualDeallocFnInfo, 4> BestDeallocFns;
+ UsualDeallocFnInfo Selected = resolveDeallocationOverload(
+ *this, FoundDelete, /*WantSize*/ FoundGlobalDelete,
+ /*WantAlign*/ hasNewExtendedAlignment(*this, AllocElemType),
+ &BestDeallocFns);
+ if (Selected)
+ Matches.push_back(std::make_pair(Selected.Found, Selected.FD));
+ else {
+ // If we failed to select an operator, all remaining functions are viable
+ // but ambiguous.
+ for (auto Fn : BestDeallocFns)
+ Matches.push_back(std::make_pair(Fn.Found, Fn.FD));
}
}
@@ -2145,130 +2387,59 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
if (Matches.size() == 1) {
OperatorDelete = Matches[0].second;
- // C++0x [expr.new]p20:
- // If the lookup finds the two-parameter form of a usual
- // deallocation function (3.7.4.2) and that function, considered
+ // C++1z [expr.new]p23:
+ // If the lookup finds a usual deallocation function (3.7.4.2)
+ // with a parameter of type std::size_t and that function, considered
// as a placement deallocation function, would have been
// selected as a match for the allocation function, the program
// is ill-formed.
- if (!PlaceArgs.empty() && getLangOpts().CPlusPlus11 &&
+ if (getLangOpts().CPlusPlus11 && isPlacementNew &&
isNonPlacementDeallocationFunction(*this, OperatorDelete)) {
- Diag(StartLoc, diag::err_placement_new_non_placement_delete)
- << SourceRange(PlaceArgs.front()->getLocStart(),
- PlaceArgs.back()->getLocEnd());
- if (!OperatorDelete->isImplicit())
- Diag(OperatorDelete->getLocation(), diag::note_previous_decl)
- << DeleteName;
- } else {
- CheckAllocationAccess(StartLoc, Range, FoundDelete.getNamingClass(),
- Matches[0].first);
- }
- }
-
- return false;
-}
-
-/// \brief Find an fitting overload for the allocation function
-/// in the specified scope.
-///
-/// \param StartLoc The location of the 'new' token.
-/// \param Range The range of the placement arguments.
-/// \param Name The name of the function ('operator new' or 'operator new[]').
-/// \param Args The placement arguments specified.
-/// \param Ctx The scope in which we should search; either a class scope or the
-/// translation unit.
-/// \param AllowMissing If \c true, report an error if we can't find any
-/// allocation functions. Otherwise, succeed but don't fill in \p
-/// Operator.
-/// \param Operator Filled in with the found allocation function. Unchanged if
-/// no allocation function was found.
-/// \param Diagnose If \c true, issue errors if the allocation function is not
-/// usable.
-bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,
- DeclarationName Name, MultiExprArg Args,
- DeclContext *Ctx,
- bool AllowMissing, FunctionDecl *&Operator,
- bool Diagnose) {
- LookupResult R(*this, Name, StartLoc, LookupOrdinaryName);
- LookupQualifiedName(R, Ctx);
- if (R.empty()) {
- if (AllowMissing || !Diagnose)
- return false;
- return Diag(StartLoc, diag::err_ovl_no_viable_function_in_call)
- << Name << Range;
- }
-
- if (R.isAmbiguous())
- return true;
-
- R.suppressDiagnostics();
-
- OverloadCandidateSet Candidates(StartLoc, OverloadCandidateSet::CSK_Normal);
- for (LookupResult::iterator Alloc = R.begin(), AllocEnd = R.end();
- Alloc != AllocEnd; ++Alloc) {
- // Even member operator new/delete are implicitly treated as
- // static, so don't use AddMemberCandidate.
- NamedDecl *D = (*Alloc)->getUnderlyingDecl();
+ UsualDeallocFnInfo Info(*this,
+ DeclAccessPair::make(OperatorDelete, AS_public));
+ // Core issue, per mail to core reflector, 2016-10-09:
+ // If this is a member operator delete, and there is a corresponding
+ // non-sized member operator delete, this isn't /really/ a sized
+ // deallocation function, it just happens to have a size_t parameter.
+ bool IsSizedDelete = Info.HasSizeT;
+ if (IsSizedDelete && !FoundGlobalDelete) {
+ auto NonSizedDelete =
+ resolveDeallocationOverload(*this, FoundDelete, /*WantSize*/false,
+ /*WantAlign*/Info.HasAlignValT);
+ if (NonSizedDelete && !NonSizedDelete.HasSizeT &&
+ NonSizedDelete.HasAlignValT == Info.HasAlignValT)
+ IsSizedDelete = false;
+ }
- if (FunctionTemplateDecl *FnTemplate = dyn_cast<FunctionTemplateDecl>(D)) {
- AddTemplateOverloadCandidate(FnTemplate, Alloc.getPair(),
- /*ExplicitTemplateArgs=*/nullptr,
- Args, Candidates,
- /*SuppressUserConversions=*/false);
- continue;
+ if (IsSizedDelete) {
+ SourceRange R = PlaceArgs.empty()
+ ? SourceRange()
+ : SourceRange(PlaceArgs.front()->getLocStart(),
+ PlaceArgs.back()->getLocEnd());
+ Diag(StartLoc, diag::err_placement_new_non_placement_delete) << R;
+ if (!OperatorDelete->isImplicit())
+ Diag(OperatorDelete->getLocation(), diag::note_previous_decl)
+ << DeleteName;
+ }
}
- FunctionDecl *Fn = cast<FunctionDecl>(D);
- AddOverloadCandidate(Fn, Alloc.getPair(), Args, Candidates,
- /*SuppressUserConversions=*/false);
- }
-
- // Do the resolution.
- OverloadCandidateSet::iterator Best;
- switch (Candidates.BestViableFunction(*this, StartLoc, Best)) {
- case OR_Success: {
- // Got one!
- FunctionDecl *FnDecl = Best->Function;
- if (CheckAllocationAccess(StartLoc, Range, R.getNamingClass(),
- Best->FoundDecl, Diagnose) == AR_inaccessible)
- return true;
+ CheckAllocationAccess(StartLoc, Range, FoundDelete.getNamingClass(),
+ Matches[0].first);
+ } else if (!Matches.empty()) {
+ // We found multiple suitable operators. Per [expr.new]p20, that means we
+ // call no 'operator delete' function, but we should at least warn the user.
+ // FIXME: Suppress this warning if the construction cannot throw.
+ Diag(StartLoc, diag::warn_ambiguous_suitable_delete_function_found)
+ << DeleteName << AllocElemType;
- Operator = FnDecl;
- return false;
+ for (auto &Match : Matches)
+ Diag(Match.second->getLocation(),
+ diag::note_member_declared_here) << DeleteName;
}
- case OR_No_Viable_Function:
- if (Diagnose) {
- Diag(StartLoc, diag::err_ovl_no_viable_function_in_call)
- << Name << Range;
- Candidates.NoteCandidates(*this, OCD_AllCandidates, Args);
- }
- return true;
-
- case OR_Ambiguous:
- if (Diagnose) {
- Diag(StartLoc, diag::err_ovl_ambiguous_call)
- << Name << Range;
- Candidates.NoteCandidates(*this, OCD_ViableCandidates, Args);
- }
- return true;
-
- case OR_Deleted: {
- if (Diagnose) {
- Diag(StartLoc, diag::err_ovl_deleted_call)
- << Best->Function->isDeleted()
- << Name
- << getDeletedOrUnavailableSuffix(Best->Function)
- << Range;
- Candidates.NoteCandidates(*this, OCD_AllCandidates, Args);
- }
- return true;
- }
- }
- llvm_unreachable("Unreachable, bad result from BestViableFunction");
+ return false;
}
-
/// DeclareGlobalNewDelete - Declare the global forms of operator new and
/// delete. These are:
/// @code
@@ -2336,41 +2507,64 @@ void Sema::DeclareGlobalNewDelete() {
nullptr);
getStdBadAlloc()->setImplicit(true);
}
+ if (!StdAlignValT && getLangOpts().AlignedAllocation) {
+ // The "std::align_val_t" enum class has not yet been declared, so build it
+ // implicitly.
+ auto *AlignValT = EnumDecl::Create(
+ Context, getOrCreateStdNamespace(), SourceLocation(), SourceLocation(),
+ &PP.getIdentifierTable().get("align_val_t"), nullptr, true, true, true);
+ AlignValT->setIntegerType(Context.getSizeType());
+ AlignValT->setPromotionType(Context.getSizeType());
+ AlignValT->setImplicit(true);
+ StdAlignValT = AlignValT;
+ }
GlobalNewDeleteDeclared = true;
QualType VoidPtr = Context.getPointerType(Context.VoidTy);
QualType SizeT = Context.getSizeType();
- DeclareGlobalAllocationFunction(
- Context.DeclarationNames.getCXXOperatorName(OO_New),
- VoidPtr, SizeT, QualType());
- DeclareGlobalAllocationFunction(
- Context.DeclarationNames.getCXXOperatorName(OO_Array_New),
- VoidPtr, SizeT, QualType());
- DeclareGlobalAllocationFunction(
- Context.DeclarationNames.getCXXOperatorName(OO_Delete),
- Context.VoidTy, VoidPtr);
- DeclareGlobalAllocationFunction(
- Context.DeclarationNames.getCXXOperatorName(OO_Array_Delete),
- Context.VoidTy, VoidPtr);
- if (getLangOpts().SizedDeallocation) {
- DeclareGlobalAllocationFunction(
- Context.DeclarationNames.getCXXOperatorName(OO_Delete),
- Context.VoidTy, VoidPtr, Context.getSizeType());
- DeclareGlobalAllocationFunction(
- Context.DeclarationNames.getCXXOperatorName(OO_Array_Delete),
- Context.VoidTy, VoidPtr, Context.getSizeType());
- }
+ auto DeclareGlobalAllocationFunctions = [&](OverloadedOperatorKind Kind,
+ QualType Return, QualType Param) {
+ llvm::SmallVector<QualType, 3> Params;
+ Params.push_back(Param);
+
+ // Create up to four variants of the function (sized/aligned).
+ bool HasSizedVariant = getLangOpts().SizedDeallocation &&
+ (Kind == OO_Delete || Kind == OO_Array_Delete);
+ bool HasAlignedVariant = getLangOpts().AlignedAllocation;
+
+ int NumSizeVariants = (HasSizedVariant ? 2 : 1);
+ int NumAlignVariants = (HasAlignedVariant ? 2 : 1);
+ for (int Sized = 0; Sized < NumSizeVariants; ++Sized) {
+ if (Sized)
+ Params.push_back(SizeT);
+
+ for (int Aligned = 0; Aligned < NumAlignVariants; ++Aligned) {
+ if (Aligned)
+ Params.push_back(Context.getTypeDeclType(getStdAlignValT()));
+
+ DeclareGlobalAllocationFunction(
+ Context.DeclarationNames.getCXXOperatorName(Kind), Return, Params);
+
+ if (Aligned)
+ Params.pop_back();
+ }
+ }
+ };
+
+ DeclareGlobalAllocationFunctions(OO_New, VoidPtr, SizeT);
+ DeclareGlobalAllocationFunctions(OO_Array_New, VoidPtr, SizeT);
+ DeclareGlobalAllocationFunctions(OO_Delete, Context.VoidTy, VoidPtr);
+ DeclareGlobalAllocationFunctions(OO_Array_Delete, Context.VoidTy, VoidPtr);
}
/// DeclareGlobalAllocationFunction - Declares a single implicit global
/// allocation function if it doesn't already exist.
void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
QualType Return,
- QualType Param1, QualType Param2) {
+ ArrayRef<QualType> Params) {
DeclContext *GlobalCtx = Context.getTranslationUnitDecl();
- unsigned NumParams = Param2.isNull() ? 1 : 2;
// Check if this function is already declared.
DeclContext::lookup_result R = GlobalCtx->lookup(Name);
@@ -2379,18 +2573,12 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
// Only look at non-template functions, as it is the predefined,
// non-templated allocation function we are trying to declare here.
if (FunctionDecl *Func = dyn_cast<FunctionDecl>(*Alloc)) {
- if (Func->getNumParams() == NumParams) {
- QualType InitialParam1Type =
- Context.getCanonicalType(Func->getParamDecl(0)
- ->getType().getUnqualifiedType());
- QualType InitialParam2Type =
- NumParams == 2
- ? Context.getCanonicalType(Func->getParamDecl(1)
- ->getType().getUnqualifiedType())
- : QualType();
- // FIXME: Do we need to check for default arguments here?
- if (InitialParam1Type == Param1 &&
- (NumParams == 1 || InitialParam2Type == Param2)) {
+ if (Func->getNumParams() == Params.size()) {
+ llvm::SmallVector<QualType, 3> FuncParams;
+ for (auto *P : Func->parameters())
+ FuncParams.push_back(
+ Context.getCanonicalType(P->getType().getUnqualifiedType()));
+ if (llvm::makeArrayRef(FuncParams) == Params) {
// Make the function visible to name lookup, even if we found it in
// an unimported module. It either is an implicitly-declared global
// allocation function, or is suppressing that function.
@@ -2419,82 +2607,80 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
getLangOpts().CPlusPlus11 ? EST_BasicNoexcept : EST_DynamicNone;
}
- QualType Params[] = { Param1, Param2 };
-
- QualType FnType = Context.getFunctionType(
- Return, llvm::makeArrayRef(Params, NumParams), EPI);
- FunctionDecl *Alloc =
- FunctionDecl::Create(Context, GlobalCtx, SourceLocation(),
- SourceLocation(), Name,
- FnType, /*TInfo=*/nullptr, SC_None, false, true);
- Alloc->setImplicit();
-
- // Implicit sized deallocation functions always have default visibility.
- Alloc->addAttr(VisibilityAttr::CreateImplicit(Context,
- VisibilityAttr::Default));
-
- ParmVarDecl *ParamDecls[2];
- for (unsigned I = 0; I != NumParams; ++I) {
- ParamDecls[I] = ParmVarDecl::Create(Context, Alloc, SourceLocation(),
- SourceLocation(), nullptr,
- Params[I], /*TInfo=*/nullptr,
- SC_None, nullptr);
- ParamDecls[I]->setImplicit();
- }
- Alloc->setParams(llvm::makeArrayRef(ParamDecls, NumParams));
-
- Context.getTranslationUnitDecl()->addDecl(Alloc);
- IdResolver.tryAddTopLevelDecl(Alloc, Name);
+ auto CreateAllocationFunctionDecl = [&](Attr *ExtraAttr) {
+ QualType FnType = Context.getFunctionType(Return, Params, EPI);
+ FunctionDecl *Alloc = FunctionDecl::Create(
+ Context, GlobalCtx, SourceLocation(), SourceLocation(), Name,
+ FnType, /*TInfo=*/nullptr, SC_None, false, true);
+ Alloc->setImplicit();
+
+ // Implicit sized deallocation functions always have default visibility.
+ Alloc->addAttr(
+ VisibilityAttr::CreateImplicit(Context, VisibilityAttr::Default));
+
+ llvm::SmallVector<ParmVarDecl *, 3> ParamDecls;
+ for (QualType T : Params) {
+ ParamDecls.push_back(ParmVarDecl::Create(
+ Context, Alloc, SourceLocation(), SourceLocation(), nullptr, T,
+ /*TInfo=*/nullptr, SC_None, nullptr));
+ ParamDecls.back()->setImplicit();
+ }
+ Alloc->setParams(ParamDecls);
+ if (ExtraAttr)
+ Alloc->addAttr(ExtraAttr);
+ Context.getTranslationUnitDecl()->addDecl(Alloc);
+ IdResolver.tryAddTopLevelDecl(Alloc, Name);
+ };
+
+ if (!LangOpts.CUDA)
+ CreateAllocationFunctionDecl(nullptr);
+ else {
+ // Host and device get their own declaration so each can be
+ // defined or re-declared independently.
+ CreateAllocationFunctionDecl(CUDAHostAttr::CreateImplicit(Context));
+ CreateAllocationFunctionDecl(CUDADeviceAttr::CreateImplicit(Context));
+ }
}
FunctionDecl *Sema::FindUsualDeallocationFunction(SourceLocation StartLoc,
bool CanProvideSize,
+ bool Overaligned,
DeclarationName Name) {
DeclareGlobalNewDelete();
LookupResult FoundDelete(*this, Name, StartLoc, LookupOrdinaryName);
LookupQualifiedName(FoundDelete, Context.getTranslationUnitDecl());
- // C++ [expr.new]p20:
- // [...] Any non-placement deallocation function matches a
- // non-placement allocation function. [...]
- llvm::SmallVector<FunctionDecl*, 2> Matches;
- for (LookupResult::iterator D = FoundDelete.begin(),
- DEnd = FoundDelete.end();
- D != DEnd; ++D) {
- if (FunctionDecl *Fn = dyn_cast<FunctionDecl>(*D))
- if (isNonPlacementDeallocationFunction(*this, Fn))
- Matches.push_back(Fn);
- }
-
- // C++1y [expr.delete]p?:
- // If the type is complete and deallocation function lookup finds both a
- // usual deallocation function with only a pointer parameter and a usual
- // deallocation function with both a pointer parameter and a size
- // parameter, then the selected deallocation function shall be the one
- // with two parameters. Otherwise, the selected deallocation function
- // shall be the function with one parameter.
- if (getLangOpts().SizedDeallocation && Matches.size() == 2) {
- unsigned NumArgs = CanProvideSize ? 2 : 1;
- if (Matches[0]->getNumParams() != NumArgs)
- Matches.erase(Matches.begin());
- else
- Matches.erase(Matches.begin() + 1);
- assert(Matches[0]->getNumParams() == NumArgs &&
- "found an unexpected usual deallocation function");
- }
+ // FIXME: It's possible for this to result in ambiguity, through a
+ // user-declared variadic operator delete or the enable_if attribute. We
+ // should probably not consider those cases to be usual deallocation
+ // functions. But for now we just make an arbitrary choice in that case.
+ auto Result = resolveDeallocationOverload(*this, FoundDelete, CanProvideSize,
+ Overaligned);
+ assert(Result.FD && "operator delete missing from global scope?");
+ return Result.FD;
+}
- if (getLangOpts().CUDA)
- EraseUnwantedCUDAMatches(dyn_cast<FunctionDecl>(CurContext), Matches);
+FunctionDecl *Sema::FindDeallocationFunctionForDestructor(SourceLocation Loc,
+ CXXRecordDecl *RD) {
+ DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Delete);
- assert(Matches.size() == 1 &&
- "unexpectedly have multiple usual deallocation functions");
- return Matches.front();
+ FunctionDecl *OperatorDelete = nullptr;
+ if (FindDeallocationFunction(Loc, RD, Name, OperatorDelete))
+ return nullptr;
+ if (OperatorDelete)
+ return OperatorDelete;
+
+ // If there's no class-specific operator delete, look up the global
+ // non-array delete.
+ return FindUsualDeallocationFunction(
+ Loc, true, hasNewExtendedAlignment(*this, Context.getRecordType(RD)),
+ Name);
}
bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
DeclarationName Name,
- FunctionDecl* &Operator, bool Diagnose) {
+ FunctionDecl *&Operator, bool Diagnose) {
LookupResult Found(*this, Name, StartLoc, LookupOrdinaryName);
// Try to find operator delete/operator delete[] in class scope.
LookupQualifiedName(Found, RD);
@@ -2504,27 +2690,20 @@ bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
Found.suppressDiagnostics();
- SmallVector<DeclAccessPair,4> Matches;
- for (LookupResult::iterator F = Found.begin(), FEnd = Found.end();
- F != FEnd; ++F) {
- NamedDecl *ND = (*F)->getUnderlyingDecl();
+ bool Overaligned = hasNewExtendedAlignment(*this, Context.getRecordType(RD));
- // Ignore template operator delete members from the check for a usual
- // deallocation function.
- if (isa<FunctionTemplateDecl>(ND))
- continue;
+ // C++17 [expr.delete]p10:
+ // If the deallocation functions have class scope, the one without a
+ // parameter of type std::size_t is selected.
+ llvm::SmallVector<UsualDeallocFnInfo, 4> Matches;
+ resolveDeallocationOverload(*this, Found, /*WantSize*/ false,
+ /*WantAlign*/ Overaligned, &Matches);
- if (cast<CXXMethodDecl>(ND)->isUsualDeallocationFunction())
- Matches.push_back(F.getPair());
- }
-
- if (getLangOpts().CUDA)
- EraseUnwantedCUDAMatches(dyn_cast<FunctionDecl>(CurContext), Matches);
-
- // There's exactly one suitable operator; pick it.
+ // If we could find an overload, use it.
if (Matches.size() == 1) {
- Operator = cast<CXXMethodDecl>(Matches[0]->getUnderlyingDecl());
+ Operator = cast<CXXMethodDecl>(Matches[0].FD);
+ // FIXME: DiagnoseUseOfDecl?
if (Operator->isDeleted()) {
if (Diagnose) {
Diag(StartLoc, diag::err_deleted_function_use);
@@ -2534,21 +2713,21 @@ bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
}
if (CheckAllocationAccess(StartLoc, SourceRange(), Found.getNamingClass(),
- Matches[0], Diagnose) == AR_inaccessible)
+ Matches[0].Found, Diagnose) == AR_inaccessible)
return true;
return false;
+ }
- // We found multiple suitable operators; complain about the ambiguity.
- } else if (!Matches.empty()) {
+ // We found multiple suitable operators; complain about the ambiguity.
+ // FIXME: The standard doesn't say to do this; it appears that the intent
+ // is that this should never happen.
+ if (!Matches.empty()) {
if (Diagnose) {
Diag(StartLoc, diag::err_ambiguous_suitable_delete_member_function_found)
<< Name << RD;
-
- for (SmallVectorImpl<DeclAccessPair>::iterator
- F = Matches.begin(), FEnd = Matches.end(); F != FEnd; ++F)
- Diag((*F)->getUnderlyingDecl()->getLocation(),
- diag::note_member_declared_here) << Name;
+ for (auto &Match : Matches)
+ Diag(Match.FD->getLocation(), diag::note_member_declared_here) << Name;
}
return true;
}
@@ -2560,9 +2739,8 @@ bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
Diag(StartLoc, diag::err_no_suitable_delete_member_function_found)
<< Name << RD;
- for (LookupResult::iterator F = Found.begin(), FEnd = Found.end();
- F != FEnd; ++F)
- Diag((*F)->getUnderlyingDecl()->getLocation(),
+ for (NamedDecl *D : Found)
+ Diag(D->getUnderlyingDecl()->getLocation(),
diag::note_member_declared_here) << Name;
}
return true;
@@ -2593,7 +2771,7 @@ public:
/// translation unit. False, if this is the initial analysis at the point
/// delete-expression was encountered.
explicit MismatchingNewDeleteDetector(bool EndOfTU)
- : IsArrayForm(false), Field(nullptr), EndOfTU(EndOfTU),
+ : Field(nullptr), IsArrayForm(false), EndOfTU(EndOfTU),
HasUndefinedConstructors(false) {}
/// \brief Checks whether pointee of a delete-expression is initialized with
@@ -2612,11 +2790,11 @@ public:
/// \param DeleteWasArrayForm Array form-ness of the delete-expression used
/// for deleting the \p Field.
MismatchResult analyzeField(FieldDecl *Field, bool DeleteWasArrayForm);
+ FieldDecl *Field;
/// List of mismatching new-expressions used for initialization of the pointee
llvm::SmallVector<const CXXNewExpr *, 4> NewExprs;
/// Indicates whether delete-expression was in array form.
bool IsArrayForm;
- FieldDecl *Field;
private:
const bool EndOfTU;
@@ -2921,7 +3099,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
QualType PointeeElem = Context.getBaseElementType(Pointee);
if (unsigned AddressSpace = Pointee.getAddressSpace())
- return Diag(Ex.get()->getLocStart(),
+ return Diag(Ex.get()->getLocStart(),
diag::err_address_space_qualified_delete)
<< Pointee.getUnqualifiedType() << AddressSpace;
@@ -2973,7 +3151,10 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
// Otherwise, the usual operator delete[] should be the
// function we just found.
else if (OperatorDelete && isa<CXXMethodDecl>(OperatorDelete))
- UsualArrayDeleteWantsSize = (OperatorDelete->getNumParams() == 2);
+ UsualArrayDeleteWantsSize =
+ UsualDeallocFnInfo(*this,
+ DeclAccessPair::make(OperatorDelete, AS_public))
+ .HasSizeT;
}
if (!PointeeRD->hasIrrelevantDestructor())
@@ -2990,20 +3171,24 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
SourceLocation());
}
- if (!OperatorDelete)
+ if (!OperatorDelete) {
+ bool IsComplete = isCompleteType(StartLoc, Pointee);
+ bool CanProvideSize =
+ IsComplete && (!ArrayForm || UsualArrayDeleteWantsSize ||
+ Pointee.isDestructedType());
+ bool Overaligned = hasNewExtendedAlignment(*this, Pointee);
+
// Look for a global declaration.
- OperatorDelete = FindUsualDeallocationFunction(
- StartLoc, isCompleteType(StartLoc, Pointee) &&
- (!ArrayForm || UsualArrayDeleteWantsSize ||
- Pointee.isDestructedType()),
- DeleteName);
+ OperatorDelete = FindUsualDeallocationFunction(StartLoc, CanProvideSize,
+ Overaligned, DeleteName);
+ }
MarkFunctionReferenced(StartLoc, OperatorDelete);
// Check access and ambiguity of operator delete and destructor.
if (PointeeRD) {
if (CXXDestructorDecl *Dtor = LookupDestructor(PointeeRD)) {
- CheckDestructorAccess(Ex.get()->getExprLoc(), Dtor,
+ CheckDestructorAccess(Ex.get()->getExprLoc(), Dtor,
PDiag(diag::err_access_dtor) << PointeeElem);
}
}
@@ -3234,7 +3419,7 @@ static ExprResult BuildCXXCastArgument(Sema &S,
ExprResult
Sema::PerformImplicitConversion(Expr *From, QualType ToType,
const ImplicitConversionSequence &ICS,
- AssignmentAction Action,
+ AssignmentAction Action,
CheckedConversionKind CCK) {
switch (ICS.getKind()) {
case ImplicitConversionSequence::StandardConversion: {
@@ -3309,6 +3494,10 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
llvm_unreachable("Cannot perform an ellipsis conversion");
case ImplicitConversionSequence::BadConversion:
+ bool Diagnosed =
+ DiagnoseAssignmentResult(Incompatible, From->getExprLoc(), ToType,
+ From->getType(), From, Action);
+ assert(Diagnosed && "failed to diagnose bad conversion"); (void)Diagnosed;
return ExprError();
}
@@ -3324,16 +3513,16 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
ExprResult
Sema::PerformImplicitConversion(Expr *From, QualType ToType,
const StandardConversionSequence& SCS,
- AssignmentAction Action,
+ AssignmentAction Action,
CheckedConversionKind CCK) {
bool CStyle = (CCK == CCK_CStyleCast || CCK == CCK_FunctionalCast);
-
+
// Overall FIXME: we are recomputing too many types here and doing far too
// much extra work. What this means is that we need to keep track of more
// information that is computed when we try the implicit conversion initially,
// so that we don't need to recompute anything here.
QualType FromType = From->getType();
-
+
if (SCS.CopyConstructor) {
// FIXME: When can ToType be a reference type?
assert(!ToType->isReferenceType());
@@ -3403,13 +3592,13 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
case ICK_Array_To_Pointer:
FromType = Context.getArrayDecayedType(FromType);
- From = ImpCastExprToType(From, FromType, CK_ArrayToPointerDecay,
+ From = ImpCastExprToType(From, FromType, CK_ArrayToPointerDecay,
VK_RValue, /*BasePath=*/nullptr, CCK).get();
break;
case ICK_Function_To_Pointer:
FromType = Context.getPointerType(FromType);
- From = ImpCastExprToType(From, FromType, CK_FunctionToPointerDecay,
+ From = ImpCastExprToType(From, FromType, CK_FunctionToPointerDecay,
VK_RValue, /*BasePath=*/nullptr, CCK).get();
break;
@@ -3446,16 +3635,6 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
// Nothing else to do.
break;
- case ICK_NoReturn_Adjustment:
- // If both sides are functions (or pointers/references to them), there could
- // be incompatible exception declarations.
- if (CheckExceptionSpecCompatibility(From, ToType))
- return ExprError();
-
- From = ImpCastExprToType(From, ToType, CK_NoOp,
- VK_RValue, /*BasePath=*/nullptr, CCK).get();
- break;
-
case ICK_Integral_Promotion:
case ICK_Integral_Conversion:
if (ToType->isBooleanType()) {
@@ -3472,7 +3651,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
case ICK_Floating_Promotion:
case ICK_Floating_Conversion:
- From = ImpCastExprToType(From, ToType, CK_FloatingCast,
+ From = ImpCastExprToType(From, ToType, CK_FloatingCast,
VK_RValue, /*BasePath=*/nullptr, CCK).get();
break;
@@ -3491,22 +3670,22 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
} else {
CK = CK_IntegralComplexCast;
}
- From = ImpCastExprToType(From, ToType, CK,
+ From = ImpCastExprToType(From, ToType, CK,
VK_RValue, /*BasePath=*/nullptr, CCK).get();
break;
}
case ICK_Floating_Integral:
if (ToType->isRealFloatingType())
- From = ImpCastExprToType(From, ToType, CK_IntegralToFloating,
+ From = ImpCastExprToType(From, ToType, CK_IntegralToFloating,
VK_RValue, /*BasePath=*/nullptr, CCK).get();
else
- From = ImpCastExprToType(From, ToType, CK_FloatingToIntegral,
+ From = ImpCastExprToType(From, ToType, CK_FloatingToIntegral,
VK_RValue, /*BasePath=*/nullptr, CCK).get();
break;
case ICK_Compatible_Conversion:
- From = ImpCastExprToType(From, ToType, CK_NoOp,
+ From = ImpCastExprToType(From, ToType, CK_NoOp,
VK_RValue, /*BasePath=*/nullptr, CCK).get();
break;
@@ -3528,20 +3707,20 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
if (From->getType()->isObjCObjectPointerType() &&
ToType->isObjCObjectPointerType())
EmitRelatedResultTypeNote(From);
- }
+ }
else if (getLangOpts().ObjCAutoRefCount &&
- !CheckObjCARCUnavailableWeakConversion(ToType,
+ !CheckObjCARCUnavailableWeakConversion(ToType,
From->getType())) {
if (Action == AA_Initializing)
- Diag(From->getLocStart(),
+ Diag(From->getLocStart(),
diag::err_arc_weak_unavailable_assign);
else
Diag(From->getLocStart(),
- diag::err_arc_convesion_of_weak_unavailable)
- << (Action == AA_Casting) << From->getType() << ToType
+ diag::err_arc_convesion_of_weak_unavailable)
+ << (Action == AA_Casting) << From->getType() << ToType
<< From->getSourceRange();
}
-
+
CastKind Kind = CK_Invalid;
CXXCastPath BasePath;
if (CheckPointerConversion(From, ToType, Kind, BasePath, CStyle))
@@ -3589,7 +3768,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
}
From = ImpCastExprToType(From, Context.BoolTy,
- ScalarTypeToBooleanCastKind(FromType),
+ ScalarTypeToBooleanCastKind(FromType),
VK_RValue, /*BasePath=*/nullptr, CCK).get();
break;
@@ -3610,7 +3789,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
}
case ICK_Vector_Conversion:
- From = ImpCastExprToType(From, ToType, CK_BitCast,
+ From = ImpCastExprToType(From, ToType, CK_BitCast,
VK_RValue, /*BasePath=*/nullptr, CCK).get();
break;
@@ -3655,7 +3834,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
// _Complex x -> x
From = ImpCastExprToType(From, ElType,
isFloatingComplex ? CK_FloatingComplexToReal
- : CK_IntegralComplexToReal,
+ : CK_IntegralComplexToReal,
VK_RValue, /*BasePath=*/nullptr, CCK).get();
// x -> y
@@ -3663,23 +3842,23 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
// do nothing
} else if (ToType->isRealFloatingType()) {
From = ImpCastExprToType(From, ToType,
- isFloatingComplex ? CK_FloatingCast : CK_IntegralToFloating,
+ isFloatingComplex ? CK_FloatingCast : CK_IntegralToFloating,
VK_RValue, /*BasePath=*/nullptr, CCK).get();
} else {
assert(ToType->isIntegerType());
From = ImpCastExprToType(From, ToType,
- isFloatingComplex ? CK_FloatingToIntegral : CK_IntegralCast,
+ isFloatingComplex ? CK_FloatingToIntegral : CK_IntegralCast,
VK_RValue, /*BasePath=*/nullptr, CCK).get();
}
}
break;
-
+
case ICK_Block_Pointer_Conversion: {
From = ImpCastExprToType(From, ToType.getUnqualifiedType(), CK_BitCast,
VK_RValue, /*BasePath=*/nullptr, CCK).get();
break;
}
-
+
case ICK_TransparentUnionConversion: {
ExprResult FromRes = From;
Sema::AssignConvertType ConvTy =
@@ -3699,12 +3878,20 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
From->getValueKind()).get();
break;
+ case ICK_Zero_Queue_Conversion:
+ From = ImpCastExprToType(From, ToType,
+ CK_ZeroToOCLQueue,
+ From->getValueKind()).get();
+ break;
+
case ICK_Lvalue_To_Rvalue:
case ICK_Array_To_Pointer:
case ICK_Function_To_Pointer:
+ case ICK_Function_Conversion:
case ICK_Qualification:
case ICK_Num_Conversion_Kinds:
case ICK_C_Only_Conversion:
+ case ICK_Incompatible_Pointer_Conversion:
llvm_unreachable("Improper second standard conversion");
}
@@ -3713,6 +3900,16 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
// Nothing to do.
break;
+ case ICK_Function_Conversion:
+ // If both sides are functions (or pointers/references to them), there could
+ // be incompatible exception declarations.
+ if (CheckExceptionSpecCompatibility(From, ToType))
+ return ExprError();
+
+ From = ImpCastExprToType(From, ToType, CK_NoOp,
+ VK_RValue, /*BasePath=*/nullptr, CCK).get();
+ break;
+
case ICK_Qualification: {
// The qualification keeps the category of the inner expression, unless the
// target type isn't a reference.
@@ -3882,8 +4079,8 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, TypeTrait UTT,
static bool HasNoThrowOperator(const RecordType *RT, OverloadedOperatorKind Op,
Sema &Self, SourceLocation KeyLoc, ASTContext &C,
- bool (CXXRecordDecl::*HasTrivial)() const,
- bool (CXXRecordDecl::*HasNonTrivial)() const,
+ bool (CXXRecordDecl::*HasTrivial)() const,
+ bool (CXXRecordDecl::*HasNonTrivial)() const,
bool (CXXMethodDecl::*IsDesiredOp)() const)
{
CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
@@ -3979,7 +4176,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
return false;
}
}
-
+
return T->isScalarType();
case UTT_IsCompound:
return T->isCompoundType();
@@ -4158,12 +4355,12 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
// false.
if (T.isPODType(C) || T->isReferenceType())
return true;
-
+
// Objective-C++ ARC: autorelease types don't require destruction.
- if (T->isObjCLifetimeType() &&
+ if (T->isObjCLifetimeType() &&
T.getObjCLifetime() == Qualifiers::OCL_Autoreleasing)
return true;
-
+
if (CXXRecordDecl *RD = C.getBaseElementType(T)->getAsCXXRecordDecl())
return RD->hasTrivialDestructor();
return false;
@@ -4345,9 +4542,9 @@ static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc,
// definition for is_constructible, as defined below, is known to call
// no operation that is not trivial.
//
- // The predicate condition for a template specialization
- // is_constructible<T, Args...> shall be satisfied if and only if the
- // following variable definition would be well-formed for some invented
+ // The predicate condition for a template specialization
+ // is_constructible<T, Args...> shall be satisfied if and only if the
+ // following variable definition would be well-formed for some invented
// variable t:
//
// T t(create<Args>()...);
@@ -4361,7 +4558,7 @@ static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc,
if (ArgTy->isVoidType() || ArgTy->isIncompleteArrayType())
continue;
- if (S.RequireCompleteType(KWLoc, ArgTy,
+ if (S.RequireCompleteType(KWLoc, ArgTy,
diag::err_incomplete_type_used_in_type_trait_expr))
return false;
}
@@ -4391,7 +4588,7 @@ static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc,
for (Expr &E : OpaqueArgExprs)
ArgExprs.push_back(&E);
- // Perform the initialization in an unevaluated context within a SFINAE
+ // Perform the initialization in an unevaluated context within a SFINAE
// trap at translation unit scope.
EnterExpressionEvaluationContext Unevaluated(S, Sema::Unevaluated);
Sema::SFINAETrap SFINAE(S, /*AccessCheckingSFINAE=*/true);
@@ -4430,12 +4627,12 @@ static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc,
}
default: llvm_unreachable("not a TT");
}
-
+
return false;
}
-ExprResult Sema::BuildTypeTrait(TypeTrait Kind, SourceLocation KWLoc,
- ArrayRef<TypeSourceInfo *> Args,
+ExprResult Sema::BuildTypeTrait(TypeTrait Kind, SourceLocation KWLoc,
+ ArrayRef<TypeSourceInfo *> Args,
SourceLocation RParenLoc) {
QualType ResultType = Context.getLogicalOperationType();
@@ -4464,14 +4661,14 @@ ExprResult Sema::ActOnTypeTrait(TypeTrait Kind, SourceLocation KWLoc,
SourceLocation RParenLoc) {
SmallVector<TypeSourceInfo *, 4> ConvertedArgs;
ConvertedArgs.reserve(Args.size());
-
+
for (unsigned I = 0, N = Args.size(); I != N; ++I) {
TypeSourceInfo *TInfo;
QualType T = GetTypeFromParser(Args[I], &TInfo);
if (!TInfo)
TInfo = Context.getTrivialTypeSourceInfo(T, KWLoc);
-
- ConvertedArgs.push_back(TInfo);
+
+ ConvertedArgs.push_back(TInfo);
}
return BuildTypeTrait(Kind, KWLoc, ConvertedArgs, RParenLoc);
@@ -4505,7 +4702,7 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, QualType LhsT,
// If Base and Derived are class types and are different types
// (ignoring possible cv-qualifiers) then Derived shall be a
// complete type.
- if (Self.RequireCompleteType(KeyLoc, RhsT,
+ if (Self.RequireCompleteType(KeyLoc, RhsT,
diag::err_incomplete_type_used_in_type_trait_expr))
return false;
@@ -4522,21 +4719,21 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, QualType LhsT,
// C++0x [meta.rel]p4:
// Given the following function prototype:
//
- // template <class T>
+ // template <class T>
// typename add_rvalue_reference<T>::type create();
//
- // the predicate condition for a template specialization
- // is_convertible<From, To> shall be satisfied if and only if
- // the return expression in the following code would be
+ // the predicate condition for a template specialization
+ // is_convertible<From, To> shall be satisfied if and only if
+ // the return expression in the following code would be
// well-formed, including any implicit conversions to the return
// type of the function:
//
- // To test() {
+ // To test() {
// return create<From>();
// }
//
- // Access checking is performed as if in a context unrelated to To and
- // From. Only the validity of the immediate context of the expression
+ // Access checking is performed as if in a context unrelated to To and
+ // From. Only the validity of the immediate context of the expression
// of the return-statement (including conversions to the return type)
// is considered.
//
@@ -4565,10 +4762,10 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, QualType LhsT,
OpaqueValueExpr From(KeyLoc, LhsT.getNonLValueExprType(Self.Context),
Expr::getValueKindForType(LhsT));
Expr *FromPtr = &From;
- InitializationKind Kind(InitializationKind::CreateCopy(KeyLoc,
+ InitializationKind Kind(InitializationKind::CreateCopy(KeyLoc,
SourceLocation()));
-
- // Perform the initialization in an unevaluated context within a SFINAE
+
+ // Perform the initialization in an unevaluated context within a SFINAE
// trap at translation unit scope.
EnterExpressionEvaluationContext Unevaluated(Self, Sema::Unevaluated);
Sema::SFINAETrap SFINAE(Self, /*AccessCheckingSFINAE=*/true);
@@ -4590,17 +4787,17 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, QualType LhsT,
// is_assignable, is known to call no operation that is not trivial
//
// is_assignable is defined as:
- // The expression declval<T>() = declval<U>() is well-formed when
+ // The expression declval<T>() = declval<U>() is well-formed when
// treated as an unevaluated operand (Clause 5).
//
- // For both, T and U shall be complete types, (possibly cv-qualified)
+ // For both, T and U shall be complete types, (possibly cv-qualified)
// void, or arrays of unknown bound.
if (!LhsT->isVoidType() && !LhsT->isIncompleteArrayType() &&
- Self.RequireCompleteType(KeyLoc, LhsT,
+ Self.RequireCompleteType(KeyLoc, LhsT,
diag::err_incomplete_type_used_in_type_trait_expr))
return false;
if (!RhsT->isVoidType() && !RhsT->isIncompleteArrayType() &&
- Self.RequireCompleteType(KeyLoc, RhsT,
+ Self.RequireCompleteType(KeyLoc, RhsT,
diag::err_incomplete_type_used_in_type_trait_expr))
return false;
@@ -4608,7 +4805,7 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, QualType LhsT,
if (LhsT->isVoidType() || RhsT->isVoidType())
return false;
- // Build expressions that emulate the effect of declval<T>() and
+ // Build expressions that emulate the effect of declval<T>() and
// declval<U>().
if (LhsT->isObjectType() || LhsT->isFunctionType())
LhsT = Self.Context.getRValueReferenceType(LhsT);
@@ -4618,8 +4815,8 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, QualType LhsT,
Expr::getValueKindForType(LhsT));
OpaqueValueExpr Rhs(KeyLoc, RhsT.getNonLValueExprType(Self.Context),
Expr::getValueKindForType(RhsT));
-
- // Attempt the assignment in an unevaluated context within a SFINAE
+
+ // Attempt the assignment in an unevaluated context within a SFINAE
// trap at translation unit scope.
EnterExpressionEvaluationContext Unevaluated(Self, Sema::Unevaluated);
Sema::SFINAETrap SFINAE(Self, /*AccessCheckingSFINAE=*/true);
@@ -4789,11 +4986,14 @@ QualType Sema::CheckPointerToMemberOperands(ExprResult &LHS, ExprResult &RHS,
!RHS.get()->getType()->isPlaceholderType() &&
"placeholders should have been weeded out by now");
- // The LHS undergoes lvalue conversions if this is ->*.
- if (isIndirect) {
+ // The LHS undergoes lvalue conversions if this is ->*, and undergoes the
+ // temporary materialization conversion otherwise.
+ if (isIndirect)
LHS = DefaultLvalueConversion(LHS.get());
- if (LHS.isInvalid()) return QualType();
- }
+ else if (LHS.get()->isRValue())
+ LHS = TemporaryMaterializationConversion(LHS.get());
+ if (LHS.isInvalid())
+ return QualType();
// The RHS always undergoes lvalue conversions.
RHS = DefaultLvalueConversion(RHS.get());
@@ -5005,8 +5205,7 @@ static bool TryClassUnification(Sema &Self, Expr *From, Expr *To,
//
// This actually refers very narrowly to the lvalue-to-rvalue conversion, not
// to the array-to-pointer or function-to-pointer conversions.
- if (!TTy->getAs<TagType>())
- TTy = TTy.getUnqualifiedType();
+ TTy = TTy.getNonLValueExprType(Self.Context);
InitializedEntity Entity = InitializedEntity::InitializeTemporary(TTy);
InitializationSequence InitSeq(Self, Entity, Kind, From);
@@ -5052,7 +5251,7 @@ static bool FindConditionalOverload(Sema &Self, ExprResult &LHS, ExprResult &RHS
Self.MarkFunctionReferenced(QuestionLoc, Best->Function);
return false;
}
-
+
case OR_No_Viable_Function:
// Emit a better diagnostic if one of the expressions is a null pointer
@@ -5199,23 +5398,35 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
// if both are glvalues of the same value category and the same type except
// for cv-qualification, an attempt is made to convert each of those
// operands to the type of the other.
+ // FIXME:
+ // Resolving a defect in P0012R1: we extend this to cover all cases where
+ // one of the operands is reference-compatible with the other, in order
+ // to support conditionals between functions differing in noexcept.
ExprValueKind LVK = LHS.get()->getValueKind();
ExprValueKind RVK = RHS.get()->getValueKind();
if (!Context.hasSameType(LTy, RTy) &&
- Context.hasSameUnqualifiedType(LTy, RTy) &&
LVK == RVK && LVK != VK_RValue) {
- // Since the unqualified types are reference-related and we require the
- // result to be as if a reference bound directly, the only conversion
- // we can perform is to add cv-qualifiers.
- Qualifiers LCVR = Qualifiers::fromCVRMask(LTy.getCVRQualifiers());
- Qualifiers RCVR = Qualifiers::fromCVRMask(RTy.getCVRQualifiers());
- if (RCVR.isStrictSupersetOf(LCVR)) {
- LHS = ImpCastExprToType(LHS.get(), RTy, CK_NoOp, LVK);
- LTy = LHS.get()->getType();
- }
- else if (LCVR.isStrictSupersetOf(RCVR)) {
+ // DerivedToBase was already handled by the class-specific case above.
+ // FIXME: Should we allow ObjC conversions here?
+ bool DerivedToBase, ObjCConversion, ObjCLifetimeConversion;
+ if (CompareReferenceRelationship(
+ QuestionLoc, LTy, RTy, DerivedToBase,
+ ObjCConversion, ObjCLifetimeConversion) == Ref_Compatible &&
+ !DerivedToBase && !ObjCConversion && !ObjCLifetimeConversion &&
+ // [...] subject to the constraint that the reference must bind
+ // directly [...]
+ !RHS.get()->refersToBitField() &&
+ !RHS.get()->refersToVectorElement()) {
RHS = ImpCastExprToType(RHS.get(), LTy, CK_NoOp, RVK);
RTy = RHS.get()->getType();
+ } else if (CompareReferenceRelationship(
+ QuestionLoc, RTy, LTy, DerivedToBase,
+ ObjCConversion, ObjCLifetimeConversion) == Ref_Compatible &&
+ !DerivedToBase && !ObjCConversion && !ObjCLifetimeConversion &&
+ !LHS.get()->refersToBitField() &&
+ !LHS.get()->refersToVectorElement()) {
+ LHS = ImpCastExprToType(LHS.get(), RTy, CK_NoOp, LVK);
+ LTy = LHS.get()->getType();
}
}
@@ -5234,6 +5445,20 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
if (LHS.get()->getObjectKind() == OK_BitField ||
RHS.get()->getObjectKind() == OK_BitField)
OK = OK_BitField;
+
+ // If we have function pointer types, unify them anyway to unify their
+ // exception specifications, if any.
+ if (LTy->isFunctionPointerType() || LTy->isMemberFunctionPointerType()) {
+ Qualifiers Qs = LTy.getQualifiers();
+ LTy = FindCompositePointerType(QuestionLoc, LHS, RHS,
+ /*ConvertArgs*/false);
+ LTy = Context.getQualifiedType(LTy, Qs);
+
+ assert(!LTy.isNull() && "failed to find composite pointer type for "
+ "canonically equivalent function ptr types");
+ assert(Context.hasSameType(LTy, RTy) && "bad composite pointer type");
+ }
+
return LTy;
}
@@ -5267,9 +5492,6 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
if (Context.getCanonicalType(LTy) == Context.getCanonicalType(RTy)) {
if (LTy->isRecordType()) {
// The operands have class type. Make a temporary copy.
- if (RequireNonAbstractType(QuestionLoc, LTy,
- diag::err_allocation_of_abstract_type))
- return QualType();
InitializedEntity Entity = InitializedEntity::InitializeTemporary(LTy);
ExprResult LHSCopy = PerformCopyInitialization(Entity,
@@ -5288,6 +5510,14 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
RHS = RHSCopy;
}
+ // If we have function pointer types, unify them anyway to unify their
+ // exception specifications, if any.
+ if (LTy->isFunctionPointerType() || LTy->isMemberFunctionPointerType()) {
+ LTy = FindCompositePointerType(QuestionLoc, LHS, RHS);
+ assert(!LTy.isNull() && "failed to find composite pointer type for "
+ "canonically equivalent function ptr types");
+ }
+
return LTy;
}
@@ -5329,19 +5559,9 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
// performed to bring them to a common type, whose cv-qualification
// shall match the cv-qualification of either the second or the third
// operand. The result is of the common type.
- bool NonStandardCompositeType = false;
- QualType Composite = FindCompositePointerType(QuestionLoc, LHS, RHS,
- isSFINAEContext() ? nullptr
- : &NonStandardCompositeType);
- if (!Composite.isNull()) {
- if (NonStandardCompositeType)
- Diag(QuestionLoc,
- diag::ext_typecheck_cond_incompatible_operands_nonstandard)
- << LTy << RTy << Composite
- << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
-
+ QualType Composite = FindCompositePointerType(QuestionLoc, LHS, RHS);
+ if (!Composite.isNull())
return Composite;
- }
// Similarly, attempt to find composite type of two objective-c pointers.
Composite = FindCompositeObjCPointerType(LHS, RHS, QuestionLoc);
@@ -5358,90 +5578,176 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
return QualType();
}
+static FunctionProtoType::ExceptionSpecInfo
+mergeExceptionSpecs(Sema &S, FunctionProtoType::ExceptionSpecInfo ESI1,
+ FunctionProtoType::ExceptionSpecInfo ESI2,
+ SmallVectorImpl<QualType> &ExceptionTypeStorage) {
+ ExceptionSpecificationType EST1 = ESI1.Type;
+ ExceptionSpecificationType EST2 = ESI2.Type;
+
+ // If either of them can throw anything, that is the result.
+ if (EST1 == EST_None) return ESI1;
+ if (EST2 == EST_None) return ESI2;
+ if (EST1 == EST_MSAny) return ESI1;
+ if (EST2 == EST_MSAny) 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 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) {
+ assert(!S.getLangOpts().CPlusPlus1z &&
+ "computing composite pointer type of dependent types");
+ return FunctionProtoType::ExceptionSpecInfo();
+ }
+
+ // Switch over the possibilities so that people adding new values know to
+ // update this function.
+ switch (EST1) {
+ case EST_None:
+ case EST_DynamicNone:
+ case EST_MSAny:
+ case EST_BasicNoexcept:
+ case EST_ComputedNoexcept:
+ llvm_unreachable("handled above");
+
+ case EST_Dynamic: {
+ // This is the fun case: both exception specifications are dynamic. Form
+ // the union of the two lists.
+ assert(EST2 == EST_Dynamic && "other cases should already be handled");
+ llvm::SmallPtrSet<QualType, 8> Found;
+ for (auto &Exceptions : {ESI1.Exceptions, ESI2.Exceptions})
+ for (QualType E : Exceptions)
+ if (Found.insert(S.Context.getCanonicalType(E)).second)
+ ExceptionTypeStorage.push_back(E);
+
+ FunctionProtoType::ExceptionSpecInfo Result(EST_Dynamic);
+ Result.Exceptions = ExceptionTypeStorage;
+ return Result;
+ }
+
+ case EST_Unevaluated:
+ case EST_Uninstantiated:
+ case EST_Unparsed:
+ llvm_unreachable("shouldn't see unresolved exception specifications here");
+ }
+
+ llvm_unreachable("invalid ExceptionSpecificationType");
+}
+
/// \brief 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++11 5.9p2. It converts both expressions to this
+/// and @p E2 according to C++1z 5p14. It converts both expressions to this
/// type and returns it.
/// It does not emit diagnostics.
///
/// \param Loc The location of the operator requiring these two expressions to
/// be converted to the composite pointer type.
///
-/// If \p NonStandardCompositeType is non-NULL, then we are permitted to find
-/// a non-standard (but still sane) composite type to which both expressions
-/// can be converted. When such a type is chosen, \c *NonStandardCompositeType
-/// will be set true.
+/// \param ConvertArgs If \c false, do not convert E1 and E2 to the target type.
QualType Sema::FindCompositePointerType(SourceLocation Loc,
Expr *&E1, Expr *&E2,
- bool *NonStandardCompositeType) {
- if (NonStandardCompositeType)
- *NonStandardCompositeType = false;
-
+ bool ConvertArgs) {
assert(getLangOpts().CPlusPlus && "This function assumes C++");
+
+ // C++1z [expr]p14:
+ // The composite pointer type of two operands p1 and p2 having types T1
+ // and T2
QualType T1 = E1->getType(), T2 = E2->getType();
- // C++11 5.9p2
- // Pointer conversions and qualification conversions are performed on
- // pointer operands to bring them to their composite pointer type. If
- // one operand is a null pointer constant, the composite pointer type is
- // std::nullptr_t if the other operand is also a null pointer constant or,
- // if the other operand is a pointer, the type of the other operand.
- if (!T1->isAnyPointerType() && !T1->isMemberPointerType() &&
- !T2->isAnyPointerType() && !T2->isMemberPointerType()) {
- if (T1->isNullPtrType() &&
- E2->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
- E2 = ImpCastExprToType(E2, T1, CK_NullToPointer).get();
- return T1;
- }
- if (T2->isNullPtrType() &&
- E1->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
- E1 = ImpCastExprToType(E1, T2, CK_NullToPointer).get();
- return T2;
- }
+ // where at least one is a pointer or pointer to member type or
+ // std::nullptr_t is:
+ bool T1IsPointerLike = T1->isAnyPointerType() || T1->isMemberPointerType() ||
+ T1->isNullPtrType();
+ bool T2IsPointerLike = T2->isAnyPointerType() || T2->isMemberPointerType() ||
+ T2->isNullPtrType();
+ if (!T1IsPointerLike && !T2IsPointerLike)
return QualType();
- }
- if (E1->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
- if (T2->isMemberPointerType())
- E1 = ImpCastExprToType(E1, T2, CK_NullToMemberPointer).get();
- else
- E1 = ImpCastExprToType(E1, T2, CK_NullToPointer).get();
- return T2;
- }
- if (E2->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
- if (T1->isMemberPointerType())
- E2 = ImpCastExprToType(E2, T1, CK_NullToMemberPointer).get();
- else
- E2 = ImpCastExprToType(E2, T1, CK_NullToPointer).get();
+ // - if both p1 and p2 are null pointer constants, std::nullptr_t;
+ // This can't actually happen, following the standard, but we also use this
+ // to implement the end of [expr.conv], which hits this case.
+ //
+ // - if either p1 or p2 is a null pointer constant, T2 or T1, respectively;
+ if (T1IsPointerLike &&
+ E2->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
+ if (ConvertArgs)
+ E2 = ImpCastExprToType(E2, T1, T1->isMemberPointerType()
+ ? CK_NullToMemberPointer
+ : CK_NullToPointer).get();
return T1;
}
+ if (T2IsPointerLike &&
+ E1->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
+ if (ConvertArgs)
+ E1 = ImpCastExprToType(E1, T2, T2->isMemberPointerType()
+ ? CK_NullToMemberPointer
+ : CK_NullToPointer).get();
+ return T2;
+ }
// Now both have to be pointers or member pointers.
- if ((!T1->isPointerType() && !T1->isMemberPointerType()) ||
- (!T2->isPointerType() && !T2->isMemberPointerType()))
+ if (!T1IsPointerLike || !T2IsPointerLike)
return QualType();
-
- // Otherwise, of one of the operands has type "pointer to cv1 void," then
- // the other has type "pointer to cv2 T" and the composite pointer type is
- // "pointer to cv12 void," where cv12 is the union of cv1 and cv2.
- // Otherwise, the composite pointer type is a pointer type similar to the
- // type of one of the operands, with a cv-qualification signature that is
- // the union of the cv-qualification signatures of the operand types.
- // In practice, the first part here is redundant; it's subsumed by the second.
- // What we do here is, we build the two possible composite types, and try the
- // conversions in both directions. If only one works, or if the two composite
- // types are the same, we have succeeded.
+ assert(!T1->isNullPtrType() && !T2->isNullPtrType() &&
+ "nullptr_t should be a null pointer constant");
+
+ // - if T1 or T2 is "pointer to cv1 void" and the other type is
+ // "pointer to cv2 T", "pointer to cv12 void", where cv12 is
+ // the union of cv1 and cv2;
+ // - if T1 or T2 is "pointer to noexcept function" and the other type is
+ // "pointer to function", where the function types are otherwise the same,
+ // "pointer to function";
+ // FIXME: This rule is defective: it should also permit removing noexcept
+ // from a pointer to member function. As a Clang extension, we also
+ // permit removing 'noreturn', so we generalize this rule to;
+ // - [Clang] If T1 and T2 are both of type "pointer to function" or
+ // "pointer to member function" and the pointee types can be unified
+ // by a function pointer conversion, that conversion is applied
+ // before checking the following rules.
+ // - if T1 is "pointer to cv1 C1" and T2 is "pointer to cv2 C2", where C1
+ // is reference-related to C2 or C2 is reference-related to C1 (8.6.3),
+ // the cv-combined type of T1 and T2 or the cv-combined type of T2 and T1,
+ // respectively;
+ // - if T1 is "pointer to member of C1 of type cv1 U1" and T2 is "pointer
+ // to member of C2 of type cv2 U2" where C1 is reference-related to C2 or
+ // C2 is reference-related to C1 (8.6.3), the cv-combined type of T2 and
+ // T1 or the cv-combined type of T1 and T2, respectively;
+ // - if T1 and T2 are similar types (4.5), the cv-combined type of T1 and
+ // T2;
+ //
+ // If looked at in the right way, these bullets all do the same thing.
+ // What we do here is, we build the two possible cv-combined types, and try
+ // the conversions in both directions. If only one works, or if the two
+ // composite types are the same, we have succeeded.
// FIXME: extended qualifiers?
- typedef SmallVector<unsigned, 4> QualifierVector;
- QualifierVector QualifierUnion;
- typedef SmallVector<std::pair<const Type *, const Type *>, 4>
- ContainingClassVector;
- ContainingClassVector MemberOfClass;
- QualType Composite1 = Context.getCanonicalType(T1),
- Composite2 = Context.getCanonicalType(T2);
+ //
+ // Note that this will fail to find a composite pointer type for "pointer
+ // to void" and "pointer to function". We can't actually perform the final
+ // conversion in this case, even though a composite pointer type formally
+ // exists.
+ SmallVector<unsigned, 4> QualifierUnion;
+ SmallVector<std::pair<const Type *, const Type *>, 4> MemberOfClass;
+ QualType Composite1 = T1;
+ QualType Composite2 = T2;
unsigned NeedConstBefore = 0;
- do {
+ while (true) {
const PointerType *Ptr1, *Ptr2;
if ((Ptr1 = Composite1->getAs<PointerType>()) &&
(Ptr2 = Composite2->getAs<PointerType>())) {
@@ -5450,8 +5756,7 @@ QualType Sema::FindCompositePointerType(SourceLocation Loc,
// If we're allowed to create a non-standard composite type, keep track
// of where we need to fill in additional 'const' qualifiers.
- if (NonStandardCompositeType &&
- Composite1.getCVRQualifiers() != Composite2.getCVRQualifiers())
+ if (Composite1.getCVRQualifiers() != Composite2.getCVRQualifiers())
NeedConstBefore = QualifierUnion.size();
QualifierUnion.push_back(
@@ -5468,8 +5773,7 @@ QualType Sema::FindCompositePointerType(SourceLocation Loc,
// If we're allowed to create a non-standard composite type, keep track
// of where we need to fill in additional 'const' qualifiers.
- if (NonStandardCompositeType &&
- Composite1.getCVRQualifiers() != Composite2.getCVRQualifiers())
+ if (Composite1.getCVRQualifiers() != Composite2.getCVRQualifiers())
NeedConstBefore = QualifierUnion.size();
QualifierUnion.push_back(
@@ -5483,109 +5787,125 @@ QualType Sema::FindCompositePointerType(SourceLocation Loc,
// Cannot unwrap any more types.
break;
- } while (true);
+ }
- if (NeedConstBefore && NonStandardCompositeType) {
+ // Apply the function pointer conversion to unify the types. We've already
+ // unwrapped down to the function types, and we want to merge rather than
+ // just convert, so do this ourselves rather than calling
+ // IsFunctionConversion.
+ //
+ // FIXME: In order to match the standard wording as closely as possible, we
+ // currently only do this under a single level of pointers. Ideally, we would
+ // allow this in general, and set NeedConstBefore to the relevant depth on
+ // the side(s) where we changed anything.
+ if (QualifierUnion.size() == 1) {
+ if (auto *FPT1 = Composite1->getAs<FunctionProtoType>()) {
+ if (auto *FPT2 = Composite2->getAs<FunctionProtoType>()) {
+ FunctionProtoType::ExtProtoInfo EPI1 = FPT1->getExtProtoInfo();
+ FunctionProtoType::ExtProtoInfo EPI2 = FPT2->getExtProtoInfo();
+
+ // The result is noreturn if both operands are.
+ bool Noreturn =
+ EPI1.ExtInfo.getNoReturn() && EPI2.ExtInfo.getNoReturn();
+ EPI1.ExtInfo = EPI1.ExtInfo.withNoReturn(Noreturn);
+ EPI2.ExtInfo = EPI2.ExtInfo.withNoReturn(Noreturn);
+
+ // The result is nothrow if both operands are.
+ SmallVector<QualType, 8> ExceptionTypeStorage;
+ EPI1.ExceptionSpec = EPI2.ExceptionSpec =
+ mergeExceptionSpecs(*this, EPI1.ExceptionSpec, EPI2.ExceptionSpec,
+ ExceptionTypeStorage);
+
+ Composite1 = Context.getFunctionType(FPT1->getReturnType(),
+ FPT1->getParamTypes(), EPI1);
+ Composite2 = Context.getFunctionType(FPT2->getReturnType(),
+ FPT2->getParamTypes(), EPI2);
+ }
+ }
+ }
+
+ if (NeedConstBefore) {
// Extension: Add 'const' to qualifiers that come before the first qualifier
// mismatch, so that our (non-standard!) composite type meets the
// requirements of C++ [conv.qual]p4 bullet 3.
- for (unsigned I = 0; I != NeedConstBefore; ++I) {
- if ((QualifierUnion[I] & Qualifiers::Const) == 0) {
+ for (unsigned I = 0; I != NeedConstBefore; ++I)
+ if ((QualifierUnion[I] & Qualifiers::Const) == 0)
QualifierUnion[I] = QualifierUnion[I] | Qualifiers::Const;
- *NonStandardCompositeType = true;
- }
- }
}
// Rewrap the composites as pointers or member pointers with the union CVRs.
- ContainingClassVector::reverse_iterator MOC
- = MemberOfClass.rbegin();
- for (QualifierVector::reverse_iterator
- I = QualifierUnion.rbegin(),
- E = QualifierUnion.rend();
- I != E; (void)++I, ++MOC) {
- Qualifiers Quals = Qualifiers::fromCVRMask(*I);
- if (MOC->first && MOC->second) {
+ auto MOC = MemberOfClass.rbegin();
+ for (unsigned CVR : llvm::reverse(QualifierUnion)) {
+ Qualifiers Quals = Qualifiers::fromCVRMask(CVR);
+ auto Classes = *MOC++;
+ if (Classes.first && Classes.second) {
// Rebuild member pointer type
Composite1 = Context.getMemberPointerType(
- Context.getQualifiedType(Composite1, Quals),
- MOC->first);
+ Context.getQualifiedType(Composite1, Quals), Classes.first);
Composite2 = Context.getMemberPointerType(
- Context.getQualifiedType(Composite2, Quals),
- MOC->second);
+ Context.getQualifiedType(Composite2, Quals), Classes.second);
} else {
// Rebuild pointer type
- Composite1
- = Context.getPointerType(Context.getQualifiedType(Composite1, Quals));
- Composite2
- = Context.getPointerType(Context.getQualifiedType(Composite2, Quals));
+ Composite1 =
+ Context.getPointerType(Context.getQualifiedType(Composite1, Quals));
+ Composite2 =
+ Context.getPointerType(Context.getQualifiedType(Composite2, Quals));
}
}
- // Try to convert to the first composite pointer type.
- InitializedEntity Entity1
- = InitializedEntity::InitializeTemporary(Composite1);
- InitializationKind Kind
- = InitializationKind::CreateCopy(Loc, SourceLocation());
- InitializationSequence E1ToC1(*this, Entity1, Kind, E1);
- InitializationSequence E2ToC1(*this, Entity1, Kind, E2);
-
- if (E1ToC1 && E2ToC1) {
- // Conversion to Composite1 is viable.
- if (!Context.hasSameType(Composite1, Composite2)) {
- // Composite2 is a different type from Composite1. Check whether
- // Composite2 is also viable.
- InitializedEntity Entity2
- = InitializedEntity::InitializeTemporary(Composite2);
- InitializationSequence E1ToC2(*this, Entity2, Kind, E1);
- InitializationSequence E2ToC2(*this, Entity2, Kind, E2);
- if (E1ToC2 && E2ToC2) {
- // Both Composite1 and Composite2 are viable and are different;
- // this is an ambiguity.
- return QualType();
- }
- }
+ struct Conversion {
+ Sema &S;
+ Expr *&E1, *&E2;
+ QualType Composite;
+ InitializedEntity Entity;
+ InitializationKind Kind;
+ InitializationSequence E1ToC, E2ToC;
+ bool Viable;
+
+ Conversion(Sema &S, SourceLocation Loc, Expr *&E1, Expr *&E2,
+ QualType Composite)
+ : S(S), E1(E1), E2(E2), Composite(Composite),
+ Entity(InitializedEntity::InitializeTemporary(Composite)),
+ Kind(InitializationKind::CreateCopy(Loc, SourceLocation())),
+ E1ToC(S, Entity, Kind, E1), E2ToC(S, Entity, Kind, E2),
+ Viable(E1ToC && E2ToC) {}
+
+ bool perform() {
+ ExprResult E1Result = E1ToC.Perform(S, Entity, Kind, E1);
+ if (E1Result.isInvalid())
+ return true;
+ E1 = E1Result.getAs<Expr>();
- // Convert E1 to Composite1
- ExprResult E1Result
- = E1ToC1.Perform(*this, Entity1, Kind, E1);
- if (E1Result.isInvalid())
- return QualType();
- E1 = E1Result.getAs<Expr>();
+ ExprResult E2Result = E2ToC.Perform(S, Entity, Kind, E2);
+ if (E2Result.isInvalid())
+ return true;
+ E2 = E2Result.getAs<Expr>();
- // Convert E2 to Composite1
- ExprResult E2Result
- = E2ToC1.Perform(*this, Entity1, Kind, E2);
- if (E2Result.isInvalid())
- return QualType();
- E2 = E2Result.getAs<Expr>();
+ return false;
+ }
+ };
- return Composite1;
+ // Try to convert to each composite pointer type.
+ Conversion C1(*this, Loc, E1, E2, Composite1);
+ if (C1.Viable && Context.hasSameType(Composite1, Composite2)) {
+ if (ConvertArgs && C1.perform())
+ return QualType();
+ return C1.Composite;
}
+ Conversion C2(*this, Loc, E1, E2, Composite2);
- // Check whether Composite2 is viable.
- InitializedEntity Entity2
- = InitializedEntity::InitializeTemporary(Composite2);
- InitializationSequence E1ToC2(*this, Entity2, Kind, E1);
- InitializationSequence E2ToC2(*this, Entity2, Kind, E2);
- if (!E1ToC2 || !E2ToC2)
+ if (C1.Viable == C2.Viable) {
+ // Either Composite1 and Composite2 are viable and are different, or
+ // neither is viable.
+ // FIXME: How both be viable and different?
return QualType();
+ }
- // Convert E1 to Composite2
- ExprResult E1Result
- = E1ToC2.Perform(*this, Entity2, Kind, E1);
- if (E1Result.isInvalid())
- return QualType();
- E1 = E1Result.getAs<Expr>();
-
- // Convert E2 to Composite2
- ExprResult E2Result
- = E2ToC2.Perform(*this, Entity2, Kind, E2);
- if (E2Result.isInvalid())
+ // Convert to the chosen type.
+ if (ConvertArgs && (C1.Viable ? C1 : C2).perform())
return QualType();
- E2 = E2Result.getAs<Expr>();
- return Composite2;
+ return C1.Viable ? C1.Composite : C2.Composite;
}
ExprResult Sema::MaybeBindToTemporary(Expr *E) {
@@ -5618,14 +5938,14 @@ ExprResult Sema::MaybeBindToTemporary(Expr *E) {
else if (MemberExpr *Mem = dyn_cast<MemberExpr>(Callee))
T = Mem->getMemberDecl()->getType();
}
-
+
if (const PointerType *Ptr = T->getAs<PointerType>())
T = Ptr->getPointeeType();
else if (const BlockPointerType *Ptr = T->getAs<BlockPointerType>())
T = Ptr->getPointeeType();
else if (const MemberPointerType *MemPtr = T->getAs<MemberPointerType>())
T = MemPtr->getPointeeType();
-
+
const FunctionType *FTy = T->getAs<FunctionType>();
assert(FTy && "call to value not of function type?");
ReturnsRetained = FTy->getExtInfo().getProducesResult();
@@ -6012,7 +6332,7 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base,
// so adjust the base type to the object type itself.
if (BaseType->isObjCObjectPointerType())
BaseType = BaseType->getPointeeType();
-
+
// C++ [basic.lookup.classref]p2:
// [...] If the type of the object expression is of pointer to scalar
// type, the unqualified-id is looked up in the context of the complete
@@ -6037,7 +6357,7 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base,
// The object type must be complete (or dependent), or
// C++11 [expr.prim.general]p3:
// Unlike the object expression in other contexts, *this is not required to
- // be of complete type for purposes of class member access (5.2.5) outside
+ // be of complete type for purposes of class member access (5.2.5) outside
// the member function body.
if (!BaseType->isDependentType() &&
!isThisOutsideMemberFunctionBody(BaseType) &&
@@ -6053,7 +6373,7 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base,
return Base;
}
-static bool CheckArrow(Sema& S, QualType& ObjectType, Expr *&Base,
+static bool CheckArrow(Sema& S, QualType& ObjectType, Expr *&Base,
tok::TokenKind& OpKind, SourceLocation OpLoc) {
if (Base->hasPlaceholderType()) {
ExprResult result = S.CheckPlaceholderExpr(Base);
@@ -6129,9 +6449,9 @@ ExprResult Sema::BuildPseudoDestructorExpr(Expr *Base,
DestructedTypeInfo = Context.getTrivialTypeSourceInfo(ObjectType,
DestructedTypeStart);
Destructed = PseudoDestructorTypeStorage(DestructedTypeInfo);
- } else if (DestructedType.getObjCLifetime() !=
+ } else if (DestructedType.getObjCLifetime() !=
ObjectType.getObjCLifetime()) {
-
+
if (DestructedType.getObjCLifetime() == Qualifiers::OCL_None) {
// Okay: just pretend that the user provided the correctly-qualified
// type.
@@ -6140,7 +6460,7 @@ ExprResult Sema::BuildPseudoDestructorExpr(Expr *Base,
<< ObjectType << DestructedType << Base->getSourceRange()
<< DestructedTypeInfo->getTypeLoc().getLocalSourceRange();
}
-
+
// Recover by setting the destructed type to the object type.
DestructedType = ObjectType;
DestructedTypeInfo = Context.getTrivialTypeSourceInfo(ObjectType,
@@ -6324,7 +6644,7 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
SourceLocation OpLoc,
tok::TokenKind OpKind,
- SourceLocation TildeLoc,
+ SourceLocation TildeLoc,
const DeclSpec& DS) {
QualType ObjectType;
if (CheckArrow(*this, ObjectType, Base, OpKind, OpLoc))
@@ -6519,7 +6839,17 @@ ExprResult Sema::IgnoredValueConversions(Expr *E) {
if (Res.isInvalid())
return E;
E = Res.get();
- }
+ }
+
+ // C++1z:
+ // If the expression is a prvalue after this optional conversion, the
+ // temporary materialization conversion is applied.
+ //
+ // We skip this step: IR generation is able to synthesize the storage for
+ // itself in the aggregate case, and adding the extra node to the AST is
+ // just clutter.
+ // FIXME: We don't emit lifetime markers for the temporaries due to this.
+ // FIXME: Do any other AST consumers care about this?
return E;
}
@@ -6549,13 +6879,13 @@ ExprResult Sema::IgnoredValueConversions(Expr *E) {
// we can unambiguously check if the variable is a constant expression.
// - if the initializer is not value dependent - we can determine whether
// it can be used to initialize a constant expression. If Init can not
-// be used to initialize a constant expression we conclude that Var can
+// be used to initialize a constant expression we conclude that Var can
// never be a constant expression.
// - FXIME: if the initializer is dependent, we can still do some analysis and
// identify certain cases unambiguously as non-const by using a Visitor:
// - such as those that involve odr-use of a ParmVarDecl, involve a new
// delete, lambda-expr, dynamic-cast, reinterpret-cast etc...
-static inline bool VariableCanNeverBeAConstantExpression(VarDecl *Var,
+static inline bool VariableCanNeverBeAConstantExpression(VarDecl *Var,
ASTContext &Context) {
if (isa<ParmVarDecl>(Var)) return true;
const VarDecl *DefVD = nullptr;
@@ -6575,14 +6905,14 @@ static inline bool VariableCanNeverBeAConstantExpression(VarDecl *Var,
return false;
}
- return !IsVariableAConstantExpression(Var, Context);
+ return !IsVariableAConstantExpression(Var, Context);
}
-/// \brief 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
-/// variables are uncaptureable or do not involve an odr-use so do not
+/// \brief 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
+/// variables are uncaptureable or do not involve an odr-use so do not
/// need to be captured.
static void CheckIfAnyEnclosingLambdasMustCaptureAnyPotentialCaptures(
@@ -6603,7 +6933,7 @@ static void CheckIfAnyEnclosingLambdasMustCaptureAnyPotentialCaptures(
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.
@@ -6614,7 +6944,7 @@ static void CheckIfAnyEnclosingLambdasMustCaptureAnyPotentialCaptures(
VarDecl *Var = nullptr;
CurrentLSI->getPotentialVariableCapture(I, Var, VarExpr);
// If the variable is clearly identified as non-odr-used and the full
- // expression is not instantiation dependent, only then do we not
+ // expression is not instantiation dependent, only then do we not
// need to check enclosing lambda's for speculative captures.
// For e.g.:
// Even though 'x' is not odr-used, it should be captured.
@@ -6636,27 +6966,27 @@ static void CheckIfAnyEnclosingLambdasMustCaptureAnyPotentialCaptures(
const unsigned FunctionScopeIndexOfCapturableLambda = Index.getValue();
MarkVarDeclODRUsed(Var, VarExpr->getExprLoc(), S,
&FunctionScopeIndexOfCapturableLambda);
- }
- const bool IsVarNeverAConstantExpression =
+ }
+ const bool IsVarNeverAConstantExpression =
VariableCanNeverBeAConstantExpression(Var, S.Context);
if (!IsFullExprInstantiationDependent || IsVarNeverAConstantExpression) {
// This full expression is not instantiation dependent or the variable
- // can not be used in a constant expression - which means
- // this variable must be odr-used here, so diagnose a
+ // can not be used in a constant expression - which means
+ // this variable must be odr-used here, so diagnose a
// capture violation early, if the variable is un-captureable.
// This is purely for diagnosing errors early. Otherwise, this
// error would get diagnosed when the lambda becomes capture ready.
QualType CaptureType, DeclRefType;
SourceLocation ExprLoc = VarExpr->getExprLoc();
if (S.tryCaptureVariable(Var, ExprLoc, S.TryCapture_Implicit,
- /*EllipsisLoc*/ SourceLocation(),
- /*BuildAndDiagnose*/false, CaptureType,
+ /*EllipsisLoc*/ SourceLocation(),
+ /*BuildAndDiagnose*/false, CaptureType,
DeclRefType, nullptr)) {
// We will never be able to capture this variable, and we need
// to be able to in any and all instantiations, so diagnose it.
S.tryCaptureVariable(Var, ExprLoc, S.TryCapture_Implicit,
- /*EllipsisLoc*/ SourceLocation(),
- /*BuildAndDiagnose*/true, CaptureType,
+ /*EllipsisLoc*/ SourceLocation(),
+ /*BuildAndDiagnose*/true, CaptureType,
DeclRefType, nullptr);
}
}
@@ -6983,15 +7313,15 @@ Sema::CorrectDelayedTyposInExpr(Expr *E, VarDecl *InitDecl,
ExprResult Sema::ActOnFinishFullExpr(Expr *FE, SourceLocation CC,
bool DiscardedValue,
- bool IsConstexpr,
+ bool IsConstexpr,
bool IsLambdaInitCaptureInitializer) {
ExprResult FullExpr = FE;
if (!FullExpr.get())
return ExprError();
-
- // If we are an init-expression in a lambdas init-capture, we should not
- // diagnose an unexpanded pack now (will be diagnosed once lambda-expr
+
+ // If we are an init-expression in a lambdas init-capture, we should not
+ // diagnose an unexpanded pack now (will be diagnosed once lambda-expr
// containing full-expression is done).
// template<class ... Ts> void test(Ts ... t) {
// test([&a(t)]() { <-- (t) is an init-expr that shouldn't be diagnosed now.
@@ -7005,7 +7335,7 @@ ExprResult Sema::ActOnFinishFullExpr(Expr *FE, SourceLocation CC,
// lambda where we've entered the introducer but not the body, or represent a
// lambda where we've entered the body, depending on where the
// parser/instantiation has got to).
- if (!IsLambdaInitCaptureInitializer &&
+ if (!IsLambdaInitCaptureInitializer &&
DiagnoseUnexpandedParameterPack(FullExpr.get()))
return ExprError();
@@ -7033,13 +7363,13 @@ ExprResult Sema::ActOnFinishFullExpr(Expr *FE, SourceLocation CC,
CheckCompletedExpr(FullExpr.get(), CC, IsConstexpr);
- // At the end of this full expression (which could be a deeply nested
- // lambda), if there is a potential capture within the nested lambda,
+ // At the end of this full expression (which could be a deeply nested
+ // lambda), if there is a potential capture within the nested lambda,
// have the outer capture-able lambda try and capture it.
// Consider the following code:
// void f(int, int);
// void f(const int&, double);
- // void foo() {
+ // void foo() {
// const int x = 10, y = 20;
// auto L = [=](auto a) {
// auto M = [=](auto b) {
@@ -7049,35 +7379,35 @@ ExprResult Sema::ActOnFinishFullExpr(Expr *FE, SourceLocation CC,
// };
// }
- // FIXME: Also consider what happens for something like this that involves
- // the gnu-extension statement-expressions or even lambda-init-captures:
+ // FIXME: Also consider what happens for something like this that involves
+ // the gnu-extension statement-expressions or even lambda-init-captures:
// void f() {
// const int n = 0;
// auto L = [&](auto a) {
// +n + ({ 0; a; });
// };
// }
- //
- // Here, we see +n, and then the full-expression 0; ends, so we don't
- // capture n (and instead remove it from our list of potential captures),
- // and then the full-expression +n + ({ 0; }); ends, but it's too late
+ //
+ // Here, we see +n, and then the full-expression 0; ends, so we don't
+ // capture n (and instead remove it from our list of potential captures),
+ // and then the full-expression +n + ({ 0; }); ends, but it's too late
// for us to see that we need to capture n after all.
LambdaScopeInfo *const CurrentLSI =
getCurLambda(/*IgnoreCapturedRegions=*/true);
- // FIXME: PR 17877 showed that getCurLambda() can return a valid pointer
+ // FIXME: PR 17877 showed that getCurLambda() can return a valid pointer
// even if CurContext is not a lambda call operator. Refer to that Bug Report
- // for an example of the code that might cause this asynchrony.
+ // for an example of the code that might cause this asynchrony.
// By ensuring we are in the context of a lambda's call operator
// we can fix the bug (we only need to check whether we need to capture
- // if we are within a lambda's body); but per the comments in that
+ // if we are within a lambda's body); but per the comments in that
// PR, a proper fix would entail :
// "Alternative suggestion:
- // - Add to Sema an integer holding the smallest (outermost) scope
- // index that we are *lexically* within, and save/restore/set to
- // FunctionScopes.size() in InstantiatingTemplate's
+ // - Add to Sema an integer holding the smallest (outermost) scope
+ // index that we are *lexically* within, and save/restore/set to
+ // FunctionScopes.size() in InstantiatingTemplate's
// constructor/destructor.
- // - Teach the handful of places that iterate over FunctionScopes to
+ // - Teach the handful of places that iterate over FunctionScopes to
// stop at the outermost enclosing lexical scope."
DeclContext *DC = CurContext;
while (DC && isa<CapturedDecl>(DC))
@@ -7096,34 +7426,34 @@ StmtResult Sema::ActOnFinishFullStmt(Stmt *FullStmt) {
return MaybeCreateStmtWithCleanups(FullStmt);
}
-Sema::IfExistsResult
+Sema::IfExistsResult
Sema::CheckMicrosoftIfExistsSymbol(Scope *S,
CXXScopeSpec &SS,
const DeclarationNameInfo &TargetNameInfo) {
DeclarationName TargetName = TargetNameInfo.getName();
if (!TargetName)
return IER_DoesNotExist;
-
+
// If the name itself is dependent, then the result is dependent.
if (TargetName.isDependentName())
return IER_Dependent;
-
+
// Do the redeclaration lookup in the current scope.
LookupResult R(*this, TargetNameInfo, Sema::LookupAnyName,
Sema::NotForRedeclaration);
LookupParsedName(R, S, &SS);
R.suppressDiagnostics();
-
+
switch (R.getResultKind()) {
case LookupResult::Found:
case LookupResult::FoundOverloaded:
case LookupResult::FoundUnresolvedValue:
case LookupResult::Ambiguous:
return IER_Exists;
-
+
case LookupResult::NotFound:
return IER_DoesNotExist;
-
+
case LookupResult::NotFoundInCurrentInstantiation:
return IER_Dependent;
}
@@ -7131,23 +7461,17 @@ Sema::CheckMicrosoftIfExistsSymbol(Scope *S,
llvm_unreachable("Invalid LookupResult Kind!");
}
-Sema::IfExistsResult
+Sema::IfExistsResult
Sema::CheckMicrosoftIfExistsSymbol(Scope *S, SourceLocation KeywordLoc,
bool IsIfExists, CXXScopeSpec &SS,
UnqualifiedId &Name) {
DeclarationNameInfo TargetNameInfo = GetNameFromUnqualifiedId(Name);
-
- // Check for unexpanded parameter packs.
- SmallVector<UnexpandedParameterPack, 4> Unexpanded;
- collectUnexpandedParameterPacks(SS, Unexpanded);
- collectUnexpandedParameterPacks(TargetNameInfo, Unexpanded);
- if (!Unexpanded.empty()) {
- DiagnoseUnexpandedParameterPacks(KeywordLoc,
- IsIfExists? UPPC_IfExists
- : UPPC_IfNotExists,
- Unexpanded);
+
+ // Check for an unexpanded parameter pack.
+ auto UPPC = IsIfExists ? UPPC_IfExists : UPPC_IfNotExists;
+ if (DiagnoseUnexpandedParameterPack(SS, UPPC) ||
+ DiagnoseUnexpandedParameterPack(TargetNameInfo, UPPC))
return IER_Error;
- }
-
+
return CheckMicrosoftIfExistsSymbol(S, SS, TargetNameInfo);
}
diff --git a/lib/Sema/SemaExprMember.cpp b/lib/Sema/SemaExprMember.cpp
index 283621889f80..806a3d813ee8 100644
--- a/lib/Sema/SemaExprMember.cpp
+++ b/lib/Sema/SemaExprMember.cpp
@@ -269,6 +269,20 @@ Sema::BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS,
llvm_unreachable("unexpected instance member access kind");
}
+/// Determine whether input char is from rgba component set.
+static bool
+IsRGBA(char c) {
+ switch (c) {
+ case 'r':
+ case 'g':
+ case 'b':
+ case 'a':
+ return true;
+ default:
+ return false;
+ }
+}
+
/// Check an ext-vector component access expression.
///
/// VK should be set in advance to the value kind of the base
@@ -308,11 +322,25 @@ CheckExtVectorComponent(Sema &S, QualType baseType, ExprValueKind &VK,
HalvingSwizzle = true;
} else if (!HexSwizzle &&
(Idx = vecType->getPointAccessorIdx(*compStr)) != -1) {
+ bool HasRGBA = IsRGBA(*compStr);
do {
+ // Ensure that xyzw and rgba components don't intermingle.
+ if (HasRGBA != IsRGBA(*compStr))
+ break;
if (HasIndex[Idx]) HasRepeated = true;
HasIndex[Idx] = true;
compStr++;
} while (*compStr && (Idx = vecType->getPointAccessorIdx(*compStr)) != -1);
+
+ // Emit a warning if an rgba selector is used earlier than OpenCL 2.2
+ if (HasRGBA || (*compStr && IsRGBA(*compStr))) {
+ if (S.getLangOpts().OpenCL && S.getLangOpts().OpenCLVersion < 220) {
+ const char *DiagBegin = HasRGBA ? CompName->getNameStart() : compStr;
+ S.Diag(OpLoc, diag::ext_opencl_ext_vector_type_rgba_selector)
+ << StringRef(DiagBegin, 1)
+ << S.getLangOpts().OpenCLVersion << SourceRange(CompLoc);
+ }
+ }
} else {
if (HexSwizzle) compStr++;
while ((Idx = vecType->getNumericAccessorIdx(*compStr)) != -1) {
@@ -339,7 +367,7 @@ CheckExtVectorComponent(Sema &S, QualType baseType, ExprValueKind &VK,
compStr++;
while (*compStr) {
- if (!vecType->isAccessorWithinNumElements(*compStr++)) {
+ if (!vecType->isAccessorWithinNumElements(*compStr++, HexSwizzle)) {
S.Diag(OpLoc, diag::err_ext_vector_component_exceeds_length)
<< baseType << SourceRange(CompLoc);
return QualType();
@@ -743,12 +771,6 @@ Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType,
false, ExtraArgs);
}
-static ExprResult
-BuildFieldReferenceExpr(Sema &S, Expr *BaseExpr, bool IsArrow,
- SourceLocation OpLoc, const CXXScopeSpec &SS,
- FieldDecl *Field, DeclAccessPair FoundDecl,
- const DeclarationNameInfo &MemberNameInfo);
-
ExprResult
Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS,
SourceLocation loc,
@@ -834,7 +856,7 @@ Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS,
// Make a nameInfo that properly uses the anonymous name.
DeclarationNameInfo memberNameInfo(field->getDeclName(), loc);
- result = BuildFieldReferenceExpr(*this, result, baseObjectIsPointer,
+ result = BuildFieldReferenceExpr(result, baseObjectIsPointer,
SourceLocation(), EmptySS, field,
foundDecl, memberNameInfo).get();
if (!result)
@@ -855,9 +877,10 @@ Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS,
DeclAccessPair::make(field, field->getAccess());
result =
- BuildFieldReferenceExpr(*this, result, /*isarrow*/ false,
- SourceLocation(), (FI == FEnd ? SS : EmptySS),
- field, fakeFoundDecl, memberNameInfo).get();
+ BuildFieldReferenceExpr(result, /*isarrow*/ false, SourceLocation(),
+ (FI == FEnd ? SS : EmptySS), field,
+ fakeFoundDecl, memberNameInfo)
+ .get();
}
return result;
@@ -946,6 +969,15 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
BaseType = BaseType->castAs<PointerType>()->getPointeeType();
}
R.setBaseObjectType(BaseType);
+
+ // C++1z [expr.ref]p2:
+ // For the first option (dot) the first expression shall be a glvalue [...]
+ if (!IsArrow && BaseExpr->isRValue()) {
+ ExprResult Converted = TemporaryMaterializationConversion(BaseExpr);
+ if (Converted.isInvalid())
+ return ExprError();
+ BaseExpr = Converted.get();
+ }
LambdaScopeInfo *const CurLSI = getCurLambda();
// If this is an implicit member reference and the overloaded
@@ -1125,8 +1157,8 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
return ExprError();
if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl))
- return BuildFieldReferenceExpr(*this, BaseExpr, IsArrow, OpLoc, SS, FD,
- FoundDecl, MemberNameInfo);
+ return BuildFieldReferenceExpr(BaseExpr, IsArrow, OpLoc, SS, FD, FoundDecl,
+ MemberNameInfo);
if (MSPropertyDecl *PD = dyn_cast<MSPropertyDecl>(MemberDecl))
return BuildMSPropertyRefExpr(*this, BaseExpr, IsArrow, SS, PD,
@@ -1371,10 +1403,17 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
// Figure out the class that declares the ivar.
assert(!ClassDeclared);
+
Decl *D = cast<Decl>(IV->getDeclContext());
- if (ObjCCategoryDecl *CAT = dyn_cast<ObjCCategoryDecl>(D))
- D = CAT->getClassInterface();
- ClassDeclared = cast<ObjCInterfaceDecl>(D);
+ if (auto *Category = dyn_cast<ObjCCategoryDecl>(D))
+ D = Category->getClassInterface();
+
+ if (auto *Implementation = dyn_cast<ObjCImplementationDecl>(D))
+ ClassDeclared = Implementation->getClassInterface();
+ else if (auto *Interface = dyn_cast<ObjCInterfaceDecl>(D))
+ ClassDeclared = Interface;
+
+ assert(ClassDeclared && "cannot query interface");
} else {
if (IsArrow &&
IDecl->FindPropertyDeclaration(
@@ -1426,11 +1465,11 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
if (IV->getAccessControl() == ObjCIvarDecl::Private) {
if (!declaresSameEntity(ClassDeclared, IDecl) ||
!declaresSameEntity(ClassOfMethodDecl, ClassDeclared))
- S.Diag(MemberLoc, diag::error_private_ivar_access)
+ S.Diag(MemberLoc, diag::err_private_ivar_access)
<< IV->getDeclName();
} else if (!IDecl->isSuperClassOf(ClassOfMethodDecl))
// @protected
- S.Diag(MemberLoc, diag::error_protected_ivar_access)
+ S.Diag(MemberLoc, diag::err_protected_ivar_access)
<< IV->getDeclName();
}
}
@@ -1443,7 +1482,7 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
if (DeclRefExpr *DE = dyn_cast<DeclRefExpr>(BaseExp))
if (DE->getType().getObjCLifetime() == Qualifiers::OCL_Weak) {
- S.Diag(DE->getLocation(), diag::error_arc_weak_ivar_access);
+ S.Diag(DE->getLocation(), diag::err_arc_weak_ivar_access);
warn = false;
}
}
@@ -1729,11 +1768,11 @@ ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base,
NameInfo, TemplateArgs, S, &ExtraArgs);
}
-static ExprResult
-BuildFieldReferenceExpr(Sema &S, Expr *BaseExpr, bool IsArrow,
- SourceLocation OpLoc, const CXXScopeSpec &SS,
- FieldDecl *Field, DeclAccessPair FoundDecl,
- const DeclarationNameInfo &MemberNameInfo) {
+ExprResult
+Sema::BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow,
+ SourceLocation OpLoc, const CXXScopeSpec &SS,
+ FieldDecl *Field, DeclAccessPair FoundDecl,
+ const DeclarationNameInfo &MemberNameInfo) {
// x.a is an l-value if 'a' has a reference type. Otherwise:
// x.a is an l-value/x-value/pr-value if the base is (and note
// that *x is always an l-value), except that if the base isn't
@@ -1767,36 +1806,34 @@ BuildFieldReferenceExpr(Sema &S, Expr *BaseExpr, bool IsArrow,
// except that 'mutable' members don't pick up 'const'.
if (Field->isMutable()) BaseQuals.removeConst();
- Qualifiers MemberQuals
- = S.Context.getCanonicalType(MemberType).getQualifiers();
+ Qualifiers MemberQuals =
+ Context.getCanonicalType(MemberType).getQualifiers();
assert(!MemberQuals.hasAddressSpace());
-
Qualifiers Combined = BaseQuals + MemberQuals;
if (Combined != MemberQuals)
- MemberType = S.Context.getQualifiedType(MemberType, Combined);
+ MemberType = Context.getQualifiedType(MemberType, Combined);
}
- S.UnusedPrivateFields.remove(Field);
+ UnusedPrivateFields.remove(Field);
- ExprResult Base =
- S.PerformObjectMemberConversion(BaseExpr, SS.getScopeRep(),
- FoundDecl, Field);
+ ExprResult Base = PerformObjectMemberConversion(BaseExpr, SS.getScopeRep(),
+ FoundDecl, Field);
if (Base.isInvalid())
return ExprError();
MemberExpr *ME =
- BuildMemberExpr(S, S.Context, Base.get(), IsArrow, OpLoc, SS,
+ BuildMemberExpr(*this, Context, Base.get(), IsArrow, OpLoc, SS,
/*TemplateKWLoc=*/SourceLocation(), Field, FoundDecl,
MemberNameInfo, MemberType, VK, OK);
// Build a reference to a private copy for non-static data members in
// non-static member functions, privatized by OpenMP constructs.
- if (S.getLangOpts().OpenMP && IsArrow &&
- !S.CurContext->isDependentContext() &&
+ if (getLangOpts().OpenMP && IsArrow &&
+ !CurContext->isDependentContext() &&
isa<CXXThisExpr>(Base.get()->IgnoreParenImpCasts())) {
- if (auto *PrivateCopy = S.IsOpenMPCapturedDecl(Field))
- return S.getOpenMPCapturedExpr(PrivateCopy, VK, OK, OpLoc);
+ if (auto *PrivateCopy = IsOpenMPCapturedDecl(Field))
+ return getOpenMPCapturedExpr(PrivateCopy, VK, OK, OpLoc);
}
return ME;
}
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index 8f0d4ff69576..7dbd660f53ec 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -1112,7 +1112,7 @@ static bool HelperToDiagnoseMismatchedMethodsInGlobalPool(Sema &S,
MatchingMethodDecl, Sema::MMS_loose)) {
if (!Warned) {
Warned = true;
- S.Diag(AtLoc, diag::warning_multiple_selectors)
+ S.Diag(AtLoc, diag::warn_multiple_selectors)
<< Method->getSelector() << FixItHint::CreateInsertion(LParenLoc, "(")
<< FixItHint::CreateInsertion(RParenLoc, ")");
S.Diag(Method->getLocation(), diag::note_method_declared_at)
@@ -1131,7 +1131,7 @@ static void DiagnoseMismatchedSelectors(Sema &S, SourceLocation AtLoc,
SourceLocation RParenLoc,
bool WarnMultipleSelectors) {
if (!WarnMultipleSelectors ||
- S.Diags.isIgnored(diag::warning_multiple_selectors, SourceLocation()))
+ S.Diags.isIgnored(diag::warn_multiple_selectors, SourceLocation()))
return;
bool Warned = false;
for (Sema::GlobalMethodPool::iterator b = S.MethodPool.begin(),
@@ -1534,7 +1534,7 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
const ObjCMethodDecl *OMD = SelectorsForTypoCorrection(Sel, ReceiverType);
if (OMD && !OMD->isInvalidDecl()) {
if (getLangOpts().ObjCAutoRefCount)
- DiagID = diag::error_method_not_found_with_typo;
+ DiagID = diag::err_method_not_found_with_typo;
else
DiagID = isClassMessage ? diag::warn_class_method_not_found_with_typo
: diag::warn_instance_method_not_found_with_typo;
@@ -1956,7 +1956,7 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
if (CurMethod->isInstanceMethod()) {
if (SuperType.isNull()) {
// The current class does not have a superclass.
- Diag(receiverNameLoc, diag::error_root_class_cannot_use_super)
+ Diag(receiverNameLoc, diag::err_root_class_cannot_use_super)
<< CurMethod->getClassInterface()->getIdentifier();
return ExprError();
}
@@ -2165,7 +2165,7 @@ ExprResult Sema::ActOnSuperMessage(Scope *S,
ObjCInterfaceDecl *Class = Method->getClassInterface();
if (!Class) {
- Diag(SuperLoc, diag::error_no_super_class_message)
+ Diag(SuperLoc, diag::err_no_super_class_message)
<< Method->getDeclName();
return ExprError();
}
@@ -2173,7 +2173,7 @@ ExprResult Sema::ActOnSuperMessage(Scope *S,
QualType SuperTy(Class->getSuperClassType(), 0);
if (SuperTy.isNull()) {
// The current class does not have a superclass.
- Diag(SuperLoc, diag::error_root_class_cannot_use_super)
+ Diag(SuperLoc, diag::err_root_class_cannot_use_super)
<< Class->getIdentifier();
return ExprError();
}
@@ -2539,6 +2539,10 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
SourceLocation RBracLoc,
MultiExprArg ArgsIn,
bool isImplicit) {
+ assert((Receiver || SuperLoc.isValid()) && "If the Receiver is null, the "
+ "SuperLoc must be valid so we can "
+ "use it instead.");
+
// The location of the receiver.
SourceLocation Loc = SuperLoc.isValid()? SuperLoc : Receiver->getLocStart();
SourceRange RecRange =
@@ -2645,7 +2649,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
CollectMultipleMethodsInGlobalPool(Sel, Methods, true/*InstanceFirst*/,
true/*CheckTheOther*/, typeBound);
if (!Methods.empty()) {
- // We chose the first method as the initial condidate, then try to
+ // We choose the first method as the initial candidate, then try to
// select a better one.
Method = Methods[0];
@@ -2701,7 +2705,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
false/*InstanceFirst*/,
true/*CheckTheOther*/);
if (!Methods.empty()) {
- // We chose the first method as the initial condidate, then try
+ // We choose the first method as the initial candidate, then try
// to select a better one.
Method = Methods[0];
@@ -2789,7 +2793,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
true/*InstanceFirst*/,
false/*CheckTheOther*/);
if (!Methods.empty()) {
- // We chose the first method as the initial condidate, then try
+ // We choose the first method as the initial candidate, then try
// to select a better one.
Method = Methods[0];
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 060ee3eef212..befee05713e0 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -11,7 +11,6 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Sema/Initialization.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/ExprCXX.h"
@@ -19,13 +18,13 @@
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/Designator.h"
+#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/SemaInternal.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
-#include <map>
using namespace clang;
@@ -470,9 +469,14 @@ ExprResult InitListChecker::PerformEmptyInit(Sema &SemaRef,
SemaRef.Diag(Entity.getDecl()->getLocation(),
diag::note_in_omitted_aggregate_initializer)
<< /*field*/1 << Entity.getDecl();
- else if (Entity.getKind() == InitializedEntity::EK_ArrayElement)
+ else if (Entity.getKind() == InitializedEntity::EK_ArrayElement) {
+ bool IsTrailingArrayNewMember =
+ Entity.getParent() &&
+ Entity.getParent()->isVariableLengthArrayNew();
SemaRef.Diag(Loc, diag::note_in_omitted_aggregate_initializer)
- << /*array element*/0 << Entity.getElementIndex();
+ << (IsTrailingArrayNewMember ? 2 : /*array element*/0)
+ << Entity.getElementIndex();
+ }
}
return ExprError();
}
@@ -686,8 +690,12 @@ InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity,
unsigned NumElements = NumInits;
if (const ArrayType *AType = SemaRef.Context.getAsArrayType(ILE->getType())) {
ElementType = AType->getElementType();
- if (const ConstantArrayType *CAType = dyn_cast<ConstantArrayType>(AType))
+ if (const auto *CAType = dyn_cast<ConstantArrayType>(AType))
NumElements = CAType->getSize().getZExtValue();
+ // For an array new with an unknown bound, ask for one additional element
+ // in order to populate the array filler.
+ if (Entity.isVariableLengthArrayNew())
+ ++NumElements;
ElementEntity = InitializedEntity::InitializeElement(SemaRef.Context,
0, Entity);
} else if (const VectorType *VType = ILE->getType()->getAs<VectorType>()) {
@@ -937,6 +945,7 @@ static void warnBracedScalarInit(Sema &S, const InitializedEntity &Entity,
case InitializedEntity::EK_Base:
case InitializedEntity::EK_Delegating:
case InitializedEntity::EK_BlockElement:
+ case InitializedEntity::EK_Binding:
llvm_unreachable("unexpected braced scalar init");
}
@@ -1229,8 +1238,9 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
// subaggregate, brace elision is assumed and the initializer is
// considered for the initialization of the first member of
// the subaggregate.
- if (!SemaRef.getLangOpts().OpenCL &&
- (ElemType->isAggregateType() || ElemType->isVectorType())) {
+ // OpenCL vector initializer is handled elsewhere.
+ if ((!SemaRef.getLangOpts().OpenCL && ElemType->isVectorType()) ||
+ ElemType->isAggregateType()) {
CheckImplicitInitList(Entity, IList, ElemType, Index, StructuredList,
StructuredIndex);
++StructuredIndex;
@@ -1685,10 +1695,13 @@ void InitListChecker::CheckArrayType(const InitializedEntity &Entity,
ArrayType::Normal, 0);
}
if (!hadError && VerifyOnly) {
- // Check if there are any members of the array that get value-initialized.
- // If so, check if doing that is possible.
+ // If there are any members of the array that get value-initialized, check
+ // that is possible. That happens if we know the bound and don't have
+ // enough elements, or if we're performing an array new with an unknown
+ // bound.
// FIXME: This needs to detect holes left by designated initializers too.
- if (maxElementsKnown && elementIndex < maxElements)
+ if ((maxElementsKnown && elementIndex < maxElements) ||
+ Entity.isVariableLengthArrayNew())
CheckEmptyInitializable(InitializedEntity::InitializeElement(
SemaRef.Context, 0, Entity),
IList->getLocEnd());
@@ -2896,7 +2909,8 @@ DeclarationName InitializedEntity::getName() const {
case EK_Variable:
case EK_Member:
- return VariableOrMember->getDeclName();
+ case EK_Binding:
+ return Variable.VariableOrMember->getDeclName();
case EK_LambdaCapture:
return DeclarationName(Capture.VarID);
@@ -2919,11 +2933,12 @@ DeclarationName InitializedEntity::getName() const {
llvm_unreachable("Invalid EntityKind!");
}
-DeclaratorDecl *InitializedEntity::getDecl() const {
+ValueDecl *InitializedEntity::getDecl() const {
switch (getKind()) {
case EK_Variable:
case EK_Member:
- return VariableOrMember;
+ case EK_Binding:
+ return Variable.VariableOrMember;
case EK_Parameter:
case EK_Parameter_CF_Audited:
@@ -2958,6 +2973,7 @@ bool InitializedEntity::allowsNRVO() const {
case EK_Parameter:
case EK_Parameter_CF_Audited:
case EK_Member:
+ case EK_Binding:
case EK_New:
case EK_Temporary:
case EK_CompoundLiteralInit:
@@ -2989,6 +3005,7 @@ unsigned InitializedEntity::dumpImpl(raw_ostream &OS) const {
case EK_Result: OS << "Result"; break;
case EK_Exception: OS << "Exception"; break;
case EK_Member: OS << "Member"; break;
+ case EK_Binding: OS << "Binding"; break;
case EK_New: OS << "New"; break;
case EK_Temporary: OS << "Temporary"; break;
case EK_CompoundLiteralInit: OS << "CompoundLiteral";break;
@@ -3005,9 +3022,9 @@ unsigned InitializedEntity::dumpImpl(raw_ostream &OS) const {
break;
}
- if (Decl *D = getDecl()) {
+ if (auto *D = getDecl()) {
OS << " ";
- cast<NamedDecl>(D)->printQualifiedName(OS);
+ D->printQualifiedName(OS);
}
OS << " '" << getType().getAsString() << "'\n";
@@ -3031,6 +3048,7 @@ void InitializationSequence::Step::Destroy() {
case SK_CastDerivedToBaseLValue:
case SK_BindReference:
case SK_BindReferenceToTemporary:
+ case SK_FinalCopy:
case SK_ExtraneousCopyToTemporary:
case SK_UserConversion:
case SK_QualificationConversionRValue:
@@ -3047,7 +3065,10 @@ void InitializationSequence::Step::Destroy() {
case SK_CAssignment:
case SK_StringInit:
case SK_ObjCObjectConversion:
+ case SK_ArrayLoopIndex:
+ case SK_ArrayLoopInit:
case SK_ArrayInit:
+ case SK_GNUArrayInit:
case SK_ParenthesizedArrayInit:
case SK_PassByIndirectCopyRestore:
case SK_PassByIndirectRestore:
@@ -3056,6 +3077,7 @@ void InitializationSequence::Step::Destroy() {
case SK_StdInitializerListConstructorCall:
case SK_OCLSamplerInit:
case SK_OCLZeroEvent:
+ case SK_OCLZeroQueue:
break;
case SK_ConversionSequence:
@@ -3065,7 +3087,14 @@ void InitializationSequence::Step::Destroy() {
}
bool InitializationSequence::isDirectReferenceBinding() const {
- return !Steps.empty() && Steps.back().Kind == SK_BindReference;
+ // There can be some lvalue adjustments after the SK_BindReference step.
+ for (auto I = Steps.rbegin(); I != Steps.rend(); ++I) {
+ if (I->Kind == SK_BindReference)
+ return true;
+ if (I->Kind == SK_BindReferenceToTemporary)
+ return false;
+ }
+ return false;
}
bool InitializationSequence::isAmbiguous() const {
@@ -3082,6 +3111,8 @@ bool InitializationSequence::isAmbiguous() const {
case FK_IncompatWideStringIntoWideChar:
case FK_AddressOfOverloadFailed: // FIXME: Could do better
case FK_NonConstLValueReferenceBindingToTemporary:
+ case FK_NonConstLValueReferenceBindingToBitfield:
+ case FK_NonConstLValueReferenceBindingToVectorElement:
case FK_NonConstLValueReferenceBindingToUnrelated:
case FK_RValueReferenceBindingToLValue:
case FK_ReferenceInitDropsQualifiers:
@@ -3150,6 +3181,13 @@ void InitializationSequence::AddReferenceBindingStep(QualType T,
Steps.push_back(S);
}
+void InitializationSequence::AddFinalCopy(QualType T) {
+ Step S;
+ S.Kind = SK_FinalCopy;
+ S.Type = T;
+ Steps.push_back(S);
+}
+
void InitializationSequence::AddExtraneousCopyToTemporary(QualType T) {
Step S;
S.Kind = SK_ExtraneousCopyToTemporary;
@@ -3266,9 +3304,20 @@ void InitializationSequence::AddObjCObjectConversionStep(QualType T) {
Steps.push_back(S);
}
-void InitializationSequence::AddArrayInitStep(QualType T) {
+void InitializationSequence::AddArrayInitStep(QualType T, bool IsGNUExtension) {
Step S;
- S.Kind = SK_ArrayInit;
+ S.Kind = IsGNUExtension ? SK_GNUArrayInit : SK_ArrayInit;
+ S.Type = T;
+ Steps.push_back(S);
+}
+
+void InitializationSequence::AddArrayInitLoopStep(QualType T, QualType EltT) {
+ Step S;
+ S.Kind = SK_ArrayLoopIndex;
+ S.Type = EltT;
+ Steps.insert(Steps.begin(), S);
+
+ S.Kind = SK_ArrayLoopInit;
S.Type = T;
Steps.push_back(S);
}
@@ -3317,6 +3366,13 @@ void InitializationSequence::AddOCLZeroEventStep(QualType T) {
Steps.push_back(S);
}
+void InitializationSequence::AddOCLZeroQueueStep(QualType T) {
+ Step S;
+ S.Kind = SK_OCLZeroQueue;
+ S.Type = T;
+ Steps.push_back(S);
+}
+
void InitializationSequence::RewrapReferenceInitList(QualType T,
InitListExpr *Syntactic) {
assert(Syntactic->getNumInits() == 1 &&
@@ -3434,6 +3490,23 @@ static bool TryInitializerListConstruction(Sema &S,
return true;
}
+/// Determine if the constructor has the signature of a copy or move
+/// constructor for the type T of the class in which it was found. That is,
+/// determine if its first parameter is of type T or reference to (possibly
+/// cv-qualified) T.
+static bool hasCopyOrMoveCtorParam(ASTContext &Ctx,
+ const ConstructorInfo &Info) {
+ if (Info.Constructor->getNumParams() == 0)
+ return false;
+
+ QualType ParmT =
+ Info.Constructor->getParamDecl(0)->getType().getNonReferenceType();
+ QualType ClassT =
+ Ctx.getRecordType(cast<CXXRecordDecl>(Info.FoundDecl->getDeclContext()));
+
+ return Ctx.hasSameUnqualifiedType(ParmT, ClassT);
+}
+
static OverloadingResult
ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc,
MultiExprArg Args,
@@ -3441,59 +3514,56 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc,
DeclContext::lookup_result Ctors,
OverloadCandidateSet::iterator &Best,
bool CopyInitializing, bool AllowExplicit,
- bool OnlyListConstructors, bool IsListInit) {
+ bool OnlyListConstructors, bool IsListInit,
+ bool SecondStepOfCopyInit = false) {
CandidateSet.clear();
for (NamedDecl *D : Ctors) {
auto Info = getConstructorInfo(D);
- if (!Info.Constructor)
+ if (!Info.Constructor || Info.Constructor->isInvalidDecl())
continue;
- bool SuppressUserConversions = false;
-
- if (!Info.ConstructorTmpl) {
- // C++11 [over.best.ics]p4:
- // ... and the constructor or user-defined conversion function is a
- // candidate by
- // - 13.3.1.3, when the argument is the temporary in the second step
- // of a class copy-initialization, or
- // - 13.3.1.4, 13.3.1.5, or 13.3.1.6 (in all cases),
- // user-defined conversion sequences are not considered.
- // FIXME: This breaks backward compatibility, e.g. PR12117. As a
- // temporary fix, let's re-instate the third bullet above until
- // there is a resolution in the standard, i.e.,
- // - 13.3.1.7 when the initializer list has exactly one element that is
- // itself an initializer list and a conversion to some class X or
- // reference to (possibly cv-qualified) X is considered for the first
- // parameter of a constructor of X.
- if ((CopyInitializing ||
- (IsListInit && Args.size() == 1 && isa<InitListExpr>(Args[0]))) &&
- Info.Constructor->isCopyOrMoveConstructor())
- SuppressUserConversions = true;
- }
-
- if (!Info.Constructor->isInvalidDecl() &&
- (AllowExplicit || !Info.Constructor->isExplicit()) &&
- (!OnlyListConstructors || S.isInitListConstructor(Info.Constructor))) {
- if (Info.ConstructorTmpl)
- S.AddTemplateOverloadCandidate(Info.ConstructorTmpl, Info.FoundDecl,
- /*ExplicitArgs*/ nullptr, Args,
- CandidateSet, SuppressUserConversions);
- else {
- // C++ [over.match.copy]p1:
- // - When initializing a temporary to be bound to the first parameter
- // of a constructor that takes a reference to possibly cv-qualified
- // T as its first argument, called with a single argument in the
- // context of direct-initialization, explicit conversion functions
- // are also considered.
- bool AllowExplicitConv = AllowExplicit && !CopyInitializing &&
- Args.size() == 1 &&
- Info.Constructor->isCopyOrMoveConstructor();
- S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl, Args,
- CandidateSet, SuppressUserConversions,
- /*PartialOverloading=*/false,
- /*AllowExplicit=*/AllowExplicitConv);
- }
+ if (!AllowExplicit && Info.Constructor->isExplicit())
+ continue;
+
+ if (OnlyListConstructors && !S.isInitListConstructor(Info.Constructor))
+ continue;
+
+ // C++11 [over.best.ics]p4:
+ // ... and the constructor or user-defined conversion function is a
+ // candidate by
+ // - 13.3.1.3, when the argument is the temporary in the second step
+ // of a class copy-initialization, or
+ // - 13.3.1.4, 13.3.1.5, or 13.3.1.6 (in all cases), [not handled here]
+ // - the second phase of 13.3.1.7 when the initializer list has exactly
+ // one element that is itself an initializer list, and the target is
+ // the first parameter of a constructor of class X, and the conversion
+ // is to X or reference to (possibly cv-qualified X),
+ // user-defined conversion sequences are not considered.
+ bool SuppressUserConversions =
+ SecondStepOfCopyInit ||
+ (IsListInit && Args.size() == 1 && isa<InitListExpr>(Args[0]) &&
+ hasCopyOrMoveCtorParam(S.Context, Info));
+
+ if (Info.ConstructorTmpl)
+ S.AddTemplateOverloadCandidate(Info.ConstructorTmpl, Info.FoundDecl,
+ /*ExplicitArgs*/ nullptr, Args,
+ CandidateSet, SuppressUserConversions);
+ else {
+ // C++ [over.match.copy]p1:
+ // - When initializing a temporary to be bound to the first parameter
+ // of a constructor [for type T] that takes a reference to possibly
+ // cv-qualified T as its first argument, called with a single
+ // argument in the context of direct-initialization, explicit
+ // conversion functions are also considered.
+ // FIXME: What if a constructor template instantiates to such a signature?
+ bool AllowExplicitConv = AllowExplicit && !CopyInitializing &&
+ Args.size() == 1 &&
+ hasCopyOrMoveCtorParam(S.Context, Info);
+ S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl, Args,
+ CandidateSet, SuppressUserConversions,
+ /*PartialOverloading=*/false,
+ /*AllowExplicit=*/AllowExplicitConv);
}
}
@@ -3504,6 +3574,9 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc,
/// \brief 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.
+/// \param DestArrayType The destination type, which is either DestType or
+/// a (possibly multidimensional) array of DestType.
/// \param IsListInit Is this list-initialization?
/// \param IsInitListCopy Is this non-list-initialization resulting from a
/// list-initialization from {x} where x is the same
@@ -3512,11 +3585,18 @@ static void TryConstructorInitialization(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
MultiExprArg Args, QualType DestType,
+ QualType DestArrayType,
InitializationSequence &Sequence,
bool IsListInit = false,
bool IsInitListCopy = false) {
- assert((!IsListInit || (Args.size() == 1 && isa<InitListExpr>(Args[0]))) &&
- "IsListInit must come with a single initializer list argument.");
+ assert(((!IsListInit && !IsInitListCopy) ||
+ (Args.size() == 1 && isa<InitListExpr>(Args[0]))) &&
+ "IsListInit/IsInitListCopy must come with a single initializer list "
+ "argument.");
+ InitListExpr *ILE =
+ (IsListInit || IsInitListCopy) ? cast<InitListExpr>(Args[0]) : nullptr;
+ MultiExprArg UnwrappedArgs =
+ ILE ? MultiExprArg(ILE->getInits(), ILE->getNumInits()) : Args;
// The type we're constructing needs to be complete.
if (!S.isCompleteType(Kind.getLocation(), DestType)) {
@@ -3524,6 +3604,25 @@ static void TryConstructorInitialization(Sema &S,
return;
}
+ // C++1z [dcl.init]p17:
+ // - If the initializer expression is a prvalue and the cv-unqualified
+ // version of the source type is the same class as the class of the
+ // destination, the initializer expression is used to initialize the
+ // destination object.
+ // Per DR (no number yet), this does not apply when initializing a base
+ // class or delegating to another constructor from a mem-initializer.
+ if (S.getLangOpts().CPlusPlus1z &&
+ Entity.getKind() != InitializedEntity::EK_Base &&
+ Entity.getKind() != InitializedEntity::EK_Delegating &&
+ UnwrappedArgs.size() == 1 && UnwrappedArgs[0]->isRValue() &&
+ S.Context.hasSameUnqualifiedType(UnwrappedArgs[0]->getType(), DestType)) {
+ // Convert qualifications if necessary.
+ Sequence.AddQualificationConversionStep(DestType, VK_RValue);
+ if (ILE)
+ Sequence.RewrapReferenceInitList(DestType, ILE);
+ return;
+ }
+
const RecordType *DestRecordType = DestType->getAs<RecordType>();
assert(DestRecordType && "Constructor initialization requires record type");
CXXRecordDecl *DestRecordDecl
@@ -3557,20 +3656,16 @@ static void TryConstructorInitialization(Sema &S,
// constructors of the class T and the argument list consists of the
// initializer list as a single argument.
if (IsListInit) {
- InitListExpr *ILE = cast<InitListExpr>(Args[0]);
AsInitializerList = true;
// If the initializer list has no elements and T has a default constructor,
// the first phase is omitted.
- if (ILE->getNumInits() != 0 || !DestRecordDecl->hasDefaultConstructor())
+ if (!(UnwrappedArgs.empty() && DestRecordDecl->hasDefaultConstructor()))
Result = ResolveConstructorOverload(S, Kind.getLocation(), Args,
CandidateSet, Ctors, Best,
CopyInitialization, AllowExplicit,
/*OnlyListConstructor=*/true,
IsListInit);
-
- // Time to unwrap the init list.
- Args = MultiExprArg(ILE->getInits(), ILE->getNumInits());
}
// C++11 [over.match.list]p1:
@@ -3580,7 +3675,7 @@ static void TryConstructorInitialization(Sema &S,
// elements of the initializer list.
if (Result == OR_No_Viable_Function) {
AsInitializerList = false;
- Result = ResolveConstructorOverload(S, Kind.getLocation(), Args,
+ Result = ResolveConstructorOverload(S, Kind.getLocation(), UnwrappedArgs,
CandidateSet, Ctors, Best,
CopyInitialization, AllowExplicit,
/*OnlyListConstructors=*/false,
@@ -3624,7 +3719,7 @@ static void TryConstructorInitialization(Sema &S,
// subsumed by the initialization.
bool HadMultipleCandidates = (CandidateSet.size() > 1);
Sequence.AddConstructorInitializationStep(
- Best->FoundDecl, CtorDecl, DestType, HadMultipleCandidates,
+ Best->FoundDecl, CtorDecl, DestArrayType, HadMultipleCandidates,
IsListInit | IsInitListCopy, AsInitializerList);
}
@@ -3790,10 +3885,11 @@ static void TryListInitialization(Sema &S,
QualType InitType = InitList->getInit(0)->getType();
if (S.Context.hasSameUnqualifiedType(InitType, DestType) ||
S.IsDerivedFrom(InitList->getLocStart(), InitType, DestType)) {
- Expr *InitAsExpr = InitList->getInit(0);
- TryConstructorInitialization(S, Entity, Kind, InitAsExpr, DestType,
- Sequence, /*InitListSyntax*/ false,
- /*IsInitListCopy*/ true);
+ Expr *InitListAsExpr = InitList;
+ TryConstructorInitialization(S, Entity, Kind, InitListAsExpr, DestType,
+ DestType, Sequence,
+ /*InitListSyntax*/false,
+ /*IsInitListCopy*/true);
return;
}
}
@@ -3848,7 +3944,7 @@ static void TryListInitialization(Sema &S,
// - Otherwise, if T is a class type, constructors are considered.
Expr *InitListAsExpr = InitList;
TryConstructorInitialization(S, Entity, Kind, InitListAsExpr, DestType,
- Sequence, /*InitListSyntax*/ true);
+ DestType, Sequence, /*InitListSyntax*/true);
} else
Sequence.SetFailed(InitializationSequence::FK_InitListBadDestinationType);
return;
@@ -3940,12 +4036,10 @@ static void TryListInitialization(Sema &S,
/// \brief Try a reference initialization that involves calling a conversion
/// function.
-static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
- const InitializedEntity &Entity,
- const InitializationKind &Kind,
- Expr *Initializer,
- bool AllowRValues,
- InitializationSequence &Sequence) {
+static OverloadingResult TryRefInitWithConversionFunction(
+ Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind,
+ Expr *Initializer, bool AllowRValues, bool IsLValueRef,
+ InitializationSequence &Sequence) {
QualType DestType = Entity.getType();
QualType cv1T1 = DestType->getAs<ReferenceType>()->getPointeeType();
QualType T1 = cv1T1.getUnqualifiedType();
@@ -4061,58 +4155,68 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
// use this initialization. Mark it as referenced.
Function->setReferenced();
- // Compute the returned type of the conversion.
+ // Compute the returned type and value kind of the conversion.
+ QualType cv3T3;
if (isa<CXXConversionDecl>(Function))
- T2 = Function->getReturnType();
+ cv3T3 = Function->getReturnType();
else
- T2 = cv1T1;
-
- // Add the user-defined conversion step.
- bool HadMultipleCandidates = (CandidateSet.size() > 1);
- Sequence.AddUserConversionStep(Function, Best->FoundDecl,
- T2.getNonLValueExprType(S.Context),
- HadMultipleCandidates);
+ cv3T3 = T1;
- // Determine whether we need to perform derived-to-base or
- // cv-qualification adjustments.
ExprValueKind VK = VK_RValue;
- if (T2->isLValueReferenceType())
+ if (cv3T3->isLValueReferenceType())
VK = VK_LValue;
- else if (const RValueReferenceType *RRef = T2->getAs<RValueReferenceType>())
+ else if (const auto *RRef = cv3T3->getAs<RValueReferenceType>())
VK = RRef->getPointeeType()->isFunctionType() ? VK_LValue : VK_XValue;
+ cv3T3 = cv3T3.getNonLValueExprType(S.Context);
+
+ // Add the user-defined conversion step.
+ bool HadMultipleCandidates = (CandidateSet.size() > 1);
+ Sequence.AddUserConversionStep(Function, Best->FoundDecl, cv3T3,
+ HadMultipleCandidates);
+ // Determine whether we'll need to perform derived-to-base adjustments or
+ // other conversions.
bool NewDerivedToBase = false;
bool NewObjCConversion = false;
bool NewObjCLifetimeConversion = false;
Sema::ReferenceCompareResult NewRefRelationship
- = S.CompareReferenceRelationship(DeclLoc, T1,
- T2.getNonLValueExprType(S.Context),
+ = S.CompareReferenceRelationship(DeclLoc, T1, cv3T3,
NewDerivedToBase, NewObjCConversion,
NewObjCLifetimeConversion);
+
+ // Add the final conversion sequence, if necessary.
if (NewRefRelationship == Sema::Ref_Incompatible) {
- // If the type we've converted to is not reference-related to the
- // type we're looking for, then there is another conversion step
- // we need to perform to produce a temporary of the right type
- // that we'll be binding to.
+ assert(!isa<CXXConstructorDecl>(Function) &&
+ "should not have conversion after constructor");
+
ImplicitConversionSequence ICS;
ICS.setStandard();
ICS.Standard = Best->FinalConversion;
- T2 = ICS.Standard.getToType(2);
- Sequence.AddConversionSequenceStep(ICS, T2);
- } else if (NewDerivedToBase)
- Sequence.AddDerivedToBaseCastStep(
- S.Context.getQualifiedType(T1,
- T2.getNonReferenceType().getQualifiers()),
- VK);
- else if (NewObjCConversion)
- Sequence.AddObjCObjectConversionStep(
- S.Context.getQualifiedType(T1,
- T2.getNonReferenceType().getQualifiers()));
+ Sequence.AddConversionSequenceStep(ICS, ICS.Standard.getToType(2));
+
+ // Every implicit conversion results in a prvalue, except for a glvalue
+ // derived-to-base conversion, which we handle below.
+ cv3T3 = ICS.Standard.getToType(2);
+ VK = VK_RValue;
+ }
- if (cv1T1.getQualifiers() != T2.getNonReferenceType().getQualifiers())
- Sequence.AddQualificationConversionStep(cv1T1, VK);
+ // If the converted initializer is a prvalue, its type T4 is adjusted to
+ // type "cv1 T4" and the temporary materialization conversion is applied.
+ //
+ // We adjust the cv-qualifications to match the reference regardless of
+ // whether we have a prvalue so that the AST records the change. In this
+ // case, T4 is "cv3 T3".
+ QualType cv1T4 = S.Context.getQualifiedType(cv3T3, cv1T1.getQualifiers());
+ if (cv1T4.getQualifiers() != cv3T3.getQualifiers())
+ Sequence.AddQualificationConversionStep(cv1T4, VK);
+ Sequence.AddReferenceBindingStep(cv1T4, VK == VK_RValue);
+ VK = IsLValueRef ? VK_LValue : VK_XValue;
+
+ if (NewDerivedToBase)
+ Sequence.AddDerivedToBaseCastStep(cv1T1, VK);
+ else if (NewObjCConversion)
+ Sequence.AddObjCObjectConversionStep(cv1T1);
- Sequence.AddReferenceBindingStep(cv1T1, !T2->isReferenceType());
return OR_Success;
}
@@ -4146,54 +4250,11 @@ static void TryReferenceInitialization(Sema &S,
T1Quals, cv2T2, T2, T2Quals, Sequence);
}
-/// Converts the target of reference initialization so that it has the
-/// appropriate qualifiers and value kind.
-///
-/// In this case, 'x' is an 'int' lvalue, but it needs to be 'const int'.
-/// \code
-/// int x;
-/// const int &r = x;
-/// \endcode
-///
-/// In this case the reference is binding to a bitfield lvalue, which isn't
-/// valid. Perform a load to create a lifetime-extended temporary instead.
-/// \code
-/// const int &r = someStruct.bitfield;
-/// \endcode
-static ExprValueKind
-convertQualifiersAndValueKindIfNecessary(Sema &S,
- InitializationSequence &Sequence,
- Expr *Initializer,
- QualType cv1T1,
- Qualifiers T1Quals,
- Qualifiers T2Quals,
- bool IsLValueRef) {
- bool IsNonAddressableType = Initializer->refersToBitField() ||
- Initializer->refersToVectorElement();
-
- if (IsNonAddressableType) {
- // C++11 [dcl.init.ref]p5: [...] Otherwise, the reference shall be an
- // lvalue reference to a non-volatile const type, or the reference shall be
- // an rvalue reference.
- //
- // If not, we can't make a temporary and bind to that. Give up and allow the
- // error to be diagnosed later.
- if (IsLValueRef && (!T1Quals.hasConst() || T1Quals.hasVolatile())) {
- assert(Initializer->isGLValue());
- return Initializer->getValueKind();
- }
-
- // Force a load so we can materialize a temporary.
- Sequence.AddLValueToRValueStep(cv1T1.getUnqualifiedType());
- return VK_RValue;
- }
-
- if (T1Quals != T2Quals) {
- Sequence.AddQualificationConversionStep(cv1T1,
- Initializer->getValueKind());
- }
-
- return Initializer->getValueKind();
+/// Determine whether an expression is a non-referenceable glvalue (one to
+/// which a reference can never bind). Attemting 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.
@@ -4231,31 +4292,28 @@ static void TryReferenceInitializationCore(Sema &S,
OverloadingResult ConvOvlResult = OR_Success;
bool T1Function = T1->isFunctionType();
if (isLValueRef || T1Function) {
- if (InitCategory.isLValue() &&
- (RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification ||
+ if (InitCategory.isLValue() && !isNonReferenceableGLValue(Initializer) &&
+ (RefRelationship == Sema::Ref_Compatible ||
(Kind.isCStyleOrFunctionalCast() &&
RefRelationship == Sema::Ref_Related))) {
// - is an lvalue (but is not a bit-field), and "cv1 T1" is
// reference-compatible with "cv2 T2," or
- //
- // Per C++ [over.best.ics]p2, we don't diagnose whether the lvalue is a
- // bit-field when we're determining whether the reference initialization
- // can occur. However, we do pay attention to whether it is a bit-field
- // to decide whether we're actually binding to a temporary created from
- // the bit-field.
+ if (T1Quals != T2Quals)
+ // Convert to cv1 T2. This should only add qualifiers unless this is a
+ // c-style cast. The removal of qualifiers in that case notionally
+ // happens after the reference binding, but that doesn't matter.
+ Sequence.AddQualificationConversionStep(
+ S.Context.getQualifiedType(T2, T1Quals),
+ Initializer->getValueKind());
if (DerivedToBase)
- Sequence.AddDerivedToBaseCastStep(
- S.Context.getQualifiedType(T1, T2Quals),
- VK_LValue);
+ Sequence.AddDerivedToBaseCastStep(cv1T1, VK_LValue);
else if (ObjCConversion)
- Sequence.AddObjCObjectConversionStep(
- S.Context.getQualifiedType(T1, T2Quals));
-
- ExprValueKind ValueKind =
- convertQualifiersAndValueKindIfNecessary(S, Sequence, Initializer,
- cv1T1, T1Quals, T2Quals,
- isLValueRef);
- Sequence.AddReferenceBindingStep(cv1T1, ValueKind == VK_RValue);
+ Sequence.AddObjCObjectConversionStep(cv1T1);
+
+ // We only create a temporary here when binding a reference to a
+ // bit-field or vector element. Those cases are't supposed to be
+ // handled by this bullet, but the outcome is the same either way.
+ Sequence.AddReferenceBindingStep(cv1T1, false);
return;
}
@@ -4270,7 +4328,8 @@ static void TryReferenceInitializationCore(Sema &S,
if (RefRelationship == Sema::Ref_Incompatible && T2->isRecordType() &&
(isLValueRef || InitCategory.isRValue())) {
ConvOvlResult = TryRefInitWithConversionFunction(
- S, Entity, Kind, Initializer, /*AllowRValues*/isRValueRef, Sequence);
+ S, Entity, Kind, Initializer, /*AllowRValues*/ isRValueRef,
+ /*IsLValueRef*/ isLValueRef, Sequence);
if (ConvOvlResult == OR_Success)
return;
if (ConvOvlResult != OR_No_Viable_Function)
@@ -4290,28 +4349,51 @@ static void TryReferenceInitializationCore(Sema &S,
Sequence.SetOverloadFailure(
InitializationSequence::FK_ReferenceInitOverloadFailed,
ConvOvlResult);
- else
- Sequence.SetFailed(InitCategory.isLValue()
- ? (RefRelationship == Sema::Ref_Related
- ? InitializationSequence::FK_ReferenceInitDropsQualifiers
- : InitializationSequence::FK_NonConstLValueReferenceBindingToUnrelated)
- : InitializationSequence::FK_NonConstLValueReferenceBindingToTemporary);
-
+ else if (!InitCategory.isLValue())
+ Sequence.SetFailed(
+ InitializationSequence::FK_NonConstLValueReferenceBindingToTemporary);
+ else {
+ InitializationSequence::FailureKind FK;
+ switch (RefRelationship) {
+ case Sema::Ref_Compatible:
+ if (Initializer->refersToBitField())
+ FK = InitializationSequence::
+ FK_NonConstLValueReferenceBindingToBitfield;
+ else if (Initializer->refersToVectorElement())
+ FK = InitializationSequence::
+ FK_NonConstLValueReferenceBindingToVectorElement;
+ else
+ llvm_unreachable("unexpected kind of compatible initializer");
+ break;
+ case Sema::Ref_Related:
+ FK = InitializationSequence::FK_ReferenceInitDropsQualifiers;
+ break;
+ case Sema::Ref_Incompatible:
+ FK = InitializationSequence::
+ FK_NonConstLValueReferenceBindingToUnrelated;
+ break;
+ }
+ Sequence.SetFailed(FK);
+ }
return;
}
// - If the initializer expression
- // - is an xvalue, class prvalue, array prvalue, or function lvalue and
- // "cv1 T1" is reference-compatible with "cv2 T2"
- // Note: functions are handled below.
+ // - is an
+ // [<=14] xvalue (but not a bit-field), class prvalue, array prvalue, or
+ // [1z] rvalue (but not a bit-field) or
+ // function lvalue and "cv1 T1" is reference-compatible with "cv2 T2"
+ //
+ // Note: functions are handled above and below rather than here...
if (!T1Function &&
- (RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification ||
+ (RefRelationship == Sema::Ref_Compatible ||
(Kind.isCStyleOrFunctionalCast() &&
RefRelationship == Sema::Ref_Related)) &&
- (InitCategory.isXValue() ||
- (InitCategory.isPRValue() && T2->isRecordType()) ||
- (InitCategory.isPRValue() && T2->isArrayType()))) {
- ExprValueKind ValueKind = InitCategory.isXValue()? VK_XValue : VK_RValue;
+ ((InitCategory.isXValue() && !isNonReferenceableGLValue(Initializer)) ||
+ (InitCategory.isPRValue() &&
+ (S.getLangOpts().CPlusPlus1z || T2->isRecordType() ||
+ T2->isArrayType())))) {
+ ExprValueKind ValueKind = InitCategory.isXValue() ? VK_XValue : VK_RValue;
if (InitCategory.isPRValue() && T2->isRecordType()) {
// The corresponding bullet in C++03 [dcl.init.ref]p5 gives the
// compiler the freedom to perform a copy here or bind to the
@@ -4328,19 +4410,22 @@ static void TryReferenceInitializationCore(Sema &S,
CheckCXX98CompatAccessibleCopy(S, Entity, Initializer);
}
+ // C++1z [dcl.init.ref]/5.2.1.2:
+ // If the converted initializer is a prvalue, its type T4 is adjusted
+ // to type "cv1 T4" and the temporary materialization conversion is
+ // applied.
+ QualType cv1T4 = S.Context.getQualifiedType(cv2T2, T1Quals);
+ if (T1Quals != T2Quals)
+ Sequence.AddQualificationConversionStep(cv1T4, ValueKind);
+ Sequence.AddReferenceBindingStep(cv1T4, ValueKind == VK_RValue);
+ ValueKind = isLValueRef ? VK_LValue : VK_XValue;
+
+ // In any case, the reference is bound to the resulting glvalue (or to
+ // an appropriate base class subobject).
if (DerivedToBase)
- Sequence.AddDerivedToBaseCastStep(S.Context.getQualifiedType(T1, T2Quals),
- ValueKind);
+ Sequence.AddDerivedToBaseCastStep(cv1T1, ValueKind);
else if (ObjCConversion)
- Sequence.AddObjCObjectConversionStep(
- S.Context.getQualifiedType(T1, T2Quals));
-
- ValueKind = convertQualifiersAndValueKindIfNecessary(S, Sequence,
- Initializer, cv1T1,
- T1Quals, T2Quals,
- isLValueRef);
-
- Sequence.AddReferenceBindingStep(cv1T1, ValueKind == VK_RValue);
+ Sequence.AddObjCObjectConversionStep(cv1T1);
return;
}
@@ -4353,7 +4438,8 @@ static void TryReferenceInitializationCore(Sema &S,
if (T2->isRecordType()) {
if (RefRelationship == Sema::Ref_Incompatible) {
ConvOvlResult = TryRefInitWithConversionFunction(
- S, Entity, Kind, Initializer, /*AllowRValues*/true, Sequence);
+ S, Entity, Kind, Initializer, /*AllowRValues*/ true,
+ /*IsLValueRef*/ isLValueRef, Sequence);
if (ConvOvlResult)
Sequence.SetOverloadFailure(
InitializationSequence::FK_ReferenceInitOverloadFailed,
@@ -4362,8 +4448,7 @@ static void TryReferenceInitializationCore(Sema &S,
return;
}
- if ((RefRelationship == Sema::Ref_Compatible ||
- RefRelationship == Sema::Ref_Compatible_With_Added_Qualification) &&
+ if (RefRelationship == Sema::Ref_Compatible &&
isRValueRef && InitCategory.isLValue()) {
Sequence.SetFailed(
InitializationSequence::FK_RValueReferenceBindingToLValue);
@@ -4462,23 +4547,21 @@ static void TryValueInitialization(Sema &S,
if (const RecordType *RT = T->getAs<RecordType>()) {
if (CXXRecordDecl *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
bool NeedZeroInitialization = true;
- if (!S.getLangOpts().CPlusPlus11) {
- // C++98:
- // -- if T is a class type (clause 9) with a user-declared constructor
- // (12.1), then the default constructor for T is called (and the
- // initialization is ill-formed if T has no accessible default
- // constructor);
- if (ClassDecl->hasUserDeclaredConstructor())
- NeedZeroInitialization = false;
- } else {
- // C++11:
- // -- if T is a class type (clause 9) with either no default constructor
- // (12.1 [class.ctor]) or a default constructor that is user-provided
- // or deleted, then the object is default-initialized;
- CXXConstructorDecl *CD = S.LookupDefaultConstructor(ClassDecl);
- if (!CD || !CD->getCanonicalDecl()->isDefaulted() || CD->isDeleted())
- NeedZeroInitialization = false;
- }
+ // C++98:
+ // -- if T is a class type (clause 9) with a user-declared constructor
+ // (12.1), then the default constructor for T is called (and the
+ // initialization is ill-formed if T has no accessible default
+ // constructor);
+ // C++11:
+ // -- if T is a class type (clause 9) with either no default constructor
+ // (12.1 [class.ctor]) or a default constructor that is user-provided
+ // or deleted, then the object is default-initialized;
+ //
+ // Note that the C++11 rule is the same as the C++98 rule if there are no
+ // defaulted or deleted constructors, so we just use it unconditionally.
+ CXXConstructorDecl *CD = S.LookupDefaultConstructor(ClassDecl);
+ if (!CD || !CD->getCanonicalDecl()->isDefaulted() || CD->isDeleted())
+ NeedZeroInitialization = false;
// -- if T is a (possibly cv-qualified) non-union class type without a
// user-provided or deleted default constructor, then the object is
@@ -4512,8 +4595,10 @@ static void TryValueInitialization(Sema &S,
MultiExprArg Args(&InitListAsExpr, InitList ? 1 : 0);
bool InitListSyntax = InitList;
- return TryConstructorInitialization(S, Entity, Kind, Args, T, Sequence,
- InitListSyntax);
+ // FIXME: Instead of creating a CXXConstructExpr of array type here,
+ // wrap a class-typed CXXConstructExpr in an ArrayInitLoopExpr.
+ return TryConstructorInitialization(
+ S, Entity, Kind, Args, T, Entity.getType(), Sequence, InitListSyntax);
}
}
@@ -4536,7 +4621,8 @@ static void TryDefaultInitialization(Sema &S,
// constructor for T is called (and the initialization is ill-formed if
// T has no accessible default constructor);
if (DestType->isRecordType() && S.getLangOpts().CPlusPlus) {
- TryConstructorInitialization(S, Entity, Kind, None, DestType, Sequence);
+ TryConstructorInitialization(S, Entity, Kind, None, DestType,
+ Entity.getType(), Sequence);
return;
}
@@ -4680,26 +4766,55 @@ static void TryUserDefinedConversion(Sema &S,
Sequence.AddUserConversionStep(Function, Best->FoundDecl,
DestType.getUnqualifiedType(),
HadMultipleCandidates);
+
+ // C++14 and before:
+ // - if the function is a constructor, the call initializes a temporary
+ // of the cv-unqualified version of the destination type. The [...]
+ // temporary [...] is then used to direct-initialize, according to the
+ // rules above, the object that is the destination of the
+ // copy-initialization.
+ // Note that this just performs a simple object copy from the temporary.
+ //
+ // C++1z:
+ // - if the function is a constructor, the call is a prvalue of the
+ // cv-unqualified version of the destination type whose return object
+ // is initialized by the constructor. The call is used to
+ // direct-initialize, according to the rules above, the object that
+ // is the destination of the copy-initialization.
+ // Therefore we need to do nothing further.
+ //
+ // FIXME: Mark this copy as extraneous.
+ if (!S.getLangOpts().CPlusPlus1z)
+ Sequence.AddFinalCopy(DestType);
+ else if (DestType.hasQualifiers())
+ Sequence.AddQualificationConversionStep(DestType, VK_RValue);
return;
}
// Add the user-defined conversion step that calls the conversion function.
QualType ConvType = Function->getCallResultType();
+ Sequence.AddUserConversionStep(Function, Best->FoundDecl, ConvType,
+ HadMultipleCandidates);
+
if (ConvType->getAs<RecordType>()) {
- // If we're converting to a class type, there may be an copy of
- // the resulting temporary object (possible to create an object of
- // a base class type). That copy is not a separate conversion, so
- // we just make a note of the actual destination type (possibly a
- // base class of the type returned by the conversion function) and
- // let the user-defined conversion step handle the conversion.
- Sequence.AddUserConversionStep(Function, Best->FoundDecl, DestType,
- HadMultipleCandidates);
+ // The call is used to direct-initialize [...] the object that is the
+ // destination of the copy-initialization.
+ //
+ // In C++1z, this does not call a constructor if we enter /17.6.1:
+ // - If the initializer expression is a prvalue and the cv-unqualified
+ // version of the source type is the same as the class of the
+ // destination [... do not make an extra copy]
+ //
+ // FIXME: Mark this copy as extraneous.
+ if (!S.getLangOpts().CPlusPlus1z ||
+ Function->getReturnType()->isReferenceType() ||
+ !S.Context.hasSameUnqualifiedType(ConvType, DestType))
+ Sequence.AddFinalCopy(DestType);
+ else if (!S.Context.hasSameType(ConvType, DestType))
+ Sequence.AddQualificationConversionStep(DestType, VK_RValue);
return;
}
- Sequence.AddUserConversionStep(Function, Best->FoundDecl, ConvType,
- HadMultipleCandidates);
-
// If the conversion following the call to the conversion function
// is interesting, add it as a separate step.
if (Best->FinalConversion.First || Best->FinalConversion.Second ||
@@ -4886,7 +5001,8 @@ static bool TryOCLSamplerInitialization(Sema &S,
QualType DestType,
Expr *Initializer) {
if (!S.getLangOpts().OpenCL || !DestType->isSamplerT() ||
- !Initializer->isIntegerConstantExpr(S.getASTContext()))
+ (!Initializer->isIntegerConstantExpr(S.Context) &&
+ !Initializer->getType()->isSamplerT()))
return false;
Sequence.AddOCLSamplerInitStep(DestType);
@@ -4914,6 +5030,20 @@ static bool TryOCLZeroEventInitialization(Sema &S,
return true;
}
+static bool TryOCLZeroQueueInitialization(Sema &S,
+ InitializationSequence &Sequence,
+ QualType DestType,
+ Expr *Initializer) {
+ if (!S.getLangOpts().OpenCL || S.getLangOpts().OpenCLVersion < 200 ||
+ !DestType->isQueueT() ||
+ !Initializer->isIntegerConstantExpr(S.getASTContext()) ||
+ (Initializer->EvaluateKnownConstInt(S.getASTContext()) != 0))
+ return false;
+
+ Sequence.AddOCLZeroQueueStep(DestType);
+ return true;
+}
+
InitializationSequence::InitializationSequence(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
@@ -4936,6 +5066,42 @@ static bool isExprAnUnaddressableFunction(Sema &S, const Expr *E) {
cast<FunctionDecl>(DRE->getDecl()));
}
+/// Determine whether we can perform an elementwise array copy for this kind
+/// of entity.
+static bool canPerformArrayCopy(const InitializedEntity &Entity) {
+ switch (Entity.getKind()) {
+ case InitializedEntity::EK_LambdaCapture:
+ // C++ [expr.prim.lambda]p24:
+ // For array members, the array elements are direct-initialized in
+ // increasing subscript order.
+ return true;
+
+ case InitializedEntity::EK_Variable:
+ // C++ [dcl.decomp]p1:
+ // [...] each element is copy-initialized or direct-initialized from the
+ // corresponding element of the assignment-expression [...]
+ return isa<DecompositionDecl>(Entity.getDecl());
+
+ case InitializedEntity::EK_Member:
+ // C++ [class.copy.ctor]p14:
+ // - if the member is an array, each element is direct-initialized with
+ // the corresponding subobject of x
+ return Entity.isImplicitMemberInitializer();
+
+ case InitializedEntity::EK_ArrayElement:
+ // All the above cases are intended to apply recursively, even though none
+ // of them actually say that.
+ if (auto *E = Entity.getParent())
+ return canPerformArrayCopy(*E);
+ break;
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
void InitializationSequence::InitializeFrom(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
@@ -5058,6 +5224,34 @@ void InitializationSequence::InitializeFrom(Sema &S,
}
}
+ // Some kinds of initialization permit an array to be initialized from
+ // another array of the same type, and perform elementwise initialization.
+ if (Initializer && isa<ConstantArrayType>(DestAT) &&
+ S.Context.hasSameUnqualifiedType(Initializer->getType(),
+ Entity.getType()) &&
+ canPerformArrayCopy(Entity)) {
+ // If source is a prvalue, use it directly.
+ if (Initializer->getValueKind() == VK_RValue) {
+ AddArrayInitStep(DestType, /*IsGNUExtension*/false);
+ return;
+ }
+
+ // Emit element-at-a-time copy loop.
+ InitializedEntity Element =
+ InitializedEntity::InitializeElement(S.Context, 0, Entity);
+ QualType InitEltT =
+ Context.getAsArrayType(Initializer->getType())->getElementType();
+ OpaqueValueExpr OVE(Initializer->getExprLoc(), InitEltT,
+ Initializer->getValueKind(),
+ Initializer->getObjectKind());
+ Expr *OVEAsExpr = &OVE;
+ InitializeFrom(S, Element, Kind, OVEAsExpr, TopLevelOfInitList,
+ TreatUnavailableAsInvalid);
+ if (!Failed())
+ AddArrayInitLoopStep(Entity.getType(), InitEltT);
+ return;
+ }
+
// Note: as an GNU C extension, we allow initialization of an
// array from a compound literal that creates an array of the same
// type, so long as the initializer has no side effects.
@@ -5071,7 +5265,7 @@ void InitializationSequence::InitializeFrom(Sema &S,
else if (Initializer->HasSideEffects(S.Context))
SetFailed(FK_NonConstantArrayInit);
else {
- AddArrayInitStep(DestType);
+ AddArrayInitStep(DestType, /*IsGNUExtension*/true);
}
}
// Note: as a GNU C++ extension, we allow list-initialization of a
@@ -5112,6 +5306,9 @@ void InitializationSequence::InitializeFrom(Sema &S,
if (TryOCLZeroEventInitialization(S, *this, DestType, Initializer))
return;
+ if (TryOCLZeroQueueInitialization(S, *this, DestType, Initializer))
+ return;
+
// Handle initialization in C
AddCAssignmentStep(DestType);
MaybeProduceObjCObject(S, *this, Entity);
@@ -5131,7 +5328,7 @@ void InitializationSequence::InitializeFrom(Sema &S,
(Context.hasSameUnqualifiedType(SourceType, DestType) ||
S.IsDerivedFrom(Initializer->getLocStart(), SourceType, DestType))))
TryConstructorInitialization(S, Entity, Kind, Args,
- DestType, *this);
+ DestType, DestType, *this);
// - Otherwise (i.e., for the remaining copy-initialization cases),
// user-defined conversion sequences that can convert from the source
// type to the destination type or (when a conversion function is
@@ -5270,6 +5467,7 @@ getAssignmentAction(const InitializedEntity &Entity, bool Diagnose = false) {
return Sema::AA_Casting;
case InitializedEntity::EK_Member:
+ case InitializedEntity::EK_Binding:
case InitializedEntity::EK_ArrayElement:
case InitializedEntity::EK_VectorElement:
case InitializedEntity::EK_ComplexElement:
@@ -5305,6 +5503,7 @@ static bool shouldBindAsTemporary(const InitializedEntity &Entity) {
case InitializedEntity::EK_Parameter_CF_Audited:
case InitializedEntity::EK_Temporary:
case InitializedEntity::EK_RelatedResult:
+ case InitializedEntity::EK_Binding:
return true;
}
@@ -5313,7 +5512,7 @@ static bool shouldBindAsTemporary(const InitializedEntity &Entity) {
/// \brief Whether the given entity, when initialized with an object
/// created for that initialization, requires destruction.
-static bool shouldDestroyTemporary(const InitializedEntity &Entity) {
+static bool shouldDestroyEntity(const InitializedEntity &Entity) {
switch (Entity.getKind()) {
case InitializedEntity::EK_Result:
case InitializedEntity::EK_New:
@@ -5326,6 +5525,7 @@ static bool shouldDestroyTemporary(const InitializedEntity &Entity) {
return false;
case InitializedEntity::EK_Member:
+ case InitializedEntity::EK_Binding:
case InitializedEntity::EK_Variable:
case InitializedEntity::EK_Parameter:
case InitializedEntity::EK_Parameter_CF_Audited:
@@ -5340,50 +5540,6 @@ static bool shouldDestroyTemporary(const InitializedEntity &Entity) {
llvm_unreachable("missed an InitializedEntity kind?");
}
-/// \brief Look for copy and move constructors and constructor templates, for
-/// copying an object via direct-initialization (per C++11 [dcl.init]p16).
-static void LookupCopyAndMoveConstructors(Sema &S,
- OverloadCandidateSet &CandidateSet,
- CXXRecordDecl *Class,
- Expr *CurInitExpr) {
- DeclContext::lookup_result R = S.LookupConstructors(Class);
- // The container holding the constructors can under certain conditions
- // be changed while iterating (e.g. because of deserialization).
- // To be safe we copy the lookup results to a new container.
- SmallVector<NamedDecl*, 16> Ctors(R.begin(), R.end());
- for (SmallVectorImpl<NamedDecl *>::iterator
- CI = Ctors.begin(), CE = Ctors.end(); CI != CE; ++CI) {
- NamedDecl *D = *CI;
- auto Info = getConstructorInfo(D);
- if (!Info.Constructor)
- continue;
-
- if (!Info.ConstructorTmpl) {
- // Handle copy/move constructors, only.
- if (Info.Constructor->isInvalidDecl() ||
- !Info.Constructor->isCopyOrMoveConstructor() ||
- !Info.Constructor->isConvertingConstructor(/*AllowExplicit=*/true))
- continue;
-
- S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl,
- CurInitExpr, CandidateSet);
- continue;
- }
-
- // Handle constructor templates.
- if (Info.ConstructorTmpl->isInvalidDecl())
- continue;
-
- if (!Info.Constructor->isConvertingConstructor(/*AllowExplicit=*/true))
- continue;
-
- // FIXME: Do we need to limit this to copy-constructor-like
- // candidates?
- S.AddTemplateOverloadCandidate(Info.ConstructorTmpl, Info.FoundDecl,
- nullptr, CurInitExpr, CandidateSet, true);
- }
-}
-
/// \brief Get the location at which initialization diagnostics should appear.
static SourceLocation getInitializationLoc(const InitializedEntity &Entity,
Expr *Initializer) {
@@ -5395,6 +5551,7 @@ static SourceLocation getInitializationLoc(const InitializedEntity &Entity,
return Entity.getThrowLoc();
case InitializedEntity::EK_Variable:
+ case InitializedEntity::EK_Binding:
return Entity.getDecl()->getLocation();
case InitializedEntity::EK_LambdaCapture:
@@ -5453,39 +5610,24 @@ static ExprResult CopyObject(Sema &S,
if (!Class)
return CurInit;
- // C++0x [class.copy]p32:
- // When certain criteria are met, an implementation is allowed to
- // omit the copy/move construction of a class object, even if the
- // copy/move constructor and/or destructor for the object have
- // side effects. [...]
- // - when a temporary class object that has not been bound to a
- // reference (12.2) would be copied/moved to a class object
- // with the same cv-unqualified type, the copy/move operation
- // can be omitted by constructing the temporary object
- // directly into the target of the omitted copy/move
- //
- // Note that the other three bullets are handled elsewhere. Copy
- // elision for return statements and throw expressions are handled as part
- // of constructor initialization, while copy elision for exception handlers
- // is handled by the run-time.
- bool Elidable = CurInitExpr->isTemporaryObject(S.Context, Class);
SourceLocation Loc = getInitializationLoc(Entity, CurInit.get());
// Make sure that the type we are copying is complete.
if (S.RequireCompleteType(Loc, T, diag::err_temp_copy_incomplete))
return CurInit;
- // Perform overload resolution using the class's copy/move constructors.
- // Only consider constructors and constructor templates. Per
- // C++0x [dcl.init]p16, second bullet to class types, this initialization
+ // Perform overload resolution using the class's constructors. Per
+ // C++11 [dcl.init]p16, second bullet for class types, this initialization
// is direct-initialization.
OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
- LookupCopyAndMoveConstructors(S, CandidateSet, Class, CurInitExpr);
-
- bool HadMultipleCandidates = (CandidateSet.size() > 1);
+ DeclContext::lookup_result Ctors = S.LookupConstructors(Class);
OverloadCandidateSet::iterator Best;
- switch (CandidateSet.BestViableFunction(S, Loc, Best)) {
+ switch (ResolveConstructorOverload(
+ S, Loc, CurInitExpr, CandidateSet, Ctors, Best,
+ /*CopyInitializing=*/false, /*AllowExplicit=*/true,
+ /*OnlyListConstructors=*/false, /*IsListInit=*/false,
+ /*SecondStepOfCopyInit=*/true)) {
case OR_Success:
break;
@@ -5515,6 +5657,8 @@ static ExprResult CopyObject(Sema &S,
return ExprError();
}
+ bool HadMultipleCandidates = CandidateSet.size() > 1;
+
CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(Best->Function);
SmallVector<Expr*, 8> ConstructorArgs;
CurInit.get(); // Ownership transferred into MultiExprArg, below.
@@ -5554,6 +5698,31 @@ static ExprResult CopyObject(Sema &S,
if (S.CompleteConstructorCall(Constructor, CurInitExpr, Loc, ConstructorArgs))
return ExprError();
+ // C++0x [class.copy]p32:
+ // When certain criteria are met, an implementation is allowed to
+ // omit the copy/move construction of a class object, even if the
+ // copy/move constructor and/or destructor for the object have
+ // side effects. [...]
+ // - when a temporary class object that has not been bound to a
+ // reference (12.2) would be copied/moved to a class object
+ // with the same cv-unqualified type, the copy/move operation
+ // can be omitted by constructing the temporary object
+ // directly into the target of the omitted copy/move
+ //
+ // Note that the other three bullets are handled elsewhere. Copy
+ // elision for return statements and throw expressions are handled as part
+ // of constructor initialization, while copy elision for exception handlers
+ // is handled by the run-time.
+ //
+ // FIXME: If the function parameter is not the same type as the temporary, we
+ // should still be able to elide the copy, but we don't have a way to
+ // represent in the AST how much should be elided in this case.
+ bool Elidable =
+ CurInitExpr->isTemporaryObject(S.Context, Class) &&
+ S.Context.hasSameUnqualifiedType(
+ Best->Function->getParamDecl(0)->getType().getNonReferenceType(),
+ CurInitExpr->getType());
+
// Actually perform the constructor call.
CurInit = S.BuildCXXConstructExpr(Loc, T, Best->FoundDecl, Constructor,
Elidable,
@@ -5589,12 +5758,16 @@ static void CheckCXX98CompatAccessibleCopy(Sema &S,
// Find constructors which would have been considered.
OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
- LookupCopyAndMoveConstructors(
- S, CandidateSet, cast<CXXRecordDecl>(Record->getDecl()), CurInitExpr);
+ DeclContext::lookup_result Ctors =
+ S.LookupConstructors(cast<CXXRecordDecl>(Record->getDecl()));
// Perform overload resolution.
OverloadCandidateSet::iterator Best;
- OverloadingResult OR = CandidateSet.BestViableFunction(S, Loc, Best);
+ OverloadingResult OR = ResolveConstructorOverload(
+ S, Loc, CurInitExpr, CandidateSet, Ctors, Best,
+ /*CopyInitializing=*/false, /*AllowExplicit=*/true,
+ /*OnlyListConstructors=*/false, /*IsListInit=*/false,
+ /*SecondStepOfCopyInit=*/true);
PartialDiagnostic Diag = S.PDiag(diag::warn_cxx98_compat_temp_copy)
<< OR << (int)Entity.getKind() << CurInitExpr->getType()
@@ -5643,11 +5816,6 @@ void InitializationSequence::PrintInitLocationNote(Sema &S,
<< Entity.getMethodDecl()->getDeclName();
}
-static bool isReferenceBinding(const InitializationSequence::Step &s) {
- return s.Kind == InitializationSequence::SK_BindReference ||
- s.Kind == InitializationSequence::SK_BindReferenceToTemporary;
-}
-
/// Returns true if the parameters describe a constructor initialization of
/// an explicit temporary object, e.g. "Point(x, y)".
static bool isExplicitTemporary(const InitializedEntity &Entity,
@@ -5714,9 +5882,10 @@ PerformConstructorInitialization(Sema &S,
// T as its first argument, called with a single argument in the
// context of direct-initialization, explicit conversion functions
// are also considered.
- bool AllowExplicitConv = Kind.AllowExplicit() && !Kind.isCopyInit() &&
- Args.size() == 1 &&
- Constructor->isCopyOrMoveConstructor();
+ bool AllowExplicitConv =
+ Kind.AllowExplicit() && !Kind.isCopyInit() && Args.size() == 1 &&
+ hasCopyOrMoveCtorParam(S.Context,
+ getConstructorInfo(Step.Function.FoundDecl));
// Determine the arguments required to actually perform the constructor
// call.
@@ -5776,7 +5945,7 @@ PerformConstructorInitialization(Sema &S,
// If the entity allows NRVO, mark the construction as elidable
// unconditionally.
if (Entity.allowsNRVO())
- CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(),
+ CurInit = S.BuildCXXConstructExpr(Loc, Step.Type,
Step.Function.FoundDecl,
Constructor, /*Elidable=*/true,
ConstructorArgs,
@@ -5787,7 +5956,7 @@ PerformConstructorInitialization(Sema &S,
ConstructKind,
ParenOrBraceRange);
else
- CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(),
+ CurInit = S.BuildCXXConstructExpr(Loc, Step.Type,
Step.Function.FoundDecl,
Constructor,
ConstructorArgs,
@@ -5826,6 +5995,7 @@ InitializedEntityOutlivesFullExpression(const InitializedEntity &Entity) {
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:
@@ -5875,6 +6045,11 @@ static const InitializedEntity *getEntityForTemporaryLifetimeExtension(
// ctor-initializer persists until the constructor exits.
return Entity;
+ case InitializedEntity::EK_Binding:
+ // Per [dcl.decomp]p3, the binding is treated as a variable of reference
+ // type.
+ return Entity;
+
case InitializedEntity::EK_Parameter:
case InitializedEntity::EK_Parameter_CF_Audited:
// -- A temporary bound to a reference parameter in a function call
@@ -5949,10 +6124,7 @@ performReferenceExtension(Expr *Init,
// Step over any subobject adjustments; we may have a materialized
// temporary inside them.
- SmallVector<const Expr *, 2> CommaLHSs;
- SmallVector<SubobjectAdjustment, 2> Adjustments;
- Init = const_cast<Expr *>(
- Init->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments));
+ Init = const_cast<Expr *>(Init->skipRValueSubobjectAdjustments());
// Per current approach for DR1376, look through casts to reference type
// when performing lifetime extension.
@@ -5960,9 +6132,10 @@ performReferenceExtension(Expr *Init,
if (CE->getSubExpr()->isGLValue())
Init = CE->getSubExpr();
- // FIXME: Per DR1213, subscripting on an array temporary produces an xvalue.
- // It's unclear if binding a reference to that xvalue extends the array
- // temporary.
+ // Per the current approach for DR1299, look through array element access
+ // when performing lifetime extension.
+ if (auto *ASE = dyn_cast<ArraySubscriptExpr>(Init))
+ Init = ASE->getBase();
} while (Init != Old);
if (MaterializeTemporaryExpr *ME = dyn_cast<MaterializeTemporaryExpr>(Init)) {
@@ -5982,10 +6155,7 @@ performReferenceExtension(Expr *Init,
static void performLifetimeExtension(Expr *Init,
const InitializedEntity *ExtendingEntity) {
// Dig out the expression which constructs the extended temporary.
- SmallVector<const Expr *, 2> CommaLHSs;
- SmallVector<SubobjectAdjustment, 2> Adjustments;
- Init = const_cast<Expr *>(
- Init->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments));
+ Init = const_cast<Expr *>(Init->skipRValueSubobjectAdjustments());
if (CXXBindTemporaryExpr *BTE = dyn_cast<CXXBindTemporaryExpr>(Init))
Init = BTE->getSubExpr();
@@ -6204,6 +6374,24 @@ Sema::CreateMaterializeTemporaryExpr(QualType T, Expr *Temporary,
return MTE;
}
+ExprResult Sema::TemporaryMaterializationConversion(Expr *E) {
+ // In C++98, we don't want to implicitly create an xvalue.
+ // FIXME: This means that AST consumers need to deal with "prvalues" that
+ // denote materialized temporaries. Maybe we should add another ValueKind
+ // for "xvalue pretending to be a prvalue" for C++98 support.
+ if (!E->isRValue() || !getLangOpts().CPlusPlus11)
+ return E;
+
+ // C++1z [conv.rval]/1: T shall be a complete type.
+ // FIXME: Does this ever matter (can we form a prvalue of incomplete type)?
+ // If so, we should check for a non-abstract class type here too.
+ QualType T = E->getType();
+ if (RequireCompleteType(E->getExprLoc(), T, diag::err_incomplete_type))
+ return ExprError();
+
+ return CreateMaterializeTemporaryExpr(E->getType(), E, false);
+}
+
ExprResult
InitializationSequence::Perform(Sema &S,
const InitializedEntity &Entity,
@@ -6250,7 +6438,7 @@ InitializationSequence::Perform(Sema &S,
SourceRange Brackets;
// Scavange the location of the brackets from the entity, if we can.
- if (DeclaratorDecl *DD = Entity.getDecl()) {
+ if (auto *DD = dyn_cast_or_null<DeclaratorDecl>(Entity.getDecl())) {
if (TypeSourceInfo *TInfo = DD->getTypeSourceInfo()) {
TypeLoc TL = TInfo->getTypeLoc();
if (IncompleteArrayTypeLoc ArrayLoc =
@@ -6302,7 +6490,9 @@ InitializationSequence::Perform(Sema &S,
if (Args.size() == 1 && Args[0]->getType()->isArrayType() &&
Entity.getType()->isPointerType() &&
InitializedEntityOutlivesFullExpression(Entity)) {
- Expr *Init = Args[0];
+ 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)
@@ -6318,6 +6508,7 @@ InitializationSequence::Perform(Sema &S,
Entity.getType();
ExprResult CurInit((Expr *)nullptr);
+ SmallVector<Expr*, 4> ArrayLoopCommonExprs;
// For initialization steps that start with a single initializer,
// grab the only argument out the Args and place it into the "current"
@@ -6329,6 +6520,7 @@ InitializationSequence::Perform(Sema &S,
case SK_CastDerivedToBaseLValue:
case SK_BindReference:
case SK_BindReferenceToTemporary:
+ case SK_FinalCopy:
case SK_ExtraneousCopyToTemporary:
case SK_UserConversion:
case SK_QualificationConversionLValue:
@@ -6344,14 +6536,18 @@ InitializationSequence::Perform(Sema &S,
case SK_CAssignment:
case SK_StringInit:
case SK_ObjCObjectConversion:
+ case SK_ArrayLoopIndex:
+ case SK_ArrayLoopInit:
case SK_ArrayInit:
+ case SK_GNUArrayInit:
case SK_ParenthesizedArrayInit:
case SK_PassByIndirectCopyRestore:
case SK_PassByIndirectRestore:
case SK_ProduceObjCObject:
case SK_StdInitializerList:
case SK_OCLSamplerInit:
- case SK_OCLZeroEvent: {
+ case SK_OCLZeroEvent:
+ case SK_OCLZeroQueue: {
assert(Args.size() == 1);
CurInit = Args[0];
if (!CurInit.get()) return ExprError();
@@ -6365,6 +6561,17 @@ InitializationSequence::Perform(Sema &S,
break;
}
+ // C++ [class.abstract]p2:
+ // no objects of an abstract class can be created except as subobjects
+ // of a class derived from it
+ auto checkAbstractType = [&](QualType T) -> bool {
+ if (Entity.getKind() == InitializedEntity::EK_Base ||
+ Entity.getKind() == InitializedEntity::EK_Delegating)
+ return false;
+ return S.RequireNonAbstractType(Kind.getLocation(), T,
+ diag::err_allocation_of_abstract_type);
+ };
+
// Walk through the computed steps for the initialization sequence,
// performing the specified conversions along the way.
bool ConstructorInitRequiresZeroInit = false;
@@ -6416,30 +6623,6 @@ InitializationSequence::Perform(Sema &S,
}
case SK_BindReference:
- // References cannot bind to bit-fields (C++ [dcl.init.ref]p5).
- if (CurInit.get()->refersToBitField()) {
- // We don't necessarily have an unambiguous source bit-field.
- FieldDecl *BitField = CurInit.get()->getSourceBitField();
- S.Diag(Kind.getLocation(), diag::err_reference_bind_to_bitfield)
- << Entity.getType().isVolatileQualified()
- << (BitField ? BitField->getDeclName() : DeclarationName())
- << (BitField != nullptr)
- << CurInit.get()->getSourceRange();
- if (BitField)
- S.Diag(BitField->getLocation(), diag::note_bitfield_decl);
-
- return ExprError();
- }
-
- if (CurInit.get()->refersToVectorElement()) {
- // References cannot bind to vector elements.
- S.Diag(Kind.getLocation(), diag::err_reference_bind_to_vector_element)
- << Entity.getType().isVolatileQualified()
- << CurInit.get()->getSourceRange();
- PrintInitLocationNote(S, Entity);
- return ExprError();
- }
-
// Reference binding does not have any corresponding ASTs.
// Check exception specifications
@@ -6469,15 +6652,15 @@ InitializationSequence::Perform(Sema &S,
// Materialize the temporary into memory.
MaterializeTemporaryExpr *MTE = S.CreateMaterializeTemporaryExpr(
- Entity.getType().getNonReferenceType(), CurInit.get(),
- Entity.getType()->isLValueReferenceType());
+ 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,
+ warnOnLifetimeExtension(S, Entity, CurInit.get(),
+ /*IsInitializerList=*/false,
ExtendingEntity->getDecl());
// If we're binding to an Objective-C object that has lifetime, we
@@ -6494,6 +6677,21 @@ InitializationSequence::Perform(Sema &S,
break;
}
+ case SK_FinalCopy:
+ if (checkAbstractType(Step->Type))
+ return ExprError();
+
+ // If the overall initialization is initializing a temporary, we already
+ // bound our argument if it was necessary to do so. If not (if we're
+ // ultimately initializing a non-temporary), our argument needs to be
+ // bound since it's initializing a function parameter.
+ // FIXME: This is a mess. Rationalize temporary destruction.
+ if (!shouldBindAsTemporary(Entity))
+ CurInit = S.MaybeBindToTemporary(CurInit.get());
+ CurInit = CopyObject(S, Step->Type, Entity, CurInit,
+ /*IsExtraneousCopy=*/false);
+ break;
+
case SK_ExtraneousCopyToTemporary:
CurInit = CopyObject(S, Step->Type, Entity, CurInit,
/*IsExtraneousCopy=*/true);
@@ -6503,7 +6701,6 @@ InitializationSequence::Perform(Sema &S,
// We have a user-defined conversion that invokes either a constructor
// or a conversion function.
CastKind CastKind;
- bool IsCopy = false;
FunctionDecl *Fn = Step->Function.Function;
DeclAccessPair FoundFn = Step->Function.FoundDecl;
bool HadMultipleCandidates = Step->Function.HadMultipleCandidates;
@@ -6512,7 +6709,6 @@ InitializationSequence::Perform(Sema &S,
// Build a call to the selected constructor.
SmallVector<Expr*, 8> ConstructorArgs;
SourceLocation Loc = CurInit.get()->getLocStart();
- CurInit.get(); // Ownership transferred into MultiExprArg, below.
// Determine the arguments required to actually perform the constructor
// call.
@@ -6541,11 +6737,6 @@ InitializationSequence::Perform(Sema &S,
return ExprError();
CastKind = CK_ConstructorConversion;
- QualType Class = S.Context.getTypeDeclType(Constructor->getParent());
- if (S.Context.hasSameUnqualifiedType(SourceType, Class) ||
- S.IsDerivedFrom(Loc, SourceType, Class))
- IsCopy = true;
-
CreatedObject = true;
} else {
// Build a call to the conversion function.
@@ -6558,29 +6749,38 @@ InitializationSequence::Perform(Sema &S,
// 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.
- ExprResult CurInitExprRes =
- S.PerformObjectArgumentInitialization(CurInit.get(),
- /*Qualifier=*/nullptr,
- FoundFn, Conversion);
- if(CurInitExprRes.isInvalid())
+ CurInit = S.PerformObjectArgumentInitialization(CurInit.get(),
+ /*Qualifier=*/nullptr,
+ FoundFn, Conversion);
+ if (CurInit.isInvalid())
return ExprError();
- CurInit = CurInitExprRes;
// Build the actual call to the conversion function.
CurInit = S.BuildCXXMemberCallExpr(CurInit.get(), FoundFn, Conversion,
HadMultipleCandidates);
- if (CurInit.isInvalid() || !CurInit.get())
+ if (CurInit.isInvalid())
return ExprError();
CastKind = CK_UserDefinedConversion;
-
CreatedObject = Conversion->getReturnType()->isRecordType();
}
- bool RequiresCopy = !IsCopy && !isReferenceBinding(Steps.back());
- bool MaybeBindToTemp = RequiresCopy || shouldBindAsTemporary(Entity);
+ if (CreatedObject && checkAbstractType(CurInit.get()->getType()))
+ return ExprError();
+
+ CurInit = ImplicitCastExpr::Create(S.Context, CurInit.get()->getType(),
+ CastKind, CurInit.get(), nullptr,
+ CurInit.get()->getValueKind());
- if (!MaybeBindToTemp && CreatedObject && shouldDestroyTemporary(Entity)) {
+ if (shouldBindAsTemporary(Entity))
+ // The overall entity is temporary, so this expression should be
+ // destroyed at the end of its full-expression.
+ CurInit = S.MaybeBindToTemporary(CurInit.getAs<Expr>());
+ else if (CreatedObject && shouldDestroyEntity(Entity)) {
+ // The object outlasts the full-expression, but we need to prepare for
+ // a destructor being run on it.
+ // FIXME: It makes no sense to do this here. This should happen
+ // regardless of how we initialized the entity.
QualType T = CurInit.get()->getType();
if (const RecordType *Record = T->getAs<RecordType>()) {
CXXDestructorDecl *Destructor
@@ -6592,15 +6792,6 @@ InitializationSequence::Perform(Sema &S,
return ExprError();
}
}
-
- CurInit = ImplicitCastExpr::Create(S.Context, CurInit.get()->getType(),
- CastKind, CurInit.get(), nullptr,
- CurInit.get()->getValueKind());
- if (MaybeBindToTemp)
- CurInit = S.MaybeBindToTemporary(CurInit.getAs<Expr>());
- if (RequiresCopy)
- CurInit = CopyObject(S, Entity.getType().getNonReferenceType(), Entity,
- CurInit, /*IsExtraneousCopy=*/false);
break;
}
@@ -6645,16 +6836,23 @@ InitializationSequence::Perform(Sema &S,
getAssignmentAction(Entity), CCK);
if (CurInitExprRes.isInvalid())
return ExprError();
+
+ S.DiscardMisalignedMemberAddress(Step->Type.getTypePtr(), CurInit.get());
+
CurInit = CurInitExprRes;
if (Step->Kind == SK_ConversionSequenceNoNarrowing &&
- S.getLangOpts().CPlusPlus && !CurInit.get()->isValueDependent())
+ S.getLangOpts().CPlusPlus)
DiagnoseNarrowingInInitList(S, *Step->ICS, SourceType, Entity.getType(),
CurInit.get());
+
break;
}
case SK_ListInitialization: {
+ if (checkAbstractType(Step->Type))
+ return ExprError();
+
InitListExpr *InitList = cast<InitListExpr>(CurInit.get());
// If we're not initializing the top-level entity, we need to create an
// InitializeTemporary entity for our target type.
@@ -6691,6 +6889,9 @@ InitializationSequence::Perform(Sema &S,
}
case SK_ConstructorInitializationFromList: {
+ if (checkAbstractType(Step->Type))
+ return ExprError();
+
// When an initializer list is passed for a parameter of type "reference
// to object", we don't get an EK_Temporary entity, but instead an
// EK_Parameter entity with reference type.
@@ -6734,6 +6935,9 @@ InitializationSequence::Perform(Sema &S,
case SK_ConstructorInitialization:
case SK_StdInitializerListConstructorCall: {
+ if (checkAbstractType(Step->Type))
+ return ExprError();
+
// When an initializer list is passed for a parameter of type "reference
// to object", we don't get an EK_Temporary entity, but instead an
// EK_Parameter entity with reference type.
@@ -6745,13 +6949,15 @@ InitializationSequence::Perform(Sema &S,
bool UseTemporary = Entity.getType()->isReferenceType();
bool IsStdInitListInit =
Step->Kind == SK_StdInitializerListConstructorCall;
+ Expr *Source = CurInit.get();
CurInit = PerformConstructorInitialization(
- S, UseTemporary ? TempEntity : Entity, Kind, Args, *Step,
+ S, UseTemporary ? TempEntity : Entity, Kind,
+ Source ? MultiExprArg(Source) : Args, *Step,
ConstructorInitRequiresZeroInit,
- /*IsListInitialization*/IsStdInitListInit,
- /*IsStdInitListInitialization*/IsStdInitListInit,
- /*LBraceLoc*/SourceLocation(),
- /*RBraceLoc*/SourceLocation());
+ /*IsListInitialization*/ IsStdInitListInit,
+ /*IsStdInitListInitialization*/ IsStdInitListInit,
+ /*LBraceLoc*/ SourceLocation(),
+ /*RBraceLoc*/ SourceLocation());
break;
}
@@ -6830,13 +7036,36 @@ InitializationSequence::Perform(Sema &S,
CurInit.get()->getValueKind());
break;
- case SK_ArrayInit:
+ case SK_ArrayLoopIndex: {
+ Expr *Cur = CurInit.get();
+ Expr *BaseExpr = new (S.Context)
+ OpaqueValueExpr(Cur->getExprLoc(), Cur->getType(),
+ Cur->getValueKind(), Cur->getObjectKind(), Cur);
+ Expr *IndexExpr =
+ new (S.Context) ArrayInitIndexExpr(S.Context.getSizeType());
+ CurInit = S.CreateBuiltinArraySubscriptExpr(
+ BaseExpr, Kind.getLocation(), IndexExpr, Kind.getLocation());
+ ArrayLoopCommonExprs.push_back(BaseExpr);
+ break;
+ }
+
+ case SK_ArrayLoopInit: {
+ assert(!ArrayLoopCommonExprs.empty() &&
+ "mismatched SK_ArrayLoopIndex and SK_ArrayLoopInit");
+ Expr *Common = ArrayLoopCommonExprs.pop_back_val();
+ CurInit = new (S.Context) ArrayInitLoopExpr(Step->Type, Common,
+ CurInit.get());
+ break;
+ }
+
+ case SK_GNUArrayInit:
// Okay: we checked everything before creating this step. Note that
// this is a GNU extension.
S.Diag(Kind.getLocation(), diag::ext_array_init_copy)
<< Step->Type << CurInit.get()->getType()
<< CurInit.get()->getSourceRange();
-
+ LLVM_FALLTHROUGH;
+ case SK_ArrayInit:
// If the destination type is an incomplete array type, update the
// type accordingly.
if (ResultType) {
@@ -6904,19 +7133,93 @@ InitializationSequence::Perform(Sema &S,
}
case SK_OCLSamplerInit: {
- assert(Step->Type->isSamplerT() &&
+ // Sampler initialzation have 5 cases:
+ // 1. function argument passing
+ // 1a. argument is a file-scope variable
+ // 1b. argument is a function-scope variable
+ // 1c. argument is one of caller function's parameters
+ // 2. variable initialization
+ // 2a. initializing a file-scope variable
+ // 2b. initializing a function-scope variable
+ //
+ // For file-scope variables, since they cannot be initialized by function
+ // call of __translate_sampler_initializer in LLVM IR, their references
+ // need to be replaced by a cast from their literal initializers to
+ // sampler type. Since sampler variables can only be used in function
+ // calls as arguments, we only need to replace them when handling the
+ // argument passing.
+ assert(Step->Type->isSamplerT() &&
"Sampler initialization on non-sampler type.");
-
- QualType SourceType = CurInit.get()->getType();
-
+ Expr *Init = CurInit.get();
+ QualType SourceType = Init->getType();
+ // Case 1
if (Entity.isParameterKind()) {
- if (!SourceType->isSamplerT())
+ if (!SourceType->isSamplerT()) {
S.Diag(Kind.getLocation(), diag::err_sampler_argument_required)
<< SourceType;
- } else if (Entity.getKind() != InitializedEntity::EK_Variable) {
- llvm_unreachable("Invalid EntityKind!");
+ break;
+ } else if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Init)) {
+ auto Var = cast<VarDecl>(DRE->getDecl());
+ // Case 1b and 1c
+ // No cast from integer to sampler is needed.
+ if (!Var->hasGlobalStorage()) {
+ CurInit = ImplicitCastExpr::Create(S.Context, Step->Type,
+ CK_LValueToRValue, Init,
+ /*BasePath=*/nullptr, VK_RValue);
+ break;
+ }
+ // Case 1a
+ // For function call with a file-scope sampler variable as argument,
+ // get the integer literal.
+ // Do not diagnose if the file-scope variable does not have initializer
+ // since this has already been diagnosed when parsing the variable
+ // declaration.
+ if (!Var->getInit() || !isa<ImplicitCastExpr>(Var->getInit()))
+ break;
+ Init = cast<ImplicitCastExpr>(const_cast<Expr*>(
+ Var->getInit()))->getSubExpr();
+ SourceType = Init->getType();
+ }
+ } else {
+ // Case 2
+ // Check initializer is 32 bit integer constant.
+ // If the initializer is taken from global variable, do not diagnose since
+ // this has already been done when parsing the variable declaration.
+ if (!Init->isConstantInitializer(S.Context, false))
+ break;
+
+ if (!SourceType->isIntegerType() ||
+ 32 != S.Context.getIntWidth(SourceType)) {
+ S.Diag(Kind.getLocation(), diag::err_sampler_initializer_not_integer)
+ << SourceType;
+ break;
+ }
+
+ llvm::APSInt Result;
+ Init->EvaluateAsInt(Result, S.Context);
+ const uint64_t SamplerValue = Result.getLimitedValue();
+ // 32-bit value of sampler's initializer is interpreted as
+ // bit-field with the following structure:
+ // |unspecified|Filter|Addressing Mode| Normalized Coords|
+ // |31 6|5 4|3 1| 0|
+ // This structure corresponds to enum values of sampler properties
+ // defined in SPIR spec v1.2 and also opencl-c.h
+ unsigned AddressingMode = (0x0E & SamplerValue) >> 1;
+ unsigned FilterMode = (0x30 & SamplerValue) >> 4;
+ if (FilterMode != 1 && FilterMode != 2)
+ S.Diag(Kind.getLocation(),
+ diag::warn_sampler_initializer_invalid_bits)
+ << "Filter Mode";
+ if (AddressingMode > 4)
+ S.Diag(Kind.getLocation(),
+ diag::warn_sampler_initializer_invalid_bits)
+ << "Addressing Mode";
}
+ // Cases 1a, 2a and 2b
+ // Insert cast from integer to sampler.
+ CurInit = S.ImpCastExprToType(Init, S.Context.OCLSamplerTy,
+ CK_IntToOCLSampler);
break;
}
case SK_OCLZeroEvent: {
@@ -6928,6 +7231,15 @@ InitializationSequence::Perform(Sema &S,
CurInit.get()->getValueKind());
break;
}
+ case SK_OCLZeroQueue: {
+ assert(Step->Type->isQueueT() &&
+ "Event initialization on non queue type.");
+
+ CurInit = S.ImpCastExprToType(CurInit.get(), Step->Type,
+ CK_ZeroToOCLQueue,
+ CurInit.get()->getValueKind());
+ break;
+ }
}
}
@@ -7190,6 +7502,25 @@ bool InitializationSequence::Diagnose(Sema &S,
<< Args[0]->getSourceRange();
break;
+ case FK_NonConstLValueReferenceBindingToBitfield: {
+ // We don't necessarily have an unambiguous source bit-field.
+ FieldDecl *BitField = Args[0]->getSourceBitField();
+ S.Diag(Kind.getLocation(), diag::err_reference_bind_to_bitfield)
+ << DestType.isVolatileQualified()
+ << (BitField ? BitField->getDeclName() : DeclarationName())
+ << (BitField != nullptr)
+ << Args[0]->getSourceRange();
+ if (BitField)
+ S.Diag(BitField->getLocation(), diag::note_bitfield_decl);
+ break;
+ }
+
+ case FK_NonConstLValueReferenceBindingToVectorElement:
+ S.Diag(Kind.getLocation(), diag::err_reference_bind_to_vector_element)
+ << DestType.isVolatileQualified()
+ << Args[0]->getSourceRange();
+ break;
+
case FK_RValueReferenceBindingToLValue:
S.Diag(Kind.getLocation(), diag::err_lvalue_to_rvalue_ref)
<< DestType.getNonReferenceType() << Args[0]->getType()
@@ -7487,6 +7818,14 @@ void InitializationSequence::dump(raw_ostream &OS) const {
OS << "non-const lvalue reference bound to temporary";
break;
+ case FK_NonConstLValueReferenceBindingToBitfield:
+ OS << "non-const lvalue reference bound to bit-field";
+ break;
+
+ case FK_NonConstLValueReferenceBindingToVectorElement:
+ OS << "non-const lvalue reference bound to vector element";
+ break;
+
case FK_NonConstLValueReferenceBindingToUnrelated:
OS << "non-const lvalue reference bound to unrelated type";
break;
@@ -7583,15 +7922,15 @@ void InitializationSequence::dump(raw_ostream &OS) const {
break;
case SK_CastDerivedToBaseRValue:
- OS << "derived-to-base case (rvalue" << S->Type.getAsString() << ")";
+ OS << "derived-to-base (rvalue)";
break;
case SK_CastDerivedToBaseXValue:
- OS << "derived-to-base case (xvalue" << S->Type.getAsString() << ")";
+ OS << "derived-to-base (xvalue)";
break;
case SK_CastDerivedToBaseLValue:
- OS << "derived-to-base case (lvalue" << S->Type.getAsString() << ")";
+ OS << "derived-to-base (lvalue)";
break;
case SK_BindReference:
@@ -7602,6 +7941,10 @@ void InitializationSequence::dump(raw_ostream &OS) const {
OS << "bind reference to a temporary";
break;
+ case SK_FinalCopy:
+ OS << "final copy in class direct-initialization";
+ break;
+
case SK_ExtraneousCopyToTemporary:
OS << "extraneous C++03 copy to temporary";
break;
@@ -7678,10 +8021,22 @@ void InitializationSequence::dump(raw_ostream &OS) const {
OS << "Objective-C object conversion";
break;
+ case SK_ArrayLoopIndex:
+ OS << "indexing for array initialization loop";
+ break;
+
+ case SK_ArrayLoopInit:
+ OS << "array initialization loop";
+ break;
+
case SK_ArrayInit:
OS << "array initialization";
break;
+ case SK_GNUArrayInit:
+ OS << "array initialization (GNU extension)";
+ break;
+
case SK_ParenthesizedArrayInit:
OS << "parenthesized array initialization";
break;
@@ -7713,6 +8068,10 @@ void InitializationSequence::dump(raw_ostream &OS) const {
case SK_OCLZeroEvent:
OS << "OpenCL event_t from zero";
break;
+
+ case SK_OCLZeroQueue:
+ OS << "OpenCL queue_t from zero";
+ break;
}
OS << " [" << S->Type.getAsString() << ']';
@@ -7750,6 +8109,7 @@ static void DiagnoseNarrowingInInitList(Sema &S,
switch (SCS->getNarrowingKind(S.Context, PostInit, ConstantValue,
ConstantType)) {
case NK_Not_Narrowing:
+ case NK_Dependent_Narrowing:
// No narrowing occurred.
return;
diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp
index 0b3af262cd61..3bae69164ffd 100644
--- a/lib/Sema/SemaLambda.cpp
+++ b/lib/Sema/SemaLambda.cpp
@@ -238,7 +238,7 @@ getGenericLambdaTemplateParameterList(LambdaScopeInfo *LSI, Sema &SemaRef) {
/*Template kw loc*/ SourceLocation(), LAngleLoc,
llvm::makeArrayRef((NamedDecl *const *)LSI->AutoTemplateParams.data(),
LSI->AutoTemplateParams.size()),
- RAngleLoc);
+ RAngleLoc, nullptr);
}
return LSI->GLTemplateParameterList;
}
@@ -361,7 +361,8 @@ CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
SourceRange IntroducerRange,
TypeSourceInfo *MethodTypeInfo,
SourceLocation EndLoc,
- ArrayRef<ParmVarDecl *> Params) {
+ ArrayRef<ParmVarDecl *> Params,
+ const bool IsConstexprSpecified) {
QualType MethodType = MethodTypeInfo->getType();
TemplateParameterList *TemplateParams =
getGenericLambdaTemplateParameterList(getCurLambda(), *this);
@@ -398,7 +399,7 @@ CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
MethodType, MethodTypeInfo,
SC_None,
/*isInline=*/true,
- /*isConstExpr=*/false,
+ IsConstexprSpecified,
EndLoc);
Method->setAccess(AS_public);
@@ -883,14 +884,20 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
CXXRecordDecl *Class = createLambdaClosureType(Intro.Range, MethodTyInfo,
KnownDependent, Intro.Default);
- CXXMethodDecl *Method = startLambdaDefinition(Class, Intro.Range,
- MethodTyInfo, EndLoc, Params);
+ CXXMethodDecl *Method =
+ startLambdaDefinition(Class, Intro.Range, MethodTyInfo, EndLoc, Params,
+ ParamInfo.getDeclSpec().isConstexprSpecified());
if (ExplicitParams)
CheckCXXDefaultArguments(Method);
// Attributes on the lambda apply to the method.
ProcessDeclAttributes(CurScope, Method, ParamInfo);
-
+
+ // CUDA lambdas get implicit attributes based on the scope in which they're
+ // declared.
+ if (getLangOpts().CUDA)
+ CUDASetLambdaAttrs(Method);
+
// Introduce the function call operator as the current declaration context.
PushDeclContext(CurScope, Method);
@@ -1148,14 +1155,16 @@ void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope,
/// \brief Add a lambda's conversion to function pointer, as described in
/// C++11 [expr.prim.lambda]p6.
-static void addFunctionPointerConversion(Sema &S,
+static void addFunctionPointerConversion(Sema &S,
SourceRange IntroducerRange,
CXXRecordDecl *Class,
CXXMethodDecl *CallOperator) {
// This conversion is explicitly disabled if the lambda's function has
// pass_object_size attributes on any of its parameters.
- if (llvm::any_of(CallOperator->parameters(),
- std::mem_fn(&ParmVarDecl::hasAttr<PassObjectSizeAttr>)))
+ auto HasPassObjectSizeAttr = [](const ParmVarDecl *P) {
+ return P->hasAttr<PassObjectSizeAttr>();
+ };
+ if (llvm::any_of(CallOperator->parameters(), HasPassObjectSizeAttr))
return;
// Add the conversion to function pointer.
@@ -1375,10 +1384,7 @@ static void addBlockPointerConversion(Sema &S,
}
static ExprResult performLambdaVarCaptureInitialization(
- Sema &S, LambdaScopeInfo::Capture &Capture,
- FieldDecl *Field,
- SmallVectorImpl<VarDecl *> &ArrayIndexVars,
- SmallVectorImpl<unsigned> &ArrayIndexStarts) {
+ Sema &S, LambdaScopeInfo::Capture &Capture, FieldDecl *Field) {
assert(Capture.isVariableCapture() && "not a variable capture");
auto *Var = Capture.getVariable();
@@ -1402,69 +1408,11 @@ static ExprResult performLambdaVarCaptureInitialization(
return ExprError();
Expr *Ref = RefResult.get();
- QualType FieldType = Field->getType();
-
- // When the variable has array type, create index variables for each
- // dimension of the array. We use these index variables to subscript
- // the source array, and other clients (e.g., CodeGen) will perform
- // the necessary iteration with these index variables.
- //
- // FIXME: This is dumb. Add a proper AST representation for array
- // copy-construction and use it here.
- SmallVector<VarDecl *, 4> IndexVariables;
- QualType BaseType = FieldType;
- QualType SizeType = S.Context.getSizeType();
- ArrayIndexStarts.push_back(ArrayIndexVars.size());
- while (const ConstantArrayType *Array
- = S.Context.getAsConstantArrayType(BaseType)) {
- // Create the iteration variable for this array index.
- IdentifierInfo *IterationVarName = nullptr;
- {
- SmallString<8> Str;
- llvm::raw_svector_ostream OS(Str);
- OS << "__i" << IndexVariables.size();
- IterationVarName = &S.Context.Idents.get(OS.str());
- }
- VarDecl *IterationVar = VarDecl::Create(
- S.Context, S.CurContext, Loc, Loc, IterationVarName, SizeType,
- S.Context.getTrivialTypeSourceInfo(SizeType, Loc), SC_None);
- IterationVar->setImplicit();
- IndexVariables.push_back(IterationVar);
- ArrayIndexVars.push_back(IterationVar);
-
- // Create a reference to the iteration variable.
- ExprResult IterationVarRef =
- S.BuildDeclRefExpr(IterationVar, SizeType, VK_LValue, Loc);
- assert(!IterationVarRef.isInvalid() &&
- "Reference to invented variable cannot fail!");
- IterationVarRef = S.DefaultLvalueConversion(IterationVarRef.get());
- assert(!IterationVarRef.isInvalid() &&
- "Conversion of invented variable cannot fail!");
-
- // Subscript the array with this iteration variable.
- ExprResult Subscript =
- S.CreateBuiltinArraySubscriptExpr(Ref, Loc, IterationVarRef.get(), Loc);
- if (Subscript.isInvalid())
- return ExprError();
-
- Ref = Subscript.get();
- BaseType = Array->getElementType();
- }
-
- // Construct the entity that we will be initializing. For an array, this
- // will be first element in the array, which may require several levels
- // of array-subscript entities.
- SmallVector<InitializedEntity, 4> Entities;
- Entities.reserve(1 + IndexVariables.size());
- Entities.push_back(InitializedEntity::InitializeLambdaCapture(
- Var->getIdentifier(), FieldType, Loc));
- for (unsigned I = 0, N = IndexVariables.size(); I != N; ++I)
- Entities.push_back(
- InitializedEntity::InitializeElement(S.Context, 0, Entities.back()));
-
+ auto Entity = InitializedEntity::InitializeLambdaCapture(
+ Var->getIdentifier(), Field->getType(), Loc);
InitializationKind InitKind = InitializationKind::CreateDirect(Loc, Loc, Loc);
- InitializationSequence Init(S, Entities.back(), InitKind, Ref);
- return Init.Perform(S, Entities.back(), InitKind, Ref);
+ InitializationSequence Init(S, Entity, InitKind, Ref);
+ return Init.Perform(S, Entity, InitKind, Ref);
}
ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
@@ -1505,8 +1453,6 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
bool ExplicitResultType;
CleanupInfo LambdaCleanup;
bool ContainsUnexpandedParameterPack;
- SmallVector<VarDecl *, 4> ArrayIndexVars;
- SmallVector<unsigned, 4> ArrayIndexStarts;
{
CallOperator = LSI->CallOperator;
Class = LSI->Lambda;
@@ -1540,14 +1486,12 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
LambdaCapture(From.getLocation(), IsImplicit,
From.isCopyCapture() ? LCK_StarThis : LCK_This));
CaptureInits.push_back(From.getInitExpr());
- ArrayIndexStarts.push_back(ArrayIndexVars.size());
continue;
}
if (From.isVLATypeCapture()) {
Captures.push_back(
LambdaCapture(From.getLocation(), IsImplicit, LCK_VLAType));
CaptureInits.push_back(nullptr);
- ArrayIndexStarts.push_back(ArrayIndexVars.size());
continue;
}
@@ -1557,13 +1501,11 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
Var, From.getEllipsisLoc()));
Expr *Init = From.getInitExpr();
if (!Init) {
- auto InitResult = performLambdaVarCaptureInitialization(
- *this, From, *CurField, ArrayIndexVars, ArrayIndexStarts);
+ auto InitResult =
+ performLambdaVarCaptureInitialization(*this, From, *CurField);
if (InitResult.isInvalid())
return ExprError();
Init = InitResult.get();
- } else {
- ArrayIndexStarts.push_back(ArrayIndexVars.size());
}
CaptureInits.push_back(Init);
}
@@ -1600,9 +1542,22 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
CaptureDefault, CaptureDefaultLoc,
Captures,
ExplicitParams, ExplicitResultType,
- CaptureInits, ArrayIndexVars,
- ArrayIndexStarts, EndLoc,
+ CaptureInits, EndLoc,
ContainsUnexpandedParameterPack);
+ // If the lambda expression's call operator is not explicitly marked constexpr
+ // and we are not in a dependent context, analyze the call operator to infer
+ // its constexpr-ness, supressing diagnostics while doing so.
+ if (getLangOpts().CPlusPlus1z && !CallOperator->isInvalidDecl() &&
+ !CallOperator->isConstexpr() &&
+ !Class->getDeclContext()->isDependentContext()) {
+ TentativeAnalysisScope DiagnosticScopeGuard(*this);
+ CallOperator->setConstexpr(
+ CheckConstexprFunctionDecl(CallOperator) &&
+ CheckConstexprFunctionBody(CallOperator, CallOperator->getBody()));
+ }
+
+ // Emit delayed shadowing warnings now that the full capture list is known.
+ DiagnoseShadowingLambdaDecls(LSI);
if (!CurContext->isDependentContext()) {
switch (ExprEvalContexts.back().Context) {
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index e2550824fb69..38a7b8c127cc 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -12,9 +12,7 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Sema/Lookup.h"
#include "clang/AST/ASTContext.h"
-#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
@@ -29,6 +27,7 @@
#include "clang/Lex/ModuleLoader.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/Lookup.h"
#include "clang/Sema/Overload.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
@@ -37,17 +36,13 @@
#include "clang/Sema/TemplateDeduction.h"
#include "clang/Sema/TypoCorrection.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h"
-#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/ADT/edit_distance.h"
#include "llvm/Support/ErrorHandling.h"
#include <algorithm>
#include <iterator>
-#include <limits>
#include <list>
-#include <map>
#include <set>
#include <utility>
#include <vector>
@@ -455,15 +450,18 @@ static bool canHideTag(NamedDecl *D) {
// Given a set of declarations in a single declarative region [...]
// exactly one declaration shall declare a class name or enumeration name
// that is not a typedef name and the other declarations shall all refer to
- // the same variable or enumerator, or all refer to functions and function
- // templates; in this case the class name or enumeration name is hidden.
+ // the same variable, non-static data member, or enumerator, or all refer
+ // to functions and function templates; in this case the class name or
+ // enumeration name is hidden.
// C++ [basic.scope.hiding]p2:
// A class name or enumeration name can be hidden by the name of a
// variable, data member, function, or enumerator declared in the same
// scope.
+ // An UnresolvedUsingValueDecl always instantiates to one of these.
D = D->getUnderlyingDecl();
return isa<VarDecl>(D) || isa<EnumConstantDecl>(D) || isa<FunctionDecl>(D) ||
- isa<FunctionTemplateDecl>(D) || isa<FieldDecl>(D);
+ isa<FunctionTemplateDecl>(D) || isa<FieldDecl>(D) ||
+ isa<UnresolvedUsingValueDecl>(D);
}
/// Resolves the result kind of this lookup.
@@ -1298,7 +1296,7 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
// If we have a context, and it's not a context stashed in the
// template parameter scope for an out-of-line definition, also
// look into that context.
- if (!(Found && S && S->isTemplateParamScope())) {
+ if (!(Found && S->isTemplateParamScope())) {
assert(Ctx->isFileContext() &&
"We should have been looking only at file context here already.");
@@ -1372,8 +1370,9 @@ Module *Sema::getOwningModule(Decl *Entity) {
auto &SrcMgr = PP.getSourceManager();
SourceLocation StartLoc =
SrcMgr.getLocForStartOfFile(SrcMgr.getMainFileID());
- auto &TopLevel =
- VisibleModulesStack.empty() ? VisibleModules : VisibleModulesStack[0];
+ auto &TopLevel = ModuleScopes.empty()
+ ? VisibleModules
+ : ModuleScopes[0].OuterVisibleModules;
TopLevel.setVisible(CachedFakeTopLevelModule, StartLoc);
}
@@ -1542,12 +1541,17 @@ bool LookupResult::isVisibleSlow(Sema &SemaRef, NamedDecl *D) {
// If this declaration is not at namespace scope nor module-private,
// then it is visible if its lexical parent has a visible definition.
DeclContext *DC = D->getLexicalDeclContext();
- if (!D->isModulePrivate() &&
- DC && !DC->isFileContext() && !isa<LinkageSpecDecl>(DC)) {
+ if (!D->isModulePrivate() && DC && !DC->isFileContext() &&
+ !isa<LinkageSpecDecl>(DC) && !isa<ExportDecl>(DC)) {
// For a parameter, check whether our current template declaration's
// lexical context is visible, not whether there's some other visible
// definition of it, because parameters aren't "within" the definition.
- if ((D->isTemplateParameter() || isa<ParmVarDecl>(D))
+ //
+ // In C++ we need to check for a visible definition due to ODR merging,
+ // and in C we must not because each declaration of a function gets its own
+ // set of declarations for tags in prototype scope.
+ if ((D->isTemplateParameter() || isa<ParmVarDecl>(D)
+ || (isa<FunctionDecl>(DC) && !SemaRef.getLangOpts().CPlusPlus))
? isVisible(SemaRef, cast<NamedDecl>(DC))
: SemaRef.hasVisibleDefinition(cast<NamedDecl>(DC))) {
if (SemaRef.ActiveTemplateInstantiations.empty() &&
@@ -5081,6 +5085,10 @@ void Sema::diagnoseTypo(const TypoCorrection &Correction,
if (PrevNote.getDiagID() && ChosenDecl)
Diag(ChosenDecl->getLocation(), PrevNote)
<< CorrectedQuotedStr << (ErrorRecovery ? FixItHint() : FixTypo);
+
+ // Add any extra diagnostics.
+ for (const PartialDiagnostic &PD : Correction.getExtraDiagnostics())
+ Diag(Correction.getCorrectionRange().getBegin(), PD);
}
TypoExpr *Sema::createDelayedTypo(std::unique_ptr<TypoCorrectionConsumer> TCC,
diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp
index 5e38751f44a5..3481b82679c2 100644
--- a/lib/Sema/SemaObjCProperty.cpp
+++ b/lib/Sema/SemaObjCProperty.cpp
@@ -753,7 +753,7 @@ static void checkARCPropertyImpl(Sema &S, SourceLocation propertyImplLoc,
break;
case Qualifiers::OCL_Weak:
- S.Diag(ivar->getLocation(), diag::error_weak_property)
+ S.Diag(ivar->getLocation(), diag::err_weak_property)
<< property->getDeclName()
<< ivar->getDeclName();
break;
@@ -904,7 +904,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
dyn_cast<ObjCContainerDecl>(CurContext);
// Make sure we have a context for the property implementation declaration.
if (!ClassImpDecl) {
- Diag(AtLoc, diag::error_missing_property_context);
+ Diag(AtLoc, diag::err_missing_property_context);
return nullptr;
}
if (PropertyIvarLoc.isInvalid())
@@ -928,11 +928,11 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
// Look for this property declaration in the @implementation's @interface
property = IDecl->FindPropertyDeclaration(PropertyId, QueryKind);
if (!property) {
- Diag(PropertyLoc, diag::error_bad_property_decl) << IDecl->getDeclName();
+ Diag(PropertyLoc, diag::err_bad_property_decl) << IDecl->getDeclName();
return nullptr;
}
if (property->isClassProperty() && Synthesize) {
- Diag(PropertyLoc, diag::error_synthesize_on_class_property) << PropertyId;
+ Diag(PropertyLoc, diag::err_synthesize_on_class_property) << PropertyId;
return nullptr;
}
unsigned PIkind = property->getPropertyAttributesAsWritten();
@@ -948,7 +948,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
if (const ObjCCategoryDecl *CD =
dyn_cast<ObjCCategoryDecl>(property->getDeclContext())) {
if (!CD->IsClassExtension()) {
- Diag(PropertyLoc, diag::error_category_property) << CD->getDeclName();
+ Diag(PropertyLoc, diag::err_category_property) << CD->getDeclName();
Diag(property->getLocation(), diag::note_property_declare);
return nullptr;
}
@@ -992,12 +992,12 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
} else if ((CatImplClass = dyn_cast<ObjCCategoryImplDecl>(ClassImpDecl))) {
if (Synthesize) {
- Diag(AtLoc, diag::error_synthesize_category_decl);
+ Diag(AtLoc, diag::err_synthesize_category_decl);
return nullptr;
}
IDecl = CatImplClass->getClassInterface();
if (!IDecl) {
- Diag(AtLoc, diag::error_missing_property_interface);
+ Diag(AtLoc, diag::err_missing_property_interface);
return nullptr;
}
ObjCCategoryDecl *Category =
@@ -1010,12 +1010,12 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
// Look for this property declaration in @implementation's category
property = Category->FindPropertyDeclaration(PropertyId, QueryKind);
if (!property) {
- Diag(PropertyLoc, diag::error_bad_category_property_decl)
+ Diag(PropertyLoc, diag::err_bad_category_property_decl)
<< Category->getDeclName();
return nullptr;
}
} else {
- Diag(AtLoc, diag::error_bad_property_context);
+ Diag(AtLoc, diag::err_bad_property_context);
return nullptr;
}
ObjCIvarDecl *Ivar = nullptr;
@@ -1146,20 +1146,22 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
diag::err_abstract_type_in_decl,
AbstractSynthesizedIvarType)) {
Diag(property->getLocation(), diag::note_property_declare);
+ // An abstract type is as bad as an incomplete type.
+ CompleteTypeErr = true;
+ }
+ if (CompleteTypeErr)
Ivar->setInvalidDecl();
- } else if (CompleteTypeErr)
- Ivar->setInvalidDecl();
ClassImpDecl->addDecl(Ivar);
IDecl->makeDeclVisibleInContext(Ivar);
if (getLangOpts().ObjCRuntime.isFragile())
- Diag(PropertyDiagLoc, diag::error_missing_property_ivar_decl)
+ Diag(PropertyDiagLoc, diag::err_missing_property_ivar_decl)
<< PropertyId;
// Note! I deliberately want it to fall thru so, we have a
// a property implementation and to avoid future warnings.
} else if (getLangOpts().ObjCRuntime.isNonFragile() &&
!declaresSameEntity(ClassDeclared, IDecl)) {
- Diag(PropertyDiagLoc, diag::error_ivar_in_superclass_use)
+ Diag(PropertyDiagLoc, diag::err_ivar_in_superclass_use)
<< property->getDeclName() << Ivar->getDeclName()
<< ClassDeclared->getDeclName();
Diag(Ivar->getLocation(), diag::note_previous_access_declaration)
@@ -1184,7 +1186,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
== Compatible);
}
if (!compat) {
- Diag(PropertyDiagLoc, diag::error_property_ivar_type)
+ Diag(PropertyDiagLoc, diag::err_property_ivar_type)
<< property->getDeclName() << PropType
<< Ivar->getDeclName() << IvarType;
Diag(Ivar->getLocation(), diag::note_ivar_decl);
@@ -1199,7 +1201,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
QualType rhsType =Context.getCanonicalType(IvarType).getUnqualifiedType();
if (lhsType != rhsType &&
lhsType->isArithmeticType()) {
- Diag(PropertyDiagLoc, diag::error_property_ivar_type)
+ Diag(PropertyDiagLoc, diag::err_property_ivar_type)
<< property->getDeclName() << PropType
<< Ivar->getDeclName() << IvarType;
Diag(Ivar->getLocation(), diag::note_ivar_decl);
@@ -1209,7 +1211,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
// __weak is explicit. So it works on Canonical type.
if ((PropType.isObjCGCWeak() && !IvarType.isObjCGCWeak() &&
getLangOpts().getGC() != LangOptions::NonGC)) {
- Diag(PropertyDiagLoc, diag::error_weak_property)
+ Diag(PropertyDiagLoc, diag::err_weak_property)
<< property->getDeclName() << Ivar->getDeclName();
Diag(Ivar->getLocation(), diag::note_ivar_decl);
// Fall thru - see previous comment
@@ -1218,7 +1220,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
if ((property->getType()->isObjCObjectPointerType() ||
PropType.isObjCGCStrong()) && IvarType.isObjCGCWeak() &&
getLangOpts().getGC() != LangOptions::NonGC) {
- Diag(PropertyDiagLoc, diag::error_strong_property)
+ Diag(PropertyDiagLoc, diag::err_strong_property)
<< property->getDeclName() << Ivar->getDeclName();
// Fall thru - see previous comment
}
@@ -1228,7 +1230,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
checkARCPropertyImpl(*this, PropertyLoc, property, Ivar);
} else if (PropertyIvar)
// @dynamic
- Diag(PropertyDiagLoc, diag::error_dynamic_property_ivar_decl);
+ Diag(PropertyDiagLoc, diag::err_dynamic_property_ivar_decl);
assert (property && "ActOnPropertyImplDecl - property declaration missing");
ObjCPropertyImplDecl *PIDecl =
@@ -1348,7 +1350,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
if (Synthesize)
if (ObjCPropertyImplDecl *PPIDecl =
IC->FindPropertyImplIvarDecl(PropertyIvar)) {
- Diag(PropertyLoc, diag::error_duplicate_ivar_use)
+ Diag(PropertyLoc, diag::err_duplicate_ivar_use)
<< PropertyId << PPIDecl->getPropertyDecl()->getIdentifier()
<< PropertyIvar;
Diag(PPIDecl->getLocation(), diag::note_previous_use);
@@ -1356,7 +1358,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
if (ObjCPropertyImplDecl *PPIDecl
= IC->FindPropertyImplDecl(PropertyId, QueryKind)) {
- Diag(PropertyLoc, diag::error_property_implemented) << PropertyId;
+ Diag(PropertyLoc, diag::err_property_implemented) << PropertyId;
Diag(PPIDecl->getLocation(), diag::note_previous_declaration);
return nullptr;
}
@@ -1387,7 +1389,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
if (Synthesize)
if (ObjCPropertyImplDecl *PPIDecl =
CatImplClass->FindPropertyImplIvarDecl(PropertyIvar)) {
- Diag(PropertyDiagLoc, diag::error_duplicate_ivar_use)
+ Diag(PropertyDiagLoc, diag::err_duplicate_ivar_use)
<< PropertyId << PPIDecl->getPropertyDecl()->getIdentifier()
<< PropertyIvar;
Diag(PPIDecl->getLocation(), diag::note_previous_use);
@@ -1395,7 +1397,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
if (ObjCPropertyImplDecl *PPIDecl =
CatImplClass->FindPropertyImplDecl(PropertyId, QueryKind)) {
- Diag(PropertyDiagLoc, diag::error_property_implemented) << PropertyId;
+ Diag(PropertyDiagLoc, diag::err_property_implemented) << PropertyId;
Diag(PPIDecl->getLocation(), diag::note_previous_declaration);
return nullptr;
}
@@ -1505,7 +1507,7 @@ bool Sema::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property,
compat = Context.canAssignObjCInterfaces(getterObjCPtr, propertyObjCPtr);
else if (CheckAssignmentConstraints(Loc, GetterType, PropertyRValueType)
!= Compatible) {
- Diag(Loc, diag::error_property_accessor_type)
+ Diag(Loc, diag::err_property_accessor_type)
<< property->getDeclName() << PropertyRValueType
<< GetterMethod->getSelector() << GetterType;
Diag(GetterMethod->getLocation(), diag::note_declared_at);
diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp
index b7ac48583e1a..804aadc0ff77 100644
--- a/lib/Sema/SemaOpenMP.cpp
+++ b/lib/Sema/SemaOpenMP.cpp
@@ -72,8 +72,13 @@ private:
typedef llvm::DenseMap<ValueDecl *, Expr *> AlignedMapTy;
typedef std::pair<unsigned, VarDecl *> LCDeclInfo;
typedef llvm::DenseMap<ValueDecl *, LCDeclInfo> LoopControlVariablesMapTy;
- typedef llvm::DenseMap<
- ValueDecl *, OMPClauseMappableExprCommon::MappableExprComponentLists>
+ /// 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;
@@ -123,7 +128,7 @@ private:
typedef SmallVector<SharingMapTy, 8>::reverse_iterator reverse_iterator;
- DSAVarData getDSA(StackTy::reverse_iterator& Iter, ValueDecl *D);
+ DSAVarData getDSA(StackTy::reverse_iterator &Iter, ValueDecl *D);
/// \brief Checks if the variable is a local for OpenMP region.
bool isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter);
@@ -293,9 +298,7 @@ public:
Stack[Stack.size() - 2].CancelRegion || Cancel;
}
/// \brief Return true if current region has inner cancel construct.
- bool isCancelRegion() const {
- return Stack.back().CancelRegion;
- }
+ bool isCancelRegion() const { return Stack.back().CancelRegion; }
/// \brief Set collapse value for the region.
void setAssociatedLoops(unsigned Val) { Stack.back().AssociatedLoops = Val; }
@@ -323,12 +326,13 @@ public:
Scope *getCurScope() { return Stack.back().CurScope; }
SourceLocation getConstructLoc() { return Stack.back().ConstructLoc; }
- // Do the check specified in \a Check to all component lists and return true
- // if any issue is found.
+ /// 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 llvm::function_ref<bool(
- OMPClauseMappableExprCommon::MappableExprComponentListRef)> &Check) {
+ const llvm::function_ref<
+ bool(OMPClauseMappableExprCommon::MappableExprComponentListRef,
+ OpenMPClauseKind)> &Check) {
auto SI = Stack.rbegin();
auto SE = Stack.rend();
@@ -344,24 +348,26 @@ public:
for (; SI != SE; ++SI) {
auto MI = SI->MappedExprComponents.find(VD);
if (MI != SI->MappedExprComponents.end())
- for (auto &L : MI->second)
- if (Check(L))
+ for (auto &L : MI->second.Components)
+ if (Check(L, MI->second.Kind))
return true;
}
return false;
}
- // Create a new mappable expression component list associated with a given
- // declaration and initialize it with the provided list of components.
+ /// 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,
- OMPClauseMappableExprCommon::MappableExprComponentListRef Components) {
+ OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
+ OpenMPClauseKind WhereFoundClauseKind) {
assert(Stack.size() > 1 &&
"Not expecting to retrieve components from a empty stack!");
auto &MEC = Stack.back().MappedExprComponents[VD];
// Create new entry and append the new components there.
- MEC.resize(MEC.size() + 1);
- MEC.back().append(Components.begin(), Components.end());
+ MEC.Components.resize(MEC.Components.size() + 1);
+ MEC.Components.back().append(Components.begin(), Components.end());
+ MEC.Kind = WhereFoundClauseKind;
}
unsigned getNestingLevel() const {
@@ -393,7 +399,7 @@ bool isParallelOrTaskRegion(OpenMPDirectiveKind DKind) {
static ValueDecl *getCanonicalDecl(ValueDecl *D) {
auto *VD = dyn_cast<VarDecl>(D);
auto *FD = dyn_cast<FieldDecl>(D);
- if (VD != nullptr) {
+ if (VD != nullptr) {
VD = VD->getCanonicalDecl();
D = VD;
} else {
@@ -404,7 +410,7 @@ static ValueDecl *getCanonicalDecl(ValueDecl *D) {
return D;
}
-DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator& Iter,
+DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator &Iter,
ValueDecl *D) {
D = getCanonicalDecl(D);
auto *VD = dyn_cast<VarDecl>(D);
@@ -771,18 +777,12 @@ DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(
D = getCanonicalDecl(D);
auto StartI = std::next(Stack.rbegin());
auto EndI = Stack.rend();
- if (FromParent && StartI != EndI) {
+ if (FromParent && StartI != EndI)
StartI = std::next(StartI);
- }
- for (auto I = StartI, EE = EndI; I != EE; ++I) {
- if (!DPred(I->Directive))
- break;
- DSAVarData DVar = getDSA(I, D);
- if (CPred(DVar.CKind))
- return DVar;
+ if (StartI == EndI || !DPred(StartI->Directive))
return DSAVarData();
- }
- return DSAVarData();
+ DSAVarData DVar = getDSA(StartI, D);
+ return CPred(DVar.CKind) ? DVar : DSAVarData();
}
bool DSAStackTy::hasExplicitDSA(
@@ -903,7 +903,6 @@ bool Sema::IsOpenMPCapturedByRef(ValueDecl *D, unsigned Level) {
// array section, the runtime library may pass the NULL value to the
// device instead of the value passed to it by the compiler.
-
if (Ty->isReferenceType())
Ty = Ty->castAs<ReferenceType>()->getPointeeType();
@@ -916,7 +915,13 @@ bool Sema::IsOpenMPCapturedByRef(ValueDecl *D, unsigned Level) {
DSAStack->checkMappableExprComponentListsForDecl(
D, /*CurrentRegionOnly=*/true,
[&](OMPClauseMappableExprCommon::MappableExprComponentListRef
- MapExprComponents) {
+ MapExprComponents,
+ OpenMPClauseKind WhereFoundClauseKind) {
+ // Only the map clause information influences how a variable is
+ // captured. E.g. is_device_ptr does not require changing the default
+ // behavior.
+ if (WhereFoundClauseKind != OMPC_map)
+ return false;
auto EI = MapExprComponents.rbegin();
auto EE = MapExprComponents.rend();
@@ -1062,7 +1067,7 @@ 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)) {
+ if (auto *D = dyn_cast_or_null<OMPExecutableDirective>(CurDirective)) {
for (auto *C : D->clauses()) {
if (auto *Clause = dyn_cast<OMPLastprivateClause>(C)) {
SmallVector<Expr *, 8> PrivateCopies;
@@ -1121,7 +1126,7 @@ public:
explicit VarDeclFilterCCC(Sema &S) : SemaRef(S) {}
bool ValidateCandidate(const TypoCorrection &Candidate) override {
NamedDecl *ND = Candidate.getCorrectionDecl();
- if (VarDecl *VD = dyn_cast_or_null<VarDecl>(ND)) {
+ if (auto *VD = dyn_cast_or_null<VarDecl>(ND)) {
return VD->hasGlobalStorage() &&
SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
SemaRef.getCurScope());
@@ -1290,7 +1295,7 @@ class LocalVarRefChecker : public ConstStmtVisitor<LocalVarRefChecker, bool> {
public:
bool VisitDeclRefExpr(const DeclRefExpr *E) {
- if (auto VD = dyn_cast<VarDecl>(E->getDecl())) {
+ if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
if (VD->hasLocalStorage()) {
SemaRef.Diag(E->getLocStart(),
diag::err_omp_local_var_in_threadprivate_init)
@@ -1471,7 +1476,8 @@ public:
auto DVar = Stack->getTopDSA(VD, false);
// Check if the variable has explicit DSA set and stop analysis if it so.
- if (DVar.RefExpr) return;
+ if (DVar.RefExpr)
+ return;
auto ELoc = E->getExprLoc();
auto DKind = Stack->getCurrentDirective();
@@ -1550,7 +1556,8 @@ public:
!Stack->isLoopControlVariable(FD).first)
ImplicitFirstprivate.push_back(E);
}
- }
+ } else
+ Visit(E->getBase());
}
void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
for (auto *C : S->clauses()) {
@@ -1587,7 +1594,8 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
case OMPD_parallel_for:
case OMPD_parallel_for_simd:
case OMPD_parallel_sections:
- case OMPD_teams: {
+ case OMPD_teams:
+ case OMPD_target_teams: {
QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1);
QualType KmpInt32PtrTy =
Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
@@ -1616,7 +1624,8 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
case OMPD_target:
case OMPD_target_parallel:
case OMPD_target_parallel_for:
- case OMPD_target_parallel_for_simd: {
+ case OMPD_target_parallel_for_simd:
+ case OMPD_target_simd: {
Sema::CapturedParamNameType Params[] = {
std::make_pair(StringRef(), QualType()) // __context with shared vars
};
@@ -1685,7 +1694,13 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
}
case OMPD_distribute_parallel_for_simd:
case OMPD_distribute_simd:
- case OMPD_distribute_parallel_for: {
+ case OMPD_distribute_parallel_for:
+ case OMPD_teams_distribute:
+ case OMPD_teams_distribute_simd:
+ case OMPD_teams_distribute_parallel_for_simd:
+ case OMPD_teams_distribute_parallel_for:
+ case OMPD_target_teams_distribute:
+ case OMPD_target_teams_distribute_parallel_for: {
QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1);
QualType KmpInt32PtrTy =
Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
@@ -1740,7 +1755,8 @@ static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id,
}
WithInit = true;
}
- auto *CED = OMPCapturedExprDecl::Create(C, S.CurContext, Id, Ty);
+ auto *CED = OMPCapturedExprDecl::Create(C, S.CurContext, Id, Ty,
+ CaptureExpr->getLocStart());
if (!WithInit)
CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C, SourceRange()));
S.CurContext->addHiddenDecl(CED);
@@ -1868,1241 +1884,12 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
const DeclarationNameInfo &CurrentName,
OpenMPDirectiveKind CancelRegion,
SourceLocation StartLoc) {
- // Allowed nesting of constructs
- // +------------------+-----------------+------------------------------------+
- // | Parent directive | Child directive | Closely (!), No-Closely(+), Both(*)|
- // +------------------+-----------------+------------------------------------+
- // | parallel | parallel | * |
- // | parallel | for | * |
- // | parallel | for simd | * |
- // | parallel | master | * |
- // | parallel | critical | * |
- // | parallel | simd | * |
- // | parallel | sections | * |
- // | parallel | section | + |
- // | parallel | single | * |
- // | parallel | parallel for | * |
- // | parallel |parallel for simd| * |
- // | parallel |parallel sections| * |
- // | parallel | task | * |
- // | parallel | taskyield | * |
- // | parallel | barrier | * |
- // | parallel | taskwait | * |
- // | parallel | taskgroup | * |
- // | parallel | flush | * |
- // | parallel | ordered | + |
- // | parallel | atomic | * |
- // | parallel | target | * |
- // | parallel | target parallel | * |
- // | parallel | target parallel | * |
- // | | for | |
- // | parallel | target enter | * |
- // | | data | |
- // | parallel | target exit | * |
- // | | data | |
- // | parallel | teams | + |
- // | parallel | cancellation | |
- // | | point | ! |
- // | parallel | cancel | ! |
- // | parallel | taskloop | * |
- // | parallel | taskloop simd | * |
- // | parallel | distribute | + |
- // | parallel | distribute | + |
- // | | parallel for | |
- // | parallel | distribute | + |
- // | |parallel for simd| |
- // | parallel | distribute simd | + |
- // +------------------+-----------------+------------------------------------+
- // | for | parallel | * |
- // | for | for | + |
- // | for | for simd | + |
- // | for | master | + |
- // | for | critical | * |
- // | for | simd | * |
- // | for | sections | + |
- // | for | section | + |
- // | for | single | + |
- // | for | parallel for | * |
- // | for |parallel for simd| * |
- // | for |parallel sections| * |
- // | for | task | * |
- // | for | taskyield | * |
- // | for | barrier | + |
- // | for | taskwait | * |
- // | for | taskgroup | * |
- // | for | flush | * |
- // | for | ordered | * (if construct is ordered) |
- // | for | atomic | * |
- // | for | target | * |
- // | for | target parallel | * |
- // | for | target parallel | * |
- // | | for | |
- // | for | target enter | * |
- // | | data | |
- // | for | target exit | * |
- // | | data | |
- // | for | teams | + |
- // | for | cancellation | |
- // | | point | ! |
- // | for | cancel | ! |
- // | for | taskloop | * |
- // | for | taskloop simd | * |
- // | for | distribute | + |
- // | for | distribute | + |
- // | | parallel for | |
- // | for | distribute | + |
- // | |parallel for simd| |
- // | for | distribute simd | + |
- // | for | target parallel | + |
- // | | for simd | |
- // +------------------+-----------------+------------------------------------+
- // | master | parallel | * |
- // | master | for | + |
- // | master | for simd | + |
- // | master | master | * |
- // | master | critical | * |
- // | master | simd | * |
- // | master | sections | + |
- // | master | section | + |
- // | master | single | + |
- // | master | parallel for | * |
- // | master |parallel for simd| * |
- // | master |parallel sections| * |
- // | master | task | * |
- // | master | taskyield | * |
- // | master | barrier | + |
- // | master | taskwait | * |
- // | master | taskgroup | * |
- // | master | flush | * |
- // | master | ordered | + |
- // | master | atomic | * |
- // | master | target | * |
- // | master | target parallel | * |
- // | master | target parallel | * |
- // | | for | |
- // | master | target enter | * |
- // | | data | |
- // | master | target exit | * |
- // | | data | |
- // | master | teams | + |
- // | master | cancellation | |
- // | | point | |
- // | master | cancel | |
- // | master | taskloop | * |
- // | master | taskloop simd | * |
- // | master | distribute | + |
- // | master | distribute | + |
- // | | parallel for | |
- // | master | distribute | + |
- // | |parallel for simd| |
- // | master | distribute simd | + |
- // | master | target parallel | + |
- // | | for simd | |
- // +------------------+-----------------+------------------------------------+
- // | critical | parallel | * |
- // | critical | for | + |
- // | critical | for simd | + |
- // | critical | master | * |
- // | critical | critical | * (should have different names) |
- // | critical | simd | * |
- // | critical | sections | + |
- // | critical | section | + |
- // | critical | single | + |
- // | critical | parallel for | * |
- // | critical |parallel for simd| * |
- // | critical |parallel sections| * |
- // | critical | task | * |
- // | critical | taskyield | * |
- // | critical | barrier | + |
- // | critical | taskwait | * |
- // | critical | taskgroup | * |
- // | critical | ordered | + |
- // | critical | atomic | * |
- // | critical | target | * |
- // | critical | target parallel | * |
- // | critical | target parallel | * |
- // | | for | |
- // | critical | target enter | * |
- // | | data | |
- // | critical | target exit | * |
- // | | data | |
- // | critical | teams | + |
- // | critical | cancellation | |
- // | | point | |
- // | critical | cancel | |
- // | critical | taskloop | * |
- // | critical | taskloop simd | * |
- // | critical | distribute | + |
- // | critical | distribute | + |
- // | | parallel for | |
- // | critical | distribute | + |
- // | |parallel for simd| |
- // | critical | distribute simd | + |
- // | critical | target parallel | + |
- // | | for simd | |
- // +------------------+-----------------+------------------------------------+
- // | simd | parallel | |
- // | simd | for | |
- // | simd | for simd | |
- // | simd | master | |
- // | simd | critical | |
- // | simd | simd | * |
- // | simd | sections | |
- // | simd | section | |
- // | simd | single | |
- // | simd | parallel for | |
- // | simd |parallel for simd| |
- // | simd |parallel sections| |
- // | simd | task | |
- // | simd | taskyield | |
- // | simd | barrier | |
- // | simd | taskwait | |
- // | simd | taskgroup | |
- // | simd | flush | |
- // | simd | ordered | + (with simd clause) |
- // | simd | atomic | |
- // | simd | target | |
- // | simd | target parallel | |
- // | simd | target parallel | |
- // | | for | |
- // | simd | target enter | |
- // | | data | |
- // | simd | target exit | |
- // | | data | |
- // | simd | teams | |
- // | simd | cancellation | |
- // | | point | |
- // | simd | cancel | |
- // | simd | taskloop | |
- // | simd | taskloop simd | |
- // | simd | distribute | |
- // | simd | distribute | |
- // | | parallel for | |
- // | simd | distribute | |
- // | |parallel for simd| |
- // | simd | distribute simd | |
- // | simd | target parallel | |
- // | | for simd | |
- // +------------------+-----------------+------------------------------------+
- // | for simd | parallel | |
- // | for simd | for | |
- // | for simd | for simd | |
- // | for simd | master | |
- // | for simd | critical | |
- // | for simd | simd | * |
- // | for simd | sections | |
- // | for simd | section | |
- // | for simd | single | |
- // | for simd | parallel for | |
- // | for simd |parallel for simd| |
- // | for simd |parallel sections| |
- // | for simd | task | |
- // | for simd | taskyield | |
- // | for simd | barrier | |
- // | for simd | taskwait | |
- // | for simd | taskgroup | |
- // | for simd | flush | |
- // | for simd | ordered | + (with simd clause) |
- // | for simd | atomic | |
- // | for simd | target | |
- // | for simd | target parallel | |
- // | for simd | target parallel | |
- // | | for | |
- // | for simd | target enter | |
- // | | data | |
- // | for simd | target exit | |
- // | | data | |
- // | for simd | teams | |
- // | for simd | cancellation | |
- // | | point | |
- // | for simd | cancel | |
- // | for simd | taskloop | |
- // | for simd | taskloop simd | |
- // | for simd | distribute | |
- // | for simd | distribute | |
- // | | parallel for | |
- // | for simd | distribute | |
- // | |parallel for simd| |
- // | for simd | distribute simd | |
- // | for simd | target parallel | |
- // | | for simd | |
- // +------------------+-----------------+------------------------------------+
- // | parallel for simd| parallel | |
- // | parallel for simd| for | |
- // | parallel for simd| for simd | |
- // | parallel for simd| master | |
- // | parallel for simd| critical | |
- // | parallel for simd| simd | * |
- // | parallel for simd| sections | |
- // | parallel for simd| section | |
- // | parallel for simd| single | |
- // | parallel for simd| parallel for | |
- // | parallel for simd|parallel for simd| |
- // | parallel for simd|parallel sections| |
- // | parallel for simd| task | |
- // | parallel for simd| taskyield | |
- // | parallel for simd| barrier | |
- // | parallel for simd| taskwait | |
- // | parallel for simd| taskgroup | |
- // | parallel for simd| flush | |
- // | parallel for simd| ordered | + (with simd clause) |
- // | parallel for simd| atomic | |
- // | parallel for simd| target | |
- // | parallel for simd| target parallel | |
- // | parallel for simd| target parallel | |
- // | | for | |
- // | parallel for simd| target enter | |
- // | | data | |
- // | parallel for simd| target exit | |
- // | | data | |
- // | parallel for simd| teams | |
- // | parallel for simd| cancellation | |
- // | | point | |
- // | parallel for simd| cancel | |
- // | parallel for simd| taskloop | |
- // | parallel for simd| taskloop simd | |
- // | parallel for simd| distribute | |
- // | parallel for simd| distribute | |
- // | | parallel for | |
- // | parallel for simd| distribute | |
- // | |parallel for simd| |
- // | parallel for simd| distribute simd | |
- // | | for simd | |
- // +------------------+-----------------+------------------------------------+
- // | sections | parallel | * |
- // | sections | for | + |
- // | sections | for simd | + |
- // | sections | master | + |
- // | sections | critical | * |
- // | sections | simd | * |
- // | sections | sections | + |
- // | sections | section | * |
- // | sections | single | + |
- // | sections | parallel for | * |
- // | sections |parallel for simd| * |
- // | sections |parallel sections| * |
- // | sections | task | * |
- // | sections | taskyield | * |
- // | sections | barrier | + |
- // | sections | taskwait | * |
- // | sections | taskgroup | * |
- // | sections | flush | * |
- // | sections | ordered | + |
- // | sections | atomic | * |
- // | sections | target | * |
- // | sections | target parallel | * |
- // | sections | target parallel | * |
- // | | for | |
- // | sections | target enter | * |
- // | | data | |
- // | sections | target exit | * |
- // | | data | |
- // | sections | teams | + |
- // | sections | cancellation | |
- // | | point | ! |
- // | sections | cancel | ! |
- // | sections | taskloop | * |
- // | sections | taskloop simd | * |
- // | sections | distribute | + |
- // | sections | distribute | + |
- // | | parallel for | |
- // | sections | distribute | + |
- // | |parallel for simd| |
- // | sections | distribute simd | + |
- // | sections | target parallel | + |
- // | | for simd | |
- // +------------------+-----------------+------------------------------------+
- // | section | parallel | * |
- // | section | for | + |
- // | section | for simd | + |
- // | section | master | + |
- // | section | critical | * |
- // | section | simd | * |
- // | section | sections | + |
- // | section | section | + |
- // | section | single | + |
- // | section | parallel for | * |
- // | section |parallel for simd| * |
- // | section |parallel sections| * |
- // | section | task | * |
- // | section | taskyield | * |
- // | section | barrier | + |
- // | section | taskwait | * |
- // | section | taskgroup | * |
- // | section | flush | * |
- // | section | ordered | + |
- // | section | atomic | * |
- // | section | target | * |
- // | section | target parallel | * |
- // | section | target parallel | * |
- // | | for | |
- // | section | target enter | * |
- // | | data | |
- // | section | target exit | * |
- // | | data | |
- // | section | teams | + |
- // | section | cancellation | |
- // | | point | ! |
- // | section | cancel | ! |
- // | section | taskloop | * |
- // | section | taskloop simd | * |
- // | section | distribute | + |
- // | section | distribute | + |
- // | | parallel for | |
- // | section | distribute | + |
- // | |parallel for simd| |
- // | section | distribute simd | + |
- // | section | target parallel | + |
- // | | for simd | |
- // +------------------+-----------------+------------------------------------+
- // | single | parallel | * |
- // | single | for | + |
- // | single | for simd | + |
- // | single | master | + |
- // | single | critical | * |
- // | single | simd | * |
- // | single | sections | + |
- // | single | section | + |
- // | single | single | + |
- // | single | parallel for | * |
- // | single |parallel for simd| * |
- // | single |parallel sections| * |
- // | single | task | * |
- // | single | taskyield | * |
- // | single | barrier | + |
- // | single | taskwait | * |
- // | single | taskgroup | * |
- // | single | flush | * |
- // | single | ordered | + |
- // | single | atomic | * |
- // | single | target | * |
- // | single | target parallel | * |
- // | single | target parallel | * |
- // | | for | |
- // | single | target enter | * |
- // | | data | |
- // | single | target exit | * |
- // | | data | |
- // | single | teams | + |
- // | single | cancellation | |
- // | | point | |
- // | single | cancel | |
- // | single | taskloop | * |
- // | single | taskloop simd | * |
- // | single | distribute | + |
- // | single | distribute | + |
- // | | parallel for | |
- // | single | distribute | + |
- // | |parallel for simd| |
- // | single | distribute simd | + |
- // | single | target parallel | + |
- // | | for simd | |
- // +------------------+-----------------+------------------------------------+
- // | parallel for | parallel | * |
- // | parallel for | for | + |
- // | parallel for | for simd | + |
- // | parallel for | master | + |
- // | parallel for | critical | * |
- // | parallel for | simd | * |
- // | parallel for | sections | + |
- // | parallel for | section | + |
- // | parallel for | single | + |
- // | parallel for | parallel for | * |
- // | parallel for |parallel for simd| * |
- // | parallel for |parallel sections| * |
- // | parallel for | task | * |
- // | parallel for | taskyield | * |
- // | parallel for | barrier | + |
- // | parallel for | taskwait | * |
- // | parallel for | taskgroup | * |
- // | parallel for | flush | * |
- // | parallel for | ordered | * (if construct is ordered) |
- // | parallel for | atomic | * |
- // | parallel for | target | * |
- // | parallel for | target parallel | * |
- // | parallel for | target parallel | * |
- // | | for | |
- // | parallel for | target enter | * |
- // | | data | |
- // | parallel for | target exit | * |
- // | | data | |
- // | parallel for | teams | + |
- // | parallel for | cancellation | |
- // | | point | ! |
- // | parallel for | cancel | ! |
- // | parallel for | taskloop | * |
- // | parallel for | taskloop simd | * |
- // | parallel for | distribute | + |
- // | parallel for | distribute | + |
- // | | parallel for | |
- // | parallel for | distribute | + |
- // | |parallel for simd| |
- // | parallel for | distribute simd | + |
- // | parallel for | target parallel | + |
- // | | for simd | |
- // +------------------+-----------------+------------------------------------+
- // | parallel sections| parallel | * |
- // | parallel sections| for | + |
- // | parallel sections| for simd | + |
- // | parallel sections| master | + |
- // | parallel sections| critical | + |
- // | parallel sections| simd | * |
- // | parallel sections| sections | + |
- // | parallel sections| section | * |
- // | parallel sections| single | + |
- // | parallel sections| parallel for | * |
- // | parallel sections|parallel for simd| * |
- // | parallel sections|parallel sections| * |
- // | parallel sections| task | * |
- // | parallel sections| taskyield | * |
- // | parallel sections| barrier | + |
- // | parallel sections| taskwait | * |
- // | parallel sections| taskgroup | * |
- // | parallel sections| flush | * |
- // | parallel sections| ordered | + |
- // | parallel sections| atomic | * |
- // | parallel sections| target | * |
- // | parallel sections| target parallel | * |
- // | parallel sections| target parallel | * |
- // | | for | |
- // | parallel sections| target enter | * |
- // | | data | |
- // | parallel sections| target exit | * |
- // | | data | |
- // | parallel sections| teams | + |
- // | parallel sections| cancellation | |
- // | | point | ! |
- // | parallel sections| cancel | ! |
- // | parallel sections| taskloop | * |
- // | parallel sections| taskloop simd | * |
- // | parallel sections| distribute | + |
- // | parallel sections| distribute | + |
- // | | parallel for | |
- // | parallel sections| distribute | + |
- // | |parallel for simd| |
- // | parallel sections| distribute simd | + |
- // | parallel sections| target parallel | + |
- // | | for simd | |
- // +------------------+-----------------+------------------------------------+
- // | task | parallel | * |
- // | task | for | + |
- // | task | for simd | + |
- // | task | master | + |
- // | task | critical | * |
- // | task | simd | * |
- // | task | sections | + |
- // | task | section | + |
- // | task | single | + |
- // | task | parallel for | * |
- // | task |parallel for simd| * |
- // | task |parallel sections| * |
- // | task | task | * |
- // | task | taskyield | * |
- // | task | barrier | + |
- // | task | taskwait | * |
- // | task | taskgroup | * |
- // | task | flush | * |
- // | task | ordered | + |
- // | task | atomic | * |
- // | task | target | * |
- // | task | target parallel | * |
- // | task | target parallel | * |
- // | | for | |
- // | task | target enter | * |
- // | | data | |
- // | task | target exit | * |
- // | | data | |
- // | task | teams | + |
- // | task | cancellation | |
- // | | point | ! |
- // | task | cancel | ! |
- // | task | taskloop | * |
- // | task | taskloop simd | * |
- // | task | distribute | + |
- // | task | distribute | + |
- // | | parallel for | |
- // | task | distribute | + |
- // | |parallel for simd| |
- // | task | distribute simd | + |
- // | task | target parallel | + |
- // | | for simd | |
- // +------------------+-----------------+------------------------------------+
- // | ordered | parallel | * |
- // | ordered | for | + |
- // | ordered | for simd | + |
- // | ordered | master | * |
- // | ordered | critical | * |
- // | ordered | simd | * |
- // | ordered | sections | + |
- // | ordered | section | + |
- // | ordered | single | + |
- // | ordered | parallel for | * |
- // | ordered |parallel for simd| * |
- // | ordered |parallel sections| * |
- // | ordered | task | * |
- // | ordered | taskyield | * |
- // | ordered | barrier | + |
- // | ordered | taskwait | * |
- // | ordered | taskgroup | * |
- // | ordered | flush | * |
- // | ordered | ordered | + |
- // | ordered | atomic | * |
- // | ordered | target | * |
- // | ordered | target parallel | * |
- // | ordered | target parallel | * |
- // | | for | |
- // | ordered | target enter | * |
- // | | data | |
- // | ordered | target exit | * |
- // | | data | |
- // | ordered | teams | + |
- // | ordered | cancellation | |
- // | | point | |
- // | ordered | cancel | |
- // | ordered | taskloop | * |
- // | ordered | taskloop simd | * |
- // | ordered | distribute | + |
- // | ordered | distribute | + |
- // | | parallel for | |
- // | ordered | distribute | + |
- // | |parallel for simd| |
- // | ordered | distribute simd | + |
- // | ordered | target parallel | + |
- // | | for simd | |
- // +------------------+-----------------+------------------------------------+
- // | atomic | parallel | |
- // | atomic | for | |
- // | atomic | for simd | |
- // | atomic | master | |
- // | atomic | critical | |
- // | atomic | simd | |
- // | atomic | sections | |
- // | atomic | section | |
- // | atomic | single | |
- // | atomic | parallel for | |
- // | atomic |parallel for simd| |
- // | atomic |parallel sections| |
- // | atomic | task | |
- // | atomic | taskyield | |
- // | atomic | barrier | |
- // | atomic | taskwait | |
- // | atomic | taskgroup | |
- // | atomic | flush | |
- // | atomic | ordered | |
- // | atomic | atomic | |
- // | atomic | target | |
- // | atomic | target parallel | |
- // | atomic | target parallel | |
- // | | for | |
- // | atomic | target enter | |
- // | | data | |
- // | atomic | target exit | |
- // | | data | |
- // | atomic | teams | |
- // | atomic | cancellation | |
- // | | point | |
- // | atomic | cancel | |
- // | atomic | taskloop | |
- // | atomic | taskloop simd | |
- // | atomic | distribute | |
- // | atomic | distribute | |
- // | | parallel for | |
- // | atomic | distribute | |
- // | |parallel for simd| |
- // | atomic | distribute simd | |
- // | atomic | target parallel | |
- // | | for simd | |
- // +------------------+-----------------+------------------------------------+
- // | target | parallel | * |
- // | target | for | * |
- // | target | for simd | * |
- // | target | master | * |
- // | target | critical | * |
- // | target | simd | * |
- // | target | sections | * |
- // | target | section | * |
- // | target | single | * |
- // | target | parallel for | * |
- // | target |parallel for simd| * |
- // | target |parallel sections| * |
- // | target | task | * |
- // | target | taskyield | * |
- // | target | barrier | * |
- // | target | taskwait | * |
- // | target | taskgroup | * |
- // | target | flush | * |
- // | target | ordered | * |
- // | target | atomic | * |
- // | target | target | |
- // | target | target parallel | |
- // | target | target parallel | |
- // | | for | |
- // | target | target enter | |
- // | | data | |
- // | target | target exit | |
- // | | data | |
- // | target | teams | * |
- // | target | cancellation | |
- // | | point | |
- // | target | cancel | |
- // | target | taskloop | * |
- // | target | taskloop simd | * |
- // | target | distribute | + |
- // | target | distribute | + |
- // | | parallel for | |
- // | target | distribute | + |
- // | |parallel for simd| |
- // | target | distribute simd | + |
- // | target | target parallel | |
- // | | for simd | |
- // +------------------+-----------------+------------------------------------+
- // | target parallel | parallel | * |
- // | target parallel | for | * |
- // | target parallel | for simd | * |
- // | target parallel | master | * |
- // | target parallel | critical | * |
- // | target parallel | simd | * |
- // | target parallel | sections | * |
- // | target parallel | section | * |
- // | target parallel | single | * |
- // | target parallel | parallel for | * |
- // | target parallel |parallel for simd| * |
- // | target parallel |parallel sections| * |
- // | target parallel | task | * |
- // | target parallel | taskyield | * |
- // | target parallel | barrier | * |
- // | target parallel | taskwait | * |
- // | target parallel | taskgroup | * |
- // | target parallel | flush | * |
- // | target parallel | ordered | * |
- // | target parallel | atomic | * |
- // | target parallel | target | |
- // | target parallel | target parallel | |
- // | target parallel | target parallel | |
- // | | for | |
- // | target parallel | target enter | |
- // | | data | |
- // | target parallel | target exit | |
- // | | data | |
- // | target parallel | teams | |
- // | target parallel | cancellation | |
- // | | point | ! |
- // | target parallel | cancel | ! |
- // | target parallel | taskloop | * |
- // | target parallel | taskloop simd | * |
- // | target parallel | distribute | |
- // | target parallel | distribute | |
- // | | parallel for | |
- // | target parallel | distribute | |
- // | |parallel for simd| |
- // | target parallel | distribute simd | |
- // | target parallel | target parallel | |
- // | | for simd | |
- // +------------------+-----------------+------------------------------------+
- // | target parallel | parallel | * |
- // | for | | |
- // | target parallel | for | * |
- // | for | | |
- // | target parallel | for simd | * |
- // | for | | |
- // | target parallel | master | * |
- // | for | | |
- // | target parallel | critical | * |
- // | for | | |
- // | target parallel | simd | * |
- // | for | | |
- // | target parallel | sections | * |
- // | for | | |
- // | target parallel | section | * |
- // | for | | |
- // | target parallel | single | * |
- // | for | | |
- // | target parallel | parallel for | * |
- // | for | | |
- // | target parallel |parallel for simd| * |
- // | for | | |
- // | target parallel |parallel sections| * |
- // | for | | |
- // | target parallel | task | * |
- // | for | | |
- // | target parallel | taskyield | * |
- // | for | | |
- // | target parallel | barrier | * |
- // | for | | |
- // | target parallel | taskwait | * |
- // | for | | |
- // | target parallel | taskgroup | * |
- // | for | | |
- // | target parallel | flush | * |
- // | for | | |
- // | target parallel | ordered | * |
- // | for | | |
- // | target parallel | atomic | * |
- // | for | | |
- // | target parallel | target | |
- // | for | | |
- // | target parallel | target parallel | |
- // | for | | |
- // | target parallel | target parallel | |
- // | for | for | |
- // | target parallel | target enter | |
- // | for | data | |
- // | target parallel | target exit | |
- // | for | data | |
- // | target parallel | teams | |
- // | for | | |
- // | target parallel | cancellation | |
- // | for | point | ! |
- // | target parallel | cancel | ! |
- // | for | | |
- // | target parallel | taskloop | * |
- // | for | | |
- // | target parallel | taskloop simd | * |
- // | for | | |
- // | target parallel | distribute | |
- // | for | | |
- // | target parallel | distribute | |
- // | for | parallel for | |
- // | target parallel | distribute | |
- // | for |parallel for simd| |
- // | target parallel | distribute simd | |
- // | for | | |
- // | target parallel | target parallel | |
- // | for | for simd | |
- // +------------------+-----------------+------------------------------------+
- // | teams | parallel | * |
- // | teams | for | + |
- // | teams | for simd | + |
- // | teams | master | + |
- // | teams | critical | + |
- // | teams | simd | + |
- // | teams | sections | + |
- // | teams | section | + |
- // | teams | single | + |
- // | teams | parallel for | * |
- // | teams |parallel for simd| * |
- // | teams |parallel sections| * |
- // | teams | task | + |
- // | teams | taskyield | + |
- // | teams | barrier | + |
- // | teams | taskwait | + |
- // | teams | taskgroup | + |
- // | teams | flush | + |
- // | teams | ordered | + |
- // | teams | atomic | + |
- // | teams | target | + |
- // | teams | target parallel | + |
- // | teams | target parallel | + |
- // | | for | |
- // | teams | target enter | + |
- // | | data | |
- // | teams | target exit | + |
- // | | data | |
- // | teams | teams | + |
- // | teams | cancellation | |
- // | | point | |
- // | teams | cancel | |
- // | teams | taskloop | + |
- // | teams | taskloop simd | + |
- // | teams | distribute | ! |
- // | teams | distribute | ! |
- // | | parallel for | |
- // | teams | distribute | ! |
- // | |parallel for simd| |
- // | teams | distribute simd | ! |
- // | teams | target parallel | + |
- // | | for simd | |
- // +------------------+-----------------+------------------------------------+
- // | taskloop | parallel | * |
- // | taskloop | for | + |
- // | taskloop | for simd | + |
- // | taskloop | master | + |
- // | taskloop | critical | * |
- // | taskloop | simd | * |
- // | taskloop | sections | + |
- // | taskloop | section | + |
- // | taskloop | single | + |
- // | taskloop | parallel for | * |
- // | taskloop |parallel for simd| * |
- // | taskloop |parallel sections| * |
- // | taskloop | task | * |
- // | taskloop | taskyield | * |
- // | taskloop | barrier | + |
- // | taskloop | taskwait | * |
- // | taskloop | taskgroup | * |
- // | taskloop | flush | * |
- // | taskloop | ordered | + |
- // | taskloop | atomic | * |
- // | taskloop | target | * |
- // | taskloop | target parallel | * |
- // | taskloop | target parallel | * |
- // | | for | |
- // | taskloop | target enter | * |
- // | | data | |
- // | taskloop | target exit | * |
- // | | data | |
- // | taskloop | teams | + |
- // | taskloop | cancellation | |
- // | | point | |
- // | taskloop | cancel | |
- // | taskloop | taskloop | * |
- // | taskloop | distribute | + |
- // | taskloop | distribute | + |
- // | | parallel for | |
- // | taskloop | distribute | + |
- // | |parallel for simd| |
- // | taskloop | distribute simd | + |
- // | taskloop | target parallel | * |
- // | | for simd | |
- // +------------------+-----------------+------------------------------------+
- // | taskloop simd | parallel | |
- // | taskloop simd | for | |
- // | taskloop simd | for simd | |
- // | taskloop simd | master | |
- // | taskloop simd | critical | |
- // | taskloop simd | simd | * |
- // | taskloop simd | sections | |
- // | taskloop simd | section | |
- // | taskloop simd | single | |
- // | taskloop simd | parallel for | |
- // | taskloop simd |parallel for simd| |
- // | taskloop simd |parallel sections| |
- // | taskloop simd | task | |
- // | taskloop simd | taskyield | |
- // | taskloop simd | barrier | |
- // | taskloop simd | taskwait | |
- // | taskloop simd | taskgroup | |
- // | taskloop simd | flush | |
- // | taskloop simd | ordered | + (with simd clause) |
- // | taskloop simd | atomic | |
- // | taskloop simd | target | |
- // | taskloop simd | target parallel | |
- // | taskloop simd | target parallel | |
- // | | for | |
- // | taskloop simd | target enter | |
- // | | data | |
- // | taskloop simd | target exit | |
- // | | data | |
- // | taskloop simd | teams | |
- // | taskloop simd | cancellation | |
- // | | point | |
- // | taskloop simd | cancel | |
- // | taskloop simd | taskloop | |
- // | taskloop simd | taskloop simd | |
- // | taskloop simd | distribute | |
- // | taskloop simd | distribute | |
- // | | parallel for | |
- // | taskloop simd | distribute | |
- // | |parallel for simd| |
- // | taskloop simd | distribute simd | |
- // | taskloop simd | target parallel | |
- // | | for simd | |
- // +------------------+-----------------+------------------------------------+
- // | distribute | parallel | * |
- // | distribute | for | * |
- // | distribute | for simd | * |
- // | distribute | master | * |
- // | distribute | critical | * |
- // | distribute | simd | * |
- // | distribute | sections | * |
- // | distribute | section | * |
- // | distribute | single | * |
- // | distribute | parallel for | * |
- // | distribute |parallel for simd| * |
- // | distribute |parallel sections| * |
- // | distribute | task | * |
- // | distribute | taskyield | * |
- // | distribute | barrier | * |
- // | distribute | taskwait | * |
- // | distribute | taskgroup | * |
- // | distribute | flush | * |
- // | distribute | ordered | + |
- // | distribute | atomic | * |
- // | distribute | target | |
- // | distribute | target parallel | |
- // | distribute | target parallel | |
- // | | for | |
- // | distribute | target enter | |
- // | | data | |
- // | distribute | target exit | |
- // | | data | |
- // | distribute | teams | |
- // | distribute | cancellation | + |
- // | | point | |
- // | distribute | cancel | + |
- // | distribute | taskloop | * |
- // | distribute | taskloop simd | * |
- // | distribute | distribute | |
- // | distribute | distribute | |
- // | | parallel for | |
- // | distribute | distribute | |
- // | |parallel for simd| |
- // | distribute | distribute simd | |
- // | distribute | target parallel | |
- // | | for simd | |
- // +------------------+-----------------+------------------------------------+
- // | distribute | parallel | * |
- // | parallel for | | |
- // | distribute | for | * |
- // | parallel for | | |
- // | distribute | for simd | * |
- // | parallel for | | |
- // | distribute | master | * |
- // | parallel for | | |
- // | distribute | critical | * |
- // | parallel for | | |
- // | distribute | simd | * |
- // | parallel for | | |
- // | distribute | sections | * |
- // | parallel for | | |
- // | distribute | section | * |
- // | parallel for | | |
- // | distribute | single | * |
- // | parallel for | | |
- // | distribute | parallel for | * |
- // | parallel for | | |
- // | distribute |parallel for simd| * |
- // | parallel for | | |
- // | distribute |parallel sections| * |
- // | parallel for | | |
- // | distribute | task | * |
- // | parallel for | | |
- // | parallel for | | |
- // | distribute | taskyield | * |
- // | parallel for | | |
- // | distribute | barrier | * |
- // | parallel for | | |
- // | distribute | taskwait | * |
- // | parallel for | | |
- // | distribute | taskgroup | * |
- // | parallel for | | |
- // | distribute | flush | * |
- // | parallel for | | |
- // | distribute | ordered | + |
- // | parallel for | | |
- // | distribute | atomic | * |
- // | parallel for | | |
- // | distribute | target | |
- // | parallel for | | |
- // | distribute | target parallel | |
- // | parallel for | | |
- // | distribute | target parallel | |
- // | parallel for | for | |
- // | distribute | target enter | |
- // | parallel for | data | |
- // | distribute | target exit | |
- // | parallel for | data | |
- // | distribute | teams | |
- // | parallel for | | |
- // | distribute | cancellation | + |
- // | parallel for | point | |
- // | distribute | cancel | + |
- // | parallel for | | |
- // | distribute | taskloop | * |
- // | parallel for | | |
- // | distribute | taskloop simd | * |
- // | parallel for | | |
- // | distribute | distribute | |
- // | parallel for | | |
- // | distribute | distribute | |
- // | parallel for | parallel for | |
- // | distribute | distribute | |
- // | parallel for |parallel for simd| |
- // | distribute | distribute simd | |
- // | parallel for | | |
- // | distribute | target parallel | |
- // | parallel for | for simd | |
- // +------------------+-----------------+------------------------------------+
- // | distribute | parallel | * |
- // | parallel for simd| | |
- // | distribute | for | * |
- // | parallel for simd| | |
- // | distribute | for simd | * |
- // | parallel for simd| | |
- // | distribute | master | * |
- // | parallel for simd| | |
- // | distribute | critical | * |
- // | parallel for simd| | |
- // | distribute | simd | * |
- // | parallel for simd| | |
- // | distribute | sections | * |
- // | parallel for simd| | |
- // | distribute | section | * |
- // | parallel for simd| | |
- // | distribute | single | * |
- // | parallel for simd| | |
- // | distribute | parallel for | * |
- // | parallel for simd| | |
- // | distribute |parallel for simd| * |
- // | parallel for simd| | |
- // | distribute |parallel sections| * |
- // | parallel for simd| | |
- // | distribute | task | * |
- // | parallel for simd| | |
- // | distribute | taskyield | * |
- // | parallel for simd| | |
- // | distribute | barrier | * |
- // | parallel for simd| | |
- // | distribute | taskwait | * |
- // | parallel for simd| | |
- // | distribute | taskgroup | * |
- // | parallel for simd| | |
- // | distribute | flush | * |
- // | parallel for simd| | |
- // | distribute | ordered | + |
- // | parallel for simd| | |
- // | distribute | atomic | * |
- // | parallel for simd| | |
- // | distribute | target | |
- // | parallel for simd| | |
- // | distribute | target parallel | |
- // | parallel for simd| | |
- // | distribute | target parallel | |
- // | parallel for simd| for | |
- // | distribute | target enter | |
- // | parallel for simd| data | |
- // | distribute | target exit | |
- // | parallel for simd| data | |
- // | distribute | teams | |
- // | parallel for simd| | |
- // | distribute | cancellation | + |
- // | parallel for simd| point | |
- // | distribute | cancel | + |
- // | parallel for simd| | |
- // | distribute | taskloop | * |
- // | parallel for simd| | |
- // | distribute | taskloop simd | * |
- // | parallel for simd| | |
- // | distribute | distribute | |
- // | parallel for simd| | |
- // | distribute | distribute | * |
- // | parallel for simd| parallel for | |
- // | distribute | distribute | * |
- // | parallel for simd|parallel for simd| |
- // | distribute | distribute simd | * |
- // | parallel for simd| | |
- // | distribute | target parallel | |
- // | parallel for simd| for simd | |
- // +------------------+-----------------+------------------------------------+
- // | distribute simd | parallel | * |
- // | distribute simd | for | * |
- // | distribute simd | for simd | * |
- // | distribute simd | master | * |
- // | distribute simd | critical | * |
- // | distribute simd | simd | * |
- // | distribute simd | sections | * |
- // | distribute simd | section | * |
- // | distribute simd | single | * |
- // | distribute simd | parallel for | * |
- // | distribute simd |parallel for simd| * |
- // | distribute simd |parallel sections| * |
- // | distribute simd | task | * |
- // | distribute simd | taskyield | * |
- // | distribute simd | barrier | * |
- // | distribute simd | taskwait | * |
- // | distribute simd | taskgroup | * |
- // | distribute simd | flush | * |
- // | distribute simd | ordered | + |
- // | distribute simd | atomic | * |
- // | distribute simd | target | * |
- // | distribute simd | target parallel | * |
- // | distribute simd | target parallel | * |
- // | | for | |
- // | distribute simd | target enter | * |
- // | | data | |
- // | distribute simd | target exit | * |
- // | | data | |
- // | distribute simd | teams | * |
- // | distribute simd | cancellation | + |
- // | | point | |
- // | distribute simd | cancel | + |
- // | distribute simd | taskloop | * |
- // | distribute simd | taskloop simd | * |
- // | distribute simd | distribute | |
- // | distribute simd | distribute | * |
- // | | parallel for | |
- // | distribute simd | distribute | * |
- // | |parallel for simd| |
- // | distribute simd | distribute simd | * |
- // | distribute simd | target parallel | * |
- // | | for simd | |
- // +------------------+-----------------+------------------------------------+
- // | target parallel | parallel | * |
- // | for simd | | |
- // | target parallel | for | * |
- // | for simd | | |
- // | target parallel | for simd | * |
- // | for simd | | |
- // | target parallel | master | * |
- // | for simd | | |
- // | target parallel | critical | * |
- // | for simd | | |
- // | target parallel | simd | ! |
- // | for simd | | |
- // | target parallel | sections | * |
- // | for simd | | |
- // | target parallel | section | * |
- // | for simd | | |
- // | target parallel | single | * |
- // | for simd | | |
- // | target parallel | parallel for | * |
- // | for simd | | |
- // | target parallel |parallel for simd| * |
- // | for simd | | |
- // | target parallel |parallel sections| * |
- // | for simd | | |
- // | target parallel | task | * |
- // | for simd | | |
- // | target parallel | taskyield | * |
- // | for simd | | |
- // | target parallel | barrier | * |
- // | for simd | | |
- // | target parallel | taskwait | * |
- // | for simd | | |
- // | target parallel | taskgroup | * |
- // | for simd | | |
- // | target parallel | flush | * |
- // | for simd | | |
- // | target parallel | ordered | + (with simd clause) |
- // | for simd | | |
- // | target parallel | atomic | * |
- // | for simd | | |
- // | target parallel | target | * |
- // | for simd | | |
- // | target parallel | target parallel | * |
- // | for simd | | |
- // | target parallel | target parallel | * |
- // | for simd | for | |
- // | target parallel | target enter | * |
- // | for simd | data | |
- // | target parallel | target exit | * |
- // | for simd | data | |
- // | target parallel | teams | * |
- // | for simd | | |
- // | target parallel | cancellation | * |
- // | for simd | point | |
- // | target parallel | cancel | * |
- // | for simd | | |
- // | target parallel | taskloop | * |
- // | for simd | | |
- // | target parallel | taskloop simd | * |
- // | for simd | | |
- // | target parallel | distribute | * |
- // | for simd | | |
- // | target parallel | distribute | * |
- // | for simd | parallel for | |
- // | target parallel | distribute | * |
- // | for simd |parallel for simd| |
- // | target parallel | distribute simd | * |
- // | for simd | | |
- // | target parallel | target parallel | * |
- // | for simd | for simd | |
- // +------------------+-----------------+------------------------------------+
if (Stack->getCurScope()) {
auto ParentRegion = Stack->getParentDirective();
auto OffendingRegion = ParentRegion;
bool NestingProhibited = false;
bool CloseNesting = true;
+ bool OrphanSeen = false;
enum {
NoRecommend,
ShouldBeInParallelRegion,
@@ -3116,7 +1903,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// OpenMP [2.8.1,simd Construct, Restrictions]
// An ordered construct with the simd clause is the only OpenMP
// construct that can appear in the simd region.
- // Allowing a SIMD consruct nested in another SIMD construct is an
+ // Allowing a SIMD construct nested in another SIMD construct is an
// extension. The OpenMP 4.5 spec does not allow it. Issue a warning
// message.
SemaRef.Diag(StartLoc, (CurrentRegion != OMPD_simd)
@@ -3144,9 +1931,11 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
}
return false;
}
- // Allow some constructs to be orphaned (they could be used in functions,
- // called from OpenMP regions with the required preconditions).
- if (ParentRegion == OMPD_unknown)
+ // Allow some constructs (except teams) to be orphaned (they could be
+ // used in functions, called from OpenMP regions with the required
+ // preconditions).
+ if (ParentRegion == OMPD_unknown &&
+ !isOpenMPNestingTeamsDirective(CurrentRegion))
return false;
if (CurrentRegion == OMPD_cancellation_point ||
CurrentRegion == OMPD_cancel) {
@@ -3184,20 +1973,17 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// critical region with the same name. Note that this restriction is not
// sufficient to prevent deadlock.
SourceLocation PreviousCriticalLoc;
- bool DeadLock =
- Stack->hasDirective([CurrentName, &PreviousCriticalLoc](
- OpenMPDirectiveKind K,
- const DeclarationNameInfo &DNI,
- SourceLocation Loc)
- ->bool {
- if (K == OMPD_critical &&
- DNI.getName() == CurrentName.getName()) {
- PreviousCriticalLoc = Loc;
- return true;
- } else
- return false;
- },
- false /* skip top directive */);
+ bool DeadLock = Stack->hasDirective(
+ [CurrentName, &PreviousCriticalLoc](OpenMPDirectiveKind K,
+ const DeclarationNameInfo &DNI,
+ SourceLocation Loc) -> bool {
+ if (K == OMPD_critical && DNI.getName() == CurrentName.getName()) {
+ PreviousCriticalLoc = Loc;
+ return true;
+ } else
+ return false;
+ },
+ false /* skip top directive */);
if (DeadLock) {
SemaRef.Diag(StartLoc,
diag::err_omp_prohibited_region_critical_same_name)
@@ -3217,7 +2003,8 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
ParentRegion == OMPD_critical ||
ParentRegion == OMPD_ordered;
} else if (isOpenMPWorksharingDirective(CurrentRegion) &&
- !isOpenMPParallelDirective(CurrentRegion)) {
+ !isOpenMPParallelDirective(CurrentRegion) &&
+ !isOpenMPTeamsDirective(CurrentRegion)) {
// OpenMP [2.16, Nesting of Regions]
// A worksharing region may not be closely nested inside a worksharing,
// explicit task, critical, ordered, atomic, or master region.
@@ -3241,15 +2028,19 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
!(isOpenMPSimdDirective(ParentRegion) ||
Stack->isParentOrderedRegion());
Recommend = ShouldBeInOrderedRegion;
- } else if (isOpenMPTeamsDirective(CurrentRegion)) {
+ } else if (isOpenMPNestingTeamsDirective(CurrentRegion)) {
// OpenMP [2.16, Nesting of Regions]
// If specified, a teams construct must be contained within a target
// construct.
NestingProhibited = ParentRegion != OMPD_target;
+ OrphanSeen = ParentRegion == OMPD_unknown;
Recommend = ShouldBeInTargetRegion;
Stack->setParentTeamsRegionLoc(Stack->getConstructLoc());
}
- if (!NestingProhibited && isOpenMPTeamsDirective(ParentRegion)) {
+ if (!NestingProhibited &&
+ !isOpenMPTargetExecutionDirective(CurrentRegion) &&
+ !isOpenMPTargetDataManagementDirective(CurrentRegion) &&
+ (ParentRegion == OMPD_teams || ParentRegion == OMPD_target_teams)) {
// OpenMP [2.16, Nesting of Regions]
// distribute, parallel, parallel sections, parallel workshare, and the
// parallel loop and parallel loop SIMD constructs are the only OpenMP
@@ -3258,11 +2049,13 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
!isOpenMPDistributeDirective(CurrentRegion);
Recommend = ShouldBeInParallelRegion;
}
- if (!NestingProhibited && isOpenMPDistributeDirective(CurrentRegion)) {
+ if (!NestingProhibited &&
+ isOpenMPNestingDistributeDirective(CurrentRegion)) {
// OpenMP 4.5 [2.17 Nesting of Regions]
// The region associated with the distribute construct must be strictly
// nested inside a teams region
- NestingProhibited = !isOpenMPTeamsDirective(ParentRegion);
+ NestingProhibited =
+ (ParentRegion != OMPD_teams && ParentRegion != OMPD_target_teams);
Recommend = ShouldBeInTeamsRegion;
}
if (!NestingProhibited &&
@@ -3285,9 +2078,14 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
CloseNesting = false;
}
if (NestingProhibited) {
- SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
- << CloseNesting << getOpenMPDirectiveName(OffendingRegion)
- << Recommend << getOpenMPDirectiveName(CurrentRegion);
+ if (OrphanSeen) {
+ SemaRef.Diag(StartLoc, diag::err_omp_orphaned_device_directive)
+ << getOpenMPDirectiveName(CurrentRegion) << Recommend;
+ } else {
+ SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
+ << CloseNesting << getOpenMPDirectiveName(OffendingRegion)
+ << Recommend << getOpenMPDirectiveName(CurrentRegion);
+ }
return true;
}
}
@@ -3602,6 +2400,45 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
AllowedNameModifiers.push_back(OMPD_target);
AllowedNameModifiers.push_back(OMPD_parallel);
break;
+ case OMPD_target_simd:
+ Res = ActOnOpenMPTargetSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
+ EndLoc, VarsWithInheritedDSA);
+ AllowedNameModifiers.push_back(OMPD_target);
+ break;
+ case OMPD_teams_distribute:
+ Res = ActOnOpenMPTeamsDistributeDirective(
+ ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
+ break;
+ case OMPD_teams_distribute_simd:
+ Res = ActOnOpenMPTeamsDistributeSimdDirective(
+ ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
+ break;
+ case OMPD_teams_distribute_parallel_for_simd:
+ Res = ActOnOpenMPTeamsDistributeParallelForSimdDirective(
+ ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
+ AllowedNameModifiers.push_back(OMPD_parallel);
+ break;
+ case OMPD_teams_distribute_parallel_for:
+ Res = ActOnOpenMPTeamsDistributeParallelForDirective(
+ ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
+ AllowedNameModifiers.push_back(OMPD_parallel);
+ break;
+ case OMPD_target_teams:
+ Res = ActOnOpenMPTargetTeamsDirective(ClausesWithImplicit, AStmt, StartLoc,
+ EndLoc);
+ AllowedNameModifiers.push_back(OMPD_target);
+ break;
+ case OMPD_target_teams_distribute:
+ Res = ActOnOpenMPTargetTeamsDistributeDirective(
+ ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
+ AllowedNameModifiers.push_back(OMPD_target);
+ break;
+ case OMPD_target_teams_distribute_parallel_for:
+ Res = ActOnOpenMPTargetTeamsDistributeParallelForDirective(
+ ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
+ AllowedNameModifiers.push_back(OMPD_target);
+ AllowedNameModifiers.push_back(OMPD_parallel);
+ break;
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_threadprivate:
@@ -3969,7 +2806,7 @@ public:
/// \brief Build reference expression to the private counter be used for
/// codegen.
Expr *BuildPrivateCounterVar() const;
- /// \brief Build initization of the counter be used for codegen.
+ /// \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;
@@ -4094,8 +2931,9 @@ bool OpenMPIterationSpaceChecker::SetStep(Expr *NewStep, bool Subtract) {
return true;
}
if (TestIsLessOp == Subtract) {
- NewStep = SemaRef.CreateBuiltinUnaryOp(NewStep->getExprLoc(), UO_Minus,
- NewStep).get();
+ NewStep =
+ SemaRef.CreateBuiltinUnaryOp(NewStep->getExprLoc(), UO_Minus, NewStep)
+ .get();
Subtract = !Subtract;
}
}
@@ -4127,7 +2965,7 @@ bool OpenMPIterationSpaceChecker::CheckInit(Stmt *S, bool EmitDiags) {
InitSrcRange = S->getSourceRange();
if (Expr *E = dyn_cast<Expr>(S))
S = E->IgnoreParens();
- if (auto BO = dyn_cast<BinaryOperator>(S)) {
+ if (auto *BO = dyn_cast<BinaryOperator>(S)) {
if (BO->getOpcode() == BO_Assign) {
auto *LHS = BO->getLHS()->IgnoreParens();
if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
@@ -4142,9 +2980,9 @@ bool OpenMPIterationSpaceChecker::CheckInit(Stmt *S, bool EmitDiags) {
return SetLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS());
}
}
- } else if (auto DS = dyn_cast<DeclStmt>(S)) {
+ } else if (auto *DS = dyn_cast<DeclStmt>(S)) {
if (DS->isSingleDecl()) {
- if (auto Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) {
+ if (auto *Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) {
if (Var->hasInit() && !Var->getType()->isReferenceType()) {
// Accept non-canonical init form here but emit ext. warning.
if (Var->getInitStyle() != VarDecl::CInit && EmitDiags)
@@ -4155,10 +2993,10 @@ bool OpenMPIterationSpaceChecker::CheckInit(Stmt *S, bool EmitDiags) {
}
}
}
- } else if (auto CE = dyn_cast<CXXOperatorCallExpr>(S)) {
+ } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
if (CE->getOperator() == OO_Equal) {
auto *LHS = CE->getArg(0);
- if (auto DRE = dyn_cast<DeclRefExpr>(LHS)) {
+ 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());
@@ -4220,7 +3058,7 @@ bool OpenMPIterationSpaceChecker::CheckCond(Expr *S) {
}
S = getExprAsWritten(S);
SourceLocation CondLoc = S->getLocStart();
- if (auto BO = dyn_cast<BinaryOperator>(S)) {
+ if (auto *BO = dyn_cast<BinaryOperator>(S)) {
if (BO->isRelationalOp()) {
if (GetInitLCDecl(BO->getLHS()) == LCDecl)
return SetUB(BO->getRHS(),
@@ -4233,7 +3071,7 @@ bool OpenMPIterationSpaceChecker::CheckCond(Expr *S) {
(BO->getOpcode() == BO_LT || BO->getOpcode() == BO_GT),
BO->getSourceRange(), BO->getOperatorLoc());
}
- } else if (auto CE = dyn_cast<CXXOperatorCallExpr>(S)) {
+ } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
if (CE->getNumArgs() == 2) {
auto Op = CE->getOperator();
switch (Op) {
@@ -4269,7 +3107,7 @@ bool OpenMPIterationSpaceChecker::CheckIncRHS(Expr *RHS) {
// var - incr
//
RHS = RHS->IgnoreParenImpCasts();
- if (auto BO = dyn_cast<BinaryOperator>(RHS)) {
+ if (auto *BO = dyn_cast<BinaryOperator>(RHS)) {
if (BO->isAdditiveOp()) {
bool IsAdd = BO->getOpcode() == BO_Add;
if (GetInitLCDecl(BO->getLHS()) == LCDecl)
@@ -4277,7 +3115,7 @@ bool OpenMPIterationSpaceChecker::CheckIncRHS(Expr *RHS) {
if (IsAdd && GetInitLCDecl(BO->getRHS()) == LCDecl)
return SetStep(BO->getLHS(), false);
}
- } else if (auto CE = dyn_cast<CXXOperatorCallExpr>(RHS)) {
+ } 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)
@@ -4317,14 +3155,15 @@ bool OpenMPIterationSpaceChecker::CheckInc(Expr *S) {
IncrementSrcRange = S->getSourceRange();
S = S->IgnoreParens();
- if (auto UO = dyn_cast<UnaryOperator>(S)) {
+ if (auto *UO = dyn_cast<UnaryOperator>(S)) {
if (UO->isIncrementDecrementOp() &&
GetInitLCDecl(UO->getSubExpr()) == LCDecl)
- return SetStep(
- SemaRef.ActOnIntegerConstant(UO->getLocStart(),
- (UO->isDecrementOp() ? -1 : 1)).get(),
- false);
- } else if (auto BO = dyn_cast<BinaryOperator>(S)) {
+ return SetStep(SemaRef
+ .ActOnIntegerConstant(UO->getLocStart(),
+ (UO->isDecrementOp() ? -1 : 1))
+ .get(),
+ false);
+ } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
switch (BO->getOpcode()) {
case BO_AddAssign:
case BO_SubAssign:
@@ -4338,16 +3177,17 @@ bool OpenMPIterationSpaceChecker::CheckInc(Expr *S) {
default:
break;
}
- } else if (auto CE = dyn_cast<CXXOperatorCallExpr>(S)) {
+ } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
switch (CE->getOperator()) {
case OO_PlusPlus:
case OO_MinusMinus:
if (GetInitLCDecl(CE->getArg(0)) == LCDecl)
- return SetStep(
- SemaRef.ActOnIntegerConstant(
- CE->getLocStart(),
- ((CE->getOperator() == OO_MinusMinus) ? -1 : 1)).get(),
- false);
+ return SetStep(SemaRef
+ .ActOnIntegerConstant(
+ CE->getLocStart(),
+ ((CE->getOperator() == OO_MinusMinus) ? -1 : 1))
+ .get(),
+ false);
break;
case OO_PlusEqual:
case OO_MinusEqual:
@@ -4544,7 +3384,7 @@ Expr *OpenMPIterationSpaceChecker::BuildPrivateCounterVar() const {
return nullptr;
}
-/// \brief Build initization of the counter be used for codegen.
+/// \brief 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.
@@ -4615,7 +3455,7 @@ static bool CheckOpenMPIterationSpace(
llvm::MapVector<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);
+ auto *For = dyn_cast_or_null<ForStmt>(S);
if (!For) {
SemaRef.Diag(S->getLocStart(), diag::err_omp_not_for)
<< (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr)
@@ -4855,8 +3695,7 @@ BuildCounterUpdate(Sema &SemaRef, Scope *S, SourceLocation Loc,
/// \brief 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;
@@ -5014,15 +3853,17 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
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)
+ 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)
+ 64 /* Bits */, SemaRef
+ .PerformImplicitConversion(
+ N0->IgnoreImpCasts(), N0->getType(),
+ Sema::AA_Converting, /*AllowExplicit=*/true)
.get(),
SemaRef);
@@ -5035,24 +3876,28 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
Scope *CurScope = DSA.getCurScope();
for (unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) {
if (PreCond.isUsable()) {
- PreCond = SemaRef.BuildBinOp(CurScope, SourceLocation(), BO_LAnd,
- PreCond.get(), IterSpaces[Cnt].PreCond);
+ PreCond =
+ SemaRef.BuildBinOp(CurScope, PreCond.get()->getExprLoc(), BO_LAnd,
+ PreCond.get(), IterSpaces[Cnt].PreCond);
}
auto N = IterSpaces[Cnt].NumIterations;
+ SourceLocation Loc = N->getExprLoc();
AllCountsNeedLessThan32Bits &= C.getTypeSize(N->getType()) < 32;
if (LastIteration32.isUsable())
LastIteration32 = SemaRef.BuildBinOp(
- CurScope, SourceLocation(), BO_Mul, LastIteration32.get(),
- SemaRef.PerformImplicitConversion(N->IgnoreImpCasts(), N->getType(),
- Sema::AA_Converting,
- /*AllowExplicit=*/true)
+ CurScope, Loc, BO_Mul, LastIteration32.get(),
+ SemaRef
+ .PerformImplicitConversion(N->IgnoreImpCasts(), N->getType(),
+ Sema::AA_Converting,
+ /*AllowExplicit=*/true)
.get());
if (LastIteration64.isUsable())
LastIteration64 = SemaRef.BuildBinOp(
- CurScope, SourceLocation(), BO_Mul, LastIteration64.get(),
- SemaRef.PerformImplicitConversion(N->IgnoreImpCasts(), N->getType(),
- Sema::AA_Converting,
- /*AllowExplicit=*/true)
+ CurScope, Loc, BO_Mul, LastIteration64.get(),
+ SemaRef
+ .PerformImplicitConversion(N->IgnoreImpCasts(), N->getType(),
+ Sema::AA_Converting,
+ /*AllowExplicit=*/true)
.get());
}
@@ -5083,7 +3928,8 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
ExprResult NumIterations = LastIteration;
{
LastIteration = SemaRef.BuildBinOp(
- CurScope, SourceLocation(), BO_Sub, LastIteration.get(),
+ CurScope, LastIteration.get()->getExprLoc(), BO_Sub,
+ LastIteration.get(),
SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
if (!LastIteration.isUsable())
return 0;
@@ -5102,7 +3948,7 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
// Prepare SaveRef + 1.
NumIterations = SemaRef.BuildBinOp(
- CurScope, SourceLocation(), BO_Add, SaveRef.get(),
+ CurScope, SaveRef.get()->getExprLoc(), BO_Add, SaveRef.get(),
SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
if (!NumIterations.isUsable())
return 0;
@@ -5110,7 +3956,7 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
SourceLocation InitLoc = IterSpaces[0].InitSrcRange.getBegin();
- // Build variables passed into runtime, nesessary for worksharing directives.
+ // Build variables passed into runtime, necessary for worksharing directives.
ExprResult LB, UB, IL, ST, EUB, PrevLB, PrevUB;
if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) ||
isOpenMPDistributeDirective(DKind)) {
@@ -5146,7 +3992,7 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
/*DirectInit*/ false, /*TypeMayContainAuto*/ false);
// Build expression: UB = min(UB, LastIteration)
- // It is nesessary for CodeGen of directives with static scheduling.
+ // It is necessary for CodeGen of directives with static scheduling.
ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, InitLoc, BO_GT,
UB.get(), LastIteration.get());
ExprResult CondOp = SemaRef.ActOnConditionalOp(
@@ -5187,11 +4033,11 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
{
VarDecl *IVDecl = buildVarDecl(SemaRef, InitLoc, RealVType, ".omp.iv");
IV = buildDeclRefExpr(SemaRef, IVDecl, RealVType, InitLoc);
- Expr *RHS = (isOpenMPWorksharingDirective(DKind) ||
- isOpenMPTaskLoopDirective(DKind) ||
- isOpenMPDistributeDirective(DKind))
- ? LB.get()
- : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
+ Expr *RHS =
+ (isOpenMPWorksharingDirective(DKind) ||
+ isOpenMPTaskLoopDirective(DKind) || isOpenMPDistributeDirective(DKind))
+ ? LB.get()
+ : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
Init = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), RHS);
Init = SemaRef.ActOnFinishFullExpr(Init.get());
}
@@ -5394,9 +4240,10 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
}
assert(I->second == OO_Plus || I->second == OO_Minus);
BinaryOperatorKind BOK = (I->second == OO_Plus) ? BO_Add : BO_Sub;
- UpCounterVal =
- SemaRef.BuildBinOp(CurScope, I->first->getExprLoc(), BOK,
- UpCounterVal, NormalizedOffset).get();
+ UpCounterVal = SemaRef
+ .BuildBinOp(CurScope, I->first->getExprLoc(), BOK,
+ UpCounterVal, NormalizedOffset)
+ .get();
}
Multiplier = *ILM;
++I;
@@ -5491,7 +4338,7 @@ StmtResult Sema::ActOnOpenMPSimdDirective(
if (!CurContext->isDependentContext()) {
// Finalize the clauses that need pre-built expressions for CodeGen.
for (auto C : Clauses) {
- if (auto LC = dyn_cast<OMPLinearClause>(C))
+ if (auto *LC = dyn_cast<OMPLinearClause>(C))
if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
B.NumIterations, *this, CurScope,
DSAStack))
@@ -5530,7 +4377,7 @@ StmtResult Sema::ActOnOpenMPForDirective(
if (!CurContext->isDependentContext()) {
// Finalize the clauses that need pre-built expressions for CodeGen.
for (auto C : Clauses) {
- if (auto LC = dyn_cast<OMPLinearClause>(C))
+ if (auto *LC = dyn_cast<OMPLinearClause>(C))
if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
B.NumIterations, *this, CurScope,
DSAStack))
@@ -5567,7 +4414,7 @@ StmtResult Sema::ActOnOpenMPForSimdDirective(
if (!CurContext->isDependentContext()) {
// Finalize the clauses that need pre-built expressions for CodeGen.
for (auto C : Clauses) {
- if (auto LC = dyn_cast<OMPLinearClause>(C))
+ if (auto *LC = dyn_cast<OMPLinearClause>(C))
if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
B.NumIterations, *this, CurScope,
DSAStack))
@@ -5592,9 +4439,9 @@ StmtResult Sema::ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses,
assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
auto BaseStmt = AStmt;
- while (CapturedStmt *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
+ while (auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
BaseStmt = CS->getCapturedStmt();
- if (auto C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
+ if (auto *C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
auto S = C->children();
if (S.begin() == S.end())
return StmtError();
@@ -5769,7 +4616,7 @@ StmtResult Sema::ActOnOpenMPParallelForDirective(
if (!CurContext->isDependentContext()) {
// Finalize the clauses that need pre-built expressions for CodeGen.
for (auto C : Clauses) {
- if (auto LC = dyn_cast<OMPLinearClause>(C))
+ if (auto *LC = dyn_cast<OMPLinearClause>(C))
if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
B.NumIterations, *this, CurScope,
DSAStack))
@@ -5811,7 +4658,7 @@ StmtResult Sema::ActOnOpenMPParallelForSimdDirective(
if (!CurContext->isDependentContext()) {
// Finalize the clauses that need pre-built expressions for CodeGen.
for (auto C : Clauses) {
- if (auto LC = dyn_cast<OMPLinearClause>(C))
+ if (auto *LC = dyn_cast<OMPLinearClause>(C))
if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
B.NumIterations, *this, CurScope,
DSAStack))
@@ -5836,9 +4683,9 @@ Sema::ActOnOpenMPParallelSectionsDirective(ArrayRef<OMPClause *> Clauses,
assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
auto BaseStmt = AStmt;
- while (CapturedStmt *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
+ while (auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
BaseStmt = CS->getCapturedStmt();
- if (auto C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
+ if (auto *C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
auto S = C->children();
if (S.begin() == S.end())
return StmtError();
@@ -5872,7 +4719,7 @@ StmtResult Sema::ActOnOpenMPTaskDirective(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.
@@ -6169,21 +5016,21 @@ bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId,
AtomicCompAssignOp->getOpcode());
OpLoc = AtomicCompAssignOp->getOperatorLoc();
E = AtomicCompAssignOp->getRHS();
- X = AtomicCompAssignOp->getLHS();
+ X = AtomicCompAssignOp->getLHS()->IgnoreParens();
IsXLHSInRHSPart = true;
} else if (auto *AtomicBinOp = dyn_cast<BinaryOperator>(
AtomicBody->IgnoreParenImpCasts())) {
// Check for Binary Operation
- if(checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
+ if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
return true;
- } else if (auto *AtomicUnaryOp =
- dyn_cast<UnaryOperator>(AtomicBody->IgnoreParenImpCasts())) {
+ } else if (auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
+ AtomicBody->IgnoreParenImpCasts())) {
// Check for Unary Operation
if (AtomicUnaryOp->isIncrementDecrementOp()) {
IsPostfixUpdate = AtomicUnaryOp->isPostfix();
Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
OpLoc = AtomicUnaryOp->getOperatorLoc();
- X = AtomicUnaryOp->getSubExpr();
+ X = AtomicUnaryOp->getSubExpr()->IgnoreParens();
E = SemaRef.ActOnIntegerConstant(OpLoc, /*uint64_t Val=*/1).get();
IsXLHSInRHSPart = true;
} else {
@@ -6243,7 +5090,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
if (!AStmt)
return StmtError();
- auto 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.
@@ -6311,8 +5158,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 (auto *AtomicBody = dyn_cast<Expr>(Body)) {
+ auto *AtomicBinOp =
dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
X = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
@@ -6373,8 +5220,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 (auto *AtomicBody = dyn_cast<Expr>(Body)) {
+ auto *AtomicBinOp =
dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
X = AtomicBinOp->getLHS();
@@ -6692,7 +5539,7 @@ StmtResult Sema::ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses,
if (auto *CS = dyn_cast<CompoundStmt>(S)) {
auto I = CS->body_begin();
while (I != CS->body_end()) {
- auto OED = dyn_cast<OMPExecutableDirective>(*I);
+ auto *OED = dyn_cast<OMPExecutableDirective>(*I);
if (!OED || !isOpenMPTeamsDirective(OED->getDirectiveKind())) {
OMPTeamsFound = false;
break;
@@ -6772,7 +5619,7 @@ StmtResult Sema::ActOnOpenMPTargetParallelForDirective(
if (!CurContext->isDependentContext()) {
// Finalize the clauses that need pre-built expressions for CodeGen.
for (auto C : Clauses) {
- if (auto LC = dyn_cast<OMPLinearClause>(C))
+ if (auto *LC = dyn_cast<OMPLinearClause>(C))
if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
B.NumIterations, *this, CurScope,
DSAStack))
@@ -6810,8 +5657,8 @@ StmtResult Sema::ActOnOpenMPTargetDataDirective(ArrayRef<OMPClause *> Clauses,
// OpenMP [2.10.1, Restrictions, p. 97]
// At least one map clause must appear on the directive.
if (!HasMapClause(Clauses)) {
- Diag(StartLoc, diag::err_omp_no_map_for_directive) <<
- getOpenMPDirectiveName(OMPD_target_data);
+ Diag(StartLoc, diag::err_omp_no_map_for_directive)
+ << getOpenMPDirectiveName(OMPD_target_data);
return StmtError();
}
@@ -7011,7 +5858,7 @@ StmtResult Sema::ActOnOpenMPTaskLoopSimdDirective(
if (!CurContext->isDependentContext()) {
// Finalize the clauses that need pre-built expressions for CodeGen.
for (auto C : Clauses) {
- if (auto LC = dyn_cast<OMPLinearClause>(C))
+ if (auto *LC = dyn_cast<OMPLinearClause>(C))
if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
B.NumIterations, *this, CurScope,
DSAStack))
@@ -7192,7 +6039,7 @@ StmtResult Sema::ActOnOpenMPTargetParallelForSimdDirective(
if (!CurContext->isDependentContext()) {
// Finalize the clauses that need pre-built expressions for CodeGen.
for (auto C : Clauses) {
- if (auto LC = dyn_cast<OMPLinearClause>(C))
+ if (auto *LC = dyn_cast<OMPLinearClause>(C))
if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
B.NumIterations, *this, CurScope,
DSAStack))
@@ -7207,6 +6054,327 @@ StmtResult Sema::ActOnOpenMPTargetParallelForSimdDirective(
Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
}
+StmtResult Sema::ActOnOpenMPTargetSimdDirective(
+ ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+ if (!AStmt)
+ return StmtError();
+
+ CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ // 1.2.2 OpenMP Language Terminology
+ // Structured block - An executable statement with a single entry at the
+ // top and a single exit at the bottom.
+ // The point of exit cannot be a branch out of the structured block.
+ // longjmp() and throw() must not violate the entry/exit criteria.
+ CS->getCapturedDecl()->setNothrow();
+
+ OMPLoopDirective::HelperExprs B;
+ // In presence of clause 'collapse' with number of loops, it will define the
+ // nested loops number.
+ unsigned NestedLoopCount =
+ CheckOpenMPLoop(OMPD_target_simd, getCollapseNumberExpr(Clauses),
+ getOrderedNumberExpr(Clauses), AStmt, *this, *DSAStack,
+ VarsWithImplicitDSA, B);
+ if (NestedLoopCount == 0)
+ return StmtError();
+
+ assert((CurContext->isDependentContext() || B.builtAll()) &&
+ "omp target simd loop exprs were not built");
+
+ if (!CurContext->isDependentContext()) {
+ // Finalize the clauses that need pre-built expressions for CodeGen.
+ for (auto C : Clauses) {
+ if (auto *LC = dyn_cast<OMPLinearClause>(C))
+ if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
+ B.NumIterations, *this, CurScope,
+ DSAStack))
+ return StmtError();
+ }
+ }
+
+ if (checkSimdlenSafelenSpecified(*this, Clauses))
+ return StmtError();
+
+ getCurFunction()->setHasBranchProtectedScope();
+ return 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) {
+ if (!AStmt)
+ return StmtError();
+
+ CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ // 1.2.2 OpenMP Language Terminology
+ // Structured block - An executable statement with a single entry at the
+ // top and a single exit at the bottom.
+ // The point of exit cannot be a branch out of the structured block.
+ // longjmp() and throw() must not violate the entry/exit criteria.
+ CS->getCapturedDecl()->setNothrow();
+
+ OMPLoopDirective::HelperExprs B;
+ // In presence of clause 'collapse' with number of loops, it will
+ // define the nested loops number.
+ unsigned NestedLoopCount =
+ CheckOpenMPLoop(OMPD_teams_distribute, getCollapseNumberExpr(Clauses),
+ nullptr /*ordered not a clause on distribute*/, AStmt,
+ *this, *DSAStack, VarsWithImplicitDSA, B);
+ if (NestedLoopCount == 0)
+ return StmtError();
+
+ assert((CurContext->isDependentContext() || B.builtAll()) &&
+ "omp teams distribute loop exprs were not built");
+
+ getCurFunction()->setHasBranchProtectedScope();
+ return OMPTeamsDistributeDirective::Create(
+ Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
+}
+
+StmtResult Sema::ActOnOpenMPTeamsDistributeSimdDirective(
+ ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+ if (!AStmt)
+ return StmtError();
+
+ CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ // 1.2.2 OpenMP Language Terminology
+ // Structured block - An executable statement with a single entry at the
+ // top and a single exit at the bottom.
+ // The point of exit cannot be a branch out of the structured block.
+ // longjmp() and throw() must not violate the entry/exit criteria.
+ CS->getCapturedDecl()->setNothrow();
+
+ OMPLoopDirective::HelperExprs B;
+ // In presence of clause 'collapse' with number of loops, it will
+ // define the nested loops number.
+ unsigned NestedLoopCount = CheckOpenMPLoop(
+ OMPD_teams_distribute_simd, getCollapseNumberExpr(Clauses),
+ nullptr /*ordered not a clause on distribute*/, AStmt, *this, *DSAStack,
+ VarsWithImplicitDSA, B);
+
+ if (NestedLoopCount == 0)
+ return StmtError();
+
+ assert((CurContext->isDependentContext() || B.builtAll()) &&
+ "omp teams distribute simd loop exprs were not built");
+
+ if (!CurContext->isDependentContext()) {
+ // Finalize the clauses that need pre-built expressions for CodeGen.
+ for (auto C : Clauses) {
+ if (auto *LC = dyn_cast<OMPLinearClause>(C))
+ if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
+ B.NumIterations, *this, CurScope,
+ DSAStack))
+ return StmtError();
+ }
+ }
+
+ if (checkSimdlenSafelenSpecified(*this, Clauses))
+ return StmtError();
+
+ getCurFunction()->setHasBranchProtectedScope();
+ return OMPTeamsDistributeSimdDirective::Create(
+ Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
+}
+
+StmtResult Sema::ActOnOpenMPTeamsDistributeParallelForSimdDirective(
+ ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+ if (!AStmt)
+ return StmtError();
+
+ CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ // 1.2.2 OpenMP Language Terminology
+ // Structured block - An executable statement with a single entry at the
+ // top and a single exit at the bottom.
+ // The point of exit cannot be a branch out of the structured block.
+ // longjmp() and throw() must not violate the entry/exit criteria.
+ CS->getCapturedDecl()->setNothrow();
+
+ OMPLoopDirective::HelperExprs B;
+ // In presence of clause 'collapse' with number of loops, it will
+ // define the nested loops number.
+ auto NestedLoopCount = CheckOpenMPLoop(
+ OMPD_teams_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
+ nullptr /*ordered not a clause on distribute*/, AStmt, *this, *DSAStack,
+ VarsWithImplicitDSA, B);
+
+ if (NestedLoopCount == 0)
+ return StmtError();
+
+ assert((CurContext->isDependentContext() || B.builtAll()) &&
+ "omp for loop exprs were not built");
+
+ if (!CurContext->isDependentContext()) {
+ // Finalize the clauses that need pre-built expressions for CodeGen.
+ for (auto C : Clauses) {
+ if (auto *LC = dyn_cast<OMPLinearClause>(C))
+ if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
+ B.NumIterations, *this, CurScope,
+ DSAStack))
+ return StmtError();
+ }
+ }
+
+ if (checkSimdlenSafelenSpecified(*this, Clauses))
+ return StmtError();
+
+ getCurFunction()->setHasBranchProtectedScope();
+ return OMPTeamsDistributeParallelForSimdDirective::Create(
+ Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
+}
+
+StmtResult Sema::ActOnOpenMPTeamsDistributeParallelForDirective(
+ ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+ if (!AStmt)
+ return StmtError();
+
+ CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ // 1.2.2 OpenMP Language Terminology
+ // Structured block - An executable statement with a single entry at the
+ // top and a single exit at the bottom.
+ // The point of exit cannot be a branch out of the structured block.
+ // longjmp() and throw() must not violate the entry/exit criteria.
+ CS->getCapturedDecl()->setNothrow();
+
+ OMPLoopDirective::HelperExprs B;
+ // In presence of clause 'collapse' with number of loops, it will
+ // define the nested loops number.
+ unsigned NestedLoopCount = CheckOpenMPLoop(
+ OMPD_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
+ nullptr /*ordered not a clause on distribute*/, AStmt, *this, *DSAStack,
+ VarsWithImplicitDSA, B);
+
+ if (NestedLoopCount == 0)
+ return StmtError();
+
+ assert((CurContext->isDependentContext() || B.builtAll()) &&
+ "omp for loop exprs were not built");
+
+ if (!CurContext->isDependentContext()) {
+ // Finalize the clauses that need pre-built expressions for CodeGen.
+ for (auto C : Clauses) {
+ if (auto *LC = dyn_cast<OMPLinearClause>(C))
+ if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
+ B.NumIterations, *this, CurScope,
+ DSAStack))
+ return StmtError();
+ }
+ }
+
+ getCurFunction()->setHasBranchProtectedScope();
+ return OMPTeamsDistributeParallelForDirective::Create(
+ Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
+}
+
+StmtResult Sema::ActOnOpenMPTargetTeamsDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ if (!AStmt)
+ return StmtError();
+
+ CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ // 1.2.2 OpenMP Language Terminology
+ // Structured block - An executable statement with a single entry at the
+ // top and a single exit at the bottom.
+ // The point of exit cannot be a branch out of the structured block.
+ // longjmp() and throw() must not violate the entry/exit criteria.
+ CS->getCapturedDecl()->setNothrow();
+
+ getCurFunction()->setHasBranchProtectedScope();
+
+ return OMPTargetTeamsDirective::Create(Context, StartLoc, EndLoc, Clauses,
+ AStmt);
+}
+
+StmtResult Sema::ActOnOpenMPTargetTeamsDistributeDirective(
+ ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA) {
+ if (!AStmt)
+ return StmtError();
+
+ CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ // 1.2.2 OpenMP Language Terminology
+ // Structured block - An executable statement with a single entry at the
+ // top and a single exit at the bottom.
+ // The point of exit cannot be a branch out of the structured block.
+ // longjmp() and throw() must not violate the entry/exit criteria.
+ CS->getCapturedDecl()->setNothrow();
+
+ OMPLoopDirective::HelperExprs B;
+ // In presence of clause 'collapse' with number of loops, it will
+ // define the nested loops number.
+ auto NestedLoopCount = CheckOpenMPLoop(
+ OMPD_target_teams_distribute,
+ getCollapseNumberExpr(Clauses),
+ nullptr /*ordered not a clause on distribute*/, AStmt, *this, *DSAStack,
+ VarsWithImplicitDSA, B);
+ if (NestedLoopCount == 0)
+ return StmtError();
+
+ assert((CurContext->isDependentContext() || B.builtAll()) &&
+ "omp target teams distribute loop exprs were not built");
+
+ getCurFunction()->setHasBranchProtectedScope();
+ 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) {
+ if (!AStmt)
+ return StmtError();
+
+ CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ // 1.2.2 OpenMP Language Terminology
+ // Structured block - An executable statement with a single entry at the
+ // top and a single exit at the bottom.
+ // The point of exit cannot be a branch out of the structured block.
+ // longjmp() and throw() must not violate the entry/exit criteria.
+ CS->getCapturedDecl()->setNothrow();
+
+ 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,
+ VarsWithImplicitDSA, B);
+ if (NestedLoopCount == 0)
+ return StmtError();
+
+ assert((CurContext->isDependentContext() || B.builtAll()) &&
+ "omp target teams distribute parallel for loop exprs were not built");
+
+ if (!CurContext->isDependentContext()) {
+ // Finalize the clauses that need pre-built expressions for CodeGen.
+ for (auto C : Clauses) {
+ if (auto *LC = dyn_cast<OMPLinearClause>(C))
+ if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
+ B.NumIterations, *this, CurScope,
+ DSAStack))
+ return StmtError();
+ }
+ }
+
+ getCurFunction()->setHasBranchProtectedScope();
+ return OMPTargetTeamsDistributeParallelForDirective::Create(
+ Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
+}
+
OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
SourceLocation StartLoc,
SourceLocation LParenLoc,
@@ -7683,8 +6851,8 @@ OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(
Res = ActOnOpenMPDefaultmapClause(
static_cast<OpenMPDefaultmapClauseModifier>(Argument[Modifier]),
static_cast<OpenMPDefaultmapClauseKind>(Argument[DefaultmapKind]),
- StartLoc, LParenLoc, ArgumentLoc[Modifier],
- ArgumentLoc[DefaultmapKind], EndLoc);
+ StartLoc, LParenLoc, ArgumentLoc[Modifier], ArgumentLoc[DefaultmapKind],
+ EndLoc);
break;
case OMPC_final:
case OMPC_num_threads:
@@ -8025,7 +7193,7 @@ OMPClause *Sema::ActOnOpenMPVarListClause(
Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc);
break;
case OMPC_depend:
- Res = ActOnOpenMPDependClause(DepKind, DepLinMapLoc, ColonLoc, VarList,
+ Res = ActOnOpenMPDependClause(DepKind, DepLinMapLoc, ColonLoc, VarList,
StartLoc, LParenLoc, EndLoc);
break;
case OMPC_map:
@@ -8207,12 +7375,13 @@ OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
continue;
}
+ auto CurrDir = DSAStack->getCurrentDirective();
// Variably modified types are not supported for tasks.
if (!Type->isAnyPointerType() && Type->isVariablyModifiedType() &&
- isOpenMPTaskingDirective(DSAStack->getCurrentDirective())) {
+ isOpenMPTaskingDirective(CurrDir)) {
Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
<< getOpenMPClauseName(OMPC_private) << Type
- << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
+ << getOpenMPDirectiveName(CurrDir);
bool IsDecl =
!VD ||
VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
@@ -8225,14 +7394,22 @@ 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 (DSAStack->getCurrentDirective() == OMPD_target) {
+ if (CurrDir == OMPD_target || CurrDir == OMPD_target_parallel ||
+ CurrDir == OMPD_target_teams ||
+ CurrDir == OMPD_target_teams_distribute ||
+ CurrDir == OMPD_target_teams_distribute_parallel_for) {
+ OpenMPClauseKind ConflictKind;
if (DSAStack->checkMappableExprComponentListsForDecl(
- VD, /* CurrentRegionOnly = */ true,
- [&](OMPClauseMappableExprCommon::MappableExprComponentListRef)
- -> bool { return true; })) {
- Diag(ELoc, diag::err_omp_variable_in_map_and_dsa)
+ VD, /*CurrentRegionOnly=*/true,
+ [&](OMPClauseMappableExprCommon::MappableExprComponentListRef,
+ OpenMPClauseKind WhereFoundClauseKind) -> bool {
+ ConflictKind = WhereFoundClauseKind;
+ return true;
+ })) {
+ Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
<< getOpenMPClauseName(OMPC_private)
- << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
+ << getOpenMPClauseName(ConflictKind)
+ << getOpenMPDirectiveName(CurrDir);
ReportOriginalDSA(*this, DSAStack, D, DVar);
continue;
}
@@ -8388,7 +7565,8 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
// worksharing regions arising from the worksharing construct ever bind
// to any of the parallel regions arising from the parallel construct.
if (isOpenMPWorksharingDirective(CurrDir) &&
- !isOpenMPParallelDirective(CurrDir)) {
+ !isOpenMPParallelDirective(CurrDir) &&
+ !isOpenMPTeamsDirective(CurrDir)) {
DVar = DSAStack->getImplicitDSA(D, true);
if (DVar.CKind != OMPC_shared &&
(isOpenMPParallelDirective(DVar.DKind) ||
@@ -8476,13 +7654,21 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(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) {
+ if (CurrDir == OMPD_target || CurrDir == OMPD_target_parallel ||
+ CurrDir == OMPD_target_teams ||
+ CurrDir == OMPD_target_teams_distribute ||
+ CurrDir == OMPD_target_teams_distribute_parallel_for) {
+ OpenMPClauseKind ConflictKind;
if (DSAStack->checkMappableExprComponentListsForDecl(
- VD, /* CurrentRegionOnly = */ true,
- [&](OMPClauseMappableExprCommon::MappableExprComponentListRef)
- -> bool { return true; })) {
- Diag(ELoc, diag::err_omp_variable_in_map_and_dsa)
+ VD, /*CurrentRegionOnly=*/true,
+ [&](OMPClauseMappableExprCommon::MappableExprComponentListRef,
+ OpenMPClauseKind WhereFoundClauseKind) -> bool {
+ ConflictKind = WhereFoundClauseKind;
+ return true;
+ })) {
+ Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
<< getOpenMPClauseName(OMPC_firstprivate)
+ << getOpenMPClauseName(ConflictKind)
<< getOpenMPDirectiveName(DSAStack->getCurrentDirective());
ReportOriginalDSA(*this, DSAStack, D, DVar);
continue;
@@ -8645,7 +7831,8 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList,
// regions.
DSAStackTy::DSAVarData TopDVar = DVar;
if (isOpenMPWorksharingDirective(CurrDir) &&
- !isOpenMPParallelDirective(CurrDir)) {
+ !isOpenMPParallelDirective(CurrDir) &&
+ !isOpenMPTeamsDirective(CurrDir)) {
DVar = DSAStack->getImplicitDSA(D, true);
if (DVar.CKind != OMPC_shared) {
Diag(ELoc, diag::err_omp_required_access)
@@ -8884,7 +8071,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 (auto *D : ULE->decls()) {
if (D == PrevD)
Lookups.push_back(UnresolvedSet<8>());
else if (auto *DRD = cast<OMPDeclareReductionDecl>(D))
@@ -9175,7 +8362,8 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
// worksharing regions arising from the worksharing construct bind.
OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
if (isOpenMPWorksharingDirective(CurrDir) &&
- !isOpenMPParallelDirective(CurrDir)) {
+ !isOpenMPParallelDirective(CurrDir) &&
+ !isOpenMPTeamsDirective(CurrDir)) {
DVar = DSAStack->getImplicitDSA(D, true);
if (DVar.CKind != OMPC_shared) {
Diag(ELoc, diag::err_omp_required_access)
@@ -9260,7 +8448,7 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
if (OASE ||
(!ASE &&
D->getType().getNonReferenceType()->isVariablyModifiedType())) {
- // For arays/array sections only:
+ // For arrays/array sections only:
// Create pseudo array type for private copy. The size for this array will
// be generated during codegen.
// For array subscripts or single variables Private Ty is the same as Type
@@ -9738,7 +8926,7 @@ static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
Expr *InitExpr = *CurInit;
// Build privatized reference to the current linear var.
- auto DE = cast<DeclRefExpr>(SimpleRefExpr);
+ auto *DE = cast<DeclRefExpr>(SimpleRefExpr);
Expr *CapturedRef;
if (LinKind == OMPC_LINEAR_uval)
CapturedRef = cast<VarDecl>(DE->getDecl())->getInit();
@@ -10040,8 +9228,7 @@ OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
auto *DstVD =
buildVarDecl(*this, RefExpr->getLocStart(), Type, ".copyprivate.dst",
D->hasAttrs() ? &D->getAttrs() : nullptr);
- auto *PseudoDstExpr =
- buildDeclRefExpr(*this, DstVD, Type, ELoc);
+ auto *PseudoDstExpr = buildDeclRefExpr(*this, DstVD, Type, ELoc);
auto AssignmentOp = BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
PseudoDstExpr, PseudoSrcExpr);
if (AssignmentOp.isInvalid())
@@ -10256,9 +9443,6 @@ static bool IsCXXRecordForMappable(Sema &SemaRef, SourceLocation Loc,
if (!RD || RD->isInvalidDecl())
return true;
- if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD))
- if (auto *CTD = CTSD->getSpecializedTemplate())
- RD = CTD->getTemplatedDecl();
auto QTy = SemaRef.Context.getRecordType(RD);
if (RD->isDynamicClass()) {
SemaRef.Diag(Loc, diag::err_omp_not_mappable_type) << QTy;
@@ -10302,8 +9486,7 @@ static bool CheckTypeMappable(SourceLocation SL, SourceRange SR, Sema &SemaRef,
SemaRef.Diag(SL, diag::err_incomplete_type) << QTy << SR;
return false;
} else if (CXXRecordDecl *RD = dyn_cast_or_null<CXXRecordDecl>(ND)) {
- if (!RD->isInvalidDecl() &&
- !IsCXXRecordForMappable(SemaRef, SL, Stack, RD))
+ if (!RD->isInvalidDecl() && !IsCXXRecordForMappable(SemaRef, SL, Stack, RD))
return false;
}
return true;
@@ -10332,7 +9515,7 @@ static bool CheckArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef,
auto *Length = OASE->getLength();
// If there is a lower bound that does not evaluates to zero, we are not
- // convering the whole dimension.
+ // covering the whole dimension.
if (LowerBound) {
llvm::APSInt ConstLowerBound;
if (!LowerBound->EvaluateAsInt(ConstLowerBound, SemaRef.getASTContext()))
@@ -10367,8 +9550,8 @@ static bool CheckArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef,
// section or array subscript) does NOT specify a single element of the array
// whose base type is \a BaseQTy.
static bool CheckArrayExpressionDoesNotReferToUnitySize(Sema &SemaRef,
- const Expr *E,
- QualType BaseQTy) {
+ const Expr *E,
+ QualType BaseQTy) {
auto *OASE = dyn_cast<OMPArraySectionExpr>(E);
// An array subscript always refer to a single element. Also, an array section
@@ -10574,16 +9757,16 @@ static Expr *CheckMapClauseExpressionBase(
bool NotUnity =
CheckArrayExpressionDoesNotReferToUnitySize(SemaRef, CurE, CurType);
- if (AllowWholeSizeArraySection && AllowUnitySizeArraySection) {
- // Any array section is currently allowed.
+ if (AllowWholeSizeArraySection) {
+ // Any array section is currently allowed. Allowing a whole size array
+ // section implies allowing a unity array section as well.
//
// If this array section refers to the whole dimension we can still
// accept other array sections before this one, except if the base is a
// pointer. Otherwise, only unitary sections are accepted.
if (NotWhole || IsPointer)
AllowWholeSizeArraySection = false;
- } else if ((AllowUnitySizeArraySection && NotUnity) ||
- (AllowWholeSizeArraySection && NotWhole)) {
+ } else if (AllowUnitySizeArraySection && NotUnity) {
// A unity or whole array section is not allowed and that is not
// compatible with the properties of the current array section.
SemaRef.Diag(
@@ -10634,7 +9817,8 @@ static bool CheckMapConflicts(
bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
VD, CurrentRegionOnly,
[&](OMPClauseMappableExprCommon::MappableExprComponentListRef
- StackComponents) -> bool {
+ StackComponents,
+ OpenMPClauseKind) -> bool {
assert(!StackComponents.empty() &&
"Map clause expression with no components!");
@@ -10686,10 +9870,10 @@ static bool CheckMapConflicts(
for (; SI != SE; ++SI) {
QualType Type;
if (auto *ASE =
- dyn_cast<ArraySubscriptExpr>(SI->getAssociatedExpression())) {
+ dyn_cast<ArraySubscriptExpr>(SI->getAssociatedExpression())) {
Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
- } else if (auto *OASE =
- dyn_cast<OMPArraySectionExpr>(SI->getAssociatedExpression())) {
+ } else if (auto *OASE = dyn_cast<OMPArraySectionExpr>(
+ SI->getAssociatedExpression())) {
auto *E = OASE->getBase()->IgnoreParenImpCasts();
Type =
OMPArraySectionExpr::getBaseOriginalType(E).getCanonicalType();
@@ -10989,11 +10173,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 && VD) {
+ if ((DKind == OMPD_target || DKind == OMPD_target_teams ||
+ DKind == OMPD_target_teams_distribute ||
+ DKind == OMPD_target_teams_distribute_parallel_for) && VD) {
auto DVar = DSAS->getTopDSA(VD, false);
if (isOpenMPPrivate(DVar.CKind)) {
- SemaRef.Diag(ELoc, diag::err_omp_variable_in_map_and_dsa)
+ 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);
continue;
@@ -11006,7 +10193,8 @@ checkMappableExpressionList(Sema &SemaRef, DSAStackTy *DSAS,
// Store the components in the stack so that they can be used to check
// against other clauses later on.
- DSAS->addMappableExpressionComponents(CurDeclaration, CurComponents);
+ DSAS->addMappableExpressionComponents(CurDeclaration, CurComponents,
+ /*WhereFoundClauseKind=*/OMPC_map);
// Save the components and declaration to create the clause. For purposes of
// the clause creation, any component list that has has base 'this' uses
@@ -11274,7 +10462,7 @@ Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareReductionDirectiveEnd(
return DeclReductions;
}
-OMPClause *Sema::ActOnOpenMPNumTeamsClause(Expr *NumTeams,
+OMPClause *Sema::ActOnOpenMPNumTeamsClause(Expr *NumTeams,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc) {
@@ -11301,8 +10489,8 @@ OMPClause *Sema::ActOnOpenMPThreadLimitClause(Expr *ThreadLimit,
/*StrictlyPositive=*/true))
return nullptr;
- return new (Context) OMPThreadLimitClause(ValExpr, StartLoc, LParenLoc,
- EndLoc);
+ return new (Context)
+ OMPThreadLimitClause(ValExpr, StartLoc, LParenLoc, EndLoc);
}
OMPClause *Sema::ActOnOpenMPPriorityClause(Expr *Priority,
@@ -11421,18 +10609,17 @@ OMPClause *Sema::ActOnOpenMPDefaultmapClause(
SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
SourceLocation KindLoc, SourceLocation EndLoc) {
// OpenMP 4.5 only supports 'defaultmap(tofrom: scalar)'
- if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom ||
- Kind != OMPC_DEFAULTMAP_scalar) {
+ if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom || Kind != OMPC_DEFAULTMAP_scalar) {
std::string Value;
SourceLocation Loc;
Value += "'";
if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) {
Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
- OMPC_DEFAULTMAP_MODIFIER_tofrom);
+ OMPC_DEFAULTMAP_MODIFIER_tofrom);
Loc = MLoc;
} else {
Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
- OMPC_DEFAULTMAP_scalar);
+ OMPC_DEFAULTMAP_scalar);
Loc = KindLoc;
}
Value += "'";
@@ -11469,11 +10656,11 @@ void Sema::ActOnFinishOpenMPDeclareTargetDirective() {
IsInOpenMPDeclareTargetContext = false;
}
-void
-Sema::ActOnOpenMPDeclareTargetName(Scope *CurScope, CXXScopeSpec &ScopeSpec,
- const DeclarationNameInfo &Id,
- OMPDeclareTargetDeclAttr::MapTypeTy MT,
- NamedDeclSetType &SameDirectiveDecls) {
+void Sema::ActOnOpenMPDeclareTargetName(Scope *CurScope,
+ CXXScopeSpec &ScopeSpec,
+ const DeclarationNameInfo &Id,
+ OMPDeclareTargetDeclAttr::MapTypeTy MT,
+ NamedDeclSetType &SameDirectiveDecls) {
LookupResult Lookup(*this, Id, LookupOrdinaryName);
LookupParsedName(Lookup, CurScope, &ScopeSpec, true);
@@ -11671,7 +10858,10 @@ OMPClause *Sema::ActOnOpenMPUseDevicePtrClause(ArrayRef<Expr *> VarList,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc) {
- SmallVector<Expr *, 8> Vars;
+ MappableVarListInfo MVLI(VarList);
+ SmallVector<Expr *, 8> PrivateCopies;
+ SmallVector<Expr *, 8> Inits;
+
for (auto &RefExpr : VarList) {
assert(RefExpr && "NULL expr in OpenMP use_device_ptr clause.");
SourceLocation ELoc;
@@ -11680,43 +10870,89 @@ OMPClause *Sema::ActOnOpenMPUseDevicePtrClause(ArrayRef<Expr *> VarList,
auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
if (Res.second) {
// It will be analyzed later.
- Vars.push_back(RefExpr);
+ MVLI.ProcessedVarList.push_back(RefExpr);
+ PrivateCopies.push_back(nullptr);
+ Inits.push_back(nullptr);
}
ValueDecl *D = Res.first;
if (!D)
continue;
QualType Type = D->getType();
- // item should be a pointer or reference to pointer
- if (!Type.getNonReferenceType()->isPointerType()) {
+ Type = Type.getNonReferenceType().getUnqualifiedType();
+
+ auto *VD = dyn_cast<VarDecl>(D);
+
+ // Item should be a pointer or reference to pointer.
+ if (!Type->isPointerType()) {
Diag(ELoc, diag::err_omp_usedeviceptr_not_a_pointer)
<< 0 << RefExpr->getSourceRange();
continue;
}
- Vars.push_back(RefExpr->IgnoreParens());
+
+ // Build the private variable and the expression that refers to it.
+ auto VDPrivate = buildVarDecl(*this, ELoc, Type, D->getName(),
+ D->hasAttrs() ? &D->getAttrs() : nullptr);
+ if (VDPrivate->isInvalidDecl())
+ continue;
+
+ CurContext->addDecl(VDPrivate);
+ auto VDPrivateRefExpr = buildDeclRefExpr(
+ *this, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
+
+ // Add temporary variable to initialize the private copy of the pointer.
+ auto *VDInit =
+ buildVarDecl(*this, RefExpr->getExprLoc(), Type, ".devptr.temp");
+ auto *VDInitRefExpr = buildDeclRefExpr(*this, VDInit, RefExpr->getType(),
+ RefExpr->getExprLoc());
+ AddInitializerToDecl(VDPrivate,
+ DefaultLvalueConversion(VDInitRefExpr).get(),
+ /*DirectInit=*/false, /*TypeMayContainAuto=*/false);
+
+ // If required, build a capture to implement the privatization initialized
+ // with the current list item value.
+ DeclRefExpr *Ref = nullptr;
+ if (!VD)
+ Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
+ MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
+ PrivateCopies.push_back(VDPrivateRefExpr);
+ Inits.push_back(VDInitRefExpr);
+
+ // We need to add a data sharing attribute for this variable to make sure it
+ // is correctly captured. A variable that shows up in a use_device_ptr has
+ // similar properties of a first private variable.
+ DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
+
+ // Create a mappable component for the list item. List items in this clause
+ // only need a component.
+ MVLI.VarBaseDeclarations.push_back(D);
+ MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
+ MVLI.VarComponents.back().push_back(
+ OMPClauseMappableExprCommon::MappableComponent(SimpleRefExpr, D));
}
- if (Vars.empty())
+ if (MVLI.ProcessedVarList.empty())
return nullptr;
- return OMPUseDevicePtrClause::Create(Context, StartLoc, LParenLoc, EndLoc,
- Vars);
+ return OMPUseDevicePtrClause::Create(
+ Context, StartLoc, LParenLoc, EndLoc, MVLI.ProcessedVarList,
+ PrivateCopies, Inits, MVLI.VarBaseDeclarations, MVLI.VarComponents);
}
OMPClause *Sema::ActOnOpenMPIsDevicePtrClause(ArrayRef<Expr *> VarList,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc) {
- SmallVector<Expr *, 8> Vars;
+ MappableVarListInfo MVLI(VarList);
for (auto &RefExpr : VarList) {
- assert(RefExpr && "NULL expr in OpenMP use_device_ptr clause.");
+ assert(RefExpr && "NULL expr in OpenMP is_device_ptr clause.");
SourceLocation ELoc;
SourceRange ERange;
Expr *SimpleRefExpr = RefExpr;
auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange);
if (Res.second) {
// It will be analyzed later.
- Vars.push_back(RefExpr);
+ MVLI.ProcessedVarList.push_back(RefExpr);
}
ValueDecl *D = Res.first;
if (!D)
@@ -11730,12 +10966,59 @@ OMPClause *Sema::ActOnOpenMPIsDevicePtrClause(ArrayRef<Expr *> VarList,
<< 0 << RefExpr->getSourceRange();
continue;
}
- Vars.push_back(RefExpr->IgnoreParens());
+
+ // Check if the declaration in the clause does not show up in any data
+ // sharing attribute.
+ auto DVar = DSAStack->getTopDSA(D, 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);
+ continue;
+ }
+
+ Expr *ConflictExpr;
+ if (DSAStack->checkMappableExprComponentListsForDecl(
+ D, /*CurrentRegionOnly=*/true,
+ [&ConflictExpr](
+ OMPClauseMappableExprCommon::MappableExprComponentListRef R,
+ OpenMPClauseKind) -> bool {
+ ConflictExpr = R.front().getAssociatedExpression();
+ return true;
+ })) {
+ Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
+ Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
+ << ConflictExpr->getSourceRange();
+ continue;
+ }
+
+ // Store the components in the stack so that they can be used to check
+ // against other clauses later on.
+ OMPClauseMappableExprCommon::MappableComponent MC(SimpleRefExpr, D);
+ DSAStack->addMappableExpressionComponents(
+ D, MC, /*WhereFoundClauseKind=*/OMPC_is_device_ptr);
+
+ // Record the expression we've just processed.
+ MVLI.ProcessedVarList.push_back(SimpleRefExpr);
+
+ // Create a mappable component for the list item. List items in this clause
+ // only need a component. We use a null declaration to signal fields in
+ // 'this'.
+ assert((isa<DeclRefExpr>(SimpleRefExpr) ||
+ isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
+ "Unexpected device pointer expression!");
+ MVLI.VarBaseDeclarations.push_back(
+ isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
+ MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
+ MVLI.VarComponents.back().push_back(MC);
}
- if (Vars.empty())
+ if (MVLI.ProcessedVarList.empty())
return nullptr;
- return OMPIsDevicePtrClause::Create(Context, StartLoc, LParenLoc, EndLoc,
- Vars);
+ return OMPIsDevicePtrClause::Create(
+ Context, StartLoc, LParenLoc, EndLoc, MVLI.ProcessedVarList,
+ MVLI.VarBaseDeclarations, MVLI.VarComponents);
}
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 40d6e910f1fb..47e3df20d911 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -39,8 +39,9 @@ using namespace clang;
using namespace sema;
static bool functionHasPassObjectSizeParams(const FunctionDecl *FD) {
- return llvm::any_of(FD->parameters(),
- std::mem_fn(&ParmVarDecl::hasAttr<PassObjectSizeAttr>));
+ return llvm::any_of(FD->parameters(), [](const ParmVarDecl *P) {
+ return P->hasAttr<PassObjectSizeAttr>();
+ });
}
/// A convenience routine for creating a decayed reference to a function.
@@ -59,6 +60,8 @@ CreateFunctionRefExpr(Sema &S, FunctionDecl *Fn, NamedDecl *FoundDecl,
// being used.
if (FoundDecl != Fn && S.DiagnoseUseOfDecl(Fn, Loc))
return ExprError();
+ if (auto *FPT = Fn->getType()->getAs<FunctionProtoType>())
+ S.ResolveExceptionSpec(Loc, FPT);
DeclRefExpr *DRE = new (S.Context) DeclRefExpr(Fn, false, Fn->getType(),
VK_LValue, Loc, LocInfo);
if (HadMultipleCandidates)
@@ -135,7 +138,8 @@ ImplicitConversionRank clang::GetConversionRank(ImplicitConversionKind Kind) {
ICR_Exact_Match, // NOTE(gbiv): This may not be completely right --
// it was omitted by the patch that added
// ICK_Zero_Event_Conversion
- ICR_C_Conversion
+ ICR_C_Conversion,
+ ICR_C_Conversion_Extension
};
return Rank[(int)Kind];
}
@@ -148,7 +152,7 @@ static const char* GetImplicitConversionName(ImplicitConversionKind Kind) {
"Lvalue-to-rvalue",
"Array-to-pointer",
"Function-to-pointer",
- "Noreturn adjustment",
+ "Function pointer conversion",
"Qualification",
"Integral promotion",
"Floating point promotion",
@@ -169,7 +173,8 @@ static const char* GetImplicitConversionName(ImplicitConversionKind Kind) {
"Transparent Union Conversion",
"Writeback conversion",
"OpenCL Zero Event Conversion",
- "C specific type conversion"
+ "C specific type conversion",
+ "Incompatible pointer conversion"
};
return Name[Kind];
}
@@ -324,6 +329,11 @@ StandardConversionSequence::getNarrowingKind(ASTContext &Ctx,
} else if (FromType->isIntegralType(Ctx) && ToType->isRealFloatingType()) {
llvm::APSInt IntConstantValue;
const Expr *Initializer = IgnoreNarrowingConversion(Converted);
+
+ // If it's value-dependent, we can't tell whether it's narrowing.
+ if (Initializer->isValueDependent())
+ return NK_Dependent_Narrowing;
+
if (Initializer &&
Initializer->isIntegerConstantExpr(IntConstantValue, Ctx)) {
// Convert the integer to the floating type.
@@ -357,6 +367,11 @@ StandardConversionSequence::getNarrowingKind(ASTContext &Ctx,
Ctx.getFloatingTypeOrder(FromType, ToType) == 1) {
// FromType is larger than ToType.
const Expr *Initializer = IgnoreNarrowingConversion(Converted);
+
+ // If it's value-dependent, we can't tell whether it's narrowing.
+ if (Initializer->isValueDependent())
+ return NK_Dependent_Narrowing;
+
if (Initializer->isCXX11ConstantExpr(Ctx, &ConstantValue)) {
// Constant!
assert(ConstantValue.isFloat());
@@ -398,6 +413,11 @@ StandardConversionSequence::getNarrowingKind(ASTContext &Ctx,
// Not all values of FromType can be represented in ToType.
llvm::APSInt InitializerValue;
const Expr *Initializer = IgnoreNarrowingConversion(Converted);
+
+ // If it's value-dependent, we can't tell whether it's narrowing.
+ if (Initializer->isValueDependent())
+ return NK_Dependent_Narrowing;
+
if (!Initializer->isIntegerConstantExpr(InitializerValue, Ctx)) {
// Such conversions on variables are always narrowing.
return NK_Variable_Narrowing;
@@ -575,6 +595,7 @@ clang::MakeDeductionFailureInfo(ASTContext &Context,
case Sema::TDK_TooManyArguments:
case Sema::TDK_TooFewArguments:
case Sema::TDK_MiscellaneousDeductionFailure:
+ case Sema::TDK_CUDATargetMismatch:
Result.Data = nullptr;
break;
@@ -642,6 +663,7 @@ void DeductionFailureInfo::Destroy() {
case Sema::TDK_TooFewArguments:
case Sema::TDK_InvalidExplicitArguments:
case Sema::TDK_FailedOverloadResolution:
+ case Sema::TDK_CUDATargetMismatch:
break;
case Sema::TDK_Inconsistent:
@@ -684,6 +706,7 @@ TemplateParameter DeductionFailureInfo::getTemplateParameter() {
case Sema::TDK_DeducedMismatch:
case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_FailedOverloadResolution:
+ case Sema::TDK_CUDATargetMismatch:
return TemplateParameter();
case Sema::TDK_Incomplete:
@@ -715,6 +738,7 @@ TemplateArgumentList *DeductionFailureInfo::getTemplateArgumentList() {
case Sema::TDK_Underqualified:
case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_FailedOverloadResolution:
+ case Sema::TDK_CUDATargetMismatch:
return nullptr;
case Sema::TDK_DeducedMismatch:
@@ -742,6 +766,7 @@ const TemplateArgument *DeductionFailureInfo::getFirstArg() {
case Sema::TDK_InvalidExplicitArguments:
case Sema::TDK_SubstitutionFailure:
case Sema::TDK_FailedOverloadResolution:
+ case Sema::TDK_CUDATargetMismatch:
return nullptr;
case Sema::TDK_Inconsistent:
@@ -769,6 +794,7 @@ const TemplateArgument *DeductionFailureInfo::getSecondArg() {
case Sema::TDK_InvalidExplicitArguments:
case Sema::TDK_SubstitutionFailure:
case Sema::TDK_FailedOverloadResolution:
+ case Sema::TDK_CUDATargetMismatch:
return nullptr;
case Sema::TDK_Inconsistent:
@@ -812,6 +838,7 @@ void OverloadCandidateSet::destroyCandidates() {
void OverloadCandidateSet::clear() {
destroyCandidates();
+ ConversionSequenceAllocator.Reset();
NumInlineSequences = 0;
Candidates.clear();
Functions.clear();
@@ -969,16 +996,23 @@ Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old,
Match = *I;
return Ovl_Match;
}
- } else if (isa<UsingDecl>(OldD)) {
+ } else if (isa<UsingDecl>(OldD) || isa<UsingPackDecl>(OldD)) {
// We can overload with these, which can show up when doing
// redeclaration checks for UsingDecls.
assert(Old.getLookupKind() == LookupUsingDeclName);
} else if (isa<TagDecl>(OldD)) {
// We can always overload with tags by hiding them.
- } else if (isa<UnresolvedUsingValueDecl>(OldD)) {
+ } else if (auto *UUD = dyn_cast<UnresolvedUsingValueDecl>(OldD)) {
// Optimistically assume that an unresolved using decl will
// overload; if it doesn't, we'll have to diagnose during
// template instantiation.
+ //
+ // Exception: if the scope is dependent and this is not a class
+ // member, the using declaration can only introduce an enumerator.
+ if (UUD->getQualifier()->isDependent() && !UUD->isCXXClassMember()) {
+ Match = *I;
+ return Ovl_NonFunction;
+ }
} else {
// (C++ 13p1):
// Only function declarations can be overloaded; object and type
@@ -1126,24 +1160,20 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
}
if (getLangOpts().CUDA && ConsiderCudaAttrs) {
+ // Don't allow overloading of destructors. (In theory we could, but it
+ // would be a giant change to clang.)
+ if (isa<CXXDestructorDecl>(New))
+ return false;
+
CUDAFunctionTarget NewTarget = IdentifyCUDATarget(New),
OldTarget = IdentifyCUDATarget(Old);
- if (NewTarget == CFT_InvalidTarget || NewTarget == CFT_Global)
+ if (NewTarget == CFT_InvalidTarget)
return false;
assert((OldTarget != CFT_InvalidTarget) && "Unexpected invalid target.");
- // Don't allow mixing of HD with other kinds. This guarantees that
- // we have only one viable function with this signature on any
- // side of CUDA compilation .
- // __global__ functions can't be overloaded based on attribute
- // difference because, like HD, they also exist on both sides.
- if ((NewTarget == CFT_HostDevice) || (OldTarget == CFT_HostDevice) ||
- (NewTarget == CFT_Global) || (OldTarget == CFT_Global))
- return false;
-
- // Allow overloading of functions with same signature, but
- // different CUDA target attributes.
+ // Allow overloading of functions with same signature and different CUDA
+ // target attributes.
return NewTarget != OldTarget;
}
@@ -1199,7 +1229,6 @@ TryUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
case OR_Success:
case OR_Deleted:
ICS.setUserDefined();
- ICS.UserDefined.Before.setAsIdentityConversion();
// C++ [over.ics.user]p4:
// A conversion of an expression of class type to the same class
// type is given Exact Match rank, and a conversion of an
@@ -1383,17 +1412,20 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
}
/// \brief Determine whether the conversion from FromType to ToType is a valid
-/// conversion that strips "noreturn" off the nested function type.
-bool Sema::IsNoReturnConversion(QualType FromType, QualType ToType,
+/// conversion that strips "noexcept" or "noreturn" off the nested function
+/// type.
+bool Sema::IsFunctionConversion(QualType FromType, QualType ToType,
QualType &ResultTy) {
if (Context.hasSameUnqualifiedType(FromType, ToType))
return false;
// Permit the conversion F(t __attribute__((noreturn))) -> F(t)
+ // or F(t noexcept) -> F(t)
// where F adds one of the following at most once:
// - a pointer
// - a member pointer
// - a block pointer
+ // Changes here need matching changes in FindCompositePointerType.
CanQualType CanTo = Context.getCanonicalType(ToType);
CanQualType CanFrom = Context.getCanonicalType(FromType);
Type::TypeClass TyClass = CanTo->getTypeClass();
@@ -1406,8 +1438,13 @@ bool Sema::IsNoReturnConversion(QualType FromType, QualType ToType,
CanTo = CanTo.getAs<BlockPointerType>()->getPointeeType();
CanFrom = CanFrom.getAs<BlockPointerType>()->getPointeeType();
} else if (TyClass == Type::MemberPointer) {
- CanTo = CanTo.getAs<MemberPointerType>()->getPointeeType();
- CanFrom = CanFrom.getAs<MemberPointerType>()->getPointeeType();
+ auto ToMPT = CanTo.getAs<MemberPointerType>();
+ auto FromMPT = CanFrom.getAs<MemberPointerType>();
+ // A function pointer conversion cannot change the class of the function.
+ if (ToMPT->getClass() != FromMPT->getClass())
+ return false;
+ CanTo = ToMPT->getPointeeType();
+ CanFrom = FromMPT->getPointeeType();
} else {
return false;
}
@@ -1418,11 +1455,37 @@ bool Sema::IsNoReturnConversion(QualType FromType, QualType ToType,
return false;
}
- const FunctionType *FromFn = cast<FunctionType>(CanFrom);
- FunctionType::ExtInfo EInfo = FromFn->getExtInfo();
- if (!EInfo.getNoReturn()) return false;
+ const auto *FromFn = cast<FunctionType>(CanFrom);
+ FunctionType::ExtInfo FromEInfo = FromFn->getExtInfo();
+
+ const auto *ToFn = cast<FunctionType>(CanTo);
+ FunctionType::ExtInfo ToEInfo = ToFn->getExtInfo();
+
+ bool Changed = false;
+
+ // Drop 'noreturn' if not present in target type.
+ if (FromEInfo.getNoReturn() && !ToEInfo.getNoReturn()) {
+ FromFn = Context.adjustFunctionType(FromFn, FromEInfo.withNoReturn(false));
+ Changed = true;
+ }
+
+ // 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)) {
+ FromFn = cast<FunctionType>(
+ Context.getFunctionType(FromFPT->getReturnType(),
+ FromFPT->getParamTypes(),
+ FromFPT->getExtProtoInfo().withExceptionSpec(
+ FunctionProtoType::ExceptionSpecInfo()))
+ .getTypePtr());
+ Changed = true;
+ }
+ }
+
+ if (!Changed)
+ return false;
- FromFn = Context.adjustFunctionType(FromFn, EInfo.withNoReturn(false));
assert(QualType(FromFn, 0).isCanonical());
if (QualType(FromFn, 0) != CanTo) return false;
@@ -1527,7 +1590,7 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
S.ExtractUnqualifiedFunctionType(ToType), FromType)) {
QualType resultTy;
// if the function type matches except for [[noreturn]], it's ok
- if (!S.IsNoReturnConversion(FromType,
+ if (!S.IsFunctionConversion(FromType,
S.ExtractUnqualifiedFunctionType(ToType), resultTy))
// otherwise, only a boolean conversion is standard
if (!ToType->isBooleanType())
@@ -1556,6 +1619,8 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
}
// Check that we've computed the proper type after overload resolution.
+ // FIXME: FixOverloadedFunctionReference has side-effects; we shouldn't
+ // be calling it from within an NDEBUG block.
assert(S.Context.hasSameType(
FromType,
S.FixOverloadedFunctionReference(From, AccessPair, Fn)->getType()));
@@ -1684,7 +1749,7 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
ToType == S.Context.Float128Ty));
if (Float128AndLongDouble &&
(&S.Context.getFloatTypeSemantics(S.Context.LongDoubleTy) !=
- &llvm::APFloat::IEEEdouble))
+ &llvm::APFloat::IEEEdouble()))
return false;
}
// Floating point conversions (C++ 4.8).
@@ -1720,9 +1785,6 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
// Compatible conversions (Clang extension for C function overloading)
SCS.Second = ICK_Compatible_Conversion;
FromType = ToType.getUnqualifiedType();
- } else if (S.IsNoReturnConversion(FromType, ToType, FromType)) {
- // Treat a conversion that strips "noreturn" as an identity conversion.
- SCS.Second = ICK_NoReturn_Adjustment;
} else if (IsTransparentUnionStandardConversion(S, From, ToType,
InOverloadResolution,
SCS, CStyle)) {
@@ -1738,40 +1800,47 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
From->EvaluateKnownConstInt(S.getASTContext()) == 0) {
SCS.Second = ICK_Zero_Event_Conversion;
FromType = ToType;
+ } else if (ToType->isQueueT() &&
+ From->isIntegerConstantExpr(S.getASTContext()) &&
+ (From->EvaluateKnownConstInt(S.getASTContext()) == 0)) {
+ SCS.Second = ICK_Zero_Queue_Conversion;
+ FromType = ToType;
} else {
// No second conversion required.
SCS.Second = ICK_Identity;
}
SCS.setToType(1, FromType);
- QualType CanonFrom;
- QualType CanonTo;
- // The third conversion can be a qualification conversion (C++ 4p1).
+ // The third conversion can be a function pointer conversion or a
+ // qualification conversion (C++ [conv.fctptr], [conv.qual]).
bool ObjCLifetimeConversion;
- if (S.IsQualificationConversion(FromType, ToType, CStyle,
- ObjCLifetimeConversion)) {
+ if (S.IsFunctionConversion(FromType, ToType, FromType)) {
+ // Function pointer conversions (removing 'noexcept') including removal of
+ // 'noreturn' (Clang extension).
+ SCS.Third = ICK_Function_Conversion;
+ } else if (S.IsQualificationConversion(FromType, ToType, CStyle,
+ ObjCLifetimeConversion)) {
SCS.Third = ICK_Qualification;
SCS.QualificationIncludesObjCLifetime = ObjCLifetimeConversion;
FromType = ToType;
- CanonFrom = S.Context.getCanonicalType(FromType);
- CanonTo = S.Context.getCanonicalType(ToType);
} else {
// No conversion required
SCS.Third = ICK_Identity;
+ }
- // C++ [over.best.ics]p6:
- // [...] Any difference in top-level cv-qualification is
- // subsumed by the initialization itself and does not constitute
- // a conversion. [...]
- CanonFrom = S.Context.getCanonicalType(FromType);
- CanonTo = S.Context.getCanonicalType(ToType);
- if (CanonFrom.getLocalUnqualifiedType()
- == CanonTo.getLocalUnqualifiedType() &&
- CanonFrom.getLocalQualifiers() != CanonTo.getLocalQualifiers()) {
- FromType = ToType;
- CanonFrom = CanonTo;
- }
+ // C++ [over.best.ics]p6:
+ // [...] Any difference in top-level cv-qualification is
+ // subsumed by the initialization itself and does not constitute
+ // a conversion. [...]
+ QualType CanonFrom = S.Context.getCanonicalType(FromType);
+ QualType CanonTo = S.Context.getCanonicalType(ToType);
+ if (CanonFrom.getLocalUnqualifiedType()
+ == CanonTo.getLocalUnqualifiedType() &&
+ CanonFrom.getLocalQualifiers() != CanonTo.getLocalQualifiers()) {
+ FromType = ToType;
+ CanonFrom = CanonTo;
}
+
SCS.setToType(2, FromType);
if (CanonFrom == CanonTo)
@@ -1783,22 +1852,43 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
return false;
ExprResult ER = ExprResult{From};
- auto Conv = S.CheckSingleAssignmentConstraints(ToType, ER,
- /*Diagnose=*/false,
- /*DiagnoseCFAudited=*/false,
- /*ConvertRHS=*/false);
- if (Conv != Sema::Compatible)
+ Sema::AssignConvertType Conv =
+ S.CheckSingleAssignmentConstraints(ToType, ER,
+ /*Diagnose=*/false,
+ /*DiagnoseCFAudited=*/false,
+ /*ConvertRHS=*/false);
+ ImplicitConversionKind SecondConv;
+ switch (Conv) {
+ case Sema::Compatible:
+ SecondConv = ICK_C_Only_Conversion;
+ break;
+ // For our purposes, discarding qualifiers is just as bad as using an
+ // incompatible pointer. Note that an IncompatiblePointer conversion can drop
+ // qualifiers, as well.
+ case Sema::CompatiblePointerDiscardsQualifiers:
+ case Sema::IncompatiblePointer:
+ case Sema::IncompatiblePointerSign:
+ SecondConv = ICK_Incompatible_Pointer_Conversion;
+ break;
+ default:
return false;
+ }
+
+ // First can only be an lvalue conversion, so we pretend that this was the
+ // second conversion. First should already be valid from earlier in the
+ // function.
+ SCS.Second = SecondConv;
+ SCS.setToType(1, ToType);
- SCS.setAllToTypes(ToType);
- // We need to set all three because we want this conversion to rank terribly,
- // and we don't know what conversions it may overlap with.
- SCS.First = ICK_C_Only_Conversion;
- SCS.Second = ICK_C_Only_Conversion;
- SCS.Third = ICK_C_Only_Conversion;
+ // Third is Identity, because Second should rank us worse than any other
+ // conversion. This could also be ICK_Qualification, but it's simpler to just
+ // lump everything in with the second conversion, and we don't gain anything
+ // from making this ICK_Qualification.
+ SCS.Third = ICK_Identity;
+ SCS.setToType(2, ToType);
return true;
}
-
+
static bool
IsTransparentUnionStandardConversion(Sema &S, Expr* From,
QualType &ToType,
@@ -2587,7 +2677,8 @@ enum {
ft_parameter_arity,
ft_parameter_mismatch,
ft_return_type,
- ft_qualifer_mismatch
+ ft_qualifer_mismatch,
+ ft_noexcept
};
/// Attempts to get the FunctionProtoType from a Type. Handles
@@ -2687,6 +2778,16 @@ void Sema::HandleFunctionTypeMismatch(PartialDiagnostic &PDiag,
return;
}
+ // Handle exception specification differences on canonical type (in C++17
+ // onwards).
+ if (cast<FunctionProtoType>(FromFunction->getCanonicalTypeUnqualified())
+ ->isNothrow(Context) !=
+ cast<FunctionProtoType>(ToFunction->getCanonicalTypeUnqualified())
+ ->isNothrow(Context)) {
+ PDiag << ft_noexcept;
+ return;
+ }
+
// Unable to find a difference, so add no extra info.
PDiag << ft_default;
}
@@ -4098,6 +4199,7 @@ Sema::CompareReferenceRelationship(SourceLocation Loc,
DerivedToBase = false;
ObjCConversion = false;
ObjCLifetimeConversion = false;
+ QualType ConvertedT2;
if (UnqualT1 == UnqualT2) {
// Nothing to do.
} else if (isCompleteType(Loc, OrigT2) &&
@@ -4108,6 +4210,15 @@ Sema::CompareReferenceRelationship(SourceLocation Loc,
UnqualT2->isObjCObjectOrInterfaceType() &&
Context.canBindObjCObjectType(UnqualT1, UnqualT2))
ObjCConversion = true;
+ else if (UnqualT2->isFunctionType() &&
+ IsFunctionConversion(UnqualT2, UnqualT1, ConvertedT2))
+ // C++1z [dcl.init.ref]p4:
+ // cv1 T1" is reference-compatible with "cv2 T2" if [...] T2 is "noexcept
+ // function" and T1 is "function"
+ //
+ // We extend this to also apply to 'noreturn', so allow any function
+ // conversion between function types.
+ return Ref_Compatible;
else
return Ref_Incompatible;
@@ -4146,10 +4257,8 @@ Sema::CompareReferenceRelationship(SourceLocation Loc,
T1Quals.removeUnaligned();
T2Quals.removeUnaligned();
- if (T1Quals == T2Quals)
+ if (T1Quals.compatiblyIncludes(T2Quals))
return Ref_Compatible;
- else if (T1Quals.compatiblyIncludes(T2Quals))
- return Ref_Compatible_With_Added_Qualification;
else
return Ref_Related;
}
@@ -4327,8 +4436,7 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
// reference-compatible with "cv2 T2," or
//
// Per C++ [over.ics.ref]p4, we don't check the bit-field property here.
- if (InitCategory.isLValue() &&
- RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification) {
+ if (InitCategory.isLValue() && RefRelationship == Sema::Ref_Compatible) {
// C++ [over.ics.ref]p1:
// When a parameter of reference type binds directly (8.5.3)
// to an argument expression, the implicit conversion sequence
@@ -4390,10 +4498,10 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
//
// -- is an xvalue, class prvalue, array prvalue or function
// lvalue and "cv1 T1" is reference-compatible with "cv2 T2", or
- if (RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification &&
+ if (RefRelationship == Sema::Ref_Compatible &&
(InitCategory.isXValue() ||
- (InitCategory.isPRValue() && (T2->isRecordType() || T2->isArrayType())) ||
- (InitCategory.isLValue() && T2->isFunctionType()))) {
+ (InitCategory.isPRValue() && (T2->isRecordType() || T2->isArrayType())) ||
+ (InitCategory.isLValue() && T2->isFunctionType()))) {
ICS.setStandard();
ICS.Standard.First = ICK_Identity;
ICS.Standard.Second = DerivedToBase? ICK_Derived_To_Base
@@ -4540,7 +4648,6 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
return ICS;
}
- ICS.UserDefined.Before.setAsIdentityConversion();
ICS.UserDefined.After.ReferenceBinding = true;
ICS.UserDefined.After.IsLvalueReference = !isRValRef;
ICS.UserDefined.After.BindsToFunctionLvalue = false;
@@ -4693,6 +4800,9 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType,
// Type is an aggregate, argument is an init list. At this point it comes
// down to checking whether the initialization works.
// FIXME: Find out whether this parameter is consumed or not.
+ // FIXME: Expose SemaInit's aggregate initialization code so that we don't
+ // need to call into the initialization code here; overload resolution
+ // should not be doing that.
InitializedEntity Entity =
InitializedEntity::InitializeParameter(S.Context, ToType,
/*Consumed=*/false);
@@ -4896,7 +5006,7 @@ TryObjectArgumentInitialization(Sema &S, SourceLocation Loc, QualType FromType,
// cv-qualification on the member function declaration.
//
// However, when finding an implicit conversion sequence for the argument, we
- // are not allowed to create temporaries or perform user-defined conversions
+ // are not allowed to perform user-defined conversions
// (C++ [over.match.funcs]p5). We perform a simplified version of
// reference binding here, that allows class rvalues to bind to
// non-constant references.
@@ -5069,9 +5179,10 @@ static bool CheckConvertedConstantConversions(Sema &S,
// conversions are fine.
switch (SCS.Second) {
case ICK_Identity:
- case ICK_NoReturn_Adjustment:
+ case ICK_Function_Conversion:
case ICK_Integral_Promotion:
case ICK_Integral_Conversion: // Narrowing conversions are checked elsewhere.
+ case ICK_Zero_Queue_Conversion:
return true;
case ICK_Boolean_Conversion:
@@ -5106,6 +5217,7 @@ static bool CheckConvertedConstantConversions(Sema &S,
case ICK_Writeback_Conversion:
case ICK_Zero_Event_Conversion:
case ICK_C_Only_Conversion:
+ case ICK_Incompatible_Pointer_Conversion:
return false;
case ICK_Lvalue_To_Rvalue:
@@ -5141,12 +5253,18 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From,
// implicitly converted to type T, where the converted
// expression is a constant expression and the implicit conversion
// sequence contains only [... list of conversions ...].
+ // C++1z [stmt.if]p2:
+ // If the if statement is of the form if constexpr, the value of the
+ // condition shall be a contextually converted constant expression of type
+ // bool.
ImplicitConversionSequence ICS =
- TryCopyInitialization(S, From, T,
- /*SuppressUserConversions=*/false,
- /*InOverloadResolution=*/false,
- /*AllowObjcWritebackConversion=*/false,
- /*AllowExplicit=*/false);
+ CCE == Sema::CCEK_ConstexprIf
+ ? TryContextuallyConvertToBool(S, From)
+ : TryCopyInitialization(S, From, T,
+ /*SuppressUserConversions=*/false,
+ /*InOverloadResolution=*/false,
+ /*AllowObjcWritebackConversion=*/false,
+ /*AllowExplicit=*/false);
StandardConversionSequence *SCS = nullptr;
switch (ICS.getKind()) {
case ImplicitConversionSequence::StandardConversion:
@@ -5192,6 +5310,9 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From,
QualType PreNarrowingType;
switch (SCS->getNarrowingKind(S.Context, Result.get(), PreNarrowingValue,
PreNarrowingType)) {
+ 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_Variable_Narrowing:
// Implicit conversion to a narrower type, and the value is not a constant
// expression. We'll diagnose this in a moment.
@@ -5210,6 +5331,11 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From,
break;
}
+ if (Result.get()->isValueDependent()) {
+ Value = APValue();
+ return Result;
+ }
+
// Check the expression is a constant expression.
SmallVector<PartialDiagnosticAt, 8> Notes;
Expr::EvalResult Eval;
@@ -5256,7 +5382,7 @@ ExprResult Sema::CheckConvertedConstantExpression(Expr *From, QualType T,
APValue V;
auto R = ::CheckConvertedConstantExpression(*this, From, T, V, CCE, true);
- if (!R.isInvalid())
+ if (!R.isInvalid() && !R.get()->isValueDependent())
Value = V.getInt();
return R;
}
@@ -5310,6 +5436,7 @@ TryContextuallyConvertToObjCPointer(Sema &S, Expr *From) {
/// PerformContextuallyConvertToObjCPointer - Perform a contextual
/// conversion of the expression From to an Objective-C pointer type.
+/// Returns a valid but null ExprResult if no conversion sequence exists.
ExprResult Sema::PerformContextuallyConvertToObjCPointer(Expr *From) {
if (checkPlaceholderForOverload(*this, From))
return ExprError();
@@ -5319,7 +5446,7 @@ ExprResult Sema::PerformContextuallyConvertToObjCPointer(Expr *From) {
TryContextuallyConvertToObjCPointer(*this, From);
if (!ICS.isBad())
return PerformImplicitConversion(From, Ty, ICS, AA_Converting);
- return ExprError();
+ return ExprResult();
}
/// Determine whether the provided type is an integral type, or an enumeration
@@ -5817,7 +5944,7 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
// case we may not yet know what the member's target is; the target is
// inferred for the member automatically, based on the bases and fields of
// the class.
- if (!Caller->isImplicit() && CheckCUDATarget(Caller, Function)) {
+ if (!Caller->isImplicit() && !IsAllowedCUDACall(Caller, Function)) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_target;
return;
@@ -5858,6 +5985,12 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
Candidate.DeductionFailure.Data = FailedAttr;
return;
}
+
+ if (LangOpts.OpenCL && isOpenCLDisabledDecl(Function)) {
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_fail_ext_disabled;
+ return;
+ }
}
ObjCMethodDecl *
@@ -5907,10 +6040,15 @@ Sema::SelectBestMethod(Selector Sel, MultiExprArg Args, bool IsInstance,
/*AllowObjCWritebackConversion=*/
getLangOpts().ObjCAutoRefCount,
/*AllowExplicit*/false);
- if (ConversionState.isBad()) {
- Match = false;
- break;
- }
+ // This function looks for a reasonably-exact match, so we consider
+ // incompatible pointer conversions to be a failure here.
+ if (ConversionState.isBad() ||
+ (ConversionState.isStandard() &&
+ ConversionState.Standard.Second ==
+ ICK_Incompatible_Pointer_Conversion)) {
+ Match = false;
+ break;
+ }
}
// Promote additional arguments to variadic methods.
if (Match && Method->isVariadic()) {
@@ -5975,7 +6113,7 @@ EnableIfAttr *Sema::CheckEnableIf(FunctionDecl *Function, ArrayRef<Expr *> Args,
SmallVector<Expr *, 16> ConvertedArgs;
bool InitializationFailed = false;
- // Ignore any variadic parameters. Converting them is pointless, since the
+ // Ignore any variadic arguments. Converting them is pointless, since the
// user can't refer to them in the enable_if condition.
unsigned ArgSizeNoVarargs = std::min(Function->param_size(), Args.size());
@@ -6198,7 +6336,7 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
// (CUDA B.1): Check for invalid calls between targets.
if (getLangOpts().CUDA)
if (const FunctionDecl *Caller = dyn_cast<FunctionDecl>(CurContext))
- if (CheckCUDATarget(Caller, Method)) {
+ if (!IsAllowedCUDACall(Caller, Method)) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_target;
return;
@@ -7538,12 +7676,12 @@ public:
}
// C++ [over.match.oper]p16:
- // For every pointer to member type T, there exist candidate operator
- // functions of the form
+ // For every pointer to member type T or type std::nullptr_t, there
+ // exist candidate operator functions of the form
//
// bool operator==(T,T);
// bool operator!=(T,T);
- void addEqualEqualOrNotEqualMemberPointerOverloads() {
+ void addEqualEqualOrNotEqualMemberPointerOrNullptrOverloads() {
/// Set of (canonical) types that we've already handled.
llvm::SmallPtrSet<QualType, 8> AddedTypes;
@@ -7560,13 +7698,22 @@ public:
QualType ParamTypes[2] = { *MemPtr, *MemPtr };
S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args, CandidateSet);
}
+
+ if (CandidateTypes[ArgIdx].hasNullPtrType()) {
+ CanQualType NullPtrTy = S.Context.getCanonicalType(S.Context.NullPtrTy);
+ if (AddedTypes.insert(NullPtrTy).second) {
+ QualType ParamTypes[2] = { NullPtrTy, NullPtrTy };
+ S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args,
+ CandidateSet);
+ }
+ }
}
}
// C++ [over.built]p15:
//
- // For every T, where T is an enumeration type, a pointer type, or
- // std::nullptr_t, there exist candidate operator functions of the form
+ // For every T, where T is an enumeration type or a pointer type,
+ // there exist candidate operator functions of the form
//
// bool operator<(T, T);
// bool operator>(T, T);
@@ -7651,17 +7798,6 @@ public:
QualType ParamTypes[2] = { *Enum, *Enum };
S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args, CandidateSet);
}
-
- if (CandidateTypes[ArgIdx].hasNullPtrType()) {
- CanQualType NullPtrTy = S.Context.getCanonicalType(S.Context.NullPtrTy);
- if (AddedTypes.insert(NullPtrTy).second &&
- !UserDefinedBinaryOperators.count(std::make_pair(NullPtrTy,
- NullPtrTy))) {
- QualType ParamTypes[2] = { NullPtrTy, NullPtrTy };
- S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args,
- CandidateSet);
- }
- }
}
}
@@ -8357,7 +8493,7 @@ void Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
case OO_EqualEqual:
case OO_ExclaimEqual:
- OpBuilder.addEqualEqualOrNotEqualMemberPointerOverloads();
+ OpBuilder.addEqualEqualOrNotEqualMemberPointerOrNullptrOverloads();
// Fall through.
case OO_Less:
@@ -8566,13 +8702,40 @@ bool clang::isBetterOverloadCandidate(Sema &S, const OverloadCandidate &Cand1,
if (Cand1.IgnoreObjectArgument || Cand2.IgnoreObjectArgument)
StartArg = 1;
+ auto IsIllFormedConversion = [&](const ImplicitConversionSequence &ICS) {
+ // We don't allow incompatible pointer conversions in C++.
+ if (!S.getLangOpts().CPlusPlus)
+ return ICS.isStandard() &&
+ ICS.Standard.Second == ICK_Incompatible_Pointer_Conversion;
+
+ // The only ill-formed conversion we allow in C++ is the string literal to
+ // char* conversion, which is only considered ill-formed after C++11.
+ return S.getLangOpts().CPlusPlus11 && !S.getLangOpts().WritableStrings &&
+ hasDeprecatedStringLiteralToCharPtrConversion(ICS);
+ };
+
+ // Define functions that don't require ill-formed conversions for a given
+ // argument to be better candidates than functions that do.
+ unsigned NumArgs = Cand1.NumConversions;
+ assert(Cand2.NumConversions == NumArgs && "Overload candidate mismatch");
+ bool HasBetterConversion = false;
+ for (unsigned ArgIdx = StartArg; ArgIdx < NumArgs; ++ArgIdx) {
+ bool Cand1Bad = IsIllFormedConversion(Cand1.Conversions[ArgIdx]);
+ bool Cand2Bad = IsIllFormedConversion(Cand2.Conversions[ArgIdx]);
+ if (Cand1Bad != Cand2Bad) {
+ if (Cand1Bad)
+ return false;
+ HasBetterConversion = true;
+ }
+ }
+
+ if (HasBetterConversion)
+ return true;
+
// C++ [over.match.best]p1:
// A viable function F1 is defined to be a better function than another
// viable function F2 if for all arguments i, ICSi(F1) is not a worse
// conversion sequence than ICSi(F2), and then...
- unsigned NumArgs = Cand1.NumConversions;
- assert(Cand2.NumConversions == NumArgs && "Overload candidate mismatch");
- bool HasBetterConversion = false;
for (unsigned ArgIdx = StartArg; ArgIdx < NumArgs; ++ArgIdx) {
switch (CompareImplicitConversionSequences(S, Loc,
Cand1.Conversions[ArgIdx],
@@ -8774,8 +8937,8 @@ OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc,
std::transform(begin(), end(), std::back_inserter(Candidates),
[](OverloadCandidate &Cand) { return &Cand; });
- // [CUDA] HD->H or HD->D calls are technically not allowed by CUDA
- // but accepted by both clang and NVCC. However during a particular
+ // [CUDA] HD->H or HD->D calls are technically not allowed by CUDA but
+ // are accepted by both clang and NVCC. However, during a particular
// compilation mode only one call variant is viable. We need to
// exclude non-viable overload candidates from consideration based
// only on their host/device attributes. Specifically, if one
@@ -8864,10 +9027,9 @@ enum OverloadCandidateKind {
oc_inherited_constructor_template
};
-OverloadCandidateKind ClassifyOverloadCandidate(Sema &S,
- NamedDecl *Found,
- FunctionDecl *Fn,
- std::string &Description) {
+static OverloadCandidateKind
+ClassifyOverloadCandidate(Sema &S, NamedDecl *Found, FunctionDecl *Fn,
+ std::string &Description) {
bool isTemplate = false;
if (FunctionTemplateDecl *FunTmpl = Fn->getPrimaryTemplate()) {
@@ -8960,8 +9122,9 @@ static bool checkAddressOfFunctionIsAvailable(Sema &S, const FunctionDecl *FD,
return false;
}
- auto I = llvm::find_if(
- FD->parameters(), std::mem_fn(&ParmVarDecl::hasAttr<PassObjectSizeAttr>));
+ auto I = llvm::find_if(FD->parameters(), [](const ParmVarDecl *P) {
+ return P->hasAttr<PassObjectSizeAttr>();
+ });
if (I == FD->param_end())
return true;
@@ -9003,7 +9166,7 @@ void Sema::NoteOverloadCandidate(NamedDecl *Found, FunctionDecl *Fn,
std::string FnDesc;
OverloadCandidateKind K = ClassifyOverloadCandidate(*this, Found, Fn, FnDesc);
PartialDiagnostic PD = PDiag(diag::note_ovl_candidate)
- << (unsigned) K << FnDesc;
+ << (unsigned) K << Fn << FnDesc;
HandleFunctionTypeMismatch(PD, Fn->getType(), DestType);
Diag(Fn->getLocation(), PD);
@@ -9436,9 +9599,25 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated,
int which = 0;
if (isa<TemplateTypeParmDecl>(ParamD))
which = 0;
- else if (isa<NonTypeTemplateParmDecl>(ParamD))
+ else if (isa<NonTypeTemplateParmDecl>(ParamD)) {
+ // Deduction might have failed because we deduced arguments of two
+ // different types for a non-type template parameter.
+ // FIXME: Use a different TDK value for this.
+ QualType T1 =
+ DeductionFailure.getFirstArg()->getNonTypeTemplateArgumentType();
+ QualType T2 =
+ DeductionFailure.getSecondArg()->getNonTypeTemplateArgumentType();
+ if (!S.Context.hasSameType(T1, T2)) {
+ S.Diag(Templated->getLocation(),
+ diag::note_ovl_candidate_inconsistent_deduction_types)
+ << ParamD->getDeclName() << *DeductionFailure.getFirstArg() << T1
+ << *DeductionFailure.getSecondArg() << T2;
+ MaybeEmitInheritedConstructorNote(S, Found);
+ return;
+ }
+
which = 1;
- else {
+ } else {
which = 2;
}
@@ -9592,6 +9771,10 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated,
S.Diag(Templated->getLocation(), diag::note_ovl_candidate_bad_deduction);
MaybeEmitInheritedConstructorNote(S, Found);
return;
+ case Sema::TDK_CUDATargetMismatch:
+ S.Diag(Templated->getLocation(),
+ diag::note_cuda_ovl_candidate_target_mismatch);
+ return;
}
}
@@ -9673,6 +9856,13 @@ static void DiagnoseFailedEnableIfAttr(Sema &S, OverloadCandidate *Cand) {
<< Attr->getCond()->getSourceRange() << Attr->getMessage();
}
+static void DiagnoseOpenCLExtensionDisabled(Sema &S, OverloadCandidate *Cand) {
+ FunctionDecl *Callee = Cand->Function;
+
+ S.Diag(Callee->getLocation(),
+ diag::note_ovl_candidate_disabled_by_extension);
+}
+
/// Generates a 'note' diagnostic for an overload candidate. We've
/// already generated a primary error at the call site.
///
@@ -9750,6 +9940,9 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
case ovl_fail_enable_if:
return DiagnoseFailedEnableIfAttr(S, Cand);
+ case ovl_fail_ext_disabled:
+ return DiagnoseOpenCLExtensionDisabled(S, Cand);
+
case ovl_fail_addr_not_available: {
bool Available = checkAddressOfCandidateIsAvailable(S, Cand->Function);
(void)Available;
@@ -9848,6 +10041,7 @@ static unsigned RankDeductionFailure(const DeductionFailureInfo &DFI) {
case Sema::TDK_DeducedMismatch:
case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_MiscellaneousDeductionFailure:
+ case Sema::TDK_CUDATargetMismatch:
return 3;
case Sema::TDK_InstantiationDepth:
@@ -10074,16 +10268,17 @@ static void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand,
/// PrintOverloadCandidates - 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) {
+void OverloadCandidateSet::NoteCandidates(
+ Sema &S, OverloadCandidateDisplayKind OCD, ArrayRef<Expr *> Args,
+ StringRef Opc, SourceLocation OpLoc,
+ llvm::function_ref<bool(OverloadCandidate &)> Filter) {
// Sort the candidates by viability and position. Sorting directly would
// be prohibitive, so we make a set of pointers and sort those.
SmallVector<OverloadCandidate*, 32> Cands;
if (OCD == OCD_AllCandidates) Cands.reserve(size());
for (iterator Cand = begin(), LastCand = end(); Cand != LastCand; ++Cand) {
+ if (!Filter(*Cand))
+ continue;
if (Cand->Viable)
Cands.push_back(Cand);
else if (OCD == OCD_AllCandidates) {
@@ -10269,6 +10464,21 @@ QualType Sema::ExtractUnqualifiedFunctionType(QualType PossiblyAFunctionType) {
return Ret;
}
+static bool completeFunctionType(Sema &S, FunctionDecl *FD, SourceLocation Loc,
+ bool Complain = true) {
+ if (S.getLangOpts().CPlusPlus14 && FD->getReturnType()->isUndeducedType() &&
+ S.DeduceReturnType(FD, Loc, Complain))
+ return true;
+
+ auto *FPT = FD->getType()->castAs<FunctionProtoType>();
+ if (S.getLangOpts().CPlusPlus1z &&
+ isUnresolvedExceptionSpec(FPT->getExceptionSpecType()) &&
+ !S.ResolveExceptionSpec(Loc, FPT))
+ return true;
+
+ return false;
+}
+
namespace {
// A helper class to help with address of function resolution
// - allows us to avoid passing around all those ugly parameters
@@ -10359,7 +10569,7 @@ private:
bool candidateHasExactlyCorrectType(const FunctionDecl *FD) {
QualType Discard;
return Context.hasSameUnqualifiedType(TargetFunctionType, FD->getType()) ||
- S.IsNoReturnConversion(FD->getType(), TargetFunctionType, Discard);
+ S.IsFunctionConversion(FD->getType(), TargetFunctionType, Discard);
}
/// \return true if A is considered a better overload candidate for the
@@ -10436,7 +10646,7 @@ private:
= S.DeduceTemplateArguments(FunctionTemplate,
&OvlExplicitTemplateArgs,
TargetFunctionType, Specialization,
- Info, /*InOverloadResolution=*/true)) {
+ Info, /*IsAddressOfFunction*/true)) {
// Make a note of the failed deduction for diagnostics.
FailedCandidates.addCandidate()
.set(CurAccessFunPair, FunctionTemplate->getTemplatedDecl(),
@@ -10472,14 +10682,13 @@ private:
if (FunctionDecl *FunDecl = dyn_cast<FunctionDecl>(Fn)) {
if (S.getLangOpts().CUDA)
if (FunctionDecl *Caller = dyn_cast<FunctionDecl>(S.CurContext))
- if (!Caller->isImplicit() && S.CheckCUDATarget(Caller, FunDecl))
+ if (!Caller->isImplicit() && !S.IsAllowedCUDACall(Caller, FunDecl))
return false;
// If any candidate has a placeholder return type, trigger its deduction
// now.
- if (S.getLangOpts().CPlusPlus14 &&
- FunDecl->getReturnType()->isUndeducedType() &&
- S.DeduceReturnType(FunDecl, SourceExpr->getLocStart(), Complain)) {
+ if (completeFunctionType(S, FunDecl, SourceExpr->getLocStart(),
+ Complain)) {
HasComplained |= Complain;
return false;
}
@@ -10704,6 +10913,8 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr,
else if (NumMatches == 1) {
Fn = Resolver.getMatchingFunctionDecl();
assert(Fn);
+ if (auto *FPT = Fn->getType()->getAs<FunctionProtoType>())
+ ResolveExceptionSpec(AddressOfExpr->getExprLoc(), FPT);
FoundResult = *Resolver.getMatchingFunctionAccessPair();
if (Complain) {
if (Resolver.IsStaticMemberFunctionFromBoundPointer())
@@ -10838,7 +11049,7 @@ Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl,
if (TemplateDeductionResult Result
= DeduceTemplateArguments(FunctionTemplate, &ExplicitTemplateArgs,
Specialization, Info,
- /*InOverloadResolution=*/true)) {
+ /*IsAddressOfFunction*/true)) {
// Make a note of the failed deduction for diagnostics.
// TODO: Actually use the failed-deduction info?
FailedCandidates.addCandidate()
@@ -10863,9 +11074,8 @@ Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl,
if (FoundResult) *FoundResult = I.getPair();
}
- if (Matched && getLangOpts().CPlusPlus14 &&
- Matched->getReturnType()->isUndeducedType() &&
- DeduceReturnType(Matched, ovl->getExprLoc(), Complain))
+ if (Matched &&
+ completeFunctionType(*this, Matched, ovl->getExprLoc(), Complain))
return nullptr;
return Matched;
@@ -11255,6 +11465,12 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
assert(!R.empty() && "lookup results empty despite recovery");
+ // If recovery created an ambiguity, just bail out.
+ if (R.isAmbiguous()) {
+ R.suppressDiagnostics();
+ return ExprError();
+ }
+
// Build an implicit member call if appropriate. Just drop the
// casts and such from the call, we don't really care.
ExprResult NewFn = ExprError();
@@ -12331,18 +12547,6 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
new (Context) CXXMemberCallExpr(Context, MemExprE, Args,
ResultType, VK, RParenLoc);
- // (CUDA B.1): Check for invalid calls between targets.
- if (getLangOpts().CUDA) {
- if (const FunctionDecl *Caller = dyn_cast<FunctionDecl>(CurContext)) {
- if (CheckCUDATarget(Caller, Method)) {
- Diag(MemExpr->getMemberLoc(), diag::err_ref_bad_target)
- << IdentifyCUDATarget(Method) << Method->getIdentifier()
- << IdentifyCUDATarget(Caller);
- return ExprError();
- }
- }
- }
-
// Check for a valid return type.
if (CheckCallReturnType(Method->getReturnType(), MemExpr->getMemberLoc(),
TheCall, Method))
@@ -12374,10 +12578,10 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
// In the case the method to call was not selected by the overloading
// resolution process, we still need to handle the enable_if attribute. Do
- // that here, so it will not hide previous -- and more relevant -- errors
- if (isa<MemberExpr>(NakedMemExpr)) {
+ // that here, so it will not hide previous -- and more relevant -- errors.
+ if (auto *MemE = dyn_cast<MemberExpr>(NakedMemExpr)) {
if (const EnableIfAttr *Attr = CheckEnableIf(Method, Args, true)) {
- Diag(MemExprE->getLocStart(),
+ Diag(MemE->getMemberLoc(),
diag::err_ovl_no_viable_member_function_in_call)
<< Method << Method->getSourceRange();
Diag(Method->getLocation(),
@@ -12619,9 +12823,9 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
// Build the full argument list for the method call (the implicit object
// parameter is placed at the beginning of the list).
- std::unique_ptr<Expr * []> MethodArgs(new Expr *[Args.size() + 1]);
+ SmallVector<Expr *, 8> MethodArgs(Args.size() + 1);
MethodArgs[0] = Object.get();
- std::copy(Args.begin(), Args.end(), &MethodArgs[1]);
+ std::copy(Args.begin(), Args.end(), MethodArgs.begin() + 1);
// Once we've built TheCall, all of the expressions are properly
// owned.
@@ -12630,10 +12834,8 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
ResultTy = ResultTy.getNonLValueExprType(Context);
CXXOperatorCallExpr *TheCall = new (Context)
- CXXOperatorCallExpr(Context, OO_Call, NewFn.get(),
- llvm::makeArrayRef(MethodArgs.get(), Args.size() + 1),
- ResultTy, VK, RParenLoc, false);
- MethodArgs.reset();
+ CXXOperatorCallExpr(Context, OO_Call, NewFn.get(), MethodArgs, ResultTy,
+ VK, RParenLoc, false);
if (CheckCallReturnType(Method->getReturnType(), LParenLoc, TheCall, Method))
return true;
@@ -12996,6 +13198,31 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
ICE->getValueKind());
}
+ if (auto *GSE = dyn_cast<GenericSelectionExpr>(E)) {
+ if (!GSE->isResultDependent()) {
+ Expr *SubExpr =
+ FixOverloadedFunctionReference(GSE->getResultExpr(), Found, Fn);
+ if (SubExpr == GSE->getResultExpr())
+ return GSE;
+
+ // Replace the resulting type information before rebuilding the generic
+ // selection expression.
+ ArrayRef<Expr *> A = GSE->getAssocExprs();
+ SmallVector<Expr *, 4> AssocExprs(A.begin(), A.end());
+ unsigned ResultIdx = GSE->getResultIndex();
+ AssocExprs[ResultIdx] = SubExpr;
+
+ return new (Context) GenericSelectionExpr(
+ Context, GSE->getGenericLoc(), GSE->getControllingExpr(),
+ GSE->getAssocTypeSourceInfos(), AssocExprs, GSE->getDefaultLoc(),
+ GSE->getRParenLoc(), GSE->containsUnexpandedParameterPack(),
+ ResultIdx);
+ }
+ // Rather than fall through to the unreachable, return the original generic
+ // selection expression.
+ return GSE;
+ }
+
if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(E)) {
assert(UnOp->getOpcode() == UO_AddrOf &&
"Can only take the address of an overloaded function");
@@ -13044,6 +13271,13 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
UnOp->getOperatorLoc());
}
+ // C++ [except.spec]p17:
+ // An exception-specification is considered to be needed when:
+ // - in an expression the function is the unique lookup result or the
+ // selected member of a set of overloaded functions
+ if (auto *FPT = Fn->getType()->getAs<FunctionProtoType>())
+ ResolveExceptionSpec(E->getExprLoc(), FPT);
+
if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(E)) {
// FIXME: avoid copy.
TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = nullptr;
diff --git a/lib/Sema/SemaPseudoObject.cpp b/lib/Sema/SemaPseudoObject.cpp
index c93d800f96d1..8e53fda846f4 100644
--- a/lib/Sema/SemaPseudoObject.cpp
+++ b/lib/Sema/SemaPseudoObject.cpp
@@ -661,7 +661,7 @@ bool ObjCPropertyOpBuilder::findSetter(bool warn) {
if (ObjCPropertyDecl *prop1 = IFace->FindPropertyDeclaration(
AltMember, prop->getQueryKind()))
if (prop != prop1 && (prop1->getSetterMethodDecl() == setter)) {
- S.Diag(RefExpr->getExprLoc(), diag::error_property_setter_ambiguous_use)
+ S.Diag(RefExpr->getExprLoc(), diag::err_property_setter_ambiguous_use)
<< prop << prop1 << setter->getSelector();
S.Diag(prop->getLocation(), diag::note_property_declare);
S.Diag(prop1->getLocation(), diag::note_property_declare);
@@ -770,7 +770,8 @@ ExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation opcLoc,
ExprResult opResult = op;
Sema::AssignConvertType assignResult
= S.CheckSingleAssignmentConstraints(paramType, opResult);
- if (S.DiagnoseAssignmentResult(assignResult, opcLoc, paramType,
+ if (opResult.isInvalid() ||
+ S.DiagnoseAssignmentResult(assignResult, opcLoc, paramType,
op->getType(), opResult.get(),
Sema::AA_Assigning))
return ExprError();
@@ -1103,8 +1104,9 @@ Sema::ObjCSubscriptKind
Diag(FromE->getExprLoc(), diag::err_objc_multiple_subscript_type_conversion)
<< FromE->getType();
for (unsigned int i = 0; i < ConversionDecls.size(); i++)
- Diag(ConversionDecls[i]->getLocation(), diag::not_conv_function_declared_at);
-
+ Diag(ConversionDecls[i]->getLocation(),
+ diag::note_conv_function_declared_at);
+
return OS_Error;
}
@@ -1479,7 +1481,7 @@ ExprResult MSPropertyOpBuilder::buildGet() {
SourceLocation(), GetterName, nullptr);
if (GetterExpr.isInvalid()) {
S.Diag(RefExpr->getMemberLoc(),
- diag::error_cannot_find_suitable_accessor) << 0 /* getter */
+ diag::err_cannot_find_suitable_accessor) << 0 /* getter */
<< RefExpr->getPropertyDecl();
return ExprError();
}
@@ -1508,7 +1510,7 @@ ExprResult MSPropertyOpBuilder::buildSet(Expr *op, SourceLocation sl,
SourceLocation(), SetterName, nullptr);
if (SetterExpr.isInvalid()) {
S.Diag(RefExpr->getMemberLoc(),
- diag::error_cannot_find_suitable_accessor) << 1 /* setter */
+ diag::err_cannot_find_suitable_accessor) << 1 /* setter */
<< RefExpr->getPropertyDecl();
return ExprError();
}
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index 8e8104e581b2..50f0a22ff02b 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -536,7 +536,7 @@ StmtResult Sema::BuildIfStmt(SourceLocation IfLoc, bool IsConstexpr,
if (Cond.isInvalid())
return StmtError();
- if (IsConstexpr)
+ if (IsConstexpr || isa<ObjCAvailabilityCheckExpr>(Cond.get().second))
getCurFunction()->setHasBranchProtectedScope();
DiagnoseUnusedExprResult(thenStmt);
@@ -1070,7 +1070,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) {
+ if (!CaseListIsErroneous && !HasConstantCond && ET &&
+ ET->getDecl()->isCompleteDefinition()) {
const EnumDecl *ED = ET->getDecl();
EnumValsTy EnumVals;
@@ -3193,6 +3194,10 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
if (FD->isNoReturn())
Diag(ReturnLoc, diag::warn_noreturn_function_has_return_expr)
<< FD->getDeclName();
+ if (FD->isMain() && RetValExp)
+ if (isa<CXXBoolLiteralExpr>(RetValExp))
+ Diag(ReturnLoc, diag::warn_main_returns_bool_literal)
+ << RetValExp->getSourceRange();
} else if (ObjCMethodDecl *MD = getCurMethodDecl()) {
FnRetType = MD->getReturnType();
isObjCMethod = true;
@@ -3447,7 +3452,7 @@ StmtResult Sema::BuildObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw) {
!ThrowType->isObjCObjectPointerType()) {
const PointerType *PT = ThrowType->getAs<PointerType>();
if (!PT || !PT->getPointeeType()->isVoidType())
- return StmtError(Diag(AtLoc, diag::error_objc_throw_expects_object)
+ return StmtError(Diag(AtLoc, diag::err_objc_throw_expects_object)
<< Throw->getType() << Throw->getSourceRange());
}
}
@@ -3468,7 +3473,7 @@ Sema::ActOnObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw,
while (AtCatchParent && !AtCatchParent->isAtCatchScope())
AtCatchParent = AtCatchParent->getParent();
if (!AtCatchParent)
- return StmtError(Diag(AtLoc, diag::error_rethrow_used_outside_catch));
+ return StmtError(Diag(AtLoc, diag::err_rethrow_used_outside_catch));
}
return BuildObjCAtThrowStmt(AtLoc, Throw);
}
@@ -3489,17 +3494,19 @@ Sema::ActOnObjCAtSynchronizedOperand(SourceLocation atLoc, Expr *operand) {
if (getLangOpts().CPlusPlus) {
if (RequireCompleteType(atLoc, type,
diag::err_incomplete_receiver_type))
- return Diag(atLoc, diag::error_objc_synchronized_expects_object)
+ return Diag(atLoc, diag::err_objc_synchronized_expects_object)
<< type << operand->getSourceRange();
ExprResult result = PerformContextuallyConvertToObjCPointer(operand);
+ if (result.isInvalid())
+ return ExprError();
if (!result.isUsable())
- return Diag(atLoc, diag::error_objc_synchronized_expects_object)
+ return Diag(atLoc, diag::err_objc_synchronized_expects_object)
<< type << operand->getSourceRange();
operand = result.get();
} else {
- return Diag(atLoc, diag::error_objc_synchronized_expects_object)
+ return Diag(atLoc, diag::err_objc_synchronized_expects_object)
<< type << operand->getSourceRange();
}
}
@@ -3644,6 +3651,11 @@ StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
!getSourceManager().isInSystemHeader(TryLoc))
Diag(TryLoc, diag::err_exceptions_disabled) << "try";
+ // Exceptions aren't allowed in CUDA device code.
+ if (getLangOpts().CUDA)
+ CUDADiagIfDeviceCode(TryLoc, diag::err_cuda_device_exceptions)
+ << "try" << CurrentCUDATarget();
+
if (getCurScope() && getCurScope()->isOpenMPSimdDirectiveScope())
Diag(TryLoc, diag::err_omp_simd_region_cannot_use_stmt) << "try";
diff --git a/lib/Sema/SemaStmtAsm.cpp b/lib/Sema/SemaStmtAsm.cpp
index cd4269cd7eae..76de9e299399 100644
--- a/lib/Sema/SemaStmtAsm.cpp
+++ b/lib/Sema/SemaStmtAsm.cpp
@@ -11,7 +11,6 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Sema/SemaInternal.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/TypeLoc.h"
@@ -21,8 +20,9 @@
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
+#include "clang/Sema/SemaInternal.h"
#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/StringSet.h"
#include "llvm/MC/MCParser/MCAsmParser.h"
using namespace clang;
using namespace sema;
@@ -138,6 +138,56 @@ static bool checkExprMemoryConstraintCompat(Sema &S, Expr *E,
return false;
}
+// Extracting the register name from the Expression value,
+// if there is no register name to extract, returns ""
+static StringRef extractRegisterName(const Expr *Expression,
+ const TargetInfo &Target) {
+ Expression = Expression->IgnoreImpCasts();
+ if (const DeclRefExpr *AsmDeclRef = dyn_cast<DeclRefExpr>(Expression)) {
+ // Handle cases where the expression is a variable
+ const VarDecl *Variable = dyn_cast<VarDecl>(AsmDeclRef->getDecl());
+ if (Variable && Variable->getStorageClass() == SC_Register) {
+ if (AsmLabelAttr *Attr = Variable->getAttr<AsmLabelAttr>())
+ if (Target.isValidGCCRegisterName(Attr->getLabel()))
+ return Target.getNormalizedGCCRegisterName(Attr->getLabel(), true);
+ }
+ }
+ return "";
+}
+
+// Checks if there is a conflict between the input and output lists with the
+// clobbers list. If there's a conflict, returns the location of the
+// conflicted clobber, else returns nullptr
+static SourceLocation
+getClobberConflictLocation(MultiExprArg Exprs, StringLiteral **Constraints,
+ StringLiteral **Clobbers, int NumClobbers,
+ const TargetInfo &Target, ASTContext &Cont) {
+ llvm::StringSet<> InOutVars;
+ // Collect all the input and output registers from the extended asm
+ // statement in order to check for conflicts with the clobber list
+ for (unsigned int i = 0; i < Exprs.size(); ++i) {
+ StringRef Constraint = Constraints[i]->getString();
+ StringRef InOutReg = Target.getConstraintRegister(
+ Constraint, extractRegisterName(Exprs[i], Target));
+ if (InOutReg != "")
+ InOutVars.insert(InOutReg);
+ }
+ // Check for each item in the clobber list if it conflicts with the input
+ // or output
+ for (int i = 0; i < NumClobbers; ++i) {
+ StringRef Clobber = Clobbers[i]->getString();
+ // We only check registers, therefore we don't check cc and memory
+ // clobbers
+ if (Clobber == "cc" || Clobber == "memory")
+ continue;
+ Clobber = Target.getNormalizedGCCRegisterName(Clobber, true);
+ // Go over the output's registers we collected
+ if (InOutVars.count(Clobber))
+ return Clobbers[i]->getLocStart();
+ }
+ return SourceLocation();
+}
+
StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
bool IsVolatile, unsigned NumOutputs,
unsigned NumInputs, IdentifierInfo **Names,
@@ -544,6 +594,13 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
return StmtError();
}
+ // Check for conflicts between clobber list and input or output lists
+ SourceLocation ConstraintLoc =
+ getClobberConflictLocation(Exprs, Constraints, Clobbers, NumClobbers,
+ Context.getTargetInfo(), Context);
+ if (ConstraintLoc.isValid())
+ return Diag(ConstraintLoc, diag::error_inoutput_conflict_with_clobber);
+
return NS;
}
@@ -751,17 +808,17 @@ LabelDecl *Sema::GetOrCreateMSAsmLabel(StringRef ExternalLabelName,
// Otherwise, insert it, but only resolve it if we have seen the label itself.
std::string InternalName;
llvm::raw_string_ostream OS(InternalName);
- // Create an internal name for the label. The name should not be a valid mangled
- // name, and should be unique. We use a dot to make the name an invalid mangled
- // name.
- OS << "__MSASMLABEL_." << MSAsmLabelNameCounter++ << "__";
- for (auto it = ExternalLabelName.begin(); it != ExternalLabelName.end();
- ++it) {
- OS << *it;
- if (*it == '$') {
- // We escape '$' in asm strings by replacing it with "$$"
+ // Create an internal name for the label. The name should not be a valid
+ // mangled name, and should be unique. We use a dot to make the name an
+ // invalid mangled name. We use LLVM's inline asm ${:uid} escape so that a
+ // unique label is generated each time this blob is emitted, even after
+ // inlining or LTO.
+ OS << "__MSASMLABEL_.${:uid}__";
+ for (char C : ExternalLabelName) {
+ OS << C;
+ // We escape '$' in asm strings by replacing it with "$$"
+ if (C == '$')
OS << '$';
- }
}
Label->setMSAsmLabel(OS.str());
}
diff --git a/lib/Sema/SemaStmtAttr.cpp b/lib/Sema/SemaStmtAttr.cpp
index 87fd88939572..01fa856132d7 100644
--- a/lib/Sema/SemaStmtAttr.cpp
+++ b/lib/Sema/SemaStmtAttr.cpp
@@ -225,16 +225,12 @@ CheckForIncompatibleAttributes(Sema &S,
static Attr *handleOpenCLUnrollHint(Sema &S, Stmt *St, const AttributeList &A,
SourceRange Range) {
- // OpenCL v2.0 s6.11.5 - opencl_unroll_hint can have 0 arguments (compiler
+ // 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.
+ // opencl_unroll_hint can have 0 arguments (compiler
// determines unrolling factor) or 1 argument (the unroll factor provided
// by the user).
- if (S.getLangOpts().OpenCLVersion < 200) {
- S.Diag(A.getLoc(), diag::err_attribute_requires_opencl_version)
- << A.getName() << "2.0" << 1;
- return nullptr;
- }
-
unsigned NumArgs = A.getNumArgs();
if (NumArgs > 1) {
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 72e499342f8f..facc5d1b375b 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -88,14 +88,14 @@ static NamedDecl *isAcceptableTemplateName(ASTContext &Context,
return nullptr;
}
-void Sema::FilterAcceptableTemplateNames(LookupResult &R,
+void Sema::FilterAcceptableTemplateNames(LookupResult &R,
bool AllowFunctionTemplates) {
// The set of class templates we've already seen.
llvm::SmallPtrSet<ClassTemplateDecl *, 8> ClassTemplates;
LookupResult::Filter filter = R.makeFilter();
while (filter.hasNext()) {
NamedDecl *Orig = filter.next();
- NamedDecl *Repl = isAcceptableTemplateName(Context, Orig,
+ NamedDecl *Repl = isAcceptableTemplateName(Context, Orig,
AllowFunctionTemplates);
if (!Repl)
filter.erase();
@@ -131,7 +131,7 @@ bool Sema::hasAnyAcceptableTemplateNames(LookupResult &R,
for (LookupResult::iterator I = R.begin(), IEnd = R.end(); I != IEnd; ++I)
if (isAcceptableTemplateName(Context, *I, AllowFunctionTemplates))
return true;
-
+
return false;
}
@@ -265,7 +265,7 @@ void Sema::LookupTemplateName(LookupResult &Found,
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();
@@ -312,7 +312,7 @@ void Sema::LookupTemplateName(LookupResult &Found,
} else {
// Perform unqualified name lookup in the current scope.
LookupName(Found, S);
-
+
if (!ObjectType.isNull())
AllowFunctionTemplatesInLookup = false;
}
@@ -429,7 +429,12 @@ Sema::ActOnDependentIdExpression(const CXXScopeSpec &SS,
bool MightBeCxx11UnevalField =
getLangOpts().CPlusPlus11 && isUnevaluatedContext();
- if (!MightBeCxx11UnevalField && !isAddressOfOperand &&
+ // Check if the nested name specifier is an enum type.
+ bool IsEnum = false;
+ if (NestedNameSpecifier *NNS = SS.getScopeRep())
+ IsEnum = dyn_cast_or_null<EnumType>(NNS->getAsType());
+
+ if (!MightBeCxx11UnevalField && !isAddressOfOperand && !IsEnum &&
isa<CXXMethodDecl>(DC) && cast<CXXMethodDecl>(DC)->isInstance()) {
QualType ThisType = cast<CXXMethodDecl>(DC)->getThisType(Context);
@@ -456,6 +461,104 @@ Sema::BuildDependentDeclRefExpr(const CXXScopeSpec &SS,
TemplateArgs);
}
+
+/// Determine whether we would be unable to instantiate this template (because
+/// it either has no definition, or is in the process of being instantiated).
+bool Sema::DiagnoseUninstantiableTemplate(SourceLocation PointOfInstantiation,
+ NamedDecl *Instantiation,
+ bool InstantiatedFromMember,
+ const NamedDecl *Pattern,
+ const NamedDecl *PatternDef,
+ TemplateSpecializationKind TSK,
+ bool Complain /*= true*/) {
+ assert(isa<TagDecl>(Instantiation) || isa<FunctionDecl>(Instantiation) ||
+ isa<VarDecl>(Instantiation));
+
+ bool IsEntityBeingDefined = false;
+ if (const TagDecl *TD = dyn_cast_or_null<TagDecl>(PatternDef))
+ IsEntityBeingDefined = TD->isBeingDefined();
+
+ if (PatternDef && !IsEntityBeingDefined) {
+ NamedDecl *SuggestedDef = nullptr;
+ if (!hasVisibleDefinition(const_cast<NamedDecl*>(PatternDef), &SuggestedDef,
+ /*OnlyNeedComplete*/false)) {
+ // If we're allowed to diagnose this and recover, do so.
+ bool Recover = Complain && !isSFINAEContext();
+ if (Complain)
+ diagnoseMissingImport(PointOfInstantiation, SuggestedDef,
+ Sema::MissingImportKind::Definition, Recover);
+ return !Recover;
+ }
+ return false;
+ }
+
+ if (!Complain || (PatternDef && PatternDef->isInvalidDecl()))
+ return true;
+
+ llvm::Optional<unsigned> Note;
+ QualType InstantiationTy;
+ if (TagDecl *TD = dyn_cast<TagDecl>(Instantiation))
+ InstantiationTy = Context.getTypeDeclType(TD);
+ if (PatternDef) {
+ Diag(PointOfInstantiation,
+ diag::err_template_instantiate_within_definition)
+ << /*implicit|explicit*/(TSK != TSK_ImplicitInstantiation)
+ << InstantiationTy;
+ // Not much point in noting the template declaration here, since
+ // we're lexically inside it.
+ Instantiation->setInvalidDecl();
+ } else if (InstantiatedFromMember) {
+ if (isa<FunctionDecl>(Instantiation)) {
+ Diag(PointOfInstantiation,
+ diag::err_explicit_instantiation_undefined_member)
+ << /*member function*/ 1 << Instantiation->getDeclName()
+ << Instantiation->getDeclContext();
+ Note = diag::note_explicit_instantiation_here;
+ } else {
+ assert(isa<TagDecl>(Instantiation) && "Must be a TagDecl!");
+ Diag(PointOfInstantiation,
+ diag::err_implicit_instantiate_member_undefined)
+ << InstantiationTy;
+ Note = diag::note_member_declared_at;
+ }
+ } else {
+ if (isa<FunctionDecl>(Instantiation)) {
+ Diag(PointOfInstantiation,
+ diag::err_explicit_instantiation_undefined_func_template)
+ << Pattern;
+ Note = diag::note_explicit_instantiation_here;
+ } else if (isa<TagDecl>(Instantiation)) {
+ Diag(PointOfInstantiation, diag::err_template_instantiate_undefined)
+ << (TSK != TSK_ImplicitInstantiation)
+ << InstantiationTy;
+ Note = diag::note_template_decl_here;
+ } else {
+ assert(isa<VarDecl>(Instantiation) && "Must be a VarDecl!");
+ if (isa<VarTemplateSpecializationDecl>(Instantiation)) {
+ Diag(PointOfInstantiation,
+ diag::err_explicit_instantiation_undefined_var_template)
+ << Instantiation;
+ Instantiation->setInvalidDecl();
+ } else
+ Diag(PointOfInstantiation,
+ diag::err_explicit_instantiation_undefined_member)
+ << /*static data member*/ 2 << Instantiation->getDeclName()
+ << Instantiation->getDeclContext();
+ Note = diag::note_explicit_instantiation_here;
+ }
+ }
+ if (Note) // Diagnostics were emitted.
+ Diag(Pattern->getLocation(), Note.getValue());
+
+ // In general, Instantiation isn't marked invalid to get more than one
+ // error for multiple undefined instantiations. But the code that does
+ // explicit declaration -> explicit definition conversion can't handle
+ // invalid declarations, so mark as invalid in that case.
+ if (TSK == TSK_ExplicitInstantiationDeclaration)
+ Instantiation->setInvalidDecl();
+ return true;
+}
+
/// DiagnoseTemplateParameterShadow - Produce a diagnostic complaining
/// that the template parameter 'PrevDecl' is being shadowed by a new
/// declaration at location Loc. Returns true to indicate that this is
@@ -626,8 +729,22 @@ Decl *Sema::ActOnTypeParameter(Scope *S, bool Typename,
///
/// \returns the (possibly-promoted) parameter type if valid;
/// otherwise, produces a diagnostic and returns a NULL type.
-QualType
-Sema::CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc) {
+QualType Sema::CheckNonTypeTemplateParameterType(TypeSourceInfo *&TSI,
+ SourceLocation Loc) {
+ if (TSI->getType()->isUndeducedType()) {
+ // C++1z [temp.dep.expr]p3:
+ // An id-expression is type-dependent if it contains
+ // - an identifier associated by name lookup with a non-type
+ // template-parameter declared with a type that contains a
+ // placeholder type (7.1.7.4),
+ TSI = SubstAutoTypeSourceInfo(TSI, Context.DependentTy);
+ }
+
+ return CheckNonTypeTemplateParameterType(TSI->getType(), Loc);
+}
+
+QualType Sema::CheckNonTypeTemplateParameterType(QualType T,
+ SourceLocation Loc) {
// We don't allow variably-modified types as the type of non-type template
// parameters.
if (T->isVariablyModifiedType()) {
@@ -653,7 +770,9 @@ Sema::CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc) {
T->isNullPtrType() ||
// If T is a dependent type, we can't do the check now, so we
// assume that it is well-formed.
- T->isDependentType()) {
+ T->isDependentType() ||
+ // Allow use of auto in template parameter declarations.
+ T->isUndeducedType()) {
// C++ [temp.param]p5: The top-level cv-qualifiers on the template-parameter
// are ignored when determining its type.
return T.getUnqualifiedType();
@@ -679,13 +798,18 @@ Decl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
SourceLocation EqualLoc,
Expr *Default) {
TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
- QualType T = TInfo->getType();
+
+ if (TInfo->getType()->isUndeducedType()) {
+ Diag(D.getIdentifierLoc(),
+ diag::warn_cxx14_compat_template_nontype_parm_auto_type)
+ << QualType(TInfo->getType()->getContainedAutoType(), 0);
+ }
assert(S->isTemplateParamScope() &&
"Non-type template parameter not in template parameter scope!");
bool Invalid = false;
- T = CheckNonTypeTemplateParameterType(T, D.getIdentifierLoc());
+ QualType T = CheckNonTypeTemplateParameterType(TInfo, D.getIdentifierLoc());
if (T.isNull()) {
T = Context.IntTy; // Recover with an 'int' type.
Invalid = true;
@@ -766,7 +890,7 @@ Decl *Sema::ActOnTemplateTemplateParameter(Scope* S,
Depth, Position, IsParameterPack,
Name, Params);
Param->setAccess(AS_public);
-
+
// If the template template parameter has a name, then link the identifier
// into the scope and lookup mechanisms.
if (Name) {
@@ -832,11 +956,10 @@ Sema::ActOnTemplateParameterList(unsigned Depth,
if (ExportLoc.isValid())
Diag(ExportLoc, diag::warn_template_export_unsupported);
- // FIXME: store RequiresClause
return TemplateParameterList::Create(
Context, TemplateLoc, LAngleLoc,
llvm::makeArrayRef((NamedDecl *const *)Params.data(), Params.size()),
- RAngleLoc);
+ RAngleLoc, RequiresClause);
}
static void SetNestedNameSpecifier(TagDecl *T, const CXXScopeSpec &SS) {
@@ -897,8 +1020,8 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
if (RequireCompleteDeclContext(SS, SemanticContext))
return true;
- // If we're adding a template to a dependent context, we may need to
- // rebuilding some of the types used within the template parameter list,
+ // If we're adding a template to a dependent context, we may need to
+ // rebuilding some of the types used within the template parameter list,
// now that we know what the current instantiation is.
if (SemanticContext->isDependentContext()) {
ContextRAII SavedContext(*this, SemanticContext);
@@ -1124,10 +1247,10 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
DeclarationName(Name), TemplateParams,
NewClass, PrevClassTemplate);
NewClass->setDescribedClassTemplate(NewTemplate);
-
+
if (ModulePrivateLoc.isValid())
NewTemplate->setModulePrivate();
-
+
// Build the type for the class template declaration now.
QualType T = NewTemplate->getInjectedClassNameSpecialization();
T = Context.getInjectedClassNameType(NewClass, T);
@@ -1218,7 +1341,7 @@ static bool DiagnoseDefaultTemplateArgument(Sema &S,
// A default template-argument shall not be specified in a
// function template declaration or a function template
// definition [...]
- // If a friend function template declaration specifies a default
+ // If a friend function template declaration specifies a default
// template-argument, that declaration shall be a definition and shall be
// the only declaration of the function template in the translation unit.
// (C++98/03 doesn't have this wording; see DR226).
@@ -1530,12 +1653,22 @@ struct DependencyChecker : RecursiveASTVisitor<DependencyChecker> {
typedef RecursiveASTVisitor<DependencyChecker> super;
unsigned Depth;
+
+ // Whether we're looking for a use of a template parameter that makes the
+ // overall construct type-dependent / a dependent type. This is strictly
+ // best-effort for now; we may fail to match at all for a dependent type
+ // in some cases if this is set.
+ bool IgnoreNonTypeDependent;
+
bool Match;
SourceLocation MatchLoc;
- DependencyChecker(unsigned Depth) : Depth(Depth), Match(false) {}
+ DependencyChecker(unsigned Depth, bool IgnoreNonTypeDependent)
+ : Depth(Depth), IgnoreNonTypeDependent(IgnoreNonTypeDependent),
+ Match(false) {}
- DependencyChecker(TemplateParameterList *Params) : Match(false) {
+ DependencyChecker(TemplateParameterList *Params, bool IgnoreNonTypeDependent)
+ : IgnoreNonTypeDependent(IgnoreNonTypeDependent), Match(false) {
NamedDecl *ND = Params->getParam(0);
if (TemplateTypeParmDecl *PD = dyn_cast<TemplateTypeParmDecl>(ND)) {
Depth = PD->getDepth();
@@ -1556,12 +1689,31 @@ struct DependencyChecker : RecursiveASTVisitor<DependencyChecker> {
return false;
}
+ bool TraverseStmt(Stmt *S, DataRecursionQueue *Q = nullptr) {
+ // Prune out non-type-dependent expressions if requested. This can
+ // sometimes result in us failing to find a template parameter reference
+ // (if a value-dependent expression creates a dependent type), but this
+ // mode is best-effort only.
+ if (auto *E = dyn_cast_or_null<Expr>(S))
+ if (IgnoreNonTypeDependent && !E->isTypeDependent())
+ return true;
+ return super::TraverseStmt(S, Q);
+ }
+
+ bool TraverseTypeLoc(TypeLoc TL) {
+ if (IgnoreNonTypeDependent && !TL.isNull() &&
+ !TL.getType()->isDependentType())
+ return true;
+ return super::TraverseTypeLoc(TL);
+ }
+
bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
return !Matches(TL.getTypePtr()->getDepth(), TL.getNameLoc());
}
bool VisitTemplateTypeParmType(const TemplateTypeParmType *T) {
- return !Matches(T->getDepth());
+ // For a best-effort search, keep looking until we find a location.
+ return IgnoreNonTypeDependent || !Matches(T->getDepth());
}
bool TraverseTemplateName(TemplateName N) {
@@ -1599,7 +1751,7 @@ struct DependencyChecker : RecursiveASTVisitor<DependencyChecker> {
/// list.
static bool
DependsOnTemplateParameters(QualType T, TemplateParameterList *Params) {
- DependencyChecker Checker(Params);
+ DependencyChecker Checker(Params, /*IgnoreNonTypeDependent*/false);
Checker.TraverseType(T);
return Checker.Match;
}
@@ -1616,10 +1768,10 @@ static SourceRange getRangeOfTypeInNestedNameSpecifier(ASTContext &Context,
return NNSLoc.getTypeLoc().getSourceRange();
} else
break;
-
+
NNSLoc = NNSLoc.getPrefix();
}
-
+
return SourceRange();
}
@@ -1662,34 +1814,34 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
bool &IsExplicitSpecialization, bool &Invalid) {
IsExplicitSpecialization = false;
Invalid = false;
-
+
// The sequence of nested types to which we will match up the template
// parameter lists. We first build this list by starting with the type named
// by the nested-name-specifier and walking out until we run out of types.
SmallVector<QualType, 4> NestedTypes;
QualType T;
if (SS.getScopeRep()) {
- if (CXXRecordDecl *Record
+ if (CXXRecordDecl *Record
= dyn_cast_or_null<CXXRecordDecl>(computeDeclContext(SS, true)))
T = Context.getTypeDeclType(Record);
else
T = QualType(SS.getScopeRep()->getAsType(), 0);
}
-
+
// If we found an explicit specialization that prevents us from needing
// 'template<>' headers, this will be set to the location of that
// explicit specialization.
SourceLocation ExplicitSpecLoc;
-
+
while (!T.isNull()) {
NestedTypes.push_back(T);
-
+
// Retrieve the parent of a record type.
if (CXXRecordDecl *Record = T->getAsCXXRecordDecl()) {
// If this type is an explicit specialization, we're done.
if (ClassTemplateSpecializationDecl *Spec
= dyn_cast<ClassTemplateSpecializationDecl>(Record)) {
- if (!isa<ClassTemplatePartialSpecializationDecl>(Spec) &&
+ if (!isa<ClassTemplatePartialSpecializationDecl>(Spec) &&
Spec->getSpecializationKind() == TSK_ExplicitSpecialization) {
ExplicitSpecLoc = Spec->getLocation();
break;
@@ -1699,14 +1851,14 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
ExplicitSpecLoc = Record->getLocation();
break;
}
-
+
if (TypeDecl *Parent = dyn_cast<TypeDecl>(Record->getParent()))
T = Context.getTypeDeclType(Parent);
else
T = QualType();
continue;
- }
-
+ }
+
if (const TemplateSpecializationType *TST
= T->getAs<TemplateSpecializationType>()) {
if (TemplateDecl *Template = TST->getTemplateName().getAsTemplateDecl()) {
@@ -1714,10 +1866,10 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
T = Context.getTypeDeclType(Parent);
else
T = QualType();
- continue;
+ continue;
}
}
-
+
// Look one step prior in a dependent template specialization type.
if (const DependentTemplateSpecializationType *DependentTST
= T->getAs<DependentTemplateSpecializationType>()) {
@@ -1727,7 +1879,7 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
T = QualType();
continue;
}
-
+
// Look one step prior in a dependent name type.
if (const DependentNameType *DependentName = T->getAs<DependentNameType>()){
if (NestedNameSpecifier *NNS = DependentName->getQualifier())
@@ -1736,18 +1888,18 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
T = QualType();
continue;
}
-
+
// Retrieve the parent of an enumeration type.
if (const EnumType *EnumT = T->getAs<EnumType>()) {
// FIXME: Forward-declared enums require a TSK_ExplicitSpecialization
// check here.
EnumDecl *Enum = EnumT->getDecl();
-
+
// Get to the parent type.
if (TypeDecl *Parent = dyn_cast<TypeDecl>(Enum->getParent()))
T = Context.getTypeDeclType(Parent);
else
- T = QualType();
+ T = QualType();
continue;
}
@@ -1799,21 +1951,21 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
for (unsigned TypeIdx = 0, NumTypes = NestedTypes.size(); TypeIdx != NumTypes;
++TypeIdx) {
T = NestedTypes[TypeIdx];
-
+
// Whether we expect a 'template<>' header.
bool NeedEmptyTemplateHeader = false;
// Whether we expect a template header with parameters.
bool NeedNonemptyTemplateHeader = false;
-
+
// For a dependent type, the set of template parameters that we
// expect to see.
TemplateParameterList *ExpectedTemplateParams = nullptr;
// C++0x [temp.expl.spec]p15:
- // A member or a member template may be nested within many enclosing
- // class templates. In an explicit specialization for such a member, the
- // member declaration shall be preceded by a template<> for each
+ // A member or a member template may be nested within many enclosing
+ // class templates. In an explicit specialization for such a member, the
+ // member declaration shall be preceded by a template<> for each
// enclosing class template that is explicitly specialized.
if (CXXRecordDecl *Record = T->getAsCXXRecordDecl()) {
if (ClassTemplatePartialSpecializationDecl *Partial
@@ -1830,38 +1982,38 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
= dyn_cast<ClassTemplateSpecializationDecl>(Record)) {
// C++0x [temp.expl.spec]p4:
// Members of an explicitly specialized class template are defined
- // in the same manner as members of normal classes, and not using
- // the template<> syntax.
+ // in the same manner as members of normal classes, and not using
+ // the template<> syntax.
if (Spec->getSpecializationKind() != TSK_ExplicitSpecialization)
NeedEmptyTemplateHeader = true;
else
continue;
} else if (Record->getTemplateSpecializationKind()) {
- if (Record->getTemplateSpecializationKind()
+ if (Record->getTemplateSpecializationKind()
!= TSK_ExplicitSpecialization &&
TypeIdx == NumTypes - 1)
IsExplicitSpecialization = true;
-
+
continue;
}
} else if (const TemplateSpecializationType *TST
= T->getAs<TemplateSpecializationType>()) {
if (TemplateDecl *Template = TST->getTemplateName().getAsTemplateDecl()) {
ExpectedTemplateParams = Template->getTemplateParameters();
- NeedNonemptyTemplateHeader = true;
+ NeedNonemptyTemplateHeader = true;
}
} else if (T->getAs<DependentTemplateSpecializationType>()) {
// FIXME: We actually could/should check the template arguments here
// against the corresponding template parameter list.
NeedNonemptyTemplateHeader = false;
- }
-
+ }
+
// C++ [temp.expl.spec]p16:
- // In an explicit specialization declaration for a member of a class
- // template or a member template that ap- pears in namespace scope, the
- // member template and some of its enclosing class templates may remain
- // unspecialized, except that the declaration shall not explicitly
- // specialize a class member template if its en- closing class templates
+ // In an explicit specialization declaration for a member of a class
+ // template or a member template that ap- pears in namespace scope, the
+ // member template and some of its enclosing class templates may remain
+ // unspecialized, except that the declaration shall not explicitly
+ // specialize a class member template if its en- closing class templates
// are not explicitly specialized as well.
if (ParamIdx < ParamLists.size()) {
if (ParamLists[ParamIdx]->size() == 0) {
@@ -1871,7 +2023,7 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
} else
SawNonEmptyTemplateParameterList = true;
}
-
+
if (NeedEmptyTemplateHeader) {
// If we're on the last of the types, and we need a 'template<>' header
// here, then it's an explicit specialization.
@@ -1881,7 +2033,7 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
if (ParamIdx < ParamLists.size()) {
if (ParamLists[ParamIdx]->size() > 0) {
// The header has template parameters when it shouldn't. Complain.
- Diag(ParamLists[ParamIdx]->getTemplateLoc(),
+ Diag(ParamLists[ParamIdx]->getTemplateLoc(),
diag::err_template_param_list_matches_nontemplate)
<< T
<< SourceRange(ParamLists[ParamIdx]->getLAngleLoc(),
@@ -1913,7 +2065,7 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
if (ParamIdx < ParamLists.size() &&
DependsOnTemplateParameters(T, ParamLists[ParamIdx]))
ExpectedTemplateParams = nullptr;
- else
+ else
continue;
}
@@ -1929,11 +2081,11 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
CheckTemplateParameterList(ParamLists[ParamIdx], nullptr,
TPC_ClassTemplateMember))
Invalid = true;
-
+
++ParamIdx;
continue;
}
-
+
Diag(DeclLoc, diag::err_template_spec_needs_template_parameters)
<< T
<< getRangeOfTypeInNestedNameSpecifier(Context, T, SS);
@@ -1956,7 +2108,7 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
// Fabricate an empty template parameter list for the invented header.
return TemplateParameterList::Create(Context, SourceLocation(),
SourceLocation(), None,
- SourceLocation());
+ SourceLocation(), nullptr);
}
return nullptr;
@@ -1983,10 +2135,10 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
// not required, and there were any 'template<>' headers, note where the
// specialization occurred.
if (ExplicitSpecLoc.isValid() && HasAnyExplicitSpecHeader)
- Diag(ExplicitSpecLoc,
+ Diag(ExplicitSpecLoc,
diag::note_explicit_template_spec_does_not_need_header)
<< NestedTypes.back();
-
+
// We have a template parameter list with no corresponding scope, which
// means that the resulting template declaration can't be instantiated
// properly (we'll end up with dependent nodes when we shouldn't).
@@ -1995,11 +2147,11 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
}
// C++ [temp.expl.spec]p16:
- // In an explicit specialization declaration for a member of a class
- // template or a member template that ap- pears in namespace scope, the
- // member template and some of its enclosing class templates may remain
- // unspecialized, except that the declaration shall not explicitly
- // specialize a class member template if its en- closing class templates
+ // In an explicit specialization declaration for a member of a class
+ // template or a member template that ap- pears in namespace scope, the
+ // member template and some of its enclosing class templates may remain
+ // unspecialized, except that the declaration shall not explicitly
+ // specialize a class member template if its en- closing class templates
// are not explicitly specialized as well.
if (ParamLists.back()->size() == 0 &&
CheckExplicitSpecialization(ParamLists[ParamIdx]->getSourceRange(),
@@ -2024,14 +2176,14 @@ void Sema::NoteAllFoundTemplates(TemplateName Name) {
<< Template->getDeclName();
return;
}
-
+
if (OverloadedTemplateStorage *OST = Name.getAsOverloadedTemplate()) {
- for (OverloadedTemplateStorage::iterator I = OST->begin(),
+ for (OverloadedTemplateStorage::iterator I = OST->begin(),
IEnd = OST->end();
I != IEnd; ++I)
Diag((*I)->getLocation(), diag::note_template_declared_here)
<< 0 << (*I)->getDeclName();
-
+
return;
}
}
@@ -2074,11 +2226,8 @@ checkBuiltinTemplateIdType(Sema &SemaRef, BuiltinTemplateDecl *BTD,
for (llvm::APSInt I(NumArgs.getBitWidth(), NumArgs.isUnsigned());
I < NumArgs; ++I) {
TemplateArgument TA(Context, I, ArgTy);
- Expr *E = SemaRef.BuildExpressionFromIntegralTemplateArgument(
- TA, TemplateArgs[2].getLocation())
- .getAs<Expr>();
- SyntheticTemplateArgs.addArgument(
- TemplateArgumentLoc(TemplateArgument(E), E));
+ SyntheticTemplateArgs.addArgument(SemaRef.getTrivialTemplateArgumentLoc(
+ TA, ArgTy, TemplateArgs[2].getLocation()));
}
// The first template argument will be reused as the template decl that
// our synthetic template arguments will be applied to.
@@ -2310,7 +2459,7 @@ Sema::ActOnTemplateIdType(CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo());
return CreateParsedType(T, TLB.getTypeSourceInfo(Context, T));
}
-
+
QualType Result = CheckTemplateIdType(Template, TemplateLoc, TemplateArgs);
if (Result.isNull())
@@ -2337,7 +2486,7 @@ Sema::ActOnTemplateIdType(CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
ElabTL.setElaboratedKeywordLoc(SourceLocation());
ElabTL.setQualifierLoc(SS.getWithLocInContext(Context));
}
-
+
return CreateParsedType(Result, TLB.getTypeSourceInfo(Context, Result));
}
@@ -2352,11 +2501,11 @@ TypeResult Sema::ActOnTagTemplateIdType(TagUseKind TUK,
ASTTemplateArgsPtr TemplateArgsIn,
SourceLocation RAngleLoc) {
TemplateName Template = TemplateD.get();
-
+
// Translate the parser's template argument list in our AST format.
TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);
translateTemplateArguments(TemplateArgsIn, TemplateArgs);
-
+
// Determine the tag kind
TagTypeKind TagKind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec);
ElaboratedTypeKeyword Keyword
@@ -2364,11 +2513,11 @@ TypeResult Sema::ActOnTagTemplateIdType(TagUseKind TUK,
if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) {
QualType T = Context.getDependentTemplateSpecializationType(Keyword,
- DTN->getQualifier(),
- DTN->getIdentifier(),
+ DTN->getQualifier(),
+ DTN->getIdentifier(),
TemplateArgs);
-
- // Build type-source information.
+
+ // Build type-source information.
TypeLocBuilder TLB;
DependentTemplateSpecializationTypeLoc SpecTL
= TLB.push<DependentTemplateSpecializationTypeLoc>(T);
@@ -2389,21 +2538,22 @@ TypeResult Sema::ActOnTagTemplateIdType(TagUseKind TUK,
// If the identifier resolves to a typedef-name or the simple-template-id
// resolves to an alias template specialization, the
// elaborated-type-specifier is ill-formed.
- Diag(TemplateLoc, diag::err_tag_reference_non_tag) << 4;
+ Diag(TemplateLoc, diag::err_tag_reference_non_tag)
+ << TAT << NTK_TypeAliasTemplate << TagKind;
Diag(TAT->getLocation(), diag::note_declared_at);
}
-
+
QualType Result = CheckTemplateIdType(Template, TemplateLoc, TemplateArgs);
if (Result.isNull())
return TypeResult(true);
-
+
// Check the tag kind
if (const RecordType *RT = Result->getAs<RecordType>()) {
RecordDecl *D = RT->getDecl();
-
+
IdentifierInfo *Id = D->getIdentifier();
assert(Id && "templated class must have an identifier");
-
+
if (!isAcceptableTagRedeclaration(D, TagKind, TUK == TUK_Definition,
TagLoc, Id)) {
Diag(TagLoc, diag::err_use_with_wrong_tag)
@@ -2433,10 +2583,6 @@ TypeResult Sema::ActOnTagTemplateIdType(TagUseKind TUK,
return CreateParsedType(Result, TLB.getTypeSourceInfo(Context, Result));
}
-static bool CheckTemplatePartialSpecializationArgs(
- Sema &S, SourceLocation NameLoc, TemplateParameterList *TemplateParams,
- unsigned ExplicitArgs, SmallVectorImpl<TemplateArgument> &TemplateArgs);
-
static bool CheckTemplateSpecializationScope(Sema &S, NamedDecl *Specialized,
NamedDecl *PrevDecl,
SourceLocation Loc,
@@ -2518,6 +2664,89 @@ makeTemplateArgumentListInfo(Sema &S, TemplateIdAnnotation &TemplateId) {
return TemplateArgs;
}
+template<typename PartialSpecDecl>
+static void checkMoreSpecializedThanPrimary(Sema &S, PartialSpecDecl *Partial) {
+ if (Partial->getDeclContext()->isDependentContext())
+ return;
+
+ // FIXME: Get the TDK from deduction in order to provide better diagnostics
+ // for non-substitution-failure issues?
+ TemplateDeductionInfo Info(Partial->getLocation());
+ if (S.isMoreSpecializedThanPrimary(Partial, Info))
+ return;
+
+ auto *Template = Partial->getSpecializedTemplate();
+ S.Diag(Partial->getLocation(),
+ diag::ext_partial_spec_not_more_specialized_than_primary)
+ << isa<VarTemplateDecl>(Template);
+
+ if (Info.hasSFINAEDiagnostic()) {
+ PartialDiagnosticAt Diag = {SourceLocation(),
+ PartialDiagnostic::NullDiagnostic()};
+ Info.takeSFINAEDiagnostic(Diag);
+ SmallString<128> SFINAEArgString;
+ Diag.second.EmitToString(S.getDiagnostics(), SFINAEArgString);
+ S.Diag(Diag.first,
+ diag::note_partial_spec_not_more_specialized_than_primary)
+ << SFINAEArgString;
+ }
+
+ S.Diag(Template->getLocation(), diag::note_template_decl_here);
+}
+
+template<typename PartialSpecDecl>
+static void checkTemplatePartialSpecialization(Sema &S,
+ PartialSpecDecl *Partial) {
+ // C++1z [temp.class.spec]p8: (DR1495)
+ // - The specialization shall be more specialized than the primary
+ // template (14.5.5.2).
+ checkMoreSpecializedThanPrimary(S, Partial);
+
+ // C++ [temp.class.spec]p8: (DR1315)
+ // - Each template-parameter shall appear at least once in the
+ // template-id outside a non-deduced context.
+ // C++1z [temp.class.spec.match]p3 (P0127R2)
+ // If the template arguments of a partial specialization cannot be
+ // deduced because of the structure of its template-parameter-list
+ // and the template-id, the program is ill-formed.
+ auto *TemplateParams = Partial->getTemplateParameters();
+ llvm::SmallBitVector DeducibleParams(TemplateParams->size());
+ S.MarkUsedTemplateParameters(Partial->getTemplateArgs(), true,
+ TemplateParams->getDepth(), DeducibleParams);
+
+ if (!DeducibleParams.all()) {
+ unsigned NumNonDeducible = DeducibleParams.size() - DeducibleParams.count();
+ S.Diag(Partial->getLocation(), diag::ext_partial_specs_not_deducible)
+ << isa<VarTemplatePartialSpecializationDecl>(Partial)
+ << (NumNonDeducible > 1)
+ << SourceRange(Partial->getLocation(),
+ Partial->getTemplateArgsAsWritten()->RAngleLoc);
+ for (unsigned I = 0, N = DeducibleParams.size(); I != N; ++I) {
+ if (!DeducibleParams[I]) {
+ NamedDecl *Param = cast<NamedDecl>(TemplateParams->getParam(I));
+ if (Param->getDeclName())
+ S.Diag(Param->getLocation(),
+ diag::note_partial_spec_unused_parameter)
+ << Param->getDeclName();
+ else
+ S.Diag(Param->getLocation(),
+ diag::note_partial_spec_unused_parameter)
+ << "(anonymous)";
+ }
+ }
+ }
+}
+
+void Sema::CheckTemplatePartialSpecialization(
+ ClassTemplatePartialSpecializationDecl *Partial) {
+ checkTemplatePartialSpecialization(*this, Partial);
+}
+
+void Sema::CheckTemplatePartialSpecialization(
+ VarTemplatePartialSpecializationDecl *Partial) {
+ checkTemplatePartialSpecialization(*this, Partial);
+}
+
DeclResult Sema::ActOnVarTemplateSpecialization(
Scope *S, Declarator &D, TypeSourceInfo *DI, SourceLocation TemplateKWLoc,
TemplateParameterList *TemplateParams, StorageClass SC,
@@ -2567,11 +2796,12 @@ DeclResult Sema::ActOnVarTemplateSpecialization(
// Find the variable template (partial) specialization declaration that
// corresponds to these arguments.
if (IsPartialSpecialization) {
- if (CheckTemplatePartialSpecializationArgs(
- *this, TemplateNameLoc, VarTemplate->getTemplateParameters(),
- TemplateArgs.size(), Converted))
+ if (CheckTemplatePartialSpecializationArgs(TemplateNameLoc, VarTemplate,
+ TemplateArgs.size(), Converted))
return true;
+ // FIXME: Move these checks to CheckTemplatePartialSpecializationArgs so we
+ // also do them during instantiation.
bool InstantiationDependent;
if (!Name.isDependent() &&
!TemplateSpecializationType::anyDependentTemplateArguments(
@@ -2643,32 +2873,7 @@ DeclResult Sema::ActOnVarTemplateSpecialization(
if (PrevPartial && PrevPartial->getInstantiatedFromMember())
PrevPartial->setMemberSpecialization();
- // Check that all of the template parameters of the variable template
- // partial specialization are deducible from the template
- // arguments. If not, this variable template partial specialization
- // will never be used.
- llvm::SmallBitVector DeducibleParams(TemplateParams->size());
- MarkUsedTemplateParameters(Partial->getTemplateArgs(), true,
- TemplateParams->getDepth(), DeducibleParams);
-
- if (!DeducibleParams.all()) {
- unsigned NumNonDeducible =
- DeducibleParams.size() - DeducibleParams.count();
- Diag(TemplateNameLoc, diag::warn_partial_specs_not_deducible)
- << /*variable template*/ 1 << (NumNonDeducible > 1)
- << SourceRange(TemplateNameLoc, RAngleLoc);
- for (unsigned I = 0, N = DeducibleParams.size(); I != N; ++I) {
- if (!DeducibleParams[I]) {
- NamedDecl *Param = cast<NamedDecl>(TemplateParams->getParam(I));
- if (Param->getDeclName())
- Diag(Param->getLocation(), diag::note_partial_spec_unused_parameter)
- << Param->getDeclName();
- else
- Diag(Param->getLocation(), diag::note_partial_spec_unused_parameter)
- << "(anonymous)";
- }
- }
- }
+ CheckTemplatePartialSpecialization(Partial);
} else {
// Create a new class template specialization declaration node for
// this explicit specialization or friend declaration.
@@ -2890,12 +3095,10 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc,
<< Decl;
// Print the matching partial specializations.
- for (SmallVector<MatchResult, 4>::iterator P = Matched.begin(),
- PEnd = Matched.end();
- P != PEnd; ++P)
- Diag(P->Partial->getLocation(), diag::note_partial_spec_match)
- << getTemplateArgumentBindingsText(
- P->Partial->getTemplateParameters(), *P->Args);
+ for (MatchResult P : Matched)
+ Diag(P.Partial->getLocation(), diag::note_partial_spec_match)
+ << getTemplateArgumentBindingsText(P.Partial->getTemplateParameters(),
+ *P.Args);
return true;
}
@@ -3206,7 +3409,7 @@ bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
// Add the converted template type argument.
ArgType = Context.getCanonicalType(ArgType);
-
+
// Objective-C ARC:
// If an explicitly-specified template argument type is a lifetime type
// with no lifetime qualifier, the __strong lifetime qualifier is inferred.
@@ -3217,7 +3420,7 @@ bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
Qs.setObjCLifetime(Qualifiers::OCL_Strong);
ArgType = Context.getQualifiedType(ArgType, Qs);
}
-
+
Converted.push_back(TemplateArgument(ArgType));
return false;
}
@@ -3347,7 +3550,7 @@ SubstDefaultTemplateArgument(Sema &SemaRef,
/// \param Converted the list of template arguments provided for template
/// parameters that precede \p Param in the template parameter list.
///
-/// \param QualifierLoc Will be set to the nested-name-specifier (with
+/// \param QualifierLoc Will be set to the nested-name-specifier (with
/// source-location information) that precedes the template name.
///
/// \returns the substituted template argument, or NULL if an error occurred.
@@ -3698,7 +3901,7 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
return false;
}
-/// \brief Diagnose an arity mismatch in the
+/// \brief Diagnose an arity mismatch in the
static bool diagnoseArityMismatch(Sema &S, TemplateDecl *Template,
SourceLocation TemplateLoc,
TemplateArgumentListInfo &TemplateArgs) {
@@ -3708,7 +3911,7 @@ static bool diagnoseArityMismatch(Sema &S, TemplateDecl *Template,
SourceRange Range;
if (NumArgs > NumParams)
- Range = SourceRange(TemplateArgs[NumParams].getLocation(),
+ Range = SourceRange(TemplateArgs[NumParams].getLocation(),
TemplateArgs.getRAngleLoc());
S.Diag(TemplateLoc, diag::err_template_arg_list_different_arity)
<< (NumArgs > NumParams)
@@ -4332,20 +4535,20 @@ isNullPointerValueTemplateArgument(Sema &S, NonTypeTemplateParmDecl *Param,
if (!S.getLangOpts().CPlusPlus11)
return NPV_NotNullPointer;
-
+
// Determine whether we have a constant expression.
ExprResult ArgRV = S.DefaultFunctionArrayConversion(Arg);
if (ArgRV.isInvalid())
return NPV_Error;
Arg = ArgRV.get();
-
+
Expr::EvalResult EvalResult;
SmallVector<PartialDiagnosticAt, 8> Notes;
EvalResult.Diag = &Notes;
if (!Arg->EvaluateAsRValue(EvalResult, S.Context) ||
EvalResult.HasSideEffects) {
SourceLocation DiagLoc = Arg->getExprLoc();
-
+
// If our only note is the usual "invalid subexpression" note, just point
// the caret at its location rather than producing an essentially
// redundant note.
@@ -4354,21 +4557,21 @@ isNullPointerValueTemplateArgument(Sema &S, NonTypeTemplateParmDecl *Param,
DiagLoc = Notes[0].first;
Notes.clear();
}
-
+
S.Diag(DiagLoc, diag::err_template_arg_not_address_constant)
<< Arg->getType() << Arg->getSourceRange();
for (unsigned I = 0, N = Notes.size(); I != N; ++I)
S.Diag(Notes[I].first, Notes[I].second);
-
+
S.Diag(Param->getLocation(), diag::note_template_param_here);
return NPV_Error;
}
-
+
// C++11 [temp.arg.nontype]p1:
// - an address constant expression of type std::nullptr_t
if (Arg->getType()->isNullPtrType())
return NPV_NullPointer;
-
+
// - a constant expression that evaluates to a null pointer value (4.10); or
// - a constant expression that evaluates to a null member pointer value
// (4.11); or
@@ -4381,7 +4584,7 @@ isNullPointerValueTemplateArgument(Sema &S, NonTypeTemplateParmDecl *Param,
S.IsQualificationConversion(Arg->getType(), ParamType, false,
ObjCLifetimeConversion))
return NPV_NullPointer;
-
+
// The types didn't match, but we know we got a null pointer; complain,
// then recover as if the types were correct.
S.Diag(Arg->getExprLoc(), diag::err_template_arg_wrongtype_null_constant)
@@ -4401,7 +4604,7 @@ isNullPointerValueTemplateArgument(Sema &S, NonTypeTemplateParmDecl *Param,
S.Diag(Param->getLocation(), diag::note_template_param_here);
return NPV_NullPointer;
}
-
+
// FIXME: If we ever want to support general, address-constant expressions
// as non-type template arguments, we should return the ExprResult here to
// be interpreted by the caller.
@@ -4902,12 +5105,33 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
CheckTemplateArgumentKind CTAK) {
SourceLocation StartLoc = Arg->getLocStart();
- // If either the parameter has a dependent type or the argument is
- // type-dependent, there's nothing we can check now.
- if (ParamType->isDependentType() || Arg->isTypeDependent()) {
- // FIXME: Produce a cloned, canonical expression?
- Converted = TemplateArgument(Arg);
- return Arg;
+ // If the parameter type somehow involves auto, deduce the type now.
+ if (getLangOpts().CPlusPlus1z && ParamType->isUndeducedType()) {
+ // When checking a deduced template argument, deduce from its type even if
+ // the type is dependent, in order to check the types of non-type template
+ // arguments line up properly in partial ordering.
+ Optional<unsigned> Depth;
+ if (CTAK != CTAK_Specified)
+ Depth = Param->getDepth() + 1;
+ if (DeduceAutoType(
+ Context.getTrivialTypeSourceInfo(ParamType, Param->getLocation()),
+ Arg, ParamType, Depth) == DAR_Failed) {
+ Diag(Arg->getExprLoc(),
+ diag::err_non_type_template_parm_type_deduction_failure)
+ << Param->getDeclName() << Param->getType() << Arg->getType()
+ << Arg->getSourceRange();
+ Diag(Param->getLocation(), diag::note_template_param_here);
+ return ExprError();
+ }
+ // CheckNonTypeTemplateParameterType will produce a diagnostic if there's
+ // an error. The error message normally references the parameter
+ // declaration, but here we'll pass the argument location because that's
+ // where the parameter type is deduced.
+ ParamType = CheckNonTypeTemplateParameterType(ParamType, Arg->getExprLoc());
+ if (ParamType.isNull()) {
+ Diag(Param->getLocation(), diag::note_template_param_here);
+ return ExprError();
+ }
}
// We should have already dropped all cv-qualifiers by now.
@@ -4915,30 +5139,36 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
"non-type template parameter type cannot be qualified");
if (CTAK == CTAK_Deduced &&
- !Context.hasSameUnqualifiedType(ParamType, Arg->getType())) {
- // C++ [temp.deduct.type]p17:
- // If, in the declaration of a function template with a non-type
- // template-parameter, the non-type template-parameter is used
- // in an expression in the function parameter-list and, if the
- // corresponding template-argument is deduced, the
- // template-argument type shall match the type of the
- // template-parameter exactly, except that a template-argument
- // deduced from an array bound may be of any integral type.
+ !Context.hasSameType(ParamType.getNonLValueExprType(Context),
+ Arg->getType())) {
+ // C++ [temp.deduct.type]p17: (DR1770)
+ // If P has a form that contains <i>, and if the type of i differs from
+ // the type of the corresponding template parameter of the template named
+ // by the enclosing simple-template-id, deduction fails.
+ //
+ // Note that CTAK will be CTAK_DeducedFromArrayBound if the form was [i]
+ // rather than <i>.
+ //
+ // FIXME: We interpret the 'i' here as referring to the expression
+ // denoting the non-type template parameter rather than the parameter
+ // itself, and so strip off references before comparing types. It's
+ // not clear how this is supposed to work for references.
Diag(StartLoc, diag::err_deduced_non_type_template_arg_type_mismatch)
- << Arg->getType().getUnqualifiedType()
+ << Arg->getType()
<< ParamType.getUnqualifiedType();
Diag(Param->getLocation(), diag::note_template_param_here);
return ExprError();
}
- if (getLangOpts().CPlusPlus1z) {
- // FIXME: We can do some limited checking for a value-dependent but not
- // type-dependent argument.
- if (Arg->isValueDependent()) {
- Converted = TemplateArgument(Arg);
- return Arg;
- }
+ // If either the parameter has a dependent type or the argument is
+ // type-dependent, there's nothing we can check now.
+ if (ParamType->isDependentType() || Arg->isTypeDependent()) {
+ // FIXME: Produce a cloned, canonical expression?
+ Converted = TemplateArgument(Arg);
+ return Arg;
+ }
+ if (getLangOpts().CPlusPlus1z) {
// C++1z [temp.arg.nontype]p1:
// A template-argument for a non-type template parameter shall be
// a converted constant expression of the type of the template-parameter.
@@ -4948,6 +5178,13 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
if (ArgResult.isInvalid())
return ExprError();
+ // For a value-dependent argument, CheckConvertedConstantExpression is
+ // permitted (and expected) to be unable to determine a value.
+ if (ArgResult.get()->isValueDependent()) {
+ Converted = TemplateArgument(ArgResult.get());
+ return ArgResult;
+ }
+
QualType CanonParamType = Context.getCanonicalType(ParamType);
// Convert the APValue to a TemplateArgument.
@@ -5052,14 +5289,6 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
// conversions (4.7) are applied.
if (getLangOpts().CPlusPlus11) {
- // We can't check arbitrary value-dependent arguments.
- // FIXME: If there's no viable conversion to the template parameter type,
- // we should be able to diagnose that prior to instantiation.
- if (Arg->isValueDependent()) {
- Converted = TemplateArgument(Arg);
- return Arg;
- }
-
// C++ [temp.arg.nontype]p1:
// A template-argument for a non-type, non-template template-parameter
// shall be one of:
@@ -5074,6 +5303,12 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
if (ArgResult.isInvalid())
return ExprError();
+ // We can't check arbitrary value-dependent arguments.
+ if (ArgResult.get()->isValueDependent()) {
+ Converted = TemplateArgument(ArgResult.get());
+ return ArgResult;
+ }
+
// Widen the argument value to sizeof(parameter type). This is almost
// always a no-op, except when the parameter type is bool. In
// that case, this may extend the argument from 1 bit to 8 bits.
@@ -5112,7 +5347,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
} else if (!Arg->isValueDependent()) {
class TmplArgICEDiagnoser : public VerifyICEDiagnoser {
QualType T;
-
+
public:
TmplArgICEDiagnoser(QualType T) : T(T) { }
@@ -5174,14 +5409,14 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
Value.setIsSigned(IntegerType->isSignedIntegerOrEnumerationType());
} else {
llvm::APSInt OldValue = Value;
-
+
// Coerce the template argument's value to the value it will have
// based on the template parameter's type.
unsigned AllowedBits = Context.getTypeSize(IntegerType);
if (Value.getBitWidth() != AllowedBits)
Value = Value.extOrTrunc(AllowedBits);
Value.setIsSigned(IntegerType->isSignedIntegerOrEnumerationType());
-
+
// Complain if an unsigned parameter received a negative value.
if (IntegerType->isUnsignedIntegerOrEnumerationType()
&& (OldValue.isSigned() && OldValue.isNegative())) {
@@ -5190,7 +5425,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
<< Arg->getSourceRange();
Diag(Param->getLocation(), diag::note_template_param_here);
}
-
+
// Complain if we overflowed the template parameter's type.
unsigned RequiredBits;
if (IntegerType->isUnsignedIntegerOrEnumerationType())
@@ -5209,7 +5444,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
}
Converted = TemplateArgument(Context, Value,
- ParamType->isEnumeralType()
+ ParamType->isEnumeralType()
? Context.getCanonicalType(ParamType)
: IntegerType);
return Arg;
@@ -5321,17 +5556,17 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
Converted = TemplateArgument(Arg);
return Arg;
}
-
+
switch (isNullPointerValueTemplateArgument(*this, Param, ParamType, Arg)) {
case NPV_NotNullPointer:
Diag(Arg->getExprLoc(), diag::err_template_arg_not_convertible)
<< Arg->getType() << ParamType;
Diag(Param->getLocation(), diag::note_template_param_here);
return ExprError();
-
+
case NPV_Error:
return ExprError();
-
+
case NPV_NullPointer:
Diag(Arg->getExprLoc(), diag::warn_cxx98_compat_template_arg_null);
Converted = TemplateArgument(Context.getCanonicalType(ParamType),
@@ -5350,6 +5585,10 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
return Arg;
}
+static void DiagnoseTemplateParameterListArityMismatch(
+ Sema &S, TemplateParameterList *New, TemplateParameterList *Old,
+ Sema::TemplateParameterListEqualKind Kind, SourceLocation TemplateArgLoc);
+
/// \brief Check a template argument against its corresponding
/// template template parameter.
///
@@ -5366,6 +5605,9 @@ bool Sema::CheckTemplateArgument(TemplateTemplateParmDecl *Param,
return false;
}
+ if (Template->isInvalidDecl())
+ return true;
+
// C++0x [temp.arg.template]p1:
// A template-argument for a template template-parameter shall be
// the name of a class template or an alias template, expressed as an
@@ -5393,6 +5635,25 @@ bool Sema::CheckTemplateArgument(TemplateTemplateParmDecl *Param,
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.
+ if (getLangOpts().RelaxedTemplateTemplateArgs) {
+ // Quick check for the common case:
+ // If P contains a parameter pack, then A [...] matches P if each of A's
+ // template parameters matches the corresponding template parameter in
+ // the template-parameter-list of P.
+ if (TemplateParameterListsAreEqual(
+ Template->getTemplateParameters(), Params, false,
+ TPL_TemplateTemplateArgumentMatch, Arg.getLocation()))
+ return false;
+
+ if (isTemplateTemplateParameterAtLeastAsSpecializedAs(Params, Template,
+ Arg.getLocation()))
+ return false;
+ // FIXME: Produce better diagnostics for deduction failures.
+ }
+
return !TemplateParameterListsAreEqual(Template->getTemplateParameters(),
Params,
true,
@@ -5578,7 +5839,7 @@ Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg,
Context.getTrivialTypeSourceInfo(OrigT, Loc),
Loc, Loc);
}
-
+
return E;
}
@@ -5604,7 +5865,7 @@ static bool MatchTemplateParameterKind(Sema &S, NamedDecl *New, NamedDecl *Old,
return false;
}
- // Check that both are parameter packs are neither are parameter packs.
+ // Check that both are parameter packs or neither are parameter packs.
// However, if we are matching a template template argument to a
// template template parameter, the template template parameter can have
// a parameter pack where the template template argument does not.
@@ -5816,12 +6077,14 @@ Sema::CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams) {
// C++ [temp]p4:
// A template [...] shall not have C linkage.
DeclContext *Ctx = S->getEntity();
- if (Ctx && Ctx->isExternCContext())
- return Diag(TemplateParams->getTemplateLoc(), diag::err_template_linkage)
- << TemplateParams->getSourceRange();
-
- while (Ctx && isa<LinkageSpecDecl>(Ctx))
- Ctx = Ctx->getParent();
+ if (Ctx && Ctx->isExternCContext()) {
+ Diag(TemplateParams->getTemplateLoc(), diag::err_template_linkage)
+ << TemplateParams->getSourceRange();
+ if (const LinkageSpecDecl *LSD = Ctx->getExternCContext())
+ Diag(LSD->getExternLoc(), diag::note_extern_c_begins_here);
+ return true;
+ }
+ Ctx = Ctx->getRedeclContext();
// C++ [temp]p2:
// A template-declaration can appear only as a namespace scope or
@@ -5957,7 +6220,7 @@ static bool CheckTemplateSpecializationScope(Sema &S,
<< 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
@@ -6035,12 +6298,12 @@ static bool CheckTemplateSpecializationScope(Sema &S,
return false;
}
-static SourceRange findTemplateParameter(unsigned Depth, Expr *E) {
- if (!E->isInstantiationDependent())
+static SourceRange findTemplateParameterInType(unsigned Depth, Expr *E) {
+ if (!E->isTypeDependent())
return SourceLocation();
- DependencyChecker Checker(Depth);
+ DependencyChecker Checker(Depth, /*IgnoreNonTypeDependent*/true);
Checker.TraverseStmt(E);
- if (Checker.Match && Checker.MatchLoc.isInvalid())
+ if (Checker.MatchLoc.isInvalid())
return E->getSourceRange();
return Checker.MatchLoc;
}
@@ -6048,9 +6311,9 @@ static SourceRange findTemplateParameter(unsigned Depth, Expr *E) {
static SourceRange findTemplateParameter(unsigned Depth, TypeLoc TL) {
if (!TL.getType()->isDependentType())
return SourceLocation();
- DependencyChecker Checker(Depth);
+ DependencyChecker Checker(Depth, /*IgnoreNonTypeDependent*/true);
Checker.TraverseTypeLoc(TL);
- if (Checker.Match && Checker.MatchLoc.isInvalid())
+ if (Checker.MatchLoc.isInvalid())
return TL.getSourceRange();
return Checker.MatchLoc;
}
@@ -6102,8 +6365,16 @@ static bool CheckNonTypeTemplatePartialSpecializationArgs(
// shall not involve a template parameter of the partial
// specialization except when the argument expression is a
// simple identifier.
+ // -- The type of a template parameter corresponding to a
+ // specialized non-type argument shall not be dependent on a
+ // parameter of the specialization.
+ // DR1315 removes the first bullet, leaving an incoherent set of rules.
+ // We implement a compromise between the original rules and DR1315:
+ // -- A specialized non-type template argument shall not be
+ // type-dependent and the corresponding template parameter
+ // shall have a non-dependent type.
SourceRange ParamUseRange =
- findTemplateParameter(Param->getDepth(), ArgExpr);
+ findTemplateParameterInType(Param->getDepth(), ArgExpr);
if (ParamUseRange.isValid()) {
if (IsDefaultArgument) {
S.Diag(TemplateNameLoc,
@@ -6119,26 +6390,15 @@ static bool CheckNonTypeTemplatePartialSpecializationArgs(
return true;
}
- // -- The type of a template parameter corresponding to a
- // specialized non-type argument shall not be dependent on a
- // parameter of the specialization.
- //
- // FIXME: We need to delay this check until instantiation in some cases:
- //
- // template<template<typename> class X> struct A {
- // template<typename T, X<T> N> struct B;
- // template<typename T> struct B<T, 0>;
- // };
- // template<typename> using X = int;
- // A<X>::B<int, 0> b;
ParamUseRange = findTemplateParameter(
- Param->getDepth(), Param->getTypeSourceInfo()->getTypeLoc());
+ Param->getDepth(), Param->getTypeSourceInfo()->getTypeLoc());
if (ParamUseRange.isValid()) {
S.Diag(IsDefaultArgument ? TemplateNameLoc : ArgExpr->getLocStart(),
diag::err_dependent_typed_non_type_arg_in_partial_spec)
- << Param->getType() << ParamUseRange;
+ << Param->getType();
S.Diag(Param->getLocation(), diag::note_template_param_here)
- << (IsDefaultArgument ? ParamUseRange : SourceRange());
+ << (IsDefaultArgument ? ParamUseRange : SourceRange())
+ << ParamUseRange;
return true;
}
}
@@ -6150,27 +6410,32 @@ static bool CheckNonTypeTemplatePartialSpecializationArgs(
/// partial specialization according to C++ [temp.class.spec]p9.
///
/// \param TemplateNameLoc the location of the template name.
-/// \param TemplateParams the template parameters of the primary class
+/// \param PrimaryTemplate the template parameters of the primary class
/// template.
/// \param NumExplicit the number of explicitly-specified template arguments.
/// \param TemplateArgs the template arguments of the class template
/// partial specialization.
///
/// \returns \c true if there was an error, \c false otherwise.
-static bool CheckTemplatePartialSpecializationArgs(
- Sema &S, SourceLocation TemplateNameLoc,
- TemplateParameterList *TemplateParams, unsigned NumExplicit,
- SmallVectorImpl<TemplateArgument> &TemplateArgs) {
- const TemplateArgument *ArgList = TemplateArgs.data();
+bool Sema::CheckTemplatePartialSpecializationArgs(
+ SourceLocation TemplateNameLoc, TemplateDecl *PrimaryTemplate,
+ unsigned NumExplicit, ArrayRef<TemplateArgument> TemplateArgs) {
+ // We have to be conservative when checking a template in a dependent
+ // context.
+ if (PrimaryTemplate->getDeclContext()->isDependentContext())
+ return false;
+ TemplateParameterList *TemplateParams =
+ PrimaryTemplate->getTemplateParameters();
for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) {
NonTypeTemplateParmDecl *Param
= dyn_cast<NonTypeTemplateParmDecl>(TemplateParams->getParam(I));
if (!Param)
continue;
- if (CheckNonTypeTemplatePartialSpecializationArgs(
- S, TemplateNameLoc, Param, &ArgList[I], 1, I >= NumExplicit))
+ if (CheckNonTypeTemplatePartialSpecializationArgs(*this, TemplateNameLoc,
+ Param, &TemplateArgs[I],
+ 1, I >= NumExplicit))
return true;
}
@@ -6314,11 +6579,12 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
// Find the class template (partial) specialization declaration that
// corresponds to these arguments.
if (isPartialSpecialization) {
- if (CheckTemplatePartialSpecializationArgs(
- *this, TemplateNameLoc, ClassTemplate->getTemplateParameters(),
- TemplateArgs.size(), Converted))
+ if (CheckTemplatePartialSpecializationArgs(TemplateNameLoc, ClassTemplate,
+ TemplateArgs.size(), Converted))
return true;
+ // FIXME: Move this to CheckTemplatePartialSpecializationArgs so we
+ // also do it during instantiation.
bool InstantiationDependent;
if (!Name.isDependent() &&
!TemplateSpecializationType::anyDependentTemplateArguments(
@@ -6363,6 +6629,9 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
//
// -- The argument list of the specialization shall not be identical
// to the implicit argument list of the primary template.
+ //
+ // This rule has since been removed, because it's redundant given DR1495,
+ // but we keep it because it produces better diagnostics and recovery.
Diag(TemplateNameLoc, diag::err_partial_spec_args_match_primary_template)
<< /*class template*/0 << (TUK == TUK_Definition)
<< FixItHint::CreateRemoval(SourceRange(LAngleLoc, RAngleLoc));
@@ -6405,34 +6674,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
if (PrevPartial && PrevPartial->getInstantiatedFromMember())
PrevPartial->setMemberSpecialization();
- // Check that all of the template parameters of the class template
- // partial specialization are deducible from the template
- // arguments. If not, this class template partial specialization
- // will never be used.
- llvm::SmallBitVector DeducibleParams(TemplateParams->size());
- MarkUsedTemplateParameters(Partial->getTemplateArgs(), true,
- TemplateParams->getDepth(),
- DeducibleParams);
-
- if (!DeducibleParams.all()) {
- unsigned NumNonDeducible = DeducibleParams.size()-DeducibleParams.count();
- Diag(TemplateNameLoc, diag::warn_partial_specs_not_deducible)
- << /*class template*/0 << (NumNonDeducible > 1)
- << SourceRange(TemplateNameLoc, RAngleLoc);
- for (unsigned I = 0, N = DeducibleParams.size(); I != N; ++I) {
- if (!DeducibleParams[I]) {
- NamedDecl *Param = cast<NamedDecl>(TemplateParams->getParam(I));
- if (Param->getDeclName())
- Diag(Param->getLocation(),
- diag::note_partial_spec_unused_parameter)
- << Param->getDeclName();
- else
- Diag(Param->getLocation(),
- diag::note_partial_spec_unused_parameter)
- << "(anonymous)";
- }
- }
- }
+ CheckTemplatePartialSpecialization(Partial);
} else {
// Create a new class template specialization declaration node for
// this explicit specialization or friend declaration.
@@ -6509,8 +6751,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
TUK = TUK_Declaration;
} else if (Def) {
SourceRange Range(TemplateNameLoc, RAngleLoc);
- Diag(TemplateNameLoc, diag::err_redefinition)
- << Context.getTypeDeclType(Specialization) << Range;
+ Diag(TemplateNameLoc, diag::err_redefinition) << Specialization << Range;
Diag(Def->getLocation(), diag::note_previous_definition);
Specialization->setInvalidDecl();
return true;
@@ -6531,7 +6772,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
Diag(Specialization->getLocation(), diag::err_module_private_specialization)
<< (isPartialSpecialization? 1 : 0)
<< FixItHint::CreateRemoval(ModulePrivateLoc);
-
+
// Build the fully-sugared type for this class template
// specialization as the user wrote in the specialization
// itself. This means that we'll pretty-print the type retrieved
@@ -6748,13 +6989,7 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
// instantiation of a template appears after a declaration of
// an explicit specialization for that template, the explicit
// instantiation has no effect.
- //
- // In C++98/03 mode, we only give an extension warning here, because it
- // is not harmful to try to explicitly instantiate something that
- // has been explicitly specialized.
- Diag(NewLoc, getLangOpts().CPlusPlus11 ?
- diag::warn_cxx98_compat_explicit_instantiation_after_specialization :
- diag::ext_explicit_instantiation_after_specialization)
+ Diag(NewLoc, diag::warn_explicit_instantiation_after_specialization)
<< PrevDecl;
Diag(PrevDecl->getLocation(),
diag::note_previous_template_specialization);
@@ -6926,6 +7161,21 @@ bool Sema::CheckFunctionTemplateSpecialization(
continue;
}
+ // Target attributes are part of the cuda function signature, so
+ // the deduced template's cuda target must match that of the
+ // specialization. Given that C++ template deduction does not
+ // take target attributes into account, we reject candidates
+ // here that have a different target.
+ if (LangOpts.CUDA &&
+ IdentifyCUDATarget(Specialization,
+ /* IgnoreImplicitHDAttributes = */ true) !=
+ IdentifyCUDATarget(FD, /* IgnoreImplicitHDAttributes = */ true)) {
+ FailedCandidates.addCandidate().set(
+ I.getPair(), FunTmpl->getTemplatedDecl(),
+ MakeDeductionFailureInfo(Context, TDK_CUDATargetMismatch, Info));
+ continue;
+ }
+
// Record this candidate.
if (ExplicitTemplateArgs)
ConvertedTemplateArgs[Specialization] = std::move(Args);
@@ -7002,7 +7252,7 @@ bool Sema::CheckFunctionTemplateSpecialization(
SpecInfo->getPointOfInstantiation(),
HasNoEffect))
return true;
-
+
// Mark the prior declaration as an explicit specialization, so that later
// clients know that this is an explicit specialization.
if (!isFriend) {
@@ -7036,6 +7286,14 @@ bool Sema::CheckFunctionTemplateSpecialization(
SpecInfo->getTemplateSpecializationKind(),
ExplicitTemplateArgs ? &ConvertedTemplateArgs[Specialization] : nullptr);
+ // A function template specialization inherits the target attributes
+ // of its template. (We require the attributes explicitly in the
+ // code to match, but a template may have implicit attributes by
+ // virtue e.g. of being constexpr, and it passes these implicit
+ // attributes on to its specializations.)
+ if (LangOpts.CUDA)
+ inheritCUDATargetAttrs(FD, *Specialization->getPrimaryTemplate());
+
// The "previous declaration" for this function template specialization is
// the prior function template specialization.
Previous.clear();
@@ -7190,7 +7448,7 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) {
if (InstantiationFunction->isDeleted()) {
assert(InstantiationFunction->getCanonicalDecl() ==
InstantiationFunction);
- InstantiationFunction->setDeletedAsWritten(false);
+ InstantiationFunction->setDeletedAsWritten(false);
}
}
@@ -7318,6 +7576,30 @@ static bool ScopeSpecifierHasTemplateId(const CXXScopeSpec &SS) {
return false;
}
+/// Make a dllexport or dllimport attr on a class template specialization take
+/// effect.
+static void dllExportImportClassTemplateSpecialization(
+ Sema &S, ClassTemplateSpecializationDecl *Def) {
+ auto *A = cast_or_null<InheritableAttr>(getDLLAttr(Def));
+ assert(A && "dllExportImportClassTemplateSpecialization called "
+ "on Def without dllexport or dllimport");
+
+ // We reject explicit instantiations in class scope, so there should
+ // never be any delayed exported classes to worry about.
+ assert(S.DelayedDllExportClasses.empty() &&
+ "delayed exports present at explicit instantiation");
+ S.checkClassLevelDLLAttribute(Def);
+
+ // Propagate attribute to base class templates.
+ for (auto &B : Def->bases()) {
+ if (auto *BT = dyn_cast_or_null<ClassTemplateSpecializationDecl>(
+ B.getType()->getAsCXXRecordDecl()))
+ S.propagateDLLAttrToBaseClassTemplate(Def, A, BT, B.getLocStart());
+ }
+
+ S.referenceDLLExportedClassMethods();
+}
+
// Explicit instantiation of a class template specialization
DeclResult
Sema::ActOnExplicitInstantiation(Scope *S,
@@ -7344,14 +7626,8 @@ Sema::ActOnExplicitInstantiation(Scope *S,
ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(TD);
if (!ClassTemplate) {
- unsigned ErrorKind = 0;
- if (isa<TypeAliasTemplateDecl>(TD)) {
- ErrorKind = 4;
- } else if (isa<TemplateTemplateParmDecl>(TD)) {
- ErrorKind = 5;
- }
-
- Diag(TemplateNameLoc, diag::err_tag_reference_non_tag) << ErrorKind;
+ NonTagKind NTK = getNonTagTypeDeclKind(TD, Kind);
+ Diag(TemplateNameLoc, diag::err_tag_reference_non_tag) << TD << NTK << Kind;
Diag(TD->getLocation(), diag::note_previous_use);
return true;
}
@@ -7561,7 +7837,8 @@ Sema::ActOnExplicitInstantiation(Scope *S,
Def->setTemplateSpecializationKind(TSK);
if (!getDLLAttr(Def) && getDLLAttr(Specialization) &&
- Context.getTargetInfo().getCXXABI().isMicrosoft()) {
+ (Context.getTargetInfo().getCXXABI().isMicrosoft() ||
+ Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment())) {
// In the MS ABI, an explicit instantiation definition can add a dll
// attribute to a template with a previous instantiation declaration.
// MinGW doesn't allow this.
@@ -7569,23 +7846,33 @@ Sema::ActOnExplicitInstantiation(Scope *S,
getDLLAttr(Specialization)->clone(getASTContext()));
A->setInherited(true);
Def->addAttr(A);
-
- // We reject explicit instantiations in class scope, so there should
- // never be any delayed exported classes to worry about.
- assert(DelayedDllExportClasses.empty() &&
- "delayed exports present at explicit instantiation");
- checkClassLevelDLLAttribute(Def);
- referenceDLLExportedClassMethods();
-
- // Propagate attribute to base class templates.
- for (auto &B : Def->bases()) {
- if (auto *BT = dyn_cast_or_null<ClassTemplateSpecializationDecl>(
- B.getType()->getAsCXXRecordDecl()))
- propagateDLLAttrToBaseClassTemplate(Def, A, BT, B.getLocStart());
- }
+ dllExportImportClassTemplateSpecialization(*this, Def);
}
}
+ // Fix a TSK_ImplicitInstantiation followed by a
+ // TSK_ExplicitInstantiationDefinition
+ if (Old_TSK == TSK_ImplicitInstantiation &&
+ Specialization->hasAttr<DLLExportAttr>() &&
+ (Context.getTargetInfo().getCXXABI().isMicrosoft() ||
+ Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment())) {
+ // In the MS ABI, an explicit instantiation definition can add a dll
+ // attribute to a template with a previous implicit instantiation.
+ // MinGW doesn't allow this. We limit clang to only adding dllexport, to
+ // avoid potentially strange codegen behavior. For example, if we extend
+ // this conditional to dllimport, and we have a source file calling a
+ // method on an implicitly instantiated template class instance and then
+ // declaring a dllimport explicit instantiation definition for the same
+ // template class, the codegen for the method call will not respect the
+ // dllimport, while it will with cl. The Def will already have the DLL
+ // attribute, since the Def and Specialization will be the same in the
+ // case of Old_TSK == TSK_ImplicitInstantiation, and we already added the
+ // attribute to the Specialization; we just need to make it take effect.
+ assert(Def == Specialization &&
+ "Def and Specialization should match for implicit instantiation");
+ dllExportImportClassTemplateSpecialization(*this, Def);
+ }
+
// Set the template specialization kind. Make sure it is set before
// instantiating the members which will trigger ASTConsumer callbacks.
Specialization->setTemplateSpecializationKind(TSK);
@@ -7754,18 +8041,18 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
return true;
// C++ [dcl.stc]p1:
- // A storage-class-specifier shall not be specified in [...] an explicit
+ // A storage-class-specifier shall not be specified in [...] an explicit
// instantiation (14.7.2) directive.
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) {
Diag(D.getIdentifierLoc(), diag::err_explicit_instantiation_of_typedef)
<< Name;
return true;
- } else if (D.getDeclSpec().getStorageClassSpec()
+ } else if (D.getDeclSpec().getStorageClassSpec()
!= DeclSpec::SCS_unspecified) {
// Complain about then remove the storage class specifier.
Diag(D.getIdentifierLoc(), diag::err_explicit_instantiation_storage_class)
<< FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
-
+
D.getMutableDeclSpec().ClearStorageClassSpecs();
}
@@ -7957,13 +8244,15 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
// instantiated from the member definition associated with its class
// template.
UnresolvedSet<8> Matches;
+ AttributeList *Attr = D.getDeclSpec().getAttributes().getList();
TemplateSpecCandidateSet FailedCandidates(D.getIdentifierLoc());
for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end();
P != PEnd; ++P) {
NamedDecl *Prev = *P;
if (!HasExplicitTemplateArgs) {
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Prev)) {
- QualType Adjusted = adjustCCAndNoReturn(R, Method->getType());
+ QualType Adjusted = adjustCCAndNoReturn(R, Method->getType(),
+ /*AdjustExceptionSpec*/true);
if (Context.hasSameUnqualifiedType(Method->getType(), Adjusted)) {
Matches.clear();
@@ -7993,6 +8282,21 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
continue;
}
+ // Target attributes are part of the cuda function signature, so
+ // the cuda target of the instantiated function must match that of its
+ // template. Given that C++ template deduction does not take
+ // target attributes into account, we reject candidates here that
+ // have a different target.
+ if (LangOpts.CUDA &&
+ IdentifyCUDATarget(Specialization,
+ /* IgnoreImplicitHDAttributes = */ true) !=
+ IdentifyCUDATarget(Attr)) {
+ FailedCandidates.addCandidate().set(
+ P.getPair(), FunTmpl->getTemplatedDecl(),
+ MakeDeductionFailureInfo(Context, TDK_CUDATargetMismatch, Info));
+ continue;
+ }
+
Matches.addDecl(Specialization, P.getAccess());
}
@@ -8063,7 +8367,6 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
}
Specialization->setTemplateSpecializationKind(TSK, D.getIdentifierLoc());
- AttributeList *Attr = D.getDeclSpec().getAttributes().getList();
if (Attr)
ProcessDeclAttributeList(S, Specialization, Attr);
@@ -8131,7 +8434,7 @@ Sema::ActOnDependentTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// Create the resulting type.
ElaboratedTypeKeyword Kwd = TypeWithKeyword::getKeywordForTagTypeKind(Kind);
QualType Result = Context.getDependentNameType(Kwd, NNS, Name);
-
+
// Create type-source location information for this type.
TypeLocBuilder TLB;
DependentNameTypeLoc TL = TLB.push<DependentNameTypeLoc>(Result);
@@ -8147,7 +8450,7 @@ Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
SourceLocation IdLoc) {
if (SS.isInvalid())
return true;
-
+
if (TypenameLoc.isValid() && S && !S->getTemplateParamParent())
Diag(TypenameLoc,
getLangOpts().CPlusPlus11 ?
@@ -8193,11 +8496,11 @@ Sema::ActOnTypenameType(Scope *S,
diag::warn_cxx98_compat_typename_outside_of_template :
diag::ext_typename_outside_of_template)
<< FixItHint::CreateRemoval(TypenameLoc);
-
+
// Translate the parser's template argument list in our AST format.
TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);
translateTemplateArguments(TemplateArgsIn, TemplateArgs);
-
+
TemplateName Template = TemplateIn.get();
if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) {
// Construct a dependent template specialization type.
@@ -8207,10 +8510,10 @@ Sema::ActOnTypenameType(Scope *S,
DTN->getQualifier(),
DTN->getIdentifier(),
TemplateArgs);
-
+
// Create source-location information for this type.
TypeLocBuilder Builder;
- DependentTemplateSpecializationTypeLoc SpecTL
+ DependentTemplateSpecializationTypeLoc SpecTL
= Builder.push<DependentTemplateSpecializationTypeLoc>(T);
SpecTL.setElaboratedKeywordLoc(TypenameLoc);
SpecTL.setQualifierLoc(SS.getWithLocInContext(Context));
@@ -8222,11 +8525,11 @@ Sema::ActOnTypenameType(Scope *S,
SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo());
return CreateParsedType(T, Builder.getTypeSourceInfo(Context, T));
}
-
+
QualType T = CheckTemplateIdType(Template, TemplateNameLoc, TemplateArgs);
if (T.isNull())
return true;
-
+
// Provide source-location information for the template specialization type.
TypeLocBuilder Builder;
TemplateSpecializationTypeLoc SpecTL
@@ -8237,12 +8540,12 @@ Sema::ActOnTypenameType(Scope *S,
SpecTL.setRAngleLoc(RAngleLoc);
for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo());
-
+
T = Context.getElaboratedType(ETK_Typename, SS.getScopeRep(), T);
ElaboratedTypeLoc TL = Builder.push<ElaboratedTypeLoc>(T);
TL.setElaboratedKeywordLoc(TypenameLoc);
TL.setQualifierLoc(SS.getWithLocInContext(Context));
-
+
TypeSourceInfo *TSI = Builder.getTypeSourceInfo(Context, T);
return CreateParsedType(T, TSI);
}
@@ -8287,9 +8590,9 @@ static bool isEnableIf(NestedNameSpecifierLoc NNS, const IdentifierInfo &II,
/// \brief Build the type that describes a C++ typename specifier,
/// e.g., "typename T::type".
QualType
-Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
+Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
SourceLocation KeywordLoc,
- NestedNameSpecifierLoc QualifierLoc,
+ NestedNameSpecifierLoc QualifierLoc,
const IdentifierInfo &II,
SourceLocation IILoc) {
CXXScopeSpec SS;
@@ -8300,8 +8603,8 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
// If the nested-name-specifier is dependent and couldn't be
// resolved to a type, build a typename type.
assert(QualifierLoc.getNestedNameSpecifier()->isDependent());
- return Context.getDependentNameType(Keyword,
- QualifierLoc.getNestedNameSpecifier(),
+ return Context.getDependentNameType(Keyword,
+ QualifierLoc.getNestedNameSpecifier(),
&II);
}
@@ -8353,8 +8656,8 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
case LookupResult::NotFoundInCurrentInstantiation:
// Okay, it's a member of an unknown instantiation.
- return Context.getDependentNameType(Keyword,
- QualifierLoc.getNestedNameSpecifier(),
+ return Context.getDependentNameType(Keyword,
+ QualifierLoc.getNestedNameSpecifier(),
&II);
case LookupResult::Found:
@@ -8362,7 +8665,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
// We found a type. Build an ElaboratedType, since the
// typename-specifier was just sugar.
MarkAnyDeclReferenced(Type->getLocation(), Type, /*OdrUse=*/false);
- return Context.getElaboratedType(ETK_Typename,
+ return Context.getElaboratedType(ETK_Typename,
QualifierLoc.getNestedNameSpecifier(),
Context.getTypeDeclType(Type));
}
@@ -8429,7 +8732,7 @@ namespace {
this->Loc = Loc;
this->Entity = Entity;
}
-
+
ExprResult TransformLambdaExpr(LambdaExpr *E) {
// Lambdas never need to be transformed.
return E;
@@ -8480,15 +8783,15 @@ ExprResult Sema::RebuildExprInCurrentInstantiation(Expr *E) {
}
bool Sema::RebuildNestedNameSpecifierInCurrentInstantiation(CXXScopeSpec &SS) {
- if (SS.isInvalid())
+ if (SS.isInvalid())
return true;
NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context);
CurrentInstantiationRebuilder Rebuilder(*this, SS.getRange().getBegin(),
DeclarationName());
- NestedNameSpecifierLoc Rebuilt
+ NestedNameSpecifierLoc Rebuilt
= Rebuilder.TransformNestedNameSpecifierLoc(QualifierLoc);
- if (!Rebuilt)
+ if (!Rebuilt)
return true;
SS.Adopt(Rebuilt);
@@ -8501,36 +8804,36 @@ bool Sema::RebuildTemplateParamsInCurrentInstantiation(
TemplateParameterList *Params) {
for (unsigned I = 0, N = Params->size(); I != N; ++I) {
Decl *Param = Params->getParam(I);
-
+
// There is nothing to rebuild in a type parameter.
if (isa<TemplateTypeParmDecl>(Param))
continue;
-
+
// Rebuild the template parameter list of a template template parameter.
- if (TemplateTemplateParmDecl *TTP
+ if (TemplateTemplateParmDecl *TTP
= dyn_cast<TemplateTemplateParmDecl>(Param)) {
if (RebuildTemplateParamsInCurrentInstantiation(
TTP->getTemplateParameters()))
return true;
-
+
continue;
}
-
+
// Rebuild the type of a non-type template parameter.
NonTypeTemplateParmDecl *NTTP = cast<NonTypeTemplateParmDecl>(Param);
- TypeSourceInfo *NewTSI
- = RebuildTypeInCurrentInstantiation(NTTP->getTypeSourceInfo(),
- NTTP->getLocation(),
+ TypeSourceInfo *NewTSI
+ = RebuildTypeInCurrentInstantiation(NTTP->getTypeSourceInfo(),
+ NTTP->getLocation(),
NTTP->getDeclName());
if (!NewTSI)
return true;
-
+
if (NewTSI != NTTP->getTypeSourceInfo()) {
NTTP->setTypeSourceInfo(NewTSI);
NTTP->setType(NewTSI->getType());
}
}
-
+
return false;
}
@@ -8580,12 +8883,12 @@ void Sema::MarkAsLateParsedTemplate(FunctionDecl *FD, Decl *FnD,
if (!FD)
return;
- LateParsedTemplate *LPT = new LateParsedTemplate;
+ auto LPT = llvm::make_unique<LateParsedTemplate>();
// Take tokens to avoid allocations
LPT->Toks.swap(Toks);
LPT->D = FnD;
- LateParsedTemplateMap.insert(std::make_pair(FD, LPT));
+ LateParsedTemplateMap.insert(std::make_pair(FD, std::move(LPT)));
FD->setLateTemplateParsed(true);
}
@@ -8611,6 +8914,7 @@ bool Sema::IsInsideALocalClassWithinATemplateFunction() {
return false;
}
+namespace {
/// \brief 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:
@@ -8738,6 +9042,7 @@ private:
}
}
};
+} // end anonymous namespace
void Sema::checkSpecializationVisibility(SourceLocation Loc, NamedDecl *Spec) {
if (!getLangOpts().Modules)
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 5740bc712e86..0bc85a2f2635 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -100,12 +100,13 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
SmallVectorImpl<DeducedTemplateArgument> &
Deduced,
unsigned TDF,
- bool PartialOrdering = false);
+ bool PartialOrdering = false,
+ bool DeducedFromArrayBound = false);
static Sema::TemplateDeductionResult
DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams,
- const TemplateArgument *Params, unsigned NumParams,
- const TemplateArgument *Args, unsigned NumArgs,
+ ArrayRef<TemplateArgument> Params,
+ ArrayRef<TemplateArgument> Args,
TemplateDeductionInfo &Info,
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
bool NumberOfArgumentsMustMatch);
@@ -113,7 +114,8 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams,
/// \brief 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(Expr *E) {
+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) {
@@ -127,7 +129,9 @@ static NonTypeTemplateParmDecl *getDeducedParameterFromExpr(Expr *E) {
}
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
- return dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl());
+ if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl()))
+ if (NTTP->getDepth() == Info.getDeducedDepth())
+ return NTTP;
return nullptr;
}
@@ -157,6 +161,20 @@ checkDeducedTemplateArguments(ASTContext &Context,
if (Y.isNull())
return X;
+ // If we have two non-type template argument values deduced for the same
+ // parameter, they must both match the type of the parameter, and thus must
+ // match each other's type. As we're only keeping one of them, we must check
+ // for that now. The exception is that if either was deduced from an array
+ // bound, the type is permitted to differ.
+ if (!X.wasDeducedFromArrayBound() && !Y.wasDeducedFromArrayBound()) {
+ QualType XType = X.getNonTypeTemplateArgumentType();
+ if (!XType.isNull()) {
+ QualType YType = Y.getNonTypeTemplateArgumentType();
+ if (YType.isNull() || !Context.hasSameType(XType, YType))
+ return DeducedTemplateArgument();
+ }
+ }
+
switch (X.getKind()) {
case TemplateArgument::Null:
llvm_unreachable("Non-deduced template arguments handled above");
@@ -167,6 +185,12 @@ checkDeducedTemplateArguments(ASTContext &Context,
Context.hasSameType(X.getAsType(), Y.getAsType()))
return X;
+ // If one of the two arguments was deduced from an array bound, the other
+ // supersedes it.
+ if (X.wasDeducedFromArrayBound() != Y.wasDeducedFromArrayBound())
+ return X.wasDeducedFromArrayBound() ? Y : X;
+
+ // The arguments are not compatible.
return DeducedTemplateArgument();
case TemplateArgument::Integral:
@@ -177,9 +201,7 @@ checkDeducedTemplateArguments(ASTContext &Context,
Y.getKind() == TemplateArgument::Declaration ||
(Y.getKind() == TemplateArgument::Integral &&
hasSameExtendedValue(X.getAsIntegral(), Y.getAsIntegral())))
- return DeducedTemplateArgument(X,
- X.wasDeducedFromArrayBound() &&
- Y.wasDeducedFromArrayBound());
+ return X.wasDeducedFromArrayBound() ? Y : X;
// All other combinations are incompatible.
return DeducedTemplateArgument();
@@ -201,37 +223,38 @@ checkDeducedTemplateArguments(ASTContext &Context,
// All other combinations are incompatible.
return DeducedTemplateArgument();
- case TemplateArgument::Expression:
- // If we deduced a dependent expression in one case and either an integral
- // constant or a declaration in another case, keep the integral constant
- // or declaration.
- if (Y.getKind() == TemplateArgument::Integral ||
- Y.getKind() == TemplateArgument::Declaration)
- return DeducedTemplateArgument(Y, X.wasDeducedFromArrayBound() &&
- Y.wasDeducedFromArrayBound());
-
- if (Y.getKind() == TemplateArgument::Expression) {
- // Compare the expressions for equality
- llvm::FoldingSetNodeID ID1, ID2;
- X.getAsExpr()->Profile(ID1, Context, true);
- Y.getAsExpr()->Profile(ID2, Context, true);
- if (ID1 == ID2)
- return X;
- }
+ case TemplateArgument::Expression: {
+ if (Y.getKind() != TemplateArgument::Expression)
+ return checkDeducedTemplateArguments(Context, Y, X);
- // All other combinations are incompatible.
+ // Compare the expressions for equality
+ llvm::FoldingSetNodeID ID1, ID2;
+ X.getAsExpr()->Profile(ID1, Context, true);
+ Y.getAsExpr()->Profile(ID2, Context, true);
+ if (ID1 == ID2)
+ return X.wasDeducedFromArrayBound() ? Y : X;
+
+ // Differing dependent expressions are incompatible.
return DeducedTemplateArgument();
+ }
case TemplateArgument::Declaration:
+ assert(!X.wasDeducedFromArrayBound());
+
// If we deduced a declaration and a dependent expression, keep the
// declaration.
if (Y.getKind() == TemplateArgument::Expression)
return X;
// If we deduced a declaration and an integral constant, keep the
- // integral constant.
- if (Y.getKind() == TemplateArgument::Integral)
+ // integral constant and whichever type did not come from an array
+ // bound.
+ if (Y.getKind() == TemplateArgument::Integral) {
+ if (Y.wasDeducedFromArrayBound())
+ return TemplateArgument(Context, Y.getAsIntegral(),
+ X.getParamTypeForDecl());
return Y;
+ }
// If we deduced two declarations, make sure they they refer to the
// same declaration.
@@ -253,9 +276,8 @@ checkDeducedTemplateArguments(ASTContext &Context,
if (Y.getKind() == TemplateArgument::Integral)
return Y;
- // If we deduced two null pointers, make sure they have the same type.
- if (Y.getKind() == TemplateArgument::NullPtr &&
- Context.hasSameType(X.getNullPtrType(), Y.getNullPtrType()))
+ // If we deduced two null pointers, they are the same.
+ if (Y.getKind() == TemplateArgument::NullPtr)
return X;
// All other combinations are incompatible.
@@ -285,19 +307,18 @@ checkDeducedTemplateArguments(ASTContext &Context,
}
/// \brief Deduce the value of the given non-type template parameter
-/// from the given constant.
+/// as the given deduced template argument. All non-type template parameter
+/// deduction is funneled through here.
static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument(
- Sema &S, NonTypeTemplateParmDecl *NTTP, const llvm::APSInt &Value,
- QualType ValueType, bool DeducedFromArrayBound, TemplateDeductionInfo &Info,
+ Sema &S, TemplateParameterList *TemplateParams,
+ NonTypeTemplateParmDecl *NTTP, const DeducedTemplateArgument &NewDeduced,
+ QualType ValueType, TemplateDeductionInfo &Info,
SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
- assert(NTTP->getDepth() == 0 &&
- "Cannot deduce non-type template argument with depth > 0");
-
- DeducedTemplateArgument NewDeduced(S.Context, Value, ValueType,
- DeducedFromArrayBound);
- DeducedTemplateArgument Result = checkDeducedTemplateArguments(S.Context,
- Deduced[NTTP->getIndex()],
- NewDeduced);
+ assert(NTTP->getDepth() == Info.getDeducedDepth() &&
+ "deducing non-type template argument with wrong depth");
+
+ DeducedTemplateArgument Result = checkDeducedTemplateArguments(
+ S.Context, Deduced[NTTP->getIndex()], NewDeduced);
if (Result.isNull()) {
Info.Param = NTTP;
Info.FirstArg = Deduced[NTTP->getIndex()];
@@ -306,68 +327,77 @@ static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument(
}
Deduced[NTTP->getIndex()] = Result;
- return Sema::TDK_Success;
+ if (!S.getLangOpts().CPlusPlus1z)
+ return Sema::TDK_Success;
+
+ // FIXME: It's not clear how deduction of a parameter of reference
+ // type from an argument (of non-reference type) should be performed.
+ // For now, we just remove reference types from both sides and let
+ // the final check for matching types sort out the mess.
+ return DeduceTemplateArgumentsByTypeMatch(
+ S, TemplateParams, NTTP->getType().getNonReferenceType(),
+ ValueType.getNonReferenceType(), Info, Deduced, TDF_SkipNonDependent,
+ /*PartialOrdering=*/false,
+ /*ArrayBound=*/NewDeduced.wasDeducedFromArrayBound());
+}
+
+/// \brief Deduce the value of the given non-type template parameter
+/// from the given integral constant.
+static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument(
+ Sema &S, TemplateParameterList *TemplateParams,
+ NonTypeTemplateParmDecl *NTTP, const llvm::APSInt &Value,
+ QualType ValueType, bool DeducedFromArrayBound, TemplateDeductionInfo &Info,
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
+ return DeduceNonTypeTemplateArgument(
+ S, TemplateParams, NTTP,
+ DeducedTemplateArgument(S.Context, Value, ValueType,
+ DeducedFromArrayBound),
+ ValueType, Info, Deduced);
+}
+
+/// \brief 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,
+ NonTypeTemplateParmDecl *NTTP, QualType NullPtrType,
+ TemplateDeductionInfo &Info,
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
+ Expr *Value =
+ S.ImpCastExprToType(new (S.Context) CXXNullPtrLiteralExpr(
+ S.Context.NullPtrTy, NTTP->getLocation()),
+ NullPtrType, CK_NullToPointer)
+ .get();
+ return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP,
+ DeducedTemplateArgument(Value),
+ Value->getType(), Info, Deduced);
}
/// \brief 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.
-static Sema::TemplateDeductionResult
-DeduceNonTypeTemplateArgument(Sema &S,
- NonTypeTemplateParmDecl *NTTP,
- Expr *Value,
- TemplateDeductionInfo &Info,
- SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
- assert(NTTP->getDepth() == 0 &&
- "Cannot deduce non-type template argument with depth > 0");
- assert((Value->isTypeDependent() || Value->isValueDependent()) &&
- "Expression template argument must be type- or value-dependent.");
-
- DeducedTemplateArgument NewDeduced(Value);
- DeducedTemplateArgument Result = checkDeducedTemplateArguments(S.Context,
- Deduced[NTTP->getIndex()],
- NewDeduced);
-
- if (Result.isNull()) {
- Info.Param = NTTP;
- Info.FirstArg = Deduced[NTTP->getIndex()];
- Info.SecondArg = NewDeduced;
- return Sema::TDK_Inconsistent;
- }
-
- Deduced[NTTP->getIndex()] = Result;
- return Sema::TDK_Success;
+static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument(
+ Sema &S, TemplateParameterList *TemplateParams,
+ NonTypeTemplateParmDecl *NTTP, Expr *Value, TemplateDeductionInfo &Info,
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
+ return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP,
+ DeducedTemplateArgument(Value),
+ Value->getType(), Info, Deduced);
}
/// \brief Deduce the value of the given non-type template parameter
/// from the given declaration.
///
/// \returns true if deduction succeeded, false otherwise.
-static Sema::TemplateDeductionResult
-DeduceNonTypeTemplateArgument(Sema &S,
- NonTypeTemplateParmDecl *NTTP,
- ValueDecl *D,
- TemplateDeductionInfo &Info,
- SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
- assert(NTTP->getDepth() == 0 &&
- "Cannot deduce non-type template argument with depth > 0");
-
+static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument(
+ Sema &S, TemplateParameterList *TemplateParams,
+ NonTypeTemplateParmDecl *NTTP, ValueDecl *D, QualType T,
+ TemplateDeductionInfo &Info,
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
D = D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr;
- TemplateArgument New(D, NTTP->getType());
- DeducedTemplateArgument NewDeduced(New);
- DeducedTemplateArgument Result = checkDeducedTemplateArguments(S.Context,
- Deduced[NTTP->getIndex()],
- NewDeduced);
- if (Result.isNull()) {
- Info.Param = NTTP;
- Info.FirstArg = Deduced[NTTP->getIndex()];
- Info.SecondArg = NewDeduced;
- return Sema::TDK_Inconsistent;
- }
-
- Deduced[NTTP->getIndex()] = Result;
- return Sema::TDK_Success;
+ TemplateArgument New(D, T);
+ return DeduceNonTypeTemplateArgument(
+ S, TemplateParams, NTTP, DeducedTemplateArgument(New), T, Info, Deduced);
}
static Sema::TemplateDeductionResult
@@ -386,6 +416,10 @@ DeduceTemplateArguments(Sema &S,
if (TemplateTemplateParmDecl *TempParam
= dyn_cast<TemplateTemplateParmDecl>(ParamDecl)) {
+ // If we're not deducing at this depth, there's nothing to deduce.
+ if (TempParam->getDepth() != Info.getDeducedDepth())
+ return Sema::TDK_Success;
+
DeducedTemplateArgument NewDeduced(S.Context.getCanonicalTemplateName(Arg));
DeducedTemplateArgument Result = checkDeducedTemplateArguments(S.Context,
Deduced[TempParam->getIndex()],
@@ -453,9 +487,9 @@ DeduceTemplateArguments(Sema &S,
// Perform template argument deduction on each template
// argument. Ignore any missing/extra arguments, since they could be
// filled in by default arguments.
- return DeduceTemplateArguments(S, TemplateParams, Param->getArgs(),
- Param->getNumArgs(), SpecArg->getArgs(),
- SpecArg->getNumArgs(), Info, Deduced,
+ return DeduceTemplateArguments(S, TemplateParams,
+ Param->template_arguments(),
+ SpecArg->template_arguments(), Info, Deduced,
/*NumberOfArgumentsMustMatch=*/false);
}
@@ -487,10 +521,9 @@ DeduceTemplateArguments(Sema &S,
return Result;
// Perform template argument deduction for the template arguments.
- return DeduceTemplateArguments(
- S, TemplateParams, Param->getArgs(), Param->getNumArgs(),
- SpecArg->getTemplateArgs().data(), SpecArg->getTemplateArgs().size(),
- Info, Deduced, /*NumberOfArgumentsMustMatch=*/true);
+ return DeduceTemplateArguments(S, TemplateParams, Param->template_arguments(),
+ SpecArg->getTemplateArgs().asArray(), Info,
+ Deduced, /*NumberOfArgumentsMustMatch=*/true);
}
/// \brief Determines whether the given type is an opaque type that
@@ -589,7 +622,7 @@ public:
for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
unsigned Depth, Index;
std::tie(Depth, Index) = getDepthAndIndex(Unexpanded[I]);
- if (Depth == 0 && !SawIndices[Index]) {
+ if (Depth == Info.getDeducedDepth() && !SawIndices[Index]) {
SawIndices[Index] = true;
// Save the deduced template argument for the parameter pack expanded
@@ -620,7 +653,8 @@ public:
S.CurrentInstantiationScope->getPartiallySubstitutedPack(
&ExplicitArgs, &NumExplicitArgs);
if (PartiallySubstitutedPack &&
- getDepthAndIndex(PartiallySubstitutedPack).second == Pack.Index)
+ getDepthAndIndex(PartiallySubstitutedPack) ==
+ std::make_pair(Info.getDeducedDepth(), Pack.Index))
Pack.New.append(ExplicitArgs, ExplicitArgs + NumExplicitArgs);
}
}
@@ -863,12 +897,12 @@ static bool hasInconsistentOrSupersetQualifiersOf(QualType ParamType,
if (ParamQs == ArgQs)
return false;
-
+
// Mismatched (but not missing) Objective-C GC attributes.
- if (ParamQs.getObjCGCAttr() != ArgQs.getObjCGCAttr() &&
+ if (ParamQs.getObjCGCAttr() != ArgQs.getObjCGCAttr() &&
ParamQs.hasObjCGCAttr())
return true;
-
+
// Mismatched (but not missing) address spaces.
if (ParamQs.getAddressSpace() != ArgQs.getAddressSpace() &&
ParamQs.hasAddressSpace())
@@ -878,7 +912,7 @@ static bool hasInconsistentOrSupersetQualifiersOf(QualType ParamType,
if (ParamQs.getObjCLifetime() != ArgQs.getObjCLifetime() &&
ParamQs.hasObjCLifetime())
return true;
-
+
// CVR qualifier superset.
return (ParamQs.getCVRQualifiers() != ArgQs.getCVRQualifiers()) &&
((ParamQs.getCVRQualifiers() | ArgQs.getCVRQualifiers())
@@ -901,9 +935,9 @@ bool Sema::isSameOrCompatibleFunctionType(CanQualType Param,
if (!ParamFunction || !ArgFunction)
return Param == Arg;
- // Noreturn adjustment.
+ // Noreturn and noexcept adjustment.
QualType AdjustedParam;
- if (IsNoReturnConversion(Param, Arg, AdjustedParam))
+ if (IsFunctionConversion(Param, Arg, AdjustedParam))
return Arg == Context.getCanonicalType(AdjustedParam);
// FIXME: Compatible calling conventions.
@@ -942,7 +976,8 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
TemplateDeductionInfo &Info,
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
unsigned TDF,
- bool PartialOrdering) {
+ bool PartialOrdering,
+ bool DeducedFromArrayBound) {
// We only want to look at the canonical types, since typedefs and
// sugar are not part of template argument deduction.
QualType Param = S.Context.getCanonicalType(ParamIn);
@@ -1057,10 +1092,12 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
// cv-list T
if (const TemplateTypeParmType *TemplateTypeParm
= Param->getAs<TemplateTypeParmType>()) {
- // Just skip any attempts to deduce from a placeholder type.
- if (Arg->isPlaceholderType())
+ // Just skip any attempts to deduce from a placeholder type or a parameter
+ // at a different depth.
+ if (Arg->isPlaceholderType() ||
+ Info.getDeducedDepth() != TemplateTypeParm->getDepth())
return Sema::TDK_Success;
-
+
unsigned Index = TemplateTypeParm->getIndex();
bool RecanonicalizeArg = false;
@@ -1085,7 +1122,8 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
return Sema::TDK_Underqualified;
}
- assert(TemplateTypeParm->getDepth() == 0 && "Can't deduce with depth > 0");
+ assert(TemplateTypeParm->getDepth() == Info.getDeducedDepth() &&
+ "saw template type parameter with wrong depth");
assert(Arg != S.Context.OverloadTy && "Unresolved overloaded function");
QualType DeducedType = Arg;
@@ -1100,7 +1138,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
DeducedQs.removeAddressSpace();
if (ParamQs.hasObjCLifetime())
DeducedQs.removeObjCLifetime();
-
+
// Objective-C ARC:
// If template deduction would produce a lifetime qualifier on a type
// that is not a lifetime type, template argument deduction fails.
@@ -1109,9 +1147,9 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
Info.Param = cast<TemplateTypeParmDecl>(TemplateParams->getParam(Index));
Info.FirstArg = TemplateArgument(Param);
Info.SecondArg = TemplateArgument(Arg);
- return Sema::TDK_Underqualified;
+ return Sema::TDK_Underqualified;
}
-
+
// Objective-C ARC:
// If template deduction would produce an argument type with lifetime type
// but no lifetime qualifier, the __strong lifetime qualifier is inferred.
@@ -1119,14 +1157,14 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
DeducedType->isObjCLifetimeType() &&
!DeducedQs.hasObjCLifetime())
DeducedQs.setObjCLifetime(Qualifiers::OCL_Strong);
-
+
DeducedType = S.Context.getQualifiedType(DeducedType.getUnqualifiedType(),
DeducedQs);
-
+
if (RecanonicalizeArg)
DeducedType = S.Context.getCanonicalType(DeducedType);
- DeducedTemplateArgument NewDeduced(DeducedType);
+ DeducedTemplateArgument NewDeduced(DeducedType, DeducedFromArrayBound);
DeducedTemplateArgument Result = checkDeducedTemplateArguments(S.Context,
Deduced[Index],
NewDeduced);
@@ -1163,7 +1201,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
if (Param.getCVRQualifiers() != Arg.getCVRQualifiers())
return Sema::TDK_NonDeducedMismatch;
}
-
+
// If the parameter type is not dependent, there is nothing to deduce.
if (!Param->isDependentType()) {
if (!(TDF & TDF_SkipNonDependent)) {
@@ -1193,7 +1231,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
case Type::Class: llvm_unreachable("deducing non-canonical type: " #Class);
#define TYPE(Class, Base)
#include "clang/AST/TypeNodes.def"
-
+
case Type::TemplateTypeParm:
case Type::SubstTemplateTypeParmPack:
llvm_unreachable("Type nodes handled above");
@@ -1211,20 +1249,20 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
case Type::ObjCObjectPointer: {
if (TDF & TDF_SkipNonDependent)
return Sema::TDK_Success;
-
+
if (TDF & TDF_IgnoreQualifiers) {
Param = Param.getUnqualifiedType();
Arg = Arg.getUnqualifiedType();
}
-
+
return Param == Arg? Sema::TDK_Success : Sema::TDK_NonDeducedMismatch;
}
-
- // _Complex T [placeholder extension]
+
+ // _Complex T [placeholder extension]
case Type::Complex:
if (const ComplexType *ComplexArg = Arg->getAs<ComplexType>())
- return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
- cast<ComplexType>(Param)->getElementType(),
+ return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
+ cast<ComplexType>(Param)->getElementType(),
ComplexArg->getElementType(),
Info, Deduced, TDF);
@@ -1337,18 +1375,18 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
// Determine the array bound is something we can deduce.
NonTypeTemplateParmDecl *NTTP
- = getDeducedParameterFromExpr(DependentArrayParm->getSizeExpr());
+ = getDeducedParameterFromExpr(Info, DependentArrayParm->getSizeExpr());
if (!NTTP)
return Sema::TDK_Success;
// We can perform template argument deduction for the given non-type
// template parameter.
- assert(NTTP->getDepth() == 0 &&
- "Cannot deduce non-type template argument at depth > 0");
+ assert(NTTP->getDepth() == Info.getDeducedDepth() &&
+ "saw non-type template parameter with wrong depth");
if (const ConstantArrayType *ConstantArrayArg
= dyn_cast<ConstantArrayType>(ArrayArg)) {
llvm::APSInt Size(ConstantArrayArg->getSize());
- return DeduceNonTypeTemplateArgument(S, NTTP, Size,
+ return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP, Size,
S.Context.getSizeType(),
/*ArrayBound=*/true,
Info, Deduced);
@@ -1356,7 +1394,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
if (const DependentSizedArrayType *DependentArrayArg
= dyn_cast<DependentSizedArrayType>(ArrayArg))
if (DependentArrayArg->getSizeExpr())
- return DeduceNonTypeTemplateArgument(S, NTTP,
+ return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP,
DependentArrayArg->getSizeExpr(),
Info, Deduced);
@@ -1549,7 +1587,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
QualType(MemPtrParam->getClass(), 0),
QualType(MemPtrArg->getClass(), 0),
- Info, Deduced,
+ Info, Deduced,
TDF & TDF_IgnoreQualifiers);
}
@@ -1580,15 +1618,15 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
// Make sure that the vectors have the same number of elements.
if (VectorParam->getNumElements() != VectorArg->getNumElements())
return Sema::TDK_NonDeducedMismatch;
-
+
// Perform deduction on the element types.
return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams,
VectorParam->getElementType(),
VectorArg->getElementType(),
Info, Deduced, TDF);
}
-
- if (const DependentSizedExtVectorType *VectorArg
+
+ if (const DependentSizedExtVectorType *VectorArg
= dyn_cast<DependentSizedExtVectorType>(Arg)) {
// We can't check the number of elements, since the argument has a
// dependent number of elements. This can only occur during partial
@@ -1600,10 +1638,10 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
VectorArg->getElementType(),
Info, Deduced, TDF);
}
-
+
return Sema::TDK_NonDeducedMismatch;
}
-
+
// (clang extension)
//
// T __attribute__(((ext_vector_type(N))))
@@ -1619,20 +1657,24 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
VectorArg->getElementType(),
Info, Deduced, TDF))
return Result;
-
+
// Perform deduction on the vector size, if we can.
NonTypeTemplateParmDecl *NTTP
- = getDeducedParameterFromExpr(VectorParam->getSizeExpr());
+ = getDeducedParameterFromExpr(Info, VectorParam->getSizeExpr());
if (!NTTP)
return Sema::TDK_Success;
llvm::APSInt ArgSize(S.Context.getTypeSize(S.Context.IntTy), false);
ArgSize = VectorArg->getNumElements();
- return DeduceNonTypeTemplateArgument(S, NTTP, ArgSize, S.Context.IntTy,
- false, Info, Deduced);
+ // 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.IntTy, true, Info,
+ Deduced);
}
-
- if (const DependentSizedExtVectorType *VectorArg
+
+ if (const DependentSizedExtVectorType *VectorArg
= dyn_cast<DependentSizedExtVectorType>(Arg)) {
// Perform deduction on the element types.
if (Sema::TemplateDeductionResult Result
@@ -1641,20 +1683,21 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
VectorArg->getElementType(),
Info, Deduced, TDF))
return Result;
-
+
// Perform deduction on the vector size, if we can.
NonTypeTemplateParmDecl *NTTP
- = getDeducedParameterFromExpr(VectorParam->getSizeExpr());
+ = getDeducedParameterFromExpr(Info, VectorParam->getSizeExpr());
if (!NTTP)
return Sema::TDK_Success;
-
- return DeduceNonTypeTemplateArgument(S, NTTP, VectorArg->getSizeExpr(),
+
+ return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP,
+ VectorArg->getSizeExpr(),
Info, Deduced);
}
-
+
return Sema::TDK_NonDeducedMismatch;
}
-
+
case Type::TypeOfExpr:
case Type::TypeOf:
case Type::DependentName:
@@ -1751,18 +1794,24 @@ DeduceTemplateArguments(Sema &S,
case TemplateArgument::Expression: {
if (NonTypeTemplateParmDecl *NTTP
- = getDeducedParameterFromExpr(Param.getAsExpr())) {
+ = getDeducedParameterFromExpr(Info, Param.getAsExpr())) {
if (Arg.getKind() == TemplateArgument::Integral)
- return DeduceNonTypeTemplateArgument(S, NTTP,
+ return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP,
Arg.getAsIntegral(),
Arg.getIntegralType(),
/*ArrayBound=*/false,
Info, Deduced);
- if (Arg.getKind() == TemplateArgument::Expression)
- return DeduceNonTypeTemplateArgument(S, NTTP, Arg.getAsExpr(),
+ if (Arg.getKind() == TemplateArgument::NullPtr)
+ return DeduceNullPtrTemplateArgument(S, TemplateParams, NTTP,
+ Arg.getNullPtrType(),
Info, Deduced);
+ if (Arg.getKind() == TemplateArgument::Expression)
+ return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP,
+ Arg.getAsExpr(), Info, Deduced);
if (Arg.getKind() == TemplateArgument::Declaration)
- return DeduceNonTypeTemplateArgument(S, NTTP, Arg.getAsDecl(),
+ return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP,
+ Arg.getAsDecl(),
+ Arg.getParamTypeForDecl(),
Info, Deduced);
Info.FirstArg = Param;
@@ -1788,45 +1837,34 @@ DeduceTemplateArguments(Sema &S,
///
/// \returns true if there is another template argument (which will be at
/// \c Args[ArgIdx]), false otherwise.
-static bool hasTemplateArgumentForDeduction(const TemplateArgument *&Args,
- unsigned &ArgIdx,
- unsigned &NumArgs) {
- if (ArgIdx == NumArgs)
+static bool hasTemplateArgumentForDeduction(ArrayRef<TemplateArgument> &Args,
+ unsigned &ArgIdx) {
+ if (ArgIdx == Args.size())
return false;
const TemplateArgument &Arg = Args[ArgIdx];
if (Arg.getKind() != TemplateArgument::Pack)
return true;
- assert(ArgIdx == NumArgs - 1 && "Pack not at the end of argument list?");
- Args = Arg.pack_begin();
- NumArgs = Arg.pack_size();
+ assert(ArgIdx == Args.size() - 1 && "Pack not at the end of argument list?");
+ Args = Arg.pack_elements();
ArgIdx = 0;
- return ArgIdx < NumArgs;
+ return ArgIdx < Args.size();
}
/// \brief Determine whether the given set of template arguments has a pack
/// expansion that is not the last template argument.
-static bool hasPackExpansionBeforeEnd(const TemplateArgument *Args,
- unsigned NumArgs) {
- unsigned ArgIdx = 0;
- while (ArgIdx < NumArgs) {
- const TemplateArgument &Arg = Args[ArgIdx];
-
- // Unwrap argument packs.
- if (Args[ArgIdx].getKind() == TemplateArgument::Pack) {
- Args = Arg.pack_begin();
- NumArgs = Arg.pack_size();
- ArgIdx = 0;
- continue;
- }
+static bool hasPackExpansionBeforeEnd(ArrayRef<TemplateArgument> Args) {
+ bool FoundPackExpansion = false;
+ for (const auto &A : Args) {
+ if (FoundPackExpansion)
+ return true;
- ++ArgIdx;
- if (ArgIdx == NumArgs)
- return false;
+ if (A.getKind() == TemplateArgument::Pack)
+ return hasPackExpansionBeforeEnd(A.pack_elements());
- if (Arg.isPackExpansion())
- return true;
+ if (A.isPackExpansion())
+ FoundPackExpansion = true;
}
return false;
@@ -1834,8 +1872,8 @@ static bool hasPackExpansionBeforeEnd(const TemplateArgument *Args,
static Sema::TemplateDeductionResult
DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams,
- const TemplateArgument *Params, unsigned NumParams,
- const TemplateArgument *Args, unsigned NumArgs,
+ ArrayRef<TemplateArgument> Params,
+ ArrayRef<TemplateArgument> Args,
TemplateDeductionInfo &Info,
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
bool NumberOfArgumentsMustMatch) {
@@ -1843,7 +1881,7 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams,
// If the template argument list of P contains a pack expansion that is not
// the last template argument, the entire template argument list is a
// non-deduced context.
- if (hasPackExpansionBeforeEnd(Params, NumParams))
+ if (hasPackExpansionBeforeEnd(Params))
return Sema::TDK_Success;
// C++0x [temp.deduct.type]p9:
@@ -1851,21 +1889,20 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams,
// respective template argument list P is compared with the corresponding
// argument Ai of the corresponding template argument list of A.
unsigned ArgIdx = 0, ParamIdx = 0;
- for (; hasTemplateArgumentForDeduction(Params, ParamIdx, NumParams);
- ++ParamIdx) {
+ for (; hasTemplateArgumentForDeduction(Params, ParamIdx); ++ParamIdx) {
if (!Params[ParamIdx].isPackExpansion()) {
// The simple case: deduce template arguments by matching Pi and Ai.
// Check whether we have enough arguments.
- if (!hasTemplateArgumentForDeduction(Args, ArgIdx, NumArgs))
+ if (!hasTemplateArgumentForDeduction(Args, ArgIdx))
return NumberOfArgumentsMustMatch ? Sema::TDK_TooFewArguments
: Sema::TDK_Success;
- if (Args[ArgIdx].isPackExpansion()) {
- // FIXME: We follow the logic of C++0x [temp.deduct.type]p22 here,
- // but applied to pack expansions that are template arguments.
+ // C++1z [temp.deduct.type]p9:
+ // During partial ordering, if Ai was originally a pack expansion [and]
+ // Pi is not a pack expansion, template argument deduction fails.
+ if (Args[ArgIdx].isPackExpansion())
return Sema::TDK_MiscellaneousDeductionFailure;
- }
// Perform deduction for this Pi/Ai pair.
if (Sema::TemplateDeductionResult Result
@@ -1899,7 +1936,7 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams,
// expanded by this pack expansion (the outer index) and for each
// template argument (the inner SmallVectors).
bool HasAnyArguments = false;
- for (; hasTemplateArgumentForDeduction(Args, ArgIdx, NumArgs); ++ArgIdx) {
+ for (; hasTemplateArgumentForDeduction(Args, ArgIdx); ++ArgIdx) {
HasAnyArguments = true;
// Deduce template arguments from the pattern.
@@ -1927,16 +1964,21 @@ DeduceTemplateArguments(Sema &S,
const TemplateArgumentList &ArgList,
TemplateDeductionInfo &Info,
SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
- return DeduceTemplateArguments(S, TemplateParams,
- ParamList.data(), ParamList.size(),
- ArgList.data(), ArgList.size(),
- Info, Deduced, false);
+ return DeduceTemplateArguments(S, TemplateParams, ParamList.asArray(),
+ ArgList.asArray(), Info, Deduced,
+ /*NumberOfArgumentsMustMatch*/false);
}
/// \brief Determine whether two template arguments are the same.
static bool isSameTemplateArg(ASTContext &Context,
- const TemplateArgument &X,
- const TemplateArgument &Y) {
+ TemplateArgument X,
+ const TemplateArgument &Y,
+ bool PackExpansionMatchesPack = false) {
+ // If we're checking deduced arguments (X) against original arguments (Y),
+ // we will have flattened packs to non-expansions in X.
+ if (PackExpansionMatchesPack && X.isPackExpansion() && !Y.isPackExpansion())
+ X = X.getPackExpansionPattern();
+
if (X.getKind() != Y.getKind())
return false;
@@ -1962,7 +2004,7 @@ static bool isSameTemplateArg(ASTContext &Context,
Y.getAsTemplateOrTemplatePattern()).getAsVoidPointer();
case TemplateArgument::Integral:
- return X.getAsIntegral() == Y.getAsIntegral();
+ return hasSameExtendedValue(X.getAsIntegral(), Y.getAsIntegral());
case TemplateArgument::Expression: {
llvm::FoldingSetNodeID XID, YID;
@@ -1979,7 +2021,7 @@ static bool isSameTemplateArg(ASTContext &Context,
XPEnd = X.pack_end(),
YP = Y.pack_begin();
XP != XPEnd; ++XP, ++YP)
- if (!isSameTemplateArg(Context, *XP, *YP))
+ if (!isSameTemplateArg(Context, *XP, *YP, PackExpansionMatchesPack))
return false;
return true;
@@ -1991,48 +2033,47 @@ static bool isSameTemplateArg(ASTContext &Context,
/// \brief Allocate a TemplateArgumentLoc where all locations have
/// been initialized to the given location.
///
-/// \param S The semantic analysis object.
-///
/// \param Arg The template argument we are producing template argument
/// location information for.
///
/// \param NTTPType For a declaration template argument, the type of
/// the non-type template parameter that corresponds to this template
-/// argument.
+/// argument. Can be null if no type sugar is available to add to the
+/// type from the template argument.
///
/// \param Loc The source location to use for the resulting template
/// argument.
-static TemplateArgumentLoc
-getTrivialTemplateArgumentLoc(Sema &S,
- const TemplateArgument &Arg,
- QualType NTTPType,
- SourceLocation Loc) {
+TemplateArgumentLoc
+Sema::getTrivialTemplateArgumentLoc(const TemplateArgument &Arg,
+ QualType NTTPType, SourceLocation Loc) {
switch (Arg.getKind()) {
case TemplateArgument::Null:
llvm_unreachable("Can't get a NULL template argument here");
case TemplateArgument::Type:
- return TemplateArgumentLoc(Arg,
- S.Context.getTrivialTypeSourceInfo(Arg.getAsType(), Loc));
+ return TemplateArgumentLoc(
+ Arg, Context.getTrivialTypeSourceInfo(Arg.getAsType(), Loc));
case TemplateArgument::Declaration: {
- Expr *E
- = S.BuildExpressionFromDeclTemplateArgument(Arg, NTTPType, Loc)
- .getAs<Expr>();
+ if (NTTPType.isNull())
+ NTTPType = Arg.getParamTypeForDecl();
+ Expr *E = BuildExpressionFromDeclTemplateArgument(Arg, NTTPType, Loc)
+ .getAs<Expr>();
return TemplateArgumentLoc(TemplateArgument(E), E);
}
case TemplateArgument::NullPtr: {
- Expr *E
- = S.BuildExpressionFromDeclTemplateArgument(Arg, NTTPType, Loc)
- .getAs<Expr>();
+ if (NTTPType.isNull())
+ NTTPType = Arg.getNullPtrType();
+ Expr *E = BuildExpressionFromDeclTemplateArgument(Arg, NTTPType, Loc)
+ .getAs<Expr>();
return TemplateArgumentLoc(TemplateArgument(NTTPType, /*isNullPtr*/true),
E);
}
case TemplateArgument::Integral: {
- Expr *E
- = S.BuildExpressionFromIntegralTemplateArgument(Arg, Loc).getAs<Expr>();
+ Expr *E =
+ BuildExpressionFromIntegralTemplateArgument(Arg, Loc).getAs<Expr>();
return TemplateArgumentLoc(TemplateArgument(E), E);
}
@@ -2041,18 +2082,16 @@ getTrivialTemplateArgumentLoc(Sema &S,
NestedNameSpecifierLocBuilder Builder;
TemplateName Template = Arg.getAsTemplate();
if (DependentTemplateName *DTN = Template.getAsDependentTemplateName())
- Builder.MakeTrivial(S.Context, DTN->getQualifier(), Loc);
+ Builder.MakeTrivial(Context, DTN->getQualifier(), Loc);
else if (QualifiedTemplateName *QTN =
Template.getAsQualifiedTemplateName())
- Builder.MakeTrivial(S.Context, QTN->getQualifier(), Loc);
-
+ Builder.MakeTrivial(Context, QTN->getQualifier(), Loc);
+
if (Arg.getKind() == TemplateArgument::Template)
- return TemplateArgumentLoc(Arg,
- Builder.getWithLocInContext(S.Context),
+ return TemplateArgumentLoc(Arg, Builder.getWithLocInContext(Context),
Loc);
-
-
- return TemplateArgumentLoc(Arg, Builder.getWithLocInContext(S.Context),
+
+ return TemplateArgumentLoc(Arg, Builder.getWithLocInContext(Context),
Loc, Loc);
}
@@ -2074,39 +2113,21 @@ ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param,
DeducedTemplateArgument Arg,
NamedDecl *Template,
TemplateDeductionInfo &Info,
- bool InFunctionTemplate,
+ bool IsDeduced,
SmallVectorImpl<TemplateArgument> &Output) {
- // First, for a non-type template parameter type that is
- // initialized by a declaration, we need the type of the
- // corresponding non-type template parameter.
- QualType NTTPType;
- if (NonTypeTemplateParmDecl *NTTP =
- dyn_cast<NonTypeTemplateParmDecl>(Param)) {
- NTTPType = NTTP->getType();
- if (NTTPType->isDependentType()) {
- TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Output);
- NTTPType = S.SubstType(NTTPType,
- MultiLevelTemplateArgumentList(TemplateArgs),
- NTTP->getLocation(),
- NTTP->getDeclName());
- if (NTTPType.isNull())
- return true;
- }
- }
-
auto ConvertArg = [&](DeducedTemplateArgument Arg,
unsigned ArgumentPackIndex) {
// Convert the deduced template argument into a template
// argument that we can check, almost as if the user had written
// the template argument explicitly.
TemplateArgumentLoc ArgLoc =
- getTrivialTemplateArgumentLoc(S, Arg, NTTPType, Info.getLocation());
+ S.getTrivialTemplateArgumentLoc(Arg, QualType(), Info.getLocation());
// Check the template argument, converting it as necessary.
return S.CheckTemplateArgument(
Param, ArgLoc, Template, Template->getLocation(),
Template->getSourceRange().getEnd(), ArgumentPackIndex, Output,
- InFunctionTemplate
+ IsDeduced
? (Arg.wasDeducedFromArrayBound() ? Sema::CTAK_DeducedFromArrayBound
: Sema::CTAK_Deduced)
: Sema::CTAK_Specified);
@@ -2132,22 +2153,28 @@ ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param,
}
// If the pack is empty, we still need to substitute into the parameter
- // itself, in case that substitution fails. For non-type parameters, we did
- // this above. For type parameters, no substitution is ever required.
- auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Param);
- if (TTP && PackedArgsBuilder.empty()) {
- // Set up a template instantiation context.
+ // itself, in case that substitution fails.
+ if (PackedArgsBuilder.empty()) {
LocalInstantiationScope Scope(S);
- Sema::InstantiatingTemplate Inst(S, Template->getLocation(), Template,
- TTP, Output,
- Template->getSourceRange());
- if (Inst.isInvalid())
- return true;
-
TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Output);
- if (!S.SubstDecl(TTP, S.CurContext,
- MultiLevelTemplateArgumentList(TemplateArgs)))
- return true;
+ MultiLevelTemplateArgumentList Args(TemplateArgs);
+
+ if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
+ Sema::InstantiatingTemplate Inst(S, Template->getLocation(), Template,
+ NTTP, Output,
+ Template->getSourceRange());
+ if (Inst.isInvalid() ||
+ S.SubstType(NTTP->getType(), Args, NTTP->getLocation(),
+ NTTP->getDeclName()).isNull())
+ return true;
+ } else if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Param)) {
+ Sema::InstantiatingTemplate Inst(S, Template->getLocation(), Template,
+ TTP, Output,
+ Template->getSourceRange());
+ if (Inst.isInvalid() || !S.SubstDecl(TTP, S.CurContext, Args))
+ return true;
+ }
+ // For type parameters, no substitution is ever required.
}
// Create the resulting argument pack.
@@ -2159,44 +2186,169 @@ ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param,
return ConvertArg(Arg, 0);
}
-/// Complete template argument deduction for a class template partial
-/// specialization.
-static Sema::TemplateDeductionResult
-FinishTemplateArgumentDeduction(Sema &S,
- ClassTemplatePartialSpecializationDecl *Partial,
- const TemplateArgumentList &TemplateArgs,
- SmallVectorImpl<DeducedTemplateArgument> &Deduced,
- TemplateDeductionInfo &Info) {
- // Unevaluated SFINAE context.
- EnterExpressionEvaluationContext Unevaluated(S, Sema::Unevaluated);
- Sema::SFINAETrap Trap(S);
+// FIXME: This should not be a template, but
+// ClassTemplatePartialSpecializationDecl sadly does not derive from
+// TemplateDecl.
+template<typename TemplateDeclT>
+static Sema::TemplateDeductionResult ConvertDeducedTemplateArguments(
+ Sema &S, TemplateDeclT *Template, bool IsDeduced,
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+ TemplateDeductionInfo &Info, SmallVectorImpl<TemplateArgument> &Builder,
+ LocalInstantiationScope *CurrentInstantiationScope = nullptr,
+ unsigned NumAlreadyConverted = 0, bool PartialOverloading = false) {
+ TemplateParameterList *TemplateParams = Template->getTemplateParameters();
- Sema::ContextRAII SavedContext(S, Partial);
+ for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) {
+ NamedDecl *Param = TemplateParams->getParam(I);
- // C++ [temp.deduct.type]p2:
- // [...] or if any template argument remains neither deduced nor
- // explicitly specified, template argument deduction fails.
- SmallVector<TemplateArgument, 4> Builder;
- TemplateParameterList *PartialParams = Partial->getTemplateParameters();
- for (unsigned I = 0, N = PartialParams->size(); I != N; ++I) {
- NamedDecl *Param = PartialParams->getParam(I);
- if (Deduced[I].isNull()) {
- Info.Param = makeTemplateParameter(Param);
+ if (!Deduced[I].isNull()) {
+ if (I < NumAlreadyConverted) {
+ // We have already fully type-checked and converted this
+ // argument, because it was explicitly-specified. Just record the
+ // presence of this argument.
+ Builder.push_back(Deduced[I]);
+ // We may have had explicitly-specified template arguments for a
+ // template parameter pack (that may or may not have been extended
+ // via additional deduced arguments).
+ if (Param->isParameterPack() && CurrentInstantiationScope) {
+ if (CurrentInstantiationScope->getPartiallySubstitutedPack() ==
+ Param) {
+ // Forget the partially-substituted pack; its substitution is now
+ // complete.
+ CurrentInstantiationScope->ResetPartiallySubstitutedPack();
+ }
+ }
+ continue;
+ }
+
+ // We have deduced this argument, so it still needs to be
+ // checked and converted.
+ if (ConvertDeducedTemplateArgument(S, Param, Deduced[I], 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;
+ }
+
+ // 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);
+ if (!TD) {
+ assert(isa<ClassTemplatePartialSpecializationDecl>(Template));
return Sema::TDK_Incomplete;
}
- // We have deduced this argument, so it still needs to be
- // checked and converted.
- if (ConvertDeducedTemplateArgument(S, Param, Deduced[I],
- Partial, Info, false,
- Builder)) {
- Info.Param = makeTemplateParameter(Param);
+ TemplateArgumentLoc DefArg = S.SubstDefaultTemplateArgumentIfAvailable(
+ TD, TD->getLocation(), TD->getSourceRange().getEnd(), Param, Builder,
+ HasDefaultArg);
+
+ // If there was no default argument, deduction is incomplete.
+ if (DefArg.getArgument().isNull()) {
+ Info.Param = makeTemplateParameter(
+ const_cast<NamedDecl *>(TemplateParams->getParam(I)));
+ Info.reset(TemplateArgumentList::CreateCopy(S.Context, Builder));
+ if (PartialOverloading) break;
+
+ return HasDefaultArg ? Sema::TDK_SubstitutionFailure
+ : Sema::TDK_Incomplete;
+ }
+
+ // Check whether we can actually use the default argument.
+ if (S.CheckTemplateArgument(Param, DefArg, TD, TD->getLocation(),
+ TD->getSourceRange().getEnd(), 0, Builder,
+ Sema::CTAK_Specified)) {
+ Info.Param = makeTemplateParameter(
+ const_cast<NamedDecl *>(TemplateParams->getParam(I)));
// FIXME: These template arguments are temporary. Free them!
Info.reset(TemplateArgumentList::CreateCopy(S.Context, Builder));
return Sema::TDK_SubstitutionFailure;
}
+
+ // If we get here, we successfully used the default template argument.
}
+ return Sema::TDK_Success;
+}
+
+DeclContext *getAsDeclContextOrEnclosing(Decl *D) {
+ if (auto *DC = dyn_cast<DeclContext>(D))
+ return DC;
+ return D->getDeclContext();
+}
+
+template<typename T> struct IsPartialSpecialization {
+ static constexpr bool value = false;
+};
+template<>
+struct IsPartialSpecialization<ClassTemplatePartialSpecializationDecl> {
+ static constexpr bool value = true;
+};
+template<>
+struct IsPartialSpecialization<VarTemplatePartialSpecializationDecl> {
+ static constexpr bool value = true;
+};
+
+/// Complete template argument deduction for a partial specialization.
+template <typename T>
+static typename std::enable_if<IsPartialSpecialization<T>::value,
+ Sema::TemplateDeductionResult>::type
+FinishTemplateArgumentDeduction(
+ Sema &S, T *Partial, bool IsPartialOrdering,
+ const TemplateArgumentList &TemplateArgs,
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+ TemplateDeductionInfo &Info) {
+ // Unevaluated SFINAE context.
+ EnterExpressionEvaluationContext Unevaluated(S, Sema::Unevaluated);
+ Sema::SFINAETrap Trap(S);
+
+ Sema::ContextRAII SavedContext(S, getAsDeclContextOrEnclosing(Partial));
+
+ // C++ [temp.deduct.type]p2:
+ // [...] or if any template argument remains neither deduced nor
+ // explicitly specified, template argument deduction fails.
+ SmallVector<TemplateArgument, 4> Builder;
+ if (auto Result = ConvertDeducedTemplateArguments(
+ S, Partial, IsPartialOrdering, Deduced, Info, Builder))
+ return Result;
+
// Form the template argument list from the deduced template arguments.
TemplateArgumentList *DeducedArgumentList
= TemplateArgumentList::CreateCopy(S.Context, Builder);
@@ -2209,11 +2361,11 @@ FinishTemplateArgumentDeduction(Sema &S,
// and are equivalent to the template arguments originally provided
// to the class template.
LocalInstantiationScope InstScope(S);
- ClassTemplateDecl *ClassTemplate = Partial->getSpecializedTemplate();
- const ASTTemplateArgumentListInfo *PartialTemplArgInfo
- = Partial->getTemplateArgsAsWritten();
- const TemplateArgumentLoc *PartialTemplateArgs
- = PartialTemplArgInfo->getTemplateArgs();
+ auto *Template = Partial->getSpecializedTemplate();
+ const ASTTemplateArgumentListInfo *PartialTemplArgInfo =
+ Partial->getTemplateArgsAsWritten();
+ const TemplateArgumentLoc *PartialTemplateArgs =
+ PartialTemplArgInfo->getTemplateArgs();
TemplateArgumentListInfo InstArgs(PartialTemplArgInfo->LAngleLoc,
PartialTemplArgInfo->RAngleLoc);
@@ -2224,21 +2376,19 @@ FinishTemplateArgumentDeduction(Sema &S,
if (ParamIdx >= Partial->getTemplateParameters()->size())
ParamIdx = Partial->getTemplateParameters()->size() - 1;
- Decl *Param
- = const_cast<NamedDecl *>(
- Partial->getTemplateParameters()->getParam(ParamIdx));
+ Decl *Param = const_cast<NamedDecl *>(
+ Partial->getTemplateParameters()->getParam(ParamIdx));
Info.Param = makeTemplateParameter(Param);
Info.FirstArg = PartialTemplateArgs[ArgIdx].getArgument();
return Sema::TDK_SubstitutionFailure;
}
SmallVector<TemplateArgument, 4> ConvertedInstArgs;
- if (S.CheckTemplateArgumentList(ClassTemplate, Partial->getLocation(),
- InstArgs, false, ConvertedInstArgs))
+ if (S.CheckTemplateArgumentList(Template, Partial->getLocation(), InstArgs,
+ false, ConvertedInstArgs))
return Sema::TDK_SubstitutionFailure;
- TemplateParameterList *TemplateParams
- = ClassTemplate->getTemplateParameters();
+ TemplateParameterList *TemplateParams = Template->getTemplateParameters();
for (unsigned I = 0, E = TemplateParams->size(); I != E; ++I) {
TemplateArgument InstArg = ConvertedInstArgs.data()[I];
if (!isSameTemplateArg(S.Context, TemplateArgs[I], InstArg)) {
@@ -2255,6 +2405,48 @@ FinishTemplateArgumentDeduction(Sema &S,
return Sema::TDK_Success;
}
+/// Complete template argument deduction for a class or variable template,
+/// when partial ordering against a partial specialization.
+// FIXME: Factor out duplication with partial specialization version above.
+Sema::TemplateDeductionResult FinishTemplateArgumentDeduction(
+ Sema &S, TemplateDecl *Template, bool PartialOrdering,
+ const TemplateArgumentList &TemplateArgs,
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+ TemplateDeductionInfo &Info) {
+ // Unevaluated SFINAE context.
+ EnterExpressionEvaluationContext Unevaluated(S, Sema::Unevaluated);
+ Sema::SFINAETrap Trap(S);
+
+ Sema::ContextRAII SavedContext(S, getAsDeclContextOrEnclosing(Template));
+
+ // C++ [temp.deduct.type]p2:
+ // [...] or if any template argument remains neither deduced nor
+ // explicitly specified, template argument deduction fails.
+ SmallVector<TemplateArgument, 4> Builder;
+ if (auto Result = ConvertDeducedTemplateArguments(
+ S, Template, /*IsDeduced*/PartialOrdering, Deduced, Info, Builder))
+ return Result;
+
+ // Check that we produced the correct argument list.
+ TemplateParameterList *TemplateParams = Template->getTemplateParameters();
+ for (unsigned I = 0, E = TemplateParams->size(); I != E; ++I) {
+ TemplateArgument InstArg = Builder[I];
+ if (!isSameTemplateArg(S.Context, TemplateArgs[I], InstArg,
+ /*PackExpansionMatchesPack*/true)) {
+ Info.Param = makeTemplateParameter(TemplateParams->getParam(I));
+ Info.FirstArg = TemplateArgs[I];
+ Info.SecondArg = InstArg;
+ return Sema::TDK_NonDeducedMismatch;
+ }
+ }
+
+ if (Trap.hasErrorOccurred())
+ return Sema::TDK_SubstitutionFailure;
+
+ return Sema::TDK_Success;
+}
+
+
/// \brief Perform template argument deduction to determine whether
/// the given template arguments match the given class template
/// partial specialization per C++ [temp.class.spec.match].
@@ -2293,112 +2485,13 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
if (Trap.hasErrorOccurred())
return Sema::TDK_SubstitutionFailure;
- return ::FinishTemplateArgumentDeduction(*this, Partial, TemplateArgs,
- Deduced, Info);
-}
-
-/// Complete template argument deduction for a variable template partial
-/// specialization.
-/// TODO: Unify with ClassTemplatePartialSpecializationDecl version?
-/// May require unifying ClassTemplate(Partial)SpecializationDecl and
-/// VarTemplate(Partial)SpecializationDecl with a new data
-/// structure Template(Partial)SpecializationDecl, and
-/// using Template(Partial)SpecializationDecl as input type.
-static Sema::TemplateDeductionResult FinishTemplateArgumentDeduction(
- Sema &S, VarTemplatePartialSpecializationDecl *Partial,
- const TemplateArgumentList &TemplateArgs,
- SmallVectorImpl<DeducedTemplateArgument> &Deduced,
- TemplateDeductionInfo &Info) {
- // Unevaluated SFINAE context.
- EnterExpressionEvaluationContext Unevaluated(S, Sema::Unevaluated);
- Sema::SFINAETrap Trap(S);
-
- // C++ [temp.deduct.type]p2:
- // [...] or if any template argument remains neither deduced nor
- // explicitly specified, template argument deduction fails.
- SmallVector<TemplateArgument, 4> Builder;
- TemplateParameterList *PartialParams = Partial->getTemplateParameters();
- for (unsigned I = 0, N = PartialParams->size(); I != N; ++I) {
- NamedDecl *Param = PartialParams->getParam(I);
- if (Deduced[I].isNull()) {
- Info.Param = makeTemplateParameter(Param);
- return Sema::TDK_Incomplete;
- }
-
- // We have deduced this argument, so it still needs to be
- // checked and converted.
- if (ConvertDeducedTemplateArgument(S, Param, Deduced[I], Partial,
- Info, false, Builder)) {
- Info.Param = makeTemplateParameter(Param);
- // FIXME: These template arguments are temporary. Free them!
- Info.reset(TemplateArgumentList::CreateCopy(S.Context, Builder));
- return Sema::TDK_SubstitutionFailure;
- }
- }
-
- // Form the template argument list from the deduced template arguments.
- TemplateArgumentList *DeducedArgumentList = TemplateArgumentList::CreateCopy(
- S.Context, Builder);
-
- Info.reset(DeducedArgumentList);
-
- // Substitute the deduced template arguments into the template
- // arguments of the class template partial specialization, and
- // verify that the instantiated template arguments are both valid
- // and are equivalent to the template arguments originally provided
- // to the class template.
- LocalInstantiationScope InstScope(S);
- VarTemplateDecl *VarTemplate = Partial->getSpecializedTemplate();
- const ASTTemplateArgumentListInfo *PartialTemplArgInfo
- = Partial->getTemplateArgsAsWritten();
- const TemplateArgumentLoc *PartialTemplateArgs
- = PartialTemplArgInfo->getTemplateArgs();
-
- TemplateArgumentListInfo InstArgs(PartialTemplArgInfo->LAngleLoc,
- PartialTemplArgInfo->RAngleLoc);
-
- if (S.Subst(PartialTemplateArgs, PartialTemplArgInfo->NumTemplateArgs,
- InstArgs, MultiLevelTemplateArgumentList(*DeducedArgumentList))) {
- unsigned ArgIdx = InstArgs.size(), ParamIdx = ArgIdx;
- if (ParamIdx >= Partial->getTemplateParameters()->size())
- ParamIdx = Partial->getTemplateParameters()->size() - 1;
-
- Decl *Param = const_cast<NamedDecl *>(
- Partial->getTemplateParameters()->getParam(ParamIdx));
- Info.Param = makeTemplateParameter(Param);
- Info.FirstArg = PartialTemplateArgs[ArgIdx].getArgument();
- return Sema::TDK_SubstitutionFailure;
- }
- SmallVector<TemplateArgument, 4> ConvertedInstArgs;
- if (S.CheckTemplateArgumentList(VarTemplate, Partial->getLocation(), InstArgs,
- false, ConvertedInstArgs))
- return Sema::TDK_SubstitutionFailure;
-
- TemplateParameterList *TemplateParams = VarTemplate->getTemplateParameters();
- for (unsigned I = 0, E = TemplateParams->size(); I != E; ++I) {
- TemplateArgument InstArg = ConvertedInstArgs.data()[I];
- if (!isSameTemplateArg(S.Context, TemplateArgs[I], InstArg)) {
- Info.Param = makeTemplateParameter(TemplateParams->getParam(I));
- Info.FirstArg = TemplateArgs[I];
- Info.SecondArg = InstArg;
- return Sema::TDK_NonDeducedMismatch;
- }
- }
-
- if (Trap.hasErrorOccurred())
- return Sema::TDK_SubstitutionFailure;
-
- return Sema::TDK_Success;
+ return ::FinishTemplateArgumentDeduction(
+ *this, Partial, /*PartialOrdering=*/false, TemplateArgs, Deduced, Info);
}
/// \brief Perform template argument deduction to determine whether
/// the given template arguments match the given variable template
/// partial specialization per C++ [temp.class.spec.match].
-/// TODO: Unify with ClassTemplatePartialSpecializationDecl version?
-/// May require unifying ClassTemplate(Partial)SpecializationDecl and
-/// VarTemplate(Partial)SpecializationDecl with a new data
-/// structure Template(Partial)SpecializationDecl, and
-/// using Template(Partial)SpecializationDecl as input type.
Sema::TemplateDeductionResult
Sema::DeduceTemplateArguments(VarTemplatePartialSpecializationDecl *Partial,
const TemplateArgumentList &TemplateArgs,
@@ -2432,8 +2525,8 @@ Sema::DeduceTemplateArguments(VarTemplatePartialSpecializationDecl *Partial,
if (Trap.hasErrorOccurred())
return Sema::TDK_SubstitutionFailure;
- return ::FinishTemplateArgumentDeduction(*this, Partial, TemplateArgs,
- Deduced, Info);
+ return ::FinishTemplateArgumentDeduction(
+ *this, Partial, /*PartialOrdering=*/false, TemplateArgs, Deduced, Info);
}
/// \brief Determine whether the given type T is a simple-template-id type.
@@ -2573,15 +2666,15 @@ Sema::SubstituteExplicitTemplateArguments(
ParamTypes, /*params*/ nullptr, ExtParamInfos))
return TDK_SubstitutionFailure;
}
-
+
// Instantiate the return type.
QualType ResultType;
{
// C++11 [expr.prim.general]p3:
- // If a declaration declares a member function or member function
- // template of a class X, the expression this is a prvalue of type
+ // If a declaration declares a member function or member function
+ // template of a class X, the expression this is a prvalue of type
// "pointer to cv-qualifier-seq X" between the optional cv-qualifer-seq
- // and the end of the function-definition, member-declarator, or
+ // and the end of the function-definition, member-declarator, or
// declarator.
unsigned ThisTypeQuals = 0;
CXXRecordDecl *ThisContext = nullptr;
@@ -2589,7 +2682,7 @@ Sema::SubstituteExplicitTemplateArguments(
ThisContext = Method->getParent();
ThisTypeQuals = Method->getTypeQualifiers();
}
-
+
CXXThisScopeRAII ThisScope(*this, ThisContext, ThisTypeQuals,
getLangOpts().CPlusPlus11);
@@ -2645,35 +2738,42 @@ Sema::SubstituteExplicitTemplateArguments(
/// \brief Check whether the deduced argument type for a call to a function
/// template matches the actual argument type per C++ [temp.deduct.call]p4.
-static bool
-CheckOriginalCallArgDeduction(Sema &S, Sema::OriginalCallArg OriginalArg,
+static bool
+CheckOriginalCallArgDeduction(Sema &S, Sema::OriginalCallArg OriginalArg,
QualType DeducedA) {
ASTContext &Context = S.Context;
-
+
QualType A = OriginalArg.OriginalArgType;
QualType OriginalParamType = OriginalArg.OriginalParamType;
-
+
// Check for type equality (top-level cv-qualifiers are ignored).
if (Context.hasSameUnqualifiedType(A, DeducedA))
return false;
-
+
// Strip off references on the argument types; they aren't needed for
// the following checks.
if (const ReferenceType *DeducedARef = DeducedA->getAs<ReferenceType>())
DeducedA = DeducedARef->getPointeeType();
if (const ReferenceType *ARef = A->getAs<ReferenceType>())
A = ARef->getPointeeType();
-
+
// C++ [temp.deduct.call]p4:
// [...] However, there are three cases that allow a difference:
- // - If the original P is a reference type, the deduced A (i.e., the
- // type referred to by the reference) can be more cv-qualified than
+ // - If the original P is a reference type, the deduced A (i.e., the
+ // type referred to by the reference) can be more cv-qualified than
// the transformed A.
if (const ReferenceType *OriginalParamRef
= OriginalParamType->getAs<ReferenceType>()) {
// We don't want to keep the reference around any more.
OriginalParamType = OriginalParamRef->getPointeeType();
-
+
+ // FIXME: Resolve core issue (no number yet): if the original P is a
+ // reference type and the transformed A is function type "noexcept F",
+ // the deduced A can be F.
+ QualType Tmp;
+ if (A->isFunctionType() && S.IsFunctionConversion(A, DeducedA, Tmp))
+ return false;
+
Qualifiers AQuals = A.getQualifiers();
Qualifiers DeducedAQuals = DeducedA.getQualifiers();
@@ -2693,34 +2793,32 @@ CheckOriginalCallArgDeduction(Sema &S, Sema::OriginalCallArg OriginalArg,
// Qualifiers match; there's nothing to do.
} else if (!DeducedAQuals.compatiblyIncludes(AQuals)) {
return true;
- } else {
+ } else {
// Qualifiers are compatible, so have the argument type adopt the
// deduced argument type's qualifiers as if we had performed the
// qualification conversion.
A = Context.getQualifiedType(A.getUnqualifiedType(), DeducedAQuals);
}
}
-
- // - The transformed A can be another pointer or pointer to member
- // type that can be converted to the deduced A via a qualification
- // conversion.
+
+ // - The transformed A can be another pointer or pointer to member
+ // type that can be converted to the deduced A via a function pointer
+ // conversion and/or a qualification conversion.
//
- // Also allow conversions which merely strip [[noreturn]] from function types
- // (recursively) as an extension.
- // FIXME: Currently, this doesn't play nicely with qualification conversions.
+ // Also allow conversions which merely strip __attribute__((noreturn)) from
+ // function types (recursively).
bool ObjCLifetimeConversion = false;
QualType ResultTy;
if ((A->isAnyPointerType() || A->isMemberPointerType()) &&
(S.IsQualificationConversion(A, DeducedA, false,
ObjCLifetimeConversion) ||
- S.IsNoReturnConversion(A, DeducedA, ResultTy)))
+ S.IsFunctionConversion(A, DeducedA, ResultTy)))
return false;
-
-
- // - If P is a class and P has the form simple-template-id, then the
+
+ // - If P is a class and P has the form simple-template-id, then the
// transformed A can be a derived class of the deduced A. [...]
- // [...] Likewise, if P is a pointer to a class of the form
- // simple-template-id, the transformed A can be a pointer to a
+ // [...] Likewise, if P is a pointer to a class of the form
+ // simple-template-id, the transformed A can be a pointer to a
// derived class pointed to by the deduced A.
if (const PointerType *OriginalParamPtr
= OriginalParamType->getAs<PointerType>()) {
@@ -2734,14 +2832,14 @@ CheckOriginalCallArgDeduction(Sema &S, Sema::OriginalCallArg OriginalArg,
}
}
}
-
+
if (Context.hasSameUnqualifiedType(A, DeducedA))
return false;
-
+
if (A->isRecordType() && isSimpleTemplateIdType(OriginalParamType) &&
S.IsDerivedFrom(SourceLocation(), A, DeducedA))
return false;
-
+
return true;
}
@@ -2759,9 +2857,6 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
TemplateDeductionInfo &Info,
SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs,
bool PartialOverloading) {
- TemplateParameterList *TemplateParams
- = FunctionTemplate->getTemplateParameters();
-
// Unevaluated SFINAE context.
EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
SFINAETrap Trap(*this);
@@ -2782,114 +2877,11 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
// [...] or if any template argument remains neither deduced nor
// explicitly specified, template argument deduction fails.
SmallVector<TemplateArgument, 4> Builder;
- for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) {
- NamedDecl *Param = TemplateParams->getParam(I);
-
- if (!Deduced[I].isNull()) {
- if (I < NumExplicitlySpecified) {
- // We have already fully type-checked and converted this
- // argument, because it was explicitly-specified. Just record the
- // presence of this argument.
- Builder.push_back(Deduced[I]);
- // We may have had explicitly-specified template arguments for a
- // template parameter pack (that may or may not have been extended
- // via additional deduced arguments).
- if (Param->isParameterPack() && CurrentInstantiationScope) {
- if (CurrentInstantiationScope->getPartiallySubstitutedPack() ==
- Param) {
- // Forget the partially-substituted pack; its substitution is now
- // complete.
- CurrentInstantiationScope->ResetPartiallySubstitutedPack();
- }
- }
- continue;
- }
-
- // We have deduced this argument, so it still needs to be
- // checked and converted.
- if (ConvertDeducedTemplateArgument(*this, Param, Deduced[I],
- FunctionTemplate, Info,
- true, Builder)) {
- Info.Param = makeTemplateParameter(Param);
- // FIXME: These template arguments are temporary. Free them!
- Info.reset(TemplateArgumentList::CreateCopy(Context, Builder));
- return TDK_SubstitutionFailure;
- }
-
- 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(*this, Param, DeducedPack,
- FunctionTemplate, Info, true,
- Builder)) {
- Info.Param = makeTemplateParameter(Param);
- // FIXME: These template arguments are temporary. Free them!
- Info.reset(TemplateArgumentList::CreateCopy(Context, Builder));
- return TDK_SubstitutionFailure;
- }
- }
- continue;
- }
-
- // Substitute into the default template argument, if available.
- bool HasDefaultArg = false;
- TemplateArgumentLoc DefArg
- = SubstDefaultTemplateArgumentIfAvailable(FunctionTemplate,
- FunctionTemplate->getLocation(),
- FunctionTemplate->getSourceRange().getEnd(),
- Param,
- Builder, HasDefaultArg);
-
- // If there was no default argument, deduction is incomplete.
- if (DefArg.getArgument().isNull()) {
- Info.Param = makeTemplateParameter(
- const_cast<NamedDecl *>(TemplateParams->getParam(I)));
- Info.reset(TemplateArgumentList::CreateCopy(Context, Builder));
- if (PartialOverloading) break;
-
- return HasDefaultArg ? TDK_SubstitutionFailure : TDK_Incomplete;
- }
-
- // Check whether we can actually use the default argument.
- if (CheckTemplateArgument(Param, DefArg,
- FunctionTemplate,
- FunctionTemplate->getLocation(),
- FunctionTemplate->getSourceRange().getEnd(),
- 0, Builder,
- CTAK_Specified)) {
- Info.Param = makeTemplateParameter(
- const_cast<NamedDecl *>(TemplateParams->getParam(I)));
- // FIXME: These template arguments are temporary. Free them!
- Info.reset(TemplateArgumentList::CreateCopy(Context, Builder));
- return TDK_SubstitutionFailure;
- }
-
- // If we get here, we successfully used the default template argument.
- }
+ if (auto Result = ConvertDeducedTemplateArguments(
+ *this, FunctionTemplate, /*IsDeduced*/true, Deduced, Info, Builder,
+ CurrentInstantiationScope, NumExplicitlySpecified,
+ PartialOverloading))
+ return Result;
// Form the template argument list from the deduced template arguments.
TemplateArgumentList *DeducedArgumentList
@@ -2927,15 +2919,15 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
if (OriginalCallArgs) {
// C++ [temp.deduct.call]p4:
// In general, the deduction process attempts to find template argument
- // values that will make the deduced A identical to A (after the type A
+ // values that will make the deduced A identical to A (after the type A
// is transformed as described above). [...]
for (unsigned I = 0, N = OriginalCallArgs->size(); I != N; ++I) {
OriginalCallArg OriginalArg = (*OriginalCallArgs)[I];
unsigned ParamIdx = OriginalArg.ArgIdx;
-
+
if (ParamIdx >= Specialization->getNumParams())
continue;
-
+
QualType DeducedA = Specialization->getParamDecl(ParamIdx)->getType();
if (CheckOriginalCallArgDeduction(*this, OriginalArg, DeducedA)) {
Info.FirstArg = TemplateArgument(DeducedA);
@@ -2945,7 +2937,7 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
}
}
}
-
+
// If we suppressed any diagnostics while performing template argument
// deduction, and if we haven't already instantiated this declaration,
// keep track of these diagnostics. They'll be emitted if this specialization
@@ -3025,7 +3017,7 @@ ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams,
return QualType();
}
-
+
// Gather the explicit template arguments, if any.
TemplateArgumentListInfo ExplicitTemplateArgs;
if (Ovl->hasExplicitTemplateArgs())
@@ -3041,14 +3033,14 @@ ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams,
// non-deduced context.
if (!Ovl->hasExplicitTemplateArgs())
return QualType();
-
- // Otherwise, see if we can resolve a function type
+
+ // Otherwise, see if we can resolve a function type
FunctionDecl *Specialization = nullptr;
TemplateDeductionInfo Info(Ovl->getNameLoc());
if (S.DeduceTemplateArguments(FunTmpl, &ExplicitTemplateArgs,
Specialization, Info))
continue;
-
+
D = Specialization;
}
@@ -3250,16 +3242,13 @@ DeduceFromInitializerList(Sema &S, TemplateParameterList *TemplateParams,
S.Context.getAsDependentSizedArrayType(AdjustedParamType);
// Determine the array bound is something we can deduce.
if (NonTypeTemplateParmDecl *NTTP =
- getDeducedParameterFromExpr(ArrTy->getSizeExpr())) {
+ getDeducedParameterFromExpr(Info, ArrTy->getSizeExpr())) {
// We can perform template argument deduction for the given non-type
// template parameter.
- assert(NTTP->getDepth() == 0 &&
- "Cannot deduce non-type template argument at depth > 0");
llvm::APInt Size(S.Context.getIntWidth(NTTP->getType()),
ILE->getNumInits());
-
Result = DeduceNonTypeTemplateArgument(
- S, NTTP, llvm::APSInt(Size), NTTP->getType(),
+ S, TemplateParams, NTTP, llvm::APSInt(Size), NTTP->getType(),
/*ArrayBound=*/true, Info, Deduced);
}
}
@@ -3291,7 +3280,7 @@ DeduceTemplateArgumentByListElement(Sema &S,
// For all other cases, just match by type.
QualType ArgType = Arg->getType();
- if (AdjustFunctionParmAndArgTypesForDeduction(S, TemplateParams, ParamType,
+ if (AdjustFunctionParmAndArgTypesForDeduction(S, TemplateParams, ParamType,
ArgType, Arg, TDF)) {
Info.Expression = Arg;
return Sema::TDK_FailedOverloadResolution;
@@ -3382,7 +3371,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
ParamIdx != NumParamTypes; ++ParamIdx) {
QualType OrigParamType = ParamTypes[ParamIdx];
QualType ParamType = OrigParamType;
-
+
const PackExpansionType *ParamExpansion
= dyn_cast<PackExpansionType>(ParamType);
if (!ParamExpansion) {
@@ -3392,7 +3381,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
Expr *Arg = Args[ArgIdx++];
QualType ArgType = Arg->getType();
-
+
unsigned TDF = 0;
if (AdjustFunctionParmAndArgTypesForDeduction(*this, TemplateParams,
ParamType, ArgType, Arg,
@@ -3419,7 +3408,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
// Keep track of the argument type and corresponding parameter index,
// so we can check for compatibility between the deduced A and A.
- OriginalCallArgs.push_back(OriginalCallArg(OrigParamType, ArgIdx-1,
+ OriginalCallArgs.push_back(OriginalCallArg(OrigParamType, ArgIdx-1,
ArgType));
if (TemplateDeductionResult Result
@@ -3482,7 +3471,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
// Keep track of the argument type and corresponding argument index,
// so we can check for compatibility between the deduced A and A.
if (hasDeducibleTemplateParameters(*this, FunctionTemplate, ParamType))
- OriginalCallArgs.push_back(OriginalCallArg(OrigParamType, ArgIdx,
+ OriginalCallArgs.push_back(OriginalCallArg(OrigParamType, ArgIdx,
ArgType));
if (TemplateDeductionResult Result
@@ -3511,25 +3500,42 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
}
QualType Sema::adjustCCAndNoReturn(QualType ArgFunctionType,
- QualType FunctionType) {
+ QualType FunctionType,
+ bool AdjustExceptionSpec) {
if (ArgFunctionType.isNull())
return ArgFunctionType;
const FunctionProtoType *FunctionTypeP =
FunctionType->castAs<FunctionProtoType>();
- CallingConv CC = FunctionTypeP->getCallConv();
- bool NoReturn = FunctionTypeP->getNoReturnAttr();
const FunctionProtoType *ArgFunctionTypeP =
ArgFunctionType->getAs<FunctionProtoType>();
- if (ArgFunctionTypeP->getCallConv() == CC &&
- ArgFunctionTypeP->getNoReturnAttr() == NoReturn)
+
+ FunctionProtoType::ExtProtoInfo EPI = ArgFunctionTypeP->getExtProtoInfo();
+ bool Rebuild = false;
+
+ CallingConv CC = FunctionTypeP->getCallConv();
+ if (EPI.ExtInfo.getCC() != CC) {
+ EPI.ExtInfo = EPI.ExtInfo.withCallingConv(CC);
+ Rebuild = true;
+ }
+
+ bool NoReturn = FunctionTypeP->getNoReturnAttr();
+ if (EPI.ExtInfo.getNoReturn() != NoReturn) {
+ EPI.ExtInfo = EPI.ExtInfo.withNoReturn(NoReturn);
+ Rebuild = true;
+ }
+
+ if (AdjustExceptionSpec && (FunctionTypeP->hasExceptionSpec() ||
+ ArgFunctionTypeP->hasExceptionSpec())) {
+ EPI.ExceptionSpec = FunctionTypeP->getExtProtoInfo().ExceptionSpec;
+ Rebuild = true;
+ }
+
+ if (!Rebuild)
return ArgFunctionType;
- FunctionType::ExtInfo EI = ArgFunctionTypeP->getExtInfo().withCallingConv(CC);
- EI = EI.withNoReturn(NoReturn);
- ArgFunctionTypeP =
- cast<FunctionProtoType>(Context.adjustFunctionType(ArgFunctionTypeP, EI));
- return QualType(ArgFunctionTypeP, 0);
+ return Context.getFunctionType(ArgFunctionTypeP->getReturnType(),
+ ArgFunctionTypeP->getParamTypes(), EPI);
}
/// \brief Deduce template arguments when taking the address of a function
@@ -3554,14 +3560,17 @@ QualType Sema::adjustCCAndNoReturn(QualType ArgFunctionType,
/// \param Info the argument will be updated to provide additional information
/// about template argument deduction.
///
+/// \param IsAddressOfFunction If \c true, we are deducing as part of taking
+/// the address of a function template per [temp.deduct.funcaddr] and
+/// [over.over]. If \c false, we are looking up a function template
+/// specialization based on its signature, per [temp.deduct.decl].
+///
/// \returns the result of template argument deduction.
-Sema::TemplateDeductionResult
-Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
- TemplateArgumentListInfo *ExplicitTemplateArgs,
- QualType ArgFunctionType,
- FunctionDecl *&Specialization,
- TemplateDeductionInfo &Info,
- bool InOverloadResolution) {
+Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
+ FunctionTemplateDecl *FunctionTemplate,
+ TemplateArgumentListInfo *ExplicitTemplateArgs, QualType ArgFunctionType,
+ FunctionDecl *&Specialization, TemplateDeductionInfo &Info,
+ bool IsAddressOfFunction) {
if (FunctionTemplate->isInvalidDecl())
return TDK_Invalid;
@@ -3569,8 +3578,13 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
TemplateParameterList *TemplateParams
= FunctionTemplate->getTemplateParameters();
QualType FunctionType = Function->getType();
- if (!InOverloadResolution)
- ArgFunctionType = adjustCCAndNoReturn(ArgFunctionType, FunctionType);
+
+ // When taking the address of a function, we require convertibility of
+ // the resulting function type. Otherwise, we allow arbitrary mismatches
+ // of calling convention, noreturn, and noexcept.
+ if (!IsAddressOfFunction)
+ ArgFunctionType = adjustCCAndNoReturn(ArgFunctionType, FunctionType,
+ /*AdjustExceptionSpec*/true);
// Substitute any explicit template arguments.
LocalInstantiationScope InstScope(*this);
@@ -3595,9 +3609,11 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
Deduced.resize(TemplateParams->size());
// If the function has a deduced return type, substitute it for a dependent
- // type so that we treat it as a non-deduced context in what follows.
+ // type so that we treat it as a non-deduced context in what follows. If we
+ // are looking up by signature, the signature type should also have a deduced
+ // return type, which we instead expect to exactly match.
bool HasDeducedReturnType = false;
- if (getLangOpts().CPlusPlus14 && InOverloadResolution &&
+ if (getLangOpts().CPlusPlus14 && IsAddressOfFunction &&
Function->getReturnType()->getContainedAutoType()) {
FunctionType = SubstAutoType(FunctionType, Context.DependentTy);
HasDeducedReturnType = true;
@@ -3605,7 +3621,8 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
if (!ArgFunctionType.isNull()) {
unsigned TDF = TDF_TopLevelParameterTypeList;
- if (InOverloadResolution) TDF |= TDF_InOverloadResolution;
+ if (IsAddressOfFunction)
+ TDF |= TDF_InOverloadResolution;
// Deduce template arguments from the function type.
if (TemplateDeductionResult Result
= DeduceTemplateArgumentsByTypeMatch(*this, TemplateParams,
@@ -3627,86 +3644,106 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
DeduceReturnType(Specialization, Info.getLocation(), false))
return TDK_MiscellaneousDeductionFailure;
+ // If the function has a dependent exception specification, resolve it now,
+ // so we can check that the exception specification matches.
+ auto *SpecializationFPT =
+ Specialization->getType()->castAs<FunctionProtoType>();
+ if (getLangOpts().CPlusPlus1z &&
+ isUnresolvedExceptionSpec(SpecializationFPT->getExceptionSpecType()) &&
+ !ResolveExceptionSpec(Info.getLocation(), SpecializationFPT))
+ return TDK_MiscellaneousDeductionFailure;
+
+ // Adjust the exception specification of the argument again to match the
+ // substituted and resolved type we just formed. (Calling convention and
+ // noreturn can't be dependent, so we don't actually need this for them
+ // right now.)
+ QualType SpecializationType = Specialization->getType();
+ if (!IsAddressOfFunction)
+ ArgFunctionType = adjustCCAndNoReturn(ArgFunctionType, SpecializationType,
+ /*AdjustExceptionSpec*/true);
+
// If the requested function type does not match the actual type of the
// specialization with respect to arguments of compatible pointer to function
// types, template argument deduction fails.
if (!ArgFunctionType.isNull()) {
- if (InOverloadResolution && !isSameOrCompatibleFunctionType(
- Context.getCanonicalType(Specialization->getType()),
- Context.getCanonicalType(ArgFunctionType)))
+ if (IsAddressOfFunction &&
+ !isSameOrCompatibleFunctionType(
+ Context.getCanonicalType(SpecializationType),
+ Context.getCanonicalType(ArgFunctionType)))
return TDK_MiscellaneousDeductionFailure;
- else if(!InOverloadResolution &&
- !Context.hasSameType(Specialization->getType(), ArgFunctionType))
+
+ if (!IsAddressOfFunction &&
+ !Context.hasSameType(SpecializationType, ArgFunctionType))
return TDK_MiscellaneousDeductionFailure;
}
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
+/// \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,
+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,
+ 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
+/// \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
+static inline Sema::TemplateDeductionResult
SpecializeCorrespondingLambdaCallOperatorAndInvoker(
CXXConversionDecl *ConversionSpecialized,
SmallVectorImpl<DeducedTemplateArgument> &DeducedArguments,
QualType ReturnTypeOfDestFunctionPtr,
TemplateDeductionInfo &TDInfo,
Sema &S) {
-
+
CXXRecordDecl *LambdaClass = ConversionSpecialized->getParent();
- assert(LambdaClass && LambdaClass->isGenericLambda());
-
+ assert(LambdaClass && LambdaClass->isGenericLambda());
+
CXXMethodDecl *CallOpGeneric = LambdaClass->getLambdaCallOperator();
QualType CallOpResultType = CallOpGeneric->getReturnType();
- const bool GenericLambdaCallOperatorHasDeducedReturnType =
+ const bool GenericLambdaCallOperatorHasDeducedReturnType =
CallOpResultType->getContainedAutoType();
-
- FunctionTemplateDecl *CallOpTemplate =
+
+ FunctionTemplateDecl *CallOpTemplate =
CallOpGeneric->getDescribedFunctionTemplate();
FunctionDecl *CallOpSpecialized = nullptr;
- // Use the deduced arguments of the conversion function, to specialize our
+ // Use the deduced arguments of the conversion function, to specialize our
// generic lambda's call operator.
if (Sema::TemplateDeductionResult Result
- = S.FinishTemplateArgumentDeduction(CallOpTemplate,
- DeducedArguments,
+ = 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,
+ 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
+ // 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.
@@ -3717,16 +3754,16 @@ SpecializeCorrespondingLambdaCallOperatorAndInvoker(
#ifndef NDEBUG
Sema::TemplateDeductionResult LLVM_ATTRIBUTE_UNUSED Result =
#endif
- S.FinishTemplateArgumentDeduction(InvokerTemplate, DeducedArguments, 0,
+ S.FinishTemplateArgumentDeduction(InvokerTemplate, DeducedArguments, 0,
InvokerSpecialized, TDInfo);
- assert(Result == Sema::TDK_Success &&
+ 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
+ // the full result type of the call op specialization
// to substitute into the 'auto' of the invoker and conversion
// function.
// For e.g.
@@ -3738,14 +3775,14 @@ SpecializeCorrespondingLambdaCallOperatorAndInvoker(
->getDeducedType();
SubstAutoWithinFunctionReturnType(InvokerSpecialized,
TypeToReplaceAutoWith, S);
- SubstAutoWithinFunctionReturnType(ConversionSpecialized,
+ SubstAutoWithinFunctionReturnType(ConversionSpecialized,
TypeToReplaceAutoWith, S);
}
-
+
// Ensure that static invoker doesn't have a const qualifier.
- // FIXME: When creating the InvokerTemplate in SemaLambda.cpp
+ // FIXME: When creating the InvokerTemplate in SemaLambda.cpp
// do not use the CallOperator's TypeSourceInfo which allows
- // the const qualifier to leak through.
+ // the const qualifier to leak through.
const FunctionProtoType *InvokerFPT = InvokerSpecialized->
getType().getTypePtr()->castAs<FunctionProtoType>();
FunctionProtoType::ExtProtoInfo EPI = InvokerFPT->getExtProtoInfo();
@@ -3857,7 +3894,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *ConversionTemplate,
// Finish template argument deduction.
FunctionDecl *ConversionSpecialized = nullptr;
TemplateDeductionResult Result
- = FinishTemplateArgumentDeduction(ConversionTemplate, Deduced, 0,
+ = FinishTemplateArgumentDeduction(ConversionTemplate, Deduced, 0,
ConversionSpecialized, Info);
Specialization = cast_or_null<CXXConversionDecl>(ConversionSpecialized);
@@ -3866,19 +3903,19 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *ConversionTemplate,
// 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
+ // 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() &&
+ assert(A->isPointerType() &&
"Can only convert from lambda to ptr-to-function");
- const FunctionType *ToFunType =
+ 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
+ // 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); };
@@ -3886,7 +3923,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *ConversionTemplate,
// char (*fp2)(int) = L; <-- Not OK.
Result = SpecializeCorrespondingLambdaCallOperatorAndInvoker(
- Specialization, Deduced, DestFunctionPtrReturnType,
+ Specialization, Deduced, DestFunctionPtrReturnType,
Info, *this);
}
return Result;
@@ -3908,16 +3945,22 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *ConversionTemplate,
/// \param Info the argument will be updated to provide additional information
/// about template argument deduction.
///
+/// \param IsAddressOfFunction If \c true, we are deducing as part of taking
+/// the address of a function template in a context where we do not have a
+/// target type, per [over.over]. If \c false, we are looking up a function
+/// template specialization based on its signature, which only happens when
+/// deducing a function parameter type from an argument that is a template-id
+/// naming a function template specialization.
+///
/// \returns the result of template argument deduction.
-Sema::TemplateDeductionResult
-Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
- TemplateArgumentListInfo *ExplicitTemplateArgs,
- FunctionDecl *&Specialization,
- TemplateDeductionInfo &Info,
- bool InOverloadResolution) {
+Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
+ FunctionTemplateDecl *FunctionTemplate,
+ TemplateArgumentListInfo *ExplicitTemplateArgs,
+ FunctionDecl *&Specialization, TemplateDeductionInfo &Info,
+ bool IsAddressOfFunction) {
return DeduceTemplateArguments(FunctionTemplate, ExplicitTemplateArgs,
QualType(), Specialization, Info,
- InOverloadResolution);
+ IsAddressOfFunction);
}
namespace {
@@ -3926,10 +3969,12 @@ namespace {
class SubstituteAutoTransform :
public TreeTransform<SubstituteAutoTransform> {
QualType Replacement;
+ bool UseAutoSugar;
public:
- SubstituteAutoTransform(Sema &SemaRef, QualType Replacement)
+ SubstituteAutoTransform(Sema &SemaRef, QualType Replacement,
+ bool UseAutoSugar = true)
: TreeTransform<SubstituteAutoTransform>(SemaRef),
- Replacement(Replacement) {}
+ Replacement(Replacement), UseAutoSugar(UseAutoSugar) {}
QualType TransformAutoType(TypeLocBuilder &TLB, AutoTypeLoc TL) {
// If we're building the type pattern to deduce against, don't wrap the
@@ -3939,19 +3984,17 @@ namespace {
// auto &&lref = lvalue;
// must transform into "rvalue reference to T" not "rvalue reference to
// auto type deduced as T" in order for [temp.deduct.call]p3 to apply.
- if (!Replacement.isNull() && isa<TemplateTypeParmType>(Replacement)) {
+ if (!UseAutoSugar) {
+ assert(isa<TemplateTypeParmType>(Replacement) &&
+ "unexpected unsugared replacement kind");
QualType Result = Replacement;
TemplateTypeParmTypeLoc NewTL =
TLB.push<TemplateTypeParmTypeLoc>(Result);
NewTL.setNameLoc(TL.getNameLoc());
return Result;
} else {
- bool Dependent =
- !Replacement.isNull() && Replacement->isDependentType();
- QualType Result =
- SemaRef.Context.getAutoType(Dependent ? QualType() : Replacement,
- TL.getTypePtr()->getKeyword(),
- Dependent);
+ QualType Result = SemaRef.Context.getAutoType(
+ Replacement, TL.getTypePtr()->getKeyword(), Replacement.isNull());
AutoTypeLoc NewTL = TLB.push<AutoTypeLoc>(Result);
NewTL.setNameLoc(TL.getNameLoc());
return Result;
@@ -3974,18 +4017,29 @@ namespace {
}
Sema::DeduceAutoResult
-Sema::DeduceAutoType(TypeSourceInfo *Type, Expr *&Init, QualType &Result) {
- return DeduceAutoType(Type->getTypeLoc(), Init, Result);
+Sema::DeduceAutoType(TypeSourceInfo *Type, Expr *&Init, QualType &Result,
+ Optional<unsigned> DependentDeductionDepth) {
+ return DeduceAutoType(Type->getTypeLoc(), Init, Result,
+ DependentDeductionDepth);
}
/// \brief Deduce the type for an auto type-specifier (C++11 [dcl.spec.auto]p6)
///
+/// Note that this is done even if the initializer is dependent. (This is
+/// necessary to support partial ordering of templates using 'auto'.)
+/// A dependent type will be produced when deducing from a dependent type.
+///
/// \param Type the type pattern using the auto type-specifier.
/// \param Init the initializer for the variable whose type is to be deduced.
/// \param Result if type deduction was successful, this will be set to the
/// deduced type.
+/// \param DependentDeductionDepth Set if we should permit deduction in
+/// dependent cases. This is necessary for template partial ordering with
+/// 'auto' template parameters. The value specified is the template
+/// parameter depth at which we should perform 'auto' deduction.
Sema::DeduceAutoResult
-Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result) {
+Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result,
+ Optional<unsigned> DependentDeductionDepth) {
if (Init->getType()->isNonOverloadPlaceholderType()) {
ExprResult NonPlaceholder = CheckPlaceholderExpr(Init);
if (NonPlaceholder.isInvalid())
@@ -3993,12 +4047,16 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result) {
Init = NonPlaceholder.get();
}
- if (Init->isTypeDependent() || Type.getType()->isDependentType()) {
- Result = SubstituteAutoTransform(*this, Context.DependentTy).Apply(Type);
+ if (!DependentDeductionDepth &&
+ (Type.getType()->isDependentType() || Init->isTypeDependent())) {
+ Result = SubstituteAutoTransform(*this, QualType()).Apply(Type);
assert(!Result.isNull() && "substituting DependentTy can't fail");
return DAR_Succeeded;
}
+ // Find the depth of template parameter to synthesize.
+ unsigned Depth = DependentDeductionDepth.getValueOr(0);
+
// If this is a 'decltype(auto)' specifier, do the decltype dance.
// Since 'decltype(auto)' can only occur at the top of the type, we
// don't need to go digging for it.
@@ -4031,15 +4089,16 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result) {
LocalInstantiationScope InstScope(*this);
// Build template<class TemplParam> void Func(FuncParam);
- TemplateTypeParmDecl *TemplParam =
- TemplateTypeParmDecl::Create(Context, nullptr, SourceLocation(), Loc, 0, 0,
- nullptr, false, false);
+ TemplateTypeParmDecl *TemplParam = TemplateTypeParmDecl::Create(
+ Context, nullptr, SourceLocation(), Loc, Depth, 0, nullptr, false, false);
QualType TemplArg = QualType(TemplParam->getTypeForDecl(), 0);
NamedDecl *TemplParamPtr = TemplParam;
- FixedSizeTemplateParameterListStorage<1> TemplateParamsSt(
- Loc, Loc, TemplParamPtr, Loc);
+ FixedSizeTemplateParameterListStorage<1, false> TemplateParamsSt(
+ Loc, Loc, TemplParamPtr, Loc, nullptr);
- QualType FuncParam = SubstituteAutoTransform(*this, TemplArg).Apply(Type);
+ QualType FuncParam =
+ SubstituteAutoTransform(*this, TemplArg, /*UseAutoSugar*/false)
+ .Apply(Type);
assert(!FuncParam.isNull() &&
"substituting template parameter for 'auto' failed");
@@ -4049,7 +4108,18 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result) {
QualType InitType = Init->getType();
unsigned TDF = 0;
- TemplateDeductionInfo Info(Loc);
+ TemplateDeductionInfo Info(Loc, Depth);
+
+ // If deduction failed, don't diagnose if the initializer is dependent; it
+ // might acquire a matching type in the instantiation.
+ auto DeductionFailed = [&]() -> DeduceAutoResult {
+ if (Init->isTypeDependent()) {
+ Result = SubstituteAutoTransform(*this, QualType()).Apply(Type);
+ assert(!Result.isNull() && "substituting DependentTy can't fail");
+ return DAR_Succeeded;
+ }
+ return DAR_Failed;
+ };
InitListExpr *InitList = dyn_cast<InitListExpr>(Init);
if (InitList) {
@@ -4057,7 +4127,7 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result) {
if (DeduceTemplateArgumentByListElement(*this, TemplateParamsSt.get(),
TemplArg, InitList->getInit(i),
Info, Deduced, TDF))
- return DAR_Failed;
+ return DeductionFailed();
}
} else {
if (!getLangOpts().CPlusPlus && Init->refersToBitField()) {
@@ -4072,11 +4142,12 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result) {
if (DeduceTemplateArgumentsByTypeMatch(*this, TemplateParamsSt.get(),
FuncParam, InitType, Info, Deduced,
TDF))
- return DAR_Failed;
+ return DeductionFailed();
}
+ // Could be null if somehow 'auto' appears in a non-deduced context.
if (Deduced[0].getKind() != TemplateArgument::Type)
- return DAR_Failed;
+ return DeductionFailed();
QualType DeducedType = Deduced[0].getAsType();
@@ -4088,7 +4159,7 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result) {
Result = SubstituteAutoTransform(*this, DeducedType).Apply(Type);
if (Result.isNull())
- return DAR_FailedAlreadyDiagnosed;
+ return DAR_FailedAlreadyDiagnosed;
// Check that the deduced argument type is compatible with the original
// argument type per C++ [temp.deduct.call]p4.
@@ -4097,22 +4168,26 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result) {
Sema::OriginalCallArg(FuncParam,0,InitType),
Result)) {
Result = QualType();
- return DAR_Failed;
+ return DeductionFailed();
}
return DAR_Succeeded;
}
-QualType Sema::SubstAutoType(QualType TypeWithAuto,
+QualType Sema::SubstAutoType(QualType TypeWithAuto,
QualType TypeToReplaceAuto) {
- return SubstituteAutoTransform(*this, TypeToReplaceAuto).
- TransformType(TypeWithAuto);
+ if (TypeToReplaceAuto->isDependentType())
+ TypeToReplaceAuto = QualType();
+ return SubstituteAutoTransform(*this, TypeToReplaceAuto)
+ .TransformType(TypeWithAuto);
}
-TypeSourceInfo* Sema::SubstAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto,
+TypeSourceInfo* Sema::SubstAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto,
QualType TypeToReplaceAuto) {
- return SubstituteAutoTransform(*this, TypeToReplaceAuto).
- TransformType(TypeWithAuto);
+ if (TypeToReplaceAuto->isDependentType())
+ TypeToReplaceAuto = QualType();
+ return SubstituteAutoTransform(*this, TypeToReplaceAuto)
+ .TransformType(TypeWithAuto);
}
void Sema::DiagnoseAutoDeductionFailure(VarDecl *VDecl, Expr *Init) {
@@ -4284,6 +4359,10 @@ static bool isAtLeastAsSpecializedAs(Sema &S,
if (Deduced[ArgIdx].isNull())
break;
+ // FIXME: We fail to implement [temp.deduct.type]p1 along this path. We need
+ // to substitute the deduced arguments back into the template and check that
+ // we get the right type.
+
if (ArgIdx == NumArgs) {
// All template arguments were deduced. FT1 is at least as specialized
// as FT2.
@@ -4487,12 +4566,12 @@ UnresolvedSetIterator Sema::getMostSpecialized(
// FIXME: Can we order the candidates in some sane way?
for (UnresolvedSetIterator I = SpecBegin; I != SpecEnd; ++I) {
PartialDiagnostic PD = CandidateDiag;
- PD << getTemplateArgumentBindingsText(
- cast<FunctionDecl>(*I)->getPrimaryTemplate()->getTemplateParameters(),
- *cast<FunctionDecl>(*I)->getTemplateSpecializationArgs());
+ const auto *FD = cast<FunctionDecl>(*I);
+ PD << FD << getTemplateArgumentBindingsText(
+ FD->getPrimaryTemplate()->getTemplateParameters(),
+ *FD->getTemplateSpecializationArgs());
if (!TargetType.isNull())
- HandleFunctionTypeMismatch(PD, cast<FunctionDecl>(*I)->getType(),
- TargetType);
+ HandleFunctionTypeMismatch(PD, FD->getType(), TargetType);
Diag((*I)->getLocation(), PD);
}
}
@@ -4500,21 +4579,17 @@ UnresolvedSetIterator Sema::getMostSpecialized(
return SpecEnd;
}
-/// \brief Returns the more specialized class template partial specialization
-/// according to the rules of partial ordering of class template partial
-/// specializations (C++ [temp.class.order]).
-///
-/// \param PS1 the first class template partial specialization
+/// Determine whether one partial specialization, P1, is at least as
+/// specialized than another, P2.
///
-/// \param PS2 the second class template partial specialization
-///
-/// \returns the more specialized class template partial specialization. If
-/// neither partial specialization is more specialized, returns NULL.
-ClassTemplatePartialSpecializationDecl *
-Sema::getMoreSpecializedPartialSpecialization(
- ClassTemplatePartialSpecializationDecl *PS1,
- ClassTemplatePartialSpecializationDecl *PS2,
- SourceLocation Loc) {
+/// \tparam TemplateLikeDecl The kind of P2, which must be a
+/// TemplateDecl or {Class,Var}TemplatePartialSpecializationDecl.
+/// \param T1 The injected-class-name of P1 (faked for a variable template).
+/// \param T2 The injected-class-name of P2 (faked for a variable template).
+template<typename TemplateLikeDecl>
+static bool isAtLeastAsSpecializedAs(Sema &S, QualType T1, QualType T2,
+ TemplateLikeDecl *P2,
+ TemplateDeductionInfo &Info) {
// C++ [temp.class.order]p1:
// For two class template partial specializations, the first is at least as
// specialized as the second if, given the following rewrite to two
@@ -4540,37 +4615,50 @@ Sema::getMoreSpecializedPartialSpecialization(
// template partial specialization's template arguments, for
// example.
SmallVector<DeducedTemplateArgument, 4> Deduced;
- TemplateDeductionInfo Info(Loc);
+ // Determine whether P1 is at least as specialized as P2.
+ Deduced.resize(P2->getTemplateParameters()->size());
+ if (DeduceTemplateArgumentsByTypeMatch(S, P2->getTemplateParameters(),
+ T2, T1, Info, Deduced, TDF_None,
+ /*PartialOrdering=*/true))
+ return false;
+
+ SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(),
+ Deduced.end());
+ Sema::InstantiatingTemplate Inst(S, Info.getLocation(), P2, DeducedArgs,
+ Info);
+ auto *TST1 = T1->castAs<TemplateSpecializationType>();
+ if (FinishTemplateArgumentDeduction(
+ S, P2, /*PartialOrdering=*/true,
+ TemplateArgumentList(TemplateArgumentList::OnStack,
+ TST1->template_arguments()),
+ Deduced, Info))
+ return false;
+
+ return true;
+}
+
+/// \brief Returns the more specialized class template partial specialization
+/// according to the rules of partial ordering of class template partial
+/// specializations (C++ [temp.class.order]).
+///
+/// \param PS1 the first class template partial specialization
+///
+/// \param PS2 the second class template partial specialization
+///
+/// \returns the more specialized class template partial specialization. If
+/// neither partial specialization is more specialized, returns NULL.
+ClassTemplatePartialSpecializationDecl *
+Sema::getMoreSpecializedPartialSpecialization(
+ ClassTemplatePartialSpecializationDecl *PS1,
+ ClassTemplatePartialSpecializationDecl *PS2,
+ SourceLocation Loc) {
QualType PT1 = PS1->getInjectedSpecializationType();
QualType PT2 = PS2->getInjectedSpecializationType();
- // Determine whether PS1 is at least as specialized as PS2
- Deduced.resize(PS2->getTemplateParameters()->size());
- bool Better1 = !DeduceTemplateArgumentsByTypeMatch(*this,
- PS2->getTemplateParameters(),
- PT2, PT1, Info, Deduced, TDF_None,
- /*PartialOrdering=*/true);
- if (Better1) {
- SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(),Deduced.end());
- InstantiatingTemplate Inst(*this, Loc, PS2, DeducedArgs, Info);
- Better1 = !::FinishTemplateArgumentDeduction(
- *this, PS2, PS1->getTemplateArgs(), Deduced, Info);
- }
-
- // Determine whether PS2 is at least as specialized as PS1
- Deduced.clear();
- Deduced.resize(PS1->getTemplateParameters()->size());
- bool Better2 = !DeduceTemplateArgumentsByTypeMatch(
- *this, PS1->getTemplateParameters(), PT1, PT2, Info, Deduced, TDF_None,
- /*PartialOrdering=*/true);
- if (Better2) {
- SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(),
- Deduced.end());
- InstantiatingTemplate Inst(*this, Loc, PS1, DeducedArgs, Info);
- Better2 = !::FinishTemplateArgumentDeduction(
- *this, PS1, PS2->getTemplateArgs(), Deduced, Info);
- }
+ TemplateDeductionInfo Info(Loc);
+ bool Better1 = isAtLeastAsSpecializedAs(*this, PT1, PT2, PS2, Info);
+ bool Better2 = isAtLeastAsSpecializedAs(*this, PT2, PT1, PS1, Info);
if (Better1 == Better2)
return nullptr;
@@ -4578,18 +4666,26 @@ Sema::getMoreSpecializedPartialSpecialization(
return Better1 ? PS1 : PS2;
}
-/// TODO: Unify with ClassTemplatePartialSpecializationDecl version?
-/// May require unifying ClassTemplate(Partial)SpecializationDecl and
-/// VarTemplate(Partial)SpecializationDecl with a new data
-/// structure Template(Partial)SpecializationDecl, and
-/// using Template(Partial)SpecializationDecl as input type.
+bool Sema::isMoreSpecializedThanPrimary(
+ ClassTemplatePartialSpecializationDecl *Spec, TemplateDeductionInfo &Info) {
+ ClassTemplateDecl *Primary = Spec->getSpecializedTemplate();
+ QualType PrimaryT = Primary->getInjectedClassNameSpecialization();
+ QualType PartialT = Spec->getInjectedSpecializationType();
+ if (!isAtLeastAsSpecializedAs(*this, PartialT, PrimaryT, Primary, Info))
+ return false;
+ if (isAtLeastAsSpecializedAs(*this, PrimaryT, PartialT, Spec, Info)) {
+ Info.clearSFINAEDiagnostic();
+ return false;
+ }
+ return true;
+}
+
VarTemplatePartialSpecializationDecl *
Sema::getMoreSpecializedPartialSpecialization(
VarTemplatePartialSpecializationDecl *PS1,
VarTemplatePartialSpecializationDecl *PS2, SourceLocation Loc) {
- SmallVector<DeducedTemplateArgument, 4> Deduced;
- TemplateDeductionInfo Info(Loc);
-
+ // Pretend the variable template specializations are class template
+ // specializations and form a fake injected class name type for comparison.
assert(PS1->getSpecializedTemplate() == PS2->getSpecializedTemplate() &&
"the partial specializations being compared should specialize"
" the same template.");
@@ -4600,39 +4696,101 @@ Sema::getMoreSpecializedPartialSpecialization(
QualType PT2 = Context.getTemplateSpecializationType(
CanonTemplate, PS2->getTemplateArgs().asArray());
- // Determine whether PS1 is at least as specialized as PS2
- Deduced.resize(PS2->getTemplateParameters()->size());
- bool Better1 = !DeduceTemplateArgumentsByTypeMatch(
- *this, PS2->getTemplateParameters(), PT2, PT1, Info, Deduced, TDF_None,
- /*PartialOrdering=*/true);
- if (Better1) {
- SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(),
- Deduced.end());
- InstantiatingTemplate Inst(*this, Loc, PS2, DeducedArgs, Info);
- Better1 = !::FinishTemplateArgumentDeduction(*this, PS2,
- PS1->getTemplateArgs(),
- Deduced, Info);
+ TemplateDeductionInfo Info(Loc);
+ bool Better1 = isAtLeastAsSpecializedAs(*this, PT1, PT2, PS2, Info);
+ bool Better2 = isAtLeastAsSpecializedAs(*this, PT2, PT1, PS1, Info);
+
+ if (Better1 == Better2)
+ return nullptr;
+
+ return Better1 ? PS1 : PS2;
+}
+
+bool Sema::isMoreSpecializedThanPrimary(
+ VarTemplatePartialSpecializationDecl *Spec, TemplateDeductionInfo &Info) {
+ TemplateDecl *Primary = Spec->getSpecializedTemplate();
+ // FIXME: Cache the injected template arguments rather than recomputing
+ // them for each partial specialization.
+ SmallVector<TemplateArgument, 8> PrimaryArgs;
+ Context.getInjectedTemplateArgs(Primary->getTemplateParameters(),
+ PrimaryArgs);
+
+ TemplateName CanonTemplate =
+ Context.getCanonicalTemplateName(TemplateName(Primary));
+ QualType PrimaryT = Context.getTemplateSpecializationType(
+ CanonTemplate, PrimaryArgs);
+ QualType PartialT = Context.getTemplateSpecializationType(
+ CanonTemplate, Spec->getTemplateArgs().asArray());
+ if (!isAtLeastAsSpecializedAs(*this, PartialT, PrimaryT, Primary, Info))
+ return false;
+ if (isAtLeastAsSpecializedAs(*this, PrimaryT, PartialT, Spec, Info)) {
+ Info.clearSFINAEDiagnostic();
+ return false;
}
+ return true;
+}
- // Determine whether PS2 is at least as specialized as PS1
- Deduced.clear();
- Deduced.resize(PS1->getTemplateParameters()->size());
- bool Better2 = !DeduceTemplateArgumentsByTypeMatch(*this,
- PS1->getTemplateParameters(),
- PT1, PT2, Info, Deduced, TDF_None,
- /*PartialOrdering=*/true);
- if (Better2) {
- SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(),Deduced.end());
- InstantiatingTemplate Inst(*this, Loc, PS1, DeducedArgs, Info);
- Better2 = !::FinishTemplateArgumentDeduction(*this, PS1,
- PS2->getTemplateArgs(),
- Deduced, Info);
+bool Sema::isTemplateTemplateParameterAtLeastAsSpecializedAs(
+ TemplateParameterList *P, TemplateDecl *AArg, SourceLocation Loc) {
+ // C++1z [temp.arg.template]p4: (DR 150)
+ // A template template-parameter P is at least as specialized as a
+ // template template-argument A if, given the following rewrite to two
+ // function templates...
+
+ // Rather than synthesize function templates, we merely perform the
+ // equivalent partial ordering by performing deduction directly on
+ // the template parameter lists of the template template parameters.
+ //
+ // Given an invented class template X with the template parameter list of
+ // A (including default arguments):
+ TemplateName X = Context.getCanonicalTemplateName(TemplateName(AArg));
+ TemplateParameterList *A = AArg->getTemplateParameters();
+
+ // - Each function template has a single function parameter whose type is
+ // a specialization of X with template arguments corresponding to the
+ // template parameters from the respective function template
+ SmallVector<TemplateArgument, 8> AArgs;
+ Context.getInjectedTemplateArgs(A, AArgs);
+
+ // Check P's arguments against A's parameter list. This will fill in default
+ // template arguments as needed. AArgs are already correct by construction.
+ // We can't just use CheckTemplateIdType because that will expand alias
+ // templates.
+ SmallVector<TemplateArgument, 4> PArgs;
+ {
+ SFINAETrap Trap(*this);
+
+ Context.getInjectedTemplateArgs(P, PArgs);
+ TemplateArgumentListInfo PArgList(P->getLAngleLoc(), P->getRAngleLoc());
+ for (unsigned I = 0, N = P->size(); I != N; ++I) {
+ // Unwrap packs that getInjectedTemplateArgs wrapped around pack
+ // expansions, to form an "as written" argument list.
+ TemplateArgument Arg = PArgs[I];
+ if (Arg.getKind() == TemplateArgument::Pack) {
+ assert(Arg.pack_size() == 1 && Arg.pack_begin()->isPackExpansion());
+ Arg = *Arg.pack_begin();
+ }
+ PArgList.addArgument(getTrivialTemplateArgumentLoc(
+ Arg, QualType(), P->getParam(I)->getLocation()));
+ }
+ PArgs.clear();
+
+ // C++1z [temp.arg.template]p3:
+ // If the rewrite produces an invalid type, then P is not at least as
+ // specialized as A.
+ if (CheckTemplateArgumentList(AArg, Loc, PArgList, false, PArgs) ||
+ Trap.hasErrorOccurred())
+ return false;
}
- if (Better1 == Better2)
- return nullptr;
+ QualType AType = Context.getTemplateSpecializationType(X, AArgs);
+ QualType PType = Context.getTemplateSpecializationType(X, PArgs);
- return Better1? PS1 : PS2;
+ // ... the function template corresponding to P is at least as specialized
+ // as the function template corresponding to A according to the partial
+ // ordering rules for function templates.
+ TemplateDeductionInfo Info(Loc, A->getDepth());
+ return isAtLeastAsSpecializedAs(*this, PType, AType, AArg, Info);
}
static void
@@ -4679,6 +4837,11 @@ MarkUsedTemplateParameters(ASTContext &Ctx,
if (NTTP->getDepth() == Depth)
Used[NTTP->getIndex()] = true;
+
+ // In C++1z mode, additional arguments may be deduced from the type of a
+ // non-type argument.
+ if (Ctx.getLangOpts().CPlusPlus1z)
+ MarkUsedTemplateParameters(Ctx, NTTP->getType(), OnlyDeduced, Depth, Used);
}
/// \brief Mark the template parameters that are used by the given
@@ -4846,7 +5009,7 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
// not the last template argument, the entire template argument list is a
// non-deduced context.
if (OnlyDeduced &&
- hasPackExpansionBeforeEnd(Spec->getArgs(), Spec->getNumArgs()))
+ hasPackExpansionBeforeEnd(Spec->template_arguments()))
break;
for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I)
@@ -4925,7 +5088,7 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
case Type::UnaryTransform:
if (!OnlyDeduced)
MarkUsedTemplateParameters(Ctx,
- cast<UnaryTransformType>(T)->getUnderlyingType(),
+ cast<UnaryTransformType>(T)->getUnderlyingType(),
OnlyDeduced, Depth, Used);
break;
@@ -5021,7 +5184,7 @@ Sema::MarkUsedTemplateParameters(const TemplateArgumentList &TemplateArgs,
// the last template argument, the entire template argument list is a
// non-deduced context.
if (OnlyDeduced &&
- hasPackExpansionBeforeEnd(TemplateArgs.data(), TemplateArgs.size()))
+ hasPackExpansionBeforeEnd(TemplateArgs.asArray()))
return;
for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
@@ -5054,7 +5217,7 @@ bool hasDeducibleTemplateParameters(Sema &S,
TemplateParameterList *TemplateParams
= FunctionTemplate->getTemplateParameters();
llvm::SmallBitVector Deduced(TemplateParams->size());
- ::MarkUsedTemplateParameters(S.Context, T, true, TemplateParams->getDepth(),
+ ::MarkUsedTemplateParameters(S.Context, T, true, TemplateParams->getDepth(),
Deduced);
return Deduced.any();
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 65a5633bf0d5..160c9f090788 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -15,6 +15,7 @@
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTLambda.h"
+#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
#include "clang/Basic/LangOptions.h"
@@ -208,9 +209,11 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(
sema::TemplateDeductionInfo *DeductionInfo)
: SemaRef(SemaRef), SavedInNonInstantiationSFINAEContext(
SemaRef.InNonInstantiationSFINAEContext) {
- // Don't allow further instantiation if a fatal error has occcured. Any
- // diagnostics we might have raised will not be visible.
- if (SemaRef.Diags.hasFatalErrorOccurred()) {
+ // Don't allow further instantiation if a fatal error and an uncompilable
+ // error have occurred. Any diagnostics we might have raised will not be
+ // visible, and we do not need to construct a correct AST.
+ if (SemaRef.Diags.hasFatalErrorOccurred() &&
+ SemaRef.Diags.hasUncompilableErrorOccurred()) {
Invalid = true;
return;
}
@@ -276,6 +279,17 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(
Sema::InstantiatingTemplate::InstantiatingTemplate(
Sema &SemaRef, SourceLocation PointOfInstantiation,
+ TemplateDecl *Template,
+ ArrayRef<TemplateArgument> TemplateArgs,
+ sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange)
+ : InstantiatingTemplate(
+ SemaRef,
+ ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution,
+ PointOfInstantiation, InstantiationRange, Template, nullptr,
+ TemplateArgs, &DeductionInfo) {}
+
+Sema::InstantiatingTemplate::InstantiatingTemplate(
+ Sema &SemaRef, SourceLocation PointOfInstantiation,
ClassTemplatePartialSpecializationDecl *PartialSpec,
ArrayRef<TemplateArgument> TemplateArgs,
sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange)
@@ -420,8 +434,7 @@ void Sema::PrintInstantiationStack() {
if (isa<ClassTemplateSpecializationDecl>(Record))
DiagID = diag::note_template_class_instantiation_here;
Diags.Report(Active->PointOfInstantiation, DiagID)
- << Context.getTypeDeclType(Record)
- << Active->InstantiationRange;
+ << Record << Active->InstantiationRange;
} else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
unsigned DiagID;
if (Function->getPrimaryTemplate())
@@ -482,29 +495,43 @@ void Sema::PrintInstantiationStack() {
break;
}
- case ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution:
- if (ClassTemplatePartialSpecializationDecl *PartialSpec =
- dyn_cast<ClassTemplatePartialSpecializationDecl>(Active->Entity)) {
+ case ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution: {
+ if (FunctionTemplateDecl *FnTmpl =
+ dyn_cast<FunctionTemplateDecl>(Active->Entity)) {
Diags.Report(Active->PointOfInstantiation,
- diag::note_partial_spec_deduct_instantiation_here)
- << Context.getTypeDeclType(PartialSpec)
- << getTemplateArgumentBindingsText(
- PartialSpec->getTemplateParameters(),
+ diag::note_function_template_deduction_instantiation_here)
+ << FnTmpl
+ << getTemplateArgumentBindingsText(FnTmpl->getTemplateParameters(),
Active->TemplateArgs,
Active->NumTemplateArgs)
<< Active->InstantiationRange;
} else {
- FunctionTemplateDecl *FnTmpl
- = cast<FunctionTemplateDecl>(Active->Entity);
+ bool IsVar = isa<VarTemplateDecl>(Active->Entity) ||
+ isa<VarTemplateSpecializationDecl>(Active->Entity);
+ bool IsTemplate = false;
+ TemplateParameterList *Params;
+ if (auto *D = dyn_cast<TemplateDecl>(Active->Entity)) {
+ IsTemplate = true;
+ Params = D->getTemplateParameters();
+ } else if (auto *D = dyn_cast<ClassTemplatePartialSpecializationDecl>(
+ Active->Entity)) {
+ Params = D->getTemplateParameters();
+ } else if (auto *D = dyn_cast<VarTemplatePartialSpecializationDecl>(
+ Active->Entity)) {
+ Params = D->getTemplateParameters();
+ } else {
+ llvm_unreachable("unexpected template kind");
+ }
+
Diags.Report(Active->PointOfInstantiation,
- diag::note_function_template_deduction_instantiation_here)
- << FnTmpl
- << getTemplateArgumentBindingsText(FnTmpl->getTemplateParameters(),
- Active->TemplateArgs,
+ diag::note_deduced_template_arg_substitution_here)
+ << IsVar << IsTemplate << cast<NamedDecl>(Active->Entity)
+ << getTemplateArgumentBindingsText(Params, Active->TemplateArgs,
Active->NumTemplateArgs)
<< Active->InstantiationRange;
}
break;
+ }
case ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation: {
ParmVarDecl *Param = cast<ParmVarDecl>(Active->Entity);
@@ -1178,8 +1205,8 @@ ExprResult TemplateInstantiator::transformNonTypeTemplateParmRef(
cast<PackExpansionType>(parm->getType())->getPattern(),
TemplateArgs, loc, parm->getDeclName());
} else {
- type = SemaRef.SubstType(parm->getType(), TemplateArgs,
- loc, parm->getDeclName());
+ type = SemaRef.SubstType(VD ? arg.getParamTypeForDecl() : arg.getNullPtrType(),
+ TemplateArgs, loc, parm->getDeclName());
}
assert(!type.isNull() && "type substitution failed for param type");
assert(!type->isDependentType() && "param type still dependent");
@@ -1684,7 +1711,7 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
// Instantiate default arguments for methods of local classes (DR1484)
// and non-defining declarations.
Sema::ContextRAII SavedContext(*this, OwningFunc);
- LocalInstantiationScope Local(*this);
+ LocalInstantiationScope Local(*this, true);
ExprResult NewArg = SubstExpr(Arg, TemplateArgs);
if (NewArg.isUsable()) {
// It would be nice if we still had this.
@@ -1858,62 +1885,6 @@ namespace clang {
}
}
-/// Determine whether we would be unable to instantiate this template (because
-/// it either has no definition, or is in the process of being instantiated).
-static bool DiagnoseUninstantiableTemplate(Sema &S,
- SourceLocation PointOfInstantiation,
- TagDecl *Instantiation,
- bool InstantiatedFromMember,
- TagDecl *Pattern,
- TagDecl *PatternDef,
- TemplateSpecializationKind TSK,
- bool Complain = true) {
- if (PatternDef && !PatternDef->isBeingDefined()) {
- NamedDecl *SuggestedDef = nullptr;
- if (!S.hasVisibleDefinition(PatternDef, &SuggestedDef,
- /*OnlyNeedComplete*/false)) {
- // If we're allowed to diagnose this and recover, do so.
- bool Recover = Complain && !S.isSFINAEContext();
- if (Complain)
- S.diagnoseMissingImport(PointOfInstantiation, SuggestedDef,
- Sema::MissingImportKind::Definition, Recover);
- return !Recover;
- }
- return false;
- }
-
- if (!Complain || (PatternDef && PatternDef->isInvalidDecl())) {
- // Say nothing
- } else if (PatternDef) {
- assert(PatternDef->isBeingDefined());
- S.Diag(PointOfInstantiation,
- diag::err_template_instantiate_within_definition)
- << (TSK != TSK_ImplicitInstantiation)
- << S.Context.getTypeDeclType(Instantiation);
- // Not much point in noting the template declaration here, since
- // we're lexically inside it.
- Instantiation->setInvalidDecl();
- } else if (InstantiatedFromMember) {
- S.Diag(PointOfInstantiation,
- diag::err_implicit_instantiate_member_undefined)
- << S.Context.getTypeDeclType(Instantiation);
- S.Diag(Pattern->getLocation(), diag::note_member_declared_at);
- } else {
- S.Diag(PointOfInstantiation, diag::err_template_instantiate_undefined)
- << (TSK != TSK_ImplicitInstantiation)
- << S.Context.getTypeDeclType(Instantiation);
- S.Diag(Pattern->getLocation(), diag::note_template_decl_here);
- }
-
- // In general, Instantiation isn't marked invalid to get more than one
- // error for multiple undefined instantiations. But the code that does
- // explicit declaration -> explicit definition conversion can't handle
- // invalid declarations, so mark as invalid in that case.
- if (TSK == TSK_ExplicitInstantiationDeclaration)
- Instantiation->setInvalidDecl();
- return true;
-}
-
/// \brief Instantiate the definition of a class from a given pattern.
///
/// \param PointOfInstantiation The point of instantiation within the
@@ -1944,7 +1915,7 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
bool Complain) {
CXXRecordDecl *PatternDef
= cast_or_null<CXXRecordDecl>(Pattern->getDefinition());
- if (DiagnoseUninstantiableTemplate(*this, PointOfInstantiation, Instantiation,
+ if (DiagnoseUninstantiableTemplate(PointOfInstantiation, Instantiation,
Instantiation->getInstantiatedFromMemberClass(),
Pattern, PatternDef, TSK, Complain))
return true;
@@ -2174,7 +2145,7 @@ bool Sema::InstantiateEnum(SourceLocation PointOfInstantiation,
const MultiLevelTemplateArgumentList &TemplateArgs,
TemplateSpecializationKind TSK) {
EnumDecl *PatternDef = Pattern->getDefinition();
- if (DiagnoseUninstantiableTemplate(*this, PointOfInstantiation, Instantiation,
+ if (DiagnoseUninstantiableTemplate(PointOfInstantiation, Instantiation,
Instantiation->getInstantiatedFromMemberEnum(),
Pattern, PatternDef, TSK,/*Complain*/true))
return true;
@@ -2251,14 +2222,10 @@ bool Sema::InstantiateInClassInitializer(
if (!OldInit) {
RecordDecl *PatternRD = Pattern->getParent();
RecordDecl *OutermostClass = PatternRD->getOuterLexicalRecordContext();
- if (OutermostClass == PatternRD) {
- Diag(Pattern->getLocEnd(), diag::err_in_class_initializer_not_yet_parsed)
- << PatternRD << Pattern;
- } else {
- Diag(Pattern->getLocEnd(),
- diag::err_in_class_initializer_not_yet_parsed_outer_class)
- << PatternRD << OutermostClass << Pattern;
- }
+ Diag(PointOfInstantiation,
+ diag::err_in_class_initializer_not_yet_parsed)
+ << OutermostClass << Pattern;
+ Diag(Pattern->getLocEnd(), diag::note_in_class_initializer_not_yet_parsed);
Instantiation->setInvalidDecl();
return true;
}
@@ -2294,6 +2261,9 @@ bool Sema::InstantiateInClassInitializer(
ActOnFinishCXXInClassMemberInitializer(
Instantiation, Init ? Init->getLocStart() : SourceLocation(), Init);
+ if (auto *L = getASTMutationListener())
+ L->DefaultMemberInitializerInstantiated(Instantiation);
+
// Exit the scope of this instantiation.
SavedContext.pop();
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index dd3748fb5337..7328dcb8760f 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -19,6 +19,7 @@
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.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"
@@ -178,7 +179,7 @@ static void instantiateDependentEnableIfAttr(
return;
Cond = Result.getAs<Expr>();
}
- if (A->getCond()->isTypeDependent() && !Cond->isTypeDependent()) {
+ if (!Cond->isTypeDependent()) {
ExprResult Converted = S.PerformContextuallyConvertToBool(Cond);
if (Converted.isInvalid())
return;
@@ -187,7 +188,7 @@ static void instantiateDependentEnableIfAttr(
SmallVector<PartialDiagnosticAt, 8> Diags;
if (A->getCond()->isValueDependent() && !Cond->isValueDependent() &&
- !Expr::isPotentialConstantExprUnevaluated(Cond, cast<FunctionDecl>(Tmpl),
+ !Expr::isPotentialConstantExprUnevaluated(Cond, cast<FunctionDecl>(New),
Diags)) {
S.Diag(A->getLocation(), diag::err_enable_if_never_constant_expr);
for (int I = 0, N = Diags.size(); I != N; ++I)
@@ -331,8 +332,7 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
continue;
}
- const EnableIfAttr *EnableIf = dyn_cast<EnableIfAttr>(TmplAttr);
- if (EnableIf && EnableIf->getCond()->isValueDependent()) {
+ if (const auto *EnableIf = dyn_cast<EnableIfAttr>(TmplAttr)) {
instantiateDependentEnableIfAttr(*this, TemplateArgs, EnableIf, Tmpl,
New);
continue;
@@ -598,12 +598,37 @@ TemplateDeclInstantiator::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) {
return Inst;
}
+Decl *TemplateDeclInstantiator::VisitBindingDecl(BindingDecl *D) {
+ auto *NewBD = BindingDecl::Create(SemaRef.Context, Owner, D->getLocation(),
+ D->getIdentifier());
+ SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, NewBD);
+ return NewBD;
+}
+
+Decl *TemplateDeclInstantiator::VisitDecompositionDecl(DecompositionDecl *D) {
+ // Transform the bindings first.
+ SmallVector<BindingDecl*, 16> NewBindings;
+ for (auto *OldBD : D->bindings())
+ NewBindings.push_back(cast<BindingDecl>(VisitBindingDecl(OldBD)));
+ ArrayRef<BindingDecl*> NewBindingArray = NewBindings;
+
+ auto *NewDD = cast_or_null<DecompositionDecl>(
+ VisitVarDecl(D, /*InstantiatingVarTemplate=*/false, &NewBindingArray));
+
+ if (!NewDD || NewDD->isInvalidDecl())
+ for (auto *NewBD : NewBindings)
+ NewBD->setInvalidDecl();
+
+ return NewDD;
+}
+
Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
return VisitVarDecl(D, /*InstantiatingVarTemplate=*/false);
}
Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D,
- bool InstantiatingVarTemplate) {
+ bool InstantiatingVarTemplate,
+ ArrayRef<BindingDecl*> *Bindings) {
// Do substitution on the type of the declaration
TypeSourceInfo *DI = SemaRef.SubstType(D->getTypeSourceInfo(),
@@ -624,9 +649,15 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D,
SemaRef.adjustContextForLocalExternDecl(DC);
// Build the instantiated declaration.
- VarDecl *Var = VarDecl::Create(SemaRef.Context, DC, D->getInnerLocStart(),
- D->getLocation(), D->getIdentifier(),
- DI->getType(), DI, D->getStorageClass());
+ VarDecl *Var;
+ if (Bindings)
+ Var = DecompositionDecl::Create(SemaRef.Context, DC, D->getInnerLocStart(),
+ D->getLocation(), DI->getType(), DI,
+ D->getStorageClass(), *Bindings);
+ else
+ Var = VarDecl::Create(SemaRef.Context, DC, D->getInnerLocStart(),
+ D->getLocation(), D->getIdentifier(), DI->getType(),
+ DI, D->getStorageClass());
// In ARC, infer 'retaining' for variables of retainable type.
if (SemaRef.getLangOpts().ObjCAutoRefCount &&
@@ -1840,11 +1871,13 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
Constructor->isExplicit(),
Constructor->isInlineSpecified(),
false, Constructor->isConstexpr());
+ Method->setRangeEnd(Constructor->getLocEnd());
} else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(D)) {
Method = CXXDestructorDecl::Create(SemaRef.Context, Record,
StartLoc, NameInfo, T, TInfo,
Destructor->isInlineSpecified(),
false);
+ Method->setRangeEnd(Destructor->getLocEnd());
} else if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(D)) {
Method = CXXConversionDecl::Create(SemaRef.Context, Record,
StartLoc, NameInfo, T, TInfo,
@@ -2052,18 +2085,18 @@ Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl(
ExpandedParameterPackTypes.reserve(D->getNumExpansionTypes());
ExpandedParameterPackTypesAsWritten.reserve(D->getNumExpansionTypes());
for (unsigned I = 0, N = D->getNumExpansionTypes(); I != N; ++I) {
- TypeSourceInfo *NewDI =SemaRef.SubstType(D->getExpansionTypeSourceInfo(I),
- TemplateArgs,
- D->getLocation(),
- D->getDeclName());
+ TypeSourceInfo *NewDI =
+ SemaRef.SubstType(D->getExpansionTypeSourceInfo(I), TemplateArgs,
+ D->getLocation(), D->getDeclName());
if (!NewDI)
return nullptr;
- ExpandedParameterPackTypesAsWritten.push_back(NewDI);
- QualType NewT =SemaRef.CheckNonTypeTemplateParameterType(NewDI->getType(),
- D->getLocation());
+ QualType NewT =
+ SemaRef.CheckNonTypeTemplateParameterType(NewDI, D->getLocation());
if (NewT.isNull())
return nullptr;
+
+ ExpandedParameterPackTypesAsWritten.push_back(NewDI);
ExpandedParameterPackTypes.push_back(NewT);
}
@@ -2103,12 +2136,12 @@ Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl(
if (!NewDI)
return nullptr;
- ExpandedParameterPackTypesAsWritten.push_back(NewDI);
- QualType NewT = SemaRef.CheckNonTypeTemplateParameterType(
- NewDI->getType(),
- D->getLocation());
+ QualType NewT =
+ SemaRef.CheckNonTypeTemplateParameterType(NewDI, D->getLocation());
if (NewT.isNull())
return nullptr;
+
+ ExpandedParameterPackTypesAsWritten.push_back(NewDI);
ExpandedParameterPackTypes.push_back(NewT);
}
@@ -2128,6 +2161,7 @@ Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl(
if (!NewPattern)
return nullptr;
+ SemaRef.CheckNonTypeTemplateParameterType(NewPattern, D->getLocation());
DI = SemaRef.CheckPackExpansion(NewPattern, Expansion.getEllipsisLoc(),
NumExpansions);
if (!DI)
@@ -2143,8 +2177,7 @@ Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl(
return nullptr;
// Check that this type is acceptable for a non-type template parameter.
- T = SemaRef.CheckNonTypeTemplateParameterType(DI->getType(),
- D->getLocation());
+ T = SemaRef.CheckNonTypeTemplateParameterType(DI, D->getLocation());
if (T.isNull()) {
T = SemaRef.Context.IntTy;
Invalid = true;
@@ -2397,8 +2430,8 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) {
}
if (!NewUD->isInvalidDecl() &&
- SemaRef.CheckUsingDeclQualifier(D->getUsingLoc(), SS, NameInfo,
- D->getLocation()))
+ SemaRef.CheckUsingDeclQualifier(D->getUsingLoc(), D->hasTypename(),
+ SS, NameInfo, D->getLocation()))
NewUD->setInvalidDecl();
SemaRef.Context.setInstantiatedFromUsingDecl(NewUD, D);
@@ -2462,35 +2495,76 @@ Decl *TemplateDeclInstantiator::VisitConstructorUsingShadowDecl(
return nullptr;
}
-Decl * TemplateDeclInstantiator
- ::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) {
- NestedNameSpecifierLoc QualifierLoc
- = SemaRef.SubstNestedNameSpecifierLoc(D->getQualifierLoc(),
- TemplateArgs);
- if (!QualifierLoc)
- return nullptr;
+template <typename T>
+Decl *TemplateDeclInstantiator::instantiateUnresolvedUsingDecl(
+ T *D, bool InstantiatingPackElement) {
+ // If this is a pack expansion, expand it now.
+ if (D->isPackExpansion() && !InstantiatingPackElement) {
+ SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+ SemaRef.collectUnexpandedParameterPacks(D->getQualifierLoc(), Unexpanded);
+ SemaRef.collectUnexpandedParameterPacks(D->getNameInfo(), Unexpanded);
- CXXScopeSpec SS;
- SS.Adopt(QualifierLoc);
+ // Determine whether the set of unexpanded parameter packs can and should
+ // be expanded.
+ bool Expand = true;
+ bool RetainExpansion = false;
+ Optional<unsigned> NumExpansions;
+ if (SemaRef.CheckParameterPacksForExpansion(
+ D->getEllipsisLoc(), D->getSourceRange(), Unexpanded, TemplateArgs,
+ Expand, RetainExpansion, NumExpansions))
+ return nullptr;
- // Since NameInfo refers to a typename, it cannot be a C++ special name.
- // Hence, no transformation is required for it.
- DeclarationNameInfo NameInfo(D->getDeclName(), D->getLocation());
- NamedDecl *UD =
- SemaRef.BuildUsingDeclaration(/*Scope*/ nullptr, D->getAccess(),
- D->getUsingLoc(), SS, NameInfo, nullptr,
- /*instantiation*/ true,
- /*typename*/ true, D->getTypenameLoc());
- if (UD)
- SemaRef.Context.setInstantiatedFromUsingDecl(cast<UsingDecl>(UD), D);
+ // This declaration cannot appear within a function template signature,
+ // so we can't have a partial argument list for a parameter pack.
+ assert(!RetainExpansion &&
+ "should never need to retain an expansion for UsingPackDecl");
- return UD;
-}
+ if (!Expand) {
+ // We cannot fully expand the pack expansion now, so substitute into the
+ // pattern and create a new pack expansion.
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, -1);
+ return instantiateUnresolvedUsingDecl(D, true);
+ }
+
+ // Within a function, we don't have any normal way to check for conflicts
+ // between shadow declarations from different using declarations in the
+ // same pack expansion, but this is always ill-formed because all expansions
+ // must produce (conflicting) enumerators.
+ //
+ // Sadly we can't just reject this in the template definition because it
+ // could be valid if the pack is empty or has exactly one expansion.
+ if (D->getDeclContext()->isFunctionOrMethod() && *NumExpansions > 1) {
+ SemaRef.Diag(D->getEllipsisLoc(),
+ diag::err_using_decl_redeclaration_expansion);
+ return nullptr;
+ }
+
+ // Instantiate the slices of this pack and build a UsingPackDecl.
+ SmallVector<NamedDecl*, 8> Expansions;
+ for (unsigned I = 0; I != *NumExpansions; ++I) {
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, I);
+ Decl *Slice = instantiateUnresolvedUsingDecl(D, true);
+ if (!Slice)
+ return nullptr;
+ // Note that we can still get unresolved using declarations here, if we
+ // had arguments for all packs but the pattern also contained other
+ // template arguments (this only happens during partial substitution, eg
+ // into the body of a generic lambda in a function template).
+ Expansions.push_back(cast<NamedDecl>(Slice));
+ }
+
+ auto *NewD = SemaRef.BuildUsingPackDecl(D, Expansions);
+ if (isDeclWithinFunction(D))
+ SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, NewD);
+ return NewD;
+ }
+
+ UnresolvedUsingTypenameDecl *TD = dyn_cast<UnresolvedUsingTypenameDecl>(D);
+ SourceLocation TypenameLoc = TD ? TD->getTypenameLoc() : SourceLocation();
-Decl * TemplateDeclInstantiator
- ::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
NestedNameSpecifierLoc QualifierLoc
- = SemaRef.SubstNestedNameSpecifierLoc(D->getQualifierLoc(), TemplateArgs);
+ = SemaRef.SubstNestedNameSpecifierLoc(D->getQualifierLoc(),
+ TemplateArgs);
if (!QualifierLoc)
return nullptr;
@@ -2500,17 +2574,48 @@ Decl * TemplateDeclInstantiator
DeclarationNameInfo NameInfo
= SemaRef.SubstDeclarationNameInfo(D->getNameInfo(), TemplateArgs);
- NamedDecl *UD =
- SemaRef.BuildUsingDeclaration(/*Scope*/ nullptr, D->getAccess(),
- D->getUsingLoc(), SS, NameInfo, nullptr,
- /*instantiation*/ true,
- /*typename*/ false, SourceLocation());
+ // Produce a pack expansion only if we're not instantiating a particular
+ // slice of a pack expansion.
+ bool InstantiatingSlice = D->getEllipsisLoc().isValid() &&
+ SemaRef.ArgumentPackSubstitutionIndex != -1;
+ SourceLocation EllipsisLoc =
+ InstantiatingSlice ? SourceLocation() : D->getEllipsisLoc();
+
+ NamedDecl *UD = SemaRef.BuildUsingDeclaration(
+ /*Scope*/ nullptr, D->getAccess(), D->getUsingLoc(),
+ /*HasTypename*/ TD, TypenameLoc, SS, NameInfo, EllipsisLoc, nullptr,
+ /*IsInstantiation*/ true);
if (UD)
- SemaRef.Context.setInstantiatedFromUsingDecl(cast<UsingDecl>(UD), D);
+ SemaRef.Context.setInstantiatedFromUsingDecl(UD, D);
return UD;
}
+Decl *TemplateDeclInstantiator::VisitUnresolvedUsingTypenameDecl(
+ UnresolvedUsingTypenameDecl *D) {
+ return instantiateUnresolvedUsingDecl(D);
+}
+
+Decl *TemplateDeclInstantiator::VisitUnresolvedUsingValueDecl(
+ UnresolvedUsingValueDecl *D) {
+ return instantiateUnresolvedUsingDecl(D);
+}
+
+Decl *TemplateDeclInstantiator::VisitUsingPackDecl(UsingPackDecl *D) {
+ SmallVector<NamedDecl*, 8> Expansions;
+ for (auto *UD : D->expansions()) {
+ if (auto *NewUD =
+ SemaRef.FindInstantiatedDecl(D->getLocation(), UD, TemplateArgs))
+ Expansions.push_back(cast<NamedDecl>(NewUD));
+ else
+ return nullptr;
+ }
+
+ auto *NewD = SemaRef.BuildUsingPackDecl(D, Expansions);
+ if (isDeclWithinFunction(D))
+ SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, NewD);
+ return NewD;
+}
Decl *TemplateDeclInstantiator::VisitClassScopeFunctionSpecializationDecl(
ClassScopeFunctionSpecializationDecl *Decl) {
@@ -2922,10 +3027,14 @@ TemplateDeclInstantiator::SubstTemplateParams(TemplateParameterList *L) {
if (Invalid)
return nullptr;
+ // Note: we substitute into associated constraints later
+ Expr *const UninstantiatedRequiresClause = L->getRequiresClause();
+
TemplateParameterList *InstL
= TemplateParameterList::Create(SemaRef.Context, L->getTemplateLoc(),
L->getLAngleLoc(), Params,
- L->getRAngleLoc());
+ L->getRAngleLoc(),
+ UninstantiatedRequiresClause);
return InstL;
}
@@ -2977,6 +3086,12 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization(
Converted))
return nullptr;
+ // Check these arguments are valid for a template partial specialization.
+ if (SemaRef.CheckTemplatePartialSpecializationArgs(
+ PartialSpec->getLocation(), ClassTemplate, InstTemplateArgs.size(),
+ Converted))
+ return nullptr;
+
// Figure out where to insert this class template partial specialization
// in the member template's set of class template partial specializations.
void *InsertPos = nullptr;
@@ -3047,6 +3162,9 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization(
InstPartialSpec->setInstantiatedFromMember(PartialSpec);
InstPartialSpec->setTypeAsWritten(WrittenTy);
+ // Check the completed partial specialization.
+ SemaRef.CheckTemplatePartialSpecialization(InstPartialSpec);
+
// Add this partial specialization to the set of class template partial
// specializations.
ClassTemplate->AddPartialSpecialization(InstPartialSpec,
@@ -3099,6 +3217,12 @@ TemplateDeclInstantiator::InstantiateVarTemplatePartialSpecialization(
InstTemplateArgs, false, Converted))
return nullptr;
+ // Check these arguments are valid for a template partial specialization.
+ if (SemaRef.CheckTemplatePartialSpecializationArgs(
+ PartialSpec->getLocation(), VarTemplate, InstTemplateArgs.size(),
+ Converted))
+ return nullptr;
+
// Figure out where to insert this variable template partial specialization
// in the member template's set of variable template partial specializations.
void *InsertPos = nullptr;
@@ -3173,6 +3297,9 @@ TemplateDeclInstantiator::InstantiateVarTemplatePartialSpecialization(
InstPartialSpec->setInstantiatedFromMember(PartialSpec);
InstPartialSpec->setTypeAsWritten(WrittenTy);
+ // Check the completed partial specialization.
+ SemaRef.CheckTemplatePartialSpecialization(InstPartialSpec);
+
// Add this partial specialization to the set of variable template partial
// specializations. The instantiation of the initializer is not necessary.
VarTemplate->AddPartialSpecialization(InstPartialSpec, /*InsertPos=*/nullptr);
@@ -3516,7 +3643,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
// Never instantiate an explicit specialization except if it is a class scope
// explicit specialization.
- if (Function->getTemplateSpecializationKind() == TSK_ExplicitSpecialization &&
+ TemplateSpecializationKind TSK = Function->getTemplateSpecializationKind();
+ if (TSK == TSK_ExplicitSpecialization &&
!Function->getClassScopeSpecializationPattern())
return;
@@ -3524,13 +3652,40 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
const FunctionDecl *PatternDecl = Function->getTemplateInstantiationPattern();
assert(PatternDecl && "instantiating a non-template");
- Stmt *Pattern = PatternDecl->getBody(PatternDecl);
- assert(PatternDecl && "template definition is not a template");
- if (!Pattern) {
- // Try to find a defaulted definition
- PatternDecl->isDefined(PatternDecl);
+ const FunctionDecl *PatternDef = PatternDecl->getDefinition();
+ Stmt *Pattern = nullptr;
+ if (PatternDef) {
+ Pattern = PatternDef->getBody(PatternDef);
+ PatternDecl = PatternDef;
+ }
+
+ // FIXME: We need to track the instantiation stack in order to know which
+ // definitions should be visible within this instantiation.
+ if (DiagnoseUninstantiableTemplate(PointOfInstantiation, Function,
+ Function->getInstantiatedFromMemberFunction(),
+ PatternDecl, PatternDef, TSK,
+ /*Complain*/DefinitionRequired)) {
+ if (DefinitionRequired)
+ Function->setInvalidDecl();
+ else if (TSK == TSK_ExplicitInstantiationDefinition) {
+ // Try again at the end of the translation unit (at which point a
+ // definition will be required).
+ assert(!Recursive);
+ PendingInstantiations.push_back(
+ std::make_pair(Function, PointOfInstantiation));
+ } else if (TSK == TSK_ImplicitInstantiation) {
+ if (AtEndOfTU && !getDiagnostics().hasErrorOccurred()) {
+ Diag(PointOfInstantiation, diag::warn_func_template_missing)
+ << Function;
+ Diag(PatternDecl->getLocation(), diag::note_forward_template_decl);
+ if (getLangOpts().CPlusPlus11)
+ Diag(PointOfInstantiation, diag::note_inst_declaration_hint)
+ << Function;
+ }
+ }
+
+ return;
}
- assert(PatternDecl && "template definition is not a template");
// Postpone late parsed template instantiations.
if (PatternDecl->isLateTemplateParsed() &&
@@ -3558,58 +3713,23 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
if (PatternDecl->isFromASTFile())
ExternalSource->ReadLateParsedTemplates(LateParsedTemplateMap);
- LateParsedTemplate *LPT = LateParsedTemplateMap.lookup(PatternDecl);
- assert(LPT && "missing LateParsedTemplate");
- LateTemplateParser(OpaqueParser, *LPT);
+ auto LPTIter = LateParsedTemplateMap.find(PatternDecl);
+ assert(LPTIter != LateParsedTemplateMap.end() &&
+ "missing LateParsedTemplate");
+ LateTemplateParser(OpaqueParser, *LPTIter->second);
Pattern = PatternDecl->getBody(PatternDecl);
}
- // FIXME: Check that the definition is visible before trying to instantiate
- // it. This requires us to track the instantiation stack in order to know
- // which definitions should be visible.
-
- if (!Pattern && !PatternDecl->isDefaulted()) {
- if (DefinitionRequired) {
- if (Function->getPrimaryTemplate())
- Diag(PointOfInstantiation,
- diag::err_explicit_instantiation_undefined_func_template)
- << Function->getPrimaryTemplate();
- else
- Diag(PointOfInstantiation,
- diag::err_explicit_instantiation_undefined_member)
- << 1 << Function->getDeclName() << Function->getDeclContext();
-
- if (PatternDecl)
- Diag(PatternDecl->getLocation(),
- diag::note_explicit_instantiation_here);
- Function->setInvalidDecl();
- } else if (Function->getTemplateSpecializationKind()
- == TSK_ExplicitInstantiationDefinition) {
- assert(!Recursive);
- PendingInstantiations.push_back(
- std::make_pair(Function, PointOfInstantiation));
- } else if (Function->getTemplateSpecializationKind()
- == TSK_ImplicitInstantiation) {
- if (AtEndOfTU && !getDiagnostics().hasErrorOccurred()) {
- Diag(PointOfInstantiation, diag::warn_func_template_missing)
- << Function;
- Diag(PatternDecl->getLocation(), diag::note_forward_template_decl);
- if (getLangOpts().CPlusPlus11)
- Diag(PointOfInstantiation, diag::note_inst_declaration_hint)
- << Function;
- }
- }
-
- return;
- }
+ // Note, we should never try to instantiate a deleted function template.
+ assert((Pattern || PatternDecl->isDefaulted()) &&
+ "unexpected kind of function template definition");
// C++1y [temp.explicit]p10:
// Except for inline functions, declarations with types deduced from their
// initializer or return value, and class template specializations, other
// explicit instantiation declarations have the effect of suppressing the
// implicit instantiation of the entity to which they refer.
- if (Function->getTemplateSpecializationKind() ==
- TSK_ExplicitInstantiationDeclaration &&
+ if (TSK == TSK_ExplicitInstantiationDeclaration &&
!PatternDecl->isInlined() &&
!PatternDecl->getReturnType()->getContainedAutoType())
return;
@@ -3631,6 +3751,10 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
PrettyDeclStackTraceEntry CrashInfo(*this, Function, SourceLocation(),
"instantiating function definition");
+ // The instantiation is visible here, even if it was first declared in an
+ // unimported module.
+ Function->setHidden(false);
+
// Copy the inner loc start from the pattern.
Function->setInnerLocStart(PatternDecl->getInnerLocStart());
@@ -4035,6 +4159,10 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
PrettyDeclStackTraceEntry CrashInfo(*this, Var, SourceLocation(),
"instantiating variable initializer");
+ // The instantiation is visible here, even if it was first declared in an
+ // unimported module.
+ Var->setHidden(false);
+
// If we're performing recursive template instantiation, create our own
// queue of pending implicit instantiations that we will instantiate
// later, while we're still within our own instantiation context.
@@ -4083,33 +4211,17 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
Def = PatternDecl->getDefinition();
}
- // FIXME: Check that the definition is visible before trying to instantiate
- // it. This requires us to track the instantiation stack in order to know
- // which definitions should be visible.
+ TemplateSpecializationKind TSK = Var->getTemplateSpecializationKind();
// If we don't have a definition of the variable template, we won't perform
// any instantiation. Rather, we rely on the user to instantiate this
// definition (or provide a specialization for it) in another translation
// unit.
- if (!Def) {
- if (DefinitionRequired) {
- if (VarSpec)
- Diag(PointOfInstantiation,
- diag::err_explicit_instantiation_undefined_var_template) << Var;
- else
- Diag(PointOfInstantiation,
- diag::err_explicit_instantiation_undefined_member)
- << 2 << Var->getDeclName() << Var->getDeclContext();
- Diag(PatternDecl->getLocation(),
- diag::note_explicit_instantiation_here);
- if (VarSpec)
- Var->setInvalidDecl();
- } else if (Var->getTemplateSpecializationKind()
- == TSK_ExplicitInstantiationDefinition) {
+ if (!Def && !DefinitionRequired) {
+ if (TSK == TSK_ExplicitInstantiationDefinition) {
PendingInstantiations.push_back(
std::make_pair(Var, PointOfInstantiation));
- } else if (Var->getTemplateSpecializationKind()
- == TSK_ImplicitInstantiation) {
+ } else if (TSK == TSK_ImplicitInstantiation) {
// Warn about missing definition at the end of translation unit.
if (AtEndOfTU && !getDiagnostics().hasErrorOccurred()) {
Diag(PointOfInstantiation, diag::warn_var_template_missing)
@@ -4118,12 +4230,20 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
if (getLangOpts().CPlusPlus11)
Diag(PointOfInstantiation, diag::note_inst_declaration_hint) << Var;
}
+ return;
}
- return;
}
- TemplateSpecializationKind TSK = Var->getTemplateSpecializationKind();
+ // FIXME: We need to track the instantiation stack in order to know which
+ // definitions should be visible within this instantiation.
+ // FIXME: Produce diagnostics when Var->getInstantiatedFromStaticDataMember().
+ if (DiagnoseUninstantiableTemplate(PointOfInstantiation, Var,
+ /*InstantiatedFromMember*/false,
+ PatternDecl, Def, TSK,
+ /*Complain*/DefinitionRequired))
+ return;
+
// Never instantiate an explicit specialization.
if (TSK == TSK_ExplicitSpecialization)
@@ -4483,22 +4603,36 @@ static bool isInstantiationOf(UsingShadowDecl *Pattern,
Pattern);
}
-static bool isInstantiationOf(UsingDecl *Pattern,
- UsingDecl *Instance,
+static bool isInstantiationOf(UsingDecl *Pattern, UsingDecl *Instance,
ASTContext &C) {
return declaresSameEntity(C.getInstantiatedFromUsingDecl(Instance), Pattern);
}
-static bool isInstantiationOf(UnresolvedUsingValueDecl *Pattern,
- UsingDecl *Instance,
- ASTContext &C) {
- return declaresSameEntity(C.getInstantiatedFromUsingDecl(Instance), Pattern);
-}
-
-static bool isInstantiationOf(UnresolvedUsingTypenameDecl *Pattern,
- UsingDecl *Instance,
- ASTContext &C) {
- return declaresSameEntity(C.getInstantiatedFromUsingDecl(Instance), Pattern);
+template<typename T>
+static bool isInstantiationOfUnresolvedUsingDecl(T *Pattern, Decl *Other,
+ ASTContext &Ctx) {
+ // An unresolved using declaration can instantiate to an unresolved using
+ // declaration, or to a using declaration or a using declaration pack.
+ //
+ // Multiple declarations can claim to be instantiated from an unresolved
+ // using declaration if it's a pack expansion. We want the UsingPackDecl
+ // in that case, not the individual UsingDecls within the pack.
+ bool OtherIsPackExpansion;
+ NamedDecl *OtherFrom;
+ if (auto *OtherUUD = dyn_cast<T>(Other)) {
+ OtherIsPackExpansion = OtherUUD->isPackExpansion();
+ OtherFrom = Ctx.getInstantiatedFromUsingDecl(OtherUUD);
+ } else if (auto *OtherUPD = dyn_cast<UsingPackDecl>(Other)) {
+ OtherIsPackExpansion = true;
+ OtherFrom = OtherUPD->getInstantiatedFromUsingDecl();
+ } else if (auto *OtherUD = dyn_cast<UsingDecl>(Other)) {
+ OtherIsPackExpansion = false;
+ OtherFrom = Ctx.getInstantiatedFromUsingDecl(OtherUD);
+ } else {
+ return false;
+ }
+ return Pattern->isPackExpansion() == OtherIsPackExpansion &&
+ declaresSameEntity(OtherFrom, Pattern);
}
static bool isInstantiationOfStaticDataMember(VarDecl *Pattern,
@@ -4519,49 +4653,40 @@ static bool isInstantiationOfStaticDataMember(VarDecl *Pattern,
// Other is the prospective instantiation
// D is the prospective pattern
static bool isInstantiationOf(ASTContext &Ctx, NamedDecl *D, Decl *Other) {
- if (D->getKind() != Other->getKind()) {
- if (UnresolvedUsingTypenameDecl *UUD
- = dyn_cast<UnresolvedUsingTypenameDecl>(D)) {
- if (UsingDecl *UD = dyn_cast<UsingDecl>(Other)) {
- return isInstantiationOf(UUD, UD, Ctx);
- }
- }
+ if (auto *UUD = dyn_cast<UnresolvedUsingTypenameDecl>(D))
+ return isInstantiationOfUnresolvedUsingDecl(UUD, Other, Ctx);
- if (UnresolvedUsingValueDecl *UUD
- = dyn_cast<UnresolvedUsingValueDecl>(D)) {
- if (UsingDecl *UD = dyn_cast<UsingDecl>(Other)) {
- return isInstantiationOf(UUD, UD, Ctx);
- }
- }
+ if (auto *UUD = dyn_cast<UnresolvedUsingValueDecl>(D))
+ return isInstantiationOfUnresolvedUsingDecl(UUD, Other, Ctx);
+ if (D->getKind() != Other->getKind())
return false;
- }
- if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Other))
+ if (auto *Record = dyn_cast<CXXRecordDecl>(Other))
return isInstantiationOf(cast<CXXRecordDecl>(D), Record);
- if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Other))
+ if (auto *Function = dyn_cast<FunctionDecl>(Other))
return isInstantiationOf(cast<FunctionDecl>(D), Function);
- if (EnumDecl *Enum = dyn_cast<EnumDecl>(Other))
+ if (auto *Enum = dyn_cast<EnumDecl>(Other))
return isInstantiationOf(cast<EnumDecl>(D), Enum);
- if (VarDecl *Var = dyn_cast<VarDecl>(Other))
+ if (auto *Var = dyn_cast<VarDecl>(Other))
if (Var->isStaticDataMember())
return isInstantiationOfStaticDataMember(cast<VarDecl>(D), Var);
- if (ClassTemplateDecl *Temp = dyn_cast<ClassTemplateDecl>(Other))
+ if (auto *Temp = dyn_cast<ClassTemplateDecl>(Other))
return isInstantiationOf(cast<ClassTemplateDecl>(D), Temp);
- if (FunctionTemplateDecl *Temp = dyn_cast<FunctionTemplateDecl>(Other))
+ if (auto *Temp = dyn_cast<FunctionTemplateDecl>(Other))
return isInstantiationOf(cast<FunctionTemplateDecl>(D), Temp);
- if (ClassTemplatePartialSpecializationDecl *PartialSpec
- = dyn_cast<ClassTemplatePartialSpecializationDecl>(Other))
+ if (auto *PartialSpec =
+ dyn_cast<ClassTemplatePartialSpecializationDecl>(Other))
return isInstantiationOf(cast<ClassTemplatePartialSpecializationDecl>(D),
PartialSpec);
- if (FieldDecl *Field = dyn_cast<FieldDecl>(Other)) {
+ if (auto *Field = dyn_cast<FieldDecl>(Other)) {
if (!Field->getDeclName()) {
// This is an unnamed field.
return declaresSameEntity(Ctx.getInstantiatedFromUnnamedFieldDecl(Field),
@@ -4569,14 +4694,14 @@ static bool isInstantiationOf(ASTContext &Ctx, NamedDecl *D, Decl *Other) {
}
}
- if (UsingDecl *Using = dyn_cast<UsingDecl>(Other))
+ if (auto *Using = dyn_cast<UsingDecl>(Other))
return isInstantiationOf(cast<UsingDecl>(D), Using, Ctx);
- if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(Other))
+ if (auto *Shadow = dyn_cast<UsingShadowDecl>(Other))
return isInstantiationOf(cast<UsingShadowDecl>(D), Shadow, Ctx);
- return D->getDeclName() && isa<NamedDecl>(Other) &&
- D->getDeclName() == cast<NamedDecl>(Other)->getDeclName();
+ return D->getDeclName() &&
+ D->getDeclName() == cast<NamedDecl>(Other)->getDeclName();
}
template<typename ForwardIterator>
@@ -4812,6 +4937,8 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
}
NamedDecl *Result = nullptr;
+ // FIXME: If the name is a dependent name, this lookup won't necessarily
+ // find it. Does that ever matter?
if (D->getDeclName()) {
DeclContext::lookup_result Found = ParentDC->lookup(D->getDeclName());
Result = findInstantiationOf(Context, D, Found.begin(), Found.end());
diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp
index 06afe87f515e..54556b505ee0 100644
--- a/lib/Sema/SemaTemplateVariadic.cpp
+++ b/lib/Sema/SemaTemplateVariadic.cpp
@@ -390,21 +390,18 @@ void Sema::collectUnexpandedParameterPacks(QualType T,
void Sema::collectUnexpandedParameterPacks(TypeLoc TL,
SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseTypeLoc(TL);
-}
+}
-void Sema::collectUnexpandedParameterPacks(CXXScopeSpec &SS,
- SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
- NestedNameSpecifier *Qualifier = SS.getScopeRep();
- if (!Qualifier)
- return;
-
- NestedNameSpecifierLoc QualifierLoc(Qualifier, SS.location_data());
+void Sema::collectUnexpandedParameterPacks(
+ NestedNameSpecifierLoc NNS,
+ SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
CollectUnexpandedParameterPacksVisitor(Unexpanded)
- .TraverseNestedNameSpecifierLoc(QualifierLoc);
+ .TraverseNestedNameSpecifierLoc(NNS);
}
-void Sema::collectUnexpandedParameterPacks(const DeclarationNameInfo &NameInfo,
- SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
+void Sema::collectUnexpandedParameterPacks(
+ const DeclarationNameInfo &NameInfo,
+ SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
CollectUnexpandedParameterPacksVisitor(Unexpanded)
.TraverseDeclarationNameInfo(NameInfo);
}
@@ -639,7 +636,7 @@ bool Sema::CheckParameterPacksForExpansion(
return true;
}
}
-
+
return false;
}
@@ -772,7 +769,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) {
}
if (Chunk.Fun.getExceptionSpecType() == EST_Dynamic) {
- for (unsigned i = 0; i != Chunk.Fun.NumExceptions; ++i) {
+ for (unsigned i = 0; i != Chunk.Fun.getNumExceptions(); ++i) {
if (Chunk.Fun.Exceptions[i]
.Ty.get()
->containsUnexpandedParameterPack())
@@ -936,12 +933,71 @@ Sema::getTemplateArgumentPackExpansionPattern(
llvm_unreachable("Invalid TemplateArgument Kind!");
}
+Optional<unsigned> Sema::getFullyPackExpandedSize(TemplateArgument Arg) {
+ assert(Arg.containsUnexpandedParameterPack());
+
+ // If this is a substituted pack, grab that pack. If not, we don't know
+ // the size yet.
+ // FIXME: We could find a size in more cases by looking for a substituted
+ // pack anywhere within this argument, but that's not necessary in the common
+ // case for 'sizeof...(A)' handling.
+ TemplateArgument Pack;
+ switch (Arg.getKind()) {
+ case TemplateArgument::Type:
+ if (auto *Subst = Arg.getAsType()->getAs<SubstTemplateTypeParmPackType>())
+ Pack = Subst->getArgumentPack();
+ else
+ return None;
+ break;
+
+ case TemplateArgument::Expression:
+ if (auto *Subst =
+ dyn_cast<SubstNonTypeTemplateParmPackExpr>(Arg.getAsExpr()))
+ Pack = Subst->getArgumentPack();
+ else if (auto *Subst = dyn_cast<FunctionParmPackExpr>(Arg.getAsExpr())) {
+ for (ParmVarDecl *PD : *Subst)
+ if (PD->isParameterPack())
+ return None;
+ return Subst->getNumExpansions();
+ } else
+ return None;
+ break;
+
+ case TemplateArgument::Template:
+ if (SubstTemplateTemplateParmPackStorage *Subst =
+ Arg.getAsTemplate().getAsSubstTemplateTemplateParmPack())
+ Pack = Subst->getArgumentPack();
+ else
+ return None;
+ break;
+
+ case TemplateArgument::Declaration:
+ case TemplateArgument::NullPtr:
+ case TemplateArgument::TemplateExpansion:
+ case TemplateArgument::Integral:
+ case TemplateArgument::Pack:
+ case TemplateArgument::Null:
+ return None;
+ }
+
+ // Check that no argument in the pack is itself a pack expansion.
+ for (TemplateArgument Elem : Pack.pack_elements()) {
+ // There's no point recursing in this case; we would have already
+ // expanded this pack expansion into the enclosing pack if we could.
+ if (Elem.isPackExpansion())
+ return None;
+ }
+ return Pack.pack_size();
+}
+
static void CheckFoldOperand(Sema &S, Expr *E) {
if (!E)
return;
E = E->IgnoreImpCasts();
- if (isa<BinaryOperator>(E) || isa<AbstractConditionalOperator>(E)) {
+ auto *OCE = dyn_cast<CXXOperatorCallExpr>(E);
+ if ((OCE && OCE->isInfixBinaryOp()) || isa<BinaryOperator>(E) ||
+ isa<AbstractConditionalOperator>(E)) {
S.Diag(E->getExprLoc(), diag::err_fold_expression_bad_operand)
<< E->getSourceRange()
<< FixItHint::CreateInsertion(E->getLocStart(), "(")
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index f3747eaa5cb5..ae9a3ee790e1 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -106,6 +106,7 @@ static void diagnoseBadTypeAttribute(Sema &S, const AttributeList &attr,
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: \
@@ -717,6 +718,7 @@ static void maybeSynthesizeBlockSignature(TypeProcessingState &state,
/*NumExceptions=*/0,
/*NoexceptExpr=*/nullptr,
/*ExceptionSpecTokens=*/nullptr,
+ /*DeclsInPrototype=*/None,
loc, loc, declarator));
// For consistency, make sure the state still has us as processing
@@ -1000,55 +1002,27 @@ static QualType applyObjCTypeArgs(Sema &S, SourceLocation loc, QualType type,
return S.Context.getObjCObjectType(type, finalTypeArgs, { }, false);
}
-/// Apply Objective-C protocol qualifiers to the given type.
-static QualType applyObjCProtocolQualifiers(
- Sema &S, SourceLocation loc, SourceRange range, QualType type,
- ArrayRef<ObjCProtocolDecl *> protocols,
- const SourceLocation *protocolLocs,
- bool failOnError = false) {
- ASTContext &ctx = S.Context;
- if (const ObjCObjectType *objT = dyn_cast<ObjCObjectType>(type.getTypePtr())){
- // FIXME: Check for protocols to which the class type is already
- // known to conform.
-
- return ctx.getObjCObjectType(objT->getBaseType(),
- objT->getTypeArgsAsWritten(),
- protocols,
- objT->isKindOfTypeAsWritten());
- }
-
- if (type->isObjCObjectType()) {
- // Silently overwrite any existing protocol qualifiers.
- // TODO: determine whether that's the right thing to do.
-
- // FIXME: Check for protocols to which the class type is already
- // known to conform.
- return ctx.getObjCObjectType(type, { }, protocols, false);
- }
-
- // id<protocol-list>
- if (type->isObjCIdType()) {
- const ObjCObjectPointerType *objPtr = type->castAs<ObjCObjectPointerType>();
- type = ctx.getObjCObjectType(ctx.ObjCBuiltinIdTy, { }, protocols,
- objPtr->isKindOfType());
- return ctx.getObjCObjectPointerType(type);
- }
-
- // Class<protocol-list>
- if (type->isObjCClassType()) {
- const ObjCObjectPointerType *objPtr = type->castAs<ObjCObjectPointerType>();
- type = ctx.getObjCObjectType(ctx.ObjCBuiltinClassTy, { }, protocols,
- objPtr->isKindOfType());
- return ctx.getObjCObjectPointerType(type);
+QualType Sema::BuildObjCTypeParamType(const ObjCTypeParamDecl *Decl,
+ SourceLocation ProtocolLAngleLoc,
+ ArrayRef<ObjCProtocolDecl *> Protocols,
+ ArrayRef<SourceLocation> ProtocolLocs,
+ SourceLocation ProtocolRAngleLoc,
+ bool FailOnError) {
+ QualType Result = QualType(Decl->getTypeForDecl(), 0);
+ if (!Protocols.empty()) {
+ bool HasError;
+ Result = Context.applyObjCProtocolQualifiers(Result, Protocols,
+ HasError);
+ if (HasError) {
+ Diag(SourceLocation(), diag::err_invalid_protocol_qualifiers)
+ << SourceRange(ProtocolLAngleLoc, ProtocolRAngleLoc);
+ if (FailOnError) Result = QualType();
+ }
+ if (FailOnError && Result.isNull())
+ return QualType();
}
- S.Diag(loc, diag::err_invalid_protocol_qualifiers)
- << range;
-
- if (failOnError)
- return QualType();
-
- return type;
+ return Result;
}
QualType Sema::BuildObjCObjectType(QualType BaseType,
@@ -1072,12 +1046,14 @@ QualType Sema::BuildObjCObjectType(QualType BaseType,
}
if (!Protocols.empty()) {
- Result = applyObjCProtocolQualifiers(*this, Loc,
- SourceRange(ProtocolLAngleLoc,
- ProtocolRAngleLoc),
- Result, Protocols,
- ProtocolLocs.data(),
- FailOnError);
+ bool HasError;
+ Result = Context.applyObjCProtocolQualifiers(Result, Protocols,
+ HasError);
+ if (HasError) {
+ Diag(Loc, diag::err_invalid_protocol_qualifiers)
+ << SourceRange(ProtocolLAngleLoc, ProtocolRAngleLoc);
+ if (FailOnError) Result = QualType();
+ }
if (FailOnError && Result.isNull())
return QualType();
}
@@ -1153,7 +1129,7 @@ TypeResult Sema::actOnObjCTypeArgsAndProtocolQualifiers(
ActualTypeArgInfos.clear();
break;
}
-
+
assert(TypeArgInfo && "No type source info?");
ActualTypeArgInfos.push_back(TypeArgInfo);
}
@@ -1170,7 +1146,7 @@ TypeResult Sema::actOnObjCTypeArgsAndProtocolQualifiers(
if (Result == T)
return BaseType;
-
+
// Create source information for this type.
TypeSourceInfo *ResultTInfo = Context.CreateTypeSourceInfo(Result);
TypeLoc ResultTL = ResultTInfo->getTypeLoc();
@@ -1183,6 +1159,20 @@ TypeResult Sema::actOnObjCTypeArgsAndProtocolQualifiers(
ResultTL = ObjCObjectPointerTL.getPointeeLoc();
}
+ if (auto OTPTL = ResultTL.getAs<ObjCTypeParamTypeLoc>()) {
+ // Protocol qualifier information.
+ if (OTPTL.getNumProtocols() > 0) {
+ assert(OTPTL.getNumProtocols() == Protocols.size());
+ OTPTL.setProtocolLAngleLoc(ProtocolLAngleLoc);
+ OTPTL.setProtocolRAngleLoc(ProtocolRAngleLoc);
+ for (unsigned i = 0, n = Protocols.size(); i != n; ++i)
+ OTPTL.setProtocolLoc(i, ProtocolLocs[i]);
+ }
+
+ // We're done. Return the completed type to the parser.
+ return CreateParsedType(Result, ResultTInfo);
+ }
+
auto ObjCObjectTL = ResultTL.castAs<ObjCObjectTypeLoc>();
// Type argument information.
@@ -1220,19 +1210,19 @@ TypeResult Sema::actOnObjCTypeArgsAndProtocolQualifiers(
return CreateParsedType(Result, ResultTInfo);
}
-static StringRef getImageAccessAttrStr(AttributeList *attrs) {
- if (attrs) {
-
- AttributeList *Next;
+static OpenCLAccessAttr::Spelling getImageAccess(const AttributeList *Attrs) {
+ if (Attrs) {
+ const AttributeList *Next = Attrs;
do {
- AttributeList &Attr = *attrs;
+ const AttributeList &Attr = *Next;
Next = Attr.getNext();
if (Attr.getKind() == AttributeList::AT_OpenCLAccess) {
- return Attr.getName()->getName();
+ return static_cast<OpenCLAccessAttr::Spelling>(
+ Attr.getSemanticSpelling());
}
} while (Next);
}
- return "";
+ return OpenCLAccessAttr::Keyword_read_only;
}
/// \brief Convert the specified declspec to the appropriate type
@@ -1411,14 +1401,6 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
Result = Context.LongDoubleTy;
else
Result = Context.DoubleTy;
-
- if (S.getLangOpts().OpenCL &&
- !((S.getLangOpts().OpenCLVersion >= 120) ||
- S.getOpenCLOptions().cl_khr_fp64)) {
- S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_requires_extension)
- << Result << "cl_khr_fp64";
- declarator.setInvalidType(true);
- }
break;
case DeclSpec::TST_float128:
if (!S.Context.getTargetInfo().hasFloat128Type())
@@ -1470,48 +1452,6 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
Result = S.GetTypeFromParser(DS.getRepAsType());
if (Result.isNull()) {
declarator.setInvalidType(true);
- } else if (S.getLangOpts().OpenCL) {
- if (Result->getAs<AtomicType>()) {
- StringRef TypeName = Result.getBaseTypeIdentifier()->getName();
- bool NoExtTypes =
- llvm::StringSwitch<bool>(TypeName)
- .Cases("atomic_int", "atomic_uint", "atomic_float",
- "atomic_flag", true)
- .Default(false);
- if (!S.getOpenCLOptions().cl_khr_int64_base_atomics && !NoExtTypes) {
- S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_requires_extension)
- << Result << "cl_khr_int64_base_atomics";
- declarator.setInvalidType(true);
- }
- if (!S.getOpenCLOptions().cl_khr_int64_extended_atomics &&
- !NoExtTypes) {
- S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_requires_extension)
- << Result << "cl_khr_int64_extended_atomics";
- declarator.setInvalidType(true);
- }
- if (!S.getOpenCLOptions().cl_khr_fp64 &&
- !TypeName.compare("atomic_double")) {
- S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_requires_extension)
- << Result << "cl_khr_fp64";
- declarator.setInvalidType(true);
- }
- } else if (!S.getOpenCLOptions().cl_khr_gl_msaa_sharing &&
- (Result->isOCLImage2dArrayMSAADepthROType() ||
- Result->isOCLImage2dArrayMSAADepthWOType() ||
- Result->isOCLImage2dArrayMSAADepthRWType() ||
- Result->isOCLImage2dArrayMSAAROType() ||
- Result->isOCLImage2dArrayMSAARWType() ||
- Result->isOCLImage2dArrayMSAAWOType() ||
- Result->isOCLImage2dMSAADepthROType() ||
- Result->isOCLImage2dMSAADepthRWType() ||
- Result->isOCLImage2dMSAADepthWOType() ||
- Result->isOCLImage2dMSAAROType() ||
- Result->isOCLImage2dMSAARWType() ||
- Result->isOCLImage2dMSAAWOType())) {
- S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_requires_extension)
- << Result << "cl_khr_gl_msaa_sharing";
- declarator.setInvalidType(true);
- }
}
// TypeQuals handled by caller.
@@ -1623,11 +1563,14 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
#define GENERIC_IMAGE_TYPE(ImgType, Id) \
case DeclSpec::TST_##ImgType##_t: \
- Result = llvm::StringSwitch<QualType>( \
- getImageAccessAttrStr(DS.getAttributes().getList())) \
- .Cases("write_only", "__write_only", Context.Id##WOTy) \
- .Cases("read_write", "__read_write", Context.Id##RWTy) \
- .Default(Context.Id##ROTy); \
+ 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; \
+ } \
break;
#include "clang/Basic/OpenCLImageTypes.def"
@@ -1637,6 +1580,10 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
break;
}
+ if (S.getLangOpts().OpenCL &&
+ S.checkOpenCLDisabledTypeDeclSpec(DS, Result))
+ declarator.setInvalidType(true);
+
// Handle complex types.
if (DS.getTypeSpecComplex() == DeclSpec::TSC_complex) {
if (S.getLangOpts().Freestanding)
@@ -1748,6 +1695,12 @@ QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc,
if (T.isNull())
return QualType();
+ // Ignore any attempt to form a cv-qualified reference.
+ if (T->isReferenceType()) {
+ Qs.removeConst();
+ Qs.removeVolatile();
+ }
+
// Enforce C99 6.7.3p2: "Types other than pointer types derived from
// object or incomplete types shall not be restrict-qualified."
if (Qs.hasRestrict()) {
@@ -1789,6 +1742,11 @@ QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc,
if (T.isNull())
return QualType();
+ // Ignore any attempt to form a cv-qualified reference.
+ if (T->isReferenceType())
+ CVRAU &=
+ ~(DeclSpec::TQ_const | DeclSpec::TQ_volatile | DeclSpec::TQ_atomic);
+
// Convert from DeclSpec::TQ to Qualifiers::TQ by just dropping TQ_atomic and
// TQ_unaligned;
unsigned CVR = CVRAU & ~(DeclSpec::TQ_atomic | DeclSpec::TQ_unaligned);
@@ -2030,7 +1988,7 @@ QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue,
return Context.getRValueReferenceType(T);
}
-/// \brief Build a Pipe type.
+/// \brief Build a Read-only Pipe type.
///
/// \param T The type to which we'll be building a Pipe.
///
@@ -2038,11 +1996,20 @@ QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue,
///
/// \returns A suitable pipe type, if there are no errors. Otherwise, returns a
/// NULL type.
-QualType Sema::BuildPipeType(QualType T, SourceLocation Loc) {
- assert(!T->isObjCObjectType() && "Should build ObjCObjectPointerType");
+QualType Sema::BuildReadPipeType(QualType T, SourceLocation Loc) {
+ return Context.getReadPipeType(T);
+}
- // Build the pipe type.
- return Context.getPipeType(T);
+/// \brief Build a Write-only Pipe type.
+///
+/// \param T The type to which we'll be building a Pipe.
+///
+/// \param Loc We do not use it for now.
+///
+/// \returns A suitable pipe type, if there are no errors. Otherwise, returns a
+/// NULL type.
+QualType Sema::BuildWritePipeType(QualType T, SourceLocation Loc) {
+ return Context.getWritePipeType(T);
}
/// Check whether the specified array size makes the array type a VLA. If so,
@@ -2242,6 +2209,10 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
Diag(Loc, diag::err_opencl_vla);
return QualType();
}
+ // CUDA device code doesn't support VLAs.
+ if (getLangOpts().CUDA && T->isVariableArrayType())
+ CUDADiagIfDeviceCode(Loc, diag::err_cuda_vla) << CurrentCUDATarget();
+
// If this is not C99, extwarn about VLA's and C99 array size modifiers.
if (!getLangOpts().C99) {
if (T->isVariableArrayType()) {
@@ -2390,28 +2361,16 @@ static void checkExtParameterInfos(Sema &S, ArrayRef<QualType> paramTypes,
}
continue;
- // swift_context parameters must be the last parameter except for
- // a possible swift_error parameter.
case ParameterABI::SwiftContext:
checkForSwiftCC(paramIndex);
- if (!(paramIndex == numParams - 1 ||
- (paramIndex == numParams - 2 &&
- EPI.ExtParameterInfos[numParams - 1].getABI()
- == ParameterABI::SwiftErrorResult))) {
- S.Diag(getParamLoc(paramIndex),
- diag::err_swift_context_not_before_swift_error_result);
- }
continue;
- // swift_error parameters must be the last parameter.
+ // swift_error parameters must be preceded by a swift_context parameter.
case ParameterABI::SwiftErrorResult:
checkForSwiftCC(paramIndex);
- if (paramIndex != numParams - 1) {
- S.Diag(getParamLoc(paramIndex),
- diag::err_swift_error_result_not_last);
- } else if (paramIndex == 0 ||
- EPI.ExtParameterInfos[paramIndex - 1].getABI()
- != ParameterABI::SwiftContext) {
+ if (paramIndex == 0 ||
+ EPI.ExtParameterInfos[paramIndex - 1].getABI() !=
+ ParameterABI::SwiftContext) {
S.Diag(getParamLoc(paramIndex),
diag::err_swift_error_result_not_after_swift_context);
}
@@ -2855,7 +2814,8 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
Error = 7; // Exception declaration
break;
case Declarator::TemplateParamContext:
- Error = 8; // Template parameter
+ if (!SemaRef.getLangOpts().CPlusPlus1z)
+ Error = 8; // Template parameter
break;
case Declarator::BlockLiteralContext:
Error = 9; // Block literal
@@ -3212,6 +3172,7 @@ namespace {
Pointer,
BlockPointer,
MemberPointer,
+ Array,
};
} // end anonymous namespace
@@ -3273,15 +3234,27 @@ namespace {
// NSError**
NSErrorPointerPointer,
};
+
+ /// Describes a declarator chunk wrapping a pointer that marks inference as
+ /// unexpected.
+ // These values must be kept in sync with diagnostics.
+ enum class PointerWrappingDeclaratorKind {
+ /// Pointer is top-level.
+ None = -1,
+ /// Pointer is an array element.
+ Array = 0,
+ /// Pointer is the referent type of a C++ reference.
+ Reference = 1
+ };
} // end anonymous namespace
/// Classify the given declarator, whose type-specified is \c type, based on
/// what kind of pointer it refers to.
///
/// This is used to determine the default nullability.
-static PointerDeclaratorKind classifyPointerDeclarator(Sema &S,
- QualType type,
- Declarator &declarator) {
+static PointerDeclaratorKind
+classifyPointerDeclarator(Sema &S, QualType type, Declarator &declarator,
+ PointerWrappingDeclaratorKind &wrappingKind) {
unsigned numNormalPointers = 0;
// For any dependent type, we consider it a non-pointer.
@@ -3293,6 +3266,10 @@ static PointerDeclaratorKind classifyPointerDeclarator(Sema &S,
DeclaratorChunk &chunk = declarator.getTypeObject(i);
switch (chunk.Kind) {
case DeclaratorChunk::Array:
+ if (numNormalPointers == 0)
+ wrappingKind = PointerWrappingDeclaratorKind::Array;
+ break;
+
case DeclaratorChunk::Function:
case DeclaratorChunk::Pipe:
break;
@@ -3303,14 +3280,18 @@ static PointerDeclaratorKind classifyPointerDeclarator(Sema &S,
: PointerDeclaratorKind::SingleLevelPointer;
case DeclaratorChunk::Paren:
+ break;
+
case DeclaratorChunk::Reference:
- continue;
+ if (numNormalPointers == 0)
+ wrappingKind = PointerWrappingDeclaratorKind::Reference;
+ break;
case DeclaratorChunk::Pointer:
++numNormalPointers;
if (numNormalPointers > 2)
return PointerDeclaratorKind::MultiLevelPointer;
- continue;
+ break;
}
}
@@ -3453,12 +3434,77 @@ static FileID getNullabilityCompletenessCheckFileID(Sema &S,
return file;
}
-/// Check for consistent use of nullability.
-static void checkNullabilityConsistency(TypeProcessingState &state,
+/// Creates a fix-it to insert a C-style nullability keyword at \p pointerLoc,
+/// taking into account whitespace before and after.
+static void fixItNullability(Sema &S, DiagnosticBuilder &Diag,
+ SourceLocation PointerLoc,
+ NullabilityKind Nullability) {
+ assert(PointerLoc.isValid());
+ if (PointerLoc.isMacroID())
+ return;
+
+ SourceLocation FixItLoc = S.getLocForEndOfToken(PointerLoc);
+ if (!FixItLoc.isValid() || FixItLoc == PointerLoc)
+ return;
+
+ const char *NextChar = S.SourceMgr.getCharacterData(FixItLoc);
+ if (!NextChar)
+ return;
+
+ SmallString<32> InsertionTextBuf{" "};
+ InsertionTextBuf += getNullabilitySpelling(Nullability);
+ InsertionTextBuf += " ";
+ StringRef InsertionText = InsertionTextBuf.str();
+
+ if (isWhitespace(*NextChar)) {
+ InsertionText = InsertionText.drop_back();
+ } else if (NextChar[-1] == '[') {
+ if (NextChar[0] == ']')
+ InsertionText = InsertionText.drop_back().drop_front();
+ else
+ InsertionText = InsertionText.drop_front();
+ } else if (!isIdentifierBody(NextChar[0], /*allow dollar*/true) &&
+ !isIdentifierBody(NextChar[-1], /*allow dollar*/true)) {
+ InsertionText = InsertionText.drop_back().drop_front();
+ }
+
+ Diag << FixItHint::CreateInsertion(FixItLoc, InsertionText);
+}
+
+static void emitNullabilityConsistencyWarning(Sema &S,
+ SimplePointerKind PointerKind,
+ SourceLocation PointerLoc) {
+ assert(PointerLoc.isValid());
+
+ if (PointerKind == SimplePointerKind::Array) {
+ S.Diag(PointerLoc, diag::warn_nullability_missing_array);
+ } else {
+ S.Diag(PointerLoc, diag::warn_nullability_missing)
+ << static_cast<unsigned>(PointerKind);
+ }
+
+ if (PointerLoc.isMacroID())
+ return;
+
+ auto addFixIt = [&](NullabilityKind Nullability) {
+ auto Diag = S.Diag(PointerLoc, diag::note_nullability_fix_it);
+ Diag << static_cast<unsigned>(Nullability);
+ Diag << static_cast<unsigned>(PointerKind);
+ fixItNullability(S, Diag, PointerLoc, Nullability);
+ };
+ addFixIt(NullabilityKind::Nullable);
+ addFixIt(NullabilityKind::NonNull);
+}
+
+/// Complains about missing nullability if the file containing \p pointerLoc
+/// has other uses of nullability (either the keywords or the \c assume_nonnull
+/// pragma).
+///
+/// If the file has \e not seen other uses of nullability, this particular
+/// pointer is saved for possible later diagnosis. See recordNullabilitySeen().
+static void checkNullabilityConsistency(Sema &S,
SimplePointerKind pointerKind,
SourceLocation pointerLoc) {
- Sema &S = state.getSema();
-
// Determine which file we're performing consistency checking for.
FileID file = getNullabilityCompletenessCheckFileID(S, pointerLoc);
if (file.isInvalid())
@@ -3468,10 +3514,16 @@ static void checkNullabilityConsistency(TypeProcessingState &state,
// about anything.
FileNullability &fileNullability = S.NullabilityMap[file];
if (!fileNullability.SawTypeNullability) {
- // If this is the first pointer declarator in the file, record it.
+ // If this is the first pointer declarator in the file, and the appropriate
+ // warning is on, record it in case we need to diagnose it retroactively.
+ diag::kind diagKind;
+ if (pointerKind == SimplePointerKind::Array)
+ diagKind = diag::warn_nullability_missing_array;
+ else
+ diagKind = diag::warn_nullability_missing;
+
if (fileNullability.PointerLoc.isInvalid() &&
- !S.Context.getDiagnostics().isIgnored(diag::warn_nullability_missing,
- pointerLoc)) {
+ !S.Context.getDiagnostics().isIgnored(diagKind, pointerLoc)) {
fileNullability.PointerLoc = pointerLoc;
fileNullability.PointerKind = static_cast<unsigned>(pointerKind);
}
@@ -3480,8 +3532,66 @@ static void checkNullabilityConsistency(TypeProcessingState &state,
}
// Complain about missing nullability.
- S.Diag(pointerLoc, diag::warn_nullability_missing)
- << static_cast<unsigned>(pointerKind);
+ emitNullabilityConsistencyWarning(S, pointerKind, pointerLoc);
+}
+
+/// Marks that a nullability feature has been used in the file containing
+/// \p loc.
+///
+/// If this file already had pointer types in it that were missing nullability,
+/// the first such instance is retroactively diagnosed.
+///
+/// \sa checkNullabilityConsistency
+static void recordNullabilitySeen(Sema &S, SourceLocation loc) {
+ FileID file = getNullabilityCompletenessCheckFileID(S, loc);
+ if (file.isInvalid())
+ return;
+
+ FileNullability &fileNullability = S.NullabilityMap[file];
+ if (fileNullability.SawTypeNullability)
+ return;
+ fileNullability.SawTypeNullability = true;
+
+ // If we haven't seen any type nullability before, now we have. Retroactively
+ // diagnose the first unannotated pointer, if there was one.
+ if (fileNullability.PointerLoc.isInvalid())
+ return;
+
+ auto kind = static_cast<SimplePointerKind>(fileNullability.PointerKind);
+ emitNullabilityConsistencyWarning(S, kind, fileNullability.PointerLoc);
+}
+
+/// Returns true if any of the declarator chunks before \p endIndex include a
+/// level of indirection: array, pointer, reference, or pointer-to-member.
+///
+/// Because declarator chunks are stored in outer-to-inner order, testing
+/// every chunk before \p endIndex is testing all chunks that embed the current
+/// chunk as part of their type.
+///
+/// It is legal to pass the result of Declarator::getNumTypeObjects() as the
+/// end index, in which case all chunks are tested.
+static bool hasOuterPointerLikeChunk(const Declarator &D, unsigned endIndex) {
+ unsigned i = endIndex;
+ while (i != 0) {
+ // Walk outwards along the declarator chunks.
+ --i;
+ const DeclaratorChunk &DC = D.getTypeObject(i);
+ switch (DC.Kind) {
+ case DeclaratorChunk::Paren:
+ break;
+ case DeclaratorChunk::Array:
+ case DeclaratorChunk::Pointer:
+ case DeclaratorChunk::Reference:
+ case DeclaratorChunk::MemberPointer:
+ return true;
+ case DeclaratorChunk::Function:
+ case DeclaratorChunk::BlockPointer:
+ case DeclaratorChunk::Pipe:
+ // These are invalid anyway, so just ignore.
+ break;
+ }
+ }
+ return false;
}
static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
@@ -3561,24 +3671,10 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// Are we in an assume-nonnull region?
bool inAssumeNonNullRegion = false;
- if (S.PP.getPragmaAssumeNonNullLoc().isValid()) {
+ SourceLocation assumeNonNullLoc = S.PP.getPragmaAssumeNonNullLoc();
+ if (assumeNonNullLoc.isValid()) {
inAssumeNonNullRegion = true;
- // Determine which file we saw the assume-nonnull region in.
- FileID file = getNullabilityCompletenessCheckFileID(
- S, S.PP.getPragmaAssumeNonNullLoc());
- if (file.isValid()) {
- FileNullability &fileNullability = S.NullabilityMap[file];
-
- // If we haven't seen any type nullability before, now we have.
- if (!fileNullability.SawTypeNullability) {
- if (fileNullability.PointerLoc.isValid()) {
- S.Diag(fileNullability.PointerLoc, diag::warn_nullability_missing)
- << static_cast<unsigned>(fileNullability.PointerKind);
- }
-
- fileNullability.SawTypeNullability = true;
- }
- }
+ recordNullabilitySeen(S, assumeNonNullLoc);
}
// Whether to complain about missing nullability specifiers or not.
@@ -3593,6 +3689,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
CAMN_Yes
} complainAboutMissingNullability = CAMN_No;
unsigned NumPointersRemaining = 0;
+ auto complainAboutInferringWithinChunk = PointerWrappingDeclaratorKind::None;
if (IsTypedefName) {
// For typedefs, we do not infer any nullability (the default),
@@ -3600,7 +3697,17 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// inner pointers.
complainAboutMissingNullability = CAMN_InnerPointers;
- if (T->canHaveNullability() && !T->getNullability(S.Context)) {
+ auto isDependentNonPointerType = [](QualType T) -> bool {
+ // Note: This is intended to be the same check as Type::canHaveNullability
+ // except with all of the ambiguous cases being treated as 'false' rather
+ // than 'true'.
+ return T->isDependentType() && !T->isAnyPointerType() &&
+ !T->isBlockPointerType() && !T->isMemberPointerType();
+ };
+
+ if (T->canHaveNullability() && !T->getNullability(S.Context) &&
+ !isDependentNonPointerType(T)) {
+ // Note that we allow but don't require nullability on dependent types.
++NumPointersRemaining;
}
@@ -3651,11 +3758,12 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// fallthrough
case Declarator::FileContext:
- case Declarator::KNRTypeListContext:
+ case Declarator::KNRTypeListContext: {
complainAboutMissingNullability = CAMN_Yes;
// Nullability inference depends on the type and declarator.
- switch (classifyPointerDeclarator(S, T, D)) {
+ auto wrappingKind = PointerWrappingDeclaratorKind::None;
+ switch (classifyPointerDeclarator(S, T, D, wrappingKind)) {
case PointerDeclaratorKind::NonPointer:
case PointerDeclaratorKind::MultiLevelPointer:
// Cannot infer nullability.
@@ -3664,6 +3772,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
case PointerDeclaratorKind::SingleLevelPointer:
// Infer _Nonnull if we are in an assumes-nonnull region.
if (inAssumeNonNullRegion) {
+ complainAboutInferringWithinChunk = wrappingKind;
inferNullability = NullabilityKind::NonNull;
inferNullabilityCS = (context == Declarator::ObjCParameterContext ||
context == Declarator::ObjCResultContext);
@@ -3704,6 +3813,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
break;
}
break;
+ }
case Declarator::ConversionIdContext:
complainAboutMissingNullability = CAMN_Yes;
@@ -3729,6 +3839,23 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
}
}
+ // Local function that returns true if its argument looks like a va_list.
+ auto isVaList = [&S](QualType T) -> bool {
+ auto *typedefTy = T->getAs<TypedefType>();
+ if (!typedefTy)
+ return false;
+ TypedefDecl *vaListTypedef = S.Context.getBuiltinVaListDecl();
+ do {
+ if (typedefTy->getDecl() == vaListTypedef)
+ return true;
+ if (auto *name = typedefTy->getDecl()->getIdentifier())
+ if (name->isStr("va_list"))
+ return true;
+ typedefTy = typedefTy->desugar()->getAs<TypedefType>();
+ } while (typedefTy);
+ return false;
+ };
+
// Local function that checks the nullability for a given pointer declarator.
// Returns true if _Nonnull was inferred.
auto inferPointerNullability = [&](SimplePointerKind pointerKind,
@@ -3762,6 +3889,15 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
->setObjCDeclQualifier(ObjCDeclSpec::DQ_CSNullability);
}
+ if (pointerLoc.isValid() &&
+ complainAboutInferringWithinChunk !=
+ PointerWrappingDeclaratorKind::None) {
+ auto Diag =
+ S.Diag(pointerLoc, diag::warn_nullability_inferred_on_nested_type);
+ Diag << static_cast<int>(complainAboutInferringWithinChunk);
+ fixItNullability(S, Diag, pointerLoc, NullabilityKind::NonNull);
+ }
+
if (inferNullabilityInnerOnly)
inferNullabilityInnerOnlyComplete = true;
return nullabilityAttr;
@@ -3779,27 +3915,42 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// Fallthrough.
case CAMN_Yes:
- checkNullabilityConsistency(state, pointerKind, pointerLoc);
+ checkNullabilityConsistency(S, pointerKind, pointerLoc);
}
return nullptr;
};
// If the type itself could have nullability but does not, infer pointer
// nullability and perform consistency checking.
- if (T->canHaveNullability() && S.ActiveTemplateInstantiations.empty() &&
- !T->getNullability(S.Context)) {
- SimplePointerKind pointerKind = SimplePointerKind::Pointer;
- if (T->isBlockPointerType())
- pointerKind = SimplePointerKind::BlockPointer;
- else if (T->isMemberPointerType())
- pointerKind = SimplePointerKind::MemberPointer;
+ if (S.ActiveTemplateInstantiations.empty()) {
+ if (T->canHaveNullability() && !T->getNullability(S.Context)) {
+ if (isVaList(T)) {
+ // Record that we've seen a pointer, but do nothing else.
+ if (NumPointersRemaining > 0)
+ --NumPointersRemaining;
+ } else {
+ SimplePointerKind pointerKind = SimplePointerKind::Pointer;
+ if (T->isBlockPointerType())
+ pointerKind = SimplePointerKind::BlockPointer;
+ else if (T->isMemberPointerType())
+ pointerKind = SimplePointerKind::MemberPointer;
+
+ if (auto *attr = inferPointerNullability(
+ pointerKind, D.getDeclSpec().getTypeSpecTypeLoc(),
+ D.getMutableDeclSpec().getAttributes().getListRef())) {
+ T = Context.getAttributedType(
+ AttributedType::getNullabilityAttrKind(*inferNullability),T,T);
+ attr->setUsedAsTypeAttr();
+ }
+ }
+ }
- if (auto *attr = inferPointerNullability(
- pointerKind, D.getDeclSpec().getTypeSpecTypeLoc(),
- D.getMutableDeclSpec().getAttributes().getListRef())) {
- T = Context.getAttributedType(
- AttributedType::getNullabilityAttrKind(*inferNullability), T, T);
- attr->setUsedAsTypeAttr();
+ if (complainAboutMissingNullability == CAMN_Yes &&
+ T->isArrayType() && !T->getNullability(S.Context) && !isVaList(T) &&
+ D.isPrototypeContext() &&
+ !hasOuterPointerLikeChunk(D, D.getNumTypeObjects())) {
+ checkNullabilityConsistency(S, SimplePointerKind::Array,
+ D.getDeclSpec().getTypeSpecTypeLoc());
}
}
@@ -3925,31 +4076,13 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// C99 6.7.5.2p1: ... and then only in the outermost array type
// derivation.
- unsigned x = chunkIndex;
- while (x != 0) {
- // Walk outwards along the declarator chunks.
- x--;
- const DeclaratorChunk &DC = D.getTypeObject(x);
- switch (DC.Kind) {
- case DeclaratorChunk::Paren:
- continue;
- case DeclaratorChunk::Array:
- case DeclaratorChunk::Pointer:
- case DeclaratorChunk::Reference:
- case DeclaratorChunk::MemberPointer:
- S.Diag(DeclType.Loc, diag::err_array_static_not_outermost) <<
- (ASM == ArrayType::Static ? "'static'" : "type qualifier");
- if (ASM == ArrayType::Static)
- ASM = ArrayType::Normal;
- ATI.TypeQuals = 0;
- D.setInvalidType(true);
- break;
- case DeclaratorChunk::Function:
- case DeclaratorChunk::BlockPointer:
- case DeclaratorChunk::Pipe:
- // These are invalid anyway, so just ignore.
- break;
- }
+ if (hasOuterPointerLikeChunk(D, chunkIndex)) {
+ S.Diag(DeclType.Loc, diag::err_array_static_not_outermost) <<
+ (ASM == ArrayType::Static ? "'static'" : "type qualifier");
+ if (ASM == ArrayType::Static)
+ ASM = ArrayType::Normal;
+ ATI.TypeQuals = 0;
+ D.setInvalidType(true);
}
}
const AutoType *AT = T->getContainedAutoType();
@@ -3964,6 +4097,16 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
break;
}
+ // Array parameters can be marked nullable as well, although it's not
+ // necessary if they're marked 'static'.
+ if (complainAboutMissingNullability == CAMN_Yes &&
+ !hasNullabilityAttr(DeclType.getAttrs()) &&
+ ASM != ArrayType::Static &&
+ D.isPrototypeContext() &&
+ !hasOuterPointerLikeChunk(D, chunkIndex)) {
+ checkNullabilityConsistency(S, SimplePointerKind::Array, DeclType.Loc);
+ }
+
T = S.BuildArrayType(T, ASM, ArraySize, ATI.TypeQuals,
SourceRange(DeclType.Loc, DeclType.EndLoc), Name);
break;
@@ -4032,7 +4175,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// FIXME: This really should be in BuildFunctionType.
if (T->isHalfType()) {
if (S.getLangOpts().OpenCL) {
- if (!S.getOpenCLOptions().cl_khr_fp16) {
+ if (!S.getOpenCLOptions().isEnabled("cl_khr_fp16")) {
S.Diag(D.getIdentifierLoc(), diag::err_opencl_invalid_return)
<< T << 0 /*pointer hint*/;
D.setInvalidType(true);
@@ -4044,13 +4187,26 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
}
}
+ if (LangOpts.OpenCL) {
// OpenCL v2.0 s6.12.5 - A block cannot be the return value of a
// function.
- if (LangOpts.OpenCL && (T->isBlockPointerType() || T->isImageType() ||
- T->isSamplerT() || T->isPipeType())) {
- S.Diag(D.getIdentifierLoc(), diag::err_opencl_invalid_return)
- << T << 1 /*hint off*/;
- D.setInvalidType(true);
+ if (T->isBlockPointerType() || T->isImageType() || T->isSamplerT() ||
+ T->isPipeType()) {
+ S.Diag(D.getIdentifierLoc(), diag::err_opencl_invalid_return)
+ << T << 1 /*hint off*/;
+ D.setInvalidType(true);
+ }
+ // OpenCL doesn't support variadic functions and blocks
+ // (s6.9.e and s6.12.5 OpenCL v2.0) except for printf.
+ // We also allow here any toolchain reserved identifiers.
+ if (FTI.isVariadic &&
+ !(D.getIdentifier() &&
+ ((D.getIdentifier()->getName() == "printf" &&
+ LangOpts.OpenCLVersion >= 120) ||
+ D.getIdentifier()->getName().startswith("__")))) {
+ S.Diag(D.getIdentifierLoc(), diag::err_opencl_variadic_function);
+ D.setInvalidType(true);
+ }
}
// Methods cannot return interface types. All ObjC objects are
@@ -4143,7 +4299,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// Exception specs are not allowed in typedefs. Complain, but add it
// anyway.
- if (IsTypedefName && FTI.getExceptionSpecType())
+ if (IsTypedefName && FTI.getExceptionSpecType() && !LangOpts.CPlusPlus1z)
S.Diag(FTI.getExceptionSpecLocBeg(),
diag::err_exception_spec_in_typedef)
<< (D.getContext() == Declarator::AliasDeclContext ||
@@ -4154,6 +4310,19 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
if (FTI.isAmbiguous)
warnAboutAmbiguousFunction(S, D, DeclType, T);
+ // GNU warning -Wstrict-prototypes
+ // Warn if a function declaration is without a prototype.
+ // This warning is issued for all kinds of unprototyped function
+ // declarations (i.e. function type typedef, function pointer etc.)
+ // C99 6.7.5.3p14:
+ // The empty list in a function declarator that is not part of a
+ // definition of that function specifies that no information
+ // about the number or types of the parameters is supplied.
+ if (D.getFunctionDefinitionKind() == FDK_Declaration &&
+ FTI.NumParams == 0 && !LangOpts.CPlusPlus)
+ S.Diag(DeclType.Loc, diag::warn_strict_prototypes)
+ << 0 << FixItHint::CreateInsertion(FTI.getRParenLoc(), "void");
+
FunctionType::ExtInfo EI(getCCForDeclaratorChunk(S, D, FTI, chunkIndex));
if (!FTI.NumParams && !FTI.isVariadic && !LangOpts.CPlusPlus) {
@@ -4239,7 +4408,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// Disallow half FP parameters.
// FIXME: This really should be in BuildFunctionType.
if (S.getLangOpts().OpenCL) {
- if (!S.getOpenCLOptions().cl_khr_fp16) {
+ if (!S.getOpenCLOptions().isEnabled("cl_khr_fp16")) {
S.Diag(Param->getLocation(),
diag::err_opencl_half_param) << ParamTy;
D.setInvalidType();
@@ -4290,7 +4459,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
if (FTI.getExceptionSpecType() == EST_Dynamic) {
// FIXME: It's rather inefficient to have to split into two vectors
// here.
- unsigned N = FTI.NumExceptions;
+ unsigned N = FTI.getNumExceptions();
DynamicExceptions.reserve(N);
DynamicExceptionRanges.reserve(N);
for (unsigned I = 0; I != N; ++I) {
@@ -4374,7 +4543,9 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
}
case DeclaratorChunk::Pipe: {
- T = S.BuildPipeType(T, DeclType.Loc );
+ T = S.BuildReadPipeType(T, DeclType.Loc);
+ processTypeAttrs(state, T, TAL_DeclSpec,
+ D.getDeclSpec().getAttributes().getList());
break;
}
}
@@ -4738,6 +4909,8 @@ static AttributeList::Kind getAttrListKind(AttributedType::Kind kind) {
return AttributeList::AT_StdCall;
case AttributedType::attr_thiscall:
return AttributeList::AT_ThisCall;
+ case AttributedType::attr_regcall:
+ return AttributeList::AT_RegCall;
case AttributedType::attr_pascal:
return AttributeList::AT_Pascal;
case AttributedType::attr_swiftcall:
@@ -4908,11 +5081,9 @@ namespace {
TL.getWrittenBuiltinSpecs() = DS.getWrittenBuiltinSpecs();
// Try to have a meaningful source location.
if (TL.getWrittenSignSpec() != TSS_unspecified)
- // Sign spec loc overrides the others (e.g., 'unsigned long').
- TL.setBuiltinLoc(DS.getTypeSpecSignLoc());
- else if (TL.getWrittenWidthSpec() != TSW_unspecified)
- // Width spec loc overrides type spec loc (e.g., 'short int').
- TL.setBuiltinLoc(DS.getTypeSpecWidthLoc());
+ TL.expandBuiltinRange(DS.getTypeSpecSignLoc());
+ if (TL.getWrittenWidthSpec() != TSW_unspecified)
+ TL.expandBuiltinRange(DS.getTypeSpecWidthRange());
}
}
void VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {
@@ -5537,7 +5708,7 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
if (Class->isArcWeakrefUnavailable()) {
S.Diag(AttrLoc, diag::err_arc_unsupported_weak_class);
S.Diag(ObjT->getInterfaceDecl()->getLocation(),
- diag::note_class_declared);
+ diag::note_class_declared);
}
}
}
@@ -5811,23 +5982,9 @@ static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State,
bool Sema::checkNullabilityTypeSpecifier(QualType &type,
NullabilityKind nullability,
SourceLocation nullabilityLoc,
- bool isContextSensitive) {
- // We saw a nullability type specifier. If this is the first one for
- // this file, note that.
- FileID file = getNullabilityCompletenessCheckFileID(*this, nullabilityLoc);
- if (!file.isInvalid()) {
- FileNullability &fileNullability = NullabilityMap[file];
- if (!fileNullability.SawTypeNullability) {
- // If we have already seen a pointer declarator without a nullability
- // annotation, complain about it.
- if (fileNullability.PointerLoc.isValid()) {
- Diag(fileNullability.PointerLoc, diag::warn_nullability_missing)
- << static_cast<unsigned>(fileNullability.PointerKind);
- }
-
- fileNullability.SawTypeNullability = true;
- }
- }
+ bool isContextSensitive,
+ bool allowOnArrayType) {
+ recordNullabilitySeen(*this, nullabilityLoc);
// Check for existing nullability attributes on the type.
QualType desugared = type;
@@ -5881,7 +6038,8 @@ bool Sema::checkNullabilityTypeSpecifier(QualType &type,
}
// If this definitely isn't a pointer type, reject the specifier.
- if (!desugared->canHaveNullability()) {
+ if (!desugared->canHaveNullability() &&
+ !(allowOnArrayType && desugared->isArrayType())) {
Diag(nullabilityLoc, diag::err_nullability_nonpointer)
<< DiagNullabilityKind(nullability, isContextSensitive) << type;
return true;
@@ -5891,7 +6049,12 @@ bool Sema::checkNullabilityTypeSpecifier(QualType &type,
// attributes, require that the type be a single-level pointer.
if (isContextSensitive) {
// Make sure that the pointee isn't itself a pointer type.
- QualType pointeeType = desugared->getPointeeType();
+ const Type *pointeeType;
+ if (desugared->isArrayType())
+ pointeeType = desugared->getArrayElementTypeNoTypeQual();
+ else
+ pointeeType = desugared->getPointeeType().getTypePtr();
+
if (pointeeType->isAnyPointerType() ||
pointeeType->isObjCObjectPointerType() ||
pointeeType->isMemberPointerType()) {
@@ -5914,6 +6077,13 @@ bool Sema::checkNullabilityTypeSpecifier(QualType &type,
}
bool Sema::checkObjCKindOfType(QualType &type, SourceLocation loc) {
+ if (isa<ObjCTypeParamType>(type)) {
+ // Build the attributed type to record where __kindof occurred.
+ type = Context.getAttributedType(AttributedType::attr_objc_kindof,
+ type, type);
+ return false;
+ }
+
// Find out if it's an Objective-C object or object pointer type;
const ObjCObjectPointerType *ptrType = type->getAs<ObjCObjectPointerType>();
const ObjCObjectType *objType = ptrType ? ptrType->getObjectType()
@@ -6070,6 +6240,8 @@ static AttributedType::Kind getCCTypeAttrKind(AttributeList &Attr) {
return AttributedType::attr_stdcall;
case AttributeList::AT_ThisCall:
return AttributedType::attr_thiscall;
+ case AttributeList::AT_RegCall:
+ return AttributedType::attr_regcall;
case AttributeList::AT_Pascal:
return AttributedType::attr_pascal;
case AttributeList::AT_SwiftCall:
@@ -6523,6 +6695,11 @@ static void HandleOpenCLAccessAttr(QualType &CurType, const AttributeList &Attr,
S.Diag(TypedefTy->getDecl()->getLocStart(),
diag::note_opencl_typedef_access_qualifier) << PrevAccessQual;
+ } else if (CurType->isPipeType()) {
+ if (Attr.getSemanticSpelling() == OpenCLAccessAttr::Keyword_write_only) {
+ QualType ElemType = CurType->getAs<PipeType>()->getElementType();
+ CurType = S.Context.getWritePipeType(ElemType);
+ }
}
}
@@ -6637,12 +6814,22 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
// don't want to distribute the nullability specifier past any
// dependent type, because that complicates the user model.
if (type->canHaveNullability() || type->isDependentType() ||
+ type->isArrayType() ||
!distributeNullabilityTypeAttr(state, type, attr)) {
+ unsigned endIndex;
+ if (TAL == TAL_DeclChunk)
+ endIndex = state.getCurrentChunkIndex();
+ else
+ endIndex = state.getDeclarator().getNumTypeObjects();
+ bool allowOnArrayType =
+ state.getDeclarator().isPrototypeContext() &&
+ !hasOuterPointerLikeChunk(state.getDeclarator(), endIndex);
if (state.getSema().checkNullabilityTypeSpecifier(
type,
mapNullabilityAttrKind(attr.getKind()),
attr.getLoc(),
- attr.isContextSensitiveKeywordAttribute())) {
+ attr.isContextSensitiveKeywordAttribute(),
+ allowOnArrayType)) {
attr.setInvalid();
}
@@ -6879,6 +7066,14 @@ bool Sema::hasVisibleDefinition(NamedDecl *D, NamedDecl **Suggested,
return false;
}
D = ED->getDefinition();
+ } else if (auto *FD = dyn_cast<FunctionDecl>(D)) {
+ if (auto *Pattern = FD->getTemplateInstantiationPattern())
+ FD = Pattern;
+ D = FD->getDefinition();
+ } else if (auto *VD = dyn_cast<VarDecl>(D)) {
+ if (auto *Pattern = VD->getTemplateInstantiationPattern())
+ VD = Pattern;
+ D = VD->getDefinition();
}
assert(D && "missing definition for pattern of instantiated definition");
@@ -6886,7 +7081,7 @@ bool Sema::hasVisibleDefinition(NamedDecl *D, NamedDecl **Suggested,
if (isVisible(D))
return true;
- // The external source may have additional definitions of this type that are
+ // The external source may have additional definitions of this entity that are
// visible, so complete the redeclaration chain now and ask again.
if (auto *Source = Context.getExternalSource()) {
Source->CompleteRedeclChain(D);
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 7224eef848de..3ab6019f0ec3 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -457,6 +457,10 @@ public:
return cast_or_null<NamedDecl>(getDerived().TransformDecl(Loc, D));
}
+ /// Transform the set of declarations in an OverloadExpr.
+ bool TransformOverloadExprDecls(OverloadExpr *Old, bool RequiresADL,
+ LookupResult &R);
+
/// \brief Transform the given nested-name-specifier with source-location
/// information.
///
@@ -699,6 +703,12 @@ public:
QualType RebuildMemberPointerType(QualType PointeeType, QualType ClassType,
SourceLocation Sigil);
+ QualType RebuildObjCTypeParamType(const ObjCTypeParamDecl *Decl,
+ SourceLocation ProtocolLAngleLoc,
+ ArrayRef<ObjCProtocolDecl *> Protocols,
+ ArrayRef<SourceLocation> ProtocolLocs,
+ SourceLocation ProtocolRAngleLoc);
+
/// \brief Build an Objective-C object type.
///
/// By default, performs semantic analysis when building the object type.
@@ -815,7 +825,7 @@ public:
/// \brief Rebuild an unresolved typename type, given the decl that
/// the UnresolvedUsingTypenameDecl was transformed to.
- QualType RebuildUnresolvedUsingType(Decl *D);
+ QualType RebuildUnresolvedUsingType(SourceLocation NameLoc, Decl *D);
/// \brief Build a new typedef type.
QualType RebuildTypedefType(TypedefNameDecl *Typedef) {
@@ -1007,11 +1017,9 @@ public:
case LookupResult::FoundOverloaded:
case LookupResult::FoundUnresolvedValue: {
NamedDecl *SomeDecl = Result.getRepresentativeDecl();
- unsigned Kind = 0;
- if (isa<TypedefDecl>(SomeDecl)) Kind = 1;
- else if (isa<TypeAliasDecl>(SomeDecl)) Kind = 2;
- else if (isa<ClassTemplateDecl>(SomeDecl)) Kind = 3;
- SemaRef.Diag(IdLoc, diag::err_tag_reference_non_tag) << Kind;
+ Sema::NonTagKind NTK = SemaRef.getNonTagTypeDeclKind(SomeDecl, Kind);
+ SemaRef.Diag(IdLoc, diag::err_tag_reference_non_tag) << SomeDecl
+ << NTK << Kind;
SemaRef.Diag(SomeDecl->getLocation(), diag::note_declared_at);
break;
}
@@ -1056,7 +1064,8 @@ public:
QualType RebuildAtomicType(QualType ValueType, SourceLocation KWLoc);
/// \brief Build a new pipe type given its value type.
- QualType RebuildPipeType(QualType ValueType, SourceLocation KWLoc);
+ QualType RebuildPipeType(QualType ValueType, SourceLocation KWLoc,
+ bool isReadPipe);
/// \brief Build a new template name given a nested name specifier, a flag
/// indicating whether the "template" keyword was provided, and the template
@@ -3216,6 +3225,9 @@ ExprResult TreeTransform<Derived>::TransformInitializer(Expr *Init,
if (ExprWithCleanups *ExprTemp = dyn_cast<ExprWithCleanups>(Init))
Init = ExprTemp->getSubExpr();
+ if (auto *AIL = dyn_cast<ArrayInitLoopExpr>(Init))
+ Init = AIL->getCommonExpr();
+
if (MaterializeTemporaryExpr *MTE = dyn_cast<MaterializeTemporaryExpr>(Init))
Init = MTE->GetTemporaryExpr();
@@ -3438,15 +3450,13 @@ TreeTransform<Derived>::TransformNestedNameSpecifierLoc(
NestedNameSpecifier *QNNS = Q.getNestedNameSpecifier();
switch (QNNS->getKind()) {
- case NestedNameSpecifier::Identifier:
- if (SemaRef.BuildCXXNestedNameSpecifier(/*Scope=*/nullptr,
- *QNNS->getAsIdentifier(),
- Q.getLocalBeginLoc(),
- Q.getLocalEndLoc(),
- ObjectType, false, SS,
- FirstQualifierInScope, false))
+ case NestedNameSpecifier::Identifier: {
+ Sema::NestedNameSpecInfo IdInfo(QNNS->getAsIdentifier(),
+ Q.getLocalBeginLoc(), Q.getLocalEndLoc(), ObjectType);
+ if (SemaRef.BuildCXXNestedNameSpecifier(/*Scope=*/nullptr, IdInfo, false,
+ SS, FirstQualifierInScope, false))
return NestedNameSpecifierLoc();
-
+ }
break;
case NestedNameSpecifier::Namespace: {
@@ -5118,6 +5128,8 @@ bool TreeTransform<Derived>::TransformExceptionSpec(
}
ESI.Exceptions = Exceptions;
+ if (ESI.Exceptions.empty())
+ ESI.Type = EST_DynamicNone;
return false;
}
@@ -5153,7 +5165,7 @@ TreeTransform<Derived>::TransformUnresolvedUsingType(TypeLocBuilder &TLB,
QualType Result = TL.getType();
if (getDerived().AlwaysRebuild() || D != T->getDecl()) {
- Result = getDerived().RebuildUnresolvedUsingType(D);
+ Result = getDerived().RebuildUnresolvedUsingType(TL.getNameLoc(), D);
if (Result.isNull())
return QualType();
}
@@ -5480,7 +5492,9 @@ QualType TreeTransform<Derived>::TransformPipeType(TypeLocBuilder &TLB,
QualType Result = TL.getType();
if (getDerived().AlwaysRebuild() || ValueType != TL.getValueLoc().getType()) {
- Result = getDerived().RebuildPipeType(ValueType, TL.getKWLoc());
+ const PipeType *PT = Result->getAs<PipeType>();
+ bool isReadPipe = PT->isReadOnly();
+ Result = getDerived().RebuildPipeType(ValueType, TL.getKWLoc(), isReadPipe);
if (Result.isNull())
return QualType();
}
@@ -5699,7 +5713,9 @@ TreeTransform<Derived>::TransformElaboratedType(TypeLocBuilder &TLB,
if (TypeAliasTemplateDecl *TAT = dyn_cast_or_null<TypeAliasTemplateDecl>(
Template.getAsTemplateDecl())) {
SemaRef.Diag(TL.getNamedTypeLoc().getBeginLoc(),
- diag::err_tag_reference_non_tag) << 4;
+ diag::err_tag_reference_non_tag)
+ << TAT << Sema::NTK_TypeAliasTemplate
+ << ElaboratedType::getTagTypeKindForKeyword(T->getKeyword());
SemaRef.Diag(TAT->getLocation(), diag::note_declared_at);
}
}
@@ -5946,6 +5962,39 @@ TreeTransform<Derived>::TransformObjCInterfaceType(TypeLocBuilder &TLB,
template<typename Derived>
QualType
+TreeTransform<Derived>::TransformObjCTypeParamType(TypeLocBuilder &TLB,
+ ObjCTypeParamTypeLoc TL) {
+ const ObjCTypeParamType *T = TL.getTypePtr();
+ ObjCTypeParamDecl *OTP = cast_or_null<ObjCTypeParamDecl>(
+ getDerived().TransformDecl(T->getDecl()->getLocation(), T->getDecl()));
+ if (!OTP)
+ return QualType();
+
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() ||
+ OTP != T->getDecl()) {
+ Result = getDerived().RebuildObjCTypeParamType(OTP,
+ TL.getProtocolLAngleLoc(),
+ llvm::makeArrayRef(TL.getTypePtr()->qual_begin(),
+ TL.getNumProtocols()),
+ TL.getProtocolLocs(),
+ TL.getProtocolRAngleLoc());
+ if (Result.isNull())
+ return QualType();
+ }
+
+ ObjCTypeParamTypeLoc NewTL = TLB.push<ObjCTypeParamTypeLoc>(Result);
+ if (TL.getNumProtocols()) {
+ NewTL.setProtocolLAngleLoc(TL.getProtocolLAngleLoc());
+ for (unsigned i = 0, n = TL.getNumProtocols(); i != n; ++i)
+ NewTL.setProtocolLoc(i, TL.getProtocolLoc(i));
+ NewTL.setProtocolRAngleLoc(TL.getProtocolRAngleLoc());
+ }
+ return Result;
+}
+
+template<typename Derived>
+QualType
TreeTransform<Derived>::TransformObjCObjectType(TypeLocBuilder &TLB,
ObjCObjectTypeLoc TL) {
// Transform base type.
@@ -6617,6 +6666,7 @@ template<typename Derived>
StmtResult
TreeTransform<Derived>::TransformCoroutineBodyStmt(CoroutineBodyStmt *S) {
// The coroutine body should be re-formed by the caller if necessary.
+ // FIXME: The coroutine body is always rebuilt by ActOnFinishFunctionBody
return getDerived().TransformStmt(S->getBody());
}
@@ -7626,6 +7676,96 @@ StmtResult TreeTransform<Derived>::TransformOMPTargetParallelForSimdDirective(
return Res;
}
+template <typename Derived>
+StmtResult TreeTransform<Derived>::TransformOMPTargetSimdDirective(
+ OMPTargetSimdDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_target_simd, DirName, nullptr,
+ D->getLocStart());
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
+template <typename Derived>
+StmtResult TreeTransform<Derived>::TransformOMPTeamsDistributeDirective(
+ OMPTeamsDistributeDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_teams_distribute, DirName,
+ nullptr, D->getLocStart());
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
+template <typename Derived>
+StmtResult TreeTransform<Derived>::TransformOMPTeamsDistributeSimdDirective(
+ OMPTeamsDistributeSimdDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(
+ OMPD_teams_distribute_simd, DirName, nullptr, D->getLocStart());
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
+template <typename Derived>
+StmtResult TreeTransform<Derived>::TransformOMPTeamsDistributeParallelForSimdDirective(
+ OMPTeamsDistributeParallelForSimdDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(
+ OMPD_teams_distribute_parallel_for_simd, DirName, nullptr, D->getLocStart());
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
+template <typename Derived>
+StmtResult TreeTransform<Derived>::TransformOMPTeamsDistributeParallelForDirective(
+ OMPTeamsDistributeParallelForDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_teams_distribute_parallel_for,
+ DirName, nullptr, D->getLocStart());
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
+template <typename Derived>
+StmtResult TreeTransform<Derived>::TransformOMPTargetTeamsDirective(
+ OMPTargetTeamsDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_target_teams, DirName,
+ nullptr, D->getLocStart());
+ auto Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
+template <typename Derived>
+StmtResult TreeTransform<Derived>::TransformOMPTargetTeamsDistributeDirective(
+ OMPTargetTeamsDistributeDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_target_teams_distribute,
+ DirName, nullptr, D->getLocStart());
+ auto Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
+template <typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformOMPTargetTeamsDistributeParallelForDirective(
+ OMPTargetTeamsDistributeParallelForDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(
+ OMPD_target_teams_distribute_parallel_for, DirName, nullptr,
+ D->getLocStart());
+ auto Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
//===----------------------------------------------------------------------===//
// OpenMP clause transformation
//===----------------------------------------------------------------------===//
@@ -8866,6 +9006,19 @@ TreeTransform<Derived>::TransformDesignatedInitExpr(DesignatedInitExpr *E) {
Desig.AddDesignator(Designator::getField(D.getFieldName(),
D.getDotLoc(),
D.getFieldLoc()));
+ if (D.getField()) {
+ FieldDecl *Field = cast_or_null<FieldDecl>(
+ getDerived().TransformDecl(D.getFieldLoc(), D.getField()));
+ if (Field != D.getField())
+ // Rebuild the expression when the transformed FieldDecl is
+ // different to the already assigned FieldDecl.
+ ExprChanged = true;
+ } else {
+ // Ensure that the designator expression is rebuilt when there isn't
+ // a resolved FieldDecl in the designator as we don't want to assign
+ // a FieldDecl to a pattern designator that will be instantiated again.
+ ExprChanged = true;
+ }
continue;
}
@@ -8935,6 +9088,20 @@ TreeTransform<Derived>::TransformNoInitExpr(
template<typename Derived>
ExprResult
+TreeTransform<Derived>::TransformArrayInitLoopExpr(ArrayInitLoopExpr *E) {
+ llvm_unreachable("Unexpected ArrayInitLoopExpr outside of initializer");
+ return ExprError();
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformArrayInitIndexExpr(ArrayInitIndexExpr *E) {
+ llvm_unreachable("Unexpected ArrayInitIndexExpr outside of initializer");
+ return ExprError();
+}
+
+template<typename Derived>
+ExprResult
TreeTransform<Derived>::TransformImplicitValueInitExpr(
ImplicitValueInitExpr *E) {
TemporaryBase Rebase(*this, E->getLocStart(), DeclarationName());
@@ -9655,44 +9822,72 @@ TreeTransform<Derived>::TransformCXXPseudoDestructorExpr(
Destroyed);
}
-template<typename Derived>
-ExprResult
-TreeTransform<Derived>::TransformUnresolvedLookupExpr(
- UnresolvedLookupExpr *Old) {
- LookupResult R(SemaRef, Old->getName(), Old->getNameLoc(),
- Sema::LookupOrdinaryName);
-
+template <typename Derived>
+bool TreeTransform<Derived>::TransformOverloadExprDecls(OverloadExpr *Old,
+ bool RequiresADL,
+ LookupResult &R) {
// Transform all the decls.
- for (UnresolvedLookupExpr::decls_iterator I = Old->decls_begin(),
- E = Old->decls_end(); I != E; ++I) {
- NamedDecl *InstD = static_cast<NamedDecl*>(
- getDerived().TransformDecl(Old->getNameLoc(),
- *I));
+ bool AllEmptyPacks = true;
+ for (auto *OldD : Old->decls()) {
+ Decl *InstD = getDerived().TransformDecl(Old->getNameLoc(), OldD);
if (!InstD) {
// Silently ignore these if a UsingShadowDecl instantiated to nothing.
// This can happen because of dependent hiding.
- if (isa<UsingShadowDecl>(*I))
+ if (isa<UsingShadowDecl>(OldD))
continue;
else {
R.clear();
- return ExprError();
+ return true;
}
}
+ // Expand using pack declarations.
+ NamedDecl *SingleDecl = cast<NamedDecl>(InstD);
+ ArrayRef<NamedDecl*> Decls = SingleDecl;
+ if (auto *UPD = dyn_cast<UsingPackDecl>(InstD))
+ Decls = UPD->expansions();
+
// Expand using declarations.
- if (isa<UsingDecl>(InstD)) {
- UsingDecl *UD = cast<UsingDecl>(InstD);
- for (auto *I : UD->shadows())
- R.addDecl(I);
- continue;
+ for (auto *D : Decls) {
+ if (auto *UD = dyn_cast<UsingDecl>(D)) {
+ for (auto *SD : UD->shadows())
+ R.addDecl(SD);
+ } else {
+ R.addDecl(D);
+ }
}
- R.addDecl(InstD);
+ AllEmptyPacks &= Decls.empty();
+ };
+
+ // C++ [temp.res]/8.4.2:
+ // The program is ill-formed, no diagnostic required, if [...] lookup for
+ // a name in the template definition found a using-declaration, but the
+ // lookup in the corresponding scope in the instantiation odoes not find
+ // any declarations because the using-declaration was a pack expansion and
+ // the corresponding pack is empty
+ if (AllEmptyPacks && !RequiresADL) {
+ getSema().Diag(Old->getNameLoc(), diag::err_using_pack_expansion_empty)
+ << isa<UnresolvedMemberExpr>(Old) << Old->getNameInfo().getName();
+ return true;
}
// Resolve a kind, but don't do any further analysis. If it's
// ambiguous, the callee needs to deal with it.
R.resolveKind();
+ return false;
+}
+
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformUnresolvedLookupExpr(
+ UnresolvedLookupExpr *Old) {
+ LookupResult R(SemaRef, Old->getName(), Old->getNameLoc(),
+ Sema::LookupOrdinaryName);
+
+ // Transform the declaration set.
+ if (TransformOverloadExprDecls(Old, Old->requiresADL(), R))
+ return ExprError();
// Rebuild the nested-name qualifier, if present.
CXXScopeSpec SS;
@@ -10222,9 +10417,23 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
CXXMethodDecl *NewCallOperator = getSema().startLambdaDefinition(
Class, E->getIntroducerRange(), NewCallOpTSI,
E->getCallOperator()->getLocEnd(),
- NewCallOpTSI->getTypeLoc().castAs<FunctionProtoTypeLoc>().getParams());
+ NewCallOpTSI->getTypeLoc().castAs<FunctionProtoTypeLoc>().getParams(),
+ E->getCallOperator()->isConstexpr());
+
LSI->CallOperator = NewCallOperator;
+ for (unsigned I = 0, NumParams = NewCallOperator->getNumParams();
+ I != NumParams; ++I) {
+ auto *P = NewCallOperator->getParamDecl(I);
+ if (P->hasUninstantiatedDefaultArg()) {
+ EnterExpressionEvaluationContext Eval(
+ getSema(), Sema::PotentiallyEvaluatedIfUsed, P);
+ ExprResult R = getDerived().TransformExpr(
+ E->getCallOperator()->getParamDecl(I)->getDefaultArg());
+ P->setDefaultArg(R.get());
+ }
+ }
+
getDerived().transformAttrs(E->getCallOperator(), NewCallOperator);
getDerived().transformedLocalDecl(E->getCallOperator(), NewCallOperator);
@@ -10546,35 +10755,9 @@ TreeTransform<Derived>::TransformUnresolvedMemberExpr(UnresolvedMemberExpr *Old)
LookupResult R(SemaRef, Old->getMemberNameInfo(),
Sema::LookupOrdinaryName);
- // Transform all the decls.
- for (UnresolvedMemberExpr::decls_iterator I = Old->decls_begin(),
- E = Old->decls_end(); I != E; ++I) {
- NamedDecl *InstD = static_cast<NamedDecl*>(
- getDerived().TransformDecl(Old->getMemberLoc(),
- *I));
- if (!InstD) {
- // Silently ignore these if a UsingShadowDecl instantiated to nothing.
- // This can happen because of dependent hiding.
- if (isa<UsingShadowDecl>(*I))
- continue;
- else {
- R.clear();
- return ExprError();
- }
- }
-
- // Expand using declarations.
- if (isa<UsingDecl>(InstD)) {
- UsingDecl *UD = cast<UsingDecl>(InstD);
- for (auto *I : UD->shadows())
- R.addDecl(I);
- continue;
- }
-
- R.addDecl(InstD);
- }
-
- R.resolveKind();
+ // Transform the declaration set.
+ if (TransformOverloadExprDecls(Old, /*RequiresADL*/false, R))
+ return ExprError();
// Determine the naming class.
if (Old->getNamingClass()) {
@@ -10704,6 +10887,51 @@ TreeTransform<Derived>::TransformSizeOfPackExpr(SizeOfPackExpr *E) {
E->getRParenLoc(), None, None);
}
+ // Try to compute the result without performing a partial substitution.
+ Optional<unsigned> Result = 0;
+ for (const TemplateArgument &Arg : PackArgs) {
+ if (!Arg.isPackExpansion()) {
+ Result = *Result + 1;
+ continue;
+ }
+
+ TemplateArgumentLoc ArgLoc;
+ InventTemplateArgumentLoc(Arg, ArgLoc);
+
+ // Find the pattern of the pack expansion.
+ SourceLocation Ellipsis;
+ Optional<unsigned> OrigNumExpansions;
+ TemplateArgumentLoc Pattern =
+ getSema().getTemplateArgumentPackExpansionPattern(ArgLoc, Ellipsis,
+ OrigNumExpansions);
+
+ // Substitute under the pack expansion. Do not expand the pack (yet).
+ TemplateArgumentLoc OutPattern;
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1);
+ if (getDerived().TransformTemplateArgument(Pattern, OutPattern,
+ /*Uneval*/ true))
+ return true;
+
+ // See if we can determine the number of arguments from the result.
+ Optional<unsigned> NumExpansions =
+ getSema().getFullyPackExpandedSize(OutPattern.getArgument());
+ if (!NumExpansions) {
+ // No: we must be in an alias template expansion, and we're going to need
+ // to actually expand the packs.
+ Result = None;
+ break;
+ }
+
+ Result = *Result + *NumExpansions;
+ }
+
+ // Common case: we could determine the number of expansions without
+ // substituting.
+ if (Result)
+ return getDerived().RebuildSizeOfPackExpr(E->getOperatorLoc(), E->getPack(),
+ E->getPackLoc(),
+ E->getRParenLoc(), *Result, None);
+
TemplateArgumentListInfo TransformedPackArgs(E->getPackLoc(),
E->getPackLoc());
{
@@ -10716,6 +10944,8 @@ TreeTransform<Derived>::TransformSizeOfPackExpr(SizeOfPackExpr *E) {
return ExprError();
}
+ // Check whether we managed to fully-expand the pack.
+ // FIXME: Is it possible for us to do so and not hit the early exit path?
SmallVector<TemplateArgument, 8> Args;
bool PartialSubstitution = false;
for (auto &Loc : TransformedPackArgs.arguments()) {
@@ -11152,6 +11382,9 @@ TreeTransform<Derived>::TransformObjCMessageExpr(ObjCMessageExpr *E) {
}
else if (E->getReceiverKind() == ObjCMessageExpr::SuperClass ||
E->getReceiverKind() == ObjCMessageExpr::SuperInstance) {
+ if (!E->getMethodDecl())
+ return ExprError();
+
// Build a new class message send to 'super'.
SmallVector<SourceLocation, 16> SelLocs;
E->getSelectorLocs(SelLocs);
@@ -11476,6 +11709,19 @@ TreeTransform<Derived>::RebuildMemberPointerType(QualType PointeeType,
}
template<typename Derived>
+QualType TreeTransform<Derived>::RebuildObjCTypeParamType(
+ const ObjCTypeParamDecl *Decl,
+ SourceLocation ProtocolLAngleLoc,
+ ArrayRef<ObjCProtocolDecl *> Protocols,
+ ArrayRef<SourceLocation> ProtocolLocs,
+ SourceLocation ProtocolRAngleLoc) {
+ return SemaRef.BuildObjCTypeParamType(Decl,
+ ProtocolLAngleLoc, Protocols,
+ ProtocolLocs, ProtocolRAngleLoc,
+ /*FailOnError=*/true);
+}
+
+template<typename Derived>
QualType TreeTransform<Derived>::RebuildObjCObjectType(
QualType BaseType,
SourceLocation Loc,
@@ -11626,21 +11872,48 @@ QualType TreeTransform<Derived>::RebuildFunctionNoProtoType(QualType T) {
}
template<typename Derived>
-QualType TreeTransform<Derived>::RebuildUnresolvedUsingType(Decl *D) {
+QualType TreeTransform<Derived>::RebuildUnresolvedUsingType(SourceLocation Loc,
+ Decl *D) {
assert(D && "no decl found");
if (D->isInvalidDecl()) return QualType();
// FIXME: Doesn't account for ObjCInterfaceDecl!
TypeDecl *Ty;
- if (isa<UsingDecl>(D)) {
- UsingDecl *Using = cast<UsingDecl>(D);
+ if (auto *UPD = dyn_cast<UsingPackDecl>(D)) {
+ // A valid resolved using typename pack expansion decl can have multiple
+ // UsingDecls, but they must each have exactly one type, and it must be
+ // the same type in every case. But we must have at least one expansion!
+ if (UPD->expansions().empty()) {
+ getSema().Diag(Loc, diag::err_using_pack_expansion_empty)
+ << UPD->isCXXClassMember() << UPD;
+ return QualType();
+ }
+
+ // We might still have some unresolved types. Try to pick a resolved type
+ // if we can. The final instantiation will check that the remaining
+ // unresolved types instantiate to the type we pick.
+ QualType FallbackT;
+ QualType T;
+ for (auto *E : UPD->expansions()) {
+ QualType ThisT = RebuildUnresolvedUsingType(Loc, E);
+ if (ThisT.isNull())
+ continue;
+ else if (ThisT->getAs<UnresolvedUsingType>())
+ FallbackT = ThisT;
+ else if (T.isNull())
+ T = ThisT;
+ else
+ assert(getSema().Context.hasSameType(ThisT, T) &&
+ "mismatched resolved types in using pack expansion");
+ }
+ return T.isNull() ? FallbackT : T;
+ } else if (auto *Using = dyn_cast<UsingDecl>(D)) {
assert(Using->hasTypename() &&
"UnresolvedUsingTypenameDecl transformed to non-typename using");
// A valid resolved using typename decl points to exactly one type decl.
assert(++Using->shadow_begin() == Using->shadow_end());
Ty = cast<TypeDecl>((*Using->shadow_begin())->getTargetDecl());
-
} else {
assert(isa<UnresolvedUsingTypenameDecl>(D) &&
"UnresolvedUsingTypenameDecl transformed to non-using decl");
@@ -11690,8 +11963,10 @@ QualType TreeTransform<Derived>::RebuildAtomicType(QualType ValueType,
template<typename Derived>
QualType TreeTransform<Derived>::RebuildPipeType(QualType ValueType,
- SourceLocation KWLoc) {
- return SemaRef.BuildPipeType(ValueType, KWLoc);
+ SourceLocation KWLoc,
+ bool isReadPipe) {
+ return isReadPipe ? SemaRef.BuildReadPipeType(ValueType, KWLoc)
+ : SemaRef.BuildWritePipeType(ValueType, KWLoc);
}
template<typename Derived>
diff --git a/lib/Sema/TypeLocBuilder.h b/lib/Sema/TypeLocBuilder.h
index 382821859768..9c77045d2e12 100644
--- a/lib/Sema/TypeLocBuilder.h
+++ b/lib/Sema/TypeLocBuilder.h
@@ -39,7 +39,7 @@ class TypeLocBuilder {
#endif
/// The inline buffer.
- enum { BufferMaxAlignment = llvm::AlignOf<void*>::Alignment };
+ enum { BufferMaxAlignment = alignof(void *) };
llvm::AlignedCharArray<BufferMaxAlignment, InlineCapacity> InlineBuffer;
unsigned NumBytesAtAlign4, NumBytesAtAlign8;
diff --git a/lib/Serialization/ASTCommon.cpp b/lib/Serialization/ASTCommon.cpp
index 22ead2b57c72..ecd249cc5025 100644
--- a/lib/Serialization/ASTCommon.cpp
+++ b/lib/Serialization/ASTCommon.cpp
@@ -183,6 +183,7 @@ serialization::getDefinitiveDeclContext(const DeclContext *DC) {
case Decl::ExternCContext:
case Decl::Namespace:
case Decl::LinkageSpec:
+ case Decl::Export:
return nullptr;
// C/C++ tag types can only be defined in one place.
@@ -284,6 +285,7 @@ bool serialization::isRedeclarableDeclKind(unsigned Kind) {
case Decl::NonTypeTemplateParm:
case Decl::TemplateTemplateParm:
case Decl::Using:
+ case Decl::UsingPack:
case Decl::ObjCMethod:
case Decl::ObjCCategory:
case Decl::ObjCCategoryImpl:
@@ -291,6 +293,7 @@ bool serialization::isRedeclarableDeclKind(unsigned Kind) {
case Decl::ObjCProperty:
case Decl::ObjCCompatibleAlias:
case Decl::LinkageSpec:
+ case Decl::Export:
case Decl::ObjCPropertyImpl:
case Decl::PragmaComment:
case Decl::PragmaDetectMismatch:
@@ -307,6 +310,8 @@ bool serialization::isRedeclarableDeclKind(unsigned Kind) {
case Decl::OMPCapturedExpr:
case Decl::OMPDeclareReduction:
case Decl::BuiltinTemplate:
+ case Decl::Decomposition:
+ case Decl::Binding:
return false;
// These indirectly derive from Redeclarable<T> but are not actually
diff --git a/lib/Serialization/ASTCommon.h b/lib/Serialization/ASTCommon.h
index 641165e4178f..cbc5f04738b1 100644
--- a/lib/Serialization/ASTCommon.h
+++ b/lib/Serialization/ASTCommon.h
@@ -30,6 +30,7 @@ enum DeclUpdateKind {
UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER,
UPD_CXX_INSTANTIATED_CLASS_DEFINITION,
UPD_CXX_INSTANTIATED_DEFAULT_ARGUMENT,
+ UPD_CXX_INSTANTIATED_DEFAULT_MEMBER_INITIALIZER,
UPD_CXX_RESOLVED_DTOR_DELETE,
UPD_CXX_RESOLVED_EXCEPTION_SPEC,
UPD_CXX_DEDUCED_RETURN_TYPE,
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index 9d1554a826aa..fe2c53b77e1d 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -1,4 +1,4 @@
-//===-- ASTReader.cpp - AST File Reader ----------------------------------===//
+//===-- ASTReader.cpp - AST File Reader -----------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -16,39 +16,62 @@
#include "ASTReaderInternals.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTMutationListener.h"
+#include "clang/AST/ASTUnresolvedSet.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclGroup.h"
+#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
-#include "clang/Frontend/PCHContainerOperations.h"
-#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/RawCommentList.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeLocVisitor.h"
+#include "clang/AST/UnresolvedSet.h"
+#include "clang/Basic/CommentOptions.h"
#include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Basic/ExceptionSpecificationType.h"
#include "clang/Basic/FileManager.h"
+#include "clang/Basic/FileSystemOptions.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/ObjCRuntime.h"
+#include "clang/Basic/OperatorKinds.h"
+#include "clang/Basic/Sanitizers.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/SourceManagerInternals.h"
+#include "clang/Basic/Specifiers.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TargetOptions.h"
+#include "clang/Basic/TokenKinds.h"
#include "clang/Basic/Version.h"
#include "clang/Basic/VersionTuple.h"
-#include "clang/Frontend/Utils.h"
+#include "clang/Frontend/PCHContainerOperations.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/ModuleMap.h"
#include "clang/Lex/PreprocessingRecord.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/Sema.h"
+#include "clang/Sema/Weak.h"
#include "clang/Serialization/ASTDeserializationListener.h"
#include "clang/Serialization/GlobalModuleIndex.h"
#include "clang/Serialization/ModuleManager.h"
#include "clang/Serialization/SerializationDiagnostic.h"
+#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/Triple.h"
#include "llvm/Bitcode/BitstreamReader.h"
#include "llvm/Support/Compression.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -56,16 +79,27 @@
#include "llvm/Support/SaveAndRestore.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
+#include <cassert>
+#include <cstdint>
#include <cstdio>
+#include <cstring>
+#include <ctime>
#include <iterator>
+#include <limits>
+#include <map>
+#include <memory>
+#include <new>
+#include <string>
#include <system_error>
+#include <tuple>
+#include <utility>
+#include <vector>
using namespace clang;
using namespace clang::serialization;
using namespace clang::serialization::reader;
using llvm::BitstreamCursor;
-
//===----------------------------------------------------------------------===//
// ChainedASTReaderListener implementation
//===----------------------------------------------------------------------===//
@@ -75,14 +109,17 @@ ChainedASTReaderListener::ReadFullVersionInformation(StringRef FullVersion) {
return First->ReadFullVersionInformation(FullVersion) ||
Second->ReadFullVersionInformation(FullVersion);
}
+
void ChainedASTReaderListener::ReadModuleName(StringRef ModuleName) {
First->ReadModuleName(ModuleName);
Second->ReadModuleName(ModuleName);
}
+
void ChainedASTReaderListener::ReadModuleMapFile(StringRef ModuleMapPath) {
First->ReadModuleMapFile(ModuleMapPath);
Second->ReadModuleMapFile(ModuleMapPath);
}
+
bool
ChainedASTReaderListener::ReadLanguageOptions(const LangOptions &LangOpts,
bool Complain,
@@ -92,6 +129,7 @@ ChainedASTReaderListener::ReadLanguageOptions(const LangOptions &LangOpts,
Second->ReadLanguageOptions(LangOpts, Complain,
AllowCompatibleDifferences);
}
+
bool ChainedASTReaderListener::ReadTargetOptions(
const TargetOptions &TargetOpts, bool Complain,
bool AllowCompatibleDifferences) {
@@ -100,11 +138,13 @@ bool ChainedASTReaderListener::ReadTargetOptions(
Second->ReadTargetOptions(TargetOpts, Complain,
AllowCompatibleDifferences);
}
+
bool ChainedASTReaderListener::ReadDiagnosticOptions(
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts, bool Complain) {
return First->ReadDiagnosticOptions(DiagOpts, Complain) ||
Second->ReadDiagnosticOptions(DiagOpts, Complain);
}
+
bool
ChainedASTReaderListener::ReadFileSystemOptions(const FileSystemOptions &FSOpts,
bool Complain) {
@@ -120,6 +160,7 @@ bool ChainedASTReaderListener::ReadHeaderSearchOptions(
Second->ReadHeaderSearchOptions(HSOpts, SpecificModuleCachePath,
Complain);
}
+
bool ChainedASTReaderListener::ReadPreprocessorOptions(
const PreprocessorOptions &PPOpts, bool Complain,
std::string &SuggestedPredefines) {
@@ -145,6 +186,7 @@ void ChainedASTReaderListener::visitModuleFile(StringRef Filename,
First->visitModuleFile(Filename, Kind);
Second->visitModuleFile(Filename, Kind);
}
+
bool ChainedASTReaderListener::visitInputFile(StringRef Filename,
bool isSystem,
bool isOverridden,
@@ -336,11 +378,13 @@ bool PCHValidator::ReadTargetOptions(const TargetOptions &TargetOpts,
}
namespace {
+
typedef llvm::StringMap<std::pair<StringRef, bool /*IsUndef*/> >
MacroDefinitionsMap;
typedef llvm::DenseMap<DeclarationName, SmallVector<NamedDecl *, 8> >
DeclsMap;
-}
+
+} // end anonymous namespace
static bool checkDiagnosticGroupMappings(DiagnosticsEngine &StoredDiags,
DiagnosticsEngine &Diags,
@@ -496,12 +540,16 @@ collectMacroDefinitions(const PreprocessorOptions &PPOpts,
/// against the preprocessor options in an existing preprocessor.
///
/// \param Diags If non-null, produce diagnostics for any mismatches incurred.
+/// \param Validate If true, validate preprocessor options. If false, allow
+/// macros defined by \p ExistingPPOpts to override those defined by
+/// \p PPOpts in SuggestedPredefines.
static bool checkPreprocessorOptions(const PreprocessorOptions &PPOpts,
const PreprocessorOptions &ExistingPPOpts,
DiagnosticsEngine *Diags,
FileManager &FileMgr,
std::string &SuggestedPredefines,
- const LangOptions &LangOpts) {
+ const LangOptions &LangOpts,
+ bool Validate = true) {
// Check macro definitions.
MacroDefinitionsMap ASTFileMacros;
collectMacroDefinitions(PPOpts, ASTFileMacros);
@@ -517,7 +565,7 @@ static bool checkPreprocessorOptions(const PreprocessorOptions &PPOpts,
// Check whether we know anything about this macro name or not.
llvm::StringMap<std::pair<StringRef, bool /*IsUndef*/> >::iterator Known
= ASTFileMacros.find(MacroName);
- if (Known == ASTFileMacros.end()) {
+ if (!Validate || Known == ASTFileMacros.end()) {
// FIXME: Check whether this identifier was referenced anywhere in the
// AST file. If so, we should reject the AST file. Unfortunately, this
// information isn't in the control block. What shall we do about it?
@@ -560,7 +608,7 @@ static bool checkPreprocessorOptions(const PreprocessorOptions &PPOpts,
}
// Check whether we're using predefines.
- if (PPOpts.UsePredefines != ExistingPPOpts.UsePredefines) {
+ if (PPOpts.UsePredefines != ExistingPPOpts.UsePredefines && Validate) {
if (Diags) {
Diags->Report(diag::err_pch_undef) << ExistingPPOpts.UsePredefines;
}
@@ -569,7 +617,7 @@ static bool checkPreprocessorOptions(const PreprocessorOptions &PPOpts,
// Detailed record is important since it is used for the module cache hash.
if (LangOpts.Modules &&
- PPOpts.DetailedRecord != ExistingPPOpts.DetailedRecord) {
+ PPOpts.DetailedRecord != ExistingPPOpts.DetailedRecord && Validate) {
if (Diags) {
Diags->Report(diag::err_pch_pp_detailed_record) << PPOpts.DetailedRecord;
}
@@ -618,6 +666,19 @@ bool PCHValidator::ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,
PP.getLangOpts());
}
+bool SimpleASTReaderListener::ReadPreprocessorOptions(
+ const PreprocessorOptions &PPOpts,
+ bool Complain,
+ std::string &SuggestedPredefines) {
+ return checkPreprocessorOptions(PPOpts,
+ PP.getPreprocessorOpts(),
+ nullptr,
+ PP.getFileManager(),
+ SuggestedPredefines,
+ PP.getLangOpts(),
+ false);
+}
+
/// Check the header search options deserialized from the control block
/// against the header search options in an existing preprocessor.
///
@@ -662,13 +723,10 @@ void ASTReader::setDeserializationListener(ASTDeserializationListener *Listener,
OwnsDeserializationListener = TakeOwnership;
}
-
-
unsigned ASTSelectorLookupTrait::ComputeHash(Selector Sel) {
return serialization::ComputeHash(Sel);
}
-
std::pair<unsigned, unsigned>
ASTSelectorLookupTrait::ReadKeyDataLength(const unsigned char*& d) {
using namespace llvm::support;
@@ -677,7 +735,7 @@ ASTSelectorLookupTrait::ReadKeyDataLength(const unsigned char*& d) {
return std::make_pair(KeyLen, DataLen);
}
-ASTSelectorLookupTrait::internal_key_type
+ASTSelectorLookupTrait::internal_key_type
ASTSelectorLookupTrait::ReadKey(const unsigned char* d, unsigned) {
using namespace llvm::support;
SelectorTable &SelTable = Reader.getContext().Selectors;
@@ -698,8 +756,8 @@ ASTSelectorLookupTrait::ReadKey(const unsigned char* d, unsigned) {
return SelTable.getSelector(N, Args.data());
}
-ASTSelectorLookupTrait::data_type
-ASTSelectorLookupTrait::ReadData(Selector, const unsigned char* d,
+ASTSelectorLookupTrait::data_type
+ASTSelectorLookupTrait::ReadData(Selector, const unsigned char* d,
unsigned DataLen) {
using namespace llvm::support;
@@ -1138,7 +1196,7 @@ bool ASTReader::ReadSourceManagerBlock(ModuleFile &F) {
RecordData Record;
while (true) {
llvm::BitstreamEntry E = SLocEntryCursor.advanceSkippingSubblocks();
-
+
switch (E.Kind) {
case llvm::BitstreamEntry::SubBlock: // Handled for us already.
case llvm::BitstreamEntry::Error:
@@ -1150,7 +1208,7 @@ bool ASTReader::ReadSourceManagerBlock(ModuleFile &F) {
// The interesting case.
break;
}
-
+
// Read a record.
Record.clear();
StringRef Blob;
@@ -1246,7 +1304,7 @@ bool ASTReader::ReadSLocEntry(int ID) {
Error("incorrectly-formatted source location entry in AST file");
return true;
}
-
+
RecordData Record;
StringRef Blob;
switch (SLocEntryCursor.readRecord(Entry.ID, Record, &Blob)) {
@@ -1312,8 +1370,7 @@ bool ASTReader::ReadSLocEntry(int ID) {
SrcMgr::CharacteristicKind
FileCharacter = (SrcMgr::CharacteristicKind)Record[2];
SourceLocation IncludeLoc = ReadSourceLocation(*F, Record[1]);
- if (IncludeLoc.isInvalid() &&
- (F->Kind == MK_ImplicitModule || F->Kind == MK_ExplicitModule)) {
+ if (IncludeLoc.isInvalid() && F->isModule()) {
IncludeLoc = getImportLocation(F);
}
@@ -1351,7 +1408,7 @@ std::pair<SourceLocation, StringRef> ASTReader::getModuleImportLoc(int ID) {
// Find which module file this entry lands in.
ModuleFile *M = GlobalSLocEntryMap.find(-ID)->second;
- if (M->Kind != MK_ImplicitModule && M->Kind != MK_ExplicitModule)
+ if (!M->isModule())
return std::make_pair(SourceLocation(), "");
// FIXME: Can we map this down to a particular submodule? That would be
@@ -1363,7 +1420,7 @@ std::pair<SourceLocation, StringRef> ASTReader::getModuleImportLoc(int ID) {
SourceLocation ASTReader::getImportLocation(ModuleFile *F) {
if (F->ImportLoc.isValid())
return F->ImportLoc;
-
+
// Otherwise we have a PCH. It's considered to be "imported" at the first
// location of its includer.
if (F->ImportedBy.empty() || !F->ImportedBy[0]) {
@@ -1425,7 +1482,7 @@ MacroInfo *ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset) {
// be able to reseek within the block and read entries.
unsigned Flags = BitstreamCursor::AF_DontPopBlockAtEnd;
llvm::BitstreamEntry Entry = Stream.advanceSkippingSubblocks(Flags);
-
+
switch (Entry.Kind) {
case llvm::BitstreamEntry::SubBlock: // Handled for us already.
case llvm::BitstreamEntry::Error:
@@ -1517,13 +1574,13 @@ MacroInfo *ASTReader::ReadMacroRecord(ModuleFile &F, uint64_t Offset) {
}
}
-PreprocessedEntityID
+PreprocessedEntityID
ASTReader::getGlobalPreprocessedEntityID(ModuleFile &M, unsigned LocalID) const {
- ContinuousRangeMap<uint32_t, int, 2>::const_iterator
+ ContinuousRangeMap<uint32_t, int, 2>::const_iterator
I = M.PreprocessedEntityRemap.find(LocalID - NUM_PREDEF_PP_ENTITY_IDS);
- assert(I != M.PreprocessedEntityRemap.end()
+ assert(I != M.PreprocessedEntityRemap.end()
&& "Invalid index into preprocessed entity index remap");
-
+
return LocalID + I->second;
}
@@ -1531,22 +1588,21 @@ unsigned HeaderFileInfoTrait::ComputeHash(internal_key_ref ikey) {
return llvm::hash_combine(ikey.Size, ikey.ModTime);
}
-HeaderFileInfoTrait::internal_key_type
+HeaderFileInfoTrait::internal_key_type
HeaderFileInfoTrait::GetInternalKey(const FileEntry *FE) {
internal_key_type ikey = {FE->getSize(),
M.HasTimestamps ? FE->getModificationTime() : 0,
FE->getName(), /*Imported*/ false};
return ikey;
}
-
+
bool HeaderFileInfoTrait::EqualKey(internal_key_ref a, internal_key_ref b) {
if (a.Size != b.Size || (a.ModTime && b.ModTime && a.ModTime != b.ModTime))
return false;
- if (llvm::sys::path::is_absolute(a.Filename) &&
- strcmp(a.Filename, b.Filename) == 0)
+ if (llvm::sys::path::is_absolute(a.Filename) && a.Filename == b.Filename)
return true;
-
+
// Determine whether the actual files are equivalent.
FileManager &FileMgr = Reader.getFileManager();
auto GetFile = [&](const internal_key_type &Key) -> const FileEntry* {
@@ -1562,7 +1618,7 @@ bool HeaderFileInfoTrait::EqualKey(internal_key_ref a, internal_key_ref b) {
const FileEntry *FEB = GetFile(b);
return FEA && FEA == FEB;
}
-
+
std::pair<unsigned, unsigned>
HeaderFileInfoTrait::ReadKeyDataLength(const unsigned char*& d) {
using namespace llvm::support;
@@ -1582,7 +1638,7 @@ HeaderFileInfoTrait::ReadKey(const unsigned char *d, unsigned) {
return ikey;
}
-HeaderFileInfoTrait::data_type
+HeaderFileInfoTrait::data_type
HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d,
unsigned DataLen) {
const unsigned char *End = d + DataLen;
@@ -1602,7 +1658,7 @@ HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d,
M, endian::readNext<uint32_t, little, unaligned>(d));
if (unsigned FrameworkOffset =
endian::readNext<uint32_t, little, unaligned>(d)) {
- // The framework offset is 1 greater than the actual offset,
+ // The framework offset is 1 greater than the actual offset,
// since 0 is used as an indicator for "no framework name".
StringRef FrameworkName(FrameworkStrings + FrameworkOffset - 1);
HFI.Framework = HS->getUniqueFrameworkName(FrameworkName);
@@ -1655,7 +1711,7 @@ void ASTReader::ReadDefinedMacros() {
BitstreamCursor &MacroCursor = I->MacroCursor;
// If there was no preprocessor block, skip this file.
- if (!MacroCursor.getBitStreamReader())
+ if (MacroCursor.getBitcodeBytes().empty())
continue;
BitstreamCursor Cursor = MacroCursor;
@@ -1664,7 +1720,7 @@ void ASTReader::ReadDefinedMacros() {
RecordData Record;
while (true) {
llvm::BitstreamEntry E = Cursor.advanceSkippingSubblocks();
-
+
switch (E.Kind) {
case llvm::BitstreamEntry::SubBlock: // Handled for us already.
case llvm::BitstreamEntry::Error:
@@ -1672,13 +1728,13 @@ void ASTReader::ReadDefinedMacros() {
return;
case llvm::BitstreamEntry::EndBlock:
goto NextCursor;
-
+
case llvm::BitstreamEntry::Record:
Record.clear();
switch (Cursor.readRecord(E.ID, Record)) {
default: // Default behavior: ignore.
break;
-
+
case PP_MACRO_OBJECT_LIKE:
case PP_MACRO_FUNCTION_LIKE: {
IdentifierInfo *II = getLocalIdentifier(*I, Record[0]);
@@ -1686,7 +1742,7 @@ void ASTReader::ReadDefinedMacros() {
updateOutOfDateIdentifier(*II);
break;
}
-
+
case PP_TOKEN:
// Ignore tokens.
break;
@@ -1699,6 +1755,7 @@ void ASTReader::ReadDefinedMacros() {
}
namespace {
+
/// \brief Visitor class used to look up identifirs in an AST file.
class IdentifierLookupVisitor {
StringRef Name;
@@ -1737,7 +1794,7 @@ namespace {
IdTable->find_hashed(Name, NameHash, &Trait);
if (Pos == IdTable->end())
return false;
-
+
// Dereferencing the iterator has the effect of building the
// IdentifierInfo node and populating it with the various
// declarations it needs.
@@ -1745,12 +1802,13 @@ namespace {
Found = *Pos;
return true;
}
-
+
// \brief Retrieve the identifier info found within the module
// files.
IdentifierInfo *getIdentifierInfo() const { return Found; }
};
-}
+
+} // end anonymous namespace
void ASTReader::updateOutOfDateIdentifier(IdentifierInfo &II) {
// Note that we are loading an identifier.
@@ -1780,7 +1838,7 @@ void ASTReader::updateOutOfDateIdentifier(IdentifierInfo &II) {
void ASTReader::markIdentifierUpToDate(IdentifierInfo *II) {
if (!II)
return;
-
+
II->setOutOfDate(false);
// Update the generation for this identifier.
@@ -1861,7 +1919,7 @@ void ASTReader::resolvePendingMacro(IdentifierInfo *II,
// Don't read the directive history for a module; we don't have anywhere
// to put it.
- if (M.Kind == MK_ImplicitModule || M.Kind == MK_ExplicitModule)
+ if (M.isModule())
return;
// Deserialize the macro directives history in reverse source-order.
@@ -1895,7 +1953,7 @@ void ASTReader::resolvePendingMacro(IdentifierInfo *II,
}
if (Latest)
- PP.setLoadedMacroDirective(II, Latest);
+ PP.setLoadedMacroDirective(II, Earliest, Latest);
}
ASTReader::InputFileInfo
@@ -1925,6 +1983,7 @@ ASTReader::readInputFileInfo(ModuleFile &F, unsigned ID) {
return R;
}
+static unsigned moduleKindForDiagnostic(ModuleKind Kind);
InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
// If this ID is bogus, just return an empty input file.
if (ID == 0 || ID > F.InputFilesLoaded.size())
@@ -1941,7 +2000,7 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
BitstreamCursor &Cursor = F.InputFilesCursor;
SavedStreamPosition SavedPosition(Cursor);
Cursor.JumpToBit(F.InputFileOffsets[ID-1]);
-
+
InputFileInfo FI = readInputFileInfo(F, ID);
off_t StoredSize = FI.StoredSize;
time_t StoredTime = FI.StoredTime;
@@ -1974,7 +2033,7 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
ErrorStr += "' referenced by AST file '";
ErrorStr += F.FileName;
ErrorStr += "'";
- Error(ErrorStr.c_str());
+ Error(ErrorStr);
}
// Record that we didn't find the file.
F.InputFilesLoaded[ID-1] = InputFile::getNotFound();
@@ -2021,7 +2080,13 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
// The top-level PCH is stale.
StringRef TopLevelPCHName(ImportStack.back()->FileName);
- Error(diag::err_fe_pch_file_modified, Filename, TopLevelPCHName);
+ unsigned DiagnosticKind = moduleKindForDiagnostic(ImportStack.back()->Kind);
+ if (DiagnosticKind == 0)
+ Error(diag::err_fe_pch_file_modified, Filename, TopLevelPCHName);
+ else if (DiagnosticKind == 1)
+ Error(diag::err_fe_module_file_modified, Filename, TopLevelPCHName);
+ else
+ Error(diag::err_fe_ast_file_modified, Filename, TopLevelPCHName);
// Print the import stack.
if (ImportStack.size() > 1 && !Diags.isDiagnosticInFlight()) {
@@ -2084,16 +2149,16 @@ static bool isDiagnosedResult(ASTReader::ASTReadResult ARR, unsigned Caps) {
ASTReader::ASTReadResult ASTReader::ReadOptionsBlock(
BitstreamCursor &Stream, unsigned ClientLoadCapabilities,
bool AllowCompatibleConfigurationMismatch, ASTReaderListener &Listener,
- std::string &SuggestedPredefines) {
+ std::string &SuggestedPredefines, bool ValidateDiagnosticOptions) {
if (Stream.EnterSubBlock(OPTIONS_BLOCK_ID))
return Failure;
// Read all of the records in the options block.
RecordData Record;
ASTReadResult Result = Success;
- while (1) {
+ while (true) {
llvm::BitstreamEntry Entry = Stream.advance();
-
+
switch (Entry.Kind) {
case llvm::BitstreamEntry::Error:
case llvm::BitstreamEntry::SubBlock:
@@ -2128,7 +2193,8 @@ ASTReader::ASTReadResult ASTReader::ReadOptionsBlock(
case DIAGNOSTIC_OPTIONS: {
bool Complain = (ClientLoadCapabilities & ARR_OutOfDate) == 0;
- if (!AllowCompatibleConfigurationMismatch &&
+ if (ValidateDiagnosticOptions &&
+ !AllowCompatibleConfigurationMismatch &&
ParseDiagnosticOptions(Record, Complain, Listener))
return OutOfDate;
break;
@@ -2178,9 +2244,9 @@ ASTReader::ReadControlBlock(ModuleFile &F,
RecordData Record;
unsigned NumInputs = 0;
unsigned NumUserInputs = 0;
- while (1) {
+ while (true) {
llvm::BitstreamEntry Entry = Stream.advance();
-
+
switch (Entry.Kind) {
case llvm::BitstreamEntry::Error:
Error("malformed block record in AST file");
@@ -2193,7 +2259,8 @@ ASTReader::ReadControlBlock(ModuleFile &F,
// All user input files reside at the index range [0, NumUserInputs), and
// system input files reside at [NumUserInputs, NumInputs). For explicitly
// loaded module files, ignore missing inputs.
- if (!DisableValidation && F.Kind != MK_ExplicitModule) {
+ if (!DisableValidation && F.Kind != MK_ExplicitModule &&
+ F.Kind != MK_PrebuiltModule) {
bool Complain = (ClientLoadCapabilities & ARR_OutOfDate) == 0;
// If we are reading a module, we will create a verification timestamp,
@@ -2224,7 +2291,8 @@ ASTReader::ReadControlBlock(ModuleFile &F,
bool IsSystem = I >= NumUserInputs;
InputFileInfo FI = readInputFileInfo(F, I+1);
Listener->visitInputFile(FI.Filename, IsSystem, FI.Overridden,
- F.Kind == MK_ExplicitModule);
+ F.Kind == MK_ExplicitModule ||
+ F.Kind == MK_PrebuiltModule);
}
}
@@ -2254,11 +2322,14 @@ ASTReader::ReadControlBlock(ModuleFile &F,
//
// FIXME: Allow this for files explicitly specified with -include-pch.
bool AllowCompatibleConfigurationMismatch =
- F.Kind == MK_ExplicitModule;
+ F.Kind == MK_ExplicitModule || F.Kind == MK_PrebuiltModule;
+ const HeaderSearchOptions &HSOpts =
+ PP.getHeaderSearchInfo().getHeaderSearchOpts();
Result = ReadOptionsBlock(Stream, ClientLoadCapabilities,
AllowCompatibleConfigurationMismatch,
- *Listener, SuggestedPredefines);
+ *Listener, SuggestedPredefines,
+ HSOpts.ModulesValidateDiagnosticOptions);
if (Result == Failure) {
Error("malformed block record in AST file");
return Result;
@@ -2278,7 +2349,7 @@ ASTReader::ReadControlBlock(ModuleFile &F,
return Failure;
}
continue;
-
+
default:
if (Stream.SkipBlock()) {
Error("malformed block record in AST file");
@@ -2286,7 +2357,7 @@ ASTReader::ReadControlBlock(ModuleFile &F,
}
continue;
}
-
+
case llvm::BitstreamEntry::Record:
// The interesting case.
break;
@@ -2338,7 +2409,7 @@ ASTReader::ReadControlBlock(ModuleFile &F,
break;
case IMPORTS: {
- // Load each of the imported PCH files.
+ // Load each of the imported PCH files.
unsigned Idx = 0, N = Record.size();
while (Idx < N) {
// Read information about the AST file.
@@ -2413,7 +2484,7 @@ ASTReader::ReadControlBlock(ModuleFile &F,
if (M && M->Directory) {
// If we're implicitly loading a module, the base directory can't
// change between the build and use.
- if (F.Kind != MK_ExplicitModule) {
+ if (F.Kind != MK_ExplicitModule && F.Kind != MK_PrebuiltModule) {
const DirectoryEntry *BuildDir =
PP.getFileManager().getDirectory(Blob);
if (!BuildDir || BuildDir != M->Directory) {
@@ -2458,9 +2529,9 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
// Read all of the records and blocks for the AST file.
RecordData Record;
- while (1) {
+ while (true) {
llvm::BitstreamEntry Entry = Stream.advance();
-
+
switch (Entry.Kind) {
case llvm::BitstreamEntry::Error:
Error("error at end of module block in AST file");
@@ -2475,7 +2546,7 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
if (DC->hasExternalLexicalStorage() &&
!getContext().getLangOpts().CPlusPlus)
DC->setMustBuildLookupTable();
-
+
return Success;
}
case llvm::BitstreamEntry::SubBlock:
@@ -2498,7 +2569,7 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
F.MacroCursor = Stream;
if (!PP.getExternalSource())
PP.setExternalSource(this);
-
+
if (Stream.SkipBlock() ||
ReadBlockAbbrevs(F.MacroCursor, PREPROCESSOR_BLOCK_ID)) {
Error("malformed block record in AST file");
@@ -2506,7 +2577,7 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
}
F.MacroStartOffset = F.MacroCursor.GetCurrentBitNo();
break;
-
+
case PREPROCESSOR_DETAIL_BLOCK_ID:
F.PreprocessorDetailCursor = Stream;
if (Stream.SkipBlock() ||
@@ -2517,23 +2588,23 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
}
F.PreprocessorDetailStartOffset
= F.PreprocessorDetailCursor.GetCurrentBitNo();
-
+
if (!PP.getPreprocessingRecord())
PP.createPreprocessingRecord();
if (!PP.getPreprocessingRecord()->getExternalSource())
PP.getPreprocessingRecord()->SetExternalSource(*this);
break;
-
+
case SOURCE_MANAGER_BLOCK_ID:
if (ReadSourceManagerBlock(F))
return Failure;
break;
-
+
case SUBMODULE_BLOCK_ID:
if (ASTReadResult Result = ReadSubmoduleBlock(F, ClientLoadCapabilities))
return Result;
break;
-
+
case COMMENTS_BLOCK_ID: {
BitstreamCursor C = Stream;
if (Stream.SkipBlock() ||
@@ -2544,7 +2615,7 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
CommentsCursors.push_back(std::make_pair(C, &F));
break;
}
-
+
default:
if (Stream.SkipBlock()) {
Error("malformed block record in AST file");
@@ -2553,7 +2624,7 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
break;
}
continue;
-
+
case llvm::BitstreamEntry::Record:
// The interesting case.
break;
@@ -2575,21 +2646,21 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
F.LocalNumTypes = Record[0];
unsigned LocalBaseTypeIndex = Record[1];
F.BaseTypeIndex = getTotalNumTypes();
-
+
if (F.LocalNumTypes > 0) {
// Introduce the global -> local mapping for types within this module.
GlobalTypeMap.insert(std::make_pair(getTotalNumTypes(), &F));
-
+
// Introduce the local -> global mapping for types within this module.
F.TypeRemap.insertOrReplace(
- std::make_pair(LocalBaseTypeIndex,
+ std::make_pair(LocalBaseTypeIndex,
F.BaseTypeIndex - LocalBaseTypeIndex));
TypesLoaded.resize(TypesLoaded.size() + F.LocalNumTypes);
}
break;
}
-
+
case DECL_OFFSET: {
if (F.LocalNumDecls != 0) {
Error("duplicate DECL_OFFSET record in AST file");
@@ -2599,18 +2670,18 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
F.LocalNumDecls = Record[0];
unsigned LocalBaseDeclID = Record[1];
F.BaseDeclID = getTotalNumDecls();
-
+
if (F.LocalNumDecls > 0) {
- // Introduce the global -> local mapping for declarations within this
+ // Introduce the global -> local mapping for declarations within this
// module.
GlobalDeclMap.insert(
std::make_pair(getTotalNumDecls() + NUM_PREDEF_DECL_IDS, &F));
-
+
// Introduce the local -> global mapping for declarations within this
// module.
F.DeclRemap.insertOrReplace(
std::make_pair(LocalBaseDeclID, F.BaseDeclID - LocalBaseDeclID));
-
+
// Introduce the global -> local mapping for declarations within this
// module.
F.GlobalToLocalDeclIDs[&F] = LocalBaseDeclID;
@@ -2619,7 +2690,7 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
}
break;
}
-
+
case TU_UPDATE_LEXICAL: {
DeclContext *TU = Context.getTranslationUnitDecl();
LexicalContents Contents(
@@ -2651,7 +2722,7 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
(const unsigned char *)F.IdentifierTableData + sizeof(uint32_t),
(const unsigned char *)F.IdentifierTableData,
ASTIdentifierLookupTrait(*this, F));
-
+
PP.getIdentifierTable().setExternalIdentifierLookup(this);
}
break;
@@ -2665,13 +2736,13 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
F.LocalNumIdentifiers = Record[0];
unsigned LocalBaseIdentifierID = Record[1];
F.BaseIdentifierID = getTotalNumIdentifiers();
-
+
if (F.LocalNumIdentifiers > 0) {
// Introduce the global -> local mapping for identifiers within this
// module.
- GlobalIdentifierMap.insert(std::make_pair(getTotalNumIdentifiers() + 1,
+ GlobalIdentifierMap.insert(std::make_pair(getTotalNumIdentifiers() + 1,
&F));
-
+
// Introduce the local -> global mapping for identifiers within this
// module.
F.IdentifierRemap.insertOrReplace(
@@ -2738,11 +2809,11 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
Error("invalid weak identifiers record");
return Failure;
}
-
- // FIXME: Ignore weak undeclared identifiers from non-original PCH
+
+ // FIXME: Ignore weak undeclared identifiers from non-original PCH
// files. This isn't the way to do it :)
WeakUndeclaredIdentifiers.clear();
-
+
// Translate the weak, undeclared identifiers into global IDs.
for (unsigned I = 0, N = Record.size(); I < N; /* in loop */) {
WeakUndeclaredIdentifiers.push_back(
@@ -2760,13 +2831,13 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
F.LocalNumSelectors = Record[0];
unsigned LocalBaseSelectorID = Record[1];
F.BaseSelectorID = getTotalNumSelectors();
-
+
if (F.LocalNumSelectors > 0) {
- // Introduce the global -> local mapping for selectors within this
+ // Introduce the global -> local mapping for selectors within this
// module.
GlobalSelectorMap.insert(std::make_pair(getTotalNumSelectors()+1, &F));
-
- // Introduce the local -> global mapping for selectors within this
+
+ // Introduce the local -> global mapping for selectors within this
// module.
F.SelectorRemap.insertOrReplace(
std::make_pair(LocalBaseSelectorID,
@@ -2776,7 +2847,7 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
}
break;
}
-
+
case METHOD_POOL:
F.SelectorLookupTableData = (const unsigned char *)Blob.data();
if (Record[0])
@@ -2791,7 +2862,7 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
case REFERENCED_SELECTOR_POOL:
if (!Record.empty()) {
for (unsigned Idx = 0, N = Record.size() - 1; Idx < N; /* in loop */) {
- ReferencedSelectorsData.push_back(getGlobalSelectorID(F,
+ ReferencedSelectorsData.push_back(getGlobalSelectorID(F,
Record[Idx++]));
ReferencedSelectorsData.push_back(ReadSourceLocation(F, Record, Idx).
getRawEncoding());
@@ -2803,7 +2874,7 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
if (!Record.empty() && Listener)
Listener->ReadCounter(F, Record[0]);
break;
-
+
case FILE_SORTED_DECLS:
F.FileSortedDecls = (const DeclID *)Blob.data();
F.NumFileSortedDecls = Record[0];
@@ -2840,7 +2911,7 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
// This module. Base was 2 when being compiled.
F.SLocRemap.insertOrReplace(std::make_pair(2U,
static_cast<int>(F.SLocEntryBaseOffset - 2)));
-
+
TotalNumSLocEntries += F.LocalNumSLocEntries;
break;
}
@@ -2932,7 +3003,7 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
Error("Multiple SOURCE_LOCATION_PRELOADS records in AST file");
return Failure;
}
-
+
F.PreloadSLocEntries.swap(Record);
break;
}
@@ -2947,12 +3018,12 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
Error("Invalid VTABLE_USES record");
return Failure;
}
-
+
// Later tables overwrite earlier ones.
// FIXME: Modules will have some trouble with this. This is clearly not
// the right way to do this.
VTableUses.clear();
-
+
for (unsigned Idx = 0, N = Record.size(); Idx != N; /* In loop */) {
VTableUses.push_back(getGlobalDeclID(F, Record[Idx++]));
VTableUses.push_back(
@@ -2980,7 +3051,7 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
break;
case SEMA_DECL_REFS:
- if (Record.size() != 2) {
+ if (Record.size() != 3) {
Error("Invalid SEMA_DECL_REFS block");
return Failure;
}
@@ -2994,13 +3065,13 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
F.NumPreprocessedEntities = Blob.size() / sizeof(PPEntityOffset);
unsigned LocalBasePreprocessedEntityID = Record[0];
-
+
unsigned StartingID;
if (!PP.getPreprocessingRecord())
PP.createPreprocessingRecord();
if (!PP.getPreprocessingRecord()->getExternalSource())
PP.getPreprocessingRecord()->SetExternalSource(*this);
- StartingID
+ StartingID
= PP.getPreprocessingRecord()
->allocateLoadedEntities(F.NumPreprocessedEntities);
F.BasePreprocessedEntityID = StartingID;
@@ -3009,7 +3080,7 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
// Introduce the global -> local mapping for preprocessed entities in
// this module.
GlobalPreprocessedEntityMap.insert(std::make_pair(StartingID, &F));
-
+
// Introduce the local -> global mapping for preprocessed entities in
// this module.
F.PreprocessedEntityRemap.insertOrReplace(
@@ -3019,7 +3090,7 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
break;
}
-
+
case DECL_UPDATE_OFFSETS: {
if (Record.size() % 2 != 0) {
Error("invalid DECL_UPDATE_OFFSETS block in AST file");
@@ -3042,12 +3113,12 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
Error("duplicate OBJC_CATEGORIES_MAP record in AST file");
return Failure;
}
-
+
F.LocalNumObjCCategoriesInMap = Record[0];
F.ObjCCategoriesMap = (const ObjCCategoriesInfo *)Blob.data();
break;
}
-
+
case OBJC_CATEGORIES:
F.ObjCCategories.swap(Record);
break;
@@ -3059,7 +3130,7 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
F.PragmaDiagMappings.insert(F.PragmaDiagMappings.end(),
Record.begin(), Record.end());
break;
-
+
case CUDA_SPECIAL_DECL_REFS:
// Later tables overwrite earlier ones.
// FIXME: Modules will have trouble with this.
@@ -3076,32 +3147,62 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
= HeaderFileInfoLookupTable::Create(
(const unsigned char *)F.HeaderFileInfoTableData + Record[0],
(const unsigned char *)F.HeaderFileInfoTableData,
- HeaderFileInfoTrait(*this, F,
+ HeaderFileInfoTrait(*this, F,
&PP.getHeaderSearchInfo(),
Blob.data() + Record[2]));
-
+
PP.getHeaderSearchInfo().SetExternalSource(this);
if (!PP.getHeaderSearchInfo().getExternalLookup())
PP.getHeaderSearchInfo().SetExternalLookup(this);
}
break;
}
-
+
case FP_PRAGMA_OPTIONS:
// Later tables overwrite earlier ones.
FPPragmaOptions.swap(Record);
break;
case OPENCL_EXTENSIONS:
- // Later tables overwrite earlier ones.
- OpenCLExtensions.swap(Record);
+ for (unsigned I = 0, E = Record.size(); I != E; ) {
+ auto Name = ReadString(Record, I);
+ auto &Opt = OpenCLExtensions.OptMap[Name];
+ Opt.Supported = Record[I++] != 0;
+ Opt.Enabled = Record[I++] != 0;
+ Opt.Avail = Record[I++];
+ Opt.Core = Record[I++];
+ }
+ break;
+
+ case OPENCL_EXTENSION_TYPES:
+ for (unsigned I = 0, E = Record.size(); I != E;) {
+ auto TypeID = static_cast<::TypeID>(Record[I++]);
+ auto *Type = GetType(TypeID).getTypePtr();
+ auto NumExt = static_cast<unsigned>(Record[I++]);
+ for (unsigned II = 0; II != NumExt; ++II) {
+ auto Ext = ReadString(Record, I);
+ OpenCLTypeExtMap[Type].insert(Ext);
+ }
+ }
+ break;
+
+ case OPENCL_EXTENSION_DECLS:
+ for (unsigned I = 0, E = Record.size(); I != E;) {
+ auto DeclID = static_cast<::DeclID>(Record[I++]);
+ auto *Decl = GetDecl(DeclID);
+ auto NumExt = static_cast<unsigned>(Record[I++]);
+ for (unsigned II = 0; II != NumExt; ++II) {
+ auto Ext = ReadString(Record, I);
+ OpenCLDeclExtMap[Decl].insert(Ext);
+ }
+ }
break;
case TENTATIVE_DEFINITIONS:
for (unsigned I = 0, N = Record.size(); I != N; ++I)
TentativeDefinitions.push_back(getGlobalDeclID(F, Record[I]));
break;
-
+
case KNOWN_NAMESPACES:
for (unsigned I = 0, N = Record.size(); I != N; ++I)
KnownNamespaces.push_back(getGlobalDeclID(F, Record[I]));
@@ -3137,7 +3238,7 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
break;
case IMPORTED_MODULES: {
- if (F.Kind != MK_ImplicitModule && F.Kind != MK_ExplicitModule) {
+ if (!F.isModule()) {
// If we aren't loading a module (which has its own exports), make
// all of the imported modules visible.
// FIXME: Deal with macros-only imports.
@@ -3210,6 +3311,14 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
UnusedLocalTypedefNameCandidates.push_back(
getGlobalDeclID(F, Record[I]));
break;
+
+ case CUDA_PRAGMA_FORCE_HOST_DEVICE_DEPTH:
+ if (Record.size() != 1) {
+ Error("invalid cuda pragma options record");
+ return Failure;
+ }
+ ForceCUDAHostDeviceDepth = Record[0];
+ break;
}
}
}
@@ -3221,7 +3330,7 @@ ASTReader::ReadModuleMapFileBlock(RecordData &Record, ModuleFile &F,
unsigned Idx = 0;
F.ModuleMapPath = ReadPath(F, Record, Idx);
- if (F.Kind == MK_ExplicitModule) {
+ if (F.Kind == MK_ExplicitModule || F.Kind == MK_PrebuiltModule) {
// For an explicitly-loaded module, we don't care whether the original
// module map file exists or matches.
return Success;
@@ -3404,6 +3513,31 @@ void ASTReader::makeModuleVisible(Module *Mod,
}
}
+/// We've merged the definition \p MergedDef into the existing definition
+/// \p Def. Ensure that \p Def is made visible whenever \p MergedDef is made
+/// visible.
+void ASTReader::mergeDefinitionVisibility(NamedDecl *Def,
+ NamedDecl *MergedDef) {
+ // FIXME: This doesn't correctly handle the case where MergedDef is visible
+ // in modules other than its owning module. We should instead give the
+ // ASTContext a list of merged definitions for Def.
+ if (Def->isHidden()) {
+ // If MergedDef is visible or becomes visible, make the definition visible.
+ if (!MergedDef->isHidden())
+ Def->Hidden = false;
+ else if (getContext().getLangOpts().ModulesLocalVisibility) {
+ getContext().mergeDefinitionIntoModule(
+ Def, MergedDef->getImportedOwningModule(),
+ /*NotifyListeners*/ false);
+ PendingMergedDefinitionsToDeduplicate.insert(Def);
+ } else {
+ auto SubmoduleID = MergedDef->getOwningModuleID();
+ assert(SubmoduleID && "hidden definition in no module");
+ HiddenNamesMap[getSubmodule(SubmoduleID)].push_back(Def);
+ }
+ }
+}
+
bool ASTReader::loadGlobalIndex() {
if (GlobalIndex)
return false;
@@ -3411,7 +3545,7 @@ bool ASTReader::loadGlobalIndex() {
if (TriedLoadingGlobalIndex || !UseGlobalIndex ||
!Context.getLangOpts().Modules)
return true;
-
+
// Try to load the global index.
TriedLoadingGlobalIndex = true;
StringRef ModuleCachePath
@@ -3445,7 +3579,7 @@ static void updateModuleTimestamp(ModuleFile &MF) {
/// cursor into the start of the given block ID, returning false on success and
/// true on failure.
static bool SkipCursorToBlock(BitstreamCursor &Cursor, unsigned BlockID) {
- while (1) {
+ while (true) {
llvm::BitstreamEntry Entry = Cursor.advance();
switch (Entry.Kind) {
case llvm::BitstreamEntry::Error:
@@ -3474,7 +3608,8 @@ static bool SkipCursorToBlock(BitstreamCursor &Cursor, unsigned BlockID) {
ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName,
ModuleKind Type,
SourceLocation ImportLoc,
- unsigned ClientLoadCapabilities) {
+ unsigned ClientLoadCapabilities,
+ SmallVectorImpl<ImportedSubmodule> *Imported) {
llvm::SaveAndRestore<SourceLocation>
SetCurImportLocRAII(CurrentImportLoc, ImportLoc);
@@ -3534,12 +3669,12 @@ ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName,
return Result;
}
- // Once read, set the ModuleFile bit base offset and update the size in
+ // Once read, set the ModuleFile bit base offset and update the size in
// bits of all files we've seen.
F.GlobalBitOffset = TotalModulesSizeInBits;
TotalModulesSizeInBits += F.SizeInBits;
GlobalBitOffsetsMap.insert(std::make_pair(F.GlobalBitOffset, &F));
-
+
// Preload SLocEntries.
for (unsigned I = 0, N = F.PreloadSLocEntries.size(); I != N; ++I) {
int Index = int(F.PreloadSLocEntries[I] - 1) + F.SLocEntryBaseID;
@@ -3592,7 +3727,8 @@ ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName,
}
if (!Context.getLangOpts().CPlusPlus ||
- (Type != MK_ImplicitModule && Type != MK_ExplicitModule)) {
+ (Type != MK_ImplicitModule && Type != MK_ExplicitModule &&
+ Type != MK_PrebuiltModule)) {
// Mark all of the identifiers in the identifier table as being out of date,
// so that various accessors know to check the loaded modules when the
// identifier is used.
@@ -3608,7 +3744,7 @@ ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName,
// Mark selectors as out of date.
for (auto Sel : SelectorGeneration)
SelectorOutOfDate[Sel.first] = true;
-
+
// Resolve any unresolved module exports.
for (unsigned I = 0, N = UnresolvedModuleRefs.size(); I != N; ++I) {
UnresolvedModuleRef &Unresolved = UnresolvedModuleRefs[I];
@@ -3639,10 +3775,14 @@ ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName,
}
UnresolvedModuleRefs.clear();
+ if (Imported)
+ Imported->append(ImportedModules.begin(),
+ ImportedModules.end());
+
// FIXME: How do we load the 'use'd modules? They may not be submodules.
// Might be unnecessary as use declarations are only used to build the
// module itself.
-
+
InitializeContext();
if (SemaObj)
@@ -3653,7 +3793,7 @@ ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName,
ModuleFile &PrimaryModule = ModuleMgr.getPrimaryModule();
if (PrimaryModule.OriginalSourceFileID.isValid()) {
- PrimaryModule.OriginalSourceFileID
+ PrimaryModule.OriginalSourceFileID
= FileID::get(PrimaryModule.SLocEntryBaseID
+ PrimaryModule.OriginalSourceFileID.getOpaqueValue() - 1);
@@ -3666,11 +3806,11 @@ ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName,
SourceMgr.setMainFileID(PrimaryModule.OriginalSourceFileID);
}
}
-
+
// For any Objective-C class definitions we have already loaded, make sure
// that we load any additional categories.
for (unsigned I = 0, N = ObjCClassesLoaded.size(); I != N; ++I) {
- loadObjCCategories(ObjCClassesLoaded[I]->getGlobalID(),
+ loadObjCCategories(ObjCClassesLoaded[I]->getGlobalID(),
ObjCClassesLoaded[I],
PreviousGeneration);
}
@@ -3693,11 +3833,12 @@ ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName,
return Success;
}
-static ASTFileSignature readASTFileSignature(llvm::BitstreamReader &StreamFile);
+static ASTFileSignature readASTFileSignature(StringRef PCH);
/// \brief Whether \p Stream starts with the AST/PCH file magic number 'CPCH'.
static bool startsWithASTFileMagic(BitstreamCursor &Stream) {
- return Stream.Read(8) == 'C' &&
+ return Stream.canSkipToPos(4) &&
+ Stream.Read(8) == 'C' &&
Stream.Read(8) == 'P' &&
Stream.Read(8) == 'C' &&
Stream.Read(8) == 'H';
@@ -3709,6 +3850,7 @@ static unsigned moduleKindForDiagnostic(ModuleKind Kind) {
return 0; // PCH
case MK_ImplicitModule:
case MK_ExplicitModule:
+ case MK_PrebuiltModule:
return 1; // module
case MK_MainFile:
case MK_Preamble:
@@ -3750,7 +3892,7 @@ ASTReader::ReadASTCore(StringRef FileName,
// Otherwise, return an error.
Diag(diag::err_module_file_not_found) << moduleKindForDiagnostic(Type)
- << FileName << ErrorStr.empty()
+ << FileName << !ErrorStr.empty()
<< ErrorStr;
return Failure;
@@ -3762,7 +3904,7 @@ ASTReader::ReadASTCore(StringRef FileName,
// Otherwise, return an error.
Diag(diag::err_module_file_out_of_date) << moduleKindForDiagnostic(Type)
- << FileName << ErrorStr.empty()
+ << FileName << !ErrorStr.empty()
<< ErrorStr;
return Failure;
}
@@ -3778,10 +3920,9 @@ ASTReader::ReadASTCore(StringRef FileName,
ModuleFile &F = *M;
BitstreamCursor &Stream = F.Stream;
- PCHContainerRdr.ExtractPCH(F.Buffer->getMemBufferRef(), F.StreamFile);
- Stream.init(&F.StreamFile);
+ Stream = BitstreamCursor(PCHContainerRdr.ExtractPCH(*F.Buffer));
F.SizeInBits = F.Buffer->getBufferSize() * 8;
-
+
// Sniff for the signature.
if (!startsWithASTFileMagic(Stream)) {
Diag(diag::err_module_file_invalid) << moduleKindForDiagnostic(Type)
@@ -3791,16 +3932,16 @@ ASTReader::ReadASTCore(StringRef FileName,
// This is used for compatibility with older PCH formats.
bool HaveReadControlBlock = false;
- while (1) {
+ while (true) {
llvm::BitstreamEntry Entry = Stream.advance();
-
+
switch (Entry.Kind) {
case llvm::BitstreamEntry::Error:
case llvm::BitstreamEntry::Record:
case llvm::BitstreamEntry::EndBlock:
Error("invalid record at top-level of AST file");
return Failure;
-
+
case llvm::BitstreamEntry::SubBlock:
break;
}
@@ -3814,7 +3955,8 @@ ASTReader::ReadASTCore(StringRef FileName,
//
// FIXME: Should we also perform the converse check? Loading a module as
// a PCH file sort of works, but it's a bit wonky.
- if ((Type == MK_ImplicitModule || Type == MK_ExplicitModule) &&
+ if ((Type == MK_ImplicitModule || Type == MK_ExplicitModule ||
+ Type == MK_PrebuiltModule) &&
F.ModuleName.empty()) {
auto Result = (Type == MK_ImplicitModule) ? OutOfDate : Failure;
if (Result != OutOfDate ||
@@ -3930,26 +4072,26 @@ ASTReader::ASTReadResult ASTReader::ReadExtensionBlock(ModuleFile &F) {
void ASTReader::InitializeContext() {
// If there's a listener, notify them that we "read" the translation unit.
if (DeserializationListener)
- DeserializationListener->DeclRead(PREDEF_DECL_TRANSLATION_UNIT_ID,
+ DeserializationListener->DeclRead(PREDEF_DECL_TRANSLATION_UNIT_ID,
Context.getTranslationUnitDecl());
// FIXME: Find a better way to deal with collisions between these
// built-in types. Right now, we just ignore the problem.
-
+
// Load the special types.
if (SpecialTypes.size() >= NumSpecialTypeIDs) {
if (unsigned String = SpecialTypes[SPECIAL_TYPE_CF_CONSTANT_STRING]) {
if (!Context.CFConstantStringTypeDecl)
Context.setCFConstantStringType(GetType(String));
}
-
+
if (unsigned File = SpecialTypes[SPECIAL_TYPE_FILE]) {
QualType FileType = GetType(File);
if (FileType.isNull()) {
Error("FILE type is NULL");
return;
}
-
+
if (!Context.FILEDecl) {
if (const TypedefType *Typedef = FileType->getAs<TypedefType>())
Context.setFILEDecl(Typedef->getDecl());
@@ -3963,14 +4105,14 @@ void ASTReader::InitializeContext() {
}
}
}
-
+
if (unsigned Jmp_buf = SpecialTypes[SPECIAL_TYPE_JMP_BUF]) {
QualType Jmp_bufType = GetType(Jmp_buf);
if (Jmp_bufType.isNull()) {
Error("jmp_buf type is NULL");
return;
}
-
+
if (!Context.jmp_bufDecl) {
if (const TypedefType *Typedef = Jmp_bufType->getAs<TypedefType>())
Context.setjmp_bufDecl(Typedef->getDecl());
@@ -3984,14 +4126,14 @@ void ASTReader::InitializeContext() {
}
}
}
-
+
if (unsigned Sigjmp_buf = SpecialTypes[SPECIAL_TYPE_SIGJMP_BUF]) {
QualType Sigjmp_bufType = GetType(Sigjmp_buf);
if (Sigjmp_bufType.isNull()) {
Error("sigjmp_buf type is NULL");
return;
}
-
+
if (!Context.sigjmp_bufDecl) {
if (const TypedefType *Typedef = Sigjmp_bufType->getAs<TypedefType>())
Context.setsigjmp_bufDecl(Typedef->getDecl());
@@ -4039,7 +4181,7 @@ void ASTReader::InitializeContext() {
}
}
}
-
+
ReadPragmaDiagnosticMappings(Context.getDiagnostics());
// If there were any CUDA special declarations, deserialize them.
@@ -4067,10 +4209,10 @@ void ASTReader::finalizeForWriting() {
// Nothing to do for now.
}
-/// \brief Reads and return the signature record from \p StreamFile's control
-/// block, or else returns 0.
-static ASTFileSignature readASTFileSignature(llvm::BitstreamReader &StreamFile){
- BitstreamCursor Stream(StreamFile);
+/// \brief Reads and return the signature record from \p PCH's control block, or
+/// else returns 0.
+static ASTFileSignature readASTFileSignature(StringRef PCH) {
+ BitstreamCursor Stream(PCH);
if (!startsWithASTFileMagic(Stream))
return 0;
@@ -4080,10 +4222,9 @@ static ASTFileSignature readASTFileSignature(llvm::BitstreamReader &StreamFile){
// Scan for SIGNATURE inside the control block.
ASTReader::RecordData Record;
- while (1) {
+ while (true) {
llvm::BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
- if (Entry.Kind == llvm::BitstreamEntry::EndBlock ||
- Entry.Kind != llvm::BitstreamEntry::Record)
+ if (Entry.Kind != llvm::BitstreamEntry::Record)
return 0;
Record.clear();
@@ -4108,16 +4249,14 @@ std::string ASTReader::getOriginalSourceFile(
}
// Initialize the stream
- llvm::BitstreamReader StreamFile;
- PCHContainerRdr.ExtractPCH((*Buffer)->getMemBufferRef(), StreamFile);
- BitstreamCursor Stream(StreamFile);
+ BitstreamCursor Stream(PCHContainerRdr.ExtractPCH(**Buffer));
// Sniff for the signature.
if (!startsWithASTFileMagic(Stream)) {
Diags.Report(diag::err_fe_not_a_pch_file) << ASTFileName;
return std::string();
}
-
+
// Scan for the CONTROL_BLOCK_ID block.
if (SkipCursorToBlock(Stream, CONTROL_BLOCK_ID)) {
Diags.Report(diag::err_fe_pch_malformed_block) << ASTFileName;
@@ -4126,16 +4265,16 @@ std::string ASTReader::getOriginalSourceFile(
// Scan for ORIGINAL_FILE inside the control block.
RecordData Record;
- while (1) {
+ while (true) {
llvm::BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
if (Entry.Kind == llvm::BitstreamEntry::EndBlock)
return std::string();
-
+
if (Entry.Kind != llvm::BitstreamEntry::Record) {
Diags.Report(diag::err_fe_pch_malformed_block) << ASTFileName;
return std::string();
}
-
+
Record.clear();
StringRef Blob;
if (Stream.readRecord(Entry.ID, Record, &Blob) == ORIGINAL_FILE)
@@ -4144,6 +4283,7 @@ std::string ASTReader::getOriginalSourceFile(
}
namespace {
+
class SimplePCHValidator : public ASTReaderListener {
const LangOptions &ExistingLangOpts;
const TargetOptions &ExistingTargetOpts;
@@ -4170,11 +4310,13 @@ namespace {
return checkLanguageOptions(ExistingLangOpts, LangOpts, nullptr,
AllowCompatibleDifferences);
}
+
bool ReadTargetOptions(const TargetOptions &TargetOpts, bool Complain,
bool AllowCompatibleDifferences) override {
return checkTargetOptions(ExistingTargetOpts, TargetOpts, nullptr,
AllowCompatibleDifferences);
}
+
bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts,
StringRef SpecificModuleCachePath,
bool Complain) override {
@@ -4182,6 +4324,7 @@ namespace {
ExistingModuleCachePath,
nullptr, ExistingLangOpts);
}
+
bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,
bool Complain,
std::string &SuggestedPredefines) override {
@@ -4189,13 +4332,14 @@ namespace {
SuggestedPredefines, ExistingLangOpts);
}
};
-}
+
+} // end anonymous namespace
bool ASTReader::readASTFileControlBlock(
StringRef Filename, FileManager &FileMgr,
const PCHContainerReader &PCHContainerRdr,
bool FindModuleFileExtensions,
- ASTReaderListener &Listener) {
+ ASTReaderListener &Listener, bool ValidateDiagnosticOptions) {
// Open the AST file.
// FIXME: This allows use of the VFS; we do not allow use of the
// VFS when actually loading a module.
@@ -4205,9 +4349,7 @@ bool ASTReader::readASTFileControlBlock(
}
// Initialize the stream
- llvm::BitstreamReader StreamFile;
- PCHContainerRdr.ExtractPCH((*Buffer)->getMemBufferRef(), StreamFile);
- BitstreamCursor Stream(StreamFile);
+ BitstreamCursor Stream(PCHContainerRdr.ExtractPCH(**Buffer));
// Sniff for the signature.
if (!startsWithASTFileMagic(Stream))
@@ -4235,7 +4377,8 @@ bool ASTReader::readASTFileControlBlock(
std::string IgnoredSuggestedPredefines;
if (ReadOptionsBlock(Stream, ARR_ConfigurationMismatch | ARR_OutOfDate,
/*AllowCompatibleConfigurationMismatch*/ false,
- Listener, IgnoredSuggestedPredefines) != Success)
+ Listener, IgnoredSuggestedPredefines,
+ ValidateDiagnosticOptions) != Success)
return true;
break;
}
@@ -4280,7 +4423,7 @@ bool ASTReader::readASTFileControlBlock(
if (Listener.ReadFullVersionInformation(Blob))
return true;
-
+
break;
}
case MODULE_NAME:
@@ -4408,7 +4551,8 @@ bool ASTReader::isAcceptableASTFile(
ExistingModuleCachePath, FileMgr);
return !readASTFileControlBlock(Filename, FileMgr, PCHContainerRdr,
/*FindModuleFileExtensions=*/false,
- validator);
+ validator,
+ /*ValidateDiagnosticOptions=*/true);
}
ASTReader::ASTReadResult
@@ -4425,7 +4569,7 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
RecordData Record;
while (true) {
llvm::BitstreamEntry Entry = F.Stream.advanceSkippingSubblocks();
-
+
switch (Entry.Kind) {
case llvm::BitstreamEntry::SubBlock: // Handled for us already.
case llvm::BitstreamEntry::Error:
@@ -4523,7 +4667,7 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
CurrentModule->ConfigMacrosExhaustive = ConfigMacrosExhaustive;
if (DeserializationListener)
DeserializationListener->ModuleRead(GlobalID, CurrentModule);
-
+
SubmodulesLoaded[GlobalIndex] = CurrentModule;
// Clear out data that will be replaced by what is in the module file.
@@ -4563,7 +4707,7 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
}
break;
}
-
+
case SUBMODULE_HEADER:
case SUBMODULE_EXCLUDED_HEADER:
case SUBMODULE_PRIVATE_HEADER:
@@ -4597,17 +4741,17 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
}
break;
}
-
+
case SUBMODULE_METADATA: {
F.BaseSubmoduleID = getTotalNumSubmodules();
F.LocalNumSubmodules = Record[0];
unsigned LocalBaseSubmoduleID = Record[1];
if (F.LocalNumSubmodules > 0) {
- // Introduce the global -> local mapping for submodules within this
+ // Introduce the global -> local mapping for submodules within this
// module.
GlobalSubmoduleMap.insert(std::make_pair(getTotalNumSubmodules()+1,&F));
-
- // Introduce the local -> global mapping for submodules within this
+
+ // Introduce the local -> global mapping for submodules within this
// module.
F.SubmoduleRemap.insertOrReplace(
std::make_pair(LocalBaseSubmoduleID,
@@ -4617,7 +4761,7 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
}
break;
}
-
+
case SUBMODULE_IMPORTS: {
for (unsigned Idx = 0; Idx != Record.size(); ++Idx) {
UnresolvedModuleRef Unresolved;
@@ -4641,8 +4785,8 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
Unresolved.IsWildcard = Record[Idx + 1];
UnresolvedModuleRefs.push_back(Unresolved);
}
-
- // Once we've loaded the set of exports, there's no reason to keep
+
+ // Once we've loaded the set of exports, there's no reason to keep
// the parsed, unresolved exports around.
CurrentModule->UnresolvedExports.clear();
break;
@@ -4673,6 +4817,13 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
UnresolvedModuleRefs.push_back(Unresolved);
break;
}
+
+ case SUBMODULE_INITIALIZERS:
+ SmallVector<uint32_t, 16> Inits;
+ for (auto &ID : Record)
+ Inits.push_back(getGlobalDeclID(F, ID));
+ Context.addLazyModuleInitializers(CurrentModule, Inits);
+ break;
}
}
}
@@ -4848,7 +4999,7 @@ std::pair<ModuleFile *, unsigned>
ASTReader::getModulePreprocessedEntity(unsigned GlobalIndex) {
GlobalPreprocessedEntityMapType::iterator
I = GlobalPreprocessedEntityMap.find(GlobalIndex);
- assert(I != GlobalPreprocessedEntityMap.end() &&
+ assert(I != GlobalPreprocessedEntityMap.end() &&
"Corrupted global preprocessed entity map");
ModuleFile *M = I->second;
unsigned LocalIndex = GlobalIndex - M->BasePreprocessedEntityID;
@@ -4884,8 +5035,8 @@ PreprocessedEntity *ASTReader::ReadPreprocessedEntity(unsigned Index) {
Error("no preprocessing record");
return nullptr;
}
-
- SavedStreamPosition SavedPosition(M.PreprocessorDetailCursor);
+
+ SavedStreamPosition SavedPosition(M.PreprocessorDetailCursor);
M.PreprocessorDetailCursor.JumpToBit(PPOffs.BitOffset);
llvm::BitstreamEntry Entry =
@@ -4924,7 +5075,7 @@ PreprocessedEntity *ASTReader::ReadPreprocessedEntity(unsigned Index) {
return ME;
}
-
+
case PPD_MACRO_DEFINITION: {
// Decode the identifier info and then check again; if the macro is
// still defined and associated with the identifier,
@@ -4936,14 +5087,14 @@ PreprocessedEntity *ASTReader::ReadPreprocessedEntity(unsigned Index) {
return MD;
}
-
+
case PPD_INCLUSION_DIRECTIVE: {
const char *FullFileNameStart = Blob.data() + Record[0];
StringRef FullFileName(FullFileNameStart, Blob.size() - Record[0]);
const FileEntry *File = nullptr;
if (!FullFileName.empty())
File = PP.getFileManager().getFile(FullFileName);
-
+
// FIXME: Stable encoding
InclusionDirective::InclusionKind Kind
= static_cast<InclusionDirective::InclusionKind>(Record[2]);
@@ -5006,7 +5157,7 @@ struct PPEntityComp {
}
};
-}
+} // end anonymous namespace
PreprocessedEntityID ASTReader::findPreprocessedEntity(SourceLocation Loc,
bool EndsAfter) const {
@@ -5084,11 +5235,11 @@ Optional<bool> ASTReader::isPreprocessedEntityInFileID(unsigned Index,
ModuleFile &M = *PPInfo.first;
unsigned LocalIndex = PPInfo.second;
const PPEntityOffset &PPOffs = M.PreprocessedEntityOffsets[LocalIndex];
-
+
SourceLocation Loc = TranslateSourceLocation(M, PPOffs.getBegin());
if (Loc.isInvalid())
return false;
-
+
if (SourceMgr.isInFileID(SourceMgr.getFileLoc(Loc), FID))
return true;
else
@@ -5096,12 +5247,13 @@ Optional<bool> ASTReader::isPreprocessedEntityInFileID(unsigned Index,
}
namespace {
+
/// \brief Visitor used to search for information about a header file.
class HeaderFileInfoVisitor {
const FileEntry *FE;
-
+
Optional<HeaderFileInfo> HFI;
-
+
public:
explicit HeaderFileInfoVisitor(const FileEntry *FE)
: FE(FE) { }
@@ -5120,17 +5272,18 @@ namespace {
HFI = *Pos;
return true;
}
-
+
Optional<HeaderFileInfo> getHeaderFileInfo() const { return HFI; }
};
-}
+
+} // end anonymous namespace
HeaderFileInfo ASTReader::GetHeaderFileInfo(const FileEntry *FE) {
HeaderFileInfoVisitor Visitor(FE);
ModuleMgr.visit(Visitor);
if (Optional<HeaderFileInfo> HFI = Visitor.getHeaderFileInfo())
return *HFI;
-
+
return HeaderFileInfo();
}
@@ -5152,7 +5305,7 @@ void ASTReader::ReadPragmaDiagnosticMappings(DiagnosticsEngine &Diag) {
FullSourceLoc(Loc, SourceMgr)));
continue;
}
-
+
assert(DiagStateID == 0);
// A new DiagState was created here.
Diag.DiagStates.push_back(*Diag.GetCurDiagState());
@@ -5161,7 +5314,7 @@ void ASTReader::ReadPragmaDiagnosticMappings(DiagnosticsEngine &Diag) {
Diag.DiagStatePoints.push_back(
DiagnosticsEngine::DiagStatePoint(NewState,
FullSourceLoc(Loc, SourceMgr)));
- while (1) {
+ while (true) {
assert(Idx < F.PragmaDiagMappings.size() &&
"Invalid data, didn't find '-1' marking end of diag/map pairs");
if (Idx >= F.PragmaDiagMappings.size()) {
@@ -5298,7 +5451,7 @@ QualType ASTReader::readTypeRecord(unsigned Index) {
QualType ClassType = readType(*Loc.F, Record, Idx);
if (PointeeType.isNull() || ClassType.isNull())
return QualType();
-
+
return Context.getMemberPointerType(PointeeType, ClassType.getTypePtr());
}
@@ -5408,7 +5561,7 @@ QualType ASTReader::readTypeRecord(unsigned Index) {
return Context.getTypeDeclType(
ReadDeclAs<UnresolvedUsingTypenameDecl>(*Loc.F, Record, Idx));
}
-
+
case TYPE_TYPEDEF: {
if (Record.size() != 2) {
Error("incorrect encoding of typedef type");
@@ -5529,6 +5682,16 @@ QualType ASTReader::readTypeRecord(unsigned Index) {
return Context.getObjCInterfaceType(ItfD->getCanonicalDecl());
}
+ case TYPE_OBJC_TYPE_PARAM: {
+ unsigned Idx = 0;
+ ObjCTypeParamDecl *Decl
+ = ReadDeclAs<ObjCTypeParamDecl>(*Loc.F, Record, Idx);
+ unsigned NumProtos = Record[Idx++];
+ SmallVector<ObjCProtocolDecl*, 4> Protos;
+ for (unsigned I = 0; I != NumProtos; ++I)
+ Protos.push_back(ReadDeclAs<ObjCProtocolDecl>(*Loc.F, Record, Idx));
+ return Context.getObjCTypeParamType(Decl, Protos);
+ }
case TYPE_OBJC_OBJECT: {
unsigned Idx = 0;
QualType Base = readType(*Loc.F, Record, Idx);
@@ -5666,15 +5829,17 @@ QualType ASTReader::readTypeRecord(unsigned Index) {
}
case TYPE_PIPE: {
- if (Record.size() != 1) {
+ if (Record.size() != 2) {
Error("Incorrect encoding of pipe type");
return QualType();
}
// Reading the pipe element type.
QualType ElementType = readType(*Loc.F, Record, Idx);
- return Context.getPipeType(ElementType);
+ unsigned ReadOnly = Record[1];
+ return Context.getPipeType(ElementType, ReadOnly);
}
+
}
llvm_unreachable("Invalid TypeCode!");
}
@@ -5701,26 +5866,27 @@ void ASTReader::readExceptionSpec(ModuleFile &ModuleFile,
}
class clang::TypeLocReader : public TypeLocVisitor<TypeLocReader> {
- ASTReader &Reader;
- ModuleFile &F;
+ ModuleFile *F;
+ ASTReader *Reader;
const ASTReader::RecordData &Record;
unsigned &Idx;
- SourceLocation ReadSourceLocation(const ASTReader::RecordData &R,
- unsigned &I) {
- return Reader.ReadSourceLocation(F, R, I);
+ SourceLocation ReadSourceLocation() {
+ return Reader->ReadSourceLocation(*F, Record, Idx);
}
- template<typename T>
- T *ReadDeclAs(const ASTReader::RecordData &Record, unsigned &Idx) {
- return Reader.ReadDeclAs<T>(F, Record, Idx);
+ TypeSourceInfo *GetTypeSourceInfo() {
+ return Reader->GetTypeSourceInfo(*F, Record, Idx);
}
-
+
+ NestedNameSpecifierLoc ReadNestedNameSpecifierLoc() {
+ return Reader->ReadNestedNameSpecifierLoc(*F, Record, Idx);
+ }
+
public:
- TypeLocReader(ASTReader &Reader, ModuleFile &F,
+ TypeLocReader(ModuleFile &F, ASTReader &Reader,
const ASTReader::RecordData &Record, unsigned &Idx)
- : Reader(Reader), F(F), Record(Record), Idx(Idx)
- { }
+ : F(&F), Reader(&Reader), Record(Record), Idx(Idx) {}
// We want compile-time assurance that we've enumerated all of
// these, so unfortunately we have to declare them first, then
@@ -5737,8 +5903,9 @@ public:
void TypeLocReader::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
// nothing to do
}
+
void TypeLocReader::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
- TL.setBuiltinLoc(ReadSourceLocation(Record, Idx));
+ TL.setBuiltinLoc(ReadSourceLocation());
if (TL.needsExtraLocalData()) {
TL.setWrittenTypeSpec(static_cast<DeclSpec::TST>(Record[Idx++]));
TL.setWrittenSignSpec(static_cast<DeclSpec::TSS>(Record[Idx++]));
@@ -5746,219 +5913,264 @@ void TypeLocReader::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
TL.setModeAttr(Record[Idx++]);
}
}
+
void TypeLocReader::VisitComplexTypeLoc(ComplexTypeLoc TL) {
- TL.setNameLoc(ReadSourceLocation(Record, Idx));
+ TL.setNameLoc(ReadSourceLocation());
}
+
void TypeLocReader::VisitPointerTypeLoc(PointerTypeLoc TL) {
- TL.setStarLoc(ReadSourceLocation(Record, Idx));
+ TL.setStarLoc(ReadSourceLocation());
}
+
void TypeLocReader::VisitDecayedTypeLoc(DecayedTypeLoc TL) {
// nothing to do
}
+
void TypeLocReader::VisitAdjustedTypeLoc(AdjustedTypeLoc TL) {
// nothing to do
}
+
void TypeLocReader::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
- TL.setCaretLoc(ReadSourceLocation(Record, Idx));
+ TL.setCaretLoc(ReadSourceLocation());
}
+
void TypeLocReader::VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {
- TL.setAmpLoc(ReadSourceLocation(Record, Idx));
+ TL.setAmpLoc(ReadSourceLocation());
}
+
void TypeLocReader::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) {
- TL.setAmpAmpLoc(ReadSourceLocation(Record, Idx));
+ TL.setAmpAmpLoc(ReadSourceLocation());
}
+
void TypeLocReader::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
- TL.setStarLoc(ReadSourceLocation(Record, Idx));
- TL.setClassTInfo(Reader.GetTypeSourceInfo(F, Record, Idx));
+ TL.setStarLoc(ReadSourceLocation());
+ TL.setClassTInfo(GetTypeSourceInfo());
}
+
void TypeLocReader::VisitArrayTypeLoc(ArrayTypeLoc TL) {
- TL.setLBracketLoc(ReadSourceLocation(Record, Idx));
- TL.setRBracketLoc(ReadSourceLocation(Record, Idx));
+ TL.setLBracketLoc(ReadSourceLocation());
+ TL.setRBracketLoc(ReadSourceLocation());
if (Record[Idx++])
- TL.setSizeExpr(Reader.ReadExpr(F));
+ TL.setSizeExpr(Reader->ReadExpr(*F));
else
TL.setSizeExpr(nullptr);
}
+
void TypeLocReader::VisitConstantArrayTypeLoc(ConstantArrayTypeLoc TL) {
VisitArrayTypeLoc(TL);
}
+
void TypeLocReader::VisitIncompleteArrayTypeLoc(IncompleteArrayTypeLoc TL) {
VisitArrayTypeLoc(TL);
}
+
void TypeLocReader::VisitVariableArrayTypeLoc(VariableArrayTypeLoc TL) {
VisitArrayTypeLoc(TL);
}
+
void TypeLocReader::VisitDependentSizedArrayTypeLoc(
DependentSizedArrayTypeLoc TL) {
VisitArrayTypeLoc(TL);
}
+
void TypeLocReader::VisitDependentSizedExtVectorTypeLoc(
DependentSizedExtVectorTypeLoc TL) {
- TL.setNameLoc(ReadSourceLocation(Record, Idx));
+ TL.setNameLoc(ReadSourceLocation());
}
+
void TypeLocReader::VisitVectorTypeLoc(VectorTypeLoc TL) {
- TL.setNameLoc(ReadSourceLocation(Record, Idx));
+ TL.setNameLoc(ReadSourceLocation());
}
+
void TypeLocReader::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) {
- TL.setNameLoc(ReadSourceLocation(Record, Idx));
+ TL.setNameLoc(ReadSourceLocation());
}
+
void TypeLocReader::VisitFunctionTypeLoc(FunctionTypeLoc TL) {
- TL.setLocalRangeBegin(ReadSourceLocation(Record, Idx));
- TL.setLParenLoc(ReadSourceLocation(Record, Idx));
- TL.setRParenLoc(ReadSourceLocation(Record, Idx));
- TL.setLocalRangeEnd(ReadSourceLocation(Record, Idx));
+ TL.setLocalRangeBegin(ReadSourceLocation());
+ TL.setLParenLoc(ReadSourceLocation());
+ TL.setRParenLoc(ReadSourceLocation());
+ TL.setLocalRangeEnd(ReadSourceLocation());
for (unsigned i = 0, e = TL.getNumParams(); i != e; ++i) {
- TL.setParam(i, ReadDeclAs<ParmVarDecl>(Record, Idx));
+ TL.setParam(i, Reader->ReadDeclAs<ParmVarDecl>(*F, Record, Idx));
}
}
+
void TypeLocReader::VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc TL) {
VisitFunctionTypeLoc(TL);
}
+
void TypeLocReader::VisitFunctionNoProtoTypeLoc(FunctionNoProtoTypeLoc TL) {
VisitFunctionTypeLoc(TL);
}
void TypeLocReader::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) {
- TL.setNameLoc(ReadSourceLocation(Record, Idx));
+ TL.setNameLoc(ReadSourceLocation());
}
void TypeLocReader::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
- TL.setNameLoc(ReadSourceLocation(Record, Idx));
+ TL.setNameLoc(ReadSourceLocation());
}
void TypeLocReader::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
- TL.setTypeofLoc(ReadSourceLocation(Record, Idx));
- TL.setLParenLoc(ReadSourceLocation(Record, Idx));
- TL.setRParenLoc(ReadSourceLocation(Record, Idx));
+ TL.setTypeofLoc(ReadSourceLocation());
+ TL.setLParenLoc(ReadSourceLocation());
+ TL.setRParenLoc(ReadSourceLocation());
}
void TypeLocReader::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
- TL.setTypeofLoc(ReadSourceLocation(Record, Idx));
- TL.setLParenLoc(ReadSourceLocation(Record, Idx));
- TL.setRParenLoc(ReadSourceLocation(Record, Idx));
- TL.setUnderlyingTInfo(Reader.GetTypeSourceInfo(F, Record, Idx));
+ TL.setTypeofLoc(ReadSourceLocation());
+ TL.setLParenLoc(ReadSourceLocation());
+ TL.setRParenLoc(ReadSourceLocation());
+ TL.setUnderlyingTInfo(GetTypeSourceInfo());
}
void TypeLocReader::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {
- TL.setNameLoc(ReadSourceLocation(Record, Idx));
+ TL.setNameLoc(ReadSourceLocation());
}
+
void TypeLocReader::VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc TL) {
- TL.setKWLoc(ReadSourceLocation(Record, Idx));
- TL.setLParenLoc(ReadSourceLocation(Record, Idx));
- TL.setRParenLoc(ReadSourceLocation(Record, Idx));
- TL.setUnderlyingTInfo(Reader.GetTypeSourceInfo(F, Record, Idx));
+ TL.setKWLoc(ReadSourceLocation());
+ TL.setLParenLoc(ReadSourceLocation());
+ TL.setRParenLoc(ReadSourceLocation());
+ TL.setUnderlyingTInfo(GetTypeSourceInfo());
}
+
void TypeLocReader::VisitAutoTypeLoc(AutoTypeLoc TL) {
- TL.setNameLoc(ReadSourceLocation(Record, Idx));
+ TL.setNameLoc(ReadSourceLocation());
}
+
void TypeLocReader::VisitRecordTypeLoc(RecordTypeLoc TL) {
- TL.setNameLoc(ReadSourceLocation(Record, Idx));
+ TL.setNameLoc(ReadSourceLocation());
}
+
void TypeLocReader::VisitEnumTypeLoc(EnumTypeLoc TL) {
- TL.setNameLoc(ReadSourceLocation(Record, Idx));
+ TL.setNameLoc(ReadSourceLocation());
}
+
void TypeLocReader::VisitAttributedTypeLoc(AttributedTypeLoc TL) {
- TL.setAttrNameLoc(ReadSourceLocation(Record, Idx));
+ TL.setAttrNameLoc(ReadSourceLocation());
if (TL.hasAttrOperand()) {
SourceRange range;
- range.setBegin(ReadSourceLocation(Record, Idx));
- range.setEnd(ReadSourceLocation(Record, Idx));
+ range.setBegin(ReadSourceLocation());
+ range.setEnd(ReadSourceLocation());
TL.setAttrOperandParensRange(range);
}
if (TL.hasAttrExprOperand()) {
if (Record[Idx++])
- TL.setAttrExprOperand(Reader.ReadExpr(F));
+ TL.setAttrExprOperand(Reader->ReadExpr(*F));
else
TL.setAttrExprOperand(nullptr);
} else if (TL.hasAttrEnumOperand())
- TL.setAttrEnumOperandLoc(ReadSourceLocation(Record, Idx));
+ TL.setAttrEnumOperandLoc(ReadSourceLocation());
}
+
void TypeLocReader::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
- TL.setNameLoc(ReadSourceLocation(Record, Idx));
+ TL.setNameLoc(ReadSourceLocation());
}
+
void TypeLocReader::VisitSubstTemplateTypeParmTypeLoc(
SubstTemplateTypeParmTypeLoc TL) {
- TL.setNameLoc(ReadSourceLocation(Record, Idx));
+ TL.setNameLoc(ReadSourceLocation());
}
void TypeLocReader::VisitSubstTemplateTypeParmPackTypeLoc(
SubstTemplateTypeParmPackTypeLoc TL) {
- TL.setNameLoc(ReadSourceLocation(Record, Idx));
+ TL.setNameLoc(ReadSourceLocation());
}
void TypeLocReader::VisitTemplateSpecializationTypeLoc(
TemplateSpecializationTypeLoc TL) {
- TL.setTemplateKeywordLoc(ReadSourceLocation(Record, Idx));
- TL.setTemplateNameLoc(ReadSourceLocation(Record, Idx));
- TL.setLAngleLoc(ReadSourceLocation(Record, Idx));
- TL.setRAngleLoc(ReadSourceLocation(Record, Idx));
+ TL.setTemplateKeywordLoc(ReadSourceLocation());
+ TL.setTemplateNameLoc(ReadSourceLocation());
+ TL.setLAngleLoc(ReadSourceLocation());
+ TL.setRAngleLoc(ReadSourceLocation());
for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)
- TL.setArgLocInfo(i,
- Reader.GetTemplateArgumentLocInfo(F,
- TL.getTypePtr()->getArg(i).getKind(),
- Record, Idx));
+ TL.setArgLocInfo(
+ i,
+ Reader->GetTemplateArgumentLocInfo(
+ *F, TL.getTypePtr()->getArg(i).getKind(), Record, Idx));
}
void TypeLocReader::VisitParenTypeLoc(ParenTypeLoc TL) {
- TL.setLParenLoc(ReadSourceLocation(Record, Idx));
- TL.setRParenLoc(ReadSourceLocation(Record, Idx));
+ TL.setLParenLoc(ReadSourceLocation());
+ TL.setRParenLoc(ReadSourceLocation());
}
+
void TypeLocReader::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {
- TL.setElaboratedKeywordLoc(ReadSourceLocation(Record, Idx));
- TL.setQualifierLoc(Reader.ReadNestedNameSpecifierLoc(F, Record, Idx));
+ TL.setElaboratedKeywordLoc(ReadSourceLocation());
+ TL.setQualifierLoc(ReadNestedNameSpecifierLoc());
}
+
void TypeLocReader::VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) {
- TL.setNameLoc(ReadSourceLocation(Record, Idx));
+ TL.setNameLoc(ReadSourceLocation());
}
+
void TypeLocReader::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {
- TL.setElaboratedKeywordLoc(ReadSourceLocation(Record, Idx));
- TL.setQualifierLoc(Reader.ReadNestedNameSpecifierLoc(F, Record, Idx));
- TL.setNameLoc(ReadSourceLocation(Record, Idx));
+ TL.setElaboratedKeywordLoc(ReadSourceLocation());
+ TL.setQualifierLoc(ReadNestedNameSpecifierLoc());
+ TL.setNameLoc(ReadSourceLocation());
}
+
void TypeLocReader::VisitDependentTemplateSpecializationTypeLoc(
DependentTemplateSpecializationTypeLoc TL) {
- TL.setElaboratedKeywordLoc(ReadSourceLocation(Record, Idx));
- TL.setQualifierLoc(Reader.ReadNestedNameSpecifierLoc(F, Record, Idx));
- TL.setTemplateKeywordLoc(ReadSourceLocation(Record, Idx));
- TL.setTemplateNameLoc(ReadSourceLocation(Record, Idx));
- TL.setLAngleLoc(ReadSourceLocation(Record, Idx));
- TL.setRAngleLoc(ReadSourceLocation(Record, Idx));
+ TL.setElaboratedKeywordLoc(ReadSourceLocation());
+ TL.setQualifierLoc(ReadNestedNameSpecifierLoc());
+ TL.setTemplateKeywordLoc(ReadSourceLocation());
+ TL.setTemplateNameLoc(ReadSourceLocation());
+ TL.setLAngleLoc(ReadSourceLocation());
+ TL.setRAngleLoc(ReadSourceLocation());
for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I)
- TL.setArgLocInfo(I,
- Reader.GetTemplateArgumentLocInfo(F,
- TL.getTypePtr()->getArg(I).getKind(),
- Record, Idx));
+ TL.setArgLocInfo(
+ I,
+ Reader->GetTemplateArgumentLocInfo(
+ *F, TL.getTypePtr()->getArg(I).getKind(), Record, Idx));
}
+
void TypeLocReader::VisitPackExpansionTypeLoc(PackExpansionTypeLoc TL) {
- TL.setEllipsisLoc(ReadSourceLocation(Record, Idx));
+ TL.setEllipsisLoc(ReadSourceLocation());
}
+
void TypeLocReader::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
- TL.setNameLoc(ReadSourceLocation(Record, Idx));
+ TL.setNameLoc(ReadSourceLocation());
}
+
+void TypeLocReader::VisitObjCTypeParamTypeLoc(ObjCTypeParamTypeLoc TL) {
+ if (TL.getNumProtocols()) {
+ TL.setProtocolLAngleLoc(ReadSourceLocation());
+ TL.setProtocolRAngleLoc(ReadSourceLocation());
+ }
+ for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)
+ TL.setProtocolLoc(i, ReadSourceLocation());
+}
+
void TypeLocReader::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
TL.setHasBaseTypeAsWritten(Record[Idx++]);
- TL.setTypeArgsLAngleLoc(ReadSourceLocation(Record, Idx));
- TL.setTypeArgsRAngleLoc(ReadSourceLocation(Record, Idx));
+ TL.setTypeArgsLAngleLoc(ReadSourceLocation());
+ TL.setTypeArgsRAngleLoc(ReadSourceLocation());
for (unsigned i = 0, e = TL.getNumTypeArgs(); i != e; ++i)
- TL.setTypeArgTInfo(i, Reader.GetTypeSourceInfo(F, Record, Idx));
- TL.setProtocolLAngleLoc(ReadSourceLocation(Record, Idx));
- TL.setProtocolRAngleLoc(ReadSourceLocation(Record, Idx));
+ TL.setTypeArgTInfo(i, GetTypeSourceInfo());
+ TL.setProtocolLAngleLoc(ReadSourceLocation());
+ TL.setProtocolRAngleLoc(ReadSourceLocation());
for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)
- TL.setProtocolLoc(i, ReadSourceLocation(Record, Idx));
+ TL.setProtocolLoc(i, ReadSourceLocation());
}
+
void TypeLocReader::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
- TL.setStarLoc(ReadSourceLocation(Record, Idx));
+ TL.setStarLoc(ReadSourceLocation());
}
+
void TypeLocReader::VisitAtomicTypeLoc(AtomicTypeLoc TL) {
- TL.setKWLoc(ReadSourceLocation(Record, Idx));
- TL.setLParenLoc(ReadSourceLocation(Record, Idx));
- TL.setRParenLoc(ReadSourceLocation(Record, Idx));
+ TL.setKWLoc(ReadSourceLocation());
+ TL.setLParenLoc(ReadSourceLocation());
+ TL.setRParenLoc(ReadSourceLocation());
}
+
void TypeLocReader::VisitPipeTypeLoc(PipeTypeLoc TL) {
- TL.setKWLoc(ReadSourceLocation(Record, Idx));
+ TL.setKWLoc(ReadSourceLocation());
}
-TypeSourceInfo *ASTReader::GetTypeSourceInfo(ModuleFile &F,
- const RecordData &Record,
- unsigned &Idx) {
+TypeSourceInfo *
+ASTReader::GetTypeSourceInfo(ModuleFile &F, const ASTReader::RecordData &Record,
+ unsigned &Idx) {
QualType InfoTy = readType(F, Record, Idx);
if (InfoTy.isNull())
return nullptr;
TypeSourceInfo *TInfo = getContext().CreateTypeSourceInfo(InfoTy);
- TypeLocReader TLR(*this, F, Record, Idx);
+ TypeLocReader TLR(F, *this, Record, Idx);
for (TypeLoc TL = TInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc())
TLR.Visit(TL);
return TInfo;
@@ -6141,18 +6353,18 @@ QualType ASTReader::getLocalType(ModuleFile &F, unsigned LocalID) {
return GetType(getGlobalTypeID(F, LocalID));
}
-serialization::TypeID
+serialization::TypeID
ASTReader::getGlobalTypeID(ModuleFile &F, unsigned LocalID) const {
unsigned FastQuals = LocalID & Qualifiers::FastMask;
unsigned LocalIndex = LocalID >> Qualifiers::FastWidth;
-
+
if (LocalIndex < NUM_PREDEF_TYPE_IDS)
return LocalID;
ContinuousRangeMap<uint32_t, int, 2>::iterator I
= F.TypeRemap.find(LocalIndex - NUM_PREDEF_TYPE_IDS);
assert(I != F.TypeRemap.end() && "Invalid index into type index remap");
-
+
unsigned GlobalIndex = LocalIndex + I->second;
return (GlobalIndex << Qualifiers::FastWidth) | FastQuals;
}
@@ -6168,18 +6380,18 @@ ASTReader::GetTemplateArgumentLocInfo(ModuleFile &F,
case TemplateArgument::Type:
return GetTypeSourceInfo(F, Record, Index);
case TemplateArgument::Template: {
- NestedNameSpecifierLoc QualifierLoc = ReadNestedNameSpecifierLoc(F, Record,
+ NestedNameSpecifierLoc QualifierLoc = ReadNestedNameSpecifierLoc(F, Record,
Index);
SourceLocation TemplateNameLoc = ReadSourceLocation(F, Record, Index);
return TemplateArgumentLocInfo(QualifierLoc, TemplateNameLoc,
SourceLocation());
}
case TemplateArgument::TemplateExpansion: {
- NestedNameSpecifierLoc QualifierLoc = ReadNestedNameSpecifierLoc(F, Record,
+ NestedNameSpecifierLoc QualifierLoc = ReadNestedNameSpecifierLoc(F, Record,
Index);
SourceLocation TemplateNameLoc = ReadSourceLocation(F, Record, Index);
SourceLocation EllipsisLoc = ReadSourceLocation(F, Record, Index);
- return TemplateArgumentLocInfo(QualifierLoc, TemplateNameLoc,
+ return TemplateArgumentLocInfo(QualifierLoc, TemplateNameLoc,
EllipsisLoc);
}
case TemplateArgument::Null:
@@ -6324,7 +6536,7 @@ CXXBaseSpecifier *ASTReader::GetExternalCXXBaseSpecifiers(uint64_t Offset) {
return Bases;
}
-serialization::DeclID
+serialization::DeclID
ASTReader::getGlobalDeclID(ModuleFile &F, LocalDeclID LocalID) const {
if (LocalID < NUM_PREDEF_DECL_IDS)
return LocalID;
@@ -6332,7 +6544,7 @@ ASTReader::getGlobalDeclID(ModuleFile &F, LocalDeclID LocalID) const {
ContinuousRangeMap<uint32_t, int, 2>::iterator I
= F.DeclRemap.find(LocalID - NUM_PREDEF_DECL_IDS);
assert(I != F.DeclRemap.end() && "Invalid index into decl index remap");
-
+
return LocalID + I->second;
}
@@ -6342,7 +6554,7 @@ bool ASTReader::isDeclIDFromModule(serialization::GlobalDeclID ID,
if (ID < NUM_PREDEF_DECL_IDS)
return false;
- return ID - NUM_PREDEF_DECL_IDS >= M.BaseDeclID &&
+ return ID - NUM_PREDEF_DECL_IDS >= M.BaseDeclID &&
ID - NUM_PREDEF_DECL_IDS < M.BaseDeclID + M.LocalNumDecls;
}
@@ -6474,11 +6686,11 @@ Decl *ASTReader::GetDecl(DeclID ID) {
return DeclsLoaded[Index];
}
-DeclID ASTReader::mapGlobalIDToModuleFileGlobalID(ModuleFile &M,
+DeclID ASTReader::mapGlobalIDToModuleFileGlobalID(ModuleFile &M,
DeclID GlobalID) {
if (GlobalID < NUM_PREDEF_DECL_IDS)
return GlobalID;
-
+
GlobalDeclMapType::const_iterator I = GlobalDeclMap.find(GlobalID);
assert(I != GlobalDeclMap.end() && "Corrupted global declaration map");
ModuleFile *Owner = I->second;
@@ -6487,18 +6699,18 @@ DeclID ASTReader::mapGlobalIDToModuleFileGlobalID(ModuleFile &M,
= M.GlobalToLocalDeclIDs.find(Owner);
if (Pos == M.GlobalToLocalDeclIDs.end())
return 0;
-
+
return GlobalID - Owner->BaseDeclID + Pos->second;
}
-serialization::DeclID ASTReader::ReadDeclID(ModuleFile &F,
+serialization::DeclID ASTReader::ReadDeclID(ModuleFile &F,
const RecordData &Record,
unsigned &Idx) {
if (Idx >= Record.size()) {
Error("Corrupted AST file");
return 0;
}
-
+
return getGlobalDeclID(F, Record[Idx++]);
}
@@ -6591,7 +6803,7 @@ public:
}
};
-}
+} // end anonymous namespace
void ASTReader::FindFileRegionDecls(FileID File,
unsigned Offset, unsigned Length,
@@ -6630,7 +6842,7 @@ void ASTReader::FindFileRegionDecls(FileID File,
EndLoc, DIDComp);
if (EndIt != DInfo.Decls.end())
++EndIt;
-
+
for (ArrayRef<serialization::LocalDeclID>::iterator
DIt = BeginIt; DIt != EndIt; ++DIt)
Decls.push_back(GetDecl(getGlobalDeclID(*DInfo.Mod, *DIt)));
@@ -6841,23 +7053,23 @@ void ASTReader::PrintStats() {
std::fprintf(stderr, "\n");
GlobalIndex->printStats();
}
-
+
std::fprintf(stderr, "\n");
dump();
std::fprintf(stderr, "\n");
}
template<typename Key, typename ModuleFile, unsigned InitialCapacity>
-static void
+static void
dumpModuleIDMap(StringRef Name,
- const ContinuousRangeMap<Key, ModuleFile *,
+ const ContinuousRangeMap<Key, ModuleFile *,
InitialCapacity> &Map) {
if (Map.begin() == Map.end())
return;
-
+
typedef ContinuousRangeMap<Key, ModuleFile *, InitialCapacity> MapType;
llvm::errs() << Name << ":\n";
- for (typename MapType::const_iterator I = Map.begin(), IEnd = Map.end();
+ for (typename MapType::const_iterator I = Map.begin(), IEnd = Map.end();
I != IEnd; ++I) {
llvm::errs() << " " << I->first << " -> " << I->second->FileName
<< "\n";
@@ -6874,11 +7086,11 @@ LLVM_DUMP_METHOD void ASTReader::dump() {
dumpModuleIDMap("Global macro map", GlobalMacroMap);
dumpModuleIDMap("Global submodule map", GlobalSubmoduleMap);
dumpModuleIDMap("Global selector map", GlobalSelectorMap);
- dumpModuleIDMap("Global preprocessed entity map",
+ dumpModuleIDMap("Global preprocessed entity map",
GlobalPreprocessedEntityMap);
-
+
llvm::errs() << "\n*** PCH/Modules Loaded:";
- for (ModuleManager::ModuleConstIterator M = ModuleMgr.begin(),
+ for (ModuleManager::ModuleConstIterator M = ModuleMgr.begin(),
MEnd = ModuleMgr.end();
M != MEnd; ++M)
(*M)->dump();
@@ -6921,14 +7133,9 @@ void ASTReader::InitializeSema(Sema &S) {
SemaObj->FPFeatures.fp_contract = FPPragmaOptions[0];
}
- // FIXME: What happens if these are changed by a module import?
- if (!OpenCLExtensions.empty()) {
- unsigned I = 0;
-#define OPENCLEXT(nm) SemaObj->OpenCLFeatures.nm = OpenCLExtensions[I++];
-#include "clang/Basic/OpenCLExtensions.def"
-
- assert(OpenCLExtensions.size() == I && "Wrong number of OPENCL_EXTENSIONS");
- }
+ SemaObj->OpenCLFeatures.copy(OpenCLExtensions);
+ SemaObj->OpenCLTypeExtMap = OpenCLTypeExtMap;
+ SemaObj->OpenCLDeclExtMap = OpenCLDeclExtMap;
UpdateSema();
}
@@ -6939,12 +7146,14 @@ void ASTReader::UpdateSema() {
// Load the offsets of the declarations that Sema references.
// They will be lazily deserialized when needed.
if (!SemaDeclRefs.empty()) {
- assert(SemaDeclRefs.size() % 2 == 0);
- for (unsigned I = 0; I != SemaDeclRefs.size(); I += 2) {
+ assert(SemaDeclRefs.size() % 3 == 0);
+ for (unsigned I = 0; I != SemaDeclRefs.size(); I += 3) {
if (!SemaObj->StdNamespace)
SemaObj->StdNamespace = SemaDeclRefs[I];
if (!SemaObj->StdBadAlloc)
SemaObj->StdBadAlloc = SemaDeclRefs[I+1];
+ if (!SemaObj->StdAlignValT)
+ SemaObj->StdAlignValT = SemaDeclRefs[I+2];
}
SemaDeclRefs.clear();
}
@@ -6961,6 +7170,7 @@ void ASTReader::UpdateSema() {
PragmaMSPointersToMembersState,
PointersToMembersPragmaLocation);
}
+ SemaObj->ForceCUDAHostDeviceDepth = ForceCUDAHostDeviceDepth;
}
IdentifierInfo *ASTReader::get(StringRef Name) {
@@ -6999,6 +7209,7 @@ IdentifierInfo *ASTReader::get(StringRef Name) {
}
namespace clang {
+
/// \brief An identifier-lookup iterator that enumerates all of the
/// identifiers stored within a set of AST files.
class ASTIdentifierIterator : public IdentifierIterator {
@@ -7026,7 +7237,8 @@ namespace clang {
StringRef Next() override;
};
-}
+
+} // end namespace clang
ASTIdentifierIterator::ASTIdentifierIterator(const ASTReader &Reader,
bool SkipModules)
@@ -7058,6 +7270,7 @@ StringRef ASTIdentifierIterator::Next() {
}
namespace {
+
/// A utility for appending two IdentifierIterators.
class ChainedIdentifierIterator : public IdentifierIterator {
std::unique_ptr<IdentifierIterator> Current;
@@ -7082,6 +7295,7 @@ public:
return Next();
}
};
+
} // end anonymous namespace.
IdentifierIterator *ASTReader::getIdentifiers() {
@@ -7097,7 +7311,9 @@ IdentifierIterator *ASTReader::getIdentifiers() {
return new ASTIdentifierIterator(*this);
}
-namespace clang { namespace serialization {
+namespace clang {
+namespace serialization {
+
class ReadMethodPoolVisitor {
ASTReader &Reader;
Selector Sel;
@@ -7119,7 +7335,7 @@ namespace clang { namespace serialization {
bool operator()(ModuleFile &M) {
if (!M.SelectorLookupTable)
return false;
-
+
// If we've already searched this module file, skip it now.
if (M.Generation <= PriorGeneration)
return true;
@@ -7149,14 +7365,14 @@ namespace clang { namespace serialization {
FactoryHasMoreThanOneDecl = Data.FactoryHasMoreThanOneDecl;
return true;
}
-
+
/// \brief Retrieve the instance methods found by this visitor.
- ArrayRef<ObjCMethodDecl *> getInstanceMethods() const {
- return InstanceMethods;
+ ArrayRef<ObjCMethodDecl *> getInstanceMethods() const {
+ return InstanceMethods;
}
/// \brief Retrieve the instance methods found by this visitor.
- ArrayRef<ObjCMethodDecl *> getFactoryMethods() const {
+ ArrayRef<ObjCMethodDecl *> getFactoryMethods() const {
return FactoryMethods;
}
@@ -7167,7 +7383,9 @@ namespace clang { namespace serialization {
}
bool factoryHasMoreThanOneDecl() const { return FactoryHasMoreThanOneDecl; }
};
-} } // end namespace clang::serialization
+
+} // end namespace serialization
+} // end namespace clang
/// \brief Add the given set of methods to the method list.
static void addMethodsToPool(Sema &S, ArrayRef<ObjCMethodDecl *> Methods,
@@ -7176,14 +7394,14 @@ static void addMethodsToPool(Sema &S, ArrayRef<ObjCMethodDecl *> Methods,
S.addMethodToGlobalList(&List, Methods[I]);
}
}
-
+
void ASTReader::ReadMethodPool(Selector Sel) {
// Get the selector generation and update it to the current generation.
unsigned &Generation = SelectorGeneration[Sel];
unsigned PriorGeneration = Generation;
Generation = getGeneration();
SelectorOutOfDate[Sel] = false;
-
+
// Search for methods defined with this selector.
++NumMethodPoolLookups;
ReadMethodPoolVisitor Visitor(*this, Sel, PriorGeneration);
@@ -7197,7 +7415,7 @@ void ASTReader::ReadMethodPool(Selector Sel) {
if (!getSema())
return;
-
+
Sema &S = *getSema();
Sema::GlobalMethodPool::iterator Pos
= S.MethodPool.insert(std::make_pair(Sel, Sema::GlobalMethods())).first;
@@ -7222,9 +7440,9 @@ void ASTReader::updateOutOfDateSelector(Selector Sel) {
void ASTReader::ReadKnownNamespaces(
SmallVectorImpl<NamespaceDecl *> &Namespaces) {
Namespaces.clear();
-
+
for (unsigned I = 0, N = KnownNamespaces.size(); I != N; ++I) {
- if (NamespaceDecl *Namespace
+ if (NamespaceDecl *Namespace
= dyn_cast_or_null<NamespaceDecl>(GetDecl(KnownNamespaces[I])))
Namespaces.push_back(Namespace);
}
@@ -7313,7 +7531,7 @@ void ASTReader::ReadReferencedSelectors(
SmallVectorImpl<std::pair<Selector, SourceLocation> > &Sels) {
if (ReferencedSelectorsData.empty())
return;
-
+
// If there are @selector references added them to its pool. This is for
// implementation of -Wselector.
unsigned int DataSize = ReferencedSelectorsData.size()-1;
@@ -7333,9 +7551,9 @@ void ASTReader::ReadWeakUndeclaredIdentifiers(
return;
for (unsigned I = 0, N = WeakUndeclaredIdentifiers.size(); I < N; /*none*/) {
- IdentifierInfo *WeakId
+ IdentifierInfo *WeakId
= DecodeIdentifierInfo(WeakUndeclaredIdentifiers[I++]);
- IdentifierInfo *AliasId
+ IdentifierInfo *AliasId
= DecodeIdentifierInfo(WeakUndeclaredIdentifiers[I++]);
SourceLocation Loc
= SourceLocation::getFromRawEncoding(WeakUndeclaredIdentifiers[I++]);
@@ -7355,7 +7573,7 @@ void ASTReader::ReadUsedVTables(SmallVectorImpl<ExternalVTableUse> &VTables) {
VT.DefinitionRequired = VTableUses[Idx++];
VTables.push_back(VT);
}
-
+
VTableUses.clear();
}
@@ -7367,17 +7585,18 @@ void ASTReader::ReadPendingInstantiations(
= SourceLocation::getFromRawEncoding(PendingInstantiations[Idx++]);
Pending.push_back(std::make_pair(D, Loc));
- }
+ }
PendingInstantiations.clear();
}
void ASTReader::ReadLateParsedTemplates(
- llvm::MapVector<const FunctionDecl *, LateParsedTemplate *> &LPTMap) {
+ llvm::MapVector<const FunctionDecl *, std::unique_ptr<LateParsedTemplate>>
+ &LPTMap) {
for (unsigned Idx = 0, N = LateParsedTemplates.size(); Idx < N;
/* In loop */) {
FunctionDecl *FD = cast<FunctionDecl>(GetDecl(LateParsedTemplates[Idx++]));
- LateParsedTemplate *LT = new LateParsedTemplate;
+ auto LT = llvm::make_unique<LateParsedTemplate>();
LT->D = GetDecl(LateParsedTemplates[Idx++]);
ModuleFile *F = getOwningModuleFile(LT->D);
@@ -7388,7 +7607,7 @@ void ASTReader::ReadLateParsedTemplates(
for (unsigned T = 0; T < TokN; ++T)
LT->Toks.push_back(ReadToken(*F, LateParsedTemplates, Idx));
- LPTMap.insert(std::make_pair(FD, LT));
+ LPTMap.insert(std::make_pair(FD, std::move(LT)));
}
LateParsedTemplates.clear();
@@ -7498,12 +7717,12 @@ IdentifierInfo *ASTReader::getLocalIdentifier(ModuleFile &M, unsigned LocalID) {
IdentifierID ASTReader::getGlobalIdentifierID(ModuleFile &M, unsigned LocalID) {
if (LocalID < NUM_PREDEF_IDENT_IDS)
return LocalID;
-
+
ContinuousRangeMap<uint32_t, int, 2>::iterator I
= M.IdentifierRemap.find(LocalID - NUM_PREDEF_IDENT_IDS);
- assert(I != M.IdentifierRemap.end()
+ assert(I != M.IdentifierRemap.end()
&& "Invalid index into identifier index remap");
-
+
return LocalID + I->second;
}
@@ -7524,7 +7743,7 @@ MacroInfo *ASTReader::getMacro(MacroID ID) {
ModuleFile *M = I->second;
unsigned Index = ID - M->BaseMacroID;
MacrosLoaded[ID] = ReadMacroRecord(*M, M->MacroOffsets[Index]);
-
+
if (DeserializationListener)
DeserializationListener->MacroRead(ID + NUM_PREDEF_MACRO_IDS,
MacrosLoaded[ID]);
@@ -7548,12 +7767,12 @@ serialization::SubmoduleID
ASTReader::getGlobalSubmoduleID(ModuleFile &M, unsigned LocalID) {
if (LocalID < NUM_PREDEF_SUBMODULE_IDS)
return LocalID;
-
+
ContinuousRangeMap<uint32_t, int, 2>::iterator I
= M.SubmoduleRemap.find(LocalID - NUM_PREDEF_SUBMODULE_IDS);
- assert(I != M.SubmoduleRemap.end()
+ assert(I != M.SubmoduleRemap.end()
&& "Invalid index into submodule index remap");
-
+
return LocalID + I->second;
}
@@ -7562,12 +7781,12 @@ Module *ASTReader::getSubmodule(SubmoduleID GlobalID) {
assert(GlobalID == 0 && "Unhandled global submodule ID");
return nullptr;
}
-
+
if (GlobalID > SubmodulesLoaded.size()) {
Error("submodule ID out of range in AST file");
return nullptr;
}
-
+
return SubmodulesLoaded[GlobalID - NUM_PREDEF_SUBMODULE_IDS];
}
@@ -7664,17 +7883,17 @@ serialization::SelectorID
ASTReader::getGlobalSelectorID(ModuleFile &M, unsigned LocalID) const {
if (LocalID < NUM_PREDEF_SELECTOR_IDS)
return LocalID;
-
+
ContinuousRangeMap<uint32_t, int, 2>::iterator I
= M.SelectorRemap.find(LocalID - NUM_PREDEF_SELECTOR_IDS);
- assert(I != M.SelectorRemap.end()
+ assert(I != M.SelectorRemap.end()
&& "Invalid index into selector index remap");
-
+
return LocalID + I->second;
}
DeclarationName
-ASTReader::ReadDeclarationName(ModuleFile &F,
+ASTReader::ReadDeclarationName(ModuleFile &F,
const RecordData &Record, unsigned &Idx) {
DeclarationName::NameKind Kind = (DeclarationName::NameKind)Record[Idx++];
switch (Kind) {
@@ -7762,13 +7981,13 @@ void ASTReader::ReadQualifierInfo(ModuleFile &F, QualifierInfo &Info,
Info.NumTemplParamLists = NumTPLists;
if (NumTPLists) {
Info.TemplParamLists = new (Context) TemplateParameterList*[NumTPLists];
- for (unsigned i=0; i != NumTPLists; ++i)
+ for (unsigned i = 0; i != NumTPLists; ++i)
Info.TemplParamLists[i] = ReadTemplateParameterList(F, Record, Idx);
}
}
TemplateName
-ASTReader::ReadTemplateName(ModuleFile &F, const RecordData &Record,
+ASTReader::ReadTemplateName(ModuleFile &F, const RecordData &Record,
unsigned &Idx) {
TemplateName::NameKind Kind = (TemplateName::NameKind)Record[Idx++];
switch (Kind) {
@@ -7795,7 +8014,7 @@ ASTReader::ReadTemplateName(ModuleFile &F, const RecordData &Record,
NestedNameSpecifier *NNS = ReadNestedNameSpecifier(F, Record, Idx);
if (Record[Idx++]) // isIdentifier
return Context.getDependentTemplateName(NNS,
- GetIdentifierInfo(F, Record,
+ GetIdentifierInfo(F, Record,
Idx));
return Context.getDependentTemplateName(NNS,
(OverloadedOperatorKind)Record[Idx++]);
@@ -7808,17 +8027,17 @@ ASTReader::ReadTemplateName(ModuleFile &F, const RecordData &Record,
TemplateName replacement = ReadTemplateName(F, Record, Idx);
return Context.getSubstTemplateTemplateParm(param, replacement);
}
-
+
case TemplateName::SubstTemplateTemplateParmPack: {
- TemplateTemplateParmDecl *Param
+ TemplateTemplateParmDecl *Param
= ReadDeclAs<TemplateTemplateParmDecl>(F, Record, Idx);
if (!Param)
return TemplateName();
-
+
TemplateArgument ArgPack = ReadTemplateArgument(F, Record, Idx);
if (ArgPack.getKind() != TemplateArgument::Pack)
return TemplateName();
-
+
return Context.getSubstTemplateTemplateParmPack(Param, ArgPack);
}
}
@@ -7856,7 +8075,7 @@ TemplateArgument ASTReader::ReadTemplateArgument(ModuleFile &F,
QualType T = readType(F, Record, Idx);
return TemplateArgument(Context, Value, T);
}
- case TemplateArgument::Template:
+ case TemplateArgument::Template:
return TemplateArgument(ReadTemplateName(F, Record, Idx));
case TemplateArgument::TemplateExpansion: {
TemplateName Name = ReadTemplateName(F, Record, Idx);
@@ -7892,9 +8111,10 @@ ASTReader::ReadTemplateParameterList(ModuleFile &F,
while (NumParams--)
Params.push_back(ReadDeclAs<NamedDecl>(F, Record, Idx));
+ // TODO: Concepts
TemplateParameterList* TemplateParams =
TemplateParameterList::Create(Context, TemplateLoc, LAngleLoc,
- Params, RAngleLoc);
+ Params, RAngleLoc, nullptr);
return TemplateParams;
}
@@ -7931,7 +8151,7 @@ ASTReader::ReadCXXBaseSpecifier(ModuleFile &F,
TypeSourceInfo *TInfo = GetTypeSourceInfo(F, Record, Idx);
SourceRange Range = ReadSourceRange(F, Record, Idx);
SourceLocation EllipsisLoc = ReadSourceLocation(F, Record, Idx);
- CXXBaseSpecifier Result(Range, isVirtual, isBaseOfClass, AS, TInfo,
+ CXXBaseSpecifier Result(Range, isVirtual, isBaseOfClass, AS, TInfo,
EllipsisLoc);
Result.setInheritConstructors(inheritConstructors);
return Result;
@@ -7973,49 +8193,29 @@ ASTReader::ReadCXXCtorInitializers(ModuleFile &F, const RecordData &Record,
Expr *Init = ReadExpr(F);
SourceLocation LParenLoc = ReadSourceLocation(F, Record, Idx);
SourceLocation RParenLoc = ReadSourceLocation(F, Record, Idx);
- bool IsWritten = Record[Idx++];
- unsigned SourceOrderOrNumArrayIndices;
- SmallVector<VarDecl *, 8> Indices;
- if (IsWritten) {
- SourceOrderOrNumArrayIndices = Record[Idx++];
- } else {
- SourceOrderOrNumArrayIndices = Record[Idx++];
- Indices.reserve(SourceOrderOrNumArrayIndices);
- for (unsigned i=0; i != SourceOrderOrNumArrayIndices; ++i)
- Indices.push_back(ReadDeclAs<VarDecl>(F, Record, Idx));
- }
CXXCtorInitializer *BOMInit;
- if (Type == CTOR_INITIALIZER_BASE) {
+ if (Type == CTOR_INITIALIZER_BASE)
BOMInit = new (Context)
CXXCtorInitializer(Context, TInfo, IsBaseVirtual, LParenLoc, Init,
RParenLoc, MemberOrEllipsisLoc);
- } else if (Type == CTOR_INITIALIZER_DELEGATING) {
+ else if (Type == CTOR_INITIALIZER_DELEGATING)
BOMInit = new (Context)
CXXCtorInitializer(Context, TInfo, LParenLoc, Init, RParenLoc);
- } else if (IsWritten) {
- if (Member)
- BOMInit = new (Context) CXXCtorInitializer(
- Context, Member, MemberOrEllipsisLoc, LParenLoc, Init, RParenLoc);
- else
- BOMInit = new (Context)
- CXXCtorInitializer(Context, IndirectMember, MemberOrEllipsisLoc,
- LParenLoc, Init, RParenLoc);
- } else {
- if (IndirectMember) {
- assert(Indices.empty() && "Indirect field improperly initialized");
- BOMInit = new (Context)
- CXXCtorInitializer(Context, IndirectMember, MemberOrEllipsisLoc,
- LParenLoc, Init, RParenLoc);
- } else {
- BOMInit = CXXCtorInitializer::Create(
- Context, Member, MemberOrEllipsisLoc, LParenLoc, Init, RParenLoc,
- Indices.data(), Indices.size());
- }
+ else if (Member)
+ BOMInit = new (Context)
+ CXXCtorInitializer(Context, Member, MemberOrEllipsisLoc, LParenLoc,
+ Init, RParenLoc);
+ else
+ BOMInit = new (Context)
+ CXXCtorInitializer(Context, IndirectMember, MemberOrEllipsisLoc,
+ LParenLoc, Init, RParenLoc);
+
+ if (/*IsWritten*/Record[Idx++]) {
+ unsigned SourceOrder = Record[Idx++];
+ BOMInit->setSourceOrder(SourceOrder);
}
- if (IsWritten)
- BOMInit->setSourceOrder(SourceOrderOrNumArrayIndices);
CtorInitializers[i] = BOMInit;
}
@@ -8078,7 +8278,7 @@ ASTReader::ReadNestedNameSpecifier(ModuleFile &F,
}
NestedNameSpecifierLoc
-ASTReader::ReadNestedNameSpecifierLoc(ModuleFile &F, const RecordData &Record,
+ASTReader::ReadNestedNameSpecifierLoc(ModuleFile &F, const RecordData &Record,
unsigned &Idx) {
unsigned N = Record[Idx++];
NestedNameSpecifierLocBuilder Builder;
@@ -8087,7 +8287,7 @@ ASTReader::ReadNestedNameSpecifierLoc(ModuleFile &F, const RecordData &Record,
= (NestedNameSpecifier::SpecifierKind)Record[Idx++];
switch (Kind) {
case NestedNameSpecifier::Identifier: {
- IdentifierInfo *II = GetIdentifierInfo(F, Record, Idx);
+ IdentifierInfo *II = GetIdentifierInfo(F, Record, Idx);
SourceRange Range = ReadSourceRange(F, Record, Idx);
Builder.Extend(Context, II, Range.getBegin(), Range.getEnd());
break;
@@ -8116,7 +8316,7 @@ ASTReader::ReadNestedNameSpecifierLoc(ModuleFile &F, const RecordData &Record,
SourceLocation ColonColonLoc = ReadSourceLocation(F, Record, Idx);
// FIXME: 'template' keyword location not saved anywhere, so we fake it.
- Builder.Extend(Context,
+ Builder.Extend(Context,
Template? T->getTypeLoc().getBeginLoc() : SourceLocation(),
T->getTypeLoc(), ColonColonLoc);
break;
@@ -8185,7 +8385,7 @@ std::string ASTReader::ReadPath(ModuleFile &F, const RecordData &Record,
return Filename;
}
-VersionTuple ASTReader::ReadVersionTuple(const RecordData &Record,
+VersionTuple ASTReader::ReadVersionTuple(const RecordData &Record,
unsigned &Idx) {
unsigned Major = Record[Idx++];
unsigned Minor = Record[Idx++];
@@ -8197,7 +8397,7 @@ VersionTuple ASTReader::ReadVersionTuple(const RecordData &Record,
return VersionTuple(Major, Minor - 1, Subminor - 1);
}
-CXXTemporary *ASTReader::ReadCXXTemporary(ModuleFile &F,
+CXXTemporary *ASTReader::ReadCXXTemporary(ModuleFile &F,
const RecordData &Record,
unsigned &Idx) {
CXXDestructorDecl *Decl = ReadDeclAs<CXXDestructorDecl>(F, Record, Idx);
@@ -8283,6 +8483,10 @@ 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));
Context.Comments.addDeserializedComments(Comments);
}
}
@@ -8350,16 +8554,14 @@ void ASTReader::finishPendingActions() {
for (unsigned IDIdx = 0, NumIDs = GlobalIDs.size(); IDIdx != NumIDs;
++IDIdx) {
const PendingMacroInfo &Info = GlobalIDs[IDIdx];
- if (Info.M->Kind != MK_ImplicitModule &&
- Info.M->Kind != MK_ExplicitModule)
+ if (!Info.M->isModule())
resolvePendingMacro(II, Info);
}
// Handle module imports.
for (unsigned IDIdx = 0, NumIDs = GlobalIDs.size(); IDIdx != NumIDs;
++IDIdx) {
const PendingMacroInfo &Info = GlobalIDs[IDIdx];
- if (Info.M->Kind == MK_ImplicitModule ||
- Info.M->Kind == MK_ExplicitModule)
+ if (Info.M->isModule())
resolvePendingMacro(II, Info);
}
}
@@ -8390,7 +8592,7 @@ void ASTReader::finishPendingActions() {
// If we deserialized any C++ or Objective-C class definitions, any
// Objective-C protocol definitions, or any redeclarable templates, make sure
- // that all redeclarations point to the definitions. Note that this can only
+ // that all redeclarations point to the definitions. Note that this can only
// happen now, after the redeclaration chains have been fully wired.
for (Decl *D : PendingDefinitions) {
if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
@@ -8446,8 +8648,11 @@ void ASTReader::finishPendingActions() {
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(PB->first)) {
// FIXME: Check for =delete/=default?
// FIXME: Complain about ODR violations here?
- if (!getContext().getLangOpts().Modules || !FD->hasBody())
+ const FunctionDecl *Defn = nullptr;
+ if (!getContext().getLangOpts().Modules || !FD->hasBody(Defn))
FD->setLazyBody(PB->second);
+ else
+ mergeDefinitionVisibility(const_cast<FunctionDecl*>(Defn), FD);
continue;
}
@@ -8542,7 +8747,7 @@ void ASTReader::diagnoseOdrViolations() {
// completed. We only really need to mark FieldDecls as invalid here.
if (!isa<TagDecl>(D))
D->setInvalidDecl();
-
+
// Ensure we don't accidentally recursively enter deserialization while
// we're producing our diagnostic.
Deserializing RecursionGuard(this);
@@ -8617,7 +8822,7 @@ void ASTReader::diagnoseOdrViolations() {
}
void ASTReader::StartedDeserializing() {
- if (++NumCurrentElementsDeserializing == 1 && ReadTimer.get())
+ if (++NumCurrentElementsDeserializing == 1 && ReadTimer.get())
ReadTimer->startTimer();
}
@@ -8694,7 +8899,10 @@ ASTReader::ASTReader(
bool AllowConfigurationMismatch, bool ValidateSystemInputs,
bool UseGlobalIndex,
std::unique_ptr<llvm::Timer> ReadTimer)
- : Listener(new PCHValidator(PP, *this)), DeserializationListener(nullptr),
+ : Listener(DisableValidation ?
+ cast<ASTReaderListener>(new SimpleASTReaderListener(PP)) :
+ cast<ASTReaderListener>(new PCHValidator(PP, *this))),
+ DeserializationListener(nullptr),
OwnsDeserializationListener(false), SourceMgr(PP.getSourceManager()),
FileMgr(PP.getFileManager()), PCHContainerRdr(PCHContainerRdr),
Diags(PP.getDiagnostics()), SemaObj(nullptr), PP(PP), Context(Context),
@@ -8743,3 +8951,10 @@ ASTReader::~ASTReader() {
IdentifierResolver &ASTReader::getIdResolver() {
return SemaObj ? SemaObj->IdResolver : DummyIdResolver;
}
+
+unsigned ASTRecordReader::readRecord(llvm::BitstreamCursor &Cursor,
+ unsigned AbbrevID) {
+ Idx = 0;
+ Record.clear();
+ return Cursor.readRecord(AbbrevID, Record);
+}
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index 35da8f3ebcfe..6e18b208a9ae 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -12,10 +12,8 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Serialization/ASTReader.h"
#include "ASTCommon.h"
#include "ASTReaderInternals.h"
-#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclGroup.h"
@@ -24,6 +22,7 @@
#include "clang/AST/Expr.h"
#include "clang/Sema/IdentifierResolver.h"
#include "clang/Sema/SemaDiagnostic.h"
+#include "clang/Serialization/ASTReader.h"
#include "llvm/Support/SaveAndRestore.h"
using namespace clang;
@@ -36,13 +35,11 @@ using namespace clang::serialization;
namespace clang {
class ASTDeclReader : public DeclVisitor<ASTDeclReader, void> {
ASTReader &Reader;
- ModuleFile &F;
- uint64_t Offset;
+ ASTRecordReader &Record;
+ ASTReader::RecordLocation Loc;
const DeclID ThisDeclID;
const SourceLocation ThisDeclLoc;
typedef ASTReader::RecordData RecordData;
- const RecordData &Record;
- unsigned &Idx;
TypeID TypeIDForTypeDecl;
unsigned AnonymousDeclNumber;
GlobalDeclID NamedDeclForTagDecl;
@@ -57,83 +54,77 @@ namespace clang {
uint64_t GetCurrentCursorOffset();
- uint64_t ReadLocalOffset(const RecordData &R, unsigned &I) {
- uint64_t LocalOffset = R[I++];
- assert(LocalOffset < Offset && "offset point after current record");
- return LocalOffset ? Offset - LocalOffset : 0;
+ uint64_t ReadLocalOffset() {
+ uint64_t LocalOffset = Record.readInt();
+ assert(LocalOffset < Loc.Offset && "offset point after current record");
+ return LocalOffset ? Loc.Offset - LocalOffset : 0;
}
- uint64_t ReadGlobalOffset(ModuleFile &F, const RecordData &R, unsigned &I) {
- uint64_t Local = ReadLocalOffset(R, I);
- return Local ? Reader.getGlobalBitOffset(F, Local) : 0;
+ uint64_t ReadGlobalOffset() {
+ uint64_t Local = ReadLocalOffset();
+ return Local ? Record.getGlobalBitOffset(Local) : 0;
}
- SourceLocation ReadSourceLocation(const RecordData &R, unsigned &I) {
- return Reader.ReadSourceLocation(F, R, I);
+ SourceLocation ReadSourceLocation() {
+ return Record.readSourceLocation();
}
- SourceRange ReadSourceRange(const RecordData &R, unsigned &I) {
- return Reader.ReadSourceRange(F, R, I);
+ SourceRange ReadSourceRange() {
+ return Record.readSourceRange();
}
- TypeSourceInfo *GetTypeSourceInfo(const RecordData &R, unsigned &I) {
- return Reader.GetTypeSourceInfo(F, R, I);
+ TypeSourceInfo *GetTypeSourceInfo() {
+ return Record.getTypeSourceInfo();
}
- serialization::DeclID ReadDeclID(const RecordData &R, unsigned &I) {
- return Reader.ReadDeclID(F, R, I);
+ serialization::DeclID ReadDeclID() {
+ return Record.readDeclID();
}
- std::string ReadString(const RecordData &R, unsigned &I) {
- return Reader.ReadString(R, I);
+ std::string ReadString() {
+ return Record.readString();
}
void ReadDeclIDList(SmallVectorImpl<DeclID> &IDs) {
- for (unsigned I = 0, Size = Record[Idx++]; I != Size; ++I)
- IDs.push_back(ReadDeclID(Record, Idx));
+ for (unsigned I = 0, Size = Record.readInt(); I != Size; ++I)
+ IDs.push_back(ReadDeclID());
}
- Decl *ReadDecl(const RecordData &R, unsigned &I) {
- return Reader.ReadDecl(F, R, I);
+ Decl *ReadDecl() {
+ return Record.readDecl();
}
template<typename T>
- T *ReadDeclAs(const RecordData &R, unsigned &I) {
- return Reader.ReadDeclAs<T>(F, R, I);
+ T *ReadDeclAs() {
+ return Record.readDeclAs<T>();
}
- void ReadQualifierInfo(QualifierInfo &Info,
- const RecordData &R, unsigned &I) {
- Reader.ReadQualifierInfo(F, Info, R, I);
- }
-
- void ReadDeclarationNameLoc(DeclarationNameLoc &DNLoc, DeclarationName Name,
- const RecordData &R, unsigned &I) {
- Reader.ReadDeclarationNameLoc(F, DNLoc, Name, R, I);
+ void ReadQualifierInfo(QualifierInfo &Info) {
+ Record.readQualifierInfo(Info);
}
-
- void ReadDeclarationNameInfo(DeclarationNameInfo &NameInfo,
- const RecordData &R, unsigned &I) {
- Reader.ReadDeclarationNameInfo(F, NameInfo, R, I);
+
+ void ReadDeclarationNameLoc(DeclarationNameLoc &DNLoc, DeclarationName Name) {
+ Record.readDeclarationNameLoc(DNLoc, Name);
}
- serialization::SubmoduleID readSubmoduleID(const RecordData &R,
- unsigned &I) {
- if (I >= R.size())
+ serialization::SubmoduleID readSubmoduleID() {
+ if (Record.getIdx() == Record.size())
return 0;
-
- return Reader.getGlobalSubmoduleID(F, R[I++]);
+
+ return Record.getGlobalSubmoduleID(Record.readInt());
}
-
- Module *readModule(const RecordData &R, unsigned &I) {
- return Reader.getSubmodule(readSubmoduleID(R, I));
+
+ Module *readModule() {
+ return Record.getSubmodule(readSubmoduleID());
}
void ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update);
- void ReadCXXDefinitionData(struct CXXRecordDecl::DefinitionData &Data,
- const RecordData &R, unsigned &I);
+ void ReadCXXDefinitionData(struct CXXRecordDecl::DefinitionData &Data);
void MergeDefinitionData(CXXRecordDecl *D,
struct CXXRecordDecl::DefinitionData &&NewDD);
+ void ReadObjCDefinitionData(struct ObjCInterfaceDecl::DefinitionData &Data);
+ void MergeDefinitionData(ObjCInterfaceDecl *D,
+ struct ObjCInterfaceDecl::DefinitionData &&NewDD);
static NamedDecl *getAnonymousDeclForMerging(ASTReader &Reader,
DeclContext *DC,
@@ -143,13 +134,13 @@ namespace clang {
/// Results from loading a RedeclarableDecl.
class RedeclarableResult {
- GlobalDeclID FirstID;
Decl *MergeWith;
+ GlobalDeclID FirstID;
bool IsKeyDecl;
public:
- RedeclarableResult(GlobalDeclID FirstID, Decl *MergeWith, bool IsKeyDecl)
- : FirstID(FirstID), MergeWith(MergeWith), IsKeyDecl(IsKeyDecl) {}
+ RedeclarableResult(Decl *MergeWith, GlobalDeclID FirstID, bool IsKeyDecl)
+ : MergeWith(MergeWith), FirstID(FirstID), IsKeyDecl(IsKeyDecl) {}
/// \brief Retrieve the first ID.
GlobalDeclID getFirstID() const { return FirstID; }
@@ -171,12 +162,12 @@ namespace clang {
ASTReader &Reader;
NamedDecl *New;
NamedDecl *Existing;
- mutable bool AddResult;
+ bool AddResult;
unsigned AnonymousDeclNumber;
IdentifierInfo *TypedefNameForLinkage;
- void operator=(FindExistingResult&) = delete;
+ void operator=(FindExistingResult &&) = delete;
public:
FindExistingResult(ASTReader &Reader)
@@ -190,7 +181,7 @@ namespace clang {
AnonymousDeclNumber(AnonymousDeclNumber),
TypedefNameForLinkage(TypedefNameForLinkage) {}
- FindExistingResult(const FindExistingResult &Other)
+ FindExistingResult(FindExistingResult &&Other)
: Reader(Other.Reader), New(Other.New), Existing(Other.Existing),
AddResult(Other.AddResult),
AnonymousDeclNumber(Other.AnonymousDeclNumber),
@@ -215,11 +206,11 @@ namespace clang {
FindExistingResult findExisting(NamedDecl *D);
public:
- ASTDeclReader(ASTReader &Reader, ASTReader::RecordLocation Loc,
- DeclID thisDeclID, SourceLocation ThisDeclLoc,
- const RecordData &Record, unsigned &Idx)
- : Reader(Reader), F(*Loc.F), Offset(Loc.Offset), ThisDeclID(thisDeclID),
- ThisDeclLoc(ThisDeclLoc), Record(Record), Idx(Idx),
+ 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) {}
@@ -251,8 +242,7 @@ namespace clang {
void Visit(Decl *D);
- void UpdateDecl(Decl *D, ModuleFile &ModuleFile,
- const RecordData &Record);
+ void UpdateDecl(Decl *D);
static void setNextObjCCategory(ObjCCategoryDecl *Cat,
ObjCCategoryDecl *Next) {
@@ -313,6 +303,8 @@ namespace clang {
void VisitVarDecl(VarDecl *VD) { VisitVarDeclImpl(VD); }
void VisitImplicitParamDecl(ImplicitParamDecl *PD);
void VisitParmVarDecl(ParmVarDecl *PD);
+ void VisitDecompositionDecl(DecompositionDecl *DD);
+ void VisitBindingDecl(BindingDecl *BD);
void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
DeclID VisitTemplateDecl(TemplateDecl *D);
RedeclarableResult VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D);
@@ -323,9 +315,11 @@ namespace clang {
void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
void VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D);
void VisitUsingDecl(UsingDecl *D);
+ void VisitUsingPackDecl(UsingPackDecl *D);
void VisitUsingShadowDecl(UsingShadowDecl *D);
void VisitConstructorUsingShadowDecl(ConstructorUsingShadowDecl *D);
void VisitLinkageSpecDecl(LinkageSpecDecl *D);
+ void VisitExportDecl(ExportDecl *D);
void VisitFileScopeAsmDecl(FileScopeAsmDecl *AD);
void VisitImportDecl(ImportDecl *D);
void VisitAccessSpecDecl(AccessSpecDecl *D);
@@ -377,27 +371,6 @@ namespace clang {
void VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D);
void VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D);
void VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D);
-
- /// We've merged the definition \p MergedDef into the existing definition
- /// \p Def. Ensure that \p Def is made visible whenever \p MergedDef is made
- /// visible.
- void mergeDefinitionVisibility(NamedDecl *Def, NamedDecl *MergedDef) {
- if (Def->isHidden()) {
- // If MergedDef is visible or becomes visible, make the definition visible.
- if (!MergedDef->isHidden())
- Def->Hidden = false;
- else if (Reader.getContext().getLangOpts().ModulesLocalVisibility) {
- Reader.getContext().mergeDefinitionIntoModule(
- Def, MergedDef->getImportedOwningModule(),
- /*NotifyListeners*/ false);
- Reader.PendingMergedDefinitionsToDeduplicate.insert(Def);
- } else {
- auto SubmoduleID = MergedDef->getOwningModuleID();
- assert(SubmoduleID && "hidden definition in no module");
- Reader.HiddenNamesMap[Reader.getSubmodule(SubmoduleID)].push_back(Def);
- }
- }
- }
};
} // end namespace clang
@@ -437,14 +410,15 @@ public:
};
} // end anonymous namespace
-template<typename DeclT>
-llvm::iterator_range<MergedRedeclIterator<DeclT>> merged_redecls(DeclT *D) {
+template <typename DeclT>
+static llvm::iterator_range<MergedRedeclIterator<DeclT>>
+merged_redecls(DeclT *D) {
return llvm::make_range(MergedRedeclIterator<DeclT>(D),
MergedRedeclIterator<DeclT>());
}
uint64_t ASTDeclReader::GetCurrentCursorOffset() {
- return F.DeclsCursor.GetCurrentBitNo() + F.GlobalBitOffset;
+ return Loc.F->DeclsCursor.GetCurrentBitNo() + Loc.F->GlobalBitOffset;
}
void ASTDeclReader::Visit(Decl *D) {
@@ -459,11 +433,10 @@ void ASTDeclReader::Visit(Decl *D) {
if (DD->DeclInfo) {
DeclaratorDecl::ExtInfo *Info =
DD->DeclInfo.get<DeclaratorDecl::ExtInfo *>();
- Info->TInfo =
- GetTypeSourceInfo(Record, Idx);
+ Info->TInfo = GetTypeSourceInfo();
}
else {
- DD->DeclInfo = GetTypeSourceInfo(Record, Idx);
+ DD->DeclInfo = GetTypeSourceInfo();
}
}
@@ -484,11 +457,11 @@ void ASTDeclReader::Visit(Decl *D) {
// We only read it if FD doesn't already have a body (e.g., from another
// module).
// FIXME: Can we diagnose ODR violations somehow?
- if (Record[Idx++]) {
+ if (Record.readInt()) {
if (auto *CD = dyn_cast<CXXConstructorDecl>(FD)) {
- CD->NumCtorInitializers = Record[Idx++];
+ CD->NumCtorInitializers = Record.readInt();
if (CD->NumCtorInitializers)
- CD->CtorInitializers = ReadGlobalOffset(F, Record, Idx);
+ CD->CtorInitializers = ReadGlobalOffset();
}
Reader.PendingBodies[FD] = GetCurrentCursorOffset();
HasPendingBody = true;
@@ -505,8 +478,8 @@ void ASTDeclReader::VisitDecl(Decl *D) {
// example, a function parameter can be used in decltype() in trailing
// return type of the function). Use the translation unit DeclContext as a
// placeholder.
- GlobalDeclID SemaDCIDForTemplateParmDecl = ReadDeclID(Record, Idx);
- GlobalDeclID LexicalDCIDForTemplateParmDecl = ReadDeclID(Record, Idx);
+ GlobalDeclID SemaDCIDForTemplateParmDecl = ReadDeclID();
+ GlobalDeclID LexicalDCIDForTemplateParmDecl = ReadDeclID();
if (!LexicalDCIDForTemplateParmDecl)
LexicalDCIDForTemplateParmDecl = SemaDCIDForTemplateParmDecl;
Reader.addPendingDeclContextInfo(D,
@@ -514,8 +487,8 @@ void ASTDeclReader::VisitDecl(Decl *D) {
LexicalDCIDForTemplateParmDecl);
D->setDeclContext(Reader.getContext().getTranslationUnitDecl());
} else {
- DeclContext *SemaDC = ReadDeclAs<DeclContext>(Record, Idx);
- DeclContext *LexicalDC = ReadDeclAs<DeclContext>(Record, Idx);
+ DeclContext *SemaDC = ReadDeclAs<DeclContext>();
+ DeclContext *LexicalDC = ReadDeclAs<DeclContext>();
if (!LexicalDC)
LexicalDC = SemaDC;
DeclContext *MergedSemaDC = Reader.MergedDeclContexts.lookup(SemaDC);
@@ -525,27 +498,27 @@ void ASTDeclReader::VisitDecl(Decl *D) {
Reader.getContext());
}
D->setLocation(ThisDeclLoc);
- D->setInvalidDecl(Record[Idx++]);
- if (Record[Idx++]) { // hasAttrs
+ D->setInvalidDecl(Record.readInt());
+ if (Record.readInt()) { // hasAttrs
AttrVec Attrs;
- Reader.ReadAttributes(F, Attrs, Record, Idx);
+ Record.readAttributes(Attrs);
// Avoid calling setAttrs() directly because it uses Decl::getASTContext()
// internally which is unsafe during derialization.
D->setAttrsImpl(Attrs, Reader.getContext());
}
- D->setImplicit(Record[Idx++]);
- D->Used = Record[Idx++];
+ D->setImplicit(Record.readInt());
+ D->Used = Record.readInt();
IsDeclMarkedUsed |= D->Used;
- D->setReferenced(Record[Idx++]);
- D->setTopLevelDeclInObjCContainer(Record[Idx++]);
- D->setAccess((AccessSpecifier)Record[Idx++]);
+ D->setReferenced(Record.readInt());
+ D->setTopLevelDeclInObjCContainer(Record.readInt());
+ D->setAccess((AccessSpecifier)Record.readInt());
D->FromASTFile = true;
- D->setModulePrivate(Record[Idx++]);
+ D->setModulePrivate(Record.readInt());
D->Hidden = D->isModulePrivate();
// Determine whether this declaration is part of a (sub)module. If so, it
// may not yet be visible.
- if (unsigned SubmoduleID = readSubmoduleID(Record, Idx)) {
+ if (unsigned SubmoduleID = readSubmoduleID()) {
// Store the owning submodule ID in the declaration.
D->setOwningModuleID(SubmoduleID);
@@ -571,22 +544,22 @@ void ASTDeclReader::VisitDecl(Decl *D) {
void ASTDeclReader::VisitPragmaCommentDecl(PragmaCommentDecl *D) {
VisitDecl(D);
- D->setLocation(ReadSourceLocation(Record, Idx));
- D->CommentKind = (PragmaMSCommentKind)Record[Idx++];
- std::string Arg = ReadString(Record, Idx);
+ D->setLocation(ReadSourceLocation());
+ D->CommentKind = (PragmaMSCommentKind)Record.readInt();
+ std::string Arg = ReadString();
memcpy(D->getTrailingObjects<char>(), Arg.data(), Arg.size());
D->getTrailingObjects<char>()[Arg.size()] = '\0';
}
void ASTDeclReader::VisitPragmaDetectMismatchDecl(PragmaDetectMismatchDecl *D) {
VisitDecl(D);
- D->setLocation(ReadSourceLocation(Record, Idx));
- std::string Name = ReadString(Record, Idx);
+ D->setLocation(ReadSourceLocation());
+ std::string Name = ReadString();
memcpy(D->getTrailingObjects<char>(), Name.data(), Name.size());
D->getTrailingObjects<char>()[Name.size()] = '\0';
D->ValueStart = Name.size() + 1;
- std::string Value = ReadString(Record, Idx);
+ std::string Value = ReadString();
memcpy(D->getTrailingObjects<char>() + D->ValueStart, Value.data(),
Value.size());
D->getTrailingObjects<char>()[D->ValueStart + Value.size()] = '\0';
@@ -598,24 +571,24 @@ void ASTDeclReader::VisitTranslationUnitDecl(TranslationUnitDecl *TU) {
void ASTDeclReader::VisitNamedDecl(NamedDecl *ND) {
VisitDecl(ND);
- ND->setDeclName(Reader.ReadDeclarationName(F, Record, Idx));
- AnonymousDeclNumber = Record[Idx++];
+ ND->setDeclName(Record.readDeclarationName());
+ AnonymousDeclNumber = Record.readInt();
}
void ASTDeclReader::VisitTypeDecl(TypeDecl *TD) {
VisitNamedDecl(TD);
- TD->setLocStart(ReadSourceLocation(Record, Idx));
+ TD->setLocStart(ReadSourceLocation());
// Delay type reading until after we have fully initialized the decl.
- TypeIDForTypeDecl = Reader.getGlobalTypeID(F, Record[Idx++]);
+ TypeIDForTypeDecl = Record.getGlobalTypeID(Record.readInt());
}
ASTDeclReader::RedeclarableResult
ASTDeclReader::VisitTypedefNameDecl(TypedefNameDecl *TD) {
RedeclarableResult Redecl = VisitRedeclarable(TD);
VisitTypeDecl(TD);
- TypeSourceInfo *TInfo = GetTypeSourceInfo(Record, Idx);
- if (Record[Idx++]) { // isModed
- QualType modedT = Reader.readType(F, Record, Idx);
+ TypeSourceInfo *TInfo = GetTypeSourceInfo();
+ if (Record.readInt()) { // isModed
+ QualType modedT = Record.readType();
TD->setModedTypeSourceInfo(TInfo, modedT);
} else
TD->setTypeSourceInfo(TInfo);
@@ -629,7 +602,7 @@ void ASTDeclReader::VisitTypedefDecl(TypedefDecl *TD) {
void ASTDeclReader::VisitTypeAliasDecl(TypeAliasDecl *TD) {
RedeclarableResult Redecl = VisitTypedefNameDecl(TD);
- if (auto *Template = ReadDeclAs<TypeAliasTemplateDecl>(Record, Idx))
+ if (auto *Template = ReadDeclAs<TypeAliasTemplateDecl>())
// Merged when we merge the template.
TD->setDescribedAliasTemplate(Template);
else
@@ -640,27 +613,27 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitTagDecl(TagDecl *TD) {
RedeclarableResult Redecl = VisitRedeclarable(TD);
VisitTypeDecl(TD);
- TD->IdentifierNamespace = Record[Idx++];
- TD->setTagKind((TagDecl::TagKind)Record[Idx++]);
+ TD->IdentifierNamespace = Record.readInt();
+ TD->setTagKind((TagDecl::TagKind)Record.readInt());
if (!isa<CXXRecordDecl>(TD))
- TD->setCompleteDefinition(Record[Idx++]);
- TD->setEmbeddedInDeclarator(Record[Idx++]);
- TD->setFreeStanding(Record[Idx++]);
- TD->setCompleteDefinitionRequired(Record[Idx++]);
- TD->setBraceRange(ReadSourceRange(Record, Idx));
+ TD->setCompleteDefinition(Record.readInt());
+ TD->setEmbeddedInDeclarator(Record.readInt());
+ TD->setFreeStanding(Record.readInt());
+ TD->setCompleteDefinitionRequired(Record.readInt());
+ TD->setBraceRange(ReadSourceRange());
- switch (Record[Idx++]) {
+ switch (Record.readInt()) {
case 0:
break;
case 1: { // ExtInfo
TagDecl::ExtInfo *Info = new (Reader.getContext()) TagDecl::ExtInfo();
- ReadQualifierInfo(*Info, Record, Idx);
+ ReadQualifierInfo(*Info);
TD->TypedefNameDeclOrQualifier = Info;
break;
}
case 2: // TypedefNameForAnonDecl
- NamedDeclForTagDecl = ReadDeclID(Record, Idx);
- TypedefNameForLinkage = Reader.GetIdentifierInfo(F, Record, Idx);
+ NamedDeclForTagDecl = ReadDeclID();
+ TypedefNameForLinkage = Record.getIdentifierInfo();
break;
default:
llvm_unreachable("unexpected tag info kind");
@@ -673,16 +646,16 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitTagDecl(TagDecl *TD) {
void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) {
VisitTagDecl(ED);
- if (TypeSourceInfo *TI = Reader.GetTypeSourceInfo(F, Record, Idx))
+ if (TypeSourceInfo *TI = GetTypeSourceInfo())
ED->setIntegerTypeSourceInfo(TI);
else
- ED->setIntegerType(Reader.readType(F, Record, Idx));
- ED->setPromotionType(Reader.readType(F, Record, Idx));
- ED->setNumPositiveBits(Record[Idx++]);
- ED->setNumNegativeBits(Record[Idx++]);
- ED->IsScoped = Record[Idx++];
- ED->IsScopedUsingClassTag = Record[Idx++];
- ED->IsFixed = Record[Idx++];
+ ED->setIntegerType(Record.readType());
+ ED->setPromotionType(Record.readType());
+ ED->setNumPositiveBits(Record.readInt());
+ ED->setNumNegativeBits(Record.readInt());
+ ED->IsScoped = Record.readInt();
+ ED->IsScopedUsingClassTag = Record.readInt();
+ ED->IsFixed = Record.readInt();
// If this is a definition subject to the ODR, and we already have a
// definition, merge this one into it.
@@ -703,15 +676,16 @@ void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) {
if (OldDef) {
Reader.MergedDeclContexts.insert(std::make_pair(ED, OldDef));
ED->IsCompleteDefinition = false;
- mergeDefinitionVisibility(OldDef, ED);
+ Reader.mergeDefinitionVisibility(OldDef, ED);
} else {
OldDef = ED;
}
}
- if (EnumDecl *InstED = ReadDeclAs<EnumDecl>(Record, Idx)) {
- TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++];
- SourceLocation POI = ReadSourceLocation(Record, Idx);
+ if (EnumDecl *InstED = ReadDeclAs<EnumDecl>()) {
+ TemplateSpecializationKind TSK =
+ (TemplateSpecializationKind)Record.readInt();
+ SourceLocation POI = ReadSourceLocation();
ED->setInstantiationOfMemberEnum(Reader.getContext(), InstED, TSK);
ED->getMemberSpecializationInfo()->setPointOfInstantiation(POI);
}
@@ -720,33 +694,33 @@ void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) {
ASTDeclReader::RedeclarableResult
ASTDeclReader::VisitRecordDeclImpl(RecordDecl *RD) {
RedeclarableResult Redecl = VisitTagDecl(RD);
- RD->setHasFlexibleArrayMember(Record[Idx++]);
- RD->setAnonymousStructOrUnion(Record[Idx++]);
- RD->setHasObjectMember(Record[Idx++]);
- RD->setHasVolatileMember(Record[Idx++]);
+ RD->setHasFlexibleArrayMember(Record.readInt());
+ RD->setAnonymousStructOrUnion(Record.readInt());
+ RD->setHasObjectMember(Record.readInt());
+ RD->setHasVolatileMember(Record.readInt());
return Redecl;
}
void ASTDeclReader::VisitValueDecl(ValueDecl *VD) {
VisitNamedDecl(VD);
- VD->setType(Reader.readType(F, Record, Idx));
+ VD->setType(Record.readType());
}
void ASTDeclReader::VisitEnumConstantDecl(EnumConstantDecl *ECD) {
VisitValueDecl(ECD);
- if (Record[Idx++])
- ECD->setInitExpr(Reader.ReadExpr(F));
- ECD->setInitVal(Reader.ReadAPSInt(Record, Idx));
+ if (Record.readInt())
+ ECD->setInitExpr(Record.readExpr());
+ ECD->setInitVal(Record.readAPSInt());
mergeMergeable(ECD);
}
void ASTDeclReader::VisitDeclaratorDecl(DeclaratorDecl *DD) {
VisitValueDecl(DD);
- DD->setInnerLocStart(ReadSourceLocation(Record, Idx));
- if (Record[Idx++]) { // hasExtInfo
+ DD->setInnerLocStart(ReadSourceLocation());
+ if (Record.readInt()) { // hasExtInfo
DeclaratorDecl::ExtInfo *Info
= new (Reader.getContext()) DeclaratorDecl::ExtInfo();
- ReadQualifierInfo(*Info, Record, Idx);
+ ReadQualifierInfo(*Info);
DD->DeclInfo = Info;
}
}
@@ -755,74 +729,72 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
RedeclarableResult Redecl = VisitRedeclarable(FD);
VisitDeclaratorDecl(FD);
- ReadDeclarationNameLoc(FD->DNLoc, FD->getDeclName(), Record, Idx);
- FD->IdentifierNamespace = Record[Idx++];
-
+ ReadDeclarationNameLoc(FD->DNLoc, FD->getDeclName());
+ FD->IdentifierNamespace = Record.readInt();
+
// FunctionDecl's body is handled last at ASTDeclReader::Visit,
// after everything else is read.
- FD->SClass = (StorageClass)Record[Idx++];
- FD->IsInline = Record[Idx++];
- FD->IsInlineSpecified = Record[Idx++];
- FD->IsVirtualAsWritten = Record[Idx++];
- FD->IsPure = Record[Idx++];
- FD->HasInheritedPrototype = Record[Idx++];
- FD->HasWrittenPrototype = Record[Idx++];
- FD->IsDeleted = Record[Idx++];
- FD->IsTrivial = Record[Idx++];
- FD->IsDefaulted = Record[Idx++];
- FD->IsExplicitlyDefaulted = Record[Idx++];
- FD->HasImplicitReturnZero = Record[Idx++];
- FD->IsConstexpr = Record[Idx++];
- FD->HasSkippedBody = Record[Idx++];
- FD->IsLateTemplateParsed = Record[Idx++];
- FD->setCachedLinkage(Linkage(Record[Idx++]));
- FD->EndRangeLoc = ReadSourceLocation(Record, Idx);
-
- switch ((FunctionDecl::TemplatedKind)Record[Idx++]) {
+ FD->SClass = (StorageClass)Record.readInt();
+ FD->IsInline = Record.readInt();
+ FD->IsInlineSpecified = Record.readInt();
+ FD->IsVirtualAsWritten = Record.readInt();
+ FD->IsPure = Record.readInt();
+ FD->HasInheritedPrototype = Record.readInt();
+ FD->HasWrittenPrototype = Record.readInt();
+ FD->IsDeleted = Record.readInt();
+ FD->IsTrivial = Record.readInt();
+ FD->IsDefaulted = Record.readInt();
+ FD->IsExplicitlyDefaulted = Record.readInt();
+ FD->HasImplicitReturnZero = Record.readInt();
+ FD->IsConstexpr = Record.readInt();
+ FD->HasSkippedBody = Record.readInt();
+ FD->IsLateTemplateParsed = Record.readInt();
+ FD->setCachedLinkage(Linkage(Record.readInt()));
+ FD->EndRangeLoc = ReadSourceLocation();
+
+ switch ((FunctionDecl::TemplatedKind)Record.readInt()) {
case FunctionDecl::TK_NonTemplate:
mergeRedeclarable(FD, Redecl);
break;
case FunctionDecl::TK_FunctionTemplate:
// Merged when we merge the template.
- FD->setDescribedFunctionTemplate(ReadDeclAs<FunctionTemplateDecl>(Record,
- Idx));
+ FD->setDescribedFunctionTemplate(ReadDeclAs<FunctionTemplateDecl>());
break;
case FunctionDecl::TK_MemberSpecialization: {
- FunctionDecl *InstFD = ReadDeclAs<FunctionDecl>(Record, Idx);
- TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++];
- SourceLocation POI = ReadSourceLocation(Record, Idx);
+ FunctionDecl *InstFD = ReadDeclAs<FunctionDecl>();
+ TemplateSpecializationKind TSK =
+ (TemplateSpecializationKind)Record.readInt();
+ SourceLocation POI = ReadSourceLocation();
FD->setInstantiationOfMemberFunction(Reader.getContext(), InstFD, TSK);
FD->getMemberSpecializationInfo()->setPointOfInstantiation(POI);
mergeRedeclarable(FD, Redecl);
break;
}
case FunctionDecl::TK_FunctionTemplateSpecialization: {
- FunctionTemplateDecl *Template = ReadDeclAs<FunctionTemplateDecl>(Record,
- Idx);
- TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++];
-
+ FunctionTemplateDecl *Template = ReadDeclAs<FunctionTemplateDecl>();
+ TemplateSpecializationKind TSK =
+ (TemplateSpecializationKind)Record.readInt();
+
// Template arguments.
SmallVector<TemplateArgument, 8> TemplArgs;
- Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx,
- /*Canonicalize*/ true);
+ Record.readTemplateArgumentList(TemplArgs, /*Canonicalize*/ true);
// Template args as written.
SmallVector<TemplateArgumentLoc, 8> TemplArgLocs;
SourceLocation LAngleLoc, RAngleLoc;
- bool HasTemplateArgumentsAsWritten = Record[Idx++];
+ bool HasTemplateArgumentsAsWritten = Record.readInt();
if (HasTemplateArgumentsAsWritten) {
- unsigned NumTemplateArgLocs = Record[Idx++];
+ unsigned NumTemplateArgLocs = Record.readInt();
TemplArgLocs.reserve(NumTemplateArgLocs);
for (unsigned i=0; i != NumTemplateArgLocs; ++i)
- TemplArgLocs.push_back(
- Reader.ReadTemplateArgumentLoc(F, Record, Idx));
-
- LAngleLoc = ReadSourceLocation(Record, Idx);
- RAngleLoc = ReadSourceLocation(Record, Idx);
+ TemplArgLocs.push_back(Record.readTemplateArgumentLoc());
+
+ LAngleLoc = ReadSourceLocation();
+ RAngleLoc = ReadSourceLocation();
}
-
- SourceLocation POI = ReadSourceLocation(Record, Idx);
+
+ SourceLocation POI = ReadSourceLocation();
ASTContext &C = Reader.getContext();
TemplateArgumentList *TemplArgList
@@ -841,8 +813,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>(Record, Idx);
+ FunctionTemplateDecl *CanonTemplate = ReadDeclAs<FunctionTemplateDecl>();
// Get the InsertPos by FindNodeOrInsertPos() instead of calling
// InsertNode(FTInfo) directly to avoid the getASTContext() call in
// FunctionTemplateSpecializationInfo's Profile().
@@ -867,18 +838,18 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
case FunctionDecl::TK_DependentFunctionTemplateSpecialization: {
// Templates.
UnresolvedSet<8> TemplDecls;
- unsigned NumTemplates = Record[Idx++];
+ unsigned NumTemplates = Record.readInt();
while (NumTemplates--)
- TemplDecls.addDecl(ReadDeclAs<NamedDecl>(Record, Idx));
-
+ TemplDecls.addDecl(ReadDeclAs<NamedDecl>());
+
// Templates args.
TemplateArgumentListInfo TemplArgs;
- unsigned NumArgs = Record[Idx++];
+ unsigned NumArgs = Record.readInt();
while (NumArgs--)
- TemplArgs.addArgument(Reader.ReadTemplateArgumentLoc(F, Record, Idx));
- TemplArgs.setLAngleLoc(ReadSourceLocation(Record, Idx));
- TemplArgs.setRAngleLoc(ReadSourceLocation(Record, Idx));
-
+ TemplArgs.addArgument(Record.readTemplateArgumentLoc());
+ TemplArgs.setLAngleLoc(ReadSourceLocation());
+ TemplArgs.setRAngleLoc(ReadSourceLocation());
+
FD->setDependentTemplateSpecialization(Reader.getContext(),
TemplDecls, TemplArgs);
// These are not merged; we don't need to merge redeclarations of dependent
@@ -888,55 +859,55 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
}
// Read in the parameters.
- unsigned NumParams = Record[Idx++];
+ unsigned NumParams = Record.readInt();
SmallVector<ParmVarDecl *, 16> Params;
Params.reserve(NumParams);
for (unsigned I = 0; I != NumParams; ++I)
- Params.push_back(ReadDeclAs<ParmVarDecl>(Record, Idx));
+ Params.push_back(ReadDeclAs<ParmVarDecl>());
FD->setParams(Reader.getContext(), Params);
}
void ASTDeclReader::VisitObjCMethodDecl(ObjCMethodDecl *MD) {
VisitNamedDecl(MD);
- if (Record[Idx++]) {
+ if (Record.readInt()) {
// Load the body on-demand. Most clients won't care, because method
// definitions rarely show up in headers.
Reader.PendingBodies[MD] = GetCurrentCursorOffset();
HasPendingBody = true;
- MD->setSelfDecl(ReadDeclAs<ImplicitParamDecl>(Record, Idx));
- MD->setCmdDecl(ReadDeclAs<ImplicitParamDecl>(Record, Idx));
- }
- MD->setInstanceMethod(Record[Idx++]);
- MD->setVariadic(Record[Idx++]);
- MD->setPropertyAccessor(Record[Idx++]);
- MD->setDefined(Record[Idx++]);
- MD->IsOverriding = Record[Idx++];
- MD->HasSkippedBody = Record[Idx++];
-
- MD->IsRedeclaration = Record[Idx++];
- MD->HasRedeclaration = Record[Idx++];
+ MD->setSelfDecl(ReadDeclAs<ImplicitParamDecl>());
+ MD->setCmdDecl(ReadDeclAs<ImplicitParamDecl>());
+ }
+ MD->setInstanceMethod(Record.readInt());
+ MD->setVariadic(Record.readInt());
+ MD->setPropertyAccessor(Record.readInt());
+ MD->setDefined(Record.readInt());
+ MD->IsOverriding = Record.readInt();
+ MD->HasSkippedBody = Record.readInt();
+
+ MD->IsRedeclaration = Record.readInt();
+ MD->HasRedeclaration = Record.readInt();
if (MD->HasRedeclaration)
Reader.getContext().setObjCMethodRedeclaration(MD,
- ReadDeclAs<ObjCMethodDecl>(Record, Idx));
-
- MD->setDeclImplementation((ObjCMethodDecl::ImplementationControl)Record[Idx++]);
- MD->setObjCDeclQualifier((Decl::ObjCDeclQualifier)Record[Idx++]);
- MD->SetRelatedResultType(Record[Idx++]);
- MD->setReturnType(Reader.readType(F, Record, Idx));
- MD->setReturnTypeSourceInfo(GetTypeSourceInfo(Record, Idx));
- MD->DeclEndLoc = ReadSourceLocation(Record, Idx);
- unsigned NumParams = Record[Idx++];
+ ReadDeclAs<ObjCMethodDecl>());
+
+ MD->setDeclImplementation((ObjCMethodDecl::ImplementationControl)Record.readInt());
+ MD->setObjCDeclQualifier((Decl::ObjCDeclQualifier)Record.readInt());
+ MD->SetRelatedResultType(Record.readInt());
+ MD->setReturnType(Record.readType());
+ MD->setReturnTypeSourceInfo(GetTypeSourceInfo());
+ MD->DeclEndLoc = ReadSourceLocation();
+ unsigned NumParams = Record.readInt();
SmallVector<ParmVarDecl *, 16> Params;
Params.reserve(NumParams);
for (unsigned I = 0; I != NumParams; ++I)
- Params.push_back(ReadDeclAs<ParmVarDecl>(Record, Idx));
+ Params.push_back(ReadDeclAs<ParmVarDecl>());
- MD->SelLocsKind = Record[Idx++];
- unsigned NumStoredSelLocs = Record[Idx++];
+ MD->SelLocsKind = Record.readInt();
+ unsigned NumStoredSelLocs = Record.readInt();
SmallVector<SourceLocation, 16> SelLocs;
SelLocs.reserve(NumStoredSelLocs);
for (unsigned i = 0; i != NumStoredSelLocs; ++i)
- SelLocs.push_back(ReadSourceLocation(Record, Idx));
+ SelLocs.push_back(ReadSourceLocation());
MD->setParamsAndSelLocs(Reader.getContext(), Params, SelLocs);
}
@@ -944,91 +915,106 @@ void ASTDeclReader::VisitObjCMethodDecl(ObjCMethodDecl *MD) {
void ASTDeclReader::VisitObjCTypeParamDecl(ObjCTypeParamDecl *D) {
VisitTypedefNameDecl(D);
- D->Variance = Record[Idx++];
- D->Index = Record[Idx++];
- D->VarianceLoc = ReadSourceLocation(Record, Idx);
- D->ColonLoc = ReadSourceLocation(Record, Idx);
+ D->Variance = Record.readInt();
+ D->Index = Record.readInt();
+ D->VarianceLoc = ReadSourceLocation();
+ D->ColonLoc = ReadSourceLocation();
}
void ASTDeclReader::VisitObjCContainerDecl(ObjCContainerDecl *CD) {
VisitNamedDecl(CD);
- CD->setAtStartLoc(ReadSourceLocation(Record, Idx));
- CD->setAtEndRange(ReadSourceRange(Record, Idx));
+ CD->setAtStartLoc(ReadSourceLocation());
+ CD->setAtEndRange(ReadSourceRange());
}
ObjCTypeParamList *ASTDeclReader::ReadObjCTypeParamList() {
- unsigned numParams = Record[Idx++];
+ unsigned numParams = Record.readInt();
if (numParams == 0)
return nullptr;
SmallVector<ObjCTypeParamDecl *, 4> typeParams;
typeParams.reserve(numParams);
for (unsigned i = 0; i != numParams; ++i) {
- auto typeParam = ReadDeclAs<ObjCTypeParamDecl>(Record, Idx);
+ auto typeParam = ReadDeclAs<ObjCTypeParamDecl>();
if (!typeParam)
return nullptr;
typeParams.push_back(typeParam);
}
- SourceLocation lAngleLoc = ReadSourceLocation(Record, Idx);
- SourceLocation rAngleLoc = ReadSourceLocation(Record, Idx);
+ SourceLocation lAngleLoc = ReadSourceLocation();
+ SourceLocation rAngleLoc = ReadSourceLocation();
return ObjCTypeParamList::create(Reader.getContext(), lAngleLoc,
typeParams, rAngleLoc);
}
+void ASTDeclReader::ReadObjCDefinitionData(
+ struct ObjCInterfaceDecl::DefinitionData &Data) {
+ // Read the superclass.
+ Data.SuperClassTInfo = GetTypeSourceInfo();
+
+ Data.EndLoc = ReadSourceLocation();
+ Data.HasDesignatedInitializers = Record.readInt();
+
+ // Read the directly referenced protocols and their SourceLocations.
+ unsigned NumProtocols = Record.readInt();
+ SmallVector<ObjCProtocolDecl *, 16> Protocols;
+ Protocols.reserve(NumProtocols);
+ for (unsigned I = 0; I != NumProtocols; ++I)
+ Protocols.push_back(ReadDeclAs<ObjCProtocolDecl>());
+ SmallVector<SourceLocation, 16> ProtoLocs;
+ ProtoLocs.reserve(NumProtocols);
+ for (unsigned I = 0; I != NumProtocols; ++I)
+ ProtoLocs.push_back(ReadSourceLocation());
+ Data.ReferencedProtocols.set(Protocols.data(), NumProtocols, ProtoLocs.data(),
+ Reader.getContext());
+
+ // Read the transitive closure of protocols referenced by this class.
+ NumProtocols = Record.readInt();
+ Protocols.clear();
+ Protocols.reserve(NumProtocols);
+ for (unsigned I = 0; I != NumProtocols; ++I)
+ Protocols.push_back(ReadDeclAs<ObjCProtocolDecl>());
+ Data.AllReferencedProtocols.set(Protocols.data(), NumProtocols,
+ Reader.getContext());
+}
+
+void ASTDeclReader::MergeDefinitionData(ObjCInterfaceDecl *D,
+ struct ObjCInterfaceDecl::DefinitionData &&NewDD) {
+ // FIXME: odr checking?
+}
+
void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) {
RedeclarableResult Redecl = VisitRedeclarable(ID);
VisitObjCContainerDecl(ID);
- TypeIDForTypeDecl = Reader.getGlobalTypeID(F, Record[Idx++]);
+ TypeIDForTypeDecl = Record.getGlobalTypeID(Record.readInt());
mergeRedeclarable(ID, Redecl);
ID->TypeParamList = ReadObjCTypeParamList();
- if (Record[Idx++]) {
+ if (Record.readInt()) {
// Read the definition.
ID->allocateDefinitionData();
-
- // Set the definition data of the canonical declaration, so other
- // redeclarations will see it.
- ID->getCanonicalDecl()->Data = ID->Data;
-
- ObjCInterfaceDecl::DefinitionData &Data = ID->data();
-
- // Read the superclass.
- Data.SuperClassTInfo = GetTypeSourceInfo(Record, Idx);
- Data.EndLoc = ReadSourceLocation(Record, Idx);
- Data.HasDesignatedInitializers = Record[Idx++];
-
- // Read the directly referenced protocols and their SourceLocations.
- unsigned NumProtocols = Record[Idx++];
- SmallVector<ObjCProtocolDecl *, 16> Protocols;
- Protocols.reserve(NumProtocols);
- for (unsigned I = 0; I != NumProtocols; ++I)
- Protocols.push_back(ReadDeclAs<ObjCProtocolDecl>(Record, Idx));
- SmallVector<SourceLocation, 16> ProtoLocs;
- ProtoLocs.reserve(NumProtocols);
- for (unsigned I = 0; I != NumProtocols; ++I)
- ProtoLocs.push_back(ReadSourceLocation(Record, Idx));
- ID->setProtocolList(Protocols.data(), NumProtocols, ProtoLocs.data(),
- Reader.getContext());
-
- // Read the transitive closure of protocols referenced by this class.
- NumProtocols = Record[Idx++];
- Protocols.clear();
- Protocols.reserve(NumProtocols);
- for (unsigned I = 0; I != NumProtocols; ++I)
- Protocols.push_back(ReadDeclAs<ObjCProtocolDecl>(Record, Idx));
- ID->data().AllReferencedProtocols.set(Protocols.data(), NumProtocols,
- Reader.getContext());
-
- // We will rebuild this list lazily.
- ID->setIvarList(nullptr);
+ ReadObjCDefinitionData(ID->data());
+ ObjCInterfaceDecl *Canon = ID->getCanonicalDecl();
+ if (Canon->Data.getPointer()) {
+ // If we already have a definition, keep the definition invariant and
+ // merge the data.
+ MergeDefinitionData(Canon, std::move(ID->data()));
+ ID->Data = Canon->Data;
+ } else {
+ // Set the definition data of the canonical declaration, so other
+ // redeclarations will see it.
+ ID->getCanonicalDecl()->Data = ID->Data;
+
+ // We will rebuild this list lazily.
+ ID->setIvarList(nullptr);
+ }
// Note that we have deserialized a definition.
Reader.PendingDefinitions.insert(ID);
-
+
// Note that we've loaded this Objective-C class.
Reader.ObjCClassesLoaded.push_back(ID);
} else {
@@ -1038,10 +1024,10 @@ void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) {
void ASTDeclReader::VisitObjCIvarDecl(ObjCIvarDecl *IVD) {
VisitFieldDecl(IVD);
- IVD->setAccessControl((ObjCIvarDecl::AccessControl)Record[Idx++]);
+ IVD->setAccessControl((ObjCIvarDecl::AccessControl)Record.readInt());
// This field will be built lazily.
IVD->setNextIvar(nullptr);
- bool synth = Record[Idx++];
+ bool synth = Record.readInt();
IVD->setSynthesize(synth);
}
@@ -1049,27 +1035,27 @@ void ASTDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) {
RedeclarableResult Redecl = VisitRedeclarable(PD);
VisitObjCContainerDecl(PD);
mergeRedeclarable(PD, Redecl);
-
- if (Record[Idx++]) {
+
+ if (Record.readInt()) {
// Read the definition.
PD->allocateDefinitionData();
-
+
// Set the definition data of the canonical declaration, so other
// redeclarations will see it.
PD->getCanonicalDecl()->Data = PD->Data;
- unsigned NumProtoRefs = Record[Idx++];
+ unsigned NumProtoRefs = Record.readInt();
SmallVector<ObjCProtocolDecl *, 16> ProtoRefs;
ProtoRefs.reserve(NumProtoRefs);
for (unsigned I = 0; I != NumProtoRefs; ++I)
- ProtoRefs.push_back(ReadDeclAs<ObjCProtocolDecl>(Record, Idx));
+ ProtoRefs.push_back(ReadDeclAs<ObjCProtocolDecl>());
SmallVector<SourceLocation, 16> ProtoLocs;
ProtoLocs.reserve(NumProtoRefs);
for (unsigned I = 0; I != NumProtoRefs; ++I)
- ProtoLocs.push_back(ReadSourceLocation(Record, Idx));
+ ProtoLocs.push_back(ReadSourceLocation());
PD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(),
Reader.getContext());
-
+
// Note that we have deserialized a definition.
Reader.PendingDefinitions.insert(PD);
} else {
@@ -1083,105 +1069,104 @@ void ASTDeclReader::VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *FD) {
void ASTDeclReader::VisitObjCCategoryDecl(ObjCCategoryDecl *CD) {
VisitObjCContainerDecl(CD);
- CD->setCategoryNameLoc(ReadSourceLocation(Record, Idx));
- CD->setIvarLBraceLoc(ReadSourceLocation(Record, Idx));
- CD->setIvarRBraceLoc(ReadSourceLocation(Record, Idx));
-
+ CD->setCategoryNameLoc(ReadSourceLocation());
+ CD->setIvarLBraceLoc(ReadSourceLocation());
+ CD->setIvarRBraceLoc(ReadSourceLocation());
+
// Note that this category has been deserialized. We do this before
// deserializing the interface declaration, so that it will consider this
/// category.
Reader.CategoriesDeserialized.insert(CD);
- CD->ClassInterface = ReadDeclAs<ObjCInterfaceDecl>(Record, Idx);
+ CD->ClassInterface = ReadDeclAs<ObjCInterfaceDecl>();
CD->TypeParamList = ReadObjCTypeParamList();
- unsigned NumProtoRefs = Record[Idx++];
+ unsigned NumProtoRefs = Record.readInt();
SmallVector<ObjCProtocolDecl *, 16> ProtoRefs;
ProtoRefs.reserve(NumProtoRefs);
for (unsigned I = 0; I != NumProtoRefs; ++I)
- ProtoRefs.push_back(ReadDeclAs<ObjCProtocolDecl>(Record, Idx));
+ ProtoRefs.push_back(ReadDeclAs<ObjCProtocolDecl>());
SmallVector<SourceLocation, 16> ProtoLocs;
ProtoLocs.reserve(NumProtoRefs);
for (unsigned I = 0; I != NumProtoRefs; ++I)
- ProtoLocs.push_back(ReadSourceLocation(Record, Idx));
+ ProtoLocs.push_back(ReadSourceLocation());
CD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(),
Reader.getContext());
}
void ASTDeclReader::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *CAD) {
VisitNamedDecl(CAD);
- CAD->setClassInterface(ReadDeclAs<ObjCInterfaceDecl>(Record, Idx));
+ CAD->setClassInterface(ReadDeclAs<ObjCInterfaceDecl>());
}
void ASTDeclReader::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
VisitNamedDecl(D);
- D->setAtLoc(ReadSourceLocation(Record, Idx));
- D->setLParenLoc(ReadSourceLocation(Record, Idx));
- QualType T = Reader.readType(F, Record, Idx);
- TypeSourceInfo *TSI = GetTypeSourceInfo(Record, Idx);
+ D->setAtLoc(ReadSourceLocation());
+ D->setLParenLoc(ReadSourceLocation());
+ QualType T = Record.readType();
+ TypeSourceInfo *TSI = GetTypeSourceInfo();
D->setType(T, TSI);
D->setPropertyAttributes(
- (ObjCPropertyDecl::PropertyAttributeKind)Record[Idx++]);
+ (ObjCPropertyDecl::PropertyAttributeKind)Record.readInt());
D->setPropertyAttributesAsWritten(
- (ObjCPropertyDecl::PropertyAttributeKind)Record[Idx++]);
+ (ObjCPropertyDecl::PropertyAttributeKind)Record.readInt());
D->setPropertyImplementation(
- (ObjCPropertyDecl::PropertyControl)Record[Idx++]);
- D->setGetterName(Reader.ReadDeclarationName(F,Record, Idx).getObjCSelector());
- D->setSetterName(Reader.ReadDeclarationName(F,Record, Idx).getObjCSelector());
- D->setGetterMethodDecl(ReadDeclAs<ObjCMethodDecl>(Record, Idx));
- D->setSetterMethodDecl(ReadDeclAs<ObjCMethodDecl>(Record, Idx));
- D->setPropertyIvarDecl(ReadDeclAs<ObjCIvarDecl>(Record, Idx));
+ (ObjCPropertyDecl::PropertyControl)Record.readInt());
+ D->setGetterName(Record.readDeclarationName().getObjCSelector());
+ D->setSetterName(Record.readDeclarationName().getObjCSelector());
+ D->setGetterMethodDecl(ReadDeclAs<ObjCMethodDecl>());
+ D->setSetterMethodDecl(ReadDeclAs<ObjCMethodDecl>());
+ D->setPropertyIvarDecl(ReadDeclAs<ObjCIvarDecl>());
}
void ASTDeclReader::VisitObjCImplDecl(ObjCImplDecl *D) {
VisitObjCContainerDecl(D);
- D->setClassInterface(ReadDeclAs<ObjCInterfaceDecl>(Record, Idx));
+ D->setClassInterface(ReadDeclAs<ObjCInterfaceDecl>());
}
void ASTDeclReader::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
VisitObjCImplDecl(D);
- D->setIdentifier(Reader.GetIdentifierInfo(F, Record, Idx));
- D->CategoryNameLoc = ReadSourceLocation(Record, Idx);
+ D->setIdentifier(Record.getIdentifierInfo());
+ D->CategoryNameLoc = ReadSourceLocation();
}
void ASTDeclReader::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
VisitObjCImplDecl(D);
- D->setSuperClass(ReadDeclAs<ObjCInterfaceDecl>(Record, Idx));
- D->SuperLoc = ReadSourceLocation(Record, Idx);
- D->setIvarLBraceLoc(ReadSourceLocation(Record, Idx));
- D->setIvarRBraceLoc(ReadSourceLocation(Record, Idx));
- D->setHasNonZeroConstructors(Record[Idx++]);
- D->setHasDestructors(Record[Idx++]);
- D->NumIvarInitializers = Record[Idx++];
+ D->setSuperClass(ReadDeclAs<ObjCInterfaceDecl>());
+ D->SuperLoc = ReadSourceLocation();
+ D->setIvarLBraceLoc(ReadSourceLocation());
+ D->setIvarRBraceLoc(ReadSourceLocation());
+ D->setHasNonZeroConstructors(Record.readInt());
+ D->setHasDestructors(Record.readInt());
+ D->NumIvarInitializers = Record.readInt();
if (D->NumIvarInitializers)
- D->IvarInitializers = ReadGlobalOffset(F, Record, Idx);
+ D->IvarInitializers = ReadGlobalOffset();
}
void ASTDeclReader::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
VisitDecl(D);
- D->setAtLoc(ReadSourceLocation(Record, Idx));
- D->setPropertyDecl(ReadDeclAs<ObjCPropertyDecl>(Record, Idx));
- D->PropertyIvarDecl = ReadDeclAs<ObjCIvarDecl>(Record, Idx);
- D->IvarLoc = ReadSourceLocation(Record, Idx);
- D->setGetterCXXConstructor(Reader.ReadExpr(F));
- D->setSetterCXXAssignment(Reader.ReadExpr(F));
+ D->setAtLoc(ReadSourceLocation());
+ D->setPropertyDecl(ReadDeclAs<ObjCPropertyDecl>());
+ D->PropertyIvarDecl = ReadDeclAs<ObjCIvarDecl>();
+ D->IvarLoc = ReadSourceLocation();
+ D->setGetterCXXConstructor(Record.readExpr());
+ D->setSetterCXXAssignment(Record.readExpr());
}
void ASTDeclReader::VisitFieldDecl(FieldDecl *FD) {
VisitDeclaratorDecl(FD);
- FD->Mutable = Record[Idx++];
- if (int BitWidthOrInitializer = Record[Idx++]) {
+ FD->Mutable = Record.readInt();
+ if (int BitWidthOrInitializer = Record.readInt()) {
FD->InitStorage.setInt(
static_cast<FieldDecl::InitStorageKind>(BitWidthOrInitializer - 1));
if (FD->InitStorage.getInt() == FieldDecl::ISK_CapturedVLAType) {
// Read captured variable length array.
- FD->InitStorage.setPointer(
- Reader.readType(F, Record, Idx).getAsOpaquePtr());
+ FD->InitStorage.setPointer(Record.readType().getAsOpaquePtr());
} else {
- FD->InitStorage.setPointer(Reader.ReadExpr(F));
+ FD->InitStorage.setPointer(Record.readExpr());
}
}
if (!FD->getDeclName()) {
- if (FieldDecl *Tmpl = ReadDeclAs<FieldDecl>(Record, Idx))
+ if (FieldDecl *Tmpl = ReadDeclAs<FieldDecl>())
Reader.getContext().setInstantiatedFromUnnamedFieldDecl(FD, Tmpl);
}
mergeMergeable(FD);
@@ -1189,19 +1174,19 @@ void ASTDeclReader::VisitFieldDecl(FieldDecl *FD) {
void ASTDeclReader::VisitMSPropertyDecl(MSPropertyDecl *PD) {
VisitDeclaratorDecl(PD);
- PD->GetterId = Reader.GetIdentifierInfo(F, Record, Idx);
- PD->SetterId = Reader.GetIdentifierInfo(F, Record, Idx);
+ PD->GetterId = Record.getIdentifierInfo();
+ PD->SetterId = Record.getIdentifierInfo();
}
void ASTDeclReader::VisitIndirectFieldDecl(IndirectFieldDecl *FD) {
VisitValueDecl(FD);
- FD->ChainingSize = Record[Idx++];
+ FD->ChainingSize = Record.readInt();
assert(FD->ChainingSize >= 2 && "Anonymous chaining must be >= 2");
FD->Chaining = new (Reader.getContext())NamedDecl*[FD->ChainingSize];
for (unsigned I = 0; I != FD->ChainingSize; ++I)
- FD->Chaining[I] = ReadDeclAs<NamedDecl>(Record, Idx);
+ FD->Chaining[I] = ReadDeclAs<NamedDecl>();
mergeMergeable(FD);
}
@@ -1210,21 +1195,23 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) {
RedeclarableResult Redecl = VisitRedeclarable(VD);
VisitDeclaratorDecl(VD);
- VD->VarDeclBits.SClass = (StorageClass)Record[Idx++];
- VD->VarDeclBits.TSCSpec = Record[Idx++];
- VD->VarDeclBits.InitStyle = Record[Idx++];
+ VD->VarDeclBits.SClass = (StorageClass)Record.readInt();
+ VD->VarDeclBits.TSCSpec = Record.readInt();
+ VD->VarDeclBits.InitStyle = Record.readInt();
if (!isa<ParmVarDecl>(VD)) {
- VD->NonParmVarDeclBits.ExceptionVar = Record[Idx++];
- VD->NonParmVarDeclBits.NRVOVariable = Record[Idx++];
- VD->NonParmVarDeclBits.CXXForRangeDecl = Record[Idx++];
- VD->NonParmVarDeclBits.ARCPseudoStrong = Record[Idx++];
- VD->NonParmVarDeclBits.IsInline = Record[Idx++];
- VD->NonParmVarDeclBits.IsInlineSpecified = Record[Idx++];
- VD->NonParmVarDeclBits.IsConstexpr = Record[Idx++];
- VD->NonParmVarDeclBits.IsInitCapture = Record[Idx++];
- VD->NonParmVarDeclBits.PreviousDeclInSameBlockScope = Record[Idx++];
- }
- Linkage VarLinkage = Linkage(Record[Idx++]);
+ VD->NonParmVarDeclBits.IsThisDeclarationADemotedDefinition =
+ Record.readInt();
+ VD->NonParmVarDeclBits.ExceptionVar = Record.readInt();
+ VD->NonParmVarDeclBits.NRVOVariable = Record.readInt();
+ VD->NonParmVarDeclBits.CXXForRangeDecl = Record.readInt();
+ VD->NonParmVarDeclBits.ARCPseudoStrong = Record.readInt();
+ VD->NonParmVarDeclBits.IsInline = Record.readInt();
+ VD->NonParmVarDeclBits.IsInlineSpecified = Record.readInt();
+ VD->NonParmVarDeclBits.IsConstexpr = Record.readInt();
+ VD->NonParmVarDeclBits.IsInitCapture = Record.readInt();
+ VD->NonParmVarDeclBits.PreviousDeclInSameBlockScope = Record.readInt();
+ }
+ Linkage VarLinkage = Linkage(Record.readInt());
VD->setCachedLinkage(VarLinkage);
// Reconstruct the one piece of the IdentifierNamespace that we need.
@@ -1232,9 +1219,9 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) {
VD->getLexicalDeclContext()->isFunctionOrMethod())
VD->setLocalExternDecl();
- if (uint64_t Val = Record[Idx++]) {
- VD->setInit(Reader.ReadExpr(F));
- if (Val > 1) {
+ if (uint64_t Val = Record.readInt()) {
+ VD->setInit(Record.readExpr());
+ if (Val > 1) { // IsInitKnownICE = 1, IsInitNotICE = 2, IsInitICE = 3
EvaluatedStmt *Eval = VD->ensureEvaluatedStmt();
Eval->CheckedICE = true;
Eval->IsICE = Val == 3;
@@ -1244,7 +1231,7 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) {
enum VarKind {
VarNotTemplate = 0, VarTemplate, StaticDataMemberSpecialization
};
- switch ((VarKind)Record[Idx++]) {
+ switch ((VarKind)Record.readInt()) {
case VarNotTemplate:
// Only true variables (not parameters or implicit parameters) can be
// merged; the other kinds are not really redeclarable at all.
@@ -1254,12 +1241,13 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) {
break;
case VarTemplate:
// Merged when we merge the template.
- VD->setDescribedVarTemplate(ReadDeclAs<VarTemplateDecl>(Record, Idx));
+ VD->setDescribedVarTemplate(ReadDeclAs<VarTemplateDecl>());
break;
case StaticDataMemberSpecialization: { // HasMemberSpecializationInfo.
- VarDecl *Tmpl = ReadDeclAs<VarDecl>(Record, Idx);
- TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++];
- SourceLocation POI = ReadSourceLocation(Record, Idx);
+ VarDecl *Tmpl = ReadDeclAs<VarDecl>();
+ TemplateSpecializationKind TSK =
+ (TemplateSpecializationKind)Record.readInt();
+ SourceLocation POI = ReadSourceLocation();
Reader.getContext().setInstantiatedFromStaticDataMember(VD, Tmpl, TSK,POI);
mergeRedeclarable(VD, Redecl);
break;
@@ -1275,10 +1263,10 @@ void ASTDeclReader::VisitImplicitParamDecl(ImplicitParamDecl *PD) {
void ASTDeclReader::VisitParmVarDecl(ParmVarDecl *PD) {
VisitVarDecl(PD);
- unsigned isObjCMethodParam = Record[Idx++];
- unsigned scopeDepth = Record[Idx++];
- unsigned scopeIndex = Record[Idx++];
- unsigned declQualifier = Record[Idx++];
+ unsigned isObjCMethodParam = Record.readInt();
+ unsigned scopeDepth = Record.readInt();
+ unsigned scopeIndex = Record.readInt();
+ unsigned declQualifier = Record.readInt();
if (isObjCMethodParam) {
assert(scopeDepth == 0);
PD->setObjCMethodScopeInfo(scopeIndex);
@@ -1286,46 +1274,58 @@ void ASTDeclReader::VisitParmVarDecl(ParmVarDecl *PD) {
} else {
PD->setScopeInfo(scopeDepth, scopeIndex);
}
- PD->ParmVarDeclBits.IsKNRPromoted = Record[Idx++];
- PD->ParmVarDeclBits.HasInheritedDefaultArg = Record[Idx++];
- if (Record[Idx++]) // hasUninstantiatedDefaultArg.
- PD->setUninstantiatedDefaultArg(Reader.ReadExpr(F));
+ PD->ParmVarDeclBits.IsKNRPromoted = Record.readInt();
+ PD->ParmVarDeclBits.HasInheritedDefaultArg = Record.readInt();
+ if (Record.readInt()) // hasUninstantiatedDefaultArg.
+ PD->setUninstantiatedDefaultArg(Record.readExpr());
// FIXME: If this is a redeclaration of a function from another module, handle
// inheritance of default arguments.
}
+void ASTDeclReader::VisitDecompositionDecl(DecompositionDecl *DD) {
+ VisitVarDecl(DD);
+ BindingDecl **BDs = DD->getTrailingObjects<BindingDecl*>();
+ for (unsigned I = 0; I != DD->NumBindings; ++I)
+ BDs[I] = ReadDeclAs<BindingDecl>();
+}
+
+void ASTDeclReader::VisitBindingDecl(BindingDecl *BD) {
+ VisitValueDecl(BD);
+ BD->Binding = Record.readExpr();
+}
+
void ASTDeclReader::VisitFileScopeAsmDecl(FileScopeAsmDecl *AD) {
VisitDecl(AD);
- AD->setAsmString(cast<StringLiteral>(Reader.ReadExpr(F)));
- AD->setRParenLoc(ReadSourceLocation(Record, Idx));
+ AD->setAsmString(cast<StringLiteral>(Record.readExpr()));
+ AD->setRParenLoc(ReadSourceLocation());
}
void ASTDeclReader::VisitBlockDecl(BlockDecl *BD) {
VisitDecl(BD);
- BD->setBody(cast_or_null<CompoundStmt>(Reader.ReadStmt(F)));
- BD->setSignatureAsWritten(GetTypeSourceInfo(Record, Idx));
- unsigned NumParams = Record[Idx++];
+ BD->setBody(cast_or_null<CompoundStmt>(Record.readStmt()));
+ BD->setSignatureAsWritten(GetTypeSourceInfo());
+ unsigned NumParams = Record.readInt();
SmallVector<ParmVarDecl *, 16> Params;
Params.reserve(NumParams);
for (unsigned I = 0; I != NumParams; ++I)
- Params.push_back(ReadDeclAs<ParmVarDecl>(Record, Idx));
+ Params.push_back(ReadDeclAs<ParmVarDecl>());
BD->setParams(Params);
- BD->setIsVariadic(Record[Idx++]);
- BD->setBlockMissingReturnType(Record[Idx++]);
- BD->setIsConversionFromLambda(Record[Idx++]);
+ BD->setIsVariadic(Record.readInt());
+ BD->setBlockMissingReturnType(Record.readInt());
+ BD->setIsConversionFromLambda(Record.readInt());
- bool capturesCXXThis = Record[Idx++];
- unsigned numCaptures = Record[Idx++];
+ bool capturesCXXThis = Record.readInt();
+ unsigned numCaptures = Record.readInt();
SmallVector<BlockDecl::Capture, 16> captures;
captures.reserve(numCaptures);
for (unsigned i = 0; i != numCaptures; ++i) {
- VarDecl *decl = ReadDeclAs<VarDecl>(Record, Idx);
- unsigned flags = Record[Idx++];
+ VarDecl *decl = ReadDeclAs<VarDecl>();
+ unsigned flags = Record.readInt();
bool byRef = (flags & 1);
bool nested = (flags & 2);
- Expr *copyExpr = ((flags & 4) ? Reader.ReadExpr(F) : nullptr);
+ Expr *copyExpr = ((flags & 4) ? Record.readExpr() : nullptr);
captures.push_back(BlockDecl::Capture(decl, byRef, nested, copyExpr));
}
@@ -1334,35 +1334,40 @@ void ASTDeclReader::VisitBlockDecl(BlockDecl *BD) {
void ASTDeclReader::VisitCapturedDecl(CapturedDecl *CD) {
VisitDecl(CD);
- unsigned ContextParamPos = Record[Idx++];
- CD->setNothrow(Record[Idx++] != 0);
+ unsigned ContextParamPos = Record.readInt();
+ CD->setNothrow(Record.readInt() != 0);
// Body is set by VisitCapturedStmt.
for (unsigned I = 0; I < CD->NumParams; ++I) {
if (I != ContextParamPos)
- CD->setParam(I, ReadDeclAs<ImplicitParamDecl>(Record, Idx));
+ CD->setParam(I, ReadDeclAs<ImplicitParamDecl>());
else
- CD->setContextParam(I, ReadDeclAs<ImplicitParamDecl>(Record, Idx));
+ CD->setContextParam(I, ReadDeclAs<ImplicitParamDecl>());
}
}
void ASTDeclReader::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
VisitDecl(D);
- D->setLanguage((LinkageSpecDecl::LanguageIDs)Record[Idx++]);
- D->setExternLoc(ReadSourceLocation(Record, Idx));
- D->setRBraceLoc(ReadSourceLocation(Record, Idx));
+ D->setLanguage((LinkageSpecDecl::LanguageIDs)Record.readInt());
+ D->setExternLoc(ReadSourceLocation());
+ D->setRBraceLoc(ReadSourceLocation());
+}
+
+void ASTDeclReader::VisitExportDecl(ExportDecl *D) {
+ VisitDecl(D);
+ D->RBraceLoc = ReadSourceLocation();
}
void ASTDeclReader::VisitLabelDecl(LabelDecl *D) {
VisitNamedDecl(D);
- D->setLocStart(ReadSourceLocation(Record, Idx));
+ D->setLocStart(ReadSourceLocation());
}
void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) {
RedeclarableResult Redecl = VisitRedeclarable(D);
VisitNamedDecl(D);
- D->setInline(Record[Idx++]);
- D->LocStart = ReadSourceLocation(Record, Idx);
- D->RBraceLoc = ReadSourceLocation(Record, Idx);
+ D->setInline(Record.readInt());
+ D->LocStart = ReadSourceLocation();
+ D->RBraceLoc = ReadSourceLocation();
// Defer loading the anonymous namespace until we've finished merging
// this namespace; loading it might load a later declaration of the
@@ -1370,7 +1375,7 @@ void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) {
// get merged before newer ones try to merge.
GlobalDeclID AnonNamespace = 0;
if (Redecl.getFirstID() == ThisDeclID) {
- AnonNamespace = ReadDeclID(Record, Idx);
+ AnonNamespace = ReadDeclID();
} else {
// Link this namespace back to the first declaration, which has already
// been deserialized.
@@ -1384,7 +1389,7 @@ void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) {
// any other module's anonymous namespaces, so don't attach the anonymous
// namespace at all.
NamespaceDecl *Anon = cast<NamespaceDecl>(Reader.GetDecl(AnonNamespace));
- if (F.Kind != MK_ImplicitModule && F.Kind != MK_ExplicitModule)
+ if (!Record.isModule())
D->setAnonymousNamespace(Anon);
}
}
@@ -1392,31 +1397,40 @@ void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) {
void ASTDeclReader::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
RedeclarableResult Redecl = VisitRedeclarable(D);
VisitNamedDecl(D);
- D->NamespaceLoc = ReadSourceLocation(Record, Idx);
- D->IdentLoc = ReadSourceLocation(Record, Idx);
- D->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx);
- D->Namespace = ReadDeclAs<NamedDecl>(Record, Idx);
+ D->NamespaceLoc = ReadSourceLocation();
+ D->IdentLoc = ReadSourceLocation();
+ D->QualifierLoc = Record.readNestedNameSpecifierLoc();
+ D->Namespace = ReadDeclAs<NamedDecl>();
mergeRedeclarable(D, Redecl);
}
void ASTDeclReader::VisitUsingDecl(UsingDecl *D) {
VisitNamedDecl(D);
- D->setUsingLoc(ReadSourceLocation(Record, Idx));
- D->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx);
- ReadDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record, Idx);
- D->FirstUsingShadow.setPointer(ReadDeclAs<UsingShadowDecl>(Record, Idx));
- D->setTypename(Record[Idx++]);
- if (NamedDecl *Pattern = ReadDeclAs<NamedDecl>(Record, Idx))
+ D->setUsingLoc(ReadSourceLocation());
+ D->QualifierLoc = Record.readNestedNameSpecifierLoc();
+ ReadDeclarationNameLoc(D->DNLoc, D->getDeclName());
+ D->FirstUsingShadow.setPointer(ReadDeclAs<UsingShadowDecl>());
+ D->setTypename(Record.readInt());
+ if (NamedDecl *Pattern = ReadDeclAs<NamedDecl>())
Reader.getContext().setInstantiatedFromUsingDecl(D, Pattern);
mergeMergeable(D);
}
+void ASTDeclReader::VisitUsingPackDecl(UsingPackDecl *D) {
+ VisitNamedDecl(D);
+ D->InstantiatedFrom = ReadDeclAs<NamedDecl>();
+ NamedDecl **Expansions = D->getTrailingObjects<NamedDecl*>();
+ for (unsigned I = 0; I != D->NumExpansions; ++I)
+ Expansions[I] = ReadDeclAs<NamedDecl>();
+ mergeMergeable(D);
+}
+
void ASTDeclReader::VisitUsingShadowDecl(UsingShadowDecl *D) {
RedeclarableResult Redecl = VisitRedeclarable(D);
VisitNamedDecl(D);
- D->setTargetDecl(ReadDeclAs<NamedDecl>(Record, Idx));
- D->UsingOrNextShadow = ReadDeclAs<NamedDecl>(Record, Idx);
- UsingShadowDecl *Pattern = ReadDeclAs<UsingShadowDecl>(Record, Idx);
+ D->setTargetDecl(ReadDeclAs<NamedDecl>());
+ D->UsingOrNextShadow = ReadDeclAs<NamedDecl>();
+ UsingShadowDecl *Pattern = ReadDeclAs<UsingShadowDecl>();
if (Pattern)
Reader.getContext().setInstantiatedFromUsingShadowDecl(D, Pattern);
mergeRedeclarable(D, Redecl);
@@ -1425,115 +1439,114 @@ void ASTDeclReader::VisitUsingShadowDecl(UsingShadowDecl *D) {
void ASTDeclReader::VisitConstructorUsingShadowDecl(
ConstructorUsingShadowDecl *D) {
VisitUsingShadowDecl(D);
- D->NominatedBaseClassShadowDecl =
- ReadDeclAs<ConstructorUsingShadowDecl>(Record, Idx);
- D->ConstructedBaseClassShadowDecl =
- ReadDeclAs<ConstructorUsingShadowDecl>(Record, Idx);
- D->IsVirtual = Record[Idx++];
+ D->NominatedBaseClassShadowDecl = ReadDeclAs<ConstructorUsingShadowDecl>();
+ D->ConstructedBaseClassShadowDecl = ReadDeclAs<ConstructorUsingShadowDecl>();
+ D->IsVirtual = Record.readInt();
}
void ASTDeclReader::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
VisitNamedDecl(D);
- D->UsingLoc = ReadSourceLocation(Record, Idx);
- D->NamespaceLoc = ReadSourceLocation(Record, Idx);
- D->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx);
- D->NominatedNamespace = ReadDeclAs<NamedDecl>(Record, Idx);
- D->CommonAncestor = ReadDeclAs<DeclContext>(Record, Idx);
+ D->UsingLoc = ReadSourceLocation();
+ D->NamespaceLoc = ReadSourceLocation();
+ D->QualifierLoc = Record.readNestedNameSpecifierLoc();
+ D->NominatedNamespace = ReadDeclAs<NamedDecl>();
+ D->CommonAncestor = ReadDeclAs<DeclContext>();
}
void ASTDeclReader::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
VisitValueDecl(D);
- D->setUsingLoc(ReadSourceLocation(Record, Idx));
- D->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx);
- ReadDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record, Idx);
+ D->setUsingLoc(ReadSourceLocation());
+ D->QualifierLoc = Record.readNestedNameSpecifierLoc();
+ ReadDeclarationNameLoc(D->DNLoc, D->getDeclName());
+ D->EllipsisLoc = ReadSourceLocation();
mergeMergeable(D);
}
void ASTDeclReader::VisitUnresolvedUsingTypenameDecl(
UnresolvedUsingTypenameDecl *D) {
VisitTypeDecl(D);
- D->TypenameLocation = ReadSourceLocation(Record, Idx);
- D->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx);
+ D->TypenameLocation = ReadSourceLocation();
+ D->QualifierLoc = Record.readNestedNameSpecifierLoc();
+ D->EllipsisLoc = ReadSourceLocation();
mergeMergeable(D);
}
void ASTDeclReader::ReadCXXDefinitionData(
- struct CXXRecordDecl::DefinitionData &Data,
- const RecordData &Record, unsigned &Idx) {
+ struct CXXRecordDecl::DefinitionData &Data) {
// Note: the caller has deserialized the IsLambda bit already.
- Data.UserDeclaredConstructor = Record[Idx++];
- Data.UserDeclaredSpecialMembers = Record[Idx++];
- Data.Aggregate = Record[Idx++];
- Data.PlainOldData = Record[Idx++];
- Data.Empty = Record[Idx++];
- Data.Polymorphic = Record[Idx++];
- Data.Abstract = Record[Idx++];
- Data.IsStandardLayout = Record[Idx++];
- Data.HasNoNonEmptyBases = Record[Idx++];
- Data.HasPrivateFields = Record[Idx++];
- Data.HasProtectedFields = Record[Idx++];
- Data.HasPublicFields = Record[Idx++];
- Data.HasMutableFields = Record[Idx++];
- Data.HasVariantMembers = Record[Idx++];
- Data.HasOnlyCMembers = Record[Idx++];
- Data.HasInClassInitializer = Record[Idx++];
- Data.HasUninitializedReferenceMember = Record[Idx++];
- Data.HasUninitializedFields = Record[Idx++];
- Data.HasInheritedConstructor = Record[Idx++];
- Data.HasInheritedAssignment = Record[Idx++];
- Data.NeedOverloadResolutionForMoveConstructor = Record[Idx++];
- Data.NeedOverloadResolutionForMoveAssignment = Record[Idx++];
- Data.NeedOverloadResolutionForDestructor = Record[Idx++];
- Data.DefaultedMoveConstructorIsDeleted = Record[Idx++];
- Data.DefaultedMoveAssignmentIsDeleted = Record[Idx++];
- Data.DefaultedDestructorIsDeleted = Record[Idx++];
- Data.HasTrivialSpecialMembers = Record[Idx++];
- Data.DeclaredNonTrivialSpecialMembers = Record[Idx++];
- Data.HasIrrelevantDestructor = Record[Idx++];
- Data.HasConstexprNonCopyMoveConstructor = Record[Idx++];
- Data.HasDefaultedDefaultConstructor = Record[Idx++];
- Data.DefaultedDefaultConstructorIsConstexpr = Record[Idx++];
- Data.HasConstexprDefaultConstructor = Record[Idx++];
- Data.HasNonLiteralTypeFieldsOrBases = Record[Idx++];
- Data.ComputedVisibleConversions = Record[Idx++];
- Data.UserProvidedDefaultConstructor = Record[Idx++];
- Data.DeclaredSpecialMembers = Record[Idx++];
- Data.ImplicitCopyConstructorHasConstParam = Record[Idx++];
- Data.ImplicitCopyAssignmentHasConstParam = Record[Idx++];
- Data.HasDeclaredCopyConstructorWithConstParam = Record[Idx++];
- Data.HasDeclaredCopyAssignmentWithConstParam = Record[Idx++];
-
- Data.NumBases = Record[Idx++];
+ Data.UserDeclaredConstructor = Record.readInt();
+ Data.UserDeclaredSpecialMembers = Record.readInt();
+ Data.Aggregate = Record.readInt();
+ Data.PlainOldData = Record.readInt();
+ Data.Empty = Record.readInt();
+ Data.Polymorphic = Record.readInt();
+ Data.Abstract = Record.readInt();
+ Data.IsStandardLayout = Record.readInt();
+ Data.HasNoNonEmptyBases = Record.readInt();
+ Data.HasPrivateFields = Record.readInt();
+ Data.HasProtectedFields = Record.readInt();
+ Data.HasPublicFields = Record.readInt();
+ Data.HasMutableFields = Record.readInt();
+ Data.HasVariantMembers = Record.readInt();
+ Data.HasOnlyCMembers = Record.readInt();
+ Data.HasInClassInitializer = Record.readInt();
+ Data.HasUninitializedReferenceMember = Record.readInt();
+ Data.HasUninitializedFields = Record.readInt();
+ Data.HasInheritedConstructor = Record.readInt();
+ Data.HasInheritedAssignment = Record.readInt();
+ Data.NeedOverloadResolutionForMoveConstructor = Record.readInt();
+ Data.NeedOverloadResolutionForMoveAssignment = Record.readInt();
+ Data.NeedOverloadResolutionForDestructor = Record.readInt();
+ Data.DefaultedMoveConstructorIsDeleted = Record.readInt();
+ Data.DefaultedMoveAssignmentIsDeleted = Record.readInt();
+ Data.DefaultedDestructorIsDeleted = Record.readInt();
+ Data.HasTrivialSpecialMembers = Record.readInt();
+ Data.DeclaredNonTrivialSpecialMembers = Record.readInt();
+ Data.HasIrrelevantDestructor = Record.readInt();
+ Data.HasConstexprNonCopyMoveConstructor = Record.readInt();
+ Data.HasDefaultedDefaultConstructor = Record.readInt();
+ Data.DefaultedDefaultConstructorIsConstexpr = Record.readInt();
+ Data.HasConstexprDefaultConstructor = Record.readInt();
+ Data.HasNonLiteralTypeFieldsOrBases = Record.readInt();
+ Data.ComputedVisibleConversions = Record.readInt();
+ Data.UserProvidedDefaultConstructor = Record.readInt();
+ Data.DeclaredSpecialMembers = Record.readInt();
+ Data.ImplicitCopyConstructorHasConstParam = Record.readInt();
+ Data.ImplicitCopyAssignmentHasConstParam = Record.readInt();
+ Data.HasDeclaredCopyConstructorWithConstParam = Record.readInt();
+ Data.HasDeclaredCopyAssignmentWithConstParam = Record.readInt();
+
+ Data.NumBases = Record.readInt();
if (Data.NumBases)
- Data.Bases = ReadGlobalOffset(F, Record, Idx);
- Data.NumVBases = Record[Idx++];
+ Data.Bases = ReadGlobalOffset();
+ Data.NumVBases = Record.readInt();
if (Data.NumVBases)
- Data.VBases = ReadGlobalOffset(F, Record, Idx);
-
- Reader.ReadUnresolvedSet(F, Data.Conversions, Record, Idx);
- Reader.ReadUnresolvedSet(F, Data.VisibleConversions, Record, Idx);
+ Data.VBases = ReadGlobalOffset();
+
+ Record.readUnresolvedSet(Data.Conversions);
+ Record.readUnresolvedSet(Data.VisibleConversions);
assert(Data.Definition && "Data.Definition should be already set!");
- Data.FirstFriend = ReadDeclID(Record, Idx);
+ Data.FirstFriend = ReadDeclID();
if (Data.IsLambda) {
typedef LambdaCapture Capture;
CXXRecordDecl::LambdaDefinitionData &Lambda
= static_cast<CXXRecordDecl::LambdaDefinitionData &>(Data);
- Lambda.Dependent = Record[Idx++];
- Lambda.IsGenericLambda = Record[Idx++];
- Lambda.CaptureDefault = Record[Idx++];
- Lambda.NumCaptures = Record[Idx++];
- Lambda.NumExplicitCaptures = Record[Idx++];
- Lambda.ManglingNumber = Record[Idx++];
- Lambda.ContextDecl = ReadDecl(Record, Idx);
+ Lambda.Dependent = Record.readInt();
+ Lambda.IsGenericLambda = Record.readInt();
+ Lambda.CaptureDefault = Record.readInt();
+ Lambda.NumCaptures = Record.readInt();
+ Lambda.NumExplicitCaptures = Record.readInt();
+ Lambda.ManglingNumber = Record.readInt();
+ Lambda.ContextDecl = ReadDeclID();
Lambda.Captures
= (Capture*)Reader.Context.Allocate(sizeof(Capture)*Lambda.NumCaptures);
Capture *ToCapture = Lambda.Captures;
- Lambda.MethodTyInfo = GetTypeSourceInfo(Record, Idx);
+ Lambda.MethodTyInfo = GetTypeSourceInfo();
for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) {
- SourceLocation Loc = ReadSourceLocation(Record, Idx);
- bool IsImplicit = Record[Idx++];
- LambdaCaptureKind Kind = static_cast<LambdaCaptureKind>(Record[Idx++]);
+ SourceLocation Loc = ReadSourceLocation();
+ bool IsImplicit = Record.readInt();
+ LambdaCaptureKind Kind = static_cast<LambdaCaptureKind>(Record.readInt());
switch (Kind) {
case LCK_StarThis:
case LCK_This:
@@ -1542,8 +1555,8 @@ void ASTDeclReader::ReadCXXDefinitionData(
break;
case LCK_ByCopy:
case LCK_ByRef:
- VarDecl *Var = ReadDeclAs<VarDecl>(Record, Idx);
- SourceLocation EllipsisLoc = ReadSourceLocation(Record, Idx);
+ VarDecl *Var = ReadDeclAs<VarDecl>();
+ SourceLocation EllipsisLoc = ReadSourceLocation();
*ToCapture++ = Capture(Loc, IsImplicit, Kind, Var, EllipsisLoc);
break;
}
@@ -1563,7 +1576,7 @@ void ASTDeclReader::MergeDefinitionData(
DD.Definition));
Reader.PendingDefinitions.erase(MergeDD.Definition);
MergeDD.Definition->IsCompleteDefinition = false;
- mergeDefinitionVisibility(DD.Definition, MergeDD.Definition);
+ Reader.mergeDefinitionVisibility(DD.Definition, MergeDD.Definition);
assert(Reader.Lookups.find(MergeDD.Definition) == Reader.Lookups.end() &&
"already loaded pending lookups for merged definition");
}
@@ -1665,14 +1678,14 @@ void ASTDeclReader::ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update) {
// Determine whether this is a lambda closure type, so that we can
// allocate the appropriate DefinitionData structure.
- bool IsLambda = Record[Idx++];
+ bool IsLambda = Record.readInt();
if (IsLambda)
DD = new (C) CXXRecordDecl::LambdaDefinitionData(D, nullptr, false, false,
LCD_None);
else
DD = new (C) struct CXXRecordDecl::DefinitionData(D);
- ReadCXXDefinitionData(*DD, Record, Idx);
+ ReadCXXDefinitionData(*DD);
// 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
@@ -1706,7 +1719,7 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) {
enum CXXRecKind {
CXXRecNotTemplate = 0, CXXRecTemplate, CXXRecMemberSpecialization
};
- switch ((CXXRecKind)Record[Idx++]) {
+ switch ((CXXRecKind)Record.readInt()) {
case CXXRecNotTemplate:
// Merged when we merge the folding set entry in the primary template.
if (!isa<ClassTemplateSpecializationDecl>(D))
@@ -1714,7 +1727,7 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) {
break;
case CXXRecTemplate: {
// Merged when we merge the template.
- ClassTemplateDecl *Template = ReadDeclAs<ClassTemplateDecl>(Record, Idx);
+ ClassTemplateDecl *Template = ReadDeclAs<ClassTemplateDecl>();
D->TemplateOrInstantiation = Template;
if (!Template->getTemplatedDecl()) {
// We've not actually loaded the ClassTemplateDecl yet, because we're
@@ -1728,9 +1741,10 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) {
break;
}
case CXXRecMemberSpecialization: {
- CXXRecordDecl *RD = ReadDeclAs<CXXRecordDecl>(Record, Idx);
- TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++];
- SourceLocation POI = ReadSourceLocation(Record, Idx);
+ CXXRecordDecl *RD = ReadDeclAs<CXXRecordDecl>();
+ TemplateSpecializationKind TSK =
+ (TemplateSpecializationKind)Record.readInt();
+ SourceLocation POI = ReadSourceLocation();
MemberSpecializationInfo *MSI = new (C) MemberSpecializationInfo(RD, TSK);
MSI->setPointOfInstantiation(POI);
D->TemplateOrInstantiation = MSI;
@@ -1739,7 +1753,7 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) {
}
}
- bool WasDefinition = Record[Idx++];
+ bool WasDefinition = Record.readInt();
if (WasDefinition)
ReadCXXRecordDefinition(D, /*Update*/false);
else
@@ -1749,7 +1763,7 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) {
// Lazily load the key function to avoid deserializing every method so we can
// compute it.
if (WasDefinition) {
- DeclID KeyFn = ReadDeclID(Record, Idx);
+ DeclID KeyFn = ReadDeclID();
if (KeyFn && D->IsCompleteDefinition)
// FIXME: This is wrong for the ARM ABI, where some other module may have
// made this function no longer be a key function. We need an update
@@ -1763,18 +1777,18 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) {
void ASTDeclReader::VisitCXXMethodDecl(CXXMethodDecl *D) {
VisitFunctionDecl(D);
- unsigned NumOverridenMethods = Record[Idx++];
+ unsigned NumOverridenMethods = Record.readInt();
if (D->isCanonicalDecl()) {
while (NumOverridenMethods--) {
// Avoid invariant checking of CXXMethodDecl::addOverriddenMethod,
// MD may be initializing.
- if (CXXMethodDecl *MD = ReadDeclAs<CXXMethodDecl>(Record, Idx))
+ if (CXXMethodDecl *MD = ReadDeclAs<CXXMethodDecl>())
Reader.getContext().addOverriddenMethod(D, MD->getCanonicalDecl());
}
} else {
// We don't care about which declarations this used to override; we get
// the relevant information from the canonical declaration.
- Idx += NumOverridenMethods;
+ Record.skipInts(NumOverridenMethods);
}
}
@@ -1782,21 +1796,21 @@ void ASTDeclReader::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
// We need the inherited constructor information to merge the declaration,
// so we have to read it before we call VisitCXXMethodDecl.
if (D->isInheritingConstructor()) {
- auto *Shadow = ReadDeclAs<ConstructorUsingShadowDecl>(Record, Idx);
- auto *Ctor = ReadDeclAs<CXXConstructorDecl>(Record, Idx);
+ auto *Shadow = ReadDeclAs<ConstructorUsingShadowDecl>();
+ auto *Ctor = ReadDeclAs<CXXConstructorDecl>();
*D->getTrailingObjects<InheritedConstructor>() =
InheritedConstructor(Shadow, Ctor);
}
VisitCXXMethodDecl(D);
- D->IsExplicitSpecified = Record[Idx++];
+ D->IsExplicitSpecified = Record.readInt();
}
void ASTDeclReader::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
VisitCXXMethodDecl(D);
- if (auto *OperatorDelete = ReadDeclAs<FunctionDecl>(Record, Idx)) {
+ if (auto *OperatorDelete = ReadDeclAs<FunctionDecl>()) {
auto *Canon = cast<CXXDestructorDecl>(D->getCanonicalDecl());
// FIXME: Check consistency if we have an old and new operator delete.
if (!Canon->OperatorDelete)
@@ -1806,65 +1820,64 @@ void ASTDeclReader::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
void ASTDeclReader::VisitCXXConversionDecl(CXXConversionDecl *D) {
VisitCXXMethodDecl(D);
- D->IsExplicitSpecified = Record[Idx++];
+ D->IsExplicitSpecified = Record.readInt();
}
void ASTDeclReader::VisitImportDecl(ImportDecl *D) {
VisitDecl(D);
- D->ImportedAndComplete.setPointer(readModule(Record, Idx));
- D->ImportedAndComplete.setInt(Record[Idx++]);
+ D->ImportedAndComplete.setPointer(readModule());
+ D->ImportedAndComplete.setInt(Record.readInt());
SourceLocation *StoredLocs = D->getTrailingObjects<SourceLocation>();
for (unsigned I = 0, N = Record.back(); I != N; ++I)
- StoredLocs[I] = ReadSourceLocation(Record, Idx);
- ++Idx; // The number of stored source locations.
+ StoredLocs[I] = ReadSourceLocation();
+ (void)Record.readInt(); // The number of stored source locations.
}
void ASTDeclReader::VisitAccessSpecDecl(AccessSpecDecl *D) {
VisitDecl(D);
- D->setColonLoc(ReadSourceLocation(Record, Idx));
+ D->setColonLoc(ReadSourceLocation());
}
void ASTDeclReader::VisitFriendDecl(FriendDecl *D) {
VisitDecl(D);
- if (Record[Idx++]) // hasFriendDecl
- D->Friend = ReadDeclAs<NamedDecl>(Record, Idx);
+ if (Record.readInt()) // hasFriendDecl
+ D->Friend = ReadDeclAs<NamedDecl>();
else
- D->Friend = GetTypeSourceInfo(Record, Idx);
+ D->Friend = GetTypeSourceInfo();
for (unsigned i = 0; i != D->NumTPLists; ++i)
D->getTrailingObjects<TemplateParameterList *>()[i] =
- Reader.ReadTemplateParameterList(F, Record, Idx);
- D->NextFriend = ReadDeclID(Record, Idx);
- D->UnsupportedFriend = (Record[Idx++] != 0);
- D->FriendLoc = ReadSourceLocation(Record, Idx);
+ Record.readTemplateParameterList();
+ D->NextFriend = ReadDeclID();
+ D->UnsupportedFriend = (Record.readInt() != 0);
+ D->FriendLoc = ReadSourceLocation();
}
void ASTDeclReader::VisitFriendTemplateDecl(FriendTemplateDecl *D) {
VisitDecl(D);
- unsigned NumParams = Record[Idx++];
+ unsigned NumParams = Record.readInt();
D->NumParams = NumParams;
D->Params = new TemplateParameterList*[NumParams];
for (unsigned i = 0; i != NumParams; ++i)
- D->Params[i] = Reader.ReadTemplateParameterList(F, Record, Idx);
- if (Record[Idx++]) // HasFriendDecl
- D->Friend = ReadDeclAs<NamedDecl>(Record, Idx);
+ D->Params[i] = Record.readTemplateParameterList();
+ if (Record.readInt()) // HasFriendDecl
+ D->Friend = ReadDeclAs<NamedDecl>();
else
- D->Friend = GetTypeSourceInfo(Record, Idx);
- D->FriendLoc = ReadSourceLocation(Record, Idx);
+ D->Friend = GetTypeSourceInfo();
+ D->FriendLoc = ReadSourceLocation();
}
DeclID ASTDeclReader::VisitTemplateDecl(TemplateDecl *D) {
VisitNamedDecl(D);
- DeclID PatternID = ReadDeclID(Record, Idx);
+ DeclID PatternID = ReadDeclID();
NamedDecl *TemplatedDecl = cast_or_null<NamedDecl>(Reader.GetDecl(PatternID));
- TemplateParameterList* TemplateParams
- = Reader.ReadTemplateParameterList(F, Record, Idx);
+ TemplateParameterList *TemplateParams = Record.readTemplateParameterList();
D->init(TemplatedDecl, TemplateParams);
return PatternID;
}
-ASTDeclReader::RedeclarableResult
+ASTDeclReader::RedeclarableResult
ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
RedeclarableResult Redecl = VisitRedeclarable(D);
@@ -1881,17 +1894,17 @@ ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
// for the 'common' pointer.
if (ThisDeclID == Redecl.getFirstID()) {
if (RedeclarableTemplateDecl *RTD
- = ReadDeclAs<RedeclarableTemplateDecl>(Record, Idx)) {
+ = ReadDeclAs<RedeclarableTemplateDecl>()) {
assert(RTD->getKind() == D->getKind() &&
"InstantiatedFromMemberTemplate kind mismatch");
D->setInstantiatedFromMemberTemplate(RTD);
- if (Record[Idx++])
+ if (Record.readInt())
D->setMemberSpecialization();
}
}
DeclID PatternID = VisitTemplateDecl(D);
- D->IdentifierNamespace = Record[Idx++];
+ D->IdentifierNamespace = Record.readInt();
mergeRedeclarable(D, Redecl, PatternID);
@@ -1971,14 +1984,14 @@ ASTDeclReader::RedeclarableResult
ASTDeclReader::VisitClassTemplateSpecializationDeclImpl(
ClassTemplateSpecializationDecl *D) {
RedeclarableResult Redecl = VisitCXXRecordDeclImpl(D);
-
+
ASTContext &C = Reader.getContext();
- if (Decl *InstD = ReadDecl(Record, Idx)) {
+ if (Decl *InstD = ReadDecl()) {
if (ClassTemplateDecl *CTD = dyn_cast<ClassTemplateDecl>(InstD)) {
D->SpecializedTemplate = CTD;
} else {
SmallVector<TemplateArgument, 8> TemplArgs;
- Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx);
+ Record.readTemplateArgumentList(TemplArgs);
TemplateArgumentList *ArgList
= TemplateArgumentList::CreateCopy(C, TemplArgs);
ClassTemplateSpecializationDecl::SpecializedPartialSpecialization *PS
@@ -1992,15 +2005,14 @@ ASTDeclReader::VisitClassTemplateSpecializationDeclImpl(
}
SmallVector<TemplateArgument, 8> TemplArgs;
- Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx,
- /*Canonicalize*/ true);
+ Record.readTemplateArgumentList(TemplArgs, /*Canonicalize*/ true);
D->TemplateArgs = TemplateArgumentList::CreateCopy(C, TemplArgs);
- D->PointOfInstantiation = ReadSourceLocation(Record, Idx);
- D->SpecializationKind = (TemplateSpecializationKind)Record[Idx++];
+ D->PointOfInstantiation = ReadSourceLocation();
+ D->SpecializationKind = (TemplateSpecializationKind)Record.readInt();
- bool writtenAsCanonicalDecl = Record[Idx++];
+ bool writtenAsCanonicalDecl = Record.readInt();
if (writtenAsCanonicalDecl) {
- ClassTemplateDecl *CanonPattern = ReadDeclAs<ClassTemplateDecl>(Record,Idx);
+ ClassTemplateDecl *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;
@@ -2030,12 +2042,12 @@ ASTDeclReader::VisitClassTemplateSpecializationDeclImpl(
}
// Explicit info.
- if (TypeSourceInfo *TyInfo = GetTypeSourceInfo(Record, Idx)) {
+ if (TypeSourceInfo *TyInfo = GetTypeSourceInfo()) {
ClassTemplateSpecializationDecl::ExplicitSpecializationInfo *ExplicitInfo
= new (C) ClassTemplateSpecializationDecl::ExplicitSpecializationInfo;
ExplicitInfo->TypeAsWritten = TyInfo;
- ExplicitInfo->ExternLoc = ReadSourceLocation(Record, Idx);
- ExplicitInfo->TemplateKeywordLoc = ReadSourceLocation(Record, Idx);
+ ExplicitInfo->ExternLoc = ReadSourceLocation();
+ ExplicitInfo->TemplateKeywordLoc = ReadSourceLocation();
D->ExplicitInfo = ExplicitInfo;
}
@@ -2046,21 +2058,21 @@ void ASTDeclReader::VisitClassTemplatePartialSpecializationDecl(
ClassTemplatePartialSpecializationDecl *D) {
RedeclarableResult Redecl = VisitClassTemplateSpecializationDeclImpl(D);
- D->TemplateParams = Reader.ReadTemplateParameterList(F, Record, Idx);
- D->ArgsAsWritten = Reader.ReadASTTemplateArgumentListInfo(F, Record, Idx);
+ D->TemplateParams = Record.readTemplateParameterList();
+ D->ArgsAsWritten = Record.readASTTemplateArgumentListInfo();
// These are read/set from/to the first declaration.
if (ThisDeclID == Redecl.getFirstID()) {
D->InstantiatedFromMember.setPointer(
- ReadDeclAs<ClassTemplatePartialSpecializationDecl>(Record, Idx));
- D->InstantiatedFromMember.setInt(Record[Idx++]);
+ ReadDeclAs<ClassTemplatePartialSpecializationDecl>());
+ D->InstantiatedFromMember.setInt(Record.readInt());
}
}
void ASTDeclReader::VisitClassScopeFunctionSpecializationDecl(
ClassScopeFunctionSpecializationDecl *D) {
VisitDecl(D);
- D->Specialization = ReadDeclAs<CXXMethodDecl>(Record, Idx);
+ D->Specialization = ReadDeclAs<CXXMethodDecl>();
}
void ASTDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
@@ -2090,12 +2102,12 @@ ASTDeclReader::VisitVarTemplateSpecializationDeclImpl(
RedeclarableResult Redecl = VisitVarDeclImpl(D);
ASTContext &C = Reader.getContext();
- if (Decl *InstD = ReadDecl(Record, Idx)) {
+ if (Decl *InstD = ReadDecl()) {
if (VarTemplateDecl *VTD = dyn_cast<VarTemplateDecl>(InstD)) {
D->SpecializedTemplate = VTD;
} else {
SmallVector<TemplateArgument, 8> TemplArgs;
- Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx);
+ Record.readTemplateArgumentList(TemplArgs);
TemplateArgumentList *ArgList = TemplateArgumentList::CreateCopy(
C, TemplArgs);
VarTemplateSpecializationDecl::SpecializedPartialSpecialization *PS =
@@ -2109,25 +2121,24 @@ ASTDeclReader::VisitVarTemplateSpecializationDeclImpl(
}
// Explicit info.
- if (TypeSourceInfo *TyInfo = GetTypeSourceInfo(Record, Idx)) {
+ if (TypeSourceInfo *TyInfo = GetTypeSourceInfo()) {
VarTemplateSpecializationDecl::ExplicitSpecializationInfo *ExplicitInfo =
new (C) VarTemplateSpecializationDecl::ExplicitSpecializationInfo;
ExplicitInfo->TypeAsWritten = TyInfo;
- ExplicitInfo->ExternLoc = ReadSourceLocation(Record, Idx);
- ExplicitInfo->TemplateKeywordLoc = ReadSourceLocation(Record, Idx);
+ ExplicitInfo->ExternLoc = ReadSourceLocation();
+ ExplicitInfo->TemplateKeywordLoc = ReadSourceLocation();
D->ExplicitInfo = ExplicitInfo;
}
SmallVector<TemplateArgument, 8> TemplArgs;
- Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx,
- /*Canonicalize*/ true);
+ Record.readTemplateArgumentList(TemplArgs, /*Canonicalize*/ true);
D->TemplateArgs = TemplateArgumentList::CreateCopy(C, TemplArgs);
- D->PointOfInstantiation = ReadSourceLocation(Record, Idx);
- D->SpecializationKind = (TemplateSpecializationKind)Record[Idx++];
+ D->PointOfInstantiation = ReadSourceLocation();
+ D->SpecializationKind = (TemplateSpecializationKind)Record.readInt();
- bool writtenAsCanonicalDecl = Record[Idx++];
+ bool writtenAsCanonicalDecl = Record.readInt();
if (writtenAsCanonicalDecl) {
- VarTemplateDecl *CanonPattern = ReadDeclAs<VarTemplateDecl>(Record, Idx);
+ VarTemplateDecl *CanonPattern = ReadDeclAs<VarTemplateDecl>();
if (D->isCanonicalDecl()) { // It's kept in the folding set.
// FIXME: If it's already present, merge it.
if (VarTemplatePartialSpecializationDecl *Partial =
@@ -2152,63 +2163,63 @@ void ASTDeclReader::VisitVarTemplatePartialSpecializationDecl(
VarTemplatePartialSpecializationDecl *D) {
RedeclarableResult Redecl = VisitVarTemplateSpecializationDeclImpl(D);
- D->TemplateParams = Reader.ReadTemplateParameterList(F, Record, Idx);
- D->ArgsAsWritten = Reader.ReadASTTemplateArgumentListInfo(F, Record, Idx);
+ D->TemplateParams = Record.readTemplateParameterList();
+ D->ArgsAsWritten = Record.readASTTemplateArgumentListInfo();
// These are read/set from/to the first declaration.
if (ThisDeclID == Redecl.getFirstID()) {
D->InstantiatedFromMember.setPointer(
- ReadDeclAs<VarTemplatePartialSpecializationDecl>(Record, Idx));
- D->InstantiatedFromMember.setInt(Record[Idx++]);
+ ReadDeclAs<VarTemplatePartialSpecializationDecl>());
+ D->InstantiatedFromMember.setInt(Record.readInt());
}
}
void ASTDeclReader::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
VisitTypeDecl(D);
- D->setDeclaredWithTypename(Record[Idx++]);
+ D->setDeclaredWithTypename(Record.readInt());
- if (Record[Idx++])
- D->setDefaultArgument(GetTypeSourceInfo(Record, Idx));
+ if (Record.readInt())
+ D->setDefaultArgument(GetTypeSourceInfo());
}
void ASTDeclReader::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
VisitDeclaratorDecl(D);
// TemplateParmPosition.
- D->setDepth(Record[Idx++]);
- D->setPosition(Record[Idx++]);
+ D->setDepth(Record.readInt());
+ D->setPosition(Record.readInt());
if (D->isExpandedParameterPack()) {
auto TypesAndInfos =
D->getTrailingObjects<std::pair<QualType, TypeSourceInfo *>>();
for (unsigned I = 0, N = D->getNumExpansionTypes(); I != N; ++I) {
- new (&TypesAndInfos[I].first) QualType(Reader.readType(F, Record, Idx));
- TypesAndInfos[I].second = GetTypeSourceInfo(Record, Idx);
+ new (&TypesAndInfos[I].first) QualType(Record.readType());
+ TypesAndInfos[I].second = GetTypeSourceInfo();
}
} else {
// Rest of NonTypeTemplateParmDecl.
- D->ParameterPack = Record[Idx++];
- if (Record[Idx++])
- D->setDefaultArgument(Reader.ReadExpr(F));
+ D->ParameterPack = Record.readInt();
+ if (Record.readInt())
+ D->setDefaultArgument(Record.readExpr());
}
}
void ASTDeclReader::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
VisitTemplateDecl(D);
// TemplateParmPosition.
- D->setDepth(Record[Idx++]);
- D->setPosition(Record[Idx++]);
+ D->setDepth(Record.readInt());
+ D->setPosition(Record.readInt());
if (D->isExpandedParameterPack()) {
TemplateParameterList **Data =
D->getTrailingObjects<TemplateParameterList *>();
for (unsigned I = 0, N = D->getNumExpansionTemplateParameters();
I != N; ++I)
- Data[I] = Reader.ReadTemplateParameterList(F, Record, Idx);
+ Data[I] = Record.readTemplateParameterList();
} else {
// Rest of TemplateTemplateParmDecl.
- D->ParameterPack = Record[Idx++];
- if (Record[Idx++])
+ D->ParameterPack = Record.readInt();
+ if (Record.readInt())
D->setDefaultArgument(Reader.getContext(),
- Reader.ReadTemplateArgumentLoc(F, Record, Idx));
+ Record.readTemplateArgumentLoc());
}
}
@@ -2218,10 +2229,10 @@ void ASTDeclReader::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) {
void ASTDeclReader::VisitStaticAssertDecl(StaticAssertDecl *D) {
VisitDecl(D);
- D->AssertExprAndFailed.setPointer(Reader.ReadExpr(F));
- D->AssertExprAndFailed.setInt(Record[Idx++]);
- D->Message = cast_or_null<StringLiteral>(Reader.ReadExpr(F));
- D->RParenLoc = ReadSourceLocation(Record, Idx);
+ D->AssertExprAndFailed.setPointer(Record.readExpr());
+ D->AssertExprAndFailed.setInt(Record.readInt());
+ D->Message = cast_or_null<StringLiteral>(Record.readExpr());
+ D->RParenLoc = ReadSourceLocation();
}
void ASTDeclReader::VisitEmptyDecl(EmptyDecl *D) {
@@ -2230,15 +2241,15 @@ void ASTDeclReader::VisitEmptyDecl(EmptyDecl *D) {
std::pair<uint64_t, uint64_t>
ASTDeclReader::VisitDeclContext(DeclContext *DC) {
- uint64_t LexicalOffset = ReadLocalOffset(Record, Idx);
- uint64_t VisibleOffset = ReadLocalOffset(Record, Idx);
+ uint64_t LexicalOffset = ReadLocalOffset();
+ uint64_t VisibleOffset = ReadLocalOffset();
return std::make_pair(LexicalOffset, VisibleOffset);
}
template <typename T>
ASTDeclReader::RedeclarableResult
ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
- DeclID FirstDeclID = ReadDeclID(Record, Idx);
+ DeclID FirstDeclID = ReadDeclID();
Decl *MergeWith = nullptr;
bool IsKeyDecl = ThisDeclID == FirstDeclID;
@@ -2252,7 +2263,7 @@ ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
FirstDeclID = ThisDeclID;
IsKeyDecl = true;
IsFirstLocalDecl = true;
- } else if (unsigned N = Record[Idx++]) {
+ } else if (unsigned N = Record.readInt()) {
// This declaration was the first local declaration, but may have imported
// other declarations.
IsKeyDecl = N == 1;
@@ -2264,13 +2275,13 @@ ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
// FIXME: Provide a known merge target to the second and subsequent such
// declaration.
for (unsigned I = 0; I != N - 1; ++I)
- MergeWith = ReadDecl(Record, Idx/*, MergeWith*/);
+ MergeWith = ReadDecl();
- RedeclOffset = ReadLocalOffset(Record, Idx);
+ RedeclOffset = ReadLocalOffset();
} else {
// This declaration was not the first local declaration. Read the first
// local declaration now, to trigger the import of other redeclarations.
- (void)ReadDecl(Record, Idx);
+ (void)ReadDecl();
}
T *FirstDecl = cast_or_null<T>(Reader.GetDecl(FirstDeclID));
@@ -2281,7 +2292,7 @@ ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
// loaded & attached later on.
D->RedeclLink = Redeclarable<T>::PreviousDeclLink(FirstDecl);
D->First = FirstDecl->getCanonicalDecl();
- }
+ }
T *DAsT = static_cast<T*>(D);
@@ -2292,7 +2303,7 @@ ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
if (IsFirstLocalDecl)
Reader.PendingDeclChains.push_back(std::make_pair(DAsT, RedeclOffset));
- return RedeclarableResult(FirstDeclID, MergeWith, IsKeyDecl);
+ return RedeclarableResult(MergeWith, FirstDeclID, IsKeyDecl);
}
/// \brief Attempts to merge the given declaration (D) with another declaration
@@ -2301,8 +2312,6 @@ template<typename T>
void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase,
RedeclarableResult &Redecl,
DeclID TemplatePatternID) {
- T *D = static_cast<T*>(DBase);
-
// If modules are not available, there is no reason to perform this merge.
if (!Reader.getContext().getLangOpts().Modules)
return;
@@ -2311,6 +2320,8 @@ void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase,
if (!DBase->isFirstDecl())
return;
+ T *D = static_cast<T*>(DBase);
+
if (auto *Existing = Redecl.getKnownMergeTarget())
// We already know of an existing declaration we should merge with.
mergeRedeclarable(D, cast<T>(Existing), Redecl, TemplatePatternID);
@@ -2334,8 +2345,9 @@ void ASTDeclReader::mergeTemplatePattern(RedeclarableTemplateDecl *D,
DeclID DsID, bool IsKeyDecl) {
auto *DPattern = D->getTemplatedDecl();
auto *ExistingPattern = Existing->getTemplatedDecl();
- RedeclarableResult Result(DPattern->getCanonicalDecl()->getGlobalID(),
- /*MergeWith*/ ExistingPattern, IsKeyDecl);
+ RedeclarableResult Result(/*MergeWith*/ ExistingPattern,
+ DPattern->getCanonicalDecl()->getGlobalID(),
+ IsKeyDecl);
if (auto *DClass = dyn_cast<CXXRecordDecl>(DPattern)) {
// Merge with any existing definition.
@@ -2436,17 +2448,17 @@ void ASTDeclReader::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) {
SmallVector<Expr *, 16> Vars;
Vars.reserve(NumVars);
for (unsigned i = 0; i != NumVars; ++i) {
- Vars.push_back(Reader.ReadExpr(F));
+ Vars.push_back(Record.readExpr());
}
D->setVars(Vars);
}
void ASTDeclReader::VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D) {
VisitValueDecl(D);
- D->setLocation(Reader.ReadSourceLocation(F, Record, Idx));
- D->setCombiner(Reader.ReadExpr(F));
- D->setInitializer(Reader.ReadExpr(F));
- D->PrevDeclInScope = Reader.ReadDeclID(F, Record, Idx);
+ D->setLocation(ReadSourceLocation());
+ D->setCombiner(Record.readExpr());
+ D->setInitializer(Record.readExpr());
+ D->PrevDeclInScope = ReadDeclID();
}
void ASTDeclReader::VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D) {
@@ -2494,10 +2506,16 @@ inline void ASTReader::LoadedDecl(unsigned Index, Decl *D) {
/// This routine should return true for anything that might affect
/// code generation, e.g., inline function definitions, Objective-C
/// declarations with metadata, etc.
-static bool isConsumerInterestedIn(Decl *D, bool HasBody) {
+static bool isConsumerInterestedIn(ASTContext &Ctx, Decl *D, bool HasBody) {
// An ObjCMethodDecl is never considered as "interesting" because its
// implementation container always is.
+ // An ImportDecl or VarDecl imported from a module will get emitted when
+ // we import the relevant module.
+ if ((isa<ImportDecl>(D) || isa<VarDecl>(D)) && Ctx.DeclMustBeEmitted(D) &&
+ D->getImportedOwningModule())
+ return false;
+
if (isa<FileScopeAsmDecl>(D) ||
isa<ObjCProtocolDecl>(D) ||
isa<ObjCImplDecl>(D) ||
@@ -2867,7 +2885,7 @@ static NamedDecl *getDeclForMerging(NamedDecl *Found,
return nullptr;
if (auto *TND = dyn_cast<TypedefNameDecl>(Found))
- return TND->getAnonDeclWithTypedefName();
+ return TND->getAnonDeclWithTypedefName(/*AnyRedecl*/true);
return nullptr;
}
@@ -3043,6 +3061,29 @@ 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);
+ D->RedeclLink.setPrevious(PrevVD);
+ D->First = PrevVD->First;
+
+ // We should keep at most one definition on the chain.
+ // FIXME: Cache the definition once we've found it. Building a chain with
+ // N definitions currently takes O(N^2) time here.
+ if (VD->isThisDeclarationADefinition() == VarDecl::Definition) {
+ for (VarDecl *CurD = PrevVD; CurD; CurD = CurD->getPreviousDecl()) {
+ if (CurD->isThisDeclarationADefinition() == VarDecl::Definition) {
+ Reader.mergeDefinitionVisibility(CurD, VD);
+ VD->demoteThisDefinitionToDeclaration();
+ break;
+ }
+ }
+ }
+}
+
+template<>
+void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader,
Redeclarable<FunctionDecl> *D,
Decl *Previous, Decl *Canon) {
FunctionDecl *FD = static_cast<FunctionDecl*>(D);
@@ -3215,13 +3256,12 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
Deserializing ADecl(this);
DeclsCursor.JumpToBit(Loc.Offset);
- RecordData Record;
+ ASTRecordReader Record(*this, *Loc.F);
+ ASTDeclReader Reader(*this, Record, Loc, ID, DeclLoc);
unsigned Code = DeclsCursor.ReadCode();
- unsigned Idx = 0;
- ASTDeclReader Reader(*this, Loc, ID, DeclLoc, Record,Idx);
Decl *D = nullptr;
- switch ((DeclCode)DeclsCursor.readRecord(Code, Record)) {
+ switch ((DeclCode)Record.readRecord(DeclsCursor, Code)) {
case DECL_CONTEXT_LEXICAL:
case DECL_CONTEXT_VISIBLE:
llvm_unreachable("Record cannot be de-serialized with ReadDeclRecord");
@@ -3246,6 +3286,9 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
case DECL_LINKAGE_SPEC:
D = LinkageSpecDecl::CreateDeserialized(Context, ID);
break;
+ case DECL_EXPORT:
+ D = ExportDecl::CreateDeserialized(Context, ID);
+ break;
case DECL_LABEL:
D = LabelDecl::CreateDeserialized(Context, ID);
break;
@@ -3258,6 +3301,9 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
case DECL_USING:
D = UsingDecl::CreateDeserialized(Context, ID);
break;
+ case DECL_USING_PACK:
+ D = UsingPackDecl::CreateDeserialized(Context, ID, Record.readInt());
+ break;
case DECL_USING_SHADOW:
D = UsingShadowDecl::CreateDeserialized(Context, ID);
break;
@@ -3295,7 +3341,7 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
D = AccessSpecDecl::CreateDeserialized(Context, ID);
break;
case DECL_FRIEND:
- D = FriendDecl::CreateDeserialized(Context, ID, Record[Idx++]);
+ D = FriendDecl::CreateDeserialized(Context, ID, Record.readInt());
break;
case DECL_FRIEND_TEMPLATE:
D = FriendTemplateDecl::CreateDeserialized(Context, ID);
@@ -3331,14 +3377,15 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
D = NonTypeTemplateParmDecl::CreateDeserialized(Context, ID);
break;
case DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK:
- D = NonTypeTemplateParmDecl::CreateDeserialized(Context, ID, Record[Idx++]);
+ D = NonTypeTemplateParmDecl::CreateDeserialized(Context, ID,
+ Record.readInt());
break;
case DECL_TEMPLATE_TEMPLATE_PARM:
D = TemplateTemplateParmDecl::CreateDeserialized(Context, ID);
break;
case DECL_EXPANDED_TEMPLATE_TEMPLATE_PARM_PACK:
D = TemplateTemplateParmDecl::CreateDeserialized(Context, ID,
- Record[Idx++]);
+ Record.readInt());
break;
case DECL_TYPE_ALIAS_TEMPLATE:
D = TypeAliasTemplateDecl::CreateDeserialized(Context, ID);
@@ -3394,6 +3441,12 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
case DECL_PARM_VAR:
D = ParmVarDecl::CreateDeserialized(Context, ID);
break;
+ case DECL_DECOMPOSITION:
+ D = DecompositionDecl::CreateDeserialized(Context, ID, Record.readInt());
+ break;
+ case DECL_BINDING:
+ D = BindingDecl::CreateDeserialized(Context, ID);
+ break;
case DECL_FILE_SCOPE_ASM:
D = FileScopeAsmDecl::CreateDeserialized(Context, ID);
break;
@@ -3404,7 +3457,7 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
D = MSPropertyDecl::CreateDeserialized(Context, ID);
break;
case DECL_CAPTURED:
- D = CapturedDecl::CreateDeserialized(Context, ID, Record[Idx++]);
+ D = CapturedDecl::CreateDeserialized(Context, ID, Record.readInt());
break;
case DECL_CXX_BASE_SPECIFIERS:
Error("attempt to read a C++ base-specifier record as a declaration");
@@ -3418,7 +3471,7 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
D = ImportDecl::CreateDeserialized(Context, ID, Record.back());
break;
case DECL_OMP_THREADPRIVATE:
- D = OMPThreadPrivateDecl::CreateDeserialized(Context, ID, Record[Idx++]);
+ D = OMPThreadPrivateDecl::CreateDeserialized(Context, ID, Record.readInt());
break;
case DECL_OMP_DECLARE_REDUCTION:
D = OMPDeclareReductionDecl::CreateDeserialized(Context, ID);
@@ -3427,11 +3480,11 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
D = OMPCapturedExprDecl::CreateDeserialized(Context, ID);
break;
case DECL_PRAGMA_COMMENT:
- D = PragmaCommentDecl::CreateDeserialized(Context, ID, Record[Idx++]);
+ D = PragmaCommentDecl::CreateDeserialized(Context, ID, Record.readInt());
break;
case DECL_PRAGMA_DETECT_MISMATCH:
D = PragmaDetectMismatchDecl::CreateDeserialized(Context, ID,
- Record[Idx++]);
+ Record.readInt());
break;
case DECL_EMPTY:
D = EmptyDecl::CreateDeserialized(Context, ID);
@@ -3460,21 +3513,24 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
ReadVisibleDeclContextStorage(*Loc.F, DeclsCursor, Offsets.second, ID))
return nullptr;
}
- assert(Idx == Record.size());
+ assert(Record.getIdx() == Record.size());
// Load any relevant update records.
PendingUpdateRecords.push_back(std::make_pair(ID, D));
// Load the categories after recursive loading is finished.
if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(D))
- if (Class->isThisDeclarationADefinition())
+ // If we already have a definition when deserializing the ObjCInterfaceDecl,
+ // we put the Decl in PendingDefinitions so we can pull the categories here.
+ if (Class->isThisDeclarationADefinition() ||
+ PendingDefinitions.count(Class))
loadObjCCategories(ID, Class);
// If we have deserialized a declaration that has a definition the
// AST consumer might need to know about, queue it.
// We don't pass it to the consumer immediately because we may be in recursive
// loading, and some declarations may still be initializing.
- if (isConsumerInterestedIn(D, Reader.hasPendingBody()))
+ if (isConsumerInterestedIn(Context, D, Reader.hasPendingBody()))
InterestingDecls.push_back(D);
return D;
@@ -3490,28 +3546,27 @@ void ASTReader::loadDeclUpdateRecords(serialization::DeclID ID, Decl *D) {
auto UpdateOffsets = std::move(UpdI->second);
DeclUpdateOffsets.erase(UpdI);
- bool WasInteresting = isConsumerInterestedIn(D, false);
+ bool WasInteresting = isConsumerInterestedIn(Context, D, false);
for (auto &FileAndOffset : UpdateOffsets) {
ModuleFile *F = FileAndOffset.first;
uint64_t Offset = FileAndOffset.second;
llvm::BitstreamCursor &Cursor = F->DeclsCursor;
SavedStreamPosition SavedPosition(Cursor);
Cursor.JumpToBit(Offset);
- RecordData Record;
unsigned Code = Cursor.ReadCode();
- unsigned RecCode = Cursor.readRecord(Code, Record);
+ ASTRecordReader Record(*this, *F);
+ unsigned RecCode = Record.readRecord(Cursor, Code);
(void)RecCode;
assert(RecCode == DECL_UPDATES && "Expected DECL_UPDATES record!");
- unsigned Idx = 0;
- ASTDeclReader Reader(*this, RecordLocation(F, Offset), ID,
- SourceLocation(), Record, Idx);
- Reader.UpdateDecl(D, *F, Record);
+ ASTDeclReader Reader(*this, Record, RecordLocation(F, Offset), ID,
+ SourceLocation());
+ Reader.UpdateDecl(D);
// We might have made this declaration interesting. If so, remember that
// we need to hand it off to the consumer.
if (!WasInteresting &&
- isConsumerInterestedIn(D, Reader.hasPendingBody())) {
+ isConsumerInterestedIn(Context, D, Reader.hasPendingBody())) {
InterestingDecls.push_back(D);
WasInteresting = true;
}
@@ -3578,12 +3633,12 @@ namespace {
/// interface all the categories for it.
class ObjCCategoriesVisitor {
ASTReader &Reader;
- serialization::GlobalDeclID InterfaceID;
ObjCInterfaceDecl *Interface;
llvm::SmallPtrSetImpl<ObjCCategoryDecl *> &Deserialized;
- unsigned PreviousGeneration;
ObjCCategoryDecl *Tail;
llvm::DenseMap<DeclarationName, ObjCCategoryDecl *> NameCategoryMap;
+ serialization::GlobalDeclID InterfaceID;
+ unsigned PreviousGeneration;
void add(ObjCCategoryDecl *Cat) {
// Only process each category once.
@@ -3626,13 +3681,13 @@ namespace {
public:
ObjCCategoriesVisitor(ASTReader &Reader,
- serialization::GlobalDeclID InterfaceID,
ObjCInterfaceDecl *Interface,
- llvm::SmallPtrSetImpl<ObjCCategoryDecl *> &Deserialized,
+ llvm::SmallPtrSetImpl<ObjCCategoryDecl *> &Deserialized,
+ serialization::GlobalDeclID InterfaceID,
unsigned PreviousGeneration)
- : Reader(Reader), InterfaceID(InterfaceID), Interface(Interface),
- Deserialized(Deserialized), PreviousGeneration(PreviousGeneration),
- Tail(nullptr)
+ : Reader(Reader), Interface(Interface), Deserialized(Deserialized),
+ Tail(nullptr), InterfaceID(InterfaceID),
+ PreviousGeneration(PreviousGeneration)
{
// Populate the name -> category map with the set of known categories.
for (auto *Cat : Interface->known_categories()) {
@@ -3687,7 +3742,7 @@ namespace {
void ASTReader::loadObjCCategories(serialization::GlobalDeclID ID,
ObjCInterfaceDecl *D,
unsigned PreviousGeneration) {
- ObjCCategoriesVisitor Visitor(*this, ID, D, CategoriesDeserialized,
+ ObjCCategoriesVisitor Visitor(*this, D, CategoriesDeserialized, ID,
PreviousGeneration);
ModuleMgr.visit(Visitor);
}
@@ -3713,15 +3768,14 @@ static void forAllLaterRedecls(DeclT *D, Fn F) {
}
}
-void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
- const RecordData &Record) {
- while (Idx < Record.size()) {
- switch ((DeclUpdateKind)Record[Idx++]) {
+void ASTDeclReader::UpdateDecl(Decl *D) {
+ while (Record.getIdx() < Record.size()) {
+ switch ((DeclUpdateKind)Record.readInt()) {
case UPD_CXX_ADDED_IMPLICIT_MEMBER: {
auto *RD = cast<CXXRecordDecl>(D);
// FIXME: If we also have an update record for instantiating the
// definition of D, we need that to happen before we get here.
- Decl *MD = Reader.ReadDecl(ModuleFile, Record, Idx);
+ Decl *MD = Record.readDecl();
assert(MD && "couldn't read decl from update record");
// FIXME: We should call addHiddenDecl instead, to add the member
// to its DeclContext.
@@ -3731,18 +3785,16 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
case UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION:
// It will be added to the template's specializations set when loaded.
- (void)Reader.ReadDecl(ModuleFile, Record, Idx);
+ (void)Record.readDecl();
break;
case UPD_CXX_ADDED_ANONYMOUS_NAMESPACE: {
- NamespaceDecl *Anon
- = Reader.ReadDeclAs<NamespaceDecl>(ModuleFile, Record, Idx);
-
+ NamespaceDecl *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 (ModuleFile.Kind != MK_ImplicitModule &&
- ModuleFile.Kind != MK_ExplicitModule) {
+ if (!Record.isModule()) {
if (TranslationUnitDecl *TU = dyn_cast<TranslationUnitDecl>(D))
TU->setAnonymousNamespace(Anon);
else
@@ -3753,7 +3805,7 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
case UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER:
cast<VarDecl>(D)->getMemberSpecializationInfo()->setPointOfInstantiation(
- Reader.ReadSourceLocation(ModuleFile, Record, Idx));
+ ReadSourceLocation());
break;
case UPD_CXX_INSTANTIATED_DEFAULT_ARGUMENT: {
@@ -3762,7 +3814,7 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
// 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 = Reader.ReadExpr(F);
+ auto DefaultArg = Record.readExpr();
// Only apply the update if the parameter still has an uninstantiated
// default argument.
@@ -3771,6 +3823,23 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
break;
}
+ case UPD_CXX_INSTANTIATED_DEFAULT_MEMBER_INITIALIZER: {
+ auto FD = cast<FieldDecl>(D);
+ auto DefaultInit = Record.readExpr();
+
+ // Only apply the update if the field still has an uninstantiated
+ // default member initializer.
+ if (FD->hasInClassInitializer() && !FD->getInClassInitializer()) {
+ if (DefaultInit)
+ FD->setInClassInitializer(DefaultInit);
+ else
+ // Instantiation failed. We can get here if we serialized an AST for
+ // an invalid program.
+ FD->removeInClassInitializer();
+ }
+ break;
+ }
+
case UPD_CXX_ADDED_FUNCTION_DEFINITION: {
FunctionDecl *FD = cast<FunctionDecl>(D);
if (Reader.PendingBodies[FD]) {
@@ -3779,7 +3848,7 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
return;
}
- if (Record[Idx++]) {
+ if (Record.readInt()) {
// Maintain AST consistency: any later redeclarations of this function
// are inline if this one is. (We might have merged another declaration
// into this one.)
@@ -3787,16 +3856,16 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
FD->setImplicitlyInline();
});
}
- FD->setInnerLocStart(Reader.ReadSourceLocation(ModuleFile, Record, Idx));
+ FD->setInnerLocStart(ReadSourceLocation());
if (auto *CD = dyn_cast<CXXConstructorDecl>(FD)) {
- CD->NumCtorInitializers = Record[Idx++];
+ CD->NumCtorInitializers = Record.readInt();
if (CD->NumCtorInitializers)
- CD->CtorInitializers = ReadGlobalOffset(F, Record, Idx);
+ CD->CtorInitializers = ReadGlobalOffset();
}
// Store the offset of the body so we can lazily load it later.
Reader.PendingBodies[FD] = GetCurrentCursorOffset();
HasPendingBody = true;
- assert(Idx == Record.size() && "lazy body must be last");
+ assert(Record.getIdx() == Record.size() && "lazy body must be last");
break;
}
@@ -3809,15 +3878,14 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
ReadCXXRecordDefinition(RD, /*Update*/true);
// Visible update is handled separately.
- uint64_t LexicalOffset = ReadLocalOffset(Record, Idx);
+ uint64_t LexicalOffset = ReadLocalOffset();
if (!HadRealDefinition && LexicalOffset) {
- Reader.ReadLexicalDeclContextStorage(ModuleFile, ModuleFile.DeclsCursor,
- LexicalOffset, RD);
+ Record.readLexicalDeclContextStorage(LexicalOffset, RD);
Reader.PendingFakeDefinitionData.erase(OldDD);
}
- auto TSK = (TemplateSpecializationKind)Record[Idx++];
- SourceLocation POI = Reader.ReadSourceLocation(ModuleFile, Record, Idx);
+ auto TSK = (TemplateSpecializationKind)Record.readInt();
+ SourceLocation POI = ReadSourceLocation();
if (MemberSpecializationInfo *MSInfo =
RD->getMemberSpecializationInfo()) {
MSInfo->setTemplateSpecializationKind(TSK);
@@ -3828,11 +3896,11 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
Spec->setTemplateSpecializationKind(TSK);
Spec->setPointOfInstantiation(POI);
- if (Record[Idx++]) {
+ if (Record.readInt()) {
auto PartialSpec =
- ReadDeclAs<ClassTemplatePartialSpecializationDecl>(Record, Idx);
+ ReadDeclAs<ClassTemplatePartialSpecializationDecl>();
SmallVector<TemplateArgument, 8> TemplArgs;
- Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx);
+ Record.readTemplateArgumentList(TemplArgs);
auto *TemplArgList = TemplateArgumentList::CreateCopy(
Reader.getContext(), TemplArgs);
@@ -3844,15 +3912,18 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
}
}
- RD->setTagKind((TagTypeKind)Record[Idx++]);
- RD->setLocation(Reader.ReadSourceLocation(ModuleFile, Record, Idx));
- RD->setLocStart(Reader.ReadSourceLocation(ModuleFile, Record, Idx));
- RD->setBraceRange(Reader.ReadSourceRange(ModuleFile, Record, Idx));
+ RD->setTagKind((TagTypeKind)Record.readInt());
+ RD->setLocation(ReadSourceLocation());
+ RD->setLocStart(ReadSourceLocation());
+ RD->setBraceRange(ReadSourceRange());
- if (Record[Idx++]) {
+ if (Record.readInt()) {
AttrVec Attrs;
- Reader.ReadAttributes(F, Attrs, Record, Idx);
- D->setAttrsImpl(Attrs, Reader.getContext());
+ Record.readAttributes(Attrs);
+ // If the declaration already has attributes, we assume that some other
+ // AST file already loaded them.
+ if (!D->hasAttrs())
+ D->setAttrsImpl(Attrs, Reader.getContext());
}
break;
}
@@ -3860,7 +3931,7 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
case UPD_CXX_RESOLVED_DTOR_DELETE: {
// Set the 'operator delete' directly to avoid emitting another update
// record.
- auto *Del = Reader.ReadDeclAs<FunctionDecl>(ModuleFile, Record, Idx);
+ auto *Del = ReadDeclAs<FunctionDecl>();
auto *First = cast<CXXDestructorDecl>(D->getCanonicalDecl());
// FIXME: Check consistency if we have an old and new operator delete.
if (!First->OperatorDelete)
@@ -3871,7 +3942,7 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
case UPD_CXX_RESOLVED_EXCEPTION_SPEC: {
FunctionProtoType::ExceptionSpecInfo ESI;
SmallVector<QualType, 8> ExceptionStorage;
- Reader.readExceptionSpec(ModuleFile, ExceptionStorage, ESI, Record, Idx);
+ Record.readExceptionSpec(ExceptionStorage, ESI);
// Update this declaration's exception specification, if needed.
auto *FD = cast<FunctionDecl>(D);
@@ -3893,7 +3964,7 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
case UPD_CXX_DEDUCED_RETURN_TYPE: {
// FIXME: Also do this when merging redecls.
- QualType DeducedResultType = Reader.readType(ModuleFile, Record, Idx);
+ 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);
@@ -3909,20 +3980,20 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
}
case UPD_MANGLING_NUMBER:
- Reader.Context.setManglingNumber(cast<NamedDecl>(D), Record[Idx++]);
+ Reader.Context.setManglingNumber(cast<NamedDecl>(D), Record.readInt());
break;
case UPD_STATIC_LOCAL_NUMBER:
- Reader.Context.setStaticLocalNumber(cast<VarDecl>(D), Record[Idx++]);
+ Reader.Context.setStaticLocalNumber(cast<VarDecl>(D), Record.readInt());
break;
case UPD_DECL_MARKED_OPENMP_THREADPRIVATE:
D->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
- Reader.Context, ReadSourceRange(Record, Idx)));
+ Reader.Context, ReadSourceRange()));
break;
case UPD_DECL_EXPORTED: {
- unsigned SubmoduleID = readSubmoduleID(Record, Idx);
+ unsigned SubmoduleID = readSubmoduleID();
auto *Exported = cast<NamedDecl>(D);
if (auto *TD = dyn_cast<TagDecl>(Exported))
Exported = TD->getDefinition();
@@ -3946,7 +4017,7 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
case UPD_DECL_MARKED_OPENMP_DECLARETARGET:
case UPD_ADDED_ATTR_TO_RECORD:
AttrVec Attrs;
- Reader.ReadAttributes(F, Attrs, Record, Idx);
+ Record.readAttributes(Attrs);
assert(Attrs.size() == 1);
D->addAttr(Attrs[0]);
break;
diff --git a/lib/Serialization/ASTReaderInternals.h b/lib/Serialization/ASTReaderInternals.h
index d392364a971b..6cb4d662e338 100644
--- a/lib/Serialization/ASTReaderInternals.h
+++ b/lib/Serialization/ASTReaderInternals.h
@@ -13,14 +13,12 @@
#ifndef LLVM_CLANG_LIB_SERIALIZATION_ASTREADERINTERNALS_H
#define LLVM_CLANG_LIB_SERIALIZATION_ASTREADERINTERNALS_H
+#include "MultiOnDiskHashTable.h"
#include "clang/AST/DeclarationName.h"
#include "clang/Serialization/ASTBitCodes.h"
#include "llvm/ADT/DenseSet.h"
-#include "llvm/ADT/PointerUnion.h"
-#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/OnDiskHashTable.h"
-#include "MultiOnDiskHashTable.h"
#include <utility>
namespace clang {
@@ -112,17 +110,6 @@ public:
struct DeclContextLookupTable {
MultiOnDiskHashTable<ASTDeclContextNameLookupTrait> Table;
-
- // These look redundant, but don't remove them -- they work around MSVC 2013's
- // inability to synthesize move operations. Without them, the
- // MultiOnDiskHashTable will be copied (despite being move-only!).
- DeclContextLookupTable() : Table() {}
- DeclContextLookupTable(DeclContextLookupTable &&O)
- : Table(std::move(O.Table)) {}
- DeclContextLookupTable &operator=(DeclContextLookupTable &&O) {
- Table = std::move(O.Table);
- return *this;
- }
};
/// \brief Base class for the trait describing the on-disk hash table for the
@@ -259,7 +246,7 @@ public:
struct internal_key_type {
off_t Size;
time_t ModTime;
- const char *Filename;
+ StringRef Filename;
bool Imported;
};
typedef const internal_key_type &internal_key_ref;
diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp
index 395da42d4f24..5607f764a9c3 100644
--- a/lib/Serialization/ASTReaderStmt.cpp
+++ b/lib/Serialization/ASTReaderStmt.cpp
@@ -26,62 +26,47 @@ namespace clang {
class ASTStmtReader : public StmtVisitor<ASTStmtReader> {
friend class OMPClauseReader;
- typedef ASTReader::RecordData RecordData;
-
- ASTReader &Reader;
- ModuleFile &F;
+
+ ASTRecordReader &Record;
llvm::BitstreamCursor &DeclsCursor;
- const ASTReader::RecordData &Record;
- unsigned &Idx;
- Token ReadToken(const RecordData &R, unsigned &I) {
- return Reader.ReadToken(F, R, I);
+ SourceLocation ReadSourceLocation() {
+ return Record.readSourceLocation();
}
- SourceLocation ReadSourceLocation(const RecordData &R, unsigned &I) {
- return Reader.ReadSourceLocation(F, R, I);
+ SourceRange ReadSourceRange() {
+ return Record.readSourceRange();
}
- SourceRange ReadSourceRange(const RecordData &R, unsigned &I) {
- return Reader.ReadSourceRange(F, R, I);
+ std::string ReadString() {
+ return Record.readString();
}
- std::string ReadString(const RecordData &R, unsigned &I) {
- return Reader.ReadString(R, I);
- }
-
- TypeSourceInfo *GetTypeSourceInfo(const RecordData &R, unsigned &I) {
- return Reader.GetTypeSourceInfo(F, R, I);
- }
-
- serialization::DeclID ReadDeclID(const RecordData &R, unsigned &I) {
- return Reader.ReadDeclID(F, R, I);
+ TypeSourceInfo *GetTypeSourceInfo() {
+ return Record.getTypeSourceInfo();
}
-
- Decl *ReadDecl(const RecordData &R, unsigned &I) {
- return Reader.ReadDecl(F, R, I);
+
+ Decl *ReadDecl() {
+ return Record.readDecl();
}
-
+
template<typename T>
- T *ReadDeclAs(const RecordData &R, unsigned &I) {
- return Reader.ReadDeclAs<T>(F, R, I);
+ T *ReadDeclAs() {
+ return Record.readDeclAs<T>();
}
- void ReadDeclarationNameLoc(DeclarationNameLoc &DNLoc, DeclarationName Name,
- const ASTReader::RecordData &R, unsigned &I) {
- Reader.ReadDeclarationNameLoc(F, DNLoc, Name, R, I);
+ void ReadDeclarationNameLoc(DeclarationNameLoc &DNLoc,
+ DeclarationName Name) {
+ Record.readDeclarationNameLoc(DNLoc, Name);
}
-
- void ReadDeclarationNameInfo(DeclarationNameInfo &NameInfo,
- const ASTReader::RecordData &R, unsigned &I) {
- Reader.ReadDeclarationNameInfo(F, NameInfo, R, I);
+
+ void ReadDeclarationNameInfo(DeclarationNameInfo &NameInfo) {
+ Record.readDeclarationNameInfo(NameInfo);
}
public:
- ASTStmtReader(ASTReader &Reader, ModuleFile &F,
- llvm::BitstreamCursor &Cursor,
- const ASTReader::RecordData &Record, unsigned &Idx)
- : Reader(Reader), F(F), DeclsCursor(Cursor), Record(Record), Idx(Idx) { }
+ ASTStmtReader(ASTRecordReader &Record, llvm::BitstreamCursor &Cursor)
+ : Record(Record), DeclsCursor(Cursor) {}
/// \brief The number of record fields required for the Stmt class
/// itself.
@@ -109,106 +94,103 @@ namespace clang {
void ASTStmtReader::ReadTemplateKWAndArgsInfo(ASTTemplateKWAndArgsInfo &Args,
TemplateArgumentLoc *ArgsLocArray,
unsigned NumTemplateArgs) {
- SourceLocation TemplateKWLoc = ReadSourceLocation(Record, Idx);
+ SourceLocation TemplateKWLoc = ReadSourceLocation();
TemplateArgumentListInfo ArgInfo;
- ArgInfo.setLAngleLoc(ReadSourceLocation(Record, Idx));
- ArgInfo.setRAngleLoc(ReadSourceLocation(Record, Idx));
+ ArgInfo.setLAngleLoc(ReadSourceLocation());
+ ArgInfo.setRAngleLoc(ReadSourceLocation());
for (unsigned i = 0; i != NumTemplateArgs; ++i)
- ArgInfo.addArgument(
- Reader.ReadTemplateArgumentLoc(F, Record, Idx));
+ ArgInfo.addArgument(Record.readTemplateArgumentLoc());
Args.initializeFrom(TemplateKWLoc, ArgInfo, ArgsLocArray);
}
void ASTStmtReader::VisitStmt(Stmt *S) {
- assert(Idx == NumStmtFields && "Incorrect statement field count");
+ assert(Record.getIdx() == NumStmtFields && "Incorrect statement field count");
}
void ASTStmtReader::VisitNullStmt(NullStmt *S) {
VisitStmt(S);
- S->setSemiLoc(ReadSourceLocation(Record, Idx));
- S->HasLeadingEmptyMacro = Record[Idx++];
+ S->setSemiLoc(ReadSourceLocation());
+ S->HasLeadingEmptyMacro = Record.readInt();
}
void ASTStmtReader::VisitCompoundStmt(CompoundStmt *S) {
VisitStmt(S);
SmallVector<Stmt *, 16> Stmts;
- unsigned NumStmts = Record[Idx++];
+ unsigned NumStmts = Record.readInt();
while (NumStmts--)
- Stmts.push_back(Reader.ReadSubStmt());
- S->setStmts(Reader.getContext(), Stmts);
- S->LBraceLoc = ReadSourceLocation(Record, Idx);
- S->RBraceLoc = ReadSourceLocation(Record, Idx);
+ Stmts.push_back(Record.readSubStmt());
+ S->setStmts(Record.getContext(), Stmts);
+ S->LBraceLoc = ReadSourceLocation();
+ S->RBraceLoc = ReadSourceLocation();
}
void ASTStmtReader::VisitSwitchCase(SwitchCase *S) {
VisitStmt(S);
- Reader.RecordSwitchCaseID(S, Record[Idx++]);
- S->setKeywordLoc(ReadSourceLocation(Record, Idx));
- S->setColonLoc(ReadSourceLocation(Record, Idx));
+ Record.recordSwitchCaseID(S, Record.readInt());
+ S->setKeywordLoc(ReadSourceLocation());
+ S->setColonLoc(ReadSourceLocation());
}
void ASTStmtReader::VisitCaseStmt(CaseStmt *S) {
VisitSwitchCase(S);
- S->setLHS(Reader.ReadSubExpr());
- S->setRHS(Reader.ReadSubExpr());
- S->setSubStmt(Reader.ReadSubStmt());
- S->setEllipsisLoc(ReadSourceLocation(Record, Idx));
+ S->setLHS(Record.readSubExpr());
+ S->setRHS(Record.readSubExpr());
+ S->setSubStmt(Record.readSubStmt());
+ S->setEllipsisLoc(ReadSourceLocation());
}
void ASTStmtReader::VisitDefaultStmt(DefaultStmt *S) {
VisitSwitchCase(S);
- S->setSubStmt(Reader.ReadSubStmt());
+ S->setSubStmt(Record.readSubStmt());
}
void ASTStmtReader::VisitLabelStmt(LabelStmt *S) {
VisitStmt(S);
- LabelDecl *LD = ReadDeclAs<LabelDecl>(Record, Idx);
+ LabelDecl *LD = ReadDeclAs<LabelDecl>();
LD->setStmt(S);
S->setDecl(LD);
- S->setSubStmt(Reader.ReadSubStmt());
- S->setIdentLoc(ReadSourceLocation(Record, Idx));
+ S->setSubStmt(Record.readSubStmt());
+ S->setIdentLoc(ReadSourceLocation());
}
void ASTStmtReader::VisitAttributedStmt(AttributedStmt *S) {
VisitStmt(S);
- uint64_t NumAttrs = Record[Idx++];
+ uint64_t NumAttrs = Record.readInt();
AttrVec Attrs;
- Reader.ReadAttributes(F, Attrs, Record, Idx);
+ Record.readAttributes(Attrs);
(void)NumAttrs;
assert(NumAttrs == S->NumAttrs);
assert(NumAttrs == Attrs.size());
std::copy(Attrs.begin(), Attrs.end(), S->getAttrArrayPtr());
- S->SubStmt = Reader.ReadSubStmt();
- S->AttrLoc = ReadSourceLocation(Record, Idx);
+ S->SubStmt = Record.readSubStmt();
+ S->AttrLoc = ReadSourceLocation();
}
void ASTStmtReader::VisitIfStmt(IfStmt *S) {
VisitStmt(S);
- S->setConstexpr(Record[Idx++]);
- S->setInit(Reader.ReadSubStmt());
- S->setConditionVariable(Reader.getContext(),
- ReadDeclAs<VarDecl>(Record, Idx));
- S->setCond(Reader.ReadSubExpr());
- S->setThen(Reader.ReadSubStmt());
- S->setElse(Reader.ReadSubStmt());
- S->setIfLoc(ReadSourceLocation(Record, Idx));
- S->setElseLoc(ReadSourceLocation(Record, Idx));
+ S->setConstexpr(Record.readInt());
+ S->setInit(Record.readSubStmt());
+ S->setConditionVariable(Record.getContext(), ReadDeclAs<VarDecl>());
+ S->setCond(Record.readSubExpr());
+ S->setThen(Record.readSubStmt());
+ S->setElse(Record.readSubStmt());
+ S->setIfLoc(ReadSourceLocation());
+ S->setElseLoc(ReadSourceLocation());
}
void ASTStmtReader::VisitSwitchStmt(SwitchStmt *S) {
VisitStmt(S);
- S->setInit(Reader.ReadSubStmt());
- S->setConditionVariable(Reader.getContext(),
- ReadDeclAs<VarDecl>(Record, Idx));
- S->setCond(Reader.ReadSubExpr());
- S->setBody(Reader.ReadSubStmt());
- S->setSwitchLoc(ReadSourceLocation(Record, Idx));
- if (Record[Idx++])
+ S->setInit(Record.readSubStmt());
+ S->setConditionVariable(Record.getContext(), ReadDeclAs<VarDecl>());
+ S->setCond(Record.readSubExpr());
+ S->setBody(Record.readSubStmt());
+ S->setSwitchLoc(ReadSourceLocation());
+ if (Record.readInt())
S->setAllEnumCasesCovered();
SwitchCase *PrevSC = nullptr;
- for (unsigned N = Record.size(); Idx != N; ++Idx) {
- SwitchCase *SC = Reader.getSwitchCaseWithID(Record[Idx]);
+ for (auto E = Record.size(); Record.getIdx() != E; ) {
+ SwitchCase *SC = Record.getSwitchCaseWithID(Record.readInt());
if (PrevSC)
PrevSC->setNextSwitchCase(SC);
else
@@ -220,81 +202,80 @@ void ASTStmtReader::VisitSwitchStmt(SwitchStmt *S) {
void ASTStmtReader::VisitWhileStmt(WhileStmt *S) {
VisitStmt(S);
- S->setConditionVariable(Reader.getContext(),
- ReadDeclAs<VarDecl>(Record, Idx));
+ S->setConditionVariable(Record.getContext(), ReadDeclAs<VarDecl>());
- S->setCond(Reader.ReadSubExpr());
- S->setBody(Reader.ReadSubStmt());
- S->setWhileLoc(ReadSourceLocation(Record, Idx));
+ S->setCond(Record.readSubExpr());
+ S->setBody(Record.readSubStmt());
+ S->setWhileLoc(ReadSourceLocation());
}
void ASTStmtReader::VisitDoStmt(DoStmt *S) {
VisitStmt(S);
- S->setCond(Reader.ReadSubExpr());
- S->setBody(Reader.ReadSubStmt());
- S->setDoLoc(ReadSourceLocation(Record, Idx));
- S->setWhileLoc(ReadSourceLocation(Record, Idx));
- S->setRParenLoc(ReadSourceLocation(Record, Idx));
+ S->setCond(Record.readSubExpr());
+ S->setBody(Record.readSubStmt());
+ S->setDoLoc(ReadSourceLocation());
+ S->setWhileLoc(ReadSourceLocation());
+ S->setRParenLoc(ReadSourceLocation());
}
void ASTStmtReader::VisitForStmt(ForStmt *S) {
VisitStmt(S);
- S->setInit(Reader.ReadSubStmt());
- S->setCond(Reader.ReadSubExpr());
- S->setConditionVariable(Reader.getContext(),
- ReadDeclAs<VarDecl>(Record, Idx));
- S->setInc(Reader.ReadSubExpr());
- S->setBody(Reader.ReadSubStmt());
- S->setForLoc(ReadSourceLocation(Record, Idx));
- S->setLParenLoc(ReadSourceLocation(Record, Idx));
- S->setRParenLoc(ReadSourceLocation(Record, Idx));
+ S->setInit(Record.readSubStmt());
+ S->setCond(Record.readSubExpr());
+ S->setConditionVariable(Record.getContext(), ReadDeclAs<VarDecl>());
+ S->setInc(Record.readSubExpr());
+ S->setBody(Record.readSubStmt());
+ S->setForLoc(ReadSourceLocation());
+ S->setLParenLoc(ReadSourceLocation());
+ S->setRParenLoc(ReadSourceLocation());
}
void ASTStmtReader::VisitGotoStmt(GotoStmt *S) {
VisitStmt(S);
- S->setLabel(ReadDeclAs<LabelDecl>(Record, Idx));
- S->setGotoLoc(ReadSourceLocation(Record, Idx));
- S->setLabelLoc(ReadSourceLocation(Record, Idx));
+ S->setLabel(ReadDeclAs<LabelDecl>());
+ S->setGotoLoc(ReadSourceLocation());
+ S->setLabelLoc(ReadSourceLocation());
}
void ASTStmtReader::VisitIndirectGotoStmt(IndirectGotoStmt *S) {
VisitStmt(S);
- S->setGotoLoc(ReadSourceLocation(Record, Idx));
- S->setStarLoc(ReadSourceLocation(Record, Idx));
- S->setTarget(Reader.ReadSubExpr());
+ S->setGotoLoc(ReadSourceLocation());
+ S->setStarLoc(ReadSourceLocation());
+ S->setTarget(Record.readSubExpr());
}
void ASTStmtReader::VisitContinueStmt(ContinueStmt *S) {
VisitStmt(S);
- S->setContinueLoc(ReadSourceLocation(Record, Idx));
+ S->setContinueLoc(ReadSourceLocation());
}
void ASTStmtReader::VisitBreakStmt(BreakStmt *S) {
VisitStmt(S);
- S->setBreakLoc(ReadSourceLocation(Record, Idx));
+ S->setBreakLoc(ReadSourceLocation());
}
void ASTStmtReader::VisitReturnStmt(ReturnStmt *S) {
VisitStmt(S);
- S->setRetValue(Reader.ReadSubExpr());
- S->setReturnLoc(ReadSourceLocation(Record, Idx));
- S->setNRVOCandidate(ReadDeclAs<VarDecl>(Record, Idx));
+ S->setRetValue(Record.readSubExpr());
+ S->setReturnLoc(ReadSourceLocation());
+ S->setNRVOCandidate(ReadDeclAs<VarDecl>());
}
void ASTStmtReader::VisitDeclStmt(DeclStmt *S) {
VisitStmt(S);
- S->setStartLoc(ReadSourceLocation(Record, Idx));
- S->setEndLoc(ReadSourceLocation(Record, Idx));
+ S->setStartLoc(ReadSourceLocation());
+ S->setEndLoc(ReadSourceLocation());
- if (Idx + 1 == Record.size()) {
+ if (Record.size() - Record.getIdx() == 1) {
// Single declaration
- S->setDeclGroup(DeclGroupRef(ReadDecl(Record, Idx)));
+ S->setDeclGroup(DeclGroupRef(ReadDecl()));
} else {
SmallVector<Decl *, 16> Decls;
- Decls.reserve(Record.size() - Idx);
- for (unsigned N = Record.size(); Idx != N; )
- Decls.push_back(ReadDecl(Record, Idx));
- S->setDeclGroup(DeclGroupRef(DeclGroup::Create(Reader.getContext(),
+ int N = Record.size() - Record.getIdx();
+ Decls.reserve(N);
+ for (int I = 0; I < N; ++I)
+ Decls.push_back(ReadDecl());
+ S->setDeclGroup(DeclGroupRef(DeclGroup::Create(Record.getContext(),
Decls.data(),
Decls.size())));
}
@@ -302,18 +283,18 @@ void ASTStmtReader::VisitDeclStmt(DeclStmt *S) {
void ASTStmtReader::VisitAsmStmt(AsmStmt *S) {
VisitStmt(S);
- S->NumOutputs = Record[Idx++];
- S->NumInputs = Record[Idx++];
- S->NumClobbers = Record[Idx++];
- S->setAsmLoc(ReadSourceLocation(Record, Idx));
- S->setVolatile(Record[Idx++]);
- S->setSimple(Record[Idx++]);
+ S->NumOutputs = Record.readInt();
+ S->NumInputs = Record.readInt();
+ S->NumClobbers = Record.readInt();
+ S->setAsmLoc(ReadSourceLocation());
+ S->setVolatile(Record.readInt());
+ S->setSimple(Record.readInt());
}
void ASTStmtReader::VisitGCCAsmStmt(GCCAsmStmt *S) {
VisitAsmStmt(S);
- S->setRParenLoc(ReadSourceLocation(Record, Idx));
- S->setAsmString(cast_or_null<StringLiteral>(Reader.ReadSubStmt()));
+ S->setRParenLoc(ReadSourceLocation());
+ S->setAsmString(cast_or_null<StringLiteral>(Record.readSubStmt()));
unsigned NumOutputs = S->getNumOutputs();
unsigned NumInputs = S->getNumInputs();
@@ -324,34 +305,34 @@ void ASTStmtReader::VisitGCCAsmStmt(GCCAsmStmt *S) {
SmallVector<StringLiteral*, 16> Constraints;
SmallVector<Stmt*, 16> Exprs;
for (unsigned I = 0, N = NumOutputs + NumInputs; I != N; ++I) {
- Names.push_back(Reader.GetIdentifierInfo(F, Record, Idx));
- Constraints.push_back(cast_or_null<StringLiteral>(Reader.ReadSubStmt()));
- Exprs.push_back(Reader.ReadSubStmt());
+ Names.push_back(Record.getIdentifierInfo());
+ Constraints.push_back(cast_or_null<StringLiteral>(Record.readSubStmt()));
+ Exprs.push_back(Record.readSubStmt());
}
// Constraints
SmallVector<StringLiteral*, 16> Clobbers;
for (unsigned I = 0; I != NumClobbers; ++I)
- Clobbers.push_back(cast_or_null<StringLiteral>(Reader.ReadSubStmt()));
+ Clobbers.push_back(cast_or_null<StringLiteral>(Record.readSubStmt()));
- S->setOutputsAndInputsAndClobbers(Reader.getContext(),
- Names.data(), Constraints.data(),
- Exprs.data(), NumOutputs, NumInputs,
+ S->setOutputsAndInputsAndClobbers(Record.getContext(),
+ Names.data(), Constraints.data(),
+ Exprs.data(), NumOutputs, NumInputs,
Clobbers.data(), NumClobbers);
}
void ASTStmtReader::VisitMSAsmStmt(MSAsmStmt *S) {
VisitAsmStmt(S);
- S->LBraceLoc = ReadSourceLocation(Record, Idx);
- S->EndLoc = ReadSourceLocation(Record, Idx);
- S->NumAsmToks = Record[Idx++];
- std::string AsmStr = ReadString(Record, Idx);
+ S->LBraceLoc = ReadSourceLocation();
+ S->EndLoc = ReadSourceLocation();
+ S->NumAsmToks = Record.readInt();
+ std::string AsmStr = ReadString();
// Read the tokens.
SmallVector<Token, 16> AsmToks;
AsmToks.reserve(S->NumAsmToks);
for (unsigned i = 0, e = S->NumAsmToks; i != e; ++i) {
- AsmToks.push_back(ReadToken(Record, Idx));
+ AsmToks.push_back(Record.readToken());
}
// The calls to reserve() for the FooData vectors are mandatory to
@@ -363,7 +344,7 @@ void ASTStmtReader::VisitMSAsmStmt(MSAsmStmt *S) {
ClobbersData.reserve(S->NumClobbers);
Clobbers.reserve(S->NumClobbers);
for (unsigned i = 0, e = S->NumClobbers; i != e; ++i) {
- ClobbersData.push_back(ReadString(Record, Idx));
+ ClobbersData.push_back(ReadString());
Clobbers.push_back(ClobbersData.back());
}
@@ -376,12 +357,12 @@ void ASTStmtReader::VisitMSAsmStmt(MSAsmStmt *S) {
ConstraintsData.reserve(NumOperands);
Constraints.reserve(NumOperands);
for (unsigned i = 0; i != NumOperands; ++i) {
- Exprs.push_back(cast<Expr>(Reader.ReadSubStmt()));
- ConstraintsData.push_back(ReadString(Record, Idx));
+ Exprs.push_back(cast<Expr>(Record.readSubStmt()));
+ ConstraintsData.push_back(ReadString());
Constraints.push_back(ConstraintsData.back());
}
- S->initialize(Reader.getContext(), AsmStr, AsmToks,
+ S->initialize(Record.getContext(), AsmStr, AsmToks,
Constraints, Exprs, Clobbers);
}
@@ -407,229 +388,229 @@ void ASTStmtReader::VisitCoyieldExpr(CoyieldExpr *S) {
void ASTStmtReader::VisitCapturedStmt(CapturedStmt *S) {
VisitStmt(S);
- ++Idx;
- S->setCapturedDecl(ReadDeclAs<CapturedDecl>(Record, Idx));
- S->setCapturedRegionKind(static_cast<CapturedRegionKind>(Record[Idx++]));
- S->setCapturedRecordDecl(ReadDeclAs<RecordDecl>(Record, Idx));
+ Record.skipInts(1);
+ S->setCapturedDecl(ReadDeclAs<CapturedDecl>());
+ S->setCapturedRegionKind(static_cast<CapturedRegionKind>(Record.readInt()));
+ S->setCapturedRecordDecl(ReadDeclAs<RecordDecl>());
// Capture inits
for (CapturedStmt::capture_init_iterator I = S->capture_init_begin(),
E = S->capture_init_end();
I != E; ++I)
- *I = Reader.ReadSubExpr();
+ *I = Record.readSubExpr();
// Body
- S->setCapturedStmt(Reader.ReadSubStmt());
+ S->setCapturedStmt(Record.readSubStmt());
S->getCapturedDecl()->setBody(S->getCapturedStmt());
// Captures
for (auto &I : S->captures()) {
- I.VarAndKind.setPointer(ReadDeclAs<VarDecl>(Record, Idx));
- I.VarAndKind
- .setInt(static_cast<CapturedStmt::VariableCaptureKind>(Record[Idx++]));
- I.Loc = ReadSourceLocation(Record, Idx);
+ I.VarAndKind.setPointer(ReadDeclAs<VarDecl>());
+ I.VarAndKind.setInt(
+ static_cast<CapturedStmt::VariableCaptureKind>(Record.readInt()));
+ I.Loc = ReadSourceLocation();
}
}
void ASTStmtReader::VisitExpr(Expr *E) {
VisitStmt(E);
- E->setType(Reader.readType(F, Record, Idx));
- E->setTypeDependent(Record[Idx++]);
- E->setValueDependent(Record[Idx++]);
- E->setInstantiationDependent(Record[Idx++]);
- E->ExprBits.ContainsUnexpandedParameterPack = Record[Idx++];
- E->setValueKind(static_cast<ExprValueKind>(Record[Idx++]));
- E->setObjectKind(static_cast<ExprObjectKind>(Record[Idx++]));
- assert(Idx == NumExprFields && "Incorrect expression field count");
+ E->setType(Record.readType());
+ E->setTypeDependent(Record.readInt());
+ E->setValueDependent(Record.readInt());
+ E->setInstantiationDependent(Record.readInt());
+ E->ExprBits.ContainsUnexpandedParameterPack = Record.readInt();
+ E->setValueKind(static_cast<ExprValueKind>(Record.readInt()));
+ E->setObjectKind(static_cast<ExprObjectKind>(Record.readInt()));
+ assert(Record.getIdx() == NumExprFields &&
+ "Incorrect expression field count");
}
void ASTStmtReader::VisitPredefinedExpr(PredefinedExpr *E) {
VisitExpr(E);
- E->setLocation(ReadSourceLocation(Record, Idx));
- E->Type = (PredefinedExpr::IdentType)Record[Idx++];
- E->FnName = cast_or_null<StringLiteral>(Reader.ReadSubExpr());
+ E->setLocation(ReadSourceLocation());
+ E->Type = (PredefinedExpr::IdentType)Record.readInt();
+ E->FnName = cast_or_null<StringLiteral>(Record.readSubExpr());
}
void ASTStmtReader::VisitDeclRefExpr(DeclRefExpr *E) {
VisitExpr(E);
- E->DeclRefExprBits.HasQualifier = Record[Idx++];
- E->DeclRefExprBits.HasFoundDecl = Record[Idx++];
- E->DeclRefExprBits.HasTemplateKWAndArgsInfo = Record[Idx++];
- E->DeclRefExprBits.HadMultipleCandidates = Record[Idx++];
- E->DeclRefExprBits.RefersToEnclosingVariableOrCapture = Record[Idx++];
+ E->DeclRefExprBits.HasQualifier = Record.readInt();
+ E->DeclRefExprBits.HasFoundDecl = Record.readInt();
+ E->DeclRefExprBits.HasTemplateKWAndArgsInfo = Record.readInt();
+ E->DeclRefExprBits.HadMultipleCandidates = Record.readInt();
+ E->DeclRefExprBits.RefersToEnclosingVariableOrCapture = Record.readInt();
unsigned NumTemplateArgs = 0;
if (E->hasTemplateKWAndArgsInfo())
- NumTemplateArgs = Record[Idx++];
+ NumTemplateArgs = Record.readInt();
if (E->hasQualifier())
new (E->getTrailingObjects<NestedNameSpecifierLoc>())
- NestedNameSpecifierLoc(
- Reader.ReadNestedNameSpecifierLoc(F, Record, Idx));
+ NestedNameSpecifierLoc(Record.readNestedNameSpecifierLoc());
if (E->hasFoundDecl())
- *E->getTrailingObjects<NamedDecl *>() = ReadDeclAs<NamedDecl>(Record, Idx);
+ *E->getTrailingObjects<NamedDecl *>() = ReadDeclAs<NamedDecl>();
if (E->hasTemplateKWAndArgsInfo())
ReadTemplateKWAndArgsInfo(
*E->getTrailingObjects<ASTTemplateKWAndArgsInfo>(),
E->getTrailingObjects<TemplateArgumentLoc>(), NumTemplateArgs);
- E->setDecl(ReadDeclAs<ValueDecl>(Record, Idx));
- E->setLocation(ReadSourceLocation(Record, Idx));
- ReadDeclarationNameLoc(E->DNLoc, E->getDecl()->getDeclName(), Record, Idx);
+ E->setDecl(ReadDeclAs<ValueDecl>());
+ E->setLocation(ReadSourceLocation());
+ ReadDeclarationNameLoc(E->DNLoc, E->getDecl()->getDeclName());
}
void ASTStmtReader::VisitIntegerLiteral(IntegerLiteral *E) {
VisitExpr(E);
- E->setLocation(ReadSourceLocation(Record, Idx));
- E->setValue(Reader.getContext(), Reader.ReadAPInt(Record, Idx));
+ E->setLocation(ReadSourceLocation());
+ E->setValue(Record.getContext(), Record.readAPInt());
}
void ASTStmtReader::VisitFloatingLiteral(FloatingLiteral *E) {
VisitExpr(E);
- E->setRawSemantics(static_cast<Stmt::APFloatSemantics>(Record[Idx++]));
- E->setExact(Record[Idx++]);
- E->setValue(Reader.getContext(),
- Reader.ReadAPFloat(Record, E->getSemantics(), Idx));
- E->setLocation(ReadSourceLocation(Record, Idx));
+ E->setRawSemantics(static_cast<Stmt::APFloatSemantics>(Record.readInt()));
+ E->setExact(Record.readInt());
+ E->setValue(Record.getContext(), Record.readAPFloat(E->getSemantics()));
+ E->setLocation(ReadSourceLocation());
}
void ASTStmtReader::VisitImaginaryLiteral(ImaginaryLiteral *E) {
VisitExpr(E);
- E->setSubExpr(Reader.ReadSubExpr());
+ E->setSubExpr(Record.readSubExpr());
}
void ASTStmtReader::VisitStringLiteral(StringLiteral *E) {
VisitExpr(E);
- unsigned Len = Record[Idx++];
- assert(Record[Idx] == E->getNumConcatenated() &&
+ unsigned Len = Record.readInt();
+ assert(Record.peekInt() == E->getNumConcatenated() &&
"Wrong number of concatenated tokens!");
- ++Idx;
+ Record.skipInts(1);
StringLiteral::StringKind kind =
- static_cast<StringLiteral::StringKind>(Record[Idx++]);
- bool isPascal = Record[Idx++];
+ static_cast<StringLiteral::StringKind>(Record.readInt());
+ bool isPascal = Record.readInt();
// Read string data
- SmallString<16> Str(&Record[Idx], &Record[Idx] + Len);
- E->setString(Reader.getContext(), Str, kind, isPascal);
- Idx += Len;
+ auto B = &Record.peekInt();
+ SmallString<16> Str(B, B + Len);
+ E->setString(Record.getContext(), Str, kind, isPascal);
+ Record.skipInts(Len);
// Read source locations
for (unsigned I = 0, N = E->getNumConcatenated(); I != N; ++I)
- E->setStrTokenLoc(I, ReadSourceLocation(Record, Idx));
+ E->setStrTokenLoc(I, ReadSourceLocation());
}
void ASTStmtReader::VisitCharacterLiteral(CharacterLiteral *E) {
VisitExpr(E);
- E->setValue(Record[Idx++]);
- E->setLocation(ReadSourceLocation(Record, Idx));
- E->setKind(static_cast<CharacterLiteral::CharacterKind>(Record[Idx++]));
+ E->setValue(Record.readInt());
+ E->setLocation(ReadSourceLocation());
+ E->setKind(static_cast<CharacterLiteral::CharacterKind>(Record.readInt()));
}
void ASTStmtReader::VisitParenExpr(ParenExpr *E) {
VisitExpr(E);
- E->setLParen(ReadSourceLocation(Record, Idx));
- E->setRParen(ReadSourceLocation(Record, Idx));
- E->setSubExpr(Reader.ReadSubExpr());
+ E->setLParen(ReadSourceLocation());
+ E->setRParen(ReadSourceLocation());
+ E->setSubExpr(Record.readSubExpr());
}
void ASTStmtReader::VisitParenListExpr(ParenListExpr *E) {
VisitExpr(E);
- unsigned NumExprs = Record[Idx++];
- E->Exprs = new (Reader.getContext()) Stmt*[NumExprs];
+ unsigned NumExprs = Record.readInt();
+ E->Exprs = new (Record.getContext()) Stmt*[NumExprs];
for (unsigned i = 0; i != NumExprs; ++i)
- E->Exprs[i] = Reader.ReadSubStmt();
+ E->Exprs[i] = Record.readSubStmt();
E->NumExprs = NumExprs;
- E->LParenLoc = ReadSourceLocation(Record, Idx);
- E->RParenLoc = ReadSourceLocation(Record, Idx);
+ E->LParenLoc = ReadSourceLocation();
+ E->RParenLoc = ReadSourceLocation();
}
void ASTStmtReader::VisitUnaryOperator(UnaryOperator *E) {
VisitExpr(E);
- E->setSubExpr(Reader.ReadSubExpr());
- E->setOpcode((UnaryOperator::Opcode)Record[Idx++]);
- E->setOperatorLoc(ReadSourceLocation(Record, Idx));
+ E->setSubExpr(Record.readSubExpr());
+ E->setOpcode((UnaryOperator::Opcode)Record.readInt());
+ E->setOperatorLoc(ReadSourceLocation());
}
void ASTStmtReader::VisitOffsetOfExpr(OffsetOfExpr *E) {
VisitExpr(E);
- assert(E->getNumComponents() == Record[Idx]);
- ++Idx;
- assert(E->getNumExpressions() == Record[Idx]);
- ++Idx;
- E->setOperatorLoc(ReadSourceLocation(Record, Idx));
- E->setRParenLoc(ReadSourceLocation(Record, Idx));
- E->setTypeSourceInfo(GetTypeSourceInfo(Record, Idx));
+ assert(E->getNumComponents() == Record.peekInt());
+ Record.skipInts(1);
+ assert(E->getNumExpressions() == Record.peekInt());
+ Record.skipInts(1);
+ E->setOperatorLoc(ReadSourceLocation());
+ E->setRParenLoc(ReadSourceLocation());
+ E->setTypeSourceInfo(GetTypeSourceInfo());
for (unsigned I = 0, N = E->getNumComponents(); I != N; ++I) {
- OffsetOfNode::Kind Kind = static_cast<OffsetOfNode::Kind>(Record[Idx++]);
- SourceLocation Start = ReadSourceLocation(Record, Idx);
- SourceLocation End = ReadSourceLocation(Record, Idx);
+ OffsetOfNode::Kind Kind = static_cast<OffsetOfNode::Kind>(Record.readInt());
+ SourceLocation Start = ReadSourceLocation();
+ SourceLocation End = ReadSourceLocation();
switch (Kind) {
case OffsetOfNode::Array:
- E->setComponent(I, OffsetOfNode(Start, Record[Idx++], End));
+ E->setComponent(I, OffsetOfNode(Start, Record.readInt(), End));
break;
case OffsetOfNode::Field:
E->setComponent(
- I, OffsetOfNode(Start, ReadDeclAs<FieldDecl>(Record, Idx), End));
+ I, OffsetOfNode(Start, ReadDeclAs<FieldDecl>(), End));
break;
case OffsetOfNode::Identifier:
E->setComponent(
I,
- OffsetOfNode(Start, Reader.GetIdentifierInfo(F, Record, Idx), End));
+ OffsetOfNode(Start, Record.getIdentifierInfo(), End));
break;
case OffsetOfNode::Base: {
- CXXBaseSpecifier *Base = new (Reader.getContext()) CXXBaseSpecifier();
- *Base = Reader.ReadCXXBaseSpecifier(F, Record, Idx);
+ CXXBaseSpecifier *Base = new (Record.getContext()) CXXBaseSpecifier();
+ *Base = Record.readCXXBaseSpecifier();
E->setComponent(I, OffsetOfNode(Base));
break;
}
}
}
-
+
for (unsigned I = 0, N = E->getNumExpressions(); I != N; ++I)
- E->setIndexExpr(I, Reader.ReadSubExpr());
+ E->setIndexExpr(I, Record.readSubExpr());
}
void ASTStmtReader::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E) {
VisitExpr(E);
- E->setKind(static_cast<UnaryExprOrTypeTrait>(Record[Idx++]));
- if (Record[Idx] == 0) {
- E->setArgument(Reader.ReadSubExpr());
- ++Idx;
+ E->setKind(static_cast<UnaryExprOrTypeTrait>(Record.readInt()));
+ if (Record.peekInt() == 0) {
+ E->setArgument(Record.readSubExpr());
+ Record.skipInts(1);
} else {
- E->setArgument(GetTypeSourceInfo(Record, Idx));
+ E->setArgument(GetTypeSourceInfo());
}
- E->setOperatorLoc(ReadSourceLocation(Record, Idx));
- E->setRParenLoc(ReadSourceLocation(Record, Idx));
+ E->setOperatorLoc(ReadSourceLocation());
+ E->setRParenLoc(ReadSourceLocation());
}
void ASTStmtReader::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
VisitExpr(E);
- E->setLHS(Reader.ReadSubExpr());
- E->setRHS(Reader.ReadSubExpr());
- E->setRBracketLoc(ReadSourceLocation(Record, Idx));
+ E->setLHS(Record.readSubExpr());
+ E->setRHS(Record.readSubExpr());
+ E->setRBracketLoc(ReadSourceLocation());
}
void ASTStmtReader::VisitOMPArraySectionExpr(OMPArraySectionExpr *E) {
VisitExpr(E);
- E->setBase(Reader.ReadSubExpr());
- E->setLowerBound(Reader.ReadSubExpr());
- E->setLength(Reader.ReadSubExpr());
- E->setColonLoc(ReadSourceLocation(Record, Idx));
- E->setRBracketLoc(ReadSourceLocation(Record, Idx));
+ E->setBase(Record.readSubExpr());
+ E->setLowerBound(Record.readSubExpr());
+ E->setLength(Record.readSubExpr());
+ E->setColonLoc(ReadSourceLocation());
+ E->setRBracketLoc(ReadSourceLocation());
}
void ASTStmtReader::VisitCallExpr(CallExpr *E) {
VisitExpr(E);
- E->setNumArgs(Reader.getContext(), Record[Idx++]);
- E->setRParenLoc(ReadSourceLocation(Record, Idx));
- E->setCallee(Reader.ReadSubExpr());
+ E->setNumArgs(Record.getContext(), Record.readInt());
+ E->setRParenLoc(ReadSourceLocation());
+ E->setCallee(Record.readSubExpr());
for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I)
- E->setArg(I, Reader.ReadSubExpr());
+ E->setArg(I, Record.readSubExpr());
}
void ASTStmtReader::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) {
@@ -644,74 +625,74 @@ void ASTStmtReader::VisitMemberExpr(MemberExpr *E) {
void ASTStmtReader::VisitObjCIsaExpr(ObjCIsaExpr *E) {
VisitExpr(E);
- E->setBase(Reader.ReadSubExpr());
- E->setIsaMemberLoc(ReadSourceLocation(Record, Idx));
- E->setOpLoc(ReadSourceLocation(Record, Idx));
- E->setArrow(Record[Idx++]);
+ E->setBase(Record.readSubExpr());
+ E->setIsaMemberLoc(ReadSourceLocation());
+ E->setOpLoc(ReadSourceLocation());
+ E->setArrow(Record.readInt());
}
void ASTStmtReader::
VisitObjCIndirectCopyRestoreExpr(ObjCIndirectCopyRestoreExpr *E) {
VisitExpr(E);
- E->Operand = Reader.ReadSubExpr();
- E->setShouldCopy(Record[Idx++]);
+ E->Operand = Record.readSubExpr();
+ E->setShouldCopy(Record.readInt());
}
void ASTStmtReader::VisitObjCBridgedCastExpr(ObjCBridgedCastExpr *E) {
VisitExplicitCastExpr(E);
- E->LParenLoc = ReadSourceLocation(Record, Idx);
- E->BridgeKeywordLoc = ReadSourceLocation(Record, Idx);
- E->Kind = Record[Idx++];
+ E->LParenLoc = ReadSourceLocation();
+ E->BridgeKeywordLoc = ReadSourceLocation();
+ E->Kind = Record.readInt();
}
void ASTStmtReader::VisitCastExpr(CastExpr *E) {
VisitExpr(E);
- unsigned NumBaseSpecs = Record[Idx++];
+ unsigned NumBaseSpecs = Record.readInt();
assert(NumBaseSpecs == E->path_size());
- E->setSubExpr(Reader.ReadSubExpr());
- E->setCastKind((CastKind)Record[Idx++]);
+ E->setSubExpr(Record.readSubExpr());
+ E->setCastKind((CastKind)Record.readInt());
CastExpr::path_iterator BaseI = E->path_begin();
while (NumBaseSpecs--) {
- CXXBaseSpecifier *BaseSpec = new (Reader.getContext()) CXXBaseSpecifier;
- *BaseSpec = Reader.ReadCXXBaseSpecifier(F, Record, Idx);
+ CXXBaseSpecifier *BaseSpec = new (Record.getContext()) CXXBaseSpecifier;
+ *BaseSpec = Record.readCXXBaseSpecifier();
*BaseI++ = BaseSpec;
}
}
void ASTStmtReader::VisitBinaryOperator(BinaryOperator *E) {
VisitExpr(E);
- E->setLHS(Reader.ReadSubExpr());
- E->setRHS(Reader.ReadSubExpr());
- E->setOpcode((BinaryOperator::Opcode)Record[Idx++]);
- E->setOperatorLoc(ReadSourceLocation(Record, Idx));
- E->setFPContractable((bool)Record[Idx++]);
+ E->setLHS(Record.readSubExpr());
+ E->setRHS(Record.readSubExpr());
+ E->setOpcode((BinaryOperator::Opcode)Record.readInt());
+ E->setOperatorLoc(ReadSourceLocation());
+ E->setFPContractable((bool)Record.readInt());
}
void ASTStmtReader::VisitCompoundAssignOperator(CompoundAssignOperator *E) {
VisitBinaryOperator(E);
- E->setComputationLHSType(Reader.readType(F, Record, Idx));
- E->setComputationResultType(Reader.readType(F, Record, Idx));
+ E->setComputationLHSType(Record.readType());
+ E->setComputationResultType(Record.readType());
}
void ASTStmtReader::VisitConditionalOperator(ConditionalOperator *E) {
VisitExpr(E);
- E->SubExprs[ConditionalOperator::COND] = Reader.ReadSubExpr();
- E->SubExprs[ConditionalOperator::LHS] = Reader.ReadSubExpr();
- E->SubExprs[ConditionalOperator::RHS] = Reader.ReadSubExpr();
- E->QuestionLoc = ReadSourceLocation(Record, Idx);
- E->ColonLoc = ReadSourceLocation(Record, Idx);
+ E->SubExprs[ConditionalOperator::COND] = Record.readSubExpr();
+ E->SubExprs[ConditionalOperator::LHS] = Record.readSubExpr();
+ E->SubExprs[ConditionalOperator::RHS] = Record.readSubExpr();
+ E->QuestionLoc = ReadSourceLocation();
+ E->ColonLoc = ReadSourceLocation();
}
void
ASTStmtReader::VisitBinaryConditionalOperator(BinaryConditionalOperator *E) {
VisitExpr(E);
- E->OpaqueValue = cast<OpaqueValueExpr>(Reader.ReadSubExpr());
- E->SubExprs[BinaryConditionalOperator::COMMON] = Reader.ReadSubExpr();
- E->SubExprs[BinaryConditionalOperator::COND] = Reader.ReadSubExpr();
- E->SubExprs[BinaryConditionalOperator::LHS] = Reader.ReadSubExpr();
- E->SubExprs[BinaryConditionalOperator::RHS] = Reader.ReadSubExpr();
- E->QuestionLoc = ReadSourceLocation(Record, Idx);
- E->ColonLoc = ReadSourceLocation(Record, Idx);
+ E->OpaqueValue = cast<OpaqueValueExpr>(Record.readSubExpr());
+ E->SubExprs[BinaryConditionalOperator::COMMON] = Record.readSubExpr();
+ E->SubExprs[BinaryConditionalOperator::COND] = Record.readSubExpr();
+ E->SubExprs[BinaryConditionalOperator::LHS] = Record.readSubExpr();
+ E->SubExprs[BinaryConditionalOperator::RHS] = Record.readSubExpr();
+ E->QuestionLoc = ReadSourceLocation();
+ E->ColonLoc = ReadSourceLocation();
}
void ASTStmtReader::VisitImplicitCastExpr(ImplicitCastExpr *E) {
@@ -720,54 +701,54 @@ void ASTStmtReader::VisitImplicitCastExpr(ImplicitCastExpr *E) {
void ASTStmtReader::VisitExplicitCastExpr(ExplicitCastExpr *E) {
VisitCastExpr(E);
- E->setTypeInfoAsWritten(GetTypeSourceInfo(Record, Idx));
+ E->setTypeInfoAsWritten(GetTypeSourceInfo());
}
void ASTStmtReader::VisitCStyleCastExpr(CStyleCastExpr *E) {
VisitExplicitCastExpr(E);
- E->setLParenLoc(ReadSourceLocation(Record, Idx));
- E->setRParenLoc(ReadSourceLocation(Record, Idx));
+ E->setLParenLoc(ReadSourceLocation());
+ E->setRParenLoc(ReadSourceLocation());
}
void ASTStmtReader::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
VisitExpr(E);
- E->setLParenLoc(ReadSourceLocation(Record, Idx));
- E->setTypeSourceInfo(GetTypeSourceInfo(Record, Idx));
- E->setInitializer(Reader.ReadSubExpr());
- E->setFileScope(Record[Idx++]);
+ E->setLParenLoc(ReadSourceLocation());
+ E->setTypeSourceInfo(GetTypeSourceInfo());
+ E->setInitializer(Record.readSubExpr());
+ E->setFileScope(Record.readInt());
}
void ASTStmtReader::VisitExtVectorElementExpr(ExtVectorElementExpr *E) {
VisitExpr(E);
- E->setBase(Reader.ReadSubExpr());
- E->setAccessor(Reader.GetIdentifierInfo(F, Record, Idx));
- E->setAccessorLoc(ReadSourceLocation(Record, Idx));
+ E->setBase(Record.readSubExpr());
+ E->setAccessor(Record.getIdentifierInfo());
+ E->setAccessorLoc(ReadSourceLocation());
}
void ASTStmtReader::VisitInitListExpr(InitListExpr *E) {
VisitExpr(E);
- if (InitListExpr *SyntForm = cast_or_null<InitListExpr>(Reader.ReadSubStmt()))
+ if (InitListExpr *SyntForm = cast_or_null<InitListExpr>(Record.readSubStmt()))
E->setSyntacticForm(SyntForm);
- E->setLBraceLoc(ReadSourceLocation(Record, Idx));
- E->setRBraceLoc(ReadSourceLocation(Record, Idx));
- bool isArrayFiller = Record[Idx++];
+ E->setLBraceLoc(ReadSourceLocation());
+ E->setRBraceLoc(ReadSourceLocation());
+ bool isArrayFiller = Record.readInt();
Expr *filler = nullptr;
if (isArrayFiller) {
- filler = Reader.ReadSubExpr();
+ filler = Record.readSubExpr();
E->ArrayFillerOrUnionFieldInit = filler;
} else
- E->ArrayFillerOrUnionFieldInit = ReadDeclAs<FieldDecl>(Record, Idx);
- E->sawArrayRangeDesignator(Record[Idx++]);
- unsigned NumInits = Record[Idx++];
- E->reserveInits(Reader.getContext(), NumInits);
+ E->ArrayFillerOrUnionFieldInit = ReadDeclAs<FieldDecl>();
+ E->sawArrayRangeDesignator(Record.readInt());
+ unsigned NumInits = Record.readInt();
+ E->reserveInits(Record.getContext(), NumInits);
if (isArrayFiller) {
for (unsigned I = 0; I != NumInits; ++I) {
- Expr *init = Reader.ReadSubExpr();
- E->updateInit(Reader.getContext(), I, init ? init : filler);
+ Expr *init = Record.readSubExpr();
+ E->updateInit(Record.getContext(), I, init ? init : filler);
}
} else {
for (unsigned I = 0; I != NumInits; ++I)
- E->updateInit(Reader.getContext(), I, Reader.ReadSubExpr());
+ E->updateInit(Record.getContext(), I, Record.readSubExpr());
}
}
@@ -775,22 +756,20 @@ void ASTStmtReader::VisitDesignatedInitExpr(DesignatedInitExpr *E) {
typedef DesignatedInitExpr::Designator Designator;
VisitExpr(E);
- unsigned NumSubExprs = Record[Idx++];
+ unsigned NumSubExprs = Record.readInt();
assert(NumSubExprs == E->getNumSubExprs() && "Wrong number of subexprs");
for (unsigned I = 0; I != NumSubExprs; ++I)
- E->setSubExpr(I, Reader.ReadSubExpr());
- E->setEqualOrColonLoc(ReadSourceLocation(Record, Idx));
- E->setGNUSyntax(Record[Idx++]);
+ E->setSubExpr(I, Record.readSubExpr());
+ E->setEqualOrColonLoc(ReadSourceLocation());
+ E->setGNUSyntax(Record.readInt());
SmallVector<Designator, 4> Designators;
- while (Idx < Record.size()) {
- switch ((DesignatorTypes)Record[Idx++]) {
+ while (Record.getIdx() < Record.size()) {
+ switch ((DesignatorTypes)Record.readInt()) {
case DESIG_FIELD_DECL: {
- FieldDecl *Field = ReadDeclAs<FieldDecl>(Record, Idx);
- SourceLocation DotLoc
- = ReadSourceLocation(Record, Idx);
- SourceLocation FieldLoc
- = ReadSourceLocation(Record, Idx);
+ FieldDecl *Field = ReadDeclAs<FieldDecl>();
+ SourceLocation DotLoc = ReadSourceLocation();
+ SourceLocation FieldLoc = ReadSourceLocation();
Designators.push_back(Designator(Field->getIdentifier(), DotLoc,
FieldLoc));
Designators.back().setField(Field);
@@ -798,162 +777,165 @@ void ASTStmtReader::VisitDesignatedInitExpr(DesignatedInitExpr *E) {
}
case DESIG_FIELD_NAME: {
- const IdentifierInfo *Name = Reader.GetIdentifierInfo(F, Record, Idx);
- SourceLocation DotLoc
- = ReadSourceLocation(Record, Idx);
- SourceLocation FieldLoc
- = ReadSourceLocation(Record, Idx);
+ const IdentifierInfo *Name = Record.getIdentifierInfo();
+ SourceLocation DotLoc = ReadSourceLocation();
+ SourceLocation FieldLoc = ReadSourceLocation();
Designators.push_back(Designator(Name, DotLoc, FieldLoc));
break;
}
case DESIG_ARRAY: {
- unsigned Index = Record[Idx++];
- SourceLocation LBracketLoc
- = ReadSourceLocation(Record, Idx);
- SourceLocation RBracketLoc
- = ReadSourceLocation(Record, Idx);
+ unsigned Index = Record.readInt();
+ SourceLocation LBracketLoc = ReadSourceLocation();
+ SourceLocation RBracketLoc = ReadSourceLocation();
Designators.push_back(Designator(Index, LBracketLoc, RBracketLoc));
break;
}
case DESIG_ARRAY_RANGE: {
- unsigned Index = Record[Idx++];
- SourceLocation LBracketLoc
- = ReadSourceLocation(Record, Idx);
- SourceLocation EllipsisLoc
- = ReadSourceLocation(Record, Idx);
- SourceLocation RBracketLoc
- = ReadSourceLocation(Record, Idx);
+ unsigned Index = Record.readInt();
+ SourceLocation LBracketLoc = ReadSourceLocation();
+ SourceLocation EllipsisLoc = ReadSourceLocation();
+ SourceLocation RBracketLoc = ReadSourceLocation();
Designators.push_back(Designator(Index, LBracketLoc, EllipsisLoc,
RBracketLoc));
break;
}
}
}
- E->setDesignators(Reader.getContext(),
+ E->setDesignators(Record.getContext(),
Designators.data(), Designators.size());
}
void ASTStmtReader::VisitDesignatedInitUpdateExpr(DesignatedInitUpdateExpr *E) {
VisitExpr(E);
- E->setBase(Reader.ReadSubExpr());
- E->setUpdater(Reader.ReadSubExpr());
+ E->setBase(Record.readSubExpr());
+ E->setUpdater(Record.readSubExpr());
}
void ASTStmtReader::VisitNoInitExpr(NoInitExpr *E) {
VisitExpr(E);
}
+void ASTStmtReader::VisitArrayInitLoopExpr(ArrayInitLoopExpr *E) {
+ VisitExpr(E);
+ E->SubExprs[0] = Record.readSubExpr();
+ E->SubExprs[1] = Record.readSubExpr();
+}
+
+void ASTStmtReader::VisitArrayInitIndexExpr(ArrayInitIndexExpr *E) {
+ VisitExpr(E);
+}
+
void ASTStmtReader::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) {
VisitExpr(E);
}
void ASTStmtReader::VisitVAArgExpr(VAArgExpr *E) {
VisitExpr(E);
- E->setSubExpr(Reader.ReadSubExpr());
- E->setWrittenTypeInfo(GetTypeSourceInfo(Record, Idx));
- E->setBuiltinLoc(ReadSourceLocation(Record, Idx));
- E->setRParenLoc(ReadSourceLocation(Record, Idx));
- E->setIsMicrosoftABI(Record[Idx++]);
+ E->setSubExpr(Record.readSubExpr());
+ E->setWrittenTypeInfo(GetTypeSourceInfo());
+ E->setBuiltinLoc(ReadSourceLocation());
+ E->setRParenLoc(ReadSourceLocation());
+ E->setIsMicrosoftABI(Record.readInt());
}
void ASTStmtReader::VisitAddrLabelExpr(AddrLabelExpr *E) {
VisitExpr(E);
- E->setAmpAmpLoc(ReadSourceLocation(Record, Idx));
- E->setLabelLoc(ReadSourceLocation(Record, Idx));
- E->setLabel(ReadDeclAs<LabelDecl>(Record, Idx));
+ E->setAmpAmpLoc(ReadSourceLocation());
+ E->setLabelLoc(ReadSourceLocation());
+ E->setLabel(ReadDeclAs<LabelDecl>());
}
void ASTStmtReader::VisitStmtExpr(StmtExpr *E) {
VisitExpr(E);
- E->setLParenLoc(ReadSourceLocation(Record, Idx));
- E->setRParenLoc(ReadSourceLocation(Record, Idx));
- E->setSubStmt(cast_or_null<CompoundStmt>(Reader.ReadSubStmt()));
+ E->setLParenLoc(ReadSourceLocation());
+ E->setRParenLoc(ReadSourceLocation());
+ E->setSubStmt(cast_or_null<CompoundStmt>(Record.readSubStmt()));
}
void ASTStmtReader::VisitChooseExpr(ChooseExpr *E) {
VisitExpr(E);
- E->setCond(Reader.ReadSubExpr());
- E->setLHS(Reader.ReadSubExpr());
- E->setRHS(Reader.ReadSubExpr());
- E->setBuiltinLoc(ReadSourceLocation(Record, Idx));
- E->setRParenLoc(ReadSourceLocation(Record, Idx));
- E->setIsConditionTrue(Record[Idx++]);
+ E->setCond(Record.readSubExpr());
+ E->setLHS(Record.readSubExpr());
+ E->setRHS(Record.readSubExpr());
+ E->setBuiltinLoc(ReadSourceLocation());
+ E->setRParenLoc(ReadSourceLocation());
+ E->setIsConditionTrue(Record.readInt());
}
void ASTStmtReader::VisitGNUNullExpr(GNUNullExpr *E) {
VisitExpr(E);
- E->setTokenLocation(ReadSourceLocation(Record, Idx));
+ E->setTokenLocation(ReadSourceLocation());
}
void ASTStmtReader::VisitShuffleVectorExpr(ShuffleVectorExpr *E) {
VisitExpr(E);
SmallVector<Expr *, 16> Exprs;
- unsigned NumExprs = Record[Idx++];
+ unsigned NumExprs = Record.readInt();
while (NumExprs--)
- Exprs.push_back(Reader.ReadSubExpr());
- E->setExprs(Reader.getContext(), Exprs);
- E->setBuiltinLoc(ReadSourceLocation(Record, Idx));
- E->setRParenLoc(ReadSourceLocation(Record, Idx));
+ Exprs.push_back(Record.readSubExpr());
+ E->setExprs(Record.getContext(), Exprs);
+ E->setBuiltinLoc(ReadSourceLocation());
+ E->setRParenLoc(ReadSourceLocation());
}
void ASTStmtReader::VisitConvertVectorExpr(ConvertVectorExpr *E) {
VisitExpr(E);
- E->BuiltinLoc = ReadSourceLocation(Record, Idx);
- E->RParenLoc = ReadSourceLocation(Record, Idx);
- E->TInfo = GetTypeSourceInfo(Record, Idx);
- E->SrcExpr = Reader.ReadSubExpr();
+ E->BuiltinLoc = ReadSourceLocation();
+ E->RParenLoc = ReadSourceLocation();
+ E->TInfo = GetTypeSourceInfo();
+ E->SrcExpr = Record.readSubExpr();
}
void ASTStmtReader::VisitBlockExpr(BlockExpr *E) {
VisitExpr(E);
- E->setBlockDecl(ReadDeclAs<BlockDecl>(Record, Idx));
+ E->setBlockDecl(ReadDeclAs<BlockDecl>());
}
void ASTStmtReader::VisitGenericSelectionExpr(GenericSelectionExpr *E) {
VisitExpr(E);
- E->NumAssocs = Record[Idx++];
- E->AssocTypes = new (Reader.getContext()) TypeSourceInfo*[E->NumAssocs];
+ E->NumAssocs = Record.readInt();
+ E->AssocTypes = new (Record.getContext()) TypeSourceInfo*[E->NumAssocs];
E->SubExprs =
- new(Reader.getContext()) Stmt*[GenericSelectionExpr::END_EXPR+E->NumAssocs];
+ new(Record.getContext()) Stmt*[GenericSelectionExpr::END_EXPR+E->NumAssocs];
- E->SubExprs[GenericSelectionExpr::CONTROLLING] = Reader.ReadSubExpr();
+ E->SubExprs[GenericSelectionExpr::CONTROLLING] = Record.readSubExpr();
for (unsigned I = 0, N = E->getNumAssocs(); I != N; ++I) {
- E->AssocTypes[I] = GetTypeSourceInfo(Record, Idx);
- E->SubExprs[GenericSelectionExpr::END_EXPR+I] = Reader.ReadSubExpr();
+ E->AssocTypes[I] = GetTypeSourceInfo();
+ E->SubExprs[GenericSelectionExpr::END_EXPR+I] = Record.readSubExpr();
}
- E->ResultIndex = Record[Idx++];
+ E->ResultIndex = Record.readInt();
- E->GenericLoc = ReadSourceLocation(Record, Idx);
- E->DefaultLoc = ReadSourceLocation(Record, Idx);
- E->RParenLoc = ReadSourceLocation(Record, Idx);
+ E->GenericLoc = ReadSourceLocation();
+ E->DefaultLoc = ReadSourceLocation();
+ E->RParenLoc = ReadSourceLocation();
}
void ASTStmtReader::VisitPseudoObjectExpr(PseudoObjectExpr *E) {
VisitExpr(E);
- unsigned numSemanticExprs = Record[Idx++];
+ unsigned numSemanticExprs = Record.readInt();
assert(numSemanticExprs + 1 == E->PseudoObjectExprBits.NumSubExprs);
- E->PseudoObjectExprBits.ResultIndex = Record[Idx++];
+ E->PseudoObjectExprBits.ResultIndex = Record.readInt();
// Read the syntactic expression.
- E->getSubExprsBuffer()[0] = Reader.ReadSubExpr();
+ E->getSubExprsBuffer()[0] = Record.readSubExpr();
// Read all the semantic expressions.
for (unsigned i = 0; i != numSemanticExprs; ++i) {
- Expr *subExpr = Reader.ReadSubExpr();
+ Expr *subExpr = Record.readSubExpr();
E->getSubExprsBuffer()[i+1] = subExpr;
}
}
void ASTStmtReader::VisitAtomicExpr(AtomicExpr *E) {
VisitExpr(E);
- E->Op = AtomicExpr::AtomicOp(Record[Idx++]);
+ E->Op = AtomicExpr::AtomicOp(Record.readInt());
E->NumSubExprs = AtomicExpr::getNumSubExprs(E->Op);
for (unsigned I = 0; I != E->NumSubExprs; ++I)
- E->SubExprs[I] = Reader.ReadSubExpr();
- E->BuiltinLoc = ReadSourceLocation(Record, Idx);
- E->RParenLoc = ReadSourceLocation(Record, Idx);
+ E->SubExprs[I] = Record.readSubExpr();
+ E->BuiltinLoc = ReadSourceLocation();
+ E->RParenLoc = ReadSourceLocation();
}
//===----------------------------------------------------------------------===//
@@ -961,142 +943,141 @@ void ASTStmtReader::VisitAtomicExpr(AtomicExpr *E) {
void ASTStmtReader::VisitObjCStringLiteral(ObjCStringLiteral *E) {
VisitExpr(E);
- E->setString(cast<StringLiteral>(Reader.ReadSubStmt()));
- E->setAtLoc(ReadSourceLocation(Record, Idx));
+ E->setString(cast<StringLiteral>(Record.readSubStmt()));
+ E->setAtLoc(ReadSourceLocation());
}
void ASTStmtReader::VisitObjCBoxedExpr(ObjCBoxedExpr *E) {
VisitExpr(E);
// could be one of several IntegerLiteral, FloatLiteral, etc.
- E->SubExpr = Reader.ReadSubStmt();
- E->BoxingMethod = ReadDeclAs<ObjCMethodDecl>(Record, Idx);
- E->Range = ReadSourceRange(Record, Idx);
+ E->SubExpr = Record.readSubStmt();
+ E->BoxingMethod = ReadDeclAs<ObjCMethodDecl>();
+ E->Range = ReadSourceRange();
}
void ASTStmtReader::VisitObjCArrayLiteral(ObjCArrayLiteral *E) {
VisitExpr(E);
- unsigned NumElements = Record[Idx++];
+ unsigned NumElements = Record.readInt();
assert(NumElements == E->getNumElements() && "Wrong number of elements");
Expr **Elements = E->getElements();
for (unsigned I = 0, N = NumElements; I != N; ++I)
- Elements[I] = Reader.ReadSubExpr();
- E->ArrayWithObjectsMethod = ReadDeclAs<ObjCMethodDecl>(Record, Idx);
- E->Range = ReadSourceRange(Record, Idx);
+ Elements[I] = Record.readSubExpr();
+ E->ArrayWithObjectsMethod = ReadDeclAs<ObjCMethodDecl>();
+ E->Range = ReadSourceRange();
}
void ASTStmtReader::VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) {
VisitExpr(E);
- unsigned NumElements = Record[Idx++];
+ unsigned NumElements = Record.readInt();
assert(NumElements == E->getNumElements() && "Wrong number of elements");
- bool HasPackExpansions = Record[Idx++];
+ bool HasPackExpansions = Record.readInt();
assert(HasPackExpansions == E->HasPackExpansions &&"Pack expansion mismatch");
ObjCDictionaryLiteral::KeyValuePair *KeyValues =
E->getTrailingObjects<ObjCDictionaryLiteral::KeyValuePair>();
ObjCDictionaryLiteral::ExpansionData *Expansions =
E->getTrailingObjects<ObjCDictionaryLiteral::ExpansionData>();
for (unsigned I = 0; I != NumElements; ++I) {
- KeyValues[I].Key = Reader.ReadSubExpr();
- KeyValues[I].Value = Reader.ReadSubExpr();
+ KeyValues[I].Key = Record.readSubExpr();
+ KeyValues[I].Value = Record.readSubExpr();
if (HasPackExpansions) {
- Expansions[I].EllipsisLoc = ReadSourceLocation(Record, Idx);
- Expansions[I].NumExpansionsPlusOne = Record[Idx++];
+ Expansions[I].EllipsisLoc = ReadSourceLocation();
+ Expansions[I].NumExpansionsPlusOne = Record.readInt();
}
}
- E->DictWithObjectsMethod = ReadDeclAs<ObjCMethodDecl>(Record, Idx);
- E->Range = ReadSourceRange(Record, Idx);
+ E->DictWithObjectsMethod = ReadDeclAs<ObjCMethodDecl>();
+ E->Range = ReadSourceRange();
}
void ASTStmtReader::VisitObjCEncodeExpr(ObjCEncodeExpr *E) {
VisitExpr(E);
- E->setEncodedTypeSourceInfo(GetTypeSourceInfo(Record, Idx));
- E->setAtLoc(ReadSourceLocation(Record, Idx));
- E->setRParenLoc(ReadSourceLocation(Record, Idx));
+ E->setEncodedTypeSourceInfo(GetTypeSourceInfo());
+ E->setAtLoc(ReadSourceLocation());
+ E->setRParenLoc(ReadSourceLocation());
}
void ASTStmtReader::VisitObjCSelectorExpr(ObjCSelectorExpr *E) {
VisitExpr(E);
- E->setSelector(Reader.ReadSelector(F, Record, Idx));
- E->setAtLoc(ReadSourceLocation(Record, Idx));
- E->setRParenLoc(ReadSourceLocation(Record, Idx));
+ E->setSelector(Record.readSelector());
+ E->setAtLoc(ReadSourceLocation());
+ E->setRParenLoc(ReadSourceLocation());
}
void ASTStmtReader::VisitObjCProtocolExpr(ObjCProtocolExpr *E) {
VisitExpr(E);
- E->setProtocol(ReadDeclAs<ObjCProtocolDecl>(Record, Idx));
- E->setAtLoc(ReadSourceLocation(Record, Idx));
- E->ProtoLoc = ReadSourceLocation(Record, Idx);
- E->setRParenLoc(ReadSourceLocation(Record, Idx));
+ E->setProtocol(ReadDeclAs<ObjCProtocolDecl>());
+ E->setAtLoc(ReadSourceLocation());
+ E->ProtoLoc = ReadSourceLocation();
+ E->setRParenLoc(ReadSourceLocation());
}
void ASTStmtReader::VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
VisitExpr(E);
- E->setDecl(ReadDeclAs<ObjCIvarDecl>(Record, Idx));
- E->setLocation(ReadSourceLocation(Record, Idx));
- E->setOpLoc(ReadSourceLocation(Record, Idx));
- E->setBase(Reader.ReadSubExpr());
- E->setIsArrow(Record[Idx++]);
- E->setIsFreeIvar(Record[Idx++]);
+ E->setDecl(ReadDeclAs<ObjCIvarDecl>());
+ E->setLocation(ReadSourceLocation());
+ E->setOpLoc(ReadSourceLocation());
+ E->setBase(Record.readSubExpr());
+ E->setIsArrow(Record.readInt());
+ E->setIsFreeIvar(Record.readInt());
}
void ASTStmtReader::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
VisitExpr(E);
- unsigned MethodRefFlags = Record[Idx++];
- bool Implicit = Record[Idx++] != 0;
+ unsigned MethodRefFlags = Record.readInt();
+ bool Implicit = Record.readInt() != 0;
if (Implicit) {
- ObjCMethodDecl *Getter = ReadDeclAs<ObjCMethodDecl>(Record, Idx);
- ObjCMethodDecl *Setter = ReadDeclAs<ObjCMethodDecl>(Record, Idx);
+ ObjCMethodDecl *Getter = ReadDeclAs<ObjCMethodDecl>();
+ ObjCMethodDecl *Setter = ReadDeclAs<ObjCMethodDecl>();
E->setImplicitProperty(Getter, Setter, MethodRefFlags);
} else {
- E->setExplicitProperty(ReadDeclAs<ObjCPropertyDecl>(Record, Idx),
- MethodRefFlags);
+ E->setExplicitProperty(ReadDeclAs<ObjCPropertyDecl>(), MethodRefFlags);
}
- E->setLocation(ReadSourceLocation(Record, Idx));
- E->setReceiverLocation(ReadSourceLocation(Record, Idx));
- switch (Record[Idx++]) {
+ E->setLocation(ReadSourceLocation());
+ E->setReceiverLocation(ReadSourceLocation());
+ switch (Record.readInt()) {
case 0:
- E->setBase(Reader.ReadSubExpr());
+ E->setBase(Record.readSubExpr());
break;
case 1:
- E->setSuperReceiver(Reader.readType(F, Record, Idx));
+ E->setSuperReceiver(Record.readType());
break;
case 2:
- E->setClassReceiver(ReadDeclAs<ObjCInterfaceDecl>(Record, Idx));
+ E->setClassReceiver(ReadDeclAs<ObjCInterfaceDecl>());
break;
}
}
void ASTStmtReader::VisitObjCSubscriptRefExpr(ObjCSubscriptRefExpr *E) {
VisitExpr(E);
- E->setRBracket(ReadSourceLocation(Record, Idx));
- E->setBaseExpr(Reader.ReadSubExpr());
- E->setKeyExpr(Reader.ReadSubExpr());
- E->GetAtIndexMethodDecl = ReadDeclAs<ObjCMethodDecl>(Record, Idx);
- E->SetAtIndexMethodDecl = ReadDeclAs<ObjCMethodDecl>(Record, Idx);
+ E->setRBracket(ReadSourceLocation());
+ E->setBaseExpr(Record.readSubExpr());
+ E->setKeyExpr(Record.readSubExpr());
+ E->GetAtIndexMethodDecl = ReadDeclAs<ObjCMethodDecl>();
+ E->SetAtIndexMethodDecl = ReadDeclAs<ObjCMethodDecl>();
}
void ASTStmtReader::VisitObjCMessageExpr(ObjCMessageExpr *E) {
VisitExpr(E);
- assert(Record[Idx] == E->getNumArgs());
- ++Idx;
- unsigned NumStoredSelLocs = Record[Idx++];
- E->SelLocsKind = Record[Idx++];
- E->setDelegateInitCall(Record[Idx++]);
- E->IsImplicit = Record[Idx++];
+ assert(Record.peekInt() == E->getNumArgs());
+ Record.skipInts(1);
+ unsigned NumStoredSelLocs = Record.readInt();
+ E->SelLocsKind = Record.readInt();
+ E->setDelegateInitCall(Record.readInt());
+ E->IsImplicit = Record.readInt();
ObjCMessageExpr::ReceiverKind Kind
- = static_cast<ObjCMessageExpr::ReceiverKind>(Record[Idx++]);
+ = static_cast<ObjCMessageExpr::ReceiverKind>(Record.readInt());
switch (Kind) {
case ObjCMessageExpr::Instance:
- E->setInstanceReceiver(Reader.ReadSubExpr());
+ E->setInstanceReceiver(Record.readSubExpr());
break;
case ObjCMessageExpr::Class:
- E->setClassReceiver(GetTypeSourceInfo(Record, Idx));
+ E->setClassReceiver(GetTypeSourceInfo());
break;
case ObjCMessageExpr::SuperClass:
case ObjCMessageExpr::SuperInstance: {
- QualType T = Reader.readType(F, Record, Idx);
- SourceLocation SuperLoc = ReadSourceLocation(Record, Idx);
+ QualType T = Record.readType();
+ SourceLocation SuperLoc = ReadSourceLocation();
E->setSuper(SuperLoc, T, Kind == ObjCMessageExpr::SuperInstance);
break;
}
@@ -1104,90 +1085,90 @@ void ASTStmtReader::VisitObjCMessageExpr(ObjCMessageExpr *E) {
assert(Kind == E->getReceiverKind());
- if (Record[Idx++])
- E->setMethodDecl(ReadDeclAs<ObjCMethodDecl>(Record, Idx));
+ if (Record.readInt())
+ E->setMethodDecl(ReadDeclAs<ObjCMethodDecl>());
else
- E->setSelector(Reader.ReadSelector(F, Record, Idx));
+ E->setSelector(Record.readSelector());
- E->LBracLoc = ReadSourceLocation(Record, Idx);
- E->RBracLoc = ReadSourceLocation(Record, Idx);
+ E->LBracLoc = ReadSourceLocation();
+ E->RBracLoc = ReadSourceLocation();
for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I)
- E->setArg(I, Reader.ReadSubExpr());
+ E->setArg(I, Record.readSubExpr());
SourceLocation *Locs = E->getStoredSelLocs();
for (unsigned I = 0; I != NumStoredSelLocs; ++I)
- Locs[I] = ReadSourceLocation(Record, Idx);
+ Locs[I] = ReadSourceLocation();
}
void ASTStmtReader::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) {
VisitStmt(S);
- S->setElement(Reader.ReadSubStmt());
- S->setCollection(Reader.ReadSubExpr());
- S->setBody(Reader.ReadSubStmt());
- S->setForLoc(ReadSourceLocation(Record, Idx));
- S->setRParenLoc(ReadSourceLocation(Record, Idx));
+ S->setElement(Record.readSubStmt());
+ S->setCollection(Record.readSubExpr());
+ S->setBody(Record.readSubStmt());
+ S->setForLoc(ReadSourceLocation());
+ S->setRParenLoc(ReadSourceLocation());
}
void ASTStmtReader::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) {
VisitStmt(S);
- S->setCatchBody(Reader.ReadSubStmt());
- S->setCatchParamDecl(ReadDeclAs<VarDecl>(Record, Idx));
- S->setAtCatchLoc(ReadSourceLocation(Record, Idx));
- S->setRParenLoc(ReadSourceLocation(Record, Idx));
+ S->setCatchBody(Record.readSubStmt());
+ S->setCatchParamDecl(ReadDeclAs<VarDecl>());
+ S->setAtCatchLoc(ReadSourceLocation());
+ S->setRParenLoc(ReadSourceLocation());
}
void ASTStmtReader::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S) {
VisitStmt(S);
- S->setFinallyBody(Reader.ReadSubStmt());
- S->setAtFinallyLoc(ReadSourceLocation(Record, Idx));
+ S->setFinallyBody(Record.readSubStmt());
+ S->setAtFinallyLoc(ReadSourceLocation());
}
void ASTStmtReader::VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S) {
VisitStmt(S);
- S->setSubStmt(Reader.ReadSubStmt());
- S->setAtLoc(ReadSourceLocation(Record, Idx));
+ S->setSubStmt(Record.readSubStmt());
+ S->setAtLoc(ReadSourceLocation());
}
void ASTStmtReader::VisitObjCAtTryStmt(ObjCAtTryStmt *S) {
VisitStmt(S);
- assert(Record[Idx] == S->getNumCatchStmts());
- ++Idx;
- bool HasFinally = Record[Idx++];
- S->setTryBody(Reader.ReadSubStmt());
+ assert(Record.peekInt() == S->getNumCatchStmts());
+ Record.skipInts(1);
+ bool HasFinally = Record.readInt();
+ S->setTryBody(Record.readSubStmt());
for (unsigned I = 0, N = S->getNumCatchStmts(); I != N; ++I)
- S->setCatchStmt(I, cast_or_null<ObjCAtCatchStmt>(Reader.ReadSubStmt()));
+ S->setCatchStmt(I, cast_or_null<ObjCAtCatchStmt>(Record.readSubStmt()));
if (HasFinally)
- S->setFinallyStmt(Reader.ReadSubStmt());
- S->setAtTryLoc(ReadSourceLocation(Record, Idx));
+ S->setFinallyStmt(Record.readSubStmt());
+ S->setAtTryLoc(ReadSourceLocation());
}
void ASTStmtReader::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S) {
VisitStmt(S);
- S->setSynchExpr(Reader.ReadSubStmt());
- S->setSynchBody(Reader.ReadSubStmt());
- S->setAtSynchronizedLoc(ReadSourceLocation(Record, Idx));
+ S->setSynchExpr(Record.readSubStmt());
+ S->setSynchBody(Record.readSubStmt());
+ S->setAtSynchronizedLoc(ReadSourceLocation());
}
void ASTStmtReader::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) {
VisitStmt(S);
- S->setThrowExpr(Reader.ReadSubStmt());
- S->setThrowLoc(ReadSourceLocation(Record, Idx));
+ S->setThrowExpr(Record.readSubStmt());
+ S->setThrowLoc(ReadSourceLocation());
}
void ASTStmtReader::VisitObjCBoolLiteralExpr(ObjCBoolLiteralExpr *E) {
VisitExpr(E);
- E->setValue(Record[Idx++]);
- E->setLocation(ReadSourceLocation(Record, Idx));
+ E->setValue(Record.readInt());
+ E->setLocation(ReadSourceLocation());
}
void ASTStmtReader::VisitObjCAvailabilityCheckExpr(ObjCAvailabilityCheckExpr *E) {
VisitExpr(E);
- SourceRange R = Reader.ReadSourceRange(F, Record, Idx);
+ SourceRange R = Record.readSourceRange();
E->AtLoc = R.getBegin();
E->RParen = R.getEnd();
- E->VersionToCheck = Reader.ReadVersionTuple(Record, Idx);
+ E->VersionToCheck = Record.readVersionTuple();
}
//===----------------------------------------------------------------------===//
@@ -1196,125 +1177,113 @@ void ASTStmtReader::VisitObjCAvailabilityCheckExpr(ObjCAvailabilityCheckExpr *E)
void ASTStmtReader::VisitCXXCatchStmt(CXXCatchStmt *S) {
VisitStmt(S);
- S->CatchLoc = ReadSourceLocation(Record, Idx);
- S->ExceptionDecl = ReadDeclAs<VarDecl>(Record, Idx);
- S->HandlerBlock = Reader.ReadSubStmt();
+ S->CatchLoc = ReadSourceLocation();
+ S->ExceptionDecl = ReadDeclAs<VarDecl>();
+ S->HandlerBlock = Record.readSubStmt();
}
void ASTStmtReader::VisitCXXTryStmt(CXXTryStmt *S) {
VisitStmt(S);
- assert(Record[Idx] == S->getNumHandlers() && "NumStmtFields is wrong ?");
- ++Idx;
- S->TryLoc = ReadSourceLocation(Record, Idx);
- S->getStmts()[0] = Reader.ReadSubStmt();
+ assert(Record.peekInt() == S->getNumHandlers() && "NumStmtFields is wrong ?");
+ Record.skipInts(1);
+ S->TryLoc = ReadSourceLocation();
+ S->getStmts()[0] = Record.readSubStmt();
for (unsigned i = 0, e = S->getNumHandlers(); i != e; ++i)
- S->getStmts()[i + 1] = Reader.ReadSubStmt();
+ S->getStmts()[i + 1] = Record.readSubStmt();
}
void ASTStmtReader::VisitCXXForRangeStmt(CXXForRangeStmt *S) {
VisitStmt(S);
- S->ForLoc = ReadSourceLocation(Record, Idx);
- S->CoawaitLoc = ReadSourceLocation(Record, Idx);
- S->ColonLoc = ReadSourceLocation(Record, Idx);
- S->RParenLoc = ReadSourceLocation(Record, Idx);
- S->setRangeStmt(Reader.ReadSubStmt());
- S->setBeginStmt(Reader.ReadSubStmt());
- S->setEndStmt(Reader.ReadSubStmt());
- S->setCond(Reader.ReadSubExpr());
- S->setInc(Reader.ReadSubExpr());
- S->setLoopVarStmt(Reader.ReadSubStmt());
- S->setBody(Reader.ReadSubStmt());
+ S->ForLoc = ReadSourceLocation();
+ S->CoawaitLoc = ReadSourceLocation();
+ S->ColonLoc = ReadSourceLocation();
+ S->RParenLoc = ReadSourceLocation();
+ S->setRangeStmt(Record.readSubStmt());
+ S->setBeginStmt(Record.readSubStmt());
+ S->setEndStmt(Record.readSubStmt());
+ S->setCond(Record.readSubExpr());
+ S->setInc(Record.readSubExpr());
+ S->setLoopVarStmt(Record.readSubStmt());
+ S->setBody(Record.readSubStmt());
}
void ASTStmtReader::VisitMSDependentExistsStmt(MSDependentExistsStmt *S) {
VisitStmt(S);
- S->KeywordLoc = ReadSourceLocation(Record, Idx);
- S->IsIfExists = Record[Idx++];
- S->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx);
- ReadDeclarationNameInfo(S->NameInfo, Record, Idx);
- S->SubStmt = Reader.ReadSubStmt();
+ S->KeywordLoc = ReadSourceLocation();
+ S->IsIfExists = Record.readInt();
+ S->QualifierLoc = Record.readNestedNameSpecifierLoc();
+ ReadDeclarationNameInfo(S->NameInfo);
+ S->SubStmt = Record.readSubStmt();
}
void ASTStmtReader::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
VisitCallExpr(E);
- E->Operator = (OverloadedOperatorKind)Record[Idx++];
- E->Range = Reader.ReadSourceRange(F, Record, Idx);
- E->setFPContractable((bool)Record[Idx++]);
+ E->Operator = (OverloadedOperatorKind)Record.readInt();
+ E->Range = Record.readSourceRange();
+ E->setFPContractable((bool)Record.readInt());
}
void ASTStmtReader::VisitCXXConstructExpr(CXXConstructExpr *E) {
VisitExpr(E);
- E->NumArgs = Record[Idx++];
+ E->NumArgs = Record.readInt();
if (E->NumArgs)
- E->Args = new (Reader.getContext()) Stmt*[E->NumArgs];
+ E->Args = new (Record.getContext()) Stmt*[E->NumArgs];
for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I)
- E->setArg(I, Reader.ReadSubExpr());
- E->setConstructor(ReadDeclAs<CXXConstructorDecl>(Record, Idx));
- E->setLocation(ReadSourceLocation(Record, Idx));
- E->setElidable(Record[Idx++]);
- E->setHadMultipleCandidates(Record[Idx++]);
- E->setListInitialization(Record[Idx++]);
- E->setStdInitListInitialization(Record[Idx++]);
- E->setRequiresZeroInitialization(Record[Idx++]);
- E->setConstructionKind((CXXConstructExpr::ConstructionKind)Record[Idx++]);
- E->ParenOrBraceRange = ReadSourceRange(Record, Idx);
+ E->setArg(I, Record.readSubExpr());
+ E->setConstructor(ReadDeclAs<CXXConstructorDecl>());
+ E->setLocation(ReadSourceLocation());
+ E->setElidable(Record.readInt());
+ E->setHadMultipleCandidates(Record.readInt());
+ E->setListInitialization(Record.readInt());
+ E->setStdInitListInitialization(Record.readInt());
+ E->setRequiresZeroInitialization(Record.readInt());
+ E->setConstructionKind((CXXConstructExpr::ConstructionKind)Record.readInt());
+ E->ParenOrBraceRange = ReadSourceRange();
}
void ASTStmtReader::VisitCXXInheritedCtorInitExpr(CXXInheritedCtorInitExpr *E) {
VisitExpr(E);
- E->Constructor = ReadDeclAs<CXXConstructorDecl>(Record, Idx);
- E->Loc = ReadSourceLocation(Record, Idx);
- E->ConstructsVirtualBase = Record[Idx++];
- E->InheritedFromVirtualBase = Record[Idx++];
+ E->Constructor = ReadDeclAs<CXXConstructorDecl>();
+ E->Loc = ReadSourceLocation();
+ E->ConstructsVirtualBase = Record.readInt();
+ E->InheritedFromVirtualBase = Record.readInt();
}
void ASTStmtReader::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E) {
VisitCXXConstructExpr(E);
- E->Type = GetTypeSourceInfo(Record, Idx);
+ E->Type = GetTypeSourceInfo();
}
void ASTStmtReader::VisitLambdaExpr(LambdaExpr *E) {
VisitExpr(E);
- unsigned NumCaptures = Record[Idx++];
+ unsigned NumCaptures = Record.readInt();
assert(NumCaptures == E->NumCaptures);(void)NumCaptures;
- unsigned NumArrayIndexVars = Record[Idx++];
- E->IntroducerRange = ReadSourceRange(Record, Idx);
- E->CaptureDefault = static_cast<LambdaCaptureDefault>(Record[Idx++]);
- E->CaptureDefaultLoc = ReadSourceLocation(Record, Idx);
- E->ExplicitParams = Record[Idx++];
- E->ExplicitResultType = Record[Idx++];
- E->ClosingBrace = ReadSourceLocation(Record, Idx);
-
+ E->IntroducerRange = ReadSourceRange();
+ E->CaptureDefault = static_cast<LambdaCaptureDefault>(Record.readInt());
+ E->CaptureDefaultLoc = ReadSourceLocation();
+ E->ExplicitParams = Record.readInt();
+ E->ExplicitResultType = Record.readInt();
+ E->ClosingBrace = ReadSourceLocation();
+
// Read capture initializers.
for (LambdaExpr::capture_init_iterator C = E->capture_init_begin(),
CEnd = E->capture_init_end();
C != CEnd; ++C)
- *C = Reader.ReadSubExpr();
-
- // Read array capture index variables.
- if (NumArrayIndexVars > 0) {
- unsigned *ArrayIndexStarts = E->getArrayIndexStarts();
- for (unsigned I = 0; I != NumCaptures + 1; ++I)
- ArrayIndexStarts[I] = Record[Idx++];
-
- VarDecl **ArrayIndexVars = E->getArrayIndexVars();
- for (unsigned I = 0; I != NumArrayIndexVars; ++I)
- ArrayIndexVars[I] = ReadDeclAs<VarDecl>(Record, Idx);
- }
+ *C = Record.readSubExpr();
}
void
ASTStmtReader::VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E) {
VisitExpr(E);
- E->SubExpr = Reader.ReadSubExpr();
+ E->SubExpr = Record.readSubExpr();
}
void ASTStmtReader::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) {
VisitExplicitCastExpr(E);
- SourceRange R = ReadSourceRange(Record, Idx);
+ SourceRange R = ReadSourceRange();
E->Loc = R.getBegin();
E->RParenLoc = R.getEnd();
- R = ReadSourceRange(Record, Idx);
+ R = ReadSourceRange();
E->AngleBrackets = R;
}
@@ -1336,342 +1305,345 @@ void ASTStmtReader::VisitCXXConstCastExpr(CXXConstCastExpr *E) {
void ASTStmtReader::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E) {
VisitExplicitCastExpr(E);
- E->setLParenLoc(ReadSourceLocation(Record, Idx));
- E->setRParenLoc(ReadSourceLocation(Record, Idx));
+ E->setLParenLoc(ReadSourceLocation());
+ E->setRParenLoc(ReadSourceLocation());
}
void ASTStmtReader::VisitUserDefinedLiteral(UserDefinedLiteral *E) {
VisitCallExpr(E);
- E->UDSuffixLoc = ReadSourceLocation(Record, Idx);
+ E->UDSuffixLoc = ReadSourceLocation();
}
void ASTStmtReader::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) {
VisitExpr(E);
- E->setValue(Record[Idx++]);
- E->setLocation(ReadSourceLocation(Record, Idx));
+ E->setValue(Record.readInt());
+ E->setLocation(ReadSourceLocation());
}
void ASTStmtReader::VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E) {
VisitExpr(E);
- E->setLocation(ReadSourceLocation(Record, Idx));
+ E->setLocation(ReadSourceLocation());
}
void ASTStmtReader::VisitCXXTypeidExpr(CXXTypeidExpr *E) {
VisitExpr(E);
- E->setSourceRange(ReadSourceRange(Record, Idx));
+ E->setSourceRange(ReadSourceRange());
if (E->isTypeOperand()) { // typeid(int)
E->setTypeOperandSourceInfo(
- GetTypeSourceInfo(Record, Idx));
+ GetTypeSourceInfo());
return;
}
-
+
// typeid(42+2)
- E->setExprOperand(Reader.ReadSubExpr());
+ E->setExprOperand(Record.readSubExpr());
}
void ASTStmtReader::VisitCXXThisExpr(CXXThisExpr *E) {
VisitExpr(E);
- E->setLocation(ReadSourceLocation(Record, Idx));
- E->setImplicit(Record[Idx++]);
+ E->setLocation(ReadSourceLocation());
+ E->setImplicit(Record.readInt());
}
void ASTStmtReader::VisitCXXThrowExpr(CXXThrowExpr *E) {
VisitExpr(E);
- E->ThrowLoc = ReadSourceLocation(Record, Idx);
- E->Op = Reader.ReadSubExpr();
- E->IsThrownVariableInScope = Record[Idx++];
+ E->ThrowLoc = ReadSourceLocation();
+ E->Op = Record.readSubExpr();
+ E->IsThrownVariableInScope = Record.readInt();
}
void ASTStmtReader::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
VisitExpr(E);
- E->Param = ReadDeclAs<ParmVarDecl>(Record, Idx);
- E->Loc = ReadSourceLocation(Record, Idx);
+ E->Param = ReadDeclAs<ParmVarDecl>();
+ E->Loc = ReadSourceLocation();
}
void ASTStmtReader::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E) {
VisitExpr(E);
- E->Field = ReadDeclAs<FieldDecl>(Record, Idx);
- E->Loc = ReadSourceLocation(Record, Idx);
+ E->Field = ReadDeclAs<FieldDecl>();
+ E->Loc = ReadSourceLocation();
}
void ASTStmtReader::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
VisitExpr(E);
- E->setTemporary(Reader.ReadCXXTemporary(F, Record, Idx));
- E->setSubExpr(Reader.ReadSubExpr());
+ E->setTemporary(Record.readCXXTemporary());
+ E->setSubExpr(Record.readSubExpr());
}
void ASTStmtReader::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) {
VisitExpr(E);
- E->TypeInfo = GetTypeSourceInfo(Record, Idx);
- E->RParenLoc = ReadSourceLocation(Record, Idx);
+ E->TypeInfo = GetTypeSourceInfo();
+ E->RParenLoc = ReadSourceLocation();
}
void ASTStmtReader::VisitCXXNewExpr(CXXNewExpr *E) {
VisitExpr(E);
- E->GlobalNew = Record[Idx++];
- bool isArray = Record[Idx++];
- E->UsualArrayDeleteWantsSize = Record[Idx++];
- unsigned NumPlacementArgs = Record[Idx++];
- E->StoredInitializationStyle = Record[Idx++];
- E->setOperatorNew(ReadDeclAs<FunctionDecl>(Record, Idx));
- E->setOperatorDelete(ReadDeclAs<FunctionDecl>(Record, Idx));
- E->AllocatedTypeInfo = GetTypeSourceInfo(Record, Idx);
- E->TypeIdParens = ReadSourceRange(Record, Idx);
- E->Range = ReadSourceRange(Record, Idx);
- E->DirectInitRange = ReadSourceRange(Record, Idx);
-
- E->AllocateArgsArray(Reader.getContext(), isArray, NumPlacementArgs,
+ E->GlobalNew = Record.readInt();
+ bool isArray = Record.readInt();
+ E->PassAlignment = Record.readInt();
+ E->UsualArrayDeleteWantsSize = Record.readInt();
+ unsigned NumPlacementArgs = Record.readInt();
+ E->StoredInitializationStyle = Record.readInt();
+ E->setOperatorNew(ReadDeclAs<FunctionDecl>());
+ E->setOperatorDelete(ReadDeclAs<FunctionDecl>());
+ E->AllocatedTypeInfo = GetTypeSourceInfo();
+ E->TypeIdParens = ReadSourceRange();
+ E->Range = ReadSourceRange();
+ E->DirectInitRange = ReadSourceRange();
+
+ E->AllocateArgsArray(Record.getContext(), isArray, NumPlacementArgs,
E->StoredInitializationStyle != 0);
// Install all the subexpressions.
for (CXXNewExpr::raw_arg_iterator I = E->raw_arg_begin(),e = E->raw_arg_end();
I != e; ++I)
- *I = Reader.ReadSubStmt();
+ *I = Record.readSubStmt();
}
void ASTStmtReader::VisitCXXDeleteExpr(CXXDeleteExpr *E) {
VisitExpr(E);
- E->GlobalDelete = Record[Idx++];
- E->ArrayForm = Record[Idx++];
- E->ArrayFormAsWritten = Record[Idx++];
- E->UsualArrayDeleteWantsSize = Record[Idx++];
- E->OperatorDelete = ReadDeclAs<FunctionDecl>(Record, Idx);
- E->Argument = Reader.ReadSubExpr();
- E->Loc = ReadSourceLocation(Record, Idx);
+ E->GlobalDelete = Record.readInt();
+ E->ArrayForm = Record.readInt();
+ E->ArrayFormAsWritten = Record.readInt();
+ E->UsualArrayDeleteWantsSize = Record.readInt();
+ E->OperatorDelete = ReadDeclAs<FunctionDecl>();
+ E->Argument = Record.readSubExpr();
+ E->Loc = ReadSourceLocation();
}
void ASTStmtReader::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) {
VisitExpr(E);
- E->Base = Reader.ReadSubExpr();
- E->IsArrow = Record[Idx++];
- E->OperatorLoc = ReadSourceLocation(Record, Idx);
- E->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx);
- E->ScopeType = GetTypeSourceInfo(Record, Idx);
- E->ColonColonLoc = ReadSourceLocation(Record, Idx);
- E->TildeLoc = ReadSourceLocation(Record, Idx);
-
- IdentifierInfo *II = Reader.GetIdentifierInfo(F, Record, Idx);
+ E->Base = Record.readSubExpr();
+ E->IsArrow = Record.readInt();
+ E->OperatorLoc = ReadSourceLocation();
+ E->QualifierLoc = Record.readNestedNameSpecifierLoc();
+ E->ScopeType = GetTypeSourceInfo();
+ E->ColonColonLoc = ReadSourceLocation();
+ E->TildeLoc = ReadSourceLocation();
+
+ IdentifierInfo *II = Record.getIdentifierInfo();
if (II)
- E->setDestroyedType(II, ReadSourceLocation(Record, Idx));
+ E->setDestroyedType(II, ReadSourceLocation());
else
- E->setDestroyedType(GetTypeSourceInfo(Record, Idx));
+ E->setDestroyedType(GetTypeSourceInfo());
}
void ASTStmtReader::VisitExprWithCleanups(ExprWithCleanups *E) {
VisitExpr(E);
- unsigned NumObjects = Record[Idx++];
+ unsigned NumObjects = Record.readInt();
assert(NumObjects == E->getNumObjects());
for (unsigned i = 0; i != NumObjects; ++i)
E->getTrailingObjects<BlockDecl *>()[i] =
- ReadDeclAs<BlockDecl>(Record, Idx);
+ ReadDeclAs<BlockDecl>();
- E->ExprWithCleanupsBits.CleanupsHaveSideEffects = Record[Idx++];
- E->SubExpr = Reader.ReadSubExpr();
+ E->ExprWithCleanupsBits.CleanupsHaveSideEffects = Record.readInt();
+ E->SubExpr = Record.readSubExpr();
}
void
ASTStmtReader::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E){
VisitExpr(E);
- if (Record[Idx++]) // HasTemplateKWAndArgsInfo
+ if (Record.readInt()) // HasTemplateKWAndArgsInfo
ReadTemplateKWAndArgsInfo(
*E->getTrailingObjects<ASTTemplateKWAndArgsInfo>(),
E->getTrailingObjects<TemplateArgumentLoc>(),
- /*NumTemplateArgs=*/Record[Idx++]);
+ /*NumTemplateArgs=*/Record.readInt());
- E->Base = Reader.ReadSubExpr();
- E->BaseType = Reader.readType(F, Record, Idx);
- E->IsArrow = Record[Idx++];
- E->OperatorLoc = ReadSourceLocation(Record, Idx);
- E->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx);
- E->FirstQualifierFoundInScope = ReadDeclAs<NamedDecl>(Record, Idx);
- ReadDeclarationNameInfo(E->MemberNameInfo, Record, Idx);
+ E->Base = Record.readSubExpr();
+ E->BaseType = Record.readType();
+ E->IsArrow = Record.readInt();
+ E->OperatorLoc = ReadSourceLocation();
+ E->QualifierLoc = Record.readNestedNameSpecifierLoc();
+ E->FirstQualifierFoundInScope = ReadDeclAs<NamedDecl>();
+ ReadDeclarationNameInfo(E->MemberNameInfo);
}
void
ASTStmtReader::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
VisitExpr(E);
- if (Record[Idx++]) // HasTemplateKWAndArgsInfo
+ if (Record.readInt()) // HasTemplateKWAndArgsInfo
ReadTemplateKWAndArgsInfo(
*E->getTrailingObjects<ASTTemplateKWAndArgsInfo>(),
E->getTrailingObjects<TemplateArgumentLoc>(),
- /*NumTemplateArgs=*/Record[Idx++]);
+ /*NumTemplateArgs=*/Record.readInt());
- E->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx);
- ReadDeclarationNameInfo(E->NameInfo, Record, Idx);
+ E->QualifierLoc = Record.readNestedNameSpecifierLoc();
+ ReadDeclarationNameInfo(E->NameInfo);
}
void
ASTStmtReader::VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E) {
VisitExpr(E);
- assert(Record[Idx] == E->arg_size() && "Read wrong record during creation ?");
- ++Idx; // NumArgs;
+ assert(Record.peekInt() == E->arg_size() &&
+ "Read wrong record during creation ?");
+ Record.skipInts(1);
for (unsigned I = 0, N = E->arg_size(); I != N; ++I)
- E->setArg(I, Reader.ReadSubExpr());
- E->Type = GetTypeSourceInfo(Record, Idx);
- E->setLParenLoc(ReadSourceLocation(Record, Idx));
- E->setRParenLoc(ReadSourceLocation(Record, Idx));
+ E->setArg(I, Record.readSubExpr());
+ E->Type = GetTypeSourceInfo();
+ E->setLParenLoc(ReadSourceLocation());
+ E->setRParenLoc(ReadSourceLocation());
}
void ASTStmtReader::VisitOverloadExpr(OverloadExpr *E) {
VisitExpr(E);
- if (Record[Idx++]) // HasTemplateKWAndArgsInfo
+ if (Record.readInt()) // HasTemplateKWAndArgsInfo
ReadTemplateKWAndArgsInfo(*E->getTrailingASTTemplateKWAndArgsInfo(),
E->getTrailingTemplateArgumentLoc(),
- /*NumTemplateArgs=*/Record[Idx++]);
+ /*NumTemplateArgs=*/Record.readInt());
- unsigned NumDecls = Record[Idx++];
+ unsigned NumDecls = Record.readInt();
UnresolvedSet<8> Decls;
for (unsigned i = 0; i != NumDecls; ++i) {
- NamedDecl *D = ReadDeclAs<NamedDecl>(Record, Idx);
- AccessSpecifier AS = (AccessSpecifier)Record[Idx++];
+ NamedDecl *D = ReadDeclAs<NamedDecl>();
+ AccessSpecifier AS = (AccessSpecifier)Record.readInt();
Decls.addDecl(D, AS);
}
- E->initializeResults(Reader.getContext(), Decls.begin(), Decls.end());
+ E->initializeResults(Record.getContext(), Decls.begin(), Decls.end());
- ReadDeclarationNameInfo(E->NameInfo, Record, Idx);
- E->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx);
+ ReadDeclarationNameInfo(E->NameInfo);
+ E->QualifierLoc = Record.readNestedNameSpecifierLoc();
}
void ASTStmtReader::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) {
VisitOverloadExpr(E);
- E->IsArrow = Record[Idx++];
- E->HasUnresolvedUsing = Record[Idx++];
- E->Base = Reader.ReadSubExpr();
- E->BaseType = Reader.readType(F, Record, Idx);
- E->OperatorLoc = ReadSourceLocation(Record, Idx);
+ E->IsArrow = Record.readInt();
+ E->HasUnresolvedUsing = Record.readInt();
+ E->Base = Record.readSubExpr();
+ E->BaseType = Record.readType();
+ E->OperatorLoc = ReadSourceLocation();
}
void ASTStmtReader::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) {
VisitOverloadExpr(E);
- E->RequiresADL = Record[Idx++];
- E->Overloaded = Record[Idx++];
- E->NamingClass = ReadDeclAs<CXXRecordDecl>(Record, Idx);
+ E->RequiresADL = Record.readInt();
+ E->Overloaded = Record.readInt();
+ E->NamingClass = ReadDeclAs<CXXRecordDecl>();
}
void ASTStmtReader::VisitTypeTraitExpr(TypeTraitExpr *E) {
VisitExpr(E);
- E->TypeTraitExprBits.NumArgs = Record[Idx++];
- E->TypeTraitExprBits.Kind = Record[Idx++];
- E->TypeTraitExprBits.Value = Record[Idx++];
- SourceRange Range = ReadSourceRange(Record, Idx);
+ E->TypeTraitExprBits.NumArgs = Record.readInt();
+ E->TypeTraitExprBits.Kind = Record.readInt();
+ E->TypeTraitExprBits.Value = Record.readInt();
+ SourceRange Range = ReadSourceRange();
E->Loc = Range.getBegin();
E->RParenLoc = Range.getEnd();
TypeSourceInfo **Args = E->getTrailingObjects<TypeSourceInfo *>();
for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I)
- Args[I] = GetTypeSourceInfo(Record, Idx);
+ Args[I] = GetTypeSourceInfo();
}
void ASTStmtReader::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) {
VisitExpr(E);
- E->ATT = (ArrayTypeTrait)Record[Idx++];
- E->Value = (unsigned int)Record[Idx++];
- SourceRange Range = ReadSourceRange(Record, Idx);
+ E->ATT = (ArrayTypeTrait)Record.readInt();
+ E->Value = (unsigned int)Record.readInt();
+ SourceRange Range = ReadSourceRange();
E->Loc = Range.getBegin();
E->RParen = Range.getEnd();
- E->QueriedType = GetTypeSourceInfo(Record, Idx);
+ E->QueriedType = GetTypeSourceInfo();
+ E->Dimension = Record.readSubExpr();
}
void ASTStmtReader::VisitExpressionTraitExpr(ExpressionTraitExpr *E) {
VisitExpr(E);
- E->ET = (ExpressionTrait)Record[Idx++];
- E->Value = (bool)Record[Idx++];
- SourceRange Range = ReadSourceRange(Record, Idx);
- E->QueriedExpression = Reader.ReadSubExpr();
+ E->ET = (ExpressionTrait)Record.readInt();
+ E->Value = (bool)Record.readInt();
+ SourceRange Range = ReadSourceRange();
+ E->QueriedExpression = Record.readSubExpr();
E->Loc = Range.getBegin();
E->RParen = Range.getEnd();
}
void ASTStmtReader::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) {
VisitExpr(E);
- E->Value = (bool)Record[Idx++];
- E->Range = ReadSourceRange(Record, Idx);
- E->Operand = Reader.ReadSubExpr();
+ E->Value = (bool)Record.readInt();
+ E->Range = ReadSourceRange();
+ E->Operand = Record.readSubExpr();
}
void ASTStmtReader::VisitPackExpansionExpr(PackExpansionExpr *E) {
VisitExpr(E);
- E->EllipsisLoc = ReadSourceLocation(Record, Idx);
- E->NumExpansions = Record[Idx++];
- E->Pattern = Reader.ReadSubExpr();
+ E->EllipsisLoc = ReadSourceLocation();
+ E->NumExpansions = Record.readInt();
+ E->Pattern = Record.readSubExpr();
}
void ASTStmtReader::VisitSizeOfPackExpr(SizeOfPackExpr *E) {
VisitExpr(E);
- unsigned NumPartialArgs = Record[Idx++];
- E->OperatorLoc = ReadSourceLocation(Record, Idx);
- E->PackLoc = ReadSourceLocation(Record, Idx);
- E->RParenLoc = ReadSourceLocation(Record, Idx);
- E->Pack = Reader.ReadDeclAs<NamedDecl>(F, Record, Idx);
+ unsigned NumPartialArgs = Record.readInt();
+ E->OperatorLoc = ReadSourceLocation();
+ E->PackLoc = ReadSourceLocation();
+ E->RParenLoc = ReadSourceLocation();
+ E->Pack = Record.readDeclAs<NamedDecl>();
if (E->isPartiallySubstituted()) {
assert(E->Length == NumPartialArgs);
for (auto *I = E->getTrailingObjects<TemplateArgument>(),
*E = I + NumPartialArgs;
I != E; ++I)
- new (I) TemplateArgument(Reader.ReadTemplateArgument(F, Record, Idx));
+ new (I) TemplateArgument(Record.readTemplateArgument());
} else if (!E->isValueDependent()) {
- E->Length = Record[Idx++];
+ E->Length = Record.readInt();
}
}
void ASTStmtReader::VisitSubstNonTypeTemplateParmExpr(
SubstNonTypeTemplateParmExpr *E) {
VisitExpr(E);
- E->Param = ReadDeclAs<NonTypeTemplateParmDecl>(Record, Idx);
- E->NameLoc = ReadSourceLocation(Record, Idx);
- E->Replacement = Reader.ReadSubExpr();
+ E->Param = ReadDeclAs<NonTypeTemplateParmDecl>();
+ E->NameLoc = ReadSourceLocation();
+ E->Replacement = Record.readSubExpr();
}
void ASTStmtReader::VisitSubstNonTypeTemplateParmPackExpr(
SubstNonTypeTemplateParmPackExpr *E) {
VisitExpr(E);
- E->Param = ReadDeclAs<NonTypeTemplateParmDecl>(Record, Idx);
- TemplateArgument ArgPack = Reader.ReadTemplateArgument(F, Record, Idx);
+ E->Param = ReadDeclAs<NonTypeTemplateParmDecl>();
+ TemplateArgument ArgPack = Record.readTemplateArgument();
if (ArgPack.getKind() != TemplateArgument::Pack)
return;
-
+
E->Arguments = ArgPack.pack_begin();
E->NumArguments = ArgPack.pack_size();
- E->NameLoc = ReadSourceLocation(Record, Idx);
+ E->NameLoc = ReadSourceLocation();
}
void ASTStmtReader::VisitFunctionParmPackExpr(FunctionParmPackExpr *E) {
VisitExpr(E);
- E->NumParameters = Record[Idx++];
- E->ParamPack = ReadDeclAs<ParmVarDecl>(Record, Idx);
- E->NameLoc = ReadSourceLocation(Record, Idx);
+ E->NumParameters = Record.readInt();
+ E->ParamPack = ReadDeclAs<ParmVarDecl>();
+ E->NameLoc = ReadSourceLocation();
ParmVarDecl **Parms = E->getTrailingObjects<ParmVarDecl *>();
for (unsigned i = 0, n = E->NumParameters; i != n; ++i)
- Parms[i] = ReadDeclAs<ParmVarDecl>(Record, Idx);
+ Parms[i] = ReadDeclAs<ParmVarDecl>();
}
void ASTStmtReader::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) {
VisitExpr(E);
- E->State = Reader.ReadSubExpr();
- auto VD = ReadDeclAs<ValueDecl>(Record, Idx);
- unsigned ManglingNumber = Record[Idx++];
+ E->State = Record.readSubExpr();
+ auto VD = ReadDeclAs<ValueDecl>();
+ unsigned ManglingNumber = Record.readInt();
E->setExtendingDecl(VD, ManglingNumber);
}
void ASTStmtReader::VisitCXXFoldExpr(CXXFoldExpr *E) {
VisitExpr(E);
- E->LParenLoc = ReadSourceLocation(Record, Idx);
- E->EllipsisLoc = ReadSourceLocation(Record, Idx);
- E->RParenLoc = ReadSourceLocation(Record, Idx);
- E->SubExprs[0] = Reader.ReadSubExpr();
- E->SubExprs[1] = Reader.ReadSubExpr();
- E->Opcode = (BinaryOperatorKind)Record[Idx++];
+ E->LParenLoc = ReadSourceLocation();
+ E->EllipsisLoc = ReadSourceLocation();
+ E->RParenLoc = ReadSourceLocation();
+ E->SubExprs[0] = Record.readSubExpr();
+ E->SubExprs[1] = Record.readSubExpr();
+ E->Opcode = (BinaryOperatorKind)Record.readInt();
}
void ASTStmtReader::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
VisitExpr(E);
- E->SourceExpr = Reader.ReadSubExpr();
- E->Loc = ReadSourceLocation(Record, Idx);
+ E->SourceExpr = Record.readSubExpr();
+ E->Loc = ReadSourceLocation();
}
void ASTStmtReader::VisitTypoExpr(TypoExpr *E) {
@@ -1683,59 +1655,59 @@ void ASTStmtReader::VisitTypoExpr(TypoExpr *E) {
//===----------------------------------------------------------------------===//
void ASTStmtReader::VisitMSPropertyRefExpr(MSPropertyRefExpr *E) {
VisitExpr(E);
- E->IsArrow = (Record[Idx++] != 0);
- E->BaseExpr = Reader.ReadSubExpr();
- E->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx);
- E->MemberLoc = ReadSourceLocation(Record, Idx);
- E->TheDecl = ReadDeclAs<MSPropertyDecl>(Record, Idx);
+ E->IsArrow = (Record.readInt() != 0);
+ E->BaseExpr = Record.readSubExpr();
+ E->QualifierLoc = Record.readNestedNameSpecifierLoc();
+ E->MemberLoc = ReadSourceLocation();
+ E->TheDecl = ReadDeclAs<MSPropertyDecl>();
}
void ASTStmtReader::VisitMSPropertySubscriptExpr(MSPropertySubscriptExpr *E) {
VisitExpr(E);
- E->setBase(Reader.ReadSubExpr());
- E->setIdx(Reader.ReadSubExpr());
- E->setRBracketLoc(ReadSourceLocation(Record, Idx));
+ E->setBase(Record.readSubExpr());
+ E->setIdx(Record.readSubExpr());
+ E->setRBracketLoc(ReadSourceLocation());
}
void ASTStmtReader::VisitCXXUuidofExpr(CXXUuidofExpr *E) {
VisitExpr(E);
- E->setSourceRange(ReadSourceRange(Record, Idx));
- std::string UuidStr = ReadString(Record, Idx);
- E->setUuidStr(StringRef(UuidStr).copy(Reader.getContext()));
+ E->setSourceRange(ReadSourceRange());
+ std::string UuidStr = ReadString();
+ E->setUuidStr(StringRef(UuidStr).copy(Record.getContext()));
if (E->isTypeOperand()) { // __uuidof(ComType)
E->setTypeOperandSourceInfo(
- GetTypeSourceInfo(Record, Idx));
+ GetTypeSourceInfo());
return;
}
-
+
// __uuidof(expr)
- E->setExprOperand(Reader.ReadSubExpr());
+ E->setExprOperand(Record.readSubExpr());
}
void ASTStmtReader::VisitSEHLeaveStmt(SEHLeaveStmt *S) {
VisitStmt(S);
- S->setLeaveLoc(ReadSourceLocation(Record, Idx));
+ S->setLeaveLoc(ReadSourceLocation());
}
void ASTStmtReader::VisitSEHExceptStmt(SEHExceptStmt *S) {
VisitStmt(S);
- S->Loc = ReadSourceLocation(Record, Idx);
- S->Children[SEHExceptStmt::FILTER_EXPR] = Reader.ReadSubStmt();
- S->Children[SEHExceptStmt::BLOCK] = Reader.ReadSubStmt();
+ S->Loc = ReadSourceLocation();
+ S->Children[SEHExceptStmt::FILTER_EXPR] = Record.readSubStmt();
+ S->Children[SEHExceptStmt::BLOCK] = Record.readSubStmt();
}
void ASTStmtReader::VisitSEHFinallyStmt(SEHFinallyStmt *S) {
VisitStmt(S);
- S->Loc = ReadSourceLocation(Record, Idx);
- S->Block = Reader.ReadSubStmt();
+ S->Loc = ReadSourceLocation();
+ S->Block = Record.readSubStmt();
}
void ASTStmtReader::VisitSEHTryStmt(SEHTryStmt *S) {
VisitStmt(S);
- S->IsCXXTry = Record[Idx++];
- S->TryLoc = ReadSourceLocation(Record, Idx);
- S->Children[SEHTryStmt::TRY] = Reader.ReadSubStmt();
- S->Children[SEHTryStmt::HANDLER] = Reader.ReadSubStmt();
+ S->IsCXXTry = Record.readInt();
+ S->TryLoc = ReadSourceLocation();
+ S->Children[SEHTryStmt::TRY] = Record.readSubStmt();
+ S->Children[SEHTryStmt::HANDLER] = Record.readSubStmt();
}
//===----------------------------------------------------------------------===//
@@ -1744,7 +1716,7 @@ void ASTStmtReader::VisitSEHTryStmt(SEHTryStmt *S) {
void ASTStmtReader::VisitCUDAKernelCallExpr(CUDAKernelCallExpr *E) {
VisitCallExpr(E);
- E->setConfig(cast<CallExpr>(Reader.ReadSubExpr()));
+ E->setConfig(cast<CallExpr>(Record.readSubExpr()));
}
//===----------------------------------------------------------------------===//
@@ -1752,9 +1724,9 @@ void ASTStmtReader::VisitCUDAKernelCallExpr(CUDAKernelCallExpr *E) {
//===----------------------------------------------------------------------===//
void ASTStmtReader::VisitAsTypeExpr(AsTypeExpr *E) {
VisitExpr(E);
- E->BuiltinLoc = ReadSourceLocation(Record, Idx);
- E->RParenLoc = ReadSourceLocation(Record, Idx);
- E->SrcExpr = Reader.ReadSubExpr();
+ E->BuiltinLoc = ReadSourceLocation();
+ E->RParenLoc = ReadSourceLocation();
+ E->SrcExpr = Record.readSubExpr();
}
//===----------------------------------------------------------------------===//
@@ -1765,12 +1737,9 @@ namespace clang {
class OMPClauseReader : public OMPClauseVisitor<OMPClauseReader> {
ASTStmtReader *Reader;
ASTContext &Context;
- const ASTReader::RecordData &Record;
- unsigned &Idx;
public:
- OMPClauseReader(ASTStmtReader *R, ASTContext &C,
- const ASTReader::RecordData &Record, unsigned &Idx)
- : Reader(R), Context(C), Record(Record), Idx(Idx) { }
+ 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();
@@ -1781,7 +1750,7 @@ public:
OMPClause *OMPClauseReader::readClause() {
OMPClause *C;
- switch (Record[Idx++]) {
+ switch (Reader->Record.readInt()) {
case OMPC_if:
C = new (Context) OMPIfClause();
break;
@@ -1846,46 +1815,46 @@ OMPClause *OMPClauseReader::readClause() {
C = new (Context) OMPNogroupClause();
break;
case OMPC_private:
- C = OMPPrivateClause::CreateEmpty(Context, Record[Idx++]);
+ C = OMPPrivateClause::CreateEmpty(Context, Reader->Record.readInt());
break;
case OMPC_firstprivate:
- C = OMPFirstprivateClause::CreateEmpty(Context, Record[Idx++]);
+ C = OMPFirstprivateClause::CreateEmpty(Context, Reader->Record.readInt());
break;
case OMPC_lastprivate:
- C = OMPLastprivateClause::CreateEmpty(Context, Record[Idx++]);
+ C = OMPLastprivateClause::CreateEmpty(Context, Reader->Record.readInt());
break;
case OMPC_shared:
- C = OMPSharedClause::CreateEmpty(Context, Record[Idx++]);
+ C = OMPSharedClause::CreateEmpty(Context, Reader->Record.readInt());
break;
case OMPC_reduction:
- C = OMPReductionClause::CreateEmpty(Context, Record[Idx++]);
+ C = OMPReductionClause::CreateEmpty(Context, Reader->Record.readInt());
break;
case OMPC_linear:
- C = OMPLinearClause::CreateEmpty(Context, Record[Idx++]);
+ C = OMPLinearClause::CreateEmpty(Context, Reader->Record.readInt());
break;
case OMPC_aligned:
- C = OMPAlignedClause::CreateEmpty(Context, Record[Idx++]);
+ C = OMPAlignedClause::CreateEmpty(Context, Reader->Record.readInt());
break;
case OMPC_copyin:
- C = OMPCopyinClause::CreateEmpty(Context, Record[Idx++]);
+ C = OMPCopyinClause::CreateEmpty(Context, Reader->Record.readInt());
break;
case OMPC_copyprivate:
- C = OMPCopyprivateClause::CreateEmpty(Context, Record[Idx++]);
+ C = OMPCopyprivateClause::CreateEmpty(Context, Reader->Record.readInt());
break;
case OMPC_flush:
- C = OMPFlushClause::CreateEmpty(Context, Record[Idx++]);
+ C = OMPFlushClause::CreateEmpty(Context, Reader->Record.readInt());
break;
case OMPC_depend:
- C = OMPDependClause::CreateEmpty(Context, Record[Idx++]);
+ C = OMPDependClause::CreateEmpty(Context, Reader->Record.readInt());
break;
case OMPC_device:
C = new (Context) OMPDeviceClause();
break;
case OMPC_map: {
- unsigned NumVars = Record[Idx++];
- unsigned NumDeclarations = Record[Idx++];
- unsigned NumLists = Record[Idx++];
- unsigned NumComponents = Record[Idx++];
+ unsigned NumVars = Reader->Record.readInt();
+ unsigned NumDeclarations = Reader->Record.readInt();
+ unsigned NumLists = Reader->Record.readInt();
+ unsigned NumComponents = Reader->Record.readInt();
C = OMPMapClause::CreateEmpty(Context, NumVars, NumDeclarations, NumLists,
NumComponents);
break;
@@ -1915,112 +1884,124 @@ OMPClause *OMPClauseReader::readClause() {
C = new (Context) OMPDefaultmapClause();
break;
case OMPC_to: {
- unsigned NumVars = Record[Idx++];
- unsigned NumDeclarations = Record[Idx++];
- unsigned NumLists = Record[Idx++];
- unsigned NumComponents = Record[Idx++];
+ unsigned NumVars = Reader->Record.readInt();
+ unsigned NumDeclarations = Reader->Record.readInt();
+ unsigned NumLists = Reader->Record.readInt();
+ unsigned NumComponents = Reader->Record.readInt();
C = OMPToClause::CreateEmpty(Context, NumVars, NumDeclarations, NumLists,
NumComponents);
break;
}
case OMPC_from: {
- unsigned NumVars = Record[Idx++];
- unsigned NumDeclarations = Record[Idx++];
- unsigned NumLists = Record[Idx++];
- unsigned NumComponents = Record[Idx++];
+ unsigned NumVars = Reader->Record.readInt();
+ unsigned NumDeclarations = Reader->Record.readInt();
+ unsigned NumLists = Reader->Record.readInt();
+ unsigned NumComponents = Reader->Record.readInt();
C = OMPFromClause::CreateEmpty(Context, NumVars, NumDeclarations, NumLists,
NumComponents);
break;
}
- case OMPC_use_device_ptr:
- C = OMPUseDevicePtrClause::CreateEmpty(Context, Record[Idx++]);
+ case OMPC_use_device_ptr: {
+ unsigned NumVars = Reader->Record.readInt();
+ unsigned NumDeclarations = Reader->Record.readInt();
+ unsigned NumLists = Reader->Record.readInt();
+ unsigned NumComponents = Reader->Record.readInt();
+ C = OMPUseDevicePtrClause::CreateEmpty(Context, NumVars, NumDeclarations,
+ NumLists, NumComponents);
break;
- case OMPC_is_device_ptr:
- C = OMPIsDevicePtrClause::CreateEmpty(Context, Record[Idx++]);
+ }
+ case OMPC_is_device_ptr: {
+ unsigned NumVars = Reader->Record.readInt();
+ unsigned NumDeclarations = Reader->Record.readInt();
+ unsigned NumLists = Reader->Record.readInt();
+ unsigned NumComponents = Reader->Record.readInt();
+ C = OMPIsDevicePtrClause::CreateEmpty(Context, NumVars, NumDeclarations,
+ NumLists, NumComponents);
break;
}
+ }
Visit(C);
- C->setLocStart(Reader->ReadSourceLocation(Record, Idx));
- C->setLocEnd(Reader->ReadSourceLocation(Record, Idx));
+ C->setLocStart(Reader->ReadSourceLocation());
+ C->setLocEnd(Reader->ReadSourceLocation());
return C;
}
void OMPClauseReader::VisitOMPClauseWithPreInit(OMPClauseWithPreInit *C) {
- C->setPreInitStmt(Reader->Reader.ReadSubStmt());
+ C->setPreInitStmt(Reader->Record.readSubStmt());
}
void OMPClauseReader::VisitOMPClauseWithPostUpdate(OMPClauseWithPostUpdate *C) {
VisitOMPClauseWithPreInit(C);
- C->setPostUpdateExpr(Reader->Reader.ReadSubExpr());
+ C->setPostUpdateExpr(Reader->Record.readSubExpr());
}
void OMPClauseReader::VisitOMPIfClause(OMPIfClause *C) {
- C->setNameModifier(static_cast<OpenMPDirectiveKind>(Record[Idx++]));
- C->setNameModifierLoc(Reader->ReadSourceLocation(Record, Idx));
- C->setColonLoc(Reader->ReadSourceLocation(Record, Idx));
- C->setCondition(Reader->Reader.ReadSubExpr());
- C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+ C->setNameModifier(static_cast<OpenMPDirectiveKind>(Reader->Record.readInt()));
+ C->setNameModifierLoc(Reader->ReadSourceLocation());
+ C->setColonLoc(Reader->ReadSourceLocation());
+ C->setCondition(Reader->Record.readSubExpr());
+ C->setLParenLoc(Reader->ReadSourceLocation());
}
void OMPClauseReader::VisitOMPFinalClause(OMPFinalClause *C) {
- C->setCondition(Reader->Reader.ReadSubExpr());
- C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+ C->setCondition(Reader->Record.readSubExpr());
+ C->setLParenLoc(Reader->ReadSourceLocation());
}
void OMPClauseReader::VisitOMPNumThreadsClause(OMPNumThreadsClause *C) {
- C->setNumThreads(Reader->Reader.ReadSubExpr());
- C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+ C->setNumThreads(Reader->Record.readSubExpr());
+ C->setLParenLoc(Reader->ReadSourceLocation());
}
void OMPClauseReader::VisitOMPSafelenClause(OMPSafelenClause *C) {
- C->setSafelen(Reader->Reader.ReadSubExpr());
- C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+ C->setSafelen(Reader->Record.readSubExpr());
+ C->setLParenLoc(Reader->ReadSourceLocation());
}
void OMPClauseReader::VisitOMPSimdlenClause(OMPSimdlenClause *C) {
- C->setSimdlen(Reader->Reader.ReadSubExpr());
- C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+ C->setSimdlen(Reader->Record.readSubExpr());
+ C->setLParenLoc(Reader->ReadSourceLocation());
}
void OMPClauseReader::VisitOMPCollapseClause(OMPCollapseClause *C) {
- C->setNumForLoops(Reader->Reader.ReadSubExpr());
- C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+ C->setNumForLoops(Reader->Record.readSubExpr());
+ C->setLParenLoc(Reader->ReadSourceLocation());
}
void OMPClauseReader::VisitOMPDefaultClause(OMPDefaultClause *C) {
C->setDefaultKind(
- static_cast<OpenMPDefaultClauseKind>(Record[Idx++]));
- C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
- C->setDefaultKindKwLoc(Reader->ReadSourceLocation(Record, Idx));
+ static_cast<OpenMPDefaultClauseKind>(Reader->Record.readInt()));
+ C->setLParenLoc(Reader->ReadSourceLocation());
+ C->setDefaultKindKwLoc(Reader->ReadSourceLocation());
}
void OMPClauseReader::VisitOMPProcBindClause(OMPProcBindClause *C) {
C->setProcBindKind(
- static_cast<OpenMPProcBindClauseKind>(Record[Idx++]));
- C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
- C->setProcBindKindKwLoc(Reader->ReadSourceLocation(Record, Idx));
+ static_cast<OpenMPProcBindClauseKind>(Reader->Record.readInt()));
+ C->setLParenLoc(Reader->ReadSourceLocation());
+ C->setProcBindKindKwLoc(Reader->ReadSourceLocation());
}
void OMPClauseReader::VisitOMPScheduleClause(OMPScheduleClause *C) {
VisitOMPClauseWithPreInit(C);
C->setScheduleKind(
- static_cast<OpenMPScheduleClauseKind>(Record[Idx++]));
+ static_cast<OpenMPScheduleClauseKind>(Reader->Record.readInt()));
C->setFirstScheduleModifier(
- static_cast<OpenMPScheduleClauseModifier>(Record[Idx++]));
+ static_cast<OpenMPScheduleClauseModifier>(Reader->Record.readInt()));
C->setSecondScheduleModifier(
- static_cast<OpenMPScheduleClauseModifier>(Record[Idx++]));
- C->setChunkSize(Reader->Reader.ReadSubExpr());
- C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
- C->setFirstScheduleModifierLoc(Reader->ReadSourceLocation(Record, Idx));
- C->setSecondScheduleModifierLoc(Reader->ReadSourceLocation(Record, Idx));
- C->setScheduleKindLoc(Reader->ReadSourceLocation(Record, Idx));
- C->setCommaLoc(Reader->ReadSourceLocation(Record, Idx));
+ static_cast<OpenMPScheduleClauseModifier>(Reader->Record.readInt()));
+ C->setChunkSize(Reader->Record.readSubExpr());
+ C->setLParenLoc(Reader->ReadSourceLocation());
+ C->setFirstScheduleModifierLoc(Reader->ReadSourceLocation());
+ C->setSecondScheduleModifierLoc(Reader->ReadSourceLocation());
+ C->setScheduleKindLoc(Reader->ReadSourceLocation());
+ C->setCommaLoc(Reader->ReadSourceLocation());
}
void OMPClauseReader::VisitOMPOrderedClause(OMPOrderedClause *C) {
- C->setNumForLoops(Reader->Reader.ReadSubExpr());
- C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+ C->setNumForLoops(Reader->Record.readSubExpr());
+ C->setLParenLoc(Reader->ReadSourceLocation());
}
void OMPClauseReader::VisitOMPNowaitClause(OMPNowaitClause *) {}
@@ -2046,83 +2027,82 @@ void OMPClauseReader::VisitOMPSIMDClause(OMPSIMDClause *) {}
void OMPClauseReader::VisitOMPNogroupClause(OMPNogroupClause *) {}
void OMPClauseReader::VisitOMPPrivateClause(OMPPrivateClause *C) {
- C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+ C->setLParenLoc(Reader->ReadSourceLocation());
unsigned NumVars = C->varlist_size();
SmallVector<Expr *, 16> Vars;
Vars.reserve(NumVars);
for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Reader.ReadSubExpr());
+ Vars.push_back(Reader->Record.readSubExpr());
C->setVarRefs(Vars);
Vars.clear();
for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Reader.ReadSubExpr());
+ Vars.push_back(Reader->Record.readSubExpr());
C->setPrivateCopies(Vars);
}
void OMPClauseReader::VisitOMPFirstprivateClause(OMPFirstprivateClause *C) {
VisitOMPClauseWithPreInit(C);
- C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+ C->setLParenLoc(Reader->ReadSourceLocation());
unsigned NumVars = C->varlist_size();
SmallVector<Expr *, 16> Vars;
Vars.reserve(NumVars);
for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Reader.ReadSubExpr());
+ Vars.push_back(Reader->Record.readSubExpr());
C->setVarRefs(Vars);
Vars.clear();
for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Reader.ReadSubExpr());
+ Vars.push_back(Reader->Record.readSubExpr());
C->setPrivateCopies(Vars);
Vars.clear();
for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Reader.ReadSubExpr());
+ Vars.push_back(Reader->Record.readSubExpr());
C->setInits(Vars);
}
void OMPClauseReader::VisitOMPLastprivateClause(OMPLastprivateClause *C) {
VisitOMPClauseWithPostUpdate(C);
- C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+ C->setLParenLoc(Reader->ReadSourceLocation());
unsigned NumVars = C->varlist_size();
SmallVector<Expr *, 16> Vars;
Vars.reserve(NumVars);
for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Reader.ReadSubExpr());
+ Vars.push_back(Reader->Record.readSubExpr());
C->setVarRefs(Vars);
Vars.clear();
for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Reader.ReadSubExpr());
+ Vars.push_back(Reader->Record.readSubExpr());
C->setPrivateCopies(Vars);
Vars.clear();
for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Reader.ReadSubExpr());
+ Vars.push_back(Reader->Record.readSubExpr());
C->setSourceExprs(Vars);
Vars.clear();
for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Reader.ReadSubExpr());
+ Vars.push_back(Reader->Record.readSubExpr());
C->setDestinationExprs(Vars);
Vars.clear();
for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Reader.ReadSubExpr());
+ Vars.push_back(Reader->Record.readSubExpr());
C->setAssignmentOps(Vars);
}
void OMPClauseReader::VisitOMPSharedClause(OMPSharedClause *C) {
- C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+ C->setLParenLoc(Reader->ReadSourceLocation());
unsigned NumVars = C->varlist_size();
SmallVector<Expr *, 16> Vars;
Vars.reserve(NumVars);
for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Reader.ReadSubExpr());
+ Vars.push_back(Reader->Record.readSubExpr());
C->setVarRefs(Vars);
}
void OMPClauseReader::VisitOMPReductionClause(OMPReductionClause *C) {
VisitOMPClauseWithPostUpdate(C);
- C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
- C->setColonLoc(Reader->ReadSourceLocation(Record, Idx));
- NestedNameSpecifierLoc NNSL =
- Reader->Reader.ReadNestedNameSpecifierLoc(Reader->F, Record, Idx);
+ C->setLParenLoc(Reader->ReadSourceLocation());
+ C->setColonLoc(Reader->ReadSourceLocation());
+ NestedNameSpecifierLoc NNSL = Reader->Record.readNestedNameSpecifierLoc();
DeclarationNameInfo DNI;
- Reader->ReadDeclarationNameInfo(DNI, Record, Idx);
+ Reader->ReadDeclarationNameInfo(DNI);
C->setQualifierLoc(NNSL);
C->setNameInfo(DNI);
@@ -2130,151 +2110,152 @@ void OMPClauseReader::VisitOMPReductionClause(OMPReductionClause *C) {
SmallVector<Expr *, 16> Vars;
Vars.reserve(NumVars);
for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Reader.ReadSubExpr());
+ Vars.push_back(Reader->Record.readSubExpr());
C->setVarRefs(Vars);
Vars.clear();
for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Reader.ReadSubExpr());
+ Vars.push_back(Reader->Record.readSubExpr());
C->setPrivates(Vars);
Vars.clear();
for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Reader.ReadSubExpr());
+ Vars.push_back(Reader->Record.readSubExpr());
C->setLHSExprs(Vars);
Vars.clear();
for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Reader.ReadSubExpr());
+ Vars.push_back(Reader->Record.readSubExpr());
C->setRHSExprs(Vars);
Vars.clear();
for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Reader.ReadSubExpr());
+ Vars.push_back(Reader->Record.readSubExpr());
C->setReductionOps(Vars);
}
void OMPClauseReader::VisitOMPLinearClause(OMPLinearClause *C) {
VisitOMPClauseWithPostUpdate(C);
- C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
- C->setColonLoc(Reader->ReadSourceLocation(Record, Idx));
- C->setModifier(static_cast<OpenMPLinearClauseKind>(Record[Idx++]));
- C->setModifierLoc(Reader->ReadSourceLocation(Record, Idx));
+ C->setLParenLoc(Reader->ReadSourceLocation());
+ C->setColonLoc(Reader->ReadSourceLocation());
+ C->setModifier(static_cast<OpenMPLinearClauseKind>(Reader->Record.readInt()));
+ C->setModifierLoc(Reader->ReadSourceLocation());
unsigned NumVars = C->varlist_size();
SmallVector<Expr *, 16> Vars;
Vars.reserve(NumVars);
for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Reader.ReadSubExpr());
+ Vars.push_back(Reader->Record.readSubExpr());
C->setVarRefs(Vars);
Vars.clear();
for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Reader.ReadSubExpr());
+ Vars.push_back(Reader->Record.readSubExpr());
C->setPrivates(Vars);
Vars.clear();
for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Reader.ReadSubExpr());
+ Vars.push_back(Reader->Record.readSubExpr());
C->setInits(Vars);
Vars.clear();
for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Reader.ReadSubExpr());
+ Vars.push_back(Reader->Record.readSubExpr());
C->setUpdates(Vars);
Vars.clear();
for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Reader.ReadSubExpr());
+ Vars.push_back(Reader->Record.readSubExpr());
C->setFinals(Vars);
- C->setStep(Reader->Reader.ReadSubExpr());
- C->setCalcStep(Reader->Reader.ReadSubExpr());
+ C->setStep(Reader->Record.readSubExpr());
+ C->setCalcStep(Reader->Record.readSubExpr());
}
void OMPClauseReader::VisitOMPAlignedClause(OMPAlignedClause *C) {
- C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
- C->setColonLoc(Reader->ReadSourceLocation(Record, Idx));
+ C->setLParenLoc(Reader->ReadSourceLocation());
+ C->setColonLoc(Reader->ReadSourceLocation());
unsigned NumVars = C->varlist_size();
SmallVector<Expr *, 16> Vars;
Vars.reserve(NumVars);
for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Reader.ReadSubExpr());
+ Vars.push_back(Reader->Record.readSubExpr());
C->setVarRefs(Vars);
- C->setAlignment(Reader->Reader.ReadSubExpr());
+ C->setAlignment(Reader->Record.readSubExpr());
}
void OMPClauseReader::VisitOMPCopyinClause(OMPCopyinClause *C) {
- C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+ C->setLParenLoc(Reader->ReadSourceLocation());
unsigned NumVars = C->varlist_size();
SmallVector<Expr *, 16> Exprs;
Exprs.reserve(NumVars);
for (unsigned i = 0; i != NumVars; ++i)
- Exprs.push_back(Reader->Reader.ReadSubExpr());
+ Exprs.push_back(Reader->Record.readSubExpr());
C->setVarRefs(Exprs);
Exprs.clear();
for (unsigned i = 0; i != NumVars; ++i)
- Exprs.push_back(Reader->Reader.ReadSubExpr());
+ Exprs.push_back(Reader->Record.readSubExpr());
C->setSourceExprs(Exprs);
Exprs.clear();
for (unsigned i = 0; i != NumVars; ++i)
- Exprs.push_back(Reader->Reader.ReadSubExpr());
+ Exprs.push_back(Reader->Record.readSubExpr());
C->setDestinationExprs(Exprs);
Exprs.clear();
for (unsigned i = 0; i != NumVars; ++i)
- Exprs.push_back(Reader->Reader.ReadSubExpr());
+ Exprs.push_back(Reader->Record.readSubExpr());
C->setAssignmentOps(Exprs);
}
void OMPClauseReader::VisitOMPCopyprivateClause(OMPCopyprivateClause *C) {
- C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+ C->setLParenLoc(Reader->ReadSourceLocation());
unsigned NumVars = C->varlist_size();
SmallVector<Expr *, 16> Exprs;
Exprs.reserve(NumVars);
for (unsigned i = 0; i != NumVars; ++i)
- Exprs.push_back(Reader->Reader.ReadSubExpr());
+ Exprs.push_back(Reader->Record.readSubExpr());
C->setVarRefs(Exprs);
Exprs.clear();
for (unsigned i = 0; i != NumVars; ++i)
- Exprs.push_back(Reader->Reader.ReadSubExpr());
+ Exprs.push_back(Reader->Record.readSubExpr());
C->setSourceExprs(Exprs);
Exprs.clear();
for (unsigned i = 0; i != NumVars; ++i)
- Exprs.push_back(Reader->Reader.ReadSubExpr());
+ Exprs.push_back(Reader->Record.readSubExpr());
C->setDestinationExprs(Exprs);
Exprs.clear();
for (unsigned i = 0; i != NumVars; ++i)
- Exprs.push_back(Reader->Reader.ReadSubExpr());
+ Exprs.push_back(Reader->Record.readSubExpr());
C->setAssignmentOps(Exprs);
}
void OMPClauseReader::VisitOMPFlushClause(OMPFlushClause *C) {
- C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+ C->setLParenLoc(Reader->ReadSourceLocation());
unsigned NumVars = C->varlist_size();
SmallVector<Expr *, 16> Vars;
Vars.reserve(NumVars);
for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Reader.ReadSubExpr());
+ Vars.push_back(Reader->Record.readSubExpr());
C->setVarRefs(Vars);
}
void OMPClauseReader::VisitOMPDependClause(OMPDependClause *C) {
- C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
- C->setDependencyKind(static_cast<OpenMPDependClauseKind>(Record[Idx++]));
- C->setDependencyLoc(Reader->ReadSourceLocation(Record, Idx));
- C->setColonLoc(Reader->ReadSourceLocation(Record, Idx));
+ C->setLParenLoc(Reader->ReadSourceLocation());
+ C->setDependencyKind(
+ static_cast<OpenMPDependClauseKind>(Reader->Record.readInt()));
+ C->setDependencyLoc(Reader->ReadSourceLocation());
+ C->setColonLoc(Reader->ReadSourceLocation());
unsigned NumVars = C->varlist_size();
SmallVector<Expr *, 16> Vars;
Vars.reserve(NumVars);
for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Reader.ReadSubExpr());
+ Vars.push_back(Reader->Record.readSubExpr());
C->setVarRefs(Vars);
- C->setCounterValue(Reader->Reader.ReadSubExpr());
+ C->setCounterValue(Reader->Record.readSubExpr());
}
void OMPClauseReader::VisitOMPDeviceClause(OMPDeviceClause *C) {
- C->setDevice(Reader->Reader.ReadSubExpr());
- C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+ C->setDevice(Reader->Record.readSubExpr());
+ C->setLParenLoc(Reader->ReadSourceLocation());
}
void OMPClauseReader::VisitOMPMapClause(OMPMapClause *C) {
- C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+ C->setLParenLoc(Reader->ReadSourceLocation());
C->setMapTypeModifier(
- static_cast<OpenMPMapClauseKind>(Record[Idx++]));
+ static_cast<OpenMPMapClauseKind>(Reader->Record.readInt()));
C->setMapType(
- static_cast<OpenMPMapClauseKind>(Record[Idx++]));
- C->setMapLoc(Reader->ReadSourceLocation(Record, Idx));
- C->setColonLoc(Reader->ReadSourceLocation(Record, Idx));
+ static_cast<OpenMPMapClauseKind>(Reader->Record.readInt()));
+ C->setMapLoc(Reader->ReadSourceLocation());
+ C->setColonLoc(Reader->ReadSourceLocation());
auto NumVars = C->varlist_size();
auto UniqueDecls = C->getUniqueDeclarationsNum();
auto TotalLists = C->getTotalComponentListNum();
@@ -2283,34 +2264,32 @@ void OMPClauseReader::VisitOMPMapClause(OMPMapClause *C) {
SmallVector<Expr *, 16> Vars;
Vars.reserve(NumVars);
for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Reader.ReadSubExpr());
+ Vars.push_back(Reader->Record.readSubExpr());
C->setVarRefs(Vars);
SmallVector<ValueDecl *, 16> Decls;
Decls.reserve(UniqueDecls);
for (unsigned i = 0; i < UniqueDecls; ++i)
- Decls.push_back(
- Reader->Reader.ReadDeclAs<ValueDecl>(Reader->F, Record, Idx));
+ Decls.push_back(Reader->Record.readDeclAs<ValueDecl>());
C->setUniqueDecls(Decls);
SmallVector<unsigned, 16> ListsPerDecl;
ListsPerDecl.reserve(UniqueDecls);
for (unsigned i = 0; i < UniqueDecls; ++i)
- ListsPerDecl.push_back(Record[Idx++]);
+ ListsPerDecl.push_back(Reader->Record.readInt());
C->setDeclNumLists(ListsPerDecl);
SmallVector<unsigned, 32> ListSizes;
ListSizes.reserve(TotalLists);
for (unsigned i = 0; i < TotalLists; ++i)
- ListSizes.push_back(Record[Idx++]);
+ ListSizes.push_back(Reader->Record.readInt());
C->setComponentListSizes(ListSizes);
SmallVector<OMPClauseMappableExprCommon::MappableComponent, 32> Components;
Components.reserve(TotalComponents);
for (unsigned i = 0; i < TotalComponents; ++i) {
- Expr *AssociatedExpr = Reader->Reader.ReadSubExpr();
- ValueDecl *AssociatedDecl =
- Reader->Reader.ReadDeclAs<ValueDecl>(Reader->F, Record, Idx);
+ Expr *AssociatedExpr = Reader->Record.readSubExpr();
+ ValueDecl *AssociatedDecl = Reader->Record.readDeclAs<ValueDecl>();
Components.push_back(OMPClauseMappableExprCommon::MappableComponent(
AssociatedExpr, AssociatedDecl));
}
@@ -2318,57 +2297,57 @@ void OMPClauseReader::VisitOMPMapClause(OMPMapClause *C) {
}
void OMPClauseReader::VisitOMPNumTeamsClause(OMPNumTeamsClause *C) {
- C->setNumTeams(Reader->Reader.ReadSubExpr());
- C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+ C->setNumTeams(Reader->Record.readSubExpr());
+ C->setLParenLoc(Reader->ReadSourceLocation());
}
void OMPClauseReader::VisitOMPThreadLimitClause(OMPThreadLimitClause *C) {
- C->setThreadLimit(Reader->Reader.ReadSubExpr());
- C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+ C->setThreadLimit(Reader->Record.readSubExpr());
+ C->setLParenLoc(Reader->ReadSourceLocation());
}
void OMPClauseReader::VisitOMPPriorityClause(OMPPriorityClause *C) {
- C->setPriority(Reader->Reader.ReadSubExpr());
- C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+ C->setPriority(Reader->Record.readSubExpr());
+ C->setLParenLoc(Reader->ReadSourceLocation());
}
void OMPClauseReader::VisitOMPGrainsizeClause(OMPGrainsizeClause *C) {
- C->setGrainsize(Reader->Reader.ReadSubExpr());
- C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+ C->setGrainsize(Reader->Record.readSubExpr());
+ C->setLParenLoc(Reader->ReadSourceLocation());
}
void OMPClauseReader::VisitOMPNumTasksClause(OMPNumTasksClause *C) {
- C->setNumTasks(Reader->Reader.ReadSubExpr());
- C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+ C->setNumTasks(Reader->Record.readSubExpr());
+ C->setLParenLoc(Reader->ReadSourceLocation());
}
void OMPClauseReader::VisitOMPHintClause(OMPHintClause *C) {
- C->setHint(Reader->Reader.ReadSubExpr());
- C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+ C->setHint(Reader->Record.readSubExpr());
+ C->setLParenLoc(Reader->ReadSourceLocation());
}
void OMPClauseReader::VisitOMPDistScheduleClause(OMPDistScheduleClause *C) {
VisitOMPClauseWithPreInit(C);
C->setDistScheduleKind(
- static_cast<OpenMPDistScheduleClauseKind>(Record[Idx++]));
- C->setChunkSize(Reader->Reader.ReadSubExpr());
- C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
- C->setDistScheduleKindLoc(Reader->ReadSourceLocation(Record, Idx));
- C->setCommaLoc(Reader->ReadSourceLocation(Record, Idx));
+ static_cast<OpenMPDistScheduleClauseKind>(Reader->Record.readInt()));
+ C->setChunkSize(Reader->Record.readSubExpr());
+ C->setLParenLoc(Reader->ReadSourceLocation());
+ C->setDistScheduleKindLoc(Reader->ReadSourceLocation());
+ C->setCommaLoc(Reader->ReadSourceLocation());
}
void OMPClauseReader::VisitOMPDefaultmapClause(OMPDefaultmapClause *C) {
C->setDefaultmapKind(
- static_cast<OpenMPDefaultmapClauseKind>(Record[Idx++]));
+ static_cast<OpenMPDefaultmapClauseKind>(Reader->Record.readInt()));
C->setDefaultmapModifier(
- static_cast<OpenMPDefaultmapClauseModifier>(Record[Idx++]));
- C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
- C->setDefaultmapModifierLoc(Reader->ReadSourceLocation(Record, Idx));
- C->setDefaultmapKindLoc(Reader->ReadSourceLocation(Record, Idx));
+ static_cast<OpenMPDefaultmapClauseModifier>(Reader->Record.readInt()));
+ C->setLParenLoc(Reader->ReadSourceLocation());
+ C->setDefaultmapModifierLoc(Reader->ReadSourceLocation());
+ C->setDefaultmapKindLoc(Reader->ReadSourceLocation());
}
void OMPClauseReader::VisitOMPToClause(OMPToClause *C) {
- C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+ C->setLParenLoc(Reader->ReadSourceLocation());
auto NumVars = C->varlist_size();
auto UniqueDecls = C->getUniqueDeclarationsNum();
auto TotalLists = C->getTotalComponentListNum();
@@ -2377,34 +2356,32 @@ void OMPClauseReader::VisitOMPToClause(OMPToClause *C) {
SmallVector<Expr *, 16> Vars;
Vars.reserve(NumVars);
for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Reader.ReadSubExpr());
+ Vars.push_back(Reader->Record.readSubExpr());
C->setVarRefs(Vars);
SmallVector<ValueDecl *, 16> Decls;
Decls.reserve(UniqueDecls);
for (unsigned i = 0; i < UniqueDecls; ++i)
- Decls.push_back(
- Reader->Reader.ReadDeclAs<ValueDecl>(Reader->F, Record, Idx));
+ Decls.push_back(Reader->Record.readDeclAs<ValueDecl>());
C->setUniqueDecls(Decls);
SmallVector<unsigned, 16> ListsPerDecl;
ListsPerDecl.reserve(UniqueDecls);
for (unsigned i = 0; i < UniqueDecls; ++i)
- ListsPerDecl.push_back(Record[Idx++]);
+ ListsPerDecl.push_back(Reader->Record.readInt());
C->setDeclNumLists(ListsPerDecl);
SmallVector<unsigned, 32> ListSizes;
ListSizes.reserve(TotalLists);
for (unsigned i = 0; i < TotalLists; ++i)
- ListSizes.push_back(Record[Idx++]);
+ ListSizes.push_back(Reader->Record.readInt());
C->setComponentListSizes(ListSizes);
SmallVector<OMPClauseMappableExprCommon::MappableComponent, 32> Components;
Components.reserve(TotalComponents);
for (unsigned i = 0; i < TotalComponents; ++i) {
- Expr *AssociatedExpr = Reader->Reader.ReadSubExpr();
- ValueDecl *AssociatedDecl =
- Reader->Reader.ReadDeclAs<ValueDecl>(Reader->F, Record, Idx);
+ Expr *AssociatedExpr = Reader->Record.readSubExpr();
+ ValueDecl *AssociatedDecl = Reader->Record.readDeclAs<ValueDecl>();
Components.push_back(OMPClauseMappableExprCommon::MappableComponent(
AssociatedExpr, AssociatedDecl));
}
@@ -2412,7 +2389,7 @@ void OMPClauseReader::VisitOMPToClause(OMPToClause *C) {
}
void OMPClauseReader::VisitOMPFromClause(OMPFromClause *C) {
- C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+ C->setLParenLoc(Reader->ReadSourceLocation());
auto NumVars = C->varlist_size();
auto UniqueDecls = C->getUniqueDeclarationsNum();
auto TotalLists = C->getTotalComponentListNum();
@@ -2421,34 +2398,32 @@ void OMPClauseReader::VisitOMPFromClause(OMPFromClause *C) {
SmallVector<Expr *, 16> Vars;
Vars.reserve(NumVars);
for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Reader.ReadSubExpr());
+ Vars.push_back(Reader->Record.readSubExpr());
C->setVarRefs(Vars);
SmallVector<ValueDecl *, 16> Decls;
Decls.reserve(UniqueDecls);
for (unsigned i = 0; i < UniqueDecls; ++i)
- Decls.push_back(
- Reader->Reader.ReadDeclAs<ValueDecl>(Reader->F, Record, Idx));
+ Decls.push_back(Reader->Record.readDeclAs<ValueDecl>());
C->setUniqueDecls(Decls);
SmallVector<unsigned, 16> ListsPerDecl;
ListsPerDecl.reserve(UniqueDecls);
for (unsigned i = 0; i < UniqueDecls; ++i)
- ListsPerDecl.push_back(Record[Idx++]);
+ ListsPerDecl.push_back(Reader->Record.readInt());
C->setDeclNumLists(ListsPerDecl);
SmallVector<unsigned, 32> ListSizes;
ListSizes.reserve(TotalLists);
for (unsigned i = 0; i < TotalLists; ++i)
- ListSizes.push_back(Record[Idx++]);
+ ListSizes.push_back(Reader->Record.readInt());
C->setComponentListSizes(ListSizes);
SmallVector<OMPClauseMappableExprCommon::MappableComponent, 32> Components;
Components.reserve(TotalComponents);
for (unsigned i = 0; i < TotalComponents; ++i) {
- Expr *AssociatedExpr = Reader->Reader.ReadSubExpr();
- ValueDecl *AssociatedDecl =
- Reader->Reader.ReadDeclAs<ValueDecl>(Reader->F, Record, Idx);
+ Expr *AssociatedExpr = Reader->Record.readSubExpr();
+ ValueDecl *AssociatedDecl = Reader->Record.readDeclAs<ValueDecl>();
Components.push_back(OMPClauseMappableExprCommon::MappableComponent(
AssociatedExpr, AssociatedDecl));
}
@@ -2456,101 +2431,172 @@ void OMPClauseReader::VisitOMPFromClause(OMPFromClause *C) {
}
void OMPClauseReader::VisitOMPUseDevicePtrClause(OMPUseDevicePtrClause *C) {
- C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
- unsigned NumVars = C->varlist_size();
+ C->setLParenLoc(Reader->ReadSourceLocation());
+ auto NumVars = C->varlist_size();
+ auto UniqueDecls = C->getUniqueDeclarationsNum();
+ auto TotalLists = C->getTotalComponentListNum();
+ auto TotalComponents = C->getTotalComponentsNum();
+
SmallVector<Expr *, 16> Vars;
Vars.reserve(NumVars);
for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Reader.ReadSubExpr());
+ Vars.push_back(Reader->Record.readSubExpr());
C->setVarRefs(Vars);
Vars.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Reader->Record.readSubExpr());
+ C->setPrivateCopies(Vars);
+ Vars.clear();
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Reader->Record.readSubExpr());
+ C->setInits(Vars);
+
+ SmallVector<ValueDecl *, 16> Decls;
+ Decls.reserve(UniqueDecls);
+ for (unsigned i = 0; i < UniqueDecls; ++i)
+ Decls.push_back(Reader->Record.readDeclAs<ValueDecl>());
+ C->setUniqueDecls(Decls);
+
+ SmallVector<unsigned, 16> ListsPerDecl;
+ ListsPerDecl.reserve(UniqueDecls);
+ for (unsigned i = 0; i < UniqueDecls; ++i)
+ ListsPerDecl.push_back(Reader->Record.readInt());
+ C->setDeclNumLists(ListsPerDecl);
+
+ SmallVector<unsigned, 32> ListSizes;
+ ListSizes.reserve(TotalLists);
+ for (unsigned i = 0; i < TotalLists; ++i)
+ ListSizes.push_back(Reader->Record.readInt());
+ C->setComponentListSizes(ListSizes);
+
+ SmallVector<OMPClauseMappableExprCommon::MappableComponent, 32> Components;
+ Components.reserve(TotalComponents);
+ for (unsigned i = 0; i < TotalComponents; ++i) {
+ Expr *AssociatedExpr = Reader->Record.readSubExpr();
+ ValueDecl *AssociatedDecl = Reader->Record.readDeclAs<ValueDecl>();
+ Components.push_back(OMPClauseMappableExprCommon::MappableComponent(
+ AssociatedExpr, AssociatedDecl));
+ }
+ C->setComponents(Components, ListSizes);
}
void OMPClauseReader::VisitOMPIsDevicePtrClause(OMPIsDevicePtrClause *C) {
- C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
- unsigned NumVars = C->varlist_size();
+ C->setLParenLoc(Reader->ReadSourceLocation());
+ auto NumVars = C->varlist_size();
+ auto UniqueDecls = C->getUniqueDeclarationsNum();
+ auto TotalLists = C->getTotalComponentListNum();
+ auto TotalComponents = C->getTotalComponentsNum();
+
SmallVector<Expr *, 16> Vars;
Vars.reserve(NumVars);
for (unsigned i = 0; i != NumVars; ++i)
- Vars.push_back(Reader->Reader.ReadSubExpr());
+ Vars.push_back(Reader->Record.readSubExpr());
C->setVarRefs(Vars);
Vars.clear();
+
+ SmallVector<ValueDecl *, 16> Decls;
+ Decls.reserve(UniqueDecls);
+ for (unsigned i = 0; i < UniqueDecls; ++i)
+ Decls.push_back(Reader->Record.readDeclAs<ValueDecl>());
+ C->setUniqueDecls(Decls);
+
+ SmallVector<unsigned, 16> ListsPerDecl;
+ ListsPerDecl.reserve(UniqueDecls);
+ for (unsigned i = 0; i < UniqueDecls; ++i)
+ ListsPerDecl.push_back(Reader->Record.readInt());
+ C->setDeclNumLists(ListsPerDecl);
+
+ SmallVector<unsigned, 32> ListSizes;
+ ListSizes.reserve(TotalLists);
+ for (unsigned i = 0; i < TotalLists; ++i)
+ ListSizes.push_back(Reader->Record.readInt());
+ C->setComponentListSizes(ListSizes);
+
+ SmallVector<OMPClauseMappableExprCommon::MappableComponent, 32> Components;
+ Components.reserve(TotalComponents);
+ for (unsigned i = 0; i < TotalComponents; ++i) {
+ Expr *AssociatedExpr = Reader->Record.readSubExpr();
+ ValueDecl *AssociatedDecl = Reader->Record.readDeclAs<ValueDecl>();
+ Components.push_back(OMPClauseMappableExprCommon::MappableComponent(
+ AssociatedExpr, AssociatedDecl));
+ }
+ C->setComponents(Components, ListSizes);
}
//===----------------------------------------------------------------------===//
// OpenMP Directives.
//===----------------------------------------------------------------------===//
void ASTStmtReader::VisitOMPExecutableDirective(OMPExecutableDirective *E) {
- E->setLocStart(ReadSourceLocation(Record, Idx));
- E->setLocEnd(ReadSourceLocation(Record, Idx));
- OMPClauseReader ClauseReader(this, Reader.getContext(), Record, Idx);
+ E->setLocStart(ReadSourceLocation());
+ E->setLocEnd(ReadSourceLocation());
+ OMPClauseReader ClauseReader(this, Record);
SmallVector<OMPClause *, 5> Clauses;
for (unsigned i = 0; i < E->getNumClauses(); ++i)
Clauses.push_back(ClauseReader.readClause());
E->setClauses(Clauses);
if (E->hasAssociatedStmt())
- E->setAssociatedStmt(Reader.ReadSubStmt());
+ E->setAssociatedStmt(Record.readSubStmt());
}
void ASTStmtReader::VisitOMPLoopDirective(OMPLoopDirective *D) {
VisitStmt(D);
// Two fields (NumClauses and CollapsedNum) were read in ReadStmtFromStream.
- Idx += 2;
+ Record.skipInts(2);
VisitOMPExecutableDirective(D);
- D->setIterationVariable(Reader.ReadSubExpr());
- D->setLastIteration(Reader.ReadSubExpr());
- D->setCalcLastIteration(Reader.ReadSubExpr());
- D->setPreCond(Reader.ReadSubExpr());
- D->setCond(Reader.ReadSubExpr());
- D->setInit(Reader.ReadSubExpr());
- D->setInc(Reader.ReadSubExpr());
- D->setPreInits(Reader.ReadSubStmt());
+ D->setIterationVariable(Record.readSubExpr());
+ D->setLastIteration(Record.readSubExpr());
+ D->setCalcLastIteration(Record.readSubExpr());
+ D->setPreCond(Record.readSubExpr());
+ D->setCond(Record.readSubExpr());
+ D->setInit(Record.readSubExpr());
+ D->setInc(Record.readSubExpr());
+ D->setPreInits(Record.readSubStmt());
if (isOpenMPWorksharingDirective(D->getDirectiveKind()) ||
isOpenMPTaskLoopDirective(D->getDirectiveKind()) ||
isOpenMPDistributeDirective(D->getDirectiveKind())) {
- D->setIsLastIterVariable(Reader.ReadSubExpr());
- D->setLowerBoundVariable(Reader.ReadSubExpr());
- D->setUpperBoundVariable(Reader.ReadSubExpr());
- D->setStrideVariable(Reader.ReadSubExpr());
- D->setEnsureUpperBound(Reader.ReadSubExpr());
- D->setNextLowerBound(Reader.ReadSubExpr());
- D->setNextUpperBound(Reader.ReadSubExpr());
- D->setNumIterations(Reader.ReadSubExpr());
+ D->setIsLastIterVariable(Record.readSubExpr());
+ D->setLowerBoundVariable(Record.readSubExpr());
+ D->setUpperBoundVariable(Record.readSubExpr());
+ D->setStrideVariable(Record.readSubExpr());
+ D->setEnsureUpperBound(Record.readSubExpr());
+ D->setNextLowerBound(Record.readSubExpr());
+ D->setNextUpperBound(Record.readSubExpr());
+ D->setNumIterations(Record.readSubExpr());
}
if (isOpenMPLoopBoundSharingDirective(D->getDirectiveKind())) {
- D->setPrevLowerBoundVariable(Reader.ReadSubExpr());
- D->setPrevUpperBoundVariable(Reader.ReadSubExpr());
+ D->setPrevLowerBoundVariable(Record.readSubExpr());
+ D->setPrevUpperBoundVariable(Record.readSubExpr());
}
SmallVector<Expr *, 4> Sub;
unsigned CollapsedNum = D->getCollapsedNumber();
Sub.reserve(CollapsedNum);
for (unsigned i = 0; i < CollapsedNum; ++i)
- Sub.push_back(Reader.ReadSubExpr());
+ Sub.push_back(Record.readSubExpr());
D->setCounters(Sub);
Sub.clear();
for (unsigned i = 0; i < CollapsedNum; ++i)
- Sub.push_back(Reader.ReadSubExpr());
+ Sub.push_back(Record.readSubExpr());
D->setPrivateCounters(Sub);
Sub.clear();
for (unsigned i = 0; i < CollapsedNum; ++i)
- Sub.push_back(Reader.ReadSubExpr());
+ Sub.push_back(Record.readSubExpr());
D->setInits(Sub);
Sub.clear();
for (unsigned i = 0; i < CollapsedNum; ++i)
- Sub.push_back(Reader.ReadSubExpr());
+ Sub.push_back(Record.readSubExpr());
D->setUpdates(Sub);
Sub.clear();
for (unsigned i = 0; i < CollapsedNum; ++i)
- Sub.push_back(Reader.ReadSubExpr());
+ Sub.push_back(Record.readSubExpr());
D->setFinals(Sub);
}
void ASTStmtReader::VisitOMPParallelDirective(OMPParallelDirective *D) {
VisitStmt(D);
// The NumClauses field was read in ReadStmtFromStream.
- ++Idx;
+ Record.skipInts(1);
VisitOMPExecutableDirective(D);
- D->setHasCancel(Record[Idx++]);
+ D->setHasCancel(Record.readInt());
}
void ASTStmtReader::VisitOMPSimdDirective(OMPSimdDirective *D) {
@@ -2559,7 +2605,7 @@ void ASTStmtReader::VisitOMPSimdDirective(OMPSimdDirective *D) {
void ASTStmtReader::VisitOMPForDirective(OMPForDirective *D) {
VisitOMPLoopDirective(D);
- D->setHasCancel(Record[Idx++]);
+ D->setHasCancel(Record.readInt());
}
void ASTStmtReader::VisitOMPForSimdDirective(OMPForSimdDirective *D) {
@@ -2569,21 +2615,21 @@ void ASTStmtReader::VisitOMPForSimdDirective(OMPForSimdDirective *D) {
void ASTStmtReader::VisitOMPSectionsDirective(OMPSectionsDirective *D) {
VisitStmt(D);
// The NumClauses field was read in ReadStmtFromStream.
- ++Idx;
+ Record.skipInts(1);
VisitOMPExecutableDirective(D);
- D->setHasCancel(Record[Idx++]);
+ D->setHasCancel(Record.readInt());
}
void ASTStmtReader::VisitOMPSectionDirective(OMPSectionDirective *D) {
VisitStmt(D);
VisitOMPExecutableDirective(D);
- D->setHasCancel(Record[Idx++]);
+ D->setHasCancel(Record.readInt());
}
void ASTStmtReader::VisitOMPSingleDirective(OMPSingleDirective *D) {
VisitStmt(D);
// The NumClauses field was read in ReadStmtFromStream.
- ++Idx;
+ Record.skipInts(1);
VisitOMPExecutableDirective(D);
}
@@ -2595,14 +2641,14 @@ void ASTStmtReader::VisitOMPMasterDirective(OMPMasterDirective *D) {
void ASTStmtReader::VisitOMPCriticalDirective(OMPCriticalDirective *D) {
VisitStmt(D);
// The NumClauses field was read in ReadStmtFromStream.
- ++Idx;
+ Record.skipInts(1);
VisitOMPExecutableDirective(D);
- ReadDeclarationNameInfo(D->DirName, Record, Idx);
+ ReadDeclarationNameInfo(D->DirName);
}
void ASTStmtReader::VisitOMPParallelForDirective(OMPParallelForDirective *D) {
VisitOMPLoopDirective(D);
- D->setHasCancel(Record[Idx++]);
+ D->setHasCancel(Record.readInt());
}
void ASTStmtReader::VisitOMPParallelForSimdDirective(
@@ -2614,17 +2660,17 @@ void ASTStmtReader::VisitOMPParallelSectionsDirective(
OMPParallelSectionsDirective *D) {
VisitStmt(D);
// The NumClauses field was read in ReadStmtFromStream.
- ++Idx;
+ Record.skipInts(1);
VisitOMPExecutableDirective(D);
- D->setHasCancel(Record[Idx++]);
+ D->setHasCancel(Record.readInt());
}
void ASTStmtReader::VisitOMPTaskDirective(OMPTaskDirective *D) {
VisitStmt(D);
// The NumClauses field was read in ReadStmtFromStream.
- ++Idx;
+ Record.skipInts(1);
VisitOMPExecutableDirective(D);
- D->setHasCancel(Record[Idx++]);
+ D->setHasCancel(Record.readInt());
}
void ASTStmtReader::VisitOMPTaskyieldDirective(OMPTaskyieldDirective *D) {
@@ -2650,74 +2696,74 @@ void ASTStmtReader::VisitOMPTaskgroupDirective(OMPTaskgroupDirective *D) {
void ASTStmtReader::VisitOMPFlushDirective(OMPFlushDirective *D) {
VisitStmt(D);
// The NumClauses field was read in ReadStmtFromStream.
- ++Idx;
+ Record.skipInts(1);
VisitOMPExecutableDirective(D);
}
void ASTStmtReader::VisitOMPOrderedDirective(OMPOrderedDirective *D) {
VisitStmt(D);
// The NumClauses field was read in ReadStmtFromStream.
- ++Idx;
+ Record.skipInts(1);
VisitOMPExecutableDirective(D);
}
void ASTStmtReader::VisitOMPAtomicDirective(OMPAtomicDirective *D) {
VisitStmt(D);
// The NumClauses field was read in ReadStmtFromStream.
- ++Idx;
+ Record.skipInts(1);
VisitOMPExecutableDirective(D);
- D->setX(Reader.ReadSubExpr());
- D->setV(Reader.ReadSubExpr());
- D->setExpr(Reader.ReadSubExpr());
- D->setUpdateExpr(Reader.ReadSubExpr());
- D->IsXLHSInRHSPart = Record[Idx++] != 0;
- D->IsPostfixUpdate = Record[Idx++] != 0;
+ D->setX(Record.readSubExpr());
+ D->setV(Record.readSubExpr());
+ D->setExpr(Record.readSubExpr());
+ D->setUpdateExpr(Record.readSubExpr());
+ D->IsXLHSInRHSPart = Record.readInt() != 0;
+ D->IsPostfixUpdate = Record.readInt() != 0;
}
void ASTStmtReader::VisitOMPTargetDirective(OMPTargetDirective *D) {
VisitStmt(D);
// The NumClauses field was read in ReadStmtFromStream.
- ++Idx;
+ Record.skipInts(1);
VisitOMPExecutableDirective(D);
}
void ASTStmtReader::VisitOMPTargetDataDirective(OMPTargetDataDirective *D) {
VisitStmt(D);
- ++Idx;
+ Record.skipInts(1);
VisitOMPExecutableDirective(D);
}
void ASTStmtReader::VisitOMPTargetEnterDataDirective(
OMPTargetEnterDataDirective *D) {
VisitStmt(D);
- ++Idx;
+ Record.skipInts(1);
VisitOMPExecutableDirective(D);
}
void ASTStmtReader::VisitOMPTargetExitDataDirective(
OMPTargetExitDataDirective *D) {
VisitStmt(D);
- ++Idx;
+ Record.skipInts(1);
VisitOMPExecutableDirective(D);
}
void ASTStmtReader::VisitOMPTargetParallelDirective(
OMPTargetParallelDirective *D) {
VisitStmt(D);
- ++Idx;
+ Record.skipInts(1);
VisitOMPExecutableDirective(D);
}
void ASTStmtReader::VisitOMPTargetParallelForDirective(
OMPTargetParallelForDirective *D) {
VisitOMPLoopDirective(D);
- D->setHasCancel(Record[Idx++]);
+ D->setHasCancel(Record.readInt());
}
void ASTStmtReader::VisitOMPTeamsDirective(OMPTeamsDirective *D) {
VisitStmt(D);
// The NumClauses field was read in ReadStmtFromStream.
- ++Idx;
+ Record.skipInts(1);
VisitOMPExecutableDirective(D);
}
@@ -2725,15 +2771,15 @@ void ASTStmtReader::VisitOMPCancellationPointDirective(
OMPCancellationPointDirective *D) {
VisitStmt(D);
VisitOMPExecutableDirective(D);
- D->setCancelRegion(static_cast<OpenMPDirectiveKind>(Record[Idx++]));
+ D->setCancelRegion(static_cast<OpenMPDirectiveKind>(Record.readInt()));
}
void ASTStmtReader::VisitOMPCancelDirective(OMPCancelDirective *D) {
VisitStmt(D);
// The NumClauses field was read in ReadStmtFromStream.
- ++Idx;
+ Record.skipInts(1);
VisitOMPExecutableDirective(D);
- D->setCancelRegion(static_cast<OpenMPDirectiveKind>(Record[Idx++]));
+ D->setCancelRegion(static_cast<OpenMPDirectiveKind>(Record.readInt()));
}
void ASTStmtReader::VisitOMPTaskLoopDirective(OMPTaskLoopDirective *D) {
@@ -2750,7 +2796,7 @@ void ASTStmtReader::VisitOMPDistributeDirective(OMPDistributeDirective *D) {
void ASTStmtReader::VisitOMPTargetUpdateDirective(OMPTargetUpdateDirective *D) {
VisitStmt(D);
- ++Idx;
+ Record.skipInts(1);
VisitOMPExecutableDirective(D);
}
void ASTStmtReader::VisitOMPDistributeParallelForDirective(
@@ -2773,6 +2819,47 @@ void ASTStmtReader::VisitOMPTargetParallelForSimdDirective(
VisitOMPLoopDirective(D);
}
+void ASTStmtReader::VisitOMPTargetSimdDirective(OMPTargetSimdDirective *D) {
+ VisitOMPLoopDirective(D);
+}
+
+void ASTStmtReader::VisitOMPTeamsDistributeDirective(
+ OMPTeamsDistributeDirective *D) {
+ VisitOMPLoopDirective(D);
+}
+
+void ASTStmtReader::VisitOMPTeamsDistributeSimdDirective(
+ OMPTeamsDistributeSimdDirective *D) {
+ VisitOMPLoopDirective(D);
+}
+
+void ASTStmtReader::VisitOMPTeamsDistributeParallelForSimdDirective(
+ OMPTeamsDistributeParallelForSimdDirective *D) {
+ VisitOMPLoopDirective(D);
+}
+
+void ASTStmtReader::VisitOMPTeamsDistributeParallelForDirective(
+ OMPTeamsDistributeParallelForDirective *D) {
+ VisitOMPLoopDirective(D);
+}
+
+void ASTStmtReader::VisitOMPTargetTeamsDirective(OMPTargetTeamsDirective *D) {
+ VisitStmt(D);
+ // The NumClauses field was read in ReadStmtFromStream.
+ Record.skipInts(1);
+ VisitOMPExecutableDirective(D);
+}
+
+void ASTStmtReader::VisitOMPTargetTeamsDistributeDirective(
+ OMPTargetTeamsDistributeDirective *D) {
+ VisitOMPLoopDirective(D);
+}
+
+void ASTStmtReader::VisitOMPTargetTeamsDistributeParallelForDirective(
+ OMPTargetTeamsDistributeParallelForDirective *D) {
+ VisitOMPLoopDirective(D);
+}
+
//===----------------------------------------------------------------------===//
// ASTReader Implementation
//===----------------------------------------------------------------------===//
@@ -2810,7 +2897,7 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
ReadingKindTracker ReadingKind(Read_Stmt, *this);
llvm::BitstreamCursor &Cursor = F.DeclsCursor;
-
+
// Map of offset to previously deserialized stmt. The offset points
/// just after the stmt record.
llvm::DenseMap<uint64_t, Stmt *> StmtEntries;
@@ -2819,14 +2906,13 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
unsigned PrevNumStmts = StmtStack.size();
#endif
- RecordData Record;
- unsigned Idx;
- ASTStmtReader Reader(*this, F, Cursor, Record, Idx);
+ ASTRecordReader Record(*this, F);
+ ASTStmtReader Reader(Record, Cursor);
Stmt::EmptyShell Empty;
while (true) {
llvm::BitstreamEntry Entry = Cursor.advanceSkippingSubblocks();
-
+
switch (Entry.Kind) {
case llvm::BitstreamEntry::SubBlock: // Handled for us already.
case llvm::BitstreamEntry::Error:
@@ -2840,11 +2926,9 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
}
Stmt *S = nullptr;
- Idx = 0;
- Record.clear();
bool Finished = false;
bool IsStmtReference = false;
- switch ((StmtCode)Cursor.readRecord(Entry.ID, Record)) {
+ switch ((StmtCode)Record.readRecord(Cursor, Entry.ID)) {
case STMT_STOP:
Finished = true;
break;
@@ -2853,7 +2937,7 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
IsStmtReference = true;
assert(StmtEntries.find(Record[0]) != StmtEntries.end() &&
"No stmt was recorded for this offset reference!");
- S = StmtEntries[Record[Idx++]];
+ S = StmtEntries[Record.readInt()];
break;
case STMT_NULL_PTR:
@@ -2991,11 +3075,11 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
break;
case EXPR_OFFSETOF:
- S = OffsetOfExpr::CreateEmpty(Context,
+ S = OffsetOfExpr::CreateEmpty(Context,
Record[ASTStmtReader::NumExprFields],
Record[ASTStmtReader::NumExprFields + 1]);
break;
-
+
case EXPR_SIZEOF_ALIGN_OF:
S = new (Context) UnaryExprOrTypeTraitExpr(Empty);
break;
@@ -3017,46 +3101,46 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
// That way we can use MemberExpr::Create and don't have to duplicate its
// logic with a MemberExpr::CreateEmpty.
- assert(Idx == 0);
+ assert(Record.getIdx() == 0);
NestedNameSpecifierLoc QualifierLoc;
- if (Record[Idx++]) { // HasQualifier.
- QualifierLoc = ReadNestedNameSpecifierLoc(F, Record, Idx);
+ if (Record.readInt()) { // HasQualifier.
+ QualifierLoc = Record.readNestedNameSpecifierLoc();
}
SourceLocation TemplateKWLoc;
TemplateArgumentListInfo ArgInfo;
- bool HasTemplateKWAndArgsInfo = Record[Idx++];
+ bool HasTemplateKWAndArgsInfo = Record.readInt();
if (HasTemplateKWAndArgsInfo) {
- TemplateKWLoc = ReadSourceLocation(F, Record, Idx);
- unsigned NumTemplateArgs = Record[Idx++];
- ArgInfo.setLAngleLoc(ReadSourceLocation(F, Record, Idx));
- ArgInfo.setRAngleLoc(ReadSourceLocation(F, Record, Idx));
+ TemplateKWLoc = Record.readSourceLocation();
+ unsigned NumTemplateArgs = Record.readInt();
+ ArgInfo.setLAngleLoc(Record.readSourceLocation());
+ ArgInfo.setRAngleLoc(Record.readSourceLocation());
for (unsigned i = 0; i != NumTemplateArgs; ++i)
- ArgInfo.addArgument(ReadTemplateArgumentLoc(F, Record, Idx));
+ ArgInfo.addArgument(Record.readTemplateArgumentLoc());
}
- bool HadMultipleCandidates = Record[Idx++];
+ bool HadMultipleCandidates = Record.readInt();
- NamedDecl *FoundD = ReadDeclAs<NamedDecl>(F, Record, Idx);
- AccessSpecifier AS = (AccessSpecifier)Record[Idx++];
+ NamedDecl *FoundD = Record.readDeclAs<NamedDecl>();
+ AccessSpecifier AS = (AccessSpecifier)Record.readInt();
DeclAccessPair FoundDecl = DeclAccessPair::make(FoundD, AS);
- QualType T = readType(F, Record, Idx);
- ExprValueKind VK = static_cast<ExprValueKind>(Record[Idx++]);
- ExprObjectKind OK = static_cast<ExprObjectKind>(Record[Idx++]);
+ QualType T = Record.readType();
+ ExprValueKind VK = static_cast<ExprValueKind>(Record.readInt());
+ ExprObjectKind OK = static_cast<ExprObjectKind>(Record.readInt());
Expr *Base = ReadSubExpr();
- ValueDecl *MemberD = ReadDeclAs<ValueDecl>(F, Record, Idx);
- SourceLocation MemberLoc = ReadSourceLocation(F, Record, Idx);
+ ValueDecl *MemberD = Record.readDeclAs<ValueDecl>();
+ SourceLocation MemberLoc = Record.readSourceLocation();
DeclarationNameInfo MemberNameInfo(MemberD->getDeclName(), MemberLoc);
- bool IsArrow = Record[Idx++];
- SourceLocation OperatorLoc = ReadSourceLocation(F, Record, Idx);
+ bool IsArrow = Record.readInt();
+ SourceLocation OperatorLoc = Record.readSourceLocation();
S = MemberExpr::Create(Context, Base, IsArrow, OperatorLoc, QualifierLoc,
TemplateKWLoc, MemberD, FoundDecl, MemberNameInfo,
HasTemplateKWAndArgsInfo ? &ArgInfo : nullptr, T,
VK, OK);
- ReadDeclarationNameLoc(F, cast<MemberExpr>(S)->MemberDNLoc,
- MemberD->getDeclName(), Record, Idx);
+ Record.readDeclarationNameLoc(cast<MemberExpr>(S)->MemberDNLoc,
+ MemberD->getDeclName());
if (HadMultipleCandidates)
cast<MemberExpr>(S)->setHadMultipleCandidates(true);
break;
@@ -3118,6 +3202,14 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
S = new (Context) NoInitExpr(Empty);
break;
+ case EXPR_ARRAY_INIT_LOOP:
+ S = new (Context) ArrayInitLoopExpr(Empty);
+ break;
+
+ case EXPR_ARRAY_INIT_INDEX:
+ S = new (Context) ArrayInitIndexExpr(Empty);
+ break;
+
case EXPR_VA_ARG:
S = new (Context) VAArgExpr(Empty);
break;
@@ -3213,7 +3305,7 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
S = new (Context) ObjCAtFinallyStmt(Empty);
break;
case STMT_OBJC_AT_TRY:
- S = ObjCAtTryStmt::CreateEmpty(Context,
+ S = ObjCAtTryStmt::CreateEmpty(Context,
Record[ASTStmtReader::NumStmtFields],
Record[ASTStmtReader::NumStmtFields + 1]);
break;
@@ -3484,6 +3576,68 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
break;
}
+ case STMT_OMP_TARGET_SIMD_DIRECTIVE: {
+ auto NumClauses = Record[ASTStmtReader::NumStmtFields];
+ auto CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1];
+ S = OMPTargetSimdDirective::CreateEmpty(Context, NumClauses, CollapsedNum,
+ Empty);
+ break;
+ }
+
+ case STMT_OMP_TEAMS_DISTRIBUTE_DIRECTIVE: {
+ auto NumClauses = Record[ASTStmtReader::NumStmtFields];
+ auto CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1];
+ S = OMPTeamsDistributeDirective::CreateEmpty(Context, NumClauses,
+ CollapsedNum, Empty);
+ break;
+ }
+
+ case STMT_OMP_TEAMS_DISTRIBUTE_SIMD_DIRECTIVE: {
+ unsigned NumClauses = Record[ASTStmtReader::NumStmtFields];
+ unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1];
+ S = OMPTeamsDistributeSimdDirective::CreateEmpty(Context, NumClauses,
+ CollapsedNum, Empty);
+ break;
+ }
+
+ case STMT_OMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_DIRECTIVE: {
+ auto NumClauses = Record[ASTStmtReader::NumStmtFields];
+ auto CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1];
+ S = OMPTeamsDistributeParallelForSimdDirective::CreateEmpty(
+ Context, NumClauses, CollapsedNum, Empty);
+ break;
+ }
+
+ case STMT_OMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_DIRECTIVE: {
+ auto NumClauses = Record[ASTStmtReader::NumStmtFields];
+ auto CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1];
+ S = OMPTeamsDistributeParallelForDirective::CreateEmpty(
+ Context, NumClauses, CollapsedNum, Empty);
+ break;
+ }
+
+ 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];
+ auto CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1];
+ S = OMPTargetTeamsDistributeDirective::CreateEmpty(Context, NumClauses,
+ CollapsedNum, Empty);
+ break;
+ }
+
+ case STMT_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_DIRECTIVE: {
+ auto NumClauses = Record[ASTStmtReader::NumStmtFields];
+ auto CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1];
+ S = OMPTargetTeamsDistributeParallelForDirective::CreateEmpty(
+ Context, NumClauses, CollapsedNum, Empty);
+ break;
+ }
+
case EXPR_CXX_OPERATOR_CALL:
S = new (Context) CXXOperatorCallExpr(Context, Empty);
break;
@@ -3576,7 +3730,7 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
case EXPR_CXX_BIND_TEMPORARY:
S = new (Context) CXXBindTemporaryExpr(Empty);
break;
-
+
case EXPR_CXX_SCALAR_VALUE_INIT:
S = new (Context) CXXScalarValueInitExpr(Empty);
break;
@@ -3589,54 +3743,54 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
case EXPR_CXX_PSEUDO_DESTRUCTOR:
S = new (Context) CXXPseudoDestructorExpr(Empty);
break;
-
+
case EXPR_EXPR_WITH_CLEANUPS:
S = ExprWithCleanups::Create(Context, Empty,
Record[ASTStmtReader::NumExprFields]);
break;
-
+
case EXPR_CXX_DEPENDENT_SCOPE_MEMBER:
S = CXXDependentScopeMemberExpr::CreateEmpty(Context,
/*HasTemplateKWAndArgsInfo=*/Record[ASTStmtReader::NumExprFields],
/*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields]
- ? Record[ASTStmtReader::NumExprFields + 1]
+ ? Record[ASTStmtReader::NumExprFields + 1]
: 0);
break;
-
+
case EXPR_CXX_DEPENDENT_SCOPE_DECL_REF:
S = DependentScopeDeclRefExpr::CreateEmpty(Context,
/*HasTemplateKWAndArgsInfo=*/Record[ASTStmtReader::NumExprFields],
/*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields]
- ? Record[ASTStmtReader::NumExprFields + 1]
+ ? Record[ASTStmtReader::NumExprFields + 1]
: 0);
break;
-
+
case EXPR_CXX_UNRESOLVED_CONSTRUCT:
S = CXXUnresolvedConstructExpr::CreateEmpty(Context,
/*NumArgs=*/Record[ASTStmtReader::NumExprFields]);
break;
-
+
case EXPR_CXX_UNRESOLVED_MEMBER:
S = UnresolvedMemberExpr::CreateEmpty(Context,
/*HasTemplateKWAndArgsInfo=*/Record[ASTStmtReader::NumExprFields],
/*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields]
- ? Record[ASTStmtReader::NumExprFields + 1]
+ ? Record[ASTStmtReader::NumExprFields + 1]
: 0);
break;
-
+
case EXPR_CXX_UNRESOLVED_LOOKUP:
S = UnresolvedLookupExpr::CreateEmpty(Context,
/*HasTemplateKWAndArgsInfo=*/Record[ASTStmtReader::NumExprFields],
/*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields]
- ? Record[ASTStmtReader::NumExprFields + 1]
+ ? Record[ASTStmtReader::NumExprFields + 1]
: 0);
break;
case EXPR_TYPE_TRAIT:
- S = TypeTraitExpr::CreateDeserialized(Context,
+ S = TypeTraitExpr::CreateDeserialized(Context,
Record[ASTStmtReader::NumExprFields]);
break;
-
+
case EXPR_ARRAY_TYPE_TRAIT:
S = new (Context) ArrayTypeTraitExpr(Empty);
break;
@@ -3652,17 +3806,17 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
case EXPR_PACK_EXPANSION:
S = new (Context) PackExpansionExpr(Empty);
break;
-
+
case EXPR_SIZEOF_PACK:
S = SizeOfPackExpr::CreateDeserialized(
Context,
/*NumPartialArgs=*/Record[ASTStmtReader::NumExprFields]);
break;
-
+
case EXPR_SUBST_NON_TYPE_TEMPLATE_PARM:
S = new (Context) SubstNonTypeTemplateParmExpr(Empty);
break;
-
+
case EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK:
S = new (Context) SubstNonTypeTemplateParmPackExpr(Empty);
break;
@@ -3671,7 +3825,7 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
S = FunctionParmPackExpr::CreateEmpty(Context,
Record[ASTStmtReader::NumExprFields]);
break;
-
+
case EXPR_MATERIALIZE_TEMPORARY:
S = new (Context) MaterializeTemporaryExpr(Empty);
break;
@@ -3687,7 +3841,7 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
case EXPR_CUDA_KERNEL_CALL:
S = new (Context) CUDAKernelCallExpr(Context, Empty);
break;
-
+
case EXPR_ASTYPE:
S = new (Context) AsTypeExpr(Empty);
break;
@@ -3701,16 +3855,14 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
case EXPR_ATOMIC:
S = new (Context) AtomicExpr(Empty);
break;
-
+
case EXPR_LAMBDA: {
unsigned NumCaptures = Record[ASTStmtReader::NumExprFields];
- unsigned NumArrayIndexVars = Record[ASTStmtReader::NumExprFields + 1];
- S = LambdaExpr::CreateDeserialized(Context, NumCaptures,
- NumArrayIndexVars);
+ S = LambdaExpr::CreateDeserialized(Context, NumCaptures);
break;
}
}
-
+
// We hit a STMT_STOP, so we're done with this expression.
if (Finished)
break;
@@ -3722,8 +3874,8 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
StmtEntries[Cursor.GetCurrentBitNo()] = S;
}
-
- assert(Idx == Record.size() && "Invalid deserialization of statement");
+ assert(Record.getIdx() == Record.size() &&
+ "Invalid deserialization of statement");
StmtStack.push_back(S);
}
Done:
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index 7589b0c5dd52..6d79ea53b659 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -12,23 +12,31 @@
//===----------------------------------------------------------------------===//
#include "clang/Serialization/ASTWriter.h"
-#include "clang/Serialization/ModuleFileExtension.h"
#include "ASTCommon.h"
#include "ASTReaderInternals.h"
#include "MultiOnDiskHashTable.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTUnresolvedSet.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclContextInternals.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclFriend.h"
-#include "clang/AST/DeclLookups.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
+#include "clang/AST/LambdaCapture.h"
+#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/RawCommentList.h"
+#include "clang/AST/TemplateName.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeLocVisitor.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/FileManager.h"
-#include "clang/Basic/FileSystemStatCache.h"
+#include "clang/Basic/FileSystemOptions.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/Module.h"
+#include "clang/Basic/ObjCRuntime.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/SourceManagerInternals.h"
#include "clang/Basic/TargetInfo.h"
@@ -38,28 +46,48 @@
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/ModuleMap.h"
#include "clang/Lex/PreprocessingRecord.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/PreprocessorOptions.h"
+#include "clang/Lex/Token.h"
#include "clang/Sema/IdentifierResolver.h"
+#include "clang/Sema/ObjCMethodList.h"
#include "clang/Sema/Sema.h"
+#include "clang/Sema/Weak.h"
#include "clang/Serialization/ASTReader.h"
+#include "clang/Serialization/Module.h"
+#include "clang/Serialization/ModuleFileExtension.h"
#include "clang/Serialization/SerializationDiagnostic.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/Bitcode/BitCodes.h"
#include "llvm/Bitcode/BitstreamWriter.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/Compression.h"
#include "llvm/Support/EndianStream.h"
-#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/OnDiskHashTable.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
+#include "llvm/Support/raw_ostream.h"
#include <algorithm>
-#include <cstdio>
-#include <string.h>
+#include <cassert>
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+#include <deque>
+#include <limits>
+#include <new>
+#include <tuple>
#include <utility>
using namespace clang;
@@ -83,6 +111,7 @@ static StringRef bytes(const SmallVectorImpl<T> &v) {
//===----------------------------------------------------------------------===//
namespace clang {
+
class ASTTypeWriter {
ASTWriter &Writer;
ASTRecordWriter Record;
@@ -127,6 +156,7 @@ namespace clang {
#define ABSTRACT_TYPE(Class, Base)
#include "clang/AST/TypeNodes.def"
};
+
} // end namespace clang
void ASTTypeWriter::VisitBuiltinType(const BuiltinType *T) {
@@ -451,6 +481,14 @@ void ASTTypeWriter::VisitObjCInterfaceType(const ObjCInterfaceType *T) {
Code = TYPE_OBJC_INTERFACE;
}
+void ASTTypeWriter::VisitObjCTypeParamType(const ObjCTypeParamType *T) {
+ Record.AddDeclRef(T->getDecl());
+ Record.push_back(T->getNumProtocols());
+ for (const auto *I : T->quals())
+ Record.AddDeclRef(I);
+ Code = TYPE_OBJC_TYPE_PARAM;
+}
+
void ASTTypeWriter::VisitObjCObjectType(const ObjCObjectType *T) {
Record.AddTypeRef(T->getBaseType());
Record.push_back(T->getTypeArgsAsWritten().size());
@@ -478,6 +516,7 @@ ASTTypeWriter::VisitAtomicType(const AtomicType *T) {
void
ASTTypeWriter::VisitPipeType(const PipeType *T) {
Record.AddTypeRef(T->getElementType());
+ Record.push_back(T->isReadOnly());
Code = TYPE_PIPE;
}
@@ -504,6 +543,7 @@ public:
void TypeLocWriter::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
// nothing to do
}
+
void TypeLocWriter::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
Record.AddSourceLocation(TL.getBuiltinLoc());
if (TL.needsExtraLocalData()) {
@@ -513,31 +553,40 @@ void TypeLocWriter::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
Record.push_back(TL.hasModeAttr());
}
}
+
void TypeLocWriter::VisitComplexTypeLoc(ComplexTypeLoc TL) {
Record.AddSourceLocation(TL.getNameLoc());
}
+
void TypeLocWriter::VisitPointerTypeLoc(PointerTypeLoc TL) {
Record.AddSourceLocation(TL.getStarLoc());
}
+
void TypeLocWriter::VisitDecayedTypeLoc(DecayedTypeLoc TL) {
// nothing to do
}
+
void TypeLocWriter::VisitAdjustedTypeLoc(AdjustedTypeLoc TL) {
// nothing to do
}
+
void TypeLocWriter::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
Record.AddSourceLocation(TL.getCaretLoc());
}
+
void TypeLocWriter::VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {
Record.AddSourceLocation(TL.getAmpLoc());
}
+
void TypeLocWriter::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) {
Record.AddSourceLocation(TL.getAmpAmpLoc());
}
+
void TypeLocWriter::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
Record.AddSourceLocation(TL.getStarLoc());
Record.AddTypeSourceInfo(TL.getClassTInfo());
}
+
void TypeLocWriter::VisitArrayTypeLoc(ArrayTypeLoc TL) {
Record.AddSourceLocation(TL.getLBracketLoc());
Record.AddSourceLocation(TL.getRBracketLoc());
@@ -545,29 +594,37 @@ void TypeLocWriter::VisitArrayTypeLoc(ArrayTypeLoc TL) {
if (TL.getSizeExpr())
Record.AddStmt(TL.getSizeExpr());
}
+
void TypeLocWriter::VisitConstantArrayTypeLoc(ConstantArrayTypeLoc TL) {
VisitArrayTypeLoc(TL);
}
+
void TypeLocWriter::VisitIncompleteArrayTypeLoc(IncompleteArrayTypeLoc TL) {
VisitArrayTypeLoc(TL);
}
+
void TypeLocWriter::VisitVariableArrayTypeLoc(VariableArrayTypeLoc TL) {
VisitArrayTypeLoc(TL);
}
+
void TypeLocWriter::VisitDependentSizedArrayTypeLoc(
DependentSizedArrayTypeLoc TL) {
VisitArrayTypeLoc(TL);
}
+
void TypeLocWriter::VisitDependentSizedExtVectorTypeLoc(
DependentSizedExtVectorTypeLoc TL) {
Record.AddSourceLocation(TL.getNameLoc());
}
+
void TypeLocWriter::VisitVectorTypeLoc(VectorTypeLoc TL) {
Record.AddSourceLocation(TL.getNameLoc());
}
+
void TypeLocWriter::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) {
Record.AddSourceLocation(TL.getNameLoc());
}
+
void TypeLocWriter::VisitFunctionTypeLoc(FunctionTypeLoc TL) {
Record.AddSourceLocation(TL.getLocalRangeBegin());
Record.AddSourceLocation(TL.getLParenLoc());
@@ -588,35 +645,50 @@ void TypeLocWriter::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) {
void TypeLocWriter::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
Record.AddSourceLocation(TL.getNameLoc());
}
+void TypeLocWriter::VisitObjCTypeParamTypeLoc(ObjCTypeParamTypeLoc TL) {
+ if (TL.getNumProtocols()) {
+ Record.AddSourceLocation(TL.getProtocolLAngleLoc());
+ Record.AddSourceLocation(TL.getProtocolRAngleLoc());
+ }
+ for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)
+ Record.AddSourceLocation(TL.getProtocolLoc(i));
+}
void TypeLocWriter::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
Record.AddSourceLocation(TL.getTypeofLoc());
Record.AddSourceLocation(TL.getLParenLoc());
Record.AddSourceLocation(TL.getRParenLoc());
}
+
void TypeLocWriter::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
Record.AddSourceLocation(TL.getTypeofLoc());
Record.AddSourceLocation(TL.getLParenLoc());
Record.AddSourceLocation(TL.getRParenLoc());
Record.AddTypeSourceInfo(TL.getUnderlyingTInfo());
}
+
void TypeLocWriter::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {
Record.AddSourceLocation(TL.getNameLoc());
}
+
void TypeLocWriter::VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc TL) {
Record.AddSourceLocation(TL.getKWLoc());
Record.AddSourceLocation(TL.getLParenLoc());
Record.AddSourceLocation(TL.getRParenLoc());
Record.AddTypeSourceInfo(TL.getUnderlyingTInfo());
}
+
void TypeLocWriter::VisitAutoTypeLoc(AutoTypeLoc TL) {
Record.AddSourceLocation(TL.getNameLoc());
}
+
void TypeLocWriter::VisitRecordTypeLoc(RecordTypeLoc TL) {
Record.AddSourceLocation(TL.getNameLoc());
}
+
void TypeLocWriter::VisitEnumTypeLoc(EnumTypeLoc TL) {
Record.AddSourceLocation(TL.getNameLoc());
}
+
void TypeLocWriter::VisitAttributedTypeLoc(AttributedTypeLoc TL) {
Record.AddSourceLocation(TL.getAttrNameLoc());
if (TL.hasAttrOperand()) {
@@ -632,17 +704,21 @@ void TypeLocWriter::VisitAttributedTypeLoc(AttributedTypeLoc TL) {
Record.AddSourceLocation(TL.getAttrEnumOperandLoc());
}
}
+
void TypeLocWriter::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
Record.AddSourceLocation(TL.getNameLoc());
}
+
void TypeLocWriter::VisitSubstTemplateTypeParmTypeLoc(
SubstTemplateTypeParmTypeLoc TL) {
Record.AddSourceLocation(TL.getNameLoc());
}
+
void TypeLocWriter::VisitSubstTemplateTypeParmPackTypeLoc(
SubstTemplateTypeParmPackTypeLoc TL) {
Record.AddSourceLocation(TL.getNameLoc());
}
+
void TypeLocWriter::VisitTemplateSpecializationTypeLoc(
TemplateSpecializationTypeLoc TL) {
Record.AddSourceLocation(TL.getTemplateKeywordLoc());
@@ -653,22 +729,27 @@ void TypeLocWriter::VisitTemplateSpecializationTypeLoc(
Record.AddTemplateArgumentLocInfo(TL.getArgLoc(i).getArgument().getKind(),
TL.getArgLoc(i).getLocInfo());
}
+
void TypeLocWriter::VisitParenTypeLoc(ParenTypeLoc TL) {
Record.AddSourceLocation(TL.getLParenLoc());
Record.AddSourceLocation(TL.getRParenLoc());
}
+
void TypeLocWriter::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {
Record.AddSourceLocation(TL.getElaboratedKeywordLoc());
Record.AddNestedNameSpecifierLoc(TL.getQualifierLoc());
}
+
void TypeLocWriter::VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) {
Record.AddSourceLocation(TL.getNameLoc());
}
+
void TypeLocWriter::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {
Record.AddSourceLocation(TL.getElaboratedKeywordLoc());
Record.AddNestedNameSpecifierLoc(TL.getQualifierLoc());
Record.AddSourceLocation(TL.getNameLoc());
}
+
void TypeLocWriter::VisitDependentTemplateSpecializationTypeLoc(
DependentTemplateSpecializationTypeLoc TL) {
Record.AddSourceLocation(TL.getElaboratedKeywordLoc());
@@ -681,12 +762,15 @@ void TypeLocWriter::VisitDependentTemplateSpecializationTypeLoc(
Record.AddTemplateArgumentLocInfo(TL.getArgLoc(I).getArgument().getKind(),
TL.getArgLoc(I).getLocInfo());
}
+
void TypeLocWriter::VisitPackExpansionTypeLoc(PackExpansionTypeLoc TL) {
Record.AddSourceLocation(TL.getEllipsisLoc());
}
+
void TypeLocWriter::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
Record.AddSourceLocation(TL.getNameLoc());
}
+
void TypeLocWriter::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
Record.push_back(TL.hasBaseTypeAsWritten());
Record.AddSourceLocation(TL.getTypeArgsLAngleLoc());
@@ -698,14 +782,17 @@ void TypeLocWriter::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)
Record.AddSourceLocation(TL.getProtocolLoc(i));
}
+
void TypeLocWriter::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
Record.AddSourceLocation(TL.getStarLoc());
}
+
void TypeLocWriter::VisitAtomicTypeLoc(AtomicTypeLoc TL) {
Record.AddSourceLocation(TL.getKWLoc());
Record.AddSourceLocation(TL.getLParenLoc());
Record.AddSourceLocation(TL.getRParenLoc());
}
+
void TypeLocWriter::VisitPipeTypeLoc(PipeTypeLoc TL) {
Record.AddSourceLocation(TL.getKWLoc());
}
@@ -905,7 +992,7 @@ static void AddStmtsExprs(llvm::BitstreamWriter &Stream,
void ASTWriter::WriteBlockInfoBlock() {
RecordData Record;
- Stream.EnterSubblock(llvm::bitc::BLOCKINFO_BLOCK_ID, 3);
+ Stream.EnterBlockInfoBlock();
#define BLOCK(X) EmitBlockID(X ## _ID, #X, Stream, Record)
#define RECORD(X) EmitRecordID(X, #X, Stream, Record)
@@ -966,6 +1053,8 @@ void ASTWriter::WriteBlockInfoBlock() {
RECORD(HEADER_SEARCH_TABLE);
RECORD(FP_PRAGMA_OPTIONS);
RECORD(OPENCL_EXTENSIONS);
+ RECORD(OPENCL_EXTENSION_TYPES);
+ RECORD(OPENCL_EXTENSION_DECLS);
RECORD(DELEGATING_CTORS);
RECORD(KNOWN_NAMESPACES);
RECORD(MODULE_OFFSET_MAP);
@@ -983,6 +1072,7 @@ void ASTWriter::WriteBlockInfoBlock() {
RECORD(POINTERS_TO_MEMBERS_PRAGMA_OPTIONS);
RECORD(UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES);
RECORD(DELETE_EXPRS_TO_ANALYZE);
+ RECORD(CUDA_PRAGMA_FORCE_HOST_DEVICE_DEPTH);
// SourceManager Block.
BLOCK(SOURCE_MANAGER_BLOCK);
@@ -1018,6 +1108,7 @@ void ASTWriter::WriteBlockInfoBlock() {
RECORD(SUBMODULE_PRIVATE_HEADER);
RECORD(SUBMODULE_TEXTUAL_HEADER);
RECORD(SUBMODULE_PRIVATE_TEXTUAL_HEADER);
+ RECORD(SUBMODULE_INITIALIZERS);
// Comments Block.
BLOCK(COMMENTS_BLOCK);
@@ -1066,6 +1157,7 @@ void ASTWriter::WriteBlockInfoBlock() {
RECORD(TYPE_ATOMIC);
RECORD(TYPE_DECAYED);
RECORD(TYPE_ADJUSTED);
+ RECORD(TYPE_OBJC_TYPE_PARAM);
RECORD(LOCAL_REDECLARATIONS);
RECORD(DECL_TYPEDEF);
RECORD(DECL_TYPEALIAS);
@@ -1212,7 +1304,7 @@ adjustFilenameForRelocatableAST(const char *Filename, StringRef BaseDir) {
}
static ASTFileSignature getSignature() {
- while (1) {
+ while (true) {
if (ASTFileSignature S = llvm::sys::Process::GetRandomNumber())
return S;
// Rely on GetRandomNumber to eventually return non-zero...
@@ -1534,6 +1626,7 @@ uint64_t ASTWriter::WriteControlBlock(Preprocessor &PP,
}
namespace {
+
/// \brief An input file.
struct InputFileEntry {
const FileEntry *File;
@@ -1541,6 +1634,7 @@ namespace {
bool IsTransient;
bool BufferOverridden;
};
+
} // end anonymous namespace
void ASTWriter::WriteInputFiles(SourceManager &SourceMgr,
@@ -1701,6 +1795,7 @@ static unsigned CreateSLocExpansionAbbrev(llvm::BitstreamWriter &Stream) {
}
namespace {
+
// Trait used for the on-disk hash table of header search information.
class HeaderFileInfoTrait {
ASTWriter &Writer;
@@ -1716,7 +1811,7 @@ namespace {
struct key_type {
const FileEntry *FE;
- const char *Filename;
+ StringRef Filename;
};
typedef const key_type &key_type_ref;
@@ -1737,7 +1832,7 @@ namespace {
EmitKeyDataLength(raw_ostream& Out, key_type_ref key, data_type_ref Data) {
using namespace llvm::support;
endian::Writer<little> LE(Out);
- unsigned KeyLen = strlen(key.Filename) + 1 + 8 + 8;
+ unsigned KeyLen = key.Filename.size() + 1 + 8 + 8;
LE.write<uint16_t>(KeyLen);
unsigned DataLen = 1 + 2 + 4 + 4;
for (auto ModInfo : HS.getModuleMap().findAllModulesForHeader(key.FE))
@@ -1754,7 +1849,7 @@ namespace {
KeyLen -= 8;
LE.write<uint64_t>(Writer.getTimestampForOutput(key.FE));
KeyLen -= 8;
- Out.write(key.Filename, KeyLen);
+ Out.write(key.Filename.data(), KeyLen);
}
void EmitData(raw_ostream &Out, key_type_ref key,
@@ -1809,6 +1904,7 @@ namespace {
const char *strings_begin() const { return FrameworkStringData.begin(); }
const char *strings_end() const { return FrameworkStringData.end(); }
};
+
} // end anonymous namespace
/// \brief Write the header search block for the list of files that
@@ -1842,13 +1938,13 @@ void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) {
continue;
// Massage the file path into an appropriate form.
- const char *Filename = File->getName();
+ StringRef Filename = File->getName();
SmallString<128> FilenameTmp(Filename);
if (PreparePathForOutput(FilenameTmp)) {
// If we performed any translation on the file name at all, we need to
// save this string, since the generator will refer to it later.
- Filename = strdup(FilenameTmp.c_str());
- SavedStrings.push_back(Filename);
+ Filename = StringRef(strdup(FilenameTmp.c_str()));
+ SavedStrings.push_back(Filename.data());
}
HeaderFileInfoTrait::key_type key = { File, Filename };
@@ -1982,14 +2078,13 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
// the reader side).
const llvm::MemoryBuffer *Buffer
= Content->getBuffer(PP.getDiagnostics(), PP.getSourceManager());
- const char *Name = Buffer->getBufferIdentifier();
+ StringRef Name = Buffer->getBufferIdentifier();
Stream.EmitRecordWithBlob(SLocBufferAbbrv, Record,
- StringRef(Name, strlen(Name) + 1));
+ StringRef(Name.data(), Name.size() + 1));
EmitBlob = true;
- if (strcmp(Name, "<built-in>") == 0) {
+ if (Name == "<built-in>")
PreloadSLocs.push_back(SLocEntryOffsets.size());
- }
}
if (EmitBlob) {
@@ -2418,7 +2513,9 @@ unsigned ASTWriter::getLocalOrImportedSubmoduleID(Module *Mod) {
if (Known != SubmoduleIDs.end())
return Known->second;
- if (Mod->getTopLevelModule() != WritingModule)
+ auto *Top = Mod->getTopLevelModule();
+ if (Top != WritingModule &&
+ !Top->fullModuleNameIs(StringRef(getLangOpts().CurrentModule)))
return 0;
return SubmoduleIDs[Mod] = NextSubmoduleID++;
@@ -2650,6 +2747,13 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
Stream.EmitRecordWithBlob(ConfigMacroAbbrev, Record, CM);
}
+ // Emit the initializers, if any.
+ RecordData Inits;
+ for (Decl *D : Context->getModuleInitializers(Mod))
+ Inits.push_back(GetDeclRef(D));
+ if (!Inits.empty())
+ Stream.EmitRecord(SUBMODULE_INITIALIZERS, Inits);
+
// Queue up the submodules of this module.
for (auto *M : Mod->submodules())
Q.push(M);
@@ -2860,6 +2964,7 @@ void ASTWriter::WriteComments() {
//===----------------------------------------------------------------------===//
namespace {
+
// Trait used for the on-disk hash table used in the method pool.
class ASTMethodPoolTrait {
ASTWriter &Writer;
@@ -2964,6 +3069,7 @@ public:
assert(Out.tell() - Start == DataLen && "Data length is wrong");
}
};
+
} // end anonymous namespace
/// \brief Write ObjC data: selectors and the method pool.
@@ -3135,6 +3241,7 @@ static NamedDecl *getDeclForLocalLookup(const LangOptions &LangOpts,
}
namespace {
+
class ASTIdentifierTableTrait {
ASTWriter &Writer;
Preprocessor &PP;
@@ -3185,6 +3292,7 @@ public:
auto MacroOffset = Writer.getMacroDirectivesOffset(II);
return isInterestingIdentifier(II, MacroOffset);
}
+
bool isInterestingNonMacroIdentifier(const IdentifierInfo *II) {
return isInterestingIdentifier(II, 0);
}
@@ -3278,6 +3386,7 @@ public:
}
}
};
+
} // end anonymous namespace
/// \brief Write the identifier table into the AST file.
@@ -3384,6 +3493,7 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP,
//===----------------------------------------------------------------------===//
namespace {
+
// Trait used for the on-disk hash table used in the method pool.
class ASTDeclContextNameLookupTrait {
ASTWriter &Writer;
@@ -3509,6 +3619,7 @@ public:
assert(Out.tell() - Start == DataLen && "Data length is wrong");
}
};
+
} // end anonymous namespace
bool ASTWriter::isLookupResultExternal(StoredDeclsList &Result,
@@ -3830,11 +3941,53 @@ void ASTWriter::WriteOpenCLExtensions(Sema &SemaRef) {
const OpenCLOptions &Opts = SemaRef.getOpenCLOptions();
RecordData Record;
-#define OPENCLEXT(nm) Record.push_back(Opts.nm);
-#include "clang/Basic/OpenCLExtensions.def"
+ for (const auto &I:Opts.OptMap) {
+ AddString(I.getKey(), Record);
+ auto V = I.getValue();
+ Record.push_back(V.Supported ? 1 : 0);
+ Record.push_back(V.Enabled ? 1 : 0);
+ Record.push_back(V.Avail);
+ Record.push_back(V.Core);
+ }
Stream.EmitRecord(OPENCL_EXTENSIONS, Record);
}
+void ASTWriter::WriteOpenCLExtensionTypes(Sema &SemaRef) {
+ if (!SemaRef.Context.getLangOpts().OpenCL)
+ return;
+
+ RecordData Record;
+ for (const auto &I : SemaRef.OpenCLTypeExtMap) {
+ Record.push_back(
+ static_cast<unsigned>(getTypeID(I.first->getCanonicalTypeInternal())));
+ Record.push_back(I.second.size());
+ for (auto Ext : I.second)
+ AddString(Ext, Record);
+ }
+ Stream.EmitRecord(OPENCL_EXTENSION_TYPES, Record);
+}
+
+void ASTWriter::WriteOpenCLExtensionDecls(Sema &SemaRef) {
+ if (!SemaRef.Context.getLangOpts().OpenCL)
+ return;
+
+ RecordData Record;
+ for (const auto &I : SemaRef.OpenCLDeclExtMap) {
+ Record.push_back(getDeclID(I.first));
+ Record.push_back(static_cast<unsigned>(I.second.size()));
+ for (auto Ext : I.second)
+ AddString(Ext, Record);
+ }
+ Stream.EmitRecord(OPENCL_EXTENSION_DECLS, Record);
+}
+
+void ASTWriter::WriteCUDAPragmas(Sema &SemaRef) {
+ if (SemaRef.ForceCUDAHostDeviceDepth > 0) {
+ RecordData::value_type Record[] = {SemaRef.ForceCUDAHostDeviceDepth};
+ Stream.EmitRecord(CUDA_PRAGMA_FORCE_HOST_DEVICE_DEPTH, Record);
+ }
+}
+
void ASTWriter::WriteObjCCategories() {
SmallVector<ObjCCategoriesInfo, 2> CategoriesMap;
RecordData Categories;
@@ -3894,14 +4047,14 @@ void ASTWriter::WriteLateParsedTemplates(Sema &SemaRef) {
return;
RecordData Record;
- for (auto LPTMapEntry : LPTMap) {
+ for (auto &LPTMapEntry : LPTMap) {
const FunctionDecl *FD = LPTMapEntry.first;
- LateParsedTemplate *LPT = LPTMapEntry.second;
+ LateParsedTemplate &LPT = *LPTMapEntry.second;
AddDeclRef(FD, Record);
- AddDeclRef(LPT->D, Record);
- Record.push_back(LPT->Toks.size());
+ AddDeclRef(LPT.D, Record);
+ Record.push_back(LPT.Toks.size());
- for (const auto &Tok : LPT->Toks) {
+ for (const auto &Tok : LPT.Toks) {
AddToken(Tok, Record);
}
}
@@ -4255,9 +4408,10 @@ uint64_t ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
// Build a record containing some declaration references.
RecordData SemaDeclRefs;
- if (SemaRef.StdNamespace || SemaRef.StdBadAlloc) {
+ if (SemaRef.StdNamespace || SemaRef.StdBadAlloc || SemaRef.StdAlignValT) {
AddDeclRef(SemaRef.getStdNamespace(), SemaDeclRefs);
AddDeclRef(SemaRef.getStdBadAlloc(), SemaDeclRefs);
+ AddDeclRef(SemaRef.getStdAlignValT(), SemaDeclRefs);
}
RecordData CUDASpecialDeclRefs;
@@ -4364,8 +4518,9 @@ uint64_t ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
Number.second));
// Make sure visible decls, added to DeclContexts previously loaded from
- // an AST file, are registered for serialization.
- for (const auto *I : UpdatingVisibleDecls) {
+ // an AST file, are registered for serialization. Likewise for template
+ // specializations added to imported templates.
+ for (const auto *I : DeclsToEmitEvenIfUnreferenced) {
GetDeclRef(I);
}
@@ -4510,11 +4665,25 @@ uint64_t ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
WriteIdentifierTable(PP, SemaRef.IdResolver, isModule);
WriteFPPragmaOptions(SemaRef.getFPOptions());
WriteOpenCLExtensions(SemaRef);
+ WriteOpenCLExtensionTypes(SemaRef);
+ WriteOpenCLExtensionDecls(SemaRef);
+ WriteCUDAPragmas(SemaRef);
WritePragmaDiagnosticMappings(Context.getDiagnostics(), isModule);
// If we're emitting a module, write out the submodule information.
if (WritingModule)
WriteSubmodules(WritingModule);
+ else if (!getLangOpts().CurrentModule.empty()) {
+ // If we're building a PCH in the implementation of a module, we may need
+ // the description of the current module.
+ //
+ // FIXME: We may need other modules that we did not load from an AST file,
+ // such as if a module declares a 'conflicts' on a different module.
+ Module *M = PP.getHeaderSearchInfo().getModuleMap().findModule(
+ getLangOpts().CurrentModule);
+ if (M && !M->IsFromModuleFile)
+ WriteSubmodules(M);
+ }
Stream.EmitRecord(SPECIAL_TYPES, SpecialTypes);
@@ -4682,6 +4851,11 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) {
cast<ParmVarDecl>(Update.getDecl())->getDefaultArg()));
break;
+ case UPD_CXX_INSTANTIATED_DEFAULT_MEMBER_INITIALIZER:
+ Record.AddStmt(
+ cast<FieldDecl>(Update.getDecl())->getInClassInitializer());
+ break;
+
case UPD_CXX_INSTANTIATED_CLASS_DEFINITION: {
auto *RD = cast<CXXRecordDecl>(D);
UpdatedDeclContexts.insert(RD->getPrimaryContext());
@@ -5159,7 +5333,7 @@ void ASTRecordWriter::AddDeclarationNameInfo(
void ASTRecordWriter::AddQualifierInfo(const QualifierInfo &Info) {
AddNestedNameSpecifierLoc(Info.QualifierLoc);
Record->push_back(Info.NumTemplParamLists);
- for (unsigned i=0, e=Info.NumTemplParamLists; i != e; ++i)
+ for (unsigned i = 0, e = Info.NumTemplParamLists; i != e; ++i)
AddTemplateParameterList(Info.TemplParamLists[i]);
}
@@ -5361,6 +5535,7 @@ void ASTRecordWriter::AddTemplateParameterList(
AddSourceLocation(TemplateParams->getTemplateLoc());
AddSourceLocation(TemplateParams->getLAngleLoc());
AddSourceLocation(TemplateParams->getRAngleLoc());
+ // TODO: Concepts
Record->push_back(TemplateParams->size());
for (const auto &P : *TemplateParams)
AddDeclRef(P);
@@ -5371,7 +5546,7 @@ void ASTRecordWriter::AddTemplateArgumentList(
const TemplateArgumentList *TemplateArgs) {
assert(TemplateArgs && "No TemplateArgs!");
Record->push_back(TemplateArgs->size());
- for (int i=0, e = TemplateArgs->size(); i != e; ++i)
+ for (int i = 0, e = TemplateArgs->size(); i != e; ++i)
AddTemplateArgument(TemplateArgs->get(i));
}
@@ -5382,7 +5557,7 @@ void ASTRecordWriter::AddASTTemplateArgumentListInfo(
AddSourceLocation(ASTTemplArgList->RAngleLoc);
Record->push_back(ASTTemplArgList->NumTemplateArgs);
const TemplateArgumentLoc *TemplArgs = ASTTemplArgList->getTemplateArgs();
- for (int i=0, e = ASTTemplArgList->NumTemplateArgs; i != e; ++i)
+ for (int i = 0, e = ASTTemplArgList->NumTemplateArgs; i != e; ++i)
AddTemplateArgumentLoc(TemplArgs[i]);
}
@@ -5452,13 +5627,8 @@ EmitCXXCtorInitializers(ASTWriter &W,
Writer.AddSourceLocation(Init->getLParenLoc());
Writer.AddSourceLocation(Init->getRParenLoc());
Writer.push_back(Init->isWritten());
- if (Init->isWritten()) {
+ if (Init->isWritten())
Writer.push_back(Init->getSourceOrder());
- } else {
- Writer.push_back(Init->getNumArrayIndices());
- for (auto *VD : Init->getArrayIndices())
- Writer.AddDeclRef(VD);
- }
}
return Writer.Emit(serialization::DECL_CXX_CTOR_INITIALIZERS);
@@ -5539,7 +5709,7 @@ void ASTRecordWriter::AddCXXDefinitionData(const CXXRecordDecl *D) {
Record->push_back(Lambda.NumCaptures);
Record->push_back(Lambda.NumExplicitCaptures);
Record->push_back(Lambda.ManglingNumber);
- AddDeclRef(Lambda.ContextDecl);
+ AddDeclRef(D->getLambdaContextDecl());
AddTypeSourceInfo(Lambda.MethodTyInfo);
for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) {
const LambdaCapture &Capture = Lambda.Captures[I];
@@ -5693,9 +5863,9 @@ void ASTWriter::AddedVisibleDecl(const DeclContext *DC, const Decl *D) {
// that we write out all of its lookup results so we don't get a nasty
// surprise when we try to emit its lookup table.
for (auto *Child : DC->decls())
- UpdatingVisibleDecls.push_back(Child);
+ DeclsToEmitEvenIfUnreferenced.push_back(Child);
}
- UpdatingVisibleDecls.push_back(D);
+ DeclsToEmitEvenIfUnreferenced.push_back(D);
}
void ASTWriter::AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D) {
@@ -5794,6 +5964,15 @@ void ASTWriter::DefaultArgumentInstantiated(const ParmVarDecl *D) {
DeclUpdate(UPD_CXX_INSTANTIATED_DEFAULT_ARGUMENT, D));
}
+void ASTWriter::DefaultMemberInitializerInstantiated(const FieldDecl *D) {
+ assert(!WritingAST && "Already writing the AST!");
+ if (!D->isFromASTFile())
+ return;
+
+ DeclUpdates[D].push_back(
+ DeclUpdate(UPD_CXX_INSTANTIATED_DEFAULT_MEMBER_INITIALIZER, D));
+}
+
void ASTWriter::AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
const ObjCInterfaceDecl *IFD) {
if (Chain && Chain->isProcessingUpdateRecords()) return;
@@ -5855,3 +6034,39 @@ void ASTWriter::AddedAttributeToRecord(const Attr *Attr,
return;
DeclUpdates[Record].push_back(DeclUpdate(UPD_ADDED_ATTR_TO_RECORD, Attr));
}
+
+void ASTWriter::AddedCXXTemplateSpecialization(
+ const ClassTemplateDecl *TD, const ClassTemplateSpecializationDecl *D) {
+ assert(!WritingAST && "Already writing the AST!");
+
+ if (!TD->getFirstDecl()->isFromASTFile())
+ return;
+ if (Chain && Chain->isProcessingUpdateRecords())
+ return;
+
+ DeclsToEmitEvenIfUnreferenced.push_back(D);
+}
+
+void ASTWriter::AddedCXXTemplateSpecialization(
+ const VarTemplateDecl *TD, const VarTemplateSpecializationDecl *D) {
+ assert(!WritingAST && "Already writing the AST!");
+
+ if (!TD->getFirstDecl()->isFromASTFile())
+ return;
+ if (Chain && Chain->isProcessingUpdateRecords())
+ return;
+
+ DeclsToEmitEvenIfUnreferenced.push_back(D);
+}
+
+void ASTWriter::AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,
+ const FunctionDecl *D) {
+ assert(!WritingAST && "Already writing the AST!");
+
+ if (!TD->getFirstDecl()->isFromASTFile())
+ return;
+ if (Chain && Chain->isProcessingUpdateRecords())
+ return;
+
+ DeclsToEmitEvenIfUnreferenced.push_back(D);
+}
diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp
index 23d18540e822..ee220f00a81f 100644
--- a/lib/Serialization/ASTWriterDecl.cpp
+++ b/lib/Serialization/ASTWriterDecl.cpp
@@ -11,7 +11,6 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Serialization/ASTWriter.h"
#include "ASTCommon.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclContextInternals.h"
@@ -20,7 +19,7 @@
#include "clang/AST/Expr.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Serialization/ASTReader.h"
-#include "llvm/ADT/Twine.h"
+#include "clang/Serialization/ASTWriter.h"
#include "llvm/Bitcode/BitstreamWriter.h"
#include "llvm/Support/ErrorHandling.h"
using namespace clang;
@@ -97,6 +96,8 @@ namespace clang {
void VisitVarDecl(VarDecl *D);
void VisitImplicitParamDecl(ImplicitParamDecl *D);
void VisitParmVarDecl(ParmVarDecl *D);
+ void VisitDecompositionDecl(DecompositionDecl *D);
+ void VisitBindingDecl(BindingDecl *D);
void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
void VisitTemplateDecl(TemplateDecl *D);
void VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D);
@@ -106,9 +107,11 @@ namespace clang {
void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
void VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D);
void VisitUsingDecl(UsingDecl *D);
+ void VisitUsingPackDecl(UsingPackDecl *D);
void VisitUsingShadowDecl(UsingShadowDecl *D);
void VisitConstructorUsingShadowDecl(ConstructorUsingShadowDecl *D);
void VisitLinkageSpecDecl(LinkageSpecDecl *D);
+ void VisitExportDecl(ExportDecl *D);
void VisitFileScopeAsmDecl(FileScopeAsmDecl *D);
void VisitImportDecl(ImportDecl *D);
void VisitAccessSpecDecl(AccessSpecDecl *D);
@@ -892,6 +895,7 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) {
Record.push_back(D->getTSCSpec());
Record.push_back(D->getInitStyle());
if (!isa<ParmVarDecl>(D)) {
+ Record.push_back(D->isThisDeclarationADemotedDefinition());
Record.push_back(D->isExceptionVariable());
Record.push_back(D->isNRVOVariable());
Record.push_back(D->isCXXForRangeDecl());
@@ -940,10 +944,7 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) {
D->getDeclName().getNameKind() == DeclarationName::Identifier &&
!D->hasExtInfo() &&
D->getFirstDecl() == D->getMostRecentDecl() &&
- D->getInitStyle() == VarDecl::CInit &&
- D->getInit() == nullptr &&
- !isa<ParmVarDecl>(D) &&
- !isa<VarTemplateSpecializationDecl>(D) &&
+ D->getKind() == Decl::Var &&
!D->isInline() &&
!D->isConstexpr() &&
!D->isInitCapture() &&
@@ -999,6 +1000,8 @@ void ASTDeclWriter::VisitParmVarDecl(ParmVarDecl *D) {
// Check things we know are true of *every* PARM_VAR_DECL, which is more than
// just us assuming it.
assert(!D->getTSCSpec() && "PARM_VAR_DECL can't use TLS");
+ assert(!D->isThisDeclarationADemotedDefinition()
+ && "PARM_VAR_DECL can't be demoted definition.");
assert(D->getAccess() == AS_none && "PARM_VAR_DECL can't be public/private");
assert(!D->isExceptionVariable() && "PARM_VAR_DECL can't be exception var");
assert(D->getPreviousDecl() == nullptr && "PARM_VAR_DECL can't be redecl");
@@ -1006,6 +1009,22 @@ void ASTDeclWriter::VisitParmVarDecl(ParmVarDecl *D) {
"PARM_VAR_DECL can't be static data member");
}
+void ASTDeclWriter::VisitDecompositionDecl(DecompositionDecl *D) {
+ // Record the number of bindings first to simplify deserialization.
+ Record.push_back(D->bindings().size());
+
+ VisitVarDecl(D);
+ for (auto *B : D->bindings())
+ Record.AddDeclRef(B);
+ Code = serialization::DECL_DECOMPOSITION;
+}
+
+void ASTDeclWriter::VisitBindingDecl(BindingDecl *D) {
+ VisitValueDecl(D);
+ Record.AddStmt(D->getBinding());
+ Code = serialization::DECL_BINDING;
+}
+
void ASTDeclWriter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) {
VisitDecl(D);
Record.AddStmt(D->getAsmString());
@@ -1064,6 +1083,12 @@ void ASTDeclWriter::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
Code = serialization::DECL_LINKAGE_SPEC;
}
+void ASTDeclWriter::VisitExportDecl(ExportDecl *D) {
+ VisitDecl(D);
+ Record.AddSourceLocation(D->getRBraceLoc());
+ Code = serialization::DECL_EXPORT;
+}
+
void ASTDeclWriter::VisitLabelDecl(LabelDecl *D) {
VisitNamedDecl(D);
Record.AddSourceLocation(D->getLocStart());
@@ -1118,6 +1143,15 @@ void ASTDeclWriter::VisitUsingDecl(UsingDecl *D) {
Code = serialization::DECL_USING;
}
+void ASTDeclWriter::VisitUsingPackDecl(UsingPackDecl *D) {
+ Record.push_back(D->NumExpansions);
+ VisitNamedDecl(D);
+ Record.AddDeclRef(D->getInstantiatedFromUsingDecl());
+ for (auto *E : D->expansions())
+ Record.AddDeclRef(E);
+ Code = serialization::DECL_USING_PACK;
+}
+
void ASTDeclWriter::VisitUsingShadowDecl(UsingShadowDecl *D) {
VisitRedeclarable(D);
VisitNamedDecl(D);
@@ -1151,6 +1185,7 @@ void ASTDeclWriter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
Record.AddSourceLocation(D->getUsingLoc());
Record.AddNestedNameSpecifierLoc(D->getQualifierLoc());
Record.AddDeclarationNameLoc(D->DNLoc, D->getDeclName());
+ Record.AddSourceLocation(D->getEllipsisLoc());
Code = serialization::DECL_UNRESOLVED_USING_VALUE;
}
@@ -1159,6 +1194,7 @@ void ASTDeclWriter::VisitUnresolvedUsingTypenameDecl(
VisitTypeDecl(D);
Record.AddSourceLocation(D->getTypenameLoc());
Record.AddNestedNameSpecifierLoc(D->getQualifierLoc());
+ Record.AddSourceLocation(D->getEllipsisLoc());
Code = serialization::DECL_UNRESOLVED_USING_TYPENAME;
}
@@ -1857,9 +1893,9 @@ void ASTWriter::WriteDeclAbbrevs() {
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerStartLoc
Abv->Add(BitCodeAbbrevOp(0)); // hasExtInfo
// VarDecl
- Abv->Add(BitCodeAbbrevOp(0)); // StorageClass
- Abv->Add(BitCodeAbbrevOp(0)); // getTSCSpec
- Abv->Add(BitCodeAbbrevOp(0)); // hasCXXDirectInitializer
+ Abv->Add(BitCodeAbbrevOp(0)); // SClass
+ Abv->Add(BitCodeAbbrevOp(0)); // TSCSpec
+ Abv->Add(BitCodeAbbrevOp(0)); // InitStyle
Abv->Add(BitCodeAbbrevOp(0)); // Linkage
Abv->Add(BitCodeAbbrevOp(0)); // HasInit
Abv->Add(BitCodeAbbrevOp(0)); // HasMemberSpecializationInfo
@@ -1933,9 +1969,10 @@ void ASTWriter::WriteDeclAbbrevs() {
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerStartLoc
Abv->Add(BitCodeAbbrevOp(0)); // hasExtInfo
// VarDecl
- Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // StorageClass
- Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // getTSCSpec
- Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // CXXDirectInitializer
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // SClass
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // TSCSpec
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // InitStyle
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsThisDeclarationADemotedDefinition
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isExceptionVariable
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isNRVOVariable
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isCXXForRangeDecl
@@ -1946,8 +1983,8 @@ void ASTWriter::WriteDeclAbbrevs() {
Abv->Add(BitCodeAbbrevOp(0)); // isInitCapture
Abv->Add(BitCodeAbbrevOp(0)); // isPrevDeclInSameScope
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Linkage
- Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // HasInit
- Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // HasMemberSpecInfo
+ 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));
@@ -2123,11 +2160,11 @@ static bool isRequiredDecl(const Decl *D, ASTContext &Context,
D->hasAttr<OMPDeclareTargetDeclAttr>())
return true;
- // ImportDecl is used by codegen to determine the set of imported modules to
- // search for inputs for automatic linking; include it if it has a semantic
- // effect.
- if (isa<ImportDecl>(D) && !WritingModule)
- return true;
+ if (WritingModule && (isa<VarDecl>(D) || isa<ImportDecl>(D))) {
+ // These declarations are part of the module initializer, and are emitted
+ // if and when the module is imported, rather than being emitted eagerly.
+ return false;
+ }
return Context.DeclMustBeEmitted(D);
}
diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp
index 84e718e9ef23..3993be146edf 100644
--- a/lib/Serialization/ASTWriterStmt.cpp
+++ b/lib/Serialization/ASTWriterStmt.cpp
@@ -792,6 +792,18 @@ void ASTStmtWriter::VisitNoInitExpr(NoInitExpr *E) {
Code = serialization::EXPR_NO_INIT;
}
+void ASTStmtWriter::VisitArrayInitLoopExpr(ArrayInitLoopExpr *E) {
+ VisitExpr(E);
+ Record.AddStmt(E->SubExprs[0]);
+ Record.AddStmt(E->SubExprs[1]);
+ Code = serialization::EXPR_ARRAY_INIT_LOOP;
+}
+
+void ASTStmtWriter::VisitArrayInitIndexExpr(ArrayInitIndexExpr *E) {
+ VisitExpr(E);
+ Code = serialization::EXPR_ARRAY_INIT_INDEX;
+}
+
void ASTStmtWriter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) {
VisitExpr(E);
Code = serialization::EXPR_IMPLICIT_VALUE_INIT;
@@ -1245,10 +1257,6 @@ void ASTStmtWriter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E) {
void ASTStmtWriter::VisitLambdaExpr(LambdaExpr *E) {
VisitExpr(E);
Record.push_back(E->NumCaptures);
- unsigned NumArrayIndexVars = 0;
- if (E->HasArrayIndexVars)
- NumArrayIndexVars = E->getArrayIndexStarts()[E->NumCaptures];
- Record.push_back(NumArrayIndexVars);
Record.AddSourceRange(E->IntroducerRange);
Record.push_back(E->CaptureDefault); // FIXME: stable encoding
Record.AddSourceLocation(E->CaptureDefaultLoc);
@@ -1263,15 +1271,6 @@ void ASTStmtWriter::VisitLambdaExpr(LambdaExpr *E) {
Record.AddStmt(*C);
}
- // Add array index variables, if any.
- if (NumArrayIndexVars) {
- Record.append(E->getArrayIndexStarts(),
- E->getArrayIndexStarts() + E->NumCaptures + 1);
- VarDecl **ArrayIndexVars = E->getArrayIndexVars();
- for (unsigned I = 0; I != NumArrayIndexVars; ++I)
- Record.AddDeclRef(ArrayIndexVars[I]);
- }
-
Code = serialization::EXPR_LAMBDA;
}
@@ -1392,6 +1391,7 @@ void ASTStmtWriter::VisitCXXNewExpr(CXXNewExpr *E) {
VisitExpr(E);
Record.push_back(E->isGlobalNew());
Record.push_back(E->isArray());
+ Record.push_back(E->passAlignment());
Record.push_back(E->doesUsualArrayDeleteWantSize());
Record.push_back(E->getNumPlacementArgs());
Record.push_back(E->StoredInitializationStyle);
@@ -1576,6 +1576,7 @@ void ASTStmtWriter::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) {
Record.push_back(E->getValue());
Record.AddSourceRange(E->getSourceRange());
Record.AddTypeSourceInfo(E->getQueriedTypeSourceInfo());
+ Record.AddStmt(E->getDimensionExpression());
Code = serialization::EXPR_ARRAY_TYPE_TRAIT;
}
@@ -2151,17 +2152,45 @@ void OMPClauseWriter::VisitOMPFromClause(OMPFromClause *C) {
void OMPClauseWriter::VisitOMPUseDevicePtrClause(OMPUseDevicePtrClause *C) {
Record.push_back(C->varlist_size());
+ Record.push_back(C->getUniqueDeclarationsNum());
+ Record.push_back(C->getTotalComponentListNum());
+ Record.push_back(C->getTotalComponentsNum());
Record.AddSourceLocation(C->getLParenLoc());
- for (auto *VE : C->varlists()) {
+ for (auto *E : C->varlists())
+ Record.AddStmt(E);
+ for (auto *VE : C->private_copies())
+ Record.AddStmt(VE);
+ for (auto *VE : C->inits())
Record.AddStmt(VE);
+ for (auto *D : C->all_decls())
+ Record.AddDeclRef(D);
+ for (auto N : C->all_num_lists())
+ Record.push_back(N);
+ for (auto N : C->all_lists_sizes())
+ Record.push_back(N);
+ for (auto &M : C->all_components()) {
+ Record.AddStmt(M.getAssociatedExpression());
+ Record.AddDeclRef(M.getAssociatedDeclaration());
}
}
void OMPClauseWriter::VisitOMPIsDevicePtrClause(OMPIsDevicePtrClause *C) {
Record.push_back(C->varlist_size());
+ Record.push_back(C->getUniqueDeclarationsNum());
+ Record.push_back(C->getTotalComponentListNum());
+ Record.push_back(C->getTotalComponentsNum());
Record.AddSourceLocation(C->getLParenLoc());
- for (auto *VE : C->varlists()) {
- Record.AddStmt(VE);
+ for (auto *E : C->varlists())
+ Record.AddStmt(E);
+ for (auto *D : C->all_decls())
+ Record.AddDeclRef(D);
+ for (auto N : C->all_num_lists())
+ Record.push_back(N);
+ for (auto N : C->all_lists_sizes())
+ Record.push_back(N);
+ for (auto &M : C->all_components()) {
+ Record.AddStmt(M.getAssociatedExpression());
+ Record.AddDeclRef(M.getAssociatedDeclaration());
}
}
@@ -2479,6 +2508,54 @@ void ASTStmtWriter::VisitOMPTargetParallelForSimdDirective(
Code = serialization::STMT_OMP_TARGET_PARALLEL_FOR_SIMD_DIRECTIVE;
}
+void ASTStmtWriter::VisitOMPTargetSimdDirective(OMPTargetSimdDirective *D) {
+ VisitOMPLoopDirective(D);
+ Code = serialization::STMT_OMP_TARGET_SIMD_DIRECTIVE;
+}
+
+void ASTStmtWriter::VisitOMPTeamsDistributeDirective(
+ OMPTeamsDistributeDirective *D) {
+ VisitOMPLoopDirective(D);
+ Code = serialization::STMT_OMP_TEAMS_DISTRIBUTE_DIRECTIVE;
+}
+
+void ASTStmtWriter::VisitOMPTeamsDistributeSimdDirective(
+ OMPTeamsDistributeSimdDirective *D) {
+ VisitOMPLoopDirective(D);
+ Code = serialization::STMT_OMP_TEAMS_DISTRIBUTE_SIMD_DIRECTIVE;
+}
+
+void ASTStmtWriter::VisitOMPTeamsDistributeParallelForSimdDirective(
+ OMPTeamsDistributeParallelForSimdDirective *D) {
+ VisitOMPLoopDirective(D);
+ Code = serialization::STMT_OMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_DIRECTIVE;
+}
+
+void ASTStmtWriter::VisitOMPTeamsDistributeParallelForDirective(
+ OMPTeamsDistributeParallelForDirective *D) {
+ VisitOMPLoopDirective(D);
+ Code = serialization::STMT_OMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_DIRECTIVE;
+}
+
+void ASTStmtWriter::VisitOMPTargetTeamsDirective(OMPTargetTeamsDirective *D) {
+ VisitStmt(D);
+ Record.push_back(D->getNumClauses());
+ VisitOMPExecutableDirective(D);
+ Code = serialization::STMT_OMP_TARGET_TEAMS_DIRECTIVE;
+}
+
+void ASTStmtWriter::VisitOMPTargetTeamsDistributeDirective(
+ OMPTargetTeamsDistributeDirective *D) {
+ VisitOMPLoopDirective(D);
+ Code = serialization::STMT_OMP_TARGET_TEAMS_DISTRIBUTE_DIRECTIVE;
+}
+
+void ASTStmtWriter::VisitOMPTargetTeamsDistributeParallelForDirective(
+ OMPTargetTeamsDistributeParallelForDirective *D) {
+ VisitOMPLoopDirective(D);
+ Code = serialization::STMT_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_DIRECTIVE;
+}
+
//===----------------------------------------------------------------------===//
// ASTWriter Implementation
//===----------------------------------------------------------------------===//
diff --git a/lib/Serialization/GeneratePCH.cpp b/lib/Serialization/GeneratePCH.cpp
index 308fde8b1dd7..e1765dafd96f 100644
--- a/lib/Serialization/GeneratePCH.cpp
+++ b/lib/Serialization/GeneratePCH.cpp
@@ -12,24 +12,21 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Serialization/ASTWriter.h"
-#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
-#include "clang/Basic/FileManager.h"
+#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/SemaConsumer.h"
+#include "clang/Serialization/ASTWriter.h"
#include "llvm/Bitcode/BitstreamWriter.h"
-#include <string>
using namespace clang;
PCHGenerator::PCHGenerator(
- const Preprocessor &PP, StringRef OutputFile,
- clang::Module *Module, StringRef isysroot,
- std::shared_ptr<PCHBuffer> Buffer,
- ArrayRef<llvm::IntrusiveRefCntPtr<ModuleFileExtension>> Extensions,
- bool AllowASTWithErrors, bool IncludeTimestamps)
- : PP(PP), OutputFile(OutputFile), Module(Module), isysroot(isysroot.str()),
+ const Preprocessor &PP, StringRef OutputFile, StringRef isysroot,
+ std::shared_ptr<PCHBuffer> Buffer,
+ ArrayRef<llvm::IntrusiveRefCntPtr<ModuleFileExtension>> Extensions,
+ bool AllowASTWithErrors, bool IncludeTimestamps)
+ : PP(PP), OutputFile(OutputFile), isysroot(isysroot.str()),
SemaPtr(nullptr), Buffer(Buffer), Stream(Buffer->Data),
Writer(Stream, Extensions, IncludeTimestamps),
AllowASTWithErrors(AllowASTWithErrors) {
@@ -48,6 +45,16 @@ void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) {
if (hasErrors && !AllowASTWithErrors)
return;
+ Module *Module = nullptr;
+ if (PP.getLangOpts().isCompilingModule()) {
+ Module = PP.getHeaderSearchInfo().lookupModule(
+ PP.getLangOpts().CurrentModule, /*AllowSearch*/ false);
+ if (!Module) {
+ assert(hasErrors && "emitting module but current module doesn't exist");
+ return;
+ }
+ }
+
// Emit the PCH file to the Buffer.
assert(SemaPtr && "No Sema?");
Buffer->Signature =
diff --git a/lib/Serialization/GlobalModuleIndex.cpp b/lib/Serialization/GlobalModuleIndex.cpp
index 581e894d9150..9f986d54a989 100644
--- a/lib/Serialization/GlobalModuleIndex.cpp
+++ b/lib/Serialization/GlobalModuleIndex.cpp
@@ -245,12 +245,8 @@ GlobalModuleIndex::readIndex(StringRef Path) {
return std::make_pair(nullptr, EC_NotFound);
std::unique_ptr<llvm::MemoryBuffer> Buffer = std::move(BufferOrErr.get());
- /// \brief The bitstream reader from which we'll read the AST file.
- llvm::BitstreamReader Reader((const unsigned char *)Buffer->getBufferStart(),
- (const unsigned char *)Buffer->getBufferEnd());
-
/// \brief The main bitstream cursor for the main block.
- llvm::BitstreamCursor Cursor(Reader);
+ llvm::BitstreamCursor Cursor(*Buffer);
// Sniff for the signature.
if (Cursor.Read(8) != 'B' ||
@@ -460,7 +456,7 @@ static void emitRecordID(unsigned ID, const char *Name,
void
GlobalModuleIndexBuilder::emitBlockInfoBlock(llvm::BitstreamWriter &Stream) {
SmallVector<uint64_t, 64> Record;
- Stream.EnterSubblock(llvm::bitc::BLOCKINFO_BLOCK_ID, 3);
+ Stream.EnterBlockInfoBlock();
#define BLOCK(X) emitBlockID(X ## _ID, #X, Stream, Record)
#define RECORD(X) emitRecordID(X, #X, Stream, Record)
@@ -504,9 +500,7 @@ bool GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) {
}
// Initialize the input stream
- llvm::BitstreamReader InStreamFile;
- PCHContainerRdr.ExtractPCH((*Buffer)->getMemBufferRef(), InStreamFile);
- llvm::BitstreamCursor InStream(InStreamFile);
+ llvm::BitstreamCursor InStream(PCHContainerRdr.ExtractPCH(**Buffer));
// Sniff for the signature.
if (InStream.Read(8) != 'C' ||
diff --git a/lib/Serialization/Module.cpp b/lib/Serialization/Module.cpp
index ca0cb3c8ea17..72b08610bb4d 100644
--- a/lib/Serialization/Module.cpp
+++ b/lib/Serialization/Module.cpp
@@ -13,7 +13,6 @@
//===----------------------------------------------------------------------===//
#include "clang/Serialization/Module.h"
#include "ASTReaderInternals.h"
-#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
diff --git a/lib/Serialization/ModuleFileExtension.cpp b/lib/Serialization/ModuleFileExtension.cpp
index 81dcfd60ce8e..5bd0a1ce660b 100644
--- a/lib/Serialization/ModuleFileExtension.cpp
+++ b/lib/Serialization/ModuleFileExtension.cpp
@@ -8,7 +8,6 @@
//===----------------------------------------------------------------------===//
#include "clang/Serialization/ModuleFileExtension.h"
#include "llvm/ADT/Hashing.h"
-#include "llvm/Support/raw_ostream.h"
using namespace clang;
ModuleFileExtension::~ModuleFileExtension() { }
diff --git a/lib/Serialization/ModuleManager.cpp b/lib/Serialization/ModuleManager.cpp
index 292f36dfeb2a..722b547e803e 100644
--- a/lib/Serialization/ModuleManager.cpp
+++ b/lib/Serialization/ModuleManager.cpp
@@ -11,14 +11,13 @@
// modules for the ASTReader.
//
//===----------------------------------------------------------------------===//
+#include "clang/Serialization/ModuleManager.h"
#include "clang/Frontend/PCHContainerOperations.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/ModuleMap.h"
#include "clang/Serialization/GlobalModuleIndex.h"
-#include "clang/Serialization/ModuleManager.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
-#include "llvm/Support/raw_ostream.h"
#include <system_error>
#ifndef NDEBUG
@@ -67,7 +66,7 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type,
// Look for the file entry. This only fails if the expected size or
// modification time differ.
const FileEntry *Entry;
- if (Type == MK_ExplicitModule) {
+ if (Type == MK_ExplicitModule || Type == MK_PrebuiltModule) {
// If we're not expecting to pull this file out of the module cache, it
// might have a different mtime due to being moved across filesystems in
// a distributed build. The size must still match, though. (As must the
@@ -85,37 +84,31 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type,
}
// Check whether we already loaded this module, before
- ModuleFile *&ModuleEntry = Modules[Entry];
+ ModuleFile *ModuleEntry = Modules[Entry];
bool NewModule = false;
if (!ModuleEntry) {
// Allocate a new module.
- ModuleFile *New = new ModuleFile(Type, Generation);
- New->Index = Chain.size();
- New->FileName = FileName.str();
- New->File = Entry;
- New->ImportLoc = ImportLoc;
- Chain.push_back(New);
- if (!New->isModule())
- PCHChain.push_back(New);
- if (!ImportedBy)
- Roots.push_back(New);
NewModule = true;
- ModuleEntry = New;
-
- New->InputFilesValidationTimestamp = 0;
- if (New->Kind == MK_ImplicitModule) {
- std::string TimestampFilename = New->getTimestampFilename();
+ ModuleEntry = new ModuleFile(Type, Generation);
+ ModuleEntry->Index = Chain.size();
+ ModuleEntry->FileName = FileName.str();
+ ModuleEntry->File = Entry;
+ ModuleEntry->ImportLoc = ImportLoc;
+ ModuleEntry->InputFilesValidationTimestamp = 0;
+
+ if (ModuleEntry->Kind == MK_ImplicitModule) {
+ std::string TimestampFilename = ModuleEntry->getTimestampFilename();
vfs::Status Status;
// A cached stat value would be fine as well.
if (!FileMgr.getNoncachedStatValue(TimestampFilename, Status))
- New->InputFilesValidationTimestamp =
- Status.getLastModificationTime().toEpochTime();
+ ModuleEntry->InputFilesValidationTimestamp =
+ llvm::sys::toTimeT(Status.getLastModificationTime());
}
// Load the contents of the module
if (std::unique_ptr<llvm::MemoryBuffer> Buffer = lookupBuffer(FileName)) {
// The buffer was already provided for us.
- New->Buffer = std::move(Buffer);
+ ModuleEntry->Buffer = std::move(Buffer);
} else {
// Open the AST file.
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buf(
@@ -127,52 +120,40 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type,
// ModuleManager it must be the same underlying file.
// FIXME: Because FileManager::getFile() doesn't guarantee that it will
// give us an open file, this may not be 100% reliable.
- Buf = FileMgr.getBufferForFile(New->File,
+ Buf = FileMgr.getBufferForFile(ModuleEntry->File,
/*IsVolatile=*/false,
/*ShouldClose=*/false);
}
if (!Buf) {
ErrorStr = Buf.getError().message();
+ delete ModuleEntry;
return Missing;
}
- New->Buffer = std::move(*Buf);
+ ModuleEntry->Buffer = std::move(*Buf);
}
// Initialize the stream.
- PCHContainerRdr.ExtractPCH(New->Buffer->getMemBufferRef(), New->StreamFile);
+ ModuleEntry->Data = PCHContainerRdr.ExtractPCH(*ModuleEntry->Buffer);
}
if (ExpectedSignature) {
- if (NewModule)
- ModuleEntry->Signature = ReadSignature(ModuleEntry->StreamFile);
- else
- assert(ModuleEntry->Signature == ReadSignature(ModuleEntry->StreamFile));
+ // If we've not read the control block yet, read the signature eagerly now
+ // so that we can check it.
+ if (!ModuleEntry->Signature)
+ ModuleEntry->Signature = ReadSignature(ModuleEntry->Data);
if (ModuleEntry->Signature != ExpectedSignature) {
ErrorStr = ModuleEntry->Signature ? "signature mismatch"
: "could not read module signature";
- if (NewModule) {
- // Remove the module file immediately, since removeModules might try to
- // invalidate the file cache for Entry, and that is not safe if this
- // module is *itself* up to date, but has an out-of-date importer.
- Modules.erase(Entry);
- assert(Chain.back() == ModuleEntry);
- Chain.pop_back();
- if (!ModuleEntry->isModule())
- PCHChain.pop_back();
- if (Roots.back() == ModuleEntry)
- Roots.pop_back();
- else
- assert(ImportedBy);
+ if (NewModule)
delete ModuleEntry;
- }
return OutOfDate;
}
}
-
+
if (ImportedBy) {
ModuleEntry->ImportedBy.insert(ImportedBy);
ImportedBy->Imports.insert(ModuleEntry);
@@ -184,7 +165,20 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type,
}
Module = ModuleEntry;
- return NewModule? NewlyLoaded : AlreadyLoaded;
+
+ if (!NewModule)
+ return AlreadyLoaded;
+
+ assert(!Modules[Entry] && "module loaded twice");
+ Modules[Entry] = ModuleEntry;
+
+ Chain.push_back(ModuleEntry);
+ if (!ModuleEntry->isModule())
+ PCHChain.push_back(ModuleEntry);
+ if (!ImportedBy)
+ Roots.push_back(ModuleEntry);
+
+ return NewlyLoaded;
}
void ModuleManager::removeModules(
@@ -413,13 +407,16 @@ bool ModuleManager::lookupModuleFile(StringRef FileName,
off_t ExpectedSize,
time_t ExpectedModTime,
const FileEntry *&File) {
+ if (FileName == "-") {
+ File = nullptr;
+ return false;
+ }
+
// Open the file immediately to ensure there is no race between stat'ing and
// opening the file.
File = FileMgr.getFile(FileName, /*openFile=*/true, /*cacheFailure=*/false);
-
- if (!File && FileName != "-") {
+ if (!File)
return false;
- }
if ((ExpectedSize && ExpectedSize != File->getSize()) ||
(ExpectedModTime && ExpectedModTime != File->getModificationTime()))
@@ -434,15 +431,15 @@ bool ModuleManager::lookupModuleFile(StringRef FileName,
namespace llvm {
template<>
struct GraphTraits<ModuleManager> {
- typedef ModuleFile NodeType;
+ typedef ModuleFile *NodeRef;
typedef llvm::SetVector<ModuleFile *>::const_iterator ChildIteratorType;
typedef ModuleManager::ModuleConstIterator nodes_iterator;
-
- static ChildIteratorType child_begin(NodeType *Node) {
+
+ static ChildIteratorType child_begin(NodeRef Node) {
return Node->Imports.begin();
}
- static ChildIteratorType child_end(NodeType *Node) {
+ static ChildIteratorType child_end(NodeRef Node) {
return Node->Imports.end();
}
diff --git a/lib/Serialization/MultiOnDiskHashTable.h b/lib/Serialization/MultiOnDiskHashTable.h
index 04dea831695c..fdbbb602b537 100644
--- a/lib/Serialization/MultiOnDiskHashTable.h
+++ b/lib/Serialization/MultiOnDiskHashTable.h
@@ -18,7 +18,11 @@
#ifndef LLVM_CLANG_LIB_SERIALIZATION_MULTIONDISKHASHTABLE_H
#define LLVM_CLANG_LIB_SERIALIZATION_MULTIONDISKHASHTABLE_H
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/Support/EndianStream.h"
#include "llvm/Support/OnDiskHashTable.h"
diff --git a/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp b/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp
new file mode 100644
index 000000000000..e6592a285e47
--- /dev/null
+++ b/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp
@@ -0,0 +1,68 @@
+//===- AnalysisOrderChecker - Print callbacks called ------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This checker prints callbacks that are called during analysis.
+// This is required to ensure that callbacks are fired in order
+// and do not duplicate or get lost.
+// Feel free to extend this checker with any callback you need to check.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+
+class AnalysisOrderChecker : public Checker< check::PreStmt<CastExpr>,
+ check::PostStmt<CastExpr>,
+ check::PreStmt<ArraySubscriptExpr>,
+ check::PostStmt<ArraySubscriptExpr>> {
+ bool isCallbackEnabled(CheckerContext &C, StringRef CallbackName) const {
+ AnalyzerOptions &Opts = C.getAnalysisManager().getAnalyzerOptions();
+ return Opts.getBooleanOption("*", false, this) ||
+ Opts.getBooleanOption(CallbackName, false, this);
+ }
+
+public:
+ void checkPreStmt(const CastExpr *CE, CheckerContext &C) const {
+ if (isCallbackEnabled(C, "PreStmtCastExpr"))
+ llvm::errs() << "PreStmt<CastExpr> (Kind : " << CE->getCastKindName()
+ << ")\n";
+ }
+
+ void checkPostStmt(const CastExpr *CE, CheckerContext &C) const {
+ if (isCallbackEnabled(C, "PostStmtCastExpr"))
+ llvm::errs() << "PostStmt<CastExpr> (Kind : " << CE->getCastKindName()
+ << ")\n";
+ }
+
+ void checkPreStmt(const ArraySubscriptExpr *SubExpr, CheckerContext &C) const {
+ if (isCallbackEnabled(C, "PreStmtArraySubscriptExpr"))
+ llvm::errs() << "PreStmt<ArraySubscriptExpr>\n";
+ }
+
+ void checkPostStmt(const ArraySubscriptExpr *SubExpr, CheckerContext &C) const {
+ if (isCallbackEnabled(C, "PostStmtArraySubscriptExpr"))
+ llvm::errs() << "PostStmt<ArraySubscriptExpr>\n";
+ }
+};
+}
+
+//===----------------------------------------------------------------------===//
+// Registration.
+//===----------------------------------------------------------------------===//
+
+void ento::registerAnalysisOrderChecker(CheckerManager &mgr) {
+ mgr.registerChecker<AnalysisOrderChecker>();
+}
diff --git a/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp b/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp
index 13f0f655b89c..848c2662019a 100644
--- a/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp
+++ b/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp
@@ -17,6 +17,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/APSIntType.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
#include "llvm/ADT/SmallString.h"
@@ -67,18 +68,47 @@ public:
static SVal computeExtentBegin(SValBuilder &svalBuilder,
const MemRegion *region) {
- while (true)
- switch (region->getKind()) {
+ const MemSpaceRegion *SR = region->getMemorySpace();
+ if (SR->getKind() == MemRegion::UnknownSpaceRegionKind)
+ return UnknownVal();
+ else
+ return svalBuilder.makeZeroArrayIndex();
+}
+
+// TODO: once the constraint manager is smart enough to handle non simplified
+// symbolic expressions remove this function. Note that this can not be used in
+// the constraint manager as is, since this does not handle overflows. It is
+// safe to assume, however, that memory offsets will not overflow.
+static std::pair<NonLoc, nonloc::ConcreteInt>
+getSimplifiedOffsets(NonLoc offset, nonloc::ConcreteInt extent,
+ SValBuilder &svalBuilder) {
+ Optional<nonloc::SymbolVal> SymVal = offset.getAs<nonloc::SymbolVal>();
+ if (SymVal && SymVal->isExpression()) {
+ if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(SymVal->getSymbol())) {
+ llvm::APSInt constant =
+ APSIntType(extent.getValue()).convert(SIE->getRHS());
+ switch (SIE->getOpcode()) {
+ case BO_Mul:
+ // The constant should never be 0 here, since it the result of scaling
+ // based on the size of a type which is never 0.
+ if ((extent.getValue() % constant) != 0)
+ return std::pair<NonLoc, nonloc::ConcreteInt>(offset, extent);
+ else
+ return getSimplifiedOffsets(
+ nonloc::SymbolVal(SIE->getLHS()),
+ svalBuilder.makeIntVal(extent.getValue() / constant),
+ svalBuilder);
+ case BO_Add:
+ return getSimplifiedOffsets(
+ nonloc::SymbolVal(SIE->getLHS()),
+ svalBuilder.makeIntVal(extent.getValue() - constant), svalBuilder);
default:
- return svalBuilder.makeZeroArrayIndex();
- case MemRegion::SymbolicRegionKind:
- // FIXME: improve this later by tracking symbolic lower bounds
- // for symbolic regions.
- return UnknownVal();
- case MemRegion::ElementRegionKind:
- region = cast<SubRegion>(region)->getSuperRegion();
- continue;
+ break;
+ }
}
+ }
+
+ return std::pair<NonLoc, nonloc::ConcreteInt>(offset, extent);
}
void ArrayBoundCheckerV2::checkLocation(SVal location, bool isLoad,
@@ -104,6 +134,8 @@ void ArrayBoundCheckerV2::checkLocation(SVal location, bool isLoad,
if (!rawOffset.getRegion())
return;
+ NonLoc rawOffsetVal = rawOffset.getByteOffset();
+
// CHECK LOWER BOUND: Is byteOffset < extent begin?
// If so, we are doing a load/store
// before the first valid offset in the memory region.
@@ -111,9 +143,17 @@ void ArrayBoundCheckerV2::checkLocation(SVal location, bool isLoad,
SVal extentBegin = computeExtentBegin(svalBuilder, rawOffset.getRegion());
if (Optional<NonLoc> NV = extentBegin.getAs<NonLoc>()) {
- SVal lowerBound =
- svalBuilder.evalBinOpNN(state, BO_LT, rawOffset.getByteOffset(), *NV,
- svalBuilder.getConditionType());
+ if (NV->getAs<nonloc::ConcreteInt>()) {
+ std::pair<NonLoc, nonloc::ConcreteInt> simplifiedOffsets =
+ getSimplifiedOffsets(rawOffset.getByteOffset(),
+ NV->castAs<nonloc::ConcreteInt>(),
+ svalBuilder);
+ rawOffsetVal = simplifiedOffsets.first;
+ *NV = simplifiedOffsets.second;
+ }
+
+ SVal lowerBound = svalBuilder.evalBinOpNN(state, BO_LT, rawOffsetVal, *NV,
+ svalBuilder.getConditionType());
Optional<NonLoc> lowerBoundToCheck = lowerBound.getAs<NonLoc>();
if (!lowerBoundToCheck)
@@ -142,10 +182,18 @@ void ArrayBoundCheckerV2::checkLocation(SVal location, bool isLoad,
if (!extentVal.getAs<NonLoc>())
break;
- SVal upperbound
- = svalBuilder.evalBinOpNN(state, BO_GE, rawOffset.getByteOffset(),
- extentVal.castAs<NonLoc>(),
- svalBuilder.getConditionType());
+ if (extentVal.getAs<nonloc::ConcreteInt>()) {
+ std::pair<NonLoc, nonloc::ConcreteInt> simplifiedOffsets =
+ getSimplifiedOffsets(rawOffset.getByteOffset(),
+ extentVal.castAs<nonloc::ConcreteInt>(),
+ svalBuilder);
+ rawOffsetVal = simplifiedOffsets.first;
+ extentVal = simplifiedOffsets.second;
+ }
+
+ SVal upperbound = svalBuilder.evalBinOpNN(state, BO_GE, rawOffsetVal,
+ extentVal.castAs<NonLoc>(),
+ svalBuilder.getConditionType());
Optional<NonLoc> upperboundToCheck = upperbound.getAs<NonLoc>();
if (!upperboundToCheck)
@@ -157,13 +205,13 @@ 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()))
+ if (state->isTainted(rawOffset.getByteOffset())) {
reportOOB(checkerContext, state_exceedsUpperBound, OOB_Tainted);
return;
- }
-
- // If we are constrained enough to definitely exceed the upper bound, report.
- if (state_exceedsUpperBound) {
+ }
+ } else if (state_exceedsUpperBound) {
+ // If we are constrained enough to definitely exceed the upper bound,
+ // report.
assert(!state_withinUpperBound);
reportOOB(checkerContext, state_exceedsUpperBound, OOB_Excedes);
return;
diff --git a/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp b/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
index 6239c5507a4b..1ea85d60c9e9 100644
--- a/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
+++ b/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
@@ -336,15 +336,15 @@ void NilArgChecker::checkPostStmt(const ObjCDictionaryLiteral *DL,
}
//===----------------------------------------------------------------------===//
-// Error reporting.
+// Checking for mismatched types passed to CFNumberCreate/CFNumberGetValue.
//===----------------------------------------------------------------------===//
namespace {
-class CFNumberCreateChecker : public Checker< check::PreStmt<CallExpr> > {
+class CFNumberChecker : public Checker< check::PreStmt<CallExpr> > {
mutable std::unique_ptr<APIMisuse> BT;
- mutable IdentifierInfo* II;
+ mutable IdentifierInfo *ICreate, *IGetValue;
public:
- CFNumberCreateChecker() : II(nullptr) {}
+ CFNumberChecker() : ICreate(nullptr), IGetValue(nullptr) {}
void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
@@ -425,7 +425,7 @@ static const char* GetCFNumberTypeStr(uint64_t i) {
}
#endif
-void CFNumberCreateChecker::checkPreStmt(const CallExpr *CE,
+void CFNumberChecker::checkPreStmt(const CallExpr *CE,
CheckerContext &C) const {
ProgramStateRef state = C.getState();
const FunctionDecl *FD = C.getCalleeDecl(CE);
@@ -433,10 +433,12 @@ void CFNumberCreateChecker::checkPreStmt(const CallExpr *CE,
return;
ASTContext &Ctx = C.getASTContext();
- if (!II)
- II = &Ctx.Idents.get("CFNumberCreate");
-
- if (FD->getIdentifier() != II || CE->getNumArgs() != 3)
+ if (!ICreate) {
+ ICreate = &Ctx.Idents.get("CFNumberCreate");
+ IGetValue = &Ctx.Idents.get("CFNumberGetValue");
+ }
+ if (!(FD->getIdentifier() == ICreate || FD->getIdentifier() == IGetValue) ||
+ CE->getNumArgs() != 3)
return;
// Get the value of the "theType" argument.
@@ -450,13 +452,13 @@ void CFNumberCreateChecker::checkPreStmt(const CallExpr *CE,
return;
uint64_t NumberKind = V->getValue().getLimitedValue();
- Optional<uint64_t> OptTargetSize = GetCFNumberSize(Ctx, NumberKind);
+ Optional<uint64_t> OptCFNumberSize = GetCFNumberSize(Ctx, NumberKind);
// FIXME: In some cases we can emit an error.
- if (!OptTargetSize)
+ if (!OptCFNumberSize)
return;
- uint64_t TargetSize = *OptTargetSize;
+ uint64_t CFNumberSize = *OptCFNumberSize;
// 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
@@ -481,39 +483,44 @@ void CFNumberCreateChecker::checkPreStmt(const CallExpr *CE,
if (!T->isIntegralOrEnumerationType())
return;
- uint64_t SourceSize = Ctx.getTypeSize(T);
+ uint64_t PrimitiveTypeSize = Ctx.getTypeSize(T);
- // CHECK: is SourceSize == TargetSize
- if (SourceSize == TargetSize)
+ if (PrimitiveTypeSize == CFNumberSize)
return;
- // Generate an error. Only generate a sink error node
- // if 'SourceSize < TargetSize'; otherwise generate a non-fatal error node.
- //
// FIXME: We can actually create an abstract "CFNumber" object that has
// the bits initialized to the provided values.
- //
- ExplodedNode *N = SourceSize < TargetSize ? C.generateErrorNode()
- : C.generateNonFatalErrorNode();
+ ExplodedNode *N = C.generateNonFatalErrorNode();
if (N) {
SmallString<128> sbuf;
llvm::raw_svector_ostream os(sbuf);
+ bool isCreate = (FD->getIdentifier() == ICreate);
+
+ if (isCreate) {
+ os << (PrimitiveTypeSize == 8 ? "An " : "A ")
+ << PrimitiveTypeSize << "-bit integer is used to initialize a "
+ << "CFNumber object that represents "
+ << (CFNumberSize == 8 ? "an " : "a ")
+ << CFNumberSize << "-bit integer; ";
+ } else {
+ os << "A CFNumber object that represents "
+ << (CFNumberSize == 8 ? "an " : "a ")
+ << CFNumberSize << "-bit integer is used to initialize "
+ << (PrimitiveTypeSize == 8 ? "an " : "a ")
+ << PrimitiveTypeSize << "-bit integer; ";
+ }
- os << (SourceSize == 8 ? "An " : "A ")
- << SourceSize << " bit integer is used to initialize a CFNumber "
- "object that represents "
- << (TargetSize == 8 ? "an " : "a ")
- << TargetSize << " bit integer. ";
-
- if (SourceSize < TargetSize)
- os << (TargetSize - SourceSize)
- << " bits of the CFNumber value will be garbage." ;
+ if (PrimitiveTypeSize < CFNumberSize)
+ os << (CFNumberSize - PrimitiveTypeSize)
+ << " bits of the CFNumber value will "
+ << (isCreate ? "be garbage." : "overwrite adjacent storage.");
else
- os << (SourceSize - TargetSize)
- << " bits of the input integer will be lost.";
+ os << (PrimitiveTypeSize - CFNumberSize)
+ << " bits of the integer value will be "
+ << (isCreate ? "lost." : "garbage.");
if (!BT)
- BT.reset(new APIMisuse(this, "Bad use of CFNumberCreate"));
+ BT.reset(new APIMisuse(this, "Bad use of CFNumber APIs"));
auto report = llvm::make_unique<BugReport>(*BT, os.str(), N);
report->addRange(CE->getArg(2)->getSourceRange());
@@ -1272,8 +1279,8 @@ void ento::registerNilArgChecker(CheckerManager &mgr) {
mgr.registerChecker<NilArgChecker>();
}
-void ento::registerCFNumberCreateChecker(CheckerManager &mgr) {
- mgr.registerChecker<CFNumberCreateChecker>();
+void ento::registerCFNumberChecker(CheckerManager &mgr) {
+ mgr.registerChecker<CFNumberChecker>();
}
void ento::registerCFRetainReleaseChecker(CheckerManager &mgr) {
diff --git a/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp b/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp
new file mode 100644
index 000000000000..082a4873217b
--- /dev/null
+++ b/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp
@@ -0,0 +1,109 @@
+//===-- BlockInCriticalSectionChecker.cpp -----------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines a checker for blocks in critical sections. This checker should find
+// the calls to blocking functions (for example: sleep, getc, fgets, read,
+// recv etc.) inside a critical section. When sleep(x) is called while a mutex
+// is held, other threades cannot lock the same mutex. This might take some
+// time, leading to bad performance or even deadlock.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.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;
+
+namespace {
+
+class BlockInCriticalSectionChecker : public Checker<check::PostCall,
+ check::PreCall> {
+
+ CallDescription LockFn, UnlockFn, SleepFn, GetcFn, FgetsFn, ReadFn, RecvFn;
+
+ std::unique_ptr<BugType> BlockInCritSectionBugType;
+
+ void reportBlockInCritSection(SymbolRef FileDescSym,
+ const CallEvent &call,
+ CheckerContext &C) const;
+
+public:
+ BlockInCriticalSectionChecker();
+
+ void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
+
+ /// Process unlock.
+ /// Process lock.
+ /// Process blocking functions (sleep, getc, fgets, read, recv)
+ void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
+
+};
+
+} // end anonymous namespace
+
+REGISTER_TRAIT_WITH_PROGRAMSTATE(MutexCounter, unsigned)
+
+BlockInCriticalSectionChecker::BlockInCriticalSectionChecker()
+ : LockFn("lock"), UnlockFn("unlock"), SleepFn("sleep"), GetcFn("getc"),
+ FgetsFn("fgets"), ReadFn("read"), RecvFn("recv") {
+ // Initialize the bug type.
+ BlockInCritSectionBugType.reset(
+ new BugType(this, "Call to blocking function in critical section",
+ "Blocking Error"));
+}
+
+void BlockInCriticalSectionChecker::checkPreCall(const CallEvent &Call,
+ CheckerContext &C) const {
+}
+
+void BlockInCriticalSectionChecker::checkPostCall(const CallEvent &Call,
+ CheckerContext &C) const {
+ if (!Call.isCalled(LockFn)
+ && !Call.isCalled(SleepFn)
+ && !Call.isCalled(GetcFn)
+ && !Call.isCalled(FgetsFn)
+ && !Call.isCalled(ReadFn)
+ && !Call.isCalled(RecvFn)
+ && !Call.isCalled(UnlockFn))
+ return;
+
+ ProgramStateRef State = C.getState();
+ unsigned mutexCount = State->get<MutexCounter>();
+ if (Call.isCalled(UnlockFn) && mutexCount > 0) {
+ State = State->set<MutexCounter>(--mutexCount);
+ C.addTransition(State);
+ } else if (Call.isCalled(LockFn)) {
+ State = State->set<MutexCounter>(++mutexCount);
+ C.addTransition(State);
+ } else if (mutexCount > 0) {
+ SymbolRef BlockDesc = Call.getReturnValue().getAsSymbol();
+ reportBlockInCritSection(BlockDesc, Call, C);
+ }
+}
+
+void BlockInCriticalSectionChecker::reportBlockInCritSection(
+ SymbolRef BlockDescSym, const CallEvent &Call, CheckerContext &C) const {
+ ExplodedNode *ErrNode = C.generateNonFatalErrorNode();
+ if (!ErrNode)
+ return;
+
+ auto R = llvm::make_unique<BugReport>(*BlockInCritSectionBugType,
+ "A blocking function %s is called inside a critical section.", ErrNode);
+ R->addRange(Call.getSourceRange());
+ R->markInteresting(BlockDescSym);
+ C.emitReport(std::move(R));
+}
+
+void ento::registerBlockInCriticalSectionChecker(CheckerManager &mgr) {
+ mgr.registerChecker<BlockInCriticalSectionChecker>();
+}
diff --git a/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp b/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp
index dab2f61229a0..8c2aef21b3ca 100644
--- a/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp
@@ -55,6 +55,7 @@ bool BuiltinFunctionChecker::evalCall(const CallExpr *CE,
return true;
}
+ case Builtin::BI__builtin_alloca_with_align:
case Builtin::BI__builtin_alloca: {
// FIXME: Refactor into StoreManager itself?
MemRegionManager& RM = C.getStoreManager().getRegionManager();
diff --git a/lib/StaticAnalyzer/Checkers/CMakeLists.txt b/lib/StaticAnalyzer/Checkers/CMakeLists.txt
index 62ccc3cb4970..41415f0376c0 100644
--- a/lib/StaticAnalyzer/Checkers/CMakeLists.txt
+++ b/lib/StaticAnalyzer/Checkers/CMakeLists.txt
@@ -4,10 +4,12 @@ set(LLVM_LINK_COMPONENTS
add_clang_library(clangStaticAnalyzerCheckers
AllocationDiagnostics.cpp
+ AnalysisOrderChecker.cpp
AnalyzerStatsChecker.cpp
ArrayBoundChecker.cpp
ArrayBoundCheckerV2.cpp
BasicObjCFoundationChecks.cpp
+ BlockInCriticalSectionChecker.cpp
BoolAssignmentChecker.cpp
BuiltinFunctionChecker.cpp
CStringChecker.cpp
@@ -22,6 +24,9 @@ add_clang_library(clangStaticAnalyzerCheckers
CheckerDocumentation.cpp
ChrootChecker.cpp
ClangCheckers.cpp
+ CloneChecker.cpp
+ ConversionChecker.cpp
+ CXXSelfAssignmentChecker.cpp
DeadStoresChecker.cpp
DebugCheckers.cpp
DereferenceChecker.cpp
@@ -32,6 +37,7 @@ add_clang_library(clangStaticAnalyzerCheckers
ExprInspectionChecker.cpp
FixedAddressChecker.cpp
GenericTaintChecker.cpp
+ GTestChecker.cpp
IdenticalExprChecker.cpp
IvarInvalidationChecker.cpp
LLVMConventionsChecker.cpp
@@ -49,10 +55,12 @@ add_clang_library(clangStaticAnalyzerCheckers
NoReturnFunctionChecker.cpp
NonNullParamChecker.cpp
NullabilityChecker.cpp
+ NumberObjectConversionChecker.cpp
ObjCAtSyncChecker.cpp
ObjCContainersASTChecker.cpp
ObjCContainersChecker.cpp
ObjCMissingSuperCallChecker.cpp
+ ObjCPropertyChecker.cpp
ObjCSelfInitChecker.cpp
ObjCSuperDeallocChecker.cpp
ObjCUnusedIVarsChecker.cpp
@@ -65,6 +73,7 @@ add_clang_library(clangStaticAnalyzerCheckers
ReturnUndefChecker.cpp
SimpleStreamChecker.cpp
StackAddrEscapeChecker.cpp
+ StdLibraryFunctionsChecker.cpp
StreamChecker.cpp
TaintTesterChecker.cpp
TestAfterDivZeroChecker.cpp
@@ -78,6 +87,7 @@ add_clang_library(clangStaticAnalyzerCheckers
UnreachableCodeChecker.cpp
VforkChecker.cpp
VLASizeChecker.cpp
+ ValistChecker.cpp
VirtualCallChecker.cpp
DEPENDS
@@ -85,6 +95,7 @@ add_clang_library(clangStaticAnalyzerCheckers
LINK_LIBS
clangAST
+ clangASTMatchers
clangAnalysis
clangBasic
clangLex
diff --git a/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
index e9512977fa6d..238032c895f6 100644
--- a/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
@@ -22,7 +22,6 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
@@ -63,7 +62,6 @@ public:
void checkPreStmt(const DeclStmt *DS, CheckerContext &C) const;
void checkLiveSymbols(ProgramStateRef state, SymbolReaper &SR) const;
void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const;
- bool wantsRegionChangeUpdate(ProgramStateRef state) const;
ProgramStateRef
checkRegionChanges(ProgramStateRef state,
@@ -686,6 +684,7 @@ SVal CStringChecker::getCStringLengthForRegion(CheckerContext &C,
QualType sizeTy = svalBuilder.getContext().getSizeType();
SVal strLength = svalBuilder.getMetadataSymbolVal(CStringChecker::getTag(),
MR, Ex, sizeTy,
+ C.getLocationContext(),
C.blockCount());
if (!hypothetical) {
@@ -2112,11 +2111,6 @@ void CStringChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const {
C.addTransition(state);
}
-bool CStringChecker::wantsRegionChangeUpdate(ProgramStateRef state) const {
- CStringLengthTy Entries = state->get<CStringLength>();
- return !Entries.isEmpty();
-}
-
ProgramStateRef
CStringChecker::checkRegionChanges(ProgramStateRef state,
const InvalidatedSymbols *,
diff --git a/lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp b/lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp
new file mode 100644
index 000000000000..7631322d255b
--- /dev/null
+++ b/lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp
@@ -0,0 +1,62 @@
+//=== CXXSelfAssignmentChecker.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 CXXSelfAssignmentChecker, which tests all custom defined
+// copy and move assignment operators for the case of self assignment, thus
+// where the parameter refers to the same location where the this pointer
+// points to. The checker itself does not do any checks at all, but it
+// causes the analyzer to check every copy and move assignment operator twice:
+// once for when 'this' aliases with the parameter and once for when it may not.
+// It is the task of the other enabled checkers to find the bugs in these two
+// different cases.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+
+class CXXSelfAssignmentChecker : public Checker<check::BeginFunction> {
+public:
+ CXXSelfAssignmentChecker();
+ void checkBeginFunction(CheckerContext &C) const;
+};
+}
+
+CXXSelfAssignmentChecker::CXXSelfAssignmentChecker() {}
+
+void CXXSelfAssignmentChecker::checkBeginFunction(CheckerContext &C) const {
+ if (!C.inTopFrame())
+ return;
+ const auto *LCtx = C.getLocationContext();
+ const auto *MD = dyn_cast<CXXMethodDecl>(LCtx->getDecl());
+ if (!MD)
+ return;
+ if (!MD->isCopyAssignmentOperator() && !MD->isMoveAssignmentOperator())
+ return;
+ auto &State = C.getState();
+ auto &SVB = C.getSValBuilder();
+ auto ThisVal =
+ State->getSVal(SVB.getCXXThis(MD, LCtx->getCurrentStackFrame()));
+ auto Param = SVB.makeLoc(State->getRegion(MD->getParamDecl(0), LCtx));
+ auto ParamVal = State->getSVal(Param);
+ ProgramStateRef SelfAssignState = State->bindLoc(Param, ThisVal);
+ C.addTransition(SelfAssignState);
+ ProgramStateRef NonSelfAssignState = State->bindLoc(Param, ParamVal);
+ C.addTransition(NonSelfAssignState);
+}
+
+void ento::registerCXXSelfAssignmentChecker(CheckerManager &Mgr) {
+ Mgr.registerChecker<CXXSelfAssignmentChecker>();
+}
diff --git a/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp b/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
index 5126716fcded..f474857a1bf4 100644
--- a/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
@@ -356,7 +356,6 @@ void CallAndMessageChecker::checkPreStmt(const CXXDeleteExpr *DE,
}
}
-
void CallAndMessageChecker::checkPreCall(const CallEvent &Call,
CheckerContext &C) const {
ProgramStateRef State = C.getState();
@@ -389,11 +388,10 @@ void CallAndMessageChecker::checkPreCall(const CallEvent &Call,
}
const Decl *D = Call.getDecl();
- const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
- if (FD) {
- // If we have a declaration, we can make sure we pass enough parameters to
- // the function.
- unsigned Params = FD->getNumParams();
+ if (D && (isa<FunctionDecl>(D) || isa<BlockDecl>(D))) {
+ // If we have a function or block declaration, we can make sure we pass
+ // enough parameters.
+ unsigned Params = Call.parameters().size();
if (Call.getNumArgs() < Params) {
ExplodedNode *N = C.generateErrorNode();
if (!N)
@@ -403,8 +401,14 @@ void CallAndMessageChecker::checkPreCall(const CallEvent &Call,
SmallString<512> Str;
llvm::raw_svector_ostream os(Str);
- os << "Function taking " << Params << " argument"
- << (Params == 1 ? "" : "s") << " is called with less ("
+ if (isa<FunctionDecl>(D)) {
+ os << "Function ";
+ } else {
+ assert(isa<BlockDecl>(D));
+ os << "Block ";
+ }
+ os << "taking " << Params << " argument"
+ << (Params == 1 ? "" : "s") << " is called with fewer ("
<< Call.getNumArgs() << ")";
C.emitReport(
@@ -425,6 +429,7 @@ void CallAndMessageChecker::checkPreCall(const CallEvent &Call,
else
BT = &BT_call_arg;
+ const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
for (unsigned i = 0, e = Call.getNumArgs(); i != e; ++i) {
const ParmVarDecl *ParamDecl = nullptr;
if(FD && i < FD->getNumParams())
diff --git a/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp b/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp
index 2337400750c7..3e178152d925 100644
--- a/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp
@@ -140,5 +140,10 @@ void CastSizeChecker::checkPreStmt(const CastExpr *CE,CheckerContext &C) const {
}
void ento::registerCastSizeChecker(CheckerManager &mgr) {
- mgr.registerChecker<CastSizeChecker>();
+ // PR31226: C++ is more complicated than what this checker currently supports.
+ // There are derived-to-base casts, there are different rules for 0-size
+ // structures, no flexible arrays, etc.
+ // FIXME: Disabled on C++ for now.
+ if (!mgr.getLangOpts().CPlusPlus)
+ mgr.registerChecker<CastSizeChecker>();
}
diff --git a/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp b/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp
index fa7841356efb..16a475ae9dd2 100644
--- a/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp
@@ -1,4 +1,4 @@
-//=== CastToStructChecker.cpp - Fixed address usage checker ----*- C++ -*--===//
+//=== CastToStructChecker.cpp ----------------------------------*- C++ -*--===//
//
// The LLVM Compiler Infrastructure
//
@@ -8,12 +8,13 @@
//===----------------------------------------------------------------------===//
//
// This files defines CastToStructChecker, a builtin checker that checks for
-// cast from non-struct pointer to struct pointer.
+// cast from non-struct pointer to struct pointer and widening struct data cast.
// This check corresponds to CWE-588.
//
//===----------------------------------------------------------------------===//
#include "ClangSACheckers.h"
+#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
@@ -23,18 +24,22 @@ using namespace clang;
using namespace ento;
namespace {
-class CastToStructChecker : public Checker< check::PreStmt<CastExpr> > {
- mutable std::unique_ptr<BuiltinBug> BT;
+class CastToStructVisitor : public RecursiveASTVisitor<CastToStructVisitor> {
+ BugReporter &BR;
+ const CheckerBase *Checker;
+ AnalysisDeclContext *AC;
public:
- void checkPreStmt(const CastExpr *CE, CheckerContext &C) const;
+ explicit CastToStructVisitor(BugReporter &B, const CheckerBase *Checker,
+ AnalysisDeclContext *A)
+ : BR(B), Checker(Checker), AC(A) {}
+ bool VisitCastExpr(const CastExpr *CE);
};
}
-void CastToStructChecker::checkPreStmt(const CastExpr *CE,
- CheckerContext &C) const {
+bool CastToStructVisitor::VisitCastExpr(const CastExpr *CE) {
const Expr *E = CE->getSubExpr();
- ASTContext &Ctx = C.getASTContext();
+ ASTContext &Ctx = AC->getASTContext();
QualType OrigTy = Ctx.getCanonicalType(E->getType());
QualType ToTy = Ctx.getCanonicalType(CE->getType());
@@ -42,34 +47,72 @@ void CastToStructChecker::checkPreStmt(const CastExpr *CE,
const PointerType *ToPTy = dyn_cast<PointerType>(ToTy.getTypePtr());
if (!ToPTy || !OrigPTy)
- return;
+ return true;
QualType OrigPointeeTy = OrigPTy->getPointeeType();
QualType ToPointeeTy = ToPTy->getPointeeType();
if (!ToPointeeTy->isStructureOrClassType())
- return;
+ return true;
// We allow cast from void*.
if (OrigPointeeTy->isVoidType())
- return;
+ return true;
// Now the cast-to-type is struct pointer, the original type is not void*.
if (!OrigPointeeTy->isRecordType()) {
- if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
- if (!BT)
- BT.reset(
- new BuiltinBug(this, "Cast from non-struct type to struct type",
- "Casting a non-structure type to a structure type "
- "and accessing a field can lead to memory access "
- "errors or data corruption."));
- auto R = llvm::make_unique<BugReport>(*BT, BT->getDescription(), N);
- R->addRange(CE->getSourceRange());
- C.emitReport(std::move(R));
- }
+ SourceRange Sr[1] = {CE->getSourceRange()};
+ PathDiagnosticLocation Loc(CE, BR.getSourceManager(), AC);
+ BR.EmitBasicReport(
+ AC->getDecl(), Checker, "Cast from non-struct type to struct type",
+ categories::LogicError, "Casting a non-structure type to a structure "
+ "type and accessing a field can lead to memory "
+ "access errors or data corruption.",
+ Loc, Sr);
+ } else {
+ // Don't warn when size of data is unknown.
+ const auto *U = dyn_cast<UnaryOperator>(E);
+ if (!U || U->getOpcode() != UO_AddrOf)
+ return true;
+
+ // Don't warn for references
+ const ValueDecl *VD = nullptr;
+ if (const auto *SE = dyn_cast<DeclRefExpr>(U->getSubExpr()))
+ VD = dyn_cast<ValueDecl>(SE->getDecl());
+ else if (const auto *SE = dyn_cast<MemberExpr>(U->getSubExpr()))
+ VD = SE->getMemberDecl();
+ if (!VD || VD->getType()->isReferenceType())
+ return true;
+
+ // Warn when there is widening cast.
+ unsigned ToWidth = Ctx.getTypeInfo(ToPointeeTy).Width;
+ unsigned OrigWidth = Ctx.getTypeInfo(OrigPointeeTy).Width;
+ if (ToWidth <= OrigWidth)
+ return true;
+
+ PathDiagnosticLocation Loc(CE, BR.getSourceManager(), AC);
+ BR.EmitBasicReport(AC->getDecl(), Checker, "Widening cast to struct type",
+ categories::LogicError,
+ "Casting data to a larger structure type and accessing "
+ "a field can lead to memory access errors or data "
+ "corruption.",
+ Loc, CE->getSourceRange());
}
+
+ return true;
}
+namespace {
+class CastToStructChecker : public Checker<check::ASTCodeBody> {
+public:
+ void checkASTCodeBody(const Decl *D, AnalysisManager &Mgr,
+ BugReporter &BR) const {
+ CastToStructVisitor Visitor(BR, this, Mgr.getAnalysisDeclContext(D));
+ Visitor.TraverseDecl(const_cast<Decl *>(D));
+ }
+};
+} // end anonymous namespace
+
void ento::registerCastToStructChecker(CheckerManager &mgr) {
mgr.registerChecker<CastToStructChecker>();
}
diff --git a/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp b/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp
index 9e863e79e41f..2818c9d9fd4a 100644
--- a/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp
+++ b/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp
@@ -34,6 +34,7 @@
#include "clang/AST/Expr.h"
#include "clang/AST/ExprObjC.h"
#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/TargetInfo.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
@@ -173,6 +174,7 @@ private:
bool classHasSeparateTeardown(const ObjCInterfaceDecl *ID) const;
bool isReleasedByCIFilterDealloc(const ObjCPropertyImplDecl *PropImpl) const;
+ bool isNibLoadedIvarWithoutRetain(const ObjCPropertyImplDecl *PropImpl) const;
};
} // End anonymous namespace.
@@ -525,7 +527,7 @@ void ObjCDeallocChecker::diagnoseMissingReleases(CheckerContext &C) const {
if (SelfRegion != IvarRegion->getSuperRegion())
continue;
- const ObjCIvarDecl *IvarDecl = IvarRegion->getDecl();
+ const ObjCIvarDecl *IvarDecl = IvarRegion->getDecl();
// Prevent an inlined call to -dealloc in a super class from warning
// about the values the subclass's -dealloc should release.
if (IvarDecl->getContainingInterface() !=
@@ -903,6 +905,9 @@ ReleaseRequirement ObjCDeallocChecker::getDeallocReleaseRequirement(
if (isReleasedByCIFilterDealloc(PropImpl))
return ReleaseRequirement::MustNotReleaseDirectly;
+ if (isNibLoadedIvarWithoutRetain(PropImpl))
+ return ReleaseRequirement::Unknown;
+
return ReleaseRequirement::MustRelease;
case ObjCPropertyDecl::Weak:
@@ -1059,6 +1064,32 @@ bool ObjCDeallocChecker::isReleasedByCIFilterDealloc(
return false;
}
+/// Returns whether the ivar backing the property is an IBOutlet that
+/// has its value set by nib loading code without retaining the value.
+///
+/// On macOS, if there is no setter, the nib-loading code sets the ivar
+/// directly, without retaining the value,
+///
+/// On iOS and its derivatives, the nib-loading code will call
+/// -setValue:forKey:, which retains the value before directly setting the ivar.
+bool ObjCDeallocChecker::isNibLoadedIvarWithoutRetain(
+ const ObjCPropertyImplDecl *PropImpl) const {
+ const ObjCIvarDecl *IvarDecl = PropImpl->getPropertyIvarDecl();
+ if (!IvarDecl->hasAttr<IBOutletAttr>())
+ return false;
+
+ const llvm::Triple &Target =
+ IvarDecl->getASTContext().getTargetInfo().getTriple();
+
+ if (!Target.isMacOSX())
+ return false;
+
+ if (PropImpl->getPropertyDecl()->getSetterMethodDecl())
+ return false;
+
+ return true;
+}
+
void ento::registerObjCDeallocChecker(CheckerManager &Mgr) {
const LangOptions &LangOpts = Mgr.getLangOpts();
// These checker only makes sense under MRR.
diff --git a/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp b/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp
index 74d05e27e8eb..86764c939dcd 100644
--- a/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp
+++ b/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp
@@ -45,6 +45,7 @@ class CheckerDocumentation : public Checker< check::PreStmt<ReturnStmt>,
check::Location,
check::Bind,
check::DeadSymbols,
+ check::BeginFunction,
check::EndFunction,
check::EndAnalysis,
check::EndOfTranslationUnit,
diff --git a/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp b/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
index 14587fb5163b..9e9939ae25c0 100644
--- a/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
@@ -19,7 +19,6 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
-#include "llvm/ADT/ImmutableMap.h"
using namespace clang;
using namespace ento;
diff --git a/lib/StaticAnalyzer/Checkers/CloneChecker.cpp b/lib/StaticAnalyzer/Checkers/CloneChecker.cpp
new file mode 100644
index 000000000000..6fa5732d10cb
--- /dev/null
+++ b/lib/StaticAnalyzer/Checkers/CloneChecker.cpp
@@ -0,0 +1,161 @@
+//===--- CloneChecker.cpp - Clone detection checker -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// CloneChecker is a checker that reports clones in the current translation
+/// unit.
+///
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/Analysis/CloneDetection.h"
+#include "clang/Basic/Diagnostic.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/AnalysisManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class CloneChecker
+ : public Checker<check::ASTCodeBody, check::EndOfTranslationUnit> {
+ mutable CloneDetector Detector;
+ mutable std::unique_ptr<BugType> BT_Exact, BT_Suspicious;
+
+public:
+ void checkASTCodeBody(const Decl *D, AnalysisManager &Mgr,
+ BugReporter &BR) const;
+
+ void checkEndOfTranslationUnit(const TranslationUnitDecl *TU,
+ AnalysisManager &Mgr, BugReporter &BR) const;
+
+ /// \brief Reports all clones to the user.
+ void reportClones(BugReporter &BR, AnalysisManager &Mgr,
+ int MinComplexity) const;
+
+ /// \brief Reports only suspicious clones to the user along with informaton
+ /// that explain why they are suspicious.
+ void reportSuspiciousClones(BugReporter &BR, AnalysisManager &Mgr,
+ int MinComplexity) const;
+};
+} // end anonymous namespace
+
+void CloneChecker::checkASTCodeBody(const Decl *D, AnalysisManager &Mgr,
+ BugReporter &BR) const {
+ // Every statement that should be included in the search for clones needs to
+ // be passed to the CloneDetector.
+ Detector.analyzeCodeBody(D);
+}
+
+void CloneChecker::checkEndOfTranslationUnit(const TranslationUnitDecl *TU,
+ AnalysisManager &Mgr,
+ BugReporter &BR) const {
+ // At this point, every statement in the translation unit has been analyzed by
+ // the CloneDetector. The only thing left to do is to report the found clones.
+
+ int MinComplexity = Mgr.getAnalyzerOptions().getOptionAsInteger(
+ "MinimumCloneComplexity", 10, this);
+ assert(MinComplexity >= 0);
+
+ bool ReportSuspiciousClones = Mgr.getAnalyzerOptions().getBooleanOption(
+ "ReportSuspiciousClones", true, this);
+
+ bool ReportNormalClones = Mgr.getAnalyzerOptions().getBooleanOption(
+ "ReportNormalClones", true, this);
+
+ if (ReportSuspiciousClones)
+ reportSuspiciousClones(BR, Mgr, MinComplexity);
+
+ if (ReportNormalClones)
+ reportClones(BR, Mgr, MinComplexity);
+}
+
+static PathDiagnosticLocation makeLocation(const StmtSequence &S,
+ AnalysisManager &Mgr) {
+ ASTContext &ACtx = Mgr.getASTContext();
+ return PathDiagnosticLocation::createBegin(
+ S.front(), ACtx.getSourceManager(),
+ Mgr.getAnalysisDeclContext(ACtx.getTranslationUnitDecl()));
+}
+
+void CloneChecker::reportClones(BugReporter &BR, AnalysisManager &Mgr,
+ int MinComplexity) const {
+
+ std::vector<CloneDetector::CloneGroup> CloneGroups;
+ Detector.findClones(CloneGroups, MinComplexity);
+
+ if (!BT_Exact)
+ BT_Exact.reset(new BugType(this, "Exact code clone", "Code clone"));
+
+ for (CloneDetector::CloneGroup &Group : CloneGroups) {
+ // We group the clones by printing the first as a warning and all others
+ // as a note.
+ auto R = llvm::make_unique<BugReport>(
+ *BT_Exact, "Duplicate code detected",
+ makeLocation(Group.Sequences.front(), Mgr));
+ R->addRange(Group.Sequences.front().getSourceRange());
+
+ for (unsigned i = 1; i < Group.Sequences.size(); ++i)
+ R->addNote("Similar code here",
+ makeLocation(Group.Sequences[i], Mgr),
+ Group.Sequences[i].getSourceRange());
+ BR.emitReport(std::move(R));
+ }
+}
+
+void CloneChecker::reportSuspiciousClones(BugReporter &BR,
+ AnalysisManager &Mgr,
+ int MinComplexity) const {
+
+ std::vector<CloneDetector::SuspiciousClonePair> Clones;
+ Detector.findSuspiciousClones(Clones, MinComplexity);
+
+ if (!BT_Suspicious)
+ BT_Suspicious.reset(
+ new BugType(this, "Suspicious code clone", "Code clone"));
+
+ ASTContext &ACtx = BR.getContext();
+ SourceManager &SM = ACtx.getSourceManager();
+ AnalysisDeclContext *ADC =
+ Mgr.getAnalysisDeclContext(ACtx.getTranslationUnitDecl());
+
+ for (CloneDetector::SuspiciousClonePair &Pair : Clones) {
+ // FIXME: We are ignoring the suggestions currently, because they are
+ // only 50% accurate (even if the second suggestion is unavailable),
+ // which may confuse the user.
+ // Think how to perform more accurate suggestions?
+
+ auto R = llvm::make_unique<BugReport>(
+ *BT_Suspicious,
+ "Potential copy-paste error; did you really mean to use '" +
+ Pair.FirstCloneInfo.Variable->getNameAsString() + "' here?",
+ PathDiagnosticLocation::createBegin(Pair.FirstCloneInfo.Mention, SM,
+ ADC));
+ R->addRange(Pair.FirstCloneInfo.Mention->getSourceRange());
+
+ R->addNote("Similar code using '" +
+ Pair.SecondCloneInfo.Variable->getNameAsString() + "' here",
+ PathDiagnosticLocation::createBegin(Pair.SecondCloneInfo.Mention,
+ SM, ADC),
+ Pair.SecondCloneInfo.Mention->getSourceRange());
+
+ BR.emitReport(std::move(R));
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Register CloneChecker
+//===----------------------------------------------------------------------===//
+
+void ento::registerCloneChecker(CheckerManager &Mgr) {
+ Mgr.registerChecker<CloneChecker>();
+}
diff --git a/lib/StaticAnalyzer/Checkers/ConversionChecker.cpp b/lib/StaticAnalyzer/Checkers/ConversionChecker.cpp
new file mode 100644
index 000000000000..2bb9e858731c
--- /dev/null
+++ b/lib/StaticAnalyzer/Checkers/ConversionChecker.cpp
@@ -0,0 +1,192 @@
+//=== ConversionChecker.cpp -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Check that there is no loss of sign/precision in assignments, comparisons
+// and multiplications.
+//
+// ConversionChecker uses path sensitive analysis to determine possible values
+// of expressions. A warning is reported when:
+// * a negative value is implicitly converted to an unsigned value in an
+// assignment, comparison or multiplication.
+// * assignment / initialization when source value is greater than the max
+// value of target
+//
+// Many compilers and tools have similar checks that are based on semantic
+// analysis. Those checks are sound but have poor precision. ConversionChecker
+// is an alternative to those checks.
+//
+//===----------------------------------------------------------------------===//
+#include "ClangSACheckers.h"
+#include "clang/AST/ParentMap.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class ConversionChecker : public Checker<check::PreStmt<ImplicitCastExpr>> {
+public:
+ void checkPreStmt(const ImplicitCastExpr *Cast, CheckerContext &C) const;
+
+private:
+ mutable std::unique_ptr<BuiltinBug> BT;
+
+ // Is there loss of precision
+ bool isLossOfPrecision(const ImplicitCastExpr *Cast, CheckerContext &C) const;
+
+ // Is there loss of sign
+ bool isLossOfSign(const ImplicitCastExpr *Cast, CheckerContext &C) const;
+
+ void reportBug(ExplodedNode *N, CheckerContext &C, const char Msg[]) const;
+};
+}
+
+void ConversionChecker::checkPreStmt(const ImplicitCastExpr *Cast,
+ CheckerContext &C) const {
+ // TODO: For now we only warn about DeclRefExpr, to avoid noise. Warn for
+ // calculations also.
+ if (!isa<DeclRefExpr>(Cast->IgnoreParenImpCasts()))
+ return;
+
+ // Don't warn for loss of sign/precision in macros.
+ if (Cast->getExprLoc().isMacroID())
+ return;
+
+ // Get Parent.
+ const ParentMap &PM = C.getLocationContext()->getParentMap();
+ const Stmt *Parent = PM.getParent(Cast);
+ if (!Parent)
+ return;
+
+ bool LossOfSign = false;
+ bool LossOfPrecision = false;
+
+ // Loss of sign/precision in binary operation.
+ if (const auto *B = dyn_cast<BinaryOperator>(Parent)) {
+ BinaryOperator::Opcode Opc = B->getOpcode();
+ if (Opc == BO_Assign || Opc == BO_AddAssign || Opc == BO_SubAssign ||
+ Opc == BO_MulAssign) {
+ LossOfSign = isLossOfSign(Cast, C);
+ LossOfPrecision = isLossOfPrecision(Cast, C);
+ } else if (B->isRelationalOp() || B->isMultiplicativeOp()) {
+ LossOfSign = isLossOfSign(Cast, C);
+ }
+ } else if (isa<DeclStmt>(Parent)) {
+ LossOfSign = isLossOfSign(Cast, C);
+ LossOfPrecision = isLossOfPrecision(Cast, C);
+ }
+
+ if (LossOfSign || LossOfPrecision) {
+ // Generate an error node.
+ ExplodedNode *N = C.generateNonFatalErrorNode(C.getState());
+ if (!N)
+ return;
+ if (LossOfSign)
+ reportBug(N, C, "Loss of sign in implicit conversion");
+ if (LossOfPrecision)
+ reportBug(N, C, "Loss of precision in implicit conversion");
+ }
+}
+
+void ConversionChecker::reportBug(ExplodedNode *N, CheckerContext &C,
+ const char Msg[]) const {
+ if (!BT)
+ BT.reset(
+ new BuiltinBug(this, "Conversion", "Possible loss of sign/precision."));
+
+ // Generate a report for this bug.
+ auto R = llvm::make_unique<BugReport>(*BT, Msg, N);
+ C.emitReport(std::move(R));
+}
+
+// Is E value greater or equal than Val?
+static bool isGreaterEqual(CheckerContext &C, const Expr *E,
+ unsigned long long Val) {
+ ProgramStateRef State = C.getState();
+ SVal EVal = C.getSVal(E);
+ if (EVal.isUnknownOrUndef() || !EVal.getAs<NonLoc>())
+ return false;
+
+ SValBuilder &Bldr = C.getSValBuilder();
+ DefinedSVal V = Bldr.makeIntVal(Val, C.getASTContext().LongLongTy);
+
+ // Is DefinedEVal greater or equal with V?
+ SVal GE = Bldr.evalBinOp(State, BO_GE, EVal, V, Bldr.getConditionType());
+ if (GE.isUnknownOrUndef())
+ return false;
+ ConstraintManager &CM = C.getConstraintManager();
+ ProgramStateRef StGE, StLT;
+ std::tie(StGE, StLT) = CM.assumeDual(State, GE.castAs<DefinedSVal>());
+ return StGE && !StLT;
+}
+
+// Is E value negative?
+static bool isNegative(CheckerContext &C, const Expr *E) {
+ ProgramStateRef State = C.getState();
+ SVal EVal = State->getSVal(E, C.getLocationContext());
+ if (EVal.isUnknownOrUndef() || !EVal.getAs<NonLoc>())
+ return false;
+ DefinedSVal DefinedEVal = EVal.castAs<DefinedSVal>();
+
+ SValBuilder &Bldr = C.getSValBuilder();
+ DefinedSVal V = Bldr.makeIntVal(0, false);
+
+ SVal LT =
+ Bldr.evalBinOp(State, BO_LT, DefinedEVal, V, Bldr.getConditionType());
+
+ // Is E value greater than MaxVal?
+ ConstraintManager &CM = C.getConstraintManager();
+ ProgramStateRef StNegative, StPositive;
+ std::tie(StNegative, StPositive) =
+ CM.assumeDual(State, LT.castAs<DefinedSVal>());
+
+ return StNegative && !StPositive;
+}
+
+bool ConversionChecker::isLossOfPrecision(const ImplicitCastExpr *Cast,
+ CheckerContext &C) const {
+ // Don't warn about explicit loss of precision.
+ if (Cast->isEvaluatable(C.getASTContext()))
+ return false;
+
+ QualType CastType = Cast->getType();
+ QualType SubType = Cast->IgnoreParenImpCasts()->getType();
+
+ if (!CastType->isIntegerType() || !SubType->isIntegerType())
+ return false;
+
+ if (C.getASTContext().getIntWidth(CastType) >=
+ C.getASTContext().getIntWidth(SubType))
+ return false;
+
+ unsigned W = C.getASTContext().getIntWidth(CastType);
+ if (W == 1 || W >= 64U)
+ return false;
+
+ unsigned long long MaxVal = 1ULL << W;
+ return isGreaterEqual(C, Cast->getSubExpr(), MaxVal);
+}
+
+bool ConversionChecker::isLossOfSign(const ImplicitCastExpr *Cast,
+ CheckerContext &C) const {
+ QualType CastType = Cast->getType();
+ QualType SubType = Cast->IgnoreParenImpCasts()->getType();
+
+ if (!CastType->isUnsignedIntegerType() || !SubType->isSignedIntegerType())
+ return false;
+
+ return isNegative(C, Cast->getSubExpr());
+}
+
+void ento::registerConversionChecker(CheckerManager &mgr) {
+ mgr.registerChecker<ConversionChecker>();
+}
diff --git a/lib/StaticAnalyzer/Checkers/DynamicTypeChecker.cpp b/lib/StaticAnalyzer/Checkers/DynamicTypeChecker.cpp
index 7e0cb8e93395..a37ebc506d04 100644
--- a/lib/StaticAnalyzer/Checkers/DynamicTypeChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/DynamicTypeChecker.cpp
@@ -107,12 +107,7 @@ PathDiagnosticPiece *DynamicTypeChecker::DynamicTypeBugVisitor::VisitNode(
return nullptr;
// Retrieve the associated statement.
- const Stmt *S = nullptr;
- ProgramPoint ProgLoc = N->getLocation();
- if (Optional<StmtPoint> SP = ProgLoc.getAs<StmtPoint>()) {
- S = SP->getStmt();
- }
-
+ const Stmt *S = PathDiagnosticLocation::getStmt(N);
if (!S)
return nullptr;
diff --git a/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp b/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
index b8e43325da04..a418c82f5a01 100644
--- a/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
+++ b/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
@@ -626,7 +626,7 @@ static bool isObjCTypeParamDependent(QualType Type) {
: public RecursiveASTVisitor<IsObjCTypeParamDependentTypeVisitor> {
public:
IsObjCTypeParamDependentTypeVisitor() : Result(false) {}
- bool VisitTypedefType(const TypedefType *Type) {
+ bool VisitObjCTypeParamType(const ObjCTypeParamType *Type) {
if (isa<ObjCTypeParamDecl>(Type->getDecl())) {
Result = true;
return false;
@@ -727,6 +727,37 @@ void DynamicTypePropagation::checkPreObjCMessage(const ObjCMethodCall &M,
if (!Method)
return;
+ // If the method is declared on a class that has a non-invariant
+ // type parameter, don't warn about parameter mismatches after performing
+ // substitution. This prevents warning when the programmer has purposely
+ // casted the receiver to a super type or unspecialized type but the analyzer
+ // has a more precise tracked type than the programmer intends at the call
+ // site.
+ //
+ // For example, consider NSArray (which has a covariant type parameter)
+ // and NSMutableArray (a subclass of NSArray where the type parameter is
+ // invariant):
+ // NSMutableArray *a = [[NSMutableArray<NSString *> alloc] init;
+ //
+ // [a containsObject:number]; // Safe: -containsObject is defined on NSArray.
+ // NSArray<NSObject *> *other = [a arrayByAddingObject:number] // Safe
+ //
+ // [a addObject:number] // Unsafe: -addObject: is defined on NSMutableArray
+ //
+
+ const ObjCInterfaceDecl *Interface = Method->getClassInterface();
+ if (!Interface)
+ return;
+
+ ObjCTypeParamList *TypeParams = Interface->getTypeParamList();
+ if (!TypeParams)
+ return;
+
+ for (ObjCTypeParamDecl *TypeParam : *TypeParams) {
+ if (TypeParam->getVariance() != ObjCTypeParamVariance::Invariant)
+ return;
+ }
+
Optional<ArrayRef<QualType>> TypeArgs =
(*TrackedType)->getObjCSubstitutions(Method->getDeclContext());
// This case might happen when there is an unspecialized override of a
@@ -909,12 +940,7 @@ PathDiagnosticPiece *DynamicTypePropagation::GenericsBugVisitor::VisitNode(
return nullptr;
// Retrieve the associated statement.
- const Stmt *S = nullptr;
- ProgramPoint ProgLoc = N->getLocation();
- if (Optional<StmtPoint> SP = ProgLoc.getAs<StmtPoint>()) {
- S = SP->getStmt();
- }
-
+ const Stmt *S = PathDiagnosticLocation::getStmt(N);
if (!S)
return nullptr;
diff --git a/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp b/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
index 31e9150cc15b..2d5cb60edf7d 100644
--- a/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
@@ -18,25 +18,41 @@ using namespace clang;
using namespace ento;
namespace {
-class ExprInspectionChecker : public Checker<eval::Call, check::DeadSymbols> {
+class ExprInspectionChecker : public Checker<eval::Call, check::DeadSymbols,
+ check::EndAnalysis> {
mutable std::unique_ptr<BugType> BT;
+ // These stats are per-analysis, not per-branch, hence they shouldn't
+ // stay inside the program state.
+ struct ReachedStat {
+ ExplodedNode *ExampleNode;
+ unsigned NumTimesReached;
+ };
+ mutable llvm::DenseMap<const CallExpr *, ReachedStat> ReachedStats;
+
void analyzerEval(const CallExpr *CE, CheckerContext &C) const;
void analyzerCheckInlined(const CallExpr *CE, CheckerContext &C) const;
void analyzerWarnIfReached(const CallExpr *CE, CheckerContext &C) const;
+ void analyzerNumTimesReached(const CallExpr *CE, CheckerContext &C) const;
void analyzerCrash(const CallExpr *CE, CheckerContext &C) const;
void analyzerWarnOnDeadSymbol(const CallExpr *CE, CheckerContext &C) const;
+ void analyzerDump(const CallExpr *CE, CheckerContext &C) const;
void analyzerExplain(const CallExpr *CE, CheckerContext &C) const;
+ void analyzerPrintState(const CallExpr *CE, CheckerContext &C) const;
void analyzerGetExtent(const CallExpr *CE, CheckerContext &C) const;
typedef void (ExprInspectionChecker::*FnCheck)(const CallExpr *,
CheckerContext &C) const;
- void reportBug(llvm::StringRef Msg, CheckerContext &C) const;
+ ExplodedNode *reportBug(llvm::StringRef Msg, CheckerContext &C) const;
+ ExplodedNode *reportBug(llvm::StringRef Msg, BugReporter &BR,
+ ExplodedNode *N) const;
public:
bool evalCall(const CallExpr *CE, CheckerContext &C) const;
void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
+ void checkEndAnalysis(ExplodedGraph &G, BugReporter &BR,
+ ExprEngine &Eng) const;
};
}
@@ -56,7 +72,12 @@ bool ExprInspectionChecker::evalCall(const CallExpr *CE,
.Case("clang_analyzer_warnOnDeadSymbol",
&ExprInspectionChecker::analyzerWarnOnDeadSymbol)
.Case("clang_analyzer_explain", &ExprInspectionChecker::analyzerExplain)
+ .Case("clang_analyzer_dump", &ExprInspectionChecker::analyzerDump)
.Case("clang_analyzer_getExtent", &ExprInspectionChecker::analyzerGetExtent)
+ .Case("clang_analyzer_printState",
+ &ExprInspectionChecker::analyzerPrintState)
+ .Case("clang_analyzer_numTimesReached",
+ &ExprInspectionChecker::analyzerNumTimesReached)
.Default(nullptr);
if (!Handler)
@@ -98,16 +119,24 @@ static const char *getArgumentValueString(const CallExpr *CE,
}
}
-void ExprInspectionChecker::reportBug(llvm::StringRef Msg,
- CheckerContext &C) const {
- if (!BT)
- BT.reset(new BugType(this, "Checking analyzer assumptions", "debug"));
-
+ExplodedNode *ExprInspectionChecker::reportBug(llvm::StringRef Msg,
+ CheckerContext &C) const {
ExplodedNode *N = C.generateNonFatalErrorNode();
+ reportBug(Msg, C.getBugReporter(), N);
+ return N;
+}
+
+ExplodedNode *ExprInspectionChecker::reportBug(llvm::StringRef Msg,
+ BugReporter &BR,
+ ExplodedNode *N) const {
if (!N)
- return;
+ return nullptr;
+
+ if (!BT)
+ BT.reset(new BugType(this, "Checking analyzer assumptions", "debug"));
- C.emitReport(llvm::make_unique<BugReport>(*BT, Msg, N));
+ BR.emitReport(llvm::make_unique<BugReport>(*BT, Msg, N));
+ return N;
}
void ExprInspectionChecker::analyzerEval(const CallExpr *CE,
@@ -127,6 +156,15 @@ void ExprInspectionChecker::analyzerWarnIfReached(const CallExpr *CE,
reportBug("REACHABLE", C);
}
+void ExprInspectionChecker::analyzerNumTimesReached(const CallExpr *CE,
+ CheckerContext &C) const {
+ ++ReachedStats[CE].NumTimesReached;
+ if (!ReachedStats[CE].ExampleNode) {
+ // Later, in checkEndAnalysis, we'd throw a report against it.
+ ReachedStats[CE].ExampleNode = C.generateNonFatalErrorNode();
+ }
+}
+
void ExprInspectionChecker::analyzerCheckInlined(const CallExpr *CE,
CheckerContext &C) const {
const LocationContext *LC = C.getPredecessor()->getLocationContext();
@@ -144,22 +182,43 @@ void ExprInspectionChecker::analyzerCheckInlined(const CallExpr *CE,
void ExprInspectionChecker::analyzerExplain(const CallExpr *CE,
CheckerContext &C) const {
- if (CE->getNumArgs() == 0)
+ if (CE->getNumArgs() == 0) {
reportBug("Missing argument for explaining", C);
+ return;
+ }
SVal V = C.getSVal(CE->getArg(0));
SValExplainer Ex(C.getASTContext());
reportBug(Ex.Visit(V), C);
}
+void ExprInspectionChecker::analyzerDump(const CallExpr *CE,
+ CheckerContext &C) const {
+ if (CE->getNumArgs() == 0) {
+ reportBug("Missing argument for dumping", C);
+ return;
+ }
+
+ SVal V = C.getSVal(CE->getArg(0));
+
+ llvm::SmallString<32> Str;
+ llvm::raw_svector_ostream OS(Str);
+ V.dumpToStream(OS);
+ reportBug(OS.str(), C);
+}
+
void ExprInspectionChecker::analyzerGetExtent(const CallExpr *CE,
CheckerContext &C) const {
- if (CE->getNumArgs() == 0)
+ if (CE->getNumArgs() == 0) {
reportBug("Missing region for obtaining extent", C);
+ return;
+ }
auto MR = dyn_cast_or_null<SubRegion>(C.getSVal(CE->getArg(0)).getAsRegion());
- if (!MR)
+ if (!MR) {
reportBug("Obtaining extent of a non-region", C);
+ return;
+ }
ProgramStateRef State = C.getState();
State = State->BindExpr(CE, C.getLocationContext(),
@@ -167,6 +226,11 @@ void ExprInspectionChecker::analyzerGetExtent(const CallExpr *CE,
C.addTransition(State);
}
+void ExprInspectionChecker::analyzerPrintState(const CallExpr *CE,
+ CheckerContext &C) const {
+ C.getState()->dump();
+}
+
void ExprInspectionChecker::analyzerWarnOnDeadSymbol(const CallExpr *CE,
CheckerContext &C) const {
if (CE->getNumArgs() == 0)
@@ -185,15 +249,28 @@ void ExprInspectionChecker::checkDeadSymbols(SymbolReaper &SymReaper,
CheckerContext &C) const {
ProgramStateRef State = C.getState();
const MarkedSymbolsTy &Syms = State->get<MarkedSymbols>();
+ ExplodedNode *N = C.getPredecessor();
for (auto I = Syms.begin(), E = Syms.end(); I != E; ++I) {
SymbolRef Sym = *I;
if (!SymReaper.isDead(Sym))
continue;
- reportBug("SYMBOL DEAD", C);
+ // The non-fatal error node should be the same for all reports.
+ if (ExplodedNode *BugNode = reportBug("SYMBOL DEAD", C))
+ N = BugNode;
State = State->remove<MarkedSymbols>(Sym);
}
- C.addTransition(State);
+ C.addTransition(State, N);
+}
+
+void ExprInspectionChecker::checkEndAnalysis(ExplodedGraph &G, BugReporter &BR,
+ ExprEngine &Eng) const {
+ for (auto Item: ReachedStats) {
+ unsigned NumTimesReached = Item.second.NumTimesReached;
+ ExplodedNode *N = Item.second.ExampleNode;
+
+ reportBug(std::to_string(NumTimesReached), BR, N);
+ }
}
void ExprInspectionChecker::analyzerCrash(const CallExpr *CE,
diff --git a/lib/StaticAnalyzer/Checkers/GTestChecker.cpp b/lib/StaticAnalyzer/Checkers/GTestChecker.cpp
new file mode 100644
index 000000000000..f0be41b293e4
--- /dev/null
+++ b/lib/StaticAnalyzer/Checkers/GTestChecker.cpp
@@ -0,0 +1,299 @@
+//==- GTestChecker.cpp - Model gtest API --*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This checker models the behavior of un-inlined APIs from the gtest
+// unit-testing library to avoid false positives when using assertions from
+// that library.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/AST/Expr.h"
+#include "clang/Basic/LangOptions.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/ProgramState.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+using namespace ento;
+
+// Modeling of un-inlined AssertionResult constructors
+//
+// The gtest unit testing API provides macros for assertions that expand
+// into an if statement that calls a series of constructors and returns
+// when the "assertion" is false.
+//
+// For example,
+//
+// ASSERT_TRUE(a == b)
+//
+// expands into:
+//
+// switch (0)
+// case 0:
+// default:
+// if (const ::testing::AssertionResult gtest_ar_ =
+// ::testing::AssertionResult((a == b)))
+// ;
+// else
+// return ::testing::internal::AssertHelper(
+// ::testing::TestPartResult::kFatalFailure,
+// "<path to project>",
+// <line number>,
+// ::testing::internal::GetBoolAssertionFailureMessage(
+// gtest_ar_, "a == b", "false", "true")
+// .c_str()) = ::testing::Message();
+//
+// where AssertionResult is defined similarly to
+//
+// class AssertionResult {
+// public:
+// AssertionResult(const AssertionResult& other);
+// explicit AssertionResult(bool success) : success_(success) {}
+// operator bool() const { return success_; }
+// ...
+// private:
+// bool success_;
+// };
+//
+// In order for the analyzer to correctly handle this assertion, it needs to
+// know that the boolean value of the expression "a == b" is stored the
+// 'success_' field of the original AssertionResult temporary and propagated
+// (via the copy constructor) into the 'success_' field of the object stored
+// in 'gtest_ar_'. That boolean value will then be returned from the bool
+// conversion method in the if statement. This guarantees that the assertion
+// holds when the return path is not taken.
+//
+// If the success value is not properly propagated, then the eager case split
+// on evaluating the expression can cause pernicious false positives
+// on the non-return path:
+//
+// ASSERT(ptr != NULL)
+// *ptr = 7; // False positive null pointer dereference here
+//
+// Unfortunately, the bool constructor cannot be inlined (because its
+// implementation is not present in the headers) and the copy constructor is
+// not inlined (because it is constructed into a temporary and the analyzer
+// does not inline these since it does not yet reliably call temporary
+// destructors).
+//
+// This checker compensates for the missing inlining by propagating the
+// _success value across the bool and copy constructors so the assertion behaves
+// as expected.
+
+namespace {
+class GTestChecker : public Checker<check::PostCall> {
+
+ mutable IdentifierInfo *AssertionResultII;
+ mutable IdentifierInfo *SuccessII;
+
+public:
+ GTestChecker();
+
+ void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
+
+private:
+ void modelAssertionResultBoolConstructor(const CXXConstructorCall *Call,
+ bool IsRef, CheckerContext &C) const;
+
+ void modelAssertionResultCopyConstructor(const CXXConstructorCall *Call,
+ CheckerContext &C) const;
+
+ void initIdentifierInfo(ASTContext &Ctx) const;
+
+ SVal
+ getAssertionResultSuccessFieldValue(const CXXRecordDecl *AssertionResultDecl,
+ SVal Instance,
+ ProgramStateRef State) const;
+
+ static ProgramStateRef assumeValuesEqual(SVal Val1, SVal Val2,
+ ProgramStateRef State,
+ CheckerContext &C);
+};
+} // End anonymous namespace.
+
+GTestChecker::GTestChecker() : AssertionResultII(nullptr), SuccessII(nullptr) {}
+
+/// Model a call to an un-inlined AssertionResult(bool) or
+/// AssertionResult(bool &, ...).
+/// To do so, constrain the value of the newly-constructed instance's 'success_'
+/// field to be equal to the passed-in boolean value.
+///
+/// \param IsRef Whether the boolean parameter is a reference or not.
+void GTestChecker::modelAssertionResultBoolConstructor(
+ const CXXConstructorCall *Call, bool IsRef, CheckerContext &C) const {
+ assert(Call->getNumArgs() >= 1 && Call->getNumArgs() <= 2);
+
+ ProgramStateRef State = C.getState();
+ SVal BooleanArgVal = Call->getArgSVal(0);
+ if (IsRef) {
+ // The argument is a reference, so load from it to get the boolean value.
+ if (!BooleanArgVal.getAs<Loc>())
+ return;
+ BooleanArgVal = C.getState()->getSVal(BooleanArgVal.castAs<Loc>());
+ }
+
+ SVal ThisVal = Call->getCXXThisVal();
+
+ SVal ThisSuccess = getAssertionResultSuccessFieldValue(
+ Call->getDecl()->getParent(), ThisVal, State);
+
+ State = assumeValuesEqual(ThisSuccess, BooleanArgVal, State, C);
+ C.addTransition(State);
+}
+
+/// Model a call to an un-inlined AssertionResult copy constructor:
+///
+/// AssertionResult(const &AssertionResult other)
+///
+/// To do so, constrain the value of the newly-constructed instance's
+/// 'success_' field to be equal to the value of the pass-in instance's
+/// 'success_' field.
+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
+ // instance to initialize this instances fields from.
+ SVal OtherVal = Call->getArgSVal(0);
+ SVal ThisVal = Call->getCXXThisVal();
+
+ const CXXRecordDecl *AssertResultClassDecl = Call->getDecl()->getParent();
+ ProgramStateRef State = C.getState();
+
+ SVal ThisSuccess = getAssertionResultSuccessFieldValue(AssertResultClassDecl,
+ ThisVal, State);
+ SVal OtherSuccess = getAssertionResultSuccessFieldValue(AssertResultClassDecl,
+ OtherVal, State);
+
+ State = assumeValuesEqual(ThisSuccess, OtherSuccess, State, C);
+ C.addTransition(State);
+}
+
+/// Model calls to AssertionResult constructors that are not inlined.
+void GTestChecker::checkPostCall(const CallEvent &Call,
+ CheckerContext &C) const {
+ /// If the constructor was inlined, there is no need model it.
+ if (C.wasInlined)
+ return;
+
+ initIdentifierInfo(C.getASTContext());
+
+ auto *CtorCall = dyn_cast<CXXConstructorCall>(&Call);
+ if (!CtorCall)
+ return;
+
+ const CXXConstructorDecl *CtorDecl = CtorCall->getDecl();
+ const CXXRecordDecl *CtorParent = CtorDecl->getParent();
+ if (CtorParent->getIdentifier() != AssertionResultII)
+ return;
+
+ unsigned ParamCount = CtorDecl->getNumParams();
+
+ // Call the appropriate modeling method based the parameters and their
+ // types.
+
+ // We have AssertionResult(const &AssertionResult)
+ if (CtorDecl->isCopyConstructor() && ParamCount == 1) {
+ modelAssertionResultCopyConstructor(CtorCall, C);
+ return;
+ }
+
+ // There are two possible boolean constructors, depending on which
+ // version of gtest is being used:
+ //
+ // v1.7 and earlier:
+ // AssertionResult(bool success)
+ //
+ // v1.8 and greater:
+ // template <typename T>
+ // AssertionResult(const T& success,
+ // typename internal::EnableIf<
+ // !internal::ImplicitlyConvertible<T,
+ // AssertionResult>::value>::type*)
+ //
+ CanQualType BoolTy = C.getASTContext().BoolTy;
+ if (ParamCount == 1 && CtorDecl->getParamDecl(0)->getType() == BoolTy) {
+ // We have AssertionResult(bool)
+ modelAssertionResultBoolConstructor(CtorCall, /*IsRef=*/false, C);
+ return;
+ }
+ if (ParamCount == 2){
+ auto *RefTy = CtorDecl->getParamDecl(0)->getType()->getAs<ReferenceType>();
+ if (RefTy &&
+ RefTy->getPointeeType()->getCanonicalTypeUnqualified() == BoolTy) {
+ // We have AssertionResult(bool &, ...)
+ modelAssertionResultBoolConstructor(CtorCall, /*IsRef=*/true, C);
+ return;
+ }
+ }
+}
+
+void GTestChecker::initIdentifierInfo(ASTContext &Ctx) const {
+ if (AssertionResultII)
+ return;
+
+ AssertionResultII = &Ctx.Idents.get("AssertionResult");
+ SuccessII = &Ctx.Idents.get("success_");
+}
+
+/// Returns the value stored in the 'success_' field of the passed-in
+/// AssertionResult instance.
+SVal GTestChecker::getAssertionResultSuccessFieldValue(
+ const CXXRecordDecl *AssertionResultDecl, SVal Instance,
+ ProgramStateRef State) const {
+
+ DeclContext::lookup_result Result = AssertionResultDecl->lookup(SuccessII);
+ if (Result.empty())
+ return UnknownVal();
+
+ auto *SuccessField = dyn_cast<FieldDecl>(Result.front());
+ if (!SuccessField)
+ return UnknownVal();
+
+ Optional<Loc> FieldLoc =
+ State->getLValue(SuccessField, Instance).getAs<Loc>();
+ if (!FieldLoc.hasValue())
+ return UnknownVal();
+
+ return State->getSVal(*FieldLoc);
+}
+
+/// Constrain the passed-in state to assume two values are equal.
+ProgramStateRef GTestChecker::assumeValuesEqual(SVal Val1, SVal Val2,
+ ProgramStateRef State,
+ CheckerContext &C) {
+ if (!Val1.getAs<DefinedOrUnknownSVal>() ||
+ !Val2.getAs<DefinedOrUnknownSVal>())
+ return State;
+
+ auto ValuesEqual =
+ C.getSValBuilder().evalEQ(State, Val1.castAs<DefinedOrUnknownSVal>(),
+ Val2.castAs<DefinedOrUnknownSVal>());
+
+ if (!ValuesEqual.getAs<DefinedSVal>())
+ return State;
+
+ State = C.getConstraintManager().assume(
+ State, ValuesEqual.castAs<DefinedSVal>(), true);
+
+ return State;
+}
+
+void ento::registerGTestChecker(CheckerManager &Mgr) {
+ const LangOptions &LangOpts = Mgr.getLangOpts();
+ // gtest is a C++ API so there is no sense running the checker
+ // if not compiling for C++.
+ if (!LangOpts.CPlusPlus)
+ return;
+
+ Mgr.registerChecker<GTestChecker>();
+}
diff --git a/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp b/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp
index 7be2f574f0e9..d1dab6d27d45 100644
--- a/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp
@@ -19,6 +19,9 @@
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/Lex/Lexer.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
@@ -26,11 +29,7 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
-#include "clang/Lex/Lexer.h"
-#include "clang/AST/RecursiveASTVisitor.h"
-#include "clang/AST/StmtVisitor.h"
#include "llvm/Support/Unicode.h"
-#include "llvm/ADT/StringSet.h"
using namespace clang;
using namespace ento;
@@ -189,6 +188,22 @@ void NonLocalizedStringChecker::initUIMethods(ASTContext &Ctx) const {
NEW_RECEIVER(NSButton)
ADD_UNARY_METHOD(NSButton, setTitle, 0)
ADD_UNARY_METHOD(NSButton, setAlternateTitle, 0)
+ IdentifierInfo *radioButtonWithTitleNSButton[] = {
+ &Ctx.Idents.get("radioButtonWithTitle"), &Ctx.Idents.get("target"),
+ &Ctx.Idents.get("action")};
+ ADD_METHOD(NSButton, radioButtonWithTitleNSButton, 3, 0)
+ IdentifierInfo *buttonWithTitleNSButtonImage[] = {
+ &Ctx.Idents.get("buttonWithTitle"), &Ctx.Idents.get("image"),
+ &Ctx.Idents.get("target"), &Ctx.Idents.get("action")};
+ ADD_METHOD(NSButton, buttonWithTitleNSButtonImage, 4, 0)
+ IdentifierInfo *checkboxWithTitleNSButton[] = {
+ &Ctx.Idents.get("checkboxWithTitle"), &Ctx.Idents.get("target"),
+ &Ctx.Idents.get("action")};
+ ADD_METHOD(NSButton, checkboxWithTitleNSButton, 3, 0)
+ IdentifierInfo *buttonWithTitleNSButtonTarget[] = {
+ &Ctx.Idents.get("buttonWithTitle"), &Ctx.Idents.get("target"),
+ &Ctx.Idents.get("action")};
+ ADD_METHOD(NSButton, buttonWithTitleNSButtonTarget, 3, 0)
NEW_RECEIVER(NSSavePanel)
ADD_UNARY_METHOD(NSSavePanel, setPrompt, 0)
@@ -271,6 +286,9 @@ void NonLocalizedStringChecker::initUIMethods(ASTContext &Ctx) const {
ADD_UNARY_METHOD(NSButtonCell, setTitle, 0)
ADD_UNARY_METHOD(NSButtonCell, setAlternateTitle, 0)
+ NEW_RECEIVER(NSDatePickerCell)
+ ADD_UNARY_METHOD(NSDatePickerCell, initTextCell, 0)
+
NEW_RECEIVER(NSSliderCell)
ADD_UNARY_METHOD(NSSliderCell, setTitle, 0)
@@ -336,9 +354,6 @@ void NonLocalizedStringChecker::initUIMethods(ASTContext &Ctx) const {
ADD_UNARY_METHOD(UIActionSheet, addButtonWithTitle, 0)
ADD_UNARY_METHOD(UIActionSheet, setTitle, 0)
- NEW_RECEIVER(NSURLSessionTask)
- ADD_UNARY_METHOD(NSURLSessionTask, setTaskDescription, 0)
-
NEW_RECEIVER(UIAccessibilityCustomAction)
IdentifierInfo *initWithNameUIAccessibilityCustomAction[] = {
&Ctx.Idents.get("initWithName"), &Ctx.Idents.get("target"),
@@ -363,6 +378,9 @@ void NonLocalizedStringChecker::initUIMethods(ASTContext &Ctx) const {
NEW_RECEIVER(NSTextField)
ADD_UNARY_METHOD(NSTextField, setPlaceholderString, 0)
+ ADD_UNARY_METHOD(NSTextField, textFieldWithString, 0)
+ ADD_UNARY_METHOD(NSTextField, wrappingLabelWithString, 0)
+ ADD_UNARY_METHOD(NSTextField, labelWithString, 0)
NEW_RECEIVER(NSAttributedString)
ADD_UNARY_METHOD(NSAttributedString, initWithString, 0)
@@ -523,9 +541,6 @@ void NonLocalizedStringChecker::initUIMethods(ASTContext &Ctx) const {
ADD_METHOD(NSUserNotificationAction,
actionWithIdentifierNSUserNotificationAction, 2, 1)
- NEW_RECEIVER(NSURLSession)
- ADD_UNARY_METHOD(NSURLSession, setSessionDescription, 0)
-
NEW_RECEIVER(UITextField)
ADD_UNARY_METHOD(UITextField, setText, 0)
ADD_UNARY_METHOD(UITextField, setPlaceholder, 0)
@@ -1001,6 +1016,8 @@ void EmptyLocalizationContextChecker::checkASTDecl(
void EmptyLocalizationContextChecker::MethodCrawler::VisitObjCMessageExpr(
const ObjCMessageExpr *ME) {
+ // FIXME: We may be able to use PPCallbacks to check for empy context
+ // comments as part of preprocessing and avoid this re-lexing hack.
const ObjCInterfaceDecl *OD = ME->getReceiverInterface();
if (!OD)
return;
@@ -1035,7 +1052,12 @@ void EmptyLocalizationContextChecker::MethodCrawler::VisitObjCMessageExpr(
SE = Mgr.getSourceManager().getSLocEntry(SLInfo.first);
}
- llvm::MemoryBuffer *BF = SE.getFile().getContentCache()->getRawBuffer();
+ bool Invalid = false;
+ llvm::MemoryBuffer *BF =
+ Mgr.getSourceManager().getBuffer(SLInfo.first, SL, &Invalid);
+ if (Invalid)
+ return;
+
Lexer TheLexer(SL, LangOptions(), BF->getBufferStart(),
BF->getBufferStart() + SLInfo.second, BF->getBufferEnd());
diff --git a/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.h b/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.h
index 22fbf4c5b303..8474d2d194e8 100644
--- a/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.h
+++ b/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.h
@@ -46,9 +46,7 @@ public:
const ExplodedNode *const ExplNode,
BugReporter &BReporter) const;
- /// Report a missing wait for a nonblocking call. A missing wait report
- /// is emitted if a nonblocking call is not matched in the scope of a
- /// function.
+ /// Report a missing wait for a nonblocking call.
///
/// \param Req request that is not matched by a wait
/// \param RequestRegion memory region of the request
diff --git a/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp b/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp
index c3d0f8f2a129..c667b9e67d4b 100644
--- a/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp
@@ -43,7 +43,8 @@ void MPIChecker::checkDoubleNonblocking(const CallEvent &PreCallEvent,
// double nonblocking detected
if (Req && Req->CurrentState == Request::State::Nonblocking) {
ExplodedNode *ErrorNode = Ctx.generateNonFatalErrorNode();
- BReporter.reportDoubleNonblocking(PreCallEvent, *Req, MR, ErrorNode, Ctx.getBugReporter());
+ BReporter.reportDoubleNonblocking(PreCallEvent, *Req, MR, ErrorNode,
+ Ctx.getBugReporter());
Ctx.addTransition(ErrorNode->getState(), ErrorNode);
}
// no error
@@ -85,7 +86,8 @@ void MPIChecker::checkUnmatchedWaits(const CallEvent &PreCallEvent,
State = ErrorNode->getState();
}
// A wait has no matching nonblocking call.
- BReporter.reportUnmatchedWait(PreCallEvent, ReqRegion, ErrorNode, Ctx.getBugReporter());
+ BReporter.reportUnmatchedWait(PreCallEvent, ReqRegion, ErrorNode,
+ Ctx.getBugReporter());
}
}
@@ -118,7 +120,8 @@ void MPIChecker::checkMissingWaits(SymbolReaper &SymReaper,
ErrorNode = Ctx.generateNonFatalErrorNode(State, &Tag);
State = ErrorNode->getState();
}
- BReporter.reportMissingWait(Req.second, Req.first, ErrorNode, Ctx.getBugReporter());
+ BReporter.reportMissingWait(Req.second, Req.first, ErrorNode,
+ Ctx.getBugReporter());
}
State = State->remove<RequestMap>(Req.first);
}
diff --git a/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.h b/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.h
index 20c60ad076a2..6b1c062ef3d5 100644
--- a/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.h
+++ b/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.h
@@ -19,8 +19,8 @@
#define LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_MPICHECKER_MPICHECKER_H
#include "MPIBugReporter.h"
-#include "MPIFunctionClassifier.h"
#include "MPITypes.h"
+#include "clang/StaticAnalyzer/Checkers/MPIFunctionClassifier.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
@@ -30,7 +30,7 @@ namespace mpi {
class MPIChecker : public Checker<check::PreCall, check::DeadSymbols> {
public:
- MPIChecker() : BReporter(*this) { }
+ MPIChecker() : BReporter(*this) {}
// path-sensitive callbacks
void checkPreCall(const CallEvent &CE, CheckerContext &Ctx) const {
@@ -49,7 +49,6 @@ public:
return;
const_cast<std::unique_ptr<MPIFunctionClassifier> &>(FuncClassifier)
.reset(new MPIFunctionClassifier{Ctx.getASTContext()});
-
}
/// Checks if a request is used by nonblocking calls multiple times
@@ -60,10 +59,9 @@ public:
void checkDoubleNonblocking(const clang::ento::CallEvent &PreCallEvent,
clang::ento::CheckerContext &Ctx) const;
- /// Checks if a request is used by a wait multiple times in sequence without
- /// intermediate nonblocking call or if the request used by the wait
- /// function was not used at all before. The check contains a guard,
- /// in order to only inspect wait functions.
+ /// Checks if the request used by the wait function was not used at all
+ /// before. The check contains a guard, in order to only inspect wait
+ /// functions.
///
/// \param PreCallEvent MPI call to verify
void checkUnmatchedWaits(const clang::ento::CallEvent &PreCallEvent,
diff --git a/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIFunctionClassifier.cpp b/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIFunctionClassifier.cpp
index ad937f683d30..12760abaeeff 100644
--- a/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIFunctionClassifier.cpp
+++ b/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIFunctionClassifier.cpp
@@ -12,7 +12,7 @@
///
//===----------------------------------------------------------------------===//
-#include "MPIFunctionClassifier.h"
+#include "clang/StaticAnalyzer/Checkers/MPIFunctionClassifier.h"
#include "llvm/ADT/STLExtras.h"
namespace clang {
diff --git a/lib/StaticAnalyzer/Checkers/MPI-Checker/MPITypes.h b/lib/StaticAnalyzer/Checkers/MPI-Checker/MPITypes.h
index 27ec950d31eb..2e7140cd771e 100644
--- a/lib/StaticAnalyzer/Checkers/MPI-Checker/MPITypes.h
+++ b/lib/StaticAnalyzer/Checkers/MPI-Checker/MPITypes.h
@@ -17,7 +17,7 @@
#ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_MPICHECKER_MPITYPES_H
#define LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_MPICHECKER_MPITYPES_H
-#include "MPIFunctionClassifier.h"
+#include "clang/StaticAnalyzer/Checkers/MPIFunctionClassifier.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "llvm/ADT/SmallSet.h"
@@ -53,7 +53,6 @@ typedef llvm::ImmutableMap<const clang::ento::MemRegion *,
} // end of namespace: mpi
-
template <>
struct ProgramStateTrait<mpi::RequestMap>
: public ProgramStatePartialTrait<mpi::RequestMapImpl> {
diff --git a/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp b/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp
index 1e56d709e4f9..86c827045e9a 100644
--- a/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp
@@ -524,12 +524,7 @@ MacOSKeychainAPIChecker::generateAllocatedDataNotReleasedReport(
// allocated, and only report a single path.
PathDiagnosticLocation LocUsedForUniqueing;
const ExplodedNode *AllocNode = getAllocationNode(N, AP.first, C);
- const Stmt *AllocStmt = nullptr;
- ProgramPoint P = AllocNode->getLocation();
- if (Optional<CallExitEnd> Exit = P.getAs<CallExitEnd>())
- AllocStmt = Exit->getCalleeContext()->getCallSite();
- else if (Optional<clang::PostStmt> PS = P.getAs<clang::PostStmt>())
- AllocStmt = PS->getStmt();
+ const Stmt *AllocStmt = PathDiagnosticLocation::getStmt(AllocNode);
if (AllocStmt)
LocUsedForUniqueing = PathDiagnosticLocation::createBegin(AllocStmt,
diff --git a/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp b/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp
index c038a2649e15..0e0f52af3165 100644
--- a/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp
@@ -33,6 +33,8 @@ namespace {
class MacOSXAPIChecker : public Checker< check::PreStmt<CallExpr> > {
mutable std::unique_ptr<BugType> BT_dispatchOnce;
+ static const ObjCIvarRegion *getParentIvarRegion(const MemRegion *R);
+
public:
void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
@@ -49,27 +51,34 @@ public:
// dispatch_once and dispatch_once_f
//===----------------------------------------------------------------------===//
+const ObjCIvarRegion *
+MacOSXAPIChecker::getParentIvarRegion(const MemRegion *R) {
+ const SubRegion *SR = dyn_cast<SubRegion>(R);
+ while (SR) {
+ if (const ObjCIvarRegion *IR = dyn_cast<ObjCIvarRegion>(SR))
+ return IR;
+ SR = dyn_cast<SubRegion>(SR->getSuperRegion());
+ }
+ return nullptr;
+}
+
void MacOSXAPIChecker::CheckDispatchOnce(CheckerContext &C, const CallExpr *CE,
StringRef FName) const {
if (CE->getNumArgs() < 1)
return;
- // 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();
- if (!R || !isa<StackSpaceRegion>(R->getMemorySpace()))
+ // Check if the first argument is improperly allocated. If so, issue a
+ // warning because that's likely to be bad news.
+ const MemRegion *R = C.getSVal(CE->getArg(0)).getAsRegion();
+ if (!R)
return;
- ExplodedNode *N = C.generateErrorNode(state);
- if (!N)
+ // Global variables are fine.
+ const MemRegion *RB = R->getBaseRegion();
+ const MemSpaceRegion *RS = RB->getMemorySpace();
+ if (isa<GlobalsSpaceRegion>(RS))
return;
- if (!BT_dispatchOnce)
- BT_dispatchOnce.reset(new BugType(this, "Improper use of 'dispatch_once'",
- "API Misuse (Apple)"));
-
// Handle _dispatch_once. In some versions of the OS X SDK we have the case
// that dispatch_once is a macro that wraps a call to _dispatch_once.
// _dispatch_once is then a function which then calls the real dispatch_once.
@@ -82,16 +91,48 @@ void MacOSXAPIChecker::CheckDispatchOnce(CheckerContext &C, const CallExpr *CE,
SmallString<256> S;
llvm::raw_svector_ostream os(S);
+ bool SuggestStatic = false;
os << "Call to '" << FName << "' uses";
- if (const VarRegion *VR = dyn_cast<VarRegion>(R))
- os << " the local variable '" << VR->getDecl()->getName() << '\'';
- else
+ if (const VarRegion *VR = dyn_cast<VarRegion>(RB)) {
+ // We filtered out globals earlier, so it must be a local variable
+ // or a block variable which is under UnknownSpaceRegion.
+ if (VR != R)
+ os << " memory within";
+ if (VR->getDecl()->hasAttr<BlocksAttr>())
+ os << " the block variable '";
+ else
+ os << " the local variable '";
+ os << VR->getDecl()->getName() << '\'';
+ SuggestStatic = true;
+ } else if (const ObjCIvarRegion *IVR = getParentIvarRegion(R)) {
+ if (IVR != R)
+ os << " memory within";
+ os << " the instance variable '" << IVR->getDecl()->getName() << '\'';
+ } else if (isa<HeapSpaceRegion>(RS)) {
+ os << " heap-allocated memory";
+ } else if (isa<UnknownSpaceRegion>(RS)) {
+ // Presence of an IVar superregion has priority over this branch, because
+ // ObjC objects are on the heap even if the core doesn't realize this.
+ // Presence of a block variable base region has priority over this branch,
+ // because block variables are known to be either on stack or on heap
+ // (might actually move between the two, hence UnknownSpace).
+ return;
+ } else {
os << " stack allocated memory";
+ }
os << " for the predicate value. Using such transient memory for "
"the predicate is potentially dangerous.";
- if (isa<VarRegion>(R) && isa<StackLocalsSpaceRegion>(R->getMemorySpace()))
+ if (SuggestStatic)
os << " Perhaps you intended to declare the variable as 'static'?";
+ ExplodedNode *N = C.generateErrorNode();
+ if (!N)
+ return;
+
+ if (!BT_dispatchOnce)
+ BT_dispatchOnce.reset(new BugType(this, "Improper use of 'dispatch_once'",
+ "API Misuse (Apple)"));
+
auto report = llvm::make_unique<BugReport>(*BT_dispatchOnce, os.str(), N);
report->addRange(CE->getArg(0)->getSourceRange());
C.emitReport(std::move(report));
diff --git a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
index e06662b16934..f7c4ea10c438 100644
--- a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -26,7 +26,6 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
-#include "llvm/ADT/ImmutableMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
@@ -288,6 +287,9 @@ private:
ProgramStateRef State,
AllocationFamily Family = AF_Malloc);
+ static ProgramStateRef addExtentSize(CheckerContext &C, const CXXNewExpr *NE,
+ ProgramStateRef State);
+
// Check if this malloc() for special flags. At present that means M_ZERO or
// __GFP_ZERO (in which case, treat it like calloc).
llvm::Optional<ProgramStateRef>
@@ -776,6 +778,8 @@ void MallocChecker::checkPostStmt(const CallExpr *CE, CheckerContext &C) const {
State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State);
}
} else if (FunI == II_kmalloc) {
+ if (CE->getNumArgs() < 1)
+ return;
llvm::Optional<ProgramStateRef> MaybeState =
performKernelMalloc(CE, C, State);
if (MaybeState.hasValue())
@@ -805,6 +809,8 @@ void MallocChecker::checkPostStmt(const CallExpr *CE, CheckerContext &C) const {
} else if (FunI == II_strndup) {
State = MallocUpdateRefState(C, CE, State);
} else if (FunI == II_alloca || FunI == II_win_alloca) {
+ if (CE->getNumArgs() < 1)
+ return;
State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State,
AF_Alloca);
State = ProcessZeroAllocation(C, CE, 0, State);
@@ -982,10 +988,58 @@ void MallocChecker::checkPostStmt(const CXXNewExpr *NE,
// existing binding.
State = MallocUpdateRefState(C, NE, State, NE->isArray() ? AF_CXXNewArray
: AF_CXXNew);
+ State = addExtentSize(C, NE, State);
State = ProcessZeroAllocation(C, NE, 0, State);
C.addTransition(State);
}
+// 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) {
+ 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());
+ // Store the extent size for the (symbolic)region
+ // containing the elements.
+ Region = (State->getSVal(NE, LCtx))
+ .getAsRegion()
+ ->getAs<SubRegion>()
+ ->getSuperRegion()
+ ->getAs<SubRegion>();
+ } else {
+ ElementCount = svalBuilder.makeIntVal(1, true);
+ Region = (State->getSVal(NE, LCtx)).getAsRegion()->getAs<SubRegion>();
+ }
+ assert(Region);
+
+ // Set the region's extent equal to the Size in Bytes.
+ QualType ElementType = NE->getAllocatedType();
+ ASTContext &AstContext = C.getASTContext();
+ CharUnits TypeSize = AstContext.getTypeSizeInChars(ElementType);
+
+ if (ElementCount.getAs<NonLoc>()) {
+ DefinedOrUnknownSVal Extent = Region->getExtent(svalBuilder);
+ // size in Bytes = ElementCount*TypeSize
+ SVal SizeInBytes = svalBuilder.evalBinOpNN(
+ State, BO_Mul, ElementCount.castAs<NonLoc>(),
+ svalBuilder.makeArrayIndex(TypeSize.getQuantity()),
+ svalBuilder.getArrayIndexType());
+ DefinedOrUnknownSVal extentMatchesSize = svalBuilder.evalEQ(
+ State, Extent, SizeInBytes.castAs<DefinedOrUnknownSVal>());
+ State = State->assume(extentMatchesSize, true);
+ }
+ return State;
+}
+
void MallocChecker::checkPreStmt(const CXXDeleteExpr *DE,
CheckerContext &C) const {
@@ -2095,12 +2149,7 @@ void MallocChecker::reportLeak(SymbolRef Sym, ExplodedNode *N,
const MemRegion *Region = nullptr;
std::tie(AllocNode, Region) = getAllocationSite(N, Sym, C);
- ProgramPoint P = AllocNode->getLocation();
- const Stmt *AllocationStmt = nullptr;
- if (Optional<CallExitEnd> Exit = P.getAs<CallExitEnd>())
- AllocationStmt = Exit->getCalleeContext()->getCallSite();
- else if (Optional<StmtPoint> SP = P.getAs<StmtPoint>())
- AllocationStmt = SP->getStmt();
+ const Stmt *AllocationStmt = PathDiagnosticLocation::getStmt(AllocNode);
if (AllocationStmt)
LocUsedForUniqueing = PathDiagnosticLocation::createBegin(AllocationStmt,
C.getSourceManager(),
@@ -2529,6 +2578,11 @@ bool MallocChecker::mayFreeAnyEscapedMemoryOrIsModeledExplicitly(
return true;
}
+ if (FName == "connectImpl" &&
+ FD->getQualifiedNameAsString() == "QObject::connectImpl") {
+ return true;
+ }
+
// Handle cases where we know a buffer's /address/ can escape.
// Note that the above checks handle some special cases where we know that
// even though the address escapes, it's still our responsibility to free the
@@ -2627,22 +2681,7 @@ MallocChecker::MallocBugVisitor::VisitNode(const ExplodedNode *N,
if (!RS)
return nullptr;
- const Stmt *S = nullptr;
- const char *Msg = nullptr;
- StackHintGeneratorForSymbol *StackHint = nullptr;
-
- // Retrieve the associated statement.
- ProgramPoint ProgLoc = N->getLocation();
- if (Optional<StmtPoint> SP = ProgLoc.getAs<StmtPoint>()) {
- S = SP->getStmt();
- } else if (Optional<CallExitEnd> Exit = ProgLoc.getAs<CallExitEnd>()) {
- S = Exit->getCalleeContext()->getCallSite();
- } else if (Optional<BlockEdge> Edge = ProgLoc.getAs<BlockEdge>()) {
- // If an assumption was made on a branch, it should be caught
- // here by looking at the state transition.
- S = Edge->getSrc()->getTerminator();
- }
-
+ const Stmt *S = PathDiagnosticLocation::getStmt(N);
if (!S)
return nullptr;
@@ -2650,6 +2689,8 @@ MallocChecker::MallocBugVisitor::VisitNode(const ExplodedNode *N,
// (__attribute__((cleanup))).
// Find out if this is an interesting point and what is the kind.
+ const char *Msg = nullptr;
+ StackHintGeneratorForSymbol *StackHint = nullptr;
if (Mode == Normal) {
if (isAllocated(RS, RSPrev, S)) {
Msg = "Memory is allocated";
diff --git a/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp b/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
index d7ec6b10c6f7..d96017a1f532 100644
--- a/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
@@ -325,10 +325,7 @@ PathDiagnosticPiece *NullabilityChecker::NullabilityBugVisitor::VisitNode(
// Retrieve the associated statement.
const Stmt *S = TrackedNullab->getNullabilitySource();
if (!S) {
- ProgramPoint ProgLoc = N->getLocation();
- if (Optional<StmtPoint> SP = ProgLoc.getAs<StmtPoint>()) {
- S = SP->getStmt();
- }
+ S = PathDiagnosticLocation::getStmt(N);
}
if (!S)
@@ -336,7 +333,7 @@ PathDiagnosticPiece *NullabilityChecker::NullabilityBugVisitor::VisitNode(
std::string InfoText =
(llvm::Twine("Nullability '") +
- getNullabilityString(TrackedNullab->getValue()) + "' is infered")
+ getNullabilityString(TrackedNullab->getValue()) + "' is inferred")
.str();
// Generate the extra diagnostic.
@@ -613,9 +610,9 @@ void NullabilityChecker::checkPreStmt(const ReturnStmt *S,
SmallString<256> SBuf;
llvm::raw_svector_ostream OS(SBuf);
- OS << "Null is returned from a " << C.getDeclDescription(D) <<
+ OS << (RetExpr->getType()->isObjCObjectPointerType() ? "nil" : "Null");
+ OS << " returned from a " << C.getDeclDescription(D) <<
" that is expected to return a non-null value";
-
reportBugIfInvariantHolds(OS.str(),
ErrorKind::NilReturnedToNonnull, N, nullptr, C,
RetExpr);
@@ -682,9 +679,10 @@ void NullabilityChecker::checkPreCall(const CallEvent &Call,
if (Param->isParameterPack())
break;
- const Expr *ArgExpr = nullptr;
- if (Idx < Call.getNumArgs())
- ArgExpr = Call.getArgExpr(Idx);
+ if (Idx >= Call.getNumArgs())
+ break;
+
+ const Expr *ArgExpr = Call.getArgExpr(Idx);
auto ArgSVal = Call.getArgSVal(Idx++).getAs<DefinedOrUnknownSVal>();
if (!ArgSVal)
continue;
@@ -709,9 +707,11 @@ void NullabilityChecker::checkPreCall(const CallEvent &Call,
ExplodedNode *N = C.generateErrorNode(State);
if (!N)
return;
+
SmallString<256> SBuf;
llvm::raw_svector_ostream OS(SBuf);
- OS << "Null passed to a callee that requires a non-null " << ParamIdx
+ OS << (Param->getType()->isObjCObjectPointerType() ? "nil" : "Null");
+ OS << " passed to a callee that requires a non-null " << ParamIdx
<< llvm::getOrdinalSuffix(ParamIdx) << " parameter";
reportBugIfInvariantHolds(OS.str(), ErrorKind::NilPassedToNonnull, N,
nullptr, C,
@@ -1130,8 +1130,11 @@ void NullabilityChecker::checkBind(SVal L, SVal V, const Stmt *S,
if (ValueExpr)
ValueStmt = ValueExpr;
- reportBugIfInvariantHolds("Null is assigned to a pointer which is "
- "expected to have non-null value",
+ SmallString<256> SBuf;
+ llvm::raw_svector_ostream OS(SBuf);
+ OS << (LocType->isObjCObjectPointerType() ? "nil" : "Null");
+ OS << " assigned to a pointer which is expected to have non-null value";
+ reportBugIfInvariantHolds(OS.str(),
ErrorKind::NilAssignedToNonnull, N, nullptr, C,
ValueStmt);
return;
diff --git a/lib/StaticAnalyzer/Checkers/NumberObjectConversionChecker.cpp b/lib/StaticAnalyzer/Checkers/NumberObjectConversionChecker.cpp
new file mode 100644
index 000000000000..40e379cb2efc
--- /dev/null
+++ b/lib/StaticAnalyzer/Checkers/NumberObjectConversionChecker.cpp
@@ -0,0 +1,348 @@
+//===- NumberObjectConversionChecker.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 NumberObjectConversionChecker, which checks for a
+// particular common mistake when dealing with numbers represented as objects
+// passed around by pointers. Namely, the language allows to reinterpret the
+// pointer as a number directly, often without throwing any warnings,
+// but in most cases the result of such conversion is clearly unexpected,
+// as pointer value, rather than number value represented by the pointee object,
+// becomes the result of such operation.
+//
+// Currently the checker supports the Objective-C NSNumber class,
+// and the OSBoolean class found in macOS low-level code; the latter
+// can only hold boolean values.
+//
+// This checker has an option "Pedantic" (boolean), which enables detection of
+// more conversion patterns (which are most likely more harmless, and therefore
+// are more likely to produce false positives) - disabled by default,
+// enabled with `-analyzer-config osx.NumberObjectConversion:Pedantic=true'.
+//
+//===----------------------------------------------------------------------===//
+
+#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 "clang/Lex/Lexer.h"
+#include "llvm/ADT/APSInt.h"
+
+using namespace clang;
+using namespace ento;
+using namespace ast_matchers;
+
+namespace {
+
+class NumberObjectConversionChecker : public Checker<check::ASTCodeBody> {
+public:
+ bool Pedantic;
+
+ void checkASTCodeBody(const Decl *D, AnalysisManager &AM,
+ BugReporter &BR) const;
+};
+
+class Callback : public MatchFinder::MatchCallback {
+ const NumberObjectConversionChecker *C;
+ BugReporter &BR;
+ AnalysisDeclContext *ADC;
+
+public:
+ Callback(const NumberObjectConversionChecker *C,
+ BugReporter &BR, AnalysisDeclContext *ADC)
+ : C(C), BR(BR), ADC(ADC) {}
+ virtual void run(const MatchFinder::MatchResult &Result);
+};
+} // end of anonymous namespace
+
+void Callback::run(const MatchFinder::MatchResult &Result) {
+ bool IsPedanticMatch =
+ (Result.Nodes.getNodeAs<Stmt>("pedantic") != nullptr);
+ if (IsPedanticMatch && !C->Pedantic)
+ return;
+
+ ASTContext &ACtx = ADC->getASTContext();
+
+ if (const Expr *CheckIfNull =
+ Result.Nodes.getNodeAs<Expr>("check_if_null")) {
+ // Unless the macro indicates that the intended type is clearly not
+ // a pointer type, we should avoid warning on comparing pointers
+ // to zero literals in non-pedantic mode.
+ // FIXME: Introduce an AST matcher to implement the macro-related logic?
+ bool MacroIndicatesWeShouldSkipTheCheck = false;
+ SourceLocation Loc = CheckIfNull->getLocStart();
+ if (Loc.isMacroID()) {
+ StringRef MacroName = Lexer::getImmediateMacroName(
+ Loc, ACtx.getSourceManager(), ACtx.getLangOpts());
+ if (MacroName == "NULL" || MacroName == "nil")
+ return;
+ if (MacroName == "YES" || MacroName == "NO")
+ MacroIndicatesWeShouldSkipTheCheck = true;
+ }
+ if (!MacroIndicatesWeShouldSkipTheCheck) {
+ llvm::APSInt Result;
+ if (CheckIfNull->IgnoreParenCasts()->EvaluateAsInt(
+ Result, ACtx, Expr::SE_AllowSideEffects)) {
+ if (Result == 0) {
+ if (!C->Pedantic)
+ return;
+ IsPedanticMatch = true;
+ }
+ }
+ }
+ }
+
+ const Stmt *Conv = Result.Nodes.getNodeAs<Stmt>("conv");
+ assert(Conv);
+
+ const Expr *ConvertedCObject = Result.Nodes.getNodeAs<Expr>("c_object");
+ const Expr *ConvertedCppObject = Result.Nodes.getNodeAs<Expr>("cpp_object");
+ const Expr *ConvertedObjCObject = Result.Nodes.getNodeAs<Expr>("objc_object");
+ bool IsCpp = (ConvertedCppObject != nullptr);
+ bool IsObjC = (ConvertedObjCObject != nullptr);
+ const Expr *Obj = IsObjC ? ConvertedObjCObject
+ : IsCpp ? ConvertedCppObject
+ : ConvertedCObject;
+ assert(Obj);
+
+ bool IsComparison =
+ (Result.Nodes.getNodeAs<Stmt>("comparison") != nullptr);
+
+ bool IsOSNumber =
+ (Result.Nodes.getNodeAs<Decl>("osnumber") != nullptr);
+
+ bool IsInteger =
+ (Result.Nodes.getNodeAs<QualType>("int_type") != nullptr);
+ bool IsObjCBool =
+ (Result.Nodes.getNodeAs<QualType>("objc_bool_type") != nullptr);
+ bool IsCppBool =
+ (Result.Nodes.getNodeAs<QualType>("cpp_bool_type") != nullptr);
+
+ llvm::SmallString<64> Msg;
+ llvm::raw_svector_ostream OS(Msg);
+
+ // Remove ObjC ARC qualifiers.
+ QualType ObjT = Obj->getType().getUnqualifiedType();
+
+ // Remove consts from pointers.
+ if (IsCpp) {
+ assert(ObjT.getCanonicalType()->isPointerType());
+ ObjT = ACtx.getPointerType(
+ ObjT->getPointeeType().getCanonicalType().getUnqualifiedType());
+ }
+
+ if (IsComparison)
+ OS << "Comparing ";
+ else
+ OS << "Converting ";
+
+ OS << "a pointer value of type '" << ObjT.getAsString() << "' to a ";
+
+ std::string EuphemismForPlain = "primitive";
+ std::string SuggestedApi = IsObjC ? (IsInteger ? "" : "-boolValue")
+ : IsCpp ? (IsOSNumber ? "" : "getValue()")
+ : "CFNumberGetValue()";
+ if (SuggestedApi.empty()) {
+ // A generic message if we're not sure what API should be called.
+ // FIXME: Pattern-match the integer type to make a better guess?
+ SuggestedApi =
+ "a method on '" + ObjT.getAsString() + "' to get the scalar value";
+ // "scalar" is not quite correct or common, but some documentation uses it
+ // when describing object methods we suggest. For consistency, we use
+ // "scalar" in the whole sentence when we need to use this word in at least
+ // one place, otherwise we use "primitive".
+ EuphemismForPlain = "scalar";
+ }
+
+ if (IsInteger)
+ OS << EuphemismForPlain << " integer value";
+ else if (IsObjCBool)
+ OS << EuphemismForPlain << " BOOL value";
+ else if (IsCppBool)
+ OS << EuphemismForPlain << " bool value";
+ else // Branch condition?
+ OS << EuphemismForPlain << " boolean value";
+
+
+ if (IsPedanticMatch)
+ OS << "; instead, either compare the pointer to "
+ << (IsObjC ? "nil" : IsCpp ? "nullptr" : "NULL") << " or ";
+ else
+ OS << "; did you mean to ";
+
+ if (IsComparison)
+ OS << "compare the result of calling " << SuggestedApi;
+ else
+ OS << "call " << SuggestedApi;
+
+ if (!IsPedanticMatch)
+ OS << "?";
+
+ BR.EmitBasicReport(
+ ADC->getDecl(), C, "Suspicious number object conversion", "Logic error",
+ OS.str(),
+ PathDiagnosticLocation::createBegin(Obj, BR.getSourceManager(), ADC),
+ Conv->getSourceRange());
+}
+
+void NumberObjectConversionChecker::checkASTCodeBody(const Decl *D,
+ AnalysisManager &AM,
+ BugReporter &BR) const {
+ // Currently this matches CoreFoundation opaque pointer typedefs.
+ auto CSuspiciousNumberObjectExprM =
+ expr(ignoringParenImpCasts(
+ expr(hasType(
+ typedefType(hasDeclaration(anyOf(
+ typedefDecl(hasName("CFNumberRef")),
+ typedefDecl(hasName("CFBooleanRef")))))))
+ .bind("c_object")));
+
+ // Currently this matches XNU kernel number-object pointers.
+ auto CppSuspiciousNumberObjectExprM =
+ expr(ignoringParenImpCasts(
+ expr(hasType(hasCanonicalType(
+ pointerType(pointee(hasCanonicalType(
+ recordType(hasDeclaration(
+ anyOf(
+ cxxRecordDecl(hasName("OSBoolean")),
+ cxxRecordDecl(hasName("OSNumber"))
+ .bind("osnumber"))))))))))
+ .bind("cpp_object")));
+
+ // Currently this matches NeXTSTEP number objects.
+ auto ObjCSuspiciousNumberObjectExprM =
+ expr(ignoringParenImpCasts(
+ expr(hasType(hasCanonicalType(
+ objcObjectPointerType(pointee(
+ qualType(hasCanonicalType(
+ qualType(hasDeclaration(
+ objcInterfaceDecl(hasName("NSNumber")))))))))))
+ .bind("objc_object")));
+
+ auto SuspiciousNumberObjectExprM = anyOf(
+ CSuspiciousNumberObjectExprM,
+ CppSuspiciousNumberObjectExprM,
+ ObjCSuspiciousNumberObjectExprM);
+
+ // Useful for predicates like "Unless we've seen the same object elsewhere".
+ auto AnotherSuspiciousNumberObjectExprM =
+ expr(anyOf(
+ equalsBoundNode("c_object"),
+ equalsBoundNode("objc_object"),
+ equalsBoundNode("cpp_object")));
+
+ // The .bind here is in order to compose the error message more accurately.
+ auto ObjCSuspiciousScalarBooleanTypeM =
+ qualType(typedefType(hasDeclaration(
+ typedefDecl(hasName("BOOL"))))).bind("objc_bool_type");
+
+ // The .bind here is in order to compose the error message more accurately.
+ auto SuspiciousScalarBooleanTypeM =
+ qualType(anyOf(qualType(booleanType()).bind("cpp_bool_type"),
+ ObjCSuspiciousScalarBooleanTypeM));
+
+ // The .bind here is in order to compose the error message more accurately.
+ // Also avoid intptr_t and uintptr_t because they were specifically created
+ // for storing pointers.
+ auto SuspiciousScalarNumberTypeM =
+ qualType(hasCanonicalType(isInteger()),
+ unless(typedefType(hasDeclaration(
+ typedefDecl(matchesName("^::u?intptr_t$"))))))
+ .bind("int_type");
+
+ auto SuspiciousScalarTypeM =
+ qualType(anyOf(SuspiciousScalarBooleanTypeM,
+ SuspiciousScalarNumberTypeM));
+
+ auto SuspiciousScalarExprM =
+ expr(ignoringParenImpCasts(expr(hasType(SuspiciousScalarTypeM))));
+
+ auto ConversionThroughAssignmentM =
+ binaryOperator(allOf(hasOperatorName("="),
+ hasLHS(SuspiciousScalarExprM),
+ hasRHS(SuspiciousNumberObjectExprM)));
+
+ auto ConversionThroughBranchingM =
+ ifStmt(hasCondition(SuspiciousNumberObjectExprM))
+ .bind("pedantic");
+
+ auto ConversionThroughCallM =
+ callExpr(hasAnyArgument(allOf(hasType(SuspiciousScalarTypeM),
+ ignoringParenImpCasts(
+ SuspiciousNumberObjectExprM))));
+
+ // We bind "check_if_null" to modify the warning message
+ // in case it was intended to compare a pointer to 0 with a relatively-ok
+ // construct "x == 0" or "x != 0".
+ auto ConversionThroughEquivalenceM =
+ binaryOperator(allOf(anyOf(hasOperatorName("=="), hasOperatorName("!=")),
+ hasEitherOperand(SuspiciousNumberObjectExprM),
+ hasEitherOperand(SuspiciousScalarExprM
+ .bind("check_if_null"))))
+ .bind("comparison");
+
+ auto ConversionThroughComparisonM =
+ binaryOperator(allOf(anyOf(hasOperatorName(">="), hasOperatorName(">"),
+ hasOperatorName("<="), hasOperatorName("<")),
+ hasEitherOperand(SuspiciousNumberObjectExprM),
+ hasEitherOperand(SuspiciousScalarExprM)))
+ .bind("comparison");
+
+ auto ConversionThroughConditionalOperatorM =
+ conditionalOperator(allOf(
+ hasCondition(SuspiciousNumberObjectExprM),
+ unless(hasTrueExpression(
+ hasDescendant(AnotherSuspiciousNumberObjectExprM))),
+ unless(hasFalseExpression(
+ hasDescendant(AnotherSuspiciousNumberObjectExprM)))))
+ .bind("pedantic");
+
+ auto ConversionThroughExclamationMarkM =
+ unaryOperator(allOf(hasOperatorName("!"),
+ has(expr(SuspiciousNumberObjectExprM))))
+ .bind("pedantic");
+
+ auto ConversionThroughExplicitBooleanCastM =
+ explicitCastExpr(allOf(hasType(SuspiciousScalarBooleanTypeM),
+ has(expr(SuspiciousNumberObjectExprM))));
+
+ auto ConversionThroughExplicitNumberCastM =
+ explicitCastExpr(allOf(hasType(SuspiciousScalarNumberTypeM),
+ has(expr(SuspiciousNumberObjectExprM))));
+
+ auto ConversionThroughInitializerM =
+ declStmt(hasSingleDecl(
+ varDecl(hasType(SuspiciousScalarTypeM),
+ hasInitializer(SuspiciousNumberObjectExprM))));
+
+ auto FinalM = stmt(anyOf(ConversionThroughAssignmentM,
+ ConversionThroughBranchingM,
+ ConversionThroughCallM,
+ ConversionThroughComparisonM,
+ ConversionThroughConditionalOperatorM,
+ ConversionThroughEquivalenceM,
+ ConversionThroughExclamationMarkM,
+ ConversionThroughExplicitBooleanCastM,
+ ConversionThroughExplicitNumberCastM,
+ ConversionThroughInitializerM)).bind("conv");
+
+ MatchFinder F;
+ Callback CB(this, BR, AM.getAnalysisDeclContext(D));
+
+ F.addMatcher(stmt(forEachDescendant(FinalM)), &CB);
+ F.match(*D->getBody(), AM.getASTContext());
+}
+
+void ento::registerNumberObjectConversionChecker(CheckerManager &Mgr) {
+ NumberObjectConversionChecker *Chk =
+ Mgr.registerChecker<NumberObjectConversionChecker>();
+ Chk->Pedantic =
+ Mgr.getAnalyzerOptions().getBooleanOption("Pedantic", false, Chk);
+}
diff --git a/lib/StaticAnalyzer/Checkers/ObjCPropertyChecker.cpp b/lib/StaticAnalyzer/Checkers/ObjCPropertyChecker.cpp
new file mode 100644
index 000000000000..b9857e51f3ea
--- /dev/null
+++ b/lib/StaticAnalyzer/Checkers/ObjCPropertyChecker.cpp
@@ -0,0 +1,82 @@
+//==- ObjCPropertyChecker.cpp - Check ObjC properties ------------*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This checker finds issues with Objective-C properties.
+// Currently finds only one kind of issue:
+// - Find synthesized properties with copy attribute of mutable NS collection
+// types. Calling -copy on such collections produces an immutable copy,
+// which contradicts the type of the property.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class ObjCPropertyChecker
+ : public Checker<check::ASTDecl<ObjCPropertyDecl>> {
+ void checkCopyMutable(const ObjCPropertyDecl *D, BugReporter &BR) const;
+
+public:
+ void checkASTDecl(const ObjCPropertyDecl *D, AnalysisManager &Mgr,
+ BugReporter &BR) const;
+};
+} // end anonymous namespace.
+
+void ObjCPropertyChecker::checkASTDecl(const ObjCPropertyDecl *D,
+ AnalysisManager &Mgr,
+ BugReporter &BR) const {
+ checkCopyMutable(D, BR);
+}
+
+void ObjCPropertyChecker::checkCopyMutable(const ObjCPropertyDecl *D,
+ BugReporter &BR) const {
+ if (D->isReadOnly() || D->getSetterKind() != ObjCPropertyDecl::Copy)
+ return;
+
+ QualType T = D->getType();
+ if (!T->isObjCObjectPointerType())
+ return;
+
+ const std::string &PropTypeName(T->getPointeeType().getCanonicalType()
+ .getUnqualifiedType()
+ .getAsString());
+ if (!StringRef(PropTypeName).startswith("NSMutable"))
+ return;
+
+ const ObjCImplDecl *ImplD = nullptr;
+ if (const ObjCInterfaceDecl *IntD =
+ dyn_cast<ObjCInterfaceDecl>(D->getDeclContext())) {
+ ImplD = IntD->getImplementation();
+ } else {
+ const ObjCCategoryDecl *CatD = cast<ObjCCategoryDecl>(D->getDeclContext());
+ ImplD = CatD->getClassInterface()->getImplementation();
+ }
+
+ if (!ImplD || ImplD->HasUserDeclaredSetterMethod(D))
+ return;
+
+ SmallString<128> Str;
+ llvm::raw_svector_ostream OS(Str);
+ OS << "Property of mutable type '" << PropTypeName
+ << "' has 'copy' attribute; an immutable object will be stored instead";
+
+ BR.EmitBasicReport(
+ D, this, "Objective-C property misuse", "Logic error", OS.str(),
+ PathDiagnosticLocation::createBegin(D, BR.getSourceManager()),
+ D->getSourceRange());
+}
+
+void ento::registerObjCPropertyChecker(CheckerManager &Mgr) {
+ Mgr.registerChecker<ObjCPropertyChecker>();
+}
diff --git a/lib/StaticAnalyzer/Checkers/ObjCSuperDeallocChecker.cpp b/lib/StaticAnalyzer/Checkers/ObjCSuperDeallocChecker.cpp
index 15980c5c5387..e75d20897710 100644
--- a/lib/StaticAnalyzer/Checkers/ObjCSuperDeallocChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/ObjCSuperDeallocChecker.cpp
@@ -191,7 +191,7 @@ void ObjCSuperDeallocChecker::reportUseAfterDealloc(SymbolRef Sym,
return;
if (Desc.empty())
- Desc = "use of 'self' after it has been deallocated";
+ Desc = "Use of 'self' after it has been deallocated";
// Generate the report.
std::unique_ptr<BugReport> BR(
diff --git a/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp b/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp
index 0640d2f49f43..a51dda6fe858 100644
--- a/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp
@@ -82,7 +82,11 @@ public:
CharUnits BaselinePad = calculateBaselinePad(RD, ASTContext, RL);
if (BaselinePad.isZero())
return;
- CharUnits OptimalPad = calculateOptimalPad(RD, ASTContext, RL);
+
+ CharUnits OptimalPad;
+ SmallVector<const FieldDecl *, 20> OptimalFieldsOrder;
+ std::tie(OptimalPad, OptimalFieldsOrder) =
+ calculateOptimalPad(RD, ASTContext, RL);
CharUnits DiffPad = PadMultiplier * (BaselinePad - OptimalPad);
if (DiffPad.getQuantity() <= AllowedPad) {
@@ -90,7 +94,7 @@ public:
// There is not enough excess padding to trigger a warning.
return;
}
- reportRecord(RD, BaselinePad, OptimalPad);
+ reportRecord(RD, BaselinePad, OptimalPad, OptimalFieldsOrder);
}
/// \brief Look for arrays of overly padded types. If the padding of the
@@ -199,22 +203,30 @@ public:
/// 7. Add tail padding by rounding the current offset up to the structure
/// alignment. Track the amount of padding added.
- static CharUnits calculateOptimalPad(const RecordDecl *RD,
- const ASTContext &ASTContext,
- const ASTRecordLayout &RL) {
- struct CharUnitPair {
+ static std::pair<CharUnits, SmallVector<const FieldDecl *, 20>>
+ calculateOptimalPad(const RecordDecl *RD, const ASTContext &ASTContext,
+ const ASTRecordLayout &RL) {
+ struct FieldInfo {
CharUnits Align;
CharUnits Size;
- bool operator<(const CharUnitPair &RHS) const {
+ const FieldDecl *Field;
+ bool operator<(const FieldInfo &RHS) const {
// Order from small alignments to large alignments,
// then large sizes to small sizes.
- return std::make_pair(Align, -Size) <
- std::make_pair(RHS.Align, -RHS.Size);
+ // then large field indices to small field indices
+ return std::make_tuple(Align, -Size,
+ Field ? -static_cast<int>(Field->getFieldIndex())
+ : 0) <
+ std::make_tuple(
+ RHS.Align, -RHS.Size,
+ RHS.Field ? -static_cast<int>(RHS.Field->getFieldIndex())
+ : 0);
}
};
- SmallVector<CharUnitPair, 20> Fields;
+ SmallVector<FieldInfo, 20> Fields;
auto GatherSizesAndAlignments = [](const FieldDecl *FD) {
- CharUnitPair RetVal;
+ FieldInfo RetVal;
+ RetVal.Field = FD;
auto &Ctx = FD->getASTContext();
std::tie(RetVal.Size, RetVal.Align) =
Ctx.getTypeInfoInChars(FD->getType());
@@ -226,14 +238,13 @@ public:
std::transform(RD->field_begin(), RD->field_end(),
std::back_inserter(Fields), GatherSizesAndAlignments);
std::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
// could pack more bytes in to a base class's tail padding.
CharUnits NewOffset = ASTContext.toCharUnitsFromBits(RL.getFieldOffset(0));
CharUnits NewPad;
-
+ SmallVector<const FieldDecl *, 20> OptimalFieldsOrder;
while (!Fields.empty()) {
unsigned TrailingZeros =
llvm::countTrailingZeros((unsigned long long)NewOffset.getQuantity());
@@ -242,7 +253,7 @@ public:
// our long long (and CharUnits internal type) negative. So shift 62.
long long CurAlignmentBits = 1ull << (std::min)(TrailingZeros, 62u);
CharUnits CurAlignment = CharUnits::fromQuantity(CurAlignmentBits);
- CharUnitPair InsertPoint = {CurAlignment, CharUnits::Zero()};
+ FieldInfo InsertPoint = {CurAlignment, CharUnits::Zero(), nullptr};
auto CurBegin = Fields.begin();
auto CurEnd = Fields.end();
@@ -255,6 +266,7 @@ public:
// We found a field that we can layout with the current alignment.
--Iter;
NewOffset += Iter->Size;
+ OptimalFieldsOrder.push_back(Iter->Field);
Fields.erase(Iter);
} else {
// We are poorly aligned, and we need to pad in order to layout another
@@ -268,18 +280,18 @@ public:
// Calculate tail padding.
CharUnits NewSize = NewOffset.alignTo(RL.getAlignment());
NewPad += NewSize - NewOffset;
- return NewPad;
+ return {NewPad, std::move(OptimalFieldsOrder)};
}
- void reportRecord(const RecordDecl *RD, CharUnits BaselinePad,
- CharUnits TargetPad) const {
+ void reportRecord(
+ const RecordDecl *RD, CharUnits BaselinePad, CharUnits OptimalPad,
+ const SmallVector<const FieldDecl *, 20> &OptimalFieldsOrder) const {
if (!PaddingBug)
PaddingBug =
llvm::make_unique<BugType>(this, "Excessive Padding", "Performance");
SmallString<100> Buf;
llvm::raw_svector_ostream Os(Buf);
-
Os << "Excessive padding in '";
Os << QualType::getAsString(RD->getTypeForDecl(), Qualifiers()) << "'";
@@ -294,16 +306,18 @@ public:
}
Os << " (" << BaselinePad.getQuantity() << " padding bytes, where "
- << TargetPad.getQuantity() << " is optimal). Consider reordering "
- << "the fields or adding explicit padding members.";
+ << OptimalPad.getQuantity() << " is optimal). \n"
+ << "Optimal fields order: \n";
+ for (const auto *FD : OptimalFieldsOrder)
+ Os << FD->getName() << ", \n";
+ Os << "consider reordering the fields or adding explicit padding "
+ "members.";
PathDiagnosticLocation CELoc =
PathDiagnosticLocation::create(RD, BR->getSourceManager());
-
auto Report = llvm::make_unique<BugReport>(*PaddingBug, Os.str(), CELoc);
Report->setDeclWithIssue(RD);
Report->addRange(RD->getSourceRange());
-
BR->emitReport(std::move(Report));
}
};
diff --git a/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp b/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp
index df5118806bff..8caf6df4d970 100644
--- a/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp
@@ -19,7 +19,6 @@
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
-#include "llvm/ADT/SmallVector.h"
using namespace clang;
using namespace ento;
diff --git a/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp b/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
index 28a4a083ea3c..7ef79c683c49 100644
--- a/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
@@ -18,7 +18,6 @@
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
-#include "llvm/ADT/ImmutableList.h"
using namespace clang;
using namespace ento;
diff --git a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
index b646127cfae7..204b0a6c468b 100644
--- a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
@@ -740,7 +740,7 @@ public:
ObjCAllocRetE(gcenabled
? RetEffect::MakeGCNotOwned()
: (usesARC ? RetEffect::MakeNotOwned(RetEffect::ObjC)
- : RetEffect::MakeOwned(RetEffect::ObjC, true))),
+ : RetEffect::MakeOwned(RetEffect::ObjC))),
ObjCInitRetE(gcenabled
? RetEffect::MakeGCNotOwned()
: (usesARC ? RetEffect::MakeNotOwned(RetEffect::ObjC)
@@ -953,7 +953,10 @@ void RetainSummaryManager::updateSummaryForCall(const RetainSummary *&S,
if (IdentifierInfo *Name = FC->getDecl()->getIdentifier()) {
// When the CGBitmapContext is deallocated, the callback here will free
// the associated data buffer.
- if (Name->isStr("CGBitmapContextCreateWithData"))
+ // The callback in dispatch_data_create frees the buffer, but not
+ // the data object.
+ if (Name->isStr("CGBitmapContextCreateWithData") ||
+ Name->isStr("dispatch_data_create"))
RE = S->getRetEffect();
}
}
@@ -1086,7 +1089,7 @@ RetainSummaryManager::getFunctionSummary(const FunctionDecl *FD) {
FName == "IOOpenFirmwarePathMatching") {
// Part of <rdar://problem/6961230>. (IOKit)
// This should be addressed using a API table.
- S = getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true),
+ S = getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF),
DoNothing, DoNothing);
} else if (FName == "IOServiceGetMatchingService" ||
FName == "IOServiceGetMatchingServices") {
@@ -1116,7 +1119,7 @@ RetainSummaryManager::getFunctionSummary(const FunctionDecl *FD) {
// passed to CGBitmapContextCreateWithData is released via
// a callback and doing full IPA to make sure this is done correctly.
ScratchArgs = AF.add(ScratchArgs, 8, StopTracking);
- S = getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true),
+ S = getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF),
DoNothing, DoNothing);
} else if (FName == "CVPixelBufferCreateWithPlanarBytes") {
// FIXES: <rdar://problem/7283567>
@@ -1126,6 +1129,14 @@ RetainSummaryManager::getFunctionSummary(const FunctionDecl *FD) {
// correctly.
ScratchArgs = AF.add(ScratchArgs, 12, StopTracking);
S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
+ } else if (FName == "VTCompressionSessionEncodeFrame") {
+ // The context argument passed to VTCompressionSessionEncodeFrame()
+ // is passed to the callback specified when creating the session
+ // (e.g. with VTCompressionSessionCreate()) which can release it.
+ // To account for this possibility, conservatively stop tracking
+ // the context.
+ ScratchArgs = AF.add(ScratchArgs, 5, StopTracking);
+ S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
} else if (FName == "dispatch_set_context" ||
FName == "xpc_connection_set_context") {
// <rdar://problem/11059275> - The analyzer currently doesn't have
@@ -1171,8 +1182,9 @@ RetainSummaryManager::getFunctionSummary(const FunctionDecl *FD) {
break;
}
- // For CoreGraphics ('CG') types.
- if (cocoa::isRefType(RetTy, "CG", FName)) {
+ // For CoreGraphics ('CG') and CoreVideo ('CV') types.
+ if (cocoa::isRefType(RetTy, "CG", FName) ||
+ cocoa::isRefType(RetTy, "CV", FName)) {
if (isRetain(FD, FName))
S = getUnarySummary(FT, cfretain);
else
@@ -1283,7 +1295,7 @@ const RetainSummary *
RetainSummaryManager::getCFSummaryCreateRule(const FunctionDecl *FD) {
assert (ScratchArgs.isEmpty());
- return getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true));
+ return getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF));
}
const RetainSummary *
@@ -1313,7 +1325,7 @@ RetainSummaryManager::getRetEffectFromAnnotations(QualType RetTy,
}
if (D->hasAttr<CFReturnsRetainedAttr>())
- return RetEffect::MakeOwned(RetEffect::CF, true);
+ return RetEffect::MakeOwned(RetEffect::CF);
if (D->hasAttr<CFReturnsNotRetainedAttr>())
return RetEffect::MakeNotOwned(RetEffect::CF);
@@ -1426,7 +1438,7 @@ RetainSummaryManager::getStandardMethodSummary(const ObjCMethodDecl *MD,
case OMF_new:
case OMF_copy:
case OMF_mutableCopy:
- ResultEff = RetEffect::MakeOwned(RetEffect::CF, true);
+ ResultEff = RetEffect::MakeOwned(RetEffect::CF);
break;
default:
ResultEff = RetEffect::MakeNotOwned(RetEffect::CF);
@@ -1448,7 +1460,7 @@ RetainSummaryManager::getStandardMethodSummary(const ObjCMethodDecl *MD,
if (cocoa::isCocoaObjectRef(RetTy))
ResultEff = ObjCAllocRetE;
else if (coreFoundation::isCFObjectRef(RetTy))
- ResultEff = RetEffect::MakeOwned(RetEffect::CF, true);
+ ResultEff = RetEffect::MakeOwned(RetEffect::CF);
break;
case OMF_autorelease:
ReceiverEff = Autorelease;
@@ -1579,7 +1591,7 @@ void RetainSummaryManager::InitializeMethodSummaries() {
// The next methods are allocators.
const RetainSummary *AllocSumm = getPersistentSummary(ObjCAllocRetE);
const RetainSummary *CFAllocSumm =
- getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true));
+ getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF));
// Create the "retain" selector.
RetEffect NoRet = RetEffect::MakeNoRet();
@@ -1978,11 +1990,23 @@ PathDiagnosticPiece *CFRefReportVisitor::VisitNode(const ExplodedNode *N,
}
if (CurrV.getObjKind() == RetEffect::CF) {
- os << " returns a Core Foundation object with a ";
+ if (Sym->getType().isNull()) {
+ os << " returns a Core Foundation object with a ";
+ } else {
+ os << " returns a Core Foundation object of type "
+ << Sym->getType().getAsString() << " with a ";
+ }
}
else {
assert (CurrV.getObjKind() == RetEffect::ObjC);
- os << " returns an Objective-C object with a ";
+ QualType T = Sym->getType();
+ if (T.isNull() || !isa<ObjCObjectPointerType>(T)) {
+ os << " returns an Objective-C object with a ";
+ } else {
+ const ObjCObjectPointerType *PT = cast<ObjCObjectPointerType>(T);
+ os << " returns an instance of "
+ << PT->getPointeeType().getAsString() << " with a ";
+ }
}
if (CurrV.isOwned()) {
@@ -2358,10 +2382,15 @@ CFRefLeakReportVisitor::getEndPath(BugReporterContext &BRC,
os << "that is annotated as NS_RETURNS_NOT_RETAINED";
else {
if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
- os << "whose name ('" << MD->getSelector().getAsString()
- << "') does not start with 'copy', 'mutableCopy', 'alloc' or 'new'."
- " This violates the naming convention rules"
- " given in the Memory Management Guide for Cocoa";
+ if (BRC.getASTContext().getLangOpts().ObjCAutoRefCount) {
+ os << "managed by Automatic Reference Counting";
+ } else {
+ os << "whose name ('" << MD->getSelector().getAsString()
+ << "') does not start with "
+ "'copy', 'mutableCopy', 'alloc' or 'new'."
+ " This violates the naming convention rules"
+ " given in the Memory Management Guide for Cocoa";
+ }
}
else {
const FunctionDecl *FD = cast<FunctionDecl>(D);
@@ -2417,12 +2446,7 @@ CFRefLeakReport::CFRefLeakReport(CFRefBug &D, const LangOptions &LOpts,
// FIXME: This will crash the analyzer if an allocation comes from an
// implicit call (ex: a destructor call).
// (Currently there are no such allocations in Cocoa, though.)
- const Stmt *AllocStmt = nullptr;
- ProgramPoint P = AllocNode->getLocation();
- if (Optional<CallExitEnd> Exit = P.getAs<CallExitEnd>())
- AllocStmt = Exit->getCalleeContext()->getCallSite();
- else
- AllocStmt = P.castAs<PostStmt>().getStmt();
+ const Stmt *AllocStmt = PathDiagnosticLocation::getStmt(AllocNode);
assert(AllocStmt && "Cannot find allocation statement");
PathDiagnosticLocation AllocLocation =
@@ -2640,10 +2664,6 @@ public:
ArrayRef<const MemRegion *> Regions,
const CallEvent *Call) const;
- bool wantsRegionChangeUpdate(ProgramStateRef state) const {
- return true;
- }
-
void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const;
void checkReturnWithRetEffect(const ReturnStmt *S, CheckerContext &C,
ExplodedNode *Pred, RetEffect RE, RefVal X,
@@ -3071,7 +3091,6 @@ void RetainCountChecker::checkSummary(const RetainSummary &Summ,
// No work necessary.
break;
- case RetEffect::OwnedAllocatedSymbol:
case RetEffect::OwnedSymbol: {
SymbolRef Sym = CallOrMsg.getReturnValue().getAsSymbol();
if (!Sym)
@@ -3372,12 +3391,13 @@ bool RetainCountChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
// Handle: id NSMakeCollectable(CFTypeRef)
canEval = II->isStr("NSMakeCollectable");
} else if (ResultTy->isPointerType()) {
- // Handle: (CF|CG)Retain
+ // Handle: (CF|CG|CV)Retain
// CFAutorelease
// CFMakeCollectable
// It's okay to be a little sloppy here (CGMakeCollectable doesn't exist).
if (cocoa::isRefType(ResultTy, "CF", FName) ||
- cocoa::isRefType(ResultTy, "CG", FName)) {
+ cocoa::isRefType(ResultTy, "CG", FName) ||
+ cocoa::isRefType(ResultTy, "CV", FName)) {
canEval = isRetain(FD, FName) || isAutorelease(FD, FName) ||
isMakeCollectable(FD, FName);
}
@@ -3866,7 +3886,7 @@ void RetainCountChecker::checkEndFunction(CheckerContext &Ctx) const {
// Don't process anything within synthesized bodies.
const LocationContext *LCtx = Pred->getLocationContext();
if (LCtx->getAnalysisDeclContext()->isBodyAutosynthesized()) {
- assert(LCtx->getParent());
+ assert(!LCtx->inTopFrame());
return;
}
diff --git a/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp b/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
new file mode 100644
index 000000000000..93ad17cffb34
--- /dev/null
+++ b/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
@@ -0,0 +1,1055 @@
+//=== StdLibraryFunctionsChecker.cpp - Model standard functions -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This checker improves modeling of a few simple library functions.
+// It does not generate warnings.
+//
+// This checker provides a specification format - `FunctionSummaryTy' - and
+// contains descriptions of some library functions in this format. Each
+// specification contains a list of branches for splitting the program state
+// upon call, and range constraints on argument and return-value symbols that
+// are satisfied on each branch. This spec can be expanded to include more
+// items, like external effects of the function.
+//
+// The main difference between this approach and the body farms technique is
+// in more explicit control over how many branches are produced. For example,
+// consider standard C function `ispunct(int x)', which returns a non-zero value
+// iff `x' is a punctuation character, that is, when `x' is in range
+// ['!', '/'] [':', '@'] U ['[', '\`'] U ['{', '~'].
+// `FunctionSummaryTy' provides only two branches for this function. However,
+// any attempt to describe this range with if-statements in the body farm
+// would result in many more branches. Because each branch needs to be analyzed
+// independently, this significantly reduces performance. Additionally,
+// once we consider a branch on which `x' is in range, say, ['!', '/'],
+// we assume that such branch is an important separate path through the program,
+// which may lead to false positives because considering this particular path
+// was not consciously intended, and therefore it might have been unreachable.
+//
+// This checker uses eval::Call for modeling "pure" functions, for which
+// their `FunctionSummaryTy' is a precise model. This avoids unnecessary
+// invalidation passes. Conflicts with other checkers are unlikely because
+// if the function has no other effects, other checkers would probably never
+// want to improve upon the modeling done by this checker.
+//
+// Non-"pure" functions, for which only partial improvement over the default
+// behavior is expected, are modeled via check::PostCall, non-intrusively.
+//
+// The following standard C functions are currently supported:
+//
+// fgetc getline isdigit isupper
+// fread isalnum isgraph isxdigit
+// fwrite isalpha islower read
+// getc isascii isprint write
+// getchar isblank ispunct
+// getdelim iscntrl isspace
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.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 clang::ento;
+
+namespace {
+class StdLibraryFunctionsChecker : public Checker<check::PostCall, eval::Call> {
+ /// Below is a series of typedefs necessary to define function specs.
+ /// We avoid nesting types here because each additional qualifier
+ /// would need to be repeated in every function spec.
+ struct FunctionSummaryTy;
+
+ /// Specify how much the analyzer engine should entrust modeling this function
+ /// to us. If he doesn't, he performs additional invalidations.
+ enum InvalidationKindTy { NoEvalCall, EvalCallAsPure };
+
+ /// A pair of ValueRangeKindTy and IntRangeVectorTy would describe a range
+ /// imposed on a particular argument or return value symbol.
+ ///
+ /// Given a range, should the argument stay inside or outside this range?
+ /// The special `ComparesToArgument' value indicates that we should
+ /// impose a constraint that involves other argument or return value symbols.
+ enum ValueRangeKindTy { OutOfRange, WithinRange, ComparesToArgument };
+
+ // The universal integral type to use in value range descriptions.
+ // Unsigned to make sure overflows are well-defined.
+ typedef uint64_t RangeIntTy;
+
+ /// Normally, describes a single range constraint, eg. {{0, 1}, {3, 4}} is
+ /// a non-negative integer, which less than 5 and not equal to 2. For
+ /// `ComparesToArgument', holds information about how exactly to compare to
+ /// the argument.
+ typedef std::vector<std::pair<RangeIntTy, RangeIntTy>> IntRangeVectorTy;
+
+ /// A reference to an argument or return value by its number.
+ /// ArgNo in CallExpr and CallEvent is defined as Unsigned, but
+ /// obviously uint32_t should be enough for all practical purposes.
+ typedef uint32_t ArgNoTy;
+ static const ArgNoTy Ret = std::numeric_limits<ArgNoTy>::max();
+
+ /// Incapsulates a single range on a single symbol within a branch.
+ class ValueRange {
+ ArgNoTy ArgNo; // Argument to which we apply the range.
+ ValueRangeKindTy Kind; // Kind of range definition.
+ IntRangeVectorTy Args; // Polymorphic arguments.
+
+ public:
+ ValueRange(ArgNoTy ArgNo, ValueRangeKindTy Kind,
+ const IntRangeVectorTy &Args)
+ : ArgNo(ArgNo), Kind(Kind), Args(Args) {}
+
+ ArgNoTy getArgNo() const { return ArgNo; }
+ ValueRangeKindTy getKind() const { return Kind; }
+
+ BinaryOperator::Opcode getOpcode() const {
+ assert(Kind == ComparesToArgument);
+ assert(Args.size() == 1);
+ BinaryOperator::Opcode Op =
+ static_cast<BinaryOperator::Opcode>(Args[0].first);
+ assert(BinaryOperator::isComparisonOp(Op) &&
+ "Only comparison ops are supported for ComparesToArgument");
+ return Op;
+ }
+
+ ArgNoTy getOtherArgNo() const {
+ assert(Kind == ComparesToArgument);
+ assert(Args.size() == 1);
+ return static_cast<ArgNoTy>(Args[0].second);
+ }
+
+ const IntRangeVectorTy &getRanges() const {
+ assert(Kind != ComparesToArgument);
+ return Args;
+ }
+
+ // We avoid creating a virtual apply() method because
+ // it makes initializer lists harder to write.
+ private:
+ ProgramStateRef
+ applyAsOutOfRange(ProgramStateRef State, const CallEvent &Call,
+ const FunctionSummaryTy &Summary) const;
+ ProgramStateRef
+ applyAsWithinRange(ProgramStateRef State, const CallEvent &Call,
+ const FunctionSummaryTy &Summary) const;
+ ProgramStateRef
+ applyAsComparesToArgument(ProgramStateRef State, const CallEvent &Call,
+ const FunctionSummaryTy &Summary) const;
+
+ public:
+ ProgramStateRef apply(ProgramStateRef State, const CallEvent &Call,
+ const FunctionSummaryTy &Summary) const {
+ switch (Kind) {
+ case OutOfRange:
+ return applyAsOutOfRange(State, Call, Summary);
+ case WithinRange:
+ return applyAsWithinRange(State, Call, Summary);
+ case ComparesToArgument:
+ return applyAsComparesToArgument(State, Call, Summary);
+ }
+ llvm_unreachable("Unknown ValueRange kind!");
+ }
+ };
+
+ /// The complete list of ranges that defines a single branch.
+ typedef std::vector<ValueRange> ValueRangeSet;
+
+ /// Includes information about function prototype (which is necessary to
+ /// ensure we're modeling the right function and casting values properly),
+ /// approach to invalidation, and a list of branches - essentially, a list
+ /// of list of ranges - essentially, a list of lists of lists of segments.
+ struct FunctionSummaryTy {
+ const std::vector<QualType> ArgTypes;
+ const QualType RetType;
+ const InvalidationKindTy InvalidationKind;
+ const std::vector<ValueRangeSet> Ranges;
+
+ private:
+ static void assertTypeSuitableForSummary(QualType T) {
+ assert(!T->isVoidType() &&
+ "We should have had no significant void types in the spec");
+ assert(T.isCanonical() &&
+ "We should only have canonical types in the spec");
+ // FIXME: lift this assert (but not the ones above!)
+ assert(T->isIntegralOrEnumerationType() &&
+ "We only support integral ranges in the spec");
+ }
+
+ public:
+ QualType getArgType(ArgNoTy ArgNo) const {
+ QualType T = (ArgNo == Ret) ? RetType : ArgTypes[ArgNo];
+ assertTypeSuitableForSummary(T);
+ return T;
+ }
+
+ /// Try our best to figure out if the call expression is the call of
+ /// *the* library function to which this specification applies.
+ bool matchesCall(const CallExpr *CE) const;
+ };
+
+ // The same function (as in, function identifier) may have different
+ // summaries assigned to it, with different argument and return value types.
+ // We call these "variants" of the function. This can be useful for handling
+ // C++ function overloads, and also it can be used when the same function
+ // may have different definitions on different platforms.
+ typedef std::vector<FunctionSummaryTy> FunctionVariantsTy;
+
+ // The map of all functions supported by the checker. It is initialized
+ // lazily, and it doesn't change after initialization.
+ typedef llvm::StringMap<FunctionVariantsTy> FunctionSummaryMapTy;
+ mutable FunctionSummaryMapTy FunctionSummaryMap;
+
+ // Auxiliary functions to support ArgNoTy within all structures
+ // in a unified manner.
+ static QualType getArgType(const FunctionSummaryTy &Summary, ArgNoTy ArgNo) {
+ return Summary.getArgType(ArgNo);
+ }
+ static QualType getArgType(const CallEvent &Call, ArgNoTy ArgNo) {
+ return ArgNo == Ret ? Call.getResultType().getCanonicalType()
+ : Call.getArgExpr(ArgNo)->getType().getCanonicalType();
+ }
+ static QualType getArgType(const CallExpr *CE, ArgNoTy ArgNo) {
+ return ArgNo == Ret ? CE->getType().getCanonicalType()
+ : CE->getArg(ArgNo)->getType().getCanonicalType();
+ }
+ static SVal getArgSVal(const CallEvent &Call, ArgNoTy ArgNo) {
+ return ArgNo == Ret ? Call.getReturnValue() : Call.getArgSVal(ArgNo);
+ }
+
+public:
+ void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
+ bool evalCall(const CallExpr *CE, CheckerContext &C) const;
+
+private:
+ Optional<FunctionSummaryTy> findFunctionSummary(const FunctionDecl *FD,
+ const CallExpr *CE,
+ CheckerContext &C) const;
+
+ void initFunctionSummaries(BasicValueFactory &BVF) const;
+};
+} // end of anonymous namespace
+
+ProgramStateRef StdLibraryFunctionsChecker::ValueRange::applyAsOutOfRange(
+ ProgramStateRef State, const CallEvent &Call,
+ const FunctionSummaryTy &Summary) const {
+
+ ProgramStateManager &Mgr = State->getStateManager();
+ SValBuilder &SVB = Mgr.getSValBuilder();
+ BasicValueFactory &BVF = SVB.getBasicValueFactory();
+ ConstraintManager &CM = Mgr.getConstraintManager();
+ QualType T = getArgType(Summary, getArgNo());
+ SVal V = getArgSVal(Call, getArgNo());
+
+ if (auto N = V.getAs<NonLoc>()) {
+ const IntRangeVectorTy &R = getRanges();
+ size_t E = R.size();
+ for (size_t I = 0; I != E; ++I) {
+ const llvm::APSInt &Min = BVF.getValue(R[I].first, T);
+ const llvm::APSInt &Max = BVF.getValue(R[I].second, T);
+ assert(Min <= Max);
+ State = CM.assumeInclusiveRange(State, *N, Min, Max, false);
+ if (!State)
+ break;
+ }
+ }
+
+ return State;
+}
+
+ProgramStateRef
+StdLibraryFunctionsChecker::ValueRange::applyAsWithinRange(
+ ProgramStateRef State, const CallEvent &Call,
+ const FunctionSummaryTy &Summary) const {
+
+ ProgramStateManager &Mgr = State->getStateManager();
+ SValBuilder &SVB = Mgr.getSValBuilder();
+ BasicValueFactory &BVF = SVB.getBasicValueFactory();
+ ConstraintManager &CM = Mgr.getConstraintManager();
+ QualType T = getArgType(Summary, getArgNo());
+ SVal V = getArgSVal(Call, getArgNo());
+
+ // "WithinRange R" is treated as "outside [T_MIN, T_MAX] \ R".
+ // We cut off [T_MIN, min(R) - 1] and [max(R) + 1, T_MAX] if necessary,
+ // and then cut away all holes in R one by one.
+ if (auto N = V.getAs<NonLoc>()) {
+ const IntRangeVectorTy &R = getRanges();
+ size_t E = R.size();
+
+ const llvm::APSInt &MinusInf = BVF.getMinValue(T);
+ const llvm::APSInt &PlusInf = BVF.getMaxValue(T);
+
+ const llvm::APSInt &Left = BVF.getValue(R[0].first - 1ULL, T);
+ if (Left != PlusInf) {
+ assert(MinusInf <= Left);
+ State = CM.assumeInclusiveRange(State, *N, MinusInf, Left, false);
+ if (!State)
+ return nullptr;
+ }
+
+ const llvm::APSInt &Right = BVF.getValue(R[E - 1].second + 1ULL, T);
+ if (Right != MinusInf) {
+ assert(Right <= PlusInf);
+ State = CM.assumeInclusiveRange(State, *N, Right, PlusInf, false);
+ if (!State)
+ return nullptr;
+ }
+
+ for (size_t I = 1; I != E; ++I) {
+ const llvm::APSInt &Min = BVF.getValue(R[I - 1].second + 1ULL, T);
+ const llvm::APSInt &Max = BVF.getValue(R[I].first - 1ULL, T);
+ assert(Min <= Max);
+ State = CM.assumeInclusiveRange(State, *N, Min, Max, false);
+ if (!State)
+ return nullptr;
+ }
+ }
+
+ return State;
+}
+
+ProgramStateRef
+StdLibraryFunctionsChecker::ValueRange::applyAsComparesToArgument(
+ ProgramStateRef State, const CallEvent &Call,
+ const FunctionSummaryTy &Summary) const {
+
+ ProgramStateManager &Mgr = State->getStateManager();
+ SValBuilder &SVB = Mgr.getSValBuilder();
+ QualType CondT = SVB.getConditionType();
+ QualType T = getArgType(Summary, getArgNo());
+ SVal V = getArgSVal(Call, getArgNo());
+
+ BinaryOperator::Opcode Op = getOpcode();
+ ArgNoTy OtherArg = getOtherArgNo();
+ SVal OtherV = getArgSVal(Call, OtherArg);
+ QualType OtherT = getArgType(Call, OtherArg);
+ // Note: we avoid integral promotion for comparison.
+ OtherV = SVB.evalCast(OtherV, T, OtherT);
+ if (auto CompV = SVB.evalBinOp(State, Op, V, OtherV, CondT)
+ .getAs<DefinedOrUnknownSVal>())
+ State = State->assume(*CompV, true);
+ return State;
+}
+
+void StdLibraryFunctionsChecker::checkPostCall(const CallEvent &Call,
+ CheckerContext &C) const {
+ const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(Call.getDecl());
+ if (!FD)
+ return;
+
+ const CallExpr *CE = dyn_cast_or_null<CallExpr>(Call.getOriginExpr());
+ if (!CE)
+ return;
+
+ Optional<FunctionSummaryTy> FoundSummary = findFunctionSummary(FD, CE, C);
+ if (!FoundSummary)
+ return;
+
+ // Now apply ranges.
+ const FunctionSummaryTy &Summary = *FoundSummary;
+ ProgramStateRef State = C.getState();
+
+ for (const auto &VRS: Summary.Ranges) {
+ ProgramStateRef NewState = State;
+ for (const auto &VR: VRS) {
+ NewState = VR.apply(NewState, Call, Summary);
+ if (!NewState)
+ break;
+ }
+
+ if (NewState && NewState != State)
+ C.addTransition(NewState);
+ }
+}
+
+bool StdLibraryFunctionsChecker::evalCall(const CallExpr *CE,
+ CheckerContext &C) const {
+ const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(CE->getCalleeDecl());
+ if (!FD)
+ return false;
+
+ Optional<FunctionSummaryTy> FoundSummary = findFunctionSummary(FD, CE, C);
+ if (!FoundSummary)
+ return false;
+
+ const FunctionSummaryTy &Summary = *FoundSummary;
+ switch (Summary.InvalidationKind) {
+ case EvalCallAsPure: {
+ ProgramStateRef State = C.getState();
+ const LocationContext *LC = C.getLocationContext();
+ SVal V = C.getSValBuilder().conjureSymbolVal(
+ CE, LC, CE->getType().getCanonicalType(), C.blockCount());
+ State = State->BindExpr(CE, LC, V);
+ C.addTransition(State);
+ return true;
+ }
+ case NoEvalCall:
+ // Summary tells us to avoid performing eval::Call. The function is possibly
+ // evaluated by another checker, or evaluated conservatively.
+ return false;
+ }
+ llvm_unreachable("Unknown invalidation kind!");
+}
+
+bool StdLibraryFunctionsChecker::FunctionSummaryTy::matchesCall(
+ const CallExpr *CE) const {
+ // Check number of arguments:
+ if (CE->getNumArgs() != ArgTypes.size())
+ return false;
+
+ // Check return type if relevant:
+ if (!RetType.isNull() && RetType != CE->getType().getCanonicalType())
+ return false;
+
+ // Check argument types when relevant:
+ for (size_t I = 0, E = ArgTypes.size(); I != E; ++I) {
+ QualType FormalT = ArgTypes[I];
+ // Null type marks irrelevant arguments.
+ if (FormalT.isNull())
+ continue;
+
+ assertTypeSuitableForSummary(FormalT);
+
+ QualType ActualT = StdLibraryFunctionsChecker::getArgType(CE, I);
+ assert(ActualT.isCanonical());
+ if (ActualT != FormalT)
+ return false;
+ }
+
+ return true;
+}
+
+Optional<StdLibraryFunctionsChecker::FunctionSummaryTy>
+StdLibraryFunctionsChecker::findFunctionSummary(const FunctionDecl *FD,
+ const CallExpr *CE,
+ CheckerContext &C) const {
+ // Note: we cannot always obtain FD from CE
+ // (eg. virtual call, or call by pointer).
+ assert(CE);
+
+ if (!FD)
+ return None;
+
+ SValBuilder &SVB = C.getSValBuilder();
+ BasicValueFactory &BVF = SVB.getBasicValueFactory();
+ initFunctionSummaries(BVF);
+
+ std::string Name = FD->getQualifiedNameAsString();
+ if (Name.empty() || !C.isCLibraryFunction(FD, Name))
+ return None;
+
+ auto FSMI = FunctionSummaryMap.find(Name);
+ if (FSMI == FunctionSummaryMap.end())
+ return None;
+
+ // Verify that function signature matches the spec in advance.
+ // Otherwise we might be modeling the wrong function.
+ // Strict checking is important because we will be conducting
+ // very integral-type-sensitive operations on arguments and
+ // return values.
+ const FunctionVariantsTy &SpecVariants = FSMI->second;
+ for (const FunctionSummaryTy &Spec : SpecVariants)
+ if (Spec.matchesCall(CE))
+ return Spec;
+
+ return None;
+}
+
+void StdLibraryFunctionsChecker::initFunctionSummaries(
+ BasicValueFactory &BVF) const {
+ if (!FunctionSummaryMap.empty())
+ return;
+
+ ASTContext &ACtx = BVF.getContext();
+
+ // These types are useful for writing specifications quickly,
+ // New specifications should probably introduce more types.
+ // Some types are hard to obtain from the AST, eg. "ssize_t".
+ // In such cases it should be possible to provide multiple variants
+ // of function summary for common cases (eg. ssize_t could be int or long
+ // or long long, so three summary variants would be enough).
+ // Of course, function variants are also useful for C++ overloads.
+ QualType Irrelevant; // A placeholder, whenever we do not care about the type.
+ QualType IntTy = ACtx.IntTy;
+ QualType LongTy = ACtx.LongTy;
+ QualType LongLongTy = ACtx.LongLongTy;
+ QualType SizeTy = ACtx.getSizeType();
+
+ RangeIntTy IntMax = BVF.getMaxValue(IntTy).getLimitedValue();
+ RangeIntTy LongMax = BVF.getMaxValue(LongTy).getLimitedValue();
+ RangeIntTy LongLongMax = BVF.getMaxValue(LongLongTy).getLimitedValue();
+
+ // We are finally ready to define specifications for all supported functions.
+ //
+ // The signature needs to have the correct number of arguments.
+ // However, we insert `Irrelevant' when the type is insignificant.
+ //
+ // Argument ranges should always cover all variants. If return value
+ // is completely unknown, omit it from the respective range set.
+ //
+ // All types in the spec need to be canonical.
+ //
+ // Every item in the list of range sets represents a particular
+ // execution path the analyzer would need to explore once
+ // the call is modeled - a new program state is constructed
+ // for every range set, and each range line in the range set
+ // corresponds to a specific constraint within this state.
+ //
+ // Upon comparing to another argument, the other argument is casted
+ // to the current argument's type. This avoids proper promotion but
+ // seems useful. For example, read() receives size_t argument,
+ // and its return value, which is of type ssize_t, cannot be greater
+ // than this argument. If we made a promotion, and the size argument
+ // is equal to, say, 10, then we'd impose a range of [0, 10] on the
+ // return value, however the correct range is [-1, 10].
+ //
+ // Please update the list of functions in the header after editing!
+ //
+ // The format is as follows:
+ //
+ //{ "function name",
+ // { spec:
+ // { argument types list, ... },
+ // return type, purity, { range set list:
+ // { range list:
+ // { argument index, within or out of, {{from, to}, ...} },
+ // { argument index, compares to argument, {{how, which}} },
+ // ...
+ // }
+ // }
+ // }
+ //}
+
+#define SUMMARY_WITH_VARIANTS(identifier) {#identifier, {
+#define END_SUMMARY_WITH_VARIANTS }},
+#define VARIANT(argument_types, return_type, invalidation_approach) \
+ { argument_types, return_type, invalidation_approach, {
+#define END_VARIANT } },
+#define SUMMARY(identifier, argument_types, return_type, \
+ invalidation_approach) \
+ { #identifier, { { argument_types, return_type, invalidation_approach, {
+#define END_SUMMARY } } } },
+#define ARGUMENT_TYPES(...) { __VA_ARGS__ }
+#define RETURN_TYPE(x) x
+#define INVALIDATION_APPROACH(x) x
+#define CASE {
+#define END_CASE },
+#define ARGUMENT_CONDITION(argument_number, condition_kind) \
+ { argument_number, condition_kind, {
+#define END_ARGUMENT_CONDITION }},
+#define RETURN_VALUE_CONDITION(condition_kind) \
+ { Ret, condition_kind, {
+#define END_RETURN_VALUE_CONDITION }},
+#define ARG_NO(x) x##U
+#define RANGE(x, y) { x, y },
+#define SINGLE_VALUE(x) RANGE(x, x)
+#define IS_LESS_THAN(arg) { BO_LE, arg }
+
+ FunctionSummaryMap = {
+ // The isascii() family of functions.
+ SUMMARY(isalnum, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy),
+ INVALIDATION_APPROACH(EvalCallAsPure))
+ CASE // Boils down to isupper() or islower() or isdigit()
+ ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
+ RANGE('0', '9')
+ RANGE('A', 'Z')
+ RANGE('a', 'z')
+ END_ARGUMENT_CONDITION
+ RETURN_VALUE_CONDITION(OutOfRange)
+ SINGLE_VALUE(0)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ CASE // The locale-specific range.
+ ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
+ RANGE(128, 255)
+ END_ARGUMENT_CONDITION
+ // No post-condition. We are completely unaware of
+ // locale-specific return values.
+ END_CASE
+ CASE
+ ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
+ RANGE('0', '9')
+ RANGE('A', 'Z')
+ RANGE('a', 'z')
+ RANGE(128, 255)
+ END_ARGUMENT_CONDITION
+ RETURN_VALUE_CONDITION(WithinRange)
+ SINGLE_VALUE(0)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ END_SUMMARY
+ SUMMARY(isalpha, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy),
+ INVALIDATION_APPROACH(EvalCallAsPure))
+ CASE // isupper() or islower(). Note that 'Z' is less than 'a'.
+ ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
+ RANGE('A', 'Z')
+ RANGE('a', 'z')
+ END_ARGUMENT_CONDITION
+ RETURN_VALUE_CONDITION(OutOfRange)
+ SINGLE_VALUE(0)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ CASE // The locale-specific range.
+ ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
+ RANGE(128, 255)
+ END_ARGUMENT_CONDITION
+ END_CASE
+ CASE // Other.
+ ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
+ RANGE('A', 'Z')
+ RANGE('a', 'z')
+ RANGE(128, 255)
+ END_ARGUMENT_CONDITION
+ RETURN_VALUE_CONDITION(WithinRange)
+ SINGLE_VALUE(0)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ END_SUMMARY
+ SUMMARY(isascii, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy),
+ INVALIDATION_APPROACH(EvalCallAsPure))
+ CASE // Is ASCII.
+ ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
+ RANGE(0, 127)
+ END_ARGUMENT_CONDITION
+ RETURN_VALUE_CONDITION(OutOfRange)
+ SINGLE_VALUE(0)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ CASE
+ ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
+ RANGE(0, 127)
+ END_ARGUMENT_CONDITION
+ RETURN_VALUE_CONDITION(WithinRange)
+ SINGLE_VALUE(0)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ END_SUMMARY
+ SUMMARY(isblank, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy),
+ INVALIDATION_APPROACH(EvalCallAsPure))
+ CASE
+ ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
+ SINGLE_VALUE('\t')
+ SINGLE_VALUE(' ')
+ END_ARGUMENT_CONDITION
+ RETURN_VALUE_CONDITION(OutOfRange)
+ SINGLE_VALUE(0)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ CASE
+ ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
+ SINGLE_VALUE('\t')
+ SINGLE_VALUE(' ')
+ END_ARGUMENT_CONDITION
+ RETURN_VALUE_CONDITION(WithinRange)
+ SINGLE_VALUE(0)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ END_SUMMARY
+ SUMMARY(iscntrl, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy),
+ INVALIDATION_APPROACH(EvalCallAsPure))
+ CASE // 0..31 or 127
+ ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
+ RANGE(0, 32)
+ SINGLE_VALUE(127)
+ END_ARGUMENT_CONDITION
+ RETURN_VALUE_CONDITION(OutOfRange)
+ SINGLE_VALUE(0)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ CASE
+ ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
+ RANGE(0, 32)
+ SINGLE_VALUE(127)
+ END_ARGUMENT_CONDITION
+ RETURN_VALUE_CONDITION(WithinRange)
+ SINGLE_VALUE(0)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ END_SUMMARY
+ SUMMARY(isdigit, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy),
+ INVALIDATION_APPROACH(EvalCallAsPure))
+ CASE // Is a digit.
+ ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
+ RANGE('0', '9')
+ END_ARGUMENT_CONDITION
+ RETURN_VALUE_CONDITION(OutOfRange)
+ SINGLE_VALUE(0)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ CASE
+ ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
+ RANGE('0', '9')
+ END_ARGUMENT_CONDITION
+ RETURN_VALUE_CONDITION(WithinRange)
+ SINGLE_VALUE(0)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ END_SUMMARY
+ SUMMARY(isgraph, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy),
+ INVALIDATION_APPROACH(EvalCallAsPure))
+ CASE
+ ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
+ RANGE(33, 126)
+ END_ARGUMENT_CONDITION
+ RETURN_VALUE_CONDITION(OutOfRange)
+ SINGLE_VALUE(0)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ CASE
+ ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
+ RANGE(33, 126)
+ END_ARGUMENT_CONDITION
+ RETURN_VALUE_CONDITION(WithinRange)
+ SINGLE_VALUE(0)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ END_SUMMARY
+ SUMMARY(islower, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy),
+ INVALIDATION_APPROACH(EvalCallAsPure))
+ CASE // Is certainly lowercase.
+ ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
+ RANGE('a', 'z')
+ END_ARGUMENT_CONDITION
+ RETURN_VALUE_CONDITION(OutOfRange)
+ SINGLE_VALUE(0)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ CASE // Is ascii but not lowercase.
+ ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
+ RANGE(0, 127)
+ END_ARGUMENT_CONDITION
+ ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
+ RANGE('a', 'z')
+ END_ARGUMENT_CONDITION
+ RETURN_VALUE_CONDITION(WithinRange)
+ SINGLE_VALUE(0)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ CASE // The locale-specific range.
+ ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
+ RANGE(128, 255)
+ END_ARGUMENT_CONDITION
+ END_CASE
+ CASE // Is not an unsigned char.
+ ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
+ RANGE(0, 255)
+ END_ARGUMENT_CONDITION
+ RETURN_VALUE_CONDITION(WithinRange)
+ SINGLE_VALUE(0)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ END_SUMMARY
+ SUMMARY(isprint, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy),
+ INVALIDATION_APPROACH(EvalCallAsPure))
+ CASE
+ ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
+ RANGE(32, 126)
+ END_ARGUMENT_CONDITION
+ RETURN_VALUE_CONDITION(OutOfRange)
+ SINGLE_VALUE(0)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ CASE
+ ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
+ RANGE(32, 126)
+ END_ARGUMENT_CONDITION
+ RETURN_VALUE_CONDITION(WithinRange)
+ SINGLE_VALUE(0)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ END_SUMMARY
+ SUMMARY(ispunct, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy),
+ INVALIDATION_APPROACH(EvalCallAsPure))
+ CASE
+ ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
+ RANGE('!', '/')
+ RANGE(':', '@')
+ RANGE('[', '`')
+ RANGE('{', '~')
+ END_ARGUMENT_CONDITION
+ RETURN_VALUE_CONDITION(OutOfRange)
+ SINGLE_VALUE(0)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ CASE
+ ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
+ RANGE('!', '/')
+ RANGE(':', '@')
+ RANGE('[', '`')
+ RANGE('{', '~')
+ END_ARGUMENT_CONDITION
+ RETURN_VALUE_CONDITION(WithinRange)
+ SINGLE_VALUE(0)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ END_SUMMARY
+ SUMMARY(isspace, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy),
+ INVALIDATION_APPROACH(EvalCallAsPure))
+ CASE // Space, '\f', '\n', '\r', '\t', '\v'.
+ ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
+ RANGE(9, 13)
+ SINGLE_VALUE(' ')
+ END_ARGUMENT_CONDITION
+ RETURN_VALUE_CONDITION(OutOfRange)
+ SINGLE_VALUE(0)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ CASE // The locale-specific range.
+ ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
+ RANGE(128, 255)
+ END_ARGUMENT_CONDITION
+ END_CASE
+ CASE
+ ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
+ RANGE(9, 13)
+ SINGLE_VALUE(' ')
+ RANGE(128, 255)
+ END_ARGUMENT_CONDITION
+ RETURN_VALUE_CONDITION(WithinRange)
+ SINGLE_VALUE(0)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ END_SUMMARY
+ SUMMARY(isupper, ARGUMENT_TYPES(IntTy), RETURN_TYPE (IntTy),
+ INVALIDATION_APPROACH(EvalCallAsPure))
+ CASE // Is certainly uppercase.
+ ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
+ RANGE('A', 'Z')
+ END_ARGUMENT_CONDITION
+ RETURN_VALUE_CONDITION(OutOfRange)
+ SINGLE_VALUE(0)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ CASE // The locale-specific range.
+ ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
+ RANGE(128, 255)
+ END_ARGUMENT_CONDITION
+ END_CASE
+ CASE // Other.
+ ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
+ RANGE('A', 'Z') RANGE(128, 255)
+ END_ARGUMENT_CONDITION
+ RETURN_VALUE_CONDITION(WithinRange)
+ SINGLE_VALUE(0)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ END_SUMMARY
+ SUMMARY(isxdigit, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy),
+ INVALIDATION_APPROACH(EvalCallAsPure))
+ CASE
+ ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
+ RANGE('0', '9')
+ RANGE('A', 'F')
+ RANGE('a', 'f')
+ END_ARGUMENT_CONDITION
+ RETURN_VALUE_CONDITION(OutOfRange)
+ SINGLE_VALUE(0)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ CASE
+ ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
+ RANGE('0', '9')
+ RANGE('A', 'F')
+ RANGE('a', 'f')
+ END_ARGUMENT_CONDITION
+ RETURN_VALUE_CONDITION(WithinRange)
+ SINGLE_VALUE(0)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ END_SUMMARY
+
+ // The getc() family of functions that returns either a char or an EOF.
+ SUMMARY(getc, ARGUMENT_TYPES(Irrelevant), RETURN_TYPE(IntTy),
+ INVALIDATION_APPROACH(NoEvalCall))
+ CASE // FIXME: EOF is assumed to be defined as -1.
+ RETURN_VALUE_CONDITION(WithinRange)
+ RANGE(-1, 255)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ END_SUMMARY
+ SUMMARY(fgetc, ARGUMENT_TYPES(Irrelevant), RETURN_TYPE(IntTy),
+ INVALIDATION_APPROACH(NoEvalCall))
+ CASE // FIXME: EOF is assumed to be defined as -1.
+ RETURN_VALUE_CONDITION(WithinRange)
+ RANGE(-1, 255)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ END_SUMMARY
+ SUMMARY(getchar, ARGUMENT_TYPES(), RETURN_TYPE(IntTy),
+ INVALIDATION_APPROACH(NoEvalCall))
+ CASE // FIXME: EOF is assumed to be defined as -1.
+ RETURN_VALUE_CONDITION(WithinRange)
+ RANGE(-1, 255)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ END_SUMMARY
+
+ // read()-like functions that never return more than buffer size.
+ // We are not sure how ssize_t is defined on every platform, so we provide
+ // three variants that should cover common cases.
+ SUMMARY_WITH_VARIANTS(read)
+ VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy),
+ RETURN_TYPE(IntTy), INVALIDATION_APPROACH(NoEvalCall))
+ CASE
+ RETURN_VALUE_CONDITION(ComparesToArgument)
+ IS_LESS_THAN(ARG_NO(2))
+ END_RETURN_VALUE_CONDITION
+ RETURN_VALUE_CONDITION(WithinRange)
+ RANGE(-1, IntMax)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ END_VARIANT
+ VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy),
+ RETURN_TYPE(LongTy), INVALIDATION_APPROACH(NoEvalCall))
+ CASE
+ RETURN_VALUE_CONDITION(ComparesToArgument)
+ IS_LESS_THAN(ARG_NO(2))
+ END_RETURN_VALUE_CONDITION
+ RETURN_VALUE_CONDITION(WithinRange)
+ RANGE(-1, LongMax)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ END_VARIANT
+ VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy),
+ RETURN_TYPE(LongLongTy), INVALIDATION_APPROACH(NoEvalCall))
+ CASE
+ RETURN_VALUE_CONDITION(ComparesToArgument)
+ IS_LESS_THAN(ARG_NO(2))
+ END_RETURN_VALUE_CONDITION
+ RETURN_VALUE_CONDITION(WithinRange)
+ RANGE(-1, LongLongMax)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ END_VARIANT
+ END_SUMMARY_WITH_VARIANTS
+ SUMMARY_WITH_VARIANTS(write)
+ // Again, due to elusive nature of ssize_t, we have duplicate
+ // our summaries to cover different variants.
+ VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy),
+ RETURN_TYPE(IntTy), INVALIDATION_APPROACH(NoEvalCall))
+ CASE
+ RETURN_VALUE_CONDITION(ComparesToArgument)
+ IS_LESS_THAN(ARG_NO(2))
+ END_RETURN_VALUE_CONDITION
+ RETURN_VALUE_CONDITION(WithinRange)
+ RANGE(-1, IntMax)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ END_VARIANT
+ VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy),
+ RETURN_TYPE(LongTy), INVALIDATION_APPROACH(NoEvalCall))
+ CASE
+ RETURN_VALUE_CONDITION(ComparesToArgument)
+ IS_LESS_THAN(ARG_NO(2))
+ END_RETURN_VALUE_CONDITION
+ RETURN_VALUE_CONDITION(WithinRange)
+ RANGE(-1, LongMax)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ END_VARIANT
+ VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy),
+ RETURN_TYPE(LongLongTy), INVALIDATION_APPROACH(NoEvalCall))
+ CASE
+ RETURN_VALUE_CONDITION(ComparesToArgument)
+ IS_LESS_THAN(ARG_NO(2))
+ END_RETURN_VALUE_CONDITION
+ RETURN_VALUE_CONDITION(WithinRange)
+ RANGE(-1, LongLongMax)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ END_VARIANT
+ END_SUMMARY_WITH_VARIANTS
+ SUMMARY(fread,
+ ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy, Irrelevant),
+ RETURN_TYPE(SizeTy), INVALIDATION_APPROACH(NoEvalCall))
+ CASE
+ RETURN_VALUE_CONDITION(ComparesToArgument)
+ IS_LESS_THAN(ARG_NO(2))
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ END_SUMMARY
+ SUMMARY(fwrite,
+ ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy, Irrelevant),
+ RETURN_TYPE(SizeTy), INVALIDATION_APPROACH(NoEvalCall))
+ CASE
+ RETURN_VALUE_CONDITION(ComparesToArgument)
+ IS_LESS_THAN(ARG_NO(2))
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ END_SUMMARY
+
+ // getline()-like functions either fail or read at least the delimiter.
+ SUMMARY_WITH_VARIANTS(getline)
+ VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, Irrelevant),
+ RETURN_TYPE(IntTy), INVALIDATION_APPROACH(NoEvalCall))
+ CASE
+ RETURN_VALUE_CONDITION(WithinRange)
+ SINGLE_VALUE(-1)
+ RANGE(1, IntMax)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ END_VARIANT
+ VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, Irrelevant),
+ RETURN_TYPE(LongTy), INVALIDATION_APPROACH(NoEvalCall))
+ CASE
+ RETURN_VALUE_CONDITION(WithinRange)
+ SINGLE_VALUE(-1)
+ RANGE(1, LongMax)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ END_VARIANT
+ VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, Irrelevant),
+ RETURN_TYPE(LongLongTy), INVALIDATION_APPROACH(NoEvalCall))
+ CASE
+ RETURN_VALUE_CONDITION(WithinRange)
+ SINGLE_VALUE(-1)
+ RANGE(1, LongLongMax)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ END_VARIANT
+ END_SUMMARY_WITH_VARIANTS
+ SUMMARY_WITH_VARIANTS(getdelim)
+ VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, Irrelevant, Irrelevant),
+ RETURN_TYPE(IntTy), INVALIDATION_APPROACH(NoEvalCall))
+ CASE
+ RETURN_VALUE_CONDITION(WithinRange)
+ SINGLE_VALUE(-1)
+ RANGE(1, IntMax)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ END_VARIANT
+ VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, Irrelevant, Irrelevant),
+ RETURN_TYPE(LongTy), INVALIDATION_APPROACH(NoEvalCall))
+ CASE
+ RETURN_VALUE_CONDITION(WithinRange)
+ SINGLE_VALUE(-1)
+ RANGE(1, LongMax)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ END_VARIANT
+ VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, Irrelevant, Irrelevant),
+ RETURN_TYPE(LongLongTy), INVALIDATION_APPROACH(NoEvalCall))
+ CASE
+ RETURN_VALUE_CONDITION(WithinRange)
+ SINGLE_VALUE(-1)
+ RANGE(1, LongLongMax)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ END_VARIANT
+ END_SUMMARY_WITH_VARIANTS
+ };
+}
+
+void ento::registerStdCLibraryFunctionsChecker(CheckerManager &mgr) {
+ // If this checker grows large enough to support C++, Objective-C, or other
+ // standard libraries, we could use multiple register...Checker() functions,
+ // which would register various checkers with the help of the same Checker
+ // class, turning on different function summaries.
+ mgr.registerChecker<StdLibraryFunctionsChecker>();
+}
diff --git a/lib/StaticAnalyzer/Checkers/StreamChecker.cpp b/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
index 82b01fe814da..915514b42133 100644
--- a/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
@@ -19,7 +19,6 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
-#include "llvm/ADT/ImmutableMap.h"
using namespace clang;
using namespace ento;
diff --git a/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp b/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
index 4b78c2058341..26bf597bd950 100644
--- a/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
@@ -21,6 +21,7 @@
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/raw_ostream.h"
#include <fcntl.h>
@@ -28,6 +29,16 @@
using namespace clang;
using namespace ento;
+enum class OpenVariant {
+ /// The standard open() call:
+ /// int open(const char *path, int oflag, ...);
+ Open,
+
+ /// The variant taking a directory file descriptor and a relative path:
+ /// int openat(int fd, const char *path, int oflag, ...);
+ OpenAt
+};
+
namespace {
class UnixAPIChecker : public Checker< check::PreStmt<CallExpr> > {
mutable std::unique_ptr<BugType> BT_open, BT_pthreadOnce, BT_mallocZero;
@@ -37,17 +48,24 @@ public:
void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
void CheckOpen(CheckerContext &C, const CallExpr *CE) const;
+ void CheckOpenAt(CheckerContext &C, const CallExpr *CE) const;
+
void CheckPthreadOnce(CheckerContext &C, const CallExpr *CE) const;
void CheckCallocZero(CheckerContext &C, const CallExpr *CE) const;
void CheckMallocZero(CheckerContext &C, const CallExpr *CE) const;
void CheckReallocZero(CheckerContext &C, const CallExpr *CE) const;
void CheckReallocfZero(CheckerContext &C, const CallExpr *CE) const;
void CheckAllocaZero(CheckerContext &C, const CallExpr *CE) const;
+ void CheckAllocaWithAlignZero(CheckerContext &C, const CallExpr *CE) const;
void CheckVallocZero(CheckerContext &C, const CallExpr *CE) const;
typedef void (UnixAPIChecker::*SubChecker)(CheckerContext &,
const CallExpr *) const;
private:
+
+ void CheckOpenVariant(CheckerContext &C,
+ const CallExpr *CE, OpenVariant Variant) const;
+
bool ReportZeroByteAllocation(CheckerContext &C,
ProgramStateRef falseState,
const Expr *arg,
@@ -89,25 +107,71 @@ void UnixAPIChecker::ReportOpenBug(CheckerContext &C,
}
void UnixAPIChecker::CheckOpen(CheckerContext &C, const CallExpr *CE) const {
+ CheckOpenVariant(C, CE, OpenVariant::Open);
+}
+
+void UnixAPIChecker::CheckOpenAt(CheckerContext &C, const CallExpr *CE) const {
+ CheckOpenVariant(C, CE, OpenVariant::OpenAt);
+}
+
+void UnixAPIChecker::CheckOpenVariant(CheckerContext &C,
+ const CallExpr *CE,
+ OpenVariant Variant) const {
+ // The index of the argument taking the flags open flags (O_RDONLY,
+ // O_WRONLY, O_CREAT, etc.),
+ unsigned int FlagsArgIndex;
+ const char *VariantName;
+ switch (Variant) {
+ case OpenVariant::Open:
+ FlagsArgIndex = 1;
+ VariantName = "open";
+ break;
+ case OpenVariant::OpenAt:
+ FlagsArgIndex = 2;
+ VariantName = "openat";
+ break;
+ };
+
+ // All calls should at least provide arguments up to the 'flags' parameter.
+ unsigned int MinArgCount = FlagsArgIndex + 1;
+
+ // If the flags has O_CREAT set then open/openat() require an additional
+ // argument specifying the file mode (permission bits) for the created file.
+ unsigned int CreateModeArgIndex = FlagsArgIndex + 1;
+
+ // The create mode argument should be the last argument.
+ unsigned int MaxArgCount = CreateModeArgIndex + 1;
+
ProgramStateRef state = C.getState();
- if (CE->getNumArgs() < 2) {
+ if (CE->getNumArgs() < MinArgCount) {
// The frontend should issue a warning for this case, so this is a sanity
// check.
return;
- } else if (CE->getNumArgs() == 3) {
- const Expr *Arg = CE->getArg(2);
+ } else if (CE->getNumArgs() == MaxArgCount) {
+ const Expr *Arg = CE->getArg(CreateModeArgIndex);
QualType QT = Arg->getType();
if (!QT->isIntegerType()) {
+ SmallString<256> SBuf;
+ llvm::raw_svector_ostream OS(SBuf);
+ OS << "The " << CreateModeArgIndex + 1
+ << llvm::getOrdinalSuffix(CreateModeArgIndex + 1)
+ << " argument to '" << VariantName << "' is not an integer";
+
ReportOpenBug(C, state,
- "Third argument to 'open' is not an integer",
+ SBuf.c_str(),
Arg->getSourceRange());
return;
}
- } else if (CE->getNumArgs() > 3) {
+ } else if (CE->getNumArgs() > MaxArgCount) {
+ SmallString<256> SBuf;
+ llvm::raw_svector_ostream OS(SBuf);
+ OS << "Call to '" << VariantName << "' with more than " << MaxArgCount
+ << " arguments";
+
ReportOpenBug(C, state,
- "Call to 'open' with more than three arguments",
- CE->getArg(3)->getSourceRange());
+ SBuf.c_str(),
+ CE->getArg(MaxArgCount)->getSourceRange());
return;
}
@@ -127,7 +191,7 @@ void UnixAPIChecker::CheckOpen(CheckerContext &C, const CallExpr *CE) const {
}
// Now check if oflags has O_CREAT set.
- const Expr *oflagsEx = CE->getArg(1);
+ const Expr *oflagsEx = CE->getArg(FlagsArgIndex);
const SVal V = state->getSVal(oflagsEx, C.getLocationContext());
if (!V.getAs<NonLoc>()) {
// The case where 'V' can be a location can only be due to a bad header,
@@ -153,10 +217,15 @@ void UnixAPIChecker::CheckOpen(CheckerContext &C, const CallExpr *CE) const {
if (!(trueState && !falseState))
return;
- if (CE->getNumArgs() < 3) {
+ if (CE->getNumArgs() < MaxArgCount) {
+ SmallString<256> SBuf;
+ llvm::raw_svector_ostream OS(SBuf);
+ OS << "Call to '" << VariantName << "' requires a "
+ << CreateModeArgIndex + 1
+ << llvm::getOrdinalSuffix(CreateModeArgIndex + 1)
+ << " argument when the 'O_CREAT' flag is set";
ReportOpenBug(C, trueState,
- "Call to 'open' requires a third argument when "
- "the 'O_CREAT' flag is set",
+ SBuf.c_str(),
oflagsEx->getSourceRange());
}
}
@@ -337,6 +406,11 @@ void UnixAPIChecker::CheckAllocaZero(CheckerContext &C,
BasicAllocationCheck(C, CE, 1, 0, "alloca");
}
+void UnixAPIChecker::CheckAllocaWithAlignZero(CheckerContext &C,
+ const CallExpr *CE) const {
+ BasicAllocationCheck(C, CE, 2, 0, "__builtin_alloca_with_align");
+}
+
void UnixAPIChecker::CheckVallocZero(CheckerContext &C,
const CallExpr *CE) const {
BasicAllocationCheck(C, CE, 1, 0, "valloc");
@@ -353,6 +427,12 @@ void UnixAPIChecker::checkPreStmt(const CallExpr *CE,
if (!FD || FD->getKind() != Decl::Function)
return;
+ // Don't treat functions in namespaces with the same name a Unix function
+ // as a call to the Unix function.
+ const DeclContext *NamespaceCtx = FD->getEnclosingNamespaceContext();
+ if (NamespaceCtx && isa<NamespaceDecl>(NamespaceCtx))
+ return;
+
StringRef FName = C.getCalleeName(FD);
if (FName.empty())
return;
@@ -360,12 +440,15 @@ void UnixAPIChecker::checkPreStmt(const CallExpr *CE,
SubChecker SC =
llvm::StringSwitch<SubChecker>(FName)
.Case("open", &UnixAPIChecker::CheckOpen)
+ .Case("openat", &UnixAPIChecker::CheckOpenAt)
.Case("pthread_once", &UnixAPIChecker::CheckPthreadOnce)
.Case("calloc", &UnixAPIChecker::CheckCallocZero)
.Case("malloc", &UnixAPIChecker::CheckMallocZero)
.Case("realloc", &UnixAPIChecker::CheckReallocZero)
.Case("reallocf", &UnixAPIChecker::CheckReallocfZero)
.Cases("alloca", "__builtin_alloca", &UnixAPIChecker::CheckAllocaZero)
+ .Case("__builtin_alloca_with_align",
+ &UnixAPIChecker::CheckAllocaWithAlignZero)
.Case("valloc", &UnixAPIChecker::CheckVallocZero)
.Default(nullptr);
diff --git a/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp b/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp
index 892e713d241f..ccd8e9a18b00 100644
--- a/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp
@@ -147,6 +147,14 @@ void UnreachableCodeChecker::checkEndAnalysis(ExplodedGraph &G,
PathDiagnosticLocation DL;
SourceLocation SL;
if (const Stmt *S = getUnreachableStmt(CB)) {
+ // In macros, 'do {...} while (0)' is often used. Don't warn about the
+ // condition 0 when it is unreachable.
+ if (S->getLocStart().isMacroID())
+ if (const auto *I = dyn_cast<IntegerLiteral>(S))
+ if (I->getValue() == 0ULL)
+ if (const Stmt *Parent = PM->getParent(S))
+ if (isa<DoStmt>(Parent))
+ continue;
SR = S->getSourceRange();
DL = PathDiagnosticLocation::createBegin(S, B.getSourceManager(), LC);
SL = DL.asLocation();
@@ -191,8 +199,10 @@ void UnreachableCodeChecker::FindUnreachableEntryPoints(const CFGBlock *CB,
// Find the Stmt* in a CFGBlock for reporting a warning
const Stmt *UnreachableCodeChecker::getUnreachableStmt(const CFGBlock *CB) {
for (CFGBlock::const_iterator I = CB->begin(), E = CB->end(); I != E; ++I) {
- if (Optional<CFGStmt> S = I->getAs<CFGStmt>())
- return S->getStmt();
+ if (Optional<CFGStmt> S = I->getAs<CFGStmt>()) {
+ if (!isa<DeclStmt>(S->getStmt()))
+ return S->getStmt();
+ }
}
if (const Stmt *S = CB->getTerminator())
return S;
diff --git a/lib/StaticAnalyzer/Checkers/ValistChecker.cpp b/lib/StaticAnalyzer/Checkers/ValistChecker.cpp
new file mode 100644
index 000000000000..b4bfa0c03341
--- /dev/null
+++ b/lib/StaticAnalyzer/Checkers/ValistChecker.cpp
@@ -0,0 +1,373 @@
+//== ValistChecker.cpp - stdarg.h macro usage checker -----------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines checkers which detect usage of uninitialized va_list values
+// and va_start calls with no matching va_end.
+//
+//===----------------------------------------------------------------------===//
+
+#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;
+
+REGISTER_SET_WITH_PROGRAMSTATE(InitializedVALists, const MemRegion *)
+
+namespace {
+typedef SmallVector<const MemRegion *, 2> RegionVector;
+
+class ValistChecker : public Checker<check::PreCall, check::PreStmt<VAArgExpr>,
+ check::DeadSymbols> {
+ mutable std::unique_ptr<BugType> BT_leakedvalist, BT_uninitaccess;
+
+ struct VAListAccepter {
+ CallDescription Func;
+ int VAListPos;
+ };
+ static const SmallVector<VAListAccepter, 15> VAListAccepters;
+ static const CallDescription VaStart, VaEnd, VaCopy;
+
+public:
+ enum CheckKind {
+ CK_Uninitialized,
+ CK_Unterminated,
+ CK_CopyToSelf,
+ CK_NumCheckKinds
+ };
+
+ DefaultBool ChecksEnabled[CK_NumCheckKinds];
+ CheckName CheckNames[CK_NumCheckKinds];
+
+ void checkPreStmt(const VAArgExpr *VAA, CheckerContext &C) const;
+ void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
+ void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const;
+
+private:
+ const MemRegion *getVAListAsRegion(SVal SV, CheckerContext &C) const;
+ StringRef getVariableNameFromRegion(const MemRegion *Reg) const;
+ const ExplodedNode *getStartCallSite(const ExplodedNode *N,
+ const MemRegion *Reg,
+ CheckerContext &C) const;
+
+ void reportUninitializedAccess(const MemRegion *VAList, StringRef Msg,
+ CheckerContext &C) const;
+ void reportLeakedVALists(const RegionVector &LeakedVALists, StringRef Msg1,
+ StringRef Msg2, CheckerContext &C, ExplodedNode *N,
+ bool ForceReport = 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> {
+ public:
+ ValistBugVisitor(const MemRegion *Reg, bool IsLeak = false)
+ : Reg(Reg), IsLeak(IsLeak) {}
+ void Profile(llvm::FoldingSetNodeID &ID) const override {
+ static int X = 0;
+ ID.AddPointer(&X);
+ ID.AddPointer(Reg);
+ }
+ std::unique_ptr<PathDiagnosticPiece>
+ getEndPath(BugReporterContext &BRC, const ExplodedNode *EndPathNode,
+ BugReport &BR) override {
+ if (!IsLeak)
+ return nullptr;
+
+ 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);
+ }
+ PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
+ const ExplodedNode *PrevN,
+ BugReporterContext &BRC,
+ BugReport &BR) override;
+
+ private:
+ const MemRegion *Reg;
+ bool IsLeak;
+ };
+};
+
+const SmallVector<ValistChecker::VAListAccepter, 15>
+ ValistChecker::VAListAccepters = {
+ {{"vfprintf", 3}, 2},
+ {{"vfscanf", 3}, 2},
+ {{"vprintf", 2}, 1},
+ {{"vscanf", 2}, 1},
+ {{"vsnprintf", 4}, 3},
+ {{"vsprintf", 3}, 2},
+ {{"vsscanf", 3}, 2},
+ {{"vfwprintf", 3}, 2},
+ {{"vfwscanf", 3}, 2},
+ {{"vwprintf", 2}, 1},
+ {{"vwscanf", 2}, 1},
+ {{"vswprintf", 4}, 3},
+ // vswprintf is the wide version of vsnprintf,
+ // vsprintf has no wide version
+ {{"vswscanf", 3}, 2}};
+const CallDescription ValistChecker::VaStart("__builtin_va_start", 2),
+ ValistChecker::VaCopy("__builtin_va_copy", 2),
+ ValistChecker::VaEnd("__builtin_va_end", 1);
+} // end anonymous namespace
+
+void ValistChecker::checkPreCall(const CallEvent &Call,
+ CheckerContext &C) const {
+ if (!Call.isGlobalCFunction())
+ return;
+ if (Call.isCalled(VaStart))
+ checkVAListStartCall(Call, C, false);
+ else if (Call.isCalled(VaCopy))
+ checkVAListStartCall(Call, C, true);
+ else if (Call.isCalled(VaEnd))
+ checkVAListEndCall(Call, C);
+ else {
+ for (auto FuncInfo : VAListAccepters) {
+ if (!Call.isCalled(FuncInfo.Func))
+ continue;
+ const MemRegion *VAList =
+ getVAListAsRegion(Call.getArgSVal(FuncInfo.VAListPos), C);
+ if (!VAList)
+ return;
+
+ if (C.getState()->contains<InitializedVALists>(VAList))
+ return;
+
+ SmallString<80> Errmsg("Function '");
+ Errmsg += FuncInfo.Func.getFunctionName();
+ Errmsg += "' is called with an uninitialized va_list argument";
+ reportUninitializedAccess(VAList, Errmsg.c_str(), C);
+ break;
+ }
+ }
+}
+
+void ValistChecker::checkPreStmt(const VAArgExpr *VAA,
+ CheckerContext &C) const {
+ ProgramStateRef State = C.getState();
+ SVal VAListSVal = State->getSVal(VAA->getSubExpr(), C.getLocationContext());
+ const MemRegion *VAList = getVAListAsRegion(VAListSVal, C);
+ if (!VAList)
+ return;
+ if (!State->contains<InitializedVALists>(VAList))
+ reportUninitializedAccess(
+ VAList, "va_arg() is called on an uninitialized va_list", C);
+}
+
+void ValistChecker::checkDeadSymbols(SymbolReaper &SR,
+ CheckerContext &C) const {
+ ProgramStateRef State = C.getState();
+ InitializedVAListsTy TrackedVALists = State->get<InitializedVALists>();
+ RegionVector LeakedVALists;
+ for (auto Reg : TrackedVALists) {
+ if (SR.isLiveRegion(Reg))
+ continue;
+ LeakedVALists.push_back(Reg);
+ State = State->remove<InitializedVALists>(Reg);
+ }
+ if (ExplodedNode *N = C.addTransition(State))
+ reportLeakedVALists(LeakedVALists, "Initialized va_list", " is leaked", C,
+ N);
+}
+
+const MemRegion *ValistChecker::getVAListAsRegion(SVal SV,
+ CheckerContext &C) const {
+ const MemRegion *Reg = SV.getAsRegion();
+ const auto *TReg = dyn_cast_or_null<TypedValueRegion>(Reg);
+ // Some VarRegion based VLAs reach here as ElementRegions.
+ const auto *EReg = dyn_cast_or_null<ElementRegion>(TReg);
+ return EReg ? EReg->getSuperRegion() : TReg;
+}
+
+// This function traverses the exploded graph backwards and finds the node where
+// the va_list is initialized. That node is used for uniquing the bug paths.
+// It is not likely that there are several different va_lists that belongs to
+// different stack frames, so that case is not yet handled.
+const ExplodedNode *ValistChecker::getStartCallSite(const ExplodedNode *N,
+ const MemRegion *Reg,
+ CheckerContext &C) const {
+ const LocationContext *LeakContext = N->getLocationContext();
+ const ExplodedNode *StartCallNode = N;
+
+ bool FoundInitializedState = false;
+
+ while (N) {
+ ProgramStateRef State = N->getState();
+ if (!State->contains<InitializedVALists>(Reg)) {
+ if (FoundInitializedState)
+ break;
+ } else {
+ FoundInitializedState = true;
+ }
+ const LocationContext *NContext = N->getLocationContext();
+ if (NContext == LeakContext || NContext->isParentOf(LeakContext))
+ StartCallNode = N;
+ N = N->pred_empty() ? nullptr : *(N->pred_begin());
+ }
+
+ return StartCallNode;
+}
+
+void ValistChecker::reportUninitializedAccess(const MemRegion *VAList,
+ StringRef Msg,
+ CheckerContext &C) const {
+ if (!ChecksEnabled[CK_Uninitialized])
+ return;
+ if (ExplodedNode *N = C.generateErrorNode()) {
+ if (!BT_uninitaccess)
+ BT_uninitaccess.reset(new BugType(CheckNames[CK_Uninitialized],
+ "Uninitialized va_list",
+ "Memory Error"));
+ auto R = llvm::make_unique<BugReport>(*BT_uninitaccess, Msg, N);
+ R->markInteresting(VAList);
+ R->addVisitor(llvm::make_unique<ValistBugVisitor>(VAList));
+ C.emitReport(std::move(R));
+ }
+}
+
+void ValistChecker::reportLeakedVALists(const RegionVector &LeakedVALists,
+ StringRef Msg1, StringRef Msg2,
+ CheckerContext &C, ExplodedNode *N,
+ bool ForceReport) const {
+ if (!(ChecksEnabled[CK_Unterminated] ||
+ (ChecksEnabled[CK_Uninitialized] && ForceReport)))
+ return;
+ for (auto Reg : LeakedVALists) {
+ if (!BT_leakedvalist) {
+ BT_leakedvalist.reset(new BugType(CheckNames[CK_Unterminated],
+ "Leaked va_list", "Memory Error"));
+ BT_leakedvalist->setSuppressOnSink(true);
+ }
+
+ const ExplodedNode *StartNode = getStartCallSite(N, Reg, C);
+ PathDiagnosticLocation LocUsedForUniqueing;
+
+ if (const Stmt *StartCallStmt = PathDiagnosticLocation::getStmt(StartNode))
+ LocUsedForUniqueing = PathDiagnosticLocation::createBegin(
+ StartCallStmt, C.getSourceManager(), StartNode->getLocationContext());
+
+ SmallString<100> Buf;
+ llvm::raw_svector_ostream OS(Buf);
+ OS << Msg1;
+ std::string VariableName = Reg->getDescriptiveName();
+ if (!VariableName.empty())
+ OS << " " << VariableName;
+ OS << Msg2;
+
+ auto R = llvm::make_unique<BugReport>(
+ *BT_leakedvalist, OS.str(), N, LocUsedForUniqueing,
+ StartNode->getLocationContext()->getDecl());
+ R->markInteresting(Reg);
+ R->addVisitor(llvm::make_unique<ValistBugVisitor>(Reg, true));
+ C.emitReport(std::move(R));
+ }
+}
+
+void ValistChecker::checkVAListStartCall(const CallEvent &Call,
+ CheckerContext &C, bool IsCopy) const {
+ const MemRegion *VAList = getVAListAsRegion(Call.getArgSVal(0), C);
+ ProgramStateRef State = C.getState();
+ if (!VAList)
+ return;
+
+ if (IsCopy) {
+ const MemRegion *Arg2 = getVAListAsRegion(Call.getArgSVal(1), C);
+ if (Arg2) {
+ if (ChecksEnabled[CK_CopyToSelf] && VAList == Arg2) {
+ RegionVector LeakedVALists{VAList};
+ if (ExplodedNode *N = C.addTransition(State))
+ reportLeakedVALists(LeakedVALists, "va_list",
+ " is copied onto itself", C, N, true);
+ return;
+ } else if (!State->contains<InitializedVALists>(Arg2)) {
+ if (State->contains<InitializedVALists>(VAList)) {
+ State = State->remove<InitializedVALists>(VAList);
+ RegionVector LeakedVALists{VAList};
+ if (ExplodedNode *N = C.addTransition(State))
+ reportLeakedVALists(LeakedVALists, "Initialized va_list",
+ " is overwritten by an uninitialized one", C, N,
+ true);
+ } else {
+ reportUninitializedAccess(Arg2, "Uninitialized va_list is copied", C);
+ }
+ return;
+ }
+ }
+ }
+ if (State->contains<InitializedVALists>(VAList)) {
+ RegionVector LeakedVALists{VAList};
+ if (ExplodedNode *N = C.addTransition(State))
+ reportLeakedVALists(LeakedVALists, "Initialized va_list",
+ " is initialized again", C, N);
+ return;
+ }
+
+ State = State->add<InitializedVALists>(VAList);
+ C.addTransition(State);
+}
+
+void ValistChecker::checkVAListEndCall(const CallEvent &Call,
+ CheckerContext &C) const {
+ const MemRegion *VAList = getVAListAsRegion(Call.getArgSVal(0), C);
+ if (!VAList)
+ return;
+
+ if (!C.getState()->contains<InitializedVALists>(VAList)) {
+ reportUninitializedAccess(
+ VAList, "va_end() is called on an uninitialized va_list", C);
+ return;
+ }
+ ProgramStateRef State = C.getState();
+ State = State->remove<InitializedVALists>(VAList);
+ C.addTransition(State);
+}
+
+PathDiagnosticPiece *ValistChecker::ValistBugVisitor::VisitNode(
+ const ExplodedNode *N, const ExplodedNode *PrevN, BugReporterContext &BRC,
+ BugReport &BR) {
+ ProgramStateRef State = N->getState();
+ ProgramStateRef StatePrev = PrevN->getState();
+
+ const Stmt *S = PathDiagnosticLocation::getStmt(N);
+ if (!S)
+ return nullptr;
+
+ StringRef Msg;
+ if (State->contains<InitializedVALists>(Reg) &&
+ !StatePrev->contains<InitializedVALists>(Reg))
+ Msg = "Initialized va_list";
+ else if (!State->contains<InitializedVALists>(Reg) &&
+ StatePrev->contains<InitializedVALists>(Reg))
+ Msg = "Ended va_list";
+
+ if (Msg.empty())
+ return nullptr;
+
+ PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
+ N->getLocationContext());
+ return new PathDiagnosticEventPiece(Pos, Msg, true);
+}
+
+#define REGISTER_CHECKER(name) \
+ void ento::register##name##Checker(CheckerManager &mgr) { \
+ ValistChecker *checker = mgr.registerChecker<ValistChecker>(); \
+ checker->ChecksEnabled[ValistChecker::CK_##name] = true; \
+ checker->CheckNames[ValistChecker::CK_##name] = mgr.getCurrentCheckName(); \
+ }
+
+REGISTER_CHECKER(Uninitialized)
+REGISTER_CHECKER(Unterminated)
+REGISTER_CHECKER(CopyToSelf)
diff --git a/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp b/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp
index 550250302611..15e8ea31c4c4 100644
--- a/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp
@@ -32,6 +32,18 @@ class WalkAST : public StmtVisitor<WalkAST> {
BugReporter &BR;
AnalysisDeclContext *AC;
+ /// The root constructor or destructor whose callees are being analyzed.
+ const CXXMethodDecl *RootMethod = nullptr;
+
+ /// Whether the checker should walk into bodies of called functions.
+ /// Controlled by the "Interprocedural" analyzer-config option.
+ bool IsInterprocedural = false;
+
+ /// Whether the checker should only warn for calls to pure virtual functions
+ /// (which is undefined behavior) or for all virtual functions (which may
+ /// may result in unexpected behavior).
+ bool ReportPureOnly = false;
+
typedef const CallExpr * WorkListUnit;
typedef SmallVector<WorkListUnit, 20> DFSWorkList;
@@ -59,9 +71,16 @@ class WalkAST : public StmtVisitor<WalkAST> {
const CallExpr *visitingCallExpr;
public:
- WalkAST(const CheckerBase *checker, BugReporter &br,
- AnalysisDeclContext *ac)
- : Checker(checker), BR(br), AC(ac), visitingCallExpr(nullptr) {}
+ WalkAST(const CheckerBase *checker, BugReporter &br, AnalysisDeclContext *ac,
+ const CXXMethodDecl *rootMethod, bool isInterprocedural,
+ bool reportPureOnly)
+ : Checker(checker), BR(br), AC(ac), RootMethod(rootMethod),
+ IsInterprocedural(isInterprocedural), ReportPureOnly(reportPureOnly),
+ visitingCallExpr(nullptr) {
+ // Walking should always start from either a constructor or a destructor.
+ assert(isa<CXXConstructorDecl>(rootMethod) ||
+ isa<CXXDestructorDecl>(rootMethod));
+ }
bool hasWork() const { return !WList.empty(); }
@@ -132,7 +151,8 @@ void WalkAST::VisitChildren(Stmt *S) {
void WalkAST::VisitCallExpr(CallExpr *CE) {
VisitChildren(CE);
- Enqueue(CE);
+ if (IsInterprocedural)
+ Enqueue(CE);
}
void WalkAST::VisitCXXMemberCallExpr(CallExpr *CE) {
@@ -164,51 +184,64 @@ void WalkAST::VisitCXXMemberCallExpr(CallExpr *CE) {
!MD->getParent()->hasAttr<FinalAttr>())
ReportVirtualCall(CE, MD->isPure());
- Enqueue(CE);
+ if (IsInterprocedural)
+ Enqueue(CE);
}
void WalkAST::ReportVirtualCall(const CallExpr *CE, bool isPure) {
+ if (ReportPureOnly && !isPure)
+ return;
+
SmallString<100> buf;
llvm::raw_svector_ostream os(buf);
- os << "Call Path : ";
- // Name of current visiting CallExpr.
- os << *CE->getDirectCallee();
-
- // Name of the CallExpr whose body is current walking.
- if (visitingCallExpr)
- os << " <-- " << *visitingCallExpr->getDirectCallee();
- // Names of FunctionDecls in worklist with state PostVisited.
- for (SmallVectorImpl<const CallExpr *>::iterator I = WList.end(),
+ // FIXME: The interprocedural diagnostic experience here is not good.
+ // Ultimately this checker should be re-written to be path sensitive.
+ // For now, only diagnose intraprocedurally, by default.
+ if (IsInterprocedural) {
+ os << "Call Path : ";
+ // Name of current visiting CallExpr.
+ os << *CE->getDirectCallee();
+
+ // Name of the CallExpr whose body is current being walked.
+ if (visitingCallExpr)
+ os << " <-- " << *visitingCallExpr->getDirectCallee();
+ // Names of FunctionDecls in worklist with state PostVisited.
+ for (SmallVectorImpl<const CallExpr *>::iterator I = WList.end(),
E = WList.begin(); I != E; --I) {
- const FunctionDecl *FD = (*(I-1))->getDirectCallee();
- assert(FD);
- if (VisitedFunctions[FD] == PostVisited)
- os << " <-- " << *FD;
+ const FunctionDecl *FD = (*(I-1))->getDirectCallee();
+ assert(FD);
+ if (VisitedFunctions[FD] == PostVisited)
+ os << " <-- " << *FD;
+ }
+
+ os << "\n";
}
PathDiagnosticLocation CELoc =
PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
SourceRange R = CE->getCallee()->getSourceRange();
- if (isPure) {
- os << "\n" << "Call pure virtual functions during construction or "
- << "destruction may leads undefined behaviour";
- BR.EmitBasicReport(AC->getDecl(), Checker,
- "Call pure virtual function during construction or "
- "Destruction",
- "Cplusplus", os.str(), CELoc, R);
- return;
- }
- else {
- os << "\n" << "Call virtual functions during construction or "
- << "destruction will never go to a more derived class";
- BR.EmitBasicReport(AC->getDecl(), Checker,
- "Call virtual function during construction or "
- "Destruction",
- "Cplusplus", os.str(), CELoc, R);
- return;
- }
+ os << "Call to ";
+ if (isPure)
+ os << "pure ";
+
+ os << "virtual function during ";
+
+ if (isa<CXXConstructorDecl>(RootMethod))
+ os << "construction ";
+ else
+ os << "destruction ";
+
+ if (isPure)
+ os << "has undefined behavior";
+ else
+ os << "will not dispatch to derived class";
+
+ BR.EmitBasicReport(AC->getDecl(), Checker,
+ "Call to virtual function during construction or "
+ "destruction",
+ "C++ Object Lifecycle", os.str(), CELoc, R);
}
//===----------------------------------------------------------------------===//
@@ -218,14 +251,18 @@ void WalkAST::ReportVirtualCall(const CallExpr *CE, bool isPure) {
namespace {
class VirtualCallChecker : public Checker<check::ASTDecl<CXXRecordDecl> > {
public:
+ DefaultBool isInterprocedural;
+ DefaultBool isPureOnly;
+
void checkASTDecl(const CXXRecordDecl *RD, AnalysisManager& mgr,
BugReporter &BR) const {
- WalkAST walker(this, BR, mgr.getAnalysisDeclContext(RD));
+ AnalysisDeclContext *ADC = mgr.getAnalysisDeclContext(RD);
// Check the constructors.
for (const auto *I : RD->ctors()) {
if (!I->isCopyOrMoveConstructor())
if (Stmt *Body = I->getBody()) {
+ WalkAST walker(this, BR, ADC, I, isInterprocedural, isPureOnly);
walker.Visit(Body);
walker.Execute();
}
@@ -234,6 +271,7 @@ public:
// Check the destructor.
if (CXXDestructorDecl *DD = RD->getDestructor())
if (Stmt *Body = DD->getBody()) {
+ WalkAST walker(this, BR, ADC, DD, isInterprocedural, isPureOnly);
walker.Visit(Body);
walker.Execute();
}
@@ -242,5 +280,12 @@ public:
}
void ento::registerVirtualCallChecker(CheckerManager &mgr) {
- mgr.registerChecker<VirtualCallChecker>();
+ VirtualCallChecker *checker = mgr.registerChecker<VirtualCallChecker>();
+ checker->isInterprocedural =
+ mgr.getAnalyzerOptions().getBooleanOption("Interprocedural", false,
+ checker);
+
+ checker->isPureOnly =
+ mgr.getAnalyzerOptions().getBooleanOption("PureOnly", false,
+ checker);
}
diff --git a/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp b/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
index 54c668cd2d6f..15422633ba33 100644
--- a/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
+++ b/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
@@ -23,6 +23,25 @@ using namespace clang;
using namespace ento;
using namespace llvm;
+std::vector<StringRef>
+AnalyzerOptions::getRegisteredCheckers(bool IncludeExperimental /* = false */) {
+ static const StringRef StaticAnalyzerChecks[] = {
+#define GET_CHECKERS
+#define CHECKER(FULLNAME, CLASS, DESCFILE, HELPTEXT, GROUPINDEX, HIDDEN) \
+ FULLNAME,
+#include "clang/StaticAnalyzer/Checkers/Checkers.inc"
+#undef CHECKER
+#undef GET_CHECKERS
+ };
+ std::vector<StringRef> Result;
+ for (StringRef CheckName : StaticAnalyzerChecks) {
+ if (!CheckName.startswith("debug.") &&
+ (IncludeExperimental || !CheckName.startswith("alpha.")))
+ Result.push_back(CheckName);
+ }
+ return Result;
+}
+
AnalyzerOptions::UserModeKind AnalyzerOptions::getUserMode() {
if (UserMode == UMK_NotSet) {
StringRef ModeStr =
@@ -344,3 +363,10 @@ bool AnalyzerOptions::shouldWidenLoops() {
WidenLoops = getBooleanOption("widen-loops", /*Default=*/false);
return WidenLoops.getValue();
}
+
+bool AnalyzerOptions::shouldDisplayNotesAsEvents() {
+ if (!DisplayNotesAsEvents.hasValue())
+ DisplayNotesAsEvents =
+ getBooleanOption("notes-as-events", /*Default=*/false);
+ return DisplayNotesAsEvents.getValue();
+}
diff --git a/lib/StaticAnalyzer/Core/BasicValueFactory.cpp b/lib/StaticAnalyzer/Core/BasicValueFactory.cpp
index 3c3f41a885e9..ebbace4e33b3 100644
--- a/lib/StaticAnalyzer/Core/BasicValueFactory.cpp
+++ b/lib/StaticAnalyzer/Core/BasicValueFactory.cpp
@@ -33,6 +33,13 @@ void LazyCompoundValData::Profile(llvm::FoldingSetNodeID& ID,
ID.AddPointer(region);
}
+void PointerToMemberData::Profile(
+ llvm::FoldingSetNodeID& ID, const DeclaratorDecl *D,
+ llvm::ImmutableList<const CXXBaseSpecifier *> L) {
+ ID.AddPointer(D);
+ ID.AddPointer(L.getInternalPointer());
+}
+
typedef std::pair<SVal, uintptr_t> SValData;
typedef std::pair<SVal, SVal> SValPair;
@@ -142,6 +149,49 @@ BasicValueFactory::getLazyCompoundValData(const StoreRef &store,
return D;
}
+const PointerToMemberData *BasicValueFactory::getPointerToMemberData(
+ const DeclaratorDecl *DD, llvm::ImmutableList<const CXXBaseSpecifier*> L) {
+ llvm::FoldingSetNodeID ID;
+ PointerToMemberData::Profile(ID, DD, L);
+ void *InsertPos;
+
+ PointerToMemberData *D =
+ PointerToMemberDataSet.FindNodeOrInsertPos(ID, InsertPos);
+
+ if (!D) {
+ D = (PointerToMemberData*) BPAlloc.Allocate<PointerToMemberData>();
+ new (D) PointerToMemberData(DD, L);
+ PointerToMemberDataSet.InsertNode(D, InsertPos);
+ }
+
+ return D;
+}
+
+const clang::ento::PointerToMemberData *BasicValueFactory::accumCXXBase(
+ llvm::iterator_range<CastExpr::path_const_iterator> PathRange,
+ const nonloc::PointerToMember &PTM) {
+ nonloc::PointerToMember::PTMDataType PTMDT = PTM.getPTMData();
+ const DeclaratorDecl *DD = nullptr;
+ llvm::ImmutableList<const CXXBaseSpecifier *> PathList;
+
+ if (PTMDT.isNull() || PTMDT.is<const DeclaratorDecl *>()) {
+ if (PTMDT.is<const DeclaratorDecl *>())
+ DD = PTMDT.get<const DeclaratorDecl *>();
+
+ PathList = CXXBaseListFactory.getEmptyList();
+ } else { // const PointerToMemberData *
+ const PointerToMemberData *PTMD =
+ PTMDT.get<const PointerToMemberData *>();
+ DD = PTMD->getDeclaratorDecl();
+
+ PathList = PTMD->getCXXBaseList();
+ }
+
+ for (const auto &I : llvm::reverse(PathRange))
+ PathList = prependCXXBase(I, PathList);
+ return getPointerToMemberData(DD, PathList);
+}
+
const llvm::APSInt*
BasicValueFactory::evalAPSInt(BinaryOperator::Opcode Op,
const llvm::APSInt& V1, const llvm::APSInt& V2) {
diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp
index 488126b0088a..53b4e699f7ad 100644
--- a/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ b/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -21,6 +21,7 @@
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
#include "clang/Analysis/CFG.h"
+#include "clang/Analysis/CFGStmtMap.h"
#include "clang/Analysis/ProgramPoint.h"
#include "clang/Basic/SourceManager.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
@@ -78,7 +79,9 @@ static PathDiagnosticEventPiece *
eventsDescribeSameCondition(PathDiagnosticEventPiece *X,
PathDiagnosticEventPiece *Y) {
// Prefer diagnostics that come from ConditionBRVisitor over
- // those that came from TrackConstraintBRVisitor.
+ // those that came from TrackConstraintBRVisitor,
+ // unless the one from ConditionBRVisitor is
+ // its generic fallback diagnostic.
const void *tagPreferred = ConditionBRVisitor::getTag();
const void *tagLesser = TrackConstraintBRVisitor::getTag();
@@ -86,10 +89,10 @@ eventsDescribeSameCondition(PathDiagnosticEventPiece *X,
return nullptr;
if (X->getTag() == tagPreferred && Y->getTag() == tagLesser)
- return X;
+ return ConditionBRVisitor::isPieceMessageGeneric(X) ? Y : X;
if (Y->getTag() == tagPreferred && X->getTag() == tagLesser)
- return Y;
+ return ConditionBRVisitor::isPieceMessageGeneric(Y) ? X : Y;
return nullptr;
}
@@ -112,15 +115,15 @@ static void removeRedundantMsgs(PathPieces &path) {
path.pop_front();
switch (piece->getKind()) {
- case clang::ento::PathDiagnosticPiece::Call:
+ case PathDiagnosticPiece::Call:
removeRedundantMsgs(cast<PathDiagnosticCallPiece>(piece)->path);
break;
- case clang::ento::PathDiagnosticPiece::Macro:
+ case PathDiagnosticPiece::Macro:
removeRedundantMsgs(cast<PathDiagnosticMacroPiece>(piece)->subPieces);
break;
- case clang::ento::PathDiagnosticPiece::ControlFlow:
+ case PathDiagnosticPiece::ControlFlow:
break;
- case clang::ento::PathDiagnosticPiece::Event: {
+ case PathDiagnosticPiece::Event: {
if (i == N-1)
break;
@@ -140,6 +143,8 @@ static void removeRedundantMsgs(PathPieces &path) {
}
break;
}
+ case PathDiagnosticPiece::Note:
+ break;
}
path.push_back(piece);
}
@@ -197,6 +202,9 @@ static bool removeUnneededCalls(PathPieces &pieces, BugReport *R,
}
case PathDiagnosticPiece::ControlFlow:
break;
+
+ case PathDiagnosticPiece::Note:
+ break;
}
pieces.push_back(piece);
@@ -3104,6 +3112,7 @@ bool GRBugReporter::generatePathDiagnostic(PathDiagnostic& PD,
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;
@@ -3277,6 +3286,19 @@ struct FRIEC_WLItem {
};
}
+static const CFGBlock *findBlockForNode(const ExplodedNode *N) {
+ ProgramPoint P = N->getLocation();
+ if (auto BEP = P.getAs<BlockEntrance>())
+ return BEP->getBlock();
+
+ // Find the node's current statement in the CFG.
+ if (const Stmt *S = PathDiagnosticLocation::getStmt(N))
+ return N->getLocationContext()->getAnalysisDeclContext()
+ ->getCFGStmtMap()->getBlock(S);
+
+ return nullptr;
+}
+
static BugReport *
FindReportInEquivalenceClass(BugReportEquivClass& EQ,
SmallVectorImpl<BugReport*> &bugReports) {
@@ -3325,6 +3347,18 @@ FindReportInEquivalenceClass(BugReportEquivClass& EQ,
continue;
}
+ // See if we are in a no-return CFG block. If so, treat this similarly
+ // to being post-dominated by a sink. This works better when the analysis
+ // is incomplete and we have never reached a no-return function
+ // we're post-dominated by.
+ // This is not quite enough to handle the incomplete analysis case.
+ // We may be post-dominated in subsequent blocks, or even
+ // inter-procedurally. However, it is not clear if more complicated
+ // cases are generally worth suppressing.
+ if (const CFGBlock *B = findBlockForNode(errorNode))
+ if (B->hasNoReturnElement())
+ continue;
+
// 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;
@@ -3402,25 +3436,28 @@ void BugReporter::FlushReport(BugReport *exampleReport,
exampleReport->getUniqueingLocation(),
exampleReport->getUniqueingDecl()));
- MaxBugClassSize = std::max(bugReports.size(),
- static_cast<size_t>(MaxBugClassSize));
+ 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());
+
+ MaxBugClassSize =
+ std::max(bugReports.size(), static_cast<size_t>(MaxBugClassSize));
- // 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.
- if (!bugReports.empty())
if (!generatePathDiagnostic(*D.get(), PD, bugReports))
return;
- MaxValidBugClassSize = std::max(bugReports.size(),
- static_cast<size_t>(MaxValidBugClassSize));
+ MaxValidBugClassSize =
+ std::max(bugReports.size(), static_cast<size_t>(MaxValidBugClassSize));
- // 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();
+ // 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.
@@ -3433,6 +3470,27 @@ void BugReporter::FlushReport(BugReport *exampleReport,
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();
+ PathDiagnosticEventPiece *ConvertedPiece =
+ new PathDiagnosticEventPiece(Piece->getLocation(),
+ Piece->getString());
+ for (const auto &R: Piece->getRanges())
+ ConvertedPiece->addRange(R);
+
+ Pieces.push_front(ConvertedPiece);
+ }
+ } else {
+ for (auto I = exampleReport->getNotes().rbegin(),
+ E = exampleReport->getNotes().rend(); I != E; ++I)
+ Pieces.push_front(*I);
+ }
+
// Get the meta data.
const BugReport::ExtraTextList &Meta = exampleReport->getExtraText();
for (BugReport::ExtraTextList::const_iterator i = Meta.begin(),
@@ -3517,6 +3575,13 @@ LLVM_DUMP_METHOD void PathDiagnosticMacroPiece::dump() const {
// 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";
diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index 0e505463bb5e..7f20f0d7703e 100644
--- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -15,6 +15,7 @@
#include "clang/AST/Expr.h"
#include "clang/AST/ExprObjC.h"
#include "clang/Analysis/CFGStmtMap.h"
+#include "clang/Lex/Lexer.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
@@ -916,7 +917,7 @@ static const Expr *peelOffOuterExpr(const Expr *Ex,
if (PropRef && PropRef->isMessagingGetter()) {
const Expr *GetterMessageSend =
POE->getSemanticExpr(POE->getNumSemanticExprs() - 1);
- assert(isa<ObjCMessageExpr>(GetterMessageSend));
+ assert(isa<ObjCMessageExpr>(GetterMessageSend->IgnoreParenCasts()));
return peelOffOuterExpr(GetterMessageSend, N);
}
}
@@ -1271,7 +1272,22 @@ ConditionBRVisitor::VisitTerminator(const Stmt *Term,
BugReporterContext &BRC) {
const Expr *Cond = nullptr;
+ // In the code below, Term is a CFG terminator and Cond is a branch condition
+ // expression upon which the decision is made on this terminator.
+ //
+ // For example, in "if (x == 0)", the "if (x == 0)" statement is a terminator,
+ // and "x == 0" is the respective condition.
+ //
+ // Another example: in "if (x && y)", we've got two terminators and two
+ // conditions due to short-circuit nature of operator "&&":
+ // 1. The "if (x && y)" statement is a terminator,
+ // and "y" is the respective condition.
+ // 2. Also "x && ..." is another terminator,
+ // and "x" is its condition.
+
switch (Term->getStmtClass()) {
+ // FIXME: Stmt::SwitchStmtClass is worth handling, however it is a bit
+ // more tricky because there are more than two branches to account for.
default:
return nullptr;
case Stmt::IfStmtClass:
@@ -1280,6 +1296,24 @@ ConditionBRVisitor::VisitTerminator(const Stmt *Term,
case Stmt::ConditionalOperatorClass:
Cond = cast<ConditionalOperator>(Term)->getCond();
break;
+ case Stmt::BinaryOperatorClass:
+ // When we encounter a logical operator (&& or ||) as a CFG terminator,
+ // then the condition is actually its LHS; otheriwse, we'd encounter
+ // the parent, such as if-statement, as a terminator.
+ const auto *BO = cast<BinaryOperator>(Term);
+ assert(BO->isLogicalOp() &&
+ "CFG terminator is not a short-circuit operator!");
+ Cond = BO->getLHS();
+ break;
+ }
+
+ // However, when we encounter a logical operator as a branch condition,
+ // then the condition is actually its RHS, because LHS would be
+ // the condition for the logical operator terminator.
+ while (const auto *InnerBO = dyn_cast<BinaryOperator>(Cond)) {
+ if (!InnerBO->isLogicalOp())
+ break;
+ Cond = InnerBO->getRHS()->IgnoreParens();
}
assert(Cond);
@@ -1294,34 +1328,54 @@ ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
BugReporterContext &BRC,
BugReport &R,
const ExplodedNode *N) {
-
- const Expr *Ex = Cond;
+ // These will be modified in code below, but we need to preserve the original
+ // values in case we want to throw the generic message.
+ const Expr *CondTmp = Cond;
+ bool tookTrueTmp = tookTrue;
while (true) {
- Ex = Ex->IgnoreParenCasts();
- switch (Ex->getStmtClass()) {
+ CondTmp = CondTmp->IgnoreParenCasts();
+ switch (CondTmp->getStmtClass()) {
default:
- return nullptr;
+ break;
case Stmt::BinaryOperatorClass:
- return VisitTrueTest(Cond, cast<BinaryOperator>(Ex), tookTrue, BRC,
- R, N);
+ if (PathDiagnosticPiece *P = VisitTrueTest(
+ Cond, cast<BinaryOperator>(CondTmp), tookTrueTmp, BRC, R, N))
+ return P;
+ break;
case Stmt::DeclRefExprClass:
- return VisitTrueTest(Cond, cast<DeclRefExpr>(Ex), tookTrue, BRC,
- R, N);
+ if (PathDiagnosticPiece *P = VisitTrueTest(
+ Cond, cast<DeclRefExpr>(CondTmp), tookTrueTmp, BRC, R, N))
+ return P;
+ break;
case Stmt::UnaryOperatorClass: {
- const UnaryOperator *UO = cast<UnaryOperator>(Ex);
+ const UnaryOperator *UO = cast<UnaryOperator>(CondTmp);
if (UO->getOpcode() == UO_LNot) {
- tookTrue = !tookTrue;
- Ex = UO->getSubExpr();
+ tookTrueTmp = !tookTrueTmp;
+ CondTmp = UO->getSubExpr();
continue;
}
- return nullptr;
+ break;
}
}
+ break;
}
+
+ // Condition too complex to explain? Just say something so that the user
+ // knew we've made some path decision at this point.
+ const LocationContext *LCtx = N->getLocationContext();
+ PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx);
+ if (!Loc.isValid() || !Loc.asLocation().isValid())
+ return nullptr;
+
+ PathDiagnosticEventPiece *Event = new PathDiagnosticEventPiece(
+ Loc, tookTrue ? GenericTrueMessage : GenericFalseMessage);
+ return Event;
}
-bool ConditionBRVisitor::patternMatch(const Expr *Ex, raw_ostream &Out,
+bool ConditionBRVisitor::patternMatch(const Expr *Ex,
+ const Expr *ParentEx,
+ raw_ostream &Out,
BugReporterContext &BRC,
BugReport &report,
const ExplodedNode *N,
@@ -1329,6 +1383,47 @@ bool ConditionBRVisitor::patternMatch(const Expr *Ex, raw_ostream &Out,
const Expr *OriginalExpr = Ex;
Ex = Ex->IgnoreParenCasts();
+ // Use heuristics to determine if Ex is a macro expending to a literal and
+ // if so, use the macro's name.
+ SourceLocation LocStart = Ex->getLocStart();
+ SourceLocation LocEnd = Ex->getLocEnd();
+ if (LocStart.isMacroID() && LocEnd.isMacroID() &&
+ (isa<GNUNullExpr>(Ex) ||
+ isa<ObjCBoolLiteralExpr>(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,
+ BRC.getSourceManager(), BRC.getASTContext().getLangOpts());
+ bool beginAndEndAreTheSameMacro = StartName.equals(EndName);
+
+ bool partOfParentMacro = false;
+ if (ParentEx->getLocStart().isMacroID()) {
+ StringRef PName = Lexer::getImmediateMacroNameForDiagnostics(
+ ParentEx->getLocStart(), BRC.getSourceManager(),
+ BRC.getASTContext().getLangOpts());
+ partOfParentMacro = PName.equals(StartName);
+ }
+
+ if (beginAndEndAreTheSameMacro && !partOfParentMacro ) {
+ // Get the location of the macro name as written by the caller.
+ SourceLocation Loc = LocStart;
+ while (LocStart.isMacroID()) {
+ Loc = LocStart;
+ LocStart = BRC.getSourceManager().getImmediateMacroCallerLoc(LocStart);
+ }
+ StringRef MacroName = Lexer::getImmediateMacroNameForDiagnostics(
+ Loc, BRC.getSourceManager(), BRC.getASTContext().getLangOpts());
+
+ // Return the macro name.
+ Out << MacroName;
+ return false;
+ }
+ }
+
if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex)) {
const bool quotes = isa<VarDecl>(DR->getDecl());
if (quotes) {
@@ -1389,10 +1484,10 @@ ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
SmallString<128> LhsString, RhsString;
{
llvm::raw_svector_ostream OutLHS(LhsString), OutRHS(RhsString);
- const bool isVarLHS = patternMatch(BExpr->getLHS(), OutLHS, BRC, R, N,
- shouldPrune);
- const bool isVarRHS = patternMatch(BExpr->getRHS(), OutRHS, BRC, R, N,
- shouldPrune);
+ const bool isVarLHS = patternMatch(BExpr->getLHS(), BExpr, OutLHS,
+ BRC, R, N, shouldPrune);
+ const bool isVarRHS = patternMatch(BExpr->getRHS(), BExpr, OutRHS,
+ BRC, R, N, shouldPrune);
shouldInvert = !isVarLHS && isVarRHS;
}
@@ -1552,6 +1647,17 @@ ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
return event;
}
+const char *const ConditionBRVisitor::GenericTrueMessage =
+ "Assuming the condition is true";
+const char *const ConditionBRVisitor::GenericFalseMessage =
+ "Assuming the condition is false";
+
+bool ConditionBRVisitor::isPieceMessageGeneric(
+ const PathDiagnosticPiece *Piece) {
+ return Piece->getString() == GenericTrueMessage ||
+ Piece->getString() == GenericFalseMessage;
+}
+
std::unique_ptr<PathDiagnosticPiece>
LikelyFalsePositiveSuppressionBRVisitor::getEndPath(BugReporterContext &BRC,
const ExplodedNode *N,
@@ -1693,3 +1799,56 @@ UndefOrNullArgVisitor::VisitNode(const ExplodedNode *N,
}
return nullptr;
}
+
+PathDiagnosticPiece *
+CXXSelfAssignmentBRVisitor::VisitNode(const ExplodedNode *Succ,
+ const ExplodedNode *Pred,
+ BugReporterContext &BRC, BugReport &BR) {
+ if (Satisfied)
+ return nullptr;
+
+ auto Edge = Succ->getLocation().getAs<BlockEdge>();
+ if (!Edge.hasValue())
+ return nullptr;
+
+ auto Tag = Edge->getTag();
+ if (!Tag)
+ return nullptr;
+
+ if (Tag->getTagDescription() != "cplusplus.SelfAssignment")
+ return nullptr;
+
+ Satisfied = true;
+
+ const auto *Met =
+ dyn_cast<CXXMethodDecl>(Succ->getCodeDecl().getAsFunction());
+ assert(Met && "Not a C++ method.");
+ assert((Met->isCopyAssignmentOperator() || Met->isMoveAssignmentOperator()) &&
+ "Not a copy/move assignment operator.");
+
+ const auto *LCtx = Edge->getLocationContext();
+
+ const auto &State = Succ->getState();
+ auto &SVB = State->getStateManager().getSValBuilder();
+
+ const auto Param =
+ State->getSVal(State->getRegion(Met->getParamDecl(0), LCtx));
+ const auto This =
+ State->getSVal(SVB.getCXXThis(Met, LCtx->getCurrentStackFrame()));
+
+ auto L = PathDiagnosticLocation::create(Met, BRC.getSourceManager());
+
+ if (!L.isValid() || !L.asLocation().isValid())
+ return nullptr;
+
+ SmallString<256> Buf;
+ llvm::raw_svector_ostream Out(Buf);
+
+ Out << "Assuming " << Met->getParamDecl(0)->getName() <<
+ ((Param == This) ? " == " : " != ") << "*this";
+
+ auto *Piece = new PathDiagnosticEventPiece(L, Out.str());
+ Piece->addRange(Met->getSourceRange());
+
+ return Piece;
+}
diff --git a/lib/StaticAnalyzer/Core/CallEvent.cpp b/lib/StaticAnalyzer/Core/CallEvent.cpp
index 52613186677a..420e2a6b5c8c 100644
--- a/lib/StaticAnalyzer/Core/CallEvent.cpp
+++ b/lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -382,6 +382,11 @@ bool AnyFunctionCall::argumentsMayEscape() const {
if (II->isStr("funopen"))
return true;
+ // - __cxa_demangle - can reallocate memory and can return the pointer to
+ // the input buffer.
+ if (II->isStr("__cxa_demangle"))
+ return true;
+
StringRef FName = II->getName();
// - CoreFoundation functions that end with "NoCopy" can free a passed-in
@@ -552,7 +557,7 @@ void CXXInstanceCall::getInitialStackFrameContents(
// FIXME: CallEvent maybe shouldn't be directly accessing StoreManager.
bool Failed;
- ThisVal = StateMgr.getStoreManager().evalDynamicCast(ThisVal, Ty, Failed);
+ ThisVal = StateMgr.getStoreManager().attemptDownCast(ThisVal, Ty, Failed);
assert(!Failed && "Calling an incorrectly devirtualized method");
}
diff --git a/lib/StaticAnalyzer/Core/CheckerManager.cpp b/lib/StaticAnalyzer/Core/CheckerManager.cpp
index d8382e88691a..79e204cdafec 100644
--- a/lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ b/lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -518,15 +518,6 @@ void CheckerManager::runCheckersForDeadSymbols(ExplodedNodeSet &Dst,
expandGraphWithCheckers(C, Dst, Src);
}
-/// \brief True if at least one checker wants to check region changes.
-bool CheckerManager::wantsRegionChangeUpdate(ProgramStateRef state) {
- for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i)
- if (RegionChangesCheckers[i].WantUpdateFn(state))
- return true;
-
- return false;
-}
-
/// \brief Run checkers for region changes.
ProgramStateRef
CheckerManager::runCheckersForRegionChanges(ProgramStateRef state,
@@ -539,8 +530,8 @@ CheckerManager::runCheckersForRegionChanges(ProgramStateRef state,
// bail out.
if (!state)
return nullptr;
- state = RegionChangesCheckers[i].CheckFn(state, invalidated,
- ExplicitRegions, Regions, Call);
+ state = RegionChangesCheckers[i](state, invalidated,
+ ExplicitRegions, Regions, Call);
}
return state;
}
@@ -726,10 +717,8 @@ void CheckerManager::_registerForDeadSymbols(CheckDeadSymbolsFunc checkfn) {
DeadSymbolsCheckers.push_back(checkfn);
}
-void CheckerManager::_registerForRegionChanges(CheckRegionChangesFunc checkfn,
- WantsRegionChangeUpdateFunc wantUpdateFn) {
- RegionChangesCheckerInfo info = {checkfn, wantUpdateFn};
- RegionChangesCheckers.push_back(info);
+void CheckerManager::_registerForRegionChanges(CheckRegionChangesFunc checkfn) {
+ RegionChangesCheckers.push_back(checkfn);
}
void CheckerManager::_registerForPointerEscape(CheckPointerEscapeFunc checkfn){
diff --git a/lib/StaticAnalyzer/Core/CheckerRegistry.cpp b/lib/StaticAnalyzer/Core/CheckerRegistry.cpp
index ba03e2f8a3c1..c9cb189a5b72 100644
--- a/lib/StaticAnalyzer/Core/CheckerRegistry.cpp
+++ b/lib/StaticAnalyzer/Core/CheckerRegistry.cpp
@@ -175,3 +175,22 @@ void CheckerRegistry::printHelp(raw_ostream &out,
out << '\n';
}
}
+
+void CheckerRegistry::printList(
+ raw_ostream &out, SmallVectorImpl<CheckerOptInfo> &opts) const {
+ std::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 (CheckerInfoSet::const_iterator i = enabledCheckers.begin(),
+ e = enabledCheckers.end();
+ i != e; ++i) {
+ out << (*i)->FullName << '\n';
+ }
+}
diff --git a/lib/StaticAnalyzer/Core/CoreEngine.cpp b/lib/StaticAnalyzer/Core/CoreEngine.cpp
index da608f6c7558..4e2866c56f0e 100644
--- a/lib/StaticAnalyzer/Core/CoreEngine.cpp
+++ b/lib/StaticAnalyzer/Core/CoreEngine.cpp
@@ -18,7 +18,6 @@
#include "clang/AST/StmtCXX.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
-#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Casting.h"
@@ -310,8 +309,19 @@ void CoreEngine::HandleBlockEdge(const BlockEdge &L, ExplodedNode *Pred) {
assert (L.getLocationContext()->getCFG()->getExit().size() == 0
&& "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;
+ }
+ }
+ }
+
// Process the final state transition.
- SubEng.processEndOfFunction(BuilderCtx, Pred);
+ SubEng.processEndOfFunction(BuilderCtx, Pred, RS);
// This path is done. Don't enqueue any more nodes.
return;
@@ -590,13 +600,14 @@ void CoreEngine::enqueueStmtNode(ExplodedNode *N,
WList->enqueue(Succ, Block, Idx+1);
}
-ExplodedNode *CoreEngine::generateCallExitBeginNode(ExplodedNode *N) {
+ExplodedNode *CoreEngine::generateCallExitBeginNode(ExplodedNode *N,
+ const ReturnStmt *RS) {
// Create a CallExitBegin node and enqueue it.
const StackFrameContext *LocCtx
= cast<StackFrameContext>(N->getLocationContext());
// Use the callee location context.
- CallExitBegin Loc(LocCtx);
+ CallExitBegin Loc(LocCtx, RS);
bool isNew;
ExplodedNode *Node = G.getNode(Loc, N->getState(), false, &isNew);
@@ -620,12 +631,12 @@ void CoreEngine::enqueue(ExplodedNodeSet &Set,
}
}
-void CoreEngine::enqueueEndOfFunction(ExplodedNodeSet &Set) {
+void CoreEngine::enqueueEndOfFunction(ExplodedNodeSet &Set, const ReturnStmt *RS) {
for (ExplodedNodeSet::iterator I = Set.begin(), E = Set.end(); I != E; ++I) {
ExplodedNode *N = *I;
// If we are in an inlined call, generate CallExitBegin node.
if (N->getLocationContext()->getParent()) {
- N = generateCallExitBeginNode(N);
+ N = generateCallExitBeginNode(N, RS);
if (N)
WList->enqueue(N);
} else {
diff --git a/lib/StaticAnalyzer/Core/ExplodedGraph.cpp b/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
index 02d382cc4885..3bc8e09333b9 100644
--- a/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
+++ b/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
@@ -17,11 +17,9 @@
#include "clang/AST/Stmt.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
-#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
-#include <vector>
using namespace clang;
using namespace ento;
diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 405aecdee032..5b2119aeda27 100644
--- a/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -27,10 +27,9 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h"
-#include "llvm/ADT/ImmutableList.h"
#include "llvm/ADT/Statistic.h"
-#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/SaveAndRestore.h"
+#include "llvm/Support/raw_ostream.h"
#ifndef NDEBUG
#include "llvm/Support/GraphWriter.h"
@@ -203,25 +202,32 @@ ExprEngine::createTemporaryRegionIfNeeded(ProgramStateRef State,
MemRegionManager &MRMgr = StateMgr.getRegionManager();
StoreManager &StoreMgr = StateMgr.getStoreManager();
- // We need to be careful about treating a derived type's value as
- // bindings for a base type. Unless we're creating a temporary pointer region,
- // start by stripping and recording base casts.
- SmallVector<const CastExpr *, 4> Casts;
- const Expr *Inner = Ex->IgnoreParens();
- if (!Loc::isLocType(Result->getType())) {
- while (const CastExpr *CE = dyn_cast<CastExpr>(Inner)) {
- if (CE->getCastKind() == CK_DerivedToBase ||
- CE->getCastKind() == CK_UncheckedDerivedToBase)
- Casts.push_back(CE);
- else if (CE->getCastKind() != CK_NoOp)
- break;
+ // MaterializeTemporaryExpr may appear out of place, after a few field and
+ // base-class accesses have been made to the object, even though semantically
+ // it is the whole object that gets materialized and lifetime-extended.
+ //
+ // For example:
+ //
+ // `-MaterializeTemporaryExpr
+ // `-MemberExpr
+ // `-CXXTemporaryObjectExpr
+ //
+ // instead of the more natural
+ //
+ // `-MemberExpr
+ // `-MaterializeTemporaryExpr
+ // `-CXXTemporaryObjectExpr
+ //
+ // Use the usual methods for obtaining the expression of the base object,
+ // and record the adjustments that we need to make to obtain the sub-object
+ // that the whole expression 'Ex' refers to. This trick is usual,
+ // in the sense that CodeGen takes a similar route.
- Inner = CE->getSubExpr()->IgnoreParens();
- }
- }
+ SmallVector<const Expr *, 2> CommaLHSs;
+ SmallVector<SubobjectAdjustment, 2> Adjustments;
+
+ const Expr *Init = Ex->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments);
- // Create a temporary object region for the inner expression (which may have
- // a more derived type) and bind the value into it.
const TypedValueRegion *TR = nullptr;
if (const MaterializeTemporaryExpr *MT =
dyn_cast<MaterializeTemporaryExpr>(Result)) {
@@ -229,25 +235,37 @@ ExprEngine::createTemporaryRegionIfNeeded(ProgramStateRef State,
// 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(Inner);
+ TR = MRMgr.getCXXStaticTempObjectRegion(Init);
}
if (!TR)
- TR = MRMgr.getCXXTempObjectRegion(Inner, LC);
+ TR = MRMgr.getCXXTempObjectRegion(Init, LC);
SVal Reg = loc::MemRegionVal(TR);
+ // Make the necessary adjustments to obtain the sub-object.
+ for (auto I = Adjustments.rbegin(), E = Adjustments.rend(); I != E; ++I) {
+ const SubobjectAdjustment &Adj = *I;
+ switch (Adj.Kind) {
+ case SubobjectAdjustment::DerivedToBaseAdjustment:
+ Reg = StoreMgr.evalDerivedToBase(Reg, Adj.DerivedToBase.BasePath);
+ break;
+ case SubobjectAdjustment::FieldAdjustment:
+ Reg = StoreMgr.getLValueField(Adj.Field, Reg);
+ break;
+ case SubobjectAdjustment::MemberPointerAdjustment:
+ // FIXME: Unimplemented.
+ State->bindDefault(Reg, UnknownVal());
+ return State;
+ }
+ }
+
+ // Try to recover some path sensitivity in case we couldn't compute the value.
if (V.isUnknown())
V = getSValBuilder().conjureSymbolVal(Result, LC, TR->getValueType(),
currBldrCtx->blockCount());
+ // Bind the value of the expression to the sub-object region, and then bind
+ // the sub-object region to our expression.
State = State->bindLoc(Reg, V);
-
- // Re-apply the casts (from innermost to outermost) for type sanity.
- for (SmallVectorImpl<const CastExpr *>::reverse_iterator I = Casts.rbegin(),
- E = Casts.rend();
- I != E; ++I) {
- Reg = StoreMgr.evalDerivedToBase(Reg, *I);
- }
-
State = State->BindExpr(Result, LC, Reg);
return State;
}
@@ -263,10 +281,6 @@ ProgramStateRef ExprEngine::processAssume(ProgramStateRef state,
return getCheckerManager().runCheckersForEvalAssume(state, cond, assumption);
}
-bool ExprEngine::wantsRegionChangeUpdate(ProgramStateRef state) {
- return getCheckerManager().wantsRegionChangeUpdate(state);
-}
-
ProgramStateRef
ExprEngine::processRegionChanges(ProgramStateRef state,
const InvalidatedSymbols *invalidated,
@@ -493,7 +507,7 @@ void ExprEngine::ProcessInitializer(const CFGInitializer Init,
}
SVal InitVal;
- if (BMI->getNumArrayIndices() > 0) {
+ if (Init->getType()->isArrayType()) {
// Handle arrays of trivial type. We can represent this with a
// primitive load/copy from the base array region.
const ArraySubscriptExpr *ASE;
@@ -597,9 +611,9 @@ void ExprEngine::ProcessAutomaticObjDtor(const CFGAutomaticObjDtor Dtor,
SVal dest = state->getLValue(varDecl, Pred->getLocationContext());
const MemRegion *Region = dest.castAs<loc::MemRegionVal>().getRegion();
- if (const ReferenceType *refType = varType->getAs<ReferenceType>()) {
- varType = refType->getPointeeType();
- Region = state->getSVal(Region).getAsRegion();
+ if (varType->isReferenceType()) {
+ Region = state->getSVal(Region).getAsRegion()->getBaseRegion();
+ varType = cast<TypedValueRegion>(Region)->getValueType();
}
VisitCXXDestructor(varType, Region, Dtor.getTriggerStmt(), /*IsBase=*/ false,
@@ -847,6 +861,14 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
case Stmt::OMPDistributeParallelForSimdDirectiveClass:
case Stmt::OMPDistributeSimdDirectiveClass:
case Stmt::OMPTargetParallelForSimdDirectiveClass:
+ case Stmt::OMPTargetSimdDirectiveClass:
+ case Stmt::OMPTeamsDistributeDirectiveClass:
+ case Stmt::OMPTeamsDistributeSimdDirectiveClass:
+ case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
+ case Stmt::OMPTeamsDistributeParallelForDirectiveClass:
+ case Stmt::OMPTargetTeamsDirectiveClass:
+ case Stmt::OMPTargetTeamsDistributeDirectiveClass:
+ case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
llvm_unreachable("Stmt should not be in analyzer evaluation loop");
case Stmt::ObjCSubscriptRefExprClass:
@@ -886,6 +908,8 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
// Cases not handled yet; but will handle some day.
case Stmt::DesignatedInitExprClass:
case Stmt::DesignatedInitUpdateExprClass:
+ case Stmt::ArrayInitLoopExprClass:
+ case Stmt::ArrayInitIndexExprClass:
case Stmt::ExtVectorElementExprClass:
case Stmt::ImaginaryLiteralClass:
case Stmt::ObjCAtCatchStmtClass:
@@ -1211,16 +1235,8 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
case Stmt::ObjCBridgedCastExprClass: {
Bldr.takeNodes(Pred);
const CastExpr *C = cast<CastExpr>(S);
- // Handle the previsit checks.
- ExplodedNodeSet dstPrevisit;
- getCheckerManager().runCheckersForPreStmt(dstPrevisit, Pred, C, *this);
-
- // Handle the expression itself.
ExplodedNodeSet dstExpr;
- for (ExplodedNodeSet::iterator i = dstPrevisit.begin(),
- e = dstPrevisit.end(); i != e ; ++i) {
- VisitCast(C, C->getSubExpr(), *i, dstExpr);
- }
+ VisitCast(C, C->getSubExpr(), Pred, dstExpr);
// Handle the postvisit checks.
getCheckerManager().runCheckersForPostStmt(Dst, dstExpr, C, *this);
@@ -1773,7 +1789,8 @@ void ExprEngine::processBeginOfFunction(NodeBuilderContext &BC,
/// ProcessEndPath - Called by CoreEngine. Used to generate end-of-path
/// nodes when the control reaches the end of a function.
void ExprEngine::processEndOfFunction(NodeBuilderContext& BC,
- ExplodedNode *Pred) {
+ ExplodedNode *Pred,
+ const ReturnStmt *RS) {
// FIXME: Assert that stackFrameDoesNotContainInitializedTemporaries(*Pred)).
// We currently cannot enable this assert, as lifetime extended temporaries
// are not modelled correctly.
@@ -1795,7 +1812,7 @@ void ExprEngine::processEndOfFunction(NodeBuilderContext& BC,
getCheckerManager().runCheckersForEndFunction(BC, Dst, Pred, *this);
}
- Engine.enqueueEndOfFunction(Dst);
+ Engine.enqueueEndOfFunction(Dst, RS);
}
/// ProcessSwitch - Called by CoreEngine. Used to generate successor
@@ -1841,7 +1858,7 @@ void ExprEngine::processSwitch(SwitchNodeBuilder& builder) {
ProgramStateRef StateCase;
if (Optional<NonLoc> NL = CondV.getAs<NonLoc>())
std::tie(StateCase, DefaultSt) =
- DefaultSt->assumeWithinInclusiveRange(*NL, V1, V2);
+ DefaultSt->assumeInclusiveRange(*NL, V1, V2);
else // UnknownVal
StateCase = DefaultSt;
@@ -1975,24 +1992,26 @@ void ExprEngine::VisitLvalArraySubscriptExpr(const ArraySubscriptExpr *A,
const Expr *Base = A->getBase()->IgnoreParens();
const Expr *Idx = A->getIdx()->IgnoreParens();
- ExplodedNodeSet checkerPreStmt;
- getCheckerManager().runCheckersForPreStmt(checkerPreStmt, Pred, A, *this);
+ ExplodedNodeSet CheckerPreStmt;
+ getCheckerManager().runCheckersForPreStmt(CheckerPreStmt, Pred, A, *this);
- StmtNodeBuilder Bldr(checkerPreStmt, Dst, *currBldrCtx);
+ ExplodedNodeSet EvalSet;
+ StmtNodeBuilder Bldr(CheckerPreStmt, EvalSet, *currBldrCtx);
assert(A->isGLValue() ||
(!AMgr.getLangOpts().CPlusPlus &&
A->getType().isCForbiddenLValueType()));
- for (ExplodedNodeSet::iterator it = checkerPreStmt.begin(),
- ei = checkerPreStmt.end(); it != ei; ++it) {
- const LocationContext *LCtx = (*it)->getLocationContext();
- ProgramStateRef state = (*it)->getState();
+ for (auto *Node : CheckerPreStmt) {
+ const LocationContext *LCtx = Node->getLocationContext();
+ ProgramStateRef state = Node->getState();
SVal V = state->getLValue(A->getType(),
state->getSVal(Idx, LCtx),
state->getSVal(Base, LCtx));
- Bldr.generateNode(A, *it, state->BindExpr(A, LCtx, V), nullptr,
+ Bldr.generateNode(A, Node, state->BindExpr(A, LCtx, V), nullptr,
ProgramPoint::PostLValueKind);
}
+
+ getCheckerManager().runCheckersForPostStmt(Dst, EvalSet, A, *this);
}
/// VisitMemberExpr - Transfer function for member expressions.
@@ -2051,7 +2070,7 @@ void ExprEngine::VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred,
if (!M->isGLValue()) {
assert(M->getType()->isArrayType());
const ImplicitCastExpr *PE =
- dyn_cast<ImplicitCastExpr>((*I)->getParentMap().getParent(M));
+ dyn_cast<ImplicitCastExpr>((*I)->getParentMap().getParentIgnoreParens(M));
if (!PE || PE->getCastKind() != CK_ArrayToPointerDecay) {
llvm_unreachable("should always be wrapped in ArrayToPointerDecay");
}
@@ -2521,26 +2540,10 @@ struct DOTGraphTraits<ExplodedNode*> :
// FIXME: Since we do not cache error nodes in ExprEngine now, this does not
// work.
static std::string getNodeAttributes(const ExplodedNode *N, void*) {
-
-#if 0
- // FIXME: Replace with a general scheme to tell if the node is
- // an error node.
- if (GraphPrintCheckerState->isImplicitNullDeref(N) ||
- GraphPrintCheckerState->isExplicitNullDeref(N) ||
- GraphPrintCheckerState->isUndefDeref(N) ||
- GraphPrintCheckerState->isUndefStore(N) ||
- GraphPrintCheckerState->isUndefControlFlow(N) ||
- GraphPrintCheckerState->isUndefResult(N) ||
- GraphPrintCheckerState->isBadCall(N) ||
- GraphPrintCheckerState->isUndefArg(N))
- return "color=\"red\",style=\"filled\"";
-
- if (GraphPrintCheckerState->isNoReturnCall(N))
- return "color=\"blue\",style=\"filled\"";
-#endif
return "";
}
+ // De-duplicate some source location pretty-printing.
static void printLocation(raw_ostream &Out, SourceLocation SLoc) {
if (SLoc.isFileID()) {
Out << "\\lline="
@@ -2550,6 +2553,12 @@ 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*){
@@ -2563,12 +2572,6 @@ struct DOTGraphTraits<ExplodedNode*> :
case ProgramPoint::BlockEntranceKind: {
Out << "Block Entrance: B"
<< Loc.castAs<BlockEntrance>().getBlock()->getBlockID();
- if (const NamedDecl *ND =
- dyn_cast<NamedDecl>(Loc.getLocationContext()->getDecl())) {
- Out << " (";
- ND->printName(Out);
- Out << ")";
- }
break;
}
@@ -2693,13 +2696,6 @@ struct DOTGraphTraits<ExplodedNode*> :
Out << "\\l";
}
-#if 0
- // FIXME: Replace with a general scheme to determine
- // the name of the check.
- if (GraphPrintCheckerState->isUndefControlFlow(N)) {
- Out << "\\|Control-flow based on\\lUndefined value.\\l";
- }
-#endif
break;
}
@@ -2721,27 +2717,6 @@ struct DOTGraphTraits<ExplodedNode*> :
else if (Loc.getAs<PostLValue>())
Out << "\\lPostLValue\\l";
-#if 0
- // FIXME: Replace with a general scheme to determine
- // the name of the check.
- if (GraphPrintCheckerState->isImplicitNullDeref(N))
- Out << "\\|Implicit-Null Dereference.\\l";
- else if (GraphPrintCheckerState->isExplicitNullDeref(N))
- Out << "\\|Explicit-Null Dereference.\\l";
- else if (GraphPrintCheckerState->isUndefDeref(N))
- Out << "\\|Dereference of undefialied value.\\l";
- else if (GraphPrintCheckerState->isUndefStore(N))
- Out << "\\|Store to Undefined Loc.";
- else if (GraphPrintCheckerState->isUndefResult(N))
- Out << "\\|Result of operation is undefined.";
- else if (GraphPrintCheckerState->isNoReturnCall(N))
- Out << "\\|Call to function marked \"noreturn\".";
- else if (GraphPrintCheckerState->isBadCall(N))
- Out << "\\|Call to NULL/Undefined.";
- else if (GraphPrintCheckerState->isUndefArg(N))
- Out << "\\|Argument in call is undefined";
-#endif
-
break;
}
}
@@ -2749,6 +2724,40 @@ struct DOTGraphTraits<ExplodedNode*> :
ProgramStateRef state = N->getState();
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);
Out << "\\l";
diff --git a/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/lib/StaticAnalyzer/Core/ExprEngineC.cpp
index 175225ba0de2..89fab1d56af0 100644
--- a/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "clang/AST/ExprCXX.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
@@ -246,6 +247,38 @@ void ExprEngine::VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred,
getCheckerManager().runCheckersForPostStmt(Dst, Tmp, BE, *this);
}
+ProgramStateRef ExprEngine::handleLValueBitCast(
+ ProgramStateRef state, const Expr* Ex, const LocationContext* LCtx,
+ QualType T, QualType ExTy, const CastExpr* CastE, StmtNodeBuilder& Bldr,
+ ExplodedNode* Pred) {
+ // Delegate to SValBuilder to process.
+ SVal V = state->getSVal(Ex, LCtx);
+ V = svalBuilder.evalCast(V, 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);
+ Bldr.generateNode(CastE, Pred, state);
+
+ return state;
+}
+
+ProgramStateRef ExprEngine::handleLVectorSplat(
+ ProgramStateRef state, const LocationContext* LCtx, const CastExpr* CastE,
+ StmtNodeBuilder &Bldr, ExplodedNode* Pred) {
+ // Recover some path sensitivity by conjuring a new value.
+ QualType resultType = CastE->getType();
+ if (CastE->isGLValue())
+ resultType = getContext().getPointerType(resultType);
+ SVal result = svalBuilder.conjureSymbolVal(nullptr, CastE, LCtx,
+ resultType,
+ currBldrCtx->blockCount());
+ state = state->BindExpr(CastE, LCtx, result);
+ Bldr.generateNode(CastE, Pred, state);
+
+ return state;
+}
+
void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
ExplodedNode *Pred, ExplodedNodeSet &Dst) {
@@ -310,8 +343,21 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
continue;
}
case CK_MemberPointerToBoolean:
- // FIXME: For now, member pointers are represented by void *.
- // FALLTHROUGH
+ case CK_PointerToBoolean: {
+ SVal V = state->getSVal(Ex, LCtx);
+ auto PTMSV = V.getAs<nonloc::PointerToMember>();
+ if (PTMSV)
+ V = svalBuilder.makeTruthVal(!PTMSV->isNullMemberPointer(), ExTy);
+ if (V.isUndef() || PTMSV) {
+ state = state->BindExpr(CastE, LCtx, V);
+ Bldr.generateNode(CastE, Pred, state);
+ continue;
+ }
+ // Explicitly proceed with default handler for this case cascade.
+ state =
+ handleLValueBitCast(state, Ex, LCtx, T, ExTy, CastE, Bldr, Pred);
+ continue;
+ }
case CK_Dependent:
case CK_ArrayToPointerDecay:
case CK_BitCast:
@@ -319,8 +365,18 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
case CK_BooleanToSignedIntegral:
case CK_NullToPointer:
case CK_IntegralToPointer:
- case CK_PointerToIntegral:
- case CK_PointerToBoolean:
+ case CK_PointerToIntegral: {
+ SVal V = state->getSVal(Ex, LCtx);
+ if (V.getAs<nonloc::PointerToMember>()) {
+ state = state->BindExpr(CastE, LCtx, UnknownVal());
+ Bldr.generateNode(CastE, Pred, state);
+ continue;
+ }
+ // Explicitly proceed with default handler for this case cascade.
+ state =
+ handleLValueBitCast(state, Ex, LCtx, T, ExTy, CastE, Bldr, Pred);
+ continue;
+ }
case CK_IntegralToBoolean:
case CK_IntegralToFloating:
case CK_FloatingToIntegral:
@@ -341,15 +397,11 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
case CK_AnyPointerToBlockPointerCast:
case CK_ObjCObjectLValueCast:
case CK_ZeroToOCLEvent:
+ case CK_ZeroToOCLQueue:
+ case CK_IntToOCLSampler:
case CK_LValueBitCast: {
- // Delegate to SValBuilder to process.
- SVal V = state->getSVal(Ex, LCtx);
- V = svalBuilder.evalCast(V, 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);
- Bldr.generateNode(CastE, Pred, state);
+ state =
+ handleLValueBitCast(state, Ex, LCtx, T, ExTy, CastE, Bldr, Pred);
continue;
}
case CK_IntegralCast: {
@@ -385,7 +437,7 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
Failed = true;
// Else, evaluate the cast.
else
- val = getStoreManager().evalDynamicCast(val, T, Failed);
+ val = getStoreManager().attemptDownCast(val, T, Failed);
if (Failed) {
if (T->isReferenceType()) {
@@ -411,29 +463,55 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
Bldr.generateNode(CastE, Pred, state);
continue;
}
+ case CK_BaseToDerived: {
+ SVal val = state->getSVal(Ex, LCtx);
+ QualType resultType = CastE->getType();
+ if (CastE->isGLValue())
+ resultType = getContext().getPointerType(resultType);
+
+ bool Failed = false;
+
+ if (!val.isConstant()) {
+ val = getStoreManager().attemptDownCast(val, T, Failed);
+ }
+
+ // Failed to cast or the result is unknown, fall back to conservative.
+ if (Failed || val.isUnknown()) {
+ val =
+ svalBuilder.conjureSymbolVal(nullptr, CastE, LCtx, resultType,
+ currBldrCtx->blockCount());
+ }
+ state = state->BindExpr(CastE, LCtx, val);
+ Bldr.generateNode(CastE, Pred, state);
+ continue;
+ }
case CK_NullToMemberPointer: {
- // FIXME: For now, member pointers are represented by void *.
- SVal V = svalBuilder.makeNull();
+ SVal V = svalBuilder.getMemberPointer(nullptr);
state = state->BindExpr(CastE, LCtx, V);
Bldr.generateNode(CastE, Pred, state);
continue;
}
+ case CK_DerivedToBaseMemberPointer:
+ case CK_BaseToDerivedMemberPointer:
+ case CK_ReinterpretMemberPointer: {
+ SVal V = state->getSVal(Ex, LCtx);
+ if (auto PTMSV = V.getAs<nonloc::PointerToMember>()) {
+ SVal CastedPTMSV = svalBuilder.makePointerToMember(
+ getBasicVals().accumCXXBase(
+ llvm::make_range<CastExpr::path_const_iterator>(
+ CastE->path_begin(), CastE->path_end()), *PTMSV));
+ state = state->BindExpr(CastE, LCtx, CastedPTMSV);
+ Bldr.generateNode(CastE, Pred, state);
+ continue;
+ }
+ // Explicitly proceed with default handler for this case cascade.
+ state = handleLVectorSplat(state, LCtx, CastE, Bldr, Pred);
+ continue;
+ }
// Various C++ casts that are not handled yet.
case CK_ToUnion:
- case CK_BaseToDerived:
- case CK_BaseToDerivedMemberPointer:
- case CK_DerivedToBaseMemberPointer:
- case CK_ReinterpretMemberPointer:
case CK_VectorSplat: {
- // Recover some path-sensitivty by conjuring a new value.
- QualType resultType = CastE->getType();
- if (CastE->isGLValue())
- resultType = getContext().getPointerType(resultType);
- SVal result = svalBuilder.conjureSymbolVal(nullptr, CastE, LCtx,
- resultType,
- currBldrCtx->blockCount());
- state = state->BindExpr(CastE, LCtx, result);
- Bldr.generateNode(CastE, Pred, state);
+ state = handleLVectorSplat(state, LCtx, CastE, Bldr, Pred);
continue;
}
}
@@ -458,15 +536,7 @@ void ExprEngine::VisitCompoundLiteralExpr(const CompoundLiteralExpr *CL,
Loc CLLoc = State->getLValue(CL, LCtx);
State = State->bindLoc(CLLoc, V);
- // Compound literal expressions are a GNU extension in C++.
- // Unlike in C, where CLs are lvalues, in C++ CLs are prvalues,
- // and like temporary objects created by the functional notation T()
- // CLs are destroyed at the end of the containing full-expression.
- // HOWEVER, an rvalue of array type is not something the analyzer can
- // reason about, since we expect all regions to be wrapped in Locs.
- // So we treat array CLs as lvalues as well, knowing that they will decay
- // to pointers as soon as they are used.
- if (CL->isGLValue() || CL->getType()->isArrayType())
+ if (CL->isGLValue())
V = CLLoc;
}
@@ -596,23 +666,13 @@ void ExprEngine::VisitLogicalExpr(const BinaryOperator* B, ExplodedNode *Pred,
if (RHSVal.isUndef()) {
X = RHSVal;
} else {
- DefinedOrUnknownSVal DefinedRHS = RHSVal.castAs<DefinedOrUnknownSVal>();
- ProgramStateRef StTrue, StFalse;
- std::tie(StTrue, StFalse) = N->getState()->assume(DefinedRHS);
- if (StTrue) {
- if (StFalse) {
- // We can't constrain the value to 0 or 1.
- // The best we can do is a cast.
- X = getSValBuilder().evalCast(RHSVal, B->getType(), RHS->getType());
- } else {
- // The value is known to be true.
- X = getSValBuilder().makeIntVal(1, B->getType());
- }
- } else {
- // The value is known to be false.
- assert(StFalse && "Infeasible path!");
- X = getSValBuilder().makeIntVal(0, B->getType());
- }
+ // We evaluate "RHSVal != 0" expression which result in 0 if the value is
+ // known to be false, 1 if the value is known to be true and a new symbol
+ // when the assumption is unknown.
+ nonloc::ConcreteInt Zero(getBasicVals().getValue(0, B->getType()));
+ X = evalBinOp(N->getState(), BO_NE,
+ svalBuilder.evalCast(RHSVal, B->getType(), RHS->getType()),
+ Zero, B->getType());
}
}
Bldr.generateNode(B, Pred, state->BindExpr(B, Pred->getLocationContext(), X));
@@ -644,7 +704,7 @@ void ExprEngine::VisitInitListExpr(const InitListExpr *IE,
for (InitListExpr::const_reverse_iterator it = IE->rbegin(),
ei = IE->rend(); it != ei; ++it) {
SVal V = state->getSVal(cast<Expr>(*it), LCtx);
- vals = getBasicVals().consVals(V, vals);
+ vals = getBasicVals().prependSVal(V, vals);
}
B.generateNode(IE, Pred,
@@ -789,8 +849,24 @@ VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Ex,
getCheckerManager().runCheckersForPostStmt(Dst, EvalSet, Ex, *this);
}
-void ExprEngine::VisitUnaryOperator(const UnaryOperator* U,
- ExplodedNode *Pred,
+void ExprEngine::handleUOExtension(ExplodedNodeSet::iterator I,
+ const UnaryOperator *U,
+ StmtNodeBuilder &Bldr) {
+ // FIXME: We can probably just have some magic in Environment::getSVal()
+ // that propagates values, instead of creating a new node here.
+ //
+ // Unary "+" is a no-op, similar to a parentheses. We still have places
+ // where it may be a block-level expression, so we need to
+ // generate an extra node that just propagates the value of the
+ // subexpression.
+ const Expr *Ex = U->getSubExpr()->IgnoreParens();
+ ProgramStateRef state = (*I)->getState();
+ const LocationContext *LCtx = (*I)->getLocationContext();
+ Bldr.generateNode(U, *I, state->BindExpr(U, LCtx,
+ state->getSVal(Ex, LCtx)));
+}
+
+void ExprEngine::VisitUnaryOperator(const UnaryOperator* U, ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
// FIXME: Prechecks eventually go in ::Visit().
ExplodedNodeSet CheckedSet;
@@ -842,24 +918,30 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U,
break;
}
+ case UO_AddrOf: {
+ // Process pointer-to-member address operation.
+ const Expr *Ex = U->getSubExpr()->IgnoreParens();
+ if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Ex)) {
+ const ValueDecl *VD = DRE->getDecl();
+
+ if (isa<CXXMethodDecl>(VD) || isa<FieldDecl>(VD)) {
+ ProgramStateRef State = (*I)->getState();
+ const LocationContext *LCtx = (*I)->getLocationContext();
+ SVal SV = svalBuilder.getMemberPointer(cast<DeclaratorDecl>(VD));
+ Bldr.generateNode(U, *I, State->BindExpr(U, LCtx, SV));
+ break;
+ }
+ }
+ // Explicitly proceed with default handler for this case cascade.
+ handleUOExtension(I, U, Bldr);
+ break;
+ }
case UO_Plus:
assert(!U->isGLValue());
// FALL-THROUGH.
case UO_Deref:
- case UO_AddrOf:
case UO_Extension: {
- // FIXME: We can probably just have some magic in Environment::getSVal()
- // that propagates values, instead of creating a new node here.
- //
- // Unary "+" is a no-op, similar to a parentheses. We still have places
- // where it may be a block-level expression, so we need to
- // generate an extra node that just propagates the value of the
- // subexpression.
- const Expr *Ex = U->getSubExpr()->IgnoreParens();
- ProgramStateRef state = (*I)->getState();
- const LocationContext *LCtx = (*I)->getLocationContext();
- Bldr.generateNode(U, *I, state->BindExpr(U, LCtx,
- state->getSVal(Ex, LCtx)));
+ handleUOExtension(I, U, Bldr);
break;
}
diff --git a/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
index 556e2239abfb..7e9b2033ca37 100644
--- a/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -65,7 +65,7 @@ void ExprEngine::performTrivialCopy(NodeBuilder &Bldr, ExplodedNode *Pred,
if (Optional<Loc> L = V.getAs<Loc>())
V = Pred->getState()->getSVal(*L);
else
- assert(V.isUnknown());
+ assert(V.isUnknownOrUndef());
const Expr *CallExpr = Call.getOriginExpr();
evalBind(Dst, CallExpr, Pred, ThisVal, V, true);
@@ -346,6 +346,30 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE,
defaultEvalCall(Bldr, *I, *Call);
}
+ // If the CFG was contructed 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
+ // in the CFG, would be called at the end of the full expression or
+ // later (for life-time extended temporaries) -- but avoids infeasible
+ // 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()) {
+
+ for (ExplodedNode *N : DstEvaluated) {
+ Bldr.generateSink(CE, N, N->getState());
+ }
+
+ // There is no need to run the PostCall and PostStmtchecker
+ // callbacks because we just generated sinks on all nodes in th
+ // frontier.
+ return;
+ }
+ }
+
ExplodedNodeSet DstPostCall;
getCheckerManager().runCheckersForPostCall(DstPostCall, DstEvaluated,
*Call, *this);
@@ -578,9 +602,9 @@ void ExprEngine::VisitLambdaExpr(const LambdaExpr *LE, ExplodedNode *Pred,
const MemRegion *R = svalBuilder.getRegionManager().getCXXTempObjectRegion(
LE, LocCtxt);
SVal V = loc::MemRegionVal(R);
-
+
ProgramStateRef State = Pred->getState();
-
+
// If we created a new MemRegion for the lambda, we should explicitly bind
// the captures.
CXXRecordDecl::field_iterator CurField = LE->getLambdaClass()->field_begin();
diff --git a/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp b/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
index 3a18956e4139..f157c3dd6ce2 100644
--- a/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
+++ b/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
@@ -152,13 +152,30 @@ void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D,
}
// Process the path.
- unsigned n = path.size();
- unsigned max = n;
-
- for (PathPieces::const_reverse_iterator I = path.rbegin(),
- E = path.rend();
- I != E; ++I, --n)
- HandlePiece(R, FID, **I, n, max);
+ // Maintain the counts of extra note pieces separately.
+ unsigned TotalPieces = path.size();
+ unsigned TotalNotePieces =
+ std::count_if(path.begin(), path.end(),
+ [](const IntrusiveRefCntPtr<PathDiagnosticPiece> &p) {
+ return isa<PathDiagnosticNotePiece>(p.get());
+ });
+
+ unsigned TotalRegularPieces = TotalPieces - TotalNotePieces;
+ unsigned NumRegularPieces = TotalRegularPieces;
+ unsigned NumNotePieces = TotalNotePieces;
+
+ for (auto I = path.rbegin(), E = path.rend(); I != E; ++I) {
+ if (isa<PathDiagnosticNotePiece>(I->get())) {
+ // This adds diagnostic bubbles, but not navigation.
+ // Navigation through note pieces would be added later,
+ // as a separate pass through the piece list.
+ HandlePiece(R, FID, **I, NumNotePieces, TotalNotePieces);
+ --NumNotePieces;
+ } else {
+ HandlePiece(R, FID, **I, NumRegularPieces, TotalRegularPieces);
+ --NumRegularPieces;
+ }
+ }
// Add line numbers, header, footer, etc.
@@ -192,24 +209,38 @@ void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D,
int ColumnNumber = path.back()->getLocation().asLocation().getExpansionColumnNumber();
// Add the name of the file as an <h1> tag.
-
{
std::string s;
llvm::raw_string_ostream os(s);
os << "<!-- REPORTHEADER -->\n"
- << "<h3>Bug Summary</h3>\n<table class=\"simpletable\">\n"
+ << "<h3>Bug Summary</h3>\n<table class=\"simpletable\">\n"
"<tr><td class=\"rowname\">File:</td><td>"
- << html::EscapeText(DirName)
- << html::EscapeText(Entry->getName())
- << "</td></tr>\n<tr><td class=\"rowname\">Location:</td><td>"
- "<a href=\"#EndPath\">line "
- << LineNumber
- << ", column "
- << ColumnNumber
- << "</a></td></tr>\n"
- "<tr><td class=\"rowname\">Description:</td><td>"
- << D.getVerboseDescription() << "</td></tr>\n";
+ << html::EscapeText(DirName)
+ << html::EscapeText(Entry->getName())
+ << "</td></tr>\n<tr><td class=\"rowname\">Warning:</td><td>"
+ "<a href=\"#EndPath\">line "
+ << LineNumber
+ << ", column "
+ << ColumnNumber
+ << "</a><br />"
+ << D.getVerboseDescription() << "</td></tr>\n";
+
+ // The navigation across the extra notes pieces.
+ unsigned NumExtraPieces = 0;
+ for (const auto &Piece : path) {
+ if (const auto *P = dyn_cast<PathDiagnosticNotePiece>(Piece.get())) {
+ int LineNumber =
+ P->getLocation().asLocation().getExpansionLineNumber();
+ int ColumnNumber =
+ P->getLocation().asLocation().getExpansionColumnNumber();
+ os << "<tr><td class=\"rowname\">Note:</td><td>"
+ << "<a href=\"#Note" << NumExtraPieces << "\">line "
+ << LineNumber << ", column " << ColumnNumber << "</a><br />"
+ << P->getString() << "</td></tr>";
+ ++NumExtraPieces;
+ }
+ }
// Output any other meta data.
@@ -385,13 +416,20 @@ void HTMLDiagnostics::HandlePiece(Rewriter& R, FileID BugFileID,
// Create the html for the message.
const char *Kind = nullptr;
+ bool IsNote = false;
+ bool SuppressIndex = (max == 1);
switch (P.getKind()) {
case PathDiagnosticPiece::Call:
- llvm_unreachable("Calls should already be handled");
+ llvm_unreachable("Calls and extra notes should already be handled");
case PathDiagnosticPiece::Event: Kind = "Event"; break;
case PathDiagnosticPiece::ControlFlow: Kind = "Control"; break;
// Setting Kind to "Control" is intentional.
case PathDiagnosticPiece::Macro: Kind = "Control"; break;
+ case PathDiagnosticPiece::Note:
+ Kind = "Note";
+ IsNote = true;
+ SuppressIndex = true;
+ break;
}
std::string sbuf;
@@ -399,7 +437,9 @@ void HTMLDiagnostics::HandlePiece(Rewriter& R, FileID BugFileID,
os << "\n<tr><td class=\"num\"></td><td class=\"line\"><div id=\"";
- if (num == max)
+ if (IsNote)
+ os << "Note" << num;
+ else if (num == max)
os << "EndPath";
else
os << "Path" << num;
@@ -461,7 +501,7 @@ void HTMLDiagnostics::HandlePiece(Rewriter& R, FileID BugFileID,
os << "\">";
- if (max > 1) {
+ if (!SuppressIndex) {
os << "<table class=\"msgT\"><tr><td valign=\"top\">";
os << "<div class=\"PathIndex";
if (Kind) os << " PathIndex" << Kind;
@@ -501,7 +541,7 @@ void HTMLDiagnostics::HandlePiece(Rewriter& R, FileID BugFileID,
os << "':\n";
- if (max > 1) {
+ if (!SuppressIndex) {
os << "</td>";
if (num < max) {
os << "<td><div class=\"PathNav\"><a href=\"#";
@@ -523,7 +563,7 @@ void HTMLDiagnostics::HandlePiece(Rewriter& R, FileID BugFileID,
else {
os << html::EscapeText(P.getString());
- if (max > 1) {
+ if (!SuppressIndex) {
os << "</td>";
if (num < max) {
os << "<td><div class=\"PathNav\"><a href=\"#";
diff --git a/lib/StaticAnalyzer/Core/IssueHash.cpp b/lib/StaticAnalyzer/Core/IssueHash.cpp
index bd5c81179adc..abdea88b1db6 100644
--- a/lib/StaticAnalyzer/Core/IssueHash.cpp
+++ b/lib/StaticAnalyzer/Core/IssueHash.cpp
@@ -13,7 +13,6 @@
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Lex/Lexer.h"
-#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
diff --git a/lib/StaticAnalyzer/Core/MemRegion.cpp b/lib/StaticAnalyzer/Core/MemRegion.cpp
index b7b6f42b2910..c4ba2ae199f8 100644
--- a/lib/StaticAnalyzer/Core/MemRegion.cpp
+++ b/lib/StaticAnalyzer/Core/MemRegion.cpp
@@ -31,28 +31,6 @@ using namespace ento;
// MemRegion Construction.
//===----------------------------------------------------------------------===//
-template<typename RegionTy> struct MemRegionManagerTrait;
-
-template <typename RegionTy, typename A1>
-RegionTy* MemRegionManager::getRegion(const A1 a1) {
- const typename MemRegionManagerTrait<RegionTy>::SuperRegionTy *superRegion =
- MemRegionManagerTrait<RegionTy>::getSuperRegion(*this, a1);
-
- llvm::FoldingSetNodeID ID;
- RegionTy::ProfileRegion(ID, a1, superRegion);
- void *InsertPos;
- RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID,
- InsertPos));
-
- if (!R) {
- R = A.Allocate<RegionTy>();
- new (R) RegionTy(a1, superRegion);
- Regions.InsertNode(R, InsertPos);
- }
-
- return R;
-}
-
template <typename RegionTy, typename A1>
RegionTy* MemRegionManager::getSubRegion(const A1 a1,
const MemRegion *superRegion) {
@@ -72,26 +50,6 @@ RegionTy* MemRegionManager::getSubRegion(const A1 a1,
}
template <typename RegionTy, typename A1, typename A2>
-RegionTy* MemRegionManager::getRegion(const A1 a1, const A2 a2) {
- const typename MemRegionManagerTrait<RegionTy>::SuperRegionTy *superRegion =
- MemRegionManagerTrait<RegionTy>::getSuperRegion(*this, a1, a2);
-
- llvm::FoldingSetNodeID ID;
- RegionTy::ProfileRegion(ID, a1, a2, superRegion);
- void *InsertPos;
- RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID,
- InsertPos));
-
- if (!R) {
- R = A.Allocate<RegionTy>();
- new (R) RegionTy(a1, a2, superRegion);
- Regions.InsertNode(R, InsertPos);
- }
-
- return R;
-}
-
-template <typename RegionTy, typename A1, typename A2>
RegionTy* MemRegionManager::getSubRegion(const A1 a1, const A2 a2,
const MemRegion *superRegion) {
llvm::FoldingSetNodeID ID;
diff --git a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
index 217d628a129c..5675cb2026f0 100644
--- a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
+++ b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
@@ -60,6 +60,7 @@ PathDiagnosticEventPiece::~PathDiagnosticEventPiece() {}
PathDiagnosticCallPiece::~PathDiagnosticCallPiece() {}
PathDiagnosticControlFlowPiece::~PathDiagnosticControlFlowPiece() {}
PathDiagnosticMacroPiece::~PathDiagnosticMacroPiece() {}
+PathDiagnosticNotePiece::~PathDiagnosticNotePiece() {}
void PathPieces::flattenTo(PathPieces &Primary, PathPieces &Current,
bool ShouldFlattenMacros) const {
@@ -95,6 +96,7 @@ void PathPieces::flattenTo(PathPieces &Primary, PathPieces &Current,
}
case PathDiagnosticPiece::Event:
case PathDiagnosticPiece::ControlFlow:
+ case PathDiagnosticPiece::Note:
Current.push_back(Piece);
break;
}
@@ -211,6 +213,12 @@ void PathDiagnosticConsumer::HandlePathDiagnostic(
const SourceManager &SMgr = D->path.front()->getLocation().getManager();
SmallVector<const PathPieces *, 5> WorkList;
WorkList.push_back(&D->path);
+ SmallString<128> buf;
+ llvm::raw_svector_ostream warning(buf);
+ warning << "warning: Path diagnostic report is not generated. Current "
+ << "output format does not support diagnostics that cross file "
+ << "boundaries. Refer to --analyzer-output for valid output "
+ << "formats\n";
while (!WorkList.empty()) {
const PathPieces &path = *WorkList.pop_back_val();
@@ -222,19 +230,25 @@ void PathDiagnosticConsumer::HandlePathDiagnostic(
if (FID.isInvalid()) {
FID = SMgr.getFileID(L);
- } else if (SMgr.getFileID(L) != FID)
- return; // FIXME: Emit a warning?
+ } else if (SMgr.getFileID(L) != FID) {
+ llvm::errs() << warning.str();
+ return;
+ }
// 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());
- if (!L.isFileID() || SMgr.getFileID(L) != FID)
- return; // FIXME: Emit a warning?
+ if (!L.isFileID() || SMgr.getFileID(L) != FID) {
+ llvm::errs() << warning.str();
+ return;
+ }
L = SMgr.getExpansionLoc(I->getEnd());
- if (!L.isFileID() || SMgr.getFileID(L) != FID)
- return; // FIXME: Emit a warning?
+ if (!L.isFileID() || SMgr.getFileID(L) != FID) {
+ llvm::errs() << warning.str();
+ return;
+ }
}
if (const PathDiagnosticCallPiece *call =
@@ -342,15 +356,16 @@ static Optional<bool> comparePiece(const PathDiagnosticPiece &X,
}
switch (X.getKind()) {
- case clang::ento::PathDiagnosticPiece::ControlFlow:
+ case PathDiagnosticPiece::ControlFlow:
return compareControlFlow(cast<PathDiagnosticControlFlowPiece>(X),
cast<PathDiagnosticControlFlowPiece>(Y));
- case clang::ento::PathDiagnosticPiece::Event:
+ case PathDiagnosticPiece::Event:
+ case PathDiagnosticPiece::Note:
return None;
- case clang::ento::PathDiagnosticPiece::Macro:
+ case PathDiagnosticPiece::Macro:
return compareMacro(cast<PathDiagnosticMacroPiece>(X),
cast<PathDiagnosticMacroPiece>(Y));
- case clang::ento::PathDiagnosticPiece::Call:
+ case PathDiagnosticPiece::Call:
return compareCall(cast<PathDiagnosticCallPiece>(X),
cast<PathDiagnosticCallPiece>(Y));
}
@@ -1098,6 +1113,10 @@ void PathDiagnosticMacroPiece::Profile(llvm::FoldingSetNodeID &ID) const {
ID.Add(**I);
}
+void PathDiagnosticNotePiece::Profile(llvm::FoldingSetNodeID &ID) const {
+ PathDiagnosticSpotPiece::Profile(ID);
+}
+
void PathDiagnostic::Profile(llvm::FoldingSetNodeID &ID) const {
ID.Add(getLocation());
ID.AddString(BugType);
diff --git a/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp b/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
index 8ad931acdf7f..c5263ee0e5ca 100644
--- a/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
+++ b/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
@@ -19,7 +19,6 @@
#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
#include "clang/StaticAnalyzer/Core/IssueHash.h"
#include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h"
-#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Casting.h"
using namespace clang;
@@ -282,6 +281,9 @@ static void ReportPiece(raw_ostream &o,
ReportMacro(o, cast<PathDiagnosticMacroPiece>(P), FM, SM, LangOpts,
indent, depth);
break;
+ case PathDiagnosticPiece::Note:
+ // FIXME: Extend the plist format to support those.
+ break;
}
}
@@ -298,40 +300,42 @@ void PlistDiagnostics::FlushDiagnosticsImpl(
SM = &Diags.front()->path.front()->getLocation().getManager();
- for (std::vector<const PathDiagnostic*>::iterator DI = Diags.begin(),
- DE = Diags.end(); DI != DE; ++DI) {
+ auto AddPieceFID = [&FM, &Fids, SM](const PathDiagnosticPiece *Piece)->void {
+ AddFID(FM, Fids, *SM, Piece->getLocation().asLocation());
+ ArrayRef<SourceRange> Ranges = Piece->getRanges();
+ for (const SourceRange &Range : Ranges) {
+ AddFID(FM, Fids, *SM, Range.getBegin());
+ AddFID(FM, Fids, *SM, Range.getEnd());
+ }
+ };
- const PathDiagnostic *D = *DI;
+ for (const PathDiagnostic *D : Diags) {
SmallVector<const PathPieces *, 5> WorkList;
WorkList.push_back(&D->path);
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();
- AddFID(FM, Fids, *SM, piece->getLocation().asLocation());
- ArrayRef<SourceRange> Ranges = piece->getRanges();
- for (ArrayRef<SourceRange>::iterator I = Ranges.begin(),
- E = Ranges.end(); I != E; ++I) {
- AddFID(FM, Fids, *SM, I->getBegin());
- AddFID(FM, Fids, *SM, I->getEnd());
- }
+ const PathPieces &Path = *WorkList.pop_back_val();
+
+ for (const auto &Iter : Path) {
+ const PathDiagnosticPiece *Piece = Iter.get();
+ AddPieceFID(Piece);
+
+ if (const PathDiagnosticCallPiece *Call =
+ dyn_cast<PathDiagnosticCallPiece>(Piece)) {
+ if (IntrusiveRefCntPtr<PathDiagnosticEventPiece>
+ CallEnterWithin = Call->getCallEnterWithinCallerEvent())
+ AddPieceFID(CallEnterWithin.get());
- if (const PathDiagnosticCallPiece *call =
- dyn_cast<PathDiagnosticCallPiece>(piece)) {
- IntrusiveRefCntPtr<PathDiagnosticEventPiece>
- callEnterWithin = call->getCallEnterWithinCallerEvent();
- if (callEnterWithin)
- AddFID(FM, Fids, *SM, callEnterWithin->getLocation().asLocation());
+ if (IntrusiveRefCntPtr<PathDiagnosticEventPiece>
+ CallEnterEvent = Call->getCallEnterEvent())
+ AddPieceFID(CallEnterEvent.get());
- WorkList.push_back(&call->path);
+ WorkList.push_back(&Call->path);
}
- else if (const PathDiagnosticMacroPiece *macro =
- dyn_cast<PathDiagnosticMacroPiece>(piece)) {
- WorkList.push_back(&macro->subPieces);
+ else if (const PathDiagnosticMacroPiece *Macro =
+ dyn_cast<PathDiagnosticMacroPiece>(Piece)) {
+ WorkList.push_back(&Macro->subPieces);
}
}
}
diff --git a/lib/StaticAnalyzer/Core/ProgramState.cpp b/lib/StaticAnalyzer/Core/ProgramState.cpp
index adda7af08db8..03ace35965cb 100644
--- a/lib/StaticAnalyzer/Core/ProgramState.cpp
+++ b/lib/StaticAnalyzer/Core/ProgramState.cpp
@@ -527,32 +527,17 @@ bool ScanReachableSymbols::scan(nonloc::CompoundVal val) {
}
bool ScanReachableSymbols::scan(const SymExpr *sym) {
- bool wasVisited = !visited.insert(sym).second;
- if (wasVisited)
- return true;
-
- if (!visitor.VisitSymbol(sym))
- return false;
+ for (SymExpr::symbol_iterator SI = sym->symbol_begin(),
+ SE = sym->symbol_end();
+ SI != SE; ++SI) {
+ bool wasVisited = !visited.insert(*SI).second;
+ if (wasVisited)
+ continue;
- // TODO: should be rewritten using SymExpr::symbol_iterator.
- switch (sym->getKind()) {
- case SymExpr::SymbolRegionValueKind:
- case SymExpr::SymbolConjuredKind:
- case SymExpr::SymbolDerivedKind:
- case SymExpr::SymbolExtentKind:
- case SymExpr::SymbolMetadataKind:
- break;
- case SymExpr::SymbolCastKind:
- return scan(cast<SymbolCast>(sym)->getOperand());
- case SymExpr::SymIntExprKind:
- return scan(cast<SymIntExpr>(sym)->getLHS());
- case SymExpr::IntSymExprKind:
- return scan(cast<IntSymExpr>(sym)->getRHS());
- case SymExpr::SymSymExprKind: {
- const SymSymExpr *x = cast<SymSymExpr>(sym);
- return scan(x->getLHS()) && scan(x->getRHS());
- }
+ if (!visitor.VisitSymbol(*SI))
+ return false;
}
+
return true;
}
diff --git a/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp b/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
index 77b0ad32b6b7..15073bb82b36 100644
--- a/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
+++ b/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
@@ -18,7 +18,6 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/ImmutableSet.h"
-#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
@@ -28,22 +27,17 @@ using namespace ento;
/// 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*> {
+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) {
+ : 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 &From() const { return *first; }
+ const llvm::APSInt &To() const { return *second; }
const llvm::APSInt *getConcreteValue() const {
return &From() == &To() ? &From() : nullptr;
}
@@ -54,7 +48,6 @@ public:
}
};
-
class RangeTrait : public llvm::ImutContainerInfo<Range> {
public:
// When comparing if one Range is less than another, we should compare
@@ -62,8 +55,8 @@ public:
// 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);
+ return *lhs.first < *rhs.first ||
+ (!(*rhs.first < *lhs.first) && *lhs.second < *rhs.second);
}
};
@@ -97,7 +90,7 @@ public:
/// 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))) {}
+ : ranges(F.add(F.getEmptySet(), Range(from, to))) {}
/// Profile - Generates a hash profile of this RangeSet for use
/// by FoldingSet.
@@ -106,16 +99,14 @@ public:
/// 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 {
+ 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,
+ 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.
@@ -135,8 +126,8 @@ private:
if (i->Includes(Lower)) {
if (i->Includes(Upper)) {
- newRanges = F.add(newRanges, Range(BV.getValue(Lower),
- BV.getValue(Upper)));
+ newRanges =
+ F.add(newRanges, Range(BV.getValue(Lower), BV.getValue(Upper)));
break;
} else
newRanges = F.add(newRanges, Range(BV.getValue(Lower), i->To()));
@@ -244,8 +235,8 @@ public:
// 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 {
+ RangeSet Intersect(BasicValueFactory &BV, Factory &F, llvm::APSInt Lower,
+ llvm::APSInt Upper) const {
if (!pin(Lower, Upper))
return F.getEmptySet();
@@ -291,53 +282,54 @@ REGISTER_TRAIT_WITH_PROGRAMSTATE(ConstraintRange,
RangeSet))
namespace {
-class RangeConstraintManager : public SimpleConstraintManager{
- RangeSet GetRange(ProgramStateRef state, SymbolRef sym);
+class RangeConstraintManager : public SimpleConstraintManager {
+ RangeSet getRange(ProgramStateRef State, SymbolRef Sym);
+
public:
- RangeConstraintManager(SubEngine *subengine, SValBuilder &SVB)
- : SimpleConstraintManager(subengine, SVB) {}
+ RangeConstraintManager(SubEngine *SE, SValBuilder &SVB)
+ : SimpleConstraintManager(SE, SVB) {}
- ProgramStateRef assumeSymNE(ProgramStateRef state, SymbolRef sym,
- const llvm::APSInt& Int,
- const llvm::APSInt& Adjustment) override;
+ ProgramStateRef assumeSymNE(ProgramStateRef State, SymbolRef Sym,
+ const llvm::APSInt &V,
+ const llvm::APSInt &Adjustment) override;
- ProgramStateRef assumeSymEQ(ProgramStateRef state, SymbolRef sym,
- const llvm::APSInt& Int,
- const llvm::APSInt& Adjustment) override;
+ ProgramStateRef assumeSymEQ(ProgramStateRef State, SymbolRef Sym,
+ const llvm::APSInt &V,
+ const llvm::APSInt &Adjustment) override;
- ProgramStateRef assumeSymLT(ProgramStateRef state, SymbolRef sym,
- const llvm::APSInt& Int,
- const llvm::APSInt& Adjustment) override;
+ ProgramStateRef assumeSymLT(ProgramStateRef State, SymbolRef Sym,
+ const llvm::APSInt &V,
+ const llvm::APSInt &Adjustment) override;
- ProgramStateRef assumeSymGT(ProgramStateRef state, SymbolRef sym,
- const llvm::APSInt& Int,
- const llvm::APSInt& Adjustment) override;
+ ProgramStateRef assumeSymGT(ProgramStateRef State, SymbolRef Sym,
+ const llvm::APSInt &V,
+ const llvm::APSInt &Adjustment) override;
- ProgramStateRef assumeSymGE(ProgramStateRef state, SymbolRef sym,
- const llvm::APSInt& Int,
- const llvm::APSInt& Adjustment) override;
+ ProgramStateRef assumeSymLE(ProgramStateRef State, SymbolRef Sym,
+ const llvm::APSInt &V,
+ const llvm::APSInt &Adjustment) override;
- ProgramStateRef assumeSymLE(ProgramStateRef state, SymbolRef sym,
- const llvm::APSInt& Int,
- const llvm::APSInt& Adjustment) override;
+ ProgramStateRef assumeSymGE(ProgramStateRef State, SymbolRef Sym,
+ const llvm::APSInt &V,
+ const llvm::APSInt &Adjustment) override;
ProgramStateRef assumeSymbolWithinInclusiveRange(
- ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From,
- const llvm::APSInt &To, const llvm::APSInt &Adjustment) override;
+ ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From,
+ const llvm::APSInt &To, const llvm::APSInt &Adjustment) override;
ProgramStateRef assumeSymbolOutOfInclusiveRange(
- ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From,
- const llvm::APSInt &To, const llvm::APSInt &Adjustment) override;
+ ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From,
+ const llvm::APSInt &To, const llvm::APSInt &Adjustment) override;
- const llvm::APSInt* getSymVal(ProgramStateRef St,
- SymbolRef sym) const override;
+ const llvm::APSInt *getSymVal(ProgramStateRef St,
+ SymbolRef Sym) const override;
ConditionTruthVal checkNull(ProgramStateRef State, SymbolRef Sym) override;
ProgramStateRef removeDeadBindings(ProgramStateRef St,
- SymbolReaper& SymReaper) override;
+ SymbolReaper &SymReaper) override;
- void print(ProgramStateRef St, raw_ostream &Out,
- const char* nl, const char *sep) override;
+ void print(ProgramStateRef St, raw_ostream &Out, const char *nl,
+ const char *sep) override;
private:
RangeSet::Factory F;
@@ -364,9 +356,9 @@ ento::CreateRangeConstraintManager(ProgramStateManager &StMgr, SubEngine *Eng) {
return llvm::make_unique<RangeConstraintManager>(Eng, StMgr.getSValBuilder());
}
-const llvm::APSInt* RangeConstraintManager::getSymVal(ProgramStateRef St,
- SymbolRef sym) const {
- const ConstraintRangeTy::data_type *T = St->get<ConstraintRange>(sym);
+const llvm::APSInt *RangeConstraintManager::getSymVal(ProgramStateRef St,
+ SymbolRef Sym) const {
+ const ConstraintRangeTy::data_type *T = St->get<ConstraintRange>(Sym);
return T ? T->getConcreteValue() : nullptr;
}
@@ -397,30 +389,32 @@ ConditionTruthVal RangeConstraintManager::checkNull(ProgramStateRef State,
/// Scan all symbols referenced by the constraints. If the symbol is not alive
/// as marked in LSymbols, mark it as dead in DSymbols.
ProgramStateRef
-RangeConstraintManager::removeDeadBindings(ProgramStateRef state,
- SymbolReaper& SymReaper) {
-
- ConstraintRangeTy CR = state->get<ConstraintRange>();
- ConstraintRangeTy::Factory& CRFactory = state->get_context<ConstraintRange>();
+RangeConstraintManager::removeDeadBindings(ProgramStateRef State,
+ SymbolReaper &SymReaper) {
+ bool Changed = false;
+ ConstraintRangeTy CR = State->get<ConstraintRange>();
+ ConstraintRangeTy::Factory &CRFactory = State->get_context<ConstraintRange>();
for (ConstraintRangeTy::iterator I = CR.begin(), E = CR.end(); I != E; ++I) {
- SymbolRef sym = I.getKey();
- if (SymReaper.maybeDead(sym))
- CR = CRFactory.remove(CR, sym);
+ SymbolRef Sym = I.getKey();
+ if (SymReaper.maybeDead(Sym)) {
+ Changed = true;
+ CR = CRFactory.remove(CR, Sym);
+ }
}
- return state->set<ConstraintRange>(CR);
+ return Changed ? State->set<ConstraintRange>(CR) : State;
}
-RangeSet
-RangeConstraintManager::GetRange(ProgramStateRef state, SymbolRef sym) {
- if (ConstraintRangeTy::data_type* V = state->get<ConstraintRange>(sym))
+RangeSet RangeConstraintManager::getRange(ProgramStateRef State,
+ SymbolRef Sym) {
+ if (ConstraintRangeTy::data_type *V = State->get<ConstraintRange>(Sym))
return *V;
// Lazily generate a new RangeSet representing all possible values for the
// given symbol type.
BasicValueFactory &BV = getBasicVals();
- QualType T = sym->getType();
+ QualType T = Sym->getType();
RangeSet Result(F, BV.getMinValue(T), BV.getMaxValue(T));
@@ -428,7 +422,7 @@ RangeConstraintManager::GetRange(ProgramStateRef state, SymbolRef sym) {
if (T->isReferenceType()) {
APSIntType IntType = BV.getAPSIntType(T);
Result = Result.Intersect(BV, F, ++IntType.getZeroValue(),
- --IntType.getZeroValue());
+ --IntType.getZeroValue());
}
return Result;
@@ -462,7 +456,7 @@ RangeConstraintManager::assumeSymNE(ProgramStateRef St, SymbolRef Sym,
// [Int-Adjustment+1, Int-Adjustment-1]
// Notice that the lower bound is greater than the upper bound.
- RangeSet New = GetRange(St, Sym).Intersect(getBasicVals(), F, Upper, Lower);
+ RangeSet New = getRange(St, Sym).Intersect(getBasicVals(), F, Upper, Lower);
return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New);
}
@@ -477,7 +471,7 @@ RangeConstraintManager::assumeSymEQ(ProgramStateRef St, SymbolRef Sym,
// [Int-Adjustment, Int-Adjustment]
llvm::APSInt AdjInt = AdjustmentType.convert(Int) - Adjustment;
- RangeSet New = GetRange(St, Sym).Intersect(getBasicVals(), F, AdjInt, AdjInt);
+ RangeSet New = getRange(St, Sym).Intersect(getBasicVals(), F, AdjInt, AdjInt);
return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New);
}
@@ -493,7 +487,7 @@ RangeSet RangeConstraintManager::getSymLTRange(ProgramStateRef St,
case APSIntType::RTR_Within:
break;
case APSIntType::RTR_Above:
- return GetRange(St, Sym);
+ return getRange(St, Sym);
}
// Special case for Int == Min. This is always false.
@@ -506,7 +500,7 @@ RangeSet RangeConstraintManager::getSymLTRange(ProgramStateRef St,
llvm::APSInt Upper = ComparisonVal - Adjustment;
--Upper;
- return GetRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper);
+ return getRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper);
}
ProgramStateRef
@@ -517,15 +511,15 @@ RangeConstraintManager::assumeSymLT(ProgramStateRef St, SymbolRef Sym,
return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New);
}
-RangeSet
-RangeConstraintManager::getSymGTRange(ProgramStateRef St, SymbolRef Sym,
- const llvm::APSInt &Int,
- const llvm::APSInt &Adjustment) {
+RangeSet RangeConstraintManager::getSymGTRange(ProgramStateRef St,
+ SymbolRef Sym,
+ const llvm::APSInt &Int,
+ const llvm::APSInt &Adjustment) {
// Before we do any real work, see if the value can even show up.
APSIntType AdjustmentType(Adjustment);
switch (AdjustmentType.testInRange(Int, true)) {
case APSIntType::RTR_Below:
- return GetRange(St, Sym);
+ return getRange(St, Sym);
case APSIntType::RTR_Within:
break;
case APSIntType::RTR_Above:
@@ -542,7 +536,7 @@ RangeConstraintManager::getSymGTRange(ProgramStateRef St, SymbolRef Sym,
llvm::APSInt Upper = Max - Adjustment;
++Lower;
- return GetRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper);
+ return getRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper);
}
ProgramStateRef
@@ -553,15 +547,15 @@ RangeConstraintManager::assumeSymGT(ProgramStateRef St, SymbolRef Sym,
return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New);
}
-RangeSet
-RangeConstraintManager::getSymGERange(ProgramStateRef St, SymbolRef Sym,
- const llvm::APSInt &Int,
- const llvm::APSInt &Adjustment) {
+RangeSet RangeConstraintManager::getSymGERange(ProgramStateRef St,
+ SymbolRef Sym,
+ const llvm::APSInt &Int,
+ const llvm::APSInt &Adjustment) {
// Before we do any real work, see if the value can even show up.
APSIntType AdjustmentType(Adjustment);
switch (AdjustmentType.testInRange(Int, true)) {
case APSIntType::RTR_Below:
- return GetRange(St, Sym);
+ return getRange(St, Sym);
case APSIntType::RTR_Within:
break;
case APSIntType::RTR_Above:
@@ -572,13 +566,13 @@ RangeConstraintManager::getSymGERange(ProgramStateRef St, SymbolRef Sym,
llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
llvm::APSInt Min = AdjustmentType.getMinValue();
if (ComparisonVal == Min)
- return GetRange(St, Sym);
+ return getRange(St, Sym);
llvm::APSInt Max = AdjustmentType.getMaxValue();
llvm::APSInt Lower = ComparisonVal - Adjustment;
llvm::APSInt Upper = Max - Adjustment;
- return GetRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper);
+ return getRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper);
}
ProgramStateRef
@@ -589,10 +583,9 @@ RangeConstraintManager::assumeSymGE(ProgramStateRef St, SymbolRef Sym,
return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New);
}
-RangeSet
-RangeConstraintManager::getSymLERange(const RangeSet &RS,
- const llvm::APSInt &Int,
- const llvm::APSInt &Adjustment) {
+RangeSet RangeConstraintManager::getSymLERange(const RangeSet &RS,
+ const llvm::APSInt &Int,
+ const llvm::APSInt &Adjustment) {
// Before we do any real work, see if the value can even show up.
APSIntType AdjustmentType(Adjustment);
switch (AdjustmentType.testInRange(Int, true)) {
@@ -617,10 +610,10 @@ RangeConstraintManager::getSymLERange(const RangeSet &RS,
return RS.Intersect(getBasicVals(), F, Lower, Upper);
}
-RangeSet
-RangeConstraintManager::getSymLERange(ProgramStateRef St, SymbolRef Sym,
- const llvm::APSInt &Int,
- const llvm::APSInt &Adjustment) {
+RangeSet RangeConstraintManager::getSymLERange(ProgramStateRef St,
+ SymbolRef Sym,
+ const llvm::APSInt &Int,
+ const llvm::APSInt &Adjustment) {
// Before we do any real work, see if the value can even show up.
APSIntType AdjustmentType(Adjustment);
switch (AdjustmentType.testInRange(Int, true)) {
@@ -629,20 +622,20 @@ RangeConstraintManager::getSymLERange(ProgramStateRef St, SymbolRef Sym,
case APSIntType::RTR_Within:
break;
case APSIntType::RTR_Above:
- return GetRange(St, Sym);
+ return getRange(St, Sym);
}
// Special case for Int == Max. This is always feasible.
llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
llvm::APSInt Max = AdjustmentType.getMaxValue();
if (ComparisonVal == Max)
- return GetRange(St, Sym);
+ return getRange(St, Sym);
llvm::APSInt Min = AdjustmentType.getMinValue();
llvm::APSInt Lower = Min - Adjustment;
llvm::APSInt Upper = ComparisonVal - Adjustment;
- return GetRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper);
+ return getRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper);
}
ProgramStateRef
@@ -653,8 +646,7 @@ RangeConstraintManager::assumeSymLE(ProgramStateRef St, SymbolRef Sym,
return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New);
}
-ProgramStateRef
-RangeConstraintManager::assumeSymbolWithinInclusiveRange(
+ProgramStateRef RangeConstraintManager::assumeSymbolWithinInclusiveRange(
ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From,
const llvm::APSInt &To, const llvm::APSInt &Adjustment) {
RangeSet New = getSymGERange(State, Sym, From, Adjustment);
@@ -664,8 +656,7 @@ RangeConstraintManager::assumeSymbolWithinInclusiveRange(
return New.isEmpty() ? nullptr : State->set<ConstraintRange>(Sym, New);
}
-ProgramStateRef
-RangeConstraintManager::assumeSymbolOutOfInclusiveRange(
+ProgramStateRef RangeConstraintManager::assumeSymbolOutOfInclusiveRange(
ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From,
const llvm::APSInt &To, const llvm::APSInt &Adjustment) {
RangeSet RangeLT = getSymLTRange(State, Sym, From, Adjustment);
@@ -679,7 +670,7 @@ RangeConstraintManager::assumeSymbolOutOfInclusiveRange(
//===------------------------------------------------------------------------===/
void RangeConstraintManager::print(ProgramStateRef St, raw_ostream &Out,
- const char* nl, const char *sep) {
+ const char *nl, const char *sep) {
ConstraintRangeTy Ranges = St->get<ConstraintRange>();
@@ -689,7 +680,8 @@ void RangeConstraintManager::print(ProgramStateRef St, raw_ostream &Out,
}
Out << nl << sep << "Ranges of symbol values:";
- for (ConstraintRangeTy::iterator I=Ranges.begin(), E=Ranges.end(); I!=E; ++I){
+ for (ConstraintRangeTy::iterator I = Ranges.begin(), E = Ranges.end(); I != E;
+ ++I) {
Out << nl << ' ' << I.getKey() << " : ";
I.getData().print(Out);
}
diff --git a/lib/StaticAnalyzer/Core/RegionStore.cpp b/lib/StaticAnalyzer/Core/RegionStore.cpp
index 0d173c464481..15ca2c14f944 100644
--- a/lib/StaticAnalyzer/Core/RegionStore.cpp
+++ b/lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -26,7 +26,6 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h"
-#include "llvm/ADT/ImmutableList.h"
#include "llvm/ADT/ImmutableMap.h"
#include "llvm/ADT/Optional.h"
#include "llvm/Support/raw_ostream.h"
@@ -1675,7 +1674,8 @@ RegionStoreManager::getBindingForDerivedDefaultValue(RegionBindingsConstRef B,
// Lazy bindings are usually handled through getExistingLazyBinding().
// We should unify these two code paths at some point.
- if (val.getAs<nonloc::LazyCompoundVal>())
+ if (val.getAs<nonloc::LazyCompoundVal>() ||
+ val.getAs<nonloc::CompoundVal>())
return val;
llvm_unreachable("Unknown default value");
@@ -2073,11 +2073,10 @@ RegionStoreManager::bindArray(RegionBindingsConstRef B,
if (Init.getAs<nonloc::LazyCompoundVal>())
return bindAggregate(B, R, Init);
- // Remaining case: explicit compound values.
-
if (Init.isUnknown())
- return setImplicitDefaultValue(B, R, ElementTy);
+ return bindAggregate(B, R, UnknownVal());
+ // Remaining case: explicit compound values.
const nonloc::CompoundVal& CV = Init.castAs<nonloc::CompoundVal>();
nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
uint64_t i = 0;
diff --git a/lib/StaticAnalyzer/Core/SValBuilder.cpp b/lib/StaticAnalyzer/Core/SValBuilder.cpp
index 72bcdd9ecb06..10b0858b8488 100644
--- a/lib/StaticAnalyzer/Core/SValBuilder.cpp
+++ b/lib/StaticAnalyzer/Core/SValBuilder.cpp
@@ -36,8 +36,11 @@ DefinedOrUnknownSVal SValBuilder::makeZeroVal(QualType type) {
if (type->isIntegralOrEnumerationType())
return makeIntVal(0, type);
+ if (type->isArrayType() || type->isRecordType() || type->isVectorType() ||
+ type->isAnyComplexType())
+ return makeCompoundVal(type, BasicVals.getEmptySValList());
+
// FIXME: Handle floats.
- // FIXME: Handle structs.
return UnknownVal();
}
@@ -182,11 +185,12 @@ SValBuilder::getConjuredHeapSymbolVal(const Expr *E,
DefinedSVal SValBuilder::getMetadataSymbolVal(const void *symbolTag,
const MemRegion *region,
const Expr *expr, QualType type,
+ const LocationContext *LCtx,
unsigned count) {
assert(SymbolManager::canSymbolicate(type) && "Invalid metadata symbol type");
SymbolRef sym =
- SymMgr.getMetadataSymbol(region, expr, type, count, symbolTag);
+ SymMgr.getMetadataSymbol(region, expr, type, LCtx, count, symbolTag);
if (Loc::isLocType(type))
return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym));
@@ -213,6 +217,10 @@ SValBuilder::getDerivedRegionValueSymbolVal(SymbolRef parentSymbol,
return nonloc::SymbolVal(sym);
}
+DefinedSVal SValBuilder::getMemberPointer(const DeclaratorDecl* DD) {
+ return nonloc::PointerToMember(DD);
+}
+
DefinedSVal SValBuilder::getFunctionPointer(const FunctionDecl *func) {
return loc::MemRegionVal(MemMgr.getFunctionCodeRegion(func));
}
diff --git a/lib/StaticAnalyzer/Core/SVals.cpp b/lib/StaticAnalyzer/Core/SVals.cpp
index a30beed688b7..9f2af3ffa709 100644
--- a/lib/StaticAnalyzer/Core/SVals.cpp
+++ b/lib/StaticAnalyzer/Core/SVals.cpp
@@ -16,6 +16,7 @@
#include "clang/AST/ExprObjC.h"
#include "clang/Basic/IdentifierTable.h"
#include "llvm/Support/raw_ostream.h"
+#include "clang/AST/DeclCXX.h"
using namespace clang;
using namespace ento;
using llvm::APSInt;
@@ -56,6 +57,10 @@ const FunctionDecl *SVal::getAsFunctionDecl() const {
return FD;
}
+ if (auto X = getAs<nonloc::PointerToMember>()) {
+ if (const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(X->getDecl()))
+ return MD;
+ }
return nullptr;
}
@@ -155,6 +160,20 @@ const TypedValueRegion *nonloc::LazyCompoundVal::getRegion() const {
return static_cast<const LazyCompoundValData*>(Data)->getRegion();
}
+const DeclaratorDecl *nonloc::PointerToMember::getDecl() const {
+ const auto PTMD = this->getPTMData();
+ if (PTMD.isNull())
+ return nullptr;
+
+ const DeclaratorDecl *DD = nullptr;
+ if (PTMD.is<const DeclaratorDecl *>())
+ DD = PTMD.get<const DeclaratorDecl *>();
+ else
+ DD = PTMD.get<const PointerToMemberData *>()->getDeclaratorDecl();
+
+ return DD;
+}
+
//===----------------------------------------------------------------------===//
// Other Iterators.
//===----------------------------------------------------------------------===//
@@ -167,6 +186,20 @@ nonloc::CompoundVal::iterator nonloc::CompoundVal::end() const {
return getValue()->end();
}
+nonloc::PointerToMember::iterator nonloc::PointerToMember::begin() const {
+ const PTMDataType PTMD = getPTMData();
+ if (PTMD.is<const DeclaratorDecl *>())
+ return nonloc::PointerToMember::iterator();
+ 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 PTMD.get<const PointerToMemberData *>()->end();
+}
+
//===----------------------------------------------------------------------===//
// Useful predicates.
//===----------------------------------------------------------------------===//
@@ -299,6 +332,26 @@ void NonLoc::dumpToStream(raw_ostream &os) const {
<< '}';
break;
}
+ case nonloc::PointerToMemberKind: {
+ os << "pointerToMember{";
+ const nonloc::PointerToMember &CastRes =
+ castAs<nonloc::PointerToMember>();
+ if (CastRes.getDecl())
+ os << "|" << CastRes.getDecl()->getQualifiedNameAsString() << "|";
+ bool first = true;
+ for (const auto &I : CastRes) {
+ if (first) {
+ os << ' '; first = false;
+ }
+ else
+ os << ", ";
+
+ os << (*I).getType().getAsString();
+ }
+
+ os << '}';
+ break;
+ }
default:
assert (false && "Pretty-printed not implemented for this NonLoc.");
break;
diff --git a/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp b/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp
index 4051242434ec..0e512ff80861 100644
--- a/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp
+++ b/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp
@@ -30,22 +30,22 @@ bool SimpleConstraintManager::canReasonAbout(SVal X) const {
if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(SE)) {
switch (SIE->getOpcode()) {
- // We don't reason yet about bitwise-constraints on symbolic values.
- case BO_And:
- case BO_Or:
- case BO_Xor:
- return false;
- // We don't reason yet about these arithmetic constraints on
- // symbolic values.
- case BO_Mul:
- case BO_Div:
- case BO_Rem:
- case BO_Shl:
- case BO_Shr:
- return false;
- // All other cases.
- default:
- return true;
+ // We don't reason yet about bitwise-constraints on symbolic values.
+ case BO_And:
+ case BO_Or:
+ case BO_Xor:
+ return false;
+ // We don't reason yet about these arithmetic constraints on
+ // symbolic values.
+ case BO_Mul:
+ case BO_Div:
+ case BO_Rem:
+ case BO_Shl:
+ case BO_Shr:
+ return false;
+ // All other cases.
+ default:
+ return true;
}
}
@@ -65,12 +65,12 @@ bool SimpleConstraintManager::canReasonAbout(SVal X) const {
return true;
}
-ProgramStateRef SimpleConstraintManager::assume(ProgramStateRef state,
- DefinedSVal Cond,
- bool Assumption) {
+ProgramStateRef SimpleConstraintManager::assume(ProgramStateRef State,
+ DefinedSVal Cond,
+ bool Assumption) {
// If we have a Loc value, cast it to a bool NonLoc first.
if (Optional<Loc> LV = Cond.getAs<Loc>()) {
- SValBuilder &SVB = state->getStateManager().getSValBuilder();
+ SValBuilder &SVB = State->getStateManager().getSValBuilder();
QualType T;
const MemRegion *MR = LV->getAsRegion();
if (const TypedRegion *TR = dyn_cast_or_null<TypedRegion>(MR))
@@ -81,19 +81,17 @@ ProgramStateRef SimpleConstraintManager::assume(ProgramStateRef state,
Cond = SVB.evalCast(*LV, SVB.getContext().BoolTy, T).castAs<DefinedSVal>();
}
- return assume(state, Cond.castAs<NonLoc>(), Assumption);
+ return assume(State, Cond.castAs<NonLoc>(), Assumption);
}
-ProgramStateRef SimpleConstraintManager::assume(ProgramStateRef state,
- NonLoc cond,
- bool assumption) {
- state = assumeAux(state, cond, assumption);
+ProgramStateRef SimpleConstraintManager::assume(ProgramStateRef State,
+ NonLoc Cond, bool Assumption) {
+ State = assumeAux(State, Cond, Assumption);
if (NotifyAssumeClients && SU)
- return SU->processAssume(state, cond, assumption);
- return state;
+ return SU->processAssume(State, Cond, Assumption);
+ return State;
}
-
ProgramStateRef
SimpleConstraintManager::assumeAuxForSymbol(ProgramStateRef State,
SymbolRef Sym, bool Assumption) {
@@ -111,16 +109,16 @@ SimpleConstraintManager::assumeAuxForSymbol(ProgramStateRef State,
return assumeSymEQ(State, Sym, zero, zero);
}
-ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef state,
- NonLoc Cond,
- bool Assumption) {
+ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef State,
+ NonLoc Cond,
+ bool Assumption) {
// We cannot reason about SymSymExprs, and can only reason about some
// SymIntExprs.
if (!canReasonAbout(Cond)) {
// Just add the constraint to the expression without trying to simplify.
- SymbolRef sym = Cond.getAsSymExpr();
- return assumeAuxForSymbol(state, sym, Assumption);
+ SymbolRef Sym = Cond.getAsSymExpr();
+ return assumeAuxForSymbol(State, Sym, Assumption);
}
switch (Cond.getSubKind()) {
@@ -129,26 +127,26 @@ ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef state,
case nonloc::SymbolValKind: {
nonloc::SymbolVal SV = Cond.castAs<nonloc::SymbolVal>();
- SymbolRef sym = SV.getSymbol();
- assert(sym);
+ SymbolRef Sym = SV.getSymbol();
+ assert(Sym);
// Handle SymbolData.
if (!SV.isExpression()) {
- return assumeAuxForSymbol(state, sym, Assumption);
+ return assumeAuxForSymbol(State, Sym, Assumption);
- // Handle symbolic expression.
- } else if (const SymIntExpr *SE = dyn_cast<SymIntExpr>(sym)) {
+ // Handle symbolic expression.
+ } else if (const SymIntExpr *SE = dyn_cast<SymIntExpr>(Sym)) {
// We can only simplify expressions whose RHS is an integer.
- BinaryOperator::Opcode op = SE->getOpcode();
- if (BinaryOperator::isComparisonOp(op)) {
+ BinaryOperator::Opcode Op = SE->getOpcode();
+ if (BinaryOperator::isComparisonOp(Op)) {
if (!Assumption)
- op = BinaryOperator::negateComparisonOp(op);
+ Op = BinaryOperator::negateComparisonOp(Op);
- return assumeSymRel(state, SE->getLHS(), op, SE->getRHS());
+ return assumeSymRel(State, SE->getLHS(), Op, SE->getRHS());
}
- } else if (const SymSymExpr *SSE = dyn_cast<SymSymExpr>(sym)) {
+ } else if (const SymSymExpr *SSE = dyn_cast<SymSymExpr>(Sym)) {
// Translate "a != b" to "(b - a) != 0".
// We invert the order of the operands as a heuristic for how loop
// conditions are usually written ("begin != end") as compared to length
@@ -163,34 +161,40 @@ ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef state,
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);
+ 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);
+ return assumeSymRel(State, Subtraction, Op, Zero);
}
// If we get here, there's nothing else we can do but treat the symbol as
// opaque.
- return assumeAuxForSymbol(state, sym, Assumption);
+ return assumeAuxForSymbol(State, Sym, Assumption);
}
case nonloc::ConcreteIntKind: {
bool b = Cond.castAs<nonloc::ConcreteInt>().getValue() != 0;
bool isFeasible = b ? Assumption : !Assumption;
- return isFeasible ? state : nullptr;
+ return isFeasible ? State : nullptr;
+ }
+
+ case nonloc::PointerToMemberKind: {
+ bool IsNull = !Cond.castAs<nonloc::PointerToMember>().isNullMemberPointer();
+ bool IsFeasible = IsNull ? Assumption : !Assumption;
+ return IsFeasible ? State : nullptr;
}
case nonloc::LocAsIntegerKind:
- return assume(state, Cond.castAs<nonloc::LocAsInteger>().getLoc(),
+ return assume(State, Cond.castAs<nonloc::LocAsInteger>().getLoc(),
Assumption);
} // end switch
}
-ProgramStateRef SimpleConstraintManager::assumeWithinInclusiveRange(
+ProgramStateRef SimpleConstraintManager::assumeInclusiveRange(
ProgramStateRef State, NonLoc Value, const llvm::APSInt &From,
const llvm::APSInt &To, bool InRange) {
@@ -207,7 +211,7 @@ ProgramStateRef SimpleConstraintManager::assumeWithinInclusiveRange(
switch (Value.getSubKind()) {
default:
- llvm_unreachable("'assumeWithinInclusiveRange' is not implemented"
+ llvm_unreachable("'assumeInclusiveRange' is not implemented"
"for this NonLoc");
case nonloc::LocAsIntegerKind:
@@ -243,13 +247,26 @@ static void computeAdjustment(SymbolRef &Sym, llvm::APSInt &Adjustment) {
}
}
-ProgramStateRef SimpleConstraintManager::assumeSymRel(ProgramStateRef state,
- const SymExpr *LHS,
- BinaryOperator::Opcode op,
- const llvm::APSInt& Int) {
- assert(BinaryOperator::isComparisonOp(op) &&
+ProgramStateRef SimpleConstraintManager::assumeSymRel(ProgramStateRef State,
+ const SymExpr *LHS,
+ BinaryOperator::Opcode Op,
+ const llvm::APSInt &Int) {
+ assert(BinaryOperator::isComparisonOp(Op) &&
"Non-comparison ops should be rewritten as comparisons to zero.");
+ SymbolRef Sym = LHS;
+
+ // Simplification: translate an assume of a constraint of the form
+ // "(exp comparison_op expr) != 0" to true into an assume of
+ // "exp comparison_op expr" to true. (And similarly, an assume of the form
+ // "(exp comparison_op expr) == 0" to true into an assume of
+ // "exp comparison_op expr" to false.)
+ if (Int == 0 && (Op == BO_EQ || Op == BO_NE)) {
+ if (const BinarySymExpr *SE = dyn_cast<BinarySymExpr>(Sym))
+ if (BinaryOperator::isComparisonOp(SE->getOpcode()))
+ return assume(State, nonloc::SymbolVal(Sym), (Op == BO_NE ? true : false));
+ }
+
// Get the type used for calculating wraparound.
BasicValueFactory &BVF = getBasicVals();
APSIntType WraparoundType = BVF.getAPSIntType(LHS->getType());
@@ -261,7 +278,6 @@ ProgramStateRef SimpleConstraintManager::assumeSymRel(ProgramStateRef state,
// x < 4 has the solution [0, 3]. x+2 < 4 has the solution [0-2, 3-2], which
// in modular arithmetic is [0, 1] U [UINT_MAX-1, UINT_MAX]. It's up to
// the subclasses of SimpleConstraintManager to handle the adjustment.
- SymbolRef Sym = LHS;
llvm::APSInt Adjustment = WraparoundType.getZeroValue();
computeAdjustment(Sym, Adjustment);
@@ -274,36 +290,33 @@ ProgramStateRef SimpleConstraintManager::assumeSymRel(ProgramStateRef state,
ComparisonType.isUnsigned() && !WraparoundType.isUnsigned())
Adjustment.setIsSigned(false);
- switch (op) {
+ switch (Op) {
default:
llvm_unreachable("invalid operation not caught by assertion above");
case BO_EQ:
- return assumeSymEQ(state, Sym, ConvertedInt, Adjustment);
+ return assumeSymEQ(State, Sym, ConvertedInt, Adjustment);
case BO_NE:
- return assumeSymNE(state, Sym, ConvertedInt, Adjustment);
+ return assumeSymNE(State, Sym, ConvertedInt, Adjustment);
case BO_GT:
- return assumeSymGT(state, Sym, ConvertedInt, Adjustment);
+ return assumeSymGT(State, Sym, ConvertedInt, Adjustment);
case BO_GE:
- return assumeSymGE(state, Sym, ConvertedInt, Adjustment);
+ return assumeSymGE(State, Sym, ConvertedInt, Adjustment);
case BO_LT:
- return assumeSymLT(state, Sym, ConvertedInt, Adjustment);
+ return assumeSymLT(State, Sym, ConvertedInt, Adjustment);
case BO_LE:
- return assumeSymLE(state, Sym, ConvertedInt, Adjustment);
+ return assumeSymLE(State, Sym, ConvertedInt, Adjustment);
} // end switch
}
-ProgramStateRef
-SimpleConstraintManager::assumeSymWithinInclusiveRange(ProgramStateRef State,
- SymbolRef Sym,
- const llvm::APSInt &From,
- const llvm::APSInt &To,
- bool InRange) {
+ProgramStateRef SimpleConstraintManager::assumeSymWithinInclusiveRange(
+ ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From,
+ const llvm::APSInt &To, bool InRange) {
// Get the type used for calculating wraparound.
BasicValueFactory &BVF = getBasicVals();
APSIntType WraparoundType = BVF.getAPSIntType(Sym->getType());
diff --git a/lib/StaticAnalyzer/Core/SimpleConstraintManager.h b/lib/StaticAnalyzer/Core/SimpleConstraintManager.h
index b26bc9486110..1128e775b320 100644
--- a/lib/StaticAnalyzer/Core/SimpleConstraintManager.h
+++ b/lib/StaticAnalyzer/Core/SimpleConstraintManager.h
@@ -24,30 +24,28 @@ namespace ento {
class SimpleConstraintManager : public ConstraintManager {
SubEngine *SU;
SValBuilder &SVB;
+
public:
- SimpleConstraintManager(SubEngine *subengine, SValBuilder &SB)
- : SU(subengine), SVB(SB) {}
+ SimpleConstraintManager(SubEngine *SE, SValBuilder &SB) : SU(SE), SVB(SB) {}
~SimpleConstraintManager() override;
//===------------------------------------------------------------------===//
// Common implementation for the interface provided by ConstraintManager.
//===------------------------------------------------------------------===//
- ProgramStateRef assume(ProgramStateRef state, DefinedSVal Cond,
- bool Assumption) override;
+ ProgramStateRef assume(ProgramStateRef State, DefinedSVal Cond,
+ bool Assumption) override;
- ProgramStateRef assume(ProgramStateRef state, NonLoc Cond, bool Assumption);
+ ProgramStateRef assume(ProgramStateRef State, NonLoc Cond, bool Assumption);
- ProgramStateRef assumeWithinInclusiveRange(ProgramStateRef State,
- NonLoc Value,
- const llvm::APSInt &From,
- const llvm::APSInt &To,
- bool InRange) override;
+ ProgramStateRef assumeInclusiveRange(ProgramStateRef State, NonLoc Value,
+ const llvm::APSInt &From,
+ const llvm::APSInt &To,
+ bool InRange) override;
- ProgramStateRef assumeSymRel(ProgramStateRef state,
- const SymExpr *LHS,
- BinaryOperator::Opcode op,
- const llvm::APSInt& Int);
+ ProgramStateRef assumeSymRel(ProgramStateRef State, const SymExpr *LHS,
+ BinaryOperator::Opcode Op,
+ const llvm::APSInt &Int);
ProgramStateRef assumeSymWithinInclusiveRange(ProgramStateRef State,
SymbolRef Sym,
@@ -55,47 +53,45 @@ public:
const llvm::APSInt &To,
bool InRange);
-
protected:
-
//===------------------------------------------------------------------===//
// Interface that subclasses must implement.
//===------------------------------------------------------------------===//
- // Each of these is of the form "$sym+Adj <> V", where "<>" is the comparison
+ // Each of these is of the form "$Sym+Adj <> V", where "<>" is the comparison
// operation for the method being invoked.
- virtual ProgramStateRef assumeSymNE(ProgramStateRef state, SymbolRef sym,
- const llvm::APSInt& V,
- const llvm::APSInt& Adjustment) = 0;
+ virtual ProgramStateRef assumeSymNE(ProgramStateRef State, SymbolRef Sym,
+ const llvm::APSInt &V,
+ const llvm::APSInt &Adjustment) = 0;
- virtual ProgramStateRef assumeSymEQ(ProgramStateRef state, SymbolRef sym,
- const llvm::APSInt& V,
- const llvm::APSInt& Adjustment) = 0;
+ virtual ProgramStateRef assumeSymEQ(ProgramStateRef State, SymbolRef Sym,
+ const llvm::APSInt &V,
+ const llvm::APSInt &Adjustment) = 0;
- virtual ProgramStateRef assumeSymLT(ProgramStateRef state, SymbolRef sym,
- const llvm::APSInt& V,
- const llvm::APSInt& Adjustment) = 0;
+ virtual ProgramStateRef assumeSymLT(ProgramStateRef State, SymbolRef Sym,
+ const llvm::APSInt &V,
+ const llvm::APSInt &Adjustment) = 0;
- virtual ProgramStateRef assumeSymGT(ProgramStateRef state, SymbolRef sym,
- const llvm::APSInt& V,
- const llvm::APSInt& Adjustment) = 0;
+ virtual ProgramStateRef assumeSymGT(ProgramStateRef State, SymbolRef Sym,
+ const llvm::APSInt &V,
+ const llvm::APSInt &Adjustment) = 0;
- virtual ProgramStateRef assumeSymLE(ProgramStateRef state, SymbolRef sym,
- const llvm::APSInt& V,
- const llvm::APSInt& Adjustment) = 0;
-
- virtual ProgramStateRef assumeSymGE(ProgramStateRef state, SymbolRef sym,
- const llvm::APSInt& V,
- const llvm::APSInt& Adjustment) = 0;
+ virtual ProgramStateRef assumeSymLE(ProgramStateRef State, SymbolRef Sym,
+ const llvm::APSInt &V,
+ const llvm::APSInt &Adjustment) = 0;
+ virtual ProgramStateRef assumeSymGE(ProgramStateRef State, SymbolRef Sym,
+ const llvm::APSInt &V,
+ const llvm::APSInt &Adjustment) = 0;
virtual ProgramStateRef assumeSymbolWithinInclusiveRange(
ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From,
const llvm::APSInt &To, const llvm::APSInt &Adjustment) = 0;
virtual ProgramStateRef assumeSymbolOutOfInclusiveRange(
- ProgramStateRef state, SymbolRef Sym, const llvm::APSInt &From,
+ ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From,
const llvm::APSInt &To, const llvm::APSInt &Adjustment) = 0;
+
//===------------------------------------------------------------------===//
// Internal implementation.
//===------------------------------------------------------------------===//
@@ -105,13 +101,11 @@ protected:
bool canReasonAbout(SVal X) const override;
- ProgramStateRef assumeAux(ProgramStateRef state,
- NonLoc Cond,
- bool Assumption);
+ ProgramStateRef assumeAux(ProgramStateRef State, NonLoc Cond,
+ bool Assumption);
- ProgramStateRef assumeAuxForSymbol(ProgramStateRef State,
- SymbolRef Sym,
- bool Assumption);
+ ProgramStateRef assumeAuxForSymbol(ProgramStateRef State, SymbolRef Sym,
+ bool Assumption);
};
} // end GR namespace
diff --git a/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp b/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
index 72b852b2e21d..28b43dd566d5 100644
--- a/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
+++ b/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
@@ -69,6 +69,9 @@ SVal SimpleSValBuilder::evalCastFromNonLoc(NonLoc val, QualType castTy) {
bool isLocType = Loc::isLocType(castTy);
+ if (val.getAs<nonloc::PointerToMember>())
+ return val;
+
if (Optional<nonloc::LocAsInteger> LI = val.getAs<nonloc::LocAsInteger>()) {
if (isLocType)
return LI->getLoc();
@@ -335,6 +338,21 @@ SVal SimpleSValBuilder::evalBinOpNN(ProgramStateRef state,
switch (lhs.getSubKind()) {
default:
return makeSymExprValNN(state, op, lhs, rhs, resultTy);
+ case nonloc::PointerToMemberKind: {
+ assert(rhs.getSubKind() == nonloc::PointerToMemberKind &&
+ "Both SVals should have pointer-to-member-type");
+ auto LPTM = lhs.castAs<nonloc::PointerToMember>(),
+ RPTM = rhs.castAs<nonloc::PointerToMember>();
+ auto LPTMD = LPTM.getPTMData(), RPTMD = RPTM.getPTMData();
+ switch (op) {
+ case BO_EQ:
+ return makeTruthVal(LPTMD == RPTMD, resultTy);
+ case BO_NE:
+ return makeTruthVal(LPTMD != RPTMD, resultTy);
+ default:
+ return UnknownVal();
+ }
+ }
case nonloc::LocAsIntegerKind: {
Loc lhsL = lhs.castAs<nonloc::LocAsInteger>().getLoc();
switch (rhs.getSubKind()) {
@@ -753,6 +771,12 @@ SVal SimpleSValBuilder::evalBinOpLL(ProgramStateRef state,
// Note, heap base symbolic regions are assumed to not alias with
// each other; for example, we assume that malloc returns different address
// on each invocation.
+ // FIXME: ObjC object pointers always reside on the heap, but currently
+ // we treat their memory space as unknown, because symbolic pointers
+ // to ObjC objects may alias. There should be a way to construct
+ // possibly-aliasing heap-based regions. For instance, MacOSXApiChecker
+ // guesses memory space for ObjC object pointers manually instead of
+ // relying on us.
if (LeftBase != RightBase &&
((!isa<SymbolicRegion>(LeftBase) && !isa<SymbolicRegion>(RightBase)) ||
(isa<HeapSpaceRegion>(LeftMS) || isa<HeapSpaceRegion>(RightMS))) ){
@@ -857,6 +881,23 @@ SVal SimpleSValBuilder::evalBinOpLL(ProgramStateRef state,
SVal SimpleSValBuilder::evalBinOpLN(ProgramStateRef state,
BinaryOperator::Opcode op,
Loc lhs, NonLoc rhs, QualType resultTy) {
+ if (op >= BO_PtrMemD && op <= BO_PtrMemI) {
+ if (auto PTMSV = rhs.getAs<nonloc::PointerToMember>()) {
+ if (PTMSV->isNullMemberPointer())
+ return UndefinedVal();
+ if (const FieldDecl *FD = PTMSV->getDeclAs<FieldDecl>()) {
+ SVal Result = lhs;
+
+ for (const auto &I : *PTMSV)
+ Result = StateMgr.getStoreManager().evalDerivedToBase(
+ Result, I->getType(),I->isVirtual());
+ return state->getLValue(FD, Result);
+ }
+ }
+
+ return rhs;
+ }
+
assert(!BinaryOperator::isComparisonOp(op) &&
"arguments to comparison ops must be of the same type");
diff --git a/lib/StaticAnalyzer/Core/Store.cpp b/lib/StaticAnalyzer/Core/Store.cpp
index de29f0eedd12..aca6e3b6255b 100644
--- a/lib/StaticAnalyzer/Core/Store.cpp
+++ b/lib/StaticAnalyzer/Core/Store.cpp
@@ -292,7 +292,7 @@ static const CXXRecordDecl *getCXXRecordType(const MemRegion *MR) {
return nullptr;
}
-SVal StoreManager::evalDynamicCast(SVal Base, QualType TargetType,
+SVal StoreManager::attemptDownCast(SVal Base, QualType TargetType,
bool &Failed) {
Failed = false;
diff --git a/lib/StaticAnalyzer/Core/SymbolManager.cpp b/lib/StaticAnalyzer/Core/SymbolManager.cpp
index b8b4af1179e5..4be85661b645 100644
--- a/lib/StaticAnalyzer/Core/SymbolManager.cpp
+++ b/lib/StaticAnalyzer/Core/SymbolManager.cpp
@@ -85,7 +85,8 @@ void SymbolMetadata::dumpToStream(raw_ostream &os) const {
void SymbolData::anchor() { }
void SymbolRegionValue::dumpToStream(raw_ostream &os) const {
- os << "reg_$" << getSymbolID() << "<" << R << ">";
+ os << "reg_$" << getSymbolID()
+ << '<' << getType().getAsString() << ' ' << R << '>';
}
bool SymExpr::symbol_iterator::operator==(const symbol_iterator &X) const {
@@ -216,17 +217,18 @@ SymbolManager::getExtentSymbol(const SubRegion *R) {
return cast<SymbolExtent>(SD);
}
-const SymbolMetadata*
+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, Count, SymbolTag);
+ SymbolMetadata::Profile(profile, R, S, T, LCtx, Count, SymbolTag);
void *InsertPos;
SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
if (!SD) {
SD = (SymExpr*) BPAlloc.Allocate<SymbolMetadata>();
- new (SD) SymbolMetadata(SymbolCounter, R, S, T, Count, SymbolTag);
+ new (SD) SymbolMetadata(SymbolCounter, R, S, T, LCtx, Count, SymbolTag);
DataSet.InsertNode(SD, InsertPos);
++SymbolCounter;
}
diff --git a/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
index 8ac229fc6583..b3e287ebf815 100644
--- a/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
+++ b/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
@@ -13,17 +13,14 @@
#include "clang/StaticAnalyzer/Frontend/AnalysisConsumer.h"
#include "ModelInjector.h"
-#include "clang/AST/ASTConsumer.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
-#include "clang/AST/ParentMap.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Analysis/Analyses/LiveVariables.h"
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/CallGraph.h"
#include "clang/Analysis/CodeInjector.h"
-#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Lex/Preprocessor.h"
@@ -36,9 +33,7 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
#include "clang/StaticAnalyzer/Frontend/CheckerRegistration.h"
-#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/PostOrderIterator.h"
-#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
@@ -118,16 +113,28 @@ public:
Diag.Report(WarnLoc, WarnID) << PD->getShortDescription()
<< PD->path.back()->getRanges();
+ // First, add extra notes, even if paths should not be included.
+ for (const auto &Piece : PD->path) {
+ if (!isa<PathDiagnosticNotePiece>(Piece.get()))
+ continue;
+
+ SourceLocation NoteLoc = Piece->getLocation().asLocation();
+ Diag.Report(NoteLoc, NoteID) << Piece->getString()
+ << Piece->getRanges();
+ }
+
if (!IncludePath)
continue;
+ // Then, add the path notes if necessary.
PathPieces FlatPath = PD->path.flatten(/*ShouldFlattenMacros=*/true);
- for (PathPieces::const_iterator PI = FlatPath.begin(),
- PE = FlatPath.end();
- PI != PE; ++PI) {
- SourceLocation NoteLoc = (*PI)->getLocation().asLocation();
- Diag.Report(NoteLoc, NoteID) << (*PI)->getString()
- << (*PI)->getRanges();
+ for (const auto &Piece : FlatPath) {
+ if (isa<PathDiagnosticNotePiece>(Piece.get()))
+ continue;
+
+ SourceLocation NoteLoc = Piece->getLocation().asLocation();
+ Diag.Report(NoteLoc, NoteID) << Piece->getString()
+ << Piece->getRanges();
}
}
}
@@ -193,14 +200,16 @@ public:
Injector(injector) {
DigestAnalyzerOptions();
if (Opts->PrintStats) {
- llvm::EnableStatistics();
- TUTotalTimer = new llvm::Timer("Analyzer Total Time");
+ llvm::EnableStatistics(false);
+ TUTotalTimer = new llvm::Timer("time", "Analyzer Total Time");
}
}
~AnalysisConsumer() override {
- if (Opts->PrintStats)
+ if (Opts->PrintStats) {
delete TUTotalTimer;
+ llvm::PrintStatistics();
+ }
}
void DigestAnalyzerOptions() {
@@ -270,19 +279,8 @@ public:
else
assert(Mode == (AM_Syntax | AM_Path) && "Unexpected mode!");
- llvm::errs() << ": " << Loc.getFilename();
- if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
- const NamedDecl *ND = cast<NamedDecl>(D);
- llvm::errs() << ' ' << ND->getQualifiedNameAsString() << '\n';
- }
- else if (isa<BlockDecl>(D)) {
- llvm::errs() << ' ' << "block(line:" << Loc.getLine() << ",col:"
- << Loc.getColumn() << '\n';
- }
- else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
- Selector S = MD->getSelector();
- llvm::errs() << ' ' << S.getAsString();
- }
+ llvm::errs() << ": " << Loc.getFilename() << ' '
+ << getFunctionName(D) << '\n';
}
}
@@ -382,6 +380,7 @@ public:
private:
void storeTopLevelDecls(DeclGroupRef DG);
+ std::string getFunctionName(const Decl *D);
/// \brief Check if we should skip (not analyze) the given function.
AnalysisMode getModeForDecl(Decl *D, AnalysisMode Mode);
@@ -431,6 +430,13 @@ static bool shouldSkipFunction(const Decl *D,
// Count naming convention errors more aggressively.
if (isa<ObjCMethodDecl>(D))
return false;
+ // We also want to reanalyze all C++ copy and move assignment operators to
+ // separately check the two cases where 'this' aliases with the parameter and
+ // where it may not. (cplusplus.SelfAssignmentChecker)
+ if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
+ if (MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator())
+ return false;
+ }
// Otherwise, if we visited the function before, do not reanalyze it.
return Visited.count(D);
@@ -442,9 +448,7 @@ AnalysisConsumer::getInliningModeForFunction(const Decl *D,
// We want to reanalyze all ObjC methods as top level to report Retain
// Count naming convention errors more aggressively. But we should tune down
// inlining when reanalyzing an already inlined function.
- if (Visited.count(D)) {
- assert(isa<ObjCMethodDecl>(D) &&
- "We are only reanalyzing ObjCMethods.");
+ if (Visited.count(D) && isa<ObjCMethodDecl>(D)) {
const ObjCMethodDecl *ObjCM = cast<ObjCMethodDecl>(D);
if (ObjCM->getMethodFamily() != OMF_init)
return ExprEngine::Inline_Minimal;
@@ -568,16 +572,64 @@ void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) {
}
-static std::string getFunctionName(const Decl *D) {
- if (const ObjCMethodDecl *ID = dyn_cast<ObjCMethodDecl>(D)) {
- return ID->getSelector().getAsString();
- }
- if (const FunctionDecl *ND = dyn_cast<FunctionDecl>(D)) {
- IdentifierInfo *II = ND->getIdentifier();
- if (II)
- return II->getName();
+std::string AnalysisConsumer::getFunctionName(const Decl *D) {
+ std::string Str;
+ llvm::raw_string_ostream OS(Str);
+
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ OS << FD->getQualifiedNameAsString();
+
+ // In C++, there are overloads.
+ if (Ctx->getLangOpts().CPlusPlus) {
+ OS << '(';
+ for (const auto &P : FD->parameters()) {
+ if (P != *FD->param_begin())
+ OS << ", ";
+ OS << P->getType().getAsString();
+ }
+ OS << ')';
+ }
+
+ } else if (isa<BlockDecl>(D)) {
+ PresumedLoc Loc = Ctx->getSourceManager().getPresumedLoc(D->getLocation());
+
+ if (Loc.isValid()) {
+ OS << "block (line: " << Loc.getLine() << ", col: " << Loc.getColumn()
+ << ')';
+ }
+
+ } else if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) {
+
+ // FIXME: copy-pasted from CGDebugInfo.cpp.
+ OS << (OMD->isInstanceMethod() ? '-' : '+') << '[';
+ const DeclContext *DC = OMD->getDeclContext();
+ if (const auto *OID = dyn_cast<ObjCImplementationDecl>(DC)) {
+ OS << OID->getName();
+ } else if (const auto *OID = dyn_cast<ObjCInterfaceDecl>(DC)) {
+ OS << OID->getName();
+ } else if (const auto *OC = dyn_cast<ObjCCategoryDecl>(DC)) {
+ if (OC->IsClassExtension()) {
+ OS << OC->getClassInterface()->getName();
+ } else {
+ OS << OC->getIdentifier()->getNameStart() << '('
+ << OC->getIdentifier()->getNameStart() << ')';
+ }
+ } else if (const auto *OCD = dyn_cast<ObjCCategoryImplDecl>(DC)) {
+ OS << ((const NamedDecl *)OCD)->getIdentifier()->getNameStart() << '('
+ << OCD->getIdentifier()->getNameStart() << ')';
+ } else if (isa<ObjCProtocolDecl>(DC)) {
+ // We can extract the type of the class from the self pointer.
+ if (ImplicitParamDecl *SelfDecl = OMD->getSelfDecl()) {
+ QualType ClassTy =
+ cast<ObjCObjectPointerType>(SelfDecl->getType())->getPointeeType();
+ ClassTy.print(OS, PrintingPolicy(LangOptions()));
+ }
+ }
+ OS << ' ' << OMD->getSelector().getAsString() << ']';
+
}
- return "";
+
+ return OS.str();
}
AnalysisConsumer::AnalysisMode
@@ -614,6 +666,12 @@ void AnalysisConsumer::HandleCode(Decl *D, AnalysisMode Mode,
if (Mode == AM_None)
return;
+ // Clear the AnalysisManager of old AnalysisDeclContexts.
+ Mgr->ClearContexts();
+ // Ignore autosynthesized code.
+ if (Mgr->getAnalysisDeclContext(D)->isBodyAutosynthesized())
+ return;
+
DisplayFunction(D, Mode, IMode);
CFG *DeclCFG = Mgr->getCFG(D);
if (DeclCFG) {
@@ -621,8 +679,6 @@ void AnalysisConsumer::HandleCode(Decl *D, AnalysisMode Mode,
MaxCFGSize = MaxCFGSize < CFGSize ? CFGSize : MaxCFGSize;
}
- // Clear the AnalysisManager of old AnalysisDeclContexts.
- Mgr->ClearContexts();
BugReporter BR(*Mgr);
if (Mode & AM_Syntax)
diff --git a/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp b/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp
index 75fa4c651ace..31b6638e651f 100644
--- a/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp
+++ b/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp
@@ -101,6 +101,16 @@ void ClangCheckerRegistry::warnIncompatible(DiagnosticsEngine *diags,
<< pluginAPIVersion;
}
+static SmallVector<CheckerOptInfo, 8>
+getCheckerOptList(const AnalyzerOptions &opts) {
+ SmallVector<CheckerOptInfo, 8> checkerOpts;
+ for (unsigned i = 0, e = opts.CheckersControlList.size(); i != e; ++i) {
+ const std::pair<std::string, bool> &opt = opts.CheckersControlList[i];
+ checkerOpts.push_back(CheckerOptInfo(opt.first, opt.second));
+ }
+ return checkerOpts;
+}
+
std::unique_ptr<CheckerManager>
ento::createCheckerManager(AnalyzerOptions &opts, const LangOptions &langOpts,
ArrayRef<std::string> plugins,
@@ -108,11 +118,7 @@ ento::createCheckerManager(AnalyzerOptions &opts, const LangOptions &langOpts,
std::unique_ptr<CheckerManager> checkerMgr(
new CheckerManager(langOpts, &opts));
- SmallVector<CheckerOptInfo, 8> checkerOpts;
- for (unsigned i = 0, e = opts.CheckersControlList.size(); i != e; ++i) {
- const std::pair<std::string, bool> &opt = opts.CheckersControlList[i];
- checkerOpts.push_back(CheckerOptInfo(opt.first.c_str(), opt.second));
- }
+ SmallVector<CheckerOptInfo, 8> checkerOpts = getCheckerOptList(opts);
ClangCheckerRegistry allCheckers(plugins, &diags);
allCheckers.initializeManager(*checkerMgr, checkerOpts);
@@ -137,3 +143,12 @@ void ento::printCheckerHelp(raw_ostream &out, ArrayRef<std::string> plugins) {
ClangCheckerRegistry(plugins).printHelp(out);
}
+
+void ento::printEnabledCheckerList(raw_ostream &out,
+ ArrayRef<std::string> plugins,
+ const AnalyzerOptions &opts) {
+ out << "OVERVIEW: Clang Static Analyzer Enabled Checkers List\n\n";
+
+ SmallVector<CheckerOptInfo, 8> checkerOpts = getCheckerOptList(opts);
+ ClangCheckerRegistry(plugins).printList(out, checkerOpts);
+}
diff --git a/lib/StaticAnalyzer/Frontend/ModelInjector.cpp b/lib/StaticAnalyzer/Frontend/ModelInjector.cpp
index ee2c3f513cdf..0a284851b08d 100644
--- a/lib/StaticAnalyzer/Frontend/ModelInjector.cpp
+++ b/lib/StaticAnalyzer/Frontend/ModelInjector.cpp
@@ -19,7 +19,6 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/CrashRecoveryContext.h"
#include "llvm/Support/FileSystem.h"
-#include <string>
#include <utility>
using namespace clang;
diff --git a/lib/StaticAnalyzer/Frontend/ModelInjector.h b/lib/StaticAnalyzer/Frontend/ModelInjector.h
index e23bf8abf384..98a5f69d68e8 100644
--- a/lib/StaticAnalyzer/Frontend/ModelInjector.h
+++ b/lib/StaticAnalyzer/Frontend/ModelInjector.h
@@ -25,11 +25,7 @@
#define LLVM_CLANG_SA_FRONTEND_MODELINJECTOR_H
#include "clang/Analysis/CodeInjector.h"
-#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/StringMap.h"
-#include <map>
-#include <memory>
-#include <vector>
namespace clang {
diff --git a/lib/Tooling/ArgumentsAdjusters.cpp b/lib/Tooling/ArgumentsAdjusters.cpp
index 2f3d829d7d19..48b925c698a7 100644
--- a/lib/Tooling/ArgumentsAdjusters.cpp
+++ b/lib/Tooling/ArgumentsAdjusters.cpp
@@ -17,7 +17,7 @@
namespace clang {
namespace tooling {
-/// Add -fsyntax-only option to the commnand line arguments.
+/// Add -fsyntax-only option to the command line arguments.
ArgumentsAdjuster getClangSyntaxOnlyAdjuster() {
return [](const CommandLineArguments &Args, StringRef /*unused*/) {
CommandLineArguments AdjustedArgs;
diff --git a/lib/Tooling/CMakeLists.txt b/lib/Tooling/CMakeLists.txt
index 56134c1164d4..2eec1dba2f36 100644
--- a/lib/Tooling/CMakeLists.txt
+++ b/lib/Tooling/CMakeLists.txt
@@ -1,4 +1,7 @@
-set(LLVM_LINK_COMPONENTS support)
+set(LLVM_LINK_COMPONENTS
+ Option
+ Support
+ )
add_subdirectory(Core)
@@ -13,6 +16,9 @@ add_clang_library(clangTooling
RefactoringCallbacks.cpp
Tooling.cpp
+ DEPENDS
+ ClangDriverOptions
+
LINK_LIBS
clangAST
clangASTMatchers
diff --git a/lib/Tooling/CompilationDatabase.cpp b/lib/Tooling/CompilationDatabase.cpp
index 8fc4a1fe5beb..8ca0b2df7013 100644
--- a/lib/Tooling/CompilationDatabase.cpp
+++ b/lib/Tooling/CompilationDatabase.cpp
@@ -32,12 +32,14 @@
using namespace clang;
using namespace tooling;
+LLVM_INSTANTIATE_REGISTRY(CompilationDatabasePluginRegistry)
+
CompilationDatabase::~CompilationDatabase() {}
std::unique_ptr<CompilationDatabase>
CompilationDatabase::loadFromDirectory(StringRef BuildDirectory,
std::string &ErrorMessage) {
- std::stringstream ErrorStream;
+ llvm::raw_string_ostream ErrorStream(ErrorMessage);
for (CompilationDatabasePluginRegistry::iterator
It = CompilationDatabasePluginRegistry::begin(),
Ie = CompilationDatabasePluginRegistry::end();
@@ -49,7 +51,6 @@ CompilationDatabase::loadFromDirectory(StringRef BuildDirectory,
return DB;
ErrorStream << It->getName() << ": " << DatabaseErrorMessage << "\n";
}
- ErrorMessage = ErrorStream.str();
return nullptr;
}
@@ -299,7 +300,8 @@ FixedCompilationDatabase(Twine Directory, ArrayRef<std::string> CommandLine) {
ToolCommandLine.insert(ToolCommandLine.end(),
CommandLine.begin(), CommandLine.end());
CompileCommands.emplace_back(Directory, StringRef(),
- std::move(ToolCommandLine));
+ std::move(ToolCommandLine),
+ StringRef());
}
std::vector<CompileCommand>
diff --git a/lib/Tooling/Core/Lookup.cpp b/lib/Tooling/Core/Lookup.cpp
index 697eeb46ce41..6edf61b8050d 100644
--- a/lib/Tooling/Core/Lookup.cpp
+++ b/lib/Tooling/Core/Lookup.cpp
@@ -13,37 +13,69 @@
#include "clang/Tooling/Core/Lookup.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
using namespace clang;
using namespace clang::tooling;
-static bool isInsideDifferentNamespaceWithSameName(const DeclContext *DeclA,
- const DeclContext *DeclB) {
- while (true) {
- // Look past non-namespaces on DeclA.
- while (DeclA && !isa<NamespaceDecl>(DeclA))
- DeclA = DeclA->getParent();
-
- // Look past non-namespaces on DeclB.
- while (DeclB && !isa<NamespaceDecl>(DeclB))
- DeclB = DeclB->getParent();
-
- // We hit the root, no namespace collision.
- if (!DeclA || !DeclB)
- return false;
+// Gets all namespaces that \p Context is in as a vector (ignoring anonymous
+// namespaces). The inner namespaces come before outer namespaces in the vector.
+// For example, if the context is in the following namespace:
+// `namespace a { namespace b { namespace c ( ... ) } }`,
+// the vector will be `{c, b, a}`.
+static llvm::SmallVector<const NamespaceDecl *, 4>
+getAllNamedNamespaces(const DeclContext *Context) {
+ llvm::SmallVector<const NamespaceDecl *, 4> Namespaces;
+ auto GetNextNamedNamespace = [](const DeclContext *Context) {
+ // Look past non-namespaces and anonymous namespaces on FromContext.
+ while (Context && (!isa<NamespaceDecl>(Context) ||
+ cast<NamespaceDecl>(Context)->isAnonymousNamespace()))
+ Context = Context->getParent();
+ return Context;
+ };
+ for (Context = GetNextNamedNamespace(Context); Context != nullptr;
+ Context = GetNextNamedNamespace(Context->getParent()))
+ Namespaces.push_back(cast<NamespaceDecl>(Context));
+ return Namespaces;
+}
+// Returns true if the context in which the type is used and the context in
+// which the type is declared are the same semantical namespace but different
+// lexical namespaces.
+static bool
+usingFromDifferentCanonicalNamespace(const DeclContext *FromContext,
+ const DeclContext *UseContext) {
+ // We can skip anonymous namespace because:
+ // 1. `FromContext` and `UseContext` must be in the same anonymous namespaces
+ // since referencing across anonymous namespaces is not possible.
+ // 2. If `FromContext` and `UseContext` are in the same anonymous namespace,
+ // the function will still return `false` as expected.
+ llvm::SmallVector<const NamespaceDecl *, 4> FromNamespaces =
+ getAllNamedNamespaces(FromContext);
+ llvm::SmallVector<const NamespaceDecl *, 4> UseNamespaces =
+ getAllNamedNamespaces(UseContext);
+ // If `UseContext` has fewer level of nested namespaces, it cannot be in the
+ // same canonical namespace as the `FromContext`.
+ if (UseNamespaces.size() < FromNamespaces.size())
+ return false;
+ unsigned Diff = UseNamespaces.size() - FromNamespaces.size();
+ auto FromIter = FromNamespaces.begin();
+ // Only compare `FromNamespaces` with namespaces in `UseNamespaces` that can
+ // collide, i.e. the top N namespaces where N is the number of namespaces in
+ // `FromNamespaces`.
+ auto UseIter = UseNamespaces.begin() + Diff;
+ for (; FromIter != FromNamespaces.end() && UseIter != UseNamespaces.end();
+ ++FromIter, ++UseIter) {
// Literally the same namespace, not a collision.
- if (DeclA == DeclB)
+ if (*FromIter == *UseIter)
return false;
-
- // Now check the names. If they match we have a different namespace with the
- // same name.
- if (cast<NamespaceDecl>(DeclA)->getDeclName() ==
- cast<NamespaceDecl>(DeclB)->getDeclName())
+ // Now check the names. If they match we have a different canonical
+ // namespace with the same name.
+ if (cast<NamespaceDecl>(*FromIter)->getDeclName() ==
+ cast<NamespaceDecl>(*UseIter)->getDeclName())
return true;
-
- DeclA = DeclA->getParent();
- DeclB = DeclB->getParent();
}
+ assert(FromIter == FromNamespaces.end() && UseIter == UseNamespaces.end());
+ return false;
}
static StringRef getBestNamespaceSubstr(const DeclContext *DeclA,
@@ -90,16 +122,22 @@ std::string tooling::replaceNestedName(const NestedNameSpecifier *Use,
"Expected fully-qualified name!");
// We can do a raw name replacement when we are not inside the namespace for
- // the original function and it is not in the global namespace. The
+ // the original class/function and it is not in the global namespace. The
// assumption is that outside the original namespace we must have a using
// statement that makes this work out and that other parts of this refactor
- // will automatically fix using statements to point to the new function
+ // will automatically fix using statements to point to the new class/function.
+ // However, if the `FromDecl` is a class forward declaration, the reference is
+ // still considered as referring to the original definition, so we can't do a
+ // raw name replacement in this case.
const bool class_name_only = !Use;
const bool in_global_namespace =
isa<TranslationUnitDecl>(FromDecl->getDeclContext());
- if (class_name_only && !in_global_namespace &&
- !isInsideDifferentNamespaceWithSameName(FromDecl->getDeclContext(),
- UseContext)) {
+ const bool is_class_forward_decl =
+ isa<CXXRecordDecl>(FromDecl) &&
+ !cast<CXXRecordDecl>(FromDecl)->isCompleteDefinition();
+ if (class_name_only && !in_global_namespace && !is_class_forward_decl &&
+ !usingFromDifferentCanonicalNamespace(FromDecl->getDeclContext(),
+ UseContext)) {
auto Pos = ReplacementString.rfind("::");
return Pos != StringRef::npos ? ReplacementString.substr(Pos + 2)
: ReplacementString;
diff --git a/lib/Tooling/Core/QualTypeNames.cpp b/lib/Tooling/Core/QualTypeNames.cpp
index 619dae1ee106..721c2c92fc27 100644
--- a/lib/Tooling/Core/QualTypeNames.cpp
+++ b/lib/Tooling/Core/QualTypeNames.cpp
@@ -14,8 +14,6 @@
#include "clang/AST/DeclarationName.h"
#include "clang/AST/GlobalDecl.h"
#include "clang/AST/Mangle.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/StringRef.h"
#include <stdio.h>
#include <memory>
diff --git a/lib/Tooling/Core/Replacement.cpp b/lib/Tooling/Core/Replacement.cpp
index 4f130709ac16..e194b59a6e2b 100644
--- a/lib/Tooling/Core/Replacement.cpp
+++ b/lib/Tooling/Core/Replacement.cpp
@@ -20,6 +20,7 @@
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Lexer.h"
#include "clang/Rewrite/Core/Rewriter.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_os_ostream.h"
@@ -29,8 +30,7 @@ namespace tooling {
static const char * const InvalidLocation = "";
-Replacement::Replacement()
- : FilePath(InvalidLocation) {}
+Replacement::Replacement() : FilePath(InvalidLocation) {}
Replacement::Replacement(StringRef FilePath, unsigned Offset, unsigned Length,
StringRef ReplacementText)
@@ -84,11 +84,8 @@ bool operator<(const Replacement &LHS, const Replacement &RHS) {
if (LHS.getOffset() != RHS.getOffset())
return LHS.getOffset() < RHS.getOffset();
- // Apply longer replacements first, specifically so that deletions are
- // executed before insertions. It is (hopefully) never the intention to
- // delete parts of newly inserted code.
if (LHS.getLength() != RHS.getLength())
- return LHS.getLength() > RHS.getLength();
+ return LHS.getLength() < RHS.getLength();
if (LHS.getFilePath() != RHS.getFilePath())
return LHS.getFilePath() < RHS.getFilePath();
@@ -138,200 +135,196 @@ void Replacement::setFromSourceRange(const SourceManager &Sources,
ReplacementText);
}
-template <typename T>
-unsigned shiftedCodePositionInternal(const T &Replaces, unsigned Position) {
- unsigned Offset = 0;
- for (const auto& R : Replaces) {
- if (R.getOffset() + R.getLength() <= Position) {
- Offset += R.getReplacementText().size() - R.getLength();
- continue;
- }
- if (R.getOffset() < Position &&
- R.getOffset() + R.getReplacementText().size() <= Position) {
- Position = R.getOffset() + R.getReplacementText().size() - 1;
- }
- break;
- }
- return Position + Offset;
+Replacement
+Replacements::getReplacementInChangedCode(const Replacement &R) const {
+ unsigned NewStart = getShiftedCodePosition(R.getOffset());
+ unsigned NewEnd = getShiftedCodePosition(R.getOffset() + R.getLength());
+ return Replacement(R.getFilePath(), NewStart, NewEnd - NewStart,
+ R.getReplacementText());
}
-unsigned shiftedCodePosition(const Replacements &Replaces, unsigned Position) {
- return shiftedCodePositionInternal(Replaces, Position);
+static std::string getReplacementErrString(replacement_error Err) {
+ switch (Err) {
+ case replacement_error::fail_to_apply:
+ return "Failed to apply a replacement.";
+ case replacement_error::wrong_file_path:
+ return "The new replacement's file path is different from the file path of "
+ "existing replacements";
+ case replacement_error::overlap_conflict:
+ return "The new replacement overlaps with an existing replacement.";
+ case replacement_error::insert_conflict:
+ return "The new insertion has the same insert location as an existing "
+ "replacement.";
+ }
+ llvm_unreachable("A value of replacement_error has no message.");
}
-// FIXME: Remove this function when Replacements is implemented as std::vector
-// instead of std::set.
-unsigned shiftedCodePosition(const std::vector<Replacement> &Replaces,
- unsigned Position) {
- return shiftedCodePositionInternal(Replaces, Position);
+std::string ReplacementError::message() const {
+ std::string Message = getReplacementErrString(Err);
+ if (NewReplacement.hasValue())
+ Message += "\nNew replacement: " + NewReplacement->toString();
+ if (ExistingReplacement.hasValue())
+ Message += "\nExisting replacement: " + ExistingReplacement->toString();
+ return Message;
}
-void deduplicate(std::vector<Replacement> &Replaces,
- std::vector<Range> &Conflicts) {
- if (Replaces.empty())
- return;
-
- auto LessNoPath = [](const Replacement &LHS, const Replacement &RHS) {
- if (LHS.getOffset() != RHS.getOffset())
- return LHS.getOffset() < RHS.getOffset();
- if (LHS.getLength() != RHS.getLength())
- return LHS.getLength() < RHS.getLength();
- return LHS.getReplacementText() < RHS.getReplacementText();
- };
-
- auto EqualNoPath = [](const Replacement &LHS, const Replacement &RHS) {
- return LHS.getOffset() == RHS.getOffset() &&
- LHS.getLength() == RHS.getLength() &&
- LHS.getReplacementText() == RHS.getReplacementText();
- };
+char ReplacementError::ID = 0;
- // Deduplicate. We don't want to deduplicate based on the path as we assume
- // that all replacements refer to the same file (or are symlinks).
- std::sort(Replaces.begin(), Replaces.end(), LessNoPath);
- Replaces.erase(std::unique(Replaces.begin(), Replaces.end(), EqualNoPath),
- Replaces.end());
-
- // Detect conflicts
- Range ConflictRange(Replaces.front().getOffset(),
- Replaces.front().getLength());
- unsigned ConflictStart = 0;
- unsigned ConflictLength = 1;
- for (unsigned i = 1; i < Replaces.size(); ++i) {
- Range Current(Replaces[i].getOffset(), Replaces[i].getLength());
- if (ConflictRange.overlapsWith(Current)) {
- // Extend conflicted range
- ConflictRange = Range(ConflictRange.getOffset(),
- std::max(ConflictRange.getLength(),
- Current.getOffset() + Current.getLength() -
- ConflictRange.getOffset()));
- ++ConflictLength;
- } else {
- if (ConflictLength > 1)
- Conflicts.push_back(Range(ConflictStart, ConflictLength));
- ConflictRange = Current;
- ConflictStart = i;
- ConflictLength = 1;
+Replacements Replacements::getCanonicalReplacements() const {
+ std::vector<Replacement> NewReplaces;
+ // Merge adjacent replacements.
+ for (const auto &R : Replaces) {
+ if (NewReplaces.empty()) {
+ NewReplaces.push_back(R);
+ continue;
}
- }
-
- if (ConflictLength > 1)
- Conflicts.push_back(Range(ConflictStart, ConflictLength));
-}
-
-bool applyAllReplacements(const Replacements &Replaces, Rewriter &Rewrite) {
- bool Result = true;
- for (Replacements::const_iterator I = Replaces.begin(),
- E = Replaces.end();
- I != E; ++I) {
- if (I->isApplicable()) {
- Result = I->apply(Rewrite) && Result;
+ auto &Prev = NewReplaces.back();
+ unsigned PrevEnd = Prev.getOffset() + Prev.getLength();
+ if (PrevEnd < R.getOffset()) {
+ NewReplaces.push_back(R);
} else {
- Result = false;
+ assert(PrevEnd == R.getOffset() &&
+ "Existing replacements must not overlap.");
+ Replacement NewR(
+ R.getFilePath(), Prev.getOffset(), Prev.getLength() + R.getLength(),
+ (Prev.getReplacementText() + R.getReplacementText()).str());
+ Prev = NewR;
}
}
- return Result;
+ ReplacementsImpl NewReplacesImpl(NewReplaces.begin(), NewReplaces.end());
+ return Replacements(NewReplacesImpl.begin(), NewReplacesImpl.end());
}
-// FIXME: Remove this function when Replacements is implemented as std::vector
-// instead of std::set.
-bool applyAllReplacements(const std::vector<Replacement> &Replaces,
- Rewriter &Rewrite) {
- bool Result = true;
- for (std::vector<Replacement>::const_iterator I = Replaces.begin(),
- E = Replaces.end();
- I != E; ++I) {
- if (I->isApplicable()) {
- Result = I->apply(Rewrite) && Result;
- } else {
- Result = false;
- }
- }
- return Result;
+// `R` and `Replaces` are order-independent if applying them in either order
+// has the same effect, so we need to compare replacements associated to
+// applying them in either order.
+llvm::Expected<Replacements>
+Replacements::mergeIfOrderIndependent(const Replacement &R) const {
+ Replacements Rs(R);
+ // A Replacements set containg 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
+ // applied.
+ Replacements ReplacesShiftedByRs;
+ for (const auto &Replace : Replaces)
+ ReplacesShiftedByRs.Replaces.insert(
+ Rs.getReplacementInChangedCode(Replace));
+ // This is equivalent to applying `Replaces` first and then `R`.
+ auto MergeShiftedRs = merge(RsShiftedByReplaces);
+ // This is equivalent to applying `R` first and then `Replaces`.
+ auto MergeShiftedReplaces = Rs.merge(ReplacesShiftedByRs);
+
+ // Since empty or segmented replacements around existing replacements might be
+ // produced above, we need to compare replacements in canonical forms.
+ if (MergeShiftedRs.getCanonicalReplacements() ==
+ MergeShiftedReplaces.getCanonicalReplacements())
+ return MergeShiftedRs;
+ return llvm::make_error<ReplacementError>(replacement_error::overlap_conflict,
+ R, *Replaces.begin());
}
-llvm::Expected<std::string> applyAllReplacements(StringRef Code,
- const Replacements &Replaces) {
- if (Replaces.empty())
- return Code.str();
+llvm::Error Replacements::add(const Replacement &R) {
+ // Check the file path.
+ if (!Replaces.empty() && R.getFilePath() != Replaces.begin()->getFilePath())
+ return llvm::make_error<ReplacementError>(
+ replacement_error::wrong_file_path, R, *Replaces.begin());
- IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
- new vfs::InMemoryFileSystem);
- FileManager Files(FileSystemOptions(), InMemoryFileSystem);
- DiagnosticsEngine Diagnostics(
- IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs),
- new DiagnosticOptions);
- SourceManager SourceMgr(Diagnostics, Files);
- Rewriter Rewrite(SourceMgr, LangOptions());
- InMemoryFileSystem->addFile(
- "<stdin>", 0, llvm::MemoryBuffer::getMemBuffer(Code, "<stdin>"));
- FileID ID = SourceMgr.createFileID(Files.getFile("<stdin>"), SourceLocation(),
- clang::SrcMgr::C_User);
- for (Replacements::const_iterator I = Replaces.begin(), E = Replaces.end();
- I != E; ++I) {
- Replacement Replace("<stdin>", I->getOffset(), I->getLength(),
- I->getReplacementText());
- if (!Replace.apply(Rewrite))
- return llvm::make_error<llvm::StringError>(
- "Failed to apply replacement: " + Replace.toString(),
- llvm::inconvertibleErrorCode());
+ // Special-case header insertions.
+ if (R.getOffset() == UINT_MAX) {
+ Replaces.insert(R);
+ return llvm::Error::success();
}
- std::string Result;
- llvm::raw_string_ostream OS(Result);
- Rewrite.getEditBuffer(ID).write(OS);
- OS.flush();
- return Result;
-}
-// Merge and sort overlapping ranges in \p Ranges.
-static std::vector<Range> mergeAndSortRanges(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();
- });
- std::vector<Range> Result;
- for (const auto &R : Ranges) {
- if (Result.empty() ||
- Result.back().getOffset() + Result.back().getLength() < R.getOffset()) {
- Result.push_back(R);
- } else {
- unsigned NewEnd =
- std::max(Result.back().getOffset() + Result.back().getLength(),
- R.getOffset() + R.getLength());
- Result[Result.size() - 1] =
- Range(Result.back().getOffset(), NewEnd - Result.back().getOffset());
+ // This replacement cannot conflict with replacements that end before
+ // this replacement starts or start after this replacement ends.
+ // We also know that there currently are no overlapping replacements.
+ // Thus, we know that all replacements that start after the end of the current
+ // replacement cannot overlap.
+ Replacement AtEnd(R.getFilePath(), R.getOffset() + R.getLength(), 0, "");
+
+ // Find the first entry that starts after or at the end of R. Note that
+ // entries that start at the end can still be conflicting if R is an
+ // insertion.
+ auto I = Replaces.lower_bound(AtEnd);
+ // If `I` starts at the same offset as `R`, `R` must be an insertion.
+ if (I != Replaces.end() && R.getOffset() == I->getOffset()) {
+ assert(R.getLength() == 0);
+ // `I` is also an insertion, `R` and `I` conflict.
+ if (I->getLength() == 0) {
+ // Check if two insertions are order-indepedent: if inserting them in
+ // either order produces the same text, they are order-independent.
+ if ((R.getReplacementText() + I->getReplacementText()).str() !=
+ (I->getReplacementText() + R.getReplacementText()).str())
+ return llvm::make_error<ReplacementError>(
+ replacement_error::insert_conflict, R, *I);
+ // If insertions are order-independent, we can merge them.
+ Replacement NewR(
+ R.getFilePath(), R.getOffset(), 0,
+ (R.getReplacementText() + I->getReplacementText()).str());
+ Replaces.erase(I);
+ Replaces.insert(std::move(NewR));
+ return llvm::Error::success();
}
+ // Insertion `R` is adjacent to a non-insertion replacement `I`, so they
+ // are order-independent. It is safe to assume that `R` will not conflict
+ // with any replacement before `I` since all replacements before `I` must
+ // either end before `R` or end at `R` but has length > 0 (if the
+ // replacement before `I` is an insertion at `R`, it would have been `I`
+ // since it is a lower bound of `AtEnd` and ordered before the current `I`
+ // in the set).
+ Replaces.insert(R);
+ return llvm::Error::success();
}
- return Result;
-}
-std::vector<Range> calculateChangedRanges(const Replacements &Replaces) {
- std::vector<Range> ChangedRanges;
- int Shift = 0;
- for (const Replacement &R : Replaces) {
- unsigned Offset = R.getOffset() + Shift;
- unsigned Length = R.getReplacementText().size();
- Shift += Length - R.getLength();
- ChangedRanges.push_back(Range(Offset, Length));
+ // `I` is the smallest iterator (after `R`) whose entry cannot overlap.
+ // If that is begin(), there are no overlaps.
+ if (I == Replaces.begin()) {
+ Replaces.insert(R);
+ return llvm::Error::success();
}
- return mergeAndSortRanges(ChangedRanges);
-}
-
-std::vector<Range>
-calculateRangesAfterReplacements(const Replacements &Replaces,
- const std::vector<Range> &Ranges) {
- auto MergedRanges = mergeAndSortRanges(Ranges);
- tooling::Replacements FakeReplaces;
- for (const auto &R : MergedRanges)
- FakeReplaces.insert(Replacement(Replaces.begin()->getFilePath(),
- R.getOffset(), R.getLength(),
- std::string(R.getLength(), ' ')));
- tooling::Replacements NewReplaces = mergeReplacements(FakeReplaces, Replaces);
- return calculateChangedRanges(NewReplaces);
+ --I;
+ auto Overlap = [](const Replacement &R1, const Replacement &R2) -> bool {
+ return Range(R1.getOffset(), R1.getLength())
+ .overlapsWith(Range(R2.getOffset(), R2.getLength()));
+ };
+ // If the previous entry does not overlap, we know that entries before it
+ // can also not overlap.
+ if (!Overlap(R, *I)) {
+ // If `R` and `I` do not have the same offset, it is safe to add `R` since
+ // it must come after `I`. Otherwise:
+ // - If `R` is an insertion, `I` must not be an insertion since it would
+ // have come after `AtEnd`.
+ // - If `R` is not an insertion, `I` must be an insertion; otherwise, `R`
+ // and `I` would have overlapped.
+ // In either case, we can safely insert `R`.
+ Replaces.insert(R);
+ } else {
+ // `I` overlaps with `R`. We need to check `R` against all overlapping
+ // replacements to see if they are order-indepedent. If they are, merge `R`
+ // with them and replace them with the merged replacements.
+ auto MergeBegin = I;
+ auto MergeEnd = std::next(I);
+ while (I != Replaces.begin()) {
+ --I;
+ // If `I` doesn't overlap with `R`, don't merge it.
+ if (!Overlap(R, *I))
+ break;
+ MergeBegin = I;
+ }
+ Replacements OverlapReplaces(MergeBegin, MergeEnd);
+ llvm::Expected<Replacements> Merged =
+ OverlapReplaces.mergeIfOrderIndependent(R);
+ if (!Merged)
+ return Merged.takeError();
+ Replaces.erase(MergeBegin, MergeEnd);
+ Replaces.insert(Merged->begin(), Merged->end());
+ }
+ return llvm::Error::success();
}
namespace {
+
// Represents a merged replacement, i.e. a replacement consisting of multiple
// overlapping replacements from 'First' and 'Second' in mergeReplacements.
//
@@ -425,26 +418,19 @@ private:
unsigned Length;
std::string Text;
};
-} // namespace
-std::map<std::string, Replacements>
-groupReplacementsByFile(const Replacements &Replaces) {
- std::map<std::string, Replacements> FileToReplaces;
- for (const auto &Replace : Replaces) {
- FileToReplaces[Replace.getFilePath()].insert(Replace);
- }
- return FileToReplaces;
-}
+} // namespace
-Replacements mergeReplacements(const Replacements &First,
- const Replacements &Second) {
- if (First.empty() || Second.empty())
- return First.empty() ? Second : First;
+Replacements Replacements::merge(const Replacements &ReplacesToMerge) const {
+ if (empty() || ReplacesToMerge.empty())
+ return empty() ? ReplacesToMerge : *this;
+ auto &First = Replaces;
+ auto &Second = ReplacesToMerge.Replaces;
// Delta is the amount of characters that replacements from 'Second' need to
// be shifted so that their offsets refer to the original text.
int Delta = 0;
- Replacements Result;
+ ReplacementsImpl Result;
// Iterate over both sets and always add the next element (smallest total
// Offset) from either 'First' or 'Second'. Merge that element with
@@ -470,6 +456,143 @@ Replacements mergeReplacements(const Replacements &First,
Delta -= Merged.deltaFirst();
Result.insert(Merged.asReplacement());
}
+ return Replacements(Result.begin(), Result.end());
+}
+
+// Combines overlapping ranges in \p Ranges and sorts the combined ranges.
+// 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();
+ });
+ std::vector<Range> Result;
+ for (const auto &R : Ranges) {
+ if (Result.empty() ||
+ Result.back().getOffset() + Result.back().getLength() < R.getOffset()) {
+ Result.push_back(R);
+ } else {
+ unsigned NewEnd =
+ std::max(Result.back().getOffset() + Result.back().getLength(),
+ R.getOffset() + R.getLength());
+ Result[Result.size() - 1] =
+ Range(Result.back().getOffset(), NewEnd - Result.back().getOffset());
+ }
+ }
+ return Result;
+}
+
+std::vector<Range>
+calculateRangesAfterReplacements(const Replacements &Replaces,
+ const std::vector<Range> &Ranges) {
+ // To calculate the new ranges,
+ // - Turn \p Ranges into Replacements at (offset, length) with an empty
+ // (unimportant) replacement text of length "length".
+ // - Merge with \p Replaces.
+ // - The new ranges will be the affected ranges of the merged replacements.
+ auto MergedRanges = combineAndSortRanges(Ranges);
+ if (Replaces.empty())
+ return MergedRanges;
+ tooling::Replacements FakeReplaces;
+ for (const auto &R : MergedRanges) {
+ auto Err = FakeReplaces.add(Replacement(Replaces.begin()->getFilePath(),
+ R.getOffset(), R.getLength(),
+ std::string(R.getLength(), ' ')));
+ assert(!Err &&
+ "Replacements must not conflict since ranges have been merged.");
+ (void)Err;
+ }
+ return FakeReplaces.merge(Replaces).getAffectedRanges();
+}
+
+std::vector<Range> Replacements::getAffectedRanges() const {
+ std::vector<Range> ChangedRanges;
+ int Shift = 0;
+ for (const Replacement &R : Replaces) {
+ unsigned Offset = R.getOffset() + Shift;
+ unsigned Length = R.getReplacementText().size();
+ Shift += Length - R.getLength();
+ ChangedRanges.push_back(Range(Offset, Length));
+ }
+ return combineAndSortRanges(ChangedRanges);
+}
+
+unsigned Replacements::getShiftedCodePosition(unsigned Position) const {
+ unsigned Offset = 0;
+ for (const auto& R : Replaces) {
+ if (R.getOffset() + R.getLength() <= Position) {
+ Offset += R.getReplacementText().size() - R.getLength();
+ continue;
+ }
+ if (R.getOffset() < Position &&
+ R.getOffset() + R.getReplacementText().size() <= Position) {
+ Position = R.getOffset() + R.getReplacementText().size();
+ if (R.getReplacementText().size() > 0)
+ Position--;
+ }
+ break;
+ }
+ return Position + Offset;
+}
+
+bool applyAllReplacements(const Replacements &Replaces, Rewriter &Rewrite) {
+ bool Result = true;
+ for (auto I = Replaces.rbegin(), E = Replaces.rend(); I != E; ++I) {
+ if (I->isApplicable()) {
+ Result = I->apply(Rewrite) && Result;
+ } else {
+ Result = false;
+ }
+ }
+ return Result;
+}
+
+llvm::Expected<std::string> applyAllReplacements(StringRef Code,
+ const Replacements &Replaces) {
+ if (Replaces.empty())
+ return Code.str();
+
+ IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
+ new vfs::InMemoryFileSystem);
+ FileManager Files(FileSystemOptions(), InMemoryFileSystem);
+ DiagnosticsEngine Diagnostics(
+ IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs),
+ new DiagnosticOptions);
+ SourceManager SourceMgr(Diagnostics, Files);
+ Rewriter Rewrite(SourceMgr, LangOptions());
+ InMemoryFileSystem->addFile(
+ "<stdin>", 0, llvm::MemoryBuffer::getMemBuffer(Code, "<stdin>"));
+ FileID ID = SourceMgr.createFileID(Files.getFile("<stdin>"), SourceLocation(),
+ clang::SrcMgr::C_User);
+ for (auto I = Replaces.rbegin(), E = Replaces.rend(); I != E; ++I) {
+ Replacement Replace("<stdin>", I->getOffset(), I->getLength(),
+ I->getReplacementText());
+ if (!Replace.apply(Rewrite))
+ return llvm::make_error<ReplacementError>(
+ replacement_error::fail_to_apply, Replace);
+ }
+ std::string Result;
+ llvm::raw_string_ostream OS(Result);
+ Rewrite.getEditBuffer(ID).write(OS);
+ OS.flush();
+ return Result;
+}
+
+std::map<std::string, Replacements> groupReplacementsByFile(
+ FileManager &FileMgr,
+ const std::map<std::string, Replacements> &FileToReplaces) {
+ std::map<std::string, Replacements> Result;
+ llvm::SmallPtrSet<const FileEntry *, 16> ProcessedFileEntries;
+ for (const auto &Entry : FileToReplaces) {
+ const FileEntry *FE = FileMgr.getFile(Entry.first);
+ if (!FE)
+ llvm::errs() << "File path " << Entry.first << " is invalid.\n";
+ else if (ProcessedFileEntries.insert(FE).second)
+ Result[Entry.first] = std::move(Entry.second);
+ }
return Result;
}
diff --git a/lib/Tooling/JSONCompilationDatabase.cpp b/lib/Tooling/JSONCompilationDatabase.cpp
index 299fbdc149bf..738e610ed946 100644
--- a/lib/Tooling/JSONCompilationDatabase.cpp
+++ b/lib/Tooling/JSONCompilationDatabase.cpp
@@ -16,7 +16,10 @@
#include "clang/Tooling/CompilationDatabasePluginRegistry.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/StringSaver.h"
#include <system_error>
namespace clang {
@@ -111,8 +114,29 @@ class CommandLineArgumentParser {
std::vector<std::string> CommandLine;
};
-std::vector<std::string> unescapeCommandLine(
- StringRef EscapedCommandLine) {
+std::vector<std::string> unescapeCommandLine(JSONCommandLineSyntax Syntax,
+ StringRef EscapedCommandLine) {
+ if (Syntax == JSONCommandLineSyntax::AutoDetect) {
+ Syntax = JSONCommandLineSyntax::Gnu;
+ llvm::Triple Triple(llvm::sys::getProcessTriple());
+ if (Triple.getOS() == llvm::Triple::OSType::Win32) {
+ // Assume Windows command line parsing on Win32 unless the triple
+ // explicitly tells us otherwise.
+ if (!Triple.hasEnvironment() ||
+ Triple.getEnvironment() == llvm::Triple::EnvironmentType::MSVC)
+ Syntax = JSONCommandLineSyntax::Windows;
+ }
+ }
+
+ if (Syntax == JSONCommandLineSyntax::Windows) {
+ llvm::BumpPtrAllocator Alloc;
+ llvm::StringSaver Saver(Alloc);
+ llvm::SmallVector<const char *, 64> T;
+ llvm::cl::TokenizeWindowsCommandLine(EscapedCommandLine, Saver, T);
+ std::vector<std::string> Result(T.begin(), T.end());
+ return Result;
+ }
+ assert(Syntax == JSONCommandLineSyntax::Gnu);
CommandLineArgumentParser parser(EscapedCommandLine);
return parser.parse();
}
@@ -123,7 +147,8 @@ class JSONCompilationDatabasePlugin : public CompilationDatabasePlugin {
SmallString<1024> JSONDatabasePath(Directory);
llvm::sys::path::append(JSONDatabasePath, "compile_commands.json");
std::unique_ptr<CompilationDatabase> Database(
- JSONCompilationDatabase::loadFromFile(JSONDatabasePath, ErrorMessage));
+ JSONCompilationDatabase::loadFromFile(
+ JSONDatabasePath, ErrorMessage, JSONCommandLineSyntax::AutoDetect));
if (!Database)
return nullptr;
return Database;
@@ -143,7 +168,8 @@ volatile int JSONAnchorSource = 0;
std::unique_ptr<JSONCompilationDatabase>
JSONCompilationDatabase::loadFromFile(StringRef FilePath,
- std::string &ErrorMessage) {
+ std::string &ErrorMessage,
+ JSONCommandLineSyntax Syntax) {
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> DatabaseBuffer =
llvm::MemoryBuffer::getFile(FilePath);
if (std::error_code Result = DatabaseBuffer.getError()) {
@@ -151,7 +177,7 @@ JSONCompilationDatabase::loadFromFile(StringRef FilePath,
return nullptr;
}
std::unique_ptr<JSONCompilationDatabase> Database(
- new JSONCompilationDatabase(std::move(*DatabaseBuffer)));
+ new JSONCompilationDatabase(std::move(*DatabaseBuffer), Syntax));
if (!Database->parse(ErrorMessage))
return nullptr;
return Database;
@@ -159,11 +185,12 @@ JSONCompilationDatabase::loadFromFile(StringRef FilePath,
std::unique_ptr<JSONCompilationDatabase>
JSONCompilationDatabase::loadFromBuffer(StringRef DatabaseString,
- std::string &ErrorMessage) {
+ std::string &ErrorMessage,
+ JSONCommandLineSyntax Syntax) {
std::unique_ptr<llvm::MemoryBuffer> DatabaseBuffer(
llvm::MemoryBuffer::getMemBuffer(DatabaseString));
std::unique_ptr<JSONCompilationDatabase> Database(
- new JSONCompilationDatabase(std::move(DatabaseBuffer)));
+ new JSONCompilationDatabase(std::move(DatabaseBuffer), Syntax));
if (!Database->parse(ErrorMessage))
return nullptr;
return Database;
@@ -211,10 +238,11 @@ JSONCompilationDatabase::getAllCompileCommands() const {
}
static std::vector<std::string>
-nodeToCommandLine(const std::vector<llvm::yaml::ScalarNode *> &Nodes) {
+nodeToCommandLine(JSONCommandLineSyntax Syntax,
+ const std::vector<llvm::yaml::ScalarNode *> &Nodes) {
SmallString<1024> Storage;
if (Nodes.size() == 1) {
- return unescapeCommandLine(Nodes[0]->getValue(Storage));
+ return unescapeCommandLine(Syntax, Nodes[0]->getValue(Storage));
}
std::vector<std::string> Arguments;
for (auto *Node : Nodes) {
@@ -229,10 +257,13 @@ void JSONCompilationDatabase::getCommands(
for (int I = 0, E = CommandsRef.size(); I != E; ++I) {
SmallString<8> DirectoryStorage;
SmallString<32> FilenameStorage;
+ SmallString<32> OutputStorage;
+ auto Output = std::get<3>(CommandsRef[I]);
Commands.emplace_back(
- std::get<0>(CommandsRef[I])->getValue(DirectoryStorage),
- std::get<1>(CommandsRef[I])->getValue(FilenameStorage),
- nodeToCommandLine(std::get<2>(CommandsRef[I])));
+ std::get<0>(CommandsRef[I])->getValue(DirectoryStorage),
+ std::get<1>(CommandsRef[I])->getValue(FilenameStorage),
+ nodeToCommandLine(Syntax, std::get<2>(CommandsRef[I])),
+ Output ? Output->getValue(OutputStorage) : "");
}
}
@@ -261,6 +292,7 @@ bool JSONCompilationDatabase::parse(std::string &ErrorMessage) {
llvm::yaml::ScalarNode *Directory = nullptr;
llvm::Optional<std::vector<llvm::yaml::ScalarNode *>> Command;
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());
@@ -303,6 +335,8 @@ bool JSONCompilationDatabase::parse(std::string &ErrorMessage) {
Command = std::vector<llvm::yaml::ScalarNode *>(1, ValueString);
} else if (KeyValue == "file") {
File = ValueString;
+ } else if (KeyValue == "output") {
+ Output = ValueString;
} else {
ErrorMessage = ("Unknown key: \"" +
KeyString->getRawValue() + "\"").str();
@@ -333,7 +367,7 @@ bool JSONCompilationDatabase::parse(std::string &ErrorMessage) {
} else {
llvm::sys::path::native(FileName, NativeFilePath);
}
- auto Cmd = CompileCommandRef(Directory, File, *Command);
+ auto Cmd = CompileCommandRef(Directory, File, *Command, Output);
IndexByFile[NativeFilePath].push_back(Cmd);
AllCommands.push_back(Cmd);
MatchTrie.insert(NativeFilePath);
diff --git a/lib/Tooling/Refactoring.cpp b/lib/Tooling/Refactoring.cpp
index 28d535aeb45f..308c1ac48b28 100644
--- a/lib/Tooling/Refactoring.cpp
+++ b/lib/Tooling/Refactoring.cpp
@@ -11,6 +11,7 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/Tooling/Refactoring.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
@@ -18,8 +19,6 @@
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Lex/Lexer.h"
#include "clang/Rewrite/Core/Rewriter.h"
-#include "clang/Tooling/Refactoring.h"
-#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_os_ostream.h"
@@ -31,7 +30,9 @@ RefactoringTool::RefactoringTool(
std::shared_ptr<PCHContainerOperations> PCHContainerOps)
: ClangTool(Compilations, SourcePaths, PCHContainerOps) {}
-Replacements &RefactoringTool::getReplacements() { return Replace; }
+std::map<std::string, Replacements> &RefactoringTool::getReplacements() {
+ return FileToReplaces;
+}
int RefactoringTool::runAndSave(FrontendActionFactory *ActionFactory) {
if (int Result = run(ActionFactory)) {
@@ -55,22 +56,26 @@ int RefactoringTool::runAndSave(FrontendActionFactory *ActionFactory) {
}
bool RefactoringTool::applyAllReplacements(Rewriter &Rewrite) {
- return tooling::applyAllReplacements(Replace, Rewrite);
+ bool Result = true;
+ for (const auto &Entry : groupReplacementsByFile(
+ Rewrite.getSourceMgr().getFileManager(), FileToReplaces))
+ Result = tooling::applyAllReplacements(Entry.second, Rewrite) && Result;
+ return Result;
}
int RefactoringTool::saveRewrittenFiles(Rewriter &Rewrite) {
return Rewrite.overwriteChangedFiles() ? 1 : 0;
}
-bool formatAndApplyAllReplacements(const Replacements &Replaces,
- Rewriter &Rewrite, StringRef Style) {
+bool formatAndApplyAllReplacements(
+ const std::map<std::string, Replacements> &FileToReplaces, Rewriter &Rewrite,
+ StringRef Style) {
SourceManager &SM = Rewrite.getSourceMgr();
FileManager &Files = SM.getFileManager();
- auto FileToReplaces = groupReplacementsByFile(Replaces);
-
bool Result = true;
- for (const auto &FileAndReplaces : FileToReplaces) {
+ for (const auto &FileAndReplaces : groupReplacementsByFile(
+ Rewrite.getSourceMgr().getFileManager(), FileToReplaces)) {
const std::string &FilePath = FileAndReplaces.first;
auto &CurReplaces = FileAndReplaces.second;
diff --git a/lib/Tooling/RefactoringCallbacks.cpp b/lib/Tooling/RefactoringCallbacks.cpp
index 4de125ec02aa..e900c23e4f64 100644
--- a/lib/Tooling/RefactoringCallbacks.cpp
+++ b/lib/Tooling/RefactoringCallbacks.cpp
@@ -39,11 +39,16 @@ ReplaceStmtWithText::ReplaceStmtWithText(StringRef FromId, StringRef ToText)
void ReplaceStmtWithText::run(
const ast_matchers::MatchFinder::MatchResult &Result) {
- if (const Stmt *FromMatch = Result.Nodes.getStmtAs<Stmt>(FromId)) {
- Replace.insert(tooling::Replacement(
+ if (const Stmt *FromMatch = Result.Nodes.getNodeAs<Stmt>(FromId)) {
+ auto Err = Replace.add(tooling::Replacement(
*Result.SourceManager,
- CharSourceRange::getTokenRange(FromMatch->getSourceRange()),
- ToText));
+ CharSourceRange::getTokenRange(FromMatch->getSourceRange()), ToText));
+ // FIXME: better error handling. For now, just print error message in the
+ // release version.
+ if (Err) {
+ llvm::errs() << llvm::toString(std::move(Err)) << "\n";
+ assert(false);
+ }
}
}
@@ -52,11 +57,18 @@ ReplaceStmtWithStmt::ReplaceStmtWithStmt(StringRef FromId, StringRef ToId)
void ReplaceStmtWithStmt::run(
const ast_matchers::MatchFinder::MatchResult &Result) {
- const Stmt *FromMatch = Result.Nodes.getStmtAs<Stmt>(FromId);
- const Stmt *ToMatch = Result.Nodes.getStmtAs<Stmt>(ToId);
- if (FromMatch && ToMatch)
- Replace.insert(replaceStmtWithStmt(
- *Result.SourceManager, *FromMatch, *ToMatch));
+ const Stmt *FromMatch = Result.Nodes.getNodeAs<Stmt>(FromId);
+ const Stmt *ToMatch = Result.Nodes.getNodeAs<Stmt>(ToId);
+ if (FromMatch && ToMatch) {
+ auto Err = Replace.add(
+ replaceStmtWithStmt(*Result.SourceManager, *FromMatch, *ToMatch));
+ // FIXME: better error handling. For now, just print error message in the
+ // release version.
+ if (Err) {
+ llvm::errs() << llvm::toString(std::move(Err)) << "\n";
+ assert(false);
+ }
+ }
}
ReplaceIfStmtWithItsBody::ReplaceIfStmtWithItsBody(StringRef Id,
@@ -65,14 +77,28 @@ ReplaceIfStmtWithItsBody::ReplaceIfStmtWithItsBody(StringRef Id,
void ReplaceIfStmtWithItsBody::run(
const ast_matchers::MatchFinder::MatchResult &Result) {
- if (const IfStmt *Node = Result.Nodes.getStmtAs<IfStmt>(Id)) {
+ if (const IfStmt *Node = Result.Nodes.getNodeAs<IfStmt>(Id)) {
const Stmt *Body = PickTrueBranch ? Node->getThen() : Node->getElse();
if (Body) {
- Replace.insert(replaceStmtWithStmt(*Result.SourceManager, *Node, *Body));
+ auto Err =
+ Replace.add(replaceStmtWithStmt(*Result.SourceManager, *Node, *Body));
+ // FIXME: better error handling. For now, just print error message in the
+ // release version.
+ if (Err) {
+ llvm::errs() << llvm::toString(std::move(Err)) << "\n";
+ assert(false);
+ }
} else if (!PickTrueBranch) {
// If we want to use the 'else'-branch, but it doesn't exist, delete
// the whole 'if'.
- Replace.insert(replaceStmtWithText(*Result.SourceManager, *Node, ""));
+ auto Err =
+ Replace.add(replaceStmtWithText(*Result.SourceManager, *Node, ""));
+ // FIXME: better error handling. For now, just print error message in the
+ // release version.
+ if (Err) {
+ llvm::errs() << llvm::toString(std::move(Err)) << "\n";
+ assert(false);
+ }
}
}
}
diff --git a/lib/Tooling/Tooling.cpp b/lib/Tooling/Tooling.cpp
index 4c7fed1e617c..529c47ef1e7a 100644
--- a/lib/Tooling/Tooling.cpp
+++ b/lib/Tooling/Tooling.cpp
@@ -13,23 +13,26 @@
//===----------------------------------------------------------------------===//
#include "clang/Tooling/Tooling.h"
-#include "clang/AST/ASTConsumer.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.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/FrontendDiagnostic.h"
#include "clang/Frontend/TextDiagnosticPrinter.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/Option/ArgList.h"
#include "llvm/Option/Option.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Host.h"
+#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include <utility>
@@ -240,6 +243,11 @@ bool ToolInvocation::run() {
Argv.push_back(Str.c_str());
const char *const BinaryName = Argv[0];
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
+ unsigned MissingArgIndex, MissingArgCount;
+ std::unique_ptr<llvm::opt::OptTable> Opts(driver::createDriverOptTable());
+ llvm::opt::InputArgList ParsedArgs = Opts->ParseArgs(
+ ArrayRef<const char *>(Argv).slice(1), MissingArgIndex, MissingArgCount);
+ ParseDiagnosticArgs(*DiagOpts, ParsedArgs);
TextDiagnosticPrinter DiagnosticPrinter(
llvm::errs(), &*DiagOpts);
DiagnosticsEngine Diagnostics(
diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt
index 814857f49c4d..27cb83afcc93 100644
--- a/runtime/CMakeLists.txt
+++ b/runtime/CMakeLists.txt
@@ -77,6 +77,8 @@ if(LLVM_BUILD_EXTERNAL_COMPILER_RT AND EXISTS ${COMPILER_RT_SRC_ROOT}/)
-DCOMPILER_RT_INCLUDE_TESTS=${LLVM_INCLUDE_TESTS}
-DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}
-DLLVM_LIBDIR_SUFFIX=${LLVM_LIBDIR_SUFFIX}
+ -DCMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET}
+ -DCMAKE_OSX_SYSROOT:PATH=${CMAKE_OSX_SYSROOT}
${COMPILER_RT_PASSTHROUGH_VARIABLES}
INSTALL_COMMAND ""
STEP_TARGETS configure build
@@ -143,6 +145,15 @@ if(LLVM_BUILD_EXTERNAL_COMPILER_RT AND EXISTS ${COMPILER_RT_SRC_ROOT}/)
DEPENDS compiler-rt-build ${COMPILER_RT_TEST_DEPENDENCIES}
WORKING_DIRECTORY ${BINARY_DIR}
VERBATIM USES_TERMINAL)
- set_property(GLOBAL APPEND PROPERTY LLVM_LIT_DEPENDS check-compiler-rt)
+
+ # Add special target to run all compiler-rt test suites.
+ get_ext_project_build_command(run_check_compiler_rt compiler-rt-test-depends)
+ add_custom_target(compiler-rt-test-depends
+ COMMAND ${run_check_compiler_rt}
+ DEPENDS compiler-rt-build ${COMPILER_RT_TEST_DEPENDENCIES}
+ WORKING_DIRECTORY ${BINARY_DIR}
+ VERBATIM USES_TERMINAL)
+ set_property(GLOBAL APPEND PROPERTY LLVM_ADDITIONAL_TEST_DEPENDS compiler-rt-test-depends)
+ set_property(GLOBAL APPEND PROPERTY LLVM_ADDITIONAL_TEST_TARGETS check-compiler-rt)
endif()
endif()
diff --git a/test/ASTMerge/Inputs/anonymous-fields1.cpp b/test/ASTMerge/anonymous-fields/Inputs/anonymous-fields1.cpp
index 829bc0edd30a..829bc0edd30a 100644
--- a/test/ASTMerge/Inputs/anonymous-fields1.cpp
+++ b/test/ASTMerge/anonymous-fields/Inputs/anonymous-fields1.cpp
diff --git a/test/ASTMerge/Inputs/anonymous-fields2.cpp b/test/ASTMerge/anonymous-fields/Inputs/anonymous-fields2.cpp
index 28ea46d98711..28ea46d98711 100644
--- a/test/ASTMerge/Inputs/anonymous-fields2.cpp
+++ b/test/ASTMerge/anonymous-fields/Inputs/anonymous-fields2.cpp
diff --git a/test/ASTMerge/anonymous-fields.cpp b/test/ASTMerge/anonymous-fields/test.cpp
index 67afc29d07e5..67afc29d07e5 100644
--- a/test/ASTMerge/anonymous-fields.cpp
+++ b/test/ASTMerge/anonymous-fields/test.cpp
diff --git a/test/ASTMerge/asm/Inputs/asm-function.cpp b/test/ASTMerge/asm/Inputs/asm-function.cpp
new file mode 100644
index 000000000000..59c4edfbcd25
--- /dev/null
+++ b/test/ASTMerge/asm/Inputs/asm-function.cpp
@@ -0,0 +1,11 @@
+
+unsigned char asmFunc(unsigned char a, unsigned char b) {
+ unsigned int la = a;
+ unsigned int lb = b;
+ unsigned int bigres;
+ unsigned char res;
+ __asm__ ("0:\n1:\n" : [bigres] "=la"(bigres) : [la] "0"(la), [lb] "c"(lb) :
+ "edx", "cc");
+ res = bigres;
+ return res;
+}
diff --git a/test/ASTMerge/asm/test.cpp b/test/ASTMerge/asm/test.cpp
new file mode 100644
index 000000000000..3a0a205720fe
--- /dev/null
+++ b/test/ASTMerge/asm/test.cpp
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -triple i386-unknown-unknown -fcxx-exceptions -emit-pch -o %t.1.ast %S/Inputs/asm-function.cpp
+// RUN: %clang_cc1 -triple i386-unknown-unknown -fcxx-exceptions -ast-merge %t.1.ast -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+void testAsmImport() {
+ asmFunc(12, 42);
+}
diff --git a/test/ASTMerge/Inputs/category1.m b/test/ASTMerge/category/Inputs/category1.m
index afcaab81f2b7..afcaab81f2b7 100644
--- a/test/ASTMerge/Inputs/category1.m
+++ b/test/ASTMerge/category/Inputs/category1.m
diff --git a/test/ASTMerge/Inputs/category2.m b/test/ASTMerge/category/Inputs/category2.m
index 49a3c270a1c2..49a3c270a1c2 100644
--- a/test/ASTMerge/Inputs/category2.m
+++ b/test/ASTMerge/category/Inputs/category2.m
diff --git a/test/ASTMerge/category.m b/test/ASTMerge/category/test.m
index c7d524816494..c7d524816494 100644
--- a/test/ASTMerge/category.m
+++ b/test/ASTMerge/category/test.m
diff --git a/test/ASTMerge/Inputs/class-template1.cpp b/test/ASTMerge/class-template/Inputs/class-template1.cpp
index 440b5abfc869..440b5abfc869 100644
--- a/test/ASTMerge/Inputs/class-template1.cpp
+++ b/test/ASTMerge/class-template/Inputs/class-template1.cpp
diff --git a/test/ASTMerge/Inputs/class-template2.cpp b/test/ASTMerge/class-template/Inputs/class-template2.cpp
index 6300301a4ffa..6300301a4ffa 100644
--- a/test/ASTMerge/Inputs/class-template2.cpp
+++ b/test/ASTMerge/class-template/Inputs/class-template2.cpp
diff --git a/test/ASTMerge/class-template.cpp b/test/ASTMerge/class-template/test.cpp
index 0ab5443db7f6..0ab5443db7f6 100644
--- a/test/ASTMerge/class-template.cpp
+++ b/test/ASTMerge/class-template/test.cpp
diff --git a/test/ASTMerge/Inputs/class1.cpp b/test/ASTMerge/class/Inputs/class1.cpp
index b0a7645cfe63..b0a7645cfe63 100644
--- a/test/ASTMerge/Inputs/class1.cpp
+++ b/test/ASTMerge/class/Inputs/class1.cpp
diff --git a/test/ASTMerge/Inputs/class2.cpp b/test/ASTMerge/class/Inputs/class2.cpp
index 2bed6d775bc4..2bed6d775bc4 100644
--- a/test/ASTMerge/Inputs/class2.cpp
+++ b/test/ASTMerge/class/Inputs/class2.cpp
diff --git a/test/ASTMerge/class.cpp b/test/ASTMerge/class/test.cpp
index a68a2d1d7690..a68a2d1d7690 100644
--- a/test/ASTMerge/class.cpp
+++ b/test/ASTMerge/class/test.cpp
diff --git a/test/ASTMerge/class2/Inputs/class3.cpp b/test/ASTMerge/class2/Inputs/class3.cpp
new file mode 100644
index 000000000000..428acc3f0319
--- /dev/null
+++ b/test/ASTMerge/class2/Inputs/class3.cpp
@@ -0,0 +1,26 @@
+class C1 {
+public:
+ C1();
+ ~C1();
+ C1 *method_1() {
+ return this;
+ }
+ C1 method_2() {
+ return C1();
+ }
+ void method_3() {
+ const C1 &ref = C1();
+ }
+};
+
+class C11 : public C1 {
+};
+
+class C2 {
+private:
+ int x;
+ friend class C3;
+public:
+ static_assert(sizeof(x) == sizeof(int), "Error");
+ typedef class C2::C2 InjType;
+};
diff --git a/test/ASTMerge/class2/test.cpp b/test/ASTMerge/class2/test.cpp
new file mode 100644
index 000000000000..6021403d7229
--- /dev/null
+++ b/test/ASTMerge/class2/test.cpp
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++1z -emit-pch -o %t.1.ast %S/Inputs/class3.cpp
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++1z -ast-merge %t.1.ast -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+class C3 {
+ int method_1(C2 *x) {
+ return x->x;
+ }
+};
diff --git a/test/ASTMerge/Inputs/body1.c b/test/ASTMerge/codegen-body/Inputs/body1.c
index d4d1e4b93781..d4d1e4b93781 100644
--- a/test/ASTMerge/Inputs/body1.c
+++ b/test/ASTMerge/codegen-body/Inputs/body1.c
diff --git a/test/ASTMerge/Inputs/body2.c b/test/ASTMerge/codegen-body/Inputs/body2.c
index 73cb1edf9917..73cb1edf9917 100644
--- a/test/ASTMerge/Inputs/body2.c
+++ b/test/ASTMerge/codegen-body/Inputs/body2.c
diff --git a/test/ASTMerge/codegen-body.c b/test/ASTMerge/codegen-body/test.c
index 7232bf4164b5..7232bf4164b5 100644
--- a/test/ASTMerge/codegen-body.c
+++ b/test/ASTMerge/codegen-body/test.c
diff --git a/test/ASTMerge/Inputs/exprs1.c b/test/ASTMerge/codegen-exprs/Inputs/exprs1.c
index 1c268da15f3d..1c268da15f3d 100644
--- a/test/ASTMerge/Inputs/exprs1.c
+++ b/test/ASTMerge/codegen-exprs/Inputs/exprs1.c
diff --git a/test/ASTMerge/Inputs/exprs2.c b/test/ASTMerge/codegen-exprs/Inputs/exprs2.c
index 1c268da15f3d..1c268da15f3d 100644
--- a/test/ASTMerge/Inputs/exprs2.c
+++ b/test/ASTMerge/codegen-exprs/Inputs/exprs2.c
diff --git a/test/ASTMerge/codegen-exprs.c b/test/ASTMerge/codegen-exprs/test.c
index b5069f993be5..b5069f993be5 100644
--- a/test/ASTMerge/codegen-exprs.c
+++ b/test/ASTMerge/codegen-exprs/test.c
diff --git a/test/ASTMerge/Inputs/enum1.c b/test/ASTMerge/enum/Inputs/enum1.c
index f2b9c5c98fde..f2b9c5c98fde 100644
--- a/test/ASTMerge/Inputs/enum1.c
+++ b/test/ASTMerge/enum/Inputs/enum1.c
diff --git a/test/ASTMerge/Inputs/enum2.c b/test/ASTMerge/enum/Inputs/enum2.c
index 315b4dcb6ef5..315b4dcb6ef5 100644
--- a/test/ASTMerge/Inputs/enum2.c
+++ b/test/ASTMerge/enum/Inputs/enum2.c
diff --git a/test/ASTMerge/enum.c b/test/ASTMerge/enum/test.c
index 7240bcced99e..7240bcced99e 100644
--- a/test/ASTMerge/enum.c
+++ b/test/ASTMerge/enum/test.c
diff --git a/test/ASTMerge/exprs-cpp/Inputs/exprs3.cpp b/test/ASTMerge/exprs-cpp/Inputs/exprs3.cpp
new file mode 100644
index 000000000000..7ed8e338452f
--- /dev/null
+++ b/test/ASTMerge/exprs-cpp/Inputs/exprs3.cpp
@@ -0,0 +1,120 @@
+// Integer literals
+const char Ch1 = 'a';
+const signed char Ch2 = 'b';
+const unsigned char Ch3 = 'c';
+
+const wchar_t Ch4 = L'd';
+const signed wchar_t Ch5 = L'e';
+const unsigned wchar_t Ch6 = L'f';
+
+const short C1 = 12;
+const unsigned short C2 = 13;
+
+const int C3 = 12;
+const unsigned int C4 = 13;
+
+const long C5 = 22;
+const unsigned long C6 = 23;
+
+const long long C7 = 66;
+const unsigned long long C8 = 67;
+
+
+// String literals
+const char str1[] = "ABCD";
+const char str2[] = "ABCD" "0123";
+
+const wchar_t wstr1[] = L"DEF";
+const wchar_t wstr2[] = L"DEF" L"123";
+
+
+// Boolean literals
+const bool bval1 = true;
+const bool bval2 = false;
+
+// Floating Literals
+const float F1 = 12.2F;
+const double F2 = 1E4;
+const long double F3 = 1.2E-3L;
+
+
+// nullptr literal
+const void *vptr = nullptr;
+
+
+int glb_1[4] = { 10, 20, 30, 40 };
+
+struct S1 {
+ int a;
+ int b[3];
+};
+
+struct S2 {
+ int c;
+ S1 d;
+};
+
+S2 glb_2 = { 22, .d.a = 44, .d.b[0] = 55, .d.b[1] = 66 };
+
+void testNewThrowDelete() {
+ throw;
+ char *p = new char[10];
+ delete[] p;
+}
+
+int testArrayElement(int *x, int n) {
+ return x[n];
+}
+
+int testTernaryOp(int c, int x, int y) {
+ return c ? x : y;
+}
+
+S1 &testConstCast(const S1 &x) {
+ return const_cast<S1&>(x);
+}
+
+S1 &testStaticCast(S1 &x) {
+ return static_cast<S1&>(x);
+}
+
+S1 &testReinterpretCast(S1 &x) {
+ return reinterpret_cast<S1&>(x);
+}
+
+S1 &testDynamicCast(S1 &x) {
+ return dynamic_cast<S1&>(x);
+}
+
+int testScalarInit(int x) {
+ return int(x);
+}
+
+struct S {
+ float f;
+ double d;
+};
+struct T {
+ int i;
+ struct S s[10];
+};
+
+void testOffsetOf() {
+ __builtin_offsetof(struct T, s[2].d);
+}
+
+
+int testDefaultArg(int a = 2*2) {
+ return a;
+}
+
+template <typename T> // T has TemplateTypeParmType
+void testTemplateTypeParmType(int i);
+
+void useTemplateType() {
+ testTemplateTypeParmType<char>(4);
+}
+
+const bool ExpressionTrait = __is_lvalue_expr(1);
+const unsigned ArrayRank = __array_rank(int[10][20]);
+const unsigned ArrayExtent = __array_extent(int[10][20], 1);
diff --git a/test/ASTMerge/exprs-cpp/test.cpp b/test/ASTMerge/exprs-cpp/test.cpp
new file mode 100644
index 000000000000..ba1f18b2c90c
--- /dev/null
+++ b/test/ASTMerge/exprs-cpp/test.cpp
@@ -0,0 +1,45 @@
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++1z -fcxx-exceptions -emit-pch -o %t.1.ast %S/Inputs/exprs3.cpp
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++1z -fcxx-exceptions -ast-merge %t.1.ast -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+static_assert(Ch1 == 'a');
+static_assert(Ch2 == 'b');
+static_assert(Ch3 == 'c');
+
+static_assert(Ch4 == L'd');
+static_assert(Ch5 == L'e');
+static_assert(Ch6 == L'f');
+
+static_assert(C1 == 12);
+static_assert(C2 == 13);
+
+static_assert(C3 == 12);
+static_assert(C4 == 13);
+
+static_assert(C5 == 22L);
+static_assert(C6 == 23L);
+
+static_assert(C7 == 66LL);
+static_assert(C8 == 67ULL);
+
+static_assert(bval1 == true);
+static_assert(bval2 == false);
+
+static_assert(ExpressionTrait == false);
+
+static_assert(ArrayRank == 2);
+static_assert(ArrayExtent == 20);
+
+void testImport(int *x, const S1 &cs1, S1 &s1) {
+ testNewThrowDelete();
+ testArrayElement(nullptr, 12);
+ testTernaryOp(0, 1, 2);
+ testConstCast(cs1);
+ testStaticCast(s1);
+ testReinterpretCast(s1);
+ testDynamicCast(s1);
+ testScalarInit(42);
+ testOffsetOf();
+ testDefaultArg(12);
+ useTemplateType();
+}
diff --git a/test/ASTMerge/exprs/Inputs/exprs1.c b/test/ASTMerge/exprs/Inputs/exprs1.c
new file mode 100644
index 000000000000..1c268da15f3d
--- /dev/null
+++ b/test/ASTMerge/exprs/Inputs/exprs1.c
@@ -0,0 +1,10 @@
+// Matching
+enum E0 {
+ E0_Val0 = 'a',
+ E0_Val1 = (17),
+ E0_Val2 = (1 << 2),
+ E0_Val3 = E0_Val2,
+ E0_Val4 = sizeof(int*),
+ E0_Val5 = (unsigned int)-1
+};
+
diff --git a/test/ASTMerge/exprs/Inputs/exprs2.c b/test/ASTMerge/exprs/Inputs/exprs2.c
new file mode 100644
index 000000000000..1c268da15f3d
--- /dev/null
+++ b/test/ASTMerge/exprs/Inputs/exprs2.c
@@ -0,0 +1,10 @@
+// Matching
+enum E0 {
+ E0_Val0 = 'a',
+ E0_Val1 = (17),
+ E0_Val2 = (1 << 2),
+ E0_Val3 = E0_Val2,
+ E0_Val4 = sizeof(int*),
+ E0_Val5 = (unsigned int)-1
+};
+
diff --git a/test/ASTMerge/exprs.c b/test/ASTMerge/exprs/test.c
index 7495bb6a874a..7495bb6a874a 100644
--- a/test/ASTMerge/exprs.c
+++ b/test/ASTMerge/exprs/test.c
diff --git a/test/ASTMerge/Inputs/function1.c b/test/ASTMerge/function/Inputs/function1.c
index 4523bd3d79bf..4523bd3d79bf 100644
--- a/test/ASTMerge/Inputs/function1.c
+++ b/test/ASTMerge/function/Inputs/function1.c
diff --git a/test/ASTMerge/Inputs/function2.c b/test/ASTMerge/function/Inputs/function2.c
index 6ca810a6f20b..6ca810a6f20b 100644
--- a/test/ASTMerge/Inputs/function2.c
+++ b/test/ASTMerge/function/Inputs/function2.c
diff --git a/test/ASTMerge/function.c b/test/ASTMerge/function/test.c
index 650f719d1fa8..650f719d1fa8 100644
--- a/test/ASTMerge/function.c
+++ b/test/ASTMerge/function/test.c
diff --git a/test/ASTMerge/Inputs/inheritance-base.cpp b/test/ASTMerge/inheritance/Inputs/inheritance-base.cpp
index 26fe42eb64da..26fe42eb64da 100644
--- a/test/ASTMerge/Inputs/inheritance-base.cpp
+++ b/test/ASTMerge/inheritance/Inputs/inheritance-base.cpp
diff --git a/test/ASTMerge/inheritance.cpp b/test/ASTMerge/inheritance/test.cpp
index 7fce82a736ab..7fce82a736ab 100644
--- a/test/ASTMerge/inheritance.cpp
+++ b/test/ASTMerge/inheritance/test.cpp
diff --git a/test/ASTMerge/Inputs/init-ctors-classes.cpp b/test/ASTMerge/init-ctors/Inputs/init-ctors-classes.cpp
index fd51f860634b..fd51f860634b 100644
--- a/test/ASTMerge/Inputs/init-ctors-classes.cpp
+++ b/test/ASTMerge/init-ctors/Inputs/init-ctors-classes.cpp
diff --git a/test/ASTMerge/init-ctors.cpp b/test/ASTMerge/init-ctors/test.cpp
index 5f0ba4decd9f..5f0ba4decd9f 100644
--- a/test/ASTMerge/init-ctors.cpp
+++ b/test/ASTMerge/init-ctors/test.cpp
diff --git a/test/ASTMerge/Inputs/interface1.m b/test/ASTMerge/interface/Inputs/interface1.m
index 5865c0eff070..5865c0eff070 100644
--- a/test/ASTMerge/Inputs/interface1.m
+++ b/test/ASTMerge/interface/Inputs/interface1.m
diff --git a/test/ASTMerge/Inputs/interface2.m b/test/ASTMerge/interface/Inputs/interface2.m
index 2133bd1381aa..2133bd1381aa 100644
--- a/test/ASTMerge/Inputs/interface2.m
+++ b/test/ASTMerge/interface/Inputs/interface2.m
diff --git a/test/ASTMerge/interface.m b/test/ASTMerge/interface/test.m
index 8ba5d73753a3..8ba5d73753a3 100644
--- a/test/ASTMerge/interface.m
+++ b/test/ASTMerge/interface/test.m
diff --git a/test/ASTMerge/macro/Inputs/macro.modulemap b/test/ASTMerge/macro/Inputs/macro.modulemap
new file mode 100644
index 000000000000..dba1f2207f15
--- /dev/null
+++ b/test/ASTMerge/macro/Inputs/macro.modulemap
@@ -0,0 +1,4 @@
+module macro1 [extern_c] {
+ header "macro1.h"
+ export *
+}
diff --git a/test/ASTMerge/macro/Inputs/macro1.h b/test/ASTMerge/macro/Inputs/macro1.h
new file mode 100644
index 000000000000..961339496787
--- /dev/null
+++ b/test/ASTMerge/macro/Inputs/macro1.h
@@ -0,0 +1,5 @@
+typedef void *VoidRef;
+
+void maybeNull(
+ int i,
+ _Nullable VoidRef *_Nullable);
diff --git a/test/ASTMerge/macro/Inputs/macro1.m b/test/ASTMerge/macro/Inputs/macro1.m
new file mode 100644
index 000000000000..2612613bd0be
--- /dev/null
+++ b/test/ASTMerge/macro/Inputs/macro1.m
@@ -0,0 +1,5 @@
+@import macro1;
+
+void foo() {
+ maybeNull(0, 0);
+}
diff --git a/test/ASTMerge/macro/Inputs/macro2.m b/test/ASTMerge/macro/Inputs/macro2.m
new file mode 100644
index 000000000000..b5b155a95b52
--- /dev/null
+++ b/test/ASTMerge/macro/Inputs/macro2.m
@@ -0,0 +1,5 @@
+void foo();
+
+void bar() {
+ foo();
+}
diff --git a/test/ASTMerge/macro/test.m b/test/ASTMerge/macro/test.m
new file mode 100644
index 000000000000..77e596d3baed
--- /dev/null
+++ b/test/ASTMerge/macro/test.m
@@ -0,0 +1,6 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t/cache
+// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t/cache -fmodule-map-file=%S/Inputs/macro.modulemap -I%S/Inputs -emit-pch -o %t.1.ast %S/Inputs/macro1.m
+// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t/cache -fmodule-map-file=%S/Inputs/macro.modulemap -I%S/Inputs -emit-pch -o %t.2.ast %S/Inputs/macro2.m
+// RUN: %clang_cc1 -fmodules -ast-merge %t.1.ast -ast-merge %t.2.ast -fsyntax-only -verify %s
+// expected-no-diagnostics
diff --git a/test/ASTMerge/Inputs/namespace1.cpp b/test/ASTMerge/namespace/Inputs/namespace1.cpp
index 1ff84f3111c9..1ff84f3111c9 100644
--- a/test/ASTMerge/Inputs/namespace1.cpp
+++ b/test/ASTMerge/namespace/Inputs/namespace1.cpp
diff --git a/test/ASTMerge/Inputs/namespace2.cpp b/test/ASTMerge/namespace/Inputs/namespace2.cpp
index 80429f700b13..80429f700b13 100644
--- a/test/ASTMerge/Inputs/namespace2.cpp
+++ b/test/ASTMerge/namespace/Inputs/namespace2.cpp
diff --git a/test/ASTMerge/namespace.cpp b/test/ASTMerge/namespace/test.cpp
index 8cc0fa2a6d97..8cc0fa2a6d97 100644
--- a/test/ASTMerge/namespace.cpp
+++ b/test/ASTMerge/namespace/test.cpp
diff --git a/test/ASTMerge/Inputs/property1.m b/test/ASTMerge/property/Inputs/property1.m
index 22fe0a02220c..22fe0a02220c 100644
--- a/test/ASTMerge/Inputs/property1.m
+++ b/test/ASTMerge/property/Inputs/property1.m
diff --git a/test/ASTMerge/Inputs/property2.m b/test/ASTMerge/property/Inputs/property2.m
index 64a03fb04ec3..64a03fb04ec3 100644
--- a/test/ASTMerge/Inputs/property2.m
+++ b/test/ASTMerge/property/Inputs/property2.m
diff --git a/test/ASTMerge/property.m b/test/ASTMerge/property/test.m
index 494802347696..494802347696 100644
--- a/test/ASTMerge/property.m
+++ b/test/ASTMerge/property/test.m
diff --git a/test/ASTMerge/Inputs/struct1.c b/test/ASTMerge/struct/Inputs/struct1.c
index af2af8abc42a..af2af8abc42a 100644
--- a/test/ASTMerge/Inputs/struct1.c
+++ b/test/ASTMerge/struct/Inputs/struct1.c
diff --git a/test/ASTMerge/Inputs/struct2.c b/test/ASTMerge/struct/Inputs/struct2.c
index 4b43df71d8d6..4b43df71d8d6 100644
--- a/test/ASTMerge/Inputs/struct2.c
+++ b/test/ASTMerge/struct/Inputs/struct2.c
diff --git a/test/ASTMerge/struct.c b/test/ASTMerge/struct/test.c
index 4f41cea26b18..4f41cea26b18 100644
--- a/test/ASTMerge/struct.c
+++ b/test/ASTMerge/struct/test.c
diff --git a/test/ASTMerge/Inputs/typedef1.c b/test/ASTMerge/typedef/Inputs/typedef1.c
index 56576756856d..56576756856d 100644
--- a/test/ASTMerge/Inputs/typedef1.c
+++ b/test/ASTMerge/typedef/Inputs/typedef1.c
diff --git a/test/ASTMerge/Inputs/typedef2.c b/test/ASTMerge/typedef/Inputs/typedef2.c
index 129d7101e91e..129d7101e91e 100644
--- a/test/ASTMerge/Inputs/typedef2.c
+++ b/test/ASTMerge/typedef/Inputs/typedef2.c
diff --git a/test/ASTMerge/typedef.c b/test/ASTMerge/typedef/test.c
index 79e472311874..79e472311874 100644
--- a/test/ASTMerge/typedef.c
+++ b/test/ASTMerge/typedef/test.c
diff --git a/test/ASTMerge/Inputs/var1.c b/test/ASTMerge/var/Inputs/var1.c
index 4f5cbe16ab6c..4f5cbe16ab6c 100644
--- a/test/ASTMerge/Inputs/var1.c
+++ b/test/ASTMerge/var/Inputs/var1.c
diff --git a/test/ASTMerge/Inputs/var1.h b/test/ASTMerge/var/Inputs/var1.h
index 1518e17ef0c8..1518e17ef0c8 100644
--- a/test/ASTMerge/Inputs/var1.h
+++ b/test/ASTMerge/var/Inputs/var1.h
diff --git a/test/ASTMerge/Inputs/var2.c b/test/ASTMerge/var/Inputs/var2.c
index 01986e4208ca..01986e4208ca 100644
--- a/test/ASTMerge/Inputs/var2.c
+++ b/test/ASTMerge/var/Inputs/var2.c
diff --git a/test/ASTMerge/var.c b/test/ASTMerge/var/test.c
index e14dc37edac7..e14dc37edac7 100644
--- a/test/ASTMerge/var.c
+++ b/test/ASTMerge/var/test.c
diff --git a/test/Analysis/CFDateGC.m b/test/Analysis/CFDateGC.m
index e12306216e60..fae144f859a8 100644
--- a/test/Analysis/CFDateGC.m
+++ b/test/Analysis/CFDateGC.m
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount -analyzer-store=region -analyzer-constraints=range -verify -fobjc-gc %s -Wno-implicit-function-declaration
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount -analyzer-store=region -verify -fobjc-gc %s -Wno-implicit-function-declaration
//===----------------------------------------------------------------------===//
// The following code is reduced using delta-debugging from
diff --git a/test/Analysis/CFNumber.c b/test/Analysis/CFNumber.c
index ebb3b1ac1ed8..d7dd951b93ce 100644
--- a/test/Analysis/CFNumber.c
+++ b/test/Analysis/CFNumber.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.coreFoundation.CFNumber,osx.cocoa.RetainCount -analyzer-store=region -analyzer-constraints=range -verify -triple x86_64-apple-darwin9 %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.coreFoundation.CFNumber,osx.cocoa.RetainCount -analyzer-store=region -verify -triple x86_64-apple-darwin9 %s
typedef signed long CFIndex;
typedef const struct __CFAllocator * CFAllocatorRef;
@@ -13,14 +13,16 @@ enum { kCFNumberSInt8Type = 1, kCFNumberSInt16Type = 2,
kCFNumberMaxType = 16 };
typedef CFIndex CFNumberType;
typedef const struct __CFNumber * CFNumberRef;
+typedef unsigned char Boolean;
extern CFNumberRef CFNumberCreate(CFAllocatorRef allocator, CFNumberType theType, const void *valuePtr);
+Boolean CFNumberGetValue(CFNumberRef number, CFNumberType theType, void *valuePtr);
-CFNumberRef f1(unsigned char x) {
- return CFNumberCreate(0, kCFNumberSInt16Type, &x); // expected-warning{{An 8 bit integer is used to initialize a CFNumber object that represents a 16 bit integer. 8 bits of the CFNumber value will be garbage}}
+__attribute__((cf_returns_retained)) CFNumberRef f1(unsigned char x) {
+ return CFNumberCreate(0, kCFNumberSInt16Type, &x); // expected-warning{{An 8-bit integer is used to initialize a CFNumber object that represents a 16-bit integer; 8 bits of the CFNumber value will be garbage}}
}
__attribute__((cf_returns_retained)) CFNumberRef f2(unsigned short x) {
- return CFNumberCreate(0, kCFNumberSInt8Type, &x); // expected-warning{{A 16 bit integer is used to initialize a CFNumber object that represents an 8 bit integer. 8 bits of the input integer will be lost}}
+ return CFNumberCreate(0, kCFNumberSInt8Type, &x); // expected-warning{{A 16-bit integer is used to initialize a CFNumber object that represents an 8-bit integer; 8 bits of the integer value will be lost}}
}
// test that the attribute overrides the naming convention.
@@ -28,6 +30,18 @@ __attribute__((cf_returns_not_retained)) CFNumberRef CreateNum(unsigned char x)
return CFNumberCreate(0, kCFNumberSInt8Type, &x); // expected-warning{{leak}}
}
-CFNumberRef f3(unsigned i) {
- return CFNumberCreate(0, kCFNumberLongType, &i); // expected-warning{{A 32 bit integer is used to initialize a CFNumber object that represents a 64 bit integer}}
+__attribute__((cf_returns_retained)) CFNumberRef f3(unsigned i) {
+ return CFNumberCreate(0, kCFNumberLongType, &i); // expected-warning{{A 32-bit integer is used to initialize a CFNumber object that represents a 64-bit integer}}
+}
+
+unsigned char getValueTest1(CFNumberRef x) {
+ unsigned char scalar = 0;
+ CFNumberGetValue(x, kCFNumberSInt16Type, &scalar); // expected-warning{{A CFNumber object that represents a 16-bit integer is used to initialize an 8-bit integer; 8 bits of the CFNumber value will overwrite adjacent storage}}
+ return scalar;
+}
+
+unsigned char getValueTest2(CFNumberRef x) {
+ unsigned short scalar = 0;
+ CFNumberGetValue(x, kCFNumberSInt8Type, &scalar); // expected-warning{{A CFNumber object that represents an 8-bit integer is used to initialize a 16-bit integer; 8 bits of the integer value will be garbage}}
+ return scalar;
}
diff --git a/test/Analysis/CFRetainRelease_NSAssertionHandler.m b/test/Analysis/CFRetainRelease_NSAssertionHandler.m
index 853bfb24dacd..be1f20de762c 100644
--- a/test/Analysis/CFRetainRelease_NSAssertionHandler.m
+++ b/test/Analysis/CFRetainRelease_NSAssertionHandler.m
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount,alpha.core -verify %s -analyzer-constraints=range -analyzer-store=region
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount,alpha.core -verify %s -analyzer-store=region
// expected-no-diagnostics
typedef struct objc_selector *SEL;
diff --git a/test/Analysis/CGColorSpace.c b/test/Analysis/CGColorSpace.c
index e2da36459a23..8681e15d39e5 100644
--- a/test/Analysis/CGColorSpace.c
+++ b/test/Analysis/CGColorSpace.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount -analyzer-store=region -analyzer-constraints=range -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount -analyzer-store=region -verify %s
typedef struct CGColorSpace *CGColorSpaceRef;
extern CGColorSpaceRef CGColorSpaceCreateDeviceRGB(void);
diff --git a/test/Analysis/CheckNSError.m b/test/Analysis/CheckNSError.m
index af645da79989..d126d29157b8 100644
--- a/test/Analysis/CheckNSError.m
+++ b/test/Analysis/CheckNSError.m
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.NSError,osx.coreFoundation.CFError -analyzer-store=region -analyzer-constraints=range -verify -Wno-objc-root-class %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.NSError,osx.coreFoundation.CFError -analyzer-store=region -verify -Wno-objc-root-class %s
typedef signed char BOOL;
diff --git a/test/Analysis/DeallocMissingRelease.m b/test/Analysis/DeallocMissingRelease.m
index 009e80151814..651f20a13621 100644
--- a/test/Analysis/DeallocMissingRelease.m
+++ b/test/Analysis/DeallocMissingRelease.m
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=osx.cocoa.Dealloc -fblocks -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=osx.cocoa.Dealloc -fblocks -triple x86_64-apple-ios4.0 -DMACOS=0 -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=osx.cocoa.Dealloc -fblocks -triple x86_64-apple-macosx10.6.0 -DMACOS=1 -verify %s
// RUN: %clang_cc1 -analyze -analyzer-checker=osx.cocoa.Dealloc -fblocks -triple x86_64-apple-darwin10 -fobjc-arc -fobjc-runtime-has-weak -verify %s
#include "Inputs/system-header-simulator-for-objc-dealloc.h"
@@ -866,3 +867,59 @@ __attribute__((objc_root_class))
@implementation NotMissingDeallocCIFilter // no-warning
@synthesize inputIvar = inputIvar;
@end
+
+
+@interface ClassWithRetainPropWithIBOutletIvarButNoSetter : NSObject {
+ // On macOS, the nib-loading code will set the ivar directly without
+ // retaining value (unike iOS, where it is retained). This means that
+ // on macOS we should not warn about a missing release for a property backed
+ // by an IBOutlet ivar when that property does not have a setter.
+ IBOutlet NSObject *ivarForOutlet;
+}
+
+@property (readonly, retain) NSObject *ivarForOutlet;
+@end
+
+@implementation ClassWithRetainPropWithIBOutletIvarButNoSetter
+
+@synthesize ivarForOutlet;
+- (void)dealloc {
+
+#if NON_ARC
+ [super dealloc];
+#if !MACOS
+// expected-warning@-2{{The 'ivarForOutlet' ivar in 'ClassWithRetainPropWithIBOutletIvarButNoSetter' was retained by a synthesized property but not released before '[super dealloc]'}}
+#endif
+#endif
+}
+
+@end
+
+@interface ClassWithRetainPropWithIBOutletIvarAndShadowingReadWrite : NSObject {
+ IBOutlet NSObject *ivarForOutlet;
+}
+
+@property (readonly, retain) NSObject *ivarForOutlet;
+
+@end
+
+@interface ClassWithRetainPropWithIBOutletIvarAndShadowingReadWrite ()
+
+// Since there is a shadowing readwrite property, there will be a retaining
+// setter and so the ivar will be retained by nib-loading code even on
+// macOS and therefore must be released.
+@property (readwrite, retain) NSObject *ivarForOutlet;
+@end
+
+@implementation ClassWithRetainPropWithIBOutletIvarAndShadowingReadWrite
+
+@synthesize ivarForOutlet;
+- (void)dealloc {
+
+#if NON_ARC
+ [super dealloc];
+// expected-warning@-1{{The 'ivarForOutlet' ivar in 'ClassWithRetainPropWithIBOutletIvarAndShadowingReadWrite' was retained by a synthesized property but not released before '[super dealloc]'}}
+#endif
+}
+
+@end
diff --git a/test/Analysis/DeallocUseAfterFreeErrors.m b/test/Analysis/DeallocUseAfterFreeErrors.m
index 3feeb6d7482c..c131e71f44a1 100644
--- a/test/Analysis/DeallocUseAfterFreeErrors.m
+++ b/test/Analysis/DeallocUseAfterFreeErrors.m
@@ -125,8 +125,8 @@ struct SomeStruct {
}
- (void)dealloc {
[super dealloc]; // expected-note {{[super dealloc] called here}}
- self.ivar = nil; // expected-warning {{use of 'self' after it has been deallocated}}
- // expected-note@-1 {{use of 'self' after it has been deallocated}}
+ self.ivar = nil; // expected-warning {{Use of 'self' after it has been deallocated}}
+ // expected-note@-1 {{Use of 'self' after it has been deallocated}}
}
@end
@@ -144,8 +144,8 @@ struct SomeStruct {
}
- (void)dealloc {
[super dealloc]; // expected-note {{[super dealloc] called here}}
- self.delegate = nil; // expected-warning {{use of 'self' after it has been deallocated}}
- // expected-note@-1 {{use of 'self' after it has been deallocated}}
+ self.delegate = nil; // expected-warning {{Use of 'self' after it has been deallocated}}
+ // expected-note@-1 {{Use of 'self' after it has been deallocated}}
}
@end
@@ -158,8 +158,8 @@ struct SomeStruct {
}
- (void)dealloc {
[super dealloc]; // expected-note {{[super dealloc] called here}}
- [self _invalidate]; // expected-warning {{use of 'self' after it has been deallocated}}
- // expected-note@-1 {{use of 'self' after it has been deallocated}}
+ [self _invalidate]; // expected-warning {{Use of 'self' after it has been deallocated}}
+ // expected-note@-1 {{Use of 'self' after it has been deallocated}}
}
@end
@@ -173,8 +173,8 @@ static void _invalidate(NSObject *object) {
@implementation SuperDeallocThenCallNonObjectiveCMethodClass
- (void)dealloc {
[super dealloc]; // expected-note {{[super dealloc] called here}}
- _invalidate(self); // expected-warning {{use of 'self' after it has been deallocated}}
- // expected-note@-1 {{use of 'self' after it has been deallocated}}
+ _invalidate(self); // expected-warning {{Use of 'self' after it has been deallocated}}
+ // expected-note@-1 {{Use of 'self' after it has been deallocated}}
}
@end
@@ -187,8 +187,8 @@ static void _invalidate(NSObject *object) {
- (void)dealloc {
[super dealloc]; // expected-note {{[super dealloc] called here}}
- [SuperDeallocThenCallObjectiveClassMethodClass invalidate:self]; // expected-warning {{use of 'self' after it has been deallocated}}
- // expected-note@-1 {{use of 'self' after it has been deallocated}}
+ [SuperDeallocThenCallObjectiveClassMethodClass invalidate:self]; // expected-warning {{Use of 'self' after it has been deallocated}}
+ // expected-note@-1 {{Use of 'self' after it has been deallocated}}
}
@end
@@ -202,14 +202,14 @@ static void _invalidate(NSObject *object) {
- (void)_invalidate {
}
- (void)dealloc {
- if (_ivar) { // expected-note {{Taking false branch}}
+ if (_ivar) { // expected-note {{Assuming the condition is false}} expected-note {{Taking false branch}}
[_ivar release];
[super dealloc];
return;
}
[super dealloc]; // expected-note {{[super dealloc] called here}}
- [self _invalidate]; // expected-warning {{use of 'self' after it has been deallocated}}
- // expected-note@-1 {{use of 'self' after it has been deallocated}}
+ [self _invalidate]; // expected-warning {{Use of 'self' after it has been deallocated}}
+ // expected-note@-1 {{Use of 'self' after it has been deallocated}}
}
@end
@@ -223,7 +223,7 @@ static void _invalidate(NSObject *object) {
@implementation MissingReturnCausesDoubleSuperDeallocClass
- (void)dealloc {
- if (_ivar) { // expected-note {{Taking true branch}}
+ if (_ivar) { // expected-note {{Assuming the condition is true}} expected-note {{Taking true branch}}
[_ivar release];
[super dealloc]; // expected-note {{[super dealloc] called here}}
// return;
@@ -366,8 +366,8 @@ static void _invalidate(NSObject *object) {
- (void)dealloc; {
[super dealloc]; // expected-note {{[super dealloc] called here}}
- [self anotherMethod]; // expected-warning {{use of 'self' after it has been deallocated}}
- // expected-note@-1 {{use of 'self' after it has been deallocated}}
+ [self anotherMethod]; // expected-warning {{Use of 'self' after it has been deallocated}}
+ // expected-note@-1 {{Use of 'self' after it has been deallocated}}
[super dealloc];
}
@end
diff --git a/test/Analysis/Inputs/localization-pch.h b/test/Analysis/Inputs/localization-pch.h
new file mode 100644
index 000000000000..973270e24ef2
--- /dev/null
+++ b/test/Analysis/Inputs/localization-pch.h
@@ -0,0 +1,5 @@
+// Used to test missing checker for missing localization context comments
+// in precompiled headers.
+
+#define MyLocalizedStringInPCH(key) NSLocalizedString((key), @"")
+
diff --git a/test/Analysis/Inputs/qt-simulator.h b/test/Analysis/Inputs/qt-simulator.h
index d1d6c0356b74..a3c7387d2003 100644
--- a/test/Analysis/Inputs/qt-simulator.h
+++ b/test/Analysis/Inputs/qt-simulator.h
@@ -1,6 +1,23 @@
#pragma clang system_header
+namespace QtPrivate {
+struct QSlotObjectBase {};
+}
+
+namespace Qt {
+enum ConnectionType {};
+}
+
+struct QMetaObject {
+ struct Connection {};
+};
+
struct QObject {
+ static QMetaObject::Connection connectImpl(const QObject *, void **,
+ const QObject *, void **,
+ QtPrivate::QSlotObjectBase *,
+ Qt::ConnectionType,
+ const int *, const QMetaObject *);
};
struct QEvent {
diff --git a/test/Analysis/Inputs/system-header-simulator-cxx.h b/test/Analysis/Inputs/system-header-simulator-cxx.h
index b32d200364b1..04f1000dbc3f 100644
--- a/test/Analysis/Inputs/system-header-simulator-cxx.h
+++ b/test/Analysis/Inputs/system-header-simulator-cxx.h
@@ -240,3 +240,12 @@ void* operator new (std::size_t size, void* ptr) throw() { return ptr; };
void* operator new[] (std::size_t size, void* ptr) throw() { return ptr; };
void operator delete (void* ptr, void*) throw() {};
void operator delete[] (void* ptr, void*) throw() {};
+
+namespace __cxxabiv1 {
+extern "C" {
+extern char *__cxa_demangle(const char *mangled_name,
+ char *output_buffer,
+ size_t *length,
+ int *status);
+}}
+namespace abi = __cxxabiv1;
diff --git a/test/Analysis/Inputs/system-header-simulator-for-valist.h b/test/Analysis/Inputs/system-header-simulator-for-valist.h
new file mode 100644
index 000000000000..7299b61353d4
--- /dev/null
+++ b/test/Analysis/Inputs/system-header-simulator-for-valist.h
@@ -0,0 +1,30 @@
+// 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
+
+#ifdef __cplusplus
+#define restrict /*restrict*/
+#endif
+
+typedef __builtin_va_list va_list;
+
+#define va_start(ap, param) __builtin_va_start(ap, param)
+#define va_end(ap) __builtin_va_end(ap)
+#define va_arg(ap, type) __builtin_va_arg(ap, type)
+#define va_copy(dst, src) __builtin_va_copy(dst, src)
+
+int vprintf (const char *restrict format, va_list arg);
+
+int vsprintf (char *restrict s, const char *restrict format, va_list arg);
+
+int some_library_function(int n, va_list arg);
+
+// No warning from system header.
+inline void __impl_detail(int fst, ...) {
+ va_list va;
+ (void)va_arg(va, int);
+}
diff --git a/test/Analysis/Inputs/system-header-simulator-objc.h b/test/Analysis/Inputs/system-header-simulator-objc.h
index 8a5d3b6403c8..df751d03e642 100644
--- a/test/Analysis/Inputs/system-header-simulator-objc.h
+++ b/test/Analysis/Inputs/system-header-simulator-objc.h
@@ -10,10 +10,20 @@ typedef unsigned short UInt16;
typedef signed long CFIndex;
typedef signed char BOOL;
+#define YES ((BOOL)1)
+#define NO ((BOOL)0)
+
typedef unsigned long NSUInteger;
typedef unsigned short unichar;
typedef UInt16 UniChar;
+#ifndef NULL
+#define __DARWIN_NULL ((void *)0)
+#define NULL __DARWIN_NULL
+#endif
+
+#define nil ((id)0)
+
enum {
NSASCIIStringEncoding = 1,
NSNEXTSTEPStringEncoding = 2,
@@ -48,6 +58,7 @@ typedef struct _NSZone NSZone;
- (oneway void)release;
- (id)autorelease;
- (id)init;
+@property (readonly, copy) NSString *description;
@end @protocol NSCopying - (id)copyWithZone:(NSZone *)zone;
@end @protocol NSMutableCopying - (id)mutableCopyWithZone:(NSZone *)zone;
@end @protocol NSCoding - (void)encodeWithCoder:(NSCoder *)aCoder;
@@ -72,6 +83,7 @@ NSFastEnumerationState;
@end
@interface NSNumber : NSValue - (char)charValue;
- (id)initWithInt:(int)value;
+- (BOOL)boolValue;
@end @class NSString;
@interface NSArray : NSObject <NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration> - (NSUInteger)count;
@end @interface NSArray (NSArrayCreation) + (id)array;
diff --git a/test/Analysis/Inputs/system-header-simulator.h b/test/Analysis/Inputs/system-header-simulator.h
index 889e23398f03..2e6f1e7d4a96 100644
--- a/test/Analysis/Inputs/system-header-simulator.h
+++ b/test/Analysis/Inputs/system-header-simulator.h
@@ -102,3 +102,11 @@ void exit(int status) __attribute__ ((__noreturn__));
void _exit(int status) __attribute__ ((__noreturn__));
void _Exit(int status) __attribute__ ((__noreturn__));
+#define UINT32_MAX 4294967295U
+#define INT64_MIN (-INT64_MAX-1)
+#define __DBL_MAX__ 1.7976931348623157e+308
+#define DBL_MAX __DBL_MAX__
+#ifndef NULL
+#define __DARWIN_NULL 0
+#define NULL __DARWIN_NULL
+#endif \ No newline at end of file
diff --git a/test/Analysis/NSPanel.m b/test/Analysis/NSPanel.m
index 1d77d1e3702b..53b18c205ef8 100644
--- a/test/Analysis/NSPanel.m
+++ b/test/Analysis/NSPanel.m
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount,alpha.core -analyzer-store=region -analyzer-constraints=range -verify -Wno-objc-root-class %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount,alpha.core -analyzer-store=region -verify -Wno-objc-root-class %s
// expected-no-diagnostics
// BEGIN delta-debugging reduced header stuff
diff --git a/test/Analysis/NSString.m b/test/Analysis/NSString.m
index 799f813022eb..1123d80ab2e8 100644
--- a/test/Analysis/NSString.m
+++ b/test/Analysis/NSString.m
@@ -1,7 +1,7 @@
-// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core,osx.cocoa.NilArg,osx.cocoa.RetainCount,alpha.core -analyzer-store=region -analyzer-constraints=range -verify -Wno-objc-root-class %s
-// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core,osx.cocoa.NilArg,osx.cocoa.RetainCount,alpha.core -analyzer-store=region -analyzer-constraints=range -analyzer-config mode=shallow -verify -Wno-objc-root-class %s
-// RUN: %clang_cc1 -DTEST_64 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core,osx.cocoa.NilArg,osx.cocoa.RetainCount,alpha.core -analyzer-store=region -analyzer-constraints=range -verify -Wno-objc-root-class %s
-// RUN: %clang_cc1 -DOSATOMIC_USE_INLINED -triple i386-apple-darwin10 -analyze -analyzer-checker=core,osx.cocoa.NilArg,osx.cocoa.RetainCount,alpha.core -analyzer-store=region -analyzer-constraints=range -verify -Wno-objc-root-class %s
+// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core,osx.cocoa.NilArg,osx.cocoa.RetainCount,alpha.core -analyzer-store=region -verify -Wno-objc-root-class %s
+// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core,osx.cocoa.NilArg,osx.cocoa.RetainCount,alpha.core -analyzer-store=region -analyzer-config mode=shallow -verify -Wno-objc-root-class %s
+// RUN: %clang_cc1 -DTEST_64 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core,osx.cocoa.NilArg,osx.cocoa.RetainCount,alpha.core -analyzer-store=region -verify -Wno-objc-root-class %s
+// RUN: %clang_cc1 -DOSATOMIC_USE_INLINED -triple i386-apple-darwin10 -analyze -analyzer-checker=core,osx.cocoa.NilArg,osx.cocoa.RetainCount,alpha.core -analyzer-store=region -verify -Wno-objc-root-class %s
//===----------------------------------------------------------------------===//
// The following code is reduced using delta-debugging from
@@ -289,7 +289,11 @@ _Bool opaque_OSAtomicCompareAndSwapPtr( void *__oldValue, void *__newValue, void
_Bool OSAtomicCompareAndSwapPtr( void *__oldValue, void *__newValue, void * volatile *__theValue ) {
return opaque_OSAtomicCompareAndSwapPtr(__oldValue, __newValue, __theValue);
}
-
+// Test that the analyzer doesn't crash when the farm model is used.
+// The analyzer ignores the autosynthesized code.
+_Bool OSAtomicCompareAndSwapEmptyFunction( void *__oldValue, void *__newValue, void * volatile *__theValue ) {
+ return 0;
+}
extern BOOL opaque_objc_atomicCompareAndSwapPtr(id predicate, id replacement, volatile id *objectLocation);
extern BOOL objc_atomicCompareAndSwapPtr(id predicate, id replacement, volatile id *objectLocation) {
return opaque_objc_atomicCompareAndSwapPtr(predicate, replacement, objectLocation);
@@ -441,4 +445,4 @@ void testOSCompareAndSwapXXBarrier_parameter_no_direct_release(NSString **old) {
- (void)callValue {
[self _value];
}
-@end \ No newline at end of file
+@end
diff --git a/test/Analysis/NSWindow.m b/test/Analysis/NSWindow.m
index a2e7297d873d..44a97e42d6c4 100644
--- a/test/Analysis/NSWindow.m
+++ b/test/Analysis/NSWindow.m
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount,alpha.core,deadcode.DeadStores -analyzer-store=region -analyzer-constraints=range -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount,alpha.core,deadcode.DeadStores -analyzer-store=region -verify %s
// These declarations were reduced using Delta-Debugging from Foundation.h
// on Mac OS X. The test cases are below.
diff --git a/test/Analysis/NewDelete-checker-test.cpp b/test/Analysis/NewDelete-checker-test.cpp
index 443cb2e87e9d..78a0015ca532 100644
--- a/test/Analysis/NewDelete-checker-test.cpp
+++ b/test/Analysis/NewDelete-checker-test.cpp
@@ -377,3 +377,19 @@ void testDoubleDeleteEmptyClass() {
delete foo;
delete foo; // expected-warning {{Attempt to delete released memory}}
}
+
+struct Base {
+ virtual ~Base() {}
+};
+
+struct Derived : Base {
+};
+
+Base *allocate() {
+ return new Derived;
+}
+
+void shouldNotReportLeak() {
+ Derived *p = (Derived *)allocate();
+ delete p;
+}
diff --git a/test/Analysis/ObjCProperties.m b/test/Analysis/ObjCProperties.m
index 1712feff5b78..201e3e165d87 100644
--- a/test/Analysis/ObjCProperties.m
+++ b/test/Analysis/ObjCProperties.m
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core -analyzer-store=region -analyzer-constraints=range -Wno-objc-root-class %s -verify
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core -analyzer-store=region -Wno-objc-root-class %s -verify
// expected-no-diagnostics
// The point of this test cases is to exercise properties in the static
diff --git a/test/Analysis/ObjCPropertiesSyntaxChecks.m b/test/Analysis/ObjCPropertiesSyntaxChecks.m
new file mode 100644
index 000000000000..5c642c581736
--- /dev/null
+++ b/test/Analysis/ObjCPropertiesSyntaxChecks.m
@@ -0,0 +1,61 @@
+// RUN: %clang_cc1 -w -fblocks -analyze -analyzer-checker=osx.ObjCProperty %s -verify
+
+#include "Inputs/system-header-simulator-objc.h"
+
+@interface I : NSObject {
+ NSMutableString *_mutableExplicitStr;
+ NSMutableString *_trulyMutableStr;
+ NSMutableString *_trulyMutableExplicitStr;
+}
+@property(copy) NSString *str; // no-warning
+@property(copy) NSMutableString *mutableStr; // expected-warning{{Property of mutable type 'NSMutableString' has 'copy' attribute; an immutable object will be stored instead}}
+@property(copy) NSMutableString *mutableExplicitStr; // expected-warning{{Property of mutable type 'NSMutableString' has 'copy' attribute; an immutable object will be stored instead}}
+@property(copy, readonly) NSMutableString *mutableReadonlyStr; // no-warning
+@property(copy, readonly) NSMutableString *mutableReadonlyStrOverriddenInChild; // no-warning
+@property(copy, readonly) NSMutableString *mutableReadonlyStrOverriddenInCategory; // no-warning
+@property(copy) NSMutableString *trulyMutableStr; // no-warning
+@property(copy) NSMutableString *trulyMutableExplicitStr; // no-warning
+@property(copy) NSMutableString *trulyMutableStrWithSynthesizedStorage; // no-warning
+@end
+
+@interface I () {}
+@property(copy) NSMutableString *mutableStrInCategory; // expected-warning{{Property of mutable type 'NSMutableString' has 'copy' attribute; an immutable object will be stored instead}}
+@property (copy, readwrite) NSMutableString *mutableReadonlyStrOverriddenInCategory; // expected-warning{{Property of mutable type 'NSMutableString' has 'copy' attribute; an immutable object will be stored instead}}
+@end
+
+@implementation I
+@synthesize mutableExplicitStr = _mutableExplicitStr;
+- (NSMutableString *)trulyMutableStr {
+ return _trulyMutableStr;
+}
+- (void)setTrulyMutableStr: (NSMutableString *) S {
+ _trulyMutableStr = [S mutableCopy];
+}
+@dynamic trulyMutableExplicitStr;
+- (NSMutableString *)trulyMutableExplicitStr {
+ return _trulyMutableExplicitStr;
+}
+- (void)setTrulyMutableExplicitStr: (NSMutableString *) S {
+ _trulyMutableExplicitStr = [S mutableCopy];
+}
+@synthesize trulyMutableStrWithSynthesizedStorage;
+- (NSMutableString *)trulyMutableStrWithSynthesizedStorage {
+ return trulyMutableStrWithSynthesizedStorage;
+}
+- (void)setTrulyMutableStrWithSynthesizedStorage: (NSMutableString *) S {
+ trulyMutableStrWithSynthesizedStorage = [S mutableCopy];
+}
+@end
+
+@interface J : I {}
+@property (copy, readwrite) NSMutableString *mutableReadonlyStrOverriddenInChild; // expected-warning{{Property of mutable type 'NSMutableString' has 'copy' attribute; an immutable object will be stored instead}}
+@end
+
+@implementation J
+@end
+
+// If we do not see the implementation then we do not want to warn,
+// because we may miss a user-defined setter that works correctly.
+@interface IWithoutImpl : NSObject {}
+@property(copy) NSMutableString *mutableStr; // no-warning
+@end
diff --git a/test/Analysis/PR2599.m b/test/Analysis/PR2599.m
index 47dadbf8894a..ac552ee613bd 100644
--- a/test/Analysis/PR2599.m
+++ b/test/Analysis/PR2599.m
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple %itanium_abi_triple -analyze -analyzer-checker=core,osx.cocoa.RetainCount,alpha.core -analyzer-constraints=range -analyzer-store=region -fobjc-gc -verify %s
+// RUN: %clang_cc1 -triple %itanium_abi_triple -analyze -analyzer-checker=core,osx.cocoa.RetainCount,alpha.core -analyzer-store=region -fobjc-gc -verify %s
typedef const void * CFTypeRef;
typedef const struct __CFString * CFStringRef;
diff --git a/test/Analysis/PR3991.m b/test/Analysis/PR3991.m
index 5f0919d6f0a6..68d5660287da 100644
--- a/test/Analysis/PR3991.m
+++ b/test/Analysis/PR3991.m
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core -analyzer-store=region -analyzer-constraints=range -verify -triple x86_64-apple-darwin9 -Wno-incomplete-implementation %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core -analyzer-store=region -verify -triple x86_64-apple-darwin9 -Wno-incomplete-implementation %s
// expected-no-diagnostics
//===----------------------------------------------------------------------===//
diff --git a/test/Analysis/additive-folding-range-constraints.c b/test/Analysis/additive-folding-range-constraints.c
index b22eb2a5b345..4baada8bf98a 100644
--- a/test/Analysis/additive-folding-range-constraints.c
+++ b/test/Analysis/additive-folding-range-constraints.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify -analyzer-constraints=range %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify %s
void clang_analyzer_eval(int);
diff --git a/test/Analysis/additive-folding.cpp b/test/Analysis/additive-folding.cpp
index c2e502623e94..6ae025bbac2e 100644
--- a/test/Analysis/additive-folding.cpp
+++ b/test/Analysis/additive-folding.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify -analyzer-constraints=range -Wno-tautological-compare %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify -Wno-tautological-compare %s
void clang_analyzer_eval(bool);
diff --git a/test/Analysis/analyzeOneFunction.m b/test/Analysis/analyzeOneFunction.m
index 1ff2fc8fe8a3..e70b2d7d5fbc 100644
--- a/test/Analysis/analyzeOneFunction.m
+++ b/test/Analysis/analyzeOneFunction.m
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -analyze -analyze-function="myMethodWithY:withX:" -analyzer-checker=core,osx.cocoa.RetainCount -analyzer-store=region -verify %s
+// RUN: %clang_cc1 -analyze -analyze-function="-[Test1 myMethodWithY:withX:]" -analyzer-checker=core,osx.cocoa.RetainCount -analyzer-store=region -verify %s
typedef signed char BOOL;
typedef unsigned int NSUInteger;
diff --git a/test/Analysis/analyze_display_progress.cpp b/test/Analysis/analyze_display_progress.cpp
deleted file mode 100644
index c84ab63de482..000000000000
--- a/test/Analysis/analyze_display_progress.cpp
+++ /dev/null
@@ -1,26 +0,0 @@
-// RUN: %clang_cc1 -analyze -analyzer-display-progress %s 2>&1 | FileCheck %s
-
-void f() {};
-void g() {};
-void h() {}
-
-struct SomeStruct {
- void f() {}
-};
-
-struct SomeOtherStruct {
- void f() {}
-};
-
-namespace ns {
- struct SomeStruct {
- void f() {}
- };
-}
-
-// CHECK: analyze_display_progress.cpp f
-// CHECK: analyze_display_progress.cpp g
-// CHECK: analyze_display_progress.cpp h
-// CHECK: analyze_display_progress.cpp SomeStruct::f
-// CHECK: analyze_display_progress.cpp SomeOtherStruct::f
-// CHECK: analyze_display_progress.cpp ns::SomeStruct::f
diff --git a/test/Analysis/analyzer-display-progress.cpp b/test/Analysis/analyzer-display-progress.cpp
new file mode 100644
index 000000000000..5d9f5e5b28f0
--- /dev/null
+++ b/test/Analysis/analyzer-display-progress.cpp
@@ -0,0 +1,30 @@
+// RUN: %clang_cc1 -analyze -analyzer-display-progress %s 2>&1 | FileCheck %s
+
+void f() {};
+void g() {};
+void h() {}
+
+struct SomeStruct {
+ void f() {}
+};
+
+struct SomeOtherStruct {
+ void f() {}
+};
+
+namespace ns {
+ struct SomeStruct {
+ void f(int) {}
+ void f(float, ::SomeStruct) {}
+ void f(float, SomeStruct) {}
+ };
+}
+
+// CHECK: analyzer-display-progress.cpp f()
+// CHECK: analyzer-display-progress.cpp g()
+// CHECK: analyzer-display-progress.cpp h()
+// CHECK: analyzer-display-progress.cpp SomeStruct::f()
+// CHECK: analyzer-display-progress.cpp SomeOtherStruct::f()
+// CHECK: analyzer-display-progress.cpp ns::SomeStruct::f(int)
+// CHECK: analyzer-display-progress.cpp ns::SomeStruct::f(float, ::SomeStruct)
+// CHECK: analyzer-display-progress.cpp ns::SomeStruct::f(float, struct ns::SomeStruct)
diff --git a/test/Analysis/analyzer-display-progress.m b/test/Analysis/analyzer-display-progress.m
new file mode 100644
index 000000000000..cc43cf36d60e
--- /dev/null
+++ b/test/Analysis/analyzer-display-progress.m
@@ -0,0 +1,30 @@
+// RUN: %clang_cc1 -fblocks -analyze -analyzer-display-progress %s 2>&1 | FileCheck %s
+
+#include "Inputs/system-header-simulator-objc.h"
+
+static void f() {}
+
+@interface I: NSObject
+-(void)instanceMethod:(int)arg1 with:(int)arg2;
++(void)classMethod;
+@end
+
+@implementation I
+-(void)instanceMethod:(int)arg1 with:(int)arg2 {}
++(void)classMethod {}
+@end
+
+void g(I *i, int x, int y) {
+ [I classMethod];
+ [i instanceMethod: x with: y];
+
+ void (^block)(void);
+ block = ^{};
+ block();
+}
+
+// CHECK: analyzer-display-progress.m f
+// CHECK: analyzer-display-progress.m -[I instanceMethod:with:]
+// CHECK: analyzer-display-progress.m +[I classMethod]
+// CHECK: analyzer-display-progress.m g
+// CHECK: analyzer-display-progress.m block (line: 22, col: 11)
diff --git a/test/Analysis/analyzer-enabled-checkers.c b/test/Analysis/analyzer-enabled-checkers.c
new file mode 100644
index 000000000000..e60de05d47a3
--- /dev/null
+++ b/test/Analysis/analyzer-enabled-checkers.c
@@ -0,0 +1,20 @@
+// RUN: %clang -target x86_64-apple-darwin10 --analyze %s -o /dev/null -Xclang -analyzer-checker=core -Xclang -analyzer-list-enabled-checkers > %t 2>&1
+// RUN: FileCheck --input-file=%t %s
+
+// CHECK: OVERVIEW: Clang Static Analyzer Enabled Checkers List
+// CHECK: core.CallAndMessage
+// CHECK: core.DivideZero
+// CHECK: core.DynamicTypePropagation
+// CHECK: core.NonNullParamChecker
+// CHECK: core.NullDereference
+// CHECK: core.StackAddressEscape
+// CHECK: core.UndefinedBinaryOperatorResult
+// CHECK: core.VLASize
+// CHECK: core.builtin.BuiltinFunctions
+// CHECK: core.builtin.NoReturnFunctions
+// CHECK: core.uninitialized.ArraySubscript
+// CHECK: core.uninitialized.Assign
+// CHECK: core.uninitialized.Branch
+// CHECK: core.uninitialized.CapturedBlockVariable
+// CHECK: core.uninitialized.UndefReturn
+
diff --git a/test/Analysis/array-struct-region.c b/test/Analysis/array-struct-region.c
index 6817124afe54..a41d04018458 100644
--- a/test/Analysis/array-struct-region.c
+++ b/test/Analysis/array-struct-region.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -analyzer-constraints=range -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -verify %s
void clang_analyzer_eval(int);
diff --git a/test/Analysis/array-struct.c b/test/Analysis/array-struct.c
index 28e09ad2e883..34bdc58ab5ae 100644
--- a/test/Analysis/array-struct.c
+++ b/test/Analysis/array-struct.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core.CastToStruct -analyzer-store=region -analyzer-constraints=range -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core.CastToStruct -analyzer-store=region -verify %s
struct s {
int data;
@@ -135,6 +135,17 @@ void f14() {
void bar(int*);
+struct s3 gets3() {
+ struct s3 s;
+ return s;
+}
+
+void accessArrayFieldNoCrash() {
+ bar(gets3().a);
+ bar((gets3().a));
+ bar(((gets3().a)));
+}
+
// Test if the array is correctly invalidated.
void f15() {
int a[10];
diff --git a/test/Analysis/block-in-critical-section.cpp b/test/Analysis/block-in-critical-section.cpp
new file mode 100644
index 000000000000..93c0b6dba665
--- /dev/null
+++ b/test/Analysis/block-in-critical-section.cpp
@@ -0,0 +1,50 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=alpha.unix.BlockInCriticalSection -std=c++11 -verify %s
+
+void sleep(int x) {}
+
+namespace std {
+struct mutex {
+ void lock() {}
+ void unlock() {}
+};
+}
+
+void testBlockInCriticalSection() {
+ std::mutex m;
+ m.lock();
+ sleep(3); // expected-warning {{A blocking function %s is called inside a critical section}}
+ m.unlock();
+}
+
+void testBlockInCriticalSectionWithNestedMutexes() {
+ std::mutex m, n, k;
+ m.lock();
+ n.lock();
+ k.lock();
+ sleep(3); // expected-warning {{A blocking function %s is called inside a critical section}}
+ k.unlock();
+ sleep(5); // expected-warning {{A blocking function %s is called inside a critical section}}
+ n.unlock();
+ sleep(3); // expected-warning {{A blocking function %s is called inside a critical section}}
+ m.unlock();
+ sleep(3); // no-warning
+}
+
+void f() {
+ sleep(1000); // expected-warning {{A blocking function %s is called inside a critical section}}
+}
+
+void testBlockInCriticalSectionInterProcedural() {
+ std::mutex m;
+ m.lock();
+ f();
+ m.unlock();
+}
+
+void testBlockInCriticalSectionUnexpectedUnlock() {
+ std::mutex m;
+ m.unlock();
+ sleep(1); // no-warning
+ m.lock();
+ sleep(1); // expected-warning {{A blocking function %s is called inside a critical section}}
+}
diff --git a/test/Analysis/blocks.m b/test/Analysis/blocks.m
index 0b1c15abb3b3..bf10c61d3a21 100644
--- a/test/Analysis/blocks.m
+++ b/test/Analysis/blocks.m
@@ -232,3 +232,12 @@ __attribute__((objc_root_class))
});
}
@end
+
+// The incorrect block variable initialization below is a hard compile-time
+// error in C++.
+#if !defined(__cplusplus)
+void call_block_with_fewer_arguments() {
+ void (^b)() = ^(int a) { };
+ b(); // expected-warning {{Block taking 1 argument is called with fewer (0)}}
+}
+#endif
diff --git a/test/Analysis/cast-to-struct.cpp b/test/Analysis/cast-to-struct.cpp
new file mode 100644
index 000000000000..45d55947c937
--- /dev/null
+++ b/test/Analysis/cast-to-struct.cpp
@@ -0,0 +1,67 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=alpha.core.CastToStruct,core -verify %s
+
+struct AB {
+ int A;
+ int B;
+};
+
+struct ABC {
+ int A;
+ int B;
+ int C;
+};
+
+struct Base {
+ Base() : A(0), B(0) {}
+ virtual ~Base() {}
+
+ int A;
+ int B;
+};
+
+struct Derived : public Base {
+ Derived() : Base(), C(0) {}
+ int C;
+};
+
+void structToStruct(struct AB *P) {
+ struct AB Ab;
+ struct ABC *Abc;
+ Abc = (struct ABC *)&Ab; // expected-warning {{Casting data to a larger structure type and accessing a field can lead to memory access errors or data corruption}}
+ Abc = (struct ABC *)P; // No warning; It is not known what data P points at.
+ Abc = (struct ABC *)&*P;
+
+ // Don't warn when the cast is not widening.
+ P = (struct AB *)&Ab; // struct AB * => struct AB *
+ struct ABC Abc2;
+ P = (struct AB *)&Abc2; // struct ABC * => struct AB *
+
+ // True negatives when casting from Base to Derived.
+ Derived D1, *D2;
+ Base &B1 = D1;
+ D2 = (Derived *)&B1;
+ D2 = dynamic_cast<Derived *>(&B1);
+ D2 = static_cast<Derived *>(&B1);
+
+ // True positives when casting from Base to Derived.
+ Base B2;
+ D2 = (Derived *)&B2;// expected-warning {{Casting data to a larger structure type and accessing a field can lead to memory access errors or data corruption}}
+ D2 = dynamic_cast<Derived *>(&B2);// expected-warning {{Casting data to a larger structure type and accessing a field can lead to memory access errors or data corruption}}
+ D2 = static_cast<Derived *>(&B2);// expected-warning {{Casting data to a larger structure type and accessing a field can lead to memory access errors or data corruption}}
+
+ // False negatives, cast from Base to Derived. With path sensitive analysis
+ // these false negatives could be fixed.
+ Base *B3 = &B2;
+ D2 = (Derived *)B3;
+ D2 = dynamic_cast<Derived *>(B3);
+ D2 = static_cast<Derived *>(B3);
+}
+
+void intToStruct(int *P) {
+ struct ABC *Abc;
+ Abc = (struct ABC *)P; // expected-warning {{Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption}}
+
+ // Cast from void *.
+ void *VP = P;
+ Abc = (struct ABC *)VP;
+}
diff --git a/test/Analysis/castexpr-callback.c b/test/Analysis/castexpr-callback.c
new file mode 100644
index 000000000000..73fa17a134a8
--- /dev/null
+++ b/test/Analysis/castexpr-callback.c
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=debug.AnalysisOrder -analyzer-config debug.AnalysisOrder:PreStmtCastExpr=true,debug.AnalysisOrder:PostStmtCastExpr=true %s 2>&1 | FileCheck %s
+
+void test(char c) {
+ int i = (int)c;
+}
+
+// CHECK: PreStmt<CastExpr> (Kind : LValueToRValue)
+// CHECK-NEXT: PostStmt<CastExpr> (Kind : LValueToRValue)
+// CHECK-NEXT: PreStmt<CastExpr> (Kind : IntegralCast)
+// CHECK-NEXT: PostStmt<CastExpr> (Kind : IntegralCast)
diff --git a/test/Analysis/casts.c b/test/Analysis/casts.c
index 42c05beb5945..b5e6e2784c8d 100644
--- a/test/Analysis/casts.c
+++ b/test/Analysis/casts.c
@@ -18,7 +18,7 @@ void getsockname();
void f(int sock) {
struct sockaddr_storage storage;
- struct sockaddr* sockaddr = (struct sockaddr*)&storage;
+ struct sockaddr* sockaddr = (struct sockaddr*)&storage; // expected-warning{{Casting data to a larger structure type and accessing a field can lead to memory access errors or data corruption}}
socklen_t addrlen = sizeof(storage);
getsockname(sock, sockaddr, &addrlen);
switch (sockaddr->sa_family) { // no-warning
diff --git a/test/Analysis/cfg.cpp b/test/Analysis/cfg.cpp
index 28cc440c46fc..3e34a0fac6af 100644
--- a/test/Analysis/cfg.cpp
+++ b/test/Analysis/cfg.cpp
@@ -92,7 +92,7 @@ void F(EmptyE e) {
// CHECK-NEXT: Succs (1): B1
// CHECK: [B1]
// CHECK-NEXT: 1: __builtin_object_size
-// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, BuiltinFnToFnPtr, unsigned long (*)(const void *, int))
+// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, BuiltinFnToFnPtr, unsigned long (*)(const void *, int) noexcept)
// CHECK-NEXT: 3: [B1.2](dummy(), 0)
// CHECK-NEXT: 4: (void)[B1.3] (CStyleCastExpr, ToVoid, void)
// CHECK-NEXT: Preds (1): B2
@@ -138,7 +138,7 @@ void test_deletedtor() {
// CHECK: [B1]
// CHECK-NEXT: 1: 5
// CHECK-NEXT: 2: CFGNewAllocator(A *)
-// CHECK-NEXT: 3: (CXXConstructExpr, class A)
+// CHECK-NEXT: 3: (CXXConstructExpr, class A [5])
// CHECK-NEXT: 4: new A {{\[\[}}B1.1]]
// CHECK-NEXT: 5: A *a = new A [5];
// CHECK-NEXT: 6: a
@@ -363,7 +363,7 @@ 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)
+// CHECK-NEXT: 7: (CXXConstructExpr, 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
@@ -432,7 +432,7 @@ void test_lifetime_extended_temporaries() {
}
-// CHECK-LABEL: int *PR18472()
+// CHECK-LABEL: template<> int *PR18472<int>()
// CHECK: [B2 (ENTRY)]
// CHECK-NEXT: Succs (1): B1
// CHECK: [B1]
diff --git a/test/Analysis/cfref_PR2519.c b/test/Analysis/cfref_PR2519.c
index 7fce2263c23b..d9642e5197d1 100644
--- a/test/Analysis/cfref_PR2519.c
+++ b/test/Analysis/cfref_PR2519.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount,alpha.core -analyzer-store=region -analyzer-constraints=range -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount,alpha.core -analyzer-store=region -verify %s
// expected-no-diagnostics
typedef unsigned char Boolean;
diff --git a/test/Analysis/cfref_rdar6080742.c b/test/Analysis/cfref_rdar6080742.c
index 0023d13703ab..7094660a352d 100644
--- a/test/Analysis/cfref_rdar6080742.c
+++ b/test/Analysis/cfref_rdar6080742.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core -analyzer-store=region -analyzer-constraints=range -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core -analyzer-store=region -verify %s
// expected-no-diagnostics
// This test case was reported in <rdar:problem/6080742>.
diff --git a/test/Analysis/comparison-implicit-casts.cpp b/test/Analysis/comparison-implicit-casts.cpp
index 96aa0ffe16b4..a991d438cb4c 100644
--- a/test/Analysis/comparison-implicit-casts.cpp
+++ b/test/Analysis/comparison-implicit-casts.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.cstring,debug.ExprInspection -analyzer-constraints=range -triple i386-apple-darwin9 -verify %s
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.cstring,debug.ExprInspection -analyzer-constraints=range -triple x86_64-apple-darwin9 -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.cstring,debug.ExprInspection -triple i386-apple-darwin9 -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.cstring,debug.ExprInspection -triple x86_64-apple-darwin9 -verify %s
// This file runs in C++ mode so that the comparison type is 'bool', not 'int'.
void clang_analyzer_eval(int);
diff --git a/test/Analysis/complex.c b/test/Analysis/complex.c
index 3900bcbfae68..6aca58948339 100644
--- a/test/Analysis/complex.c
+++ b/test/Analysis/complex.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-store=region -analyzer-constraints=range -verify -Wno-unreachable-code -ffreestanding %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-store=region -verify -Wno-unreachable-code -ffreestanding %s
#include <stdint.h>
diff --git a/test/Analysis/conditional-path-notes.c b/test/Analysis/conditional-path-notes.c
index 43f1e2692d8b..448af7f97fae 100644
--- a/test/Analysis/conditional-path-notes.c
+++ b/test/Analysis/conditional-path-notes.c
@@ -64,10 +64,12 @@ void testDiagnosableBranch(int a) {
}
}
-void testNonDiagnosableBranchLogical(int a, int b) {
+void testDiagnosableBranchLogical(int a, int b) {
if (a && b) {
- // expected-note@-1 {{Left side of '&&' is true}}
- // expected-note@-2 {{Taking true branch}}
+ // expected-note@-1 {{Assuming 'a' is not equal to 0}}
+ // expected-note@-2 {{Left side of '&&' is true}}
+ // expected-note@-3 {{Assuming 'b' is not equal to 0}}
+ // expected-note@-4 {{Taking true branch}}
*(volatile int *)0 = 1; // expected-warning{{Dereference of null pointer}}
// expected-note@-1 {{Dereference of null pointer}}
}
@@ -1342,6 +1344,35 @@ void testNonDiagnosableBranchArithmetic(int a, int b) {
// 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>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>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: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Assuming &apos;a&apos; is not equal to 0</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Assuming &apos;a&apos; is not equal to 0</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>control</string>
// CHECK-NEXT: <key>edges</key>
// CHECK-NEXT: <array>
@@ -1376,6 +1407,35 @@ void testNonDiagnosableBranchArithmetic(int a, int b) {
// 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>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>68</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>68</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: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Assuming &apos;b&apos; is not equal to 0</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Assuming &apos;b&apos; is not equal to 0</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>control</string>
// CHECK-NEXT: <key>edges</key>
// CHECK-NEXT: <array>
@@ -1396,12 +1456,12 @@ void testNonDiagnosableBranchArithmetic(int a, int b) {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>71</integer>
+// CHECK-NEXT: <key>line</key><integer>73</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>line</key><integer>73</integer>
// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1417,12 +1477,12 @@ void testNonDiagnosableBranchArithmetic(int a, int b) {
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>71</integer>
+// CHECK-NEXT: <key>line</key><integer>73</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>line</key><integer>73</integer>
// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1430,12 +1490,12 @@ void testNonDiagnosableBranchArithmetic(int a, int b) {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>71</integer>
+// CHECK-NEXT: <key>line</key><integer>73</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>71</integer>
+// CHECK-NEXT: <key>line</key><integer>73</integer>
// CHECK-NEXT: <key>col</key><integer>24</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1447,7 +1507,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>71</integer>
+// CHECK-NEXT: <key>line</key><integer>73</integer>
// CHECK-NEXT: <key>col</key><integer>24</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1455,12 +1515,12 @@ void testNonDiagnosableBranchArithmetic(int a, int b) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>71</integer>
+// CHECK-NEXT: <key>line</key><integer>73</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>line</key><integer>73</integer>
// CHECK-NEXT: <key>col</key><integer>26</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1478,13 +1538,13 @@ void testNonDiagnosableBranchArithmetic(int a, int b) {
// 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>ebd0bb32bbdcaa2a806ff1984974c07a</string>
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>a2b345c9681d9dd3aa15d12810759cb9</string>
// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testNonDiagnosableBranchLogical</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>4</string>
+// CHECK-NEXT: <key>issue_context</key><string>testDiagnosableBranchLogical</string>
+// CHECK-NEXT: <key>issue_hash_function_offset</key><string>6</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>71</integer>
+// CHECK-NEXT: <key>line</key><integer>73</integer>
// CHECK-NEXT: <key>col</key><integer>24</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1500,12 +1560,12 @@ void testNonDiagnosableBranchArithmetic(int a, int b) {
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>77</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>77</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>
@@ -1513,12 +1573,12 @@ void testNonDiagnosableBranchArithmetic(int a, int b) {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
+// CHECK-NEXT: <key>line</key><integer>81</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>79</integer>
+// CHECK-NEXT: <key>line</key><integer>81</integer>
// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1534,12 +1594,12 @@ void testNonDiagnosableBranchArithmetic(int a, int b) {
// CHECK-NEXT: <key>start</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
+// CHECK-NEXT: <key>line</key><integer>81</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>79</integer>
+// CHECK-NEXT: <key>line</key><integer>81</integer>
// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1547,12 +1607,12 @@ void testNonDiagnosableBranchArithmetic(int a, int b) {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
+// CHECK-NEXT: <key>line</key><integer>81</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>79</integer>
+// CHECK-NEXT: <key>line</key><integer>81</integer>
// CHECK-NEXT: <key>col</key><integer>24</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1564,7 +1624,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>79</integer>
+// CHECK-NEXT: <key>line</key><integer>81</integer>
// CHECK-NEXT: <key>col</key><integer>24</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1572,12 +1632,12 @@ void testNonDiagnosableBranchArithmetic(int a, int b) {
// CHECK-NEXT: <array>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>79</integer>
+// CHECK-NEXT: <key>line</key><integer>81</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>79</integer>
+// CHECK-NEXT: <key>line</key><integer>81</integer>
// CHECK-NEXT: <key>col</key><integer>26</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
@@ -1601,7 +1661,7 @@ void testNonDiagnosableBranchArithmetic(int a, int b) {
// 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>79</integer>
+// CHECK-NEXT: <key>line</key><integer>81</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/conversion.c b/test/Analysis/conversion.c
new file mode 100644
index 000000000000..f202696dc623
--- /dev/null
+++ b/test/Analysis/conversion.c
@@ -0,0 +1,125 @@
+// RUN: %clang_cc1 -Wno-conversion -analyze -analyzer-checker=core,alpha.core.Conversion -verify %s
+
+unsigned char U8;
+signed char S8;
+
+void assign(unsigned U, signed S) {
+ if (S < -10)
+ U8 = S; // expected-warning {{Loss of sign in implicit conversion}}
+ if (U > 300)
+ S8 = U; // expected-warning {{Loss of precision in implicit conversion}}
+ if (S > 10)
+ U8 = S;
+ if (U < 200)
+ S8 = U;
+}
+
+void init1() {
+ long long A = 1LL << 60;
+ short X = A; // expected-warning {{Loss of precision in implicit conversion}}
+}
+
+void relational(unsigned U, signed S) {
+ if (S > 10) {
+ if (U < S) {
+ }
+ }
+ if (S < -10) {
+ if (U < S) { // expected-warning {{Loss of sign in implicit conversion}}
+ }
+ }
+}
+
+void multiplication(unsigned U, signed S) {
+ if (S > 5)
+ S = U * S;
+ if (S < -10)
+ S = U * S; // expected-warning {{Loss of sign}}
+}
+
+void division(unsigned U, signed S) {
+ if (S > 5)
+ S = U / S;
+ if (S < -10)
+ S = U / S; // expected-warning {{Loss of sign}}
+}
+
+void dontwarn1(unsigned U, signed S) {
+ U8 = S; // It might be known that S is always 0x00-0xff.
+ S8 = U; // It might be known that U is always 0x00-0xff.
+
+ U8 = -1; // Explicit conversion.
+ S8 = ~0U; // Explicit conversion.
+ if (U > 300)
+ U8 &= U; // No loss of precision since there is &=.
+}
+
+void dontwarn2(unsigned int U) {
+ if (U <= 4294967295) {
+ }
+ if (U <= (2147483647 * 2U + 1U)) {
+ }
+}
+
+void dontwarn3(int X) {
+ S8 = X ? 'a' : 'b';
+}
+
+// don't warn for macros
+#define DOSTUFF ({ unsigned X = 1000; U8 = X; })
+void dontwarn4() {
+ DOSTUFF;
+}
+
+// don't warn for calculations
+// seen some fp. For instance: c2 = (c2 >= 'A' && c2 <= 'Z') ? c2 - 'A' + 'a' : c2;
+// there is a todo in the checker to handle calculations
+void dontwarn5() {
+ signed S = -32;
+ U8 = S + 10;
+}
+
+
+// false positives..
+
+int isascii(int c);
+void falsePositive1() {
+ char kb2[5];
+ int X = 1000;
+ if (isascii(X)) {
+ // FIXME: should not warn here:
+ kb2[0] = X; // expected-warning {{Loss of precision}}
+ }
+}
+
+
+typedef struct FILE {} FILE; int getc(FILE *stream);
+# define EOF (-1)
+char reply_string[8192];
+FILE *cin;
+extern int dostuff (void);
+int falsePositive2() {
+ int c, n;
+ int dig;
+ char *cp = reply_string;
+ int pflag = 0;
+ int code;
+
+ for (;;) {
+ dig = n = code = 0;
+ while ((c = getc(cin)) != '\n') {
+ if (dig < 4 && dostuff())
+ code = code * 10 + (c - '0');
+ if (!pflag && code == 227)
+ pflag = 1;
+ if (n == 0)
+ n = c;
+ if (c == EOF)
+ return(4);
+ if (cp < &reply_string[sizeof(reply_string) - 1])
+ // FIXME: should not warn here:
+ *cp++ = c; // expected-warning {{Loss of precision}}
+ }
+ }
+}
+
diff --git a/test/Analysis/copypaste/asm.cpp b/test/Analysis/copypaste/asm.cpp
new file mode 100644
index 000000000000..e93f119198a3
--- /dev/null
+++ b/test/Analysis/copypaste/asm.cpp
@@ -0,0 +1,44 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -analyze -analyzer-checker=alpha.clone.CloneChecker -verify %s
+
+// expected-no-diagnostics
+
+int foo1(int src) {
+ int dst = src;
+ if (src < 100 && src > 0) {
+
+ asm ("mov %1, %0\n\t"
+ "add $1, %0"
+ : "=r" (dst)
+ : "r" (src));
+
+ }
+ return dst;
+}
+
+// Identical to foo1 except that it adds two instead of one, so it's no clone.
+int foo2(int src) {
+ int dst = src;
+ if (src < 100 && src > 0) {
+
+ asm ("mov %1, %0\n\t"
+ "add $2, %0"
+ : "=r" (dst)
+ : "r" (src));
+
+ }
+ return dst;
+}
+
+// Identical to foo1 except that its a volatile asm statement, so it's no clone.
+int foo3(int src) {
+ int dst = src;
+ if (src < 100 && src > 0) {
+
+ asm volatile ("mov %1, %0\n\t"
+ "add $1, %0"
+ : "=r" (dst)
+ : "r" (src));
+
+ }
+ return dst;
+}
diff --git a/test/Analysis/copypaste/attributes.cpp b/test/Analysis/copypaste/attributes.cpp
new file mode 100644
index 000000000000..72d654c6e060
--- /dev/null
+++ b/test/Analysis/copypaste/attributes.cpp
@@ -0,0 +1,28 @@
+// RUN: %clang_cc1 -analyze -std=c++1z -analyzer-checker=alpha.clone.CloneChecker -verify %s
+
+// expected-no-diagnostics
+
+int foo1(int n) {
+ int result = 0;
+ switch (n) {
+ case 33:
+ result += 33;
+ [[clang::fallthrough]];
+ case 44:
+ result += 44;
+ }
+ return result;
+}
+
+// Identical to foo1 except the missing attribute.
+int foo2(int n) {
+ int result = 0;
+ switch (n) {
+ case 33:
+ result += 33;
+ ;
+ case 44:
+ result += 44;
+ }
+ return result;
+}
diff --git a/test/Analysis/copypaste/blocks.cpp b/test/Analysis/copypaste/blocks.cpp
new file mode 100644
index 000000000000..133b5cbcd6ac
--- /dev/null
+++ b/test/Analysis/copypaste/blocks.cpp
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -analyze -fblocks -std=c++11 -analyzer-checker=alpha.clone.CloneChecker -verify %s
+
+// This tests if we search for clones in blocks.
+
+void log();
+
+auto BlockA = ^(int a, int b){ // expected-warning{{Duplicate code detected}}
+ log();
+ if (a > b)
+ return a;
+ return b;
+};
+
+auto BlockB = ^(int a, int b){ // expected-note{{Similar code here}}
+ log();
+ if (a > b)
+ return a;
+ return b;
+};
diff --git a/test/Analysis/copypaste/call.cpp b/test/Analysis/copypaste/call.cpp
new file mode 100644
index 000000000000..8e95f7cb304a
--- /dev/null
+++ b/test/Analysis/copypaste/call.cpp
@@ -0,0 +1,102 @@
+// RUN: %clang_cc1 -analyze -std=c++1z -analyzer-checker=alpha.clone.CloneChecker -verify %s
+
+// expected-no-diagnostics
+
+bool a();
+bool b();
+
+// Calls method a with some extra code to pass the minimum complexity
+bool foo1(int x) {
+ if (x > 0)
+ return false;
+ else if (x < 0)
+ return a();
+ return true;
+}
+
+// Calls method b with some extra code to pass the minimum complexity
+bool foo2(int x) {
+ if (x > 0)
+ return false;
+ else if (x < 0)
+ return b();
+ return true;
+}
+
+// Test that we don't crash on function pointer calls
+
+bool (*funcPtr)(int);
+
+bool fooPtr1(int x) {
+ if (x > 0)
+ return false;
+ else if (x < 0)
+ return funcPtr(1);
+ return true;
+}
+
+// Test that we respect the template arguments of function templates
+
+template<typename T, unsigned N>
+bool templateFunc() { unsigned i = N; return false; }
+
+bool fooTemplate1(int x) {
+ if (x > 0)
+ return false;
+ else if (x < 0)
+ return templateFunc<int, 1>();
+ return true;
+}
+
+bool fooTemplate2(int x) {
+ if (x > 0)
+ return false;
+ else if (x < 0)
+ return templateFunc<long, 1>();
+ return true;
+}
+
+bool fooTemplate3(int x) {
+ if (x > 0)
+ return false;
+ else if (x < 0)
+ return templateFunc<long, 2>();
+ return true;
+}
+
+// Test that we don't just concatenate the template arguments into a string
+// without having any padding between them (e.g. foo<X, XX>() != foo<XX, X>()).
+
+class X {};
+class XX {};
+
+template<typename T1, typename T2>
+bool templatePaddingFunc() { return false; }
+
+bool fooTemplatePadding1(int x) {
+ if (x > 0)
+ return false;
+ else if (x < 0)
+ return templatePaddingFunc<X, XX>();
+ return true;
+}
+
+bool fooTemplatePadding2(int x) {
+ if (x > 0)
+ return false;
+ else if (x < 0)
+ return templatePaddingFunc<XX, X>();
+ return true;
+}
+
+// Test that we don't crash on member functions of template instantiations.
+
+template<typename T>
+struct A {
+ void foo(T t) {}
+};
+
+void fooTestInstantiation() {
+ A<int> a;
+ a.foo(1);
+}
diff --git a/test/Analysis/copypaste/catch.cpp b/test/Analysis/copypaste/catch.cpp
new file mode 100644
index 000000000000..590ce8f223f9
--- /dev/null
+++ b/test/Analysis/copypaste/catch.cpp
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -analyze -fcxx-exceptions -std=c++1z -analyzer-checker=alpha.clone.CloneChecker -verify %s
+
+// expected-no-diagnostics
+
+bool foo1(int x) {
+ if (x > 0)
+ return false;
+ else if (x < 0)
+ try { x--; } catch (int i) {}
+ return true;
+}
+
+// Uses parenthesis instead of type
+bool foo2(int x) {
+ if (x > 0)
+ return false;
+ else if (x < 0)
+ try { x--; } catch (...) {}
+ return true;
+}
+
+// Catches a different type (long instead of int)
+bool foo3(int x) {
+ if (x > 0)
+ return false;
+ else if (x < 0)
+ try { x--; } catch (long i) {}
+ return true;
+}
diff --git a/test/Analysis/copypaste/delete.cpp b/test/Analysis/copypaste/delete.cpp
new file mode 100644
index 000000000000..dc42c9c0595b
--- /dev/null
+++ b/test/Analysis/copypaste/delete.cpp
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -analyze -std=c++1z -analyzer-checker=alpha.clone.CloneChecker -verify %s
+
+// expected-no-diagnostics
+
+bool foo1(int x, int* a) {
+ if (x > 0)
+ return false;
+ else if (x < 0)
+ delete a;
+ return true;
+}
+
+// Explicit global delete
+bool foo2(int x, int* a) {
+ if (x > 0)
+ return false;
+ else if (x < 0)
+ ::delete a;
+ return true;
+}
+
+// Array delete
+bool foo3(int x, int* a) {
+ if (x > 0)
+ return false;
+ else if (x < 0)
+ delete[] a;
+ return true;
+}
diff --git a/test/Analysis/copypaste/dependent-exist.cpp b/test/Analysis/copypaste/dependent-exist.cpp
new file mode 100644
index 000000000000..5182ba61c9dc
--- /dev/null
+++ b/test/Analysis/copypaste/dependent-exist.cpp
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -analyze -fms-extensions -std=c++1z -analyzer-checker=alpha.clone.CloneChecker -verify %s
+
+// expected-no-diagnostics
+
+bool foo1(int x) {
+ if (x < 0) {
+ __if_exists(x) { return false; }
+ }
+ return true;
+}
+
+// Same as above, but __if_not_exists
+bool foo2(int x) {
+ if (x < 0) {
+ __if_not_exists(x) { return false; }
+ }
+ return true;
+}
diff --git a/test/Analysis/copypaste/expr-types.cpp b/test/Analysis/copypaste/expr-types.cpp
new file mode 100644
index 000000000000..14eef6eac636
--- /dev/null
+++ b/test/Analysis/copypaste/expr-types.cpp
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -analyze -std=c++11 -analyzer-checker=alpha.clone.CloneChecker -verify %s
+
+// expected-no-diagnostics
+
+
+int foo1(int a, int b) {
+ if (a > b)
+ return a;
+ return b;
+}
+
+// Different types, so not a clone
+int foo2(long a, long b) {
+ if (a > b)
+ return a;
+ return b;
+}
diff --git a/test/Analysis/copypaste/fold.cpp b/test/Analysis/copypaste/fold.cpp
new file mode 100644
index 000000000000..548dfb19af56
--- /dev/null
+++ b/test/Analysis/copypaste/fold.cpp
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -analyze -std=c++1z -analyzer-checker=alpha.clone.CloneChecker -verify %s
+
+// expected-no-diagnostics
+
+int global = 0;
+
+template<typename ...Args>
+int foo1(Args&&... args) {
+ if (global > 0)
+ return 0;
+ else if (global < 0)
+ return (args + ...);
+ return 1;
+}
+
+// Different opeator in fold expression.
+template<typename ...Args>
+int foo2(Args&&... args) {
+ if (global > 0)
+ return 0;
+ else if (global < 0)
+ return (args - ...);
+ return 1;
+}
+
+// Parameter pack on a different side
+template<typename ...Args>
+int foo3(Args&&... args) {
+ if (global > 0)
+ return 0;
+ else if (global < 0)
+ return -1;
+ return (... + args);
+return 1;
+}
diff --git a/test/Analysis/copypaste/function-try-block.cpp b/test/Analysis/copypaste/function-try-block.cpp
new file mode 100644
index 000000000000..7a69097579ab
--- /dev/null
+++ b/test/Analysis/copypaste/function-try-block.cpp
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -analyze -fcxx-exceptions -std=c++1z -analyzer-checker=alpha.clone.CloneChecker -verify %s
+
+// Tests if function try blocks are correctly handled.
+
+void nonCompoundStmt1(int& x)
+ try { x += 1; } catch(...) { x -= 1; } // expected-warning{{Duplicate code detected}}
+
+void nonCompoundStmt2(int& x)
+ try { x += 1; } catch(...) { x -= 1; } // expected-note{{Similar code here}}
diff --git a/test/Analysis/copypaste/functions.cpp b/test/Analysis/copypaste/functions.cpp
new file mode 100644
index 000000000000..c95443de72d1
--- /dev/null
+++ b/test/Analysis/copypaste/functions.cpp
@@ -0,0 +1,58 @@
+// RUN: %clang_cc1 -analyze -std=c++11 -analyzer-checker=alpha.clone.CloneChecker -verify %s
+
+// This tests if we search for clones in functions.
+
+void log();
+
+int max(int a, int b) { // expected-warning{{Duplicate code detected}}
+ log();
+ if (a > b)
+ return a;
+ return b;
+}
+
+int maxClone(int x, int y) { // expected-note{{Similar code here}}
+ log();
+ if (x > y)
+ return x;
+ return y;
+}
+
+// Functions below are not clones and should not be reported.
+
+// The next two functions test that statement classes are still respected when
+// checking for clones in expressions. This will show that the statement
+// specific data of all base classes is collected, and not just the data of the
+// first base class.
+int testBaseClass(int a, int b) { // no-warning
+ log();
+ if (a > b)
+ return true ? a : b;
+ return b;
+}
+int testBaseClass2(int a, int b) { // no-warning
+ log();
+ if (a > b)
+ return __builtin_choose_expr(true, a, b);
+ return b;
+}
+
+// No clone because of the different comparison operator.
+int min1(int a, int b) { // no-warning
+ log();
+ if (a < b)
+ return a;
+ return b;
+}
+
+// No clone because of the different pattern in which the variables are used.
+int min2(int a, int b) { // no-warning
+ log();
+ if (a > b)
+ return b;
+ return a;
+}
+
+int foo(int a, int b) { // no-warning
+ return a + b;
+}
diff --git a/test/Analysis/copypaste/generic.c b/test/Analysis/copypaste/generic.c
new file mode 100644
index 000000000000..9d8392139b39
--- /dev/null
+++ b/test/Analysis/copypaste/generic.c
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -analyze -std=c11 -analyzer-checker=alpha.clone.CloneChecker -verify %s
+
+// expected-no-diagnostics
+
+int global;
+
+int foo1() {
+ if (global > 0)
+ return 0;
+ else if (global < 0)
+ return _Generic(global, double: 1, float: 2, default: 3);
+ return 1;
+}
+
+// Different associated type (int instead of float)
+int foo2() {
+ if (global > 0)
+ return 0;
+ else if (global < 0)
+ return _Generic(global, double: 1, int: 2, default: 4);
+ return 1;
+}
+
+// Different number of associated types.
+int foo3() {
+ if (global > 0)
+ return 0;
+ else if (global < 0)
+ return _Generic(global, double: 1, default: 4);
+ return 1;
+}
diff --git a/test/Analysis/copypaste/labels.cpp b/test/Analysis/copypaste/labels.cpp
new file mode 100644
index 000000000000..26318ac40510
--- /dev/null
+++ b/test/Analysis/copypaste/labels.cpp
@@ -0,0 +1,51 @@
+// RUN: %clang_cc1 -analyze -std=gnu++11 -analyzer-checker=alpha.clone.CloneChecker -verify %s
+
+// expected-no-diagnostics
+
+
+bool foo1(int x) {
+ start:
+ if (x != 3) {
+ ++x;
+ void *ptr = &&start;
+ goto start;
+ }
+ end:
+ return false;
+}
+
+// Targeting a different label with the address-of-label operator.
+bool foo2(int x) {
+ start:
+ if (x != 3) {
+ ++x;
+ void *ptr = &&end;
+ goto start;
+ }
+ end:
+ return false;
+}
+
+// Different target label in goto
+bool foo3(int x) {
+ start:
+ if (x != 3) {
+ ++x;
+ void *ptr = &&start;
+ goto end;
+ }
+ end:
+ return false;
+}
+
+// FIXME: Can't detect same algorithm as in foo1 but with different label names.
+bool foo4(int x) {
+ foo:
+ if (x != 3) {
+ ++x;
+ void *ptr = &&foo;
+ goto foo;
+ }
+ end:
+ return false;
+}
diff --git a/test/Analysis/copypaste/lambda.cpp b/test/Analysis/copypaste/lambda.cpp
new file mode 100644
index 000000000000..c13c56f6671d
--- /dev/null
+++ b/test/Analysis/copypaste/lambda.cpp
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 -analyze -std=c++11 -analyzer-checker=alpha.clone.CloneChecker -verify %s
+
+// expected-no-diagnostics
+
+void foo1(int a, long b) {
+ auto l = [a, b](){};
+}
+
+void foo2(int a, long b) {
+ auto l = [&a, b](){};
+}
+
+void foo3(int a, long b) {
+ auto l = [a](){};
+}
+
+void foo4(int a, long b) {
+ auto l = [=](){};
+}
+
+void foo5(int a, long b) {
+ auto l = [&](){};
+}
+
diff --git a/test/Analysis/copypaste/macro-complexity.cpp b/test/Analysis/copypaste/macro-complexity.cpp
new file mode 100644
index 000000000000..aca4df1d025c
--- /dev/null
+++ b/test/Analysis/copypaste/macro-complexity.cpp
@@ -0,0 +1,50 @@
+// RUN: %clang_cc1 -analyze -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
+// influence the complexity. See the CloneSignature class in CloneDetection.h
+// for more information about complexity values of clones.
+
+#define MACRO_FOO(a, b) a > b ? -a * a : -b * b;
+
+// First, manually apply MACRO_FOO and see if the code gets detected as a clone.
+// This confirms that with the current configuration the macro body would be
+// considered large enough to pass the MinimumCloneComplexity constraint.
+
+int manualMacro(int a, int b) { // expected-warning{{Duplicate code detected}}
+ return a > b ? -a * a : -b * b;
+}
+
+int manualMacroClone(int a, int b) { // expected-note{{Similar code here}}
+ return a > b ? -a * a : -b * b;
+}
+
+// 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
+// value and the resulting code will never pass the MinimumCloneComplexity
+// constraint.
+
+int macro(int a, int b) {
+ return MACRO_FOO(a, b);
+}
+
+int macroClone(int a, int b) {
+ return MACRO_FOO(a, b);
+}
+
+// So far we only tested that macros increase the complexity by a lesser amount
+// than normal code. We also need to be sure this amount is not zero because
+// we otherwise macro code would be 'invisible' for the CloneDetector.
+// This tests that it is possible to increase the reach the minimum complexity
+// by only using macros. This is only possible if the complexity value is bigger
+// than zero.
+
+#define NEG(A) -(A)
+
+int nestedMacros() { // expected-warning{{Duplicate code detected}}
+ return NEG(NEG(NEG(NEG(NEG(NEG(NEG(NEG(NEG(NEG(1))))))))));
+}
+
+int nestedMacrosClone() { // expected-note{{Similar code here}}
+ return NEG(NEG(NEG(NEG(NEG(NEG(NEG(NEG(NEG(NEG(1))))))))));
+}
diff --git a/test/Analysis/copypaste/macros.cpp b/test/Analysis/copypaste/macros.cpp
new file mode 100644
index 000000000000..db9b4c6ee2e4
--- /dev/null
+++ b/test/Analysis/copypaste/macros.cpp
@@ -0,0 +1,67 @@
+// RUN: %clang_cc1 -analyze -std=c++11 -analyzer-checker=alpha.clone.CloneChecker -verify %s
+
+// Tests that macros and non-macro clones aren't mixed into the same hash
+// group. This is currently necessary as all clones in a hash group need
+// to have the same complexity value. Macros have smaller complexity values
+// and need to be in their own hash group.
+
+int foo(int a) { // expected-warning{{Duplicate code detected}}
+ a = a + 1;
+ a = a + 1 / 1;
+ a = a + 1 + 1 + 1;
+ a = a + 1 - 1 + 1 + 1;
+ a = a + 1 * 1 + 1 + 1 + 1;
+ a = a + 1 / 1 + 1 + 1 + 1;
+ return a;
+}
+
+int fooClone(int a) { // expected-note{{Similar code here}}
+ a = a + 1;
+ a = a + 1 / 1;
+ a = a + 1 + 1 + 1;
+ a = a + 1 - 1 + 1 + 1;
+ a = a + 1 * 1 + 1 + 1 + 1;
+ a = a + 1 / 1 + 1 + 1 + 1;
+ return a;
+}
+
+// Below is the same AST as above but this time generated with macros. The
+// clones below should land in their own hash group for the reasons given above.
+
+#define ASSIGN(T, V) T = T + V
+
+int macro(int a) { // expected-warning{{Duplicate code detected}}
+ ASSIGN(a, 1);
+ ASSIGN(a, 1 / 1);
+ ASSIGN(a, 1 + 1 + 1);
+ ASSIGN(a, 1 - 1 + 1 + 1);
+ ASSIGN(a, 1 * 1 + 1 + 1 + 1);
+ ASSIGN(a, 1 / 1 + 1 + 1 + 1);
+ return a;
+}
+
+int macroClone(int a) { // expected-note{{Similar code here}}
+ ASSIGN(a, 1);
+ ASSIGN(a, 1 / 1);
+ ASSIGN(a, 1 + 1 + 1);
+ ASSIGN(a, 1 - 1 + 1 + 1);
+ ASSIGN(a, 1 * 1 + 1 + 1 + 1);
+ ASSIGN(a, 1 / 1 + 1 + 1 + 1);
+ return a;
+}
+
+// FIXME: Macros with empty definitions in the AST are currently ignored.
+
+#define EMPTY
+
+int fooFalsePositiveClone(int a) { // expected-note{{Similar code here}}
+ a = EMPTY a + 1;
+ a = a + 1 / 1;
+ a = a + 1 + 1 + 1;
+ a = a + 1 - 1 + 1 + 1;
+ a = a + 1 * 1 + 1 + 1 + 1;
+ a = a + 1 / 1 + 1 + 1 + 1;
+ return a;
+}
+
+
diff --git a/test/Analysis/copypaste/objc-methods.m b/test/Analysis/copypaste/objc-methods.m
new file mode 100644
index 000000000000..9b8002c003a2
--- /dev/null
+++ b/test/Analysis/copypaste/objc-methods.m
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -analyze -Wno-objc-root-class -analyzer-checker=alpha.clone.CloneChecker -verify %s
+
+// This tests if we search for clones in Objective-C methods.
+
+@interface A
+- (int) setOk : (int) a : (int) b;
+@end
+
+@implementation A
+- (int) setOk : (int) a : (int) b { // expected-warning{{Duplicate code detected}}
+ if (a > b)
+ return a;
+ return b;
+}
+@end
+
+@interface B
+- (int) setOk : (int) a : (int) b;
+@end
+
+@implementation B
+- (int) setOk : (int) a : (int) b { // expected-note{{Similar code here}}
+ if (a > b)
+ return a;
+ return b;
+}
+@end
diff --git a/test/Analysis/copypaste/plist-diagnostics-notes-as-events.cpp b/test/Analysis/copypaste/plist-diagnostics-notes-as-events.cpp
new file mode 100644
index 000000000000..1180d447a7a3
--- /dev/null
+++ b/test/Analysis/copypaste/plist-diagnostics-notes-as-events.cpp
@@ -0,0 +1,97 @@
+// RUN: %clang_cc1 -analyze -analyzer-output=plist -analyzer-config notes-as-events=true -o %t.plist -std=c++11 -analyzer-checker=alpha.clone.CloneChecker -verify %s
+// RUN: FileCheck --input-file=%t.plist %s
+
+void log();
+
+int max(int a, int b) { // expected-warning{{Duplicate code detected}}
+ log();
+ if (a > b)
+ return a;
+ return b;
+}
+
+int maxClone(int a, int b) { // no-note (converted into event)
+ log();
+ if (a > b)
+ return a;
+ return b;
+}
+
+// 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>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>depth</key><integer>0</integer>
+// 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: <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>col</key><integer>23</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>6</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>11</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>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Duplicate code detected</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Duplicate code detected</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Duplicate code detected</string>
+// CHECK-NEXT: <key>category</key><string>Code clone</string>
+// CHECK-NEXT: <key>type</key><string>Exact code clone</string>
+// CHECK-NEXT: <key>check_name</key><string>alpha.clone.CloneChecker</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>3d15184f38c5fa57e479b744fe3f5035</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>6</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: </array>
diff --git a/test/Analysis/copypaste/plist-diagnostics.cpp b/test/Analysis/copypaste/plist-diagnostics.cpp
new file mode 100644
index 000000000000..109d8e4fc71f
--- /dev/null
+++ b/test/Analysis/copypaste/plist-diagnostics.cpp
@@ -0,0 +1,71 @@
+// RUN: %clang_cc1 -analyze -analyzer-output=plist -o %t.plist -std=c++11 -analyzer-checker=alpha.clone.CloneChecker -verify %s
+// RUN: FileCheck --input-file=%t.plist %s
+
+void log();
+
+int max(int a, int b) { // expected-warning{{Duplicate code detected}}
+ log();
+ if (a > b)
+ return a;
+ return b;
+}
+
+int maxClone(int a, int b) { // expected-note{{Similar code here}}
+ log();
+ if (a > b)
+ return a;
+ 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>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>6</integer>
+// CHECK-NEXT: <key>col</key><integer>23</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>6</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>11</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>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Duplicate code detected</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Duplicate code detected</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Duplicate code detected</string>
+// CHECK-NEXT: <key>category</key><string>Code clone</string>
+// CHECK-NEXT: <key>type</key><string>Exact code clone</string>
+// CHECK-NEXT: <key>check_name</key><string>alpha.clone.CloneChecker</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>3d15184f38c5fa57e479b744fe3f5035</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>6</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: </array>
diff --git a/test/Analysis/copypaste/sub-sequences.cpp b/test/Analysis/copypaste/sub-sequences.cpp
new file mode 100644
index 000000000000..ff73632e4353
--- /dev/null
+++ b/test/Analysis/copypaste/sub-sequences.cpp
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -analyze -std=c++11 -analyzer-checker=alpha.clone.CloneChecker -verify %s
+
+// This tests if sub-sequences can match with normal sequences.
+
+void log2(int a);
+void log();
+
+int max(int a, int b) {
+ log2(a);
+ log(); // expected-warning{{Duplicate code detected}}
+ if (a > b)
+ return a;
+ return b;
+}
+
+int maxClone(int a, int b) {
+ log(); // expected-note{{Similar code here}}
+ if (a > b)
+ return a;
+ return b;
+}
+
+// Functions below are not clones and should not be reported.
+
+int foo(int a, int b) { // no-warning
+ return a + b;
+}
diff --git a/test/Analysis/copypaste/suspicious-clones.cpp b/test/Analysis/copypaste/suspicious-clones.cpp
new file mode 100644
index 000000000000..c64a1dc8b8ff
--- /dev/null
+++ b/test/Analysis/copypaste/suspicious-clones.cpp
@@ -0,0 +1,97 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=alpha.clone.CloneChecker -analyzer-config alpha.clone.CloneChecker:ReportSuspiciousClones=true -analyzer-config alpha.clone.CloneChecker:ReportNormalClones=false -verify %s
+
+// Tests finding a suspicious clone that references local variables.
+
+void log();
+
+int max(int a, int b) {
+ log();
+ if (a > b)
+ return a;
+ return b; // expected-note{{Similar code using 'b' here}}
+}
+
+int maxClone(int x, int y, int z) {
+ log();
+ if (x > y)
+ return x;
+ return z; // expected-warning{{Potential copy-paste error; did you really mean to use 'z' here?}}
+}
+
+// Tests finding a suspicious clone that references global variables.
+
+struct mutex {
+ bool try_lock();
+ void unlock();
+};
+
+mutex m1;
+mutex m2;
+int i;
+
+void busyIncrement() {
+ while (true) {
+ if (m1.try_lock()) {
+ ++i;
+ m1.unlock(); // expected-note{{Similar code using 'm1' here}}
+ if (i > 1000) {
+ return;
+ }
+ }
+ }
+}
+
+void faultyBusyIncrement() {
+ while (true) {
+ if (m1.try_lock()) {
+ ++i;
+ m2.unlock(); // expected-warning{{Potential copy-paste error; did you really mean to use 'm2' here?}}
+ if (i > 1000) {
+ return;
+ }
+ }
+ }
+}
+
+// Tests that we provide two suggestions in cases where two fixes are possible.
+
+int foo(int a, int b, int c) {
+ a += b + c;
+ b /= a + b;
+ c -= b * a; // expected-warning{{Potential copy-paste error; did you really mean to use 'b' here?}}
+ return c;
+}
+
+int fooClone(int a, int b, int c) {
+ a += b + c;
+ b /= a + b;
+ c -= a * a; // expected-note{{Similar code using 'a' here}}
+ return c;
+}
+
+
+// Tests that for clone groups with a many possible suspicious clone pairs, at
+// most one warning per clone group is generated and every relevant clone is
+// reported through either a warning or a note.
+
+long bar1(long a, long b, long c, long d) {
+ c = a - b;
+ c = c / d * a;
+ d = b * b - c; // expected-warning{{Potential copy-paste error; did you really mean to use 'b' here?}}
+ return d;
+}
+
+long bar2(long a, long b, long c, long d) {
+ c = a - b;
+ c = c / d * a;
+ d = c * b - c; // expected-note{{Similar code using 'c' here}} \
+ // expected-warning{{Potential copy-paste error; did you really mean to use 'c' here?}}
+ return d;
+}
+
+long bar3(long a, long b, long c, long d) {
+ c = a - b;
+ c = c / d * a;
+ d = a * b - c; // expected-note{{Similar code using 'a' here}}
+ return d;
+}
diff --git a/test/Analysis/copypaste/text-diagnostics.cpp b/test/Analysis/copypaste/text-diagnostics.cpp
new file mode 100644
index 000000000000..a80afdb1eaf8
--- /dev/null
+++ b/test/Analysis/copypaste/text-diagnostics.cpp
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -analyze -analyzer-output=text -std=c++11 -analyzer-checker=alpha.clone.CloneChecker -verify %s
+
+void log();
+
+int max(int a, int b) { // expected-warning{{Duplicate code detected}} // expected-note{{Duplicate code detected}}
+ log();
+ if (a > b)
+ return a;
+ return b;
+}
+
+int maxClone(int a, int b) { // expected-note{{Similar code here}}
+ log();
+ if (a > b)
+ return a;
+ return b;
+}
diff --git a/test/Analysis/dead-stores.c b/test/Analysis/dead-stores.c
index cddb6c666ad5..c55b34ff2112 100644
--- a/test/Analysis/dead-stores.c
+++ b/test/Analysis/dead-stores.c
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -Wunused-variable -analyze -analyzer-checker=core,deadcode.DeadStores -fblocks -verify -Wno-unreachable-code -analyzer-opt-analyze-nested-blocks %s
-// RUN: %clang_cc1 -Wunused-variable -analyze -analyzer-checker=core,deadcode.DeadStores -analyzer-store=region -analyzer-constraints=range -fblocks -verify -Wno-unreachable-code -analyzer-opt-analyze-nested-blocks %s
+// RUN: %clang_cc1 -Wunused-variable -analyze -analyzer-checker=core,deadcode.DeadStores -analyzer-store=region -fblocks -verify -Wno-unreachable-code -analyzer-opt-analyze-nested-blocks %s
void f1() {
int k, y; // expected-warning{{unused variable 'k'}} expected-warning{{unused variable 'y'}}
diff --git a/test/Analysis/dead-stores.cpp b/test/Analysis/dead-stores.cpp
index 78cba161065f..77b349edd091 100644
--- a/test/Analysis/dead-stores.cpp
+++ b/test/Analysis/dead-stores.cpp
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fblocks -std=c++11 -analyze -analyzer-checker=deadcode.DeadStores -verify -Wno-unreachable-code %s
-// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fblocks -std=c++11 -analyze -analyzer-store=region -analyzer-constraints=range -analyzer-checker=deadcode.DeadStores -verify -Wno-unreachable-code %s
+// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fblocks -std=c++11 -analyze -analyzer-store=region -analyzer-checker=deadcode.DeadStores -verify -Wno-unreachable-code %s
//===----------------------------------------------------------------------===//
// Basic dead store checking (but in C++ mode).
diff --git a/test/Analysis/diagnostics/Inputs/include/plist-diagnostics-include-check-macro.def b/test/Analysis/diagnostics/Inputs/include/plist-diagnostics-include-check-macro.def
new file mode 100644
index 000000000000..9bbd9366906e
--- /dev/null
+++ b/test/Analysis/diagnostics/Inputs/include/plist-diagnostics-include-check-macro.def
@@ -0,0 +1 @@
+PLIST_DEF_MACRO
diff --git a/test/Analysis/diagnostics/Inputs/include/plist-diagnostics-include-check-macro.h b/test/Analysis/diagnostics/Inputs/include/plist-diagnostics-include-check-macro.h
new file mode 100644
index 000000000000..9ce68ed08d1a
--- /dev/null
+++ b/test/Analysis/diagnostics/Inputs/include/plist-diagnostics-include-check-macro.h
@@ -0,0 +1,9 @@
+void clang_analyzer_warnIfReached();
+
+class PlistCheckMacro {
+public:
+ PlistCheckMacro () { }
+ void run() {
+ clang_analyzer_warnIfReached();
+ }
+};
diff --git a/test/Analysis/diagnostics/diag-cross-file-boundaries.c b/test/Analysis/diagnostics/diag-cross-file-boundaries.c
new file mode 100644
index 000000000000..270163e85607
--- /dev/null
+++ b/test/Analysis/diagnostics/diag-cross-file-boundaries.c
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=core -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-output=html -o PR12421.html %s 2>&1 | FileCheck %s
+
+// Test for PR12421
+#include "diag-cross-file-boundaries.h"
+
+int main(){
+ f();
+ return 0;
+}
+
+// CHECK: warning: Path diagnostic report is not generated.
diff --git a/test/Analysis/diagnostics/diag-cross-file-boundaries.h b/test/Analysis/diagnostics/diag-cross-file-boundaries.h
new file mode 100644
index 000000000000..1af7d1f1fbb4
--- /dev/null
+++ b/test/Analysis/diagnostics/diag-cross-file-boundaries.h
@@ -0,0 +1,4 @@
+static void f() {
+ int *p = 0;
+ *p = 1; // expected-warning{{Dereference of null pointer}}
+}
diff --git a/test/Analysis/diagnostics/macros.cpp b/test/Analysis/diagnostics/macros.cpp
new file mode 100644
index 000000000000..8d7fccde1c61
--- /dev/null
+++ b/test/Analysis/diagnostics/macros.cpp
@@ -0,0 +1,48 @@
+// RUN: %clang_cc1 -analyze -std=c++11 -analyzer-checker=core,osx -analyzer-output=text -verify %s
+
+#include "../Inputs/system-header-simulator.h"
+#include "../Inputs/system-header-simulator-cxx.h"
+
+void testIntMacro(unsigned int i) {
+ if (i == UINT32_MAX) { // expected-note {{Assuming 'i' is equal to UINT32_MAX}}
+ // expected-note@-1 {{Taking true branch}}
+ char *p = NULL; // expected-note {{'p' initialized to a null pointer value}}
+ *p = 7; // expected-warning {{Dereference of null pointer (loaded from variable 'p')}}
+ // expected-note@-1 {{Dereference of null pointer (loaded from variable 'p')}}
+ }
+}
+
+void testNULLMacro(int *p) {
+ if (p == NULL) { // expected-note {{Assuming 'p' is equal to NULL}}
+ // expected-note@-1 {{Taking true branch}}
+ *p = 7; // expected-warning {{Dereference of null pointer (loaded from variable 'p')}}
+ // expected-note@-1 {{Dereference of null pointer (loaded from variable 'p')}}
+ }
+}
+
+void testnullptrMacro(int *p) {
+ if (p == nullptr) { // expected-note {{Assuming pointer value is null}}
+ // expected-note@-1 {{Taking true branch}}
+ *p = 7; // expected-warning {{Dereference of null pointer (loaded from variable 'p')}}
+ // expected-note@-1 {{Dereference of null pointer (loaded from variable 'p')}}
+ }
+}
+
+// There are no path notes on the comparison to float types.
+void testDoubleMacro(double d) {
+ if (d == DBL_MAX) { // expected-note {{Taking true branch}}
+
+ char *p = NULL; // expected-note {{'p' initialized to a null pointer value}}
+ *p = 7; // expected-warning {{Dereference of null pointer (loaded from variable 'p')}}
+ // expected-note@-1 {{Dereference of null pointer (loaded from variable 'p')}}
+ }
+}
+
+void testboolMacro(bool b, int *p) {
+ p = nullptr; // expected-note {{Null pointer value stored to 'p'}}
+ if (b == false) { // expected-note {{Assuming the condition is true}}
+ // expected-note@-1 {{Taking true branch}}
+ *p = 7; // expected-warning {{Dereference of null pointer (loaded from variable 'p')}}
+ // expected-note@-1 {{Dereference of null pointer (loaded from variable 'p')}}
+ }
+}
diff --git a/test/Analysis/diagnostics/macros.m b/test/Analysis/diagnostics/macros.m
new file mode 100644
index 000000000000..7ef80b302dd9
--- /dev/null
+++ b/test/Analysis/diagnostics/macros.m
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx -fblocks -analyzer-output=text -verify %s
+
+#include "../Inputs/system-header-simulator-objc.h"
+
+@interface NSDictionary : NSObject
+- (NSUInteger)count;
+- (id)objectForKey:(id)aKey;
+- (NSEnumerator *)keyEnumerator;
+@end
+@interface NSMutableDictionary : NSDictionary
+- (void)setObject:(id)anObject forKey:(id <NSCopying>)aKey;
+@end
+
+void testBOOLMacro(BOOL b) {
+ if (b == YES) { // expected-note {{Assuming 'b' is equal to YES}}
+ // expected-note@-1 {{Taking true branch}}
+ char *p = NULL;// expected-note {{'p' initialized to a null pointer value}}
+ *p = 7; // expected-warning {{Dereference of null pointer (loaded from variable 'p')}}
+ // expected-note@-1 {{Dereference of null pointer (loaded from variable 'p')}}
+ }
+}
+
+void testNilMacro(NSMutableDictionary *d, NSObject *o) {
+ if (o == nil) // expected-note {{Assuming 'o' is equal to nil}}
+ // expected-note@-1 {{Taking true branch}}
+ [d setObject:o forKey:[o description]]; // expected-warning {{Key argument to 'setObject:forKey:' cannot be nil}}
+ // expected-note@-1 {{'description' not called because the receiver is nil}}
+ // expected-note@-2 {{Key argument to 'setObject:forKey:' cannot be nil}}
+
+ return;
+}
diff --git a/test/Analysis/diagnostics/plist-diagnostics-include-check.cpp b/test/Analysis/diagnostics/plist-diagnostics-include-check.cpp
new file mode 100644
index 000000000000..6ed39451a8bc
--- /dev/null
+++ b/test/Analysis/diagnostics/plist-diagnostics-include-check.cpp
@@ -0,0 +1,140 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=debug.ExprInspection -analyzer-output=plist-multi-file %s -o %t.plist
+// RUN: FileCheck --input-file=%t.plist %s
+
+#include "Inputs/include/plist-diagnostics-include-check-macro.h"
+
+void foo() {
+ PlistCheckMacro()
+#define PLIST_DEF_MACRO .run();
+#include "Inputs/include/plist-diagnostics-include-check-macro.def"
+}
+
+// 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>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>1</integer>
+// CHECK-NEXT: <key>col</key><integer>15</integer>
+// CHECK-NEXT: <key>file</key><integer>2</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;PlistCheckMacro::run&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Calling &apos;PlistCheckMacro::run&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>6</integer>
+// CHECK-NEXT: <key>col</key><integer>3</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;foo&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Entered call from &apos;foo&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>6</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>6</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: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>7</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>1</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>7</integer>
+// CHECK-NEXT: <key>col</key><integer>32</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>7</integer>
+// CHECK-NEXT: <key>col</key><integer>5</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>7</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>1</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>7</integer>
+// CHECK-NEXT: <key>col</key><integer>34</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>REACHABLE</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>REACHABLE</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>REACHABLE</string>
+// CHECK-NEXT: <key>category</key><string>debug</string>
+// CHECK-NEXT: <key>type</key><string>Checking analyzer assumptions</string>
+// CHECK-NEXT: <key>check_name</key><string>debug.ExprInspection</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>93b4eab05b21c892c8e31723e5af3f59</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>C++ method</string>
+// CHECK-NEXT: <key>issue_context</key><string>run</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>7</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>1</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
diff --git a/test/Analysis/dispatch-once.m b/test/Analysis/dispatch-once.m
new file mode 100644
index 000000000000..7d54147aebe2
--- /dev/null
+++ b/test/Analysis/dispatch-once.m
@@ -0,0 +1,109 @@
+// RUN: %clang_cc1 -w -fblocks -analyze -analyzer-checker=core,osx.API,unix.Malloc -verify %s
+// RUN: %clang_cc1 -w -fblocks -fobjc-arc -analyze -analyzer-checker=core,osx.API,unix.Malloc -verify %s
+
+#include "Inputs/system-header-simulator-objc.h"
+
+typedef unsigned long size_t;
+void *calloc(size_t nmemb, size_t size);
+
+typedef void (^dispatch_block_t)(void);
+typedef long dispatch_once_t;
+void dispatch_once(dispatch_once_t *predicate, dispatch_block_t block);
+
+void test_stack() {
+ dispatch_once_t once;
+ dispatch_once(&once, ^{}); // expected-warning{{Call to 'dispatch_once' uses the local variable 'once' for the predicate value. Using such transient memory for the predicate is potentially dangerous. Perhaps you intended to declare the variable as 'static'?}}
+}
+
+void test_static_local() {
+ static dispatch_once_t once;
+ dispatch_once(&once, ^{}); // no-warning
+}
+
+void test_heap_var() {
+ dispatch_once_t *once = calloc(1, sizeof(dispatch_once_t));
+ // Use regexps to check that we're NOT suggesting to make this static.
+ dispatch_once(once, ^{}); // expected-warning-re{{{{^Call to 'dispatch_once' uses heap-allocated memory for the predicate value. Using such transient memory for the predicate is potentially dangerous$}}}}
+}
+
+void test_external_pointer(dispatch_once_t *once) {
+ // External pointer does not necessarily point to the heap.
+ dispatch_once(once, ^{}); // no-warning
+}
+
+typedef struct {
+ dispatch_once_t once;
+} Struct;
+
+void test_local_struct() {
+ Struct s;
+ dispatch_once(&s.once, ^{}); // expected-warning{{Call to 'dispatch_once' uses memory within the local variable 's' for the predicate value.}}
+}
+
+void test_heap_struct() {
+ Struct *s = calloc(1, sizeof(Struct));
+ dispatch_once(&s->once, ^{}); // expected-warning{{Call to 'dispatch_once' uses heap-allocated memory for the predicate value.}}
+}
+
+@interface Object : NSObject {
+@public
+ dispatch_once_t once;
+ Struct s;
+ dispatch_once_t once_array[2];
+}
+- (void)test_ivar_from_inside;
+- (void)test_ivar_struct_from_inside;
+@end
+
+@implementation Object
+- (void)test_ivar_from_inside {
+ dispatch_once(&once, ^{}); // expected-warning{{Call to 'dispatch_once' uses the instance variable 'once' for the predicate value.}}
+}
+- (void)test_ivar_struct_from_inside {
+ dispatch_once(&s.once, ^{}); // expected-warning{{Call to 'dispatch_once' uses memory within the instance variable 's' for the predicate value.}}
+}
+- (void)test_ivar_array_from_inside {
+ dispatch_once(&once_array[1], ^{}); // expected-warning{{Call to 'dispatch_once' uses memory within the instance variable 'once_array' for the predicate value.}}
+}
+@end
+
+void test_ivar_from_alloc_init() {
+ Object *o = [[Object alloc] init];
+ dispatch_once(&o->once, ^{}); // expected-warning{{Call to 'dispatch_once' uses the instance variable 'once' for the predicate value.}}
+}
+void test_ivar_struct_from_alloc_init() {
+ Object *o = [[Object alloc] init];
+ dispatch_once(&o->s.once, ^{}); // expected-warning{{Call to 'dispatch_once' uses memory within the instance variable 's' for the predicate value.}}
+}
+void test_ivar_array_from_alloc_init() {
+ Object *o = [[Object alloc] init];
+ dispatch_once(&o->once_array[1], ^{}); // expected-warning{{Call to 'dispatch_once' uses memory within the instance variable 'once_array' for the predicate value.}}
+}
+
+void test_ivar_from_external_obj(Object *o) {
+ // ObjC object pointer always points to the heap.
+ dispatch_once(&o->once, ^{}); // expected-warning{{Call to 'dispatch_once' uses the instance variable 'once' for the predicate value.}}
+}
+void test_ivar_struct_from_external_obj(Object *o) {
+ dispatch_once(&o->s.once, ^{}); // expected-warning{{Call to 'dispatch_once' uses memory within the instance variable 's' for the predicate value.}}
+}
+void test_ivar_array_from_external_obj(Object *o) {
+ dispatch_once(&o->once_array[1], ^{}); // expected-warning{{Call to 'dispatch_once' uses memory within the instance variable 'once_array' for the predicate value.}}
+}
+
+void test_block_var_from_block() {
+ __block dispatch_once_t once;
+ ^{
+ dispatch_once(&once, ^{}); // expected-warning{{Call to 'dispatch_once' uses the block variable 'once' for the predicate value.}}
+ };
+}
+
+void use_block_var(dispatch_once_t *once);
+
+void test_block_var_from_outside_block() {
+ __block dispatch_once_t once;
+ ^{
+ use_block_var(&once);
+ };
+ dispatch_once(&once, ^{}); // expected-warning{{Call to 'dispatch_once' uses the block variable 'once' for the predicate value.}}
+}
diff --git a/test/Analysis/edges-new.mm b/test/Analysis/edges-new.mm
index 07d1b6a5ac2e..5cc21e04ece0 100644
--- a/test/Analysis/edges-new.mm
+++ b/test/Analysis/edges-new.mm
@@ -2438,9 +2438,9 @@ namespace rdar14960554 {
// CHECK-NEXT: </array>
// CHECK-NEXT: <key>depth</key><integer>0</integer>
// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFNumberCreate&apos; returns a Core Foundation object with a +1 retain count</string>
+// CHECK-NEXT: <string>Call to function &apos;CFNumberCreate&apos; returns a Core Foundation object of type CFNumberRef with a +1 retain count</string>
// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFNumberCreate&apos; returns a Core Foundation object with a +1 retain count</string>
+// CHECK-NEXT: <string>Call to function &apos;CFNumberCreate&apos; returns a Core Foundation object of type CFNumberRef with a +1 retain count</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>control</string>
@@ -7344,6 +7344,35 @@ namespace rdar14960554 {
// 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>255</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>255</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>255</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>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>
@@ -7626,6 +7655,35 @@ namespace rdar14960554 {
// 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>263</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>263</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>263</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: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Assuming &apos;coin&apos; is not equal to 0</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Assuming &apos;coin&apos; is not equal to 0</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>control</string>
// CHECK-NEXT: <key>edges</key>
// CHECK-NEXT: <array>
@@ -7908,6 +7966,35 @@ namespace rdar14960554 {
// 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>263</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>263</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>263</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: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Assuming &apos;coin&apos; is 0</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Assuming &apos;coin&apos; is 0</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>control</string>
// CHECK-NEXT: <key>edges</key>
// CHECK-NEXT: <array>
@@ -8530,6 +8617,35 @@ namespace rdar14960554 {
// 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>276</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>276</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>276</integer>
+// CHECK-NEXT: <key>col</key><integer>57</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>
@@ -10834,6 +10950,69 @@ namespace rdar14960554 {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>420</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>420</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>420</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>420</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>420</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>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>420</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>420</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>421</integer>
// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
@@ -11075,6 +11254,69 @@ namespace rdar14960554 {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>430</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>430</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>
+// CHECK-NEXT: <key>line</key><integer>430</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>430</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>430</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>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>430</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>430</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: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>431</integer>
// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
@@ -11113,9 +11355,9 @@ namespace rdar14960554 {
// CHECK-NEXT: </array>
// CHECK-NEXT: <key>depth</key><integer>0</integer>
// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
+// CHECK-NEXT: <string>Method returns an instance of RDar10797980 with a +1 retain count</string>
// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
+// CHECK-NEXT: <string>Method returns an instance of RDar10797980 with a +1 retain count</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>control</string>
@@ -12046,6 +12288,69 @@ namespace rdar14960554 {
// 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>462</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>462</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>462</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>462</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>462</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>462</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>462</integer>
+// CHECK-NEXT: <key>col</key><integer>26</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>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -12083,12 +12388,12 @@ namespace rdar14960554 {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>3</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>462</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>col</key><integer>19</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -12459,6 +12764,69 @@ namespace rdar14960554 {
// 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>462</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>462</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>462</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>462</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>462</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>462</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>462</integer>
+// CHECK-NEXT: <key>col</key><integer>26</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 false</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Assuming the condition is false</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -12496,12 +12864,12 @@ namespace rdar14960554 {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>3</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>462</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>col</key><integer>19</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -12935,6 +13303,69 @@ namespace rdar14960554 {
// 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>462</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>462</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>462</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>462</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>462</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>462</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>462</integer>
+// CHECK-NEXT: <key>col</key><integer>26</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 false</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Assuming the condition is false</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -12972,12 +13403,12 @@ namespace rdar14960554 {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>3</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>462</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>col</key><integer>19</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -13697,6 +14128,69 @@ namespace rdar14960554 {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>493</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>493</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>
+// CHECK-NEXT: <key>line</key><integer>493</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>493</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>493</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: </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>493</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>493</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>494</integer>
// CHECK-NEXT: <key>col</key><integer>7</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
@@ -13779,6 +14273,69 @@ namespace rdar14960554 {
// 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>498</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>498</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>498</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>498</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>
+// CHECK-NEXT: <key>line</key><integer>498</integer>
+// CHECK-NEXT: <key>col</key><integer>15</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>498</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>498</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: </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>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -13816,12 +14373,12 @@ namespace rdar14960554 {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>3</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>498</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>
@@ -14192,6 +14749,69 @@ namespace rdar14960554 {
// 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>462</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>462</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>462</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>462</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>462</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>462</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>462</integer>
+// CHECK-NEXT: <key>col</key><integer>26</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 false</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Assuming the condition is false</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -14229,12 +14849,12 @@ namespace rdar14960554 {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>3</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>462</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>col</key><integer>19</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -14954,6 +15574,69 @@ namespace rdar14960554 {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>493</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>493</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>
+// CHECK-NEXT: <key>line</key><integer>493</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>493</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>493</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: </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>493</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>493</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>494</integer>
// CHECK-NEXT: <key>col</key><integer>7</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
@@ -15036,6 +15719,69 @@ namespace rdar14960554 {
// 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>498</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>498</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>498</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>498</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>
+// CHECK-NEXT: <key>line</key><integer>498</integer>
+// CHECK-NEXT: <key>col</key><integer>15</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>498</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>498</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: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Assuming the condition is false</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Assuming the condition is false</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -15073,12 +15819,12 @@ namespace rdar14960554 {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>3</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>498</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>
@@ -15099,6 +15845,69 @@ namespace rdar14960554 {
// 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>503</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>503</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>503</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>503</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>503</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>503</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>503</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: </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>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -15136,12 +15945,12 @@ namespace rdar14960554 {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>3</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>503</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>col</key><integer>10</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -15512,6 +16321,69 @@ namespace rdar14960554 {
// 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>462</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>462</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>462</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>462</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>462</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>462</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>462</integer>
+// CHECK-NEXT: <key>col</key><integer>26</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 false</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Assuming the condition is false</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -15549,12 +16421,12 @@ namespace rdar14960554 {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>3</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>462</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>col</key><integer>19</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -16274,6 +17146,69 @@ namespace rdar14960554 {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>493</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>493</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>
+// CHECK-NEXT: <key>line</key><integer>493</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>493</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>493</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: </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>493</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>493</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>494</integer>
// CHECK-NEXT: <key>col</key><integer>7</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
@@ -16356,6 +17291,69 @@ namespace rdar14960554 {
// 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>498</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>498</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>498</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>498</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>
+// CHECK-NEXT: <key>line</key><integer>498</integer>
+// CHECK-NEXT: <key>col</key><integer>15</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>498</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>498</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: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Assuming the condition is false</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Assuming the condition is false</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -16393,12 +17391,12 @@ namespace rdar14960554 {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>3</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>498</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>
@@ -16419,6 +17417,69 @@ namespace rdar14960554 {
// 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>503</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>503</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>503</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>503</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>503</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>503</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>503</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: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Assuming the condition is false</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Assuming the condition is false</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -16456,12 +17517,12 @@ namespace rdar14960554 {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>3</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>503</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>col</key><integer>10</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -16482,6 +17543,69 @@ namespace rdar14960554 {
// 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>508</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>508</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>508</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>508</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>508</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>508</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>508</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: </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>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -16519,12 +17643,12 @@ namespace rdar14960554 {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>508</integer>
-// CHECK-NEXT: <key>col</key><integer>3</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>508</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>col</key><integer>10</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -16599,6 +17723,69 @@ namespace rdar14960554 {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>510</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>510</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>
+// CHECK-NEXT: <key>line</key><integer>510</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>510</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>510</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: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Assuming the condition is false</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Assuming the condition is false</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>510</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>510</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>512</integer>
// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
@@ -16929,6 +18116,69 @@ namespace rdar14960554 {
// 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>462</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>462</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>462</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>462</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>462</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>462</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>462</integer>
+// CHECK-NEXT: <key>col</key><integer>26</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 false</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Assuming the condition is false</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -16966,12 +18216,12 @@ namespace rdar14960554 {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>462</integer>
-// CHECK-NEXT: <key>col</key><integer>3</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>462</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>col</key><integer>19</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -17691,6 +18941,69 @@ namespace rdar14960554 {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>493</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>493</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>
+// CHECK-NEXT: <key>line</key><integer>493</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>493</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>493</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: </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>493</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>493</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>494</integer>
// CHECK-NEXT: <key>col</key><integer>7</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
@@ -17773,6 +19086,69 @@ namespace rdar14960554 {
// 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>498</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>498</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>498</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>498</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>
+// CHECK-NEXT: <key>line</key><integer>498</integer>
+// CHECK-NEXT: <key>col</key><integer>15</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>498</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>498</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: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Assuming the condition is false</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Assuming the condition is false</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -17810,12 +19186,12 @@ namespace rdar14960554 {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>498</integer>
-// CHECK-NEXT: <key>col</key><integer>3</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>498</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>
@@ -17836,6 +19212,69 @@ namespace rdar14960554 {
// 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>503</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>503</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>503</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>503</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>503</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>503</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>503</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: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Assuming the condition is false</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Assuming the condition is false</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -17873,12 +19312,12 @@ namespace rdar14960554 {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>503</integer>
-// CHECK-NEXT: <key>col</key><integer>3</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>503</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>col</key><integer>10</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -17899,6 +19338,69 @@ namespace rdar14960554 {
// 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>508</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>508</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>508</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>508</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>508</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>508</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>508</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: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Assuming the condition is false</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Assuming the condition is false</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>event</string>
// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
@@ -17936,12 +19438,12 @@ namespace rdar14960554 {
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>line</key><integer>508</integer>
-// CHECK-NEXT: <key>col</key><integer>3</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>508</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>col</key><integer>10</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
@@ -18079,6 +19581,69 @@ namespace rdar14960554 {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>517</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>517</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>
+// CHECK-NEXT: <key>line</key><integer>517</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>517</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>517</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: </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>517</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>517</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>518</integer>
// CHECK-NEXT: <key>col</key><integer>7</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
@@ -18760,9 +20325,9 @@ namespace rdar14960554 {
// CHECK-NEXT: </array>
// CHECK-NEXT: <key>depth</key><integer>0</integer>
// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
+// CHECK-NEXT: <string>Method returns an instance of NSObject with a +1 retain count</string>
// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
+// 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>
diff --git a/test/Analysis/explain-svals.cpp b/test/Analysis/explain-svals.cpp
index c0ed74914ed7..be2f83037051 100644
--- a/test/Analysis/explain-svals.cpp
+++ b/test/Analysis/explain-svals.cpp
@@ -47,7 +47,7 @@ void test_2(char *ptr, int ext) {
clang_analyzer_explain(glob_ptr); // expected-warning-re{{{{^value derived from \(symbol of type 'int' conjured at statement 'conjure\(\)'\) for global variable 'glob_ptr'$}}}}
clang_analyzer_explain(clang_analyzer_getExtent(ptr)); // expected-warning-re{{{{^extent of pointee of argument 'ptr'$}}}}
int *x = new int[ext];
- clang_analyzer_explain(x); // expected-warning-re{{{{^pointer to element of type 'int' with index 0 of pointee of symbol of type 'int \*' conjured at statement 'new int \[ext\]'$}}}}
+ clang_analyzer_explain(x); // expected-warning-re{{{{^pointer to element of type 'int' with index 0 of heap segment that starts at symbol of type 'int \*' conjured at statement 'new int \[ext\]'$}}}}
// Sic! What gets computed is the extent of the element-region.
clang_analyzer_explain(clang_analyzer_getExtent(x)); // expected-warning-re{{{{^signed 32-bit integer '4'$}}}}
delete[] x;
@@ -76,7 +76,7 @@ void test_4(int x, int y) {
clang_analyzer_explain(&stat); // expected-warning-re{{{{^pointer to static local variable 'stat'$}}}}
clang_analyzer_explain(stat_glob); // expected-warning-re{{{{^initial value of global variable 'stat_glob'$}}}}
clang_analyzer_explain(&stat_glob); // expected-warning-re{{{{^pointer to global variable 'stat_glob'$}}}}
- clang_analyzer_explain((int[]){1, 2, 3}); // expected-warning-re{{{{^pointer to element of type 'int' with index 0 of compound literal \(int \[3\]\)\{1, 2, 3\}$}}}}
+ clang_analyzer_explain((int[]){1, 2, 3}); // expected-warning-re{{{{^pointer to element of type 'int' with index 0 of temporary object constructed at statement '\(int \[3\]\)\{1, 2, 3\}'$}}}}
}
namespace {
diff --git a/test/Analysis/explain-svals.m b/test/Analysis/explain-svals.m
new file mode 100644
index 000000000000..34cdacfa282c
--- /dev/null
+++ b/test/Analysis/explain-svals.m
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -w -triple i386-apple-darwin10 -fblocks -analyze -analyzer-checker=core.builtin,debug.ExprInspection -verify %s
+
+#include "Inputs/system-header-simulator-objc.h"
+
+void clang_analyzer_explain(void *);
+
+@interface Object : NSObject {
+@public
+ Object *x;
+}
+@end
+
+void test_1(Object *p) {
+ clang_analyzer_explain(p); // expected-warning-re{{{{^argument 'p'$}}}}
+ clang_analyzer_explain(p->x); // expected-warning-re{{{{^initial value of instance variable 'x' of object at argument 'p'$}}}}
+ Object *q = [[Object alloc] init];
+ clang_analyzer_explain(q); // expected-warning-re{{{{^symbol of type 'Object \*' conjured at statement '\[\[Object alloc\] init\]'$}}}}
+ clang_analyzer_explain(q->x); // expected-warning-re{{{{^initial value of instance variable 'x' of object at symbol of type 'Object \*' conjured at statement '\[\[Object alloc\] init\]'$}}}}
+}
+
+void test_2() {
+ __block int x;
+ ^{
+ clang_analyzer_explain(&x); // expected-warning-re{{{{^pointer to block variable 'x'$}}}}
+ };
+ clang_analyzer_explain(&x); // expected-warning-re{{{{^pointer to block variable 'x'$}}}}
+}
diff --git a/test/Analysis/expr-inspection.c b/test/Analysis/expr-inspection.c
new file mode 100644
index 000000000000..69e18cb1e686
--- /dev/null
+++ b/test/Analysis/expr-inspection.c
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=debug.ExprInspection -verify %s 2>&1 | FileCheck %s
+
+// Self-tests for the debug.ExprInspection checker.
+
+void clang_analyzer_dump(int x);
+void clang_analyzer_printState();
+void clang_analyzer_numTimesReached();
+
+void foo(int x) {
+ clang_analyzer_dump(x); // expected-warning{{reg_$0<int x>}}
+ int y = 1;
+ clang_analyzer_printState();
+ for (; y < 3; ++y)
+ clang_analyzer_numTimesReached(); // expected-warning{{2}}
+}
+
+// CHECK: Store (direct and default bindings)
+// CHECK-NEXT: (y,0,direct) : 1 S32b
+
+// CHECK: Expressions:
+// CHECK-NEXT: clang_analyzer_printState : &code{clang_analyzer_printState}
+// CHECK-NEXT: Ranges are empty.
diff --git a/test/Analysis/generics.m b/test/Analysis/generics.m
index 490ac5dc8ad0..da5c5126566c 100644
--- a/test/Analysis/generics.m
+++ b/test/Analysis/generics.m
@@ -43,11 +43,18 @@ __attribute__((objc_root_class))
+ (instancetype)getEmpty;
+ (NSArray<ObjectType> *)getEmpty2;
- (BOOL)contains:(ObjectType)obj;
+- (BOOL)containsObject:(ObjectType)anObject;
- (ObjectType)getObjAtIndex:(NSUInteger)idx;
- (ObjectType)objectAtIndexedSubscript:(NSUInteger)idx;
+- (NSArray<ObjectType> *)arrayByAddingObject:(ObjectType)anObject;
@property(readonly) ObjectType firstObject;
@end
+@interface NSMutableArray<ObjectType> : NSArray<ObjectType>
+- (void)addObject:(ObjectType)anObject;
+- (instancetype)init;
+@end
+
@interface MutableArray<ObjectType> : NSArray<ObjectType>
- (void)addObject:(ObjectType)anObject;
@end
@@ -87,41 +94,51 @@ void withArrMutableString(NSArray<NSMutableString *> *);
void withMutArrString(MutableArray<NSString *> *);
void withMutArrMutableString(MutableArray<NSMutableString *> *);
-void incompatibleTypesErased(NSArray *a, NSArray<NSString *> *b,
- NSArray<NSNumber *> *c) {
+void incompatibleTypesErased(NSArray *a, NSMutableArray<NSString *> *b,
+ NSArray<NSNumber *> *c,
+ NSMutableArray *d) {
a = b;
- c = a; // expected-warning {{Conversion from value of type 'NSArray<NSString *> *' to incompatible type 'NSArray<NSNumber *> *'}}
- [a contains: [[NSNumber alloc] init]]; // expected-warning {{Conversion}}
+ c = a; // expected-warning {{Conversion from value of type 'NSMutableArray<NSString *> *' to incompatible type 'NSArray<NSNumber *> *'}}
+ [a contains: [[NSNumber alloc] init]];
[a contains: [[NSString alloc] init]];
doStuff(a); // expected-warning {{Conversion}}
+
+ d = b;
+ [d addObject: [[NSNumber alloc] init]]; // expected-warning {{Conversion from value of type 'NSNumber *' to incompatible type 'NSString *'}}
}
void crossProceduralErasedTypes() {
NSArray<NSString *> *a = getTypedStuff(); // expected-warning {{Conversion}}
}
-void incompatibleTypesErasedReverseConversion(NSArray *a,
- NSArray<NSString *> *b) {
+void incompatibleTypesErasedReverseConversion(NSMutableArray *a,
+ NSMutableArray<NSString *> *b) {
b = a;
- [a contains: [[NSNumber alloc] init]]; // expected-warning {{Conversion}}
+ [a contains: [[NSNumber alloc] init]];
[a contains: [[NSString alloc] init]];
doStuff(a); // expected-warning {{Conversion}}
+
+ [a addObject: [[NSNumber alloc] init]]; // expected-warning {{Conversion from value of type 'NSNumber *' to incompatible type 'NSString *'}}
}
-void idErasedIncompatibleTypesReverseConversion(id a, NSArray<NSString *> *b) {
+void idErasedIncompatibleTypesReverseConversion(id a, NSMutableArray<NSString *> *b) {
b = a;
- [a contains: [[NSNumber alloc] init]]; // expected-warning {{Conversion}}
+ [a contains: [[NSNumber alloc] init]];
[a contains: [[NSString alloc] init]];
doStuff(a); // expected-warning {{Conversion}}
+
+ [a addObject:[[NSNumber alloc] init]]; // expected-warning {{Conversion from value of type 'NSNumber *' to incompatible type 'NSString *'}}
}
-void idErasedIncompatibleTypes(id a, NSArray<NSString *> *b,
+void idErasedIncompatibleTypes(id a, NSMutableArray<NSString *> *b,
NSArray<NSNumber *> *c) {
a = b;
c = a; // expected-warning {{Conversion}}
- [a contains: [[NSNumber alloc] init]]; // expected-warning {{Conversion}}
+ [a contains: [[NSNumber alloc] init]];
[a contains: [[NSString alloc] init]];
doStuff(a); // expected-warning {{Conversion}}
+
+ [a addObject:[[NSNumber alloc] init]]; // expected-warning {{Conversion from value of type 'NSNumber *' to incompatible type 'NSString *'}}
}
void pathSensitiveInference(MutableArray *m, MutableArray<NSString *> *a,
@@ -161,9 +178,11 @@ void genericSubtypeOfGeneric(id d, ExceptionalArray<NSString *> *a,
MutableArray<NSNumber *> *c) {
d = a;
[d contains: [[NSString alloc] init]];
- [d contains: [[NSNumber alloc] init]]; // expected-warning {{Conversion}}
+ [d contains: [[NSNumber alloc] init]];
b = d;
c = d; // expected-warning {{Conversion}}
+
+ [d addObject: [[NSNumber alloc] init]]; // expected-warning {{Conversion from value of type 'NSNumber *' to incompatible type 'NSString *'}}
}
void genericSubtypeOfGenericReverse(id d, ExceptionalArray<NSString *> *a,
@@ -171,9 +190,11 @@ void genericSubtypeOfGenericReverse(id d, ExceptionalArray<NSString *> *a,
MutableArray<NSNumber *> *c) {
a = d;
[d contains: [[NSString alloc] init]];
- [d contains: [[NSNumber alloc] init]]; // expected-warning {{Conversion}}
+ [d contains: [[NSNumber alloc] init]];
b = d;
c = d; // expected-warning {{Conversion}}
+
+ [d addObject: [[NSNumber alloc] init]]; // expected-warning {{Conversion from value of type 'NSNumber *' to incompatible type 'NSString *'}}
}
void inferenceFromAPI(id a) {
@@ -277,7 +298,7 @@ void testUnannotatedLiterals() {
void testAnnotatedLiterals() {
NSArray<NSString *> *arr = @[@"A", @"B"];
NSArray *arr2 = arr;
- [arr2 contains: [[NSNumber alloc] init]]; // expected-warning {{Conversion}}
+ [arr2 contains: [[NSNumber alloc] init]];
}
void nonExistentMethodDoesNotCrash(id a, MutableArray<NSMutableString *> *b) {
@@ -343,6560 +364,6780 @@ void testGetMostInformativeDerivedForId(NSArray<NSString *> *a,
[x takesType:[[NSNumber alloc] init]]; // expected-warning {{Conversion from value of type 'NSNumber *' to incompatible type 'NSString *'}}
}
-// 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>92</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>92</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>92</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>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSArray&lt;NSString *&gt; *&apos; to &apos;NSArray *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSArray&lt;NSString *&gt; *&apos; to &apos;NSArray *&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>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>93</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>93</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>
+void testArgumentAfterUpcastToRootWithCovariantTypeParameter(NSArray<NSString *> *allStrings, NSNumber *number) {
+ NSArray<NSObject *> *allObjects = allStrings; // no-warning
+ NSArray<NSObject *> *moreObjects = [allObjects arrayByAddingObject:number]; // no-warning
+}
+
+void testArgumentAfterUpcastWithCovariantTypeParameter(NSArray<NSMutableString *> *allMutableStrings, NSNumber *number) {
+ NSArray<NSString *> *allStrings = allMutableStrings; // no-warning
+ id numberAsId = number;
+ NSArray<NSString *> *moreStrings = [allStrings arrayByAddingObject:numberAsId]; // Sema: expected-warning {{Object has a dynamic type 'NSNumber *' which is incompatible with static type 'NSString *'}}
+}
+
+void testArgumentAfterCastToUnspecializedWithCovariantTypeParameter(NSArray<NSMutableString *> *allMutableStrings, NSNumber *number) {
+ NSArray *allStrings = allMutableStrings; // no-warning
+ id numberAsId = number;
+
+ NSArray *moreStringsUnspecialized = [allStrings arrayByAddingObject:numberAsId]; // no-warning
+
+ // Ideally the analyzer would warn here.
+ NSArray<NSString *> *moreStringsSpecialized = [allStrings arrayByAddingObject:numberAsId];
+}
+
+void testCallToMethodWithCovariantParameterOnInstanceOfSubclassWithInvariantParameter(NSMutableArray<NSMutableString *> *mutableArrayOfMutableStrings, NSString *someString) {
+ NSArray<NSString *> *arrayOfStrings = mutableArrayOfMutableStrings;
+ [arrayOfStrings containsObject:someString]; // no-warning
+}
+
+// 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>100</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: <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>3</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>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>93</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>93</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: <key>line</key><integer>100</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>100</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: </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>93</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSMutableArray&lt;NSString *&gt; *&apos; to &apos;NSArray *&apos;)</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSMutableArray&lt;NSString *&gt; *&apos; to &apos;NSArray *&apos;)</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</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>line</key><integer>93</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>93</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// 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>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>101</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>101</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>9632a21d129601d531e0b4585a27c686</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>incompatibleTypesErased</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>93</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: <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>92</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: </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>line</key><integer>92</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>92</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>101</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>101</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>101</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>101</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSArray&lt;NSString *&gt; *&apos; to &apos;NSArray *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSArray&lt;NSString *&gt; *&apos; to &apos;NSArray *&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// 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>101</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: <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>94</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>94</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: <key>line</key><integer>101</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>101</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: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
+// CHECK-NEXT: <key>type</key><string>Generics</string>
+// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>33d4584e2bf66b029ab9d152cc9cd8f7</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>incompatibleTypesErased</string>
+// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>101</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: <dict>
+// CHECK-NEXT: <key>path</key>
+// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>94</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>kind</key><string>event</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>100</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>100</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>100</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>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSMutableArray&lt;NSString *&gt; *&apos; to &apos;NSArray *&apos;)</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSMutableArray&lt;NSString *&gt; *&apos; to &apos;NSArray *&apos;)</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</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>line</key><integer>94</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>94</integer>
-// CHECK-NEXT: <key>col</key><integer>38</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// 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>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>104</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>104</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>3c9499ea9f5adc148d5c4b684e3dcc5a</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>incompatibleTypesErased</string>
-// 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>94</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: <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>92</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: </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>line</key><integer>92</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>92</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>104</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>104</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>104</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>104</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSArray&lt;NSString *&gt; *&apos; to &apos;NSArray *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSArray&lt;NSString *&gt; *&apos; to &apos;NSArray *&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// 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>104</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>
// 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>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>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: <key>line</key><integer>104</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>104</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: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
+// CHECK-NEXT: <key>type</key><string>Generics</string>
+// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>6edc910aaa9dc1f2d823abc8cb75360f</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>incompatibleTypesErased</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>104</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: <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>100</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: <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>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>96</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>96</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: <key>line</key><integer>100</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>100</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: </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>96</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSMutableArray&lt;NSString *&gt; *&apos; to &apos;NSArray *&apos;)</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSMutableArray&lt;NSString *&gt; *&apos; to &apos;NSArray *&apos;)</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</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>line</key><integer>96</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>96</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// 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>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>107</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>107</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>1d8497465a98d7cc2067a916e217d5bc</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>incompatibleTypesErased</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>96</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: <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: </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>107</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: <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>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>100</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>100</integer>
-// CHECK-NEXT: <key>col</key><integer>40</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: <key>line</key><integer>107</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>107</integer>
+// CHECK-NEXT: <key>col</key><integer>39</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
// 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>100</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
+// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
+// CHECK-NEXT: <key>type</key><string>Generics</string>
+// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>73c71c858082f5d7a2258f707927da3c</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>incompatibleTypesErased</string>
+// 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>107</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: <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>line</key><integer>100</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>100</integer>
-// CHECK-NEXT: <key>col</key><integer>42</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>111</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>111</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>111</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>111</integer>
+// CHECK-NEXT: <key>col</key><integer>40</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
// 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;getTypedStuff&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;getTypedStuff&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>79</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;crossProceduralErasedTypes&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;crossProceduralErasedTypes&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// 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>111</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: <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>1</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>80</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>80</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: <key>line</key><integer>111</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>111</integer>
+// CHECK-NEXT: <key>col</key><integer>42</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Calling &apos;getTypedStuff&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Calling &apos;getTypedStuff&apos;</string>
+// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>80</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>kind</key><string>event</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>86</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;crossProceduralErasedTypes&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Entered call from &apos;crossProceduralErasedTypes&apos;</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</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>line</key><integer>80</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>80</integer>
-// CHECK-NEXT: <key>col</key><integer>37</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// 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>1</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>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>87</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>87</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSNumber *&gt; *&apos; is inferred from implicit cast (from &apos;NSArray *&apos; to &apos;NSArray&lt;NSNumber *&gt; *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSNumber *&gt; *&apos; is inferred from implicit cast (from &apos;NSArray *&apos; to &apos;NSArray&lt;NSNumber *&gt; *&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// 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>87</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: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>80</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>80</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>81</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>81</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: <key>line</key><integer>87</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>87</integer>
+// CHECK-NEXT: <key>col</key><integer>37</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
// 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>100</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>depth</key><integer>1</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSNumber *&gt; *&apos; is inferred from implicit cast (from &apos;NSArray *&apos; to &apos;NSArray&lt;NSNumber *&gt; *&apos;)</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSNumber *&gt; *&apos; is inferred from implicit cast (from &apos;NSArray *&apos; to &apos;NSArray&lt;NSNumber *&gt; *&apos;)</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>100</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>100</integer>
-// CHECK-NEXT: <key>col</key><integer>42</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;getTypedStuff&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Returning from &apos;getTypedStuff&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>100</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>100</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>100</integer>
-// CHECK-NEXT: <key>col</key><integer>42</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>Conversion from value of type &apos;NSArray&lt;NSNumber *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSString *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSArray&lt;NSNumber *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSString *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSArray&lt;NSNumber *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSString *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>82c378fdcfcc5c0318d2f3ca46420ec1</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>crossProceduralErasedTypes</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>100</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: <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>105</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: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>105</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>105</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// 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>3</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>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>88</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>88</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSArray *&apos; to &apos;NSArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSArray *&apos; to &apos;NSArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// 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>111</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: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>105</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>105</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>106</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>106</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: <key>line</key><integer>111</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>111</integer>
+// CHECK-NEXT: <key>col</key><integer>42</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Returning from &apos;getTypedStuff&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Returning from &apos;getTypedStuff&apos;</string>
+// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>106</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>kind</key><string>event</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>111</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>111</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>111</integer>
+// CHECK-NEXT: <key>col</key><integer>42</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>Conversion from value of type &apos;NSArray&lt;NSNumber *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSString *&gt; *&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;NSArray&lt;NSNumber *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSString *&gt; *&apos;</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSArray&lt;NSNumber *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSString *&gt; *&apos;</string>
+// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
+// CHECK-NEXT: <key>type</key><string>Generics</string>
+// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>82c378fdcfcc5c0318d2f3ca46420ec1</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>crossProceduralErasedTypes</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>111</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: <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>116</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>116</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>116</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>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSMutableArray *&apos; to &apos;NSMutableArray&lt;NSString *&gt; *&apos;)</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSMutableArray *&apos; to &apos;NSMutableArray&lt;NSString *&gt; *&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>line</key><integer>106</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>106</integer>
-// CHECK-NEXT: <key>col</key><integer>38</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>116</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>116</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>119</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>119</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>97a49604cb3d640307a104f14b6d950d</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>incompatibleTypesErasedReverseConversion</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>106</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: <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>105</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: </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>line</key><integer>105</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>105</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>119</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>119</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>119</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>119</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSArray *&apos; to &apos;NSArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSArray *&apos; to &apos;NSArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// 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>119</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>
// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>105</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>105</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>108</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>108</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: <key>line</key><integer>119</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>119</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: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
+// CHECK-NEXT: <key>type</key><string>Generics</string>
+// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>234e3c299ee75a4dd4563e0ea88b9ed9</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>incompatibleTypesErasedReverseConversion</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>119</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: <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>116</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: <dict>
-// CHECK-NEXT: <key>start</key>
-// 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>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>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>108</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>108</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: <key>line</key><integer>116</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>116</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: </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>108</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSMutableArray *&apos; to &apos;NSMutableArray&lt;NSString *&gt; *&apos;)</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSMutableArray *&apos; to &apos;NSMutableArray&lt;NSString *&gt; *&apos;)</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>108</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>108</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>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>b358a659d36c93a9fba593cf6d866a2b</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>incompatibleTypesErasedReverseConversion</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>108</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: <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>112</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: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>112</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>112</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>116</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>116</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>121</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>121</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;NSArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;NSArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// 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>121</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: <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>3</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>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>113</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>113</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: <key>line</key><integer>121</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>121</integer>
+// CHECK-NEXT: <key>col</key><integer>39</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
+// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
+// CHECK-NEXT: <key>type</key><string>Generics</string>
+// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>e875afc5479fec33a693ce2b550a9573</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>incompatibleTypesErasedReverseConversion</string>
+// CHECK-NEXT: <key>issue_hash_function_offset</key><string>6</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>121</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: <dict>
+// CHECK-NEXT: <key>path</key>
+// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>113</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>kind</key><string>event</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>125</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>125</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>125</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>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;NSMutableArray&lt;NSString *&gt; *&apos;)</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;NSMutableArray&lt;NSString *&gt; *&apos;)</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</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>line</key><integer>113</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>113</integer>
-// CHECK-NEXT: <key>col</key><integer>38</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// 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>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>128</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>128</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>a57d9309397250421e9b96afe80c2045</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>idErasedIncompatibleTypesReverseConversion</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>113</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: <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>112</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: </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>line</key><integer>112</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>112</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// 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>3</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>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>128</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>128</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;NSArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;NSArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// 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>128</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>
// 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>3</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>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>115</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>115</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: <key>line</key><integer>128</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>128</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: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
+// CHECK-NEXT: <key>type</key><string>Generics</string>
+// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>d7fa9fa89fe860ed8f5d22631233a5fa</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>idErasedIncompatibleTypesReverseConversion</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>128</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: <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>125</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: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>115</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>115</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>115</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>115</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: <key>line</key><integer>125</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>125</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: </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>115</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;NSMutableArray&lt;NSString *&gt; *&apos;)</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;NSMutableArray&lt;NSString *&gt; *&apos;)</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>115</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>115</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>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>3c86c79284e67f28d04b7ef88bedbb8b</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>idErasedIncompatibleTypesReverseConversion</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>115</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: <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>120</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: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>120</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>120</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// 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>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>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>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
// 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>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSArray&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSArray&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// 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>130</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: <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>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>121</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>121</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: <key>line</key><integer>130</integer>
+// CHECK-NEXT: <key>col</key><integer>16</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>38</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
+// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
+// CHECK-NEXT: <key>type</key><string>Generics</string>
+// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>7de91182a5d6e40a85fa3b91cf3fd089</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>idErasedIncompatibleTypesReverseConversion</string>
+// CHECK-NEXT: <key>issue_hash_function_offset</key><string>6</string>
+// CHECK-NEXT: <key>location</key>
+// 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: <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>135</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: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>121</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>121</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>121</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>121</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: <key>line</key><integer>135</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>135</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: </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>121</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSMutableArray&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSMutableArray&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</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>line</key><integer>121</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>121</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// 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>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>136</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>136</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>a669a3ca1da5a07458c0186f43a295cb</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>idErasedIncompatibleTypes</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>121</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: <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>120</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: </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>line</key><integer>120</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>120</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// 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>3</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>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>136</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>136</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSArray&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSArray&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// 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>136</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: <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>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>122</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>122</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: <key>line</key><integer>136</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>136</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: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
+// CHECK-NEXT: <key>type</key><string>Generics</string>
+// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>8960776d84319407ac2bf7a1531d19b0</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>idErasedIncompatibleTypes</string>
+// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>136</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: <dict>
+// CHECK-NEXT: <key>path</key>
+// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>122</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// 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>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>135</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>135</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>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSMutableArray&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSMutableArray&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</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>line</key><integer>122</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>122</integer>
-// CHECK-NEXT: <key>col</key><integer>38</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// 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>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>139</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>139</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>7ab912bd3fb03b47dc9489cac0297e2a</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>idErasedIncompatibleTypes</string>
-// 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>122</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: <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>120</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: </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>line</key><integer>120</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>120</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>139</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>139</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>139</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>139</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSArray&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSArray&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// 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>139</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>
// 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>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>124</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>124</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: <key>line</key><integer>139</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>139</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: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSMutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
+// CHECK-NEXT: <key>type</key><string>Generics</string>
+// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>93b114c7a385294dce5c25ed04a8b25a</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>idErasedIncompatibleTypes</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>139</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: <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>135</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: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>124</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>124</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>124</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>124</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: <key>line</key><integer>135</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>135</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: </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>124</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSMutableArray&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Type &apos;NSMutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSMutableArray&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</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>line</key><integer>124</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>124</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// 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>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>141</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>141</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>0c7b4313b8b720c914b04863f47f971f</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>idErasedIncompatibleTypes</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>124</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: <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: </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>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</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>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>129</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>133</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>133</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: <key>line</key><integer>141</integer>
+// CHECK-NEXT: <key>col</key><integer>16</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>38</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
// 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>133</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
+// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
+// CHECK-NEXT: <key>type</key><string>Generics</string>
+// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>4c17f22d7e977f3343d2e2129b9229c3</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>idErasedIncompatibleTypes</string>
+// CHECK-NEXT: <key>issue_hash_function_offset</key><string>7</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>141</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: <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>line</key><integer>133</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>133</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// 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>3</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>146</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>146</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to &apos;MutableArray *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to &apos;MutableArray *&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>133</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>133</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>134</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>134</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: </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>7</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</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>
-// CHECK-NEXT: </dict>
-// 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>
-// 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>3</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>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: <key>line</key><integer>146</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>146</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: </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>136</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Assuming the condition is false</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Assuming the condition is false</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</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>line</key><integer>136</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>136</integer>
-// CHECK-NEXT: <key>col</key><integer>39</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// 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>7</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>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>150</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>150</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>24a08781e7d8971a7d8f8f607ce40074</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>pathSensitiveInference</string>
-// 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>136</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: <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>141</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: </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>150</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>150</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>150</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: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to &apos;MutableArray *&apos;)</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to &apos;MutableArray *&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>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// 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>5</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>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>151</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>151</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>line</key><integer>141</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</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>
+// CHECK-NEXT: </dict>
+// 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>
+// 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>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
// 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>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// 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: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>141</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>141</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>142</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>142</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: <key>line</key><integer>153</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>153</integer>
+// CHECK-NEXT: <key>col</key><integer>39</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
+// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
+// CHECK-NEXT: <key>type</key><string>Generics</string>
+// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>24a08781e7d8971a7d8f8f607ce40074</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>pathSensitiveInference</string>
+// 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>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: <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>158</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: <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>3</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>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>142</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>142</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: <key>line</key><integer>158</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>158</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: </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>142</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</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>line</key><integer>142</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>142</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>158</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>158</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>159</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>159</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>a8534f675404d57d833dc3c371d49845</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>verifyAPIusage</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>142</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: <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>147</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: </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>line</key><integer>147</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>147</integer>
-// CHECK-NEXT: <key>col</key><integer>42</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// 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>3</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>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>159</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>159</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from explicit cast (from &apos;MutableArray *&apos; to &apos;MutableArray&lt;NSMutableString *&gt; *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from explicit cast (from &apos;MutableArray *&apos; to &apos;MutableArray&lt;NSMutableString *&gt; *&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// 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>159</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>
// 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>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: <key>line</key><integer>159</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>159</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: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
+// CHECK-NEXT: <key>type</key><string>Generics</string>
+// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>a8534f675404d57d833dc3c371d49845</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>verifyAPIusage</string>
+// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>159</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: <dict>
+// CHECK-NEXT: <key>path</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: <key>kind</key><string>event</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>164</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>164</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>164</integer>
+// CHECK-NEXT: <key>col</key><integer>42</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>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from explicit cast (from &apos;MutableArray *&apos; to &apos;MutableArray&lt;NSMutableString *&gt; *&apos;)</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from explicit cast (from &apos;MutableArray *&apos; to &apos;MutableArray&lt;NSMutableString *&gt; *&apos;)</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</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>line</key><integer>148</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>148</integer>
-// CHECK-NEXT: <key>col</key><integer>39</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>164</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>164</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>165</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>165</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>0549631e5a7fa668375061b6c898e438</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>trustExplicitCasts</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// 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: <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: </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>165</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: <dict>
-// CHECK-NEXT: <key>start</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>
-// CHECK-NEXT: </dict>
-// 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>
-// 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>3</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>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: <key>line</key><integer>165</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>165</integer>
+// CHECK-NEXT: <key>col</key><integer>39</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
// 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>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
+// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
+// CHECK-NEXT: <key>type</key><string>Generics</string>
+// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>0549631e5a7fa668375061b6c898e438</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>trustExplicitCasts</string>
+// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>165</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: <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>line</key><integer>155</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>155</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>171</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>171</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>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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;MutableArray&lt;NSString *&gt; *&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>155</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>155</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>156</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>156</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: </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>172</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: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>156</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>156</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>156</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>156</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: <key>line</key><integer>172</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>172</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: </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>156</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</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>line</key><integer>156</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>156</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// 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>173</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>173</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>d113e22b9ee9ded1cd94750c3557eff4</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>subtypeOfGeneric</string>
-// 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>156</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: <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>162</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: </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>line</key><integer>162</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>162</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>173</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>173</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>173</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>173</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;ExceptionalArray&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;ExceptionalArray&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// 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>173</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: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>162</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>162</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>164</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>164</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: <key>line</key><integer>173</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>173</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: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSNumber *&gt; *&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSNumber *&gt; *&apos;</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSNumber *&gt; *&apos;</string>
+// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
+// CHECK-NEXT: <key>type</key><string>Generics</string>
+// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>d113e22b9ee9ded1cd94750c3557eff4</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>subtypeOfGeneric</string>
+// 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>173</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: <dict>
+// CHECK-NEXT: <key>path</key>
+// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>164</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>kind</key><string>event</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>179</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>179</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>179</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>Type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;ExceptionalArray&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;ExceptionalArray&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</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>line</key><integer>164</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>164</integer>
-// CHECK-NEXT: <key>col</key><integer>38</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>179</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>179</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>183</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>183</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>22fad8121164716006b2a12f4ddc494e</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>genericSubtypeOfGeneric</string>
-// 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>164</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: <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>162</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: </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>line</key><integer>162</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>162</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// 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>3</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>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>183</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>183</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;ExceptionalArray&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;ExceptionalArray&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// 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>183</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: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>162</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>162</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>166</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>166</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: <key>line</key><integer>183</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>183</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: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSNumber *&gt; *&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSNumber *&gt; *&apos;</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSNumber *&gt; *&apos;</string>
+// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
+// CHECK-NEXT: <key>type</key><string>Generics</string>
+// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>f1b900572a63726a729714a765595c38</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>genericSubtypeOfGeneric</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>183</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: <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>179</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: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>166</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>166</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>166</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>166</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: <key>line</key><integer>179</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>179</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: </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>166</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;ExceptionalArray&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;ExceptionalArray&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>166</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>166</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>Conversion from value of type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>f1b900572a63726a729714a765595c38</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>genericSubtypeOfGeneric</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>166</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: <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>172</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: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>172</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>172</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>179</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>179</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>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>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
// 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>Type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;ExceptionalArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;ExceptionalArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// 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>185</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: <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>174</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>174</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: <key>line</key><integer>185</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>185</integer>
+// CHECK-NEXT: <key>col</key><integer>39</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
+// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
+// CHECK-NEXT: <key>type</key><string>Generics</string>
+// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>cbb926c9de226a3eac85fb961a93f39a</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>genericSubtypeOfGeneric</string>
+// CHECK-NEXT: <key>issue_hash_function_offset</key><string>7</string>
+// CHECK-NEXT: <key>location</key>
+// 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: <dict>
+// CHECK-NEXT: <key>path</key>
+// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>174</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>kind</key><string>event</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>191</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>191</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>191</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>Type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;ExceptionalArray&lt;NSString *&gt; *&apos;)</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;ExceptionalArray&lt;NSString *&gt; *&apos;)</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</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>line</key><integer>174</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>174</integer>
-// CHECK-NEXT: <key>col</key><integer>38</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>191</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>191</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>195</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>195</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>c70c13fbce3e6a90637decd9d0e19d95</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>genericSubtypeOfGenericReverse</string>
-// 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>174</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: <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>172</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: </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>line</key><integer>172</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>172</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>195</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>195</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>195</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>195</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;ExceptionalArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;ExceptionalArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// 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>195</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: <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>176</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>176</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: <key>line</key><integer>195</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>195</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: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSNumber *&gt; *&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSNumber *&gt; *&apos;</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSNumber *&gt; *&apos;</string>
+// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
+// CHECK-NEXT: <key>type</key><string>Generics</string>
+// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>b6ee3b22fbad45f213b4bf14bec7eeaf</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>genericSubtypeOfGenericReverse</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>195</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: <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>191</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: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>176</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>176</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>176</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>176</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: <key>line</key><integer>191</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>191</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: </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>176</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;ExceptionalArray&lt;NSString *&gt; *&apos;)</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;ExceptionalArray&lt;NSString *&gt; *&apos;)</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>176</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>176</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>Conversion from value of type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;ExceptionalArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>b6ee3b22fbad45f213b4bf14bec7eeaf</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>genericSubtypeOfGenericReverse</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>176</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: <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>182</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</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>line</key><integer>182</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>182</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>191</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>191</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>2</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>2</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
// 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>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// 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>197</integer>
+// CHECK-NEXT: <key>col</key><integer>2</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>182</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>182</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>183</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>183</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: </dict>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>197</integer>
+// CHECK-NEXT: <key>col</key><integer>16</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>38</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
+// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
+// CHECK-NEXT: <key>type</key><string>Generics</string>
+// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>6561f05506a8ceca3afc79fc59912b94</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>genericSubtypeOfGenericReverse</string>
+// CHECK-NEXT: <key>issue_hash_function_offset</key><string>7</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>197</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: <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>203</integer>
+// CHECK-NEXT: <key>col</key><integer>20</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</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>3</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>25</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>27</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>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: <key>line</key><integer>203</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>203</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: </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>183</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</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>line</key><integer>183</integer>
-// CHECK-NEXT: <key>col</key><integer>27</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>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>203</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>203</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>204</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>25</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
// 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>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>6aab15d40b39ec0a6b749e561d486e6a</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>inferenceFromAPI</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>183</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// 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>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>187</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// 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>line</key><integer>187</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>187</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>204</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>25</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>204</integer>
+// CHECK-NEXT: <key>col</key><integer>27</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>27</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
// 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>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;MutableArray&lt;NSMutableString *&gt; *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;MutableArray&lt;NSMutableString *&gt; *&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// 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>27</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>187</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>187</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: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>188</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>188</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: <key>line</key><integer>204</integer>
+// CHECK-NEXT: <key>col</key><integer>27</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>27</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
+// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
+// CHECK-NEXT: <key>type</key><string>Generics</string>
+// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>6aab15d40b39ec0a6b749e561d486e6a</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>inferenceFromAPI</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>204</integer>
+// CHECK-NEXT: <key>col</key><integer>27</integer>
+// 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>event</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>208</integer>
+// CHECK-NEXT: <key>col</key><integer>27</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>188</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>188</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>188</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>188</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: <key>line</key><integer>208</integer>
+// CHECK-NEXT: <key>col</key><integer>27</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>208</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: </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>188</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;MutableArray&lt;NSMutableString *&gt; *&apos;)</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;id&apos; to &apos;MutableArray&lt;NSMutableString *&gt; *&apos;)</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</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>line</key><integer>188</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>188</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// 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>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>208</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: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>209</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>209</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>bd1da1b7775323773555e5d5c122661f</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>inferenceFromAPI2</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>188</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: <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>192</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// 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>line</key><integer>192</integer>
-// CHECK-NEXT: <key>col</key><integer>27</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>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>209</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>209</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>209</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>209</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;LegacyMutableArray *&apos; to &apos;MutableArray&lt;NSMutableString *&gt; *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;LegacyMutableArray *&apos; to &apos;MutableArray&lt;NSMutableString *&gt; *&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// 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>209</integer>
+// CHECK-NEXT: <key>col</key><integer>20</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>192</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>25</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>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>193</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: <key>line</key><integer>209</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>209</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: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
+// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
+// CHECK-NEXT: <key>type</key><string>Generics</string>
+// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>bd1da1b7775323773555e5d5c122661f</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>inferenceFromAPI2</string>
+// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>209</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: <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>213</integer>
+// CHECK-NEXT: <key>col</key><integer>27</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// 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>193</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>193</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>193</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: <key>line</key><integer>213</integer>
+// CHECK-NEXT: <key>col</key><integer>27</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>213</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: </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>193</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;LegacyMutableArray *&apos; to &apos;MutableArray&lt;NSMutableString *&gt; *&apos;)</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;LegacyMutableArray *&apos; to &apos;MutableArray&lt;NSMutableString *&gt; *&apos;)</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</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>line</key><integer>193</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>193</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>213</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>213</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: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>214</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>214</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>3f2abd3c0b4b4a80a71bcbb668124ffb</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>inferenceFromAPIWithLegacyTypes</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>193</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: <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>197</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// 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>line</key><integer>197</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>197</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>214</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>214</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>214</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>214</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;LegacySpecialMutableArray *&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;LegacySpecialMutableArray *&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// 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>214</integer>
+// CHECK-NEXT: <key>col</key><integer>20</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</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>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>198</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>198</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: </dict>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>214</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>214</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: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
+// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
+// CHECK-NEXT: <key>type</key><string>Generics</string>
+// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>3f2abd3c0b4b4a80a71bcbb668124ffb</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>inferenceFromAPIWithLegacyTypes</string>
+// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>214</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: <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>218</integer>
+// CHECK-NEXT: <key>col</key><integer>20</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>198</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>198</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: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>198</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>198</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: <key>line</key><integer>218</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>218</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: </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>198</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;LegacySpecialMutableArray *&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;LegacySpecialMutableArray *&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</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>line</key><integer>198</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>198</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>218</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>218</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>219</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>219</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: </dict>
// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>73a50f2592e8b3c9af898749f24176f7</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>inferenceFromAPIWithLegacyTypes2</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>198</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// 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>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>202</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// 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>line</key><integer>202</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>202</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>219</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>219</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: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>219</integer>
+// CHECK-NEXT: <key>col</key><integer>27</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>219</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;__kindof NSArray&lt;NSString *&gt; *&apos; to &apos;LegacyMutableArray *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;__kindof NSArray&lt;NSString *&gt; *&apos; to &apos;LegacyMutableArray *&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// 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>219</integer>
+// CHECK-NEXT: <key>col</key><integer>27</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>202</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>202</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>203</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>203</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: <key>line</key><integer>219</integer>
+// CHECK-NEXT: <key>col</key><integer>27</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>219</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: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
+// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
+// CHECK-NEXT: <key>type</key><string>Generics</string>
+// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>73a50f2592e8b3c9af898749f24176f7</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>inferenceFromAPIWithLegacyTypes2</string>
+// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>219</integer>
+// CHECK-NEXT: <key>col</key><integer>27</integer>
+// 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>line</key><integer>203</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>kind</key><string>event</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>223</integer>
+// CHECK-NEXT: <key>col</key><integer>27</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>223</integer>
+// CHECK-NEXT: <key>col</key><integer>27</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>223</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: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;__kindof NSArray&lt;NSString *&gt; *&apos; to &apos;LegacyMutableArray *&apos;)</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;__kindof NSArray&lt;NSString *&gt; *&apos; to &apos;LegacyMutableArray *&apos;)</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</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>line</key><integer>203</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>203</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>223</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>223</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>224</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>224</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;LegacyMutableArray *&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;LegacyMutableArray *&apos; to &apos;MutableArray&lt;NSString *&gt; *&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>203</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>203</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>204</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>25</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: </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>224</integer>
+// CHECK-NEXT: <key>col</key><integer>20</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>204</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>25</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>204</integer>
-// CHECK-NEXT: <key>col</key><integer>27</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>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: <key>line</key><integer>224</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>224</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: </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>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;LegacyMutableArray *&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;LegacyMutableArray *&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</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>line</key><integer>204</integer>
-// CHECK-NEXT: <key>col</key><integer>27</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>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>224</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>224</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>225</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>225</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: </dict>
// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>23ca540c8961ab9a362a194e1e895f86</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>inferenceFromAPIWithLegacyTypes3</string>
-// 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>204</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// 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>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>208</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// 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>line</key><integer>208</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>208</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>225</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>225</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: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>225</integer>
+// CHECK-NEXT: <key>col</key><integer>27</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>225</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;BuggyMutableArray&lt;NSMutableString *&gt; *&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;BuggyMutableArray&lt;NSMutableString *&gt; *&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// 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>225</integer>
+// CHECK-NEXT: <key>col</key><integer>27</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// 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>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>208</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>209</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>209</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: </dict>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>225</integer>
+// CHECK-NEXT: <key>col</key><integer>27</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>225</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: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
+// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
+// CHECK-NEXT: <key>type</key><string>Generics</string>
+// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>23ca540c8961ab9a362a194e1e895f86</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>inferenceFromAPIWithLegacyTypes3</string>
+// 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>225</integer>
+// CHECK-NEXT: <key>col</key><integer>27</integer>
+// 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>event</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>229</integer>
+// CHECK-NEXT: <key>col</key><integer>20</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>209</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>209</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: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>209</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>209</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: <key>line</key><integer>229</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>229</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: </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>209</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;BuggyMutableArray&lt;NSMutableString *&gt; *&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;BuggyMutableArray&lt;NSMutableString *&gt; *&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</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>line</key><integer>209</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>209</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>229</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>229</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>230</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>230</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: </dict>
// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>be7e9426f827314f05fd4e15b25909df</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>inferenceFromAPIWithBuggyTypes</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>209</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// 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>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>213</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// 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>line</key><integer>213</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>213</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>230</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>230</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: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>230</integer>
+// CHECK-NEXT: <key>col</key><integer>27</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>230</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;BuggySpecialMutableArray&lt;NSMutableString *&gt; *&apos; to &apos;MutableArray&lt;NSMutableString *&gt; *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;BuggySpecialMutableArray&lt;NSMutableString *&gt; *&apos; to &apos;MutableArray&lt;NSMutableString *&gt; *&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// 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>230</integer>
+// CHECK-NEXT: <key>col</key><integer>27</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>213</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>213</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: <key>end</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>214</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>214</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: <key>line</key><integer>230</integer>
+// CHECK-NEXT: <key>col</key><integer>27</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>230</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: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
+// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
+// CHECK-NEXT: <key>type</key><string>Generics</string>
+// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>be7e9426f827314f05fd4e15b25909df</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>inferenceFromAPIWithBuggyTypes</string>
+// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>230</integer>
+// CHECK-NEXT: <key>col</key><integer>27</integer>
+// 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>event</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>234</integer>
+// CHECK-NEXT: <key>col</key><integer>27</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>214</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>214</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>214</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>214</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: <key>line</key><integer>234</integer>
+// CHECK-NEXT: <key>col</key><integer>27</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>234</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: </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>214</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;BuggySpecialMutableArray&lt;NSMutableString *&gt; *&apos; to &apos;MutableArray&lt;NSMutableString *&gt; *&apos;)</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;BuggySpecialMutableArray&lt;NSMutableString *&gt; *&apos; to &apos;MutableArray&lt;NSMutableString *&gt; *&apos;)</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</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>line</key><integer>214</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>214</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>234</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>234</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: <key>end</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>235</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>235</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>0f97a618ccac913d7c8631b5b86a133e</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>InferenceFromAPIWithBuggyTypes2</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>214</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: <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>218</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: </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>line</key><integer>218</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>218</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>235</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>235</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>235</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>235</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to &apos;id&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to &apos;id&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// 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>235</integer>
+// CHECK-NEXT: <key>col</key><integer>20</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>218</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>218</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>220</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>220</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: <key>line</key><integer>235</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>235</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: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
+// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
+// CHECK-NEXT: <key>type</key><string>Generics</string>
+// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>0f97a618ccac913d7c8631b5b86a133e</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>InferenceFromAPIWithBuggyTypes2</string>
+// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>235</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: <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>239</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: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>220</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>220</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>220</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>220</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: <key>line</key><integer>239</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>239</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: </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>220</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to &apos;id&apos;)</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to &apos;id&apos;)</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</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>line</key><integer>220</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>220</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// 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>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>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>18</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
// 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>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>725c54c88bb271138b1de545ee59a8aa</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>InferenceFromAPIWithBuggyTypes3</string>
-// 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>220</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: <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>224</integer>
-// CHECK-NEXT: <key>col</key><integer>45</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// 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>line</key><integer>224</integer>
-// CHECK-NEXT: <key>col</key><integer>45</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>224</integer>
-// CHECK-NEXT: <key>col</key><integer>45</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</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>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>241</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>241</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;__kindof NSArray&lt;NSString *&gt; *&apos; to &apos;BuggyMutableArray&lt;NSMutableString *&gt; *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;__kindof NSArray&lt;NSString *&gt; *&apos; to &apos;BuggyMutableArray&lt;NSMutableString *&gt; *&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// 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>241</integer>
+// CHECK-NEXT: <key>col</key><integer>20</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>224</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>224</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>225</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>225</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: <key>line</key><integer>241</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>241</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: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSString *&gt; *&apos;</string>
+// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
+// CHECK-NEXT: <key>type</key><string>Generics</string>
+// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>725c54c88bb271138b1de545ee59a8aa</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>InferenceFromAPIWithBuggyTypes3</string>
+// 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>241</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: <dict>
+// CHECK-NEXT: <key>path</key>
+// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>225</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>kind</key><string>event</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>245</integer>
+// CHECK-NEXT: <key>col</key><integer>45</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>245</integer>
+// CHECK-NEXT: <key>col</key><integer>45</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>45</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>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;__kindof NSArray&lt;NSString *&gt; *&apos; to &apos;BuggyMutableArray&lt;NSMutableString *&gt; *&apos;)</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;__kindof NSArray&lt;NSString *&gt; *&apos; to &apos;BuggyMutableArray&lt;NSMutableString *&gt; *&apos;)</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</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>line</key><integer>225</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>225</integer>
-// CHECK-NEXT: <key>col</key><integer>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// 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>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>246</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>246</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;BuggyMutableArray&lt;NSMutableString *&gt; *&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;BuggyMutableArray&lt;NSMutableString *&gt; *&apos; to &apos;MutableArray&lt;NSString *&gt; *&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>225</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>225</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>226</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>25</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: </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>246</integer>
+// CHECK-NEXT: <key>col</key><integer>20</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</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>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>25</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>27</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>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: <key>line</key><integer>246</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>246</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: </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>226</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;BuggyMutableArray&lt;NSMutableString *&gt; *&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;BuggyMutableArray&lt;NSMutableString *&gt; *&apos; to &apos;MutableArray&lt;NSString *&gt; *&apos;)</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</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>line</key><integer>226</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>246</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>246</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>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>25</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>line</key><integer>226</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// 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>25</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>27</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>27</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
// 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>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>fb867af384c612fe5c09f821127eeaf0</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>InferenceFromAPIWithBuggyTypes4</string>
-// 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>226</integer>
-// CHECK-NEXT: <key>col</key><integer>27</integer>
-// 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>238</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>238</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>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>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: </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>247</integer>
+// CHECK-NEXT: <key>col</key><integer>27</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</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>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>239</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>239</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: <key>line</key><integer>247</integer>
+// CHECK-NEXT: <key>col</key><integer>27</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>27</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
// 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>239</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;MutableArray&lt;NSString *&gt; *&apos; to incompatible type &apos;MutableArray&lt;NSMutableString *&gt; *&apos;</string>
+// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
+// CHECK-NEXT: <key>type</key><string>Generics</string>
+// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>fb867af384c612fe5c09f821127eeaf0</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>InferenceFromAPIWithBuggyTypes4</string>
+// 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>247</integer>
+// CHECK-NEXT: <key>col</key><integer>27</integer>
+// 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>line</key><integer>239</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>239</integer>
-// CHECK-NEXT: <key>col</key><integer>38</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>259</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>259</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>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>10</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
// 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>Type &apos;NSNumber *&apos; is inferred from this context</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;NSNumber *&apos; is inferred from this context</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>239</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: </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>line</key><integer>239</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>239</integer>
-// CHECK-NEXT: <key>col</key><integer>38</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// 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>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>260</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>260</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Type Error</string>
-// CHECK-NEXT: <key>type</key><string>Dynamic and static type mismatch</string>
-// CHECK-NEXT: <key>check_name</key><string>alpha.core.DynamicTypeChecker</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>2e9f738345d9fa7dae2324ff7accd1ae</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>workWithProperties</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>239</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: <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: </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>260</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: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>238</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>238</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>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>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: <key>line</key><integer>260</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>260</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: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Type &apos;NSNumber *&apos; is inferred from this context</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Type &apos;NSNumber *&apos; is inferred from this context</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>260</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: <dict>
-// CHECK-NEXT: <key>start</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>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>241</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>241</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: <key>line</key><integer>260</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>260</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: </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>241</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
+// CHECK-NEXT: <key>category</key><string>Type Error</string>
+// CHECK-NEXT: <key>type</key><string>Dynamic and static type mismatch</string>
+// CHECK-NEXT: <key>check_name</key><string>alpha.core.DynamicTypeChecker</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>2e9f738345d9fa7dae2324ff7accd1ae</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>workWithProperties</string>
+// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>260</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: <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>line</key><integer>241</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>241</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>259</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>259</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>262</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>262</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;NSNumber *&apos; is inferred from this context</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;NSNumber *&apos; is inferred from this context</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>241</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: </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>line</key><integer>241</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>241</integer>
-// CHECK-NEXT: <key>col</key><integer>23</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>262</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>262</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>262</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>262</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Type Error</string>
-// CHECK-NEXT: <key>type</key><string>Dynamic and static type mismatch</string>
-// CHECK-NEXT: <key>check_name</key><string>alpha.core.DynamicTypeChecker</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>d85392b4efadf710b8da65a043a65e24</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>workWithProperties</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>241</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: <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: </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>262</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: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>238</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>238</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>243</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>243</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: <key>line</key><integer>262</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>262</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: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Type &apos;NSNumber *&apos; is inferred from this context</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Type &apos;NSNumber *&apos; is inferred from this context</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>262</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: <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>3</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>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>243</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>243</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: <key>line</key><integer>262</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>262</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: </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>243</integer>
-// CHECK-NEXT: <key>col</key><integer>11</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
+// CHECK-NEXT: <key>category</key><string>Type Error</string>
+// CHECK-NEXT: <key>type</key><string>Dynamic and static type mismatch</string>
+// CHECK-NEXT: <key>check_name</key><string>alpha.core.DynamicTypeChecker</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>d85392b4efadf710b8da65a043a65e24</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>workWithProperties</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>262</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: <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>line</key><integer>243</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>243</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>259</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>259</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>264</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>264</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;NSNumber *&apos; is inferred from this context</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;NSNumber *&apos; is inferred from this context</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>243</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: </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>line</key><integer>243</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>243</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>264</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>264</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>264</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>264</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Type Error</string>
-// CHECK-NEXT: <key>type</key><string>Dynamic and static type mismatch</string>
-// CHECK-NEXT: <key>check_name</key><string>alpha.core.DynamicTypeChecker</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>456c6227549a5e577088c9dce4cea452</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>workWithProperties</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>6</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>243</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: <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: </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>264</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>
// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>238</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>238</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>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>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: <key>line</key><integer>264</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>264</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: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Type &apos;NSNumber *&apos; is inferred from this context</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Type &apos;NSNumber *&apos; is inferred from this context</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>264</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: <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>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>245</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>245</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: <key>line</key><integer>264</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>264</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: </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>245</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>245</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>245</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;NSNumber *&apos; is inferred from this context</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;NSNumber *&apos; is inferred from this context</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>245</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: <key>description</key><string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
+// CHECK-NEXT: <key>category</key><string>Type Error</string>
+// CHECK-NEXT: <key>type</key><string>Dynamic and static type mismatch</string>
+// CHECK-NEXT: <key>check_name</key><string>alpha.core.DynamicTypeChecker</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>456c6227549a5e577088c9dce4cea452</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>workWithProperties</string>
+// CHECK-NEXT: <key>issue_hash_function_offset</key><string>6</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>264</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: <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>line</key><integer>245</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>245</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>259</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>259</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>266</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>266</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Type Error</string>
-// CHECK-NEXT: <key>type</key><string>Dynamic and static type mismatch</string>
-// CHECK-NEXT: <key>check_name</key><string>alpha.core.DynamicTypeChecker</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>df7f090d2b72ac07bc2351177ed6552d</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>workWithProperties</string>
-// 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>245</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: <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>251</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: </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>line</key><integer>251</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>251</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>266</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>266</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>266</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>266</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to &apos;NSArray&lt;NSMutableString *&gt; *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to &apos;NSArray&lt;NSMutableString *&gt; *&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// 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>266</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: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>251</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>251</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>252</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>252</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: <key>line</key><integer>266</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>266</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: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Type &apos;NSNumber *&apos; is inferred from this context</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Type &apos;NSNumber *&apos; is inferred from this context</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>266</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: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>252</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>252</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>253</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>253</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: <key>line</key><integer>266</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>266</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: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
+// CHECK-NEXT: <key>category</key><string>Type Error</string>
+// CHECK-NEXT: <key>type</key><string>Dynamic and static type mismatch</string>
+// CHECK-NEXT: <key>check_name</key><string>alpha.core.DynamicTypeChecker</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>df7f090d2b72ac07bc2351177ed6552d</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>workWithProperties</string>
+// 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>266</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: <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>272</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: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>253</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>253</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>254</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>254</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: <key>line</key><integer>272</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>272</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: </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>254</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to &apos;NSArray&lt;NSMutableString *&gt; *&apos;)</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to &apos;NSArray&lt;NSMutableString *&gt; *&apos;)</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</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>line</key><integer>254</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>272</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>272</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>273</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>273</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>line</key><integer>254</integer>
-// CHECK-NEXT: <key>col</key><integer>41</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>273</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>273</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>273</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>273</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>a0fa75143d7a7ac234292642a6d93360</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>findMethodDeclInTrackedType</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>254</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: <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>263</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: </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>273</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>273</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>273</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>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>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>273</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>273</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>274</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>274</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>line</key><integer>263</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>274</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>274</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>275</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>275</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to &apos;__kindof NSArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to &apos;__kindof NSArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// 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>275</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>263</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>263</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>264</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>264</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: <key>line</key><integer>275</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>275</integer>
+// CHECK-NEXT: <key>col</key><integer>41</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
+// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
+// CHECK-NEXT: <key>type</key><string>Generics</string>
+// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>a0fa75143d7a7ac234292642a6d93360</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>findMethodDeclInTrackedType</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>275</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: <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>284</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: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>264</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>264</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>265</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>265</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: <key>line</key><integer>284</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>284</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: </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>265</integer>
-// CHECK-NEXT: <key>col</key><integer>5</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to &apos;__kindof NSArray&lt;NSString *&gt; *&apos;)</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Type &apos;MutableArray&lt;NSMutableString *&gt; *&apos; is inferred from implicit cast (from &apos;MutableArray&lt;NSMutableString *&gt; *&apos; to &apos;__kindof NSArray&lt;NSString *&gt; *&apos;)</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</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>line</key><integer>265</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>265</integer>
-// CHECK-NEXT: <key>col</key><integer>41</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>284</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>284</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>285</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>285</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>d0b99c8523e81ec43ba4ea80aeedef1b</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>findMethodDeclInTrackedType2</string>
-// 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>265</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: <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>278</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// 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>line</key><integer>278</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>278</integer>
-// CHECK-NEXT: <key>col</key><integer>42</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>285</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>285</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>285</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>285</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSArray *&apos; to &apos;NSArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSArray *&apos; to &apos;NSArray&lt;NSString *&gt; *&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// 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>285</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: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>278</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>278</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>280</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>280</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: <key>line</key><integer>285</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>285</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: </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>280</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// 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: <key>ranges</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>line</key><integer>280</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>280</integer>
-// CHECK-NEXT: <key>col</key><integer>41</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>285</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>285</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>286</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>286</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>ed543d4961e934fb4ac8db00e885fc7f</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testAnnotatedLiterals</string>
-// 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>280</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: <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>289</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>289</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>290</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>290</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: </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>286</integer>
+// CHECK-NEXT: <key>col</key><integer>5</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>290</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>290</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>290</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>290</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: </dict>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>286</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>286</integer>
+// CHECK-NEXT: <key>col</key><integer>41</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
// 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>290</integer>
-// CHECK-NEXT: <key>col</key><integer>28</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSString *&apos; to incompatible type &apos;NSMutableString *&apos;</string>
+// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
+// CHECK-NEXT: <key>type</key><string>Generics</string>
+// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>d0b99c8523e81ec43ba4ea80aeedef1b</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>findMethodDeclInTrackedType2</string>
+// 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>286</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: <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>line</key><integer>290</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>290</integer>
-// CHECK-NEXT: <key>col</key><integer>39</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>310</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>310</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>311</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>311</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from this context</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from this context</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>290</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: </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>line</key><integer>290</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>290</integer>
-// CHECK-NEXT: <key>col</key><integer>39</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>311</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>311</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>311</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>311</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: </dict>
// CHECK-NEXT: </array>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>46aa94b866747bcbe1ded581da7a2633</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>trackedClassVariables</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>290</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: <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: </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>311</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: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>289</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>289</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>291</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>291</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: <key>line</key><integer>311</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>311</integer>
+// CHECK-NEXT: <key>col</key><integer>39</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from this context</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from this context</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>311</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: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>291</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>291</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>291</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>291</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: <key>line</key><integer>311</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>311</integer>
+// CHECK-NEXT: <key>col</key><integer>39</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
// 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>291</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>291</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>291</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from this context</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from this context</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>291</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: <key>description</key><string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
+// CHECK-NEXT: <key>type</key><string>Generics</string>
+// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>46aa94b866747bcbe1ded581da7a2633</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>trackedClassVariables</string>
+// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>311</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: <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>line</key><integer>291</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>291</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>310</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>310</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>312</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>312</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>a759006d1ce88e15fcd6de6a29e2579c</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>trackedClassVariables</string>
-// 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>291</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: <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>295</integer>
-// CHECK-NEXT: <key>col</key><integer>13</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// 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>line</key><integer>295</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>295</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>312</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>312</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>312</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>312</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSArray&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSArray&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// 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>312</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: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>295</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>295</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>296</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>296</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: <key>line</key><integer>312</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>312</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: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from this context</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from this context</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>312</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: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>296</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>296</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>296</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>296</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: <key>line</key><integer>312</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>312</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: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
+// CHECK-NEXT: <key>type</key><string>Generics</string>
+// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>a759006d1ce88e15fcd6de6a29e2579c</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>trackedClassVariables</string>
+// 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>312</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: <dict>
+// CHECK-NEXT: <key>path</key>
+// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>296</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>kind</key><string>event</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>316</integer>
+// CHECK-NEXT: <key>col</key><integer>13</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>316</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>316</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: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSArray&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;NSArray&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</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>line</key><integer>296</integer>
-// CHECK-NEXT: <key>col</key><integer>18</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>316</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>316</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>317</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>317</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>line</key><integer>296</integer>
-// CHECK-NEXT: <key>col</key><integer>21</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>317</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>317</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>317</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>317</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>4bb1729ff86647750b458e6f8d883f08</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>nestedCollections</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>296</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: <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: </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>317</integer>
+// CHECK-NEXT: <key>col</key><integer>18</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>308</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>308</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>309</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>309</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: <key>line</key><integer>317</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>317</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: </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>309</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
+// CHECK-NEXT: <key>type</key><string>Generics</string>
+// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>4bb1729ff86647750b458e6f8d883f08</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>nestedCollections</string>
+// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>317</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: <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>line</key><integer>309</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>309</integer>
-// CHECK-NEXT: <key>col</key><integer>29</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>329</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>329</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>330</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>330</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from this context</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from this context</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>309</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>309</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>310</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>310</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: </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>330</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: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>310</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>310</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>310</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>310</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: <key>line</key><integer>330</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>330</integer>
+// CHECK-NEXT: <key>col</key><integer>29</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
// 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>310</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from this context</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from this context</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</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>line</key><integer>310</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>330</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>330</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>331</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>331</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>line</key><integer>310</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>331</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>331</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>331</integer>
+// CHECK-NEXT: <key>col</key><integer>30</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>331</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>38831553eaecfb6c02b51e71d21ec6ea</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>returnCollectionToIdVariable</string>
-// 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>310</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// 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: </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>331</integer>
+// CHECK-NEXT: <key>col</key><integer>30</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>314</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>314</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>315</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>315</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: <key>line</key><integer>331</integer>
+// CHECK-NEXT: <key>col</key><integer>30</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>331</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: </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>315</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
+// CHECK-NEXT: <key>type</key><string>Generics</string>
+// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>38831553eaecfb6c02b51e71d21ec6ea</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>returnCollectionToIdVariable</string>
+// 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>331</integer>
+// CHECK-NEXT: <key>col</key><integer>30</integer>
+// 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>line</key><integer>315</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>315</integer>
-// CHECK-NEXT: <key>col</key><integer>35</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>335</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>335</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>336</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>336</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from this context</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from this context</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>315</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>315</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>316</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>316</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: </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>336</integer>
+// CHECK-NEXT: <key>col</key><integer>16</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>316</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>316</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>316</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>316</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: <key>line</key><integer>336</integer>
+// CHECK-NEXT: <key>col</key><integer>16</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>336</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: </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>316</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from this context</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from this context</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</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>line</key><integer>316</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>336</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>336</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>337</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>337</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>line</key><integer>316</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>337</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>337</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>337</integer>
+// CHECK-NEXT: <key>col</key><integer>30</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>337</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>9fcbd4dcf212f004877292aa5085322b</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>eraseSpecialization</string>
-// 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>316</integer>
-// CHECK-NEXT: <key>col</key><integer>30</integer>
-// 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>320</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>320</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>321</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>321</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: </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>337</integer>
+// CHECK-NEXT: <key>col</key><integer>30</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>321</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>321</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>321</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>321</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: <key>line</key><integer>337</integer>
+// CHECK-NEXT: <key>col</key><integer>30</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>337</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: </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>321</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSArray&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSNumber *&gt; *&apos;</string>
+// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
+// CHECK-NEXT: <key>type</key><string>Generics</string>
+// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>9fcbd4dcf212f004877292aa5085322b</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>eraseSpecialization</string>
+// 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>337</integer>
+// CHECK-NEXT: <key>col</key><integer>30</integer>
+// 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>line</key><integer>321</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>321</integer>
-// CHECK-NEXT: <key>col</key><integer>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>341</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>341</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>342</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>342</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from this context</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from this context</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>321</integer>
-// CHECK-NEXT: <key>col</key><integer>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// 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>line</key><integer>321</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>321</integer>
-// CHECK-NEXT: <key>col</key><integer>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>342</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>342</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>342</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>342</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object has a dynamic type &apos;NSArray&lt;NSString *&gt; *&apos; which is incompatible with static type &apos;NSSet *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object has a dynamic type &apos;NSArray&lt;NSString *&gt; *&apos; which is incompatible with static type &apos;NSSet *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Object has a dynamic type &apos;NSArray&lt;NSString *&gt; *&apos; which is incompatible with static type &apos;NSSet *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Type Error</string>
-// CHECK-NEXT: <key>type</key><string>Dynamic and static type mismatch</string>
-// CHECK-NEXT: <key>check_name</key><string>alpha.core.DynamicTypeChecker</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>be6714fed24af6e7ac522b87a5098de0</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>returnToUnrelatedType</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>321</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: <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: </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>342</integer>
+// CHECK-NEXT: <key>col</key><integer>14</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>ranges</key>
// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>326</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>326</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>327</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>327</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: <key>line</key><integer>342</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>342</integer>
+// CHECK-NEXT: <key>col</key><integer>33</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from this context</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Type &apos;NSArray&lt;NSString *&gt; *&apos; is inferred from this context</string>
+// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>327</integer>
-// CHECK-NEXT: <key>col</key><integer>10</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>kind</key><string>event</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>342</integer>
+// CHECK-NEXT: <key>col</key><integer>14</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>342</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>342</integer>
+// CHECK-NEXT: <key>col</key><integer>33</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 has a dynamic type &apos;NSArray&lt;NSString *&gt; *&apos; which is incompatible with static type &apos;NSSet *&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Object has a dynamic type &apos;NSArray&lt;NSString *&gt; *&apos; which is incompatible with static type &apos;NSSet *&apos;</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Object has a dynamic type &apos;NSArray&lt;NSString *&gt; *&apos; which is incompatible with static type &apos;NSSet *&apos;</string>
+// CHECK-NEXT: <key>category</key><string>Type Error</string>
+// CHECK-NEXT: <key>type</key><string>Dynamic and static type mismatch</string>
+// CHECK-NEXT: <key>check_name</key><string>alpha.core.DynamicTypeChecker</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>be6714fed24af6e7ac522b87a5098de0</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>returnToUnrelatedType</string>
+// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>342</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: <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>line</key><integer>327</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>327</integer>
-// CHECK-NEXT: <key>col</key><integer>29</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>347</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>347</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>348</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>348</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;NSString *&apos; is inferred from this context</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;NSString *&apos; is inferred from this context</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>327</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>327</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>328</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>328</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: </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>348</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: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>328</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>328</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>328</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>328</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: <key>line</key><integer>348</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>348</integer>
+// CHECK-NEXT: <key>col</key><integer>29</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
// 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>328</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Type &apos;NSString *&apos; is inferred from this context</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Type &apos;NSString *&apos; is inferred from this context</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</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>line</key><integer>328</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>328</integer>
-// CHECK-NEXT: <key>col</key><integer>19</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>348</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>348</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>349</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>349</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Object has a dynamic type &apos;NSString *&apos; which is incompatible with static type &apos;NSNumber *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Object has a dynamic type &apos;NSString *&apos; which is incompatible with static type &apos;NSNumber *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Object has a dynamic type &apos;NSString *&apos; which is incompatible with static type &apos;NSNumber *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Type Error</string>
-// CHECK-NEXT: <key>type</key><string>Dynamic and static type mismatch</string>
-// CHECK-NEXT: <key>check_name</key><string>alpha.core.DynamicTypeChecker</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>5e96ef711c8f115bc64f69baa3f6ea7a</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>returnToIdVariable</string>
-// 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>328</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: <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>337</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: </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>line</key><integer>337</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>337</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>349</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>349</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>349</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>349</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;UnrelatedTypeGeneric&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;UnrelatedTypeGeneric&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;UnrelatedTypeGeneric&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;UnrelatedTypeGeneric&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// 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>349</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: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>337</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>337</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>338</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>338</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: <key>line</key><integer>349</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>349</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: </array>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Object has a dynamic type &apos;NSString *&apos; which is incompatible with static type &apos;NSNumber *&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Object has a dynamic type &apos;NSString *&apos; which is incompatible with static type &apos;NSNumber *&apos;</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Object has a dynamic type &apos;NSString *&apos; which is incompatible with static type &apos;NSNumber *&apos;</string>
+// CHECK-NEXT: <key>category</key><string>Type Error</string>
+// CHECK-NEXT: <key>type</key><string>Dynamic and static type mismatch</string>
+// CHECK-NEXT: <key>check_name</key><string>alpha.core.DynamicTypeChecker</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>5e96ef711c8f115bc64f69baa3f6ea7a</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>returnToIdVariable</string>
+// 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>349</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: <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>358</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: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>338</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>338</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>338</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>338</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: <key>line</key><integer>358</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>358</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: </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>338</integer>
-// CHECK-NEXT: <key>col</key><integer>7</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Type &apos;UnrelatedTypeGeneric&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;UnrelatedTypeGeneric&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Type &apos;UnrelatedTypeGeneric&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;UnrelatedTypeGeneric&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</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>line</key><integer>338</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>338</integer>
-// CHECK-NEXT: <key>col</key><integer>9</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>358</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>358</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>359</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>359</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;UnrelatedTypeGeneric&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSString *&gt; *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;UnrelatedTypeGeneric&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSString *&gt; *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;UnrelatedTypeGeneric&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSString *&gt; *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>8347f65fb51a85ccd462d75ffd761078</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testGetMostInformativeDerivedForId</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>338</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: <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>337</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: </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>line</key><integer>337</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>359</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>359</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>359</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>359</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>
+// CHECK-NEXT: <key>line</key><integer>359</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>359</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>359</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: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;UnrelatedTypeGeneric&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSString *&gt; *&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;UnrelatedTypeGeneric&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSString *&gt; *&apos;</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;UnrelatedTypeGeneric&lt;NSString *&gt; *&apos; to incompatible type &apos;NSArray&lt;NSString *&gt; *&apos;</string>
+// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
+// CHECK-NEXT: <key>type</key><string>Generics</string>
+// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>8347f65fb51a85ccd462d75ffd761078</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>testGetMostInformativeDerivedForId</string>
+// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>359</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: <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>358</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>358</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>358</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: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Type &apos;UnrelatedTypeGeneric&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;UnrelatedTypeGeneric&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Type &apos;UnrelatedTypeGeneric&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;UnrelatedTypeGeneric&lt;NSString *&gt; *&apos; to &apos;id&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>line</key><integer>337</integer>
-// CHECK-NEXT: <key>col</key><integer>12</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>358</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>358</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>364</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>364</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Type &apos;UnrelatedTypeGeneric&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;UnrelatedTypeGeneric&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Type &apos;UnrelatedTypeGeneric&lt;NSString *&gt; *&apos; is inferred from implicit cast (from &apos;UnrelatedTypeGeneric&lt;NSString *&gt; *&apos; to &apos;id&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// 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>364</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: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>337</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>337</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>343</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>343</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: <key>line</key><integer>364</integer>
+// CHECK-NEXT: <key>col</key><integer>16</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>364</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: </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>343</integer>
-// CHECK-NEXT: <key>col</key><integer>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
-// CHECK-NEXT: <array>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
+// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
+// CHECK-NEXT: <key>type</key><string>Generics</string>
+// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>6528db66f562ac0c2a94933f3ca5f6a8</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>testGetMostInformativeDerivedForId</string>
+// CHECK-NEXT: <key>issue_hash_function_offset</key><string>7</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>364</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: <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>line</key><integer>343</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>373</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>373</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>375</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>375</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>line</key><integer>343</integer>
-// CHECK-NEXT: <key>col</key><integer>38</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>375</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>375</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>375</integer>
+// CHECK-NEXT: <key>col</key><integer>70</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>375</integer>
+// CHECK-NEXT: <key>col</key><integer>79</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
// 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>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Conversion from value of type &apos;NSNumber *&apos; to incompatible type &apos;NSString *&apos;</string>
-// CHECK-NEXT: <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK-NEXT: <key>type</key><string>Generics</string>
-// CHECK-NEXT: <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>6528db66f562ac0c2a94933f3ca5f6a8</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>testGetMostInformativeDerivedForId</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>7</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>343</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: </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>375</integer>
+// CHECK-NEXT: <key>col</key><integer>70</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>375</integer>
+// CHECK-NEXT: <key>col</key><integer>70</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>375</integer>
+// CHECK-NEXT: <key>col</key><integer>79</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 has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Object has a dynamic type &apos;NSNumber *&apos; which is incompatible with static type &apos;NSString *&apos;</string>
+// CHECK-NEXT: <key>category</key><string>Type Error</string>
+// CHECK-NEXT: <key>type</key><string>Dynamic and static type mismatch</string>
+// CHECK-NEXT: <key>check_name</key><string>alpha.core.DynamicTypeChecker</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>56326e7b73d049256717eba7005ccc4d</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>testArgumentAfterUpcastWithCovariantTypeParameter</string>
+// 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>375</integer>
+// CHECK-NEXT: <key>col</key><integer>70</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
diff --git a/test/Analysis/gtest.cpp b/test/Analysis/gtest.cpp
new file mode 100644
index 000000000000..f33569598e1e
--- /dev/null
+++ b/test/Analysis/gtest.cpp
@@ -0,0 +1,153 @@
+//RUN: %clang_cc1 -cc1 -std=c++11 -analyze -analyzer-checker=core,apiModeling.google.GTest,debug.ExprInspection -analyzer-eagerly-assume %s -verify
+//RUN: %clang_cc1 -cc1 -std=c++11 -analyze -analyzer-checker=core,apiModeling.google.GTest,debug.ExprInspection -analyzer-eagerly-assume -DGTEST_VERSION_1_8_AND_LATER=1 %s -verify
+//RUN: %clang_cc1 -cc1 -std=c++11 -analyze -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();
+
+namespace std {
+ class string {
+ public:
+ ~string();
+ const char *c_str();
+ };
+}
+
+namespace testing {
+
+class Message { };
+class TestPartResult {
+ public:
+ enum Type {
+ kSuccess,
+ kNonFatalFailure,
+ kFatalFailure
+ };
+};
+
+namespace internal {
+
+class AssertHelper {
+ public:
+ AssertHelper(TestPartResult::Type type, const char* file, int line,
+ const char* message);
+ ~AssertHelper();
+ void operator=(const Message& message) const;
+};
+
+
+template <typename T>
+struct AddReference { typedef T& type; };
+template <typename T>
+struct AddReference<T&> { typedef T& type; };
+template <typename From, typename To>
+class ImplicitlyConvertible {
+ private:
+ static typename AddReference<From>::type MakeFrom();
+ static char Helper(To);
+ static char (&Helper(...))[2];
+ public:
+ static const bool value =
+ sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1;
+};
+template <typename From, typename To>
+const bool ImplicitlyConvertible<From, To>::value;
+template<bool> struct EnableIf;
+template<> struct EnableIf<true> { typedef void type; };
+
+} // end internal
+
+
+class AssertionResult {
+public:
+
+ // The implementation for the copy constructor is not exposed in the
+ // interface.
+ AssertionResult(const AssertionResult& other);
+
+#if defined(GTEST_VERSION_1_8_AND_LATER)
+ template <typename T>
+ explicit AssertionResult(
+ const T& success,
+ typename internal::EnableIf<
+ !internal::ImplicitlyConvertible<T, AssertionResult>::value>::type*
+ /*enabler*/ = 0)
+ : success_(success) {}
+#else
+ explicit AssertionResult(bool success) : success_(success) {}
+#endif
+
+ operator bool() const { return success_; }
+
+ // The actual AssertionResult does not have an explicit destructor, but
+ // it does have a non-trivial member veriable, so we add a destructor here
+ // to force temporary cleanups.
+ ~AssertionResult();
+private:
+
+ bool success_;
+};
+
+namespace internal {
+std::string GetBoolAssertionFailureMessage(
+ const AssertionResult& assertion_result,
+ const char* expression_text,
+ const char* actual_predicate_value,
+ const char* expected_predicate_value);
+} // end internal
+
+} // end testing
+
+#define GTEST_MESSAGE_AT_(file, line, message, result_type) \
+ ::testing::internal::AssertHelper(result_type, file, line, message) \
+ = ::testing::Message()
+
+#define GTEST_MESSAGE_(message, result_type) \
+ GTEST_MESSAGE_AT_(__FILE__, __LINE__, message, result_type)
+
+#define GTEST_FATAL_FAILURE_(message) \
+ return GTEST_MESSAGE_(message, ::testing::TestPartResult::kFatalFailure)
+
+#define GTEST_NONFATAL_FAILURE_(message) \
+ GTEST_MESSAGE_(message, ::testing::TestPartResult::kNonFatalFailure)
+
+# define GTEST_AMBIGUOUS_ELSE_BLOCKER_ switch (0) case 0: default:
+
+#define GTEST_TEST_BOOLEAN_(expression, text, actual, expected, fail) \
+ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+ if (const ::testing::AssertionResult gtest_ar_ = \
+ ::testing::AssertionResult(expression)) \
+ ; \
+ else \
+ fail(::testing::internal::GetBoolAssertionFailureMessage(\
+ gtest_ar_, text, #actual, #expected).c_str())
+
+#define EXPECT_TRUE(condition) \
+ GTEST_TEST_BOOLEAN_((condition), #condition, false, true, \
+ GTEST_NONFATAL_FAILURE_)
+#define ASSERT_TRUE(condition) \
+ GTEST_TEST_BOOLEAN_((condition), #condition, false, true, \
+ GTEST_FATAL_FAILURE_)
+
+#define ASSERT_FALSE(condition) \
+ GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \
+ GTEST_FATAL_FAILURE_)
+
+void testAssertTrue(int *p) {
+ ASSERT_TRUE(p != nullptr);
+ EXPECT_TRUE(1 == *p); // no-warning
+}
+
+void testAssertFalse(int *p) {
+ ASSERT_FALSE(p == nullptr);
+ EXPECT_TRUE(1 == *p); // no-warning
+}
+
+void testConstrainState(int p) {
+ ASSERT_TRUE(p == 7);
+
+ clang_analyzer_eval(p == 7); // expected-warning {{TRUE}}
+
+ ASSERT_TRUE(false);
+ clang_analyzer_warnIfReached(); // no-warning
+}
diff --git a/test/Analysis/inline.c b/test/Analysis/inline.c
index 9ecdce33a36d..03c4ea832581 100644
--- a/test/Analysis/inline.c
+++ b/test/Analysis/inline.c
@@ -114,5 +114,5 @@ void never_called_by_anyone() {
void knr_one_argument(a) int a; { }
void call_with_less_arguments() {
- knr_one_argument(); // expected-warning{{too few arguments}} expected-warning{{Function taking 1 argument}}
+ knr_one_argument(); // expected-warning{{too few arguments}} expected-warning{{Function taking 1 argument is called with fewer (0)}}
}
diff --git a/test/Analysis/inline.cpp b/test/Analysis/inline.cpp
index b7962b53a89b..9fc4f81c05b6 100644
--- a/test/Analysis/inline.cpp
+++ b/test/Analysis/inline.cpp
@@ -441,6 +441,6 @@ namespace rdar12409977 {
namespace bug16307 {
void one_argument(int a) { }
void call_with_less() {
- reinterpret_cast<void (*)()>(one_argument)(); // expected-warning{{Function taking 1 argument}}
+ reinterpret_cast<void (*)()>(one_argument)(); // expected-warning{{Function taking 1 argument is called with fewer (0)}}
}
}
diff --git a/test/Analysis/inlining/InlineObjCClassMethod.m b/test/Analysis/inlining/InlineObjCClassMethod.m
index 6efcb894fecd..c9cc90ba27c0 100644
--- a/test/Analysis/inlining/InlineObjCClassMethod.m
+++ b/test/Analysis/inlining/InlineObjCClassMethod.m
@@ -174,12 +174,12 @@ int foo4() {
@implementation MyClassSelf
+ (int)testClassMethodByKnownVarDecl {
int y = [MyParentSelf testSelf];
- return 5/y; // Should warn here.
+ return 5/y; // expected-warning{{Division by zero}}
}
@end
int foo2() {
int y = [MyParentSelf testSelf];
- return 5/y; // Should warn here.
+ return 5/y; // expected-warning{{Division by zero}}
}
// TODO: We do not inline 'getNum' in the following case, where the value of
diff --git a/test/Analysis/inlining/false-positive-suppression.m b/test/Analysis/inlining/false-positive-suppression.m
index 1a5ff662c18e..685e29e23131 100644
--- a/test/Analysis/inlining/false-positive-suppression.m
+++ b/test/Analysis/inlining/false-positive-suppression.m
@@ -1,8 +1,11 @@
// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-config suppress-null-return-paths=false -verify %s
// RUN: %clang_cc1 -analyze -analyzer-checker=core -verify -DSUPPRESSED=1 %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core -fobjc-arc -verify -DSUPPRESSED=1 %s
// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-config avoid-suppressing-null-argument-paths=true -DSUPPRESSED=1 -DNULL_ARGS=1 -verify %s
-#ifdef SUPPRESSED
+#define ARC __has_feature(objc_arc)
+
+#if defined(SUPPRESSED) && !ARC
// expected-no-diagnostics
#endif
@@ -24,8 +27,9 @@ void testNilReceiverHelperA(int *x) {
void testNilReceiverHelperB(int *x) {
*x = 1;
-#ifndef SUPPRESSED
- // expected-warning@-2 {{Dereference of null pointer}}
+// FIXME: Suppression for this case isn't working under ARC. It should.
+#if !defined(SUPPRESSED) || (defined(SUPPRESSED) && ARC)
+ // expected-warning@-3 {{Dereference of null pointer}}
#endif
}
@@ -40,13 +44,17 @@ void testNilReceiver(int coin) {
// FALSE NEGATIVES (over-suppression)
__attribute__((objc_root_class))
-@interface SomeClass
+@interface SomeClass {
+ int ivar;
+}
-(int *)methodReturningNull;
@property(readonly) int *propertyReturningNull;
@property(readonly) int *synthesizedProperty;
+@property(readonly) SomeClass *propertyReturningNil;
+
@end
@interface SubOfSomeClass : SomeClass
@@ -64,6 +72,10 @@ __attribute__((objc_root_class))
return 0;
}
+-(SomeClass *)propertyReturningNil {
+ return 0;
+}
+
+(int *)classPropertyReturningNull {
return 0;
}
@@ -103,6 +115,16 @@ void testClassPropertyReturningNull() {
#endif
}
+@implementation SomeClass (ForTestOfPropertyReturningNil)
+void testPropertyReturningNil(SomeClass *sc) {
+ SomeClass *result = sc.propertyReturningNil;
+ result->ivar = 1;
+#ifndef SUPPRESSED
+ // expected-warning@-2 {{Access to instance variable 'ivar' results in a dereference of a null pointer (loaded from variable 'result')}}
+#endif
+}
+@end
+
void testSynthesizedPropertyReturningNull(SomeClass *sc) {
if (sc.synthesizedProperty)
return;
diff --git a/test/Analysis/inlining/path-notes.m b/test/Analysis/inlining/path-notes.m
index 492b44c9879c..d9b5a5820fe5 100644
--- a/test/Analysis/inlining/path-notes.m
+++ b/test/Analysis/inlining/path-notes.m
@@ -137,7 +137,7 @@ void testNilReceiverHelper(int *x) {
}
void testNilReceiver(id *x) {
- if (*x) {
+ if (*x) { // expected-note {{Assuming the condition is false}}
// expected-note@-1 {{Taking false branch}}
return;
}
@@ -160,7 +160,7 @@ id testAutoreleaseTakesEffectInDispatch() {
dispatch_once(&token, ^{});
id x = [[[[NSObject alloc] init] autorelease] autorelease];
- // expected-note@-1 {{Method returns an Objective-C object with a +1 retain count}}
+ // expected-note@-1 {{Method returns an instance of NSObject with a +1 retain count}}
// expected-note@-2 {{Object autoreleased}}
// expected-note@-3 {{Object autoreleased}}
@@ -1171,6 +1171,69 @@ void testNullDereferenceInDispatch() {
// 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>7</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>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>140</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>140</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>140</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>Assuming the condition is false</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Assuming the condition is false</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>140</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>140</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>144</integer>
// CHECK-NEXT: <key>col</key><integer>3</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
@@ -1777,9 +1840,9 @@ void testNullDereferenceInDispatch() {
// CHECK-NEXT: </array>
// CHECK-NEXT: <key>depth</key><integer>0</integer>
// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
+// CHECK-NEXT: <string>Method returns an instance of NSObject with a +1 retain count</string>
// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
+// 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>
diff --git a/test/Analysis/lifetime-extension.cpp b/test/Analysis/lifetime-extension.cpp
new file mode 100644
index 000000000000..124eef32fde3
--- /dev/null
+++ b/test/Analysis/lifetime-extension.cpp
@@ -0,0 +1,46 @@
+// RUN: %clang_cc1 -Wno-unused -std=c++11 -analyze -analyzer-checker=debug.ExprInspection -verify %s
+
+void clang_analyzer_eval(bool);
+
+namespace pr17001_call_wrong_destructor {
+bool x;
+struct A {
+ int *a;
+ A() {}
+ ~A() {}
+};
+struct B : public A {
+ B() {}
+ ~B() { x = true; }
+};
+
+void f() {
+ {
+ const A &a = B();
+ }
+ clang_analyzer_eval(x); // expected-warning{{TRUE}}
+}
+} // end namespace pr17001_call_wrong_destructor
+
+namespace pr19539_crash_on_destroying_an_integer {
+struct A {
+ int i;
+ int j[2];
+ A() : i(1) {
+ j[0] = 2;
+ j[1] = 3;
+ }
+ ~A() {}
+};
+
+void f() {
+ const int &x = A().i; // no-crash
+ 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}}
+}
+} // end namespace pr19539_crash_on_destroying_an_integer
diff --git a/test/Analysis/localization-aggressive.m b/test/Analysis/localization-aggressive.m
index 79c9c1331212..89950d4eed74 100644
--- a/test/Analysis/localization-aggressive.m
+++ b/test/Analysis/localization-aggressive.m
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -analyze -fblocks -analyzer-store=region -analyzer-checker=optin.osx.cocoa.localizability.NonLocalizedStringChecker -analyzer-checker=optin.osx.cocoa.localizability.EmptyLocalizationContextChecker -verify -analyzer-config AggressiveReport=true %s
+// RUN: %clang_cc1 -fblocks -x objective-c-header -emit-pch -o %t.pch %S/Inputs/localization-pch.h
+
+// RUN: %clang_cc1 -analyze -fblocks -analyzer-store=region -analyzer-checker=optin.osx.cocoa.localizability.NonLocalizedStringChecker -analyzer-checker=optin.osx.cocoa.localizability.EmptyLocalizationContextChecker -include-pch %t.pch -verify -analyzer-config AggressiveReport=true %s
// These declarations were reduced using Delta-Debugging from Foundation.h
// on Mac OS X.
@@ -249,6 +251,10 @@ NSString *ForceLocalized(NSString *str) { return str; }
NSString *string3 = NSLocalizedString((0 ? @"Critical" : @"Current"),nil); // expected-warning {{Localized string macro should include a non-empty comment for translators}}
}
+- (void)testMacroExpansionDefinedInPCH {
+ NSString *string = MyLocalizedStringInPCH(@"Hello"); // expected-warning {{Localized string macro should include a non-empty comment for translators}}
+}
+
#define KCLocalizedString(x,comment) NSLocalizedString(x, comment)
#define POSSIBLE_FALSE_POSITIVE(s,other) KCLocalizedString(s,@"Comment")
diff --git a/test/Analysis/localization.m b/test/Analysis/localization.m
index dc80705428cf..200eac3f037e 100644
--- a/test/Analysis/localization.m
+++ b/test/Analysis/localization.m
@@ -61,7 +61,7 @@ NSString *KHLocalizedString(NSString* key, NSString* comment) {
UILabel *testLabel = [[UILabel alloc] init];
NSString *bar = NSLocalizedString(@"Hello", @"Comment");
- if (random()) { // expected-note {{Taking true branch}}
+ if (random()) { // expected-note {{Assuming the condition is true}} expected-note {{Taking true branch}}
bar = @"Unlocalized string"; // expected-note {{Non-localized string literal here}}
}
diff --git a/test/Analysis/malloc-custom.c b/test/Analysis/malloc-custom.c
new file mode 100644
index 000000000000..3c16bbd17e68
--- /dev/null
+++ b/test/Analysis/malloc-custom.c
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc -Wno-incompatible-library-redeclaration -verify %s
+
+// Various tests to make the 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,
+// CMake tests can generate these.
+
+// expected-no-diagnostics
+
+char alloca();
+char malloc();
+char realloc();
+char kmalloc();
+char valloc();
+char calloc();
+
+char free();
+char kfree();
+
+void testCustomArgumentlessAllocation() {
+ alloca(); // no-crash
+ malloc(); // no-crash
+ realloc(); // no-crash
+ kmalloc(); // no-crash
+ valloc(); // no-crash
+ calloc(); // no-crash
+
+ free(); // no-crash
+ kfree(); // no-crash
+}
+
diff --git a/test/Analysis/malloc-plist.c b/test/Analysis/malloc-plist.c
index 35ad43ae941f..d6c4f39103fa 100644
--- a/test/Analysis/malloc-plist.c
+++ b/test/Analysis/malloc-plist.c
@@ -1623,6 +1623,69 @@ void testMyMalloc() {
// 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>9</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>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>
+// CHECK-NEXT: <key>line</key><integer>55</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>55</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>55</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: </array>
+// CHECK-NEXT: <key>depth</key><integer>1</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>55</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>55</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>56</integer>
// CHECK-NEXT: <key>col</key><integer>7</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
diff --git a/test/Analysis/malloc.c b/test/Analysis/malloc.c
index 51e2cd604327..d5bc6571e42a 100644
--- a/test/Analysis/malloc.c
+++ b/test/Analysis/malloc.c
@@ -1763,6 +1763,17 @@ void testConstEscapeThroughAnotherField() {
constEscape(&(s.x)); // could free s->p!
} // no-warning
+// PR15623
+int testNoCheckerDataPropogationFromLogicalOpOperandToOpResult(void) {
+ char *param = malloc(10);
+ char *value = malloc(10);
+ int ok = (param && value);
+ free(param);
+ free(value);
+ // Previously we ended up with 'Use of memory after it is freed' on return.
+ return ok; // no warning
+}
+
// ----------------------------------------------------------------------------
// False negatives.
diff --git a/test/Analysis/malloc.cpp b/test/Analysis/malloc.cpp
index 75d06d66c2c3..a8a79cac868b 100644
--- a/test/Analysis/malloc.cpp
+++ b/test/Analysis/malloc.cpp
@@ -1,4 +1,7 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.deadcode.UnreachableCode,alpha.core.CastSize,unix.Malloc -analyzer-store=region -verify %s
+// RUN: %clang_cc1 -w -analyze -analyzer-checker=core,alpha.deadcode.UnreachableCode,alpha.core.CastSize,unix.Malloc,cplusplus.NewDelete -analyzer-store=region -verify %s
+// RUN: %clang_cc1 -triple i386-unknown-linux-gnu -w -analyze -analyzer-checker=core,alpha.deadcode.UnreachableCode,alpha.core.CastSize,unix.Malloc,cplusplus.NewDelete -analyzer-store=region -verify %s
+
+#include "Inputs/system-header-simulator-cxx.h"
typedef __typeof(sizeof(int)) size_t;
void *malloc(size_t);
@@ -105,4 +108,34 @@ void appendWrapperNested(char *getterName) {
void fooNested(const char* name) {
char* getterName = strdup(name);
appendWrapperNested(getterName); // no-warning
-} \ No newline at end of file
+}
+
+namespace PR31226 {
+ struct b2 {
+ int f;
+ };
+
+ struct b1 : virtual b2 {
+ void m();
+ };
+
+ struct d : b1, b2 {
+ };
+
+ void f() {
+ d *p = new d();
+ p->m(); // no-crash // no-warning
+ }
+}
+
+// Allow __cxa_demangle to escape.
+char* test_cxa_demangle(const char* sym) {
+ size_t funcnamesize = 256;
+ char* funcname = (char*)malloc(funcnamesize);
+ int status;
+ char* ret = abi::__cxa_demangle(sym, funcname, &funcnamesize, &status);
+ if (status == 0) {
+ funcname = ret;
+ }
+ return funcname; // no-warning
+}
diff --git a/test/Analysis/max-nodes-suppress-on-sink.c b/test/Analysis/max-nodes-suppress-on-sink.c
new file mode 100644
index 000000000000..c45bee8203df
--- /dev/null
+++ b/test/Analysis/max-nodes-suppress-on-sink.c
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-config max-nodes=12 -verify %s
+
+// Here we test how "suppress on sink" feature of certain bugtypes interacts
+// with reaching analysis limits.
+
+// If we report a warning of a bug-type with "suppress on sink" attribute set
+// (such as MallocChecker's memory leak warning), then failing to reach the
+// reason for the sink (eg. no-return function such as "exit()") due to analysis
+// limits (eg. max-nodes option), we may produce a false positive.
+
+typedef __typeof(sizeof(int)) size_t;
+void *malloc(size_t);
+
+extern void exit(int) __attribute__ ((__noreturn__));
+
+void clang_analyzer_warnIfReached(void);
+
+void test_single_cfg_block_sink() {
+ void *p = malloc(1); // no-warning (wherever the leak warning may occur here)
+
+ // Due to max-nodes option in the run line, we should reach the first call
+ // but bail out before the second call.
+ // If the test on these two lines starts failing, see if modifying
+ // the max-nodes run-line helps.
+ clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
+ clang_analyzer_warnIfReached(); // no-warning
+
+ // Even though we do not reach this line, we should still suppress
+ // the leak report.
+ exit(0);
+}
diff --git a/test/Analysis/misc-ps-64.m b/test/Analysis/misc-ps-64.m
index 1fbbeefd2ae4..be50d4606d4f 100644
--- a/test/Analysis/misc-ps-64.m
+++ b/test/Analysis/misc-ps-64.m
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -analyze -analyzer-checker=core,alpha.core -analyzer-store=region -analyzer-constraints=range -verify -fblocks %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -analyze -analyzer-checker=core,alpha.core -analyzer-store=region -verify -fblocks %s
// expected-no-diagnostics
// <rdar://problem/6440393> - A bunch of misc. failures involving evaluating
diff --git a/test/Analysis/misc-ps-eager-assume.m b/test/Analysis/misc-ps-eager-assume.m
index 9fbe3d0e4ee9..ca056d8fff9e 100644
--- a/test/Analysis/misc-ps-eager-assume.m
+++ b/test/Analysis/misc-ps-eager-assume.m
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core -analyzer-store=region -analyzer-constraints=range -verify -fblocks %s -analyzer-eagerly-assume
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core -analyzer-store=region -verify -fblocks %s -analyzer-eagerly-assume
// expected-no-diagnostics
// Delta-reduced header stuff (needed for test cases).
diff --git a/test/Analysis/misc-ps-ranges.m b/test/Analysis/misc-ps-ranges.m
index 90add22677f4..d8720e9a377c 100644
--- a/test/Analysis/misc-ps-ranges.m
+++ b/test/Analysis/misc-ps-ranges.m
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core -analyzer-store=region -analyzer-constraints=range -verify -fblocks %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core -analyzer-store=region -verify -fblocks %s
// <rdar://problem/6776949>
// main's 'argc' argument is always > 0
diff --git a/test/Analysis/misc-ps-region-store.cpp b/test/Analysis/misc-ps-region-store.cpp
index af9f7cf838e0..daa6d64f2bd5 100644
--- a/test/Analysis/misc-ps-region-store.cpp
+++ b/test/Analysis/misc-ps-region-store.cpp
@@ -138,7 +138,7 @@ void pr7675_test() {
pr7675(10.0);
pr7675(10);
pr7675('c');
- pr7675_i(4.0i);
+ pr7675_i(4.0j);
// Add check to ensure we are analyzing the code up to this point.
clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
diff --git a/test/Analysis/misc-ps.c b/test/Analysis/misc-ps.c
index 01cad1549cda..ad65437e4c1d 100644
--- a/test/Analysis/misc-ps.c
+++ b/test/Analysis/misc-ps.c
@@ -191,3 +191,13 @@ static void PR16131(int x) {
clang_analyzer_eval(*ip == 42); // expected-warning{{TRUE}}
clang_analyzer_eval(*(int *)&v == 42); // expected-warning{{TRUE}}
}
+
+// PR15623: Currently the analyzer doesn't handle symbolic expressions of the
+// form "(exp comparison_op expr) != 0" very well. We perform a simplification
+// translating an assume of a constraint of the form "(exp comparison_op expr)
+// != 0" to true into an assume of "exp comparison_op expr" to true.
+void PR15623(int n) {
+ if ((n == 0) != 0) {
+ clang_analyzer_eval(n == 0); // expected-warning{{TRUE}}
+ }
+}
diff --git a/test/Analysis/misc-ps.m b/test/Analysis/misc-ps.m
index ad7393b82d30..f979cf3eed82 100644
--- a/test/Analysis/misc-ps.m
+++ b/test/Analysis/misc-ps.m
@@ -1,6 +1,6 @@
// NOTE: Use '-fobjc-gc' to test the analysis being run twice, and multiple reports are not issued.
-// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core,alpha.core,osx.cocoa.AtSync -analyzer-store=region -analyzer-constraints=range -verify -fblocks -Wno-unreachable-code -Wno-null-dereference -Wno-objc-root-class %s
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core,alpha.core,osx.cocoa.AtSync -analyzer-store=region -analyzer-constraints=range -verify -fblocks -Wno-unreachable-code -Wno-null-dereference -Wno-objc-root-class %s
+// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core,alpha.core,osx.cocoa.AtSync -analyzer-store=region -verify -fblocks -Wno-unreachable-code -Wno-null-dereference -Wno-objc-root-class %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core,alpha.core,osx.cocoa.AtSync -analyzer-store=region -verify -fblocks -Wno-unreachable-code -Wno-null-dereference -Wno-objc-root-class %s
#ifndef __clang_analyzer__
#error __clang_analyzer__ not defined
diff --git a/test/Analysis/model-file.cpp b/test/Analysis/model-file.cpp
index f181c423d9b0..41cdf7fef48c 100644
--- a/test/Analysis/model-file.cpp
+++ b/test/Analysis/model-file.cpp
@@ -209,6 +209,35 @@ int main() {
// 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>31</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>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>27</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>
diff --git a/test/Analysis/nil-receiver-undefined-larger-than-voidptr-ret-region.m b/test/Analysis/nil-receiver-undefined-larger-than-voidptr-ret-region.m
index 384501ac89e1..e63e2cafaf42 100644
--- a/test/Analysis/nil-receiver-undefined-larger-than-voidptr-ret-region.m
+++ b/test/Analysis/nil-receiver-undefined-larger-than-voidptr-ret-region.m
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple i386-apple-darwin8 -analyze -analyzer-checker=core,alpha.core -analyzer-constraints=range -analyzer-store=region -verify -Wno-objc-root-class %s
+// RUN: %clang_cc1 -triple i386-apple-darwin8 -analyze -analyzer-checker=core,alpha.core -analyzer-store=region -verify -Wno-objc-root-class %s
// <rdar://problem/6888289> - This test case shows that a nil instance
// variable can possibly be initialized by a method.
diff --git a/test/Analysis/nil-receiver-undefined-larger-than-voidptr-ret.m b/test/Analysis/nil-receiver-undefined-larger-than-voidptr-ret.m
index 43a527be1907..4f9939040446 100644
--- a/test/Analysis/nil-receiver-undefined-larger-than-voidptr-ret.m
+++ b/test/Analysis/nil-receiver-undefined-larger-than-voidptr-ret.m
@@ -1,8 +1,8 @@
-// RUN: %clang_cc1 -triple i386-apple-darwin8 -analyze -analyzer-checker=core,alpha.core -analyzer-constraints=range -analyzer-store=region -Wno-objc-root-class %s > %t.1 2>&1
+// RUN: %clang_cc1 -triple i386-apple-darwin8 -analyze -analyzer-checker=core,alpha.core -analyzer-store=region -Wno-objc-root-class %s > %t.1 2>&1
// RUN: FileCheck -input-file=%t.1 -check-prefix=CHECK-darwin8 %s
-// RUN: %clang_cc1 -triple i386-apple-darwin9 -analyze -analyzer-checker=core,alpha.core -analyzer-constraints=range -analyzer-store=region -Wno-objc-root-class %s > %t.2 2>&1
+// RUN: %clang_cc1 -triple i386-apple-darwin9 -analyze -analyzer-checker=core,alpha.core -analyzer-store=region -Wno-objc-root-class %s > %t.2 2>&1
// RUN: FileCheck -input-file=%t.2 -check-prefix=CHECK-darwin9 %s
-// RUN: %clang_cc1 -triple thumbv6-apple-ios4.0 -analyze -analyzer-checker=core,alpha.core -analyzer-constraints=range -analyzer-store=region -Wno-objc-root-class %s > %t.3 2>&1
+// RUN: %clang_cc1 -triple thumbv6-apple-ios4.0 -analyze -analyzer-checker=core,alpha.core -analyzer-store=region -Wno-objc-root-class %s > %t.3 2>&1
// RUN: FileCheck -input-file=%t.3 -check-prefix=CHECK-darwin9 %s
@interface MyClass {}
diff --git a/test/Analysis/non-diagnosable-assumptions.c b/test/Analysis/non-diagnosable-assumptions.c
new file mode 100644
index 000000000000..50cc8d603b95
--- /dev/null
+++ b/test/Analysis/non-diagnosable-assumptions.c
@@ -0,0 +1,47 @@
+// RUN: %clang_cc1 -w -analyze -analyzer-checker=core.DivideZero -analyzer-output=text -verify %s
+
+// This test file verifies the "Assuming..." diagnostic pieces that are being
+// reported when the branch condition was too complicated to explain.
+// Therefore, if your change replaces the generic "Assuming the condition is
+// true" with a more specific message, causing this test to fail, the condition
+// should be replaced with a more complicated condition that we still cannot
+// properly explain to the user. Once we reach the point at which all conditions
+// are "diagnosable", this test (or this note) should probably be removed,
+// together with the code section that handles generic messages for
+// non-diagnosable conditions.
+
+// Function calls are currently non-diagnosable.
+int non_diagnosable();
+
+void test_true() {
+ if (non_diagnosable()) {
+ // expected-note@-1{{Assuming the condition is true}}
+ // expected-note@-2{{Taking true branch}}
+ 1 / 0;
+ // expected-warning@-1{{Division by zero}}
+ // expected-note@-2{{Division by zero}}
+ }
+}
+
+void test_false() {
+ if (non_diagnosable()) {
+ // expected-note@-1{{Assuming the condition is false}}
+ // expected-note@-2{{Taking false branch}}
+ } else {
+ 1 / 0;
+ // expected-warning@-1{{Division by zero}}
+ // expected-note@-2{{Division by zero}}
+ }
+}
+
+// Test that we're still reporting that the condition is true,
+// when we encounter an exclamation mark (used to be broken).
+void test_exclamation_mark() {
+ if (!non_diagnosable()) {
+ // expected-note@-1{{Assuming the condition is true}}
+ // expected-note@-2{{Taking true branch}}
+ 1 / 0;
+ // expected-warning@-1{{Division by zero}}
+ // expected-note@-2{{Division by zero}}
+ }
+}
diff --git a/test/Analysis/null-deref-ps.c b/test/Analysis/null-deref-ps.c
index 79b3b3a5758c..b0d2292547f6 100644
--- a/test/Analysis/null-deref-ps.c
+++ b/test/Analysis/null-deref-ps.c
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core,deadcode,alpha.core -std=gnu99 -analyzer-store=region -analyzer-constraints=range -analyzer-purge=none -verify %s -Wno-error=return-type
-// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core,deadcode,alpha.core -std=gnu99 -analyzer-store=region -analyzer-constraints=range -verify %s -Wno-error=return-type
+// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core,deadcode,alpha.core -std=gnu99 -analyzer-store=region -analyzer-purge=none -verify %s -Wno-error=return-type
+// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core,deadcode,alpha.core -std=gnu99 -analyzer-store=region -verify %s -Wno-error=return-type
typedef unsigned uintptr_t;
diff --git a/test/Analysis/nullability-no-arc.mm b/test/Analysis/nullability-no-arc.mm
index 37d29b7457af..e872266d2770 100644
--- a/test/Analysis/nullability-no-arc.mm
+++ b/test/Analysis/nullability-no-arc.mm
@@ -17,20 +17,20 @@ NSObject<NSObject>
@interface TestObject : NSObject
@end
-TestObject * _Nonnull returnsNilObjCInstanceIndirectly() {
- TestObject *local = 0;
- return local; // expected-warning {{Null is returned from a function that is expected to return a non-null value}}
+TestObject *_Nonnull returnsNilObjCInstanceIndirectly() {
+ TestObject *local = nil;
+ return local; // expected-warning {{nil returned from a function that is expected to return a non-null value}}
}
TestObject * _Nonnull returnsNilObjCInstanceIndirectlyWithSupressingCast() {
- TestObject *local = 0;
+ TestObject *local = nil;
return (TestObject * _Nonnull)local; // no-warning
}
TestObject * _Nonnull returnsNilObjCInstanceDirectly() {
// The first warning is from Sema. The second is from the static analyzer.
return nil; // expected-warning {{null returned from function that requires a non-null return value}}
- // expected-warning@-1 {{Null is returned from a function that is expected to return a non-null value}}
+ // expected-warning@-1 {{nil returned from a function that is expected to return a non-null value}}
}
TestObject * _Nonnull returnsNilObjCInstanceDirectlyWithSuppressingCast() {
@@ -43,7 +43,7 @@ void testObjCNonARCNoInitialization(TestObject * _Nonnull p) {
}
void testObjCNonARCExplicitZeroInitialization() {
- TestObject * _Nonnull explicitlyZeroInitialized = nil; // expected-warning {{Null is assigned to a pointer which is expected to have non-null value}}
+ TestObject * _Nonnull explicitlyZeroInitialized = nil; // expected-warning {{nil assigned to a pointer which is expected to have non-null value}}
}
@interface ClassWithInitializers : NSObject
diff --git a/test/Analysis/nullability.c b/test/Analysis/nullability.c
new file mode 100644
index 000000000000..a282969e03d4
--- /dev/null
+++ b/test/Analysis/nullability.c
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -fblocks -analyze -analyzer-checker=core,nullability -verify %s
+
+void it_takes_two(int a, int b);
+void function_pointer_arity_mismatch() {
+ void(*fptr)() = it_takes_two;
+ fptr(1); // no-crash expected-warning {{Function taking 2 arguments is called with fewer (1)}}
+}
+
+void block_arity_mismatch() {
+ void(^b)() = ^(int a, int b) { };
+ b(1); // no-crash expected-warning {{Block taking 2 arguments is called with fewer (1)}}
+}
diff --git a/test/Analysis/nullability.mm b/test/Analysis/nullability.mm
index c6d6519d90e7..e4f13c6162cb 100644
--- a/test/Analysis/nullability.mm
+++ b/test/Analysis/nullability.mm
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -fblocks -analyze -analyzer-checker=core,nullability -DNOSYSTEMHEADERS=0 -verify %s
-// RUN: %clang_cc1 -fblocks -analyze -analyzer-checker=core,nullability -analyzer-config nullability:NoDiagnoseCallsToSystemHeaders=true -DNOSYSTEMHEADERS=1 -verify %s
+// RUN: %clang_cc1 -fblocks -analyze -analyzer-checker=core,nullability.NullPassedToNonnull,nullability.NullReturnedFromNonnull,nullability.NullablePassedToNonnull,nullability.NullableReturnedFromNonnull,nullability.NullableDereferenced -DNOSYSTEMHEADERS=0 -verify %s
+// RUN: %clang_cc1 -fblocks -analyze -analyzer-checker=core,nullability.NullPassedToNonnull,nullability.NullReturnedFromNonnull,nullability.NullablePassedToNonnull,nullability.NullableReturnedFromNonnull,nullability.NullableDereferenced -analyzer-config nullability:NoDiagnoseCallsToSystemHeaders=true -DNOSYSTEMHEADERS=1 -verify %s
#include "Inputs/system-header-simulator-for-nullability.h"
@@ -75,7 +75,7 @@ void testBasicRules() {
}
Dummy a;
Dummy *_Nonnull nonnull = &a;
- nonnull = q; // expected-warning {{Null is assigned to a pointer which is expected to have non-null value}}
+ nonnull = q; // expected-warning {{Null assigned to a pointer which is expected to have non-null value}}
q = &a;
takesNullable(q);
takesNonnull(q);
@@ -107,7 +107,7 @@ Dummy *_Nonnull testNullableReturn(Dummy *_Nullable a) {
Dummy *_Nonnull testNullReturn() {
Dummy *p = 0;
- return p; // expected-warning {{Null is returned from a function that is expected to return a non-null value}}
+ return p; // expected-warning {{Null returned from a function that is expected to return a non-null value}}
}
void testObjCMessageResultNullability() {
@@ -229,7 +229,7 @@ void testConditionalNilPassToNonnull(Dummy *p) {
Dummy * _Nonnull testIndirectCastNilToNonnullAndReturn() {
Dummy *p = (Dummy * _Nonnull)0;
// FIXME: Ideally the cast above would suppress this warning.
- return p; // expected-warning {{Null is returned from a function that is expected to return a non-null value}}
+ return p; // expected-warning {{Null returned from a function that is expected to return a non-null value}}
}
void testInvalidPropagation() {
diff --git a/test/Analysis/nullability_nullonly.mm b/test/Analysis/nullability_nullonly.mm
index 9671877719f3..359841d97a62 100644
--- a/test/Analysis/nullability_nullonly.mm
+++ b/test/Analysis/nullability_nullonly.mm
@@ -24,7 +24,7 @@ void testBasicRules() {
Dummy *_Nonnull testNullReturn() {
Dummy *p = 0;
- return p; // expected-warning {{Null is returned from a function that is expected to return a non-null value}}
+ return p; // expected-warning {{Null returned from a function that is expected to return a non-null value}}
}
void onlyReportFirstPreconditionViolationOnPath() {
@@ -100,24 +100,24 @@ void testObjCARCImplicitZeroInitialization() {
}
void testObjCARCExplicitZeroInitialization() {
- TestObject * _Nonnull explicitlyZeroInitialized = nil; // expected-warning {{Null is assigned to a pointer which is expected to have non-null value}}
+ TestObject * _Nonnull explicitlyZeroInitialized = nil; // expected-warning {{nil assigned to a pointer which is expected to have non-null value}}
}
// Under ARC, returned expressions of ObjC objects types are are implicitly
// cast to _Nonnull when the functions return type is _Nonnull, so make
// sure this doesn't implicit cast doesn't suppress a legitimate warning.
TestObject * _Nonnull returnsNilObjCInstanceIndirectly() {
- TestObject *local = 0;
- return local; // expected-warning {{Null is returned from a function that is expected to return a non-null value}}
+ TestObject *local = nil;
+ return local; // expected-warning {{nil returned from a function that is expected to return a non-null value}}
}
TestObject * _Nonnull returnsNilObjCInstanceIndirectlyWithSupressingCast() {
- TestObject *local = 0;
+ TestObject *local = nil;
return (TestObject * _Nonnull)local; // no-warning
}
TestObject * _Nonnull returnsNilObjCInstanceDirectly() {
- return nil; // expected-warning {{Null is returned from a function that is expected to return a non-null value}}
+ return nil; // expected-warning {{nil returned from a function that is expected to return a non-null value}}
}
TestObject * _Nonnull returnsNilObjCInstanceDirectlyWithSuppressingCast() {
@@ -130,7 +130,7 @@ TestObject * _Nonnull returnsNilObjCInstanceDirectlyWithSuppressingCast() {
@implementation SomeClass (MethodReturn)
- (SomeClass * _Nonnull)testReturnsNilInNonnull {
SomeClass *local = nil;
- return local; // expected-warning {{Null is returned from a method that is expected to return a non-null value}}
+ return local; // expected-warning {{nil returned from a method that is expected to return a non-null value}}
}
- (SomeClass * _Nonnull)testReturnsCastSuppressedNilInNonnull {
@@ -154,7 +154,7 @@ void callFunctionInSystemHeader() {
NSSystemFunctionTakingNonnull(s);
#if !NOSYSTEMHEADERS
- // expected-warning@-2{{Null passed to a callee that requires a non-null 1st parameter}}
+ // expected-warning@-2{{nil passed to a callee that requires a non-null 1st parameter}}
#endif
}
@@ -165,6 +165,6 @@ void callMethodInSystemHeader() {
NSSystemClass *sc = [[NSSystemClass alloc] init];
[sc takesNonnull:s];
#if !NOSYSTEMHEADERS
- // expected-warning@-2{{Null passed to a callee that requires a non-null 1st parameter}}
+ // expected-warning@-2{{nil passed to a callee that requires a non-null 1st parameter}}
#endif
}
diff --git a/test/Analysis/number-object-conversion.c b/test/Analysis/number-object-conversion.c
new file mode 100644
index 000000000000..c4ffaaffef12
--- /dev/null
+++ b/test/Analysis/number-object-conversion.c
@@ -0,0 +1,40 @@
+// RUN: %clang_cc1 -triple i386-apple-darwin10 -w -analyze -analyzer-checker=osx.NumberObjectConversion %s -verify
+// RUN: %clang_cc1 -triple i386-apple-darwin10 -w -analyze -analyzer-checker=osx.NumberObjectConversion -analyzer-config osx.NumberObjectConversion:Pedantic=true -DPEDANTIC %s -verify
+
+#define NULL ((void *)0)
+
+typedef const struct __CFNumber *CFNumberRef;
+
+void takes_int(int);
+
+void bad(CFNumberRef p) {
+#ifdef PEDANTIC
+ if (p) {} // expected-warning{{Converting a pointer value of type 'CFNumberRef' to a primitive boolean value; instead, either compare the pointer to NULL or call CFNumberGetValue()}}
+ if (!p) {} // expected-warning{{Converting a pointer value of type 'CFNumberRef' to a primitive boolean value; instead, either compare the pointer to NULL or call CFNumberGetValue()}}
+ p ? 1 : 2; // expected-warning{{Converting a pointer value of type 'CFNumberRef' to a primitive boolean value; instead, either compare the pointer to NULL or call CFNumberGetValue()}}
+ if (p == 0) {} // expected-warning{{Comparing a pointer value of type 'CFNumberRef' to a primitive integer value; instead, either compare the pointer to NULL or compare the result of calling CFNumberGetValue()}}
+#else
+ if (p) {} // no-warning
+ if (!p) {} // no-warning
+ p ? 1 : 2; // no-warning
+ if (p == 0) {} // no-warning
+#endif
+ if (p > 0) {} // expected-warning{{Comparing a pointer value of type 'CFNumberRef' to a primitive integer value; did you mean to compare the result of calling CFNumberGetValue()?}}
+ int x = p; // expected-warning{{Converting a pointer value of type 'CFNumberRef' to a primitive integer value; did you mean to call CFNumberGetValue()?}}
+ x = p; // expected-warning{{Converting a pointer value of type 'CFNumberRef' to a primitive integer value; did you mean to call CFNumberGetValue()?}}
+ takes_int(p); // expected-warning{{Converting a pointer value of type 'CFNumberRef' to a primitive integer value; did you mean to call CFNumberGetValue()?}}
+ takes_int(x); // no-warning
+}
+
+// Conversion of a pointer to an intptr_t is fine.
+typedef long intptr_t;
+typedef unsigned long uintptr_t;
+typedef long fintptr_t; // Fake, for testing the regex.
+void test_intptr_t(CFNumberRef p) {
+ (long)p; // expected-warning{{Converting a pointer value of type 'CFNumberRef' to a primitive integer value; did you mean to call CFNumberGetValue()?}}
+ (intptr_t)p; // no-warning
+ (unsigned long)p; // expected-warning{{Converting a pointer value of type 'CFNumberRef' to a primitive integer value; did you mean to call CFNumberGetValue()?}}
+ (uintptr_t)p; // no-warning
+ (fintptr_t)p; // expected-warning{{Converting a pointer value of type 'CFNumberRef' to a primitive integer value; did you mean to call CFNumberGetValue()?}}
+}
+
diff --git a/test/Analysis/number-object-conversion.cpp b/test/Analysis/number-object-conversion.cpp
new file mode 100644
index 000000000000..9dea7b067d08
--- /dev/null
+++ b/test/Analysis/number-object-conversion.cpp
@@ -0,0 +1,94 @@
+// RUN: %clang_cc1 -triple i386-apple-darwin10 -w -std=c++11 -analyze -analyzer-checker=osx.NumberObjectConversion %s -verify
+// RUN: %clang_cc1 -triple i386-apple-darwin10 -w -std=c++11 -analyze -analyzer-checker=osx.NumberObjectConversion -analyzer-config osx.NumberObjectConversion:Pedantic=true -DPEDANTIC %s -verify
+
+#define NULL ((void *)0)
+#include "Inputs/system-header-simulator-cxx.h" // for nullptr
+
+class OSBoolean {
+public:
+ virtual bool isTrue() const;
+ virtual bool isFalse() const;
+};
+
+class OSNumber {
+public:
+ virtual bool isEqualTo(const OSNumber *);
+ virtual unsigned char unsigned8BitValue() const;
+ virtual unsigned short unsigned16BitValue() const;
+ virtual unsigned int unsigned32BitValue() const;
+ virtual unsigned long long unsigned64BitValue() const;
+};
+
+extern const OSBoolean *const &kOSBooleanFalse;
+extern const OSBoolean *const &kOSBooleanTrue;
+
+void takes_bool(bool);
+
+void bad_boolean(const OSBoolean *p) {
+#ifdef PEDANTIC
+ if (p) {} // expected-warning{{Converting a pointer value of type 'class OSBoolean *' to a primitive boolean value; instead, either compare the pointer to nullptr or call getValue()}}
+ if (!p) {} // expected-warning{{Converting a pointer value of type 'class OSBoolean *' to a primitive boolean value; instead, either compare the pointer to nullptr or call getValue()}}
+ p ? 1 : 2; // expected-warning{{Converting a pointer value of type 'class OSBoolean *' to a primitive boolean value; instead, either compare the pointer to nullptr or call getValue()}}
+#else
+ if (p) {} // no-warning
+ if (!p) {} // no-warning
+ p ? 1 : 2; // no-warning
+#endif
+ (bool)p; // expected-warning{{Converting a pointer value of type 'class OSBoolean *' to a primitive bool value; did you mean to call getValue()?}}
+ bool x = p; // expected-warning{{Converting a pointer value of type 'class OSBoolean *' to a primitive bool value; did you mean to call getValue()?}}
+ x = p; // expected-warning{{Converting a pointer value of type 'class OSBoolean *' to a primitive bool value; did you mean to call getValue()?}}
+ takes_bool(p); // expected-warning{{Converting a pointer value of type 'class OSBoolean *' to a primitive bool value; did you mean to call getValue()?}}
+ takes_bool(x); // no-warning
+}
+
+void bad_number(const OSNumber *p) {
+#ifdef PEDANTIC
+ if (p) {} // expected-warning{{Converting a pointer value of type 'class OSNumber *' to a scalar boolean value; instead, either compare the pointer to nullptr or call a method on 'class OSNumber *' to get the scalar value}}
+ if (!p) {} // expected-warning{{Converting a pointer value of type 'class OSNumber *' to a scalar boolean value; instead, either compare the pointer to nullptr or call a method on 'class OSNumber *' to get the scalar value}}
+ p ? 1 : 2; // expected-warning{{Converting a pointer value of type 'class OSNumber *' to a scalar boolean value; instead, either compare the pointer to nullptr or call a method on 'class OSNumber *' to get the scalar value}}
+ if (p == 0) {} // expected-warning{{Comparing a pointer value of type 'class OSNumber *' to a scalar integer value; instead, either compare the pointer to nullptr or compare the result of calling a method on 'class OSNumber *' to get the scalar value}}
+#else
+ if (p) {} // no-warning
+ if (!p) {} // no-warning
+ p ? 1 : 2; // no-warning
+ if (p == 0) {} // no-warning
+#endif
+ (int)p; // expected-warning{{Converting a pointer value of type 'class OSNumber *' to a scalar integer value; did you mean to call a method on 'class OSNumber *' to get the scalar value?}}
+ takes_bool(p); // expected-warning{{Converting a pointer value of type 'class OSNumber *' to a scalar bool value; did you mean to call a method on 'class OSNumber *' to get the scalar value?}}
+}
+
+typedef bool sugared_bool;
+typedef const OSBoolean *sugared_OSBoolean;
+void bad_sugared(sugared_OSBoolean p) {
+ sugared_bool x = p; // expected-warning{{Converting a pointer value of type 'class OSBoolean *' to a primitive bool value; did you mean to call getValue()?}}
+}
+
+void good(const OSBoolean *p) {
+ bool x = p->isTrue(); // no-warning
+ (bool)p->isFalse(); // no-warning
+ if (p == kOSBooleanTrue) {} // no-warning
+}
+
+void suppression(const OSBoolean *p) {
+ if (p == NULL) {} // no-warning
+ bool y = (p == nullptr); // no-warning
+}
+
+// Conversion of a pointer to an intptr_t is fine.
+typedef long intptr_t;
+typedef unsigned long uintptr_t;
+typedef long fintptr_t; // Fake, for testing the regex.
+void test_intptr_t(const OSBoolean *p) {
+ (long)p; // expected-warning{{Converting a pointer value of type 'class OSBoolean *' to a primitive integer value; did you mean to call getValue()?}}
+ (intptr_t)p; // no-warning
+ (unsigned long)p; // expected-warning{{Converting a pointer value of type 'class OSBoolean *' to a primitive integer value; did you mean to call getValue()?}}
+ (uintptr_t)p; // no-warning
+ (fintptr_t)p; // expected-warning{{Converting a pointer value of type 'class OSBoolean *' to a primitive integer value; did you mean to call getValue()?}}
+}
+
+// Test a different definition of NULL.
+#undef NULL
+#define NULL 0
+void test_non_pointer_NULL(const OSBoolean *p) {
+ if (p == NULL) {} // no-warning
+}
diff --git a/test/Analysis/number-object-conversion.m b/test/Analysis/number-object-conversion.m
new file mode 100644
index 000000000000..08d4a195431d
--- /dev/null
+++ b/test/Analysis/number-object-conversion.m
@@ -0,0 +1,112 @@
+// RUN: %clang_cc1 -triple i386-apple-darwin10 -fblocks -w -analyze -analyzer-checker=osx.NumberObjectConversion %s -verify
+// RUN: %clang_cc1 -triple i386-apple-darwin10 -fblocks -w -analyze -analyzer-checker=osx.NumberObjectConversion -analyzer-config osx.NumberObjectConversion:Pedantic=true -DPEDANTIC %s -verify
+// RUN: %clang_cc1 -triple i386-apple-darwin10 -fblocks -fobjc-arc -w -analyze -analyzer-checker=osx.NumberObjectConversion %s -verify
+// RUN: %clang_cc1 -triple i386-apple-darwin10 -fblocks -fobjc-arc -w -analyze -analyzer-checker=osx.NumberObjectConversion -analyzer-config osx.NumberObjectConversion:Pedantic=true -DPEDANTIC %s -verify
+
+#include "Inputs/system-header-simulator-objc.h"
+
+void takes_boolean(BOOL);
+void takes_integer(int);
+
+void bad(NSNumber *p) {
+#ifdef PEDANTIC
+ if (p) {} // expected-warning{{Converting a pointer value of type 'NSNumber *' to a primitive boolean value; instead, either compare the pointer to nil or call -boolValue}}
+ if (!p) {} // expected-warning{{Converting a pointer value of type 'NSNumber *' to a primitive boolean value; instead, either compare the pointer to nil or call -boolValue}}
+ (!p) ? 1 : 2; // expected-warning{{Converting a pointer value of type 'NSNumber *' to a primitive boolean value; instead, either compare the pointer to nil or call -boolValue}}
+ if (p == 0) {} // expected-warning{{Comparing a pointer value of type 'NSNumber *' to a scalar integer value; instead, either compare the pointer to nil or compare the result of calling a method on 'NSNumber *' to get the scalar value}}
+#else
+ if (p) {} // no-warning
+ if (!p) {} // no-warning
+ (!p) ? 1 : 2; // no-warning
+ if (p == 0) {} // no-warning
+#endif
+ (BOOL)p; // expected-warning{{Converting a pointer value of type 'NSNumber *' to a primitive BOOL value; did you mean to call -boolValue?}}
+ if (p > 0) {} // expected-warning{{Comparing a pointer value of type 'NSNumber *' to a scalar integer value; did you mean to compare the result of calling a method on 'NSNumber *' to get the scalar value?}}
+ if (p == YES) {} // expected-warning{{Comparing a pointer value of type 'NSNumber *' to a primitive BOOL value; did you mean to compare the result of calling -boolValue?}}
+ if (p == NO) {} // expected-warning{{Comparing a pointer value of type 'NSNumber *' to a primitive BOOL value; did you mean to compare the result of calling -boolValue?}}
+ BOOL x = p; // expected-warning{{Converting a pointer value of type 'NSNumber *' to a primitive BOOL value; did you mean to call -boolValue?}}
+ x = p; // expected-warning{{Converting a pointer value of type 'NSNumber *' to a primitive BOOL value; did you mean to call -boolValue?}}
+ x = (p == YES); // expected-warning{{Comparing a pointer value of type 'NSNumber *' to a primitive BOOL value; did you mean to compare the result of calling -boolValue?}}
+ if (p == 1) {} // expected-warning{{Comparing a pointer value of type 'NSNumber *' to a scalar integer value; did you mean to compare the result of calling a method on 'NSNumber *' to get the scalar value?}}
+ int y = p; // expected-warning{{Converting a pointer value of type 'NSNumber *' to a scalar integer value; did you mean to call a method on 'NSNumber *' to get the scalar value?}}
+ y = p; // expected-warning{{Converting a pointer value of type 'NSNumber *' to a scalar integer value; did you mean to call a method on 'NSNumber *' to get the scalar value?}}
+ takes_boolean(p); // expected-warning{{Converting a pointer value of type 'NSNumber *' to a primitive BOOL value; did you mean to call -boolValue?}}
+ takes_integer(p); // expected-warning{{Converting a pointer value of type 'NSNumber *' to a scalar integer value; did you mean to call a method on 'NSNumber *' to get the scalar value?}}
+ takes_boolean(x); // no-warning
+ takes_integer(y); // no-warning
+}
+
+typedef NSNumber *SugaredNumber;
+void bad_sugared(SugaredNumber p) {
+ p == YES; // expected-warning{{Comparing a pointer value of type 'SugaredNumber' to a primitive BOOL value; did you mean to compare the result of calling -boolValue?}}
+}
+
+@interface I : NSObject {
+@public
+ NSNumber *ivar;
+ NSNumber *prop;
+}
+- (NSNumber *)foo;
+@property(copy) NSNumber *prop;
+@end
+
+@implementation I
+@synthesize prop;
+@end
+
+void bad_ivar(I *i) {
+ i->ivar == YES; // expected-warning{{Comparing a pointer value of type 'NSNumber *' to a primitive BOOL value; did you mean to compare the result of calling -boolValue?}}
+ i->prop == YES; // expected-warning{{Comparing a pointer value of type 'NSNumber *' to a primitive BOOL value; did you mean to compare the result of calling -boolValue?}}
+ [i foo] == YES; // expected-warning{{Comparing a pointer value of type 'NSNumber *' to a primitive BOOL value; did you mean to compare the result of calling -boolValue?}}
+}
+
+void good(NSNumber *p) {
+ if ([p boolValue] == NO) {} // no-warning
+ if ([p boolValue] == YES) {} // no-warning
+ BOOL x = [p boolValue]; // no-warning
+}
+
+void suppression(NSNumber *p) {
+ if (p == NULL) {} // no-warning
+ if (p == nil) {} // no-warning
+}
+
+// Conversion of a pointer to an intptr_t is fine.
+typedef long intptr_t;
+typedef unsigned long uintptr_t;
+typedef long fintptr_t; // Fake, for testing the regex.
+void test_intptr_t(NSNumber *p) {
+ (long)p; // expected-warning{{Converting a pointer value of type 'NSNumber *' to a scalar integer value; did you mean to call a method on 'NSNumber *' to get the scalar value?}}
+ (intptr_t)p; // no-warning
+ (unsigned long)p; // expected-warning{{Converting a pointer value of type 'NSNumber *' to a scalar integer value; did you mean to call a method on 'NSNumber *' to get the scalar value?}}
+ (uintptr_t)p; // no-warning
+ (fintptr_t)p; // expected-warning{{Converting a pointer value of type 'NSNumber *' to a scalar integer value; did you mean to call a method on 'NSNumber *' to get the scalar value?}}
+}
+
+// Test macro suppressions.
+#define FOO 0
+#define BAR 1
+void test_macro(NSNumber *p) {
+ if (p != BAR) {} // expected-warning{{Comparing a pointer value of type 'NSNumber *' to a scalar integer value; did you mean to compare the result of calling a method on 'NSNumber *' to get the scalar value?}}
+#ifdef PEDANTIC
+ if (p != FOO) {} // expected-warning{{Comparing a pointer value of type 'NSNumber *' to a scalar integer value; instead, either compare the pointer to nil or compare the result of calling a method on 'NSNumber *' to get the scalar value}}
+#else
+ if (p != FOO) {} // no-warning
+#endif
+}
+
+#define NULL_INSIDE_MACRO NULL
+void test_NULL_inside_macro(NSNumber *p) {
+#ifdef PEDANTIC
+ if (p == NULL_INSIDE_MACRO) {} // no-warning
+#else
+ if (p == NULL_INSIDE_MACRO) {} // no-warning
+#endif
+}
+
+// Test a different definition of NULL.
+#undef NULL
+#define NULL 0
+void test_non_pointer_NULL(NSNumber *p) {
+ if (p == NULL) {} // no-warning
+}
diff --git a/test/Analysis/objc-arc.m b/test/Analysis/objc-arc.m
index e9ef459036b2..2d47c18ba46e 100644
--- a/test/Analysis/objc-arc.m
+++ b/test/Analysis/objc-arc.m
@@ -441,9 +441,9 @@ id rdar14061675() {
// CHECK-NEXT: </array>
// CHECK-NEXT: <key>depth</key><integer>0</integer>
// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object with a +1 retain count</string>
+// CHECK-NEXT: <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type CFDateRef with a +1 retain count</string>
// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object with a +1 retain count</string>
+// CHECK-NEXT: <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type CFDateRef with a +1 retain count</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>control</string>
@@ -911,9 +911,9 @@ id rdar14061675() {
// CHECK-NEXT: </array>
// CHECK-NEXT: <key>depth</key><integer>0</integer>
// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object with a +1 retain count</string>
+// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type CFTypeRef with a +1 retain count</string>
// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object with a +1 retain count</string>
+// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type CFTypeRef with a +1 retain count</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>control</string>
@@ -1091,9 +1091,9 @@ id rdar14061675() {
// CHECK-NEXT: </array>
// CHECK-NEXT: <key>depth</key><integer>0</integer>
// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateString&apos; returns a Core Foundation object with a +1 retain count</string>
+// CHECK-NEXT: <string>Call to function &apos;CFCreateString&apos; returns a Core Foundation object of type CFStringRef with a +1 retain count</string>
// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateString&apos; returns a Core Foundation object with a +1 retain count</string>
+// CHECK-NEXT: <string>Call to function &apos;CFCreateString&apos; returns a Core Foundation object of type CFStringRef with a +1 retain count</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>control</string>
@@ -1466,9 +1466,9 @@ id rdar14061675() {
// CHECK-NEXT: </array>
// CHECK-NEXT: <key>depth</key><integer>0</integer>
// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object with a +1 retain count</string>
+// CHECK-NEXT: <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type CFDateRef with a +1 retain count</string>
// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object with a +1 retain count</string>
+// CHECK-NEXT: <string>Call to function &apos;CFDateCreate&apos; returns a Core Foundation object of type CFDateRef with a +1 retain count</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>control</string>
@@ -1782,9 +1782,9 @@ id rdar14061675() {
// CHECK-NEXT: </array>
// CHECK-NEXT: <key>depth</key><integer>0</integer>
// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateString&apos; returns a Core Foundation object with a +1 retain count</string>
+// CHECK-NEXT: <string>Call to function &apos;CFCreateString&apos; returns a Core Foundation object of type CFStringRef with a +1 retain count</string>
// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateString&apos; returns a Core Foundation object with a +1 retain count</string>
+// CHECK-NEXT: <string>Call to function &apos;CFCreateString&apos; returns a Core Foundation object of type CFStringRef with a +1 retain count</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>control</string>
@@ -1879,9 +1879,9 @@ id rdar14061675() {
// CHECK-NEXT: </array>
// CHECK-NEXT: <key>depth</key><integer>0</integer>
// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +0 retain count</string>
+// CHECK-NEXT: <string>Method returns an instance of NSObject with a +0 retain count</string>
// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +0 retain count</string>
+// CHECK-NEXT: <string>Method returns an instance of NSObject with a +0 retain count</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>control</string>
diff --git a/test/Analysis/out-of-bounds-new.cpp b/test/Analysis/out-of-bounds-new.cpp
new file mode 100644
index 000000000000..ee7bb1ec444b
--- /dev/null
+++ b/test/Analysis/out-of-bounds-new.cpp
@@ -0,0 +1,156 @@
+// RUN: %clang_cc1 -std=c++11 -Wno-array-bounds -analyze -analyzer-checker=unix,core,alpha.security.ArrayBoundV2 -verify %s
+
+// Tests doing an out-of-bounds access after the end of an array using:
+// - constant integer index
+// - constant integer size for buffer
+void test1(int x) {
+ int *buf = new int[100];
+ buf[100] = 1; // expected-warning{{Out of bound memory access}}
+}
+
+void test1_ok(int x) {
+ int *buf = new int[100];
+ buf[99] = 1; // no-warning
+}
+
+// Tests doing an out-of-bounds access after the end of an array using:
+// - indirect pointer to buffer
+// - constant integer index
+// - constant integer size for buffer
+void test1_ptr(int x) {
+ int *buf = new int[100];
+ int *p = buf;
+ p[101] = 1; // expected-warning{{Out of bound memory access}}
+}
+
+void test1_ptr_ok(int x) {
+ int *buf = new int[100];
+ int *p = buf;
+ p[99] = 1; // no-warning
+}
+
+// Tests doing an out-of-bounds access before the start of an array using:
+// - indirect pointer to buffer, manipulated using simple pointer arithmetic
+// - constant integer index
+// - constant integer size for buffer
+void test1_ptr_arith(int x) {
+ int *buf = new int[100];
+ int *p = buf;
+ p = p + 100;
+ p[0] = 1; // expected-warning{{Out of bound memory access}}
+}
+
+void test1_ptr_arith_ok(int x) {
+ int *buf = new int[100];
+ int *p = buf;
+ p = p + 99;
+ p[0] = 1; // no-warning
+}
+
+void test1_ptr_arith_bad(int x) {
+ int *buf = new int[100];
+ int *p = buf;
+ p = p + 99;
+ p[1] = 1; // expected-warning{{Out of bound memory access}}
+}
+
+void test1_ptr_arith_ok2(int x) {
+ int *buf = new int[100];
+ int *p = buf;
+ p = p + 99;
+ p[-1] = 1; // no-warning
+}
+
+// Tests doing an out-of-bounds access before the start of an array using:
+// - constant integer index
+// - constant integer size for buffer
+void test2(int x) {
+ int *buf = new int[100];
+ buf[-1] = 1; // expected-warning{{Out of bound memory access}}
+}
+
+// Tests doing an out-of-bounds access before the start of an array using:
+// - indirect pointer to buffer
+// - constant integer index
+// - constant integer size for buffer
+void test2_ptr(int x) {
+ int *buf = new int[100];
+ int *p = buf;
+ p[-1] = 1; // expected-warning{{Out of bound memory access}}
+}
+
+// Tests doing an out-of-bounds access before the start of an array using:
+// - indirect pointer to buffer, manipulated using simple pointer arithmetic
+// - constant integer index
+// - constant integer size for buffer
+void test2_ptr_arith(int x) {
+ int *buf = new int[100];
+ int *p = buf;
+ --p;
+ p[0] = 1; // expected-warning {{Out of bound memory access (accessed memory precedes memory block)}}
+}
+
+// Tests under-indexing
+// of a multi-dimensional array
+void test2_multi(int x) {
+ auto buf = new int[100][100];
+ buf[0][-1] = 1; // expected-warning{{Out of bound memory access}}
+}
+
+// Tests under-indexing
+// of a multi-dimensional array
+void test2_multi_b(int x) {
+ auto buf = new int[100][100];
+ buf[-1][0] = 1; // expected-warning{{Out of bound memory access}}
+}
+
+// Tests over-indexing
+// of a multi-dimensional array
+void test2_multi_c(int x) {
+ auto buf = new int[100][100];
+ buf[100][0] = 1; // expected-warning{{Out of bound memory access}}
+}
+
+// Tests over-indexing
+// of a multi-dimensional array
+void test2_multi_2(int x) {
+ auto buf = new int[100][100];
+ buf[99][100] = 1; // expected-warning{{Out of bound memory access}}
+}
+
+// Tests normal access of
+// a multi-dimensional array
+void test2_multi_ok(int x) {
+ auto buf = new int[100][100];
+ buf[0][0] = 1; // no-warning
+}
+
+// Tests over-indexing using different types
+// array
+void test_diff_types(int x) {
+ int *buf = new int[10]; //10*sizeof(int) Bytes allocated
+ char *cptr = (char *)buf;
+ cptr[sizeof(int) * 9] = 1; // no-warning
+ cptr[sizeof(int) * 10] = 1; // expected-warning{{Out of bound memory access}}
+}
+
+// Tests over-indexing
+//if the allocated area is non-array
+void test_non_array(int x) {
+ int *ip = new int;
+ ip[0] = 1; // no-warning
+ ip[1] = 2; // expected-warning{{Out of bound memory access}}
+}
+
+//Tests over-indexing
+//if the allocated area size is a runtime parameter
+void test_dynamic_size(int s) {
+ int *buf = new int[s];
+ buf[0] = 1; // no-warning
+}
+//Tests complex arithmetic
+//in new expression
+void test_dynamic_size2(unsigned m,unsigned n){
+ unsigned *U = nullptr;
+ U = new unsigned[m + n + 1];
+}
diff --git a/test/Analysis/out-of-bounds.c b/test/Analysis/out-of-bounds.c
index d89a23961903..ca1e0d05006a 100644
--- a/test/Analysis/out-of-bounds.c
+++ b/test/Analysis/out-of-bounds.c
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -Wno-array-bounds -analyze -analyzer-checker=core,alpha.security.ArrayBoundV2 -verify %s
+// RUN: %clang_cc1 -Wno-array-bounds -analyze -analyzer-checker=core,alpha.security.ArrayBoundV2,debug.ExprInspection -verify %s
+
+void clang_analyzer_eval(int);
// Tests doing an out-of-bounds access after the end of an array using:
// - constant integer index
@@ -128,22 +130,22 @@ void test2_multi_ok(int x) {
buf[0][0] = 1; // no-warning
}
-// *** FIXME ***
-// We don't get a warning here yet because our symbolic constraint solving
-// doesn't handle: (symbol * constant) < constant
void test3(int x) {
int buf[100];
if (x < 0)
- buf[x] = 1;
+ buf[x] = 1; // expected-warning{{Out of bound memory access}}
}
-// *** FIXME ***
-// We don't get a warning here yet because our symbolic constraint solving
-// doesn't handle: (symbol * constant) < constant
void test4(int x) {
int buf[100];
if (x > 99)
- buf[x] = 1;
+ buf[x] = 1; // expected-warning{{Out of bound memory access}}
+}
+
+void test_assume_after_access(unsigned long x) {
+ int buf[100];
+ buf[x] = 1;
+ clang_analyzer_eval(x <= 99); // expected-warning{{TRUE}}
}
// Don't warn when indexing below the start of a symbolic region's whose
@@ -166,3 +168,9 @@ void test_extern_void() {
p[1] = 42; // no-warning
}
+void test_assume_after_access2(unsigned long x) {
+ char buf[100];
+ buf[x] = 1;
+ clang_analyzer_eval(x <= 99); // expected-warning{{TRUE}}
+}
+
diff --git a/test/Analysis/padding_message.cpp b/test/Analysis/padding_message.cpp
index f73a11af4e7d..bbfa45394d85 100644
--- a/test/Analysis/padding_message.cpp
+++ b/test/Analysis/padding_message.cpp
@@ -1,13 +1,25 @@
// RUN: %clang_cc1 -triple x86_64-unknown-linux -std=c++14 -analyze -analyzer-checker=optin.performance -analyzer-config optin.performance.Padding:AllowedPad=2 -verify %s
-// expected-warning@+1{{Excessive padding in 'struct IntSandwich' (6 padding bytes, where 2 is optimal)}}
+// expected-warning@+7{{\
+Excessive padding in 'struct IntSandwich' (6 padding bytes, where 2 is optimal). \
+Optimal fields order: \
+i, \
+c1, \
+c2, \
+}}
struct IntSandwich {
char c1;
int i;
char c2;
};
-// expected-warning@+1{{Excessive padding in 'struct TurDuckHen' (6 padding bytes, where 2 is optimal)}}
+// expected-warning@+7{{\
+Excessive padding in 'struct TurDuckHen' (6 padding bytes, where 2 is optimal). \
+Optimal fields order: \
+i, \
+c1, \
+c2, \
+}}
struct TurDuckHen {
char c1;
struct IntSandwich i;
@@ -16,7 +28,17 @@ struct TurDuckHen {
#pragma pack(push)
#pragma pack(2)
-// expected-warning@+1{{Excessive padding in 'struct SmallIntSandwich' (4 padding bytes, where 0 is optimal)}}
+// expected-warning@+11{{\
+Excessive padding in 'struct SmallIntSandwich' (4 padding bytes, where 0 is optimal). \
+Optimal fields order: \
+i1, \
+i2, \
+i3, \
+c1, \
+c2, \
+c3, \
+c4, \
+}}
struct SmallIntSandwich {
char c1;
int i1;
@@ -34,7 +56,13 @@ union SomeUnion { // no-warning
int i;
};
-// expected-warning@+1{{Excessive padding in 'struct HoldsAUnion' (6 padding bytes, where 2 is optimal)}}
+// expected-warning@+7{{\
+Excessive padding in 'struct HoldsAUnion' (6 padding bytes, where 2 is optimal). \
+Optimal fields order: \
+u, \
+c1, \
+c2, \
+}}
struct HoldsAUnion {
char c1;
union SomeUnion u;
@@ -49,28 +77,53 @@ struct MediumIntArray { // no-warning
int i[5];
};
-// expected-warning@+1{{Excessive padding in 'struct StructSandwich' (6 padding bytes, where 2 is optimal)}}
+// expected-warning@+7{{\
+Excessive padding in 'struct StructSandwich' (6 padding bytes, where 2 is optimal). \
+Optimal fields order: \
+m, \
+s, \
+s2, \
+}}
struct StructSandwich {
struct SmallCharArray s;
struct MediumIntArray m;
struct SmallCharArray s2;
};
-// expected-warning@+1{{Excessive padding in 'TypedefSandwich' (6 padding bytes, where 2 is optimal)}}
+// expected-warning@+7{{\
+Excessive padding in 'TypedefSandwich' (6 padding bytes, where 2 is optimal). \
+Optimal fields order: \
+i, \
+c1, \
+c2, \
+}}
typedef struct {
char c1;
int i;
char c2;
} TypedefSandwich;
-// expected-warning@+1{{Excessive padding in 'struct StructAttrAlign' (10 padding bytes, where 2 is optimal)}}
+// expected-warning@+7{{\
+Excessive padding in 'struct StructAttrAlign' (10 padding bytes, where 2 is optimal). \
+Optimal fields order: \
+i, \
+c1, \
+c2, \
+}}
struct StructAttrAlign {
char c1;
int i;
char c2;
} __attribute__((aligned(8)));
-// expected-warning@+1{{Excessive padding in 'struct OverlyAlignedChar' (8185 padding bytes, where 4089 is optimal)}}
+// expected-warning@+8{{\
+Excessive padding in 'struct OverlyAlignedChar' (8185 padding bytes, where 4089 is optimal). \
+Optimal fields order: \
+c, \
+c1, \
+c2, \
+x, \
+}}
struct OverlyAlignedChar {
char c1;
int x;
@@ -78,7 +131,13 @@ struct OverlyAlignedChar {
char c __attribute__((aligned(4096)));
};
-// expected-warning@+1{{Excessive padding in 'struct HoldsOverlyAlignedChar' (8190 padding bytes, where 4094 is optimal)}}
+// expected-warning@+7{{\
+Excessive padding in 'struct HoldsOverlyAlignedChar' (8190 padding bytes, where 4094 is optimal). \
+Optimal fields order: \
+o, \
+c1, \
+c2, \
+}}
struct HoldsOverlyAlignedChar {
char c1;
struct OverlyAlignedChar o;
@@ -86,7 +145,13 @@ struct HoldsOverlyAlignedChar {
};
void internalStructFunc() {
- // expected-warning@+1{{Excessive padding in 'struct X' (6 padding bytes, where 2 is optimal)}}
+ // expected-warning@+7{{\
+Excessive padding in 'struct X' (6 padding bytes, where 2 is optimal). \
+Optimal fields order: \
+t, \
+c1, \
+c2, \
+}}
struct X {
char c1;
int t;
@@ -96,7 +161,13 @@ void internalStructFunc() {
}
void typedefStructFunc() {
- // expected-warning@+1{{Excessive padding in 'S' (6 padding bytes, where 2 is optimal)}}
+ // expected-warning@+7{{\
+Excessive padding in 'S' (6 padding bytes, where 2 is optimal). \
+Optimal fields order: \
+t, \
+c1, \
+c2, \
+}}
typedef struct {
char c1;
int t;
@@ -105,21 +176,39 @@ void typedefStructFunc() {
S obj;
}
-// expected-warning@+1{{Excessive padding in 'struct DefaultAttrAlign' (22 padding bytes, where 6 is optimal)}}
+// expected-warning@+7{{\
+Excessive padding in 'struct DefaultAttrAlign' (22 padding bytes, where 6 is optimal). \
+Optimal fields order: \
+i, \
+c1, \
+c2, \
+}}
struct DefaultAttrAlign {
char c1;
long long i;
char c2;
} __attribute__((aligned));
-// expected-warning@+1{{Excessive padding in 'struct SmallArrayShortSandwich' (2 padding bytes, where 0 is optimal)}}
+// expected-warning@+7{{\
+Excessive padding in 'struct SmallArrayShortSandwich' (2 padding bytes, where 0 is optimal). \
+Optimal fields order: \
+s, \
+c1, \
+c2, \
+}}
struct SmallArrayShortSandwich {
char c1;
short s;
char c2;
} ShortArray[20];
-// expected-warning@+1{{Excessive padding in 'struct SmallArrayInFunc' (2 padding bytes, where 0 is optimal)}}
+// expected-warning@+7{{\
+Excessive padding in 'struct SmallArrayInFunc' (2 padding bytes, where 0 is optimal). \
+Optimal fields order: \
+s, \
+c1, \
+c2, \
+}}
struct SmallArrayInFunc {
char c1;
short s;
@@ -130,7 +219,13 @@ void arrayHolder() {
struct SmallArrayInFunc Arr[15];
}
-// expected-warning@+1{{Excessive padding in 'class VirtualIntSandwich' (10 padding bytes, where 2 is optimal)}}
+// expected-warning@+7{{\
+Excessive padding in 'class VirtualIntSandwich' (10 padding bytes, where 2 is optimal). \
+Optimal fields order: \
+i, \
+c1, \
+c2, \
+}}
class VirtualIntSandwich {
virtual void foo() {}
char c1;
@@ -139,7 +234,14 @@ class VirtualIntSandwich {
};
// constructed so as not to have tail padding
-// expected-warning@+1{{Excessive padding in 'class InnerPaddedB' (6 padding bytes, where 2 is optimal)}}
+// expected-warning@+8{{\
+Excessive padding in 'class InnerPaddedB' (6 padding bytes, where 2 is optimal). \
+Optimal fields order: \
+i1, \
+i2, \
+c1, \
+c2, \
+}}
class InnerPaddedB {
char c1;
int i1;
@@ -149,17 +251,35 @@ class InnerPaddedB {
class Empty {}; // no-warning
-// expected-warning@+1{{Excessive padding in 'class LotsOfSpace' (6 padding bytes, where 2 is optimal)}}
+// expected-warning@+7{{\
+Excessive padding in 'class LotsOfSpace' (6 padding bytes, where 2 is optimal). \
+Optimal fields order: \
+i, \
+e1, \
+e2, \
+}}
class LotsOfSpace {
Empty e1;
int i;
Empty e2;
};
-// expected-warning@+1{{Excessive padding in 'TypedefSandwich2' (6 padding bytes, where 2 is optimal)}}
+// expected-warning@+7{{\
+Excessive padding in 'TypedefSandwich2' (6 padding bytes, where 2 is optimal). \
+Optimal fields order: \
+t, \
+c1, \
+c2, \
+}}
typedef struct {
char c1;
- // expected-warning@+1{{Excessive padding in 'TypedefSandwich2::NestedTypedef' (6 padding bytes, where 2 is optimal)}}
+ // expected-warning@+7{{\
+Excessive padding in 'TypedefSandwich2::NestedTypedef' (6 padding bytes, where 2 is optimal). \
+Optimal fields order: \
+i, \
+c1, \
+c2, \
+}}
typedef struct {
char c1;
int i;
@@ -171,7 +291,13 @@ typedef struct {
template <typename T>
struct Foo {
- // expected-warning@+1{{Excessive padding in 'struct Foo<int>::Nested' (6 padding bytes, where 2 is optimal)}}
+ // expected-warning@+7{{\
+Excessive padding in 'struct Foo<int>::Nested' (6 padding bytes, where 2 is optimal). \
+Optimal fields order: \
+t, \
+c1, \
+c2, \
+}}
struct Nested {
char c1;
T t;
diff --git a/test/Analysis/plist-html-macros.c b/test/Analysis/plist-html-macros.c
index 954aab099725..dbdbb30c4b2f 100644
--- a/test/Analysis/plist-html-macros.c
+++ b/test/Analysis/plist-html-macros.c
@@ -1,12 +1,11 @@
-// REQUIRES: shell
// RUN: %clang_cc1 -analyze -analyzer-checker=core -verify %s
// (sanity check)
// RUN: rm -rf %t.dir
// RUN: mkdir -p %t.dir
// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-output=plist-html -o %t.dir/index.plist %s
-// RUN: ls %t.dir | grep \\.html | count 1
-// RUN: grep \\.html %t.dir/index.plist | count 1
+// RUN: ls %t.dir | grep '\.html' | count 1
+// RUN: grep '\.html' %t.dir/index.plist | count 1
// This tests two things: that the two calls to null_deref below are coalesced
// into a single bug by both the plist and HTML diagnostics, and that the plist
diff --git a/test/Analysis/plist-output-alternate.m b/test/Analysis/plist-output-alternate.m
index 164f1c5991a2..7c8e51385777 100644
--- a/test/Analysis/plist-output-alternate.m
+++ b/test/Analysis/plist-output-alternate.m
@@ -1191,9 +1191,9 @@ void rdar8331641(int x) {
// CHECK-NEXT: </array>
// CHECK-NEXT: <key>depth</key><integer>0</integer>
// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFNumberCreate&apos; returns a Core Foundation object with a +1 retain count</string>
+// CHECK-NEXT: <string>Call to function &apos;CFNumberCreate&apos; returns a Core Foundation object of type CFNumberRef with a +1 retain count</string>
// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFNumberCreate&apos; returns a Core Foundation object with a +1 retain count</string>
+// CHECK-NEXT: <string>Call to function &apos;CFNumberCreate&apos; returns a Core Foundation object of type CFNumberRef with a +1 retain count</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>control</string>
diff --git a/test/Analysis/plist-output.m b/test/Analysis/plist-output.m
index f885c72ad4ff..affbb5d14d9c 100644
--- a/test/Analysis/plist-output.m
+++ b/test/Analysis/plist-output.m
@@ -1834,6 +1834,69 @@ int testFoo(Foo *x) {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>75</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>75</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>75</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>75</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>75</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>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>75</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>75</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>76</integer>
// CHECK-NEXT: <key>col</key><integer>5</integer>
// CHECK-NEXT: <key>file</key><integer>0</integer>
@@ -2041,6 +2104,69 @@ int testFoo(Foo *x) {
// CHECK-NEXT: <key>end</key>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>85</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>85</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>
+// CHECK-NEXT: <key>line</key><integer>85</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>85</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>85</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>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>85</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>85</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: <key>end</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>
diff --git a/test/Analysis/pointer-to-member.cpp b/test/Analysis/pointer-to-member.cpp
index 37d04399b7b7..eef20627a132 100644
--- a/test/Analysis/pointer-to-member.cpp
+++ b/test/Analysis/pointer-to-member.cpp
@@ -35,8 +35,7 @@ void testComparison() {
clang_analyzer_eval(&A::getPtr == &A::getPtr); // expected-warning{{TRUE}}
clang_analyzer_eval(&A::getPtr == 0); // expected-warning{{FALSE}}
- // FIXME: Should be TRUE.
- clang_analyzer_eval(&A::m_ptr == &A::m_ptr); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(&A::m_ptr == &A::m_ptr); // expected-warning{{TRUE}}
}
namespace PR15742 {
@@ -62,21 +61,156 @@ namespace PR15742 {
}
}
-// ---------------
-// FALSE NEGATIVES
-// ---------------
-
bool testDereferencing() {
A obj;
obj.m_ptr = 0;
A::MemberPointer member = &A::m_ptr;
- // FIXME: Should be TRUE.
- clang_analyzer_eval(obj.*member == 0); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(obj.*member == 0); // expected-warning{{TRUE}}
member = 0;
- // FIXME: Should emit a null dereference.
- return obj.*member; // no-warning
+ return obj.*member; // expected-warning{{The result of the '.*' expression is undefined}}
+}
+
+namespace testPointerToMemberFunction {
+ struct A {
+ virtual int foo() { return 1; }
+ int bar() { return 2; }
+ };
+
+ struct B : public A {
+ virtual int foo() { return 3; }
+ };
+
+ typedef int (A::*AFnPointer)();
+ typedef int (B::*BFnPointer)();
+
+ void testPointerToMemberCasts() {
+ AFnPointer AFP = &A::bar;
+ BFnPointer StaticCastedBase2Derived = static_cast<BFnPointer>(&A::bar),
+ CCastedBase2Derived = (BFnPointer) (&A::bar);
+ A a;
+ B b;
+
+ clang_analyzer_eval((a.*AFP)() == 2); // expected-warning{{TRUE}}
+ clang_analyzer_eval((b.*StaticCastedBase2Derived)() == 2); // expected-warning{{TRUE}}
+ clang_analyzer_eval(((b.*CCastedBase2Derived)() == 2)); // expected-warning{{TRUE}}
+ }
+
+ void testPointerToMemberVirtualCall() {
+ A a;
+ B b;
+ A *APtr = &a;
+ AFnPointer AFP = &A::foo;
+
+ clang_analyzer_eval((APtr->*AFP)() == 1); // expected-warning{{TRUE}}
+
+ APtr = &b;
+
+ clang_analyzer_eval((APtr->*AFP)() == 3); // expected-warning{{TRUE}}
+ }
+} // end of testPointerToMemberFunction namespace
+
+namespace testPointerToMemberData {
+ struct A {
+ int i;
+ };
+
+ void testPointerToMemberData() {
+ int A::*AMdPointer = &A::i;
+ A a;
+
+ a.i = 42;
+ a.*AMdPointer += 1;
+
+ clang_analyzer_eval(a.i == 43); // expected-warning{{TRUE}}
+ }
+} // end of testPointerToMemberData namespace
+
+namespace testPointerToMemberMiscCasts {
+struct B {
+ int f;
+};
+
+struct D : public B {
+ int g;
+};
+
+void foo() {
+ D d;
+ d.f = 7;
+
+ int B::* pfb = &B::f;
+ int D::* pfd = pfb;
+ int v = d.*pfd;
+
+ clang_analyzer_eval(v == 7); // expected-warning{{TRUE}}
+}
+} // end of testPointerToMemberMiscCasts namespace
+
+namespace testPointerToMemberMiscCasts2 {
+struct B {
+ int f;
+};
+struct L : public B { };
+struct R : public B { };
+struct D : public L, R { };
+
+void foo() {
+ D d;
+
+ int B::* pb = &B::f;
+ int L::* pl = pb;
+ int R::* pr = pb;
+
+ int D::* pdl = pl;
+ int D::* pdr = pr;
+
+ clang_analyzer_eval(pdl == pdr); // expected-warning{{FALSE}}
+ clang_analyzer_eval(pb == pl); // expected-warning{{TRUE}}
+}
+} // end of testPointerToMemberMiscCasts2 namespace
+
+namespace testPointerToMemberDiamond {
+struct B {
+ int f;
+};
+struct L1 : public B { };
+struct R1 : public B { };
+struct M : public L1, R1 { };
+struct L2 : public M { };
+struct R2 : public M { };
+struct D2 : public L2, R2 { };
+
+void diamond() {
+ M m;
+
+ static_cast<L1 *>(&m)->f = 7;
+ static_cast<R1 *>(&m)->f = 16;
+
+ int L1::* pl1 = &B::f;
+ int M::* pm_via_l1 = pl1;
+
+ int R1::* pr1 = &B::f;
+ int M::* pm_via_r1 = pr1;
+
+ clang_analyzer_eval(m.*(pm_via_l1) == 7); // expected-warning {{TRUE}}
+ clang_analyzer_eval(m.*(pm_via_r1) == 16); // expected-warning {{TRUE}}
+}
+
+void double_diamond() {
+ D2 d2;
+
+ static_cast<L1 *>(static_cast<L2 *>(&d2))->f = 1;
+ static_cast<L1 *>(static_cast<R2 *>(&d2))->f = 2;
+ static_cast<R1 *>(static_cast<L2 *>(&d2))->f = 3;
+ static_cast<R1 *>(static_cast<R2 *>(&d2))->f = 4;
+
+ clang_analyzer_eval(d2.*(static_cast<int D2::*>(static_cast<int L2::*>(static_cast<int L1::*>(&B::f)))) == 1); // expected-warning {{TRUE}}
+ clang_analyzer_eval(d2.*(static_cast<int D2::*>(static_cast<int R2::*>(static_cast<int L1::*>(&B::f)))) == 2); // expected-warning {{TRUE}}
+ clang_analyzer_eval(d2.*(static_cast<int D2::*>(static_cast<int L2::*>(static_cast<int R1::*>(&B::f)))) == 3); // expected-warning {{TRUE}}
+ clang_analyzer_eval(d2.*(static_cast<int D2::*>(static_cast<int R2::*>(static_cast<int R1::*>(&B::f)))) == 4); // expected-warning {{TRUE}}
}
+} // end of testPointerToMemberDiamond namespace
diff --git a/test/Analysis/qt_malloc.cpp b/test/Analysis/qt_malloc.cpp
index d29835f73faa..200556ea306d 100644
--- a/test/Analysis/qt_malloc.cpp
+++ b/test/Analysis/qt_malloc.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.deadcode.UnreachableCode,alpha.core.CastSize,unix.Malloc,cplusplus -analyzer-store=region -verify %s
+// RUN: %clang_cc1 -std=c++11 -analyze -analyzer-checker=core,alpha.deadcode.UnreachableCode,alpha.core.CastSize,unix.Malloc,cplusplus -analyzer-store=region -verify %s
// expected-no-diagnostics
#include "Inputs/qt-simulator.h"
@@ -13,3 +13,9 @@ void send(QObject *obj)
QEvent *e4 = new QEvent(QEvent::None);
QApplication::postEvent(obj, e4);
}
+
+void connect(QObject *obj) {
+ obj->connectImpl(nullptr, nullptr, nullptr, nullptr,
+ new QtPrivate::QSlotObjectBase(), (Qt::ConnectionType)0,
+ nullptr, nullptr);
+}
diff --git a/test/Analysis/rdar-6562655.m b/test/Analysis/rdar-6562655.m
index 1c866bb03732..9591f551f3d9 100644
--- a/test/Analysis/rdar-6562655.m
+++ b/test/Analysis/rdar-6562655.m
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount,alpha.core -analyzer-constraints=range -analyzer-store=region -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount,alpha.core -analyzer-store=region -verify %s
// expected-no-diagnostics
//
// This test case mainly checks that the retain/release checker doesn't crash
diff --git a/test/Analysis/rdar-6600344-nil-receiver-undefined-struct-ret.m b/test/Analysis/rdar-6600344-nil-receiver-undefined-struct-ret.m
index 74d5484fae8b..e9809db50119 100644
--- a/test/Analysis/rdar-6600344-nil-receiver-undefined-struct-ret.m
+++ b/test/Analysis/rdar-6600344-nil-receiver-undefined-struct-ret.m
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core -analyzer-constraints=range -analyzer-store=region -verify -Wno-objc-root-class %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core -analyzer-store=region -verify -Wno-objc-root-class %s
// expected-no-diagnostics
typedef struct Foo { int x; } Bar;
diff --git a/test/Analysis/reference.cpp b/test/Analysis/reference.cpp
index cd0202ebcb35..951079d43e47 100644
--- a/test/Analysis/reference.cpp
+++ b/test/Analysis/reference.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -analyzer-store=region -analyzer-constraints=range -verify -Wno-null-dereference -Wno-tautological-undefined-compare %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -analyzer-store=region -verify -Wno-null-dereference -Wno-tautological-undefined-compare %s
void clang_analyzer_eval(bool);
diff --git a/test/Analysis/retain-release-arc.m b/test/Analysis/retain-release-arc.m
new file mode 100644
index 000000000000..6f3cbfbe5a9f
--- /dev/null
+++ b/test/Analysis/retain-release-arc.m
@@ -0,0 +1,166 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.ClassRelease,osx.cocoa.RetainCount -fobjc-arc -fblocks -verify -Wno-objc-root-class %s -analyzer-output=text
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.ClassRelease,osx.cocoa.RetainCount -fblocks -verify -Wno-objc-root-class %s -analyzer-output=text
+
+typedef __typeof(sizeof(int)) size_t;
+
+#define HAS_ARC __has_feature(objc_arc)
+
+typedef unsigned long long CFOptionFlags;
+typedef signed long long CFIndex;
+
+typedef CFIndex CFPropertyListFormat; enum {
+ kCFPropertyListOpenStepFormat = 1,
+ kCFPropertyListXMLFormat_v1_0 = 100,
+ kCFPropertyListBinaryFormat_v1_0 = 200
+};
+
+typedef const struct __CFAllocator * CFAllocatorRef;
+extern const CFAllocatorRef kCFAllocatorDefault;
+typedef struct __CFDictionary * CFDictionaryRef;
+typedef struct __CFError * CFErrorRef;
+typedef struct __CFDataRef * CFDataRef;
+typedef void * CFPropertyListRef;
+
+CFPropertyListRef CFPropertyListCreateWithData(CFAllocatorRef allocator, CFDataRef data, CFOptionFlags options, CFPropertyListFormat *format, CFErrorRef *error);
+
+typedef signed char BOOL;
+typedef struct _NSZone NSZone;
+@class NSDictionary;
+@class NSData;
+@class NSString;
+
+@protocol NSObject
+- (BOOL)isEqual:(id)object;
+- (id)retain;
+- (oneway void)release;
+- (id)autorelease;
+- (NSString *)description;
+- (id)init;
+@end
+@interface NSObject <NSObject> {}
++ (id)allocWithZone:(NSZone *)zone;
++ (id)alloc;
++ (id)new;
+- (void)dealloc;
+@end
+
+@interface NSDictionary : NSObject
+@end
+
+#define OS_OBJECT_RETURNS_RETAINED __attribute__((__ns_returns_retained__))
+#define DISPATCH_RETURNS_RETAINED OS_OBJECT_RETURNS_RETAINED
+
+@protocol OS_dispatch_object
+@end
+@protocol OS_dispatch_data <OS_dispatch_object>
+@end
+@protocol OS_dispatch_queue <OS_dispatch_object>
+@end
+
+typedef NSObject<OS_dispatch_object> *dispatch_object_t;
+typedef NSObject<OS_dispatch_data> *dispatch_data_t;
+typedef NSObject<OS_dispatch_queue> *dispatch_queue_t;
+
+typedef void (^dispatch_block_t)(void);
+
+dispatch_queue_t dispatch_get_main_queue(void);
+
+DISPATCH_RETURNS_RETAINED dispatch_data_t
+dispatch_data_create(const void *buffer, size_t size,
+ dispatch_queue_t _Nullable queue,
+ dispatch_block_t _Nullable destructor);
+
+void _dispatch_object_validate(dispatch_object_t object);
+
+#define dispatch_retain(object) \
+ __extension__({ dispatch_object_t _o = (object); \
+ _dispatch_object_validate(_o); \
+ (void)[_o retain]; })
+#define dispatch_release(object) \
+ __extension__({ dispatch_object_t _o = (object); \
+ _dispatch_object_validate(_o); \
+ [_o release]; })
+
+
+@interface SomeClass
+@end
+
+@implementation SomeClass
+- (NSDictionary *)copyTestWithBridgeReturningRetainable:(NSData *)plistData {
+ CFErrorRef error;
+ CFDictionaryRef testDict = CFPropertyListCreateWithData(kCFAllocatorDefault, (__bridge CFDataRef)plistData, 0, 0, &error);
+#if HAS_ARC
+ // expected-note@-2 {{Call to function 'CFPropertyListCreateWithData' returns a Core Foundation object of type CFPropertyListRef with a +1 retain count}}
+#endif
+ return (__bridge NSDictionary *)testDict;
+#if HAS_ARC
+ // expected-warning@-2 {{Potential leak of an object stored into 'testDict'}}
+ // expected-note@-3 {{Object returned to caller as an owning reference (single retain count transferred to caller)}}
+ // expected-note@-4 {{Object leaked: object allocated and stored into 'testDict' is returned from a method managed by Automatic Reference Counting}}
+#endif
+}
+
+- (NSDictionary *)copyTestWithoutBridgeReturningRetainable:(NSData *)plistData {
+ NSDictionary *testDict = [[NSDictionary alloc] init];
+ return testDict; // no-warning
+}
+
+- (NSDictionary *)copyTestWithBridgeTransferReturningRetainable:(NSData *)plistData {
+ CFErrorRef error;
+ CFDictionaryRef testDict = CFPropertyListCreateWithData(kCFAllocatorDefault, (__bridge CFDataRef)plistData, 0, 0, &error);
+ return (__bridge_transfer NSDictionary *)testDict; // no-warning under ARC
+#if !HAS_ARC
+ // expected-warning@-2 {{'__bridge_transfer' casts have no effect when not using ARC}} // Warning from Sema
+#endif
+}
+
+- (CFDictionaryRef)copyTestReturningCoreFoundation:(NSData *)plistData {
+ CFErrorRef error;
+ CFDictionaryRef testDict = CFPropertyListCreateWithData(kCFAllocatorDefault, (__bridge CFDataRef)plistData, 0, 0, &error);
+ return testDict;
+}
+@end
+
+int buf[1024];
+
+void libdispatch_leaked_data() {
+ dispatch_data_t data = dispatch_data_create(buf, 1024,
+ dispatch_get_main_queue(), ^{});
+}
+#if !HAS_ARC
+ // expected-warning@-2{{Potential leak of an object stored into 'data'}}
+ // expected-note@-5{{Call to function 'dispatch_data_create' returns an Objective-C object with a +1 retain count}}
+ // expected-note@-4{{Object leaked: object allocated and stored into 'data' is not referenced later in this execution path and has a retain count of +1}}
+#endif
+
+void libdispatch_dispatch_released_data() {
+ dispatch_data_t data = dispatch_data_create(buf, 1024,
+ dispatch_get_main_queue(), ^{});
+#if !HAS_ARC
+ dispatch_release(data); // no-warning
+#endif
+}
+
+void libdispatch_objc_released_data() {
+ dispatch_data_t data = dispatch_data_create(buf, 1024,
+ dispatch_get_main_queue(), ^{});
+#if !HAS_ARC
+ [data release]; // no-warning
+#endif
+}
+
+void libdispatch_leaked_retained_data() {
+ dispatch_data_t data = dispatch_data_create(buf, 1024,
+ dispatch_get_main_queue(), ^{});
+#if !HAS_ARC
+ dispatch_retain(data);
+ [data release];
+#endif
+}
+#if !HAS_ARC
+// expected-warning@-2{{Potential leak of an object stored into 'data'}}
+// expected-note@-9{{Call to function 'dispatch_data_create' returns an Objective-C object with a +1 retain count}}
+// expected-note@-7{{Reference count incremented. The object now has a +2 retain count}}
+// expected-note@-7{{Reference count decremented. The object now has a +1 retain count}}
+// expected-note@-6{{Object leaked: object allocated and stored into 'data' is not referenced later in this execution path and has a retain count of +1}}
+#endif
diff --git a/test/Analysis/retain-release-path-notes-gc.m b/test/Analysis/retain-release-path-notes-gc.m
index 08e4151a71a8..5b5558215060 100644
--- a/test/Analysis/retain-release-path-notes-gc.m
+++ b/test/Analysis/retain-release-path-notes-gc.m
@@ -40,12 +40,12 @@ CFTypeRef CFGetSomething();
void creationViaCFCreate () {
- CFTypeRef leaked = CFCreateSomething(); // expected-note{{Call to function 'CFCreateSomething' returns a Core Foundation object with a +1 retain count. Core Foundation objects are not automatically garbage collected}}
+ CFTypeRef leaked = CFCreateSomething(); // expected-note{{Call to function 'CFCreateSomething' returns a Core Foundation object of type CFTypeRef with a +1 retain count. Core Foundation objects are not automatically garbage collected}}
return; // expected-warning{{leak}} expected-note{{Object leaked: object allocated and stored into 'leaked' is not referenced later in this execution path and has a retain count of +1}}
}
void makeCollectable () {
- CFTypeRef leaked = CFCreateSomething(); // expected-note{{Call to function 'CFCreateSomething' returns a Core Foundation object with a +1 retain count. Core Foundation objects are not automatically garbage collected}}
+ CFTypeRef leaked = CFCreateSomething(); // expected-note{{Call to function 'CFCreateSomething' returns a Core Foundation object of type CFTypeRef with a +1 retain count. Core Foundation objects are not automatically garbage collected}}
CFRetain(leaked); // expected-note{{Reference count incremented. The object now has a +2 retain count}}
CFMakeCollectable(leaked); // expected-note{{In GC mode a call to 'CFMakeCollectable' decrements an object's retain count and registers the object with the garbage collector. An object must have a 0 retain count to be garbage collected. After this call its retain count is +1}}
NSMakeCollectable(leaked); // expected-note{{In GC mode a call to 'NSMakeCollectable' decrements an object's retain count and registers the object with the garbage collector. Since it now has a 0 retain count the object can be automatically collected by the garbage collector}}
@@ -54,7 +54,7 @@ void makeCollectable () {
}
void retainReleaseIgnored () {
- id object = [[NSObject alloc] init]; // expected-note{{Method returns an Objective-C object with a +0 retain count}}
+ id object = [[NSObject alloc] init]; // expected-note{{Method returns an instance of NSObject with a +0 retain count}}
[object retain]; // expected-note{{In GC mode the 'retain' message has no effect}}
[object release]; // expected-note{{In GC mode the 'release' message has no effect}}
[object autorelease]; // expected-note{{In GC mode an 'autorelease' has no effect}}
@@ -63,12 +63,12 @@ void retainReleaseIgnored () {
@implementation Foo (FundamentalRuleUnderGC)
- (id)getViolation {
- id object = (id) CFCreateSomething(); // expected-note{{Call to function 'CFCreateSomething' returns a Core Foundation object with a +1 retain count. Core Foundation objects are not automatically garbage collected}}
+ id object = (id) CFCreateSomething(); // expected-note{{Call to function 'CFCreateSomething' returns a Core Foundation object of type CFTypeRef with a +1 retain count. Core Foundation objects are not automatically garbage collected}}
return object; // expected-warning{{leak}} expected-note{{Object returned to caller as an owning reference (single retain count transferred to caller)}} expected-note{{Object leaked: object allocated and stored into 'object' and returned from method 'getViolation' is potentially leaked when using garbage collection. Callers of this method do not expect a returned object with a +1 retain count since they expect the object to be managed by the garbage collector}}
}
- (id)copyViolation {
- id object = (id) CFCreateSomething(); // expected-note{{Call to function 'CFCreateSomething' returns a Core Foundation object with a +1 retain count. Core Foundation objects are not automatically garbage collected}}
+ id object = (id) CFCreateSomething(); // expected-note{{Call to function 'CFCreateSomething' returns a Core Foundation object of type CFTypeRef with a +1 retain count. Core Foundation objects are not automatically garbage collected}}
return object; // expected-warning{{leak}} expected-note{{Object returned to caller as an owning reference (single retain count transferred to caller)}} expected-note{{Object leaked: object allocated and stored into 'object' and returned from method 'copyViolation' is potentially leaked when using garbage collection. Callers of this method do not expect a returned object with a +1 retain count since they expect the object to be managed by the garbage collector}}
}
@end
@@ -137,9 +137,9 @@ void retainReleaseIgnored () {
// CHECK-NEXT: </array>
// CHECK-NEXT: <key>depth</key><integer>0</integer>
// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object with a +1 retain count. Core Foundation objects are not automatically garbage collected</string>
+// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type CFTypeRef with a +1 retain count. Core Foundation objects are not automatically garbage collected</string>
// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object with a +1 retain count. Core Foundation objects are not automatically garbage collected</string>
+// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type CFTypeRef with a +1 retain count. Core Foundation objects are not automatically garbage collected</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>control</string>
@@ -283,9 +283,9 @@ void retainReleaseIgnored () {
// CHECK-NEXT: </array>
// CHECK-NEXT: <key>depth</key><integer>0</integer>
// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object with a +1 retain count. Core Foundation objects are not automatically garbage collected</string>
+// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type CFTypeRef with a +1 retain count. Core Foundation objects are not automatically garbage collected</string>
// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object with a +1 retain count. Core Foundation objects are not automatically garbage collected</string>
+// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type CFTypeRef with a +1 retain count. Core Foundation objects are not automatically garbage collected</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>control</string>
@@ -729,9 +729,9 @@ void retainReleaseIgnored () {
// CHECK-NEXT: </array>
// CHECK-NEXT: <key>depth</key><integer>0</integer>
// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +0 retain count</string>
+// CHECK-NEXT: <string>Method returns an instance of NSObject with a +0 retain count</string>
// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +0 retain count</string>
+// CHECK-NEXT: <string>Method returns an instance of NSObject with a +0 retain count</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>control</string>
@@ -1100,9 +1100,9 @@ void retainReleaseIgnored () {
// CHECK-NEXT: </array>
// CHECK-NEXT: <key>depth</key><integer>0</integer>
// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object with a +1 retain count. Core Foundation objects are not automatically garbage collected</string>
+// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type CFTypeRef with a +1 retain count. Core Foundation objects are not automatically garbage collected</string>
// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object with a +1 retain count. Core Foundation objects are not automatically garbage collected</string>
+// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type CFTypeRef with a +1 retain count. Core Foundation objects are not automatically garbage collected</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>control</string>
@@ -1287,9 +1287,9 @@ void retainReleaseIgnored () {
// CHECK-NEXT: </array>
// CHECK-NEXT: <key>depth</key><integer>0</integer>
// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object with a +1 retain count. Core Foundation objects are not automatically garbage collected</string>
+// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type CFTypeRef with a +1 retain count. Core Foundation objects are not automatically garbage collected</string>
// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object with a +1 retain count. Core Foundation objects are not automatically garbage collected</string>
+// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type CFTypeRef with a +1 retain count. Core Foundation objects are not automatically garbage collected</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>control</string>
diff --git a/test/Analysis/retain-release-path-notes.m b/test/Analysis/retain-release-path-notes.m
index 51104fb81464..23347bc3aa73 100644
--- a/test/Analysis/retain-release-path-notes.m
+++ b/test/Analysis/retain-release-path-notes.m
@@ -44,12 +44,12 @@ CFTypeRef CFGetSomething();
void creationViaAlloc () {
- id leaked = [[NSObject alloc] init]; // expected-note{{Method returns an Objective-C object with a +1 retain count}}
+ id leaked = [[NSObject alloc] init]; // expected-note{{Method returns an instance of NSObject with a +1 retain count}}
return; // expected-warning{{leak}} expected-note{{Object leaked: object allocated and stored into 'leaked' is not referenced later in this execution path and has a retain count of +1}}
}
void creationViaCFCreate () {
- CFTypeRef leaked = CFCreateSomething(); // expected-note{{Call to function 'CFCreateSomething' returns a Core Foundation object with a +1 retain count}}
+ CFTypeRef leaked = CFCreateSomething(); // expected-note{{Call to function 'CFCreateSomething' returns a Core Foundation object of type CFTypeRef with a +1 retain count}}
return; // expected-warning{{leak}} expected-note{{Object leaked: object allocated and stored into 'leaked' is not referenced later in this execution path and has a retain count of +1}}
}
@@ -68,25 +68,25 @@ void acquisitionViaProperty (Foo *foo) {
}
void acquisitionViaCFFunction () {
- CFTypeRef leaked = CFGetSomething(); // expected-note{{Call to function 'CFGetSomething' returns a Core Foundation object with a +0 retain count}}
+ CFTypeRef leaked = CFGetSomething(); // expected-note{{Call to function 'CFGetSomething' returns a Core Foundation object of type CFTypeRef with a +0 retain count}}
CFRetain(leaked); // expected-note{{Reference count incremented. The object now has a +1 retain count}}
return; // expected-warning{{leak}} expected-note{{Object leaked: object allocated and stored into 'leaked' is not referenced later in this execution path and has a retain count of +1}}
}
void explicitDealloc () {
- id object = [[NSObject alloc] init]; // expected-note{{Method returns an Objective-C object with a +1 retain count}}
+ id object = [[NSObject alloc] init]; // expected-note{{Method returns an instance of NSObject with a +1 retain count}}
[object dealloc]; // expected-note{{Object released by directly sending the '-dealloc' message}}
[object class]; // expected-warning{{Reference-counted object is used after it is released}} // expected-note{{Reference-counted object is used after it is released}}
}
void implicitDealloc () {
- id object = [[NSObject alloc] init]; // expected-note{{Method returns an Objective-C object with a +1 retain count}}
+ id object = [[NSObject alloc] init]; // expected-note{{Method returns an instance of NSObject with a +1 retain count}}
[object release]; // expected-note{{Object released}}
[object class]; // expected-warning{{Reference-counted object is used after it is released}} // expected-note{{Reference-counted object is used after it is released}}
}
void overAutorelease () {
- id object = [[NSObject alloc] init]; // expected-note{{Method returns an Objective-C object with a +1 retain count}}
+ id object = [[NSObject alloc] init]; // expected-note{{Method returns an instance of NSObject with a +1 retain count}}
[object autorelease]; // expected-note{{Object autoreleased}}
[object autorelease]; // expected-note{{Object autoreleased}}
return; // expected-warning{{Object autoreleased too many times}} expected-note{{Object was autoreleased 2 times but the object has a +1 retain count}}
@@ -99,19 +99,19 @@ void autoreleaseUnowned (Foo *foo) {
}
void makeCollectableIgnored () {
- CFTypeRef leaked = CFCreateSomething(); // expected-note{{Call to function 'CFCreateSomething' returns a Core Foundation object with a +1 retain count}}
+ CFTypeRef leaked = CFCreateSomething(); // expected-note{{Call to function 'CFCreateSomething' returns a Core Foundation object of type CFTypeRef with a +1 retain count}}
CFMakeCollectable(leaked); // expected-note{{When GC is not enabled a call to 'CFMakeCollectable' has no effect on its argument}}
NSMakeCollectable(leaked); // expected-note{{When GC is not enabled a call to 'NSMakeCollectable' has no effect on its argument}}
return; // expected-warning{{leak}} expected-note{{Object leaked: object allocated and stored into 'leaked' is not referenced later in this execution path and has a retain count of +1}}
}
CFTypeRef CFCopyRuleViolation () {
- CFTypeRef object = CFGetSomething(); // expected-note{{Call to function 'CFGetSomething' returns a Core Foundation object with a +0 retain count}}
+ CFTypeRef object = CFGetSomething(); // expected-note{{Call to function 'CFGetSomething' returns a Core Foundation object of type CFTypeRef with a +0 retain count}}
return object; // expected-warning{{Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected}} expected-note{{Object returned to caller with a +0 retain count}} expected-note{{Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected}}
}
CFTypeRef CFGetRuleViolation () {
- CFTypeRef object = CFCreateSomething(); // expected-note{{Call to function 'CFCreateSomething' returns a Core Foundation object with a +1 retain count}}
+ CFTypeRef object = CFCreateSomething(); // expected-note{{Call to function 'CFCreateSomething' returns a Core Foundation object of type CFTypeRef with a +1 retain count}}
return object; // expected-warning{{leak}} expected-note{{Object returned to caller as an owning reference (single retain count transferred to caller)}} expected-note{{Object leaked: object allocated and stored into 'object' is returned from a function whose name ('CFGetRuleViolation') does not contain 'Copy' or 'Create'. This violates the naming convention rules given in the Memory Management Guide for Core Foundation}}
}
@@ -132,12 +132,12 @@ CFTypeRef CFGetRuleViolation () {
}
- (id)getViolation {
- id result = [[Foo alloc] init]; // expected-note{{Method returns an Objective-C object with a +1 retain count}}
+ id result = [[Foo alloc] init]; // expected-note{{Method returns an instance of Foo with a +1 retain count}}
return result; // expected-warning{{leak}} expected-note{{Object returned to caller as an owning reference (single retain count transferred to caller)}} expected-note{{Object leaked: object allocated and stored into 'result' is returned from a method whose name ('getViolation') does not start with 'copy', 'mutableCopy', 'alloc' or 'new'. This violates the naming convention rules given in the Memory Management Guide for Cocoa}}
}
- (id)copyAutorelease {
- id result = [[Foo alloc] init]; // expected-note{{Method returns an Objective-C object with a +1 retain count}}
+ id result = [[Foo alloc] init]; // expected-note{{Method returns an instance of Foo with a +1 retain count}}
[result autorelease]; // expected-note{{Object autoreleased}}
return result; // expected-warning{{Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected}} expected-note{{Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected}}
}
@@ -212,7 +212,7 @@ static int Cond;
}
-(id)initY {
- self = [super init]; //expected-note {{Method returns an Objective-C object with a +1 retain count}}
+ self = [super init]; //expected-note {{Method returns an instance of MyObj with a +1 retain count}}
return self;
}
@@ -224,7 +224,7 @@ static int Cond;
+(void)test {
// initX is inlined since we explicitely mark it as interesting
id x = [[MyObj alloc] initX]; // expected-warning {{Potential leak of an object}}
- // expected-note@-1 {{Method returns an Objective-C object with a +1 retain count}}
+ // expected-note@-1 {{Method returns an instance of MyObj with a +1 retain count}}
// expected-note@-2 {{Calling 'initX'}}
// expected-note@-3 {{Returning from 'initX'}}
// expected-note@-4 {{Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1}}
@@ -244,20 +244,20 @@ static int Cond;
void CFOverAutorelease() {
- CFTypeRef object = CFCreateSomething(); // expected-note{{Call to function 'CFCreateSomething' returns a Core Foundation object with a +1 retain count}}
+ CFTypeRef object = CFCreateSomething(); // expected-note{{Call to function 'CFCreateSomething' returns a Core Foundation object of type CFTypeRef with a +1 retain count}}
CFAutorelease(object); // expected-note{{Object autoreleased}}
CFAutorelease(object); // expected-note{{Object autoreleased}}
return; // expected-warning{{Object autoreleased too many times}} expected-note{{Object was autoreleased 2 times but the object has a +1 retain count}}
}
void CFAutoreleaseUnowned() {
- CFTypeRef object = CFGetSomething(); // expected-note{{Call to function 'CFGetSomething' returns a Core Foundation object with a +0 retain count}}
+ CFTypeRef object = CFGetSomething(); // expected-note{{Call to function 'CFGetSomething' returns a Core Foundation object of type CFTypeRef with a +0 retain count}}
CFAutorelease(object); // expected-note{{Object autoreleased}}
return; // expected-warning{{Object autoreleased too many times}} expected-note{{Object was autoreleased but has a +0 retain count}}
}
void CFAutoreleaseUnownedMixed() {
- CFTypeRef object = CFGetSomething(); // expected-note{{Call to function 'CFGetSomething' returns a Core Foundation object with a +0 retain count}}
+ CFTypeRef object = CFGetSomething(); // expected-note{{Call to function 'CFGetSomething' returns a Core Foundation object of type CFTypeRef with a +0 retain count}}
CFAutorelease(object); // expected-note{{Object autoreleased}}
[(id)object autorelease]; // expected-note{{Object autoreleased}}
return; // expected-warning{{Object autoreleased too many times}} expected-note{{Object was autoreleased 2 times but the object has a +0 retain count}}
@@ -393,9 +393,9 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: </array>
// CHECK-NEXT: <key>depth</key><integer>0</integer>
// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
+// CHECK-NEXT: <string>Method returns an instance of NSObject with a +1 retain count</string>
// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
+// 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>
@@ -539,9 +539,9 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: </array>
// CHECK-NEXT: <key>depth</key><integer>0</integer>
// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object with a +1 retain count</string>
+// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type CFTypeRef with a +1 retain count</string>
// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object with a +1 retain count</string>
+// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type CFTypeRef with a +1 retain count</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>control</string>
@@ -1277,9 +1277,9 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: </array>
// CHECK-NEXT: <key>depth</key><integer>0</integer>
// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFGetSomething&apos; returns a Core Foundation object with a +0 retain count</string>
+// CHECK-NEXT: <string>Call to function &apos;CFGetSomething&apos; returns a Core Foundation object of type CFTypeRef with a +0 retain count</string>
// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFGetSomething&apos; returns a Core Foundation object with a +0 retain count</string>
+// CHECK-NEXT: <string>Call to function &apos;CFGetSomething&apos; returns a Core Foundation object of type CFTypeRef with a +0 retain count</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>control</string>
@@ -1498,9 +1498,9 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: </array>
// CHECK-NEXT: <key>depth</key><integer>0</integer>
// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
+// CHECK-NEXT: <string>Method returns an instance of NSObject with a +1 retain count</string>
// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
+// 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>
@@ -1719,9 +1719,9 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: </array>
// CHECK-NEXT: <key>depth</key><integer>0</integer>
// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
+// CHECK-NEXT: <string>Method returns an instance of NSObject with a +1 retain count</string>
// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
+// 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>
@@ -1940,9 +1940,9 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: </array>
// CHECK-NEXT: <key>depth</key><integer>0</integer>
// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
+// CHECK-NEXT: <string>Method returns an instance of NSObject with a +1 retain count</string>
// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
+// 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>
@@ -2457,9 +2457,9 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: </array>
// CHECK-NEXT: <key>depth</key><integer>0</integer>
// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object with a +1 retain count</string>
+// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type CFTypeRef with a +1 retain count</string>
// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object with a +1 retain count</string>
+// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type CFTypeRef with a +1 retain count</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>control</string>
@@ -2753,9 +2753,9 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: </array>
// CHECK-NEXT: <key>depth</key><integer>0</integer>
// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFGetSomething&apos; returns a Core Foundation object with a +0 retain count</string>
+// CHECK-NEXT: <string>Call to function &apos;CFGetSomething&apos; returns a Core Foundation object of type CFTypeRef with a +0 retain count</string>
// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFGetSomething&apos; returns a Core Foundation object with a +0 retain count</string>
+// CHECK-NEXT: <string>Call to function &apos;CFGetSomething&apos; returns a Core Foundation object of type CFTypeRef with a +0 retain count</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>control</string>
@@ -2940,9 +2940,9 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: </array>
// CHECK-NEXT: <key>depth</key><integer>0</integer>
// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object with a +1 retain count</string>
+// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type CFTypeRef with a +1 retain count</string>
// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object with a +1 retain count</string>
+// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type CFTypeRef with a +1 retain count</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>control</string>
@@ -3688,9 +3688,9 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: </array>
// CHECK-NEXT: <key>depth</key><integer>0</integer>
// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
+// CHECK-NEXT: <string>Method returns an instance of Foo with a +1 retain count</string>
// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
+// CHECK-NEXT: <string>Method returns an instance of Foo with a +1 retain count</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>control</string>
@@ -3875,9 +3875,9 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: </array>
// CHECK-NEXT: <key>depth</key><integer>0</integer>
// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
+// CHECK-NEXT: <string>Method returns an instance of Foo with a +1 retain count</string>
// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
+// CHECK-NEXT: <string>Method returns an instance of Foo with a +1 retain count</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>control</string>
@@ -4826,9 +4826,9 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: </array>
// CHECK-NEXT: <key>depth</key><integer>0</integer>
// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
+// 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 Objective-C object with a +1 retain count</string>
+// 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>
@@ -5354,9 +5354,9 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: </array>
// CHECK-NEXT: <key>depth</key><integer>1</integer>
// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Method returns an Objective-C object with a +1 retain count</string>
+// 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 Objective-C object with a +1 retain count</string>
+// 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>
@@ -5563,9 +5563,9 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: </array>
// CHECK-NEXT: <key>depth</key><integer>0</integer>
// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object with a +1 retain count</string>
+// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type CFTypeRef with a +1 retain count</string>
// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object with a +1 retain count</string>
+// CHECK-NEXT: <string>Call to function &apos;CFCreateSomething&apos; returns a Core Foundation object of type CFTypeRef with a +1 retain count</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>control</string>
@@ -5859,9 +5859,9 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: </array>
// CHECK-NEXT: <key>depth</key><integer>0</integer>
// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFGetSomething&apos; returns a Core Foundation object with a +0 retain count</string>
+// CHECK-NEXT: <string>Call to function &apos;CFGetSomething&apos; returns a Core Foundation object of type CFTypeRef with a +0 retain count</string>
// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFGetSomething&apos; returns a Core Foundation object with a +0 retain count</string>
+// CHECK-NEXT: <string>Call to function &apos;CFGetSomething&apos; returns a Core Foundation object of type CFTypeRef with a +0 retain count</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>control</string>
@@ -6080,9 +6080,9 @@ void CFAutoreleaseUnownedMixed() {
// CHECK-NEXT: </array>
// CHECK-NEXT: <key>depth</key><integer>0</integer>
// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFGetSomething&apos; returns a Core Foundation object with a +0 retain count</string>
+// CHECK-NEXT: <string>Call to function &apos;CFGetSomething&apos; returns a Core Foundation object of type CFTypeRef with a +0 retain count</string>
// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to function &apos;CFGetSomething&apos; returns a Core Foundation object with a +0 retain count</string>
+// CHECK-NEXT: <string>Call to function &apos;CFGetSomething&apos; returns a Core Foundation object of type CFTypeRef with a +0 retain count</string>
// CHECK-NEXT: </dict>
// CHECK-NEXT: <dict>
// CHECK-NEXT: <key>kind</key><string>control</string>
diff --git a/test/Analysis/retain-release.m b/test/Analysis/retain-release.m
index f0d91e34c1b0..b883a86602ba 100644
--- a/test/Analysis/retain-release.m
+++ b/test/Analysis/retain-release.m
@@ -1247,6 +1247,108 @@ CVReturn rdar_7283567_2(CFAllocatorRef allocator, size_t width, size_t height,
pixelBufferAttributes, pixelBufferOut) ;
}
+#pragma clang arc_cf_code_audited begin
+typedef struct SomeOpaqueStruct *CMSampleBufferRef;
+CVImageBufferRef _Nonnull CMSampleBufferGetImageBuffer(CMSampleBufferRef _Nonnull sbuf);
+#pragma clang arc_cf_code_audited end
+
+CVBufferRef _Nullable CVBufferRetain(CVBufferRef _Nullable buffer);
+void CVBufferRelease(CF_CONSUMED CVBufferRef _Nullable buffer);
+
+void testCVPrefixRetain(CMSampleBufferRef sbuf) {
+ // Make sure RetainCountChecker treats CVFooRetain() as a CF-style retain.
+ CVPixelBufferRef pixelBuf = CMSampleBufferGetImageBuffer(sbuf);
+ CVBufferRetain(pixelBuf);
+ CVBufferRelease(pixelBuf); // no-warning
+
+
+ // Make sure result of CVFooRetain() is the same as its argument.
+ CVPixelBufferRef pixelBufAlias = CVBufferRetain(pixelBuf);
+ CVBufferRelease(pixelBufAlias); // no-warning
+}
+
+typedef signed long SInt32;
+typedef SInt32 OSStatus;
+typedef FourCharCode CMVideoCodecType;
+
+
+typedef UInt32 VTEncodeInfoFlags; enum {
+ kVTEncodeInfo_Asynchronous = 1UL << 0,
+ kVTEncodeInfo_FrameDropped = 1UL << 1,
+};
+typedef struct
+{
+ int ignore;
+} CMTime;
+
+
+typedef void (*VTCompressionOutputCallback)(
+ void * _Nullable outputCallbackRefCon,
+ void * _Nullable sourceFrameRefCon,
+ OSStatus status,
+ VTEncodeInfoFlags infoFlags,
+ _Nullable CMSampleBufferRef sampleBuffer );
+
+typedef struct OpaqueVTCompressionSession* VTCompressionSessionRef;
+
+extern OSStatus
+VTCompressionSessionCreate(_Nullable CFAllocatorRef allocator,
+ int32_t width,
+ int32_t height,
+ CMVideoCodecType codecType,
+ _Nullable CFDictionaryRef encoderSpecification,
+ _Nullable CFDictionaryRef sourceImageBufferAttributes,
+ _Nullable CFAllocatorRef compressedDataAllocator,
+ _Nullable VTCompressionOutputCallback outputCallback,
+ void * _Nullable outputCallbackRefCon,
+ CF_RETURNS_RETAINED _Nullable VTCompressionSessionRef * _Nonnull compressionSessionOut);
+
+extern OSStatus
+VTCompressionSessionEncodeFrame(
+ _Nonnull VTCompressionSessionRef session,
+ _Nonnull CVImageBufferRef imageBuffer,
+ CMTime presentationTimeStamp,
+ CMTime duration,
+ _Nullable CFDictionaryRef frameProperties,
+ void * _Nullable sourceFrameRefCon,
+ VTEncodeInfoFlags * _Nullable infoFlagsOut);
+
+OSStatus test_VTCompressionSessionCreateAndEncode_CallbackReleases(
+ _Nullable CFAllocatorRef allocator,
+ int32_t width,
+ int32_t height,
+ CMVideoCodecType codecType,
+ _Nullable CFDictionaryRef encoderSpecification,
+ _Nullable CFDictionaryRef sourceImageBufferAttributes,
+ _Nullable CFAllocatorRef compressedDataAllocator,
+ _Nullable VTCompressionOutputCallback outputCallback,
+
+ _Nonnull CVImageBufferRef imageBuffer,
+ CMTime presentationTimeStamp,
+ CMTime duration,
+ _Nullable CFDictionaryRef frameProperties
+) {
+
+ // The outputCallback is passed both contexts and so can release either.
+ NSNumber *contextForCreate = [[NSNumber alloc] initWithInt:5]; // no-warning
+ NSNumber *contextForEncode = [[NSNumber alloc] initWithInt:6]; // no-warning
+
+ VTCompressionSessionRef session = 0;
+ OSStatus status = VTCompressionSessionCreate(allocator,
+ width, height, codecType, encoderSpecification,
+ sourceImageBufferAttributes,
+ compressedDataAllocator, outputCallback, contextForCreate,
+ &session);
+
+ VTEncodeInfoFlags encodeInfoFlags;
+
+ status = VTCompressionSessionEncodeFrame(session, imageBuffer,
+ presentationTimeStamp, duration, frameProperties, contextForEncode,
+ &encodeInfoFlags);
+
+ return status;
+}
+
//===----------------------------------------------------------------------===//
// <rdar://problem/7358899> False leak associated with
// CGBitmapContextCreateWithData
diff --git a/test/Analysis/self-assign.cpp b/test/Analysis/self-assign.cpp
new file mode 100644
index 000000000000..74fb0fea2476
--- /dev/null
+++ b/test/Analysis/self-assign.cpp
@@ -0,0 +1,89 @@
+// RUN: %clang_cc1 -std=c++11 -analyze -analyzer-checker=core,cplusplus,unix.Malloc,debug.ExprInspection %s -verify -analyzer-output=text
+
+extern "C" char *strdup(const char* s);
+extern "C" void free(void* ptr);
+
+namespace std {
+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);
+}
+
+void clang_analyzer_eval(int);
+
+class StringUsed {
+public:
+ StringUsed(const char *s = "") : str(strdup(s)) {}
+ StringUsed(const StringUsed &rhs) : str(strdup(rhs.str)) {}
+ ~StringUsed();
+ StringUsed& operator=(const StringUsed &rhs);
+ StringUsed& operator=(StringUsed &&rhs);
+ operator const char*() const;
+private:
+ char *str;
+};
+
+StringUsed::~StringUsed() {
+ free(str);
+}
+
+StringUsed& StringUsed::operator=(const StringUsed &rhs) { // expected-note{{Assuming rhs == *this}} expected-note{{Assuming rhs == *this}} expected-note{{Assuming rhs != *this}}
+ clang_analyzer_eval(*this == rhs); // expected-warning{{TRUE}} expected-warning{{UNKNOWN}} expected-note{{TRUE}} expected-note{{UNKNOWN}}
+ free(str); // expected-note{{Memory is released}}
+ str = strdup(rhs.str); // expected-warning{{Use of memory after it is freed}} expected-note{{Use of memory after it is freed}}
+ return *this;
+}
+
+StringUsed& StringUsed::operator=(StringUsed &&rhs) { // expected-note{{Assuming rhs == *this}} expected-note{{Assuming rhs != *this}}
+ clang_analyzer_eval(*this == rhs); // expected-warning{{TRUE}} expected-warning{{UNKNOWN}} expected-note{{TRUE}} expected-note{{UNKNOWN}}
+ str = rhs.str;
+ rhs.str = nullptr; // FIXME: An improved leak checker should warn here
+ return *this;
+}
+
+StringUsed::operator const char*() const {
+ return str;
+}
+
+class StringUnused {
+public:
+ StringUnused(const char *s = "") : str(strdup(s)) {}
+ StringUnused(const StringUnused &rhs) : str(strdup(rhs.str)) {}
+ ~StringUnused();
+ StringUnused& operator=(const StringUnused &rhs);
+ StringUnused& operator=(StringUnused &&rhs);
+ operator const char*() const;
+private:
+ char *str;
+};
+
+StringUnused::~StringUnused() {
+ free(str);
+}
+
+StringUnused& StringUnused::operator=(const StringUnused &rhs) { // expected-note{{Assuming rhs == *this}} expected-note{{Assuming rhs == *this}} expected-note{{Assuming rhs != *this}}
+ clang_analyzer_eval(*this == rhs); // expected-warning{{TRUE}} expected-warning{{UNKNOWN}} expected-note{{TRUE}} expected-note{{UNKNOWN}}
+ free(str); // expected-note{{Memory is released}}
+ str = strdup(rhs.str); // expected-warning{{Use of memory after it is freed}} expected-note{{Use of memory after it is freed}}
+ return *this;
+}
+
+StringUnused& StringUnused::operator=(StringUnused &&rhs) { // expected-note{{Assuming rhs == *this}} expected-note{{Assuming rhs != *this}}
+ clang_analyzer_eval(*this == rhs); // expected-warning{{TRUE}} expected-warning{{UNKNOWN}} expected-note{{TRUE}} expected-note{{UNKNOWN}}
+ str = rhs.str;
+ rhs.str = nullptr; // FIXME: An improved leak checker should warn here
+ return *this;
+}
+
+StringUnused::operator const char*() const {
+ return str;
+}
+
+
+int main() {
+ StringUsed s1 ("test"), s2;
+ s2 = s1;
+ s2 = std::move(s1);
+ return 0;
+}
diff --git a/test/Analysis/std-c-library-functions.c b/test/Analysis/std-c-library-functions.c
new file mode 100644
index 000000000000..6b78a26d44bb
--- /dev/null
+++ b/test/Analysis/std-c-library-functions.c
@@ -0,0 +1,188 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=unix.StdCLibraryFunctions,debug.ExprInspection -verify %s
+// RUN: %clang_cc1 -triple i686-unknown-linux -analyze -analyzer-checker=unix.StdCLibraryFunctions,debug.ExprInspection -verify %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -analyze -analyzer-checker=unix.StdCLibraryFunctions,debug.ExprInspection -verify %s
+// RUN: %clang_cc1 -triple armv7-a15-linux -analyze -analyzer-checker=unix.StdCLibraryFunctions,debug.ExprInspection -verify %s
+// RUN: %clang_cc1 -triple thumbv7-a15-linux -analyze -analyzer-checker=unix.StdCLibraryFunctions,debug.ExprInspection -verify %s
+
+void clang_analyzer_eval(int);
+
+int glob;
+
+typedef struct FILE FILE;
+#define EOF -1
+
+int getc(FILE *);
+void test_getc(FILE *fp) {
+ int x;
+ while ((x = getc(fp)) != EOF) {
+ clang_analyzer_eval(x > 255); // expected-warning{{FALSE}}
+ clang_analyzer_eval(x >= 0); // expected-warning{{TRUE}}
+ }
+}
+
+int fgetc(FILE *);
+void test_fgets(FILE *fp) {
+ clang_analyzer_eval(fgetc(fp) < 256); // expected-warning{{TRUE}}
+ clang_analyzer_eval(fgetc(fp) >= 0); // expected-warning{{UNKNOWN}}
+}
+
+
+typedef typeof(sizeof(int)) size_t;
+typedef signed long ssize_t;
+ssize_t read(int, void *, size_t);
+ssize_t write(int, const void *, size_t);
+void test_read_write(int fd, char *buf) {
+ glob = 1;
+ ssize_t x = write(fd, buf, 10);
+ clang_analyzer_eval(glob); // expected-warning{{UNKNOWN}}
+ if (x >= 0) {
+ clang_analyzer_eval(x <= 10); // expected-warning{{TRUE}}
+ ssize_t y = read(fd, &glob, sizeof(glob));
+ if (y >= 0) {
+ clang_analyzer_eval(y <= sizeof(glob)); // expected-warning{{TRUE}}
+ } else {
+ // -1 overflows on promotion!
+ clang_analyzer_eval(y <= sizeof(glob)); // expected-warning{{FALSE}}
+ }
+ } else {
+ clang_analyzer_eval(x == -1); // expected-warning{{TRUE}}
+ }
+}
+
+size_t fread(void *, size_t, size_t, FILE *);
+size_t fwrite(const void *restrict, size_t, size_t, FILE *restrict);
+void test_fread_fwrite(FILE *fp, int *buf) {
+ size_t x = fwrite(buf, sizeof(int), 10, fp);
+ clang_analyzer_eval(x <= 10); // expected-warning{{TRUE}}
+ 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}}
+}
+
+ssize_t getline(char **, size_t *, FILE *);
+void test_getline(FILE *fp) {
+ char *line = 0;
+ size_t n = 0;
+ ssize_t len;
+ while ((len = getline(&line, &n, fp)) != -1) {
+ clang_analyzer_eval(len == 0); // expected-warning{{FALSE}}
+ }
+}
+
+int isascii(int);
+void test_isascii(int x) {
+ clang_analyzer_eval(isascii(123)); // expected-warning{{TRUE}}
+ clang_analyzer_eval(isascii(-1)); // expected-warning{{FALSE}}
+ if (isascii(x)) {
+ clang_analyzer_eval(x < 128); // expected-warning{{TRUE}}
+ clang_analyzer_eval(x >= 0); // expected-warning{{TRUE}}
+ } else {
+ if (x > 42)
+ clang_analyzer_eval(x >= 128); // expected-warning{{TRUE}}
+ else
+ clang_analyzer_eval(x < 0); // expected-warning{{TRUE}}
+ }
+ glob = 1;
+ isascii('a');
+ clang_analyzer_eval(glob); // expected-warning{{TRUE}}
+}
+
+int islower(int);
+void test_islower(int x) {
+ clang_analyzer_eval(islower('x')); // expected-warning{{TRUE}}
+ clang_analyzer_eval(islower('X')); // expected-warning{{FALSE}}
+ if (islower(x))
+ clang_analyzer_eval(x < 'a'); // expected-warning{{FALSE}}
+}
+
+int getchar(void);
+void test_getchar() {
+ int x = getchar();
+ if (x == EOF)
+ return;
+ clang_analyzer_eval(x < 0); // expected-warning{{FALSE}}
+ clang_analyzer_eval(x < 256); // expected-warning{{TRUE}}
+}
+
+int isalpha(int);
+void test_isalpha() {
+ clang_analyzer_eval(isalpha(']')); // expected-warning{{FALSE}}
+ clang_analyzer_eval(isalpha('Q')); // expected-warning{{TRUE}}
+ clang_analyzer_eval(isalpha(128)); // expected-warning{{UNKNOWN}}
+}
+
+int isalnum(int);
+void test_alnum() {
+ clang_analyzer_eval(isalnum('1')); // expected-warning{{TRUE}}
+ clang_analyzer_eval(isalnum(')')); // expected-warning{{FALSE}}
+}
+
+int isblank(int);
+void test_isblank() {
+ clang_analyzer_eval(isblank('\t')); // expected-warning{{TRUE}}
+ clang_analyzer_eval(isblank(' ')); // expected-warning{{TRUE}}
+ clang_analyzer_eval(isblank('\n')); // expected-warning{{FALSE}}
+}
+
+int ispunct(int);
+void test_ispunct(int x) {
+ clang_analyzer_eval(ispunct(' ')); // expected-warning{{FALSE}}
+ clang_analyzer_eval(ispunct(-1)); // expected-warning{{FALSE}}
+ clang_analyzer_eval(ispunct('#')); // expected-warning{{TRUE}}
+ clang_analyzer_eval(ispunct('_')); // expected-warning{{TRUE}}
+ if (ispunct(x))
+ clang_analyzer_eval(x < 127); // expected-warning{{TRUE}}
+}
+
+int isupper(int);
+void test_isupper(int x) {
+ if (isupper(x))
+ clang_analyzer_eval(x < 'A'); // expected-warning{{FALSE}}
+}
+
+int isgraph(int);
+int isprint(int);
+void test_isgraph_isprint(int x) {
+ char y = x;
+ if (isgraph(y))
+ clang_analyzer_eval(isprint(x)); // expected-warning{{TRUE}}
+}
+
+int isdigit(int);
+void test_mixed_branches(int x) {
+ if (isdigit(x)) {
+ clang_analyzer_eval(isgraph(x)); // expected-warning{{TRUE}}
+ clang_analyzer_eval(isblank(x)); // expected-warning{{FALSE}}
+ } else if (isascii(x)) {
+ // isalnum() bifurcates here.
+ clang_analyzer_eval(isalnum(x)); // expected-warning{{TRUE}} // expected-warning{{FALSE}}
+ clang_analyzer_eval(isprint(x)); // expected-warning{{TRUE}} // expected-warning{{FALSE}}
+ }
+}
+
+int isspace(int);
+void test_isspace(int x) {
+ if (!isascii(x))
+ return;
+ char y = x;
+ if (y == ' ')
+ clang_analyzer_eval(isspace(x)); // expected-warning{{TRUE}}
+}
+
+int isxdigit(int);
+void test_isxdigit(int x) {
+ if (isxdigit(x) && isupper(x)) {
+ clang_analyzer_eval(x >= 'A'); // expected-warning{{TRUE}}
+ clang_analyzer_eval(x <= 'F'); // expected-warning{{TRUE}}
+ }
+}
+
+void test_call_by_pointer() {
+ typedef int (*func)(int);
+ func f = isascii;
+ clang_analyzer_eval(f('A')); // expected-warning{{TRUE}}
+ f = ispunct;
+ clang_analyzer_eval(f('A')); // expected-warning{{FALSE}}
+}
diff --git a/test/Analysis/std-c-library-functions.cpp b/test/Analysis/std-c-library-functions.cpp
new file mode 100644
index 000000000000..e6ac66bc81a3
--- /dev/null
+++ b/test/Analysis/std-c-library-functions.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -analyze -analyzer-checker=unix.StdCLibraryFunctions,debug.ExprInspection -verify %s
+
+// Test that we don't model functions with broken prototypes.
+// Because they probably work differently as well.
+//
+// This test lives in a separate file because we wanted to test all functions
+// in the .c file, however in C there are no overloads.
+
+void clang_analyzer_eval(bool);
+bool isalpha(char);
+
+void test() {
+ clang_analyzer_eval(isalpha('A')); // no-crash // expected-warning{{UNKNOWN}}
+}
diff --git a/test/Analysis/string.c b/test/Analysis/string.c
index 2803362ba43e..e541219d05a2 100644
--- a/test/Analysis/string.c
+++ b/test/Analysis/string.c
@@ -154,6 +154,23 @@ void strlen_liveness(const char *x) {
clang_analyzer_eval(strlen(x) < 5); // expected-warning{{FALSE}}
}
+
+size_t strlenWrapper(const char *str) {
+ return strlen(str);
+}
+
+extern void invalidate(char *s);
+
+void testStrlenCallee() {
+ char str[42];
+ invalidate(str);
+ size_t lenBefore = strlenWrapper(str);
+ invalidate(str);
+ size_t lenAfter = strlenWrapper(str);
+ clang_analyzer_eval(lenBefore == lenAfter); // expected-warning{{UNKNOWN}}
+}
+
+
//===----------------------------------------------------------------------===
// strnlen()
//===----------------------------------------------------------------------===
diff --git a/test/Analysis/symbol-reaper.c b/test/Analysis/symbol-reaper.c
index 4051c38c2e77..362a22d4caf3 100644
--- a/test/Analysis/symbol-reaper.c
+++ b/test/Analysis/symbol-reaper.c
@@ -2,6 +2,7 @@
void clang_analyzer_eval(int);
void clang_analyzer_warnOnDeadSymbol(int);
+void clang_analyzer_numTimesReached();
int conjure_index();
@@ -10,6 +11,9 @@ void test_that_expr_inspection_works() {
int x = conjure_index();
clang_analyzer_warnOnDeadSymbol(x);
} while(0); // expected-warning{{SYMBOL DEAD}}
+
+ // Make sure we don't accidentally split state in ExprInspection.
+ clang_analyzer_numTimesReached(); // expected-warning{{1}}
}
// These tests verify the reaping of symbols that are only referenced as
diff --git a/test/Analysis/temp-obj-dtors-cfg-output.cpp b/test/Analysis/temp-obj-dtors-cfg-output.cpp
index b425d9161101..a9e455625957 100644
--- a/test/Analysis/temp-obj-dtors-cfg-output.cpp
+++ b/test/Analysis/temp-obj-dtors-cfg-output.cpp
@@ -1093,9 +1093,9 @@ int testConsistencyNestedNormalReturn(bool value) {
// CHECK: 1: int a;
// CHECK: 2: NoReturn() (CXXConstructExpr, class NoReturn)
// CHECK: 3: [B2.2] (BindTemporary)
-// CHECK: 4: [B2.3].f
-// CHECK: 5: [B2.4]()
-// CHECK: 6: ~NoReturn() (Temporary object destructor)
+// CHECK: [[MEMBER:[45]]]: [B2.{{[34]}}].f
+// CHECK: {{[56]}}: [B2.[[MEMBER]]]()
+// CHECK: {{[67]}}: ~NoReturn() (Temporary object destructor)
// CHECK: Preds (1): B3
// CHECK: Succs (1): B0
// CHECK: [B0 (EXIT)]
diff --git a/test/Analysis/temporaries.cpp b/test/Analysis/temporaries.cpp
index e96e9b0e28d7..49cf070177fc 100644
--- a/test/Analysis/temporaries.cpp
+++ b/test/Analysis/temporaries.cpp
@@ -413,6 +413,32 @@ namespace destructors {
value ? DefaultParam(42) : DefaultParam(42);
}
}
+#else // !TEMPORARY_DTORS
+
+// Test for fallback logic that conservatively stops exploration after
+// executing a temporary constructor for a class with a no-return destructor
+// when temporary destructors are not enabled in the CFG.
+
+ struct CtorWithNoReturnDtor {
+ CtorWithNoReturnDtor() = default;
+
+ ~CtorWithNoReturnDtor() __attribute__((noreturn));
+ };
+
+ void testDefaultContructorWithNoReturnDtor() {
+ CtorWithNoReturnDtor();
+ clang_analyzer_warnIfReached(); // no-warning
+ }
+
+ void testLifeExtensionWithNoReturnDtor() {
+ 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
+ // scope.
+ clang_analyzer_warnIfReached(); // no-warning
+ }
+
#endif // TEMPORARY_DTORS
}
diff --git a/test/Analysis/uninit-vals-union.c b/test/Analysis/uninit-vals-union.c
new file mode 100644
index 000000000000..927dfa2e5979
--- /dev/null
+++ b/test/Analysis/uninit-vals-union.c
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=core.builtin -analyzer-store=region -verify -Wno-unused %s
+
+typedef union {
+ int y;
+} U;
+
+typedef struct { int x; } A;
+
+void foo() {
+ U u = {};
+ A *a = &u; // expected-warning{{incompatible pointer types}}
+ a->x; // no-crash
+}
diff --git a/test/Analysis/uninit-vals.cpp b/test/Analysis/uninit-vals.cpp
new file mode 100644
index 000000000000..387c3754dae4
--- /dev/null
+++ b/test/Analysis/uninit-vals.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=core.builtin -verify -DCHECK_FOR_CRASH %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core -verify %s
+
+#ifdef CHECK_FOR_CRASH
+// expected-no-diagnostics
+#endif
+
+namespace PerformTrivialCopyForUndefs {
+struct A {
+ int x;
+};
+
+struct B {
+ A a;
+};
+
+struct C {
+ B b;
+};
+
+void foo() {
+ C c1;
+ C *c2;
+#ifdef CHECK_FOR_CRASH
+ // If the value of variable is not defined and checkers that check undefined
+ // values are not enabled, performTrivialCopy should be able to handle the
+ // case with undefined values, too.
+ c1.b.a = c2->b.a;
+#else
+ c1.b.a = c2->b.a; // expected-warning{{Function call argument is an uninitialized value}}
+#endif
+}
+}
+
diff --git a/test/Analysis/unions-region.m b/test/Analysis/unions-region.m
index 3a9fb93bf8ad..636198ad0594 100644
--- a/test/Analysis/unions-region.m
+++ b/test/Analysis/unions-region.m
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-store=region -analyzer-constraints=range %s -verify
+// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-store=region %s -verify
// expected-no-diagnostics
//===-- unions-region.m ---------------------------------------------------===//
diff --git a/test/Analysis/unix-api.c b/test/Analysis/unix-api.c
index 86c702d72594..24b145d3d3d9 100644
--- a/test/Analysis/unix-api.c
+++ b/test/Analysis/unix-api.c
@@ -9,6 +9,7 @@
#endif
int open(const char *, int, ...);
+int openat(int, const char *, int, ...);
int close(int fildes);
void open_1(const char *path) {
@@ -21,21 +22,37 @@ void open_1(const char *path) {
void open_2(const char *path) {
int fd;
int mode = 0x0;
- fd = open(path, O_RDONLY, mode, NULL); // expected-warning{{Call to 'open' with more than three arguments}}
+ fd = open(path, O_RDONLY, mode, NULL); // expected-warning{{Call to 'open' with more than 3 arguments}}
+ if (fd > -1)
+ close(fd);
+}
+
+void openat_2(int base_fd, const char *path) {
+ int fd;
+ int mode = 0x0;
+ fd = openat(base_fd, path, O_RDONLY, mode, NULL); // expected-warning{{Call to 'openat' with more than 4 arguments}}
if (fd > -1)
close(fd);
}
void open_3(const char *path) {
int fd;
- fd = open(path, O_RDONLY, NULL); // expected-warning{{Third argument to 'open' is not an integer}}
+ fd = open(path, O_RDONLY, NULL); // expected-warning{{The 3rd argument to 'open' is not an integer}}
if (fd > -1)
close(fd);
}
+void openat_3(int base_fd, const char *path) {
+ int fd;
+ fd = openat(base_fd, path, O_RDONLY, NULL); // expected-warning{{The 4th argument to 'openat' is not an integer}}
+ if (fd > -1)
+ close(fd);
+}
+
+
void open_4(const char *path) {
int fd;
- fd = open(path, O_RDONLY, ""); // expected-warning{{Third argument to 'open' is not an integer}}
+ fd = open(path, O_RDONLY, ""); // expected-warning{{The 3rd argument to 'open' is not an integer}}
if (fd > -1)
close(fd);
}
@@ -45,7 +62,7 @@ void open_5(const char *path) {
struct {
int val;
} st = {0};
- fd = open(path, O_RDONLY, st); // expected-warning{{Third argument to 'open' is not an integer}}
+ fd = open(path, O_RDONLY, st); // expected-warning{{The 3rd argument to 'open' is not an integer}}
if (fd > -1)
close(fd);
}
@@ -62,14 +79,14 @@ void open_6(const char *path) {
void open_7(const char *path) {
int fd;
- fd = open(path, O_RDONLY, &open); // expected-warning{{Third argument to 'open' is not an integer}}
+ fd = open(path, O_RDONLY, &open); // expected-warning{{The 3rd argument to 'open' is not an integer}}
if (fd > -1)
close(fd);
}
void open_8(const char *path) {
int fd;
- fd = open(path, O_RDONLY, 0.0f); // expected-warning{{Third argument to 'open' is not an integer}}
+ fd = open(path, O_RDONLY, 0.0f); // expected-warning{{The 3rd argument to 'open' is not an integer}}
if (fd > -1)
close(fd);
}
diff --git a/test/Analysis/unix-api.cpp b/test/Analysis/unix-api.cpp
new file mode 100644
index 000000000000..1c8f99632c07
--- /dev/null
+++ b/test/Analysis/unix-api.cpp
@@ -0,0 +1,62 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.API -verify %s
+extern "C" {
+#ifndef O_RDONLY
+#define O_RDONLY 0
+#endif
+
+#ifndef NULL
+#define NULL ((void*) 0)
+#endif
+
+int open(const char *, int, ...);
+int close(int fildes);
+
+} // extern "C"
+
+namespace MyNameSpace {
+int open(const char *a, int b, int c, int d);
+}
+
+void unix_open(const char *path) {
+ int fd;
+ fd = open(path, O_RDONLY); // no-warning
+ if (fd > -1)
+ close(fd);
+}
+
+void unix_open_misuse(const char *path) {
+ int fd;
+ int mode = 0x0;
+ fd = open(path, O_RDONLY, mode, NULL); // expected-warning{{Call to 'open' with more than 3 arguments}}
+ if (fd > -1)
+ close(fd);
+}
+
+// Don't treat open() in namespaces as the POSIX open()
+void namespaced_open(const char *path) {
+ MyNameSpace::open("Hi", 2, 3, 4); // no-warning
+
+ using namespace MyNameSpace;
+
+ open("Hi", 2, 3, 4); // no-warning
+
+ int fd;
+ int mode = 0x0;
+ fd = ::open(path, O_RDONLY, mode, NULL); // expected-warning{{Call to 'open' with more than 3 arguments}}
+ if (fd > -1)
+ close(fd);
+}
+
+class MyClass {
+public:
+ static int open(const char *a, int b, int c, int d);
+
+ int open(int a, int, int c, int d);
+};
+
+void class_qualified_open() {
+ MyClass::open("Hi", 2, 3, 4); // no-warning
+
+ MyClass mc;
+ mc.open(1, 2, 3, 4); // no-warning
+}
diff --git a/test/Analysis/unix-fns.c b/test/Analysis/unix-fns.c
index df9edc430f3f..b14457845895 100644
--- a/test/Analysis/unix-fns.c
+++ b/test/Analysis/unix-fns.c
@@ -44,6 +44,7 @@ void dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);
#define O_RDONLY 0x0000
#endif
int open(const char *, int, ...);
+int openat(int, const char *, int, ...);
int close(int fildes);
void test_open(const char *path) {
@@ -52,11 +53,22 @@ void test_open(const char *path) {
if (!fd)
close(fd);
- fd = open(path, O_CREAT); // expected-warning{{Call to 'open' requires a third argument when the 'O_CREAT' flag is set}}
+ fd = open(path, O_CREAT); // expected-warning{{Call to 'open' requires a 3rd argument when the 'O_CREAT' flag is set}}
if (!fd)
close(fd);
}
+void test_open_at(int directory_fd, const char *relative_path) {
+ int fd;
+ fd = openat(directory_fd, relative_path, O_RDONLY); // no-warning
+ if (!fd)
+ close(fd);
+
+ fd = openat(directory_fd, relative_path, O_CREAT); // expected-warning{{Call to 'openat' requires a 4th argument when the 'O_CREAT' flag is set}}
+ if (!fd)
+ close(fd);
+}
+
void test_dispatch_once() {
dispatch_once_t pred = 0;
do { if (__builtin_expect(*(&pred), ~0l) != ~0l) dispatch_once((&pred), (^() {})); } while (0); // expected-warning{{Call to 'dispatch_once' uses the local variable 'pred' for the predicate value}}
@@ -203,1999 +215,2213 @@ void test_inline_dispatch_once() {
});
}
-// CHECK: <key>diagnostics</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>path</key>
-// CHECK-NEXT: <array>
+// 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>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>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>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>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>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>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>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>53</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>53</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>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <key>line</key><integer>53</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>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>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>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>4</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>line</key><integer>53</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: <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>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>52</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>52</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>line</key><integer>53</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: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>52</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: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Assuming &apos;fd&apos; is not equal to 0</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Assuming &apos;fd&apos; is not equal to 0</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: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>52</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>52</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: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>53</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>53</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>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>4</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;fd&apos; is not equal to 0</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;fd&apos; is not equal to 0</string>
-// CHECK-NEXT: </dict>
+// 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>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>56</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>56</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>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <key>line</key><integer>56</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>
+// CHECK-NEXT: <array>
// 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>7</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>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>55</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>55</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>line</key><integer>56</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: <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>3</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>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>55</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>55</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>line</key><integer>56</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: </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>55</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>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Call to &apos;open&apos; requires a 3rd argument when the &apos;O_CREAT&apos; flag is set</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Call to &apos;open&apos; requires a 3rd argument when the &apos;O_CREAT&apos; flag is set</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Call to &apos;open&apos; requires a 3rd argument when the &apos;O_CREAT&apos; flag is set</string>
+// CHECK-NEXT: <key>category</key><string>Unix API</string>
+// CHECK-NEXT: <key>type</key><string>Improper use of &apos;open&apos;</string>
+// CHECK-NEXT: <key>check_name</key><string>unix.API</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>5ef25c5c47db3dbfb329901d426452e7</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>test_open</string>
+// CHECK-NEXT: <key>issue_hash_function_offset</key><string>6</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>56</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: <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: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>55</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>55</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: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>62</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>62</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>64</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>64</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: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to &apos;open&apos; requires a third argument when the &apos;O_CREAT&apos; flag is set</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to &apos;open&apos; requires a third argument when the &apos;O_CREAT&apos; flag is set</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Call to &apos;open&apos; requires a third argument when the &apos;O_CREAT&apos; flag is set</string>
-// CHECK-NEXT: <key>category</key><string>Unix API</string>
-// CHECK-NEXT: <key>type</key><string>Improper use of &apos;open&apos;</string>
-// CHECK-NEXT: <key>check_name</key><string>unix.API</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>5ef25c5c47db3dbfb329901d426452e7</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_open</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>6</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>55</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: <dict>
-// CHECK-NEXT: <key>path</key>
-// 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>64</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>64</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>64</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>64</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>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <key>line</key><integer>64</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>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>61</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>61</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>62</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>62</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>line</key><integer>64</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: <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>62</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>62</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>62</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>62</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>line</key><integer>64</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: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Assuming &apos;fd&apos; is not equal to 0</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Assuming &apos;fd&apos; is not equal to 0</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>64</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>64</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>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>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>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>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>67</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>67</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>event</string>
+// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <key>line</key><integer>67</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>
+// CHECK-NEXT: <array>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>62</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>62</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>62</integer>
-// CHECK-NEXT: <key>col</key><integer>52</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>62</integer>
-// CHECK-NEXT: <key>col</key><integer>64</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>line</key><integer>67</integer>
+// CHECK-NEXT: <key>col</key><integer>44</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>50</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
// 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>62</integer>
-// CHECK-NEXT: <key>col</key><integer>52</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Call to &apos;openat&apos; requires a 4th argument when the &apos;O_CREAT&apos; flag is set</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Call to &apos;openat&apos; requires a 4th argument when the &apos;O_CREAT&apos; flag is set</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Call to &apos;openat&apos; requires a 4th argument when the &apos;O_CREAT&apos; flag is set</string>
+// CHECK-NEXT: <key>category</key><string>Unix API</string>
+// CHECK-NEXT: <key>type</key><string>Improper use of &apos;open&apos;</string>
+// CHECK-NEXT: <key>check_name</key><string>unix.API</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>433b17840bb989e7a13dc6337c1ed220</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>test_open_at</string>
+// CHECK-NEXT: <key>issue_hash_function_offset</key><string>6</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>67</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: <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: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>62</integer>
-// CHECK-NEXT: <key>col</key><integer>66</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>62</integer>
-// CHECK-NEXT: <key>col</key><integer>72</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// 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>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>74</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>74</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: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to &apos;dispatch_once&apos; uses the local variable &apos;pred&apos; for the predicate value. Using such transient memory for the predicate is potentially dangerous. Perhaps you intended to declare the variable as &apos;static&apos;?</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to &apos;dispatch_once&apos; uses the local variable &apos;pred&apos; for the predicate value. Using such transient memory for the predicate is potentially dangerous. Perhaps you intended to declare the variable as &apos;static&apos;?</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Call to &apos;dispatch_once&apos; uses the local variable &apos;pred&apos; for the predicate value. Using such transient memory for the predicate is potentially dangerous. Perhaps you intended to declare the variable as &apos;static&apos;?</string>
-// CHECK-NEXT: <key>category</key><string>API Misuse (Apple)</string>
-// CHECK-NEXT: <key>type</key><string>Improper use of &apos;dispatch_once&apos;</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.API</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>173fbcac3fc64dbaec32768d4cfda250</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_dispatch_once</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>62</integer>
-// CHECK-NEXT: <key>col</key><integer>52</integer>
-// 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: <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>74</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>74</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>74</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>74</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>74</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>74</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>74</integer>
+// CHECK-NEXT: <key>col</key><integer>52</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>74</integer>
+// CHECK-NEXT: <key>col</key><integer>64</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>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <key>line</key><integer>74</integer>
+// CHECK-NEXT: <key>col</key><integer>52</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>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>72</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>72</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>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>14</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>line</key><integer>74</integer>
+// CHECK-NEXT: <key>col</key><integer>66</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>74</integer>
+// CHECK-NEXT: <key>col</key><integer>72</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
// 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>73</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: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Call to &apos;dispatch_once&apos; uses the local variable &apos;pred&apos; for the predicate value. Using such transient memory for the predicate is potentially dangerous. Perhaps you intended to declare the variable as &apos;static&apos;?</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Call to &apos;dispatch_once&apos; uses the local variable &apos;pred&apos; for the predicate value. Using such transient memory for the predicate is potentially dangerous. Perhaps you intended to declare the variable as &apos;static&apos;?</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Call to &apos;dispatch_once&apos; uses the local variable &apos;pred&apos; for the predicate value. Using such transient memory for the predicate is potentially dangerous. Perhaps you intended to declare the variable as &apos;static&apos;?</string>
+// CHECK-NEXT: <key>category</key><string>API Misuse (Apple)</string>
+// CHECK-NEXT: <key>type</key><string>Improper use of &apos;dispatch_once&apos;</string>
+// CHECK-NEXT: <key>check_name</key><string>osx.API</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>173fbcac3fc64dbaec32768d4cfda250</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>test_dispatch_once</string>
+// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>74</integer>
+// CHECK-NEXT: <key>col</key><integer>52</integer>
+// 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: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>73</integer>
-// CHECK-NEXT: <key>col</key><integer>16</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>20</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>84</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>84</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>85</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>85</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: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to &apos;pthread_once&apos; uses the local variable &apos;pred&apos; for the &quot;control&quot; value. Using such transient memory for the control value is potentially dangerous. Perhaps you intended to declare the variable as &apos;static&apos;?</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to &apos;pthread_once&apos; uses the local variable &apos;pred&apos; for the &quot;control&quot; value. Using such transient memory for the control value is potentially dangerous. Perhaps you intended to declare the variable as &apos;static&apos;?</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Call to &apos;pthread_once&apos; uses the local variable &apos;pred&apos; for the &quot;control&quot; value. Using such transient memory for the control value is potentially dangerous. Perhaps you intended to declare the variable as &apos;static&apos;?</string>
-// CHECK-NEXT: <key>category</key><string>Unix API</string>
-// CHECK-NEXT: <key>type</key><string>Improper use of &apos;pthread_once&apos;</string>
-// CHECK-NEXT: <key>check_name</key><string>unix.API</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>1e2f657a65cf8ee3c3ac2227de05ade4</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_pthread_once</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// 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: <dict>
-// CHECK-NEXT: <key>path</key>
-// 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>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <key>line</key><integer>85</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>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>82</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>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>82</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>82</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>line</key><integer>85</integer>
+// CHECK-NEXT: <key>col</key><integer>16</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>85</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: <dict>
-// 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>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Call to &apos;pthread_once&apos; uses the local variable &apos;pred&apos; for the &quot;control&quot; value. Using such transient memory for the control value is potentially dangerous. Perhaps you intended to declare the variable as &apos;static&apos;?</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Call to &apos;pthread_once&apos; uses the local variable &apos;pred&apos; for the &quot;control&quot; value. Using such transient memory for the control value is potentially dangerous. Perhaps you intended to declare the variable as &apos;static&apos;?</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Call to &apos;pthread_once&apos; uses the local variable &apos;pred&apos; for the &quot;control&quot; value. Using such transient memory for the control value is potentially dangerous. Perhaps you intended to declare the variable as &apos;static&apos;?</string>
+// CHECK-NEXT: <key>category</key><string>Unix API</string>
+// CHECK-NEXT: <key>type</key><string>Improper use of &apos;pthread_once&apos;</string>
+// CHECK-NEXT: <key>check_name</key><string>unix.API</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>1e2f657a65cf8ee3c3ac2227de05ade4</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>test_pthread_once</string>
+// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>85</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: <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: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>82</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>82</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: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>94</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>94</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>94</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>94</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: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to &apos;malloc&apos; has an allocation size of 0 bytes</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to &apos;malloc&apos; has an allocation size of 0 bytes</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Call to &apos;malloc&apos; has an allocation size of 0 bytes</string>
-// CHECK-NEXT: <key>category</key><string>Unix API</string>
-// CHECK-NEXT: <key>type</key><string>Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131)</string>
-// CHECK-NEXT: <key>check_name</key><string>unix.API</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>0e841458f0cb7cf161d35f9db5862dcf</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>pr2899</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>82</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: <dict>
-// CHECK-NEXT: <key>path</key>
-// 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>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <key>line</key><integer>94</integer>
+// CHECK-NEXT: <key>col</key><integer>15</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>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>94</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>94</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>94</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>94</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>line</key><integer>94</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>94</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: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>94</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Call to &apos;malloc&apos; has an allocation size of 0 bytes</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Call to &apos;malloc&apos; has an allocation size of 0 bytes</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Call to &apos;malloc&apos; has an allocation size of 0 bytes</string>
+// CHECK-NEXT: <key>category</key><string>Unix API</string>
+// CHECK-NEXT: <key>type</key><string>Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131)</string>
+// CHECK-NEXT: <key>check_name</key><string>unix.API</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>0e841458f0cb7cf161d35f9db5862dcf</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>pr2899</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>94</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: <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: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>94</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>94</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: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>106</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>106</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>106</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>106</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: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to &apos;calloc&apos; has an allocation size of 0 bytes</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to &apos;calloc&apos; has an allocation size of 0 bytes</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Call to &apos;calloc&apos; has an allocation size of 0 bytes</string>
-// CHECK-NEXT: <key>category</key><string>Unix API</string>
-// CHECK-NEXT: <key>type</key><string>Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131)</string>
-// CHECK-NEXT: <key>check_name</key><string>unix.API</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>a267ff573c7e8b959a3f886677893eb0</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_calloc</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>94</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: <dict>
-// CHECK-NEXT: <key>path</key>
-// 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>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <key>line</key><integer>106</integer>
+// CHECK-NEXT: <key>col</key><integer>15</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>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>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>100</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>100</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>line</key><integer>106</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>106</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: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>100</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Call to &apos;calloc&apos; has an allocation size of 0 bytes</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Call to &apos;calloc&apos; has an allocation size of 0 bytes</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Call to &apos;calloc&apos; has an allocation size of 0 bytes</string>
+// CHECK-NEXT: <key>category</key><string>Unix API</string>
+// CHECK-NEXT: <key>type</key><string>Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131)</string>
+// CHECK-NEXT: <key>check_name</key><string>unix.API</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>a267ff573c7e8b959a3f886677893eb0</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>test_calloc</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>106</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: <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: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>100</integer>
-// CHECK-NEXT: <key>col</key><integer>26</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>26</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// 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>3</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>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>112</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>112</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: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to &apos;calloc&apos; has an allocation size of 0 bytes</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to &apos;calloc&apos; has an allocation size of 0 bytes</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Call to &apos;calloc&apos; has an allocation size of 0 bytes</string>
-// CHECK-NEXT: <key>category</key><string>Unix API</string>
-// CHECK-NEXT: <key>type</key><string>Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131)</string>
-// CHECK-NEXT: <key>check_name</key><string>unix.API</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>14eb72957baab3c63bac610a10e6f48b</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_calloc2</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>100</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: <dict>
-// CHECK-NEXT: <key>path</key>
-// 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>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <key>line</key><integer>112</integer>
+// CHECK-NEXT: <key>col</key><integer>15</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>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>112</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>112</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>112</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>112</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: <key>line</key><integer>112</integer>
+// CHECK-NEXT: <key>col</key><integer>26</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>26</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
// 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>112</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Call to &apos;calloc&apos; has an allocation size of 0 bytes</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Call to &apos;calloc&apos; has an allocation size of 0 bytes</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Call to &apos;calloc&apos; has an allocation size of 0 bytes</string>
+// CHECK-NEXT: <key>category</key><string>Unix API</string>
+// CHECK-NEXT: <key>type</key><string>Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131)</string>
+// CHECK-NEXT: <key>check_name</key><string>unix.API</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>14eb72957baab3c63bac610a10e6f48b</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>test_calloc2</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>112</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: <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: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>112</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>112</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: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>124</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>124</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>124</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>124</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: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to &apos;realloc&apos; has an allocation size of 0 bytes</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to &apos;realloc&apos; has an allocation size of 0 bytes</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Call to &apos;realloc&apos; has an allocation size of 0 bytes</string>
-// CHECK-NEXT: <key>category</key><string>Unix API</string>
-// CHECK-NEXT: <key>type</key><string>Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131)</string>
-// CHECK-NEXT: <key>check_name</key><string>unix.API</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>7f6f67ebe3d481aed7750005bea7e371</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_realloc</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>112</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: <dict>
-// CHECK-NEXT: <key>path</key>
-// 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>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <key>line</key><integer>124</integer>
+// CHECK-NEXT: <key>col</key><integer>15</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>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>118</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>118</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>118</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>118</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>line</key><integer>124</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>124</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: </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>118</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Call to &apos;realloc&apos; has an allocation size of 0 bytes</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Call to &apos;realloc&apos; has an allocation size of 0 bytes</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Call to &apos;realloc&apos; has an allocation size of 0 bytes</string>
+// CHECK-NEXT: <key>category</key><string>Unix API</string>
+// CHECK-NEXT: <key>type</key><string>Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131)</string>
+// CHECK-NEXT: <key>check_name</key><string>unix.API</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>7f6f67ebe3d481aed7750005bea7e371</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>test_realloc</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>124</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: <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: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>118</integer>
-// CHECK-NEXT: <key>col</key><integer>29</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>118</integer>
-// CHECK-NEXT: <key>col</key><integer>29</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// 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>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>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>22</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to &apos;reallocf&apos; has an allocation size of 0 bytes</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to &apos;reallocf&apos; has an allocation size of 0 bytes</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Call to &apos;reallocf&apos; has an allocation size of 0 bytes</string>
-// CHECK-NEXT: <key>category</key><string>Unix API</string>
-// CHECK-NEXT: <key>type</key><string>Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131)</string>
-// CHECK-NEXT: <key>check_name</key><string>unix.API</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>4941698efbd81601653dff10ef9c645b</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_reallocf</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>118</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: <dict>
-// CHECK-NEXT: <key>path</key>
-// 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>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// 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: <key>ranges</key>
+// CHECK-NEXT: <array>
// 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>3</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>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>136</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>136</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>line</key><integer>130</integer>
+// CHECK-NEXT: <key>col</key><integer>29</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>29</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
// 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>136</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Call to &apos;reallocf&apos; has an allocation size of 0 bytes</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Call to &apos;reallocf&apos; has an allocation size of 0 bytes</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Call to &apos;reallocf&apos; has an allocation size of 0 bytes</string>
+// CHECK-NEXT: <key>category</key><string>Unix API</string>
+// CHECK-NEXT: <key>type</key><string>Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131)</string>
+// CHECK-NEXT: <key>check_name</key><string>unix.API</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>4941698efbd81601653dff10ef9c645b</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>test_reallocf</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>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: <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: <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>22</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</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>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>148</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>148</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: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to &apos;alloca&apos; has an allocation size of 0 bytes</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to &apos;alloca&apos; has an allocation size of 0 bytes</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Call to &apos;alloca&apos; has an allocation size of 0 bytes</string>
-// CHECK-NEXT: <key>category</key><string>Unix API</string>
-// CHECK-NEXT: <key>type</key><string>Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131)</string>
-// CHECK-NEXT: <key>check_name</key><string>unix.API</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>b7ca3488e81d9d9d4b8dc545258ce97c</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_alloca</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>136</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: <dict>
-// CHECK-NEXT: <key>path</key>
-// 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>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <key>line</key><integer>148</integer>
+// CHECK-NEXT: <key>col</key><integer>15</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>start</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>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>148</integer>
-// CHECK-NEXT: <key>col</key><integer>16</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>31</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>line</key><integer>148</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>148</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: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>148</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Call to &apos;alloca&apos; has an allocation size of 0 bytes</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Call to &apos;alloca&apos; has an allocation size of 0 bytes</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Call to &apos;alloca&apos; has an allocation size of 0 bytes</string>
+// CHECK-NEXT: <key>category</key><string>Unix API</string>
+// CHECK-NEXT: <key>type</key><string>Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131)</string>
+// CHECK-NEXT: <key>check_name</key><string>unix.API</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>b7ca3488e81d9d9d4b8dc545258ce97c</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>test_alloca</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>148</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: <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: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>148</integer>
-// CHECK-NEXT: <key>col</key><integer>33</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>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// 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>3</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>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>160</integer>
+// CHECK-NEXT: <key>col</key><integer>16</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>31</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to &apos;alloca&apos; has an allocation size of 0 bytes</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to &apos;alloca&apos; has an allocation size of 0 bytes</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Call to &apos;alloca&apos; has an allocation size of 0 bytes</string>
-// CHECK-NEXT: <key>category</key><string>Unix API</string>
-// CHECK-NEXT: <key>type</key><string>Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131)</string>
-// CHECK-NEXT: <key>check_name</key><string>unix.API</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>1ec52551362b070237f47f6bb6c3847d</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_builtin_alloca</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>148</integer>
-// CHECK-NEXT: <key>col</key><integer>16</integer>
-// 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: <dict>
+// CHECK-NEXT: <key>kind</key><string>event</string>
+// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <key>line</key><integer>160</integer>
+// CHECK-NEXT: <key>col</key><integer>16</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>start</key>
-// 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>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>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>160</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>160</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>line</key><integer>160</integer>
+// CHECK-NEXT: <key>col</key><integer>33</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>33</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
// 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>160</integer>
-// CHECK-NEXT: <key>col</key><integer>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Call to &apos;alloca&apos; has an allocation size of 0 bytes</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Call to &apos;alloca&apos; has an allocation size of 0 bytes</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Call to &apos;alloca&apos; has an allocation size of 0 bytes</string>
+// CHECK-NEXT: <key>category</key><string>Unix API</string>
+// CHECK-NEXT: <key>type</key><string>Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131)</string>
+// CHECK-NEXT: <key>check_name</key><string>unix.API</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>1ec52551362b070237f47f6bb6c3847d</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>test_builtin_alloca</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>160</integer>
+// CHECK-NEXT: <key>col</key><integer>16</integer>
+// 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: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>160</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>160</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: <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>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>172</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>172</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: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to &apos;valloc&apos; has an allocation size of 0 bytes</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to &apos;valloc&apos; has an allocation size of 0 bytes</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Call to &apos;valloc&apos; has an allocation size of 0 bytes</string>
-// CHECK-NEXT: <key>category</key><string>Unix API</string>
-// CHECK-NEXT: <key>type</key><string>Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131)</string>
-// CHECK-NEXT: <key>check_name</key><string>unix.API</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>675741e04c8d0071d280324e23f41d35</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_valloc</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>160</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: <dict>
-// CHECK-NEXT: <key>path</key>
-// 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>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <key>line</key><integer>172</integer>
+// CHECK-NEXT: <key>col</key><integer>15</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>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>183</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>183</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>184</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>184</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>line</key><integer>172</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>172</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: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>184</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: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Call to &apos;valloc&apos; has an allocation size of 0 bytes</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Call to &apos;valloc&apos; has an allocation size of 0 bytes</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Call to &apos;valloc&apos; has an allocation size of 0 bytes</string>
+// CHECK-NEXT: <key>category</key><string>Unix API</string>
+// CHECK-NEXT: <key>type</key><string>Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131)</string>
+// CHECK-NEXT: <key>check_name</key><string>unix.API</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>675741e04c8d0071d280324e23f41d35</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>test_valloc</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>172</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: <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: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>184</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>184</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: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>195</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>195</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>196</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>196</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: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Call to &apos;dispatch_once&apos; uses the local variable &apos;pred&apos; for the predicate value. Using such transient memory for the predicate is potentially dangerous. Perhaps you intended to declare the variable as &apos;static&apos;?</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Call to &apos;dispatch_once&apos; uses the local variable &apos;pred&apos; for the predicate value. Using such transient memory for the predicate is potentially dangerous. Perhaps you intended to declare the variable as &apos;static&apos;?</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Call to &apos;dispatch_once&apos; uses the local variable &apos;pred&apos; for the predicate value. Using such transient memory for the predicate is potentially dangerous. Perhaps you intended to declare the variable as &apos;static&apos;?</string>
-// CHECK-NEXT: <key>category</key><string>API Misuse (Apple)</string>
-// CHECK-NEXT: <key>type</key><string>Improper use of &apos;dispatch_once&apos;</string>
-// CHECK-NEXT: <key>check_name</key><string>osx.API</string>
-// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
-// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>8ded1f2025c1e4a4bcd5302dc97006d9</string>
-// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
-// CHECK-NEXT: <key>issue_context</key><string>test_dispatch_once_in_macro</string>
-// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>184</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: <dict>
-// CHECK-NEXT: <key>path</key>
-// 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>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>189</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>189</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>189</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>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
+// CHECK-NEXT: <key>line</key><integer>196</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>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <key>ranges</key>
+// CHECK-NEXT: <array>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>189</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>189</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>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>15</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>line</key><integer>196</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>196</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: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Call to &apos;dispatch_once&apos; uses the local variable &apos;pred&apos; for the predicate value. Using such transient memory for the predicate is potentially dangerous. Perhaps you intended to declare the variable as &apos;static&apos;?</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Call to &apos;dispatch_once&apos; uses the local variable &apos;pred&apos; for the predicate value. Using such transient memory for the predicate is potentially dangerous. Perhaps you intended to declare the variable as &apos;static&apos;?</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Call to &apos;dispatch_once&apos; uses the local variable &apos;pred&apos; for the predicate value. Using such transient memory for the predicate is potentially dangerous. Perhaps you intended to declare the variable as &apos;static&apos;?</string>
+// CHECK-NEXT: <key>category</key><string>API Misuse (Apple)</string>
+// CHECK-NEXT: <key>type</key><string>Improper use of &apos;dispatch_once&apos;</string>
+// CHECK-NEXT: <key>check_name</key><string>osx.API</string>
+// CHECK-NEXT: <!-- This hash is experimental and going to change! -->
+// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>8ded1f2025c1e4a4bcd5302dc97006d9</string>
+// CHECK-NEXT: <key>issue_context_kind</key><string>function</string>
+// CHECK-NEXT: <key>issue_context</key><string>test_dispatch_once_in_macro</string>
+// CHECK-NEXT: <key>issue_hash_function_offset</key><string>2</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>
+// 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>event</string>
+// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <key>line</key><integer>201</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>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>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>190</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>190</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>line</key><integer>201</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>201</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: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>190</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: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>&apos;p&apos; initialized to 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: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>190</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>194</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: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>201</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>201</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>202</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>202</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: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; captured by block as a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// 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>event</string>
-// CHECK-NEXT: <key>location</key>
-// 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: <key>ranges</key>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>kind</key><string>control</string>
+// CHECK-NEXT: <key>edges</key>
// CHECK-NEXT: <array>
-// 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>194</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: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>202</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>202</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>202</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>202</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: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;dispatch_sync&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;dispatch_sync&apos;</string>
-// CHECK-NEXT: </dict>
+// 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>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// 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: <key>ranges</key>
-// CHECK-NEXT: <array>
-// 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>194</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>1</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling anonymous block</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling anonymous block</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>190</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>2</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;dispatch_sync&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;dispatch_sync&apos;</string>
+// CHECK-NEXT: <key>line</key><integer>202</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>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <key>ranges</key>
+// CHECK-NEXT: <array>
// 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>24</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>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>191</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>191</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>line</key><integer>202</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>206</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: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>&apos;p&apos; captured by block as a null pointer value</string>
+// CHECK-NEXT: <key>message</key>
+// 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>event</string>
+// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <key>line</key><integer>202</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>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</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>191</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>191</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>191</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>line</key><integer>202</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>206</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: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Calling &apos;dispatch_sync&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Calling &apos;dispatch_sync&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>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</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>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</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>191</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>2</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Assuming &apos;q&apos; is non-null</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Assuming &apos;q&apos; is non-null</string>
+// CHECK-NEXT: <key>line</key><integer>202</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>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <key>ranges</key>
+// CHECK-NEXT: <array>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>191</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>191</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>192</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>3</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>line</key><integer>202</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>206</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: </array>
+// CHECK-NEXT: <key>depth</key><integer>1</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Calling anonymous block</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Calling anonymous block</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>202</integer>
+// CHECK-NEXT: <key>col</key><integer>24</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>depth</key><integer>2</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Entered call from &apos;dispatch_sync&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Entered call from &apos;dispatch_sync&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>202</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>202</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>203</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>203</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>203</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>203</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>203</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>203</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>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <key>line</key><integer>203</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>
+// CHECK-NEXT: <array>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>192</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>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>192</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>192</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>line</key><integer>203</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>203</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: <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>6</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>ranges</key>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>depth</key><integer>2</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Assuming &apos;q&apos; is non-null</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Assuming &apos;q&apos; is non-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: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>192</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>192</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: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>203</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>203</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>204</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>3</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>depth</key><integer>2</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
-// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&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>5d3f4c433004c7a6d4a06aa30cc3ea85</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>192</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: <dict>
-// CHECK-NEXT: <key>path</key>
-// 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>204</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>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>204</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>204</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>event</string>
+// CHECK-NEXT: <key>location</key>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <key>line</key><integer>204</integer>
+// CHECK-NEXT: <key>col</key><integer>6</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>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>199</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>199</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>200</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>200</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>line</key><integer>204</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>204</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: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>200</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: <key>depth</key><integer>2</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&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>5d3f4c433004c7a6d4a06aa30cc3ea85</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>204</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: <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: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>200</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>200</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: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>211</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>211</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>212</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>212</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: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
-// CHECK-NEXT: </dict>
+// 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>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <key>line</key><integer>212</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>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>200</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>200</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>201</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>201</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>line</key><integer>212</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>212</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: <dict>
-// CHECK-NEXT: <key>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>201</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: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>&apos;p&apos; initialized to a null pointer value</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>&apos;p&apos; initialized to 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: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>201</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>203</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: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>212</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>212</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>213</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>213</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: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>&apos;p&apos; captured by block as a null pointer value</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>&apos;p&apos; captured by block as a null pointer value</string>
-// CHECK-NEXT: </dict>
+// 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>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>201</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>201</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>203</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: </array>
-// CHECK-NEXT: <key>depth</key><integer>0</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling &apos;_dispatch_once&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;_dispatch_once&apos;</string>
+// CHECK-NEXT: <key>line</key><integer>213</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>213</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>215</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: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>&apos;p&apos; captured by block as a null pointer value</string>
+// CHECK-NEXT: <key>message</key>
+// 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>event</string>
+// CHECK-NEXT: <key>location</key>
// 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>175</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;test_inline_dispatch_once&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;test_inline_dispatch_once&apos;</string>
+// CHECK-NEXT: <key>line</key><integer>213</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>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <key>ranges</key>
+// CHECK-NEXT: <array>
// 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>1</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>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>177</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>177</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>line</key><integer>213</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>4</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>depth</key><integer>0</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Calling &apos;_dispatch_once&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Calling &apos;_dispatch_once&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>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>177</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>177</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>177</integer>
-// CHECK-NEXT: <key>col</key><integer>33</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>Calling &apos;dispatch_once&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling &apos;dispatch_once&apos;</string>
+// CHECK-NEXT: <key>line</key><integer>187</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>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>177</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: <key>depth</key><integer>1</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Entered call from &apos;test_inline_dispatch_once&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Entered call from &apos;test_inline_dispatch_once&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: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>177</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>177</integer>
-// CHECK-NEXT: <key>col</key><integer>33</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: </array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>187</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>187</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>189</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>189</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: <key>depth</key><integer>2</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Calling anonymous block</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Calling anonymous block</string>
-// CHECK-NEXT: </dict>
+// 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>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>201</integer>
-// CHECK-NEXT: <key>col</key><integer>24</integer>
-// CHECK-NEXT: <key>file</key><integer>0</integer>
-// CHECK-NEXT: </dict>
-// CHECK-NEXT: <key>depth</key><integer>3</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Entered call from &apos;dispatch_once&apos;</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Entered call from &apos;dispatch_once&apos;</string>
+// CHECK-NEXT: <key>line</key><integer>189</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>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <key>ranges</key>
+// CHECK-NEXT: <array>
// CHECK-NEXT: <array>
// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>201</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>201</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>202</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>202</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>line</key><integer>189</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>189</integer>
+// CHECK-NEXT: <key>col</key><integer>33</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>depth</key><integer>1</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Calling &apos;dispatch_once&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Calling &apos;dispatch_once&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>kind</key><string>control</string>
-// CHECK-NEXT: <key>edges</key>
+// CHECK-NEXT: <key>line</key><integer>189</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>start</key>
-// CHECK-NEXT: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>202</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>202</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>202</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>202</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>line</key><integer>189</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>189</integer>
+// CHECK-NEXT: <key>col</key><integer>33</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
// CHECK-NEXT: </dict>
// CHECK-NEXT: </array>
-// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>depth</key><integer>2</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Calling anonymous block</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Calling anonymous block</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>kind</key><string>event</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>202</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: <key>line</key><integer>213</integer>
+// CHECK-NEXT: <key>col</key><integer>24</integer>
+// CHECK-NEXT: <key>file</key><integer>0</integer>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: <key>depth</key><integer>3</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Entered call from &apos;dispatch_once&apos;</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Entered call from &apos;dispatch_once&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: <array>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>202</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>202</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: <key>start</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>213</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>213</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>214</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>214</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: <key>depth</key><integer>3</integer>
-// CHECK-NEXT: <key>extended_message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
-// CHECK-NEXT: <key>message</key>
-// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &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>214</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>214</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>214</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>214</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>214</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>description</key><string>Dereference of null pointer (loaded from variable &apos;p&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>265c4fd608dafee211bfa93d21c28866</string>
-// CHECK-NEXT: <key>location</key>
-// CHECK-NEXT: <dict>
-// CHECK-NEXT: <key>line</key><integer>202</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: </array>
+// CHECK-NEXT: <key>ranges</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>214</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>214</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: </array>
+// CHECK-NEXT: <key>depth</key><integer>3</integer>
+// CHECK-NEXT: <key>extended_message</key>
+// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+// CHECK-NEXT: <key>message</key>
+// CHECK-NEXT: <string>Dereference of null pointer (loaded from variable &apos;p&apos;)</string>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: <key>description</key><string>Dereference of null pointer (loaded from variable &apos;p&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>265c4fd608dafee211bfa93d21c28866</string>
+// CHECK-NEXT: <key>location</key>
+// CHECK-NEXT: <dict>
+// CHECK-NEXT: <key>line</key><integer>214</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: </array>
diff --git a/test/Analysis/unreachable-code-path.c b/test/Analysis/unreachable-code-path.c
index 08019d9cbe31..4ddfb21f0a0f 100644
--- a/test/Analysis/unreachable-code-path.c
+++ b/test/Analysis/unreachable-code-path.c
@@ -158,3 +158,58 @@ void testInlined() {
}
}
}
+
+// Don't warn about unreachable VarDecl.
+void dostuff(int*A);
+void varDecl1(int X) {
+ switch (X) {
+ int A; // No warning here.
+ case 1:
+ dostuff(&A);
+ break;
+ case 2:
+ dostuff(&A);
+ break;
+ }
+}
+void varDecl2(int X) {
+ switch (X) {
+ int A=1; // expected-warning {{never executed}}
+ case 1:
+ dostuff(&A);
+ break;
+ case 2:
+ dostuff(&A);
+ break;
+ }
+}
+
+// Ensure that ExplodedGraph and unoptimized CFG match.
+void test12(int x) {
+ switch (x) {
+ case 1:
+ break; // not unreachable
+ case 2:
+ do { } while (0);
+ break;
+ }
+}
+
+// Don't merge return nodes in ExplodedGraph unless they are same.
+extern int table[];
+static int inlineFunction(const int i) {
+ if (table[i] != 0)
+ return 1;
+ return 0;
+}
+void test13(int i) {
+ int x = inlineFunction(i);
+ x && x < 10; // no-warning
+}
+
+// Don't warn in a macro
+#define RETURN(X) do { return; } while (0)
+void macro(void) {
+ RETURN(1); // no-warning
+}
+
diff --git a/test/Analysis/valist-uninitialized.c b/test/Analysis/valist-uninitialized.c
new file mode 100644
index 000000000000..b1f11d138fec
--- /dev/null
+++ b/test/Analysis/valist-uninitialized.c
@@ -0,0 +1,178 @@
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -analyze -analyzer-checker=core,alpha.valist.Uninitialized,alpha.valist.CopyToSelf -analyzer-output=text -analyzer-store=region -verify %s
+
+#include "Inputs/system-header-simulator-for-valist.h"
+
+void f1(int fst, ...) {
+ va_list va;
+ (void)va_arg(va, int); //expected-warning{{va_arg() is called on an uninitialized va_list}} expected-note{{va_arg() is called on an uninitialized va_list}}
+}
+
+int f2(int fst, ...) {
+ va_list va;
+ va_start(va, fst); // expected-note{{Initialized va_list}}
+ va_end(va); // expected-note{{Ended va_list}}
+ return va_arg(va, int); //expected-warning{{va_arg() is called on an uninitialized va_list}} expected-note{{va_arg() is called on an uninitialized va_list}}
+}
+
+void f3(int fst, ...) {
+ va_list va, va2;
+ va_start(va, fst);
+ va_copy(va2, va);
+ va_end(va);
+ (void)va_arg(va2, int);
+ va_end(va2);
+} //no-warning
+
+void f4(int cond, ...) {
+ va_list va;
+ if (cond) { // expected-note{{Assuming 'cond' is 0}} expected-note{{Taking false branch}}
+ va_start(va, cond);
+ (void)va_arg(va,int);
+ }
+ va_end(va); //expected-warning{{va_end() is called on an uninitialized va_list}} expected-note{{va_end() is called on an uninitialized va_list}}
+}
+
+void f5(va_list fst, ...) {
+ va_start(fst, fst);
+ (void)va_arg(fst, int);
+ va_end(fst);
+} // no-warning
+
+//FIXME: this should not cause a warning
+void f6(va_list *fst, ...) {
+ va_start(*fst, fst);
+ (void)va_arg(*fst, int); //expected-warning{{va_arg() is called on an uninitialized va_list}} expected-note{{va_arg() is called on an uninitialized va_list}}
+ va_end(*fst);
+}
+
+void f7(int *fst, ...) {
+ va_list x;
+ va_list *y = &x;
+ va_start(*y,fst);
+ (void)va_arg(x, int);
+ va_end(x);
+} // no-warning
+
+void f8(int *fst, ...) {
+ va_list x;
+ va_list *y = &x;
+ va_start(*y,fst); // expected-note{{Initialized va_list}}
+ va_end(x); // expected-note{{Ended va_list}}
+ (void)va_arg(*y, int); //expected-warning{{va_arg() is called on an uninitialized va_list}} expected-note{{va_arg() is called on an uninitialized va_list}}
+} // no-warning
+
+// This only contains problems which are handled by varargs.Unterminated.
+void reinit(int *fst, ...) {
+ va_list va;
+ va_start(va, fst);
+ va_start(va, fst);
+ (void)va_arg(va, int);
+} // no-warning
+
+void reinitOk(int *fst, ...) {
+ va_list va;
+ va_start(va, fst);
+ (void)va_arg(va, int);
+ va_end(va);
+ va_start(va, fst);
+ (void)va_arg(va, int);
+ va_end(va);
+} // no-warning
+
+void reinit3(int *fst, ...) {
+ va_list va;
+ va_start(va, fst); // expected-note{{Initialized va_list}}
+ (void)va_arg(va, int);
+ va_end(va); // expected-note{{Ended va_list}}
+ va_start(va, fst); // expected-note{{Initialized va_list}}
+ (void)va_arg(va, int);
+ va_end(va); // expected-note{{Ended va_list}}
+ (void)va_arg(va, int); //expected-warning{{va_arg() is called on an uninitialized va_list}} expected-note{{va_arg() is called on an uninitialized va_list}}
+}
+
+void copyself(int fst, ...) {
+ va_list va;
+ va_start(va, fst); // expected-note{{Initialized va_list}}
+ va_copy(va, va); // expected-warning{{va_list 'va' is copied onto itself}} expected-note{{va_list 'va' is copied onto itself}}
+ va_end(va);
+} // no-warning
+
+void copyselfUninit(int fst, ...) {
+ va_list va;
+ va_copy(va, va); // expected-warning{{va_list 'va' is copied onto itself}} expected-note{{va_list 'va' is copied onto itself}}
+} // no-warning
+
+void copyOverwrite(int fst, ...) {
+ va_list va, va2;
+ va_start(va, fst); // expected-note{{Initialized va_list}}
+ va_copy(va, va2); // expected-warning{{Initialized va_list 'va' is overwritten by an uninitialized one}} expected-note{{Initialized va_list 'va' is overwritten by an uninitialized one}}
+} // no-warning
+
+void copyUnint(int fst, ...) {
+ va_list va, va2;
+ va_copy(va, va2); // expected-warning{{Uninitialized va_list is copied}} expected-note{{Uninitialized va_list is copied}}
+}
+
+void g1(int fst, ...) {
+ va_list va;
+ va_end(va); // expected-warning{{va_end() is called on an uninitialized va_list}} expected-note{{va_end() is called on an uninitialized va_list}}
+}
+
+void g2(int fst, ...) {
+ va_list va;
+ va_start(va, fst); // expected-note{{Initialized va_list}}
+ va_end(va); // expected-note{{Ended va_list}}
+ va_end(va); // expected-warning{{va_end() is called on an uninitialized va_list}} expected-note{{va_end() is called on an uninitialized va_list}}
+}
+
+void is_sink(int fst, ...) {
+ va_list va;
+ va_end(va); // expected-warning{{va_end() is called on an uninitialized va_list}} expected-note{{va_end() is called on an uninitialized va_list}}
+ *((volatile int *)0) = 1; //no-warning
+}
+
+// NOTE: this is invalid, as the man page of va_end requires that "Each invocation of va_start()
+// must be matched by a corresponding invocation of va_end() in the same function."
+void ends_arg(va_list arg) {
+ va_end(arg);
+} //no-warning
+
+void uses_arg(va_list arg) {
+ (void)va_arg(arg, int);
+} //no-warning
+
+// This is the same function as the previous one, but it is called in call_uses_arg2(),
+// and the warning is generated during the analysis of call_uses_arg2().
+void inlined_uses_arg(va_list arg) {
+ (void)va_arg(arg, int); //expected-warning{{va_arg() is called on an uninitialized va_list}} expected-note{{va_arg() is called on an uninitialized va_list}}
+}
+
+void call_inlined_uses_arg(int fst, ...) {
+ va_list va;
+ inlined_uses_arg(va); // expected-note{{Calling 'inlined_uses_arg'}}
+}
+
+void call_vprintf_ok(int isstring, ...) {
+ va_list va;
+ va_start(va, isstring);
+ vprintf(isstring ? "%s" : "%d", va);
+ va_end(va);
+} //no-warning
+
+void call_vprintf_bad(int isstring, ...) {
+ va_list va;
+ vprintf(isstring ? "%s" : "%d", va); //expected-warning{{Function 'vprintf' is called with an uninitialized va_list argument}} expected-note{{Function 'vprintf' is called with an uninitialized va_list argument}} expected-note{{Assuming 'isstring' is 0}} expected-note{{'?' condition is false}}
+}
+
+void call_vsprintf_bad(char *buffer, ...) {
+ va_list va;
+ va_start(va, buffer); // expected-note{{Initialized va_list}}
+ va_end(va); // expected-note{{Ended va_list}}
+ vsprintf(buffer, "%s %d %d %lf %03d", va); //expected-warning{{Function 'vsprintf' is called with an uninitialized va_list argument}} expected-note{{Function 'vsprintf' is called with an uninitialized va_list argument}}
+}
+
+void call_some_other_func(int n, ...) {
+ va_list va;
+ some_library_function(n, va);
+} //no-warning
+
diff --git a/test/Analysis/valist-unterminated.c b/test/Analysis/valist-unterminated.c
new file mode 100644
index 000000000000..63ee992b2894
--- /dev/null
+++ b/test/Analysis/valist-unterminated.c
@@ -0,0 +1,133 @@
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -analyze -analyzer-checker=core,alpha.valist.Unterminated,alpha.valist.CopyToSelf -analyzer-output=text -analyzer-store=region -verify %s
+
+#include "Inputs/system-header-simulator-for-valist.h"
+
+void f1(int fst, ...) {
+ va_list va;
+ va_start(va, fst); // expected-note{{Initialized va_list}}
+ return; // expected-warning{{Initialized va_list 'va' is leaked}} expected-note{{Initialized va_list 'va' is leaked}}
+}
+
+void f2(int fst, ...) {
+ va_list va;
+ va_start(va, fst); // expected-note{{Initialized va_list}}
+ va_end(va); // expected-note{{Ended va_list}}
+ va_start(va, fst); // expected-note{{Initialized va_list}}
+} // expected-warning{{Initialized va_list 'va' is leaked}} expected-note{{Initialized va_list 'va' is leaked}}}
+
+void f3(int fst, ...) {
+ va_list va, va2;
+ va_start(va, fst);
+ va_copy(va2, va); // expected-note{{Initialized va_list}}
+ va_end(va); // expected-warning{{Initialized va_list 'va2' is leaked}} expected-note{{Initialized va_list 'va2' is leaked}}
+}
+
+void f4(va_list *fst, ...) {
+ va_start(*fst, fst); // expected-note{{Initialized va_list}}
+ return; // expected-warning{{Initialized va_list is leaked}} expected-note{{Initialized va_list is leaked}}
+}
+
+void f5(va_list fst, ...) {
+ va_start(fst, fst);
+ //FIXME: this should cause a warning
+} // no-warning
+
+void f6(va_list *fst, ...) {
+ va_start(*fst, fst); // expected-note{{Initialized va_list}}
+ (void)va_arg(*fst, int);
+ //FIXME: this should NOT cause a warning
+ va_end(*fst); // expected-warning{{Initialized va_list is leaked}} expected-note{{Initialized va_list is leaked}}
+}
+
+void f7(int *fst, ...) {
+ va_list x;
+ va_list *y = &x;
+ va_start(*y,fst); // expected-note{{Initialized va_list}}
+} // expected-warning{{Initialized va_list 'x' is leaked}} expected-note{{Initialized va_list 'x' is leaked}}
+
+void f8(int *fst, ...) {
+ va_list x;
+ va_list *y = &x;
+ va_start(*y,fst);
+ va_end(x);
+} // no-warning
+
+void reinit(int *fst, ...) {
+ va_list va;
+ va_start(va, fst); // expected-note{{Initialized va_list}} expected-note{{Initialized va_list}}
+ va_start(va, fst); // expected-warning{{Initialized va_list 'va' is initialized again}} expected-note{{Initialized va_list 'va' is initialized again}}
+} // expected-warning{{Initialized va_list 'va' is leaked}} expected-note{{Initialized va_list 'va' is leaked}}
+
+void reinitOk(int *fst, ...) {
+ va_list va;
+ va_start(va, fst);
+ va_end(va);
+ va_start(va, fst);
+ va_end(va);
+} // no-warning
+
+void copyself(int fst, ...) {
+ va_list va;
+ va_start(va, fst); // expected-note{{Initialized va_list}}
+ va_copy(va, va); // expected-warning{{va_list 'va' is copied onto itself}} expected-note{{va_list 'va' is copied onto itself}}
+ va_end(va);
+} // no-warning
+
+void copyselfUninit(int fst, ...) {
+ va_list va;
+ va_copy(va, va); // expected-warning{{va_list 'va' is copied onto itself}} expected-note{{va_list 'va' is copied onto itself}}
+} // no-warning
+
+void copyOverwrite(int fst, ...) {
+ va_list va, va2;
+ va_start(va, fst); // expected-note{{Initialized va_list}}
+ va_copy(va, va2); // expected-warning{{Initialized va_list 'va' is overwritten by an uninitialized one}} expected-note{{Initialized va_list 'va' is overwritten by an uninitialized one}}
+} // no-warning
+
+//This only generates a warning for the valist.Uninitialized checker
+void copyUnint(int fst, ...) {
+ va_list va, va2;
+ va_copy(va, va2);
+} // no-warning
+
+void recopy(int fst, ...) {
+ va_list va, va2;
+ va_start(va, fst);
+ va_copy(va2, va); // expected-note{{Initialized va_list}}
+ va_copy(va2, va); // expected-warning{{Initialized va_list 'va2' is initialized again}} expected-note{{Initialized va_list 'va2' is initialized again}}
+ va_end(va);
+ va_end(va2);
+} //no-warning
+
+void doublemsg(int fst, ...) {
+ va_list va, va2;
+ va_start(va, fst), va_start(va2, fst); // expected-warning{{Initialized va_list 'va' is leaked}} expected-warning{{Initialized va_list 'va2' is leaked}} expected-note{{Initialized va_list}} expected-note{{Initialized va_list}} expected-note{{Initialized va_list}} expected-note{{Initialized va_list 'va' is leaked}}
+}
+
+void in_array(int fst, ...) {
+ va_list va_array[8];
+ va_start(va_array[3], fst); // expected-note{{Initialized va_list}}
+} // expected-warning{{Initialized va_list 'va_array[3]' is leaked}} expected-note{{Initialized va_list 'va_array[3]' is leaked}}
+
+struct containing_a_valist {
+ va_list vafield;
+ int foobar;
+};
+
+void in_struct(int fst, ...) {
+ struct containing_a_valist s;
+ va_start(s.vafield, fst); // expected-note{{Initialized va_list}}
+} // expected-warning{{Initialized va_list 's.vafield' is leaked}} expected-note{{Initialized va_list 's.vafield' is leaked}}
+
+void casting(int fst, ...) {
+ char mem[sizeof(va_list)];
+ va_start(*(va_list *) mem, fst); // expected-note{{Initialized va_list}}
+} // expected-warning{{Initialized va_list 'mem[0]' is leaked}} expected-note{{Initialized va_list 'mem[0]' is leaked}}
+
+
+void castingOk(int fst, ...) {
+ char mem[sizeof(va_list)];
+ va_start(*(va_list *) mem, fst);
+ va_end(*(va_list *) mem);
+} // no-warning
+
diff --git a/test/Analysis/virtualcall.cpp b/test/Analysis/virtualcall.cpp
index 8ce1d4103b9c..e42b898a0738 100644
--- a/test/Analysis/virtualcall.cpp
+++ b/test/Analysis/virtualcall.cpp
@@ -1,36 +1,79 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=alpha.cplusplus.VirtualCall -analyzer-store region -verify -std=c++11 %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=optin.cplusplus.VirtualCall -analyzer-store region -verify -std=c++11 %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=optin.cplusplus.VirtualCall -analyzer-store region -analyzer-config optin.cplusplus.VirtualCall:Interprocedural=true -DINTERPROCEDURAL=1 -verify -std=c++11 %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=optin.cplusplus.VirtualCall -analyzer-store region -analyzer-config optin.cplusplus.VirtualCall:PureOnly=true -DPUREONLY=1 -verify -std=c++11 %s
+
+/* When INTERPROCEDURAL is set, we expect diagnostics in all functions reachable
+ from a constructor or destructor. If it is not set, we expect diagnostics
+ only in the constructor or destructor.
+
+ When PUREONLY is set, we expect diagnostics only for calls to pure virtual
+ functions not to non-pure virtual functions.
+*/
class A {
public:
A();
+ A(int i);
+
~A() {};
- virtual int foo() = 0;
+ virtual int foo() = 0; // from Sema: expected-note {{'foo' declared here}}
virtual void bar() = 0;
void f() {
- foo(); // expected-warning{{Call pure virtual functions during construction or destruction may leads undefined behaviour}}
+ foo();
+#if INTERPROCEDURAL
+ // expected-warning-re@-2 {{{{^}}Call Path : foo <-- fCall to pure virtual function during construction has undefined behavior}}
+#endif
}
};
class B : public A {
public:
B() {
- foo(); // expected-warning{{Call virtual functions during construction or destruction will never go to a more derived class}}
+ foo();
+#if !PUREONLY
+#if INTERPROCEDURAL
+ // expected-warning-re@-3 {{{{^}}Call Path : fooCall to virtual function during construction will not dispatch to derived class}}
+#else
+ // expected-warning-re@-5 {{{{^}}Call to virtual function during construction will not dispatch to derived class}}
+#endif
+#endif
+
}
~B();
virtual int foo();
- virtual void bar() { foo(); } // expected-warning{{Call virtual functions during construction or destruction will never go to a more derived class}}
+ virtual void bar() { foo(); }
+#if INTERPROCEDURAL
+ // expected-warning-re@-2 {{{{^}}Call Path : foo <-- barCall to virtual function during destruction will not dispatch to derived class}}
+#endif
};
A::A() {
f();
}
+A::A(int i) {
+ foo(); // From Sema: expected-warning {{call to pure virtual member function 'foo' has undefined behavior}}
+#if INTERPROCEDURAL
+ // expected-warning-re@-2 {{{{^}}Call Path : fooCall to pure virtual function during construction has undefined behavior}}
+#else
+ // expected-warning-re@-4 {{{{^}}Call to pure virtual function during construction has undefined behavior}}
+#endif
+}
+
B::~B() {
this->B::foo(); // no-warning
this->B::bar();
- this->foo(); // expected-warning{{Call virtual functions during construction or destruction will never go to a more derived class}}
+ this->foo();
+#if !PUREONLY
+#if INTERPROCEDURAL
+ // expected-warning-re@-3 {{{{^}}Call Path : fooCall to virtual function during destruction will not dispatch to derived class}}
+#else
+ // expected-warning-re@-5 {{{{^}}Call to virtual function during destruction will not dispatch to derived class}}
+#endif
+#endif
+
}
class C : public B {
@@ -43,7 +86,14 @@ public:
};
C::C() {
- f(foo()); // expected-warning{{Call virtual functions during construction or destruction will never go to a more derived class}}
+ f(foo());
+#if !PUREONLY
+#if INTERPROCEDURAL
+ // expected-warning-re@-3 {{{{^}}Call Path : fooCall to virtual function during construction will not dispatch to derived class}}
+#else
+ // expected-warning-re@-5 {{{{^}}Call to virtual function during construction will not dispatch to derived class}}
+#endif
+#endif
}
class D : public B {
diff --git a/test/Analysis/virtualcall.h b/test/Analysis/virtualcall.h
index 9f7094dc63e9..c2ad8a6444c1 100644
--- a/test/Analysis/virtualcall.h
+++ b/test/Analysis/virtualcall.h
@@ -18,7 +18,15 @@ namespace header {
class A {
public:
A() {
- foo(); // expected-warning{{Call virtual functions during construction or destruction will never go to a more derived class}}
+ foo();
+#if !PUREONLY
+#if INTERPROCEDURAL
+ // expected-warning-re@-3 {{{{^}}Call Path : fooCall to virtual function during construction will not dispatch to derived class}}
+#else
+ // expected-warning-re@-5 {{{{^}}Call to virtual function during construction will not dispatch to derived class}}
+#endif
+#endif
+
}
virtual int foo();
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index f4be0adf14f8..46bf2ae213ae 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -9,6 +9,15 @@ endif ()
string(REPLACE ${CMAKE_CFG_INTDIR} ${LLVM_BUILD_MODE} CLANG_TOOLS_DIR ${LLVM_RUNTIME_OUTPUT_INTDIR})
+if(CLANG_BUILT_STANDALONE)
+ # Set HAVE_LIBZ according to recorded LLVM_ENABLE_ZLIB value. This
+ # value is forced to 0 if zlib was not found, so it is fine to use it
+ # instead of HAVE_LIBZ (not recorded).
+ if(LLVM_ENABLE_ZLIB)
+ set(HAVE_LIBZ 1)
+ endif()
+endif()
+
configure_lit_site_cfg(
${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg
@@ -29,6 +38,8 @@ list(APPEND CLANG_TEST_DEPS
clang-format
c-index-test diagtool
clang-tblgen
+ clang-offload-bundler
+ clang-import-test
)
if(CLANG_ENABLE_STATIC_ANALYZER)
diff --git a/test/CXX/basic/basic.lookup/basic.lookup.elab/p2.cpp b/test/CXX/basic/basic.lookup/basic.lookup.elab/p2.cpp
index 004d1e491f17..ca17ba50ac29 100644
--- a/test/CXX/basic/basic.lookup/basic.lookup.elab/p2.cpp
+++ b/test/CXX/basic/basic.lookup/basic.lookup.elab/p2.cpp
@@ -9,7 +9,7 @@ namespace test0 {
typedef int A; // expected-note {{declared here}}
int test() {
- struct A a; // expected-error {{elaborated type refers to a typedef}}
+ struct A a; // expected-error {{typedef 'A' cannot be referenced with a struct specifier}}
return a.foo;
}
}
@@ -18,7 +18,7 @@ namespace test0 {
template <class> class A; // expected-note {{declared here}}
int test() {
- struct A a; // expected-error {{elaborated type refers to a template}}
+ struct A a; // expected-error {{template 'A' cannot be referenced with a struct specifier}}
return a.foo;
}
}
diff --git a/test/CXX/basic/basic.stc/basic.stc.dynamic/basic.stc.dynamic.deallocation/p2.cpp b/test/CXX/basic/basic.stc/basic.stc.dynamic/basic.stc.dynamic.deallocation/p2.cpp
new file mode 100644
index 000000000000..9e3210c6650f
--- /dev/null
+++ b/test/CXX/basic/basic.stc/basic.stc.dynamic/basic.stc.dynamic.deallocation/p2.cpp
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -std=c++1z -fsized-deallocation -fexceptions -verify %s
+
+using size_t = decltype(sizeof(0));
+
+namespace std { enum class align_val_t : size_t {}; }
+
+// p2 says "A template instance is never a usual deallocation function,
+// regardless of its signature." We (and every other implementation) assume
+// this means "A function template specialization [...]"
+template<typename...Ts> struct A {
+ void *operator new(size_t);
+ void operator delete(void*, Ts...) = delete; // expected-note 4{{deleted}}
+};
+
+auto *a1 = new A<>; // expected-error {{deleted}}
+auto *a2 = new A<size_t>; // expected-error {{deleted}}
+auto *a3 = new A<std::align_val_t>; // expected-error {{deleted}}
+auto *a4 = new A<size_t, std::align_val_t>; // expected-error {{deleted}}
+auto *a5 = new A<std::align_val_t, size_t>; // ok, not usual
diff --git a/test/CXX/basic/basic.stc/basic.stc.dynamic/p2-noexceptions.cpp b/test/CXX/basic/basic.stc/basic.stc.dynamic/p2-noexceptions.cpp
index 9819ea0293f6..41aeeee73eda 100644
--- a/test/CXX/basic/basic.stc/basic.stc.dynamic/p2-noexceptions.cpp
+++ b/test/CXX/basic/basic.stc/basic.stc.dynamic/p2-noexceptions.cpp
@@ -1,3 +1,5 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
// RUN: %clang_cc1 -fsyntax-only -verify %s
// expected-no-diagnostics
namespace std {
diff --git a/test/CXX/basic/basic.stc/basic.stc.dynamic/p2.cpp b/test/CXX/basic/basic.stc/basic.stc.dynamic/p2.cpp
index 47b51585556f..257aca1c3f7b 100644
--- a/test/CXX/basic/basic.stc/basic.stc.dynamic/p2.cpp
+++ b/test/CXX/basic/basic.stc/basic.stc.dynamic/p2.cpp
@@ -1,3 +1,5 @@
+// RUN: %clang_cc1 -fsyntax-only -fexceptions -fcxx-exceptions -verify -std=c++98 %s
+// RUN: %clang_cc1 -fsyntax-only -fexceptions -fcxx-exceptions -verify -std=c++11 %s
// RUN: %clang_cc1 -fsyntax-only -fexceptions -fcxx-exceptions -verify %s
int *use_new(int N) {
if (N == 1)
@@ -19,10 +21,21 @@ namespace std {
typedef __SIZE_TYPE__ size_t;
}
-void* operator new(std::size_t) throw(std::bad_alloc); // expected-note{{previous declaration}}
+void* operator new(std::size_t) throw(std::bad_alloc);
+#if __cplusplus < 201103L
+// expected-note@-2 {{previous declaration}}
+#endif
void* operator new[](std::size_t) throw(std::bad_alloc);
void operator delete(void*) throw(); // expected-note{{previous declaration}}
void operator delete[](void*) throw();
-void* operator new(std::size_t); // expected-warning{{'operator new' is missing exception specification 'throw(std::bad_alloc)'}}
-void operator delete(void*); // expected-warning{{'operator delete' is missing exception specification 'throw()'}}
+void* operator new(std::size_t);
+#if __cplusplus < 201103L
+// expected-warning@-2 {{'operator new' is missing exception specification 'throw(std::bad_alloc)'}}
+#endif
+void operator delete(void*);
+#if __cplusplus < 201103L
+// expected-warning@-2 {{'operator delete' is missing exception specification 'throw()'}}
+#else
+// expected-warning@-4 {{previously declared with an explicit exception specification redeclared with an implicit}}
+#endif
diff --git a/test/CXX/class.access/class.friend/p1.cpp b/test/CXX/class.access/class.friend/p1.cpp
index 54069b6b87be..b6a1bcdab926 100644
--- a/test/CXX/class.access/class.friend/p1.cpp
+++ b/test/CXX/class.access/class.friend/p1.cpp
@@ -1,3 +1,6 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++14 %s
// RUN: %clang_cc1 -fsyntax-only -verify %s
// C++'0x [class.friend] p1:
@@ -216,9 +219,17 @@ namespace test6 {
struct A {};
struct B {
- friend A::A();
+ friend
+#if __cplusplus >= 201103L
+ constexpr
+#endif
+ A::A();
friend A::~A();
- friend A &A::operator=(const A&);
+ friend
+#if __cplusplus >= 201402L
+ constexpr
+#endif
+ A &A::operator=(const A&);
};
}
@@ -233,7 +244,11 @@ namespace test7 {
class A {
friend void X<int>::foo();
friend X<int>::X();
- friend X<int>::X(const X&);
+ friend
+#if __cplusplus >= 201103L
+ constexpr
+#endif
+ X<int>::X(const X&);
private:
A(); // expected-note 2 {{declared private here}}
diff --git a/test/CXX/class.access/p4.cpp b/test/CXX/class.access/p4.cpp
index 435b09920df6..f010ad5a2cb3 100644
--- a/test/CXX/class.access/p4.cpp
+++ b/test/CXX/class.access/p4.cpp
@@ -1,3 +1,5 @@
+// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++98 %s
+// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++11 %s
// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify %s
// C++0x [class.access]p4:
@@ -88,7 +90,7 @@ namespace test1 {
namespace test2 {
class A {
private:
- A(); // expected-note 3 {{declared private here}}
+ A(); // expected-note 1+{{declared private here}}
static A foo;
};
@@ -96,6 +98,7 @@ namespace test2 {
A a; // expected-error {{calling a private constructor}}
A A::foo; // okay
+#if __cplusplus < 201103L
class B : A { }; // expected-error {{base class 'test2::A' has private default constructor}}
B b; // expected-note{{implicit default constructor}}
@@ -106,6 +109,19 @@ namespace test2 {
class D : C { }; // expected-error {{inherited virtual base class 'test2::A' has private default constructor}}
D d; // expected-note{{implicit default constructor}}
+#else
+ class B : A { }; // expected-note {{base class 'test2::A' has an inaccessible default constructor}}
+ B b; // expected-error {{call to implicitly-deleted default constructor}}
+
+ // FIXME: Do a better job of explaining how we get here from class D.
+ class C : virtual A { // expected-note {{default constructor of 'D' is implicitly deleted because base class 'test2::A' has an inaccessible default constructor}}
+ public:
+ C();
+ };
+
+ class D : C { };
+ D d; // expected-error {{call to implicitly-deleted default constructor}}
+#endif
}
// Implicit destructor calls.
@@ -123,6 +139,7 @@ namespace test3 {
A local; // expected-error {{variable of type 'test3::A' has private destructor}}
}
+#if __cplusplus < 201103L
template <unsigned N> class Base { ~Base(); }; // expected-note 14 {{declared private here}}
class Base2 : virtual Base<2> { ~Base2(); }; // expected-note 3 {{declared private here}} \
// expected-error {{base class 'Base<2>' has private destructor}}
@@ -152,6 +169,33 @@ namespace test3 {
{};
Derived3 d3; // expected-note {{implicit default constructor}}\
// expected-note{{implicit destructor}}}
+#else
+ template <unsigned N> class Base { ~Base(); }; // expected-note 4{{declared private here}}
+ class Base2 : virtual Base<2> { ~Base2(); }; // expected-note 1{{declared private here}}
+ class Base3 : virtual Base<3> { public: ~Base3(); };
+
+ // These don't cause diagnostics because we don't need the destructor.
+ class Derived0 : Base<0> { ~Derived0(); };
+ class Derived1 : Base<1> { };
+
+ class Derived2 : // expected-error {{inherited virtual base class 'Base<2>' has private destructor}} \
+ // expected-error {{inherited virtual base class 'Base<3>' has private destructor}}
+ Base<0>, // expected-error {{base class 'Base<0>' has private destructor}}
+ virtual Base<1>, // expected-error {{base class 'Base<1>' has private destructor}}
+ Base2, // expected-error {{base class 'test3::Base2' has private destructor}}
+ virtual Base3
+ {
+ ~Derived2() {}
+ };
+
+ class Derived3 :
+ Base<0>, // expected-note {{deleted because base class 'Base<0>' has an inaccessible destructor}}
+ virtual Base<1>,
+ Base2,
+ virtual Base3
+ {};
+ Derived3 d3; // expected-error {{implicitly-deleted default constructor}}
+#endif
}
// Conversion functions.
@@ -201,9 +245,13 @@ namespace test4 {
// Implicit copy assignment operator uses.
namespace test5 {
class A {
- void operator=(const A &); // expected-note 2 {{implicitly declared private here}}
+ void operator=(const A &);
+#if __cplusplus < 201103L
+ // expected-note@-2 2{{implicitly declared private here}}
+#endif
};
+#if __cplusplus < 201103L
class Test1 { A a; }; // expected-error {{private member}}
void test1() {
Test1 a;
@@ -215,15 +263,32 @@ namespace test5 {
Test2 a;
a = Test2(); // expected-note{{implicit copy}}
}
+#else
+ class Test1 { A a; }; // expected-note {{because field 'a' has an inaccessible copy assignment operator}}
+ void test1() {
+ Test1 a;
+ a = Test1(); // expected-error {{copy assignment operator is implicitly deleted}}
+ }
+
+ class Test2 : A {}; // expected-note {{because base class 'test5::A' has an inaccessible copy assignment operator}}
+ void test2() {
+ Test2 a;
+ a = Test2(); // expected-error {{copy assignment operator is implicitly deleted}}
+ }
+#endif
}
// Implicit copy constructor uses.
namespace test6 {
class A {
public: A();
- private: A(const A &); // expected-note 2 {{declared private here}}
+ private: A(const A &);
+#if __cplusplus < 201103L
+ // expected-note@-2 2{{declared private here}}
+#endif
};
+#if __cplusplus < 201103L
class Test1 { A a; }; // expected-error {{field of type 'test6::A' has private copy constructor}}
void test1(const Test1 &t) {
Test1 a = t; // expected-note{{implicit copy}}
@@ -233,6 +298,17 @@ namespace test6 {
void test2(const Test2 &t) {
Test2 a = t; // expected-note{{implicit copy}}
}
+#else
+ class Test1 { A a; }; // expected-note {{field 'a' has an inaccessible copy constructor}}
+ void test1(const Test1 &t) {
+ Test1 a = t; // expected-error{{implicitly-deleted}}
+ }
+
+ class Test2 : A {}; // expected-note {{base class 'test6::A' has an inaccessible copy constructor}}
+ void test2(const Test2 &t) {
+ Test2 a = t; // expected-error{{implicitly-deleted}}
+ }
+#endif
}
// Redeclaration lookups are not accesses.
diff --git a/test/CXX/class.derived/class.abstract/p16.cpp b/test/CXX/class.derived/class.abstract/p16.cpp
index 2053218ca5b5..29adbccac479 100644
--- a/test/CXX/class.derived/class.abstract/p16.cpp
+++ b/test/CXX/class.derived/class.abstract/p16.cpp
@@ -31,12 +31,20 @@ private:
D &operator=(D&&) = default;
virtual ~D(); // expected-note 2{{here}}
};
-struct E : D {}; // expected-error {{deleted function '~E' cannot override a non-deleted function}} \
- // expected-error {{deleted function 'operator=' cannot override a non-deleted function}}
+struct E : D {};
+// expected-error@-1 {{deleted function '~E' cannot override a non-deleted function}}
+// expected-note@-2 {{destructor of 'E' is implicitly deleted because base class 'D' has an inaccessible destructor}}
+// expected-error@-3 {{deleted function 'operator=' cannot override a non-deleted function}}
+// expected-note@-4 {{copy assignment operator of 'E' is implicitly deleted because base class 'D' has an inaccessible copy assignment operator}}
struct F : D {};
-struct G : D {}; // expected-error {{deleted function '~G' cannot override a non-deleted function}}
- // expected-error@-1 {{deleted function 'operator=' cannot override a non-deleted function}}
+struct G : D {};
+// expected-error@-1 {{deleted function '~G' cannot override a non-deleted function}}
+// expected-note@-2 {{move assignment operator of 'G' is implicitly deleted because base class 'D' has an inaccessible move assignment operator}}
+// expected-error@-3 {{deleted function 'operator=' cannot override a non-deleted function}}
+// expected-note@-4 {{destructor of 'G' is implicitly deleted because base class 'D' has an inaccessible destructor}}
struct H : D {
- H &operator=(H&&) = default; // expected-error {{deleted function 'operator=' cannot override a non-deleted function}}
+ H &operator=(H&&) = default;
+ // expected-error@-1 {{deleted function 'operator=' cannot override a non-deleted function}}
+ // expected-note@-3 {{move assignment operator of 'H' is implicitly deleted because base class 'D' has an inaccessible move assignment operator}}
~H();
};
diff --git a/test/CXX/class.derived/class.abstract/p2.cpp b/test/CXX/class.derived/class.abstract/p2.cpp
new file mode 100644
index 000000000000..713a5269f143
--- /dev/null
+++ b/test/CXX/class.derived/class.abstract/p2.cpp
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -std=c++1z -verify %s
+
+// no objects of an abstract class can be created except as subobjects of a
+// class derived from it
+
+struct A {
+ A() {}
+ A(int) : A() {} // ok
+
+ virtual void f() = 0; // expected-note 1+{{unimplemented}}
+};
+
+void f(A &&a);
+
+void g() {
+ f({}); // expected-error {{abstract class}}
+ f({0}); // expected-error {{abstract class}}
+ f(0); // expected-error {{abstract class}}
+}
+
+struct B : A {
+ B() : A() {} // ok
+};
diff --git a/test/CXX/class.derived/class.abstract/p3.cpp b/test/CXX/class.derived/class.abstract/p3.cpp
new file mode 100644
index 000000000000..ad5b87478835
--- /dev/null
+++ b/test/CXX/class.derived/class.abstract/p3.cpp
@@ -0,0 +1,97 @@
+// RUN: %clang_cc1 -std=c++1z -verify %s
+
+struct A {
+ A() {}
+ A(int) : A() {} // ok
+
+ virtual void f() = 0; // expected-note 1+{{unimplemented}}
+};
+
+template<typename> struct SecretlyAbstract {
+ SecretlyAbstract();
+ SecretlyAbstract(int);
+ virtual void f() = 0; // expected-note 1+{{unimplemented}}
+};
+using B = SecretlyAbstract<int>;
+using C = SecretlyAbstract<float>;
+using D = SecretlyAbstract<char>[1];
+
+B b; // expected-error {{abstract class}}
+D d; // expected-error {{abstract class}}
+
+template<int> struct N;
+
+// Note: C is not instantiated anywhere in this file, so we never discover that
+// it is in fact abstract. The C++ standard suggests that we need to
+// instantiate in all cases where abstractness could affect the validity of a
+// program, but that breaks a *lot* of code, so we don't do that.
+//
+// FIXME: Once DR1640 is resolved, remove the check on forming an abstract
+// array type entirely. The only restriction we need is that you can't create
+// an object of abstract (most-derived) type.
+
+
+// An abstract class shall not be used
+
+// - as a parameter type
+void f(A&);
+void f(A); // expected-error {{abstract class}}
+void f(A[1]); // expected-error {{abstract class}}
+void f(B); // expected-error {{abstract class}}
+void f(B[1]); // expected-error {{abstract class}}
+void f(C);
+void f(C[1]);
+void f(D); // expected-error {{abstract class}}
+void f(D[1]); // expected-error {{abstract class}}
+
+// - as a function return type
+A &f(N<0>);
+A *f(N<1>);
+A f(N<2>); // expected-error {{abstract class}}
+A (&f(N<3>))[2]; // expected-error {{abstract class}}
+B f(N<4>); // expected-error {{abstract class}}
+B (&f(N<5>))[2]; // expected-error {{abstract class}}
+C f(N<6>);
+C (&f(N<7>))[2];
+
+// - as the type of an explicit conversion
+void g(A&&);
+void h() {
+ A(); // expected-error {{abstract class}}
+ A(0); // expected-error {{abstract class}}
+ A{}; // expected-error {{abstract class}}
+ A{0}; // expected-error {{abstract class}}
+ (A)(0); // expected-error {{abstract class}}
+ (A){}; // expected-error {{abstract class}}
+ (A){0}; // expected-error {{abstract class}}
+
+ D(); // expected-error {{array type}}
+ D{}; // expected-error {{abstract class}}
+ D{0}; // expected-error {{abstract class}}
+ (D){}; // expected-error {{abstract class}}
+ (D){0}; // expected-error {{abstract class}}
+}
+
+template<typename T> void t(T); // expected-note 2{{abstract class}}
+void i(A &a, B &b, C &c, D &d) {
+ // FIXME: These should be handled consistently. We currently reject the first
+ // two early because we (probably incorrectly, depending on dr1640) take
+ // abstractness into account in forming implicit conversion sequences.
+ t(a); // expected-error {{no matching function}}
+ t(b); // expected-error {{no matching function}}
+ t(c); // expected-error {{allocating an object of abstract class type}}
+ t(d); // ok, decays to pointer
+}
+
+struct E : A {
+ E() : A() {} // ok
+ E(int n) : A( A(n) ) {} // expected-error {{abstract class}}
+};
+
+namespace std {
+ template<typename T> struct initializer_list {
+ const T *begin, *end;
+ initializer_list();
+ };
+}
+std::initializer_list<A> ila = {1, 2, 3, 4}; // expected-error {{abstract class}}
diff --git a/test/CXX/class/class.union/p1.cpp b/test/CXX/class/class.union/p1.cpp
index 439cc9cec8da..84ce1c991533 100644
--- a/test/CXX/class/class.union/p1.cpp
+++ b/test/CXX/class/class.union/p1.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s
void abort() __attribute__((noreturn));
diff --git a/test/CXX/conv/conv.fctptr/p1.cpp b/test/CXX/conv/conv.fctptr/p1.cpp
new file mode 100644
index 000000000000..be9c050af51e
--- /dev/null
+++ b/test/CXX/conv/conv.fctptr/p1.cpp
@@ -0,0 +1,43 @@
+// RUN: %clang_cc1 -std=c++1z -verify %s -triple x86_64-unknown-unknown
+
+struct S;
+
+typedef void Nothrow() noexcept;
+typedef void Throw();
+
+Nothrow *a;
+Throw *b;
+Nothrow S::*c;
+Throw S::*d;
+
+void test() {
+ a = b; // expected-error {{assigning to 'Nothrow *' (aka 'void (*)() noexcept') from incompatible type 'Throw *' (aka 'void (*)()'): different exception specifications}}
+ b = a;
+ c = d; // expected-error {{assigning to 'Nothrow S::*' from incompatible type 'Throw S::*': different exception specifications}}
+ d = c;
+
+ // Function pointer conversions do not combine properly with qualification conversions.
+ // FIXME: This seems like a defect.
+ Nothrow *const *pa = b; // expected-error {{cannot initialize}}
+ Throw *const *pb = a; // expected-error {{cannot initialize}}
+ Nothrow *const S::*pc = d; // expected-error {{cannot initialize}}
+ Throw *const S::*pd = c; // expected-error {{cannot initialize}}
+}
+
+// ... The result is a pointer to the function.
+void f() noexcept;
+constexpr void (*p)() = &f;
+static_assert(f == p);
+
+struct S { void f() noexcept; };
+constexpr void (S::*q)() = &S::f;
+static_assert(q == &S::f);
+
+
+namespace std_example {
+ void (*p)();
+ void (**pp)() noexcept = &p; // expected-error {{cannot initialize a variable of type 'void (**)() noexcept' with an rvalue of type 'void (**)()'}}
+
+ struct S { typedef void (*p)(); operator p(); }; // expected-note {{candidate}}
+ void (*q)() noexcept = S(); // expected-error {{no viable conversion from 'std_example::S' to 'void (*)() noexcept'}}
+}
diff --git a/test/CXX/cpp/cpp.predefined/p1.cpp b/test/CXX/cpp/cpp.predefined/p1.cpp
new file mode 100644
index 000000000000..c0dcbd54f387
--- /dev/null
+++ b/test/CXX/cpp/cpp.predefined/p1.cpp
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -std=c++1z %s -verify -triple x86_64-linux-gnu -DALIGN=16
+// RUN: %clang_cc1 -std=c++1z %s -verify -fnew-alignment=2 -DALIGN=2
+// RUN: %clang_cc1 -std=c++1z %s -verify -fnew-alignment=256 -DALIGN=256
+
+// expected-no-diagnostics
+
+#if ALIGN != __STDCPP_DEFAULT_NEW_ALIGNMENT__
+#error wrong value for __STDCPP_DEFAULT_NEW_ALIGNMENT__
+#endif
diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.def/p7.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.def/p7.cpp
index f92362380a1c..39bed7db7ab3 100644
--- a/test/CXX/dcl.dcl/basic.namespace/namespace.def/p7.cpp
+++ b/test/CXX/dcl.dcl/basic.namespace/namespace.def/p7.cpp
@@ -1,13 +1,18 @@
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
+// FIXME: We should probably suppress the warning on reopening an inline
+// namespace without the inline keyword if it's not the first opening of the
+// namespace in the file, because there's no risk of the inlineness differing
+// across TUs in that case.
+
namespace NIL {} // expected-note {{previous definition}}
inline namespace NIL {} // expected-error {{cannot be reopened as inline}}
inline namespace IL {} // expected-note {{previous definition}}
-namespace IL {} // expected-warning{{inline namespace cannot be reopened as a non-inline namespace}}
+namespace IL {} // expected-warning{{inline namespace reopened as a non-inline namespace}}
namespace {} // expected-note {{previous definition}}
inline namespace {} // expected-error {{cannot be reopened as inline}}
namespace X {
inline namespace {} // expected-note {{previous definition}}
- namespace {} // expected-warning {{cannot be reopened as a non-inline namespace}}
+ namespace {} // expected-warning {{inline namespace reopened as a non-inline namespace}}
}
diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp
index 6c63f061ab0f..0ea4eeb1e9b0 100644
--- a/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp
+++ b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp
@@ -1,5 +1,6 @@
// RUN: %clang_cc1 -fsyntax-only -std=c++98 -verify %s
// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify %s
// RUN: not %clang_cc1 -fsyntax-only -std=c++98 -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck --check-prefix=CXX98 %s
// RUN: not %clang_cc1 -fsyntax-only -std=c++11 -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck --check-prefix=CXX11 %s
// C++0x N2914.
@@ -44,10 +45,158 @@ void f() {
#endif
}
-template <typename T>
-struct PR21933 : T {
- static void StaticFun() { using T::member; } // expected-error{{using declaration cannot refer to class member}}
-};
+namespace PR21933 {
+ struct A { int member; };
+ struct B { static int member; };
+ enum C { member };
+
+ template <typename T>
+ struct X {
+ static void StaticFun() {
+ using T::member; // expected-error 2{{class member}} expected-note {{use a reference instead}}
+#if __cplusplus < 201103L
+ // expected-error@-2 {{cannot be used prior to '::'}}
+#endif
+ (void)member;
+ }
+ };
+ template<typename T>
+ struct Y : T {
+ static void StaticFun() {
+ using T::member; // expected-error 2{{class member}} expected-note {{use a reference instead}}
+ (void)member;
+ }
+ };
+
+ void f() {
+ X<A>::StaticFun(); // expected-note {{instantiation of}}
+ X<B>::StaticFun(); // expected-note {{instantiation of}}
+ X<C>::StaticFun();
+#if __cplusplus < 201103L
+ // expected-note@-2 {{instantiation of}}
+#endif
+ Y<A>::StaticFun(); // expected-note {{instantiation of}}
+ Y<B>::StaticFun(); // expected-note {{instantiation of}}
+ }
+
+ template<typename T, typename U> void value_vs_value() {
+ using T::a; // expected-note {{previous}}
+#if __cplusplus < 201103L
+ // expected-error@-2 {{cannot be used prior to '::'}}
+#endif
+ extern int a(); // expected-error {{different kind of symbol}}
+ a();
+
+ extern int b(); // expected-note {{previous}}
+ using T::b; // expected-error {{different kind of symbol}}
+ b();
+
+ using T::c; // expected-note {{previous}}
+ using U::c; // expected-error-re {{redefinition of 'c'{{$}}}}
+ c();
+ }
+
+ template<typename T, typename U> void value_vs_type() {
+ using T::Xt; // expected-note {{previous}}
+ typedef struct {} Xt; // expected-error {{different kind of symbol}}
+ (void)Xt;
+
+ using T::Xs; // expected-note {{hidden by}}
+ struct Xs {};
+ (void)Xs;
+ Xs xs; // expected-error {{must use 'struct'}}
+
+ using T::Xe; // expected-note {{hidden by}}
+ enum Xe {};
+ (void)Xe;
+ Xe xe; // expected-error {{must use 'enum'}}
+
+ typedef struct {} Yt; // expected-note {{candidate}}
+ using T::Yt; // eypected-error {{different kind of symbol}} expected-note {{candidate}}
+ Yt yt; // expected-error {{ambiguous}}
+
+ struct Ys {};
+ using T::Ys; // expected-note {{hidden by}}
+ (void)Ys;
+ Ys ys; // expected-error {{must use 'struct'}}
+
+ enum Ye {};
+ using T::Ye; // expected-note {{hidden by}}
+ Ye ye; // expected-error {{must use 'enum'}}
+ }
+
+ template<typename T> void type() {
+ // Must be a class member because T:: can only name a class or enum,
+ // and an enum cannot have a type member.
+ using typename T::X; // expected-error {{cannot refer to class member}}
+ }
+
+ namespace N1 { enum E { a, b, c }; }
+ namespace N2 { enum E { a, b, c }; }
+ void g() { value_vs_value<N1::E, N2::E>(); }
+#if __cplusplus < 201103L
+ // expected-note@-2 {{in instantiation of}}
+#endif
+
+#if __cplusplus >= 201402L
+ namespace partial_substitute {
+ template<typename T> auto f() {
+ return [](auto x) {
+ using A = typename T::template U<decltype(x)>;
+ using A::E::e;
+ struct S : A {
+ using A::f;
+ using typename A::type;
+ type f(int) { return e; }
+ };
+ return S();
+ };
+ }
+ enum Enum { e };
+ struct X {
+ template<typename T> struct U {
+ int f(int, int);
+ using type = int;
+ using E = Enum;
+ };
+ };
+ int test() {
+ auto s = f<X>()(0);
+ return s.f(0) + s.f(0, 0);
+ }
+
+ template<typename T, typename U> auto g() {
+ return [](auto x) {
+ using X = decltype(x);
+ struct S : T::template Q<X>, U::template Q<X> {
+ using T::template Q<X>::f;
+ using U::template Q<X>::f;
+ void h() { f(); }
+ void h(int n) { f(n); }
+ };
+ return S();
+ };
+ }
+ struct A { template<typename> struct Q { int f(); }; };
+ struct B { template<typename> struct Q { int f(int); }; };
+ int test2() {
+ auto s = g<A, B>()(0);
+ s.f();
+ s.f(0);
+ s.h();
+ s.h(0);
+ }
+ }
+#endif
+
+ template<typename T, typename U> struct RepeatedMember : T, U {
+ // FIXME: This is the wrong error: we should complain that a member type
+ // cannot be redeclared at class scope.
+ using typename T::type; // expected-note {{candidate}}
+ using typename U::type; // expected-note {{candidate}}
+ type x; // expected-error {{ambiguous}}
+ };
+}
struct S {
static int n;
diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p2-0x.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p2-0x.cpp
index 027104151ac6..f3e79c0aae44 100644
--- a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p2-0x.cpp
+++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p2-0x.cpp
@@ -2,18 +2,18 @@
struct A { typedef int type; };
template<typename T> using X = A; // expected-note {{declared here}}
-struct X<int>* p2; // expected-error {{elaborated type refers to a type alias template}}
+struct X<int>* p2; // expected-error {{type alias template 'X' cannot be referenced with a struct specifier}}
template<typename T> using Id = T; // expected-note {{declared here}}
template<template<typename> class F>
struct Y {
- struct F<int> i; // expected-error {{elaborated type refers to a type alias template}}
+ struct F<int> i; // expected-error {{type alias template 'Id' cannot be referenced with a struct specifier}}
typename F<A>::type j; // ok
// FIXME: don't produce the diagnostic both for the definition and the instantiation.
template<typename T> using U = F<char>; // expected-note 2{{declared here}}
- struct Y<F>::template U<char> k; // expected-error 2{{elaborated type refers to a type alias template}}
+ struct Y<F>::template U<char> k; // expected-error 2{{type alias template 'U' cannot be referenced with a struct specifier}}
typename Y<F>::template U<char> l; // ok
};
template struct Y<Id>; // expected-note {{requested here}}
diff --git a/test/CXX/dcl.decl/dcl.decomp/p2.cpp b/test/CXX/dcl.decl/dcl.decomp/p2.cpp
new file mode 100644
index 000000000000..211719a7e9c6
--- /dev/null
+++ b/test/CXX/dcl.decl/dcl.decomp/p2.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -std=c++1z -verify %s -Wpedantic
+
+struct X {
+ X(int);
+ X(const X&) = delete;
+};
+
+int array() {
+ static int arr[3] = {};
+ auto [a, b, c] = arr;
+ static_assert(&a != &arr[0]);
+
+ using I3 = int[3];
+ auto [a2, b2, c2] = I3{1, 2, 3};
+
+ using X3 = X[3];
+ auto [a3, b3, c3] = X3{1, 2, 3};
+
+ auto &[d, e] = arr; // expected-error {{type 'int [3]' decomposes into 3 elements, but only 2 names were provided}}
+ auto &[f, g, h, i] = arr; // expected-error {{type 'int [3]' decomposes into 3 elements, but 4 names were provided}}
+
+ auto &[r0, r1, r2] = arr;
+ const auto &[cr0, cr1, cr2] = arr;
+
+ static_assert(&arr[0] == &r0);
+ static_assert(&arr[0] == &cr0);
+
+ using T = int;
+ using T = decltype(r0);
+ using U = const int;
+ using U = decltype(cr0);
+
+ return r1 + cr2;
+}
diff --git a/test/CXX/dcl.decl/dcl.decomp/p3.cpp b/test/CXX/dcl.decl/dcl.decomp/p3.cpp
new file mode 100644
index 000000000000..b7092e3af023
--- /dev/null
+++ b/test/CXX/dcl.decl/dcl.decomp/p3.cpp
@@ -0,0 +1,232 @@
+// RUN: %clang_cc1 -std=c++1z -verify %s
+
+using size_t = decltype(sizeof(0));
+
+struct A { int x, y; };
+struct B { int x, y; };
+
+void no_tuple_size_1() { auto [x, y] = A(); } // ok, decompose elementwise
+
+namespace std { template<typename T> struct tuple_size; }
+void no_tuple_size_2() { auto [x, y] = A(); } // ok, decompose elementwise
+
+struct Bad1 { int a, b; };
+template<> struct std::tuple_size<Bad1> {};
+void no_tuple_size_3() { auto [x, y] = Bad1(); } // expected-error {{cannot decompose this type; 'std::tuple_size<Bad1>::value' is not a valid integral constant expression}}
+
+struct Bad2 {};
+template<> struct std::tuple_size<Bad2> { const int value = 5; };
+void no_tuple_size_4() { auto [x, y] = Bad2(); } // expected-error {{cannot decompose this type; 'std::tuple_size<Bad2>::value' is not a valid integral constant expression}}
+
+template<> struct std::tuple_size<A> { static const int value = 3; };
+template<> struct std::tuple_size<B> { enum { value = 3 }; };
+
+void no_get_1() {
+ {
+ auto [a0, a1] = A(); // expected-error {{decomposes into 3 elements}}
+ auto [b0, b1] = B(); // expected-error {{decomposes into 3 elements}}
+ }
+ auto [a0, a1, a2] = A(); // expected-error {{undeclared identifier 'get'}} expected-note {{in implicit initialization of binding declaration 'a0'}}
+}
+
+int get(A);
+
+void no_get_2() {
+ // FIXME: This diagnostic is not great.
+ auto [a0, a1, a2] = A(); // expected-error {{undeclared identifier 'get'}} expected-note {{in implicit initialization of binding declaration 'a0'}}
+}
+
+template<int> float &get(A);
+
+void no_tuple_element_1() {
+ auto [a0, a1, a2] = A(); // expected-error-re {{'std::tuple_element<0U{{L*}}, A>::type' does not name a type}} expected-note {{in implicit}}
+}
+
+namespace std { template<size_t, typename> struct tuple_element; } // expected-note 2{{here}}
+
+void no_tuple_element_2() {
+ auto [a0, a1, a2] = A(); // expected-error {{implicit instantiation of undefined template 'std::tuple_element<0, A>'}} expected-note {{in implicit}}
+}
+
+template<> struct std::tuple_element<0, A> { typedef float type; };
+
+void no_tuple_element_3() {
+ auto [a0, a1, a2] = A(); // expected-error {{implicit instantiation of undefined template 'std::tuple_element<1, A>'}} expected-note {{in implicit}}
+}
+
+template<> struct std::tuple_element<1, A> { typedef float &type; };
+template<> struct std::tuple_element<2, A> { typedef const float &type; };
+
+template<int N> auto get(B) -> int (&)[N + 1];
+template<int N> struct std::tuple_element<N, B> { typedef int type[N +1 ]; };
+
+template<typename T> struct std::tuple_size<const T> : std::tuple_size<T> {};
+template<size_t N, typename T> struct std::tuple_element<N, const T> {
+ typedef const typename std::tuple_element<N, T>::type type;
+};
+
+void referenced_type() {
+ auto [a0, a1, a2] = A();
+ auto [b0, b1, b2] = B();
+
+ A a;
+ B b;
+ auto &[ar0, ar1, ar2] = a;
+ auto &[br0, br1, br2] = b;
+
+ auto &&[arr0, arr1, arr2] = A();
+ auto &&[brr0, brr1, brr2] = B();
+
+ const auto &[acr0, acr1, acr2] = A();
+ const auto &[bcr0, bcr1, bcr2] = B();
+
+
+ using Float = float;
+ using Float = decltype(a0);
+ using Float = decltype(ar0);
+ using Float = decltype(arr0);
+
+ using ConstFloat = const float;
+ using ConstFloat = decltype(acr0);
+
+ using FloatRef = float&;
+ using FloatRef = decltype(a1);
+ using FloatRef = decltype(ar1);
+ using FloatRef = decltype(arr1);
+ using FloatRef = decltype(acr1);
+
+ using ConstFloatRef = const float&;
+ using ConstFloatRef = decltype(a2);
+ using ConstFloatRef = decltype(ar2);
+ using ConstFloatRef = decltype(arr2);
+ using ConstFloatRef = decltype(acr2);
+
+
+ using Int1 = int[1];
+ using Int1 = decltype(b0);
+ using Int1 = decltype(br0);
+ using Int1 = decltype(brr0);
+
+ using ConstInt1 = const int[1];
+ using ConstInt1 = decltype(bcr0);
+
+ using Int2 = int[2];
+ using Int2 = decltype(b1);
+ using Int2 = decltype(br1);
+ using Int2 = decltype(brr1);
+
+ using ConstInt2 = const int[2];
+ using ConstInt2 = decltype(bcr1);
+
+ using Int3 = int[3];
+ using Int3 = decltype(b2);
+ using Int3 = decltype(br2);
+ using Int3 = decltype(brr2);
+
+ using ConstInt3 = const int[3];
+ using ConstInt3 = decltype(bcr2);
+}
+
+struct C { template<int> int get(); };
+template<> struct std::tuple_size<C> { static const int value = 1; };
+template<> struct std::tuple_element<0, C> { typedef int type; };
+
+int member_get() {
+ auto [c] = C();
+ using T = int;
+ using T = decltype(c);
+ return c;
+}
+
+struct D { template<int> struct get {}; }; // expected-note {{declared here}}
+template<> struct std::tuple_size<D> { static const int value = 1; };
+template<> struct std::tuple_element<0, D> { typedef D::get<0> type; };
+void member_get_class_template() {
+ auto [d] = D(); // expected-error {{cannot refer to member 'get' in 'D' with '.'}} expected-note {{in implicit init}}
+}
+
+struct E { int get(); };
+template<> struct std::tuple_size<E> { static const int value = 1; };
+template<> struct std::tuple_element<0, E> { typedef int type; };
+void member_get_non_template() {
+ // FIXME: This diagnostic is not very good.
+ auto [e] = E(); // expected-error {{no member named 'get'}} expected-note {{in implicit init}}
+}
+
+namespace ADL {
+ struct X {};
+};
+template<int> int get(ADL::X);
+template<> struct std::tuple_size<ADL::X> { static const int value = 1; };
+template<> struct std::tuple_element<0, ADL::X> { typedef int type; };
+void adl_only_bad() {
+ auto [x] = ADL::X(); // expected-error {{undeclared identifier 'get'}} expected-note {{in implicit init}}
+}
+
+template<typename ElemType, typename GetTypeLV, typename GetTypeRV>
+struct wrap {
+ template<size_t> GetTypeLV get() &;
+ template<size_t> GetTypeRV get() &&;
+};
+template<typename ET, typename GTL, typename GTR>
+struct std::tuple_size<wrap<ET, GTL, GTR>> {
+ static const int value = 1;
+};
+template<typename ET, typename GTL, typename GTR>
+struct std::tuple_element<0, wrap<ET, GTL, GTR>> {
+ using type = ET;
+};
+
+template<typename T> T &lvalue();
+
+void test_value_category() {
+ // If the declared variable is an lvalue reference, the operand to get is an
+ // lvalue. Otherwise it's an xvalue.
+ { auto [a] = wrap<int, void, int>(); }
+ { auto &[a] = lvalue<wrap<int, int, void>>(); }
+ { auto &&[a] = wrap<int, void, int>(); }
+ // If the initializer (call to get) is an lvalue, the binding is an lvalue
+ // reference to the element type. Otherwise it's an rvalue reference to the
+ // element type.
+ { auto [a] = wrap<int, void, int&>(); }
+ { auto [a] = wrap<int&, void, int&>(); }
+ { auto [a] = wrap<int&&, void, int&>(); } // ok, reference collapse to int&
+
+ { auto [a] = wrap<int, void, int&&>(); }
+ { auto [a] = wrap<int&, void, int&&>(); } // expected-error {{non-const lvalue reference to type 'int' cannot bind}} expected-note {{in implicit}}
+ { auto [a] = wrap<const int&, void, int&&>(); }
+ { auto [a] = wrap<int&&, void, int&&>(); }
+
+ { auto [a] = wrap<int, void, float&>(); } // expected-error {{cannot bind}} expected-note {{implicit}}
+ { auto [a] = wrap<const int, void, float&>(); } // ok, const int &a can bind to float
+ { auto [a] = wrap<int, void, float>(); } // ok, int &&a can bind to float
+}
+
+namespace constant {
+ struct Q {};
+ template<int N> constexpr int get(Q &&) { return N * N; }
+}
+template<> struct std::tuple_size<constant::Q> { static const int value = 3; };
+template<int N> struct std::tuple_element<N, constant::Q> { typedef int type; };
+namespace constant {
+ Q q;
+ // This creates and lifetime-extends a temporary to hold the result of each get() call.
+ auto [a, b, c] = q; // expected-note {{temporary}}
+ static_assert(a == 0); // expected-error {{constant expression}} expected-note {{temporary}}
+
+ constexpr bool f() {
+ auto [a, b, c] = q;
+ return a == 0 && b == 1 && c == 4;
+ }
+ static_assert(f());
+
+ constexpr int g() {
+ int *p = nullptr;
+ {
+ auto [a, b, c] = q;
+ p = &c;
+ }
+ return *p; // expected-note {{read of object outside its lifetime}}
+ }
+ static_assert(g() == 4); // expected-error {{constant}} expected-note {{in call to 'g()'}}
+}
diff --git a/test/CXX/dcl.decl/dcl.decomp/p4.cpp b/test/CXX/dcl.decl/dcl.decomp/p4.cpp
new file mode 100644
index 000000000000..c461eb6f54b7
--- /dev/null
+++ b/test/CXX/dcl.decl/dcl.decomp/p4.cpp
@@ -0,0 +1,200 @@
+// RUN: %clang_cc1 -std=c++1z -verify -triple i686-linux-gnu %s
+
+template<typename T, typename U> struct same;
+template<typename T> struct same<T, T> { ~same(); };
+
+struct Empty {};
+
+struct A {
+ int a;
+};
+
+namespace NonPublicMembers {
+ struct NonPublic1 {
+ protected:
+ int a; // expected-note {{declared protected here}}
+ };
+
+ struct NonPublic2 {
+ private:
+ int a; // expected-note 2{{declared private here}}
+ };
+
+ struct NonPublic3 : private A {}; // expected-note {{constrained by private inheritance}}
+
+ struct NonPublic4 : NonPublic2 {};
+
+ void test() {
+ auto [a1] = NonPublic1(); // expected-error {{cannot decompose non-public member 'a' of 'NonPublicMembers::NonPublic1'}}
+ auto [a2] = NonPublic2(); // expected-error {{cannot decompose non-public member 'a' of 'NonPublicMembers::NonPublic2'}}
+ auto [a3] = NonPublic3(); // expected-error {{cannot decompose members of non-public base class 'A' of 'NonPublic3'}}
+ auto [a4] = NonPublic4(); // expected-error {{cannot decompose non-public member 'a' of 'NonPublicMembers::NonPublic4'}}
+ }
+}
+
+namespace AnonymousMember {
+ struct Struct {
+ struct { // expected-note {{declared here}}
+ int i;
+ };
+ };
+
+ struct Union {
+ union { // expected-note {{declared here}}
+ int i;
+ };
+ };
+
+ void test() {
+ auto [a1] = Struct(); // expected-error {{cannot decompose class type 'AnonymousMember::Struct' because it has an anonymous struct member}}
+ auto [a2] = Union(); // expected-error {{cannot decompose class type 'AnonymousMember::Union' because it has an anonymous union member}}
+ }
+}
+
+namespace MultipleClasses {
+ struct B : A {
+ int a;
+ };
+
+ struct C { int a; };
+ struct D : A, C {};
+
+ struct E : virtual A {};
+ struct F : A, E {}; // expected-warning {{direct base 'A' is inaccessible due to ambiguity}}
+
+ struct G : virtual A {};
+ struct H : E, G {};
+
+ struct I { int i; };
+ struct J : I {};
+ struct K : I, virtual J {}; // expected-warning {{direct base 'MultipleClasses::I' is inaccessible due to ambiguity}}
+
+ struct L : virtual J {};
+ struct M : virtual J, L {};
+
+ void test() {
+ auto [b] = B(); // expected-error {{cannot decompose class type 'B': both it and its base class 'A' have non-static data members}}
+ auto [d] = D(); // expected-error {{cannot decompose class type 'D': its base classes 'A' and 'MultipleClasses::C' have non-static data members}}
+ auto [e] = E();
+ auto [f] = F(); // expected-error-re {{cannot decompose members of ambiguous base class 'A' of 'F':{{.*}}struct MultipleClasses::F -> struct A{{.*}}struct MultipleClasses::F -> struct MultipleClasses::E -> struct A}}
+ auto [h] = H(); // ok, only one (virtual) base subobject even though there are two paths to it
+ auto [k] = K(); // expected-error {{cannot decompose members of ambiguous base class 'MultipleClasses::I'}}
+ auto [m] = M(); // ok, all paths to I are through the same virtual base subobject J
+
+ same<decltype(m), int>();
+ }
+}
+
+namespace BindingTypes {
+ struct A {
+ int i = 0;
+ int &r = i;
+ const float f = i;
+ mutable volatile int mvi;
+ };
+ void e() {
+ auto [i,r,f,mvi] = A();
+
+ same<decltype(i), int>();
+ same<decltype(r), int&>();
+ same<decltype(f), const float>();
+ same<decltype(mvi), volatile int>();
+
+ same<decltype((i)), int&>();
+ same<decltype((r)), int&>();
+ same<decltype((f)), const float&>();
+ same<decltype((mvi)), volatile int&>();
+ }
+ void f() {
+ auto &&[i,r,f,mvi] = A();
+
+ same<decltype(i), int>();
+ same<decltype(r), int&>();
+ same<decltype(f), const float>();
+ same<decltype(mvi), volatile int>();
+
+ same<decltype((i)), int&>();
+ same<decltype((r)), int&>();
+ same<decltype((f)), const float&>();
+ same<decltype((mvi)), volatile int&>();
+ }
+ void g() {
+ const auto [i,r,f,mvi] = A();
+
+ same<decltype(i), const int>();
+ same<decltype(r), int&>();
+ same<decltype(f), const float>();
+ same<decltype(mvi), volatile int>(); // not 'const volatile int', per expected resolution of DRxxx
+
+ same<decltype((i)), const int&>();
+ same<decltype((r)), int&>();
+ same<decltype((f)), const float&>();
+ same<decltype((mvi)), volatile int&>(); // not 'const volatile int&', per expected resolution of DRxxx
+ }
+ void h() {
+ typedef const A CA;
+ auto &[i,r,f,mvi] = CA(); // type of var is 'const A &'
+
+ same<decltype(i), const int>(); // not 'int', per expected resolution of DRxxx
+ same<decltype(r), int&>();
+ same<decltype(f), const float>();
+ same<decltype(mvi), volatile int>(); // not 'const volatile int', per expected resolution of DRxxx
+
+ same<decltype((i)), const int&>(); // not 'int&', per expected resolution of DRxxx
+ same<decltype((r)), int&>();
+ same<decltype((f)), const float&>();
+ same<decltype((mvi)), volatile int&>(); // not 'const volatile int&', per expected resolution of DRxxx
+ }
+ struct B {
+ mutable int i;
+ };
+ void mut() {
+ auto [i] = B();
+ const auto [ci] = B();
+ volatile auto [vi] = B();
+ same<decltype(i), int>();
+ same<decltype(ci), int>();
+ same<decltype(vi), volatile int>();
+ }
+}
+
+namespace Bitfield {
+ struct S { unsigned long long x : 4, y : 32; int z; }; // expected-note 2{{here}}
+ int f(S s) {
+ auto [a, b, c] = s;
+ unsigned long long &ra = a; // expected-error {{bit-field 'x'}}
+ unsigned long long &rb = b; // expected-error {{bit-field 'y'}}
+ int &rc = c;
+
+ // the type of the binding is the type of the field
+ same<decltype(a), unsigned long long>();
+ same<decltype(b), unsigned long long>();
+
+ // the type of the expression is an lvalue of the field type
+ // (even though a reference can't bind to the field)
+ same<decltype((a)), unsigned long long&>();
+ same<decltype((b)), unsigned long long&>();
+
+ // the expression promotes to a type large enough to hold the result
+ same<decltype(+a), int>();
+ same<decltype(+b), unsigned int>();
+ return rc;
+ }
+}
+
+namespace Constexpr {
+ struct Q { int a, b; constexpr Q() : a(1), b(2) {} };
+ constexpr Q q;
+ auto &[qa, qb] = q;
+ static_assert(&qa == &q.a && &qb == &q.b);
+ static_assert(qa == 1 && qb == 2);
+}
+
+namespace std_example {
+ struct S { int x1 : 2; volatile double y1; };
+ S f();
+ const auto [x, y] = f();
+
+ same<decltype((x)), const int&> same1;
+ same<decltype((y)), const volatile double&> same2;
+}
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 40f6431e3ddb..7a92e7a13d95 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
@@ -122,3 +122,39 @@ struct DefaultedAggr {
~DefaultedAggr() = default;
};
DefaultedAggr da = { 42 } ;
+
+struct ExplicitDefaultedAggr {
+ int n;
+ explicit ExplicitDefaultedAggr() = default; // expected-note {{candidate}}
+ ExplicitDefaultedAggr(const ExplicitDefaultedAggr &) = default; // expected-note {{candidate}}
+ ExplicitDefaultedAggr(ExplicitDefaultedAggr &&) = default; // expected-note {{candidate}}
+};
+ExplicitDefaultedAggr eda = { 42 }; // expected-error {{no matching constructor}}
+ExplicitDefaultedAggr eda2{};
+
+struct DefaultedBase {
+ int n;
+ DefaultedBase() = default; // expected-note 0+ {{candidate}}
+ DefaultedBase(DefaultedBase const&) = default; // expected-note 0+ {{candidate}}
+ DefaultedBase(DefaultedBase &&) = default; // expected-note 0+ {{candidate}}
+};
+
+struct InheritingConstructors : DefaultedBase { // expected-note 3 {{candidate}}
+ using DefaultedBase::DefaultedBase; // expected-note 2 {{inherited here}}
+};
+InheritingConstructors ic = { 42 }; // expected-error {{no matching constructor}}
+
+struct NonInheritingConstructors : DefaultedBase {}; // expected-note 0+ {{candidate}}
+NonInheritingConstructors nic = { 42 };
+#if __cplusplus <= 201402L
+// expected-error@-2 {{no matching constructor}}
+#endif
+
+struct NonAggrBase {
+ NonAggrBase(int) {}
+};
+struct HasNonAggrBase : NonAggrBase {}; // expected-note 0+ {{candidate}}
+HasNonAggrBase hnab = {42};
+#if __cplusplus <= 201402L
+// expected-error@-2 {{no matching constructor}}
+#endif
diff --git a/test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x-fixits.cpp b/test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x-fixits.cpp
index 299611ba7359..d66494fa2c2c 100644
--- a/test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x-fixits.cpp
+++ b/test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x-fixits.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -Wc++11-compat -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++98 -Wc++11-compat -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
// Verify that the appropriate fixits are emitted for narrowing conversions in
// initializer lists.
diff --git a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p4.cpp b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p4.cpp
new file mode 100644
index 000000000000..1a3732d99ea6
--- /dev/null
+++ b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p4.cpp
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -std=c++1z -verify %s
+
+void f() noexcept;
+void (&r)() = f;
+void (&s)() noexcept = r; // expected-error {{cannot bind}}
+
+void (&cond1)() noexcept = true ? r : f; // expected-error {{cannot bind}}
+void (&cond2)() noexcept = true ? f : r; // expected-error {{cannot bind}}
+// FIXME: Strictly, the rules in p4 don't allow this, because the operand types
+// are not of the same type other than cv-qualifiers, but we consider that to
+// be a defect, and instead allow reference-compatible types here.
+void (&cond3)() = true ? r : f;
+void (&cond4)() = true ? f : r;
diff --git a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-cxx03-extra-copy.cpp b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-cxx03-extra-copy.cpp
index f86b24e99259..7a5caef36e73 100644
--- a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-cxx03-extra-copy.cpp
+++ b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-cxx03-extra-copy.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -fdiagnostics-show-option -Wbind-to-temporary-copy -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++03 -fdiagnostics-show-option -Wbind-to-temporary-copy -verify %s
// C++03 requires that we check for a copy constructor when binding a
// reference to a temporary, since we are allowed to make a copy, Even
@@ -19,7 +19,7 @@ private:
};
struct X3 {
- X3();
+ X3(); // expected-note{{requires 0 arguments, but 1 was provided}}
private:
X3(X3&); // expected-note{{candidate constructor not viable: expects an l-value for 1st argument}}
@@ -42,8 +42,8 @@ struct X4 {
// Check for "dangerous" default arguments that could cause recursion.
struct X5 {
- X5();
- X5(const X5&, const X5& = X5()); // expected-warning{{no viable constructor copying parameter of type 'X5'}}
+ X5(); // expected-note {{requires 0 arguments}}
+ X5(const X5&, const X5& = X5()); // expected-warning{{no viable constructor copying parameter of type 'X5'}} expected-note {{requires 2 arguments}}
};
void g1(const X1&);
diff --git a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp
index be1113d47e3a..052349c8e2e0 100644
--- a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp
+++ b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -ast-dump %s 2>&1 | FileCheck %s
-// CHECK: example0
+// CHECK-LABEL: example0
void example0() {
double d = 2.0;
// CHECK: VarDecl{{.*}}rd 'double &'
@@ -14,14 +14,15 @@ void example0() {
struct A { };
struct B : A { } b;
-// CHECK: example1
+// CHECK-LABEL: example1
void example1() {
// CHECK: VarDecl{{.*}}ra 'struct A &'
// CHECK: ImplicitCastExpr{{.*}}'struct A' lvalue <DerivedToBase (A)>
A &ra = b;
// CHECK: VarDecl{{.*}}rca 'const struct A &'
- // CHECK: ImplicitCastExpr{{.*}}'const struct A' lvalue <NoOp>
- // CHECK: ImplicitCastExpr{{.*}}'struct A' lvalue <DerivedToBase (A)>
+ // CHECK: ImplicitCastExpr{{.*}}'const struct A' lvalue <DerivedToBase (A)>
+ // CHECK-NOT: MaterializeTemporaryExpr
+ // CHECK: ImplicitCastExpr{{.*}}'const struct B' lvalue <NoOp>
const A& rca = b;
}
@@ -31,21 +32,23 @@ struct X {
operator B();
} x;
-// CHECK: example2
+// CHECK-LABEL: example2
void example2() {
// CHECK: VarDecl{{.*}}rca 'const struct A &'
- // CHECK: ImplicitCastExpr{{.*}}'const struct A' <NoOp>
- // CHECK: ImplicitCastExpr{{.*}}'struct A' <DerivedToBase (A)>
+ // CHECK: ImplicitCastExpr{{.*}}'const struct A' lvalue <DerivedToBase (A)>
+ // CHECK: MaterializeTemporaryExpr{{.*}}'const struct B'
+ // CHECK: ImplicitCastExpr{{.*}}'const struct B' <NoOp>
// CHECK: CallExpr{{.*}}B
const A &rca = f();
// CHECK: VarDecl{{.*}}r 'const struct A &'
- // CHECK: ImplicitCastExpr{{.*}}'const struct A' <NoOp>
- // CHECK: ImplicitCastExpr{{.*}}'struct A' <DerivedToBase (A)>
+ // CHECK: ImplicitCastExpr{{.*}}'const struct A' lvalue <DerivedToBase (A)>
+ // CHECK: MaterializeTemporaryExpr{{.*}}'const struct B'
+ // CHECK: ImplicitCastExpr{{.*}}'const struct B' <NoOp>
// CHECK: CXXMemberCallExpr{{.*}}'struct B'
const A& r = x;
}
-// CHECK: example3
+// CHECK-LABEL: example3
void example3() {
// CHECK: VarDecl{{.*}}rcd2 'const double &'
// CHECK: ImplicitCastExpr{{.*}} <IntegralToFloating>
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 263f661208c5..e775e8f0e3cc 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
@@ -41,7 +41,7 @@ namespace PR6066 {
namespace test3 {
struct A {
- unsigned bitX : 4; // expected-note 4 {{bit-field is declared here}}
+ unsigned bitX : 4; // expected-note 3 {{bit-field is declared here}}
unsigned bitY : 4; // expected-note {{bit-field is declared here}}
unsigned var;
@@ -50,7 +50,7 @@ namespace test3 {
void test(A *a) {
unsigned &t0 = a->bitX; // expected-error {{non-const reference cannot bind to bit-field 'bitX'}}
- unsigned &t1 = (unsigned&) a->bitX; // expected-error {{non-const reference cannot bind to bit-field 'bitX'}}
+ unsigned &t1 = (unsigned&) a->bitX; // expected-error {{C-style cast from bit-field lvalue to reference type 'unsigned int &'}}
unsigned &t2 = const_cast<unsigned&>(a->bitX); // expected-error {{const_cast from bit-field lvalue to reference type 'unsigned int &'}}
unsigned &t3 = (a->foo(), a->bitX); // expected-error {{non-const reference cannot bind to bit-field 'bitX'}}
unsigned &t4 = (a->var ? a->bitX : a->bitY); // expected-error {{non-const reference cannot bind to bit-field}}
diff --git a/test/CXX/dcl.decl/dcl.init/p5.cpp b/test/CXX/dcl.decl/dcl.init/p5.cpp
index e7ccb2ec41e6..76e53edf3357 100644
--- a/test/CXX/dcl.decl/dcl.init/p5.cpp
+++ b/test/CXX/dcl.decl/dcl.init/p5.cpp
@@ -1,3 +1,5 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
// RUN: %clang_cc1 -fsyntax-only -verify %s
// A program that calls for default-initialization or value-initialization of
@@ -5,6 +7,11 @@
// cv-unqualified version of T is used for these definitions of
// zero-initialization, default-initialization, and value-initialization.
+typedef int &IR;
+IR r; // expected-error {{declaration of reference variable 'r' requires an initializer}}
+int n = IR(); // expected-error {{reference to type 'int' requires an initializer}}
+
+#if __cplusplus < 201103L
struct S { // expected-error {{implicit default constructor for 'S' must explicitly initialize the reference member}}
int &x; // expected-note {{declared here}} expected-error 3{{reference to type 'int' requires an initializer}}
};
@@ -22,6 +29,25 @@ struct U {
T t[3]; // expected-note {{in value-initialization of type 'T' here}}
};
U u = U(); // expected-note {{in value-initialization of type 'U' here}}
+#else
+struct S {
+ int &x; // expected-note 4{{because field 'x' of reference type 'int &' would not be initialized}}
+};
+S s; // expected-error {{deleted default constructor}}
+S f() {
+ return S(); // expected-error {{deleted default constructor}}
+}
+
+struct T
+ : S { // expected-note 2{{because base class 'S' has a deleted default constructor}}
+};
+T t = T(); // expected-error {{deleted default constructor}}
+
+struct U {
+ T t[3]; // expected-note {{because field 't' has a deleted default constructor}}
+};
+U u = U(); // expected-error {{deleted default constructor}}
+#endif
// Ensure that we handle C++11 in-class initializers properly as an extension.
// In this case, there is no user-declared default constructor, so we
@@ -29,20 +55,19 @@ U u = U(); // expected-note {{in value-initialization of type 'U' here}}
// constructor call anyway, because the default constructor is not trivial.
struct V {
int n;
- int &r = n; // expected-warning {{C++11}}
+ int &r = n; // expected-warning 0-1{{C++11}}
};
V v = V(); // ok
struct W {
int n;
- S s = { n }; // expected-warning {{C++11}}
+ S s = { n }; // expected-warning 0-1{{C++11}}
};
W w = W(); // ok
// Ensure we're not faking this up by making the default constructor
// non-trivial.
-#define static_assert(B, S) typedef int assert_failed[(B) ? 1 : -1];
-static_assert(__has_trivial_constructor(S), "");
-static_assert(__has_trivial_constructor(T), "");
-static_assert(__has_trivial_constructor(U), "");
-static_assert(!__has_trivial_constructor(V), "");
-static_assert(!__has_trivial_constructor(W), "");
+_Static_assert(__has_trivial_constructor(S), "");
+_Static_assert(__has_trivial_constructor(T), "");
+_Static_assert(__has_trivial_constructor(U), "");
+_Static_assert(!__has_trivial_constructor(V), "");
+_Static_assert(!__has_trivial_constructor(W), "");
diff --git a/test/CXX/dcl.decl/dcl.init/p7.cpp b/test/CXX/dcl.decl/dcl.init/p7.cpp
index 03216f4c28ac..1c1d793e8a5e 100644
--- a/test/CXX/dcl.decl/dcl.init/p7.cpp
+++ b/test/CXX/dcl.decl/dcl.init/p7.cpp
@@ -12,3 +12,5 @@ struct B : NotAggregateBase {
explicit B() = default; // expected-note {{here}}
};
B b = {}; // expected-error {{chosen constructor is explicit}}
+B b2{};
+B b3;
diff --git a/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p6-0x.cpp b/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p6-0x.cpp
index cec747e1d605..d93cc8b90874 100644
--- a/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p6-0x.cpp
+++ b/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p6-0x.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++1z -fsyntax-only -verify %s
void f0() &; // expected-error {{non-member function cannot have '&' qualifier}}
void f1() &&; // expected-error {{non-member function cannot have '&&' qualifier}}
@@ -58,3 +59,16 @@ template<typename T> struct pass {
};
pass<func_type_lvalue> pass0;
pass<func_type_lvalue> pass1;
+
+template<typename T, typename U> struct is_same { static const bool value = false; };
+template<typename T> struct is_same<T, T> { static const bool value = true; };
+constexpr bool cxx1z = __cplusplus > 201402L;
+
+void noexcept_true() noexcept(true);
+void noexcept_false() noexcept(false);
+using func_type_noexcept_true = wrap<decltype(noexcept_true)>;
+using func_type_noexcept_false = wrap<decltype(noexcept_false)>;
+static_assert(is_same<func_type_noexcept_false, func_type_noexcept_true>::value == !cxx1z, "");
+static_assert(is_same<func_type_noexcept_false::val, func_type_noexcept_true::val>::value == !cxx1z, "");
+static_assert(is_same<func_type_noexcept_false::ptr, func_type_noexcept_true::ptr>::value == !cxx1z, "");
+static_assert(is_same<func_type_noexcept_false::ref, func_type_noexcept_true::ref>::value == !cxx1z, "");
diff --git a/test/CXX/drs/dr0xx.cpp b/test/CXX/drs/dr0xx.cpp
index 3bb6701b32e1..c988b6aba57e 100644
--- a/test/CXX/drs/dr0xx.cpp
+++ b/test/CXX/drs/dr0xx.cpp
@@ -248,7 +248,7 @@ namespace dr20 { // dr20: yes
private:
X(const X&); // expected-note {{here}}
};
- X f();
+ X &f();
X x = f(); // expected-error {{private}}
}
@@ -276,20 +276,39 @@ namespace dr23 { // dr23: yes
namespace dr25 { // dr25: yes
struct A {
- void f() throw(int);
+ void f() throw(int); // expected-error 0-1{{ISO C++1z does not allow}} expected-note 0-1{{use 'noexcept}}
};
- void (A::*f)() throw (int);
- void (A::*g)() throw () = f; // expected-error {{is not superset of source}}
+ void (A::*f)() throw (int); // expected-error 0-1{{ISO C++1z does not allow}} expected-note 0-1{{use 'noexcept}}
+ void (A::*g)() throw () = f;
+#if __cplusplus <= 201402L
+ // expected-error@-2 {{is not superset of source}}
+#else
+ // expected-error@-4 {{different exception specifications}}
+#endif
void (A::*g2)() throw () = 0;
- void (A::*h)() throw (int, char) = f;
- void (A::*i)() throw () = &A::f; // expected-error {{is not superset of source}}
+ void (A::*h)() throw (int, char) = f; // expected-error 0-1{{ISO C++1z does not allow}} expected-note 0-1{{use 'noexcept}}
+ void (A::*i)() throw () = &A::f;
+#if __cplusplus <= 201402L
+ // expected-error@-2 {{is not superset of source}}
+#else
+ // expected-error@-4 {{different exception specifications}}
+#endif
void (A::*i2)() throw () = 0;
- void (A::*j)() throw (int, char) = &A::f;
+ void (A::*j)() throw (int, char) = &A::f; // expected-error 0-1{{ISO C++1z does not allow}} expected-note 0-1{{use 'noexcept}}
void x() {
- // FIXME: Don't produce the second error here.
- g2 = f; // expected-error {{is not superset}} expected-error {{incompatible}}
+ g2 = f;
+#if __cplusplus <= 201402L
+ // expected-error@-2 {{is not superset of source}}
+#else
+ // expected-error@-4 {{different exception specifications}}
+#endif
h = f;
- i2 = &A::f; // expected-error {{is not superset}} expected-error {{incompatible}}
+ i2 = &A::f;
+#if __cplusplus <= 201402L
+ // expected-error@-2 {{is not superset of source}}
+#else
+ // expected-error@-4 {{different exception specifications}}
+#endif
j = &A::f;
}
}
@@ -297,8 +316,15 @@ namespace dr25 { // dr25: yes
namespace dr26 { // dr26: yes
struct A { A(A, const A & = A()); }; // expected-error {{must pass its first argument by reference}}
struct B {
- B(); // expected-note {{candidate}}
- B(const B &, B = B()); // expected-error {{no matching constructor}} expected-note {{candidate}} expected-note {{here}}
+ B(); // expected-note 0-1{{candidate}}
+ B(const B &, B = B());
+#if __cplusplus <= 201402L
+ // expected-error@-2 {{no matching constructor}} expected-note@-2 {{candidate}} expected-note@-2 {{here}}
+#endif
+ };
+ struct C {
+ static C &f();
+ C(const C &, C = f()); // expected-error {{no matching constructor}} expected-note {{candidate}} expected-note {{here}}
};
}
@@ -307,7 +333,7 @@ namespace dr27 { // dr27: yes
E &m = true ? n : n;
}
-// dr28: na
+// dr28: na lib
namespace dr29 { // dr29: 3.4
void dr29_f0(); // expected-note {{here}}
@@ -643,25 +669,33 @@ namespace dr58 { // dr58: yes
namespace dr59 { // dr59: yes
template<typename T> struct convert_to { operator T() const; };
- struct A {}; // expected-note 2{{volatile qualifier}}
- struct B : A {}; // expected-note 2{{volatile qualifier}}
-#if __cplusplus >= 201103L // move constructors
- // expected-note@-3 2{{volatile qualifier}}
- // expected-note@-3 2{{volatile qualifier}}
-#endif
+ struct A {}; // expected-note 5+{{candidate}}
+ struct B : A {}; // expected-note 0+{{candidate}}
A a1 = convert_to<A>();
A a2 = convert_to<A&>();
A a3 = convert_to<const A>();
- A a4 = convert_to<const volatile A>(); // expected-error {{no viable}}
+ A a4 = convert_to<const volatile A>();
+#if __cplusplus <= 201402L
+ // expected-error@-2 {{no viable}}
+#endif
A a5 = convert_to<const volatile A&>(); // expected-error {{no viable}}
B b1 = convert_to<B>();
B b2 = convert_to<B&>();
B b3 = convert_to<const B>();
- B b4 = convert_to<const volatile B>(); // expected-error {{no viable}}
+ B b4 = convert_to<const volatile B>();
+#if __cplusplus <= 201402L
+ // expected-error@-2 {{no viable}}
+#endif
B b5 = convert_to<const volatile B&>(); // expected-error {{no viable}}
+ A c1 = convert_to<B>();
+ A c2 = convert_to<B&>();
+ A c3 = convert_to<const B>();
+ A c4 = convert_to<const volatile B>(); // expected-error {{no viable}}
+ A c5 = convert_to<const volatile B&>(); // expected-error {{no viable}}
+
int n1 = convert_to<int>();
int n2 = convert_to<int&>();
int n3 = convert_to<const int>();
@@ -901,14 +935,17 @@ namespace dr84 { // dr84: yes
struct A { operator B() const; };
struct C {};
struct B {
- B(B&); // expected-note {{candidate}}
- B(C);
+ B(B&); // expected-note 0-1{{candidate}}
+ B(C); // expected-note 0-1{{no known conversion from 'dr84::B' to 'dr84::C'}}
operator C() const;
};
A a;
// Cannot use B(C) / operator C() pair to construct the B from the B temporary
- // here.
- B b = a; // expected-error {{no viable}}
+ // here. In C++1z, we initialize the B object directly using 'A::operator B()'.
+ B b = a;
+#if __cplusplus <= 201402L
+ // expected-error@-2 {{no viable}}
+#endif
}
namespace dr85 { // dr85: yes
@@ -942,10 +979,11 @@ namespace dr85 { // dr85: yes
// dr86: dup 446
namespace dr87 { // dr87: no
+ // FIXME: Superseded by dr1975
template<typename T> struct X {};
// FIXME: This is invalid.
X<void() throw()> x;
- // ... but this is valid.
+ // This is valid under dr87 but not under dr1975.
X<void(void() throw())> y;
}
@@ -994,24 +1032,40 @@ namespace dr91 { // dr91: yes
int k = f(U());
}
-namespace dr92 { // FIXME: Issue is still open.
- void f() throw(int, float);
- void (*p)() throw(int) = &f; // expected-error {{target exception specification is not superset of source}}
- void (*q)() throw(int);
- void (**pp)() throw() = &q; // expected-error {{exception specifications are not allowed}}
+namespace dr92 { // dr92: 4.0 c++17
+ void f() throw(int, float); // expected-error 0-1{{ISO C++1z does not allow}} expected-note 0-1{{use 'noexcept}}
+ void (*p)() throw(int) = &f; // expected-error 0-1{{ISO C++1z does not allow}} expected-note 0-1{{use 'noexcept}}
+#if __cplusplus <= 201402L
+ // expected-error@-2 {{target exception specification is not superset of source}}
+#else
+ // expected-warning@-4 {{target exception specification is not superset of source}}
+#endif
+ void (*q)() throw(int); // expected-error 0-1{{ISO C++1z does not allow}} expected-note 0-1{{use 'noexcept}}
+ void (**pp)() throw() = &q;
+#if __cplusplus <= 201402L
+ // expected-error@-2 {{exception specifications are not allowed}}
+#else
+ // expected-error@-4 {{cannot initialize}}
+#endif
- void g(void() throw());
- void h() {
- g(f); // expected-error {{is not superset}}
- g(q); // expected-error {{is not superset}}
+ void g(void() throw()); // expected-note 0-2 {{no known conversion}} expected-warning 0-1{{mangled name of 'g' will change in C++17}}
+ void h() throw() {
+ g(f); // expected-error-re {{{{is not superset|no matching function}}}}
+ g(q); // expected-error-re {{{{is not superset|no matching function}}}}
}
// Prior to C++17, this is OK because the exception specification is not
// considered in this context. In C++17, we *do* perform an implicit
- // conversion (which performs initialization), but we convert to the type of
- // the template parameter, which does not include the exception specification.
+ // conversion (which performs initialization), and the exception specification
+ // is part of the type of the parameter, so this is invalid.
template<void() throw()> struct X {};
- X<&f> xp; // ok
+ X<&f> xp;
+#if __cplusplus > 201402L
+ // expected-error@-2 {{not implicitly convertible}}
+#endif
+
+ template<void() throw(int)> struct Y {}; // expected-error 0-1{{ISO C++1z does not allow}} expected-note 0-1{{use 'noexcept}}
+ Y<&h> yp; // ok
}
// dr93: na
diff --git a/test/CXX/drs/dr10xx.cpp b/test/CXX/drs/dr10xx.cpp
index a1d7ef67c66d..e11e796165e2 100644
--- a/test/CXX/drs/dr10xx.cpp
+++ b/test/CXX/drs/dr10xx.cpp
@@ -3,8 +3,6 @@
// 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
-// expected-no-diagnostics
-
namespace std {
__extension__ typedef __SIZE_TYPE__ size_t;
@@ -32,6 +30,18 @@ namespace dr1048 { // dr1048: 3.6
#endif
}
+namespace dr1054 { // dr1054: no
+ // FIXME: Test is incomplete.
+ struct A {} volatile a;
+ void f() {
+ // FIXME: This is wrong: an lvalue-to-rvalue conversion is applied here,
+ // which copy-initializes a temporary from 'a'. Therefore this is
+ // ill-formed because A does not have a volatile copy constructor.
+ // (We might want to track this aspect under dr1383 instead?)
+ a; // expected-warning {{assign into a variable to force a volatile load}}
+ }
+}
+
namespace dr1070 { // dr1070: 3.5
#if __cplusplus >= 201103L
struct A {
diff --git a/test/CXX/drs/dr118.cpp b/test/CXX/drs/dr118.cpp
new file mode 100644
index 000000000000..58aa3912c801
--- /dev/null
+++ b/test/CXX/drs/dr118.cpp
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -triple x86_64-linux -std=c++98 %s -pedantic-errors -emit-llvm -o - | FileCheck %s --implicit-check-not " call "
+// RUN: %clang_cc1 -triple x86_64-linux -std=c++11 %s -pedantic-errors -emit-llvm -o - | FileCheck %s --implicit-check-not " call "
+// RUN: %clang_cc1 -triple x86_64-linux -std=c++14 %s -pedantic-errors -emit-llvm -o - | FileCheck %s --implicit-check-not " call "
+// RUN: %clang_cc1 -triple x86_64-linux -std=c++1z %s -pedantic-errors -emit-llvm -o - | FileCheck %s --implicit-check-not " call "
+
+// dr118: yes
+
+struct S {
+ virtual void f();
+};
+void (S::*pmf)();
+
+// CHECK-LABEL: define {{.*}} @_Z1g
+void g(S *sp) {
+ // CHECK: call void %
+ sp->f(); // 1: polymorphic
+ // CHECK: call void @
+ sp->S::f(); // 2: non-polymorphic
+ // CHECK: call void @
+ (sp->S::f)(); // 3: non-polymorphic
+ // CHECK: call void %
+ (sp->*pmf)(); // 4: polymorphic
+ // CHECK: call void %
+ (sp->*&S::f)(); // 5: polymorphic
+}
+
diff --git a/test/CXX/drs/dr12xx.cpp b/test/CXX/drs/dr12xx.cpp
index 048c21acde56..72d8d683ab7a 100644
--- a/test/CXX/drs/dr12xx.cpp
+++ b/test/CXX/drs/dr12xx.cpp
@@ -3,7 +3,16 @@
// 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
-// expected-no-diagnostics
+namespace dr1213 { // dr1213: 4.0
+#if __cplusplus >= 201103L
+ using T = int[3];
+ int &&r = T{}[1];
+
+ using T = decltype((T{}));
+ using U = decltype((T{}[2]));
+ using U = int &&;
+#endif
+}
namespace dr1250 { // dr1250: 3.9
struct Incomplete;
@@ -16,3 +25,29 @@ struct Derived : Base {
virtual Incomplete *meow();
};
} // dr1250
+
+namespace dr1295 { // dr1295: 4.0
+ struct X {
+ unsigned bitfield : 4;
+ };
+
+ X x = {1};
+
+ unsigned const &r1 = static_cast<X &&>(x).bitfield; // expected-error 0-1{{C++11}}
+ unsigned const &r2 = static_cast<unsigned &&>(x.bitfield); // expected-error 0-1{{C++11}}
+
+ template<unsigned &r> struct Y {};
+ Y<x.bitfield> y;
+#if __cplusplus <= 201402L
+ // expected-error@-2 {{does not refer to any declaration}} expected-note@-3 {{here}}
+#else
+ // expected-error@-4 {{refers to subobject}}
+#endif
+
+#if __cplusplus >= 201103L
+ const unsigned other = 0;
+ using T = decltype(true ? other : x.bitfield);
+ using T = unsigned;
+#endif
+}
+
diff --git a/test/CXX/drs/dr13xx.cpp b/test/CXX/drs/dr13xx.cpp
index 8c3e7f2a04ca..28bebcbb607e 100644
--- a/test/CXX/drs/dr13xx.cpp
+++ b/test/CXX/drs/dr13xx.cpp
@@ -3,6 +3,136 @@
// 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 dr1315 { // dr1315: partial
+ template <int I, int J> struct A {};
+ template <int I> // expected-note {{non-deducible template parameter 'I'}}
+ struct A<I + 5, I * 2> {}; // expected-error {{contains a template parameter that cannot be deduced}}
+ template <int I> struct A<I, I> {};
+
+ template <int I, int J, int K> struct B;
+ template <int I, int K> struct B<I, I * 2, K> {}; // expected-note {{matches}}
+ B<1, 2, 3> b1;
+
+ // Multiple declarations with the same dependent expression are equivalent
+ // for partial ordering purposes.
+ template <int I> struct B<I, I * 2, 2> { typedef int type; };
+ B<1, 2, 2>::type b2;
+
+ // Multiple declarations with differing dependent expressions are unordered.
+ template <int I, int K> struct B<I, I + 1, K> {}; // expected-note {{matches}}
+ B<1, 2, 4> b3; // expected-error {{ambiguous}}
+
+ // FIXME: Under dr1315, this is perhaps valid, but that is not clear: this
+ // fails the "more specialized than the primary template" test because the
+ // dependent type of T::value is not the same as 'int'.
+ // A core issue will be opened to decide what is supposed to happen here.
+ template <typename T, int I> struct C;
+ template <typename T> struct C<T, T::value>;
+ // expected-error@-1 {{type of specialized non-type template argument depends on a template parameter of the partial specialization}}
+}
+
+namespace dr1330 { // dr1330: 4.0 c++11
+ // exception-specifications are parsed in a context where the class is complete.
+ struct A {
+ void f() throw(T) {} // expected-error 0-1{{C++1z}} expected-note 0-1{{noexcept}}
+ struct T {};
+
+#if __cplusplus >= 201103L
+ void g() noexcept(&a == b) {}
+ static int a;
+ static constexpr int *b = &a;
+#endif
+ };
+
+ void (A::*af1)() throw(A::T) = &A::f; // expected-error 0-1{{C++1z}} expected-note 0-1{{noexcept}}
+ void (A::*af2)() throw() = &A::f; // expected-error-re {{{{not superset|different exception spec}}}}
+
+#if __cplusplus >= 201103L
+ static_assert(noexcept(A().g()), "");
+#endif
+
+ // Likewise, they're instantiated separately from an enclosing class template.
+ template<typename U>
+ struct B {
+ void f() throw(T, typename U::type) {} // expected-error 0-1{{C++1z}} expected-note 0-1{{noexcept}}
+ struct T {};
+
+#if __cplusplus >= 201103L
+ void g() noexcept(&a == b && U::value) {}
+ static int a;
+ static constexpr int *b = &a;
+#endif
+ };
+
+ B<int> bi; // ok
+
+ struct P {
+ typedef int type;
+ static const int value = true;
+ };
+
+ void (B<P>::*bpf1)() throw(B<P>::T, int) = &B<P>::f; // expected-error 0-1{{C++1z}} expected-note 0-1{{noexcept}}
+#if __cplusplus < 201103L
+ // expected-error@-2 {{not superset}}
+ // FIXME: We only delay instantiation in C++11 onwards. In C++98, something
+ // weird happens: instantiation of B<P> fails because it references T before
+ // it's instantiated, but the diagnostic is suppressed in
+ // Sema::FindInstantiatedDecl because we've already hit an error. This is
+ // obviously a bad way to react to this situation; we should still producing
+ // the "T has not yet been instantiated" error here, rather than giving
+ // confusing errors later on.
+#endif
+ void (B<P>::*bpf2)() throw(int) = &B<P>::f; // expected-error 0-1{{C++1z}} expected-note 0-1{{noexcept}}
+#if __cplusplus <= 201402L
+ // expected-error@-2 {{not superset}}
+#else
+ // expected-warning@-4 {{not superset}}
+#endif
+ void (B<P>::*bpf3)() = &B<P>::f;
+ void (B<P>::*bpf4)() throw() = &B<P>::f;
+#if __cplusplus <= 201402L
+ // expected-error@-2 {{not superset}}
+#else
+ // expected-error@-4 {{different exception specifications}}
+#endif
+
+#if __cplusplus >= 201103L
+ static_assert(noexcept(B<P>().g()), "");
+ struct Q { static const int value = false; };
+ static_assert(!noexcept(B<Q>().g()), "");
+#endif
+
+ template<typename T> int f() throw(typename T::error) { return 0; } // expected-error 1-4{{prior to '::'}} expected-note 0-1{{instantiation of}}
+#if __cplusplus > 201402L
+ // expected-error@-2 0-1{{C++1z}} expected-note@-2 0-1{{noexcept}}
+#endif
+ // An exception-specification is needed even if the function is only used in
+ // an unevaluated operand.
+ int f1 = sizeof(f<int>()); // expected-note {{instantiation of}}
+#if __cplusplus >= 201103L
+ decltype(f<char>()) f2; // expected-note {{instantiation of}}
+ bool f3 = noexcept(f<float>()); // expected-note {{instantiation of}}
+#endif
+ template int f<short>(); // expected-note {{instantiation of}}
+
+ template<typename T> struct C {
+ C() throw(typename T::type); // expected-error 1-2{{prior to '::'}}
+#if __cplusplus > 201402L
+ // expected-error@-2 0-1{{C++1z}} expected-note@-2 0-1{{noexcept}}
+#endif
+ };
+ struct D : C<void> {}; // ok
+#if __cplusplus < 201103L
+ // expected-note@-2 {{instantiation of}}
+#endif
+ void f(D &d) { d = d; } // ok
+
+ // FIXME: In C++11 onwards, we should also note the declaration of 'e' as the
+ // line that triggers the use of E::E()'s exception specification.
+ struct E : C<int> {}; // expected-note {{in instantiation of}}
+ E e;
+}
+
namespace dr1346 { // dr1346: 3.5
auto a(1); // expected-error 0-1{{extension}}
auto b(1, 2); // expected-error {{multiple expressions}} expected-error 0-1{{extension}}
diff --git a/test/CXX/drs/dr14xx.cpp b/test/CXX/drs/dr14xx.cpp
index 9491f7da1476..9e724d918346 100644
--- a/test/CXX/drs/dr14xx.cpp
+++ b/test/CXX/drs/dr14xx.cpp
@@ -342,4 +342,32 @@ namespace dr1490 { // dr1490: 3.7 c++11
char s[4]{"abc"}; // Ok
std::initializer_list<char>{"abc"}; // expected-error {{expected unqualified-id}}}
} // dr190
+
+namespace dr1495 { // dr1495: 4.0
+ // Deduction succeeds in both directions.
+ template<typename T, typename U> struct A {}; // expected-note {{template is declared here}}
+ template<typename T, typename U> struct A<U, T> {}; // expected-error {{class template partial specialization is not more specialized}}
+
+ // Primary template is more specialized.
+ template<typename, typename...> struct B {}; // expected-note {{template is declared here}}
+ template<typename ...Ts> struct B<Ts...> {}; // expected-error {{not more specialized}}
+
+ // Deduction fails in both directions.
+ template<int, typename, typename ...> struct C {}; // expected-note {{template is declared here}}
+ template<typename ...Ts> struct C<0, Ts...> {}; // expected-error {{not more specialized}}
+
+#if __cplusplus >= 201402L
+ // Deduction succeeds in both directions.
+ template<typename T, typename U> int a; // expected-note {{template is declared here}}
+ template<typename T, typename U> int a<U, T>; // expected-error {{variable template partial specialization is not more specialized}}
+
+ // Primary template is more specialized.
+ template<typename, typename...> int b; // expected-note {{template is declared here}}
+ template<typename ...Ts> int b<Ts...>; // expected-error {{not more specialized}}
+
+ // Deduction fails in both directions.
+ template<int, typename, typename ...> int c; // expected-note {{template is declared here}}
+ template<typename ...Ts> int c<0, Ts...>; // expected-error {{not more specialized}}
+#endif
+}
#endif
diff --git a/test/CXX/drs/dr158.cpp b/test/CXX/drs/dr158.cpp
new file mode 100644
index 000000000000..33f837ca0627
--- /dev/null
+++ b/test/CXX/drs/dr158.cpp
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -triple x86_64-linux -std=c++98 %s -O3 -disable-llvm-passes -pedantic-errors -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-linux -std=c++11 %s -O3 -disable-llvm-passes -pedantic-errors -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-linux -std=c++14 %s -O3 -disable-llvm-passes -pedantic-errors -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-linux -std=c++1z %s -O3 -disable-llvm-passes -pedantic-errors -emit-llvm -o - | FileCheck %s
+
+// dr158: yes
+
+// CHECK-LABEL: define {{.*}} @_Z1f
+const int *f(const int * const *p, int **q) {
+ // CHECK: load i32**, {{.*}}, !tbaa ![[INTPTR_TBAA:[^,]*]]
+ const int *x = *p;
+ // CHECK: store i32* null, {{.*}}, !tbaa ![[INTPTR_TBAA]]
+ *q = 0;
+ return x;
+}
+
+struct A {};
+
+// CHECK-LABEL: define {{.*}} @_Z1g
+const int *(A::*const *g(const int *(A::* const **p)[3], int *(A::***q)[3]))[3] {
+ // CHECK: load i64**, {{.*}}, !tbaa ![[MEMPTR_TBAA:[^,]*]]
+ const int *(A::*const *x)[3] = *p;
+ // CHECK: store i64* null, {{.*}}, !tbaa ![[MEMPTR_TBAA]]
+ *q = 0;
+ return x;
+}
+
diff --git a/test/CXX/drs/dr15xx.cpp b/test/CXX/drs/dr15xx.cpp
index 5f85a196fd6a..fb0d9334f6b6 100644
--- a/test/CXX/drs/dr15xx.cpp
+++ b/test/CXX/drs/dr15xx.cpp
@@ -3,9 +3,223 @@
// 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-no-diagnostics
+namespace dr1512 { // dr1512: 4.0
+ void f(char *p) {
+ if (p > 0) {} // expected-error {{ordered comparison between pointer and zero}}
+#if __cplusplus >= 201103L
+ if (p > nullptr) {} // expected-error {{invalid operands}}
+#endif
+ }
+ bool g(int **x, const int **y) {
+ return x < y;
+ }
+
+ template<typename T> T val();
+
+ template<typename A, typename B, typename C> void composite_pointer_type_is_base() {
+ typedef __typeof(true ? val<A>() : val<B>()) type;
+ typedef C type;
+
+ typedef __typeof(val<A>() == val<B>()) cmp;
+ typedef __typeof(val<A>() != val<B>()) cmp;
+ typedef bool cmp;
+ }
+
+ template<typename A, typename B, typename C> void composite_pointer_type_is_ord() {
+ composite_pointer_type_is_base<A, B, C>();
+
+ typedef __typeof(val<A>() < val<B>()) cmp;
+ typedef __typeof(val<A>() <= val<B>()) cmp;
+ typedef __typeof(val<A>() > val<B>()) cmp;
+ typedef __typeof(val<A>() >= val<B>()) cmp;
+ typedef bool cmp;
+ }
+
+ template <typename A, typename B, typename C>
+ void composite_pointer_type_is_unord(int = 0) {
+ composite_pointer_type_is_base<A, B, C>();
+ }
+ template <typename A, typename B, typename C>
+ void composite_pointer_type_is_unord(__typeof(val<A>() < val<B>()) * = 0);
+ template <typename A, typename B, typename C>
+ void composite_pointer_type_is_unord(__typeof(val<A>() <= val<B>()) * = 0);
+ template <typename A, typename B, typename C>
+ void composite_pointer_type_is_unord(__typeof(val<A>() > val<B>()) * = 0);
+ template <typename A, typename B, typename C>
+ void composite_pointer_type_is_unord(__typeof(val<A>() >= val<B>()) * = 0);
+
+ // A call to this is ambiguous if a composite pointer type exists.
+ template<typename A, typename B>
+ void no_composite_pointer_type(__typeof((true ? val<A>() : val<B>()), void()) * = 0);
+ template<typename A, typename B> void no_composite_pointer_type(int = 0);
+
+ struct A {};
+ struct B : A {};
+ struct C {};
+
+ void test() {
+#if __cplusplus >= 201103L
+ using nullptr_t = decltype(nullptr);
+ composite_pointer_type_is_unord<nullptr_t, nullptr_t, nullptr_t>();
+ no_composite_pointer_type<nullptr_t, int>();
+
+ composite_pointer_type_is_unord<nullptr_t, const char**, const char**>();
+ composite_pointer_type_is_unord<const char**, nullptr_t, const char**>();
+#endif
+
+ composite_pointer_type_is_ord<const int *, volatile void *, const volatile void*>();
+ composite_pointer_type_is_ord<const void *, volatile int *, const volatile void*>();
+
+ composite_pointer_type_is_ord<const A*, volatile B*, const volatile A*>();
+ composite_pointer_type_is_ord<const B*, volatile A*, const volatile A*>();
+
+ composite_pointer_type_is_unord<const int *A::*, volatile int *B::*, const volatile int *const B::*>();
+ composite_pointer_type_is_unord<const int *B::*, volatile int *A::*, const volatile int *const B::*>();
+ no_composite_pointer_type<int (A::*)(), int (C::*)()>();
+ no_composite_pointer_type<const int (A::*)(), volatile int (C::*)()>();
+
+#if __cplusplus > 201402
+ composite_pointer_type_is_ord<int (*)() noexcept, int (*)(), int (*)()>();
+ composite_pointer_type_is_ord<int (*)(), int (*)() noexcept, int (*)()>();
+ composite_pointer_type_is_unord<int (A::*)() noexcept, int (A::*)(), int (A::*)()>();
+ composite_pointer_type_is_unord<int (A::*)(), int (A::*)() noexcept, int (A::*)()>();
+ // FIXME: This looks like a standard defect; these should probably all have type 'int (B::*)()'.
+ composite_pointer_type_is_unord<int (B::*)(), int (A::*)() noexcept, int (B::*)()>();
+ composite_pointer_type_is_unord<int (A::*)() noexcept, int (B::*)(), int (B::*)()>();
+ composite_pointer_type_is_unord<int (B::*)() noexcept, int (A::*)(), int (B::*)()>();
+ composite_pointer_type_is_unord<int (A::*)(), int (B::*)() noexcept, int (B::*)()>();
+
+ // FIXME: It would be reasonable to permit these, with a common type of 'int (*const *)()'.
+ no_composite_pointer_type<int (**)() noexcept, int (**)()>();
+ no_composite_pointer_type<int (**)(), int (**)() noexcept>();
+
+ // FIXME: It would be reasonable to permit these, with a common type of 'int (A::*)()'.
+ no_composite_pointer_type<int (A::*)() const, int (A::*)()>();
+ no_composite_pointer_type<int (A::*)(), int (A::*)() const>();
+
+ // FIXME: It would be reasonable to permit these, with a common type of
+ // 'int (A::*)() &' and 'int (A::*)() &&', respectively.
+ no_composite_pointer_type<int (A::*)() &, int (A::*)()>();
+ no_composite_pointer_type<int (A::*)(), int (A::*)() &>();
+ no_composite_pointer_type<int (A::*)() &&, int (A::*)()>();
+ no_composite_pointer_type<int (A::*)(), int (A::*)() &&>();
+
+ no_composite_pointer_type<int (A::*)() &&, int (A::*)() &>();
+ no_composite_pointer_type<int (A::*)() &, int (A::*)() &&>();
+
+ no_composite_pointer_type<int (C::*)(), int (A::*)() noexcept>();
+ no_composite_pointer_type<int (A::*)() noexcept, int (C::*)()>();
+#endif
+ }
+
+ template<typename T> struct Wrap { operator T(); };
+ void test_overload() {
+#if __cplusplus >= 201103L
+ using nullptr_t = decltype(nullptr);
+ void(Wrap<nullptr_t>() == Wrap<nullptr_t>());
+ void(Wrap<nullptr_t>() != Wrap<nullptr_t>());
+ void(Wrap<nullptr_t>() < Wrap<nullptr_t>()); // expected-error {{invalid operands}}
+ void(Wrap<nullptr_t>() > Wrap<nullptr_t>()); // expected-error {{invalid operands}}
+ 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.
+ 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
+ }
+}
+
+namespace dr1518 { // dr1518: 4.0
+#if __cplusplus >= 201103L
+struct Z0 { // expected-note 0+ {{candidate}}
+ explicit Z0() = default; // expected-note 0+ {{here}}
+};
+struct Z { // expected-note 0+ {{candidate}}
+ explicit Z(); // expected-note 0+ {{here}}
+ explicit Z(int);
+ explicit Z(int, int); // expected-note 0+ {{here}}
+};
+template <class T> int Eat(T); // expected-note 0+ {{candidate}}
+Z0 a;
+Z0 b{};
+Z0 c = {}; // expected-error {{explicit in copy-initialization}}
+int i = Eat<Z0>({}); // expected-error {{no matching function for call to 'Eat'}}
+
+Z c2 = {}; // expected-error {{explicit in copy-initialization}}
+int i2 = Eat<Z>({}); // expected-error {{no matching function for call to 'Eat'}}
+Z a1 = 1; // expected-error {{no viable conversion}}
+Z a3 = Z(1);
+Z a2(1);
+Z *p = new Z(1);
+Z a4 = (Z)1;
+Z a5 = static_cast<Z>(1);
+Z a6 = {4, 3}; // expected-error {{explicit in copy-initialization}}
+
+struct UserProvidedBaseCtor { // expected-note 0+ {{candidate}}
+ UserProvidedBaseCtor() {}
+};
+struct DoesntInheritCtor : UserProvidedBaseCtor { // expected-note 0+ {{candidate}}
+ int x;
+};
+DoesntInheritCtor I{{}, 42};
+#if __cplusplus <= 201402L
+// expected-error@-2 {{no matching constructor}}
+#endif
+
+struct BaseCtor { BaseCtor() = default; }; // expected-note 0+ {{candidate}}
+struct InheritsCtor : BaseCtor { // expected-note 1+ {{candidate}}
+ using BaseCtor::BaseCtor; // expected-note 2 {{inherited here}}
+ int x;
+};
+InheritsCtor II = {{}, 42}; // expected-error {{no matching constructor}}
+
+namespace std_example {
+ struct A {
+ explicit A() = default; // expected-note 2{{declared here}}
+ };
+
+ struct B : A {
+ explicit B() = default; // expected-note 2{{declared here}}
+ };
+
+ struct C {
+ explicit C(); // expected-note 2{{declared here}}
+ };
+
+ struct D : A {
+ C c;
+ explicit D() = default; // expected-note 2{{declared here}}
+ };
+
+ template <typename T> void f() {
+ T t; // ok
+ T u{}; // ok
+ T v = {}; // expected-error 4{{explicit}}
+ }
+ template <typename T> void g() {
+ void x(T t); // expected-note 4{{parameter}}
+ x({}); // expected-error 4{{explicit}}
+ }
+
+ void test() {
+ f<A>(); // expected-note {{instantiation of}}
+ f<B>(); // expected-note {{instantiation of}}
+ f<C>(); // expected-note {{instantiation of}}
+ f<D>(); // expected-note {{instantiation of}}
+ g<A>(); // expected-note {{instantiation of}}
+ g<B>(); // expected-note {{instantiation of}}
+ g<C>(); // expected-note {{instantiation of}}
+ g<D>(); // expected-note {{instantiation of}}
+ }
+}
+#endif // __cplusplus >= 201103L
+}
namespace dr1550 { // dr1550: yes
int f(bool b, int n) {
diff --git a/test/CXX/drs/dr16xx.cpp b/test/CXX/drs/dr16xx.cpp
index 65467e35e4d6..02aa5f9909eb 100644
--- a/test/CXX/drs/dr16xx.cpp
+++ b/test/CXX/drs/dr16xx.cpp
@@ -3,10 +3,6 @@
// 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-no-diagnostics
-#endif
-
namespace dr1684 { // dr1684: 3.6
#if __cplusplus >= 201103L
struct NonLiteral { // expected-note {{because}}
@@ -44,6 +40,35 @@ namespace dr1631 { // dr1631: 3.7
#endif
}
+namespace dr1638 { // dr1638: yes
+#if __cplusplus >= 201103L
+ template<typename T> struct A {
+ enum class E; // expected-note {{previous}}
+ enum class F : T; // expected-note 2{{previous}}
+ };
+
+ template<> enum class A<int>::E;
+ template<> enum class A<int>::E {};
+ template<> enum class A<int>::F : int;
+ template<> enum class A<int>::F : int {};
+
+ template<> enum class A<short>::E : int;
+ template<> enum class A<short>::E : int {};
+
+ template<> enum class A<short>::F; // expected-error {{different underlying type}}
+ template<> enum class A<char>::E : char; // expected-error {{different underlying type}}
+ template<> enum class A<char>::F : int; // expected-error {{different underlying type}}
+
+ enum class A<unsigned>::E; // expected-error {{template specialization requires 'template<>'}} expected-error {{nested name specifier}}
+ template enum class A<unsigned>::E; // expected-error {{enumerations cannot be explicitly instantiated}}
+ enum class A<unsigned>::E *e; // expected-error {{must use 'enum' not 'enum class'}}
+
+ struct B {
+ friend enum class A<unsigned>::E; // expected-error {{must use 'enum' not 'enum class'}}
+ };
+#endif
+}
+
namespace dr1645 { // dr1645: 3.9
#if __cplusplus >= 201103L
struct A { // expected-note 2{{candidate}}
@@ -60,3 +85,19 @@ namespace dr1645 { // dr1645: 3.9
constexpr B b(0, 0); // expected-error {{ambiguous}}
#endif
}
+
+namespace dr1653 { // dr1653: 4.0 c++17
+ void f(bool b) {
+ ++b;
+ b++;
+#if __cplusplus <= 201402L
+ // expected-warning@-3 {{deprecated}} expected-warning@-2 {{deprecated}}
+#else
+ // expected-error@-5 {{incrementing expression of type bool}} expected-error@-4 {{incrementing expression of type bool}}
+#endif
+ --b; // expected-error {{cannot decrement expression of type bool}}
+ b--; // expected-error {{cannot decrement expression of type bool}}
+ b += 1; // ok
+ b -= 1; // ok
+ }
+}
diff --git a/test/CXX/drs/dr18xx.cpp b/test/CXX/drs/dr18xx.cpp
index bc72b67d1e0b..436bccc8e42e 100644
--- a/test/CXX/drs/dr18xx.cpp
+++ b/test/CXX/drs/dr18xx.cpp
@@ -7,11 +7,11 @@
// expected-no-diagnostics
#endif
-void dr1891() { // dr1891: 3.6
+void dr1891() { // dr1891: 4.0
#if __cplusplus >= 201103L
int n;
- auto a = []{}; // expected-note 2{{candidate}}
- auto b = [=]{ return n; }; // expected-note 2{{candidate}}
+ auto a = []{}; // expected-note 2{{candidate}} expected-note 2{{here}}
+ auto b = [=]{ return n; }; // expected-note 2{{candidate}} expected-note 2{{here}}
typedef decltype(a) A;
typedef decltype(b) B;
@@ -20,5 +20,10 @@ void dr1891() { // dr1891: 3.6
A x; // expected-error {{no matching constructor}}
B y; // expected-error {{no matching constructor}}
+
+ a = a; // expected-error {{copy assignment operator is implicitly deleted}}
+ a = static_cast<A&&>(a); // expected-error {{copy assignment operator is implicitly deleted}}
+ b = b; // expected-error {{copy assignment operator is implicitly deleted}}
+ b = static_cast<B&&>(b); // expected-error {{copy assignment operator is implicitly deleted}}
#endif
}
diff --git a/test/CXX/drs/dr1xx.cpp b/test/CXX/drs/dr1xx.cpp
index 8d368a5a54e8..9521f0a8b784 100644
--- a/test/CXX/drs/dr1xx.cpp
+++ b/test/CXX/drs/dr1xx.cpp
@@ -35,7 +35,7 @@ namespace dr102 { // dr102: yes
}
// dr103: na
-// dr104 FIXME: add codegen test
+// dr104: na lib
// dr105: na
namespace dr106 { // dr106: sup 540
@@ -202,7 +202,7 @@ namespace dr116 { // dr116: yes
}
// dr117: na
-// dr118 FIXME: add codegen test
+// dr118 is in its own file.
// dr119: na
// dr120: na
@@ -235,13 +235,11 @@ namespace dr125 {
friend dr125_A (::dr125_B::dr125_C)(); // ok
friend dr125_A::dr125_B::dr125_C(); // expected-error {{did you mean the constructor name 'dr125_B'?}}
// expected-error@-1 {{missing exception specification}}
-#if __cplusplus >= 201103L
- // expected-error@-3 {{follows constexpr declaration}} expected-note@-10 {{here}}
-#endif
};
}
namespace dr126 { // dr126: no
+#if __cplusplus <= 201402L
struct C {};
struct D : C {};
struct E : private C { friend class A; friend class B; };
@@ -314,12 +312,15 @@ namespace dr126 { // dr126: no
virtual void y() throw(int*); // ok
virtual void z() throw(long); // expected-error {{more lax}}
};
+#else
+ void f() throw(int); // expected-error {{ISO C++1z does not allow}} expected-note {{use 'noexcept}}
+#endif
}
namespace dr127 { // dr127: yes
__extension__ typedef __decltype(sizeof(0)) size_t;
template<typename T> struct A {
- A() throw(int);
+ A() { throw 0; }
void *operator new(size_t, const char * = 0);
void operator delete(void *, const char *) { T::error; } // expected-error 2{{no members}}
void operator delete(void *) { T::error; }
@@ -579,11 +580,18 @@ namespace dr151 { // dr151: yes
namespace dr152 { // dr152: yes
struct A {
- A(); // expected-note {{not viable}}
+ A(); // expected-note 0-2{{not viable}}
explicit A(const A&);
};
- A a1 = A(); // expected-error {{no matching constructor}}
+ A a1 = A();
+#if __cplusplus <= 201402L
+ // expected-error@-2 {{no matching constructor}}
+#endif
A a2((A()));
+
+ A &f();
+ A a3 = f(); // expected-error {{no matching constructor}}
+ A a4(f());
}
// dr153: na
@@ -600,7 +608,7 @@ namespace dr155 { // dr155: dup 632
struct S { int n; } s = { { 1 } }; // expected-warning {{braces around scalar initializer}}
}
-// dr158 FIXME write codegen test
+// dr158 is in its own file.
namespace dr159 { // dr159: 3.5
namespace X { void f(); }
@@ -826,11 +834,20 @@ namespace dr176 { // dr176: yes
namespace dr177 { // dr177: yes
struct B {};
struct A {
- A(A &); // expected-note {{not viable: expects an l-value}}
- A(const B &);
+ A(A &); // expected-note 0-1{{not viable: expects an l-value}}
+ A(const B &); // expected-note 0-1{{not viable: no known conversion from 'dr177::A' to}}
};
B b;
- A a = b; // expected-error {{no viable constructor copying variable}}
+ A a = b;
+#if __cplusplus <= 201402L
+ // expected-error@-2 {{no viable constructor copying variable}}
+#endif
+
+ struct C { C(C&); }; // expected-note {{not viable: no known conversion from 'dr177::D' to 'dr177::C &'}}
+ struct D : C {};
+ struct E { operator D(); };
+ E e;
+ C c = e; // expected-error {{no viable constructor copying variable of type 'dr177::D'}}
}
namespace dr178 { // dr178: yes
diff --git a/test/CXX/drs/dr2xx.cpp b/test/CXX/drs/dr2xx.cpp
index 25c853590ae6..a9f0c8fcc999 100644
--- a/test/CXX/drs/dr2xx.cpp
+++ b/test/CXX/drs/dr2xx.cpp
@@ -620,7 +620,7 @@ namespace dr254 { // dr254: yes
template<typename T> struct A {
typedef typename T::type type; // ok even if this is a typedef-name, because
// it's not an elaborated-type-specifier
- typedef struct T::type foo; // expected-error {{elaborated type refers to a typedef}}
+ typedef struct T::type foo; // expected-error {{typedef 'type' cannot be referenced with a struct specifier}}
};
struct B { struct type {}; };
struct C { typedef struct {} type; }; // expected-note {{here}}
@@ -679,17 +679,13 @@ namespace dr258 { // dr258: yes
} f; // expected-error {{abstract}}
}
-namespace dr259 { // dr259: yes c++11
+namespace dr259 { // dr259: 4.0
template<typename T> struct A {};
template struct A<int>; // expected-note {{previous}}
template struct A<int>; // expected-error {{duplicate explicit instantiation}}
- // FIXME: We only apply this DR in C++11 mode.
- template<> struct A<float>;
- template struct A<float>;
-#if __cplusplus < 201103L
- // expected-error@-2 {{extension}} expected-note@-3 {{here}}
-#endif
+ template<> struct A<float>; // expected-note {{previous}}
+ template struct A<float>; // expected-warning {{has no effect}}
template struct A<char>; // expected-note {{here}}
template<> struct A<char>; // expected-error {{explicit specialization of 'dr259::A<char>' after instantiation}}
@@ -702,11 +698,8 @@ namespace dr259 { // dr259: yes c++11
template<typename T> struct B; // expected-note {{here}}
template struct B<int>; // expected-error {{undefined}}
- template<> struct B<float>;
- template struct B<float>;
-#if __cplusplus < 201103L
- // expected-error@-2 {{extension}} expected-note@-3 {{here}}
-#endif
+ template<> struct B<float>; // expected-note {{previous}}
+ template struct B<float>; // expected-warning {{has no effect}}
}
// FIXME: When dr260 is resolved, also add tests for DR507.
@@ -990,12 +983,32 @@ namespace dr289 { // dr289: yes
namespace dr294 { // dr294: no
void f() throw(int);
+#if __cplusplus > 201402L
+ // expected-error@-2 {{ISO C++1z does not allow}} expected-note@-2 {{use 'noexcept}}
+#endif
int main() {
- (void)static_cast<void (*)() throw()>(f); // FIXME: ill-formed
- (void)static_cast<void (*)() throw(int)>(f); // FIXME: ill-formed
+ (void)static_cast<void (*)() throw()>(f); // FIXME: ill-formed in C++14 and before
+#if __cplusplus > 201402L
+ // FIXME: expected-error@-2 {{not allowed}}
+ //
+ // Irony: the above is valid in C++17 and beyond, but that's exactly when
+ // we reject it. In C++14 and before, this is ill-formed because an
+ // exception-specification is not permitted in a type-id. In C++17, this is
+ // valid because it's the inverse of a standard conversion sequence
+ // containing a function pointer conversion. (Well, it's actually not valid
+ // yet, as a static_cast is not permitted to reverse a function pointer
+ // conversion, but that is being changed by core issue).
+#endif
+ (void)static_cast<void (*)() throw(int)>(f); // FIXME: ill-formed in C++14 and before
+#if __cplusplus > 201402L
+ // expected-error@-2 {{ISO C++1z does not allow}} expected-note@-2 {{use 'noexcept}}
+#endif
- void (*p)() throw() = f; // expected-error {{not superset}}
+ void (*p)() throw() = f; // expected-error-re {{{{not superset|different exception specification}}}}
void (*q)() throw(int) = f;
+#if __cplusplus > 201402L
+ // expected-error@-2 {{ISO C++1z does not allow}} expected-note@-2 {{use 'noexcept}}
+#endif
}
}
@@ -1035,8 +1048,8 @@ namespace dr298 { // dr298: yes
C::type i3;
struct A a;
- struct B b; // expected-error {{refers to a typedef}}
- struct C c; // expected-error {{refers to a typedef}}
+ struct B b; // expected-error {{typedef 'B' cannot be referenced with a struct specifier}}
+ struct C c; // expected-error {{typedef 'C' cannot be referenced with a struct specifier}}
B::B() {} // expected-error {{requires a type specifier}}
B::A() {} // ok
diff --git a/test/CXX/drs/dr4xx.cpp b/test/CXX/drs/dr4xx.cpp
index b1c21f8631dd..6046c4afefd5 100644
--- a/test/CXX/drs/dr4xx.cpp
+++ b/test/CXX/drs/dr4xx.cpp
@@ -90,7 +90,7 @@ namespace dr407 { // dr407: 3.8
struct S *p;
{
typedef struct S S; // expected-note {{here}}
- struct S *p; // expected-error {{refers to a typedef}}
+ struct S *p; // expected-error {{typedef 'S' cannot be referenced with a struct specifier}}
}
}
struct S {};
@@ -327,7 +327,7 @@ namespace dr420 { // dr420: yes
namespace dr421 { // dr421: yes
struct X { X(); int n; int &r; };
- int *p = &X().n; // expected-error {{taking the address of a temporary}}
+ int *p = &X().n; // expected-error-re {{{{taking the address of a temporary|cannot take the address of an rvalue}}}}
int *q = &X().r;
}
@@ -508,9 +508,18 @@ namespace dr437 { // dr437: sup 1308
template<typename U> struct T : U {};
struct S {
void f() throw(S);
+#if __cplusplus > 201402L
+ // expected-error@-2 {{ISO C++1z does not allow}} expected-note@-2 {{use 'noexcept}}
+#endif
void g() throw(T<S>);
+#if __cplusplus > 201402L
+ // expected-error@-2 {{ISO C++1z does not allow}} expected-note@-2 {{use 'noexcept}}
+#endif
struct U;
void h() throw(U);
+#if __cplusplus > 201402L
+ // expected-error@-2 {{ISO C++1z does not allow}} expected-note@-2 {{use 'noexcept}}
+#endif
struct U {};
};
}
@@ -553,12 +562,21 @@ namespace dr446 { // dr446: yes
void(b ? a : a);
b ? A() : a; // expected-error {{deleted}}
b ? a : A(); // expected-error {{deleted}}
- b ? A() : A(); // expected-error {{deleted}}
+ b ? A() : A();
+#if __cplusplus <= 201402L
+ // expected-error@-2 {{deleted}}
+#endif
void(b ? a : c);
b ? a : C(); // expected-error {{deleted}}
- b ? c : A(); // expected-error {{deleted}}
- b ? A() : C(); // expected-error {{deleted}}
+ b ? c : A();
+#if __cplusplus <= 201402L
+ // expected-error@-2 {{deleted}}
+#endif
+ b ? A() : C();
+#if __cplusplus <= 201402L
+ // expected-error@-2 {{deleted}}
+#endif
}
}
@@ -874,10 +892,12 @@ namespace dr479 { // dr479: yes
void f() {
throw S();
// expected-error@-1 {{temporary of type 'dr479::S' has private destructor}}
- // expected-error@-2 {{calling a private constructor}}
- // expected-error@-3 {{exception object of type 'dr479::S' has private destructor}}
+ // expected-error@-2 {{exception object of type 'dr479::S' has private destructor}}
#if __cplusplus < 201103L
- // expected-error@-5 {{C++98 requires an accessible copy constructor}}
+ // expected-error@-4 {{C++98 requires an accessible copy constructor}}
+#endif
+#if __cplusplus <= 201402L
+ // expected-error@-7 {{calling a private constructor}} (copy ctor)
#endif
}
void g() {
diff --git a/test/CXX/drs/dr5xx.cpp b/test/CXX/drs/dr5xx.cpp
index e0bab57e5254..f065128cd4bd 100644
--- a/test/CXX/drs/dr5xx.cpp
+++ b/test/CXX/drs/dr5xx.cpp
@@ -8,6 +8,12 @@
// with -verify.
__extension__ typedef __SIZE_TYPE__ size_t;
void *operator new(size_t); // expected-error 0-1{{missing exception spec}} expected-note{{candidate}}
+#if __cplusplus > 201402L
+namespace std {
+ enum class align_val_t : size_t {};
+}
+void *operator new(size_t, std::align_val_t); // expected-note{{candidate}}
+#endif
namespace dr500 { // dr500: dup 372
class D;
@@ -857,14 +863,13 @@ namespace dr580 { // dr580: partial
// dr582: na
-namespace dr583 { // dr583: no
+namespace dr583 { // dr583: 4.0
// see n3624
int *p;
- // FIXME: These are all ill-formed.
- bool b1 = p < 0;
- bool b2 = p > 0;
- bool b3 = p <= 0;
- bool b4 = p >= 0;
+ bool b1 = p < 0; // expected-error {{ordered comparison between pointer and zero}}
+ bool b2 = p > 0; // expected-error {{ordered comparison between pointer and zero}}
+ bool b3 = p <= 0; // expected-error {{ordered comparison between pointer and zero}}
+ bool b4 = p >= 0; // expected-error {{ordered comparison between pointer and zero}}
}
// dr584: na
@@ -948,6 +953,9 @@ namespace dr591 { // dr591: no
namespace dr595 { // dr595: dup 1330
template<class T> struct X {
void f() throw(T) {}
+#if __cplusplus > 201402L
+ // expected-error@-2 {{ISO C++1z does not allow}} expected-note@-2 {{use 'noexcept}}
+#endif
};
struct S {
X<S> xs;
diff --git a/test/CXX/drs/dr6xx.cpp b/test/CXX/drs/dr6xx.cpp
index 1d37a6d3e80c..9dfcc7d6b464 100644
--- a/test/CXX/drs/dr6xx.cpp
+++ b/test/CXX/drs/dr6xx.cpp
@@ -142,15 +142,21 @@ namespace dr615 { // dr615: yes
static int n = f();
}
-namespace dr616 { // dr616: no
+namespace dr616 { // dr616: 4.0
#if __cplusplus >= 201103L
struct S { int n; } s;
- // FIXME: These should all be 'int &&'
- using T = decltype(S().n);
- using T = decltype(static_cast<S&&>(s).n);
- using T = decltype(S().*&S::n); // expected-note 2{{previous}}
- using T = decltype(static_cast<S&&>(s).*&S::n); // expected-error {{different type}}
- using T = int&&; // expected-error {{different type}}
+ S f();
+ using T = decltype((S().n));
+ using T = decltype((static_cast<S&&>(s).n));
+ using T = decltype((f().n));
+ using T = decltype(S().*&S::n);
+ using T = decltype(static_cast<S&&>(s).*&S::n);
+ using T = decltype(f().*&S::n);
+ using T = int&&;
+
+ using U = decltype(S().n);
+ using U = decltype(static_cast<S&&>(s).n);
+ using U = int;
#endif
}
@@ -347,3 +353,66 @@ namespace dr639 { // dr639: yes
void((i = 0) + (i = 0)); // expected-warning {{unsequenced}}
}
}
+
+namespace dr692 { // dr692: no
+ namespace temp_func_order_example2 {
+ template <typename T, typename U> struct A {};
+ template <typename T, typename U> void f(U, A<U, T> *p = 0); // expected-note {{candidate}}
+ template <typename U> int &f(U, A<U, U> *p = 0); // expected-note {{candidate}}
+ template <typename T> void g(T, T = T());
+ template <typename T, typename... U> void g(T, U...); // expected-error 0-1{{C++11}}
+ void h() {
+ int &r = f<int>(42, (A<int, int> *)0);
+ f<int>(42); // expected-error {{ambiguous}}
+ // FIXME: We should reject this due to ambiguity between the pack and the
+ // default argument. Only parameters with arguments are considered during
+ // partial ordering of function templates.
+ g(42);
+ }
+ }
+
+ namespace temp_func_order_example3 {
+ template <typename T, typename... U> void f(T, U...); // expected-error 0-1{{C++11}}
+ template <typename T> void f(T);
+ template <typename T, typename... U> int &g(T *, U...); // expected-error 0-1{{C++11}}
+ template <typename T> void g(T);
+ void h(int i) {
+ // This is made ambiguous by dr692, but made valid again by dr1395.
+ f(&i);
+ int &r = g(&i);
+ }
+ }
+
+ namespace temp_deduct_partial_example {
+ template <typename... Args> char &f(Args... args); // expected-error 0-1{{C++11}}
+ template <typename T1, typename... Args> short &f(T1 a1, Args... args); // expected-error 0-1{{C++11}}
+ template <typename T1, typename T2> int &f(T1 a1, T2 a2);
+ void g() {
+ char &a = f();
+ short &b = f(1, 2, 3);
+ int &c = f(1, 2);
+ }
+ }
+
+ namespace temp_deduct_type_example1 {
+ template <class T1, class ...Z> class S; // expected-error 0-1{{C++11}}
+ template <class T1, class ...Z> class S<T1, const Z&...>; // expected-error 0-1{{C++11}}
+ template <class T1, class T2> class S<T1, const T2&> {};
+ S<int, const int&> s;
+
+ // FIXME: This should select the first partial specialization. Deduction of
+ // the second from the first should succeed, because we should ignore the
+ // trailing pack in A with no corresponding P.
+ template<class T, class... U> struct A; // expected-error 0-1{{C++11}}
+ template<class T1, class T2, class... U> struct A<T1,T2*,U...>; // expected-note {{matches}} expected-error 0-1{{C++11}}
+ template<class T1, class T2> struct A<T1,T2> {}; // expected-note {{matches}}
+ template struct A<int, int*>; // expected-error {{ambiguous}}
+ }
+
+ namespace temp_deduct_type_example3 {
+ // FIXME: This should select the first template, as in the case above.
+ template<class T, class... U> void f(T*, U...){} // expected-note {{candidate}} expected-error 0-1{{C++11}}
+ template<class T> void f(T){} // expected-note {{candidate}}
+ template void f(int*); // expected-error {{ambiguous}}
+ }
+}
diff --git a/test/CXX/except/except.spec/p2-places-1z.cpp b/test/CXX/except/except.spec/p2-places-1z.cpp
new file mode 100644
index 000000000000..619ea33b5349
--- /dev/null
+++ b/test/CXX/except/except.spec/p2-places-1z.cpp
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -std=c++1z -fexceptions -fcxx-exceptions -fsyntax-only -verify %s
+
+// In C++1z, we can put an exception-specification on any function declarator; the
+// corresponding paragraph from C++14 and before was deleted.
+// expected-no-diagnostics
+
+void f() noexcept;
+void (*fp)() noexcept;
+void (**fpp)() noexcept;
+void g(void (**pfa)() noexcept);
+void (**h())() noexcept;
+
+template<typename T> struct A {};
+template<void() noexcept> struct B {};
+A<void() noexcept> a;
+B<f> b;
+auto *p = new decltype(f)**;
diff --git a/test/CXX/except/except.spec/p2-places.cpp b/test/CXX/except/except.spec/p2-places.cpp
index 67647fb043a9..ea842af89845 100644
--- a/test/CXX/except/except.spec/p2-places.cpp
+++ b/test/CXX/except/except.spec/p2-places.cpp
@@ -37,6 +37,8 @@ namespace dyn {
// Pointer to function returning pointer to pointer to function with spec
void (**(*h())())() throw(int); // expected-error {{not allowed beyond a single}}
+ // FIXME: Missing a lot of negative tests, primarily type-ids in various places
+ // We fail to diagnose all of those.
}
namespace noex {
diff --git a/test/CXX/except/except.spec/p5-pointers.cpp b/test/CXX/except/except.spec/p5-pointers.cpp
index fe4a264587f5..dedc5bd376f9 100644
--- a/test/CXX/except/except.spec/p5-pointers.cpp
+++ b/test/CXX/except/except.spec/p5-pointers.cpp
@@ -41,25 +41,25 @@ void fnptrs()
{
// Assignment and initialization of function pointers.
void (*t1)() throw() = &s1; // valid
- t1 = &s2; // expected-error {{not superset}} expected-error {{incompatible type}}
- t1 = &s3; // expected-error {{not superset}} expected-error {{incompatible type}}
+ t1 = &s2; // expected-error {{not superset}}
+ t1 = &s3; // expected-error {{not superset}}
void (&t2)() throw() = s2; // expected-error {{not superset}}
void (*t3)() throw(int) = &s2; // valid
void (*t4)() throw(A) = &s1; // valid
t4 = &s3; // valid
t4 = &s4; // valid
- t4 = &s5; // expected-error {{not superset}} expected-error {{incompatible type}}
+ t4 = &s5; // expected-error {{not superset}}
void (*t5)() = &s1; // valid
t5 = &s2; // valid
t5 = &s6; // valid
t5 = &s7; // valid
- t1 = t3; // expected-error {{not superset}} expected-error {{incompatible type}}
+ t1 = t3; // expected-error {{not superset}}
t3 = t1; // valid
void (*t6)() throw(B1);
- t6 = t4; // expected-error {{not superset}} expected-error {{incompatible type}}
+ t6 = t4; // expected-error {{not superset}}
t4 = t6; // valid
t5 = t1; // valid
- t1 = t5; // expected-error {{not superset}} expected-error {{incompatible type}}
+ t1 = t5; // expected-error {{not superset}}
// return types and arguments must match exactly, no inheritance allowed
void (*(*t7)())() throw(B1) = &s8; // valid
diff --git a/test/CXX/expr/expr.cond/p4.cpp b/test/CXX/expr/expr.cond/p4.cpp
new file mode 100644
index 000000000000..4d0cf3538cf0
--- /dev/null
+++ b/test/CXX/expr/expr.cond/p4.cpp
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -std=c++98 -verify %s
+// RUN: %clang_cc1 -std=c++1z -verify %s
+
+// expected-no-diagnostics
+
+struct A { A(); A(int); };
+void f() {
+ const A a;
+ true ? a : 0;
+}
diff --git a/test/CXX/expr/expr.const/p2-0x.cpp b/test/CXX/expr/expr.const/p2-0x.cpp
index fd15960647ca..6d46bf5d77dd 100644
--- a/test/CXX/expr/expr.const/p2-0x.cpp
+++ b/test/CXX/expr/expr.const/p2-0x.cpp
@@ -33,11 +33,11 @@ struct NonConstexpr3 {
int m : NonConstexpr2().n; // expected-error {{constant expression}} expected-note {{undefined constructor 'NonConstexpr2'}}
};
struct NonConstexpr4 {
- NonConstexpr4(); // expected-note {{declared here}}
+ NonConstexpr4();
int n;
};
struct NonConstexpr5 {
- int n : NonConstexpr4().n; // expected-error {{constant expression}} expected-note {{non-constexpr constructor 'NonConstexpr4' cannot be used in a constant expression}}
+ int n : NonConstexpr4().n; // expected-error {{constant expression}} expected-note {{non-literal type 'NonConstexpr4' cannot be used in a constant expression}}
};
// - an invocation of an undefined constexpr function or an undefined
@@ -321,7 +321,7 @@ namespace LValueToRValue {
// temporary object whose lifetime has not ended, initialized with a
// constant expression;
constexpr volatile S f() { return S(); }
- static_assert(f().i, ""); // ok! there's no lvalue-to-rvalue conversion here!
+ static_assert(f().i, ""); // expected-error {{constant expression}} expected-note {{read of volatile-qualified type}}
static_assert(((volatile const S&&)(S)0).i, ""); // expected-error {{constant expression}} expected-note {{read of volatile-qualified type}}
}
@@ -461,14 +461,14 @@ namespace UnspecifiedRelations {
constexpr bool u2 = p > q; // expected-error {{constant expression}}
constexpr bool u3 = p <= q; // expected-error {{constant expression}}
constexpr bool u4 = p >= q; // expected-error {{constant expression}}
- constexpr bool u5 = p < 0; // expected-error {{constant expression}}
- constexpr bool u6 = p <= 0; // expected-error {{constant expression}}
- constexpr bool u7 = p > 0; // expected-error {{constant expression}}
- constexpr bool u8 = p >= 0; // expected-error {{constant expression}}
- constexpr bool u9 = 0 < q; // expected-error {{constant expression}}
- constexpr bool u10 = 0 <= q; // expected-error {{constant expression}}
- constexpr bool u11 = 0 > q; // expected-error {{constant expression}}
- constexpr bool u12 = 0 >= q; // expected-error {{constant expression}}
+ constexpr bool u5 = p < (int*)0; // expected-error {{constant expression}}
+ constexpr bool u6 = p <= (int*)0; // expected-error {{constant expression}}
+ constexpr bool u7 = p > (int*)0; // expected-error {{constant expression}}
+ constexpr bool u8 = p >= (int*)0; // expected-error {{constant expression}}
+ constexpr bool u9 = (int*)0 < q; // expected-error {{constant expression}}
+ constexpr bool u10 = (int*)0 <= q; // expected-error {{constant expression}}
+ constexpr bool u11 = (int*)0 > q; // expected-error {{constant expression}}
+ constexpr bool u12 = (int*)0 >= q; // expected-error {{constant expression}}
void f(), g();
constexpr void (*pf)() = &f, (*pg)() = &g;
@@ -522,7 +522,7 @@ namespace UnspecifiedRelations {
constexpr void *null = 0;
constexpr void *pv = (void*)&s.a;
constexpr void *qv = (void*)&s.b;
- constexpr bool v1 = null < 0;
+ constexpr bool v1 = null < (int*)0;
constexpr bool v2 = null < pv; // expected-error {{constant expression}}
constexpr bool v3 = null == pv; // ok
constexpr bool v4 = qv == pv; // ok
diff --git a/test/CXX/expr/expr.const/p3-0x.cpp b/test/CXX/expr/expr.const/p3-0x.cpp
index d9d84853ebae..731e0c312fa1 100644
--- a/test/CXX/expr/expr.const/p3-0x.cpp
+++ b/test/CXX/expr/expr.const/p3-0x.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++1z -verify %s
// A converted constant expression of type T is a core constant expression,
int nonconst = 8; // expected-note 3 {{here}}
@@ -40,10 +41,10 @@ const E e10 = E10;
template<E> struct T {};
T<e10> s10;
-// integral promotions, and
+// integral promotions,
enum class EE { EE32 = ' ', EE65 = 'A', EE1 = (short)1, EE5 = E5 };
-// integral conversions other than narrowing conversions
+// integral conversions other than narrowing conversions,
int b(unsigned n) {
switch (n) {
case E6:
@@ -74,12 +75,22 @@ using Int = A<-3>; // expected-error {{template argument evaluates to -3, which
// Note, conversions from integral or unscoped enumeration types to bool are
// integral conversions as well as boolean conversions.
+// FIXME: Per core issue 1407, this is not correct.
template<typename T, T v> struct Val { static constexpr T value = v; };
static_assert(Val<bool, E1>::value == 1, ""); // ok
static_assert(Val<bool, '\0'>::value == 0, ""); // ok
static_assert(Val<bool, U'\1'>::value == 1, ""); // ok
static_assert(Val<bool, E5>::value == 1, ""); // expected-error {{5, which cannot be narrowed to type 'bool'}}
+// function pointer conversions [C++17]
+void noexcept_false() noexcept(false);
+void noexcept_true() noexcept(true);
+Val<decltype(&noexcept_false), &noexcept_true> remove_noexcept;
+Val<decltype(&noexcept_true), &noexcept_false> add_noexcept;
+#if __cplusplus > 201402L
+// expected-error@-2 {{value of type 'void (*)() noexcept(false)' is not implicitly convertible to 'void (*)() noexcept'}}
+#endif
+
// (no other conversions are permitted)
using Int = A<1.0>; // expected-error {{conversion from 'double' to 'unsigned char' is not allowed in a converted constant expression}}
enum B : bool {
diff --git a/test/CXX/expr/expr.post/expr.static.cast/p3-p4-0x.cpp b/test/CXX/expr/expr.post/expr.static.cast/p3-p4-0x.cpp
new file mode 100644
index 000000000000..8701a00d5cf0
--- /dev/null
+++ b/test/CXX/expr/expr.post/expr.static.cast/p3-p4-0x.cpp
@@ -0,0 +1,43 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+
+
+// p3
+// A glvalue of type "cv1 T1" can be cast to type "rvalue reference to
+// cv2 T2" if "cv2 T2" is reference-compatible with "cv1 T1" (8.5.3).
+// p4
+// Otherwise, an expression e can be explicitly converted to a type T using a
+// static_cast of the form static_cast<T>(e) if the declaration T t(e); is
+// well-formed, for some invented temporary variable t (8.5). [...]
+struct A { };
+struct B : A { };
+
+struct C { explicit operator A&&(); };
+struct D { operator B(); };
+
+template<typename T> T& lvalue();
+template<typename T> T&& xvalue();
+template <typename T> T prvalue();
+
+void test(A &a, B &b) {
+ A &&ar0 = static_cast<A&&>(prvalue<A>());
+ A &&ar1 = static_cast<A&&>(prvalue<B>());
+ A &&ar2 = static_cast<A&&>(lvalue<C>());
+ A &&ar3 = static_cast<A&&>(xvalue<C>());
+ A &&ar4 = static_cast<A&&>(prvalue<C>());
+ A &&ar5 = static_cast<A&&>(lvalue<D>());
+ A &&ar6 = static_cast<A&&>(xvalue<D>());
+ A &&ar7 = static_cast<A&&>(prvalue<D>());
+
+ A &&ar8 = static_cast<A&&>(prvalue<const A>()); // expected-error {{binding value of type 'const A' to reference to type 'A' drops 'const' qualifier}}
+ A &&ar9 = static_cast<A&&>(lvalue<const A>()); // expected-error {{cannot cast from lvalue of type 'const A'}}
+ A &&ar10 = static_cast<A&&>(xvalue<const A>()); // expected-error {{cannot cast from rvalue of type 'const A'}}
+
+ const A &&ar11 = static_cast<const A&&>(prvalue<A>());
+ const A &&ar12 = static_cast<const A&&>(prvalue<B>());
+ const A &&ar13 = static_cast<const A&&>(lvalue<C>());
+ const A &&ar14 = static_cast<const A&&>(xvalue<C>());
+ const A &&ar15 = static_cast<const A&&>(prvalue<C>());
+ const A &&ar16 = static_cast<const A&&>(lvalue<D>());
+
+ const A &&ar17 = static_cast<const A&&>(prvalue<A const volatile>()); // expected-error {{binding value of type 'const volatile A' to reference to type 'const A' drops 'volatile' qualifier}}
+}
diff --git a/test/CXX/expr/expr.post/expr.static.cast/p7.cpp b/test/CXX/expr/expr.post/expr.static.cast/p7.cpp
new file mode 100644
index 000000000000..fd8e478b5193
--- /dev/null
+++ b/test/CXX/expr/expr.post/expr.static.cast/p7.cpp
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -std=c++1z -verify %s -fcxx-exceptions
+
+void (*p)() noexcept;
+void (*q)();
+
+void f() {
+ // FIXME: This seems like a bad rule.
+ p = static_cast<decltype(p)>(q); // expected-error {{not allowed}}
+ q = static_cast<decltype(q)>(p);
+}
diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p19.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p19.cpp
index 40360e40694c..1dbcbf498031 100644
--- a/test/CXX/expr/expr.prim/expr.prim.lambda/p19.cpp
+++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p19.cpp
@@ -7,7 +7,7 @@ struct MoveOnly {
template<typename T> T &&move(T&);
void test_special_member_functions(MoveOnly mo, int i) {
- auto lambda1 = [i]() { }; // expected-note {{lambda expression begins here}} expected-note 2{{candidate}}
+ auto lambda1 = [i]() { }; // expected-note 2{{lambda expression begins here}} expected-note 2{{candidate}}
// Default constructor
decltype(lambda1) lambda2; // expected-error{{no matching constructor}}
@@ -16,7 +16,7 @@ void test_special_member_functions(MoveOnly mo, int i) {
lambda1 = lambda1; // expected-error{{copy assignment operator is implicitly deleted}}
// Move assignment operator
- lambda1 = move(lambda1);
+ lambda1 = move(lambda1); // expected-error{{copy assignment operator is implicitly deleted}}
// Copy constructor
decltype(lambda1) lambda3 = lambda1;
diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p6.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p6.cpp
index 8b43cefa92c0..90a3aec50cb3 100644
--- a/test/CXX/expr/expr.prim/expr.prim.lambda/p6.cpp
+++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p6.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify
+// RUN: %clang_cc1 -fsyntax-only -std=c++1z %s -verify
void test_conversion() {
int (*fp1)(int) = [](int x) { return x + 1; };
@@ -9,6 +10,15 @@ void test_conversion() {
volatile const auto lambda2 = [](int x) { }; // expected-note{{but method is not marked volatile}}
void (*fp4)(int) = lambda2; // expected-error{{no viable conversion}}
+
+ void (*fp5)(int) noexcept = [](int x) { };
+#if __cplusplus > 201402L
+ // expected-error@-2 {{no viable}} expected-note@-2 {{candidate}}
+ void (*fp5a)(int) noexcept = [](auto x) { };
+ // expected-error@-1 {{no viable}} expected-note@-1 {{candidate}}
+ void (*fp5b)(int) noexcept = [](auto x) noexcept { };
+#endif
+ void (*fp6)(int) noexcept = [](int x) noexcept { };
}
void test_no_conversion() {
diff --git a/test/CXX/expr/expr.unary/expr.delete/p10.cpp b/test/CXX/expr/expr.unary/expr.delete/p10.cpp
new file mode 100644
index 000000000000..aad2747dd32f
--- /dev/null
+++ b/test/CXX/expr/expr.unary/expr.delete/p10.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -std=c++1z -verify %s
+
+using size_t = decltype(sizeof(0));
+namespace std { enum class align_val_t : size_t {}; }
+
+// Aligned version is preferred over unaligned version,
+// unsized version is preferred over sized version.
+template<unsigned Align>
+struct alignas(Align) A {
+ void operator delete(void*);
+ void operator delete(void*, std::align_val_t) = delete; // expected-note {{here}}
+
+ void operator delete(void*, size_t) = delete;
+ void operator delete(void*, size_t, std::align_val_t) = delete;
+};
+void f(A<__STDCPP_DEFAULT_NEW_ALIGNMENT__> *p) { delete p; }
+void f(A<__STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2> *p) { delete p; } // expected-error {{deleted}}
+
+template<unsigned Align>
+struct alignas(Align) B {
+ void operator delete(void*, size_t);
+ void operator delete(void*, size_t, std::align_val_t) = delete; // expected-note {{here}}
+};
+void f(B<__STDCPP_DEFAULT_NEW_ALIGNMENT__> *p) { delete p; }
+void f(B<__STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2> *p) { delete p; } // expected-error {{deleted}}
diff --git a/test/CXX/expr/expr.unary/expr.new/p14.cpp b/test/CXX/expr/expr.unary/expr.new/p14.cpp
new file mode 100644
index 000000000000..6537cdcfeafa
--- /dev/null
+++ b/test/CXX/expr/expr.unary/expr.new/p14.cpp
@@ -0,0 +1,69 @@
+// RUN: %clang_cc1 -std=c++1z -fsized-deallocation -fexceptions %s -verify
+
+using size_t = decltype(sizeof(0));
+namespace std { enum class align_val_t : size_t {}; }
+
+struct Arg {} arg;
+
+// If the type is aligned, first try with an alignment argument and then
+// without. If not, never consider supplying an alignment.
+
+template<unsigned Align, typename ...Ts>
+struct alignas(Align) Unaligned {
+ void *operator new(size_t, Ts...) = delete; // expected-note 4{{deleted}}
+};
+auto *ua = new Unaligned<__STDCPP_DEFAULT_NEW_ALIGNMENT__>; // expected-error {{deleted}}
+auto *ub = new Unaligned<__STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2>; // expected-error {{deleted}}
+auto *uap = new (arg) Unaligned<__STDCPP_DEFAULT_NEW_ALIGNMENT__, Arg>; // expected-error {{deleted}}
+auto *ubp = new (arg) Unaligned<__STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2, Arg>; // expected-error {{deleted}}
+
+template<unsigned Align, typename ...Ts>
+struct alignas(Align) Aligned {
+ void *operator new(size_t, std::align_val_t, Ts...) = delete; // expected-note 2{{deleted}} expected-note 2{{not viable}}
+};
+auto *aa = new Aligned<__STDCPP_DEFAULT_NEW_ALIGNMENT__>; // expected-error {{no matching}}
+auto *ab = new Aligned<__STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2>; // expected-error {{deleted}}
+auto *aap = new (arg) Aligned<__STDCPP_DEFAULT_NEW_ALIGNMENT__, Arg>; // expected-error {{no matching}}
+auto *abp = new (arg) Aligned<__STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2, Arg>; // expected-error {{deleted}}
+
+// If both are available, we prefer the aligned version for an overaligned
+// type, and only use the unaligned version for a non-overaligned type.
+
+template<unsigned Align, typename ...Ts>
+struct alignas(Align) Both1 {
+ void *operator new(size_t, Ts...); // expected-note 2{{not viable}}
+ void *operator new(size_t, std::align_val_t, Ts...) = delete; // expected-note 2{{deleted}}
+};
+template<unsigned Align, typename ...Ts>
+struct alignas(Align) Both2 {
+ void *operator new(size_t, Ts...) = delete; // expected-note 2{{deleted}}
+ void *operator new(size_t, std::align_val_t, Ts...); // expected-note 2{{not viable}}
+};
+auto *b1a = new Both1<__STDCPP_DEFAULT_NEW_ALIGNMENT__>;
+auto *b1b = new Both1<__STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2>; // expected-error {{deleted}}
+auto *b2a = new Both2<__STDCPP_DEFAULT_NEW_ALIGNMENT__>; // expected-error {{deleted}}
+auto *b2b = new Both2<__STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2>;
+auto *b1ap = new (arg) Both1<__STDCPP_DEFAULT_NEW_ALIGNMENT__, Arg>;
+auto *b1bp = new (arg) Both1<__STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2, Arg>; // expected-error {{deleted}}
+auto *b2ap = new (arg) Both2<__STDCPP_DEFAULT_NEW_ALIGNMENT__, Arg>; // expected-error {{deleted}}
+auto *b2bp = new (arg) Both2<__STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2, Arg>;
+
+// Note that the aligned form can select a function with a parameter different
+// from std::align_val_t.
+
+struct alignas(__STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2) WeirdAlignedAlloc1 {
+ void *operator new(size_t, ...) = delete; // expected-note 2{{deleted}}
+};
+auto *waa1 = new WeirdAlignedAlloc1; // expected-error {{deleted}}
+auto *waa1p = new (arg) WeirdAlignedAlloc1; // expected-error {{deleted}}
+
+struct alignas(__STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2) WeirdAlignedAlloc2 {
+ template<typename ...T>
+ void *operator new(size_t, T...) {
+ using U = void(T...); // expected-note 2{{previous}}
+ using U = void; // expected-error {{different types ('void' vs 'void (std::align_val_t)')}} \
+ expected-error {{different types ('void' vs 'void (std::align_val_t, Arg)')}}
+ }
+};
+auto *waa2 = new WeirdAlignedAlloc2; // expected-note {{instantiation of}}
+auto *waa2p = new (arg) WeirdAlignedAlloc2; // expected-note {{instantiation of}}
diff --git a/test/CXX/expr/expr.unary/expr.new/p20-0x.cpp b/test/CXX/expr/expr.unary/expr.new/p20-0x.cpp
index eca1ec790199..13676a8a07ce 100644
--- a/test/CXX/expr/expr.unary/expr.new/p20-0x.cpp
+++ b/test/CXX/expr/expr.unary/expr.new/p20-0x.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -fexceptions %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++14 -fexceptions %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++1z -fexceptions %s
typedef __SIZE_TYPE__ size_t;
+namespace std { enum class align_val_t : size_t {}; }
+
struct S {
// Placement allocation function:
static void* operator new(size_t, size_t);
@@ -9,5 +13,56 @@ struct S {
};
void testS() {
- S* p = new (0) S; // expected-error{{'new' expression with placement arguments refers to non-placement 'operator delete'}}
+ S* p = new (0) S; // expected-error{{'new' expression with placement arguments refers to non-placement 'operator delete'}}
+}
+
+struct T {
+ // Placement allocation function:
+ static void* operator new(size_t, size_t);
+ // Usual (non-placement) deallocation function:
+ static void operator delete(void*);
+ // Placement deallocation function:
+ static void operator delete(void*, size_t);
+};
+
+void testT() {
+ T* p = new (0) T; // ok
+}
+
+#if __cplusplus > 201402L
+struct U {
+ // Placement allocation function:
+ static void* operator new(size_t, size_t, std::align_val_t);
+ // Placement deallocation function:
+ static void operator delete(void*, size_t, std::align_val_t); // expected-note{{declared here}}
+};
+
+void testU() {
+ U* p = new (0, std::align_val_t(0)) U; // expected-error{{'new' expression with placement arguments refers to non-placement 'operator delete'}}
+}
+
+struct V {
+ // Placement allocation function:
+ static void* operator new(size_t, size_t, std::align_val_t);
+ // Usual (non-placement) deallocation function:
+ static void operator delete(void*, std::align_val_t);
+ // Placement deallocation function:
+ static void operator delete(void*, size_t, std::align_val_t);
+};
+
+void testV() {
+ V* p = new (0, std::align_val_t(0)) V;
+}
+
+struct W {
+ // Placement allocation function:
+ static void* operator new(size_t, size_t, std::align_val_t);
+ // Usual (non-placement) deallocation functions:
+ static void operator delete(void*);
+ static void operator delete(void*, size_t, std::align_val_t); // expected-note {{declared here}}
+};
+
+void testW() {
+ W* p = new (0, std::align_val_t(0)) W; // expected-error{{'new' expression with placement arguments refers to non-placement 'operator delete'}}
}
+#endif
diff --git a/test/CXX/expr/p13.cpp b/test/CXX/expr/p13.cpp
new file mode 100644
index 000000000000..0f22ce0b7ceb
--- /dev/null
+++ b/test/CXX/expr/p13.cpp
@@ -0,0 +1,51 @@
+// RUN: %clang_cc1 -std=c++1z -verify %s -fexceptions -fcxx-exceptions -Wno-dynamic-exception-spec
+
+struct X {};
+struct Y : X {};
+
+using A = void (*)() noexcept;
+using B = void (*)();
+using C = void (X::*)() noexcept;
+using D = void (X::*)();
+using E = void (Y::*)() noexcept;
+using F = void (Y::*)();
+
+void f(A a, B b, C c, D d, E e, F f, bool k) {
+ a = k ? a : b; // expected-error {{different exception specifications}}
+ b = k ? a : b;
+
+ c = k ? c : d; // expected-error {{different exception specifications}}
+ d = k ? c : d;
+
+ e = k ? c : f; // expected-error {{different exception specifications}}
+ e = k ? d : e; // expected-error {{different exception specifications}}
+ f = k ? c : f;
+ f = k ? d : e;
+
+ const A ak = a;
+ const B bk = b;
+ const A &ak2 = k ? ak : ak;
+ const A &ak3 = k ? ak : bk; // expected-error {{could not bind}}
+ const B &bk3 = k ? ak : bk;
+}
+
+namespace dynamic_exception_spec {
+ // Prior to P0012, we had:
+ // "[...] the target entity shall allow at least the exceptions allowed
+ // by the source value in the assignment or initialization"
+ //
+ // There's really only one way we can coherently apply this to conditional
+ // expressions: this must hold no matter which branch was taken.
+ using X = void (*)() throw(int);
+ using Y = void (*)() throw(float);
+ using Z = void (*)() throw(int, float);
+ void g(X x, Y y, Z z, bool k) {
+ x = k ? X() : Y(); // expected-warning {{not superset}}
+ y = k ? X() : Y(); // expected-warning {{not superset}}
+ z = k ? X() : Y();
+
+ x = k ? x : y; // expected-warning {{not superset}}
+ y = k ? x : y; // expected-warning {{not superset}}
+ z = k ? x : y;
+ }
+}
diff --git a/test/CXX/over/over.built/p15.cpp b/test/CXX/over/over.built/p15.cpp
new file mode 100644
index 000000000000..64ed3e7b83de
--- /dev/null
+++ b/test/CXX/over/over.built/p15.cpp
@@ -0,0 +1,83 @@
+// RUN: %clang_cc1 -std=c++11 -verify %s -Wno-tautological-compare
+
+struct A { operator decltype(nullptr)(); };
+struct B { operator const int *(); };
+void f(A a, B b, volatile int *pi) {
+ (void)(a == a);
+ (void)(a != a);
+ (void)(a < a); // expected-error {{invalid operands}}
+ (void)(a > a); // expected-error {{invalid operands}}
+ (void)(a <= a); // expected-error {{invalid operands}}
+ (void)(a >= a); // expected-error {{invalid operands}}
+
+ (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)(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)(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)(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)(b == pi);
+ (void)(b != pi);
+ (void)(b < pi);
+ (void)(b > pi);
+ (void)(b <= pi);
+ (void)(b >= pi);
+
+ (void)(pi == b);
+ (void)(pi != b);
+ (void)(pi < b);
+ (void)(pi > b);
+ (void)(pi <= b);
+ (void)(pi >= b);
+
+ (void)(b == b);
+ (void)(b != b);
+ (void)(b < b);
+ (void)(b > b);
+ (void)(b <= b);
+ (void)(b >= b);
+
+ (void)(pi == pi);
+ (void)(pi != pi);
+ (void)(pi < pi);
+ (void)(pi > pi);
+ (void)(pi <= pi);
+ (void)(pi >= pi);
+}
+
+// FIXME: This is wrong: the type T = 'const volatile int * const * const *'
+// would work here, and there exists a builtin candidate for that type.
+struct C { operator const int ***(); };
+void g(C c, volatile int ***p) {
+ (void)(c < p); // expected-error {{invalid operands}}
+}
diff --git a/test/CXX/over/over.built/p16.cpp b/test/CXX/over/over.built/p16.cpp
new file mode 100644
index 000000000000..139e86447524
--- /dev/null
+++ b/test/CXX/over/over.built/p16.cpp
@@ -0,0 +1,75 @@
+// RUN: %clang_cc1 -std=c++11 -verify %s -Wno-tautological-compare
+
+struct A { operator decltype(nullptr)(); };
+struct B { operator int A::*(); };
+void f(A a, B b, int A::*pi) {
+ (void)(a == a);
+ (void)(a != a);
+ (void)(a < a); // expected-error {{invalid operands}}
+ (void)(a > a); // expected-error {{invalid operands}}
+ (void)(a <= a); // expected-error {{invalid operands}}
+ (void)(a >= a); // expected-error {{invalid operands}}
+
+ (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);
+ (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);
+ (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);
+ (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);
+ (void)(b < pi); // expected-error {{invalid operands}}
+ (void)(b > pi); // expected-error {{invalid operands}}
+ (void)(b <= pi); // expected-error {{invalid operands}}
+ (void)(b >= pi); // expected-error {{invalid operands}}
+
+ (void)(pi == b);
+ (void)(pi != b);
+ (void)(pi < b); // expected-error {{invalid operands}}
+ (void)(pi > b); // expected-error {{invalid operands}}
+ (void)(pi <= b); // expected-error {{invalid operands}}
+ (void)(pi >= b); // expected-error {{invalid operands}}
+
+ (void)(b == b);
+ (void)(b != b);
+ (void)(b < b); // expected-error {{invalid operands}}
+ (void)(b > b); // expected-error {{invalid operands}}
+ (void)(b <= b); // expected-error {{invalid operands}}
+ (void)(b >= b); // expected-error {{invalid operands}}
+
+ (void)(pi == pi);
+ (void)(pi != pi);
+ (void)(pi < pi); // expected-error {{invalid operands}}
+ (void)(pi > pi); // expected-error {{invalid operands}}
+ (void)(pi <= pi); // expected-error {{invalid operands}}
+ (void)(pi >= pi); // expected-error {{invalid operands}}
+}
+
+// FIXME: This is wrong: type T = 'const volatile int * const A::* const B::*'
+// would work here, and there exists a builtin candidate for that type.
+struct C { operator const int *A::*B::*(); };
+void g(C c, volatile int *A::*B::*p) {
+ (void)(c == p); // expected-error {{invalid operands}}
+}
diff --git a/test/CXX/over/over.match/over.match.best/over.best.ics/over.ics.scs/p3.cpp b/test/CXX/over/over.match/over.match.best/over.best.ics/over.ics.scs/p3.cpp
new file mode 100644
index 000000000000..df2fc2cd2e82
--- /dev/null
+++ b/test/CXX/over/over.match/over.match.best/over.best.ics/over.ics.scs/p3.cpp
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -std=c++1z -verify %s
+
+void f(void() noexcept); // expected-note {{no known conversion from 'void ()' to 'void (*)() noexcept'}}
+void f(void()) = delete; // expected-note {{explicitly deleted}}
+
+void g();
+void h() noexcept;
+
+void test() {
+ f(g); // expected-error {{call to deleted}}
+ f(h);
+}
diff --git a/test/CXX/over/over.oper/over.literal/p6.cpp b/test/CXX/over/over.oper/over.literal/p6.cpp
index 6bfb8560d688..9ecf9ccccb14 100644
--- a/test/CXX/over/over.oper/over.literal/p6.cpp
+++ b/test/CXX/over/over.oper/over.literal/p6.cpp
@@ -1,9 +1,11 @@
// RUN: %clang_cc1 -std=c++11 %s -verify
+// expected-note@+1 {{extern "C" language linkage specification begins here}}
extern "C" void operator "" _a(const char *); // expected-error {{must have C++ linkage}}
extern "C" template<char...> void operator "" _b(); // expected-error {{must have C++ linkage}}
+// expected-note@-1 {{extern "C" language linkage specification begins here}}
-extern "C" {
+extern "C" { // expected-note 4 {{extern "C" language linkage specification begins here}}
void operator "" _c(const char *); // expected-error {{must have C++ linkage}}
template<char...> void operator "" _d(); // expected-error {{must have C++ linkage}}
namespace N {
diff --git a/test/CXX/over/over.over/p1.cpp b/test/CXX/over/over.over/p1.cpp
index 10c60da013cb..e31a2c506756 100644
--- a/test/CXX/over/over.over/p1.cpp
+++ b/test/CXX/over/over.over/p1.cpp
@@ -1,7 +1,9 @@
-// RUN: %clang_cc1 -fsyntax-only %s
+// RUN: %clang_cc1 -fsyntax-only -DNOEXCEPT= -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++1z -DNOEXCEPT= -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++1z -DNOEXCEPT=noexcept -verify %s
-template<typename T> T f0(T);
-int f0(int);
+template<typename T> T f0(T) NOEXCEPT;
+int f0(int) NOEXCEPT;
// -- an object or reference being initialized
struct S {
@@ -92,3 +94,18 @@ Y1<f0> y1;
Y1<&f0> y1a;
Y2<f0> y2;
Y3<f0> y3;
+
+#if __cplusplus > 201402L
+namespace MixedNoexcept {
+ inline namespace A {
+ void f() noexcept; // expected-note {{candidate}}
+ }
+ inline namespace B {
+ void f(); // expected-note {{candidate}}
+ }
+ void (*p)() noexcept = &f; // ok
+ void (*q)() = &f; // expected-error {{ambiguous}}
+}
+#else
+// expected-no-diagnostics
+#endif
diff --git a/test/CXX/special/class.copy/implicit-move-def.cpp b/test/CXX/special/class.copy/implicit-move-def.cpp
index f344b0cc6a0f..7a6a1ee984e9 100644
--- a/test/CXX/special/class.copy/implicit-move-def.cpp
+++ b/test/CXX/special/class.copy/implicit-move-def.cpp
@@ -110,8 +110,8 @@ void move_VirtualWithEmptyBase(VirtualWithEmptyBase &x, VirtualWithEmptyBase &y)
// CHECK-CTOR: call {{.*}} @_ZN1FC1EOS_
// CHECK-CTOR: call {{.*}} @_ZN1EC1EOS_
// array loop
-// CHECK-CTOR: br i1
// CHECK-CTOR: call {{.*}} @_ZN1FC1EOS_
+// CHECK-CTOR: br i1
// CHECK-CTOR: define linkonce_odr {{.*}} @_ZN1GC2EOS_
// CHECK-CTOR: call {{.*}} @_ZN1EC1EOS_
diff --git a/test/CXX/special/class.copy/p20.cpp b/test/CXX/special/class.copy/p20.cpp
index 8dfb7ca8a068..4f17879ecfb7 100644
--- a/test/CXX/special/class.copy/p20.cpp
+++ b/test/CXX/special/class.copy/p20.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
struct ConstCopy {
ConstCopy();
diff --git a/test/CXX/special/class.dtor/p3-0x.cpp b/test/CXX/special/class.dtor/p3-0x.cpp
index 2d7eba490bc8..f6a64260e0df 100644
--- a/test/CXX/special/class.dtor/p3-0x.cpp
+++ b/test/CXX/special/class.dtor/p3-0x.cpp
@@ -176,4 +176,4 @@ struct TVC : VX
template <typename T>
TVC<T>::~TVC() {}
-// CHECK: attributes [[ATTRGRP]] = { nounwind{{.*}} }
+// CHECK: attributes [[ATTRGRP]] = { noinline nounwind{{.*}} }
diff --git a/test/CXX/special/class.dtor/p5-0x.cpp b/test/CXX/special/class.dtor/p5-0x.cpp
index e32279ef125b..595784f0d5f9 100644
--- a/test/CXX/special/class.dtor/p5-0x.cpp
+++ b/test/CXX/special/class.dtor/p5-0x.cpp
@@ -90,7 +90,7 @@ class D1 {
public:
virtual ~D1() = default; // expected-note {{here}}
} d1; // ok
-struct D2 : D1 { // expected-note {{virtual destructor requires an unambiguous, accessible 'operator delete'}} \
+struct D2 : D1 { // expected-note 2{{virtual destructor requires an unambiguous, accessible 'operator delete'}} \
// expected-error {{deleted function '~D2' cannot override a non-deleted}}
// implicitly-virtual destructor
} d2; // expected-error {{deleted function}}
diff --git a/test/CXX/special/class.dtor/p9.cpp b/test/CXX/special/class.dtor/p9.cpp
index 42a4236a4a07..e812491fbb4b 100644
--- a/test/CXX/special/class.dtor/p9.cpp
+++ b/test/CXX/special/class.dtor/p9.cpp
@@ -1,7 +1,9 @@
-// RUN: %clang_cc1 -fsyntax-only -triple %itanium_abi_triple -verify %s
-// RUN: %clang_cc1 -fsyntax-only -triple %ms_abi_triple -DMSABI -verify %s
+// RUN: %clang_cc1 -fsyntax-only -triple %itanium_abi_triple -verify -std=c++98 %s
+// RUN: %clang_cc1 -fsyntax-only -triple %ms_abi_triple -DMSABI -verify -std=c++98 %s
+// RUN: %clang_cc1 -fsyntax-only -triple %itanium_abi_triple -verify -std=c++11 %s
+// RUN: %clang_cc1 -fsyntax-only -triple %ms_abi_triple -DMSABI -verify -std=c++11 %s
-typedef typeof(sizeof(int)) size_t;
+typedef __typeof(sizeof(int)) size_t;
// PR7803
namespace test0 {
@@ -29,13 +31,13 @@ namespace test0 {
namespace test1 {
class A {
public:
- static void operator delete(void *p) {}; // expected-note {{member 'operator delete' declared here}}
+ static void operator delete(void *p) {};
virtual ~A();
};
class B : protected A {
public:
- static void operator delete(void *, size_t) {}; // expected-note {{member 'operator delete' declared here}}
+ static void operator delete(void *, size_t) {};
~B();
};
@@ -47,7 +49,20 @@ namespace test1 {
~C();
};
- C::~C() {} // expected-error {{multiple suitable 'operator delete' functions in 'C'}}
+ // We assume that the intent is to treat C::operator delete(void*, size_t) as
+ // /not/ being a usual deallocation function, as it would be if it were
+ // declared with in C directly.
+ C::~C() {}
+
+ struct D {
+ void operator delete(void*); // expected-note {{member 'operator delete' declared here}}
+ void operator delete(void*, ...); // expected-note {{member 'operator delete' declared here}}
+ virtual ~D();
+ };
+ // FIXME: The standard doesn't say this is ill-formed, but presumably either
+ // it should be or the variadic operator delete should not be a usual
+ // deallocation function.
+ D::~D() {} // expected-error {{multiple suitable 'operator delete' functions in 'D'}}
}
// ...at the point of definition of a virtual destructor...
@@ -63,6 +78,7 @@ namespace test2 {
};
B::~B() {} // expected-error {{no suitable member 'operator delete' in 'B'}}
+#if __cplusplus < 201103L
struct CBase { virtual ~CBase(); };
struct C : CBase { // expected-error {{no suitable member 'operator delete' in 'C'}}
static void operator delete(void*, const int &); // expected-note {{declared here}}
@@ -70,6 +86,15 @@ namespace test2 {
void test() {
C c; // expected-note {{first required here}}
}
+#else
+ struct CBase { virtual ~CBase(); }; // expected-note {{overridden virtual function is here}}
+ struct C : CBase { // expected-error {{deleted function '~C' cannot override a non-deleted function}} expected-note 2{{requires an unambiguous, accessible 'operator delete'}}
+ static void operator delete(void*, const int &);
+ };
+ void test() {
+ C c; // expected-error {{attempt to use a deleted function}}
+ }
+#endif
}
// PR7346
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 e07d879df8f1..1f4362740b00 100644
--- a/test/CXX/special/class.init/class.inhctor.init/p1.cpp
+++ b/test/CXX/special/class.init/class.inhctor.init/p1.cpp
@@ -87,6 +87,13 @@ namespace vbase {
D d2(0, 0); // expected-error {{deleted}}
}
+namespace vbase_of_vbase {
+ struct V { V(int); };
+ struct W : virtual V { using V::V; };
+ struct X : virtual W, virtual V { using W::W; };
+ X x(0);
+}
+
namespace constexpr_init_order {
struct Param;
struct A {
diff --git a/test/CXX/stmt.stmt/stmt.select/stmt.if/p2.cpp b/test/CXX/stmt.stmt/stmt.select/stmt.if/p2.cpp
index d6a2169a5baf..c33bf0eba231 100644
--- a/test/CXX/stmt.stmt/stmt.select/stmt.if/p2.cpp
+++ b/test/CXX/stmt.stmt/stmt.select/stmt.if/p2.cpp
@@ -46,6 +46,11 @@ namespace ccce {
if constexpr (N) {} // expected-error {{cannot be narrowed}}
}
template void g<5>(); // expected-note {{instantiation of}}
+ void h() {
+ if constexpr (4.3) {} // expected-error{{conversion from 'double' to 'bool' is not allowed in a converted constant expression}}
+ constexpr void *p = nullptr;
+ if constexpr (p) {} // expected-error{{conversion from 'void *const' to 'bool' is not allowed in a converted constant expression}}
+ }
}
namespace generic_lambda {
diff --git a/test/CXX/temp/temp.arg/temp.arg.nontype/p5.cpp b/test/CXX/temp/temp.arg/temp.arg.nontype/p5.cpp
index 249563e7d9bf..5341290a1446 100644
--- a/test/CXX/temp/temp.arg/temp.arg.nontype/p5.cpp
+++ b/test/CXX/temp/temp.arg/temp.arg.nontype/p5.cpp
@@ -1,3 +1,7 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++14 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++1z %s
// RUN: %clang_cc1 -fsyntax-only -verify %s
// C++0x [temp.arg.nontype] p5:
@@ -45,15 +49,23 @@ namespace pointer_to_object_parameters {
operator int() const;
};
- template<X const *Ptr> struct A2; // expected-note{{template parameter is declared here}}
+ template<X const *Ptr> struct A2; // expected-note 0-1{{template parameter is declared here}}
- X *X_ptr;
+ X *X_ptr; // expected-note 0-1{{declared here}}
X an_X;
X array_of_Xs[10];
- A2<X_ptr> *a12; // expected-error{{must have its address taken}}
+ A2<X_ptr> *a12;
+#if __cplusplus < 201103L
+ // expected-error@-2 {{must have its address taken}}
+#else
+ // expected-error@-4 {{not a constant expression}} expected-note@-4 {{read of non-constexpr variable}}
+#endif
A2<array_of_Xs> *a13;
A2<&an_X> *a13_2;
- A2<(&an_X)> *a13_3; // expected-warning{{address non-type template argument cannot be surrounded by parentheses}}
+ A2<(&an_X)> *a13_3;
+#if __cplusplus < 201103L
+ // expected-warning@-2 {{address non-type template argument cannot be surrounded by parentheses}}
+#endif
// PR6244
struct X1 {} X1v;
@@ -62,12 +74,24 @@ namespace pointer_to_object_parameters {
struct X4 : X3<&X1v> { };
// PR6563
- int *bar;
- template <int *> struct zed {}; // expected-note 2{{template parameter is declared here}}
- void g(zed<bar>*); // expected-error{{must have its address taken}}
-
- int baz;
- void g2(zed<baz>*); // expected-error{{must have its address taken}}
+ int *bar; // expected-note 0-1{{declared here}}
+ template <int *> struct zed {}; // expected-note 0-2{{template parameter is declared here}}
+ void g(zed<bar>*);
+#if __cplusplus < 201103L
+ // expected-error@-2 {{must have its address taken}}
+#else
+ // expected-error@-4 {{not a constant expression}} expected-note@-4 {{read of non-constexpr variable}}
+#endif
+
+ int baz; // expected-note 0-1{{declared here}}
+ void g2(zed<baz>*);
+#if __cplusplus < 201103L
+ // expected-error@-2 {{must have its address taken}}
+#elif __cplusplus <= 201402L
+ // expected-error@-4 {{not a constant expression}} expected-note@-4 {{read of non-const variable}}
+#else
+ // expected-error@-6 {{not implicitly convertible to 'int *'}}
+#endif
void g3(zed<&baz>*); // okay
}
@@ -78,9 +102,9 @@ namespace pointer_to_object_parameters {
// template-argument. The template-parameter is bound directly to the
// template-argument, which shall be an lvalue.
namespace reference_parameters {
- template <int& N> struct S0 { }; // expected-note 3 {{template parameter is declared here}}
- template <const int& N> struct S1 { }; // expected-note 2 {{template parameter is declared here}}
- template <volatile int& N> struct S2 { }; // expected-note 2 {{template parameter is declared here}}
+ template <int& N> struct S0 { }; // expected-note 0-3{{template parameter is declared here}}
+ template <const int& N> struct S1 { }; // expected-note 0-2{{template parameter is declared here}}
+ template <volatile int& N> struct S2 { }; // expected-note 0-2{{template parameter is declared here}}
template <const volatile int& N> struct S3 { };
int i;
extern const int ci;
@@ -88,19 +112,19 @@ namespace reference_parameters {
extern const volatile int cvi;
void test() {
S0<i> s0;
- S0<ci> s0c; // expected-error{{reference binding of non-type template parameter of type 'int &' to template argument of type 'const int' ignores qualifiers}}
- S0<vi> s0v; // expected-error{{reference binding of non-type template parameter of type 'int &' to template argument of type 'volatile int' ignores qualifiers}}
- S0<cvi> s0cv; // expected-error{{reference binding of non-type template parameter of type 'int &' to template argument of type 'const volatile int' ignores qualifiers}}
+ S0<ci> s0c; // expected-error{{type 'const int'}}
+ S0<vi> s0v; // expected-error{{type 'volatile int'}}
+ S0<cvi> s0cv; // expected-error{{type 'const volatile int'}}
S1<i> s1;
S1<ci> s1c;
- S1<vi> s1v; // expected-error{{reference binding of non-type template parameter of type 'const int &' to template argument of type 'volatile int' ignores qualifiers}}
- S1<cvi> s1cv; // expected-error{{reference binding of non-type template parameter of type 'const int &' to template argument of type 'const volatile int' ignores qualifiers}}
+ S1<vi> s1v; // expected-error{{type 'volatile int'}}
+ S1<cvi> s1cv; // expected-error{{type 'const volatile int'}}
S2<i> s2;
- S2<ci> s2c; // expected-error{{reference binding of non-type template parameter of type 'volatile int &' to template argument of type 'const int' ignores qualifiers}}
+ S2<ci> s2c; // expected-error{{type 'const int'}}
S2<vi> s2v;
- S2<cvi> s2cv; // expected-error{{reference binding of non-type template parameter of type 'volatile int &' to template argument of type 'const volatile int' ignores qualifiers}}
+ S2<cvi> s2cv; // expected-error{{type 'const volatile int'}}
S3<i> s3;
S3<ci> s3c;
@@ -125,9 +149,12 @@ namespace reference_parameters {
}
namespace PR6749 {
- template <int& i> struct foo {}; // expected-note{{template parameter is declared here}}
+ template <int& i> struct foo {}; // expected-note 0-1{{template parameter is declared here}}
int x, &y = x;
- foo<y> f; // expected-error{{is not an object}}
+ foo<y> f;
+#if __cplusplus <= 201402L
+ // expected-error@-2 {{is not an object}}
+#endif
}
}
@@ -138,16 +165,21 @@ namespace reference_parameters {
// a set of overloaded functions (or a pointer to such), the matching
// function is selected from the set (13.4).
namespace pointer_to_function {
- template<int (*)(int)> struct X0 { }; // expected-note 3{{template parameter is declared here}}
+ template<int (*)(int)> struct X0 { }; // expected-note 0-3{{template parameter is declared here}}
int f(int);
int f(float);
int g(float);
- int (*funcptr)(int);
+ int (*funcptr)(int); // expected-note 0-1{{declared here}}
void x0a(X0<f>);
void x0b(X0<&f>);
- void x0c(X0<g>); // expected-error{{non-type template argument of type 'int (float)' cannot be converted to a value of type 'int (*)(int)'}}
- void x0d(X0<&g>); // expected-error{{non-type template argument of type 'int (*)(float)' cannot be converted to a value of type 'int (*)(int)'}}
- void x0e(X0<funcptr>); // expected-error{{must have its address taken}}
+ void x0c(X0<g>); // expected-error-re{{type 'int (float)' {{.*}}convert{{.*}} 'int (*)(int)'}}
+ void x0d(X0<&g>); // expected-error-re{{type 'int (*)(float)' {{.*}}convert{{.*}} 'int (*)(int)'}}
+ void x0e(X0<funcptr>);
+#if __cplusplus < 201103L
+ // expected-error@-2 {{must have its address taken}}
+#else
+ // expected-error@-4 {{not a constant expression}} expected-note@-4 {{read of non-constexpr variable}}
+#endif
}
// -- For a non-type template-parameter of type reference to function, no
@@ -155,16 +187,23 @@ namespace pointer_to_function {
// overloaded functions, the matching function is selected from the set
// (13.4).
namespace reference_to_function {
- template<int (&)(int)> struct X0 { }; // expected-note 4{{template parameter is declared here}}
+ template<int (&)(int)> struct X0 { }; // expected-note 0-4{{template parameter is declared here}}
int f(int);
int f(float);
int g(float);
int (*funcptr)(int);
void x0a(X0<f>);
+#if __cplusplus <= 201402L
void x0b(X0<&f>); // expected-error{{address taken in non-type template argument for template parameter of reference type 'int (&)(int)'}}
void x0c(X0<g>); // expected-error{{non-type template parameter of reference type 'int (&)(int)' cannot bind to template argument of type 'int (float)'}}
void x0d(X0<&g>); // expected-error{{address taken in non-type template argument for template parameter of reference type 'int (&)(int)'}}
void x0e(X0<funcptr>); // expected-error{{non-type template parameter of reference type 'int (&)(int)' cannot bind to template argument of type 'int (*)(int)'}}
+#else
+ void x0b(X0<&f>); // expected-error{{value of type '<overloaded function type>' is not implicitly convertible to 'int (&)(int)'}}
+ void x0c(X0<g>); // expected-error{{value of type 'int (float)' is not implicitly convertible to 'int (&)(int)'}}
+ void x0d(X0<&g>); // expected-error{{value of type 'int (*)(float)' is not implicitly convertible to 'int (&)(int)'}}
+ void x0e(X0<funcptr>); // expected-error{{value of type 'int (*)(int)' is not implicitly convertible to 'int (&)(int)'}}
+#endif
}
// -- For a non-type template-parameter of type pointer to member function,
// if the template-argument is of type std::nullptr_t, the null member
@@ -181,10 +220,10 @@ namespace pointer_to_member_function {
float h(float);
};
- template<int (Y::*)(int)> struct X0 {}; // expected-note{{template parameter is declared here}}
+ template<int (Y::*)(int)> struct X0 {}; // expected-note 0-1{{template parameter is declared here}}
X0<&Y::f> x0a;
X0<&Y::g> x0b;
- X0<&Y::h> x0c; // expected-error-re{{non-type template argument of type 'float (pointer_to_member_function::Y::*)(float){{( __attribute__\(\(thiscall\)\))?}}' cannot be converted to a value of type 'int (pointer_to_member_function::Y::*)(int){{( __attribute__\(\(thiscall\)\))?}}'}}
+ X0<&Y::h> x0c; // expected-error-re{{type 'float (pointer_to_member_function::Y::*)(float){{( __attribute__\(\(thiscall\)\))?}}' {{.*}} convert{{.*}} 'int (pointer_to_member_function::Y::*)(int){{( __attribute__\(\(thiscall\)\))?}}'}}
}
// -- For a non-type template-parameter of type pointer to data member,
@@ -195,9 +234,14 @@ namespace pointer_to_member_data {
struct X { int x; };
struct Y : X { int y; };
- template<int Y::*> struct X0 {}; // expected-note{{template parameter is declared here}}
+ template<int Y::*> struct X0 {}; // expected-note 0-1{{template parameter is declared here}}
X0<&Y::y> x0a;
- X0<&Y::x> x0b; // expected-error{{non-type template argument of type 'int pointer_to_member_data::X::*' cannot be converted to a value of type 'int pointer_to_member_data::Y::*'}}
+ X0<&Y::x> x0b;
+#if __cplusplus <= 201402L
+ // expected-error@-2 {{non-type template argument of type 'int pointer_to_member_data::X::*' cannot be converted to a value of type 'int pointer_to_member_data::Y::*'}}
+#else
+ // expected-error@-4 {{conversion from 'int pointer_to_member_data::X::*' to 'int pointer_to_member_data::Y::*' is not allowed in a converted constant expression}}
+#endif
// Test qualification conversions
template<const int Y::*> struct X1 {};
diff --git a/test/CXX/temp/temp.decls/temp.class.spec/p8-0x.cpp b/test/CXX/temp/temp.decls/temp.class.spec/p8-0x.cpp
index aa1e2d443fdd..52fbd9457422 100644
--- a/test/CXX/temp/temp.decls/temp.class.spec/p8-0x.cpp
+++ b/test/CXX/temp/temp.decls/temp.class.spec/p8-0x.cpp
@@ -2,7 +2,10 @@
template<int ...Values> struct X1;
-template<int ...Values>
-struct X1<0, Values+1 ...>; // expected-error{{non-type template argument depends on a template parameter of the partial specialization}}
-
+template<int ...Values> // expected-note {{non-deducible}}
+struct X1<0, Values+1 ...>; // expected-error{{contains a template parameter that cannot be deduced}}
+template<typename T, int ...Values> struct X2; // expected-note {{here}}
+template<int ...Values> struct X2<X1<Values...>, Values+1 ...> {}; // ok (DR1315)
+X2<X1<1, 2, 3>, 2, 3, 4> x2; // ok
+X2<X1<1, 2, 3>, 2, 3, 4, 5> x3; // expected-error {{undefined template}}
diff --git a/test/CXX/temp/temp.decls/temp.class.spec/p8-1y.cpp b/test/CXX/temp/temp.decls/temp.class.spec/p8-1y.cpp
index 2651f9942091..388a80ee765c 100644
--- a/test/CXX/temp/temp.decls/temp.class.spec/p8-1y.cpp
+++ b/test/CXX/temp/temp.decls/temp.class.spec/p8-1y.cpp
@@ -21,15 +21,16 @@ template<template<typename> class...X> int v4<X...>;
template<typename Outer> struct X {
template<typename Inner> static int y;
- template<typename Inner> static int y<Outer>; // expected-warning {{cannot be deduced}} expected-note {{'Inner'}}
+ // FIXME: It would be preferable to only diagnose this once.
+ template<typename Inner> static int y<Outer>; // expected-error 3{{cannot be deduced}} expected-note 3{{'Inner'}}
template<typename Inner> static int y<Inner>; // expected-error {{does not specialize}}
+
+ template<typename, int> static int z;
+ template<Outer N> static int z<int, N>; // expected-error {{not implicitly convertible}}
};
-template<typename Outer> template<typename Inner> int X<Outer>::y<Outer>; // expected-warning {{cannot be deduced}} expected-note {{'Inner'}}
+template<typename Outer> template<typename Inner> int X<Outer>::y<Outer>; // expected-error {{cannot be deduced}} expected-note {{'Inner'}}
template<typename Outer> template<typename Inner> int X<Outer>::y<Inner>; // expected-error {{does not specialize}}
+template<> template<typename Inner> int X<int>::y<Inner>; // expected-error {{does not specialize}} expected-note {{instantiation of}}
-// FIXME: Merging this with the above class causes an assertion failure when
-// instantiating one of the bogus partial specializations.
-template<typename Outer> struct Y {
- template<typename Inner> static int y;
-};
-template<> template<typename Inner> int Y<int>::y<Inner>; // expected-error {{does not specialize}}
+X<int> xi;
+X<int*> xf; // expected-note {{instantiation of}}
diff --git a/test/CXX/temp/temp.decls/temp.class/temp.static/p1.cpp b/test/CXX/temp/temp.decls/temp.class/temp.static/p1.cpp
index 215f48d9d8e6..332357bb36a8 100644
--- a/test/CXX/temp/temp.decls/temp.class/temp.static/p1.cpp
+++ b/test/CXX/temp/temp.decls/temp.class/temp.static/p1.cpp
@@ -28,4 +28,4 @@ X2& get_X2() {
return X0<X2>::value; // expected-note{{instantiation}}
}
-template<typename T> T x; // expected-warning{{variable templates are a C++14 extension}}
+template<typename T> T x; // expected-warning 0-1{{variable templates are a C++14 extension}}
diff --git a/test/CXX/temp/temp.decls/temp.friend/p1.cpp b/test/CXX/temp/temp.decls/temp.friend/p1.cpp
index 640d03d4c96f..f1f3f7016242 100644
--- a/test/CXX/temp/temp.decls/temp.friend/p1.cpp
+++ b/test/CXX/temp/temp.decls/temp.friend/p1.cpp
@@ -174,7 +174,7 @@ namespace test7 {
// This shouldn't crash.
template <class T> class D {
- friend class A; // expected-error {{elaborated type refers to a template}}
+ friend class A; // expected-error {{template 'A' cannot be referenced with a class specifier}}
};
template class D<int>;
}
diff --git a/test/CXX/temp/temp.decls/temp.variadic/fixed-expansion.cpp b/test/CXX/temp/temp.decls/temp.variadic/fixed-expansion.cpp
index a466be0a61de..a990c82564aa 100644
--- a/test/CXX/temp/temp.decls/temp.variadic/fixed-expansion.cpp
+++ b/test/CXX/temp/temp.decls/temp.variadic/fixed-expansion.cpp
@@ -108,10 +108,10 @@ namespace PR9021b {
namespace PartialSpecialization {
template<typename T, typename U, typename V = U>
- struct X0; // expected-note{{template is declared here}}
+ struct X0; // expected-note 2{{template is declared here}}
template<typename ...Ts>
- struct X0<Ts...> {
+ struct X0<Ts...> { // expected-error {{class template partial specialization is not more specialized than the primary template}}
};
X0<int> x0i; // expected-error{{too few template arguments for class template 'X0'}}
diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/p9.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/p9.cpp
index 9fd3df59d103..f7103a33cc72 100644
--- a/test/CXX/temp/temp.fct.spec/temp.deduct/p9.cpp
+++ b/test/CXX/temp/temp.fct.spec/temp.deduct/p9.cpp
@@ -32,8 +32,11 @@ namespace PR6707 {
static const unsigned char ten = 10;
template<typename T, T Value, typename U>
void f2(X<T, Value>, X<U, Value>);
+ // expected-note@-1 {{candidate template ignored: deduced values of conflicting types for parameter 'Value' (10 of type 'int' vs. 10 of type 'char')}}
+ // expected-note@-2 {{candidate template ignored: deduced values of conflicting types for parameter 'Value' (10 of type 'char' vs. 10 of type 'int')}}
void g2() {
- f2(X<int, 10>(), X<char, ten>());
+ f2(X<int, 10>(), X<char, ten>()); // expected-error {{no matching}}
+ f2(X<char, 10>(), X<int, ten>()); // expected-error {{no matching}}
}
}
diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p4.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p4.cpp
index 132d61814227..e7b665a34137 100644
--- a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p4.cpp
+++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p4.cpp
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
-// expected-no-diagnostics
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++1z %s
namespace PR8598 {
template<class T> struct identity { typedef T type; };
@@ -19,3 +19,38 @@ namespace PR12132 {
fun(&A::x);
}
}
+
+#if __cplusplus > 201402L
+namespace noexcept_conversion {
+ template<typename R> void foo(R());
+ template<typename R> void bar(R()) = delete;
+ template<typename R> void bar(R() noexcept) {}
+ void f() throw() {
+ foo(&f);
+ bar(&f);
+ }
+ // There is no corresponding rule for references.
+ // We consider this to be a defect, and allow deduction to succeed in this
+ // case. FIXME: Check this should be accepted once the DR is resolved.
+ template<typename R> void baz(R(&)());
+ void g() {
+ baz(f);
+ }
+
+ // But there is one for member pointers.
+ template<typename R, typename C, typename ...A> void quux(R (C::*)(A...));
+ struct Q { void f(int, char) noexcept { quux(&Q::f); } };
+
+ void g1() noexcept;
+ void g2();
+ template <class T> int h(T *, T *); // expected-note {{deduced conflicting types for parameter 'T' ('void () noexcept' vs. 'void ()')}}
+ int x = h(g1, g2); // expected-error {{no matching function}}
+
+ // FIXME: It seems like a defect that B is not deducible here.
+ template<bool B> int i(void () noexcept(B)); // expected-note 2{{couldn't infer template argument 'B'}}
+ int i1 = i(g1); // expected-error {{no matching function}}
+ int i2 = i(g2); // expected-error {{no matching function}}
+}
+#else
+// expected-no-diagnostics
+#endif
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 4dca820c1929..b45ed96d1445 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,4 @@
-// RUN: %clang_cc1 -fsyntax-only %s
+// RUN: %clang_cc1 -fsyntax-only %s -verify
struct AnyT {
template<typename T>
@@ -11,34 +11,54 @@ void test_cvqual_ref(AnyT any) {
struct AnyThreeLevelPtr {
template<typename T>
- operator T***() const
- {
- T x = 0;
- // FIXME: looks like we get this wrong, too!
- // x = 0; // will fail if T is deduced to a const type
- // (EDG and GCC get this wrong)
- return 0;
+ operator T***() const {
+ T x = 0; // expected-note 2{{declared const here}}
+ x = 0; // expected-error 2{{const-qualified type}}
+ T ***p;
+ return p;
}
};
struct X { };
void test_deduce_with_qual(AnyThreeLevelPtr a3) {
- int * const * const * const ip = a3;
+ int * const * const * const ip1 = a3;
+ // FIXME: This is wrong; we are supposed to deduce 'T = int' here.
+ const int * const * const * const ip2 = a3; // expected-note {{instantiation of}}
+ // This one is correct, though.
+ const double * * * ip3 = a3; // expected-note {{instantiation of}}
}
struct AnyPtrMem {
template<typename Class, typename T>
operator T Class::*() const
{
- T x = 0;
- // FIXME: looks like we get this wrong, too!
- // x = 0; // will fail if T is deduced to a const type.
- // (EDG and GCC get this wrong)
+ // This is correct: we don't need a qualification conversion here, so we
+ // deduce 'T = const float'.
+ T x = 0; // expected-note {{declared const here}}
+ x = 0; // expected-error {{const-qualified type}}
return 0;
}
};
void test_deduce_ptrmem_with_qual(AnyPtrMem apm) {
- const float X::* pm = apm;
+ const float X::* pm = apm; // expected-note {{instantiation of}}
+}
+
+struct TwoLevelPtrMem {
+ template<typename Class1, typename Class2, typename T>
+ operator T Class1::*Class2::*() const
+ {
+ T x = 0; // expected-note 2{{declared const here}}
+ x = 0; // expected-error 2{{const-qualified type}}
+ return 0;
+ }
+};
+
+void test_deduce_two_level_ptrmem_with_qual(TwoLevelPtrMem apm) {
+ // FIXME: This is wrong: we should deduce T = 'float'
+ const float X::* const X::* pm2 = apm; // expected-note {{instantiation of}}
+ // This is correct: we don't need a qualification conversion, so we directly
+ // deduce T = 'const double'
+ const double X::* X::* pm1 = apm; // expected-note {{instantiation of}}
}
diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p5.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p5.cpp
new file mode 100644
index 000000000000..8821d538dcbe
--- /dev/null
+++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p5.cpp
@@ -0,0 +1,61 @@
+// RUN: %clang_cc1 -std=c++1z -verify %s
+
+template<typename T, bool B> using Fn = T () noexcept(B);
+
+// - If the original A is a function pointer type, A can be "pointer to
+// function" even if the deduced A is "pointer to noexcept function".
+struct A {
+ template<typename T> operator Fn<T, false>*(); // expected-note {{candidate}}
+};
+struct B {
+ template<typename T> operator Fn<T, true>*();
+};
+void (*p1)() = A();
+void (*p2)() = B();
+void (*p3)() noexcept = A(); // expected-error {{no viable conversion}}
+void (*p4)() noexcept = B();
+
+// - If the original A is a pointer to member function type, A can be "pointer
+// to member of type function" even if the deduced A is "pointer to member of
+// type noexcept function".
+struct C {
+ template<typename T> operator Fn<T, false> A::*(); // expected-note {{candidate}}
+};
+struct D {
+ template<typename T> operator Fn<T, true> A::*();
+};
+void (A::*q1)() = C();
+void (A::*q2)() = D();
+void (A::*q3)() noexcept = C(); // expected-error {{no viable conversion}}
+void (A::*q4)() noexcept = D();
+
+// There is no corresponding rule for references.
+// FIXME: This seems like a defect.
+// FIXME: We don't actually implement the final check for equal types at all!
+// Instead, we handle the matching via [over.ics.user]p3:
+// "If the user-defined conversion is specified by a specialization of a
+// conversion function template, the second standard conversion sequence
+// shall have exact match rank."
+// Note that this *does* allow discarding noexcept, since that conversion has
+// Exact Match rank.
+struct E {
+ template<typename T> operator Fn<T, false>&(); // expected-note {{candidate}}
+};
+struct F {
+ template<typename T> operator Fn<T, true>&();
+};
+void (&r1)() = E();
+void (&r2)() = F();
+void (&r3)() noexcept = E(); // expected-error {{no viable conversion}}
+void (&r4)() noexcept = F();
+
+// FIXME: We reject this for entirely the wrong reason. We incorrectly succeed
+// in deducing T = void, U = G::B, and only fail due to [over.ics.user]p3.
+struct G {
+ template<typename, typename> struct A {};
+ template<typename U> struct A<U, int> : A<U, void> {};
+ struct B { typedef int type; };
+
+ template<typename T, typename U = B> operator A<T, typename U::type> *(); // expected-note {{candidate function [with T = void, U = G::B]}}
+};
+G::A<void, void> *g = G(); // expected-error {{no viable conversion}}
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 b807a0ff9f11..54a54b0c486b 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
@@ -32,7 +32,7 @@ namespace PackExpansionNotAtEnd {
template<typename ... Types, // expected-note{{non-deducible template parameter 'Types'}}
typename Tail> // expected-note{{non-deducible template parameter 'Tail'}}
- struct UselessPartialSpec<Types..., Tail>; // expected-warning{{class template partial specialization contains template parameters that cannot be deduced; this partial specialization will never be used}}
+ struct UselessPartialSpec<Types..., Tail>; // expected-error{{class template partial specialization contains template parameters that cannot be deduced; this partial specialization will never be used}}
}
namespace DeduceNonTypeTemplateArgsInArray {
diff --git a/test/CXX/temp/temp.spec/no-body.cpp b/test/CXX/temp/temp.spec/no-body.cpp
index 4ec18fdf820f..6d1b82fe1898 100644
--- a/test/CXX/temp/temp.spec/no-body.cpp
+++ b/test/CXX/temp/temp.spec/no-body.cpp
@@ -43,7 +43,7 @@ namespace good { // Only good in C++98/03
namespace unsupported {
#ifndef FIXING
- template struct y; // expected-error {{elaborated type refers to a template}}
+ template struct y; // expected-error {{template 'y' cannot be referenced with a struct specifier}}
#endif
}
diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp
index d12feeff0bbc..ec2e380864bf 100644
--- a/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp
+++ b/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp
@@ -223,8 +223,8 @@ namespace spec_vs_expl_inst {
namespace SID {
template <typename STRING_TYPE> class BasicStringPiece;
- template <> class BasicStringPiece<int> { };
- template class BasicStringPiece<int>; // expected-note {{explicit instantiation definition is here}}
+ template <> class BasicStringPiece<int> { }; // expected-note {{previous template specialization is here}}
+ template class BasicStringPiece<int>; // expected-note {{explicit instantiation definition is here}} expected-warning {{has no effect}}
extern template class BasicStringPiece<int>; // expected-error {{explicit instantiation declaration (with 'extern') follows explicit instantiation definition (without 'extern')}}
}
@@ -252,8 +252,8 @@ namespace spec_vs_expl_inst {
namespace DSI {
template <typename STRING_TYPE> class BasicStringPiece; // expected-note {{template is declared here}}
extern template class BasicStringPiece<int>; // expected-error {{explicit instantiation of undefined template 'spec_vs_expl_inst::DSI::BasicStringPiece<int>'}}
- template <> class BasicStringPiece<int> { };
- template class BasicStringPiece<int>;
+ template <> class BasicStringPiece<int> { }; // expected-note {{previous}}
+ template class BasicStringPiece<int>; // expected-warning {{has no effect}}
}
// The same again, with a defined template class.
@@ -267,8 +267,8 @@ namespace spec_vs_expl_inst {
namespace SID_WithDefinedTemplate {
template <typename STRING_TYPE> class BasicStringPiece {};
- template <> class BasicStringPiece<int> { };
- template class BasicStringPiece<int>; // expected-note {{explicit instantiation definition is here}}
+ template <> class BasicStringPiece<int> { }; // expected-note {{previous}}
+ template class BasicStringPiece<int>; // expected-note {{explicit instantiation definition is here}} expected-warning {{has no effect}}
extern template class BasicStringPiece<int>; // expected-error {{explicit instantiation declaration (with 'extern') follows explicit instantiation definition (without 'extern')}}
}
@@ -283,7 +283,7 @@ namespace spec_vs_expl_inst {
template <typename STRING_TYPE> class BasicStringPiece {};
template class BasicStringPiece<int>; // expected-note {{explicit instantiation definition is here}} expected-note {{previous definition is here}}
extern template class BasicStringPiece<int>; // expected-error {{explicit instantiation declaration (with 'extern') follows explicit instantiation definition (without 'extern')}}
- template <> class BasicStringPiece<int> { }; // expected-error {{redefinition of 'spec_vs_expl_inst::IDS_WithDefinedTemplate::BasicStringPiece<int>'}}
+ template <> class BasicStringPiece<int> { }; // expected-error {{redefinition of 'BasicStringPiece<int>'}}
}
namespace DIS_WithDefinedTemplate {
@@ -304,23 +304,23 @@ namespace spec_vs_expl_inst {
namespace SII_WithDefinedTemplate {
template <typename STRING_TYPE> class BasicStringPiece {};
- template <> class BasicStringPiece<int> { };
- template class BasicStringPiece<int>; // expected-note {{previous explicit instantiation is here}}
+ template <> class BasicStringPiece<int> { }; // expected-note {{previous}}
+ template class BasicStringPiece<int>; // expected-note {{previous explicit instantiation is here}} expected-warning {{has no effect}}
template class BasicStringPiece<int>; // expected-error {{duplicate explicit instantiation of 'BasicStringPiece<int>'}}
}
namespace SIS {
template <typename STRING_TYPE> class BasicStringPiece;
- template <> class BasicStringPiece<int> { }; // expected-note {{previous definition is here}}
- template class BasicStringPiece<int>;
- template <> class BasicStringPiece<int> { }; // expected-error {{redefinition of 'spec_vs_expl_inst::SIS::BasicStringPiece<int>'}}
+ template <> class BasicStringPiece<int> { }; // expected-note {{previous definition is here}} expected-note {{previous}}
+ template class BasicStringPiece<int>; // expected-warning {{has no effect}}
+ template <> class BasicStringPiece<int> { }; // expected-error {{redefinition of 'BasicStringPiece<int>'}}
}
namespace SDS {
template <typename STRING_TYPE> class BasicStringPiece;
template <> class BasicStringPiece<int> { }; // expected-note {{previous definition is here}}
extern template class BasicStringPiece<int>;
- template <> class BasicStringPiece<int> { }; // expected-error {{redefinition of 'spec_vs_expl_inst::SDS::BasicStringPiece<int>'}}
+ template <> class BasicStringPiece<int> { }; // expected-error {{redefinition of 'BasicStringPiece<int>'}}
}
namespace SDIS {
@@ -328,7 +328,7 @@ namespace spec_vs_expl_inst {
template <> class BasicStringPiece<int> { }; // expected-note {{previous definition is here}}
extern template class BasicStringPiece<int>;
template class BasicStringPiece<int>;
- template <> class BasicStringPiece<int> { }; // expected-error {{redefinition of 'spec_vs_expl_inst::SDIS::BasicStringPiece<int>'}}
+ template <> class BasicStringPiece<int> { }; // expected-error {{redefinition of 'BasicStringPiece<int>'}}
}
}
diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p4.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p4.cpp
index 772aef6b585a..ac040ccb3d64 100644
--- a/test/CXX/temp/temp.spec/temp.expl.spec/p4.cpp
+++ b/test/CXX/temp/temp.spec/temp.expl.spec/p4.cpp
@@ -1,6 +1,8 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
// RUN: %clang_cc1 -fsyntax-only -verify %s
-struct IntHolder { // expected-note{{here}} // expected-note 2{{candidate constructor (the implicit copy constructor)}}
+struct IntHolder { // expected-note 0-1{{here}} expected-note 2-4{{candidate constructor (the implicit}}
IntHolder(int); // expected-note 2{{candidate constructor}}
};
@@ -12,8 +14,13 @@ struct X { // expected-note{{here}}
void g() { }
- struct Inner { // expected-error{{implicit default}}
+ struct Inner {
+#if __cplusplus >= 201103L
+ T value; // expected-note {{has no default constructor}}
+#else
+ // expected-error@-4 {{implicit default}}
T value; // expected-note {{member is declared here}}
+#endif
};
static T value;
@@ -26,7 +33,12 @@ IntHolder &test_X_IntHolderInt(X<IntHolder, int> xih) {
xih.g(); // okay
xih.f(); // expected-note{{instantiation}}
- X<IntHolder, int>::Inner inner; // expected-note {{first required here}}
+ X<IntHolder, int>::Inner inner;
+#if __cplusplus >= 201103L
+ // expected-error@-2 {{call to implicitly-deleted}}
+#else
+ // expected-note@-4 {{first required here}}
+#endif
return X<IntHolder, int>::value; // expected-note{{instantiation}}
}
diff --git a/test/CXX/temp/temp.spec/temp.explicit/p4.cpp b/test/CXX/temp/temp.spec/temp.explicit/p4.cpp
index 09c428e01df3..0a8a0ce9ff18 100644
--- a/test/CXX/temp/temp.spec/temp.explicit/p4.cpp
+++ b/test/CXX/temp/temp.spec/temp.explicit/p4.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -pedantic %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
template<typename T> void f0(T); // expected-note{{here}}
template void f0(int); // expected-error{{explicit instantiation of undefined function template}}
@@ -17,19 +18,19 @@ template void X0<int>::f1(); // expected-error{{explicit instantiation of undefi
template int X0<int>::value; // expected-error{{explicit instantiation of undefined static data member}}
template<> void f0(long); // expected-note{{previous template specialization is here}}
-template void f0(long); // expected-warning{{explicit instantiation of 'f0<long>' that occurs after an explicit specialization will be ignored}}
+template void f0(long); // expected-warning{{explicit instantiation of 'f0<long>' that occurs after an explicit specialization has no effect}}
template<> void X0<long>::f1(); // expected-note{{previous template specialization is here}}
-template void X0<long>::f1(); // expected-warning{{explicit instantiation of 'f1' that occurs after an explicit specialization will be ignored}}
+template void X0<long>::f1(); // expected-warning{{explicit instantiation of 'f1' that occurs after an explicit specialization has no effect}}
template<> struct X0<long>::Inner; // expected-note{{previous template specialization is here}}
-template struct X0<long>::Inner; // expected-warning{{explicit instantiation of 'Inner' that occurs after an explicit specialization will be ignored}}
+template struct X0<long>::Inner; // expected-warning{{explicit instantiation of 'Inner' that occurs after an explicit specialization has no effect}}
template<> long X0<long>::value; // expected-note{{previous template specialization is here}}
-template long X0<long>::value; // expected-warning{{explicit instantiation of 'value' that occurs after an explicit specialization will be ignored}}
+template long X0<long>::value; // expected-warning{{explicit instantiation of 'value' that occurs after an explicit specialization has no effect}}
template<> struct X0<double>; // expected-note{{previous template specialization is here}}
-template struct X0<double>; // expected-warning{{explicit instantiation of 'X0<double>' that occurs after an explicit specialization will be ignored}}
+template struct X0<double>; // expected-warning{{explicit instantiation of 'X0<double>' that occurs after an explicit specialization has no effect}}
// PR 6458
namespace test0 {
@@ -43,6 +44,6 @@ namespace test0 {
// inappropriately instantiating this template.
void *ptr = x;
}
- extern template class foo<char>; // expected-warning {{extern templates are a C++11 extension}}
+ extern template class foo<char>; // expected-warning 0-1{{extern templates are a C++11 extension}}
template class foo<char>;
}
diff --git a/test/CXX/temp/temp.spec/temp.explicit/p9-linkage.cpp b/test/CXX/temp/temp.spec/temp.explicit/p9-linkage.cpp
index 38dc367b227e..9bdccc8e7324 100644
--- a/test/CXX/temp/temp.spec/temp.explicit/p9-linkage.cpp
+++ b/test/CXX/temp/temp.spec/temp.explicit/p9-linkage.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin -O1 -disable-llvm-optzns -emit-llvm -std=c++11 -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -O1 -disable-llvm-passes -emit-llvm -std=c++11 -o - %s | FileCheck %s
template<typename T>
struct X0 {
diff --git a/test/CodeCompletion/ctor-initializer.cpp b/test/CodeCompletion/ctor-initializer.cpp
index 00af64dd4fa4..e54b347f9fa4 100644
--- a/test/CodeCompletion/ctor-initializer.cpp
+++ b/test/CodeCompletion/ctor-initializer.cpp
@@ -1,11 +1,13 @@
struct Base1 {
Base1() : {}
- // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:2:12 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
+ // RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:2:12 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
+ // RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:2:12 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
// CHECK-CC1: COMPLETION: Pattern : member1(<#args#>)
// CHECK-CC1: COMPLETION: Pattern : member2(<#args#>
Base1(int) : member1(123), {}
- // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:7:30 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s
+ // RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:8:30 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s
+ // RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:8:30 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s
// CHECK-CC2-NOT: COMPLETION: Pattern : member1(<#args#>)
// CHECK-CC2: COMPLETION: Pattern : member2(<#args#>
@@ -21,14 +23,16 @@ struct Derived : public Base1 {
};
Derived::Derived() : {}
-// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:23:22 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:25:22 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:25:22 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s
// CHECK-CC3: COMPLETION: Pattern : Base1(<#args#>)
// CHECK-CC3: COMPLETION: Pattern : deriv1(<#args#>)
Derived::Derived(int) try : {
} catch (...) {
}
-// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:28:29 %s -o - | FileCheck -check-prefix=CHECK-CC4 %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:31:29 %s -o - | FileCheck -check-prefix=CHECK-CC4 %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:31:29 %s -o - | FileCheck -check-prefix=CHECK-CC4 %s
// CHECK-CC4: COMPLETION: Pattern : Base1(<#args#>)
// CHECK-CC4: COMPLETION: Pattern : deriv1(<#args#>)
@@ -36,6 +40,23 @@ Derived::Derived(float) try : Base1(),
{
} catch (...) {
}
-// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:35:39 %s -o - | FileCheck -check-prefix=CHECK-CC5 %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:39:39 %s -o - | FileCheck -check-prefix=CHECK-CC5 %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:39:39 %s -o - | FileCheck -check-prefix=CHECK-CC5 %s
// CHECK-CC5-NOT: COMPLETION: Pattern : Base1(<#args#>)
// CHECK-CC5: COMPLETION: Pattern : deriv1(<#args#>)
+
+struct A {
+ A() : , member2() {}
+ // RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:49:9 %s -o - | FileCheck -check-prefix=CHECK-CC6 %s
+ // RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:49:9 %s -o - | FileCheck -check-prefix=CHECK-CC6 %s
+ // CHECK-CC6: COMPLETION: Pattern : member1(<#args#>
+ int member1, member2;
+};
+
+struct B {
+ B() : member2() {}
+ // 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#>
+ int member1, member2;
+};
diff --git a/test/CodeCompletion/objc-message.mm b/test/CodeCompletion/objc-message.mm
index 352a18e0da97..7a503097e076 100644
--- a/test/CodeCompletion/objc-message.mm
+++ b/test/CodeCompletion/objc-message.mm
@@ -38,9 +38,9 @@ void func(const RetainPtr<id <FooTestProtocol>>& ptr)
[ptr instanceMethod1];
}
-// RUN: %clang_cc1 -fsyntax-only -std=c++11 -code-completion-at=%s:33:7 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -code-completion-at=%s:33:8 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
// CHECK-CC1: categoryInstanceMethod : [#id#]categoryInstanceMethod
// CHECK-CC1: instanceMethod1 : [#id#]instanceMethod1
// CHECK-CC1: protocolInstanceMethod : [#id#]protocolInstanceMethod
-// RUN: %clang_cc1 -fsyntax-only -std=c++11 -code-completion-at=%s:38:7 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -code-completion-at=%s:38:8 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s
// CHECK-CC2: protocolInstanceMethod : [#id#]protocolInstanceMethod
diff --git a/test/CodeCompletion/objc-protocol-member-access.m b/test/CodeCompletion/objc-protocol-member-access.m
new file mode 100644
index 000000000000..0ed55387e3d6
--- /dev/null
+++ b/test/CodeCompletion/objc-protocol-member-access.m
@@ -0,0 +1,24 @@
+// Note: the run lines follow their respective tests, since line/column
+// matter in this test.
+
+@protocol Bar
+@property (readonly) int bar;
+@end
+
+@protocol Foo <Bar>
+
+@property (nonatomic, readonly) int foo;
+- (void)foobar: (int)x;
+
+@end
+
+int getFoo(id object) {
+ id<Foo> modelObject = (id<Foo>)object;
+ int foo = modelObject.;
+ return foo;
+}
+
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:17:25 %s -o - | FileCheck %s
+// CHECK: bar : [#int#]bar
+// CHECK: foo : [#int#]foo
+// CHECK-NOT: foobar
diff --git a/test/CodeGen/2008-04-08-NoExceptions.c b/test/CodeGen/2008-04-08-NoExceptions.c
index 1213492d1db0..6528c35b5485 100644
--- a/test/CodeGen/2008-04-08-NoExceptions.c
+++ b/test/CodeGen/2008-04-08-NoExceptions.c
@@ -9,4 +9,4 @@ void g(void) {
// CHECK-NOT: declare void @f() [[NUW]]
-// CHECK: attributes [[NUW]] = { nounwind{{.*}} }
+// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} }
diff --git a/test/CodeGen/2009-10-20-GlobalDebug.c b/test/CodeGen/2009-10-20-GlobalDebug.c
index 080f02ea7ed4..0d7c759f905e 100644
--- a/test/CodeGen/2009-10-20-GlobalDebug.c
+++ b/test/CodeGen/2009-10-20-GlobalDebug.c
@@ -1,16 +1,20 @@
// REQUIRES: x86-registered-target
// RUN: %clang -target i386-apple-darwin10 -flto -S -g %s -o - | FileCheck %s
+
+// CHECK: @main.localstatic = internal global i32 0, align 4, !dbg [[L:![0-9]+]]
+// CHECK: @global = common global i32 0, align 4, !dbg [[G:![0-9]+]]
+
int global;
int main() {
static int localstatic;
return 0;
}
-// CHECK: !DIGlobalVariable(name: "localstatic"
-// CHECK-NOT: linkageName:
-// CHECK-SAME: line: 5,
-// CHECK-SAME: variable: i32* @main.localstatic
-// CHECK: !DIGlobalVariable(name: "global"
-// CHECK-NOT: linkageName:
-// CHECK-SAME: line: 3,
-// CHECK-SAME: variable: i32* @global
+// CHECK: [[L]] = !DIGlobalVariableExpression(var: [[LV:.*]])
+// CHECK: [[LV]] = distinct !DIGlobalVariable(name: "localstatic"
+// CHECK-NOT: linkageName:
+// CHECK-SAME: line: 9,
+// CHECK: [[G]] = !DIGlobalVariableExpression(var: [[GV:.*]])
+// CHECK: [[GV]] = distinct !DIGlobalVariable(name: "global"
+// CHECK-NOT: linkageName:
+// CHECK-SAME: line: 7,
diff --git a/test/CodeGen/2010-08-10-DbgConstant.c b/test/CodeGen/2010-08-10-DbgConstant.c
index cbc1841cf187..68947edd526a 100644
--- a/test/CodeGen/2010-08-10-DbgConstant.c
+++ b/test/CodeGen/2010-08-10-DbgConstant.c
@@ -1,5 +1,6 @@
// RUN: %clang_cc1 -S -emit-llvm -debug-info-kind=limited %s -o - | FileCheck %s
-// CHECK: !DIGlobalVariable(
+// CHECK: !DIGlobalVariableExpression(var: [[VAR:.*]], expr: [[EXPR:![0-9]+]])
+// CHECK: [[EXPR]] = !DIExpression(DW_OP_constu, 201, DW_OP_stack_value)
static const unsigned int ro = 201;
void bar(int);
diff --git a/test/CodeGen/3dnow-builtins.c b/test/CodeGen/3dnow-builtins.c
index fdee2a7619a0..26e8700b9a2c 100644
--- a/test/CodeGen/3dnow-builtins.c
+++ b/test/CodeGen/3dnow-builtins.c
@@ -1,8 +1,6 @@
-// RUN: %clang_cc1 %s -triple=x86_64-unknown-unknown -target-feature +3dnowa -emit-llvm -o - -Werror | FileCheck %s -check-prefix=GCC -check-prefix=CHECK
-// RUN: %clang_cc1 %s -triple=x86_64-scei-ps4 -target-feature +3dnowa -emit-llvm -o - -Werror | FileCheck %s -check-prefix=PS4 -check-prefix=CHECK
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-unknown-unknown -target-feature +3dnowa -emit-llvm -o - -Wall -Werror | FileCheck %s -check-prefix=GCC -check-prefix=CHECK
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-scei-ps4 -target-feature +3dnowa -emit-llvm -o - -Wall -Werror | FileCheck %s -check-prefix=PS4 -check-prefix=CHECK
-// Don't include mm_malloc.h, it's system specific.
-#define __MM_MALLOC_H
#include <x86intrin.h>
diff --git a/test/CodeGen/64bit-swiftcall.c b/test/CodeGen/64bit-swiftcall.c
new file mode 100644
index 000000000000..c1f098172371
--- /dev/null
+++ b/test/CodeGen/64bit-swiftcall.c
@@ -0,0 +1,1007 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -target-cpu core2 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple arm64-apple-ios9 -target-cpu cyclone -emit-llvm -o - %s | FileCheck %s
+
+// REQUIRES: aarch64-registered-target,x86-registered-target
+
+#define SWIFTCALL __attribute__((swiftcall))
+#define OUT __attribute__((swift_indirect_result))
+#define ERROR __attribute__((swift_error_result))
+#define CONTEXT __attribute__((swift_context))
+
+// CHECK: [[STRUCT2_RESULT:@.*]] = private {{.*}} constant [[STRUCT2_TYPE:%.*]] { i32 0, i8 0, i8 undef, i8 0, float 0.000000e+00, float 0.000000e+00 }
+
+/*****************************************************************************/
+/****************************** PARAMETER ABIS *******************************/
+/*****************************************************************************/
+
+SWIFTCALL void indirect_result_1(OUT int *arg0, OUT float *arg1) {}
+// CHECK-LABEL: define {{.*}} void @indirect_result_1(i32* noalias sret align 4 dereferenceable(4){{.*}}, float* noalias align 4 dereferenceable(4){{.*}})
+
+// TODO: maybe this shouldn't suppress sret.
+SWIFTCALL int indirect_result_2(OUT int *arg0, OUT float *arg1) { __builtin_unreachable(); }
+// CHECK-LABEL: define {{.*}} i32 @indirect_result_2(i32* noalias align 4 dereferenceable(4){{.*}}, float* noalias align 4 dereferenceable(4){{.*}})
+
+typedef struct { char array[1024]; } struct_reallybig;
+SWIFTCALL struct_reallybig indirect_result_3(OUT int *arg0, OUT float *arg1) { __builtin_unreachable(); }
+// CHECK-LABEL: define {{.*}} void @indirect_result_3({{.*}}* noalias sret {{.*}}, i32* noalias align 4 dereferenceable(4){{.*}}, float* noalias align 4 dereferenceable(4){{.*}})
+
+SWIFTCALL void context_1(CONTEXT void *self) {}
+// CHECK-LABEL: define {{.*}} void @context_1(i8* swiftself
+
+SWIFTCALL void context_2(void *arg0, CONTEXT void *self) {}
+// CHECK-LABEL: define {{.*}} void @context_2(i8*{{.*}}, i8* swiftself
+
+SWIFTCALL void context_error_1(CONTEXT int *self, ERROR float **error) {}
+// CHECK-LABEL: define {{.*}} void @context_error_1(i32* swiftself{{.*}}, float** swifterror)
+// CHECK: [[TEMP:%.*]] = alloca float*, align 8
+// CHECK: [[T0:%.*]] = load float*, float** [[ERRORARG:%.*]], align 8
+// CHECK: store float* [[T0]], float** [[TEMP]], align 8
+// CHECK: [[T0:%.*]] = load float*, float** [[TEMP]], align 8
+// CHECK: store float* [[T0]], float** [[ERRORARG]], align 8
+void test_context_error_1() {
+ int x;
+ float *error;
+ context_error_1(&x, &error);
+}
+// CHECK-LABEL: define void @test_context_error_1()
+// CHECK: [[X:%.*]] = alloca i32, align 4
+// CHECK: [[ERROR:%.*]] = alloca float*, align 8
+// CHECK: [[TEMP:%.*]] = alloca swifterror float*, align 8
+// CHECK: [[T0:%.*]] = load float*, float** [[ERROR]], align 8
+// CHECK: store float* [[T0]], float** [[TEMP]], align 8
+// CHECK: call [[SWIFTCC:swiftcc]] void @context_error_1(i32* swiftself [[X]], float** swifterror [[TEMP]])
+// CHECK: [[T0:%.*]] = load float*, float** [[TEMP]], align 8
+// CHECK: store float* [[T0]], float** [[ERROR]], align 8
+
+SWIFTCALL void context_error_2(short s, CONTEXT int *self, ERROR float **error) {}
+// CHECK-LABEL: define {{.*}} void @context_error_2(i16{{.*}}, i32* swiftself{{.*}}, float** swifterror)
+
+/*****************************************************************************/
+/********************************** LOWERING *********************************/
+/*****************************************************************************/
+
+typedef float float4 __attribute__((ext_vector_type(4)));
+typedef float float8 __attribute__((ext_vector_type(8)));
+typedef double double2 __attribute__((ext_vector_type(2)));
+typedef double double4 __attribute__((ext_vector_type(4)));
+typedef int int3 __attribute__((ext_vector_type(3)));
+typedef int int4 __attribute__((ext_vector_type(4)));
+typedef int int5 __attribute__((ext_vector_type(5)));
+typedef int int8 __attribute__((ext_vector_type(8)));
+typedef char char16 __attribute__((ext_vector_type(16)));
+typedef short short8 __attribute__((ext_vector_type(8)));
+typedef long long long2 __attribute__((ext_vector_type(2)));
+
+#define TEST(TYPE) \
+ SWIFTCALL TYPE return_##TYPE(void) { \
+ TYPE result = {}; \
+ return result; \
+ } \
+ SWIFTCALL void take_##TYPE(TYPE v) { \
+ } \
+ void test_##TYPE() { \
+ take_##TYPE(return_##TYPE()); \
+ }
+
+/*****************************************************************************/
+/*********************************** STRUCTS *********************************/
+/*****************************************************************************/
+
+typedef struct {
+} struct_empty;
+TEST(struct_empty);
+// CHECK-LABEL: define {{.*}} @return_struct_empty()
+// CHECK: ret void
+// CHECK-LABEL: define {{.*}} @take_struct_empty()
+// CHECK: ret void
+
+typedef struct {
+ int x;
+ char c0;
+ char c1;
+ float f0;
+ float f1;
+} struct_1;
+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
+// CHECK: [[GEP1:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1
+// CHECK: [[T1:%.*]] = load i64, i64* [[GEP1]], align 4
+// CHECK: [[R0:%.*]] = insertvalue { i64, i64 } undef, i64 [[T0]], 0
+// 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: [[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
+// CHECK: store i64 %0, i64* [[GEP0]], align 4
+// CHECK: [[GEP1:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1
+// CHECK: store i64 %1, i64* [[GEP1]], align 4
+// CHECK: ret void
+// CHECK: }
+// CHECK-LABEL: define 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 }*
+// CHECK: [[GEP0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0
+// CHECK: [[E0:%.*]] = extractvalue { i64, i64 } [[RET]], 0
+// CHECK: store i64 [[E0]], i64* [[GEP0]], align 4
+// CHECK: [[GEP1:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1
+// CHECK: [[E1:%.*]] = extractvalue { i64, i64 } [[RET]], 1
+// CHECK: store i64 [[E1]], i64* [[GEP1]], align 4
+// CHECK: [[CAST2:%.*]] = bitcast [[STRUCT1]]* [[AGG]] to { i64, i64 }*
+// CHECK: [[GEP2:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST2]], i32 0, i32 0
+// CHECK: [[V0:%.*]] = load i64, i64* [[GEP2]], align 4
+// CHECK: [[GEP3:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST2]], i32 0, i32 1
+// CHECK: [[V1:%.*]] = load i64, i64* [[GEP3]], align 4
+// CHECK: call swiftcc void @take_struct_1(i64 [[V0]], i64 [[V1]])
+// CHECK: ret void
+// CHECK: }
+
+typedef struct {
+ int x;
+ char c0;
+ __attribute__((aligned(2))) char c1;
+ float f0;
+ float f1;
+} struct_2;
+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: 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
+// CHECK: [[GEP1:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1
+// CHECK: [[T1:%.*]] = load i64, i64* [[GEP1]], align 4
+// CHECK: [[R0:%.*]] = insertvalue { i64, i64 } undef, i64 [[T0]], 0
+// 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: [[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
+// CHECK: store i64 %0, i64* [[GEP0]], align 4
+// CHECK: [[GEP1:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1
+// CHECK: store i64 %1, i64* [[GEP1]], align 4
+// CHECK: ret void
+// CHECK: }
+// CHECK-LABEL: define 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 }*
+// CHECK: [[GEP:%.*]] = getelementptr inbounds {{.*}} [[CAST_TMP]], i32 0, i32 0
+// CHECK: [[T0:%.*]] = extractvalue { i64, i64 } [[CALL]], 0
+// CHECK: store i64 [[T0]], i64* [[GEP]], align 4
+// CHECK: [[GEP:%.*]] = getelementptr inbounds {{.*}} [[CAST_TMP]], i32 0, i32 1
+// CHECK: [[T0:%.*]] = extractvalue { i64, i64 } [[CALL]], 1
+// CHECK: store i64 [[T0]], i64* [[GEP]], align 4
+// CHECK: [[CAST:%.*]] = bitcast [[STRUCT2_TYPE]]* [[TMP]] to { i64, i64 }*
+// CHECK: [[GEP:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0
+// CHECK: [[R0:%.*]] = load i64, i64* [[GEP]], align 4
+// CHECK: [[GEP:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1
+// CHECK: [[R1:%.*]] = load i64, i64* [[GEP]], align 4
+// CHECK: call swiftcc void @take_struct_2(i64 [[R0]], i64 [[R1]])
+// CHECK: ret void
+// CHECK: }
+
+// There's no way to put a field randomly in the middle of an otherwise
+// empty storage unit in C, so that case has to be tested in C++, which
+// can use empty structs to introduce arbitrary padding. (In C, they end up
+// with size 0 and so don't affect layout.)
+
+// Misaligned data rule.
+typedef struct {
+ char c0;
+ __attribute__((packed)) float f;
+} struct_misaligned_1;
+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 { 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: [[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: [[AGG:%.*]] = alloca [[STRUCT:%.*]], align 1
+// CHECK: [[CALL:%.*]] = call swiftcc i64 @return_struct_misaligned_1()
+// CHECK: [[T0:%.*]] = bitcast [[STRUCT]]* [[AGG]] to { i64 }*
+// CHECK: [[T1:%.*]] = getelementptr inbounds { i64 }, { i64 }* [[T0]], i32 0, i32 0
+// CHECK: store i64 [[CALL]], i64* [[T1]], align 1
+// CHECK: [[T0:%.*]] = bitcast [[STRUCT]]* [[AGG]] to { i64 }*
+// CHECK: [[T1:%.*]] = getelementptr inbounds { i64 }, { i64 }* [[T0]], i32 0, i32 0
+// CHECK: [[P:%.*]] = load i64, i64* [[T1]], align 1
+// CHECK: call swiftcc void @take_struct_misaligned_1(i64 [[P]])
+// CHECK: ret void
+// CHECK: }
+
+// Too many scalars.
+typedef struct {
+ long long x[5];
+} struct_big_1;
+TEST(struct_big_1)
+
+// CHECK-LABEL: define {{.*}} void @return_struct_big_1({{.*}} noalias sret
+
+// Should not be byval.
+// CHECK-LABEL: define {{.*}} void @take_struct_big_1({{.*}}*{{( %.*)?}})
+
+/*****************************************************************************/
+/********************************* TYPE MERGING ******************************/
+/*****************************************************************************/
+
+typedef union {
+ float f;
+ double d;
+} union_het_fp;
+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 { 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: [[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: [[AGG:%.*]] = alloca [[UNION:%.*]], align 8
+// CHECK: [[CALL:%.*]] = call swiftcc i64 @return_union_het_fp()
+// CHECK: [[T0:%.*]] = bitcast [[UNION]]* [[AGG]] to { i64 }*
+// CHECK: [[T1:%.*]] = getelementptr inbounds { i64 }, { i64 }* [[T0]], i32 0, i32 0
+// CHECK: store i64 [[CALL]], i64* [[T1]], align 8
+// CHECK: [[T0:%.*]] = bitcast [[UNION]]* [[AGG]] to { i64 }*
+// CHECK: [[T1:%.*]] = getelementptr inbounds { i64 }, { i64 }* [[T0]], i32 0, i32 0
+// CHECK: [[V0:%.*]] = load i64, i64* [[T1]], align 8
+// CHECK: call swiftcc void @take_union_het_fp(i64 [[V0]])
+// CHECK: ret void
+// CHECK: }
+
+
+typedef union {
+ float f1;
+ float f2;
+} union_hom_fp;
+TEST(union_hom_fp)
+// CHECK-LABEL: define 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 }]]*
+// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
+// CHECK: store float [[CALL]], float* [[T0]], align 4
+// CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP]] to [[AGG]]*
+// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
+// CHECK: [[FIRST:%.*]] = load float, float* [[T0]], align 4
+// CHECK: call [[SWIFTCC]] void @take_union_hom_fp(float [[FIRST]])
+// CHECK: ret void
+
+typedef union {
+ float f1;
+ float4 fv2;
+} union_hom_fp_partial;
+TEST(union_hom_fp_partial)
+// CHECK: define 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 }*
+// CHECK: [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0
+// CHECK: [[T1:%.*]] = extractvalue { i64, i64 } [[CALL]], 0
+// CHECK: store i64 [[T1]], i64* [[T0]], align 16
+// CHECK: [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1
+// CHECK: [[T1:%.*]] = extractvalue { i64, i64 } [[CALL]], 1
+// CHECK: store i64 [[T1]], i64* [[T0]], align 8
+// CHECK: [[CAST:%.*]] = bitcast [[UNION]]* [[AGG]] to { i64, i64 }*
+// CHECK: [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0
+// CHECK: [[V0:%.*]] = load i64, i64* [[T0]], align 16
+// CHECK: [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1
+// CHECK: [[V1:%.*]] = load i64, i64* [[T0]], align 8
+// CHECK: call swiftcc void @take_union_hom_fp_partial(i64 [[V0]], i64 [[V1]])
+// CHECK: ret void
+// CHECK: }
+
+typedef union {
+ struct { int x, y; } f1;
+ float4 fv2;
+} union_het_fpv_partial;
+TEST(union_het_fpv_partial)
+// CHECK-LABEL: define 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 }*
+// CHECK: [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0
+// CHECK: [[T1:%.*]] = extractvalue { i64, i64 } [[CALL]], 0
+// CHECK: store i64 [[T1]], i64* [[T0]], align 16
+// CHECK: [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1
+// CHECK: [[T1:%.*]] = extractvalue { i64, i64 } [[CALL]], 1
+// CHECK: store i64 [[T1]], i64* [[T0]], align 8
+// CHECK: [[CAST:%.*]] = bitcast [[UNION]]* [[AGG]] to { i64, i64 }*
+// CHECK: [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0
+// CHECK: [[V0:%.*]] = load i64, i64* [[T0]], align 16
+// CHECK: [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1
+// CHECK: [[V1:%.*]] = load i64, i64* [[T0]], align 8
+// CHECK: call swiftcc void @take_union_het_fpv_partial(i64 [[V0]], i64 [[V1]])
+// CHECK: ret void
+// CHECK: }
+
+/*****************************************************************************/
+/****************************** VECTOR LEGALIZATION **************************/
+/*****************************************************************************/
+
+TEST(int4)
+// CHECK-LABEL: define {{.*}} <4 x i32> @return_int4()
+// CHECK-LABEL: define {{.*}} @take_int4(<4 x i32>
+
+TEST(int8)
+// CHECK-LABEL: define {{.*}} @return_int8()
+// CHECK: [[RET:%.*]] = alloca [[REC:<8 x i32>]], align 16
+// CHECK: [[VAR:%.*]] = alloca [[REC]], align
+// CHECK: store
+// CHECK: load
+// CHECK: store
+// CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[RET]] to [[AGG:{ <4 x i32>, <4 x i32> }]]*
+// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
+// CHECK: [[FIRST:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align
+// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
+// CHECK: [[SECOND:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align
+// CHECK: [[T0:%.*]] = insertvalue [[UAGG:{ <4 x i32>, <4 x i32> }]] undef, <4 x i32> [[FIRST]], 0
+// CHECK: [[T1:%.*]] = insertvalue [[UAGG]] [[T0]], <4 x i32> [[SECOND]], 1
+// CHECK: ret [[UAGG]] [[T1]]
+// CHECK-LABEL: define {{.*}} @take_int8(<4 x i32>, <4 x i32>)
+// CHECK: [[V:%.*]] = alloca [[REC]], align
+// CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[V]] to [[AGG]]*
+// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
+// CHECK: store <4 x i32> %0, <4 x i32>* [[T0]], align
+// 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: [[TMP1:%.*]] = alloca [[REC]], align
+// CHECK: [[TMP2:%.*]] = alloca [[REC]], align
+// CHECK: [[CALL:%.*]] = call [[SWIFTCC]] [[UAGG]] @return_int8()
+// CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP1]] to [[AGG]]*
+// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
+// CHECK: [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 0
+// CHECK: store <4 x i32> [[T1]], <4 x i32>* [[T0]], align
+// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
+// CHECK: [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 1
+// CHECK: store <4 x i32> [[T1]], <4 x i32>* [[T0]], align
+// CHECK: [[V:%.*]] = load [[REC]], [[REC]]* [[TMP1]], align
+// CHECK: store [[REC]] [[V]], [[REC]]* [[TMP2]], align
+// CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP2]] to [[AGG]]*
+// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
+// CHECK: [[FIRST:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align
+// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
+// CHECK: [[SECOND:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align
+// CHECK: call [[SWIFTCC]] void @take_int8(<4 x i32> [[FIRST]], <4 x i32> [[SECOND]])
+// CHECK: ret void
+
+TEST(int5)
+// CHECK-LABEL: define {{.*}} @return_int5()
+// CHECK: [[RET:%.*]] = alloca [[REC:<5 x i32>]], align 16
+// CHECK: [[VAR:%.*]] = alloca [[REC]], align
+// CHECK: store
+// CHECK: load
+// CHECK: store
+// CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[RET]] to [[AGG:{ <4 x i32>, i32 }]]*
+// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
+// CHECK: [[FIRST:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align
+// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
+// CHECK: [[SECOND:%.*]] = load i32, i32* [[T0]], align
+// CHECK: [[T0:%.*]] = insertvalue [[UAGG:{ <4 x i32>, i32 }]] undef, <4 x i32> [[FIRST]], 0
+// CHECK: [[T1:%.*]] = insertvalue [[UAGG]] [[T0]], i32 [[SECOND]], 1
+// CHECK: ret [[UAGG]] [[T1]]
+// CHECK-LABEL: define {{.*}} @take_int5(<4 x i32>, i32)
+// CHECK: [[V:%.*]] = alloca [[REC]], align
+// CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[V]] to [[AGG]]*
+// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
+// CHECK: store <4 x i32> %0, <4 x i32>* [[T0]], align
+// 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: [[TMP1:%.*]] = alloca [[REC]], align
+// CHECK: [[TMP2:%.*]] = alloca [[REC]], align
+// CHECK: [[CALL:%.*]] = call [[SWIFTCC]] [[UAGG]] @return_int5()
+// CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP1]] to [[AGG]]*
+// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
+// CHECK: [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 0
+// CHECK: store <4 x i32> [[T1]], <4 x i32>* [[T0]], align
+// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
+// CHECK: [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 1
+// CHECK: store i32 [[T1]], i32* [[T0]], align
+// CHECK: [[V:%.*]] = load [[REC]], [[REC]]* [[TMP1]], align
+// CHECK: store [[REC]] [[V]], [[REC]]* [[TMP2]], align
+// CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP2]] to [[AGG]]*
+// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
+// CHECK: [[FIRST:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align
+// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
+// CHECK: [[SECOND:%.*]] = load i32, i32* [[T0]], align
+// CHECK: call [[SWIFTCC]] void @take_int5(<4 x i32> [[FIRST]], i32 [[SECOND]])
+// CHECK: ret void
+
+typedef struct {
+ int x;
+ int3 v __attribute__((packed));
+} misaligned_int3;
+TEST(misaligned_int3)
+// CHECK-LABEL: define swiftcc void @take_misaligned_int3(i64, i64)
+
+typedef struct {
+ float f0;
+} struct_f1;
+TEST(struct_f1)
+// CHECK-LABEL: define swiftcc float @return_struct_f1()
+// CHECK-LABEL: define swiftcc void @take_struct_f1(float)
+
+typedef struct {
+ float f0;
+ float f1;
+} struct_f2;
+TEST(struct_f2)
+// CHECK-LABEL: define swiftcc i64 @return_struct_f2()
+// CHECK-LABEL: define swiftcc void @take_struct_f2(i64)
+
+typedef struct {
+ float f0;
+ float f1;
+ float f2;
+} struct_f3;
+TEST(struct_f3)
+// CHECK-LABEL: define swiftcc { i64, float } @return_struct_f3()
+// CHECK-LABEL: define swiftcc void @take_struct_f3(i64, float)
+
+typedef struct {
+ float f0;
+ float f1;
+ float f2;
+ float f3;
+} struct_f4;
+TEST(struct_f4)
+// CHECK-LABEL: define swiftcc { i64, i64 } @return_struct_f4()
+// CHECK-LABEL: define swiftcc void @take_struct_f4(i64, i64)
+
+
+typedef struct {
+ double d0;
+} struct_d1;
+TEST(struct_d1)
+// CHECK-LABEL: define swiftcc double @return_struct_d1()
+// CHECK-LABEL: define swiftcc void @take_struct_d1(double)
+
+typedef struct {
+ double d0;
+ double d1;
+} struct_d2;
+TEST(struct_d2)
+
+// CHECK-LABEL: define swiftcc { double, double } @return_struct_d2()
+// CHECK-LABEL: define swiftcc void @take_struct_d2(double, double)
+typedef struct {
+ double d0;
+ double d1;
+ double d2;
+} struct_d3;
+TEST(struct_d3)
+// CHECK-LABEL: define swiftcc { double, double, double } @return_struct_d3()
+// CHECK-LABEL: define swiftcc void @take_struct_d3(double, double, double)
+
+typedef struct {
+ double d0;
+ double d1;
+ double d2;
+ double d3;
+} struct_d4;
+TEST(struct_d4)
+// CHECK-LABEL: define swiftcc { double, double, double, double } @return_struct_d4()
+// CHECK-LABEL: define swiftcc void @take_struct_d4(double, double, double, double)
+
+typedef struct {
+ double d0;
+ double d1;
+ double d2;
+ double d3;
+ double d4;
+} struct_d5;
+TEST(struct_d5)
+// CHECK: define swiftcc void @return_struct_d5([[STRUCT5:%.*]]* noalias sret
+// CHECK: define swiftcc void @take_struct_d5([[STRUCT5]]
+
+typedef struct {
+ char c0;
+} struct_c1;
+TEST(struct_c1)
+// CHECK-LABEL: define swiftcc i8 @return_struct_c1()
+// CHECK-LABEL: define swiftcc void @take_struct_c1(i8)
+
+typedef struct {
+ char c0;
+ char c1;
+} struct_c2;
+TEST(struct_c2)
+// CHECK-LABEL: define swiftcc i16 @return_struct_c2()
+// CHECK-LABEL: define swiftcc void @take_struct_c2(i16)
+//
+
+typedef struct {
+ char c0;
+ char c1;
+ char c2;
+} struct_c3;
+TEST(struct_c3)
+// CHECK-LABEL: define swiftcc i32 @return_struct_c3()
+// CHECK-LABEL: define swiftcc void @take_struct_c3(i32)
+
+typedef struct {
+ char c0;
+ char c1;
+ char c2;
+ char c3;
+} struct_c4;
+TEST(struct_c4)
+// CHECK-LABEL: define swiftcc i32 @return_struct_c4()
+// CHECK-LABEL: define swiftcc void @take_struct_c4(i32)
+
+typedef struct {
+ char c0;
+ char c1;
+ char c2;
+ char c3;
+ char c4;
+} struct_c5;
+TEST(struct_c5)
+// CHECK-LABEL: define swiftcc i64 @return_struct_c5()
+// CHECK-LABEL: define swiftcc void @take_struct_c5(i64)
+//
+typedef struct {
+ char c0;
+ char c1;
+ char c2;
+ char c3;
+ char c4;
+ char c5;
+ char c6;
+ char c7;
+ char c8;
+} struct_c9;
+TEST(struct_c9)
+// CHECK-LABEL: define swiftcc { i64, i8 } @return_struct_c9()
+// CHECK-LABEL: define swiftcc void @take_struct_c9(i64, i8)
+
+typedef struct {
+ short s0;
+} struct_s1;
+TEST(struct_s1)
+// CHECK-LABEL: define swiftcc i16 @return_struct_s1()
+// CHECK-LABEL: define swiftcc void @take_struct_s1(i16)
+
+typedef struct {
+ short s0;
+ short s1;
+} struct_s2;
+TEST(struct_s2)
+// CHECK-LABEL: define swiftcc i32 @return_struct_s2()
+// CHECK-LABEL: define swiftcc void @take_struct_s2(i32)
+//
+
+typedef struct {
+ short s0;
+ short s1;
+ short s2;
+} struct_s3;
+TEST(struct_s3)
+// CHECK-LABEL: define swiftcc i64 @return_struct_s3()
+// CHECK-LABEL: define swiftcc void @take_struct_s3(i64)
+
+typedef struct {
+ short s0;
+ short s1;
+ short s2;
+ short s3;
+} struct_s4;
+TEST(struct_s4)
+// CHECK-LABEL: define swiftcc i64 @return_struct_s4()
+// CHECK-LABEL: define swiftcc void @take_struct_s4(i64)
+
+typedef struct {
+ short s0;
+ short s1;
+ short s2;
+ short s3;
+ short s4;
+} struct_s5;
+TEST(struct_s5)
+// CHECK-LABEL: define swiftcc { i64, i16 } @return_struct_s5()
+// CHECK-LABEL: define swiftcc void @take_struct_s5(i64, i16)
+
+
+typedef struct {
+ int i0;
+} struct_i1;
+TEST(struct_i1)
+// CHECK-LABEL: define swiftcc i32 @return_struct_i1()
+// CHECK-LABEL: define swiftcc void @take_struct_i1(i32)
+
+typedef struct {
+ int i0;
+ int i1;
+} struct_i2;
+TEST(struct_i2)
+// CHECK-LABEL: define swiftcc i64 @return_struct_i2()
+// CHECK-LABEL: define swiftcc void @take_struct_i2(i64)
+
+typedef struct {
+ int i0;
+ int i1;
+ int i2;
+} struct_i3;
+TEST(struct_i3)
+// CHECK-LABEL: define swiftcc { i64, i32 } @return_struct_i3()
+// CHECK-LABEL: define swiftcc void @take_struct_i3(i64, i32)
+
+typedef struct {
+ int i0;
+ int i1;
+ int i2;
+ int i3;
+} struct_i4;
+TEST(struct_i4)
+// CHECK-LABEL: define swiftcc { i64, i64 } @return_struct_i4()
+// CHECK-LABEL: define swiftcc void @take_struct_i4(i64, i64)
+
+typedef struct {
+ long long l0;
+} struct_l1;
+TEST(struct_l1)
+// CHECK-LABEL: define swiftcc i64 @return_struct_l1()
+// CHECK-LABEL: define swiftcc void @take_struct_l1(i64)
+
+typedef struct {
+ long long l0;
+ long long l1;
+} struct_l2;
+TEST(struct_l2)
+// CHECK-LABEL: define swiftcc { i64, i64 } @return_struct_l2()
+// CHECK-LABEL: define swiftcc void @take_struct_l2(i64, i64)
+
+typedef struct {
+ long long l0;
+ long long l1;
+ long long l2;
+} struct_l3;
+TEST(struct_l3)
+// CHECK-LABEL: define swiftcc { i64, i64, i64 } @return_struct_l3()
+// CHECK-LABEL: define swiftcc void @take_struct_l3(i64, i64, i64)
+
+typedef struct {
+ long long l0;
+ long long l1;
+ long long l2;
+ long long l3;
+} struct_l4;
+TEST(struct_l4)
+// CHECK-LABEL: define swiftcc { i64, i64, i64, i64 } @return_struct_l4()
+// CHECK-LABEL: define swiftcc void @take_struct_l4(i64, i64, i64, i64)
+
+typedef struct {
+ long long l0;
+ long long l1;
+ long long l2;
+ long long l3;
+ long long l4;
+} struct_l5;
+TEST(struct_l5)
+// CHECK: define swiftcc void @return_struct_l5([[STRUCT5:%.*]]* noalias sret
+// CHECK: define swiftcc void @take_struct_l5([[STRUCT5]]*
+
+typedef struct {
+ char16 c0;
+} struct_vc1;
+TEST(struct_vc1)
+// CHECK-LABEL: define swiftcc <16 x i8> @return_struct_vc1()
+// CHECK-LABEL: define swiftcc void @take_struct_vc1(<16 x i8>)
+
+typedef struct {
+ char16 c0;
+ char16 c1;
+} struct_vc2;
+TEST(struct_vc2)
+// CHECK-LABEL: define swiftcc { <16 x i8>, <16 x i8> } @return_struct_vc2()
+// CHECK-LABEL: define swiftcc void @take_struct_vc2(<16 x i8>, <16 x i8>)
+
+typedef struct {
+ char16 c0;
+ char16 c1;
+ char16 c2;
+} struct_vc3;
+TEST(struct_vc3)
+// CHECK-LABEL: define swiftcc { <16 x i8>, <16 x i8>, <16 x i8> } @return_struct_vc3()
+// CHECK-LABEL: define swiftcc void @take_struct_vc3(<16 x i8>, <16 x i8>, <16 x i8>)
+
+typedef struct {
+ char16 c0;
+ char16 c1;
+ char16 c2;
+ char16 c3;
+} struct_vc4;
+TEST(struct_vc4)
+// CHECK-LABEL: define swiftcc { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } @return_struct_vc4()
+// CHECK-LABEL: define swiftcc void @take_struct_vc4(<16 x i8>, <16 x i8>, <16 x i8>, <16 x i8>)
+
+typedef struct {
+ char16 c0;
+ char16 c1;
+ char16 c2;
+ char16 c3;
+ char16 c4;
+} struct_vc5;
+TEST(struct_vc5)
+// CHECK: define swiftcc void @return_struct_vc5([[STRUCT:%.*]]* noalias sret
+// CHECK: define swiftcc void @take_struct_vc5([[STRUCT]]
+
+typedef struct {
+ short8 c0;
+} struct_vs1;
+TEST(struct_vs1)
+// CHECK-LABEL: define swiftcc <8 x i16> @return_struct_vs1()
+// CHECK-LABEL: define swiftcc void @take_struct_vs1(<8 x i16>)
+
+typedef struct {
+ short8 c0;
+ short8 c1;
+} struct_vs2;
+TEST(struct_vs2)
+// CHECK-LABEL: define swiftcc { <8 x i16>, <8 x i16> } @return_struct_vs2()
+// CHECK-LABEL: define swiftcc void @take_struct_vs2(<8 x i16>, <8 x i16>)
+
+typedef struct {
+ short8 c0;
+ short8 c1;
+ short8 c2;
+} struct_vs3;
+TEST(struct_vs3)
+// CHECK-LABEL: define swiftcc { <8 x i16>, <8 x i16>, <8 x i16> } @return_struct_vs3()
+// CHECK-LABEL: define swiftcc void @take_struct_vs3(<8 x i16>, <8 x i16>, <8 x i16>)
+
+typedef struct {
+ short8 c0;
+ short8 c1;
+ short8 c2;
+ short8 c3;
+} struct_vs4;
+TEST(struct_vs4)
+// CHECK-LABEL: define swiftcc { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } @return_struct_vs4()
+// CHECK-LABEL: define swiftcc void @take_struct_vs4(<8 x i16>, <8 x i16>, <8 x i16>, <8 x i16>)
+
+typedef struct {
+ short8 c0;
+ short8 c1;
+ short8 c2;
+ short8 c3;
+ short8 c4;
+} struct_vs5;
+TEST(struct_vs5)
+// CHECK: define swiftcc void @return_struct_vs5([[STRUCT:%.*]]* noalias sret
+// CHECK: define swiftcc void @take_struct_vs5([[STRUCT]]
+
+typedef struct {
+ int4 c0;
+} struct_vi1;
+TEST(struct_vi1)
+// CHECK-LABEL: define swiftcc <4 x i32> @return_struct_vi1()
+// CHECK-LABEL: define swiftcc void @take_struct_vi1(<4 x i32>)
+
+typedef struct {
+ int4 c0;
+ int4 c1;
+} struct_vi2;
+TEST(struct_vi2)
+// CHECK-LABEL: define swiftcc { <4 x i32>, <4 x i32> } @return_struct_vi2()
+// CHECK-LABEL: define swiftcc void @take_struct_vi2(<4 x i32>, <4 x i32>)
+
+typedef struct {
+ int4 c0;
+ int4 c1;
+ int4 c2;
+} struct_vi3;
+TEST(struct_vi3)
+// CHECK-LABEL: define swiftcc { <4 x i32>, <4 x i32>, <4 x i32> } @return_struct_vi3()
+// CHECK-LABEL: define swiftcc void @take_struct_vi3(<4 x i32>, <4 x i32>, <4 x i32>)
+
+typedef struct {
+ int4 c0;
+ int4 c1;
+ int4 c2;
+ int4 c3;
+} struct_vi4;
+TEST(struct_vi4)
+// CHECK-LABEL: define swiftcc { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } @return_struct_vi4()
+// CHECK-LABEL: define swiftcc void @take_struct_vi4(<4 x i32>, <4 x i32>, <4 x i32>, <4 x i32>)
+
+typedef struct {
+ int4 c0;
+ int4 c1;
+ int4 c2;
+ int4 c3;
+ int4 c4;
+} struct_vi5;
+TEST(struct_vi5)
+// CHECK: define swiftcc void @return_struct_vi5([[STRUCT:%.*]]* noalias sret
+// CHECK: define swiftcc void @take_struct_vi5([[STRUCT]]
+
+typedef struct {
+ long2 c0;
+} struct_vl1;
+TEST(struct_vl1)
+// CHECK-LABEL: define swiftcc <2 x i64> @return_struct_vl1()
+// CHECK-LABEL: define swiftcc void @take_struct_vl1(<2 x i64>)
+
+typedef struct {
+ long2 c0;
+ long2 c1;
+ long2 c2;
+ long2 c3;
+} struct_vl4;
+TEST(struct_vl4)
+// CHECK-LABEL: define swiftcc { <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> } @return_struct_vl4()
+// CHECK-LABEL: define swiftcc void @take_struct_vl4(<2 x i64>, <2 x i64>, <2 x i64>, <2 x i64>)
+
+typedef struct {
+ long2 c0;
+ long2 c1;
+ long2 c2;
+ long2 c3;
+ long2 c4;
+} struct_vl5;
+TEST(struct_vl5)
+// CHECK: define swiftcc void @return_struct_vl5([[STRUCT:%.*]]* noalias sret
+// CHECK: define swiftcc void @take_struct_vl5([[STRUCT]]
+
+typedef struct {
+ double2 c0;
+} struct_vd1;
+TEST(struct_vd1)
+// CHECK-LABEL: define swiftcc <2 x double> @return_struct_vd1()
+// CHECK-LABEL: define swiftcc void @take_struct_vd1(<2 x double>)
+
+typedef struct {
+ double2 c0;
+ double2 c1;
+ double2 c2;
+ double2 c3;
+} struct_vd4;
+TEST(struct_vd4)
+// CHECK-LABEL: define swiftcc { <2 x double>, <2 x double>, <2 x double>, <2 x double> } @return_struct_vd4()
+// CHECK-LABEL: define swiftcc void @take_struct_vd4(<2 x double>, <2 x double>, <2 x double>, <2 x double>)
+
+typedef struct {
+ double2 c0;
+ double2 c1;
+ double2 c2;
+ double2 c3;
+ double2 c4;
+} struct_vd5;
+TEST(struct_vd5)
+// CHECK: define swiftcc void @return_struct_vd5([[STRUCT:%.*]]* noalias sret
+// CHECK: define swiftcc void @take_struct_vd5([[STRUCT]]
+
+typedef struct {
+ double4 c0;
+} struct_vd41;
+TEST(struct_vd41)
+// CHECK-LABEL: define swiftcc { <2 x double>, <2 x double> } @return_struct_vd41()
+// CHECK-LABEL: define swiftcc void @take_struct_vd41(<2 x double>, <2 x double>)
+
+typedef struct {
+ double4 c0;
+ double4 c1;
+} struct_vd42;
+TEST(struct_vd42)
+// CHECK-LABEL: define swiftcc { <2 x double>, <2 x double>, <2 x double>, <2 x double> } @return_struct_vd42()
+// CHECK-LABEL: define swiftcc void @take_struct_vd42(<2 x double>, <2 x double>, <2 x double>, <2 x double>)
+
+typedef struct {
+ double4 c0;
+ double4 c1;
+ double4 c2;
+} struct_vd43;
+TEST(struct_vd43)
+// CHECK: define swiftcc void @return_struct_vd43([[STRUCT:%.*]]* noalias sret
+// CHECK: define swiftcc void @take_struct_vd43([[STRUCT]]
+
+typedef struct {
+ float4 c0;
+} struct_vf1;
+TEST(struct_vf1)
+// CHECK-LABEL: define swiftcc <4 x float> @return_struct_vf1()
+// CHECK-LABEL: define swiftcc void @take_struct_vf1(<4 x float>)
+
+typedef struct {
+ float4 c0;
+ float4 c1;
+} struct_vf2;
+TEST(struct_vf2)
+// CHECK-LABEL: define swiftcc { <4 x float>, <4 x float> } @return_struct_vf2()
+// CHECK-LABEL: define swiftcc void @take_struct_vf2(<4 x float>, <4 x float>)
+
+typedef struct {
+ float4 c0;
+ float4 c1;
+ float4 c2;
+ float4 c3;
+} struct_vf4;
+TEST(struct_vf4)
+// CHECK-LABEL: define swiftcc { <4 x float>, <4 x float>, <4 x float>, <4 x float> } @return_struct_vf4()
+// CHECK-LABEL: define swiftcc void @take_struct_vf4(<4 x float>, <4 x float>, <4 x float>, <4 x float>)
+
+typedef struct {
+ float4 c0;
+ float4 c1;
+ float4 c2;
+ float4 c3;
+ float4 c4;
+} struct_vf5;
+TEST(struct_vf5)
+// CHECK: define swiftcc void @return_struct_vf5([[STRUCT:%.*]]* noalias sret
+// CHECK: define swiftcc void @take_struct_vf5([[STRUCT]]
+
+typedef struct {
+ float8 c0;
+} struct_vf81;
+TEST(struct_vf81)
+// CHECK-LABEL: define swiftcc { <4 x float>, <4 x float> } @return_struct_vf81()
+// CHECK-LABEL: define swiftcc void @take_struct_vf81(<4 x float>, <4 x float>)
+
+// Don't crash.
+typedef union {
+int4 v[2];
+struct {
+ int LSW;
+ int d7;
+ int d6;
+ int d5;
+ int d4;
+ int d3;
+ int d2;
+ int MSW;
+} s;
+} union_het_vecint;
+TEST(union_het_vecint)
+// CHECK: define swiftcc void @return_union_het_vecint([[UNION:%.*]]* noalias sret
+// CHECK: define swiftcc void @take_union_het_vecint([[UNION]]*
diff --git a/test/CodeGen/CFStrings.c b/test/CodeGen/CFStrings.c
index 17de39c6aed8..4edb5ff26e60 100644
--- a/test/CodeGen/CFStrings.c
+++ b/test/CodeGen/CFStrings.c
@@ -13,6 +13,10 @@
// RUN: %clang_cc1 -triple i386-apple-macosx -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MACHO -check-prefix CHECK-MACHO32
// RUN: %clang_cc1 -triple x86_64-macho -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MACHO -check-prefix CHECK-MACHO64
+// RUN: %clang_cc1 -triple thumbv7-windows -S %s -o - | FileCheck %s -check-prefix CHECK-ASM-COFF
+// RUN: %clang_cc1 -triple thumbv7-elf -S %s -o - | FileCheck %s -check-prefix CHECK-ASM-ELF
+// RUN: %clang_cc1 -triple thumbv7-macho -S %s -o - | FileCheck %s -check-prefix CHECK-ASM-MACHO
+
typedef struct __CFString *CFStringRef;
const CFStringRef one = (CFStringRef)__builtin___CFStringMakeConstantString("one");
const CFStringRef two = (CFStringRef)__builtin___CFStringMakeConstantString("\xef\xbf\xbd\x74\xef\xbf\xbd\x77\xef\xbf\xbd\x6f");
@@ -21,21 +25,21 @@ const CFStringRef two = (CFStringRef)__builtin___CFStringMakeConstantString("\xe
// CHECK-ELF: @.str = private unnamed_addr constant [4 x i8] c"one\00", align 1
// CHECK-MACHO: @.str = private unnamed_addr constant [4 x i8] c"one\00", section "__TEXT,__cstring,cstring_literals", align 1
-// CHECK-COFF: @_unnamed_cfstring_ = private constant %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 1992, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i32 3 }, section "cfstring", align {{[48]}}
-// CHECK-ELF32: @_unnamed_cfstring_ = private constant %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 1992, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i32 3 }, section "cfstring", align 4
-// CHECK-ELF64: @_unnamed_cfstring_ = private constant %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 1992, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i64 3 }, section "cfstring", align 8
-// CHECK-MACHO32: @_unnamed_cfstring_ = private constant %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 1992, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i32 3 }, section "__DATA,__cfstring", align 4
-// CHECK-MACHO64: @_unnamed_cfstring_ = private constant %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 1992, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i64 3 }, section "__DATA,__cfstring", align 8
+// CHECK-COFF: @_unnamed_cfstring_ = private global %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 1992, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i32 3 }, section "cfstring", align {{[48]}}
+// CHECK-ELF32: @_unnamed_cfstring_ = private global %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 1992, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i32 3 }, section "cfstring", align 4
+// CHECK-ELF64: @_unnamed_cfstring_ = private global %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 1992, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i64 3 }, section "cfstring", align 8
+// CHECK-MACHO32: @_unnamed_cfstring_ = private global %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 1992, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i32 3 }, section "__DATA,__cfstring", align 4
+// CHECK-MACHO64: @_unnamed_cfstring_ = private global %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 1992, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i64 3 }, section "__DATA,__cfstring", align 8
// CHECK-COFF: @.str.1 = private unnamed_addr constant [7 x i16] [i16 -3, i16 116, i16 -3, i16 119, i16 -3, i16 111, i16 0], align 2
// CHECK-ELF: @.str.1 = private unnamed_addr constant [7 x i16] [i16 -3, i16 116, i16 -3, i16 119, i16 -3, i16 111, i16 0], align 2
// CHECK-MACHO: @.str.1 = private unnamed_addr constant [7 x i16] [i16 -3, i16 116, i16 -3, i16 119, i16 -3, i16 111, i16 0], section "__TEXT,__ustring", align 2
-// CHECK-COFF: @_unnamed_cfstring_.2 = private constant %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 2000, i8* bitcast ([7 x i16]* @.str.1 to i8*), i32 6 }, section "cfstring", align {{[48]}}
-// CHECK-ELF32: @_unnamed_cfstring_.2 = private constant %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 2000, i8* bitcast ([7 x i16]* @.str.1 to i8*), i32 6 }, section "cfstring", align 4
-// CHECK-ELF64: @_unnamed_cfstring_.2 = private constant %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 2000, i8* bitcast ([7 x i16]* @.str.1 to i8*), i64 6 }, section "cfstring", align 8
-// CHECK-MACHO32: @_unnamed_cfstring_.2 = private constant %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 2000, i8* bitcast ([7 x i16]* @.str.1 to i8*), i32 6 }, section "__DATA,__cfstring", align 4
-// CHECK-MACHO64: @_unnamed_cfstring_.2 = private constant %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 2000, i8* bitcast ([7 x i16]* @.str.1 to i8*), i64 6 }, section "__DATA,__cfstring", align 8
+// CHECK-COFF: @_unnamed_cfstring_.2 = private global %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 2000, i8* bitcast ([7 x i16]* @.str.1 to i8*), i32 6 }, section "cfstring", align {{[48]}}
+// CHECK-ELF32: @_unnamed_cfstring_.2 = private global %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 2000, i8* bitcast ([7 x i16]* @.str.1 to i8*), i32 6 }, section "cfstring", align 4
+// CHECK-ELF64: @_unnamed_cfstring_.2 = private global %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 2000, i8* bitcast ([7 x i16]* @.str.1 to i8*), i64 6 }, section "cfstring", align 8
+// CHECK-MACHO32: @_unnamed_cfstring_.2 = private global %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 2000, i8* bitcast ([7 x i16]* @.str.1 to i8*), i32 6 }, section "__DATA,__cfstring", align 4
+// CHECK-MACHO64: @_unnamed_cfstring_.2 = private global %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 2000, i8* bitcast ([7 x i16]* @.str.1 to i8*), i64 6 }, section "__DATA,__cfstring", align 8
// CHECK-ELF-DATA-SECTION: .section .rodata.str1.1
// CHECK-ELF-DATA-SECTION: .asciz "one"
@@ -49,3 +53,7 @@ const CFStringRef two = (CFStringRef)__builtin___CFStringMakeConstantString("\xe
// CHECK-ELF-DATA-SECTION: .short 111
// CHECK-ELF-DATA-SECTION: .short 0
+// CHECK-ASM-COFF: .section cfstring,"dw"
+// CHECK-ASM-ELF: .section cfstring,"aw"
+// CHECK-ASM-MACHO: .section __DATA,__cfstring
+
diff --git a/test/CodeGen/Inputs/debug-info-file-checksum.c b/test/CodeGen/Inputs/debug-info-file-checksum.c
new file mode 100644
index 000000000000..081f6f0c2891
--- /dev/null
+++ b/test/CodeGen/Inputs/debug-info-file-checksum.c
@@ -0,0 +1,3 @@
+int foo(int x) {
+ return x+1;
+}
diff --git a/test/CodeGen/Inputs/opt-record.proftext b/test/CodeGen/Inputs/opt-record.proftext
new file mode 100644
index 000000000000..cf2530c6be54
--- /dev/null
+++ b/test/CodeGen/Inputs/opt-record.proftext
@@ -0,0 +1,26 @@
+foo
+# Func Hash:
+0
+# Num Counters:
+1
+# Counter Values:
+30
+
+bar
+# Func Hash:
+0
+# Num Counters:
+1
+# Counter Values:
+30
+
+Test
+# Func Hash:
+269
+# Num Counters:
+3
+# Counter Values:
+1
+30
+15
+
diff --git a/test/CodeGen/aarch64-neon-2velem.c b/test/CodeGen/aarch64-neon-2velem.c
index 36500f62a5d9..2866990433df 100644
--- a/test/CodeGen/aarch64-neon-2velem.c
+++ b/test/CodeGen/aarch64-neon-2velem.c
@@ -4,7 +4,7 @@
#include <arm_neon.h>
-// CHECK-LABEL: define <4 x i16> @test_vmla_lane_s16(<4 x i16> %a, <4 x i16> %b, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmla_lane_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[MUL:%.*]] = mul <4 x i16> %b, [[SHUFFLE]]
// CHECK: [[ADD:%.*]] = add <4 x i16> %a, [[MUL]]
@@ -13,7 +13,7 @@ int16x4_t test_vmla_lane_s16(int16x4_t a, int16x4_t b, int16x4_t v) {
return vmla_lane_s16(a, b, v, 3);
}
-// CHECK-LABEL: define <8 x i16> @test_vmlaq_lane_s16(<8 x i16> %a, <8 x i16> %b, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmlaq_lane_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <8 x i32> <i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3>
// CHECK: [[MUL:%.*]] = mul <8 x i16> %b, [[SHUFFLE]]
// CHECK: [[ADD:%.*]] = add <8 x i16> %a, [[MUL]]
@@ -22,7 +22,7 @@ int16x8_t test_vmlaq_lane_s16(int16x8_t a, int16x8_t b, int16x4_t v) {
return vmlaq_lane_s16(a, b, v, 3);
}
-// CHECK-LABEL: define <2 x i32> @test_vmla_lane_s32(<2 x i32> %a, <2 x i32> %b, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmla_lane_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> <i32 1, i32 1>
// CHECK: [[MUL:%.*]] = mul <2 x i32> %b, [[SHUFFLE]]
// CHECK: [[ADD:%.*]] = add <2 x i32> %a, [[MUL]]
@@ -31,7 +31,7 @@ int32x2_t test_vmla_lane_s32(int32x2_t a, int32x2_t b, int32x2_t v) {
return vmla_lane_s32(a, b, v, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlaq_lane_s32(<4 x i32> %a, <4 x i32> %b, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmlaq_lane_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
// CHECK: [[MUL:%.*]] = mul <4 x i32> %b, [[SHUFFLE]]
// CHECK: [[ADD:%.*]] = add <4 x i32> %a, [[MUL]]
@@ -40,7 +40,7 @@ int32x4_t test_vmlaq_lane_s32(int32x4_t a, int32x4_t b, int32x2_t v) {
return vmlaq_lane_s32(a, b, v, 1);
}
-// CHECK-LABEL: define <4 x i16> @test_vmla_laneq_s16(<4 x i16> %a, <4 x i16> %b, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmla_laneq_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> <i32 7, i32 7, i32 7, i32 7>
// CHECK: [[MUL:%.*]] = mul <4 x i16> %b, [[SHUFFLE]]
// CHECK: [[ADD:%.*]] = add <4 x i16> %a, [[MUL]]
@@ -49,7 +49,7 @@ int16x4_t test_vmla_laneq_s16(int16x4_t a, int16x4_t b, int16x8_t v) {
return vmla_laneq_s16(a, b, v, 7);
}
-// CHECK-LABEL: define <8 x i16> @test_vmlaq_laneq_s16(<8 x i16> %a, <8 x i16> %b, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmlaq_laneq_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <8 x i32> <i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7>
// CHECK: [[MUL:%.*]] = mul <8 x i16> %b, [[SHUFFLE]]
// CHECK: [[ADD:%.*]] = add <8 x i16> %a, [[MUL]]
@@ -58,7 +58,7 @@ int16x8_t test_vmlaq_laneq_s16(int16x8_t a, int16x8_t b, int16x8_t v) {
return vmlaq_laneq_s16(a, b, v, 7);
}
-// CHECK-LABEL: define <2 x i32> @test_vmla_laneq_s32(<2 x i32> %a, <2 x i32> %b, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmla_laneq_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> <i32 3, i32 3>
// CHECK: [[MUL:%.*]] = mul <2 x i32> %b, [[SHUFFLE]]
// CHECK: [[ADD:%.*]] = add <2 x i32> %a, [[MUL]]
@@ -67,7 +67,7 @@ int32x2_t test_vmla_laneq_s32(int32x2_t a, int32x2_t b, int32x4_t v) {
return vmla_laneq_s32(a, b, v, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlaq_laneq_s32(<4 x i32> %a, <4 x i32> %b, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmlaq_laneq_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[MUL:%.*]] = mul <4 x i32> %b, [[SHUFFLE]]
// CHECK: [[ADD:%.*]] = add <4 x i32> %a, [[MUL]]
@@ -76,7 +76,7 @@ int32x4_t test_vmlaq_laneq_s32(int32x4_t a, int32x4_t b, int32x4_t v) {
return vmlaq_laneq_s32(a, b, v, 3);
}
-// CHECK-LABEL: define <4 x i16> @test_vmls_lane_s16(<4 x i16> %a, <4 x i16> %b, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmls_lane_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[MUL:%.*]] = mul <4 x i16> %b, [[SHUFFLE]]
// CHECK: [[SUB:%.*]] = sub <4 x i16> %a, [[MUL]]
@@ -85,7 +85,7 @@ int16x4_t test_vmls_lane_s16(int16x4_t a, int16x4_t b, int16x4_t v) {
return vmls_lane_s16(a, b, v, 3);
}
-// CHECK-LABEL: define <8 x i16> @test_vmlsq_lane_s16(<8 x i16> %a, <8 x i16> %b, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmlsq_lane_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <8 x i32> <i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3>
// CHECK: [[MUL:%.*]] = mul <8 x i16> %b, [[SHUFFLE]]
// CHECK: [[SUB:%.*]] = sub <8 x i16> %a, [[MUL]]
@@ -94,7 +94,7 @@ int16x8_t test_vmlsq_lane_s16(int16x8_t a, int16x8_t b, int16x4_t v) {
return vmlsq_lane_s16(a, b, v, 3);
}
-// CHECK-LABEL: define <2 x i32> @test_vmls_lane_s32(<2 x i32> %a, <2 x i32> %b, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmls_lane_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> <i32 1, i32 1>
// CHECK: [[MUL:%.*]] = mul <2 x i32> %b, [[SHUFFLE]]
// CHECK: [[SUB:%.*]] = sub <2 x i32> %a, [[MUL]]
@@ -103,7 +103,7 @@ int32x2_t test_vmls_lane_s32(int32x2_t a, int32x2_t b, int32x2_t v) {
return vmls_lane_s32(a, b, v, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlsq_lane_s32(<4 x i32> %a, <4 x i32> %b, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmlsq_lane_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
// CHECK: [[MUL:%.*]] = mul <4 x i32> %b, [[SHUFFLE]]
// CHECK: [[SUB:%.*]] = sub <4 x i32> %a, [[MUL]]
@@ -112,7 +112,7 @@ int32x4_t test_vmlsq_lane_s32(int32x4_t a, int32x4_t b, int32x2_t v) {
return vmlsq_lane_s32(a, b, v, 1);
}
-// CHECK-LABEL: define <4 x i16> @test_vmls_laneq_s16(<4 x i16> %a, <4 x i16> %b, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmls_laneq_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> <i32 7, i32 7, i32 7, i32 7>
// CHECK: [[MUL:%.*]] = mul <4 x i16> %b, [[SHUFFLE]]
// CHECK: [[SUB:%.*]] = sub <4 x i16> %a, [[MUL]]
@@ -121,7 +121,7 @@ int16x4_t test_vmls_laneq_s16(int16x4_t a, int16x4_t b, int16x8_t v) {
return vmls_laneq_s16(a, b, v, 7);
}
-// CHECK-LABEL: define <8 x i16> @test_vmlsq_laneq_s16(<8 x i16> %a, <8 x i16> %b, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmlsq_laneq_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <8 x i32> <i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7>
// CHECK: [[MUL:%.*]] = mul <8 x i16> %b, [[SHUFFLE]]
// CHECK: [[SUB:%.*]] = sub <8 x i16> %a, [[MUL]]
@@ -130,7 +130,7 @@ int16x8_t test_vmlsq_laneq_s16(int16x8_t a, int16x8_t b, int16x8_t v) {
return vmlsq_laneq_s16(a, b, v, 7);
}
-// CHECK-LABEL: define <2 x i32> @test_vmls_laneq_s32(<2 x i32> %a, <2 x i32> %b, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmls_laneq_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> <i32 3, i32 3>
// CHECK: [[MUL:%.*]] = mul <2 x i32> %b, [[SHUFFLE]]
// CHECK: [[SUB:%.*]] = sub <2 x i32> %a, [[MUL]]
@@ -139,7 +139,7 @@ int32x2_t test_vmls_laneq_s32(int32x2_t a, int32x2_t b, int32x4_t v) {
return vmls_laneq_s32(a, b, v, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlsq_laneq_s32(<4 x i32> %a, <4 x i32> %b, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmlsq_laneq_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[MUL:%.*]] = mul <4 x i32> %b, [[SHUFFLE]]
// CHECK: [[SUB:%.*]] = sub <4 x i32> %a, [[MUL]]
@@ -148,7 +148,7 @@ int32x4_t test_vmlsq_laneq_s32(int32x4_t a, int32x4_t b, int32x4_t v) {
return vmlsq_laneq_s32(a, b, v, 3);
}
-// CHECK-LABEL: define <4 x i16> @test_vmul_lane_s16(<4 x i16> %a, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmul_lane_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[MUL:%.*]] = mul <4 x i16> %a, [[SHUFFLE]]
// CHECK: ret <4 x i16> [[MUL]]
@@ -156,7 +156,7 @@ int16x4_t test_vmul_lane_s16(int16x4_t a, int16x4_t v) {
return vmul_lane_s16(a, v, 3);
}
-// CHECK-LABEL: define <8 x i16> @test_vmulq_lane_s16(<8 x i16> %a, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmulq_lane_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <8 x i32> <i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3>
// CHECK: [[MUL:%.*]] = mul <8 x i16> %a, [[SHUFFLE]]
// CHECK: ret <8 x i16> [[MUL]]
@@ -164,7 +164,7 @@ int16x8_t test_vmulq_lane_s16(int16x8_t a, int16x4_t v) {
return vmulq_lane_s16(a, v, 3);
}
-// CHECK-LABEL: define <2 x i32> @test_vmul_lane_s32(<2 x i32> %a, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmul_lane_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> <i32 1, i32 1>
// CHECK: [[MUL:%.*]] = mul <2 x i32> %a, [[SHUFFLE]]
// CHECK: ret <2 x i32> [[MUL]]
@@ -172,7 +172,7 @@ int32x2_t test_vmul_lane_s32(int32x2_t a, int32x2_t v) {
return vmul_lane_s32(a, v, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vmulq_lane_s32(<4 x i32> %a, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmulq_lane_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
// CHECK: [[MUL:%.*]] = mul <4 x i32> %a, [[SHUFFLE]]
// CHECK: ret <4 x i32> [[MUL]]
@@ -180,7 +180,7 @@ int32x4_t test_vmulq_lane_s32(int32x4_t a, int32x2_t v) {
return vmulq_lane_s32(a, v, 1);
}
-// CHECK-LABEL: define <4 x i16> @test_vmul_lane_u16(<4 x i16> %a, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmul_lane_u16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[MUL:%.*]] = mul <4 x i16> %a, [[SHUFFLE]]
// CHECK: ret <4 x i16> [[MUL]]
@@ -188,7 +188,7 @@ uint16x4_t test_vmul_lane_u16(uint16x4_t a, uint16x4_t v) {
return vmul_lane_u16(a, v, 3);
}
-// CHECK-LABEL: define <8 x i16> @test_vmulq_lane_u16(<8 x i16> %a, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmulq_lane_u16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <8 x i32> <i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3>
// CHECK: [[MUL:%.*]] = mul <8 x i16> %a, [[SHUFFLE]]
// CHECK: ret <8 x i16> [[MUL]]
@@ -196,7 +196,7 @@ uint16x8_t test_vmulq_lane_u16(uint16x8_t a, uint16x4_t v) {
return vmulq_lane_u16(a, v, 3);
}
-// CHECK-LABEL: define <2 x i32> @test_vmul_lane_u32(<2 x i32> %a, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmul_lane_u32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> <i32 1, i32 1>
// CHECK: [[MUL:%.*]] = mul <2 x i32> %a, [[SHUFFLE]]
// CHECK: ret <2 x i32> [[MUL]]
@@ -204,7 +204,7 @@ uint32x2_t test_vmul_lane_u32(uint32x2_t a, uint32x2_t v) {
return vmul_lane_u32(a, v, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vmulq_lane_u32(<4 x i32> %a, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmulq_lane_u32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
// CHECK: [[MUL:%.*]] = mul <4 x i32> %a, [[SHUFFLE]]
// CHECK: ret <4 x i32> [[MUL]]
@@ -212,7 +212,7 @@ uint32x4_t test_vmulq_lane_u32(uint32x4_t a, uint32x2_t v) {
return vmulq_lane_u32(a, v, 1);
}
-// CHECK-LABEL: define <4 x i16> @test_vmul_laneq_s16(<4 x i16> %a, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmul_laneq_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> <i32 7, i32 7, i32 7, i32 7>
// CHECK: [[MUL:%.*]] = mul <4 x i16> %a, [[SHUFFLE]]
// CHECK: ret <4 x i16> [[MUL]]
@@ -220,7 +220,7 @@ int16x4_t test_vmul_laneq_s16(int16x4_t a, int16x8_t v) {
return vmul_laneq_s16(a, v, 7);
}
-// CHECK-LABEL: define <8 x i16> @test_vmulq_laneq_s16(<8 x i16> %a, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmulq_laneq_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <8 x i32> <i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7>
// CHECK: [[MUL:%.*]] = mul <8 x i16> %a, [[SHUFFLE]]
// CHECK: ret <8 x i16> [[MUL]]
@@ -228,7 +228,7 @@ int16x8_t test_vmulq_laneq_s16(int16x8_t a, int16x8_t v) {
return vmulq_laneq_s16(a, v, 7);
}
-// CHECK-LABEL: define <2 x i32> @test_vmul_laneq_s32(<2 x i32> %a, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmul_laneq_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> <i32 3, i32 3>
// CHECK: [[MUL:%.*]] = mul <2 x i32> %a, [[SHUFFLE]]
// CHECK: ret <2 x i32> [[MUL]]
@@ -236,7 +236,7 @@ int32x2_t test_vmul_laneq_s32(int32x2_t a, int32x4_t v) {
return vmul_laneq_s32(a, v, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vmulq_laneq_s32(<4 x i32> %a, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmulq_laneq_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[MUL:%.*]] = mul <4 x i32> %a, [[SHUFFLE]]
// CHECK: ret <4 x i32> [[MUL]]
@@ -244,7 +244,7 @@ int32x4_t test_vmulq_laneq_s32(int32x4_t a, int32x4_t v) {
return vmulq_laneq_s32(a, v, 3);
}
-// CHECK-LABEL: define <4 x i16> @test_vmul_laneq_u16(<4 x i16> %a, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmul_laneq_u16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> <i32 7, i32 7, i32 7, i32 7>
// CHECK: [[MUL:%.*]] = mul <4 x i16> %a, [[SHUFFLE]]
// CHECK: ret <4 x i16> [[MUL]]
@@ -252,7 +252,7 @@ uint16x4_t test_vmul_laneq_u16(uint16x4_t a, uint16x8_t v) {
return vmul_laneq_u16(a, v, 7);
}
-// CHECK-LABEL: define <8 x i16> @test_vmulq_laneq_u16(<8 x i16> %a, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmulq_laneq_u16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <8 x i32> <i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7>
// CHECK: [[MUL:%.*]] = mul <8 x i16> %a, [[SHUFFLE]]
// CHECK: ret <8 x i16> [[MUL]]
@@ -260,7 +260,7 @@ uint16x8_t test_vmulq_laneq_u16(uint16x8_t a, uint16x8_t v) {
return vmulq_laneq_u16(a, v, 7);
}
-// CHECK-LABEL: define <2 x i32> @test_vmul_laneq_u32(<2 x i32> %a, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmul_laneq_u32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> <i32 3, i32 3>
// CHECK: [[MUL:%.*]] = mul <2 x i32> %a, [[SHUFFLE]]
// CHECK: ret <2 x i32> [[MUL]]
@@ -268,7 +268,7 @@ uint32x2_t test_vmul_laneq_u32(uint32x2_t a, uint32x4_t v) {
return vmul_laneq_u32(a, v, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vmulq_laneq_u32(<4 x i32> %a, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmulq_laneq_u32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[MUL:%.*]] = mul <4 x i32> %a, [[SHUFFLE]]
// CHECK: ret <4 x i32> [[MUL]]
@@ -276,7 +276,7 @@ uint32x4_t test_vmulq_laneq_u32(uint32x4_t a, uint32x4_t v) {
return vmulq_laneq_u32(a, v, 3);
}
-// CHECK-LABEL: define <2 x float> @test_vfma_lane_f32(<2 x float> %a, <2 x float> %b, <2 x float> %v) #0 {
+// CHECK-LABEL: @test_vfma_lane_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x float> %v to <8 x i8>
@@ -290,7 +290,7 @@ float32x2_t test_vfma_lane_f32(float32x2_t a, float32x2_t b, float32x2_t v) {
return vfma_lane_f32(a, b, v, 1);
}
-// CHECK-LABEL: define <4 x float> @test_vfmaq_lane_f32(<4 x float> %a, <4 x float> %b, <2 x float> %v) #0 {
+// CHECK-LABEL: @test_vfmaq_lane_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x float> %v to <8 x i8>
@@ -304,7 +304,7 @@ float32x4_t test_vfmaq_lane_f32(float32x4_t a, float32x4_t b, float32x2_t v) {
return vfmaq_lane_f32(a, b, v, 1);
}
-// CHECK-LABEL: define <2 x float> @test_vfma_laneq_f32(<2 x float> %a, <2 x float> %b, <4 x float> %v) #0 {
+// CHECK-LABEL: @test_vfma_laneq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x float> %v to <16 x i8>
@@ -318,7 +318,7 @@ float32x2_t test_vfma_laneq_f32(float32x2_t a, float32x2_t b, float32x4_t v) {
return vfma_laneq_f32(a, b, v, 3);
}
-// CHECK-LABEL: define <4 x float> @test_vfmaq_laneq_f32(<4 x float> %a, <4 x float> %b, <4 x float> %v) #0 {
+// CHECK-LABEL: @test_vfmaq_laneq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x float> %v to <16 x i8>
@@ -332,7 +332,7 @@ float32x4_t test_vfmaq_laneq_f32(float32x4_t a, float32x4_t b, float32x4_t v) {
return vfmaq_laneq_f32(a, b, v, 3);
}
-// CHECK-LABEL: define <2 x float> @test_vfms_lane_f32(<2 x float> %a, <2 x float> %b, <2 x float> %v) #0 {
+// CHECK-LABEL: @test_vfms_lane_f32(
// CHECK: [[SUB:%.*]] = fsub <2 x float> <float -0.000000e+00, float -0.000000e+00>, %b
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> [[SUB]] to <8 x i8>
@@ -347,7 +347,7 @@ float32x2_t test_vfms_lane_f32(float32x2_t a, float32x2_t b, float32x2_t v) {
return vfms_lane_f32(a, b, v, 1);
}
-// CHECK-LABEL: define <4 x float> @test_vfmsq_lane_f32(<4 x float> %a, <4 x float> %b, <2 x float> %v) #0 {
+// CHECK-LABEL: @test_vfmsq_lane_f32(
// CHECK: [[SUB:%.*]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %b
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> [[SUB]] to <16 x i8>
@@ -362,7 +362,7 @@ float32x4_t test_vfmsq_lane_f32(float32x4_t a, float32x4_t b, float32x2_t v) {
return vfmsq_lane_f32(a, b, v, 1);
}
-// CHECK-LABEL: define <2 x float> @test_vfms_laneq_f32(<2 x float> %a, <2 x float> %b, <4 x float> %v) #0 {
+// CHECK-LABEL: @test_vfms_laneq_f32(
// CHECK: [[SUB:%.*]] = fsub <2 x float> <float -0.000000e+00, float -0.000000e+00>, %b
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> [[SUB]] to <8 x i8>
@@ -377,7 +377,7 @@ float32x2_t test_vfms_laneq_f32(float32x2_t a, float32x2_t b, float32x4_t v) {
return vfms_laneq_f32(a, b, v, 3);
}
-// CHECK-LABEL: define <4 x float> @test_vfmsq_laneq_f32(<4 x float> %a, <4 x float> %b, <4 x float> %v) #0 {
+// CHECK-LABEL: @test_vfmsq_laneq_f32(
// CHECK: [[SUB:%.*]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %b
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> [[SUB]] to <16 x i8>
@@ -392,7 +392,7 @@ float32x4_t test_vfmsq_laneq_f32(float32x4_t a, float32x4_t b, float32x4_t v) {
return vfmsq_laneq_f32(a, b, v, 3);
}
-// CHECK-LABEL: define <2 x double> @test_vfmaq_lane_f64(<2 x double> %a, <2 x double> %b, <1 x double> %v) #0 {
+// CHECK-LABEL: @test_vfmaq_lane_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x double> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <1 x double> %v to <8 x i8>
@@ -406,7 +406,7 @@ float64x2_t test_vfmaq_lane_f64(float64x2_t a, float64x2_t b, float64x1_t v) {
return vfmaq_lane_f64(a, b, v, 0);
}
-// CHECK-LABEL: define <2 x double> @test_vfmaq_laneq_f64(<2 x double> %a, <2 x double> %b, <2 x double> %v) #0 {
+// CHECK-LABEL: @test_vfmaq_laneq_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x double> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x double> %v to <16 x i8>
@@ -420,7 +420,7 @@ float64x2_t test_vfmaq_laneq_f64(float64x2_t a, float64x2_t b, float64x2_t v) {
return vfmaq_laneq_f64(a, b, v, 1);
}
-// CHECK-LABEL: define <2 x double> @test_vfmsq_lane_f64(<2 x double> %a, <2 x double> %b, <1 x double> %v) #0 {
+// CHECK-LABEL: @test_vfmsq_lane_f64(
// CHECK: [[SUB:%.*]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %b
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x double> [[SUB]] to <16 x i8>
@@ -435,7 +435,7 @@ float64x2_t test_vfmsq_lane_f64(float64x2_t a, float64x2_t b, float64x1_t v) {
return vfmsq_lane_f64(a, b, v, 0);
}
-// CHECK-LABEL: define <2 x double> @test_vfmsq_laneq_f64(<2 x double> %a, <2 x double> %b, <2 x double> %v) #0 {
+// CHECK-LABEL: @test_vfmsq_laneq_f64(
// CHECK: [[SUB:%.*]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %b
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x double> [[SUB]] to <16 x i8>
@@ -450,7 +450,7 @@ float64x2_t test_vfmsq_laneq_f64(float64x2_t a, float64x2_t b, float64x2_t v) {
return vfmsq_laneq_f64(a, b, v, 1);
}
-// CHECK-LABEL: define float @test_vfmas_laneq_f32(float %a, float %b, <4 x float> %v) #0 {
+// CHECK-LABEL: @test_vfmas_laneq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %v to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
// CHECK: [[EXTRACT:%.*]] = extractelement <4 x float> [[TMP1]], i32 3
@@ -460,7 +460,7 @@ float32_t test_vfmas_laneq_f32(float32_t a, float32_t b, float32x4_t v) {
return vfmas_laneq_f32(a, b, v, 3);
}
-// CHECK-LABEL: define double @test_vfmsd_lane_f64(double %a, double %b, <1 x double> %v) #0 {
+// CHECK-LABEL: @test_vfmsd_lane_f64(
// CHECK: [[SUB:%.*]] = fsub double -0.000000e+00, %b
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %v to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x double>
@@ -471,7 +471,7 @@ float64_t test_vfmsd_lane_f64(float64_t a, float64_t b, float64x1_t v) {
return vfmsd_lane_f64(a, b, v, 0);
}
-// CHECK-LABEL: define float @test_vfmss_laneq_f32(float %a, float %b, <4 x float> %v) #0 {
+// CHECK-LABEL: @test_vfmss_laneq_f32(
// CHECK: [[SUB:%.*]] = fsub float -0.000000e+00, %b
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %v to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
@@ -482,7 +482,7 @@ float32_t test_vfmss_laneq_f32(float32_t a, float32_t b, float32x4_t v) {
return vfmss_laneq_f32(a, b, v, 3);
}
-// CHECK-LABEL: define double @test_vfmsd_laneq_f64(double %a, double %b, <2 x double> %v) #0 {
+// CHECK-LABEL: @test_vfmsd_laneq_f64(
// CHECK: [[SUB:%.*]] = fsub double -0.000000e+00, %b
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %v to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
@@ -493,991 +493,823 @@ float64_t test_vfmsd_laneq_f64(float64_t a, float64_t b, float64x2_t v) {
return vfmsd_laneq_f64(a, b, v, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlal_lane_s16(<4 x i32> %a, <4 x i16> %b, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmlal_lane_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> %b, <4 x i16> [[SHUFFLE]]) #2
// CHECK: [[ADD:%.*]] = add <4 x i32> %a, [[VMULL2_I]]
// CHECK: ret <4 x i32> [[ADD]]
int32x4_t test_vmlal_lane_s16(int32x4_t a, int16x4_t b, int16x4_t v) {
return vmlal_lane_s16(a, b, v, 3);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlal_lane_s32(<2 x i64> %a, <2 x i32> %b, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmlal_lane_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> <i32 1, i32 1>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> %b, <2 x i32> [[SHUFFLE]]) #2
// CHECK: [[ADD:%.*]] = add <2 x i64> %a, [[VMULL2_I]]
// CHECK: ret <2 x i64> [[ADD]]
int64x2_t test_vmlal_lane_s32(int64x2_t a, int32x2_t b, int32x2_t v) {
return vmlal_lane_s32(a, b, v, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlal_laneq_s16(<4 x i32> %a, <4 x i16> %b, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmlal_laneq_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> <i32 7, i32 7, i32 7, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> %b, <4 x i16> [[SHUFFLE]]) #2
// CHECK: [[ADD:%.*]] = add <4 x i32> %a, [[VMULL2_I]]
// CHECK: ret <4 x i32> [[ADD]]
int32x4_t test_vmlal_laneq_s16(int32x4_t a, int16x4_t b, int16x8_t v) {
return vmlal_laneq_s16(a, b, v, 7);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlal_laneq_s32(<2 x i64> %a, <2 x i32> %b, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmlal_laneq_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> <i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> %b, <2 x i32> [[SHUFFLE]]) #2
// CHECK: [[ADD:%.*]] = add <2 x i64> %a, [[VMULL2_I]]
// CHECK: ret <2 x i64> [[ADD]]
int64x2_t test_vmlal_laneq_s32(int64x2_t a, int32x2_t b, int32x4_t v) {
return vmlal_laneq_s32(a, b, v, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlal_high_lane_s16(<4 x i32> %a, <8 x i16> %b, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmlal_high_lane_s16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[SHUFFLE_I]], <4 x i16> [[SHUFFLE]]) #2
// CHECK: [[ADD:%.*]] = add <4 x i32> %a, [[VMULL2_I]]
// CHECK: ret <4 x i32> [[ADD]]
int32x4_t test_vmlal_high_lane_s16(int32x4_t a, int16x8_t b, int16x4_t v) {
return vmlal_high_lane_s16(a, b, v, 3);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlal_high_lane_s32(<2 x i64> %a, <4 x i32> %b, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmlal_high_lane_s32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> <i32 1, i32 1>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[SHUFFLE_I]], <2 x i32> [[SHUFFLE]]) #2
// CHECK: [[ADD:%.*]] = add <2 x i64> %a, [[VMULL2_I]]
// CHECK: ret <2 x i64> [[ADD]]
int64x2_t test_vmlal_high_lane_s32(int64x2_t a, int32x4_t b, int32x2_t v) {
return vmlal_high_lane_s32(a, b, v, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlal_high_laneq_s16(<4 x i32> %a, <8 x i16> %b, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmlal_high_laneq_s16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> <i32 7, i32 7, i32 7, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[SHUFFLE_I]], <4 x i16> [[SHUFFLE]]) #2
// CHECK: [[ADD:%.*]] = add <4 x i32> %a, [[VMULL2_I]]
// CHECK: ret <4 x i32> [[ADD]]
int32x4_t test_vmlal_high_laneq_s16(int32x4_t a, int16x8_t b, int16x8_t v) {
return vmlal_high_laneq_s16(a, b, v, 7);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlal_high_laneq_s32(<2 x i64> %a, <4 x i32> %b, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmlal_high_laneq_s32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> <i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[SHUFFLE_I]], <2 x i32> [[SHUFFLE]]) #2
// CHECK: [[ADD:%.*]] = add <2 x i64> %a, [[VMULL2_I]]
// CHECK: ret <2 x i64> [[ADD]]
int64x2_t test_vmlal_high_laneq_s32(int64x2_t a, int32x4_t b, int32x4_t v) {
return vmlal_high_laneq_s32(a, b, v, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlsl_lane_s16(<4 x i32> %a, <4 x i16> %b, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmlsl_lane_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> %b, <4 x i16> [[SHUFFLE]]) #2
// CHECK: [[SUB:%.*]] = sub <4 x i32> %a, [[VMULL2_I]]
// CHECK: ret <4 x i32> [[SUB]]
int32x4_t test_vmlsl_lane_s16(int32x4_t a, int16x4_t b, int16x4_t v) {
return vmlsl_lane_s16(a, b, v, 3);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlsl_lane_s32(<2 x i64> %a, <2 x i32> %b, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmlsl_lane_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> <i32 1, i32 1>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> %b, <2 x i32> [[SHUFFLE]]) #2
// CHECK: [[SUB:%.*]] = sub <2 x i64> %a, [[VMULL2_I]]
// CHECK: ret <2 x i64> [[SUB]]
int64x2_t test_vmlsl_lane_s32(int64x2_t a, int32x2_t b, int32x2_t v) {
return vmlsl_lane_s32(a, b, v, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlsl_laneq_s16(<4 x i32> %a, <4 x i16> %b, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmlsl_laneq_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> <i32 7, i32 7, i32 7, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> %b, <4 x i16> [[SHUFFLE]]) #2
// CHECK: [[SUB:%.*]] = sub <4 x i32> %a, [[VMULL2_I]]
// CHECK: ret <4 x i32> [[SUB]]
int32x4_t test_vmlsl_laneq_s16(int32x4_t a, int16x4_t b, int16x8_t v) {
return vmlsl_laneq_s16(a, b, v, 7);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlsl_laneq_s32(<2 x i64> %a, <2 x i32> %b, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmlsl_laneq_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> <i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> %b, <2 x i32> [[SHUFFLE]]) #2
// CHECK: [[SUB:%.*]] = sub <2 x i64> %a, [[VMULL2_I]]
// CHECK: ret <2 x i64> [[SUB]]
int64x2_t test_vmlsl_laneq_s32(int64x2_t a, int32x2_t b, int32x4_t v) {
return vmlsl_laneq_s32(a, b, v, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlsl_high_lane_s16(<4 x i32> %a, <8 x i16> %b, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmlsl_high_lane_s16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[SHUFFLE_I]], <4 x i16> [[SHUFFLE]]) #2
// CHECK: [[SUB:%.*]] = sub <4 x i32> %a, [[VMULL2_I]]
// CHECK: ret <4 x i32> [[SUB]]
int32x4_t test_vmlsl_high_lane_s16(int32x4_t a, int16x8_t b, int16x4_t v) {
return vmlsl_high_lane_s16(a, b, v, 3);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlsl_high_lane_s32(<2 x i64> %a, <4 x i32> %b, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmlsl_high_lane_s32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> <i32 1, i32 1>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[SHUFFLE_I]], <2 x i32> [[SHUFFLE]]) #2
// CHECK: [[SUB:%.*]] = sub <2 x i64> %a, [[VMULL2_I]]
// CHECK: ret <2 x i64> [[SUB]]
int64x2_t test_vmlsl_high_lane_s32(int64x2_t a, int32x4_t b, int32x2_t v) {
return vmlsl_high_lane_s32(a, b, v, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlsl_high_laneq_s16(<4 x i32> %a, <8 x i16> %b, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmlsl_high_laneq_s16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> <i32 7, i32 7, i32 7, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[SHUFFLE_I]], <4 x i16> [[SHUFFLE]]) #2
// CHECK: [[SUB:%.*]] = sub <4 x i32> %a, [[VMULL2_I]]
// CHECK: ret <4 x i32> [[SUB]]
int32x4_t test_vmlsl_high_laneq_s16(int32x4_t a, int16x8_t b, int16x8_t v) {
return vmlsl_high_laneq_s16(a, b, v, 7);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlsl_high_laneq_s32(<2 x i64> %a, <4 x i32> %b, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmlsl_high_laneq_s32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> <i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[SHUFFLE_I]], <2 x i32> [[SHUFFLE]]) #2
// CHECK: [[SUB:%.*]] = sub <2 x i64> %a, [[VMULL2_I]]
// CHECK: ret <2 x i64> [[SUB]]
int64x2_t test_vmlsl_high_laneq_s32(int64x2_t a, int32x4_t b, int32x4_t v) {
return vmlsl_high_laneq_s32(a, b, v, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlal_lane_u16(<4 x i32> %a, <4 x i16> %b, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmlal_lane_u16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> %b, <4 x i16> [[SHUFFLE]]) #2
// CHECK: [[ADD:%.*]] = add <4 x i32> %a, [[VMULL2_I]]
// CHECK: ret <4 x i32> [[ADD]]
int32x4_t test_vmlal_lane_u16(int32x4_t a, int16x4_t b, int16x4_t v) {
return vmlal_lane_u16(a, b, v, 3);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlal_lane_u32(<2 x i64> %a, <2 x i32> %b, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmlal_lane_u32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> <i32 1, i32 1>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> %b, <2 x i32> [[SHUFFLE]]) #2
// CHECK: [[ADD:%.*]] = add <2 x i64> %a, [[VMULL2_I]]
// CHECK: ret <2 x i64> [[ADD]]
int64x2_t test_vmlal_lane_u32(int64x2_t a, int32x2_t b, int32x2_t v) {
return vmlal_lane_u32(a, b, v, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlal_laneq_u16(<4 x i32> %a, <4 x i16> %b, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmlal_laneq_u16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> <i32 7, i32 7, i32 7, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> %b, <4 x i16> [[SHUFFLE]]) #2
// CHECK: [[ADD:%.*]] = add <4 x i32> %a, [[VMULL2_I]]
// CHECK: ret <4 x i32> [[ADD]]
int32x4_t test_vmlal_laneq_u16(int32x4_t a, int16x4_t b, int16x8_t v) {
return vmlal_laneq_u16(a, b, v, 7);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlal_laneq_u32(<2 x i64> %a, <2 x i32> %b, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmlal_laneq_u32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> <i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> %b, <2 x i32> [[SHUFFLE]]) #2
// CHECK: [[ADD:%.*]] = add <2 x i64> %a, [[VMULL2_I]]
// CHECK: ret <2 x i64> [[ADD]]
int64x2_t test_vmlal_laneq_u32(int64x2_t a, int32x2_t b, int32x4_t v) {
return vmlal_laneq_u32(a, b, v, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlal_high_lane_u16(<4 x i32> %a, <8 x i16> %b, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmlal_high_lane_u16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[SHUFFLE_I]], <4 x i16> [[SHUFFLE]]) #2
// CHECK: [[ADD:%.*]] = add <4 x i32> %a, [[VMULL2_I]]
// CHECK: ret <4 x i32> [[ADD]]
int32x4_t test_vmlal_high_lane_u16(int32x4_t a, int16x8_t b, int16x4_t v) {
return vmlal_high_lane_u16(a, b, v, 3);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlal_high_lane_u32(<2 x i64> %a, <4 x i32> %b, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmlal_high_lane_u32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> <i32 1, i32 1>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[SHUFFLE_I]], <2 x i32> [[SHUFFLE]]) #2
// CHECK: [[ADD:%.*]] = add <2 x i64> %a, [[VMULL2_I]]
// CHECK: ret <2 x i64> [[ADD]]
int64x2_t test_vmlal_high_lane_u32(int64x2_t a, int32x4_t b, int32x2_t v) {
return vmlal_high_lane_u32(a, b, v, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlal_high_laneq_u16(<4 x i32> %a, <8 x i16> %b, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmlal_high_laneq_u16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> <i32 7, i32 7, i32 7, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[SHUFFLE_I]], <4 x i16> [[SHUFFLE]]) #2
// CHECK: [[ADD:%.*]] = add <4 x i32> %a, [[VMULL2_I]]
// CHECK: ret <4 x i32> [[ADD]]
int32x4_t test_vmlal_high_laneq_u16(int32x4_t a, int16x8_t b, int16x8_t v) {
return vmlal_high_laneq_u16(a, b, v, 7);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlal_high_laneq_u32(<2 x i64> %a, <4 x i32> %b, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmlal_high_laneq_u32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> <i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[SHUFFLE_I]], <2 x i32> [[SHUFFLE]]) #2
// CHECK: [[ADD:%.*]] = add <2 x i64> %a, [[VMULL2_I]]
// CHECK: ret <2 x i64> [[ADD]]
int64x2_t test_vmlal_high_laneq_u32(int64x2_t a, int32x4_t b, int32x4_t v) {
return vmlal_high_laneq_u32(a, b, v, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlsl_lane_u16(<4 x i32> %a, <4 x i16> %b, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmlsl_lane_u16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> %b, <4 x i16> [[SHUFFLE]]) #2
// CHECK: [[SUB:%.*]] = sub <4 x i32> %a, [[VMULL2_I]]
// CHECK: ret <4 x i32> [[SUB]]
int32x4_t test_vmlsl_lane_u16(int32x4_t a, int16x4_t b, int16x4_t v) {
return vmlsl_lane_u16(a, b, v, 3);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlsl_lane_u32(<2 x i64> %a, <2 x i32> %b, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmlsl_lane_u32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> <i32 1, i32 1>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> %b, <2 x i32> [[SHUFFLE]]) #2
// CHECK: [[SUB:%.*]] = sub <2 x i64> %a, [[VMULL2_I]]
// CHECK: ret <2 x i64> [[SUB]]
int64x2_t test_vmlsl_lane_u32(int64x2_t a, int32x2_t b, int32x2_t v) {
return vmlsl_lane_u32(a, b, v, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlsl_laneq_u16(<4 x i32> %a, <4 x i16> %b, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmlsl_laneq_u16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> <i32 7, i32 7, i32 7, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> %b, <4 x i16> [[SHUFFLE]]) #2
// CHECK: [[SUB:%.*]] = sub <4 x i32> %a, [[VMULL2_I]]
// CHECK: ret <4 x i32> [[SUB]]
int32x4_t test_vmlsl_laneq_u16(int32x4_t a, int16x4_t b, int16x8_t v) {
return vmlsl_laneq_u16(a, b, v, 7);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlsl_laneq_u32(<2 x i64> %a, <2 x i32> %b, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmlsl_laneq_u32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> <i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> %b, <2 x i32> [[SHUFFLE]]) #2
// CHECK: [[SUB:%.*]] = sub <2 x i64> %a, [[VMULL2_I]]
// CHECK: ret <2 x i64> [[SUB]]
int64x2_t test_vmlsl_laneq_u32(int64x2_t a, int32x2_t b, int32x4_t v) {
return vmlsl_laneq_u32(a, b, v, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlsl_high_lane_u16(<4 x i32> %a, <8 x i16> %b, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmlsl_high_lane_u16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[SHUFFLE_I]], <4 x i16> [[SHUFFLE]]) #2
// CHECK: [[SUB:%.*]] = sub <4 x i32> %a, [[VMULL2_I]]
// CHECK: ret <4 x i32> [[SUB]]
int32x4_t test_vmlsl_high_lane_u16(int32x4_t a, int16x8_t b, int16x4_t v) {
return vmlsl_high_lane_u16(a, b, v, 3);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlsl_high_lane_u32(<2 x i64> %a, <4 x i32> %b, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmlsl_high_lane_u32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> <i32 1, i32 1>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[SHUFFLE_I]], <2 x i32> [[SHUFFLE]]) #2
// CHECK: [[SUB:%.*]] = sub <2 x i64> %a, [[VMULL2_I]]
// CHECK: ret <2 x i64> [[SUB]]
int64x2_t test_vmlsl_high_lane_u32(int64x2_t a, int32x4_t b, int32x2_t v) {
return vmlsl_high_lane_u32(a, b, v, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlsl_high_laneq_u16(<4 x i32> %a, <8 x i16> %b, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmlsl_high_laneq_u16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> <i32 7, i32 7, i32 7, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[SHUFFLE_I]], <4 x i16> [[SHUFFLE]]) #2
// CHECK: [[SUB:%.*]] = sub <4 x i32> %a, [[VMULL2_I]]
// CHECK: ret <4 x i32> [[SUB]]
int32x4_t test_vmlsl_high_laneq_u16(int32x4_t a, int16x8_t b, int16x8_t v) {
return vmlsl_high_laneq_u16(a, b, v, 7);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlsl_high_laneq_u32(<2 x i64> %a, <4 x i32> %b, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmlsl_high_laneq_u32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> <i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[SHUFFLE_I]], <2 x i32> [[SHUFFLE]]) #2
// CHECK: [[SUB:%.*]] = sub <2 x i64> %a, [[VMULL2_I]]
// CHECK: ret <2 x i64> [[SUB]]
int64x2_t test_vmlsl_high_laneq_u32(int64x2_t a, int32x4_t b, int32x4_t v) {
return vmlsl_high_laneq_u32(a, b, v, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vmull_lane_s16(<4 x i16> %a, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmull_lane_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> %a, <4 x i16> [[SHUFFLE]]) #2
// CHECK: ret <4 x i32> [[VMULL2_I]]
int32x4_t test_vmull_lane_s16(int16x4_t a, int16x4_t v) {
return vmull_lane_s16(a, v, 3);
}
-// CHECK-LABEL: define <2 x i64> @test_vmull_lane_s32(<2 x i32> %a, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmull_lane_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> <i32 1, i32 1>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> %a, <2 x i32> [[SHUFFLE]]) #2
// CHECK: ret <2 x i64> [[VMULL2_I]]
int64x2_t test_vmull_lane_s32(int32x2_t a, int32x2_t v) {
return vmull_lane_s32(a, v, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vmull_lane_u16(<4 x i16> %a, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmull_lane_u16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> %a, <4 x i16> [[SHUFFLE]]) #2
// CHECK: ret <4 x i32> [[VMULL2_I]]
uint32x4_t test_vmull_lane_u16(uint16x4_t a, uint16x4_t v) {
return vmull_lane_u16(a, v, 3);
}
-// CHECK-LABEL: define <2 x i64> @test_vmull_lane_u32(<2 x i32> %a, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmull_lane_u32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> <i32 1, i32 1>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> %a, <2 x i32> [[SHUFFLE]]) #2
// CHECK: ret <2 x i64> [[VMULL2_I]]
uint64x2_t test_vmull_lane_u32(uint32x2_t a, uint32x2_t v) {
return vmull_lane_u32(a, v, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vmull_high_lane_s16(<8 x i16> %a, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmull_high_lane_s16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %a, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[SHUFFLE_I]], <4 x i16> [[SHUFFLE]]) #2
// CHECK: ret <4 x i32> [[VMULL2_I]]
int32x4_t test_vmull_high_lane_s16(int16x8_t a, int16x4_t v) {
return vmull_high_lane_s16(a, v, 3);
}
-// CHECK-LABEL: define <2 x i64> @test_vmull_high_lane_s32(<4 x i32> %a, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmull_high_lane_s32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %a, <2 x i32> <i32 2, i32 3>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> <i32 1, i32 1>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[SHUFFLE_I]], <2 x i32> [[SHUFFLE]]) #2
// CHECK: ret <2 x i64> [[VMULL2_I]]
int64x2_t test_vmull_high_lane_s32(int32x4_t a, int32x2_t v) {
return vmull_high_lane_s32(a, v, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vmull_high_lane_u16(<8 x i16> %a, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmull_high_lane_u16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %a, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[SHUFFLE_I]], <4 x i16> [[SHUFFLE]]) #2
// CHECK: ret <4 x i32> [[VMULL2_I]]
uint32x4_t test_vmull_high_lane_u16(uint16x8_t a, uint16x4_t v) {
return vmull_high_lane_u16(a, v, 3);
}
-// CHECK-LABEL: define <2 x i64> @test_vmull_high_lane_u32(<4 x i32> %a, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmull_high_lane_u32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %a, <2 x i32> <i32 2, i32 3>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> <i32 1, i32 1>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[SHUFFLE_I]], <2 x i32> [[SHUFFLE]]) #2
// CHECK: ret <2 x i64> [[VMULL2_I]]
uint64x2_t test_vmull_high_lane_u32(uint32x4_t a, uint32x2_t v) {
return vmull_high_lane_u32(a, v, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vmull_laneq_s16(<4 x i16> %a, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmull_laneq_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> <i32 7, i32 7, i32 7, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> %a, <4 x i16> [[SHUFFLE]]) #2
// CHECK: ret <4 x i32> [[VMULL2_I]]
int32x4_t test_vmull_laneq_s16(int16x4_t a, int16x8_t v) {
return vmull_laneq_s16(a, v, 7);
}
-// CHECK-LABEL: define <2 x i64> @test_vmull_laneq_s32(<2 x i32> %a, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmull_laneq_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> <i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> %a, <2 x i32> [[SHUFFLE]]) #2
// CHECK: ret <2 x i64> [[VMULL2_I]]
int64x2_t test_vmull_laneq_s32(int32x2_t a, int32x4_t v) {
return vmull_laneq_s32(a, v, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vmull_laneq_u16(<4 x i16> %a, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmull_laneq_u16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> <i32 7, i32 7, i32 7, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> %a, <4 x i16> [[SHUFFLE]]) #2
// CHECK: ret <4 x i32> [[VMULL2_I]]
uint32x4_t test_vmull_laneq_u16(uint16x4_t a, uint16x8_t v) {
return vmull_laneq_u16(a, v, 7);
}
-// CHECK-LABEL: define <2 x i64> @test_vmull_laneq_u32(<2 x i32> %a, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmull_laneq_u32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> <i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> %a, <2 x i32> [[SHUFFLE]]) #2
// CHECK: ret <2 x i64> [[VMULL2_I]]
uint64x2_t test_vmull_laneq_u32(uint32x2_t a, uint32x4_t v) {
return vmull_laneq_u32(a, v, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vmull_high_laneq_s16(<8 x i16> %a, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmull_high_laneq_s16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %a, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> <i32 7, i32 7, i32 7, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[SHUFFLE_I]], <4 x i16> [[SHUFFLE]]) #2
// CHECK: ret <4 x i32> [[VMULL2_I]]
int32x4_t test_vmull_high_laneq_s16(int16x8_t a, int16x8_t v) {
return vmull_high_laneq_s16(a, v, 7);
}
-// CHECK-LABEL: define <2 x i64> @test_vmull_high_laneq_s32(<4 x i32> %a, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmull_high_laneq_s32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %a, <2 x i32> <i32 2, i32 3>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> <i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[SHUFFLE_I]], <2 x i32> [[SHUFFLE]]) #2
// CHECK: ret <2 x i64> [[VMULL2_I]]
int64x2_t test_vmull_high_laneq_s32(int32x4_t a, int32x4_t v) {
return vmull_high_laneq_s32(a, v, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vmull_high_laneq_u16(<8 x i16> %a, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmull_high_laneq_u16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %a, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> <i32 7, i32 7, i32 7, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[SHUFFLE_I]], <4 x i16> [[SHUFFLE]]) #2
// CHECK: ret <4 x i32> [[VMULL2_I]]
uint32x4_t test_vmull_high_laneq_u16(uint16x8_t a, uint16x8_t v) {
return vmull_high_laneq_u16(a, v, 7);
}
-// CHECK-LABEL: define <2 x i64> @test_vmull_high_laneq_u32(<4 x i32> %a, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmull_high_laneq_u32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %a, <2 x i32> <i32 2, i32 3>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> <i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[SHUFFLE_I]], <2 x i32> [[SHUFFLE]]) #2
// CHECK: ret <2 x i64> [[VMULL2_I]]
uint64x2_t test_vmull_high_laneq_u32(uint32x4_t a, uint32x4_t v) {
return vmull_high_laneq_u32(a, v, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vqdmlal_lane_s16(<4 x i32> %a, <4 x i16> %b, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vqdmlal_lane_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMLAL1_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VQDMLAL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[VQDMLAL_I]], <4 x i16> [[VQDMLAL1_I]]) #2
-// CHECK: [[VQDMLAL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQDMLAL_V3_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqadd.v4i32(<4 x i32> [[VQDMLAL_V_I]], <4 x i32> [[VQDMLAL2_I]]) #2
+// CHECK: [[VQDMLAL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> %b, <4 x i16> [[SHUFFLE]]) #2
+// CHECK: [[VQDMLAL_V3_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqadd.v4i32(<4 x i32> %a, <4 x i32> [[VQDMLAL2_I]]) #2
// CHECK: ret <4 x i32> [[VQDMLAL_V3_I]]
int32x4_t test_vqdmlal_lane_s16(int32x4_t a, int16x4_t b, int16x4_t v) {
return vqdmlal_lane_s16(a, b, v, 3);
}
-// CHECK-LABEL: define <2 x i64> @test_vqdmlal_lane_s32(<2 x i64> %a, <2 x i32> %b, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vqdmlal_lane_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> <i32 1, i32 1>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMLAL1_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VQDMLAL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[VQDMLAL_I]], <2 x i32> [[VQDMLAL1_I]]) #2
-// CHECK: [[VQDMLAL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQDMLAL_V3_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqadd.v2i64(<2 x i64> [[VQDMLAL_V_I]], <2 x i64> [[VQDMLAL2_I]]) #2
+// CHECK: [[VQDMLAL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> %b, <2 x i32> [[SHUFFLE]]) #2
+// CHECK: [[VQDMLAL_V3_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqadd.v2i64(<2 x i64> %a, <2 x i64> [[VQDMLAL2_I]]) #2
// CHECK: ret <2 x i64> [[VQDMLAL_V3_I]]
int64x2_t test_vqdmlal_lane_s32(int64x2_t a, int32x2_t b, int32x2_t v) {
return vqdmlal_lane_s32(a, b, v, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vqdmlal_high_lane_s16(<4 x i32> %a, <8 x i16> %b, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vqdmlal_high_lane_s16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMLAL1_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VQDMLAL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[VQDMLAL_I]], <4 x i16> [[VQDMLAL1_I]]) #2
-// CHECK: [[VQDMLAL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQDMLAL_V3_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqadd.v4i32(<4 x i32> [[VQDMLAL_V_I]], <4 x i32> [[VQDMLAL2_I]]) #2
+// CHECK: [[VQDMLAL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[SHUFFLE_I]], <4 x i16> [[SHUFFLE]]) #2
+// CHECK: [[VQDMLAL_V3_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqadd.v4i32(<4 x i32> %a, <4 x i32> [[VQDMLAL2_I]]) #2
// CHECK: ret <4 x i32> [[VQDMLAL_V3_I]]
int32x4_t test_vqdmlal_high_lane_s16(int32x4_t a, int16x8_t b, int16x4_t v) {
return vqdmlal_high_lane_s16(a, b, v, 3);
}
-// CHECK-LABEL: define <2 x i64> @test_vqdmlal_high_lane_s32(<2 x i64> %a, <4 x i32> %b, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vqdmlal_high_lane_s32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> <i32 1, i32 1>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMLAL1_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VQDMLAL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[VQDMLAL_I]], <2 x i32> [[VQDMLAL1_I]]) #2
-// CHECK: [[VQDMLAL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQDMLAL_V3_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqadd.v2i64(<2 x i64> [[VQDMLAL_V_I]], <2 x i64> [[VQDMLAL2_I]]) #2
+// CHECK: [[VQDMLAL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[SHUFFLE_I]], <2 x i32> [[SHUFFLE]]) #2
+// CHECK: [[VQDMLAL_V3_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqadd.v2i64(<2 x i64> %a, <2 x i64> [[VQDMLAL2_I]]) #2
// CHECK: ret <2 x i64> [[VQDMLAL_V3_I]]
int64x2_t test_vqdmlal_high_lane_s32(int64x2_t a, int32x4_t b, int32x2_t v) {
return vqdmlal_high_lane_s32(a, b, v, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vqdmlsl_lane_s16(<4 x i32> %a, <4 x i16> %b, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vqdmlsl_lane_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMLAL1_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VQDMLAL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[VQDMLAL_I]], <4 x i16> [[VQDMLAL1_I]]) #2
-// CHECK: [[VQDMLSL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQDMLSL_V3_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqsub.v4i32(<4 x i32> [[VQDMLSL_V_I]], <4 x i32> [[VQDMLAL2_I]]) #2
+// CHECK: [[VQDMLAL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> %b, <4 x i16> [[SHUFFLE]]) #2
+// CHECK: [[VQDMLSL_V3_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqsub.v4i32(<4 x i32> %a, <4 x i32> [[VQDMLAL2_I]]) #2
// CHECK: ret <4 x i32> [[VQDMLSL_V3_I]]
int32x4_t test_vqdmlsl_lane_s16(int32x4_t a, int16x4_t b, int16x4_t v) {
return vqdmlsl_lane_s16(a, b, v, 3);
}
-// CHECK-LABEL: define <2 x i64> @test_vqdmlsl_lane_s32(<2 x i64> %a, <2 x i32> %b, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vqdmlsl_lane_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> <i32 1, i32 1>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMLAL1_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VQDMLAL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[VQDMLAL_I]], <2 x i32> [[VQDMLAL1_I]]) #2
-// CHECK: [[VQDMLSL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQDMLSL_V3_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqsub.v2i64(<2 x i64> [[VQDMLSL_V_I]], <2 x i64> [[VQDMLAL2_I]]) #2
+// CHECK: [[VQDMLAL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> %b, <2 x i32> [[SHUFFLE]]) #2
+// CHECK: [[VQDMLSL_V3_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqsub.v2i64(<2 x i64> %a, <2 x i64> [[VQDMLAL2_I]]) #2
// CHECK: ret <2 x i64> [[VQDMLSL_V3_I]]
int64x2_t test_vqdmlsl_lane_s32(int64x2_t a, int32x2_t b, int32x2_t v) {
return vqdmlsl_lane_s32(a, b, v, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vqdmlsl_high_lane_s16(<4 x i32> %a, <8 x i16> %b, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vqdmlsl_high_lane_s16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMLAL1_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VQDMLAL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[VQDMLAL_I]], <4 x i16> [[VQDMLAL1_I]]) #2
-// CHECK: [[VQDMLSL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQDMLSL_V3_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqsub.v4i32(<4 x i32> [[VQDMLSL_V_I]], <4 x i32> [[VQDMLAL2_I]]) #2
+// CHECK: [[VQDMLAL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[SHUFFLE_I]], <4 x i16> [[SHUFFLE]]) #2
+// CHECK: [[VQDMLSL_V3_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqsub.v4i32(<4 x i32> %a, <4 x i32> [[VQDMLAL2_I]]) #2
// CHECK: ret <4 x i32> [[VQDMLSL_V3_I]]
int32x4_t test_vqdmlsl_high_lane_s16(int32x4_t a, int16x8_t b, int16x4_t v) {
return vqdmlsl_high_lane_s16(a, b, v, 3);
}
-// CHECK-LABEL: define <2 x i64> @test_vqdmlsl_high_lane_s32(<2 x i64> %a, <4 x i32> %b, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vqdmlsl_high_lane_s32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> <i32 1, i32 1>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMLAL1_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VQDMLAL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[VQDMLAL_I]], <2 x i32> [[VQDMLAL1_I]]) #2
-// CHECK: [[VQDMLSL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQDMLSL_V3_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqsub.v2i64(<2 x i64> [[VQDMLSL_V_I]], <2 x i64> [[VQDMLAL2_I]]) #2
+// CHECK: [[VQDMLAL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[SHUFFLE_I]], <2 x i32> [[SHUFFLE]]) #2
+// CHECK: [[VQDMLSL_V3_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqsub.v2i64(<2 x i64> %a, <2 x i64> [[VQDMLAL2_I]]) #2
// CHECK: ret <2 x i64> [[VQDMLSL_V3_I]]
int64x2_t test_vqdmlsl_high_lane_s32(int64x2_t a, int32x4_t b, int32x2_t v) {
return vqdmlsl_high_lane_s32(a, b, v, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vqdmull_lane_s16(<4 x i16> %a, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vqdmull_lane_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMULL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQDMULL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMULL_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[VQDMULL_V_I]], <4 x i16> [[VQDMULL_V1_I]]) #2
+// CHECK: [[VQDMULL_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> %a, <4 x i16> [[SHUFFLE]]) #2
// CHECK: [[VQDMULL_V3_I:%.*]] = bitcast <4 x i32> [[VQDMULL_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQDMULL_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VQDMULL_V2_I]]
int32x4_t test_vqdmull_lane_s16(int16x4_t a, int16x4_t v) {
return vqdmull_lane_s16(a, v, 3);
}
-// CHECK-LABEL: define <2 x i64> @test_vqdmull_lane_s32(<2 x i32> %a, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vqdmull_lane_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> <i32 1, i32 1>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMULL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQDMULL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMULL_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[VQDMULL_V_I]], <2 x i32> [[VQDMULL_V1_I]]) #2
+// CHECK: [[VQDMULL_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> %a, <2 x i32> [[SHUFFLE]]) #2
// CHECK: [[VQDMULL_V3_I:%.*]] = bitcast <2 x i64> [[VQDMULL_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQDMULL_V3_I]] to <2 x i64>
-// CHECK: ret <2 x i64> [[TMP2]]
+// CHECK: ret <2 x i64> [[VQDMULL_V2_I]]
int64x2_t test_vqdmull_lane_s32(int32x2_t a, int32x2_t v) {
return vqdmull_lane_s32(a, v, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vqdmull_laneq_s16(<4 x i16> %a, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vqdmull_laneq_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMULL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQDMULL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMULL_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[VQDMULL_V_I]], <4 x i16> [[VQDMULL_V1_I]]) #2
+// CHECK: [[VQDMULL_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> %a, <4 x i16> [[SHUFFLE]]) #2
// CHECK: [[VQDMULL_V3_I:%.*]] = bitcast <4 x i32> [[VQDMULL_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQDMULL_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VQDMULL_V2_I]]
int32x4_t test_vqdmull_laneq_s16(int16x4_t a, int16x8_t v) {
return vqdmull_laneq_s16(a, v, 3);
}
-// CHECK-LABEL: define <2 x i64> @test_vqdmull_laneq_s32(<2 x i32> %a, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vqdmull_laneq_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> <i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMULL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQDMULL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMULL_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[VQDMULL_V_I]], <2 x i32> [[VQDMULL_V1_I]]) #2
+// CHECK: [[VQDMULL_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> %a, <2 x i32> [[SHUFFLE]]) #2
// CHECK: [[VQDMULL_V3_I:%.*]] = bitcast <2 x i64> [[VQDMULL_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQDMULL_V3_I]] to <2 x i64>
-// CHECK: ret <2 x i64> [[TMP2]]
+// CHECK: ret <2 x i64> [[VQDMULL_V2_I]]
int64x2_t test_vqdmull_laneq_s32(int32x2_t a, int32x4_t v) {
return vqdmull_laneq_s32(a, v, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vqdmull_high_lane_s16(<8 x i16> %a, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vqdmull_high_lane_s16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %a, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMULL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQDMULL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMULL_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[VQDMULL_V_I]], <4 x i16> [[VQDMULL_V1_I]]) #2
+// CHECK: [[VQDMULL_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[SHUFFLE_I]], <4 x i16> [[SHUFFLE]]) #2
// CHECK: [[VQDMULL_V3_I:%.*]] = bitcast <4 x i32> [[VQDMULL_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQDMULL_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VQDMULL_V2_I]]
int32x4_t test_vqdmull_high_lane_s16(int16x8_t a, int16x4_t v) {
return vqdmull_high_lane_s16(a, v, 3);
}
-// CHECK-LABEL: define <2 x i64> @test_vqdmull_high_lane_s32(<4 x i32> %a, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vqdmull_high_lane_s32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %a, <2 x i32> <i32 2, i32 3>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> <i32 1, i32 1>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMULL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQDMULL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMULL_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[VQDMULL_V_I]], <2 x i32> [[VQDMULL_V1_I]]) #2
+// CHECK: [[VQDMULL_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[SHUFFLE_I]], <2 x i32> [[SHUFFLE]]) #2
// CHECK: [[VQDMULL_V3_I:%.*]] = bitcast <2 x i64> [[VQDMULL_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQDMULL_V3_I]] to <2 x i64>
-// CHECK: ret <2 x i64> [[TMP2]]
+// CHECK: ret <2 x i64> [[VQDMULL_V2_I]]
int64x2_t test_vqdmull_high_lane_s32(int32x4_t a, int32x2_t v) {
return vqdmull_high_lane_s32(a, v, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vqdmull_high_laneq_s16(<8 x i16> %a, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vqdmull_high_laneq_s16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %a, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> <i32 7, i32 7, i32 7, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMULL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQDMULL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMULL_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[VQDMULL_V_I]], <4 x i16> [[VQDMULL_V1_I]]) #2
+// CHECK: [[VQDMULL_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[SHUFFLE_I]], <4 x i16> [[SHUFFLE]]) #2
// CHECK: [[VQDMULL_V3_I:%.*]] = bitcast <4 x i32> [[VQDMULL_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQDMULL_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VQDMULL_V2_I]]
int32x4_t test_vqdmull_high_laneq_s16(int16x8_t a, int16x8_t v) {
return vqdmull_high_laneq_s16(a, v, 7);
}
-// CHECK-LABEL: define <2 x i64> @test_vqdmull_high_laneq_s32(<4 x i32> %a, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vqdmull_high_laneq_s32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %a, <2 x i32> <i32 2, i32 3>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> <i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMULL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQDMULL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMULL_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[VQDMULL_V_I]], <2 x i32> [[VQDMULL_V1_I]]) #2
+// CHECK: [[VQDMULL_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[SHUFFLE_I]], <2 x i32> [[SHUFFLE]]) #2
// CHECK: [[VQDMULL_V3_I:%.*]] = bitcast <2 x i64> [[VQDMULL_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQDMULL_V3_I]] to <2 x i64>
-// CHECK: ret <2 x i64> [[TMP2]]
+// CHECK: ret <2 x i64> [[VQDMULL_V2_I]]
int64x2_t test_vqdmull_high_laneq_s32(int32x4_t a, int32x4_t v) {
return vqdmull_high_laneq_s32(a, v, 3);
}
-// CHECK-LABEL: define <4 x i16> @test_vqdmulh_lane_s16(<4 x i16> %a, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vqdmulh_lane_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMULH_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQDMULH_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMULH_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqdmulh.v4i16(<4 x i16> [[VQDMULH_V_I]], <4 x i16> [[VQDMULH_V1_I]]) #2
+// CHECK: [[VQDMULH_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqdmulh.v4i16(<4 x i16> %a, <4 x i16> [[SHUFFLE]]) #2
// CHECK: [[VQDMULH_V3_I:%.*]] = bitcast <4 x i16> [[VQDMULH_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQDMULH_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VQDMULH_V2_I]]
int16x4_t test_vqdmulh_lane_s16(int16x4_t a, int16x4_t v) {
return vqdmulh_lane_s16(a, v, 3);
}
-// CHECK-LABEL: define <8 x i16> @test_vqdmulhq_lane_s16(<8 x i16> %a, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vqdmulhq_lane_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <8 x i32> <i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> [[SHUFFLE]] to <16 x i8>
-// CHECK: [[VQDMULHQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VQDMULHQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VQDMULHQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.sqdmulh.v8i16(<8 x i16> [[VQDMULHQ_V_I]], <8 x i16> [[VQDMULHQ_V1_I]]) #2
+// CHECK: [[VQDMULHQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.sqdmulh.v8i16(<8 x i16> %a, <8 x i16> [[SHUFFLE]]) #2
// CHECK: [[VQDMULHQ_V3_I:%.*]] = bitcast <8 x i16> [[VQDMULHQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQDMULHQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VQDMULHQ_V2_I]]
int16x8_t test_vqdmulhq_lane_s16(int16x8_t a, int16x4_t v) {
return vqdmulhq_lane_s16(a, v, 3);
}
-// CHECK-LABEL: define <2 x i32> @test_vqdmulh_lane_s32(<2 x i32> %a, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vqdmulh_lane_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> <i32 1, i32 1>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMULH_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQDMULH_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMULH_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqdmulh.v2i32(<2 x i32> [[VQDMULH_V_I]], <2 x i32> [[VQDMULH_V1_I]]) #2
+// CHECK: [[VQDMULH_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqdmulh.v2i32(<2 x i32> %a, <2 x i32> [[SHUFFLE]]) #2
// CHECK: [[VQDMULH_V3_I:%.*]] = bitcast <2 x i32> [[VQDMULH_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQDMULH_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VQDMULH_V2_I]]
int32x2_t test_vqdmulh_lane_s32(int32x2_t a, int32x2_t v) {
return vqdmulh_lane_s32(a, v, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vqdmulhq_lane_s32(<4 x i32> %a, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vqdmulhq_lane_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> [[SHUFFLE]] to <16 x i8>
-// CHECK: [[VQDMULHQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQDMULHQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VQDMULHQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmulh.v4i32(<4 x i32> [[VQDMULHQ_V_I]], <4 x i32> [[VQDMULHQ_V1_I]]) #2
+// CHECK: [[VQDMULHQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmulh.v4i32(<4 x i32> %a, <4 x i32> [[SHUFFLE]]) #2
// CHECK: [[VQDMULHQ_V3_I:%.*]] = bitcast <4 x i32> [[VQDMULHQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQDMULHQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VQDMULHQ_V2_I]]
int32x4_t test_vqdmulhq_lane_s32(int32x4_t a, int32x2_t v) {
return vqdmulhq_lane_s32(a, v, 1);
}
-// CHECK-LABEL: define <4 x i16> @test_vqrdmulh_lane_s16(<4 x i16> %a, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vqrdmulh_lane_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQRDMULH_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQRDMULH_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQRDMULH_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqrdmulh.v4i16(<4 x i16> [[VQRDMULH_V_I]], <4 x i16> [[VQRDMULH_V1_I]]) #2
+// CHECK: [[VQRDMULH_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqrdmulh.v4i16(<4 x i16> %a, <4 x i16> [[SHUFFLE]]) #2
// CHECK: [[VQRDMULH_V3_I:%.*]] = bitcast <4 x i16> [[VQRDMULH_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQRDMULH_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VQRDMULH_V2_I]]
int16x4_t test_vqrdmulh_lane_s16(int16x4_t a, int16x4_t v) {
return vqrdmulh_lane_s16(a, v, 3);
}
-// CHECK-LABEL: define <8 x i16> @test_vqrdmulhq_lane_s16(<8 x i16> %a, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vqrdmulhq_lane_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <8 x i32> <i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> [[SHUFFLE]] to <16 x i8>
-// CHECK: [[VQRDMULHQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VQRDMULHQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VQRDMULHQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.sqrdmulh.v8i16(<8 x i16> [[VQRDMULHQ_V_I]], <8 x i16> [[VQRDMULHQ_V1_I]]) #2
+// CHECK: [[VQRDMULHQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.sqrdmulh.v8i16(<8 x i16> %a, <8 x i16> [[SHUFFLE]]) #2
// CHECK: [[VQRDMULHQ_V3_I:%.*]] = bitcast <8 x i16> [[VQRDMULHQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQRDMULHQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VQRDMULHQ_V2_I]]
int16x8_t test_vqrdmulhq_lane_s16(int16x8_t a, int16x4_t v) {
return vqrdmulhq_lane_s16(a, v, 3);
}
-// CHECK-LABEL: define <2 x i32> @test_vqrdmulh_lane_s32(<2 x i32> %a, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vqrdmulh_lane_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> <i32 1, i32 1>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQRDMULH_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQRDMULH_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQRDMULH_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqrdmulh.v2i32(<2 x i32> [[VQRDMULH_V_I]], <2 x i32> [[VQRDMULH_V1_I]]) #2
+// CHECK: [[VQRDMULH_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqrdmulh.v2i32(<2 x i32> %a, <2 x i32> [[SHUFFLE]]) #2
// CHECK: [[VQRDMULH_V3_I:%.*]] = bitcast <2 x i32> [[VQRDMULH_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQRDMULH_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VQRDMULH_V2_I]]
int32x2_t test_vqrdmulh_lane_s32(int32x2_t a, int32x2_t v) {
return vqrdmulh_lane_s32(a, v, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vqrdmulhq_lane_s32(<4 x i32> %a, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vqrdmulhq_lane_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> [[SHUFFLE]] to <16 x i8>
-// CHECK: [[VQRDMULHQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQRDMULHQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VQRDMULHQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqrdmulh.v4i32(<4 x i32> [[VQRDMULHQ_V_I]], <4 x i32> [[VQRDMULHQ_V1_I]]) #2
+// CHECK: [[VQRDMULHQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqrdmulh.v4i32(<4 x i32> %a, <4 x i32> [[SHUFFLE]]) #2
// CHECK: [[VQRDMULHQ_V3_I:%.*]] = bitcast <4 x i32> [[VQRDMULHQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQRDMULHQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VQRDMULHQ_V2_I]]
int32x4_t test_vqrdmulhq_lane_s32(int32x4_t a, int32x2_t v) {
return vqrdmulhq_lane_s32(a, v, 1);
}
-// CHECK-LABEL: define <2 x float> @test_vmul_lane_f32(<2 x float> %a, <2 x float> %v) #0 {
+// CHECK-LABEL: @test_vmul_lane_f32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x float> %v, <2 x float> %v, <2 x i32> <i32 1, i32 1>
// CHECK: [[MUL:%.*]] = fmul <2 x float> %a, [[SHUFFLE]]
// CHECK: ret <2 x float> [[MUL]]
@@ -1485,8 +1317,7 @@ float32x2_t test_vmul_lane_f32(float32x2_t a, float32x2_t v) {
return vmul_lane_f32(a, v, 1);
}
-
-// CHECK-LABEL: define <1 x double> @test_vmul_lane_f64(<1 x double> %a, <1 x double> %v) #0 {
+// CHECK-LABEL: @test_vmul_lane_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x double> %v to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to double
@@ -1495,20 +1326,21 @@ float32x2_t test_vmul_lane_f32(float32x2_t a, float32x2_t v) {
// CHECK: [[TMP4:%.*]] = fmul double [[TMP2]], [[EXTRACT]]
// CHECK: [[TMP5:%.*]] = bitcast double [[TMP4]] to <1 x double>
// CHECK: ret <1 x double> [[TMP5]]
+
float64x1_t test_vmul_lane_f64(float64x1_t a, float64x1_t v) {
return vmul_lane_f64(a, v, 0);
}
-
-// CHECK-LABEL: define <4 x float> @test_vmulq_lane_f32(<4 x float> %a, <2 x float> %v) #0 {
+// CHECK-LABEL: @test_vmulq_lane_f32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x float> %v, <2 x float> %v, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
// CHECK: [[MUL:%.*]] = fmul <4 x float> %a, [[SHUFFLE]]
// CHECK: ret <4 x float> [[MUL]]
+
float32x4_t test_vmulq_lane_f32(float32x4_t a, float32x2_t v) {
return vmulq_lane_f32(a, v, 1);
}
-// CHECK-LABEL: define <2 x double> @test_vmulq_lane_f64(<2 x double> %a, <1 x double> %v) #0 {
+// CHECK-LABEL: @test_vmulq_lane_f64(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <1 x double> %v, <1 x double> %v, <2 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = fmul <2 x double> %a, [[SHUFFLE]]
// CHECK: ret <2 x double> [[MUL]]
@@ -1516,7 +1348,7 @@ float64x2_t test_vmulq_lane_f64(float64x2_t a, float64x1_t v) {
return vmulq_lane_f64(a, v, 0);
}
-// CHECK-LABEL: define <2 x float> @test_vmul_laneq_f32(<2 x float> %a, <4 x float> %v) #0 {
+// CHECK-LABEL: @test_vmul_laneq_f32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x float> %v, <4 x float> %v, <2 x i32> <i32 3, i32 3>
// CHECK: [[MUL:%.*]] = fmul <2 x float> %a, [[SHUFFLE]]
// CHECK: ret <2 x float> [[MUL]]
@@ -1524,7 +1356,7 @@ float32x2_t test_vmul_laneq_f32(float32x2_t a, float32x4_t v) {
return vmul_laneq_f32(a, v, 3);
}
-// CHECK-LABEL: define <1 x double> @test_vmul_laneq_f64(<1 x double> %a, <2 x double> %v) #0 {
+// CHECK-LABEL: @test_vmul_laneq_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x double> %v to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to double
@@ -1537,16 +1369,16 @@ float64x1_t test_vmul_laneq_f64(float64x1_t a, float64x2_t v) {
return vmul_laneq_f64(a, v, 1);
}
-
-// CHECK-LABEL: define <4 x float> @test_vmulq_laneq_f32(<4 x float> %a, <4 x float> %v) #0 {
+// CHECK-LABEL: @test_vmulq_laneq_f32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x float> %v, <4 x float> %v, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[MUL:%.*]] = fmul <4 x float> %a, [[SHUFFLE]]
// CHECK: ret <4 x float> [[MUL]]
+
float32x4_t test_vmulq_laneq_f32(float32x4_t a, float32x4_t v) {
return vmulq_laneq_f32(a, v, 3);
}
-// CHECK-LABEL: define <2 x double> @test_vmulq_laneq_f64(<2 x double> %a, <2 x double> %v) #0 {
+// CHECK-LABEL: @test_vmulq_laneq_f64(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x double> %v, <2 x double> %v, <2 x i32> <i32 1, i32 1>
// CHECK: [[MUL:%.*]] = fmul <2 x double> %a, [[SHUFFLE]]
// CHECK: ret <2 x double> [[MUL]]
@@ -1554,79 +1386,67 @@ float64x2_t test_vmulq_laneq_f64(float64x2_t a, float64x2_t v) {
return vmulq_laneq_f64(a, v, 1);
}
-// CHECK-LABEL: define <2 x float> @test_vmulx_lane_f32(<2 x float> %a, <2 x float> %v) #0 {
+// CHECK-LABEL: @test_vmulx_lane_f32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x float> %v, <2 x float> %v, <2 x i32> <i32 1, i32 1>
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULX_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VMULX1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK: [[VMULX2_I:%.*]] = call <2 x float> @llvm.aarch64.neon.fmulx.v2f32(<2 x float> [[VMULX_I]], <2 x float> [[VMULX1_I]]) #2
+// CHECK: [[VMULX2_I:%.*]] = call <2 x float> @llvm.aarch64.neon.fmulx.v2f32(<2 x float> %a, <2 x float> [[SHUFFLE]]) #2
// CHECK: ret <2 x float> [[VMULX2_I]]
float32x2_t test_vmulx_lane_f32(float32x2_t a, float32x2_t v) {
return vmulx_lane_f32(a, v, 1);
}
-// CHECK-LABEL: define <4 x float> @test_vmulxq_lane_f32(<4 x float> %a, <2 x float> %v) #0 {
+// CHECK-LABEL: @test_vmulxq_lane_f32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x float> %v, <2 x float> %v, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> [[SHUFFLE]] to <16 x i8>
-// CHECK: [[VMULX_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VMULX1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
-// CHECK: [[VMULX2_I:%.*]] = call <4 x float> @llvm.aarch64.neon.fmulx.v4f32(<4 x float> [[VMULX_I]], <4 x float> [[VMULX1_I]]) #2
+// CHECK: [[VMULX2_I:%.*]] = call <4 x float> @llvm.aarch64.neon.fmulx.v4f32(<4 x float> %a, <4 x float> [[SHUFFLE]]) #2
// CHECK: ret <4 x float> [[VMULX2_I]]
float32x4_t test_vmulxq_lane_f32(float32x4_t a, float32x2_t v) {
return vmulxq_lane_f32(a, v, 1);
}
-// CHECK-LABEL: define <2 x double> @test_vmulxq_lane_f64(<2 x double> %a, <1 x double> %v) #0 {
+// CHECK-LABEL: @test_vmulxq_lane_f64(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <1 x double> %v, <1 x double> %v, <2 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x double> [[SHUFFLE]] to <16 x i8>
-// CHECK: [[VMULX_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VMULX1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x double>
-// CHECK: [[VMULX2_I:%.*]] = call <2 x double> @llvm.aarch64.neon.fmulx.v2f64(<2 x double> [[VMULX_I]], <2 x double> [[VMULX1_I]]) #2
+// CHECK: [[VMULX2_I:%.*]] = call <2 x double> @llvm.aarch64.neon.fmulx.v2f64(<2 x double> %a, <2 x double> [[SHUFFLE]]) #2
// CHECK: ret <2 x double> [[VMULX2_I]]
float64x2_t test_vmulxq_lane_f64(float64x2_t a, float64x1_t v) {
return vmulxq_lane_f64(a, v, 0);
}
-// CHECK-LABEL: define <2 x float> @test_vmulx_laneq_f32(<2 x float> %a, <4 x float> %v) #0 {
+// CHECK-LABEL: @test_vmulx_laneq_f32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x float> %v, <4 x float> %v, <2 x i32> <i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULX_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VMULX1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK: [[VMULX2_I:%.*]] = call <2 x float> @llvm.aarch64.neon.fmulx.v2f32(<2 x float> [[VMULX_I]], <2 x float> [[VMULX1_I]]) #2
+// CHECK: [[VMULX2_I:%.*]] = call <2 x float> @llvm.aarch64.neon.fmulx.v2f32(<2 x float> %a, <2 x float> [[SHUFFLE]]) #2
// CHECK: ret <2 x float> [[VMULX2_I]]
float32x2_t test_vmulx_laneq_f32(float32x2_t a, float32x4_t v) {
return vmulx_laneq_f32(a, v, 3);
}
-// CHECK-LABEL: define <4 x float> @test_vmulxq_laneq_f32(<4 x float> %a, <4 x float> %v) #0 {
+// CHECK-LABEL: @test_vmulxq_laneq_f32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x float> %v, <4 x float> %v, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> [[SHUFFLE]] to <16 x i8>
-// CHECK: [[VMULX_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VMULX1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
-// CHECK: [[VMULX2_I:%.*]] = call <4 x float> @llvm.aarch64.neon.fmulx.v4f32(<4 x float> [[VMULX_I]], <4 x float> [[VMULX1_I]]) #2
+// CHECK: [[VMULX2_I:%.*]] = call <4 x float> @llvm.aarch64.neon.fmulx.v4f32(<4 x float> %a, <4 x float> [[SHUFFLE]]) #2
// CHECK: ret <4 x float> [[VMULX2_I]]
float32x4_t test_vmulxq_laneq_f32(float32x4_t a, float32x4_t v) {
return vmulxq_laneq_f32(a, v, 3);
}
-// CHECK-LABEL: define <2 x double> @test_vmulxq_laneq_f64(<2 x double> %a, <2 x double> %v) #0 {
+// CHECK-LABEL: @test_vmulxq_laneq_f64(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x double> %v, <2 x double> %v, <2 x i32> <i32 1, i32 1>
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x double> [[SHUFFLE]] to <16 x i8>
-// CHECK: [[VMULX_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VMULX1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x double>
-// CHECK: [[VMULX2_I:%.*]] = call <2 x double> @llvm.aarch64.neon.fmulx.v2f64(<2 x double> [[VMULX_I]], <2 x double> [[VMULX1_I]]) #2
+// CHECK: [[VMULX2_I:%.*]] = call <2 x double> @llvm.aarch64.neon.fmulx.v2f64(<2 x double> %a, <2 x double> [[SHUFFLE]]) #2
// CHECK: ret <2 x double> [[VMULX2_I]]
float64x2_t test_vmulxq_laneq_f64(float64x2_t a, float64x2_t v) {
return vmulxq_laneq_f64(a, v, 1);
}
-// CHECK-LABEL: define <4 x i16> @test_vmla_lane_s16_0(<4 x i16> %a, <4 x i16> %b, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmla_lane_s16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = mul <4 x i16> %b, [[SHUFFLE]]
// CHECK: [[ADD:%.*]] = add <4 x i16> %a, [[MUL]]
@@ -1635,7 +1455,7 @@ int16x4_t test_vmla_lane_s16_0(int16x4_t a, int16x4_t b, int16x4_t v) {
return vmla_lane_s16(a, b, v, 0);
}
-// CHECK-LABEL: define <8 x i16> @test_vmlaq_lane_s16_0(<8 x i16> %a, <8 x i16> %b, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmlaq_lane_s16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <8 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = mul <8 x i16> %b, [[SHUFFLE]]
// CHECK: [[ADD:%.*]] = add <8 x i16> %a, [[MUL]]
@@ -1644,7 +1464,7 @@ int16x8_t test_vmlaq_lane_s16_0(int16x8_t a, int16x8_t b, int16x4_t v) {
return vmlaq_lane_s16(a, b, v, 0);
}
-// CHECK-LABEL: define <2 x i32> @test_vmla_lane_s32_0(<2 x i32> %a, <2 x i32> %b, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmla_lane_s32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = mul <2 x i32> %b, [[SHUFFLE]]
// CHECK: [[ADD:%.*]] = add <2 x i32> %a, [[MUL]]
@@ -1653,7 +1473,7 @@ int32x2_t test_vmla_lane_s32_0(int32x2_t a, int32x2_t b, int32x2_t v) {
return vmla_lane_s32(a, b, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlaq_lane_s32_0(<4 x i32> %a, <4 x i32> %b, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmlaq_lane_s32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <4 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = mul <4 x i32> %b, [[SHUFFLE]]
// CHECK: [[ADD:%.*]] = add <4 x i32> %a, [[MUL]]
@@ -1662,7 +1482,7 @@ int32x4_t test_vmlaq_lane_s32_0(int32x4_t a, int32x4_t b, int32x2_t v) {
return vmlaq_lane_s32(a, b, v, 0);
}
-// CHECK-LABEL: define <4 x i16> @test_vmla_laneq_s16_0(<4 x i16> %a, <4 x i16> %b, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmla_laneq_s16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = mul <4 x i16> %b, [[SHUFFLE]]
// CHECK: [[ADD:%.*]] = add <4 x i16> %a, [[MUL]]
@@ -1671,7 +1491,7 @@ int16x4_t test_vmla_laneq_s16_0(int16x4_t a, int16x4_t b, int16x8_t v) {
return vmla_laneq_s16(a, b, v, 0);
}
-// CHECK-LABEL: define <8 x i16> @test_vmlaq_laneq_s16_0(<8 x i16> %a, <8 x i16> %b, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmlaq_laneq_s16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <8 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = mul <8 x i16> %b, [[SHUFFLE]]
// CHECK: [[ADD:%.*]] = add <8 x i16> %a, [[MUL]]
@@ -1680,7 +1500,7 @@ int16x8_t test_vmlaq_laneq_s16_0(int16x8_t a, int16x8_t b, int16x8_t v) {
return vmlaq_laneq_s16(a, b, v, 0);
}
-// CHECK-LABEL: define <2 x i32> @test_vmla_laneq_s32_0(<2 x i32> %a, <2 x i32> %b, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmla_laneq_s32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = mul <2 x i32> %b, [[SHUFFLE]]
// CHECK: [[ADD:%.*]] = add <2 x i32> %a, [[MUL]]
@@ -1689,7 +1509,7 @@ int32x2_t test_vmla_laneq_s32_0(int32x2_t a, int32x2_t b, int32x4_t v) {
return vmla_laneq_s32(a, b, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlaq_laneq_s32_0(<4 x i32> %a, <4 x i32> %b, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmlaq_laneq_s32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <4 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = mul <4 x i32> %b, [[SHUFFLE]]
// CHECK: [[ADD:%.*]] = add <4 x i32> %a, [[MUL]]
@@ -1698,7 +1518,7 @@ int32x4_t test_vmlaq_laneq_s32_0(int32x4_t a, int32x4_t b, int32x4_t v) {
return vmlaq_laneq_s32(a, b, v, 0);
}
-// CHECK-LABEL: define <4 x i16> @test_vmls_lane_s16_0(<4 x i16> %a, <4 x i16> %b, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmls_lane_s16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = mul <4 x i16> %b, [[SHUFFLE]]
// CHECK: [[SUB:%.*]] = sub <4 x i16> %a, [[MUL]]
@@ -1707,7 +1527,7 @@ int16x4_t test_vmls_lane_s16_0(int16x4_t a, int16x4_t b, int16x4_t v) {
return vmls_lane_s16(a, b, v, 0);
}
-// CHECK-LABEL: define <8 x i16> @test_vmlsq_lane_s16_0(<8 x i16> %a, <8 x i16> %b, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmlsq_lane_s16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <8 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = mul <8 x i16> %b, [[SHUFFLE]]
// CHECK: [[SUB:%.*]] = sub <8 x i16> %a, [[MUL]]
@@ -1716,7 +1536,7 @@ int16x8_t test_vmlsq_lane_s16_0(int16x8_t a, int16x8_t b, int16x4_t v) {
return vmlsq_lane_s16(a, b, v, 0);
}
-// CHECK-LABEL: define <2 x i32> @test_vmls_lane_s32_0(<2 x i32> %a, <2 x i32> %b, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmls_lane_s32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = mul <2 x i32> %b, [[SHUFFLE]]
// CHECK: [[SUB:%.*]] = sub <2 x i32> %a, [[MUL]]
@@ -1725,7 +1545,7 @@ int32x2_t test_vmls_lane_s32_0(int32x2_t a, int32x2_t b, int32x2_t v) {
return vmls_lane_s32(a, b, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlsq_lane_s32_0(<4 x i32> %a, <4 x i32> %b, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmlsq_lane_s32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <4 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = mul <4 x i32> %b, [[SHUFFLE]]
// CHECK: [[SUB:%.*]] = sub <4 x i32> %a, [[MUL]]
@@ -1734,7 +1554,7 @@ int32x4_t test_vmlsq_lane_s32_0(int32x4_t a, int32x4_t b, int32x2_t v) {
return vmlsq_lane_s32(a, b, v, 0);
}
-// CHECK-LABEL: define <4 x i16> @test_vmls_laneq_s16_0(<4 x i16> %a, <4 x i16> %b, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmls_laneq_s16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = mul <4 x i16> %b, [[SHUFFLE]]
// CHECK: [[SUB:%.*]] = sub <4 x i16> %a, [[MUL]]
@@ -1743,7 +1563,7 @@ int16x4_t test_vmls_laneq_s16_0(int16x4_t a, int16x4_t b, int16x8_t v) {
return vmls_laneq_s16(a, b, v, 0);
}
-// CHECK-LABEL: define <8 x i16> @test_vmlsq_laneq_s16_0(<8 x i16> %a, <8 x i16> %b, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmlsq_laneq_s16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <8 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = mul <8 x i16> %b, [[SHUFFLE]]
// CHECK: [[SUB:%.*]] = sub <8 x i16> %a, [[MUL]]
@@ -1752,7 +1572,7 @@ int16x8_t test_vmlsq_laneq_s16_0(int16x8_t a, int16x8_t b, int16x8_t v) {
return vmlsq_laneq_s16(a, b, v, 0);
}
-// CHECK-LABEL: define <2 x i32> @test_vmls_laneq_s32_0(<2 x i32> %a, <2 x i32> %b, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmls_laneq_s32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = mul <2 x i32> %b, [[SHUFFLE]]
// CHECK: [[SUB:%.*]] = sub <2 x i32> %a, [[MUL]]
@@ -1761,7 +1581,7 @@ int32x2_t test_vmls_laneq_s32_0(int32x2_t a, int32x2_t b, int32x4_t v) {
return vmls_laneq_s32(a, b, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlsq_laneq_s32_0(<4 x i32> %a, <4 x i32> %b, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmlsq_laneq_s32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <4 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = mul <4 x i32> %b, [[SHUFFLE]]
// CHECK: [[SUB:%.*]] = sub <4 x i32> %a, [[MUL]]
@@ -1770,7 +1590,7 @@ int32x4_t test_vmlsq_laneq_s32_0(int32x4_t a, int32x4_t b, int32x4_t v) {
return vmlsq_laneq_s32(a, b, v, 0);
}
-// CHECK-LABEL: define <4 x i16> @test_vmul_lane_s16_0(<4 x i16> %a, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmul_lane_s16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = mul <4 x i16> %a, [[SHUFFLE]]
// CHECK: ret <4 x i16> [[MUL]]
@@ -1778,7 +1598,7 @@ int16x4_t test_vmul_lane_s16_0(int16x4_t a, int16x4_t v) {
return vmul_lane_s16(a, v, 0);
}
-// CHECK-LABEL: define <8 x i16> @test_vmulq_lane_s16_0(<8 x i16> %a, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmulq_lane_s16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <8 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = mul <8 x i16> %a, [[SHUFFLE]]
// CHECK: ret <8 x i16> [[MUL]]
@@ -1786,7 +1606,7 @@ int16x8_t test_vmulq_lane_s16_0(int16x8_t a, int16x4_t v) {
return vmulq_lane_s16(a, v, 0);
}
-// CHECK-LABEL: define <2 x i32> @test_vmul_lane_s32_0(<2 x i32> %a, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmul_lane_s32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = mul <2 x i32> %a, [[SHUFFLE]]
// CHECK: ret <2 x i32> [[MUL]]
@@ -1794,7 +1614,7 @@ int32x2_t test_vmul_lane_s32_0(int32x2_t a, int32x2_t v) {
return vmul_lane_s32(a, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vmulq_lane_s32_0(<4 x i32> %a, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmulq_lane_s32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <4 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = mul <4 x i32> %a, [[SHUFFLE]]
// CHECK: ret <4 x i32> [[MUL]]
@@ -1802,7 +1622,7 @@ int32x4_t test_vmulq_lane_s32_0(int32x4_t a, int32x2_t v) {
return vmulq_lane_s32(a, v, 0);
}
-// CHECK-LABEL: define <4 x i16> @test_vmul_lane_u16_0(<4 x i16> %a, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmul_lane_u16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = mul <4 x i16> %a, [[SHUFFLE]]
// CHECK: ret <4 x i16> [[MUL]]
@@ -1810,7 +1630,7 @@ uint16x4_t test_vmul_lane_u16_0(uint16x4_t a, uint16x4_t v) {
return vmul_lane_u16(a, v, 0);
}
-// CHECK-LABEL: define <8 x i16> @test_vmulq_lane_u16_0(<8 x i16> %a, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmulq_lane_u16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <8 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = mul <8 x i16> %a, [[SHUFFLE]]
// CHECK: ret <8 x i16> [[MUL]]
@@ -1818,7 +1638,7 @@ uint16x8_t test_vmulq_lane_u16_0(uint16x8_t a, uint16x4_t v) {
return vmulq_lane_u16(a, v, 0);
}
-// CHECK-LABEL: define <2 x i32> @test_vmul_lane_u32_0(<2 x i32> %a, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmul_lane_u32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = mul <2 x i32> %a, [[SHUFFLE]]
// CHECK: ret <2 x i32> [[MUL]]
@@ -1826,7 +1646,7 @@ uint32x2_t test_vmul_lane_u32_0(uint32x2_t a, uint32x2_t v) {
return vmul_lane_u32(a, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vmulq_lane_u32_0(<4 x i32> %a, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmulq_lane_u32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <4 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = mul <4 x i32> %a, [[SHUFFLE]]
// CHECK: ret <4 x i32> [[MUL]]
@@ -1834,7 +1654,7 @@ uint32x4_t test_vmulq_lane_u32_0(uint32x4_t a, uint32x2_t v) {
return vmulq_lane_u32(a, v, 0);
}
-// CHECK-LABEL: define <4 x i16> @test_vmul_laneq_s16_0(<4 x i16> %a, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmul_laneq_s16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = mul <4 x i16> %a, [[SHUFFLE]]
// CHECK: ret <4 x i16> [[MUL]]
@@ -1842,7 +1662,7 @@ int16x4_t test_vmul_laneq_s16_0(int16x4_t a, int16x8_t v) {
return vmul_laneq_s16(a, v, 0);
}
-// CHECK-LABEL: define <8 x i16> @test_vmulq_laneq_s16_0(<8 x i16> %a, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmulq_laneq_s16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <8 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = mul <8 x i16> %a, [[SHUFFLE]]
// CHECK: ret <8 x i16> [[MUL]]
@@ -1850,7 +1670,7 @@ int16x8_t test_vmulq_laneq_s16_0(int16x8_t a, int16x8_t v) {
return vmulq_laneq_s16(a, v, 0);
}
-// CHECK-LABEL: define <2 x i32> @test_vmul_laneq_s32_0(<2 x i32> %a, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmul_laneq_s32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = mul <2 x i32> %a, [[SHUFFLE]]
// CHECK: ret <2 x i32> [[MUL]]
@@ -1858,7 +1678,7 @@ int32x2_t test_vmul_laneq_s32_0(int32x2_t a, int32x4_t v) {
return vmul_laneq_s32(a, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vmulq_laneq_s32_0(<4 x i32> %a, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmulq_laneq_s32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <4 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = mul <4 x i32> %a, [[SHUFFLE]]
// CHECK: ret <4 x i32> [[MUL]]
@@ -1866,7 +1686,7 @@ int32x4_t test_vmulq_laneq_s32_0(int32x4_t a, int32x4_t v) {
return vmulq_laneq_s32(a, v, 0);
}
-// CHECK-LABEL: define <4 x i16> @test_vmul_laneq_u16_0(<4 x i16> %a, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmul_laneq_u16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = mul <4 x i16> %a, [[SHUFFLE]]
// CHECK: ret <4 x i16> [[MUL]]
@@ -1874,7 +1694,7 @@ uint16x4_t test_vmul_laneq_u16_0(uint16x4_t a, uint16x8_t v) {
return vmul_laneq_u16(a, v, 0);
}
-// CHECK-LABEL: define <8 x i16> @test_vmulq_laneq_u16_0(<8 x i16> %a, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmulq_laneq_u16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <8 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = mul <8 x i16> %a, [[SHUFFLE]]
// CHECK: ret <8 x i16> [[MUL]]
@@ -1882,7 +1702,7 @@ uint16x8_t test_vmulq_laneq_u16_0(uint16x8_t a, uint16x8_t v) {
return vmulq_laneq_u16(a, v, 0);
}
-// CHECK-LABEL: define <2 x i32> @test_vmul_laneq_u32_0(<2 x i32> %a, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmul_laneq_u32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = mul <2 x i32> %a, [[SHUFFLE]]
// CHECK: ret <2 x i32> [[MUL]]
@@ -1890,7 +1710,7 @@ uint32x2_t test_vmul_laneq_u32_0(uint32x2_t a, uint32x4_t v) {
return vmul_laneq_u32(a, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vmulq_laneq_u32_0(<4 x i32> %a, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmulq_laneq_u32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <4 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = mul <4 x i32> %a, [[SHUFFLE]]
// CHECK: ret <4 x i32> [[MUL]]
@@ -1898,7 +1718,7 @@ uint32x4_t test_vmulq_laneq_u32_0(uint32x4_t a, uint32x4_t v) {
return vmulq_laneq_u32(a, v, 0);
}
-// CHECK-LABEL: define <2 x float> @test_vfma_lane_f32_0(<2 x float> %a, <2 x float> %b, <2 x float> %v) #0 {
+// CHECK-LABEL: @test_vfma_lane_f32_0(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x float> %v to <8 x i8>
@@ -1912,7 +1732,7 @@ float32x2_t test_vfma_lane_f32_0(float32x2_t a, float32x2_t b, float32x2_t v) {
return vfma_lane_f32(a, b, v, 0);
}
-// CHECK-LABEL: define <4 x float> @test_vfmaq_lane_f32_0(<4 x float> %a, <4 x float> %b, <2 x float> %v) #0 {
+// CHECK-LABEL: @test_vfmaq_lane_f32_0(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x float> %v to <8 x i8>
@@ -1926,7 +1746,7 @@ float32x4_t test_vfmaq_lane_f32_0(float32x4_t a, float32x4_t b, float32x2_t v) {
return vfmaq_lane_f32(a, b, v, 0);
}
-// CHECK-LABEL: define <2 x float> @test_vfma_laneq_f32_0(<2 x float> %a, <2 x float> %b, <4 x float> %v) #0 {
+// CHECK-LABEL: @test_vfma_laneq_f32_0(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x float> %v to <16 x i8>
@@ -1940,7 +1760,7 @@ float32x2_t test_vfma_laneq_f32_0(float32x2_t a, float32x2_t b, float32x4_t v) {
return vfma_laneq_f32(a, b, v, 0);
}
-// CHECK-LABEL: define <4 x float> @test_vfmaq_laneq_f32_0(<4 x float> %a, <4 x float> %b, <4 x float> %v) #0 {
+// CHECK-LABEL: @test_vfmaq_laneq_f32_0(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x float> %v to <16 x i8>
@@ -1954,7 +1774,7 @@ float32x4_t test_vfmaq_laneq_f32_0(float32x4_t a, float32x4_t b, float32x4_t v)
return vfmaq_laneq_f32(a, b, v, 0);
}
-// CHECK-LABEL: define <2 x float> @test_vfms_lane_f32_0(<2 x float> %a, <2 x float> %b, <2 x float> %v) #0 {
+// CHECK-LABEL: @test_vfms_lane_f32_0(
// CHECK: [[SUB:%.*]] = fsub <2 x float> <float -0.000000e+00, float -0.000000e+00>, %b
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> [[SUB]] to <8 x i8>
@@ -1969,7 +1789,7 @@ float32x2_t test_vfms_lane_f32_0(float32x2_t a, float32x2_t b, float32x2_t v) {
return vfms_lane_f32(a, b, v, 0);
}
-// CHECK-LABEL: define <4 x float> @test_vfmsq_lane_f32_0(<4 x float> %a, <4 x float> %b, <2 x float> %v) #0 {
+// CHECK-LABEL: @test_vfmsq_lane_f32_0(
// CHECK: [[SUB:%.*]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %b
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> [[SUB]] to <16 x i8>
@@ -1984,7 +1804,7 @@ float32x4_t test_vfmsq_lane_f32_0(float32x4_t a, float32x4_t b, float32x2_t v) {
return vfmsq_lane_f32(a, b, v, 0);
}
-// CHECK-LABEL: define <2 x float> @test_vfms_laneq_f32_0(<2 x float> %a, <2 x float> %b, <4 x float> %v) #0 {
+// CHECK-LABEL: @test_vfms_laneq_f32_0(
// CHECK: [[SUB:%.*]] = fsub <2 x float> <float -0.000000e+00, float -0.000000e+00>, %b
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> [[SUB]] to <8 x i8>
@@ -1999,7 +1819,7 @@ float32x2_t test_vfms_laneq_f32_0(float32x2_t a, float32x2_t b, float32x4_t v) {
return vfms_laneq_f32(a, b, v, 0);
}
-// CHECK-LABEL: define <4 x float> @test_vfmsq_laneq_f32_0(<4 x float> %a, <4 x float> %b, <4 x float> %v) #0 {
+// CHECK-LABEL: @test_vfmsq_laneq_f32_0(
// CHECK: [[SUB:%.*]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %b
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> [[SUB]] to <16 x i8>
@@ -2014,7 +1834,7 @@ float32x4_t test_vfmsq_laneq_f32_0(float32x4_t a, float32x4_t b, float32x4_t v)
return vfmsq_laneq_f32(a, b, v, 0);
}
-// CHECK-LABEL: define <2 x double> @test_vfmaq_laneq_f64_0(<2 x double> %a, <2 x double> %b, <2 x double> %v) #0 {
+// CHECK-LABEL: @test_vfmaq_laneq_f64_0(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x double> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x double> %v to <16 x i8>
@@ -2028,7 +1848,7 @@ float64x2_t test_vfmaq_laneq_f64_0(float64x2_t a, float64x2_t b, float64x2_t v)
return vfmaq_laneq_f64(a, b, v, 0);
}
-// CHECK-LABEL: define <2 x double> @test_vfmsq_laneq_f64_0(<2 x double> %a, <2 x double> %b, <2 x double> %v) #0 {
+// CHECK-LABEL: @test_vfmsq_laneq_f64_0(
// CHECK: [[SUB:%.*]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %b
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x double> [[SUB]] to <16 x i8>
@@ -2043,991 +1863,821 @@ float64x2_t test_vfmsq_laneq_f64_0(float64x2_t a, float64x2_t b, float64x2_t v)
return vfmsq_laneq_f64(a, b, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlal_lane_s16_0(<4 x i32> %a, <4 x i16> %b, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmlal_lane_s16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> %b, <4 x i16> [[SHUFFLE]]) #2
// CHECK: [[ADD:%.*]] = add <4 x i32> %a, [[VMULL2_I]]
// CHECK: ret <4 x i32> [[ADD]]
int32x4_t test_vmlal_lane_s16_0(int32x4_t a, int16x4_t b, int16x4_t v) {
return vmlal_lane_s16(a, b, v, 0);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlal_lane_s32_0(<2 x i64> %a, <2 x i32> %b, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmlal_lane_s32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> %b, <2 x i32> [[SHUFFLE]]) #2
// CHECK: [[ADD:%.*]] = add <2 x i64> %a, [[VMULL2_I]]
// CHECK: ret <2 x i64> [[ADD]]
int64x2_t test_vmlal_lane_s32_0(int64x2_t a, int32x2_t b, int32x2_t v) {
return vmlal_lane_s32(a, b, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlal_laneq_s16_0(<4 x i32> %a, <4 x i16> %b, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmlal_laneq_s16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> %b, <4 x i16> [[SHUFFLE]]) #2
// CHECK: [[ADD:%.*]] = add <4 x i32> %a, [[VMULL2_I]]
// CHECK: ret <4 x i32> [[ADD]]
int32x4_t test_vmlal_laneq_s16_0(int32x4_t a, int16x4_t b, int16x8_t v) {
return vmlal_laneq_s16(a, b, v, 0);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlal_laneq_s32_0(<2 x i64> %a, <2 x i32> %b, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmlal_laneq_s32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> %b, <2 x i32> [[SHUFFLE]]) #2
// CHECK: [[ADD:%.*]] = add <2 x i64> %a, [[VMULL2_I]]
// CHECK: ret <2 x i64> [[ADD]]
int64x2_t test_vmlal_laneq_s32_0(int64x2_t a, int32x2_t b, int32x4_t v) {
return vmlal_laneq_s32(a, b, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlal_high_lane_s16_0(<4 x i32> %a, <8 x i16> %b, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmlal_high_lane_s16_0(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[SHUFFLE_I]], <4 x i16> [[SHUFFLE]]) #2
// CHECK: [[ADD:%.*]] = add <4 x i32> %a, [[VMULL2_I]]
// CHECK: ret <4 x i32> [[ADD]]
int32x4_t test_vmlal_high_lane_s16_0(int32x4_t a, int16x8_t b, int16x4_t v) {
return vmlal_high_lane_s16(a, b, v, 0);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlal_high_lane_s32_0(<2 x i64> %a, <4 x i32> %b, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmlal_high_lane_s32_0(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[SHUFFLE_I]], <2 x i32> [[SHUFFLE]]) #2
// CHECK: [[ADD:%.*]] = add <2 x i64> %a, [[VMULL2_I]]
// CHECK: ret <2 x i64> [[ADD]]
int64x2_t test_vmlal_high_lane_s32_0(int64x2_t a, int32x4_t b, int32x2_t v) {
return vmlal_high_lane_s32(a, b, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlal_high_laneq_s16_0(<4 x i32> %a, <8 x i16> %b, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmlal_high_laneq_s16_0(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[SHUFFLE_I]], <4 x i16> [[SHUFFLE]]) #2
// CHECK: [[ADD:%.*]] = add <4 x i32> %a, [[VMULL2_I]]
// CHECK: ret <4 x i32> [[ADD]]
int32x4_t test_vmlal_high_laneq_s16_0(int32x4_t a, int16x8_t b, int16x8_t v) {
return vmlal_high_laneq_s16(a, b, v, 0);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlal_high_laneq_s32_0(<2 x i64> %a, <4 x i32> %b, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmlal_high_laneq_s32_0(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[SHUFFLE_I]], <2 x i32> [[SHUFFLE]]) #2
// CHECK: [[ADD:%.*]] = add <2 x i64> %a, [[VMULL2_I]]
// CHECK: ret <2 x i64> [[ADD]]
int64x2_t test_vmlal_high_laneq_s32_0(int64x2_t a, int32x4_t b, int32x4_t v) {
return vmlal_high_laneq_s32(a, b, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlsl_lane_s16_0(<4 x i32> %a, <4 x i16> %b, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmlsl_lane_s16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> %b, <4 x i16> [[SHUFFLE]]) #2
// CHECK: [[SUB:%.*]] = sub <4 x i32> %a, [[VMULL2_I]]
// CHECK: ret <4 x i32> [[SUB]]
int32x4_t test_vmlsl_lane_s16_0(int32x4_t a, int16x4_t b, int16x4_t v) {
return vmlsl_lane_s16(a, b, v, 0);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlsl_lane_s32_0(<2 x i64> %a, <2 x i32> %b, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmlsl_lane_s32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> %b, <2 x i32> [[SHUFFLE]]) #2
// CHECK: [[SUB:%.*]] = sub <2 x i64> %a, [[VMULL2_I]]
// CHECK: ret <2 x i64> [[SUB]]
int64x2_t test_vmlsl_lane_s32_0(int64x2_t a, int32x2_t b, int32x2_t v) {
return vmlsl_lane_s32(a, b, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlsl_laneq_s16_0(<4 x i32> %a, <4 x i16> %b, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmlsl_laneq_s16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> %b, <4 x i16> [[SHUFFLE]]) #2
// CHECK: [[SUB:%.*]] = sub <4 x i32> %a, [[VMULL2_I]]
// CHECK: ret <4 x i32> [[SUB]]
int32x4_t test_vmlsl_laneq_s16_0(int32x4_t a, int16x4_t b, int16x8_t v) {
return vmlsl_laneq_s16(a, b, v, 0);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlsl_laneq_s32_0(<2 x i64> %a, <2 x i32> %b, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmlsl_laneq_s32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> %b, <2 x i32> [[SHUFFLE]]) #2
// CHECK: [[SUB:%.*]] = sub <2 x i64> %a, [[VMULL2_I]]
// CHECK: ret <2 x i64> [[SUB]]
int64x2_t test_vmlsl_laneq_s32_0(int64x2_t a, int32x2_t b, int32x4_t v) {
return vmlsl_laneq_s32(a, b, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlsl_high_lane_s16_0(<4 x i32> %a, <8 x i16> %b, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmlsl_high_lane_s16_0(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[SHUFFLE_I]], <4 x i16> [[SHUFFLE]]) #2
// CHECK: [[SUB:%.*]] = sub <4 x i32> %a, [[VMULL2_I]]
// CHECK: ret <4 x i32> [[SUB]]
int32x4_t test_vmlsl_high_lane_s16_0(int32x4_t a, int16x8_t b, int16x4_t v) {
return vmlsl_high_lane_s16(a, b, v, 0);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlsl_high_lane_s32_0(<2 x i64> %a, <4 x i32> %b, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmlsl_high_lane_s32_0(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[SHUFFLE_I]], <2 x i32> [[SHUFFLE]]) #2
// CHECK: [[SUB:%.*]] = sub <2 x i64> %a, [[VMULL2_I]]
// CHECK: ret <2 x i64> [[SUB]]
int64x2_t test_vmlsl_high_lane_s32_0(int64x2_t a, int32x4_t b, int32x2_t v) {
return vmlsl_high_lane_s32(a, b, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlsl_high_laneq_s16_0(<4 x i32> %a, <8 x i16> %b, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmlsl_high_laneq_s16_0(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[SHUFFLE_I]], <4 x i16> [[SHUFFLE]]) #2
// CHECK: [[SUB:%.*]] = sub <4 x i32> %a, [[VMULL2_I]]
// CHECK: ret <4 x i32> [[SUB]]
int32x4_t test_vmlsl_high_laneq_s16_0(int32x4_t a, int16x8_t b, int16x8_t v) {
return vmlsl_high_laneq_s16(a, b, v, 0);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlsl_high_laneq_s32_0(<2 x i64> %a, <4 x i32> %b, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmlsl_high_laneq_s32_0(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[SHUFFLE_I]], <2 x i32> [[SHUFFLE]]) #2
// CHECK: [[SUB:%.*]] = sub <2 x i64> %a, [[VMULL2_I]]
// CHECK: ret <2 x i64> [[SUB]]
int64x2_t test_vmlsl_high_laneq_s32_0(int64x2_t a, int32x4_t b, int32x4_t v) {
return vmlsl_high_laneq_s32(a, b, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlal_lane_u16_0(<4 x i32> %a, <4 x i16> %b, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmlal_lane_u16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> %b, <4 x i16> [[SHUFFLE]]) #2
// CHECK: [[ADD:%.*]] = add <4 x i32> %a, [[VMULL2_I]]
// CHECK: ret <4 x i32> [[ADD]]
int32x4_t test_vmlal_lane_u16_0(int32x4_t a, int16x4_t b, int16x4_t v) {
return vmlal_lane_u16(a, b, v, 0);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlal_lane_u32_0(<2 x i64> %a, <2 x i32> %b, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmlal_lane_u32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> %b, <2 x i32> [[SHUFFLE]]) #2
// CHECK: [[ADD:%.*]] = add <2 x i64> %a, [[VMULL2_I]]
// CHECK: ret <2 x i64> [[ADD]]
int64x2_t test_vmlal_lane_u32_0(int64x2_t a, int32x2_t b, int32x2_t v) {
return vmlal_lane_u32(a, b, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlal_laneq_u16_0(<4 x i32> %a, <4 x i16> %b, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmlal_laneq_u16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> %b, <4 x i16> [[SHUFFLE]]) #2
// CHECK: [[ADD:%.*]] = add <4 x i32> %a, [[VMULL2_I]]
// CHECK: ret <4 x i32> [[ADD]]
int32x4_t test_vmlal_laneq_u16_0(int32x4_t a, int16x4_t b, int16x8_t v) {
return vmlal_laneq_u16(a, b, v, 0);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlal_laneq_u32_0(<2 x i64> %a, <2 x i32> %b, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmlal_laneq_u32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> %b, <2 x i32> [[SHUFFLE]]) #2
// CHECK: [[ADD:%.*]] = add <2 x i64> %a, [[VMULL2_I]]
// CHECK: ret <2 x i64> [[ADD]]
int64x2_t test_vmlal_laneq_u32_0(int64x2_t a, int32x2_t b, int32x4_t v) {
return vmlal_laneq_u32(a, b, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlal_high_lane_u16_0(<4 x i32> %a, <8 x i16> %b, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmlal_high_lane_u16_0(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[SHUFFLE_I]], <4 x i16> [[SHUFFLE]]) #2
// CHECK: [[ADD:%.*]] = add <4 x i32> %a, [[VMULL2_I]]
// CHECK: ret <4 x i32> [[ADD]]
int32x4_t test_vmlal_high_lane_u16_0(int32x4_t a, int16x8_t b, int16x4_t v) {
return vmlal_high_lane_u16(a, b, v, 0);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlal_high_lane_u32_0(<2 x i64> %a, <4 x i32> %b, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmlal_high_lane_u32_0(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[SHUFFLE_I]], <2 x i32> [[SHUFFLE]]) #2
// CHECK: [[ADD:%.*]] = add <2 x i64> %a, [[VMULL2_I]]
// CHECK: ret <2 x i64> [[ADD]]
int64x2_t test_vmlal_high_lane_u32_0(int64x2_t a, int32x4_t b, int32x2_t v) {
return vmlal_high_lane_u32(a, b, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlal_high_laneq_u16_0(<4 x i32> %a, <8 x i16> %b, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmlal_high_laneq_u16_0(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[SHUFFLE_I]], <4 x i16> [[SHUFFLE]]) #2
// CHECK: [[ADD:%.*]] = add <4 x i32> %a, [[VMULL2_I]]
// CHECK: ret <4 x i32> [[ADD]]
int32x4_t test_vmlal_high_laneq_u16_0(int32x4_t a, int16x8_t b, int16x8_t v) {
return vmlal_high_laneq_u16(a, b, v, 0);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlal_high_laneq_u32_0(<2 x i64> %a, <4 x i32> %b, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmlal_high_laneq_u32_0(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[SHUFFLE_I]], <2 x i32> [[SHUFFLE]]) #2
// CHECK: [[ADD:%.*]] = add <2 x i64> %a, [[VMULL2_I]]
// CHECK: ret <2 x i64> [[ADD]]
int64x2_t test_vmlal_high_laneq_u32_0(int64x2_t a, int32x4_t b, int32x4_t v) {
return vmlal_high_laneq_u32(a, b, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlsl_lane_u16_0(<4 x i32> %a, <4 x i16> %b, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmlsl_lane_u16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> %b, <4 x i16> [[SHUFFLE]]) #2
// CHECK: [[SUB:%.*]] = sub <4 x i32> %a, [[VMULL2_I]]
// CHECK: ret <4 x i32> [[SUB]]
int32x4_t test_vmlsl_lane_u16_0(int32x4_t a, int16x4_t b, int16x4_t v) {
return vmlsl_lane_u16(a, b, v, 0);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlsl_lane_u32_0(<2 x i64> %a, <2 x i32> %b, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmlsl_lane_u32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> %b, <2 x i32> [[SHUFFLE]]) #2
// CHECK: [[SUB:%.*]] = sub <2 x i64> %a, [[VMULL2_I]]
// CHECK: ret <2 x i64> [[SUB]]
int64x2_t test_vmlsl_lane_u32_0(int64x2_t a, int32x2_t b, int32x2_t v) {
return vmlsl_lane_u32(a, b, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlsl_laneq_u16_0(<4 x i32> %a, <4 x i16> %b, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmlsl_laneq_u16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> %b, <4 x i16> [[SHUFFLE]]) #2
// CHECK: [[SUB:%.*]] = sub <4 x i32> %a, [[VMULL2_I]]
// CHECK: ret <4 x i32> [[SUB]]
int32x4_t test_vmlsl_laneq_u16_0(int32x4_t a, int16x4_t b, int16x8_t v) {
return vmlsl_laneq_u16(a, b, v, 0);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlsl_laneq_u32_0(<2 x i64> %a, <2 x i32> %b, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmlsl_laneq_u32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> %b, <2 x i32> [[SHUFFLE]]) #2
// CHECK: [[SUB:%.*]] = sub <2 x i64> %a, [[VMULL2_I]]
// CHECK: ret <2 x i64> [[SUB]]
int64x2_t test_vmlsl_laneq_u32_0(int64x2_t a, int32x2_t b, int32x4_t v) {
return vmlsl_laneq_u32(a, b, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlsl_high_lane_u16_0(<4 x i32> %a, <8 x i16> %b, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmlsl_high_lane_u16_0(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[SHUFFLE_I]], <4 x i16> [[SHUFFLE]]) #2
// CHECK: [[SUB:%.*]] = sub <4 x i32> %a, [[VMULL2_I]]
// CHECK: ret <4 x i32> [[SUB]]
int32x4_t test_vmlsl_high_lane_u16_0(int32x4_t a, int16x8_t b, int16x4_t v) {
return vmlsl_high_lane_u16(a, b, v, 0);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlsl_high_lane_u32_0(<2 x i64> %a, <4 x i32> %b, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmlsl_high_lane_u32_0(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[SHUFFLE_I]], <2 x i32> [[SHUFFLE]]) #2
// CHECK: [[SUB:%.*]] = sub <2 x i64> %a, [[VMULL2_I]]
// CHECK: ret <2 x i64> [[SUB]]
int64x2_t test_vmlsl_high_lane_u32_0(int64x2_t a, int32x4_t b, int32x2_t v) {
return vmlsl_high_lane_u32(a, b, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlsl_high_laneq_u16_0(<4 x i32> %a, <8 x i16> %b, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmlsl_high_laneq_u16_0(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[SHUFFLE_I]], <4 x i16> [[SHUFFLE]]) #2
// CHECK: [[SUB:%.*]] = sub <4 x i32> %a, [[VMULL2_I]]
// CHECK: ret <4 x i32> [[SUB]]
int32x4_t test_vmlsl_high_laneq_u16_0(int32x4_t a, int16x8_t b, int16x8_t v) {
return vmlsl_high_laneq_u16(a, b, v, 0);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlsl_high_laneq_u32_0(<2 x i64> %a, <4 x i32> %b, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmlsl_high_laneq_u32_0(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[SHUFFLE_I]], <2 x i32> [[SHUFFLE]]) #2
// CHECK: [[SUB:%.*]] = sub <2 x i64> %a, [[VMULL2_I]]
// CHECK: ret <2 x i64> [[SUB]]
int64x2_t test_vmlsl_high_laneq_u32_0(int64x2_t a, int32x4_t b, int32x4_t v) {
return vmlsl_high_laneq_u32(a, b, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vmull_lane_s16_0(<4 x i16> %a, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmull_lane_s16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> %a, <4 x i16> [[SHUFFLE]]) #2
// CHECK: ret <4 x i32> [[VMULL2_I]]
int32x4_t test_vmull_lane_s16_0(int16x4_t a, int16x4_t v) {
return vmull_lane_s16(a, v, 0);
}
-// CHECK-LABEL: define <2 x i64> @test_vmull_lane_s32_0(<2 x i32> %a, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmull_lane_s32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> %a, <2 x i32> [[SHUFFLE]]) #2
// CHECK: ret <2 x i64> [[VMULL2_I]]
int64x2_t test_vmull_lane_s32_0(int32x2_t a, int32x2_t v) {
return vmull_lane_s32(a, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vmull_lane_u16_0(<4 x i16> %a, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmull_lane_u16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> %a, <4 x i16> [[SHUFFLE]]) #2
// CHECK: ret <4 x i32> [[VMULL2_I]]
uint32x4_t test_vmull_lane_u16_0(uint16x4_t a, uint16x4_t v) {
return vmull_lane_u16(a, v, 0);
}
-// CHECK-LABEL: define <2 x i64> @test_vmull_lane_u32_0(<2 x i32> %a, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmull_lane_u32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> %a, <2 x i32> [[SHUFFLE]]) #2
// CHECK: ret <2 x i64> [[VMULL2_I]]
uint64x2_t test_vmull_lane_u32_0(uint32x2_t a, uint32x2_t v) {
return vmull_lane_u32(a, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vmull_high_lane_s16_0(<8 x i16> %a, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmull_high_lane_s16_0(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %a, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[SHUFFLE_I]], <4 x i16> [[SHUFFLE]]) #2
// CHECK: ret <4 x i32> [[VMULL2_I]]
int32x4_t test_vmull_high_lane_s16_0(int16x8_t a, int16x4_t v) {
return vmull_high_lane_s16(a, v, 0);
}
-// CHECK-LABEL: define <2 x i64> @test_vmull_high_lane_s32_0(<4 x i32> %a, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmull_high_lane_s32_0(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %a, <2 x i32> <i32 2, i32 3>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[SHUFFLE_I]], <2 x i32> [[SHUFFLE]]) #2
// CHECK: ret <2 x i64> [[VMULL2_I]]
int64x2_t test_vmull_high_lane_s32_0(int32x4_t a, int32x2_t v) {
return vmull_high_lane_s32(a, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vmull_high_lane_u16_0(<8 x i16> %a, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmull_high_lane_u16_0(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %a, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[SHUFFLE_I]], <4 x i16> [[SHUFFLE]]) #2
// CHECK: ret <4 x i32> [[VMULL2_I]]
uint32x4_t test_vmull_high_lane_u16_0(uint16x8_t a, uint16x4_t v) {
return vmull_high_lane_u16(a, v, 0);
}
-// CHECK-LABEL: define <2 x i64> @test_vmull_high_lane_u32_0(<4 x i32> %a, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmull_high_lane_u32_0(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %a, <2 x i32> <i32 2, i32 3>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[SHUFFLE_I]], <2 x i32> [[SHUFFLE]]) #2
// CHECK: ret <2 x i64> [[VMULL2_I]]
uint64x2_t test_vmull_high_lane_u32_0(uint32x4_t a, uint32x2_t v) {
return vmull_high_lane_u32(a, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vmull_laneq_s16_0(<4 x i16> %a, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmull_laneq_s16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> %a, <4 x i16> [[SHUFFLE]]) #2
// CHECK: ret <4 x i32> [[VMULL2_I]]
int32x4_t test_vmull_laneq_s16_0(int16x4_t a, int16x8_t v) {
return vmull_laneq_s16(a, v, 0);
}
-// CHECK-LABEL: define <2 x i64> @test_vmull_laneq_s32_0(<2 x i32> %a, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmull_laneq_s32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> %a, <2 x i32> [[SHUFFLE]]) #2
// CHECK: ret <2 x i64> [[VMULL2_I]]
int64x2_t test_vmull_laneq_s32_0(int32x2_t a, int32x4_t v) {
return vmull_laneq_s32(a, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vmull_laneq_u16_0(<4 x i16> %a, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmull_laneq_u16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> %a, <4 x i16> [[SHUFFLE]]) #2
// CHECK: ret <4 x i32> [[VMULL2_I]]
uint32x4_t test_vmull_laneq_u16_0(uint16x4_t a, uint16x8_t v) {
return vmull_laneq_u16(a, v, 0);
}
-// CHECK-LABEL: define <2 x i64> @test_vmull_laneq_u32_0(<2 x i32> %a, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmull_laneq_u32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> %a, <2 x i32> [[SHUFFLE]]) #2
// CHECK: ret <2 x i64> [[VMULL2_I]]
uint64x2_t test_vmull_laneq_u32_0(uint32x2_t a, uint32x4_t v) {
return vmull_laneq_u32(a, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vmull_high_laneq_s16_0(<8 x i16> %a, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmull_high_laneq_s16_0(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %a, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[SHUFFLE_I]], <4 x i16> [[SHUFFLE]]) #2
// CHECK: ret <4 x i32> [[VMULL2_I]]
int32x4_t test_vmull_high_laneq_s16_0(int16x8_t a, int16x8_t v) {
return vmull_high_laneq_s16(a, v, 0);
}
-// CHECK-LABEL: define <2 x i64> @test_vmull_high_laneq_s32_0(<4 x i32> %a, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmull_high_laneq_s32_0(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %a, <2 x i32> <i32 2, i32 3>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[SHUFFLE_I]], <2 x i32> [[SHUFFLE]]) #2
// CHECK: ret <2 x i64> [[VMULL2_I]]
int64x2_t test_vmull_high_laneq_s32_0(int32x4_t a, int32x4_t v) {
return vmull_high_laneq_s32(a, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vmull_high_laneq_u16_0(<8 x i16> %a, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmull_high_laneq_u16_0(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %a, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[SHUFFLE_I]], <4 x i16> [[SHUFFLE]]) #2
// CHECK: ret <4 x i32> [[VMULL2_I]]
uint32x4_t test_vmull_high_laneq_u16_0(uint16x8_t a, uint16x8_t v) {
return vmull_high_laneq_u16(a, v, 0);
}
-// CHECK-LABEL: define <2 x i64> @test_vmull_high_laneq_u32_0(<4 x i32> %a, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmull_high_laneq_u32_0(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %a, <2 x i32> <i32 2, i32 3>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #2
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[SHUFFLE_I]], <2 x i32> [[SHUFFLE]]) #2
// CHECK: ret <2 x i64> [[VMULL2_I]]
uint64x2_t test_vmull_high_laneq_u32_0(uint32x4_t a, uint32x4_t v) {
return vmull_high_laneq_u32(a, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vqdmlal_lane_s16_0(<4 x i32> %a, <4 x i16> %b, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vqdmlal_lane_s16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMLAL1_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VQDMLAL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[VQDMLAL_I]], <4 x i16> [[VQDMLAL1_I]]) #2
-// CHECK: [[VQDMLAL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQDMLAL_V3_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqadd.v4i32(<4 x i32> [[VQDMLAL_V_I]], <4 x i32> [[VQDMLAL2_I]]) #2
+// CHECK: [[VQDMLAL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> %b, <4 x i16> [[SHUFFLE]]) #2
+// CHECK: [[VQDMLAL_V3_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqadd.v4i32(<4 x i32> %a, <4 x i32> [[VQDMLAL2_I]]) #2
// CHECK: ret <4 x i32> [[VQDMLAL_V3_I]]
int32x4_t test_vqdmlal_lane_s16_0(int32x4_t a, int16x4_t b, int16x4_t v) {
return vqdmlal_lane_s16(a, b, v, 0);
}
-// CHECK-LABEL: define <2 x i64> @test_vqdmlal_lane_s32_0(<2 x i64> %a, <2 x i32> %b, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vqdmlal_lane_s32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMLAL1_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VQDMLAL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[VQDMLAL_I]], <2 x i32> [[VQDMLAL1_I]]) #2
-// CHECK: [[VQDMLAL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQDMLAL_V3_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqadd.v2i64(<2 x i64> [[VQDMLAL_V_I]], <2 x i64> [[VQDMLAL2_I]]) #2
+// CHECK: [[VQDMLAL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> %b, <2 x i32> [[SHUFFLE]]) #2
+// CHECK: [[VQDMLAL_V3_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqadd.v2i64(<2 x i64> %a, <2 x i64> [[VQDMLAL2_I]]) #2
// CHECK: ret <2 x i64> [[VQDMLAL_V3_I]]
int64x2_t test_vqdmlal_lane_s32_0(int64x2_t a, int32x2_t b, int32x2_t v) {
return vqdmlal_lane_s32(a, b, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vqdmlal_high_lane_s16_0(<4 x i32> %a, <8 x i16> %b, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vqdmlal_high_lane_s16_0(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMLAL1_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VQDMLAL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[VQDMLAL_I]], <4 x i16> [[VQDMLAL1_I]]) #2
-// CHECK: [[VQDMLAL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQDMLAL_V3_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqadd.v4i32(<4 x i32> [[VQDMLAL_V_I]], <4 x i32> [[VQDMLAL2_I]]) #2
+// CHECK: [[VQDMLAL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[SHUFFLE_I]], <4 x i16> [[SHUFFLE]]) #2
+// CHECK: [[VQDMLAL_V3_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqadd.v4i32(<4 x i32> %a, <4 x i32> [[VQDMLAL2_I]]) #2
// CHECK: ret <4 x i32> [[VQDMLAL_V3_I]]
int32x4_t test_vqdmlal_high_lane_s16_0(int32x4_t a, int16x8_t b, int16x4_t v) {
return vqdmlal_high_lane_s16(a, b, v, 0);
}
-// CHECK-LABEL: define <2 x i64> @test_vqdmlal_high_lane_s32_0(<2 x i64> %a, <4 x i32> %b, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vqdmlal_high_lane_s32_0(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMLAL1_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VQDMLAL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[VQDMLAL_I]], <2 x i32> [[VQDMLAL1_I]]) #2
-// CHECK: [[VQDMLAL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQDMLAL_V3_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqadd.v2i64(<2 x i64> [[VQDMLAL_V_I]], <2 x i64> [[VQDMLAL2_I]]) #2
+// CHECK: [[VQDMLAL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[SHUFFLE_I]], <2 x i32> [[SHUFFLE]]) #2
+// CHECK: [[VQDMLAL_V3_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqadd.v2i64(<2 x i64> %a, <2 x i64> [[VQDMLAL2_I]]) #2
// CHECK: ret <2 x i64> [[VQDMLAL_V3_I]]
int64x2_t test_vqdmlal_high_lane_s32_0(int64x2_t a, int32x4_t b, int32x2_t v) {
return vqdmlal_high_lane_s32(a, b, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vqdmlsl_lane_s16_0(<4 x i32> %a, <4 x i16> %b, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vqdmlsl_lane_s16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMLAL1_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VQDMLAL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[VQDMLAL_I]], <4 x i16> [[VQDMLAL1_I]]) #2
-// CHECK: [[VQDMLSL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQDMLSL_V3_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqsub.v4i32(<4 x i32> [[VQDMLSL_V_I]], <4 x i32> [[VQDMLAL2_I]]) #2
+// CHECK: [[VQDMLAL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> %b, <4 x i16> [[SHUFFLE]]) #2
+// CHECK: [[VQDMLSL_V3_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqsub.v4i32(<4 x i32> %a, <4 x i32> [[VQDMLAL2_I]]) #2
// CHECK: ret <4 x i32> [[VQDMLSL_V3_I]]
int32x4_t test_vqdmlsl_lane_s16_0(int32x4_t a, int16x4_t b, int16x4_t v) {
return vqdmlsl_lane_s16(a, b, v, 0);
}
-// CHECK-LABEL: define <2 x i64> @test_vqdmlsl_lane_s32_0(<2 x i64> %a, <2 x i32> %b, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vqdmlsl_lane_s32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMLAL1_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VQDMLAL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[VQDMLAL_I]], <2 x i32> [[VQDMLAL1_I]]) #2
-// CHECK: [[VQDMLSL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQDMLSL_V3_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqsub.v2i64(<2 x i64> [[VQDMLSL_V_I]], <2 x i64> [[VQDMLAL2_I]]) #2
+// CHECK: [[VQDMLAL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> %b, <2 x i32> [[SHUFFLE]]) #2
+// CHECK: [[VQDMLSL_V3_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqsub.v2i64(<2 x i64> %a, <2 x i64> [[VQDMLAL2_I]]) #2
// CHECK: ret <2 x i64> [[VQDMLSL_V3_I]]
int64x2_t test_vqdmlsl_lane_s32_0(int64x2_t a, int32x2_t b, int32x2_t v) {
return vqdmlsl_lane_s32(a, b, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vqdmlsl_high_lane_s16_0(<4 x i32> %a, <8 x i16> %b, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vqdmlsl_high_lane_s16_0(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMLAL1_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VQDMLAL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[VQDMLAL_I]], <4 x i16> [[VQDMLAL1_I]]) #2
-// CHECK: [[VQDMLSL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQDMLSL_V3_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqsub.v4i32(<4 x i32> [[VQDMLSL_V_I]], <4 x i32> [[VQDMLAL2_I]]) #2
+// CHECK: [[VQDMLAL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[SHUFFLE_I]], <4 x i16> [[SHUFFLE]]) #2
+// CHECK: [[VQDMLSL_V3_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqsub.v4i32(<4 x i32> %a, <4 x i32> [[VQDMLAL2_I]]) #2
// CHECK: ret <4 x i32> [[VQDMLSL_V3_I]]
int32x4_t test_vqdmlsl_high_lane_s16_0(int32x4_t a, int16x8_t b, int16x4_t v) {
return vqdmlsl_high_lane_s16(a, b, v, 0);
}
-// CHECK-LABEL: define <2 x i64> @test_vqdmlsl_high_lane_s32_0(<2 x i64> %a, <4 x i32> %b, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vqdmlsl_high_lane_s32_0(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMLAL1_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VQDMLAL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[VQDMLAL_I]], <2 x i32> [[VQDMLAL1_I]]) #2
-// CHECK: [[VQDMLSL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQDMLSL_V3_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqsub.v2i64(<2 x i64> [[VQDMLSL_V_I]], <2 x i64> [[VQDMLAL2_I]]) #2
+// CHECK: [[VQDMLAL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[SHUFFLE_I]], <2 x i32> [[SHUFFLE]]) #2
+// CHECK: [[VQDMLSL_V3_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqsub.v2i64(<2 x i64> %a, <2 x i64> [[VQDMLAL2_I]]) #2
// CHECK: ret <2 x i64> [[VQDMLSL_V3_I]]
int64x2_t test_vqdmlsl_high_lane_s32_0(int64x2_t a, int32x4_t b, int32x2_t v) {
return vqdmlsl_high_lane_s32(a, b, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vqdmull_lane_s16_0(<4 x i16> %a, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vqdmull_lane_s16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMULL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQDMULL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMULL_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[VQDMULL_V_I]], <4 x i16> [[VQDMULL_V1_I]]) #2
+// CHECK: [[VQDMULL_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> %a, <4 x i16> [[SHUFFLE]]) #2
// CHECK: [[VQDMULL_V3_I:%.*]] = bitcast <4 x i32> [[VQDMULL_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQDMULL_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VQDMULL_V2_I]]
int32x4_t test_vqdmull_lane_s16_0(int16x4_t a, int16x4_t v) {
return vqdmull_lane_s16(a, v, 0);
}
-// CHECK-LABEL: define <2 x i64> @test_vqdmull_lane_s32_0(<2 x i32> %a, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vqdmull_lane_s32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMULL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQDMULL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMULL_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[VQDMULL_V_I]], <2 x i32> [[VQDMULL_V1_I]]) #2
+// CHECK: [[VQDMULL_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> %a, <2 x i32> [[SHUFFLE]]) #2
// CHECK: [[VQDMULL_V3_I:%.*]] = bitcast <2 x i64> [[VQDMULL_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQDMULL_V3_I]] to <2 x i64>
-// CHECK: ret <2 x i64> [[TMP2]]
+// CHECK: ret <2 x i64> [[VQDMULL_V2_I]]
int64x2_t test_vqdmull_lane_s32_0(int32x2_t a, int32x2_t v) {
return vqdmull_lane_s32(a, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vqdmull_laneq_s16_0(<4 x i16> %a, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vqdmull_laneq_s16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMULL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQDMULL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMULL_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[VQDMULL_V_I]], <4 x i16> [[VQDMULL_V1_I]]) #2
+// CHECK: [[VQDMULL_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> %a, <4 x i16> [[SHUFFLE]]) #2
// CHECK: [[VQDMULL_V3_I:%.*]] = bitcast <4 x i32> [[VQDMULL_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQDMULL_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VQDMULL_V2_I]]
int32x4_t test_vqdmull_laneq_s16_0(int16x4_t a, int16x8_t v) {
return vqdmull_laneq_s16(a, v, 0);
}
-// CHECK-LABEL: define <2 x i64> @test_vqdmull_laneq_s32_0(<2 x i32> %a, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vqdmull_laneq_s32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMULL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQDMULL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMULL_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[VQDMULL_V_I]], <2 x i32> [[VQDMULL_V1_I]]) #2
+// CHECK: [[VQDMULL_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> %a, <2 x i32> [[SHUFFLE]]) #2
// CHECK: [[VQDMULL_V3_I:%.*]] = bitcast <2 x i64> [[VQDMULL_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQDMULL_V3_I]] to <2 x i64>
-// CHECK: ret <2 x i64> [[TMP2]]
+// CHECK: ret <2 x i64> [[VQDMULL_V2_I]]
int64x2_t test_vqdmull_laneq_s32_0(int32x2_t a, int32x4_t v) {
return vqdmull_laneq_s32(a, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vqdmull_high_lane_s16_0(<8 x i16> %a, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vqdmull_high_lane_s16_0(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %a, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMULL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQDMULL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMULL_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[VQDMULL_V_I]], <4 x i16> [[VQDMULL_V1_I]]) #2
+// CHECK: [[VQDMULL_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[SHUFFLE_I]], <4 x i16> [[SHUFFLE]]) #2
// CHECK: [[VQDMULL_V3_I:%.*]] = bitcast <4 x i32> [[VQDMULL_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQDMULL_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VQDMULL_V2_I]]
int32x4_t test_vqdmull_high_lane_s16_0(int16x8_t a, int16x4_t v) {
return vqdmull_high_lane_s16(a, v, 0);
}
-// CHECK-LABEL: define <2 x i64> @test_vqdmull_high_lane_s32_0(<4 x i32> %a, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vqdmull_high_lane_s32_0(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %a, <2 x i32> <i32 2, i32 3>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMULL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQDMULL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMULL_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[VQDMULL_V_I]], <2 x i32> [[VQDMULL_V1_I]]) #2
+// CHECK: [[VQDMULL_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[SHUFFLE_I]], <2 x i32> [[SHUFFLE]]) #2
// CHECK: [[VQDMULL_V3_I:%.*]] = bitcast <2 x i64> [[VQDMULL_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQDMULL_V3_I]] to <2 x i64>
-// CHECK: ret <2 x i64> [[TMP2]]
+// CHECK: ret <2 x i64> [[VQDMULL_V2_I]]
int64x2_t test_vqdmull_high_lane_s32_0(int32x4_t a, int32x2_t v) {
return vqdmull_high_lane_s32(a, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vqdmull_high_laneq_s16_0(<8 x i16> %a, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vqdmull_high_laneq_s16_0(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %a, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMULL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQDMULL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMULL_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[VQDMULL_V_I]], <4 x i16> [[VQDMULL_V1_I]]) #2
+// CHECK: [[VQDMULL_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[SHUFFLE_I]], <4 x i16> [[SHUFFLE]]) #2
// CHECK: [[VQDMULL_V3_I:%.*]] = bitcast <4 x i32> [[VQDMULL_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQDMULL_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VQDMULL_V2_I]]
int32x4_t test_vqdmull_high_laneq_s16_0(int16x8_t a, int16x8_t v) {
return vqdmull_high_laneq_s16(a, v, 0);
}
-// CHECK-LABEL: define <2 x i64> @test_vqdmull_high_laneq_s32_0(<4 x i32> %a, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vqdmull_high_laneq_s32_0(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %a, <2 x i32> <i32 2, i32 3>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMULL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQDMULL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMULL_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[VQDMULL_V_I]], <2 x i32> [[VQDMULL_V1_I]]) #2
+// CHECK: [[VQDMULL_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[SHUFFLE_I]], <2 x i32> [[SHUFFLE]]) #2
// CHECK: [[VQDMULL_V3_I:%.*]] = bitcast <2 x i64> [[VQDMULL_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQDMULL_V3_I]] to <2 x i64>
-// CHECK: ret <2 x i64> [[TMP2]]
+// CHECK: ret <2 x i64> [[VQDMULL_V2_I]]
int64x2_t test_vqdmull_high_laneq_s32_0(int32x4_t a, int32x4_t v) {
return vqdmull_high_laneq_s32(a, v, 0);
}
-// CHECK-LABEL: define <4 x i16> @test_vqdmulh_lane_s16_0(<4 x i16> %a, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vqdmulh_lane_s16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMULH_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQDMULH_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMULH_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqdmulh.v4i16(<4 x i16> [[VQDMULH_V_I]], <4 x i16> [[VQDMULH_V1_I]]) #2
+// CHECK: [[VQDMULH_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqdmulh.v4i16(<4 x i16> %a, <4 x i16> [[SHUFFLE]]) #2
// CHECK: [[VQDMULH_V3_I:%.*]] = bitcast <4 x i16> [[VQDMULH_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQDMULH_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VQDMULH_V2_I]]
int16x4_t test_vqdmulh_lane_s16_0(int16x4_t a, int16x4_t v) {
return vqdmulh_lane_s16(a, v, 0);
}
-// CHECK-LABEL: define <8 x i16> @test_vqdmulhq_lane_s16_0(<8 x i16> %a, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vqdmulhq_lane_s16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <8 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> [[SHUFFLE]] to <16 x i8>
-// CHECK: [[VQDMULHQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VQDMULHQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VQDMULHQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.sqdmulh.v8i16(<8 x i16> [[VQDMULHQ_V_I]], <8 x i16> [[VQDMULHQ_V1_I]]) #2
+// CHECK: [[VQDMULHQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.sqdmulh.v8i16(<8 x i16> %a, <8 x i16> [[SHUFFLE]]) #2
// CHECK: [[VQDMULHQ_V3_I:%.*]] = bitcast <8 x i16> [[VQDMULHQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQDMULHQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VQDMULHQ_V2_I]]
int16x8_t test_vqdmulhq_lane_s16_0(int16x8_t a, int16x4_t v) {
return vqdmulhq_lane_s16(a, v, 0);
}
-// CHECK-LABEL: define <2 x i32> @test_vqdmulh_lane_s32_0(<2 x i32> %a, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vqdmulh_lane_s32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMULH_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQDMULH_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMULH_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqdmulh.v2i32(<2 x i32> [[VQDMULH_V_I]], <2 x i32> [[VQDMULH_V1_I]]) #2
+// CHECK: [[VQDMULH_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqdmulh.v2i32(<2 x i32> %a, <2 x i32> [[SHUFFLE]]) #2
// CHECK: [[VQDMULH_V3_I:%.*]] = bitcast <2 x i32> [[VQDMULH_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQDMULH_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VQDMULH_V2_I]]
int32x2_t test_vqdmulh_lane_s32_0(int32x2_t a, int32x2_t v) {
return vqdmulh_lane_s32(a, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vqdmulhq_lane_s32_0(<4 x i32> %a, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vqdmulhq_lane_s32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <4 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> [[SHUFFLE]] to <16 x i8>
-// CHECK: [[VQDMULHQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQDMULHQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VQDMULHQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmulh.v4i32(<4 x i32> [[VQDMULHQ_V_I]], <4 x i32> [[VQDMULHQ_V1_I]]) #2
+// CHECK: [[VQDMULHQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmulh.v4i32(<4 x i32> %a, <4 x i32> [[SHUFFLE]]) #2
// CHECK: [[VQDMULHQ_V3_I:%.*]] = bitcast <4 x i32> [[VQDMULHQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQDMULHQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VQDMULHQ_V2_I]]
int32x4_t test_vqdmulhq_lane_s32_0(int32x4_t a, int32x2_t v) {
return vqdmulhq_lane_s32(a, v, 0);
}
-// CHECK-LABEL: define <4 x i16> @test_vqrdmulh_lane_s16_0(<4 x i16> %a, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vqrdmulh_lane_s16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQRDMULH_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQRDMULH_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQRDMULH_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqrdmulh.v4i16(<4 x i16> [[VQRDMULH_V_I]], <4 x i16> [[VQRDMULH_V1_I]]) #2
+// CHECK: [[VQRDMULH_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqrdmulh.v4i16(<4 x i16> %a, <4 x i16> [[SHUFFLE]]) #2
// CHECK: [[VQRDMULH_V3_I:%.*]] = bitcast <4 x i16> [[VQRDMULH_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQRDMULH_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VQRDMULH_V2_I]]
int16x4_t test_vqrdmulh_lane_s16_0(int16x4_t a, int16x4_t v) {
return vqrdmulh_lane_s16(a, v, 0);
}
-// CHECK-LABEL: define <8 x i16> @test_vqrdmulhq_lane_s16_0(<8 x i16> %a, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vqrdmulhq_lane_s16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <8 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> [[SHUFFLE]] to <16 x i8>
-// CHECK: [[VQRDMULHQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VQRDMULHQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VQRDMULHQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.sqrdmulh.v8i16(<8 x i16> [[VQRDMULHQ_V_I]], <8 x i16> [[VQRDMULHQ_V1_I]]) #2
-// CHECK: [[VQRDMULHQ_V3_I:%.*]] = bitcast <8 x i16> [[VQRDMULHQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQRDMULHQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: [[VQRDMULHQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.sqrdmulh.v8i16(<8 x i16> %a, <8 x i16> [[SHUFFLE]]) #2
+// CHECK: ret <8 x i16> [[VQRDMULHQ_V2_I]]
int16x8_t test_vqrdmulhq_lane_s16_0(int16x8_t a, int16x4_t v) {
return vqrdmulhq_lane_s16(a, v, 0);
}
-// CHECK-LABEL: define <2 x i32> @test_vqrdmulh_lane_s32_0(<2 x i32> %a, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vqrdmulh_lane_s32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQRDMULH_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQRDMULH_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQRDMULH_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqrdmulh.v2i32(<2 x i32> [[VQRDMULH_V_I]], <2 x i32> [[VQRDMULH_V1_I]]) #2
+// CHECK: [[VQRDMULH_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqrdmulh.v2i32(<2 x i32> %a, <2 x i32> [[SHUFFLE]]) #2
// CHECK: [[VQRDMULH_V3_I:%.*]] = bitcast <2 x i32> [[VQRDMULH_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQRDMULH_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VQRDMULH_V2_I]]
int32x2_t test_vqrdmulh_lane_s32_0(int32x2_t a, int32x2_t v) {
return vqrdmulh_lane_s32(a, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vqrdmulhq_lane_s32_0(<4 x i32> %a, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vqrdmulhq_lane_s32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <4 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> [[SHUFFLE]] to <16 x i8>
-// CHECK: [[VQRDMULHQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQRDMULHQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VQRDMULHQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqrdmulh.v4i32(<4 x i32> [[VQRDMULHQ_V_I]], <4 x i32> [[VQRDMULHQ_V1_I]]) #2
-// CHECK: [[VQRDMULHQ_V3_I:%.*]] = bitcast <4 x i32> [[VQRDMULHQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQRDMULHQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: [[VQRDMULHQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqrdmulh.v4i32(<4 x i32> %a, <4 x i32> [[SHUFFLE]]) #2
+// CHECK: ret <4 x i32> [[VQRDMULHQ_V2_I]]
int32x4_t test_vqrdmulhq_lane_s32_0(int32x4_t a, int32x2_t v) {
return vqrdmulhq_lane_s32(a, v, 0);
}
-// CHECK-LABEL: define <2 x float> @test_vmul_lane_f32_0(<2 x float> %a, <2 x float> %v) #0 {
+// CHECK-LABEL: @test_vmul_lane_f32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x float> %v, <2 x float> %v, <2 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = fmul <2 x float> %a, [[SHUFFLE]]
// CHECK: ret <2 x float> [[MUL]]
@@ -3035,7 +2685,7 @@ float32x2_t test_vmul_lane_f32_0(float32x2_t a, float32x2_t v) {
return vmul_lane_f32(a, v, 0);
}
-// CHECK-LABEL: define <4 x float> @test_vmulq_lane_f32_0(<4 x float> %a, <2 x float> %v) #0 {
+// CHECK-LABEL: @test_vmulq_lane_f32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x float> %v, <2 x float> %v, <4 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = fmul <4 x float> %a, [[SHUFFLE]]
// CHECK: ret <4 x float> [[MUL]]
@@ -3043,7 +2693,7 @@ float32x4_t test_vmulq_lane_f32_0(float32x4_t a, float32x2_t v) {
return vmulq_lane_f32(a, v, 0);
}
-// CHECK-LABEL: define <2 x float> @test_vmul_laneq_f32_0(<2 x float> %a, <4 x float> %v) #0 {
+// CHECK-LABEL: @test_vmul_laneq_f32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x float> %v, <4 x float> %v, <2 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = fmul <2 x float> %a, [[SHUFFLE]]
// CHECK: ret <2 x float> [[MUL]]
@@ -3051,7 +2701,7 @@ float32x2_t test_vmul_laneq_f32_0(float32x2_t a, float32x4_t v) {
return vmul_laneq_f32(a, v, 0);
}
-// CHECK-LABEL: define <1 x double> @test_vmul_laneq_f64_0(<1 x double> %a, <2 x double> %v) #0 {
+// CHECK-LABEL: @test_vmul_laneq_f64_0(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x double> %v to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to double
@@ -3064,7 +2714,7 @@ float64x1_t test_vmul_laneq_f64_0(float64x1_t a, float64x2_t v) {
return vmul_laneq_f64(a, v, 0);
}
-// CHECK-LABEL: define <4 x float> @test_vmulq_laneq_f32_0(<4 x float> %a, <4 x float> %v) #0 {
+// CHECK-LABEL: @test_vmulq_laneq_f32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x float> %v, <4 x float> %v, <4 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = fmul <4 x float> %a, [[SHUFFLE]]
// CHECK: ret <4 x float> [[MUL]]
@@ -3072,7 +2722,7 @@ float32x4_t test_vmulq_laneq_f32_0(float32x4_t a, float32x4_t v) {
return vmulq_laneq_f32(a, v, 0);
}
-// CHECK-LABEL: define <2 x double> @test_vmulq_laneq_f64_0(<2 x double> %a, <2 x double> %v) #0 {
+// CHECK-LABEL: @test_vmulq_laneq_f64_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x double> %v, <2 x double> %v, <2 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = fmul <2 x double> %a, [[SHUFFLE]]
// CHECK: ret <2 x double> [[MUL]]
@@ -3080,79 +2730,67 @@ float64x2_t test_vmulq_laneq_f64_0(float64x2_t a, float64x2_t v) {
return vmulq_laneq_f64(a, v, 0);
}
-// CHECK-LABEL: define <2 x float> @test_vmulx_lane_f32_0(<2 x float> %a, <2 x float> %v) #0 {
+// CHECK-LABEL: @test_vmulx_lane_f32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x float> %v, <2 x float> %v, <2 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULX_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VMULX1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK: [[VMULX2_I:%.*]] = call <2 x float> @llvm.aarch64.neon.fmulx.v2f32(<2 x float> [[VMULX_I]], <2 x float> [[VMULX1_I]]) #2
+// CHECK: [[VMULX2_I:%.*]] = call <2 x float> @llvm.aarch64.neon.fmulx.v2f32(<2 x float> %a, <2 x float> [[SHUFFLE]]) #2
// CHECK: ret <2 x float> [[VMULX2_I]]
float32x2_t test_vmulx_lane_f32_0(float32x2_t a, float32x2_t v) {
return vmulx_lane_f32(a, v, 0);
}
-// CHECK-LABEL: define <4 x float> @test_vmulxq_lane_f32_0(<4 x float> %a, <2 x float> %v) #0 {
+// CHECK-LABEL: @test_vmulxq_lane_f32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x float> %v, <2 x float> %v, <4 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> [[SHUFFLE]] to <16 x i8>
-// CHECK: [[VMULX_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VMULX1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
-// CHECK: [[VMULX2_I:%.*]] = call <4 x float> @llvm.aarch64.neon.fmulx.v4f32(<4 x float> [[VMULX_I]], <4 x float> [[VMULX1_I]]) #2
+// CHECK: [[VMULX2_I:%.*]] = call <4 x float> @llvm.aarch64.neon.fmulx.v4f32(<4 x float> %a, <4 x float> [[SHUFFLE]]) #2
// CHECK: ret <4 x float> [[VMULX2_I]]
float32x4_t test_vmulxq_lane_f32_0(float32x4_t a, float32x2_t v) {
return vmulxq_lane_f32(a, v, 0);
}
-// CHECK-LABEL: define <2 x double> @test_vmulxq_lane_f64_0(<2 x double> %a, <1 x double> %v) #0 {
+// CHECK-LABEL: @test_vmulxq_lane_f64_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <1 x double> %v, <1 x double> %v, <2 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x double> [[SHUFFLE]] to <16 x i8>
-// CHECK: [[VMULX_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VMULX1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x double>
-// CHECK: [[VMULX2_I:%.*]] = call <2 x double> @llvm.aarch64.neon.fmulx.v2f64(<2 x double> [[VMULX_I]], <2 x double> [[VMULX1_I]]) #2
+// CHECK: [[VMULX2_I:%.*]] = call <2 x double> @llvm.aarch64.neon.fmulx.v2f64(<2 x double> %a, <2 x double> [[SHUFFLE]]) #2
// CHECK: ret <2 x double> [[VMULX2_I]]
float64x2_t test_vmulxq_lane_f64_0(float64x2_t a, float64x1_t v) {
return vmulxq_lane_f64(a, v, 0);
}
-// CHECK-LABEL: define <2 x float> @test_vmulx_laneq_f32_0(<2 x float> %a, <4 x float> %v) #0 {
+// CHECK-LABEL: @test_vmulx_laneq_f32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x float> %v, <4 x float> %v, <2 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULX_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VMULX1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK: [[VMULX2_I:%.*]] = call <2 x float> @llvm.aarch64.neon.fmulx.v2f32(<2 x float> [[VMULX_I]], <2 x float> [[VMULX1_I]]) #2
+// CHECK: [[VMULX2_I:%.*]] = call <2 x float> @llvm.aarch64.neon.fmulx.v2f32(<2 x float> %a, <2 x float> [[SHUFFLE]]) #2
// CHECK: ret <2 x float> [[VMULX2_I]]
float32x2_t test_vmulx_laneq_f32_0(float32x2_t a, float32x4_t v) {
return vmulx_laneq_f32(a, v, 0);
}
-// CHECK-LABEL: define <4 x float> @test_vmulxq_laneq_f32_0(<4 x float> %a, <4 x float> %v) #0 {
+// CHECK-LABEL: @test_vmulxq_laneq_f32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x float> %v, <4 x float> %v, <4 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> [[SHUFFLE]] to <16 x i8>
-// CHECK: [[VMULX_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VMULX1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
-// CHECK: [[VMULX2_I:%.*]] = call <4 x float> @llvm.aarch64.neon.fmulx.v4f32(<4 x float> [[VMULX_I]], <4 x float> [[VMULX1_I]]) #2
+// CHECK: [[VMULX2_I:%.*]] = call <4 x float> @llvm.aarch64.neon.fmulx.v4f32(<4 x float> %a, <4 x float> [[SHUFFLE]]) #2
// CHECK: ret <4 x float> [[VMULX2_I]]
float32x4_t test_vmulxq_laneq_f32_0(float32x4_t a, float32x4_t v) {
return vmulxq_laneq_f32(a, v, 0);
}
-// CHECK-LABEL: define <2 x double> @test_vmulxq_laneq_f64_0(<2 x double> %a, <2 x double> %v) #0 {
+// CHECK-LABEL: @test_vmulxq_laneq_f64_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x double> %v, <2 x double> %v, <2 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x double> [[SHUFFLE]] to <16 x i8>
-// CHECK: [[VMULX_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VMULX1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x double>
-// CHECK: [[VMULX2_I:%.*]] = call <2 x double> @llvm.aarch64.neon.fmulx.v2f64(<2 x double> [[VMULX_I]], <2 x double> [[VMULX1_I]]) #2
+// CHECK: [[VMULX2_I:%.*]] = call <2 x double> @llvm.aarch64.neon.fmulx.v2f64(<2 x double> %a, <2 x double> [[SHUFFLE]]) #2
// CHECK: ret <2 x double> [[VMULX2_I]]
float64x2_t test_vmulxq_laneq_f64_0(float64x2_t a, float64x2_t v) {
return vmulxq_laneq_f64(a, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vmull_high_n_s16(<8 x i16> %a, i16 %b) #0 {
+// CHECK-LABEL: @test_vmull_high_n_s16(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %a, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I]] to <8 x i8>
// CHECK: [[VECINIT_I_I:%.*]] = insertelement <4 x i16> undef, i16 %b, i32 0
@@ -3160,29 +2798,25 @@ float64x2_t test_vmulxq_laneq_f64_0(float64x2_t a, float64x2_t v) {
// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <4 x i16> [[VECINIT1_I_I]], i16 %b, i32 2
// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <4 x i16> [[VECINIT2_I_I]], i16 %b, i32 3
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[VECINIT3_I_I]] to <8 x i8>
-// CHECK: [[VMULL_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL4_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL5_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[VMULL_I_I]], <4 x i16> [[VMULL4_I_I]]) #2
+// CHECK: [[VMULL5_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[SHUFFLE_I_I]], <4 x i16> [[VECINIT3_I_I]]) #2
// CHECK: ret <4 x i32> [[VMULL5_I_I]]
int32x4_t test_vmull_high_n_s16(int16x8_t a, int16_t b) {
return vmull_high_n_s16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vmull_high_n_s32(<4 x i32> %a, i32 %b) #0 {
+// CHECK-LABEL: @test_vmull_high_n_s32(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %a, <2 x i32> <i32 2, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I]] to <8 x i8>
// CHECK: [[VECINIT_I_I:%.*]] = insertelement <2 x i32> undef, i32 %b, i32 0
// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <2 x i32> [[VECINIT_I_I]], i32 %b, i32 1
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[VECINIT1_I_I]] to <8 x i8>
-// CHECK: [[VMULL_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL2_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL3_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[VMULL_I_I]], <2 x i32> [[VMULL2_I_I]]) #2
+// CHECK: [[VMULL3_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[SHUFFLE_I_I]], <2 x i32> [[VECINIT1_I_I]]) #2
// CHECK: ret <2 x i64> [[VMULL3_I_I]]
int64x2_t test_vmull_high_n_s32(int32x4_t a, int32_t b) {
return vmull_high_n_s32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vmull_high_n_u16(<8 x i16> %a, i16 %b) #0 {
+// CHECK-LABEL: @test_vmull_high_n_u16(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %a, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I]] to <8 x i8>
// CHECK: [[VECINIT_I_I:%.*]] = insertelement <4 x i16> undef, i16 %b, i32 0
@@ -3190,29 +2824,25 @@ int64x2_t test_vmull_high_n_s32(int32x4_t a, int32_t b) {
// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <4 x i16> [[VECINIT1_I_I]], i16 %b, i32 2
// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <4 x i16> [[VECINIT2_I_I]], i16 %b, i32 3
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[VECINIT3_I_I]] to <8 x i8>
-// CHECK: [[VMULL_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL4_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL5_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[VMULL_I_I]], <4 x i16> [[VMULL4_I_I]]) #2
+// CHECK: [[VMULL5_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[SHUFFLE_I_I]], <4 x i16> [[VECINIT3_I_I]]) #2
// CHECK: ret <4 x i32> [[VMULL5_I_I]]
uint32x4_t test_vmull_high_n_u16(uint16x8_t a, uint16_t b) {
return vmull_high_n_u16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vmull_high_n_u32(<4 x i32> %a, i32 %b) #0 {
+// CHECK-LABEL: @test_vmull_high_n_u32(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %a, <2 x i32> <i32 2, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I]] to <8 x i8>
// CHECK: [[VECINIT_I_I:%.*]] = insertelement <2 x i32> undef, i32 %b, i32 0
// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <2 x i32> [[VECINIT_I_I]], i32 %b, i32 1
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[VECINIT1_I_I]] to <8 x i8>
-// CHECK: [[VMULL_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL2_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL3_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[VMULL_I_I]], <2 x i32> [[VMULL2_I_I]]) #2
+// CHECK: [[VMULL3_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[SHUFFLE_I_I]], <2 x i32> [[VECINIT1_I_I]]) #2
// CHECK: ret <2 x i64> [[VMULL3_I_I]]
uint64x2_t test_vmull_high_n_u32(uint32x4_t a, uint32_t b) {
return vmull_high_n_u32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vqdmull_high_n_s16(<8 x i16> %a, i16 %b) #0 {
+// CHECK-LABEL: @test_vqdmull_high_n_s16(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %a, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I]] to <8 x i8>
// CHECK: [[VECINIT_I_I:%.*]] = insertelement <4 x i16> undef, i16 %b, i32 0
@@ -3220,33 +2850,27 @@ uint64x2_t test_vmull_high_n_u32(uint32x4_t a, uint32_t b) {
// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <4 x i16> [[VECINIT1_I_I]], i16 %b, i32 2
// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <4 x i16> [[VECINIT2_I_I]], i16 %b, i32 3
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[VECINIT3_I_I]] to <8 x i8>
-// CHECK: [[VQDMULL_V_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQDMULL_V4_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMULL_V5_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[VQDMULL_V_I_I]], <4 x i16> [[VQDMULL_V4_I_I]]) #2
+// CHECK: [[VQDMULL_V5_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[SHUFFLE_I_I]], <4 x i16> [[VECINIT3_I_I]]) #2
// CHECK: [[VQDMULL_V6_I_I:%.*]] = bitcast <4 x i32> [[VQDMULL_V5_I_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQDMULL_V6_I_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VQDMULL_V5_I_I]]
int32x4_t test_vqdmull_high_n_s16(int16x8_t a, int16_t b) {
return vqdmull_high_n_s16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vqdmull_high_n_s32(<4 x i32> %a, i32 %b) #0 {
+// CHECK-LABEL: @test_vqdmull_high_n_s32(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %a, <2 x i32> <i32 2, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I]] to <8 x i8>
// CHECK: [[VECINIT_I_I:%.*]] = insertelement <2 x i32> undef, i32 %b, i32 0
// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <2 x i32> [[VECINIT_I_I]], i32 %b, i32 1
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[VECINIT1_I_I]] to <8 x i8>
-// CHECK: [[VQDMULL_V_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQDMULL_V2_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMULL_V3_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[VQDMULL_V_I_I]], <2 x i32> [[VQDMULL_V2_I_I]]) #2
+// CHECK: [[VQDMULL_V3_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[SHUFFLE_I_I]], <2 x i32> [[VECINIT1_I_I]]) #2
// CHECK: [[VQDMULL_V4_I_I:%.*]] = bitcast <2 x i64> [[VQDMULL_V3_I_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQDMULL_V4_I_I]] to <2 x i64>
-// CHECK: ret <2 x i64> [[TMP2]]
+// CHECK: ret <2 x i64> [[VQDMULL_V3_I_I]]
int64x2_t test_vqdmull_high_n_s32(int32x4_t a, int32_t b) {
return vqdmull_high_n_s32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlal_high_n_s16(<4 x i32> %a, <8 x i16> %b, i16 %c) #0 {
+// CHECK-LABEL: @test_vmlal_high_n_s16(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[VECINIT_I_I:%.*]] = insertelement <4 x i16> undef, i16 %c, i32 0
// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <4 x i16> [[VECINIT_I_I]], i16 %c, i32 1
@@ -3254,31 +2878,27 @@ int64x2_t test_vqdmull_high_n_s32(int32x4_t a, int32_t b) {
// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <4 x i16> [[VECINIT2_I_I]], i16 %c, i32 3
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[VECINIT3_I_I]] to <8 x i8>
-// CHECK: [[VMULL_I_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[VMULL_I_I_I]], <4 x i16> [[VMULL1_I_I_I]]) #2
+// CHECK: [[VMULL2_I_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[SHUFFLE_I_I]], <4 x i16> [[VECINIT3_I_I]]) #2
// CHECK: [[ADD_I_I:%.*]] = add <4 x i32> %a, [[VMULL2_I_I_I]]
// CHECK: ret <4 x i32> [[ADD_I_I]]
int32x4_t test_vmlal_high_n_s16(int32x4_t a, int16x8_t b, int16_t c) {
return vmlal_high_n_s16(a, b, c);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlal_high_n_s32(<2 x i64> %a, <4 x i32> %b, i32 %c) #0 {
+// CHECK-LABEL: @test_vmlal_high_n_s32(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
// CHECK: [[VECINIT_I_I:%.*]] = insertelement <2 x i32> undef, i32 %c, i32 0
// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <2 x i32> [[VECINIT_I_I]], i32 %c, i32 1
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[VECINIT1_I_I]] to <8 x i8>
-// CHECK: [[VMULL_I_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[VMULL_I_I_I]], <2 x i32> [[VMULL1_I_I_I]]) #2
+// CHECK: [[VMULL2_I_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[SHUFFLE_I_I]], <2 x i32> [[VECINIT1_I_I]]) #2
// CHECK: [[ADD_I_I:%.*]] = add <2 x i64> %a, [[VMULL2_I_I_I]]
// CHECK: ret <2 x i64> [[ADD_I_I]]
int64x2_t test_vmlal_high_n_s32(int64x2_t a, int32x4_t b, int32_t c) {
return vmlal_high_n_s32(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlal_high_n_u16(<4 x i32> %a, <8 x i16> %b, i16 %c) #0 {
+// CHECK-LABEL: @test_vmlal_high_n_u16(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[VECINIT_I_I:%.*]] = insertelement <4 x i16> undef, i16 %c, i32 0
// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <4 x i16> [[VECINIT_I_I]], i16 %c, i32 1
@@ -3286,31 +2906,27 @@ int64x2_t test_vmlal_high_n_s32(int64x2_t a, int32x4_t b, int32_t c) {
// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <4 x i16> [[VECINIT2_I_I]], i16 %c, i32 3
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[VECINIT3_I_I]] to <8 x i8>
-// CHECK: [[VMULL_I_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[VMULL_I_I_I]], <4 x i16> [[VMULL1_I_I_I]]) #2
+// CHECK: [[VMULL2_I_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[SHUFFLE_I_I]], <4 x i16> [[VECINIT3_I_I]]) #2
// CHECK: [[ADD_I_I:%.*]] = add <4 x i32> %a, [[VMULL2_I_I_I]]
// CHECK: ret <4 x i32> [[ADD_I_I]]
uint32x4_t test_vmlal_high_n_u16(uint32x4_t a, uint16x8_t b, uint16_t c) {
return vmlal_high_n_u16(a, b, c);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlal_high_n_u32(<2 x i64> %a, <4 x i32> %b, i32 %c) #0 {
+// CHECK-LABEL: @test_vmlal_high_n_u32(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
// CHECK: [[VECINIT_I_I:%.*]] = insertelement <2 x i32> undef, i32 %c, i32 0
// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <2 x i32> [[VECINIT_I_I]], i32 %c, i32 1
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[VECINIT1_I_I]] to <8 x i8>
-// CHECK: [[VMULL_I_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[VMULL_I_I_I]], <2 x i32> [[VMULL1_I_I_I]]) #2
+// CHECK: [[VMULL2_I_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[SHUFFLE_I_I]], <2 x i32> [[VECINIT1_I_I]]) #2
// CHECK: [[ADD_I_I:%.*]] = add <2 x i64> %a, [[VMULL2_I_I_I]]
// CHECK: ret <2 x i64> [[ADD_I_I]]
uint64x2_t test_vmlal_high_n_u32(uint64x2_t a, uint32x4_t b, uint32_t c) {
return vmlal_high_n_u32(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vqdmlal_high_n_s16(<4 x i32> %a, <8 x i16> %b, i16 %c) #0 {
+// CHECK-LABEL: @test_vqdmlal_high_n_s16(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I]] to <8 x i8>
@@ -3319,34 +2935,28 @@ uint64x2_t test_vmlal_high_n_u32(uint64x2_t a, uint32x4_t b, uint32_t c) {
// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <4 x i16> [[VECINIT1_I_I]], i16 %c, i32 2
// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <4 x i16> [[VECINIT2_I_I]], i16 %c, i32 3
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> [[VECINIT3_I_I]] to <8 x i8>
-// CHECK: [[VQDMLAL_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMLAL4_I_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VQDMLAL5_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[VQDMLAL_I_I]], <4 x i16> [[VQDMLAL4_I_I]]) #2
-// CHECK: [[VQDMLAL_V_I_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQDMLAL_V6_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqadd.v4i32(<4 x i32> [[VQDMLAL_V_I_I]], <4 x i32> [[VQDMLAL5_I_I]]) #2
+// CHECK: [[VQDMLAL5_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[SHUFFLE_I_I]], <4 x i16> [[VECINIT3_I_I]]) #2
+// CHECK: [[VQDMLAL_V6_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqadd.v4i32(<4 x i32> %a, <4 x i32> [[VQDMLAL5_I_I]]) #2
// CHECK: ret <4 x i32> [[VQDMLAL_V6_I_I]]
int32x4_t test_vqdmlal_high_n_s16(int32x4_t a, int16x8_t b, int16_t c) {
return vqdmlal_high_n_s16(a, b, c);
}
-// CHECK-LABEL: define <2 x i64> @test_vqdmlal_high_n_s32(<2 x i64> %a, <4 x i32> %b, i32 %c) #0 {
+// CHECK-LABEL: @test_vqdmlal_high_n_s32(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I]] to <8 x i8>
// CHECK: [[VECINIT_I_I:%.*]] = insertelement <2 x i32> undef, i32 %c, i32 0
// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <2 x i32> [[VECINIT_I_I]], i32 %c, i32 1
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> [[VECINIT1_I_I]] to <8 x i8>
-// CHECK: [[VQDMLAL_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMLAL2_I_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VQDMLAL3_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[VQDMLAL_I_I]], <2 x i32> [[VQDMLAL2_I_I]]) #2
-// CHECK: [[VQDMLAL_V_I_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQDMLAL_V4_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqadd.v2i64(<2 x i64> [[VQDMLAL_V_I_I]], <2 x i64> [[VQDMLAL3_I_I]]) #2
+// CHECK: [[VQDMLAL3_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[SHUFFLE_I_I]], <2 x i32> [[VECINIT1_I_I]]) #2
+// CHECK: [[VQDMLAL_V4_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqadd.v2i64(<2 x i64> %a, <2 x i64> [[VQDMLAL3_I_I]]) #2
// CHECK: ret <2 x i64> [[VQDMLAL_V4_I_I]]
int64x2_t test_vqdmlal_high_n_s32(int64x2_t a, int32x4_t b, int32_t c) {
return vqdmlal_high_n_s32(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlsl_high_n_s16(<4 x i32> %a, <8 x i16> %b, i16 %c) #0 {
+// CHECK-LABEL: @test_vmlsl_high_n_s16(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[VECINIT_I_I:%.*]] = insertelement <4 x i16> undef, i16 %c, i32 0
// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <4 x i16> [[VECINIT_I_I]], i16 %c, i32 1
@@ -3354,31 +2964,27 @@ int64x2_t test_vqdmlal_high_n_s32(int64x2_t a, int32x4_t b, int32_t c) {
// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <4 x i16> [[VECINIT2_I_I]], i16 %c, i32 3
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[VECINIT3_I_I]] to <8 x i8>
-// CHECK: [[VMULL_I_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[VMULL_I_I_I]], <4 x i16> [[VMULL1_I_I_I]]) #2
+// CHECK: [[VMULL2_I_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[SHUFFLE_I_I]], <4 x i16> [[VECINIT3_I_I]]) #2
// CHECK: [[SUB_I_I:%.*]] = sub <4 x i32> %a, [[VMULL2_I_I_I]]
// CHECK: ret <4 x i32> [[SUB_I_I]]
int32x4_t test_vmlsl_high_n_s16(int32x4_t a, int16x8_t b, int16_t c) {
return vmlsl_high_n_s16(a, b, c);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlsl_high_n_s32(<2 x i64> %a, <4 x i32> %b, i32 %c) #0 {
+// CHECK-LABEL: @test_vmlsl_high_n_s32(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
// CHECK: [[VECINIT_I_I:%.*]] = insertelement <2 x i32> undef, i32 %c, i32 0
// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <2 x i32> [[VECINIT_I_I]], i32 %c, i32 1
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[VECINIT1_I_I]] to <8 x i8>
-// CHECK: [[VMULL_I_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[VMULL_I_I_I]], <2 x i32> [[VMULL1_I_I_I]]) #2
+// CHECK: [[VMULL2_I_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[SHUFFLE_I_I]], <2 x i32> [[VECINIT1_I_I]]) #2
// CHECK: [[SUB_I_I:%.*]] = sub <2 x i64> %a, [[VMULL2_I_I_I]]
// CHECK: ret <2 x i64> [[SUB_I_I]]
int64x2_t test_vmlsl_high_n_s32(int64x2_t a, int32x4_t b, int32_t c) {
return vmlsl_high_n_s32(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlsl_high_n_u16(<4 x i32> %a, <8 x i16> %b, i16 %c) #0 {
+// CHECK-LABEL: @test_vmlsl_high_n_u16(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[VECINIT_I_I:%.*]] = insertelement <4 x i16> undef, i16 %c, i32 0
// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <4 x i16> [[VECINIT_I_I]], i16 %c, i32 1
@@ -3386,31 +2992,27 @@ int64x2_t test_vmlsl_high_n_s32(int64x2_t a, int32x4_t b, int32_t c) {
// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <4 x i16> [[VECINIT2_I_I]], i16 %c, i32 3
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[VECINIT3_I_I]] to <8 x i8>
-// CHECK: [[VMULL_I_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[VMULL_I_I_I]], <4 x i16> [[VMULL1_I_I_I]]) #2
+// CHECK: [[VMULL2_I_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[SHUFFLE_I_I]], <4 x i16> [[VECINIT3_I_I]]) #2
// CHECK: [[SUB_I_I:%.*]] = sub <4 x i32> %a, [[VMULL2_I_I_I]]
// CHECK: ret <4 x i32> [[SUB_I_I]]
uint32x4_t test_vmlsl_high_n_u16(uint32x4_t a, uint16x8_t b, uint16_t c) {
return vmlsl_high_n_u16(a, b, c);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlsl_high_n_u32(<2 x i64> %a, <4 x i32> %b, i32 %c) #0 {
+// CHECK-LABEL: @test_vmlsl_high_n_u32(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
// CHECK: [[VECINIT_I_I:%.*]] = insertelement <2 x i32> undef, i32 %c, i32 0
// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <2 x i32> [[VECINIT_I_I]], i32 %c, i32 1
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[VECINIT1_I_I]] to <8 x i8>
-// CHECK: [[VMULL_I_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[VMULL_I_I_I]], <2 x i32> [[VMULL1_I_I_I]]) #2
+// CHECK: [[VMULL2_I_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[SHUFFLE_I_I]], <2 x i32> [[VECINIT1_I_I]]) #2
// CHECK: [[SUB_I_I:%.*]] = sub <2 x i64> %a, [[VMULL2_I_I_I]]
// CHECK: ret <2 x i64> [[SUB_I_I]]
uint64x2_t test_vmlsl_high_n_u32(uint64x2_t a, uint32x4_t b, uint32_t c) {
return vmlsl_high_n_u32(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vqdmlsl_high_n_s16(<4 x i32> %a, <8 x i16> %b, i16 %c) #0 {
+// CHECK-LABEL: @test_vqdmlsl_high_n_s16(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I]] to <8 x i8>
@@ -3419,34 +3021,28 @@ uint64x2_t test_vmlsl_high_n_u32(uint64x2_t a, uint32x4_t b, uint32_t c) {
// CHECK: [[VECINIT2_I_I:%.*]] = insertelement <4 x i16> [[VECINIT1_I_I]], i16 %c, i32 2
// CHECK: [[VECINIT3_I_I:%.*]] = insertelement <4 x i16> [[VECINIT2_I_I]], i16 %c, i32 3
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> [[VECINIT3_I_I]] to <8 x i8>
-// CHECK: [[VQDMLAL_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMLAL4_I_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VQDMLAL5_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[VQDMLAL_I_I]], <4 x i16> [[VQDMLAL4_I_I]]) #2
-// CHECK: [[VQDMLSL_V_I_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQDMLSL_V6_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqsub.v4i32(<4 x i32> [[VQDMLSL_V_I_I]], <4 x i32> [[VQDMLAL5_I_I]]) #2
+// CHECK: [[VQDMLAL5_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[SHUFFLE_I_I]], <4 x i16> [[VECINIT3_I_I]]) #2
+// CHECK: [[VQDMLSL_V6_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqsub.v4i32(<4 x i32> %a, <4 x i32> [[VQDMLAL5_I_I]]) #2
// CHECK: ret <4 x i32> [[VQDMLSL_V6_I_I]]
int32x4_t test_vqdmlsl_high_n_s16(int32x4_t a, int16x8_t b, int16_t c) {
return vqdmlsl_high_n_s16(a, b, c);
}
-// CHECK-LABEL: define <2 x i64> @test_vqdmlsl_high_n_s32(<2 x i64> %a, <4 x i32> %b, i32 %c) #0 {
+// CHECK-LABEL: @test_vqdmlsl_high_n_s32(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I]] to <8 x i8>
// CHECK: [[VECINIT_I_I:%.*]] = insertelement <2 x i32> undef, i32 %c, i32 0
// CHECK: [[VECINIT1_I_I:%.*]] = insertelement <2 x i32> [[VECINIT_I_I]], i32 %c, i32 1
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> [[VECINIT1_I_I]] to <8 x i8>
-// CHECK: [[VQDMLAL_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMLAL2_I_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VQDMLAL3_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[VQDMLAL_I_I]], <2 x i32> [[VQDMLAL2_I_I]]) #2
-// CHECK: [[VQDMLSL_V_I_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQDMLSL_V4_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqsub.v2i64(<2 x i64> [[VQDMLSL_V_I_I]], <2 x i64> [[VQDMLAL3_I_I]]) #2
+// CHECK: [[VQDMLAL3_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[SHUFFLE_I_I]], <2 x i32> [[VECINIT1_I_I]]) #2
+// CHECK: [[VQDMLSL_V4_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqsub.v2i64(<2 x i64> %a, <2 x i64> [[VQDMLAL3_I_I]]) #2
// CHECK: ret <2 x i64> [[VQDMLSL_V4_I_I]]
int64x2_t test_vqdmlsl_high_n_s32(int64x2_t a, int32x4_t b, int32_t c) {
return vqdmlsl_high_n_s32(a, b, c);
}
-// CHECK-LABEL: define <2 x float> @test_vmul_n_f32(<2 x float> %a, float %b) #0 {
+// CHECK-LABEL: @test_vmul_n_f32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x float> undef, float %b, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x float> [[VECINIT_I]], float %b, i32 1
// CHECK: [[MUL_I:%.*]] = fmul <2 x float> %a, [[VECINIT1_I]]
@@ -3455,7 +3051,7 @@ float32x2_t test_vmul_n_f32(float32x2_t a, float32_t b) {
return vmul_n_f32(a, b);
}
-// CHECK-LABEL: define <4 x float> @test_vmulq_n_f32(<4 x float> %a, float %b) #0 {
+// CHECK-LABEL: @test_vmulq_n_f32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x float> undef, float %b, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x float> [[VECINIT_I]], float %b, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x float> [[VECINIT1_I]], float %b, i32 2
@@ -3466,7 +3062,7 @@ float32x4_t test_vmulq_n_f32(float32x4_t a, float32_t b) {
return vmulq_n_f32(a, b);
}
-// CHECK-LABEL: define <2 x double> @test_vmulq_n_f64(<2 x double> %a, double %b) #0 {
+// CHECK-LABEL: @test_vmulq_n_f64(
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x double> undef, double %b, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x double> [[VECINIT_I]], double %b, i32 1
// CHECK: [[MUL_I:%.*]] = fmul <2 x double> %a, [[VECINIT1_I]]
@@ -3475,22 +3071,19 @@ float64x2_t test_vmulq_n_f64(float64x2_t a, float64_t b) {
return vmulq_n_f64(a, b);
}
-// CHECK-LABEL: define <2 x float> @test_vfma_n_f32(<2 x float> %a, <2 x float> %b, float %n) #0 {
+// CHECK-LABEL: @test_vfma_n_f32(
// 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: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// 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:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK: [[TMP5:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x float>
-// CHECK: [[TMP6:%.*]] = call <2 x float> @llvm.fma.v2f32(<2 x float> [[TMP4]], <2 x float> [[TMP5]], <2 x float> [[TMP3]]) #2
-// CHECK: ret <2 x float> [[TMP6]]
+// CHECK: [[TMP3:%.*]] = call <2 x float> @llvm.fma.v2f32(<2 x float> %b, <2 x float> [[VECINIT1_I]], <2 x float> %a) #2
+// 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-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
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x float> [[VECINIT1_I]], float %n, i32 2
@@ -3498,32 +3091,26 @@ float32x2_t test_vfma_n_f32(float32x2_t a, float32x2_t b, float32_t n) {
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// 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:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <4 x float>
-// CHECK: [[TMP6:%.*]] = call <4 x float> @llvm.fma.v4f32(<4 x float> [[TMP4]], <4 x float> [[TMP5]], <4 x float> [[TMP3]]) #2
-// CHECK: ret <4 x float> [[TMP6]]
+// CHECK: [[TMP3:%.*]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %b, <4 x float> [[VECINIT3_I]], <4 x float> %a) #2
+// 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);
}
-// CHECK-LABEL: define <2 x float> @test_vfms_n_f32(<2 x float> %a, <2 x float> %b, float %n) #0 {
+// CHECK-LABEL: @test_vfms_n_f32(
// CHECK: [[SUB_I:%.*]] = fsub <2 x float> <float -0.000000e+00, float -0.000000e+00>, %b
// 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: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> [[SUB_I]] to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x float> [[VECINIT1_I]] to <8 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK: [[TMP5:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x float>
-// CHECK: [[TMP6:%.*]] = call <2 x float> @llvm.fma.v2f32(<2 x float> [[TMP4]], <2 x float> [[TMP5]], <2 x float> [[TMP3]]) #2
-// CHECK: ret <2 x float> [[TMP6]]
+// CHECK: [[TMP3:%.*]] = call <2 x float> @llvm.fma.v2f32(<2 x float> [[SUB_I]], <2 x float> [[VECINIT1_I]], <2 x float> %a) #2
+// CHECK: ret <2 x float> [[TMP3]]
float32x2_t test_vfms_n_f32(float32x2_t a, float32x2_t b, float32_t n) {
return vfms_n_f32(a, b, n);
}
-// CHECK-LABEL: define <4 x float> @test_vfmsq_n_f32(<4 x float> %a, <4 x float> %b, float %n) #0 {
+// 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
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x float> [[VECINIT_I]], float %n, i32 1
@@ -3532,16 +3119,13 @@ float32x2_t test_vfms_n_f32(float32x2_t a, float32x2_t b, float32_t n) {
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> [[SUB_I]] to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x float> [[VECINIT3_I]] to <16 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <4 x float>
-// CHECK: [[TMP6:%.*]] = call <4 x float> @llvm.fma.v4f32(<4 x float> [[TMP4]], <4 x float> [[TMP5]], <4 x float> [[TMP3]]) #2
-// CHECK: ret <4 x float> [[TMP6]]
+// CHECK: [[TMP3:%.*]] = call <4 x float> @llvm.fma.v4f32(<4 x float> [[SUB_I]], <4 x float> [[VECINIT3_I]], <4 x float> %a) #2
+// CHECK: ret <4 x float> [[TMP3]]
float32x4_t test_vfmsq_n_f32(float32x4_t a, float32x4_t b, float32_t n) {
return vfmsq_n_f32(a, b, n);
}
-// CHECK-LABEL: define <4 x i16> @test_vmul_n_s16(<4 x i16> %a, i16 %b) #0 {
+// CHECK-LABEL: @test_vmul_n_s16(
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i16> undef, i16 %b, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i16> [[VECINIT_I]], i16 %b, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i16> [[VECINIT1_I]], i16 %b, i32 2
@@ -3552,7 +3136,7 @@ int16x4_t test_vmul_n_s16(int16x4_t a, int16_t b) {
return vmul_n_s16(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vmulq_n_s16(<8 x i16> %a, i16 %b) #0 {
+// CHECK-LABEL: @test_vmulq_n_s16(
// CHECK: [[VECINIT_I:%.*]] = insertelement <8 x i16> undef, i16 %b, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <8 x i16> [[VECINIT_I]], i16 %b, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <8 x i16> [[VECINIT1_I]], i16 %b, i32 2
@@ -3567,7 +3151,7 @@ int16x8_t test_vmulq_n_s16(int16x8_t a, int16_t b) {
return vmulq_n_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vmul_n_s32(<2 x i32> %a, i32 %b) #0 {
+// CHECK-LABEL: @test_vmul_n_s32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x i32> undef, i32 %b, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x i32> [[VECINIT_I]], i32 %b, i32 1
// CHECK: [[MUL_I:%.*]] = mul <2 x i32> %a, [[VECINIT1_I]]
@@ -3576,7 +3160,7 @@ int32x2_t test_vmul_n_s32(int32x2_t a, int32_t b) {
return vmul_n_s32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vmulq_n_s32(<4 x i32> %a, i32 %b) #0 {
+// CHECK-LABEL: @test_vmulq_n_s32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i32> undef, i32 %b, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i32> [[VECINIT_I]], i32 %b, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i32> [[VECINIT1_I]], i32 %b, i32 2
@@ -3587,7 +3171,7 @@ int32x4_t test_vmulq_n_s32(int32x4_t a, int32_t b) {
return vmulq_n_s32(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vmul_n_u16(<4 x i16> %a, i16 %b) #0 {
+// CHECK-LABEL: @test_vmul_n_u16(
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i16> undef, i16 %b, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i16> [[VECINIT_I]], i16 %b, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i16> [[VECINIT1_I]], i16 %b, i32 2
@@ -3598,7 +3182,7 @@ uint16x4_t test_vmul_n_u16(uint16x4_t a, uint16_t b) {
return vmul_n_u16(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vmulq_n_u16(<8 x i16> %a, i16 %b) #0 {
+// CHECK-LABEL: @test_vmulq_n_u16(
// CHECK: [[VECINIT_I:%.*]] = insertelement <8 x i16> undef, i16 %b, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <8 x i16> [[VECINIT_I]], i16 %b, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <8 x i16> [[VECINIT1_I]], i16 %b, i32 2
@@ -3613,7 +3197,7 @@ uint16x8_t test_vmulq_n_u16(uint16x8_t a, uint16_t b) {
return vmulq_n_u16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vmul_n_u32(<2 x i32> %a, i32 %b) #0 {
+// CHECK-LABEL: @test_vmul_n_u32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x i32> undef, i32 %b, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x i32> [[VECINIT_I]], i32 %b, i32 1
// CHECK: [[MUL_I:%.*]] = mul <2 x i32> %a, [[VECINIT1_I]]
@@ -3622,7 +3206,7 @@ uint32x2_t test_vmul_n_u32(uint32x2_t a, uint32_t b) {
return vmul_n_u32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vmulq_n_u32(<4 x i32> %a, i32 %b) #0 {
+// CHECK-LABEL: @test_vmulq_n_u32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i32> undef, i32 %b, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i32> [[VECINIT_I]], i32 %b, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i32> [[VECINIT1_I]], i32 %b, i32 2
@@ -3633,112 +3217,95 @@ uint32x4_t test_vmulq_n_u32(uint32x4_t a, uint32_t b) {
return vmulq_n_u32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vmull_n_s16(<4 x i16> %a, i16 %b) #0 {
+// CHECK-LABEL: @test_vmull_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i16> undef, i16 %b, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i16> [[VECINIT_I]], i16 %b, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i16> [[VECINIT1_I]], i16 %b, i32 2
// CHECK: [[VECINIT3_I:%.*]] = insertelement <4 x i16> [[VECINIT2_I]], i16 %b, i32 3
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[VECINIT3_I]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL4_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL5_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL4_I]]) #2
+// CHECK: [[VMULL5_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> %a, <4 x i16> [[VECINIT3_I]]) #2
// CHECK: ret <4 x i32> [[VMULL5_I]]
int32x4_t test_vmull_n_s16(int16x4_t a, int16_t b) {
return vmull_n_s16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vmull_n_s32(<2 x i32> %a, i32 %b) #0 {
+// CHECK-LABEL: @test_vmull_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x i32> undef, i32 %b, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x i32> [[VECINIT_I]], i32 %b, i32 1
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[VECINIT1_I]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL3_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL2_I]]) #2
+// CHECK: [[VMULL3_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> %a, <2 x i32> [[VECINIT1_I]]) #2
// CHECK: ret <2 x i64> [[VMULL3_I]]
int64x2_t test_vmull_n_s32(int32x2_t a, int32_t b) {
return vmull_n_s32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vmull_n_u16(<4 x i16> %a, i16 %b) #0 {
+// CHECK-LABEL: @test_vmull_n_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i16> undef, i16 %b, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i16> [[VECINIT_I]], i16 %b, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i16> [[VECINIT1_I]], i16 %b, i32 2
// CHECK: [[VECINIT3_I:%.*]] = insertelement <4 x i16> [[VECINIT2_I]], i16 %b, i32 3
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[VECINIT3_I]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL4_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL5_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL4_I]]) #2
+// CHECK: [[VMULL5_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> %a, <4 x i16> [[VECINIT3_I]]) #2
// CHECK: ret <4 x i32> [[VMULL5_I]]
uint32x4_t test_vmull_n_u16(uint16x4_t a, uint16_t b) {
return vmull_n_u16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vmull_n_u32(<2 x i32> %a, i32 %b) #0 {
+// CHECK-LABEL: @test_vmull_n_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x i32> undef, i32 %b, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x i32> [[VECINIT_I]], i32 %b, i32 1
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[VECINIT1_I]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL3_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL2_I]]) #2
+// CHECK: [[VMULL3_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> %a, <2 x i32> [[VECINIT1_I]]) #2
// CHECK: ret <2 x i64> [[VMULL3_I]]
uint64x2_t test_vmull_n_u32(uint32x2_t a, uint32_t b) {
return vmull_n_u32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vqdmull_n_s16(<4 x i16> %a, i16 %b) #0 {
+// CHECK-LABEL: @test_vqdmull_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i16> undef, i16 %b, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i16> [[VECINIT_I]], i16 %b, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i16> [[VECINIT1_I]], i16 %b, i32 2
// CHECK: [[VECINIT3_I:%.*]] = insertelement <4 x i16> [[VECINIT2_I]], i16 %b, i32 3
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[VECINIT3_I]] to <8 x i8>
-// CHECK: [[VQDMULL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQDMULL_V4_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMULL_V5_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[VQDMULL_V_I]], <4 x i16> [[VQDMULL_V4_I]]) #2
+// CHECK: [[VQDMULL_V5_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> %a, <4 x i16> [[VECINIT3_I]]) #2
// CHECK: [[VQDMULL_V6_I:%.*]] = bitcast <4 x i32> [[VQDMULL_V5_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQDMULL_V6_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VQDMULL_V5_I]]
int32x4_t test_vqdmull_n_s16(int16x4_t a, int16_t b) {
return vqdmull_n_s16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vqdmull_n_s32(<2 x i32> %a, i32 %b) #0 {
+// CHECK-LABEL: @test_vqdmull_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x i32> undef, i32 %b, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x i32> [[VECINIT_I]], i32 %b, i32 1
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[VECINIT1_I]] to <8 x i8>
-// CHECK: [[VQDMULL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQDMULL_V2_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMULL_V3_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[VQDMULL_V_I]], <2 x i32> [[VQDMULL_V2_I]]) #2
+// CHECK: [[VQDMULL_V3_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> %a, <2 x i32> [[VECINIT1_I]]) #2
// CHECK: [[VQDMULL_V4_I:%.*]] = bitcast <2 x i64> [[VQDMULL_V3_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQDMULL_V4_I]] to <2 x i64>
-// CHECK: ret <2 x i64> [[TMP2]]
+// CHECK: ret <2 x i64> [[VQDMULL_V3_I]]
int64x2_t test_vqdmull_n_s32(int32x2_t a, int32_t b) {
return vqdmull_n_s32(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vqdmulh_n_s16(<4 x i16> %a, i16 %b) #0 {
+// CHECK-LABEL: @test_vqdmulh_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i16> undef, i16 %b, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i16> [[VECINIT_I]], i16 %b, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i16> [[VECINIT1_I]], i16 %b, i32 2
// CHECK: [[VECINIT3_I:%.*]] = insertelement <4 x i16> [[VECINIT2_I]], i16 %b, i32 3
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[VECINIT3_I]] to <8 x i8>
-// CHECK: [[VQDMULH_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQDMULH_V4_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMULH_V5_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqdmulh.v4i16(<4 x i16> [[VQDMULH_V_I]], <4 x i16> [[VQDMULH_V4_I]]) #2
+// CHECK: [[VQDMULH_V5_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqdmulh.v4i16(<4 x i16> %a, <4 x i16> [[VECINIT3_I]]) #2
// CHECK: [[VQDMULH_V6_I:%.*]] = bitcast <4 x i16> [[VQDMULH_V5_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQDMULH_V6_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VQDMULH_V5_I]]
int16x4_t test_vqdmulh_n_s16(int16x4_t a, int16_t b) {
return vqdmulh_n_s16(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vqdmulhq_n_s16(<8 x i16> %a, i16 %b) #0 {
+// CHECK-LABEL: @test_vqdmulhq_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[VECINIT_I:%.*]] = insertelement <8 x i16> undef, i16 %b, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <8 x i16> [[VECINIT_I]], i16 %b, i32 1
@@ -3749,66 +3316,54 @@ int16x4_t test_vqdmulh_n_s16(int16x4_t a, int16_t b) {
// CHECK: [[VECINIT6_I:%.*]] = insertelement <8 x i16> [[VECINIT5_I]], i16 %b, i32 6
// CHECK: [[VECINIT7_I:%.*]] = insertelement <8 x i16> [[VECINIT6_I]], i16 %b, i32 7
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> [[VECINIT7_I]] to <16 x i8>
-// CHECK: [[VQDMULHQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VQDMULHQ_V8_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VQDMULHQ_V9_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.sqdmulh.v8i16(<8 x i16> [[VQDMULHQ_V_I]], <8 x i16> [[VQDMULHQ_V8_I]]) #2
+// CHECK: [[VQDMULHQ_V9_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.sqdmulh.v8i16(<8 x i16> %a, <8 x i16> [[VECINIT7_I]]) #2
// CHECK: [[VQDMULHQ_V10_I:%.*]] = bitcast <8 x i16> [[VQDMULHQ_V9_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQDMULHQ_V10_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VQDMULHQ_V9_I]]
int16x8_t test_vqdmulhq_n_s16(int16x8_t a, int16_t b) {
return vqdmulhq_n_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vqdmulh_n_s32(<2 x i32> %a, i32 %b) #0 {
+// CHECK-LABEL: @test_vqdmulh_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x i32> undef, i32 %b, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x i32> [[VECINIT_I]], i32 %b, i32 1
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[VECINIT1_I]] to <8 x i8>
-// CHECK: [[VQDMULH_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQDMULH_V2_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMULH_V3_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqdmulh.v2i32(<2 x i32> [[VQDMULH_V_I]], <2 x i32> [[VQDMULH_V2_I]]) #2
+// CHECK: [[VQDMULH_V3_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqdmulh.v2i32(<2 x i32> %a, <2 x i32> [[VECINIT1_I]]) #2
// CHECK: [[VQDMULH_V4_I:%.*]] = bitcast <2 x i32> [[VQDMULH_V3_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQDMULH_V4_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VQDMULH_V3_I]]
int32x2_t test_vqdmulh_n_s32(int32x2_t a, int32_t b) {
return vqdmulh_n_s32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vqdmulhq_n_s32(<4 x i32> %a, i32 %b) #0 {
+// CHECK-LABEL: @test_vqdmulhq_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i32> undef, i32 %b, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i32> [[VECINIT_I]], i32 %b, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i32> [[VECINIT1_I]], i32 %b, i32 2
// CHECK: [[VECINIT3_I:%.*]] = insertelement <4 x i32> [[VECINIT2_I]], i32 %b, i32 3
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> [[VECINIT3_I]] to <16 x i8>
-// CHECK: [[VQDMULHQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQDMULHQ_V4_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VQDMULHQ_V5_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmulh.v4i32(<4 x i32> [[VQDMULHQ_V_I]], <4 x i32> [[VQDMULHQ_V4_I]]) #2
+// CHECK: [[VQDMULHQ_V5_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmulh.v4i32(<4 x i32> %a, <4 x i32> [[VECINIT3_I]]) #2
// CHECK: [[VQDMULHQ_V6_I:%.*]] = bitcast <4 x i32> [[VQDMULHQ_V5_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQDMULHQ_V6_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VQDMULHQ_V5_I]]
int32x4_t test_vqdmulhq_n_s32(int32x4_t a, int32_t b) {
return vqdmulhq_n_s32(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vqrdmulh_n_s16(<4 x i16> %a, i16 %b) #0 {
+// CHECK-LABEL: @test_vqrdmulh_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i16> undef, i16 %b, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i16> [[VECINIT_I]], i16 %b, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i16> [[VECINIT1_I]], i16 %b, i32 2
// CHECK: [[VECINIT3_I:%.*]] = insertelement <4 x i16> [[VECINIT2_I]], i16 %b, i32 3
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[VECINIT3_I]] to <8 x i8>
-// CHECK: [[VQRDMULH_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQRDMULH_V4_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQRDMULH_V5_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqrdmulh.v4i16(<4 x i16> [[VQRDMULH_V_I]], <4 x i16> [[VQRDMULH_V4_I]]) #2
+// CHECK: [[VQRDMULH_V5_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqrdmulh.v4i16(<4 x i16> %a, <4 x i16> [[VECINIT3_I]]) #2
// CHECK: [[VQRDMULH_V6_I:%.*]] = bitcast <4 x i16> [[VQRDMULH_V5_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQRDMULH_V6_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VQRDMULH_V5_I]]
int16x4_t test_vqrdmulh_n_s16(int16x4_t a, int16_t b) {
return vqrdmulh_n_s16(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vqrdmulhq_n_s16(<8 x i16> %a, i16 %b) #0 {
+// CHECK-LABEL: @test_vqrdmulhq_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[VECINIT_I:%.*]] = insertelement <8 x i16> undef, i16 %b, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <8 x i16> [[VECINIT_I]], i16 %b, i32 1
@@ -3819,49 +3374,40 @@ int16x4_t test_vqrdmulh_n_s16(int16x4_t a, int16_t b) {
// CHECK: [[VECINIT6_I:%.*]] = insertelement <8 x i16> [[VECINIT5_I]], i16 %b, i32 6
// CHECK: [[VECINIT7_I:%.*]] = insertelement <8 x i16> [[VECINIT6_I]], i16 %b, i32 7
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> [[VECINIT7_I]] to <16 x i8>
-// CHECK: [[VQRDMULHQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VQRDMULHQ_V8_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VQRDMULHQ_V9_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.sqrdmulh.v8i16(<8 x i16> [[VQRDMULHQ_V_I]], <8 x i16> [[VQRDMULHQ_V8_I]]) #2
+// CHECK: [[VQRDMULHQ_V9_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.sqrdmulh.v8i16(<8 x i16> %a, <8 x i16> [[VECINIT7_I]]) #2
// CHECK: [[VQRDMULHQ_V10_I:%.*]] = bitcast <8 x i16> [[VQRDMULHQ_V9_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQRDMULHQ_V10_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VQRDMULHQ_V9_I]]
int16x8_t test_vqrdmulhq_n_s16(int16x8_t a, int16_t b) {
return vqrdmulhq_n_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vqrdmulh_n_s32(<2 x i32> %a, i32 %b) #0 {
+// CHECK-LABEL: @test_vqrdmulh_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x i32> undef, i32 %b, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x i32> [[VECINIT_I]], i32 %b, i32 1
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[VECINIT1_I]] to <8 x i8>
-// CHECK: [[VQRDMULH_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQRDMULH_V2_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQRDMULH_V3_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqrdmulh.v2i32(<2 x i32> [[VQRDMULH_V_I]], <2 x i32> [[VQRDMULH_V2_I]]) #2
+// CHECK: [[VQRDMULH_V3_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqrdmulh.v2i32(<2 x i32> %a, <2 x i32> [[VECINIT1_I]]) #2
// CHECK: [[VQRDMULH_V4_I:%.*]] = bitcast <2 x i32> [[VQRDMULH_V3_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQRDMULH_V4_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VQRDMULH_V3_I]]
int32x2_t test_vqrdmulh_n_s32(int32x2_t a, int32_t b) {
return vqrdmulh_n_s32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vqrdmulhq_n_s32(<4 x i32> %a, i32 %b) #0 {
+// CHECK-LABEL: @test_vqrdmulhq_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i32> undef, i32 %b, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i32> [[VECINIT_I]], i32 %b, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i32> [[VECINIT1_I]], i32 %b, i32 2
// CHECK: [[VECINIT3_I:%.*]] = insertelement <4 x i32> [[VECINIT2_I]], i32 %b, i32 3
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> [[VECINIT3_I]] to <16 x i8>
-// CHECK: [[VQRDMULHQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQRDMULHQ_V4_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VQRDMULHQ_V5_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqrdmulh.v4i32(<4 x i32> [[VQRDMULHQ_V_I]], <4 x i32> [[VQRDMULHQ_V4_I]]) #2
+// CHECK: [[VQRDMULHQ_V5_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqrdmulh.v4i32(<4 x i32> %a, <4 x i32> [[VECINIT3_I]]) #2
// CHECK: [[VQRDMULHQ_V6_I:%.*]] = bitcast <4 x i32> [[VQRDMULHQ_V5_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQRDMULHQ_V6_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VQRDMULHQ_V5_I]]
int32x4_t test_vqrdmulhq_n_s32(int32x4_t a, int32_t b) {
return vqrdmulhq_n_s32(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vmla_n_s16(<4 x i16> %a, <4 x i16> %b, i16 %c) #0 {
+// CHECK-LABEL: @test_vmla_n_s16(
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i16> undef, i16 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i16> [[VECINIT_I]], i16 %c, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i16> [[VECINIT1_I]], i16 %c, i32 2
@@ -3873,7 +3419,7 @@ int16x4_t test_vmla_n_s16(int16x4_t a, int16x4_t b, int16_t c) {
return vmla_n_s16(a, b, c);
}
-// CHECK-LABEL: define <8 x i16> @test_vmlaq_n_s16(<8 x i16> %a, <8 x i16> %b, i16 %c) #0 {
+// CHECK-LABEL: @test_vmlaq_n_s16(
// CHECK: [[VECINIT_I:%.*]] = insertelement <8 x i16> undef, i16 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <8 x i16> [[VECINIT_I]], i16 %c, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <8 x i16> [[VECINIT1_I]], i16 %c, i32 2
@@ -3889,7 +3435,7 @@ int16x8_t test_vmlaq_n_s16(int16x8_t a, int16x8_t b, int16_t c) {
return vmlaq_n_s16(a, b, c);
}
-// CHECK-LABEL: define <2 x i32> @test_vmla_n_s32(<2 x i32> %a, <2 x i32> %b, i32 %c) #0 {
+// CHECK-LABEL: @test_vmla_n_s32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x i32> undef, i32 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x i32> [[VECINIT_I]], i32 %c, i32 1
// CHECK: [[MUL_I:%.*]] = mul <2 x i32> %b, [[VECINIT1_I]]
@@ -3899,7 +3445,7 @@ int32x2_t test_vmla_n_s32(int32x2_t a, int32x2_t b, int32_t c) {
return vmla_n_s32(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlaq_n_s32(<4 x i32> %a, <4 x i32> %b, i32 %c) #0 {
+// CHECK-LABEL: @test_vmlaq_n_s32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i32> undef, i32 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i32> [[VECINIT_I]], i32 %c, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i32> [[VECINIT1_I]], i32 %c, i32 2
@@ -3911,7 +3457,7 @@ int32x4_t test_vmlaq_n_s32(int32x4_t a, int32x4_t b, int32_t c) {
return vmlaq_n_s32(a, b, c);
}
-// CHECK-LABEL: define <4 x i16> @test_vmla_n_u16(<4 x i16> %a, <4 x i16> %b, i16 %c) #0 {
+// CHECK-LABEL: @test_vmla_n_u16(
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i16> undef, i16 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i16> [[VECINIT_I]], i16 %c, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i16> [[VECINIT1_I]], i16 %c, i32 2
@@ -3923,7 +3469,7 @@ uint16x4_t test_vmla_n_u16(uint16x4_t a, uint16x4_t b, uint16_t c) {
return vmla_n_u16(a, b, c);
}
-// CHECK-LABEL: define <8 x i16> @test_vmlaq_n_u16(<8 x i16> %a, <8 x i16> %b, i16 %c) #0 {
+// CHECK-LABEL: @test_vmlaq_n_u16(
// CHECK: [[VECINIT_I:%.*]] = insertelement <8 x i16> undef, i16 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <8 x i16> [[VECINIT_I]], i16 %c, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <8 x i16> [[VECINIT1_I]], i16 %c, i32 2
@@ -3939,7 +3485,7 @@ uint16x8_t test_vmlaq_n_u16(uint16x8_t a, uint16x8_t b, uint16_t c) {
return vmlaq_n_u16(a, b, c);
}
-// CHECK-LABEL: define <2 x i32> @test_vmla_n_u32(<2 x i32> %a, <2 x i32> %b, i32 %c) #0 {
+// CHECK-LABEL: @test_vmla_n_u32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x i32> undef, i32 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x i32> [[VECINIT_I]], i32 %c, i32 1
// CHECK: [[MUL_I:%.*]] = mul <2 x i32> %b, [[VECINIT1_I]]
@@ -3949,7 +3495,7 @@ uint32x2_t test_vmla_n_u32(uint32x2_t a, uint32x2_t b, uint32_t c) {
return vmla_n_u32(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlaq_n_u32(<4 x i32> %a, <4 x i32> %b, i32 %c) #0 {
+// CHECK-LABEL: @test_vmlaq_n_u32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i32> undef, i32 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i32> [[VECINIT_I]], i32 %c, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i32> [[VECINIT1_I]], i32 %c, i32 2
@@ -3961,67 +3507,59 @@ uint32x4_t test_vmlaq_n_u32(uint32x4_t a, uint32x4_t b, uint32_t c) {
return vmlaq_n_u32(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlal_n_s16(<4 x i32> %a, <4 x i16> %b, i16 %c) #0 {
+// CHECK-LABEL: @test_vmlal_n_s16(
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i16> undef, i16 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i16> [[VECINIT_I]], i16 %c, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i16> [[VECINIT1_I]], i16 %c, i32 2
// CHECK: [[VECINIT3_I:%.*]] = insertelement <4 x i16> [[VECINIT2_I]], i16 %c, i32 3
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[VECINIT3_I]] to <8 x i8>
-// CHECK: [[VMULL_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[VMULL_I_I]], <4 x i16> [[VMULL1_I_I]]) #2
+// CHECK: [[VMULL2_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> %b, <4 x i16> [[VECINIT3_I]]) #2
// CHECK: [[ADD_I:%.*]] = add <4 x i32> %a, [[VMULL2_I_I]]
// CHECK: ret <4 x i32> [[ADD_I]]
int32x4_t test_vmlal_n_s16(int32x4_t a, int16x4_t b, int16_t c) {
return vmlal_n_s16(a, b, c);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlal_n_s32(<2 x i64> %a, <2 x i32> %b, i32 %c) #0 {
+// CHECK-LABEL: @test_vmlal_n_s32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x i32> undef, i32 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x i32> [[VECINIT_I]], i32 %c, i32 1
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[VECINIT1_I]] to <8 x i8>
-// CHECK: [[VMULL_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[VMULL_I_I]], <2 x i32> [[VMULL1_I_I]]) #2
+// CHECK: [[VMULL2_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> %b, <2 x i32> [[VECINIT1_I]]) #2
// CHECK: [[ADD_I:%.*]] = add <2 x i64> %a, [[VMULL2_I_I]]
// CHECK: ret <2 x i64> [[ADD_I]]
int64x2_t test_vmlal_n_s32(int64x2_t a, int32x2_t b, int32_t c) {
return vmlal_n_s32(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlal_n_u16(<4 x i32> %a, <4 x i16> %b, i16 %c) #0 {
+// CHECK-LABEL: @test_vmlal_n_u16(
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i16> undef, i16 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i16> [[VECINIT_I]], i16 %c, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i16> [[VECINIT1_I]], i16 %c, i32 2
// CHECK: [[VECINIT3_I:%.*]] = insertelement <4 x i16> [[VECINIT2_I]], i16 %c, i32 3
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[VECINIT3_I]] to <8 x i8>
-// CHECK: [[VMULL_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[VMULL_I_I]], <4 x i16> [[VMULL1_I_I]]) #2
+// CHECK: [[VMULL2_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> %b, <4 x i16> [[VECINIT3_I]]) #2
// CHECK: [[ADD_I:%.*]] = add <4 x i32> %a, [[VMULL2_I_I]]
// CHECK: ret <4 x i32> [[ADD_I]]
uint32x4_t test_vmlal_n_u16(uint32x4_t a, uint16x4_t b, uint16_t c) {
return vmlal_n_u16(a, b, c);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlal_n_u32(<2 x i64> %a, <2 x i32> %b, i32 %c) #0 {
+// CHECK-LABEL: @test_vmlal_n_u32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x i32> undef, i32 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x i32> [[VECINIT_I]], i32 %c, i32 1
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[VECINIT1_I]] to <8 x i8>
-// CHECK: [[VMULL_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[VMULL_I_I]], <2 x i32> [[VMULL1_I_I]]) #2
+// CHECK: [[VMULL2_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> %b, <2 x i32> [[VECINIT1_I]]) #2
// CHECK: [[ADD_I:%.*]] = add <2 x i64> %a, [[VMULL2_I_I]]
// CHECK: ret <2 x i64> [[ADD_I]]
uint64x2_t test_vmlal_n_u32(uint64x2_t a, uint32x2_t b, uint32_t c) {
return vmlal_n_u32(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vqdmlal_n_s16(<4 x i32> %a, <4 x i16> %b, i16 %c) #0 {
+// CHECK-LABEL: @test_vqdmlal_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i16> undef, i16 %c, i32 0
@@ -4029,33 +3567,27 @@ uint64x2_t test_vmlal_n_u32(uint64x2_t a, uint32x2_t b, uint32_t c) {
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i16> [[VECINIT1_I]], i16 %c, i32 2
// CHECK: [[VECINIT3_I:%.*]] = insertelement <4 x i16> [[VECINIT2_I]], i16 %c, i32 3
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> [[VECINIT3_I]] to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMLAL4_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VQDMLAL5_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[VQDMLAL_I]], <4 x i16> [[VQDMLAL4_I]]) #2
-// CHECK: [[VQDMLAL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQDMLAL_V6_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqadd.v4i32(<4 x i32> [[VQDMLAL_V_I]], <4 x i32> [[VQDMLAL5_I]]) #2
+// CHECK: [[VQDMLAL5_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> %b, <4 x i16> [[VECINIT3_I]]) #2
+// CHECK: [[VQDMLAL_V6_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqadd.v4i32(<4 x i32> %a, <4 x i32> [[VQDMLAL5_I]]) #2
// CHECK: ret <4 x i32> [[VQDMLAL_V6_I]]
int32x4_t test_vqdmlal_n_s16(int32x4_t a, int16x4_t b, int16_t c) {
return vqdmlal_n_s16(a, b, c);
}
-// CHECK-LABEL: define <2 x i64> @test_vqdmlal_n_s32(<2 x i64> %a, <2 x i32> %b, i32 %c) #0 {
+// CHECK-LABEL: @test_vqdmlal_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x i32> undef, i32 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x i32> [[VECINIT_I]], i32 %c, i32 1
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> [[VECINIT1_I]] to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMLAL2_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VQDMLAL3_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[VQDMLAL_I]], <2 x i32> [[VQDMLAL2_I]]) #2
-// CHECK: [[VQDMLAL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQDMLAL_V4_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqadd.v2i64(<2 x i64> [[VQDMLAL_V_I]], <2 x i64> [[VQDMLAL3_I]]) #2
+// CHECK: [[VQDMLAL3_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> %b, <2 x i32> [[VECINIT1_I]]) #2
+// CHECK: [[VQDMLAL_V4_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqadd.v2i64(<2 x i64> %a, <2 x i64> [[VQDMLAL3_I]]) #2
// CHECK: ret <2 x i64> [[VQDMLAL_V4_I]]
int64x2_t test_vqdmlal_n_s32(int64x2_t a, int32x2_t b, int32_t c) {
return vqdmlal_n_s32(a, b, c);
}
-// CHECK-LABEL: define <4 x i16> @test_vmls_n_s16(<4 x i16> %a, <4 x i16> %b, i16 %c) #0 {
+// CHECK-LABEL: @test_vmls_n_s16(
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i16> undef, i16 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i16> [[VECINIT_I]], i16 %c, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i16> [[VECINIT1_I]], i16 %c, i32 2
@@ -4067,7 +3599,7 @@ int16x4_t test_vmls_n_s16(int16x4_t a, int16x4_t b, int16_t c) {
return vmls_n_s16(a, b, c);
}
-// CHECK-LABEL: define <8 x i16> @test_vmlsq_n_s16(<8 x i16> %a, <8 x i16> %b, i16 %c) #0 {
+// CHECK-LABEL: @test_vmlsq_n_s16(
// CHECK: [[VECINIT_I:%.*]] = insertelement <8 x i16> undef, i16 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <8 x i16> [[VECINIT_I]], i16 %c, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <8 x i16> [[VECINIT1_I]], i16 %c, i32 2
@@ -4083,7 +3615,7 @@ int16x8_t test_vmlsq_n_s16(int16x8_t a, int16x8_t b, int16_t c) {
return vmlsq_n_s16(a, b, c);
}
-// CHECK-LABEL: define <2 x i32> @test_vmls_n_s32(<2 x i32> %a, <2 x i32> %b, i32 %c) #0 {
+// CHECK-LABEL: @test_vmls_n_s32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x i32> undef, i32 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x i32> [[VECINIT_I]], i32 %c, i32 1
// CHECK: [[MUL_I:%.*]] = mul <2 x i32> %b, [[VECINIT1_I]]
@@ -4093,7 +3625,7 @@ int32x2_t test_vmls_n_s32(int32x2_t a, int32x2_t b, int32_t c) {
return vmls_n_s32(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlsq_n_s32(<4 x i32> %a, <4 x i32> %b, i32 %c) #0 {
+// CHECK-LABEL: @test_vmlsq_n_s32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i32> undef, i32 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i32> [[VECINIT_I]], i32 %c, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i32> [[VECINIT1_I]], i32 %c, i32 2
@@ -4105,7 +3637,7 @@ int32x4_t test_vmlsq_n_s32(int32x4_t a, int32x4_t b, int32_t c) {
return vmlsq_n_s32(a, b, c);
}
-// CHECK-LABEL: define <4 x i16> @test_vmls_n_u16(<4 x i16> %a, <4 x i16> %b, i16 %c) #0 {
+// CHECK-LABEL: @test_vmls_n_u16(
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i16> undef, i16 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i16> [[VECINIT_I]], i16 %c, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i16> [[VECINIT1_I]], i16 %c, i32 2
@@ -4117,7 +3649,7 @@ uint16x4_t test_vmls_n_u16(uint16x4_t a, uint16x4_t b, uint16_t c) {
return vmls_n_u16(a, b, c);
}
-// CHECK-LABEL: define <8 x i16> @test_vmlsq_n_u16(<8 x i16> %a, <8 x i16> %b, i16 %c) #0 {
+// CHECK-LABEL: @test_vmlsq_n_u16(
// CHECK: [[VECINIT_I:%.*]] = insertelement <8 x i16> undef, i16 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <8 x i16> [[VECINIT_I]], i16 %c, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <8 x i16> [[VECINIT1_I]], i16 %c, i32 2
@@ -4133,7 +3665,7 @@ uint16x8_t test_vmlsq_n_u16(uint16x8_t a, uint16x8_t b, uint16_t c) {
return vmlsq_n_u16(a, b, c);
}
-// CHECK-LABEL: define <2 x i32> @test_vmls_n_u32(<2 x i32> %a, <2 x i32> %b, i32 %c) #0 {
+// CHECK-LABEL: @test_vmls_n_u32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x i32> undef, i32 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x i32> [[VECINIT_I]], i32 %c, i32 1
// CHECK: [[MUL_I:%.*]] = mul <2 x i32> %b, [[VECINIT1_I]]
@@ -4143,7 +3675,7 @@ uint32x2_t test_vmls_n_u32(uint32x2_t a, uint32x2_t b, uint32_t c) {
return vmls_n_u32(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlsq_n_u32(<4 x i32> %a, <4 x i32> %b, i32 %c) #0 {
+// CHECK-LABEL: @test_vmlsq_n_u32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i32> undef, i32 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i32> [[VECINIT_I]], i32 %c, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i32> [[VECINIT1_I]], i32 %c, i32 2
@@ -4155,67 +3687,59 @@ uint32x4_t test_vmlsq_n_u32(uint32x4_t a, uint32x4_t b, uint32_t c) {
return vmlsq_n_u32(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlsl_n_s16(<4 x i32> %a, <4 x i16> %b, i16 %c) #0 {
+// CHECK-LABEL: @test_vmlsl_n_s16(
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i16> undef, i16 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i16> [[VECINIT_I]], i16 %c, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i16> [[VECINIT1_I]], i16 %c, i32 2
// CHECK: [[VECINIT3_I:%.*]] = insertelement <4 x i16> [[VECINIT2_I]], i16 %c, i32 3
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[VECINIT3_I]] to <8 x i8>
-// CHECK: [[VMULL_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[VMULL_I_I]], <4 x i16> [[VMULL1_I_I]]) #2
+// CHECK: [[VMULL2_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> %b, <4 x i16> [[VECINIT3_I]]) #2
// CHECK: [[SUB_I:%.*]] = sub <4 x i32> %a, [[VMULL2_I_I]]
// CHECK: ret <4 x i32> [[SUB_I]]
int32x4_t test_vmlsl_n_s16(int32x4_t a, int16x4_t b, int16_t c) {
return vmlsl_n_s16(a, b, c);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlsl_n_s32(<2 x i64> %a, <2 x i32> %b, i32 %c) #0 {
+// CHECK-LABEL: @test_vmlsl_n_s32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x i32> undef, i32 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x i32> [[VECINIT_I]], i32 %c, i32 1
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[VECINIT1_I]] to <8 x i8>
-// CHECK: [[VMULL_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[VMULL_I_I]], <2 x i32> [[VMULL1_I_I]]) #2
+// CHECK: [[VMULL2_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> %b, <2 x i32> [[VECINIT1_I]]) #2
// CHECK: [[SUB_I:%.*]] = sub <2 x i64> %a, [[VMULL2_I_I]]
// CHECK: ret <2 x i64> [[SUB_I]]
int64x2_t test_vmlsl_n_s32(int64x2_t a, int32x2_t b, int32_t c) {
return vmlsl_n_s32(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlsl_n_u16(<4 x i32> %a, <4 x i16> %b, i16 %c) #0 {
+// CHECK-LABEL: @test_vmlsl_n_u16(
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i16> undef, i16 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i16> [[VECINIT_I]], i16 %c, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i16> [[VECINIT1_I]], i16 %c, i32 2
// CHECK: [[VECINIT3_I:%.*]] = insertelement <4 x i16> [[VECINIT2_I]], i16 %c, i32 3
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[VECINIT3_I]] to <8 x i8>
-// CHECK: [[VMULL_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[VMULL_I_I]], <4 x i16> [[VMULL1_I_I]]) #2
+// CHECK: [[VMULL2_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> %b, <4 x i16> [[VECINIT3_I]]) #2
// CHECK: [[SUB_I:%.*]] = sub <4 x i32> %a, [[VMULL2_I_I]]
// CHECK: ret <4 x i32> [[SUB_I]]
uint32x4_t test_vmlsl_n_u16(uint32x4_t a, uint16x4_t b, uint16_t c) {
return vmlsl_n_u16(a, b, c);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlsl_n_u32(<2 x i64> %a, <2 x i32> %b, i32 %c) #0 {
+// CHECK-LABEL: @test_vmlsl_n_u32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x i32> undef, i32 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x i32> [[VECINIT_I]], i32 %c, i32 1
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[VECINIT1_I]] to <8 x i8>
-// CHECK: [[VMULL_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[VMULL_I_I]], <2 x i32> [[VMULL1_I_I]]) #2
+// CHECK: [[VMULL2_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> %b, <2 x i32> [[VECINIT1_I]]) #2
// CHECK: [[SUB_I:%.*]] = sub <2 x i64> %a, [[VMULL2_I_I]]
// CHECK: ret <2 x i64> [[SUB_I]]
uint64x2_t test_vmlsl_n_u32(uint64x2_t a, uint32x2_t b, uint32_t c) {
return vmlsl_n_u32(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vqdmlsl_n_s16(<4 x i32> %a, <4 x i16> %b, i16 %c) #0 {
+// CHECK-LABEL: @test_vqdmlsl_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i16> undef, i16 %c, i32 0
@@ -4223,33 +3747,27 @@ uint64x2_t test_vmlsl_n_u32(uint64x2_t a, uint32x2_t b, uint32_t c) {
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i16> [[VECINIT1_I]], i16 %c, i32 2
// CHECK: [[VECINIT3_I:%.*]] = insertelement <4 x i16> [[VECINIT2_I]], i16 %c, i32 3
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> [[VECINIT3_I]] to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMLAL4_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VQDMLAL5_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[VQDMLAL_I]], <4 x i16> [[VQDMLAL4_I]]) #2
-// CHECK: [[VQDMLSL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQDMLSL_V6_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqsub.v4i32(<4 x i32> [[VQDMLSL_V_I]], <4 x i32> [[VQDMLAL5_I]]) #2
+// CHECK: [[VQDMLAL5_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> %b, <4 x i16> [[VECINIT3_I]]) #2
+// CHECK: [[VQDMLSL_V6_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqsub.v4i32(<4 x i32> %a, <4 x i32> [[VQDMLAL5_I]]) #2
// CHECK: ret <4 x i32> [[VQDMLSL_V6_I]]
int32x4_t test_vqdmlsl_n_s16(int32x4_t a, int16x4_t b, int16_t c) {
return vqdmlsl_n_s16(a, b, c);
}
-// CHECK-LABEL: define <2 x i64> @test_vqdmlsl_n_s32(<2 x i64> %a, <2 x i32> %b, i32 %c) #0 {
+// CHECK-LABEL: @test_vqdmlsl_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x i32> undef, i32 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x i32> [[VECINIT_I]], i32 %c, i32 1
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> [[VECINIT1_I]] to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMLAL2_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VQDMLAL3_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[VQDMLAL_I]], <2 x i32> [[VQDMLAL2_I]]) #2
-// CHECK: [[VQDMLSL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQDMLSL_V4_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqsub.v2i64(<2 x i64> [[VQDMLSL_V_I]], <2 x i64> [[VQDMLAL3_I]]) #2
+// CHECK: [[VQDMLAL3_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> %b, <2 x i32> [[VECINIT1_I]]) #2
+// CHECK: [[VQDMLSL_V4_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqsub.v2i64(<2 x i64> %a, <2 x i64> [[VQDMLAL3_I]]) #2
// CHECK: ret <2 x i64> [[VQDMLSL_V4_I]]
int64x2_t test_vqdmlsl_n_s32(int64x2_t a, int32x2_t b, int32_t c) {
return vqdmlsl_n_s32(a, b, c);
}
-// CHECK-LABEL: define <4 x i16> @test_vmla_lane_u16_0(<4 x i16> %a, <4 x i16> %b, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmla_lane_u16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = mul <4 x i16> %b, [[SHUFFLE]]
// CHECK: [[ADD:%.*]] = add <4 x i16> %a, [[MUL]]
@@ -4258,7 +3776,7 @@ uint16x4_t test_vmla_lane_u16_0(uint16x4_t a, uint16x4_t b, uint16x4_t v) {
return vmla_lane_u16(a, b, v, 0);
}
-// CHECK-LABEL: define <8 x i16> @test_vmlaq_lane_u16_0(<8 x i16> %a, <8 x i16> %b, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmlaq_lane_u16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <8 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = mul <8 x i16> %b, [[SHUFFLE]]
// CHECK: [[ADD:%.*]] = add <8 x i16> %a, [[MUL]]
@@ -4267,7 +3785,7 @@ uint16x8_t test_vmlaq_lane_u16_0(uint16x8_t a, uint16x8_t b, uint16x4_t v) {
return vmlaq_lane_u16(a, b, v, 0);
}
-// CHECK-LABEL: define <2 x i32> @test_vmla_lane_u32_0(<2 x i32> %a, <2 x i32> %b, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmla_lane_u32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = mul <2 x i32> %b, [[SHUFFLE]]
// CHECK: [[ADD:%.*]] = add <2 x i32> %a, [[MUL]]
@@ -4276,7 +3794,7 @@ uint32x2_t test_vmla_lane_u32_0(uint32x2_t a, uint32x2_t b, uint32x2_t v) {
return vmla_lane_u32(a, b, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlaq_lane_u32_0(<4 x i32> %a, <4 x i32> %b, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmlaq_lane_u32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <4 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = mul <4 x i32> %b, [[SHUFFLE]]
// CHECK: [[ADD:%.*]] = add <4 x i32> %a, [[MUL]]
@@ -4285,7 +3803,7 @@ uint32x4_t test_vmlaq_lane_u32_0(uint32x4_t a, uint32x4_t b, uint32x2_t v) {
return vmlaq_lane_u32(a, b, v, 0);
}
-// CHECK-LABEL: define <4 x i16> @test_vmla_laneq_u16_0(<4 x i16> %a, <4 x i16> %b, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmla_laneq_u16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = mul <4 x i16> %b, [[SHUFFLE]]
// CHECK: [[ADD:%.*]] = add <4 x i16> %a, [[MUL]]
@@ -4294,7 +3812,7 @@ uint16x4_t test_vmla_laneq_u16_0(uint16x4_t a, uint16x4_t b, uint16x8_t v) {
return vmla_laneq_u16(a, b, v, 0);
}
-// CHECK-LABEL: define <8 x i16> @test_vmlaq_laneq_u16_0(<8 x i16> %a, <8 x i16> %b, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmlaq_laneq_u16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <8 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = mul <8 x i16> %b, [[SHUFFLE]]
// CHECK: [[ADD:%.*]] = add <8 x i16> %a, [[MUL]]
@@ -4303,7 +3821,7 @@ uint16x8_t test_vmlaq_laneq_u16_0(uint16x8_t a, uint16x8_t b, uint16x8_t v) {
return vmlaq_laneq_u16(a, b, v, 0);
}
-// CHECK-LABEL: define <2 x i32> @test_vmla_laneq_u32_0(<2 x i32> %a, <2 x i32> %b, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmla_laneq_u32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = mul <2 x i32> %b, [[SHUFFLE]]
// CHECK: [[ADD:%.*]] = add <2 x i32> %a, [[MUL]]
@@ -4312,7 +3830,7 @@ uint32x2_t test_vmla_laneq_u32_0(uint32x2_t a, uint32x2_t b, uint32x4_t v) {
return vmla_laneq_u32(a, b, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlaq_laneq_u32_0(<4 x i32> %a, <4 x i32> %b, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmlaq_laneq_u32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <4 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = mul <4 x i32> %b, [[SHUFFLE]]
// CHECK: [[ADD:%.*]] = add <4 x i32> %a, [[MUL]]
@@ -4321,69 +3839,57 @@ uint32x4_t test_vmlaq_laneq_u32_0(uint32x4_t a, uint32x4_t b, uint32x4_t v) {
return vmlaq_laneq_u32(a, b, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vqdmlal_laneq_s16_0(<4 x i32> %a, <4 x i16> %b, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vqdmlal_laneq_s16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMLAL1_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VQDMLAL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[VQDMLAL_I]], <4 x i16> [[VQDMLAL1_I]]) #2
-// CHECK: [[VQDMLAL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQDMLAL_V3_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqadd.v4i32(<4 x i32> [[VQDMLAL_V_I]], <4 x i32> [[VQDMLAL2_I]]) #2
+// CHECK: [[VQDMLAL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> %b, <4 x i16> [[SHUFFLE]]) #2
+// CHECK: [[VQDMLAL_V3_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqadd.v4i32(<4 x i32> %a, <4 x i32> [[VQDMLAL2_I]]) #2
// CHECK: ret <4 x i32> [[VQDMLAL_V3_I]]
int32x4_t test_vqdmlal_laneq_s16_0(int32x4_t a, int16x4_t b, int16x8_t v) {
return vqdmlal_laneq_s16(a, b, v, 0);
}
-// CHECK-LABEL: define <2 x i64> @test_vqdmlal_laneq_s32_0(<2 x i64> %a, <2 x i32> %b, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vqdmlal_laneq_s32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMLAL1_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VQDMLAL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[VQDMLAL_I]], <2 x i32> [[VQDMLAL1_I]]) #2
-// CHECK: [[VQDMLAL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQDMLAL_V3_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqadd.v2i64(<2 x i64> [[VQDMLAL_V_I]], <2 x i64> [[VQDMLAL2_I]]) #2
+// CHECK: [[VQDMLAL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> %b, <2 x i32> [[SHUFFLE]]) #2
+// CHECK: [[VQDMLAL_V3_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqadd.v2i64(<2 x i64> %a, <2 x i64> [[VQDMLAL2_I]]) #2
// CHECK: ret <2 x i64> [[VQDMLAL_V3_I]]
int64x2_t test_vqdmlal_laneq_s32_0(int64x2_t a, int32x2_t b, int32x4_t v) {
return vqdmlal_laneq_s32(a, b, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vqdmlal_high_laneq_s16_0(<4 x i32> %a, <8 x i16> %b, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vqdmlal_high_laneq_s16_0(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMLAL1_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VQDMLAL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[VQDMLAL_I]], <4 x i16> [[VQDMLAL1_I]]) #2
-// CHECK: [[VQDMLAL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQDMLAL_V3_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqadd.v4i32(<4 x i32> [[VQDMLAL_V_I]], <4 x i32> [[VQDMLAL2_I]]) #2
+// CHECK: [[VQDMLAL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[SHUFFLE_I]], <4 x i16> [[SHUFFLE]]) #2
+// CHECK: [[VQDMLAL_V3_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqadd.v4i32(<4 x i32> %a, <4 x i32> [[VQDMLAL2_I]]) #2
// CHECK: ret <4 x i32> [[VQDMLAL_V3_I]]
int32x4_t test_vqdmlal_high_laneq_s16_0(int32x4_t a, int16x8_t b, int16x8_t v) {
return vqdmlal_high_laneq_s16(a, b, v, 0);
}
-// CHECK-LABEL: define <2 x i64> @test_vqdmlal_high_laneq_s32_0(<2 x i64> %a, <4 x i32> %b, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vqdmlal_high_laneq_s32_0(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMLAL1_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VQDMLAL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[VQDMLAL_I]], <2 x i32> [[VQDMLAL1_I]]) #2
-// CHECK: [[VQDMLAL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQDMLAL_V3_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqadd.v2i64(<2 x i64> [[VQDMLAL_V_I]], <2 x i64> [[VQDMLAL2_I]]) #2
+// CHECK: [[VQDMLAL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[SHUFFLE_I]], <2 x i32> [[SHUFFLE]]) #2
+// CHECK: [[VQDMLAL_V3_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqadd.v2i64(<2 x i64> %a, <2 x i64> [[VQDMLAL2_I]]) #2
// CHECK: ret <2 x i64> [[VQDMLAL_V3_I]]
int64x2_t test_vqdmlal_high_laneq_s32_0(int64x2_t a, int32x4_t b, int32x4_t v) {
return vqdmlal_high_laneq_s32(a, b, v, 0);
}
-// CHECK-LABEL: define <4 x i16> @test_vmls_lane_u16_0(<4 x i16> %a, <4 x i16> %b, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmls_lane_u16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = mul <4 x i16> %b, [[SHUFFLE]]
// CHECK: [[SUB:%.*]] = sub <4 x i16> %a, [[MUL]]
@@ -4392,7 +3898,7 @@ uint16x4_t test_vmls_lane_u16_0(uint16x4_t a, uint16x4_t b, uint16x4_t v) {
return vmls_lane_u16(a, b, v, 0);
}
-// CHECK-LABEL: define <8 x i16> @test_vmlsq_lane_u16_0(<8 x i16> %a, <8 x i16> %b, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmlsq_lane_u16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <8 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = mul <8 x i16> %b, [[SHUFFLE]]
// CHECK: [[SUB:%.*]] = sub <8 x i16> %a, [[MUL]]
@@ -4401,7 +3907,7 @@ uint16x8_t test_vmlsq_lane_u16_0(uint16x8_t a, uint16x8_t b, uint16x4_t v) {
return vmlsq_lane_u16(a, b, v, 0);
}
-// CHECK-LABEL: define <2 x i32> @test_vmls_lane_u32_0(<2 x i32> %a, <2 x i32> %b, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmls_lane_u32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = mul <2 x i32> %b, [[SHUFFLE]]
// CHECK: [[SUB:%.*]] = sub <2 x i32> %a, [[MUL]]
@@ -4410,7 +3916,7 @@ uint32x2_t test_vmls_lane_u32_0(uint32x2_t a, uint32x2_t b, uint32x2_t v) {
return vmls_lane_u32(a, b, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlsq_lane_u32_0(<4 x i32> %a, <4 x i32> %b, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmlsq_lane_u32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <4 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = mul <4 x i32> %b, [[SHUFFLE]]
// CHECK: [[SUB:%.*]] = sub <4 x i32> %a, [[MUL]]
@@ -4419,7 +3925,7 @@ uint32x4_t test_vmlsq_lane_u32_0(uint32x4_t a, uint32x4_t b, uint32x2_t v) {
return vmlsq_lane_u32(a, b, v, 0);
}
-// CHECK-LABEL: define <4 x i16> @test_vmls_laneq_u16_0(<4 x i16> %a, <4 x i16> %b, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmls_laneq_u16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = mul <4 x i16> %b, [[SHUFFLE]]
// CHECK: [[SUB:%.*]] = sub <4 x i16> %a, [[MUL]]
@@ -4428,7 +3934,7 @@ uint16x4_t test_vmls_laneq_u16_0(uint16x4_t a, uint16x4_t b, uint16x8_t v) {
return vmls_laneq_u16(a, b, v, 0);
}
-// CHECK-LABEL: define <8 x i16> @test_vmlsq_laneq_u16_0(<8 x i16> %a, <8 x i16> %b, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmlsq_laneq_u16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <8 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = mul <8 x i16> %b, [[SHUFFLE]]
// CHECK: [[SUB:%.*]] = sub <8 x i16> %a, [[MUL]]
@@ -4437,7 +3943,7 @@ uint16x8_t test_vmlsq_laneq_u16_0(uint16x8_t a, uint16x8_t b, uint16x8_t v) {
return vmlsq_laneq_u16(a, b, v, 0);
}
-// CHECK-LABEL: define <2 x i32> @test_vmls_laneq_u32_0(<2 x i32> %a, <2 x i32> %b, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmls_laneq_u32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = mul <2 x i32> %b, [[SHUFFLE]]
// CHECK: [[SUB:%.*]] = sub <2 x i32> %a, [[MUL]]
@@ -4446,7 +3952,7 @@ uint32x2_t test_vmls_laneq_u32_0(uint32x2_t a, uint32x2_t b, uint32x4_t v) {
return vmls_laneq_u32(a, b, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlsq_laneq_u32_0(<4 x i32> %a, <4 x i32> %b, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmlsq_laneq_u32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <4 x i32> zeroinitializer
// CHECK: [[MUL:%.*]] = mul <4 x i32> %b, [[SHUFFLE]]
// CHECK: [[SUB:%.*]] = sub <4 x i32> %a, [[MUL]]
@@ -4455,181 +3961,145 @@ uint32x4_t test_vmlsq_laneq_u32_0(uint32x4_t a, uint32x4_t b, uint32x4_t v) {
return vmlsq_laneq_u32(a, b, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vqdmlsl_laneq_s16_0(<4 x i32> %a, <4 x i16> %b, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vqdmlsl_laneq_s16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMLAL1_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VQDMLAL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[VQDMLAL_I]], <4 x i16> [[VQDMLAL1_I]]) #2
-// CHECK: [[VQDMLSL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQDMLSL_V3_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqsub.v4i32(<4 x i32> [[VQDMLSL_V_I]], <4 x i32> [[VQDMLAL2_I]]) #2
+// CHECK: [[VQDMLAL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> %b, <4 x i16> [[SHUFFLE]]) #2
+// CHECK: [[VQDMLSL_V3_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqsub.v4i32(<4 x i32> %a, <4 x i32> [[VQDMLAL2_I]]) #2
// CHECK: ret <4 x i32> [[VQDMLSL_V3_I]]
int32x4_t test_vqdmlsl_laneq_s16_0(int32x4_t a, int16x4_t b, int16x8_t v) {
return vqdmlsl_laneq_s16(a, b, v, 0);
}
-// CHECK-LABEL: define <2 x i64> @test_vqdmlsl_laneq_s32_0(<2 x i64> %a, <2 x i32> %b, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vqdmlsl_laneq_s32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMLAL1_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VQDMLAL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[VQDMLAL_I]], <2 x i32> [[VQDMLAL1_I]]) #2
-// CHECK: [[VQDMLSL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQDMLSL_V3_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqsub.v2i64(<2 x i64> [[VQDMLSL_V_I]], <2 x i64> [[VQDMLAL2_I]]) #2
+// CHECK: [[VQDMLAL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> %b, <2 x i32> [[SHUFFLE]]) #2
+// CHECK: [[VQDMLSL_V3_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqsub.v2i64(<2 x i64> %a, <2 x i64> [[VQDMLAL2_I]]) #2
// CHECK: ret <2 x i64> [[VQDMLSL_V3_I]]
int64x2_t test_vqdmlsl_laneq_s32_0(int64x2_t a, int32x2_t b, int32x4_t v) {
return vqdmlsl_laneq_s32(a, b, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vqdmlsl_high_laneq_s16_0(<4 x i32> %a, <8 x i16> %b, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vqdmlsl_high_laneq_s16_0(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMLAL1_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VQDMLAL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[VQDMLAL_I]], <4 x i16> [[VQDMLAL1_I]]) #2
-// CHECK: [[VQDMLSL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQDMLSL_V3_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqsub.v4i32(<4 x i32> [[VQDMLSL_V_I]], <4 x i32> [[VQDMLAL2_I]]) #2
+// CHECK: [[VQDMLAL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[SHUFFLE_I]], <4 x i16> [[SHUFFLE]]) #2
+// CHECK: [[VQDMLSL_V3_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqsub.v4i32(<4 x i32> %a, <4 x i32> [[VQDMLAL2_I]]) #2
// CHECK: ret <4 x i32> [[VQDMLSL_V3_I]]
int32x4_t test_vqdmlsl_high_laneq_s16_0(int32x4_t a, int16x8_t b, int16x8_t v) {
return vqdmlsl_high_laneq_s16(a, b, v, 0);
}
-// CHECK-LABEL: define <2 x i64> @test_vqdmlsl_high_laneq_s32_0(<2 x i64> %a, <4 x i32> %b, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vqdmlsl_high_laneq_s32_0(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMLAL1_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VQDMLAL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[VQDMLAL_I]], <2 x i32> [[VQDMLAL1_I]]) #2
-// CHECK: [[VQDMLSL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQDMLSL_V3_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqsub.v2i64(<2 x i64> [[VQDMLSL_V_I]], <2 x i64> [[VQDMLAL2_I]]) #2
+// CHECK: [[VQDMLAL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[SHUFFLE_I]], <2 x i32> [[SHUFFLE]]) #2
+// CHECK: [[VQDMLSL_V3_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqsub.v2i64(<2 x i64> %a, <2 x i64> [[VQDMLAL2_I]]) #2
// CHECK: ret <2 x i64> [[VQDMLSL_V3_I]]
int64x2_t test_vqdmlsl_high_laneq_s32_0(int64x2_t a, int32x4_t b, int32x4_t v) {
return vqdmlsl_high_laneq_s32(a, b, v, 0);
}
-// CHECK-LABEL: define <4 x i16> @test_vqdmulh_laneq_s16_0(<4 x i16> %a, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vqdmulh_laneq_s16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMULH_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQDMULH_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMULH_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqdmulh.v4i16(<4 x i16> [[VQDMULH_V_I]], <4 x i16> [[VQDMULH_V1_I]]) #2
+// CHECK: [[VQDMULH_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqdmulh.v4i16(<4 x i16> %a, <4 x i16> [[SHUFFLE]]) #2
// CHECK: [[VQDMULH_V3_I:%.*]] = bitcast <4 x i16> [[VQDMULH_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQDMULH_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VQDMULH_V2_I]]
int16x4_t test_vqdmulh_laneq_s16_0(int16x4_t a, int16x8_t v) {
return vqdmulh_laneq_s16(a, v, 0);
}
-// CHECK-LABEL: define <8 x i16> @test_vqdmulhq_laneq_s16_0(<8 x i16> %a, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vqdmulhq_laneq_s16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <8 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> [[SHUFFLE]] to <16 x i8>
-// CHECK: [[VQDMULHQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VQDMULHQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VQDMULHQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.sqdmulh.v8i16(<8 x i16> [[VQDMULHQ_V_I]], <8 x i16> [[VQDMULHQ_V1_I]]) #2
+// CHECK: [[VQDMULHQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.sqdmulh.v8i16(<8 x i16> %a, <8 x i16> [[SHUFFLE]]) #2
// CHECK: [[VQDMULHQ_V3_I:%.*]] = bitcast <8 x i16> [[VQDMULHQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQDMULHQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VQDMULHQ_V2_I]]
int16x8_t test_vqdmulhq_laneq_s16_0(int16x8_t a, int16x8_t v) {
return vqdmulhq_laneq_s16(a, v, 0);
}
-// CHECK-LABEL: define <2 x i32> @test_vqdmulh_laneq_s32_0(<2 x i32> %a, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vqdmulh_laneq_s32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMULH_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQDMULH_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMULH_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqdmulh.v2i32(<2 x i32> [[VQDMULH_V_I]], <2 x i32> [[VQDMULH_V1_I]]) #2
+// CHECK: [[VQDMULH_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqdmulh.v2i32(<2 x i32> %a, <2 x i32> [[SHUFFLE]]) #2
// CHECK: [[VQDMULH_V3_I:%.*]] = bitcast <2 x i32> [[VQDMULH_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQDMULH_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VQDMULH_V2_I]]
int32x2_t test_vqdmulh_laneq_s32_0(int32x2_t a, int32x4_t v) {
return vqdmulh_laneq_s32(a, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vqdmulhq_laneq_s32_0(<4 x i32> %a, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vqdmulhq_laneq_s32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <4 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> [[SHUFFLE]] to <16 x i8>
-// CHECK: [[VQDMULHQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQDMULHQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VQDMULHQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmulh.v4i32(<4 x i32> [[VQDMULHQ_V_I]], <4 x i32> [[VQDMULHQ_V1_I]]) #2
+// CHECK: [[VQDMULHQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmulh.v4i32(<4 x i32> %a, <4 x i32> [[SHUFFLE]]) #2
// CHECK: [[VQDMULHQ_V3_I:%.*]] = bitcast <4 x i32> [[VQDMULHQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQDMULHQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VQDMULHQ_V2_I]]
int32x4_t test_vqdmulhq_laneq_s32_0(int32x4_t a, int32x4_t v) {
return vqdmulhq_laneq_s32(a, v, 0);
}
-// CHECK-LABEL: define <4 x i16> @test_vqrdmulh_laneq_s16_0(<4 x i16> %a, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vqrdmulh_laneq_s16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQRDMULH_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQRDMULH_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQRDMULH_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqrdmulh.v4i16(<4 x i16> [[VQRDMULH_V_I]], <4 x i16> [[VQRDMULH_V1_I]]) #2
+// CHECK: [[VQRDMULH_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqrdmulh.v4i16(<4 x i16> %a, <4 x i16> [[SHUFFLE]]) #2
// CHECK: [[VQRDMULH_V3_I:%.*]] = bitcast <4 x i16> [[VQRDMULH_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQRDMULH_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VQRDMULH_V2_I]]
int16x4_t test_vqrdmulh_laneq_s16_0(int16x4_t a, int16x8_t v) {
return vqrdmulh_laneq_s16(a, v, 0);
}
-// CHECK-LABEL: define <8 x i16> @test_vqrdmulhq_laneq_s16_0(<8 x i16> %a, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vqrdmulhq_laneq_s16_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <8 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> [[SHUFFLE]] to <16 x i8>
-// CHECK: [[VQRDMULHQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VQRDMULHQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VQRDMULHQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.sqrdmulh.v8i16(<8 x i16> [[VQRDMULHQ_V_I]], <8 x i16> [[VQRDMULHQ_V1_I]]) #2
+// CHECK: [[VQRDMULHQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.sqrdmulh.v8i16(<8 x i16> %a, <8 x i16> [[SHUFFLE]]) #2
// CHECK: [[VQRDMULHQ_V3_I:%.*]] = bitcast <8 x i16> [[VQRDMULHQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQRDMULHQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VQRDMULHQ_V2_I]]
int16x8_t test_vqrdmulhq_laneq_s16_0(int16x8_t a, int16x8_t v) {
return vqrdmulhq_laneq_s16(a, v, 0);
}
-// CHECK-LABEL: define <2 x i32> @test_vqrdmulh_laneq_s32_0(<2 x i32> %a, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vqrdmulh_laneq_s32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQRDMULH_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQRDMULH_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQRDMULH_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqrdmulh.v2i32(<2 x i32> [[VQRDMULH_V_I]], <2 x i32> [[VQRDMULH_V1_I]]) #2
+// CHECK: [[VQRDMULH_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqrdmulh.v2i32(<2 x i32> %a, <2 x i32> [[SHUFFLE]]) #2
// CHECK: [[VQRDMULH_V3_I:%.*]] = bitcast <2 x i32> [[VQRDMULH_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQRDMULH_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VQRDMULH_V2_I]]
int32x2_t test_vqrdmulh_laneq_s32_0(int32x2_t a, int32x4_t v) {
return vqrdmulh_laneq_s32(a, v, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vqrdmulhq_laneq_s32_0(<4 x i32> %a, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vqrdmulhq_laneq_s32_0(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <4 x i32> zeroinitializer
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> [[SHUFFLE]] to <16 x i8>
-// CHECK: [[VQRDMULHQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQRDMULHQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VQRDMULHQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqrdmulh.v4i32(<4 x i32> [[VQRDMULHQ_V_I]], <4 x i32> [[VQRDMULHQ_V1_I]]) #2
+// CHECK: [[VQRDMULHQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqrdmulh.v4i32(<4 x i32> %a, <4 x i32> [[SHUFFLE]]) #2
// CHECK: [[VQRDMULHQ_V3_I:%.*]] = bitcast <4 x i32> [[VQRDMULHQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQRDMULHQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VQRDMULHQ_V2_I]]
int32x4_t test_vqrdmulhq_laneq_s32_0(int32x4_t a, int32x4_t v) {
return vqrdmulhq_laneq_s32(a, v, 0);
}
-// CHECK-LABEL: define <4 x i16> @test_vmla_lane_u16(<4 x i16> %a, <4 x i16> %b, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmla_lane_u16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[MUL:%.*]] = mul <4 x i16> %b, [[SHUFFLE]]
// CHECK: [[ADD:%.*]] = add <4 x i16> %a, [[MUL]]
@@ -4638,7 +4108,7 @@ uint16x4_t test_vmla_lane_u16(uint16x4_t a, uint16x4_t b, uint16x4_t v) {
return vmla_lane_u16(a, b, v, 3);
}
-// CHECK-LABEL: define <8 x i16> @test_vmlaq_lane_u16(<8 x i16> %a, <8 x i16> %b, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmlaq_lane_u16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <8 x i32> <i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3>
// CHECK: [[MUL:%.*]] = mul <8 x i16> %b, [[SHUFFLE]]
// CHECK: [[ADD:%.*]] = add <8 x i16> %a, [[MUL]]
@@ -4647,7 +4117,7 @@ uint16x8_t test_vmlaq_lane_u16(uint16x8_t a, uint16x8_t b, uint16x4_t v) {
return vmlaq_lane_u16(a, b, v, 3);
}
-// CHECK-LABEL: define <2 x i32> @test_vmla_lane_u32(<2 x i32> %a, <2 x i32> %b, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmla_lane_u32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> <i32 1, i32 1>
// CHECK: [[MUL:%.*]] = mul <2 x i32> %b, [[SHUFFLE]]
// CHECK: [[ADD:%.*]] = add <2 x i32> %a, [[MUL]]
@@ -4656,7 +4126,7 @@ uint32x2_t test_vmla_lane_u32(uint32x2_t a, uint32x2_t b, uint32x2_t v) {
return vmla_lane_u32(a, b, v, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlaq_lane_u32(<4 x i32> %a, <4 x i32> %b, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmlaq_lane_u32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
// CHECK: [[MUL:%.*]] = mul <4 x i32> %b, [[SHUFFLE]]
// CHECK: [[ADD:%.*]] = add <4 x i32> %a, [[MUL]]
@@ -4665,7 +4135,7 @@ uint32x4_t test_vmlaq_lane_u32(uint32x4_t a, uint32x4_t b, uint32x2_t v) {
return vmlaq_lane_u32(a, b, v, 1);
}
-// CHECK-LABEL: define <4 x i16> @test_vmla_laneq_u16(<4 x i16> %a, <4 x i16> %b, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmla_laneq_u16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> <i32 7, i32 7, i32 7, i32 7>
// CHECK: [[MUL:%.*]] = mul <4 x i16> %b, [[SHUFFLE]]
// CHECK: [[ADD:%.*]] = add <4 x i16> %a, [[MUL]]
@@ -4674,7 +4144,7 @@ uint16x4_t test_vmla_laneq_u16(uint16x4_t a, uint16x4_t b, uint16x8_t v) {
return vmla_laneq_u16(a, b, v, 7);
}
-// CHECK-LABEL: define <8 x i16> @test_vmlaq_laneq_u16(<8 x i16> %a, <8 x i16> %b, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmlaq_laneq_u16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <8 x i32> <i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7>
// CHECK: [[MUL:%.*]] = mul <8 x i16> %b, [[SHUFFLE]]
// CHECK: [[ADD:%.*]] = add <8 x i16> %a, [[MUL]]
@@ -4683,7 +4153,7 @@ uint16x8_t test_vmlaq_laneq_u16(uint16x8_t a, uint16x8_t b, uint16x8_t v) {
return vmlaq_laneq_u16(a, b, v, 7);
}
-// CHECK-LABEL: define <2 x i32> @test_vmla_laneq_u32(<2 x i32> %a, <2 x i32> %b, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmla_laneq_u32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> <i32 3, i32 3>
// CHECK: [[MUL:%.*]] = mul <2 x i32> %b, [[SHUFFLE]]
// CHECK: [[ADD:%.*]] = add <2 x i32> %a, [[MUL]]
@@ -4692,7 +4162,7 @@ uint32x2_t test_vmla_laneq_u32(uint32x2_t a, uint32x2_t b, uint32x4_t v) {
return vmla_laneq_u32(a, b, v, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlaq_laneq_u32(<4 x i32> %a, <4 x i32> %b, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmlaq_laneq_u32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[MUL:%.*]] = mul <4 x i32> %b, [[SHUFFLE]]
// CHECK: [[ADD:%.*]] = add <4 x i32> %a, [[MUL]]
@@ -4701,69 +4171,57 @@ uint32x4_t test_vmlaq_laneq_u32(uint32x4_t a, uint32x4_t b, uint32x4_t v) {
return vmlaq_laneq_u32(a, b, v, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vqdmlal_laneq_s16(<4 x i32> %a, <4 x i16> %b, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vqdmlal_laneq_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> <i32 7, i32 7, i32 7, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMLAL1_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VQDMLAL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[VQDMLAL_I]], <4 x i16> [[VQDMLAL1_I]]) #2
-// CHECK: [[VQDMLAL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQDMLAL_V3_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqadd.v4i32(<4 x i32> [[VQDMLAL_V_I]], <4 x i32> [[VQDMLAL2_I]]) #2
+// CHECK: [[VQDMLAL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> %b, <4 x i16> [[SHUFFLE]]) #2
+// CHECK: [[VQDMLAL_V3_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqadd.v4i32(<4 x i32> %a, <4 x i32> [[VQDMLAL2_I]]) #2
// CHECK: ret <4 x i32> [[VQDMLAL_V3_I]]
int32x4_t test_vqdmlal_laneq_s16(int32x4_t a, int16x4_t b, int16x8_t v) {
return vqdmlal_laneq_s16(a, b, v, 7);
}
-// CHECK-LABEL: define <2 x i64> @test_vqdmlal_laneq_s32(<2 x i64> %a, <2 x i32> %b, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vqdmlal_laneq_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> <i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMLAL1_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VQDMLAL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[VQDMLAL_I]], <2 x i32> [[VQDMLAL1_I]]) #2
-// CHECK: [[VQDMLAL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQDMLAL_V3_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqadd.v2i64(<2 x i64> [[VQDMLAL_V_I]], <2 x i64> [[VQDMLAL2_I]]) #2
+// CHECK: [[VQDMLAL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> %b, <2 x i32> [[SHUFFLE]]) #2
+// CHECK: [[VQDMLAL_V3_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqadd.v2i64(<2 x i64> %a, <2 x i64> [[VQDMLAL2_I]]) #2
// CHECK: ret <2 x i64> [[VQDMLAL_V3_I]]
int64x2_t test_vqdmlal_laneq_s32(int64x2_t a, int32x2_t b, int32x4_t v) {
return vqdmlal_laneq_s32(a, b, v, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vqdmlal_high_laneq_s16(<4 x i32> %a, <8 x i16> %b, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vqdmlal_high_laneq_s16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> <i32 7, i32 7, i32 7, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMLAL1_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VQDMLAL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[VQDMLAL_I]], <4 x i16> [[VQDMLAL1_I]]) #2
-// CHECK: [[VQDMLAL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQDMLAL_V3_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqadd.v4i32(<4 x i32> [[VQDMLAL_V_I]], <4 x i32> [[VQDMLAL2_I]]) #2
+// CHECK: [[VQDMLAL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[SHUFFLE_I]], <4 x i16> [[SHUFFLE]]) #2
+// CHECK: [[VQDMLAL_V3_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqadd.v4i32(<4 x i32> %a, <4 x i32> [[VQDMLAL2_I]]) #2
// CHECK: ret <4 x i32> [[VQDMLAL_V3_I]]
int32x4_t test_vqdmlal_high_laneq_s16(int32x4_t a, int16x8_t b, int16x8_t v) {
return vqdmlal_high_laneq_s16(a, b, v, 7);
}
-// CHECK-LABEL: define <2 x i64> @test_vqdmlal_high_laneq_s32(<2 x i64> %a, <4 x i32> %b, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vqdmlal_high_laneq_s32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> <i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMLAL1_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VQDMLAL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[VQDMLAL_I]], <2 x i32> [[VQDMLAL1_I]]) #2
-// CHECK: [[VQDMLAL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQDMLAL_V3_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqadd.v2i64(<2 x i64> [[VQDMLAL_V_I]], <2 x i64> [[VQDMLAL2_I]]) #2
+// CHECK: [[VQDMLAL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[SHUFFLE_I]], <2 x i32> [[SHUFFLE]]) #2
+// CHECK: [[VQDMLAL_V3_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqadd.v2i64(<2 x i64> %a, <2 x i64> [[VQDMLAL2_I]]) #2
// CHECK: ret <2 x i64> [[VQDMLAL_V3_I]]
int64x2_t test_vqdmlal_high_laneq_s32(int64x2_t a, int32x4_t b, int32x4_t v) {
return vqdmlal_high_laneq_s32(a, b, v, 3);
}
-// CHECK-LABEL: define <4 x i16> @test_vmls_lane_u16(<4 x i16> %a, <4 x i16> %b, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmls_lane_u16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[MUL:%.*]] = mul <4 x i16> %b, [[SHUFFLE]]
// CHECK: [[SUB:%.*]] = sub <4 x i16> %a, [[MUL]]
@@ -4772,7 +4230,7 @@ uint16x4_t test_vmls_lane_u16(uint16x4_t a, uint16x4_t b, uint16x4_t v) {
return vmls_lane_u16(a, b, v, 3);
}
-// CHECK-LABEL: define <8 x i16> @test_vmlsq_lane_u16(<8 x i16> %a, <8 x i16> %b, <4 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmlsq_lane_u16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %v, <4 x i16> %v, <8 x i32> <i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3>
// CHECK: [[MUL:%.*]] = mul <8 x i16> %b, [[SHUFFLE]]
// CHECK: [[SUB:%.*]] = sub <8 x i16> %a, [[MUL]]
@@ -4781,7 +4239,7 @@ uint16x8_t test_vmlsq_lane_u16(uint16x8_t a, uint16x8_t b, uint16x4_t v) {
return vmlsq_lane_u16(a, b, v, 3);
}
-// CHECK-LABEL: define <2 x i32> @test_vmls_lane_u32(<2 x i32> %a, <2 x i32> %b, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmls_lane_u32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <2 x i32> <i32 1, i32 1>
// CHECK: [[MUL:%.*]] = mul <2 x i32> %b, [[SHUFFLE]]
// CHECK: [[SUB:%.*]] = sub <2 x i32> %a, [[MUL]]
@@ -4790,7 +4248,7 @@ uint32x2_t test_vmls_lane_u32(uint32x2_t a, uint32x2_t b, uint32x2_t v) {
return vmls_lane_u32(a, b, v, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlsq_lane_u32(<4 x i32> %a, <4 x i32> %b, <2 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmlsq_lane_u32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %v, <2 x i32> %v, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
// CHECK: [[MUL:%.*]] = mul <4 x i32> %b, [[SHUFFLE]]
// CHECK: [[SUB:%.*]] = sub <4 x i32> %a, [[MUL]]
@@ -4799,7 +4257,7 @@ uint32x4_t test_vmlsq_lane_u32(uint32x4_t a, uint32x4_t b, uint32x2_t v) {
return vmlsq_lane_u32(a, b, v, 1);
}
-// CHECK-LABEL: define <4 x i16> @test_vmls_laneq_u16(<4 x i16> %a, <4 x i16> %b, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmls_laneq_u16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> <i32 7, i32 7, i32 7, i32 7>
// CHECK: [[MUL:%.*]] = mul <4 x i16> %b, [[SHUFFLE]]
// CHECK: [[SUB:%.*]] = sub <4 x i16> %a, [[MUL]]
@@ -4808,7 +4266,7 @@ uint16x4_t test_vmls_laneq_u16(uint16x4_t a, uint16x4_t b, uint16x8_t v) {
return vmls_laneq_u16(a, b, v, 7);
}
-// CHECK-LABEL: define <8 x i16> @test_vmlsq_laneq_u16(<8 x i16> %a, <8 x i16> %b, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vmlsq_laneq_u16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <8 x i32> <i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7>
// CHECK: [[MUL:%.*]] = mul <8 x i16> %b, [[SHUFFLE]]
// CHECK: [[SUB:%.*]] = sub <8 x i16> %a, [[MUL]]
@@ -4817,7 +4275,7 @@ uint16x8_t test_vmlsq_laneq_u16(uint16x8_t a, uint16x8_t b, uint16x8_t v) {
return vmlsq_laneq_u16(a, b, v, 7);
}
-// CHECK-LABEL: define <2 x i32> @test_vmls_laneq_u32(<2 x i32> %a, <2 x i32> %b, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmls_laneq_u32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> <i32 3, i32 3>
// CHECK: [[MUL:%.*]] = mul <2 x i32> %b, [[SHUFFLE]]
// CHECK: [[SUB:%.*]] = sub <2 x i32> %a, [[MUL]]
@@ -4826,7 +4284,7 @@ uint32x2_t test_vmls_laneq_u32(uint32x2_t a, uint32x2_t b, uint32x4_t v) {
return vmls_laneq_u32(a, b, v, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlsq_laneq_u32(<4 x i32> %a, <4 x i32> %b, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vmlsq_laneq_u32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[MUL:%.*]] = mul <4 x i32> %b, [[SHUFFLE]]
// CHECK: [[SUB:%.*]] = sub <4 x i32> %a, [[MUL]]
@@ -4835,177 +4293,140 @@ uint32x4_t test_vmlsq_laneq_u32(uint32x4_t a, uint32x4_t b, uint32x4_t v) {
return vmlsq_laneq_u32(a, b, v, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vqdmlsl_laneq_s16(<4 x i32> %a, <4 x i16> %b, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vqdmlsl_laneq_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> <i32 7, i32 7, i32 7, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMLAL1_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VQDMLAL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[VQDMLAL_I]], <4 x i16> [[VQDMLAL1_I]]) #2
-// CHECK: [[VQDMLSL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQDMLSL_V3_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqsub.v4i32(<4 x i32> [[VQDMLSL_V_I]], <4 x i32> [[VQDMLAL2_I]]) #2
+// CHECK: [[VQDMLAL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> %b, <4 x i16> [[SHUFFLE]]) #2
+// CHECK: [[VQDMLSL_V3_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqsub.v4i32(<4 x i32> %a, <4 x i32> [[VQDMLAL2_I]]) #2
// CHECK: ret <4 x i32> [[VQDMLSL_V3_I]]
int32x4_t test_vqdmlsl_laneq_s16(int32x4_t a, int16x4_t b, int16x8_t v) {
return vqdmlsl_laneq_s16(a, b, v, 7);
}
-// CHECK-LABEL: define <2 x i64> @test_vqdmlsl_laneq_s32(<2 x i64> %a, <2 x i32> %b, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vqdmlsl_laneq_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> <i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMLAL1_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VQDMLAL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[VQDMLAL_I]], <2 x i32> [[VQDMLAL1_I]]) #2
-// CHECK: [[VQDMLSL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQDMLSL_V3_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqsub.v2i64(<2 x i64> [[VQDMLSL_V_I]], <2 x i64> [[VQDMLAL2_I]]) #2
+// CHECK: [[VQDMLAL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> %b, <2 x i32> [[SHUFFLE]]) #2
+// CHECK: [[VQDMLSL_V3_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqsub.v2i64(<2 x i64> %a, <2 x i64> [[VQDMLAL2_I]]) #2
// CHECK: ret <2 x i64> [[VQDMLSL_V3_I]]
int64x2_t test_vqdmlsl_laneq_s32(int64x2_t a, int32x2_t b, int32x4_t v) {
return vqdmlsl_laneq_s32(a, b, v, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vqdmlsl_high_laneq_s16(<4 x i32> %a, <8 x i16> %b, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vqdmlsl_high_laneq_s16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> <i32 7, i32 7, i32 7, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMLAL1_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VQDMLAL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[VQDMLAL_I]], <4 x i16> [[VQDMLAL1_I]]) #2
-// CHECK: [[VQDMLSL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQDMLSL_V3_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqsub.v4i32(<4 x i32> [[VQDMLSL_V_I]], <4 x i32> [[VQDMLAL2_I]]) #2
+// CHECK: [[VQDMLAL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[SHUFFLE_I]], <4 x i16> [[SHUFFLE]]) #2
+// CHECK: [[VQDMLSL_V3_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqsub.v4i32(<4 x i32> %a, <4 x i32> [[VQDMLAL2_I]]) #2
// CHECK: ret <4 x i32> [[VQDMLSL_V3_I]]
int32x4_t test_vqdmlsl_high_laneq_s16(int32x4_t a, int16x8_t b, int16x8_t v) {
return vqdmlsl_high_laneq_s16(a, b, v, 7);
}
-// CHECK-LABEL: define <2 x i64> @test_vqdmlsl_high_laneq_s32(<2 x i64> %a, <4 x i32> %b, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vqdmlsl_high_laneq_s32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> <i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMLAL1_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VQDMLAL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[VQDMLAL_I]], <2 x i32> [[VQDMLAL1_I]]) #2
-// CHECK: [[VQDMLSL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQDMLSL_V3_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqsub.v2i64(<2 x i64> [[VQDMLSL_V_I]], <2 x i64> [[VQDMLAL2_I]]) #2
+// CHECK: [[VQDMLAL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[SHUFFLE_I]], <2 x i32> [[SHUFFLE]]) #2
+// CHECK: [[VQDMLSL_V3_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqsub.v2i64(<2 x i64> %a, <2 x i64> [[VQDMLAL2_I]]) #2
// CHECK: ret <2 x i64> [[VQDMLSL_V3_I]]
int64x2_t test_vqdmlsl_high_laneq_s32(int64x2_t a, int32x4_t b, int32x4_t v) {
return vqdmlsl_high_laneq_s32(a, b, v, 3);
}
-// CHECK-LABEL: define <4 x i16> @test_vqdmulh_laneq_s16(<4 x i16> %a, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vqdmulh_laneq_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> <i32 7, i32 7, i32 7, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMULH_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQDMULH_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMULH_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqdmulh.v4i16(<4 x i16> [[VQDMULH_V_I]], <4 x i16> [[VQDMULH_V1_I]]) #2
+// CHECK: [[VQDMULH_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqdmulh.v4i16(<4 x i16> %a, <4 x i16> [[SHUFFLE]]) #2
// CHECK: [[VQDMULH_V3_I:%.*]] = bitcast <4 x i16> [[VQDMULH_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQDMULH_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VQDMULH_V2_I]]
int16x4_t test_vqdmulh_laneq_s16(int16x4_t a, int16x8_t v) {
return vqdmulh_laneq_s16(a, v, 7);
}
-// CHECK-LABEL: define <8 x i16> @test_vqdmulhq_laneq_s16(<8 x i16> %a, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vqdmulhq_laneq_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <8 x i32> <i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> [[SHUFFLE]] to <16 x i8>
-// CHECK: [[VQDMULHQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VQDMULHQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VQDMULHQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.sqdmulh.v8i16(<8 x i16> [[VQDMULHQ_V_I]], <8 x i16> [[VQDMULHQ_V1_I]]) #2
+// CHECK: [[VQDMULHQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.sqdmulh.v8i16(<8 x i16> %a, <8 x i16> [[SHUFFLE]]) #2
// CHECK: [[VQDMULHQ_V3_I:%.*]] = bitcast <8 x i16> [[VQDMULHQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQDMULHQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VQDMULHQ_V2_I]]
int16x8_t test_vqdmulhq_laneq_s16(int16x8_t a, int16x8_t v) {
return vqdmulhq_laneq_s16(a, v, 7);
}
-// CHECK-LABEL: define <2 x i32> @test_vqdmulh_laneq_s32(<2 x i32> %a, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vqdmulh_laneq_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> <i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMULH_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQDMULH_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMULH_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqdmulh.v2i32(<2 x i32> [[VQDMULH_V_I]], <2 x i32> [[VQDMULH_V1_I]]) #2
+// CHECK: [[VQDMULH_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqdmulh.v2i32(<2 x i32> %a, <2 x i32> [[SHUFFLE]]) #2
// CHECK: [[VQDMULH_V3_I:%.*]] = bitcast <2 x i32> [[VQDMULH_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQDMULH_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VQDMULH_V2_I]]
int32x2_t test_vqdmulh_laneq_s32(int32x2_t a, int32x4_t v) {
return vqdmulh_laneq_s32(a, v, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vqdmulhq_laneq_s32(<4 x i32> %a, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vqdmulhq_laneq_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> [[SHUFFLE]] to <16 x i8>
-// CHECK: [[VQDMULHQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQDMULHQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VQDMULHQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmulh.v4i32(<4 x i32> [[VQDMULHQ_V_I]], <4 x i32> [[VQDMULHQ_V1_I]]) #2
+// CHECK: [[VQDMULHQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmulh.v4i32(<4 x i32> %a, <4 x i32> [[SHUFFLE]]) #2
// CHECK: [[VQDMULHQ_V3_I:%.*]] = bitcast <4 x i32> [[VQDMULHQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQDMULHQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VQDMULHQ_V2_I]]
int32x4_t test_vqdmulhq_laneq_s32(int32x4_t a, int32x4_t v) {
return vqdmulhq_laneq_s32(a, v, 3);
}
-// CHECK-LABEL: define <4 x i16> @test_vqrdmulh_laneq_s16(<4 x i16> %a, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vqrdmulh_laneq_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <4 x i32> <i32 7, i32 7, i32 7, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQRDMULH_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQRDMULH_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQRDMULH_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqrdmulh.v4i16(<4 x i16> [[VQRDMULH_V_I]], <4 x i16> [[VQRDMULH_V1_I]]) #2
+// CHECK: [[VQRDMULH_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqrdmulh.v4i16(<4 x i16> %a, <4 x i16> [[SHUFFLE]]) #2
// CHECK: [[VQRDMULH_V3_I:%.*]] = bitcast <4 x i16> [[VQRDMULH_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQRDMULH_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VQRDMULH_V2_I]]
int16x4_t test_vqrdmulh_laneq_s16(int16x4_t a, int16x8_t v) {
return vqrdmulh_laneq_s16(a, v, 7);
}
-// CHECK-LABEL: define <8 x i16> @test_vqrdmulhq_laneq_s16(<8 x i16> %a, <8 x i16> %v) #0 {
+// CHECK-LABEL: @test_vqrdmulhq_laneq_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i16> %v, <8 x i16> %v, <8 x i32> <i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> [[SHUFFLE]] to <16 x i8>
-// CHECK: [[VQRDMULHQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VQRDMULHQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VQRDMULHQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.sqrdmulh.v8i16(<8 x i16> [[VQRDMULHQ_V_I]], <8 x i16> [[VQRDMULHQ_V1_I]]) #2
+// CHECK: [[VQRDMULHQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.sqrdmulh.v8i16(<8 x i16> %a, <8 x i16> [[SHUFFLE]]) #2
// CHECK: [[VQRDMULHQ_V3_I:%.*]] = bitcast <8 x i16> [[VQRDMULHQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQRDMULHQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VQRDMULHQ_V2_I]]
int16x8_t test_vqrdmulhq_laneq_s16(int16x8_t a, int16x8_t v) {
return vqrdmulhq_laneq_s16(a, v, 7);
}
-// CHECK-LABEL: define <2 x i32> @test_vqrdmulh_laneq_s32(<2 x i32> %a, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vqrdmulh_laneq_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <2 x i32> <i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQRDMULH_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQRDMULH_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQRDMULH_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqrdmulh.v2i32(<2 x i32> [[VQRDMULH_V_I]], <2 x i32> [[VQRDMULH_V1_I]]) #2
+// CHECK: [[VQRDMULH_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqrdmulh.v2i32(<2 x i32> %a, <2 x i32> [[SHUFFLE]]) #2
// CHECK: [[VQRDMULH_V3_I:%.*]] = bitcast <2 x i32> [[VQRDMULH_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQRDMULH_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VQRDMULH_V2_I]]
int32x2_t test_vqrdmulh_laneq_s32(int32x2_t a, int32x4_t v) {
return vqrdmulh_laneq_s32(a, v, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vqrdmulhq_laneq_s32(<4 x i32> %a, <4 x i32> %v) #0 {
+// CHECK-LABEL: @test_vqrdmulhq_laneq_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i32> %v, <4 x i32> %v, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> [[SHUFFLE]] to <16 x i8>
-// CHECK: [[VQRDMULHQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQRDMULHQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VQRDMULHQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqrdmulh.v4i32(<4 x i32> [[VQRDMULHQ_V_I]], <4 x i32> [[VQRDMULHQ_V1_I]]) #2
+// CHECK: [[VQRDMULHQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqrdmulh.v4i32(<4 x i32> %a, <4 x i32> [[SHUFFLE]]) #2
// CHECK: [[VQRDMULHQ_V3_I:%.*]] = bitcast <4 x i32> [[VQRDMULHQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQRDMULHQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VQRDMULHQ_V2_I]]
int32x4_t test_vqrdmulhq_laneq_s32(int32x4_t a, int32x4_t v) {
return vqrdmulhq_laneq_s32(a, v, 3);
}
-
diff --git a/test/CodeGen/aarch64-neon-across.c b/test/CodeGen/aarch64-neon-across.c
index 04a7b26e8a27..6d7a0d5bcde4 100644
--- a/test/CodeGen/aarch64-neon-across.c
+++ b/test/CodeGen/aarch64-neon-across.c
@@ -14,9 +14,7 @@ int16_t test_vaddlv_s8(int8x8_t a) {
}
// CHECK-LABEL: define i32 @test_vaddlv_s16(<4 x i16> %a) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VADDLV_I:%.*]] = call i32 @llvm.aarch64.neon.saddlv.i32.v4i16(<4 x i16> [[TMP1]]) #2
+// CHECK: [[VADDLV_I:%.*]] = call i32 @llvm.aarch64.neon.saddlv.i32.v4i16(<4 x i16> %a) #2
// CHECK: ret i32 [[VADDLV_I]]
int32_t test_vaddlv_s16(int16x4_t a) {
return vaddlv_s16(a);
@@ -31,9 +29,7 @@ uint16_t test_vaddlv_u8(uint8x8_t a) {
}
// CHECK-LABEL: define i32 @test_vaddlv_u16(<4 x i16> %a) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VADDLV_I:%.*]] = call i32 @llvm.aarch64.neon.uaddlv.i32.v4i16(<4 x i16> [[TMP1]]) #2
+// CHECK: [[VADDLV_I:%.*]] = call i32 @llvm.aarch64.neon.uaddlv.i32.v4i16(<4 x i16> %a) #2
// CHECK: ret i32 [[VADDLV_I]]
uint32_t test_vaddlv_u16(uint16x4_t a) {
return vaddlv_u16(a);
@@ -48,18 +44,14 @@ int16_t test_vaddlvq_s8(int8x16_t a) {
}
// CHECK-LABEL: define i32 @test_vaddlvq_s16(<8 x i16> %a) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VADDLV_I:%.*]] = call i32 @llvm.aarch64.neon.saddlv.i32.v8i16(<8 x i16> [[TMP1]]) #2
+// CHECK: [[VADDLV_I:%.*]] = call i32 @llvm.aarch64.neon.saddlv.i32.v8i16(<8 x i16> %a) #2
// CHECK: ret i32 [[VADDLV_I]]
int32_t test_vaddlvq_s16(int16x8_t a) {
return vaddlvq_s16(a);
}
// CHECK-LABEL: define i64 @test_vaddlvq_s32(<4 x i32> %a) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VADDLVQ_S32_I:%.*]] = call i64 @llvm.aarch64.neon.saddlv.i64.v4i32(<4 x i32> [[TMP1]]) #2
+// CHECK: [[VADDLVQ_S32_I:%.*]] = call i64 @llvm.aarch64.neon.saddlv.i64.v4i32(<4 x i32> %a) #2
// CHECK: ret i64 [[VADDLVQ_S32_I]]
int64_t test_vaddlvq_s32(int32x4_t a) {
return vaddlvq_s32(a);
@@ -74,18 +66,14 @@ uint16_t test_vaddlvq_u8(uint8x16_t a) {
}
// CHECK-LABEL: define i32 @test_vaddlvq_u16(<8 x i16> %a) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VADDLV_I:%.*]] = call i32 @llvm.aarch64.neon.uaddlv.i32.v8i16(<8 x i16> [[TMP1]]) #2
+// CHECK: [[VADDLV_I:%.*]] = call i32 @llvm.aarch64.neon.uaddlv.i32.v8i16(<8 x i16> %a) #2
// CHECK: ret i32 [[VADDLV_I]]
uint32_t test_vaddlvq_u16(uint16x8_t a) {
return vaddlvq_u16(a);
}
// CHECK-LABEL: define i64 @test_vaddlvq_u32(<4 x i32> %a) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VADDLVQ_U32_I:%.*]] = call i64 @llvm.aarch64.neon.uaddlv.i64.v4i32(<4 x i32> [[TMP1]]) #2
+// CHECK: [[VADDLVQ_U32_I:%.*]] = call i64 @llvm.aarch64.neon.uaddlv.i64.v4i32(<4 x i32> %a) #2
// CHECK: ret i64 [[VADDLVQ_U32_I]]
uint64_t test_vaddlvq_u32(uint32x4_t a) {
return vaddlvq_u32(a);
@@ -100,9 +88,7 @@ int8_t test_vmaxv_s8(int8x8_t a) {
}
// CHECK-LABEL: define i16 @test_vmaxv_s16(<4 x i16> %a) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMAXV_I:%.*]] = call i32 @llvm.aarch64.neon.smaxv.i32.v4i16(<4 x i16> [[TMP1]]) #2
+// CHECK: [[VMAXV_I:%.*]] = call i32 @llvm.aarch64.neon.smaxv.i32.v4i16(<4 x i16> %a) #2
// CHECK: [[TMP2:%.*]] = trunc i32 [[VMAXV_I]] to i16
// CHECK: ret i16 [[TMP2]]
int16_t test_vmaxv_s16(int16x4_t a) {
@@ -118,9 +104,7 @@ uint8_t test_vmaxv_u8(uint8x8_t a) {
}
// CHECK-LABEL: define i16 @test_vmaxv_u16(<4 x i16> %a) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMAXV_I:%.*]] = call i32 @llvm.aarch64.neon.umaxv.i32.v4i16(<4 x i16> [[TMP1]]) #2
+// CHECK: [[VMAXV_I:%.*]] = call i32 @llvm.aarch64.neon.umaxv.i32.v4i16(<4 x i16> %a) #2
// CHECK: [[TMP2:%.*]] = trunc i32 [[VMAXV_I]] to i16
// CHECK: ret i16 [[TMP2]]
uint16_t test_vmaxv_u16(uint16x4_t a) {
@@ -136,9 +120,7 @@ int8_t test_vmaxvq_s8(int8x16_t a) {
}
// CHECK-LABEL: define i16 @test_vmaxvq_s16(<8 x i16> %a) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VMAXV_I:%.*]] = call i32 @llvm.aarch64.neon.smaxv.i32.v8i16(<8 x i16> [[TMP1]]) #2
+// CHECK: [[VMAXV_I:%.*]] = call i32 @llvm.aarch64.neon.smaxv.i32.v8i16(<8 x i16> %a) #2
// CHECK: [[TMP2:%.*]] = trunc i32 [[VMAXV_I]] to i16
// CHECK: ret i16 [[TMP2]]
int16_t test_vmaxvq_s16(int16x8_t a) {
@@ -146,9 +128,7 @@ int16_t test_vmaxvq_s16(int16x8_t a) {
}
// CHECK-LABEL: define i32 @test_vmaxvq_s32(<4 x i32> %a) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VMAXVQ_S32_I:%.*]] = call i32 @llvm.aarch64.neon.smaxv.i32.v4i32(<4 x i32> [[TMP1]]) #2
+// CHECK: [[VMAXVQ_S32_I:%.*]] = call i32 @llvm.aarch64.neon.smaxv.i32.v4i32(<4 x i32> %a) #2
// CHECK: ret i32 [[VMAXVQ_S32_I]]
int32_t test_vmaxvq_s32(int32x4_t a) {
return vmaxvq_s32(a);
@@ -163,9 +143,7 @@ uint8_t test_vmaxvq_u8(uint8x16_t a) {
}
// CHECK-LABEL: define i16 @test_vmaxvq_u16(<8 x i16> %a) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VMAXV_I:%.*]] = call i32 @llvm.aarch64.neon.umaxv.i32.v8i16(<8 x i16> [[TMP1]]) #2
+// CHECK: [[VMAXV_I:%.*]] = call i32 @llvm.aarch64.neon.umaxv.i32.v8i16(<8 x i16> %a) #2
// CHECK: [[TMP2:%.*]] = trunc i32 [[VMAXV_I]] to i16
// CHECK: ret i16 [[TMP2]]
uint16_t test_vmaxvq_u16(uint16x8_t a) {
@@ -173,9 +151,7 @@ uint16_t test_vmaxvq_u16(uint16x8_t a) {
}
// CHECK-LABEL: define i32 @test_vmaxvq_u32(<4 x i32> %a) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VMAXVQ_U32_I:%.*]] = call i32 @llvm.aarch64.neon.umaxv.i32.v4i32(<4 x i32> [[TMP1]]) #2
+// CHECK: [[VMAXVQ_U32_I:%.*]] = call i32 @llvm.aarch64.neon.umaxv.i32.v4i32(<4 x i32> %a) #2
// CHECK: ret i32 [[VMAXVQ_U32_I]]
uint32_t test_vmaxvq_u32(uint32x4_t a) {
return vmaxvq_u32(a);
@@ -190,9 +166,7 @@ int8_t test_vminv_s8(int8x8_t a) {
}
// CHECK-LABEL: define i16 @test_vminv_s16(<4 x i16> %a) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMINV_I:%.*]] = call i32 @llvm.aarch64.neon.sminv.i32.v4i16(<4 x i16> [[TMP1]]) #2
+// CHECK: [[VMINV_I:%.*]] = call i32 @llvm.aarch64.neon.sminv.i32.v4i16(<4 x i16> %a) #2
// CHECK: [[TMP2:%.*]] = trunc i32 [[VMINV_I]] to i16
// CHECK: ret i16 [[TMP2]]
int16_t test_vminv_s16(int16x4_t a) {
@@ -208,9 +182,7 @@ uint8_t test_vminv_u8(uint8x8_t a) {
}
// CHECK-LABEL: define i16 @test_vminv_u16(<4 x i16> %a) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMINV_I:%.*]] = call i32 @llvm.aarch64.neon.uminv.i32.v4i16(<4 x i16> [[TMP1]]) #2
+// CHECK: [[VMINV_I:%.*]] = call i32 @llvm.aarch64.neon.uminv.i32.v4i16(<4 x i16> %a) #2
// CHECK: [[TMP2:%.*]] = trunc i32 [[VMINV_I]] to i16
// CHECK: ret i16 [[TMP2]]
uint16_t test_vminv_u16(uint16x4_t a) {
@@ -226,9 +198,7 @@ int8_t test_vminvq_s8(int8x16_t a) {
}
// CHECK-LABEL: define i16 @test_vminvq_s16(<8 x i16> %a) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VMINV_I:%.*]] = call i32 @llvm.aarch64.neon.sminv.i32.v8i16(<8 x i16> [[TMP1]]) #2
+// CHECK: [[VMINV_I:%.*]] = call i32 @llvm.aarch64.neon.sminv.i32.v8i16(<8 x i16> %a) #2
// CHECK: [[TMP2:%.*]] = trunc i32 [[VMINV_I]] to i16
// CHECK: ret i16 [[TMP2]]
int16_t test_vminvq_s16(int16x8_t a) {
@@ -236,9 +206,7 @@ int16_t test_vminvq_s16(int16x8_t a) {
}
// CHECK-LABEL: define i32 @test_vminvq_s32(<4 x i32> %a) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VMINVQ_S32_I:%.*]] = call i32 @llvm.aarch64.neon.sminv.i32.v4i32(<4 x i32> [[TMP1]]) #2
+// CHECK: [[VMINVQ_S32_I:%.*]] = call i32 @llvm.aarch64.neon.sminv.i32.v4i32(<4 x i32> %a) #2
// CHECK: ret i32 [[VMINVQ_S32_I]]
int32_t test_vminvq_s32(int32x4_t a) {
return vminvq_s32(a);
@@ -253,9 +221,7 @@ uint8_t test_vminvq_u8(uint8x16_t a) {
}
// CHECK-LABEL: define i16 @test_vminvq_u16(<8 x i16> %a) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VMINV_I:%.*]] = call i32 @llvm.aarch64.neon.uminv.i32.v8i16(<8 x i16> [[TMP1]]) #2
+// CHECK: [[VMINV_I:%.*]] = call i32 @llvm.aarch64.neon.uminv.i32.v8i16(<8 x i16> %a) #2
// CHECK: [[TMP2:%.*]] = trunc i32 [[VMINV_I]] to i16
// CHECK: ret i16 [[TMP2]]
uint16_t test_vminvq_u16(uint16x8_t a) {
@@ -263,9 +229,7 @@ uint16_t test_vminvq_u16(uint16x8_t a) {
}
// CHECK-LABEL: define i32 @test_vminvq_u32(<4 x i32> %a) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VMINVQ_U32_I:%.*]] = call i32 @llvm.aarch64.neon.uminv.i32.v4i32(<4 x i32> [[TMP1]]) #2
+// CHECK: [[VMINVQ_U32_I:%.*]] = call i32 @llvm.aarch64.neon.uminv.i32.v4i32(<4 x i32> %a) #2
// CHECK: ret i32 [[VMINVQ_U32_I]]
uint32_t test_vminvq_u32(uint32x4_t a) {
return vminvq_u32(a);
@@ -280,9 +244,7 @@ int8_t test_vaddv_s8(int8x8_t a) {
}
// CHECK-LABEL: define i16 @test_vaddv_s16(<4 x i16> %a) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VADDV_I:%.*]] = call i32 @llvm.aarch64.neon.saddv.i32.v4i16(<4 x i16> [[TMP1]]) #2
+// CHECK: [[VADDV_I:%.*]] = call i32 @llvm.aarch64.neon.saddv.i32.v4i16(<4 x i16> %a) #2
// CHECK: [[TMP2:%.*]] = trunc i32 [[VADDV_I]] to i16
// CHECK: ret i16 [[TMP2]]
int16_t test_vaddv_s16(int16x4_t a) {
@@ -298,9 +260,7 @@ uint8_t test_vaddv_u8(uint8x8_t a) {
}
// CHECK-LABEL: define i16 @test_vaddv_u16(<4 x i16> %a) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VADDV_I:%.*]] = call i32 @llvm.aarch64.neon.uaddv.i32.v4i16(<4 x i16> [[TMP1]]) #2
+// CHECK: [[VADDV_I:%.*]] = call i32 @llvm.aarch64.neon.uaddv.i32.v4i16(<4 x i16> %a) #2
// CHECK: [[TMP2:%.*]] = trunc i32 [[VADDV_I]] to i16
// CHECK: ret i16 [[TMP2]]
uint16_t test_vaddv_u16(uint16x4_t a) {
@@ -316,9 +276,7 @@ int8_t test_vaddvq_s8(int8x16_t a) {
}
// CHECK-LABEL: define i16 @test_vaddvq_s16(<8 x i16> %a) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VADDV_I:%.*]] = call i32 @llvm.aarch64.neon.saddv.i32.v8i16(<8 x i16> [[TMP1]]) #2
+// CHECK: [[VADDV_I:%.*]] = call i32 @llvm.aarch64.neon.saddv.i32.v8i16(<8 x i16> %a) #2
// CHECK: [[TMP2:%.*]] = trunc i32 [[VADDV_I]] to i16
// CHECK: ret i16 [[TMP2]]
int16_t test_vaddvq_s16(int16x8_t a) {
@@ -326,9 +284,7 @@ int16_t test_vaddvq_s16(int16x8_t a) {
}
// CHECK-LABEL: define i32 @test_vaddvq_s32(<4 x i32> %a) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VADDVQ_S32_I:%.*]] = call i32 @llvm.aarch64.neon.saddv.i32.v4i32(<4 x i32> [[TMP1]]) #2
+// CHECK: [[VADDVQ_S32_I:%.*]] = call i32 @llvm.aarch64.neon.saddv.i32.v4i32(<4 x i32> %a) #2
// CHECK: ret i32 [[VADDVQ_S32_I]]
int32_t test_vaddvq_s32(int32x4_t a) {
return vaddvq_s32(a);
@@ -343,9 +299,7 @@ uint8_t test_vaddvq_u8(uint8x16_t a) {
}
// CHECK-LABEL: define i16 @test_vaddvq_u16(<8 x i16> %a) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VADDV_I:%.*]] = call i32 @llvm.aarch64.neon.uaddv.i32.v8i16(<8 x i16> [[TMP1]]) #2
+// CHECK: [[VADDV_I:%.*]] = call i32 @llvm.aarch64.neon.uaddv.i32.v8i16(<8 x i16> %a) #2
// CHECK: [[TMP2:%.*]] = trunc i32 [[VADDV_I]] to i16
// CHECK: ret i16 [[TMP2]]
uint16_t test_vaddvq_u16(uint16x8_t a) {
@@ -353,45 +307,35 @@ uint16_t test_vaddvq_u16(uint16x8_t a) {
}
// CHECK-LABEL: define i32 @test_vaddvq_u32(<4 x i32> %a) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VADDVQ_U32_I:%.*]] = call i32 @llvm.aarch64.neon.uaddv.i32.v4i32(<4 x i32> [[TMP1]]) #2
+// CHECK: [[VADDVQ_U32_I:%.*]] = call i32 @llvm.aarch64.neon.uaddv.i32.v4i32(<4 x i32> %a) #2
// CHECK: ret i32 [[VADDVQ_U32_I]]
uint32_t test_vaddvq_u32(uint32x4_t a) {
return vaddvq_u32(a);
}
// CHECK-LABEL: define float @test_vmaxvq_f32(<4 x float> %a) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VMAXVQ_F32_I:%.*]] = call float @llvm.aarch64.neon.fmaxv.f32.v4f32(<4 x float> [[TMP1]]) #2
+// CHECK: [[VMAXVQ_F32_I:%.*]] = call float @llvm.aarch64.neon.fmaxv.f32.v4f32(<4 x float> %a) #2
// CHECK: ret float [[VMAXVQ_F32_I]]
float32_t test_vmaxvq_f32(float32x4_t a) {
return vmaxvq_f32(a);
}
// CHECK-LABEL: define float @test_vminvq_f32(<4 x float> %a) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VMINVQ_F32_I:%.*]] = call float @llvm.aarch64.neon.fminv.f32.v4f32(<4 x float> [[TMP1]]) #2
+// CHECK: [[VMINVQ_F32_I:%.*]] = call float @llvm.aarch64.neon.fminv.f32.v4f32(<4 x float> %a) #2
// CHECK: ret float [[VMINVQ_F32_I]]
float32_t test_vminvq_f32(float32x4_t a) {
return vminvq_f32(a);
}
// CHECK-LABEL: define float @test_vmaxnmvq_f32(<4 x float> %a) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VMAXNMVQ_F32_I:%.*]] = call float @llvm.aarch64.neon.fmaxnmv.f32.v4f32(<4 x float> [[TMP1]]) #2
+// CHECK: [[VMAXNMVQ_F32_I:%.*]] = call float @llvm.aarch64.neon.fmaxnmv.f32.v4f32(<4 x float> %a) #2
// CHECK: ret float [[VMAXNMVQ_F32_I]]
float32_t test_vmaxnmvq_f32(float32x4_t a) {
return vmaxnmvq_f32(a);
}
// CHECK-LABEL: define float @test_vminnmvq_f32(<4 x float> %a) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VMINNMVQ_F32_I:%.*]] = call float @llvm.aarch64.neon.fminnmv.f32.v4f32(<4 x float> [[TMP1]]) #2
+// CHECK: [[VMINNMVQ_F32_I:%.*]] = call float @llvm.aarch64.neon.fminnmv.f32.v4f32(<4 x float> %a) #2
// CHECK: ret float [[VMINNMVQ_F32_I]]
float32_t test_vminnmvq_f32(float32x4_t a) {
return vminnmvq_f32(a);
diff --git a/test/CodeGen/aarch64-neon-fma.c b/test/CodeGen/aarch64-neon-fma.c
index 836321af0609..6ada533c66ee 100644
--- a/test/CodeGen/aarch64-neon-fma.c
+++ b/test/CodeGen/aarch64-neon-fma.c
@@ -214,13 +214,7 @@ float32x4_t test_vmlsq_laneq_f32(float32x4_t a, float32x4_t b, float32x4_t v) {
// CHECK-LABEL: define <2 x double> @test_vfmaq_n_f64(<2 x double> %a, <2 x double> %b, double %c) #0 {
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x double> undef, double %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x double> [[VECINIT_I]], double %c, i32 1
-// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <2 x double> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <2 x double> [[VECINIT1_I]] to <16 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x double>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <2 x double>
-// CHECK: [[TMP6:%.*]] = call <2 x double> @llvm.fma.v2f64(<2 x double> [[TMP4]], <2 x double> [[TMP5]], <2 x double> [[TMP3]]) #2
+// CHECK: [[TMP6:%.*]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %b, <2 x double> [[VECINIT1_I]], <2 x double> %a)
// CHECK: ret <2 x double> [[TMP6]]
float64x2_t test_vfmaq_n_f64(float64x2_t a, float64x2_t b, float64_t c) {
return vfmaq_n_f64(a, b, c);
@@ -230,13 +224,7 @@ float64x2_t test_vfmaq_n_f64(float64x2_t a, float64x2_t b, float64_t c) {
// CHECK: [[SUB_I:%.*]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %b
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x double> undef, double %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x double> [[VECINIT_I]], double %c, i32 1
-// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <2 x double> [[SUB_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <2 x double> [[VECINIT1_I]] to <16 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x double>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <2 x double>
-// CHECK: [[TMP6:%.*]] = call <2 x double> @llvm.fma.v2f64(<2 x double> [[TMP4]], <2 x double> [[TMP5]], <2 x double> [[TMP3]]) #2
+// CHECK: [[TMP6:%.*]] = call <2 x double> @llvm.fma.v2f64(<2 x double> [[SUB_I]], <2 x double> [[VECINIT1_I]], <2 x double> %a) #2
// CHECK: ret <2 x double> [[TMP6]]
float64x2_t test_vfmsq_n_f64(float64x2_t a, float64x2_t b, float64_t c) {
return vfmsq_n_f64(a, b, c);
diff --git a/test/CodeGen/aarch64-neon-intrinsics.c b/test/CodeGen/aarch64-neon-intrinsics.c
index b087ce91e568..2ffbcdce372c 100644
--- a/test/CodeGen/aarch64-neon-intrinsics.c
+++ b/test/CodeGen/aarch64-neon-intrinsics.c
@@ -7,396 +7,392 @@
#include <arm_neon.h>
-// CHECK-LABEL: define <8 x i8> @test_vadd_s8(<8 x i8> %v1, <8 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vadd_s8(
// CHECK: [[ADD_I:%.*]] = add <8 x i8> %v1, %v2
// CHECK: ret <8 x i8> [[ADD_I]]
int8x8_t test_vadd_s8(int8x8_t v1, int8x8_t v2) {
return vadd_s8(v1, v2);
}
-// CHECK-LABEL: define <4 x i16> @test_vadd_s16(<4 x i16> %v1, <4 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vadd_s16(
// CHECK: [[ADD_I:%.*]] = add <4 x i16> %v1, %v2
// CHECK: ret <4 x i16> [[ADD_I]]
int16x4_t test_vadd_s16(int16x4_t v1, int16x4_t v2) {
return vadd_s16(v1, v2);
}
-// CHECK-LABEL: define <2 x i32> @test_vadd_s32(<2 x i32> %v1, <2 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vadd_s32(
// CHECK: [[ADD_I:%.*]] = add <2 x i32> %v1, %v2
// CHECK: ret <2 x i32> [[ADD_I]]
int32x2_t test_vadd_s32(int32x2_t v1, int32x2_t v2) {
return vadd_s32(v1, v2);
}
-// CHECK-LABEL: define <1 x i64> @test_vadd_s64(<1 x i64> %v1, <1 x i64> %v2) #0 {
+// CHECK-LABEL: @test_vadd_s64(
// CHECK: [[ADD_I:%.*]] = add <1 x i64> %v1, %v2
// CHECK: ret <1 x i64> [[ADD_I]]
int64x1_t test_vadd_s64(int64x1_t v1, int64x1_t v2) {
return vadd_s64(v1, v2);
}
-// CHECK-LABEL: define <2 x float> @test_vadd_f32(<2 x float> %v1, <2 x float> %v2) #0 {
+// CHECK-LABEL: @test_vadd_f32(
// CHECK: [[ADD_I:%.*]] = fadd <2 x float> %v1, %v2
// CHECK: ret <2 x float> [[ADD_I]]
float32x2_t test_vadd_f32(float32x2_t v1, float32x2_t v2) {
return vadd_f32(v1, v2);
}
-// CHECK-LABEL: define <8 x i8> @test_vadd_u8(<8 x i8> %v1, <8 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vadd_u8(
// CHECK: [[ADD_I:%.*]] = add <8 x i8> %v1, %v2
// CHECK: ret <8 x i8> [[ADD_I]]
uint8x8_t test_vadd_u8(uint8x8_t v1, uint8x8_t v2) {
return vadd_u8(v1, v2);
}
-// CHECK-LABEL: define <4 x i16> @test_vadd_u16(<4 x i16> %v1, <4 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vadd_u16(
// CHECK: [[ADD_I:%.*]] = add <4 x i16> %v1, %v2
// CHECK: ret <4 x i16> [[ADD_I]]
uint16x4_t test_vadd_u16(uint16x4_t v1, uint16x4_t v2) {
return vadd_u16(v1, v2);
}
-// CHECK-LABEL: define <2 x i32> @test_vadd_u32(<2 x i32> %v1, <2 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vadd_u32(
// CHECK: [[ADD_I:%.*]] = add <2 x i32> %v1, %v2
// CHECK: ret <2 x i32> [[ADD_I]]
uint32x2_t test_vadd_u32(uint32x2_t v1, uint32x2_t v2) {
return vadd_u32(v1, v2);
}
-// CHECK-LABEL: define <1 x i64> @test_vadd_u64(<1 x i64> %v1, <1 x i64> %v2) #0 {
+// CHECK-LABEL: @test_vadd_u64(
// CHECK: [[ADD_I:%.*]] = add <1 x i64> %v1, %v2
// CHECK: ret <1 x i64> [[ADD_I]]
uint64x1_t test_vadd_u64(uint64x1_t v1, uint64x1_t v2) {
return vadd_u64(v1, v2);
}
-// CHECK-LABEL: define <16 x i8> @test_vaddq_s8(<16 x i8> %v1, <16 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vaddq_s8(
// CHECK: [[ADD_I:%.*]] = add <16 x i8> %v1, %v2
// CHECK: ret <16 x i8> [[ADD_I]]
int8x16_t test_vaddq_s8(int8x16_t v1, int8x16_t v2) {
return vaddq_s8(v1, v2);
}
-// CHECK-LABEL: define <8 x i16> @test_vaddq_s16(<8 x i16> %v1, <8 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vaddq_s16(
// CHECK: [[ADD_I:%.*]] = add <8 x i16> %v1, %v2
// CHECK: ret <8 x i16> [[ADD_I]]
int16x8_t test_vaddq_s16(int16x8_t v1, int16x8_t v2) {
return vaddq_s16(v1, v2);
}
-// CHECK-LABEL: define <4 x i32> @test_vaddq_s32(<4 x i32> %v1, <4 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vaddq_s32(
// CHECK: [[ADD_I:%.*]] = add <4 x i32> %v1, %v2
// CHECK: ret <4 x i32> [[ADD_I]]
-int32x4_t test_vaddq_s32(int32x4_t v1,int32x4_t v2) {
+int32x4_t test_vaddq_s32(int32x4_t v1, int32x4_t v2) {
return vaddq_s32(v1, v2);
}
-// CHECK-LABEL: define <2 x i64> @test_vaddq_s64(<2 x i64> %v1, <2 x i64> %v2) #0 {
+// CHECK-LABEL: @test_vaddq_s64(
// CHECK: [[ADD_I:%.*]] = add <2 x i64> %v1, %v2
// CHECK: ret <2 x i64> [[ADD_I]]
int64x2_t test_vaddq_s64(int64x2_t v1, int64x2_t v2) {
return vaddq_s64(v1, v2);
}
-// CHECK-LABEL: define <4 x float> @test_vaddq_f32(<4 x float> %v1, <4 x float> %v2) #0 {
+// CHECK-LABEL: @test_vaddq_f32(
// CHECK: [[ADD_I:%.*]] = fadd <4 x float> %v1, %v2
// CHECK: ret <4 x float> [[ADD_I]]
float32x4_t test_vaddq_f32(float32x4_t v1, float32x4_t v2) {
return vaddq_f32(v1, v2);
}
-// CHECK-LABEL: define <2 x double> @test_vaddq_f64(<2 x double> %v1, <2 x double> %v2) #0 {
+// CHECK-LABEL: @test_vaddq_f64(
// CHECK: [[ADD_I:%.*]] = fadd <2 x double> %v1, %v2
// CHECK: ret <2 x double> [[ADD_I]]
float64x2_t test_vaddq_f64(float64x2_t v1, float64x2_t v2) {
return vaddq_f64(v1, v2);
}
-// CHECK-LABEL: define <16 x i8> @test_vaddq_u8(<16 x i8> %v1, <16 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vaddq_u8(
// CHECK: [[ADD_I:%.*]] = add <16 x i8> %v1, %v2
// CHECK: ret <16 x i8> [[ADD_I]]
uint8x16_t test_vaddq_u8(uint8x16_t v1, uint8x16_t v2) {
return vaddq_u8(v1, v2);
}
-// CHECK-LABEL: define <8 x i16> @test_vaddq_u16(<8 x i16> %v1, <8 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vaddq_u16(
// CHECK: [[ADD_I:%.*]] = add <8 x i16> %v1, %v2
// CHECK: ret <8 x i16> [[ADD_I]]
uint16x8_t test_vaddq_u16(uint16x8_t v1, uint16x8_t v2) {
return vaddq_u16(v1, v2);
}
-// CHECK-LABEL: define <4 x i32> @test_vaddq_u32(<4 x i32> %v1, <4 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vaddq_u32(
// CHECK: [[ADD_I:%.*]] = add <4 x i32> %v1, %v2
// CHECK: ret <4 x i32> [[ADD_I]]
uint32x4_t test_vaddq_u32(uint32x4_t v1, uint32x4_t v2) {
return vaddq_u32(v1, v2);
}
-// CHECK-LABEL: define <2 x i64> @test_vaddq_u64(<2 x i64> %v1, <2 x i64> %v2) #0 {
+// CHECK-LABEL: @test_vaddq_u64(
// CHECK: [[ADD_I:%.*]] = add <2 x i64> %v1, %v2
// CHECK: ret <2 x i64> [[ADD_I]]
uint64x2_t test_vaddq_u64(uint64x2_t v1, uint64x2_t v2) {
return vaddq_u64(v1, v2);
}
-// CHECK-LABEL: define <8 x i8> @test_vsub_s8(<8 x i8> %v1, <8 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vsub_s8(
// CHECK: [[SUB_I:%.*]] = sub <8 x i8> %v1, %v2
// CHECK: ret <8 x i8> [[SUB_I]]
int8x8_t test_vsub_s8(int8x8_t v1, int8x8_t v2) {
return vsub_s8(v1, v2);
}
-// CHECK-LABEL: define <4 x i16> @test_vsub_s16(<4 x i16> %v1, <4 x i16> %v2) #0 {
+
+// CHECK-LABEL: @test_vsub_s16(
// CHECK: [[SUB_I:%.*]] = sub <4 x i16> %v1, %v2
// CHECK: ret <4 x i16> [[SUB_I]]
int16x4_t test_vsub_s16(int16x4_t v1, int16x4_t v2) {
return vsub_s16(v1, v2);
}
-// CHECK-LABEL: define <2 x i32> @test_vsub_s32(<2 x i32> %v1, <2 x i32> %v2) #0 {
+
+// CHECK-LABEL: @test_vsub_s32(
// CHECK: [[SUB_I:%.*]] = sub <2 x i32> %v1, %v2
// CHECK: ret <2 x i32> [[SUB_I]]
int32x2_t test_vsub_s32(int32x2_t v1, int32x2_t v2) {
return vsub_s32(v1, v2);
}
-// CHECK-LABEL: define <1 x i64> @test_vsub_s64(<1 x i64> %v1, <1 x i64> %v2) #0 {
+// CHECK-LABEL: @test_vsub_s64(
// CHECK: [[SUB_I:%.*]] = sub <1 x i64> %v1, %v2
// CHECK: ret <1 x i64> [[SUB_I]]
int64x1_t test_vsub_s64(int64x1_t v1, int64x1_t v2) {
return vsub_s64(v1, v2);
}
-// CHECK-LABEL: define <2 x float> @test_vsub_f32(<2 x float> %v1, <2 x float> %v2) #0 {
+// CHECK-LABEL: @test_vsub_f32(
// CHECK: [[SUB_I:%.*]] = fsub <2 x float> %v1, %v2
// CHECK: ret <2 x float> [[SUB_I]]
float32x2_t test_vsub_f32(float32x2_t v1, float32x2_t v2) {
return vsub_f32(v1, v2);
}
-// CHECK-LABEL: define <8 x i8> @test_vsub_u8(<8 x i8> %v1, <8 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vsub_u8(
// CHECK: [[SUB_I:%.*]] = sub <8 x i8> %v1, %v2
// CHECK: ret <8 x i8> [[SUB_I]]
uint8x8_t test_vsub_u8(uint8x8_t v1, uint8x8_t v2) {
return vsub_u8(v1, v2);
}
-// CHECK-LABEL: define <4 x i16> @test_vsub_u16(<4 x i16> %v1, <4 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vsub_u16(
// CHECK: [[SUB_I:%.*]] = sub <4 x i16> %v1, %v2
// CHECK: ret <4 x i16> [[SUB_I]]
uint16x4_t test_vsub_u16(uint16x4_t v1, uint16x4_t v2) {
return vsub_u16(v1, v2);
}
-// CHECK-LABEL: define <2 x i32> @test_vsub_u32(<2 x i32> %v1, <2 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vsub_u32(
// CHECK: [[SUB_I:%.*]] = sub <2 x i32> %v1, %v2
// CHECK: ret <2 x i32> [[SUB_I]]
uint32x2_t test_vsub_u32(uint32x2_t v1, uint32x2_t v2) {
return vsub_u32(v1, v2);
}
-// CHECK-LABEL: define <1 x i64> @test_vsub_u64(<1 x i64> %v1, <1 x i64> %v2) #0 {
+// CHECK-LABEL: @test_vsub_u64(
// CHECK: [[SUB_I:%.*]] = sub <1 x i64> %v1, %v2
// CHECK: ret <1 x i64> [[SUB_I]]
uint64x1_t test_vsub_u64(uint64x1_t v1, uint64x1_t v2) {
return vsub_u64(v1, v2);
}
-// CHECK-LABEL: define <16 x i8> @test_vsubq_s8(<16 x i8> %v1, <16 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vsubq_s8(
// CHECK: [[SUB_I:%.*]] = sub <16 x i8> %v1, %v2
// CHECK: ret <16 x i8> [[SUB_I]]
int8x16_t test_vsubq_s8(int8x16_t v1, int8x16_t v2) {
return vsubq_s8(v1, v2);
}
-// CHECK-LABEL: define <8 x i16> @test_vsubq_s16(<8 x i16> %v1, <8 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vsubq_s16(
// CHECK: [[SUB_I:%.*]] = sub <8 x i16> %v1, %v2
// CHECK: ret <8 x i16> [[SUB_I]]
int16x8_t test_vsubq_s16(int16x8_t v1, int16x8_t v2) {
return vsubq_s16(v1, v2);
}
-// CHECK-LABEL: define <4 x i32> @test_vsubq_s32(<4 x i32> %v1, <4 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vsubq_s32(
// CHECK: [[SUB_I:%.*]] = sub <4 x i32> %v1, %v2
// CHECK: ret <4 x i32> [[SUB_I]]
-int32x4_t test_vsubq_s32(int32x4_t v1,int32x4_t v2) {
+int32x4_t test_vsubq_s32(int32x4_t v1, int32x4_t v2) {
return vsubq_s32(v1, v2);
}
-// CHECK-LABEL: define <2 x i64> @test_vsubq_s64(<2 x i64> %v1, <2 x i64> %v2) #0 {
+// CHECK-LABEL: @test_vsubq_s64(
// CHECK: [[SUB_I:%.*]] = sub <2 x i64> %v1, %v2
// CHECK: ret <2 x i64> [[SUB_I]]
int64x2_t test_vsubq_s64(int64x2_t v1, int64x2_t v2) {
return vsubq_s64(v1, v2);
}
-// CHECK-LABEL: define <4 x float> @test_vsubq_f32(<4 x float> %v1, <4 x float> %v2) #0 {
+// CHECK-LABEL: @test_vsubq_f32(
// CHECK: [[SUB_I:%.*]] = fsub <4 x float> %v1, %v2
// CHECK: ret <4 x float> [[SUB_I]]
float32x4_t test_vsubq_f32(float32x4_t v1, float32x4_t v2) {
return vsubq_f32(v1, v2);
}
-// CHECK-LABEL: define <2 x double> @test_vsubq_f64(<2 x double> %v1, <2 x double> %v2) #0 {
+// CHECK-LABEL: @test_vsubq_f64(
// CHECK: [[SUB_I:%.*]] = fsub <2 x double> %v1, %v2
// CHECK: ret <2 x double> [[SUB_I]]
float64x2_t test_vsubq_f64(float64x2_t v1, float64x2_t v2) {
return vsubq_f64(v1, v2);
}
-// CHECK-LABEL: define <16 x i8> @test_vsubq_u8(<16 x i8> %v1, <16 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vsubq_u8(
// CHECK: [[SUB_I:%.*]] = sub <16 x i8> %v1, %v2
// CHECK: ret <16 x i8> [[SUB_I]]
uint8x16_t test_vsubq_u8(uint8x16_t v1, uint8x16_t v2) {
return vsubq_u8(v1, v2);
}
-// CHECK-LABEL: define <8 x i16> @test_vsubq_u16(<8 x i16> %v1, <8 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vsubq_u16(
// CHECK: [[SUB_I:%.*]] = sub <8 x i16> %v1, %v2
// CHECK: ret <8 x i16> [[SUB_I]]
uint16x8_t test_vsubq_u16(uint16x8_t v1, uint16x8_t v2) {
return vsubq_u16(v1, v2);
}
-// CHECK-LABEL: define <4 x i32> @test_vsubq_u32(<4 x i32> %v1, <4 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vsubq_u32(
// CHECK: [[SUB_I:%.*]] = sub <4 x i32> %v1, %v2
// CHECK: ret <4 x i32> [[SUB_I]]
uint32x4_t test_vsubq_u32(uint32x4_t v1, uint32x4_t v2) {
return vsubq_u32(v1, v2);
}
-// CHECK-LABEL: define <2 x i64> @test_vsubq_u64(<2 x i64> %v1, <2 x i64> %v2) #0 {
+// CHECK-LABEL: @test_vsubq_u64(
// CHECK: [[SUB_I:%.*]] = sub <2 x i64> %v1, %v2
// CHECK: ret <2 x i64> [[SUB_I]]
uint64x2_t test_vsubq_u64(uint64x2_t v1, uint64x2_t v2) {
return vsubq_u64(v1, v2);
}
-// CHECK-LABEL: define <8 x i8> @test_vmul_s8(<8 x i8> %v1, <8 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vmul_s8(
// CHECK: [[MUL_I:%.*]] = mul <8 x i8> %v1, %v2
// CHECK: ret <8 x i8> [[MUL_I]]
int8x8_t test_vmul_s8(int8x8_t v1, int8x8_t v2) {
return vmul_s8(v1, v2);
}
-// CHECK-LABEL: define <4 x i16> @test_vmul_s16(<4 x i16> %v1, <4 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vmul_s16(
// CHECK: [[MUL_I:%.*]] = mul <4 x i16> %v1, %v2
// CHECK: ret <4 x i16> [[MUL_I]]
int16x4_t test_vmul_s16(int16x4_t v1, int16x4_t v2) {
return vmul_s16(v1, v2);
}
-// CHECK-LABEL: define <2 x i32> @test_vmul_s32(<2 x i32> %v1, <2 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vmul_s32(
// CHECK: [[MUL_I:%.*]] = mul <2 x i32> %v1, %v2
// CHECK: ret <2 x i32> [[MUL_I]]
int32x2_t test_vmul_s32(int32x2_t v1, int32x2_t v2) {
return vmul_s32(v1, v2);
}
-// CHECK-LABEL: define <2 x float> @test_vmul_f32(<2 x float> %v1, <2 x float> %v2) #0 {
+// CHECK-LABEL: @test_vmul_f32(
// CHECK: [[MUL_I:%.*]] = fmul <2 x float> %v1, %v2
// CHECK: ret <2 x float> [[MUL_I]]
float32x2_t test_vmul_f32(float32x2_t v1, float32x2_t v2) {
return vmul_f32(v1, v2);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vmul_u8(<8 x i8> %v1, <8 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vmul_u8(
// CHECK: [[MUL_I:%.*]] = mul <8 x i8> %v1, %v2
// CHECK: ret <8 x i8> [[MUL_I]]
uint8x8_t test_vmul_u8(uint8x8_t v1, uint8x8_t v2) {
return vmul_u8(v1, v2);
}
-// CHECK-LABEL: define <4 x i16> @test_vmul_u16(<4 x i16> %v1, <4 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vmul_u16(
// CHECK: [[MUL_I:%.*]] = mul <4 x i16> %v1, %v2
// CHECK: ret <4 x i16> [[MUL_I]]
uint16x4_t test_vmul_u16(uint16x4_t v1, uint16x4_t v2) {
return vmul_u16(v1, v2);
}
-// CHECK-LABEL: define <2 x i32> @test_vmul_u32(<2 x i32> %v1, <2 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vmul_u32(
// CHECK: [[MUL_I:%.*]] = mul <2 x i32> %v1, %v2
// CHECK: ret <2 x i32> [[MUL_I]]
uint32x2_t test_vmul_u32(uint32x2_t v1, uint32x2_t v2) {
return vmul_u32(v1, v2);
}
-// CHECK-LABEL: define <16 x i8> @test_vmulq_s8(<16 x i8> %v1, <16 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vmulq_s8(
// CHECK: [[MUL_I:%.*]] = mul <16 x i8> %v1, %v2
// CHECK: ret <16 x i8> [[MUL_I]]
int8x16_t test_vmulq_s8(int8x16_t v1, int8x16_t v2) {
return vmulq_s8(v1, v2);
}
-// CHECK-LABEL: define <8 x i16> @test_vmulq_s16(<8 x i16> %v1, <8 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vmulq_s16(
// CHECK: [[MUL_I:%.*]] = mul <8 x i16> %v1, %v2
// CHECK: ret <8 x i16> [[MUL_I]]
int16x8_t test_vmulq_s16(int16x8_t v1, int16x8_t v2) {
return vmulq_s16(v1, v2);
}
-// CHECK-LABEL: define <4 x i32> @test_vmulq_s32(<4 x i32> %v1, <4 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vmulq_s32(
// CHECK: [[MUL_I:%.*]] = mul <4 x i32> %v1, %v2
// CHECK: ret <4 x i32> [[MUL_I]]
int32x4_t test_vmulq_s32(int32x4_t v1, int32x4_t v2) {
return vmulq_s32(v1, v2);
}
-
-// CHECK-LABEL: define <16 x i8> @test_vmulq_u8(<16 x i8> %v1, <16 x i8> %v2) #0 {
+
+// CHECK-LABEL: @test_vmulq_u8(
// CHECK: [[MUL_I:%.*]] = mul <16 x i8> %v1, %v2
// CHECK: ret <16 x i8> [[MUL_I]]
uint8x16_t test_vmulq_u8(uint8x16_t v1, uint8x16_t v2) {
return vmulq_u8(v1, v2);
}
-// CHECK-LABEL: define <8 x i16> @test_vmulq_u16(<8 x i16> %v1, <8 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vmulq_u16(
// CHECK: [[MUL_I:%.*]] = mul <8 x i16> %v1, %v2
// CHECK: ret <8 x i16> [[MUL_I]]
uint16x8_t test_vmulq_u16(uint16x8_t v1, uint16x8_t v2) {
return vmulq_u16(v1, v2);
}
-// CHECK-LABEL: define <4 x i32> @test_vmulq_u32(<4 x i32> %v1, <4 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vmulq_u32(
// CHECK: [[MUL_I:%.*]] = mul <4 x i32> %v1, %v2
// CHECK: ret <4 x i32> [[MUL_I]]
uint32x4_t test_vmulq_u32(uint32x4_t v1, uint32x4_t v2) {
return vmulq_u32(v1, v2);
}
-// CHECK-LABEL: define <4 x float> @test_vmulq_f32(<4 x float> %v1, <4 x float> %v2) #0 {
+// CHECK-LABEL: @test_vmulq_f32(
// CHECK: [[MUL_I:%.*]] = fmul <4 x float> %v1, %v2
// CHECK: ret <4 x float> [[MUL_I]]
float32x4_t test_vmulq_f32(float32x4_t v1, float32x4_t v2) {
return vmulq_f32(v1, v2);
}
-// CHECK-LABEL: define <2 x double> @test_vmulq_f64(<2 x double> %v1, <2 x double> %v2) #0 {
+// CHECK-LABEL: @test_vmulq_f64(
// CHECK: [[MUL_I:%.*]] = fmul <2 x double> %v1, %v2
// CHECK: ret <2 x double> [[MUL_I]]
float64x2_t test_vmulq_f64(float64x2_t v1, float64x2_t v2) {
return vmulq_f64(v1, v2);
}
-// CHECK-LABEL: define <8 x i8> @test_vmul_p8(<8 x i8> %v1, <8 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vmul_p8(
// CHECK: [[VMUL_V_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.pmul.v8i8(<8 x i8> %v1, <8 x i8> %v2) #4
// CHECK: ret <8 x i8> [[VMUL_V_I]]
poly8x8_t test_vmul_p8(poly8x8_t v1, poly8x8_t v2) {
- // test_vmul_p8
return vmul_p8(v1, v2);
- // pmul {{v[0-9]+}}.8b, {{v[0-9]+}}.8b, {{v[0-9]+}}.8b
}
-// CHECK-LABEL: define <16 x i8> @test_vmulq_p8(<16 x i8> %v1, <16 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vmulq_p8(
// CHECK: [[VMULQ_V_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.pmul.v16i8(<16 x i8> %v1, <16 x i8> %v2) #4
// CHECK: ret <16 x i8> [[VMULQ_V_I]]
poly8x16_t test_vmulq_p8(poly8x16_t v1, poly8x16_t v2) {
- // test_vmulq_p8
return vmulq_p8(v1, v2);
- // pmul {{v[0-9]+}}.16b, {{v[0-9]+}}.16b, {{v[0-9]+}}.16b
}
-
-// CHECK-LABEL: define <8 x i8> @test_vmla_s8(<8 x i8> %v1, <8 x i8> %v2, <8 x i8> %v3) #0 {
+// CHECK-LABEL: @test_vmla_s8(
// CHECK: [[MUL_I:%.*]] = mul <8 x i8> %v2, %v3
// CHECK: [[ADD_I:%.*]] = add <8 x i8> %v1, [[MUL_I]]
// CHECK: ret <8 x i8> [[ADD_I]]
@@ -404,7 +400,7 @@ int8x8_t test_vmla_s8(int8x8_t v1, int8x8_t v2, int8x8_t v3) {
return vmla_s8(v1, v2, v3);
}
-// CHECK-LABEL: define <8 x i8> @test_vmla_s16(<4 x i16> %v1, <4 x i16> %v2, <4 x i16> %v3) #0 {
+// CHECK-LABEL: @test_vmla_s16(
// CHECK: [[MUL_I:%.*]] = mul <4 x i16> %v2, %v3
// CHECK: [[ADD_I:%.*]] = add <4 x i16> %v1, [[MUL_I]]
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[ADD_I]] to <8 x i8>
@@ -413,7 +409,7 @@ int8x8_t test_vmla_s16(int16x4_t v1, int16x4_t v2, int16x4_t v3) {
return vmla_s16(v1, v2, v3);
}
-// CHECK-LABEL: define <2 x i32> @test_vmla_s32(<2 x i32> %v1, <2 x i32> %v2, <2 x i32> %v3) #0 {
+// CHECK-LABEL: @test_vmla_s32(
// CHECK: [[MUL_I:%.*]] = mul <2 x i32> %v2, %v3
// CHECK: [[ADD_I:%.*]] = add <2 x i32> %v1, [[MUL_I]]
// CHECK: ret <2 x i32> [[ADD_I]]
@@ -421,7 +417,7 @@ int32x2_t test_vmla_s32(int32x2_t v1, int32x2_t v2, int32x2_t v3) {
return vmla_s32(v1, v2, v3);
}
-// CHECK-LABEL: define <2 x float> @test_vmla_f32(<2 x float> %v1, <2 x float> %v2, <2 x float> %v3) #0 {
+// CHECK-LABEL: @test_vmla_f32(
// CHECK: [[MUL_I:%.*]] = fmul <2 x float> %v2, %v3
// CHECK: [[ADD_I:%.*]] = fadd <2 x float> %v1, [[MUL_I]]
// CHECK: ret <2 x float> [[ADD_I]]
@@ -429,7 +425,7 @@ float32x2_t test_vmla_f32(float32x2_t v1, float32x2_t v2, float32x2_t v3) {
return vmla_f32(v1, v2, v3);
}
-// CHECK-LABEL: define <8 x i8> @test_vmla_u8(<8 x i8> %v1, <8 x i8> %v2, <8 x i8> %v3) #0 {
+// CHECK-LABEL: @test_vmla_u8(
// CHECK: [[MUL_I:%.*]] = mul <8 x i8> %v2, %v3
// CHECK: [[ADD_I:%.*]] = add <8 x i8> %v1, [[MUL_I]]
// CHECK: ret <8 x i8> [[ADD_I]]
@@ -437,7 +433,7 @@ uint8x8_t test_vmla_u8(uint8x8_t v1, uint8x8_t v2, uint8x8_t v3) {
return vmla_u8(v1, v2, v3);
}
-// CHECK-LABEL: define <4 x i16> @test_vmla_u16(<4 x i16> %v1, <4 x i16> %v2, <4 x i16> %v3) #0 {
+// CHECK-LABEL: @test_vmla_u16(
// CHECK: [[MUL_I:%.*]] = mul <4 x i16> %v2, %v3
// CHECK: [[ADD_I:%.*]] = add <4 x i16> %v1, [[MUL_I]]
// CHECK: ret <4 x i16> [[ADD_I]]
@@ -445,7 +441,7 @@ uint16x4_t test_vmla_u16(uint16x4_t v1, uint16x4_t v2, uint16x4_t v3) {
return vmla_u16(v1, v2, v3);
}
-// CHECK-LABEL: define <2 x i32> @test_vmla_u32(<2 x i32> %v1, <2 x i32> %v2, <2 x i32> %v3) #0 {
+// CHECK-LABEL: @test_vmla_u32(
// CHECK: [[MUL_I:%.*]] = mul <2 x i32> %v2, %v3
// CHECK: [[ADD_I:%.*]] = add <2 x i32> %v1, [[MUL_I]]
// CHECK: ret <2 x i32> [[ADD_I]]
@@ -453,7 +449,7 @@ uint32x2_t test_vmla_u32(uint32x2_t v1, uint32x2_t v2, uint32x2_t v3) {
return vmla_u32(v1, v2, v3);
}
-// CHECK-LABEL: define <16 x i8> @test_vmlaq_s8(<16 x i8> %v1, <16 x i8> %v2, <16 x i8> %v3) #0 {
+// CHECK-LABEL: @test_vmlaq_s8(
// CHECK: [[MUL_I:%.*]] = mul <16 x i8> %v2, %v3
// CHECK: [[ADD_I:%.*]] = add <16 x i8> %v1, [[MUL_I]]
// CHECK: ret <16 x i8> [[ADD_I]]
@@ -461,7 +457,7 @@ int8x16_t test_vmlaq_s8(int8x16_t v1, int8x16_t v2, int8x16_t v3) {
return vmlaq_s8(v1, v2, v3);
}
-// CHECK-LABEL: define <8 x i16> @test_vmlaq_s16(<8 x i16> %v1, <8 x i16> %v2, <8 x i16> %v3) #0 {
+// CHECK-LABEL: @test_vmlaq_s16(
// CHECK: [[MUL_I:%.*]] = mul <8 x i16> %v2, %v3
// CHECK: [[ADD_I:%.*]] = add <8 x i16> %v1, [[MUL_I]]
// CHECK: ret <8 x i16> [[ADD_I]]
@@ -469,15 +465,15 @@ int16x8_t test_vmlaq_s16(int16x8_t v1, int16x8_t v2, int16x8_t v3) {
return vmlaq_s16(v1, v2, v3);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlaq_s32(<4 x i32> %v1, <4 x i32> %v2, <4 x i32> %v3) #0 {
+// CHECK-LABEL: @test_vmlaq_s32(
// CHECK: [[MUL_I:%.*]] = mul <4 x i32> %v2, %v3
// CHECK: [[ADD_I:%.*]] = add <4 x i32> %v1, [[MUL_I]]
// CHECK: ret <4 x i32> [[ADD_I]]
int32x4_t test_vmlaq_s32(int32x4_t v1, int32x4_t v2, int32x4_t v3) {
return vmlaq_s32(v1, v2, v3);
-}
+}
-// CHECK-LABEL: define <4 x float> @test_vmlaq_f32(<4 x float> %v1, <4 x float> %v2, <4 x float> %v3) #0 {
+// CHECK-LABEL: @test_vmlaq_f32(
// CHECK: [[MUL_I:%.*]] = fmul <4 x float> %v2, %v3
// CHECK: [[ADD_I:%.*]] = fadd <4 x float> %v1, [[MUL_I]]
// CHECK: ret <4 x float> [[ADD_I]]
@@ -485,7 +481,7 @@ float32x4_t test_vmlaq_f32(float32x4_t v1, float32x4_t v2, float32x4_t v3) {
return vmlaq_f32(v1, v2, v3);
}
-// CHECK-LABEL: define <16 x i8> @test_vmlaq_u8(<16 x i8> %v1, <16 x i8> %v2, <16 x i8> %v3) #0 {
+// CHECK-LABEL: @test_vmlaq_u8(
// CHECK: [[MUL_I:%.*]] = mul <16 x i8> %v2, %v3
// CHECK: [[ADD_I:%.*]] = add <16 x i8> %v1, [[MUL_I]]
// CHECK: ret <16 x i8> [[ADD_I]]
@@ -493,7 +489,7 @@ uint8x16_t test_vmlaq_u8(uint8x16_t v1, uint8x16_t v2, uint8x16_t v3) {
return vmlaq_u8(v1, v2, v3);
}
-// CHECK-LABEL: define <8 x i16> @test_vmlaq_u16(<8 x i16> %v1, <8 x i16> %v2, <8 x i16> %v3) #0 {
+// CHECK-LABEL: @test_vmlaq_u16(
// CHECK: [[MUL_I:%.*]] = mul <8 x i16> %v2, %v3
// CHECK: [[ADD_I:%.*]] = add <8 x i16> %v1, [[MUL_I]]
// CHECK: ret <8 x i16> [[ADD_I]]
@@ -501,7 +497,7 @@ uint16x8_t test_vmlaq_u16(uint16x8_t v1, uint16x8_t v2, uint16x8_t v3) {
return vmlaq_u16(v1, v2, v3);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlaq_u32(<4 x i32> %v1, <4 x i32> %v2, <4 x i32> %v3) #0 {
+// CHECK-LABEL: @test_vmlaq_u32(
// CHECK: [[MUL_I:%.*]] = mul <4 x i32> %v2, %v3
// CHECK: [[ADD_I:%.*]] = add <4 x i32> %v1, [[MUL_I]]
// CHECK: ret <4 x i32> [[ADD_I]]
@@ -509,7 +505,7 @@ uint32x4_t test_vmlaq_u32(uint32x4_t v1, uint32x4_t v2, uint32x4_t v3) {
return vmlaq_u32(v1, v2, v3);
}
-// CHECK-LABEL: define <2 x double> @test_vmlaq_f64(<2 x double> %v1, <2 x double> %v2, <2 x double> %v3) #0 {
+// CHECK-LABEL: @test_vmlaq_f64(
// CHECK: [[MUL_I:%.*]] = fmul <2 x double> %v2, %v3
// CHECK: [[ADD_I:%.*]] = fadd <2 x double> %v1, [[MUL_I]]
// CHECK: ret <2 x double> [[ADD_I]]
@@ -517,7 +513,7 @@ float64x2_t test_vmlaq_f64(float64x2_t v1, float64x2_t v2, float64x2_t v3) {
return vmlaq_f64(v1, v2, v3);
}
-// CHECK-LABEL: define <8 x i8> @test_vmls_s8(<8 x i8> %v1, <8 x i8> %v2, <8 x i8> %v3) #0 {
+// CHECK-LABEL: @test_vmls_s8(
// CHECK: [[MUL_I:%.*]] = mul <8 x i8> %v2, %v3
// CHECK: [[SUB_I:%.*]] = sub <8 x i8> %v1, [[MUL_I]]
// CHECK: ret <8 x i8> [[SUB_I]]
@@ -525,7 +521,7 @@ int8x8_t test_vmls_s8(int8x8_t v1, int8x8_t v2, int8x8_t v3) {
return vmls_s8(v1, v2, v3);
}
-// CHECK-LABEL: define <8 x i8> @test_vmls_s16(<4 x i16> %v1, <4 x i16> %v2, <4 x i16> %v3) #0 {
+// CHECK-LABEL: @test_vmls_s16(
// CHECK: [[MUL_I:%.*]] = mul <4 x i16> %v2, %v3
// CHECK: [[SUB_I:%.*]] = sub <4 x i16> %v1, [[MUL_I]]
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SUB_I]] to <8 x i8>
@@ -534,7 +530,7 @@ int8x8_t test_vmls_s16(int16x4_t v1, int16x4_t v2, int16x4_t v3) {
return vmls_s16(v1, v2, v3);
}
-// CHECK-LABEL: define <2 x i32> @test_vmls_s32(<2 x i32> %v1, <2 x i32> %v2, <2 x i32> %v3) #0 {
+// CHECK-LABEL: @test_vmls_s32(
// CHECK: [[MUL_I:%.*]] = mul <2 x i32> %v2, %v3
// CHECK: [[SUB_I:%.*]] = sub <2 x i32> %v1, [[MUL_I]]
// CHECK: ret <2 x i32> [[SUB_I]]
@@ -542,7 +538,7 @@ int32x2_t test_vmls_s32(int32x2_t v1, int32x2_t v2, int32x2_t v3) {
return vmls_s32(v1, v2, v3);
}
-// CHECK-LABEL: define <2 x float> @test_vmls_f32(<2 x float> %v1, <2 x float> %v2, <2 x float> %v3) #0 {
+// CHECK-LABEL: @test_vmls_f32(
// CHECK: [[MUL_I:%.*]] = fmul <2 x float> %v2, %v3
// CHECK: [[SUB_I:%.*]] = fsub <2 x float> %v1, [[MUL_I]]
// CHECK: ret <2 x float> [[SUB_I]]
@@ -550,7 +546,7 @@ float32x2_t test_vmls_f32(float32x2_t v1, float32x2_t v2, float32x2_t v3) {
return vmls_f32(v1, v2, v3);
}
-// CHECK-LABEL: define <8 x i8> @test_vmls_u8(<8 x i8> %v1, <8 x i8> %v2, <8 x i8> %v3) #0 {
+// CHECK-LABEL: @test_vmls_u8(
// CHECK: [[MUL_I:%.*]] = mul <8 x i8> %v2, %v3
// CHECK: [[SUB_I:%.*]] = sub <8 x i8> %v1, [[MUL_I]]
// CHECK: ret <8 x i8> [[SUB_I]]
@@ -558,7 +554,7 @@ uint8x8_t test_vmls_u8(uint8x8_t v1, uint8x8_t v2, uint8x8_t v3) {
return vmls_u8(v1, v2, v3);
}
-// CHECK-LABEL: define <4 x i16> @test_vmls_u16(<4 x i16> %v1, <4 x i16> %v2, <4 x i16> %v3) #0 {
+// CHECK-LABEL: @test_vmls_u16(
// CHECK: [[MUL_I:%.*]] = mul <4 x i16> %v2, %v3
// CHECK: [[SUB_I:%.*]] = sub <4 x i16> %v1, [[MUL_I]]
// CHECK: ret <4 x i16> [[SUB_I]]
@@ -566,14 +562,15 @@ uint16x4_t test_vmls_u16(uint16x4_t v1, uint16x4_t v2, uint16x4_t v3) {
return vmls_u16(v1, v2, v3);
}
-// CHECK-LABEL: define <2 x i32> @test_vmls_u32(<2 x i32> %v1, <2 x i32> %v2, <2 x i32> %v3) #0 {
+// CHECK-LABEL: @test_vmls_u32(
// CHECK: [[MUL_I:%.*]] = mul <2 x i32> %v2, %v3
// CHECK: [[SUB_I:%.*]] = sub <2 x i32> %v1, [[MUL_I]]
// CHECK: ret <2 x i32> [[SUB_I]]
uint32x2_t test_vmls_u32(uint32x2_t v1, uint32x2_t v2, uint32x2_t v3) {
return vmls_u32(v1, v2, v3);
}
-// CHECK-LABEL: define <16 x i8> @test_vmlsq_s8(<16 x i8> %v1, <16 x i8> %v2, <16 x i8> %v3) #0 {
+
+// CHECK-LABEL: @test_vmlsq_s8(
// CHECK: [[MUL_I:%.*]] = mul <16 x i8> %v2, %v3
// CHECK: [[SUB_I:%.*]] = sub <16 x i8> %v1, [[MUL_I]]
// CHECK: ret <16 x i8> [[SUB_I]]
@@ -581,7 +578,7 @@ int8x16_t test_vmlsq_s8(int8x16_t v1, int8x16_t v2, int8x16_t v3) {
return vmlsq_s8(v1, v2, v3);
}
-// CHECK-LABEL: define <8 x i16> @test_vmlsq_s16(<8 x i16> %v1, <8 x i16> %v2, <8 x i16> %v3) #0 {
+// CHECK-LABEL: @test_vmlsq_s16(
// CHECK: [[MUL_I:%.*]] = mul <8 x i16> %v2, %v3
// CHECK: [[SUB_I:%.*]] = sub <8 x i16> %v1, [[MUL_I]]
// CHECK: ret <8 x i16> [[SUB_I]]
@@ -589,7 +586,7 @@ int16x8_t test_vmlsq_s16(int16x8_t v1, int16x8_t v2, int16x8_t v3) {
return vmlsq_s16(v1, v2, v3);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlsq_s32(<4 x i32> %v1, <4 x i32> %v2, <4 x i32> %v3) #0 {
+// CHECK-LABEL: @test_vmlsq_s32(
// CHECK: [[MUL_I:%.*]] = mul <4 x i32> %v2, %v3
// CHECK: [[SUB_I:%.*]] = sub <4 x i32> %v1, [[MUL_I]]
// CHECK: ret <4 x i32> [[SUB_I]]
@@ -597,14 +594,15 @@ int32x4_t test_vmlsq_s32(int32x4_t v1, int32x4_t v2, int32x4_t v3) {
return vmlsq_s32(v1, v2, v3);
}
-// CHECK-LABEL: define <4 x float> @test_vmlsq_f32(<4 x float> %v1, <4 x float> %v2, <4 x float> %v3) #0 {
+// CHECK-LABEL: @test_vmlsq_f32(
// CHECK: [[MUL_I:%.*]] = fmul <4 x float> %v2, %v3
// CHECK: [[SUB_I:%.*]] = fsub <4 x float> %v1, [[MUL_I]]
// CHECK: ret <4 x float> [[SUB_I]]
float32x4_t test_vmlsq_f32(float32x4_t v1, float32x4_t v2, float32x4_t v3) {
return vmlsq_f32(v1, v2, v3);
}
-// CHECK-LABEL: define <16 x i8> @test_vmlsq_u8(<16 x i8> %v1, <16 x i8> %v2, <16 x i8> %v3) #0 {
+
+// CHECK-LABEL: @test_vmlsq_u8(
// CHECK: [[MUL_I:%.*]] = mul <16 x i8> %v2, %v3
// CHECK: [[SUB_I:%.*]] = sub <16 x i8> %v1, [[MUL_I]]
// CHECK: ret <16 x i8> [[SUB_I]]
@@ -612,7 +610,7 @@ uint8x16_t test_vmlsq_u8(uint8x16_t v1, uint8x16_t v2, uint8x16_t v3) {
return vmlsq_u8(v1, v2, v3);
}
-// CHECK-LABEL: define <8 x i16> @test_vmlsq_u16(<8 x i16> %v1, <8 x i16> %v2, <8 x i16> %v3) #0 {
+// CHECK-LABEL: @test_vmlsq_u16(
// CHECK: [[MUL_I:%.*]] = mul <8 x i16> %v2, %v3
// CHECK: [[SUB_I:%.*]] = sub <8 x i16> %v1, [[MUL_I]]
// CHECK: ret <8 x i16> [[SUB_I]]
@@ -620,7 +618,7 @@ uint16x8_t test_vmlsq_u16(uint16x8_t v1, uint16x8_t v2, uint16x8_t v3) {
return vmlsq_u16(v1, v2, v3);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlsq_u32(<4 x i32> %v1, <4 x i32> %v2, <4 x i32> %v3) #0 {
+// CHECK-LABEL: @test_vmlsq_u32(
// CHECK: [[MUL_I:%.*]] = mul <4 x i32> %v2, %v3
// CHECK: [[SUB_I:%.*]] = sub <4 x i32> %v1, [[MUL_I]]
// CHECK: ret <4 x i32> [[SUB_I]]
@@ -628,115 +626,99 @@ uint32x4_t test_vmlsq_u32(uint32x4_t v1, uint32x4_t v2, uint32x4_t v3) {
return vmlsq_u32(v1, v2, v3);
}
-// CHECK-LABEL: define <2 x double> @test_vmlsq_f64(<2 x double> %v1, <2 x double> %v2, <2 x double> %v3) #0 {
+// CHECK-LABEL: @test_vmlsq_f64(
// CHECK: [[MUL_I:%.*]] = fmul <2 x double> %v2, %v3
// CHECK: [[SUB_I:%.*]] = fsub <2 x double> %v1, [[MUL_I]]
// CHECK: ret <2 x double> [[SUB_I]]
float64x2_t test_vmlsq_f64(float64x2_t v1, float64x2_t v2, float64x2_t v3) {
return vmlsq_f64(v1, v2, v3);
}
-// CHECK-LABEL: define <2 x float> @test_vfma_f32(<2 x float> %v1, <2 x float> %v2, <2 x float> %v3) #0 {
+
+// CHECK-LABEL: @test_vfma_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %v1 to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %v2 to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x float> %v3 to <8 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK: [[TMP5:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x float>
-// CHECK: [[TMP6:%.*]] = call <2 x float> @llvm.fma.v2f32(<2 x float> [[TMP4]], <2 x float> [[TMP5]], <2 x float> [[TMP3]]) #4
-// CHECK: ret <2 x float> [[TMP6]]
+// CHECK: [[TMP3:%.*]] = call <2 x float> @llvm.fma.v2f32(<2 x float> %v2, <2 x float> %v3, <2 x float> %v1) #4
+// CHECK: ret <2 x float> [[TMP3]]
float32x2_t test_vfma_f32(float32x2_t v1, float32x2_t v2, float32x2_t v3) {
return vfma_f32(v1, v2, v3);
}
-// CHECK-LABEL: define <4 x float> @test_vfmaq_f32(<4 x float> %v1, <4 x float> %v2, <4 x float> %v3) #0 {
+// CHECK-LABEL: @test_vfmaq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %v2 to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x float> %v3 to <16 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <4 x float>
-// CHECK: [[TMP6:%.*]] = call <4 x float> @llvm.fma.v4f32(<4 x float> [[TMP4]], <4 x float> [[TMP5]], <4 x float> [[TMP3]]) #4
-// CHECK: ret <4 x float> [[TMP6]]
+// CHECK: [[TMP3:%.*]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %v2, <4 x float> %v3, <4 x float> %v1) #4
+// CHECK: ret <4 x float> [[TMP3]]
float32x4_t test_vfmaq_f32(float32x4_t v1, float32x4_t v2, float32x4_t v3) {
return vfmaq_f32(v1, v2, v3);
}
-// CHECK-LABEL: define <2 x double> @test_vfmaq_f64(<2 x double> %v1, <2 x double> %v2, <2 x double> %v3) #0 {
+// CHECK-LABEL: @test_vfmaq_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x double> %v2 to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x double> %v3 to <16 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x double>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <2 x double>
-// CHECK: [[TMP6:%.*]] = call <2 x double> @llvm.fma.v2f64(<2 x double> [[TMP4]], <2 x double> [[TMP5]], <2 x double> [[TMP3]]) #4
-// CHECK: ret <2 x double> [[TMP6]]
+// CHECK: [[TMP3:%.*]] = call <2 x double> @llvm.fma.v2f64(<2 x double> %v2, <2 x double> %v3, <2 x double> %v1) #4
+// CHECK: ret <2 x double> [[TMP3]]
float64x2_t test_vfmaq_f64(float64x2_t v1, float64x2_t v2, float64x2_t v3) {
return vfmaq_f64(v1, v2, v3);
}
-// CHECK-LABEL: define <2 x float> @test_vfms_f32(<2 x float> %v1, <2 x float> %v2, <2 x float> %v3) #0 {
+
+// CHECK-LABEL: @test_vfms_f32(
// CHECK: [[SUB_I:%.*]] = fsub <2 x float> <float -0.000000e+00, float -0.000000e+00>, %v2
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %v1 to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> [[SUB_I]] to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x float> %v3 to <8 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK: [[TMP5:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x float>
-// CHECK: [[TMP6:%.*]] = call <2 x float> @llvm.fma.v2f32(<2 x float> [[TMP4]], <2 x float> [[TMP5]], <2 x float> [[TMP3]]) #4
-// CHECK: ret <2 x float> [[TMP6]]
+// CHECK: [[TMP3:%.*]] = call <2 x float> @llvm.fma.v2f32(<2 x float> [[SUB_I]], <2 x float> %v3, <2 x float> %v1) #4
+// CHECK: ret <2 x float> [[TMP3]]
float32x2_t test_vfms_f32(float32x2_t v1, float32x2_t v2, float32x2_t v3) {
return vfms_f32(v1, v2, v3);
}
-// CHECK-LABEL: define <4 x float> @test_vfmsq_f32(<4 x float> %v1, <4 x float> %v2, <4 x float> %v3) #0 {
+// CHECK-LABEL: @test_vfmsq_f32(
// CHECK: [[SUB_I:%.*]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %v2
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> [[SUB_I]] to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x float> %v3 to <16 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <4 x float>
-// CHECK: [[TMP6:%.*]] = call <4 x float> @llvm.fma.v4f32(<4 x float> [[TMP4]], <4 x float> [[TMP5]], <4 x float> [[TMP3]]) #4
-// CHECK: ret <4 x float> [[TMP6]]
+// CHECK: [[TMP3:%.*]] = call <4 x float> @llvm.fma.v4f32(<4 x float> [[SUB_I]], <4 x float> %v3, <4 x float> %v1) #4
+// CHECK: ret <4 x float> [[TMP3]]
float32x4_t test_vfmsq_f32(float32x4_t v1, float32x4_t v2, float32x4_t v3) {
return vfmsq_f32(v1, v2, v3);
}
-// CHECK-LABEL: define <2 x double> @test_vfmsq_f64(<2 x double> %v1, <2 x double> %v2, <2 x double> %v3) #0 {
+// CHECK-LABEL: @test_vfmsq_f64(
// CHECK: [[SUB_I:%.*]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %v2
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x double> [[SUB_I]] to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x double> %v3 to <16 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x double>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <2 x double>
-// CHECK: [[TMP6:%.*]] = call <2 x double> @llvm.fma.v2f64(<2 x double> [[TMP4]], <2 x double> [[TMP5]], <2 x double> [[TMP3]]) #4
-// CHECK: ret <2 x double> [[TMP6]]
+// CHECK: [[TMP3:%.*]] = call <2 x double> @llvm.fma.v2f64(<2 x double> [[SUB_I]], <2 x double> %v3, <2 x double> %v1) #4
+// CHECK: ret <2 x double> [[TMP3]]
float64x2_t test_vfmsq_f64(float64x2_t v1, float64x2_t v2, float64x2_t v3) {
return vfmsq_f64(v1, v2, v3);
}
-// CHECK-LABEL: define <2 x double> @test_vdivq_f64(<2 x double> %v1, <2 x double> %v2) #0 {
+// CHECK-LABEL: @test_vdivq_f64(
// CHECK: [[DIV_I:%.*]] = fdiv <2 x double> %v1, %v2
// CHECK: ret <2 x double> [[DIV_I]]
float64x2_t test_vdivq_f64(float64x2_t v1, float64x2_t v2) {
return vdivq_f64(v1, v2);
}
-// CHECK-LABEL: define <4 x float> @test_vdivq_f32(<4 x float> %v1, <4 x float> %v2) #0 {
+// CHECK-LABEL: @test_vdivq_f32(
// CHECK: [[DIV_I:%.*]] = fdiv <4 x float> %v1, %v2
// CHECK: ret <4 x float> [[DIV_I]]
float32x4_t test_vdivq_f32(float32x4_t v1, float32x4_t v2) {
return vdivq_f32(v1, v2);
}
-// CHECK-LABEL: define <2 x float> @test_vdiv_f32(<2 x float> %v1, <2 x float> %v2) #0 {
+// CHECK-LABEL: @test_vdiv_f32(
// CHECK: [[DIV_I:%.*]] = fdiv <2 x float> %v1, %v2
// CHECK: ret <2 x float> [[DIV_I]]
float32x2_t test_vdiv_f32(float32x2_t v1, float32x2_t v2) {
return vdiv_f32(v1, v2);
}
-// CHECK-LABEL: define <8 x i8> @test_vaba_s8(<8 x i8> %v1, <8 x i8> %v2, <8 x i8> %v3) #0 {
+// CHECK-LABEL: @test_vaba_s8(
// CHECK: [[VABD_I_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.sabd.v8i8(<8 x i8> %v2, <8 x i8> %v3) #4
// CHECK: [[ADD_I:%.*]] = add <8 x i8> %v1, [[VABD_I_I]]
// CHECK: ret <8 x i8> [[ADD_I]]
@@ -744,31 +726,27 @@ int8x8_t test_vaba_s8(int8x8_t v1, int8x8_t v2, int8x8_t v3) {
return vaba_s8(v1, v2, v3);
}
-// CHECK-LABEL: define <4 x i16> @test_vaba_s16(<4 x i16> %v1, <4 x i16> %v2, <4 x i16> %v3) #0 {
+// CHECK-LABEL: @test_vaba_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %v2 to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %v3 to <8 x i8>
-// CHECK: [[VABD_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VABD1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VABD2_I_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sabd.v4i16(<4 x i16> [[VABD_I_I]], <4 x i16> [[VABD1_I_I]]) #4
+// CHECK: [[VABD2_I_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sabd.v4i16(<4 x i16> %v2, <4 x i16> %v3) #4
// CHECK: [[ADD_I:%.*]] = add <4 x i16> %v1, [[VABD2_I_I]]
// CHECK: ret <4 x i16> [[ADD_I]]
int16x4_t test_vaba_s16(int16x4_t v1, int16x4_t v2, int16x4_t v3) {
return vaba_s16(v1, v2, v3);
}
-// CHECK-LABEL: define <2 x i32> @test_vaba_s32(<2 x i32> %v1, <2 x i32> %v2, <2 x i32> %v3) #0 {
+// CHECK-LABEL: @test_vaba_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %v2 to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %v3 to <8 x i8>
-// CHECK: [[VABD_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VABD1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VABD2_I_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sabd.v2i32(<2 x i32> [[VABD_I_I]], <2 x i32> [[VABD1_I_I]]) #4
+// CHECK: [[VABD2_I_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sabd.v2i32(<2 x i32> %v2, <2 x i32> %v3) #4
// CHECK: [[ADD_I:%.*]] = add <2 x i32> %v1, [[VABD2_I_I]]
// CHECK: ret <2 x i32> [[ADD_I]]
int32x2_t test_vaba_s32(int32x2_t v1, int32x2_t v2, int32x2_t v3) {
return vaba_s32(v1, v2, v3);
}
-// CHECK-LABEL: define <8 x i8> @test_vaba_u8(<8 x i8> %v1, <8 x i8> %v2, <8 x i8> %v3) #0 {
+// CHECK-LABEL: @test_vaba_u8(
// CHECK: [[VABD_I_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.uabd.v8i8(<8 x i8> %v2, <8 x i8> %v3) #4
// CHECK: [[ADD_I:%.*]] = add <8 x i8> %v1, [[VABD_I_I]]
// CHECK: ret <8 x i8> [[ADD_I]]
@@ -776,31 +754,27 @@ uint8x8_t test_vaba_u8(uint8x8_t v1, uint8x8_t v2, uint8x8_t v3) {
return vaba_u8(v1, v2, v3);
}
-// CHECK-LABEL: define <4 x i16> @test_vaba_u16(<4 x i16> %v1, <4 x i16> %v2, <4 x i16> %v3) #0 {
+// CHECK-LABEL: @test_vaba_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %v2 to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %v3 to <8 x i8>
-// CHECK: [[VABD_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VABD1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VABD2_I_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.uabd.v4i16(<4 x i16> [[VABD_I_I]], <4 x i16> [[VABD1_I_I]]) #4
+// CHECK: [[VABD2_I_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.uabd.v4i16(<4 x i16> %v2, <4 x i16> %v3) #4
// CHECK: [[ADD_I:%.*]] = add <4 x i16> %v1, [[VABD2_I_I]]
// CHECK: ret <4 x i16> [[ADD_I]]
uint16x4_t test_vaba_u16(uint16x4_t v1, uint16x4_t v2, uint16x4_t v3) {
return vaba_u16(v1, v2, v3);
}
-// CHECK-LABEL: define <2 x i32> @test_vaba_u32(<2 x i32> %v1, <2 x i32> %v2, <2 x i32> %v3) #0 {
+// CHECK-LABEL: @test_vaba_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %v2 to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %v3 to <8 x i8>
-// CHECK: [[VABD_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VABD1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VABD2_I_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.uabd.v2i32(<2 x i32> [[VABD_I_I]], <2 x i32> [[VABD1_I_I]]) #4
+// CHECK: [[VABD2_I_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.uabd.v2i32(<2 x i32> %v2, <2 x i32> %v3) #4
// CHECK: [[ADD_I:%.*]] = add <2 x i32> %v1, [[VABD2_I_I]]
// CHECK: ret <2 x i32> [[ADD_I]]
uint32x2_t test_vaba_u32(uint32x2_t v1, uint32x2_t v2, uint32x2_t v3) {
return vaba_u32(v1, v2, v3);
}
-// CHECK-LABEL: define <16 x i8> @test_vabaq_s8(<16 x i8> %v1, <16 x i8> %v2, <16 x i8> %v3) #0 {
+// CHECK-LABEL: @test_vabaq_s8(
// CHECK: [[VABD_I_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.sabd.v16i8(<16 x i8> %v2, <16 x i8> %v3) #4
// CHECK: [[ADD_I:%.*]] = add <16 x i8> %v1, [[VABD_I_I]]
// CHECK: ret <16 x i8> [[ADD_I]]
@@ -808,31 +782,27 @@ int8x16_t test_vabaq_s8(int8x16_t v1, int8x16_t v2, int8x16_t v3) {
return vabaq_s8(v1, v2, v3);
}
-// CHECK-LABEL: define <8 x i16> @test_vabaq_s16(<8 x i16> %v1, <8 x i16> %v2, <8 x i16> %v3) #0 {
+// CHECK-LABEL: @test_vabaq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %v2 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %v3 to <16 x i8>
-// CHECK: [[VABD_I_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VABD1_I_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VABD2_I_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.sabd.v8i16(<8 x i16> [[VABD_I_I]], <8 x i16> [[VABD1_I_I]]) #4
+// CHECK: [[VABD2_I_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.sabd.v8i16(<8 x i16> %v2, <8 x i16> %v3) #4
// CHECK: [[ADD_I:%.*]] = add <8 x i16> %v1, [[VABD2_I_I]]
// CHECK: ret <8 x i16> [[ADD_I]]
int16x8_t test_vabaq_s16(int16x8_t v1, int16x8_t v2, int16x8_t v3) {
return vabaq_s16(v1, v2, v3);
}
-// CHECK-LABEL: define <4 x i32> @test_vabaq_s32(<4 x i32> %v1, <4 x i32> %v2, <4 x i32> %v3) #0 {
+// CHECK-LABEL: @test_vabaq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %v2 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %v3 to <16 x i8>
-// CHECK: [[VABD_I_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VABD1_I_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VABD2_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sabd.v4i32(<4 x i32> [[VABD_I_I]], <4 x i32> [[VABD1_I_I]]) #4
+// CHECK: [[VABD2_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sabd.v4i32(<4 x i32> %v2, <4 x i32> %v3) #4
// CHECK: [[ADD_I:%.*]] = add <4 x i32> %v1, [[VABD2_I_I]]
// CHECK: ret <4 x i32> [[ADD_I]]
int32x4_t test_vabaq_s32(int32x4_t v1, int32x4_t v2, int32x4_t v3) {
return vabaq_s32(v1, v2, v3);
}
-// CHECK-LABEL: define <16 x i8> @test_vabaq_u8(<16 x i8> %v1, <16 x i8> %v2, <16 x i8> %v3) #0 {
+// CHECK-LABEL: @test_vabaq_u8(
// CHECK: [[VABD_I_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.uabd.v16i8(<16 x i8> %v2, <16 x i8> %v3) #4
// CHECK: [[ADD_I:%.*]] = add <16 x i8> %v1, [[VABD_I_I]]
// CHECK: ret <16 x i8> [[ADD_I]]
@@ -840,181 +810,154 @@ uint8x16_t test_vabaq_u8(uint8x16_t v1, uint8x16_t v2, uint8x16_t v3) {
return vabaq_u8(v1, v2, v3);
}
-// CHECK-LABEL: define <8 x i16> @test_vabaq_u16(<8 x i16> %v1, <8 x i16> %v2, <8 x i16> %v3) #0 {
+// CHECK-LABEL: @test_vabaq_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %v2 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %v3 to <16 x i8>
-// CHECK: [[VABD_I_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VABD1_I_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VABD2_I_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.uabd.v8i16(<8 x i16> [[VABD_I_I]], <8 x i16> [[VABD1_I_I]]) #4
+// CHECK: [[VABD2_I_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.uabd.v8i16(<8 x i16> %v2, <8 x i16> %v3) #4
// CHECK: [[ADD_I:%.*]] = add <8 x i16> %v1, [[VABD2_I_I]]
// CHECK: ret <8 x i16> [[ADD_I]]
uint16x8_t test_vabaq_u16(uint16x8_t v1, uint16x8_t v2, uint16x8_t v3) {
return vabaq_u16(v1, v2, v3);
}
-// CHECK-LABEL: define <4 x i32> @test_vabaq_u32(<4 x i32> %v1, <4 x i32> %v2, <4 x i32> %v3) #0 {
+// CHECK-LABEL: @test_vabaq_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %v2 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %v3 to <16 x i8>
-// CHECK: [[VABD_I_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VABD1_I_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VABD2_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.uabd.v4i32(<4 x i32> [[VABD_I_I]], <4 x i32> [[VABD1_I_I]]) #4
+// CHECK: [[VABD2_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.uabd.v4i32(<4 x i32> %v2, <4 x i32> %v3) #4
// CHECK: [[ADD_I:%.*]] = add <4 x i32> %v1, [[VABD2_I_I]]
// CHECK: ret <4 x i32> [[ADD_I]]
uint32x4_t test_vabaq_u32(uint32x4_t v1, uint32x4_t v2, uint32x4_t v3) {
return vabaq_u32(v1, v2, v3);
}
-// CHECK-LABEL: define <8 x i8> @test_vabd_s8(<8 x i8> %v1, <8 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vabd_s8(
// CHECK: [[VABD_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.sabd.v8i8(<8 x i8> %v1, <8 x i8> %v2) #4
// CHECK: ret <8 x i8> [[VABD_I]]
int8x8_t test_vabd_s8(int8x8_t v1, int8x8_t v2) {
return vabd_s8(v1, v2);
}
-// CHECK-LABEL: define <4 x i16> @test_vabd_s16(<4 x i16> %v1, <4 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vabd_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %v1 to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %v2 to <8 x i8>
-// CHECK: [[VABD_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VABD1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VABD2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sabd.v4i16(<4 x i16> [[VABD_I]], <4 x i16> [[VABD1_I]]) #4
+// CHECK: [[VABD2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sabd.v4i16(<4 x i16> %v1, <4 x i16> %v2) #4
// CHECK: ret <4 x i16> [[VABD2_I]]
int16x4_t test_vabd_s16(int16x4_t v1, int16x4_t v2) {
return vabd_s16(v1, v2);
}
-// CHECK-LABEL: define <2 x i32> @test_vabd_s32(<2 x i32> %v1, <2 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vabd_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %v1 to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %v2 to <8 x i8>
-// CHECK: [[VABD_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VABD1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VABD2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sabd.v2i32(<2 x i32> [[VABD_I]], <2 x i32> [[VABD1_I]]) #4
+// CHECK: [[VABD2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sabd.v2i32(<2 x i32> %v1, <2 x i32> %v2) #4
// CHECK: ret <2 x i32> [[VABD2_I]]
int32x2_t test_vabd_s32(int32x2_t v1, int32x2_t v2) {
return vabd_s32(v1, v2);
}
-// CHECK-LABEL: define <8 x i8> @test_vabd_u8(<8 x i8> %v1, <8 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vabd_u8(
// CHECK: [[VABD_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.uabd.v8i8(<8 x i8> %v1, <8 x i8> %v2) #4
// CHECK: ret <8 x i8> [[VABD_I]]
uint8x8_t test_vabd_u8(uint8x8_t v1, uint8x8_t v2) {
return vabd_u8(v1, v2);
}
-// CHECK-LABEL: define <4 x i16> @test_vabd_u16(<4 x i16> %v1, <4 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vabd_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %v1 to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %v2 to <8 x i8>
-// CHECK: [[VABD_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VABD1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VABD2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.uabd.v4i16(<4 x i16> [[VABD_I]], <4 x i16> [[VABD1_I]]) #4
+// CHECK: [[VABD2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.uabd.v4i16(<4 x i16> %v1, <4 x i16> %v2) #4
// CHECK: ret <4 x i16> [[VABD2_I]]
uint16x4_t test_vabd_u16(uint16x4_t v1, uint16x4_t v2) {
return vabd_u16(v1, v2);
}
-// CHECK-LABEL: define <2 x i32> @test_vabd_u32(<2 x i32> %v1, <2 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vabd_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %v1 to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %v2 to <8 x i8>
-// CHECK: [[VABD_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VABD1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VABD2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.uabd.v2i32(<2 x i32> [[VABD_I]], <2 x i32> [[VABD1_I]]) #4
+// CHECK: [[VABD2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.uabd.v2i32(<2 x i32> %v1, <2 x i32> %v2) #4
// CHECK: ret <2 x i32> [[VABD2_I]]
uint32x2_t test_vabd_u32(uint32x2_t v1, uint32x2_t v2) {
return vabd_u32(v1, v2);
}
-// CHECK-LABEL: define <2 x float> @test_vabd_f32(<2 x float> %v1, <2 x float> %v2) #0 {
+// CHECK-LABEL: @test_vabd_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %v1 to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %v2 to <8 x i8>
-// CHECK: [[VABD_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VABD1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK: [[VABD2_I:%.*]] = call <2 x float> @llvm.aarch64.neon.fabd.v2f32(<2 x float> [[VABD_I]], <2 x float> [[VABD1_I]]) #4
+// CHECK: [[VABD2_I:%.*]] = call <2 x float> @llvm.aarch64.neon.fabd.v2f32(<2 x float> %v1, <2 x float> %v2) #4
// CHECK: ret <2 x float> [[VABD2_I]]
float32x2_t test_vabd_f32(float32x2_t v1, float32x2_t v2) {
return vabd_f32(v1, v2);
}
-// CHECK-LABEL: define <16 x i8> @test_vabdq_s8(<16 x i8> %v1, <16 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vabdq_s8(
// CHECK: [[VABD_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.sabd.v16i8(<16 x i8> %v1, <16 x i8> %v2) #4
// CHECK: ret <16 x i8> [[VABD_I]]
int8x16_t test_vabdq_s8(int8x16_t v1, int8x16_t v2) {
return vabdq_s8(v1, v2);
}
-// CHECK-LABEL: define <8 x i16> @test_vabdq_s16(<8 x i16> %v1, <8 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vabdq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %v2 to <16 x i8>
-// CHECK: [[VABD_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VABD1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VABD2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.sabd.v8i16(<8 x i16> [[VABD_I]], <8 x i16> [[VABD1_I]]) #4
+// CHECK: [[VABD2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.sabd.v8i16(<8 x i16> %v1, <8 x i16> %v2) #4
// CHECK: ret <8 x i16> [[VABD2_I]]
int16x8_t test_vabdq_s16(int16x8_t v1, int16x8_t v2) {
return vabdq_s16(v1, v2);
}
-// CHECK-LABEL: define <4 x i32> @test_vabdq_s32(<4 x i32> %v1, <4 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vabdq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %v2 to <16 x i8>
-// CHECK: [[VABD_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VABD1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VABD2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sabd.v4i32(<4 x i32> [[VABD_I]], <4 x i32> [[VABD1_I]]) #4
+// CHECK: [[VABD2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sabd.v4i32(<4 x i32> %v1, <4 x i32> %v2) #4
// CHECK: ret <4 x i32> [[VABD2_I]]
int32x4_t test_vabdq_s32(int32x4_t v1, int32x4_t v2) {
return vabdq_s32(v1, v2);
}
-// CHECK-LABEL: define <16 x i8> @test_vabdq_u8(<16 x i8> %v1, <16 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vabdq_u8(
// CHECK: [[VABD_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.uabd.v16i8(<16 x i8> %v1, <16 x i8> %v2) #4
// CHECK: ret <16 x i8> [[VABD_I]]
uint8x16_t test_vabdq_u8(uint8x16_t v1, uint8x16_t v2) {
return vabdq_u8(v1, v2);
}
-// CHECK-LABEL: define <8 x i16> @test_vabdq_u16(<8 x i16> %v1, <8 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vabdq_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %v2 to <16 x i8>
-// CHECK: [[VABD_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VABD1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VABD2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.uabd.v8i16(<8 x i16> [[VABD_I]], <8 x i16> [[VABD1_I]]) #4
+// CHECK: [[VABD2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.uabd.v8i16(<8 x i16> %v1, <8 x i16> %v2) #4
// CHECK: ret <8 x i16> [[VABD2_I]]
uint16x8_t test_vabdq_u16(uint16x8_t v1, uint16x8_t v2) {
return vabdq_u16(v1, v2);
}
-// CHECK-LABEL: define <4 x i32> @test_vabdq_u32(<4 x i32> %v1, <4 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vabdq_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %v2 to <16 x i8>
-// CHECK: [[VABD_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VABD1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VABD2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.uabd.v4i32(<4 x i32> [[VABD_I]], <4 x i32> [[VABD1_I]]) #4
+// CHECK: [[VABD2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.uabd.v4i32(<4 x i32> %v1, <4 x i32> %v2) #4
// CHECK: ret <4 x i32> [[VABD2_I]]
uint32x4_t test_vabdq_u32(uint32x4_t v1, uint32x4_t v2) {
return vabdq_u32(v1, v2);
}
-// CHECK-LABEL: define <4 x float> @test_vabdq_f32(<4 x float> %v1, <4 x float> %v2) #0 {
+// CHECK-LABEL: @test_vabdq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %v2 to <16 x i8>
-// CHECK: [[VABD_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VABD1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
-// CHECK: [[VABD2_I:%.*]] = call <4 x float> @llvm.aarch64.neon.fabd.v4f32(<4 x float> [[VABD_I]], <4 x float> [[VABD1_I]]) #4
+// CHECK: [[VABD2_I:%.*]] = call <4 x float> @llvm.aarch64.neon.fabd.v4f32(<4 x float> %v1, <4 x float> %v2) #4
// CHECK: ret <4 x float> [[VABD2_I]]
float32x4_t test_vabdq_f32(float32x4_t v1, float32x4_t v2) {
return vabdq_f32(v1, v2);
}
-// CHECK-LABEL: define <2 x double> @test_vabdq_f64(<2 x double> %v1, <2 x double> %v2) #0 {
+// CHECK-LABEL: @test_vabdq_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x double> %v2 to <16 x i8>
-// CHECK: [[VABD_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VABD1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x double>
-// CHECK: [[VABD2_I:%.*]] = call <2 x double> @llvm.aarch64.neon.fabd.v2f64(<2 x double> [[VABD_I]], <2 x double> [[VABD1_I]]) #4
+// CHECK: [[VABD2_I:%.*]] = call <2 x double> @llvm.aarch64.neon.fabd.v2f64(<2 x double> %v1, <2 x double> %v2) #4
// CHECK: ret <2 x double> [[VABD2_I]]
float64x2_t test_vabdq_f64(float64x2_t v1, float64x2_t v2) {
return vabdq_f64(v1, v2);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vbsl_s8(<8 x i8> %v1, <8 x i8> %v2, <8 x i8> %v3) #0 {
+// CHECK-LABEL: @test_vbsl_s8(
// CHECK: [[VBSL_I:%.*]] = and <8 x i8> %v1, %v2
// CHECK: [[TMP0:%.*]] = xor <8 x i8> %v1, <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>
// CHECK: [[VBSL1_I:%.*]] = and <8 x i8> [[TMP0]], %v3
@@ -1024,16 +967,13 @@ int8x8_t test_vbsl_s8(uint8x8_t v1, int8x8_t v2, int8x8_t v3) {
return vbsl_s8(v1, v2, v3);
}
-// CHECK-LABEL: define <8 x i8> @test_vbsl_s16(<4 x i16> %v1, <4 x i16> %v2, <4 x i16> %v3) #0 {
+// CHECK-LABEL: @test_vbsl_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %v1 to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %v2 to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %v3 to <8 x i8>
-// CHECK: [[VBSL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VBSL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VBSL2_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VBSL3_I:%.*]] = and <4 x i16> [[VBSL_I]], [[VBSL1_I]]
-// CHECK: [[TMP3:%.*]] = xor <4 x i16> [[VBSL_I]], <i16 -1, i16 -1, i16 -1, i16 -1>
-// CHECK: [[VBSL4_I:%.*]] = and <4 x i16> [[TMP3]], [[VBSL2_I]]
+// CHECK: [[VBSL3_I:%.*]] = and <4 x i16> %v1, %v2
+// CHECK: [[TMP3:%.*]] = xor <4 x i16> %v1, <i16 -1, i16 -1, i16 -1, i16 -1>
+// CHECK: [[VBSL4_I:%.*]] = and <4 x i16> [[TMP3]], %v3
// CHECK: [[VBSL5_I:%.*]] = or <4 x i16> [[VBSL3_I]], [[VBSL4_I]]
// CHECK: [[TMP4:%.*]] = bitcast <4 x i16> [[VBSL5_I]] to <8 x i8>
// CHECK: ret <8 x i8> [[TMP4]]
@@ -1041,39 +981,33 @@ int8x8_t test_vbsl_s16(uint16x4_t v1, int16x4_t v2, int16x4_t v3) {
return vbsl_s16(v1, v2, v3);
}
-// CHECK-LABEL: define <2 x i32> @test_vbsl_s32(<2 x i32> %v1, <2 x i32> %v2, <2 x i32> %v3) #0 {
+// CHECK-LABEL: @test_vbsl_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %v1 to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %v2 to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> %v3 to <8 x i8>
-// CHECK: [[VBSL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VBSL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VBSL2_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VBSL3_I:%.*]] = and <2 x i32> [[VBSL_I]], [[VBSL1_I]]
-// CHECK: [[TMP3:%.*]] = xor <2 x i32> [[VBSL_I]], <i32 -1, i32 -1>
-// CHECK: [[VBSL4_I:%.*]] = and <2 x i32> [[TMP3]], [[VBSL2_I]]
+// CHECK: [[VBSL3_I:%.*]] = and <2 x i32> %v1, %v2
+// CHECK: [[TMP3:%.*]] = xor <2 x i32> %v1, <i32 -1, i32 -1>
+// CHECK: [[VBSL4_I:%.*]] = and <2 x i32> [[TMP3]], %v3
// CHECK: [[VBSL5_I:%.*]] = or <2 x i32> [[VBSL3_I]], [[VBSL4_I]]
// CHECK: ret <2 x i32> [[VBSL5_I]]
int32x2_t test_vbsl_s32(uint32x2_t v1, int32x2_t v2, int32x2_t v3) {
return vbsl_s32(v1, v2, v3);
}
-// CHECK-LABEL: define <1 x i64> @test_vbsl_s64(<1 x i64> %v1, <1 x i64> %v2, <1 x i64> %v3) #0 {
+// CHECK-LABEL: @test_vbsl_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %v1 to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %v2 to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <1 x i64> %v3 to <8 x i8>
-// CHECK: [[VBSL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
-// CHECK: [[VBSL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x i64>
-// CHECK: [[VBSL2_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <1 x i64>
-// CHECK: [[VBSL3_I:%.*]] = and <1 x i64> [[VBSL_I]], [[VBSL1_I]]
-// CHECK: [[TMP3:%.*]] = xor <1 x i64> [[VBSL_I]], <i64 -1>
-// CHECK: [[VBSL4_I:%.*]] = and <1 x i64> [[TMP3]], [[VBSL2_I]]
+// CHECK: [[VBSL3_I:%.*]] = and <1 x i64> %v1, %v2
+// CHECK: [[TMP3:%.*]] = xor <1 x i64> %v1, <i64 -1>
+// CHECK: [[VBSL4_I:%.*]] = and <1 x i64> [[TMP3]], %v3
// CHECK: [[VBSL5_I:%.*]] = or <1 x i64> [[VBSL3_I]], [[VBSL4_I]]
// CHECK: ret <1 x i64> [[VBSL5_I]]
uint64x1_t test_vbsl_s64(uint64x1_t v1, uint64x1_t v2, uint64x1_t v3) {
return vbsl_s64(v1, v2, v3);
}
-// CHECK-LABEL: define <8 x i8> @test_vbsl_u8(<8 x i8> %v1, <8 x i8> %v2, <8 x i8> %v3) #0 {
+// CHECK-LABEL: @test_vbsl_u8(
// CHECK: [[VBSL_I:%.*]] = and <8 x i8> %v1, %v2
// CHECK: [[TMP0:%.*]] = xor <8 x i8> %v1, <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>
// CHECK: [[VBSL1_I:%.*]] = and <8 x i8> [[TMP0]], %v3
@@ -1083,64 +1017,54 @@ uint8x8_t test_vbsl_u8(uint8x8_t v1, uint8x8_t v2, uint8x8_t v3) {
return vbsl_u8(v1, v2, v3);
}
-// CHECK-LABEL: define <4 x i16> @test_vbsl_u16(<4 x i16> %v1, <4 x i16> %v2, <4 x i16> %v3) #0 {
+// CHECK-LABEL: @test_vbsl_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %v1 to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %v2 to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %v3 to <8 x i8>
-// CHECK: [[VBSL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VBSL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VBSL2_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VBSL3_I:%.*]] = and <4 x i16> [[VBSL_I]], [[VBSL1_I]]
-// CHECK: [[TMP3:%.*]] = xor <4 x i16> [[VBSL_I]], <i16 -1, i16 -1, i16 -1, i16 -1>
-// CHECK: [[VBSL4_I:%.*]] = and <4 x i16> [[TMP3]], [[VBSL2_I]]
+// CHECK: [[VBSL3_I:%.*]] = and <4 x i16> %v1, %v2
+// CHECK: [[TMP3:%.*]] = xor <4 x i16> %v1, <i16 -1, i16 -1, i16 -1, i16 -1>
+// CHECK: [[VBSL4_I:%.*]] = and <4 x i16> [[TMP3]], %v3
// CHECK: [[VBSL5_I:%.*]] = or <4 x i16> [[VBSL3_I]], [[VBSL4_I]]
// CHECK: ret <4 x i16> [[VBSL5_I]]
uint16x4_t test_vbsl_u16(uint16x4_t v1, uint16x4_t v2, uint16x4_t v3) {
return vbsl_u16(v1, v2, v3);
}
-// CHECK-LABEL: define <2 x i32> @test_vbsl_u32(<2 x i32> %v1, <2 x i32> %v2, <2 x i32> %v3) #0 {
+// CHECK-LABEL: @test_vbsl_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %v1 to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %v2 to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> %v3 to <8 x i8>
-// CHECK: [[VBSL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VBSL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VBSL2_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VBSL3_I:%.*]] = and <2 x i32> [[VBSL_I]], [[VBSL1_I]]
-// CHECK: [[TMP3:%.*]] = xor <2 x i32> [[VBSL_I]], <i32 -1, i32 -1>
-// CHECK: [[VBSL4_I:%.*]] = and <2 x i32> [[TMP3]], [[VBSL2_I]]
+// CHECK: [[VBSL3_I:%.*]] = and <2 x i32> %v1, %v2
+// CHECK: [[TMP3:%.*]] = xor <2 x i32> %v1, <i32 -1, i32 -1>
+// CHECK: [[VBSL4_I:%.*]] = and <2 x i32> [[TMP3]], %v3
// CHECK: [[VBSL5_I:%.*]] = or <2 x i32> [[VBSL3_I]], [[VBSL4_I]]
// CHECK: ret <2 x i32> [[VBSL5_I]]
uint32x2_t test_vbsl_u32(uint32x2_t v1, uint32x2_t v2, uint32x2_t v3) {
return vbsl_u32(v1, v2, v3);
}
-// CHECK-LABEL: define <1 x i64> @test_vbsl_u64(<1 x i64> %v1, <1 x i64> %v2, <1 x i64> %v3) #0 {
+// CHECK-LABEL: @test_vbsl_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %v1 to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %v2 to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <1 x i64> %v3 to <8 x i8>
-// CHECK: [[VBSL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
-// CHECK: [[VBSL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x i64>
-// CHECK: [[VBSL2_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <1 x i64>
-// CHECK: [[VBSL3_I:%.*]] = and <1 x i64> [[VBSL_I]], [[VBSL1_I]]
-// CHECK: [[TMP3:%.*]] = xor <1 x i64> [[VBSL_I]], <i64 -1>
-// CHECK: [[VBSL4_I:%.*]] = and <1 x i64> [[TMP3]], [[VBSL2_I]]
+// CHECK: [[VBSL3_I:%.*]] = and <1 x i64> %v1, %v2
+// CHECK: [[TMP3:%.*]] = xor <1 x i64> %v1, <i64 -1>
+// CHECK: [[VBSL4_I:%.*]] = and <1 x i64> [[TMP3]], %v3
// CHECK: [[VBSL5_I:%.*]] = or <1 x i64> [[VBSL3_I]], [[VBSL4_I]]
// CHECK: ret <1 x i64> [[VBSL5_I]]
uint64x1_t test_vbsl_u64(uint64x1_t v1, uint64x1_t v2, uint64x1_t v3) {
return vbsl_u64(v1, v2, v3);
}
-// CHECK-LABEL: define <2 x float> @test_vbsl_f32(<2 x float> %v1, <2 x float> %v2, <2 x float> %v3) #0 {
+// CHECK-LABEL: @test_vbsl_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %v1 to <2 x i32>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[TMP0]] to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x float> %v2 to <8 x i8>
// CHECK: [[TMP3:%.*]] = bitcast <2 x float> %v3 to <8 x i8>
-// CHECK: [[VBSL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
// CHECK: [[VBSL1_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
// CHECK: [[VBSL2_I:%.*]] = bitcast <8 x i8> [[TMP3]] to <2 x i32>
-// CHECK: [[VBSL3_I:%.*]] = and <2 x i32> [[VBSL_I]], [[VBSL1_I]]
-// CHECK: [[TMP4:%.*]] = xor <2 x i32> [[VBSL_I]], <i32 -1, i32 -1>
+// CHECK: [[VBSL3_I:%.*]] = and <2 x i32> [[TMP0]], [[VBSL1_I]]
+// CHECK: [[TMP4:%.*]] = xor <2 x i32> [[TMP0]], <i32 -1, i32 -1>
// CHECK: [[VBSL4_I:%.*]] = and <2 x i32> [[TMP4]], [[VBSL2_I]]
// CHECK: [[VBSL5_I:%.*]] = or <2 x i32> [[VBSL3_I]], [[VBSL4_I]]
// CHECK: [[TMP5:%.*]] = bitcast <2 x i32> [[VBSL5_I]] to <2 x float>
@@ -1149,15 +1073,14 @@ float32x2_t test_vbsl_f32(float32x2_t v1, float32x2_t v2, float32x2_t v3) {
return vbsl_f32(v1, v2, v3);
}
-// CHECK-LABEL: define <1 x double> @test_vbsl_f64(<1 x i64> %v1, <1 x double> %v2, <1 x double> %v3) #0 {
+// CHECK-LABEL: @test_vbsl_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %v1 to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x double> %v2 to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <1 x double> %v3 to <8 x i8>
-// CHECK: [[VBSL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
// CHECK: [[VBSL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x i64>
// CHECK: [[VBSL2_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <1 x i64>
-// CHECK: [[VBSL3_I:%.*]] = and <1 x i64> [[VBSL_I]], [[VBSL1_I]]
-// CHECK: [[TMP3:%.*]] = xor <1 x i64> [[VBSL_I]], <i64 -1>
+// CHECK: [[VBSL3_I:%.*]] = and <1 x i64> %v1, [[VBSL1_I]]
+// CHECK: [[TMP3:%.*]] = xor <1 x i64> %v1, <i64 -1>
// CHECK: [[VBSL4_I:%.*]] = and <1 x i64> [[TMP3]], [[VBSL2_I]]
// CHECK: [[VBSL5_I:%.*]] = or <1 x i64> [[VBSL3_I]], [[VBSL4_I]]
// CHECK: [[TMP4:%.*]] = bitcast <1 x i64> [[VBSL5_I]] to <1 x double>
@@ -1166,7 +1089,7 @@ float64x1_t test_vbsl_f64(uint64x1_t v1, float64x1_t v2, float64x1_t v3) {
return vbsl_f64(v1, v2, v3);
}
-// CHECK-LABEL: define <8 x i8> @test_vbsl_p8(<8 x i8> %v1, <8 x i8> %v2, <8 x i8> %v3) #0 {
+// CHECK-LABEL: @test_vbsl_p8(
// CHECK: [[VBSL_I:%.*]] = and <8 x i8> %v1, %v2
// CHECK: [[TMP0:%.*]] = xor <8 x i8> %v1, <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>
// CHECK: [[VBSL1_I:%.*]] = and <8 x i8> [[TMP0]], %v3
@@ -1176,23 +1099,20 @@ poly8x8_t test_vbsl_p8(uint8x8_t v1, poly8x8_t v2, poly8x8_t v3) {
return vbsl_p8(v1, v2, v3);
}
-// CHECK-LABEL: define <4 x i16> @test_vbsl_p16(<4 x i16> %v1, <4 x i16> %v2, <4 x i16> %v3) #0 {
+// CHECK-LABEL: @test_vbsl_p16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %v1 to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %v2 to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %v3 to <8 x i8>
-// CHECK: [[VBSL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VBSL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VBSL2_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VBSL3_I:%.*]] = and <4 x i16> [[VBSL_I]], [[VBSL1_I]]
-// CHECK: [[TMP3:%.*]] = xor <4 x i16> [[VBSL_I]], <i16 -1, i16 -1, i16 -1, i16 -1>
-// CHECK: [[VBSL4_I:%.*]] = and <4 x i16> [[TMP3]], [[VBSL2_I]]
+// CHECK: [[VBSL3_I:%.*]] = and <4 x i16> %v1, %v2
+// CHECK: [[TMP3:%.*]] = xor <4 x i16> %v1, <i16 -1, i16 -1, i16 -1, i16 -1>
+// CHECK: [[VBSL4_I:%.*]] = and <4 x i16> [[TMP3]], %v3
// CHECK: [[VBSL5_I:%.*]] = or <4 x i16> [[VBSL3_I]], [[VBSL4_I]]
// CHECK: ret <4 x i16> [[VBSL5_I]]
poly16x4_t test_vbsl_p16(uint16x4_t v1, poly16x4_t v2, poly16x4_t v3) {
return vbsl_p16(v1, v2, v3);
}
-// CHECK-LABEL: define <16 x i8> @test_vbslq_s8(<16 x i8> %v1, <16 x i8> %v2, <16 x i8> %v3) #0 {
+// CHECK-LABEL: @test_vbslq_s8(
// CHECK: [[VBSL_I:%.*]] = and <16 x i8> %v1, %v2
// CHECK: [[TMP0:%.*]] = xor <16 x i8> %v1, <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>
// CHECK: [[VBSL1_I:%.*]] = and <16 x i8> [[TMP0]], %v3
@@ -1202,55 +1122,46 @@ int8x16_t test_vbslq_s8(uint8x16_t v1, int8x16_t v2, int8x16_t v3) {
return vbslq_s8(v1, v2, v3);
}
-// CHECK-LABEL: define <8 x i16> @test_vbslq_s16(<8 x i16> %v1, <8 x i16> %v2, <8 x i16> %v3) #0 {
+// CHECK-LABEL: @test_vbslq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %v2 to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i16> %v3 to <16 x i8>
-// CHECK: [[VBSL_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VBSL1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VBSL2_I:%.*]] = bitcast <16 x i8> [[TMP2]] to <8 x i16>
-// CHECK: [[VBSL3_I:%.*]] = and <8 x i16> [[VBSL_I]], [[VBSL1_I]]
-// CHECK: [[TMP3:%.*]] = xor <8 x i16> [[VBSL_I]], <i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1>
-// CHECK: [[VBSL4_I:%.*]] = and <8 x i16> [[TMP3]], [[VBSL2_I]]
+// CHECK: [[VBSL3_I:%.*]] = and <8 x i16> %v1, %v2
+// CHECK: [[TMP3:%.*]] = xor <8 x i16> %v1, <i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1>
+// CHECK: [[VBSL4_I:%.*]] = and <8 x i16> [[TMP3]], %v3
// CHECK: [[VBSL5_I:%.*]] = or <8 x i16> [[VBSL3_I]], [[VBSL4_I]]
// CHECK: ret <8 x i16> [[VBSL5_I]]
int16x8_t test_vbslq_s16(uint16x8_t v1, int16x8_t v2, int16x8_t v3) {
return vbslq_s16(v1, v2, v3);
}
-// CHECK-LABEL: define <4 x i32> @test_vbslq_s32(<4 x i32> %v1, <4 x i32> %v2, <4 x i32> %v3) #0 {
+// CHECK-LABEL: @test_vbslq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %v2 to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i32> %v3 to <16 x i8>
-// CHECK: [[VBSL_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VBSL1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VBSL2_I:%.*]] = bitcast <16 x i8> [[TMP2]] to <4 x i32>
-// CHECK: [[VBSL3_I:%.*]] = and <4 x i32> [[VBSL_I]], [[VBSL1_I]]
-// CHECK: [[TMP3:%.*]] = xor <4 x i32> [[VBSL_I]], <i32 -1, i32 -1, i32 -1, i32 -1>
-// CHECK: [[VBSL4_I:%.*]] = and <4 x i32> [[TMP3]], [[VBSL2_I]]
+// CHECK: [[VBSL3_I:%.*]] = and <4 x i32> %v1, %v2
+// CHECK: [[TMP3:%.*]] = xor <4 x i32> %v1, <i32 -1, i32 -1, i32 -1, i32 -1>
+// CHECK: [[VBSL4_I:%.*]] = and <4 x i32> [[TMP3]], %v3
// CHECK: [[VBSL5_I:%.*]] = or <4 x i32> [[VBSL3_I]], [[VBSL4_I]]
// CHECK: ret <4 x i32> [[VBSL5_I]]
int32x4_t test_vbslq_s32(uint32x4_t v1, int32x4_t v2, int32x4_t v3) {
return vbslq_s32(v1, v2, v3);
}
-// CHECK-LABEL: define <2 x i64> @test_vbslq_s64(<2 x i64> %v1, <2 x i64> %v2, <2 x i64> %v3) #0 {
+// CHECK-LABEL: @test_vbslq_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %v2 to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i64> %v3 to <16 x i8>
-// CHECK: [[VBSL_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VBSL1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VBSL2_I:%.*]] = bitcast <16 x i8> [[TMP2]] to <2 x i64>
-// CHECK: [[VBSL3_I:%.*]] = and <2 x i64> [[VBSL_I]], [[VBSL1_I]]
-// CHECK: [[TMP3:%.*]] = xor <2 x i64> [[VBSL_I]], <i64 -1, i64 -1>
-// CHECK: [[VBSL4_I:%.*]] = and <2 x i64> [[TMP3]], [[VBSL2_I]]
+// CHECK: [[VBSL3_I:%.*]] = and <2 x i64> %v1, %v2
+// CHECK: [[TMP3:%.*]] = xor <2 x i64> %v1, <i64 -1, i64 -1>
+// CHECK: [[VBSL4_I:%.*]] = and <2 x i64> [[TMP3]], %v3
// CHECK: [[VBSL5_I:%.*]] = or <2 x i64> [[VBSL3_I]], [[VBSL4_I]]
// CHECK: ret <2 x i64> [[VBSL5_I]]
int64x2_t test_vbslq_s64(uint64x2_t v1, int64x2_t v2, int64x2_t v3) {
return vbslq_s64(v1, v2, v3);
}
-// CHECK-LABEL: define <16 x i8> @test_vbslq_u8(<16 x i8> %v1, <16 x i8> %v2, <16 x i8> %v3) #0 {
+// CHECK-LABEL: @test_vbslq_u8(
// CHECK: [[VBSL_I:%.*]] = and <16 x i8> %v1, %v2
// CHECK: [[TMP0:%.*]] = xor <16 x i8> %v1, <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>
// CHECK: [[VBSL1_I:%.*]] = and <16 x i8> [[TMP0]], %v3
@@ -1260,63 +1171,53 @@ uint8x16_t test_vbslq_u8(uint8x16_t v1, uint8x16_t v2, uint8x16_t v3) {
return vbslq_u8(v1, v2, v3);
}
-// CHECK-LABEL: define <8 x i16> @test_vbslq_u16(<8 x i16> %v1, <8 x i16> %v2, <8 x i16> %v3) #0 {
+// CHECK-LABEL: @test_vbslq_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %v2 to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i16> %v3 to <16 x i8>
-// CHECK: [[VBSL_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VBSL1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VBSL2_I:%.*]] = bitcast <16 x i8> [[TMP2]] to <8 x i16>
-// CHECK: [[VBSL3_I:%.*]] = and <8 x i16> [[VBSL_I]], [[VBSL1_I]]
-// CHECK: [[TMP3:%.*]] = xor <8 x i16> [[VBSL_I]], <i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1>
-// CHECK: [[VBSL4_I:%.*]] = and <8 x i16> [[TMP3]], [[VBSL2_I]]
+// CHECK: [[VBSL3_I:%.*]] = and <8 x i16> %v1, %v2
+// CHECK: [[TMP3:%.*]] = xor <8 x i16> %v1, <i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1>
+// CHECK: [[VBSL4_I:%.*]] = and <8 x i16> [[TMP3]], %v3
// CHECK: [[VBSL5_I:%.*]] = or <8 x i16> [[VBSL3_I]], [[VBSL4_I]]
// CHECK: ret <8 x i16> [[VBSL5_I]]
uint16x8_t test_vbslq_u16(uint16x8_t v1, uint16x8_t v2, uint16x8_t v3) {
return vbslq_u16(v1, v2, v3);
}
-// CHECK-LABEL: define <4 x i32> @test_vbslq_u32(<4 x i32> %v1, <4 x i32> %v2, <4 x i32> %v3) #0 {
+// CHECK-LABEL: @test_vbslq_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %v2 to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i32> %v3 to <16 x i8>
-// CHECK: [[VBSL_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VBSL1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VBSL2_I:%.*]] = bitcast <16 x i8> [[TMP2]] to <4 x i32>
-// CHECK: [[VBSL3_I:%.*]] = and <4 x i32> [[VBSL_I]], [[VBSL1_I]]
-// CHECK: [[TMP3:%.*]] = xor <4 x i32> [[VBSL_I]], <i32 -1, i32 -1, i32 -1, i32 -1>
-// CHECK: [[VBSL4_I:%.*]] = and <4 x i32> [[TMP3]], [[VBSL2_I]]
+// CHECK: [[VBSL3_I:%.*]] = and <4 x i32> %v1, %v2
+// CHECK: [[TMP3:%.*]] = xor <4 x i32> %v1, <i32 -1, i32 -1, i32 -1, i32 -1>
+// CHECK: [[VBSL4_I:%.*]] = and <4 x i32> [[TMP3]], %v3
// CHECK: [[VBSL5_I:%.*]] = or <4 x i32> [[VBSL3_I]], [[VBSL4_I]]
// CHECK: ret <4 x i32> [[VBSL5_I]]
int32x4_t test_vbslq_u32(uint32x4_t v1, int32x4_t v2, int32x4_t v3) {
return vbslq_s32(v1, v2, v3);
}
-// CHECK-LABEL: define <2 x i64> @test_vbslq_u64(<2 x i64> %v1, <2 x i64> %v2, <2 x i64> %v3) #0 {
+// CHECK-LABEL: @test_vbslq_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %v2 to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i64> %v3 to <16 x i8>
-// CHECK: [[VBSL_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VBSL1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VBSL2_I:%.*]] = bitcast <16 x i8> [[TMP2]] to <2 x i64>
-// CHECK: [[VBSL3_I:%.*]] = and <2 x i64> [[VBSL_I]], [[VBSL1_I]]
-// CHECK: [[TMP3:%.*]] = xor <2 x i64> [[VBSL_I]], <i64 -1, i64 -1>
-// CHECK: [[VBSL4_I:%.*]] = and <2 x i64> [[TMP3]], [[VBSL2_I]]
+// CHECK: [[VBSL3_I:%.*]] = and <2 x i64> %v1, %v2
+// CHECK: [[TMP3:%.*]] = xor <2 x i64> %v1, <i64 -1, i64 -1>
+// CHECK: [[VBSL4_I:%.*]] = and <2 x i64> [[TMP3]], %v3
// CHECK: [[VBSL5_I:%.*]] = or <2 x i64> [[VBSL3_I]], [[VBSL4_I]]
// CHECK: ret <2 x i64> [[VBSL5_I]]
uint64x2_t test_vbslq_u64(uint64x2_t v1, uint64x2_t v2, uint64x2_t v3) {
return vbslq_u64(v1, v2, v3);
}
-// CHECK-LABEL: define <4 x float> @test_vbslq_f32(<4 x i32> %v1, <4 x float> %v2, <4 x float> %v3) #0 {
+// CHECK-LABEL: @test_vbslq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %v2 to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x float> %v3 to <16 x i8>
-// CHECK: [[VBSL_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VBSL1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
// CHECK: [[VBSL2_I:%.*]] = bitcast <16 x i8> [[TMP2]] to <4 x i32>
-// CHECK: [[VBSL3_I:%.*]] = and <4 x i32> [[VBSL_I]], [[VBSL1_I]]
-// CHECK: [[TMP3:%.*]] = xor <4 x i32> [[VBSL_I]], <i32 -1, i32 -1, i32 -1, i32 -1>
+// CHECK: [[VBSL3_I:%.*]] = and <4 x i32> %v1, [[VBSL1_I]]
+// CHECK: [[TMP3:%.*]] = xor <4 x i32> %v1, <i32 -1, i32 -1, i32 -1, i32 -1>
// CHECK: [[VBSL4_I:%.*]] = and <4 x i32> [[TMP3]], [[VBSL2_I]]
// CHECK: [[VBSL5_I:%.*]] = or <4 x i32> [[VBSL3_I]], [[VBSL4_I]]
// CHECK: [[TMP4:%.*]] = bitcast <4 x i32> [[VBSL5_I]] to <4 x float>
@@ -1325,7 +1226,7 @@ float32x4_t test_vbslq_f32(uint32x4_t v1, float32x4_t v2, float32x4_t v3) {
return vbslq_f32(v1, v2, v3);
}
-// CHECK-LABEL: define <16 x i8> @test_vbslq_p8(<16 x i8> %v1, <16 x i8> %v2, <16 x i8> %v3) #0 {
+// CHECK-LABEL: @test_vbslq_p8(
// CHECK: [[VBSL_I:%.*]] = and <16 x i8> %v1, %v2
// CHECK: [[TMP0:%.*]] = xor <16 x i8> %v1, <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>
// CHECK: [[VBSL1_I:%.*]] = and <16 x i8> [[TMP0]], %v3
@@ -1335,31 +1236,27 @@ poly8x16_t test_vbslq_p8(uint8x16_t v1, poly8x16_t v2, poly8x16_t v3) {
return vbslq_p8(v1, v2, v3);
}
-// CHECK-LABEL: define <8 x i16> @test_vbslq_p16(<8 x i16> %v1, <8 x i16> %v2, <8 x i16> %v3) #0 {
+// CHECK-LABEL: @test_vbslq_p16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %v2 to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i16> %v3 to <16 x i8>
-// CHECK: [[VBSL_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VBSL1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VBSL2_I:%.*]] = bitcast <16 x i8> [[TMP2]] to <8 x i16>
-// CHECK: [[VBSL3_I:%.*]] = and <8 x i16> [[VBSL_I]], [[VBSL1_I]]
-// CHECK: [[TMP3:%.*]] = xor <8 x i16> [[VBSL_I]], <i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1>
-// CHECK: [[VBSL4_I:%.*]] = and <8 x i16> [[TMP3]], [[VBSL2_I]]
+// CHECK: [[VBSL3_I:%.*]] = and <8 x i16> %v1, %v2
+// CHECK: [[TMP3:%.*]] = xor <8 x i16> %v1, <i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1>
+// CHECK: [[VBSL4_I:%.*]] = and <8 x i16> [[TMP3]], %v3
// CHECK: [[VBSL5_I:%.*]] = or <8 x i16> [[VBSL3_I]], [[VBSL4_I]]
// CHECK: ret <8 x i16> [[VBSL5_I]]
poly16x8_t test_vbslq_p16(uint16x8_t v1, poly16x8_t v2, poly16x8_t v3) {
return vbslq_p16(v1, v2, v3);
}
-// CHECK-LABEL: define <2 x double> @test_vbslq_f64(<2 x i64> %v1, <2 x double> %v2, <2 x double> %v3) #0 {
+// CHECK-LABEL: @test_vbslq_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x double> %v2 to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x double> %v3 to <16 x i8>
-// CHECK: [[VBSL_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VBSL1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
// CHECK: [[VBSL2_I:%.*]] = bitcast <16 x i8> [[TMP2]] to <2 x i64>
-// CHECK: [[VBSL3_I:%.*]] = and <2 x i64> [[VBSL_I]], [[VBSL1_I]]
-// CHECK: [[TMP3:%.*]] = xor <2 x i64> [[VBSL_I]], <i64 -1, i64 -1>
+// CHECK: [[VBSL3_I:%.*]] = and <2 x i64> %v1, [[VBSL1_I]]
+// CHECK: [[TMP3:%.*]] = xor <2 x i64> %v1, <i64 -1, i64 -1>
// CHECK: [[VBSL4_I:%.*]] = and <2 x i64> [[TMP3]], [[VBSL2_I]]
// CHECK: [[VBSL5_I:%.*]] = or <2 x i64> [[VBSL3_I]], [[VBSL4_I]]
// CHECK: [[TMP4:%.*]] = bitcast <2 x i64> [[VBSL5_I]] to <2 x double>
@@ -1368,267 +1265,216 @@ float64x2_t test_vbslq_f64(uint64x2_t v1, float64x2_t v2, float64x2_t v3) {
return vbslq_f64(v1, v2, v3);
}
-// CHECK-LABEL: define <2 x float> @test_vrecps_f32(<2 x float> %v1, <2 x float> %v2) #0 {
+// CHECK-LABEL: @test_vrecps_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %v1 to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %v2 to <8 x i8>
-// CHECK: [[VRECPS_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VRECPS_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK: [[VRECPS_V2_I:%.*]] = call <2 x float> @llvm.aarch64.neon.frecps.v2f32(<2 x float> [[VRECPS_V_I]], <2 x float> [[VRECPS_V1_I]]) #4
-// CHECK: [[VRECPS_V3_I:%.*]] = bitcast <2 x float> [[VRECPS_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRECPS_V3_I]] to <2 x float>
-// CHECK: ret <2 x float> [[TMP2]]
+// CHECK: [[VRECPS_V2_I:%.*]] = call <2 x float> @llvm.aarch64.neon.frecps.v2f32(<2 x float> %v1, <2 x float> %v2) #4
+// CHECK: ret <2 x float> [[VRECPS_V2_I]]
float32x2_t test_vrecps_f32(float32x2_t v1, float32x2_t v2) {
- return vrecps_f32(v1, v2);
+ return vrecps_f32(v1, v2);
}
-// CHECK-LABEL: define <4 x float> @test_vrecpsq_f32(<4 x float> %v1, <4 x float> %v2) #0 {
+// CHECK-LABEL: @test_vrecpsq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %v2 to <16 x i8>
-// CHECK: [[VRECPSQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VRECPSQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
-// CHECK: [[VRECPSQ_V2_I:%.*]] = call <4 x float> @llvm.aarch64.neon.frecps.v4f32(<4 x float> [[VRECPSQ_V_I]], <4 x float> [[VRECPSQ_V1_I]]) #4
+// CHECK: [[VRECPSQ_V2_I:%.*]] = call <4 x float> @llvm.aarch64.neon.frecps.v4f32(<4 x float> %v1, <4 x float> %v2) #4
// CHECK: [[VRECPSQ_V3_I:%.*]] = bitcast <4 x float> [[VRECPSQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VRECPSQ_V3_I]] to <4 x float>
-// CHECK: ret <4 x float> [[TMP2]]
+// CHECK: ret <4 x float> [[VRECPSQ_V2_I]]
float32x4_t test_vrecpsq_f32(float32x4_t v1, float32x4_t v2) {
- return vrecpsq_f32(v1, v2);
+ return vrecpsq_f32(v1, v2);
}
-// CHECK-LABEL: define <2 x double> @test_vrecpsq_f64(<2 x double> %v1, <2 x double> %v2) #0 {
+// CHECK-LABEL: @test_vrecpsq_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x double> %v2 to <16 x i8>
-// CHECK: [[VRECPSQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VRECPSQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x double>
-// CHECK: [[VRECPSQ_V2_I:%.*]] = call <2 x double> @llvm.aarch64.neon.frecps.v2f64(<2 x double> [[VRECPSQ_V_I]], <2 x double> [[VRECPSQ_V1_I]]) #4
+// CHECK: [[VRECPSQ_V2_I:%.*]] = call <2 x double> @llvm.aarch64.neon.frecps.v2f64(<2 x double> %v1, <2 x double> %v2) #4
// CHECK: [[VRECPSQ_V3_I:%.*]] = bitcast <2 x double> [[VRECPSQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VRECPSQ_V3_I]] to <2 x double>
-// CHECK: ret <2 x double> [[TMP2]]
+// CHECK: ret <2 x double> [[VRECPSQ_V2_I]]
float64x2_t test_vrecpsq_f64(float64x2_t v1, float64x2_t v2) {
return vrecpsq_f64(v1, v2);
}
-// CHECK-LABEL: define <2 x float> @test_vrsqrts_f32(<2 x float> %v1, <2 x float> %v2) #0 {
+// CHECK-LABEL: @test_vrsqrts_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %v1 to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %v2 to <8 x i8>
-// CHECK: [[VRSQRTS_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VRSQRTS_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK: [[VRSQRTS_V2_I:%.*]] = call <2 x float> @llvm.aarch64.neon.frsqrts.v2f32(<2 x float> [[VRSQRTS_V_I]], <2 x float> [[VRSQRTS_V1_I]]) #4
+// CHECK: [[VRSQRTS_V2_I:%.*]] = call <2 x float> @llvm.aarch64.neon.frsqrts.v2f32(<2 x float> %v1, <2 x float> %v2) #4
// CHECK: [[VRSQRTS_V3_I:%.*]] = bitcast <2 x float> [[VRSQRTS_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRSQRTS_V3_I]] to <2 x float>
-// CHECK: ret <2 x float> [[TMP2]]
+// CHECK: ret <2 x float> [[VRSQRTS_V2_I]]
float32x2_t test_vrsqrts_f32(float32x2_t v1, float32x2_t v2) {
return vrsqrts_f32(v1, v2);
}
-// CHECK-LABEL: define <4 x float> @test_vrsqrtsq_f32(<4 x float> %v1, <4 x float> %v2) #0 {
+// CHECK-LABEL: @test_vrsqrtsq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %v2 to <16 x i8>
-// CHECK: [[VRSQRTSQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VRSQRTSQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
-// CHECK: [[VRSQRTSQ_V2_I:%.*]] = call <4 x float> @llvm.aarch64.neon.frsqrts.v4f32(<4 x float> [[VRSQRTSQ_V_I]], <4 x float> [[VRSQRTSQ_V1_I]]) #4
+// CHECK: [[VRSQRTSQ_V2_I:%.*]] = call <4 x float> @llvm.aarch64.neon.frsqrts.v4f32(<4 x float> %v1, <4 x float> %v2) #4
// CHECK: [[VRSQRTSQ_V3_I:%.*]] = bitcast <4 x float> [[VRSQRTSQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VRSQRTSQ_V3_I]] to <4 x float>
-// CHECK: ret <4 x float> [[TMP2]]
+// CHECK: ret <4 x float> [[VRSQRTSQ_V2_I]]
float32x4_t test_vrsqrtsq_f32(float32x4_t v1, float32x4_t v2) {
return vrsqrtsq_f32(v1, v2);
}
-// CHECK-LABEL: define <2 x double> @test_vrsqrtsq_f64(<2 x double> %v1, <2 x double> %v2) #0 {
+// CHECK-LABEL: @test_vrsqrtsq_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x double> %v2 to <16 x i8>
-// CHECK: [[VRSQRTSQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VRSQRTSQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x double>
-// CHECK: [[VRSQRTSQ_V2_I:%.*]] = call <2 x double> @llvm.aarch64.neon.frsqrts.v2f64(<2 x double> [[VRSQRTSQ_V_I]], <2 x double> [[VRSQRTSQ_V1_I]]) #4
+// CHECK: [[VRSQRTSQ_V2_I:%.*]] = call <2 x double> @llvm.aarch64.neon.frsqrts.v2f64(<2 x double> %v1, <2 x double> %v2) #4
// CHECK: [[VRSQRTSQ_V3_I:%.*]] = bitcast <2 x double> [[VRSQRTSQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VRSQRTSQ_V3_I]] to <2 x double>
-// CHECK: ret <2 x double> [[TMP2]]
+// CHECK: ret <2 x double> [[VRSQRTSQ_V2_I]]
float64x2_t test_vrsqrtsq_f64(float64x2_t v1, float64x2_t v2) {
return vrsqrtsq_f64(v1, v2);
}
-// CHECK-LABEL: define <2 x i32> @test_vcage_f32(<2 x float> %v1, <2 x float> %v2) #0 {
+// CHECK-LABEL: @test_vcage_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %v1 to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %v2 to <8 x i8>
-// CHECK: [[VCAGE_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VCAGE_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK: [[VCAGE_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.facge.v2i32.v2f32(<2 x float> [[VCAGE_V_I]], <2 x float> [[VCAGE_V1_I]]) #4
+// CHECK: [[VCAGE_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.facge.v2i32.v2f32(<2 x float> %v1, <2 x float> %v2) #4
// CHECK: ret <2 x i32> [[VCAGE_V2_I]]
uint32x2_t test_vcage_f32(float32x2_t v1, float32x2_t v2) {
return vcage_f32(v1, v2);
}
-// CHECK-LABEL: define <1 x i64> @test_vcage_f64(<1 x double> %a, <1 x double> %b) #0 {
+// CHECK-LABEL: @test_vcage_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x double> %b to <8 x i8>
-// CHECK: [[VCAGE_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x double>
-// CHECK: [[VCAGE_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x double>
-// CHECK: [[VCAGE_V2_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.facge.v1i64.v1f64(<1 x double> [[VCAGE_V_I]], <1 x double> [[VCAGE_V1_I]]) #4
+// CHECK: [[VCAGE_V2_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.facge.v1i64.v1f64(<1 x double> %a, <1 x double> %b) #4
// CHECK: ret <1 x i64> [[VCAGE_V2_I]]
uint64x1_t test_vcage_f64(float64x1_t a, float64x1_t b) {
return vcage_f64(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vcageq_f32(<4 x float> %v1, <4 x float> %v2) #0 {
+// CHECK-LABEL: @test_vcageq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %v2 to <16 x i8>
-// CHECK: [[VCAGEQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VCAGEQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
-// CHECK: [[VCAGEQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.facge.v4i32.v4f32(<4 x float> [[VCAGEQ_V_I]], <4 x float> [[VCAGEQ_V1_I]]) #4
+// CHECK: [[VCAGEQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.facge.v4i32.v4f32(<4 x float> %v1, <4 x float> %v2) #4
// CHECK: ret <4 x i32> [[VCAGEQ_V2_I]]
uint32x4_t test_vcageq_f32(float32x4_t v1, float32x4_t v2) {
return vcageq_f32(v1, v2);
}
-// CHECK-LABEL: define <2 x i64> @test_vcageq_f64(<2 x double> %v1, <2 x double> %v2) #0 {
+// CHECK-LABEL: @test_vcageq_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x double> %v2 to <16 x i8>
-// CHECK: [[VCAGEQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VCAGEQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x double>
-// CHECK: [[VCAGEQ_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.facge.v2i64.v2f64(<2 x double> [[VCAGEQ_V_I]], <2 x double> [[VCAGEQ_V1_I]]) #4
+// CHECK: [[VCAGEQ_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.facge.v2i64.v2f64(<2 x double> %v1, <2 x double> %v2) #4
// CHECK: ret <2 x i64> [[VCAGEQ_V2_I]]
uint64x2_t test_vcageq_f64(float64x2_t v1, float64x2_t v2) {
return vcageq_f64(v1, v2);
}
-// CHECK-LABEL: define <2 x i32> @test_vcagt_f32(<2 x float> %v1, <2 x float> %v2) #0 {
+// CHECK-LABEL: @test_vcagt_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %v1 to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %v2 to <8 x i8>
-// CHECK: [[VCAGT_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VCAGT_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK: [[VCAGT_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.facgt.v2i32.v2f32(<2 x float> [[VCAGT_V_I]], <2 x float> [[VCAGT_V1_I]]) #4
+// CHECK: [[VCAGT_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.facgt.v2i32.v2f32(<2 x float> %v1, <2 x float> %v2) #4
// CHECK: ret <2 x i32> [[VCAGT_V2_I]]
uint32x2_t test_vcagt_f32(float32x2_t v1, float32x2_t v2) {
return vcagt_f32(v1, v2);
}
-// CHECK-LABEL: define <1 x i64> @test_vcagt_f64(<1 x double> %a, <1 x double> %b) #0 {
+// CHECK-LABEL: @test_vcagt_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x double> %b to <8 x i8>
-// CHECK: [[VCAGT_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x double>
-// CHECK: [[VCAGT_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x double>
-// CHECK: [[VCAGT_V2_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.facgt.v1i64.v1f64(<1 x double> [[VCAGT_V_I]], <1 x double> [[VCAGT_V1_I]]) #4
+// CHECK: [[VCAGT_V2_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.facgt.v1i64.v1f64(<1 x double> %a, <1 x double> %b) #4
// CHECK: ret <1 x i64> [[VCAGT_V2_I]]
uint64x1_t test_vcagt_f64(float64x1_t a, float64x1_t b) {
return vcagt_f64(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vcagtq_f32(<4 x float> %v1, <4 x float> %v2) #0 {
+// CHECK-LABEL: @test_vcagtq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %v2 to <16 x i8>
-// CHECK: [[VCAGTQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VCAGTQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
-// CHECK: [[VCAGTQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.facgt.v4i32.v4f32(<4 x float> [[VCAGTQ_V_I]], <4 x float> [[VCAGTQ_V1_I]]) #4
+// CHECK: [[VCAGTQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.facgt.v4i32.v4f32(<4 x float> %v1, <4 x float> %v2) #4
// CHECK: ret <4 x i32> [[VCAGTQ_V2_I]]
uint32x4_t test_vcagtq_f32(float32x4_t v1, float32x4_t v2) {
return vcagtq_f32(v1, v2);
}
-// CHECK-LABEL: define <2 x i64> @test_vcagtq_f64(<2 x double> %v1, <2 x double> %v2) #0 {
+// CHECK-LABEL: @test_vcagtq_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x double> %v2 to <16 x i8>
-// CHECK: [[VCAGTQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VCAGTQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x double>
-// CHECK: [[VCAGTQ_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.facgt.v2i64.v2f64(<2 x double> [[VCAGTQ_V_I]], <2 x double> [[VCAGTQ_V1_I]]) #4
+// CHECK: [[VCAGTQ_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.facgt.v2i64.v2f64(<2 x double> %v1, <2 x double> %v2) #4
// CHECK: ret <2 x i64> [[VCAGTQ_V2_I]]
uint64x2_t test_vcagtq_f64(float64x2_t v1, float64x2_t v2) {
return vcagtq_f64(v1, v2);
}
-// CHECK-LABEL: define <2 x i32> @test_vcale_f32(<2 x float> %v1, <2 x float> %v2) #0 {
+// CHECK-LABEL: @test_vcale_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %v1 to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %v2 to <8 x i8>
-// CHECK: [[VCALE_V_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK: [[VCALE_V1_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VCALE_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.facge.v2i32.v2f32(<2 x float> [[VCALE_V_I]], <2 x float> [[VCALE_V1_I]]) #4
+// CHECK: [[VCALE_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.facge.v2i32.v2f32(<2 x float> %v2, <2 x float> %v1) #4
// CHECK: ret <2 x i32> [[VCALE_V2_I]]
uint32x2_t test_vcale_f32(float32x2_t v1, float32x2_t v2) {
return vcale_f32(v1, v2);
// Using registers other than v0, v1 are possible, but would be odd.
}
-// CHECK-LABEL: define <1 x i64> @test_vcale_f64(<1 x double> %a, <1 x double> %b) #0 {
+// CHECK-LABEL: @test_vcale_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x double> %b to <8 x i8>
-// CHECK: [[VCALE_V_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x double>
-// CHECK: [[VCALE_V1_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x double>
-// CHECK: [[VCALE_V2_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.facge.v1i64.v1f64(<1 x double> [[VCALE_V_I]], <1 x double> [[VCALE_V1_I]]) #4
+// CHECK: [[VCALE_V2_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.facge.v1i64.v1f64(<1 x double> %b, <1 x double> %a) #4
// CHECK: ret <1 x i64> [[VCALE_V2_I]]
uint64x1_t test_vcale_f64(float64x1_t a, float64x1_t b) {
return vcale_f64(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vcaleq_f32(<4 x float> %v1, <4 x float> %v2) #0 {
+// CHECK-LABEL: @test_vcaleq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %v2 to <16 x i8>
-// CHECK: [[VCALEQ_V_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
-// CHECK: [[VCALEQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VCALEQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.facge.v4i32.v4f32(<4 x float> [[VCALEQ_V_I]], <4 x float> [[VCALEQ_V1_I]]) #4
+// CHECK: [[VCALEQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.facge.v4i32.v4f32(<4 x float> %v2, <4 x float> %v1) #4
// CHECK: ret <4 x i32> [[VCALEQ_V2_I]]
uint32x4_t test_vcaleq_f32(float32x4_t v1, float32x4_t v2) {
return vcaleq_f32(v1, v2);
// Using registers other than v0, v1 are possible, but would be odd.
}
-// CHECK-LABEL: define <2 x i64> @test_vcaleq_f64(<2 x double> %v1, <2 x double> %v2) #0 {
+// CHECK-LABEL: @test_vcaleq_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x double> %v2 to <16 x i8>
-// CHECK: [[VCALEQ_V_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x double>
-// CHECK: [[VCALEQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VCALEQ_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.facge.v2i64.v2f64(<2 x double> [[VCALEQ_V_I]], <2 x double> [[VCALEQ_V1_I]]) #4
+// CHECK: [[VCALEQ_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.facge.v2i64.v2f64(<2 x double> %v2, <2 x double> %v1) #4
// CHECK: ret <2 x i64> [[VCALEQ_V2_I]]
uint64x2_t test_vcaleq_f64(float64x2_t v1, float64x2_t v2) {
return vcaleq_f64(v1, v2);
// Using registers other than v0, v1 are possible, but would be odd.
}
-// CHECK-LABEL: define <2 x i32> @test_vcalt_f32(<2 x float> %v1, <2 x float> %v2) #0 {
+// CHECK-LABEL: @test_vcalt_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %v1 to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %v2 to <8 x i8>
-// CHECK: [[VCALT_V_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK: [[VCALT_V1_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VCALT_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.facgt.v2i32.v2f32(<2 x float> [[VCALT_V_I]], <2 x float> [[VCALT_V1_I]]) #4
+// CHECK: [[VCALT_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.facgt.v2i32.v2f32(<2 x float> %v2, <2 x float> %v1) #4
// CHECK: ret <2 x i32> [[VCALT_V2_I]]
uint32x2_t test_vcalt_f32(float32x2_t v1, float32x2_t v2) {
return vcalt_f32(v1, v2);
// Using registers other than v0, v1 are possible, but would be odd.
}
-// CHECK-LABEL: define <1 x i64> @test_vcalt_f64(<1 x double> %a, <1 x double> %b) #0 {
+// CHECK-LABEL: @test_vcalt_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x double> %b to <8 x i8>
-// CHECK: [[VCALT_V_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x double>
-// CHECK: [[VCALT_V1_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x double>
-// CHECK: [[VCALT_V2_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.facgt.v1i64.v1f64(<1 x double> [[VCALT_V_I]], <1 x double> [[VCALT_V1_I]]) #4
+// CHECK: [[VCALT_V2_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.facgt.v1i64.v1f64(<1 x double> %b, <1 x double> %a) #4
// CHECK: ret <1 x i64> [[VCALT_V2_I]]
uint64x1_t test_vcalt_f64(float64x1_t a, float64x1_t b) {
return vcalt_f64(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vcaltq_f32(<4 x float> %v1, <4 x float> %v2) #0 {
+// CHECK-LABEL: @test_vcaltq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %v2 to <16 x i8>
-// CHECK: [[VCALTQ_V_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
-// CHECK: [[VCALTQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VCALTQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.facgt.v4i32.v4f32(<4 x float> [[VCALTQ_V_I]], <4 x float> [[VCALTQ_V1_I]]) #4
+// CHECK: [[VCALTQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.facgt.v4i32.v4f32(<4 x float> %v2, <4 x float> %v1) #4
// CHECK: ret <4 x i32> [[VCALTQ_V2_I]]
uint32x4_t test_vcaltq_f32(float32x4_t v1, float32x4_t v2) {
return vcaltq_f32(v1, v2);
// Using registers other than v0, v1 are possible, but would be odd.
}
-// CHECK-LABEL: define <2 x i64> @test_vcaltq_f64(<2 x double> %v1, <2 x double> %v2) #0 {
+// CHECK-LABEL: @test_vcaltq_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x double> %v2 to <16 x i8>
-// CHECK: [[VCALTQ_V_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x double>
-// CHECK: [[VCALTQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VCALTQ_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.facgt.v2i64.v2f64(<2 x double> [[VCALTQ_V_I]], <2 x double> [[VCALTQ_V1_I]]) #4
+// CHECK: [[VCALTQ_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.facgt.v2i64.v2f64(<2 x double> %v2, <2 x double> %v1) #4
// CHECK: ret <2 x i64> [[VCALTQ_V2_I]]
uint64x2_t test_vcaltq_f64(float64x2_t v1, float64x2_t v2) {
return vcaltq_f64(v1, v2);
// Using registers other than v0, v1 are possible, but would be odd.
}
-// CHECK-LABEL: define <8 x i8> @test_vtst_s8(<8 x i8> %v1, <8 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vtst_s8(
// CHECK: [[TMP0:%.*]] = and <8 x i8> %v1, %v2
// CHECK: [[TMP1:%.*]] = icmp ne <8 x i8> [[TMP0]], zeroinitializer
// CHECK: [[VTST_I:%.*]] = sext <8 x i1> [[TMP1]] to <8 x i8>
@@ -1637,33 +1483,29 @@ uint8x8_t test_vtst_s8(int8x8_t v1, int8x8_t v2) {
return vtst_s8(v1, v2);
}
-// CHECK-LABEL: define <4 x i16> @test_vtst_s16(<4 x i16> %v1, <4 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vtst_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %v1 to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %v2 to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[TMP4:%.*]] = and <4 x i16> [[TMP2]], [[TMP3]]
-// CHECK: [[TMP5:%.*]] = icmp ne <4 x i16> [[TMP4]], zeroinitializer
-// CHECK: [[VTST_I:%.*]] = sext <4 x i1> [[TMP5]] to <4 x i16>
+// CHECK: [[TMP2:%.*]] = and <4 x i16> %v1, %v2
+// CHECK: [[TMP3:%.*]] = icmp ne <4 x i16> [[TMP2]], zeroinitializer
+// CHECK: [[VTST_I:%.*]] = sext <4 x i1> [[TMP3]] to <4 x i16>
// CHECK: ret <4 x i16> [[VTST_I]]
uint16x4_t test_vtst_s16(int16x4_t v1, int16x4_t v2) {
return vtst_s16(v1, v2);
}
-// CHECK-LABEL: define <2 x i32> @test_vtst_s32(<2 x i32> %v1, <2 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vtst_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %v1 to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %v2 to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[TMP4:%.*]] = and <2 x i32> [[TMP2]], [[TMP3]]
-// CHECK: [[TMP5:%.*]] = icmp ne <2 x i32> [[TMP4]], zeroinitializer
-// CHECK: [[VTST_I:%.*]] = sext <2 x i1> [[TMP5]] to <2 x i32>
+// CHECK: [[TMP2:%.*]] = and <2 x i32> %v1, %v2
+// CHECK: [[TMP3:%.*]] = icmp ne <2 x i32> [[TMP2]], zeroinitializer
+// CHECK: [[VTST_I:%.*]] = sext <2 x i1> [[TMP3]] to <2 x i32>
// CHECK: ret <2 x i32> [[VTST_I]]
uint32x2_t test_vtst_s32(int32x2_t v1, int32x2_t v2) {
return vtst_s32(v1, v2);
}
-// CHECK-LABEL: define <8 x i8> @test_vtst_u8(<8 x i8> %v1, <8 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vtst_u8(
// CHECK: [[TMP0:%.*]] = and <8 x i8> %v1, %v2
// CHECK: [[TMP1:%.*]] = icmp ne <8 x i8> [[TMP0]], zeroinitializer
// CHECK: [[VTST_I:%.*]] = sext <8 x i1> [[TMP1]] to <8 x i8>
@@ -1672,33 +1514,29 @@ uint8x8_t test_vtst_u8(uint8x8_t v1, uint8x8_t v2) {
return vtst_u8(v1, v2);
}
-// CHECK-LABEL: define <4 x i16> @test_vtst_u16(<4 x i16> %v1, <4 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vtst_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %v1 to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %v2 to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[TMP4:%.*]] = and <4 x i16> [[TMP2]], [[TMP3]]
-// CHECK: [[TMP5:%.*]] = icmp ne <4 x i16> [[TMP4]], zeroinitializer
-// CHECK: [[VTST_I:%.*]] = sext <4 x i1> [[TMP5]] to <4 x i16>
+// CHECK: [[TMP2:%.*]] = and <4 x i16> %v1, %v2
+// CHECK: [[TMP3:%.*]] = icmp ne <4 x i16> [[TMP2]], zeroinitializer
+// CHECK: [[VTST_I:%.*]] = sext <4 x i1> [[TMP3]] to <4 x i16>
// CHECK: ret <4 x i16> [[VTST_I]]
uint16x4_t test_vtst_u16(uint16x4_t v1, uint16x4_t v2) {
return vtst_u16(v1, v2);
}
-// CHECK-LABEL: define <2 x i32> @test_vtst_u32(<2 x i32> %v1, <2 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vtst_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %v1 to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %v2 to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[TMP4:%.*]] = and <2 x i32> [[TMP2]], [[TMP3]]
-// CHECK: [[TMP5:%.*]] = icmp ne <2 x i32> [[TMP4]], zeroinitializer
-// CHECK: [[VTST_I:%.*]] = sext <2 x i1> [[TMP5]] to <2 x i32>
+// CHECK: [[TMP2:%.*]] = and <2 x i32> %v1, %v2
+// CHECK: [[TMP3:%.*]] = icmp ne <2 x i32> [[TMP2]], zeroinitializer
+// CHECK: [[VTST_I:%.*]] = sext <2 x i1> [[TMP3]] to <2 x i32>
// CHECK: ret <2 x i32> [[VTST_I]]
uint32x2_t test_vtst_u32(uint32x2_t v1, uint32x2_t v2) {
return vtst_u32(v1, v2);
}
-// CHECK-LABEL: define <16 x i8> @test_vtstq_s8(<16 x i8> %v1, <16 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vtstq_s8(
// CHECK: [[TMP0:%.*]] = and <16 x i8> %v1, %v2
// CHECK: [[TMP1:%.*]] = icmp ne <16 x i8> [[TMP0]], zeroinitializer
// CHECK: [[VTST_I:%.*]] = sext <16 x i1> [[TMP1]] to <16 x i8>
@@ -1707,33 +1545,29 @@ uint8x16_t test_vtstq_s8(int8x16_t v1, int8x16_t v2) {
return vtstq_s8(v1, v2);
}
-// CHECK-LABEL: define <8 x i16> @test_vtstq_s16(<8 x i16> %v1, <8 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vtstq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %v2 to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[TMP4:%.*]] = and <8 x i16> [[TMP2]], [[TMP3]]
-// CHECK: [[TMP5:%.*]] = icmp ne <8 x i16> [[TMP4]], zeroinitializer
-// CHECK: [[VTST_I:%.*]] = sext <8 x i1> [[TMP5]] to <8 x i16>
+// CHECK: [[TMP2:%.*]] = and <8 x i16> %v1, %v2
+// CHECK: [[TMP3:%.*]] = icmp ne <8 x i16> [[TMP2]], zeroinitializer
+// CHECK: [[VTST_I:%.*]] = sext <8 x i1> [[TMP3]] to <8 x i16>
// CHECK: ret <8 x i16> [[VTST_I]]
uint16x8_t test_vtstq_s16(int16x8_t v1, int16x8_t v2) {
return vtstq_s16(v1, v2);
}
-// CHECK-LABEL: define <4 x i32> @test_vtstq_s32(<4 x i32> %v1, <4 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vtstq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %v2 to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[TMP4:%.*]] = and <4 x i32> [[TMP2]], [[TMP3]]
-// CHECK: [[TMP5:%.*]] = icmp ne <4 x i32> [[TMP4]], zeroinitializer
-// CHECK: [[VTST_I:%.*]] = sext <4 x i1> [[TMP5]] to <4 x i32>
+// CHECK: [[TMP2:%.*]] = and <4 x i32> %v1, %v2
+// CHECK: [[TMP3:%.*]] = icmp ne <4 x i32> [[TMP2]], zeroinitializer
+// CHECK: [[VTST_I:%.*]] = sext <4 x i1> [[TMP3]] to <4 x i32>
// CHECK: ret <4 x i32> [[VTST_I]]
uint32x4_t test_vtstq_s32(int32x4_t v1, int32x4_t v2) {
return vtstq_s32(v1, v2);
}
-// CHECK-LABEL: define <16 x i8> @test_vtstq_u8(<16 x i8> %v1, <16 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vtstq_u8(
// CHECK: [[TMP0:%.*]] = and <16 x i8> %v1, %v2
// CHECK: [[TMP1:%.*]] = icmp ne <16 x i8> [[TMP0]], zeroinitializer
// CHECK: [[VTST_I:%.*]] = sext <16 x i1> [[TMP1]] to <16 x i8>
@@ -1742,59 +1576,51 @@ uint8x16_t test_vtstq_u8(uint8x16_t v1, uint8x16_t v2) {
return vtstq_u8(v1, v2);
}
-// CHECK-LABEL: define <8 x i16> @test_vtstq_u16(<8 x i16> %v1, <8 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vtstq_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %v2 to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[TMP4:%.*]] = and <8 x i16> [[TMP2]], [[TMP3]]
-// CHECK: [[TMP5:%.*]] = icmp ne <8 x i16> [[TMP4]], zeroinitializer
-// CHECK: [[VTST_I:%.*]] = sext <8 x i1> [[TMP5]] to <8 x i16>
+// CHECK: [[TMP2:%.*]] = and <8 x i16> %v1, %v2
+// CHECK: [[TMP3:%.*]] = icmp ne <8 x i16> [[TMP2]], zeroinitializer
+// CHECK: [[VTST_I:%.*]] = sext <8 x i1> [[TMP3]] to <8 x i16>
// CHECK: ret <8 x i16> [[VTST_I]]
uint16x8_t test_vtstq_u16(uint16x8_t v1, uint16x8_t v2) {
return vtstq_u16(v1, v2);
}
-// CHECK-LABEL: define <4 x i32> @test_vtstq_u32(<4 x i32> %v1, <4 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vtstq_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %v2 to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[TMP4:%.*]] = and <4 x i32> [[TMP2]], [[TMP3]]
-// CHECK: [[TMP5:%.*]] = icmp ne <4 x i32> [[TMP4]], zeroinitializer
-// CHECK: [[VTST_I:%.*]] = sext <4 x i1> [[TMP5]] to <4 x i32>
+// CHECK: [[TMP2:%.*]] = and <4 x i32> %v1, %v2
+// CHECK: [[TMP3:%.*]] = icmp ne <4 x i32> [[TMP2]], zeroinitializer
+// CHECK: [[VTST_I:%.*]] = sext <4 x i1> [[TMP3]] to <4 x i32>
// CHECK: ret <4 x i32> [[VTST_I]]
uint32x4_t test_vtstq_u32(uint32x4_t v1, uint32x4_t v2) {
return vtstq_u32(v1, v2);
}
-// CHECK-LABEL: define <2 x i64> @test_vtstq_s64(<2 x i64> %v1, <2 x i64> %v2) #0 {
+// CHECK-LABEL: @test_vtstq_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %v2 to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[TMP4:%.*]] = and <2 x i64> [[TMP2]], [[TMP3]]
-// CHECK: [[TMP5:%.*]] = icmp ne <2 x i64> [[TMP4]], zeroinitializer
-// CHECK: [[VTST_I:%.*]] = sext <2 x i1> [[TMP5]] to <2 x i64>
+// CHECK: [[TMP2:%.*]] = and <2 x i64> %v1, %v2
+// CHECK: [[TMP3:%.*]] = icmp ne <2 x i64> [[TMP2]], zeroinitializer
+// CHECK: [[VTST_I:%.*]] = sext <2 x i1> [[TMP3]] to <2 x i64>
// CHECK: ret <2 x i64> [[VTST_I]]
uint64x2_t test_vtstq_s64(int64x2_t v1, int64x2_t v2) {
return vtstq_s64(v1, v2);
}
-// CHECK-LABEL: define <2 x i64> @test_vtstq_u64(<2 x i64> %v1, <2 x i64> %v2) #0 {
+// CHECK-LABEL: @test_vtstq_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %v2 to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[TMP4:%.*]] = and <2 x i64> [[TMP2]], [[TMP3]]
-// CHECK: [[TMP5:%.*]] = icmp ne <2 x i64> [[TMP4]], zeroinitializer
-// CHECK: [[VTST_I:%.*]] = sext <2 x i1> [[TMP5]] to <2 x i64>
+// CHECK: [[TMP2:%.*]] = and <2 x i64> %v1, %v2
+// CHECK: [[TMP3:%.*]] = icmp ne <2 x i64> [[TMP2]], zeroinitializer
+// CHECK: [[VTST_I:%.*]] = sext <2 x i1> [[TMP3]] to <2 x i64>
// CHECK: ret <2 x i64> [[VTST_I]]
uint64x2_t test_vtstq_u64(uint64x2_t v1, uint64x2_t v2) {
return vtstq_u64(v1, v2);
}
-// CHECK-LABEL: define <8 x i8> @test_vtst_p8(<8 x i8> %v1, <8 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vtst_p8(
// CHECK: [[TMP0:%.*]] = and <8 x i8> %v1, %v2
// CHECK: [[TMP1:%.*]] = icmp ne <8 x i8> [[TMP0]], zeroinitializer
// CHECK: [[VTST_I:%.*]] = sext <8 x i1> [[TMP1]] to <8 x i8>
@@ -1803,20 +1629,18 @@ uint8x8_t test_vtst_p8(poly8x8_t v1, poly8x8_t v2) {
return vtst_p8(v1, v2);
}
-// CHECK-LABEL: define <4 x i16> @test_vtst_p16(<4 x i16> %v1, <4 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vtst_p16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %v1 to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %v2 to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[TMP4:%.*]] = and <4 x i16> [[TMP2]], [[TMP3]]
-// CHECK: [[TMP5:%.*]] = icmp ne <4 x i16> [[TMP4]], zeroinitializer
-// CHECK: [[VTST_I:%.*]] = sext <4 x i1> [[TMP5]] to <4 x i16>
+// CHECK: [[TMP2:%.*]] = and <4 x i16> %v1, %v2
+// CHECK: [[TMP3:%.*]] = icmp ne <4 x i16> [[TMP2]], zeroinitializer
+// CHECK: [[VTST_I:%.*]] = sext <4 x i1> [[TMP3]] to <4 x i16>
// CHECK: ret <4 x i16> [[VTST_I]]
uint16x4_t test_vtst_p16(poly16x4_t v1, poly16x4_t v2) {
return vtst_p16(v1, v2);
}
-// CHECK-LABEL: define <16 x i8> @test_vtstq_p8(<16 x i8> %v1, <16 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vtstq_p8(
// CHECK: [[TMP0:%.*]] = and <16 x i8> %v1, %v2
// CHECK: [[TMP1:%.*]] = icmp ne <16 x i8> [[TMP0]], zeroinitializer
// CHECK: [[VTST_I:%.*]] = sext <16 x i1> [[TMP1]] to <16 x i8>
@@ -1825,46 +1649,40 @@ uint8x16_t test_vtstq_p8(poly8x16_t v1, poly8x16_t v2) {
return vtstq_p8(v1, v2);
}
-// CHECK-LABEL: define <8 x i16> @test_vtstq_p16(<8 x i16> %v1, <8 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vtstq_p16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %v2 to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[TMP4:%.*]] = and <8 x i16> [[TMP2]], [[TMP3]]
-// CHECK: [[TMP5:%.*]] = icmp ne <8 x i16> [[TMP4]], zeroinitializer
-// CHECK: [[VTST_I:%.*]] = sext <8 x i1> [[TMP5]] to <8 x i16>
+// CHECK: [[TMP2:%.*]] = and <8 x i16> %v1, %v2
+// CHECK: [[TMP3:%.*]] = icmp ne <8 x i16> [[TMP2]], zeroinitializer
+// CHECK: [[VTST_I:%.*]] = sext <8 x i1> [[TMP3]] to <8 x i16>
// CHECK: ret <8 x i16> [[VTST_I]]
uint16x8_t test_vtstq_p16(poly16x8_t v1, poly16x8_t v2) {
return vtstq_p16(v1, v2);
}
-// CHECK-LABEL: define <1 x i64> @test_vtst_s64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vtst_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x i64>
-// CHECK: [[TMP4:%.*]] = and <1 x i64> [[TMP2]], [[TMP3]]
-// CHECK: [[TMP5:%.*]] = icmp ne <1 x i64> [[TMP4]], zeroinitializer
-// CHECK: [[VTST_I:%.*]] = sext <1 x i1> [[TMP5]] to <1 x i64>
+// CHECK: [[TMP2:%.*]] = and <1 x i64> %a, %b
+// CHECK: [[TMP3:%.*]] = icmp ne <1 x i64> [[TMP2]], zeroinitializer
+// CHECK: [[VTST_I:%.*]] = sext <1 x i1> [[TMP3]] to <1 x i64>
// CHECK: ret <1 x i64> [[VTST_I]]
uint64x1_t test_vtst_s64(int64x1_t a, int64x1_t b) {
return vtst_s64(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vtst_u64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vtst_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x i64>
-// CHECK: [[TMP4:%.*]] = and <1 x i64> [[TMP2]], [[TMP3]]
-// CHECK: [[TMP5:%.*]] = icmp ne <1 x i64> [[TMP4]], zeroinitializer
-// CHECK: [[VTST_I:%.*]] = sext <1 x i1> [[TMP5]] to <1 x i64>
+// CHECK: [[TMP2:%.*]] = and <1 x i64> %a, %b
+// CHECK: [[TMP3:%.*]] = icmp ne <1 x i64> [[TMP2]], zeroinitializer
+// CHECK: [[VTST_I:%.*]] = sext <1 x i1> [[TMP3]] to <1 x i64>
// CHECK: ret <1 x i64> [[VTST_I]]
uint64x1_t test_vtst_u64(uint64x1_t a, uint64x1_t b) {
return vtst_u64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vceq_s8(<8 x i8> %v1, <8 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vceq_s8(
// CHECK: [[CMP_I:%.*]] = icmp eq <8 x i8> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <8 x i1> [[CMP_I]] to <8 x i8>
// CHECK: ret <8 x i8> [[SEXT_I]]
@@ -1872,7 +1690,7 @@ uint8x8_t test_vceq_s8(int8x8_t v1, int8x8_t v2) {
return vceq_s8(v1, v2);
}
-// CHECK-LABEL: define <4 x i16> @test_vceq_s16(<4 x i16> %v1, <4 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vceq_s16(
// CHECK: [[CMP_I:%.*]] = icmp eq <4 x i16> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i16>
// CHECK: ret <4 x i16> [[SEXT_I]]
@@ -1880,7 +1698,7 @@ uint16x4_t test_vceq_s16(int16x4_t v1, int16x4_t v2) {
return vceq_s16(v1, v2);
}
-// CHECK-LABEL: define <2 x i32> @test_vceq_s32(<2 x i32> %v1, <2 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vceq_s32(
// CHECK: [[CMP_I:%.*]] = icmp eq <2 x i32> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <2 x i1> [[CMP_I]] to <2 x i32>
// CHECK: ret <2 x i32> [[SEXT_I]]
@@ -1888,7 +1706,7 @@ uint32x2_t test_vceq_s32(int32x2_t v1, int32x2_t v2) {
return vceq_s32(v1, v2);
}
-// CHECK-LABEL: define <1 x i64> @test_vceq_s64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vceq_s64(
// CHECK: [[CMP_I:%.*]] = icmp eq <1 x i64> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <1 x i1> [[CMP_I]] to <1 x i64>
// CHECK: ret <1 x i64> [[SEXT_I]]
@@ -1896,7 +1714,7 @@ uint64x1_t test_vceq_s64(int64x1_t a, int64x1_t b) {
return vceq_s64(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vceq_u64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vceq_u64(
// CHECK: [[CMP_I:%.*]] = icmp eq <1 x i64> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <1 x i1> [[CMP_I]] to <1 x i64>
// CHECK: ret <1 x i64> [[SEXT_I]]
@@ -1904,7 +1722,7 @@ uint64x1_t test_vceq_u64(uint64x1_t a, uint64x1_t b) {
return vceq_u64(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vceq_f32(<2 x float> %v1, <2 x float> %v2) #0 {
+// CHECK-LABEL: @test_vceq_f32(
// CHECK: [[CMP_I:%.*]] = fcmp oeq <2 x float> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <2 x i1> [[CMP_I]] to <2 x i32>
// CHECK: ret <2 x i32> [[SEXT_I]]
@@ -1912,7 +1730,7 @@ uint32x2_t test_vceq_f32(float32x2_t v1, float32x2_t v2) {
return vceq_f32(v1, v2);
}
-// CHECK-LABEL: define <1 x i64> @test_vceq_f64(<1 x double> %a, <1 x double> %b) #0 {
+// CHECK-LABEL: @test_vceq_f64(
// CHECK: [[CMP_I:%.*]] = fcmp oeq <1 x double> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <1 x i1> [[CMP_I]] to <1 x i64>
// CHECK: ret <1 x i64> [[SEXT_I]]
@@ -1920,7 +1738,7 @@ uint64x1_t test_vceq_f64(float64x1_t a, float64x1_t b) {
return vceq_f64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vceq_u8(<8 x i8> %v1, <8 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vceq_u8(
// CHECK: [[CMP_I:%.*]] = icmp eq <8 x i8> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <8 x i1> [[CMP_I]] to <8 x i8>
// CHECK: ret <8 x i8> [[SEXT_I]]
@@ -1928,7 +1746,7 @@ uint8x8_t test_vceq_u8(uint8x8_t v1, uint8x8_t v2) {
return vceq_u8(v1, v2);
}
-// CHECK-LABEL: define <4 x i16> @test_vceq_u16(<4 x i16> %v1, <4 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vceq_u16(
// CHECK: [[CMP_I:%.*]] = icmp eq <4 x i16> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i16>
// CHECK: ret <4 x i16> [[SEXT_I]]
@@ -1936,7 +1754,7 @@ uint16x4_t test_vceq_u16(uint16x4_t v1, uint16x4_t v2) {
return vceq_u16(v1, v2);
}
-// CHECK-LABEL: define <2 x i32> @test_vceq_u32(<2 x i32> %v1, <2 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vceq_u32(
// CHECK: [[CMP_I:%.*]] = icmp eq <2 x i32> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <2 x i1> [[CMP_I]] to <2 x i32>
// CHECK: ret <2 x i32> [[SEXT_I]]
@@ -1944,7 +1762,7 @@ uint32x2_t test_vceq_u32(uint32x2_t v1, uint32x2_t v2) {
return vceq_u32(v1, v2);
}
-// CHECK-LABEL: define <8 x i8> @test_vceq_p8(<8 x i8> %v1, <8 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vceq_p8(
// CHECK: [[CMP_I:%.*]] = icmp eq <8 x i8> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <8 x i1> [[CMP_I]] to <8 x i8>
// CHECK: ret <8 x i8> [[SEXT_I]]
@@ -1952,7 +1770,7 @@ uint8x8_t test_vceq_p8(poly8x8_t v1, poly8x8_t v2) {
return vceq_p8(v1, v2);
}
-// CHECK-LABEL: define <16 x i8> @test_vceqq_s8(<16 x i8> %v1, <16 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vceqq_s8(
// CHECK: [[CMP_I:%.*]] = icmp eq <16 x i8> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <16 x i1> [[CMP_I]] to <16 x i8>
// CHECK: ret <16 x i8> [[SEXT_I]]
@@ -1960,7 +1778,7 @@ uint8x16_t test_vceqq_s8(int8x16_t v1, int8x16_t v2) {
return vceqq_s8(v1, v2);
}
-// CHECK-LABEL: define <8 x i16> @test_vceqq_s16(<8 x i16> %v1, <8 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vceqq_s16(
// CHECK: [[CMP_I:%.*]] = icmp eq <8 x i16> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <8 x i1> [[CMP_I]] to <8 x i16>
// CHECK: ret <8 x i16> [[SEXT_I]]
@@ -1968,7 +1786,7 @@ uint16x8_t test_vceqq_s16(int16x8_t v1, int16x8_t v2) {
return vceqq_s16(v1, v2);
}
-// CHECK-LABEL: define <4 x i32> @test_vceqq_s32(<4 x i32> %v1, <4 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vceqq_s32(
// CHECK: [[CMP_I:%.*]] = icmp eq <4 x i32> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i32>
// CHECK: ret <4 x i32> [[SEXT_I]]
@@ -1976,7 +1794,7 @@ uint32x4_t test_vceqq_s32(int32x4_t v1, int32x4_t v2) {
return vceqq_s32(v1, v2);
}
-// CHECK-LABEL: define <4 x i32> @test_vceqq_f32(<4 x float> %v1, <4 x float> %v2) #0 {
+// CHECK-LABEL: @test_vceqq_f32(
// CHECK: [[CMP_I:%.*]] = fcmp oeq <4 x float> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i32>
// CHECK: ret <4 x i32> [[SEXT_I]]
@@ -1984,7 +1802,7 @@ uint32x4_t test_vceqq_f32(float32x4_t v1, float32x4_t v2) {
return vceqq_f32(v1, v2);
}
-// CHECK-LABEL: define <16 x i8> @test_vceqq_u8(<16 x i8> %v1, <16 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vceqq_u8(
// CHECK: [[CMP_I:%.*]] = icmp eq <16 x i8> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <16 x i1> [[CMP_I]] to <16 x i8>
// CHECK: ret <16 x i8> [[SEXT_I]]
@@ -1992,7 +1810,7 @@ uint8x16_t test_vceqq_u8(uint8x16_t v1, uint8x16_t v2) {
return vceqq_u8(v1, v2);
}
-// CHECK-LABEL: define <8 x i16> @test_vceqq_u16(<8 x i16> %v1, <8 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vceqq_u16(
// CHECK: [[CMP_I:%.*]] = icmp eq <8 x i16> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <8 x i1> [[CMP_I]] to <8 x i16>
// CHECK: ret <8 x i16> [[SEXT_I]]
@@ -2000,7 +1818,7 @@ uint16x8_t test_vceqq_u16(uint16x8_t v1, uint16x8_t v2) {
return vceqq_u16(v1, v2);
}
-// CHECK-LABEL: define <4 x i32> @test_vceqq_u32(<4 x i32> %v1, <4 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vceqq_u32(
// CHECK: [[CMP_I:%.*]] = icmp eq <4 x i32> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i32>
// CHECK: ret <4 x i32> [[SEXT_I]]
@@ -2008,7 +1826,7 @@ uint32x4_t test_vceqq_u32(uint32x4_t v1, uint32x4_t v2) {
return vceqq_u32(v1, v2);
}
-// CHECK-LABEL: define <16 x i8> @test_vceqq_p8(<16 x i8> %v1, <16 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vceqq_p8(
// CHECK: [[CMP_I:%.*]] = icmp eq <16 x i8> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <16 x i1> [[CMP_I]] to <16 x i8>
// CHECK: ret <16 x i8> [[SEXT_I]]
@@ -2016,8 +1834,7 @@ uint8x16_t test_vceqq_p8(poly8x16_t v1, poly8x16_t v2) {
return vceqq_p8(v1, v2);
}
-
-// CHECK-LABEL: define <2 x i64> @test_vceqq_s64(<2 x i64> %v1, <2 x i64> %v2) #0 {
+// CHECK-LABEL: @test_vceqq_s64(
// CHECK: [[CMP_I:%.*]] = icmp eq <2 x i64> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <2 x i1> [[CMP_I]] to <2 x i64>
// CHECK: ret <2 x i64> [[SEXT_I]]
@@ -2025,7 +1842,7 @@ uint64x2_t test_vceqq_s64(int64x2_t v1, int64x2_t v2) {
return vceqq_s64(v1, v2);
}
-// CHECK-LABEL: define <2 x i64> @test_vceqq_u64(<2 x i64> %v1, <2 x i64> %v2) #0 {
+// CHECK-LABEL: @test_vceqq_u64(
// CHECK: [[CMP_I:%.*]] = icmp eq <2 x i64> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <2 x i1> [[CMP_I]] to <2 x i64>
// CHECK: ret <2 x i64> [[SEXT_I]]
@@ -2033,14 +1850,15 @@ uint64x2_t test_vceqq_u64(uint64x2_t v1, uint64x2_t v2) {
return vceqq_u64(v1, v2);
}
-// CHECK-LABEL: define <2 x i64> @test_vceqq_f64(<2 x double> %v1, <2 x double> %v2) #0 {
+// CHECK-LABEL: @test_vceqq_f64(
// CHECK: [[CMP_I:%.*]] = fcmp oeq <2 x double> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <2 x i1> [[CMP_I]] to <2 x i64>
// CHECK: ret <2 x i64> [[SEXT_I]]
uint64x2_t test_vceqq_f64(float64x2_t v1, float64x2_t v2) {
return vceqq_f64(v1, v2);
}
-// CHECK-LABEL: define <8 x i8> @test_vcge_s8(<8 x i8> %v1, <8 x i8> %v2) #0 {
+
+// CHECK-LABEL: @test_vcge_s8(
// CHECK: [[CMP_I:%.*]] = icmp sge <8 x i8> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <8 x i1> [[CMP_I]] to <8 x i8>
// CHECK: ret <8 x i8> [[SEXT_I]]
@@ -2048,7 +1866,7 @@ uint8x8_t test_vcge_s8(int8x8_t v1, int8x8_t v2) {
return vcge_s8(v1, v2);
}
-// CHECK-LABEL: define <4 x i16> @test_vcge_s16(<4 x i16> %v1, <4 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vcge_s16(
// CHECK: [[CMP_I:%.*]] = icmp sge <4 x i16> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i16>
// CHECK: ret <4 x i16> [[SEXT_I]]
@@ -2056,7 +1874,7 @@ uint16x4_t test_vcge_s16(int16x4_t v1, int16x4_t v2) {
return vcge_s16(v1, v2);
}
-// CHECK-LABEL: define <2 x i32> @test_vcge_s32(<2 x i32> %v1, <2 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vcge_s32(
// CHECK: [[CMP_I:%.*]] = icmp sge <2 x i32> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <2 x i1> [[CMP_I]] to <2 x i32>
// CHECK: ret <2 x i32> [[SEXT_I]]
@@ -2064,7 +1882,7 @@ uint32x2_t test_vcge_s32(int32x2_t v1, int32x2_t v2) {
return vcge_s32(v1, v2);
}
-// CHECK-LABEL: define <1 x i64> @test_vcge_s64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vcge_s64(
// CHECK: [[CMP_I:%.*]] = icmp sge <1 x i64> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <1 x i1> [[CMP_I]] to <1 x i64>
// CHECK: ret <1 x i64> [[SEXT_I]]
@@ -2072,7 +1890,7 @@ uint64x1_t test_vcge_s64(int64x1_t a, int64x1_t b) {
return vcge_s64(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vcge_u64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vcge_u64(
// CHECK: [[CMP_I:%.*]] = icmp uge <1 x i64> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <1 x i1> [[CMP_I]] to <1 x i64>
// CHECK: ret <1 x i64> [[SEXT_I]]
@@ -2080,7 +1898,7 @@ uint64x1_t test_vcge_u64(uint64x1_t a, uint64x1_t b) {
return vcge_u64(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vcge_f32(<2 x float> %v1, <2 x float> %v2) #0 {
+// CHECK-LABEL: @test_vcge_f32(
// CHECK: [[CMP_I:%.*]] = fcmp oge <2 x float> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <2 x i1> [[CMP_I]] to <2 x i32>
// CHECK: ret <2 x i32> [[SEXT_I]]
@@ -2088,7 +1906,7 @@ uint32x2_t test_vcge_f32(float32x2_t v1, float32x2_t v2) {
return vcge_f32(v1, v2);
}
-// CHECK-LABEL: define <1 x i64> @test_vcge_f64(<1 x double> %a, <1 x double> %b) #0 {
+// CHECK-LABEL: @test_vcge_f64(
// CHECK: [[CMP_I:%.*]] = fcmp oge <1 x double> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <1 x i1> [[CMP_I]] to <1 x i64>
// CHECK: ret <1 x i64> [[SEXT_I]]
@@ -2096,7 +1914,7 @@ uint64x1_t test_vcge_f64(float64x1_t a, float64x1_t b) {
return vcge_f64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vcge_u8(<8 x i8> %v1, <8 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vcge_u8(
// CHECK: [[CMP_I:%.*]] = icmp uge <8 x i8> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <8 x i1> [[CMP_I]] to <8 x i8>
// CHECK: ret <8 x i8> [[SEXT_I]]
@@ -2104,7 +1922,7 @@ uint8x8_t test_vcge_u8(uint8x8_t v1, uint8x8_t v2) {
return vcge_u8(v1, v2);
}
-// CHECK-LABEL: define <4 x i16> @test_vcge_u16(<4 x i16> %v1, <4 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vcge_u16(
// CHECK: [[CMP_I:%.*]] = icmp uge <4 x i16> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i16>
// CHECK: ret <4 x i16> [[SEXT_I]]
@@ -2112,7 +1930,7 @@ uint16x4_t test_vcge_u16(uint16x4_t v1, uint16x4_t v2) {
return vcge_u16(v1, v2);
}
-// CHECK-LABEL: define <2 x i32> @test_vcge_u32(<2 x i32> %v1, <2 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vcge_u32(
// CHECK: [[CMP_I:%.*]] = icmp uge <2 x i32> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <2 x i1> [[CMP_I]] to <2 x i32>
// CHECK: ret <2 x i32> [[SEXT_I]]
@@ -2120,7 +1938,7 @@ uint32x2_t test_vcge_u32(uint32x2_t v1, uint32x2_t v2) {
return vcge_u32(v1, v2);
}
-// CHECK-LABEL: define <16 x i8> @test_vcgeq_s8(<16 x i8> %v1, <16 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vcgeq_s8(
// CHECK: [[CMP_I:%.*]] = icmp sge <16 x i8> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <16 x i1> [[CMP_I]] to <16 x i8>
// CHECK: ret <16 x i8> [[SEXT_I]]
@@ -2128,7 +1946,7 @@ uint8x16_t test_vcgeq_s8(int8x16_t v1, int8x16_t v2) {
return vcgeq_s8(v1, v2);
}
-// CHECK-LABEL: define <8 x i16> @test_vcgeq_s16(<8 x i16> %v1, <8 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vcgeq_s16(
// CHECK: [[CMP_I:%.*]] = icmp sge <8 x i16> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <8 x i1> [[CMP_I]] to <8 x i16>
// CHECK: ret <8 x i16> [[SEXT_I]]
@@ -2136,7 +1954,7 @@ uint16x8_t test_vcgeq_s16(int16x8_t v1, int16x8_t v2) {
return vcgeq_s16(v1, v2);
}
-// CHECK-LABEL: define <4 x i32> @test_vcgeq_s32(<4 x i32> %v1, <4 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vcgeq_s32(
// CHECK: [[CMP_I:%.*]] = icmp sge <4 x i32> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i32>
// CHECK: ret <4 x i32> [[SEXT_I]]
@@ -2144,7 +1962,7 @@ uint32x4_t test_vcgeq_s32(int32x4_t v1, int32x4_t v2) {
return vcgeq_s32(v1, v2);
}
-// CHECK-LABEL: define <4 x i32> @test_vcgeq_f32(<4 x float> %v1, <4 x float> %v2) #0 {
+// CHECK-LABEL: @test_vcgeq_f32(
// CHECK: [[CMP_I:%.*]] = fcmp oge <4 x float> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i32>
// CHECK: ret <4 x i32> [[SEXT_I]]
@@ -2152,7 +1970,7 @@ uint32x4_t test_vcgeq_f32(float32x4_t v1, float32x4_t v2) {
return vcgeq_f32(v1, v2);
}
-// CHECK-LABEL: define <16 x i8> @test_vcgeq_u8(<16 x i8> %v1, <16 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vcgeq_u8(
// CHECK: [[CMP_I:%.*]] = icmp uge <16 x i8> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <16 x i1> [[CMP_I]] to <16 x i8>
// CHECK: ret <16 x i8> [[SEXT_I]]
@@ -2160,7 +1978,7 @@ uint8x16_t test_vcgeq_u8(uint8x16_t v1, uint8x16_t v2) {
return vcgeq_u8(v1, v2);
}
-// CHECK-LABEL: define <8 x i16> @test_vcgeq_u16(<8 x i16> %v1, <8 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vcgeq_u16(
// CHECK: [[CMP_I:%.*]] = icmp uge <8 x i16> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <8 x i1> [[CMP_I]] to <8 x i16>
// CHECK: ret <8 x i16> [[SEXT_I]]
@@ -2168,7 +1986,7 @@ uint16x8_t test_vcgeq_u16(uint16x8_t v1, uint16x8_t v2) {
return vcgeq_u16(v1, v2);
}
-// CHECK-LABEL: define <4 x i32> @test_vcgeq_u32(<4 x i32> %v1, <4 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vcgeq_u32(
// CHECK: [[CMP_I:%.*]] = icmp uge <4 x i32> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i32>
// CHECK: ret <4 x i32> [[SEXT_I]]
@@ -2176,7 +1994,7 @@ uint32x4_t test_vcgeq_u32(uint32x4_t v1, uint32x4_t v2) {
return vcgeq_u32(v1, v2);
}
-// CHECK-LABEL: define <2 x i64> @test_vcgeq_s64(<2 x i64> %v1, <2 x i64> %v2) #0 {
+// CHECK-LABEL: @test_vcgeq_s64(
// CHECK: [[CMP_I:%.*]] = icmp sge <2 x i64> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <2 x i1> [[CMP_I]] to <2 x i64>
// CHECK: ret <2 x i64> [[SEXT_I]]
@@ -2184,7 +2002,7 @@ uint64x2_t test_vcgeq_s64(int64x2_t v1, int64x2_t v2) {
return vcgeq_s64(v1, v2);
}
-// CHECK-LABEL: define <2 x i64> @test_vcgeq_u64(<2 x i64> %v1, <2 x i64> %v2) #0 {
+// CHECK-LABEL: @test_vcgeq_u64(
// CHECK: [[CMP_I:%.*]] = icmp uge <2 x i64> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <2 x i1> [[CMP_I]] to <2 x i64>
// CHECK: ret <2 x i64> [[SEXT_I]]
@@ -2192,7 +2010,7 @@ uint64x2_t test_vcgeq_u64(uint64x2_t v1, uint64x2_t v2) {
return vcgeq_u64(v1, v2);
}
-// CHECK-LABEL: define <2 x i64> @test_vcgeq_f64(<2 x double> %v1, <2 x double> %v2) #0 {
+// CHECK-LABEL: @test_vcgeq_f64(
// CHECK: [[CMP_I:%.*]] = fcmp oge <2 x double> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <2 x i1> [[CMP_I]] to <2 x i64>
// CHECK: ret <2 x i64> [[SEXT_I]]
@@ -2200,18 +2018,18 @@ uint64x2_t test_vcgeq_f64(float64x2_t v1, float64x2_t v2) {
return vcgeq_f64(v1, v2);
}
-// Notes about vcle:
-// LE condition predicate implemented as GE, so check reversed operands.
-// Using registers other than v0, v1 are possible, but would be odd.
-// CHECK-LABEL: define <8 x i8> @test_vcle_s8(<8 x i8> %v1, <8 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vcle_s8(
// CHECK: [[CMP_I:%.*]] = icmp sle <8 x i8> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <8 x i1> [[CMP_I]] to <8 x i8>
// CHECK: ret <8 x i8> [[SEXT_I]]
+// Notes about vcle:
+// LE condition predicate implemented as GE, so check reversed operands.
+// Using registers other than v0, v1 are possible, but would be odd.
uint8x8_t test_vcle_s8(int8x8_t v1, int8x8_t v2) {
return vcle_s8(v1, v2);
}
-// CHECK-LABEL: define <4 x i16> @test_vcle_s16(<4 x i16> %v1, <4 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vcle_s16(
// CHECK: [[CMP_I:%.*]] = icmp sle <4 x i16> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i16>
// CHECK: ret <4 x i16> [[SEXT_I]]
@@ -2219,7 +2037,7 @@ uint16x4_t test_vcle_s16(int16x4_t v1, int16x4_t v2) {
return vcle_s16(v1, v2);
}
-// CHECK-LABEL: define <2 x i32> @test_vcle_s32(<2 x i32> %v1, <2 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vcle_s32(
// CHECK: [[CMP_I:%.*]] = icmp sle <2 x i32> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <2 x i1> [[CMP_I]] to <2 x i32>
// CHECK: ret <2 x i32> [[SEXT_I]]
@@ -2227,7 +2045,7 @@ uint32x2_t test_vcle_s32(int32x2_t v1, int32x2_t v2) {
return vcle_s32(v1, v2);
}
-// CHECK-LABEL: define <1 x i64> @test_vcle_s64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vcle_s64(
// CHECK: [[CMP_I:%.*]] = icmp sle <1 x i64> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <1 x i1> [[CMP_I]] to <1 x i64>
// CHECK: ret <1 x i64> [[SEXT_I]]
@@ -2235,7 +2053,7 @@ uint64x1_t test_vcle_s64(int64x1_t a, int64x1_t b) {
return vcle_s64(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vcle_u64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vcle_u64(
// CHECK: [[CMP_I:%.*]] = icmp ule <1 x i64> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <1 x i1> [[CMP_I]] to <1 x i64>
// CHECK: ret <1 x i64> [[SEXT_I]]
@@ -2243,7 +2061,7 @@ uint64x1_t test_vcle_u64(uint64x1_t a, uint64x1_t b) {
return vcle_u64(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vcle_f32(<2 x float> %v1, <2 x float> %v2) #0 {
+// CHECK-LABEL: @test_vcle_f32(
// CHECK: [[CMP_I:%.*]] = fcmp ole <2 x float> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <2 x i1> [[CMP_I]] to <2 x i32>
// CHECK: ret <2 x i32> [[SEXT_I]]
@@ -2251,7 +2069,7 @@ uint32x2_t test_vcle_f32(float32x2_t v1, float32x2_t v2) {
return vcle_f32(v1, v2);
}
-// CHECK-LABEL: define <1 x i64> @test_vcle_f64(<1 x double> %a, <1 x double> %b) #0 {
+// CHECK-LABEL: @test_vcle_f64(
// CHECK: [[CMP_I:%.*]] = fcmp ole <1 x double> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <1 x i1> [[CMP_I]] to <1 x i64>
// CHECK: ret <1 x i64> [[SEXT_I]]
@@ -2259,7 +2077,7 @@ uint64x1_t test_vcle_f64(float64x1_t a, float64x1_t b) {
return vcle_f64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vcle_u8(<8 x i8> %v1, <8 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vcle_u8(
// CHECK: [[CMP_I:%.*]] = icmp ule <8 x i8> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <8 x i1> [[CMP_I]] to <8 x i8>
// CHECK: ret <8 x i8> [[SEXT_I]]
@@ -2267,7 +2085,7 @@ uint8x8_t test_vcle_u8(uint8x8_t v1, uint8x8_t v2) {
return vcle_u8(v1, v2);
}
-// CHECK-LABEL: define <4 x i16> @test_vcle_u16(<4 x i16> %v1, <4 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vcle_u16(
// CHECK: [[CMP_I:%.*]] = icmp ule <4 x i16> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i16>
// CHECK: ret <4 x i16> [[SEXT_I]]
@@ -2275,7 +2093,7 @@ uint16x4_t test_vcle_u16(uint16x4_t v1, uint16x4_t v2) {
return vcle_u16(v1, v2);
}
-// CHECK-LABEL: define <2 x i32> @test_vcle_u32(<2 x i32> %v1, <2 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vcle_u32(
// CHECK: [[CMP_I:%.*]] = icmp ule <2 x i32> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <2 x i1> [[CMP_I]] to <2 x i32>
// CHECK: ret <2 x i32> [[SEXT_I]]
@@ -2283,7 +2101,7 @@ uint32x2_t test_vcle_u32(uint32x2_t v1, uint32x2_t v2) {
return vcle_u32(v1, v2);
}
-// CHECK-LABEL: define <16 x i8> @test_vcleq_s8(<16 x i8> %v1, <16 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vcleq_s8(
// CHECK: [[CMP_I:%.*]] = icmp sle <16 x i8> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <16 x i1> [[CMP_I]] to <16 x i8>
// CHECK: ret <16 x i8> [[SEXT_I]]
@@ -2291,7 +2109,7 @@ uint8x16_t test_vcleq_s8(int8x16_t v1, int8x16_t v2) {
return vcleq_s8(v1, v2);
}
-// CHECK-LABEL: define <8 x i16> @test_vcleq_s16(<8 x i16> %v1, <8 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vcleq_s16(
// CHECK: [[CMP_I:%.*]] = icmp sle <8 x i16> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <8 x i1> [[CMP_I]] to <8 x i16>
// CHECK: ret <8 x i16> [[SEXT_I]]
@@ -2299,7 +2117,7 @@ uint16x8_t test_vcleq_s16(int16x8_t v1, int16x8_t v2) {
return vcleq_s16(v1, v2);
}
-// CHECK-LABEL: define <4 x i32> @test_vcleq_s32(<4 x i32> %v1, <4 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vcleq_s32(
// CHECK: [[CMP_I:%.*]] = icmp sle <4 x i32> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i32>
// CHECK: ret <4 x i32> [[SEXT_I]]
@@ -2307,7 +2125,7 @@ uint32x4_t test_vcleq_s32(int32x4_t v1, int32x4_t v2) {
return vcleq_s32(v1, v2);
}
-// CHECK-LABEL: define <4 x i32> @test_vcleq_f32(<4 x float> %v1, <4 x float> %v2) #0 {
+// CHECK-LABEL: @test_vcleq_f32(
// CHECK: [[CMP_I:%.*]] = fcmp ole <4 x float> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i32>
// CHECK: ret <4 x i32> [[SEXT_I]]
@@ -2315,7 +2133,7 @@ uint32x4_t test_vcleq_f32(float32x4_t v1, float32x4_t v2) {
return vcleq_f32(v1, v2);
}
-// CHECK-LABEL: define <16 x i8> @test_vcleq_u8(<16 x i8> %v1, <16 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vcleq_u8(
// CHECK: [[CMP_I:%.*]] = icmp ule <16 x i8> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <16 x i1> [[CMP_I]] to <16 x i8>
// CHECK: ret <16 x i8> [[SEXT_I]]
@@ -2323,7 +2141,7 @@ uint8x16_t test_vcleq_u8(uint8x16_t v1, uint8x16_t v2) {
return vcleq_u8(v1, v2);
}
-// CHECK-LABEL: define <8 x i16> @test_vcleq_u16(<8 x i16> %v1, <8 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vcleq_u16(
// CHECK: [[CMP_I:%.*]] = icmp ule <8 x i16> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <8 x i1> [[CMP_I]] to <8 x i16>
// CHECK: ret <8 x i16> [[SEXT_I]]
@@ -2331,7 +2149,7 @@ uint16x8_t test_vcleq_u16(uint16x8_t v1, uint16x8_t v2) {
return vcleq_u16(v1, v2);
}
-// CHECK-LABEL: define <4 x i32> @test_vcleq_u32(<4 x i32> %v1, <4 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vcleq_u32(
// CHECK: [[CMP_I:%.*]] = icmp ule <4 x i32> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i32>
// CHECK: ret <4 x i32> [[SEXT_I]]
@@ -2339,7 +2157,7 @@ uint32x4_t test_vcleq_u32(uint32x4_t v1, uint32x4_t v2) {
return vcleq_u32(v1, v2);
}
-// CHECK-LABEL: define <2 x i64> @test_vcleq_s64(<2 x i64> %v1, <2 x i64> %v2) #0 {
+// CHECK-LABEL: @test_vcleq_s64(
// CHECK: [[CMP_I:%.*]] = icmp sle <2 x i64> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <2 x i1> [[CMP_I]] to <2 x i64>
// CHECK: ret <2 x i64> [[SEXT_I]]
@@ -2347,7 +2165,7 @@ uint64x2_t test_vcleq_s64(int64x2_t v1, int64x2_t v2) {
return vcleq_s64(v1, v2);
}
-// CHECK-LABEL: define <2 x i64> @test_vcleq_u64(<2 x i64> %v1, <2 x i64> %v2) #0 {
+// CHECK-LABEL: @test_vcleq_u64(
// CHECK: [[CMP_I:%.*]] = icmp ule <2 x i64> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <2 x i1> [[CMP_I]] to <2 x i64>
// CHECK: ret <2 x i64> [[SEXT_I]]
@@ -2355,7 +2173,7 @@ uint64x2_t test_vcleq_u64(uint64x2_t v1, uint64x2_t v2) {
return vcleq_u64(v1, v2);
}
-// CHECK-LABEL: define <2 x i64> @test_vcleq_f64(<2 x double> %v1, <2 x double> %v2) #0 {
+// CHECK-LABEL: @test_vcleq_f64(
// CHECK: [[CMP_I:%.*]] = fcmp ole <2 x double> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <2 x i1> [[CMP_I]] to <2 x i64>
// CHECK: ret <2 x i64> [[SEXT_I]]
@@ -2363,8 +2181,7 @@ uint64x2_t test_vcleq_f64(float64x2_t v1, float64x2_t v2) {
return vcleq_f64(v1, v2);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vcgt_s8(<8 x i8> %v1, <8 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vcgt_s8(
// CHECK: [[CMP_I:%.*]] = icmp sgt <8 x i8> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <8 x i1> [[CMP_I]] to <8 x i8>
// CHECK: ret <8 x i8> [[SEXT_I]]
@@ -2372,7 +2189,7 @@ uint8x8_t test_vcgt_s8(int8x8_t v1, int8x8_t v2) {
return vcgt_s8(v1, v2);
}
-// CHECK-LABEL: define <4 x i16> @test_vcgt_s16(<4 x i16> %v1, <4 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vcgt_s16(
// CHECK: [[CMP_I:%.*]] = icmp sgt <4 x i16> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i16>
// CHECK: ret <4 x i16> [[SEXT_I]]
@@ -2380,7 +2197,7 @@ uint16x4_t test_vcgt_s16(int16x4_t v1, int16x4_t v2) {
return vcgt_s16(v1, v2);
}
-// CHECK-LABEL: define <2 x i32> @test_vcgt_s32(<2 x i32> %v1, <2 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vcgt_s32(
// CHECK: [[CMP_I:%.*]] = icmp sgt <2 x i32> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <2 x i1> [[CMP_I]] to <2 x i32>
// CHECK: ret <2 x i32> [[SEXT_I]]
@@ -2388,7 +2205,7 @@ uint32x2_t test_vcgt_s32(int32x2_t v1, int32x2_t v2) {
return vcgt_s32(v1, v2);
}
-// CHECK-LABEL: define <1 x i64> @test_vcgt_s64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vcgt_s64(
// CHECK: [[CMP_I:%.*]] = icmp sgt <1 x i64> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <1 x i1> [[CMP_I]] to <1 x i64>
// CHECK: ret <1 x i64> [[SEXT_I]]
@@ -2396,7 +2213,7 @@ uint64x1_t test_vcgt_s64(int64x1_t a, int64x1_t b) {
return vcgt_s64(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vcgt_u64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vcgt_u64(
// CHECK: [[CMP_I:%.*]] = icmp ugt <1 x i64> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <1 x i1> [[CMP_I]] to <1 x i64>
// CHECK: ret <1 x i64> [[SEXT_I]]
@@ -2404,7 +2221,7 @@ uint64x1_t test_vcgt_u64(uint64x1_t a, uint64x1_t b) {
return vcgt_u64(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vcgt_f32(<2 x float> %v1, <2 x float> %v2) #0 {
+// CHECK-LABEL: @test_vcgt_f32(
// CHECK: [[CMP_I:%.*]] = fcmp ogt <2 x float> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <2 x i1> [[CMP_I]] to <2 x i32>
// CHECK: ret <2 x i32> [[SEXT_I]]
@@ -2412,7 +2229,7 @@ uint32x2_t test_vcgt_f32(float32x2_t v1, float32x2_t v2) {
return vcgt_f32(v1, v2);
}
-// CHECK-LABEL: define <1 x i64> @test_vcgt_f64(<1 x double> %a, <1 x double> %b) #0 {
+// CHECK-LABEL: @test_vcgt_f64(
// CHECK: [[CMP_I:%.*]] = fcmp ogt <1 x double> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <1 x i1> [[CMP_I]] to <1 x i64>
// CHECK: ret <1 x i64> [[SEXT_I]]
@@ -2420,7 +2237,7 @@ uint64x1_t test_vcgt_f64(float64x1_t a, float64x1_t b) {
return vcgt_f64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vcgt_u8(<8 x i8> %v1, <8 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vcgt_u8(
// CHECK: [[CMP_I:%.*]] = icmp ugt <8 x i8> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <8 x i1> [[CMP_I]] to <8 x i8>
// CHECK: ret <8 x i8> [[SEXT_I]]
@@ -2428,7 +2245,7 @@ uint8x8_t test_vcgt_u8(uint8x8_t v1, uint8x8_t v2) {
return vcgt_u8(v1, v2);
}
-// CHECK-LABEL: define <4 x i16> @test_vcgt_u16(<4 x i16> %v1, <4 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vcgt_u16(
// CHECK: [[CMP_I:%.*]] = icmp ugt <4 x i16> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i16>
// CHECK: ret <4 x i16> [[SEXT_I]]
@@ -2436,7 +2253,7 @@ uint16x4_t test_vcgt_u16(uint16x4_t v1, uint16x4_t v2) {
return vcgt_u16(v1, v2);
}
-// CHECK-LABEL: define <2 x i32> @test_vcgt_u32(<2 x i32> %v1, <2 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vcgt_u32(
// CHECK: [[CMP_I:%.*]] = icmp ugt <2 x i32> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <2 x i1> [[CMP_I]] to <2 x i32>
// CHECK: ret <2 x i32> [[SEXT_I]]
@@ -2444,7 +2261,7 @@ uint32x2_t test_vcgt_u32(uint32x2_t v1, uint32x2_t v2) {
return vcgt_u32(v1, v2);
}
-// CHECK-LABEL: define <16 x i8> @test_vcgtq_s8(<16 x i8> %v1, <16 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vcgtq_s8(
// CHECK: [[CMP_I:%.*]] = icmp sgt <16 x i8> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <16 x i1> [[CMP_I]] to <16 x i8>
// CHECK: ret <16 x i8> [[SEXT_I]]
@@ -2452,7 +2269,7 @@ uint8x16_t test_vcgtq_s8(int8x16_t v1, int8x16_t v2) {
return vcgtq_s8(v1, v2);
}
-// CHECK-LABEL: define <8 x i16> @test_vcgtq_s16(<8 x i16> %v1, <8 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vcgtq_s16(
// CHECK: [[CMP_I:%.*]] = icmp sgt <8 x i16> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <8 x i1> [[CMP_I]] to <8 x i16>
// CHECK: ret <8 x i16> [[SEXT_I]]
@@ -2460,7 +2277,7 @@ uint16x8_t test_vcgtq_s16(int16x8_t v1, int16x8_t v2) {
return vcgtq_s16(v1, v2);
}
-// CHECK-LABEL: define <4 x i32> @test_vcgtq_s32(<4 x i32> %v1, <4 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vcgtq_s32(
// CHECK: [[CMP_I:%.*]] = icmp sgt <4 x i32> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i32>
// CHECK: ret <4 x i32> [[SEXT_I]]
@@ -2468,7 +2285,7 @@ uint32x4_t test_vcgtq_s32(int32x4_t v1, int32x4_t v2) {
return vcgtq_s32(v1, v2);
}
-// CHECK-LABEL: define <4 x i32> @test_vcgtq_f32(<4 x float> %v1, <4 x float> %v2) #0 {
+// CHECK-LABEL: @test_vcgtq_f32(
// CHECK: [[CMP_I:%.*]] = fcmp ogt <4 x float> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i32>
// CHECK: ret <4 x i32> [[SEXT_I]]
@@ -2476,7 +2293,7 @@ uint32x4_t test_vcgtq_f32(float32x4_t v1, float32x4_t v2) {
return vcgtq_f32(v1, v2);
}
-// CHECK-LABEL: define <16 x i8> @test_vcgtq_u8(<16 x i8> %v1, <16 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vcgtq_u8(
// CHECK: [[CMP_I:%.*]] = icmp ugt <16 x i8> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <16 x i1> [[CMP_I]] to <16 x i8>
// CHECK: ret <16 x i8> [[SEXT_I]]
@@ -2484,7 +2301,7 @@ uint8x16_t test_vcgtq_u8(uint8x16_t v1, uint8x16_t v2) {
return vcgtq_u8(v1, v2);
}
-// CHECK-LABEL: define <8 x i16> @test_vcgtq_u16(<8 x i16> %v1, <8 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vcgtq_u16(
// CHECK: [[CMP_I:%.*]] = icmp ugt <8 x i16> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <8 x i1> [[CMP_I]] to <8 x i16>
// CHECK: ret <8 x i16> [[SEXT_I]]
@@ -2492,7 +2309,7 @@ uint16x8_t test_vcgtq_u16(uint16x8_t v1, uint16x8_t v2) {
return vcgtq_u16(v1, v2);
}
-// CHECK-LABEL: define <4 x i32> @test_vcgtq_u32(<4 x i32> %v1, <4 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vcgtq_u32(
// CHECK: [[CMP_I:%.*]] = icmp ugt <4 x i32> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i32>
// CHECK: ret <4 x i32> [[SEXT_I]]
@@ -2500,7 +2317,7 @@ uint32x4_t test_vcgtq_u32(uint32x4_t v1, uint32x4_t v2) {
return vcgtq_u32(v1, v2);
}
-// CHECK-LABEL: define <2 x i64> @test_vcgtq_s64(<2 x i64> %v1, <2 x i64> %v2) #0 {
+// CHECK-LABEL: @test_vcgtq_s64(
// CHECK: [[CMP_I:%.*]] = icmp sgt <2 x i64> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <2 x i1> [[CMP_I]] to <2 x i64>
// CHECK: ret <2 x i64> [[SEXT_I]]
@@ -2508,7 +2325,7 @@ uint64x2_t test_vcgtq_s64(int64x2_t v1, int64x2_t v2) {
return vcgtq_s64(v1, v2);
}
-// CHECK-LABEL: define <2 x i64> @test_vcgtq_u64(<2 x i64> %v1, <2 x i64> %v2) #0 {
+// CHECK-LABEL: @test_vcgtq_u64(
// CHECK: [[CMP_I:%.*]] = icmp ugt <2 x i64> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <2 x i1> [[CMP_I]] to <2 x i64>
// CHECK: ret <2 x i64> [[SEXT_I]]
@@ -2516,7 +2333,7 @@ uint64x2_t test_vcgtq_u64(uint64x2_t v1, uint64x2_t v2) {
return vcgtq_u64(v1, v2);
}
-// CHECK-LABEL: define <2 x i64> @test_vcgtq_f64(<2 x double> %v1, <2 x double> %v2) #0 {
+// CHECK-LABEL: @test_vcgtq_f64(
// CHECK: [[CMP_I:%.*]] = fcmp ogt <2 x double> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <2 x i1> [[CMP_I]] to <2 x i64>
// CHECK: ret <2 x i64> [[SEXT_I]]
@@ -2524,20 +2341,18 @@ uint64x2_t test_vcgtq_f64(float64x2_t v1, float64x2_t v2) {
return vcgtq_f64(v1, v2);
}
-
-// Notes about vclt:
-// LT condition predicate implemented as GT, so check reversed operands.
-// Using registers other than v0, v1 are possible, but would be odd.
-
-// CHECK-LABEL: define <8 x i8> @test_vclt_s8(<8 x i8> %v1, <8 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vclt_s8(
// CHECK: [[CMP_I:%.*]] = icmp slt <8 x i8> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <8 x i1> [[CMP_I]] to <8 x i8>
// CHECK: ret <8 x i8> [[SEXT_I]]
+// Notes about vclt:
+// LT condition predicate implemented as GT, so check reversed operands.
+// Using registers other than v0, v1 are possible, but would be odd.
uint8x8_t test_vclt_s8(int8x8_t v1, int8x8_t v2) {
return vclt_s8(v1, v2);
}
-// CHECK-LABEL: define <4 x i16> @test_vclt_s16(<4 x i16> %v1, <4 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vclt_s16(
// CHECK: [[CMP_I:%.*]] = icmp slt <4 x i16> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i16>
// CHECK: ret <4 x i16> [[SEXT_I]]
@@ -2545,7 +2360,7 @@ uint16x4_t test_vclt_s16(int16x4_t v1, int16x4_t v2) {
return vclt_s16(v1, v2);
}
-// CHECK-LABEL: define <2 x i32> @test_vclt_s32(<2 x i32> %v1, <2 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vclt_s32(
// CHECK: [[CMP_I:%.*]] = icmp slt <2 x i32> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <2 x i1> [[CMP_I]] to <2 x i32>
// CHECK: ret <2 x i32> [[SEXT_I]]
@@ -2553,7 +2368,7 @@ uint32x2_t test_vclt_s32(int32x2_t v1, int32x2_t v2) {
return vclt_s32(v1, v2);
}
-// CHECK-LABEL: define <1 x i64> @test_vclt_s64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vclt_s64(
// CHECK: [[CMP_I:%.*]] = icmp slt <1 x i64> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <1 x i1> [[CMP_I]] to <1 x i64>
// CHECK: ret <1 x i64> [[SEXT_I]]
@@ -2561,7 +2376,7 @@ uint64x1_t test_vclt_s64(int64x1_t a, int64x1_t b) {
return vclt_s64(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vclt_u64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vclt_u64(
// CHECK: [[CMP_I:%.*]] = icmp ult <1 x i64> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <1 x i1> [[CMP_I]] to <1 x i64>
// CHECK: ret <1 x i64> [[SEXT_I]]
@@ -2569,7 +2384,7 @@ uint64x1_t test_vclt_u64(uint64x1_t a, uint64x1_t b) {
return vclt_u64(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vclt_f32(<2 x float> %v1, <2 x float> %v2) #0 {
+// CHECK-LABEL: @test_vclt_f32(
// CHECK: [[CMP_I:%.*]] = fcmp olt <2 x float> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <2 x i1> [[CMP_I]] to <2 x i32>
// CHECK: ret <2 x i32> [[SEXT_I]]
@@ -2577,7 +2392,7 @@ uint32x2_t test_vclt_f32(float32x2_t v1, float32x2_t v2) {
return vclt_f32(v1, v2);
}
-// CHECK-LABEL: define <1 x i64> @test_vclt_f64(<1 x double> %a, <1 x double> %b) #0 {
+// CHECK-LABEL: @test_vclt_f64(
// CHECK: [[CMP_I:%.*]] = fcmp olt <1 x double> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <1 x i1> [[CMP_I]] to <1 x i64>
// CHECK: ret <1 x i64> [[SEXT_I]]
@@ -2585,7 +2400,7 @@ uint64x1_t test_vclt_f64(float64x1_t a, float64x1_t b) {
return vclt_f64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vclt_u8(<8 x i8> %v1, <8 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vclt_u8(
// CHECK: [[CMP_I:%.*]] = icmp ult <8 x i8> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <8 x i1> [[CMP_I]] to <8 x i8>
// CHECK: ret <8 x i8> [[SEXT_I]]
@@ -2593,7 +2408,7 @@ uint8x8_t test_vclt_u8(uint8x8_t v1, uint8x8_t v2) {
return vclt_u8(v1, v2);
}
-// CHECK-LABEL: define <4 x i16> @test_vclt_u16(<4 x i16> %v1, <4 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vclt_u16(
// CHECK: [[CMP_I:%.*]] = icmp ult <4 x i16> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i16>
// CHECK: ret <4 x i16> [[SEXT_I]]
@@ -2601,7 +2416,7 @@ uint16x4_t test_vclt_u16(uint16x4_t v1, uint16x4_t v2) {
return vclt_u16(v1, v2);
}
-// CHECK-LABEL: define <2 x i32> @test_vclt_u32(<2 x i32> %v1, <2 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vclt_u32(
// CHECK: [[CMP_I:%.*]] = icmp ult <2 x i32> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <2 x i1> [[CMP_I]] to <2 x i32>
// CHECK: ret <2 x i32> [[SEXT_I]]
@@ -2609,7 +2424,7 @@ uint32x2_t test_vclt_u32(uint32x2_t v1, uint32x2_t v2) {
return vclt_u32(v1, v2);
}
-// CHECK-LABEL: define <16 x i8> @test_vcltq_s8(<16 x i8> %v1, <16 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vcltq_s8(
// CHECK: [[CMP_I:%.*]] = icmp slt <16 x i8> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <16 x i1> [[CMP_I]] to <16 x i8>
// CHECK: ret <16 x i8> [[SEXT_I]]
@@ -2617,7 +2432,7 @@ uint8x16_t test_vcltq_s8(int8x16_t v1, int8x16_t v2) {
return vcltq_s8(v1, v2);
}
-// CHECK-LABEL: define <8 x i16> @test_vcltq_s16(<8 x i16> %v1, <8 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vcltq_s16(
// CHECK: [[CMP_I:%.*]] = icmp slt <8 x i16> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <8 x i1> [[CMP_I]] to <8 x i16>
// CHECK: ret <8 x i16> [[SEXT_I]]
@@ -2625,7 +2440,7 @@ uint16x8_t test_vcltq_s16(int16x8_t v1, int16x8_t v2) {
return vcltq_s16(v1, v2);
}
-// CHECK-LABEL: define <4 x i32> @test_vcltq_s32(<4 x i32> %v1, <4 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vcltq_s32(
// CHECK: [[CMP_I:%.*]] = icmp slt <4 x i32> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i32>
// CHECK: ret <4 x i32> [[SEXT_I]]
@@ -2633,7 +2448,7 @@ uint32x4_t test_vcltq_s32(int32x4_t v1, int32x4_t v2) {
return vcltq_s32(v1, v2);
}
-// CHECK-LABEL: define <4 x i32> @test_vcltq_f32(<4 x float> %v1, <4 x float> %v2) #0 {
+// CHECK-LABEL: @test_vcltq_f32(
// CHECK: [[CMP_I:%.*]] = fcmp olt <4 x float> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i32>
// CHECK: ret <4 x i32> [[SEXT_I]]
@@ -2641,7 +2456,7 @@ uint32x4_t test_vcltq_f32(float32x4_t v1, float32x4_t v2) {
return vcltq_f32(v1, v2);
}
-// CHECK-LABEL: define <16 x i8> @test_vcltq_u8(<16 x i8> %v1, <16 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vcltq_u8(
// CHECK: [[CMP_I:%.*]] = icmp ult <16 x i8> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <16 x i1> [[CMP_I]] to <16 x i8>
// CHECK: ret <16 x i8> [[SEXT_I]]
@@ -2649,7 +2464,7 @@ uint8x16_t test_vcltq_u8(uint8x16_t v1, uint8x16_t v2) {
return vcltq_u8(v1, v2);
}
-// CHECK-LABEL: define <8 x i16> @test_vcltq_u16(<8 x i16> %v1, <8 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vcltq_u16(
// CHECK: [[CMP_I:%.*]] = icmp ult <8 x i16> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <8 x i1> [[CMP_I]] to <8 x i16>
// CHECK: ret <8 x i16> [[SEXT_I]]
@@ -2657,7 +2472,7 @@ uint16x8_t test_vcltq_u16(uint16x8_t v1, uint16x8_t v2) {
return vcltq_u16(v1, v2);
}
-// CHECK-LABEL: define <4 x i32> @test_vcltq_u32(<4 x i32> %v1, <4 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vcltq_u32(
// CHECK: [[CMP_I:%.*]] = icmp ult <4 x i32> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i32>
// CHECK: ret <4 x i32> [[SEXT_I]]
@@ -2665,7 +2480,7 @@ uint32x4_t test_vcltq_u32(uint32x4_t v1, uint32x4_t v2) {
return vcltq_u32(v1, v2);
}
-// CHECK-LABEL: define <2 x i64> @test_vcltq_s64(<2 x i64> %v1, <2 x i64> %v2) #0 {
+// CHECK-LABEL: @test_vcltq_s64(
// CHECK: [[CMP_I:%.*]] = icmp slt <2 x i64> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <2 x i1> [[CMP_I]] to <2 x i64>
// CHECK: ret <2 x i64> [[SEXT_I]]
@@ -2673,7 +2488,7 @@ uint64x2_t test_vcltq_s64(int64x2_t v1, int64x2_t v2) {
return vcltq_s64(v1, v2);
}
-// CHECK-LABEL: define <2 x i64> @test_vcltq_u64(<2 x i64> %v1, <2 x i64> %v2) #0 {
+// CHECK-LABEL: @test_vcltq_u64(
// CHECK: [[CMP_I:%.*]] = icmp ult <2 x i64> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <2 x i1> [[CMP_I]] to <2 x i64>
// CHECK: ret <2 x i64> [[SEXT_I]]
@@ -2681,7 +2496,7 @@ uint64x2_t test_vcltq_u64(uint64x2_t v1, uint64x2_t v2) {
return vcltq_u64(v1, v2);
}
-// CHECK-LABEL: define <2 x i64> @test_vcltq_f64(<2 x double> %v1, <2 x double> %v2) #0 {
+// CHECK-LABEL: @test_vcltq_f64(
// CHECK: [[CMP_I:%.*]] = fcmp olt <2 x double> %v1, %v2
// CHECK: [[SEXT_I:%.*]] = sext <2 x i1> [[CMP_I]] to <2 x i64>
// CHECK: ret <2 x i64> [[SEXT_I]]
@@ -2689,1513 +2504,1219 @@ uint64x2_t test_vcltq_f64(float64x2_t v1, float64x2_t v2) {
return vcltq_f64(v1, v2);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vhadd_s8(<8 x i8> %v1, <8 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vhadd_s8(
// CHECK: [[VHADD_V_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.shadd.v8i8(<8 x i8> %v1, <8 x i8> %v2) #4
// CHECK: ret <8 x i8> [[VHADD_V_I]]
int8x8_t test_vhadd_s8(int8x8_t v1, int8x8_t v2) {
return vhadd_s8(v1, v2);
}
-// CHECK-LABEL: define <4 x i16> @test_vhadd_s16(<4 x i16> %v1, <4 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vhadd_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %v1 to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %v2 to <8 x i8>
-// CHECK: [[VHADD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VHADD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VHADD_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.shadd.v4i16(<4 x i16> [[VHADD_V_I]], <4 x i16> [[VHADD_V1_I]]) #4
+// CHECK: [[VHADD_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.shadd.v4i16(<4 x i16> %v1, <4 x i16> %v2) #4
// CHECK: [[VHADD_V3_I:%.*]] = bitcast <4 x i16> [[VHADD_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VHADD_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VHADD_V2_I]]
int16x4_t test_vhadd_s16(int16x4_t v1, int16x4_t v2) {
return vhadd_s16(v1, v2);
}
-// CHECK-LABEL: define <2 x i32> @test_vhadd_s32(<2 x i32> %v1, <2 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vhadd_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %v1 to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %v2 to <8 x i8>
-// CHECK: [[VHADD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VHADD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VHADD_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.shadd.v2i32(<2 x i32> [[VHADD_V_I]], <2 x i32> [[VHADD_V1_I]]) #4
+// CHECK: [[VHADD_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.shadd.v2i32(<2 x i32> %v1, <2 x i32> %v2) #4
// CHECK: [[VHADD_V3_I:%.*]] = bitcast <2 x i32> [[VHADD_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VHADD_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VHADD_V2_I]]
int32x2_t test_vhadd_s32(int32x2_t v1, int32x2_t v2) {
return vhadd_s32(v1, v2);
}
-// CHECK-LABEL: define <8 x i8> @test_vhadd_u8(<8 x i8> %v1, <8 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vhadd_u8(
// CHECK: [[VHADD_V_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.uhadd.v8i8(<8 x i8> %v1, <8 x i8> %v2) #4
// CHECK: ret <8 x i8> [[VHADD_V_I]]
uint8x8_t test_vhadd_u8(uint8x8_t v1, uint8x8_t v2) {
return vhadd_u8(v1, v2);
}
-// CHECK-LABEL: define <4 x i16> @test_vhadd_u16(<4 x i16> %v1, <4 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vhadd_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %v1 to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %v2 to <8 x i8>
-// CHECK: [[VHADD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VHADD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VHADD_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.uhadd.v4i16(<4 x i16> [[VHADD_V_I]], <4 x i16> [[VHADD_V1_I]]) #4
+// CHECK: [[VHADD_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.uhadd.v4i16(<4 x i16> %v1, <4 x i16> %v2) #4
// CHECK: [[VHADD_V3_I:%.*]] = bitcast <4 x i16> [[VHADD_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VHADD_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VHADD_V2_I]]
uint16x4_t test_vhadd_u16(uint16x4_t v1, uint16x4_t v2) {
return vhadd_u16(v1, v2);
}
-// CHECK-LABEL: define <2 x i32> @test_vhadd_u32(<2 x i32> %v1, <2 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vhadd_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %v1 to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %v2 to <8 x i8>
-// CHECK: [[VHADD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VHADD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VHADD_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.uhadd.v2i32(<2 x i32> [[VHADD_V_I]], <2 x i32> [[VHADD_V1_I]]) #4
+// CHECK: [[VHADD_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.uhadd.v2i32(<2 x i32> %v1, <2 x i32> %v2) #4
// CHECK: [[VHADD_V3_I:%.*]] = bitcast <2 x i32> [[VHADD_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VHADD_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VHADD_V2_I]]
uint32x2_t test_vhadd_u32(uint32x2_t v1, uint32x2_t v2) {
return vhadd_u32(v1, v2);
}
-// CHECK-LABEL: define <16 x i8> @test_vhaddq_s8(<16 x i8> %v1, <16 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vhaddq_s8(
// CHECK: [[VHADDQ_V_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.shadd.v16i8(<16 x i8> %v1, <16 x i8> %v2) #4
// CHECK: ret <16 x i8> [[VHADDQ_V_I]]
int8x16_t test_vhaddq_s8(int8x16_t v1, int8x16_t v2) {
return vhaddq_s8(v1, v2);
}
-// CHECK-LABEL: define <8 x i16> @test_vhaddq_s16(<8 x i16> %v1, <8 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vhaddq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %v2 to <16 x i8>
-// CHECK: [[VHADDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VHADDQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VHADDQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.shadd.v8i16(<8 x i16> [[VHADDQ_V_I]], <8 x i16> [[VHADDQ_V1_I]]) #4
+// CHECK: [[VHADDQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.shadd.v8i16(<8 x i16> %v1, <8 x i16> %v2) #4
// CHECK: [[VHADDQ_V3_I:%.*]] = bitcast <8 x i16> [[VHADDQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VHADDQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VHADDQ_V2_I]]
int16x8_t test_vhaddq_s16(int16x8_t v1, int16x8_t v2) {
return vhaddq_s16(v1, v2);
}
-// CHECK-LABEL: define <4 x i32> @test_vhaddq_s32(<4 x i32> %v1, <4 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vhaddq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %v2 to <16 x i8>
-// CHECK: [[VHADDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VHADDQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VHADDQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.shadd.v4i32(<4 x i32> [[VHADDQ_V_I]], <4 x i32> [[VHADDQ_V1_I]]) #4
+// CHECK: [[VHADDQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.shadd.v4i32(<4 x i32> %v1, <4 x i32> %v2) #4
// CHECK: [[VHADDQ_V3_I:%.*]] = bitcast <4 x i32> [[VHADDQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VHADDQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VHADDQ_V2_I]]
int32x4_t test_vhaddq_s32(int32x4_t v1, int32x4_t v2) {
return vhaddq_s32(v1, v2);
}
-// CHECK-LABEL: define <16 x i8> @test_vhaddq_u8(<16 x i8> %v1, <16 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vhaddq_u8(
// CHECK: [[VHADDQ_V_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.uhadd.v16i8(<16 x i8> %v1, <16 x i8> %v2) #4
// CHECK: ret <16 x i8> [[VHADDQ_V_I]]
uint8x16_t test_vhaddq_u8(uint8x16_t v1, uint8x16_t v2) {
return vhaddq_u8(v1, v2);
}
-// CHECK-LABEL: define <8 x i16> @test_vhaddq_u16(<8 x i16> %v1, <8 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vhaddq_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %v2 to <16 x i8>
-// CHECK: [[VHADDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VHADDQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VHADDQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.uhadd.v8i16(<8 x i16> [[VHADDQ_V_I]], <8 x i16> [[VHADDQ_V1_I]]) #4
+// CHECK: [[VHADDQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.uhadd.v8i16(<8 x i16> %v1, <8 x i16> %v2) #4
// CHECK: [[VHADDQ_V3_I:%.*]] = bitcast <8 x i16> [[VHADDQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VHADDQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VHADDQ_V2_I]]
uint16x8_t test_vhaddq_u16(uint16x8_t v1, uint16x8_t v2) {
return vhaddq_u16(v1, v2);
}
-// CHECK-LABEL: define <4 x i32> @test_vhaddq_u32(<4 x i32> %v1, <4 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vhaddq_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %v2 to <16 x i8>
-// CHECK: [[VHADDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VHADDQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VHADDQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.uhadd.v4i32(<4 x i32> [[VHADDQ_V_I]], <4 x i32> [[VHADDQ_V1_I]]) #4
+// CHECK: [[VHADDQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.uhadd.v4i32(<4 x i32> %v1, <4 x i32> %v2) #4
// CHECK: [[VHADDQ_V3_I:%.*]] = bitcast <4 x i32> [[VHADDQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VHADDQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VHADDQ_V2_I]]
uint32x4_t test_vhaddq_u32(uint32x4_t v1, uint32x4_t v2) {
return vhaddq_u32(v1, v2);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vhsub_s8(<8 x i8> %v1, <8 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vhsub_s8(
// CHECK: [[VHSUB_V_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.shsub.v8i8(<8 x i8> %v1, <8 x i8> %v2) #4
// CHECK: ret <8 x i8> [[VHSUB_V_I]]
int8x8_t test_vhsub_s8(int8x8_t v1, int8x8_t v2) {
return vhsub_s8(v1, v2);
}
-// CHECK-LABEL: define <4 x i16> @test_vhsub_s16(<4 x i16> %v1, <4 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vhsub_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %v1 to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %v2 to <8 x i8>
-// CHECK: [[VHSUB_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VHSUB_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VHSUB_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.shsub.v4i16(<4 x i16> [[VHSUB_V_I]], <4 x i16> [[VHSUB_V1_I]]) #4
+// CHECK: [[VHSUB_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.shsub.v4i16(<4 x i16> %v1, <4 x i16> %v2) #4
// CHECK: [[VHSUB_V3_I:%.*]] = bitcast <4 x i16> [[VHSUB_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VHSUB_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VHSUB_V2_I]]
int16x4_t test_vhsub_s16(int16x4_t v1, int16x4_t v2) {
return vhsub_s16(v1, v2);
}
-// CHECK-LABEL: define <2 x i32> @test_vhsub_s32(<2 x i32> %v1, <2 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vhsub_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %v1 to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %v2 to <8 x i8>
-// CHECK: [[VHSUB_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VHSUB_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VHSUB_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.shsub.v2i32(<2 x i32> [[VHSUB_V_I]], <2 x i32> [[VHSUB_V1_I]]) #4
+// CHECK: [[VHSUB_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.shsub.v2i32(<2 x i32> %v1, <2 x i32> %v2) #4
// CHECK: [[VHSUB_V3_I:%.*]] = bitcast <2 x i32> [[VHSUB_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VHSUB_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VHSUB_V2_I]]
int32x2_t test_vhsub_s32(int32x2_t v1, int32x2_t v2) {
return vhsub_s32(v1, v2);
}
-// CHECK-LABEL: define <8 x i8> @test_vhsub_u8(<8 x i8> %v1, <8 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vhsub_u8(
// CHECK: [[VHSUB_V_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.uhsub.v8i8(<8 x i8> %v1, <8 x i8> %v2) #4
// CHECK: ret <8 x i8> [[VHSUB_V_I]]
uint8x8_t test_vhsub_u8(uint8x8_t v1, uint8x8_t v2) {
return vhsub_u8(v1, v2);
}
-// CHECK-LABEL: define <4 x i16> @test_vhsub_u16(<4 x i16> %v1, <4 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vhsub_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %v1 to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %v2 to <8 x i8>
-// CHECK: [[VHSUB_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VHSUB_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VHSUB_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.uhsub.v4i16(<4 x i16> [[VHSUB_V_I]], <4 x i16> [[VHSUB_V1_I]]) #4
+// CHECK: [[VHSUB_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.uhsub.v4i16(<4 x i16> %v1, <4 x i16> %v2) #4
// CHECK: [[VHSUB_V3_I:%.*]] = bitcast <4 x i16> [[VHSUB_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VHSUB_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VHSUB_V2_I]]
uint16x4_t test_vhsub_u16(uint16x4_t v1, uint16x4_t v2) {
return vhsub_u16(v1, v2);
}
-// CHECK-LABEL: define <2 x i32> @test_vhsub_u32(<2 x i32> %v1, <2 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vhsub_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %v1 to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %v2 to <8 x i8>
-// CHECK: [[VHSUB_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VHSUB_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VHSUB_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.uhsub.v2i32(<2 x i32> [[VHSUB_V_I]], <2 x i32> [[VHSUB_V1_I]]) #4
+// CHECK: [[VHSUB_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.uhsub.v2i32(<2 x i32> %v1, <2 x i32> %v2) #4
// CHECK: [[VHSUB_V3_I:%.*]] = bitcast <2 x i32> [[VHSUB_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VHSUB_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VHSUB_V2_I]]
uint32x2_t test_vhsub_u32(uint32x2_t v1, uint32x2_t v2) {
return vhsub_u32(v1, v2);
}
-// CHECK-LABEL: define <16 x i8> @test_vhsubq_s8(<16 x i8> %v1, <16 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vhsubq_s8(
// CHECK: [[VHSUBQ_V_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.shsub.v16i8(<16 x i8> %v1, <16 x i8> %v2) #4
// CHECK: ret <16 x i8> [[VHSUBQ_V_I]]
int8x16_t test_vhsubq_s8(int8x16_t v1, int8x16_t v2) {
return vhsubq_s8(v1, v2);
}
-// CHECK-LABEL: define <8 x i16> @test_vhsubq_s16(<8 x i16> %v1, <8 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vhsubq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %v2 to <16 x i8>
-// CHECK: [[VHSUBQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VHSUBQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VHSUBQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.shsub.v8i16(<8 x i16> [[VHSUBQ_V_I]], <8 x i16> [[VHSUBQ_V1_I]]) #4
+// CHECK: [[VHSUBQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.shsub.v8i16(<8 x i16> %v1, <8 x i16> %v2) #4
// CHECK: [[VHSUBQ_V3_I:%.*]] = bitcast <8 x i16> [[VHSUBQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VHSUBQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VHSUBQ_V2_I]]
int16x8_t test_vhsubq_s16(int16x8_t v1, int16x8_t v2) {
return vhsubq_s16(v1, v2);
}
-// CHECK-LABEL: define <4 x i32> @test_vhsubq_s32(<4 x i32> %v1, <4 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vhsubq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %v2 to <16 x i8>
-// CHECK: [[VHSUBQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VHSUBQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VHSUBQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.shsub.v4i32(<4 x i32> [[VHSUBQ_V_I]], <4 x i32> [[VHSUBQ_V1_I]]) #4
+// CHECK: [[VHSUBQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.shsub.v4i32(<4 x i32> %v1, <4 x i32> %v2) #4
// CHECK: [[VHSUBQ_V3_I:%.*]] = bitcast <4 x i32> [[VHSUBQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VHSUBQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VHSUBQ_V2_I]]
int32x4_t test_vhsubq_s32(int32x4_t v1, int32x4_t v2) {
return vhsubq_s32(v1, v2);
}
-// CHECK-LABEL: define <16 x i8> @test_vhsubq_u8(<16 x i8> %v1, <16 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vhsubq_u8(
// CHECK: [[VHSUBQ_V_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.uhsub.v16i8(<16 x i8> %v1, <16 x i8> %v2) #4
// CHECK: ret <16 x i8> [[VHSUBQ_V_I]]
uint8x16_t test_vhsubq_u8(uint8x16_t v1, uint8x16_t v2) {
return vhsubq_u8(v1, v2);
}
-// CHECK-LABEL: define <8 x i16> @test_vhsubq_u16(<8 x i16> %v1, <8 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vhsubq_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %v2 to <16 x i8>
-// CHECK: [[VHSUBQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VHSUBQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VHSUBQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.uhsub.v8i16(<8 x i16> [[VHSUBQ_V_I]], <8 x i16> [[VHSUBQ_V1_I]]) #4
+// CHECK: [[VHSUBQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.uhsub.v8i16(<8 x i16> %v1, <8 x i16> %v2) #4
// CHECK: [[VHSUBQ_V3_I:%.*]] = bitcast <8 x i16> [[VHSUBQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VHSUBQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VHSUBQ_V2_I]]
uint16x8_t test_vhsubq_u16(uint16x8_t v1, uint16x8_t v2) {
return vhsubq_u16(v1, v2);
}
-// CHECK-LABEL: define <4 x i32> @test_vhsubq_u32(<4 x i32> %v1, <4 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vhsubq_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %v2 to <16 x i8>
-// CHECK: [[VHSUBQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VHSUBQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VHSUBQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.uhsub.v4i32(<4 x i32> [[VHSUBQ_V_I]], <4 x i32> [[VHSUBQ_V1_I]]) #4
+// CHECK: [[VHSUBQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.uhsub.v4i32(<4 x i32> %v1, <4 x i32> %v2) #4
// CHECK: [[VHSUBQ_V3_I:%.*]] = bitcast <4 x i32> [[VHSUBQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VHSUBQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VHSUBQ_V2_I]]
uint32x4_t test_vhsubq_u32(uint32x4_t v1, uint32x4_t v2) {
return vhsubq_u32(v1, v2);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vrhadd_s8(<8 x i8> %v1, <8 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vrhadd_s8(
// CHECK: [[VRHADD_V_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.srhadd.v8i8(<8 x i8> %v1, <8 x i8> %v2) #4
// CHECK: ret <8 x i8> [[VRHADD_V_I]]
int8x8_t test_vrhadd_s8(int8x8_t v1, int8x8_t v2) {
return vrhadd_s8(v1, v2);
}
-// CHECK-LABEL: define <4 x i16> @test_vrhadd_s16(<4 x i16> %v1, <4 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vrhadd_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %v1 to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %v2 to <8 x i8>
-// CHECK: [[VRHADD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VRHADD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VRHADD_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.srhadd.v4i16(<4 x i16> [[VRHADD_V_I]], <4 x i16> [[VRHADD_V1_I]]) #4
+// CHECK: [[VRHADD_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.srhadd.v4i16(<4 x i16> %v1, <4 x i16> %v2) #4
// CHECK: [[VRHADD_V3_I:%.*]] = bitcast <4 x i16> [[VRHADD_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRHADD_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VRHADD_V2_I]]
int16x4_t test_vrhadd_s16(int16x4_t v1, int16x4_t v2) {
return vrhadd_s16(v1, v2);
}
-// CHECK-LABEL: define <2 x i32> @test_vrhadd_s32(<2 x i32> %v1, <2 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vrhadd_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %v1 to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %v2 to <8 x i8>
-// CHECK: [[VRHADD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VRHADD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VRHADD_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.srhadd.v2i32(<2 x i32> [[VRHADD_V_I]], <2 x i32> [[VRHADD_V1_I]]) #4
+// CHECK: [[VRHADD_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.srhadd.v2i32(<2 x i32> %v1, <2 x i32> %v2) #4
// CHECK: [[VRHADD_V3_I:%.*]] = bitcast <2 x i32> [[VRHADD_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRHADD_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VRHADD_V2_I]]
int32x2_t test_vrhadd_s32(int32x2_t v1, int32x2_t v2) {
return vrhadd_s32(v1, v2);
}
-// CHECK-LABEL: define <8 x i8> @test_vrhadd_u8(<8 x i8> %v1, <8 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vrhadd_u8(
// CHECK: [[VRHADD_V_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.urhadd.v8i8(<8 x i8> %v1, <8 x i8> %v2) #4
// CHECK: ret <8 x i8> [[VRHADD_V_I]]
uint8x8_t test_vrhadd_u8(uint8x8_t v1, uint8x8_t v2) {
return vrhadd_u8(v1, v2);
}
-// CHECK-LABEL: define <4 x i16> @test_vrhadd_u16(<4 x i16> %v1, <4 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vrhadd_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %v1 to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %v2 to <8 x i8>
-// CHECK: [[VRHADD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VRHADD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VRHADD_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.urhadd.v4i16(<4 x i16> [[VRHADD_V_I]], <4 x i16> [[VRHADD_V1_I]]) #4
+// CHECK: [[VRHADD_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.urhadd.v4i16(<4 x i16> %v1, <4 x i16> %v2) #4
// CHECK: [[VRHADD_V3_I:%.*]] = bitcast <4 x i16> [[VRHADD_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRHADD_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VRHADD_V2_I]]
uint16x4_t test_vrhadd_u16(uint16x4_t v1, uint16x4_t v2) {
return vrhadd_u16(v1, v2);
}
-// CHECK-LABEL: define <2 x i32> @test_vrhadd_u32(<2 x i32> %v1, <2 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vrhadd_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %v1 to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %v2 to <8 x i8>
-// CHECK: [[VRHADD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VRHADD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VRHADD_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.urhadd.v2i32(<2 x i32> [[VRHADD_V_I]], <2 x i32> [[VRHADD_V1_I]]) #4
+// CHECK: [[VRHADD_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.urhadd.v2i32(<2 x i32> %v1, <2 x i32> %v2) #4
// CHECK: [[VRHADD_V3_I:%.*]] = bitcast <2 x i32> [[VRHADD_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRHADD_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VRHADD_V2_I]]
uint32x2_t test_vrhadd_u32(uint32x2_t v1, uint32x2_t v2) {
return vrhadd_u32(v1, v2);
}
-// CHECK-LABEL: define <16 x i8> @test_vrhaddq_s8(<16 x i8> %v1, <16 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vrhaddq_s8(
// CHECK: [[VRHADDQ_V_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.srhadd.v16i8(<16 x i8> %v1, <16 x i8> %v2) #4
// CHECK: ret <16 x i8> [[VRHADDQ_V_I]]
int8x16_t test_vrhaddq_s8(int8x16_t v1, int8x16_t v2) {
return vrhaddq_s8(v1, v2);
}
-// CHECK-LABEL: define <8 x i16> @test_vrhaddq_s16(<8 x i16> %v1, <8 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vrhaddq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %v2 to <16 x i8>
-// CHECK: [[VRHADDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VRHADDQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VRHADDQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.srhadd.v8i16(<8 x i16> [[VRHADDQ_V_I]], <8 x i16> [[VRHADDQ_V1_I]]) #4
+// CHECK: [[VRHADDQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.srhadd.v8i16(<8 x i16> %v1, <8 x i16> %v2) #4
// CHECK: [[VRHADDQ_V3_I:%.*]] = bitcast <8 x i16> [[VRHADDQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VRHADDQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VRHADDQ_V2_I]]
int16x8_t test_vrhaddq_s16(int16x8_t v1, int16x8_t v2) {
return vrhaddq_s16(v1, v2);
}
-// CHECK-LABEL: define <4 x i32> @test_vrhaddq_s32(<4 x i32> %v1, <4 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vrhaddq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %v2 to <16 x i8>
-// CHECK: [[VRHADDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VRHADDQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VRHADDQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.srhadd.v4i32(<4 x i32> [[VRHADDQ_V_I]], <4 x i32> [[VRHADDQ_V1_I]]) #4
+// CHECK: [[VRHADDQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.srhadd.v4i32(<4 x i32> %v1, <4 x i32> %v2) #4
// CHECK: [[VRHADDQ_V3_I:%.*]] = bitcast <4 x i32> [[VRHADDQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VRHADDQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VRHADDQ_V2_I]]
int32x4_t test_vrhaddq_s32(int32x4_t v1, int32x4_t v2) {
return vrhaddq_s32(v1, v2);
}
-// CHECK-LABEL: define <16 x i8> @test_vrhaddq_u8(<16 x i8> %v1, <16 x i8> %v2) #0 {
+// CHECK-LABEL: @test_vrhaddq_u8(
// CHECK: [[VRHADDQ_V_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.urhadd.v16i8(<16 x i8> %v1, <16 x i8> %v2) #4
// CHECK: ret <16 x i8> [[VRHADDQ_V_I]]
uint8x16_t test_vrhaddq_u8(uint8x16_t v1, uint8x16_t v2) {
return vrhaddq_u8(v1, v2);
}
-// CHECK-LABEL: define <8 x i16> @test_vrhaddq_u16(<8 x i16> %v1, <8 x i16> %v2) #0 {
+// CHECK-LABEL: @test_vrhaddq_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %v2 to <16 x i8>
-// CHECK: [[VRHADDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VRHADDQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VRHADDQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.urhadd.v8i16(<8 x i16> [[VRHADDQ_V_I]], <8 x i16> [[VRHADDQ_V1_I]]) #4
+// CHECK: [[VRHADDQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.urhadd.v8i16(<8 x i16> %v1, <8 x i16> %v2) #4
// CHECK: [[VRHADDQ_V3_I:%.*]] = bitcast <8 x i16> [[VRHADDQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VRHADDQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VRHADDQ_V2_I]]
uint16x8_t test_vrhaddq_u16(uint16x8_t v1, uint16x8_t v2) {
return vrhaddq_u16(v1, v2);
}
-// CHECK-LABEL: define <4 x i32> @test_vrhaddq_u32(<4 x i32> %v1, <4 x i32> %v2) #0 {
+// CHECK-LABEL: @test_vrhaddq_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %v1 to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %v2 to <16 x i8>
-// CHECK: [[VRHADDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VRHADDQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VRHADDQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.urhadd.v4i32(<4 x i32> [[VRHADDQ_V_I]], <4 x i32> [[VRHADDQ_V1_I]]) #4
+// CHECK: [[VRHADDQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.urhadd.v4i32(<4 x i32> %v1, <4 x i32> %v2) #4
// CHECK: [[VRHADDQ_V3_I:%.*]] = bitcast <4 x i32> [[VRHADDQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VRHADDQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VRHADDQ_V2_I]]
uint32x4_t test_vrhaddq_u32(uint32x4_t v1, uint32x4_t v2) {
return vrhaddq_u32(v1, v2);
}
-// CHECK-LABEL: define <8 x i8> @test_vqadd_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+
+// CHECK-LABEL: @test_vqadd_s8(
// CHECK: [[VQADD_V_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.sqadd.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VQADD_V_I]]
int8x8_t test_vqadd_s8(int8x8_t a, int8x8_t b) {
return vqadd_s8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vqadd_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqadd_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VQADD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQADD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQADD_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqadd.v4i16(<4 x i16> [[VQADD_V_I]], <4 x i16> [[VQADD_V1_I]]) #4
+// CHECK: [[VQADD_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqadd.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VQADD_V3_I:%.*]] = bitcast <4 x i16> [[VQADD_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQADD_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VQADD_V2_I]]
int16x4_t test_vqadd_s16(int16x4_t a, int16x4_t b) {
return vqadd_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vqadd_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqadd_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VQADD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQADD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQADD_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqadd.v2i32(<2 x i32> [[VQADD_V_I]], <2 x i32> [[VQADD_V1_I]]) #4
+// CHECK: [[VQADD_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqadd.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VQADD_V3_I:%.*]] = bitcast <2 x i32> [[VQADD_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQADD_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VQADD_V2_I]]
int32x2_t test_vqadd_s32(int32x2_t a, int32x2_t b) {
return vqadd_s32(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vqadd_s64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vqadd_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
-// CHECK: [[VQADD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
-// CHECK: [[VQADD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x i64>
-// CHECK: [[VQADD_V2_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.sqadd.v1i64(<1 x i64> [[VQADD_V_I]], <1 x i64> [[VQADD_V1_I]]) #4
+// CHECK: [[VQADD_V2_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.sqadd.v1i64(<1 x i64> %a, <1 x i64> %b) #4
// CHECK: [[VQADD_V3_I:%.*]] = bitcast <1 x i64> [[VQADD_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQADD_V3_I]] to <1 x i64>
-// CHECK: ret <1 x i64> [[TMP2]]
+// CHECK: ret <1 x i64> [[VQADD_V2_I]]
int64x1_t test_vqadd_s64(int64x1_t a, int64x1_t b) {
return vqadd_s64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vqadd_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vqadd_u8(
// CHECK: [[VQADD_V_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.uqadd.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VQADD_V_I]]
uint8x8_t test_vqadd_u8(uint8x8_t a, uint8x8_t b) {
return vqadd_u8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vqadd_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqadd_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VQADD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQADD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQADD_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.uqadd.v4i16(<4 x i16> [[VQADD_V_I]], <4 x i16> [[VQADD_V1_I]]) #4
+// CHECK: [[VQADD_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.uqadd.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VQADD_V3_I:%.*]] = bitcast <4 x i16> [[VQADD_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQADD_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VQADD_V2_I]]
uint16x4_t test_vqadd_u16(uint16x4_t a, uint16x4_t b) {
return vqadd_u16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vqadd_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqadd_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VQADD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQADD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQADD_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.uqadd.v2i32(<2 x i32> [[VQADD_V_I]], <2 x i32> [[VQADD_V1_I]]) #4
+// CHECK: [[VQADD_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.uqadd.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VQADD_V3_I:%.*]] = bitcast <2 x i32> [[VQADD_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQADD_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VQADD_V2_I]]
uint32x2_t test_vqadd_u32(uint32x2_t a, uint32x2_t b) {
return vqadd_u32(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vqadd_u64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vqadd_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
-// CHECK: [[VQADD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
-// CHECK: [[VQADD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x i64>
-// CHECK: [[VQADD_V2_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.uqadd.v1i64(<1 x i64> [[VQADD_V_I]], <1 x i64> [[VQADD_V1_I]]) #4
+// CHECK: [[VQADD_V2_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.uqadd.v1i64(<1 x i64> %a, <1 x i64> %b) #4
// CHECK: [[VQADD_V3_I:%.*]] = bitcast <1 x i64> [[VQADD_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQADD_V3_I]] to <1 x i64>
-// CHECK: ret <1 x i64> [[TMP2]]
+// CHECK: ret <1 x i64> [[VQADD_V2_I]]
uint64x1_t test_vqadd_u64(uint64x1_t a, uint64x1_t b) {
return vqadd_u64(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vqaddq_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vqaddq_s8(
// CHECK: [[VQADDQ_V_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.sqadd.v16i8(<16 x i8> %a, <16 x i8> %b) #4
// CHECK: ret <16 x i8> [[VQADDQ_V_I]]
int8x16_t test_vqaddq_s8(int8x16_t a, int8x16_t b) {
return vqaddq_s8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vqaddq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqaddq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VQADDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VQADDQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VQADDQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.sqadd.v8i16(<8 x i16> [[VQADDQ_V_I]], <8 x i16> [[VQADDQ_V1_I]]) #4
+// CHECK: [[VQADDQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.sqadd.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: [[VQADDQ_V3_I:%.*]] = bitcast <8 x i16> [[VQADDQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQADDQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VQADDQ_V2_I]]
int16x8_t test_vqaddq_s16(int16x8_t a, int16x8_t b) {
return vqaddq_s16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vqaddq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqaddq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VQADDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQADDQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VQADDQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqadd.v4i32(<4 x i32> [[VQADDQ_V_I]], <4 x i32> [[VQADDQ_V1_I]]) #4
+// CHECK: [[VQADDQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqadd.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VQADDQ_V3_I:%.*]] = bitcast <4 x i32> [[VQADDQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQADDQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VQADDQ_V2_I]]
int32x4_t test_vqaddq_s32(int32x4_t a, int32x4_t b) {
return vqaddq_s32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vqaddq_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vqaddq_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[VQADDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQADDQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VQADDQ_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqadd.v2i64(<2 x i64> [[VQADDQ_V_I]], <2 x i64> [[VQADDQ_V1_I]]) #4
+// CHECK: [[VQADDQ_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqadd.v2i64(<2 x i64> %a, <2 x i64> %b) #4
// CHECK: [[VQADDQ_V3_I:%.*]] = bitcast <2 x i64> [[VQADDQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQADDQ_V3_I]] to <2 x i64>
-// CHECK: ret <2 x i64> [[TMP2]]
+// CHECK: ret <2 x i64> [[VQADDQ_V2_I]]
int64x2_t test_vqaddq_s64(int64x2_t a, int64x2_t b) {
return vqaddq_s64(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vqaddq_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vqaddq_u8(
// CHECK: [[VQADDQ_V_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.uqadd.v16i8(<16 x i8> %a, <16 x i8> %b) #4
// CHECK: ret <16 x i8> [[VQADDQ_V_I]]
uint8x16_t test_vqaddq_u8(uint8x16_t a, uint8x16_t b) {
return vqaddq_u8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vqaddq_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqaddq_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VQADDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VQADDQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VQADDQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.uqadd.v8i16(<8 x i16> [[VQADDQ_V_I]], <8 x i16> [[VQADDQ_V1_I]]) #4
+// CHECK: [[VQADDQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.uqadd.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: [[VQADDQ_V3_I:%.*]] = bitcast <8 x i16> [[VQADDQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQADDQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VQADDQ_V2_I]]
uint16x8_t test_vqaddq_u16(uint16x8_t a, uint16x8_t b) {
return vqaddq_u16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vqaddq_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqaddq_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VQADDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQADDQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VQADDQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.uqadd.v4i32(<4 x i32> [[VQADDQ_V_I]], <4 x i32> [[VQADDQ_V1_I]]) #4
+// CHECK: [[VQADDQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.uqadd.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VQADDQ_V3_I:%.*]] = bitcast <4 x i32> [[VQADDQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQADDQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VQADDQ_V2_I]]
uint32x4_t test_vqaddq_u32(uint32x4_t a, uint32x4_t b) {
return vqaddq_u32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vqaddq_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vqaddq_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[VQADDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQADDQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VQADDQ_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.uqadd.v2i64(<2 x i64> [[VQADDQ_V_I]], <2 x i64> [[VQADDQ_V1_I]]) #4
+// CHECK: [[VQADDQ_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.uqadd.v2i64(<2 x i64> %a, <2 x i64> %b) #4
// CHECK: [[VQADDQ_V3_I:%.*]] = bitcast <2 x i64> [[VQADDQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQADDQ_V3_I]] to <2 x i64>
-// CHECK: ret <2 x i64> [[TMP2]]
+// CHECK: ret <2 x i64> [[VQADDQ_V2_I]]
uint64x2_t test_vqaddq_u64(uint64x2_t a, uint64x2_t b) {
return vqaddq_u64(a, b);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vqsub_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vqsub_s8(
// CHECK: [[VQSUB_V_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.sqsub.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VQSUB_V_I]]
int8x8_t test_vqsub_s8(int8x8_t a, int8x8_t b) {
return vqsub_s8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vqsub_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqsub_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VQSUB_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQSUB_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQSUB_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqsub.v4i16(<4 x i16> [[VQSUB_V_I]], <4 x i16> [[VQSUB_V1_I]]) #4
+// CHECK: [[VQSUB_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqsub.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VQSUB_V3_I:%.*]] = bitcast <4 x i16> [[VQSUB_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQSUB_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VQSUB_V2_I]]
int16x4_t test_vqsub_s16(int16x4_t a, int16x4_t b) {
return vqsub_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vqsub_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqsub_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VQSUB_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQSUB_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQSUB_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqsub.v2i32(<2 x i32> [[VQSUB_V_I]], <2 x i32> [[VQSUB_V1_I]]) #4
+// CHECK: [[VQSUB_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqsub.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VQSUB_V3_I:%.*]] = bitcast <2 x i32> [[VQSUB_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQSUB_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VQSUB_V2_I]]
int32x2_t test_vqsub_s32(int32x2_t a, int32x2_t b) {
return vqsub_s32(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vqsub_s64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vqsub_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
-// CHECK: [[VQSUB_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
-// CHECK: [[VQSUB_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x i64>
-// CHECK: [[VQSUB_V2_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.sqsub.v1i64(<1 x i64> [[VQSUB_V_I]], <1 x i64> [[VQSUB_V1_I]]) #4
+// CHECK: [[VQSUB_V2_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.sqsub.v1i64(<1 x i64> %a, <1 x i64> %b) #4
// CHECK: [[VQSUB_V3_I:%.*]] = bitcast <1 x i64> [[VQSUB_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQSUB_V3_I]] to <1 x i64>
-// CHECK: ret <1 x i64> [[TMP2]]
+// CHECK: ret <1 x i64> [[VQSUB_V2_I]]
int64x1_t test_vqsub_s64(int64x1_t a, int64x1_t b) {
return vqsub_s64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vqsub_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vqsub_u8(
// CHECK: [[VQSUB_V_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.uqsub.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VQSUB_V_I]]
uint8x8_t test_vqsub_u8(uint8x8_t a, uint8x8_t b) {
return vqsub_u8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vqsub_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqsub_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VQSUB_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQSUB_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQSUB_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.uqsub.v4i16(<4 x i16> [[VQSUB_V_I]], <4 x i16> [[VQSUB_V1_I]]) #4
+// CHECK: [[VQSUB_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.uqsub.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VQSUB_V3_I:%.*]] = bitcast <4 x i16> [[VQSUB_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQSUB_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VQSUB_V2_I]]
uint16x4_t test_vqsub_u16(uint16x4_t a, uint16x4_t b) {
return vqsub_u16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vqsub_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqsub_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VQSUB_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQSUB_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQSUB_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.uqsub.v2i32(<2 x i32> [[VQSUB_V_I]], <2 x i32> [[VQSUB_V1_I]]) #4
+// CHECK: [[VQSUB_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.uqsub.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VQSUB_V3_I:%.*]] = bitcast <2 x i32> [[VQSUB_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQSUB_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VQSUB_V2_I]]
uint32x2_t test_vqsub_u32(uint32x2_t a, uint32x2_t b) {
return vqsub_u32(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vqsub_u64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vqsub_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
-// CHECK: [[VQSUB_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
-// CHECK: [[VQSUB_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x i64>
-// CHECK: [[VQSUB_V2_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.uqsub.v1i64(<1 x i64> [[VQSUB_V_I]], <1 x i64> [[VQSUB_V1_I]]) #4
+// CHECK: [[VQSUB_V2_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.uqsub.v1i64(<1 x i64> %a, <1 x i64> %b) #4
// CHECK: [[VQSUB_V3_I:%.*]] = bitcast <1 x i64> [[VQSUB_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQSUB_V3_I]] to <1 x i64>
-// CHECK: ret <1 x i64> [[TMP2]]
+// CHECK: ret <1 x i64> [[VQSUB_V2_I]]
uint64x1_t test_vqsub_u64(uint64x1_t a, uint64x1_t b) {
return vqsub_u64(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vqsubq_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vqsubq_s8(
// CHECK: [[VQSUBQ_V_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.sqsub.v16i8(<16 x i8> %a, <16 x i8> %b) #4
// CHECK: ret <16 x i8> [[VQSUBQ_V_I]]
int8x16_t test_vqsubq_s8(int8x16_t a, int8x16_t b) {
return vqsubq_s8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vqsubq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqsubq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VQSUBQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VQSUBQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VQSUBQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.sqsub.v8i16(<8 x i16> [[VQSUBQ_V_I]], <8 x i16> [[VQSUBQ_V1_I]]) #4
+// CHECK: [[VQSUBQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.sqsub.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: [[VQSUBQ_V3_I:%.*]] = bitcast <8 x i16> [[VQSUBQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQSUBQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VQSUBQ_V2_I]]
int16x8_t test_vqsubq_s16(int16x8_t a, int16x8_t b) {
return vqsubq_s16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vqsubq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqsubq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VQSUBQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQSUBQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VQSUBQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqsub.v4i32(<4 x i32> [[VQSUBQ_V_I]], <4 x i32> [[VQSUBQ_V1_I]]) #4
+// CHECK: [[VQSUBQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqsub.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VQSUBQ_V3_I:%.*]] = bitcast <4 x i32> [[VQSUBQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQSUBQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VQSUBQ_V2_I]]
int32x4_t test_vqsubq_s32(int32x4_t a, int32x4_t b) {
return vqsubq_s32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vqsubq_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vqsubq_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[VQSUBQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQSUBQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VQSUBQ_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqsub.v2i64(<2 x i64> [[VQSUBQ_V_I]], <2 x i64> [[VQSUBQ_V1_I]]) #4
+// CHECK: [[VQSUBQ_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqsub.v2i64(<2 x i64> %a, <2 x i64> %b) #4
// CHECK: [[VQSUBQ_V3_I:%.*]] = bitcast <2 x i64> [[VQSUBQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQSUBQ_V3_I]] to <2 x i64>
-// CHECK: ret <2 x i64> [[TMP2]]
+// CHECK: ret <2 x i64> [[VQSUBQ_V2_I]]
int64x2_t test_vqsubq_s64(int64x2_t a, int64x2_t b) {
return vqsubq_s64(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vqsubq_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vqsubq_u8(
// CHECK: [[VQSUBQ_V_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.uqsub.v16i8(<16 x i8> %a, <16 x i8> %b) #4
// CHECK: ret <16 x i8> [[VQSUBQ_V_I]]
uint8x16_t test_vqsubq_u8(uint8x16_t a, uint8x16_t b) {
return vqsubq_u8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vqsubq_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqsubq_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VQSUBQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VQSUBQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VQSUBQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.uqsub.v8i16(<8 x i16> [[VQSUBQ_V_I]], <8 x i16> [[VQSUBQ_V1_I]]) #4
+// CHECK: [[VQSUBQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.uqsub.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: [[VQSUBQ_V3_I:%.*]] = bitcast <8 x i16> [[VQSUBQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQSUBQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VQSUBQ_V2_I]]
uint16x8_t test_vqsubq_u16(uint16x8_t a, uint16x8_t b) {
return vqsubq_u16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vqsubq_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqsubq_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VQSUBQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQSUBQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VQSUBQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.uqsub.v4i32(<4 x i32> [[VQSUBQ_V_I]], <4 x i32> [[VQSUBQ_V1_I]]) #4
+// CHECK: [[VQSUBQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.uqsub.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VQSUBQ_V3_I:%.*]] = bitcast <4 x i32> [[VQSUBQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQSUBQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VQSUBQ_V2_I]]
uint32x4_t test_vqsubq_u32(uint32x4_t a, uint32x4_t b) {
return vqsubq_u32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vqsubq_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vqsubq_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[VQSUBQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQSUBQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VQSUBQ_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.uqsub.v2i64(<2 x i64> [[VQSUBQ_V_I]], <2 x i64> [[VQSUBQ_V1_I]]) #4
+// CHECK: [[VQSUBQ_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.uqsub.v2i64(<2 x i64> %a, <2 x i64> %b) #4
// CHECK: [[VQSUBQ_V3_I:%.*]] = bitcast <2 x i64> [[VQSUBQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQSUBQ_V3_I]] to <2 x i64>
-// CHECK: ret <2 x i64> [[TMP2]]
+// CHECK: ret <2 x i64> [[VQSUBQ_V2_I]]
uint64x2_t test_vqsubq_u64(uint64x2_t a, uint64x2_t b) {
return vqsubq_u64(a, b);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vshl_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vshl_s8(
// CHECK: [[VSHL_V_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.sshl.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VSHL_V_I]]
int8x8_t test_vshl_s8(int8x8_t a, int8x8_t b) {
return vshl_s8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vshl_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vshl_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VSHL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VSHL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VSHL_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sshl.v4i16(<4 x i16> [[VSHL_V_I]], <4 x i16> [[VSHL_V1_I]]) #4
+// CHECK: [[VSHL_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sshl.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VSHL_V3_I:%.*]] = bitcast <4 x i16> [[VSHL_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VSHL_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VSHL_V2_I]]
int16x4_t test_vshl_s16(int16x4_t a, int16x4_t b) {
return vshl_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vshl_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vshl_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VSHL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VSHL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VSHL_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sshl.v2i32(<2 x i32> [[VSHL_V_I]], <2 x i32> [[VSHL_V1_I]]) #4
+// CHECK: [[VSHL_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sshl.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VSHL_V3_I:%.*]] = bitcast <2 x i32> [[VSHL_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VSHL_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VSHL_V2_I]]
int32x2_t test_vshl_s32(int32x2_t a, int32x2_t b) {
return vshl_s32(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vshl_s64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vshl_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
-// CHECK: [[VSHL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
-// CHECK: [[VSHL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x i64>
-// CHECK: [[VSHL_V2_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.sshl.v1i64(<1 x i64> [[VSHL_V_I]], <1 x i64> [[VSHL_V1_I]]) #4
+// CHECK: [[VSHL_V2_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.sshl.v1i64(<1 x i64> %a, <1 x i64> %b) #4
// CHECK: [[VSHL_V3_I:%.*]] = bitcast <1 x i64> [[VSHL_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VSHL_V3_I]] to <1 x i64>
-// CHECK: ret <1 x i64> [[TMP2]]
+// CHECK: ret <1 x i64> [[VSHL_V2_I]]
int64x1_t test_vshl_s64(int64x1_t a, int64x1_t b) {
return vshl_s64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vshl_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vshl_u8(
// CHECK: [[VSHL_V_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.ushl.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VSHL_V_I]]
uint8x8_t test_vshl_u8(uint8x8_t a, int8x8_t b) {
return vshl_u8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vshl_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vshl_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VSHL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VSHL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VSHL_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.ushl.v4i16(<4 x i16> [[VSHL_V_I]], <4 x i16> [[VSHL_V1_I]]) #4
+// CHECK: [[VSHL_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.ushl.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VSHL_V3_I:%.*]] = bitcast <4 x i16> [[VSHL_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VSHL_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VSHL_V2_I]]
uint16x4_t test_vshl_u16(uint16x4_t a, int16x4_t b) {
return vshl_u16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vshl_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vshl_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VSHL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VSHL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VSHL_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.ushl.v2i32(<2 x i32> [[VSHL_V_I]], <2 x i32> [[VSHL_V1_I]]) #4
+// CHECK: [[VSHL_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.ushl.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VSHL_V3_I:%.*]] = bitcast <2 x i32> [[VSHL_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VSHL_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VSHL_V2_I]]
uint32x2_t test_vshl_u32(uint32x2_t a, int32x2_t b) {
return vshl_u32(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vshl_u64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vshl_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
-// CHECK: [[VSHL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
-// CHECK: [[VSHL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x i64>
-// CHECK: [[VSHL_V2_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.ushl.v1i64(<1 x i64> [[VSHL_V_I]], <1 x i64> [[VSHL_V1_I]]) #4
+// CHECK: [[VSHL_V2_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.ushl.v1i64(<1 x i64> %a, <1 x i64> %b) #4
// CHECK: [[VSHL_V3_I:%.*]] = bitcast <1 x i64> [[VSHL_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VSHL_V3_I]] to <1 x i64>
-// CHECK: ret <1 x i64> [[TMP2]]
+// CHECK: ret <1 x i64> [[VSHL_V2_I]]
uint64x1_t test_vshl_u64(uint64x1_t a, int64x1_t b) {
return vshl_u64(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vshlq_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vshlq_s8(
// CHECK: [[VSHLQ_V_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.sshl.v16i8(<16 x i8> %a, <16 x i8> %b) #4
// CHECK: ret <16 x i8> [[VSHLQ_V_I]]
int8x16_t test_vshlq_s8(int8x16_t a, int8x16_t b) {
return vshlq_s8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vshlq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vshlq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VSHLQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VSHLQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VSHLQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.sshl.v8i16(<8 x i16> [[VSHLQ_V_I]], <8 x i16> [[VSHLQ_V1_I]]) #4
+// CHECK: [[VSHLQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.sshl.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: [[VSHLQ_V3_I:%.*]] = bitcast <8 x i16> [[VSHLQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VSHLQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VSHLQ_V2_I]]
int16x8_t test_vshlq_s16(int16x8_t a, int16x8_t b) {
return vshlq_s16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vshlq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vshlq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VSHLQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VSHLQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VSHLQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sshl.v4i32(<4 x i32> [[VSHLQ_V_I]], <4 x i32> [[VSHLQ_V1_I]]) #4
+// CHECK: [[VSHLQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sshl.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VSHLQ_V3_I:%.*]] = bitcast <4 x i32> [[VSHLQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VSHLQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VSHLQ_V2_I]]
int32x4_t test_vshlq_s32(int32x4_t a, int32x4_t b) {
return vshlq_s32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vshlq_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vshlq_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[VSHLQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VSHLQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VSHLQ_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sshl.v2i64(<2 x i64> [[VSHLQ_V_I]], <2 x i64> [[VSHLQ_V1_I]]) #4
+// CHECK: [[VSHLQ_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sshl.v2i64(<2 x i64> %a, <2 x i64> %b) #4
// CHECK: [[VSHLQ_V3_I:%.*]] = bitcast <2 x i64> [[VSHLQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VSHLQ_V3_I]] to <2 x i64>
-// CHECK: ret <2 x i64> [[TMP2]]
+// CHECK: ret <2 x i64> [[VSHLQ_V2_I]]
int64x2_t test_vshlq_s64(int64x2_t a, int64x2_t b) {
return vshlq_s64(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vshlq_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vshlq_u8(
// CHECK: [[VSHLQ_V_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.ushl.v16i8(<16 x i8> %a, <16 x i8> %b) #4
// CHECK: ret <16 x i8> [[VSHLQ_V_I]]
uint8x16_t test_vshlq_u8(uint8x16_t a, int8x16_t b) {
return vshlq_u8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vshlq_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vshlq_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VSHLQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VSHLQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VSHLQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.ushl.v8i16(<8 x i16> [[VSHLQ_V_I]], <8 x i16> [[VSHLQ_V1_I]]) #4
+// CHECK: [[VSHLQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.ushl.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: [[VSHLQ_V3_I:%.*]] = bitcast <8 x i16> [[VSHLQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VSHLQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VSHLQ_V2_I]]
uint16x8_t test_vshlq_u16(uint16x8_t a, int16x8_t b) {
return vshlq_u16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vshlq_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vshlq_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VSHLQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VSHLQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VSHLQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.ushl.v4i32(<4 x i32> [[VSHLQ_V_I]], <4 x i32> [[VSHLQ_V1_I]]) #4
+// CHECK: [[VSHLQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.ushl.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VSHLQ_V3_I:%.*]] = bitcast <4 x i32> [[VSHLQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VSHLQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VSHLQ_V2_I]]
uint32x4_t test_vshlq_u32(uint32x4_t a, int32x4_t b) {
return vshlq_u32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vshlq_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vshlq_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[VSHLQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VSHLQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VSHLQ_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.ushl.v2i64(<2 x i64> [[VSHLQ_V_I]], <2 x i64> [[VSHLQ_V1_I]]) #4
+// CHECK: [[VSHLQ_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.ushl.v2i64(<2 x i64> %a, <2 x i64> %b) #4
// CHECK: [[VSHLQ_V3_I:%.*]] = bitcast <2 x i64> [[VSHLQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VSHLQ_V3_I]] to <2 x i64>
-// CHECK: ret <2 x i64> [[TMP2]]
+// CHECK: ret <2 x i64> [[VSHLQ_V2_I]]
uint64x2_t test_vshlq_u64(uint64x2_t a, int64x2_t b) {
return vshlq_u64(a, b);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vqshl_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vqshl_s8(
// CHECK: [[VQSHL_V_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.sqshl.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VQSHL_V_I]]
int8x8_t test_vqshl_s8(int8x8_t a, int8x8_t b) {
return vqshl_s8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vqshl_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqshl_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VQSHL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQSHL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQSHL_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqshl.v4i16(<4 x i16> [[VQSHL_V_I]], <4 x i16> [[VQSHL_V1_I]]) #4
+// CHECK: [[VQSHL_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqshl.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VQSHL_V3_I:%.*]] = bitcast <4 x i16> [[VQSHL_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQSHL_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VQSHL_V2_I]]
int16x4_t test_vqshl_s16(int16x4_t a, int16x4_t b) {
return vqshl_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vqshl_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqshl_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VQSHL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQSHL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQSHL_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqshl.v2i32(<2 x i32> [[VQSHL_V_I]], <2 x i32> [[VQSHL_V1_I]]) #4
+// CHECK: [[VQSHL_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqshl.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VQSHL_V3_I:%.*]] = bitcast <2 x i32> [[VQSHL_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQSHL_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VQSHL_V2_I]]
int32x2_t test_vqshl_s32(int32x2_t a, int32x2_t b) {
return vqshl_s32(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vqshl_s64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vqshl_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
-// CHECK: [[VQSHL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
-// CHECK: [[VQSHL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x i64>
-// CHECK: [[VQSHL_V2_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.sqshl.v1i64(<1 x i64> [[VQSHL_V_I]], <1 x i64> [[VQSHL_V1_I]]) #4
+// CHECK: [[VQSHL_V2_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.sqshl.v1i64(<1 x i64> %a, <1 x i64> %b) #4
// CHECK: [[VQSHL_V3_I:%.*]] = bitcast <1 x i64> [[VQSHL_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQSHL_V3_I]] to <1 x i64>
-// CHECK: ret <1 x i64> [[TMP2]]
+// CHECK: ret <1 x i64> [[VQSHL_V2_I]]
int64x1_t test_vqshl_s64(int64x1_t a, int64x1_t b) {
return vqshl_s64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vqshl_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vqshl_u8(
// CHECK: [[VQSHL_V_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.uqshl.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VQSHL_V_I]]
uint8x8_t test_vqshl_u8(uint8x8_t a, int8x8_t b) {
return vqshl_u8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vqshl_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqshl_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VQSHL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQSHL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQSHL_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.uqshl.v4i16(<4 x i16> [[VQSHL_V_I]], <4 x i16> [[VQSHL_V1_I]]) #4
+// CHECK: [[VQSHL_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.uqshl.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VQSHL_V3_I:%.*]] = bitcast <4 x i16> [[VQSHL_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQSHL_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VQSHL_V2_I]]
uint16x4_t test_vqshl_u16(uint16x4_t a, int16x4_t b) {
return vqshl_u16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vqshl_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqshl_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VQSHL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQSHL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQSHL_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.uqshl.v2i32(<2 x i32> [[VQSHL_V_I]], <2 x i32> [[VQSHL_V1_I]]) #4
+// CHECK: [[VQSHL_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.uqshl.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VQSHL_V3_I:%.*]] = bitcast <2 x i32> [[VQSHL_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQSHL_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VQSHL_V2_I]]
uint32x2_t test_vqshl_u32(uint32x2_t a, int32x2_t b) {
return vqshl_u32(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vqshl_u64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vqshl_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
-// CHECK: [[VQSHL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
-// CHECK: [[VQSHL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x i64>
-// CHECK: [[VQSHL_V2_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.uqshl.v1i64(<1 x i64> [[VQSHL_V_I]], <1 x i64> [[VQSHL_V1_I]]) #4
+// CHECK: [[VQSHL_V2_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.uqshl.v1i64(<1 x i64> %a, <1 x i64> %b) #4
// CHECK: [[VQSHL_V3_I:%.*]] = bitcast <1 x i64> [[VQSHL_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQSHL_V3_I]] to <1 x i64>
-// CHECK: ret <1 x i64> [[TMP2]]
+// CHECK: ret <1 x i64> [[VQSHL_V2_I]]
uint64x1_t test_vqshl_u64(uint64x1_t a, int64x1_t b) {
return vqshl_u64(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vqshlq_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vqshlq_s8(
// CHECK: [[VQSHLQ_V_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.sqshl.v16i8(<16 x i8> %a, <16 x i8> %b) #4
// CHECK: ret <16 x i8> [[VQSHLQ_V_I]]
int8x16_t test_vqshlq_s8(int8x16_t a, int8x16_t b) {
return vqshlq_s8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vqshlq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqshlq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VQSHLQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VQSHLQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VQSHLQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.sqshl.v8i16(<8 x i16> [[VQSHLQ_V_I]], <8 x i16> [[VQSHLQ_V1_I]]) #4
+// CHECK: [[VQSHLQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.sqshl.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: [[VQSHLQ_V3_I:%.*]] = bitcast <8 x i16> [[VQSHLQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQSHLQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VQSHLQ_V2_I]]
int16x8_t test_vqshlq_s16(int16x8_t a, int16x8_t b) {
return vqshlq_s16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vqshlq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqshlq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VQSHLQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQSHLQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VQSHLQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqshl.v4i32(<4 x i32> [[VQSHLQ_V_I]], <4 x i32> [[VQSHLQ_V1_I]]) #4
+// CHECK: [[VQSHLQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqshl.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VQSHLQ_V3_I:%.*]] = bitcast <4 x i32> [[VQSHLQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQSHLQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VQSHLQ_V2_I]]
int32x4_t test_vqshlq_s32(int32x4_t a, int32x4_t b) {
return vqshlq_s32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vqshlq_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vqshlq_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[VQSHLQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQSHLQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VQSHLQ_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqshl.v2i64(<2 x i64> [[VQSHLQ_V_I]], <2 x i64> [[VQSHLQ_V1_I]]) #4
+// CHECK: [[VQSHLQ_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqshl.v2i64(<2 x i64> %a, <2 x i64> %b) #4
// CHECK: [[VQSHLQ_V3_I:%.*]] = bitcast <2 x i64> [[VQSHLQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQSHLQ_V3_I]] to <2 x i64>
-// CHECK: ret <2 x i64> [[TMP2]]
+// CHECK: ret <2 x i64> [[VQSHLQ_V2_I]]
int64x2_t test_vqshlq_s64(int64x2_t a, int64x2_t b) {
return vqshlq_s64(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vqshlq_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vqshlq_u8(
// CHECK: [[VQSHLQ_V_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.uqshl.v16i8(<16 x i8> %a, <16 x i8> %b) #4
// CHECK: ret <16 x i8> [[VQSHLQ_V_I]]
uint8x16_t test_vqshlq_u8(uint8x16_t a, int8x16_t b) {
return vqshlq_u8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vqshlq_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqshlq_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VQSHLQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VQSHLQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VQSHLQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.uqshl.v8i16(<8 x i16> [[VQSHLQ_V_I]], <8 x i16> [[VQSHLQ_V1_I]]) #4
+// CHECK: [[VQSHLQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.uqshl.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: [[VQSHLQ_V3_I:%.*]] = bitcast <8 x i16> [[VQSHLQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQSHLQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VQSHLQ_V2_I]]
uint16x8_t test_vqshlq_u16(uint16x8_t a, int16x8_t b) {
return vqshlq_u16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vqshlq_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqshlq_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VQSHLQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQSHLQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VQSHLQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.uqshl.v4i32(<4 x i32> [[VQSHLQ_V_I]], <4 x i32> [[VQSHLQ_V1_I]]) #4
+// CHECK: [[VQSHLQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.uqshl.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VQSHLQ_V3_I:%.*]] = bitcast <4 x i32> [[VQSHLQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQSHLQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VQSHLQ_V2_I]]
uint32x4_t test_vqshlq_u32(uint32x4_t a, int32x4_t b) {
return vqshlq_u32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vqshlq_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vqshlq_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[VQSHLQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQSHLQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VQSHLQ_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.uqshl.v2i64(<2 x i64> [[VQSHLQ_V_I]], <2 x i64> [[VQSHLQ_V1_I]]) #4
+// CHECK: [[VQSHLQ_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.uqshl.v2i64(<2 x i64> %a, <2 x i64> %b) #4
// CHECK: [[VQSHLQ_V3_I:%.*]] = bitcast <2 x i64> [[VQSHLQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQSHLQ_V3_I]] to <2 x i64>
-// CHECK: ret <2 x i64> [[TMP2]]
+// CHECK: ret <2 x i64> [[VQSHLQ_V2_I]]
uint64x2_t test_vqshlq_u64(uint64x2_t a, int64x2_t b) {
return vqshlq_u64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vrshl_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vrshl_s8(
// CHECK: [[VRSHL_V_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.srshl.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VRSHL_V_I]]
int8x8_t test_vrshl_s8(int8x8_t a, int8x8_t b) {
return vrshl_s8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vrshl_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vrshl_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VRSHL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VRSHL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VRSHL_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.srshl.v4i16(<4 x i16> [[VRSHL_V_I]], <4 x i16> [[VRSHL_V1_I]]) #4
+// CHECK: [[VRSHL_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.srshl.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VRSHL_V3_I:%.*]] = bitcast <4 x i16> [[VRSHL_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRSHL_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VRSHL_V2_I]]
int16x4_t test_vrshl_s16(int16x4_t a, int16x4_t b) {
return vrshl_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vrshl_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vrshl_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VRSHL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VRSHL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VRSHL_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.srshl.v2i32(<2 x i32> [[VRSHL_V_I]], <2 x i32> [[VRSHL_V1_I]]) #4
+// CHECK: [[VRSHL_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.srshl.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VRSHL_V3_I:%.*]] = bitcast <2 x i32> [[VRSHL_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRSHL_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VRSHL_V2_I]]
int32x2_t test_vrshl_s32(int32x2_t a, int32x2_t b) {
return vrshl_s32(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vrshl_s64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vrshl_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
-// CHECK: [[VRSHL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
-// CHECK: [[VRSHL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x i64>
-// CHECK: [[VRSHL_V2_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.srshl.v1i64(<1 x i64> [[VRSHL_V_I]], <1 x i64> [[VRSHL_V1_I]]) #4
+// CHECK: [[VRSHL_V2_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.srshl.v1i64(<1 x i64> %a, <1 x i64> %b) #4
// CHECK: [[VRSHL_V3_I:%.*]] = bitcast <1 x i64> [[VRSHL_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRSHL_V3_I]] to <1 x i64>
-// CHECK: ret <1 x i64> [[TMP2]]
+// CHECK: ret <1 x i64> [[VRSHL_V2_I]]
int64x1_t test_vrshl_s64(int64x1_t a, int64x1_t b) {
return vrshl_s64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vrshl_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vrshl_u8(
// CHECK: [[VRSHL_V_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.urshl.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VRSHL_V_I]]
uint8x8_t test_vrshl_u8(uint8x8_t a, int8x8_t b) {
return vrshl_u8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vrshl_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vrshl_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VRSHL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VRSHL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VRSHL_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.urshl.v4i16(<4 x i16> [[VRSHL_V_I]], <4 x i16> [[VRSHL_V1_I]]) #4
+// CHECK: [[VRSHL_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.urshl.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VRSHL_V3_I:%.*]] = bitcast <4 x i16> [[VRSHL_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRSHL_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VRSHL_V2_I]]
uint16x4_t test_vrshl_u16(uint16x4_t a, int16x4_t b) {
return vrshl_u16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vrshl_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vrshl_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VRSHL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VRSHL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VRSHL_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.urshl.v2i32(<2 x i32> [[VRSHL_V_I]], <2 x i32> [[VRSHL_V1_I]]) #4
+// CHECK: [[VRSHL_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.urshl.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VRSHL_V3_I:%.*]] = bitcast <2 x i32> [[VRSHL_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRSHL_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VRSHL_V2_I]]
uint32x2_t test_vrshl_u32(uint32x2_t a, int32x2_t b) {
return vrshl_u32(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vrshl_u64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vrshl_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
-// CHECK: [[VRSHL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
-// CHECK: [[VRSHL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x i64>
-// CHECK: [[VRSHL_V2_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.urshl.v1i64(<1 x i64> [[VRSHL_V_I]], <1 x i64> [[VRSHL_V1_I]]) #4
+// CHECK: [[VRSHL_V2_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.urshl.v1i64(<1 x i64> %a, <1 x i64> %b) #4
// CHECK: [[VRSHL_V3_I:%.*]] = bitcast <1 x i64> [[VRSHL_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRSHL_V3_I]] to <1 x i64>
-// CHECK: ret <1 x i64> [[TMP2]]
+// CHECK: ret <1 x i64> [[VRSHL_V2_I]]
uint64x1_t test_vrshl_u64(uint64x1_t a, int64x1_t b) {
return vrshl_u64(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vrshlq_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vrshlq_s8(
// CHECK: [[VRSHLQ_V_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.srshl.v16i8(<16 x i8> %a, <16 x i8> %b) #4
// CHECK: ret <16 x i8> [[VRSHLQ_V_I]]
int8x16_t test_vrshlq_s8(int8x16_t a, int8x16_t b) {
return vrshlq_s8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vrshlq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vrshlq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VRSHLQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VRSHLQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VRSHLQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.srshl.v8i16(<8 x i16> [[VRSHLQ_V_I]], <8 x i16> [[VRSHLQ_V1_I]]) #4
+// CHECK: [[VRSHLQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.srshl.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: [[VRSHLQ_V3_I:%.*]] = bitcast <8 x i16> [[VRSHLQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VRSHLQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VRSHLQ_V2_I]]
int16x8_t test_vrshlq_s16(int16x8_t a, int16x8_t b) {
return vrshlq_s16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vrshlq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vrshlq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VRSHLQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VRSHLQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VRSHLQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.srshl.v4i32(<4 x i32> [[VRSHLQ_V_I]], <4 x i32> [[VRSHLQ_V1_I]]) #4
+// CHECK: [[VRSHLQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.srshl.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VRSHLQ_V3_I:%.*]] = bitcast <4 x i32> [[VRSHLQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VRSHLQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VRSHLQ_V2_I]]
int32x4_t test_vrshlq_s32(int32x4_t a, int32x4_t b) {
return vrshlq_s32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vrshlq_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vrshlq_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[VRSHLQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VRSHLQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VRSHLQ_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.srshl.v2i64(<2 x i64> [[VRSHLQ_V_I]], <2 x i64> [[VRSHLQ_V1_I]]) #4
+// CHECK: [[VRSHLQ_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.srshl.v2i64(<2 x i64> %a, <2 x i64> %b) #4
// CHECK: [[VRSHLQ_V3_I:%.*]] = bitcast <2 x i64> [[VRSHLQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VRSHLQ_V3_I]] to <2 x i64>
-// CHECK: ret <2 x i64> [[TMP2]]
+// CHECK: ret <2 x i64> [[VRSHLQ_V2_I]]
int64x2_t test_vrshlq_s64(int64x2_t a, int64x2_t b) {
return vrshlq_s64(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vrshlq_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vrshlq_u8(
// CHECK: [[VRSHLQ_V_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.urshl.v16i8(<16 x i8> %a, <16 x i8> %b) #4
// CHECK: ret <16 x i8> [[VRSHLQ_V_I]]
uint8x16_t test_vrshlq_u8(uint8x16_t a, int8x16_t b) {
return vrshlq_u8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vrshlq_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vrshlq_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VRSHLQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VRSHLQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VRSHLQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.urshl.v8i16(<8 x i16> [[VRSHLQ_V_I]], <8 x i16> [[VRSHLQ_V1_I]]) #4
+// CHECK: [[VRSHLQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.urshl.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: [[VRSHLQ_V3_I:%.*]] = bitcast <8 x i16> [[VRSHLQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VRSHLQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VRSHLQ_V2_I]]
uint16x8_t test_vrshlq_u16(uint16x8_t a, int16x8_t b) {
return vrshlq_u16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vrshlq_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vrshlq_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VRSHLQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VRSHLQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VRSHLQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.urshl.v4i32(<4 x i32> [[VRSHLQ_V_I]], <4 x i32> [[VRSHLQ_V1_I]]) #4
+// CHECK: [[VRSHLQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.urshl.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VRSHLQ_V3_I:%.*]] = bitcast <4 x i32> [[VRSHLQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VRSHLQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VRSHLQ_V2_I]]
uint32x4_t test_vrshlq_u32(uint32x4_t a, int32x4_t b) {
return vrshlq_u32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vrshlq_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vrshlq_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[VRSHLQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VRSHLQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VRSHLQ_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.urshl.v2i64(<2 x i64> [[VRSHLQ_V_I]], <2 x i64> [[VRSHLQ_V1_I]]) #4
+// CHECK: [[VRSHLQ_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.urshl.v2i64(<2 x i64> %a, <2 x i64> %b) #4
// CHECK: [[VRSHLQ_V3_I:%.*]] = bitcast <2 x i64> [[VRSHLQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VRSHLQ_V3_I]] to <2 x i64>
-// CHECK: ret <2 x i64> [[TMP2]]
+// CHECK: ret <2 x i64> [[VRSHLQ_V2_I]]
uint64x2_t test_vrshlq_u64(uint64x2_t a, int64x2_t b) {
return vrshlq_u64(a, b);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vqrshl_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vqrshl_s8(
// CHECK: [[VQRSHL_V_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.sqrshl.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VQRSHL_V_I]]
int8x8_t test_vqrshl_s8(int8x8_t a, int8x8_t b) {
return vqrshl_s8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vqrshl_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqrshl_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VQRSHL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQRSHL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQRSHL_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqrshl.v4i16(<4 x i16> [[VQRSHL_V_I]], <4 x i16> [[VQRSHL_V1_I]]) #4
+// CHECK: [[VQRSHL_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqrshl.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VQRSHL_V3_I:%.*]] = bitcast <4 x i16> [[VQRSHL_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQRSHL_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VQRSHL_V2_I]]
int16x4_t test_vqrshl_s16(int16x4_t a, int16x4_t b) {
return vqrshl_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vqrshl_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqrshl_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VQRSHL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQRSHL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQRSHL_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqrshl.v2i32(<2 x i32> [[VQRSHL_V_I]], <2 x i32> [[VQRSHL_V1_I]]) #4
+// CHECK: [[VQRSHL_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqrshl.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VQRSHL_V3_I:%.*]] = bitcast <2 x i32> [[VQRSHL_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQRSHL_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VQRSHL_V2_I]]
int32x2_t test_vqrshl_s32(int32x2_t a, int32x2_t b) {
return vqrshl_s32(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vqrshl_s64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vqrshl_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
-// CHECK: [[VQRSHL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
-// CHECK: [[VQRSHL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x i64>
-// CHECK: [[VQRSHL_V2_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.sqrshl.v1i64(<1 x i64> [[VQRSHL_V_I]], <1 x i64> [[VQRSHL_V1_I]]) #4
+// CHECK: [[VQRSHL_V2_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.sqrshl.v1i64(<1 x i64> %a, <1 x i64> %b) #4
// CHECK: [[VQRSHL_V3_I:%.*]] = bitcast <1 x i64> [[VQRSHL_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQRSHL_V3_I]] to <1 x i64>
-// CHECK: ret <1 x i64> [[TMP2]]
+// CHECK: ret <1 x i64> [[VQRSHL_V2_I]]
int64x1_t test_vqrshl_s64(int64x1_t a, int64x1_t b) {
return vqrshl_s64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vqrshl_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vqrshl_u8(
// CHECK: [[VQRSHL_V_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.uqrshl.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VQRSHL_V_I]]
uint8x8_t test_vqrshl_u8(uint8x8_t a, int8x8_t b) {
return vqrshl_u8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vqrshl_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqrshl_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VQRSHL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQRSHL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQRSHL_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.uqrshl.v4i16(<4 x i16> [[VQRSHL_V_I]], <4 x i16> [[VQRSHL_V1_I]]) #4
+// CHECK: [[VQRSHL_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.uqrshl.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VQRSHL_V3_I:%.*]] = bitcast <4 x i16> [[VQRSHL_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQRSHL_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VQRSHL_V2_I]]
uint16x4_t test_vqrshl_u16(uint16x4_t a, int16x4_t b) {
return vqrshl_u16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vqrshl_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqrshl_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VQRSHL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQRSHL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQRSHL_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.uqrshl.v2i32(<2 x i32> [[VQRSHL_V_I]], <2 x i32> [[VQRSHL_V1_I]]) #4
+// CHECK: [[VQRSHL_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.uqrshl.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VQRSHL_V3_I:%.*]] = bitcast <2 x i32> [[VQRSHL_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQRSHL_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VQRSHL_V2_I]]
uint32x2_t test_vqrshl_u32(uint32x2_t a, int32x2_t b) {
return vqrshl_u32(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vqrshl_u64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vqrshl_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
-// CHECK: [[VQRSHL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
-// CHECK: [[VQRSHL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x i64>
-// CHECK: [[VQRSHL_V2_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.uqrshl.v1i64(<1 x i64> [[VQRSHL_V_I]], <1 x i64> [[VQRSHL_V1_I]]) #4
+// CHECK: [[VQRSHL_V2_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.uqrshl.v1i64(<1 x i64> %a, <1 x i64> %b) #4
// CHECK: [[VQRSHL_V3_I:%.*]] = bitcast <1 x i64> [[VQRSHL_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQRSHL_V3_I]] to <1 x i64>
-// CHECK: ret <1 x i64> [[TMP2]]
+// CHECK: ret <1 x i64> [[VQRSHL_V2_I]]
uint64x1_t test_vqrshl_u64(uint64x1_t a, int64x1_t b) {
return vqrshl_u64(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vqrshlq_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vqrshlq_s8(
// CHECK: [[VQRSHLQ_V_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.sqrshl.v16i8(<16 x i8> %a, <16 x i8> %b) #4
// CHECK: ret <16 x i8> [[VQRSHLQ_V_I]]
int8x16_t test_vqrshlq_s8(int8x16_t a, int8x16_t b) {
return vqrshlq_s8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vqrshlq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqrshlq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VQRSHLQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VQRSHLQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VQRSHLQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.sqrshl.v8i16(<8 x i16> [[VQRSHLQ_V_I]], <8 x i16> [[VQRSHLQ_V1_I]]) #4
+// CHECK: [[VQRSHLQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.sqrshl.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: [[VQRSHLQ_V3_I:%.*]] = bitcast <8 x i16> [[VQRSHLQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQRSHLQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VQRSHLQ_V2_I]]
int16x8_t test_vqrshlq_s16(int16x8_t a, int16x8_t b) {
return vqrshlq_s16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vqrshlq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqrshlq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VQRSHLQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQRSHLQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VQRSHLQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqrshl.v4i32(<4 x i32> [[VQRSHLQ_V_I]], <4 x i32> [[VQRSHLQ_V1_I]]) #4
+// CHECK: [[VQRSHLQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqrshl.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VQRSHLQ_V3_I:%.*]] = bitcast <4 x i32> [[VQRSHLQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQRSHLQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VQRSHLQ_V2_I]]
int32x4_t test_vqrshlq_s32(int32x4_t a, int32x4_t b) {
return vqrshlq_s32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vqrshlq_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vqrshlq_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[VQRSHLQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQRSHLQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VQRSHLQ_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqrshl.v2i64(<2 x i64> [[VQRSHLQ_V_I]], <2 x i64> [[VQRSHLQ_V1_I]]) #4
+// CHECK: [[VQRSHLQ_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqrshl.v2i64(<2 x i64> %a, <2 x i64> %b) #4
// CHECK: [[VQRSHLQ_V3_I:%.*]] = bitcast <2 x i64> [[VQRSHLQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQRSHLQ_V3_I]] to <2 x i64>
-// CHECK: ret <2 x i64> [[TMP2]]
+// CHECK: ret <2 x i64> [[VQRSHLQ_V2_I]]
int64x2_t test_vqrshlq_s64(int64x2_t a, int64x2_t b) {
return vqrshlq_s64(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vqrshlq_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vqrshlq_u8(
// CHECK: [[VQRSHLQ_V_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.uqrshl.v16i8(<16 x i8> %a, <16 x i8> %b) #4
// CHECK: ret <16 x i8> [[VQRSHLQ_V_I]]
uint8x16_t test_vqrshlq_u8(uint8x16_t a, int8x16_t b) {
return vqrshlq_u8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vqrshlq_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqrshlq_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VQRSHLQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VQRSHLQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VQRSHLQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.uqrshl.v8i16(<8 x i16> [[VQRSHLQ_V_I]], <8 x i16> [[VQRSHLQ_V1_I]]) #4
+// CHECK: [[VQRSHLQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.uqrshl.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: [[VQRSHLQ_V3_I:%.*]] = bitcast <8 x i16> [[VQRSHLQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQRSHLQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VQRSHLQ_V2_I]]
uint16x8_t test_vqrshlq_u16(uint16x8_t a, int16x8_t b) {
return vqrshlq_u16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vqrshlq_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqrshlq_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VQRSHLQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQRSHLQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VQRSHLQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.uqrshl.v4i32(<4 x i32> [[VQRSHLQ_V_I]], <4 x i32> [[VQRSHLQ_V1_I]]) #4
+// CHECK: [[VQRSHLQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.uqrshl.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VQRSHLQ_V3_I:%.*]] = bitcast <4 x i32> [[VQRSHLQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQRSHLQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VQRSHLQ_V2_I]]
uint32x4_t test_vqrshlq_u32(uint32x4_t a, int32x4_t b) {
return vqrshlq_u32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vqrshlq_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vqrshlq_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[VQRSHLQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQRSHLQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VQRSHLQ_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.uqrshl.v2i64(<2 x i64> [[VQRSHLQ_V_I]], <2 x i64> [[VQRSHLQ_V1_I]]) #4
+// CHECK: [[VQRSHLQ_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.uqrshl.v2i64(<2 x i64> %a, <2 x i64> %b) #4
// CHECK: [[VQRSHLQ_V3_I:%.*]] = bitcast <2 x i64> [[VQRSHLQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQRSHLQ_V3_I]] to <2 x i64>
-// CHECK: ret <2 x i64> [[TMP2]]
+// CHECK: ret <2 x i64> [[VQRSHLQ_V2_I]]
uint64x2_t test_vqrshlq_u64(uint64x2_t a, int64x2_t b) {
return vqrshlq_u64(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vsli_n_p64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vsli_n_p64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
// CHECK: [[VSLI_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
@@ -4203,10 +3724,10 @@ uint64x2_t test_vqrshlq_u64(uint64x2_t a, int64x2_t b) {
// CHECK: [[VSLI_N2:%.*]] = call <1 x i64> @llvm.aarch64.neon.vsli.v1i64(<1 x i64> [[VSLI_N]], <1 x i64> [[VSLI_N1]], i32 0)
// CHECK: ret <1 x i64> [[VSLI_N2]]
poly64x1_t test_vsli_n_p64(poly64x1_t a, poly64x1_t b) {
- return vsli_n_p64(a, b, 0);
+ return vsli_n_p64(a, b, 0);
}
-// CHECK-LABEL: define <2 x i64> @test_vsliq_n_p64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vsliq_n_p64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
// CHECK: [[VSLI_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
@@ -4214,1054 +3735,878 @@ poly64x1_t test_vsli_n_p64(poly64x1_t a, poly64x1_t b) {
// CHECK: [[VSLI_N2:%.*]] = call <2 x i64> @llvm.aarch64.neon.vsli.v2i64(<2 x i64> [[VSLI_N]], <2 x i64> [[VSLI_N1]], i32 0)
// CHECK: ret <2 x i64> [[VSLI_N2]]
poly64x2_t test_vsliq_n_p64(poly64x2_t a, poly64x2_t b) {
- return vsliq_n_p64(a, b, 0);
+ return vsliq_n_p64(a, b, 0);
}
-// CHECK-LABEL: define <8 x i8> @test_vmax_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vmax_s8(
// CHECK: [[VMAX_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.smax.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VMAX_I]]
int8x8_t test_vmax_s8(int8x8_t a, int8x8_t b) {
return vmax_s8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vmax_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vmax_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VMAX_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMAX1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMAX2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.smax.v4i16(<4 x i16> [[VMAX_I]], <4 x i16> [[VMAX1_I]]) #4
+// CHECK: [[VMAX2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.smax.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: ret <4 x i16> [[VMAX2_I]]
int16x4_t test_vmax_s16(int16x4_t a, int16x4_t b) {
return vmax_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vmax_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vmax_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VMAX_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMAX1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMAX2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.smax.v2i32(<2 x i32> [[VMAX_I]], <2 x i32> [[VMAX1_I]]) #4
+// CHECK: [[VMAX2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.smax.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: ret <2 x i32> [[VMAX2_I]]
int32x2_t test_vmax_s32(int32x2_t a, int32x2_t b) {
return vmax_s32(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vmax_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vmax_u8(
// CHECK: [[VMAX_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.umax.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VMAX_I]]
uint8x8_t test_vmax_u8(uint8x8_t a, uint8x8_t b) {
return vmax_u8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vmax_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vmax_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VMAX_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMAX1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMAX2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.umax.v4i16(<4 x i16> [[VMAX_I]], <4 x i16> [[VMAX1_I]]) #4
+// CHECK: [[VMAX2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.umax.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: ret <4 x i16> [[VMAX2_I]]
uint16x4_t test_vmax_u16(uint16x4_t a, uint16x4_t b) {
return vmax_u16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vmax_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vmax_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VMAX_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMAX1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMAX2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.umax.v2i32(<2 x i32> [[VMAX_I]], <2 x i32> [[VMAX1_I]]) #4
+// CHECK: [[VMAX2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.umax.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: ret <2 x i32> [[VMAX2_I]]
uint32x2_t test_vmax_u32(uint32x2_t a, uint32x2_t b) {
return vmax_u32(a, b);
}
-// CHECK-LABEL: define <2 x float> @test_vmax_f32(<2 x float> %a, <2 x float> %b) #0 {
+// CHECK-LABEL: @test_vmax_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %b to <8 x i8>
-// CHECK: [[VMAX_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VMAX1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK: [[VMAX2_I:%.*]] = call <2 x float> @llvm.aarch64.neon.fmax.v2f32(<2 x float> [[VMAX_I]], <2 x float> [[VMAX1_I]]) #4
+// CHECK: [[VMAX2_I:%.*]] = call <2 x float> @llvm.aarch64.neon.fmax.v2f32(<2 x float> %a, <2 x float> %b) #4
// CHECK: ret <2 x float> [[VMAX2_I]]
float32x2_t test_vmax_f32(float32x2_t a, float32x2_t b) {
return vmax_f32(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vmaxq_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vmaxq_s8(
// CHECK: [[VMAX_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.smax.v16i8(<16 x i8> %a, <16 x i8> %b) #4
// CHECK: ret <16 x i8> [[VMAX_I]]
int8x16_t test_vmaxq_s8(int8x16_t a, int8x16_t b) {
return vmaxq_s8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vmaxq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vmaxq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VMAX_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VMAX1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VMAX2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.smax.v8i16(<8 x i16> [[VMAX_I]], <8 x i16> [[VMAX1_I]]) #4
+// CHECK: [[VMAX2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.smax.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: ret <8 x i16> [[VMAX2_I]]
int16x8_t test_vmaxq_s16(int16x8_t a, int16x8_t b) {
return vmaxq_s16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vmaxq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vmaxq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VMAX_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VMAX1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VMAX2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smax.v4i32(<4 x i32> [[VMAX_I]], <4 x i32> [[VMAX1_I]]) #4
+// CHECK: [[VMAX2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smax.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: ret <4 x i32> [[VMAX2_I]]
int32x4_t test_vmaxq_s32(int32x4_t a, int32x4_t b) {
return vmaxq_s32(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vmaxq_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vmaxq_u8(
// CHECK: [[VMAX_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.umax.v16i8(<16 x i8> %a, <16 x i8> %b) #4
// CHECK: ret <16 x i8> [[VMAX_I]]
uint8x16_t test_vmaxq_u8(uint8x16_t a, uint8x16_t b) {
return vmaxq_u8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vmaxq_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vmaxq_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VMAX_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VMAX1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VMAX2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.umax.v8i16(<8 x i16> [[VMAX_I]], <8 x i16> [[VMAX1_I]]) #4
+// CHECK: [[VMAX2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.umax.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: ret <8 x i16> [[VMAX2_I]]
uint16x8_t test_vmaxq_u16(uint16x8_t a, uint16x8_t b) {
return vmaxq_u16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vmaxq_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vmaxq_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VMAX_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VMAX1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VMAX2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umax.v4i32(<4 x i32> [[VMAX_I]], <4 x i32> [[VMAX1_I]]) #4
+// CHECK: [[VMAX2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umax.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: ret <4 x i32> [[VMAX2_I]]
uint32x4_t test_vmaxq_u32(uint32x4_t a, uint32x4_t b) {
return vmaxq_u32(a, b);
}
-// CHECK-LABEL: define <4 x float> @test_vmaxq_f32(<4 x float> %a, <4 x float> %b) #0 {
+// CHECK-LABEL: @test_vmaxq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %b to <16 x i8>
-// CHECK: [[VMAX_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VMAX1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
-// CHECK: [[VMAX2_I:%.*]] = call <4 x float> @llvm.aarch64.neon.fmax.v4f32(<4 x float> [[VMAX_I]], <4 x float> [[VMAX1_I]]) #4
+// CHECK: [[VMAX2_I:%.*]] = call <4 x float> @llvm.aarch64.neon.fmax.v4f32(<4 x float> %a, <4 x float> %b) #4
// CHECK: ret <4 x float> [[VMAX2_I]]
float32x4_t test_vmaxq_f32(float32x4_t a, float32x4_t b) {
return vmaxq_f32(a, b);
}
-// CHECK-LABEL: define <2 x double> @test_vmaxq_f64(<2 x double> %a, <2 x double> %b) #0 {
+// CHECK-LABEL: @test_vmaxq_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x double> %b to <16 x i8>
-// CHECK: [[VMAX_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VMAX1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x double>
-// CHECK: [[VMAX2_I:%.*]] = call <2 x double> @llvm.aarch64.neon.fmax.v2f64(<2 x double> [[VMAX_I]], <2 x double> [[VMAX1_I]]) #4
+// CHECK: [[VMAX2_I:%.*]] = call <2 x double> @llvm.aarch64.neon.fmax.v2f64(<2 x double> %a, <2 x double> %b) #4
// CHECK: ret <2 x double> [[VMAX2_I]]
float64x2_t test_vmaxq_f64(float64x2_t a, float64x2_t b) {
return vmaxq_f64(a, b);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vmin_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vmin_s8(
// CHECK: [[VMIN_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.smin.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VMIN_I]]
int8x8_t test_vmin_s8(int8x8_t a, int8x8_t b) {
return vmin_s8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vmin_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vmin_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VMIN_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMIN1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMIN2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.smin.v4i16(<4 x i16> [[VMIN_I]], <4 x i16> [[VMIN1_I]]) #4
+// CHECK: [[VMIN2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.smin.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: ret <4 x i16> [[VMIN2_I]]
int16x4_t test_vmin_s16(int16x4_t a, int16x4_t b) {
return vmin_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vmin_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vmin_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VMIN_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMIN1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMIN2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.smin.v2i32(<2 x i32> [[VMIN_I]], <2 x i32> [[VMIN1_I]]) #4
+// CHECK: [[VMIN2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.smin.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: ret <2 x i32> [[VMIN2_I]]
int32x2_t test_vmin_s32(int32x2_t a, int32x2_t b) {
return vmin_s32(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vmin_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vmin_u8(
// CHECK: [[VMIN_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.umin.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VMIN_I]]
uint8x8_t test_vmin_u8(uint8x8_t a, uint8x8_t b) {
return vmin_u8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vmin_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vmin_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VMIN_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMIN1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMIN2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.umin.v4i16(<4 x i16> [[VMIN_I]], <4 x i16> [[VMIN1_I]]) #4
+// CHECK: [[VMIN2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.umin.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: ret <4 x i16> [[VMIN2_I]]
uint16x4_t test_vmin_u16(uint16x4_t a, uint16x4_t b) {
return vmin_u16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vmin_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vmin_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VMIN_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMIN1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMIN2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.umin.v2i32(<2 x i32> [[VMIN_I]], <2 x i32> [[VMIN1_I]]) #4
+// CHECK: [[VMIN2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.umin.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: ret <2 x i32> [[VMIN2_I]]
uint32x2_t test_vmin_u32(uint32x2_t a, uint32x2_t b) {
return vmin_u32(a, b);
}
-// CHECK-LABEL: define <2 x float> @test_vmin_f32(<2 x float> %a, <2 x float> %b) #0 {
+// CHECK-LABEL: @test_vmin_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %b to <8 x i8>
-// CHECK: [[VMIN_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VMIN1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK: [[VMIN2_I:%.*]] = call <2 x float> @llvm.aarch64.neon.fmin.v2f32(<2 x float> [[VMIN_I]], <2 x float> [[VMIN1_I]]) #4
+// CHECK: [[VMIN2_I:%.*]] = call <2 x float> @llvm.aarch64.neon.fmin.v2f32(<2 x float> %a, <2 x float> %b) #4
// CHECK: ret <2 x float> [[VMIN2_I]]
float32x2_t test_vmin_f32(float32x2_t a, float32x2_t b) {
return vmin_f32(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vminq_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vminq_s8(
// CHECK: [[VMIN_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.smin.v16i8(<16 x i8> %a, <16 x i8> %b) #4
// CHECK: ret <16 x i8> [[VMIN_I]]
int8x16_t test_vminq_s8(int8x16_t a, int8x16_t b) {
return vminq_s8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vminq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vminq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VMIN_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VMIN1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VMIN2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.smin.v8i16(<8 x i16> [[VMIN_I]], <8 x i16> [[VMIN1_I]]) #4
+// CHECK: [[VMIN2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.smin.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: ret <8 x i16> [[VMIN2_I]]
int16x8_t test_vminq_s16(int16x8_t a, int16x8_t b) {
return vminq_s16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vminq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vminq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VMIN_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VMIN1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VMIN2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smin.v4i32(<4 x i32> [[VMIN_I]], <4 x i32> [[VMIN1_I]]) #4
+// CHECK: [[VMIN2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smin.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: ret <4 x i32> [[VMIN2_I]]
int32x4_t test_vminq_s32(int32x4_t a, int32x4_t b) {
return vminq_s32(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vminq_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vminq_u8(
// CHECK: [[VMIN_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.umin.v16i8(<16 x i8> %a, <16 x i8> %b) #4
// CHECK: ret <16 x i8> [[VMIN_I]]
uint8x16_t test_vminq_u8(uint8x16_t a, uint8x16_t b) {
return vminq_u8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vminq_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vminq_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VMIN_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VMIN1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VMIN2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.umin.v8i16(<8 x i16> [[VMIN_I]], <8 x i16> [[VMIN1_I]]) #4
+// CHECK: [[VMIN2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.umin.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: ret <8 x i16> [[VMIN2_I]]
uint16x8_t test_vminq_u16(uint16x8_t a, uint16x8_t b) {
return vminq_u16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vminq_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vminq_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VMIN_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VMIN1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VMIN2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umin.v4i32(<4 x i32> [[VMIN_I]], <4 x i32> [[VMIN1_I]]) #4
+// CHECK: [[VMIN2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umin.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: ret <4 x i32> [[VMIN2_I]]
uint32x4_t test_vminq_u32(uint32x4_t a, uint32x4_t b) {
return vminq_u32(a, b);
}
-// CHECK-LABEL: define <4 x float> @test_vminq_f32(<4 x float> %a, <4 x float> %b) #0 {
+// CHECK-LABEL: @test_vminq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %b to <16 x i8>
-// CHECK: [[VMIN_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VMIN1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
-// CHECK: [[VMIN2_I:%.*]] = call <4 x float> @llvm.aarch64.neon.fmin.v4f32(<4 x float> [[VMIN_I]], <4 x float> [[VMIN1_I]]) #4
+// CHECK: [[VMIN2_I:%.*]] = call <4 x float> @llvm.aarch64.neon.fmin.v4f32(<4 x float> %a, <4 x float> %b) #4
// CHECK: ret <4 x float> [[VMIN2_I]]
float32x4_t test_vminq_f32(float32x4_t a, float32x4_t b) {
return vminq_f32(a, b);
}
-// CHECK-LABEL: define <2 x double> @test_vminq_f64(<2 x double> %a, <2 x double> %b) #0 {
+// CHECK-LABEL: @test_vminq_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x double> %b to <16 x i8>
-// CHECK: [[VMIN_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VMIN1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x double>
-// CHECK: [[VMIN2_I:%.*]] = call <2 x double> @llvm.aarch64.neon.fmin.v2f64(<2 x double> [[VMIN_I]], <2 x double> [[VMIN1_I]]) #4
+// CHECK: [[VMIN2_I:%.*]] = call <2 x double> @llvm.aarch64.neon.fmin.v2f64(<2 x double> %a, <2 x double> %b) #4
// CHECK: ret <2 x double> [[VMIN2_I]]
float64x2_t test_vminq_f64(float64x2_t a, float64x2_t b) {
return vminq_f64(a, b);
}
-// CHECK-LABEL: define <2 x float> @test_vmaxnm_f32(<2 x float> %a, <2 x float> %b) #0 {
+// CHECK-LABEL: @test_vmaxnm_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %b to <8 x i8>
-// CHECK: [[VMAXNM_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VMAXNM1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK: [[VMAXNM2_I:%.*]] = call <2 x float> @llvm.aarch64.neon.fmaxnm.v2f32(<2 x float> [[VMAXNM_I]], <2 x float> [[VMAXNM1_I]]) #4
+// CHECK: [[VMAXNM2_I:%.*]] = call <2 x float> @llvm.aarch64.neon.fmaxnm.v2f32(<2 x float> %a, <2 x float> %b) #4
// CHECK: ret <2 x float> [[VMAXNM2_I]]
float32x2_t test_vmaxnm_f32(float32x2_t a, float32x2_t b) {
return vmaxnm_f32(a, b);
}
-// CHECK-LABEL: define <4 x float> @test_vmaxnmq_f32(<4 x float> %a, <4 x float> %b) #0 {
+// CHECK-LABEL: @test_vmaxnmq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %b to <16 x i8>
-// CHECK: [[VMAXNM_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VMAXNM1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
-// CHECK: [[VMAXNM2_I:%.*]] = call <4 x float> @llvm.aarch64.neon.fmaxnm.v4f32(<4 x float> [[VMAXNM_I]], <4 x float> [[VMAXNM1_I]]) #4
+// CHECK: [[VMAXNM2_I:%.*]] = call <4 x float> @llvm.aarch64.neon.fmaxnm.v4f32(<4 x float> %a, <4 x float> %b) #4
// CHECK: ret <4 x float> [[VMAXNM2_I]]
float32x4_t test_vmaxnmq_f32(float32x4_t a, float32x4_t b) {
return vmaxnmq_f32(a, b);
}
-// CHECK-LABEL: define <2 x double> @test_vmaxnmq_f64(<2 x double> %a, <2 x double> %b) #0 {
+// CHECK-LABEL: @test_vmaxnmq_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x double> %b to <16 x i8>
-// CHECK: [[VMAXNM_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VMAXNM1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x double>
-// CHECK: [[VMAXNM2_I:%.*]] = call <2 x double> @llvm.aarch64.neon.fmaxnm.v2f64(<2 x double> [[VMAXNM_I]], <2 x double> [[VMAXNM1_I]]) #4
+// CHECK: [[VMAXNM2_I:%.*]] = call <2 x double> @llvm.aarch64.neon.fmaxnm.v2f64(<2 x double> %a, <2 x double> %b) #4
// CHECK: ret <2 x double> [[VMAXNM2_I]]
float64x2_t test_vmaxnmq_f64(float64x2_t a, float64x2_t b) {
return vmaxnmq_f64(a, b);
}
-// CHECK-LABEL: define <2 x float> @test_vminnm_f32(<2 x float> %a, <2 x float> %b) #0 {
+// CHECK-LABEL: @test_vminnm_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %b to <8 x i8>
-// CHECK: [[VMINNM_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VMINNM1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK: [[VMINNM2_I:%.*]] = call <2 x float> @llvm.aarch64.neon.fminnm.v2f32(<2 x float> [[VMINNM_I]], <2 x float> [[VMINNM1_I]]) #4
+// CHECK: [[VMINNM2_I:%.*]] = call <2 x float> @llvm.aarch64.neon.fminnm.v2f32(<2 x float> %a, <2 x float> %b) #4
// CHECK: ret <2 x float> [[VMINNM2_I]]
float32x2_t test_vminnm_f32(float32x2_t a, float32x2_t b) {
return vminnm_f32(a, b);
}
-// CHECK-LABEL: define <4 x float> @test_vminnmq_f32(<4 x float> %a, <4 x float> %b) #0 {
+// CHECK-LABEL: @test_vminnmq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %b to <16 x i8>
-// CHECK: [[VMINNM_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VMINNM1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
-// CHECK: [[VMINNM2_I:%.*]] = call <4 x float> @llvm.aarch64.neon.fminnm.v4f32(<4 x float> [[VMINNM_I]], <4 x float> [[VMINNM1_I]]) #4
+// CHECK: [[VMINNM2_I:%.*]] = call <4 x float> @llvm.aarch64.neon.fminnm.v4f32(<4 x float> %a, <4 x float> %b) #4
// CHECK: ret <4 x float> [[VMINNM2_I]]
float32x4_t test_vminnmq_f32(float32x4_t a, float32x4_t b) {
return vminnmq_f32(a, b);
}
-// CHECK-LABEL: define <2 x double> @test_vminnmq_f64(<2 x double> %a, <2 x double> %b) #0 {
+// CHECK-LABEL: @test_vminnmq_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x double> %b to <16 x i8>
-// CHECK: [[VMINNM_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VMINNM1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x double>
-// CHECK: [[VMINNM2_I:%.*]] = call <2 x double> @llvm.aarch64.neon.fminnm.v2f64(<2 x double> [[VMINNM_I]], <2 x double> [[VMINNM1_I]]) #4
+// CHECK: [[VMINNM2_I:%.*]] = call <2 x double> @llvm.aarch64.neon.fminnm.v2f64(<2 x double> %a, <2 x double> %b) #4
// CHECK: ret <2 x double> [[VMINNM2_I]]
float64x2_t test_vminnmq_f64(float64x2_t a, float64x2_t b) {
return vminnmq_f64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vpmax_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vpmax_s8(
// CHECK: [[VPMAX_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.smaxp.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VPMAX_I]]
int8x8_t test_vpmax_s8(int8x8_t a, int8x8_t b) {
return vpmax_s8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vpmax_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vpmax_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VPMAX_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VPMAX1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VPMAX2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.smaxp.v4i16(<4 x i16> [[VPMAX_I]], <4 x i16> [[VPMAX1_I]]) #4
+// CHECK: [[VPMAX2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.smaxp.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: ret <4 x i16> [[VPMAX2_I]]
int16x4_t test_vpmax_s16(int16x4_t a, int16x4_t b) {
return vpmax_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vpmax_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vpmax_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VPMAX_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VPMAX1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VPMAX2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.smaxp.v2i32(<2 x i32> [[VPMAX_I]], <2 x i32> [[VPMAX1_I]]) #4
+// CHECK: [[VPMAX2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.smaxp.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: ret <2 x i32> [[VPMAX2_I]]
int32x2_t test_vpmax_s32(int32x2_t a, int32x2_t b) {
return vpmax_s32(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vpmax_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vpmax_u8(
// CHECK: [[VPMAX_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.umaxp.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VPMAX_I]]
uint8x8_t test_vpmax_u8(uint8x8_t a, uint8x8_t b) {
return vpmax_u8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vpmax_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vpmax_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VPMAX_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VPMAX1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VPMAX2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.umaxp.v4i16(<4 x i16> [[VPMAX_I]], <4 x i16> [[VPMAX1_I]]) #4
+// CHECK: [[VPMAX2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.umaxp.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: ret <4 x i16> [[VPMAX2_I]]
uint16x4_t test_vpmax_u16(uint16x4_t a, uint16x4_t b) {
return vpmax_u16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vpmax_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vpmax_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VPMAX_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VPMAX1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VPMAX2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.umaxp.v2i32(<2 x i32> [[VPMAX_I]], <2 x i32> [[VPMAX1_I]]) #4
+// CHECK: [[VPMAX2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.umaxp.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: ret <2 x i32> [[VPMAX2_I]]
uint32x2_t test_vpmax_u32(uint32x2_t a, uint32x2_t b) {
return vpmax_u32(a, b);
}
-// CHECK-LABEL: define <2 x float> @test_vpmax_f32(<2 x float> %a, <2 x float> %b) #0 {
+// CHECK-LABEL: @test_vpmax_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %b to <8 x i8>
-// CHECK: [[VPMAX_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VPMAX1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK: [[VPMAX2_I:%.*]] = call <2 x float> @llvm.aarch64.neon.fmaxp.v2f32(<2 x float> [[VPMAX_I]], <2 x float> [[VPMAX1_I]]) #4
+// CHECK: [[VPMAX2_I:%.*]] = call <2 x float> @llvm.aarch64.neon.fmaxp.v2f32(<2 x float> %a, <2 x float> %b) #4
// CHECK: ret <2 x float> [[VPMAX2_I]]
float32x2_t test_vpmax_f32(float32x2_t a, float32x2_t b) {
return vpmax_f32(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vpmaxq_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vpmaxq_s8(
// CHECK: [[VPMAX_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.smaxp.v16i8(<16 x i8> %a, <16 x i8> %b) #4
// CHECK: ret <16 x i8> [[VPMAX_I]]
int8x16_t test_vpmaxq_s8(int8x16_t a, int8x16_t b) {
return vpmaxq_s8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vpmaxq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vpmaxq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VPMAX_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VPMAX1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VPMAX2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.smaxp.v8i16(<8 x i16> [[VPMAX_I]], <8 x i16> [[VPMAX1_I]]) #4
+// CHECK: [[VPMAX2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.smaxp.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: ret <8 x i16> [[VPMAX2_I]]
int16x8_t test_vpmaxq_s16(int16x8_t a, int16x8_t b) {
return vpmaxq_s16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vpmaxq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vpmaxq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VPMAX_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VPMAX1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VPMAX2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smaxp.v4i32(<4 x i32> [[VPMAX_I]], <4 x i32> [[VPMAX1_I]]) #4
+// CHECK: [[VPMAX2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smaxp.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: ret <4 x i32> [[VPMAX2_I]]
int32x4_t test_vpmaxq_s32(int32x4_t a, int32x4_t b) {
return vpmaxq_s32(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vpmaxq_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vpmaxq_u8(
// CHECK: [[VPMAX_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.umaxp.v16i8(<16 x i8> %a, <16 x i8> %b) #4
// CHECK: ret <16 x i8> [[VPMAX_I]]
uint8x16_t test_vpmaxq_u8(uint8x16_t a, uint8x16_t b) {
return vpmaxq_u8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vpmaxq_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vpmaxq_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VPMAX_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VPMAX1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VPMAX2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.umaxp.v8i16(<8 x i16> [[VPMAX_I]], <8 x i16> [[VPMAX1_I]]) #4
+// CHECK: [[VPMAX2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.umaxp.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: ret <8 x i16> [[VPMAX2_I]]
uint16x8_t test_vpmaxq_u16(uint16x8_t a, uint16x8_t b) {
return vpmaxq_u16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vpmaxq_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vpmaxq_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VPMAX_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VPMAX1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VPMAX2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umaxp.v4i32(<4 x i32> [[VPMAX_I]], <4 x i32> [[VPMAX1_I]]) #4
+// CHECK: [[VPMAX2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umaxp.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: ret <4 x i32> [[VPMAX2_I]]
uint32x4_t test_vpmaxq_u32(uint32x4_t a, uint32x4_t b) {
return vpmaxq_u32(a, b);
}
-// CHECK-LABEL: define <4 x float> @test_vpmaxq_f32(<4 x float> %a, <4 x float> %b) #0 {
+// CHECK-LABEL: @test_vpmaxq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %b to <16 x i8>
-// CHECK: [[VPMAX_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VPMAX1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
-// CHECK: [[VPMAX2_I:%.*]] = call <4 x float> @llvm.aarch64.neon.fmaxp.v4f32(<4 x float> [[VPMAX_I]], <4 x float> [[VPMAX1_I]]) #4
+// CHECK: [[VPMAX2_I:%.*]] = call <4 x float> @llvm.aarch64.neon.fmaxp.v4f32(<4 x float> %a, <4 x float> %b) #4
// CHECK: ret <4 x float> [[VPMAX2_I]]
float32x4_t test_vpmaxq_f32(float32x4_t a, float32x4_t b) {
return vpmaxq_f32(a, b);
}
-// CHECK-LABEL: define <2 x double> @test_vpmaxq_f64(<2 x double> %a, <2 x double> %b) #0 {
+// CHECK-LABEL: @test_vpmaxq_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x double> %b to <16 x i8>
-// CHECK: [[VPMAX_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VPMAX1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x double>
-// CHECK: [[VPMAX2_I:%.*]] = call <2 x double> @llvm.aarch64.neon.fmaxp.v2f64(<2 x double> [[VPMAX_I]], <2 x double> [[VPMAX1_I]]) #4
+// CHECK: [[VPMAX2_I:%.*]] = call <2 x double> @llvm.aarch64.neon.fmaxp.v2f64(<2 x double> %a, <2 x double> %b) #4
// CHECK: ret <2 x double> [[VPMAX2_I]]
float64x2_t test_vpmaxq_f64(float64x2_t a, float64x2_t b) {
return vpmaxq_f64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vpmin_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vpmin_s8(
// CHECK: [[VPMIN_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.sminp.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VPMIN_I]]
int8x8_t test_vpmin_s8(int8x8_t a, int8x8_t b) {
return vpmin_s8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vpmin_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vpmin_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VPMIN_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VPMIN1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VPMIN2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sminp.v4i16(<4 x i16> [[VPMIN_I]], <4 x i16> [[VPMIN1_I]]) #4
+// CHECK: [[VPMIN2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sminp.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: ret <4 x i16> [[VPMIN2_I]]
int16x4_t test_vpmin_s16(int16x4_t a, int16x4_t b) {
return vpmin_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vpmin_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vpmin_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VPMIN_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VPMIN1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VPMIN2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sminp.v2i32(<2 x i32> [[VPMIN_I]], <2 x i32> [[VPMIN1_I]]) #4
+// CHECK: [[VPMIN2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sminp.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: ret <2 x i32> [[VPMIN2_I]]
int32x2_t test_vpmin_s32(int32x2_t a, int32x2_t b) {
return vpmin_s32(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vpmin_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vpmin_u8(
// CHECK: [[VPMIN_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.uminp.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VPMIN_I]]
uint8x8_t test_vpmin_u8(uint8x8_t a, uint8x8_t b) {
return vpmin_u8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vpmin_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vpmin_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VPMIN_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VPMIN1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VPMIN2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.uminp.v4i16(<4 x i16> [[VPMIN_I]], <4 x i16> [[VPMIN1_I]]) #4
+// CHECK: [[VPMIN2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.uminp.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: ret <4 x i16> [[VPMIN2_I]]
uint16x4_t test_vpmin_u16(uint16x4_t a, uint16x4_t b) {
return vpmin_u16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vpmin_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vpmin_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VPMIN_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VPMIN1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VPMIN2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.uminp.v2i32(<2 x i32> [[VPMIN_I]], <2 x i32> [[VPMIN1_I]]) #4
+// CHECK: [[VPMIN2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.uminp.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: ret <2 x i32> [[VPMIN2_I]]
uint32x2_t test_vpmin_u32(uint32x2_t a, uint32x2_t b) {
return vpmin_u32(a, b);
}
-// CHECK-LABEL: define <2 x float> @test_vpmin_f32(<2 x float> %a, <2 x float> %b) #0 {
+// CHECK-LABEL: @test_vpmin_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %b to <8 x i8>
-// CHECK: [[VPMIN_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VPMIN1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK: [[VPMIN2_I:%.*]] = call <2 x float> @llvm.aarch64.neon.fminp.v2f32(<2 x float> [[VPMIN_I]], <2 x float> [[VPMIN1_I]]) #4
+// CHECK: [[VPMIN2_I:%.*]] = call <2 x float> @llvm.aarch64.neon.fminp.v2f32(<2 x float> %a, <2 x float> %b) #4
// CHECK: ret <2 x float> [[VPMIN2_I]]
float32x2_t test_vpmin_f32(float32x2_t a, float32x2_t b) {
return vpmin_f32(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vpminq_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vpminq_s8(
// CHECK: [[VPMIN_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.sminp.v16i8(<16 x i8> %a, <16 x i8> %b) #4
// CHECK: ret <16 x i8> [[VPMIN_I]]
int8x16_t test_vpminq_s8(int8x16_t a, int8x16_t b) {
return vpminq_s8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vpminq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vpminq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VPMIN_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VPMIN1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VPMIN2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.sminp.v8i16(<8 x i16> [[VPMIN_I]], <8 x i16> [[VPMIN1_I]]) #4
+// CHECK: [[VPMIN2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.sminp.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: ret <8 x i16> [[VPMIN2_I]]
int16x8_t test_vpminq_s16(int16x8_t a, int16x8_t b) {
return vpminq_s16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vpminq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vpminq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VPMIN_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VPMIN1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VPMIN2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sminp.v4i32(<4 x i32> [[VPMIN_I]], <4 x i32> [[VPMIN1_I]]) #4
+// CHECK: [[VPMIN2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sminp.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: ret <4 x i32> [[VPMIN2_I]]
int32x4_t test_vpminq_s32(int32x4_t a, int32x4_t b) {
return vpminq_s32(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vpminq_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vpminq_u8(
// CHECK: [[VPMIN_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.uminp.v16i8(<16 x i8> %a, <16 x i8> %b) #4
// CHECK: ret <16 x i8> [[VPMIN_I]]
uint8x16_t test_vpminq_u8(uint8x16_t a, uint8x16_t b) {
return vpminq_u8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vpminq_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vpminq_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VPMIN_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VPMIN1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VPMIN2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.uminp.v8i16(<8 x i16> [[VPMIN_I]], <8 x i16> [[VPMIN1_I]]) #4
+// CHECK: [[VPMIN2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.uminp.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: ret <8 x i16> [[VPMIN2_I]]
uint16x8_t test_vpminq_u16(uint16x8_t a, uint16x8_t b) {
return vpminq_u16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vpminq_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vpminq_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VPMIN_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VPMIN1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VPMIN2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.uminp.v4i32(<4 x i32> [[VPMIN_I]], <4 x i32> [[VPMIN1_I]]) #4
+// CHECK: [[VPMIN2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.uminp.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: ret <4 x i32> [[VPMIN2_I]]
uint32x4_t test_vpminq_u32(uint32x4_t a, uint32x4_t b) {
return vpminq_u32(a, b);
}
-// CHECK-LABEL: define <4 x float> @test_vpminq_f32(<4 x float> %a, <4 x float> %b) #0 {
+// CHECK-LABEL: @test_vpminq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %b to <16 x i8>
-// CHECK: [[VPMIN_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VPMIN1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
-// CHECK: [[VPMIN2_I:%.*]] = call <4 x float> @llvm.aarch64.neon.fminp.v4f32(<4 x float> [[VPMIN_I]], <4 x float> [[VPMIN1_I]]) #4
+// CHECK: [[VPMIN2_I:%.*]] = call <4 x float> @llvm.aarch64.neon.fminp.v4f32(<4 x float> %a, <4 x float> %b) #4
// CHECK: ret <4 x float> [[VPMIN2_I]]
float32x4_t test_vpminq_f32(float32x4_t a, float32x4_t b) {
return vpminq_f32(a, b);
}
-// CHECK-LABEL: define <2 x double> @test_vpminq_f64(<2 x double> %a, <2 x double> %b) #0 {
+// CHECK-LABEL: @test_vpminq_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x double> %b to <16 x i8>
-// CHECK: [[VPMIN_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VPMIN1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x double>
-// CHECK: [[VPMIN2_I:%.*]] = call <2 x double> @llvm.aarch64.neon.fminp.v2f64(<2 x double> [[VPMIN_I]], <2 x double> [[VPMIN1_I]]) #4
+// CHECK: [[VPMIN2_I:%.*]] = call <2 x double> @llvm.aarch64.neon.fminp.v2f64(<2 x double> %a, <2 x double> %b) #4
// CHECK: ret <2 x double> [[VPMIN2_I]]
float64x2_t test_vpminq_f64(float64x2_t a, float64x2_t b) {
return vpminq_f64(a, b);
}
-// CHECK-LABEL: define <2 x float> @test_vpmaxnm_f32(<2 x float> %a, <2 x float> %b) #0 {
+// CHECK-LABEL: @test_vpmaxnm_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %b to <8 x i8>
-// CHECK: [[VPMAXNM_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VPMAXNM1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK: [[VPMAXNM2_I:%.*]] = call <2 x float> @llvm.aarch64.neon.fmaxnmp.v2f32(<2 x float> [[VPMAXNM_I]], <2 x float> [[VPMAXNM1_I]]) #4
+// CHECK: [[VPMAXNM2_I:%.*]] = call <2 x float> @llvm.aarch64.neon.fmaxnmp.v2f32(<2 x float> %a, <2 x float> %b) #4
// CHECK: ret <2 x float> [[VPMAXNM2_I]]
float32x2_t test_vpmaxnm_f32(float32x2_t a, float32x2_t b) {
return vpmaxnm_f32(a, b);
}
-// CHECK-LABEL: define <4 x float> @test_vpmaxnmq_f32(<4 x float> %a, <4 x float> %b) #0 {
+// CHECK-LABEL: @test_vpmaxnmq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %b to <16 x i8>
-// CHECK: [[VPMAXNM_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VPMAXNM1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
-// CHECK: [[VPMAXNM2_I:%.*]] = call <4 x float> @llvm.aarch64.neon.fmaxnmp.v4f32(<4 x float> [[VPMAXNM_I]], <4 x float> [[VPMAXNM1_I]]) #4
+// CHECK: [[VPMAXNM2_I:%.*]] = call <4 x float> @llvm.aarch64.neon.fmaxnmp.v4f32(<4 x float> %a, <4 x float> %b) #4
// CHECK: ret <4 x float> [[VPMAXNM2_I]]
float32x4_t test_vpmaxnmq_f32(float32x4_t a, float32x4_t b) {
return vpmaxnmq_f32(a, b);
}
-// CHECK-LABEL: define <2 x double> @test_vpmaxnmq_f64(<2 x double> %a, <2 x double> %b) #0 {
+// CHECK-LABEL: @test_vpmaxnmq_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x double> %b to <16 x i8>
-// CHECK: [[VPMAXNM_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VPMAXNM1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x double>
-// CHECK: [[VPMAXNM2_I:%.*]] = call <2 x double> @llvm.aarch64.neon.fmaxnmp.v2f64(<2 x double> [[VPMAXNM_I]], <2 x double> [[VPMAXNM1_I]]) #4
+// CHECK: [[VPMAXNM2_I:%.*]] = call <2 x double> @llvm.aarch64.neon.fmaxnmp.v2f64(<2 x double> %a, <2 x double> %b) #4
// CHECK: ret <2 x double> [[VPMAXNM2_I]]
float64x2_t test_vpmaxnmq_f64(float64x2_t a, float64x2_t b) {
return vpmaxnmq_f64(a, b);
}
-// CHECK-LABEL: define <2 x float> @test_vpminnm_f32(<2 x float> %a, <2 x float> %b) #0 {
+// CHECK-LABEL: @test_vpminnm_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %b to <8 x i8>
-// CHECK: [[VPMINNM_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VPMINNM1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK: [[VPMINNM2_I:%.*]] = call <2 x float> @llvm.aarch64.neon.fminnmp.v2f32(<2 x float> [[VPMINNM_I]], <2 x float> [[VPMINNM1_I]]) #4
+// CHECK: [[VPMINNM2_I:%.*]] = call <2 x float> @llvm.aarch64.neon.fminnmp.v2f32(<2 x float> %a, <2 x float> %b) #4
// CHECK: ret <2 x float> [[VPMINNM2_I]]
float32x2_t test_vpminnm_f32(float32x2_t a, float32x2_t b) {
return vpminnm_f32(a, b);
}
-// CHECK-LABEL: define <4 x float> @test_vpminnmq_f32(<4 x float> %a, <4 x float> %b) #0 {
+// CHECK-LABEL: @test_vpminnmq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %b to <16 x i8>
-// CHECK: [[VPMINNM_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VPMINNM1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
-// CHECK: [[VPMINNM2_I:%.*]] = call <4 x float> @llvm.aarch64.neon.fminnmp.v4f32(<4 x float> [[VPMINNM_I]], <4 x float> [[VPMINNM1_I]]) #4
+// CHECK: [[VPMINNM2_I:%.*]] = call <4 x float> @llvm.aarch64.neon.fminnmp.v4f32(<4 x float> %a, <4 x float> %b) #4
// CHECK: ret <4 x float> [[VPMINNM2_I]]
float32x4_t test_vpminnmq_f32(float32x4_t a, float32x4_t b) {
return vpminnmq_f32(a, b);
}
-// CHECK-LABEL: define <2 x double> @test_vpminnmq_f64(<2 x double> %a, <2 x double> %b) #0 {
+// CHECK-LABEL: @test_vpminnmq_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x double> %b to <16 x i8>
-// CHECK: [[VPMINNM_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VPMINNM1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x double>
-// CHECK: [[VPMINNM2_I:%.*]] = call <2 x double> @llvm.aarch64.neon.fminnmp.v2f64(<2 x double> [[VPMINNM_I]], <2 x double> [[VPMINNM1_I]]) #4
+// CHECK: [[VPMINNM2_I:%.*]] = call <2 x double> @llvm.aarch64.neon.fminnmp.v2f64(<2 x double> %a, <2 x double> %b) #4
// CHECK: ret <2 x double> [[VPMINNM2_I]]
float64x2_t test_vpminnmq_f64(float64x2_t a, float64x2_t b) {
return vpminnmq_f64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vpadd_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vpadd_s8(
// CHECK: [[VPADD_V_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.addp.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VPADD_V_I]]
int8x8_t test_vpadd_s8(int8x8_t a, int8x8_t b) {
return vpadd_s8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vpadd_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vpadd_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VPADD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VPADD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VPADD_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.addp.v4i16(<4 x i16> [[VPADD_V_I]], <4 x i16> [[VPADD_V1_I]]) #4
+// CHECK: [[VPADD_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.addp.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VPADD_V3_I:%.*]] = bitcast <4 x i16> [[VPADD_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VPADD_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VPADD_V2_I]]
int16x4_t test_vpadd_s16(int16x4_t a, int16x4_t b) {
return vpadd_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vpadd_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vpadd_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VPADD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VPADD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VPADD_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.addp.v2i32(<2 x i32> [[VPADD_V_I]], <2 x i32> [[VPADD_V1_I]]) #4
+// CHECK: [[VPADD_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.addp.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VPADD_V3_I:%.*]] = bitcast <2 x i32> [[VPADD_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VPADD_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VPADD_V2_I]]
int32x2_t test_vpadd_s32(int32x2_t a, int32x2_t b) {
return vpadd_s32(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vpadd_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vpadd_u8(
// CHECK: [[VPADD_V_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.addp.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VPADD_V_I]]
uint8x8_t test_vpadd_u8(uint8x8_t a, uint8x8_t b) {
return vpadd_u8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vpadd_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vpadd_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VPADD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VPADD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VPADD_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.addp.v4i16(<4 x i16> [[VPADD_V_I]], <4 x i16> [[VPADD_V1_I]]) #4
+// CHECK: [[VPADD_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.addp.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VPADD_V3_I:%.*]] = bitcast <4 x i16> [[VPADD_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VPADD_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VPADD_V2_I]]
uint16x4_t test_vpadd_u16(uint16x4_t a, uint16x4_t b) {
return vpadd_u16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vpadd_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vpadd_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VPADD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VPADD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VPADD_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.addp.v2i32(<2 x i32> [[VPADD_V_I]], <2 x i32> [[VPADD_V1_I]]) #4
+// CHECK: [[VPADD_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.addp.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VPADD_V3_I:%.*]] = bitcast <2 x i32> [[VPADD_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VPADD_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VPADD_V2_I]]
uint32x2_t test_vpadd_u32(uint32x2_t a, uint32x2_t b) {
return vpadd_u32(a, b);
}
-// CHECK-LABEL: define <2 x float> @test_vpadd_f32(<2 x float> %a, <2 x float> %b) #0 {
+// CHECK-LABEL: @test_vpadd_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %b to <8 x i8>
-// CHECK: [[VPADD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VPADD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK: [[VPADD_V2_I:%.*]] = call <2 x float> @llvm.aarch64.neon.addp.v2f32(<2 x float> [[VPADD_V_I]], <2 x float> [[VPADD_V1_I]]) #4
+// CHECK: [[VPADD_V2_I:%.*]] = call <2 x float> @llvm.aarch64.neon.addp.v2f32(<2 x float> %a, <2 x float> %b) #4
// CHECK: [[VPADD_V3_I:%.*]] = bitcast <2 x float> [[VPADD_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VPADD_V3_I]] to <2 x float>
-// CHECK: ret <2 x float> [[TMP2]]
+// CHECK: ret <2 x float> [[VPADD_V2_I]]
float32x2_t test_vpadd_f32(float32x2_t a, float32x2_t b) {
return vpadd_f32(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vpaddq_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vpaddq_s8(
// CHECK: [[VPADDQ_V_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.addp.v16i8(<16 x i8> %a, <16 x i8> %b) #4
// CHECK: ret <16 x i8> [[VPADDQ_V_I]]
int8x16_t test_vpaddq_s8(int8x16_t a, int8x16_t b) {
return vpaddq_s8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vpaddq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vpaddq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VPADDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VPADDQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VPADDQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.addp.v8i16(<8 x i16> [[VPADDQ_V_I]], <8 x i16> [[VPADDQ_V1_I]]) #4
+// CHECK: [[VPADDQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.addp.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: [[VPADDQ_V3_I:%.*]] = bitcast <8 x i16> [[VPADDQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VPADDQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VPADDQ_V2_I]]
int16x8_t test_vpaddq_s16(int16x8_t a, int16x8_t b) {
return vpaddq_s16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vpaddq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vpaddq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VPADDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VPADDQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VPADDQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.addp.v4i32(<4 x i32> [[VPADDQ_V_I]], <4 x i32> [[VPADDQ_V1_I]]) #4
+// CHECK: [[VPADDQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.addp.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VPADDQ_V3_I:%.*]] = bitcast <4 x i32> [[VPADDQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VPADDQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VPADDQ_V2_I]]
int32x4_t test_vpaddq_s32(int32x4_t a, int32x4_t b) {
return vpaddq_s32(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vpaddq_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vpaddq_u8(
// CHECK: [[VPADDQ_V_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.addp.v16i8(<16 x i8> %a, <16 x i8> %b) #4
// CHECK: ret <16 x i8> [[VPADDQ_V_I]]
uint8x16_t test_vpaddq_u8(uint8x16_t a, uint8x16_t b) {
return vpaddq_u8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vpaddq_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vpaddq_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VPADDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VPADDQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VPADDQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.addp.v8i16(<8 x i16> [[VPADDQ_V_I]], <8 x i16> [[VPADDQ_V1_I]]) #4
+// CHECK: [[VPADDQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.addp.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: [[VPADDQ_V3_I:%.*]] = bitcast <8 x i16> [[VPADDQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VPADDQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VPADDQ_V2_I]]
uint16x8_t test_vpaddq_u16(uint16x8_t a, uint16x8_t b) {
return vpaddq_u16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vpaddq_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vpaddq_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VPADDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VPADDQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VPADDQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.addp.v4i32(<4 x i32> [[VPADDQ_V_I]], <4 x i32> [[VPADDQ_V1_I]]) #4
+// CHECK: [[VPADDQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.addp.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VPADDQ_V3_I:%.*]] = bitcast <4 x i32> [[VPADDQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VPADDQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VPADDQ_V2_I]]
uint32x4_t test_vpaddq_u32(uint32x4_t a, uint32x4_t b) {
return vpaddq_u32(a, b);
}
-// CHECK-LABEL: define <4 x float> @test_vpaddq_f32(<4 x float> %a, <4 x float> %b) #0 {
+// CHECK-LABEL: @test_vpaddq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %b to <16 x i8>
-// CHECK: [[VPADDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VPADDQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
-// CHECK: [[VPADDQ_V2_I:%.*]] = call <4 x float> @llvm.aarch64.neon.addp.v4f32(<4 x float> [[VPADDQ_V_I]], <4 x float> [[VPADDQ_V1_I]]) #4
+// CHECK: [[VPADDQ_V2_I:%.*]] = call <4 x float> @llvm.aarch64.neon.addp.v4f32(<4 x float> %a, <4 x float> %b) #4
// CHECK: [[VPADDQ_V3_I:%.*]] = bitcast <4 x float> [[VPADDQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VPADDQ_V3_I]] to <4 x float>
-// CHECK: ret <4 x float> [[TMP2]]
+// CHECK: ret <4 x float> [[VPADDQ_V2_I]]
float32x4_t test_vpaddq_f32(float32x4_t a, float32x4_t b) {
return vpaddq_f32(a, b);
}
-// CHECK-LABEL: define <2 x double> @test_vpaddq_f64(<2 x double> %a, <2 x double> %b) #0 {
+// CHECK-LABEL: @test_vpaddq_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x double> %b to <16 x i8>
-// CHECK: [[VPADDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VPADDQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x double>
-// CHECK: [[VPADDQ_V2_I:%.*]] = call <2 x double> @llvm.aarch64.neon.addp.v2f64(<2 x double> [[VPADDQ_V_I]], <2 x double> [[VPADDQ_V1_I]]) #4
+// CHECK: [[VPADDQ_V2_I:%.*]] = call <2 x double> @llvm.aarch64.neon.addp.v2f64(<2 x double> %a, <2 x double> %b) #4
// CHECK: [[VPADDQ_V3_I:%.*]] = bitcast <2 x double> [[VPADDQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VPADDQ_V3_I]] to <2 x double>
-// CHECK: ret <2 x double> [[TMP2]]
+// CHECK: ret <2 x double> [[VPADDQ_V2_I]]
float64x2_t test_vpaddq_f64(float64x2_t a, float64x2_t b) {
return vpaddq_f64(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vqdmulh_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqdmulh_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VQDMULH_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQDMULH_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMULH_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqdmulh.v4i16(<4 x i16> [[VQDMULH_V_I]], <4 x i16> [[VQDMULH_V1_I]]) #4
+// CHECK: [[VQDMULH_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqdmulh.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VQDMULH_V3_I:%.*]] = bitcast <4 x i16> [[VQDMULH_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQDMULH_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VQDMULH_V2_I]]
int16x4_t test_vqdmulh_s16(int16x4_t a, int16x4_t b) {
return vqdmulh_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vqdmulh_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqdmulh_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VQDMULH_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQDMULH_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMULH_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqdmulh.v2i32(<2 x i32> [[VQDMULH_V_I]], <2 x i32> [[VQDMULH_V1_I]]) #4
+// CHECK: [[VQDMULH_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqdmulh.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VQDMULH_V3_I:%.*]] = bitcast <2 x i32> [[VQDMULH_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQDMULH_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VQDMULH_V2_I]]
int32x2_t test_vqdmulh_s32(int32x2_t a, int32x2_t b) {
return vqdmulh_s32(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vqdmulhq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqdmulhq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VQDMULHQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VQDMULHQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VQDMULHQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.sqdmulh.v8i16(<8 x i16> [[VQDMULHQ_V_I]], <8 x i16> [[VQDMULHQ_V1_I]]) #4
+// CHECK: [[VQDMULHQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.sqdmulh.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: [[VQDMULHQ_V3_I:%.*]] = bitcast <8 x i16> [[VQDMULHQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQDMULHQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VQDMULHQ_V2_I]]
int16x8_t test_vqdmulhq_s16(int16x8_t a, int16x8_t b) {
return vqdmulhq_s16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vqdmulhq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqdmulhq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VQDMULHQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQDMULHQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VQDMULHQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmulh.v4i32(<4 x i32> [[VQDMULHQ_V_I]], <4 x i32> [[VQDMULHQ_V1_I]]) #4
+// CHECK: [[VQDMULHQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmulh.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VQDMULHQ_V3_I:%.*]] = bitcast <4 x i32> [[VQDMULHQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQDMULHQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VQDMULHQ_V2_I]]
int32x4_t test_vqdmulhq_s32(int32x4_t a, int32x4_t b) {
return vqdmulhq_s32(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vqrdmulh_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqrdmulh_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VQRDMULH_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQRDMULH_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQRDMULH_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqrdmulh.v4i16(<4 x i16> [[VQRDMULH_V_I]], <4 x i16> [[VQRDMULH_V1_I]]) #4
+// CHECK: [[VQRDMULH_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqrdmulh.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VQRDMULH_V3_I:%.*]] = bitcast <4 x i16> [[VQRDMULH_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQRDMULH_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VQRDMULH_V2_I]]
int16x4_t test_vqrdmulh_s16(int16x4_t a, int16x4_t b) {
return vqrdmulh_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vqrdmulh_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqrdmulh_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VQRDMULH_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQRDMULH_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQRDMULH_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqrdmulh.v2i32(<2 x i32> [[VQRDMULH_V_I]], <2 x i32> [[VQRDMULH_V1_I]]) #4
+// CHECK: [[VQRDMULH_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqrdmulh.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VQRDMULH_V3_I:%.*]] = bitcast <2 x i32> [[VQRDMULH_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQRDMULH_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VQRDMULH_V2_I]]
int32x2_t test_vqrdmulh_s32(int32x2_t a, int32x2_t b) {
return vqrdmulh_s32(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vqrdmulhq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqrdmulhq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VQRDMULHQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VQRDMULHQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VQRDMULHQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.sqrdmulh.v8i16(<8 x i16> [[VQRDMULHQ_V_I]], <8 x i16> [[VQRDMULHQ_V1_I]]) #4
+// CHECK: [[VQRDMULHQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.sqrdmulh.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: [[VQRDMULHQ_V3_I:%.*]] = bitcast <8 x i16> [[VQRDMULHQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQRDMULHQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VQRDMULHQ_V2_I]]
int16x8_t test_vqrdmulhq_s16(int16x8_t a, int16x8_t b) {
return vqrdmulhq_s16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vqrdmulhq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqrdmulhq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VQRDMULHQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQRDMULHQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VQRDMULHQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqrdmulh.v4i32(<4 x i32> [[VQRDMULHQ_V_I]], <4 x i32> [[VQRDMULHQ_V1_I]]) #4
+// CHECK: [[VQRDMULHQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqrdmulh.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VQRDMULHQ_V3_I:%.*]] = bitcast <4 x i32> [[VQRDMULHQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQRDMULHQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VQRDMULHQ_V2_I]]
int32x4_t test_vqrdmulhq_s32(int32x4_t a, int32x4_t b) {
return vqrdmulhq_s32(a, b);
}
-// CHECK-LABEL: define <2 x float> @test_vmulx_f32(<2 x float> %a, <2 x float> %b) #0 {
+// CHECK-LABEL: @test_vmulx_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %b to <8 x i8>
-// CHECK: [[VMULX_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VMULX1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK: [[VMULX2_I:%.*]] = call <2 x float> @llvm.aarch64.neon.fmulx.v2f32(<2 x float> [[VMULX_I]], <2 x float> [[VMULX1_I]]) #4
+// CHECK: [[VMULX2_I:%.*]] = call <2 x float> @llvm.aarch64.neon.fmulx.v2f32(<2 x float> %a, <2 x float> %b) #4
// CHECK: ret <2 x float> [[VMULX2_I]]
float32x2_t test_vmulx_f32(float32x2_t a, float32x2_t b) {
return vmulx_f32(a, b);
}
-// CHECK-LABEL: define <4 x float> @test_vmulxq_f32(<4 x float> %a, <4 x float> %b) #0 {
+// CHECK-LABEL: @test_vmulxq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %b to <16 x i8>
-// CHECK: [[VMULX_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VMULX1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
-// CHECK: [[VMULX2_I:%.*]] = call <4 x float> @llvm.aarch64.neon.fmulx.v4f32(<4 x float> [[VMULX_I]], <4 x float> [[VMULX1_I]]) #4
+// CHECK: [[VMULX2_I:%.*]] = call <4 x float> @llvm.aarch64.neon.fmulx.v4f32(<4 x float> %a, <4 x float> %b) #4
// CHECK: ret <4 x float> [[VMULX2_I]]
float32x4_t test_vmulxq_f32(float32x4_t a, float32x4_t b) {
return vmulxq_f32(a, b);
}
-// CHECK-LABEL: define <2 x double> @test_vmulxq_f64(<2 x double> %a, <2 x double> %b) #0 {
+// CHECK-LABEL: @test_vmulxq_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x double> %b to <16 x i8>
-// CHECK: [[VMULX_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VMULX1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x double>
-// CHECK: [[VMULX2_I:%.*]] = call <2 x double> @llvm.aarch64.neon.fmulx.v2f64(<2 x double> [[VMULX_I]], <2 x double> [[VMULX1_I]]) #4
+// CHECK: [[VMULX2_I:%.*]] = call <2 x double> @llvm.aarch64.neon.fmulx.v2f64(<2 x double> %a, <2 x double> %b) #4
// CHECK: ret <2 x double> [[VMULX2_I]]
float64x2_t test_vmulxq_f64(float64x2_t a, float64x2_t b) {
return vmulxq_f64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vshl_n_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vshl_n_s8(
// CHECK: [[VSHL_N:%.*]] = shl <8 x i8> %a, <i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3>
// CHECK: ret <8 x i8> [[VSHL_N]]
int8x8_t test_vshl_n_s8(int8x8_t a) {
return vshl_n_s8(a, 3);
}
-// CHECK-LABEL: define <4 x i16> @test_vshl_n_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vshl_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
// CHECK: [[VSHL_N:%.*]] = shl <4 x i16> [[TMP1]], <i16 3, i16 3, i16 3, i16 3>
@@ -5270,7 +4615,7 @@ int16x4_t test_vshl_n_s16(int16x4_t a) {
return vshl_n_s16(a, 3);
}
-// CHECK-LABEL: define <2 x i32> @test_vshl_n_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vshl_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
// CHECK: [[VSHL_N:%.*]] = shl <2 x i32> [[TMP1]], <i32 3, i32 3>
@@ -5279,14 +4624,14 @@ int32x2_t test_vshl_n_s32(int32x2_t a) {
return vshl_n_s32(a, 3);
}
-// CHECK-LABEL: define <16 x i8> @test_vshlq_n_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vshlq_n_s8(
// CHECK: [[VSHL_N:%.*]] = shl <16 x i8> %a, <i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3>
// CHECK: ret <16 x i8> [[VSHL_N]]
int8x16_t test_vshlq_n_s8(int8x16_t a) {
return vshlq_n_s8(a, 3);
}
-// CHECK-LABEL: define <8 x i16> @test_vshlq_n_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vshlq_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VSHL_N:%.*]] = shl <8 x i16> [[TMP1]], <i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3>
@@ -5295,7 +4640,7 @@ int16x8_t test_vshlq_n_s16(int16x8_t a) {
return vshlq_n_s16(a, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vshlq_n_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vshlq_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VSHL_N:%.*]] = shl <4 x i32> [[TMP1]], <i32 3, i32 3, i32 3, i32 3>
@@ -5304,7 +4649,7 @@ int32x4_t test_vshlq_n_s32(int32x4_t a) {
return vshlq_n_s32(a, 3);
}
-// CHECK-LABEL: define <2 x i64> @test_vshlq_n_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vshlq_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VSHL_N:%.*]] = shl <2 x i64> [[TMP1]], <i64 3, i64 3>
@@ -5313,14 +4658,14 @@ int64x2_t test_vshlq_n_s64(int64x2_t a) {
return vshlq_n_s64(a, 3);
}
-// CHECK-LABEL: define <8 x i8> @test_vshl_n_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vshl_n_u8(
// CHECK: [[VSHL_N:%.*]] = shl <8 x i8> %a, <i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3>
// CHECK: ret <8 x i8> [[VSHL_N]]
int8x8_t test_vshl_n_u8(int8x8_t a) {
return vshl_n_u8(a, 3);
}
-// CHECK-LABEL: define <4 x i16> @test_vshl_n_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vshl_n_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
// CHECK: [[VSHL_N:%.*]] = shl <4 x i16> [[TMP1]], <i16 3, i16 3, i16 3, i16 3>
@@ -5329,7 +4674,7 @@ int16x4_t test_vshl_n_u16(int16x4_t a) {
return vshl_n_u16(a, 3);
}
-// CHECK-LABEL: define <2 x i32> @test_vshl_n_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vshl_n_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
// CHECK: [[VSHL_N:%.*]] = shl <2 x i32> [[TMP1]], <i32 3, i32 3>
@@ -5338,14 +4683,14 @@ int32x2_t test_vshl_n_u32(int32x2_t a) {
return vshl_n_u32(a, 3);
}
-// CHECK-LABEL: define <16 x i8> @test_vshlq_n_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vshlq_n_u8(
// CHECK: [[VSHL_N:%.*]] = shl <16 x i8> %a, <i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3>
// CHECK: ret <16 x i8> [[VSHL_N]]
int8x16_t test_vshlq_n_u8(int8x16_t a) {
return vshlq_n_u8(a, 3);
}
-// CHECK-LABEL: define <8 x i16> @test_vshlq_n_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vshlq_n_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VSHL_N:%.*]] = shl <8 x i16> [[TMP1]], <i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3>
@@ -5354,7 +4699,7 @@ int16x8_t test_vshlq_n_u16(int16x8_t a) {
return vshlq_n_u16(a, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vshlq_n_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vshlq_n_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VSHL_N:%.*]] = shl <4 x i32> [[TMP1]], <i32 3, i32 3, i32 3, i32 3>
@@ -5363,7 +4708,7 @@ int32x4_t test_vshlq_n_u32(int32x4_t a) {
return vshlq_n_u32(a, 3);
}
-// CHECK-LABEL: define <2 x i64> @test_vshlq_n_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vshlq_n_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VSHL_N:%.*]] = shl <2 x i64> [[TMP1]], <i64 3, i64 3>
@@ -5372,14 +4717,14 @@ int64x2_t test_vshlq_n_u64(int64x2_t a) {
return vshlq_n_u64(a, 3);
}
-// CHECK-LABEL: define <8 x i8> @test_vshr_n_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vshr_n_s8(
// CHECK: [[VSHR_N:%.*]] = ashr <8 x i8> %a, <i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3>
// CHECK: ret <8 x i8> [[VSHR_N]]
int8x8_t test_vshr_n_s8(int8x8_t a) {
return vshr_n_s8(a, 3);
}
-// CHECK-LABEL: define <4 x i16> @test_vshr_n_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vshr_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
// CHECK: [[VSHR_N:%.*]] = ashr <4 x i16> [[TMP1]], <i16 3, i16 3, i16 3, i16 3>
@@ -5388,7 +4733,7 @@ int16x4_t test_vshr_n_s16(int16x4_t a) {
return vshr_n_s16(a, 3);
}
-// CHECK-LABEL: define <2 x i32> @test_vshr_n_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vshr_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
// CHECK: [[VSHR_N:%.*]] = ashr <2 x i32> [[TMP1]], <i32 3, i32 3>
@@ -5397,14 +4742,14 @@ int32x2_t test_vshr_n_s32(int32x2_t a) {
return vshr_n_s32(a, 3);
}
-// CHECK-LABEL: define <16 x i8> @test_vshrq_n_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vshrq_n_s8(
// CHECK: [[VSHR_N:%.*]] = ashr <16 x i8> %a, <i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3>
// CHECK: ret <16 x i8> [[VSHR_N]]
int8x16_t test_vshrq_n_s8(int8x16_t a) {
return vshrq_n_s8(a, 3);
}
-// CHECK-LABEL: define <8 x i16> @test_vshrq_n_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vshrq_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VSHR_N:%.*]] = ashr <8 x i16> [[TMP1]], <i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3>
@@ -5413,7 +4758,7 @@ int16x8_t test_vshrq_n_s16(int16x8_t a) {
return vshrq_n_s16(a, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vshrq_n_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vshrq_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VSHR_N:%.*]] = ashr <4 x i32> [[TMP1]], <i32 3, i32 3, i32 3, i32 3>
@@ -5422,7 +4767,7 @@ int32x4_t test_vshrq_n_s32(int32x4_t a) {
return vshrq_n_s32(a, 3);
}
-// CHECK-LABEL: define <2 x i64> @test_vshrq_n_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vshrq_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VSHR_N:%.*]] = ashr <2 x i64> [[TMP1]], <i64 3, i64 3>
@@ -5431,14 +4776,14 @@ int64x2_t test_vshrq_n_s64(int64x2_t a) {
return vshrq_n_s64(a, 3);
}
-// CHECK-LABEL: define <8 x i8> @test_vshr_n_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vshr_n_u8(
// CHECK: [[VSHR_N:%.*]] = lshr <8 x i8> %a, <i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3>
// CHECK: ret <8 x i8> [[VSHR_N]]
int8x8_t test_vshr_n_u8(int8x8_t a) {
return vshr_n_u8(a, 3);
}
-// CHECK-LABEL: define <4 x i16> @test_vshr_n_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vshr_n_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
// CHECK: [[VSHR_N:%.*]] = lshr <4 x i16> [[TMP1]], <i16 3, i16 3, i16 3, i16 3>
@@ -5447,7 +4792,7 @@ int16x4_t test_vshr_n_u16(int16x4_t a) {
return vshr_n_u16(a, 3);
}
-// CHECK-LABEL: define <2 x i32> @test_vshr_n_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vshr_n_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
// CHECK: [[VSHR_N:%.*]] = lshr <2 x i32> [[TMP1]], <i32 3, i32 3>
@@ -5456,14 +4801,14 @@ int32x2_t test_vshr_n_u32(int32x2_t a) {
return vshr_n_u32(a, 3);
}
-// CHECK-LABEL: define <16 x i8> @test_vshrq_n_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vshrq_n_u8(
// CHECK: [[VSHR_N:%.*]] = lshr <16 x i8> %a, <i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3>
// CHECK: ret <16 x i8> [[VSHR_N]]
int8x16_t test_vshrq_n_u8(int8x16_t a) {
return vshrq_n_u8(a, 3);
}
-// CHECK-LABEL: define <8 x i16> @test_vshrq_n_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vshrq_n_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VSHR_N:%.*]] = lshr <8 x i16> [[TMP1]], <i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3>
@@ -5472,7 +4817,7 @@ int16x8_t test_vshrq_n_u16(int16x8_t a) {
return vshrq_n_u16(a, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vshrq_n_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vshrq_n_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VSHR_N:%.*]] = lshr <4 x i32> [[TMP1]], <i32 3, i32 3, i32 3, i32 3>
@@ -5481,7 +4826,7 @@ int32x4_t test_vshrq_n_u32(int32x4_t a) {
return vshrq_n_u32(a, 3);
}
-// CHECK-LABEL: define <2 x i64> @test_vshrq_n_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vshrq_n_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VSHR_N:%.*]] = lshr <2 x i64> [[TMP1]], <i64 3, i64 3>
@@ -5490,7 +4835,7 @@ int64x2_t test_vshrq_n_u64(int64x2_t a) {
return vshrq_n_u64(a, 3);
}
-// CHECK-LABEL: define <8 x i8> @test_vsra_n_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsra_n_s8(
// CHECK: [[VSRA_N:%.*]] = ashr <8 x i8> %b, <i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3>
// CHECK: [[TMP0:%.*]] = add <8 x i8> %a, [[VSRA_N]]
// CHECK: ret <8 x i8> [[TMP0]]
@@ -5498,7 +4843,7 @@ int8x8_t test_vsra_n_s8(int8x8_t a, int8x8_t b) {
return vsra_n_s8(a, b, 3);
}
-// CHECK-LABEL: define <4 x i16> @test_vsra_n_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsra_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
@@ -5510,7 +4855,7 @@ int16x4_t test_vsra_n_s16(int16x4_t a, int16x4_t b) {
return vsra_n_s16(a, b, 3);
}
-// CHECK-LABEL: define <2 x i32> @test_vsra_n_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsra_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
@@ -5522,7 +4867,7 @@ int32x2_t test_vsra_n_s32(int32x2_t a, int32x2_t b) {
return vsra_n_s32(a, b, 3);
}
-// CHECK-LABEL: define <16 x i8> @test_vsraq_n_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsraq_n_s8(
// CHECK: [[VSRA_N:%.*]] = ashr <16 x i8> %b, <i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3>
// CHECK: [[TMP0:%.*]] = add <16 x i8> %a, [[VSRA_N]]
// CHECK: ret <16 x i8> [[TMP0]]
@@ -5530,7 +4875,7 @@ int8x16_t test_vsraq_n_s8(int8x16_t a, int8x16_t b) {
return vsraq_n_s8(a, b, 3);
}
-// CHECK-LABEL: define <8 x i16> @test_vsraq_n_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsraq_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
@@ -5542,7 +4887,7 @@ int16x8_t test_vsraq_n_s16(int16x8_t a, int16x8_t b) {
return vsraq_n_s16(a, b, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vsraq_n_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsraq_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
@@ -5554,7 +4899,7 @@ int32x4_t test_vsraq_n_s32(int32x4_t a, int32x4_t b) {
return vsraq_n_s32(a, b, 3);
}
-// CHECK-LABEL: define <2 x i64> @test_vsraq_n_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vsraq_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
@@ -5566,7 +4911,7 @@ int64x2_t test_vsraq_n_s64(int64x2_t a, int64x2_t b) {
return vsraq_n_s64(a, b, 3);
}
-// CHECK-LABEL: define <8 x i8> @test_vsra_n_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsra_n_u8(
// CHECK: [[VSRA_N:%.*]] = lshr <8 x i8> %b, <i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3>
// CHECK: [[TMP0:%.*]] = add <8 x i8> %a, [[VSRA_N]]
// CHECK: ret <8 x i8> [[TMP0]]
@@ -5574,7 +4919,7 @@ int8x8_t test_vsra_n_u8(int8x8_t a, int8x8_t b) {
return vsra_n_u8(a, b, 3);
}
-// CHECK-LABEL: define <4 x i16> @test_vsra_n_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsra_n_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
@@ -5586,7 +4931,7 @@ int16x4_t test_vsra_n_u16(int16x4_t a, int16x4_t b) {
return vsra_n_u16(a, b, 3);
}
-// CHECK-LABEL: define <2 x i32> @test_vsra_n_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsra_n_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
@@ -5598,7 +4943,7 @@ int32x2_t test_vsra_n_u32(int32x2_t a, int32x2_t b) {
return vsra_n_u32(a, b, 3);
}
-// CHECK-LABEL: define <16 x i8> @test_vsraq_n_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsraq_n_u8(
// CHECK: [[VSRA_N:%.*]] = lshr <16 x i8> %b, <i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3>
// CHECK: [[TMP0:%.*]] = add <16 x i8> %a, [[VSRA_N]]
// CHECK: ret <16 x i8> [[TMP0]]
@@ -5606,7 +4951,7 @@ int8x16_t test_vsraq_n_u8(int8x16_t a, int8x16_t b) {
return vsraq_n_u8(a, b, 3);
}
-// CHECK-LABEL: define <8 x i16> @test_vsraq_n_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsraq_n_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
@@ -5618,7 +4963,7 @@ int16x8_t test_vsraq_n_u16(int16x8_t a, int16x8_t b) {
return vsraq_n_u16(a, b, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vsraq_n_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsraq_n_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
@@ -5630,7 +4975,7 @@ int32x4_t test_vsraq_n_u32(int32x4_t a, int32x4_t b) {
return vsraq_n_u32(a, b, 3);
}
-// CHECK-LABEL: define <2 x i64> @test_vsraq_n_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vsraq_n_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
@@ -5642,14 +4987,14 @@ int64x2_t test_vsraq_n_u64(int64x2_t a, int64x2_t b) {
return vsraq_n_u64(a, b, 3);
}
-// CHECK-LABEL: define <8 x i8> @test_vrshr_n_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrshr_n_s8(
// CHECK: [[VRSHR_N:%.*]] = call <8 x i8> @llvm.aarch64.neon.srshl.v8i8(<8 x i8> %a, <8 x i8> <i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3>)
// CHECK: ret <8 x i8> [[VRSHR_N]]
int8x8_t test_vrshr_n_s8(int8x8_t a) {
return vrshr_n_s8(a, 3);
}
-// CHECK-LABEL: define <4 x i16> @test_vrshr_n_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vrshr_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[VRSHR_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
// CHECK: [[VRSHR_N1:%.*]] = call <4 x i16> @llvm.aarch64.neon.srshl.v4i16(<4 x i16> [[VRSHR_N]], <4 x i16> <i16 -3, i16 -3, i16 -3, i16 -3>)
@@ -5658,7 +5003,7 @@ int16x4_t test_vrshr_n_s16(int16x4_t a) {
return vrshr_n_s16(a, 3);
}
-// CHECK-LABEL: define <2 x i32> @test_vrshr_n_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vrshr_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[VRSHR_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
// CHECK: [[VRSHR_N1:%.*]] = call <2 x i32> @llvm.aarch64.neon.srshl.v2i32(<2 x i32> [[VRSHR_N]], <2 x i32> <i32 -3, i32 -3>)
@@ -5667,14 +5012,14 @@ int32x2_t test_vrshr_n_s32(int32x2_t a) {
return vrshr_n_s32(a, 3);
}
-// CHECK-LABEL: define <16 x i8> @test_vrshrq_n_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrshrq_n_s8(
// CHECK: [[VRSHR_N:%.*]] = call <16 x i8> @llvm.aarch64.neon.srshl.v16i8(<16 x i8> %a, <16 x i8> <i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3>)
// CHECK: ret <16 x i8> [[VRSHR_N]]
int8x16_t test_vrshrq_n_s8(int8x16_t a) {
return vrshrq_n_s8(a, 3);
}
-// CHECK-LABEL: define <8 x i16> @test_vrshrq_n_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vrshrq_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[VRSHR_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VRSHR_N1:%.*]] = call <8 x i16> @llvm.aarch64.neon.srshl.v8i16(<8 x i16> [[VRSHR_N]], <8 x i16> <i16 -3, i16 -3, i16 -3, i16 -3, i16 -3, i16 -3, i16 -3, i16 -3>)
@@ -5683,7 +5028,7 @@ int16x8_t test_vrshrq_n_s16(int16x8_t a) {
return vrshrq_n_s16(a, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vrshrq_n_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vrshrq_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[VRSHR_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VRSHR_N1:%.*]] = call <4 x i32> @llvm.aarch64.neon.srshl.v4i32(<4 x i32> [[VRSHR_N]], <4 x i32> <i32 -3, i32 -3, i32 -3, i32 -3>)
@@ -5692,7 +5037,7 @@ int32x4_t test_vrshrq_n_s32(int32x4_t a) {
return vrshrq_n_s32(a, 3);
}
-// CHECK-LABEL: define <2 x i64> @test_vrshrq_n_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vrshrq_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[VRSHR_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VRSHR_N1:%.*]] = call <2 x i64> @llvm.aarch64.neon.srshl.v2i64(<2 x i64> [[VRSHR_N]], <2 x i64> <i64 -3, i64 -3>)
@@ -5701,14 +5046,14 @@ int64x2_t test_vrshrq_n_s64(int64x2_t a) {
return vrshrq_n_s64(a, 3);
}
-// CHECK-LABEL: define <8 x i8> @test_vrshr_n_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrshr_n_u8(
// CHECK: [[VRSHR_N:%.*]] = call <8 x i8> @llvm.aarch64.neon.urshl.v8i8(<8 x i8> %a, <8 x i8> <i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3>)
// CHECK: ret <8 x i8> [[VRSHR_N]]
int8x8_t test_vrshr_n_u8(int8x8_t a) {
return vrshr_n_u8(a, 3);
}
-// CHECK-LABEL: define <4 x i16> @test_vrshr_n_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vrshr_n_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[VRSHR_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
// CHECK: [[VRSHR_N1:%.*]] = call <4 x i16> @llvm.aarch64.neon.urshl.v4i16(<4 x i16> [[VRSHR_N]], <4 x i16> <i16 -3, i16 -3, i16 -3, i16 -3>)
@@ -5717,7 +5062,7 @@ int16x4_t test_vrshr_n_u16(int16x4_t a) {
return vrshr_n_u16(a, 3);
}
-// CHECK-LABEL: define <2 x i32> @test_vrshr_n_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vrshr_n_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[VRSHR_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
// CHECK: [[VRSHR_N1:%.*]] = call <2 x i32> @llvm.aarch64.neon.urshl.v2i32(<2 x i32> [[VRSHR_N]], <2 x i32> <i32 -3, i32 -3>)
@@ -5726,14 +5071,14 @@ int32x2_t test_vrshr_n_u32(int32x2_t a) {
return vrshr_n_u32(a, 3);
}
-// CHECK-LABEL: define <16 x i8> @test_vrshrq_n_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrshrq_n_u8(
// CHECK: [[VRSHR_N:%.*]] = call <16 x i8> @llvm.aarch64.neon.urshl.v16i8(<16 x i8> %a, <16 x i8> <i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3>)
// CHECK: ret <16 x i8> [[VRSHR_N]]
int8x16_t test_vrshrq_n_u8(int8x16_t a) {
return vrshrq_n_u8(a, 3);
}
-// CHECK-LABEL: define <8 x i16> @test_vrshrq_n_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vrshrq_n_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[VRSHR_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VRSHR_N1:%.*]] = call <8 x i16> @llvm.aarch64.neon.urshl.v8i16(<8 x i16> [[VRSHR_N]], <8 x i16> <i16 -3, i16 -3, i16 -3, i16 -3, i16 -3, i16 -3, i16 -3, i16 -3>)
@@ -5742,7 +5087,7 @@ int16x8_t test_vrshrq_n_u16(int16x8_t a) {
return vrshrq_n_u16(a, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vrshrq_n_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vrshrq_n_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[VRSHR_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VRSHR_N1:%.*]] = call <4 x i32> @llvm.aarch64.neon.urshl.v4i32(<4 x i32> [[VRSHR_N]], <4 x i32> <i32 -3, i32 -3, i32 -3, i32 -3>)
@@ -5751,7 +5096,7 @@ int32x4_t test_vrshrq_n_u32(int32x4_t a) {
return vrshrq_n_u32(a, 3);
}
-// CHECK-LABEL: define <2 x i64> @test_vrshrq_n_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vrshrq_n_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[VRSHR_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VRSHR_N1:%.*]] = call <2 x i64> @llvm.aarch64.neon.urshl.v2i64(<2 x i64> [[VRSHR_N]], <2 x i64> <i64 -3, i64 -3>)
@@ -5760,7 +5105,7 @@ int64x2_t test_vrshrq_n_u64(int64x2_t a) {
return vrshrq_n_u64(a, 3);
}
-// CHECK-LABEL: define <8 x i8> @test_vrsra_n_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vrsra_n_s8(
// CHECK: [[VRSHR_N:%.*]] = call <8 x i8> @llvm.aarch64.neon.srshl.v8i8(<8 x i8> %b, <8 x i8> <i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3>)
// CHECK: [[TMP0:%.*]] = add <8 x i8> %a, [[VRSHR_N]]
// CHECK: ret <8 x i8> [[TMP0]]
@@ -5768,7 +5113,7 @@ int8x8_t test_vrsra_n_s8(int8x8_t a, int8x8_t b) {
return vrsra_n_s8(a, b, 3);
}
-// CHECK-LABEL: define <4 x i16> @test_vrsra_n_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vrsra_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[VRSHR_N:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
@@ -5780,7 +5125,7 @@ int16x4_t test_vrsra_n_s16(int16x4_t a, int16x4_t b) {
return vrsra_n_s16(a, b, 3);
}
-// CHECK-LABEL: define <2 x i32> @test_vrsra_n_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vrsra_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[VRSHR_N:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
@@ -5792,7 +5137,7 @@ int32x2_t test_vrsra_n_s32(int32x2_t a, int32x2_t b) {
return vrsra_n_s32(a, b, 3);
}
-// CHECK-LABEL: define <16 x i8> @test_vrsraq_n_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vrsraq_n_s8(
// CHECK: [[VRSHR_N:%.*]] = call <16 x i8> @llvm.aarch64.neon.srshl.v16i8(<16 x i8> %b, <16 x i8> <i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3>)
// CHECK: [[TMP0:%.*]] = add <16 x i8> %a, [[VRSHR_N]]
// CHECK: ret <16 x i8> [[TMP0]]
@@ -5800,7 +5145,7 @@ int8x16_t test_vrsraq_n_s8(int8x16_t a, int8x16_t b) {
return vrsraq_n_s8(a, b, 3);
}
-// CHECK-LABEL: define <8 x i16> @test_vrsraq_n_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vrsraq_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[VRSHR_N:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
@@ -5812,7 +5157,7 @@ int16x8_t test_vrsraq_n_s16(int16x8_t a, int16x8_t b) {
return vrsraq_n_s16(a, b, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vrsraq_n_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vrsraq_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[VRSHR_N:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
@@ -5824,7 +5169,7 @@ int32x4_t test_vrsraq_n_s32(int32x4_t a, int32x4_t b) {
return vrsraq_n_s32(a, b, 3);
}
-// CHECK-LABEL: define <2 x i64> @test_vrsraq_n_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vrsraq_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
// CHECK: [[VRSHR_N:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
@@ -5836,7 +5181,7 @@ int64x2_t test_vrsraq_n_s64(int64x2_t a, int64x2_t b) {
return vrsraq_n_s64(a, b, 3);
}
-// CHECK-LABEL: define <8 x i8> @test_vrsra_n_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vrsra_n_u8(
// CHECK: [[VRSHR_N:%.*]] = call <8 x i8> @llvm.aarch64.neon.urshl.v8i8(<8 x i8> %b, <8 x i8> <i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3>)
// CHECK: [[TMP0:%.*]] = add <8 x i8> %a, [[VRSHR_N]]
// CHECK: ret <8 x i8> [[TMP0]]
@@ -5844,7 +5189,7 @@ int8x8_t test_vrsra_n_u8(int8x8_t a, int8x8_t b) {
return vrsra_n_u8(a, b, 3);
}
-// CHECK-LABEL: define <4 x i16> @test_vrsra_n_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vrsra_n_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[VRSHR_N:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
@@ -5856,7 +5201,7 @@ int16x4_t test_vrsra_n_u16(int16x4_t a, int16x4_t b) {
return vrsra_n_u16(a, b, 3);
}
-// CHECK-LABEL: define <2 x i32> @test_vrsra_n_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vrsra_n_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[VRSHR_N:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
@@ -5868,7 +5213,7 @@ int32x2_t test_vrsra_n_u32(int32x2_t a, int32x2_t b) {
return vrsra_n_u32(a, b, 3);
}
-// CHECK-LABEL: define <16 x i8> @test_vrsraq_n_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vrsraq_n_u8(
// CHECK: [[VRSHR_N:%.*]] = call <16 x i8> @llvm.aarch64.neon.urshl.v16i8(<16 x i8> %b, <16 x i8> <i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3, i8 -3>)
// CHECK: [[TMP0:%.*]] = add <16 x i8> %a, [[VRSHR_N]]
// CHECK: ret <16 x i8> [[TMP0]]
@@ -5876,7 +5221,7 @@ int8x16_t test_vrsraq_n_u8(int8x16_t a, int8x16_t b) {
return vrsraq_n_u8(a, b, 3);
}
-// CHECK-LABEL: define <8 x i16> @test_vrsraq_n_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vrsraq_n_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[VRSHR_N:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
@@ -5888,7 +5233,7 @@ int16x8_t test_vrsraq_n_u16(int16x8_t a, int16x8_t b) {
return vrsraq_n_u16(a, b, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vrsraq_n_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vrsraq_n_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[VRSHR_N:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
@@ -5900,7 +5245,7 @@ int32x4_t test_vrsraq_n_u32(int32x4_t a, int32x4_t b) {
return vrsraq_n_u32(a, b, 3);
}
-// CHECK-LABEL: define <2 x i64> @test_vrsraq_n_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vrsraq_n_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
// CHECK: [[VRSHR_N:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
@@ -5912,14 +5257,14 @@ int64x2_t test_vrsraq_n_u64(int64x2_t a, int64x2_t b) {
return vrsraq_n_u64(a, b, 3);
}
-// CHECK-LABEL: define <8 x i8> @test_vsri_n_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsri_n_s8(
// CHECK: [[VSRI_N:%.*]] = call <8 x i8> @llvm.aarch64.neon.vsri.v8i8(<8 x i8> %a, <8 x i8> %b, i32 3)
// CHECK: ret <8 x i8> [[VSRI_N]]
int8x8_t test_vsri_n_s8(int8x8_t a, int8x8_t b) {
return vsri_n_s8(a, b, 3);
}
-// CHECK-LABEL: define <4 x i16> @test_vsri_n_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsri_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[VSRI_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
@@ -5930,7 +5275,7 @@ int16x4_t test_vsri_n_s16(int16x4_t a, int16x4_t b) {
return vsri_n_s16(a, b, 3);
}
-// CHECK-LABEL: define <2 x i32> @test_vsri_n_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsri_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[VSRI_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
@@ -5941,14 +5286,14 @@ int32x2_t test_vsri_n_s32(int32x2_t a, int32x2_t b) {
return vsri_n_s32(a, b, 3);
}
-// CHECK-LABEL: define <16 x i8> @test_vsriq_n_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsriq_n_s8(
// CHECK: [[VSRI_N:%.*]] = call <16 x i8> @llvm.aarch64.neon.vsri.v16i8(<16 x i8> %a, <16 x i8> %b, i32 3)
// CHECK: ret <16 x i8> [[VSRI_N]]
int8x16_t test_vsriq_n_s8(int8x16_t a, int8x16_t b) {
return vsriq_n_s8(a, b, 3);
}
-// CHECK-LABEL: define <8 x i16> @test_vsriq_n_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsriq_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[VSRI_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
@@ -5959,7 +5304,7 @@ int16x8_t test_vsriq_n_s16(int16x8_t a, int16x8_t b) {
return vsriq_n_s16(a, b, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vsriq_n_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsriq_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[VSRI_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
@@ -5970,7 +5315,7 @@ int32x4_t test_vsriq_n_s32(int32x4_t a, int32x4_t b) {
return vsriq_n_s32(a, b, 3);
}
-// CHECK-LABEL: define <2 x i64> @test_vsriq_n_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vsriq_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
// CHECK: [[VSRI_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
@@ -5981,14 +5326,14 @@ int64x2_t test_vsriq_n_s64(int64x2_t a, int64x2_t b) {
return vsriq_n_s64(a, b, 3);
}
-// CHECK-LABEL: define <8 x i8> @test_vsri_n_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsri_n_u8(
// CHECK: [[VSRI_N:%.*]] = call <8 x i8> @llvm.aarch64.neon.vsri.v8i8(<8 x i8> %a, <8 x i8> %b, i32 3)
// CHECK: ret <8 x i8> [[VSRI_N]]
int8x8_t test_vsri_n_u8(int8x8_t a, int8x8_t b) {
return vsri_n_u8(a, b, 3);
}
-// CHECK-LABEL: define <4 x i16> @test_vsri_n_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsri_n_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[VSRI_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
@@ -5999,7 +5344,7 @@ int16x4_t test_vsri_n_u16(int16x4_t a, int16x4_t b) {
return vsri_n_u16(a, b, 3);
}
-// CHECK-LABEL: define <2 x i32> @test_vsri_n_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsri_n_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[VSRI_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
@@ -6010,14 +5355,14 @@ int32x2_t test_vsri_n_u32(int32x2_t a, int32x2_t b) {
return vsri_n_u32(a, b, 3);
}
-// CHECK-LABEL: define <16 x i8> @test_vsriq_n_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsriq_n_u8(
// CHECK: [[VSRI_N:%.*]] = call <16 x i8> @llvm.aarch64.neon.vsri.v16i8(<16 x i8> %a, <16 x i8> %b, i32 3)
// CHECK: ret <16 x i8> [[VSRI_N]]
int8x16_t test_vsriq_n_u8(int8x16_t a, int8x16_t b) {
return vsriq_n_u8(a, b, 3);
}
-// CHECK-LABEL: define <8 x i16> @test_vsriq_n_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsriq_n_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[VSRI_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
@@ -6028,7 +5373,7 @@ int16x8_t test_vsriq_n_u16(int16x8_t a, int16x8_t b) {
return vsriq_n_u16(a, b, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vsriq_n_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsriq_n_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[VSRI_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
@@ -6039,7 +5384,7 @@ int32x4_t test_vsriq_n_u32(int32x4_t a, int32x4_t b) {
return vsriq_n_u32(a, b, 3);
}
-// CHECK-LABEL: define <2 x i64> @test_vsriq_n_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vsriq_n_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
// CHECK: [[VSRI_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
@@ -6050,14 +5395,14 @@ int64x2_t test_vsriq_n_u64(int64x2_t a, int64x2_t b) {
return vsriq_n_u64(a, b, 3);
}
-// CHECK-LABEL: define <8 x i8> @test_vsri_n_p8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsri_n_p8(
// CHECK: [[VSRI_N:%.*]] = call <8 x i8> @llvm.aarch64.neon.vsri.v8i8(<8 x i8> %a, <8 x i8> %b, i32 3)
// CHECK: ret <8 x i8> [[VSRI_N]]
poly8x8_t test_vsri_n_p8(poly8x8_t a, poly8x8_t b) {
return vsri_n_p8(a, b, 3);
}
-// CHECK-LABEL: define <4 x i16> @test_vsri_n_p16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsri_n_p16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[VSRI_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
@@ -6068,14 +5413,14 @@ poly16x4_t test_vsri_n_p16(poly16x4_t a, poly16x4_t b) {
return vsri_n_p16(a, b, 15);
}
-// CHECK-LABEL: define <16 x i8> @test_vsriq_n_p8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsriq_n_p8(
// CHECK: [[VSRI_N:%.*]] = call <16 x i8> @llvm.aarch64.neon.vsri.v16i8(<16 x i8> %a, <16 x i8> %b, i32 3)
// CHECK: ret <16 x i8> [[VSRI_N]]
poly8x16_t test_vsriq_n_p8(poly8x16_t a, poly8x16_t b) {
return vsriq_n_p8(a, b, 3);
}
-// CHECK-LABEL: define <8 x i16> @test_vsriq_n_p16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsriq_n_p16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[VSRI_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
@@ -6086,14 +5431,14 @@ poly16x8_t test_vsriq_n_p16(poly16x8_t a, poly16x8_t b) {
return vsriq_n_p16(a, b, 15);
}
-// CHECK-LABEL: define <8 x i8> @test_vsli_n_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsli_n_s8(
// CHECK: [[VSLI_N:%.*]] = call <8 x i8> @llvm.aarch64.neon.vsli.v8i8(<8 x i8> %a, <8 x i8> %b, i32 3)
// CHECK: ret <8 x i8> [[VSLI_N]]
int8x8_t test_vsli_n_s8(int8x8_t a, int8x8_t b) {
return vsli_n_s8(a, b, 3);
}
-// CHECK-LABEL: define <4 x i16> @test_vsli_n_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsli_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[VSLI_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
@@ -6104,7 +5449,7 @@ int16x4_t test_vsli_n_s16(int16x4_t a, int16x4_t b) {
return vsli_n_s16(a, b, 3);
}
-// CHECK-LABEL: define <2 x i32> @test_vsli_n_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsli_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[VSLI_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
@@ -6115,14 +5460,14 @@ int32x2_t test_vsli_n_s32(int32x2_t a, int32x2_t b) {
return vsli_n_s32(a, b, 3);
}
-// CHECK-LABEL: define <16 x i8> @test_vsliq_n_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsliq_n_s8(
// CHECK: [[VSLI_N:%.*]] = call <16 x i8> @llvm.aarch64.neon.vsli.v16i8(<16 x i8> %a, <16 x i8> %b, i32 3)
// CHECK: ret <16 x i8> [[VSLI_N]]
int8x16_t test_vsliq_n_s8(int8x16_t a, int8x16_t b) {
return vsliq_n_s8(a, b, 3);
}
-// CHECK-LABEL: define <8 x i16> @test_vsliq_n_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsliq_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[VSLI_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
@@ -6133,7 +5478,7 @@ int16x8_t test_vsliq_n_s16(int16x8_t a, int16x8_t b) {
return vsliq_n_s16(a, b, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vsliq_n_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsliq_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[VSLI_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
@@ -6144,7 +5489,7 @@ int32x4_t test_vsliq_n_s32(int32x4_t a, int32x4_t b) {
return vsliq_n_s32(a, b, 3);
}
-// CHECK-LABEL: define <2 x i64> @test_vsliq_n_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vsliq_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
// CHECK: [[VSLI_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
@@ -6155,14 +5500,14 @@ int64x2_t test_vsliq_n_s64(int64x2_t a, int64x2_t b) {
return vsliq_n_s64(a, b, 3);
}
-// CHECK-LABEL: define <8 x i8> @test_vsli_n_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsli_n_u8(
// CHECK: [[VSLI_N:%.*]] = call <8 x i8> @llvm.aarch64.neon.vsli.v8i8(<8 x i8> %a, <8 x i8> %b, i32 3)
// CHECK: ret <8 x i8> [[VSLI_N]]
uint8x8_t test_vsli_n_u8(uint8x8_t a, uint8x8_t b) {
return vsli_n_u8(a, b, 3);
}
-// CHECK-LABEL: define <4 x i16> @test_vsli_n_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsli_n_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[VSLI_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
@@ -6173,7 +5518,7 @@ uint16x4_t test_vsli_n_u16(uint16x4_t a, uint16x4_t b) {
return vsli_n_u16(a, b, 3);
}
-// CHECK-LABEL: define <2 x i32> @test_vsli_n_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsli_n_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[VSLI_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
@@ -6184,14 +5529,14 @@ uint32x2_t test_vsli_n_u32(uint32x2_t a, uint32x2_t b) {
return vsli_n_u32(a, b, 3);
}
-// CHECK-LABEL: define <16 x i8> @test_vsliq_n_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsliq_n_u8(
// CHECK: [[VSLI_N:%.*]] = call <16 x i8> @llvm.aarch64.neon.vsli.v16i8(<16 x i8> %a, <16 x i8> %b, i32 3)
// CHECK: ret <16 x i8> [[VSLI_N]]
uint8x16_t test_vsliq_n_u8(uint8x16_t a, uint8x16_t b) {
return vsliq_n_u8(a, b, 3);
}
-// CHECK-LABEL: define <8 x i16> @test_vsliq_n_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsliq_n_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[VSLI_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
@@ -6202,7 +5547,7 @@ uint16x8_t test_vsliq_n_u16(uint16x8_t a, uint16x8_t b) {
return vsliq_n_u16(a, b, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vsliq_n_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsliq_n_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[VSLI_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
@@ -6213,7 +5558,7 @@ uint32x4_t test_vsliq_n_u32(uint32x4_t a, uint32x4_t b) {
return vsliq_n_u32(a, b, 3);
}
-// CHECK-LABEL: define <2 x i64> @test_vsliq_n_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vsliq_n_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
// CHECK: [[VSLI_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
@@ -6224,14 +5569,14 @@ uint64x2_t test_vsliq_n_u64(uint64x2_t a, uint64x2_t b) {
return vsliq_n_u64(a, b, 3);
}
-// CHECK-LABEL: define <8 x i8> @test_vsli_n_p8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsli_n_p8(
// CHECK: [[VSLI_N:%.*]] = call <8 x i8> @llvm.aarch64.neon.vsli.v8i8(<8 x i8> %a, <8 x i8> %b, i32 3)
// CHECK: ret <8 x i8> [[VSLI_N]]
poly8x8_t test_vsli_n_p8(poly8x8_t a, poly8x8_t b) {
return vsli_n_p8(a, b, 3);
}
-// CHECK-LABEL: define <4 x i16> @test_vsli_n_p16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsli_n_p16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[VSLI_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
@@ -6242,14 +5587,14 @@ poly16x4_t test_vsli_n_p16(poly16x4_t a, poly16x4_t b) {
return vsli_n_p16(a, b, 15);
}
-// CHECK-LABEL: define <16 x i8> @test_vsliq_n_p8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsliq_n_p8(
// CHECK: [[VSLI_N:%.*]] = call <16 x i8> @llvm.aarch64.neon.vsli.v16i8(<16 x i8> %a, <16 x i8> %b, i32 3)
// CHECK: ret <16 x i8> [[VSLI_N]]
poly8x16_t test_vsliq_n_p8(poly8x16_t a, poly8x16_t b) {
return vsliq_n_p8(a, b, 3);
}
-// CHECK-LABEL: define <8 x i16> @test_vsliq_n_p16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsliq_n_p16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[VSLI_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
@@ -6260,14 +5605,14 @@ poly16x8_t test_vsliq_n_p16(poly16x8_t a, poly16x8_t b) {
return vsliq_n_p16(a, b, 15);
}
-// CHECK-LABEL: define <8 x i8> @test_vqshlu_n_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vqshlu_n_s8(
// CHECK: [[VQSHLU_N:%.*]] = call <8 x i8> @llvm.aarch64.neon.sqshlu.v8i8(<8 x i8> %a, <8 x i8> <i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3>)
// CHECK: ret <8 x i8> [[VQSHLU_N]]
int8x8_t test_vqshlu_n_s8(int8x8_t a) {
return vqshlu_n_s8(a, 3);
}
-// CHECK-LABEL: define <4 x i16> @test_vqshlu_n_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vqshlu_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[VQSHLU_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
// CHECK: [[VQSHLU_N1:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqshlu.v4i16(<4 x i16> [[VQSHLU_N]], <4 x i16> <i16 3, i16 3, i16 3, i16 3>)
@@ -6276,7 +5621,7 @@ int16x4_t test_vqshlu_n_s16(int16x4_t a) {
return vqshlu_n_s16(a, 3);
}
-// CHECK-LABEL: define <2 x i32> @test_vqshlu_n_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vqshlu_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[VQSHLU_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
// CHECK: [[VQSHLU_N1:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqshlu.v2i32(<2 x i32> [[VQSHLU_N]], <2 x i32> <i32 3, i32 3>)
@@ -6285,14 +5630,14 @@ int32x2_t test_vqshlu_n_s32(int32x2_t a) {
return vqshlu_n_s32(a, 3);
}
-// CHECK-LABEL: define <16 x i8> @test_vqshluq_n_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vqshluq_n_s8(
// CHECK: [[VQSHLU_N:%.*]] = call <16 x i8> @llvm.aarch64.neon.sqshlu.v16i8(<16 x i8> %a, <16 x i8> <i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3>)
// CHECK: ret <16 x i8> [[VQSHLU_N]]
int8x16_t test_vqshluq_n_s8(int8x16_t a) {
return vqshluq_n_s8(a, 3);
}
-// CHECK-LABEL: define <8 x i16> @test_vqshluq_n_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vqshluq_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[VQSHLU_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VQSHLU_N1:%.*]] = call <8 x i16> @llvm.aarch64.neon.sqshlu.v8i16(<8 x i16> [[VQSHLU_N]], <8 x i16> <i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3>)
@@ -6301,7 +5646,7 @@ int16x8_t test_vqshluq_n_s16(int16x8_t a) {
return vqshluq_n_s16(a, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vqshluq_n_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vqshluq_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[VQSHLU_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VQSHLU_N1:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqshlu.v4i32(<4 x i32> [[VQSHLU_N]], <4 x i32> <i32 3, i32 3, i32 3, i32 3>)
@@ -6310,7 +5655,7 @@ int32x4_t test_vqshluq_n_s32(int32x4_t a) {
return vqshluq_n_s32(a, 3);
}
-// CHECK-LABEL: define <2 x i64> @test_vqshluq_n_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vqshluq_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[VQSHLU_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VQSHLU_N1:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqshlu.v2i64(<2 x i64> [[VQSHLU_N]], <2 x i64> <i64 3, i64 3>)
@@ -6319,7 +5664,7 @@ int64x2_t test_vqshluq_n_s64(int64x2_t a) {
return vqshluq_n_s64(a, 3);
}
-// CHECK-LABEL: define <8 x i8> @test_vshrn_n_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vshrn_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[TMP2:%.*]] = ashr <8 x i16> [[TMP1]], <i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3>
@@ -6329,7 +5674,7 @@ int8x8_t test_vshrn_n_s16(int16x8_t a) {
return vshrn_n_s16(a, 3);
}
-// CHECK-LABEL: define <4 x i16> @test_vshrn_n_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vshrn_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[TMP2:%.*]] = ashr <4 x i32> [[TMP1]], <i32 9, i32 9, i32 9, i32 9>
@@ -6339,7 +5684,7 @@ int16x4_t test_vshrn_n_s32(int32x4_t a) {
return vshrn_n_s32(a, 9);
}
-// CHECK-LABEL: define <2 x i32> @test_vshrn_n_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vshrn_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[TMP2:%.*]] = ashr <2 x i64> [[TMP1]], <i64 19, i64 19>
@@ -6349,7 +5694,7 @@ int32x2_t test_vshrn_n_s64(int64x2_t a) {
return vshrn_n_s64(a, 19);
}
-// CHECK-LABEL: define <8 x i8> @test_vshrn_n_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vshrn_n_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[TMP2:%.*]] = lshr <8 x i16> [[TMP1]], <i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3>
@@ -6359,7 +5704,7 @@ uint8x8_t test_vshrn_n_u16(uint16x8_t a) {
return vshrn_n_u16(a, 3);
}
-// CHECK-LABEL: define <4 x i16> @test_vshrn_n_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vshrn_n_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[TMP2:%.*]] = lshr <4 x i32> [[TMP1]], <i32 9, i32 9, i32 9, i32 9>
@@ -6369,7 +5714,7 @@ uint16x4_t test_vshrn_n_u32(uint32x4_t a) {
return vshrn_n_u32(a, 9);
}
-// CHECK-LABEL: define <2 x i32> @test_vshrn_n_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vshrn_n_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[TMP2:%.*]] = lshr <2 x i64> [[TMP1]], <i64 19, i64 19>
@@ -6379,7 +5724,7 @@ uint32x2_t test_vshrn_n_u64(uint64x2_t a) {
return vshrn_n_u64(a, 19);
}
-// CHECK-LABEL: define <16 x i8> @test_vshrn_high_n_s16(<8 x i8> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vshrn_high_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[TMP2:%.*]] = ashr <8 x i16> [[TMP1]], <i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3>
@@ -6390,7 +5735,7 @@ int8x16_t test_vshrn_high_n_s16(int8x8_t a, int16x8_t b) {
return vshrn_high_n_s16(a, b, 3);
}
-// CHECK-LABEL: define <8 x i16> @test_vshrn_high_n_s32(<4 x i16> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vshrn_high_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[TMP2:%.*]] = ashr <4 x i32> [[TMP1]], <i32 9, i32 9, i32 9, i32 9>
@@ -6401,7 +5746,7 @@ int16x8_t test_vshrn_high_n_s32(int16x4_t a, int32x4_t b) {
return vshrn_high_n_s32(a, b, 9);
}
-// CHECK-LABEL: define <4 x i32> @test_vshrn_high_n_s64(<2 x i32> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vshrn_high_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %b to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[TMP2:%.*]] = ashr <2 x i64> [[TMP1]], <i64 19, i64 19>
@@ -6412,7 +5757,7 @@ int32x4_t test_vshrn_high_n_s64(int32x2_t a, int64x2_t b) {
return vshrn_high_n_s64(a, b, 19);
}
-// CHECK-LABEL: define <16 x i8> @test_vshrn_high_n_u16(<8 x i8> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vshrn_high_n_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[TMP2:%.*]] = lshr <8 x i16> [[TMP1]], <i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3>
@@ -6423,7 +5768,7 @@ uint8x16_t test_vshrn_high_n_u16(uint8x8_t a, uint16x8_t b) {
return vshrn_high_n_u16(a, b, 3);
}
-// CHECK-LABEL: define <8 x i16> @test_vshrn_high_n_u32(<4 x i16> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vshrn_high_n_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[TMP2:%.*]] = lshr <4 x i32> [[TMP1]], <i32 9, i32 9, i32 9, i32 9>
@@ -6434,7 +5779,7 @@ uint16x8_t test_vshrn_high_n_u32(uint16x4_t a, uint32x4_t b) {
return vshrn_high_n_u32(a, b, 9);
}
-// CHECK-LABEL: define <4 x i32> @test_vshrn_high_n_u64(<2 x i32> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vshrn_high_n_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %b to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[TMP2:%.*]] = lshr <2 x i64> [[TMP1]], <i64 19, i64 19>
@@ -6445,7 +5790,7 @@ uint32x4_t test_vshrn_high_n_u64(uint32x2_t a, uint64x2_t b) {
return vshrn_high_n_u64(a, b, 19);
}
-// CHECK-LABEL: define <8 x i8> @test_vqshrun_n_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vqshrun_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[VQSHRUN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VQSHRUN_N1:%.*]] = call <8 x i8> @llvm.aarch64.neon.sqshrun.v8i8(<8 x i16> [[VQSHRUN_N]], i32 3)
@@ -6454,7 +5799,7 @@ int8x8_t test_vqshrun_n_s16(int16x8_t a) {
return vqshrun_n_s16(a, 3);
}
-// CHECK-LABEL: define <4 x i16> @test_vqshrun_n_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vqshrun_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[VQSHRUN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VQSHRUN_N1:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqshrun.v4i16(<4 x i32> [[VQSHRUN_N]], i32 9)
@@ -6463,7 +5808,7 @@ int16x4_t test_vqshrun_n_s32(int32x4_t a) {
return vqshrun_n_s32(a, 9);
}
-// CHECK-LABEL: define <2 x i32> @test_vqshrun_n_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vqshrun_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[VQSHRUN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VQSHRUN_N1:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqshrun.v2i32(<2 x i64> [[VQSHRUN_N]], i32 19)
@@ -6472,7 +5817,7 @@ int32x2_t test_vqshrun_n_s64(int64x2_t a) {
return vqshrun_n_s64(a, 19);
}
-// CHECK-LABEL: define <16 x i8> @test_vqshrun_high_n_s16(<8 x i8> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqshrun_high_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[VQSHRUN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VQSHRUN_N1:%.*]] = call <8 x i8> @llvm.aarch64.neon.sqshrun.v8i8(<8 x i16> [[VQSHRUN_N]], i32 3)
@@ -6482,7 +5827,7 @@ int8x16_t test_vqshrun_high_n_s16(int8x8_t a, int16x8_t b) {
return vqshrun_high_n_s16(a, b, 3);
}
-// CHECK-LABEL: define <8 x i16> @test_vqshrun_high_n_s32(<4 x i16> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqshrun_high_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[VQSHRUN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VQSHRUN_N1:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqshrun.v4i16(<4 x i32> [[VQSHRUN_N]], i32 9)
@@ -6492,7 +5837,7 @@ int16x8_t test_vqshrun_high_n_s32(int16x4_t a, int32x4_t b) {
return vqshrun_high_n_s32(a, b, 9);
}
-// CHECK-LABEL: define <4 x i32> @test_vqshrun_high_n_s64(<2 x i32> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vqshrun_high_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %b to <16 x i8>
// CHECK: [[VQSHRUN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VQSHRUN_N1:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqshrun.v2i32(<2 x i64> [[VQSHRUN_N]], i32 19)
@@ -6502,7 +5847,7 @@ int32x4_t test_vqshrun_high_n_s64(int32x2_t a, int64x2_t b) {
return vqshrun_high_n_s64(a, b, 19);
}
-// CHECK-LABEL: define <8 x i8> @test_vrshrn_n_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vrshrn_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[VRSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VRSHRN_N1:%.*]] = call <8 x i8> @llvm.aarch64.neon.rshrn.v8i8(<8 x i16> [[VRSHRN_N]], i32 3)
@@ -6511,7 +5856,7 @@ int8x8_t test_vrshrn_n_s16(int16x8_t a) {
return vrshrn_n_s16(a, 3);
}
-// CHECK-LABEL: define <4 x i16> @test_vrshrn_n_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vrshrn_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[VRSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VRSHRN_N1:%.*]] = call <4 x i16> @llvm.aarch64.neon.rshrn.v4i16(<4 x i32> [[VRSHRN_N]], i32 9)
@@ -6520,7 +5865,7 @@ int16x4_t test_vrshrn_n_s32(int32x4_t a) {
return vrshrn_n_s32(a, 9);
}
-// CHECK-LABEL: define <2 x i32> @test_vrshrn_n_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vrshrn_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[VRSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VRSHRN_N1:%.*]] = call <2 x i32> @llvm.aarch64.neon.rshrn.v2i32(<2 x i64> [[VRSHRN_N]], i32 19)
@@ -6529,7 +5874,7 @@ int32x2_t test_vrshrn_n_s64(int64x2_t a) {
return vrshrn_n_s64(a, 19);
}
-// CHECK-LABEL: define <8 x i8> @test_vrshrn_n_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vrshrn_n_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[VRSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VRSHRN_N1:%.*]] = call <8 x i8> @llvm.aarch64.neon.rshrn.v8i8(<8 x i16> [[VRSHRN_N]], i32 3)
@@ -6538,7 +5883,7 @@ uint8x8_t test_vrshrn_n_u16(uint16x8_t a) {
return vrshrn_n_u16(a, 3);
}
-// CHECK-LABEL: define <4 x i16> @test_vrshrn_n_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vrshrn_n_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[VRSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VRSHRN_N1:%.*]] = call <4 x i16> @llvm.aarch64.neon.rshrn.v4i16(<4 x i32> [[VRSHRN_N]], i32 9)
@@ -6547,7 +5892,7 @@ uint16x4_t test_vrshrn_n_u32(uint32x4_t a) {
return vrshrn_n_u32(a, 9);
}
-// CHECK-LABEL: define <2 x i32> @test_vrshrn_n_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vrshrn_n_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[VRSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VRSHRN_N1:%.*]] = call <2 x i32> @llvm.aarch64.neon.rshrn.v2i32(<2 x i64> [[VRSHRN_N]], i32 19)
@@ -6556,7 +5901,7 @@ uint32x2_t test_vrshrn_n_u64(uint64x2_t a) {
return vrshrn_n_u64(a, 19);
}
-// CHECK-LABEL: define <16 x i8> @test_vrshrn_high_n_s16(<8 x i8> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vrshrn_high_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[VRSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VRSHRN_N1:%.*]] = call <8 x i8> @llvm.aarch64.neon.rshrn.v8i8(<8 x i16> [[VRSHRN_N]], i32 3)
@@ -6566,7 +5911,7 @@ int8x16_t test_vrshrn_high_n_s16(int8x8_t a, int16x8_t b) {
return vrshrn_high_n_s16(a, b, 3);
}
-// CHECK-LABEL: define <8 x i16> @test_vrshrn_high_n_s32(<4 x i16> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vrshrn_high_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[VRSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VRSHRN_N1:%.*]] = call <4 x i16> @llvm.aarch64.neon.rshrn.v4i16(<4 x i32> [[VRSHRN_N]], i32 9)
@@ -6576,7 +5921,7 @@ int16x8_t test_vrshrn_high_n_s32(int16x4_t a, int32x4_t b) {
return vrshrn_high_n_s32(a, b, 9);
}
-// CHECK-LABEL: define <4 x i32> @test_vrshrn_high_n_s64(<2 x i32> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vrshrn_high_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %b to <16 x i8>
// CHECK: [[VRSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VRSHRN_N1:%.*]] = call <2 x i32> @llvm.aarch64.neon.rshrn.v2i32(<2 x i64> [[VRSHRN_N]], i32 19)
@@ -6586,7 +5931,7 @@ int32x4_t test_vrshrn_high_n_s64(int32x2_t a, int64x2_t b) {
return vrshrn_high_n_s64(a, b, 19);
}
-// CHECK-LABEL: define <16 x i8> @test_vrshrn_high_n_u16(<8 x i8> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vrshrn_high_n_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[VRSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VRSHRN_N1:%.*]] = call <8 x i8> @llvm.aarch64.neon.rshrn.v8i8(<8 x i16> [[VRSHRN_N]], i32 3)
@@ -6596,7 +5941,7 @@ uint8x16_t test_vrshrn_high_n_u16(uint8x8_t a, uint16x8_t b) {
return vrshrn_high_n_u16(a, b, 3);
}
-// CHECK-LABEL: define <8 x i16> @test_vrshrn_high_n_u32(<4 x i16> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vrshrn_high_n_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[VRSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VRSHRN_N1:%.*]] = call <4 x i16> @llvm.aarch64.neon.rshrn.v4i16(<4 x i32> [[VRSHRN_N]], i32 9)
@@ -6606,7 +5951,7 @@ uint16x8_t test_vrshrn_high_n_u32(uint16x4_t a, uint32x4_t b) {
return vrshrn_high_n_u32(a, b, 9);
}
-// CHECK-LABEL: define <4 x i32> @test_vrshrn_high_n_u64(<2 x i32> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vrshrn_high_n_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %b to <16 x i8>
// CHECK: [[VRSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VRSHRN_N1:%.*]] = call <2 x i32> @llvm.aarch64.neon.rshrn.v2i32(<2 x i64> [[VRSHRN_N]], i32 19)
@@ -6616,7 +5961,7 @@ uint32x4_t test_vrshrn_high_n_u64(uint32x2_t a, uint64x2_t b) {
return vrshrn_high_n_u64(a, b, 19);
}
-// CHECK-LABEL: define <8 x i8> @test_vqrshrun_n_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vqrshrun_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[VQRSHRUN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VQRSHRUN_N1:%.*]] = call <8 x i8> @llvm.aarch64.neon.sqrshrun.v8i8(<8 x i16> [[VQRSHRUN_N]], i32 3)
@@ -6625,7 +5970,7 @@ int8x8_t test_vqrshrun_n_s16(int16x8_t a) {
return vqrshrun_n_s16(a, 3);
}
-// CHECK-LABEL: define <4 x i16> @test_vqrshrun_n_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vqrshrun_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[VQRSHRUN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VQRSHRUN_N1:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqrshrun.v4i16(<4 x i32> [[VQRSHRUN_N]], i32 9)
@@ -6634,7 +5979,7 @@ int16x4_t test_vqrshrun_n_s32(int32x4_t a) {
return vqrshrun_n_s32(a, 9);
}
-// CHECK-LABEL: define <2 x i32> @test_vqrshrun_n_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vqrshrun_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[VQRSHRUN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VQRSHRUN_N1:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqrshrun.v2i32(<2 x i64> [[VQRSHRUN_N]], i32 19)
@@ -6643,7 +5988,7 @@ int32x2_t test_vqrshrun_n_s64(int64x2_t a) {
return vqrshrun_n_s64(a, 19);
}
-// CHECK-LABEL: define <16 x i8> @test_vqrshrun_high_n_s16(<8 x i8> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqrshrun_high_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[VQRSHRUN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VQRSHRUN_N1:%.*]] = call <8 x i8> @llvm.aarch64.neon.sqrshrun.v8i8(<8 x i16> [[VQRSHRUN_N]], i32 3)
@@ -6653,7 +5998,7 @@ int8x16_t test_vqrshrun_high_n_s16(int8x8_t a, int16x8_t b) {
return vqrshrun_high_n_s16(a, b, 3);
}
-// CHECK-LABEL: define <8 x i16> @test_vqrshrun_high_n_s32(<4 x i16> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqrshrun_high_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[VQRSHRUN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VQRSHRUN_N1:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqrshrun.v4i16(<4 x i32> [[VQRSHRUN_N]], i32 9)
@@ -6663,7 +6008,7 @@ int16x8_t test_vqrshrun_high_n_s32(int16x4_t a, int32x4_t b) {
return vqrshrun_high_n_s32(a, b, 9);
}
-// CHECK-LABEL: define <4 x i32> @test_vqrshrun_high_n_s64(<2 x i32> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vqrshrun_high_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %b to <16 x i8>
// CHECK: [[VQRSHRUN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VQRSHRUN_N1:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqrshrun.v2i32(<2 x i64> [[VQRSHRUN_N]], i32 19)
@@ -6673,7 +6018,7 @@ int32x4_t test_vqrshrun_high_n_s64(int32x2_t a, int64x2_t b) {
return vqrshrun_high_n_s64(a, b, 19);
}
-// CHECK-LABEL: define <8 x i8> @test_vqshrn_n_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vqshrn_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[VQSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VQSHRN_N1:%.*]] = call <8 x i8> @llvm.aarch64.neon.sqshrn.v8i8(<8 x i16> [[VQSHRN_N]], i32 3)
@@ -6682,7 +6027,7 @@ int8x8_t test_vqshrn_n_s16(int16x8_t a) {
return vqshrn_n_s16(a, 3);
}
-// CHECK-LABEL: define <4 x i16> @test_vqshrn_n_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vqshrn_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[VQSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VQSHRN_N1:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqshrn.v4i16(<4 x i32> [[VQSHRN_N]], i32 9)
@@ -6691,7 +6036,7 @@ int16x4_t test_vqshrn_n_s32(int32x4_t a) {
return vqshrn_n_s32(a, 9);
}
-// CHECK-LABEL: define <2 x i32> @test_vqshrn_n_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vqshrn_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[VQSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VQSHRN_N1:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqshrn.v2i32(<2 x i64> [[VQSHRN_N]], i32 19)
@@ -6700,7 +6045,7 @@ int32x2_t test_vqshrn_n_s64(int64x2_t a) {
return vqshrn_n_s64(a, 19);
}
-// CHECK-LABEL: define <8 x i8> @test_vqshrn_n_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vqshrn_n_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[VQSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VQSHRN_N1:%.*]] = call <8 x i8> @llvm.aarch64.neon.uqshrn.v8i8(<8 x i16> [[VQSHRN_N]], i32 3)
@@ -6709,7 +6054,7 @@ uint8x8_t test_vqshrn_n_u16(uint16x8_t a) {
return vqshrn_n_u16(a, 3);
}
-// CHECK-LABEL: define <4 x i16> @test_vqshrn_n_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vqshrn_n_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[VQSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VQSHRN_N1:%.*]] = call <4 x i16> @llvm.aarch64.neon.uqshrn.v4i16(<4 x i32> [[VQSHRN_N]], i32 9)
@@ -6718,7 +6063,7 @@ uint16x4_t test_vqshrn_n_u32(uint32x4_t a) {
return vqshrn_n_u32(a, 9);
}
-// CHECK-LABEL: define <2 x i32> @test_vqshrn_n_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vqshrn_n_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[VQSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VQSHRN_N1:%.*]] = call <2 x i32> @llvm.aarch64.neon.uqshrn.v2i32(<2 x i64> [[VQSHRN_N]], i32 19)
@@ -6727,7 +6072,7 @@ uint32x2_t test_vqshrn_n_u64(uint64x2_t a) {
return vqshrn_n_u64(a, 19);
}
-// CHECK-LABEL: define <16 x i8> @test_vqshrn_high_n_s16(<8 x i8> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqshrn_high_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[VQSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VQSHRN_N1:%.*]] = call <8 x i8> @llvm.aarch64.neon.sqshrn.v8i8(<8 x i16> [[VQSHRN_N]], i32 3)
@@ -6737,7 +6082,7 @@ int8x16_t test_vqshrn_high_n_s16(int8x8_t a, int16x8_t b) {
return vqshrn_high_n_s16(a, b, 3);
}
-// CHECK-LABEL: define <8 x i16> @test_vqshrn_high_n_s32(<4 x i16> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqshrn_high_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[VQSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VQSHRN_N1:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqshrn.v4i16(<4 x i32> [[VQSHRN_N]], i32 9)
@@ -6747,7 +6092,7 @@ int16x8_t test_vqshrn_high_n_s32(int16x4_t a, int32x4_t b) {
return vqshrn_high_n_s32(a, b, 9);
}
-// CHECK-LABEL: define <4 x i32> @test_vqshrn_high_n_s64(<2 x i32> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vqshrn_high_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %b to <16 x i8>
// CHECK: [[VQSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VQSHRN_N1:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqshrn.v2i32(<2 x i64> [[VQSHRN_N]], i32 19)
@@ -6757,7 +6102,7 @@ int32x4_t test_vqshrn_high_n_s64(int32x2_t a, int64x2_t b) {
return vqshrn_high_n_s64(a, b, 19);
}
-// CHECK-LABEL: define <16 x i8> @test_vqshrn_high_n_u16(<8 x i8> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqshrn_high_n_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[VQSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VQSHRN_N1:%.*]] = call <8 x i8> @llvm.aarch64.neon.uqshrn.v8i8(<8 x i16> [[VQSHRN_N]], i32 3)
@@ -6767,7 +6112,7 @@ uint8x16_t test_vqshrn_high_n_u16(uint8x8_t a, uint16x8_t b) {
return vqshrn_high_n_u16(a, b, 3);
}
-// CHECK-LABEL: define <8 x i16> @test_vqshrn_high_n_u32(<4 x i16> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqshrn_high_n_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[VQSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VQSHRN_N1:%.*]] = call <4 x i16> @llvm.aarch64.neon.uqshrn.v4i16(<4 x i32> [[VQSHRN_N]], i32 9)
@@ -6777,7 +6122,7 @@ uint16x8_t test_vqshrn_high_n_u32(uint16x4_t a, uint32x4_t b) {
return vqshrn_high_n_u32(a, b, 9);
}
-// CHECK-LABEL: define <4 x i32> @test_vqshrn_high_n_u64(<2 x i32> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vqshrn_high_n_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %b to <16 x i8>
// CHECK: [[VQSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VQSHRN_N1:%.*]] = call <2 x i32> @llvm.aarch64.neon.uqshrn.v2i32(<2 x i64> [[VQSHRN_N]], i32 19)
@@ -6787,7 +6132,7 @@ uint32x4_t test_vqshrn_high_n_u64(uint32x2_t a, uint64x2_t b) {
return vqshrn_high_n_u64(a, b, 19);
}
-// CHECK-LABEL: define <8 x i8> @test_vqrshrn_n_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vqrshrn_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[VQRSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VQRSHRN_N1:%.*]] = call <8 x i8> @llvm.aarch64.neon.sqrshrn.v8i8(<8 x i16> [[VQRSHRN_N]], i32 3)
@@ -6796,7 +6141,7 @@ int8x8_t test_vqrshrn_n_s16(int16x8_t a) {
return vqrshrn_n_s16(a, 3);
}
-// CHECK-LABEL: define <4 x i16> @test_vqrshrn_n_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vqrshrn_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[VQRSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VQRSHRN_N1:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqrshrn.v4i16(<4 x i32> [[VQRSHRN_N]], i32 9)
@@ -6805,7 +6150,7 @@ int16x4_t test_vqrshrn_n_s32(int32x4_t a) {
return vqrshrn_n_s32(a, 9);
}
-// CHECK-LABEL: define <2 x i32> @test_vqrshrn_n_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vqrshrn_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[VQRSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VQRSHRN_N1:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqrshrn.v2i32(<2 x i64> [[VQRSHRN_N]], i32 19)
@@ -6814,7 +6159,7 @@ int32x2_t test_vqrshrn_n_s64(int64x2_t a) {
return vqrshrn_n_s64(a, 19);
}
-// CHECK-LABEL: define <8 x i8> @test_vqrshrn_n_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vqrshrn_n_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[VQRSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VQRSHRN_N1:%.*]] = call <8 x i8> @llvm.aarch64.neon.uqrshrn.v8i8(<8 x i16> [[VQRSHRN_N]], i32 3)
@@ -6823,7 +6168,7 @@ uint8x8_t test_vqrshrn_n_u16(uint16x8_t a) {
return vqrshrn_n_u16(a, 3);
}
-// CHECK-LABEL: define <4 x i16> @test_vqrshrn_n_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vqrshrn_n_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[VQRSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VQRSHRN_N1:%.*]] = call <4 x i16> @llvm.aarch64.neon.uqrshrn.v4i16(<4 x i32> [[VQRSHRN_N]], i32 9)
@@ -6832,7 +6177,7 @@ uint16x4_t test_vqrshrn_n_u32(uint32x4_t a) {
return vqrshrn_n_u32(a, 9);
}
-// CHECK-LABEL: define <2 x i32> @test_vqrshrn_n_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vqrshrn_n_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[VQRSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VQRSHRN_N1:%.*]] = call <2 x i32> @llvm.aarch64.neon.uqrshrn.v2i32(<2 x i64> [[VQRSHRN_N]], i32 19)
@@ -6841,7 +6186,7 @@ uint32x2_t test_vqrshrn_n_u64(uint64x2_t a) {
return vqrshrn_n_u64(a, 19);
}
-// CHECK-LABEL: define <16 x i8> @test_vqrshrn_high_n_s16(<8 x i8> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqrshrn_high_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[VQRSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VQRSHRN_N1:%.*]] = call <8 x i8> @llvm.aarch64.neon.sqrshrn.v8i8(<8 x i16> [[VQRSHRN_N]], i32 3)
@@ -6851,7 +6196,7 @@ int8x16_t test_vqrshrn_high_n_s16(int8x8_t a, int16x8_t b) {
return vqrshrn_high_n_s16(a, b, 3);
}
-// CHECK-LABEL: define <8 x i16> @test_vqrshrn_high_n_s32(<4 x i16> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqrshrn_high_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[VQRSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VQRSHRN_N1:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqrshrn.v4i16(<4 x i32> [[VQRSHRN_N]], i32 9)
@@ -6861,7 +6206,7 @@ int16x8_t test_vqrshrn_high_n_s32(int16x4_t a, int32x4_t b) {
return vqrshrn_high_n_s32(a, b, 9);
}
-// CHECK-LABEL: define <4 x i32> @test_vqrshrn_high_n_s64(<2 x i32> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vqrshrn_high_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %b to <16 x i8>
// CHECK: [[VQRSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VQRSHRN_N1:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqrshrn.v2i32(<2 x i64> [[VQRSHRN_N]], i32 19)
@@ -6871,7 +6216,7 @@ int32x4_t test_vqrshrn_high_n_s64(int32x2_t a, int64x2_t b) {
return vqrshrn_high_n_s64(a, b, 19);
}
-// CHECK-LABEL: define <16 x i8> @test_vqrshrn_high_n_u16(<8 x i8> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqrshrn_high_n_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[VQRSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VQRSHRN_N1:%.*]] = call <8 x i8> @llvm.aarch64.neon.uqrshrn.v8i8(<8 x i16> [[VQRSHRN_N]], i32 3)
@@ -6881,7 +6226,7 @@ uint8x16_t test_vqrshrn_high_n_u16(uint8x8_t a, uint16x8_t b) {
return vqrshrn_high_n_u16(a, b, 3);
}
-// CHECK-LABEL: define <8 x i16> @test_vqrshrn_high_n_u32(<4 x i16> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqrshrn_high_n_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[VQRSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VQRSHRN_N1:%.*]] = call <4 x i16> @llvm.aarch64.neon.uqrshrn.v4i16(<4 x i32> [[VQRSHRN_N]], i32 9)
@@ -6891,7 +6236,7 @@ uint16x8_t test_vqrshrn_high_n_u32(uint16x4_t a, uint32x4_t b) {
return vqrshrn_high_n_u32(a, b, 9);
}
-// CHECK-LABEL: define <4 x i32> @test_vqrshrn_high_n_u64(<2 x i32> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vqrshrn_high_n_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %b to <16 x i8>
// CHECK: [[VQRSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VQRSHRN_N1:%.*]] = call <2 x i32> @llvm.aarch64.neon.uqrshrn.v2i32(<2 x i64> [[VQRSHRN_N]], i32 19)
@@ -6901,7 +6246,7 @@ uint32x4_t test_vqrshrn_high_n_u64(uint32x2_t a, uint64x2_t b) {
return vqrshrn_high_n_u64(a, b, 19);
}
-// CHECK-LABEL: define <8 x i16> @test_vshll_n_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vshll_n_s8(
// CHECK: [[TMP0:%.*]] = sext <8 x i8> %a to <8 x i16>
// CHECK: [[VSHLL_N:%.*]] = shl <8 x i16> [[TMP0]], <i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3>
// CHECK: ret <8 x i16> [[VSHLL_N]]
@@ -6909,7 +6254,7 @@ int16x8_t test_vshll_n_s8(int8x8_t a) {
return vshll_n_s8(a, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vshll_n_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vshll_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
// CHECK: [[TMP2:%.*]] = sext <4 x i16> [[TMP1]] to <4 x i32>
@@ -6919,7 +6264,7 @@ int32x4_t test_vshll_n_s16(int16x4_t a) {
return vshll_n_s16(a, 9);
}
-// CHECK-LABEL: define <2 x i64> @test_vshll_n_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vshll_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
// CHECK: [[TMP2:%.*]] = sext <2 x i32> [[TMP1]] to <2 x i64>
@@ -6929,7 +6274,7 @@ int64x2_t test_vshll_n_s32(int32x2_t a) {
return vshll_n_s32(a, 19);
}
-// CHECK-LABEL: define <8 x i16> @test_vshll_n_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vshll_n_u8(
// CHECK: [[TMP0:%.*]] = zext <8 x i8> %a to <8 x i16>
// CHECK: [[VSHLL_N:%.*]] = shl <8 x i16> [[TMP0]], <i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3>
// CHECK: ret <8 x i16> [[VSHLL_N]]
@@ -6937,7 +6282,7 @@ uint16x8_t test_vshll_n_u8(uint8x8_t a) {
return vshll_n_u8(a, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vshll_n_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vshll_n_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
// CHECK: [[TMP2:%.*]] = zext <4 x i16> [[TMP1]] to <4 x i32>
@@ -6947,7 +6292,7 @@ uint32x4_t test_vshll_n_u16(uint16x4_t a) {
return vshll_n_u16(a, 9);
}
-// CHECK-LABEL: define <2 x i64> @test_vshll_n_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vshll_n_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
// CHECK: [[TMP2:%.*]] = zext <2 x i32> [[TMP1]] to <2 x i64>
@@ -6957,7 +6302,7 @@ uint64x2_t test_vshll_n_u32(uint32x2_t a) {
return vshll_n_u32(a, 19);
}
-// CHECK-LABEL: define <8 x i16> @test_vshll_high_n_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vshll_high_n_s8(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %a, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: [[TMP0:%.*]] = sext <8 x i8> [[SHUFFLE_I]] to <8 x i16>
// CHECK: [[VSHLL_N:%.*]] = shl <8 x i16> [[TMP0]], <i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3>
@@ -6966,7 +6311,7 @@ int16x8_t test_vshll_high_n_s8(int8x16_t a) {
return vshll_high_n_s8(a, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vshll_high_n_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vshll_high_n_s16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %a, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
@@ -6977,7 +6322,7 @@ int32x4_t test_vshll_high_n_s16(int16x8_t a) {
return vshll_high_n_s16(a, 9);
}
-// CHECK-LABEL: define <2 x i64> @test_vshll_high_n_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vshll_high_n_s32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %a, <2 x i32> <i32 2, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
@@ -6988,7 +6333,7 @@ int64x2_t test_vshll_high_n_s32(int32x4_t a) {
return vshll_high_n_s32(a, 19);
}
-// CHECK-LABEL: define <8 x i16> @test_vshll_high_n_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vshll_high_n_u8(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %a, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: [[TMP0:%.*]] = zext <8 x i8> [[SHUFFLE_I]] to <8 x i16>
// CHECK: [[VSHLL_N:%.*]] = shl <8 x i16> [[TMP0]], <i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3>
@@ -6997,7 +6342,7 @@ uint16x8_t test_vshll_high_n_u8(uint8x16_t a) {
return vshll_high_n_u8(a, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vshll_high_n_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vshll_high_n_u16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %a, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
@@ -7008,7 +6353,7 @@ uint32x4_t test_vshll_high_n_u16(uint16x8_t a) {
return vshll_high_n_u16(a, 9);
}
-// CHECK-LABEL: define <2 x i64> @test_vshll_high_n_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vshll_high_n_u32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %a, <2 x i32> <i32 2, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
@@ -7019,57 +6364,53 @@ uint64x2_t test_vshll_high_n_u32(uint32x4_t a) {
return vshll_high_n_u32(a, 19);
}
-// CHECK-LABEL: define <8 x i16> @test_vmovl_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vmovl_s8(
// CHECK: [[VMOVL_I:%.*]] = sext <8 x i8> %a to <8 x i16>
// CHECK: ret <8 x i16> [[VMOVL_I]]
int16x8_t test_vmovl_s8(int8x8_t a) {
return vmovl_s8(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vmovl_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vmovl_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMOVL_I:%.*]] = sext <4 x i16> [[TMP1]] to <4 x i32>
+// CHECK: [[VMOVL_I:%.*]] = sext <4 x i16> %a to <4 x i32>
// CHECK: ret <4 x i32> [[VMOVL_I]]
int32x4_t test_vmovl_s16(int16x4_t a) {
return vmovl_s16(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vmovl_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vmovl_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMOVL_I:%.*]] = sext <2 x i32> [[TMP1]] to <2 x i64>
+// CHECK: [[VMOVL_I:%.*]] = sext <2 x i32> %a to <2 x i64>
// CHECK: ret <2 x i64> [[VMOVL_I]]
int64x2_t test_vmovl_s32(int32x2_t a) {
return vmovl_s32(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vmovl_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vmovl_u8(
// CHECK: [[VMOVL_I:%.*]] = zext <8 x i8> %a to <8 x i16>
// CHECK: ret <8 x i16> [[VMOVL_I]]
uint16x8_t test_vmovl_u8(uint8x8_t a) {
return vmovl_u8(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vmovl_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vmovl_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMOVL_I:%.*]] = zext <4 x i16> [[TMP1]] to <4 x i32>
+// CHECK: [[VMOVL_I:%.*]] = zext <4 x i16> %a to <4 x i32>
// CHECK: ret <4 x i32> [[VMOVL_I]]
uint32x4_t test_vmovl_u16(uint16x4_t a) {
return vmovl_u16(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vmovl_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vmovl_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMOVL_I:%.*]] = zext <2 x i32> [[TMP1]] to <2 x i64>
+// CHECK: [[VMOVL_I:%.*]] = zext <2 x i32> %a to <2 x i64>
// CHECK: ret <2 x i64> [[VMOVL_I]]
uint64x2_t test_vmovl_u32(uint32x2_t a) {
return vmovl_u32(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vmovl_high_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vmovl_high_s8(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %a, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: [[TMP0:%.*]] = sext <8 x i8> [[SHUFFLE_I_I]] to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
@@ -7077,27 +6418,25 @@ int16x8_t test_vmovl_high_s8(int8x16_t a) {
return vmovl_high_s8(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vmovl_high_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vmovl_high_s16(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %a, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[TMP2:%.*]] = sext <4 x i16> [[TMP1]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: [[TMP1:%.*]] = sext <4 x i16> [[SHUFFLE_I_I]] to <4 x i32>
+// CHECK: ret <4 x i32> [[TMP1]]
int32x4_t test_vmovl_high_s16(int16x8_t a) {
return vmovl_high_s16(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vmovl_high_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vmovl_high_s32(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %a, <2 x i32> <i32 2, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[TMP2:%.*]] = sext <2 x i32> [[TMP1]] to <2 x i64>
-// CHECK: ret <2 x i64> [[TMP2]]
+// CHECK: [[TMP1:%.*]] = sext <2 x i32> [[SHUFFLE_I_I]] to <2 x i64>
+// CHECK: ret <2 x i64> [[TMP1]]
int64x2_t test_vmovl_high_s32(int32x4_t a) {
return vmovl_high_s32(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vmovl_high_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vmovl_high_u8(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %a, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: [[TMP0:%.*]] = zext <8 x i8> [[SHUFFLE_I_I]] to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
@@ -7105,27 +6444,25 @@ uint16x8_t test_vmovl_high_u8(uint8x16_t a) {
return vmovl_high_u8(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vmovl_high_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vmovl_high_u16(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %a, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[TMP2:%.*]] = zext <4 x i16> [[TMP1]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: [[TMP1:%.*]] = zext <4 x i16> [[SHUFFLE_I_I]] to <4 x i32>
+// CHECK: ret <4 x i32> [[TMP1]]
uint32x4_t test_vmovl_high_u16(uint16x8_t a) {
return vmovl_high_u16(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vmovl_high_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vmovl_high_u32(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %a, <2 x i32> <i32 2, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[TMP2:%.*]] = zext <2 x i32> [[TMP1]] to <2 x i64>
-// CHECK: ret <2 x i64> [[TMP2]]
+// CHECK: [[TMP1:%.*]] = zext <2 x i32> [[SHUFFLE_I_I]] to <2 x i64>
+// CHECK: ret <2 x i64> [[TMP1]]
uint64x2_t test_vmovl_high_u32(uint32x4_t a) {
return vmovl_high_u32(a);
}
-// CHECK-LABEL: define <2 x float> @test_vcvt_n_f32_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vcvt_n_f32_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[VCVT_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
// CHECK: [[VCVT_N1:%.*]] = call <2 x float> @llvm.aarch64.neon.vcvtfxs2fp.v2f32.v2i32(<2 x i32> [[VCVT_N]], i32 31)
@@ -7134,7 +6471,7 @@ float32x2_t test_vcvt_n_f32_s32(int32x2_t a) {
return vcvt_n_f32_s32(a, 31);
}
-// CHECK-LABEL: define <4 x float> @test_vcvtq_n_f32_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vcvtq_n_f32_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[VCVT_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VCVT_N1:%.*]] = call <4 x float> @llvm.aarch64.neon.vcvtfxs2fp.v4f32.v4i32(<4 x i32> [[VCVT_N]], i32 31)
@@ -7143,7 +6480,7 @@ float32x4_t test_vcvtq_n_f32_s32(int32x4_t a) {
return vcvtq_n_f32_s32(a, 31);
}
-// CHECK-LABEL: define <2 x double> @test_vcvtq_n_f64_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vcvtq_n_f64_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[VCVT_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VCVT_N1:%.*]] = call <2 x double> @llvm.aarch64.neon.vcvtfxs2fp.v2f64.v2i64(<2 x i64> [[VCVT_N]], i32 50)
@@ -7152,7 +6489,7 @@ float64x2_t test_vcvtq_n_f64_s64(int64x2_t a) {
return vcvtq_n_f64_s64(a, 50);
}
-// CHECK-LABEL: define <2 x float> @test_vcvt_n_f32_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vcvt_n_f32_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[VCVT_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
// CHECK: [[VCVT_N1:%.*]] = call <2 x float> @llvm.aarch64.neon.vcvtfxu2fp.v2f32.v2i32(<2 x i32> [[VCVT_N]], i32 31)
@@ -7161,7 +6498,7 @@ float32x2_t test_vcvt_n_f32_u32(uint32x2_t a) {
return vcvt_n_f32_u32(a, 31);
}
-// CHECK-LABEL: define <4 x float> @test_vcvtq_n_f32_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vcvtq_n_f32_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[VCVT_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VCVT_N1:%.*]] = call <4 x float> @llvm.aarch64.neon.vcvtfxu2fp.v4f32.v4i32(<4 x i32> [[VCVT_N]], i32 31)
@@ -7170,7 +6507,7 @@ float32x4_t test_vcvtq_n_f32_u32(uint32x4_t a) {
return vcvtq_n_f32_u32(a, 31);
}
-// CHECK-LABEL: define <2 x double> @test_vcvtq_n_f64_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vcvtq_n_f64_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[VCVT_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VCVT_N1:%.*]] = call <2 x double> @llvm.aarch64.neon.vcvtfxu2fp.v2f64.v2i64(<2 x i64> [[VCVT_N]], i32 50)
@@ -7179,7 +6516,7 @@ float64x2_t test_vcvtq_n_f64_u64(uint64x2_t a) {
return vcvtq_n_f64_u64(a, 50);
}
-// CHECK-LABEL: define <2 x i32> @test_vcvt_n_s32_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vcvt_n_s32_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[VCVT_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
// CHECK: [[VCVT_N1:%.*]] = call <2 x i32> @llvm.aarch64.neon.vcvtfp2fxs.v2i32.v2f32(<2 x float> [[VCVT_N]], i32 31)
@@ -7188,7 +6525,7 @@ int32x2_t test_vcvt_n_s32_f32(float32x2_t a) {
return vcvt_n_s32_f32(a, 31);
}
-// CHECK-LABEL: define <4 x i32> @test_vcvtq_n_s32_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vcvtq_n_s32_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[VCVT_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
// CHECK: [[VCVT_N1:%.*]] = call <4 x i32> @llvm.aarch64.neon.vcvtfp2fxs.v4i32.v4f32(<4 x float> [[VCVT_N]], i32 31)
@@ -7197,7 +6534,7 @@ int32x4_t test_vcvtq_n_s32_f32(float32x4_t a) {
return vcvtq_n_s32_f32(a, 31);
}
-// CHECK-LABEL: define <2 x i64> @test_vcvtq_n_s64_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vcvtq_n_s64_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
// CHECK: [[VCVT_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
// CHECK: [[VCVT_N1:%.*]] = call <2 x i64> @llvm.aarch64.neon.vcvtfp2fxs.v2i64.v2f64(<2 x double> [[VCVT_N]], i32 50)
@@ -7206,7 +6543,7 @@ int64x2_t test_vcvtq_n_s64_f64(float64x2_t a) {
return vcvtq_n_s64_f64(a, 50);
}
-// CHECK-LABEL: define <2 x i32> @test_vcvt_n_u32_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vcvt_n_u32_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[VCVT_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
// CHECK: [[VCVT_N1:%.*]] = call <2 x i32> @llvm.aarch64.neon.vcvtfp2fxu.v2i32.v2f32(<2 x float> [[VCVT_N]], i32 31)
@@ -7215,7 +6552,7 @@ uint32x2_t test_vcvt_n_u32_f32(float32x2_t a) {
return vcvt_n_u32_f32(a, 31);
}
-// CHECK-LABEL: define <4 x i32> @test_vcvtq_n_u32_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vcvtq_n_u32_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[VCVT_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
// CHECK: [[VCVT_N1:%.*]] = call <4 x i32> @llvm.aarch64.neon.vcvtfp2fxu.v4i32.v4f32(<4 x float> [[VCVT_N]], i32 31)
@@ -7224,7 +6561,7 @@ uint32x4_t test_vcvtq_n_u32_f32(float32x4_t a) {
return vcvtq_n_u32_f32(a, 31);
}
-// CHECK-LABEL: define <2 x i64> @test_vcvtq_n_u64_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vcvtq_n_u64_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
// CHECK: [[VCVT_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
// CHECK: [[VCVT_N1:%.*]] = call <2 x i64> @llvm.aarch64.neon.vcvtfp2fxu.v2i64.v2f64(<2 x double> [[VCVT_N]], i32 50)
@@ -7233,7 +6570,7 @@ uint64x2_t test_vcvtq_n_u64_f64(float64x2_t a) {
return vcvtq_n_u64_f64(a, 50);
}
-// CHECK-LABEL: define <8 x i16> @test_vaddl_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vaddl_s8(
// CHECK: [[VMOVL_I_I:%.*]] = sext <8 x i8> %a to <8 x i16>
// CHECK: [[VMOVL_I4_I:%.*]] = sext <8 x i8> %b to <8 x i16>
// CHECK: [[ADD_I:%.*]] = add <8 x i16> [[VMOVL_I_I]], [[VMOVL_I4_I]]
@@ -7242,33 +6579,29 @@ int16x8_t test_vaddl_s8(int8x8_t a, int8x8_t b) {
return vaddl_s8(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vaddl_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vaddl_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMOVL_I_I:%.*]] = sext <4 x i16> [[TMP1]] to <4 x i32>
-// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VMOVL_I4_I:%.*]] = sext <4 x i16> [[TMP3]] to <4 x i32>
+// CHECK: [[VMOVL_I_I:%.*]] = sext <4 x i16> %a to <4 x i32>
+// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
+// CHECK: [[VMOVL_I4_I:%.*]] = sext <4 x i16> %b to <4 x i32>
// CHECK: [[ADD_I:%.*]] = add <4 x i32> [[VMOVL_I_I]], [[VMOVL_I4_I]]
// CHECK: ret <4 x i32> [[ADD_I]]
int32x4_t test_vaddl_s16(int16x4_t a, int16x4_t b) {
return vaddl_s16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vaddl_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vaddl_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMOVL_I_I:%.*]] = sext <2 x i32> [[TMP1]] to <2 x i64>
-// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VMOVL_I4_I:%.*]] = sext <2 x i32> [[TMP3]] to <2 x i64>
+// CHECK: [[VMOVL_I_I:%.*]] = sext <2 x i32> %a to <2 x i64>
+// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
+// CHECK: [[VMOVL_I4_I:%.*]] = sext <2 x i32> %b to <2 x i64>
// CHECK: [[ADD_I:%.*]] = add <2 x i64> [[VMOVL_I_I]], [[VMOVL_I4_I]]
// CHECK: ret <2 x i64> [[ADD_I]]
int64x2_t test_vaddl_s32(int32x2_t a, int32x2_t b) {
return vaddl_s32(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vaddl_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vaddl_u8(
// CHECK: [[VMOVL_I_I:%.*]] = zext <8 x i8> %a to <8 x i16>
// CHECK: [[VMOVL_I4_I:%.*]] = zext <8 x i8> %b to <8 x i16>
// CHECK: [[ADD_I:%.*]] = add <8 x i16> [[VMOVL_I_I]], [[VMOVL_I4_I]]
@@ -7277,33 +6610,29 @@ uint16x8_t test_vaddl_u8(uint8x8_t a, uint8x8_t b) {
return vaddl_u8(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vaddl_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vaddl_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMOVL_I_I:%.*]] = zext <4 x i16> [[TMP1]] to <4 x i32>
-// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VMOVL_I4_I:%.*]] = zext <4 x i16> [[TMP3]] to <4 x i32>
+// CHECK: [[VMOVL_I_I:%.*]] = zext <4 x i16> %a to <4 x i32>
+// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
+// CHECK: [[VMOVL_I4_I:%.*]] = zext <4 x i16> %b to <4 x i32>
// CHECK: [[ADD_I:%.*]] = add <4 x i32> [[VMOVL_I_I]], [[VMOVL_I4_I]]
// CHECK: ret <4 x i32> [[ADD_I]]
uint32x4_t test_vaddl_u16(uint16x4_t a, uint16x4_t b) {
return vaddl_u16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vaddl_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vaddl_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMOVL_I_I:%.*]] = zext <2 x i32> [[TMP1]] to <2 x i64>
-// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VMOVL_I4_I:%.*]] = zext <2 x i32> [[TMP3]] to <2 x i64>
+// CHECK: [[VMOVL_I_I:%.*]] = zext <2 x i32> %a to <2 x i64>
+// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
+// CHECK: [[VMOVL_I4_I:%.*]] = zext <2 x i32> %b to <2 x i64>
// CHECK: [[ADD_I:%.*]] = add <2 x i64> [[VMOVL_I_I]], [[VMOVL_I4_I]]
// CHECK: ret <2 x i64> [[ADD_I]]
uint64x2_t test_vaddl_u32(uint32x2_t a, uint32x2_t b) {
return vaddl_u32(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vaddl_high_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vaddl_high_s8(
// CHECK: [[SHUFFLE_I_I_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %a, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: [[TMP0:%.*]] = sext <8 x i8> [[SHUFFLE_I_I_I]] to <8 x i16>
// CHECK: [[SHUFFLE_I_I10_I:%.*]] = shufflevector <16 x i8> %b, <16 x i8> %b, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
@@ -7314,37 +6643,33 @@ int16x8_t test_vaddl_high_s8(int8x16_t a, int8x16_t b) {
return vaddl_high_s8(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vaddl_high_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vaddl_high_s16(
// CHECK: [[SHUFFLE_I_I_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %a, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[TMP2:%.*]] = sext <4 x i16> [[TMP1]] to <4 x i32>
+// CHECK: [[TMP1:%.*]] = sext <4 x i16> [[SHUFFLE_I_I_I]] to <4 x i32>
// CHECK: [[SHUFFLE_I_I10_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
-// CHECK: [[TMP3:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I10_I]] to <8 x i8>
-// CHECK: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP3]] to <4 x i16>
-// CHECK: [[TMP5:%.*]] = sext <4 x i16> [[TMP4]] to <4 x i32>
-// CHECK: [[ADD_I:%.*]] = add <4 x i32> [[TMP2]], [[TMP5]]
+// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I10_I]] to <8 x i8>
+// CHECK: [[TMP3:%.*]] = sext <4 x i16> [[SHUFFLE_I_I10_I]] to <4 x i32>
+// CHECK: [[ADD_I:%.*]] = add <4 x i32> [[TMP1]], [[TMP3]]
// CHECK: ret <4 x i32> [[ADD_I]]
int32x4_t test_vaddl_high_s16(int16x8_t a, int16x8_t b) {
return vaddl_high_s16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vaddl_high_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vaddl_high_s32(
// CHECK: [[SHUFFLE_I_I_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %a, <2 x i32> <i32 2, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[TMP2:%.*]] = sext <2 x i32> [[TMP1]] to <2 x i64>
+// CHECK: [[TMP1:%.*]] = sext <2 x i32> [[SHUFFLE_I_I_I]] to <2 x i64>
// CHECK: [[SHUFFLE_I_I10_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
-// CHECK: [[TMP3:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I10_I]] to <8 x i8>
-// CHECK: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP3]] to <2 x i32>
-// CHECK: [[TMP5:%.*]] = sext <2 x i32> [[TMP4]] to <2 x i64>
-// CHECK: [[ADD_I:%.*]] = add <2 x i64> [[TMP2]], [[TMP5]]
+// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I10_I]] to <8 x i8>
+// CHECK: [[TMP3:%.*]] = sext <2 x i32> [[SHUFFLE_I_I10_I]] to <2 x i64>
+// CHECK: [[ADD_I:%.*]] = add <2 x i64> [[TMP1]], [[TMP3]]
// CHECK: ret <2 x i64> [[ADD_I]]
int64x2_t test_vaddl_high_s32(int32x4_t a, int32x4_t b) {
return vaddl_high_s32(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vaddl_high_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vaddl_high_u8(
// CHECK: [[SHUFFLE_I_I_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %a, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: [[TMP0:%.*]] = zext <8 x i8> [[SHUFFLE_I_I_I]] to <8 x i16>
// CHECK: [[SHUFFLE_I_I10_I:%.*]] = shufflevector <16 x i8> %b, <16 x i8> %b, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
@@ -7355,37 +6680,33 @@ uint16x8_t test_vaddl_high_u8(uint8x16_t a, uint8x16_t b) {
return vaddl_high_u8(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vaddl_high_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vaddl_high_u16(
// CHECK: [[SHUFFLE_I_I_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %a, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[TMP2:%.*]] = zext <4 x i16> [[TMP1]] to <4 x i32>
+// CHECK: [[TMP1:%.*]] = zext <4 x i16> [[SHUFFLE_I_I_I]] to <4 x i32>
// CHECK: [[SHUFFLE_I_I10_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
-// CHECK: [[TMP3:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I10_I]] to <8 x i8>
-// CHECK: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP3]] to <4 x i16>
-// CHECK: [[TMP5:%.*]] = zext <4 x i16> [[TMP4]] to <4 x i32>
-// CHECK: [[ADD_I:%.*]] = add <4 x i32> [[TMP2]], [[TMP5]]
+// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I10_I]] to <8 x i8>
+// CHECK: [[TMP3:%.*]] = zext <4 x i16> [[SHUFFLE_I_I10_I]] to <4 x i32>
+// CHECK: [[ADD_I:%.*]] = add <4 x i32> [[TMP1]], [[TMP3]]
// CHECK: ret <4 x i32> [[ADD_I]]
uint32x4_t test_vaddl_high_u16(uint16x8_t a, uint16x8_t b) {
return vaddl_high_u16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vaddl_high_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vaddl_high_u32(
// CHECK: [[SHUFFLE_I_I_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %a, <2 x i32> <i32 2, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[TMP2:%.*]] = zext <2 x i32> [[TMP1]] to <2 x i64>
+// CHECK: [[TMP1:%.*]] = zext <2 x i32> [[SHUFFLE_I_I_I]] to <2 x i64>
// CHECK: [[SHUFFLE_I_I10_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
-// CHECK: [[TMP3:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I10_I]] to <8 x i8>
-// CHECK: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP3]] to <2 x i32>
-// CHECK: [[TMP5:%.*]] = zext <2 x i32> [[TMP4]] to <2 x i64>
-// CHECK: [[ADD_I:%.*]] = add <2 x i64> [[TMP2]], [[TMP5]]
+// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I10_I]] to <8 x i8>
+// CHECK: [[TMP3:%.*]] = zext <2 x i32> [[SHUFFLE_I_I10_I]] to <2 x i64>
+// CHECK: [[ADD_I:%.*]] = add <2 x i64> [[TMP1]], [[TMP3]]
// CHECK: ret <2 x i64> [[ADD_I]]
uint64x2_t test_vaddl_high_u32(uint32x4_t a, uint32x4_t b) {
return vaddl_high_u32(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vaddw_s8(<8 x i16> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vaddw_s8(
// CHECK: [[VMOVL_I_I:%.*]] = sext <8 x i8> %b to <8 x i16>
// CHECK: [[ADD_I:%.*]] = add <8 x i16> %a, [[VMOVL_I_I]]
// CHECK: ret <8 x i16> [[ADD_I]]
@@ -7393,27 +6714,25 @@ int16x8_t test_vaddw_s8(int16x8_t a, int8x8_t b) {
return vaddw_s8(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vaddw_s16(<4 x i32> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vaddw_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMOVL_I_I:%.*]] = sext <4 x i16> [[TMP1]] to <4 x i32>
+// CHECK: [[VMOVL_I_I:%.*]] = sext <4 x i16> %b to <4 x i32>
// CHECK: [[ADD_I:%.*]] = add <4 x i32> %a, [[VMOVL_I_I]]
// CHECK: ret <4 x i32> [[ADD_I]]
int32x4_t test_vaddw_s16(int32x4_t a, int16x4_t b) {
return vaddw_s16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vaddw_s32(<2 x i64> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vaddw_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMOVL_I_I:%.*]] = sext <2 x i32> [[TMP1]] to <2 x i64>
+// CHECK: [[VMOVL_I_I:%.*]] = sext <2 x i32> %b to <2 x i64>
// CHECK: [[ADD_I:%.*]] = add <2 x i64> %a, [[VMOVL_I_I]]
// CHECK: ret <2 x i64> [[ADD_I]]
int64x2_t test_vaddw_s32(int64x2_t a, int32x2_t b) {
return vaddw_s32(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vaddw_u8(<8 x i16> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vaddw_u8(
// CHECK: [[VMOVL_I_I:%.*]] = zext <8 x i8> %b to <8 x i16>
// CHECK: [[ADD_I:%.*]] = add <8 x i16> %a, [[VMOVL_I_I]]
// CHECK: ret <8 x i16> [[ADD_I]]
@@ -7421,27 +6740,25 @@ uint16x8_t test_vaddw_u8(uint16x8_t a, uint8x8_t b) {
return vaddw_u8(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vaddw_u16(<4 x i32> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vaddw_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMOVL_I_I:%.*]] = zext <4 x i16> [[TMP1]] to <4 x i32>
+// CHECK: [[VMOVL_I_I:%.*]] = zext <4 x i16> %b to <4 x i32>
// CHECK: [[ADD_I:%.*]] = add <4 x i32> %a, [[VMOVL_I_I]]
// CHECK: ret <4 x i32> [[ADD_I]]
uint32x4_t test_vaddw_u16(uint32x4_t a, uint16x4_t b) {
return vaddw_u16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vaddw_u32(<2 x i64> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vaddw_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMOVL_I_I:%.*]] = zext <2 x i32> [[TMP1]] to <2 x i64>
+// CHECK: [[VMOVL_I_I:%.*]] = zext <2 x i32> %b to <2 x i64>
// CHECK: [[ADD_I:%.*]] = add <2 x i64> %a, [[VMOVL_I_I]]
// CHECK: ret <2 x i64> [[ADD_I]]
uint64x2_t test_vaddw_u32(uint64x2_t a, uint32x2_t b) {
return vaddw_u32(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vaddw_high_s8(<8 x i16> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vaddw_high_s8(
// CHECK: [[SHUFFLE_I_I_I:%.*]] = shufflevector <16 x i8> %b, <16 x i8> %b, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: [[TMP0:%.*]] = sext <8 x i8> [[SHUFFLE_I_I_I]] to <8 x i16>
// CHECK: [[ADD_I:%.*]] = add <8 x i16> %a, [[TMP0]]
@@ -7450,29 +6767,27 @@ int16x8_t test_vaddw_high_s8(int16x8_t a, int8x16_t b) {
return vaddw_high_s8(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vaddw_high_s16(<4 x i32> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vaddw_high_s16(
// CHECK: [[SHUFFLE_I_I_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[TMP2:%.*]] = sext <4 x i16> [[TMP1]] to <4 x i32>
-// CHECK: [[ADD_I:%.*]] = add <4 x i32> %a, [[TMP2]]
+// CHECK: [[TMP1:%.*]] = sext <4 x i16> [[SHUFFLE_I_I_I]] to <4 x i32>
+// CHECK: [[ADD_I:%.*]] = add <4 x i32> %a, [[TMP1]]
// CHECK: ret <4 x i32> [[ADD_I]]
int32x4_t test_vaddw_high_s16(int32x4_t a, int16x8_t b) {
return vaddw_high_s16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vaddw_high_s32(<2 x i64> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vaddw_high_s32(
// CHECK: [[SHUFFLE_I_I_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[TMP2:%.*]] = sext <2 x i32> [[TMP1]] to <2 x i64>
-// CHECK: [[ADD_I:%.*]] = add <2 x i64> %a, [[TMP2]]
+// CHECK: [[TMP1:%.*]] = sext <2 x i32> [[SHUFFLE_I_I_I]] to <2 x i64>
+// CHECK: [[ADD_I:%.*]] = add <2 x i64> %a, [[TMP1]]
// CHECK: ret <2 x i64> [[ADD_I]]
int64x2_t test_vaddw_high_s32(int64x2_t a, int32x4_t b) {
return vaddw_high_s32(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vaddw_high_u8(<8 x i16> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vaddw_high_u8(
// CHECK: [[SHUFFLE_I_I_I:%.*]] = shufflevector <16 x i8> %b, <16 x i8> %b, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: [[TMP0:%.*]] = zext <8 x i8> [[SHUFFLE_I_I_I]] to <8 x i16>
// CHECK: [[ADD_I:%.*]] = add <8 x i16> %a, [[TMP0]]
@@ -7481,29 +6796,27 @@ uint16x8_t test_vaddw_high_u8(uint16x8_t a, uint8x16_t b) {
return vaddw_high_u8(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vaddw_high_u16(<4 x i32> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vaddw_high_u16(
// CHECK: [[SHUFFLE_I_I_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[TMP2:%.*]] = zext <4 x i16> [[TMP1]] to <4 x i32>
-// CHECK: [[ADD_I:%.*]] = add <4 x i32> %a, [[TMP2]]
+// CHECK: [[TMP1:%.*]] = zext <4 x i16> [[SHUFFLE_I_I_I]] to <4 x i32>
+// CHECK: [[ADD_I:%.*]] = add <4 x i32> %a, [[TMP1]]
// CHECK: ret <4 x i32> [[ADD_I]]
uint32x4_t test_vaddw_high_u16(uint32x4_t a, uint16x8_t b) {
return vaddw_high_u16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vaddw_high_u32(<2 x i64> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vaddw_high_u32(
// CHECK: [[SHUFFLE_I_I_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[TMP2:%.*]] = zext <2 x i32> [[TMP1]] to <2 x i64>
-// CHECK: [[ADD_I:%.*]] = add <2 x i64> %a, [[TMP2]]
+// CHECK: [[TMP1:%.*]] = zext <2 x i32> [[SHUFFLE_I_I_I]] to <2 x i64>
+// CHECK: [[ADD_I:%.*]] = add <2 x i64> %a, [[TMP1]]
// CHECK: ret <2 x i64> [[ADD_I]]
uint64x2_t test_vaddw_high_u32(uint64x2_t a, uint32x4_t b) {
return vaddw_high_u32(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vsubl_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsubl_s8(
// CHECK: [[VMOVL_I_I:%.*]] = sext <8 x i8> %a to <8 x i16>
// CHECK: [[VMOVL_I4_I:%.*]] = sext <8 x i8> %b to <8 x i16>
// CHECK: [[SUB_I:%.*]] = sub <8 x i16> [[VMOVL_I_I]], [[VMOVL_I4_I]]
@@ -7512,33 +6825,29 @@ int16x8_t test_vsubl_s8(int8x8_t a, int8x8_t b) {
return vsubl_s8(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vsubl_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsubl_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMOVL_I_I:%.*]] = sext <4 x i16> [[TMP1]] to <4 x i32>
-// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VMOVL_I4_I:%.*]] = sext <4 x i16> [[TMP3]] to <4 x i32>
+// CHECK: [[VMOVL_I_I:%.*]] = sext <4 x i16> %a to <4 x i32>
+// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
+// CHECK: [[VMOVL_I4_I:%.*]] = sext <4 x i16> %b to <4 x i32>
// CHECK: [[SUB_I:%.*]] = sub <4 x i32> [[VMOVL_I_I]], [[VMOVL_I4_I]]
// CHECK: ret <4 x i32> [[SUB_I]]
int32x4_t test_vsubl_s16(int16x4_t a, int16x4_t b) {
return vsubl_s16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vsubl_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsubl_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMOVL_I_I:%.*]] = sext <2 x i32> [[TMP1]] to <2 x i64>
-// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VMOVL_I4_I:%.*]] = sext <2 x i32> [[TMP3]] to <2 x i64>
+// CHECK: [[VMOVL_I_I:%.*]] = sext <2 x i32> %a to <2 x i64>
+// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
+// CHECK: [[VMOVL_I4_I:%.*]] = sext <2 x i32> %b to <2 x i64>
// CHECK: [[SUB_I:%.*]] = sub <2 x i64> [[VMOVL_I_I]], [[VMOVL_I4_I]]
// CHECK: ret <2 x i64> [[SUB_I]]
int64x2_t test_vsubl_s32(int32x2_t a, int32x2_t b) {
return vsubl_s32(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vsubl_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsubl_u8(
// CHECK: [[VMOVL_I_I:%.*]] = zext <8 x i8> %a to <8 x i16>
// CHECK: [[VMOVL_I4_I:%.*]] = zext <8 x i8> %b to <8 x i16>
// CHECK: [[SUB_I:%.*]] = sub <8 x i16> [[VMOVL_I_I]], [[VMOVL_I4_I]]
@@ -7547,33 +6856,29 @@ uint16x8_t test_vsubl_u8(uint8x8_t a, uint8x8_t b) {
return vsubl_u8(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vsubl_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsubl_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMOVL_I_I:%.*]] = zext <4 x i16> [[TMP1]] to <4 x i32>
-// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VMOVL_I4_I:%.*]] = zext <4 x i16> [[TMP3]] to <4 x i32>
+// CHECK: [[VMOVL_I_I:%.*]] = zext <4 x i16> %a to <4 x i32>
+// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
+// CHECK: [[VMOVL_I4_I:%.*]] = zext <4 x i16> %b to <4 x i32>
// CHECK: [[SUB_I:%.*]] = sub <4 x i32> [[VMOVL_I_I]], [[VMOVL_I4_I]]
// CHECK: ret <4 x i32> [[SUB_I]]
uint32x4_t test_vsubl_u16(uint16x4_t a, uint16x4_t b) {
return vsubl_u16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vsubl_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsubl_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMOVL_I_I:%.*]] = zext <2 x i32> [[TMP1]] to <2 x i64>
-// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VMOVL_I4_I:%.*]] = zext <2 x i32> [[TMP3]] to <2 x i64>
+// CHECK: [[VMOVL_I_I:%.*]] = zext <2 x i32> %a to <2 x i64>
+// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
+// CHECK: [[VMOVL_I4_I:%.*]] = zext <2 x i32> %b to <2 x i64>
// CHECK: [[SUB_I:%.*]] = sub <2 x i64> [[VMOVL_I_I]], [[VMOVL_I4_I]]
// CHECK: ret <2 x i64> [[SUB_I]]
uint64x2_t test_vsubl_u32(uint32x2_t a, uint32x2_t b) {
return vsubl_u32(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vsubl_high_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsubl_high_s8(
// CHECK: [[SHUFFLE_I_I_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %a, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: [[TMP0:%.*]] = sext <8 x i8> [[SHUFFLE_I_I_I]] to <8 x i16>
// CHECK: [[SHUFFLE_I_I10_I:%.*]] = shufflevector <16 x i8> %b, <16 x i8> %b, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
@@ -7584,37 +6889,33 @@ int16x8_t test_vsubl_high_s8(int8x16_t a, int8x16_t b) {
return vsubl_high_s8(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vsubl_high_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsubl_high_s16(
// CHECK: [[SHUFFLE_I_I_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %a, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[TMP2:%.*]] = sext <4 x i16> [[TMP1]] to <4 x i32>
+// CHECK: [[TMP1:%.*]] = sext <4 x i16> [[SHUFFLE_I_I_I]] to <4 x i32>
// CHECK: [[SHUFFLE_I_I10_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
-// CHECK: [[TMP3:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I10_I]] to <8 x i8>
-// CHECK: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP3]] to <4 x i16>
-// CHECK: [[TMP5:%.*]] = sext <4 x i16> [[TMP4]] to <4 x i32>
-// CHECK: [[SUB_I:%.*]] = sub <4 x i32> [[TMP2]], [[TMP5]]
+// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I10_I]] to <8 x i8>
+// CHECK: [[TMP3:%.*]] = sext <4 x i16> [[SHUFFLE_I_I10_I]] to <4 x i32>
+// CHECK: [[SUB_I:%.*]] = sub <4 x i32> [[TMP1]], [[TMP3]]
// CHECK: ret <4 x i32> [[SUB_I]]
int32x4_t test_vsubl_high_s16(int16x8_t a, int16x8_t b) {
return vsubl_high_s16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vsubl_high_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsubl_high_s32(
// CHECK: [[SHUFFLE_I_I_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %a, <2 x i32> <i32 2, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[TMP2:%.*]] = sext <2 x i32> [[TMP1]] to <2 x i64>
+// CHECK: [[TMP1:%.*]] = sext <2 x i32> [[SHUFFLE_I_I_I]] to <2 x i64>
// CHECK: [[SHUFFLE_I_I10_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
-// CHECK: [[TMP3:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I10_I]] to <8 x i8>
-// CHECK: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP3]] to <2 x i32>
-// CHECK: [[TMP5:%.*]] = sext <2 x i32> [[TMP4]] to <2 x i64>
-// CHECK: [[SUB_I:%.*]] = sub <2 x i64> [[TMP2]], [[TMP5]]
+// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I10_I]] to <8 x i8>
+// CHECK: [[TMP3:%.*]] = sext <2 x i32> [[SHUFFLE_I_I10_I]] to <2 x i64>
+// CHECK: [[SUB_I:%.*]] = sub <2 x i64> [[TMP1]], [[TMP3]]
// CHECK: ret <2 x i64> [[SUB_I]]
int64x2_t test_vsubl_high_s32(int32x4_t a, int32x4_t b) {
return vsubl_high_s32(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vsubl_high_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsubl_high_u8(
// CHECK: [[SHUFFLE_I_I_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %a, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: [[TMP0:%.*]] = zext <8 x i8> [[SHUFFLE_I_I_I]] to <8 x i16>
// CHECK: [[SHUFFLE_I_I10_I:%.*]] = shufflevector <16 x i8> %b, <16 x i8> %b, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
@@ -7625,37 +6926,33 @@ uint16x8_t test_vsubl_high_u8(uint8x16_t a, uint8x16_t b) {
return vsubl_high_u8(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vsubl_high_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsubl_high_u16(
// CHECK: [[SHUFFLE_I_I_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %a, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[TMP2:%.*]] = zext <4 x i16> [[TMP1]] to <4 x i32>
+// CHECK: [[TMP1:%.*]] = zext <4 x i16> [[SHUFFLE_I_I_I]] to <4 x i32>
// CHECK: [[SHUFFLE_I_I10_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
-// CHECK: [[TMP3:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I10_I]] to <8 x i8>
-// CHECK: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP3]] to <4 x i16>
-// CHECK: [[TMP5:%.*]] = zext <4 x i16> [[TMP4]] to <4 x i32>
-// CHECK: [[SUB_I:%.*]] = sub <4 x i32> [[TMP2]], [[TMP5]]
+// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I10_I]] to <8 x i8>
+// CHECK: [[TMP3:%.*]] = zext <4 x i16> [[SHUFFLE_I_I10_I]] to <4 x i32>
+// CHECK: [[SUB_I:%.*]] = sub <4 x i32> [[TMP1]], [[TMP3]]
// CHECK: ret <4 x i32> [[SUB_I]]
uint32x4_t test_vsubl_high_u16(uint16x8_t a, uint16x8_t b) {
return vsubl_high_u16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vsubl_high_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsubl_high_u32(
// CHECK: [[SHUFFLE_I_I_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %a, <2 x i32> <i32 2, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[TMP2:%.*]] = zext <2 x i32> [[TMP1]] to <2 x i64>
+// CHECK: [[TMP1:%.*]] = zext <2 x i32> [[SHUFFLE_I_I_I]] to <2 x i64>
// CHECK: [[SHUFFLE_I_I10_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
-// CHECK: [[TMP3:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I10_I]] to <8 x i8>
-// CHECK: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP3]] to <2 x i32>
-// CHECK: [[TMP5:%.*]] = zext <2 x i32> [[TMP4]] to <2 x i64>
-// CHECK: [[SUB_I:%.*]] = sub <2 x i64> [[TMP2]], [[TMP5]]
+// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I10_I]] to <8 x i8>
+// CHECK: [[TMP3:%.*]] = zext <2 x i32> [[SHUFFLE_I_I10_I]] to <2 x i64>
+// CHECK: [[SUB_I:%.*]] = sub <2 x i64> [[TMP1]], [[TMP3]]
// CHECK: ret <2 x i64> [[SUB_I]]
uint64x2_t test_vsubl_high_u32(uint32x4_t a, uint32x4_t b) {
return vsubl_high_u32(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vsubw_s8(<8 x i16> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsubw_s8(
// CHECK: [[VMOVL_I_I:%.*]] = sext <8 x i8> %b to <8 x i16>
// CHECK: [[SUB_I:%.*]] = sub <8 x i16> %a, [[VMOVL_I_I]]
// CHECK: ret <8 x i16> [[SUB_I]]
@@ -7663,27 +6960,25 @@ int16x8_t test_vsubw_s8(int16x8_t a, int8x8_t b) {
return vsubw_s8(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vsubw_s16(<4 x i32> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsubw_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMOVL_I_I:%.*]] = sext <4 x i16> [[TMP1]] to <4 x i32>
+// CHECK: [[VMOVL_I_I:%.*]] = sext <4 x i16> %b to <4 x i32>
// CHECK: [[SUB_I:%.*]] = sub <4 x i32> %a, [[VMOVL_I_I]]
// CHECK: ret <4 x i32> [[SUB_I]]
int32x4_t test_vsubw_s16(int32x4_t a, int16x4_t b) {
return vsubw_s16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vsubw_s32(<2 x i64> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsubw_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMOVL_I_I:%.*]] = sext <2 x i32> [[TMP1]] to <2 x i64>
+// CHECK: [[VMOVL_I_I:%.*]] = sext <2 x i32> %b to <2 x i64>
// CHECK: [[SUB_I:%.*]] = sub <2 x i64> %a, [[VMOVL_I_I]]
// CHECK: ret <2 x i64> [[SUB_I]]
int64x2_t test_vsubw_s32(int64x2_t a, int32x2_t b) {
return vsubw_s32(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vsubw_u8(<8 x i16> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsubw_u8(
// CHECK: [[VMOVL_I_I:%.*]] = zext <8 x i8> %b to <8 x i16>
// CHECK: [[SUB_I:%.*]] = sub <8 x i16> %a, [[VMOVL_I_I]]
// CHECK: ret <8 x i16> [[SUB_I]]
@@ -7691,27 +6986,25 @@ uint16x8_t test_vsubw_u8(uint16x8_t a, uint8x8_t b) {
return vsubw_u8(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vsubw_u16(<4 x i32> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsubw_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMOVL_I_I:%.*]] = zext <4 x i16> [[TMP1]] to <4 x i32>
+// CHECK: [[VMOVL_I_I:%.*]] = zext <4 x i16> %b to <4 x i32>
// CHECK: [[SUB_I:%.*]] = sub <4 x i32> %a, [[VMOVL_I_I]]
// CHECK: ret <4 x i32> [[SUB_I]]
uint32x4_t test_vsubw_u16(uint32x4_t a, uint16x4_t b) {
return vsubw_u16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vsubw_u32(<2 x i64> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsubw_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMOVL_I_I:%.*]] = zext <2 x i32> [[TMP1]] to <2 x i64>
+// CHECK: [[VMOVL_I_I:%.*]] = zext <2 x i32> %b to <2 x i64>
// CHECK: [[SUB_I:%.*]] = sub <2 x i64> %a, [[VMOVL_I_I]]
// CHECK: ret <2 x i64> [[SUB_I]]
uint64x2_t test_vsubw_u32(uint64x2_t a, uint32x2_t b) {
return vsubw_u32(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vsubw_high_s8(<8 x i16> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsubw_high_s8(
// CHECK: [[SHUFFLE_I_I_I:%.*]] = shufflevector <16 x i8> %b, <16 x i8> %b, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: [[TMP0:%.*]] = sext <8 x i8> [[SHUFFLE_I_I_I]] to <8 x i16>
// CHECK: [[SUB_I:%.*]] = sub <8 x i16> %a, [[TMP0]]
@@ -7720,29 +7013,27 @@ int16x8_t test_vsubw_high_s8(int16x8_t a, int8x16_t b) {
return vsubw_high_s8(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vsubw_high_s16(<4 x i32> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsubw_high_s16(
// CHECK: [[SHUFFLE_I_I_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[TMP2:%.*]] = sext <4 x i16> [[TMP1]] to <4 x i32>
-// CHECK: [[SUB_I:%.*]] = sub <4 x i32> %a, [[TMP2]]
+// CHECK: [[TMP1:%.*]] = sext <4 x i16> [[SHUFFLE_I_I_I]] to <4 x i32>
+// CHECK: [[SUB_I:%.*]] = sub <4 x i32> %a, [[TMP1]]
// CHECK: ret <4 x i32> [[SUB_I]]
int32x4_t test_vsubw_high_s16(int32x4_t a, int16x8_t b) {
return vsubw_high_s16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vsubw_high_s32(<2 x i64> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsubw_high_s32(
// CHECK: [[SHUFFLE_I_I_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[TMP2:%.*]] = sext <2 x i32> [[TMP1]] to <2 x i64>
-// CHECK: [[SUB_I:%.*]] = sub <2 x i64> %a, [[TMP2]]
+// CHECK: [[TMP1:%.*]] = sext <2 x i32> [[SHUFFLE_I_I_I]] to <2 x i64>
+// CHECK: [[SUB_I:%.*]] = sub <2 x i64> %a, [[TMP1]]
// CHECK: ret <2 x i64> [[SUB_I]]
int64x2_t test_vsubw_high_s32(int64x2_t a, int32x4_t b) {
return vsubw_high_s32(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vsubw_high_u8(<8 x i16> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsubw_high_u8(
// CHECK: [[SHUFFLE_I_I_I:%.*]] = shufflevector <16 x i8> %b, <16 x i8> %b, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: [[TMP0:%.*]] = zext <8 x i8> [[SHUFFLE_I_I_I]] to <8 x i16>
// CHECK: [[SUB_I:%.*]] = sub <8 x i16> %a, [[TMP0]]
@@ -7751,34 +7042,30 @@ uint16x8_t test_vsubw_high_u8(uint16x8_t a, uint8x16_t b) {
return vsubw_high_u8(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vsubw_high_u16(<4 x i32> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsubw_high_u16(
// CHECK: [[SHUFFLE_I_I_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[TMP2:%.*]] = zext <4 x i16> [[TMP1]] to <4 x i32>
-// CHECK: [[SUB_I:%.*]] = sub <4 x i32> %a, [[TMP2]]
+// CHECK: [[TMP1:%.*]] = zext <4 x i16> [[SHUFFLE_I_I_I]] to <4 x i32>
+// CHECK: [[SUB_I:%.*]] = sub <4 x i32> %a, [[TMP1]]
// CHECK: ret <4 x i32> [[SUB_I]]
uint32x4_t test_vsubw_high_u16(uint32x4_t a, uint16x8_t b) {
return vsubw_high_u16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vsubw_high_u32(<2 x i64> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsubw_high_u32(
// CHECK: [[SHUFFLE_I_I_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[TMP2:%.*]] = zext <2 x i32> [[TMP1]] to <2 x i64>
-// CHECK: [[SUB_I:%.*]] = sub <2 x i64> %a, [[TMP2]]
+// CHECK: [[TMP1:%.*]] = zext <2 x i32> [[SHUFFLE_I_I_I]] to <2 x i64>
+// CHECK: [[SUB_I:%.*]] = sub <2 x i64> %a, [[TMP1]]
// CHECK: ret <2 x i64> [[SUB_I]]
uint64x2_t test_vsubw_high_u32(uint64x2_t a, uint32x4_t b) {
return vsubw_high_u32(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vaddhn_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vaddhn_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VADDHN_I:%.*]] = add <8 x i16> [[TMP2]], [[TMP3]]
+// CHECK: [[VADDHN_I:%.*]] = add <8 x i16> %a, %b
// CHECK: [[VADDHN1_I:%.*]] = lshr <8 x i16> [[VADDHN_I]], <i16 8, i16 8, i16 8, i16 8, i16 8, i16 8, i16 8, i16 8>
// CHECK: [[VADDHN2_I:%.*]] = trunc <8 x i16> [[VADDHN1_I]] to <8 x i8>
// CHECK: ret <8 x i8> [[VADDHN2_I]]
@@ -7786,12 +7073,10 @@ int8x8_t test_vaddhn_s16(int16x8_t a, int16x8_t b) {
return vaddhn_s16(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vaddhn_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vaddhn_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VADDHN_I:%.*]] = add <4 x i32> [[TMP2]], [[TMP3]]
+// CHECK: [[VADDHN_I:%.*]] = add <4 x i32> %a, %b
// CHECK: [[VADDHN1_I:%.*]] = lshr <4 x i32> [[VADDHN_I]], <i32 16, i32 16, i32 16, i32 16>
// CHECK: [[VADDHN2_I:%.*]] = trunc <4 x i32> [[VADDHN1_I]] to <4 x i16>
// CHECK: ret <4 x i16> [[VADDHN2_I]]
@@ -7799,12 +7084,10 @@ int16x4_t test_vaddhn_s32(int32x4_t a, int32x4_t b) {
return vaddhn_s32(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vaddhn_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vaddhn_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VADDHN_I:%.*]] = add <2 x i64> [[TMP2]], [[TMP3]]
+// CHECK: [[VADDHN_I:%.*]] = add <2 x i64> %a, %b
// CHECK: [[VADDHN1_I:%.*]] = lshr <2 x i64> [[VADDHN_I]], <i64 32, i64 32>
// CHECK: [[VADDHN2_I:%.*]] = trunc <2 x i64> [[VADDHN1_I]] to <2 x i32>
// CHECK: ret <2 x i32> [[VADDHN2_I]]
@@ -7812,12 +7095,10 @@ int32x2_t test_vaddhn_s64(int64x2_t a, int64x2_t b) {
return vaddhn_s64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vaddhn_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vaddhn_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VADDHN_I:%.*]] = add <8 x i16> [[TMP2]], [[TMP3]]
+// CHECK: [[VADDHN_I:%.*]] = add <8 x i16> %a, %b
// CHECK: [[VADDHN1_I:%.*]] = lshr <8 x i16> [[VADDHN_I]], <i16 8, i16 8, i16 8, i16 8, i16 8, i16 8, i16 8, i16 8>
// CHECK: [[VADDHN2_I:%.*]] = trunc <8 x i16> [[VADDHN1_I]] to <8 x i8>
// CHECK: ret <8 x i8> [[VADDHN2_I]]
@@ -7825,12 +7106,10 @@ uint8x8_t test_vaddhn_u16(uint16x8_t a, uint16x8_t b) {
return vaddhn_u16(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vaddhn_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vaddhn_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VADDHN_I:%.*]] = add <4 x i32> [[TMP2]], [[TMP3]]
+// CHECK: [[VADDHN_I:%.*]] = add <4 x i32> %a, %b
// CHECK: [[VADDHN1_I:%.*]] = lshr <4 x i32> [[VADDHN_I]], <i32 16, i32 16, i32 16, i32 16>
// CHECK: [[VADDHN2_I:%.*]] = trunc <4 x i32> [[VADDHN1_I]] to <4 x i16>
// CHECK: ret <4 x i16> [[VADDHN2_I]]
@@ -7838,12 +7117,10 @@ uint16x4_t test_vaddhn_u32(uint32x4_t a, uint32x4_t b) {
return vaddhn_u32(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vaddhn_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vaddhn_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VADDHN_I:%.*]] = add <2 x i64> [[TMP2]], [[TMP3]]
+// CHECK: [[VADDHN_I:%.*]] = add <2 x i64> %a, %b
// CHECK: [[VADDHN1_I:%.*]] = lshr <2 x i64> [[VADDHN_I]], <i64 32, i64 32>
// CHECK: [[VADDHN2_I:%.*]] = trunc <2 x i64> [[VADDHN1_I]] to <2 x i32>
// CHECK: ret <2 x i32> [[VADDHN2_I]]
@@ -7851,12 +7128,10 @@ uint32x2_t test_vaddhn_u64(uint64x2_t a, uint64x2_t b) {
return vaddhn_u64(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vaddhn_high_s16(<8 x i8> %r, <8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vaddhn_high_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VADDHN_I_I:%.*]] = add <8 x i16> [[TMP2]], [[TMP3]]
+// CHECK: [[VADDHN_I_I:%.*]] = add <8 x i16> %a, %b
// CHECK: [[VADDHN1_I_I:%.*]] = lshr <8 x i16> [[VADDHN_I_I]], <i16 8, i16 8, i16 8, i16 8, i16 8, i16 8, i16 8, i16 8>
// CHECK: [[VADDHN2_I_I:%.*]] = trunc <8 x i16> [[VADDHN1_I_I]] to <8 x i8>
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <8 x i8> %r, <8 x i8> [[VADDHN2_I_I]], <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>
@@ -7865,12 +7140,10 @@ int8x16_t test_vaddhn_high_s16(int8x8_t r, int16x8_t a, int16x8_t b) {
return vaddhn_high_s16(r, a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vaddhn_high_s32(<4 x i16> %r, <4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vaddhn_high_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VADDHN_I_I:%.*]] = add <4 x i32> [[TMP2]], [[TMP3]]
+// CHECK: [[VADDHN_I_I:%.*]] = add <4 x i32> %a, %b
// CHECK: [[VADDHN1_I_I:%.*]] = lshr <4 x i32> [[VADDHN_I_I]], <i32 16, i32 16, i32 16, i32 16>
// CHECK: [[VADDHN2_I_I:%.*]] = trunc <4 x i32> [[VADDHN1_I_I]] to <4 x i16>
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x i16> %r, <4 x i16> [[VADDHN2_I_I]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
@@ -7879,12 +7152,10 @@ int16x8_t test_vaddhn_high_s32(int16x4_t r, int32x4_t a, int32x4_t b) {
return vaddhn_high_s32(r, a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vaddhn_high_s64(<2 x i32> %r, <2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vaddhn_high_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VADDHN_I_I:%.*]] = add <2 x i64> [[TMP2]], [[TMP3]]
+// CHECK: [[VADDHN_I_I:%.*]] = add <2 x i64> %a, %b
// CHECK: [[VADDHN1_I_I:%.*]] = lshr <2 x i64> [[VADDHN_I_I]], <i64 32, i64 32>
// CHECK: [[VADDHN2_I_I:%.*]] = trunc <2 x i64> [[VADDHN1_I_I]] to <2 x i32>
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <2 x i32> %r, <2 x i32> [[VADDHN2_I_I]], <4 x i32> <i32 0, i32 1, i32 2, i32 3>
@@ -7893,12 +7164,10 @@ int32x4_t test_vaddhn_high_s64(int32x2_t r, int64x2_t a, int64x2_t b) {
return vaddhn_high_s64(r, a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vaddhn_high_u16(<8 x i8> %r, <8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vaddhn_high_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VADDHN_I_I:%.*]] = add <8 x i16> [[TMP2]], [[TMP3]]
+// CHECK: [[VADDHN_I_I:%.*]] = add <8 x i16> %a, %b
// CHECK: [[VADDHN1_I_I:%.*]] = lshr <8 x i16> [[VADDHN_I_I]], <i16 8, i16 8, i16 8, i16 8, i16 8, i16 8, i16 8, i16 8>
// CHECK: [[VADDHN2_I_I:%.*]] = trunc <8 x i16> [[VADDHN1_I_I]] to <8 x i8>
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <8 x i8> %r, <8 x i8> [[VADDHN2_I_I]], <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>
@@ -7907,12 +7176,10 @@ uint8x16_t test_vaddhn_high_u16(uint8x8_t r, uint16x8_t a, uint16x8_t b) {
return vaddhn_high_u16(r, a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vaddhn_high_u32(<4 x i16> %r, <4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vaddhn_high_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VADDHN_I_I:%.*]] = add <4 x i32> [[TMP2]], [[TMP3]]
+// CHECK: [[VADDHN_I_I:%.*]] = add <4 x i32> %a, %b
// CHECK: [[VADDHN1_I_I:%.*]] = lshr <4 x i32> [[VADDHN_I_I]], <i32 16, i32 16, i32 16, i32 16>
// CHECK: [[VADDHN2_I_I:%.*]] = trunc <4 x i32> [[VADDHN1_I_I]] to <4 x i16>
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x i16> %r, <4 x i16> [[VADDHN2_I_I]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
@@ -7921,12 +7188,10 @@ uint16x8_t test_vaddhn_high_u32(uint16x4_t r, uint32x4_t a, uint32x4_t b) {
return vaddhn_high_u32(r, a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vaddhn_high_u64(<2 x i32> %r, <2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vaddhn_high_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VADDHN_I_I:%.*]] = add <2 x i64> [[TMP2]], [[TMP3]]
+// CHECK: [[VADDHN_I_I:%.*]] = add <2 x i64> %a, %b
// CHECK: [[VADDHN1_I_I:%.*]] = lshr <2 x i64> [[VADDHN_I_I]], <i64 32, i64 32>
// CHECK: [[VADDHN2_I_I:%.*]] = trunc <2 x i64> [[VADDHN1_I_I]] to <2 x i32>
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <2 x i32> %r, <2 x i32> [[VADDHN2_I_I]], <4 x i32> <i32 0, i32 1, i32 2, i32 3>
@@ -7935,166 +7200,132 @@ uint32x4_t test_vaddhn_high_u64(uint32x2_t r, uint64x2_t a, uint64x2_t b) {
return vaddhn_high_u64(r, a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vraddhn_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vraddhn_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VRADDHN_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VRADDHN_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VRADDHN_V2_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.raddhn.v8i8(<8 x i16> [[VRADDHN_V_I]], <8 x i16> [[VRADDHN_V1_I]]) #4
+// CHECK: [[VRADDHN_V2_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.raddhn.v8i8(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: ret <8 x i8> [[VRADDHN_V2_I]]
int8x8_t test_vraddhn_s16(int16x8_t a, int16x8_t b) {
return vraddhn_s16(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vraddhn_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vraddhn_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VRADDHN_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VRADDHN_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VRADDHN_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.raddhn.v4i16(<4 x i32> [[VRADDHN_V_I]], <4 x i32> [[VRADDHN_V1_I]]) #4
+// CHECK: [[VRADDHN_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.raddhn.v4i16(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VRADDHN_V3_I:%.*]] = bitcast <4 x i16> [[VRADDHN_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRADDHN_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VRADDHN_V2_I]]
int16x4_t test_vraddhn_s32(int32x4_t a, int32x4_t b) {
return vraddhn_s32(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vraddhn_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vraddhn_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[VRADDHN_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VRADDHN_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VRADDHN_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.raddhn.v2i32(<2 x i64> [[VRADDHN_V_I]], <2 x i64> [[VRADDHN_V1_I]]) #4
+// CHECK: [[VRADDHN_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.raddhn.v2i32(<2 x i64> %a, <2 x i64> %b) #4
// CHECK: [[VRADDHN_V3_I:%.*]] = bitcast <2 x i32> [[VRADDHN_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRADDHN_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VRADDHN_V2_I]]
int32x2_t test_vraddhn_s64(int64x2_t a, int64x2_t b) {
return vraddhn_s64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vraddhn_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vraddhn_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VRADDHN_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VRADDHN_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VRADDHN_V2_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.raddhn.v8i8(<8 x i16> [[VRADDHN_V_I]], <8 x i16> [[VRADDHN_V1_I]]) #4
+// CHECK: [[VRADDHN_V2_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.raddhn.v8i8(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: ret <8 x i8> [[VRADDHN_V2_I]]
uint8x8_t test_vraddhn_u16(uint16x8_t a, uint16x8_t b) {
return vraddhn_u16(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vraddhn_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vraddhn_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VRADDHN_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VRADDHN_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VRADDHN_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.raddhn.v4i16(<4 x i32> [[VRADDHN_V_I]], <4 x i32> [[VRADDHN_V1_I]]) #4
+// CHECK: [[VRADDHN_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.raddhn.v4i16(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VRADDHN_V3_I:%.*]] = bitcast <4 x i16> [[VRADDHN_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRADDHN_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VRADDHN_V2_I]]
uint16x4_t test_vraddhn_u32(uint32x4_t a, uint32x4_t b) {
return vraddhn_u32(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vraddhn_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vraddhn_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[VRADDHN_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VRADDHN_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VRADDHN_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.raddhn.v2i32(<2 x i64> [[VRADDHN_V_I]], <2 x i64> [[VRADDHN_V1_I]]) #4
+// CHECK: [[VRADDHN_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.raddhn.v2i32(<2 x i64> %a, <2 x i64> %b) #4
// CHECK: [[VRADDHN_V3_I:%.*]] = bitcast <2 x i32> [[VRADDHN_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRADDHN_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VRADDHN_V2_I]]
uint32x2_t test_vraddhn_u64(uint64x2_t a, uint64x2_t b) {
return vraddhn_u64(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vraddhn_high_s16(<8 x i8> %r, <8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vraddhn_high_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VRADDHN_V_I_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VRADDHN_V1_I_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VRADDHN_V2_I_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.raddhn.v8i8(<8 x i16> [[VRADDHN_V_I_I]], <8 x i16> [[VRADDHN_V1_I_I]]) #4
+// CHECK: [[VRADDHN_V2_I_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.raddhn.v8i8(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <8 x i8> %r, <8 x i8> [[VRADDHN_V2_I_I]], <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 <16 x i8> [[SHUFFLE_I_I]]
int8x16_t test_vraddhn_high_s16(int8x8_t r, int16x8_t a, int16x8_t b) {
return vraddhn_high_s16(r, a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vraddhn_high_s32(<4 x i16> %r, <4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vraddhn_high_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VRADDHN_V_I_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VRADDHN_V1_I_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VRADDHN_V2_I_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.raddhn.v4i16(<4 x i32> [[VRADDHN_V_I_I]], <4 x i32> [[VRADDHN_V1_I_I]]) #4
+// CHECK: [[VRADDHN_V2_I_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.raddhn.v4i16(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VRADDHN_V3_I_I:%.*]] = bitcast <4 x i16> [[VRADDHN_V2_I_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRADDHN_V3_I_I]] to <4 x i16>
-// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x i16> %r, <4 x i16> [[TMP2]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x i16> %r, <4 x i16> [[VRADDHN_V2_I_I]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
// CHECK: ret <8 x i16> [[SHUFFLE_I_I]]
int16x8_t test_vraddhn_high_s32(int16x4_t r, int32x4_t a, int32x4_t b) {
return vraddhn_high_s32(r, a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vraddhn_high_s64(<2 x i32> %r, <2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vraddhn_high_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[VRADDHN_V_I_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VRADDHN_V1_I_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VRADDHN_V2_I_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.raddhn.v2i32(<2 x i64> [[VRADDHN_V_I_I]], <2 x i64> [[VRADDHN_V1_I_I]]) #4
+// CHECK: [[VRADDHN_V2_I_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.raddhn.v2i32(<2 x i64> %a, <2 x i64> %b) #4
// CHECK: [[VRADDHN_V3_I_I:%.*]] = bitcast <2 x i32> [[VRADDHN_V2_I_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRADDHN_V3_I_I]] to <2 x i32>
-// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <2 x i32> %r, <2 x i32> [[TMP2]], <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <2 x i32> %r, <2 x i32> [[VRADDHN_V2_I_I]], <4 x i32> <i32 0, i32 1, i32 2, i32 3>
// CHECK: ret <4 x i32> [[SHUFFLE_I_I]]
int32x4_t test_vraddhn_high_s64(int32x2_t r, int64x2_t a, int64x2_t b) {
return vraddhn_high_s64(r, a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vraddhn_high_u16(<8 x i8> %r, <8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vraddhn_high_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VRADDHN_V_I_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VRADDHN_V1_I_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VRADDHN_V2_I_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.raddhn.v8i8(<8 x i16> [[VRADDHN_V_I_I]], <8 x i16> [[VRADDHN_V1_I_I]]) #4
+// CHECK: [[VRADDHN_V2_I_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.raddhn.v8i8(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <8 x i8> %r, <8 x i8> [[VRADDHN_V2_I_I]], <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 <16 x i8> [[SHUFFLE_I_I]]
uint8x16_t test_vraddhn_high_u16(uint8x8_t r, uint16x8_t a, uint16x8_t b) {
return vraddhn_high_u16(r, a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vraddhn_high_u32(<4 x i16> %r, <4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vraddhn_high_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VRADDHN_V_I_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VRADDHN_V1_I_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VRADDHN_V2_I_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.raddhn.v4i16(<4 x i32> [[VRADDHN_V_I_I]], <4 x i32> [[VRADDHN_V1_I_I]]) #4
+// CHECK: [[VRADDHN_V2_I_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.raddhn.v4i16(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VRADDHN_V3_I_I:%.*]] = bitcast <4 x i16> [[VRADDHN_V2_I_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRADDHN_V3_I_I]] to <4 x i16>
-// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x i16> %r, <4 x i16> [[TMP2]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x i16> %r, <4 x i16> [[VRADDHN_V2_I_I]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
// CHECK: ret <8 x i16> [[SHUFFLE_I_I]]
uint16x8_t test_vraddhn_high_u32(uint16x4_t r, uint32x4_t a, uint32x4_t b) {
return vraddhn_high_u32(r, a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vraddhn_high_u64(<2 x i32> %r, <2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vraddhn_high_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[VRADDHN_V_I_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VRADDHN_V1_I_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VRADDHN_V2_I_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.raddhn.v2i32(<2 x i64> [[VRADDHN_V_I_I]], <2 x i64> [[VRADDHN_V1_I_I]]) #4
+// CHECK: [[VRADDHN_V2_I_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.raddhn.v2i32(<2 x i64> %a, <2 x i64> %b) #4
// CHECK: [[VRADDHN_V3_I_I:%.*]] = bitcast <2 x i32> [[VRADDHN_V2_I_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRADDHN_V3_I_I]] to <2 x i32>
-// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <2 x i32> %r, <2 x i32> [[TMP2]], <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <2 x i32> %r, <2 x i32> [[VRADDHN_V2_I_I]], <4 x i32> <i32 0, i32 1, i32 2, i32 3>
// CHECK: ret <4 x i32> [[SHUFFLE_I_I]]
uint32x4_t test_vraddhn_high_u64(uint32x2_t r, uint64x2_t a, uint64x2_t b) {
return vraddhn_high_u64(r, a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vsubhn_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsubhn_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VSUBHN_I:%.*]] = sub <8 x i16> [[TMP2]], [[TMP3]]
+// CHECK: [[VSUBHN_I:%.*]] = sub <8 x i16> %a, %b
// CHECK: [[VSUBHN1_I:%.*]] = lshr <8 x i16> [[VSUBHN_I]], <i16 8, i16 8, i16 8, i16 8, i16 8, i16 8, i16 8, i16 8>
// CHECK: [[VSUBHN2_I:%.*]] = trunc <8 x i16> [[VSUBHN1_I]] to <8 x i8>
// CHECK: ret <8 x i8> [[VSUBHN2_I]]
@@ -8102,12 +7333,10 @@ int8x8_t test_vsubhn_s16(int16x8_t a, int16x8_t b) {
return vsubhn_s16(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vsubhn_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsubhn_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VSUBHN_I:%.*]] = sub <4 x i32> [[TMP2]], [[TMP3]]
+// CHECK: [[VSUBHN_I:%.*]] = sub <4 x i32> %a, %b
// CHECK: [[VSUBHN1_I:%.*]] = lshr <4 x i32> [[VSUBHN_I]], <i32 16, i32 16, i32 16, i32 16>
// CHECK: [[VSUBHN2_I:%.*]] = trunc <4 x i32> [[VSUBHN1_I]] to <4 x i16>
// CHECK: ret <4 x i16> [[VSUBHN2_I]]
@@ -8115,12 +7344,10 @@ int16x4_t test_vsubhn_s32(int32x4_t a, int32x4_t b) {
return vsubhn_s32(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vsubhn_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vsubhn_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VSUBHN_I:%.*]] = sub <2 x i64> [[TMP2]], [[TMP3]]
+// CHECK: [[VSUBHN_I:%.*]] = sub <2 x i64> %a, %b
// CHECK: [[VSUBHN1_I:%.*]] = lshr <2 x i64> [[VSUBHN_I]], <i64 32, i64 32>
// CHECK: [[VSUBHN2_I:%.*]] = trunc <2 x i64> [[VSUBHN1_I]] to <2 x i32>
// CHECK: ret <2 x i32> [[VSUBHN2_I]]
@@ -8128,12 +7355,10 @@ int32x2_t test_vsubhn_s64(int64x2_t a, int64x2_t b) {
return vsubhn_s64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vsubhn_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsubhn_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VSUBHN_I:%.*]] = sub <8 x i16> [[TMP2]], [[TMP3]]
+// CHECK: [[VSUBHN_I:%.*]] = sub <8 x i16> %a, %b
// CHECK: [[VSUBHN1_I:%.*]] = lshr <8 x i16> [[VSUBHN_I]], <i16 8, i16 8, i16 8, i16 8, i16 8, i16 8, i16 8, i16 8>
// CHECK: [[VSUBHN2_I:%.*]] = trunc <8 x i16> [[VSUBHN1_I]] to <8 x i8>
// CHECK: ret <8 x i8> [[VSUBHN2_I]]
@@ -8141,12 +7366,10 @@ uint8x8_t test_vsubhn_u16(uint16x8_t a, uint16x8_t b) {
return vsubhn_u16(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vsubhn_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsubhn_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VSUBHN_I:%.*]] = sub <4 x i32> [[TMP2]], [[TMP3]]
+// CHECK: [[VSUBHN_I:%.*]] = sub <4 x i32> %a, %b
// CHECK: [[VSUBHN1_I:%.*]] = lshr <4 x i32> [[VSUBHN_I]], <i32 16, i32 16, i32 16, i32 16>
// CHECK: [[VSUBHN2_I:%.*]] = trunc <4 x i32> [[VSUBHN1_I]] to <4 x i16>
// CHECK: ret <4 x i16> [[VSUBHN2_I]]
@@ -8154,12 +7377,10 @@ uint16x4_t test_vsubhn_u32(uint32x4_t a, uint32x4_t b) {
return vsubhn_u32(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vsubhn_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vsubhn_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VSUBHN_I:%.*]] = sub <2 x i64> [[TMP2]], [[TMP3]]
+// CHECK: [[VSUBHN_I:%.*]] = sub <2 x i64> %a, %b
// CHECK: [[VSUBHN1_I:%.*]] = lshr <2 x i64> [[VSUBHN_I]], <i64 32, i64 32>
// CHECK: [[VSUBHN2_I:%.*]] = trunc <2 x i64> [[VSUBHN1_I]] to <2 x i32>
// CHECK: ret <2 x i32> [[VSUBHN2_I]]
@@ -8167,12 +7388,10 @@ uint32x2_t test_vsubhn_u64(uint64x2_t a, uint64x2_t b) {
return vsubhn_u64(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vsubhn_high_s16(<8 x i8> %r, <8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsubhn_high_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VSUBHN_I_I:%.*]] = sub <8 x i16> [[TMP2]], [[TMP3]]
+// CHECK: [[VSUBHN_I_I:%.*]] = sub <8 x i16> %a, %b
// CHECK: [[VSUBHN1_I_I:%.*]] = lshr <8 x i16> [[VSUBHN_I_I]], <i16 8, i16 8, i16 8, i16 8, i16 8, i16 8, i16 8, i16 8>
// CHECK: [[VSUBHN2_I_I:%.*]] = trunc <8 x i16> [[VSUBHN1_I_I]] to <8 x i8>
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <8 x i8> %r, <8 x i8> [[VSUBHN2_I_I]], <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>
@@ -8181,12 +7400,10 @@ int8x16_t test_vsubhn_high_s16(int8x8_t r, int16x8_t a, int16x8_t b) {
return vsubhn_high_s16(r, a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vsubhn_high_s32(<4 x i16> %r, <4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsubhn_high_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VSUBHN_I_I:%.*]] = sub <4 x i32> [[TMP2]], [[TMP3]]
+// CHECK: [[VSUBHN_I_I:%.*]] = sub <4 x i32> %a, %b
// CHECK: [[VSUBHN1_I_I:%.*]] = lshr <4 x i32> [[VSUBHN_I_I]], <i32 16, i32 16, i32 16, i32 16>
// CHECK: [[VSUBHN2_I_I:%.*]] = trunc <4 x i32> [[VSUBHN1_I_I]] to <4 x i16>
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x i16> %r, <4 x i16> [[VSUBHN2_I_I]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
@@ -8195,12 +7412,10 @@ int16x8_t test_vsubhn_high_s32(int16x4_t r, int32x4_t a, int32x4_t b) {
return vsubhn_high_s32(r, a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vsubhn_high_s64(<2 x i32> %r, <2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vsubhn_high_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VSUBHN_I_I:%.*]] = sub <2 x i64> [[TMP2]], [[TMP3]]
+// CHECK: [[VSUBHN_I_I:%.*]] = sub <2 x i64> %a, %b
// CHECK: [[VSUBHN1_I_I:%.*]] = lshr <2 x i64> [[VSUBHN_I_I]], <i64 32, i64 32>
// CHECK: [[VSUBHN2_I_I:%.*]] = trunc <2 x i64> [[VSUBHN1_I_I]] to <2 x i32>
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <2 x i32> %r, <2 x i32> [[VSUBHN2_I_I]], <4 x i32> <i32 0, i32 1, i32 2, i32 3>
@@ -8209,12 +7424,10 @@ int32x4_t test_vsubhn_high_s64(int32x2_t r, int64x2_t a, int64x2_t b) {
return vsubhn_high_s64(r, a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vsubhn_high_u16(<8 x i8> %r, <8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsubhn_high_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VSUBHN_I_I:%.*]] = sub <8 x i16> [[TMP2]], [[TMP3]]
+// CHECK: [[VSUBHN_I_I:%.*]] = sub <8 x i16> %a, %b
// CHECK: [[VSUBHN1_I_I:%.*]] = lshr <8 x i16> [[VSUBHN_I_I]], <i16 8, i16 8, i16 8, i16 8, i16 8, i16 8, i16 8, i16 8>
// CHECK: [[VSUBHN2_I_I:%.*]] = trunc <8 x i16> [[VSUBHN1_I_I]] to <8 x i8>
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <8 x i8> %r, <8 x i8> [[VSUBHN2_I_I]], <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>
@@ -8223,12 +7436,10 @@ uint8x16_t test_vsubhn_high_u16(uint8x8_t r, uint16x8_t a, uint16x8_t b) {
return vsubhn_high_u16(r, a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vsubhn_high_u32(<4 x i16> %r, <4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsubhn_high_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VSUBHN_I_I:%.*]] = sub <4 x i32> [[TMP2]], [[TMP3]]
+// CHECK: [[VSUBHN_I_I:%.*]] = sub <4 x i32> %a, %b
// CHECK: [[VSUBHN1_I_I:%.*]] = lshr <4 x i32> [[VSUBHN_I_I]], <i32 16, i32 16, i32 16, i32 16>
// CHECK: [[VSUBHN2_I_I:%.*]] = trunc <4 x i32> [[VSUBHN1_I_I]] to <4 x i16>
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x i16> %r, <4 x i16> [[VSUBHN2_I_I]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
@@ -8237,12 +7448,10 @@ uint16x8_t test_vsubhn_high_u32(uint16x4_t r, uint32x4_t a, uint32x4_t b) {
return vsubhn_high_u32(r, a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vsubhn_high_u64(<2 x i32> %r, <2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vsubhn_high_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VSUBHN_I_I:%.*]] = sub <2 x i64> [[TMP2]], [[TMP3]]
+// CHECK: [[VSUBHN_I_I:%.*]] = sub <2 x i64> %a, %b
// CHECK: [[VSUBHN1_I_I:%.*]] = lshr <2 x i64> [[VSUBHN_I_I]], <i64 32, i64 32>
// CHECK: [[VSUBHN2_I_I:%.*]] = trunc <2 x i64> [[VSUBHN1_I_I]] to <2 x i32>
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <2 x i32> %r, <2 x i32> [[VSUBHN2_I_I]], <4 x i32> <i32 0, i32 1, i32 2, i32 3>
@@ -8251,228 +7460,189 @@ uint32x4_t test_vsubhn_high_u64(uint32x2_t r, uint64x2_t a, uint64x2_t b) {
return vsubhn_high_u64(r, a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vrsubhn_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vrsubhn_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VRSUBHN_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VRSUBHN_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VRSUBHN_V2_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.rsubhn.v8i8(<8 x i16> [[VRSUBHN_V_I]], <8 x i16> [[VRSUBHN_V1_I]]) #4
+// CHECK: [[VRSUBHN_V2_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.rsubhn.v8i8(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: ret <8 x i8> [[VRSUBHN_V2_I]]
int8x8_t test_vrsubhn_s16(int16x8_t a, int16x8_t b) {
return vrsubhn_s16(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vrsubhn_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vrsubhn_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VRSUBHN_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VRSUBHN_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VRSUBHN_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.rsubhn.v4i16(<4 x i32> [[VRSUBHN_V_I]], <4 x i32> [[VRSUBHN_V1_I]]) #4
+// CHECK: [[VRSUBHN_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.rsubhn.v4i16(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VRSUBHN_V3_I:%.*]] = bitcast <4 x i16> [[VRSUBHN_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRSUBHN_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VRSUBHN_V2_I]]
int16x4_t test_vrsubhn_s32(int32x4_t a, int32x4_t b) {
return vrsubhn_s32(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vrsubhn_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vrsubhn_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[VRSUBHN_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VRSUBHN_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VRSUBHN_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.rsubhn.v2i32(<2 x i64> [[VRSUBHN_V_I]], <2 x i64> [[VRSUBHN_V1_I]]) #4
+// CHECK: [[VRSUBHN_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.rsubhn.v2i32(<2 x i64> %a, <2 x i64> %b) #4
// CHECK: [[VRSUBHN_V3_I:%.*]] = bitcast <2 x i32> [[VRSUBHN_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRSUBHN_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VRSUBHN_V2_I]]
int32x2_t test_vrsubhn_s64(int64x2_t a, int64x2_t b) {
return vrsubhn_s64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vrsubhn_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vrsubhn_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VRSUBHN_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VRSUBHN_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VRSUBHN_V2_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.rsubhn.v8i8(<8 x i16> [[VRSUBHN_V_I]], <8 x i16> [[VRSUBHN_V1_I]]) #4
+// CHECK: [[VRSUBHN_V2_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.rsubhn.v8i8(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: ret <8 x i8> [[VRSUBHN_V2_I]]
uint8x8_t test_vrsubhn_u16(uint16x8_t a, uint16x8_t b) {
return vrsubhn_u16(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vrsubhn_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vrsubhn_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VRSUBHN_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VRSUBHN_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VRSUBHN_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.rsubhn.v4i16(<4 x i32> [[VRSUBHN_V_I]], <4 x i32> [[VRSUBHN_V1_I]]) #4
+// CHECK: [[VRSUBHN_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.rsubhn.v4i16(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VRSUBHN_V3_I:%.*]] = bitcast <4 x i16> [[VRSUBHN_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRSUBHN_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VRSUBHN_V2_I]]
uint16x4_t test_vrsubhn_u32(uint32x4_t a, uint32x4_t b) {
return vrsubhn_u32(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vrsubhn_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vrsubhn_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[VRSUBHN_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VRSUBHN_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VRSUBHN_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.rsubhn.v2i32(<2 x i64> [[VRSUBHN_V_I]], <2 x i64> [[VRSUBHN_V1_I]]) #4
+// CHECK: [[VRSUBHN_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.rsubhn.v2i32(<2 x i64> %a, <2 x i64> %b) #4
// CHECK: [[VRSUBHN_V3_I:%.*]] = bitcast <2 x i32> [[VRSUBHN_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRSUBHN_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VRSUBHN_V2_I]]
uint32x2_t test_vrsubhn_u64(uint64x2_t a, uint64x2_t b) {
return vrsubhn_u64(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vrsubhn_high_s16(<8 x i8> %r, <8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vrsubhn_high_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VRSUBHN_V_I_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VRSUBHN_V1_I_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VRSUBHN_V2_I_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.rsubhn.v8i8(<8 x i16> [[VRSUBHN_V_I_I]], <8 x i16> [[VRSUBHN_V1_I_I]]) #4
+// CHECK: [[VRSUBHN_V2_I_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.rsubhn.v8i8(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <8 x i8> %r, <8 x i8> [[VRSUBHN_V2_I_I]], <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 <16 x i8> [[SHUFFLE_I_I]]
int8x16_t test_vrsubhn_high_s16(int8x8_t r, int16x8_t a, int16x8_t b) {
return vrsubhn_high_s16(r, a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vrsubhn_high_s32(<4 x i16> %r, <4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vrsubhn_high_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VRSUBHN_V_I_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VRSUBHN_V1_I_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VRSUBHN_V2_I_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.rsubhn.v4i16(<4 x i32> [[VRSUBHN_V_I_I]], <4 x i32> [[VRSUBHN_V1_I_I]]) #4
+// CHECK: [[VRSUBHN_V2_I_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.rsubhn.v4i16(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VRSUBHN_V3_I_I:%.*]] = bitcast <4 x i16> [[VRSUBHN_V2_I_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRSUBHN_V3_I_I]] to <4 x i16>
-// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x i16> %r, <4 x i16> [[TMP2]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x i16> %r, <4 x i16> [[VRSUBHN_V2_I_I]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
// CHECK: ret <8 x i16> [[SHUFFLE_I_I]]
int16x8_t test_vrsubhn_high_s32(int16x4_t r, int32x4_t a, int32x4_t b) {
return vrsubhn_high_s32(r, a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vrsubhn_high_s64(<2 x i32> %r, <2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vrsubhn_high_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[VRSUBHN_V_I_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VRSUBHN_V1_I_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VRSUBHN_V2_I_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.rsubhn.v2i32(<2 x i64> [[VRSUBHN_V_I_I]], <2 x i64> [[VRSUBHN_V1_I_I]]) #4
+// CHECK: [[VRSUBHN_V2_I_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.rsubhn.v2i32(<2 x i64> %a, <2 x i64> %b) #4
// CHECK: [[VRSUBHN_V3_I_I:%.*]] = bitcast <2 x i32> [[VRSUBHN_V2_I_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRSUBHN_V3_I_I]] to <2 x i32>
-// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <2 x i32> %r, <2 x i32> [[TMP2]], <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <2 x i32> %r, <2 x i32> [[VRSUBHN_V2_I_I]], <4 x i32> <i32 0, i32 1, i32 2, i32 3>
// CHECK: ret <4 x i32> [[SHUFFLE_I_I]]
int32x4_t test_vrsubhn_high_s64(int32x2_t r, int64x2_t a, int64x2_t b) {
return vrsubhn_high_s64(r, a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vrsubhn_high_u16(<8 x i8> %r, <8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vrsubhn_high_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VRSUBHN_V_I_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VRSUBHN_V1_I_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VRSUBHN_V2_I_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.rsubhn.v8i8(<8 x i16> [[VRSUBHN_V_I_I]], <8 x i16> [[VRSUBHN_V1_I_I]]) #4
+// CHECK: [[VRSUBHN_V2_I_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.rsubhn.v8i8(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <8 x i8> %r, <8 x i8> [[VRSUBHN_V2_I_I]], <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 <16 x i8> [[SHUFFLE_I_I]]
uint8x16_t test_vrsubhn_high_u16(uint8x8_t r, uint16x8_t a, uint16x8_t b) {
return vrsubhn_high_u16(r, a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vrsubhn_high_u32(<4 x i16> %r, <4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vrsubhn_high_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VRSUBHN_V_I_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VRSUBHN_V1_I_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VRSUBHN_V2_I_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.rsubhn.v4i16(<4 x i32> [[VRSUBHN_V_I_I]], <4 x i32> [[VRSUBHN_V1_I_I]]) #4
+// CHECK: [[VRSUBHN_V2_I_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.rsubhn.v4i16(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VRSUBHN_V3_I_I:%.*]] = bitcast <4 x i16> [[VRSUBHN_V2_I_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRSUBHN_V3_I_I]] to <4 x i16>
-// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x i16> %r, <4 x i16> [[TMP2]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x i16> %r, <4 x i16> [[VRSUBHN_V2_I_I]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
// CHECK: ret <8 x i16> [[SHUFFLE_I_I]]
uint16x8_t test_vrsubhn_high_u32(uint16x4_t r, uint32x4_t a, uint32x4_t b) {
return vrsubhn_high_u32(r, a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vrsubhn_high_u64(<2 x i32> %r, <2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vrsubhn_high_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[VRSUBHN_V_I_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VRSUBHN_V1_I_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VRSUBHN_V2_I_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.rsubhn.v2i32(<2 x i64> [[VRSUBHN_V_I_I]], <2 x i64> [[VRSUBHN_V1_I_I]]) #4
+// CHECK: [[VRSUBHN_V2_I_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.rsubhn.v2i32(<2 x i64> %a, <2 x i64> %b) #4
// CHECK: [[VRSUBHN_V3_I_I:%.*]] = bitcast <2 x i32> [[VRSUBHN_V2_I_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRSUBHN_V3_I_I]] to <2 x i32>
-// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <2 x i32> %r, <2 x i32> [[TMP2]], <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <2 x i32> %r, <2 x i32> [[VRSUBHN_V2_I_I]], <4 x i32> <i32 0, i32 1, i32 2, i32 3>
// CHECK: ret <4 x i32> [[SHUFFLE_I_I]]
uint32x4_t test_vrsubhn_high_u64(uint32x2_t r, uint64x2_t a, uint64x2_t b) {
return vrsubhn_high_u64(r, a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vabdl_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vabdl_s8(
// CHECK: [[VABD_I_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.sabd.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: [[VMOVL_I_I:%.*]] = zext <8 x i8> [[VABD_I_I]] to <8 x i16>
// CHECK: ret <8 x i16> [[VMOVL_I_I]]
int16x8_t test_vabdl_s8(int8x8_t a, int8x8_t b) {
return vabdl_s8(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vabdl_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+
+// CHECK-LABEL: @test_vabdl_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VABD_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VABD1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VABD2_I_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sabd.v4i16(<4 x i16> [[VABD_I_I]], <4 x i16> [[VABD1_I_I]]) #4
+// CHECK: [[VABD2_I_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sabd.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> [[VABD2_I_I]] to <8 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VMOVL_I_I:%.*]] = zext <4 x i16> [[TMP3]] to <4 x i32>
+// CHECK: [[VMOVL_I_I:%.*]] = zext <4 x i16> [[VABD2_I_I]] to <4 x i32>
// CHECK: ret <4 x i32> [[VMOVL_I_I]]
int32x4_t test_vabdl_s16(int16x4_t a, int16x4_t b) {
return vabdl_s16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vabdl_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+
+// CHECK-LABEL: @test_vabdl_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VABD_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VABD1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VABD2_I_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sabd.v2i32(<2 x i32> [[VABD_I_I]], <2 x i32> [[VABD1_I_I]]) #4
+// CHECK: [[VABD2_I_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sabd.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> [[VABD2_I_I]] to <8 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VMOVL_I_I:%.*]] = zext <2 x i32> [[TMP3]] to <2 x i64>
+// CHECK: [[VMOVL_I_I:%.*]] = zext <2 x i32> [[VABD2_I_I]] to <2 x i64>
// CHECK: ret <2 x i64> [[VMOVL_I_I]]
int64x2_t test_vabdl_s32(int32x2_t a, int32x2_t b) {
return vabdl_s32(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vabdl_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+
+// CHECK-LABEL: @test_vabdl_u8(
// CHECK: [[VABD_I_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.uabd.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: [[VMOVL_I_I:%.*]] = zext <8 x i8> [[VABD_I_I]] to <8 x i16>
// CHECK: ret <8 x i16> [[VMOVL_I_I]]
uint16x8_t test_vabdl_u8(uint8x8_t a, uint8x8_t b) {
return vabdl_u8(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vabdl_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+
+// CHECK-LABEL: @test_vabdl_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VABD_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VABD1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VABD2_I_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.uabd.v4i16(<4 x i16> [[VABD_I_I]], <4 x i16> [[VABD1_I_I]]) #4
+// CHECK: [[VABD2_I_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.uabd.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> [[VABD2_I_I]] to <8 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VMOVL_I_I:%.*]] = zext <4 x i16> [[TMP3]] to <4 x i32>
+// CHECK: [[VMOVL_I_I:%.*]] = zext <4 x i16> [[VABD2_I_I]] to <4 x i32>
// CHECK: ret <4 x i32> [[VMOVL_I_I]]
uint32x4_t test_vabdl_u16(uint16x4_t a, uint16x4_t b) {
return vabdl_u16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vabdl_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+
+// CHECK-LABEL: @test_vabdl_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VABD_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VABD1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VABD2_I_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.uabd.v2i32(<2 x i32> [[VABD_I_I]], <2 x i32> [[VABD1_I_I]]) #4
+// CHECK: [[VABD2_I_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.uabd.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> [[VABD2_I_I]] to <8 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VMOVL_I_I:%.*]] = zext <2 x i32> [[TMP3]] to <2 x i64>
+// CHECK: [[VMOVL_I_I:%.*]] = zext <2 x i32> [[VABD2_I_I]] to <2 x i64>
// CHECK: ret <2 x i64> [[VMOVL_I_I]]
uint64x2_t test_vabdl_u32(uint32x2_t a, uint32x2_t b) {
return vabdl_u32(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vabal_s8(<8 x i16> %a, <8 x i8> %b, <8 x i8> %c) #0 {
+// CHECK-LABEL: @test_vabal_s8(
// CHECK: [[VABD_I_I_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.sabd.v8i8(<8 x i8> %b, <8 x i8> %c) #4
// CHECK: [[VMOVL_I_I_I:%.*]] = zext <8 x i8> [[VABD_I_I_I]] to <8 x i16>
// CHECK: [[ADD_I:%.*]] = add <8 x i16> %a, [[VMOVL_I_I_I]]
@@ -8480,35 +7650,32 @@ uint64x2_t test_vabdl_u32(uint32x2_t a, uint32x2_t b) {
int16x8_t test_vabal_s8(int16x8_t a, int8x8_t b, int8x8_t c) {
return vabal_s8(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vabal_s16(<4 x i32> %a, <4 x i16> %b, <4 x i16> %c) #0 {
+
+// CHECK-LABEL: @test_vabal_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %c to <8 x i8>
-// CHECK: [[VABD_I_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VABD1_I_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VABD2_I_I_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sabd.v4i16(<4 x i16> [[VABD_I_I_I]], <4 x i16> [[VABD1_I_I_I]]) #4
+// CHECK: [[VABD2_I_I_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sabd.v4i16(<4 x i16> %b, <4 x i16> %c) #4
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> [[VABD2_I_I_I]] to <8 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VMOVL_I_I_I:%.*]] = zext <4 x i16> [[TMP3]] to <4 x i32>
+// CHECK: [[VMOVL_I_I_I:%.*]] = zext <4 x i16> [[VABD2_I_I_I]] to <4 x i32>
// CHECK: [[ADD_I:%.*]] = add <4 x i32> %a, [[VMOVL_I_I_I]]
// CHECK: ret <4 x i32> [[ADD_I]]
int32x4_t test_vabal_s16(int32x4_t a, int16x4_t b, int16x4_t c) {
return vabal_s16(a, b, c);
}
-// CHECK-LABEL: define <2 x i64> @test_vabal_s32(<2 x i64> %a, <2 x i32> %b, <2 x i32> %c) #0 {
+
+// CHECK-LABEL: @test_vabal_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %c to <8 x i8>
-// CHECK: [[VABD_I_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VABD1_I_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VABD2_I_I_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sabd.v2i32(<2 x i32> [[VABD_I_I_I]], <2 x i32> [[VABD1_I_I_I]]) #4
+// CHECK: [[VABD2_I_I_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sabd.v2i32(<2 x i32> %b, <2 x i32> %c) #4
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> [[VABD2_I_I_I]] to <8 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VMOVL_I_I_I:%.*]] = zext <2 x i32> [[TMP3]] to <2 x i64>
+// CHECK: [[VMOVL_I_I_I:%.*]] = zext <2 x i32> [[VABD2_I_I_I]] to <2 x i64>
// CHECK: [[ADD_I:%.*]] = add <2 x i64> %a, [[VMOVL_I_I_I]]
// CHECK: ret <2 x i64> [[ADD_I]]
int64x2_t test_vabal_s32(int64x2_t a, int32x2_t b, int32x2_t c) {
return vabal_s32(a, b, c);
}
-// CHECK-LABEL: define <8 x i16> @test_vabal_u8(<8 x i16> %a, <8 x i8> %b, <8 x i8> %c) #0 {
+
+// CHECK-LABEL: @test_vabal_u8(
// CHECK: [[VABD_I_I_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.uabd.v8i8(<8 x i8> %b, <8 x i8> %c) #4
// CHECK: [[VMOVL_I_I_I:%.*]] = zext <8 x i8> [[VABD_I_I_I]] to <8 x i16>
// CHECK: [[ADD_I:%.*]] = add <8 x i16> %a, [[VMOVL_I_I_I]]
@@ -8516,36 +7683,32 @@ int64x2_t test_vabal_s32(int64x2_t a, int32x2_t b, int32x2_t c) {
uint16x8_t test_vabal_u8(uint16x8_t a, uint8x8_t b, uint8x8_t c) {
return vabal_u8(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vabal_u16(<4 x i32> %a, <4 x i16> %b, <4 x i16> %c) #0 {
+
+// CHECK-LABEL: @test_vabal_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %c to <8 x i8>
-// CHECK: [[VABD_I_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VABD1_I_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VABD2_I_I_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.uabd.v4i16(<4 x i16> [[VABD_I_I_I]], <4 x i16> [[VABD1_I_I_I]]) #4
+// CHECK: [[VABD2_I_I_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.uabd.v4i16(<4 x i16> %b, <4 x i16> %c) #4
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> [[VABD2_I_I_I]] to <8 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VMOVL_I_I_I:%.*]] = zext <4 x i16> [[TMP3]] to <4 x i32>
+// CHECK: [[VMOVL_I_I_I:%.*]] = zext <4 x i16> [[VABD2_I_I_I]] to <4 x i32>
// CHECK: [[ADD_I:%.*]] = add <4 x i32> %a, [[VMOVL_I_I_I]]
// CHECK: ret <4 x i32> [[ADD_I]]
uint32x4_t test_vabal_u16(uint32x4_t a, uint16x4_t b, uint16x4_t c) {
return vabal_u16(a, b, c);
}
-// CHECK-LABEL: define <2 x i64> @test_vabal_u32(<2 x i64> %a, <2 x i32> %b, <2 x i32> %c) #0 {
+
+// CHECK-LABEL: @test_vabal_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %c to <8 x i8>
-// CHECK: [[VABD_I_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VABD1_I_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VABD2_I_I_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.uabd.v2i32(<2 x i32> [[VABD_I_I_I]], <2 x i32> [[VABD1_I_I_I]]) #4
+// CHECK: [[VABD2_I_I_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.uabd.v2i32(<2 x i32> %b, <2 x i32> %c) #4
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> [[VABD2_I_I_I]] to <8 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VMOVL_I_I_I:%.*]] = zext <2 x i32> [[TMP3]] to <2 x i64>
+// CHECK: [[VMOVL_I_I_I:%.*]] = zext <2 x i32> [[VABD2_I_I_I]] to <2 x i64>
// CHECK: [[ADD_I:%.*]] = add <2 x i64> %a, [[VMOVL_I_I_I]]
// CHECK: ret <2 x i64> [[ADD_I]]
uint64x2_t test_vabal_u32(uint64x2_t a, uint32x2_t b, uint32x2_t c) {
return vabal_u32(a, b, c);
}
-// CHECK-LABEL: define <8 x i16> @test_vabdl_high_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vabdl_high_s8(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %a, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: [[SHUFFLE_I7_I:%.*]] = shufflevector <16 x i8> %b, <16 x i8> %b, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: [[VABD_I_I_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.sabd.v8i8(<8 x i8> [[SHUFFLE_I_I]], <8 x i8> [[SHUFFLE_I7_I]]) #4
@@ -8554,37 +7717,34 @@ uint64x2_t test_vabal_u32(uint64x2_t a, uint32x2_t b, uint32x2_t c) {
int16x8_t test_vabdl_high_s8(int8x16_t a, int8x16_t b) {
return vabdl_high_s8(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vabdl_high_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+
+// CHECK-LABEL: @test_vabdl_high_s16(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %a, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[SHUFFLE_I7_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE_I7_I]] to <8 x i8>
-// CHECK: [[VABD_I_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VABD1_I_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VABD2_I_I_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sabd.v4i16(<4 x i16> [[VABD_I_I_I]], <4 x i16> [[VABD1_I_I_I]]) #4
+// CHECK: [[VABD2_I_I_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sabd.v4i16(<4 x i16> [[SHUFFLE_I_I]], <4 x i16> [[SHUFFLE_I7_I]]) #4
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> [[VABD2_I_I_I]] to <8 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VMOVL_I_I_I:%.*]] = zext <4 x i16> [[TMP3]] to <4 x i32>
+// CHECK: [[VMOVL_I_I_I:%.*]] = zext <4 x i16> [[VABD2_I_I_I]] to <4 x i32>
// CHECK: ret <4 x i32> [[VMOVL_I_I_I]]
int32x4_t test_vabdl_high_s16(int16x8_t a, int16x8_t b) {
return vabdl_high_s16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vabdl_high_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+
+// CHECK-LABEL: @test_vabdl_high_s32(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %a, <2 x i32> <i32 2, i32 3>
// CHECK: [[SHUFFLE_I7_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE_I7_I]] to <8 x i8>
-// CHECK: [[VABD_I_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VABD1_I_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VABD2_I_I_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sabd.v2i32(<2 x i32> [[VABD_I_I_I]], <2 x i32> [[VABD1_I_I_I]]) #4
+// CHECK: [[VABD2_I_I_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sabd.v2i32(<2 x i32> [[SHUFFLE_I_I]], <2 x i32> [[SHUFFLE_I7_I]]) #4
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> [[VABD2_I_I_I]] to <8 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VMOVL_I_I_I:%.*]] = zext <2 x i32> [[TMP3]] to <2 x i64>
+// CHECK: [[VMOVL_I_I_I:%.*]] = zext <2 x i32> [[VABD2_I_I_I]] to <2 x i64>
// CHECK: ret <2 x i64> [[VMOVL_I_I_I]]
int64x2_t test_vabdl_high_s32(int32x4_t a, int32x4_t b) {
return vabdl_high_s32(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vabdl_high_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+
+// CHECK-LABEL: @test_vabdl_high_u8(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %a, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: [[SHUFFLE_I7_I:%.*]] = shufflevector <16 x i8> %b, <16 x i8> %b, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: [[VABD_I_I_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.uabd.v8i8(<8 x i8> [[SHUFFLE_I_I]], <8 x i8> [[SHUFFLE_I7_I]]) #4
@@ -8593,38 +7753,34 @@ int64x2_t test_vabdl_high_s32(int32x4_t a, int32x4_t b) {
uint16x8_t test_vabdl_high_u8(uint8x16_t a, uint8x16_t b) {
return vabdl_high_u8(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vabdl_high_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+
+// CHECK-LABEL: @test_vabdl_high_u16(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %a, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[SHUFFLE_I7_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE_I7_I]] to <8 x i8>
-// CHECK: [[VABD_I_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VABD1_I_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VABD2_I_I_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.uabd.v4i16(<4 x i16> [[VABD_I_I_I]], <4 x i16> [[VABD1_I_I_I]]) #4
+// CHECK: [[VABD2_I_I_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.uabd.v4i16(<4 x i16> [[SHUFFLE_I_I]], <4 x i16> [[SHUFFLE_I7_I]]) #4
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> [[VABD2_I_I_I]] to <8 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VMOVL_I_I_I:%.*]] = zext <4 x i16> [[TMP3]] to <4 x i32>
+// CHECK: [[VMOVL_I_I_I:%.*]] = zext <4 x i16> [[VABD2_I_I_I]] to <4 x i32>
// CHECK: ret <4 x i32> [[VMOVL_I_I_I]]
uint32x4_t test_vabdl_high_u16(uint16x8_t a, uint16x8_t b) {
return vabdl_high_u16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vabdl_high_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+
+// CHECK-LABEL: @test_vabdl_high_u32(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %a, <2 x i32> <i32 2, i32 3>
// CHECK: [[SHUFFLE_I7_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE_I7_I]] to <8 x i8>
-// CHECK: [[VABD_I_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VABD1_I_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VABD2_I_I_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.uabd.v2i32(<2 x i32> [[VABD_I_I_I]], <2 x i32> [[VABD1_I_I_I]]) #4
+// CHECK: [[VABD2_I_I_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.uabd.v2i32(<2 x i32> [[SHUFFLE_I_I]], <2 x i32> [[SHUFFLE_I7_I]]) #4
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> [[VABD2_I_I_I]] to <8 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VMOVL_I_I_I:%.*]] = zext <2 x i32> [[TMP3]] to <2 x i64>
+// CHECK: [[VMOVL_I_I_I:%.*]] = zext <2 x i32> [[VABD2_I_I_I]] to <2 x i64>
// CHECK: ret <2 x i64> [[VMOVL_I_I_I]]
uint64x2_t test_vabdl_high_u32(uint32x4_t a, uint32x4_t b) {
return vabdl_high_u32(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vabal_high_s8(<8 x i16> %a, <16 x i8> %b, <16 x i8> %c) #0 {
+// CHECK-LABEL: @test_vabal_high_s8(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <16 x i8> %b, <16 x i8> %b, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: [[SHUFFLE_I7_I:%.*]] = shufflevector <16 x i8> %c, <16 x i8> %c, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: [[VABD_I_I_I_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.sabd.v8i8(<8 x i8> [[SHUFFLE_I_I]], <8 x i8> [[SHUFFLE_I7_I]]) #4
@@ -8634,39 +7790,36 @@ uint64x2_t test_vabdl_high_u32(uint32x4_t a, uint32x4_t b) {
int16x8_t test_vabal_high_s8(int16x8_t a, int8x16_t b, int8x16_t c) {
return vabal_high_s8(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vabal_high_s16(<4 x i32> %a, <8 x i16> %b, <8 x i16> %c) #0 {
+
+// CHECK-LABEL: @test_vabal_high_s16(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[SHUFFLE_I7_I:%.*]] = shufflevector <8 x i16> %c, <8 x i16> %c, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE_I7_I]] to <8 x i8>
-// CHECK: [[VABD_I_I_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VABD1_I_I_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VABD2_I_I_I_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sabd.v4i16(<4 x i16> [[VABD_I_I_I_I]], <4 x i16> [[VABD1_I_I_I_I]]) #4
+// CHECK: [[VABD2_I_I_I_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sabd.v4i16(<4 x i16> [[SHUFFLE_I_I]], <4 x i16> [[SHUFFLE_I7_I]]) #4
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> [[VABD2_I_I_I_I]] to <8 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VMOVL_I_I_I_I:%.*]] = zext <4 x i16> [[TMP3]] to <4 x i32>
+// CHECK: [[VMOVL_I_I_I_I:%.*]] = zext <4 x i16> [[VABD2_I_I_I_I]] to <4 x i32>
// CHECK: [[ADD_I_I:%.*]] = add <4 x i32> %a, [[VMOVL_I_I_I_I]]
// CHECK: ret <4 x i32> [[ADD_I_I]]
int32x4_t test_vabal_high_s16(int32x4_t a, int16x8_t b, int16x8_t c) {
return vabal_high_s16(a, b, c);
}
-// CHECK-LABEL: define <2 x i64> @test_vabal_high_s32(<2 x i64> %a, <4 x i32> %b, <4 x i32> %c) #0 {
+
+// CHECK-LABEL: @test_vabal_high_s32(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
// CHECK: [[SHUFFLE_I7_I:%.*]] = shufflevector <4 x i32> %c, <4 x i32> %c, <2 x i32> <i32 2, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE_I7_I]] to <8 x i8>
-// CHECK: [[VABD_I_I_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VABD1_I_I_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VABD2_I_I_I_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sabd.v2i32(<2 x i32> [[VABD_I_I_I_I]], <2 x i32> [[VABD1_I_I_I_I]]) #4
+// CHECK: [[VABD2_I_I_I_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sabd.v2i32(<2 x i32> [[SHUFFLE_I_I]], <2 x i32> [[SHUFFLE_I7_I]]) #4
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> [[VABD2_I_I_I_I]] to <8 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VMOVL_I_I_I_I:%.*]] = zext <2 x i32> [[TMP3]] to <2 x i64>
+// CHECK: [[VMOVL_I_I_I_I:%.*]] = zext <2 x i32> [[VABD2_I_I_I_I]] to <2 x i64>
// CHECK: [[ADD_I_I:%.*]] = add <2 x i64> %a, [[VMOVL_I_I_I_I]]
// CHECK: ret <2 x i64> [[ADD_I_I]]
int64x2_t test_vabal_high_s32(int64x2_t a, int32x4_t b, int32x4_t c) {
return vabal_high_s32(a, b, c);
}
-// CHECK-LABEL: define <8 x i16> @test_vabal_high_u8(<8 x i16> %a, <16 x i8> %b, <16 x i8> %c) #0 {
+
+// CHECK-LABEL: @test_vabal_high_u8(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <16 x i8> %b, <16 x i8> %b, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: [[SHUFFLE_I7_I:%.*]] = shufflevector <16 x i8> %c, <16 x i8> %c, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: [[VABD_I_I_I_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.uabd.v8i8(<8 x i8> [[SHUFFLE_I_I]], <8 x i8> [[SHUFFLE_I7_I]]) #4
@@ -8676,93 +7829,86 @@ int64x2_t test_vabal_high_s32(int64x2_t a, int32x4_t b, int32x4_t c) {
uint16x8_t test_vabal_high_u8(uint16x8_t a, uint8x16_t b, uint8x16_t c) {
return vabal_high_u8(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vabal_high_u16(<4 x i32> %a, <8 x i16> %b, <8 x i16> %c) #0 {
+
+// CHECK-LABEL: @test_vabal_high_u16(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[SHUFFLE_I7_I:%.*]] = shufflevector <8 x i16> %c, <8 x i16> %c, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE_I7_I]] to <8 x i8>
-// CHECK: [[VABD_I_I_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VABD1_I_I_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VABD2_I_I_I_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.uabd.v4i16(<4 x i16> [[VABD_I_I_I_I]], <4 x i16> [[VABD1_I_I_I_I]]) #4
+// CHECK: [[VABD2_I_I_I_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.uabd.v4i16(<4 x i16> [[SHUFFLE_I_I]], <4 x i16> [[SHUFFLE_I7_I]]) #4
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> [[VABD2_I_I_I_I]] to <8 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VMOVL_I_I_I_I:%.*]] = zext <4 x i16> [[TMP3]] to <4 x i32>
+// CHECK: [[VMOVL_I_I_I_I:%.*]] = zext <4 x i16> [[VABD2_I_I_I_I]] to <4 x i32>
// CHECK: [[ADD_I_I:%.*]] = add <4 x i32> %a, [[VMOVL_I_I_I_I]]
// CHECK: ret <4 x i32> [[ADD_I_I]]
uint32x4_t test_vabal_high_u16(uint32x4_t a, uint16x8_t b, uint16x8_t c) {
return vabal_high_u16(a, b, c);
}
-// CHECK-LABEL: define <2 x i64> @test_vabal_high_u32(<2 x i64> %a, <4 x i32> %b, <4 x i32> %c) #0 {
+
+// CHECK-LABEL: @test_vabal_high_u32(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
// CHECK: [[SHUFFLE_I7_I:%.*]] = shufflevector <4 x i32> %c, <4 x i32> %c, <2 x i32> <i32 2, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE_I7_I]] to <8 x i8>
-// CHECK: [[VABD_I_I_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VABD1_I_I_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VABD2_I_I_I_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.uabd.v2i32(<2 x i32> [[VABD_I_I_I_I]], <2 x i32> [[VABD1_I_I_I_I]]) #4
+// CHECK: [[VABD2_I_I_I_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.uabd.v2i32(<2 x i32> [[SHUFFLE_I_I]], <2 x i32> [[SHUFFLE_I7_I]]) #4
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> [[VABD2_I_I_I_I]] to <8 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VMOVL_I_I_I_I:%.*]] = zext <2 x i32> [[TMP3]] to <2 x i64>
+// CHECK: [[VMOVL_I_I_I_I:%.*]] = zext <2 x i32> [[VABD2_I_I_I_I]] to <2 x i64>
// CHECK: [[ADD_I_I:%.*]] = add <2 x i64> %a, [[VMOVL_I_I_I_I]]
// CHECK: ret <2 x i64> [[ADD_I_I]]
uint64x2_t test_vabal_high_u32(uint64x2_t a, uint32x4_t b, uint32x4_t c) {
return vabal_high_u32(a, b, c);
}
-// CHECK-LABEL: define <8 x i16> @test_vmull_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vmull_s8(
// CHECK: [[VMULL_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.smull.v8i16(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i16> [[VMULL_I]]
int16x8_t test_vmull_s8(int8x8_t a, int8x8_t b) {
return vmull_s8(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vmull_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+
+// CHECK-LABEL: @test_vmull_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #4
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: ret <4 x i32> [[VMULL2_I]]
int32x4_t test_vmull_s16(int16x4_t a, int16x4_t b) {
return vmull_s16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vmull_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+
+// CHECK-LABEL: @test_vmull_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #4
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: ret <2 x i64> [[VMULL2_I]]
int64x2_t test_vmull_s32(int32x2_t a, int32x2_t b) {
return vmull_s32(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vmull_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+
+// CHECK-LABEL: @test_vmull_u8(
// CHECK: [[VMULL_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.umull.v8i16(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i16> [[VMULL_I]]
uint16x8_t test_vmull_u8(uint8x8_t a, uint8x8_t b) {
return vmull_u8(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vmull_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+
+// CHECK-LABEL: @test_vmull_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #4
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: ret <4 x i32> [[VMULL2_I]]
uint32x4_t test_vmull_u16(uint16x4_t a, uint16x4_t b) {
return vmull_u16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vmull_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+
+// CHECK-LABEL: @test_vmull_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #4
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: ret <2 x i64> [[VMULL2_I]]
uint64x2_t test_vmull_u32(uint32x2_t a, uint32x2_t b) {
return vmull_u32(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vmull_high_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vmull_high_s8(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %a, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: [[SHUFFLE_I7_I:%.*]] = shufflevector <16 x i8> %b, <16 x i8> %b, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: [[VMULL_I_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.smull.v8i16(<8 x i8> [[SHUFFLE_I_I]], <8 x i8> [[SHUFFLE_I7_I]]) #4
@@ -8770,31 +7916,30 @@ uint64x2_t test_vmull_u32(uint32x2_t a, uint32x2_t b) {
int16x8_t test_vmull_high_s8(int8x16_t a, int8x16_t b) {
return vmull_high_s8(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vmull_high_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+
+// CHECK-LABEL: @test_vmull_high_s16(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %a, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[SHUFFLE_I7_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE_I7_I]] to <8 x i8>
-// CHECK: [[VMULL_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[VMULL_I_I]], <4 x i16> [[VMULL1_I_I]]) #4
+// CHECK: [[VMULL2_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[SHUFFLE_I_I]], <4 x i16> [[SHUFFLE_I7_I]]) #4
// CHECK: ret <4 x i32> [[VMULL2_I_I]]
int32x4_t test_vmull_high_s16(int16x8_t a, int16x8_t b) {
return vmull_high_s16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vmull_high_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+
+// CHECK-LABEL: @test_vmull_high_s32(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %a, <2 x i32> <i32 2, i32 3>
// CHECK: [[SHUFFLE_I7_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE_I7_I]] to <8 x i8>
-// CHECK: [[VMULL_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[VMULL_I_I]], <2 x i32> [[VMULL1_I_I]]) #4
+// CHECK: [[VMULL2_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[SHUFFLE_I_I]], <2 x i32> [[SHUFFLE_I7_I]]) #4
// CHECK: ret <2 x i64> [[VMULL2_I_I]]
int64x2_t test_vmull_high_s32(int32x4_t a, int32x4_t b) {
return vmull_high_s32(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vmull_high_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+
+// CHECK-LABEL: @test_vmull_high_u8(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %a, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: [[SHUFFLE_I7_I:%.*]] = shufflevector <16 x i8> %b, <16 x i8> %b, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: [[VMULL_I_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.umull.v8i16(<8 x i8> [[SHUFFLE_I_I]], <8 x i8> [[SHUFFLE_I7_I]]) #4
@@ -8802,91 +7947,86 @@ int64x2_t test_vmull_high_s32(int32x4_t a, int32x4_t b) {
uint16x8_t test_vmull_high_u8(uint8x16_t a, uint8x16_t b) {
return vmull_high_u8(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vmull_high_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+
+// CHECK-LABEL: @test_vmull_high_u16(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %a, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[SHUFFLE_I7_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE_I7_I]] to <8 x i8>
-// CHECK: [[VMULL_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[VMULL_I_I]], <4 x i16> [[VMULL1_I_I]]) #4
+// CHECK: [[VMULL2_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[SHUFFLE_I_I]], <4 x i16> [[SHUFFLE_I7_I]]) #4
// CHECK: ret <4 x i32> [[VMULL2_I_I]]
uint32x4_t test_vmull_high_u16(uint16x8_t a, uint16x8_t b) {
return vmull_high_u16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vmull_high_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+
+// CHECK-LABEL: @test_vmull_high_u32(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %a, <2 x i32> <i32 2, i32 3>
// CHECK: [[SHUFFLE_I7_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE_I7_I]] to <8 x i8>
-// CHECK: [[VMULL_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[VMULL_I_I]], <2 x i32> [[VMULL1_I_I]]) #4
+// CHECK: [[VMULL2_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[SHUFFLE_I_I]], <2 x i32> [[SHUFFLE_I7_I]]) #4
// CHECK: ret <2 x i64> [[VMULL2_I_I]]
uint64x2_t test_vmull_high_u32(uint32x4_t a, uint32x4_t b) {
return vmull_high_u32(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vmlal_s8(<8 x i16> %a, <8 x i8> %b, <8 x i8> %c) #0 {
+// CHECK-LABEL: @test_vmlal_s8(
// CHECK: [[VMULL_I_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.smull.v8i16(<8 x i8> %b, <8 x i8> %c) #4
// CHECK: [[ADD_I:%.*]] = add <8 x i16> %a, [[VMULL_I_I]]
// CHECK: ret <8 x i16> [[ADD_I]]
int16x8_t test_vmlal_s8(int16x8_t a, int8x8_t b, int8x8_t c) {
return vmlal_s8(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlal_s16(<4 x i32> %a, <4 x i16> %b, <4 x i16> %c) #0 {
+
+// CHECK-LABEL: @test_vmlal_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %c to <8 x i8>
-// CHECK: [[VMULL_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[VMULL_I_I]], <4 x i16> [[VMULL1_I_I]]) #4
+// CHECK: [[VMULL2_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> %b, <4 x i16> %c) #4
// CHECK: [[ADD_I:%.*]] = add <4 x i32> %a, [[VMULL2_I_I]]
// CHECK: ret <4 x i32> [[ADD_I]]
int32x4_t test_vmlal_s16(int32x4_t a, int16x4_t b, int16x4_t c) {
return vmlal_s16(a, b, c);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlal_s32(<2 x i64> %a, <2 x i32> %b, <2 x i32> %c) #0 {
+
+// CHECK-LABEL: @test_vmlal_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %c to <8 x i8>
-// CHECK: [[VMULL_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[VMULL_I_I]], <2 x i32> [[VMULL1_I_I]]) #4
+// CHECK: [[VMULL2_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> %b, <2 x i32> %c) #4
// CHECK: [[ADD_I:%.*]] = add <2 x i64> %a, [[VMULL2_I_I]]
// CHECK: ret <2 x i64> [[ADD_I]]
int64x2_t test_vmlal_s32(int64x2_t a, int32x2_t b, int32x2_t c) {
return vmlal_s32(a, b, c);
}
-// CHECK-LABEL: define <8 x i16> @test_vmlal_u8(<8 x i16> %a, <8 x i8> %b, <8 x i8> %c) #0 {
+
+// CHECK-LABEL: @test_vmlal_u8(
// CHECK: [[VMULL_I_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.umull.v8i16(<8 x i8> %b, <8 x i8> %c) #4
// CHECK: [[ADD_I:%.*]] = add <8 x i16> %a, [[VMULL_I_I]]
// CHECK: ret <8 x i16> [[ADD_I]]
uint16x8_t test_vmlal_u8(uint16x8_t a, uint8x8_t b, uint8x8_t c) {
return vmlal_u8(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlal_u16(<4 x i32> %a, <4 x i16> %b, <4 x i16> %c) #0 {
+
+// CHECK-LABEL: @test_vmlal_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %c to <8 x i8>
-// CHECK: [[VMULL_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[VMULL_I_I]], <4 x i16> [[VMULL1_I_I]]) #4
+// CHECK: [[VMULL2_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> %b, <4 x i16> %c) #4
// CHECK: [[ADD_I:%.*]] = add <4 x i32> %a, [[VMULL2_I_I]]
// CHECK: ret <4 x i32> [[ADD_I]]
uint32x4_t test_vmlal_u16(uint32x4_t a, uint16x4_t b, uint16x4_t c) {
return vmlal_u16(a, b, c);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlal_u32(<2 x i64> %a, <2 x i32> %b, <2 x i32> %c) #0 {
+
+// CHECK-LABEL: @test_vmlal_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %c to <8 x i8>
-// CHECK: [[VMULL_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[VMULL_I_I]], <2 x i32> [[VMULL1_I_I]]) #4
+// CHECK: [[VMULL2_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> %b, <2 x i32> %c) #4
// CHECK: [[ADD_I:%.*]] = add <2 x i64> %a, [[VMULL2_I_I]]
// CHECK: ret <2 x i64> [[ADD_I]]
uint64x2_t test_vmlal_u32(uint64x2_t a, uint32x2_t b, uint32x2_t c) {
return vmlal_u32(a, b, c);
}
-// CHECK-LABEL: define <8 x i16> @test_vmlal_high_s8(<8 x i16> %a, <16 x i8> %b, <16 x i8> %c) #0 {
+// CHECK-LABEL: @test_vmlal_high_s8(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <16 x i8> %b, <16 x i8> %b, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: [[SHUFFLE_I7_I:%.*]] = shufflevector <16 x i8> %c, <16 x i8> %c, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: [[VMULL_I_I_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.smull.v8i16(<8 x i8> [[SHUFFLE_I_I]], <8 x i8> [[SHUFFLE_I7_I]]) #4
@@ -8895,33 +8035,32 @@ uint64x2_t test_vmlal_u32(uint64x2_t a, uint32x2_t b, uint32x2_t c) {
int16x8_t test_vmlal_high_s8(int16x8_t a, int8x16_t b, int8x16_t c) {
return vmlal_high_s8(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlal_high_s16(<4 x i32> %a, <8 x i16> %b, <8 x i16> %c) #0 {
+
+// CHECK-LABEL: @test_vmlal_high_s16(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[SHUFFLE_I7_I:%.*]] = shufflevector <8 x i16> %c, <8 x i16> %c, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE_I7_I]] to <8 x i8>
-// CHECK: [[VMULL_I_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[VMULL_I_I_I]], <4 x i16> [[VMULL1_I_I_I]]) #4
+// CHECK: [[VMULL2_I_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[SHUFFLE_I_I]], <4 x i16> [[SHUFFLE_I7_I]]) #4
// CHECK: [[ADD_I_I:%.*]] = add <4 x i32> %a, [[VMULL2_I_I_I]]
// CHECK: ret <4 x i32> [[ADD_I_I]]
int32x4_t test_vmlal_high_s16(int32x4_t a, int16x8_t b, int16x8_t c) {
return vmlal_high_s16(a, b, c);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlal_high_s32(<2 x i64> %a, <4 x i32> %b, <4 x i32> %c) #0 {
+
+// CHECK-LABEL: @test_vmlal_high_s32(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
// CHECK: [[SHUFFLE_I7_I:%.*]] = shufflevector <4 x i32> %c, <4 x i32> %c, <2 x i32> <i32 2, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE_I7_I]] to <8 x i8>
-// CHECK: [[VMULL_I_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[VMULL_I_I_I]], <2 x i32> [[VMULL1_I_I_I]]) #4
+// CHECK: [[VMULL2_I_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[SHUFFLE_I_I]], <2 x i32> [[SHUFFLE_I7_I]]) #4
// CHECK: [[ADD_I_I:%.*]] = add <2 x i64> %a, [[VMULL2_I_I_I]]
// CHECK: ret <2 x i64> [[ADD_I_I]]
int64x2_t test_vmlal_high_s32(int64x2_t a, int32x4_t b, int32x4_t c) {
return vmlal_high_s32(a, b, c);
}
-// CHECK-LABEL: define <8 x i16> @test_vmlal_high_u8(<8 x i16> %a, <16 x i8> %b, <16 x i8> %c) #0 {
+
+// CHECK-LABEL: @test_vmlal_high_u8(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <16 x i8> %b, <16 x i8> %b, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: [[SHUFFLE_I7_I:%.*]] = shufflevector <16 x i8> %c, <16 x i8> %c, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: [[VMULL_I_I_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.umull.v8i16(<8 x i8> [[SHUFFLE_I_I]], <8 x i8> [[SHUFFLE_I7_I]]) #4
@@ -8930,93 +8069,88 @@ int64x2_t test_vmlal_high_s32(int64x2_t a, int32x4_t b, int32x4_t c) {
uint16x8_t test_vmlal_high_u8(uint16x8_t a, uint8x16_t b, uint8x16_t c) {
return vmlal_high_u8(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlal_high_u16(<4 x i32> %a, <8 x i16> %b, <8 x i16> %c) #0 {
+
+// CHECK-LABEL: @test_vmlal_high_u16(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[SHUFFLE_I7_I:%.*]] = shufflevector <8 x i16> %c, <8 x i16> %c, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE_I7_I]] to <8 x i8>
-// CHECK: [[VMULL_I_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[VMULL_I_I_I]], <4 x i16> [[VMULL1_I_I_I]]) #4
+// CHECK: [[VMULL2_I_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[SHUFFLE_I_I]], <4 x i16> [[SHUFFLE_I7_I]]) #4
// CHECK: [[ADD_I_I:%.*]] = add <4 x i32> %a, [[VMULL2_I_I_I]]
// CHECK: ret <4 x i32> [[ADD_I_I]]
uint32x4_t test_vmlal_high_u16(uint32x4_t a, uint16x8_t b, uint16x8_t c) {
return vmlal_high_u16(a, b, c);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlal_high_u32(<2 x i64> %a, <4 x i32> %b, <4 x i32> %c) #0 {
+
+// CHECK-LABEL: @test_vmlal_high_u32(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
// CHECK: [[SHUFFLE_I7_I:%.*]] = shufflevector <4 x i32> %c, <4 x i32> %c, <2 x i32> <i32 2, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE_I7_I]] to <8 x i8>
-// CHECK: [[VMULL_I_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[VMULL_I_I_I]], <2 x i32> [[VMULL1_I_I_I]]) #4
+// CHECK: [[VMULL2_I_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[SHUFFLE_I_I]], <2 x i32> [[SHUFFLE_I7_I]]) #4
// CHECK: [[ADD_I_I:%.*]] = add <2 x i64> %a, [[VMULL2_I_I_I]]
// CHECK: ret <2 x i64> [[ADD_I_I]]
uint64x2_t test_vmlal_high_u32(uint64x2_t a, uint32x4_t b, uint32x4_t c) {
return vmlal_high_u32(a, b, c);
}
-// CHECK-LABEL: define <8 x i16> @test_vmlsl_s8(<8 x i16> %a, <8 x i8> %b, <8 x i8> %c) #0 {
+// CHECK-LABEL: @test_vmlsl_s8(
// CHECK: [[VMULL_I_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.smull.v8i16(<8 x i8> %b, <8 x i8> %c) #4
// CHECK: [[SUB_I:%.*]] = sub <8 x i16> %a, [[VMULL_I_I]]
// CHECK: ret <8 x i16> [[SUB_I]]
int16x8_t test_vmlsl_s8(int16x8_t a, int8x8_t b, int8x8_t c) {
return vmlsl_s8(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlsl_s16(<4 x i32> %a, <4 x i16> %b, <4 x i16> %c) #0 {
+
+// CHECK-LABEL: @test_vmlsl_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %c to <8 x i8>
-// CHECK: [[VMULL_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[VMULL_I_I]], <4 x i16> [[VMULL1_I_I]]) #4
+// CHECK: [[VMULL2_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> %b, <4 x i16> %c) #4
// CHECK: [[SUB_I:%.*]] = sub <4 x i32> %a, [[VMULL2_I_I]]
// CHECK: ret <4 x i32> [[SUB_I]]
int32x4_t test_vmlsl_s16(int32x4_t a, int16x4_t b, int16x4_t c) {
return vmlsl_s16(a, b, c);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlsl_s32(<2 x i64> %a, <2 x i32> %b, <2 x i32> %c) #0 {
+
+// CHECK-LABEL: @test_vmlsl_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %c to <8 x i8>
-// CHECK: [[VMULL_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[VMULL_I_I]], <2 x i32> [[VMULL1_I_I]]) #4
+// CHECK: [[VMULL2_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> %b, <2 x i32> %c) #4
// CHECK: [[SUB_I:%.*]] = sub <2 x i64> %a, [[VMULL2_I_I]]
// CHECK: ret <2 x i64> [[SUB_I]]
int64x2_t test_vmlsl_s32(int64x2_t a, int32x2_t b, int32x2_t c) {
return vmlsl_s32(a, b, c);
}
-// CHECK-LABEL: define <8 x i16> @test_vmlsl_u8(<8 x i16> %a, <8 x i8> %b, <8 x i8> %c) #0 {
+
+// CHECK-LABEL: @test_vmlsl_u8(
// CHECK: [[VMULL_I_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.umull.v8i16(<8 x i8> %b, <8 x i8> %c) #4
// CHECK: [[SUB_I:%.*]] = sub <8 x i16> %a, [[VMULL_I_I]]
// CHECK: ret <8 x i16> [[SUB_I]]
uint16x8_t test_vmlsl_u8(uint16x8_t a, uint8x8_t b, uint8x8_t c) {
return vmlsl_u8(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlsl_u16(<4 x i32> %a, <4 x i16> %b, <4 x i16> %c) #0 {
+
+// CHECK-LABEL: @test_vmlsl_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %c to <8 x i8>
-// CHECK: [[VMULL_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[VMULL_I_I]], <4 x i16> [[VMULL1_I_I]]) #4
+// CHECK: [[VMULL2_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> %b, <4 x i16> %c) #4
// CHECK: [[SUB_I:%.*]] = sub <4 x i32> %a, [[VMULL2_I_I]]
// CHECK: ret <4 x i32> [[SUB_I]]
uint32x4_t test_vmlsl_u16(uint32x4_t a, uint16x4_t b, uint16x4_t c) {
return vmlsl_u16(a, b, c);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlsl_u32(<2 x i64> %a, <2 x i32> %b, <2 x i32> %c) #0 {
+
+// CHECK-LABEL: @test_vmlsl_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %c to <8 x i8>
-// CHECK: [[VMULL_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[VMULL_I_I]], <2 x i32> [[VMULL1_I_I]]) #4
+// CHECK: [[VMULL2_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> %b, <2 x i32> %c) #4
// CHECK: [[SUB_I:%.*]] = sub <2 x i64> %a, [[VMULL2_I_I]]
// CHECK: ret <2 x i64> [[SUB_I]]
uint64x2_t test_vmlsl_u32(uint64x2_t a, uint32x2_t b, uint32x2_t c) {
return vmlsl_u32(a, b, c);
}
-// CHECK-LABEL: define <8 x i16> @test_vmlsl_high_s8(<8 x i16> %a, <16 x i8> %b, <16 x i8> %c) #0 {
+// CHECK-LABEL: @test_vmlsl_high_s8(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <16 x i8> %b, <16 x i8> %b, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: [[SHUFFLE_I7_I:%.*]] = shufflevector <16 x i8> %c, <16 x i8> %c, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: [[VMULL_I_I_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.smull.v8i16(<8 x i8> [[SHUFFLE_I_I]], <8 x i8> [[SHUFFLE_I7_I]]) #4
@@ -9025,33 +8159,32 @@ uint64x2_t test_vmlsl_u32(uint64x2_t a, uint32x2_t b, uint32x2_t c) {
int16x8_t test_vmlsl_high_s8(int16x8_t a, int8x16_t b, int8x16_t c) {
return vmlsl_high_s8(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlsl_high_s16(<4 x i32> %a, <8 x i16> %b, <8 x i16> %c) #0 {
+
+// CHECK-LABEL: @test_vmlsl_high_s16(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[SHUFFLE_I7_I:%.*]] = shufflevector <8 x i16> %c, <8 x i16> %c, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE_I7_I]] to <8 x i8>
-// CHECK: [[VMULL_I_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[VMULL_I_I_I]], <4 x i16> [[VMULL1_I_I_I]]) #4
+// CHECK: [[VMULL2_I_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.smull.v4i32(<4 x i16> [[SHUFFLE_I_I]], <4 x i16> [[SHUFFLE_I7_I]]) #4
// CHECK: [[SUB_I_I:%.*]] = sub <4 x i32> %a, [[VMULL2_I_I_I]]
// CHECK: ret <4 x i32> [[SUB_I_I]]
int32x4_t test_vmlsl_high_s16(int32x4_t a, int16x8_t b, int16x8_t c) {
return vmlsl_high_s16(a, b, c);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlsl_high_s32(<2 x i64> %a, <4 x i32> %b, <4 x i32> %c) #0 {
+
+// CHECK-LABEL: @test_vmlsl_high_s32(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
// CHECK: [[SHUFFLE_I7_I:%.*]] = shufflevector <4 x i32> %c, <4 x i32> %c, <2 x i32> <i32 2, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE_I7_I]] to <8 x i8>
-// CHECK: [[VMULL_I_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[VMULL_I_I_I]], <2 x i32> [[VMULL1_I_I_I]]) #4
+// CHECK: [[VMULL2_I_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.smull.v2i64(<2 x i32> [[SHUFFLE_I_I]], <2 x i32> [[SHUFFLE_I7_I]]) #4
// CHECK: [[SUB_I_I:%.*]] = sub <2 x i64> %a, [[VMULL2_I_I_I]]
// CHECK: ret <2 x i64> [[SUB_I_I]]
int64x2_t test_vmlsl_high_s32(int64x2_t a, int32x4_t b, int32x4_t c) {
return vmlsl_high_s32(a, b, c);
}
-// CHECK-LABEL: define <8 x i16> @test_vmlsl_high_u8(<8 x i16> %a, <16 x i8> %b, <16 x i8> %c) #0 {
+
+// CHECK-LABEL: @test_vmlsl_high_u8(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <16 x i8> %b, <16 x i8> %b, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: [[SHUFFLE_I7_I:%.*]] = shufflevector <16 x i8> %c, <16 x i8> %c, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: [[VMULL_I_I_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.umull.v8i16(<8 x i8> [[SHUFFLE_I_I]], <8 x i8> [[SHUFFLE_I7_I]]) #4
@@ -9060,215 +8193,179 @@ int64x2_t test_vmlsl_high_s32(int64x2_t a, int32x4_t b, int32x4_t c) {
uint16x8_t test_vmlsl_high_u8(uint16x8_t a, uint8x16_t b, uint8x16_t c) {
return vmlsl_high_u8(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlsl_high_u16(<4 x i32> %a, <8 x i16> %b, <8 x i16> %c) #0 {
+
+// CHECK-LABEL: @test_vmlsl_high_u16(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[SHUFFLE_I7_I:%.*]] = shufflevector <8 x i16> %c, <8 x i16> %c, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE_I7_I]] to <8 x i8>
-// CHECK: [[VMULL_I_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[VMULL_I_I_I]], <4 x i16> [[VMULL1_I_I_I]]) #4
+// CHECK: [[VMULL2_I_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.umull.v4i32(<4 x i16> [[SHUFFLE_I_I]], <4 x i16> [[SHUFFLE_I7_I]]) #4
// CHECK: [[SUB_I_I:%.*]] = sub <4 x i32> %a, [[VMULL2_I_I_I]]
// CHECK: ret <4 x i32> [[SUB_I_I]]
uint32x4_t test_vmlsl_high_u16(uint32x4_t a, uint16x8_t b, uint16x8_t c) {
return vmlsl_high_u16(a, b, c);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlsl_high_u32(<2 x i64> %a, <4 x i32> %b, <4 x i32> %c) #0 {
+
+// CHECK-LABEL: @test_vmlsl_high_u32(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
// CHECK: [[SHUFFLE_I7_I:%.*]] = shufflevector <4 x i32> %c, <4 x i32> %c, <2 x i32> <i32 2, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE_I7_I]] to <8 x i8>
-// CHECK: [[VMULL_I_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[VMULL_I_I_I]], <2 x i32> [[VMULL1_I_I_I]]) #4
+// CHECK: [[VMULL2_I_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.umull.v2i64(<2 x i32> [[SHUFFLE_I_I]], <2 x i32> [[SHUFFLE_I7_I]]) #4
// CHECK: [[SUB_I_I:%.*]] = sub <2 x i64> %a, [[VMULL2_I_I_I]]
// CHECK: ret <2 x i64> [[SUB_I_I]]
uint64x2_t test_vmlsl_high_u32(uint64x2_t a, uint32x4_t b, uint32x4_t c) {
return vmlsl_high_u32(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vqdmull_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqdmull_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VQDMULL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQDMULL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMULL_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[VQDMULL_V_I]], <4 x i16> [[VQDMULL_V1_I]]) #4
+// CHECK: [[VQDMULL_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VQDMULL_V3_I:%.*]] = bitcast <4 x i32> [[VQDMULL_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQDMULL_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VQDMULL_V2_I]]
int32x4_t test_vqdmull_s16(int16x4_t a, int16x4_t b) {
return vqdmull_s16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vqdmull_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+
+// CHECK-LABEL: @test_vqdmull_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VQDMULL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQDMULL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMULL_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[VQDMULL_V_I]], <2 x i32> [[VQDMULL_V1_I]]) #4
+// CHECK: [[VQDMULL_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VQDMULL_V3_I:%.*]] = bitcast <2 x i64> [[VQDMULL_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQDMULL_V3_I]] to <2 x i64>
-// CHECK: ret <2 x i64> [[TMP2]]
+// CHECK: ret <2 x i64> [[VQDMULL_V2_I]]
int64x2_t test_vqdmull_s32(int32x2_t a, int32x2_t b) {
return vqdmull_s32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vqdmlal_s16(<4 x i32> %a, <4 x i16> %b, <4 x i16> %c) #0 {
+// CHECK-LABEL: @test_vqdmlal_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %c to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMLAL1_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VQDMLAL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[VQDMLAL_I]], <4 x i16> [[VQDMLAL1_I]]) #4
-// CHECK: [[VQDMLAL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQDMLAL_V3_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqadd.v4i32(<4 x i32> [[VQDMLAL_V_I]], <4 x i32> [[VQDMLAL2_I]]) #4
+// CHECK: [[VQDMLAL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> %b, <4 x i16> %c) #4
+// CHECK: [[VQDMLAL_V3_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqadd.v4i32(<4 x i32> %a, <4 x i32> [[VQDMLAL2_I]]) #4
// CHECK: ret <4 x i32> [[VQDMLAL_V3_I]]
int32x4_t test_vqdmlal_s16(int32x4_t a, int16x4_t b, int16x4_t c) {
return vqdmlal_s16(a, b, c);
}
-// CHECK-LABEL: define <2 x i64> @test_vqdmlal_s32(<2 x i64> %a, <2 x i32> %b, <2 x i32> %c) #0 {
+// CHECK-LABEL: @test_vqdmlal_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> %c to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMLAL1_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VQDMLAL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[VQDMLAL_I]], <2 x i32> [[VQDMLAL1_I]]) #4
-// CHECK: [[VQDMLAL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQDMLAL_V3_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqadd.v2i64(<2 x i64> [[VQDMLAL_V_I]], <2 x i64> [[VQDMLAL2_I]]) #4
+// CHECK: [[VQDMLAL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> %b, <2 x i32> %c) #4
+// CHECK: [[VQDMLAL_V3_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqadd.v2i64(<2 x i64> %a, <2 x i64> [[VQDMLAL2_I]]) #4
// CHECK: ret <2 x i64> [[VQDMLAL_V3_I]]
int64x2_t test_vqdmlal_s32(int64x2_t a, int32x2_t b, int32x2_t c) {
return vqdmlal_s32(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vqdmlsl_s16(<4 x i32> %a, <4 x i16> %b, <4 x i16> %c) #0 {
+// CHECK-LABEL: @test_vqdmlsl_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %c to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMLAL1_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VQDMLAL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[VQDMLAL_I]], <4 x i16> [[VQDMLAL1_I]]) #4
-// CHECK: [[VQDMLSL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQDMLSL_V3_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqsub.v4i32(<4 x i32> [[VQDMLSL_V_I]], <4 x i32> [[VQDMLAL2_I]]) #4
+// CHECK: [[VQDMLAL2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> %b, <4 x i16> %c) #4
+// CHECK: [[VQDMLSL_V3_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqsub.v4i32(<4 x i32> %a, <4 x i32> [[VQDMLAL2_I]]) #4
// CHECK: ret <4 x i32> [[VQDMLSL_V3_I]]
int32x4_t test_vqdmlsl_s16(int32x4_t a, int16x4_t b, int16x4_t c) {
return vqdmlsl_s16(a, b, c);
}
-// CHECK-LABEL: define <2 x i64> @test_vqdmlsl_s32(<2 x i64> %a, <2 x i32> %b, <2 x i32> %c) #0 {
+// CHECK-LABEL: @test_vqdmlsl_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> %c to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMLAL1_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VQDMLAL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[VQDMLAL_I]], <2 x i32> [[VQDMLAL1_I]]) #4
-// CHECK: [[VQDMLSL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQDMLSL_V3_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqsub.v2i64(<2 x i64> [[VQDMLSL_V_I]], <2 x i64> [[VQDMLAL2_I]]) #4
+// CHECK: [[VQDMLAL2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> %b, <2 x i32> %c) #4
+// CHECK: [[VQDMLSL_V3_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqsub.v2i64(<2 x i64> %a, <2 x i64> [[VQDMLAL2_I]]) #4
// CHECK: ret <2 x i64> [[VQDMLSL_V3_I]]
int64x2_t test_vqdmlsl_s32(int64x2_t a, int32x2_t b, int32x2_t c) {
return vqdmlsl_s32(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vqdmull_high_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqdmull_high_s16(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %a, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[SHUFFLE_I7_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE_I7_I]] to <8 x i8>
-// CHECK: [[VQDMULL_V_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQDMULL_V1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMULL_V2_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[VQDMULL_V_I_I]], <4 x i16> [[VQDMULL_V1_I_I]]) #4
+// CHECK: [[VQDMULL_V2_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[SHUFFLE_I_I]], <4 x i16> [[SHUFFLE_I7_I]]) #4
// CHECK: [[VQDMULL_V3_I_I:%.*]] = bitcast <4 x i32> [[VQDMULL_V2_I_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQDMULL_V3_I_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VQDMULL_V2_I_I]]
int32x4_t test_vqdmull_high_s16(int16x8_t a, int16x8_t b) {
return vqdmull_high_s16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vqdmull_high_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+
+// CHECK-LABEL: @test_vqdmull_high_s32(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %a, <2 x i32> <i32 2, i32 3>
// CHECK: [[SHUFFLE_I7_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE_I7_I]] to <8 x i8>
-// CHECK: [[VQDMULL_V_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQDMULL_V1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMULL_V2_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[VQDMULL_V_I_I]], <2 x i32> [[VQDMULL_V1_I_I]]) #4
+// CHECK: [[VQDMULL_V2_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[SHUFFLE_I_I]], <2 x i32> [[SHUFFLE_I7_I]]) #4
// CHECK: [[VQDMULL_V3_I_I:%.*]] = bitcast <2 x i64> [[VQDMULL_V2_I_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQDMULL_V3_I_I]] to <2 x i64>
-// CHECK: ret <2 x i64> [[TMP2]]
+// CHECK: ret <2 x i64> [[VQDMULL_V2_I_I]]
int64x2_t test_vqdmull_high_s32(int32x4_t a, int32x4_t b) {
return vqdmull_high_s32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vqdmlal_high_s16(<4 x i32> %a, <8 x i16> %b, <8 x i16> %c) #0 {
+// CHECK-LABEL: @test_vqdmlal_high_s16(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[SHUFFLE_I7_I:%.*]] = shufflevector <8 x i16> %c, <8 x i16> %c, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I]] to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> [[SHUFFLE_I7_I]] to <8 x i8>
-// CHECK: [[VQDMLAL_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMLAL1_I_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VQDMLAL2_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[VQDMLAL_I_I]], <4 x i16> [[VQDMLAL1_I_I]]) #4
-// CHECK: [[VQDMLAL_V_I_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQDMLAL_V3_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqadd.v4i32(<4 x i32> [[VQDMLAL_V_I_I]], <4 x i32> [[VQDMLAL2_I_I]]) #4
+// CHECK: [[VQDMLAL2_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[SHUFFLE_I_I]], <4 x i16> [[SHUFFLE_I7_I]]) #4
+// CHECK: [[VQDMLAL_V3_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqadd.v4i32(<4 x i32> %a, <4 x i32> [[VQDMLAL2_I_I]]) #4
// CHECK: ret <4 x i32> [[VQDMLAL_V3_I_I]]
int32x4_t test_vqdmlal_high_s16(int32x4_t a, int16x8_t b, int16x8_t c) {
return vqdmlal_high_s16(a, b, c);
}
-// CHECK-LABEL: define <2 x i64> @test_vqdmlal_high_s32(<2 x i64> %a, <4 x i32> %b, <4 x i32> %c) #0 {
+// CHECK-LABEL: @test_vqdmlal_high_s32(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
// CHECK: [[SHUFFLE_I7_I:%.*]] = shufflevector <4 x i32> %c, <4 x i32> %c, <2 x i32> <i32 2, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I]] to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> [[SHUFFLE_I7_I]] to <8 x i8>
-// CHECK: [[VQDMLAL_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMLAL1_I_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VQDMLAL2_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[VQDMLAL_I_I]], <2 x i32> [[VQDMLAL1_I_I]]) #4
-// CHECK: [[VQDMLAL_V_I_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQDMLAL_V3_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqadd.v2i64(<2 x i64> [[VQDMLAL_V_I_I]], <2 x i64> [[VQDMLAL2_I_I]]) #4
+// CHECK: [[VQDMLAL2_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[SHUFFLE_I_I]], <2 x i32> [[SHUFFLE_I7_I]]) #4
+// CHECK: [[VQDMLAL_V3_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqadd.v2i64(<2 x i64> %a, <2 x i64> [[VQDMLAL2_I_I]]) #4
// CHECK: ret <2 x i64> [[VQDMLAL_V3_I_I]]
int64x2_t test_vqdmlal_high_s32(int64x2_t a, int32x4_t b, int32x4_t c) {
return vqdmlal_high_s32(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vqdmlsl_high_s16(<4 x i32> %a, <8 x i16> %b, <8 x i16> %c) #0 {
+// CHECK-LABEL: @test_vqdmlsl_high_s16(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <8 x i16> %b, <8 x i16> %b, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[SHUFFLE_I7_I:%.*]] = shufflevector <8 x i16> %c, <8 x i16> %c, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE_I_I]] to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> [[SHUFFLE_I7_I]] to <8 x i8>
-// CHECK: [[VQDMLAL_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMLAL1_I_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VQDMLAL2_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[VQDMLAL_I_I]], <4 x i16> [[VQDMLAL1_I_I]]) #4
-// CHECK: [[VQDMLSL_V_I_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQDMLSL_V3_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqsub.v4i32(<4 x i32> [[VQDMLSL_V_I_I]], <4 x i32> [[VQDMLAL2_I_I]]) #4
+// CHECK: [[VQDMLAL2_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[SHUFFLE_I_I]], <4 x i16> [[SHUFFLE_I7_I]]) #4
+// CHECK: [[VQDMLSL_V3_I_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqsub.v4i32(<4 x i32> %a, <4 x i32> [[VQDMLAL2_I_I]]) #4
// CHECK: ret <4 x i32> [[VQDMLSL_V3_I_I]]
int32x4_t test_vqdmlsl_high_s16(int32x4_t a, int16x8_t b, int16x8_t c) {
return vqdmlsl_high_s16(a, b, c);
}
-// CHECK-LABEL: define <2 x i64> @test_vqdmlsl_high_s32(<2 x i64> %a, <4 x i32> %b, <4 x i32> %c) #0 {
+// CHECK-LABEL: @test_vqdmlsl_high_s32(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x i32> %b, <4 x i32> %b, <2 x i32> <i32 2, i32 3>
// CHECK: [[SHUFFLE_I7_I:%.*]] = shufflevector <4 x i32> %c, <4 x i32> %c, <2 x i32> <i32 2, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE_I_I]] to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> [[SHUFFLE_I7_I]] to <8 x i8>
-// CHECK: [[VQDMLAL_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMLAL1_I_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VQDMLAL2_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[VQDMLAL_I_I]], <2 x i32> [[VQDMLAL1_I_I]]) #4
-// CHECK: [[VQDMLSL_V_I_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQDMLSL_V3_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqsub.v2i64(<2 x i64> [[VQDMLSL_V_I_I]], <2 x i64> [[VQDMLAL2_I_I]]) #4
+// CHECK: [[VQDMLAL2_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqdmull.v2i64(<2 x i32> [[SHUFFLE_I_I]], <2 x i32> [[SHUFFLE_I7_I]]) #4
+// CHECK: [[VQDMLSL_V3_I_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqsub.v2i64(<2 x i64> %a, <2 x i64> [[VQDMLAL2_I_I]]) #4
// CHECK: ret <2 x i64> [[VQDMLSL_V3_I_I]]
int64x2_t test_vqdmlsl_high_s32(int64x2_t a, int32x4_t b, int32x4_t c) {
return vqdmlsl_high_s32(a, b, c);
}
-// CHECK-LABEL: define <8 x i16> @test_vmull_p8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vmull_p8(
// CHECK: [[VMULL_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.pmull.v8i16(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i16> [[VMULL_I]]
poly16x8_t test_vmull_p8(poly8x8_t a, poly8x8_t b) {
return vmull_p8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vmull_high_p8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vmull_high_p8(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %a, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: [[SHUFFLE_I7_I:%.*]] = shufflevector <16 x i8> %b, <16 x i8> %b, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: [[VMULL_I_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.pmull.v8i16(<8 x i8> [[SHUFFLE_I_I]], <8 x i8> [[SHUFFLE_I7_I]]) #4
@@ -9277,35 +8374,35 @@ poly16x8_t test_vmull_high_p8(poly8x16_t a, poly8x16_t b) {
return vmull_high_p8(a, b);
}
-// CHECK-LABEL: define i64 @test_vaddd_s64(i64 %a, i64 %b) #0 {
+// CHECK-LABEL: @test_vaddd_s64(
// CHECK: [[VADDD_I:%.*]] = add i64 %a, %b
// CHECK: ret i64 [[VADDD_I]]
int64_t test_vaddd_s64(int64_t a, int64_t b) {
return vaddd_s64(a, b);
}
-// CHECK-LABEL: define i64 @test_vaddd_u64(i64 %a, i64 %b) #0 {
+// CHECK-LABEL: @test_vaddd_u64(
// CHECK: [[VADDD_I:%.*]] = add i64 %a, %b
// CHECK: ret i64 [[VADDD_I]]
uint64_t test_vaddd_u64(uint64_t a, uint64_t b) {
return vaddd_u64(a, b);
}
-// CHECK-LABEL: define i64 @test_vsubd_s64(i64 %a, i64 %b) #0 {
+// CHECK-LABEL: @test_vsubd_s64(
// CHECK: [[VSUBD_I:%.*]] = sub i64 %a, %b
// CHECK: ret i64 [[VSUBD_I]]
int64_t test_vsubd_s64(int64_t a, int64_t b) {
return vsubd_s64(a, b);
}
-// CHECK-LABEL: define i64 @test_vsubd_u64(i64 %a, i64 %b) #0 {
+// CHECK-LABEL: @test_vsubd_u64(
// CHECK: [[VSUBD_I:%.*]] = sub i64 %a, %b
// CHECK: ret i64 [[VSUBD_I]]
uint64_t test_vsubd_u64(uint64_t a, uint64_t b) {
return vsubd_u64(a, b);
}
-// CHECK-LABEL: define i8 @test_vqaddb_s8(i8 %a, i8 %b) #0 {
+// CHECK-LABEL: @test_vqaddb_s8(
// CHECK: [[TMP0:%.*]] = insertelement <8 x i8> undef, i8 %a, i64 0
// CHECK: [[TMP1:%.*]] = insertelement <8 x i8> undef, i8 %b, i64 0
// CHECK: [[VQADDB_S8_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.sqadd.v8i8(<8 x i8> [[TMP0]], <8 x i8> [[TMP1]]) #4
@@ -9315,7 +8412,7 @@ int8_t test_vqaddb_s8(int8_t a, int8_t b) {
return vqaddb_s8(a, b);
}
-// CHECK-LABEL: define i16 @test_vqaddh_s16(i16 %a, i16 %b) #0 {
+// CHECK-LABEL: @test_vqaddh_s16(
// CHECK: [[TMP0:%.*]] = insertelement <4 x i16> undef, i16 %a, i64 0
// CHECK: [[TMP1:%.*]] = insertelement <4 x i16> undef, i16 %b, i64 0
// CHECK: [[VQADDH_S16_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqadd.v4i16(<4 x i16> [[TMP0]], <4 x i16> [[TMP1]]) #4
@@ -9325,21 +8422,21 @@ int16_t test_vqaddh_s16(int16_t a, int16_t b) {
return vqaddh_s16(a, b);
}
-// CHECK-LABEL: define i32 @test_vqadds_s32(i32 %a, i32 %b) #0 {
+// CHECK-LABEL: @test_vqadds_s32(
// CHECK: [[VQADDS_S32_I:%.*]] = call i32 @llvm.aarch64.neon.sqadd.i32(i32 %a, i32 %b) #4
// CHECK: ret i32 [[VQADDS_S32_I]]
int32_t test_vqadds_s32(int32_t a, int32_t b) {
return vqadds_s32(a, b);
}
-// CHECK-LABEL: define i64 @test_vqaddd_s64(i64 %a, i64 %b) #0 {
+// CHECK-LABEL: @test_vqaddd_s64(
// CHECK: [[VQADDD_S64_I:%.*]] = call i64 @llvm.aarch64.neon.sqadd.i64(i64 %a, i64 %b) #4
// CHECK: ret i64 [[VQADDD_S64_I]]
int64_t test_vqaddd_s64(int64_t a, int64_t b) {
return vqaddd_s64(a, b);
}
-// CHECK-LABEL: define i8 @test_vqaddb_u8(i8 %a, i8 %b) #0 {
+// CHECK-LABEL: @test_vqaddb_u8(
// CHECK: [[TMP0:%.*]] = insertelement <8 x i8> undef, i8 %a, i64 0
// CHECK: [[TMP1:%.*]] = insertelement <8 x i8> undef, i8 %b, i64 0
// CHECK: [[VQADDB_U8_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.uqadd.v8i8(<8 x i8> [[TMP0]], <8 x i8> [[TMP1]]) #4
@@ -9349,7 +8446,7 @@ uint8_t test_vqaddb_u8(uint8_t a, uint8_t b) {
return vqaddb_u8(a, b);
}
-// CHECK-LABEL: define i16 @test_vqaddh_u16(i16 %a, i16 %b) #0 {
+// CHECK-LABEL: @test_vqaddh_u16(
// CHECK: [[TMP0:%.*]] = insertelement <4 x i16> undef, i16 %a, i64 0
// CHECK: [[TMP1:%.*]] = insertelement <4 x i16> undef, i16 %b, i64 0
// CHECK: [[VQADDH_U16_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.uqadd.v4i16(<4 x i16> [[TMP0]], <4 x i16> [[TMP1]]) #4
@@ -9359,21 +8456,21 @@ uint16_t test_vqaddh_u16(uint16_t a, uint16_t b) {
return vqaddh_u16(a, b);
}
-// CHECK-LABEL: define i32 @test_vqadds_u32(i32 %a, i32 %b) #0 {
+// CHECK-LABEL: @test_vqadds_u32(
// CHECK: [[VQADDS_U32_I:%.*]] = call i32 @llvm.aarch64.neon.uqadd.i32(i32 %a, i32 %b) #4
// CHECK: ret i32 [[VQADDS_U32_I]]
uint32_t test_vqadds_u32(uint32_t a, uint32_t b) {
return vqadds_u32(a, b);
}
-// CHECK-LABEL: define i64 @test_vqaddd_u64(i64 %a, i64 %b) #0 {
+// CHECK-LABEL: @test_vqaddd_u64(
// CHECK: [[VQADDD_U64_I:%.*]] = call i64 @llvm.aarch64.neon.uqadd.i64(i64 %a, i64 %b) #4
// CHECK: ret i64 [[VQADDD_U64_I]]
uint64_t test_vqaddd_u64(uint64_t a, uint64_t b) {
return vqaddd_u64(a, b);
}
-// CHECK-LABEL: define i8 @test_vqsubb_s8(i8 %a, i8 %b) #0 {
+// CHECK-LABEL: @test_vqsubb_s8(
// CHECK: [[TMP0:%.*]] = insertelement <8 x i8> undef, i8 %a, i64 0
// CHECK: [[TMP1:%.*]] = insertelement <8 x i8> undef, i8 %b, i64 0
// CHECK: [[VQSUBB_S8_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.sqsub.v8i8(<8 x i8> [[TMP0]], <8 x i8> [[TMP1]]) #4
@@ -9383,7 +8480,7 @@ int8_t test_vqsubb_s8(int8_t a, int8_t b) {
return vqsubb_s8(a, b);
}
-// CHECK-LABEL: define i16 @test_vqsubh_s16(i16 %a, i16 %b) #0 {
+// CHECK-LABEL: @test_vqsubh_s16(
// CHECK: [[TMP0:%.*]] = insertelement <4 x i16> undef, i16 %a, i64 0
// CHECK: [[TMP1:%.*]] = insertelement <4 x i16> undef, i16 %b, i64 0
// CHECK: [[VQSUBH_S16_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqsub.v4i16(<4 x i16> [[TMP0]], <4 x i16> [[TMP1]]) #4
@@ -9393,21 +8490,21 @@ int16_t test_vqsubh_s16(int16_t a, int16_t b) {
return vqsubh_s16(a, b);
}
-// CHECK-LABEL: define i32 @test_vqsubs_s32(i32 %a, i32 %b) #0 {
+// CHECK-LABEL: @test_vqsubs_s32(
// CHECK: [[VQSUBS_S32_I:%.*]] = call i32 @llvm.aarch64.neon.sqsub.i32(i32 %a, i32 %b) #4
// CHECK: ret i32 [[VQSUBS_S32_I]]
int32_t test_vqsubs_s32(int32_t a, int32_t b) {
return vqsubs_s32(a, b);
}
-// CHECK-LABEL: define i64 @test_vqsubd_s64(i64 %a, i64 %b) #0 {
+// CHECK-LABEL: @test_vqsubd_s64(
// CHECK: [[VQSUBD_S64_I:%.*]] = call i64 @llvm.aarch64.neon.sqsub.i64(i64 %a, i64 %b) #4
// CHECK: ret i64 [[VQSUBD_S64_I]]
int64_t test_vqsubd_s64(int64_t a, int64_t b) {
return vqsubd_s64(a, b);
}
-// CHECK-LABEL: define i8 @test_vqsubb_u8(i8 %a, i8 %b) #0 {
+// CHECK-LABEL: @test_vqsubb_u8(
// CHECK: [[TMP0:%.*]] = insertelement <8 x i8> undef, i8 %a, i64 0
// CHECK: [[TMP1:%.*]] = insertelement <8 x i8> undef, i8 %b, i64 0
// CHECK: [[VQSUBB_U8_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.uqsub.v8i8(<8 x i8> [[TMP0]], <8 x i8> [[TMP1]]) #4
@@ -9417,7 +8514,7 @@ uint8_t test_vqsubb_u8(uint8_t a, uint8_t b) {
return vqsubb_u8(a, b);
}
-// CHECK-LABEL: define i16 @test_vqsubh_u16(i16 %a, i16 %b) #0 {
+// CHECK-LABEL: @test_vqsubh_u16(
// CHECK: [[TMP0:%.*]] = insertelement <4 x i16> undef, i16 %a, i64 0
// CHECK: [[TMP1:%.*]] = insertelement <4 x i16> undef, i16 %b, i64 0
// CHECK: [[VQSUBH_U16_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.uqsub.v4i16(<4 x i16> [[TMP0]], <4 x i16> [[TMP1]]) #4
@@ -9427,35 +8524,35 @@ uint16_t test_vqsubh_u16(uint16_t a, uint16_t b) {
return vqsubh_u16(a, b);
}
-// CHECK-LABEL: define i32 @test_vqsubs_u32(i32 %a, i32 %b) #0 {
+// CHECK-LABEL: @test_vqsubs_u32(
// CHECK: [[VQSUBS_U32_I:%.*]] = call i32 @llvm.aarch64.neon.uqsub.i32(i32 %a, i32 %b) #4
// CHECK: ret i32 [[VQSUBS_U32_I]]
uint32_t test_vqsubs_u32(uint32_t a, uint32_t b) {
return vqsubs_u32(a, b);
}
-// CHECK-LABEL: define i64 @test_vqsubd_u64(i64 %a, i64 %b) #0 {
+// CHECK-LABEL: @test_vqsubd_u64(
// CHECK: [[VQSUBD_U64_I:%.*]] = call i64 @llvm.aarch64.neon.uqsub.i64(i64 %a, i64 %b) #4
// CHECK: ret i64 [[VQSUBD_U64_I]]
uint64_t test_vqsubd_u64(uint64_t a, uint64_t b) {
return vqsubd_u64(a, b);
}
-// CHECK-LABEL: define i64 @test_vshld_s64(i64 %a, i64 %b) #0 {
+// CHECK-LABEL: @test_vshld_s64(
// CHECK: [[VSHLD_S64_I:%.*]] = call i64 @llvm.aarch64.neon.sshl.i64(i64 %a, i64 %b) #4
// CHECK: ret i64 [[VSHLD_S64_I]]
int64_t test_vshld_s64(int64_t a, int64_t b) {
return vshld_s64(a, b);
}
-// CHECK-LABEL: define i64 @test_vshld_u64(i64 %a, i64 %b) #0 {
+// CHECK-LABEL: @test_vshld_u64(
// CHECK: [[VSHLD_U64_I:%.*]] = call i64 @llvm.aarch64.neon.ushl.i64(i64 %a, i64 %b) #4
// CHECK: ret i64 [[VSHLD_U64_I]]
uint64_t test_vshld_u64(uint64_t a, uint64_t b) {
return vshld_u64(a, b);
}
-// CHECK-LABEL: define i8 @test_vqshlb_s8(i8 %a, i8 %b) #0 {
+// CHECK-LABEL: @test_vqshlb_s8(
// CHECK: [[TMP0:%.*]] = insertelement <8 x i8> undef, i8 %a, i64 0
// CHECK: [[TMP1:%.*]] = insertelement <8 x i8> undef, i8 %b, i64 0
// CHECK: [[VQSHLB_S8_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.sqshl.v8i8(<8 x i8> [[TMP0]], <8 x i8> [[TMP1]]) #4
@@ -9465,7 +8562,7 @@ int8_t test_vqshlb_s8(int8_t a, int8_t b) {
return vqshlb_s8(a, b);
}
-// CHECK-LABEL: define i16 @test_vqshlh_s16(i16 %a, i16 %b) #0 {
+// CHECK-LABEL: @test_vqshlh_s16(
// CHECK: [[TMP0:%.*]] = insertelement <4 x i16> undef, i16 %a, i64 0
// CHECK: [[TMP1:%.*]] = insertelement <4 x i16> undef, i16 %b, i64 0
// CHECK: [[VQSHLH_S16_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqshl.v4i16(<4 x i16> [[TMP0]], <4 x i16> [[TMP1]]) #4
@@ -9475,21 +8572,21 @@ int16_t test_vqshlh_s16(int16_t a, int16_t b) {
return vqshlh_s16(a, b);
}
-// CHECK-LABEL: define i32 @test_vqshls_s32(i32 %a, i32 %b) #0 {
+// CHECK-LABEL: @test_vqshls_s32(
// CHECK: [[VQSHLS_S32_I:%.*]] = call i32 @llvm.aarch64.neon.sqshl.i32(i32 %a, i32 %b) #4
// CHECK: ret i32 [[VQSHLS_S32_I]]
int32_t test_vqshls_s32(int32_t a, int32_t b) {
return vqshls_s32(a, b);
}
-// CHECK-LABEL: define i64 @test_vqshld_s64(i64 %a, i64 %b) #0 {
+// CHECK-LABEL: @test_vqshld_s64(
// CHECK: [[VQSHLD_S64_I:%.*]] = call i64 @llvm.aarch64.neon.sqshl.i64(i64 %a, i64 %b) #4
// CHECK: ret i64 [[VQSHLD_S64_I]]
int64_t test_vqshld_s64(int64_t a, int64_t b) {
return vqshld_s64(a, b);
}
-// CHECK-LABEL: define i8 @test_vqshlb_u8(i8 %a, i8 %b) #0 {
+// CHECK-LABEL: @test_vqshlb_u8(
// CHECK: [[TMP0:%.*]] = insertelement <8 x i8> undef, i8 %a, i64 0
// CHECK: [[TMP1:%.*]] = insertelement <8 x i8> undef, i8 %b, i64 0
// CHECK: [[VQSHLB_U8_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.uqshl.v8i8(<8 x i8> [[TMP0]], <8 x i8> [[TMP1]]) #4
@@ -9499,7 +8596,7 @@ uint8_t test_vqshlb_u8(uint8_t a, uint8_t b) {
return vqshlb_u8(a, b);
}
-// CHECK-LABEL: define i16 @test_vqshlh_u16(i16 %a, i16 %b) #0 {
+// CHECK-LABEL: @test_vqshlh_u16(
// CHECK: [[TMP0:%.*]] = insertelement <4 x i16> undef, i16 %a, i64 0
// CHECK: [[TMP1:%.*]] = insertelement <4 x i16> undef, i16 %b, i64 0
// CHECK: [[VQSHLH_U16_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.uqshl.v4i16(<4 x i16> [[TMP0]], <4 x i16> [[TMP1]]) #4
@@ -9509,36 +8606,35 @@ uint16_t test_vqshlh_u16(uint16_t a, uint16_t b) {
return vqshlh_u16(a, b);
}
-// CHECK-LABEL: define i32 @test_vqshls_u32(i32 %a, i32 %b) #0 {
+// CHECK-LABEL: @test_vqshls_u32(
// CHECK: [[VQSHLS_U32_I:%.*]] = call i32 @llvm.aarch64.neon.uqshl.i32(i32 %a, i32 %b) #4
// CHECK: ret i32 [[VQSHLS_U32_I]]
uint32_t test_vqshls_u32(uint32_t a, uint32_t b) {
return vqshls_u32(a, b);
}
-// CHECK-LABEL: define i64 @test_vqshld_u64(i64 %a, i64 %b) #0 {
+// CHECK-LABEL: @test_vqshld_u64(
// CHECK: [[VQSHLD_U64_I:%.*]] = call i64 @llvm.aarch64.neon.uqshl.i64(i64 %a, i64 %b) #4
// CHECK: ret i64 [[VQSHLD_U64_I]]
uint64_t test_vqshld_u64(uint64_t a, uint64_t b) {
return vqshld_u64(a, b);
}
-// CHECK-LABEL: define i64 @test_vrshld_s64(i64 %a, i64 %b) #0 {
+// CHECK-LABEL: @test_vrshld_s64(
// CHECK: [[VRSHLD_S64_I:%.*]] = call i64 @llvm.aarch64.neon.srshl.i64(i64 %a, i64 %b) #4
// CHECK: ret i64 [[VRSHLD_S64_I]]
int64_t test_vrshld_s64(int64_t a, int64_t b) {
return vrshld_s64(a, b);
}
-
-// CHECK-LABEL: define i64 @test_vrshld_u64(i64 %a, i64 %b) #0 {
+// CHECK-LABEL: @test_vrshld_u64(
// CHECK: [[VRSHLD_U64_I:%.*]] = call i64 @llvm.aarch64.neon.urshl.i64(i64 %a, i64 %b) #4
// CHECK: ret i64 [[VRSHLD_U64_I]]
uint64_t test_vrshld_u64(uint64_t a, uint64_t b) {
return vrshld_u64(a, b);
}
-// CHECK-LABEL: define i8 @test_vqrshlb_s8(i8 %a, i8 %b) #0 {
+// CHECK-LABEL: @test_vqrshlb_s8(
// CHECK: [[TMP0:%.*]] = insertelement <8 x i8> undef, i8 %a, i64 0
// CHECK: [[TMP1:%.*]] = insertelement <8 x i8> undef, i8 %b, i64 0
// CHECK: [[VQRSHLB_S8_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.sqrshl.v8i8(<8 x i8> [[TMP0]], <8 x i8> [[TMP1]]) #4
@@ -9548,7 +8644,7 @@ int8_t test_vqrshlb_s8(int8_t a, int8_t b) {
return vqrshlb_s8(a, b);
}
-// CHECK-LABEL: define i16 @test_vqrshlh_s16(i16 %a, i16 %b) #0 {
+// CHECK-LABEL: @test_vqrshlh_s16(
// CHECK: [[TMP0:%.*]] = insertelement <4 x i16> undef, i16 %a, i64 0
// CHECK: [[TMP1:%.*]] = insertelement <4 x i16> undef, i16 %b, i64 0
// CHECK: [[VQRSHLH_S16_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqrshl.v4i16(<4 x i16> [[TMP0]], <4 x i16> [[TMP1]]) #4
@@ -9558,21 +8654,21 @@ int16_t test_vqrshlh_s16(int16_t a, int16_t b) {
return vqrshlh_s16(a, b);
}
-// CHECK-LABEL: define i32 @test_vqrshls_s32(i32 %a, i32 %b) #0 {
+// CHECK-LABEL: @test_vqrshls_s32(
// CHECK: [[VQRSHLS_S32_I:%.*]] = call i32 @llvm.aarch64.neon.sqrshl.i32(i32 %a, i32 %b) #4
// CHECK: ret i32 [[VQRSHLS_S32_I]]
int32_t test_vqrshls_s32(int32_t a, int32_t b) {
return vqrshls_s32(a, b);
}
-// CHECK-LABEL: define i64 @test_vqrshld_s64(i64 %a, i64 %b) #0 {
+// CHECK-LABEL: @test_vqrshld_s64(
// CHECK: [[VQRSHLD_S64_I:%.*]] = call i64 @llvm.aarch64.neon.sqrshl.i64(i64 %a, i64 %b) #4
// CHECK: ret i64 [[VQRSHLD_S64_I]]
int64_t test_vqrshld_s64(int64_t a, int64_t b) {
return vqrshld_s64(a, b);
}
-// CHECK-LABEL: define i8 @test_vqrshlb_u8(i8 %a, i8 %b) #0 {
+// CHECK-LABEL: @test_vqrshlb_u8(
// CHECK: [[TMP0:%.*]] = insertelement <8 x i8> undef, i8 %a, i64 0
// CHECK: [[TMP1:%.*]] = insertelement <8 x i8> undef, i8 %b, i64 0
// CHECK: [[VQRSHLB_U8_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.uqrshl.v8i8(<8 x i8> [[TMP0]], <8 x i8> [[TMP1]]) #4
@@ -9582,7 +8678,7 @@ uint8_t test_vqrshlb_u8(uint8_t a, uint8_t b) {
return vqrshlb_u8(a, b);
}
-// CHECK-LABEL: define i16 @test_vqrshlh_u16(i16 %a, i16 %b) #0 {
+// CHECK-LABEL: @test_vqrshlh_u16(
// CHECK: [[TMP0:%.*]] = insertelement <4 x i16> undef, i16 %a, i64 0
// CHECK: [[TMP1:%.*]] = insertelement <4 x i16> undef, i16 %b, i64 0
// CHECK: [[VQRSHLH_U16_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.uqrshl.v4i16(<4 x i16> [[TMP0]], <4 x i16> [[TMP1]]) #4
@@ -9592,124 +8688,113 @@ uint16_t test_vqrshlh_u16(uint16_t a, uint16_t b) {
return vqrshlh_u16(a, b);
}
-// CHECK-LABEL: define i32 @test_vqrshls_u32(i32 %a, i32 %b) #0 {
+// CHECK-LABEL: @test_vqrshls_u32(
// CHECK: [[VQRSHLS_U32_I:%.*]] = call i32 @llvm.aarch64.neon.uqrshl.i32(i32 %a, i32 %b) #4
// CHECK: ret i32 [[VQRSHLS_U32_I]]
uint32_t test_vqrshls_u32(uint32_t a, uint32_t b) {
return vqrshls_u32(a, b);
}
-// CHECK-LABEL: define i64 @test_vqrshld_u64(i64 %a, i64 %b) #0 {
+// CHECK-LABEL: @test_vqrshld_u64(
// CHECK: [[VQRSHLD_U64_I:%.*]] = call i64 @llvm.aarch64.neon.uqrshl.i64(i64 %a, i64 %b) #4
// CHECK: ret i64 [[VQRSHLD_U64_I]]
uint64_t test_vqrshld_u64(uint64_t a, uint64_t b) {
return vqrshld_u64(a, b);
}
-// CHECK-LABEL: define i64 @test_vpaddd_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vpaddd_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VPADDD_S64_I:%.*]] = call i64 @llvm.aarch64.neon.uaddv.i64.v2i64(<2 x i64> [[TMP1]]) #4
+// CHECK: [[VPADDD_S64_I:%.*]] = call i64 @llvm.aarch64.neon.uaddv.i64.v2i64(<2 x i64> %a) #4
// CHECK: ret i64 [[VPADDD_S64_I]]
int64_t test_vpaddd_s64(int64x2_t a) {
return vpaddd_s64(a);
}
-// CHECK-LABEL: define float @test_vpadds_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vpadds_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[LANE0_I:%.*]] = extractelement <2 x float> [[TMP1]], i64 0
-// CHECK: [[LANE1_I:%.*]] = extractelement <2 x float> [[TMP1]], i64 1
+// CHECK: [[LANE0_I:%.*]] = extractelement <2 x float> %a, i64 0
+// CHECK: [[LANE1_I:%.*]] = extractelement <2 x float> %a, i64 1
// CHECK: [[VPADDD_I:%.*]] = fadd float [[LANE0_I]], [[LANE1_I]]
// CHECK: ret float [[VPADDD_I]]
float32_t test_vpadds_f32(float32x2_t a) {
return vpadds_f32(a);
}
-// CHECK-LABEL: define double @test_vpaddd_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vpaddd_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[LANE0_I:%.*]] = extractelement <2 x double> [[TMP1]], i64 0
-// CHECK: [[LANE1_I:%.*]] = extractelement <2 x double> [[TMP1]], i64 1
+// CHECK: [[LANE0_I:%.*]] = extractelement <2 x double> %a, i64 0
+// CHECK: [[LANE1_I:%.*]] = extractelement <2 x double> %a, i64 1
// CHECK: [[VPADDD_I:%.*]] = fadd double [[LANE0_I]], [[LANE1_I]]
// CHECK: ret double [[VPADDD_I]]
float64_t test_vpaddd_f64(float64x2_t a) {
return vpaddd_f64(a);
}
-// CHECK-LABEL: define float @test_vpmaxnms_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vpmaxnms_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VPMAXNMS_F32_I:%.*]] = call float @llvm.aarch64.neon.fmaxnmv.f32.v2f32(<2 x float> [[TMP1]]) #4
+// CHECK: [[VPMAXNMS_F32_I:%.*]] = call float @llvm.aarch64.neon.fmaxnmv.f32.v2f32(<2 x float> %a) #4
// CHECK: ret float [[VPMAXNMS_F32_I]]
float32_t test_vpmaxnms_f32(float32x2_t a) {
return vpmaxnms_f32(a);
}
-// CHECK-LABEL: define double @test_vpmaxnmqd_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vpmaxnmqd_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VPMAXNMQD_F64_I:%.*]] = call double @llvm.aarch64.neon.fmaxnmv.f64.v2f64(<2 x double> [[TMP1]]) #4
+// CHECK: [[VPMAXNMQD_F64_I:%.*]] = call double @llvm.aarch64.neon.fmaxnmv.f64.v2f64(<2 x double> %a) #4
// CHECK: ret double [[VPMAXNMQD_F64_I]]
float64_t test_vpmaxnmqd_f64(float64x2_t a) {
return vpmaxnmqd_f64(a);
}
-// CHECK-LABEL: define float @test_vpmaxs_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vpmaxs_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VPMAXS_F32_I:%.*]] = call float @llvm.aarch64.neon.fmaxv.f32.v2f32(<2 x float> [[TMP1]]) #4
+// CHECK: [[VPMAXS_F32_I:%.*]] = call float @llvm.aarch64.neon.fmaxv.f32.v2f32(<2 x float> %a) #4
// CHECK: ret float [[VPMAXS_F32_I]]
float32_t test_vpmaxs_f32(float32x2_t a) {
return vpmaxs_f32(a);
}
-// CHECK-LABEL: define double @test_vpmaxqd_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vpmaxqd_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VPMAXQD_F64_I:%.*]] = call double @llvm.aarch64.neon.fmaxv.f64.v2f64(<2 x double> [[TMP1]]) #4
+// CHECK: [[VPMAXQD_F64_I:%.*]] = call double @llvm.aarch64.neon.fmaxv.f64.v2f64(<2 x double> %a) #4
// CHECK: ret double [[VPMAXQD_F64_I]]
float64_t test_vpmaxqd_f64(float64x2_t a) {
return vpmaxqd_f64(a);
}
-// CHECK-LABEL: define float @test_vpminnms_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vpminnms_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VPMINNMS_F32_I:%.*]] = call float @llvm.aarch64.neon.fminnmv.f32.v2f32(<2 x float> [[TMP1]]) #4
+// CHECK: [[VPMINNMS_F32_I:%.*]] = call float @llvm.aarch64.neon.fminnmv.f32.v2f32(<2 x float> %a) #4
// CHECK: ret float [[VPMINNMS_F32_I]]
float32_t test_vpminnms_f32(float32x2_t a) {
return vpminnms_f32(a);
}
-// CHECK-LABEL: define double @test_vpminnmqd_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vpminnmqd_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VPMINNMQD_F64_I:%.*]] = call double @llvm.aarch64.neon.fminnmv.f64.v2f64(<2 x double> [[TMP1]]) #4
+// CHECK: [[VPMINNMQD_F64_I:%.*]] = call double @llvm.aarch64.neon.fminnmv.f64.v2f64(<2 x double> %a) #4
// CHECK: ret double [[VPMINNMQD_F64_I]]
float64_t test_vpminnmqd_f64(float64x2_t a) {
return vpminnmqd_f64(a);
}
-// CHECK-LABEL: define float @test_vpmins_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vpmins_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VPMINS_F32_I:%.*]] = call float @llvm.aarch64.neon.fminv.f32.v2f32(<2 x float> [[TMP1]]) #4
+// CHECK: [[VPMINS_F32_I:%.*]] = call float @llvm.aarch64.neon.fminv.f32.v2f32(<2 x float> %a) #4
// CHECK: ret float [[VPMINS_F32_I]]
float32_t test_vpmins_f32(float32x2_t a) {
return vpmins_f32(a);
}
-// CHECK-LABEL: define double @test_vpminqd_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vpminqd_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VPMINQD_F64_I:%.*]] = call double @llvm.aarch64.neon.fminv.f64.v2f64(<2 x double> [[TMP1]]) #4
+// CHECK: [[VPMINQD_F64_I:%.*]] = call double @llvm.aarch64.neon.fminv.f64.v2f64(<2 x double> %a) #4
// CHECK: ret double [[VPMINQD_F64_I]]
float64_t test_vpminqd_f64(float64x2_t a) {
return vpminqd_f64(a);
}
-// CHECK-LABEL: define i16 @test_vqdmulhh_s16(i16 %a, i16 %b) #0 {
+// CHECK-LABEL: @test_vqdmulhh_s16(
// CHECK: [[TMP0:%.*]] = insertelement <4 x i16> undef, i16 %a, i64 0
// CHECK: [[TMP1:%.*]] = insertelement <4 x i16> undef, i16 %b, i64 0
// CHECK: [[VQDMULHH_S16_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqdmulh.v4i16(<4 x i16> [[TMP0]], <4 x i16> [[TMP1]]) #4
@@ -9719,14 +8804,14 @@ int16_t test_vqdmulhh_s16(int16_t a, int16_t b) {
return vqdmulhh_s16(a, b);
}
-// CHECK-LABEL: define i32 @test_vqdmulhs_s32(i32 %a, i32 %b) #0 {
+// CHECK-LABEL: @test_vqdmulhs_s32(
// CHECK: [[VQDMULHS_S32_I:%.*]] = call i32 @llvm.aarch64.neon.sqdmulh.i32(i32 %a, i32 %b) #4
// CHECK: ret i32 [[VQDMULHS_S32_I]]
int32_t test_vqdmulhs_s32(int32_t a, int32_t b) {
return vqdmulhs_s32(a, b);
}
-// CHECK-LABEL: define i16 @test_vqrdmulhh_s16(i16 %a, i16 %b) #0 {
+// CHECK-LABEL: @test_vqrdmulhh_s16(
// CHECK: [[TMP0:%.*]] = insertelement <4 x i16> undef, i16 %a, i64 0
// CHECK: [[TMP1:%.*]] = insertelement <4 x i16> undef, i16 %b, i64 0
// CHECK: [[VQRDMULHH_S16_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqrdmulh.v4i16(<4 x i16> [[TMP0]], <4 x i16> [[TMP1]]) #4
@@ -9736,155 +8821,151 @@ int16_t test_vqrdmulhh_s16(int16_t a, int16_t b) {
return vqrdmulhh_s16(a, b);
}
-// CHECK-LABEL: define i32 @test_vqrdmulhs_s32(i32 %a, i32 %b) #0 {
+// CHECK-LABEL: @test_vqrdmulhs_s32(
// CHECK: [[VQRDMULHS_S32_I:%.*]] = call i32 @llvm.aarch64.neon.sqrdmulh.i32(i32 %a, i32 %b) #4
// CHECK: ret i32 [[VQRDMULHS_S32_I]]
int32_t test_vqrdmulhs_s32(int32_t a, int32_t b) {
return vqrdmulhs_s32(a, b);
}
-// CHECK-LABEL: define float @test_vmulxs_f32(float %a, float %b) #0 {
+// CHECK-LABEL: @test_vmulxs_f32(
// CHECK: [[VMULXS_F32_I:%.*]] = call float @llvm.aarch64.neon.fmulx.f32(float %a, float %b) #4
// CHECK: ret float [[VMULXS_F32_I]]
float32_t test_vmulxs_f32(float32_t a, float32_t b) {
return vmulxs_f32(a, b);
}
-// CHECK-LABEL: define double @test_vmulxd_f64(double %a, double %b) #0 {
+// CHECK-LABEL: @test_vmulxd_f64(
// CHECK: [[VMULXD_F64_I:%.*]] = call double @llvm.aarch64.neon.fmulx.f64(double %a, double %b) #4
// CHECK: ret double [[VMULXD_F64_I]]
float64_t test_vmulxd_f64(float64_t a, float64_t b) {
return vmulxd_f64(a, b);
}
-// CHECK-LABEL: define <1 x double> @test_vmulx_f64(<1 x double> %a, <1 x double> %b) #0 {
+// CHECK-LABEL: @test_vmulx_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x double> %b to <8 x i8>
-// CHECK: [[VMULX_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x double>
-// CHECK: [[VMULX1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x double>
-// CHECK: [[VMULX2_I:%.*]] = call <1 x double> @llvm.aarch64.neon.fmulx.v1f64(<1 x double> [[VMULX_I]], <1 x double> [[VMULX1_I]]) #4
+// CHECK: [[VMULX2_I:%.*]] = call <1 x double> @llvm.aarch64.neon.fmulx.v1f64(<1 x double> %a, <1 x double> %b) #4
// CHECK: ret <1 x double> [[VMULX2_I]]
float64x1_t test_vmulx_f64(float64x1_t a, float64x1_t b) {
return vmulx_f64(a, b);
}
-// CHECK-LABEL: define float @test_vrecpss_f32(float %a, float %b) #0 {
+// CHECK-LABEL: @test_vrecpss_f32(
// CHECK: [[VRECPS_I:%.*]] = call float @llvm.aarch64.neon.frecps.f32(float %a, float %b) #4
// CHECK: ret float [[VRECPS_I]]
float32_t test_vrecpss_f32(float32_t a, float32_t b) {
return vrecpss_f32(a, b);
}
-// CHECK-LABEL: define double @test_vrecpsd_f64(double %a, double %b) #0 {
+// CHECK-LABEL: @test_vrecpsd_f64(
// CHECK: [[VRECPS_I:%.*]] = call double @llvm.aarch64.neon.frecps.f64(double %a, double %b) #4
// CHECK: ret double [[VRECPS_I]]
float64_t test_vrecpsd_f64(float64_t a, float64_t b) {
return vrecpsd_f64(a, b);
}
-// CHECK-LABEL: define float @test_vrsqrtss_f32(float %a, float %b) #0 {
+// CHECK-LABEL: @test_vrsqrtss_f32(
// CHECK: [[VRSQRTSS_F32_I:%.*]] = call float @llvm.aarch64.neon.frsqrts.f32(float %a, float %b) #4
// CHECK: ret float [[VRSQRTSS_F32_I]]
float32_t test_vrsqrtss_f32(float32_t a, float32_t b) {
return vrsqrtss_f32(a, b);
}
-// CHECK-LABEL: define double @test_vrsqrtsd_f64(double %a, double %b) #0 {
+// CHECK-LABEL: @test_vrsqrtsd_f64(
// CHECK: [[VRSQRTSD_F64_I:%.*]] = call double @llvm.aarch64.neon.frsqrts.f64(double %a, double %b) #4
// CHECK: ret double [[VRSQRTSD_F64_I]]
float64_t test_vrsqrtsd_f64(float64_t a, float64_t b) {
return vrsqrtsd_f64(a, b);
}
-// CHECK-LABEL: define float @test_vcvts_f32_s32(i32 %a) #0 {
+// CHECK-LABEL: @test_vcvts_f32_s32(
// CHECK: [[TMP0:%.*]] = sitofp i32 %a to float
// CHECK: ret float [[TMP0]]
float32_t test_vcvts_f32_s32(int32_t a) {
return vcvts_f32_s32(a);
}
-// CHECK-LABEL: define double @test_vcvtd_f64_s64(i64 %a) #0 {
+// CHECK-LABEL: @test_vcvtd_f64_s64(
// CHECK: [[TMP0:%.*]] = sitofp i64 %a to double
// CHECK: ret double [[TMP0]]
float64_t test_vcvtd_f64_s64(int64_t a) {
return vcvtd_f64_s64(a);
}
-// CHECK-LABEL: define float @test_vcvts_f32_u32(i32 %a) #0 {
+// CHECK-LABEL: @test_vcvts_f32_u32(
// CHECK: [[TMP0:%.*]] = uitofp i32 %a to float
// CHECK: ret float [[TMP0]]
float32_t test_vcvts_f32_u32(uint32_t a) {
return vcvts_f32_u32(a);
}
-// CHECK-LABEL: define double @test_vcvtd_f64_u64(i64 %a) #0 {
+// CHECK-LABEL: @test_vcvtd_f64_u64(
// CHECK: [[TMP0:%.*]] = uitofp i64 %a to double
// CHECK: ret double [[TMP0]]
float64_t test_vcvtd_f64_u64(uint64_t a) {
return vcvtd_f64_u64(a);
}
-// CHECK-LABEL: define float @test_vrecpes_f32(float %a) #0 {
+// CHECK-LABEL: @test_vrecpes_f32(
// CHECK: [[VRECPES_F32_I:%.*]] = call float @llvm.aarch64.neon.frecpe.f32(float %a) #4
// CHECK: ret float [[VRECPES_F32_I]]
float32_t test_vrecpes_f32(float32_t a) {
return vrecpes_f32(a);
}
-
-// CHECK-LABEL: define double @test_vrecped_f64(double %a) #0 {
+
+// CHECK-LABEL: @test_vrecped_f64(
// CHECK: [[VRECPED_F64_I:%.*]] = call double @llvm.aarch64.neon.frecpe.f64(double %a) #4
// CHECK: ret double [[VRECPED_F64_I]]
float64_t test_vrecped_f64(float64_t a) {
return vrecped_f64(a);
}
-
-// CHECK-LABEL: define float @test_vrecpxs_f32(float %a) #0 {
+
+// CHECK-LABEL: @test_vrecpxs_f32(
// CHECK: [[VRECPXS_F32_I:%.*]] = call float @llvm.aarch64.neon.frecpx.f32(float %a) #4
// CHECK: ret float [[VRECPXS_F32_I]]
float32_t test_vrecpxs_f32(float32_t a) {
return vrecpxs_f32(a);
- }
-
-// CHECK-LABEL: define double @test_vrecpxd_f64(double %a) #0 {
+}
+
+// CHECK-LABEL: @test_vrecpxd_f64(
// CHECK: [[VRECPXD_F64_I:%.*]] = call double @llvm.aarch64.neon.frecpx.f64(double %a) #4
// CHECK: ret double [[VRECPXD_F64_I]]
float64_t test_vrecpxd_f64(float64_t a) {
return vrecpxd_f64(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vrsqrte_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vrsqrte_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[VRSQRTE_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VRSQRTE_V1_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.ursqrte.v2i32(<2 x i32> [[VRSQRTE_V_I]]) #4
+// CHECK: [[VRSQRTE_V1_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.ursqrte.v2i32(<2 x i32> %a) #4
// CHECK: ret <2 x i32> [[VRSQRTE_V1_I]]
uint32x2_t test_vrsqrte_u32(uint32x2_t a) {
return vrsqrte_u32(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vrsqrteq_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vrsqrteq_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
-// CHECK: [[VRSQRTEQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VRSQRTEQ_V1_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.ursqrte.v4i32(<4 x i32> [[VRSQRTEQ_V_I]]) #4
+// CHECK: [[VRSQRTEQ_V1_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.ursqrte.v4i32(<4 x i32> %a) #4
// CHECK: ret <4 x i32> [[VRSQRTEQ_V1_I]]
uint32x4_t test_vrsqrteq_u32(uint32x4_t a) {
return vrsqrteq_u32(a);
}
-// CHECK-LABEL: define float @test_vrsqrtes_f32(float %a) #0 {
+// CHECK-LABEL: @test_vrsqrtes_f32(
// CHECK: [[VRSQRTES_F32_I:%.*]] = call float @llvm.aarch64.neon.frsqrte.f32(float %a) #4
// CHECK: ret float [[VRSQRTES_F32_I]]
float32_t test_vrsqrtes_f32(float32_t a) {
return vrsqrtes_f32(a);
}
-// CHECK-LABEL: define double @test_vrsqrted_f64(double %a) #0 {
+// CHECK-LABEL: @test_vrsqrted_f64(
// CHECK: [[VRSQRTED_F64_I:%.*]] = call double @llvm.aarch64.neon.frsqrte.f64(double %a) #4
// CHECK: ret double [[VRSQRTED_F64_I]]
float64_t test_vrsqrted_f64(float64_t a) {
return vrsqrted_f64(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vld1q_u8(i8* %a) #0 {
+// CHECK-LABEL: @test_vld1q_u8(
// CHECK: [[TMP0:%.*]] = bitcast i8* %a to <16 x i8>*
// CHECK: [[TMP1:%.*]] = load <16 x i8>, <16 x i8>* [[TMP0]]
// CHECK: ret <16 x i8> [[TMP1]]
@@ -9892,7 +8973,7 @@ uint8x16_t test_vld1q_u8(uint8_t const *a) {
return vld1q_u8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vld1q_u16(i16* %a) #0 {
+// CHECK-LABEL: @test_vld1q_u16(
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <8 x i16>*
// CHECK: [[TMP2:%.*]] = load <8 x i16>, <8 x i16>* [[TMP1]]
@@ -9901,7 +8982,7 @@ uint16x8_t test_vld1q_u16(uint16_t const *a) {
return vld1q_u16(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vld1q_u32(i32* %a) #0 {
+// CHECK-LABEL: @test_vld1q_u32(
// CHECK: [[TMP0:%.*]] = bitcast i32* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <4 x i32>*
// CHECK: [[TMP2:%.*]] = load <4 x i32>, <4 x i32>* [[TMP1]]
@@ -9910,7 +8991,7 @@ uint32x4_t test_vld1q_u32(uint32_t const *a) {
return vld1q_u32(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vld1q_u64(i64* %a) #0 {
+// CHECK-LABEL: @test_vld1q_u64(
// CHECK: [[TMP0:%.*]] = bitcast i64* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <2 x i64>*
// CHECK: [[TMP2:%.*]] = load <2 x i64>, <2 x i64>* [[TMP1]]
@@ -9919,7 +9000,7 @@ uint64x2_t test_vld1q_u64(uint64_t const *a) {
return vld1q_u64(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vld1q_s8(i8* %a) #0 {
+// CHECK-LABEL: @test_vld1q_s8(
// CHECK: [[TMP0:%.*]] = bitcast i8* %a to <16 x i8>*
// CHECK: [[TMP1:%.*]] = load <16 x i8>, <16 x i8>* [[TMP0]]
// CHECK: ret <16 x i8> [[TMP1]]
@@ -9927,7 +9008,7 @@ int8x16_t test_vld1q_s8(int8_t const *a) {
return vld1q_s8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vld1q_s16(i16* %a) #0 {
+// CHECK-LABEL: @test_vld1q_s16(
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <8 x i16>*
// CHECK: [[TMP2:%.*]] = load <8 x i16>, <8 x i16>* [[TMP1]]
@@ -9936,7 +9017,7 @@ int16x8_t test_vld1q_s16(int16_t const *a) {
return vld1q_s16(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vld1q_s32(i32* %a) #0 {
+// CHECK-LABEL: @test_vld1q_s32(
// CHECK: [[TMP0:%.*]] = bitcast i32* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <4 x i32>*
// CHECK: [[TMP2:%.*]] = load <4 x i32>, <4 x i32>* [[TMP1]]
@@ -9945,7 +9026,7 @@ int32x4_t test_vld1q_s32(int32_t const *a) {
return vld1q_s32(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vld1q_s64(i64* %a) #0 {
+// CHECK-LABEL: @test_vld1q_s64(
// CHECK: [[TMP0:%.*]] = bitcast i64* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <2 x i64>*
// CHECK: [[TMP2:%.*]] = load <2 x i64>, <2 x i64>* [[TMP1]]
@@ -9954,7 +9035,7 @@ int64x2_t test_vld1q_s64(int64_t const *a) {
return vld1q_s64(a);
}
-// CHECK-LABEL: define <8 x half> @test_vld1q_f16(half* %a) #0 {
+// CHECK-LABEL: @test_vld1q_f16(
// CHECK: [[TMP0:%.*]] = bitcast half* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <8 x i16>*
// CHECK: [[TMP2:%.*]] = load <8 x i16>, <8 x i16>* [[TMP1]]
@@ -9964,7 +9045,7 @@ float16x8_t test_vld1q_f16(float16_t const *a) {
return vld1q_f16(a);
}
-// CHECK-LABEL: define <4 x float> @test_vld1q_f32(float* %a) #0 {
+// CHECK-LABEL: @test_vld1q_f32(
// CHECK: [[TMP0:%.*]] = bitcast float* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <4 x float>*
// CHECK: [[TMP2:%.*]] = load <4 x float>, <4 x float>* [[TMP1]]
@@ -9973,7 +9054,7 @@ float32x4_t test_vld1q_f32(float32_t const *a) {
return vld1q_f32(a);
}
-// CHECK-LABEL: define <2 x double> @test_vld1q_f64(double* %a) #0 {
+// CHECK-LABEL: @test_vld1q_f64(
// CHECK: [[TMP0:%.*]] = bitcast double* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <2 x double>*
// CHECK: [[TMP2:%.*]] = load <2 x double>, <2 x double>* [[TMP1]]
@@ -9982,7 +9063,7 @@ float64x2_t test_vld1q_f64(float64_t const *a) {
return vld1q_f64(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vld1q_p8(i8* %a) #0 {
+// CHECK-LABEL: @test_vld1q_p8(
// CHECK: [[TMP0:%.*]] = bitcast i8* %a to <16 x i8>*
// CHECK: [[TMP1:%.*]] = load <16 x i8>, <16 x i8>* [[TMP0]]
// CHECK: ret <16 x i8> [[TMP1]]
@@ -9990,7 +9071,7 @@ poly8x16_t test_vld1q_p8(poly8_t const *a) {
return vld1q_p8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vld1q_p16(i16* %a) #0 {
+// CHECK-LABEL: @test_vld1q_p16(
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <8 x i16>*
// CHECK: [[TMP2:%.*]] = load <8 x i16>, <8 x i16>* [[TMP1]]
@@ -9999,7 +9080,7 @@ poly16x8_t test_vld1q_p16(poly16_t const *a) {
return vld1q_p16(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vld1_u8(i8* %a) #0 {
+// CHECK-LABEL: @test_vld1_u8(
// CHECK: [[TMP0:%.*]] = bitcast i8* %a to <8 x i8>*
// CHECK: [[TMP1:%.*]] = load <8 x i8>, <8 x i8>* [[TMP0]]
// CHECK: ret <8 x i8> [[TMP1]]
@@ -10007,7 +9088,7 @@ uint8x8_t test_vld1_u8(uint8_t const *a) {
return vld1_u8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vld1_u16(i16* %a) #0 {
+// CHECK-LABEL: @test_vld1_u16(
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <4 x i16>*
// CHECK: [[TMP2:%.*]] = load <4 x i16>, <4 x i16>* [[TMP1]]
@@ -10016,7 +9097,7 @@ uint16x4_t test_vld1_u16(uint16_t const *a) {
return vld1_u16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vld1_u32(i32* %a) #0 {
+// CHECK-LABEL: @test_vld1_u32(
// CHECK: [[TMP0:%.*]] = bitcast i32* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <2 x i32>*
// CHECK: [[TMP2:%.*]] = load <2 x i32>, <2 x i32>* [[TMP1]]
@@ -10025,7 +9106,7 @@ uint32x2_t test_vld1_u32(uint32_t const *a) {
return vld1_u32(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vld1_u64(i64* %a) #0 {
+// CHECK-LABEL: @test_vld1_u64(
// CHECK: [[TMP0:%.*]] = bitcast i64* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <1 x i64>*
// CHECK: [[TMP2:%.*]] = load <1 x i64>, <1 x i64>* [[TMP1]]
@@ -10034,7 +9115,7 @@ uint64x1_t test_vld1_u64(uint64_t const *a) {
return vld1_u64(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vld1_s8(i8* %a) #0 {
+// CHECK-LABEL: @test_vld1_s8(
// CHECK: [[TMP0:%.*]] = bitcast i8* %a to <8 x i8>*
// CHECK: [[TMP1:%.*]] = load <8 x i8>, <8 x i8>* [[TMP0]]
// CHECK: ret <8 x i8> [[TMP1]]
@@ -10042,7 +9123,7 @@ int8x8_t test_vld1_s8(int8_t const *a) {
return vld1_s8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vld1_s16(i16* %a) #0 {
+// CHECK-LABEL: @test_vld1_s16(
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <4 x i16>*
// CHECK: [[TMP2:%.*]] = load <4 x i16>, <4 x i16>* [[TMP1]]
@@ -10051,7 +9132,7 @@ int16x4_t test_vld1_s16(int16_t const *a) {
return vld1_s16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vld1_s32(i32* %a) #0 {
+// CHECK-LABEL: @test_vld1_s32(
// CHECK: [[TMP0:%.*]] = bitcast i32* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <2 x i32>*
// CHECK: [[TMP2:%.*]] = load <2 x i32>, <2 x i32>* [[TMP1]]
@@ -10060,7 +9141,7 @@ int32x2_t test_vld1_s32(int32_t const *a) {
return vld1_s32(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vld1_s64(i64* %a) #0 {
+// CHECK-LABEL: @test_vld1_s64(
// CHECK: [[TMP0:%.*]] = bitcast i64* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <1 x i64>*
// CHECK: [[TMP2:%.*]] = load <1 x i64>, <1 x i64>* [[TMP1]]
@@ -10069,7 +9150,7 @@ int64x1_t test_vld1_s64(int64_t const *a) {
return vld1_s64(a);
}
-// CHECK-LABEL: define <4 x half> @test_vld1_f16(half* %a) #0 {
+// CHECK-LABEL: @test_vld1_f16(
// CHECK: [[TMP0:%.*]] = bitcast half* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <4 x i16>*
// CHECK: [[TMP2:%.*]] = load <4 x i16>, <4 x i16>* [[TMP1]]
@@ -10079,7 +9160,7 @@ float16x4_t test_vld1_f16(float16_t const *a) {
return vld1_f16(a);
}
-// CHECK-LABEL: define <2 x float> @test_vld1_f32(float* %a) #0 {
+// CHECK-LABEL: @test_vld1_f32(
// CHECK: [[TMP0:%.*]] = bitcast float* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <2 x float>*
// CHECK: [[TMP2:%.*]] = load <2 x float>, <2 x float>* [[TMP1]]
@@ -10088,7 +9169,7 @@ float32x2_t test_vld1_f32(float32_t const *a) {
return vld1_f32(a);
}
-// CHECK-LABEL: define <1 x double> @test_vld1_f64(double* %a) #0 {
+// CHECK-LABEL: @test_vld1_f64(
// CHECK: [[TMP0:%.*]] = bitcast double* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <1 x double>*
// CHECK: [[TMP2:%.*]] = load <1 x double>, <1 x double>* [[TMP1]]
@@ -10097,7 +9178,7 @@ float64x1_t test_vld1_f64(float64_t const *a) {
return vld1_f64(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vld1_p8(i8* %a) #0 {
+// CHECK-LABEL: @test_vld1_p8(
// CHECK: [[TMP0:%.*]] = bitcast i8* %a to <8 x i8>*
// CHECK: [[TMP1:%.*]] = load <8 x i8>, <8 x i8>* [[TMP0]]
// CHECK: ret <8 x i8> [[TMP1]]
@@ -10105,7 +9186,7 @@ poly8x8_t test_vld1_p8(poly8_t const *a) {
return vld1_p8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vld1_p16(i16* %a) #0 {
+// CHECK-LABEL: @test_vld1_p16(
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <4 x i16>*
// CHECK: [[TMP2:%.*]] = load <4 x i16>, <4 x i16>* [[TMP1]]
@@ -10114,7 +9195,7 @@ poly16x4_t test_vld1_p16(poly16_t const *a) {
return vld1_p16(a);
}
-// CHECK-LABEL: define %struct.uint8x16x2_t @test_vld2q_u8(i8* %a) #0 {
+// CHECK-LABEL: @test_vld2q_u8(
// 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*
@@ -10131,7 +9212,7 @@ uint8x16x2_t test_vld2q_u8(uint8_t const *a) {
return vld2q_u8(a);
}
-// CHECK-LABEL: define %struct.uint16x8x2_t @test_vld2q_u16(i16* %a) #0 {
+// CHECK-LABEL: @test_vld2q_u16(
// 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*
@@ -10149,7 +9230,7 @@ uint16x8x2_t test_vld2q_u16(uint16_t const *a) {
return vld2q_u16(a);
}
-// CHECK-LABEL: define %struct.uint32x4x2_t @test_vld2q_u32(i32* %a) #0 {
+// CHECK-LABEL: @test_vld2q_u32(
// 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*
@@ -10167,7 +9248,7 @@ uint32x4x2_t test_vld2q_u32(uint32_t const *a) {
return vld2q_u32(a);
}
-// CHECK-LABEL: define %struct.uint64x2x2_t @test_vld2q_u64(i64* %a) #0 {
+// CHECK-LABEL: @test_vld2q_u64(
// 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*
@@ -10185,7 +9266,7 @@ uint64x2x2_t test_vld2q_u64(uint64_t const *a) {
return vld2q_u64(a);
}
-// CHECK-LABEL: define %struct.int8x16x2_t @test_vld2q_s8(i8* %a) #0 {
+// CHECK-LABEL: @test_vld2q_s8(
// 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*
@@ -10202,7 +9283,7 @@ int8x16x2_t test_vld2q_s8(int8_t const *a) {
return vld2q_s8(a);
}
-// CHECK-LABEL: define %struct.int16x8x2_t @test_vld2q_s16(i16* %a) #0 {
+// CHECK-LABEL: @test_vld2q_s16(
// 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*
@@ -10220,7 +9301,7 @@ int16x8x2_t test_vld2q_s16(int16_t const *a) {
return vld2q_s16(a);
}
-// CHECK-LABEL: define %struct.int32x4x2_t @test_vld2q_s32(i32* %a) #0 {
+// CHECK-LABEL: @test_vld2q_s32(
// 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*
@@ -10238,7 +9319,7 @@ int32x4x2_t test_vld2q_s32(int32_t const *a) {
return vld2q_s32(a);
}
-// CHECK-LABEL: define %struct.int64x2x2_t @test_vld2q_s64(i64* %a) #0 {
+// CHECK-LABEL: @test_vld2q_s64(
// 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*
@@ -10256,7 +9337,7 @@ int64x2x2_t test_vld2q_s64(int64_t const *a) {
return vld2q_s64(a);
}
-// CHECK-LABEL: define %struct.float16x8x2_t @test_vld2q_f16(half* %a) #0 {
+// CHECK-LABEL: @test_vld2q_f16(
// 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*
@@ -10274,7 +9355,7 @@ float16x8x2_t test_vld2q_f16(float16_t const *a) {
return vld2q_f16(a);
}
-// CHECK-LABEL: define %struct.float32x4x2_t @test_vld2q_f32(float* %a) #0 {
+// CHECK-LABEL: @test_vld2q_f32(
// 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*
@@ -10292,7 +9373,7 @@ float32x4x2_t test_vld2q_f32(float32_t const *a) {
return vld2q_f32(a);
}
-// CHECK-LABEL: define %struct.float64x2x2_t @test_vld2q_f64(double* %a) #0 {
+// CHECK-LABEL: @test_vld2q_f64(
// CHECK: [[RETVAL:%.*]] = alloca %struct.float64x2x2_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.float64x2x2_t, align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x2x2_t* [[__RET]] to i8*
@@ -10310,7 +9391,7 @@ float64x2x2_t test_vld2q_f64(float64_t const *a) {
return vld2q_f64(a);
}
-// CHECK-LABEL: define %struct.poly8x16x2_t @test_vld2q_p8(i8* %a) #0 {
+// CHECK-LABEL: @test_vld2q_p8(
// 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*
@@ -10327,7 +9408,7 @@ poly8x16x2_t test_vld2q_p8(poly8_t const *a) {
return vld2q_p8(a);
}
-// CHECK-LABEL: define %struct.poly16x8x2_t @test_vld2q_p16(i16* %a) #0 {
+// CHECK-LABEL: @test_vld2q_p16(
// 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*
@@ -10345,7 +9426,7 @@ poly16x8x2_t test_vld2q_p16(poly16_t const *a) {
return vld2q_p16(a);
}
-// CHECK-LABEL: define %struct.uint8x8x2_t @test_vld2_u8(i8* %a) #0 {
+// CHECK-LABEL: @test_vld2_u8(
// 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*
@@ -10362,7 +9443,7 @@ uint8x8x2_t test_vld2_u8(uint8_t const *a) {
return vld2_u8(a);
}
-// CHECK-LABEL: define %struct.uint16x4x2_t @test_vld2_u16(i16* %a) #0 {
+// CHECK-LABEL: @test_vld2_u16(
// 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*
@@ -10380,7 +9461,7 @@ uint16x4x2_t test_vld2_u16(uint16_t const *a) {
return vld2_u16(a);
}
-// CHECK-LABEL: define %struct.uint32x2x2_t @test_vld2_u32(i32* %a) #0 {
+// CHECK-LABEL: @test_vld2_u32(
// 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*
@@ -10398,7 +9479,7 @@ uint32x2x2_t test_vld2_u32(uint32_t const *a) {
return vld2_u32(a);
}
-// CHECK-LABEL: define %struct.uint64x1x2_t @test_vld2_u64(i64* %a) #0 {
+// CHECK-LABEL: @test_vld2_u64(
// 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*
@@ -10416,7 +9497,7 @@ uint64x1x2_t test_vld2_u64(uint64_t const *a) {
return vld2_u64(a);
}
-// CHECK-LABEL: define %struct.int8x8x2_t @test_vld2_s8(i8* %a) #0 {
+// CHECK-LABEL: @test_vld2_s8(
// 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*
@@ -10433,7 +9514,7 @@ int8x8x2_t test_vld2_s8(int8_t const *a) {
return vld2_s8(a);
}
-// CHECK-LABEL: define %struct.int16x4x2_t @test_vld2_s16(i16* %a) #0 {
+// CHECK-LABEL: @test_vld2_s16(
// 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*
@@ -10451,7 +9532,7 @@ int16x4x2_t test_vld2_s16(int16_t const *a) {
return vld2_s16(a);
}
-// CHECK-LABEL: define %struct.int32x2x2_t @test_vld2_s32(i32* %a) #0 {
+// CHECK-LABEL: @test_vld2_s32(
// 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*
@@ -10469,7 +9550,7 @@ int32x2x2_t test_vld2_s32(int32_t const *a) {
return vld2_s32(a);
}
-// CHECK-LABEL: define %struct.int64x1x2_t @test_vld2_s64(i64* %a) #0 {
+// CHECK-LABEL: @test_vld2_s64(
// 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*
@@ -10487,7 +9568,7 @@ int64x1x2_t test_vld2_s64(int64_t const *a) {
return vld2_s64(a);
}
-// CHECK-LABEL: define %struct.float16x4x2_t @test_vld2_f16(half* %a) #0 {
+// CHECK-LABEL: @test_vld2_f16(
// 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*
@@ -10505,7 +9586,7 @@ float16x4x2_t test_vld2_f16(float16_t const *a) {
return vld2_f16(a);
}
-// CHECK-LABEL: define %struct.float32x2x2_t @test_vld2_f32(float* %a) #0 {
+// CHECK-LABEL: @test_vld2_f32(
// 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*
@@ -10523,7 +9604,7 @@ float32x2x2_t test_vld2_f32(float32_t const *a) {
return vld2_f32(a);
}
-// CHECK-LABEL: define %struct.float64x1x2_t @test_vld2_f64(double* %a) #0 {
+// CHECK-LABEL: @test_vld2_f64(
// CHECK: [[RETVAL:%.*]] = alloca %struct.float64x1x2_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.float64x1x2_t, align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x1x2_t* [[__RET]] to i8*
@@ -10541,7 +9622,7 @@ float64x1x2_t test_vld2_f64(float64_t const *a) {
return vld2_f64(a);
}
-// CHECK-LABEL: define %struct.poly8x8x2_t @test_vld2_p8(i8* %a) #0 {
+// CHECK-LABEL: @test_vld2_p8(
// 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*
@@ -10558,7 +9639,7 @@ poly8x8x2_t test_vld2_p8(poly8_t const *a) {
return vld2_p8(a);
}
-// CHECK-LABEL: define %struct.poly16x4x2_t @test_vld2_p16(i16* %a) #0 {
+// CHECK-LABEL: @test_vld2_p16(
// 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*
@@ -10576,7 +9657,7 @@ poly16x4x2_t test_vld2_p16(poly16_t const *a) {
return vld2_p16(a);
}
-// CHECK-LABEL: define %struct.uint8x16x3_t @test_vld3q_u8(i8* %a) #0 {
+// CHECK-LABEL: @test_vld3q_u8(
// 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*
@@ -10593,7 +9674,7 @@ uint8x16x3_t test_vld3q_u8(uint8_t const *a) {
return vld3q_u8(a);
}
-// CHECK-LABEL: define %struct.uint16x8x3_t @test_vld3q_u16(i16* %a) #0 {
+// CHECK-LABEL: @test_vld3q_u16(
// 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*
@@ -10611,7 +9692,7 @@ uint16x8x3_t test_vld3q_u16(uint16_t const *a) {
return vld3q_u16(a);
}
-// CHECK-LABEL: define %struct.uint32x4x3_t @test_vld3q_u32(i32* %a) #0 {
+// CHECK-LABEL: @test_vld3q_u32(
// 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*
@@ -10629,7 +9710,7 @@ uint32x4x3_t test_vld3q_u32(uint32_t const *a) {
return vld3q_u32(a);
}
-// CHECK-LABEL: define %struct.uint64x2x3_t @test_vld3q_u64(i64* %a) #0 {
+// CHECK-LABEL: @test_vld3q_u64(
// 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*
@@ -10647,7 +9728,7 @@ uint64x2x3_t test_vld3q_u64(uint64_t const *a) {
return vld3q_u64(a);
}
-// CHECK-LABEL: define %struct.int8x16x3_t @test_vld3q_s8(i8* %a) #0 {
+// CHECK-LABEL: @test_vld3q_s8(
// 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*
@@ -10664,7 +9745,7 @@ int8x16x3_t test_vld3q_s8(int8_t const *a) {
return vld3q_s8(a);
}
-// CHECK-LABEL: define %struct.int16x8x3_t @test_vld3q_s16(i16* %a) #0 {
+// CHECK-LABEL: @test_vld3q_s16(
// 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*
@@ -10682,7 +9763,7 @@ int16x8x3_t test_vld3q_s16(int16_t const *a) {
return vld3q_s16(a);
}
-// CHECK-LABEL: define %struct.int32x4x3_t @test_vld3q_s32(i32* %a) #0 {
+// CHECK-LABEL: @test_vld3q_s32(
// 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*
@@ -10700,7 +9781,7 @@ int32x4x3_t test_vld3q_s32(int32_t const *a) {
return vld3q_s32(a);
}
-// CHECK-LABEL: define %struct.int64x2x3_t @test_vld3q_s64(i64* %a) #0 {
+// CHECK-LABEL: @test_vld3q_s64(
// 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*
@@ -10718,7 +9799,7 @@ int64x2x3_t test_vld3q_s64(int64_t const *a) {
return vld3q_s64(a);
}
-// CHECK-LABEL: define %struct.float16x8x3_t @test_vld3q_f16(half* %a) #0 {
+// CHECK-LABEL: @test_vld3q_f16(
// 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*
@@ -10736,7 +9817,7 @@ float16x8x3_t test_vld3q_f16(float16_t const *a) {
return vld3q_f16(a);
}
-// CHECK-LABEL: define %struct.float32x4x3_t @test_vld3q_f32(float* %a) #0 {
+// CHECK-LABEL: @test_vld3q_f32(
// 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*
@@ -10754,7 +9835,7 @@ float32x4x3_t test_vld3q_f32(float32_t const *a) {
return vld3q_f32(a);
}
-// CHECK-LABEL: define %struct.float64x2x3_t @test_vld3q_f64(double* %a) #0 {
+// CHECK-LABEL: @test_vld3q_f64(
// CHECK: [[RETVAL:%.*]] = alloca %struct.float64x2x3_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.float64x2x3_t, align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x2x3_t* [[__RET]] to i8*
@@ -10772,7 +9853,7 @@ float64x2x3_t test_vld3q_f64(float64_t const *a) {
return vld3q_f64(a);
}
-// CHECK-LABEL: define %struct.poly8x16x3_t @test_vld3q_p8(i8* %a) #0 {
+// CHECK-LABEL: @test_vld3q_p8(
// 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*
@@ -10789,7 +9870,7 @@ poly8x16x3_t test_vld3q_p8(poly8_t const *a) {
return vld3q_p8(a);
}
-// CHECK-LABEL: define %struct.poly16x8x3_t @test_vld3q_p16(i16* %a) #0 {
+// CHECK-LABEL: @test_vld3q_p16(
// 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*
@@ -10807,7 +9888,7 @@ poly16x8x3_t test_vld3q_p16(poly16_t const *a) {
return vld3q_p16(a);
}
-// CHECK-LABEL: define %struct.uint8x8x3_t @test_vld3_u8(i8* %a) #0 {
+// CHECK-LABEL: @test_vld3_u8(
// 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*
@@ -10824,7 +9905,7 @@ uint8x8x3_t test_vld3_u8(uint8_t const *a) {
return vld3_u8(a);
}
-// CHECK-LABEL: define %struct.uint16x4x3_t @test_vld3_u16(i16* %a) #0 {
+// CHECK-LABEL: @test_vld3_u16(
// 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*
@@ -10842,7 +9923,7 @@ uint16x4x3_t test_vld3_u16(uint16_t const *a) {
return vld3_u16(a);
}
-// CHECK-LABEL: define %struct.uint32x2x3_t @test_vld3_u32(i32* %a) #0 {
+// CHECK-LABEL: @test_vld3_u32(
// 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*
@@ -10860,7 +9941,7 @@ uint32x2x3_t test_vld3_u32(uint32_t const *a) {
return vld3_u32(a);
}
-// CHECK-LABEL: define %struct.uint64x1x3_t @test_vld3_u64(i64* %a) #0 {
+// CHECK-LABEL: @test_vld3_u64(
// 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*
@@ -10878,7 +9959,7 @@ uint64x1x3_t test_vld3_u64(uint64_t const *a) {
return vld3_u64(a);
}
-// CHECK-LABEL: define %struct.int8x8x3_t @test_vld3_s8(i8* %a) #0 {
+// CHECK-LABEL: @test_vld3_s8(
// 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*
@@ -10895,7 +9976,7 @@ int8x8x3_t test_vld3_s8(int8_t const *a) {
return vld3_s8(a);
}
-// CHECK-LABEL: define %struct.int16x4x3_t @test_vld3_s16(i16* %a) #0 {
+// CHECK-LABEL: @test_vld3_s16(
// 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*
@@ -10913,7 +9994,7 @@ int16x4x3_t test_vld3_s16(int16_t const *a) {
return vld3_s16(a);
}
-// CHECK-LABEL: define %struct.int32x2x3_t @test_vld3_s32(i32* %a) #0 {
+// CHECK-LABEL: @test_vld3_s32(
// 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*
@@ -10931,7 +10012,7 @@ int32x2x3_t test_vld3_s32(int32_t const *a) {
return vld3_s32(a);
}
-// CHECK-LABEL: define %struct.int64x1x3_t @test_vld3_s64(i64* %a) #0 {
+// CHECK-LABEL: @test_vld3_s64(
// 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*
@@ -10949,7 +10030,7 @@ int64x1x3_t test_vld3_s64(int64_t const *a) {
return vld3_s64(a);
}
-// CHECK-LABEL: define %struct.float16x4x3_t @test_vld3_f16(half* %a) #0 {
+// CHECK-LABEL: @test_vld3_f16(
// 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*
@@ -10967,7 +10048,7 @@ float16x4x3_t test_vld3_f16(float16_t const *a) {
return vld3_f16(a);
}
-// CHECK-LABEL: define %struct.float32x2x3_t @test_vld3_f32(float* %a) #0 {
+// CHECK-LABEL: @test_vld3_f32(
// 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*
@@ -10985,7 +10066,7 @@ float32x2x3_t test_vld3_f32(float32_t const *a) {
return vld3_f32(a);
}
-// CHECK-LABEL: define %struct.float64x1x3_t @test_vld3_f64(double* %a) #0 {
+// CHECK-LABEL: @test_vld3_f64(
// CHECK: [[RETVAL:%.*]] = alloca %struct.float64x1x3_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.float64x1x3_t, align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x1x3_t* [[__RET]] to i8*
@@ -11003,7 +10084,7 @@ float64x1x3_t test_vld3_f64(float64_t const *a) {
return vld3_f64(a);
}
-// CHECK-LABEL: define %struct.poly8x8x3_t @test_vld3_p8(i8* %a) #0 {
+// CHECK-LABEL: @test_vld3_p8(
// 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*
@@ -11020,7 +10101,7 @@ poly8x8x3_t test_vld3_p8(poly8_t const *a) {
return vld3_p8(a);
}
-// CHECK-LABEL: define %struct.poly16x4x3_t @test_vld3_p16(i16* %a) #0 {
+// CHECK-LABEL: @test_vld3_p16(
// 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*
@@ -11038,7 +10119,7 @@ poly16x4x3_t test_vld3_p16(poly16_t const *a) {
return vld3_p16(a);
}
-// CHECK-LABEL: define %struct.uint8x16x4_t @test_vld4q_u8(i8* %a) #0 {
+// CHECK-LABEL: @test_vld4q_u8(
// 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*
@@ -11055,7 +10136,7 @@ uint8x16x4_t test_vld4q_u8(uint8_t const *a) {
return vld4q_u8(a);
}
-// CHECK-LABEL: define %struct.uint16x8x4_t @test_vld4q_u16(i16* %a) #0 {
+// CHECK-LABEL: @test_vld4q_u16(
// 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*
@@ -11073,7 +10154,7 @@ uint16x8x4_t test_vld4q_u16(uint16_t const *a) {
return vld4q_u16(a);
}
-// CHECK-LABEL: define %struct.uint32x4x4_t @test_vld4q_u32(i32* %a) #0 {
+// CHECK-LABEL: @test_vld4q_u32(
// 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*
@@ -11091,7 +10172,7 @@ uint32x4x4_t test_vld4q_u32(uint32_t const *a) {
return vld4q_u32(a);
}
-// CHECK-LABEL: define %struct.uint64x2x4_t @test_vld4q_u64(i64* %a) #0 {
+// CHECK-LABEL: @test_vld4q_u64(
// 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*
@@ -11109,7 +10190,7 @@ uint64x2x4_t test_vld4q_u64(uint64_t const *a) {
return vld4q_u64(a);
}
-// CHECK-LABEL: define %struct.int8x16x4_t @test_vld4q_s8(i8* %a) #0 {
+// CHECK-LABEL: @test_vld4q_s8(
// 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*
@@ -11126,7 +10207,7 @@ int8x16x4_t test_vld4q_s8(int8_t const *a) {
return vld4q_s8(a);
}
-// CHECK-LABEL: define %struct.int16x8x4_t @test_vld4q_s16(i16* %a) #0 {
+// CHECK-LABEL: @test_vld4q_s16(
// 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*
@@ -11144,7 +10225,7 @@ int16x8x4_t test_vld4q_s16(int16_t const *a) {
return vld4q_s16(a);
}
-// CHECK-LABEL: define %struct.int32x4x4_t @test_vld4q_s32(i32* %a) #0 {
+// CHECK-LABEL: @test_vld4q_s32(
// 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*
@@ -11162,7 +10243,7 @@ int32x4x4_t test_vld4q_s32(int32_t const *a) {
return vld4q_s32(a);
}
-// CHECK-LABEL: define %struct.int64x2x4_t @test_vld4q_s64(i64* %a) #0 {
+// CHECK-LABEL: @test_vld4q_s64(
// 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*
@@ -11180,7 +10261,7 @@ int64x2x4_t test_vld4q_s64(int64_t const *a) {
return vld4q_s64(a);
}
-// CHECK-LABEL: define %struct.float16x8x4_t @test_vld4q_f16(half* %a) #0 {
+// CHECK-LABEL: @test_vld4q_f16(
// 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*
@@ -11198,7 +10279,7 @@ float16x8x4_t test_vld4q_f16(float16_t const *a) {
return vld4q_f16(a);
}
-// CHECK-LABEL: define %struct.float32x4x4_t @test_vld4q_f32(float* %a) #0 {
+// CHECK-LABEL: @test_vld4q_f32(
// 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*
@@ -11216,7 +10297,7 @@ float32x4x4_t test_vld4q_f32(float32_t const *a) {
return vld4q_f32(a);
}
-// CHECK-LABEL: define %struct.float64x2x4_t @test_vld4q_f64(double* %a) #0 {
+// CHECK-LABEL: @test_vld4q_f64(
// CHECK: [[RETVAL:%.*]] = alloca %struct.float64x2x4_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.float64x2x4_t, align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x2x4_t* [[__RET]] to i8*
@@ -11234,7 +10315,7 @@ float64x2x4_t test_vld4q_f64(float64_t const *a) {
return vld4q_f64(a);
}
-// CHECK-LABEL: define %struct.poly8x16x4_t @test_vld4q_p8(i8* %a) #0 {
+// CHECK-LABEL: @test_vld4q_p8(
// 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*
@@ -11251,7 +10332,7 @@ poly8x16x4_t test_vld4q_p8(poly8_t const *a) {
return vld4q_p8(a);
}
-// CHECK-LABEL: define %struct.poly16x8x4_t @test_vld4q_p16(i16* %a) #0 {
+// CHECK-LABEL: @test_vld4q_p16(
// 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*
@@ -11269,7 +10350,7 @@ poly16x8x4_t test_vld4q_p16(poly16_t const *a) {
return vld4q_p16(a);
}
-// CHECK-LABEL: define %struct.uint8x8x4_t @test_vld4_u8(i8* %a) #0 {
+// CHECK-LABEL: @test_vld4_u8(
// 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*
@@ -11286,7 +10367,7 @@ uint8x8x4_t test_vld4_u8(uint8_t const *a) {
return vld4_u8(a);
}
-// CHECK-LABEL: define %struct.uint16x4x4_t @test_vld4_u16(i16* %a) #0 {
+// CHECK-LABEL: @test_vld4_u16(
// 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*
@@ -11304,7 +10385,7 @@ uint16x4x4_t test_vld4_u16(uint16_t const *a) {
return vld4_u16(a);
}
-// CHECK-LABEL: define %struct.uint32x2x4_t @test_vld4_u32(i32* %a) #0 {
+// CHECK-LABEL: @test_vld4_u32(
// 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*
@@ -11322,7 +10403,7 @@ uint32x2x4_t test_vld4_u32(uint32_t const *a) {
return vld4_u32(a);
}
-// CHECK-LABEL: define %struct.uint64x1x4_t @test_vld4_u64(i64* %a) #0 {
+// CHECK-LABEL: @test_vld4_u64(
// 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*
@@ -11340,7 +10421,7 @@ uint64x1x4_t test_vld4_u64(uint64_t const *a) {
return vld4_u64(a);
}
-// CHECK-LABEL: define %struct.int8x8x4_t @test_vld4_s8(i8* %a) #0 {
+// CHECK-LABEL: @test_vld4_s8(
// 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*
@@ -11357,7 +10438,7 @@ int8x8x4_t test_vld4_s8(int8_t const *a) {
return vld4_s8(a);
}
-// CHECK-LABEL: define %struct.int16x4x4_t @test_vld4_s16(i16* %a) #0 {
+// CHECK-LABEL: @test_vld4_s16(
// 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*
@@ -11375,7 +10456,7 @@ int16x4x4_t test_vld4_s16(int16_t const *a) {
return vld4_s16(a);
}
-// CHECK-LABEL: define %struct.int32x2x4_t @test_vld4_s32(i32* %a) #0 {
+// CHECK-LABEL: @test_vld4_s32(
// 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*
@@ -11393,7 +10474,7 @@ int32x2x4_t test_vld4_s32(int32_t const *a) {
return vld4_s32(a);
}
-// CHECK-LABEL: define %struct.int64x1x4_t @test_vld4_s64(i64* %a) #0 {
+// CHECK-LABEL: @test_vld4_s64(
// 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*
@@ -11411,7 +10492,7 @@ int64x1x4_t test_vld4_s64(int64_t const *a) {
return vld4_s64(a);
}
-// CHECK-LABEL: define %struct.float16x4x4_t @test_vld4_f16(half* %a) #0 {
+// CHECK-LABEL: @test_vld4_f16(
// 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*
@@ -11429,7 +10510,7 @@ float16x4x4_t test_vld4_f16(float16_t const *a) {
return vld4_f16(a);
}
-// CHECK-LABEL: define %struct.float32x2x4_t @test_vld4_f32(float* %a) #0 {
+// CHECK-LABEL: @test_vld4_f32(
// 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*
@@ -11447,7 +10528,7 @@ float32x2x4_t test_vld4_f32(float32_t const *a) {
return vld4_f32(a);
}
-// CHECK-LABEL: define %struct.float64x1x4_t @test_vld4_f64(double* %a) #0 {
+// CHECK-LABEL: @test_vld4_f64(
// CHECK: [[RETVAL:%.*]] = alloca %struct.float64x1x4_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.float64x1x4_t, align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x1x4_t* [[__RET]] to i8*
@@ -11465,7 +10546,7 @@ float64x1x4_t test_vld4_f64(float64_t const *a) {
return vld4_f64(a);
}
-// CHECK-LABEL: define %struct.poly8x8x4_t @test_vld4_p8(i8* %a) #0 {
+// CHECK-LABEL: @test_vld4_p8(
// 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*
@@ -11482,7 +10563,7 @@ poly8x8x4_t test_vld4_p8(poly8_t const *a) {
return vld4_p8(a);
}
-// CHECK-LABEL: define %struct.poly16x4x4_t @test_vld4_p16(i16* %a) #0 {
+// CHECK-LABEL: @test_vld4_p16(
// 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*
@@ -11500,7 +10581,7 @@ poly16x4x4_t test_vld4_p16(poly16_t const *a) {
return vld4_p16(a);
}
-// CHECK-LABEL: define void @test_vst1q_u8(i8* %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vst1q_u8(
// CHECK: [[TMP0:%.*]] = bitcast i8* %a to <16 x i8>*
// CHECK: store <16 x i8> %b, <16 x i8>* [[TMP0]]
// CHECK: ret void
@@ -11508,7 +10589,7 @@ void test_vst1q_u8(uint8_t *a, uint8x16_t b) {
vst1q_u8(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_u16(i16* %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vst1q_u16(
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to <8 x i16>*
@@ -11519,7 +10600,7 @@ void test_vst1q_u16(uint16_t *a, uint16x8_t b) {
vst1q_u16(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_u32(i32* %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vst1q_u32(
// CHECK: [[TMP0:%.*]] = bitcast i32* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to <4 x i32>*
@@ -11530,7 +10611,7 @@ void test_vst1q_u32(uint32_t *a, uint32x4_t b) {
vst1q_u32(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_u64(i64* %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vst1q_u64(
// CHECK: [[TMP0:%.*]] = bitcast i64* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to <2 x i64>*
@@ -11541,7 +10622,7 @@ void test_vst1q_u64(uint64_t *a, uint64x2_t b) {
vst1q_u64(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_s8(i8* %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vst1q_s8(
// CHECK: [[TMP0:%.*]] = bitcast i8* %a to <16 x i8>*
// CHECK: store <16 x i8> %b, <16 x i8>* [[TMP0]]
// CHECK: ret void
@@ -11549,7 +10630,7 @@ void test_vst1q_s8(int8_t *a, int8x16_t b) {
vst1q_s8(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_s16(i16* %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vst1q_s16(
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to <8 x i16>*
@@ -11560,7 +10641,7 @@ void test_vst1q_s16(int16_t *a, int16x8_t b) {
vst1q_s16(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_s32(i32* %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vst1q_s32(
// CHECK: [[TMP0:%.*]] = bitcast i32* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to <4 x i32>*
@@ -11571,7 +10652,7 @@ void test_vst1q_s32(int32_t *a, int32x4_t b) {
vst1q_s32(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_s64(i64* %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vst1q_s64(
// CHECK: [[TMP0:%.*]] = bitcast i64* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to <2 x i64>*
@@ -11582,7 +10663,7 @@ void test_vst1q_s64(int64_t *a, int64x2_t b) {
vst1q_s64(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_f16(half* %a, <8 x half> %b) #0 {
+// CHECK-LABEL: @test_vst1q_f16(
// CHECK: [[TMP0:%.*]] = bitcast half* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <8 x half> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to <8 x i16>*
@@ -11593,7 +10674,7 @@ void test_vst1q_f16(float16_t *a, float16x8_t b) {
vst1q_f16(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_f32(float* %a, <4 x float> %b) #0 {
+// CHECK-LABEL: @test_vst1q_f32(
// CHECK: [[TMP0:%.*]] = bitcast float* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to <4 x float>*
@@ -11604,7 +10685,7 @@ void test_vst1q_f32(float32_t *a, float32x4_t b) {
vst1q_f32(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_f64(double* %a, <2 x double> %b) #0 {
+// CHECK-LABEL: @test_vst1q_f64(
// CHECK: [[TMP0:%.*]] = bitcast double* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x double> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to <2 x double>*
@@ -11615,7 +10696,7 @@ void test_vst1q_f64(float64_t *a, float64x2_t b) {
vst1q_f64(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_p8(i8* %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vst1q_p8(
// CHECK: [[TMP0:%.*]] = bitcast i8* %a to <16 x i8>*
// CHECK: store <16 x i8> %b, <16 x i8>* [[TMP0]]
// CHECK: ret void
@@ -11623,7 +10704,7 @@ void test_vst1q_p8(poly8_t *a, poly8x16_t b) {
vst1q_p8(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_p16(i16* %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vst1q_p16(
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to <8 x i16>*
@@ -11634,7 +10715,7 @@ void test_vst1q_p16(poly16_t *a, poly16x8_t b) {
vst1q_p16(a, b);
}
-// CHECK-LABEL: define void @test_vst1_u8(i8* %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vst1_u8(
// CHECK: [[TMP0:%.*]] = bitcast i8* %a to <8 x i8>*
// CHECK: store <8 x i8> %b, <8 x i8>* [[TMP0]]
// CHECK: ret void
@@ -11642,7 +10723,7 @@ void test_vst1_u8(uint8_t *a, uint8x8_t b) {
vst1_u8(a, b);
}
-// CHECK-LABEL: define void @test_vst1_u16(i16* %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vst1_u16(
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to <4 x i16>*
@@ -11653,7 +10734,7 @@ void test_vst1_u16(uint16_t *a, uint16x4_t b) {
vst1_u16(a, b);
}
-// CHECK-LABEL: define void @test_vst1_u32(i32* %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vst1_u32(
// CHECK: [[TMP0:%.*]] = bitcast i32* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to <2 x i32>*
@@ -11664,7 +10745,7 @@ void test_vst1_u32(uint32_t *a, uint32x2_t b) {
vst1_u32(a, b);
}
-// CHECK-LABEL: define void @test_vst1_u64(i64* %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vst1_u64(
// CHECK: [[TMP0:%.*]] = bitcast i64* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to <1 x i64>*
@@ -11675,7 +10756,7 @@ void test_vst1_u64(uint64_t *a, uint64x1_t b) {
vst1_u64(a, b);
}
-// CHECK-LABEL: define void @test_vst1_s8(i8* %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vst1_s8(
// CHECK: [[TMP0:%.*]] = bitcast i8* %a to <8 x i8>*
// CHECK: store <8 x i8> %b, <8 x i8>* [[TMP0]]
// CHECK: ret void
@@ -11683,7 +10764,7 @@ void test_vst1_s8(int8_t *a, int8x8_t b) {
vst1_s8(a, b);
}
-// CHECK-LABEL: define void @test_vst1_s16(i16* %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vst1_s16(
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to <4 x i16>*
@@ -11694,7 +10775,7 @@ void test_vst1_s16(int16_t *a, int16x4_t b) {
vst1_s16(a, b);
}
-// CHECK-LABEL: define void @test_vst1_s32(i32* %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vst1_s32(
// CHECK: [[TMP0:%.*]] = bitcast i32* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to <2 x i32>*
@@ -11705,7 +10786,7 @@ void test_vst1_s32(int32_t *a, int32x2_t b) {
vst1_s32(a, b);
}
-// CHECK-LABEL: define void @test_vst1_s64(i64* %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vst1_s64(
// CHECK: [[TMP0:%.*]] = bitcast i64* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to <1 x i64>*
@@ -11716,7 +10797,7 @@ void test_vst1_s64(int64_t *a, int64x1_t b) {
vst1_s64(a, b);
}
-// CHECK-LABEL: define void @test_vst1_f16(half* %a, <4 x half> %b) #0 {
+// CHECK-LABEL: @test_vst1_f16(
// CHECK: [[TMP0:%.*]] = bitcast half* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x half> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to <4 x i16>*
@@ -11727,7 +10808,7 @@ void test_vst1_f16(float16_t *a, float16x4_t b) {
vst1_f16(a, b);
}
-// CHECK-LABEL: define void @test_vst1_f32(float* %a, <2 x float> %b) #0 {
+// CHECK-LABEL: @test_vst1_f32(
// CHECK: [[TMP0:%.*]] = bitcast float* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to <2 x float>*
@@ -11738,7 +10819,7 @@ void test_vst1_f32(float32_t *a, float32x2_t b) {
vst1_f32(a, b);
}
-// CHECK-LABEL: define void @test_vst1_f64(double* %a, <1 x double> %b) #0 {
+// CHECK-LABEL: @test_vst1_f64(
// CHECK: [[TMP0:%.*]] = bitcast double* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <1 x double> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to <1 x double>*
@@ -11749,7 +10830,7 @@ void test_vst1_f64(float64_t *a, float64x1_t b) {
vst1_f64(a, b);
}
-// CHECK-LABEL: define void @test_vst1_p8(i8* %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vst1_p8(
// CHECK: [[TMP0:%.*]] = bitcast i8* %a to <8 x i8>*
// CHECK: store <8 x i8> %b, <8 x i8>* [[TMP0]]
// CHECK: ret void
@@ -11757,7 +10838,7 @@ void test_vst1_p8(poly8_t *a, poly8x8_t b) {
vst1_p8(a, b);
}
-// CHECK-LABEL: define void @test_vst1_p16(i16* %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vst1_p16(
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to <4 x i16>*
@@ -11768,7 +10849,7 @@ void test_vst1_p16(poly16_t *a, poly16x4_t b) {
vst1_p16(a, b);
}
-// CHECK-LABEL: define void @test_vst2q_u8(i8* %a, [2 x <16 x i8>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2q_u8(
// 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
@@ -11788,7 +10869,7 @@ void test_vst2q_u8(uint8_t *a, uint8x16x2_t b) {
vst2q_u8(a, b);
}
-// CHECK-LABEL: define void @test_vst2q_u16(i16* %a, [2 x <8 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2q_u16(
// 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
@@ -11813,7 +10894,7 @@ void test_vst2q_u16(uint16_t *a, uint16x8x2_t b) {
vst2q_u16(a, b);
}
-// CHECK-LABEL: define void @test_vst2q_u32(i32* %a, [2 x <4 x i32>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2q_u32(
// 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
@@ -11838,7 +10919,7 @@ void test_vst2q_u32(uint32_t *a, uint32x4x2_t b) {
vst2q_u32(a, b);
}
-// CHECK-LABEL: define void @test_vst2q_u64(i64* %a, [2 x <2 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2q_u64(
// 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
@@ -11863,7 +10944,7 @@ void test_vst2q_u64(uint64_t *a, uint64x2x2_t b) {
vst2q_u64(a, b);
}
-// CHECK-LABEL: define void @test_vst2q_s8(i8* %a, [2 x <16 x i8>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2q_s8(
// 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
@@ -11883,7 +10964,7 @@ void test_vst2q_s8(int8_t *a, int8x16x2_t b) {
vst2q_s8(a, b);
}
-// CHECK-LABEL: define void @test_vst2q_s16(i16* %a, [2 x <8 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2q_s16(
// 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
@@ -11908,7 +10989,7 @@ void test_vst2q_s16(int16_t *a, int16x8x2_t b) {
vst2q_s16(a, b);
}
-// CHECK-LABEL: define void @test_vst2q_s32(i32* %a, [2 x <4 x i32>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2q_s32(
// 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
@@ -11933,7 +11014,7 @@ void test_vst2q_s32(int32_t *a, int32x4x2_t b) {
vst2q_s32(a, b);
}
-// CHECK-LABEL: define void @test_vst2q_s64(i64* %a, [2 x <2 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2q_s64(
// 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
@@ -11958,7 +11039,7 @@ void test_vst2q_s64(int64_t *a, int64x2x2_t b) {
vst2q_s64(a, b);
}
-// CHECK-LABEL: define void @test_vst2q_f16(half* %a, [2 x <8 x half>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2q_f16(
// 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
@@ -11983,7 +11064,7 @@ void test_vst2q_f16(float16_t *a, float16x8x2_t b) {
vst2q_f16(a, b);
}
-// CHECK-LABEL: define void @test_vst2q_f32(float* %a, [2 x <4 x float>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2q_f32(
// 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
@@ -12008,7 +11089,7 @@ void test_vst2q_f32(float32_t *a, float32x4x2_t b) {
vst2q_f32(a, b);
}
-// CHECK-LABEL: define void @test_vst2q_f64(double* %a, [2 x <2 x double>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2q_f64(
// CHECK: [[B:%.*]] = alloca %struct.float64x2x2_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.float64x2x2_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float64x2x2_t, %struct.float64x2x2_t* [[B]], i32 0, i32 0
@@ -12033,7 +11114,7 @@ void test_vst2q_f64(float64_t *a, float64x2x2_t b) {
vst2q_f64(a, b);
}
-// CHECK-LABEL: define void @test_vst2q_p8(i8* %a, [2 x <16 x i8>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2q_p8(
// 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
@@ -12053,7 +11134,7 @@ void test_vst2q_p8(poly8_t *a, poly8x16x2_t b) {
vst2q_p8(a, b);
}
-// CHECK-LABEL: define void @test_vst2q_p16(i16* %a, [2 x <8 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2q_p16(
// 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
@@ -12078,7 +11159,7 @@ void test_vst2q_p16(poly16_t *a, poly16x8x2_t b) {
vst2q_p16(a, b);
}
-// CHECK-LABEL: define void @test_vst2_u8(i8* %a, [2 x <8 x i8>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2_u8(
// 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
@@ -12098,7 +11179,7 @@ void test_vst2_u8(uint8_t *a, uint8x8x2_t b) {
vst2_u8(a, b);
}
-// CHECK-LABEL: define void @test_vst2_u16(i16* %a, [2 x <4 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2_u16(
// 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
@@ -12123,7 +11204,7 @@ void test_vst2_u16(uint16_t *a, uint16x4x2_t b) {
vst2_u16(a, b);
}
-// CHECK-LABEL: define void @test_vst2_u32(i32* %a, [2 x <2 x i32>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2_u32(
// 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
@@ -12148,7 +11229,7 @@ void test_vst2_u32(uint32_t *a, uint32x2x2_t b) {
vst2_u32(a, b);
}
-// CHECK-LABEL: define void @test_vst2_u64(i64* %a, [2 x <1 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2_u64(
// 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
@@ -12173,7 +11254,7 @@ void test_vst2_u64(uint64_t *a, uint64x1x2_t b) {
vst2_u64(a, b);
}
-// CHECK-LABEL: define void @test_vst2_s8(i8* %a, [2 x <8 x i8>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2_s8(
// 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
@@ -12193,7 +11274,7 @@ void test_vst2_s8(int8_t *a, int8x8x2_t b) {
vst2_s8(a, b);
}
-// CHECK-LABEL: define void @test_vst2_s16(i16* %a, [2 x <4 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2_s16(
// 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
@@ -12218,7 +11299,7 @@ void test_vst2_s16(int16_t *a, int16x4x2_t b) {
vst2_s16(a, b);
}
-// CHECK-LABEL: define void @test_vst2_s32(i32* %a, [2 x <2 x i32>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2_s32(
// 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
@@ -12243,7 +11324,7 @@ void test_vst2_s32(int32_t *a, int32x2x2_t b) {
vst2_s32(a, b);
}
-// CHECK-LABEL: define void @test_vst2_s64(i64* %a, [2 x <1 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2_s64(
// 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
@@ -12268,7 +11349,7 @@ void test_vst2_s64(int64_t *a, int64x1x2_t b) {
vst2_s64(a, b);
}
-// CHECK-LABEL: define void @test_vst2_f16(half* %a, [2 x <4 x half>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2_f16(
// 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
@@ -12293,7 +11374,7 @@ void test_vst2_f16(float16_t *a, float16x4x2_t b) {
vst2_f16(a, b);
}
-// CHECK-LABEL: define void @test_vst2_f32(float* %a, [2 x <2 x float>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2_f32(
// 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
@@ -12318,7 +11399,7 @@ void test_vst2_f32(float32_t *a, float32x2x2_t b) {
vst2_f32(a, b);
}
-// CHECK-LABEL: define void @test_vst2_f64(double* %a, [2 x <1 x double>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2_f64(
// CHECK: [[B:%.*]] = alloca %struct.float64x1x2_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.float64x1x2_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float64x1x2_t, %struct.float64x1x2_t* [[B]], i32 0, i32 0
@@ -12343,7 +11424,7 @@ void test_vst2_f64(float64_t *a, float64x1x2_t b) {
vst2_f64(a, b);
}
-// CHECK-LABEL: define void @test_vst2_p8(i8* %a, [2 x <8 x i8>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2_p8(
// 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
@@ -12363,7 +11444,7 @@ void test_vst2_p8(poly8_t *a, poly8x8x2_t b) {
vst2_p8(a, b);
}
-// CHECK-LABEL: define void @test_vst2_p16(i16* %a, [2 x <4 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2_p16(
// 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
@@ -12388,7 +11469,7 @@ void test_vst2_p16(poly16_t *a, poly16x4x2_t b) {
vst2_p16(a, b);
}
-// CHECK-LABEL: define void @test_vst3q_u8(i8* %a, [3 x <16 x i8>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3q_u8(
// 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
@@ -12411,7 +11492,7 @@ void test_vst3q_u8(uint8_t *a, uint8x16x3_t b) {
vst3q_u8(a, b);
}
-// CHECK-LABEL: define void @test_vst3q_u16(i16* %a, [3 x <8 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3q_u16(
// 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
@@ -12441,7 +11522,7 @@ void test_vst3q_u16(uint16_t *a, uint16x8x3_t b) {
vst3q_u16(a, b);
}
-// CHECK-LABEL: define void @test_vst3q_u32(i32* %a, [3 x <4 x i32>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3q_u32(
// 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
@@ -12471,7 +11552,7 @@ void test_vst3q_u32(uint32_t *a, uint32x4x3_t b) {
vst3q_u32(a, b);
}
-// CHECK-LABEL: define void @test_vst3q_u64(i64* %a, [3 x <2 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3q_u64(
// 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
@@ -12501,7 +11582,7 @@ void test_vst3q_u64(uint64_t *a, uint64x2x3_t b) {
vst3q_u64(a, b);
}
-// CHECK-LABEL: define void @test_vst3q_s8(i8* %a, [3 x <16 x i8>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3q_s8(
// 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
@@ -12524,7 +11605,7 @@ void test_vst3q_s8(int8_t *a, int8x16x3_t b) {
vst3q_s8(a, b);
}
-// CHECK-LABEL: define void @test_vst3q_s16(i16* %a, [3 x <8 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3q_s16(
// 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
@@ -12554,7 +11635,7 @@ void test_vst3q_s16(int16_t *a, int16x8x3_t b) {
vst3q_s16(a, b);
}
-// CHECK-LABEL: define void @test_vst3q_s32(i32* %a, [3 x <4 x i32>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3q_s32(
// 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
@@ -12584,7 +11665,7 @@ void test_vst3q_s32(int32_t *a, int32x4x3_t b) {
vst3q_s32(a, b);
}
-// CHECK-LABEL: define void @test_vst3q_s64(i64* %a, [3 x <2 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3q_s64(
// 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
@@ -12614,7 +11695,7 @@ void test_vst3q_s64(int64_t *a, int64x2x3_t b) {
vst3q_s64(a, b);
}
-// CHECK-LABEL: define void @test_vst3q_f16(half* %a, [3 x <8 x half>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3q_f16(
// 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
@@ -12644,7 +11725,7 @@ void test_vst3q_f16(float16_t *a, float16x8x3_t b) {
vst3q_f16(a, b);
}
-// CHECK-LABEL: define void @test_vst3q_f32(float* %a, [3 x <4 x float>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3q_f32(
// 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
@@ -12674,7 +11755,7 @@ void test_vst3q_f32(float32_t *a, float32x4x3_t b) {
vst3q_f32(a, b);
}
-// CHECK-LABEL: define void @test_vst3q_f64(double* %a, [3 x <2 x double>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3q_f64(
// CHECK: [[B:%.*]] = alloca %struct.float64x2x3_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.float64x2x3_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float64x2x3_t, %struct.float64x2x3_t* [[B]], i32 0, i32 0
@@ -12704,7 +11785,7 @@ void test_vst3q_f64(float64_t *a, float64x2x3_t b) {
vst3q_f64(a, b);
}
-// CHECK-LABEL: define void @test_vst3q_p8(i8* %a, [3 x <16 x i8>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3q_p8(
// 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
@@ -12727,7 +11808,7 @@ void test_vst3q_p8(poly8_t *a, poly8x16x3_t b) {
vst3q_p8(a, b);
}
-// CHECK-LABEL: define void @test_vst3q_p16(i16* %a, [3 x <8 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3q_p16(
// 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
@@ -12757,7 +11838,7 @@ void test_vst3q_p16(poly16_t *a, poly16x8x3_t b) {
vst3q_p16(a, b);
}
-// CHECK-LABEL: define void @test_vst3_u8(i8* %a, [3 x <8 x i8>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3_u8(
// 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
@@ -12780,7 +11861,7 @@ void test_vst3_u8(uint8_t *a, uint8x8x3_t b) {
vst3_u8(a, b);
}
-// CHECK-LABEL: define void @test_vst3_u16(i16* %a, [3 x <4 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3_u16(
// 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
@@ -12810,7 +11891,7 @@ void test_vst3_u16(uint16_t *a, uint16x4x3_t b) {
vst3_u16(a, b);
}
-// CHECK-LABEL: define void @test_vst3_u32(i32* %a, [3 x <2 x i32>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3_u32(
// 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
@@ -12840,7 +11921,7 @@ void test_vst3_u32(uint32_t *a, uint32x2x3_t b) {
vst3_u32(a, b);
}
-// CHECK-LABEL: define void @test_vst3_u64(i64* %a, [3 x <1 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3_u64(
// 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
@@ -12870,7 +11951,7 @@ void test_vst3_u64(uint64_t *a, uint64x1x3_t b) {
vst3_u64(a, b);
}
-// CHECK-LABEL: define void @test_vst3_s8(i8* %a, [3 x <8 x i8>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3_s8(
// 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
@@ -12893,7 +11974,7 @@ void test_vst3_s8(int8_t *a, int8x8x3_t b) {
vst3_s8(a, b);
}
-// CHECK-LABEL: define void @test_vst3_s16(i16* %a, [3 x <4 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3_s16(
// 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
@@ -12923,7 +12004,7 @@ void test_vst3_s16(int16_t *a, int16x4x3_t b) {
vst3_s16(a, b);
}
-// CHECK-LABEL: define void @test_vst3_s32(i32* %a, [3 x <2 x i32>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3_s32(
// 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
@@ -12953,7 +12034,7 @@ void test_vst3_s32(int32_t *a, int32x2x3_t b) {
vst3_s32(a, b);
}
-// CHECK-LABEL: define void @test_vst3_s64(i64* %a, [3 x <1 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3_s64(
// 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
@@ -12983,7 +12064,7 @@ void test_vst3_s64(int64_t *a, int64x1x3_t b) {
vst3_s64(a, b);
}
-// CHECK-LABEL: define void @test_vst3_f16(half* %a, [3 x <4 x half>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3_f16(
// 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
@@ -13013,7 +12094,7 @@ void test_vst3_f16(float16_t *a, float16x4x3_t b) {
vst3_f16(a, b);
}
-// CHECK-LABEL: define void @test_vst3_f32(float* %a, [3 x <2 x float>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3_f32(
// 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
@@ -13043,7 +12124,7 @@ void test_vst3_f32(float32_t *a, float32x2x3_t b) {
vst3_f32(a, b);
}
-// CHECK-LABEL: define void @test_vst3_f64(double* %a, [3 x <1 x double>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3_f64(
// CHECK: [[B:%.*]] = alloca %struct.float64x1x3_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.float64x1x3_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float64x1x3_t, %struct.float64x1x3_t* [[B]], i32 0, i32 0
@@ -13073,7 +12154,7 @@ void test_vst3_f64(float64_t *a, float64x1x3_t b) {
vst3_f64(a, b);
}
-// CHECK-LABEL: define void @test_vst3_p8(i8* %a, [3 x <8 x i8>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3_p8(
// 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
@@ -13096,7 +12177,7 @@ void test_vst3_p8(poly8_t *a, poly8x8x3_t b) {
vst3_p8(a, b);
}
-// CHECK-LABEL: define void @test_vst3_p16(i16* %a, [3 x <4 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3_p16(
// 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
@@ -13126,7 +12207,7 @@ void test_vst3_p16(poly16_t *a, poly16x4x3_t b) {
vst3_p16(a, b);
}
-// CHECK-LABEL: define void @test_vst4q_u8(i8* %a, [4 x <16 x i8>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4q_u8(
// 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
@@ -13152,7 +12233,7 @@ void test_vst4q_u8(uint8_t *a, uint8x16x4_t b) {
vst4q_u8(a, b);
}
-// CHECK-LABEL: define void @test_vst4q_u16(i16* %a, [4 x <8 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4q_u16(
// 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
@@ -13187,7 +12268,7 @@ void test_vst4q_u16(uint16_t *a, uint16x8x4_t b) {
vst4q_u16(a, b);
}
-// CHECK-LABEL: define void @test_vst4q_u32(i32* %a, [4 x <4 x i32>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4q_u32(
// 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
@@ -13222,7 +12303,7 @@ void test_vst4q_u32(uint32_t *a, uint32x4x4_t b) {
vst4q_u32(a, b);
}
-// CHECK-LABEL: define void @test_vst4q_u64(i64* %a, [4 x <2 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4q_u64(
// 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
@@ -13257,7 +12338,7 @@ void test_vst4q_u64(uint64_t *a, uint64x2x4_t b) {
vst4q_u64(a, b);
}
-// CHECK-LABEL: define void @test_vst4q_s8(i8* %a, [4 x <16 x i8>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4q_s8(
// 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
@@ -13283,7 +12364,7 @@ void test_vst4q_s8(int8_t *a, int8x16x4_t b) {
vst4q_s8(a, b);
}
-// CHECK-LABEL: define void @test_vst4q_s16(i16* %a, [4 x <8 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4q_s16(
// 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
@@ -13318,7 +12399,7 @@ void test_vst4q_s16(int16_t *a, int16x8x4_t b) {
vst4q_s16(a, b);
}
-// CHECK-LABEL: define void @test_vst4q_s32(i32* %a, [4 x <4 x i32>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4q_s32(
// 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
@@ -13353,7 +12434,7 @@ void test_vst4q_s32(int32_t *a, int32x4x4_t b) {
vst4q_s32(a, b);
}
-// CHECK-LABEL: define void @test_vst4q_s64(i64* %a, [4 x <2 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4q_s64(
// 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
@@ -13388,7 +12469,7 @@ void test_vst4q_s64(int64_t *a, int64x2x4_t b) {
vst4q_s64(a, b);
}
-// CHECK-LABEL: define void @test_vst4q_f16(half* %a, [4 x <8 x half>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4q_f16(
// 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
@@ -13423,7 +12504,7 @@ void test_vst4q_f16(float16_t *a, float16x8x4_t b) {
vst4q_f16(a, b);
}
-// CHECK-LABEL: define void @test_vst4q_f32(float* %a, [4 x <4 x float>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4q_f32(
// 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
@@ -13458,7 +12539,7 @@ void test_vst4q_f32(float32_t *a, float32x4x4_t b) {
vst4q_f32(a, b);
}
-// CHECK-LABEL: define void @test_vst4q_f64(double* %a, [4 x <2 x double>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4q_f64(
// CHECK: [[B:%.*]] = alloca %struct.float64x2x4_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.float64x2x4_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float64x2x4_t, %struct.float64x2x4_t* [[B]], i32 0, i32 0
@@ -13493,7 +12574,7 @@ void test_vst4q_f64(float64_t *a, float64x2x4_t b) {
vst4q_f64(a, b);
}
-// CHECK-LABEL: define void @test_vst4q_p8(i8* %a, [4 x <16 x i8>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4q_p8(
// 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
@@ -13519,7 +12600,7 @@ void test_vst4q_p8(poly8_t *a, poly8x16x4_t b) {
vst4q_p8(a, b);
}
-// CHECK-LABEL: define void @test_vst4q_p16(i16* %a, [4 x <8 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4q_p16(
// 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
@@ -13554,7 +12635,7 @@ void test_vst4q_p16(poly16_t *a, poly16x8x4_t b) {
vst4q_p16(a, b);
}
-// CHECK-LABEL: define void @test_vst4_u8(i8* %a, [4 x <8 x i8>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4_u8(
// 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
@@ -13580,7 +12661,7 @@ void test_vst4_u8(uint8_t *a, uint8x8x4_t b) {
vst4_u8(a, b);
}
-// CHECK-LABEL: define void @test_vst4_u16(i16* %a, [4 x <4 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4_u16(
// 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
@@ -13615,7 +12696,7 @@ void test_vst4_u16(uint16_t *a, uint16x4x4_t b) {
vst4_u16(a, b);
}
-// CHECK-LABEL: define void @test_vst4_u32(i32* %a, [4 x <2 x i32>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4_u32(
// 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
@@ -13650,7 +12731,7 @@ void test_vst4_u32(uint32_t *a, uint32x2x4_t b) {
vst4_u32(a, b);
}
-// CHECK-LABEL: define void @test_vst4_u64(i64* %a, [4 x <1 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4_u64(
// 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
@@ -13685,7 +12766,7 @@ void test_vst4_u64(uint64_t *a, uint64x1x4_t b) {
vst4_u64(a, b);
}
-// CHECK-LABEL: define void @test_vst4_s8(i8* %a, [4 x <8 x i8>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4_s8(
// 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
@@ -13711,7 +12792,7 @@ void test_vst4_s8(int8_t *a, int8x8x4_t b) {
vst4_s8(a, b);
}
-// CHECK-LABEL: define void @test_vst4_s16(i16* %a, [4 x <4 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4_s16(
// 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
@@ -13746,7 +12827,7 @@ void test_vst4_s16(int16_t *a, int16x4x4_t b) {
vst4_s16(a, b);
}
-// CHECK-LABEL: define void @test_vst4_s32(i32* %a, [4 x <2 x i32>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4_s32(
// 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
@@ -13781,7 +12862,7 @@ void test_vst4_s32(int32_t *a, int32x2x4_t b) {
vst4_s32(a, b);
}
-// CHECK-LABEL: define void @test_vst4_s64(i64* %a, [4 x <1 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4_s64(
// 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
@@ -13816,7 +12897,7 @@ void test_vst4_s64(int64_t *a, int64x1x4_t b) {
vst4_s64(a, b);
}
-// CHECK-LABEL: define void @test_vst4_f16(half* %a, [4 x <4 x half>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4_f16(
// 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
@@ -13851,7 +12932,7 @@ void test_vst4_f16(float16_t *a, float16x4x4_t b) {
vst4_f16(a, b);
}
-// CHECK-LABEL: define void @test_vst4_f32(float* %a, [4 x <2 x float>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4_f32(
// 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
@@ -13886,7 +12967,7 @@ void test_vst4_f32(float32_t *a, float32x2x4_t b) {
vst4_f32(a, b);
}
-// CHECK-LABEL: define void @test_vst4_f64(double* %a, [4 x <1 x double>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4_f64(
// CHECK: [[B:%.*]] = alloca %struct.float64x1x4_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.float64x1x4_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float64x1x4_t, %struct.float64x1x4_t* [[B]], i32 0, i32 0
@@ -13921,7 +13002,7 @@ void test_vst4_f64(float64_t *a, float64x1x4_t b) {
vst4_f64(a, b);
}
-// CHECK-LABEL: define void @test_vst4_p8(i8* %a, [4 x <8 x i8>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4_p8(
// 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
@@ -13947,7 +13028,7 @@ void test_vst4_p8(poly8_t *a, poly8x8x4_t b) {
vst4_p8(a, b);
}
-// CHECK-LABEL: define void @test_vst4_p16(i16* %a, [4 x <4 x i16>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4_p16(
// 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
@@ -13982,7 +13063,7 @@ void test_vst4_p16(poly16_t *a, poly16x4x4_t b) {
vst4_p16(a, b);
}
-// CHECK-LABEL: define %struct.uint8x16x2_t @test_vld1q_u8_x2(i8* %a) #0 {
+// 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*
@@ -13998,7 +13079,7 @@ uint8x16x2_t test_vld1q_u8_x2(uint8_t const *a) {
return vld1q_u8_x2(a);
}
-// CHECK-LABEL: define %struct.uint16x8x2_t @test_vld1q_u16_x2(i16* %a) #0 {
+// 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*
@@ -14016,7 +13097,7 @@ uint16x8x2_t test_vld1q_u16_x2(uint16_t const *a) {
return vld1q_u16_x2(a);
}
-// CHECK-LABEL: define %struct.uint32x4x2_t @test_vld1q_u32_x2(i32* %a) #0 {
+// 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*
@@ -14034,7 +13115,7 @@ uint32x4x2_t test_vld1q_u32_x2(uint32_t const *a) {
return vld1q_u32_x2(a);
}
-// CHECK-LABEL: define %struct.uint64x2x2_t @test_vld1q_u64_x2(i64* %a) #0 {
+// 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*
@@ -14052,7 +13133,7 @@ uint64x2x2_t test_vld1q_u64_x2(uint64_t const *a) {
return vld1q_u64_x2(a);
}
-// CHECK-LABEL: define %struct.int8x16x2_t @test_vld1q_s8_x2(i8* %a) #0 {
+// 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*
@@ -14068,7 +13149,7 @@ int8x16x2_t test_vld1q_s8_x2(int8_t const *a) {
return vld1q_s8_x2(a);
}
-// CHECK-LABEL: define %struct.int16x8x2_t @test_vld1q_s16_x2(i16* %a) #0 {
+// 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*
@@ -14086,7 +13167,7 @@ int16x8x2_t test_vld1q_s16_x2(int16_t const *a) {
return vld1q_s16_x2(a);
}
-// CHECK-LABEL: define %struct.int32x4x2_t @test_vld1q_s32_x2(i32* %a) #0 {
+// 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*
@@ -14104,7 +13185,7 @@ int32x4x2_t test_vld1q_s32_x2(int32_t const *a) {
return vld1q_s32_x2(a);
}
-// CHECK-LABEL: define %struct.int64x2x2_t @test_vld1q_s64_x2(i64* %a) #0 {
+// 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*
@@ -14122,7 +13203,7 @@ int64x2x2_t test_vld1q_s64_x2(int64_t const *a) {
return vld1q_s64_x2(a);
}
-// CHECK-LABEL: define %struct.float16x8x2_t @test_vld1q_f16_x2(half* %a) #0 {
+// 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*
@@ -14140,7 +13221,7 @@ float16x8x2_t test_vld1q_f16_x2(float16_t const *a) {
return vld1q_f16_x2(a);
}
-// CHECK-LABEL: define %struct.float32x4x2_t @test_vld1q_f32_x2(float* %a) #0 {
+// 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*
@@ -14158,7 +13239,7 @@ float32x4x2_t test_vld1q_f32_x2(float32_t const *a) {
return vld1q_f32_x2(a);
}
-// CHECK-LABEL: define %struct.float64x2x2_t @test_vld1q_f64_x2(double* %a) #0 {
+// CHECK-LABEL: @test_vld1q_f64_x2(
// CHECK: [[RETVAL:%.*]] = alloca %struct.float64x2x2_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.float64x2x2_t, align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x2x2_t* [[__RET]] to i8*
@@ -14176,7 +13257,7 @@ float64x2x2_t test_vld1q_f64_x2(float64_t const *a) {
return vld1q_f64_x2(a);
}
-// CHECK-LABEL: define %struct.poly8x16x2_t @test_vld1q_p8_x2(i8* %a) #0 {
+// 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*
@@ -14192,7 +13273,7 @@ poly8x16x2_t test_vld1q_p8_x2(poly8_t const *a) {
return vld1q_p8_x2(a);
}
-// CHECK-LABEL: define %struct.poly16x8x2_t @test_vld1q_p16_x2(i16* %a) #0 {
+// 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*
@@ -14210,7 +13291,7 @@ poly16x8x2_t test_vld1q_p16_x2(poly16_t const *a) {
return vld1q_p16_x2(a);
}
-// CHECK-LABEL: define %struct.poly64x2x2_t @test_vld1q_p64_x2(i64* %a) #0 {
+// CHECK-LABEL: @test_vld1q_p64_x2(
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly64x2x2_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.poly64x2x2_t, align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly64x2x2_t* [[__RET]] to i8*
@@ -14228,7 +13309,7 @@ poly64x2x2_t test_vld1q_p64_x2(poly64_t const *a) {
return vld1q_p64_x2(a);
}
-// CHECK-LABEL: define %struct.uint8x8x2_t @test_vld1_u8_x2(i8* %a) #0 {
+// 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*
@@ -14244,7 +13325,7 @@ uint8x8x2_t test_vld1_u8_x2(uint8_t const *a) {
return vld1_u8_x2(a);
}
-// CHECK-LABEL: define %struct.uint16x4x2_t @test_vld1_u16_x2(i16* %a) #0 {
+// 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*
@@ -14262,7 +13343,7 @@ uint16x4x2_t test_vld1_u16_x2(uint16_t const *a) {
return vld1_u16_x2(a);
}
-// CHECK-LABEL: define %struct.uint32x2x2_t @test_vld1_u32_x2(i32* %a) #0 {
+// 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*
@@ -14280,7 +13361,7 @@ uint32x2x2_t test_vld1_u32_x2(uint32_t const *a) {
return vld1_u32_x2(a);
}
-// CHECK-LABEL: define %struct.uint64x1x2_t @test_vld1_u64_x2(i64* %a) #0 {
+// 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*
@@ -14298,7 +13379,7 @@ uint64x1x2_t test_vld1_u64_x2(uint64_t const *a) {
return vld1_u64_x2(a);
}
-// CHECK-LABEL: define %struct.int8x8x2_t @test_vld1_s8_x2(i8* %a) #0 {
+// 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*
@@ -14314,7 +13395,7 @@ int8x8x2_t test_vld1_s8_x2(int8_t const *a) {
return vld1_s8_x2(a);
}
-// CHECK-LABEL: define %struct.int16x4x2_t @test_vld1_s16_x2(i16* %a) #0 {
+// 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*
@@ -14332,7 +13413,7 @@ int16x4x2_t test_vld1_s16_x2(int16_t const *a) {
return vld1_s16_x2(a);
}
-// CHECK-LABEL: define %struct.int32x2x2_t @test_vld1_s32_x2(i32* %a) #0 {
+// 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*
@@ -14350,7 +13431,7 @@ int32x2x2_t test_vld1_s32_x2(int32_t const *a) {
return vld1_s32_x2(a);
}
-// CHECK-LABEL: define %struct.int64x1x2_t @test_vld1_s64_x2(i64* %a) #0 {
+// 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*
@@ -14368,7 +13449,7 @@ int64x1x2_t test_vld1_s64_x2(int64_t const *a) {
return vld1_s64_x2(a);
}
-// CHECK-LABEL: define %struct.float16x4x2_t @test_vld1_f16_x2(half* %a) #0 {
+// 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*
@@ -14386,7 +13467,7 @@ float16x4x2_t test_vld1_f16_x2(float16_t const *a) {
return vld1_f16_x2(a);
}
-// CHECK-LABEL: define %struct.float32x2x2_t @test_vld1_f32_x2(float* %a) #0 {
+// 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*
@@ -14404,7 +13485,7 @@ float32x2x2_t test_vld1_f32_x2(float32_t const *a) {
return vld1_f32_x2(a);
}
-// CHECK-LABEL: define %struct.float64x1x2_t @test_vld1_f64_x2(double* %a) #0 {
+// CHECK-LABEL: @test_vld1_f64_x2(
// CHECK: [[RETVAL:%.*]] = alloca %struct.float64x1x2_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.float64x1x2_t, align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x1x2_t* [[__RET]] to i8*
@@ -14422,7 +13503,7 @@ float64x1x2_t test_vld1_f64_x2(float64_t const *a) {
return vld1_f64_x2(a);
}
-// CHECK-LABEL: define %struct.poly8x8x2_t @test_vld1_p8_x2(i8* %a) #0 {
+// 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*
@@ -14438,7 +13519,7 @@ poly8x8x2_t test_vld1_p8_x2(poly8_t const *a) {
return vld1_p8_x2(a);
}
-// CHECK-LABEL: define %struct.poly16x4x2_t @test_vld1_p16_x2(i16* %a) #0 {
+// 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*
@@ -14456,7 +13537,7 @@ poly16x4x2_t test_vld1_p16_x2(poly16_t const *a) {
return vld1_p16_x2(a);
}
-// CHECK-LABEL: define %struct.poly64x1x2_t @test_vld1_p64_x2(i64* %a) #0 {
+// CHECK-LABEL: @test_vld1_p64_x2(
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly64x1x2_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.poly64x1x2_t, align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly64x1x2_t* [[__RET]] to i8*
@@ -14474,7 +13555,7 @@ poly64x1x2_t test_vld1_p64_x2(poly64_t const *a) {
return vld1_p64_x2(a);
}
-// CHECK-LABEL: define %struct.uint8x16x3_t @test_vld1q_u8_x3(i8* %a) #0 {
+// 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*
@@ -14490,7 +13571,7 @@ uint8x16x3_t test_vld1q_u8_x3(uint8_t const *a) {
return vld1q_u8_x3(a);
}
-// CHECK-LABEL: define %struct.uint16x8x3_t @test_vld1q_u16_x3(i16* %a) #0 {
+// 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*
@@ -14508,7 +13589,7 @@ uint16x8x3_t test_vld1q_u16_x3(uint16_t const *a) {
return vld1q_u16_x3(a);
}
-// CHECK-LABEL: define %struct.uint32x4x3_t @test_vld1q_u32_x3(i32* %a) #0 {
+// 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*
@@ -14526,7 +13607,7 @@ uint32x4x3_t test_vld1q_u32_x3(uint32_t const *a) {
return vld1q_u32_x3(a);
}
-// CHECK-LABEL: define %struct.uint64x2x3_t @test_vld1q_u64_x3(i64* %a) #0 {
+// 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*
@@ -14544,7 +13625,7 @@ uint64x2x3_t test_vld1q_u64_x3(uint64_t const *a) {
return vld1q_u64_x3(a);
}
-// CHECK-LABEL: define %struct.int8x16x3_t @test_vld1q_s8_x3(i8* %a) #0 {
+// 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*
@@ -14560,7 +13641,7 @@ int8x16x3_t test_vld1q_s8_x3(int8_t const *a) {
return vld1q_s8_x3(a);
}
-// CHECK-LABEL: define %struct.int16x8x3_t @test_vld1q_s16_x3(i16* %a) #0 {
+// 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*
@@ -14578,7 +13659,7 @@ int16x8x3_t test_vld1q_s16_x3(int16_t const *a) {
return vld1q_s16_x3(a);
}
-// CHECK-LABEL: define %struct.int32x4x3_t @test_vld1q_s32_x3(i32* %a) #0 {
+// 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*
@@ -14596,7 +13677,7 @@ int32x4x3_t test_vld1q_s32_x3(int32_t const *a) {
return vld1q_s32_x3(a);
}
-// CHECK-LABEL: define %struct.int64x2x3_t @test_vld1q_s64_x3(i64* %a) #0 {
+// 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*
@@ -14614,7 +13695,7 @@ int64x2x3_t test_vld1q_s64_x3(int64_t const *a) {
return vld1q_s64_x3(a);
}
-// CHECK-LABEL: define %struct.float16x8x3_t @test_vld1q_f16_x3(half* %a) #0 {
+// 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*
@@ -14632,7 +13713,7 @@ float16x8x3_t test_vld1q_f16_x3(float16_t const *a) {
return vld1q_f16_x3(a);
}
-// CHECK-LABEL: define %struct.float32x4x3_t @test_vld1q_f32_x3(float* %a) #0 {
+// 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*
@@ -14650,7 +13731,7 @@ float32x4x3_t test_vld1q_f32_x3(float32_t const *a) {
return vld1q_f32_x3(a);
}
-// CHECK-LABEL: define %struct.float64x2x3_t @test_vld1q_f64_x3(double* %a) #0 {
+// CHECK-LABEL: @test_vld1q_f64_x3(
// CHECK: [[RETVAL:%.*]] = alloca %struct.float64x2x3_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.float64x2x3_t, align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x2x3_t* [[__RET]] to i8*
@@ -14668,7 +13749,7 @@ float64x2x3_t test_vld1q_f64_x3(float64_t const *a) {
return vld1q_f64_x3(a);
}
-// CHECK-LABEL: define %struct.poly8x16x3_t @test_vld1q_p8_x3(i8* %a) #0 {
+// 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*
@@ -14684,7 +13765,7 @@ poly8x16x3_t test_vld1q_p8_x3(poly8_t const *a) {
return vld1q_p8_x3(a);
}
-// CHECK-LABEL: define %struct.poly16x8x3_t @test_vld1q_p16_x3(i16* %a) #0 {
+// 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*
@@ -14702,7 +13783,7 @@ poly16x8x3_t test_vld1q_p16_x3(poly16_t const *a) {
return vld1q_p16_x3(a);
}
-// CHECK-LABEL: define %struct.poly64x2x3_t @test_vld1q_p64_x3(i64* %a) #0 {
+// CHECK-LABEL: @test_vld1q_p64_x3(
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly64x2x3_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.poly64x2x3_t, align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly64x2x3_t* [[__RET]] to i8*
@@ -14720,7 +13801,7 @@ poly64x2x3_t test_vld1q_p64_x3(poly64_t const *a) {
return vld1q_p64_x3(a);
}
-// CHECK-LABEL: define %struct.uint8x8x3_t @test_vld1_u8_x3(i8* %a) #0 {
+// 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*
@@ -14736,7 +13817,7 @@ uint8x8x3_t test_vld1_u8_x3(uint8_t const *a) {
return vld1_u8_x3(a);
}
-// CHECK-LABEL: define %struct.uint16x4x3_t @test_vld1_u16_x3(i16* %a) #0 {
+// 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*
@@ -14754,7 +13835,7 @@ uint16x4x3_t test_vld1_u16_x3(uint16_t const *a) {
return vld1_u16_x3(a);
}
-// CHECK-LABEL: define %struct.uint32x2x3_t @test_vld1_u32_x3(i32* %a) #0 {
+// 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*
@@ -14772,7 +13853,7 @@ uint32x2x3_t test_vld1_u32_x3(uint32_t const *a) {
return vld1_u32_x3(a);
}
-// CHECK-LABEL: define %struct.uint64x1x3_t @test_vld1_u64_x3(i64* %a) #0 {
+// 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*
@@ -14790,7 +13871,7 @@ uint64x1x3_t test_vld1_u64_x3(uint64_t const *a) {
return vld1_u64_x3(a);
}
-// CHECK-LABEL: define %struct.int8x8x3_t @test_vld1_s8_x3(i8* %a) #0 {
+// 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*
@@ -14806,7 +13887,7 @@ int8x8x3_t test_vld1_s8_x3(int8_t const *a) {
return vld1_s8_x3(a);
}
-// CHECK-LABEL: define %struct.int16x4x3_t @test_vld1_s16_x3(i16* %a) #0 {
+// 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*
@@ -14824,7 +13905,7 @@ int16x4x3_t test_vld1_s16_x3(int16_t const *a) {
return vld1_s16_x3(a);
}
-// CHECK-LABEL: define %struct.int32x2x3_t @test_vld1_s32_x3(i32* %a) #0 {
+// 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*
@@ -14842,7 +13923,7 @@ int32x2x3_t test_vld1_s32_x3(int32_t const *a) {
return vld1_s32_x3(a);
}
-// CHECK-LABEL: define %struct.int64x1x3_t @test_vld1_s64_x3(i64* %a) #0 {
+// 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*
@@ -14860,7 +13941,7 @@ int64x1x3_t test_vld1_s64_x3(int64_t const *a) {
return vld1_s64_x3(a);
}
-// CHECK-LABEL: define %struct.float16x4x3_t @test_vld1_f16_x3(half* %a) #0 {
+// 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*
@@ -14878,7 +13959,7 @@ float16x4x3_t test_vld1_f16_x3(float16_t const *a) {
return vld1_f16_x3(a);
}
-// CHECK-LABEL: define %struct.float32x2x3_t @test_vld1_f32_x3(float* %a) #0 {
+// 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*
@@ -14896,7 +13977,7 @@ float32x2x3_t test_vld1_f32_x3(float32_t const *a) {
return vld1_f32_x3(a);
}
-// CHECK-LABEL: define %struct.float64x1x3_t @test_vld1_f64_x3(double* %a) #0 {
+// CHECK-LABEL: @test_vld1_f64_x3(
// CHECK: [[RETVAL:%.*]] = alloca %struct.float64x1x3_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.float64x1x3_t, align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x1x3_t* [[__RET]] to i8*
@@ -14914,7 +13995,7 @@ float64x1x3_t test_vld1_f64_x3(float64_t const *a) {
return vld1_f64_x3(a);
}
-// CHECK-LABEL: define %struct.poly8x8x3_t @test_vld1_p8_x3(i8* %a) #0 {
+// 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*
@@ -14930,7 +14011,7 @@ poly8x8x3_t test_vld1_p8_x3(poly8_t const *a) {
return vld1_p8_x3(a);
}
-// CHECK-LABEL: define %struct.poly16x4x3_t @test_vld1_p16_x3(i16* %a) #0 {
+// 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*
@@ -14948,7 +14029,7 @@ poly16x4x3_t test_vld1_p16_x3(poly16_t const *a) {
return vld1_p16_x3(a);
}
-// CHECK-LABEL: define %struct.poly64x1x3_t @test_vld1_p64_x3(i64* %a) #0 {
+// CHECK-LABEL: @test_vld1_p64_x3(
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly64x1x3_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.poly64x1x3_t, align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly64x1x3_t* [[__RET]] to i8*
@@ -14966,7 +14047,7 @@ poly64x1x3_t test_vld1_p64_x3(poly64_t const *a) {
return vld1_p64_x3(a);
}
-// CHECK-LABEL: define %struct.uint8x16x4_t @test_vld1q_u8_x4(i8* %a) #0 {
+// 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*
@@ -14982,7 +14063,7 @@ uint8x16x4_t test_vld1q_u8_x4(uint8_t const *a) {
return vld1q_u8_x4(a);
}
-// CHECK-LABEL: define %struct.uint16x8x4_t @test_vld1q_u16_x4(i16* %a) #0 {
+// 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*
@@ -15000,7 +14081,7 @@ uint16x8x4_t test_vld1q_u16_x4(uint16_t const *a) {
return vld1q_u16_x4(a);
}
-// CHECK-LABEL: define %struct.uint32x4x4_t @test_vld1q_u32_x4(i32* %a) #0 {
+// 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*
@@ -15018,7 +14099,7 @@ uint32x4x4_t test_vld1q_u32_x4(uint32_t const *a) {
return vld1q_u32_x4(a);
}
-// CHECK-LABEL: define %struct.uint64x2x4_t @test_vld1q_u64_x4(i64* %a) #0 {
+// 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*
@@ -15036,7 +14117,7 @@ uint64x2x4_t test_vld1q_u64_x4(uint64_t const *a) {
return vld1q_u64_x4(a);
}
-// CHECK-LABEL: define %struct.int8x16x4_t @test_vld1q_s8_x4(i8* %a) #0 {
+// 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*
@@ -15052,7 +14133,7 @@ int8x16x4_t test_vld1q_s8_x4(int8_t const *a) {
return vld1q_s8_x4(a);
}
-// CHECK-LABEL: define %struct.int16x8x4_t @test_vld1q_s16_x4(i16* %a) #0 {
+// 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*
@@ -15070,7 +14151,7 @@ int16x8x4_t test_vld1q_s16_x4(int16_t const *a) {
return vld1q_s16_x4(a);
}
-// CHECK-LABEL: define %struct.int32x4x4_t @test_vld1q_s32_x4(i32* %a) #0 {
+// 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*
@@ -15088,7 +14169,7 @@ int32x4x4_t test_vld1q_s32_x4(int32_t const *a) {
return vld1q_s32_x4(a);
}
-// CHECK-LABEL: define %struct.int64x2x4_t @test_vld1q_s64_x4(i64* %a) #0 {
+// 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*
@@ -15106,7 +14187,7 @@ int64x2x4_t test_vld1q_s64_x4(int64_t const *a) {
return vld1q_s64_x4(a);
}
-// CHECK-LABEL: define %struct.float16x8x4_t @test_vld1q_f16_x4(half* %a) #0 {
+// 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*
@@ -15124,7 +14205,7 @@ float16x8x4_t test_vld1q_f16_x4(float16_t const *a) {
return vld1q_f16_x4(a);
}
-// CHECK-LABEL: define %struct.float32x4x4_t @test_vld1q_f32_x4(float* %a) #0 {
+// 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*
@@ -15142,7 +14223,7 @@ float32x4x4_t test_vld1q_f32_x4(float32_t const *a) {
return vld1q_f32_x4(a);
}
-// CHECK-LABEL: define %struct.float64x2x4_t @test_vld1q_f64_x4(double* %a) #0 {
+// CHECK-LABEL: @test_vld1q_f64_x4(
// CHECK: [[RETVAL:%.*]] = alloca %struct.float64x2x4_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.float64x2x4_t, align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x2x4_t* [[__RET]] to i8*
@@ -15160,7 +14241,7 @@ float64x2x4_t test_vld1q_f64_x4(float64_t const *a) {
return vld1q_f64_x4(a);
}
-// CHECK-LABEL: define %struct.poly8x16x4_t @test_vld1q_p8_x4(i8* %a) #0 {
+// 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*
@@ -15176,7 +14257,7 @@ poly8x16x4_t test_vld1q_p8_x4(poly8_t const *a) {
return vld1q_p8_x4(a);
}
-// CHECK-LABEL: define %struct.poly16x8x4_t @test_vld1q_p16_x4(i16* %a) #0 {
+// 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*
@@ -15194,7 +14275,7 @@ poly16x8x4_t test_vld1q_p16_x4(poly16_t const *a) {
return vld1q_p16_x4(a);
}
-// CHECK-LABEL: define %struct.poly64x2x4_t @test_vld1q_p64_x4(i64* %a) #0 {
+// CHECK-LABEL: @test_vld1q_p64_x4(
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly64x2x4_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.poly64x2x4_t, align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly64x2x4_t* [[__RET]] to i8*
@@ -15212,7 +14293,7 @@ poly64x2x4_t test_vld1q_p64_x4(poly64_t const *a) {
return vld1q_p64_x4(a);
}
-// CHECK-LABEL: define %struct.uint8x8x4_t @test_vld1_u8_x4(i8* %a) #0 {
+// 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*
@@ -15228,7 +14309,7 @@ uint8x8x4_t test_vld1_u8_x4(uint8_t const *a) {
return vld1_u8_x4(a);
}
-// CHECK-LABEL: define %struct.uint16x4x4_t @test_vld1_u16_x4(i16* %a) #0 {
+// 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*
@@ -15246,7 +14327,7 @@ uint16x4x4_t test_vld1_u16_x4(uint16_t const *a) {
return vld1_u16_x4(a);
}
-// CHECK-LABEL: define %struct.uint32x2x4_t @test_vld1_u32_x4(i32* %a) #0 {
+// 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*
@@ -15264,7 +14345,7 @@ uint32x2x4_t test_vld1_u32_x4(uint32_t const *a) {
return vld1_u32_x4(a);
}
-// CHECK-LABEL: define %struct.uint64x1x4_t @test_vld1_u64_x4(i64* %a) #0 {
+// 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*
@@ -15282,7 +14363,7 @@ uint64x1x4_t test_vld1_u64_x4(uint64_t const *a) {
return vld1_u64_x4(a);
}
-// CHECK-LABEL: define %struct.int8x8x4_t @test_vld1_s8_x4(i8* %a) #0 {
+// 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*
@@ -15298,7 +14379,7 @@ int8x8x4_t test_vld1_s8_x4(int8_t const *a) {
return vld1_s8_x4(a);
}
-// CHECK-LABEL: define %struct.int16x4x4_t @test_vld1_s16_x4(i16* %a) #0 {
+// 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*
@@ -15316,7 +14397,7 @@ int16x4x4_t test_vld1_s16_x4(int16_t const *a) {
return vld1_s16_x4(a);
}
-// CHECK-LABEL: define %struct.int32x2x4_t @test_vld1_s32_x4(i32* %a) #0 {
+// 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*
@@ -15334,7 +14415,7 @@ int32x2x4_t test_vld1_s32_x4(int32_t const *a) {
return vld1_s32_x4(a);
}
-// CHECK-LABEL: define %struct.int64x1x4_t @test_vld1_s64_x4(i64* %a) #0 {
+// 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*
@@ -15352,7 +14433,7 @@ int64x1x4_t test_vld1_s64_x4(int64_t const *a) {
return vld1_s64_x4(a);
}
-// CHECK-LABEL: define %struct.float16x4x4_t @test_vld1_f16_x4(half* %a) #0 {
+// 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*
@@ -15370,7 +14451,7 @@ float16x4x4_t test_vld1_f16_x4(float16_t const *a) {
return vld1_f16_x4(a);
}
-// CHECK-LABEL: define %struct.float32x2x4_t @test_vld1_f32_x4(float* %a) #0 {
+// 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*
@@ -15388,7 +14469,7 @@ float32x2x4_t test_vld1_f32_x4(float32_t const *a) {
return vld1_f32_x4(a);
}
-// CHECK-LABEL: define %struct.float64x1x4_t @test_vld1_f64_x4(double* %a) #0 {
+// CHECK-LABEL: @test_vld1_f64_x4(
// CHECK: [[RETVAL:%.*]] = alloca %struct.float64x1x4_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.float64x1x4_t, align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.float64x1x4_t* [[__RET]] to i8*
@@ -15406,7 +14487,7 @@ float64x1x4_t test_vld1_f64_x4(float64_t const *a) {
return vld1_f64_x4(a);
}
-// CHECK-LABEL: define %struct.poly8x8x4_t @test_vld1_p8_x4(i8* %a) #0 {
+// 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*
@@ -15422,7 +14503,7 @@ poly8x8x4_t test_vld1_p8_x4(poly8_t const *a) {
return vld1_p8_x4(a);
}
-// CHECK-LABEL: define %struct.poly16x4x4_t @test_vld1_p16_x4(i16* %a) #0 {
+// 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*
@@ -15440,7 +14521,7 @@ poly16x4x4_t test_vld1_p16_x4(poly16_t const *a) {
return vld1_p16_x4(a);
}
-// CHECK-LABEL: define %struct.poly64x1x4_t @test_vld1_p64_x4(i64* %a) #0 {
+// CHECK-LABEL: @test_vld1_p64_x4(
// CHECK: [[RETVAL:%.*]] = alloca %struct.poly64x1x4_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.poly64x1x4_t, align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly64x1x4_t* [[__RET]] to i8*
@@ -15458,7 +14539,7 @@ poly64x1x4_t test_vld1_p64_x4(poly64_t const *a) {
return vld1_p64_x4(a);
}
-// CHECK-LABEL: define void @test_vst1q_u8_x2(i8* %a, [2 x <16 x i8>] %b.coerce) #0 {
+// 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
@@ -15478,7 +14559,7 @@ void test_vst1q_u8_x2(uint8_t *a, uint8x16x2_t b) {
vst1q_u8_x2(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_u16_x2(i16* %a, [2 x <8 x i16>] %b.coerce) #0 {
+// 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
@@ -15504,7 +14585,7 @@ void test_vst1q_u16_x2(uint16_t *a, uint16x8x2_t b) {
vst1q_u16_x2(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_u32_x2(i32* %a, [2 x <4 x i32>] %b.coerce) #0 {
+// 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
@@ -15530,7 +14611,7 @@ void test_vst1q_u32_x2(uint32_t *a, uint32x4x2_t b) {
vst1q_u32_x2(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_u64_x2(i64* %a, [2 x <2 x i64>] %b.coerce) #0 {
+// 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
@@ -15556,7 +14637,7 @@ void test_vst1q_u64_x2(uint64_t *a, uint64x2x2_t b) {
vst1q_u64_x2(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_s8_x2(i8* %a, [2 x <16 x i8>] %b.coerce) #0 {
+// 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
@@ -15576,7 +14657,7 @@ void test_vst1q_s8_x2(int8_t *a, int8x16x2_t b) {
vst1q_s8_x2(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_s16_x2(i16* %a, [2 x <8 x i16>] %b.coerce) #0 {
+// 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
@@ -15602,7 +14683,7 @@ void test_vst1q_s16_x2(int16_t *a, int16x8x2_t b) {
vst1q_s16_x2(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_s32_x2(i32* %a, [2 x <4 x i32>] %b.coerce) #0 {
+// 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
@@ -15628,7 +14709,7 @@ void test_vst1q_s32_x2(int32_t *a, int32x4x2_t b) {
vst1q_s32_x2(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_s64_x2(i64* %a, [2 x <2 x i64>] %b.coerce) #0 {
+// 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
@@ -15654,7 +14735,7 @@ void test_vst1q_s64_x2(int64_t *a, int64x2x2_t b) {
vst1q_s64_x2(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_f16_x2(half* %a, [2 x <8 x half>] %b.coerce) #0 {
+// 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
@@ -15680,7 +14761,7 @@ void test_vst1q_f16_x2(float16_t *a, float16x8x2_t b) {
vst1q_f16_x2(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_f32_x2(float* %a, [2 x <4 x float>] %b.coerce) #0 {
+// 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
@@ -15706,7 +14787,7 @@ void test_vst1q_f32_x2(float32_t *a, float32x4x2_t b) {
vst1q_f32_x2(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_f64_x2(double* %a, [2 x <2 x double>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst1q_f64_x2(
// CHECK: [[B:%.*]] = alloca %struct.float64x2x2_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.float64x2x2_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float64x2x2_t, %struct.float64x2x2_t* [[B]], i32 0, i32 0
@@ -15732,7 +14813,7 @@ void test_vst1q_f64_x2(float64_t *a, float64x2x2_t b) {
vst1q_f64_x2(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_p8_x2(i8* %a, [2 x <16 x i8>] %b.coerce) #0 {
+// 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
@@ -15752,7 +14833,7 @@ void test_vst1q_p8_x2(poly8_t *a, poly8x16x2_t b) {
vst1q_p8_x2(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_p16_x2(i16* %a, [2 x <8 x i16>] %b.coerce) #0 {
+// 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
@@ -15778,7 +14859,7 @@ void test_vst1q_p16_x2(poly16_t *a, poly16x8x2_t b) {
vst1q_p16_x2(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_p64_x2(i64* %a, [2 x <2 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst1q_p64_x2(
// CHECK: [[B:%.*]] = alloca %struct.poly64x2x2_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.poly64x2x2_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly64x2x2_t, %struct.poly64x2x2_t* [[B]], i32 0, i32 0
@@ -15804,7 +14885,7 @@ void test_vst1q_p64_x2(poly64_t *a, poly64x2x2_t b) {
vst1q_p64_x2(a, b);
}
-// CHECK-LABEL: define void @test_vst1_u8_x2(i8* %a, [2 x <8 x i8>] %b.coerce) #0 {
+// 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
@@ -15824,7 +14905,7 @@ void test_vst1_u8_x2(uint8_t *a, uint8x8x2_t b) {
vst1_u8_x2(a, b);
}
-// CHECK-LABEL: define void @test_vst1_u16_x2(i16* %a, [2 x <4 x i16>] %b.coerce) #0 {
+// 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
@@ -15850,7 +14931,7 @@ void test_vst1_u16_x2(uint16_t *a, uint16x4x2_t b) {
vst1_u16_x2(a, b);
}
-// CHECK-LABEL: define void @test_vst1_u32_x2(i32* %a, [2 x <2 x i32>] %b.coerce) #0 {
+// 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
@@ -15876,7 +14957,7 @@ void test_vst1_u32_x2(uint32_t *a, uint32x2x2_t b) {
vst1_u32_x2(a, b);
}
-// CHECK-LABEL: define void @test_vst1_u64_x2(i64* %a, [2 x <1 x i64>] %b.coerce) #0 {
+// 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
@@ -15902,7 +14983,7 @@ void test_vst1_u64_x2(uint64_t *a, uint64x1x2_t b) {
vst1_u64_x2(a, b);
}
-// CHECK-LABEL: define void @test_vst1_s8_x2(i8* %a, [2 x <8 x i8>] %b.coerce) #0 {
+// 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
@@ -15922,7 +15003,7 @@ void test_vst1_s8_x2(int8_t *a, int8x8x2_t b) {
vst1_s8_x2(a, b);
}
-// CHECK-LABEL: define void @test_vst1_s16_x2(i16* %a, [2 x <4 x i16>] %b.coerce) #0 {
+// 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
@@ -15948,7 +15029,7 @@ void test_vst1_s16_x2(int16_t *a, int16x4x2_t b) {
vst1_s16_x2(a, b);
}
-// CHECK-LABEL: define void @test_vst1_s32_x2(i32* %a, [2 x <2 x i32>] %b.coerce) #0 {
+// 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
@@ -15974,7 +15055,7 @@ void test_vst1_s32_x2(int32_t *a, int32x2x2_t b) {
vst1_s32_x2(a, b);
}
-// CHECK-LABEL: define void @test_vst1_s64_x2(i64* %a, [2 x <1 x i64>] %b.coerce) #0 {
+// 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
@@ -16000,7 +15081,7 @@ void test_vst1_s64_x2(int64_t *a, int64x1x2_t b) {
vst1_s64_x2(a, b);
}
-// CHECK-LABEL: define void @test_vst1_f16_x2(half* %a, [2 x <4 x half>] %b.coerce) #0 {
+// 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
@@ -16026,7 +15107,7 @@ void test_vst1_f16_x2(float16_t *a, float16x4x2_t b) {
vst1_f16_x2(a, b);
}
-// CHECK-LABEL: define void @test_vst1_f32_x2(float* %a, [2 x <2 x float>] %b.coerce) #0 {
+// 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
@@ -16052,7 +15133,7 @@ void test_vst1_f32_x2(float32_t *a, float32x2x2_t b) {
vst1_f32_x2(a, b);
}
-// CHECK-LABEL: define void @test_vst1_f64_x2(double* %a, [2 x <1 x double>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst1_f64_x2(
// CHECK: [[B:%.*]] = alloca %struct.float64x1x2_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.float64x1x2_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float64x1x2_t, %struct.float64x1x2_t* [[B]], i32 0, i32 0
@@ -16078,7 +15159,7 @@ void test_vst1_f64_x2(float64_t *a, float64x1x2_t b) {
vst1_f64_x2(a, b);
}
-// CHECK-LABEL: define void @test_vst1_p8_x2(i8* %a, [2 x <8 x i8>] %b.coerce) #0 {
+// 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
@@ -16098,7 +15179,7 @@ void test_vst1_p8_x2(poly8_t *a, poly8x8x2_t b) {
vst1_p8_x2(a, b);
}
-// CHECK-LABEL: define void @test_vst1_p16_x2(i16* %a, [2 x <4 x i16>] %b.coerce) #0 {
+// 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
@@ -16124,7 +15205,7 @@ void test_vst1_p16_x2(poly16_t *a, poly16x4x2_t b) {
vst1_p16_x2(a, b);
}
-// CHECK-LABEL: define void @test_vst1_p64_x2(i64* %a, [2 x <1 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst1_p64_x2(
// CHECK: [[B:%.*]] = alloca %struct.poly64x1x2_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.poly64x1x2_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly64x1x2_t, %struct.poly64x1x2_t* [[B]], i32 0, i32 0
@@ -16150,7 +15231,7 @@ void test_vst1_p64_x2(poly64_t *a, poly64x1x2_t b) {
vst1_p64_x2(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_u8_x3(i8* %a, [3 x <16 x i8>] %b.coerce) #0 {
+// 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
@@ -16173,7 +15254,7 @@ void test_vst1q_u8_x3(uint8_t *a, uint8x16x3_t b) {
vst1q_u8_x3(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_u16_x3(i16* %a, [3 x <8 x i16>] %b.coerce) #0 {
+// 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
@@ -16204,7 +15285,7 @@ void test_vst1q_u16_x3(uint16_t *a, uint16x8x3_t b) {
vst1q_u16_x3(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_u32_x3(i32* %a, [3 x <4 x i32>] %b.coerce) #0 {
+// 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
@@ -16235,7 +15316,7 @@ void test_vst1q_u32_x3(uint32_t *a, uint32x4x3_t b) {
vst1q_u32_x3(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_u64_x3(i64* %a, [3 x <2 x i64>] %b.coerce) #0 {
+// 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
@@ -16266,7 +15347,7 @@ void test_vst1q_u64_x3(uint64_t *a, uint64x2x3_t b) {
vst1q_u64_x3(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_s8_x3(i8* %a, [3 x <16 x i8>] %b.coerce) #0 {
+// 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
@@ -16289,7 +15370,7 @@ void test_vst1q_s8_x3(int8_t *a, int8x16x3_t b) {
vst1q_s8_x3(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_s16_x3(i16* %a, [3 x <8 x i16>] %b.coerce) #0 {
+// 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
@@ -16320,7 +15401,7 @@ void test_vst1q_s16_x3(int16_t *a, int16x8x3_t b) {
vst1q_s16_x3(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_s32_x3(i32* %a, [3 x <4 x i32>] %b.coerce) #0 {
+// 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
@@ -16351,7 +15432,7 @@ void test_vst1q_s32_x3(int32_t *a, int32x4x3_t b) {
vst1q_s32_x3(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_s64_x3(i64* %a, [3 x <2 x i64>] %b.coerce) #0 {
+// 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
@@ -16382,7 +15463,7 @@ void test_vst1q_s64_x3(int64_t *a, int64x2x3_t b) {
vst1q_s64_x3(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_f16_x3(half* %a, [3 x <8 x half>] %b.coerce) #0 {
+// 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
@@ -16413,7 +15494,7 @@ void test_vst1q_f16_x3(float16_t *a, float16x8x3_t b) {
vst1q_f16_x3(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_f32_x3(float* %a, [3 x <4 x float>] %b.coerce) #0 {
+// 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
@@ -16444,7 +15525,7 @@ void test_vst1q_f32_x3(float32_t *a, float32x4x3_t b) {
vst1q_f32_x3(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_f64_x3(double* %a, [3 x <2 x double>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst1q_f64_x3(
// CHECK: [[B:%.*]] = alloca %struct.float64x2x3_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.float64x2x3_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float64x2x3_t, %struct.float64x2x3_t* [[B]], i32 0, i32 0
@@ -16475,7 +15556,7 @@ void test_vst1q_f64_x3(float64_t *a, float64x2x3_t b) {
vst1q_f64_x3(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_p8_x3(i8* %a, [3 x <16 x i8>] %b.coerce) #0 {
+// 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
@@ -16498,7 +15579,7 @@ void test_vst1q_p8_x3(poly8_t *a, poly8x16x3_t b) {
vst1q_p8_x3(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_p16_x3(i16* %a, [3 x <8 x i16>] %b.coerce) #0 {
+// 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
@@ -16529,7 +15610,7 @@ void test_vst1q_p16_x3(poly16_t *a, poly16x8x3_t b) {
vst1q_p16_x3(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_p64_x3(i64* %a, [3 x <2 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst1q_p64_x3(
// CHECK: [[B:%.*]] = alloca %struct.poly64x2x3_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.poly64x2x3_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly64x2x3_t, %struct.poly64x2x3_t* [[B]], i32 0, i32 0
@@ -16560,7 +15641,7 @@ void test_vst1q_p64_x3(poly64_t *a, poly64x2x3_t b) {
vst1q_p64_x3(a, b);
}
-// CHECK-LABEL: define void @test_vst1_u8_x3(i8* %a, [3 x <8 x i8>] %b.coerce) #0 {
+// 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
@@ -16583,7 +15664,7 @@ void test_vst1_u8_x3(uint8_t *a, uint8x8x3_t b) {
vst1_u8_x3(a, b);
}
-// CHECK-LABEL: define void @test_vst1_u16_x3(i16* %a, [3 x <4 x i16>] %b.coerce) #0 {
+// 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
@@ -16614,7 +15695,7 @@ void test_vst1_u16_x3(uint16_t *a, uint16x4x3_t b) {
vst1_u16_x3(a, b);
}
-// CHECK-LABEL: define void @test_vst1_u32_x3(i32* %a, [3 x <2 x i32>] %b.coerce) #0 {
+// 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
@@ -16645,7 +15726,7 @@ void test_vst1_u32_x3(uint32_t *a, uint32x2x3_t b) {
vst1_u32_x3(a, b);
}
-// CHECK-LABEL: define void @test_vst1_u64_x3(i64* %a, [3 x <1 x i64>] %b.coerce) #0 {
+// 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
@@ -16676,7 +15757,7 @@ void test_vst1_u64_x3(uint64_t *a, uint64x1x3_t b) {
vst1_u64_x3(a, b);
}
-// CHECK-LABEL: define void @test_vst1_s8_x3(i8* %a, [3 x <8 x i8>] %b.coerce) #0 {
+// 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
@@ -16699,7 +15780,7 @@ void test_vst1_s8_x3(int8_t *a, int8x8x3_t b) {
vst1_s8_x3(a, b);
}
-// CHECK-LABEL: define void @test_vst1_s16_x3(i16* %a, [3 x <4 x i16>] %b.coerce) #0 {
+// 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
@@ -16730,7 +15811,7 @@ void test_vst1_s16_x3(int16_t *a, int16x4x3_t b) {
vst1_s16_x3(a, b);
}
-// CHECK-LABEL: define void @test_vst1_s32_x3(i32* %a, [3 x <2 x i32>] %b.coerce) #0 {
+// 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
@@ -16761,7 +15842,7 @@ void test_vst1_s32_x3(int32_t *a, int32x2x3_t b) {
vst1_s32_x3(a, b);
}
-// CHECK-LABEL: define void @test_vst1_s64_x3(i64* %a, [3 x <1 x i64>] %b.coerce) #0 {
+// 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
@@ -16792,7 +15873,7 @@ void test_vst1_s64_x3(int64_t *a, int64x1x3_t b) {
vst1_s64_x3(a, b);
}
-// CHECK-LABEL: define void @test_vst1_f16_x3(half* %a, [3 x <4 x half>] %b.coerce) #0 {
+// 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
@@ -16823,7 +15904,7 @@ void test_vst1_f16_x3(float16_t *a, float16x4x3_t b) {
vst1_f16_x3(a, b);
}
-// CHECK-LABEL: define void @test_vst1_f32_x3(float* %a, [3 x <2 x float>] %b.coerce) #0 {
+// 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
@@ -16854,7 +15935,7 @@ void test_vst1_f32_x3(float32_t *a, float32x2x3_t b) {
vst1_f32_x3(a, b);
}
-// CHECK-LABEL: define void @test_vst1_f64_x3(double* %a, [3 x <1 x double>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst1_f64_x3(
// CHECK: [[B:%.*]] = alloca %struct.float64x1x3_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.float64x1x3_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float64x1x3_t, %struct.float64x1x3_t* [[B]], i32 0, i32 0
@@ -16885,7 +15966,7 @@ void test_vst1_f64_x3(float64_t *a, float64x1x3_t b) {
vst1_f64_x3(a, b);
}
-// CHECK-LABEL: define void @test_vst1_p8_x3(i8* %a, [3 x <8 x i8>] %b.coerce) #0 {
+// 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
@@ -16908,7 +15989,7 @@ void test_vst1_p8_x3(poly8_t *a, poly8x8x3_t b) {
vst1_p8_x3(a, b);
}
-// CHECK-LABEL: define void @test_vst1_p16_x3(i16* %a, [3 x <4 x i16>] %b.coerce) #0 {
+// 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
@@ -16939,7 +16020,7 @@ void test_vst1_p16_x3(poly16_t *a, poly16x4x3_t b) {
vst1_p16_x3(a, b);
}
-// CHECK-LABEL: define void @test_vst1_p64_x3(i64* %a, [3 x <1 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst1_p64_x3(
// CHECK: [[B:%.*]] = alloca %struct.poly64x1x3_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.poly64x1x3_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly64x1x3_t, %struct.poly64x1x3_t* [[B]], i32 0, i32 0
@@ -16970,7 +16051,7 @@ void test_vst1_p64_x3(poly64_t *a, poly64x1x3_t b) {
vst1_p64_x3(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_u8_x4(i8* %a, [4 x <16 x i8>] %b.coerce) #0 {
+// 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
@@ -16996,7 +16077,7 @@ void test_vst1q_u8_x4(uint8_t *a, uint8x16x4_t b) {
vst1q_u8_x4(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_u16_x4(i16* %a, [4 x <8 x i16>] %b.coerce) #0 {
+// 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
@@ -17032,7 +16113,7 @@ void test_vst1q_u16_x4(uint16_t *a, uint16x8x4_t b) {
vst1q_u16_x4(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_u32_x4(i32* %a, [4 x <4 x i32>] %b.coerce) #0 {
+// 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
@@ -17068,7 +16149,7 @@ void test_vst1q_u32_x4(uint32_t *a, uint32x4x4_t b) {
vst1q_u32_x4(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_u64_x4(i64* %a, [4 x <2 x i64>] %b.coerce) #0 {
+// 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
@@ -17104,7 +16185,7 @@ void test_vst1q_u64_x4(uint64_t *a, uint64x2x4_t b) {
vst1q_u64_x4(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_s8_x4(i8* %a, [4 x <16 x i8>] %b.coerce) #0 {
+// 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
@@ -17130,7 +16211,7 @@ void test_vst1q_s8_x4(int8_t *a, int8x16x4_t b) {
vst1q_s8_x4(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_s16_x4(i16* %a, [4 x <8 x i16>] %b.coerce) #0 {
+// 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
@@ -17166,7 +16247,7 @@ void test_vst1q_s16_x4(int16_t *a, int16x8x4_t b) {
vst1q_s16_x4(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_s32_x4(i32* %a, [4 x <4 x i32>] %b.coerce) #0 {
+// 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
@@ -17202,7 +16283,7 @@ void test_vst1q_s32_x4(int32_t *a, int32x4x4_t b) {
vst1q_s32_x4(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_s64_x4(i64* %a, [4 x <2 x i64>] %b.coerce) #0 {
+// 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
@@ -17238,7 +16319,7 @@ void test_vst1q_s64_x4(int64_t *a, int64x2x4_t b) {
vst1q_s64_x4(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_f16_x4(half* %a, [4 x <8 x half>] %b.coerce) #0 {
+// 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
@@ -17274,7 +16355,7 @@ void test_vst1q_f16_x4(float16_t *a, float16x8x4_t b) {
vst1q_f16_x4(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_f32_x4(float* %a, [4 x <4 x float>] %b.coerce) #0 {
+// 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
@@ -17310,7 +16391,7 @@ void test_vst1q_f32_x4(float32_t *a, float32x4x4_t b) {
vst1q_f32_x4(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_f64_x4(double* %a, [4 x <2 x double>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst1q_f64_x4(
// CHECK: [[B:%.*]] = alloca %struct.float64x2x4_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.float64x2x4_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float64x2x4_t, %struct.float64x2x4_t* [[B]], i32 0, i32 0
@@ -17346,7 +16427,7 @@ void test_vst1q_f64_x4(float64_t *a, float64x2x4_t b) {
vst1q_f64_x4(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_p8_x4(i8* %a, [4 x <16 x i8>] %b.coerce) #0 {
+// 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
@@ -17372,7 +16453,7 @@ void test_vst1q_p8_x4(poly8_t *a, poly8x16x4_t b) {
vst1q_p8_x4(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_p16_x4(i16* %a, [4 x <8 x i16>] %b.coerce) #0 {
+// 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
@@ -17408,7 +16489,7 @@ void test_vst1q_p16_x4(poly16_t *a, poly16x8x4_t b) {
vst1q_p16_x4(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_p64_x4(i64* %a, [4 x <2 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst1q_p64_x4(
// CHECK: [[B:%.*]] = alloca %struct.poly64x2x4_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.poly64x2x4_t, align 16
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly64x2x4_t, %struct.poly64x2x4_t* [[B]], i32 0, i32 0
@@ -17444,7 +16525,7 @@ void test_vst1q_p64_x4(poly64_t *a, poly64x2x4_t b) {
vst1q_p64_x4(a, b);
}
-// CHECK-LABEL: define void @test_vst1_u8_x4(i8* %a, [4 x <8 x i8>] %b.coerce) #0 {
+// 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
@@ -17470,7 +16551,7 @@ void test_vst1_u8_x4(uint8_t *a, uint8x8x4_t b) {
vst1_u8_x4(a, b);
}
-// CHECK-LABEL: define void @test_vst1_u16_x4(i16* %a, [4 x <4 x i16>] %b.coerce) #0 {
+// 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
@@ -17506,7 +16587,7 @@ void test_vst1_u16_x4(uint16_t *a, uint16x4x4_t b) {
vst1_u16_x4(a, b);
}
-// CHECK-LABEL: define void @test_vst1_u32_x4(i32* %a, [4 x <2 x i32>] %b.coerce) #0 {
+// 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
@@ -17542,7 +16623,7 @@ void test_vst1_u32_x4(uint32_t *a, uint32x2x4_t b) {
vst1_u32_x4(a, b);
}
-// CHECK-LABEL: define void @test_vst1_u64_x4(i64* %a, [4 x <1 x i64>] %b.coerce) #0 {
+// 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
@@ -17578,7 +16659,7 @@ void test_vst1_u64_x4(uint64_t *a, uint64x1x4_t b) {
vst1_u64_x4(a, b);
}
-// CHECK-LABEL: define void @test_vst1_s8_x4(i8* %a, [4 x <8 x i8>] %b.coerce) #0 {
+// 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
@@ -17604,7 +16685,7 @@ void test_vst1_s8_x4(int8_t *a, int8x8x4_t b) {
vst1_s8_x4(a, b);
}
-// CHECK-LABEL: define void @test_vst1_s16_x4(i16* %a, [4 x <4 x i16>] %b.coerce) #0 {
+// 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
@@ -17640,7 +16721,7 @@ void test_vst1_s16_x4(int16_t *a, int16x4x4_t b) {
vst1_s16_x4(a, b);
}
-// CHECK-LABEL: define void @test_vst1_s32_x4(i32* %a, [4 x <2 x i32>] %b.coerce) #0 {
+// 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
@@ -17676,7 +16757,7 @@ void test_vst1_s32_x4(int32_t *a, int32x2x4_t b) {
vst1_s32_x4(a, b);
}
-// CHECK-LABEL: define void @test_vst1_s64_x4(i64* %a, [4 x <1 x i64>] %b.coerce) #0 {
+// 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
@@ -17712,7 +16793,7 @@ void test_vst1_s64_x4(int64_t *a, int64x1x4_t b) {
vst1_s64_x4(a, b);
}
-// CHECK-LABEL: define void @test_vst1_f16_x4(half* %a, [4 x <4 x half>] %b.coerce) #0 {
+// 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
@@ -17748,7 +16829,7 @@ void test_vst1_f16_x4(float16_t *a, float16x4x4_t b) {
vst1_f16_x4(a, b);
}
-// CHECK-LABEL: define void @test_vst1_f32_x4(float* %a, [4 x <2 x float>] %b.coerce) #0 {
+// 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
@@ -17784,7 +16865,7 @@ void test_vst1_f32_x4(float32_t *a, float32x2x4_t b) {
vst1_f32_x4(a, b);
}
-// CHECK-LABEL: define void @test_vst1_f64_x4(double* %a, [4 x <1 x double>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst1_f64_x4(
// CHECK: [[B:%.*]] = alloca %struct.float64x1x4_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.float64x1x4_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.float64x1x4_t, %struct.float64x1x4_t* [[B]], i32 0, i32 0
@@ -17820,7 +16901,7 @@ void test_vst1_f64_x4(float64_t *a, float64x1x4_t b) {
vst1_f64_x4(a, b);
}
-// CHECK-LABEL: define void @test_vst1_p8_x4(i8* %a, [4 x <8 x i8>] %b.coerce) #0 {
+// 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
@@ -17846,7 +16927,7 @@ void test_vst1_p8_x4(poly8_t *a, poly8x8x4_t b) {
vst1_p8_x4(a, b);
}
-// CHECK-LABEL: define void @test_vst1_p16_x4(i16* %a, [4 x <4 x i16>] %b.coerce) #0 {
+// 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
@@ -17882,7 +16963,7 @@ void test_vst1_p16_x4(poly16_t *a, poly16x4x4_t b) {
vst1_p16_x4(a, b);
}
-// CHECK-LABEL: define void @test_vst1_p64_x4(i64* %a, [4 x <1 x i64>] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst1_p64_x4(
// CHECK: [[B:%.*]] = alloca %struct.poly64x1x4_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.poly64x1x4_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly64x1x4_t, %struct.poly64x1x4_t* [[B]], i32 0, i32 0
@@ -17918,7 +16999,7 @@ void test_vst1_p64_x4(poly64_t *a, poly64x1x4_t b) {
vst1_p64_x4(a, b);
}
-// CHECK-LABEL: define i64 @test_vceqd_s64(i64 %a, i64 %b) #0 {
+// CHECK-LABEL: @test_vceqd_s64(
// CHECK: [[TMP0:%.*]] = icmp eq i64 %a, %b
// CHECK: [[VCEQD_I:%.*]] = sext i1 [[TMP0]] to i64
// CHECK: ret i64 [[VCEQD_I]]
@@ -17926,7 +17007,7 @@ int64_t test_vceqd_s64(int64_t a, int64_t b) {
return (int64_t)vceqd_s64(a, b);
}
-// CHECK-LABEL: define i64 @test_vceqd_u64(i64 %a, i64 %b) #0 {
+// CHECK-LABEL: @test_vceqd_u64(
// CHECK: [[TMP0:%.*]] = icmp eq i64 %a, %b
// CHECK: [[VCEQD_I:%.*]] = sext i1 [[TMP0]] to i64
// CHECK: ret i64 [[VCEQD_I]]
@@ -17934,7 +17015,7 @@ uint64_t test_vceqd_u64(uint64_t a, uint64_t b) {
return (int64_t)vceqd_u64(a, b);
}
-// CHECK-LABEL: define i64 @test_vceqzd_s64(i64 %a) #0 {
+// CHECK-LABEL: @test_vceqzd_s64(
// CHECK: [[TMP0:%.*]] = icmp eq i64 %a, 0
// CHECK: [[VCEQZ_I:%.*]] = sext i1 [[TMP0]] to i64
// CHECK: ret i64 [[VCEQZ_I]]
@@ -17942,7 +17023,7 @@ int64_t test_vceqzd_s64(int64_t a) {
return (int64_t)vceqzd_s64(a);
}
-// CHECK-LABEL: define i64 @test_vceqzd_u64(i64 %a) #0 {
+// CHECK-LABEL: @test_vceqzd_u64(
// CHECK: [[TMP0:%.*]] = icmp eq i64 %a, 0
// CHECK: [[VCEQZD_I:%.*]] = sext i1 [[TMP0]] to i64
// CHECK: ret i64 [[VCEQZD_I]]
@@ -17950,7 +17031,7 @@ int64_t test_vceqzd_u64(int64_t a) {
return (int64_t)vceqzd_u64(a);
}
-// CHECK-LABEL: define i64 @test_vcged_s64(i64 %a, i64 %b) #0 {
+// CHECK-LABEL: @test_vcged_s64(
// CHECK: [[TMP0:%.*]] = icmp sge i64 %a, %b
// CHECK: [[VCEQD_I:%.*]] = sext i1 [[TMP0]] to i64
// CHECK: ret i64 [[VCEQD_I]]
@@ -17958,15 +17039,15 @@ int64_t test_vcged_s64(int64_t a, int64_t b) {
return (int64_t)vcged_s64(a, b);
}
-// CHECK-LABEL: define i64 @test_vcged_u64(i64 %a, i64 %b) #0 {
+// CHECK-LABEL: @test_vcged_u64(
// CHECK: [[TMP0:%.*]] = icmp uge i64 %a, %b
// CHECK: [[VCEQD_I:%.*]] = sext i1 [[TMP0]] to i64
// CHECK: ret i64 [[VCEQD_I]]
uint64_t test_vcged_u64(uint64_t a, uint64_t b) {
- return (uint64_t)vcged_u64(a, b);
+ return (uint64_t)vcged_u64(a, b);
}
-// CHECK-LABEL: define i64 @test_vcgezd_s64(i64 %a) #0 {
+// CHECK-LABEL: @test_vcgezd_s64(
// CHECK: [[TMP0:%.*]] = icmp sge i64 %a, 0
// CHECK: [[VCGEZ_I:%.*]] = sext i1 [[TMP0]] to i64
// CHECK: ret i64 [[VCGEZ_I]]
@@ -17974,7 +17055,7 @@ int64_t test_vcgezd_s64(int64_t a) {
return (int64_t)vcgezd_s64(a);
}
-// CHECK-LABEL: define i64 @test_vcgtd_s64(i64 %a, i64 %b) #0 {
+// CHECK-LABEL: @test_vcgtd_s64(
// CHECK: [[TMP0:%.*]] = icmp sgt i64 %a, %b
// CHECK: [[VCEQD_I:%.*]] = sext i1 [[TMP0]] to i64
// CHECK: ret i64 [[VCEQD_I]]
@@ -17982,7 +17063,7 @@ int64_t test_vcgtd_s64(int64_t a, int64_t b) {
return (int64_t)vcgtd_s64(a, b);
}
-// CHECK-LABEL: define i64 @test_vcgtd_u64(i64 %a, i64 %b) #0 {
+// CHECK-LABEL: @test_vcgtd_u64(
// CHECK: [[TMP0:%.*]] = icmp ugt i64 %a, %b
// CHECK: [[VCEQD_I:%.*]] = sext i1 [[TMP0]] to i64
// CHECK: ret i64 [[VCEQD_I]]
@@ -17990,7 +17071,7 @@ uint64_t test_vcgtd_u64(uint64_t a, uint64_t b) {
return (uint64_t)vcgtd_u64(a, b);
}
-// CHECK-LABEL: define i64 @test_vcgtzd_s64(i64 %a) #0 {
+// CHECK-LABEL: @test_vcgtzd_s64(
// CHECK: [[TMP0:%.*]] = icmp sgt i64 %a, 0
// CHECK: [[VCGTZ_I:%.*]] = sext i1 [[TMP0]] to i64
// CHECK: ret i64 [[VCGTZ_I]]
@@ -17998,7 +17079,7 @@ int64_t test_vcgtzd_s64(int64_t a) {
return (int64_t)vcgtzd_s64(a);
}
-// CHECK-LABEL: define i64 @test_vcled_s64(i64 %a, i64 %b) #0 {
+// CHECK-LABEL: @test_vcled_s64(
// CHECK: [[TMP0:%.*]] = icmp sle i64 %a, %b
// CHECK: [[VCEQD_I:%.*]] = sext i1 [[TMP0]] to i64
// CHECK: ret i64 [[VCEQD_I]]
@@ -18006,7 +17087,7 @@ int64_t test_vcled_s64(int64_t a, int64_t b) {
return (int64_t)vcled_s64(a, b);
}
-// CHECK-LABEL: define i64 @test_vcled_u64(i64 %a, i64 %b) #0 {
+// CHECK-LABEL: @test_vcled_u64(
// CHECK: [[TMP0:%.*]] = icmp ule i64 %a, %b
// CHECK: [[VCEQD_I:%.*]] = sext i1 [[TMP0]] to i64
// CHECK: ret i64 [[VCEQD_I]]
@@ -18014,7 +17095,7 @@ uint64_t test_vcled_u64(uint64_t a, uint64_t b) {
return (uint64_t)vcled_u64(a, b);
}
-// CHECK-LABEL: define i64 @test_vclezd_s64(i64 %a) #0 {
+// CHECK-LABEL: @test_vclezd_s64(
// CHECK: [[TMP0:%.*]] = icmp sle i64 %a, 0
// CHECK: [[VCLEZ_I:%.*]] = sext i1 [[TMP0]] to i64
// CHECK: ret i64 [[VCLEZ_I]]
@@ -18022,7 +17103,7 @@ int64_t test_vclezd_s64(int64_t a) {
return (int64_t)vclezd_s64(a);
}
-// CHECK-LABEL: define i64 @test_vcltd_s64(i64 %a, i64 %b) #0 {
+// CHECK-LABEL: @test_vcltd_s64(
// CHECK: [[TMP0:%.*]] = icmp slt i64 %a, %b
// CHECK: [[VCEQD_I:%.*]] = sext i1 [[TMP0]] to i64
// CHECK: ret i64 [[VCEQD_I]]
@@ -18030,7 +17111,7 @@ int64_t test_vcltd_s64(int64_t a, int64_t b) {
return (int64_t)vcltd_s64(a, b);
}
-// CHECK-LABEL: define i64 @test_vcltd_u64(i64 %a, i64 %b) #0 {
+// CHECK-LABEL: @test_vcltd_u64(
// CHECK: [[TMP0:%.*]] = icmp ult i64 %a, %b
// CHECK: [[VCEQD_I:%.*]] = sext i1 [[TMP0]] to i64
// CHECK: ret i64 [[VCEQD_I]]
@@ -18038,7 +17119,7 @@ uint64_t test_vcltd_u64(uint64_t a, uint64_t b) {
return (uint64_t)vcltd_u64(a, b);
}
-// CHECK-LABEL: define i64 @test_vcltzd_s64(i64 %a) #0 {
+// CHECK-LABEL: @test_vcltzd_s64(
// CHECK: [[TMP0:%.*]] = icmp slt i64 %a, 0
// CHECK: [[VCLTZ_I:%.*]] = sext i1 [[TMP0]] to i64
// CHECK: ret i64 [[VCLTZ_I]]
@@ -18046,7 +17127,7 @@ int64_t test_vcltzd_s64(int64_t a) {
return (int64_t)vcltzd_s64(a);
}
-// CHECK-LABEL: define i64 @test_vtstd_s64(i64 %a, i64 %b) #0 {
+// CHECK-LABEL: @test_vtstd_s64(
// CHECK: [[TMP0:%.*]] = and i64 %a, %b
// CHECK: [[TMP1:%.*]] = icmp ne i64 [[TMP0]], 0
// CHECK: [[VTSTD_I:%.*]] = sext i1 [[TMP1]] to i64
@@ -18055,7 +17136,7 @@ int64_t test_vtstd_s64(int64_t a, int64_t b) {
return (int64_t)vtstd_s64(a, b);
}
-// CHECK-LABEL: define i64 @test_vtstd_u64(i64 %a, i64 %b) #0 {
+// CHECK-LABEL: @test_vtstd_u64(
// CHECK: [[TMP0:%.*]] = and i64 %a, %b
// CHECK: [[TMP1:%.*]] = icmp ne i64 [[TMP0]], 0
// CHECK: [[VTSTD_I:%.*]] = sext i1 [[TMP1]] to i64
@@ -18064,14 +17145,14 @@ uint64_t test_vtstd_u64(uint64_t a, uint64_t b) {
return (uint64_t)vtstd_u64(a, b);
}
-// CHECK-LABEL: define i64 @test_vabsd_s64(i64 %a) #0 {
+// CHECK-LABEL: @test_vabsd_s64(
// CHECK: [[VABSD_S64_I:%.*]] = call i64 @llvm.aarch64.neon.abs.i64(i64 %a) #4
// CHECK: ret i64 [[VABSD_S64_I]]
int64_t test_vabsd_s64(int64_t a) {
return (int64_t)vabsd_s64(a);
}
-// CHECK-LABEL: define i8 @test_vqabsb_s8(i8 %a) #0 {
+// CHECK-LABEL: @test_vqabsb_s8(
// CHECK: [[TMP0:%.*]] = insertelement <8 x i8> undef, i8 %a, i64 0
// CHECK: [[VQABSB_S8_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.sqabs.v8i8(<8 x i8> [[TMP0]]) #4
// CHECK: [[TMP1:%.*]] = extractelement <8 x i8> [[VQABSB_S8_I]], i64 0
@@ -18080,7 +17161,7 @@ int8_t test_vqabsb_s8(int8_t a) {
return (int8_t)vqabsb_s8(a);
}
-// CHECK-LABEL: define i16 @test_vqabsh_s16(i16 %a) #0 {
+// CHECK-LABEL: @test_vqabsh_s16(
// CHECK: [[TMP0:%.*]] = insertelement <4 x i16> undef, i16 %a, i64 0
// CHECK: [[VQABSH_S16_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqabs.v4i16(<4 x i16> [[TMP0]]) #4
// CHECK: [[TMP1:%.*]] = extractelement <4 x i16> [[VQABSH_S16_I]], i64 0
@@ -18089,28 +17170,28 @@ int16_t test_vqabsh_s16(int16_t a) {
return (int16_t)vqabsh_s16(a);
}
-// CHECK-LABEL: define i32 @test_vqabss_s32(i32 %a) #0 {
+// CHECK-LABEL: @test_vqabss_s32(
// CHECK: [[VQABSS_S32_I:%.*]] = call i32 @llvm.aarch64.neon.sqabs.i32(i32 %a) #4
// CHECK: ret i32 [[VQABSS_S32_I]]
int32_t test_vqabss_s32(int32_t a) {
return (int32_t)vqabss_s32(a);
}
-// CHECK-LABEL: define i64 @test_vqabsd_s64(i64 %a) #0 {
+// CHECK-LABEL: @test_vqabsd_s64(
// CHECK: [[VQABSD_S64_I:%.*]] = call i64 @llvm.aarch64.neon.sqabs.i64(i64 %a) #4
// CHECK: ret i64 [[VQABSD_S64_I]]
int64_t test_vqabsd_s64(int64_t a) {
return (int64_t)vqabsd_s64(a);
}
-// CHECK-LABEL: define i64 @test_vnegd_s64(i64 %a) #0 {
+// CHECK-LABEL: @test_vnegd_s64(
// CHECK: [[VNEGD_I:%.*]] = sub i64 0, %a
// CHECK: ret i64 [[VNEGD_I]]
int64_t test_vnegd_s64(int64_t a) {
return (int64_t)vnegd_s64(a);
}
-// CHECK-LABEL: define i8 @test_vqnegb_s8(i8 %a) #0 {
+// CHECK-LABEL: @test_vqnegb_s8(
// CHECK: [[TMP0:%.*]] = insertelement <8 x i8> undef, i8 %a, i64 0
// CHECK: [[VQNEGB_S8_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.sqneg.v8i8(<8 x i8> [[TMP0]]) #4
// CHECK: [[TMP1:%.*]] = extractelement <8 x i8> [[VQNEGB_S8_I]], i64 0
@@ -18119,7 +17200,7 @@ int8_t test_vqnegb_s8(int8_t a) {
return (int8_t)vqnegb_s8(a);
}
-// CHECK-LABEL: define i16 @test_vqnegh_s16(i16 %a) #0 {
+// CHECK-LABEL: @test_vqnegh_s16(
// CHECK: [[TMP0:%.*]] = insertelement <4 x i16> undef, i16 %a, i64 0
// CHECK: [[VQNEGH_S16_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqneg.v4i16(<4 x i16> [[TMP0]]) #4
// CHECK: [[TMP1:%.*]] = extractelement <4 x i16> [[VQNEGH_S16_I]], i64 0
@@ -18128,21 +17209,21 @@ int16_t test_vqnegh_s16(int16_t a) {
return (int16_t)vqnegh_s16(a);
}
-// CHECK-LABEL: define i32 @test_vqnegs_s32(i32 %a) #0 {
+// CHECK-LABEL: @test_vqnegs_s32(
// CHECK: [[VQNEGS_S32_I:%.*]] = call i32 @llvm.aarch64.neon.sqneg.i32(i32 %a) #4
// CHECK: ret i32 [[VQNEGS_S32_I]]
int32_t test_vqnegs_s32(int32_t a) {
return (int32_t)vqnegs_s32(a);
}
-// CHECK-LABEL: define i64 @test_vqnegd_s64(i64 %a) #0 {
+// CHECK-LABEL: @test_vqnegd_s64(
// CHECK: [[VQNEGD_S64_I:%.*]] = call i64 @llvm.aarch64.neon.sqneg.i64(i64 %a) #4
// CHECK: ret i64 [[VQNEGD_S64_I]]
int64_t test_vqnegd_s64(int64_t a) {
return (int64_t)vqnegd_s64(a);
}
-// CHECK-LABEL: define i8 @test_vuqaddb_s8(i8 %a, i8 %b) #0 {
+// CHECK-LABEL: @test_vuqaddb_s8(
// CHECK: [[TMP0:%.*]] = insertelement <8 x i8> undef, i8 %a, i64 0
// CHECK: [[TMP1:%.*]] = insertelement <8 x i8> undef, i8 %b, i64 0
// CHECK: [[VUQADDB_S8_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.suqadd.v8i8(<8 x i8> [[TMP0]], <8 x i8> [[TMP1]]) #4
@@ -18152,7 +17233,7 @@ int8_t test_vuqaddb_s8(int8_t a, int8_t b) {
return (int8_t)vuqaddb_s8(a, b);
}
-// CHECK-LABEL: define i16 @test_vuqaddh_s16(i16 %a, i16 %b) #0 {
+// CHECK-LABEL: @test_vuqaddh_s16(
// CHECK: [[TMP0:%.*]] = insertelement <4 x i16> undef, i16 %a, i64 0
// CHECK: [[TMP1:%.*]] = insertelement <4 x i16> undef, i16 %b, i64 0
// CHECK: [[VUQADDH_S16_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.suqadd.v4i16(<4 x i16> [[TMP0]], <4 x i16> [[TMP1]]) #4
@@ -18162,21 +17243,21 @@ int16_t test_vuqaddh_s16(int16_t a, int16_t b) {
return (int16_t)vuqaddh_s16(a, b);
}
-// CHECK-LABEL: define i32 @test_vuqadds_s32(i32 %a, i32 %b) #0 {
+// CHECK-LABEL: @test_vuqadds_s32(
// CHECK: [[VUQADDS_S32_I:%.*]] = call i32 @llvm.aarch64.neon.suqadd.i32(i32 %a, i32 %b) #4
// CHECK: ret i32 [[VUQADDS_S32_I]]
int32_t test_vuqadds_s32(int32_t a, int32_t b) {
return (int32_t)vuqadds_s32(a, b);
}
-// CHECK-LABEL: define i64 @test_vuqaddd_s64(i64 %a, i64 %b) #0 {
+// CHECK-LABEL: @test_vuqaddd_s64(
// CHECK: [[VUQADDD_S64_I:%.*]] = call i64 @llvm.aarch64.neon.suqadd.i64(i64 %a, i64 %b) #4
// CHECK: ret i64 [[VUQADDD_S64_I]]
int64_t test_vuqaddd_s64(int64_t a, int64_t b) {
return (int64_t)vuqaddd_s64(a, b);
}
-// CHECK-LABEL: define i8 @test_vsqaddb_u8(i8 %a, i8 %b) #0 {
+// CHECK-LABEL: @test_vsqaddb_u8(
// CHECK: [[TMP0:%.*]] = insertelement <8 x i8> undef, i8 %a, i64 0
// CHECK: [[TMP1:%.*]] = insertelement <8 x i8> undef, i8 %b, i64 0
// CHECK: [[VSQADDB_U8_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.usqadd.v8i8(<8 x i8> [[TMP0]], <8 x i8> [[TMP1]]) #4
@@ -18186,7 +17267,7 @@ uint8_t test_vsqaddb_u8(uint8_t a, uint8_t b) {
return (uint8_t)vsqaddb_u8(a, b);
}
-// CHECK-LABEL: define i16 @test_vsqaddh_u16(i16 %a, i16 %b) #0 {
+// CHECK-LABEL: @test_vsqaddh_u16(
// CHECK: [[TMP0:%.*]] = insertelement <4 x i16> undef, i16 %a, i64 0
// CHECK: [[TMP1:%.*]] = insertelement <4 x i16> undef, i16 %b, i64 0
// CHECK: [[VSQADDH_U16_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.usqadd.v4i16(<4 x i16> [[TMP0]], <4 x i16> [[TMP1]]) #4
@@ -18196,21 +17277,21 @@ uint16_t test_vsqaddh_u16(uint16_t a, uint16_t b) {
return (uint16_t)vsqaddh_u16(a, b);
}
-// CHECK-LABEL: define i32 @test_vsqadds_u32(i32 %a, i32 %b) #0 {
+// CHECK-LABEL: @test_vsqadds_u32(
// CHECK: [[VSQADDS_U32_I:%.*]] = call i32 @llvm.aarch64.neon.usqadd.i32(i32 %a, i32 %b) #4
// CHECK: ret i32 [[VSQADDS_U32_I]]
uint32_t test_vsqadds_u32(uint32_t a, uint32_t b) {
return (uint32_t)vsqadds_u32(a, b);
}
-// CHECK-LABEL: define i64 @test_vsqaddd_u64(i64 %a, i64 %b) #0 {
+// CHECK-LABEL: @test_vsqaddd_u64(
// CHECK: [[VSQADDD_U64_I:%.*]] = call i64 @llvm.aarch64.neon.usqadd.i64(i64 %a, i64 %b) #4
// CHECK: ret i64 [[VSQADDD_U64_I]]
uint64_t test_vsqaddd_u64(uint64_t a, uint64_t b) {
return (uint64_t)vsqaddd_u64(a, b);
}
-// CHECK-LABEL: define i32 @test_vqdmlalh_s16(i32 %a, i16 %b, i16 %c) #0 {
+// CHECK-LABEL: @test_vqdmlalh_s16(
// CHECK: [[TMP0:%.*]] = insertelement <4 x i16> undef, i16 %b, i64 0
// CHECK: [[TMP1:%.*]] = insertelement <4 x i16> undef, i16 %c, i64 0
// CHECK: [[VQDMLXL_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[TMP0]], <4 x i16> [[TMP1]]) #4
@@ -18218,11 +17299,10 @@ uint64_t test_vsqaddd_u64(uint64_t a, uint64_t b) {
// CHECK: [[VQDMLXL1_I:%.*]] = call i32 @llvm.aarch64.neon.sqadd.i32(i32 %a, i32 [[LANE0_I]]) #4
// CHECK: ret i32 [[VQDMLXL1_I]]
int32_t test_vqdmlalh_s16(int32_t a, int16_t b, int16_t c) {
-
return (int32_t)vqdmlalh_s16(a, b, c);
}
-// CHECK-LABEL: define i64 @test_vqdmlals_s32(i64 %a, i32 %b, i32 %c) #0 {
+// CHECK-LABEL: @test_vqdmlals_s32(
// CHECK: [[VQDMLXL_I:%.*]] = call i64 @llvm.aarch64.neon.sqdmulls.scalar(i32 %b, i32 %c) #4
// CHECK: [[VQDMLXL1_I:%.*]] = call i64 @llvm.aarch64.neon.sqadd.i64(i64 %a, i64 [[VQDMLXL_I]]) #4
// CHECK: ret i64 [[VQDMLXL1_I]]
@@ -18230,7 +17310,7 @@ int64_t test_vqdmlals_s32(int64_t a, int32_t b, int32_t c) {
return (int64_t)vqdmlals_s32(a, b, c);
}
-// CHECK-LABEL: define i32 @test_vqdmlslh_s16(i32 %a, i16 %b, i16 %c) #0 {
+// CHECK-LABEL: @test_vqdmlslh_s16(
// CHECK: [[TMP0:%.*]] = insertelement <4 x i16> undef, i16 %b, i64 0
// CHECK: [[TMP1:%.*]] = insertelement <4 x i16> undef, i16 %c, i64 0
// CHECK: [[VQDMLXL_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[TMP0]], <4 x i16> [[TMP1]]) #4
@@ -18238,11 +17318,10 @@ int64_t test_vqdmlals_s32(int64_t a, int32_t b, int32_t c) {
// CHECK: [[VQDMLXL1_I:%.*]] = call i32 @llvm.aarch64.neon.sqsub.i32(i32 %a, i32 [[LANE0_I]]) #4
// CHECK: ret i32 [[VQDMLXL1_I]]
int32_t test_vqdmlslh_s16(int32_t a, int16_t b, int16_t c) {
-
return (int32_t)vqdmlslh_s16(a, b, c);
}
-// CHECK-LABEL: define i64 @test_vqdmlsls_s32(i64 %a, i32 %b, i32 %c) #0 {
+// CHECK-LABEL: @test_vqdmlsls_s32(
// CHECK: [[VQDMLXL_I:%.*]] = call i64 @llvm.aarch64.neon.sqdmulls.scalar(i32 %b, i32 %c) #4
// CHECK: [[VQDMLXL1_I:%.*]] = call i64 @llvm.aarch64.neon.sqsub.i64(i64 %a, i64 [[VQDMLXL_I]]) #4
// CHECK: ret i64 [[VQDMLXL1_I]]
@@ -18250,7 +17329,7 @@ int64_t test_vqdmlsls_s32(int64_t a, int32_t b, int32_t c) {
return (int64_t)vqdmlsls_s32(a, b, c);
}
-// CHECK-LABEL: define i32 @test_vqdmullh_s16(i16 %a, i16 %b) #0 {
+// CHECK-LABEL: @test_vqdmullh_s16(
// CHECK: [[TMP0:%.*]] = insertelement <4 x i16> undef, i16 %a, i64 0
// CHECK: [[TMP1:%.*]] = insertelement <4 x i16> undef, i16 %b, i64 0
// CHECK: [[VQDMULLH_S16_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqdmull.v4i32(<4 x i16> [[TMP0]], <4 x i16> [[TMP1]]) #4
@@ -18260,14 +17339,14 @@ int32_t test_vqdmullh_s16(int16_t a, int16_t b) {
return (int32_t)vqdmullh_s16(a, b);
}
-// CHECK-LABEL: define i64 @test_vqdmulls_s32(i32 %a, i32 %b) #0 {
+// CHECK-LABEL: @test_vqdmulls_s32(
// CHECK: [[VQDMULLS_S32_I:%.*]] = call i64 @llvm.aarch64.neon.sqdmulls.scalar(i32 %a, i32 %b) #4
// CHECK: ret i64 [[VQDMULLS_S32_I]]
int64_t test_vqdmulls_s32(int32_t a, int32_t b) {
return (int64_t)vqdmulls_s32(a, b);
}
-// CHECK-LABEL: define i8 @test_vqmovunh_s16(i16 %a) #0 {
+// CHECK-LABEL: @test_vqmovunh_s16(
// CHECK: [[TMP0:%.*]] = insertelement <8 x i16> undef, i16 %a, i64 0
// CHECK: [[VQMOVUNH_S16_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.sqxtun.v8i8(<8 x i16> [[TMP0]]) #4
// CHECK: [[TMP1:%.*]] = extractelement <8 x i8> [[VQMOVUNH_S16_I]], i64 0
@@ -18276,7 +17355,7 @@ int8_t test_vqmovunh_s16(int16_t a) {
return (int8_t)vqmovunh_s16(a);
}
-// CHECK-LABEL: define i16 @test_vqmovuns_s32(i32 %a) #0 {
+// CHECK-LABEL: @test_vqmovuns_s32(
// CHECK: [[TMP0:%.*]] = insertelement <4 x i32> undef, i32 %a, i64 0
// CHECK: [[VQMOVUNS_S32_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqxtun.v4i16(<4 x i32> [[TMP0]]) #4
// CHECK: [[TMP1:%.*]] = extractelement <4 x i16> [[VQMOVUNS_S32_I]], i64 0
@@ -18285,14 +17364,14 @@ int16_t test_vqmovuns_s32(int32_t a) {
return (int16_t)vqmovuns_s32(a);
}
-// CHECK-LABEL: define i32 @test_vqmovund_s64(i64 %a) #0 {
+// CHECK-LABEL: @test_vqmovund_s64(
// CHECK: [[VQMOVUND_S64_I:%.*]] = call i32 @llvm.aarch64.neon.scalar.sqxtun.i32.i64(i64 %a) #4
// CHECK: ret i32 [[VQMOVUND_S64_I]]
int32_t test_vqmovund_s64(int64_t a) {
return (int32_t)vqmovund_s64(a);
}
-// CHECK-LABEL: define i8 @test_vqmovnh_s16(i16 %a) #0 {
+// CHECK-LABEL: @test_vqmovnh_s16(
// CHECK: [[TMP0:%.*]] = insertelement <8 x i16> undef, i16 %a, i64 0
// CHECK: [[VQMOVNH_S16_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.sqxtn.v8i8(<8 x i16> [[TMP0]]) #4
// CHECK: [[TMP1:%.*]] = extractelement <8 x i8> [[VQMOVNH_S16_I]], i64 0
@@ -18301,7 +17380,7 @@ int8_t test_vqmovnh_s16(int16_t a) {
return (int8_t)vqmovnh_s16(a);
}
-// CHECK-LABEL: define i16 @test_vqmovns_s32(i32 %a) #0 {
+// CHECK-LABEL: @test_vqmovns_s32(
// CHECK: [[TMP0:%.*]] = insertelement <4 x i32> undef, i32 %a, i64 0
// CHECK: [[VQMOVNS_S32_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqxtn.v4i16(<4 x i32> [[TMP0]]) #4
// CHECK: [[TMP1:%.*]] = extractelement <4 x i16> [[VQMOVNS_S32_I]], i64 0
@@ -18310,14 +17389,14 @@ int16_t test_vqmovns_s32(int32_t a) {
return (int16_t)vqmovns_s32(a);
}
-// CHECK-LABEL: define i32 @test_vqmovnd_s64(i64 %a) #0 {
+// CHECK-LABEL: @test_vqmovnd_s64(
// CHECK: [[VQMOVND_S64_I:%.*]] = call i32 @llvm.aarch64.neon.scalar.sqxtn.i32.i64(i64 %a) #4
// CHECK: ret i32 [[VQMOVND_S64_I]]
int32_t test_vqmovnd_s64(int64_t a) {
return (int32_t)vqmovnd_s64(a);
}
-// CHECK-LABEL: define i8 @test_vqmovnh_u16(i16 %a) #0 {
+// CHECK-LABEL: @test_vqmovnh_u16(
// CHECK: [[TMP0:%.*]] = insertelement <8 x i16> undef, i16 %a, i64 0
// CHECK: [[VQMOVNH_U16_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.uqxtn.v8i8(<8 x i16> [[TMP0]]) #4
// CHECK: [[TMP1:%.*]] = extractelement <8 x i8> [[VQMOVNH_U16_I]], i64 0
@@ -18326,7 +17405,7 @@ int8_t test_vqmovnh_u16(int16_t a) {
return (int8_t)vqmovnh_u16(a);
}
-// CHECK-LABEL: define i16 @test_vqmovns_u32(i32 %a) #0 {
+// CHECK-LABEL: @test_vqmovns_u32(
// CHECK: [[TMP0:%.*]] = insertelement <4 x i32> undef, i32 %a, i64 0
// CHECK: [[VQMOVNS_U32_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.uqxtn.v4i16(<4 x i32> [[TMP0]]) #4
// CHECK: [[TMP1:%.*]] = extractelement <4 x i16> [[VQMOVNS_U32_I]], i64 0
@@ -18335,14 +17414,14 @@ int16_t test_vqmovns_u32(int32_t a) {
return (int16_t)vqmovns_u32(a);
}
-// CHECK-LABEL: define i32 @test_vqmovnd_u64(i64 %a) #0 {
+// CHECK-LABEL: @test_vqmovnd_u64(
// CHECK: [[VQMOVND_U64_I:%.*]] = call i32 @llvm.aarch64.neon.scalar.uqxtn.i32.i64(i64 %a) #4
// CHECK: ret i32 [[VQMOVND_U64_I]]
int32_t test_vqmovnd_u64(int64_t a) {
return (int32_t)vqmovnd_u64(a);
}
-// CHECK-LABEL: define i32 @test_vceqs_f32(float %a, float %b) #0 {
+// CHECK-LABEL: @test_vceqs_f32(
// CHECK: [[TMP0:%.*]] = fcmp oeq float %a, %b
// CHECK: [[VCMPD_I:%.*]] = sext i1 [[TMP0]] to i32
// CHECK: ret i32 [[VCMPD_I]]
@@ -18350,7 +17429,7 @@ uint32_t test_vceqs_f32(float32_t a, float32_t b) {
return (uint32_t)vceqs_f32(a, b);
}
-// CHECK-LABEL: define i64 @test_vceqd_f64(double %a, double %b) #0 {
+// CHECK-LABEL: @test_vceqd_f64(
// CHECK: [[TMP0:%.*]] = fcmp oeq double %a, %b
// CHECK: [[VCMPD_I:%.*]] = sext i1 [[TMP0]] to i64
// CHECK: ret i64 [[VCMPD_I]]
@@ -18358,7 +17437,7 @@ uint64_t test_vceqd_f64(float64_t a, float64_t b) {
return (uint64_t)vceqd_f64(a, b);
}
-// CHECK-LABEL: define i32 @test_vceqzs_f32(float %a) #0 {
+// CHECK-LABEL: @test_vceqzs_f32(
// CHECK: [[TMP0:%.*]] = fcmp oeq float %a, 0.000000e+00
// CHECK: [[VCEQZ_I:%.*]] = sext i1 [[TMP0]] to i32
// CHECK: ret i32 [[VCEQZ_I]]
@@ -18366,7 +17445,7 @@ uint32_t test_vceqzs_f32(float32_t a) {
return (uint32_t)vceqzs_f32(a);
}
-// CHECK-LABEL: define i64 @test_vceqzd_f64(double %a) #0 {
+// CHECK-LABEL: @test_vceqzd_f64(
// CHECK: [[TMP0:%.*]] = fcmp oeq double %a, 0.000000e+00
// CHECK: [[VCEQZ_I:%.*]] = sext i1 [[TMP0]] to i64
// CHECK: ret i64 [[VCEQZ_I]]
@@ -18374,7 +17453,7 @@ uint64_t test_vceqzd_f64(float64_t a) {
return (uint64_t)vceqzd_f64(a);
}
-// CHECK-LABEL: define i32 @test_vcges_f32(float %a, float %b) #0 {
+// CHECK-LABEL: @test_vcges_f32(
// CHECK: [[TMP0:%.*]] = fcmp oge float %a, %b
// CHECK: [[VCMPD_I:%.*]] = sext i1 [[TMP0]] to i32
// CHECK: ret i32 [[VCMPD_I]]
@@ -18382,7 +17461,7 @@ uint32_t test_vcges_f32(float32_t a, float32_t b) {
return (uint32_t)vcges_f32(a, b);
}
-// CHECK-LABEL: define i64 @test_vcged_f64(double %a, double %b) #0 {
+// CHECK-LABEL: @test_vcged_f64(
// CHECK: [[TMP0:%.*]] = fcmp oge double %a, %b
// CHECK: [[VCMPD_I:%.*]] = sext i1 [[TMP0]] to i64
// CHECK: ret i64 [[VCMPD_I]]
@@ -18390,7 +17469,7 @@ uint64_t test_vcged_f64(float64_t a, float64_t b) {
return (uint64_t)vcged_f64(a, b);
}
-// CHECK-LABEL: define i32 @test_vcgezs_f32(float %a) #0 {
+// CHECK-LABEL: @test_vcgezs_f32(
// CHECK: [[TMP0:%.*]] = fcmp oge float %a, 0.000000e+00
// CHECK: [[VCGEZ_I:%.*]] = sext i1 [[TMP0]] to i32
// CHECK: ret i32 [[VCGEZ_I]]
@@ -18398,7 +17477,7 @@ uint32_t test_vcgezs_f32(float32_t a) {
return (uint32_t)vcgezs_f32(a);
}
-// CHECK-LABEL: define i64 @test_vcgezd_f64(double %a) #0 {
+// CHECK-LABEL: @test_vcgezd_f64(
// CHECK: [[TMP0:%.*]] = fcmp oge double %a, 0.000000e+00
// CHECK: [[VCGEZ_I:%.*]] = sext i1 [[TMP0]] to i64
// CHECK: ret i64 [[VCGEZ_I]]
@@ -18406,7 +17485,7 @@ uint64_t test_vcgezd_f64(float64_t a) {
return (uint64_t)vcgezd_f64(a);
}
-// CHECK-LABEL: define i32 @test_vcgts_f32(float %a, float %b) #0 {
+// CHECK-LABEL: @test_vcgts_f32(
// CHECK: [[TMP0:%.*]] = fcmp ogt float %a, %b
// CHECK: [[VCMPD_I:%.*]] = sext i1 [[TMP0]] to i32
// CHECK: ret i32 [[VCMPD_I]]
@@ -18414,7 +17493,7 @@ uint32_t test_vcgts_f32(float32_t a, float32_t b) {
return (uint32_t)vcgts_f32(a, b);
}
-// CHECK-LABEL: define i64 @test_vcgtd_f64(double %a, double %b) #0 {
+// CHECK-LABEL: @test_vcgtd_f64(
// CHECK: [[TMP0:%.*]] = fcmp ogt double %a, %b
// CHECK: [[VCMPD_I:%.*]] = sext i1 [[TMP0]] to i64
// CHECK: ret i64 [[VCMPD_I]]
@@ -18422,7 +17501,7 @@ uint64_t test_vcgtd_f64(float64_t a, float64_t b) {
return (uint64_t)vcgtd_f64(a, b);
}
-// CHECK-LABEL: define i32 @test_vcgtzs_f32(float %a) #0 {
+// CHECK-LABEL: @test_vcgtzs_f32(
// CHECK: [[TMP0:%.*]] = fcmp ogt float %a, 0.000000e+00
// CHECK: [[VCGTZ_I:%.*]] = sext i1 [[TMP0]] to i32
// CHECK: ret i32 [[VCGTZ_I]]
@@ -18430,7 +17509,7 @@ uint32_t test_vcgtzs_f32(float32_t a) {
return (uint32_t)vcgtzs_f32(a);
}
-// CHECK-LABEL: define i64 @test_vcgtzd_f64(double %a) #0 {
+// CHECK-LABEL: @test_vcgtzd_f64(
// CHECK: [[TMP0:%.*]] = fcmp ogt double %a, 0.000000e+00
// CHECK: [[VCGTZ_I:%.*]] = sext i1 [[TMP0]] to i64
// CHECK: ret i64 [[VCGTZ_I]]
@@ -18438,7 +17517,7 @@ uint64_t test_vcgtzd_f64(float64_t a) {
return (uint64_t)vcgtzd_f64(a);
}
-// CHECK-LABEL: define i32 @test_vcles_f32(float %a, float %b) #0 {
+// CHECK-LABEL: @test_vcles_f32(
// CHECK: [[TMP0:%.*]] = fcmp ole float %a, %b
// CHECK: [[VCMPD_I:%.*]] = sext i1 [[TMP0]] to i32
// CHECK: ret i32 [[VCMPD_I]]
@@ -18446,7 +17525,7 @@ uint32_t test_vcles_f32(float32_t a, float32_t b) {
return (uint32_t)vcles_f32(a, b);
}
-// CHECK-LABEL: define i64 @test_vcled_f64(double %a, double %b) #0 {
+// CHECK-LABEL: @test_vcled_f64(
// CHECK: [[TMP0:%.*]] = fcmp ole double %a, %b
// CHECK: [[VCMPD_I:%.*]] = sext i1 [[TMP0]] to i64
// CHECK: ret i64 [[VCMPD_I]]
@@ -18454,7 +17533,7 @@ uint64_t test_vcled_f64(float64_t a, float64_t b) {
return (uint64_t)vcled_f64(a, b);
}
-// CHECK-LABEL: define i32 @test_vclezs_f32(float %a) #0 {
+// CHECK-LABEL: @test_vclezs_f32(
// CHECK: [[TMP0:%.*]] = fcmp ole float %a, 0.000000e+00
// CHECK: [[VCLEZ_I:%.*]] = sext i1 [[TMP0]] to i32
// CHECK: ret i32 [[VCLEZ_I]]
@@ -18462,7 +17541,7 @@ uint32_t test_vclezs_f32(float32_t a) {
return (uint32_t)vclezs_f32(a);
}
-// CHECK-LABEL: define i64 @test_vclezd_f64(double %a) #0 {
+// CHECK-LABEL: @test_vclezd_f64(
// CHECK: [[TMP0:%.*]] = fcmp ole double %a, 0.000000e+00
// CHECK: [[VCLEZ_I:%.*]] = sext i1 [[TMP0]] to i64
// CHECK: ret i64 [[VCLEZ_I]]
@@ -18470,7 +17549,7 @@ uint64_t test_vclezd_f64(float64_t a) {
return (uint64_t)vclezd_f64(a);
}
-// CHECK-LABEL: define i32 @test_vclts_f32(float %a, float %b) #0 {
+// CHECK-LABEL: @test_vclts_f32(
// CHECK: [[TMP0:%.*]] = fcmp olt float %a, %b
// CHECK: [[VCMPD_I:%.*]] = sext i1 [[TMP0]] to i32
// CHECK: ret i32 [[VCMPD_I]]
@@ -18478,7 +17557,7 @@ uint32_t test_vclts_f32(float32_t a, float32_t b) {
return (uint32_t)vclts_f32(a, b);
}
-// CHECK-LABEL: define i64 @test_vcltd_f64(double %a, double %b) #0 {
+// CHECK-LABEL: @test_vcltd_f64(
// CHECK: [[TMP0:%.*]] = fcmp olt double %a, %b
// CHECK: [[VCMPD_I:%.*]] = sext i1 [[TMP0]] to i64
// CHECK: ret i64 [[VCMPD_I]]
@@ -18486,7 +17565,7 @@ uint64_t test_vcltd_f64(float64_t a, float64_t b) {
return (uint64_t)vcltd_f64(a, b);
}
-// CHECK-LABEL: define i32 @test_vcltzs_f32(float %a) #0 {
+// CHECK-LABEL: @test_vcltzs_f32(
// CHECK: [[TMP0:%.*]] = fcmp olt float %a, 0.000000e+00
// CHECK: [[VCLTZ_I:%.*]] = sext i1 [[TMP0]] to i32
// CHECK: ret i32 [[VCLTZ_I]]
@@ -18494,7 +17573,7 @@ uint32_t test_vcltzs_f32(float32_t a) {
return (uint32_t)vcltzs_f32(a);
}
-// CHECK-LABEL: define i64 @test_vcltzd_f64(double %a) #0 {
+// CHECK-LABEL: @test_vcltzd_f64(
// CHECK: [[TMP0:%.*]] = fcmp olt double %a, 0.000000e+00
// CHECK: [[VCLTZ_I:%.*]] = sext i1 [[TMP0]] to i64
// CHECK: ret i64 [[VCLTZ_I]]
@@ -18502,70 +17581,70 @@ uint64_t test_vcltzd_f64(float64_t a) {
return (uint64_t)vcltzd_f64(a);
}
-// CHECK-LABEL: define i32 @test_vcages_f32(float %a, float %b) #0 {
+// CHECK-LABEL: @test_vcages_f32(
// CHECK: [[VCAGES_F32_I:%.*]] = call i32 @llvm.aarch64.neon.facge.i32.f32(float %a, float %b) #4
// CHECK: ret i32 [[VCAGES_F32_I]]
uint32_t test_vcages_f32(float32_t a, float32_t b) {
return (uint32_t)vcages_f32(a, b);
}
-// CHECK-LABEL: define i64 @test_vcaged_f64(double %a, double %b) #0 {
+// CHECK-LABEL: @test_vcaged_f64(
// CHECK: [[VCAGED_F64_I:%.*]] = call i64 @llvm.aarch64.neon.facge.i64.f64(double %a, double %b) #4
// CHECK: ret i64 [[VCAGED_F64_I]]
uint64_t test_vcaged_f64(float64_t a, float64_t b) {
return (uint64_t)vcaged_f64(a, b);
}
-// CHECK-LABEL: define i32 @test_vcagts_f32(float %a, float %b) #0 {
+// CHECK-LABEL: @test_vcagts_f32(
// CHECK: [[VCAGTS_F32_I:%.*]] = call i32 @llvm.aarch64.neon.facgt.i32.f32(float %a, float %b) #4
// CHECK: ret i32 [[VCAGTS_F32_I]]
uint32_t test_vcagts_f32(float32_t a, float32_t b) {
return (uint32_t)vcagts_f32(a, b);
}
-// CHECK-LABEL: define i64 @test_vcagtd_f64(double %a, double %b) #0 {
+// CHECK-LABEL: @test_vcagtd_f64(
// CHECK: [[VCAGTD_F64_I:%.*]] = call i64 @llvm.aarch64.neon.facgt.i64.f64(double %a, double %b) #4
// CHECK: ret i64 [[VCAGTD_F64_I]]
uint64_t test_vcagtd_f64(float64_t a, float64_t b) {
return (uint64_t)vcagtd_f64(a, b);
}
-// CHECK-LABEL: define i32 @test_vcales_f32(float %a, float %b) #0 {
+// CHECK-LABEL: @test_vcales_f32(
// CHECK: [[VCALES_F32_I:%.*]] = call i32 @llvm.aarch64.neon.facge.i32.f32(float %b, float %a) #4
// CHECK: ret i32 [[VCALES_F32_I]]
uint32_t test_vcales_f32(float32_t a, float32_t b) {
return (uint32_t)vcales_f32(a, b);
}
-// CHECK-LABEL: define i64 @test_vcaled_f64(double %a, double %b) #0 {
+// CHECK-LABEL: @test_vcaled_f64(
// CHECK: [[VCALED_F64_I:%.*]] = call i64 @llvm.aarch64.neon.facge.i64.f64(double %b, double %a) #4
// CHECK: ret i64 [[VCALED_F64_I]]
uint64_t test_vcaled_f64(float64_t a, float64_t b) {
return (uint64_t)vcaled_f64(a, b);
}
-// CHECK-LABEL: define i32 @test_vcalts_f32(float %a, float %b) #0 {
+// CHECK-LABEL: @test_vcalts_f32(
// CHECK: [[VCALTS_F32_I:%.*]] = call i32 @llvm.aarch64.neon.facgt.i32.f32(float %b, float %a) #4
// CHECK: ret i32 [[VCALTS_F32_I]]
uint32_t test_vcalts_f32(float32_t a, float32_t b) {
return (uint32_t)vcalts_f32(a, b);
}
-// CHECK-LABEL: define i64 @test_vcaltd_f64(double %a, double %b) #0 {
+// CHECK-LABEL: @test_vcaltd_f64(
// CHECK: [[VCALTD_F64_I:%.*]] = call i64 @llvm.aarch64.neon.facgt.i64.f64(double %b, double %a) #4
// CHECK: ret i64 [[VCALTD_F64_I]]
uint64_t test_vcaltd_f64(float64_t a, float64_t b) {
return (uint64_t)vcaltd_f64(a, b);
}
-// CHECK-LABEL: define i64 @test_vshrd_n_s64(i64 %a) #0 {
+// CHECK-LABEL: @test_vshrd_n_s64(
// CHECK: [[SHRD_N:%.*]] = ashr i64 %a, 1
// CHECK: ret i64 [[SHRD_N]]
int64_t test_vshrd_n_s64(int64_t a) {
return (int64_t)vshrd_n_s64(a, 1);
}
-// CHECK-LABEL: define <1 x i64> @test_vshr_n_s64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vshr_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
// CHECK: [[VSHR_N:%.*]] = ashr <1 x i64> [[TMP1]], <i64 1>
@@ -18574,22 +17653,20 @@ int64x1_t test_vshr_n_s64(int64x1_t a) {
return vshr_n_s64(a, 1);
}
-// CHECK-LABEL: define i64 @test_vshrd_n_u64(i64 %a) #0 {
+// CHECK-LABEL: @test_vshrd_n_u64(
// CHECK: ret i64 0
uint64_t test_vshrd_n_u64(uint64_t a) {
-
return (uint64_t)vshrd_n_u64(a, 64);
}
-// CHECK-LABEL: define i64 @test_vshrd_n_u64_2() #0 {
+// CHECK-LABEL: @test_vshrd_n_u64_2(
// CHECK: ret i64 0
uint64_t test_vshrd_n_u64_2() {
-
uint64_t a = UINT64_C(0xf000000000000000);
return vshrd_n_u64(a, 64);
}
-// CHECK-LABEL: define <1 x i64> @test_vshr_n_u64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vshr_n_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
// CHECK: [[VSHR_N:%.*]] = lshr <1 x i64> [[TMP1]], <i64 1>
@@ -18598,14 +17675,14 @@ uint64x1_t test_vshr_n_u64(uint64x1_t a) {
return vshr_n_u64(a, 1);
}
-// CHECK-LABEL: define i64 @test_vrshrd_n_s64(i64 %a) #0 {
+// CHECK-LABEL: @test_vrshrd_n_s64(
// CHECK: [[VRSHR_N:%.*]] = call i64 @llvm.aarch64.neon.srshl.i64(i64 %a, i64 -63)
// CHECK: ret i64 [[VRSHR_N]]
int64_t test_vrshrd_n_s64(int64_t a) {
return (int64_t)vrshrd_n_s64(a, 63);
}
-// CHECK-LABEL: define <1 x i64> @test_vrshr_n_s64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vrshr_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[VRSHR_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
// CHECK: [[VRSHR_N1:%.*]] = call <1 x i64> @llvm.aarch64.neon.srshl.v1i64(<1 x i64> [[VRSHR_N]], <1 x i64> <i64 -1>)
@@ -18614,14 +17691,14 @@ int64x1_t test_vrshr_n_s64(int64x1_t a) {
return vrshr_n_s64(a, 1);
}
-// CHECK-LABEL: define i64 @test_vrshrd_n_u64(i64 %a) #0 {
+// CHECK-LABEL: @test_vrshrd_n_u64(
// CHECK: [[VRSHR_N:%.*]] = call i64 @llvm.aarch64.neon.urshl.i64(i64 %a, i64 -63)
// CHECK: ret i64 [[VRSHR_N]]
uint64_t test_vrshrd_n_u64(uint64_t a) {
return (uint64_t)vrshrd_n_u64(a, 63);
}
-// CHECK-LABEL: define <1 x i64> @test_vrshr_n_u64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vrshr_n_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[VRSHR_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
// CHECK: [[VRSHR_N1:%.*]] = call <1 x i64> @llvm.aarch64.neon.urshl.v1i64(<1 x i64> [[VRSHR_N]], <1 x i64> <i64 -1>)
@@ -18630,7 +17707,7 @@ uint64x1_t test_vrshr_n_u64(uint64x1_t a) {
return vrshr_n_u64(a, 1);
}
-// CHECK-LABEL: define i64 @test_vsrad_n_s64(i64 %a, i64 %b) #0 {
+// CHECK-LABEL: @test_vsrad_n_s64(
// CHECK: [[SHRD_N:%.*]] = ashr i64 %b, 63
// CHECK: [[TMP0:%.*]] = add i64 %a, [[SHRD_N]]
// CHECK: ret i64 [[TMP0]]
@@ -18638,7 +17715,7 @@ int64_t test_vsrad_n_s64(int64_t a, int64_t b) {
return (int64_t)vsrad_n_s64(a, b, 63);
}
-// CHECK-LABEL: define <1 x i64> @test_vsra_n_s64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vsra_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
@@ -18650,7 +17727,7 @@ int64x1_t test_vsra_n_s64(int64x1_t a, int64x1_t b) {
return vsra_n_s64(a, b, 1);
}
-// CHECK-LABEL: define i64 @test_vsrad_n_u64(i64 %a, i64 %b) #0 {
+// CHECK-LABEL: @test_vsrad_n_u64(
// CHECK: [[SHRD_N:%.*]] = lshr i64 %b, 63
// CHECK: [[TMP0:%.*]] = add i64 %a, [[SHRD_N]]
// CHECK: ret i64 [[TMP0]]
@@ -18658,14 +17735,13 @@ uint64_t test_vsrad_n_u64(uint64_t a, uint64_t b) {
return (uint64_t)vsrad_n_u64(a, b, 63);
}
-// CHECK-LABEL: define i64 @test_vsrad_n_u64_2(i64 %a, i64 %b) #0 {
+// CHECK-LABEL: @test_vsrad_n_u64_2(
// CHECK: ret i64 %a
uint64_t test_vsrad_n_u64_2(uint64_t a, uint64_t b) {
-
return (uint64_t)vsrad_n_u64(a, b, 64);
}
-// CHECK-LABEL: define <1 x i64> @test_vsra_n_u64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vsra_n_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
@@ -18677,7 +17753,7 @@ uint64x1_t test_vsra_n_u64(uint64x1_t a, uint64x1_t b) {
return vsra_n_u64(a, b, 1);
}
-// CHECK-LABEL: define i64 @test_vrsrad_n_s64(i64 %a, i64 %b) #0 {
+// CHECK-LABEL: @test_vrsrad_n_s64(
// CHECK: [[TMP0:%.*]] = call i64 @llvm.aarch64.neon.srshl.i64(i64 %b, i64 -63)
// CHECK: [[TMP1:%.*]] = add i64 %a, [[TMP0]]
// CHECK: ret i64 [[TMP1]]
@@ -18685,7 +17761,7 @@ int64_t test_vrsrad_n_s64(int64_t a, int64_t b) {
return (int64_t)vrsrad_n_s64(a, b, 63);
}
-// CHECK-LABEL: define <1 x i64> @test_vrsra_n_s64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vrsra_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
// CHECK: [[VRSHR_N:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x i64>
@@ -18697,7 +17773,7 @@ int64x1_t test_vrsra_n_s64(int64x1_t a, int64x1_t b) {
return vrsra_n_s64(a, b, 1);
}
-// CHECK-LABEL: define i64 @test_vrsrad_n_u64(i64 %a, i64 %b) #0 {
+// CHECK-LABEL: @test_vrsrad_n_u64(
// CHECK: [[TMP0:%.*]] = call i64 @llvm.aarch64.neon.urshl.i64(i64 %b, i64 -63)
// CHECK: [[TMP1:%.*]] = add i64 %a, [[TMP0]]
// CHECK: ret i64 [[TMP1]]
@@ -18705,7 +17781,7 @@ uint64_t test_vrsrad_n_u64(uint64_t a, uint64_t b) {
return (uint64_t)vrsrad_n_u64(a, b, 63);
}
-// CHECK-LABEL: define <1 x i64> @test_vrsra_n_u64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vrsra_n_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
// CHECK: [[VRSHR_N:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x i64>
@@ -18717,13 +17793,14 @@ uint64x1_t test_vrsra_n_u64(uint64x1_t a, uint64x1_t b) {
return vrsra_n_u64(a, b, 1);
}
-// CHECK-LABEL: define i64 @test_vshld_n_s64(i64 %a) #0 {
+// CHECK-LABEL: @test_vshld_n_s64(
// CHECK: [[SHLD_N:%.*]] = shl i64 %a, 1
// CHECK: ret i64 [[SHLD_N]]
int64_t test_vshld_n_s64(int64_t a) {
return (int64_t)vshld_n_s64(a, 1);
}
-// CHECK-LABEL: define <1 x i64> @test_vshl_n_s64(<1 x i64> %a) #0 {
+
+// CHECK-LABEL: @test_vshl_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
// CHECK: [[VSHL_N:%.*]] = shl <1 x i64> [[TMP1]], <i64 1>
@@ -18732,14 +17809,14 @@ int64x1_t test_vshl_n_s64(int64x1_t a) {
return vshl_n_s64(a, 1);
}
-// CHECK-LABEL: define i64 @test_vshld_n_u64(i64 %a) #0 {
+// CHECK-LABEL: @test_vshld_n_u64(
// CHECK: [[SHLD_N:%.*]] = shl i64 %a, 63
// CHECK: ret i64 [[SHLD_N]]
uint64_t test_vshld_n_u64(uint64_t a) {
return (uint64_t)vshld_n_u64(a, 63);
}
-// CHECK-LABEL: define <1 x i64> @test_vshl_n_u64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vshl_n_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
// CHECK: [[VSHL_N:%.*]] = shl <1 x i64> [[TMP1]], <i64 1>
@@ -18748,7 +17825,7 @@ uint64x1_t test_vshl_n_u64(uint64x1_t a) {
return vshl_n_u64(a, 1);
}
-// CHECK-LABEL: define i8 @test_vqshlb_n_s8(i8 %a) #0 {
+// CHECK-LABEL: @test_vqshlb_n_s8(
// CHECK: [[TMP0:%.*]] = insertelement <8 x i8> undef, i8 %a, i64 0
// CHECK: [[VQSHLB_N_S8:%.*]] = call <8 x i8> @llvm.aarch64.neon.sqshl.v8i8(<8 x i8> [[TMP0]], <8 x i8> <i8 7, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef>)
// CHECK: [[TMP1:%.*]] = extractelement <8 x i8> [[VQSHLB_N_S8]], i64 0
@@ -18757,7 +17834,7 @@ int8_t test_vqshlb_n_s8(int8_t a) {
return (int8_t)vqshlb_n_s8(a, 7);
}
-// CHECK-LABEL: define i16 @test_vqshlh_n_s16(i16 %a) #0 {
+// CHECK-LABEL: @test_vqshlh_n_s16(
// CHECK: [[TMP0:%.*]] = insertelement <4 x i16> undef, i16 %a, i64 0
// CHECK: [[VQSHLH_N_S16:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqshl.v4i16(<4 x i16> [[TMP0]], <4 x i16> <i16 15, i16 undef, i16 undef, i16 undef>)
// CHECK: [[TMP1:%.*]] = extractelement <4 x i16> [[VQSHLH_N_S16]], i64 0
@@ -18766,35 +17843,35 @@ int16_t test_vqshlh_n_s16(int16_t a) {
return (int16_t)vqshlh_n_s16(a, 15);
}
-// CHECK-LABEL: define i32 @test_vqshls_n_s32(i32 %a) #0 {
+// CHECK-LABEL: @test_vqshls_n_s32(
// CHECK: [[VQSHLS_N_S32:%.*]] = call i32 @llvm.aarch64.neon.sqshl.i32(i32 %a, i32 31)
// CHECK: ret i32 [[VQSHLS_N_S32]]
int32_t test_vqshls_n_s32(int32_t a) {
return (int32_t)vqshls_n_s32(a, 31);
}
-// CHECK-LABEL: define i64 @test_vqshld_n_s64(i64 %a) #0 {
+// CHECK-LABEL: @test_vqshld_n_s64(
// CHECK: [[VQSHL_N:%.*]] = call i64 @llvm.aarch64.neon.sqshl.i64(i64 %a, i64 63)
// CHECK: ret i64 [[VQSHL_N]]
int64_t test_vqshld_n_s64(int64_t a) {
return (int64_t)vqshld_n_s64(a, 63);
}
-// CHECK-LABEL: define <8 x i8> @test_vqshl_n_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vqshl_n_s8(
// CHECK: [[VQSHL_N:%.*]] = call <8 x i8> @llvm.aarch64.neon.sqshl.v8i8(<8 x i8> %a, <8 x i8> zeroinitializer)
// CHECK: ret <8 x i8> [[VQSHL_N]]
int8x8_t test_vqshl_n_s8(int8x8_t a) {
return vqshl_n_s8(a, 0);
}
-// CHECK-LABEL: define <16 x i8> @test_vqshlq_n_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vqshlq_n_s8(
// CHECK: [[VQSHL_N:%.*]] = call <16 x i8> @llvm.aarch64.neon.sqshl.v16i8(<16 x i8> %a, <16 x i8> zeroinitializer)
// CHECK: ret <16 x i8> [[VQSHL_N]]
int8x16_t test_vqshlq_n_s8(int8x16_t a) {
return vqshlq_n_s8(a, 0);
}
-// CHECK-LABEL: define <4 x i16> @test_vqshl_n_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vqshl_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[VQSHL_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
// CHECK: [[VQSHL_N1:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqshl.v4i16(<4 x i16> [[VQSHL_N]], <4 x i16> zeroinitializer)
@@ -18803,7 +17880,7 @@ int16x4_t test_vqshl_n_s16(int16x4_t a) {
return vqshl_n_s16(a, 0);
}
-// CHECK-LABEL: define <8 x i16> @test_vqshlq_n_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vqshlq_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[VQSHL_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VQSHL_N1:%.*]] = call <8 x i16> @llvm.aarch64.neon.sqshl.v8i16(<8 x i16> [[VQSHL_N]], <8 x i16> zeroinitializer)
@@ -18812,7 +17889,7 @@ int16x8_t test_vqshlq_n_s16(int16x8_t a) {
return vqshlq_n_s16(a, 0);
}
-// CHECK-LABEL: define <2 x i32> @test_vqshl_n_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vqshl_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[VQSHL_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
// CHECK: [[VQSHL_N1:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqshl.v2i32(<2 x i32> [[VQSHL_N]], <2 x i32> zeroinitializer)
@@ -18821,7 +17898,7 @@ int32x2_t test_vqshl_n_s32(int32x2_t a) {
return vqshl_n_s32(a, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vqshlq_n_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vqshlq_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[VQSHL_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VQSHL_N1:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqshl.v4i32(<4 x i32> [[VQSHL_N]], <4 x i32> zeroinitializer)
@@ -18830,7 +17907,7 @@ int32x4_t test_vqshlq_n_s32(int32x4_t a) {
return vqshlq_n_s32(a, 0);
}
-// CHECK-LABEL: define <2 x i64> @test_vqshlq_n_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vqshlq_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[VQSHL_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VQSHL_N1:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqshl.v2i64(<2 x i64> [[VQSHL_N]], <2 x i64> zeroinitializer)
@@ -18839,21 +17916,21 @@ int64x2_t test_vqshlq_n_s64(int64x2_t a) {
return vqshlq_n_s64(a, 0);
}
-// CHECK-LABEL: define <8 x i8> @test_vqshl_n_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vqshl_n_u8(
// CHECK: [[VQSHL_N:%.*]] = call <8 x i8> @llvm.aarch64.neon.uqshl.v8i8(<8 x i8> %a, <8 x i8> zeroinitializer)
// CHECK: ret <8 x i8> [[VQSHL_N]]
uint8x8_t test_vqshl_n_u8(uint8x8_t a) {
return vqshl_n_u8(a, 0);
}
-// CHECK-LABEL: define <16 x i8> @test_vqshlq_n_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vqshlq_n_u8(
// CHECK: [[VQSHL_N:%.*]] = call <16 x i8> @llvm.aarch64.neon.uqshl.v16i8(<16 x i8> %a, <16 x i8> zeroinitializer)
// CHECK: ret <16 x i8> [[VQSHL_N]]
uint8x16_t test_vqshlq_n_u8(uint8x16_t a) {
return vqshlq_n_u8(a, 0);
}
-// CHECK-LABEL: define <4 x i16> @test_vqshl_n_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vqshl_n_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[VQSHL_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
// CHECK: [[VQSHL_N1:%.*]] = call <4 x i16> @llvm.aarch64.neon.uqshl.v4i16(<4 x i16> [[VQSHL_N]], <4 x i16> zeroinitializer)
@@ -18862,7 +17939,7 @@ uint16x4_t test_vqshl_n_u16(uint16x4_t a) {
return vqshl_n_u16(a, 0);
}
-// CHECK-LABEL: define <8 x i16> @test_vqshlq_n_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vqshlq_n_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[VQSHL_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VQSHL_N1:%.*]] = call <8 x i16> @llvm.aarch64.neon.uqshl.v8i16(<8 x i16> [[VQSHL_N]], <8 x i16> zeroinitializer)
@@ -18871,7 +17948,7 @@ uint16x8_t test_vqshlq_n_u16(uint16x8_t a) {
return vqshlq_n_u16(a, 0);
}
-// CHECK-LABEL: define <2 x i32> @test_vqshl_n_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vqshl_n_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[VQSHL_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
// CHECK: [[VQSHL_N1:%.*]] = call <2 x i32> @llvm.aarch64.neon.uqshl.v2i32(<2 x i32> [[VQSHL_N]], <2 x i32> zeroinitializer)
@@ -18880,7 +17957,7 @@ uint32x2_t test_vqshl_n_u32(uint32x2_t a) {
return vqshl_n_u32(a, 0);
}
-// CHECK-LABEL: define <4 x i32> @test_vqshlq_n_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vqshlq_n_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[VQSHL_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VQSHL_N1:%.*]] = call <4 x i32> @llvm.aarch64.neon.uqshl.v4i32(<4 x i32> [[VQSHL_N]], <4 x i32> zeroinitializer)
@@ -18889,7 +17966,7 @@ uint32x4_t test_vqshlq_n_u32(uint32x4_t a) {
return vqshlq_n_u32(a, 0);
}
-// CHECK-LABEL: define <2 x i64> @test_vqshlq_n_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vqshlq_n_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[VQSHL_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VQSHL_N1:%.*]] = call <2 x i64> @llvm.aarch64.neon.uqshl.v2i64(<2 x i64> [[VQSHL_N]], <2 x i64> zeroinitializer)
@@ -18898,7 +17975,7 @@ uint64x2_t test_vqshlq_n_u64(uint64x2_t a) {
return vqshlq_n_u64(a, 0);
}
-// CHECK-LABEL: define <1 x i64> @test_vqshl_n_s64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vqshl_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[VQSHL_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
// CHECK: [[VQSHL_N1:%.*]] = call <1 x i64> @llvm.aarch64.neon.sqshl.v1i64(<1 x i64> [[VQSHL_N]], <1 x i64> <i64 1>)
@@ -18907,7 +17984,7 @@ int64x1_t test_vqshl_n_s64(int64x1_t a) {
return vqshl_n_s64(a, 1);
}
-// CHECK-LABEL: define i8 @test_vqshlb_n_u8(i8 %a) #0 {
+// CHECK-LABEL: @test_vqshlb_n_u8(
// CHECK: [[TMP0:%.*]] = insertelement <8 x i8> undef, i8 %a, i64 0
// CHECK: [[VQSHLB_N_U8:%.*]] = call <8 x i8> @llvm.aarch64.neon.uqshl.v8i8(<8 x i8> [[TMP0]], <8 x i8> <i8 7, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef>)
// CHECK: [[TMP1:%.*]] = extractelement <8 x i8> [[VQSHLB_N_U8]], i64 0
@@ -18916,7 +17993,7 @@ uint8_t test_vqshlb_n_u8(uint8_t a) {
return (uint8_t)vqshlb_n_u8(a, 7);
}
-// CHECK-LABEL: define i16 @test_vqshlh_n_u16(i16 %a) #0 {
+// CHECK-LABEL: @test_vqshlh_n_u16(
// CHECK: [[TMP0:%.*]] = insertelement <4 x i16> undef, i16 %a, i64 0
// CHECK: [[VQSHLH_N_U16:%.*]] = call <4 x i16> @llvm.aarch64.neon.uqshl.v4i16(<4 x i16> [[TMP0]], <4 x i16> <i16 15, i16 undef, i16 undef, i16 undef>)
// CHECK: [[TMP1:%.*]] = extractelement <4 x i16> [[VQSHLH_N_U16]], i64 0
@@ -18925,21 +18002,21 @@ uint16_t test_vqshlh_n_u16(uint16_t a) {
return (uint16_t)vqshlh_n_u16(a, 15);
}
-// CHECK-LABEL: define i32 @test_vqshls_n_u32(i32 %a) #0 {
+// CHECK-LABEL: @test_vqshls_n_u32(
// CHECK: [[VQSHLS_N_U32:%.*]] = call i32 @llvm.aarch64.neon.uqshl.i32(i32 %a, i32 31)
// CHECK: ret i32 [[VQSHLS_N_U32]]
uint32_t test_vqshls_n_u32(uint32_t a) {
return (uint32_t)vqshls_n_u32(a, 31);
}
-// CHECK-LABEL: define i64 @test_vqshld_n_u64(i64 %a) #0 {
+// CHECK-LABEL: @test_vqshld_n_u64(
// CHECK: [[VQSHL_N:%.*]] = call i64 @llvm.aarch64.neon.uqshl.i64(i64 %a, i64 63)
// CHECK: ret i64 [[VQSHL_N]]
uint64_t test_vqshld_n_u64(uint64_t a) {
return (uint64_t)vqshld_n_u64(a, 63);
}
-// CHECK-LABEL: define <1 x i64> @test_vqshl_n_u64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vqshl_n_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[VQSHL_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
// CHECK: [[VQSHL_N1:%.*]] = call <1 x i64> @llvm.aarch64.neon.uqshl.v1i64(<1 x i64> [[VQSHL_N]], <1 x i64> <i64 1>)
@@ -18948,7 +18025,7 @@ uint64x1_t test_vqshl_n_u64(uint64x1_t a) {
return vqshl_n_u64(a, 1);
}
-// CHECK-LABEL: define i8 @test_vqshlub_n_s8(i8 %a) #0 {
+// CHECK-LABEL: @test_vqshlub_n_s8(
// CHECK: [[TMP0:%.*]] = insertelement <8 x i8> undef, i8 %a, i64 0
// CHECK: [[VQSHLUB_N_S8:%.*]] = call <8 x i8> @llvm.aarch64.neon.sqshlu.v8i8(<8 x i8> [[TMP0]], <8 x i8> <i8 7, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef>)
// CHECK: [[TMP1:%.*]] = extractelement <8 x i8> [[VQSHLUB_N_S8]], i64 0
@@ -18957,7 +18034,7 @@ int8_t test_vqshlub_n_s8(int8_t a) {
return (int8_t)vqshlub_n_s8(a, 7);
}
-// CHECK-LABEL: define i16 @test_vqshluh_n_s16(i16 %a) #0 {
+// CHECK-LABEL: @test_vqshluh_n_s16(
// CHECK: [[TMP0:%.*]] = insertelement <4 x i16> undef, i16 %a, i64 0
// CHECK: [[VQSHLUH_N_S16:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqshlu.v4i16(<4 x i16> [[TMP0]], <4 x i16> <i16 15, i16 undef, i16 undef, i16 undef>)
// CHECK: [[TMP1:%.*]] = extractelement <4 x i16> [[VQSHLUH_N_S16]], i64 0
@@ -18966,21 +18043,21 @@ int16_t test_vqshluh_n_s16(int16_t a) {
return (int16_t)vqshluh_n_s16(a, 15);
}
-// CHECK-LABEL: define i32 @test_vqshlus_n_s32(i32 %a) #0 {
+// CHECK-LABEL: @test_vqshlus_n_s32(
// CHECK: [[VQSHLUS_N_S32:%.*]] = call i32 @llvm.aarch64.neon.sqshlu.i32(i32 %a, i32 31)
// CHECK: ret i32 [[VQSHLUS_N_S32]]
int32_t test_vqshlus_n_s32(int32_t a) {
return (int32_t)vqshlus_n_s32(a, 31);
}
-// CHECK-LABEL: define i64 @test_vqshlud_n_s64(i64 %a) #0 {
+// CHECK-LABEL: @test_vqshlud_n_s64(
// CHECK: [[VQSHLU_N:%.*]] = call i64 @llvm.aarch64.neon.sqshlu.i64(i64 %a, i64 63)
// CHECK: ret i64 [[VQSHLU_N]]
int64_t test_vqshlud_n_s64(int64_t a) {
return (int64_t)vqshlud_n_s64(a, 63);
}
-// CHECK-LABEL: define <1 x i64> @test_vqshlu_n_s64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vqshlu_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[VQSHLU_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
// CHECK: [[VQSHLU_N1:%.*]] = call <1 x i64> @llvm.aarch64.neon.sqshlu.v1i64(<1 x i64> [[VQSHLU_N]], <1 x i64> <i64 1>)
@@ -18989,7 +18066,7 @@ uint64x1_t test_vqshlu_n_s64(int64x1_t a) {
return vqshlu_n_s64(a, 1);
}
-// CHECK-LABEL: define i64 @test_vsrid_n_s64(i64 %a, i64 %b) #0 {
+// CHECK-LABEL: @test_vsrid_n_s64(
// CHECK: [[VSRID_N_S64:%.*]] = bitcast i64 %a to <1 x i64>
// CHECK: [[VSRID_N_S641:%.*]] = bitcast i64 %b to <1 x i64>
// CHECK: [[VSRID_N_S642:%.*]] = call <1 x i64> @llvm.aarch64.neon.vsri.v1i64(<1 x i64> [[VSRID_N_S64]], <1 x i64> [[VSRID_N_S641]], i32 63)
@@ -18999,7 +18076,7 @@ int64_t test_vsrid_n_s64(int64_t a, int64_t b) {
return (int64_t)vsrid_n_s64(a, b, 63);
}
-// CHECK-LABEL: define <1 x i64> @test_vsri_n_s64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vsri_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
// CHECK: [[VSRI_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
@@ -19010,7 +18087,7 @@ int64x1_t test_vsri_n_s64(int64x1_t a, int64x1_t b) {
return vsri_n_s64(a, b, 1);
}
-// CHECK-LABEL: define i64 @test_vsrid_n_u64(i64 %a, i64 %b) #0 {
+// CHECK-LABEL: @test_vsrid_n_u64(
// CHECK: [[VSRID_N_U64:%.*]] = bitcast i64 %a to <1 x i64>
// CHECK: [[VSRID_N_U641:%.*]] = bitcast i64 %b to <1 x i64>
// CHECK: [[VSRID_N_U642:%.*]] = call <1 x i64> @llvm.aarch64.neon.vsri.v1i64(<1 x i64> [[VSRID_N_U64]], <1 x i64> [[VSRID_N_U641]], i32 63)
@@ -19020,7 +18097,7 @@ uint64_t test_vsrid_n_u64(uint64_t a, uint64_t b) {
return (uint64_t)vsrid_n_u64(a, b, 63);
}
-// CHECK-LABEL: define <1 x i64> @test_vsri_n_u64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vsri_n_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
// CHECK: [[VSRI_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
@@ -19031,7 +18108,7 @@ uint64x1_t test_vsri_n_u64(uint64x1_t a, uint64x1_t b) {
return vsri_n_u64(a, b, 1);
}
-// CHECK-LABEL: define i64 @test_vslid_n_s64(i64 %a, i64 %b) #0 {
+// CHECK-LABEL: @test_vslid_n_s64(
// CHECK: [[VSLID_N_S64:%.*]] = bitcast i64 %a to <1 x i64>
// CHECK: [[VSLID_N_S641:%.*]] = bitcast i64 %b to <1 x i64>
// CHECK: [[VSLID_N_S642:%.*]] = call <1 x i64> @llvm.aarch64.neon.vsli.v1i64(<1 x i64> [[VSLID_N_S64]], <1 x i64> [[VSLID_N_S641]], i32 63)
@@ -19041,7 +18118,7 @@ int64_t test_vslid_n_s64(int64_t a, int64_t b) {
return (int64_t)vslid_n_s64(a, b, 63);
}
-// CHECK-LABEL: define <1 x i64> @test_vsli_n_s64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vsli_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
// CHECK: [[VSLI_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
@@ -19052,7 +18129,7 @@ int64x1_t test_vsli_n_s64(int64x1_t a, int64x1_t b) {
return vsli_n_s64(a, b, 1);
}
-// CHECK-LABEL: define i64 @test_vslid_n_u64(i64 %a, i64 %b) #0 {
+// CHECK-LABEL: @test_vslid_n_u64(
// CHECK: [[VSLID_N_U64:%.*]] = bitcast i64 %a to <1 x i64>
// CHECK: [[VSLID_N_U641:%.*]] = bitcast i64 %b to <1 x i64>
// CHECK: [[VSLID_N_U642:%.*]] = call <1 x i64> @llvm.aarch64.neon.vsli.v1i64(<1 x i64> [[VSLID_N_U64]], <1 x i64> [[VSLID_N_U641]], i32 63)
@@ -19062,7 +18139,7 @@ uint64_t test_vslid_n_u64(uint64_t a, uint64_t b) {
return (uint64_t)vslid_n_u64(a, b, 63);
}
-// CHECK-LABEL: define <1 x i64> @test_vsli_n_u64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vsli_n_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
// CHECK: [[VSLI_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
@@ -19073,7 +18150,7 @@ uint64x1_t test_vsli_n_u64(uint64x1_t a, uint64x1_t b) {
return vsli_n_u64(a, b, 1);
}
-// CHECK-LABEL: define i8 @test_vqshrnh_n_s16(i16 %a) #0 {
+// CHECK-LABEL: @test_vqshrnh_n_s16(
// CHECK: [[TMP0:%.*]] = insertelement <8 x i16> undef, i16 %a, i64 0
// CHECK: [[VQSHRNH_N_S16:%.*]] = call <8 x i8> @llvm.aarch64.neon.sqshrn.v8i8(<8 x i16> [[TMP0]], i32 8)
// CHECK: [[TMP1:%.*]] = extractelement <8 x i8> [[VQSHRNH_N_S16]], i64 0
@@ -19082,7 +18159,7 @@ int8_t test_vqshrnh_n_s16(int16_t a) {
return (int8_t)vqshrnh_n_s16(a, 8);
}
-// CHECK-LABEL: define i16 @test_vqshrns_n_s32(i32 %a) #0 {
+// CHECK-LABEL: @test_vqshrns_n_s32(
// CHECK: [[TMP0:%.*]] = insertelement <4 x i32> undef, i32 %a, i64 0
// CHECK: [[VQSHRNS_N_S32:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqshrn.v4i16(<4 x i32> [[TMP0]], i32 16)
// CHECK: [[TMP1:%.*]] = extractelement <4 x i16> [[VQSHRNS_N_S32]], i64 0
@@ -19091,14 +18168,14 @@ int16_t test_vqshrns_n_s32(int32_t a) {
return (int16_t)vqshrns_n_s32(a, 16);
}
-// CHECK-LABEL: define i32 @test_vqshrnd_n_s64(i64 %a) #0 {
+// CHECK-LABEL: @test_vqshrnd_n_s64(
// CHECK: [[VQSHRND_N_S64:%.*]] = call i32 @llvm.aarch64.neon.sqshrn.i32(i64 %a, i32 32)
// CHECK: ret i32 [[VQSHRND_N_S64]]
int32_t test_vqshrnd_n_s64(int64_t a) {
return (int32_t)vqshrnd_n_s64(a, 32);
}
-// CHECK-LABEL: define i8 @test_vqshrnh_n_u16(i16 %a) #0 {
+// CHECK-LABEL: @test_vqshrnh_n_u16(
// CHECK: [[TMP0:%.*]] = insertelement <8 x i16> undef, i16 %a, i64 0
// CHECK: [[VQSHRNH_N_U16:%.*]] = call <8 x i8> @llvm.aarch64.neon.uqshrn.v8i8(<8 x i16> [[TMP0]], i32 8)
// CHECK: [[TMP1:%.*]] = extractelement <8 x i8> [[VQSHRNH_N_U16]], i64 0
@@ -19107,7 +18184,7 @@ uint8_t test_vqshrnh_n_u16(uint16_t a) {
return (uint8_t)vqshrnh_n_u16(a, 8);
}
-// CHECK-LABEL: define i16 @test_vqshrns_n_u32(i32 %a) #0 {
+// CHECK-LABEL: @test_vqshrns_n_u32(
// CHECK: [[TMP0:%.*]] = insertelement <4 x i32> undef, i32 %a, i64 0
// CHECK: [[VQSHRNS_N_U32:%.*]] = call <4 x i16> @llvm.aarch64.neon.uqshrn.v4i16(<4 x i32> [[TMP0]], i32 16)
// CHECK: [[TMP1:%.*]] = extractelement <4 x i16> [[VQSHRNS_N_U32]], i64 0
@@ -19116,14 +18193,14 @@ uint16_t test_vqshrns_n_u32(uint32_t a) {
return (uint16_t)vqshrns_n_u32(a, 16);
}
-// CHECK-LABEL: define i32 @test_vqshrnd_n_u64(i64 %a) #0 {
+// CHECK-LABEL: @test_vqshrnd_n_u64(
// CHECK: [[VQSHRND_N_U64:%.*]] = call i32 @llvm.aarch64.neon.uqshrn.i32(i64 %a, i32 32)
// CHECK: ret i32 [[VQSHRND_N_U64]]
uint32_t test_vqshrnd_n_u64(uint64_t a) {
return (uint32_t)vqshrnd_n_u64(a, 32);
}
-// CHECK-LABEL: define i8 @test_vqrshrnh_n_s16(i16 %a) #0 {
+// CHECK-LABEL: @test_vqrshrnh_n_s16(
// CHECK: [[TMP0:%.*]] = insertelement <8 x i16> undef, i16 %a, i64 0
// CHECK: [[VQRSHRNH_N_S16:%.*]] = call <8 x i8> @llvm.aarch64.neon.sqrshrn.v8i8(<8 x i16> [[TMP0]], i32 8)
// CHECK: [[TMP1:%.*]] = extractelement <8 x i8> [[VQRSHRNH_N_S16]], i64 0
@@ -19132,7 +18209,7 @@ int8_t test_vqrshrnh_n_s16(int16_t a) {
return (int8_t)vqrshrnh_n_s16(a, 8);
}
-// CHECK-LABEL: define i16 @test_vqrshrns_n_s32(i32 %a) #0 {
+// CHECK-LABEL: @test_vqrshrns_n_s32(
// CHECK: [[TMP0:%.*]] = insertelement <4 x i32> undef, i32 %a, i64 0
// CHECK: [[VQRSHRNS_N_S32:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqrshrn.v4i16(<4 x i32> [[TMP0]], i32 16)
// CHECK: [[TMP1:%.*]] = extractelement <4 x i16> [[VQRSHRNS_N_S32]], i64 0
@@ -19141,14 +18218,14 @@ int16_t test_vqrshrns_n_s32(int32_t a) {
return (int16_t)vqrshrns_n_s32(a, 16);
}
-// CHECK-LABEL: define i32 @test_vqrshrnd_n_s64(i64 %a) #0 {
+// CHECK-LABEL: @test_vqrshrnd_n_s64(
// CHECK: [[VQRSHRND_N_S64:%.*]] = call i32 @llvm.aarch64.neon.sqrshrn.i32(i64 %a, i32 32)
// CHECK: ret i32 [[VQRSHRND_N_S64]]
int32_t test_vqrshrnd_n_s64(int64_t a) {
return (int32_t)vqrshrnd_n_s64(a, 32);
}
-// CHECK-LABEL: define i8 @test_vqrshrnh_n_u16(i16 %a) #0 {
+// CHECK-LABEL: @test_vqrshrnh_n_u16(
// CHECK: [[TMP0:%.*]] = insertelement <8 x i16> undef, i16 %a, i64 0
// CHECK: [[VQRSHRNH_N_U16:%.*]] = call <8 x i8> @llvm.aarch64.neon.uqrshrn.v8i8(<8 x i16> [[TMP0]], i32 8)
// CHECK: [[TMP1:%.*]] = extractelement <8 x i8> [[VQRSHRNH_N_U16]], i64 0
@@ -19157,7 +18234,7 @@ uint8_t test_vqrshrnh_n_u16(uint16_t a) {
return (uint8_t)vqrshrnh_n_u16(a, 8);
}
-// CHECK-LABEL: define i16 @test_vqrshrns_n_u32(i32 %a) #0 {
+// CHECK-LABEL: @test_vqrshrns_n_u32(
// CHECK: [[TMP0:%.*]] = insertelement <4 x i32> undef, i32 %a, i64 0
// CHECK: [[VQRSHRNS_N_U32:%.*]] = call <4 x i16> @llvm.aarch64.neon.uqrshrn.v4i16(<4 x i32> [[TMP0]], i32 16)
// CHECK: [[TMP1:%.*]] = extractelement <4 x i16> [[VQRSHRNS_N_U32]], i64 0
@@ -19166,14 +18243,14 @@ uint16_t test_vqrshrns_n_u32(uint32_t a) {
return (uint16_t)vqrshrns_n_u32(a, 16);
}
-// CHECK-LABEL: define i32 @test_vqrshrnd_n_u64(i64 %a) #0 {
+// CHECK-LABEL: @test_vqrshrnd_n_u64(
// CHECK: [[VQRSHRND_N_U64:%.*]] = call i32 @llvm.aarch64.neon.uqrshrn.i32(i64 %a, i32 32)
// CHECK: ret i32 [[VQRSHRND_N_U64]]
uint32_t test_vqrshrnd_n_u64(uint64_t a) {
return (uint32_t)vqrshrnd_n_u64(a, 32);
}
-// CHECK-LABEL: define i8 @test_vqshrunh_n_s16(i16 %a) #0 {
+// CHECK-LABEL: @test_vqshrunh_n_s16(
// CHECK: [[TMP0:%.*]] = insertelement <8 x i16> undef, i16 %a, i64 0
// CHECK: [[VQSHRUNH_N_S16:%.*]] = call <8 x i8> @llvm.aarch64.neon.sqshrun.v8i8(<8 x i16> [[TMP0]], i32 8)
// CHECK: [[TMP1:%.*]] = extractelement <8 x i8> [[VQSHRUNH_N_S16]], i64 0
@@ -19182,7 +18259,7 @@ int8_t test_vqshrunh_n_s16(int16_t a) {
return (int8_t)vqshrunh_n_s16(a, 8);
}
-// CHECK-LABEL: define i16 @test_vqshruns_n_s32(i32 %a) #0 {
+// CHECK-LABEL: @test_vqshruns_n_s32(
// CHECK: [[TMP0:%.*]] = insertelement <4 x i32> undef, i32 %a, i64 0
// CHECK: [[VQSHRUNS_N_S32:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqshrun.v4i16(<4 x i32> [[TMP0]], i32 16)
// CHECK: [[TMP1:%.*]] = extractelement <4 x i16> [[VQSHRUNS_N_S32]], i64 0
@@ -19191,14 +18268,14 @@ int16_t test_vqshruns_n_s32(int32_t a) {
return (int16_t)vqshruns_n_s32(a, 16);
}
-// CHECK-LABEL: define i32 @test_vqshrund_n_s64(i64 %a) #0 {
+// CHECK-LABEL: @test_vqshrund_n_s64(
// CHECK: [[VQSHRUND_N_S64:%.*]] = call i32 @llvm.aarch64.neon.sqshrun.i32(i64 %a, i32 32)
// CHECK: ret i32 [[VQSHRUND_N_S64]]
int32_t test_vqshrund_n_s64(int64_t a) {
return (int32_t)vqshrund_n_s64(a, 32);
}
-// CHECK-LABEL: define i8 @test_vqrshrunh_n_s16(i16 %a) #0 {
+// CHECK-LABEL: @test_vqrshrunh_n_s16(
// CHECK: [[TMP0:%.*]] = insertelement <8 x i16> undef, i16 %a, i64 0
// CHECK: [[VQRSHRUNH_N_S16:%.*]] = call <8 x i8> @llvm.aarch64.neon.sqrshrun.v8i8(<8 x i16> [[TMP0]], i32 8)
// CHECK: [[TMP1:%.*]] = extractelement <8 x i8> [[VQRSHRUNH_N_S16]], i64 0
@@ -19207,7 +18284,7 @@ int8_t test_vqrshrunh_n_s16(int16_t a) {
return (int8_t)vqrshrunh_n_s16(a, 8);
}
-// CHECK-LABEL: define i16 @test_vqrshruns_n_s32(i32 %a) #0 {
+// CHECK-LABEL: @test_vqrshruns_n_s32(
// CHECK: [[TMP0:%.*]] = insertelement <4 x i32> undef, i32 %a, i64 0
// CHECK: [[VQRSHRUNS_N_S32:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqrshrun.v4i16(<4 x i32> [[TMP0]], i32 16)
// CHECK: [[TMP1:%.*]] = extractelement <4 x i16> [[VQRSHRUNS_N_S32]], i64 0
@@ -19216,2894 +18293,2855 @@ int16_t test_vqrshruns_n_s32(int32_t a) {
return (int16_t)vqrshruns_n_s32(a, 16);
}
-// CHECK-LABEL: define i32 @test_vqrshrund_n_s64(i64 %a) #0 {
+// CHECK-LABEL: @test_vqrshrund_n_s64(
// CHECK: [[VQRSHRUND_N_S64:%.*]] = call i32 @llvm.aarch64.neon.sqrshrun.i32(i64 %a, i32 32)
// CHECK: ret i32 [[VQRSHRUND_N_S64]]
int32_t test_vqrshrund_n_s64(int64_t a) {
return (int32_t)vqrshrund_n_s64(a, 32);
}
-// CHECK-LABEL: define float @test_vcvts_n_f32_s32(i32 %a) #0 {
+// CHECK-LABEL: @test_vcvts_n_f32_s32(
// CHECK: [[VCVTS_N_F32_S32:%.*]] = call float @llvm.aarch64.neon.vcvtfxs2fp.f32.i32(i32 %a, i32 1)
// CHECK: ret float [[VCVTS_N_F32_S32]]
float32_t test_vcvts_n_f32_s32(int32_t a) {
return vcvts_n_f32_s32(a, 1);
}
-// CHECK-LABEL: define double @test_vcvtd_n_f64_s64(i64 %a) #0 {
+// CHECK-LABEL: @test_vcvtd_n_f64_s64(
// CHECK: [[VCVTD_N_F64_S64:%.*]] = call double @llvm.aarch64.neon.vcvtfxs2fp.f64.i64(i64 %a, i32 1)
// CHECK: ret double [[VCVTD_N_F64_S64]]
float64_t test_vcvtd_n_f64_s64(int64_t a) {
return vcvtd_n_f64_s64(a, 1);
}
-// CHECK-LABEL: define float @test_vcvts_n_f32_u32(i32 %a) #0 {
+// CHECK-LABEL: @test_vcvts_n_f32_u32(
// CHECK: [[VCVTS_N_F32_U32:%.*]] = call float @llvm.aarch64.neon.vcvtfxu2fp.f32.i32(i32 %a, i32 32)
// CHECK: ret float [[VCVTS_N_F32_U32]]
float32_t test_vcvts_n_f32_u32(uint32_t a) {
return vcvts_n_f32_u32(a, 32);
}
-// CHECK-LABEL: define double @test_vcvtd_n_f64_u64(i64 %a) #0 {
+// CHECK-LABEL: @test_vcvtd_n_f64_u64(
// CHECK: [[VCVTD_N_F64_U64:%.*]] = call double @llvm.aarch64.neon.vcvtfxu2fp.f64.i64(i64 %a, i32 64)
// CHECK: ret double [[VCVTD_N_F64_U64]]
float64_t test_vcvtd_n_f64_u64(uint64_t a) {
return vcvtd_n_f64_u64(a, 64);
}
-// CHECK-LABEL: define i32 @test_vcvts_n_s32_f32(float %a) #0 {
+// CHECK-LABEL: @test_vcvts_n_s32_f32(
// CHECK: [[VCVTS_N_S32_F32:%.*]] = call i32 @llvm.aarch64.neon.vcvtfp2fxs.i32.f32(float %a, i32 1)
// CHECK: ret i32 [[VCVTS_N_S32_F32]]
int32_t test_vcvts_n_s32_f32(float32_t a) {
return (int32_t)vcvts_n_s32_f32(a, 1);
}
-// CHECK-LABEL: define i64 @test_vcvtd_n_s64_f64(double %a) #0 {
+// CHECK-LABEL: @test_vcvtd_n_s64_f64(
// CHECK: [[VCVTD_N_S64_F64:%.*]] = call i64 @llvm.aarch64.neon.vcvtfp2fxs.i64.f64(double %a, i32 1)
// CHECK: ret i64 [[VCVTD_N_S64_F64]]
int64_t test_vcvtd_n_s64_f64(float64_t a) {
return (int64_t)vcvtd_n_s64_f64(a, 1);
}
-// CHECK-LABEL: define i32 @test_vcvts_n_u32_f32(float %a) #0 {
+// CHECK-LABEL: @test_vcvts_n_u32_f32(
// CHECK: [[VCVTS_N_U32_F32:%.*]] = call i32 @llvm.aarch64.neon.vcvtfp2fxu.i32.f32(float %a, i32 32)
// CHECK: ret i32 [[VCVTS_N_U32_F32]]
uint32_t test_vcvts_n_u32_f32(float32_t a) {
return (uint32_t)vcvts_n_u32_f32(a, 32);
}
-// CHECK-LABEL: define i64 @test_vcvtd_n_u64_f64(double %a) #0 {
+// CHECK-LABEL: @test_vcvtd_n_u64_f64(
// CHECK: [[VCVTD_N_U64_F64:%.*]] = call i64 @llvm.aarch64.neon.vcvtfp2fxu.i64.f64(double %a, i32 64)
// CHECK: ret i64 [[VCVTD_N_U64_F64]]
uint64_t test_vcvtd_n_u64_f64(float64_t a) {
return (uint64_t)vcvtd_n_u64_f64(a, 64);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_s8_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s8_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
int8x8_t test_vreinterpret_s8_s16(int16x4_t a) {
return vreinterpret_s8_s16(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_s8_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s8_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
int8x8_t test_vreinterpret_s8_s32(int32x2_t a) {
return vreinterpret_s8_s32(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_s8_s64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s8_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
int8x8_t test_vreinterpret_s8_s64(int64x1_t a) {
return vreinterpret_s8_s64(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_s8_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s8_u8(
// CHECK: ret <8 x i8> %a
int8x8_t test_vreinterpret_s8_u8(uint8x8_t a) {
return vreinterpret_s8_u8(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_s8_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s8_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
int8x8_t test_vreinterpret_s8_u16(uint16x4_t a) {
return vreinterpret_s8_u16(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_s8_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s8_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
int8x8_t test_vreinterpret_s8_u32(uint32x2_t a) {
return vreinterpret_s8_u32(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_s8_u64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s8_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
int8x8_t test_vreinterpret_s8_u64(uint64x1_t a) {
return vreinterpret_s8_u64(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_s8_f16(<4 x half> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s8_f16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x half> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
int8x8_t test_vreinterpret_s8_f16(float16x4_t a) {
return vreinterpret_s8_f16(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_s8_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s8_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
int8x8_t test_vreinterpret_s8_f32(float32x2_t a) {
return vreinterpret_s8_f32(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_s8_f64(<1 x double> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s8_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
int8x8_t test_vreinterpret_s8_f64(float64x1_t a) {
return vreinterpret_s8_f64(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_s8_p8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s8_p8(
// CHECK: ret <8 x i8> %a
int8x8_t test_vreinterpret_s8_p8(poly8x8_t a) {
return vreinterpret_s8_p8(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_s8_p16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s8_p16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
int8x8_t test_vreinterpret_s8_p16(poly16x4_t a) {
return vreinterpret_s8_p16(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_s8_p64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s8_p64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
int8x8_t test_vreinterpret_s8_p64(poly64x1_t a) {
return vreinterpret_s8_p64(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_s16_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s16_s8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
int16x4_t test_vreinterpret_s16_s8(int8x8_t a) {
return vreinterpret_s16_s8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_s16_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s16_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
int16x4_t test_vreinterpret_s16_s32(int32x2_t a) {
return vreinterpret_s16_s32(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_s16_s64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s16_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
int16x4_t test_vreinterpret_s16_s64(int64x1_t a) {
return vreinterpret_s16_s64(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_s16_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s16_u8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
int16x4_t test_vreinterpret_s16_u8(uint8x8_t a) {
return vreinterpret_s16_u8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_s16_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s16_u16(
// CHECK: ret <4 x i16> %a
int16x4_t test_vreinterpret_s16_u16(uint16x4_t a) {
return vreinterpret_s16_u16(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_s16_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s16_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
int16x4_t test_vreinterpret_s16_u32(uint32x2_t a) {
return vreinterpret_s16_u32(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_s16_u64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s16_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
int16x4_t test_vreinterpret_s16_u64(uint64x1_t a) {
return vreinterpret_s16_u64(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_s16_f16(<4 x half> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s16_f16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x half> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
int16x4_t test_vreinterpret_s16_f16(float16x4_t a) {
return vreinterpret_s16_f16(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_s16_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s16_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
int16x4_t test_vreinterpret_s16_f32(float32x2_t a) {
return vreinterpret_s16_f32(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_s16_f64(<1 x double> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s16_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
int16x4_t test_vreinterpret_s16_f64(float64x1_t a) {
return vreinterpret_s16_f64(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_s16_p8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s16_p8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
int16x4_t test_vreinterpret_s16_p8(poly8x8_t a) {
return vreinterpret_s16_p8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_s16_p16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s16_p16(
// CHECK: ret <4 x i16> %a
int16x4_t test_vreinterpret_s16_p16(poly16x4_t a) {
return vreinterpret_s16_p16(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_s16_p64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s16_p64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
int16x4_t test_vreinterpret_s16_p64(poly64x1_t a) {
return vreinterpret_s16_p64(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vreinterpret_s32_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s32_s8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <2 x i32>
// CHECK: ret <2 x i32> [[TMP0]]
int32x2_t test_vreinterpret_s32_s8(int8x8_t a) {
return vreinterpret_s32_s8(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vreinterpret_s32_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s32_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <2 x i32>
// CHECK: ret <2 x i32> [[TMP0]]
int32x2_t test_vreinterpret_s32_s16(int16x4_t a) {
return vreinterpret_s32_s16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vreinterpret_s32_s64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s32_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <2 x i32>
// CHECK: ret <2 x i32> [[TMP0]]
int32x2_t test_vreinterpret_s32_s64(int64x1_t a) {
return vreinterpret_s32_s64(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vreinterpret_s32_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s32_u8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <2 x i32>
// CHECK: ret <2 x i32> [[TMP0]]
int32x2_t test_vreinterpret_s32_u8(uint8x8_t a) {
return vreinterpret_s32_u8(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vreinterpret_s32_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s32_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <2 x i32>
// CHECK: ret <2 x i32> [[TMP0]]
int32x2_t test_vreinterpret_s32_u16(uint16x4_t a) {
return vreinterpret_s32_u16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vreinterpret_s32_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s32_u32(
// CHECK: ret <2 x i32> %a
int32x2_t test_vreinterpret_s32_u32(uint32x2_t a) {
return vreinterpret_s32_u32(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vreinterpret_s32_u64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s32_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <2 x i32>
// CHECK: ret <2 x i32> [[TMP0]]
int32x2_t test_vreinterpret_s32_u64(uint64x1_t a) {
return vreinterpret_s32_u64(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vreinterpret_s32_f16(<4 x half> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s32_f16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x half> %a to <2 x i32>
// CHECK: ret <2 x i32> [[TMP0]]
int32x2_t test_vreinterpret_s32_f16(float16x4_t a) {
return vreinterpret_s32_f16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vreinterpret_s32_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s32_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <2 x i32>
// CHECK: ret <2 x i32> [[TMP0]]
int32x2_t test_vreinterpret_s32_f32(float32x2_t a) {
return vreinterpret_s32_f32(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vreinterpret_s32_f64(<1 x double> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s32_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <2 x i32>
// CHECK: ret <2 x i32> [[TMP0]]
int32x2_t test_vreinterpret_s32_f64(float64x1_t a) {
return vreinterpret_s32_f64(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vreinterpret_s32_p8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s32_p8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <2 x i32>
// CHECK: ret <2 x i32> [[TMP0]]
int32x2_t test_vreinterpret_s32_p8(poly8x8_t a) {
return vreinterpret_s32_p8(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vreinterpret_s32_p16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s32_p16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <2 x i32>
// CHECK: ret <2 x i32> [[TMP0]]
int32x2_t test_vreinterpret_s32_p16(poly16x4_t a) {
return vreinterpret_s32_p16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vreinterpret_s32_p64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s32_p64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <2 x i32>
// CHECK: ret <2 x i32> [[TMP0]]
int32x2_t test_vreinterpret_s32_p64(poly64x1_t a) {
return vreinterpret_s32_p64(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_s64_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s64_s8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
int64x1_t test_vreinterpret_s64_s8(int8x8_t a) {
return vreinterpret_s64_s8(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_s64_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s64_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
int64x1_t test_vreinterpret_s64_s16(int16x4_t a) {
return vreinterpret_s64_s16(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_s64_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s64_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
int64x1_t test_vreinterpret_s64_s32(int32x2_t a) {
return vreinterpret_s64_s32(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_s64_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s64_u8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
int64x1_t test_vreinterpret_s64_u8(uint8x8_t a) {
return vreinterpret_s64_u8(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_s64_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s64_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
int64x1_t test_vreinterpret_s64_u16(uint16x4_t a) {
return vreinterpret_s64_u16(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_s64_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s64_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
int64x1_t test_vreinterpret_s64_u32(uint32x2_t a) {
return vreinterpret_s64_u32(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_s64_u64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s64_u64(
// CHECK: ret <1 x i64> %a
int64x1_t test_vreinterpret_s64_u64(uint64x1_t a) {
return vreinterpret_s64_u64(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_s64_f16(<4 x half> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s64_f16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x half> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
int64x1_t test_vreinterpret_s64_f16(float16x4_t a) {
return vreinterpret_s64_f16(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_s64_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s64_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
int64x1_t test_vreinterpret_s64_f32(float32x2_t a) {
return vreinterpret_s64_f32(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_s64_f64(<1 x double> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s64_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
int64x1_t test_vreinterpret_s64_f64(float64x1_t a) {
return vreinterpret_s64_f64(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_s64_p8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s64_p8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
int64x1_t test_vreinterpret_s64_p8(poly8x8_t a) {
return vreinterpret_s64_p8(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_s64_p16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s64_p16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
int64x1_t test_vreinterpret_s64_p16(poly16x4_t a) {
return vreinterpret_s64_p16(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_s64_p64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s64_p64(
// CHECK: ret <1 x i64> %a
int64x1_t test_vreinterpret_s64_p64(poly64x1_t a) {
return vreinterpret_s64_p64(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_u8_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u8_s8(
// CHECK: ret <8 x i8> %a
uint8x8_t test_vreinterpret_u8_s8(int8x8_t a) {
return vreinterpret_u8_s8(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_u8_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u8_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
uint8x8_t test_vreinterpret_u8_s16(int16x4_t a) {
return vreinterpret_u8_s16(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_u8_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u8_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
uint8x8_t test_vreinterpret_u8_s32(int32x2_t a) {
return vreinterpret_u8_s32(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_u8_s64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u8_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
uint8x8_t test_vreinterpret_u8_s64(int64x1_t a) {
return vreinterpret_u8_s64(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_u8_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u8_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
uint8x8_t test_vreinterpret_u8_u16(uint16x4_t a) {
return vreinterpret_u8_u16(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_u8_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u8_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
uint8x8_t test_vreinterpret_u8_u32(uint32x2_t a) {
return vreinterpret_u8_u32(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_u8_u64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u8_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
uint8x8_t test_vreinterpret_u8_u64(uint64x1_t a) {
return vreinterpret_u8_u64(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_u8_f16(<4 x half> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u8_f16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x half> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
uint8x8_t test_vreinterpret_u8_f16(float16x4_t a) {
return vreinterpret_u8_f16(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_u8_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u8_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
uint8x8_t test_vreinterpret_u8_f32(float32x2_t a) {
return vreinterpret_u8_f32(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_u8_f64(<1 x double> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u8_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
uint8x8_t test_vreinterpret_u8_f64(float64x1_t a) {
return vreinterpret_u8_f64(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_u8_p8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u8_p8(
// CHECK: ret <8 x i8> %a
uint8x8_t test_vreinterpret_u8_p8(poly8x8_t a) {
return vreinterpret_u8_p8(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_u8_p16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u8_p16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
uint8x8_t test_vreinterpret_u8_p16(poly16x4_t a) {
return vreinterpret_u8_p16(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_u8_p64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u8_p64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
uint8x8_t test_vreinterpret_u8_p64(poly64x1_t a) {
return vreinterpret_u8_p64(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_u16_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u16_s8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
uint16x4_t test_vreinterpret_u16_s8(int8x8_t a) {
return vreinterpret_u16_s8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_u16_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u16_s16(
// CHECK: ret <4 x i16> %a
uint16x4_t test_vreinterpret_u16_s16(int16x4_t a) {
return vreinterpret_u16_s16(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_u16_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u16_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
uint16x4_t test_vreinterpret_u16_s32(int32x2_t a) {
return vreinterpret_u16_s32(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_u16_s64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u16_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
uint16x4_t test_vreinterpret_u16_s64(int64x1_t a) {
return vreinterpret_u16_s64(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_u16_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u16_u8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
uint16x4_t test_vreinterpret_u16_u8(uint8x8_t a) {
return vreinterpret_u16_u8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_u16_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u16_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
uint16x4_t test_vreinterpret_u16_u32(uint32x2_t a) {
return vreinterpret_u16_u32(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_u16_u64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u16_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
uint16x4_t test_vreinterpret_u16_u64(uint64x1_t a) {
return vreinterpret_u16_u64(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_u16_f16(<4 x half> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u16_f16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x half> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
uint16x4_t test_vreinterpret_u16_f16(float16x4_t a) {
return vreinterpret_u16_f16(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_u16_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u16_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
uint16x4_t test_vreinterpret_u16_f32(float32x2_t a) {
return vreinterpret_u16_f32(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_u16_f64(<1 x double> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u16_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
uint16x4_t test_vreinterpret_u16_f64(float64x1_t a) {
return vreinterpret_u16_f64(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_u16_p8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u16_p8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
uint16x4_t test_vreinterpret_u16_p8(poly8x8_t a) {
return vreinterpret_u16_p8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_u16_p16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u16_p16(
// CHECK: ret <4 x i16> %a
uint16x4_t test_vreinterpret_u16_p16(poly16x4_t a) {
return vreinterpret_u16_p16(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_u16_p64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u16_p64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
uint16x4_t test_vreinterpret_u16_p64(poly64x1_t a) {
return vreinterpret_u16_p64(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vreinterpret_u32_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u32_s8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <2 x i32>
// CHECK: ret <2 x i32> [[TMP0]]
uint32x2_t test_vreinterpret_u32_s8(int8x8_t a) {
return vreinterpret_u32_s8(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vreinterpret_u32_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u32_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <2 x i32>
// CHECK: ret <2 x i32> [[TMP0]]
uint32x2_t test_vreinterpret_u32_s16(int16x4_t a) {
return vreinterpret_u32_s16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vreinterpret_u32_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u32_s32(
// CHECK: ret <2 x i32> %a
uint32x2_t test_vreinterpret_u32_s32(int32x2_t a) {
return vreinterpret_u32_s32(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vreinterpret_u32_s64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u32_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <2 x i32>
// CHECK: ret <2 x i32> [[TMP0]]
uint32x2_t test_vreinterpret_u32_s64(int64x1_t a) {
return vreinterpret_u32_s64(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vreinterpret_u32_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u32_u8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <2 x i32>
// CHECK: ret <2 x i32> [[TMP0]]
uint32x2_t test_vreinterpret_u32_u8(uint8x8_t a) {
return vreinterpret_u32_u8(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vreinterpret_u32_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u32_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <2 x i32>
// CHECK: ret <2 x i32> [[TMP0]]
uint32x2_t test_vreinterpret_u32_u16(uint16x4_t a) {
return vreinterpret_u32_u16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vreinterpret_u32_u64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u32_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <2 x i32>
// CHECK: ret <2 x i32> [[TMP0]]
uint32x2_t test_vreinterpret_u32_u64(uint64x1_t a) {
return vreinterpret_u32_u64(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vreinterpret_u32_f16(<4 x half> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u32_f16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x half> %a to <2 x i32>
// CHECK: ret <2 x i32> [[TMP0]]
uint32x2_t test_vreinterpret_u32_f16(float16x4_t a) {
return vreinterpret_u32_f16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vreinterpret_u32_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u32_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <2 x i32>
// CHECK: ret <2 x i32> [[TMP0]]
uint32x2_t test_vreinterpret_u32_f32(float32x2_t a) {
return vreinterpret_u32_f32(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vreinterpret_u32_f64(<1 x double> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u32_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <2 x i32>
// CHECK: ret <2 x i32> [[TMP0]]
uint32x2_t test_vreinterpret_u32_f64(float64x1_t a) {
return vreinterpret_u32_f64(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vreinterpret_u32_p8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u32_p8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <2 x i32>
// CHECK: ret <2 x i32> [[TMP0]]
uint32x2_t test_vreinterpret_u32_p8(poly8x8_t a) {
return vreinterpret_u32_p8(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vreinterpret_u32_p16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u32_p16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <2 x i32>
// CHECK: ret <2 x i32> [[TMP0]]
uint32x2_t test_vreinterpret_u32_p16(poly16x4_t a) {
return vreinterpret_u32_p16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vreinterpret_u32_p64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u32_p64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <2 x i32>
// CHECK: ret <2 x i32> [[TMP0]]
uint32x2_t test_vreinterpret_u32_p64(poly64x1_t a) {
return vreinterpret_u32_p64(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_u64_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u64_s8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
uint64x1_t test_vreinterpret_u64_s8(int8x8_t a) {
return vreinterpret_u64_s8(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_u64_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u64_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
uint64x1_t test_vreinterpret_u64_s16(int16x4_t a) {
return vreinterpret_u64_s16(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_u64_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u64_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
uint64x1_t test_vreinterpret_u64_s32(int32x2_t a) {
return vreinterpret_u64_s32(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_u64_s64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u64_s64(
// CHECK: ret <1 x i64> %a
uint64x1_t test_vreinterpret_u64_s64(int64x1_t a) {
return vreinterpret_u64_s64(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_u64_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u64_u8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
uint64x1_t test_vreinterpret_u64_u8(uint8x8_t a) {
return vreinterpret_u64_u8(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_u64_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u64_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
uint64x1_t test_vreinterpret_u64_u16(uint16x4_t a) {
return vreinterpret_u64_u16(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_u64_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u64_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
uint64x1_t test_vreinterpret_u64_u32(uint32x2_t a) {
return vreinterpret_u64_u32(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_u64_f16(<4 x half> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u64_f16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x half> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
uint64x1_t test_vreinterpret_u64_f16(float16x4_t a) {
return vreinterpret_u64_f16(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_u64_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u64_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
uint64x1_t test_vreinterpret_u64_f32(float32x2_t a) {
return vreinterpret_u64_f32(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_u64_f64(<1 x double> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u64_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
uint64x1_t test_vreinterpret_u64_f64(float64x1_t a) {
return vreinterpret_u64_f64(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_u64_p8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u64_p8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
uint64x1_t test_vreinterpret_u64_p8(poly8x8_t a) {
return vreinterpret_u64_p8(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_u64_p16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u64_p16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
uint64x1_t test_vreinterpret_u64_p16(poly16x4_t a) {
return vreinterpret_u64_p16(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_u64_p64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u64_p64(
// CHECK: ret <1 x i64> %a
uint64x1_t test_vreinterpret_u64_p64(poly64x1_t a) {
return vreinterpret_u64_p64(a);
}
-// CHECK-LABEL: define <4 x half> @test_vreinterpret_f16_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f16_s8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <4 x half>
// CHECK: ret <4 x half> [[TMP0]]
float16x4_t test_vreinterpret_f16_s8(int8x8_t a) {
return vreinterpret_f16_s8(a);
}
-// CHECK-LABEL: define <4 x half> @test_vreinterpret_f16_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f16_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <4 x half>
// CHECK: ret <4 x half> [[TMP0]]
float16x4_t test_vreinterpret_f16_s16(int16x4_t a) {
return vreinterpret_f16_s16(a);
}
-// CHECK-LABEL: define <4 x half> @test_vreinterpret_f16_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f16_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <4 x half>
// CHECK: ret <4 x half> [[TMP0]]
float16x4_t test_vreinterpret_f16_s32(int32x2_t a) {
return vreinterpret_f16_s32(a);
}
-// CHECK-LABEL: define <4 x half> @test_vreinterpret_f16_s64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f16_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <4 x half>
// CHECK: ret <4 x half> [[TMP0]]
float16x4_t test_vreinterpret_f16_s64(int64x1_t a) {
return vreinterpret_f16_s64(a);
}
-// CHECK-LABEL: define <4 x half> @test_vreinterpret_f16_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f16_u8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <4 x half>
// CHECK: ret <4 x half> [[TMP0]]
float16x4_t test_vreinterpret_f16_u8(uint8x8_t a) {
return vreinterpret_f16_u8(a);
}
-// CHECK-LABEL: define <4 x half> @test_vreinterpret_f16_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f16_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <4 x half>
// CHECK: ret <4 x half> [[TMP0]]
float16x4_t test_vreinterpret_f16_u16(uint16x4_t a) {
return vreinterpret_f16_u16(a);
}
-// CHECK-LABEL: define <4 x half> @test_vreinterpret_f16_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f16_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <4 x half>
// CHECK: ret <4 x half> [[TMP0]]
float16x4_t test_vreinterpret_f16_u32(uint32x2_t a) {
return vreinterpret_f16_u32(a);
}
-// CHECK-LABEL: define <4 x half> @test_vreinterpret_f16_u64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f16_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <4 x half>
// CHECK: ret <4 x half> [[TMP0]]
float16x4_t test_vreinterpret_f16_u64(uint64x1_t a) {
return vreinterpret_f16_u64(a);
}
-// CHECK-LABEL: define <4 x half> @test_vreinterpret_f16_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f16_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <4 x half>
// CHECK: ret <4 x half> [[TMP0]]
float16x4_t test_vreinterpret_f16_f32(float32x2_t a) {
return vreinterpret_f16_f32(a);
}
-// CHECK-LABEL: define <4 x half> @test_vreinterpret_f16_f64(<1 x double> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f16_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <4 x half>
// CHECK: ret <4 x half> [[TMP0]]
float16x4_t test_vreinterpret_f16_f64(float64x1_t a) {
return vreinterpret_f16_f64(a);
}
-// CHECK-LABEL: define <4 x half> @test_vreinterpret_f16_p8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f16_p8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <4 x half>
// CHECK: ret <4 x half> [[TMP0]]
float16x4_t test_vreinterpret_f16_p8(poly8x8_t a) {
return vreinterpret_f16_p8(a);
}
-// CHECK-LABEL: define <4 x half> @test_vreinterpret_f16_p16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f16_p16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <4 x half>
// CHECK: ret <4 x half> [[TMP0]]
float16x4_t test_vreinterpret_f16_p16(poly16x4_t a) {
return vreinterpret_f16_p16(a);
}
-// CHECK-LABEL: define <4 x half> @test_vreinterpret_f16_p64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f16_p64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <4 x half>
// CHECK: ret <4 x half> [[TMP0]]
float16x4_t test_vreinterpret_f16_p64(poly64x1_t a) {
return vreinterpret_f16_p64(a);
}
-// CHECK-LABEL: define <2 x float> @test_vreinterpret_f32_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f32_s8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <2 x float>
// CHECK: ret <2 x float> [[TMP0]]
float32x2_t test_vreinterpret_f32_s8(int8x8_t a) {
return vreinterpret_f32_s8(a);
}
-// CHECK-LABEL: define <2 x float> @test_vreinterpret_f32_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f32_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <2 x float>
// CHECK: ret <2 x float> [[TMP0]]
float32x2_t test_vreinterpret_f32_s16(int16x4_t a) {
return vreinterpret_f32_s16(a);
}
-// CHECK-LABEL: define <2 x float> @test_vreinterpret_f32_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f32_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <2 x float>
// CHECK: ret <2 x float> [[TMP0]]
float32x2_t test_vreinterpret_f32_s32(int32x2_t a) {
return vreinterpret_f32_s32(a);
}
-// CHECK-LABEL: define <2 x float> @test_vreinterpret_f32_s64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f32_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <2 x float>
// CHECK: ret <2 x float> [[TMP0]]
float32x2_t test_vreinterpret_f32_s64(int64x1_t a) {
return vreinterpret_f32_s64(a);
}
-// CHECK-LABEL: define <2 x float> @test_vreinterpret_f32_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f32_u8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <2 x float>
// CHECK: ret <2 x float> [[TMP0]]
float32x2_t test_vreinterpret_f32_u8(uint8x8_t a) {
return vreinterpret_f32_u8(a);
}
-// CHECK-LABEL: define <2 x float> @test_vreinterpret_f32_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f32_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <2 x float>
// CHECK: ret <2 x float> [[TMP0]]
float32x2_t test_vreinterpret_f32_u16(uint16x4_t a) {
return vreinterpret_f32_u16(a);
}
-// CHECK-LABEL: define <2 x float> @test_vreinterpret_f32_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f32_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <2 x float>
// CHECK: ret <2 x float> [[TMP0]]
float32x2_t test_vreinterpret_f32_u32(uint32x2_t a) {
return vreinterpret_f32_u32(a);
}
-// CHECK-LABEL: define <2 x float> @test_vreinterpret_f32_u64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f32_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <2 x float>
// CHECK: ret <2 x float> [[TMP0]]
float32x2_t test_vreinterpret_f32_u64(uint64x1_t a) {
return vreinterpret_f32_u64(a);
}
-// CHECK-LABEL: define <2 x float> @test_vreinterpret_f32_f16(<4 x half> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f32_f16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x half> %a to <2 x float>
// CHECK: ret <2 x float> [[TMP0]]
float32x2_t test_vreinterpret_f32_f16(float16x4_t a) {
return vreinterpret_f32_f16(a);
}
-// CHECK-LABEL: define <2 x float> @test_vreinterpret_f32_f64(<1 x double> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f32_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <2 x float>
// CHECK: ret <2 x float> [[TMP0]]
float32x2_t test_vreinterpret_f32_f64(float64x1_t a) {
return vreinterpret_f32_f64(a);
}
-// CHECK-LABEL: define <2 x float> @test_vreinterpret_f32_p8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f32_p8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <2 x float>
// CHECK: ret <2 x float> [[TMP0]]
float32x2_t test_vreinterpret_f32_p8(poly8x8_t a) {
return vreinterpret_f32_p8(a);
}
-// CHECK-LABEL: define <2 x float> @test_vreinterpret_f32_p16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f32_p16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <2 x float>
// CHECK: ret <2 x float> [[TMP0]]
float32x2_t test_vreinterpret_f32_p16(poly16x4_t a) {
return vreinterpret_f32_p16(a);
}
-// CHECK-LABEL: define <2 x float> @test_vreinterpret_f32_p64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f32_p64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <2 x float>
// CHECK: ret <2 x float> [[TMP0]]
float32x2_t test_vreinterpret_f32_p64(poly64x1_t a) {
return vreinterpret_f32_p64(a);
}
-// CHECK-LABEL: define <1 x double> @test_vreinterpret_f64_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f64_s8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <1 x double>
// CHECK: ret <1 x double> [[TMP0]]
float64x1_t test_vreinterpret_f64_s8(int8x8_t a) {
return vreinterpret_f64_s8(a);
}
-// CHECK-LABEL: define <1 x double> @test_vreinterpret_f64_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f64_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <1 x double>
// CHECK: ret <1 x double> [[TMP0]]
float64x1_t test_vreinterpret_f64_s16(int16x4_t a) {
return vreinterpret_f64_s16(a);
}
-// CHECK-LABEL: define <1 x double> @test_vreinterpret_f64_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f64_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <1 x double>
// CHECK: ret <1 x double> [[TMP0]]
float64x1_t test_vreinterpret_f64_s32(int32x2_t a) {
return vreinterpret_f64_s32(a);
}
-// CHECK-LABEL: define <1 x double> @test_vreinterpret_f64_s64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f64_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <1 x double>
// CHECK: ret <1 x double> [[TMP0]]
float64x1_t test_vreinterpret_f64_s64(int64x1_t a) {
return vreinterpret_f64_s64(a);
}
-// CHECK-LABEL: define <1 x double> @test_vreinterpret_f64_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f64_u8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <1 x double>
// CHECK: ret <1 x double> [[TMP0]]
float64x1_t test_vreinterpret_f64_u8(uint8x8_t a) {
return vreinterpret_f64_u8(a);
}
-// CHECK-LABEL: define <1 x double> @test_vreinterpret_f64_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f64_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <1 x double>
// CHECK: ret <1 x double> [[TMP0]]
float64x1_t test_vreinterpret_f64_u16(uint16x4_t a) {
return vreinterpret_f64_u16(a);
}
-// CHECK-LABEL: define <1 x double> @test_vreinterpret_f64_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f64_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <1 x double>
// CHECK: ret <1 x double> [[TMP0]]
float64x1_t test_vreinterpret_f64_u32(uint32x2_t a) {
return vreinterpret_f64_u32(a);
}
-// CHECK-LABEL: define <1 x double> @test_vreinterpret_f64_u64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f64_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <1 x double>
// CHECK: ret <1 x double> [[TMP0]]
float64x1_t test_vreinterpret_f64_u64(uint64x1_t a) {
return vreinterpret_f64_u64(a);
}
-// CHECK-LABEL: define <1 x double> @test_vreinterpret_f64_f16(<4 x half> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f64_f16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x half> %a to <1 x double>
// CHECK: ret <1 x double> [[TMP0]]
float64x1_t test_vreinterpret_f64_f16(float16x4_t a) {
return vreinterpret_f64_f16(a);
}
-// CHECK-LABEL: define <1 x double> @test_vreinterpret_f64_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f64_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <1 x double>
// CHECK: ret <1 x double> [[TMP0]]
float64x1_t test_vreinterpret_f64_f32(float32x2_t a) {
return vreinterpret_f64_f32(a);
}
-// CHECK-LABEL: define <1 x double> @test_vreinterpret_f64_p8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f64_p8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <1 x double>
// CHECK: ret <1 x double> [[TMP0]]
float64x1_t test_vreinterpret_f64_p8(poly8x8_t a) {
return vreinterpret_f64_p8(a);
}
-// CHECK-LABEL: define <1 x double> @test_vreinterpret_f64_p16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f64_p16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <1 x double>
// CHECK: ret <1 x double> [[TMP0]]
float64x1_t test_vreinterpret_f64_p16(poly16x4_t a) {
return vreinterpret_f64_p16(a);
}
-// CHECK-LABEL: define <1 x double> @test_vreinterpret_f64_p64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f64_p64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <1 x double>
// CHECK: ret <1 x double> [[TMP0]]
float64x1_t test_vreinterpret_f64_p64(poly64x1_t a) {
return vreinterpret_f64_p64(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_p8_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p8_s8(
// CHECK: ret <8 x i8> %a
poly8x8_t test_vreinterpret_p8_s8(int8x8_t a) {
return vreinterpret_p8_s8(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_p8_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p8_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
poly8x8_t test_vreinterpret_p8_s16(int16x4_t a) {
return vreinterpret_p8_s16(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_p8_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p8_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
poly8x8_t test_vreinterpret_p8_s32(int32x2_t a) {
return vreinterpret_p8_s32(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_p8_s64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p8_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
poly8x8_t test_vreinterpret_p8_s64(int64x1_t a) {
return vreinterpret_p8_s64(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_p8_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p8_u8(
// CHECK: ret <8 x i8> %a
poly8x8_t test_vreinterpret_p8_u8(uint8x8_t a) {
return vreinterpret_p8_u8(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_p8_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p8_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
poly8x8_t test_vreinterpret_p8_u16(uint16x4_t a) {
return vreinterpret_p8_u16(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_p8_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p8_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
poly8x8_t test_vreinterpret_p8_u32(uint32x2_t a) {
return vreinterpret_p8_u32(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_p8_u64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p8_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
poly8x8_t test_vreinterpret_p8_u64(uint64x1_t a) {
return vreinterpret_p8_u64(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_p8_f16(<4 x half> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p8_f16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x half> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
poly8x8_t test_vreinterpret_p8_f16(float16x4_t a) {
return vreinterpret_p8_f16(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_p8_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p8_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
poly8x8_t test_vreinterpret_p8_f32(float32x2_t a) {
return vreinterpret_p8_f32(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_p8_f64(<1 x double> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p8_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
poly8x8_t test_vreinterpret_p8_f64(float64x1_t a) {
return vreinterpret_p8_f64(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_p8_p16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p8_p16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
poly8x8_t test_vreinterpret_p8_p16(poly16x4_t a) {
return vreinterpret_p8_p16(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_p8_p64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p8_p64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
poly8x8_t test_vreinterpret_p8_p64(poly64x1_t a) {
return vreinterpret_p8_p64(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_p16_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p16_s8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
poly16x4_t test_vreinterpret_p16_s8(int8x8_t a) {
return vreinterpret_p16_s8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_p16_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p16_s16(
// CHECK: ret <4 x i16> %a
poly16x4_t test_vreinterpret_p16_s16(int16x4_t a) {
return vreinterpret_p16_s16(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_p16_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p16_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
poly16x4_t test_vreinterpret_p16_s32(int32x2_t a) {
return vreinterpret_p16_s32(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_p16_s64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p16_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
poly16x4_t test_vreinterpret_p16_s64(int64x1_t a) {
return vreinterpret_p16_s64(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_p16_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p16_u8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
poly16x4_t test_vreinterpret_p16_u8(uint8x8_t a) {
return vreinterpret_p16_u8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_p16_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p16_u16(
// CHECK: ret <4 x i16> %a
poly16x4_t test_vreinterpret_p16_u16(uint16x4_t a) {
return vreinterpret_p16_u16(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_p16_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p16_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
poly16x4_t test_vreinterpret_p16_u32(uint32x2_t a) {
return vreinterpret_p16_u32(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_p16_u64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p16_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
poly16x4_t test_vreinterpret_p16_u64(uint64x1_t a) {
return vreinterpret_p16_u64(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_p16_f16(<4 x half> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p16_f16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x half> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
poly16x4_t test_vreinterpret_p16_f16(float16x4_t a) {
return vreinterpret_p16_f16(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_p16_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p16_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
poly16x4_t test_vreinterpret_p16_f32(float32x2_t a) {
return vreinterpret_p16_f32(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_p16_f64(<1 x double> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p16_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
poly16x4_t test_vreinterpret_p16_f64(float64x1_t a) {
return vreinterpret_p16_f64(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_p16_p8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p16_p8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
poly16x4_t test_vreinterpret_p16_p8(poly8x8_t a) {
return vreinterpret_p16_p8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_p16_p64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p16_p64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
poly16x4_t test_vreinterpret_p16_p64(poly64x1_t a) {
return vreinterpret_p16_p64(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_p64_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p64_s8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
poly64x1_t test_vreinterpret_p64_s8(int8x8_t a) {
return vreinterpret_p64_s8(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_p64_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p64_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
poly64x1_t test_vreinterpret_p64_s16(int16x4_t a) {
return vreinterpret_p64_s16(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_p64_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p64_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
poly64x1_t test_vreinterpret_p64_s32(int32x2_t a) {
return vreinterpret_p64_s32(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_p64_s64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p64_s64(
// CHECK: ret <1 x i64> %a
poly64x1_t test_vreinterpret_p64_s64(int64x1_t a) {
return vreinterpret_p64_s64(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_p64_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p64_u8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
poly64x1_t test_vreinterpret_p64_u8(uint8x8_t a) {
return vreinterpret_p64_u8(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_p64_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p64_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
poly64x1_t test_vreinterpret_p64_u16(uint16x4_t a) {
return vreinterpret_p64_u16(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_p64_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p64_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
poly64x1_t test_vreinterpret_p64_u32(uint32x2_t a) {
return vreinterpret_p64_u32(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_p64_u64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p64_u64(
// CHECK: ret <1 x i64> %a
poly64x1_t test_vreinterpret_p64_u64(uint64x1_t a) {
return vreinterpret_p64_u64(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_p64_f16(<4 x half> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p64_f16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x half> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
poly64x1_t test_vreinterpret_p64_f16(float16x4_t a) {
return vreinterpret_p64_f16(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_p64_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p64_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
poly64x1_t test_vreinterpret_p64_f32(float32x2_t a) {
return vreinterpret_p64_f32(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_p64_f64(<1 x double> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p64_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
poly64x1_t test_vreinterpret_p64_f64(float64x1_t a) {
return vreinterpret_p64_f64(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_p64_p8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p64_p8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
poly64x1_t test_vreinterpret_p64_p8(poly8x8_t a) {
return vreinterpret_p64_p8(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_p64_p16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p64_p16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
poly64x1_t test_vreinterpret_p64_p16(poly16x4_t a) {
return vreinterpret_p64_p16(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_s8_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s8_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
int8x16_t test_vreinterpretq_s8_s16(int16x8_t a) {
return vreinterpretq_s8_s16(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_s8_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s8_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
int8x16_t test_vreinterpretq_s8_s32(int32x4_t a) {
return vreinterpretq_s8_s32(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_s8_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s8_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
int8x16_t test_vreinterpretq_s8_s64(int64x2_t a) {
return vreinterpretq_s8_s64(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_s8_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s8_u8(
// CHECK: ret <16 x i8> %a
int8x16_t test_vreinterpretq_s8_u8(uint8x16_t a) {
return vreinterpretq_s8_u8(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_s8_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s8_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
int8x16_t test_vreinterpretq_s8_u16(uint16x8_t a) {
return vreinterpretq_s8_u16(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_s8_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s8_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
int8x16_t test_vreinterpretq_s8_u32(uint32x4_t a) {
return vreinterpretq_s8_u32(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_s8_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s8_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
int8x16_t test_vreinterpretq_s8_u64(uint64x2_t a) {
return vreinterpretq_s8_u64(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_s8_f16(<8 x half> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s8_f16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x half> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
int8x16_t test_vreinterpretq_s8_f16(float16x8_t a) {
return vreinterpretq_s8_f16(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_s8_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s8_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
int8x16_t test_vreinterpretq_s8_f32(float32x4_t a) {
return vreinterpretq_s8_f32(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_s8_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s8_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
int8x16_t test_vreinterpretq_s8_f64(float64x2_t a) {
return vreinterpretq_s8_f64(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_s8_p8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s8_p8(
// CHECK: ret <16 x i8> %a
int8x16_t test_vreinterpretq_s8_p8(poly8x16_t a) {
return vreinterpretq_s8_p8(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_s8_p16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s8_p16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
int8x16_t test_vreinterpretq_s8_p16(poly16x8_t a) {
return vreinterpretq_s8_p16(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_s8_p64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s8_p64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
int8x16_t test_vreinterpretq_s8_p64(poly64x2_t a) {
return vreinterpretq_s8_p64(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_s16_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s16_s8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
int16x8_t test_vreinterpretq_s16_s8(int8x16_t a) {
return vreinterpretq_s16_s8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_s16_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s16_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
int16x8_t test_vreinterpretq_s16_s32(int32x4_t a) {
return vreinterpretq_s16_s32(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_s16_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s16_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
int16x8_t test_vreinterpretq_s16_s64(int64x2_t a) {
return vreinterpretq_s16_s64(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_s16_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s16_u8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
int16x8_t test_vreinterpretq_s16_u8(uint8x16_t a) {
return vreinterpretq_s16_u8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_s16_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s16_u16(
// CHECK: ret <8 x i16> %a
int16x8_t test_vreinterpretq_s16_u16(uint16x8_t a) {
return vreinterpretq_s16_u16(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_s16_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s16_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
int16x8_t test_vreinterpretq_s16_u32(uint32x4_t a) {
return vreinterpretq_s16_u32(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_s16_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s16_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
int16x8_t test_vreinterpretq_s16_u64(uint64x2_t a) {
return vreinterpretq_s16_u64(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_s16_f16(<8 x half> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s16_f16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x half> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
int16x8_t test_vreinterpretq_s16_f16(float16x8_t a) {
return vreinterpretq_s16_f16(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_s16_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s16_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
int16x8_t test_vreinterpretq_s16_f32(float32x4_t a) {
return vreinterpretq_s16_f32(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_s16_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s16_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
int16x8_t test_vreinterpretq_s16_f64(float64x2_t a) {
return vreinterpretq_s16_f64(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_s16_p8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s16_p8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
int16x8_t test_vreinterpretq_s16_p8(poly8x16_t a) {
return vreinterpretq_s16_p8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_s16_p16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s16_p16(
// CHECK: ret <8 x i16> %a
int16x8_t test_vreinterpretq_s16_p16(poly16x8_t a) {
return vreinterpretq_s16_p16(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_s16_p64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s16_p64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
int16x8_t test_vreinterpretq_s16_p64(poly64x2_t a) {
return vreinterpretq_s16_p64(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_s32_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s32_s8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <4 x i32>
// CHECK: ret <4 x i32> [[TMP0]]
int32x4_t test_vreinterpretq_s32_s8(int8x16_t a) {
return vreinterpretq_s32_s8(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_s32_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s32_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <4 x i32>
// CHECK: ret <4 x i32> [[TMP0]]
int32x4_t test_vreinterpretq_s32_s16(int16x8_t a) {
return vreinterpretq_s32_s16(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_s32_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s32_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <4 x i32>
// CHECK: ret <4 x i32> [[TMP0]]
int32x4_t test_vreinterpretq_s32_s64(int64x2_t a) {
return vreinterpretq_s32_s64(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_s32_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s32_u8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <4 x i32>
// CHECK: ret <4 x i32> [[TMP0]]
int32x4_t test_vreinterpretq_s32_u8(uint8x16_t a) {
return vreinterpretq_s32_u8(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_s32_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s32_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <4 x i32>
// CHECK: ret <4 x i32> [[TMP0]]
int32x4_t test_vreinterpretq_s32_u16(uint16x8_t a) {
return vreinterpretq_s32_u16(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_s32_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s32_u32(
// CHECK: ret <4 x i32> %a
int32x4_t test_vreinterpretq_s32_u32(uint32x4_t a) {
return vreinterpretq_s32_u32(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_s32_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s32_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <4 x i32>
// CHECK: ret <4 x i32> [[TMP0]]
int32x4_t test_vreinterpretq_s32_u64(uint64x2_t a) {
return vreinterpretq_s32_u64(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_s32_f16(<8 x half> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s32_f16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x half> %a to <4 x i32>
// CHECK: ret <4 x i32> [[TMP0]]
int32x4_t test_vreinterpretq_s32_f16(float16x8_t a) {
return vreinterpretq_s32_f16(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_s32_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s32_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <4 x i32>
// CHECK: ret <4 x i32> [[TMP0]]
int32x4_t test_vreinterpretq_s32_f32(float32x4_t a) {
return vreinterpretq_s32_f32(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_s32_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s32_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <4 x i32>
// CHECK: ret <4 x i32> [[TMP0]]
int32x4_t test_vreinterpretq_s32_f64(float64x2_t a) {
return vreinterpretq_s32_f64(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_s32_p8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s32_p8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <4 x i32>
// CHECK: ret <4 x i32> [[TMP0]]
int32x4_t test_vreinterpretq_s32_p8(poly8x16_t a) {
return vreinterpretq_s32_p8(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_s32_p16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s32_p16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <4 x i32>
// CHECK: ret <4 x i32> [[TMP0]]
int32x4_t test_vreinterpretq_s32_p16(poly16x8_t a) {
return vreinterpretq_s32_p16(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_s32_p64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s32_p64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <4 x i32>
// CHECK: ret <4 x i32> [[TMP0]]
int32x4_t test_vreinterpretq_s32_p64(poly64x2_t a) {
return vreinterpretq_s32_p64(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_s64_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s64_s8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
int64x2_t test_vreinterpretq_s64_s8(int8x16_t a) {
return vreinterpretq_s64_s8(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_s64_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s64_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
int64x2_t test_vreinterpretq_s64_s16(int16x8_t a) {
return vreinterpretq_s64_s16(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_s64_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s64_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
int64x2_t test_vreinterpretq_s64_s32(int32x4_t a) {
return vreinterpretq_s64_s32(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_s64_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s64_u8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
int64x2_t test_vreinterpretq_s64_u8(uint8x16_t a) {
return vreinterpretq_s64_u8(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_s64_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s64_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
int64x2_t test_vreinterpretq_s64_u16(uint16x8_t a) {
return vreinterpretq_s64_u16(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_s64_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s64_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
int64x2_t test_vreinterpretq_s64_u32(uint32x4_t a) {
return vreinterpretq_s64_u32(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_s64_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s64_u64(
// CHECK: ret <2 x i64> %a
int64x2_t test_vreinterpretq_s64_u64(uint64x2_t a) {
return vreinterpretq_s64_u64(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_s64_f16(<8 x half> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s64_f16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x half> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
int64x2_t test_vreinterpretq_s64_f16(float16x8_t a) {
return vreinterpretq_s64_f16(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_s64_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s64_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
int64x2_t test_vreinterpretq_s64_f32(float32x4_t a) {
return vreinterpretq_s64_f32(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_s64_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s64_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
int64x2_t test_vreinterpretq_s64_f64(float64x2_t a) {
return vreinterpretq_s64_f64(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_s64_p8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s64_p8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
int64x2_t test_vreinterpretq_s64_p8(poly8x16_t a) {
return vreinterpretq_s64_p8(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_s64_p16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s64_p16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
int64x2_t test_vreinterpretq_s64_p16(poly16x8_t a) {
return vreinterpretq_s64_p16(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_s64_p64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s64_p64(
// CHECK: ret <2 x i64> %a
int64x2_t test_vreinterpretq_s64_p64(poly64x2_t a) {
return vreinterpretq_s64_p64(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_u8_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u8_s8(
// CHECK: ret <16 x i8> %a
uint8x16_t test_vreinterpretq_u8_s8(int8x16_t a) {
return vreinterpretq_u8_s8(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_u8_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u8_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
uint8x16_t test_vreinterpretq_u8_s16(int16x8_t a) {
return vreinterpretq_u8_s16(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_u8_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u8_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
uint8x16_t test_vreinterpretq_u8_s32(int32x4_t a) {
return vreinterpretq_u8_s32(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_u8_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u8_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
uint8x16_t test_vreinterpretq_u8_s64(int64x2_t a) {
return vreinterpretq_u8_s64(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_u8_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u8_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
uint8x16_t test_vreinterpretq_u8_u16(uint16x8_t a) {
return vreinterpretq_u8_u16(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_u8_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u8_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
uint8x16_t test_vreinterpretq_u8_u32(uint32x4_t a) {
return vreinterpretq_u8_u32(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_u8_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u8_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
uint8x16_t test_vreinterpretq_u8_u64(uint64x2_t a) {
return vreinterpretq_u8_u64(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_u8_f16(<8 x half> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u8_f16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x half> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
uint8x16_t test_vreinterpretq_u8_f16(float16x8_t a) {
return vreinterpretq_u8_f16(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_u8_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u8_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
uint8x16_t test_vreinterpretq_u8_f32(float32x4_t a) {
return vreinterpretq_u8_f32(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_u8_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u8_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
uint8x16_t test_vreinterpretq_u8_f64(float64x2_t a) {
return vreinterpretq_u8_f64(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_u8_p8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u8_p8(
// CHECK: ret <16 x i8> %a
uint8x16_t test_vreinterpretq_u8_p8(poly8x16_t a) {
return vreinterpretq_u8_p8(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_u8_p16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u8_p16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
uint8x16_t test_vreinterpretq_u8_p16(poly16x8_t a) {
return vreinterpretq_u8_p16(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_u8_p64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u8_p64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
uint8x16_t test_vreinterpretq_u8_p64(poly64x2_t a) {
return vreinterpretq_u8_p64(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_u16_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u16_s8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
uint16x8_t test_vreinterpretq_u16_s8(int8x16_t a) {
return vreinterpretq_u16_s8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_u16_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u16_s16(
// CHECK: ret <8 x i16> %a
uint16x8_t test_vreinterpretq_u16_s16(int16x8_t a) {
return vreinterpretq_u16_s16(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_u16_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u16_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
uint16x8_t test_vreinterpretq_u16_s32(int32x4_t a) {
return vreinterpretq_u16_s32(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_u16_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u16_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
uint16x8_t test_vreinterpretq_u16_s64(int64x2_t a) {
return vreinterpretq_u16_s64(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_u16_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u16_u8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
uint16x8_t test_vreinterpretq_u16_u8(uint8x16_t a) {
return vreinterpretq_u16_u8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_u16_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u16_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
uint16x8_t test_vreinterpretq_u16_u32(uint32x4_t a) {
return vreinterpretq_u16_u32(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_u16_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u16_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
uint16x8_t test_vreinterpretq_u16_u64(uint64x2_t a) {
return vreinterpretq_u16_u64(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_u16_f16(<8 x half> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u16_f16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x half> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
uint16x8_t test_vreinterpretq_u16_f16(float16x8_t a) {
return vreinterpretq_u16_f16(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_u16_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u16_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
uint16x8_t test_vreinterpretq_u16_f32(float32x4_t a) {
return vreinterpretq_u16_f32(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_u16_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u16_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
uint16x8_t test_vreinterpretq_u16_f64(float64x2_t a) {
return vreinterpretq_u16_f64(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_u16_p8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u16_p8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
uint16x8_t test_vreinterpretq_u16_p8(poly8x16_t a) {
return vreinterpretq_u16_p8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_u16_p16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u16_p16(
// CHECK: ret <8 x i16> %a
uint16x8_t test_vreinterpretq_u16_p16(poly16x8_t a) {
return vreinterpretq_u16_p16(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_u16_p64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u16_p64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
uint16x8_t test_vreinterpretq_u16_p64(poly64x2_t a) {
return vreinterpretq_u16_p64(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_u32_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u32_s8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <4 x i32>
// CHECK: ret <4 x i32> [[TMP0]]
uint32x4_t test_vreinterpretq_u32_s8(int8x16_t a) {
return vreinterpretq_u32_s8(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_u32_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u32_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <4 x i32>
// CHECK: ret <4 x i32> [[TMP0]]
uint32x4_t test_vreinterpretq_u32_s16(int16x8_t a) {
return vreinterpretq_u32_s16(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_u32_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u32_s32(
// CHECK: ret <4 x i32> %a
uint32x4_t test_vreinterpretq_u32_s32(int32x4_t a) {
return vreinterpretq_u32_s32(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_u32_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u32_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <4 x i32>
// CHECK: ret <4 x i32> [[TMP0]]
uint32x4_t test_vreinterpretq_u32_s64(int64x2_t a) {
return vreinterpretq_u32_s64(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_u32_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u32_u8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <4 x i32>
// CHECK: ret <4 x i32> [[TMP0]]
uint32x4_t test_vreinterpretq_u32_u8(uint8x16_t a) {
return vreinterpretq_u32_u8(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_u32_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u32_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <4 x i32>
// CHECK: ret <4 x i32> [[TMP0]]
uint32x4_t test_vreinterpretq_u32_u16(uint16x8_t a) {
return vreinterpretq_u32_u16(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_u32_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u32_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <4 x i32>
// CHECK: ret <4 x i32> [[TMP0]]
uint32x4_t test_vreinterpretq_u32_u64(uint64x2_t a) {
return vreinterpretq_u32_u64(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_u32_f16(<8 x half> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u32_f16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x half> %a to <4 x i32>
// CHECK: ret <4 x i32> [[TMP0]]
uint32x4_t test_vreinterpretq_u32_f16(float16x8_t a) {
return vreinterpretq_u32_f16(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_u32_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u32_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <4 x i32>
// CHECK: ret <4 x i32> [[TMP0]]
uint32x4_t test_vreinterpretq_u32_f32(float32x4_t a) {
return vreinterpretq_u32_f32(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_u32_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u32_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <4 x i32>
// CHECK: ret <4 x i32> [[TMP0]]
uint32x4_t test_vreinterpretq_u32_f64(float64x2_t a) {
return vreinterpretq_u32_f64(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_u32_p8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u32_p8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <4 x i32>
// CHECK: ret <4 x i32> [[TMP0]]
uint32x4_t test_vreinterpretq_u32_p8(poly8x16_t a) {
return vreinterpretq_u32_p8(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_u32_p16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u32_p16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <4 x i32>
// CHECK: ret <4 x i32> [[TMP0]]
uint32x4_t test_vreinterpretq_u32_p16(poly16x8_t a) {
return vreinterpretq_u32_p16(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_u32_p64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u32_p64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <4 x i32>
// CHECK: ret <4 x i32> [[TMP0]]
uint32x4_t test_vreinterpretq_u32_p64(poly64x2_t a) {
return vreinterpretq_u32_p64(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_u64_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u64_s8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
uint64x2_t test_vreinterpretq_u64_s8(int8x16_t a) {
return vreinterpretq_u64_s8(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_u64_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u64_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
uint64x2_t test_vreinterpretq_u64_s16(int16x8_t a) {
return vreinterpretq_u64_s16(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_u64_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u64_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
uint64x2_t test_vreinterpretq_u64_s32(int32x4_t a) {
return vreinterpretq_u64_s32(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_u64_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u64_s64(
// CHECK: ret <2 x i64> %a
uint64x2_t test_vreinterpretq_u64_s64(int64x2_t a) {
return vreinterpretq_u64_s64(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_u64_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u64_u8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
uint64x2_t test_vreinterpretq_u64_u8(uint8x16_t a) {
return vreinterpretq_u64_u8(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_u64_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u64_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
uint64x2_t test_vreinterpretq_u64_u16(uint16x8_t a) {
return vreinterpretq_u64_u16(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_u64_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u64_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
uint64x2_t test_vreinterpretq_u64_u32(uint32x4_t a) {
return vreinterpretq_u64_u32(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_u64_f16(<8 x half> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u64_f16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x half> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
uint64x2_t test_vreinterpretq_u64_f16(float16x8_t a) {
return vreinterpretq_u64_f16(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_u64_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u64_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
uint64x2_t test_vreinterpretq_u64_f32(float32x4_t a) {
return vreinterpretq_u64_f32(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_u64_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u64_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
uint64x2_t test_vreinterpretq_u64_f64(float64x2_t a) {
return vreinterpretq_u64_f64(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_u64_p8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u64_p8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
uint64x2_t test_vreinterpretq_u64_p8(poly8x16_t a) {
return vreinterpretq_u64_p8(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_u64_p16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u64_p16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
uint64x2_t test_vreinterpretq_u64_p16(poly16x8_t a) {
return vreinterpretq_u64_p16(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_u64_p64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u64_p64(
// CHECK: ret <2 x i64> %a
uint64x2_t test_vreinterpretq_u64_p64(poly64x2_t a) {
return vreinterpretq_u64_p64(a);
}
-// CHECK-LABEL: define <8 x half> @test_vreinterpretq_f16_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f16_s8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <8 x half>
// CHECK: ret <8 x half> [[TMP0]]
float16x8_t test_vreinterpretq_f16_s8(int8x16_t a) {
return vreinterpretq_f16_s8(a);
}
-// CHECK-LABEL: define <8 x half> @test_vreinterpretq_f16_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f16_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <8 x half>
// CHECK: ret <8 x half> [[TMP0]]
float16x8_t test_vreinterpretq_f16_s16(int16x8_t a) {
return vreinterpretq_f16_s16(a);
}
-// CHECK-LABEL: define <8 x half> @test_vreinterpretq_f16_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f16_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <8 x half>
// CHECK: ret <8 x half> [[TMP0]]
float16x8_t test_vreinterpretq_f16_s32(int32x4_t a) {
return vreinterpretq_f16_s32(a);
}
-// CHECK-LABEL: define <8 x half> @test_vreinterpretq_f16_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f16_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <8 x half>
// CHECK: ret <8 x half> [[TMP0]]
float16x8_t test_vreinterpretq_f16_s64(int64x2_t a) {
return vreinterpretq_f16_s64(a);
}
-// CHECK-LABEL: define <8 x half> @test_vreinterpretq_f16_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f16_u8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <8 x half>
// CHECK: ret <8 x half> [[TMP0]]
float16x8_t test_vreinterpretq_f16_u8(uint8x16_t a) {
return vreinterpretq_f16_u8(a);
}
-// CHECK-LABEL: define <8 x half> @test_vreinterpretq_f16_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f16_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <8 x half>
// CHECK: ret <8 x half> [[TMP0]]
float16x8_t test_vreinterpretq_f16_u16(uint16x8_t a) {
return vreinterpretq_f16_u16(a);
}
-// CHECK-LABEL: define <8 x half> @test_vreinterpretq_f16_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f16_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <8 x half>
// CHECK: ret <8 x half> [[TMP0]]
float16x8_t test_vreinterpretq_f16_u32(uint32x4_t a) {
return vreinterpretq_f16_u32(a);
}
-// CHECK-LABEL: define <8 x half> @test_vreinterpretq_f16_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f16_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <8 x half>
// CHECK: ret <8 x half> [[TMP0]]
float16x8_t test_vreinterpretq_f16_u64(uint64x2_t a) {
return vreinterpretq_f16_u64(a);
}
-// CHECK-LABEL: define <8 x half> @test_vreinterpretq_f16_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f16_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <8 x half>
// CHECK: ret <8 x half> [[TMP0]]
float16x8_t test_vreinterpretq_f16_f32(float32x4_t a) {
return vreinterpretq_f16_f32(a);
}
-// CHECK-LABEL: define <8 x half> @test_vreinterpretq_f16_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f16_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <8 x half>
// CHECK: ret <8 x half> [[TMP0]]
float16x8_t test_vreinterpretq_f16_f64(float64x2_t a) {
return vreinterpretq_f16_f64(a);
}
-// CHECK-LABEL: define <8 x half> @test_vreinterpretq_f16_p8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f16_p8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <8 x half>
// CHECK: ret <8 x half> [[TMP0]]
float16x8_t test_vreinterpretq_f16_p8(poly8x16_t a) {
return vreinterpretq_f16_p8(a);
}
-// CHECK-LABEL: define <8 x half> @test_vreinterpretq_f16_p16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f16_p16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <8 x half>
// CHECK: ret <8 x half> [[TMP0]]
float16x8_t test_vreinterpretq_f16_p16(poly16x8_t a) {
return vreinterpretq_f16_p16(a);
}
-// CHECK-LABEL: define <8 x half> @test_vreinterpretq_f16_p64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f16_p64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <8 x half>
// CHECK: ret <8 x half> [[TMP0]]
float16x8_t test_vreinterpretq_f16_p64(poly64x2_t a) {
return vreinterpretq_f16_p64(a);
}
-// CHECK-LABEL: define <4 x float> @test_vreinterpretq_f32_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f32_s8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <4 x float>
// CHECK: ret <4 x float> [[TMP0]]
float32x4_t test_vreinterpretq_f32_s8(int8x16_t a) {
return vreinterpretq_f32_s8(a);
}
-// CHECK-LABEL: define <4 x float> @test_vreinterpretq_f32_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f32_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <4 x float>
// CHECK: ret <4 x float> [[TMP0]]
float32x4_t test_vreinterpretq_f32_s16(int16x8_t a) {
return vreinterpretq_f32_s16(a);
}
-// CHECK-LABEL: define <4 x float> @test_vreinterpretq_f32_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f32_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <4 x float>
// CHECK: ret <4 x float> [[TMP0]]
float32x4_t test_vreinterpretq_f32_s32(int32x4_t a) {
return vreinterpretq_f32_s32(a);
}
-// CHECK-LABEL: define <4 x float> @test_vreinterpretq_f32_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f32_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <4 x float>
// CHECK: ret <4 x float> [[TMP0]]
float32x4_t test_vreinterpretq_f32_s64(int64x2_t a) {
return vreinterpretq_f32_s64(a);
}
-// CHECK-LABEL: define <4 x float> @test_vreinterpretq_f32_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f32_u8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <4 x float>
// CHECK: ret <4 x float> [[TMP0]]
float32x4_t test_vreinterpretq_f32_u8(uint8x16_t a) {
return vreinterpretq_f32_u8(a);
}
-// CHECK-LABEL: define <4 x float> @test_vreinterpretq_f32_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f32_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <4 x float>
// CHECK: ret <4 x float> [[TMP0]]
float32x4_t test_vreinterpretq_f32_u16(uint16x8_t a) {
return vreinterpretq_f32_u16(a);
}
-// CHECK-LABEL: define <4 x float> @test_vreinterpretq_f32_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f32_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <4 x float>
// CHECK: ret <4 x float> [[TMP0]]
float32x4_t test_vreinterpretq_f32_u32(uint32x4_t a) {
return vreinterpretq_f32_u32(a);
}
-// CHECK-LABEL: define <4 x float> @test_vreinterpretq_f32_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f32_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <4 x float>
// CHECK: ret <4 x float> [[TMP0]]
float32x4_t test_vreinterpretq_f32_u64(uint64x2_t a) {
return vreinterpretq_f32_u64(a);
}
-// CHECK-LABEL: define <4 x float> @test_vreinterpretq_f32_f16(<8 x half> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f32_f16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x half> %a to <4 x float>
// CHECK: ret <4 x float> [[TMP0]]
float32x4_t test_vreinterpretq_f32_f16(float16x8_t a) {
return vreinterpretq_f32_f16(a);
}
-// CHECK-LABEL: define <4 x float> @test_vreinterpretq_f32_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f32_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <4 x float>
// CHECK: ret <4 x float> [[TMP0]]
float32x4_t test_vreinterpretq_f32_f64(float64x2_t a) {
return vreinterpretq_f32_f64(a);
}
-// CHECK-LABEL: define <4 x float> @test_vreinterpretq_f32_p8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f32_p8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <4 x float>
// CHECK: ret <4 x float> [[TMP0]]
float32x4_t test_vreinterpretq_f32_p8(poly8x16_t a) {
return vreinterpretq_f32_p8(a);
}
-// CHECK-LABEL: define <4 x float> @test_vreinterpretq_f32_p16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f32_p16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <4 x float>
// CHECK: ret <4 x float> [[TMP0]]
float32x4_t test_vreinterpretq_f32_p16(poly16x8_t a) {
return vreinterpretq_f32_p16(a);
}
-// CHECK-LABEL: define <4 x float> @test_vreinterpretq_f32_p64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f32_p64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <4 x float>
// CHECK: ret <4 x float> [[TMP0]]
float32x4_t test_vreinterpretq_f32_p64(poly64x2_t a) {
return vreinterpretq_f32_p64(a);
}
-// CHECK-LABEL: define <2 x double> @test_vreinterpretq_f64_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f64_s8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <2 x double>
// CHECK: ret <2 x double> [[TMP0]]
float64x2_t test_vreinterpretq_f64_s8(int8x16_t a) {
return vreinterpretq_f64_s8(a);
}
-// CHECK-LABEL: define <2 x double> @test_vreinterpretq_f64_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f64_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <2 x double>
// CHECK: ret <2 x double> [[TMP0]]
float64x2_t test_vreinterpretq_f64_s16(int16x8_t a) {
return vreinterpretq_f64_s16(a);
}
-// CHECK-LABEL: define <2 x double> @test_vreinterpretq_f64_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f64_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <2 x double>
// CHECK: ret <2 x double> [[TMP0]]
float64x2_t test_vreinterpretq_f64_s32(int32x4_t a) {
return vreinterpretq_f64_s32(a);
}
-// CHECK-LABEL: define <2 x double> @test_vreinterpretq_f64_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f64_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <2 x double>
// CHECK: ret <2 x double> [[TMP0]]
float64x2_t test_vreinterpretq_f64_s64(int64x2_t a) {
return vreinterpretq_f64_s64(a);
}
-// CHECK-LABEL: define <2 x double> @test_vreinterpretq_f64_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f64_u8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <2 x double>
// CHECK: ret <2 x double> [[TMP0]]
float64x2_t test_vreinterpretq_f64_u8(uint8x16_t a) {
return vreinterpretq_f64_u8(a);
}
-// CHECK-LABEL: define <2 x double> @test_vreinterpretq_f64_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f64_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <2 x double>
// CHECK: ret <2 x double> [[TMP0]]
float64x2_t test_vreinterpretq_f64_u16(uint16x8_t a) {
return vreinterpretq_f64_u16(a);
}
-// CHECK-LABEL: define <2 x double> @test_vreinterpretq_f64_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f64_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <2 x double>
// CHECK: ret <2 x double> [[TMP0]]
float64x2_t test_vreinterpretq_f64_u32(uint32x4_t a) {
return vreinterpretq_f64_u32(a);
}
-// CHECK-LABEL: define <2 x double> @test_vreinterpretq_f64_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f64_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <2 x double>
// CHECK: ret <2 x double> [[TMP0]]
float64x2_t test_vreinterpretq_f64_u64(uint64x2_t a) {
return vreinterpretq_f64_u64(a);
}
-// CHECK-LABEL: define <2 x double> @test_vreinterpretq_f64_f16(<8 x half> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f64_f16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x half> %a to <2 x double>
// CHECK: ret <2 x double> [[TMP0]]
float64x2_t test_vreinterpretq_f64_f16(float16x8_t a) {
return vreinterpretq_f64_f16(a);
}
-// CHECK-LABEL: define <2 x double> @test_vreinterpretq_f64_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f64_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <2 x double>
// CHECK: ret <2 x double> [[TMP0]]
float64x2_t test_vreinterpretq_f64_f32(float32x4_t a) {
return vreinterpretq_f64_f32(a);
}
-// CHECK-LABEL: define <2 x double> @test_vreinterpretq_f64_p8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f64_p8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <2 x double>
// CHECK: ret <2 x double> [[TMP0]]
float64x2_t test_vreinterpretq_f64_p8(poly8x16_t a) {
return vreinterpretq_f64_p8(a);
}
-// CHECK-LABEL: define <2 x double> @test_vreinterpretq_f64_p16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f64_p16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <2 x double>
// CHECK: ret <2 x double> [[TMP0]]
float64x2_t test_vreinterpretq_f64_p16(poly16x8_t a) {
return vreinterpretq_f64_p16(a);
}
-// CHECK-LABEL: define <2 x double> @test_vreinterpretq_f64_p64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f64_p64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <2 x double>
// CHECK: ret <2 x double> [[TMP0]]
float64x2_t test_vreinterpretq_f64_p64(poly64x2_t a) {
return vreinterpretq_f64_p64(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_p8_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p8_s8(
// CHECK: ret <16 x i8> %a
poly8x16_t test_vreinterpretq_p8_s8(int8x16_t a) {
return vreinterpretq_p8_s8(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_p8_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p8_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
poly8x16_t test_vreinterpretq_p8_s16(int16x8_t a) {
return vreinterpretq_p8_s16(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_p8_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p8_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
poly8x16_t test_vreinterpretq_p8_s32(int32x4_t a) {
return vreinterpretq_p8_s32(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_p8_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p8_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
poly8x16_t test_vreinterpretq_p8_s64(int64x2_t a) {
return vreinterpretq_p8_s64(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_p8_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p8_u8(
// CHECK: ret <16 x i8> %a
poly8x16_t test_vreinterpretq_p8_u8(uint8x16_t a) {
return vreinterpretq_p8_u8(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_p8_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p8_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
poly8x16_t test_vreinterpretq_p8_u16(uint16x8_t a) {
return vreinterpretq_p8_u16(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_p8_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p8_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
poly8x16_t test_vreinterpretq_p8_u32(uint32x4_t a) {
return vreinterpretq_p8_u32(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_p8_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p8_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
poly8x16_t test_vreinterpretq_p8_u64(uint64x2_t a) {
return vreinterpretq_p8_u64(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_p8_f16(<8 x half> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p8_f16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x half> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
poly8x16_t test_vreinterpretq_p8_f16(float16x8_t a) {
return vreinterpretq_p8_f16(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_p8_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p8_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
poly8x16_t test_vreinterpretq_p8_f32(float32x4_t a) {
return vreinterpretq_p8_f32(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_p8_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p8_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
poly8x16_t test_vreinterpretq_p8_f64(float64x2_t a) {
return vreinterpretq_p8_f64(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_p8_p16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p8_p16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
poly8x16_t test_vreinterpretq_p8_p16(poly16x8_t a) {
return vreinterpretq_p8_p16(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_p8_p64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p8_p64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
poly8x16_t test_vreinterpretq_p8_p64(poly64x2_t a) {
return vreinterpretq_p8_p64(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_p16_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p16_s8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
poly16x8_t test_vreinterpretq_p16_s8(int8x16_t a) {
return vreinterpretq_p16_s8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_p16_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p16_s16(
// CHECK: ret <8 x i16> %a
poly16x8_t test_vreinterpretq_p16_s16(int16x8_t a) {
return vreinterpretq_p16_s16(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_p16_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p16_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
poly16x8_t test_vreinterpretq_p16_s32(int32x4_t a) {
return vreinterpretq_p16_s32(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_p16_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p16_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
poly16x8_t test_vreinterpretq_p16_s64(int64x2_t a) {
return vreinterpretq_p16_s64(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_p16_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p16_u8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
poly16x8_t test_vreinterpretq_p16_u8(uint8x16_t a) {
return vreinterpretq_p16_u8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_p16_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p16_u16(
// CHECK: ret <8 x i16> %a
poly16x8_t test_vreinterpretq_p16_u16(uint16x8_t a) {
return vreinterpretq_p16_u16(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_p16_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p16_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
poly16x8_t test_vreinterpretq_p16_u32(uint32x4_t a) {
return vreinterpretq_p16_u32(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_p16_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p16_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
poly16x8_t test_vreinterpretq_p16_u64(uint64x2_t a) {
return vreinterpretq_p16_u64(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_p16_f16(<8 x half> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p16_f16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x half> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
poly16x8_t test_vreinterpretq_p16_f16(float16x8_t a) {
return vreinterpretq_p16_f16(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_p16_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p16_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
poly16x8_t test_vreinterpretq_p16_f32(float32x4_t a) {
return vreinterpretq_p16_f32(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_p16_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p16_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
poly16x8_t test_vreinterpretq_p16_f64(float64x2_t a) {
return vreinterpretq_p16_f64(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_p16_p8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p16_p8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
poly16x8_t test_vreinterpretq_p16_p8(poly8x16_t a) {
return vreinterpretq_p16_p8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_p16_p64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p16_p64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
poly16x8_t test_vreinterpretq_p16_p64(poly64x2_t a) {
return vreinterpretq_p16_p64(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_p64_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p64_s8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
poly64x2_t test_vreinterpretq_p64_s8(int8x16_t a) {
return vreinterpretq_p64_s8(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_p64_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p64_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
poly64x2_t test_vreinterpretq_p64_s16(int16x8_t a) {
return vreinterpretq_p64_s16(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_p64_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p64_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
poly64x2_t test_vreinterpretq_p64_s32(int32x4_t a) {
return vreinterpretq_p64_s32(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_p64_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p64_s64(
// CHECK: ret <2 x i64> %a
poly64x2_t test_vreinterpretq_p64_s64(int64x2_t a) {
return vreinterpretq_p64_s64(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_p64_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p64_u8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
poly64x2_t test_vreinterpretq_p64_u8(uint8x16_t a) {
return vreinterpretq_p64_u8(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_p64_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p64_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
poly64x2_t test_vreinterpretq_p64_u16(uint16x8_t a) {
return vreinterpretq_p64_u16(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_p64_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p64_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
poly64x2_t test_vreinterpretq_p64_u32(uint32x4_t a) {
return vreinterpretq_p64_u32(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_p64_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p64_u64(
// CHECK: ret <2 x i64> %a
poly64x2_t test_vreinterpretq_p64_u64(uint64x2_t a) {
return vreinterpretq_p64_u64(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_p64_f16(<8 x half> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p64_f16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x half> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
poly64x2_t test_vreinterpretq_p64_f16(float16x8_t a) {
return vreinterpretq_p64_f16(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_p64_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p64_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
poly64x2_t test_vreinterpretq_p64_f32(float32x4_t a) {
return vreinterpretq_p64_f32(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_p64_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p64_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
poly64x2_t test_vreinterpretq_p64_f64(float64x2_t a) {
return vreinterpretq_p64_f64(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_p64_p8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p64_p8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
poly64x2_t test_vreinterpretq_p64_p8(poly8x16_t a) {
return vreinterpretq_p64_p8(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_p64_p16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p64_p16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
poly64x2_t test_vreinterpretq_p64_p16(poly16x8_t a) {
return vreinterpretq_p64_p16(a);
}
-// CHECK-LABEL: define float @test_vabds_f32(float %a, float %b) #0 {
+// CHECK-LABEL: @test_vabds_f32(
// CHECK: [[VABDS_F32_I:%.*]] = call float @llvm.aarch64.sisd.fabd.f32(float %a, float %b) #4
// CHECK: ret float [[VABDS_F32_I]]
float32_t test_vabds_f32(float32_t a, float32_t b) {
return vabds_f32(a, b);
}
-// CHECK-LABEL: define double @test_vabdd_f64(double %a, double %b) #0 {
+// CHECK-LABEL: @test_vabdd_f64(
// CHECK: [[VABDD_F64_I:%.*]] = call double @llvm.aarch64.sisd.fabd.f64(double %a, double %b) #4
// CHECK: ret double [[VABDD_F64_I]]
float64_t test_vabdd_f64(float64_t a, float64_t b) {
return vabdd_f64(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vuqadd_s64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vuqadd_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
-// CHECK: [[VUQADD_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
-// CHECK: [[VUQADD1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x i64>
-// CHECK: [[VUQADD2_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.suqadd.v1i64(<1 x i64> [[VUQADD_I]], <1 x i64> [[VUQADD1_I]]) #4
+// CHECK: [[VUQADD2_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.suqadd.v1i64(<1 x i64> %a, <1 x i64> %b) #4
// CHECK: ret <1 x i64> [[VUQADD2_I]]
int64x1_t test_vuqadd_s64(int64x1_t a, uint64x1_t b) {
return vuqadd_s64(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vsqadd_u64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vsqadd_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
-// CHECK: [[VSQADD_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
-// CHECK: [[VSQADD1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x i64>
-// CHECK: [[VSQADD2_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.usqadd.v1i64(<1 x i64> [[VSQADD_I]], <1 x i64> [[VSQADD1_I]]) #4
+// CHECK: [[VSQADD2_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.usqadd.v1i64(<1 x i64> %a, <1 x i64> %b) #4
// CHECK: ret <1 x i64> [[VSQADD2_I]]
uint64x1_t test_vsqadd_u64(uint64x1_t a, int64x1_t b) {
return vsqadd_u64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vsqadd_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsqadd_u8(
// CHECK: [[VSQADD_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.usqadd.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VSQADD_I]]
uint8x8_t test_vsqadd_u8(uint8x8_t a, int8x8_t b) {
return vsqadd_u8(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vsqaddq_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsqaddq_u8(
// CHECK: [[VSQADD_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.usqadd.v16i8(<16 x i8> %a, <16 x i8> %b) #4
// CHECK: ret <16 x i8> [[VSQADD_I]]
uint8x16_t test_vsqaddq_u8(uint8x16_t a, int8x16_t b) {
return vsqaddq_u8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vsqadd_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsqadd_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VSQADD_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VSQADD1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VSQADD2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.usqadd.v4i16(<4 x i16> [[VSQADD_I]], <4 x i16> [[VSQADD1_I]]) #4
+// CHECK: [[VSQADD2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.usqadd.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: ret <4 x i16> [[VSQADD2_I]]
uint16x4_t test_vsqadd_u16(uint16x4_t a, int16x4_t b) {
return vsqadd_u16(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vsqaddq_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsqaddq_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VSQADD_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VSQADD1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VSQADD2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.usqadd.v8i16(<8 x i16> [[VSQADD_I]], <8 x i16> [[VSQADD1_I]]) #4
+// CHECK: [[VSQADD2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.usqadd.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: ret <8 x i16> [[VSQADD2_I]]
uint16x8_t test_vsqaddq_u16(uint16x8_t a, int16x8_t b) {
return vsqaddq_u16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vsqadd_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsqadd_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VSQADD_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VSQADD1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VSQADD2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.usqadd.v2i32(<2 x i32> [[VSQADD_I]], <2 x i32> [[VSQADD1_I]]) #4
+// CHECK: [[VSQADD2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.usqadd.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: ret <2 x i32> [[VSQADD2_I]]
uint32x2_t test_vsqadd_u32(uint32x2_t a, int32x2_t b) {
return vsqadd_u32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vsqaddq_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsqaddq_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VSQADD_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VSQADD1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VSQADD2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.usqadd.v4i32(<4 x i32> [[VSQADD_I]], <4 x i32> [[VSQADD1_I]]) #4
+// CHECK: [[VSQADD2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.usqadd.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: ret <4 x i32> [[VSQADD2_I]]
uint32x4_t test_vsqaddq_u32(uint32x4_t a, int32x4_t b) {
return vsqaddq_u32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vsqaddq_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vsqaddq_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[VSQADD_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VSQADD1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VSQADD2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.usqadd.v2i64(<2 x i64> [[VSQADD_I]], <2 x i64> [[VSQADD1_I]]) #4
+// CHECK: [[VSQADD2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.usqadd.v2i64(<2 x i64> %a, <2 x i64> %b) #4
// CHECK: ret <2 x i64> [[VSQADD2_I]]
uint64x2_t test_vsqaddq_u64(uint64x2_t a, int64x2_t b) {
return vsqaddq_u64(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vabs_s64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vabs_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
-// CHECK: [[VABS_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
-// CHECK: [[VABS1_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.abs.v1i64(<1 x i64> [[VABS_I]]) #4
+// CHECK: [[VABS1_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.abs.v1i64(<1 x i64> %a) #4
// CHECK: ret <1 x i64> [[VABS1_I]]
int64x1_t test_vabs_s64(int64x1_t a) {
return vabs_s64(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vqabs_s64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vqabs_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
-// CHECK: [[VQABS_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
-// CHECK: [[VQABS_V1_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.sqabs.v1i64(<1 x i64> [[VQABS_V_I]]) #4
+// CHECK: [[VQABS_V1_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.sqabs.v1i64(<1 x i64> %a) #4
// CHECK: [[VQABS_V2_I:%.*]] = bitcast <1 x i64> [[VQABS_V1_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[VQABS_V2_I]] to <1 x i64>
-// CHECK: ret <1 x i64> [[TMP1]]
+// CHECK: ret <1 x i64> [[VQABS_V1_I]]
int64x1_t test_vqabs_s64(int64x1_t a) {
return vqabs_s64(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vqneg_s64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vqneg_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
-// CHECK: [[VQNEG_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
-// CHECK: [[VQNEG_V1_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.sqneg.v1i64(<1 x i64> [[VQNEG_V_I]]) #4
+// CHECK: [[VQNEG_V1_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.sqneg.v1i64(<1 x i64> %a) #4
// CHECK: [[VQNEG_V2_I:%.*]] = bitcast <1 x i64> [[VQNEG_V1_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[VQNEG_V2_I]] to <1 x i64>
-// CHECK: ret <1 x i64> [[TMP1]]
+// CHECK: ret <1 x i64> [[VQNEG_V1_I]]
int64x1_t test_vqneg_s64(int64x1_t a) {
return vqneg_s64(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vneg_s64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vneg_s64(
// CHECK: [[SUB_I:%.*]] = sub <1 x i64> zeroinitializer, %a
// CHECK: ret <1 x i64> [[SUB_I]]
int64x1_t test_vneg_s64(int64x1_t a) {
return vneg_s64(a);
}
-// CHECK-LABEL: define float @test_vaddv_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vaddv_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VADDV_F32_I:%.*]] = call float @llvm.aarch64.neon.faddv.f32.v2f32(<2 x float> [[TMP1]]) #4
+// CHECK: [[VADDV_F32_I:%.*]] = call float @llvm.aarch64.neon.faddv.f32.v2f32(<2 x float> %a) #4
// CHECK: ret float [[VADDV_F32_I]]
float32_t test_vaddv_f32(float32x2_t a) {
return vaddv_f32(a);
}
-// CHECK-LABEL: define float @test_vaddvq_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vaddvq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VADDVQ_F32_I:%.*]] = call float @llvm.aarch64.neon.faddv.f32.v4f32(<4 x float> [[TMP1]]) #4
+// CHECK: [[VADDVQ_F32_I:%.*]] = call float @llvm.aarch64.neon.faddv.f32.v4f32(<4 x float> %a) #4
// CHECK: ret float [[VADDVQ_F32_I]]
float32_t test_vaddvq_f32(float32x4_t a) {
return vaddvq_f32(a);
}
-// CHECK-LABEL: define double @test_vaddvq_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vaddvq_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VADDVQ_F64_I:%.*]] = call double @llvm.aarch64.neon.faddv.f64.v2f64(<2 x double> [[TMP1]]) #4
+// CHECK: [[VADDVQ_F64_I:%.*]] = call double @llvm.aarch64.neon.faddv.f64.v2f64(<2 x double> %a) #4
// CHECK: ret double [[VADDVQ_F64_I]]
float64_t test_vaddvq_f64(float64x2_t a) {
return vaddvq_f64(a);
}
-// CHECK-LABEL: define float @test_vmaxv_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vmaxv_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VMAXV_F32_I:%.*]] = call float @llvm.aarch64.neon.fmaxv.f32.v2f32(<2 x float> [[TMP1]]) #4
+// CHECK: [[VMAXV_F32_I:%.*]] = call float @llvm.aarch64.neon.fmaxv.f32.v2f32(<2 x float> %a) #4
// CHECK: ret float [[VMAXV_F32_I]]
float32_t test_vmaxv_f32(float32x2_t a) {
return vmaxv_f32(a);
}
-// CHECK-LABEL: define double @test_vmaxvq_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vmaxvq_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VMAXVQ_F64_I:%.*]] = call double @llvm.aarch64.neon.fmaxv.f64.v2f64(<2 x double> [[TMP1]]) #4
+// CHECK: [[VMAXVQ_F64_I:%.*]] = call double @llvm.aarch64.neon.fmaxv.f64.v2f64(<2 x double> %a) #4
// CHECK: ret double [[VMAXVQ_F64_I]]
float64_t test_vmaxvq_f64(float64x2_t a) {
return vmaxvq_f64(a);
}
-// CHECK-LABEL: define float @test_vminv_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vminv_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VMINV_F32_I:%.*]] = call float @llvm.aarch64.neon.fminv.f32.v2f32(<2 x float> [[TMP1]]) #4
+// CHECK: [[VMINV_F32_I:%.*]] = call float @llvm.aarch64.neon.fminv.f32.v2f32(<2 x float> %a) #4
// CHECK: ret float [[VMINV_F32_I]]
float32_t test_vminv_f32(float32x2_t a) {
return vminv_f32(a);
}
-// CHECK-LABEL: define double @test_vminvq_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vminvq_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VMINVQ_F64_I:%.*]] = call double @llvm.aarch64.neon.fminv.f64.v2f64(<2 x double> [[TMP1]]) #4
+// CHECK: [[VMINVQ_F64_I:%.*]] = call double @llvm.aarch64.neon.fminv.f64.v2f64(<2 x double> %a) #4
// CHECK: ret double [[VMINVQ_F64_I]]
float64_t test_vminvq_f64(float64x2_t a) {
return vminvq_f64(a);
}
-// CHECK-LABEL: define double @test_vmaxnmvq_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vmaxnmvq_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VMAXNMVQ_F64_I:%.*]] = call double @llvm.aarch64.neon.fmaxnmv.f64.v2f64(<2 x double> [[TMP1]]) #4
+// CHECK: [[VMAXNMVQ_F64_I:%.*]] = call double @llvm.aarch64.neon.fmaxnmv.f64.v2f64(<2 x double> %a) #4
// CHECK: ret double [[VMAXNMVQ_F64_I]]
float64_t test_vmaxnmvq_f64(float64x2_t a) {
return vmaxnmvq_f64(a);
}
-// CHECK-LABEL: define float @test_vmaxnmv_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vmaxnmv_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VMAXNMV_F32_I:%.*]] = call float @llvm.aarch64.neon.fmaxnmv.f32.v2f32(<2 x float> [[TMP1]]) #4
+// CHECK: [[VMAXNMV_F32_I:%.*]] = call float @llvm.aarch64.neon.fmaxnmv.f32.v2f32(<2 x float> %a) #4
// CHECK: ret float [[VMAXNMV_F32_I]]
float32_t test_vmaxnmv_f32(float32x2_t a) {
return vmaxnmv_f32(a);
}
-// CHECK-LABEL: define double @test_vminnmvq_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vminnmvq_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VMINNMVQ_F64_I:%.*]] = call double @llvm.aarch64.neon.fminnmv.f64.v2f64(<2 x double> [[TMP1]]) #4
+// CHECK: [[VMINNMVQ_F64_I:%.*]] = call double @llvm.aarch64.neon.fminnmv.f64.v2f64(<2 x double> %a) #4
// CHECK: ret double [[VMINNMVQ_F64_I]]
float64_t test_vminnmvq_f64(float64x2_t a) {
return vminnmvq_f64(a);
}
-// CHECK-LABEL: define float @test_vminnmv_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vminnmv_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VMINNMV_F32_I:%.*]] = call float @llvm.aarch64.neon.fminnmv.f32.v2f32(<2 x float> [[TMP1]]) #4
+// CHECK: [[VMINNMV_F32_I:%.*]] = call float @llvm.aarch64.neon.fminnmv.f32.v2f32(<2 x float> %a) #4
// CHECK: ret float [[VMINNMV_F32_I]]
float32_t test_vminnmv_f32(float32x2_t a) {
return vminnmv_f32(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vpaddq_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vpaddq_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[VPADDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VPADDQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VPADDQ_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.addp.v2i64(<2 x i64> [[VPADDQ_V_I]], <2 x i64> [[VPADDQ_V1_I]]) #4
+// CHECK: [[VPADDQ_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.addp.v2i64(<2 x i64> %a, <2 x i64> %b) #4
// CHECK: [[VPADDQ_V3_I:%.*]] = bitcast <2 x i64> [[VPADDQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VPADDQ_V3_I]] to <2 x i64>
-// CHECK: ret <2 x i64> [[TMP2]]
+// CHECK: ret <2 x i64> [[VPADDQ_V2_I]]
int64x2_t test_vpaddq_s64(int64x2_t a, int64x2_t b) {
return vpaddq_s64(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vpaddq_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vpaddq_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[VPADDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VPADDQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VPADDQ_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.addp.v2i64(<2 x i64> [[VPADDQ_V_I]], <2 x i64> [[VPADDQ_V1_I]]) #4
+// CHECK: [[VPADDQ_V2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.addp.v2i64(<2 x i64> %a, <2 x i64> %b) #4
// CHECK: [[VPADDQ_V3_I:%.*]] = bitcast <2 x i64> [[VPADDQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VPADDQ_V3_I]] to <2 x i64>
-// CHECK: ret <2 x i64> [[TMP2]]
+// CHECK: ret <2 x i64> [[VPADDQ_V2_I]]
uint64x2_t test_vpaddq_u64(uint64x2_t a, uint64x2_t b) {
return vpaddq_u64(a, b);
}
-// CHECK-LABEL: define i64 @test_vpaddd_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vpaddd_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VPADDD_U64_I:%.*]] = call i64 @llvm.aarch64.neon.uaddv.i64.v2i64(<2 x i64> [[TMP1]]) #4
+// CHECK: [[VPADDD_U64_I:%.*]] = call i64 @llvm.aarch64.neon.uaddv.i64.v2i64(<2 x i64> %a) #4
// CHECK: ret i64 [[VPADDD_U64_I]]
uint64_t test_vpaddd_u64(uint64x2_t a) {
return vpaddd_u64(a);
}
-// CHECK-LABEL: define i64 @test_vaddvq_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vaddvq_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VADDVQ_S64_I:%.*]] = call i64 @llvm.aarch64.neon.saddv.i64.v2i64(<2 x i64> [[TMP1]]) #4
+// CHECK: [[VADDVQ_S64_I:%.*]] = call i64 @llvm.aarch64.neon.saddv.i64.v2i64(<2 x i64> %a) #4
// CHECK: ret i64 [[VADDVQ_S64_I]]
int64_t test_vaddvq_s64(int64x2_t a) {
return vaddvq_s64(a);
}
-// CHECK-LABEL: define i64 @test_vaddvq_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vaddvq_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VADDVQ_U64_I:%.*]] = call i64 @llvm.aarch64.neon.uaddv.i64.v2i64(<2 x i64> [[TMP1]]) #4
+// CHECK: [[VADDVQ_U64_I:%.*]] = call i64 @llvm.aarch64.neon.uaddv.i64.v2i64(<2 x i64> %a) #4
// CHECK: ret i64 [[VADDVQ_U64_I]]
uint64_t test_vaddvq_u64(uint64x2_t a) {
return vaddvq_u64(a);
}
-// CHECK-LABEL: define <1 x double> @test_vadd_f64(<1 x double> %a, <1 x double> %b) #0 {
+// CHECK-LABEL: @test_vadd_f64(
// CHECK: [[ADD_I:%.*]] = fadd <1 x double> %a, %b
// CHECK: ret <1 x double> [[ADD_I]]
float64x1_t test_vadd_f64(float64x1_t a, float64x1_t b) {
return vadd_f64(a, b);
}
-// CHECK-LABEL: define <1 x double> @test_vmul_f64(<1 x double> %a, <1 x double> %b) #0 {
+// CHECK-LABEL: @test_vmul_f64(
// CHECK: [[MUL_I:%.*]] = fmul <1 x double> %a, %b
// CHECK: ret <1 x double> [[MUL_I]]
float64x1_t test_vmul_f64(float64x1_t a, float64x1_t b) {
return vmul_f64(a, b);
}
-// CHECK-LABEL: define <1 x double> @test_vdiv_f64(<1 x double> %a, <1 x double> %b) #0 {
+// CHECK-LABEL: @test_vdiv_f64(
// CHECK: [[DIV_I:%.*]] = fdiv <1 x double> %a, %b
// CHECK: ret <1 x double> [[DIV_I]]
float64x1_t test_vdiv_f64(float64x1_t a, float64x1_t b) {
return vdiv_f64(a, b);
}
-// CHECK-LABEL: define <1 x double> @test_vmla_f64(<1 x double> %a, <1 x double> %b, <1 x double> %c) #0 {
+// CHECK-LABEL: @test_vmla_f64(
// CHECK: [[MUL_I:%.*]] = fmul <1 x double> %b, %c
// CHECK: [[ADD_I:%.*]] = fadd <1 x double> %a, [[MUL_I]]
// CHECK: ret <1 x double> [[ADD_I]]
@@ -22111,7 +21149,7 @@ float64x1_t test_vmla_f64(float64x1_t a, float64x1_t b, float64x1_t c) {
return vmla_f64(a, b, c);
}
-// CHECK-LABEL: define <1 x double> @test_vmls_f64(<1 x double> %a, <1 x double> %b, <1 x double> %c) #0 {
+// CHECK-LABEL: @test_vmls_f64(
// CHECK: [[MUL_I:%.*]] = fmul <1 x double> %b, %c
// CHECK: [[SUB_I:%.*]] = fsub <1 x double> %a, [[MUL_I]]
// CHECK: ret <1 x double> [[SUB_I]]
@@ -22119,220 +21157,191 @@ float64x1_t test_vmls_f64(float64x1_t a, float64x1_t b, float64x1_t c) {
return vmls_f64(a, b, c);
}
-// CHECK-LABEL: define <1 x double> @test_vfma_f64(<1 x double> %a, <1 x double> %b, <1 x double> %c) #0 {
+// CHECK-LABEL: @test_vfma_f64(
// 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> %c to <8 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x double>
-// CHECK: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x double>
-// CHECK: [[TMP5:%.*]] = bitcast <8 x i8> [[TMP2]] to <1 x double>
-// CHECK: [[TMP6:%.*]] = call <1 x double> @llvm.fma.v1f64(<1 x double> [[TMP4]], <1 x double> [[TMP5]], <1 x double> [[TMP3]]) #4
-// CHECK: ret <1 x double> [[TMP6]]
+// CHECK: [[TMP3:%.*]] = call <1 x double> @llvm.fma.v1f64(<1 x double> %b, <1 x double> %c, <1 x double> %a) #4
+// CHECK: ret <1 x double> [[TMP3]]
float64x1_t test_vfma_f64(float64x1_t a, float64x1_t b, float64x1_t c) {
return vfma_f64(a, b, c);
}
-// CHECK-LABEL: define <1 x double> @test_vfms_f64(<1 x double> %a, <1 x double> %b, <1 x double> %c) #0 {
+// CHECK-LABEL: @test_vfms_f64(
// CHECK: [[SUB_I:%.*]] = fsub <1 x double> <double -0.000000e+00>, %b
// 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> %c to <8 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x double>
-// CHECK: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x double>
-// CHECK: [[TMP5:%.*]] = bitcast <8 x i8> [[TMP2]] to <1 x double>
-// CHECK: [[TMP6:%.*]] = call <1 x double> @llvm.fma.v1f64(<1 x double> [[TMP4]], <1 x double> [[TMP5]], <1 x double> [[TMP3]]) #4
-// CHECK: ret <1 x double> [[TMP6]]
+// CHECK: [[TMP3:%.*]] = call <1 x double> @llvm.fma.v1f64(<1 x double> [[SUB_I]], <1 x double> %c, <1 x double> %a) #4
+// CHECK: ret <1 x double> [[TMP3]]
float64x1_t test_vfms_f64(float64x1_t a, float64x1_t b, float64x1_t c) {
return vfms_f64(a, b, c);
}
-// CHECK-LABEL: define <1 x double> @test_vsub_f64(<1 x double> %a, <1 x double> %b) #0 {
+// CHECK-LABEL: @test_vsub_f64(
// CHECK: [[SUB_I:%.*]] = fsub <1 x double> %a, %b
// CHECK: ret <1 x double> [[SUB_I]]
float64x1_t test_vsub_f64(float64x1_t a, float64x1_t b) {
return vsub_f64(a, b);
}
-// CHECK-LABEL: define <1 x double> @test_vabd_f64(<1 x double> %a, <1 x double> %b) #0 {
+// CHECK-LABEL: @test_vabd_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x double> %b to <8 x i8>
-// CHECK: [[VABD_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x double>
-// CHECK: [[VABD1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x double>
-// CHECK: [[VABD2_I:%.*]] = call <1 x double> @llvm.aarch64.neon.fabd.v1f64(<1 x double> [[VABD_I]], <1 x double> [[VABD1_I]]) #4
+// CHECK: [[VABD2_I:%.*]] = call <1 x double> @llvm.aarch64.neon.fabd.v1f64(<1 x double> %a, <1 x double> %b) #4
// CHECK: ret <1 x double> [[VABD2_I]]
float64x1_t test_vabd_f64(float64x1_t a, float64x1_t b) {
return vabd_f64(a, b);
}
-// CHECK-LABEL: define <1 x double> @test_vmax_f64(<1 x double> %a, <1 x double> %b) #0 {
+// CHECK-LABEL: @test_vmax_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x double> %b to <8 x i8>
-// CHECK: [[VMAX_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x double>
-// CHECK: [[VMAX1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x double>
-// CHECK: [[VMAX2_I:%.*]] = call <1 x double> @llvm.aarch64.neon.fmax.v1f64(<1 x double> [[VMAX_I]], <1 x double> [[VMAX1_I]]) #4
+// CHECK: [[VMAX2_I:%.*]] = call <1 x double> @llvm.aarch64.neon.fmax.v1f64(<1 x double> %a, <1 x double> %b) #4
// CHECK: ret <1 x double> [[VMAX2_I]]
float64x1_t test_vmax_f64(float64x1_t a, float64x1_t b) {
return vmax_f64(a, b);
}
-// CHECK-LABEL: define <1 x double> @test_vmin_f64(<1 x double> %a, <1 x double> %b) #0 {
+// CHECK-LABEL: @test_vmin_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x double> %b to <8 x i8>
-// CHECK: [[VMIN_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x double>
-// CHECK: [[VMIN1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x double>
-// CHECK: [[VMIN2_I:%.*]] = call <1 x double> @llvm.aarch64.neon.fmin.v1f64(<1 x double> [[VMIN_I]], <1 x double> [[VMIN1_I]]) #4
+// CHECK: [[VMIN2_I:%.*]] = call <1 x double> @llvm.aarch64.neon.fmin.v1f64(<1 x double> %a, <1 x double> %b) #4
// CHECK: ret <1 x double> [[VMIN2_I]]
float64x1_t test_vmin_f64(float64x1_t a, float64x1_t b) {
return vmin_f64(a, b);
}
-// CHECK-LABEL: define <1 x double> @test_vmaxnm_f64(<1 x double> %a, <1 x double> %b) #0 {
+// CHECK-LABEL: @test_vmaxnm_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x double> %b to <8 x i8>
-// CHECK: [[VMAXNM_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x double>
-// CHECK: [[VMAXNM1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x double>
-// CHECK: [[VMAXNM2_I:%.*]] = call <1 x double> @llvm.aarch64.neon.fmaxnm.v1f64(<1 x double> [[VMAXNM_I]], <1 x double> [[VMAXNM1_I]]) #4
+// CHECK: [[VMAXNM2_I:%.*]] = call <1 x double> @llvm.aarch64.neon.fmaxnm.v1f64(<1 x double> %a, <1 x double> %b) #4
// CHECK: ret <1 x double> [[VMAXNM2_I]]
float64x1_t test_vmaxnm_f64(float64x1_t a, float64x1_t b) {
return vmaxnm_f64(a, b);
}
-// CHECK-LABEL: define <1 x double> @test_vminnm_f64(<1 x double> %a, <1 x double> %b) #0 {
+// CHECK-LABEL: @test_vminnm_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x double> %b to <8 x i8>
-// CHECK: [[VMINNM_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x double>
-// CHECK: [[VMINNM1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x double>
-// CHECK: [[VMINNM2_I:%.*]] = call <1 x double> @llvm.aarch64.neon.fminnm.v1f64(<1 x double> [[VMINNM_I]], <1 x double> [[VMINNM1_I]]) #4
+// CHECK: [[VMINNM2_I:%.*]] = call <1 x double> @llvm.aarch64.neon.fminnm.v1f64(<1 x double> %a, <1 x double> %b) #4
// CHECK: ret <1 x double> [[VMINNM2_I]]
float64x1_t test_vminnm_f64(float64x1_t a, float64x1_t b) {
return vminnm_f64(a, b);
}
-// CHECK-LABEL: define <1 x double> @test_vabs_f64(<1 x double> %a) #0 {
+// CHECK-LABEL: @test_vabs_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
-// CHECK: [[VABS_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x double>
-// CHECK: [[VABS1_I:%.*]] = call <1 x double> @llvm.fabs.v1f64(<1 x double> [[VABS_I]]) #4
+// CHECK: [[VABS1_I:%.*]] = call <1 x double> @llvm.fabs.v1f64(<1 x double> %a) #4
// CHECK: ret <1 x double> [[VABS1_I]]
float64x1_t test_vabs_f64(float64x1_t a) {
return vabs_f64(a);
}
-// CHECK-LABEL: define <1 x double> @test_vneg_f64(<1 x double> %a) #0 {
+// CHECK-LABEL: @test_vneg_f64(
// CHECK: [[SUB_I:%.*]] = fsub <1 x double> <double -0.000000e+00>, %a
// CHECK: ret <1 x double> [[SUB_I]]
float64x1_t test_vneg_f64(float64x1_t a) {
return vneg_f64(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vcvt_s64_f64(<1 x double> %a) #0 {
+// CHECK-LABEL: @test_vcvt_s64_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x double>
-// CHECK: [[TMP2:%.*]] = fptosi <1 x double> [[TMP1]] to <1 x i64>
-// CHECK: ret <1 x i64> [[TMP2]]
+// CHECK: [[TMP1:%.*]] = fptosi <1 x double> %a to <1 x i64>
+// CHECK: ret <1 x i64> [[TMP1]]
int64x1_t test_vcvt_s64_f64(float64x1_t a) {
return vcvt_s64_f64(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vcvt_u64_f64(<1 x double> %a) #0 {
+// CHECK-LABEL: @test_vcvt_u64_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x double>
-// CHECK: [[TMP2:%.*]] = fptoui <1 x double> [[TMP1]] to <1 x i64>
-// CHECK: ret <1 x i64> [[TMP2]]
+// CHECK: [[TMP1:%.*]] = fptoui <1 x double> %a to <1 x i64>
+// CHECK: ret <1 x i64> [[TMP1]]
uint64x1_t test_vcvt_u64_f64(float64x1_t a) {
return vcvt_u64_f64(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vcvtn_s64_f64(<1 x double> %a) #0 {
+// CHECK-LABEL: @test_vcvtn_s64_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
-// CHECK: [[VCVTN_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x double>
-// CHECK: [[VCVTN1_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.fcvtns.v1i64.v1f64(<1 x double> [[VCVTN_I]]) #4
+// CHECK: [[VCVTN1_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.fcvtns.v1i64.v1f64(<1 x double> %a) #4
// CHECK: ret <1 x i64> [[VCVTN1_I]]
int64x1_t test_vcvtn_s64_f64(float64x1_t a) {
return vcvtn_s64_f64(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vcvtn_u64_f64(<1 x double> %a) #0 {
+// CHECK-LABEL: @test_vcvtn_u64_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
-// CHECK: [[VCVTN_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x double>
-// CHECK: [[VCVTN1_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.fcvtnu.v1i64.v1f64(<1 x double> [[VCVTN_I]]) #4
+// CHECK: [[VCVTN1_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.fcvtnu.v1i64.v1f64(<1 x double> %a) #4
// CHECK: ret <1 x i64> [[VCVTN1_I]]
uint64x1_t test_vcvtn_u64_f64(float64x1_t a) {
return vcvtn_u64_f64(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vcvtp_s64_f64(<1 x double> %a) #0 {
+// CHECK-LABEL: @test_vcvtp_s64_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
-// CHECK: [[VCVTP_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x double>
-// CHECK: [[VCVTP1_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.fcvtps.v1i64.v1f64(<1 x double> [[VCVTP_I]]) #4
+// CHECK: [[VCVTP1_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.fcvtps.v1i64.v1f64(<1 x double> %a) #4
// CHECK: ret <1 x i64> [[VCVTP1_I]]
int64x1_t test_vcvtp_s64_f64(float64x1_t a) {
return vcvtp_s64_f64(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vcvtp_u64_f64(<1 x double> %a) #0 {
+// CHECK-LABEL: @test_vcvtp_u64_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
-// CHECK: [[VCVTP_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x double>
-// CHECK: [[VCVTP1_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.fcvtpu.v1i64.v1f64(<1 x double> [[VCVTP_I]]) #4
+// CHECK: [[VCVTP1_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.fcvtpu.v1i64.v1f64(<1 x double> %a) #4
// CHECK: ret <1 x i64> [[VCVTP1_I]]
uint64x1_t test_vcvtp_u64_f64(float64x1_t a) {
return vcvtp_u64_f64(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vcvtm_s64_f64(<1 x double> %a) #0 {
+// CHECK-LABEL: @test_vcvtm_s64_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
-// CHECK: [[VCVTM_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x double>
-// CHECK: [[VCVTM1_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.fcvtms.v1i64.v1f64(<1 x double> [[VCVTM_I]]) #4
+// CHECK: [[VCVTM1_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.fcvtms.v1i64.v1f64(<1 x double> %a) #4
// CHECK: ret <1 x i64> [[VCVTM1_I]]
int64x1_t test_vcvtm_s64_f64(float64x1_t a) {
return vcvtm_s64_f64(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vcvtm_u64_f64(<1 x double> %a) #0 {
+// CHECK-LABEL: @test_vcvtm_u64_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
-// CHECK: [[VCVTM_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x double>
-// CHECK: [[VCVTM1_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.fcvtmu.v1i64.v1f64(<1 x double> [[VCVTM_I]]) #4
+// CHECK: [[VCVTM1_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.fcvtmu.v1i64.v1f64(<1 x double> %a) #4
// CHECK: ret <1 x i64> [[VCVTM1_I]]
uint64x1_t test_vcvtm_u64_f64(float64x1_t a) {
return vcvtm_u64_f64(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vcvta_s64_f64(<1 x double> %a) #0 {
+// CHECK-LABEL: @test_vcvta_s64_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
-// CHECK: [[VCVTA_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x double>
-// CHECK: [[VCVTA1_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.fcvtas.v1i64.v1f64(<1 x double> [[VCVTA_I]]) #4
+// CHECK: [[VCVTA1_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.fcvtas.v1i64.v1f64(<1 x double> %a) #4
// CHECK: ret <1 x i64> [[VCVTA1_I]]
int64x1_t test_vcvta_s64_f64(float64x1_t a) {
return vcvta_s64_f64(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vcvta_u64_f64(<1 x double> %a) #0 {
+// CHECK-LABEL: @test_vcvta_u64_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
-// CHECK: [[VCVTA_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x double>
-// CHECK: [[VCVTA1_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.fcvtau.v1i64.v1f64(<1 x double> [[VCVTA_I]]) #4
+// CHECK: [[VCVTA1_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.fcvtau.v1i64.v1f64(<1 x double> %a) #4
// CHECK: ret <1 x i64> [[VCVTA1_I]]
uint64x1_t test_vcvta_u64_f64(float64x1_t a) {
return vcvta_u64_f64(a);
}
-// CHECK-LABEL: define <1 x double> @test_vcvt_f64_s64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vcvt_f64_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
-// CHECK: [[VCVT_I:%.*]] = sitofp <1 x i64> [[TMP1]] to <1 x double>
+// CHECK: [[VCVT_I:%.*]] = sitofp <1 x i64> %a to <1 x double>
// CHECK: ret <1 x double> [[VCVT_I]]
float64x1_t test_vcvt_f64_s64(int64x1_t a) {
return vcvt_f64_s64(a);
}
-// CHECK-LABEL: define <1 x double> @test_vcvt_f64_u64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vcvt_f64_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
-// CHECK: [[VCVT_I:%.*]] = uitofp <1 x i64> [[TMP1]] to <1 x double>
+// CHECK: [[VCVT_I:%.*]] = uitofp <1 x i64> %a to <1 x double>
// CHECK: ret <1 x double> [[VCVT_I]]
float64x1_t test_vcvt_f64_u64(uint64x1_t a) {
return vcvt_f64_u64(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vcvt_n_s64_f64(<1 x double> %a) #0 {
+// CHECK-LABEL: @test_vcvt_n_s64_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
// CHECK: [[VCVT_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x double>
// CHECK: [[VCVT_N1:%.*]] = call <1 x i64> @llvm.aarch64.neon.vcvtfp2fxs.v1i64.v1f64(<1 x double> [[VCVT_N]], i32 64)
@@ -22341,7 +21350,7 @@ int64x1_t test_vcvt_n_s64_f64(float64x1_t a) {
return vcvt_n_s64_f64(a, 64);
}
-// CHECK-LABEL: define <1 x i64> @test_vcvt_n_u64_f64(<1 x double> %a) #0 {
+// CHECK-LABEL: @test_vcvt_n_u64_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
// CHECK: [[VCVT_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x double>
// CHECK: [[VCVT_N1:%.*]] = call <1 x i64> @llvm.aarch64.neon.vcvtfp2fxu.v1i64.v1f64(<1 x double> [[VCVT_N]], i32 64)
@@ -22350,7 +21359,7 @@ uint64x1_t test_vcvt_n_u64_f64(float64x1_t a) {
return vcvt_n_u64_f64(a, 64);
}
-// CHECK-LABEL: define <1 x double> @test_vcvt_n_f64_s64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vcvt_n_f64_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[VCVT_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
// CHECK: [[VCVT_N1:%.*]] = call <1 x double> @llvm.aarch64.neon.vcvtfxs2fp.v1f64.v1i64(<1 x i64> [[VCVT_N]], i32 64)
@@ -22359,7 +21368,7 @@ float64x1_t test_vcvt_n_f64_s64(int64x1_t a) {
return vcvt_n_f64_s64(a, 64);
}
-// CHECK-LABEL: define <1 x double> @test_vcvt_n_f64_u64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vcvt_n_f64_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[VCVT_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
// CHECK: [[VCVT_N1:%.*]] = call <1 x double> @llvm.aarch64.neon.vcvtfxu2fp.v1f64.v1i64(<1 x i64> [[VCVT_N]], i32 64)
@@ -22368,189 +21377,164 @@ float64x1_t test_vcvt_n_f64_u64(uint64x1_t a) {
return vcvt_n_f64_u64(a, 64);
}
-// CHECK-LABEL: define <1 x double> @test_vrndn_f64(<1 x double> %a) #0 {
+// CHECK-LABEL: @test_vrndn_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
-// CHECK: [[VRNDN_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x double>
-// CHECK: [[VRNDN1_I:%.*]] = call <1 x double> @llvm.aarch64.neon.frintn.v1f64(<1 x double> [[VRNDN_I]]) #4
+// CHECK: [[VRNDN1_I:%.*]] = call <1 x double> @llvm.aarch64.neon.frintn.v1f64(<1 x double> %a) #4
// CHECK: ret <1 x double> [[VRNDN1_I]]
float64x1_t test_vrndn_f64(float64x1_t a) {
return vrndn_f64(a);
}
-// CHECK-LABEL: define <1 x double> @test_vrnda_f64(<1 x double> %a) #0 {
+// CHECK-LABEL: @test_vrnda_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
-// CHECK: [[VRNDA_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x double>
-// CHECK: [[VRNDA1_I:%.*]] = call <1 x double> @llvm.round.v1f64(<1 x double> [[VRNDA_I]]) #4
+// CHECK: [[VRNDA1_I:%.*]] = call <1 x double> @llvm.round.v1f64(<1 x double> %a) #4
// CHECK: ret <1 x double> [[VRNDA1_I]]
float64x1_t test_vrnda_f64(float64x1_t a) {
return vrnda_f64(a);
}
-// CHECK-LABEL: define <1 x double> @test_vrndp_f64(<1 x double> %a) #0 {
+// CHECK-LABEL: @test_vrndp_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
-// CHECK: [[VRNDP_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x double>
-// CHECK: [[VRNDP1_I:%.*]] = call <1 x double> @llvm.ceil.v1f64(<1 x double> [[VRNDP_I]]) #4
+// CHECK: [[VRNDP1_I:%.*]] = call <1 x double> @llvm.ceil.v1f64(<1 x double> %a) #4
// CHECK: ret <1 x double> [[VRNDP1_I]]
float64x1_t test_vrndp_f64(float64x1_t a) {
return vrndp_f64(a);
}
-// CHECK-LABEL: define <1 x double> @test_vrndm_f64(<1 x double> %a) #0 {
+// CHECK-LABEL: @test_vrndm_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
-// CHECK: [[VRNDM_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x double>
-// CHECK: [[VRNDM1_I:%.*]] = call <1 x double> @llvm.floor.v1f64(<1 x double> [[VRNDM_I]]) #4
+// CHECK: [[VRNDM1_I:%.*]] = call <1 x double> @llvm.floor.v1f64(<1 x double> %a) #4
// CHECK: ret <1 x double> [[VRNDM1_I]]
float64x1_t test_vrndm_f64(float64x1_t a) {
return vrndm_f64(a);
}
-// CHECK-LABEL: define <1 x double> @test_vrndx_f64(<1 x double> %a) #0 {
+// CHECK-LABEL: @test_vrndx_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
-// CHECK: [[VRNDX_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x double>
-// CHECK: [[VRNDX1_I:%.*]] = call <1 x double> @llvm.rint.v1f64(<1 x double> [[VRNDX_I]]) #4
+// CHECK: [[VRNDX1_I:%.*]] = call <1 x double> @llvm.rint.v1f64(<1 x double> %a) #4
// CHECK: ret <1 x double> [[VRNDX1_I]]
float64x1_t test_vrndx_f64(float64x1_t a) {
return vrndx_f64(a);
}
-// CHECK-LABEL: define <1 x double> @test_vrnd_f64(<1 x double> %a) #0 {
+// CHECK-LABEL: @test_vrnd_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
-// CHECK: [[VRNDZ_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x double>
-// CHECK: [[VRNDZ1_I:%.*]] = call <1 x double> @llvm.trunc.v1f64(<1 x double> [[VRNDZ_I]]) #4
+// CHECK: [[VRNDZ1_I:%.*]] = call <1 x double> @llvm.trunc.v1f64(<1 x double> %a) #4
// CHECK: ret <1 x double> [[VRNDZ1_I]]
float64x1_t test_vrnd_f64(float64x1_t a) {
return vrnd_f64(a);
}
-// CHECK-LABEL: define <1 x double> @test_vrndi_f64(<1 x double> %a) #0 {
+// CHECK-LABEL: @test_vrndi_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
-// CHECK: [[VRNDI_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x double>
-// CHECK: [[VRNDI1_I:%.*]] = call <1 x double> @llvm.nearbyint.v1f64(<1 x double> [[VRNDI_I]]) #4
+// CHECK: [[VRNDI1_I:%.*]] = call <1 x double> @llvm.nearbyint.v1f64(<1 x double> %a) #4
// CHECK: ret <1 x double> [[VRNDI1_I]]
float64x1_t test_vrndi_f64(float64x1_t a) {
return vrndi_f64(a);
}
-// CHECK-LABEL: define <1 x double> @test_vrsqrte_f64(<1 x double> %a) #0 {
+// CHECK-LABEL: @test_vrsqrte_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
-// CHECK: [[VRSQRTE_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x double>
-// CHECK: [[VRSQRTE_V1_I:%.*]] = call <1 x double> @llvm.aarch64.neon.frsqrte.v1f64(<1 x double> [[VRSQRTE_V_I]]) #4
+// CHECK: [[VRSQRTE_V1_I:%.*]] = call <1 x double> @llvm.aarch64.neon.frsqrte.v1f64(<1 x double> %a) #4
// CHECK: ret <1 x double> [[VRSQRTE_V1_I]]
float64x1_t test_vrsqrte_f64(float64x1_t a) {
return vrsqrte_f64(a);
}
-// CHECK-LABEL: define <1 x double> @test_vrecpe_f64(<1 x double> %a) #0 {
+// CHECK-LABEL: @test_vrecpe_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
-// CHECK: [[VRECPE_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x double>
-// CHECK: [[VRECPE_V1_I:%.*]] = call <1 x double> @llvm.aarch64.neon.frecpe.v1f64(<1 x double> [[VRECPE_V_I]]) #4
+// CHECK: [[VRECPE_V1_I:%.*]] = call <1 x double> @llvm.aarch64.neon.frecpe.v1f64(<1 x double> %a) #4
// CHECK: ret <1 x double> [[VRECPE_V1_I]]
float64x1_t test_vrecpe_f64(float64x1_t a) {
return vrecpe_f64(a);
}
-// CHECK-LABEL: define <1 x double> @test_vsqrt_f64(<1 x double> %a) #0 {
+// CHECK-LABEL: @test_vsqrt_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x double>
-// CHECK: [[VSQRT_I:%.*]] = call <1 x double> @llvm.sqrt.v1f64(<1 x double> [[TMP1]]) #4
+// CHECK: [[VSQRT_I:%.*]] = call <1 x double> @llvm.sqrt.v1f64(<1 x double> %a) #4
// CHECK: ret <1 x double> [[VSQRT_I]]
float64x1_t test_vsqrt_f64(float64x1_t a) {
return vsqrt_f64(a);
}
-// CHECK-LABEL: define <1 x double> @test_vrecps_f64(<1 x double> %a, <1 x double> %b) #0 {
+// CHECK-LABEL: @test_vrecps_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x double> %b to <8 x i8>
-// CHECK: [[VRECPS_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x double>
-// CHECK: [[VRECPS_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x double>
-// CHECK: [[VRECPS_V2_I:%.*]] = call <1 x double> @llvm.aarch64.neon.frecps.v1f64(<1 x double> [[VRECPS_V_I]], <1 x double> [[VRECPS_V1_I]]) #4
-// CHECK: [[VRECPS_V3_I:%.*]] = bitcast <1 x double> [[VRECPS_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRECPS_V3_I]] to <1 x double>
-// CHECK: ret <1 x double> [[TMP2]]
+// CHECK: [[VRECPS_V2_I:%.*]] = call <1 x double> @llvm.aarch64.neon.frecps.v1f64(<1 x double> %a, <1 x double> %b) #4
+// CHECK: ret <1 x double> [[VRECPS_V2_I]]
float64x1_t test_vrecps_f64(float64x1_t a, float64x1_t b) {
return vrecps_f64(a, b);
}
-// CHECK-LABEL: define <1 x double> @test_vrsqrts_f64(<1 x double> %a, <1 x double> %b) #0 {
+// CHECK-LABEL: @test_vrsqrts_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x double> %b to <8 x i8>
-// CHECK: [[VRSQRTS_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x double>
-// CHECK: [[VRSQRTS_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x double>
-// CHECK: [[VRSQRTS_V2_I:%.*]] = call <1 x double> @llvm.aarch64.neon.frsqrts.v1f64(<1 x double> [[VRSQRTS_V_I]], <1 x double> [[VRSQRTS_V1_I]]) #4
+// CHECK: [[VRSQRTS_V2_I:%.*]] = call <1 x double> @llvm.aarch64.neon.frsqrts.v1f64(<1 x double> %a, <1 x double> %b) #4
// CHECK: [[VRSQRTS_V3_I:%.*]] = bitcast <1 x double> [[VRSQRTS_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRSQRTS_V3_I]] to <1 x double>
-// CHECK: ret <1 x double> [[TMP2]]
+// CHECK: ret <1 x double> [[VRSQRTS_V2_I]]
float64x1_t test_vrsqrts_f64(float64x1_t a, float64x1_t b) {
return vrsqrts_f64(a, b);
}
-// CHECK-LABEL: define i32 @test_vminv_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vminv_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMINV_S32_I:%.*]] = call i32 @llvm.aarch64.neon.sminv.i32.v2i32(<2 x i32> [[TMP1]]) #4
+// CHECK: [[VMINV_S32_I:%.*]] = call i32 @llvm.aarch64.neon.sminv.i32.v2i32(<2 x i32> %a) #4
// CHECK: ret i32 [[VMINV_S32_I]]
int32_t test_vminv_s32(int32x2_t a) {
return vminv_s32(a);
}
-// CHECK-LABEL: define i32 @test_vminv_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vminv_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMINV_U32_I:%.*]] = call i32 @llvm.aarch64.neon.uminv.i32.v2i32(<2 x i32> [[TMP1]]) #4
+// CHECK: [[VMINV_U32_I:%.*]] = call i32 @llvm.aarch64.neon.uminv.i32.v2i32(<2 x i32> %a) #4
// CHECK: ret i32 [[VMINV_U32_I]]
uint32_t test_vminv_u32(uint32x2_t a) {
return vminv_u32(a);
}
-// CHECK-LABEL: define i32 @test_vmaxv_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vmaxv_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMAXV_S32_I:%.*]] = call i32 @llvm.aarch64.neon.smaxv.i32.v2i32(<2 x i32> [[TMP1]]) #4
+// CHECK: [[VMAXV_S32_I:%.*]] = call i32 @llvm.aarch64.neon.smaxv.i32.v2i32(<2 x i32> %a) #4
// CHECK: ret i32 [[VMAXV_S32_I]]
int32_t test_vmaxv_s32(int32x2_t a) {
return vmaxv_s32(a);
}
-// CHECK-LABEL: define i32 @test_vmaxv_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vmaxv_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMAXV_U32_I:%.*]] = call i32 @llvm.aarch64.neon.umaxv.i32.v2i32(<2 x i32> [[TMP1]]) #4
+// CHECK: [[VMAXV_U32_I:%.*]] = call i32 @llvm.aarch64.neon.umaxv.i32.v2i32(<2 x i32> %a) #4
// CHECK: ret i32 [[VMAXV_U32_I]]
uint32_t test_vmaxv_u32(uint32x2_t a) {
return vmaxv_u32(a);
}
-// CHECK-LABEL: define i32 @test_vaddv_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vaddv_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VADDV_S32_I:%.*]] = call i32 @llvm.aarch64.neon.saddv.i32.v2i32(<2 x i32> [[TMP1]]) #4
+// CHECK: [[VADDV_S32_I:%.*]] = call i32 @llvm.aarch64.neon.saddv.i32.v2i32(<2 x i32> %a) #4
// CHECK: ret i32 [[VADDV_S32_I]]
int32_t test_vaddv_s32(int32x2_t a) {
return vaddv_s32(a);
}
-// CHECK-LABEL: define i32 @test_vaddv_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vaddv_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VADDV_U32_I:%.*]] = call i32 @llvm.aarch64.neon.uaddv.i32.v2i32(<2 x i32> [[TMP1]]) #4
+// CHECK: [[VADDV_U32_I:%.*]] = call i32 @llvm.aarch64.neon.uaddv.i32.v2i32(<2 x i32> %a) #4
// CHECK: ret i32 [[VADDV_U32_I]]
uint32_t test_vaddv_u32(uint32x2_t a) {
return vaddv_u32(a);
}
-// CHECK-LABEL: define i64 @test_vaddlv_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vaddlv_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VADDLV_S32_I:%.*]] = call i64 @llvm.aarch64.neon.saddlv.i64.v2i32(<2 x i32> [[TMP1]]) #4
+// CHECK: [[VADDLV_S32_I:%.*]] = call i64 @llvm.aarch64.neon.saddlv.i64.v2i32(<2 x i32> %a) #4
// CHECK: ret i64 [[VADDLV_S32_I]]
int64_t test_vaddlv_s32(int32x2_t a) {
return vaddlv_s32(a);
}
-// CHECK-LABEL: define i64 @test_vaddlv_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vaddlv_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VADDLV_U32_I:%.*]] = call i64 @llvm.aarch64.neon.uaddlv.i64.v2i32(<2 x i32> [[TMP1]]) #4
+// CHECK: [[VADDLV_U32_I:%.*]] = call i64 @llvm.aarch64.neon.uaddlv.i64.v2i32(<2 x i32> %a) #4
// CHECK: ret i64 [[VADDLV_U32_I]]
uint64_t test_vaddlv_u32(uint32x2_t a) {
return vaddlv_u32(a);
diff --git a/test/CodeGen/aarch64-neon-misc.c b/test/CodeGen/aarch64-neon-misc.c
index 4ecf562a5d29..1342bbb0c8cb 100644
--- a/test/CodeGen/aarch64-neon-misc.c
+++ b/test/CodeGen/aarch64-neon-misc.c
@@ -6,7 +6,7 @@
#include <arm_neon.h>
-// CHECK-LABEL: define <8 x i8> @test_vceqz_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vceqz_s8(
// CHECK: [[TMP0:%.*]] = icmp eq <8 x i8> %a, zeroinitializer
// CHECK: [[VCEQZ_I:%.*]] = sext <8 x i1> [[TMP0]] to <8 x i8>
// CHECK: ret <8 x i8> [[VCEQZ_I]]
@@ -14,57 +14,52 @@ uint8x8_t test_vceqz_s8(int8x8_t a) {
return vceqz_s8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vceqz_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vceqz_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[TMP2:%.*]] = icmp eq <4 x i16> [[TMP1]], zeroinitializer
-// CHECK: [[VCEQZ_I:%.*]] = sext <4 x i1> [[TMP2]] to <4 x i16>
+// CHECK: [[TMP1:%.*]] = icmp eq <4 x i16> %a, zeroinitializer
+// CHECK: [[VCEQZ_I:%.*]] = sext <4 x i1> [[TMP1]] to <4 x i16>
// CHECK: ret <4 x i16> [[VCEQZ_I]]
uint16x4_t test_vceqz_s16(int16x4_t a) {
return vceqz_s16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vceqz_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vceqz_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[TMP2:%.*]] = icmp eq <2 x i32> [[TMP1]], zeroinitializer
-// CHECK: [[VCEQZ_I:%.*]] = sext <2 x i1> [[TMP2]] to <2 x i32>
+// CHECK: [[TMP1:%.*]] = icmp eq <2 x i32> %a, zeroinitializer
+// CHECK: [[VCEQZ_I:%.*]] = sext <2 x i1> [[TMP1]] to <2 x i32>
// CHECK: ret <2 x i32> [[VCEQZ_I]]
uint32x2_t test_vceqz_s32(int32x2_t a) {
return vceqz_s32(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vceqz_s64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vceqz_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
-// CHECK: [[TMP2:%.*]] = icmp eq <1 x i64> [[TMP1]], zeroinitializer
-// CHECK: [[VCEQZ_I:%.*]] = sext <1 x i1> [[TMP2]] to <1 x i64>
+// CHECK: [[TMP1:%.*]] = icmp eq <1 x i64> %a, zeroinitializer
+// CHECK: [[VCEQZ_I:%.*]] = sext <1 x i1> [[TMP1]] to <1 x i64>
// CHECK: ret <1 x i64> [[VCEQZ_I]]
uint64x1_t test_vceqz_s64(int64x1_t a) {
return vceqz_s64(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vceqz_u64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vceqz_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
-// CHECK: [[TMP2:%.*]] = icmp eq <1 x i64> [[TMP1]], zeroinitializer
-// CHECK: [[VCEQZ_I:%.*]] = sext <1 x i1> [[TMP2]] to <1 x i64>
+// CHECK: [[TMP1:%.*]] = icmp eq <1 x i64> %a, zeroinitializer
+// CHECK: [[VCEQZ_I:%.*]] = sext <1 x i1> [[TMP1]] to <1 x i64>
// CHECK: ret <1 x i64> [[VCEQZ_I]]
uint64x1_t test_vceqz_u64(uint64x1_t a) {
return vceqz_u64(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vceqz_p64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vceqz_p64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
-// CHECK: [[TMP2:%.*]] = icmp eq <1 x i64> [[TMP1]], zeroinitializer
-// CHECK: [[VCEQZ_I:%.*]] = sext <1 x i1> [[TMP2]] to <1 x i64>
+// CHECK: [[TMP1:%.*]] = icmp eq <1 x i64> %a, zeroinitializer
+// CHECK: [[VCEQZ_I:%.*]] = sext <1 x i1> [[TMP1]] to <1 x i64>
// CHECK: ret <1 x i64> [[VCEQZ_I]]
uint64x1_t test_vceqz_p64(poly64x1_t a) {
return vceqz_p64(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vceqzq_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vceqzq_s8(
// CHECK: [[TMP0:%.*]] = icmp eq <16 x i8> %a, zeroinitializer
// CHECK: [[VCEQZ_I:%.*]] = sext <16 x i1> [[TMP0]] to <16 x i8>
// CHECK: ret <16 x i8> [[VCEQZ_I]]
@@ -72,37 +67,34 @@ uint8x16_t test_vceqzq_s8(int8x16_t a) {
return vceqzq_s8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vceqzq_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vceqzq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[TMP2:%.*]] = icmp eq <8 x i16> [[TMP1]], zeroinitializer
-// CHECK: [[VCEQZ_I:%.*]] = sext <8 x i1> [[TMP2]] to <8 x i16>
+// CHECK: [[TMP1:%.*]] = icmp eq <8 x i16> %a, zeroinitializer
+// CHECK: [[VCEQZ_I:%.*]] = sext <8 x i1> [[TMP1]] to <8 x i16>
// CHECK: ret <8 x i16> [[VCEQZ_I]]
uint16x8_t test_vceqzq_s16(int16x8_t a) {
return vceqzq_s16(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vceqzq_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vceqzq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[TMP2:%.*]] = icmp eq <4 x i32> [[TMP1]], zeroinitializer
-// CHECK: [[VCEQZ_I:%.*]] = sext <4 x i1> [[TMP2]] to <4 x i32>
+// CHECK: [[TMP1:%.*]] = icmp eq <4 x i32> %a, zeroinitializer
+// CHECK: [[VCEQZ_I:%.*]] = sext <4 x i1> [[TMP1]] to <4 x i32>
// CHECK: ret <4 x i32> [[VCEQZ_I]]
uint32x4_t test_vceqzq_s32(int32x4_t a) {
return vceqzq_s32(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vceqzq_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vceqzq_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[TMP2:%.*]] = icmp eq <2 x i64> [[TMP1]], zeroinitializer
-// CHECK: [[VCEQZ_I:%.*]] = sext <2 x i1> [[TMP2]] to <2 x i64>
+// CHECK: [[TMP1:%.*]] = icmp eq <2 x i64> %a, zeroinitializer
+// CHECK: [[VCEQZ_I:%.*]] = sext <2 x i1> [[TMP1]] to <2 x i64>
// CHECK: ret <2 x i64> [[VCEQZ_I]]
uint64x2_t test_vceqzq_s64(int64x2_t a) {
return vceqzq_s64(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vceqz_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vceqz_u8(
// CHECK: [[TMP0:%.*]] = icmp eq <8 x i8> %a, zeroinitializer
// CHECK: [[VCEQZ_I:%.*]] = sext <8 x i1> [[TMP0]] to <8 x i8>
// CHECK: ret <8 x i8> [[VCEQZ_I]]
@@ -110,27 +102,25 @@ uint8x8_t test_vceqz_u8(uint8x8_t a) {
return vceqz_u8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vceqz_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vceqz_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[TMP2:%.*]] = icmp eq <4 x i16> [[TMP1]], zeroinitializer
-// CHECK: [[VCEQZ_I:%.*]] = sext <4 x i1> [[TMP2]] to <4 x i16>
+// CHECK: [[TMP1:%.*]] = icmp eq <4 x i16> %a, zeroinitializer
+// CHECK: [[VCEQZ_I:%.*]] = sext <4 x i1> [[TMP1]] to <4 x i16>
// CHECK: ret <4 x i16> [[VCEQZ_I]]
uint16x4_t test_vceqz_u16(uint16x4_t a) {
return vceqz_u16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vceqz_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vceqz_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[TMP2:%.*]] = icmp eq <2 x i32> [[TMP1]], zeroinitializer
-// CHECK: [[VCEQZ_I:%.*]] = sext <2 x i1> [[TMP2]] to <2 x i32>
+// CHECK: [[TMP1:%.*]] = icmp eq <2 x i32> %a, zeroinitializer
+// CHECK: [[VCEQZ_I:%.*]] = sext <2 x i1> [[TMP1]] to <2 x i32>
// CHECK: ret <2 x i32> [[VCEQZ_I]]
uint32x2_t test_vceqz_u32(uint32x2_t a) {
return vceqz_u32(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vceqzq_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vceqzq_u8(
// CHECK: [[TMP0:%.*]] = icmp eq <16 x i8> %a, zeroinitializer
// CHECK: [[VCEQZ_I:%.*]] = sext <16 x i1> [[TMP0]] to <16 x i8>
// CHECK: ret <16 x i8> [[VCEQZ_I]]
@@ -138,67 +128,61 @@ uint8x16_t test_vceqzq_u8(uint8x16_t a) {
return vceqzq_u8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vceqzq_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vceqzq_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[TMP2:%.*]] = icmp eq <8 x i16> [[TMP1]], zeroinitializer
-// CHECK: [[VCEQZ_I:%.*]] = sext <8 x i1> [[TMP2]] to <8 x i16>
+// CHECK: [[TMP1:%.*]] = icmp eq <8 x i16> %a, zeroinitializer
+// CHECK: [[VCEQZ_I:%.*]] = sext <8 x i1> [[TMP1]] to <8 x i16>
// CHECK: ret <8 x i16> [[VCEQZ_I]]
uint16x8_t test_vceqzq_u16(uint16x8_t a) {
return vceqzq_u16(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vceqzq_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vceqzq_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[TMP2:%.*]] = icmp eq <4 x i32> [[TMP1]], zeroinitializer
-// CHECK: [[VCEQZ_I:%.*]] = sext <4 x i1> [[TMP2]] to <4 x i32>
+// CHECK: [[TMP1:%.*]] = icmp eq <4 x i32> %a, zeroinitializer
+// CHECK: [[VCEQZ_I:%.*]] = sext <4 x i1> [[TMP1]] to <4 x i32>
// CHECK: ret <4 x i32> [[VCEQZ_I]]
uint32x4_t test_vceqzq_u32(uint32x4_t a) {
return vceqzq_u32(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vceqzq_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vceqzq_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[TMP2:%.*]] = icmp eq <2 x i64> [[TMP1]], zeroinitializer
-// CHECK: [[VCEQZ_I:%.*]] = sext <2 x i1> [[TMP2]] to <2 x i64>
+// CHECK: [[TMP1:%.*]] = icmp eq <2 x i64> %a, zeroinitializer
+// CHECK: [[VCEQZ_I:%.*]] = sext <2 x i1> [[TMP1]] to <2 x i64>
// CHECK: ret <2 x i64> [[VCEQZ_I]]
uint64x2_t test_vceqzq_u64(uint64x2_t a) {
return vceqzq_u64(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vceqz_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vceqz_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[TMP2:%.*]] = fcmp oeq <2 x float> [[TMP1]], zeroinitializer
-// CHECK: [[VCEQZ_I:%.*]] = sext <2 x i1> [[TMP2]] to <2 x i32>
+// CHECK: [[TMP1:%.*]] = fcmp oeq <2 x float> %a, zeroinitializer
+// CHECK: [[VCEQZ_I:%.*]] = sext <2 x i1> [[TMP1]] to <2 x i32>
// CHECK: ret <2 x i32> [[VCEQZ_I]]
uint32x2_t test_vceqz_f32(float32x2_t a) {
return vceqz_f32(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vceqz_f64(<1 x double> %a) #0 {
+// CHECK-LABEL: @test_vceqz_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x double>
-// CHECK: [[TMP2:%.*]] = fcmp oeq <1 x double> [[TMP1]], zeroinitializer
-// CHECK: [[VCEQZ_I:%.*]] = sext <1 x i1> [[TMP2]] to <1 x i64>
+// CHECK: [[TMP1:%.*]] = fcmp oeq <1 x double> %a, zeroinitializer
+// CHECK: [[VCEQZ_I:%.*]] = sext <1 x i1> [[TMP1]] to <1 x i64>
// CHECK: ret <1 x i64> [[VCEQZ_I]]
uint64x1_t test_vceqz_f64(float64x1_t a) {
return vceqz_f64(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vceqzq_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vceqzq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[TMP2:%.*]] = fcmp oeq <4 x float> [[TMP1]], zeroinitializer
-// CHECK: [[VCEQZ_I:%.*]] = sext <4 x i1> [[TMP2]] to <4 x i32>
+// CHECK: [[TMP1:%.*]] = fcmp oeq <4 x float> %a, zeroinitializer
+// CHECK: [[VCEQZ_I:%.*]] = sext <4 x i1> [[TMP1]] to <4 x i32>
// CHECK: ret <4 x i32> [[VCEQZ_I]]
uint32x4_t test_vceqzq_f32(float32x4_t a) {
return vceqzq_f32(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vceqz_p8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vceqz_p8(
// CHECK: [[TMP0:%.*]] = icmp eq <8 x i8> %a, zeroinitializer
// CHECK: [[VCEQZ_I:%.*]] = sext <8 x i1> [[TMP0]] to <8 x i8>
// CHECK: ret <8 x i8> [[VCEQZ_I]]
@@ -206,7 +190,7 @@ uint8x8_t test_vceqz_p8(poly8x8_t a) {
return vceqz_p8(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vceqzq_p8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vceqzq_p8(
// CHECK: [[TMP0:%.*]] = icmp eq <16 x i8> %a, zeroinitializer
// CHECK: [[VCEQZ_I:%.*]] = sext <16 x i1> [[TMP0]] to <16 x i8>
// CHECK: ret <16 x i8> [[VCEQZ_I]]
@@ -214,47 +198,43 @@ uint8x16_t test_vceqzq_p8(poly8x16_t a) {
return vceqzq_p8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vceqz_p16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vceqz_p16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[TMP2:%.*]] = icmp eq <4 x i16> [[TMP1]], zeroinitializer
-// CHECK: [[VCEQZ_I:%.*]] = sext <4 x i1> [[TMP2]] to <4 x i16>
+// CHECK: [[TMP1:%.*]] = icmp eq <4 x i16> %a, zeroinitializer
+// CHECK: [[VCEQZ_I:%.*]] = sext <4 x i1> [[TMP1]] to <4 x i16>
// CHECK: ret <4 x i16> [[VCEQZ_I]]
uint16x4_t test_vceqz_p16(poly16x4_t a) {
return vceqz_p16(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vceqzq_p16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vceqzq_p16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[TMP2:%.*]] = icmp eq <8 x i16> [[TMP1]], zeroinitializer
-// CHECK: [[VCEQZ_I:%.*]] = sext <8 x i1> [[TMP2]] to <8 x i16>
+// CHECK: [[TMP1:%.*]] = icmp eq <8 x i16> %a, zeroinitializer
+// CHECK: [[VCEQZ_I:%.*]] = sext <8 x i1> [[TMP1]] to <8 x i16>
// CHECK: ret <8 x i16> [[VCEQZ_I]]
uint16x8_t test_vceqzq_p16(poly16x8_t a) {
return vceqzq_p16(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vceqzq_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vceqzq_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[TMP2:%.*]] = fcmp oeq <2 x double> [[TMP1]], zeroinitializer
-// CHECK: [[VCEQZ_I:%.*]] = sext <2 x i1> [[TMP2]] to <2 x i64>
+// CHECK: [[TMP1:%.*]] = fcmp oeq <2 x double> %a, zeroinitializer
+// CHECK: [[VCEQZ_I:%.*]] = sext <2 x i1> [[TMP1]] to <2 x i64>
// CHECK: ret <2 x i64> [[VCEQZ_I]]
uint64x2_t test_vceqzq_f64(float64x2_t a) {
return vceqzq_f64(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vceqzq_p64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vceqzq_p64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[TMP2:%.*]] = icmp eq <2 x i64> [[TMP1]], zeroinitializer
-// CHECK: [[VCEQZ_I:%.*]] = sext <2 x i1> [[TMP2]] to <2 x i64>
+// CHECK: [[TMP1:%.*]] = icmp eq <2 x i64> %a, zeroinitializer
+// CHECK: [[VCEQZ_I:%.*]] = sext <2 x i1> [[TMP1]] to <2 x i64>
// CHECK: ret <2 x i64> [[VCEQZ_I]]
uint64x2_t test_vceqzq_p64(poly64x2_t a) {
return vceqzq_p64(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vcgez_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vcgez_s8(
// CHECK: [[TMP0:%.*]] = icmp sge <8 x i8> %a, zeroinitializer
// CHECK: [[VCGEZ_I:%.*]] = sext <8 x i1> [[TMP0]] to <8 x i8>
// CHECK: ret <8 x i8> [[VCGEZ_I]]
@@ -262,37 +242,34 @@ uint8x8_t test_vcgez_s8(int8x8_t a) {
return vcgez_s8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vcgez_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vcgez_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[TMP2:%.*]] = icmp sge <4 x i16> [[TMP1]], zeroinitializer
-// CHECK: [[VCGEZ_I:%.*]] = sext <4 x i1> [[TMP2]] to <4 x i16>
+// CHECK: [[TMP1:%.*]] = icmp sge <4 x i16> %a, zeroinitializer
+// CHECK: [[VCGEZ_I:%.*]] = sext <4 x i1> [[TMP1]] to <4 x i16>
// CHECK: ret <4 x i16> [[VCGEZ_I]]
uint16x4_t test_vcgez_s16(int16x4_t a) {
return vcgez_s16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vcgez_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vcgez_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[TMP2:%.*]] = icmp sge <2 x i32> [[TMP1]], zeroinitializer
-// CHECK: [[VCGEZ_I:%.*]] = sext <2 x i1> [[TMP2]] to <2 x i32>
+// CHECK: [[TMP1:%.*]] = icmp sge <2 x i32> %a, zeroinitializer
+// CHECK: [[VCGEZ_I:%.*]] = sext <2 x i1> [[TMP1]] to <2 x i32>
// CHECK: ret <2 x i32> [[VCGEZ_I]]
uint32x2_t test_vcgez_s32(int32x2_t a) {
return vcgez_s32(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vcgez_s64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vcgez_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
-// CHECK: [[TMP2:%.*]] = icmp sge <1 x i64> [[TMP1]], zeroinitializer
-// CHECK: [[VCGEZ_I:%.*]] = sext <1 x i1> [[TMP2]] to <1 x i64>
+// CHECK: [[TMP1:%.*]] = icmp sge <1 x i64> %a, zeroinitializer
+// CHECK: [[VCGEZ_I:%.*]] = sext <1 x i1> [[TMP1]] to <1 x i64>
// CHECK: ret <1 x i64> [[VCGEZ_I]]
uint64x1_t test_vcgez_s64(int64x1_t a) {
return vcgez_s64(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vcgezq_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vcgezq_s8(
// CHECK: [[TMP0:%.*]] = icmp sge <16 x i8> %a, zeroinitializer
// CHECK: [[VCGEZ_I:%.*]] = sext <16 x i1> [[TMP0]] to <16 x i8>
// CHECK: ret <16 x i8> [[VCGEZ_I]]
@@ -300,77 +277,70 @@ uint8x16_t test_vcgezq_s8(int8x16_t a) {
return vcgezq_s8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vcgezq_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vcgezq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[TMP2:%.*]] = icmp sge <8 x i16> [[TMP1]], zeroinitializer
-// CHECK: [[VCGEZ_I:%.*]] = sext <8 x i1> [[TMP2]] to <8 x i16>
+// CHECK: [[TMP1:%.*]] = icmp sge <8 x i16> %a, zeroinitializer
+// CHECK: [[VCGEZ_I:%.*]] = sext <8 x i1> [[TMP1]] to <8 x i16>
// CHECK: ret <8 x i16> [[VCGEZ_I]]
uint16x8_t test_vcgezq_s16(int16x8_t a) {
return vcgezq_s16(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vcgezq_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vcgezq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[TMP2:%.*]] = icmp sge <4 x i32> [[TMP1]], zeroinitializer
-// CHECK: [[VCGEZ_I:%.*]] = sext <4 x i1> [[TMP2]] to <4 x i32>
+// CHECK: [[TMP1:%.*]] = icmp sge <4 x i32> %a, zeroinitializer
+// CHECK: [[VCGEZ_I:%.*]] = sext <4 x i1> [[TMP1]] to <4 x i32>
// CHECK: ret <4 x i32> [[VCGEZ_I]]
uint32x4_t test_vcgezq_s32(int32x4_t a) {
return vcgezq_s32(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vcgezq_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vcgezq_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[TMP2:%.*]] = icmp sge <2 x i64> [[TMP1]], zeroinitializer
-// CHECK: [[VCGEZ_I:%.*]] = sext <2 x i1> [[TMP2]] to <2 x i64>
+// CHECK: [[TMP1:%.*]] = icmp sge <2 x i64> %a, zeroinitializer
+// CHECK: [[VCGEZ_I:%.*]] = sext <2 x i1> [[TMP1]] to <2 x i64>
// CHECK: ret <2 x i64> [[VCGEZ_I]]
uint64x2_t test_vcgezq_s64(int64x2_t a) {
return vcgezq_s64(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vcgez_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vcgez_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[TMP2:%.*]] = fcmp oge <2 x float> [[TMP1]], zeroinitializer
-// CHECK: [[VCGEZ_I:%.*]] = sext <2 x i1> [[TMP2]] to <2 x i32>
+// CHECK: [[TMP1:%.*]] = fcmp oge <2 x float> %a, zeroinitializer
+// CHECK: [[VCGEZ_I:%.*]] = sext <2 x i1> [[TMP1]] to <2 x i32>
// CHECK: ret <2 x i32> [[VCGEZ_I]]
uint32x2_t test_vcgez_f32(float32x2_t a) {
return vcgez_f32(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vcgez_f64(<1 x double> %a) #0 {
+// CHECK-LABEL: @test_vcgez_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x double>
-// CHECK: [[TMP2:%.*]] = fcmp oge <1 x double> [[TMP1]], zeroinitializer
-// CHECK: [[VCGEZ_I:%.*]] = sext <1 x i1> [[TMP2]] to <1 x i64>
+// CHECK: [[TMP1:%.*]] = fcmp oge <1 x double> %a, zeroinitializer
+// CHECK: [[VCGEZ_I:%.*]] = sext <1 x i1> [[TMP1]] to <1 x i64>
// CHECK: ret <1 x i64> [[VCGEZ_I]]
uint64x1_t test_vcgez_f64(float64x1_t a) {
return vcgez_f64(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vcgezq_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vcgezq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[TMP2:%.*]] = fcmp oge <4 x float> [[TMP1]], zeroinitializer
-// CHECK: [[VCGEZ_I:%.*]] = sext <4 x i1> [[TMP2]] to <4 x i32>
+// CHECK: [[TMP1:%.*]] = fcmp oge <4 x float> %a, zeroinitializer
+// CHECK: [[VCGEZ_I:%.*]] = sext <4 x i1> [[TMP1]] to <4 x i32>
// CHECK: ret <4 x i32> [[VCGEZ_I]]
uint32x4_t test_vcgezq_f32(float32x4_t a) {
return vcgezq_f32(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vcgezq_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vcgezq_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[TMP2:%.*]] = fcmp oge <2 x double> [[TMP1]], zeroinitializer
-// CHECK: [[VCGEZ_I:%.*]] = sext <2 x i1> [[TMP2]] to <2 x i64>
+// CHECK: [[TMP1:%.*]] = fcmp oge <2 x double> %a, zeroinitializer
+// CHECK: [[VCGEZ_I:%.*]] = sext <2 x i1> [[TMP1]] to <2 x i64>
// CHECK: ret <2 x i64> [[VCGEZ_I]]
uint64x2_t test_vcgezq_f64(float64x2_t a) {
return vcgezq_f64(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vclez_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vclez_s8(
// CHECK: [[TMP0:%.*]] = icmp sle <8 x i8> %a, zeroinitializer
// CHECK: [[VCLEZ_I:%.*]] = sext <8 x i1> [[TMP0]] to <8 x i8>
// CHECK: ret <8 x i8> [[VCLEZ_I]]
@@ -378,37 +348,34 @@ uint8x8_t test_vclez_s8(int8x8_t a) {
return vclez_s8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vclez_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vclez_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[TMP2:%.*]] = icmp sle <4 x i16> [[TMP1]], zeroinitializer
-// CHECK: [[VCLEZ_I:%.*]] = sext <4 x i1> [[TMP2]] to <4 x i16>
+// CHECK: [[TMP1:%.*]] = icmp sle <4 x i16> %a, zeroinitializer
+// CHECK: [[VCLEZ_I:%.*]] = sext <4 x i1> [[TMP1]] to <4 x i16>
// CHECK: ret <4 x i16> [[VCLEZ_I]]
uint16x4_t test_vclez_s16(int16x4_t a) {
return vclez_s16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vclez_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vclez_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[TMP2:%.*]] = icmp sle <2 x i32> [[TMP1]], zeroinitializer
-// CHECK: [[VCLEZ_I:%.*]] = sext <2 x i1> [[TMP2]] to <2 x i32>
+// CHECK: [[TMP1:%.*]] = icmp sle <2 x i32> %a, zeroinitializer
+// CHECK: [[VCLEZ_I:%.*]] = sext <2 x i1> [[TMP1]] to <2 x i32>
// CHECK: ret <2 x i32> [[VCLEZ_I]]
uint32x2_t test_vclez_s32(int32x2_t a) {
return vclez_s32(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vclez_s64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vclez_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
-// CHECK: [[TMP2:%.*]] = icmp sle <1 x i64> [[TMP1]], zeroinitializer
-// CHECK: [[VCLEZ_I:%.*]] = sext <1 x i1> [[TMP2]] to <1 x i64>
+// CHECK: [[TMP1:%.*]] = icmp sle <1 x i64> %a, zeroinitializer
+// CHECK: [[VCLEZ_I:%.*]] = sext <1 x i1> [[TMP1]] to <1 x i64>
// CHECK: ret <1 x i64> [[VCLEZ_I]]
uint64x1_t test_vclez_s64(int64x1_t a) {
return vclez_s64(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vclezq_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vclezq_s8(
// CHECK: [[TMP0:%.*]] = icmp sle <16 x i8> %a, zeroinitializer
// CHECK: [[VCLEZ_I:%.*]] = sext <16 x i1> [[TMP0]] to <16 x i8>
// CHECK: ret <16 x i8> [[VCLEZ_I]]
@@ -416,77 +383,70 @@ uint8x16_t test_vclezq_s8(int8x16_t a) {
return vclezq_s8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vclezq_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vclezq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[TMP2:%.*]] = icmp sle <8 x i16> [[TMP1]], zeroinitializer
-// CHECK: [[VCLEZ_I:%.*]] = sext <8 x i1> [[TMP2]] to <8 x i16>
+// CHECK: [[TMP1:%.*]] = icmp sle <8 x i16> %a, zeroinitializer
+// CHECK: [[VCLEZ_I:%.*]] = sext <8 x i1> [[TMP1]] to <8 x i16>
// CHECK: ret <8 x i16> [[VCLEZ_I]]
uint16x8_t test_vclezq_s16(int16x8_t a) {
return vclezq_s16(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vclezq_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vclezq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[TMP2:%.*]] = icmp sle <4 x i32> [[TMP1]], zeroinitializer
-// CHECK: [[VCLEZ_I:%.*]] = sext <4 x i1> [[TMP2]] to <4 x i32>
+// CHECK: [[TMP1:%.*]] = icmp sle <4 x i32> %a, zeroinitializer
+// CHECK: [[VCLEZ_I:%.*]] = sext <4 x i1> [[TMP1]] to <4 x i32>
// CHECK: ret <4 x i32> [[VCLEZ_I]]
uint32x4_t test_vclezq_s32(int32x4_t a) {
return vclezq_s32(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vclezq_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vclezq_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[TMP2:%.*]] = icmp sle <2 x i64> [[TMP1]], zeroinitializer
-// CHECK: [[VCLEZ_I:%.*]] = sext <2 x i1> [[TMP2]] to <2 x i64>
+// CHECK: [[TMP1:%.*]] = icmp sle <2 x i64> %a, zeroinitializer
+// CHECK: [[VCLEZ_I:%.*]] = sext <2 x i1> [[TMP1]] to <2 x i64>
// CHECK: ret <2 x i64> [[VCLEZ_I]]
uint64x2_t test_vclezq_s64(int64x2_t a) {
return vclezq_s64(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vclez_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vclez_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[TMP2:%.*]] = fcmp ole <2 x float> [[TMP1]], zeroinitializer
-// CHECK: [[VCLEZ_I:%.*]] = sext <2 x i1> [[TMP2]] to <2 x i32>
+// CHECK: [[TMP1:%.*]] = fcmp ole <2 x float> %a, zeroinitializer
+// CHECK: [[VCLEZ_I:%.*]] = sext <2 x i1> [[TMP1]] to <2 x i32>
// CHECK: ret <2 x i32> [[VCLEZ_I]]
uint32x2_t test_vclez_f32(float32x2_t a) {
return vclez_f32(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vclez_f64(<1 x double> %a) #0 {
+// CHECK-LABEL: @test_vclez_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x double>
-// CHECK: [[TMP2:%.*]] = fcmp ole <1 x double> [[TMP1]], zeroinitializer
-// CHECK: [[VCLEZ_I:%.*]] = sext <1 x i1> [[TMP2]] to <1 x i64>
+// CHECK: [[TMP1:%.*]] = fcmp ole <1 x double> %a, zeroinitializer
+// CHECK: [[VCLEZ_I:%.*]] = sext <1 x i1> [[TMP1]] to <1 x i64>
// CHECK: ret <1 x i64> [[VCLEZ_I]]
uint64x1_t test_vclez_f64(float64x1_t a) {
return vclez_f64(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vclezq_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vclezq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[TMP2:%.*]] = fcmp ole <4 x float> [[TMP1]], zeroinitializer
-// CHECK: [[VCLEZ_I:%.*]] = sext <4 x i1> [[TMP2]] to <4 x i32>
+// CHECK: [[TMP1:%.*]] = fcmp ole <4 x float> %a, zeroinitializer
+// CHECK: [[VCLEZ_I:%.*]] = sext <4 x i1> [[TMP1]] to <4 x i32>
// CHECK: ret <4 x i32> [[VCLEZ_I]]
uint32x4_t test_vclezq_f32(float32x4_t a) {
return vclezq_f32(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vclezq_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vclezq_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[TMP2:%.*]] = fcmp ole <2 x double> [[TMP1]], zeroinitializer
-// CHECK: [[VCLEZ_I:%.*]] = sext <2 x i1> [[TMP2]] to <2 x i64>
+// CHECK: [[TMP1:%.*]] = fcmp ole <2 x double> %a, zeroinitializer
+// CHECK: [[VCLEZ_I:%.*]] = sext <2 x i1> [[TMP1]] to <2 x i64>
// CHECK: ret <2 x i64> [[VCLEZ_I]]
uint64x2_t test_vclezq_f64(float64x2_t a) {
return vclezq_f64(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vcgtz_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vcgtz_s8(
// CHECK: [[TMP0:%.*]] = icmp sgt <8 x i8> %a, zeroinitializer
// CHECK: [[VCGTZ_I:%.*]] = sext <8 x i1> [[TMP0]] to <8 x i8>
// CHECK: ret <8 x i8> [[VCGTZ_I]]
@@ -494,37 +454,34 @@ uint8x8_t test_vcgtz_s8(int8x8_t a) {
return vcgtz_s8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vcgtz_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vcgtz_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[TMP2:%.*]] = icmp sgt <4 x i16> [[TMP1]], zeroinitializer
-// CHECK: [[VCGTZ_I:%.*]] = sext <4 x i1> [[TMP2]] to <4 x i16>
+// CHECK: [[TMP1:%.*]] = icmp sgt <4 x i16> %a, zeroinitializer
+// CHECK: [[VCGTZ_I:%.*]] = sext <4 x i1> [[TMP1]] to <4 x i16>
// CHECK: ret <4 x i16> [[VCGTZ_I]]
uint16x4_t test_vcgtz_s16(int16x4_t a) {
return vcgtz_s16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vcgtz_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vcgtz_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[TMP2:%.*]] = icmp sgt <2 x i32> [[TMP1]], zeroinitializer
-// CHECK: [[VCGTZ_I:%.*]] = sext <2 x i1> [[TMP2]] to <2 x i32>
+// CHECK: [[TMP1:%.*]] = icmp sgt <2 x i32> %a, zeroinitializer
+// CHECK: [[VCGTZ_I:%.*]] = sext <2 x i1> [[TMP1]] to <2 x i32>
// CHECK: ret <2 x i32> [[VCGTZ_I]]
uint32x2_t test_vcgtz_s32(int32x2_t a) {
return vcgtz_s32(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vcgtz_s64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vcgtz_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
-// CHECK: [[TMP2:%.*]] = icmp sgt <1 x i64> [[TMP1]], zeroinitializer
-// CHECK: [[VCGTZ_I:%.*]] = sext <1 x i1> [[TMP2]] to <1 x i64>
+// CHECK: [[TMP1:%.*]] = icmp sgt <1 x i64> %a, zeroinitializer
+// CHECK: [[VCGTZ_I:%.*]] = sext <1 x i1> [[TMP1]] to <1 x i64>
// CHECK: ret <1 x i64> [[VCGTZ_I]]
uint64x1_t test_vcgtz_s64(int64x1_t a) {
return vcgtz_s64(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vcgtzq_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vcgtzq_s8(
// CHECK: [[TMP0:%.*]] = icmp sgt <16 x i8> %a, zeroinitializer
// CHECK: [[VCGTZ_I:%.*]] = sext <16 x i1> [[TMP0]] to <16 x i8>
// CHECK: ret <16 x i8> [[VCGTZ_I]]
@@ -532,77 +489,70 @@ uint8x16_t test_vcgtzq_s8(int8x16_t a) {
return vcgtzq_s8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vcgtzq_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vcgtzq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[TMP2:%.*]] = icmp sgt <8 x i16> [[TMP1]], zeroinitializer
-// CHECK: [[VCGTZ_I:%.*]] = sext <8 x i1> [[TMP2]] to <8 x i16>
+// CHECK: [[TMP1:%.*]] = icmp sgt <8 x i16> %a, zeroinitializer
+// CHECK: [[VCGTZ_I:%.*]] = sext <8 x i1> [[TMP1]] to <8 x i16>
// CHECK: ret <8 x i16> [[VCGTZ_I]]
uint16x8_t test_vcgtzq_s16(int16x8_t a) {
return vcgtzq_s16(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vcgtzq_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vcgtzq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[TMP2:%.*]] = icmp sgt <4 x i32> [[TMP1]], zeroinitializer
-// CHECK: [[VCGTZ_I:%.*]] = sext <4 x i1> [[TMP2]] to <4 x i32>
+// CHECK: [[TMP1:%.*]] = icmp sgt <4 x i32> %a, zeroinitializer
+// CHECK: [[VCGTZ_I:%.*]] = sext <4 x i1> [[TMP1]] to <4 x i32>
// CHECK: ret <4 x i32> [[VCGTZ_I]]
uint32x4_t test_vcgtzq_s32(int32x4_t a) {
return vcgtzq_s32(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vcgtzq_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vcgtzq_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[TMP2:%.*]] = icmp sgt <2 x i64> [[TMP1]], zeroinitializer
-// CHECK: [[VCGTZ_I:%.*]] = sext <2 x i1> [[TMP2]] to <2 x i64>
+// CHECK: [[TMP1:%.*]] = icmp sgt <2 x i64> %a, zeroinitializer
+// CHECK: [[VCGTZ_I:%.*]] = sext <2 x i1> [[TMP1]] to <2 x i64>
// CHECK: ret <2 x i64> [[VCGTZ_I]]
uint64x2_t test_vcgtzq_s64(int64x2_t a) {
return vcgtzq_s64(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vcgtz_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vcgtz_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[TMP2:%.*]] = fcmp ogt <2 x float> [[TMP1]], zeroinitializer
-// CHECK: [[VCGTZ_I:%.*]] = sext <2 x i1> [[TMP2]] to <2 x i32>
+// CHECK: [[TMP1:%.*]] = fcmp ogt <2 x float> %a, zeroinitializer
+// CHECK: [[VCGTZ_I:%.*]] = sext <2 x i1> [[TMP1]] to <2 x i32>
// CHECK: ret <2 x i32> [[VCGTZ_I]]
uint32x2_t test_vcgtz_f32(float32x2_t a) {
return vcgtz_f32(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vcgtz_f64(<1 x double> %a) #0 {
+// CHECK-LABEL: @test_vcgtz_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x double>
-// CHECK: [[TMP2:%.*]] = fcmp ogt <1 x double> [[TMP1]], zeroinitializer
-// CHECK: [[VCGTZ_I:%.*]] = sext <1 x i1> [[TMP2]] to <1 x i64>
+// CHECK: [[TMP1:%.*]] = fcmp ogt <1 x double> %a, zeroinitializer
+// CHECK: [[VCGTZ_I:%.*]] = sext <1 x i1> [[TMP1]] to <1 x i64>
// CHECK: ret <1 x i64> [[VCGTZ_I]]
uint64x1_t test_vcgtz_f64(float64x1_t a) {
return vcgtz_f64(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vcgtzq_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vcgtzq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[TMP2:%.*]] = fcmp ogt <4 x float> [[TMP1]], zeroinitializer
-// CHECK: [[VCGTZ_I:%.*]] = sext <4 x i1> [[TMP2]] to <4 x i32>
+// CHECK: [[TMP1:%.*]] = fcmp ogt <4 x float> %a, zeroinitializer
+// CHECK: [[VCGTZ_I:%.*]] = sext <4 x i1> [[TMP1]] to <4 x i32>
// CHECK: ret <4 x i32> [[VCGTZ_I]]
uint32x4_t test_vcgtzq_f32(float32x4_t a) {
return vcgtzq_f32(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vcgtzq_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vcgtzq_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[TMP2:%.*]] = fcmp ogt <2 x double> [[TMP1]], zeroinitializer
-// CHECK: [[VCGTZ_I:%.*]] = sext <2 x i1> [[TMP2]] to <2 x i64>
+// CHECK: [[TMP1:%.*]] = fcmp ogt <2 x double> %a, zeroinitializer
+// CHECK: [[VCGTZ_I:%.*]] = sext <2 x i1> [[TMP1]] to <2 x i64>
// CHECK: ret <2 x i64> [[VCGTZ_I]]
uint64x2_t test_vcgtzq_f64(float64x2_t a) {
return vcgtzq_f64(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vcltz_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vcltz_s8(
// CHECK: [[TMP0:%.*]] = icmp slt <8 x i8> %a, zeroinitializer
// CHECK: [[VCLTZ_I:%.*]] = sext <8 x i1> [[TMP0]] to <8 x i8>
// CHECK: ret <8 x i8> [[VCLTZ_I]]
@@ -610,37 +560,34 @@ uint8x8_t test_vcltz_s8(int8x8_t a) {
return vcltz_s8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vcltz_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vcltz_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[TMP2:%.*]] = icmp slt <4 x i16> [[TMP1]], zeroinitializer
-// CHECK: [[VCLTZ_I:%.*]] = sext <4 x i1> [[TMP2]] to <4 x i16>
+// CHECK: [[TMP1:%.*]] = icmp slt <4 x i16> %a, zeroinitializer
+// CHECK: [[VCLTZ_I:%.*]] = sext <4 x i1> [[TMP1]] to <4 x i16>
// CHECK: ret <4 x i16> [[VCLTZ_I]]
uint16x4_t test_vcltz_s16(int16x4_t a) {
return vcltz_s16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vcltz_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vcltz_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[TMP2:%.*]] = icmp slt <2 x i32> [[TMP1]], zeroinitializer
-// CHECK: [[VCLTZ_I:%.*]] = sext <2 x i1> [[TMP2]] to <2 x i32>
+// CHECK: [[TMP1:%.*]] = icmp slt <2 x i32> %a, zeroinitializer
+// CHECK: [[VCLTZ_I:%.*]] = sext <2 x i1> [[TMP1]] to <2 x i32>
// CHECK: ret <2 x i32> [[VCLTZ_I]]
uint32x2_t test_vcltz_s32(int32x2_t a) {
return vcltz_s32(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vcltz_s64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vcltz_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
-// CHECK: [[TMP2:%.*]] = icmp slt <1 x i64> [[TMP1]], zeroinitializer
-// CHECK: [[VCLTZ_I:%.*]] = sext <1 x i1> [[TMP2]] to <1 x i64>
+// CHECK: [[TMP1:%.*]] = icmp slt <1 x i64> %a, zeroinitializer
+// CHECK: [[VCLTZ_I:%.*]] = sext <1 x i1> [[TMP1]] to <1 x i64>
// CHECK: ret <1 x i64> [[VCLTZ_I]]
uint64x1_t test_vcltz_s64(int64x1_t a) {
return vcltz_s64(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vcltzq_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vcltzq_s8(
// CHECK: [[TMP0:%.*]] = icmp slt <16 x i8> %a, zeroinitializer
// CHECK: [[VCLTZ_I:%.*]] = sext <16 x i1> [[TMP0]] to <16 x i8>
// CHECK: ret <16 x i8> [[VCLTZ_I]]
@@ -648,1593 +595,1454 @@ uint8x16_t test_vcltzq_s8(int8x16_t a) {
return vcltzq_s8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vcltzq_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vcltzq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[TMP2:%.*]] = icmp slt <8 x i16> [[TMP1]], zeroinitializer
-// CHECK: [[VCLTZ_I:%.*]] = sext <8 x i1> [[TMP2]] to <8 x i16>
+// CHECK: [[TMP1:%.*]] = icmp slt <8 x i16> %a, zeroinitializer
+// CHECK: [[VCLTZ_I:%.*]] = sext <8 x i1> [[TMP1]] to <8 x i16>
// CHECK: ret <8 x i16> [[VCLTZ_I]]
uint16x8_t test_vcltzq_s16(int16x8_t a) {
return vcltzq_s16(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vcltzq_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vcltzq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[TMP2:%.*]] = icmp slt <4 x i32> [[TMP1]], zeroinitializer
-// CHECK: [[VCLTZ_I:%.*]] = sext <4 x i1> [[TMP2]] to <4 x i32>
+// CHECK: [[TMP1:%.*]] = icmp slt <4 x i32> %a, zeroinitializer
+// CHECK: [[VCLTZ_I:%.*]] = sext <4 x i1> [[TMP1]] to <4 x i32>
// CHECK: ret <4 x i32> [[VCLTZ_I]]
uint32x4_t test_vcltzq_s32(int32x4_t a) {
return vcltzq_s32(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vcltzq_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vcltzq_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[TMP2:%.*]] = icmp slt <2 x i64> [[TMP1]], zeroinitializer
-// CHECK: [[VCLTZ_I:%.*]] = sext <2 x i1> [[TMP2]] to <2 x i64>
+// CHECK: [[TMP1:%.*]] = icmp slt <2 x i64> %a, zeroinitializer
+// CHECK: [[VCLTZ_I:%.*]] = sext <2 x i1> [[TMP1]] to <2 x i64>
// CHECK: ret <2 x i64> [[VCLTZ_I]]
uint64x2_t test_vcltzq_s64(int64x2_t a) {
return vcltzq_s64(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vcltz_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vcltz_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[TMP2:%.*]] = fcmp olt <2 x float> [[TMP1]], zeroinitializer
-// CHECK: [[VCLTZ_I:%.*]] = sext <2 x i1> [[TMP2]] to <2 x i32>
+// CHECK: [[TMP1:%.*]] = fcmp olt <2 x float> %a, zeroinitializer
+// CHECK: [[VCLTZ_I:%.*]] = sext <2 x i1> [[TMP1]] to <2 x i32>
// CHECK: ret <2 x i32> [[VCLTZ_I]]
uint32x2_t test_vcltz_f32(float32x2_t a) {
return vcltz_f32(a);
}
-
-// CHECK-LABEL: define <1 x i64> @test_vcltz_f64(<1 x double> %a) #0 {
+
+// CHECK-LABEL: @test_vcltz_f64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x double>
-// CHECK: [[TMP2:%.*]] = fcmp olt <1 x double> [[TMP1]], zeroinitializer
-// CHECK: [[VCLTZ_I:%.*]] = sext <1 x i1> [[TMP2]] to <1 x i64>
+// CHECK: [[TMP1:%.*]] = fcmp olt <1 x double> %a, zeroinitializer
+// CHECK: [[VCLTZ_I:%.*]] = sext <1 x i1> [[TMP1]] to <1 x i64>
// CHECK: ret <1 x i64> [[VCLTZ_I]]
uint64x1_t test_vcltz_f64(float64x1_t a) {
return vcltz_f64(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vcltzq_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vcltzq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[TMP2:%.*]] = fcmp olt <4 x float> [[TMP1]], zeroinitializer
-// CHECK: [[VCLTZ_I:%.*]] = sext <4 x i1> [[TMP2]] to <4 x i32>
+// CHECK: [[TMP1:%.*]] = fcmp olt <4 x float> %a, zeroinitializer
+// CHECK: [[VCLTZ_I:%.*]] = sext <4 x i1> [[TMP1]] to <4 x i32>
// CHECK: ret <4 x i32> [[VCLTZ_I]]
uint32x4_t test_vcltzq_f32(float32x4_t a) {
return vcltzq_f32(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vcltzq_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vcltzq_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[TMP2:%.*]] = fcmp olt <2 x double> [[TMP1]], zeroinitializer
-// CHECK: [[VCLTZ_I:%.*]] = sext <2 x i1> [[TMP2]] to <2 x i64>
+// CHECK: [[TMP1:%.*]] = fcmp olt <2 x double> %a, zeroinitializer
+// CHECK: [[VCLTZ_I:%.*]] = sext <2 x i1> [[TMP1]] to <2 x i64>
// CHECK: ret <2 x i64> [[VCLTZ_I]]
uint64x2_t test_vcltzq_f64(float64x2_t a) {
return vcltzq_f64(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vrev16_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrev16_s8(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %a, <8 x i32> <i32 1, i32 0, i32 3, i32 2, i32 5, i32 4, i32 7, i32 6>
// CHECK: ret <8 x i8> [[SHUFFLE_I]]
int8x8_t test_vrev16_s8(int8x8_t a) {
return vrev16_s8(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vrev16_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrev16_u8(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %a, <8 x i32> <i32 1, i32 0, i32 3, i32 2, i32 5, i32 4, i32 7, i32 6>
// CHECK: ret <8 x i8> [[SHUFFLE_I]]
uint8x8_t test_vrev16_u8(uint8x8_t a) {
return vrev16_u8(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vrev16_p8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrev16_p8(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %a, <8 x i32> <i32 1, i32 0, i32 3, i32 2, i32 5, i32 4, i32 7, i32 6>
// CHECK: ret <8 x i8> [[SHUFFLE_I]]
poly8x8_t test_vrev16_p8(poly8x8_t a) {
return vrev16_p8(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vrev16q_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrev16q_s8(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %a, <16 x i32> <i32 1, i32 0, i32 3, i32 2, i32 5, i32 4, i32 7, i32 6, i32 9, i32 8, i32 11, i32 10, i32 13, i32 12, i32 15, i32 14>
// CHECK: ret <16 x i8> [[SHUFFLE_I]]
int8x16_t test_vrev16q_s8(int8x16_t a) {
return vrev16q_s8(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vrev16q_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrev16q_u8(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %a, <16 x i32> <i32 1, i32 0, i32 3, i32 2, i32 5, i32 4, i32 7, i32 6, i32 9, i32 8, i32 11, i32 10, i32 13, i32 12, i32 15, i32 14>
// CHECK: ret <16 x i8> [[SHUFFLE_I]]
uint8x16_t test_vrev16q_u8(uint8x16_t a) {
return vrev16q_u8(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vrev16q_p8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrev16q_p8(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %a, <16 x i32> <i32 1, i32 0, i32 3, i32 2, i32 5, i32 4, i32 7, i32 6, i32 9, i32 8, i32 11, i32 10, i32 13, i32 12, i32 15, i32 14>
// CHECK: ret <16 x i8> [[SHUFFLE_I]]
poly8x16_t test_vrev16q_p8(poly8x16_t a) {
return vrev16q_p8(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vrev32_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrev32_s8(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %a, <8 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4>
// CHECK: ret <8 x i8> [[SHUFFLE_I]]
int8x8_t test_vrev32_s8(int8x8_t a) {
return vrev32_s8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vrev32_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vrev32_s16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %a, <4 x i32> <i32 1, i32 0, i32 3, i32 2>
// CHECK: ret <4 x i16> [[SHUFFLE_I]]
int16x4_t test_vrev32_s16(int16x4_t a) {
return vrev32_s16(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vrev32_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrev32_u8(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %a, <8 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4>
// CHECK: ret <8 x i8> [[SHUFFLE_I]]
uint8x8_t test_vrev32_u8(uint8x8_t a) {
return vrev32_u8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vrev32_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vrev32_u16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %a, <4 x i32> <i32 1, i32 0, i32 3, i32 2>
// CHECK: ret <4 x i16> [[SHUFFLE_I]]
uint16x4_t test_vrev32_u16(uint16x4_t a) {
return vrev32_u16(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vrev32_p8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrev32_p8(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %a, <8 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4>
// CHECK: ret <8 x i8> [[SHUFFLE_I]]
poly8x8_t test_vrev32_p8(poly8x8_t a) {
return vrev32_p8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vrev32_p16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vrev32_p16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %a, <4 x i32> <i32 1, i32 0, i32 3, i32 2>
// CHECK: ret <4 x i16> [[SHUFFLE_I]]
poly16x4_t test_vrev32_p16(poly16x4_t a) {
return vrev32_p16(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vrev32q_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrev32q_s8(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %a, <16 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4, i32 11, i32 10, i32 9, i32 8, i32 15, i32 14, i32 13, i32 12>
// CHECK: ret <16 x i8> [[SHUFFLE_I]]
int8x16_t test_vrev32q_s8(int8x16_t a) {
return vrev32q_s8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vrev32q_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vrev32q_s16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %a, <8 x i32> <i32 1, i32 0, i32 3, i32 2, i32 5, i32 4, i32 7, i32 6>
// CHECK: ret <8 x i16> [[SHUFFLE_I]]
int16x8_t test_vrev32q_s16(int16x8_t a) {
return vrev32q_s16(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vrev32q_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrev32q_u8(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %a, <16 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4, i32 11, i32 10, i32 9, i32 8, i32 15, i32 14, i32 13, i32 12>
// CHECK: ret <16 x i8> [[SHUFFLE_I]]
uint8x16_t test_vrev32q_u8(uint8x16_t a) {
return vrev32q_u8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vrev32q_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vrev32q_u16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %a, <8 x i32> <i32 1, i32 0, i32 3, i32 2, i32 5, i32 4, i32 7, i32 6>
// CHECK: ret <8 x i16> [[SHUFFLE_I]]
uint16x8_t test_vrev32q_u16(uint16x8_t a) {
return vrev32q_u16(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vrev32q_p8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrev32q_p8(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %a, <16 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4, i32 11, i32 10, i32 9, i32 8, i32 15, i32 14, i32 13, i32 12>
// CHECK: ret <16 x i8> [[SHUFFLE_I]]
poly8x16_t test_vrev32q_p8(poly8x16_t a) {
return vrev32q_p8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vrev32q_p16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vrev32q_p16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %a, <8 x i32> <i32 1, i32 0, i32 3, i32 2, i32 5, i32 4, i32 7, i32 6>
// CHECK: ret <8 x i16> [[SHUFFLE_I]]
poly16x8_t test_vrev32q_p16(poly16x8_t a) {
return vrev32q_p16(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vrev64_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrev64_s8(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %a, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
// CHECK: ret <8 x i8> [[SHUFFLE_I]]
int8x8_t test_vrev64_s8(int8x8_t a) {
return vrev64_s8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vrev64_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vrev64_s16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %a, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
// CHECK: ret <4 x i16> [[SHUFFLE_I]]
int16x4_t test_vrev64_s16(int16x4_t a) {
return vrev64_s16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vrev64_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vrev64_s32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %a, <2 x i32> <i32 1, i32 0>
// CHECK: ret <2 x i32> [[SHUFFLE_I]]
int32x2_t test_vrev64_s32(int32x2_t a) {
return vrev64_s32(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vrev64_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrev64_u8(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %a, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
// CHECK: ret <8 x i8> [[SHUFFLE_I]]
uint8x8_t test_vrev64_u8(uint8x8_t a) {
return vrev64_u8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vrev64_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vrev64_u16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %a, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
// CHECK: ret <4 x i16> [[SHUFFLE_I]]
uint16x4_t test_vrev64_u16(uint16x4_t a) {
return vrev64_u16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vrev64_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vrev64_u32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %a, <2 x i32> <i32 1, i32 0>
// CHECK: ret <2 x i32> [[SHUFFLE_I]]
uint32x2_t test_vrev64_u32(uint32x2_t a) {
return vrev64_u32(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vrev64_p8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrev64_p8(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %a, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
// CHECK: ret <8 x i8> [[SHUFFLE_I]]
poly8x8_t test_vrev64_p8(poly8x8_t a) {
return vrev64_p8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vrev64_p16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vrev64_p16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %a, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
// CHECK: ret <4 x i16> [[SHUFFLE_I]]
poly16x4_t test_vrev64_p16(poly16x4_t a) {
return vrev64_p16(a);
}
-// CHECK-LABEL: define <2 x float> @test_vrev64_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vrev64_f32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x float> %a, <2 x float> %a, <2 x i32> <i32 1, i32 0>
// CHECK: ret <2 x float> [[SHUFFLE_I]]
float32x2_t test_vrev64_f32(float32x2_t a) {
return vrev64_f32(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vrev64q_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrev64q_s8(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %a, <16 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0, i32 15, i32 14, i32 13, i32 12, i32 11, i32 10, i32 9, i32 8>
// CHECK: ret <16 x i8> [[SHUFFLE_I]]
int8x16_t test_vrev64q_s8(int8x16_t a) {
return vrev64q_s8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vrev64q_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vrev64q_s16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %a, <8 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4>
// CHECK: ret <8 x i16> [[SHUFFLE_I]]
int16x8_t test_vrev64q_s16(int16x8_t a) {
return vrev64q_s16(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vrev64q_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vrev64q_s32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %a, <4 x i32> <i32 1, i32 0, i32 3, i32 2>
// CHECK: ret <4 x i32> [[SHUFFLE_I]]
int32x4_t test_vrev64q_s32(int32x4_t a) {
return vrev64q_s32(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vrev64q_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrev64q_u8(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %a, <16 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0, i32 15, i32 14, i32 13, i32 12, i32 11, i32 10, i32 9, i32 8>
// CHECK: ret <16 x i8> [[SHUFFLE_I]]
uint8x16_t test_vrev64q_u8(uint8x16_t a) {
return vrev64q_u8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vrev64q_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vrev64q_u16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %a, <8 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4>
// CHECK: ret <8 x i16> [[SHUFFLE_I]]
uint16x8_t test_vrev64q_u16(uint16x8_t a) {
return vrev64q_u16(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vrev64q_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vrev64q_u32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %a, <4 x i32> <i32 1, i32 0, i32 3, i32 2>
// CHECK: ret <4 x i32> [[SHUFFLE_I]]
uint32x4_t test_vrev64q_u32(uint32x4_t a) {
return vrev64q_u32(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vrev64q_p8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrev64q_p8(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %a, <16 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0, i32 15, i32 14, i32 13, i32 12, i32 11, i32 10, i32 9, i32 8>
// CHECK: ret <16 x i8> [[SHUFFLE_I]]
poly8x16_t test_vrev64q_p8(poly8x16_t a) {
return vrev64q_p8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vrev64q_p16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vrev64q_p16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %a, <8 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4>
// CHECK: ret <8 x i16> [[SHUFFLE_I]]
poly16x8_t test_vrev64q_p16(poly16x8_t a) {
return vrev64q_p16(a);
}
-// CHECK-LABEL: define <4 x float> @test_vrev64q_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vrev64q_f32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x float> %a, <4 x float> %a, <4 x i32> <i32 1, i32 0, i32 3, i32 2>
// CHECK: ret <4 x float> [[SHUFFLE_I]]
float32x4_t test_vrev64q_f32(float32x4_t a) {
return vrev64q_f32(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vpaddl_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vpaddl_s8(
// CHECK: [[VPADDL_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.saddlp.v4i16.v8i8(<8 x i8> %a) #2
// CHECK: ret <4 x i16> [[VPADDL_I]]
int16x4_t test_vpaddl_s8(int8x8_t a) {
return vpaddl_s8(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vpaddl_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vpaddl_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
-// CHECK: [[VPADDL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VPADDL1_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.saddlp.v2i32.v4i16(<4 x i16> [[VPADDL_I]]) #2
+// CHECK: [[VPADDL1_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.saddlp.v2i32.v4i16(<4 x i16> %a) #2
// CHECK: ret <2 x i32> [[VPADDL1_I]]
int32x2_t test_vpaddl_s16(int16x4_t a) {
return vpaddl_s16(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vpaddl_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vpaddl_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[VPADDL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VPADDL1_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.saddlp.v1i64.v2i32(<2 x i32> [[VPADDL_I]]) #2
+// CHECK: [[VPADDL1_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.saddlp.v1i64.v2i32(<2 x i32> %a) #2
// CHECK: ret <1 x i64> [[VPADDL1_I]]
int64x1_t test_vpaddl_s32(int32x2_t a) {
return vpaddl_s32(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vpaddl_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vpaddl_u8(
// CHECK: [[VPADDL_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.uaddlp.v4i16.v8i8(<8 x i8> %a) #2
// CHECK: ret <4 x i16> [[VPADDL_I]]
uint16x4_t test_vpaddl_u8(uint8x8_t a) {
return vpaddl_u8(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vpaddl_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vpaddl_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
-// CHECK: [[VPADDL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VPADDL1_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.uaddlp.v2i32.v4i16(<4 x i16> [[VPADDL_I]]) #2
+// CHECK: [[VPADDL1_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.uaddlp.v2i32.v4i16(<4 x i16> %a) #2
// CHECK: ret <2 x i32> [[VPADDL1_I]]
uint32x2_t test_vpaddl_u16(uint16x4_t a) {
return vpaddl_u16(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vpaddl_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vpaddl_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[VPADDL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VPADDL1_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.uaddlp.v1i64.v2i32(<2 x i32> [[VPADDL_I]]) #2
+// CHECK: [[VPADDL1_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.uaddlp.v1i64.v2i32(<2 x i32> %a) #2
// CHECK: ret <1 x i64> [[VPADDL1_I]]
uint64x1_t test_vpaddl_u32(uint32x2_t a) {
return vpaddl_u32(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vpaddlq_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vpaddlq_s8(
// CHECK: [[VPADDL_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.saddlp.v8i16.v16i8(<16 x i8> %a) #2
// CHECK: ret <8 x i16> [[VPADDL_I]]
int16x8_t test_vpaddlq_s8(int8x16_t a) {
return vpaddlq_s8(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vpaddlq_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vpaddlq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
-// CHECK: [[VPADDL_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VPADDL1_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.saddlp.v4i32.v8i16(<8 x i16> [[VPADDL_I]]) #2
+// CHECK: [[VPADDL1_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.saddlp.v4i32.v8i16(<8 x i16> %a) #2
// CHECK: ret <4 x i32> [[VPADDL1_I]]
int32x4_t test_vpaddlq_s16(int16x8_t a) {
return vpaddlq_s16(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vpaddlq_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vpaddlq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
-// CHECK: [[VPADDL_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VPADDL1_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.saddlp.v2i64.v4i32(<4 x i32> [[VPADDL_I]]) #2
+// CHECK: [[VPADDL1_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.saddlp.v2i64.v4i32(<4 x i32> %a) #2
// CHECK: ret <2 x i64> [[VPADDL1_I]]
int64x2_t test_vpaddlq_s32(int32x4_t a) {
return vpaddlq_s32(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vpaddlq_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vpaddlq_u8(
// CHECK: [[VPADDL_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.uaddlp.v8i16.v16i8(<16 x i8> %a) #2
// CHECK: ret <8 x i16> [[VPADDL_I]]
uint16x8_t test_vpaddlq_u8(uint8x16_t a) {
return vpaddlq_u8(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vpaddlq_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vpaddlq_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
-// CHECK: [[VPADDL_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VPADDL1_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.uaddlp.v4i32.v8i16(<8 x i16> [[VPADDL_I]]) #2
+// CHECK: [[VPADDL1_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.uaddlp.v4i32.v8i16(<8 x i16> %a) #2
// CHECK: ret <4 x i32> [[VPADDL1_I]]
uint32x4_t test_vpaddlq_u16(uint16x8_t a) {
return vpaddlq_u16(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vpaddlq_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vpaddlq_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
-// CHECK: [[VPADDL_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VPADDL1_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.uaddlp.v2i64.v4i32(<4 x i32> [[VPADDL_I]]) #2
+// CHECK: [[VPADDL1_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.uaddlp.v2i64.v4i32(<4 x i32> %a) #2
// CHECK: ret <2 x i64> [[VPADDL1_I]]
uint64x2_t test_vpaddlq_u32(uint32x4_t a) {
return vpaddlq_u32(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vpadal_s8(<4 x i16> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vpadal_s8(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[VPADAL_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.saddlp.v4i16.v8i8(<8 x i8> %b) #2
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[TMP2:%.*]] = add <4 x i16> [[VPADAL_I]], [[TMP1]]
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: [[TMP1:%.*]] = add <4 x i16> [[VPADAL_I]], %a
+// CHECK: ret <4 x i16> [[TMP1]]
int16x4_t test_vpadal_s8(int16x4_t a, int8x8_t b) {
return vpadal_s8(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vpadal_s16(<2 x i32> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vpadal_s16(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VPADAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VPADAL1_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.saddlp.v2i32.v4i16(<4 x i16> [[VPADAL_I]]) #2
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[TMP3:%.*]] = add <2 x i32> [[VPADAL1_I]], [[TMP2]]
-// CHECK: ret <2 x i32> [[TMP3]]
+// CHECK: [[VPADAL1_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.saddlp.v2i32.v4i16(<4 x i16> %b) #2
+// CHECK: [[TMP2:%.*]] = add <2 x i32> [[VPADAL1_I]], %a
+// CHECK: ret <2 x i32> [[TMP2]]
int32x2_t test_vpadal_s16(int32x2_t a, int16x4_t b) {
return vpadal_s16(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vpadal_s32(<1 x i64> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vpadal_s32(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VPADAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VPADAL1_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.saddlp.v1i64.v2i32(<2 x i32> [[VPADAL_I]]) #2
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
-// CHECK: [[TMP3:%.*]] = add <1 x i64> [[VPADAL1_I]], [[TMP2]]
-// CHECK: ret <1 x i64> [[TMP3]]
+// CHECK: [[VPADAL1_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.saddlp.v1i64.v2i32(<2 x i32> %b) #2
+// CHECK: [[TMP2:%.*]] = add <1 x i64> [[VPADAL1_I]], %a
+// CHECK: ret <1 x i64> [[TMP2]]
int64x1_t test_vpadal_s32(int64x1_t a, int32x2_t b) {
return vpadal_s32(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vpadal_u8(<4 x i16> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vpadal_u8(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[VPADAL_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.uaddlp.v4i16.v8i8(<8 x i8> %b) #2
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[TMP2:%.*]] = add <4 x i16> [[VPADAL_I]], [[TMP1]]
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: [[TMP1:%.*]] = add <4 x i16> [[VPADAL_I]], %a
+// CHECK: ret <4 x i16> [[TMP1]]
uint16x4_t test_vpadal_u8(uint16x4_t a, uint8x8_t b) {
return vpadal_u8(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vpadal_u16(<2 x i32> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vpadal_u16(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VPADAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VPADAL1_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.uaddlp.v2i32.v4i16(<4 x i16> [[VPADAL_I]]) #2
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[TMP3:%.*]] = add <2 x i32> [[VPADAL1_I]], [[TMP2]]
-// CHECK: ret <2 x i32> [[TMP3]]
+// CHECK: [[VPADAL1_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.uaddlp.v2i32.v4i16(<4 x i16> %b) #2
+// CHECK: [[TMP2:%.*]] = add <2 x i32> [[VPADAL1_I]], %a
+// CHECK: ret <2 x i32> [[TMP2]]
uint32x2_t test_vpadal_u16(uint32x2_t a, uint16x4_t b) {
return vpadal_u16(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vpadal_u32(<1 x i64> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vpadal_u32(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VPADAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VPADAL1_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.uaddlp.v1i64.v2i32(<2 x i32> [[VPADAL_I]]) #2
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
-// CHECK: [[TMP3:%.*]] = add <1 x i64> [[VPADAL1_I]], [[TMP2]]
-// CHECK: ret <1 x i64> [[TMP3]]
+// CHECK: [[VPADAL1_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.uaddlp.v1i64.v2i32(<2 x i32> %b) #2
+// CHECK: [[TMP2:%.*]] = add <1 x i64> [[VPADAL1_I]], %a
+// CHECK: ret <1 x i64> [[TMP2]]
uint64x1_t test_vpadal_u32(uint64x1_t a, uint32x2_t b) {
return vpadal_u32(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vpadalq_s8(<8 x i16> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vpadalq_s8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[VPADAL_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.saddlp.v8i16.v16i8(<16 x i8> %b) #2
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[TMP2:%.*]] = add <8 x i16> [[VPADAL_I]], [[TMP1]]
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: [[TMP1:%.*]] = add <8 x i16> [[VPADAL_I]], %a
+// CHECK: ret <8 x i16> [[TMP1]]
int16x8_t test_vpadalq_s8(int16x8_t a, int8x16_t b) {
return vpadalq_s8(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vpadalq_s16(<4 x i32> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vpadalq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VPADAL_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VPADAL1_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.saddlp.v4i32.v8i16(<8 x i16> [[VPADAL_I]]) #2
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[TMP3:%.*]] = add <4 x i32> [[VPADAL1_I]], [[TMP2]]
-// CHECK: ret <4 x i32> [[TMP3]]
+// CHECK: [[VPADAL1_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.saddlp.v4i32.v8i16(<8 x i16> %b) #2
+// CHECK: [[TMP2:%.*]] = add <4 x i32> [[VPADAL1_I]], %a
+// CHECK: ret <4 x i32> [[TMP2]]
int32x4_t test_vpadalq_s16(int32x4_t a, int16x8_t b) {
return vpadalq_s16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vpadalq_s32(<2 x i64> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vpadalq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VPADAL_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VPADAL1_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.saddlp.v2i64.v4i32(<4 x i32> [[VPADAL_I]]) #2
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[TMP3:%.*]] = add <2 x i64> [[VPADAL1_I]], [[TMP2]]
-// CHECK: ret <2 x i64> [[TMP3]]
+// CHECK: [[VPADAL1_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.saddlp.v2i64.v4i32(<4 x i32> %b) #2
+// CHECK: [[TMP2:%.*]] = add <2 x i64> [[VPADAL1_I]], %a
+// CHECK: ret <2 x i64> [[TMP2]]
int64x2_t test_vpadalq_s32(int64x2_t a, int32x4_t b) {
return vpadalq_s32(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vpadalq_u8(<8 x i16> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vpadalq_u8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[VPADAL_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.uaddlp.v8i16.v16i8(<16 x i8> %b) #2
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[TMP2:%.*]] = add <8 x i16> [[VPADAL_I]], [[TMP1]]
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: [[TMP1:%.*]] = add <8 x i16> [[VPADAL_I]], %a
+// CHECK: ret <8 x i16> [[TMP1]]
uint16x8_t test_vpadalq_u8(uint16x8_t a, uint8x16_t b) {
return vpadalq_u8(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vpadalq_u16(<4 x i32> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vpadalq_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VPADAL_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VPADAL1_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.uaddlp.v4i32.v8i16(<8 x i16> [[VPADAL_I]]) #2
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[TMP3:%.*]] = add <4 x i32> [[VPADAL1_I]], [[TMP2]]
-// CHECK: ret <4 x i32> [[TMP3]]
+// CHECK: [[VPADAL1_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.uaddlp.v4i32.v8i16(<8 x i16> %b) #2
+// CHECK: [[TMP2:%.*]] = add <4 x i32> [[VPADAL1_I]], %a
+// CHECK: ret <4 x i32> [[TMP2]]
uint32x4_t test_vpadalq_u16(uint32x4_t a, uint16x8_t b) {
return vpadalq_u16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vpadalq_u32(<2 x i64> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vpadalq_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VPADAL_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VPADAL1_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.uaddlp.v2i64.v4i32(<4 x i32> [[VPADAL_I]]) #2
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[TMP3:%.*]] = add <2 x i64> [[VPADAL1_I]], [[TMP2]]
-// CHECK: ret <2 x i64> [[TMP3]]
+// CHECK: [[VPADAL1_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.uaddlp.v2i64.v4i32(<4 x i32> %b) #2
+// CHECK: [[TMP2:%.*]] = add <2 x i64> [[VPADAL1_I]], %a
+// CHECK: ret <2 x i64> [[TMP2]]
uint64x2_t test_vpadalq_u32(uint64x2_t a, uint32x4_t b) {
return vpadalq_u32(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vqabs_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vqabs_s8(
// CHECK: [[VQABS_V_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.sqabs.v8i8(<8 x i8> %a) #2
// CHECK: ret <8 x i8> [[VQABS_V_I]]
int8x8_t test_vqabs_s8(int8x8_t a) {
return vqabs_s8(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vqabsq_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vqabsq_s8(
// CHECK: [[VQABSQ_V_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.sqabs.v16i8(<16 x i8> %a) #2
// CHECK: ret <16 x i8> [[VQABSQ_V_I]]
int8x16_t test_vqabsq_s8(int8x16_t a) {
return vqabsq_s8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vqabs_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vqabs_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
-// CHECK: [[VQABS_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQABS_V1_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqabs.v4i16(<4 x i16> [[VQABS_V_I]]) #2
+// CHECK: [[VQABS_V1_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqabs.v4i16(<4 x i16> %a) #2
// CHECK: [[VQABS_V2_I:%.*]] = bitcast <4 x i16> [[VQABS_V1_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[VQABS_V2_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP1]]
+// CHECK: ret <4 x i16> [[VQABS_V1_I]]
int16x4_t test_vqabs_s16(int16x4_t a) {
return vqabs_s16(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vqabsq_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vqabsq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
-// CHECK: [[VQABSQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VQABSQ_V1_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.sqabs.v8i16(<8 x i16> [[VQABSQ_V_I]]) #2
+// CHECK: [[VQABSQ_V1_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.sqabs.v8i16(<8 x i16> %a) #2
// CHECK: [[VQABSQ_V2_I:%.*]] = bitcast <8 x i16> [[VQABSQ_V1_I]] to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[VQABSQ_V2_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP1]]
+// CHECK: ret <8 x i16> [[VQABSQ_V1_I]]
int16x8_t test_vqabsq_s16(int16x8_t a) {
return vqabsq_s16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vqabs_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vqabs_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[VQABS_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQABS_V1_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqabs.v2i32(<2 x i32> [[VQABS_V_I]]) #2
+// CHECK: [[VQABS_V1_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqabs.v2i32(<2 x i32> %a) #2
// CHECK: [[VQABS_V2_I:%.*]] = bitcast <2 x i32> [[VQABS_V1_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[VQABS_V2_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP1]]
+// CHECK: ret <2 x i32> [[VQABS_V1_I]]
int32x2_t test_vqabs_s32(int32x2_t a) {
return vqabs_s32(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vqabsq_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vqabsq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
-// CHECK: [[VQABSQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQABSQ_V1_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqabs.v4i32(<4 x i32> [[VQABSQ_V_I]]) #2
+// CHECK: [[VQABSQ_V1_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqabs.v4i32(<4 x i32> %a) #2
// CHECK: [[VQABSQ_V2_I:%.*]] = bitcast <4 x i32> [[VQABSQ_V1_I]] to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[VQABSQ_V2_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP1]]
+// CHECK: ret <4 x i32> [[VQABSQ_V1_I]]
int32x4_t test_vqabsq_s32(int32x4_t a) {
return vqabsq_s32(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vqabsq_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vqabsq_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
-// CHECK: [[VQABSQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQABSQ_V1_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqabs.v2i64(<2 x i64> [[VQABSQ_V_I]]) #2
+// CHECK: [[VQABSQ_V1_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqabs.v2i64(<2 x i64> %a) #2
// CHECK: [[VQABSQ_V2_I:%.*]] = bitcast <2 x i64> [[VQABSQ_V1_I]] to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[VQABSQ_V2_I]] to <2 x i64>
-// CHECK: ret <2 x i64> [[TMP1]]
+// CHECK: ret <2 x i64> [[VQABSQ_V1_I]]
int64x2_t test_vqabsq_s64(int64x2_t a) {
return vqabsq_s64(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vqneg_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vqneg_s8(
// CHECK: [[VQNEG_V_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.sqneg.v8i8(<8 x i8> %a) #2
// CHECK: ret <8 x i8> [[VQNEG_V_I]]
int8x8_t test_vqneg_s8(int8x8_t a) {
return vqneg_s8(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vqnegq_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vqnegq_s8(
// CHECK: [[VQNEGQ_V_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.sqneg.v16i8(<16 x i8> %a) #2
// CHECK: ret <16 x i8> [[VQNEGQ_V_I]]
int8x16_t test_vqnegq_s8(int8x16_t a) {
return vqnegq_s8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vqneg_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vqneg_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
-// CHECK: [[VQNEG_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQNEG_V1_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqneg.v4i16(<4 x i16> [[VQNEG_V_I]]) #2
+// CHECK: [[VQNEG_V1_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqneg.v4i16(<4 x i16> %a) #2
// CHECK: [[VQNEG_V2_I:%.*]] = bitcast <4 x i16> [[VQNEG_V1_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[VQNEG_V2_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP1]]
+// CHECK: ret <4 x i16> [[VQNEG_V1_I]]
int16x4_t test_vqneg_s16(int16x4_t a) {
return vqneg_s16(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vqnegq_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vqnegq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
-// CHECK: [[VQNEGQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VQNEGQ_V1_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.sqneg.v8i16(<8 x i16> [[VQNEGQ_V_I]]) #2
+// CHECK: [[VQNEGQ_V1_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.sqneg.v8i16(<8 x i16> %a) #2
// CHECK: [[VQNEGQ_V2_I:%.*]] = bitcast <8 x i16> [[VQNEGQ_V1_I]] to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[VQNEGQ_V2_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP1]]
+// CHECK: ret <8 x i16> [[VQNEGQ_V1_I]]
int16x8_t test_vqnegq_s16(int16x8_t a) {
return vqnegq_s16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vqneg_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vqneg_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[VQNEG_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQNEG_V1_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqneg.v2i32(<2 x i32> [[VQNEG_V_I]]) #2
+// CHECK: [[VQNEG_V1_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqneg.v2i32(<2 x i32> %a) #2
// CHECK: [[VQNEG_V2_I:%.*]] = bitcast <2 x i32> [[VQNEG_V1_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[VQNEG_V2_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP1]]
+// CHECK: ret <2 x i32> [[VQNEG_V1_I]]
int32x2_t test_vqneg_s32(int32x2_t a) {
return vqneg_s32(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vqnegq_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vqnegq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
-// CHECK: [[VQNEGQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQNEGQ_V1_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqneg.v4i32(<4 x i32> [[VQNEGQ_V_I]]) #2
+// CHECK: [[VQNEGQ_V1_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.sqneg.v4i32(<4 x i32> %a) #2
// CHECK: [[VQNEGQ_V2_I:%.*]] = bitcast <4 x i32> [[VQNEGQ_V1_I]] to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[VQNEGQ_V2_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP1]]
+// CHECK: ret <4 x i32> [[VQNEGQ_V1_I]]
int32x4_t test_vqnegq_s32(int32x4_t a) {
return vqnegq_s32(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vqnegq_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vqnegq_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
-// CHECK: [[VQNEGQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQNEGQ_V1_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqneg.v2i64(<2 x i64> [[VQNEGQ_V_I]]) #2
+// CHECK: [[VQNEGQ_V1_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.sqneg.v2i64(<2 x i64> %a) #2
// CHECK: [[VQNEGQ_V2_I:%.*]] = bitcast <2 x i64> [[VQNEGQ_V1_I]] to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[VQNEGQ_V2_I]] to <2 x i64>
-// CHECK: ret <2 x i64> [[TMP1]]
+// CHECK: ret <2 x i64> [[VQNEGQ_V1_I]]
int64x2_t test_vqnegq_s64(int64x2_t a) {
return vqnegq_s64(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vneg_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vneg_s8(
// CHECK: [[SUB_I:%.*]] = sub <8 x i8> zeroinitializer, %a
// CHECK: ret <8 x i8> [[SUB_I]]
int8x8_t test_vneg_s8(int8x8_t a) {
return vneg_s8(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vnegq_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vnegq_s8(
// CHECK: [[SUB_I:%.*]] = sub <16 x i8> zeroinitializer, %a
// CHECK: ret <16 x i8> [[SUB_I]]
int8x16_t test_vnegq_s8(int8x16_t a) {
return vnegq_s8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vneg_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vneg_s16(
// CHECK: [[SUB_I:%.*]] = sub <4 x i16> zeroinitializer, %a
// CHECK: ret <4 x i16> [[SUB_I]]
int16x4_t test_vneg_s16(int16x4_t a) {
return vneg_s16(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vnegq_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vnegq_s16(
// CHECK: [[SUB_I:%.*]] = sub <8 x i16> zeroinitializer, %a
// CHECK: ret <8 x i16> [[SUB_I]]
int16x8_t test_vnegq_s16(int16x8_t a) {
return vnegq_s16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vneg_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vneg_s32(
// CHECK: [[SUB_I:%.*]] = sub <2 x i32> zeroinitializer, %a
// CHECK: ret <2 x i32> [[SUB_I]]
int32x2_t test_vneg_s32(int32x2_t a) {
return vneg_s32(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vnegq_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vnegq_s32(
// CHECK: [[SUB_I:%.*]] = sub <4 x i32> zeroinitializer, %a
// CHECK: ret <4 x i32> [[SUB_I]]
int32x4_t test_vnegq_s32(int32x4_t a) {
return vnegq_s32(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vnegq_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vnegq_s64(
// CHECK: [[SUB_I:%.*]] = sub <2 x i64> zeroinitializer, %a
// CHECK: ret <2 x i64> [[SUB_I]]
int64x2_t test_vnegq_s64(int64x2_t a) {
return vnegq_s64(a);
}
-// CHECK-LABEL: define <2 x float> @test_vneg_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vneg_f32(
// CHECK: [[SUB_I:%.*]] = fsub <2 x float> <float -0.000000e+00, float -0.000000e+00>, %a
// CHECK: ret <2 x float> [[SUB_I]]
float32x2_t test_vneg_f32(float32x2_t a) {
return vneg_f32(a);
}
-// CHECK-LABEL: define <4 x float> @test_vnegq_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vnegq_f32(
// CHECK: [[SUB_I:%.*]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %a
// CHECK: ret <4 x float> [[SUB_I]]
float32x4_t test_vnegq_f32(float32x4_t a) {
return vnegq_f32(a);
}
-// CHECK-LABEL: define <2 x double> @test_vnegq_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vnegq_f64(
// CHECK: [[SUB_I:%.*]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, %a
// CHECK: ret <2 x double> [[SUB_I]]
float64x2_t test_vnegq_f64(float64x2_t a) {
return vnegq_f64(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vabs_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vabs_s8(
// CHECK: [[VABS_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.abs.v8i8(<8 x i8> %a) #2
// CHECK: ret <8 x i8> [[VABS_I]]
int8x8_t test_vabs_s8(int8x8_t a) {
return vabs_s8(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vabsq_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vabsq_s8(
// CHECK: [[VABS_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.abs.v16i8(<16 x i8> %a) #2
// CHECK: ret <16 x i8> [[VABS_I]]
int8x16_t test_vabsq_s8(int8x16_t a) {
return vabsq_s8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vabs_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vabs_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
-// CHECK: [[VABS_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VABS1_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.abs.v4i16(<4 x i16> [[VABS_I]]) #2
+// CHECK: [[VABS1_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.abs.v4i16(<4 x i16> %a) #2
// CHECK: ret <4 x i16> [[VABS1_I]]
int16x4_t test_vabs_s16(int16x4_t a) {
return vabs_s16(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vabsq_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vabsq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
-// CHECK: [[VABS_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VABS1_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.abs.v8i16(<8 x i16> [[VABS_I]]) #2
+// CHECK: [[VABS1_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.abs.v8i16(<8 x i16> %a) #2
// CHECK: ret <8 x i16> [[VABS1_I]]
int16x8_t test_vabsq_s16(int16x8_t a) {
return vabsq_s16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vabs_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vabs_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[VABS_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VABS1_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.abs.v2i32(<2 x i32> [[VABS_I]]) #2
+// CHECK: [[VABS1_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.abs.v2i32(<2 x i32> %a) #2
// CHECK: ret <2 x i32> [[VABS1_I]]
int32x2_t test_vabs_s32(int32x2_t a) {
return vabs_s32(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vabsq_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vabsq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
-// CHECK: [[VABS_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VABS1_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.abs.v4i32(<4 x i32> [[VABS_I]]) #2
+// CHECK: [[VABS1_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.abs.v4i32(<4 x i32> %a) #2
// CHECK: ret <4 x i32> [[VABS1_I]]
int32x4_t test_vabsq_s32(int32x4_t a) {
return vabsq_s32(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vabsq_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vabsq_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
-// CHECK: [[VABS_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VABS1_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.abs.v2i64(<2 x i64> [[VABS_I]]) #2
+// CHECK: [[VABS1_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.abs.v2i64(<2 x i64> %a) #2
// CHECK: ret <2 x i64> [[VABS1_I]]
int64x2_t test_vabsq_s64(int64x2_t a) {
return vabsq_s64(a);
}
-// CHECK-LABEL: define <2 x float> @test_vabs_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vabs_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[VABS_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VABS1_I:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[VABS_I]]) #2
+// CHECK: [[VABS1_I:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> %a) #2
// CHECK: ret <2 x float> [[VABS1_I]]
float32x2_t test_vabs_f32(float32x2_t a) {
return vabs_f32(a);
}
-// CHECK-LABEL: define <4 x float> @test_vabsq_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vabsq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[VABS_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VABS1_I:%.*]] = call <4 x float> @llvm.fabs.v4f32(<4 x float> [[VABS_I]]) #2
+// CHECK: [[VABS1_I:%.*]] = call <4 x float> @llvm.fabs.v4f32(<4 x float> %a) #2
// CHECK: ret <4 x float> [[VABS1_I]]
float32x4_t test_vabsq_f32(float32x4_t a) {
return vabsq_f32(a);
}
-// CHECK-LABEL: define <2 x double> @test_vabsq_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vabsq_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
-// CHECK: [[VABS_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VABS1_I:%.*]] = call <2 x double> @llvm.fabs.v2f64(<2 x double> [[VABS_I]]) #2
+// CHECK: [[VABS1_I:%.*]] = call <2 x double> @llvm.fabs.v2f64(<2 x double> %a) #2
// CHECK: ret <2 x double> [[VABS1_I]]
float64x2_t test_vabsq_f64(float64x2_t a) {
return vabsq_f64(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vuqadd_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vuqadd_s8(
// CHECK: [[VUQADD_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.suqadd.v8i8(<8 x i8> %a, <8 x i8> %b) #2
// CHECK: ret <8 x i8> [[VUQADD_I]]
int8x8_t test_vuqadd_s8(int8x8_t a, int8x8_t b) {
return vuqadd_s8(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vuqaddq_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vuqaddq_s8(
// CHECK: [[VUQADD_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.suqadd.v16i8(<16 x i8> %a, <16 x i8> %b) #2
// CHECK: ret <16 x i8> [[VUQADD_I]]
int8x16_t test_vuqaddq_s8(int8x16_t a, int8x16_t b) {
return vuqaddq_s8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vuqadd_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vuqadd_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VUQADD_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VUQADD1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VUQADD2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.suqadd.v4i16(<4 x i16> [[VUQADD_I]], <4 x i16> [[VUQADD1_I]]) #2
+// CHECK: [[VUQADD2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.suqadd.v4i16(<4 x i16> %a, <4 x i16> %b) #2
// CHECK: ret <4 x i16> [[VUQADD2_I]]
int16x4_t test_vuqadd_s16(int16x4_t a, int16x4_t b) {
return vuqadd_s16(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vuqaddq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vuqaddq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VUQADD_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VUQADD1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VUQADD2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.suqadd.v8i16(<8 x i16> [[VUQADD_I]], <8 x i16> [[VUQADD1_I]]) #2
+// CHECK: [[VUQADD2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.suqadd.v8i16(<8 x i16> %a, <8 x i16> %b) #2
// CHECK: ret <8 x i16> [[VUQADD2_I]]
int16x8_t test_vuqaddq_s16(int16x8_t a, int16x8_t b) {
return vuqaddq_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vuqadd_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vuqadd_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VUQADD_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VUQADD1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VUQADD2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.suqadd.v2i32(<2 x i32> [[VUQADD_I]], <2 x i32> [[VUQADD1_I]]) #2
+// CHECK: [[VUQADD2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.suqadd.v2i32(<2 x i32> %a, <2 x i32> %b) #2
// CHECK: ret <2 x i32> [[VUQADD2_I]]
int32x2_t test_vuqadd_s32(int32x2_t a, int32x2_t b) {
return vuqadd_s32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vuqaddq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vuqaddq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VUQADD_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VUQADD1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VUQADD2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.suqadd.v4i32(<4 x i32> [[VUQADD_I]], <4 x i32> [[VUQADD1_I]]) #2
+// CHECK: [[VUQADD2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.suqadd.v4i32(<4 x i32> %a, <4 x i32> %b) #2
// CHECK: ret <4 x i32> [[VUQADD2_I]]
int32x4_t test_vuqaddq_s32(int32x4_t a, int32x4_t b) {
return vuqaddq_s32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vuqaddq_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vuqaddq_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[VUQADD_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VUQADD1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VUQADD2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.suqadd.v2i64(<2 x i64> [[VUQADD_I]], <2 x i64> [[VUQADD1_I]]) #2
+// CHECK: [[VUQADD2_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.suqadd.v2i64(<2 x i64> %a, <2 x i64> %b) #2
// CHECK: ret <2 x i64> [[VUQADD2_I]]
int64x2_t test_vuqaddq_s64(int64x2_t a, int64x2_t b) {
return vuqaddq_s64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vcls_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vcls_s8(
// CHECK: [[VCLS_V_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.cls.v8i8(<8 x i8> %a) #2
// CHECK: ret <8 x i8> [[VCLS_V_I]]
int8x8_t test_vcls_s8(int8x8_t a) {
return vcls_s8(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vclsq_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vclsq_s8(
// CHECK: [[VCLSQ_V_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.cls.v16i8(<16 x i8> %a) #2
// CHECK: ret <16 x i8> [[VCLSQ_V_I]]
int8x16_t test_vclsq_s8(int8x16_t a) {
return vclsq_s8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vcls_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vcls_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
-// CHECK: [[VCLS_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VCLS_V1_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.cls.v4i16(<4 x i16> [[VCLS_V_I]]) #2
+// CHECK: [[VCLS_V1_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.cls.v4i16(<4 x i16> %a) #2
// CHECK: [[VCLS_V2_I:%.*]] = bitcast <4 x i16> [[VCLS_V1_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[VCLS_V2_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP1]]
+// CHECK: ret <4 x i16> [[VCLS_V1_I]]
int16x4_t test_vcls_s16(int16x4_t a) {
return vcls_s16(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vclsq_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vclsq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
-// CHECK: [[VCLSQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VCLSQ_V1_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.cls.v8i16(<8 x i16> [[VCLSQ_V_I]]) #2
+// CHECK: [[VCLSQ_V1_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.cls.v8i16(<8 x i16> %a) #2
// CHECK: [[VCLSQ_V2_I:%.*]] = bitcast <8 x i16> [[VCLSQ_V1_I]] to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[VCLSQ_V2_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP1]]
+// CHECK: ret <8 x i16> [[VCLSQ_V1_I]]
int16x8_t test_vclsq_s16(int16x8_t a) {
return vclsq_s16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vcls_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vcls_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[VCLS_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VCLS_V1_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.cls.v2i32(<2 x i32> [[VCLS_V_I]]) #2
+// CHECK: [[VCLS_V1_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.cls.v2i32(<2 x i32> %a) #2
// CHECK: [[VCLS_V2_I:%.*]] = bitcast <2 x i32> [[VCLS_V1_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[VCLS_V2_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP1]]
+// CHECK: ret <2 x i32> [[VCLS_V1_I]]
int32x2_t test_vcls_s32(int32x2_t a) {
return vcls_s32(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vclsq_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vclsq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
-// CHECK: [[VCLSQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VCLSQ_V1_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.cls.v4i32(<4 x i32> [[VCLSQ_V_I]]) #2
+// CHECK: [[VCLSQ_V1_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.cls.v4i32(<4 x i32> %a) #2
// CHECK: [[VCLSQ_V2_I:%.*]] = bitcast <4 x i32> [[VCLSQ_V1_I]] to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[VCLSQ_V2_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP1]]
+// CHECK: ret <4 x i32> [[VCLSQ_V1_I]]
int32x4_t test_vclsq_s32(int32x4_t a) {
return vclsq_s32(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vclz_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vclz_s8(
// CHECK: [[VCLZ_V_I:%.*]] = call <8 x i8> @llvm.ctlz.v8i8(<8 x i8> %a, i1 false) #2
// CHECK: ret <8 x i8> [[VCLZ_V_I]]
int8x8_t test_vclz_s8(int8x8_t a) {
return vclz_s8(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vclzq_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vclzq_s8(
// CHECK: [[VCLZQ_V_I:%.*]] = call <16 x i8> @llvm.ctlz.v16i8(<16 x i8> %a, i1 false) #2
// CHECK: ret <16 x i8> [[VCLZQ_V_I]]
int8x16_t test_vclzq_s8(int8x16_t a) {
return vclzq_s8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vclz_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vclz_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
-// CHECK: [[VCLZ_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VCLZ_V1_I:%.*]] = call <4 x i16> @llvm.ctlz.v4i16(<4 x i16> [[VCLZ_V_I]], i1 false) #2
+// CHECK: [[VCLZ_V1_I:%.*]] = call <4 x i16> @llvm.ctlz.v4i16(<4 x i16> %a, i1 false) #2
// CHECK: [[VCLZ_V2_I:%.*]] = bitcast <4 x i16> [[VCLZ_V1_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[VCLZ_V2_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP1]]
+// CHECK: ret <4 x i16> [[VCLZ_V1_I]]
int16x4_t test_vclz_s16(int16x4_t a) {
return vclz_s16(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vclzq_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vclzq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
-// CHECK: [[VCLZQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VCLZQ_V1_I:%.*]] = call <8 x i16> @llvm.ctlz.v8i16(<8 x i16> [[VCLZQ_V_I]], i1 false) #2
+// CHECK: [[VCLZQ_V1_I:%.*]] = call <8 x i16> @llvm.ctlz.v8i16(<8 x i16> %a, i1 false) #2
// CHECK: [[VCLZQ_V2_I:%.*]] = bitcast <8 x i16> [[VCLZQ_V1_I]] to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[VCLZQ_V2_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP1]]
+// CHECK: ret <8 x i16> [[VCLZQ_V1_I]]
int16x8_t test_vclzq_s16(int16x8_t a) {
return vclzq_s16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vclz_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vclz_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[VCLZ_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VCLZ_V1_I:%.*]] = call <2 x i32> @llvm.ctlz.v2i32(<2 x i32> [[VCLZ_V_I]], i1 false) #2
+// CHECK: [[VCLZ_V1_I:%.*]] = call <2 x i32> @llvm.ctlz.v2i32(<2 x i32> %a, i1 false) #2
// CHECK: [[VCLZ_V2_I:%.*]] = bitcast <2 x i32> [[VCLZ_V1_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[VCLZ_V2_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP1]]
+// CHECK: ret <2 x i32> [[VCLZ_V1_I]]
int32x2_t test_vclz_s32(int32x2_t a) {
return vclz_s32(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vclzq_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vclzq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
-// CHECK: [[VCLZQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VCLZQ_V1_I:%.*]] = call <4 x i32> @llvm.ctlz.v4i32(<4 x i32> [[VCLZQ_V_I]], i1 false) #2
+// CHECK: [[VCLZQ_V1_I:%.*]] = call <4 x i32> @llvm.ctlz.v4i32(<4 x i32> %a, i1 false) #2
// CHECK: [[VCLZQ_V2_I:%.*]] = bitcast <4 x i32> [[VCLZQ_V1_I]] to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[VCLZQ_V2_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP1]]
+// CHECK: ret <4 x i32> [[VCLZQ_V1_I]]
int32x4_t test_vclzq_s32(int32x4_t a) {
return vclzq_s32(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vclz_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vclz_u8(
// CHECK: [[VCLZ_V_I:%.*]] = call <8 x i8> @llvm.ctlz.v8i8(<8 x i8> %a, i1 false) #2
// CHECK: ret <8 x i8> [[VCLZ_V_I]]
uint8x8_t test_vclz_u8(uint8x8_t a) {
return vclz_u8(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vclzq_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vclzq_u8(
// CHECK: [[VCLZQ_V_I:%.*]] = call <16 x i8> @llvm.ctlz.v16i8(<16 x i8> %a, i1 false) #2
// CHECK: ret <16 x i8> [[VCLZQ_V_I]]
uint8x16_t test_vclzq_u8(uint8x16_t a) {
return vclzq_u8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vclz_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vclz_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
-// CHECK: [[VCLZ_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VCLZ_V1_I:%.*]] = call <4 x i16> @llvm.ctlz.v4i16(<4 x i16> [[VCLZ_V_I]], i1 false) #2
+// CHECK: [[VCLZ_V1_I:%.*]] = call <4 x i16> @llvm.ctlz.v4i16(<4 x i16> %a, i1 false) #2
// CHECK: [[VCLZ_V2_I:%.*]] = bitcast <4 x i16> [[VCLZ_V1_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[VCLZ_V2_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP1]]
+// CHECK: ret <4 x i16> [[VCLZ_V1_I]]
uint16x4_t test_vclz_u16(uint16x4_t a) {
return vclz_u16(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vclzq_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vclzq_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
-// CHECK: [[VCLZQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VCLZQ_V1_I:%.*]] = call <8 x i16> @llvm.ctlz.v8i16(<8 x i16> [[VCLZQ_V_I]], i1 false) #2
+// CHECK: [[VCLZQ_V1_I:%.*]] = call <8 x i16> @llvm.ctlz.v8i16(<8 x i16> %a, i1 false) #2
// CHECK: [[VCLZQ_V2_I:%.*]] = bitcast <8 x i16> [[VCLZQ_V1_I]] to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[VCLZQ_V2_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP1]]
+// CHECK: ret <8 x i16> [[VCLZQ_V1_I]]
uint16x8_t test_vclzq_u16(uint16x8_t a) {
return vclzq_u16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vclz_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vclz_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[VCLZ_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VCLZ_V1_I:%.*]] = call <2 x i32> @llvm.ctlz.v2i32(<2 x i32> [[VCLZ_V_I]], i1 false) #2
+// CHECK: [[VCLZ_V1_I:%.*]] = call <2 x i32> @llvm.ctlz.v2i32(<2 x i32> %a, i1 false) #2
// CHECK: [[VCLZ_V2_I:%.*]] = bitcast <2 x i32> [[VCLZ_V1_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[VCLZ_V2_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP1]]
+// CHECK: ret <2 x i32> [[VCLZ_V1_I]]
uint32x2_t test_vclz_u32(uint32x2_t a) {
return vclz_u32(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vclzq_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vclzq_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
-// CHECK: [[VCLZQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VCLZQ_V1_I:%.*]] = call <4 x i32> @llvm.ctlz.v4i32(<4 x i32> [[VCLZQ_V_I]], i1 false) #2
+// CHECK: [[VCLZQ_V1_I:%.*]] = call <4 x i32> @llvm.ctlz.v4i32(<4 x i32> %a, i1 false) #2
// CHECK: [[VCLZQ_V2_I:%.*]] = bitcast <4 x i32> [[VCLZQ_V1_I]] to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[VCLZQ_V2_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP1]]
+// CHECK: ret <4 x i32> [[VCLZQ_V1_I]]
uint32x4_t test_vclzq_u32(uint32x4_t a) {
return vclzq_u32(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vcnt_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vcnt_s8(
// CHECK: [[VCNT_V_I:%.*]] = call <8 x i8> @llvm.ctpop.v8i8(<8 x i8> %a) #2
// CHECK: ret <8 x i8> [[VCNT_V_I]]
int8x8_t test_vcnt_s8(int8x8_t a) {
return vcnt_s8(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vcntq_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vcntq_s8(
// CHECK: [[VCNTQ_V_I:%.*]] = call <16 x i8> @llvm.ctpop.v16i8(<16 x i8> %a) #2
// CHECK: ret <16 x i8> [[VCNTQ_V_I]]
int8x16_t test_vcntq_s8(int8x16_t a) {
return vcntq_s8(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vcnt_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vcnt_u8(
// CHECK: [[VCNT_V_I:%.*]] = call <8 x i8> @llvm.ctpop.v8i8(<8 x i8> %a) #2
// CHECK: ret <8 x i8> [[VCNT_V_I]]
uint8x8_t test_vcnt_u8(uint8x8_t a) {
return vcnt_u8(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vcntq_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vcntq_u8(
// CHECK: [[VCNTQ_V_I:%.*]] = call <16 x i8> @llvm.ctpop.v16i8(<16 x i8> %a) #2
// CHECK: ret <16 x i8> [[VCNTQ_V_I]]
uint8x16_t test_vcntq_u8(uint8x16_t a) {
return vcntq_u8(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vcnt_p8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vcnt_p8(
// CHECK: [[VCNT_V_I:%.*]] = call <8 x i8> @llvm.ctpop.v8i8(<8 x i8> %a) #2
// CHECK: ret <8 x i8> [[VCNT_V_I]]
poly8x8_t test_vcnt_p8(poly8x8_t a) {
return vcnt_p8(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vcntq_p8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vcntq_p8(
// CHECK: [[VCNTQ_V_I:%.*]] = call <16 x i8> @llvm.ctpop.v16i8(<16 x i8> %a) #2
// CHECK: ret <16 x i8> [[VCNTQ_V_I]]
poly8x16_t test_vcntq_p8(poly8x16_t a) {
return vcntq_p8(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vmvn_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vmvn_s8(
// CHECK: [[NEG_I:%.*]] = xor <8 x i8> %a, <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>
// CHECK: ret <8 x i8> [[NEG_I]]
int8x8_t test_vmvn_s8(int8x8_t a) {
return vmvn_s8(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vmvnq_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vmvnq_s8(
// CHECK: [[NEG_I:%.*]] = xor <16 x i8> %a, <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>
// CHECK: ret <16 x i8> [[NEG_I]]
int8x16_t test_vmvnq_s8(int8x16_t a) {
return vmvnq_s8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vmvn_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vmvn_s16(
// CHECK: [[NEG_I:%.*]] = xor <4 x i16> %a, <i16 -1, i16 -1, i16 -1, i16 -1>
// CHECK: ret <4 x i16> [[NEG_I]]
int16x4_t test_vmvn_s16(int16x4_t a) {
return vmvn_s16(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vmvnq_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vmvnq_s16(
// CHECK: [[NEG_I:%.*]] = xor <8 x i16> %a, <i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1>
// CHECK: ret <8 x i16> [[NEG_I]]
int16x8_t test_vmvnq_s16(int16x8_t a) {
return vmvnq_s16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vmvn_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vmvn_s32(
// CHECK: [[NEG_I:%.*]] = xor <2 x i32> %a, <i32 -1, i32 -1>
// CHECK: ret <2 x i32> [[NEG_I]]
int32x2_t test_vmvn_s32(int32x2_t a) {
return vmvn_s32(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vmvnq_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vmvnq_s32(
// CHECK: [[NEG_I:%.*]] = xor <4 x i32> %a, <i32 -1, i32 -1, i32 -1, i32 -1>
// CHECK: ret <4 x i32> [[NEG_I]]
int32x4_t test_vmvnq_s32(int32x4_t a) {
return vmvnq_s32(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vmvn_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vmvn_u8(
// CHECK: [[NEG_I:%.*]] = xor <8 x i8> %a, <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>
// CHECK: ret <8 x i8> [[NEG_I]]
uint8x8_t test_vmvn_u8(uint8x8_t a) {
return vmvn_u8(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vmvnq_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vmvnq_u8(
// CHECK: [[NEG_I:%.*]] = xor <16 x i8> %a, <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>
// CHECK: ret <16 x i8> [[NEG_I]]
uint8x16_t test_vmvnq_u8(uint8x16_t a) {
return vmvnq_u8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vmvn_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vmvn_u16(
// CHECK: [[NEG_I:%.*]] = xor <4 x i16> %a, <i16 -1, i16 -1, i16 -1, i16 -1>
// CHECK: ret <4 x i16> [[NEG_I]]
uint16x4_t test_vmvn_u16(uint16x4_t a) {
return vmvn_u16(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vmvnq_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vmvnq_u16(
// CHECK: [[NEG_I:%.*]] = xor <8 x i16> %a, <i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1>
// CHECK: ret <8 x i16> [[NEG_I]]
uint16x8_t test_vmvnq_u16(uint16x8_t a) {
return vmvnq_u16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vmvn_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vmvn_u32(
// CHECK: [[NEG_I:%.*]] = xor <2 x i32> %a, <i32 -1, i32 -1>
// CHECK: ret <2 x i32> [[NEG_I]]
uint32x2_t test_vmvn_u32(uint32x2_t a) {
return vmvn_u32(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vmvnq_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vmvnq_u32(
// CHECK: [[NEG_I:%.*]] = xor <4 x i32> %a, <i32 -1, i32 -1, i32 -1, i32 -1>
// CHECK: ret <4 x i32> [[NEG_I]]
uint32x4_t test_vmvnq_u32(uint32x4_t a) {
return vmvnq_u32(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vmvn_p8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vmvn_p8(
// CHECK: [[NEG_I:%.*]] = xor <8 x i8> %a, <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>
// CHECK: ret <8 x i8> [[NEG_I]]
poly8x8_t test_vmvn_p8(poly8x8_t a) {
return vmvn_p8(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vmvnq_p8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vmvnq_p8(
// CHECK: [[NEG_I:%.*]] = xor <16 x i8> %a, <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>
// CHECK: ret <16 x i8> [[NEG_I]]
poly8x16_t test_vmvnq_p8(poly8x16_t a) {
return vmvnq_p8(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vrbit_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrbit_s8(
// CHECK: [[VRBIT_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.rbit.v8i8(<8 x i8> %a) #2
// CHECK: ret <8 x i8> [[VRBIT_I]]
int8x8_t test_vrbit_s8(int8x8_t a) {
return vrbit_s8(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vrbitq_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrbitq_s8(
// CHECK: [[VRBIT_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.rbit.v16i8(<16 x i8> %a) #2
// CHECK: ret <16 x i8> [[VRBIT_I]]
int8x16_t test_vrbitq_s8(int8x16_t a) {
return vrbitq_s8(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vrbit_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrbit_u8(
// CHECK: [[VRBIT_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.rbit.v8i8(<8 x i8> %a) #2
// CHECK: ret <8 x i8> [[VRBIT_I]]
uint8x8_t test_vrbit_u8(uint8x8_t a) {
return vrbit_u8(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vrbitq_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrbitq_u8(
// CHECK: [[VRBIT_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.rbit.v16i8(<16 x i8> %a) #2
// CHECK: ret <16 x i8> [[VRBIT_I]]
uint8x16_t test_vrbitq_u8(uint8x16_t a) {
return vrbitq_u8(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vrbit_p8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrbit_p8(
// CHECK: [[VRBIT_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.rbit.v8i8(<8 x i8> %a) #2
// CHECK: ret <8 x i8> [[VRBIT_I]]
poly8x8_t test_vrbit_p8(poly8x8_t a) {
return vrbit_p8(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vrbitq_p8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrbitq_p8(
// CHECK: [[VRBIT_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.rbit.v16i8(<16 x i8> %a) #2
// CHECK: ret <16 x i8> [[VRBIT_I]]
poly8x16_t test_vrbitq_p8(poly8x16_t a) {
return vrbitq_p8(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vmovn_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vmovn_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VMOVN_I:%.*]] = trunc <8 x i16> [[TMP1]] to <8 x i8>
+// CHECK: [[VMOVN_I:%.*]] = trunc <8 x i16> %a to <8 x i8>
// CHECK: ret <8 x i8> [[VMOVN_I]]
int8x8_t test_vmovn_s16(int16x8_t a) {
return vmovn_s16(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vmovn_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vmovn_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VMOVN_I:%.*]] = trunc <4 x i32> [[TMP1]] to <4 x i16>
+// CHECK: [[VMOVN_I:%.*]] = trunc <4 x i32> %a to <4 x i16>
// CHECK: ret <4 x i16> [[VMOVN_I]]
int16x4_t test_vmovn_s32(int32x4_t a) {
return vmovn_s32(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vmovn_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vmovn_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VMOVN_I:%.*]] = trunc <2 x i64> [[TMP1]] to <2 x i32>
+// CHECK: [[VMOVN_I:%.*]] = trunc <2 x i64> %a to <2 x i32>
// CHECK: ret <2 x i32> [[VMOVN_I]]
int32x2_t test_vmovn_s64(int64x2_t a) {
return vmovn_s64(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vmovn_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vmovn_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VMOVN_I:%.*]] = trunc <8 x i16> [[TMP1]] to <8 x i8>
+// CHECK: [[VMOVN_I:%.*]] = trunc <8 x i16> %a to <8 x i8>
// CHECK: ret <8 x i8> [[VMOVN_I]]
uint8x8_t test_vmovn_u16(uint16x8_t a) {
return vmovn_u16(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vmovn_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vmovn_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VMOVN_I:%.*]] = trunc <4 x i32> [[TMP1]] to <4 x i16>
+// CHECK: [[VMOVN_I:%.*]] = trunc <4 x i32> %a to <4 x i16>
// CHECK: ret <4 x i16> [[VMOVN_I]]
uint16x4_t test_vmovn_u32(uint32x4_t a) {
return vmovn_u32(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vmovn_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vmovn_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VMOVN_I:%.*]] = trunc <2 x i64> [[TMP1]] to <2 x i32>
+// CHECK: [[VMOVN_I:%.*]] = trunc <2 x i64> %a to <2 x i32>
// CHECK: ret <2 x i32> [[VMOVN_I]]
uint32x2_t test_vmovn_u64(uint64x2_t a) {
return vmovn_u64(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vmovn_high_s16(<8 x i8> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vmovn_high_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VMOVN_I_I:%.*]] = trunc <8 x i16> [[TMP1]] to <8 x i8>
+// CHECK: [[VMOVN_I_I:%.*]] = trunc <8 x i16> %b to <8 x i8>
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> [[VMOVN_I_I]], <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 <16 x i8> [[SHUFFLE_I_I]]
int8x16_t test_vmovn_high_s16(int8x8_t a, int16x8_t b) {
return vmovn_high_s16(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vmovn_high_s32(<4 x i16> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vmovn_high_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VMOVN_I_I:%.*]] = trunc <4 x i32> [[TMP1]] to <4 x i16>
+// CHECK: [[VMOVN_I_I:%.*]] = trunc <4 x i32> %b to <4 x i16>
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> [[VMOVN_I_I]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
// CHECK: ret <8 x i16> [[SHUFFLE_I_I]]
int16x8_t test_vmovn_high_s32(int16x4_t a, int32x4_t b) {
return vmovn_high_s32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vmovn_high_s64(<2 x i32> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vmovn_high_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VMOVN_I_I:%.*]] = trunc <2 x i64> [[TMP1]] to <2 x i32>
+// CHECK: [[VMOVN_I_I:%.*]] = trunc <2 x i64> %b to <2 x i32>
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> [[VMOVN_I_I]], <4 x i32> <i32 0, i32 1, i32 2, i32 3>
// CHECK: ret <4 x i32> [[SHUFFLE_I_I]]
int32x4_t test_vmovn_high_s64(int32x2_t a, int64x2_t b) {
return vmovn_high_s64(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vmovn_high_u16(<8 x i8> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vmovn_high_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VMOVN_I_I:%.*]] = trunc <8 x i16> [[TMP1]] to <8 x i8>
+// CHECK: [[VMOVN_I_I:%.*]] = trunc <8 x i16> %b to <8 x i8>
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> [[VMOVN_I_I]], <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 <16 x i8> [[SHUFFLE_I_I]]
int8x16_t test_vmovn_high_u16(int8x8_t a, int16x8_t b) {
return vmovn_high_u16(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vmovn_high_u32(<4 x i16> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vmovn_high_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VMOVN_I_I:%.*]] = trunc <4 x i32> [[TMP1]] to <4 x i16>
+// CHECK: [[VMOVN_I_I:%.*]] = trunc <4 x i32> %b to <4 x i16>
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> [[VMOVN_I_I]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
// CHECK: ret <8 x i16> [[SHUFFLE_I_I]]
int16x8_t test_vmovn_high_u32(int16x4_t a, int32x4_t b) {
return vmovn_high_u32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vmovn_high_u64(<2 x i32> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vmovn_high_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VMOVN_I_I:%.*]] = trunc <2 x i64> [[TMP1]] to <2 x i32>
+// CHECK: [[VMOVN_I_I:%.*]] = trunc <2 x i64> %b to <2 x i32>
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> [[VMOVN_I_I]], <4 x i32> <i32 0, i32 1, i32 2, i32 3>
// CHECK: ret <4 x i32> [[SHUFFLE_I_I]]
int32x4_t test_vmovn_high_u64(int32x2_t a, int64x2_t b) {
return vmovn_high_u64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vqmovun_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vqmovun_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
-// CHECK: [[VQMOVUN_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VQMOVUN_V1_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.sqxtun.v8i8(<8 x i16> [[VQMOVUN_V_I]]) #2
+// CHECK: [[VQMOVUN_V1_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.sqxtun.v8i8(<8 x i16> %a) #2
// CHECK: ret <8 x i8> [[VQMOVUN_V1_I]]
int8x8_t test_vqmovun_s16(int16x8_t a) {
return vqmovun_s16(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vqmovun_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vqmovun_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
-// CHECK: [[VQMOVUN_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQMOVUN_V1_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqxtun.v4i16(<4 x i32> [[VQMOVUN_V_I]]) #2
+// CHECK: [[VQMOVUN_V1_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqxtun.v4i16(<4 x i32> %a) #2
// CHECK: [[VQMOVUN_V2_I:%.*]] = bitcast <4 x i16> [[VQMOVUN_V1_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[VQMOVUN_V2_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP1]]
+// CHECK: ret <4 x i16> [[VQMOVUN_V1_I]]
int16x4_t test_vqmovun_s32(int32x4_t a) {
return vqmovun_s32(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vqmovun_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vqmovun_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
-// CHECK: [[VQMOVUN_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQMOVUN_V1_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqxtun.v2i32(<2 x i64> [[VQMOVUN_V_I]]) #2
+// CHECK: [[VQMOVUN_V1_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqxtun.v2i32(<2 x i64> %a) #2
// CHECK: [[VQMOVUN_V2_I:%.*]] = bitcast <2 x i32> [[VQMOVUN_V1_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[VQMOVUN_V2_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP1]]
+// CHECK: ret <2 x i32> [[VQMOVUN_V1_I]]
int32x2_t test_vqmovun_s64(int64x2_t a) {
return vqmovun_s64(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vqmovun_high_s16(<8 x i8> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqmovun_high_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VQMOVUN_V_I_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VQMOVUN_V1_I_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.sqxtun.v8i8(<8 x i16> [[VQMOVUN_V_I_I]]) #2
+// CHECK: [[VQMOVUN_V1_I_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.sqxtun.v8i8(<8 x i16> %b) #2
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> [[VQMOVUN_V1_I_I]], <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 <16 x i8> [[SHUFFLE_I_I]]
int8x16_t test_vqmovun_high_s16(int8x8_t a, int16x8_t b) {
return vqmovun_high_s16(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vqmovun_high_s32(<4 x i16> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqmovun_high_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VQMOVUN_V_I_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQMOVUN_V1_I_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqxtun.v4i16(<4 x i32> [[VQMOVUN_V_I_I]]) #2
+// CHECK: [[VQMOVUN_V1_I_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqxtun.v4i16(<4 x i32> %b) #2
// CHECK: [[VQMOVUN_V2_I_I:%.*]] = bitcast <4 x i16> [[VQMOVUN_V1_I_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[VQMOVUN_V2_I_I]] to <4 x i16>
-// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> [[TMP1]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> [[VQMOVUN_V1_I_I]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
// CHECK: ret <8 x i16> [[SHUFFLE_I_I]]
int16x8_t test_vqmovun_high_s32(int16x4_t a, int32x4_t b) {
return vqmovun_high_s32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vqmovun_high_s64(<2 x i32> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vqmovun_high_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[VQMOVUN_V_I_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQMOVUN_V1_I_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqxtun.v2i32(<2 x i64> [[VQMOVUN_V_I_I]]) #2
+// CHECK: [[VQMOVUN_V1_I_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqxtun.v2i32(<2 x i64> %b) #2
// CHECK: [[VQMOVUN_V2_I_I:%.*]] = bitcast <2 x i32> [[VQMOVUN_V1_I_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[VQMOVUN_V2_I_I]] to <2 x i32>
-// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> [[TMP1]], <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> [[VQMOVUN_V1_I_I]], <4 x i32> <i32 0, i32 1, i32 2, i32 3>
// CHECK: ret <4 x i32> [[SHUFFLE_I_I]]
int32x4_t test_vqmovun_high_s64(int32x2_t a, int64x2_t b) {
return vqmovun_high_s64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vqmovn_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vqmovn_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
-// CHECK: [[VQMOVN_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VQMOVN_V1_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.sqxtn.v8i8(<8 x i16> [[VQMOVN_V_I]]) #2
+// CHECK: [[VQMOVN_V1_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.sqxtn.v8i8(<8 x i16> %a) #2
// CHECK: ret <8 x i8> [[VQMOVN_V1_I]]
int8x8_t test_vqmovn_s16(int16x8_t a) {
return vqmovn_s16(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vqmovn_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vqmovn_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
-// CHECK: [[VQMOVN_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQMOVN_V1_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqxtn.v4i16(<4 x i32> [[VQMOVN_V_I]]) #2
+// CHECK: [[VQMOVN_V1_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqxtn.v4i16(<4 x i32> %a) #2
// CHECK: [[VQMOVN_V2_I:%.*]] = bitcast <4 x i16> [[VQMOVN_V1_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[VQMOVN_V2_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP1]]
+// CHECK: ret <4 x i16> [[VQMOVN_V1_I]]
int16x4_t test_vqmovn_s32(int32x4_t a) {
return vqmovn_s32(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vqmovn_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vqmovn_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
-// CHECK: [[VQMOVN_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQMOVN_V1_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqxtn.v2i32(<2 x i64> [[VQMOVN_V_I]]) #2
+// CHECK: [[VQMOVN_V1_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqxtn.v2i32(<2 x i64> %a) #2
// CHECK: [[VQMOVN_V2_I:%.*]] = bitcast <2 x i32> [[VQMOVN_V1_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[VQMOVN_V2_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP1]]
+// CHECK: ret <2 x i32> [[VQMOVN_V1_I]]
int32x2_t test_vqmovn_s64(int64x2_t a) {
return vqmovn_s64(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vqmovn_high_s16(<8 x i8> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqmovn_high_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VQMOVN_V_I_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VQMOVN_V1_I_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.sqxtn.v8i8(<8 x i16> [[VQMOVN_V_I_I]]) #2
+// CHECK: [[VQMOVN_V1_I_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.sqxtn.v8i8(<8 x i16> %b) #2
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> [[VQMOVN_V1_I_I]], <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 <16 x i8> [[SHUFFLE_I_I]]
int8x16_t test_vqmovn_high_s16(int8x8_t a, int16x8_t b) {
return vqmovn_high_s16(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vqmovn_high_s32(<4 x i16> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqmovn_high_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VQMOVN_V_I_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQMOVN_V1_I_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqxtn.v4i16(<4 x i32> [[VQMOVN_V_I_I]]) #2
+// CHECK: [[VQMOVN_V1_I_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.sqxtn.v4i16(<4 x i32> %b) #2
// CHECK: [[VQMOVN_V2_I_I:%.*]] = bitcast <4 x i16> [[VQMOVN_V1_I_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[VQMOVN_V2_I_I]] to <4 x i16>
-// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> [[TMP1]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> [[VQMOVN_V1_I_I]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
// CHECK: ret <8 x i16> [[SHUFFLE_I_I]]
int16x8_t test_vqmovn_high_s32(int16x4_t a, int32x4_t b) {
return vqmovn_high_s32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vqmovn_high_s64(<2 x i32> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vqmovn_high_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[VQMOVN_V_I_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQMOVN_V1_I_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqxtn.v2i32(<2 x i64> [[VQMOVN_V_I_I]]) #2
+// CHECK: [[VQMOVN_V1_I_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.sqxtn.v2i32(<2 x i64> %b) #2
// CHECK: [[VQMOVN_V2_I_I:%.*]] = bitcast <2 x i32> [[VQMOVN_V1_I_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[VQMOVN_V2_I_I]] to <2 x i32>
-// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> [[TMP1]], <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> [[VQMOVN_V1_I_I]], <4 x i32> <i32 0, i32 1, i32 2, i32 3>
// CHECK: ret <4 x i32> [[SHUFFLE_I_I]]
int32x4_t test_vqmovn_high_s64(int32x2_t a, int64x2_t b) {
return vqmovn_high_s64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vqmovn_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vqmovn_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
-// CHECK: [[VQMOVN_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VQMOVN_V1_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.uqxtn.v8i8(<8 x i16> [[VQMOVN_V_I]]) #2
+// CHECK: [[VQMOVN_V1_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.uqxtn.v8i8(<8 x i16> %a) #2
// CHECK: ret <8 x i8> [[VQMOVN_V1_I]]
uint8x8_t test_vqmovn_u16(uint16x8_t a) {
return vqmovn_u16(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vqmovn_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vqmovn_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
-// CHECK: [[VQMOVN_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQMOVN_V1_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.uqxtn.v4i16(<4 x i32> [[VQMOVN_V_I]]) #2
+// CHECK: [[VQMOVN_V1_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.uqxtn.v4i16(<4 x i32> %a) #2
// CHECK: [[VQMOVN_V2_I:%.*]] = bitcast <4 x i16> [[VQMOVN_V1_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[VQMOVN_V2_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP1]]
+// CHECK: ret <4 x i16> [[VQMOVN_V1_I]]
uint16x4_t test_vqmovn_u32(uint32x4_t a) {
return vqmovn_u32(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vqmovn_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vqmovn_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
-// CHECK: [[VQMOVN_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQMOVN_V1_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.uqxtn.v2i32(<2 x i64> [[VQMOVN_V_I]]) #2
+// CHECK: [[VQMOVN_V1_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.uqxtn.v2i32(<2 x i64> %a) #2
// CHECK: [[VQMOVN_V2_I:%.*]] = bitcast <2 x i32> [[VQMOVN_V1_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[VQMOVN_V2_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP1]]
+// CHECK: ret <2 x i32> [[VQMOVN_V1_I]]
uint32x2_t test_vqmovn_u64(uint64x2_t a) {
return vqmovn_u64(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vqmovn_high_u16(<8 x i8> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqmovn_high_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VQMOVN_V_I_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VQMOVN_V1_I_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.uqxtn.v8i8(<8 x i16> [[VQMOVN_V_I_I]]) #2
+// CHECK: [[VQMOVN_V1_I_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.uqxtn.v8i8(<8 x i16> %b) #2
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> [[VQMOVN_V1_I_I]], <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 <16 x i8> [[SHUFFLE_I_I]]
uint8x16_t test_vqmovn_high_u16(uint8x8_t a, uint16x8_t b) {
return vqmovn_high_u16(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vqmovn_high_u32(<4 x i16> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqmovn_high_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VQMOVN_V_I_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQMOVN_V1_I_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.uqxtn.v4i16(<4 x i32> [[VQMOVN_V_I_I]]) #2
+// CHECK: [[VQMOVN_V1_I_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.uqxtn.v4i16(<4 x i32> %b) #2
// CHECK: [[VQMOVN_V2_I_I:%.*]] = bitcast <4 x i16> [[VQMOVN_V1_I_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[VQMOVN_V2_I_I]] to <4 x i16>
-// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> [[TMP1]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> [[VQMOVN_V1_I_I]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
// CHECK: ret <8 x i16> [[SHUFFLE_I_I]]
uint16x8_t test_vqmovn_high_u32(uint16x4_t a, uint32x4_t b) {
return vqmovn_high_u32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vqmovn_high_u64(<2 x i32> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vqmovn_high_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[VQMOVN_V_I_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQMOVN_V1_I_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.uqxtn.v2i32(<2 x i64> [[VQMOVN_V_I_I]]) #2
+// CHECK: [[VQMOVN_V1_I_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.uqxtn.v2i32(<2 x i64> %b) #2
// CHECK: [[VQMOVN_V2_I_I:%.*]] = bitcast <2 x i32> [[VQMOVN_V1_I_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[VQMOVN_V2_I_I]] to <2 x i32>
-// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> [[TMP1]], <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> [[VQMOVN_V1_I_I]], <4 x i32> <i32 0, i32 1, i32 2, i32 3>
// CHECK: ret <4 x i32> [[SHUFFLE_I_I]]
uint32x4_t test_vqmovn_high_u64(uint32x2_t a, uint64x2_t b) {
return vqmovn_high_u64(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vshll_n_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vshll_n_s8(
// CHECK: [[TMP0:%.*]] = sext <8 x i8> %a to <8 x i16>
// CHECK: [[VSHLL_N:%.*]] = shl <8 x i16> [[TMP0]], <i16 8, i16 8, i16 8, i16 8, i16 8, i16 8, i16 8, i16 8>
// CHECK: ret <8 x i16> [[VSHLL_N]]
@@ -2242,7 +2050,7 @@ int16x8_t test_vshll_n_s8(int8x8_t a) {
return vshll_n_s8(a, 8);
}
-// CHECK-LABEL: define <4 x i32> @test_vshll_n_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vshll_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
// CHECK: [[TMP2:%.*]] = sext <4 x i16> [[TMP1]] to <4 x i32>
@@ -2252,7 +2060,7 @@ int32x4_t test_vshll_n_s16(int16x4_t a) {
return vshll_n_s16(a, 16);
}
-// CHECK-LABEL: define <2 x i64> @test_vshll_n_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vshll_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
// CHECK: [[TMP2:%.*]] = sext <2 x i32> [[TMP1]] to <2 x i64>
@@ -2262,7 +2070,7 @@ int64x2_t test_vshll_n_s32(int32x2_t a) {
return vshll_n_s32(a, 32);
}
-// CHECK-LABEL: define <8 x i16> @test_vshll_n_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vshll_n_u8(
// CHECK: [[TMP0:%.*]] = zext <8 x i8> %a to <8 x i16>
// CHECK: [[VSHLL_N:%.*]] = shl <8 x i16> [[TMP0]], <i16 8, i16 8, i16 8, i16 8, i16 8, i16 8, i16 8, i16 8>
// CHECK: ret <8 x i16> [[VSHLL_N]]
@@ -2270,7 +2078,7 @@ uint16x8_t test_vshll_n_u8(uint8x8_t a) {
return vshll_n_u8(a, 8);
}
-// CHECK-LABEL: define <4 x i32> @test_vshll_n_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vshll_n_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
// CHECK: [[TMP2:%.*]] = zext <4 x i16> [[TMP1]] to <4 x i32>
@@ -2280,7 +2088,7 @@ uint32x4_t test_vshll_n_u16(uint16x4_t a) {
return vshll_n_u16(a, 16);
}
-// CHECK-LABEL: define <2 x i64> @test_vshll_n_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vshll_n_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
// CHECK: [[TMP2:%.*]] = zext <2 x i32> [[TMP1]] to <2 x i64>
@@ -2290,7 +2098,7 @@ uint64x2_t test_vshll_n_u32(uint32x2_t a) {
return vshll_n_u32(a, 32);
}
-// CHECK-LABEL: define <8 x i16> @test_vshll_high_n_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vshll_high_n_s8(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %a, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: [[TMP0:%.*]] = sext <8 x i8> [[SHUFFLE_I]] to <8 x i16>
// CHECK: [[VSHLL_N:%.*]] = shl <8 x i16> [[TMP0]], <i16 8, i16 8, i16 8, i16 8, i16 8, i16 8, i16 8, i16 8>
@@ -2299,7 +2107,7 @@ int16x8_t test_vshll_high_n_s8(int8x16_t a) {
return vshll_high_n_s8(a, 8);
}
-// CHECK-LABEL: define <4 x i32> @test_vshll_high_n_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vshll_high_n_s16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %a, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
@@ -2310,7 +2118,7 @@ int32x4_t test_vshll_high_n_s16(int16x8_t a) {
return vshll_high_n_s16(a, 16);
}
-// CHECK-LABEL: define <2 x i64> @test_vshll_high_n_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vshll_high_n_s32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %a, <2 x i32> <i32 2, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
@@ -2321,7 +2129,7 @@ int64x2_t test_vshll_high_n_s32(int32x4_t a) {
return vshll_high_n_s32(a, 32);
}
-// CHECK-LABEL: define <8 x i16> @test_vshll_high_n_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vshll_high_n_u8(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %a, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: [[TMP0:%.*]] = zext <8 x i8> [[SHUFFLE_I]] to <8 x i16>
// CHECK: [[VSHLL_N:%.*]] = shl <8 x i16> [[TMP0]], <i16 8, i16 8, i16 8, i16 8, i16 8, i16 8, i16 8, i16 8>
@@ -2330,7 +2138,7 @@ uint16x8_t test_vshll_high_n_u8(uint8x16_t a) {
return vshll_high_n_u8(a, 8);
}
-// CHECK-LABEL: define <4 x i32> @test_vshll_high_n_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vshll_high_n_u16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %a, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
@@ -2341,7 +2149,7 @@ uint32x4_t test_vshll_high_n_u16(uint16x8_t a) {
return vshll_high_n_u16(a, 16);
}
-// CHECK-LABEL: define <2 x i64> @test_vshll_high_n_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vshll_high_n_u32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %a, <2 x i32> <i32 2, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
@@ -2352,10 +2160,9 @@ uint64x2_t test_vshll_high_n_u32(uint32x4_t a) {
return vshll_high_n_u32(a, 32);
}
-// CHECK-LABEL: define <4 x half> @test_vcvt_f16_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vcvt_f16_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[VCVT_F16_F32_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VCVT_F16_F321_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.vcvtfp2hf(<4 x float> [[VCVT_F16_F32_I]]) #2
+// CHECK: [[VCVT_F16_F321_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.vcvtfp2hf(<4 x float> %a) #2
// CHECK: [[VCVT_F16_F322_I:%.*]] = bitcast <4 x i16> [[VCVT_F16_F321_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[VCVT_F16_F322_I]] to <4 x half>
// CHECK: ret <4 x half> [[TMP1]]
@@ -2363,10 +2170,9 @@ float16x4_t test_vcvt_f16_f32(float32x4_t a) {
return vcvt_f16_f32(a);
}
-// CHECK-LABEL: define <8 x half> @test_vcvt_high_f16_f32(<4 x half> %a, <4 x float> %b) #0 {
+// CHECK-LABEL: @test_vcvt_high_f16_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %b to <16 x i8>
-// CHECK: [[VCVT_F16_F32_I_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VCVT_F16_F321_I_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.vcvtfp2hf(<4 x float> [[VCVT_F16_F32_I_I]]) #2
+// CHECK: [[VCVT_F16_F321_I_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.vcvtfp2hf(<4 x float> %b) #2
// CHECK: [[VCVT_F16_F322_I_I:%.*]] = bitcast <4 x i16> [[VCVT_F16_F321_I_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[VCVT_F16_F322_I_I]] to <4 x half>
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x half> %a, <4 x half> [[TMP1]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
@@ -2375,693 +2181,617 @@ float16x8_t test_vcvt_high_f16_f32(float16x4_t a, float32x4_t b) {
return vcvt_high_f16_f32(a, b);
}
-// CHECK-LABEL: define <2 x float> @test_vcvt_f32_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vcvt_f32_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VCVT_I:%.*]] = fptrunc <2 x double> [[TMP1]] to <2 x float>
+// CHECK: [[VCVT_I:%.*]] = fptrunc <2 x double> %a to <2 x float>
// CHECK: ret <2 x float> [[VCVT_I]]
float32x2_t test_vcvt_f32_f64(float64x2_t a) {
return vcvt_f32_f64(a);
}
-// CHECK-LABEL: define <4 x float> @test_vcvt_high_f32_f64(<2 x float> %a, <2 x double> %b) #0 {
+// CHECK-LABEL: @test_vcvt_high_f32_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %b to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VCVT_I_I:%.*]] = fptrunc <2 x double> [[TMP1]] to <2 x float>
+// CHECK: [[VCVT_I_I:%.*]] = fptrunc <2 x double> %b to <2 x float>
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <2 x float> %a, <2 x float> [[VCVT_I_I]], <4 x i32> <i32 0, i32 1, i32 2, i32 3>
// CHECK: ret <4 x float> [[SHUFFLE_I_I]]
float32x4_t test_vcvt_high_f32_f64(float32x2_t a, float64x2_t b) {
return vcvt_high_f32_f64(a, b);
}
-// CHECK-LABEL: define <2 x float> @test_vcvtx_f32_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vcvtx_f32_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
-// CHECK: [[VCVTX_F32_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VCVTX_F32_V1_I:%.*]] = call <2 x float> @llvm.aarch64.neon.fcvtxn.v2f32.v2f64(<2 x double> [[VCVTX_F32_V_I]]) #2
+// CHECK: [[VCVTX_F32_V1_I:%.*]] = call <2 x float> @llvm.aarch64.neon.fcvtxn.v2f32.v2f64(<2 x double> %a) #2
// CHECK: ret <2 x float> [[VCVTX_F32_V1_I]]
float32x2_t test_vcvtx_f32_f64(float64x2_t a) {
return vcvtx_f32_f64(a);
}
-// CHECK-LABEL: define <4 x float> @test_vcvtx_high_f32_f64(<2 x float> %a, <2 x double> %b) #0 {
+// CHECK-LABEL: @test_vcvtx_high_f32_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %b to <16 x i8>
-// CHECK: [[VCVTX_F32_V_I_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VCVTX_F32_V1_I_I:%.*]] = call <2 x float> @llvm.aarch64.neon.fcvtxn.v2f32.v2f64(<2 x double> [[VCVTX_F32_V_I_I]]) #2
+// CHECK: [[VCVTX_F32_V1_I_I:%.*]] = call <2 x float> @llvm.aarch64.neon.fcvtxn.v2f32.v2f64(<2 x double> %b) #2
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <2 x float> %a, <2 x float> [[VCVTX_F32_V1_I_I]], <4 x i32> <i32 0, i32 1, i32 2, i32 3>
// CHECK: ret <4 x float> [[SHUFFLE_I_I]]
float32x4_t test_vcvtx_high_f32_f64(float32x2_t a, float64x2_t b) {
return vcvtx_high_f32_f64(a, b);
}
-// CHECK-LABEL: define <4 x float> @test_vcvt_f32_f16(<4 x half> %a) #0 {
+// CHECK-LABEL: @test_vcvt_f32_f16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x half> %a to <8 x i8>
// CHECK: [[VCVT_F32_F16_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
// CHECK: [[VCVT_F32_F161_I:%.*]] = call <4 x float> @llvm.aarch64.neon.vcvthf2fp(<4 x i16> [[VCVT_F32_F16_I]]) #2
// CHECK: [[VCVT_F32_F162_I:%.*]] = bitcast <4 x float> [[VCVT_F32_F161_I]] to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[VCVT_F32_F162_I]] to <4 x float>
-// CHECK: ret <4 x float> [[TMP1]]
+// CHECK: ret <4 x float> [[VCVT_F32_F161_I]]
float32x4_t test_vcvt_f32_f16(float16x4_t a) {
return vcvt_f32_f16(a);
}
-// CHECK-LABEL: define <4 x float> @test_vcvt_high_f32_f16(<8 x half> %a) #0 {
+// CHECK-LABEL: @test_vcvt_high_f32_f16(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <8 x half> %a, <8 x half> %a, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: [[TMP0:%.*]] = bitcast <4 x half> [[SHUFFLE_I_I]] to <8 x i8>
// CHECK: [[VCVT_F32_F16_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
// CHECK: [[VCVT_F32_F161_I_I:%.*]] = call <4 x float> @llvm.aarch64.neon.vcvthf2fp(<4 x i16> [[VCVT_F32_F16_I_I]]) #2
// CHECK: [[VCVT_F32_F162_I_I:%.*]] = bitcast <4 x float> [[VCVT_F32_F161_I_I]] to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[VCVT_F32_F162_I_I]] to <4 x float>
-// CHECK: ret <4 x float> [[TMP1]]
+// CHECK: ret <4 x float> [[VCVT_F32_F161_I_I]]
float32x4_t test_vcvt_high_f32_f16(float16x8_t a) {
return vcvt_high_f32_f16(a);
}
-// CHECK-LABEL: define <2 x double> @test_vcvt_f64_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vcvt_f64_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VCVT_I:%.*]] = fpext <2 x float> [[TMP1]] to <2 x double>
+// CHECK: [[VCVT_I:%.*]] = fpext <2 x float> %a to <2 x double>
// CHECK: ret <2 x double> [[VCVT_I]]
float64x2_t test_vcvt_f64_f32(float32x2_t a) {
return vcvt_f64_f32(a);
}
-// CHECK-LABEL: define <2 x double> @test_vcvt_high_f64_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vcvt_high_f64_f32(
// CHECK: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x float> %a, <4 x float> %a, <2 x i32> <i32 2, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> [[SHUFFLE_I_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VCVT_I_I:%.*]] = fpext <2 x float> [[TMP1]] to <2 x double>
+// CHECK: [[VCVT_I_I:%.*]] = fpext <2 x float> [[SHUFFLE_I_I]] to <2 x double>
// CHECK: ret <2 x double> [[VCVT_I_I]]
float64x2_t test_vcvt_high_f64_f32(float32x4_t a) {
return vcvt_high_f64_f32(a);
}
-// CHECK-LABEL: define <2 x float> @test_vrndn_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vrndn_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[VRNDN_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VRNDN1_I:%.*]] = call <2 x float> @llvm.aarch64.neon.frintn.v2f32(<2 x float> [[VRNDN_I]]) #2
+// CHECK: [[VRNDN1_I:%.*]] = call <2 x float> @llvm.aarch64.neon.frintn.v2f32(<2 x float> %a) #2
// CHECK: ret <2 x float> [[VRNDN1_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-LABEL: @test_vrndnq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[VRNDN_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VRNDN1_I:%.*]] = call <4 x float> @llvm.aarch64.neon.frintn.v4f32(<4 x float> [[VRNDN_I]]) #2
+// CHECK: [[VRNDN1_I:%.*]] = call <4 x float> @llvm.aarch64.neon.frintn.v4f32(<4 x float> %a) #2
// CHECK: ret <4 x float> [[VRNDN1_I]]
float32x4_t test_vrndnq_f32(float32x4_t a) {
return vrndnq_f32(a);
}
-// CHECK-LABEL: define <2 x double> @test_vrndnq_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vrndnq_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
-// CHECK: [[VRNDN_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VRNDN1_I:%.*]] = call <2 x double> @llvm.aarch64.neon.frintn.v2f64(<2 x double> [[VRNDN_I]]) #2
+// CHECK: [[VRNDN1_I:%.*]] = call <2 x double> @llvm.aarch64.neon.frintn.v2f64(<2 x double> %a) #2
// CHECK: ret <2 x double> [[VRNDN1_I]]
float64x2_t test_vrndnq_f64(float64x2_t a) {
return vrndnq_f64(a);
}
-// CHECK-LABEL: define <2 x float> @test_vrnda_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vrnda_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[VRNDA_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VRNDA1_I:%.*]] = call <2 x float> @llvm.round.v2f32(<2 x float> [[VRNDA_I]]) #2
+// CHECK: [[VRNDA1_I:%.*]] = call <2 x float> @llvm.round.v2f32(<2 x float> %a) #2
// CHECK: ret <2 x float> [[VRNDA1_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-LABEL: @test_vrndaq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[VRNDA_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VRNDA1_I:%.*]] = call <4 x float> @llvm.round.v4f32(<4 x float> [[VRNDA_I]]) #2
+// CHECK: [[VRNDA1_I:%.*]] = call <4 x float> @llvm.round.v4f32(<4 x float> %a) #2
// CHECK: ret <4 x float> [[VRNDA1_I]]
float32x4_t test_vrndaq_f32(float32x4_t a) {
return vrndaq_f32(a);
}
-// CHECK-LABEL: define <2 x double> @test_vrndaq_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vrndaq_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
-// CHECK: [[VRNDA_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VRNDA1_I:%.*]] = call <2 x double> @llvm.round.v2f64(<2 x double> [[VRNDA_I]]) #2
+// CHECK: [[VRNDA1_I:%.*]] = call <2 x double> @llvm.round.v2f64(<2 x double> %a) #2
// CHECK: ret <2 x double> [[VRNDA1_I]]
float64x2_t test_vrndaq_f64(float64x2_t a) {
return vrndaq_f64(a);
}
-// CHECK-LABEL: define <2 x float> @test_vrndp_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vrndp_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[VRNDP_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VRNDP1_I:%.*]] = call <2 x float> @llvm.ceil.v2f32(<2 x float> [[VRNDP_I]]) #2
+// CHECK: [[VRNDP1_I:%.*]] = call <2 x float> @llvm.ceil.v2f32(<2 x float> %a) #2
// CHECK: ret <2 x float> [[VRNDP1_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-LABEL: @test_vrndpq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[VRNDP_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VRNDP1_I:%.*]] = call <4 x float> @llvm.ceil.v4f32(<4 x float> [[VRNDP_I]]) #2
+// CHECK: [[VRNDP1_I:%.*]] = call <4 x float> @llvm.ceil.v4f32(<4 x float> %a) #2
// CHECK: ret <4 x float> [[VRNDP1_I]]
float32x4_t test_vrndpq_f32(float32x4_t a) {
return vrndpq_f32(a);
}
-// CHECK-LABEL: define <2 x double> @test_vrndpq_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vrndpq_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
-// CHECK: [[VRNDP_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VRNDP1_I:%.*]] = call <2 x double> @llvm.ceil.v2f64(<2 x double> [[VRNDP_I]]) #2
+// CHECK: [[VRNDP1_I:%.*]] = call <2 x double> @llvm.ceil.v2f64(<2 x double> %a) #2
// CHECK: ret <2 x double> [[VRNDP1_I]]
float64x2_t test_vrndpq_f64(float64x2_t a) {
return vrndpq_f64(a);
}
-// CHECK-LABEL: define <2 x float> @test_vrndm_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vrndm_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[VRNDM_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VRNDM1_I:%.*]] = call <2 x float> @llvm.floor.v2f32(<2 x float> [[VRNDM_I]]) #2
+// CHECK: [[VRNDM1_I:%.*]] = call <2 x float> @llvm.floor.v2f32(<2 x float> %a) #2
// CHECK: ret <2 x float> [[VRNDM1_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-LABEL: @test_vrndmq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[VRNDM_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VRNDM1_I:%.*]] = call <4 x float> @llvm.floor.v4f32(<4 x float> [[VRNDM_I]]) #2
+// CHECK: [[VRNDM1_I:%.*]] = call <4 x float> @llvm.floor.v4f32(<4 x float> %a) #2
// CHECK: ret <4 x float> [[VRNDM1_I]]
float32x4_t test_vrndmq_f32(float32x4_t a) {
return vrndmq_f32(a);
}
-// CHECK-LABEL: define <2 x double> @test_vrndmq_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vrndmq_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
-// CHECK: [[VRNDM_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VRNDM1_I:%.*]] = call <2 x double> @llvm.floor.v2f64(<2 x double> [[VRNDM_I]]) #2
+// CHECK: [[VRNDM1_I:%.*]] = call <2 x double> @llvm.floor.v2f64(<2 x double> %a) #2
// CHECK: ret <2 x double> [[VRNDM1_I]]
float64x2_t test_vrndmq_f64(float64x2_t a) {
return vrndmq_f64(a);
}
-// CHECK-LABEL: define <2 x float> @test_vrndx_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vrndx_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[VRNDX_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VRNDX1_I:%.*]] = call <2 x float> @llvm.rint.v2f32(<2 x float> [[VRNDX_I]]) #2
+// CHECK: [[VRNDX1_I:%.*]] = call <2 x float> @llvm.rint.v2f32(<2 x float> %a) #2
// CHECK: ret <2 x float> [[VRNDX1_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-LABEL: @test_vrndxq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[VRNDX_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VRNDX1_I:%.*]] = call <4 x float> @llvm.rint.v4f32(<4 x float> [[VRNDX_I]]) #2
+// CHECK: [[VRNDX1_I:%.*]] = call <4 x float> @llvm.rint.v4f32(<4 x float> %a) #2
// CHECK: ret <4 x float> [[VRNDX1_I]]
float32x4_t test_vrndxq_f32(float32x4_t a) {
return vrndxq_f32(a);
}
-// CHECK-LABEL: define <2 x double> @test_vrndxq_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vrndxq_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
-// CHECK: [[VRNDX_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VRNDX1_I:%.*]] = call <2 x double> @llvm.rint.v2f64(<2 x double> [[VRNDX_I]]) #2
+// CHECK: [[VRNDX1_I:%.*]] = call <2 x double> @llvm.rint.v2f64(<2 x double> %a) #2
// CHECK: ret <2 x double> [[VRNDX1_I]]
float64x2_t test_vrndxq_f64(float64x2_t a) {
return vrndxq_f64(a);
}
-// CHECK-LABEL: define <2 x float> @test_vrnd_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vrnd_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[VRNDZ_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VRNDZ1_I:%.*]] = call <2 x float> @llvm.trunc.v2f32(<2 x float> [[VRNDZ_I]]) #2
+// CHECK: [[VRNDZ1_I:%.*]] = call <2 x float> @llvm.trunc.v2f32(<2 x float> %a) #2
// CHECK: ret <2 x float> [[VRNDZ1_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-LABEL: @test_vrndq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[VRNDZ_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VRNDZ1_I:%.*]] = call <4 x float> @llvm.trunc.v4f32(<4 x float> [[VRNDZ_I]]) #2
+// CHECK: [[VRNDZ1_I:%.*]] = call <4 x float> @llvm.trunc.v4f32(<4 x float> %a) #2
// CHECK: ret <4 x float> [[VRNDZ1_I]]
float32x4_t test_vrndq_f32(float32x4_t a) {
return vrndq_f32(a);
}
-// CHECK-LABEL: define <2 x double> @test_vrndq_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vrndq_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
-// CHECK: [[VRNDZ_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VRNDZ1_I:%.*]] = call <2 x double> @llvm.trunc.v2f64(<2 x double> [[VRNDZ_I]]) #2
+// CHECK: [[VRNDZ1_I:%.*]] = call <2 x double> @llvm.trunc.v2f64(<2 x double> %a) #2
// CHECK: ret <2 x double> [[VRNDZ1_I]]
float64x2_t test_vrndq_f64(float64x2_t a) {
return vrndq_f64(a);
}
-// CHECK-LABEL: define <2 x float> @test_vrndi_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vrndi_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[VRNDI_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VRNDI1_I:%.*]] = call <2 x float> @llvm.nearbyint.v2f32(<2 x float> [[VRNDI_I]]) #2
+// CHECK: [[VRNDI1_I:%.*]] = call <2 x float> @llvm.nearbyint.v2f32(<2 x float> %a) #2
// 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) #0 {
+// CHECK-LABEL: @test_vrndiq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[VRNDI_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VRNDI1_I:%.*]] = call <4 x float> @llvm.nearbyint.v4f32(<4 x float> [[VRNDI_I]]) #2
+// CHECK: [[VRNDI1_I:%.*]] = call <4 x float> @llvm.nearbyint.v4f32(<4 x float> %a) #2
// CHECK: ret <4 x float> [[VRNDI1_I]]
float32x4_t test_vrndiq_f32(float32x4_t a) {
return vrndiq_f32(a);
}
-// CHECK-LABEL: define <2 x double> @test_vrndiq_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vrndiq_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
-// CHECK: [[VRNDI_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VRNDI1_I:%.*]] = call <2 x double> @llvm.nearbyint.v2f64(<2 x double> [[VRNDI_I]]) #2
+// CHECK: [[VRNDI1_I:%.*]] = call <2 x double> @llvm.nearbyint.v2f64(<2 x double> %a) #2
// CHECK: ret <2 x double> [[VRNDI1_I]]
float64x2_t test_vrndiq_f64(float64x2_t a) {
return vrndiq_f64(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vcvt_s32_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vcvt_s32_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[TMP2:%.*]] = fptosi <2 x float> [[TMP1]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: [[TMP1:%.*]] = fptosi <2 x float> %a to <2 x i32>
+// CHECK: ret <2 x i32> [[TMP1]]
int32x2_t test_vcvt_s32_f32(float32x2_t a) {
return vcvt_s32_f32(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vcvtq_s32_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vcvtq_s32_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[TMP2:%.*]] = fptosi <4 x float> [[TMP1]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: [[TMP1:%.*]] = fptosi <4 x float> %a to <4 x i32>
+// CHECK: ret <4 x i32> [[TMP1]]
int32x4_t test_vcvtq_s32_f32(float32x4_t a) {
return vcvtq_s32_f32(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vcvtq_s64_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vcvtq_s64_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[TMP2:%.*]] = fptosi <2 x double> [[TMP1]] to <2 x i64>
-// CHECK: ret <2 x i64> [[TMP2]]
+// CHECK: [[TMP1:%.*]] = fptosi <2 x double> %a to <2 x i64>
+// CHECK: ret <2 x i64> [[TMP1]]
int64x2_t test_vcvtq_s64_f64(float64x2_t a) {
return vcvtq_s64_f64(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vcvt_u32_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vcvt_u32_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[TMP2:%.*]] = fptoui <2 x float> [[TMP1]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: [[TMP1:%.*]] = fptoui <2 x float> %a to <2 x i32>
+// CHECK: ret <2 x i32> [[TMP1]]
uint32x2_t test_vcvt_u32_f32(float32x2_t a) {
return vcvt_u32_f32(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vcvtq_u32_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vcvtq_u32_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[TMP2:%.*]] = fptoui <4 x float> [[TMP1]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: [[TMP1:%.*]] = fptoui <4 x float> %a to <4 x i32>
+// CHECK: ret <4 x i32> [[TMP1]]
uint32x4_t test_vcvtq_u32_f32(float32x4_t a) {
return vcvtq_u32_f32(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vcvtq_u64_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vcvtq_u64_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[TMP2:%.*]] = fptoui <2 x double> [[TMP1]] to <2 x i64>
-// CHECK: ret <2 x i64> [[TMP2]]
+// CHECK: [[TMP1:%.*]] = fptoui <2 x double> %a to <2 x i64>
+// CHECK: ret <2 x i64> [[TMP1]]
uint64x2_t test_vcvtq_u64_f64(float64x2_t a) {
return vcvtq_u64_f64(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vcvtn_s32_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vcvtn_s32_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[VCVTN_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VCVTN1_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.fcvtns.v2i32.v2f32(<2 x float> [[VCVTN_I]]) #2
+// CHECK: [[VCVTN1_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.fcvtns.v2i32.v2f32(<2 x float> %a) #2
// CHECK: ret <2 x i32> [[VCVTN1_I]]
int32x2_t test_vcvtn_s32_f32(float32x2_t a) {
return vcvtn_s32_f32(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vcvtnq_s32_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vcvtnq_s32_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[VCVTN_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VCVTN1_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.fcvtns.v4i32.v4f32(<4 x float> [[VCVTN_I]]) #2
+// CHECK: [[VCVTN1_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.fcvtns.v4i32.v4f32(<4 x float> %a) #2
// CHECK: ret <4 x i32> [[VCVTN1_I]]
int32x4_t test_vcvtnq_s32_f32(float32x4_t a) {
return vcvtnq_s32_f32(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vcvtnq_s64_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vcvtnq_s64_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
-// CHECK: [[VCVTN_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VCVTN1_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.fcvtns.v2i64.v2f64(<2 x double> [[VCVTN_I]]) #2
+// CHECK: [[VCVTN1_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.fcvtns.v2i64.v2f64(<2 x double> %a) #2
// CHECK: ret <2 x i64> [[VCVTN1_I]]
int64x2_t test_vcvtnq_s64_f64(float64x2_t a) {
return vcvtnq_s64_f64(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vcvtn_u32_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vcvtn_u32_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[VCVTN_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VCVTN1_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.fcvtnu.v2i32.v2f32(<2 x float> [[VCVTN_I]]) #2
+// CHECK: [[VCVTN1_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.fcvtnu.v2i32.v2f32(<2 x float> %a) #2
// CHECK: ret <2 x i32> [[VCVTN1_I]]
uint32x2_t test_vcvtn_u32_f32(float32x2_t a) {
return vcvtn_u32_f32(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vcvtnq_u32_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vcvtnq_u32_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[VCVTN_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VCVTN1_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.fcvtnu.v4i32.v4f32(<4 x float> [[VCVTN_I]]) #2
+// CHECK: [[VCVTN1_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.fcvtnu.v4i32.v4f32(<4 x float> %a) #2
// CHECK: ret <4 x i32> [[VCVTN1_I]]
uint32x4_t test_vcvtnq_u32_f32(float32x4_t a) {
return vcvtnq_u32_f32(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vcvtnq_u64_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vcvtnq_u64_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
-// CHECK: [[VCVTN_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VCVTN1_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.fcvtnu.v2i64.v2f64(<2 x double> [[VCVTN_I]]) #2
+// CHECK: [[VCVTN1_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.fcvtnu.v2i64.v2f64(<2 x double> %a) #2
// CHECK: ret <2 x i64> [[VCVTN1_I]]
uint64x2_t test_vcvtnq_u64_f64(float64x2_t a) {
return vcvtnq_u64_f64(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vcvtp_s32_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vcvtp_s32_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[VCVTP_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VCVTP1_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.fcvtps.v2i32.v2f32(<2 x float> [[VCVTP_I]]) #2
+// CHECK: [[VCVTP1_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.fcvtps.v2i32.v2f32(<2 x float> %a) #2
// CHECK: ret <2 x i32> [[VCVTP1_I]]
int32x2_t test_vcvtp_s32_f32(float32x2_t a) {
return vcvtp_s32_f32(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vcvtpq_s32_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vcvtpq_s32_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[VCVTP_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VCVTP1_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.fcvtps.v4i32.v4f32(<4 x float> [[VCVTP_I]]) #2
+// CHECK: [[VCVTP1_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.fcvtps.v4i32.v4f32(<4 x float> %a) #2
// CHECK: ret <4 x i32> [[VCVTP1_I]]
int32x4_t test_vcvtpq_s32_f32(float32x4_t a) {
return vcvtpq_s32_f32(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vcvtpq_s64_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vcvtpq_s64_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
-// CHECK: [[VCVTP_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VCVTP1_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.fcvtps.v2i64.v2f64(<2 x double> [[VCVTP_I]]) #2
+// CHECK: [[VCVTP1_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.fcvtps.v2i64.v2f64(<2 x double> %a) #2
// CHECK: ret <2 x i64> [[VCVTP1_I]]
int64x2_t test_vcvtpq_s64_f64(float64x2_t a) {
return vcvtpq_s64_f64(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vcvtp_u32_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vcvtp_u32_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[VCVTP_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VCVTP1_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.fcvtpu.v2i32.v2f32(<2 x float> [[VCVTP_I]]) #2
+// CHECK: [[VCVTP1_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.fcvtpu.v2i32.v2f32(<2 x float> %a) #2
// CHECK: ret <2 x i32> [[VCVTP1_I]]
uint32x2_t test_vcvtp_u32_f32(float32x2_t a) {
return vcvtp_u32_f32(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vcvtpq_u32_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vcvtpq_u32_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[VCVTP_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VCVTP1_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.fcvtpu.v4i32.v4f32(<4 x float> [[VCVTP_I]]) #2
+// CHECK: [[VCVTP1_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.fcvtpu.v4i32.v4f32(<4 x float> %a) #2
// CHECK: ret <4 x i32> [[VCVTP1_I]]
uint32x4_t test_vcvtpq_u32_f32(float32x4_t a) {
return vcvtpq_u32_f32(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vcvtpq_u64_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vcvtpq_u64_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
-// CHECK: [[VCVTP_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VCVTP1_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.fcvtpu.v2i64.v2f64(<2 x double> [[VCVTP_I]]) #2
+// CHECK: [[VCVTP1_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.fcvtpu.v2i64.v2f64(<2 x double> %a) #2
// CHECK: ret <2 x i64> [[VCVTP1_I]]
uint64x2_t test_vcvtpq_u64_f64(float64x2_t a) {
return vcvtpq_u64_f64(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vcvtm_s32_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vcvtm_s32_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[VCVTM_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VCVTM1_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.fcvtms.v2i32.v2f32(<2 x float> [[VCVTM_I]]) #2
+// CHECK: [[VCVTM1_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.fcvtms.v2i32.v2f32(<2 x float> %a) #2
// CHECK: ret <2 x i32> [[VCVTM1_I]]
int32x2_t test_vcvtm_s32_f32(float32x2_t a) {
return vcvtm_s32_f32(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vcvtmq_s32_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vcvtmq_s32_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[VCVTM_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VCVTM1_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.fcvtms.v4i32.v4f32(<4 x float> [[VCVTM_I]]) #2
+// CHECK: [[VCVTM1_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.fcvtms.v4i32.v4f32(<4 x float> %a) #2
// CHECK: ret <4 x i32> [[VCVTM1_I]]
int32x4_t test_vcvtmq_s32_f32(float32x4_t a) {
return vcvtmq_s32_f32(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vcvtmq_s64_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vcvtmq_s64_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
-// CHECK: [[VCVTM_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VCVTM1_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.fcvtms.v2i64.v2f64(<2 x double> [[VCVTM_I]]) #2
+// CHECK: [[VCVTM1_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.fcvtms.v2i64.v2f64(<2 x double> %a) #2
// CHECK: ret <2 x i64> [[VCVTM1_I]]
int64x2_t test_vcvtmq_s64_f64(float64x2_t a) {
return vcvtmq_s64_f64(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vcvtm_u32_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vcvtm_u32_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[VCVTM_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VCVTM1_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.fcvtmu.v2i32.v2f32(<2 x float> [[VCVTM_I]]) #2
+// CHECK: [[VCVTM1_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.fcvtmu.v2i32.v2f32(<2 x float> %a) #2
// CHECK: ret <2 x i32> [[VCVTM1_I]]
uint32x2_t test_vcvtm_u32_f32(float32x2_t a) {
return vcvtm_u32_f32(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vcvtmq_u32_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vcvtmq_u32_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[VCVTM_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VCVTM1_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.fcvtmu.v4i32.v4f32(<4 x float> [[VCVTM_I]]) #2
+// CHECK: [[VCVTM1_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.fcvtmu.v4i32.v4f32(<4 x float> %a) #2
// CHECK: ret <4 x i32> [[VCVTM1_I]]
uint32x4_t test_vcvtmq_u32_f32(float32x4_t a) {
return vcvtmq_u32_f32(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vcvtmq_u64_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vcvtmq_u64_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
-// CHECK: [[VCVTM_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VCVTM1_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.fcvtmu.v2i64.v2f64(<2 x double> [[VCVTM_I]]) #2
+// CHECK: [[VCVTM1_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.fcvtmu.v2i64.v2f64(<2 x double> %a) #2
// CHECK: ret <2 x i64> [[VCVTM1_I]]
uint64x2_t test_vcvtmq_u64_f64(float64x2_t a) {
return vcvtmq_u64_f64(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vcvta_s32_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vcvta_s32_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[VCVTA_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VCVTA1_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.fcvtas.v2i32.v2f32(<2 x float> [[VCVTA_I]]) #2
+// CHECK: [[VCVTA1_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.fcvtas.v2i32.v2f32(<2 x float> %a) #2
// CHECK: ret <2 x i32> [[VCVTA1_I]]
int32x2_t test_vcvta_s32_f32(float32x2_t a) {
return vcvta_s32_f32(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vcvtaq_s32_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vcvtaq_s32_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[VCVTA_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VCVTA1_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.fcvtas.v4i32.v4f32(<4 x float> [[VCVTA_I]]) #2
+// CHECK: [[VCVTA1_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.fcvtas.v4i32.v4f32(<4 x float> %a) #2
// CHECK: ret <4 x i32> [[VCVTA1_I]]
int32x4_t test_vcvtaq_s32_f32(float32x4_t a) {
return vcvtaq_s32_f32(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vcvtaq_s64_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vcvtaq_s64_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
-// CHECK: [[VCVTA_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VCVTA1_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.fcvtas.v2i64.v2f64(<2 x double> [[VCVTA_I]]) #2
+// CHECK: [[VCVTA1_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.fcvtas.v2i64.v2f64(<2 x double> %a) #2
// CHECK: ret <2 x i64> [[VCVTA1_I]]
int64x2_t test_vcvtaq_s64_f64(float64x2_t a) {
return vcvtaq_s64_f64(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vcvta_u32_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vcvta_u32_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[VCVTA_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VCVTA1_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.fcvtau.v2i32.v2f32(<2 x float> [[VCVTA_I]]) #2
+// CHECK: [[VCVTA1_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.fcvtau.v2i32.v2f32(<2 x float> %a) #2
// CHECK: ret <2 x i32> [[VCVTA1_I]]
uint32x2_t test_vcvta_u32_f32(float32x2_t a) {
return vcvta_u32_f32(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vcvtaq_u32_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vcvtaq_u32_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[VCVTA_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VCVTA1_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.fcvtau.v4i32.v4f32(<4 x float> [[VCVTA_I]]) #2
+// CHECK: [[VCVTA1_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.fcvtau.v4i32.v4f32(<4 x float> %a) #2
// CHECK: ret <4 x i32> [[VCVTA1_I]]
uint32x4_t test_vcvtaq_u32_f32(float32x4_t a) {
return vcvtaq_u32_f32(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vcvtaq_u64_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vcvtaq_u64_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
-// CHECK: [[VCVTA_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VCVTA1_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.fcvtau.v2i64.v2f64(<2 x double> [[VCVTA_I]]) #2
+// CHECK: [[VCVTA1_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.fcvtau.v2i64.v2f64(<2 x double> %a) #2
// CHECK: ret <2 x i64> [[VCVTA1_I]]
uint64x2_t test_vcvtaq_u64_f64(float64x2_t a) {
return vcvtaq_u64_f64(a);
}
-// CHECK-LABEL: define <2 x float> @test_vrsqrte_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vrsqrte_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[VRSQRTE_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VRSQRTE_V1_I:%.*]] = call <2 x float> @llvm.aarch64.neon.frsqrte.v2f32(<2 x float> [[VRSQRTE_V_I]]) #2
+// CHECK: [[VRSQRTE_V1_I:%.*]] = call <2 x float> @llvm.aarch64.neon.frsqrte.v2f32(<2 x float> %a) #2
// CHECK: ret <2 x float> [[VRSQRTE_V1_I]]
float32x2_t test_vrsqrte_f32(float32x2_t a) {
return vrsqrte_f32(a);
}
-// CHECK-LABEL: define <4 x float> @test_vrsqrteq_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vrsqrteq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[VRSQRTEQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VRSQRTEQ_V1_I:%.*]] = call <4 x float> @llvm.aarch64.neon.frsqrte.v4f32(<4 x float> [[VRSQRTEQ_V_I]]) #2
+// CHECK: [[VRSQRTEQ_V1_I:%.*]] = call <4 x float> @llvm.aarch64.neon.frsqrte.v4f32(<4 x float> %a) #2
// CHECK: ret <4 x float> [[VRSQRTEQ_V1_I]]
float32x4_t test_vrsqrteq_f32(float32x4_t a) {
return vrsqrteq_f32(a);
}
-// CHECK-LABEL: define <2 x double> @test_vrsqrteq_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vrsqrteq_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
-// CHECK: [[VRSQRTEQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VRSQRTEQ_V1_I:%.*]] = call <2 x double> @llvm.aarch64.neon.frsqrte.v2f64(<2 x double> [[VRSQRTEQ_V_I]]) #2
+// CHECK: [[VRSQRTEQ_V1_I:%.*]] = call <2 x double> @llvm.aarch64.neon.frsqrte.v2f64(<2 x double> %a) #2
// CHECK: ret <2 x double> [[VRSQRTEQ_V1_I]]
float64x2_t test_vrsqrteq_f64(float64x2_t a) {
return vrsqrteq_f64(a);
}
-// CHECK-LABEL: define <2 x float> @test_vrecpe_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vrecpe_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[VRECPE_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VRECPE_V1_I:%.*]] = call <2 x float> @llvm.aarch64.neon.frecpe.v2f32(<2 x float> [[VRECPE_V_I]]) #2
+// CHECK: [[VRECPE_V1_I:%.*]] = call <2 x float> @llvm.aarch64.neon.frecpe.v2f32(<2 x float> %a) #2
// CHECK: ret <2 x float> [[VRECPE_V1_I]]
float32x2_t test_vrecpe_f32(float32x2_t a) {
return vrecpe_f32(a);
}
-// CHECK-LABEL: define <4 x float> @test_vrecpeq_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vrecpeq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[VRECPEQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VRECPEQ_V1_I:%.*]] = call <4 x float> @llvm.aarch64.neon.frecpe.v4f32(<4 x float> [[VRECPEQ_V_I]]) #2
+// CHECK: [[VRECPEQ_V1_I:%.*]] = call <4 x float> @llvm.aarch64.neon.frecpe.v4f32(<4 x float> %a) #2
// CHECK: ret <4 x float> [[VRECPEQ_V1_I]]
float32x4_t test_vrecpeq_f32(float32x4_t a) {
return vrecpeq_f32(a);
}
-// CHECK-LABEL: define <2 x double> @test_vrecpeq_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vrecpeq_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
-// CHECK: [[VRECPEQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VRECPEQ_V1_I:%.*]] = call <2 x double> @llvm.aarch64.neon.frecpe.v2f64(<2 x double> [[VRECPEQ_V_I]]) #2
+// CHECK: [[VRECPEQ_V1_I:%.*]] = call <2 x double> @llvm.aarch64.neon.frecpe.v2f64(<2 x double> %a) #2
// CHECK: ret <2 x double> [[VRECPEQ_V1_I]]
float64x2_t test_vrecpeq_f64(float64x2_t a) {
return vrecpeq_f64(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vrecpe_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vrecpe_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[VRECPE_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VRECPE_V1_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.urecpe.v2i32(<2 x i32> [[VRECPE_V_I]]) #2
+// CHECK: [[VRECPE_V1_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.urecpe.v2i32(<2 x i32> %a) #2
// CHECK: ret <2 x i32> [[VRECPE_V1_I]]
uint32x2_t test_vrecpe_u32(uint32x2_t a) {
return vrecpe_u32(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vrecpeq_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vrecpeq_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
-// CHECK: [[VRECPEQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VRECPEQ_V1_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.urecpe.v4i32(<4 x i32> [[VRECPEQ_V_I]]) #2
+// CHECK: [[VRECPEQ_V1_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.urecpe.v4i32(<4 x i32> %a) #2
// CHECK: ret <4 x i32> [[VRECPEQ_V1_I]]
uint32x4_t test_vrecpeq_u32(uint32x4_t a) {
return vrecpeq_u32(a);
}
-// CHECK-LABEL: define <2 x float> @test_vsqrt_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vsqrt_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VSQRT_I:%.*]] = call <2 x float> @llvm.sqrt.v2f32(<2 x float> [[TMP1]]) #2
+// CHECK: [[VSQRT_I:%.*]] = call <2 x float> @llvm.sqrt.v2f32(<2 x float> %a) #2
// CHECK: ret <2 x float> [[VSQRT_I]]
float32x2_t test_vsqrt_f32(float32x2_t a) {
return vsqrt_f32(a);
}
-// CHECK-LABEL: define <4 x float> @test_vsqrtq_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vsqrtq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VSQRT_I:%.*]] = call <4 x float> @llvm.sqrt.v4f32(<4 x float> [[TMP1]]) #2
+// CHECK: [[VSQRT_I:%.*]] = call <4 x float> @llvm.sqrt.v4f32(<4 x float> %a) #2
// CHECK: ret <4 x float> [[VSQRT_I]]
float32x4_t test_vsqrtq_f32(float32x4_t a) {
return vsqrtq_f32(a);
}
-// CHECK-LABEL: define <2 x double> @test_vsqrtq_f64(<2 x double> %a) #0 {
+// CHECK-LABEL: @test_vsqrtq_f64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x double> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x double>
-// CHECK: [[VSQRT_I:%.*]] = call <2 x double> @llvm.sqrt.v2f64(<2 x double> [[TMP1]]) #2
+// CHECK: [[VSQRT_I:%.*]] = call <2 x double> @llvm.sqrt.v2f64(<2 x double> %a) #2
// CHECK: ret <2 x double> [[VSQRT_I]]
float64x2_t test_vsqrtq_f64(float64x2_t a) {
return vsqrtq_f64(a);
}
-// CHECK-LABEL: define <2 x float> @test_vcvt_f32_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vcvt_f32_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VCVT_I:%.*]] = sitofp <2 x i32> [[TMP1]] to <2 x float>
+// CHECK: [[VCVT_I:%.*]] = sitofp <2 x i32> %a to <2 x float>
// CHECK: ret <2 x float> [[VCVT_I]]
float32x2_t test_vcvt_f32_s32(int32x2_t a) {
return vcvt_f32_s32(a);
}
-// CHECK-LABEL: define <2 x float> @test_vcvt_f32_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vcvt_f32_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VCVT_I:%.*]] = uitofp <2 x i32> [[TMP1]] to <2 x float>
+// CHECK: [[VCVT_I:%.*]] = uitofp <2 x i32> %a to <2 x float>
// CHECK: ret <2 x float> [[VCVT_I]]
float32x2_t test_vcvt_f32_u32(uint32x2_t a) {
return vcvt_f32_u32(a);
}
-// CHECK-LABEL: define <4 x float> @test_vcvtq_f32_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vcvtq_f32_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VCVT_I:%.*]] = sitofp <4 x i32> [[TMP1]] to <4 x float>
+// CHECK: [[VCVT_I:%.*]] = sitofp <4 x i32> %a to <4 x float>
// CHECK: ret <4 x float> [[VCVT_I]]
float32x4_t test_vcvtq_f32_s32(int32x4_t a) {
return vcvtq_f32_s32(a);
}
-// CHECK-LABEL: define <4 x float> @test_vcvtq_f32_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vcvtq_f32_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VCVT_I:%.*]] = uitofp <4 x i32> [[TMP1]] to <4 x float>
+// CHECK: [[VCVT_I:%.*]] = uitofp <4 x i32> %a to <4 x float>
// CHECK: ret <4 x float> [[VCVT_I]]
float32x4_t test_vcvtq_f32_u32(uint32x4_t a) {
return vcvtq_f32_u32(a);
}
-// CHECK-LABEL: define <2 x double> @test_vcvtq_f64_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vcvtq_f64_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VCVT_I:%.*]] = sitofp <2 x i64> [[TMP1]] to <2 x double>
+// CHECK: [[VCVT_I:%.*]] = sitofp <2 x i64> %a to <2 x double>
// CHECK: ret <2 x double> [[VCVT_I]]
float64x2_t test_vcvtq_f64_s64(int64x2_t a) {
return vcvtq_f64_s64(a);
}
-// CHECK-LABEL: define <2 x double> @test_vcvtq_f64_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vcvtq_f64_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VCVT_I:%.*]] = uitofp <2 x i64> [[TMP1]] to <2 x double>
+// CHECK: [[VCVT_I:%.*]] = uitofp <2 x i64> %a to <2 x double>
// CHECK: ret <2 x double> [[VCVT_I]]
float64x2_t test_vcvtq_f64_u64(uint64x2_t a) {
return vcvtq_f64_u64(a);
diff --git a/test/CodeGen/aarch64-neon-perm.c b/test/CodeGen/aarch64-neon-perm.c
index ca9f15d22c67..5b8a99c993fe 100644
--- a/test/CodeGen/aarch64-neon-perm.c
+++ b/test/CodeGen/aarch64-neon-perm.c
@@ -4,889 +4,889 @@
// Test new aarch64 intrinsics and types
#include <arm_neon.h>
-// CHECK-LABEL: define <8 x i8> @test_vuzp1_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vuzp1_s8(
// CHECK: [[SHUFFLE_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: ret <8 x i8> [[SHUFFLE_I]]
int8x8_t test_vuzp1_s8(int8x8_t a, int8x8_t b) {
return vuzp1_s8(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vuzp1q_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vuzp1q_s8(
// CHECK: [[SHUFFLE_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: ret <16 x i8> [[SHUFFLE_I]]
int8x16_t test_vuzp1q_s8(int8x16_t a, int8x16_t b) {
return vuzp1q_s8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vuzp1_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vuzp1_s16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
// CHECK: ret <4 x i16> [[SHUFFLE_I]]
int16x4_t test_vuzp1_s16(int16x4_t a, int16x4_t b) {
return vuzp1_s16(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vuzp1q_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vuzp1q_s16(
// CHECK: [[SHUFFLE_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: ret <8 x i16> [[SHUFFLE_I]]
int16x8_t test_vuzp1q_s16(int16x8_t a, int16x8_t b) {
return vuzp1q_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vuzp1_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vuzp1_s32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <2 x i32> <i32 0, i32 2>
// CHECK: ret <2 x i32> [[SHUFFLE_I]]
int32x2_t test_vuzp1_s32(int32x2_t a, int32x2_t b) {
return vuzp1_s32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vuzp1q_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vuzp1q_s32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
// CHECK: ret <4 x i32> [[SHUFFLE_I]]
int32x4_t test_vuzp1q_s32(int32x4_t a, int32x4_t b) {
return vuzp1q_s32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vuzp1q_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vuzp1q_s64(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x i64> %a, <2 x i64> %b, <2 x i32> <i32 0, i32 2>
// CHECK: ret <2 x i64> [[SHUFFLE_I]]
int64x2_t test_vuzp1q_s64(int64x2_t a, int64x2_t b) {
return vuzp1q_s64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vuzp1_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vuzp1_u8(
// CHECK: [[SHUFFLE_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: ret <8 x i8> [[SHUFFLE_I]]
uint8x8_t test_vuzp1_u8(uint8x8_t a, uint8x8_t b) {
return vuzp1_u8(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vuzp1q_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vuzp1q_u8(
// CHECK: [[SHUFFLE_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: ret <16 x i8> [[SHUFFLE_I]]
uint8x16_t test_vuzp1q_u8(uint8x16_t a, uint8x16_t b) {
return vuzp1q_u8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vuzp1_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vuzp1_u16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
// CHECK: ret <4 x i16> [[SHUFFLE_I]]
uint16x4_t test_vuzp1_u16(uint16x4_t a, uint16x4_t b) {
return vuzp1_u16(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vuzp1q_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vuzp1q_u16(
// CHECK: [[SHUFFLE_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: ret <8 x i16> [[SHUFFLE_I]]
uint16x8_t test_vuzp1q_u16(uint16x8_t a, uint16x8_t b) {
return vuzp1q_u16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vuzp1_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vuzp1_u32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <2 x i32> <i32 0, i32 2>
// CHECK: ret <2 x i32> [[SHUFFLE_I]]
uint32x2_t test_vuzp1_u32(uint32x2_t a, uint32x2_t b) {
return vuzp1_u32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vuzp1q_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vuzp1q_u32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
// CHECK: ret <4 x i32> [[SHUFFLE_I]]
uint32x4_t test_vuzp1q_u32(uint32x4_t a, uint32x4_t b) {
return vuzp1q_u32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vuzp1q_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vuzp1q_u64(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x i64> %a, <2 x i64> %b, <2 x i32> <i32 0, i32 2>
// CHECK: ret <2 x i64> [[SHUFFLE_I]]
uint64x2_t test_vuzp1q_u64(uint64x2_t a, uint64x2_t b) {
return vuzp1q_u64(a, b);
}
-// CHECK-LABEL: define <2 x float> @test_vuzp1_f32(<2 x float> %a, <2 x float> %b) #0 {
+// CHECK-LABEL: @test_vuzp1_f32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x float> %a, <2 x float> %b, <2 x i32> <i32 0, i32 2>
// CHECK: ret <2 x float> [[SHUFFLE_I]]
float32x2_t test_vuzp1_f32(float32x2_t a, float32x2_t b) {
return vuzp1_f32(a, b);
}
-// CHECK-LABEL: define <4 x float> @test_vuzp1q_f32(<4 x float> %a, <4 x float> %b) #0 {
+// CHECK-LABEL: @test_vuzp1q_f32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x float> %a, <4 x float> %b, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
// CHECK: ret <4 x float> [[SHUFFLE_I]]
float32x4_t test_vuzp1q_f32(float32x4_t a, float32x4_t b) {
return vuzp1q_f32(a, b);
}
-// CHECK-LABEL: define <2 x double> @test_vuzp1q_f64(<2 x double> %a, <2 x double> %b) #0 {
+// CHECK-LABEL: @test_vuzp1q_f64(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x double> %a, <2 x double> %b, <2 x i32> <i32 0, i32 2>
// CHECK: ret <2 x double> [[SHUFFLE_I]]
float64x2_t test_vuzp1q_f64(float64x2_t a, float64x2_t b) {
return vuzp1q_f64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vuzp1_p8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vuzp1_p8(
// CHECK: [[SHUFFLE_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: ret <8 x i8> [[SHUFFLE_I]]
poly8x8_t test_vuzp1_p8(poly8x8_t a, poly8x8_t b) {
return vuzp1_p8(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vuzp1q_p8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vuzp1q_p8(
// CHECK: [[SHUFFLE_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: ret <16 x i8> [[SHUFFLE_I]]
poly8x16_t test_vuzp1q_p8(poly8x16_t a, poly8x16_t b) {
return vuzp1q_p8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vuzp1_p16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vuzp1_p16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
// CHECK: ret <4 x i16> [[SHUFFLE_I]]
poly16x4_t test_vuzp1_p16(poly16x4_t a, poly16x4_t b) {
return vuzp1_p16(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vuzp1q_p16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vuzp1q_p16(
// CHECK: [[SHUFFLE_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: ret <8 x i16> [[SHUFFLE_I]]
poly16x8_t test_vuzp1q_p16(poly16x8_t a, poly16x8_t b) {
return vuzp1q_p16(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vuzp2_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vuzp2_s8(
// CHECK: [[SHUFFLE_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: ret <8 x i8> [[SHUFFLE_I]]
int8x8_t test_vuzp2_s8(int8x8_t a, int8x8_t b) {
return vuzp2_s8(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vuzp2q_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vuzp2q_s8(
// CHECK: [[SHUFFLE_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: ret <16 x i8> [[SHUFFLE_I]]
int8x16_t test_vuzp2q_s8(int8x16_t a, int8x16_t b) {
return vuzp2q_s8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vuzp2_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vuzp2_s16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
// CHECK: ret <4 x i16> [[SHUFFLE_I]]
int16x4_t test_vuzp2_s16(int16x4_t a, int16x4_t b) {
return vuzp2_s16(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vuzp2q_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vuzp2q_s16(
// CHECK: [[SHUFFLE_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: ret <8 x i16> [[SHUFFLE_I]]
int16x8_t test_vuzp2q_s16(int16x8_t a, int16x8_t b) {
return vuzp2q_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vuzp2_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vuzp2_s32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <2 x i32> <i32 1, i32 3>
// CHECK: ret <2 x i32> [[SHUFFLE_I]]
int32x2_t test_vuzp2_s32(int32x2_t a, int32x2_t b) {
return vuzp2_s32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vuzp2q_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vuzp2q_s32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
// CHECK: ret <4 x i32> [[SHUFFLE_I]]
int32x4_t test_vuzp2q_s32(int32x4_t a, int32x4_t b) {
return vuzp2q_s32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vuzp2q_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vuzp2q_s64(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x i64> %a, <2 x i64> %b, <2 x i32> <i32 1, i32 3>
// CHECK: ret <2 x i64> [[SHUFFLE_I]]
int64x2_t test_vuzp2q_s64(int64x2_t a, int64x2_t b) {
return vuzp2q_s64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vuzp2_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vuzp2_u8(
// CHECK: [[SHUFFLE_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: ret <8 x i8> [[SHUFFLE_I]]
uint8x8_t test_vuzp2_u8(uint8x8_t a, uint8x8_t b) {
return vuzp2_u8(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vuzp2q_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vuzp2q_u8(
// CHECK: [[SHUFFLE_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: ret <16 x i8> [[SHUFFLE_I]]
uint8x16_t test_vuzp2q_u8(uint8x16_t a, uint8x16_t b) {
return vuzp2q_u8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vuzp2_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vuzp2_u16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
// CHECK: ret <4 x i16> [[SHUFFLE_I]]
uint16x4_t test_vuzp2_u16(uint16x4_t a, uint16x4_t b) {
return vuzp2_u16(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vuzp2q_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vuzp2q_u16(
// CHECK: [[SHUFFLE_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: ret <8 x i16> [[SHUFFLE_I]]
uint16x8_t test_vuzp2q_u16(uint16x8_t a, uint16x8_t b) {
return vuzp2q_u16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vuzp2_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vuzp2_u32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <2 x i32> <i32 1, i32 3>
// CHECK: ret <2 x i32> [[SHUFFLE_I]]
uint32x2_t test_vuzp2_u32(uint32x2_t a, uint32x2_t b) {
return vuzp2_u32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vuzp2q_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vuzp2q_u32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
// CHECK: ret <4 x i32> [[SHUFFLE_I]]
uint32x4_t test_vuzp2q_u32(uint32x4_t a, uint32x4_t b) {
return vuzp2q_u32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vuzp2q_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vuzp2q_u64(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x i64> %a, <2 x i64> %b, <2 x i32> <i32 1, i32 3>
// CHECK: ret <2 x i64> [[SHUFFLE_I]]
uint64x2_t test_vuzp2q_u64(uint64x2_t a, uint64x2_t b) {
return vuzp2q_u64(a, b);
}
-// CHECK-LABEL: define <2 x float> @test_vuzp2_f32(<2 x float> %a, <2 x float> %b) #0 {
+// CHECK-LABEL: @test_vuzp2_f32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x float> %a, <2 x float> %b, <2 x i32> <i32 1, i32 3>
// CHECK: ret <2 x float> [[SHUFFLE_I]]
float32x2_t test_vuzp2_f32(float32x2_t a, float32x2_t b) {
return vuzp2_f32(a, b);
}
-// CHECK-LABEL: define <4 x float> @test_vuzp2q_f32(<4 x float> %a, <4 x float> %b) #0 {
+// CHECK-LABEL: @test_vuzp2q_f32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x float> %a, <4 x float> %b, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
// CHECK: ret <4 x float> [[SHUFFLE_I]]
float32x4_t test_vuzp2q_f32(float32x4_t a, float32x4_t b) {
return vuzp2q_f32(a, b);
}
-// CHECK-LABEL: define <2 x double> @test_vuzp2q_f64(<2 x double> %a, <2 x double> %b) #0 {
+// CHECK-LABEL: @test_vuzp2q_f64(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x double> %a, <2 x double> %b, <2 x i32> <i32 1, i32 3>
// CHECK: ret <2 x double> [[SHUFFLE_I]]
float64x2_t test_vuzp2q_f64(float64x2_t a, float64x2_t b) {
return vuzp2q_f64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vuzp2_p8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vuzp2_p8(
// CHECK: [[SHUFFLE_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: ret <8 x i8> [[SHUFFLE_I]]
poly8x8_t test_vuzp2_p8(poly8x8_t a, poly8x8_t b) {
return vuzp2_p8(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vuzp2q_p8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vuzp2q_p8(
// CHECK: [[SHUFFLE_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: ret <16 x i8> [[SHUFFLE_I]]
poly8x16_t test_vuzp2q_p8(poly8x16_t a, poly8x16_t b) {
return vuzp2q_p8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vuzp2_p16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vuzp2_p16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
// CHECK: ret <4 x i16> [[SHUFFLE_I]]
poly16x4_t test_vuzp2_p16(poly16x4_t a, poly16x4_t b) {
return vuzp2_p16(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vuzp2q_p16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vuzp2q_p16(
// CHECK: [[SHUFFLE_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: ret <8 x i16> [[SHUFFLE_I]]
poly16x8_t test_vuzp2q_p16(poly16x8_t a, poly16x8_t b) {
return vuzp2q_p16(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vzip1_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vzip1_s8(
// CHECK: [[SHUFFLE_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: ret <8 x i8> [[SHUFFLE_I]]
int8x8_t test_vzip1_s8(int8x8_t a, int8x8_t b) {
return vzip1_s8(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vzip1q_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vzip1q_s8(
// CHECK: [[SHUFFLE_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: ret <16 x i8> [[SHUFFLE_I]]
int8x16_t test_vzip1q_s8(int8x16_t a, int8x16_t b) {
return vzip1q_s8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vzip1_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vzip1_s16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 0, i32 4, i32 1, i32 5>
// CHECK: ret <4 x i16> [[SHUFFLE_I]]
int16x4_t test_vzip1_s16(int16x4_t a, int16x4_t b) {
return vzip1_s16(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vzip1q_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vzip1q_s16(
// CHECK: [[SHUFFLE_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: ret <8 x i16> [[SHUFFLE_I]]
int16x8_t test_vzip1q_s16(int16x8_t a, int16x8_t b) {
return vzip1q_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vzip1_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vzip1_s32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <2 x i32> <i32 0, i32 2>
// CHECK: ret <2 x i32> [[SHUFFLE_I]]
int32x2_t test_vzip1_s32(int32x2_t a, int32x2_t b) {
return vzip1_s32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vzip1q_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vzip1q_s32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 0, i32 4, i32 1, i32 5>
// CHECK: ret <4 x i32> [[SHUFFLE_I]]
int32x4_t test_vzip1q_s32(int32x4_t a, int32x4_t b) {
return vzip1q_s32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vzip1q_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vzip1q_s64(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x i64> %a, <2 x i64> %b, <2 x i32> <i32 0, i32 2>
// CHECK: ret <2 x i64> [[SHUFFLE_I]]
int64x2_t test_vzip1q_s64(int64x2_t a, int64x2_t b) {
return vzip1q_s64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vzip1_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vzip1_u8(
// CHECK: [[SHUFFLE_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: ret <8 x i8> [[SHUFFLE_I]]
uint8x8_t test_vzip1_u8(uint8x8_t a, uint8x8_t b) {
return vzip1_u8(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vzip1q_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vzip1q_u8(
// CHECK: [[SHUFFLE_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: ret <16 x i8> [[SHUFFLE_I]]
uint8x16_t test_vzip1q_u8(uint8x16_t a, uint8x16_t b) {
return vzip1q_u8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vzip1_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vzip1_u16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 0, i32 4, i32 1, i32 5>
// CHECK: ret <4 x i16> [[SHUFFLE_I]]
uint16x4_t test_vzip1_u16(uint16x4_t a, uint16x4_t b) {
return vzip1_u16(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vzip1q_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vzip1q_u16(
// CHECK: [[SHUFFLE_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: ret <8 x i16> [[SHUFFLE_I]]
uint16x8_t test_vzip1q_u16(uint16x8_t a, uint16x8_t b) {
return vzip1q_u16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vzip1_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vzip1_u32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <2 x i32> <i32 0, i32 2>
// CHECK: ret <2 x i32> [[SHUFFLE_I]]
uint32x2_t test_vzip1_u32(uint32x2_t a, uint32x2_t b) {
return vzip1_u32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vzip1q_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vzip1q_u32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 0, i32 4, i32 1, i32 5>
// CHECK: ret <4 x i32> [[SHUFFLE_I]]
uint32x4_t test_vzip1q_u32(uint32x4_t a, uint32x4_t b) {
return vzip1q_u32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vzip1q_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vzip1q_u64(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x i64> %a, <2 x i64> %b, <2 x i32> <i32 0, i32 2>
// CHECK: ret <2 x i64> [[SHUFFLE_I]]
uint64x2_t test_vzip1q_u64(uint64x2_t a, uint64x2_t b) {
return vzip1q_u64(a, b);
}
-// CHECK-LABEL: define <2 x float> @test_vzip1_f32(<2 x float> %a, <2 x float> %b) #0 {
+// CHECK-LABEL: @test_vzip1_f32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x float> %a, <2 x float> %b, <2 x i32> <i32 0, i32 2>
// CHECK: ret <2 x float> [[SHUFFLE_I]]
float32x2_t test_vzip1_f32(float32x2_t a, float32x2_t b) {
return vzip1_f32(a, b);
}
-// CHECK-LABEL: define <4 x float> @test_vzip1q_f32(<4 x float> %a, <4 x float> %b) #0 {
+// CHECK-LABEL: @test_vzip1q_f32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x float> %a, <4 x float> %b, <4 x i32> <i32 0, i32 4, i32 1, i32 5>
// CHECK: ret <4 x float> [[SHUFFLE_I]]
float32x4_t test_vzip1q_f32(float32x4_t a, float32x4_t b) {
return vzip1q_f32(a, b);
}
-// CHECK-LABEL: define <2 x double> @test_vzip1q_f64(<2 x double> %a, <2 x double> %b) #0 {
+// CHECK-LABEL: @test_vzip1q_f64(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x double> %a, <2 x double> %b, <2 x i32> <i32 0, i32 2>
// CHECK: ret <2 x double> [[SHUFFLE_I]]
float64x2_t test_vzip1q_f64(float64x2_t a, float64x2_t b) {
return vzip1q_f64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vzip1_p8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vzip1_p8(
// CHECK: [[SHUFFLE_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: ret <8 x i8> [[SHUFFLE_I]]
poly8x8_t test_vzip1_p8(poly8x8_t a, poly8x8_t b) {
return vzip1_p8(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vzip1q_p8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vzip1q_p8(
// CHECK: [[SHUFFLE_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: ret <16 x i8> [[SHUFFLE_I]]
poly8x16_t test_vzip1q_p8(poly8x16_t a, poly8x16_t b) {
return vzip1q_p8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vzip1_p16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vzip1_p16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 0, i32 4, i32 1, i32 5>
// CHECK: ret <4 x i16> [[SHUFFLE_I]]
poly16x4_t test_vzip1_p16(poly16x4_t a, poly16x4_t b) {
return vzip1_p16(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vzip1q_p16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vzip1q_p16(
// CHECK: [[SHUFFLE_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: ret <8 x i16> [[SHUFFLE_I]]
poly16x8_t test_vzip1q_p16(poly16x8_t a, poly16x8_t b) {
return vzip1q_p16(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vzip2_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vzip2_s8(
// CHECK: [[SHUFFLE_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: ret <8 x i8> [[SHUFFLE_I]]
int8x8_t test_vzip2_s8(int8x8_t a, int8x8_t b) {
return vzip2_s8(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vzip2q_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vzip2q_s8(
// CHECK: [[SHUFFLE_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: ret <16 x i8> [[SHUFFLE_I]]
int8x16_t test_vzip2q_s8(int8x16_t a, int8x16_t b) {
return vzip2q_s8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vzip2_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vzip2_s16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 2, i32 6, i32 3, i32 7>
// CHECK: ret <4 x i16> [[SHUFFLE_I]]
int16x4_t test_vzip2_s16(int16x4_t a, int16x4_t b) {
return vzip2_s16(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vzip2q_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vzip2q_s16(
// CHECK: [[SHUFFLE_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: ret <8 x i16> [[SHUFFLE_I]]
int16x8_t test_vzip2q_s16(int16x8_t a, int16x8_t b) {
return vzip2q_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vzip2_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vzip2_s32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <2 x i32> <i32 1, i32 3>
// CHECK: ret <2 x i32> [[SHUFFLE_I]]
int32x2_t test_vzip2_s32(int32x2_t a, int32x2_t b) {
return vzip2_s32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vzip2q_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vzip2q_s32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 2, i32 6, i32 3, i32 7>
// CHECK: ret <4 x i32> [[SHUFFLE_I]]
int32x4_t test_vzip2q_s32(int32x4_t a, int32x4_t b) {
return vzip2q_s32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vzip2q_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vzip2q_s64(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x i64> %a, <2 x i64> %b, <2 x i32> <i32 1, i32 3>
// CHECK: ret <2 x i64> [[SHUFFLE_I]]
int64x2_t test_vzip2q_s64(int64x2_t a, int64x2_t b) {
return vzip2q_s64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vzip2_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vzip2_u8(
// CHECK: [[SHUFFLE_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: ret <8 x i8> [[SHUFFLE_I]]
uint8x8_t test_vzip2_u8(uint8x8_t a, uint8x8_t b) {
return vzip2_u8(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vzip2q_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vzip2q_u8(
// CHECK: [[SHUFFLE_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: ret <16 x i8> [[SHUFFLE_I]]
uint8x16_t test_vzip2q_u8(uint8x16_t a, uint8x16_t b) {
return vzip2q_u8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vzip2_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vzip2_u16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 2, i32 6, i32 3, i32 7>
// CHECK: ret <4 x i16> [[SHUFFLE_I]]
uint16x4_t test_vzip2_u16(uint16x4_t a, uint16x4_t b) {
return vzip2_u16(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vzip2q_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vzip2q_u16(
// CHECK: [[SHUFFLE_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: ret <8 x i16> [[SHUFFLE_I]]
uint16x8_t test_vzip2q_u16(uint16x8_t a, uint16x8_t b) {
return vzip2q_u16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vzip2_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vzip2_u32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <2 x i32> <i32 1, i32 3>
// CHECK: ret <2 x i32> [[SHUFFLE_I]]
uint32x2_t test_vzip2_u32(uint32x2_t a, uint32x2_t b) {
return vzip2_u32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vzip2q_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vzip2q_u32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 2, i32 6, i32 3, i32 7>
// CHECK: ret <4 x i32> [[SHUFFLE_I]]
uint32x4_t test_vzip2q_u32(uint32x4_t a, uint32x4_t b) {
return vzip2q_u32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vzip2q_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vzip2q_u64(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x i64> %a, <2 x i64> %b, <2 x i32> <i32 1, i32 3>
// CHECK: ret <2 x i64> [[SHUFFLE_I]]
uint64x2_t test_vzip2q_u64(uint64x2_t a, uint64x2_t b) {
return vzip2q_u64(a, b);
}
-// CHECK-LABEL: define <2 x float> @test_vzip2_f32(<2 x float> %a, <2 x float> %b) #0 {
+// CHECK-LABEL: @test_vzip2_f32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x float> %a, <2 x float> %b, <2 x i32> <i32 1, i32 3>
// CHECK: ret <2 x float> [[SHUFFLE_I]]
float32x2_t test_vzip2_f32(float32x2_t a, float32x2_t b) {
return vzip2_f32(a, b);
}
-// CHECK-LABEL: define <4 x float> @test_vzip2q_f32(<4 x float> %a, <4 x float> %b) #0 {
+// CHECK-LABEL: @test_vzip2q_f32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x float> %a, <4 x float> %b, <4 x i32> <i32 2, i32 6, i32 3, i32 7>
// CHECK: ret <4 x float> [[SHUFFLE_I]]
float32x4_t test_vzip2q_f32(float32x4_t a, float32x4_t b) {
return vzip2q_f32(a, b);
}
-// CHECK-LABEL: define <2 x double> @test_vzip2q_f64(<2 x double> %a, <2 x double> %b) #0 {
+// CHECK-LABEL: @test_vzip2q_f64(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x double> %a, <2 x double> %b, <2 x i32> <i32 1, i32 3>
// CHECK: ret <2 x double> [[SHUFFLE_I]]
float64x2_t test_vzip2q_f64(float64x2_t a, float64x2_t b) {
return vzip2q_f64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vzip2_p8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vzip2_p8(
// CHECK: [[SHUFFLE_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: ret <8 x i8> [[SHUFFLE_I]]
poly8x8_t test_vzip2_p8(poly8x8_t a, poly8x8_t b) {
return vzip2_p8(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vzip2q_p8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vzip2q_p8(
// CHECK: [[SHUFFLE_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: ret <16 x i8> [[SHUFFLE_I]]
poly8x16_t test_vzip2q_p8(poly8x16_t a, poly8x16_t b) {
return vzip2q_p8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vzip2_p16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vzip2_p16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 2, i32 6, i32 3, i32 7>
// CHECK: ret <4 x i16> [[SHUFFLE_I]]
poly16x4_t test_vzip2_p16(poly16x4_t a, poly16x4_t b) {
return vzip2_p16(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vzip2q_p16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vzip2q_p16(
// CHECK: [[SHUFFLE_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: ret <8 x i16> [[SHUFFLE_I]]
poly16x8_t test_vzip2q_p16(poly16x8_t a, poly16x8_t b) {
return vzip2q_p16(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vtrn1_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vtrn1_s8(
// CHECK: [[SHUFFLE_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: ret <8 x i8> [[SHUFFLE_I]]
int8x8_t test_vtrn1_s8(int8x8_t a, int8x8_t b) {
return vtrn1_s8(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vtrn1q_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vtrn1q_s8(
// CHECK: [[SHUFFLE_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: ret <16 x i8> [[SHUFFLE_I]]
int8x16_t test_vtrn1q_s8(int8x16_t a, int8x16_t b) {
return vtrn1q_s8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vtrn1_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vtrn1_s16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 0, i32 4, i32 2, i32 6>
// CHECK: ret <4 x i16> [[SHUFFLE_I]]
int16x4_t test_vtrn1_s16(int16x4_t a, int16x4_t b) {
return vtrn1_s16(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vtrn1q_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vtrn1q_s16(
// CHECK: [[SHUFFLE_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: ret <8 x i16> [[SHUFFLE_I]]
int16x8_t test_vtrn1q_s16(int16x8_t a, int16x8_t b) {
return vtrn1q_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vtrn1_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vtrn1_s32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <2 x i32> <i32 0, i32 2>
// CHECK: ret <2 x i32> [[SHUFFLE_I]]
int32x2_t test_vtrn1_s32(int32x2_t a, int32x2_t b) {
return vtrn1_s32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vtrn1q_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vtrn1q_s32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 0, i32 4, i32 2, i32 6>
// CHECK: ret <4 x i32> [[SHUFFLE_I]]
int32x4_t test_vtrn1q_s32(int32x4_t a, int32x4_t b) {
return vtrn1q_s32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vtrn1q_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vtrn1q_s64(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x i64> %a, <2 x i64> %b, <2 x i32> <i32 0, i32 2>
// CHECK: ret <2 x i64> [[SHUFFLE_I]]
int64x2_t test_vtrn1q_s64(int64x2_t a, int64x2_t b) {
return vtrn1q_s64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vtrn1_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vtrn1_u8(
// CHECK: [[SHUFFLE_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: ret <8 x i8> [[SHUFFLE_I]]
uint8x8_t test_vtrn1_u8(uint8x8_t a, uint8x8_t b) {
return vtrn1_u8(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vtrn1q_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vtrn1q_u8(
// CHECK: [[SHUFFLE_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: ret <16 x i8> [[SHUFFLE_I]]
uint8x16_t test_vtrn1q_u8(uint8x16_t a, uint8x16_t b) {
return vtrn1q_u8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vtrn1_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vtrn1_u16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 0, i32 4, i32 2, i32 6>
// CHECK: ret <4 x i16> [[SHUFFLE_I]]
uint16x4_t test_vtrn1_u16(uint16x4_t a, uint16x4_t b) {
return vtrn1_u16(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vtrn1q_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vtrn1q_u16(
// CHECK: [[SHUFFLE_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: ret <8 x i16> [[SHUFFLE_I]]
uint16x8_t test_vtrn1q_u16(uint16x8_t a, uint16x8_t b) {
return vtrn1q_u16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vtrn1_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vtrn1_u32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <2 x i32> <i32 0, i32 2>
// CHECK: ret <2 x i32> [[SHUFFLE_I]]
uint32x2_t test_vtrn1_u32(uint32x2_t a, uint32x2_t b) {
return vtrn1_u32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vtrn1q_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vtrn1q_u32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 0, i32 4, i32 2, i32 6>
// CHECK: ret <4 x i32> [[SHUFFLE_I]]
uint32x4_t test_vtrn1q_u32(uint32x4_t a, uint32x4_t b) {
return vtrn1q_u32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vtrn1q_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vtrn1q_u64(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x i64> %a, <2 x i64> %b, <2 x i32> <i32 0, i32 2>
// CHECK: ret <2 x i64> [[SHUFFLE_I]]
uint64x2_t test_vtrn1q_u64(uint64x2_t a, uint64x2_t b) {
return vtrn1q_u64(a, b);
}
-// CHECK-LABEL: define <2 x float> @test_vtrn1_f32(<2 x float> %a, <2 x float> %b) #0 {
+// CHECK-LABEL: @test_vtrn1_f32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x float> %a, <2 x float> %b, <2 x i32> <i32 0, i32 2>
// CHECK: ret <2 x float> [[SHUFFLE_I]]
float32x2_t test_vtrn1_f32(float32x2_t a, float32x2_t b) {
return vtrn1_f32(a, b);
}
-// CHECK-LABEL: define <4 x float> @test_vtrn1q_f32(<4 x float> %a, <4 x float> %b) #0 {
+// CHECK-LABEL: @test_vtrn1q_f32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x float> %a, <4 x float> %b, <4 x i32> <i32 0, i32 4, i32 2, i32 6>
// CHECK: ret <4 x float> [[SHUFFLE_I]]
float32x4_t test_vtrn1q_f32(float32x4_t a, float32x4_t b) {
return vtrn1q_f32(a, b);
}
-// CHECK-LABEL: define <2 x double> @test_vtrn1q_f64(<2 x double> %a, <2 x double> %b) #0 {
+// CHECK-LABEL: @test_vtrn1q_f64(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x double> %a, <2 x double> %b, <2 x i32> <i32 0, i32 2>
// CHECK: ret <2 x double> [[SHUFFLE_I]]
float64x2_t test_vtrn1q_f64(float64x2_t a, float64x2_t b) {
return vtrn1q_f64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vtrn1_p8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vtrn1_p8(
// CHECK: [[SHUFFLE_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: ret <8 x i8> [[SHUFFLE_I]]
poly8x8_t test_vtrn1_p8(poly8x8_t a, poly8x8_t b) {
return vtrn1_p8(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vtrn1q_p8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vtrn1q_p8(
// CHECK: [[SHUFFLE_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: ret <16 x i8> [[SHUFFLE_I]]
poly8x16_t test_vtrn1q_p8(poly8x16_t a, poly8x16_t b) {
return vtrn1q_p8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vtrn1_p16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vtrn1_p16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 0, i32 4, i32 2, i32 6>
// CHECK: ret <4 x i16> [[SHUFFLE_I]]
poly16x4_t test_vtrn1_p16(poly16x4_t a, poly16x4_t b) {
return vtrn1_p16(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vtrn1q_p16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vtrn1q_p16(
// CHECK: [[SHUFFLE_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: ret <8 x i16> [[SHUFFLE_I]]
poly16x8_t test_vtrn1q_p16(poly16x8_t a, poly16x8_t b) {
return vtrn1q_p16(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vtrn2_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vtrn2_s8(
// CHECK: [[SHUFFLE_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: ret <8 x i8> [[SHUFFLE_I]]
int8x8_t test_vtrn2_s8(int8x8_t a, int8x8_t b) {
return vtrn2_s8(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vtrn2q_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vtrn2q_s8(
// CHECK: [[SHUFFLE_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: ret <16 x i8> [[SHUFFLE_I]]
int8x16_t test_vtrn2q_s8(int8x16_t a, int8x16_t b) {
return vtrn2q_s8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vtrn2_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vtrn2_s16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 1, i32 5, i32 3, i32 7>
// CHECK: ret <4 x i16> [[SHUFFLE_I]]
int16x4_t test_vtrn2_s16(int16x4_t a, int16x4_t b) {
return vtrn2_s16(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vtrn2q_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vtrn2q_s16(
// CHECK: [[SHUFFLE_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: ret <8 x i16> [[SHUFFLE_I]]
int16x8_t test_vtrn2q_s16(int16x8_t a, int16x8_t b) {
return vtrn2q_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vtrn2_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vtrn2_s32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <2 x i32> <i32 1, i32 3>
// CHECK: ret <2 x i32> [[SHUFFLE_I]]
int32x2_t test_vtrn2_s32(int32x2_t a, int32x2_t b) {
return vtrn2_s32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vtrn2q_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vtrn2q_s32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 1, i32 5, i32 3, i32 7>
// CHECK: ret <4 x i32> [[SHUFFLE_I]]
int32x4_t test_vtrn2q_s32(int32x4_t a, int32x4_t b) {
return vtrn2q_s32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vtrn2q_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vtrn2q_s64(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x i64> %a, <2 x i64> %b, <2 x i32> <i32 1, i32 3>
// CHECK: ret <2 x i64> [[SHUFFLE_I]]
int64x2_t test_vtrn2q_s64(int64x2_t a, int64x2_t b) {
return vtrn2q_s64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vtrn2_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vtrn2_u8(
// CHECK: [[SHUFFLE_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: ret <8 x i8> [[SHUFFLE_I]]
uint8x8_t test_vtrn2_u8(uint8x8_t a, uint8x8_t b) {
return vtrn2_u8(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vtrn2q_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vtrn2q_u8(
// CHECK: [[SHUFFLE_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: ret <16 x i8> [[SHUFFLE_I]]
uint8x16_t test_vtrn2q_u8(uint8x16_t a, uint8x16_t b) {
return vtrn2q_u8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vtrn2_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vtrn2_u16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 1, i32 5, i32 3, i32 7>
// CHECK: ret <4 x i16> [[SHUFFLE_I]]
uint16x4_t test_vtrn2_u16(uint16x4_t a, uint16x4_t b) {
return vtrn2_u16(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vtrn2q_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vtrn2q_u16(
// CHECK: [[SHUFFLE_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: ret <8 x i16> [[SHUFFLE_I]]
uint16x8_t test_vtrn2q_u16(uint16x8_t a, uint16x8_t b) {
return vtrn2q_u16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vtrn2_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vtrn2_u32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <2 x i32> <i32 1, i32 3>
// CHECK: ret <2 x i32> [[SHUFFLE_I]]
uint32x2_t test_vtrn2_u32(uint32x2_t a, uint32x2_t b) {
return vtrn2_u32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vtrn2q_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vtrn2q_u32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 1, i32 5, i32 3, i32 7>
// CHECK: ret <4 x i32> [[SHUFFLE_I]]
uint32x4_t test_vtrn2q_u32(uint32x4_t a, uint32x4_t b) {
return vtrn2q_u32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vtrn2q_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vtrn2q_u64(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x i64> %a, <2 x i64> %b, <2 x i32> <i32 1, i32 3>
// CHECK: ret <2 x i64> [[SHUFFLE_I]]
uint64x2_t test_vtrn2q_u64(uint64x2_t a, uint64x2_t b) {
return vtrn2q_u64(a, b);
}
-// CHECK-LABEL: define <2 x float> @test_vtrn2_f32(<2 x float> %a, <2 x float> %b) #0 {
+// CHECK-LABEL: @test_vtrn2_f32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x float> %a, <2 x float> %b, <2 x i32> <i32 1, i32 3>
// CHECK: ret <2 x float> [[SHUFFLE_I]]
float32x2_t test_vtrn2_f32(float32x2_t a, float32x2_t b) {
return vtrn2_f32(a, b);
}
-// CHECK-LABEL: define <4 x float> @test_vtrn2q_f32(<4 x float> %a, <4 x float> %b) #0 {
+// CHECK-LABEL: @test_vtrn2q_f32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x float> %a, <4 x float> %b, <4 x i32> <i32 1, i32 5, i32 3, i32 7>
// CHECK: ret <4 x float> [[SHUFFLE_I]]
float32x4_t test_vtrn2q_f32(float32x4_t a, float32x4_t b) {
return vtrn2q_f32(a, b);
}
-// CHECK-LABEL: define <2 x double> @test_vtrn2q_f64(<2 x double> %a, <2 x double> %b) #0 {
+// CHECK-LABEL: @test_vtrn2q_f64(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x double> %a, <2 x double> %b, <2 x i32> <i32 1, i32 3>
// CHECK: ret <2 x double> [[SHUFFLE_I]]
float64x2_t test_vtrn2q_f64(float64x2_t a, float64x2_t b) {
return vtrn2q_f64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vtrn2_p8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vtrn2_p8(
// CHECK: [[SHUFFLE_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: ret <8 x i8> [[SHUFFLE_I]]
poly8x8_t test_vtrn2_p8(poly8x8_t a, poly8x8_t b) {
return vtrn2_p8(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vtrn2q_p8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vtrn2q_p8(
// CHECK: [[SHUFFLE_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: ret <16 x i8> [[SHUFFLE_I]]
poly8x16_t test_vtrn2q_p8(poly8x16_t a, poly8x16_t b) {
return vtrn2q_p8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vtrn2_p16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vtrn2_p16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 1, i32 5, i32 3, i32 7>
// CHECK: ret <4 x i16> [[SHUFFLE_I]]
poly16x4_t test_vtrn2_p16(poly16x4_t a, poly16x4_t b) {
return vtrn2_p16(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vtrn2q_p16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vtrn2q_p16(
// CHECK: [[SHUFFLE_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: ret <8 x i16> [[SHUFFLE_I]]
poly16x8_t test_vtrn2q_p16(poly16x8_t a, poly16x8_t b) {
return vtrn2q_p16(a, b);
}
-// CHECK-LABEL: define %struct.int8x8x2_t @test_vuzp_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// 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
@@ -910,7 +910,7 @@ int8x8x2_t test_vuzp_s8(int8x8_t a, int8x8_t b) {
return vuzp_s8(a, b);
}
-// CHECK-LABEL: define %struct.int16x4x2_t @test_vuzp_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// 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
@@ -918,26 +918,25 @@ int8x8x2_t test_vuzp_s8(int8x8_t a, int8x8_t b) {
// 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: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[TMP5:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VUZP_I:%.*]] = shufflevector <4 x i16> [[TMP4]], <4 x i16> [[TMP5]], <4 x i32> <i32 0, i32 2, i32 4, i32 6>
+// 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]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
-// CHECK: [[VUZP1_I:%.*]] = shufflevector <4 x i16> [[TMP4]], <4 x i16> [[TMP5]], <4 x i32> <i32 1, i32 3, i32 5, i32 7>
-// CHECK: store <4 x i16> [[VUZP1_I]], <4 x i16>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.int16x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.int16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP7]], i8* [[TMP8]], i64 16, i32 8, i1 false) #2
-// CHECK: [[TMP9:%.*]] = load %struct.int16x4x2_t, %struct.int16x4x2_t* [[RETVAL_I]], align 8
-// CHECK: [[TMP10:%.*]] = getelementptr inbounds %struct.int16x4x2_t, %struct.int16x4x2_t* [[RETVAL]], i32 0, i32 0
-// CHECK: [[TMP11:%.*]] = extractvalue %struct.int16x4x2_t [[TMP9]], 0
-// CHECK: store [2 x <4 x i16>] [[TMP11]], [2 x <4 x i16>]* [[TMP10]], align 8
-// CHECK: [[TMP12:%.*]] = load %struct.int16x4x2_t, %struct.int16x4x2_t* [[RETVAL]], align 8
-// CHECK: ret %struct.int16x4x2_t [[TMP12]]
+// 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
+// CHECK: store [2 x <4 x i16>] [[TMP9]], [2 x <4 x i16>]* [[TMP8]], align 8
+// CHECK: [[TMP10:%.*]] = load %struct.int16x4x2_t, %struct.int16x4x2_t* [[RETVAL]], align 8
+// CHECK: ret %struct.int16x4x2_t [[TMP10]]
int16x4x2_t test_vuzp_s16(int16x4_t a, int16x4_t b) {
return vuzp_s16(a, b);
}
-// CHECK-LABEL: define %struct.int32x2x2_t @test_vuzp_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+
+// 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
@@ -945,26 +944,25 @@ int16x4x2_t test_vuzp_s16(int16x4_t a, int16x4_t b) {
// 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: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[TMP5:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VUZP_I:%.*]] = shufflevector <2 x i32> [[TMP4]], <2 x i32> [[TMP5]], <2 x i32> <i32 0, i32 2>
+// 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]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <2 x i32>, <2 x i32>* [[TMP3]], i32 1
-// CHECK: [[VUZP1_I:%.*]] = shufflevector <2 x i32> [[TMP4]], <2 x i32> [[TMP5]], <2 x i32> <i32 1, i32 3>
-// CHECK: store <2 x i32> [[VUZP1_I]], <2 x i32>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.int32x2x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.int32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP7]], i8* [[TMP8]], i64 16, i32 8, i1 false) #2
-// CHECK: [[TMP9:%.*]] = load %struct.int32x2x2_t, %struct.int32x2x2_t* [[RETVAL_I]], align 8
-// CHECK: [[TMP10:%.*]] = getelementptr inbounds %struct.int32x2x2_t, %struct.int32x2x2_t* [[RETVAL]], i32 0, i32 0
-// CHECK: [[TMP11:%.*]] = extractvalue %struct.int32x2x2_t [[TMP9]], 0
-// CHECK: store [2 x <2 x i32>] [[TMP11]], [2 x <2 x i32>]* [[TMP10]], align 8
-// CHECK: [[TMP12:%.*]] = load %struct.int32x2x2_t, %struct.int32x2x2_t* [[RETVAL]], align 8
-// CHECK: ret %struct.int32x2x2_t [[TMP12]]
+// 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
+// CHECK: store [2 x <2 x i32>] [[TMP9]], [2 x <2 x i32>]* [[TMP8]], align 8
+// CHECK: [[TMP10:%.*]] = load %struct.int32x2x2_t, %struct.int32x2x2_t* [[RETVAL]], align 8
+// CHECK: ret %struct.int32x2x2_t [[TMP10]]
int32x2x2_t test_vuzp_s32(int32x2_t a, int32x2_t b) {
return vuzp_s32(a, b);
}
-// CHECK-LABEL: define %struct.uint8x8x2_t @test_vuzp_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+
+// 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
@@ -987,7 +985,8 @@ int32x2x2_t test_vuzp_s32(int32x2_t a, int32x2_t b) {
uint8x8x2_t test_vuzp_u8(uint8x8_t a, uint8x8_t b) {
return vuzp_u8(a, b);
}
-// CHECK-LABEL: define %struct.uint16x4x2_t @test_vuzp_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+
+// 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
@@ -995,26 +994,25 @@ uint8x8x2_t test_vuzp_u8(uint8x8_t a, uint8x8_t b) {
// 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: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[TMP5:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VUZP_I:%.*]] = shufflevector <4 x i16> [[TMP4]], <4 x i16> [[TMP5]], <4 x i32> <i32 0, i32 2, i32 4, i32 6>
+// 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]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
-// CHECK: [[VUZP1_I:%.*]] = shufflevector <4 x i16> [[TMP4]], <4 x i16> [[TMP5]], <4 x i32> <i32 1, i32 3, i32 5, i32 7>
-// CHECK: store <4 x i16> [[VUZP1_I]], <4 x i16>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.uint16x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP7]], i8* [[TMP8]], i64 16, i32 8, i1 false) #2
-// CHECK: [[TMP9:%.*]] = load %struct.uint16x4x2_t, %struct.uint16x4x2_t* [[RETVAL_I]], align 8
-// CHECK: [[TMP10:%.*]] = getelementptr inbounds %struct.uint16x4x2_t, %struct.uint16x4x2_t* [[RETVAL]], i32 0, i32 0
-// CHECK: [[TMP11:%.*]] = extractvalue %struct.uint16x4x2_t [[TMP9]], 0
-// CHECK: store [2 x <4 x i16>] [[TMP11]], [2 x <4 x i16>]* [[TMP10]], align 8
-// CHECK: [[TMP12:%.*]] = load %struct.uint16x4x2_t, %struct.uint16x4x2_t* [[RETVAL]], align 8
-// CHECK: ret %struct.uint16x4x2_t [[TMP12]]
+// 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
+// CHECK: store [2 x <4 x i16>] [[TMP9]], [2 x <4 x i16>]* [[TMP8]], align 8
+// CHECK: [[TMP10:%.*]] = load %struct.uint16x4x2_t, %struct.uint16x4x2_t* [[RETVAL]], align 8
+// CHECK: ret %struct.uint16x4x2_t [[TMP10]]
uint16x4x2_t test_vuzp_u16(uint16x4_t a, uint16x4_t b) {
return vuzp_u16(a, b);
}
-// CHECK-LABEL: define %struct.uint32x2x2_t @test_vuzp_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+
+// 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
@@ -1022,26 +1020,25 @@ uint16x4x2_t test_vuzp_u16(uint16x4_t a, uint16x4_t b) {
// 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: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[TMP5:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VUZP_I:%.*]] = shufflevector <2 x i32> [[TMP4]], <2 x i32> [[TMP5]], <2 x i32> <i32 0, i32 2>
+// 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]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <2 x i32>, <2 x i32>* [[TMP3]], i32 1
-// CHECK: [[VUZP1_I:%.*]] = shufflevector <2 x i32> [[TMP4]], <2 x i32> [[TMP5]], <2 x i32> <i32 1, i32 3>
-// CHECK: store <2 x i32> [[VUZP1_I]], <2 x i32>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.uint32x2x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP7]], i8* [[TMP8]], i64 16, i32 8, i1 false) #2
-// CHECK: [[TMP9:%.*]] = load %struct.uint32x2x2_t, %struct.uint32x2x2_t* [[RETVAL_I]], align 8
-// CHECK: [[TMP10:%.*]] = getelementptr inbounds %struct.uint32x2x2_t, %struct.uint32x2x2_t* [[RETVAL]], i32 0, i32 0
-// CHECK: [[TMP11:%.*]] = extractvalue %struct.uint32x2x2_t [[TMP9]], 0
-// CHECK: store [2 x <2 x i32>] [[TMP11]], [2 x <2 x i32>]* [[TMP10]], align 8
-// CHECK: [[TMP12:%.*]] = load %struct.uint32x2x2_t, %struct.uint32x2x2_t* [[RETVAL]], align 8
-// CHECK: ret %struct.uint32x2x2_t [[TMP12]]
+// 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
+// CHECK: store [2 x <2 x i32>] [[TMP9]], [2 x <2 x i32>]* [[TMP8]], align 8
+// CHECK: [[TMP10:%.*]] = load %struct.uint32x2x2_t, %struct.uint32x2x2_t* [[RETVAL]], align 8
+// CHECK: ret %struct.uint32x2x2_t [[TMP10]]
uint32x2x2_t test_vuzp_u32(uint32x2_t a, uint32x2_t b) {
return vuzp_u32(a, b);
}
-// CHECK-LABEL: define %struct.float32x2x2_t @test_vuzp_f32(<2 x float> %a, <2 x float> %b) #0 {
+
+// 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
@@ -1049,26 +1046,25 @@ uint32x2x2_t test_vuzp_u32(uint32x2_t a, uint32x2_t b) {
// 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: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK: [[TMP5:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x float>
-// CHECK: [[VUZP_I:%.*]] = shufflevector <2 x float> [[TMP4]], <2 x float> [[TMP5]], <2 x i32> <i32 0, i32 2>
+// 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]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <2 x float>, <2 x float>* [[TMP3]], i32 1
-// CHECK: [[VUZP1_I:%.*]] = shufflevector <2 x float> [[TMP4]], <2 x float> [[TMP5]], <2 x i32> <i32 1, i32 3>
-// CHECK: store <2 x float> [[VUZP1_I]], <2 x float>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.float32x2x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.float32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP7]], i8* [[TMP8]], i64 16, i32 8, i1 false) #2
-// CHECK: [[TMP9:%.*]] = load %struct.float32x2x2_t, %struct.float32x2x2_t* [[RETVAL_I]], align 8
-// CHECK: [[TMP10:%.*]] = getelementptr inbounds %struct.float32x2x2_t, %struct.float32x2x2_t* [[RETVAL]], i32 0, i32 0
-// CHECK: [[TMP11:%.*]] = extractvalue %struct.float32x2x2_t [[TMP9]], 0
-// CHECK: store [2 x <2 x float>] [[TMP11]], [2 x <2 x float>]* [[TMP10]], align 8
-// CHECK: [[TMP12:%.*]] = load %struct.float32x2x2_t, %struct.float32x2x2_t* [[RETVAL]], align 8
-// CHECK: ret %struct.float32x2x2_t [[TMP12]]
+// 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
+// CHECK: store [2 x <2 x float>] [[TMP9]], [2 x <2 x float>]* [[TMP8]], align 8
+// CHECK: [[TMP10:%.*]] = load %struct.float32x2x2_t, %struct.float32x2x2_t* [[RETVAL]], align 8
+// CHECK: ret %struct.float32x2x2_t [[TMP10]]
float32x2x2_t test_vuzp_f32(float32x2_t a, float32x2_t b) {
return vuzp_f32(a, b);
}
-// CHECK-LABEL: define %struct.poly8x8x2_t @test_vuzp_p8(<8 x i8> %a, <8 x i8> %b) #0 {
+
+// 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
@@ -1091,7 +1087,8 @@ float32x2x2_t test_vuzp_f32(float32x2_t a, float32x2_t b) {
poly8x8x2_t test_vuzp_p8(poly8x8_t a, poly8x8_t b) {
return vuzp_p8(a, b);
}
-// CHECK-LABEL: define %struct.poly16x4x2_t @test_vuzp_p16(<4 x i16> %a, <4 x i16> %b) #0 {
+
+// 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
@@ -1099,26 +1096,25 @@ poly8x8x2_t test_vuzp_p8(poly8x8_t a, poly8x8_t b) {
// 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: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[TMP5:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VUZP_I:%.*]] = shufflevector <4 x i16> [[TMP4]], <4 x i16> [[TMP5]], <4 x i32> <i32 0, i32 2, i32 4, i32 6>
+// 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]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
-// CHECK: [[VUZP1_I:%.*]] = shufflevector <4 x i16> [[TMP4]], <4 x i16> [[TMP5]], <4 x i32> <i32 1, i32 3, i32 5, i32 7>
-// CHECK: store <4 x i16> [[VUZP1_I]], <4 x i16>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.poly16x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP7]], i8* [[TMP8]], i64 16, i32 8, i1 false) #2
-// CHECK: [[TMP9:%.*]] = load %struct.poly16x4x2_t, %struct.poly16x4x2_t* [[RETVAL_I]], align 8
-// CHECK: [[TMP10:%.*]] = getelementptr inbounds %struct.poly16x4x2_t, %struct.poly16x4x2_t* [[RETVAL]], i32 0, i32 0
-// CHECK: [[TMP11:%.*]] = extractvalue %struct.poly16x4x2_t [[TMP9]], 0
-// CHECK: store [2 x <4 x i16>] [[TMP11]], [2 x <4 x i16>]* [[TMP10]], align 8
-// CHECK: [[TMP12:%.*]] = load %struct.poly16x4x2_t, %struct.poly16x4x2_t* [[RETVAL]], align 8
-// CHECK: ret %struct.poly16x4x2_t [[TMP12]]
+// 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
+// CHECK: store [2 x <4 x i16>] [[TMP9]], [2 x <4 x i16>]* [[TMP8]], align 8
+// CHECK: [[TMP10:%.*]] = load %struct.poly16x4x2_t, %struct.poly16x4x2_t* [[RETVAL]], align 8
+// CHECK: ret %struct.poly16x4x2_t [[TMP10]]
poly16x4x2_t test_vuzp_p16(poly16x4_t a, poly16x4_t b) {
return vuzp_p16(a, b);
}
-// CHECK-LABEL: define %struct.int8x16x2_t @test_vuzpq_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+
+// 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
@@ -1141,7 +1137,8 @@ poly16x4x2_t test_vuzp_p16(poly16x4_t a, poly16x4_t b) {
int8x16x2_t test_vuzpq_s8(int8x16_t a, int8x16_t b) {
return vuzpq_s8(a, b);
}
-// CHECK-LABEL: define %struct.int16x8x2_t @test_vuzpq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+
+// 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
@@ -1149,26 +1146,25 @@ int8x16x2_t test_vuzpq_s8(int8x16_t a, int8x16_t b) {
// 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: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <8 x i16>
-// CHECK: [[VUZP_I:%.*]] = shufflevector <8 x i16> [[TMP4]], <8 x i16> [[TMP5]], <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
+// 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]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
-// CHECK: [[VUZP1_I:%.*]] = shufflevector <8 x i16> [[TMP4]], <8 x i16> [[TMP5]], <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>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.int16x8x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.int16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP7]], i8* [[TMP8]], i64 32, i32 16, i1 false) #2
-// CHECK: [[TMP9:%.*]] = load %struct.int16x8x2_t, %struct.int16x8x2_t* [[RETVAL_I]], align 16
-// CHECK: [[TMP10:%.*]] = getelementptr inbounds %struct.int16x8x2_t, %struct.int16x8x2_t* [[RETVAL]], i32 0, i32 0
-// CHECK: [[TMP11:%.*]] = extractvalue %struct.int16x8x2_t [[TMP9]], 0
-// CHECK: store [2 x <8 x i16>] [[TMP11]], [2 x <8 x i16>]* [[TMP10]], align 16
-// CHECK: [[TMP12:%.*]] = load %struct.int16x8x2_t, %struct.int16x8x2_t* [[RETVAL]], align 16
-// CHECK: ret %struct.int16x8x2_t [[TMP12]]
+// 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
+// CHECK: store [2 x <8 x i16>] [[TMP9]], [2 x <8 x i16>]* [[TMP8]], align 16
+// CHECK: [[TMP10:%.*]] = load %struct.int16x8x2_t, %struct.int16x8x2_t* [[RETVAL]], align 16
+// CHECK: ret %struct.int16x8x2_t [[TMP10]]
int16x8x2_t test_vuzpq_s16(int16x8_t a, int16x8_t b) {
return vuzpq_s16(a, b);
}
-// CHECK-LABEL: define %struct.int32x4x2_t @test_vuzpq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+
+// 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
@@ -1176,26 +1172,25 @@ int16x8x2_t test_vuzpq_s16(int16x8_t a, int16x8_t b) {
// 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: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <4 x i32>
-// CHECK: [[VUZP_I:%.*]] = shufflevector <4 x i32> [[TMP4]], <4 x i32> [[TMP5]], <4 x i32> <i32 0, i32 2, i32 4, i32 6>
+// 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]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <4 x i32>, <4 x i32>* [[TMP3]], i32 1
-// CHECK: [[VUZP1_I:%.*]] = shufflevector <4 x i32> [[TMP4]], <4 x i32> [[TMP5]], <4 x i32> <i32 1, i32 3, i32 5, i32 7>
-// CHECK: store <4 x i32> [[VUZP1_I]], <4 x i32>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.int32x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.int32x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP7]], i8* [[TMP8]], i64 32, i32 16, i1 false) #2
-// CHECK: [[TMP9:%.*]] = load %struct.int32x4x2_t, %struct.int32x4x2_t* [[RETVAL_I]], align 16
-// CHECK: [[TMP10:%.*]] = getelementptr inbounds %struct.int32x4x2_t, %struct.int32x4x2_t* [[RETVAL]], i32 0, i32 0
-// CHECK: [[TMP11:%.*]] = extractvalue %struct.int32x4x2_t [[TMP9]], 0
-// CHECK: store [2 x <4 x i32>] [[TMP11]], [2 x <4 x i32>]* [[TMP10]], align 16
-// CHECK: [[TMP12:%.*]] = load %struct.int32x4x2_t, %struct.int32x4x2_t* [[RETVAL]], align 16
-// CHECK: ret %struct.int32x4x2_t [[TMP12]]
+// 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
+// CHECK: store [2 x <4 x i32>] [[TMP9]], [2 x <4 x i32>]* [[TMP8]], align 16
+// CHECK: [[TMP10:%.*]] = load %struct.int32x4x2_t, %struct.int32x4x2_t* [[RETVAL]], align 16
+// CHECK: ret %struct.int32x4x2_t [[TMP10]]
int32x4x2_t test_vuzpq_s32(int32x4_t a, int32x4_t b) {
return vuzpq_s32(a, b);
}
-// CHECK-LABEL: define %struct.uint8x16x2_t @test_vuzpq_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+
+// 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
@@ -1218,7 +1213,8 @@ int32x4x2_t test_vuzpq_s32(int32x4_t a, int32x4_t b) {
uint8x16x2_t test_vuzpq_u8(uint8x16_t a, uint8x16_t b) {
return vuzpq_u8(a, b);
}
-// CHECK-LABEL: define %struct.uint16x8x2_t @test_vuzpq_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+
+// 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
@@ -1226,26 +1222,25 @@ uint8x16x2_t test_vuzpq_u8(uint8x16_t a, uint8x16_t b) {
// 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: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <8 x i16>
-// CHECK: [[VUZP_I:%.*]] = shufflevector <8 x i16> [[TMP4]], <8 x i16> [[TMP5]], <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
+// 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]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
-// CHECK: [[VUZP1_I:%.*]] = shufflevector <8 x i16> [[TMP4]], <8 x i16> [[TMP5]], <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>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.uint16x8x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP7]], i8* [[TMP8]], i64 32, i32 16, i1 false) #2
-// CHECK: [[TMP9:%.*]] = load %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[RETVAL_I]], align 16
-// CHECK: [[TMP10:%.*]] = getelementptr inbounds %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[RETVAL]], i32 0, i32 0
-// CHECK: [[TMP11:%.*]] = extractvalue %struct.uint16x8x2_t [[TMP9]], 0
-// CHECK: store [2 x <8 x i16>] [[TMP11]], [2 x <8 x i16>]* [[TMP10]], align 16
-// CHECK: [[TMP12:%.*]] = load %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[RETVAL]], align 16
-// CHECK: ret %struct.uint16x8x2_t [[TMP12]]
+// 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
+// CHECK: store [2 x <8 x i16>] [[TMP9]], [2 x <8 x i16>]* [[TMP8]], align 16
+// CHECK: [[TMP10:%.*]] = load %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[RETVAL]], align 16
+// CHECK: ret %struct.uint16x8x2_t [[TMP10]]
uint16x8x2_t test_vuzpq_u16(uint16x8_t a, uint16x8_t b) {
return vuzpq_u16(a, b);
}
-// CHECK-LABEL: define %struct.uint32x4x2_t @test_vuzpq_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+
+// 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
@@ -1253,26 +1248,25 @@ uint16x8x2_t test_vuzpq_u16(uint16x8_t a, uint16x8_t b) {
// 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: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <4 x i32>
-// CHECK: [[VUZP_I:%.*]] = shufflevector <4 x i32> [[TMP4]], <4 x i32> [[TMP5]], <4 x i32> <i32 0, i32 2, i32 4, i32 6>
+// 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]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <4 x i32>, <4 x i32>* [[TMP3]], i32 1
-// CHECK: [[VUZP1_I:%.*]] = shufflevector <4 x i32> [[TMP4]], <4 x i32> [[TMP5]], <4 x i32> <i32 1, i32 3, i32 5, i32 7>
-// CHECK: store <4 x i32> [[VUZP1_I]], <4 x i32>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.uint32x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP7]], i8* [[TMP8]], i64 32, i32 16, i1 false) #2
-// CHECK: [[TMP9:%.*]] = load %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[RETVAL_I]], align 16
-// CHECK: [[TMP10:%.*]] = getelementptr inbounds %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[RETVAL]], i32 0, i32 0
-// CHECK: [[TMP11:%.*]] = extractvalue %struct.uint32x4x2_t [[TMP9]], 0
-// CHECK: store [2 x <4 x i32>] [[TMP11]], [2 x <4 x i32>]* [[TMP10]], align 16
-// CHECK: [[TMP12:%.*]] = load %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[RETVAL]], align 16
-// CHECK: ret %struct.uint32x4x2_t [[TMP12]]
+// 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
+// CHECK: store [2 x <4 x i32>] [[TMP9]], [2 x <4 x i32>]* [[TMP8]], align 16
+// CHECK: [[TMP10:%.*]] = load %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[RETVAL]], align 16
+// CHECK: ret %struct.uint32x4x2_t [[TMP10]]
uint32x4x2_t test_vuzpq_u32(uint32x4_t a, uint32x4_t b) {
return vuzpq_u32(a, b);
}
-// CHECK-LABEL: define %struct.float32x4x2_t @test_vuzpq_f32(<4 x float> %a, <4 x float> %b) #0 {
+
+// 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
@@ -1280,26 +1274,25 @@ uint32x4x2_t test_vuzpq_u32(uint32x4_t a, uint32x4_t b) {
// 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: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <4 x float>
-// CHECK: [[VUZP_I:%.*]] = shufflevector <4 x float> [[TMP4]], <4 x float> [[TMP5]], <4 x i32> <i32 0, i32 2, i32 4, i32 6>
+// 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]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <4 x float>, <4 x float>* [[TMP3]], i32 1
-// CHECK: [[VUZP1_I:%.*]] = shufflevector <4 x float> [[TMP4]], <4 x float> [[TMP5]], <4 x i32> <i32 1, i32 3, i32 5, i32 7>
-// CHECK: store <4 x float> [[VUZP1_I]], <4 x float>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.float32x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.float32x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP7]], i8* [[TMP8]], i64 32, i32 16, i1 false) #2
-// CHECK: [[TMP9:%.*]] = load %struct.float32x4x2_t, %struct.float32x4x2_t* [[RETVAL_I]], align 16
-// CHECK: [[TMP10:%.*]] = getelementptr inbounds %struct.float32x4x2_t, %struct.float32x4x2_t* [[RETVAL]], i32 0, i32 0
-// CHECK: [[TMP11:%.*]] = extractvalue %struct.float32x4x2_t [[TMP9]], 0
-// CHECK: store [2 x <4 x float>] [[TMP11]], [2 x <4 x float>]* [[TMP10]], align 16
-// CHECK: [[TMP12:%.*]] = load %struct.float32x4x2_t, %struct.float32x4x2_t* [[RETVAL]], align 16
-// CHECK: ret %struct.float32x4x2_t [[TMP12]]
+// 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
+// CHECK: store [2 x <4 x float>] [[TMP9]], [2 x <4 x float>]* [[TMP8]], align 16
+// CHECK: [[TMP10:%.*]] = load %struct.float32x4x2_t, %struct.float32x4x2_t* [[RETVAL]], align 16
+// CHECK: ret %struct.float32x4x2_t [[TMP10]]
float32x4x2_t test_vuzpq_f32(float32x4_t a, float32x4_t b) {
return vuzpq_f32(a, b);
}
-// CHECK-LABEL: define %struct.poly8x16x2_t @test_vuzpq_p8(<16 x i8> %a, <16 x i8> %b) #0 {
+
+// 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
@@ -1322,7 +1315,8 @@ float32x4x2_t test_vuzpq_f32(float32x4_t a, float32x4_t b) {
poly8x16x2_t test_vuzpq_p8(poly8x16_t a, poly8x16_t b) {
return vuzpq_p8(a, b);
}
-// CHECK-LABEL: define %struct.poly16x8x2_t @test_vuzpq_p16(<8 x i16> %a, <8 x i16> %b) #0 {
+
+// 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
@@ -1330,27 +1324,25 @@ poly8x16x2_t test_vuzpq_p8(poly8x16_t a, poly8x16_t b) {
// 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: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <8 x i16>
-// CHECK: [[VUZP_I:%.*]] = shufflevector <8 x i16> [[TMP4]], <8 x i16> [[TMP5]], <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
+// 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]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
-// CHECK: [[VUZP1_I:%.*]] = shufflevector <8 x i16> [[TMP4]], <8 x i16> [[TMP5]], <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>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.poly16x8x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP7]], i8* [[TMP8]], i64 32, i32 16, i1 false) #2
-// CHECK: [[TMP9:%.*]] = load %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[RETVAL_I]], align 16
-// CHECK: [[TMP10:%.*]] = getelementptr inbounds %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[RETVAL]], i32 0, i32 0
-// CHECK: [[TMP11:%.*]] = extractvalue %struct.poly16x8x2_t [[TMP9]], 0
-// CHECK: store [2 x <8 x i16>] [[TMP11]], [2 x <8 x i16>]* [[TMP10]], align 16
-// CHECK: [[TMP12:%.*]] = load %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[RETVAL]], align 16
-// CHECK: ret %struct.poly16x8x2_t [[TMP12]]
+// 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
+// CHECK: store [2 x <8 x i16>] [[TMP9]], [2 x <8 x i16>]* [[TMP8]], align 16
+// CHECK: [[TMP10:%.*]] = load %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[RETVAL]], align 16
+// CHECK: ret %struct.poly16x8x2_t [[TMP10]]
poly16x8x2_t test_vuzpq_p16(poly16x8_t a, poly16x8_t b) {
return vuzpq_p16(a, b);
}
-// CHECK-LABEL: define %struct.int8x8x2_t @test_vzip_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// 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
@@ -1374,7 +1366,7 @@ int8x8x2_t test_vzip_s8(int8x8_t a, int8x8_t b) {
return vzip_s8(a, b);
}
-// CHECK-LABEL: define %struct.int16x4x2_t @test_vzip_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// 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
@@ -1382,26 +1374,25 @@ int8x8x2_t test_vzip_s8(int8x8_t a, int8x8_t b) {
// 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: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[TMP5:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VZIP_I:%.*]] = shufflevector <4 x i16> [[TMP4]], <4 x i16> [[TMP5]], <4 x i32> <i32 0, i32 4, i32 1, i32 5>
+// 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]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
-// CHECK: [[VZIP1_I:%.*]] = shufflevector <4 x i16> [[TMP4]], <4 x i16> [[TMP5]], <4 x i32> <i32 2, i32 6, i32 3, i32 7>
-// CHECK: store <4 x i16> [[VZIP1_I]], <4 x i16>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.int16x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.int16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP7]], i8* [[TMP8]], i64 16, i32 8, i1 false) #2
-// CHECK: [[TMP9:%.*]] = load %struct.int16x4x2_t, %struct.int16x4x2_t* [[RETVAL_I]], align 8
-// CHECK: [[TMP10:%.*]] = getelementptr inbounds %struct.int16x4x2_t, %struct.int16x4x2_t* [[RETVAL]], i32 0, i32 0
-// CHECK: [[TMP11:%.*]] = extractvalue %struct.int16x4x2_t [[TMP9]], 0
-// CHECK: store [2 x <4 x i16>] [[TMP11]], [2 x <4 x i16>]* [[TMP10]], align 8
-// CHECK: [[TMP12:%.*]] = load %struct.int16x4x2_t, %struct.int16x4x2_t* [[RETVAL]], align 8
-// CHECK: ret %struct.int16x4x2_t [[TMP12]]
+// 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
+// CHECK: store [2 x <4 x i16>] [[TMP9]], [2 x <4 x i16>]* [[TMP8]], align 8
+// CHECK: [[TMP10:%.*]] = load %struct.int16x4x2_t, %struct.int16x4x2_t* [[RETVAL]], align 8
+// CHECK: ret %struct.int16x4x2_t [[TMP10]]
int16x4x2_t test_vzip_s16(int16x4_t a, int16x4_t b) {
return vzip_s16(a, b);
}
-// CHECK-LABEL: define %struct.int32x2x2_t @test_vzip_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+
+// 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
@@ -1409,26 +1400,25 @@ int16x4x2_t test_vzip_s16(int16x4_t a, int16x4_t b) {
// 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: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[TMP5:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VZIP_I:%.*]] = shufflevector <2 x i32> [[TMP4]], <2 x i32> [[TMP5]], <2 x i32> <i32 0, i32 2>
+// 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]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <2 x i32>, <2 x i32>* [[TMP3]], i32 1
-// CHECK: [[VZIP1_I:%.*]] = shufflevector <2 x i32> [[TMP4]], <2 x i32> [[TMP5]], <2 x i32> <i32 1, i32 3>
-// CHECK: store <2 x i32> [[VZIP1_I]], <2 x i32>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.int32x2x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.int32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP7]], i8* [[TMP8]], i64 16, i32 8, i1 false) #2
-// CHECK: [[TMP9:%.*]] = load %struct.int32x2x2_t, %struct.int32x2x2_t* [[RETVAL_I]], align 8
-// CHECK: [[TMP10:%.*]] = getelementptr inbounds %struct.int32x2x2_t, %struct.int32x2x2_t* [[RETVAL]], i32 0, i32 0
-// CHECK: [[TMP11:%.*]] = extractvalue %struct.int32x2x2_t [[TMP9]], 0
-// CHECK: store [2 x <2 x i32>] [[TMP11]], [2 x <2 x i32>]* [[TMP10]], align 8
-// CHECK: [[TMP12:%.*]] = load %struct.int32x2x2_t, %struct.int32x2x2_t* [[RETVAL]], align 8
-// CHECK: ret %struct.int32x2x2_t [[TMP12]]
+// 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
+// CHECK: store [2 x <2 x i32>] [[TMP9]], [2 x <2 x i32>]* [[TMP8]], align 8
+// CHECK: [[TMP10:%.*]] = load %struct.int32x2x2_t, %struct.int32x2x2_t* [[RETVAL]], align 8
+// CHECK: ret %struct.int32x2x2_t [[TMP10]]
int32x2x2_t test_vzip_s32(int32x2_t a, int32x2_t b) {
return vzip_s32(a, b);
}
-// CHECK-LABEL: define %struct.uint8x8x2_t @test_vzip_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+
+// 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
@@ -1451,7 +1441,8 @@ int32x2x2_t test_vzip_s32(int32x2_t a, int32x2_t b) {
uint8x8x2_t test_vzip_u8(uint8x8_t a, uint8x8_t b) {
return vzip_u8(a, b);
}
-// CHECK-LABEL: define %struct.uint16x4x2_t @test_vzip_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+
+// 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
@@ -1459,26 +1450,25 @@ uint8x8x2_t test_vzip_u8(uint8x8_t a, uint8x8_t b) {
// 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: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[TMP5:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VZIP_I:%.*]] = shufflevector <4 x i16> [[TMP4]], <4 x i16> [[TMP5]], <4 x i32> <i32 0, i32 4, i32 1, i32 5>
+// 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]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
-// CHECK: [[VZIP1_I:%.*]] = shufflevector <4 x i16> [[TMP4]], <4 x i16> [[TMP5]], <4 x i32> <i32 2, i32 6, i32 3, i32 7>
-// CHECK: store <4 x i16> [[VZIP1_I]], <4 x i16>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.uint16x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP7]], i8* [[TMP8]], i64 16, i32 8, i1 false) #2
-// CHECK: [[TMP9:%.*]] = load %struct.uint16x4x2_t, %struct.uint16x4x2_t* [[RETVAL_I]], align 8
-// CHECK: [[TMP10:%.*]] = getelementptr inbounds %struct.uint16x4x2_t, %struct.uint16x4x2_t* [[RETVAL]], i32 0, i32 0
-// CHECK: [[TMP11:%.*]] = extractvalue %struct.uint16x4x2_t [[TMP9]], 0
-// CHECK: store [2 x <4 x i16>] [[TMP11]], [2 x <4 x i16>]* [[TMP10]], align 8
-// CHECK: [[TMP12:%.*]] = load %struct.uint16x4x2_t, %struct.uint16x4x2_t* [[RETVAL]], align 8
-// CHECK: ret %struct.uint16x4x2_t [[TMP12]]
+// 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
+// CHECK: store [2 x <4 x i16>] [[TMP9]], [2 x <4 x i16>]* [[TMP8]], align 8
+// CHECK: [[TMP10:%.*]] = load %struct.uint16x4x2_t, %struct.uint16x4x2_t* [[RETVAL]], align 8
+// CHECK: ret %struct.uint16x4x2_t [[TMP10]]
uint16x4x2_t test_vzip_u16(uint16x4_t a, uint16x4_t b) {
return vzip_u16(a, b);
}
-// CHECK-LABEL: define %struct.uint32x2x2_t @test_vzip_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+
+// 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
@@ -1486,26 +1476,25 @@ uint16x4x2_t test_vzip_u16(uint16x4_t a, uint16x4_t b) {
// 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: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[TMP5:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VZIP_I:%.*]] = shufflevector <2 x i32> [[TMP4]], <2 x i32> [[TMP5]], <2 x i32> <i32 0, i32 2>
+// 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]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <2 x i32>, <2 x i32>* [[TMP3]], i32 1
-// CHECK: [[VZIP1_I:%.*]] = shufflevector <2 x i32> [[TMP4]], <2 x i32> [[TMP5]], <2 x i32> <i32 1, i32 3>
-// CHECK: store <2 x i32> [[VZIP1_I]], <2 x i32>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.uint32x2x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP7]], i8* [[TMP8]], i64 16, i32 8, i1 false) #2
-// CHECK: [[TMP9:%.*]] = load %struct.uint32x2x2_t, %struct.uint32x2x2_t* [[RETVAL_I]], align 8
-// CHECK: [[TMP10:%.*]] = getelementptr inbounds %struct.uint32x2x2_t, %struct.uint32x2x2_t* [[RETVAL]], i32 0, i32 0
-// CHECK: [[TMP11:%.*]] = extractvalue %struct.uint32x2x2_t [[TMP9]], 0
-// CHECK: store [2 x <2 x i32>] [[TMP11]], [2 x <2 x i32>]* [[TMP10]], align 8
-// CHECK: [[TMP12:%.*]] = load %struct.uint32x2x2_t, %struct.uint32x2x2_t* [[RETVAL]], align 8
-// CHECK: ret %struct.uint32x2x2_t [[TMP12]]
+// 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
+// CHECK: store [2 x <2 x i32>] [[TMP9]], [2 x <2 x i32>]* [[TMP8]], align 8
+// CHECK: [[TMP10:%.*]] = load %struct.uint32x2x2_t, %struct.uint32x2x2_t* [[RETVAL]], align 8
+// CHECK: ret %struct.uint32x2x2_t [[TMP10]]
uint32x2x2_t test_vzip_u32(uint32x2_t a, uint32x2_t b) {
return vzip_u32(a, b);
}
-// CHECK-LABEL: define %struct.float32x2x2_t @test_vzip_f32(<2 x float> %a, <2 x float> %b) #0 {
+
+// 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
@@ -1513,26 +1502,25 @@ uint32x2x2_t test_vzip_u32(uint32x2_t a, uint32x2_t b) {
// 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: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK: [[TMP5:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x float>
-// CHECK: [[VZIP_I:%.*]] = shufflevector <2 x float> [[TMP4]], <2 x float> [[TMP5]], <2 x i32> <i32 0, i32 2>
+// 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]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <2 x float>, <2 x float>* [[TMP3]], i32 1
-// CHECK: [[VZIP1_I:%.*]] = shufflevector <2 x float> [[TMP4]], <2 x float> [[TMP5]], <2 x i32> <i32 1, i32 3>
-// CHECK: store <2 x float> [[VZIP1_I]], <2 x float>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.float32x2x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.float32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP7]], i8* [[TMP8]], i64 16, i32 8, i1 false) #2
-// CHECK: [[TMP9:%.*]] = load %struct.float32x2x2_t, %struct.float32x2x2_t* [[RETVAL_I]], align 8
-// CHECK: [[TMP10:%.*]] = getelementptr inbounds %struct.float32x2x2_t, %struct.float32x2x2_t* [[RETVAL]], i32 0, i32 0
-// CHECK: [[TMP11:%.*]] = extractvalue %struct.float32x2x2_t [[TMP9]], 0
-// CHECK: store [2 x <2 x float>] [[TMP11]], [2 x <2 x float>]* [[TMP10]], align 8
-// CHECK: [[TMP12:%.*]] = load %struct.float32x2x2_t, %struct.float32x2x2_t* [[RETVAL]], align 8
-// CHECK: ret %struct.float32x2x2_t [[TMP12]]
+// 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
+// CHECK: store [2 x <2 x float>] [[TMP9]], [2 x <2 x float>]* [[TMP8]], align 8
+// CHECK: [[TMP10:%.*]] = load %struct.float32x2x2_t, %struct.float32x2x2_t* [[RETVAL]], align 8
+// CHECK: ret %struct.float32x2x2_t [[TMP10]]
float32x2x2_t test_vzip_f32(float32x2_t a, float32x2_t b) {
return vzip_f32(a, b);
}
-// CHECK-LABEL: define %struct.poly8x8x2_t @test_vzip_p8(<8 x i8> %a, <8 x i8> %b) #0 {
+
+// 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
@@ -1555,7 +1543,8 @@ float32x2x2_t test_vzip_f32(float32x2_t a, float32x2_t b) {
poly8x8x2_t test_vzip_p8(poly8x8_t a, poly8x8_t b) {
return vzip_p8(a, b);
}
-// CHECK-LABEL: define %struct.poly16x4x2_t @test_vzip_p16(<4 x i16> %a, <4 x i16> %b) #0 {
+
+// 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
@@ -1563,26 +1552,25 @@ poly8x8x2_t test_vzip_p8(poly8x8_t a, poly8x8_t b) {
// 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: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[TMP5:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VZIP_I:%.*]] = shufflevector <4 x i16> [[TMP4]], <4 x i16> [[TMP5]], <4 x i32> <i32 0, i32 4, i32 1, i32 5>
+// 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]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
-// CHECK: [[VZIP1_I:%.*]] = shufflevector <4 x i16> [[TMP4]], <4 x i16> [[TMP5]], <4 x i32> <i32 2, i32 6, i32 3, i32 7>
-// CHECK: store <4 x i16> [[VZIP1_I]], <4 x i16>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.poly16x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP7]], i8* [[TMP8]], i64 16, i32 8, i1 false) #2
-// CHECK: [[TMP9:%.*]] = load %struct.poly16x4x2_t, %struct.poly16x4x2_t* [[RETVAL_I]], align 8
-// CHECK: [[TMP10:%.*]] = getelementptr inbounds %struct.poly16x4x2_t, %struct.poly16x4x2_t* [[RETVAL]], i32 0, i32 0
-// CHECK: [[TMP11:%.*]] = extractvalue %struct.poly16x4x2_t [[TMP9]], 0
-// CHECK: store [2 x <4 x i16>] [[TMP11]], [2 x <4 x i16>]* [[TMP10]], align 8
-// CHECK: [[TMP12:%.*]] = load %struct.poly16x4x2_t, %struct.poly16x4x2_t* [[RETVAL]], align 8
-// CHECK: ret %struct.poly16x4x2_t [[TMP12]]
+// 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
+// CHECK: store [2 x <4 x i16>] [[TMP9]], [2 x <4 x i16>]* [[TMP8]], align 8
+// CHECK: [[TMP10:%.*]] = load %struct.poly16x4x2_t, %struct.poly16x4x2_t* [[RETVAL]], align 8
+// CHECK: ret %struct.poly16x4x2_t [[TMP10]]
poly16x4x2_t test_vzip_p16(poly16x4_t a, poly16x4_t b) {
return vzip_p16(a, b);
}
-// CHECK-LABEL: define %struct.int8x16x2_t @test_vzipq_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+
+// 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
@@ -1605,7 +1593,8 @@ poly16x4x2_t test_vzip_p16(poly16x4_t a, poly16x4_t b) {
int8x16x2_t test_vzipq_s8(int8x16_t a, int8x16_t b) {
return vzipq_s8(a, b);
}
-// CHECK-LABEL: define %struct.int16x8x2_t @test_vzipq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+
+// 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
@@ -1613,26 +1602,25 @@ int8x16x2_t test_vzipq_s8(int8x16_t a, int8x16_t b) {
// 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: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <8 x i16>
-// CHECK: [[VZIP_I:%.*]] = shufflevector <8 x i16> [[TMP4]], <8 x i16> [[TMP5]], <8 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11>
+// 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]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
-// CHECK: [[VZIP1_I:%.*]] = shufflevector <8 x i16> [[TMP4]], <8 x i16> [[TMP5]], <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>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.int16x8x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.int16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP7]], i8* [[TMP8]], i64 32, i32 16, i1 false) #2
-// CHECK: [[TMP9:%.*]] = load %struct.int16x8x2_t, %struct.int16x8x2_t* [[RETVAL_I]], align 16
-// CHECK: [[TMP10:%.*]] = getelementptr inbounds %struct.int16x8x2_t, %struct.int16x8x2_t* [[RETVAL]], i32 0, i32 0
-// CHECK: [[TMP11:%.*]] = extractvalue %struct.int16x8x2_t [[TMP9]], 0
-// CHECK: store [2 x <8 x i16>] [[TMP11]], [2 x <8 x i16>]* [[TMP10]], align 16
-// CHECK: [[TMP12:%.*]] = load %struct.int16x8x2_t, %struct.int16x8x2_t* [[RETVAL]], align 16
-// CHECK: ret %struct.int16x8x2_t [[TMP12]]
+// 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
+// CHECK: store [2 x <8 x i16>] [[TMP9]], [2 x <8 x i16>]* [[TMP8]], align 16
+// CHECK: [[TMP10:%.*]] = load %struct.int16x8x2_t, %struct.int16x8x2_t* [[RETVAL]], align 16
+// CHECK: ret %struct.int16x8x2_t [[TMP10]]
int16x8x2_t test_vzipq_s16(int16x8_t a, int16x8_t b) {
return vzipq_s16(a, b);
}
-// CHECK-LABEL: define %struct.int32x4x2_t @test_vzipq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+
+// 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
@@ -1640,26 +1628,25 @@ int16x8x2_t test_vzipq_s16(int16x8_t a, int16x8_t b) {
// 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: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <4 x i32>
-// CHECK: [[VZIP_I:%.*]] = shufflevector <4 x i32> [[TMP4]], <4 x i32> [[TMP5]], <4 x i32> <i32 0, i32 4, i32 1, i32 5>
+// 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]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <4 x i32>, <4 x i32>* [[TMP3]], i32 1
-// CHECK: [[VZIP1_I:%.*]] = shufflevector <4 x i32> [[TMP4]], <4 x i32> [[TMP5]], <4 x i32> <i32 2, i32 6, i32 3, i32 7>
-// CHECK: store <4 x i32> [[VZIP1_I]], <4 x i32>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.int32x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.int32x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP7]], i8* [[TMP8]], i64 32, i32 16, i1 false) #2
-// CHECK: [[TMP9:%.*]] = load %struct.int32x4x2_t, %struct.int32x4x2_t* [[RETVAL_I]], align 16
-// CHECK: [[TMP10:%.*]] = getelementptr inbounds %struct.int32x4x2_t, %struct.int32x4x2_t* [[RETVAL]], i32 0, i32 0
-// CHECK: [[TMP11:%.*]] = extractvalue %struct.int32x4x2_t [[TMP9]], 0
-// CHECK: store [2 x <4 x i32>] [[TMP11]], [2 x <4 x i32>]* [[TMP10]], align 16
-// CHECK: [[TMP12:%.*]] = load %struct.int32x4x2_t, %struct.int32x4x2_t* [[RETVAL]], align 16
-// CHECK: ret %struct.int32x4x2_t [[TMP12]]
+// 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
+// CHECK: store [2 x <4 x i32>] [[TMP9]], [2 x <4 x i32>]* [[TMP8]], align 16
+// CHECK: [[TMP10:%.*]] = load %struct.int32x4x2_t, %struct.int32x4x2_t* [[RETVAL]], align 16
+// CHECK: ret %struct.int32x4x2_t [[TMP10]]
int32x4x2_t test_vzipq_s32(int32x4_t a, int32x4_t b) {
return vzipq_s32(a, b);
}
-// CHECK-LABEL: define %struct.uint8x16x2_t @test_vzipq_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+
+// 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
@@ -1682,7 +1669,8 @@ int32x4x2_t test_vzipq_s32(int32x4_t a, int32x4_t b) {
uint8x16x2_t test_vzipq_u8(uint8x16_t a, uint8x16_t b) {
return vzipq_u8(a, b);
}
-// CHECK-LABEL: define %struct.uint16x8x2_t @test_vzipq_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+
+// 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
@@ -1690,26 +1678,25 @@ uint8x16x2_t test_vzipq_u8(uint8x16_t a, uint8x16_t b) {
// 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: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <8 x i16>
-// CHECK: [[VZIP_I:%.*]] = shufflevector <8 x i16> [[TMP4]], <8 x i16> [[TMP5]], <8 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11>
+// 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]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
-// CHECK: [[VZIP1_I:%.*]] = shufflevector <8 x i16> [[TMP4]], <8 x i16> [[TMP5]], <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>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.uint16x8x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP7]], i8* [[TMP8]], i64 32, i32 16, i1 false) #2
-// CHECK: [[TMP9:%.*]] = load %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[RETVAL_I]], align 16
-// CHECK: [[TMP10:%.*]] = getelementptr inbounds %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[RETVAL]], i32 0, i32 0
-// CHECK: [[TMP11:%.*]] = extractvalue %struct.uint16x8x2_t [[TMP9]], 0
-// CHECK: store [2 x <8 x i16>] [[TMP11]], [2 x <8 x i16>]* [[TMP10]], align 16
-// CHECK: [[TMP12:%.*]] = load %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[RETVAL]], align 16
-// CHECK: ret %struct.uint16x8x2_t [[TMP12]]
+// 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
+// CHECK: store [2 x <8 x i16>] [[TMP9]], [2 x <8 x i16>]* [[TMP8]], align 16
+// CHECK: [[TMP10:%.*]] = load %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[RETVAL]], align 16
+// CHECK: ret %struct.uint16x8x2_t [[TMP10]]
uint16x8x2_t test_vzipq_u16(uint16x8_t a, uint16x8_t b) {
return vzipq_u16(a, b);
}
-// CHECK-LABEL: define %struct.uint32x4x2_t @test_vzipq_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+
+// 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
@@ -1717,26 +1704,25 @@ uint16x8x2_t test_vzipq_u16(uint16x8_t a, uint16x8_t b) {
// 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: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <4 x i32>
-// CHECK: [[VZIP_I:%.*]] = shufflevector <4 x i32> [[TMP4]], <4 x i32> [[TMP5]], <4 x i32> <i32 0, i32 4, i32 1, i32 5>
+// 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]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <4 x i32>, <4 x i32>* [[TMP3]], i32 1
-// CHECK: [[VZIP1_I:%.*]] = shufflevector <4 x i32> [[TMP4]], <4 x i32> [[TMP5]], <4 x i32> <i32 2, i32 6, i32 3, i32 7>
-// CHECK: store <4 x i32> [[VZIP1_I]], <4 x i32>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.uint32x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP7]], i8* [[TMP8]], i64 32, i32 16, i1 false) #2
-// CHECK: [[TMP9:%.*]] = load %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[RETVAL_I]], align 16
-// CHECK: [[TMP10:%.*]] = getelementptr inbounds %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[RETVAL]], i32 0, i32 0
-// CHECK: [[TMP11:%.*]] = extractvalue %struct.uint32x4x2_t [[TMP9]], 0
-// CHECK: store [2 x <4 x i32>] [[TMP11]], [2 x <4 x i32>]* [[TMP10]], align 16
-// CHECK: [[TMP12:%.*]] = load %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[RETVAL]], align 16
-// CHECK: ret %struct.uint32x4x2_t [[TMP12]]
+// 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
+// CHECK: store [2 x <4 x i32>] [[TMP9]], [2 x <4 x i32>]* [[TMP8]], align 16
+// CHECK: [[TMP10:%.*]] = load %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[RETVAL]], align 16
+// CHECK: ret %struct.uint32x4x2_t [[TMP10]]
uint32x4x2_t test_vzipq_u32(uint32x4_t a, uint32x4_t b) {
return vzipq_u32(a, b);
}
-// CHECK-LABEL: define %struct.float32x4x2_t @test_vzipq_f32(<4 x float> %a, <4 x float> %b) #0 {
+
+// 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
@@ -1744,26 +1730,25 @@ uint32x4x2_t test_vzipq_u32(uint32x4_t a, uint32x4_t b) {
// 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: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <4 x float>
-// CHECK: [[VZIP_I:%.*]] = shufflevector <4 x float> [[TMP4]], <4 x float> [[TMP5]], <4 x i32> <i32 0, i32 4, i32 1, i32 5>
+// 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]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <4 x float>, <4 x float>* [[TMP3]], i32 1
-// CHECK: [[VZIP1_I:%.*]] = shufflevector <4 x float> [[TMP4]], <4 x float> [[TMP5]], <4 x i32> <i32 2, i32 6, i32 3, i32 7>
-// CHECK: store <4 x float> [[VZIP1_I]], <4 x float>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.float32x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.float32x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP7]], i8* [[TMP8]], i64 32, i32 16, i1 false) #2
-// CHECK: [[TMP9:%.*]] = load %struct.float32x4x2_t, %struct.float32x4x2_t* [[RETVAL_I]], align 16
-// CHECK: [[TMP10:%.*]] = getelementptr inbounds %struct.float32x4x2_t, %struct.float32x4x2_t* [[RETVAL]], i32 0, i32 0
-// CHECK: [[TMP11:%.*]] = extractvalue %struct.float32x4x2_t [[TMP9]], 0
-// CHECK: store [2 x <4 x float>] [[TMP11]], [2 x <4 x float>]* [[TMP10]], align 16
-// CHECK: [[TMP12:%.*]] = load %struct.float32x4x2_t, %struct.float32x4x2_t* [[RETVAL]], align 16
-// CHECK: ret %struct.float32x4x2_t [[TMP12]]
+// 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
+// CHECK: store [2 x <4 x float>] [[TMP9]], [2 x <4 x float>]* [[TMP8]], align 16
+// CHECK: [[TMP10:%.*]] = load %struct.float32x4x2_t, %struct.float32x4x2_t* [[RETVAL]], align 16
+// CHECK: ret %struct.float32x4x2_t [[TMP10]]
float32x4x2_t test_vzipq_f32(float32x4_t a, float32x4_t b) {
return vzipq_f32(a, b);
}
-// CHECK-LABEL: define %struct.poly8x16x2_t @test_vzipq_p8(<16 x i8> %a, <16 x i8> %b) #0 {
+
+// 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
@@ -1786,7 +1771,8 @@ float32x4x2_t test_vzipq_f32(float32x4_t a, float32x4_t b) {
poly8x16x2_t test_vzipq_p8(poly8x16_t a, poly8x16_t b) {
return vzipq_p8(a, b);
}
-// CHECK-LABEL: define %struct.poly16x8x2_t @test_vzipq_p16(<8 x i16> %a, <8 x i16> %b) #0 {
+
+// 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
@@ -1794,27 +1780,25 @@ poly8x16x2_t test_vzipq_p8(poly8x16_t a, poly8x16_t b) {
// 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: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <8 x i16>
-// CHECK: [[VZIP_I:%.*]] = shufflevector <8 x i16> [[TMP4]], <8 x i16> [[TMP5]], <8 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11>
+// 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]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
-// CHECK: [[VZIP1_I:%.*]] = shufflevector <8 x i16> [[TMP4]], <8 x i16> [[TMP5]], <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>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.poly16x8x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP7]], i8* [[TMP8]], i64 32, i32 16, i1 false) #2
-// CHECK: [[TMP9:%.*]] = load %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[RETVAL_I]], align 16
-// CHECK: [[TMP10:%.*]] = getelementptr inbounds %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[RETVAL]], i32 0, i32 0
-// CHECK: [[TMP11:%.*]] = extractvalue %struct.poly16x8x2_t [[TMP9]], 0
-// CHECK: store [2 x <8 x i16>] [[TMP11]], [2 x <8 x i16>]* [[TMP10]], align 16
-// CHECK: [[TMP12:%.*]] = load %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[RETVAL]], align 16
-// CHECK: ret %struct.poly16x8x2_t [[TMP12]]
+// 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
+// CHECK: store [2 x <8 x i16>] [[TMP9]], [2 x <8 x i16>]* [[TMP8]], align 16
+// CHECK: [[TMP10:%.*]] = load %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[RETVAL]], align 16
+// CHECK: ret %struct.poly16x8x2_t [[TMP10]]
poly16x8x2_t test_vzipq_p16(poly16x8_t a, poly16x8_t b) {
return vzipq_p16(a, b);
}
-// CHECK-LABEL: define %struct.int8x8x2_t @test_vtrn_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// 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
@@ -1838,7 +1822,7 @@ int8x8x2_t test_vtrn_s8(int8x8_t a, int8x8_t b) {
return vtrn_s8(a, b);
}
-// CHECK-LABEL: define %struct.int16x4x2_t @test_vtrn_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// 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
@@ -1846,26 +1830,25 @@ int8x8x2_t test_vtrn_s8(int8x8_t a, int8x8_t b) {
// 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: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[TMP5:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VTRN_I:%.*]] = shufflevector <4 x i16> [[TMP4]], <4 x i16> [[TMP5]], <4 x i32> <i32 0, i32 4, i32 2, i32 6>
+// 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]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
-// CHECK: [[VTRN1_I:%.*]] = shufflevector <4 x i16> [[TMP4]], <4 x i16> [[TMP5]], <4 x i32> <i32 1, i32 5, i32 3, i32 7>
-// CHECK: store <4 x i16> [[VTRN1_I]], <4 x i16>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.int16x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.int16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP7]], i8* [[TMP8]], i64 16, i32 8, i1 false) #2
-// CHECK: [[TMP9:%.*]] = load %struct.int16x4x2_t, %struct.int16x4x2_t* [[RETVAL_I]], align 8
-// CHECK: [[TMP10:%.*]] = getelementptr inbounds %struct.int16x4x2_t, %struct.int16x4x2_t* [[RETVAL]], i32 0, i32 0
-// CHECK: [[TMP11:%.*]] = extractvalue %struct.int16x4x2_t [[TMP9]], 0
-// CHECK: store [2 x <4 x i16>] [[TMP11]], [2 x <4 x i16>]* [[TMP10]], align 8
-// CHECK: [[TMP12:%.*]] = load %struct.int16x4x2_t, %struct.int16x4x2_t* [[RETVAL]], align 8
-// CHECK: ret %struct.int16x4x2_t [[TMP12]]
+// 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
+// CHECK: store [2 x <4 x i16>] [[TMP9]], [2 x <4 x i16>]* [[TMP8]], align 8
+// CHECK: [[TMP10:%.*]] = load %struct.int16x4x2_t, %struct.int16x4x2_t* [[RETVAL]], align 8
+// CHECK: ret %struct.int16x4x2_t [[TMP10]]
int16x4x2_t test_vtrn_s16(int16x4_t a, int16x4_t b) {
return vtrn_s16(a, b);
}
-// CHECK-LABEL: define %struct.int32x2x2_t @test_vtrn_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+
+// 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
@@ -1873,26 +1856,25 @@ int16x4x2_t test_vtrn_s16(int16x4_t a, int16x4_t b) {
// 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: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[TMP5:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VTRN_I:%.*]] = shufflevector <2 x i32> [[TMP4]], <2 x i32> [[TMP5]], <2 x i32> <i32 0, i32 2>
+// 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]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <2 x i32>, <2 x i32>* [[TMP3]], i32 1
-// CHECK: [[VTRN1_I:%.*]] = shufflevector <2 x i32> [[TMP4]], <2 x i32> [[TMP5]], <2 x i32> <i32 1, i32 3>
-// CHECK: store <2 x i32> [[VTRN1_I]], <2 x i32>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.int32x2x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.int32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP7]], i8* [[TMP8]], i64 16, i32 8, i1 false) #2
-// CHECK: [[TMP9:%.*]] = load %struct.int32x2x2_t, %struct.int32x2x2_t* [[RETVAL_I]], align 8
-// CHECK: [[TMP10:%.*]] = getelementptr inbounds %struct.int32x2x2_t, %struct.int32x2x2_t* [[RETVAL]], i32 0, i32 0
-// CHECK: [[TMP11:%.*]] = extractvalue %struct.int32x2x2_t [[TMP9]], 0
-// CHECK: store [2 x <2 x i32>] [[TMP11]], [2 x <2 x i32>]* [[TMP10]], align 8
-// CHECK: [[TMP12:%.*]] = load %struct.int32x2x2_t, %struct.int32x2x2_t* [[RETVAL]], align 8
-// CHECK: ret %struct.int32x2x2_t [[TMP12]]
+// 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
+// CHECK: store [2 x <2 x i32>] [[TMP9]], [2 x <2 x i32>]* [[TMP8]], align 8
+// CHECK: [[TMP10:%.*]] = load %struct.int32x2x2_t, %struct.int32x2x2_t* [[RETVAL]], align 8
+// CHECK: ret %struct.int32x2x2_t [[TMP10]]
int32x2x2_t test_vtrn_s32(int32x2_t a, int32x2_t b) {
return vtrn_s32(a, b);
}
-// CHECK-LABEL: define %struct.uint8x8x2_t @test_vtrn_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+
+// 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
@@ -1915,7 +1897,8 @@ int32x2x2_t test_vtrn_s32(int32x2_t a, int32x2_t b) {
uint8x8x2_t test_vtrn_u8(uint8x8_t a, uint8x8_t b) {
return vtrn_u8(a, b);
}
-// CHECK-LABEL: define %struct.uint16x4x2_t @test_vtrn_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+
+// 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
@@ -1923,26 +1906,25 @@ uint8x8x2_t test_vtrn_u8(uint8x8_t a, uint8x8_t b) {
// 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: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[TMP5:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VTRN_I:%.*]] = shufflevector <4 x i16> [[TMP4]], <4 x i16> [[TMP5]], <4 x i32> <i32 0, i32 4, i32 2, i32 6>
+// 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]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
-// CHECK: [[VTRN1_I:%.*]] = shufflevector <4 x i16> [[TMP4]], <4 x i16> [[TMP5]], <4 x i32> <i32 1, i32 5, i32 3, i32 7>
-// CHECK: store <4 x i16> [[VTRN1_I]], <4 x i16>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.uint16x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP7]], i8* [[TMP8]], i64 16, i32 8, i1 false) #2
-// CHECK: [[TMP9:%.*]] = load %struct.uint16x4x2_t, %struct.uint16x4x2_t* [[RETVAL_I]], align 8
-// CHECK: [[TMP10:%.*]] = getelementptr inbounds %struct.uint16x4x2_t, %struct.uint16x4x2_t* [[RETVAL]], i32 0, i32 0
-// CHECK: [[TMP11:%.*]] = extractvalue %struct.uint16x4x2_t [[TMP9]], 0
-// CHECK: store [2 x <4 x i16>] [[TMP11]], [2 x <4 x i16>]* [[TMP10]], align 8
-// CHECK: [[TMP12:%.*]] = load %struct.uint16x4x2_t, %struct.uint16x4x2_t* [[RETVAL]], align 8
-// CHECK: ret %struct.uint16x4x2_t [[TMP12]]
+// 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
+// CHECK: store [2 x <4 x i16>] [[TMP9]], [2 x <4 x i16>]* [[TMP8]], align 8
+// CHECK: [[TMP10:%.*]] = load %struct.uint16x4x2_t, %struct.uint16x4x2_t* [[RETVAL]], align 8
+// CHECK: ret %struct.uint16x4x2_t [[TMP10]]
uint16x4x2_t test_vtrn_u16(uint16x4_t a, uint16x4_t b) {
return vtrn_u16(a, b);
}
-// CHECK-LABEL: define %struct.uint32x2x2_t @test_vtrn_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+
+// 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
@@ -1950,26 +1932,25 @@ uint16x4x2_t test_vtrn_u16(uint16x4_t a, uint16x4_t b) {
// 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: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[TMP5:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VTRN_I:%.*]] = shufflevector <2 x i32> [[TMP4]], <2 x i32> [[TMP5]], <2 x i32> <i32 0, i32 2>
+// 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]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <2 x i32>, <2 x i32>* [[TMP3]], i32 1
-// CHECK: [[VTRN1_I:%.*]] = shufflevector <2 x i32> [[TMP4]], <2 x i32> [[TMP5]], <2 x i32> <i32 1, i32 3>
-// CHECK: store <2 x i32> [[VTRN1_I]], <2 x i32>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.uint32x2x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP7]], i8* [[TMP8]], i64 16, i32 8, i1 false) #2
-// CHECK: [[TMP9:%.*]] = load %struct.uint32x2x2_t, %struct.uint32x2x2_t* [[RETVAL_I]], align 8
-// CHECK: [[TMP10:%.*]] = getelementptr inbounds %struct.uint32x2x2_t, %struct.uint32x2x2_t* [[RETVAL]], i32 0, i32 0
-// CHECK: [[TMP11:%.*]] = extractvalue %struct.uint32x2x2_t [[TMP9]], 0
-// CHECK: store [2 x <2 x i32>] [[TMP11]], [2 x <2 x i32>]* [[TMP10]], align 8
-// CHECK: [[TMP12:%.*]] = load %struct.uint32x2x2_t, %struct.uint32x2x2_t* [[RETVAL]], align 8
-// CHECK: ret %struct.uint32x2x2_t [[TMP12]]
+// 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
+// CHECK: store [2 x <2 x i32>] [[TMP9]], [2 x <2 x i32>]* [[TMP8]], align 8
+// CHECK: [[TMP10:%.*]] = load %struct.uint32x2x2_t, %struct.uint32x2x2_t* [[RETVAL]], align 8
+// CHECK: ret %struct.uint32x2x2_t [[TMP10]]
uint32x2x2_t test_vtrn_u32(uint32x2_t a, uint32x2_t b) {
return vtrn_u32(a, b);
}
-// CHECK-LABEL: define %struct.float32x2x2_t @test_vtrn_f32(<2 x float> %a, <2 x float> %b) #0 {
+
+// 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
@@ -1977,26 +1958,25 @@ uint32x2x2_t test_vtrn_u32(uint32x2_t a, uint32x2_t b) {
// 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: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK: [[TMP5:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x float>
-// CHECK: [[VTRN_I:%.*]] = shufflevector <2 x float> [[TMP4]], <2 x float> [[TMP5]], <2 x i32> <i32 0, i32 2>
+// 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]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <2 x float>, <2 x float>* [[TMP3]], i32 1
-// CHECK: [[VTRN1_I:%.*]] = shufflevector <2 x float> [[TMP4]], <2 x float> [[TMP5]], <2 x i32> <i32 1, i32 3>
-// CHECK: store <2 x float> [[VTRN1_I]], <2 x float>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.float32x2x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.float32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP7]], i8* [[TMP8]], i64 16, i32 8, i1 false) #2
-// CHECK: [[TMP9:%.*]] = load %struct.float32x2x2_t, %struct.float32x2x2_t* [[RETVAL_I]], align 8
-// CHECK: [[TMP10:%.*]] = getelementptr inbounds %struct.float32x2x2_t, %struct.float32x2x2_t* [[RETVAL]], i32 0, i32 0
-// CHECK: [[TMP11:%.*]] = extractvalue %struct.float32x2x2_t [[TMP9]], 0
-// CHECK: store [2 x <2 x float>] [[TMP11]], [2 x <2 x float>]* [[TMP10]], align 8
-// CHECK: [[TMP12:%.*]] = load %struct.float32x2x2_t, %struct.float32x2x2_t* [[RETVAL]], align 8
-// CHECK: ret %struct.float32x2x2_t [[TMP12]]
+// 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
+// CHECK: store [2 x <2 x float>] [[TMP9]], [2 x <2 x float>]* [[TMP8]], align 8
+// CHECK: [[TMP10:%.*]] = load %struct.float32x2x2_t, %struct.float32x2x2_t* [[RETVAL]], align 8
+// CHECK: ret %struct.float32x2x2_t [[TMP10]]
float32x2x2_t test_vtrn_f32(float32x2_t a, float32x2_t b) {
return vtrn_f32(a, b);
}
-// CHECK-LABEL: define %struct.poly8x8x2_t @test_vtrn_p8(<8 x i8> %a, <8 x i8> %b) #0 {
+
+// 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
@@ -2019,7 +1999,8 @@ float32x2x2_t test_vtrn_f32(float32x2_t a, float32x2_t b) {
poly8x8x2_t test_vtrn_p8(poly8x8_t a, poly8x8_t b) {
return vtrn_p8(a, b);
}
-// CHECK-LABEL: define %struct.poly16x4x2_t @test_vtrn_p16(<4 x i16> %a, <4 x i16> %b) #0 {
+
+// 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
@@ -2027,26 +2008,25 @@ poly8x8x2_t test_vtrn_p8(poly8x8_t a, poly8x8_t b) {
// 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: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[TMP5:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VTRN_I:%.*]] = shufflevector <4 x i16> [[TMP4]], <4 x i16> [[TMP5]], <4 x i32> <i32 0, i32 4, i32 2, i32 6>
+// 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]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
-// CHECK: [[VTRN1_I:%.*]] = shufflevector <4 x i16> [[TMP4]], <4 x i16> [[TMP5]], <4 x i32> <i32 1, i32 5, i32 3, i32 7>
-// CHECK: store <4 x i16> [[VTRN1_I]], <4 x i16>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.poly16x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP7]], i8* [[TMP8]], i64 16, i32 8, i1 false) #2
-// CHECK: [[TMP9:%.*]] = load %struct.poly16x4x2_t, %struct.poly16x4x2_t* [[RETVAL_I]], align 8
-// CHECK: [[TMP10:%.*]] = getelementptr inbounds %struct.poly16x4x2_t, %struct.poly16x4x2_t* [[RETVAL]], i32 0, i32 0
-// CHECK: [[TMP11:%.*]] = extractvalue %struct.poly16x4x2_t [[TMP9]], 0
-// CHECK: store [2 x <4 x i16>] [[TMP11]], [2 x <4 x i16>]* [[TMP10]], align 8
-// CHECK: [[TMP12:%.*]] = load %struct.poly16x4x2_t, %struct.poly16x4x2_t* [[RETVAL]], align 8
-// CHECK: ret %struct.poly16x4x2_t [[TMP12]]
+// 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
+// CHECK: store [2 x <4 x i16>] [[TMP9]], [2 x <4 x i16>]* [[TMP8]], align 8
+// CHECK: [[TMP10:%.*]] = load %struct.poly16x4x2_t, %struct.poly16x4x2_t* [[RETVAL]], align 8
+// CHECK: ret %struct.poly16x4x2_t [[TMP10]]
poly16x4x2_t test_vtrn_p16(poly16x4_t a, poly16x4_t b) {
return vtrn_p16(a, b);
}
-// CHECK-LABEL: define %struct.int8x16x2_t @test_vtrnq_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+
+// 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
@@ -2069,7 +2049,8 @@ poly16x4x2_t test_vtrn_p16(poly16x4_t a, poly16x4_t b) {
int8x16x2_t test_vtrnq_s8(int8x16_t a, int8x16_t b) {
return vtrnq_s8(a, b);
}
-// CHECK-LABEL: define %struct.int16x8x2_t @test_vtrnq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+
+// 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
@@ -2077,26 +2058,25 @@ int8x16x2_t test_vtrnq_s8(int8x16_t a, int8x16_t b) {
// 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: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <8 x i16>
-// CHECK: [[VTRN_I:%.*]] = shufflevector <8 x i16> [[TMP4]], <8 x i16> [[TMP5]], <8 x i32> <i32 0, i32 8, i32 2, i32 10, i32 4, i32 12, i32 6, i32 14>
+// 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]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
-// CHECK: [[VTRN1_I:%.*]] = shufflevector <8 x i16> [[TMP4]], <8 x i16> [[TMP5]], <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>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.int16x8x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.int16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP7]], i8* [[TMP8]], i64 32, i32 16, i1 false) #2
-// CHECK: [[TMP9:%.*]] = load %struct.int16x8x2_t, %struct.int16x8x2_t* [[RETVAL_I]], align 16
-// CHECK: [[TMP10:%.*]] = getelementptr inbounds %struct.int16x8x2_t, %struct.int16x8x2_t* [[RETVAL]], i32 0, i32 0
-// CHECK: [[TMP11:%.*]] = extractvalue %struct.int16x8x2_t [[TMP9]], 0
-// CHECK: store [2 x <8 x i16>] [[TMP11]], [2 x <8 x i16>]* [[TMP10]], align 16
-// CHECK: [[TMP12:%.*]] = load %struct.int16x8x2_t, %struct.int16x8x2_t* [[RETVAL]], align 16
-// CHECK: ret %struct.int16x8x2_t [[TMP12]]
+// 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
+// CHECK: store [2 x <8 x i16>] [[TMP9]], [2 x <8 x i16>]* [[TMP8]], align 16
+// CHECK: [[TMP10:%.*]] = load %struct.int16x8x2_t, %struct.int16x8x2_t* [[RETVAL]], align 16
+// CHECK: ret %struct.int16x8x2_t [[TMP10]]
int16x8x2_t test_vtrnq_s16(int16x8_t a, int16x8_t b) {
return vtrnq_s16(a, b);
}
-// CHECK-LABEL: define %struct.int32x4x2_t @test_vtrnq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+
+// 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
@@ -2104,26 +2084,25 @@ int16x8x2_t test_vtrnq_s16(int16x8_t a, int16x8_t b) {
// 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: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <4 x i32>
-// CHECK: [[VTRN_I:%.*]] = shufflevector <4 x i32> [[TMP4]], <4 x i32> [[TMP5]], <4 x i32> <i32 0, i32 4, i32 2, i32 6>
+// 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]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <4 x i32>, <4 x i32>* [[TMP3]], i32 1
-// CHECK: [[VTRN1_I:%.*]] = shufflevector <4 x i32> [[TMP4]], <4 x i32> [[TMP5]], <4 x i32> <i32 1, i32 5, i32 3, i32 7>
-// CHECK: store <4 x i32> [[VTRN1_I]], <4 x i32>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.int32x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.int32x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP7]], i8* [[TMP8]], i64 32, i32 16, i1 false) #2
-// CHECK: [[TMP9:%.*]] = load %struct.int32x4x2_t, %struct.int32x4x2_t* [[RETVAL_I]], align 16
-// CHECK: [[TMP10:%.*]] = getelementptr inbounds %struct.int32x4x2_t, %struct.int32x4x2_t* [[RETVAL]], i32 0, i32 0
-// CHECK: [[TMP11:%.*]] = extractvalue %struct.int32x4x2_t [[TMP9]], 0
-// CHECK: store [2 x <4 x i32>] [[TMP11]], [2 x <4 x i32>]* [[TMP10]], align 16
-// CHECK: [[TMP12:%.*]] = load %struct.int32x4x2_t, %struct.int32x4x2_t* [[RETVAL]], align 16
-// CHECK: ret %struct.int32x4x2_t [[TMP12]]
+// 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
+// CHECK: store [2 x <4 x i32>] [[TMP9]], [2 x <4 x i32>]* [[TMP8]], align 16
+// CHECK: [[TMP10:%.*]] = load %struct.int32x4x2_t, %struct.int32x4x2_t* [[RETVAL]], align 16
+// CHECK: ret %struct.int32x4x2_t [[TMP10]]
int32x4x2_t test_vtrnq_s32(int32x4_t a, int32x4_t b) {
return vtrnq_s32(a, b);
}
-// CHECK-LABEL: define %struct.uint8x16x2_t @test_vtrnq_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+
+// 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
@@ -2146,7 +2125,8 @@ int32x4x2_t test_vtrnq_s32(int32x4_t a, int32x4_t b) {
uint8x16x2_t test_vtrnq_u8(uint8x16_t a, uint8x16_t b) {
return vtrnq_u8(a, b);
}
-// CHECK-LABEL: define %struct.uint16x8x2_t @test_vtrnq_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+
+// 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
@@ -2154,26 +2134,25 @@ uint8x16x2_t test_vtrnq_u8(uint8x16_t a, uint8x16_t b) {
// 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: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <8 x i16>
-// CHECK: [[VTRN_I:%.*]] = shufflevector <8 x i16> [[TMP4]], <8 x i16> [[TMP5]], <8 x i32> <i32 0, i32 8, i32 2, i32 10, i32 4, i32 12, i32 6, i32 14>
+// 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]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
-// CHECK: [[VTRN1_I:%.*]] = shufflevector <8 x i16> [[TMP4]], <8 x i16> [[TMP5]], <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>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.uint16x8x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP7]], i8* [[TMP8]], i64 32, i32 16, i1 false) #2
-// CHECK: [[TMP9:%.*]] = load %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[RETVAL_I]], align 16
-// CHECK: [[TMP10:%.*]] = getelementptr inbounds %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[RETVAL]], i32 0, i32 0
-// CHECK: [[TMP11:%.*]] = extractvalue %struct.uint16x8x2_t [[TMP9]], 0
-// CHECK: store [2 x <8 x i16>] [[TMP11]], [2 x <8 x i16>]* [[TMP10]], align 16
-// CHECK: [[TMP12:%.*]] = load %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[RETVAL]], align 16
-// CHECK: ret %struct.uint16x8x2_t [[TMP12]]
+// 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
+// CHECK: store [2 x <8 x i16>] [[TMP9]], [2 x <8 x i16>]* [[TMP8]], align 16
+// CHECK: [[TMP10:%.*]] = load %struct.uint16x8x2_t, %struct.uint16x8x2_t* [[RETVAL]], align 16
+// CHECK: ret %struct.uint16x8x2_t [[TMP10]]
uint16x8x2_t test_vtrnq_u16(uint16x8_t a, uint16x8_t b) {
return vtrnq_u16(a, b);
}
-// CHECK-LABEL: define %struct.uint32x4x2_t @test_vtrnq_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+
+// 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
@@ -2181,26 +2160,25 @@ uint16x8x2_t test_vtrnq_u16(uint16x8_t a, uint16x8_t b) {
// 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: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <4 x i32>
-// CHECK: [[VTRN_I:%.*]] = shufflevector <4 x i32> [[TMP4]], <4 x i32> [[TMP5]], <4 x i32> <i32 0, i32 4, i32 2, i32 6>
+// 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]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <4 x i32>, <4 x i32>* [[TMP3]], i32 1
-// CHECK: [[VTRN1_I:%.*]] = shufflevector <4 x i32> [[TMP4]], <4 x i32> [[TMP5]], <4 x i32> <i32 1, i32 5, i32 3, i32 7>
-// CHECK: store <4 x i32> [[VTRN1_I]], <4 x i32>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.uint32x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP7]], i8* [[TMP8]], i64 32, i32 16, i1 false) #2
-// CHECK: [[TMP9:%.*]] = load %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[RETVAL_I]], align 16
-// CHECK: [[TMP10:%.*]] = getelementptr inbounds %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[RETVAL]], i32 0, i32 0
-// CHECK: [[TMP11:%.*]] = extractvalue %struct.uint32x4x2_t [[TMP9]], 0
-// CHECK: store [2 x <4 x i32>] [[TMP11]], [2 x <4 x i32>]* [[TMP10]], align 16
-// CHECK: [[TMP12:%.*]] = load %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[RETVAL]], align 16
-// CHECK: ret %struct.uint32x4x2_t [[TMP12]]
+// 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
+// CHECK: store [2 x <4 x i32>] [[TMP9]], [2 x <4 x i32>]* [[TMP8]], align 16
+// CHECK: [[TMP10:%.*]] = load %struct.uint32x4x2_t, %struct.uint32x4x2_t* [[RETVAL]], align 16
+// CHECK: ret %struct.uint32x4x2_t [[TMP10]]
uint32x4x2_t test_vtrnq_u32(uint32x4_t a, uint32x4_t b) {
return vtrnq_u32(a, b);
}
-// CHECK-LABEL: define %struct.float32x4x2_t @test_vtrnq_f32(<4 x float> %a, <4 x float> %b) #0 {
+
+// 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
@@ -2208,26 +2186,25 @@ uint32x4x2_t test_vtrnq_u32(uint32x4_t a, uint32x4_t b) {
// 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: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <4 x float>
-// CHECK: [[VTRN_I:%.*]] = shufflevector <4 x float> [[TMP4]], <4 x float> [[TMP5]], <4 x i32> <i32 0, i32 4, i32 2, i32 6>
+// 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]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <4 x float>, <4 x float>* [[TMP3]], i32 1
-// CHECK: [[VTRN1_I:%.*]] = shufflevector <4 x float> [[TMP4]], <4 x float> [[TMP5]], <4 x i32> <i32 1, i32 5, i32 3, i32 7>
-// CHECK: store <4 x float> [[VTRN1_I]], <4 x float>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.float32x4x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.float32x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP7]], i8* [[TMP8]], i64 32, i32 16, i1 false) #2
-// CHECK: [[TMP9:%.*]] = load %struct.float32x4x2_t, %struct.float32x4x2_t* [[RETVAL_I]], align 16
-// CHECK: [[TMP10:%.*]] = getelementptr inbounds %struct.float32x4x2_t, %struct.float32x4x2_t* [[RETVAL]], i32 0, i32 0
-// CHECK: [[TMP11:%.*]] = extractvalue %struct.float32x4x2_t [[TMP9]], 0
-// CHECK: store [2 x <4 x float>] [[TMP11]], [2 x <4 x float>]* [[TMP10]], align 16
-// CHECK: [[TMP12:%.*]] = load %struct.float32x4x2_t, %struct.float32x4x2_t* [[RETVAL]], align 16
-// CHECK: ret %struct.float32x4x2_t [[TMP12]]
+// 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
+// CHECK: store [2 x <4 x float>] [[TMP9]], [2 x <4 x float>]* [[TMP8]], align 16
+// CHECK: [[TMP10:%.*]] = load %struct.float32x4x2_t, %struct.float32x4x2_t* [[RETVAL]], align 16
+// CHECK: ret %struct.float32x4x2_t [[TMP10]]
float32x4x2_t test_vtrnq_f32(float32x4_t a, float32x4_t b) {
return vtrnq_f32(a, b);
}
-// CHECK-LABEL: define %struct.poly8x16x2_t @test_vtrnq_p8(<16 x i8> %a, <16 x i8> %b) #0 {
+
+// 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
@@ -2250,7 +2227,8 @@ float32x4x2_t test_vtrnq_f32(float32x4_t a, float32x4_t b) {
poly8x16x2_t test_vtrnq_p8(poly8x16_t a, poly8x16_t b) {
return vtrnq_p8(a, b);
}
-// CHECK-LABEL: define %struct.poly16x8x2_t @test_vtrnq_p16(<8 x i16> %a, <8 x i16> %b) #0 {
+
+// 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
@@ -2258,22 +2236,20 @@ poly8x16x2_t test_vtrnq_p8(poly8x16_t a, poly8x16_t b) {
// 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: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <8 x i16>
-// CHECK: [[VTRN_I:%.*]] = shufflevector <8 x i16> [[TMP4]], <8 x i16> [[TMP5]], <8 x i32> <i32 0, i32 8, i32 2, i32 10, i32 4, i32 12, i32 6, i32 14>
+// 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]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
-// CHECK: [[VTRN1_I:%.*]] = shufflevector <8 x i16> [[TMP4]], <8 x i16> [[TMP5]], <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>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.poly16x8x2_t* [[RETVAL_I]] to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[TMP7]], i8* [[TMP8]], i64 32, i32 16, i1 false) #2
-// CHECK: [[TMP9:%.*]] = load %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[RETVAL_I]], align 16
-// CHECK: [[TMP10:%.*]] = getelementptr inbounds %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[RETVAL]], i32 0, i32 0
-// CHECK: [[TMP11:%.*]] = extractvalue %struct.poly16x8x2_t [[TMP9]], 0
-// CHECK: store [2 x <8 x i16>] [[TMP11]], [2 x <8 x i16>]* [[TMP10]], align 16
-// CHECK: [[TMP12:%.*]] = load %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[RETVAL]], align 16
-// CHECK: ret %struct.poly16x8x2_t [[TMP12]]
+// 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
+// CHECK: store [2 x <8 x i16>] [[TMP9]], [2 x <8 x i16>]* [[TMP8]], align 16
+// CHECK: [[TMP10:%.*]] = load %struct.poly16x8x2_t, %struct.poly16x8x2_t* [[RETVAL]], align 16
+// CHECK: ret %struct.poly16x8x2_t [[TMP10]]
poly16x8x2_t test_vtrnq_p16(poly16x8_t a, poly16x8_t b) {
return vtrnq_p16(a, b);
}
diff --git a/test/CodeGen/aarch64-neon-scalar-x-indexed-elem.c b/test/CodeGen/aarch64-neon-scalar-x-indexed-elem.c
index 39aab2540e8a..ac5a090fd2e6 100644
--- a/test/CodeGen/aarch64-neon-scalar-x-indexed-elem.c
+++ b/test/CodeGen/aarch64-neon-scalar-x-indexed-elem.c
@@ -47,9 +47,7 @@ float64_t test_vmuld_laneq_f64(float64_t a, float64x2_t b) {
}
// CHECK-LABEL: define <1 x double> @test_vmul_n_f64(<1 x double> %a, double %b) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <1 x double> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x double>
-// CHECK: [[TMP2:%.*]] = bitcast <1 x double> [[TMP1]] to double
+// CHECK: [[TMP2:%.*]] = bitcast <1 x double> %a to double
// CHECK: [[TMP3:%.*]] = fmul double [[TMP2]], %b
// CHECK: [[TMP4:%.*]] = bitcast double [[TMP3]] to <1 x double>
// CHECK: ret <1 x double> [[TMP4]]
diff --git a/test/CodeGen/aarch64-poly64.c b/test/CodeGen/aarch64-poly64.c
index 762ca94e5e57..eadeda640434 100644
--- a/test/CodeGen/aarch64-poly64.c
+++ b/test/CodeGen/aarch64-poly64.c
@@ -23,11 +23,7 @@ uint64x2_t test_vceqq_p64(poly64x2_t a, poly64x2_t b) {
}
// CHECK-LABEL: define <1 x i64> @test_vtst_p64(<1 x i64> %a, <1 x i64> %b) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x i64>
-// CHECK: [[TMP4:%.*]] = and <1 x i64> [[TMP2]], [[TMP3]]
+// CHECK: [[TMP4:%.*]] = and <1 x i64> %a, %b
// CHECK: [[TMP5:%.*]] = icmp ne <1 x i64> [[TMP4]], zeroinitializer
// CHECK: [[VTST_I:%.*]] = sext <1 x i1> [[TMP5]] to <1 x i64>
// CHECK: ret <1 x i64> [[VTST_I]]
@@ -36,11 +32,7 @@ uint64x1_t test_vtst_p64(poly64x1_t a, poly64x1_t b) {
}
// CHECK-LABEL: define <2 x i64> @test_vtstq_p64(<2 x i64> %a, <2 x i64> %b) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[TMP4:%.*]] = and <2 x i64> [[TMP2]], [[TMP3]]
+// CHECK: [[TMP4:%.*]] = and <2 x i64> %a, %b
// CHECK: [[TMP5:%.*]] = icmp ne <2 x i64> [[TMP4]], zeroinitializer
// CHECK: [[VTST_I:%.*]] = sext <2 x i1> [[TMP5]] to <2 x i64>
// CHECK: ret <2 x i64> [[VTST_I]]
@@ -49,15 +41,9 @@ uint64x2_t test_vtstq_p64(poly64x2_t a, poly64x2_t b) {
}
// CHECK-LABEL: define <1 x i64> @test_vbsl_p64(<1 x i64> %a, <1 x i64> %b, <1 x i64> %c) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <1 x i64> %c to <8 x i8>
-// CHECK: [[VBSL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
-// CHECK: [[VBSL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x i64>
-// CHECK: [[VBSL2_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <1 x i64>
-// CHECK: [[VBSL3_I:%.*]] = and <1 x i64> [[VBSL_I]], [[VBSL1_I]]
-// CHECK: [[TMP3:%.*]] = xor <1 x i64> [[VBSL_I]], <i64 -1>
-// CHECK: [[VBSL4_I:%.*]] = and <1 x i64> [[TMP3]], [[VBSL2_I]]
+// CHECK: [[VBSL3_I:%.*]] = and <1 x i64> %a, %b
+// CHECK: [[TMP3:%.*]] = xor <1 x i64> %a, <i64 -1>
+// CHECK: [[VBSL4_I:%.*]] = and <1 x i64> [[TMP3]], %c
// CHECK: [[VBSL5_I:%.*]] = or <1 x i64> [[VBSL3_I]], [[VBSL4_I]]
// CHECK: ret <1 x i64> [[VBSL5_I]]
poly64x1_t test_vbsl_p64(poly64x1_t a, poly64x1_t b, poly64x1_t c) {
@@ -65,15 +51,9 @@ poly64x1_t test_vbsl_p64(poly64x1_t a, poly64x1_t b, poly64x1_t c) {
}
// CHECK-LABEL: define <2 x i64> @test_vbslq_p64(<2 x i64> %a, <2 x i64> %b, <2 x i64> %c) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <2 x i64> %c to <16 x i8>
-// CHECK: [[VBSL_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VBSL1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VBSL2_I:%.*]] = bitcast <16 x i8> [[TMP2]] to <2 x i64>
-// CHECK: [[VBSL3_I:%.*]] = and <2 x i64> [[VBSL_I]], [[VBSL1_I]]
-// CHECK: [[TMP3:%.*]] = xor <2 x i64> [[VBSL_I]], <i64 -1, i64 -1>
-// CHECK: [[VBSL4_I:%.*]] = and <2 x i64> [[TMP3]], [[VBSL2_I]]
+// CHECK: [[VBSL3_I:%.*]] = and <2 x i64> %a, %b
+// CHECK: [[TMP3:%.*]] = xor <2 x i64> %a, <i64 -1, i64 -1>
+// CHECK: [[VBSL4_I:%.*]] = and <2 x i64> [[TMP3]], %c
// CHECK: [[VBSL5_I:%.*]] = or <2 x i64> [[VBSL3_I]], [[VBSL4_I]]
// CHECK: ret <2 x i64> [[VBSL5_I]]
poly64x2_t test_vbslq_p64(poly64x2_t a, poly64x2_t b, poly64x2_t c) {
diff --git a/test/CodeGen/address-safety-attr-kasan.cpp b/test/CodeGen/address-safety-attr-kasan.cpp
index c84ba88291da..4d8333d2ffea 100644
--- a/test/CodeGen/address-safety-attr-kasan.cpp
+++ b/test/CodeGen/address-safety-attr-kasan.cpp
@@ -8,31 +8,31 @@
int HasSanitizeAddress() {
return 1;
}
-// CHECK-NOASAN: {{Function Attrs: nounwind$}}
-// CHECK-ASAN: Function Attrs: nounwind sanitize_address
-// CHECK-KASAN: Function Attrs: nounwind sanitize_address
+// 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: nounwind$}}
-// CHECK-ASAN: {{Function Attrs: nounwind$}}
-// CHECK-KASAN: {{Function Attrs: nounwind sanitize_address$}}
+// 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: nounwind$}}
-// CHECK-ASAN: {{Function Attrs: nounwind$}}
-// CHECK-KASAN: {{Function Attrs: nounwind sanitize_address$}}
+// 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: nounwind$}}
-// CHECK-ASAN: {{Function Attrs: nounwind sanitize_address$}}
-// CHECK-KASAN: {{Function Attrs: nounwind$}}
+// 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-safety-attr.cpp b/test/CodeGen/address-safety-attr.cpp
index 402d6bad909d..60faeddbd4ce 100644
--- a/test/CodeGen/address-safety-attr.cpp
+++ b/test/CodeGen/address-safety-attr.cpp
@@ -9,12 +9,11 @@ int DefinedInDifferentFile(int *a);
// RUN: echo "fun:*BlacklistedFunction*" > %t.func.blacklist
// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin -emit-llvm -o - %s -include %t.extra-source.cpp -fsanitize=address -fsanitize-blacklist=%t.func.blacklist | FileCheck -check-prefix=BLFUNC %s
-// RUN: echo "src:%s" > %t.file.blacklist
+// The blacklist file uses regexps, so escape backslashes, which are common in
+// Windows paths.
+// RUN: echo "src:%s" | sed -e 's/\\/\\\\/g' > %t.file.blacklist
// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin -emit-llvm -o - %s -include %t.extra-source.cpp -fsanitize=address -fsanitize-blacklist=%t.file.blacklist | FileCheck -check-prefix=BLFILE %s
-// FIXME: %t.file.blacklist is like "src:x:\path\to\clang\test\CodeGen\address-safety-attr.cpp"
-// REQUIRES: shell
-
// The sanitize_address attribute should be attached to functions
// when AddressSanitizer is enabled, unless no_sanitize_address attribute
// is present.
@@ -144,13 +143,13 @@ int global2 = *(int*)((char*)&global1+1);
// BLFUNC: @__cxx_global_var_init{{.*}}[[WITH]]
// ASAN: @__cxx_global_var_init{{.*}}[[WITH]]
-// WITHOUT: attributes [[NOATTR]] = { nounwind{{.*}} }
+// WITHOUT: attributes [[NOATTR]] = { noinline nounwind{{.*}} }
-// BLFILE: attributes [[WITH]] = { nounwind sanitize_address{{.*}} }
-// BLFILE: attributes [[NOATTR]] = { nounwind{{.*}} }
+// BLFILE: attributes [[WITH]] = { noinline nounwind sanitize_address{{.*}} }
+// BLFILE: attributes [[NOATTR]] = { noinline nounwind{{.*}} }
-// BLFUNC: attributes [[WITH]] = { nounwind sanitize_address{{.*}} }
-// BLFUNC: attributes [[NOATTR]] = { nounwind{{.*}} }
+// BLFUNC: attributes [[WITH]] = { noinline nounwind sanitize_address{{.*}} }
+// BLFUNC: attributes [[NOATTR]] = { noinline nounwind{{.*}} }
-// ASAN: attributes [[WITH]] = { nounwind sanitize_address{{.*}} }
-// ASAN: attributes [[NOATTR]] = { nounwind{{.*}} }
+// ASAN: attributes [[WITH]] = { noinline nounwind sanitize_address{{.*}} }
+// ASAN: attributes [[NOATTR]] = { noinline nounwind{{.*}} }
diff --git a/test/CodeGen/address-space-field1.c b/test/CodeGen/address-space-field1.c
index 109c69201cb2..64b51aefc9a1 100644
--- a/test/CodeGen/address-space-field1.c
+++ b/test/CodeGen/address-space-field1.c
@@ -37,4 +37,4 @@ void test_addrspace(__addr1 S* p1, __addr2 S*p2) {
p1->b = p2->a;
}
-// CHECK: attributes [[NUW]] = { nounwind{{.*}} }
+// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} }
diff --git a/test/CodeGen/alias.c b/test/CodeGen/alias.c
index c34dcf5ca229..6ec12702d86b 100644
--- a/test/CodeGen/alias.c
+++ b/test/CodeGen/alias.c
@@ -77,9 +77,9 @@ int outer_weak(int a) { return inner_weak_a(a); }
// CHECKCC: call arm_aapcs_vfpcc i32 @inner_weak(i32 %{{.*}})
// CHECKCC: define internal arm_aapcs_vfpcc i32 @inner_weak(i32 %a) [[NUW]] {
-// CHECKBASIC: attributes [[NUW]] = { nounwind{{.*}} }
+// CHECKBASIC: attributes [[NUW]] = { noinline nounwind{{.*}} }
-// CHECKCC: attributes [[NUW]] = { nounwind{{.*}} }
+// CHECKCC: attributes [[NUW]] = { noinline nounwind{{.*}} }
void test8_bar() {}
void test8_foo() __attribute__((weak, alias("test8_bar")));
diff --git a/test/CodeGen/alloc-size.c b/test/CodeGen/alloc-size.c
new file mode 100644
index 000000000000..1e503f0579c9
--- /dev/null
+++ b/test/CodeGen/alloc-size.c
@@ -0,0 +1,352 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm %s -o - 2>&1 | FileCheck %s
+
+#define NULL ((void *)0)
+
+int gi;
+
+typedef unsigned long size_t;
+
+// CHECK-DAG-RE: define void @my_malloc({{.*}}) #[[MALLOC_ATTR_NUMBER:[0-9]+]]
+// N.B. LLVM's allocsize arguments are base-0, whereas ours are base-1 (for
+// compat with GCC)
+// CHECK-DAG-RE: attributes #[[MALLOC_ATTR_NUMBER]] = {.*allocsize(0).*}
+void *my_malloc(size_t) __attribute__((alloc_size(1)));
+
+// CHECK-DAG-RE: define void @my_calloc({{.*}}) #[[CALLOC_ATTR_NUMBER:[0-9]+]]
+// CHECK-DAG-RE: attributes #[[CALLOC_ATTR_NUMBER]] = {.*allocsize(0, 1).*}
+void *my_calloc(size_t, size_t) __attribute__((alloc_size(1, 2)));
+
+// CHECK-LABEL: @test1
+void test1() {
+ void *const vp = my_malloc(100);
+ // CHECK: store i32 100
+ gi = __builtin_object_size(vp, 0);
+ // CHECK: store i32 100
+ gi = __builtin_object_size(vp, 1);
+ // CHECK: store i32 100
+ gi = __builtin_object_size(vp, 2);
+ // CHECK: store i32 100
+ gi = __builtin_object_size(vp, 3);
+
+ void *const arr = my_calloc(100, 5);
+ // CHECK: store i32 500
+ gi = __builtin_object_size(arr, 0);
+ // CHECK: store i32 500
+ gi = __builtin_object_size(arr, 1);
+ // CHECK: store i32 500
+ gi = __builtin_object_size(arr, 2);
+ // CHECK: store i32 500
+ gi = __builtin_object_size(arr, 3);
+
+ // CHECK: store i32 100
+ gi = __builtin_object_size(my_malloc(100), 0);
+ // CHECK: store i32 100
+ gi = __builtin_object_size(my_malloc(100), 1);
+ // CHECK: store i32 100
+ gi = __builtin_object_size(my_malloc(100), 2);
+ // CHECK: store i32 100
+ gi = __builtin_object_size(my_malloc(100), 3);
+
+ // CHECK: store i32 500
+ gi = __builtin_object_size(my_calloc(100, 5), 0);
+ // CHECK: store i32 500
+ gi = __builtin_object_size(my_calloc(100, 5), 1);
+ // CHECK: store i32 500
+ gi = __builtin_object_size(my_calloc(100, 5), 2);
+ // CHECK: store i32 500
+ gi = __builtin_object_size(my_calloc(100, 5), 3);
+
+ void *const zeroPtr = my_malloc(0);
+ // CHECK: store i32 0
+ gi = __builtin_object_size(zeroPtr, 0);
+ // CHECK: store i32 0
+ gi = __builtin_object_size(my_malloc(0), 0);
+
+ void *const zeroArr1 = my_calloc(0, 1);
+ void *const zeroArr2 = my_calloc(1, 0);
+ // CHECK: store i32 0
+ gi = __builtin_object_size(zeroArr1, 0);
+ // CHECK: store i32 0
+ gi = __builtin_object_size(zeroArr2, 0);
+ // CHECK: store i32 0
+ gi = __builtin_object_size(my_calloc(1, 0), 0);
+ // CHECK: store i32 0
+ gi = __builtin_object_size(my_calloc(0, 1), 0);
+}
+
+// CHECK-LABEL: @test2
+void test2() {
+ void *const vp = my_malloc(gi);
+ // CHECK: @llvm.objectsize
+ gi = __builtin_object_size(vp, 0);
+
+ void *const arr1 = my_calloc(gi, 1);
+ // CHECK: @llvm.objectsize
+ gi = __builtin_object_size(arr1, 0);
+
+ void *const arr2 = my_calloc(1, gi);
+ // CHECK: @llvm.objectsize
+ gi = __builtin_object_size(arr2, 0);
+}
+
+// CHECK-LABEL: @test3
+void test3() {
+ char *const buf = (char *)my_calloc(100, 5);
+ // CHECK: store i32 500
+ gi = __builtin_object_size(buf, 0);
+ // CHECK: store i32 500
+ gi = __builtin_object_size(buf, 1);
+ // CHECK: store i32 500
+ gi = __builtin_object_size(buf, 2);
+ // CHECK: store i32 500
+ gi = __builtin_object_size(buf, 3);
+}
+
+struct Data {
+ int a;
+ int t[10];
+ char pad[3];
+ char end[1];
+};
+
+// CHECK-LABEL: @test5
+void test5() {
+ struct Data *const data = my_malloc(sizeof(*data));
+ // CHECK: store i32 48
+ gi = __builtin_object_size(data, 0);
+ // CHECK: store i32 48
+ gi = __builtin_object_size(data, 1);
+ // CHECK: store i32 48
+ gi = __builtin_object_size(data, 2);
+ // CHECK: store i32 48
+ gi = __builtin_object_size(data, 3);
+
+ // CHECK: store i32 40
+ gi = __builtin_object_size(&data->t[1], 0);
+ // CHECK: store i32 36
+ gi = __builtin_object_size(&data->t[1], 1);
+ // CHECK: store i32 40
+ gi = __builtin_object_size(&data->t[1], 2);
+ // CHECK: store i32 36
+ gi = __builtin_object_size(&data->t[1], 3);
+
+ struct Data *const arr = my_calloc(sizeof(*data), 2);
+ // CHECK: store i32 96
+ gi = __builtin_object_size(arr, 0);
+ // CHECK: store i32 96
+ gi = __builtin_object_size(arr, 1);
+ // CHECK: store i32 96
+ gi = __builtin_object_size(arr, 2);
+ // CHECK: store i32 96
+ gi = __builtin_object_size(arr, 3);
+
+ // CHECK: store i32 88
+ gi = __builtin_object_size(&arr->t[1], 0);
+ // CHECK: store i32 36
+ gi = __builtin_object_size(&arr->t[1], 1);
+ // CHECK: store i32 88
+ gi = __builtin_object_size(&arr->t[1], 2);
+ // CHECK: store i32 36
+ gi = __builtin_object_size(&arr->t[1], 3);
+}
+
+// CHECK-LABEL: @test6
+void test6() {
+ // Things that would normally trigger conservative estimates don't need to do
+ // so when we know the source of the allocation.
+ struct Data *const data = my_malloc(sizeof(*data) + 10);
+ // CHECK: store i32 11
+ gi = __builtin_object_size(data->end, 0);
+ // CHECK: store i32 11
+ gi = __builtin_object_size(data->end, 1);
+ // CHECK: store i32 11
+ gi = __builtin_object_size(data->end, 2);
+ // CHECK: store i32 11
+ gi = __builtin_object_size(data->end, 3);
+
+ struct Data *const arr = my_calloc(sizeof(*arr) + 5, 3);
+ // AFAICT, GCC treats malloc and calloc identically. So, we should do the
+ // same.
+ //
+ // Additionally, GCC ignores the initial array index when determining whether
+ // we're writing off the end of an alloc_size base. e.g.
+ // arr[0].end
+ // arr[1].end
+ // arr[2].end
+ // ...Are all considered "writing off the end", because there's no way to tell
+ // with high accuracy if the user meant "allocate a single N-byte `Data`",
+ // or "allocate M smaller `Data`s with extra padding".
+
+ // CHECK: store i32 112
+ gi = __builtin_object_size(arr->end, 0);
+ // CHECK: store i32 112
+ gi = __builtin_object_size(arr->end, 1);
+ // CHECK: store i32 112
+ gi = __builtin_object_size(arr->end, 2);
+ // CHECK: store i32 112
+ gi = __builtin_object_size(arr->end, 3);
+
+ // CHECK: store i32 112
+ gi = __builtin_object_size(arr[0].end, 0);
+ // CHECK: store i32 112
+ gi = __builtin_object_size(arr[0].end, 1);
+ // CHECK: store i32 112
+ gi = __builtin_object_size(arr[0].end, 2);
+ // CHECK: store i32 112
+ gi = __builtin_object_size(arr[0].end, 3);
+
+ // CHECK: store i32 64
+ gi = __builtin_object_size(arr[1].end, 0);
+ // CHECK: store i32 64
+ gi = __builtin_object_size(arr[1].end, 1);
+ // CHECK: store i32 64
+ gi = __builtin_object_size(arr[1].end, 2);
+ // CHECK: store i32 64
+ gi = __builtin_object_size(arr[1].end, 3);
+
+ // CHECK: store i32 16
+ gi = __builtin_object_size(arr[2].end, 0);
+ // CHECK: store i32 16
+ gi = __builtin_object_size(arr[2].end, 1);
+ // CHECK: store i32 16
+ gi = __builtin_object_size(arr[2].end, 2);
+ // CHECK: store i32 16
+ gi = __builtin_object_size(arr[2].end, 3);
+}
+
+// CHECK-LABEL: @test7
+void test7() {
+ struct Data *const data = my_malloc(sizeof(*data) + 5);
+ // CHECK: store i32 9
+ gi = __builtin_object_size(data->pad, 0);
+ // CHECK: store i32 3
+ gi = __builtin_object_size(data->pad, 1);
+ // CHECK: store i32 9
+ gi = __builtin_object_size(data->pad, 2);
+ // CHECK: store i32 3
+ gi = __builtin_object_size(data->pad, 3);
+}
+
+// CHECK-LABEL: @test8
+void test8() {
+ // Non-const pointers aren't currently supported.
+ void *buf = my_calloc(100, 5);
+ // CHECK: @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false)
+ gi = __builtin_object_size(buf, 0);
+ // CHECK: @llvm.objectsize
+ gi = __builtin_object_size(buf, 1);
+ // CHECK: @llvm.objectsize
+ gi = __builtin_object_size(buf, 2);
+ // CHECK: store i32 0
+ gi = __builtin_object_size(buf, 3);
+}
+
+// CHECK-LABEL: @test9
+void test9() {
+ // Check to be sure that we unwrap things correctly.
+ short *const buf0 = (my_malloc(100));
+ short *const buf1 = (short*)(my_malloc(100));
+ short *const buf2 = ((short*)(my_malloc(100)));
+
+ // CHECK: store i32 100
+ gi = __builtin_object_size(buf0, 0);
+ // CHECK: store i32 100
+ gi = __builtin_object_size(buf1, 0);
+ // CHECK: store i32 100
+ gi = __builtin_object_size(buf2, 0);
+}
+
+// CHECK-LABEL: @test10
+void test10() {
+ // Yay overflow
+ short *const arr = my_calloc((size_t)-1 / 2 + 1, 2);
+ // CHECK: @llvm.objectsize
+ gi = __builtin_object_size(arr, 0);
+ // CHECK: @llvm.objectsize
+ gi = __builtin_object_size(arr, 1);
+ // CHECK: @llvm.objectsize
+ gi = __builtin_object_size(arr, 2);
+ // CHECK: store i32 0
+ gi = __builtin_object_size(arr, 3);
+
+ // As an implementation detail, CharUnits can't handle numbers greater than or
+ // equal to 2**63. Realistically, this shouldn't be a problem, but we should
+ // be sure we don't emit crazy results for this case.
+ short *const buf = my_malloc((size_t)-1);
+ // CHECK: @llvm.objectsize
+ gi = __builtin_object_size(buf, 0);
+ // CHECK: @llvm.objectsize
+ gi = __builtin_object_size(buf, 1);
+ // CHECK: @llvm.objectsize
+ gi = __builtin_object_size(buf, 2);
+ // CHECK: store i32 0
+ gi = __builtin_object_size(buf, 3);
+
+ short *const arr_big = my_calloc((size_t)-1 / 2 - 1, 2);
+ // CHECK: @llvm.objectsize
+ gi = __builtin_object_size(arr_big, 0);
+ // CHECK: @llvm.objectsize
+ gi = __builtin_object_size(arr_big, 1);
+ // CHECK: @llvm.objectsize
+ gi = __builtin_object_size(arr_big, 2);
+ // CHECK: store i32 0
+ gi = __builtin_object_size(arr_big, 3);
+}
+
+void *my_tiny_malloc(char) __attribute__((alloc_size(1)));
+void *my_tiny_calloc(char, char) __attribute__((alloc_size(1, 2)));
+
+// CHECK-LABEL: @test11
+void test11() {
+ void *const vp = my_tiny_malloc(100);
+ // CHECK: store i32 100
+ gi = __builtin_object_size(vp, 0);
+ // CHECK: store i32 100
+ gi = __builtin_object_size(vp, 1);
+ // CHECK: store i32 100
+ gi = __builtin_object_size(vp, 2);
+ // CHECK: store i32 100
+ gi = __builtin_object_size(vp, 3);
+
+ // N.B. This causes char overflow, but not size_t overflow, so it should be
+ // supported.
+ void *const arr = my_tiny_calloc(100, 5);
+ // CHECK: store i32 500
+ gi = __builtin_object_size(arr, 0);
+ // CHECK: store i32 500
+ gi = __builtin_object_size(arr, 1);
+ // CHECK: store i32 500
+ gi = __builtin_object_size(arr, 2);
+ // CHECK: store i32 500
+ gi = __builtin_object_size(arr, 3);
+}
+
+void *my_signed_malloc(long) __attribute__((alloc_size(1)));
+void *my_signed_calloc(long, long) __attribute__((alloc_size(1, 2)));
+
+// CHECK-LABEL: @test12
+void test12() {
+ // CHECK: store i32 100
+ gi = __builtin_object_size(my_signed_malloc(100), 0);
+ // CHECK: store i32 500
+ gi = __builtin_object_size(my_signed_calloc(100, 5), 0);
+
+ void *const vp = my_signed_malloc(-2);
+ // CHECK: @llvm.objectsize
+ gi = __builtin_object_size(vp, 0);
+ // N.B. These get lowered to -1 because the function calls may have
+ // side-effects, and we can't determine the objectsize.
+ // CHECK: store i32 -1
+ gi = __builtin_object_size(my_signed_malloc(-2), 0);
+
+ void *const arr1 = my_signed_calloc(-2, 1);
+ void *const arr2 = my_signed_calloc(1, -2);
+ // CHECK: @llvm.objectsize
+ gi = __builtin_object_size(arr1, 0);
+ // CHECK: @llvm.objectsize
+ gi = __builtin_object_size(arr2, 0);
+ // CHECK: store i32 -1
+ gi = __builtin_object_size(my_signed_calloc(1, -2), 0);
+ // CHECK: store i32 -1
+ gi = __builtin_object_size(my_signed_calloc(-2, 1), 0);
+}
diff --git a/test/CodeGen/always_inline.c b/test/CodeGen/always_inline.c
index c91fd43f2761..19d93d9db066 100644
--- a/test/CodeGen/always_inline.c
+++ b/test/CodeGen/always_inline.c
@@ -1,7 +1,7 @@
// RUN: %clang -emit-llvm -S -o %t %s
// RUN: not grep '@f0' %t
// RUN: not grep 'call ' %t
-// RUN: %clang -mllvm -disable-llvm-optzns -emit-llvm -S -o %t %s
+// RUN: %clang -mllvm -disable-llvm-passes -emit-llvm -S -o %t %s
// RUN: grep '@f0' %t | count 2
//static int f0() {
diff --git a/test/CodeGen/arm-neon-directed-rounding.c b/test/CodeGen/arm-neon-directed-rounding.c
index 3625e63b17a0..7471b1c230c9 100644
--- a/test/CodeGen/arm-neon-directed-rounding.c
+++ b/test/CodeGen/arm-neon-directed-rounding.c
@@ -3,133 +3,85 @@
#include <arm_neon.h>
// CHECK-LABEL: define <2 x float> @test_vrnda_f32(<2 x float> %a) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[VRNDA_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VRNDA_V1_I:%.*]] = call <2 x float> @llvm.arm.neon.vrinta.v2f32(<2 x float> [[VRNDA_V_I]]) #2
-// CHECK: [[VRNDA_V2_I:%.*]] = bitcast <2 x float> [[VRNDA_V1_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[VRNDA_V2_I]] to <2 x float>
-// CHECK: ret <2 x float> [[TMP1]]
+// 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]]
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: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[VRNDAQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VRNDAQ_V1_I:%.*]] = call <4 x float> @llvm.arm.neon.vrinta.v4f32(<4 x float> [[VRNDAQ_V_I]]) #2
-// CHECK: [[VRNDAQ_V2_I:%.*]] = bitcast <4 x float> [[VRNDAQ_V1_I]] to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[VRNDAQ_V2_I]] to <4 x float>
-// CHECK: ret <4 x float> [[TMP1]]
+// 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]]
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: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[VRNDM_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VRNDM_V1_I:%.*]] = call <2 x float> @llvm.arm.neon.vrintm.v2f32(<2 x float> [[VRNDM_V_I]]) #2
-// CHECK: [[VRNDM_V2_I:%.*]] = bitcast <2 x float> [[VRNDM_V1_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[VRNDM_V2_I]] to <2 x float>
-// CHECK: ret <2 x float> [[TMP1]]
+// 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]]
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: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[VRNDMQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VRNDMQ_V1_I:%.*]] = call <4 x float> @llvm.arm.neon.vrintm.v4f32(<4 x float> [[VRNDMQ_V_I]]) #2
-// CHECK: [[VRNDMQ_V2_I:%.*]] = bitcast <4 x float> [[VRNDMQ_V1_I]] to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[VRNDMQ_V2_I]] to <4 x float>
-// CHECK: ret <4 x float> [[TMP1]]
+// 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]]
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: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[VRNDN_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VRNDN_V1_I:%.*]] = call <2 x float> @llvm.arm.neon.vrintn.v2f32(<2 x float> [[VRNDN_V_I]]) #2
-// CHECK: [[VRNDN_V2_I:%.*]] = bitcast <2 x float> [[VRNDN_V1_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[VRNDN_V2_I]] to <2 x float>
-// CHECK: ret <2 x float> [[TMP1]]
+// 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]]
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: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[VRNDNQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VRNDNQ_V1_I:%.*]] = call <4 x float> @llvm.arm.neon.vrintn.v4f32(<4 x float> [[VRNDNQ_V_I]]) #2
-// CHECK: [[VRNDNQ_V2_I:%.*]] = bitcast <4 x float> [[VRNDNQ_V1_I]] to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[VRNDNQ_V2_I]] to <4 x float>
-// CHECK: ret <4 x float> [[TMP1]]
+// 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]]
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: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[VRNDP_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VRNDP_V1_I:%.*]] = call <2 x float> @llvm.arm.neon.vrintp.v2f32(<2 x float> [[VRNDP_V_I]]) #2
-// CHECK: [[VRNDP_V2_I:%.*]] = bitcast <2 x float> [[VRNDP_V1_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[VRNDP_V2_I]] to <2 x float>
-// CHECK: ret <2 x float> [[TMP1]]
+// 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]]
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: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[VRNDPQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VRNDPQ_V1_I:%.*]] = call <4 x float> @llvm.arm.neon.vrintp.v4f32(<4 x float> [[VRNDPQ_V_I]]) #2
-// CHECK: [[VRNDPQ_V2_I:%.*]] = bitcast <4 x float> [[VRNDPQ_V1_I]] to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[VRNDPQ_V2_I]] to <4 x float>
-// CHECK: ret <4 x float> [[TMP1]]
+// 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]]
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: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[VRNDX_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VRNDX_V1_I:%.*]] = call <2 x float> @llvm.arm.neon.vrintx.v2f32(<2 x float> [[VRNDX_V_I]]) #2
-// CHECK: [[VRNDX_V2_I:%.*]] = bitcast <2 x float> [[VRNDX_V1_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[VRNDX_V2_I]] to <2 x float>
-// CHECK: ret <2 x float> [[TMP1]]
+// 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]]
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: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[VRNDXQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VRNDXQ_V1_I:%.*]] = call <4 x float> @llvm.arm.neon.vrintx.v4f32(<4 x float> [[VRNDXQ_V_I]]) #2
-// CHECK: [[VRNDXQ_V2_I:%.*]] = bitcast <4 x float> [[VRNDXQ_V1_I]] to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[VRNDXQ_V2_I]] to <4 x float>
-// CHECK: ret <4 x float> [[TMP1]]
+// 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]]
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: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[VRND_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VRND_V1_I:%.*]] = call <2 x float> @llvm.arm.neon.vrintz.v2f32(<2 x float> [[VRND_V_I]]) #2
-// CHECK: [[VRND_V2_I:%.*]] = bitcast <2 x float> [[VRND_V1_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[VRND_V2_I]] to <2 x float>
-// CHECK: ret <2 x float> [[TMP1]]
+// 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]]
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: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[VRNDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VRNDQ_V1_I:%.*]] = call <4 x float> @llvm.arm.neon.vrintz.v4f32(<4 x float> [[VRNDQ_V_I]]) #2
-// CHECK: [[VRNDQ_V2_I:%.*]] = bitcast <4 x float> [[VRNDQ_V1_I]] to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[VRNDQ_V2_I]] to <4 x float>
-// CHECK: ret <4 x float> [[TMP1]]
+// 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]]
float32x4_t test_vrndq_f32(float32x4_t a) {
return vrndq_f32(a);
}
diff --git a/test/CodeGen/arm-neon-fma.c b/test/CodeGen/arm-neon-fma.c
index ff6acbcc2e91..9311f6be6834 100644
--- a/test/CodeGen/arm-neon-fma.c
+++ b/test/CodeGen/arm-neon-fma.c
@@ -8,26 +8,14 @@
#include <arm_neon.h>
// CHECK-LABEL: define <2 x float> @test_fma_order(<2 x float> %accum, <2 x float> %lhs, <2 x float> %rhs) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %accum to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %lhs to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <2 x float> %rhs to <8 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK: [[TMP5:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x float>
-// CHECK: [[TMP6:%.*]] = call <2 x float> @llvm.fma.v2f32(<2 x float> [[TMP4]], <2 x float> [[TMP5]], <2 x float> [[TMP3]]) #2
+// CHECK: [[TMP6:%.*]] = call <2 x float> @llvm.fma.v2f32(<2 x float> %lhs, <2 x float> %rhs, <2 x float> %accum) #2
// CHECK: ret <2 x float> [[TMP6]]
float32x2_t test_fma_order(float32x2_t accum, float32x2_t lhs, float32x2_t rhs) {
return vfma_f32(accum, lhs, rhs);
}
// CHECK-LABEL: define <4 x float> @test_fmaq_order(<4 x float> %accum, <4 x float> %lhs, <4 x float> %rhs) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %accum to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %lhs to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <4 x float> %rhs to <16 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <4 x float>
-// CHECK: [[TMP6:%.*]] = call <4 x float> @llvm.fma.v4f32(<4 x float> [[TMP4]], <4 x float> [[TMP5]], <4 x float> [[TMP3]]) #2
+// CHECK: [[TMP6:%.*]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %lhs, <4 x float> %rhs, <4 x float> %accum) #2
// CHECK: ret <4 x float> [[TMP6]]
float32x4_t test_fmaq_order(float32x4_t accum, float32x4_t lhs, float32x4_t rhs) {
return vfmaq_f32(accum, lhs, rhs);
diff --git a/test/CodeGen/arm-neon-numeric-maxmin.c b/test/CodeGen/arm-neon-numeric-maxmin.c
index 6e385b9c49ef..38f020a756df 100644
--- a/test/CodeGen/arm-neon-numeric-maxmin.c
+++ b/test/CodeGen/arm-neon-numeric-maxmin.c
@@ -3,53 +3,29 @@
#include <arm_neon.h>
// CHECK-LABEL: define <2 x float> @test_vmaxnm_f32(<2 x float> %a, <2 x float> %b) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %b to <8 x i8>
-// CHECK: [[VMAXNM_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VMAXNM_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK: [[VMAXNM_V2_I:%.*]] = call <2 x float> @llvm.arm.neon.vmaxnm.v2f32(<2 x float> [[VMAXNM_V_I]], <2 x float> [[VMAXNM_V1_I]]) #2
-// CHECK: [[VMAXNM_V3_I:%.*]] = bitcast <2 x float> [[VMAXNM_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VMAXNM_V3_I]] to <2 x float>
-// CHECK: ret <2 x float> [[TMP2]]
+// CHECK: [[VMAXNM_V2_I:%.*]] = call <2 x float> @llvm.arm.neon.vmaxnm.v2f32(<2 x float> %a, <2 x float> %b) #2
+// CHECK: ret <2 x float> [[VMAXNM_V2_I]]
float32x2_t test_vmaxnm_f32(float32x2_t a, float32x2_t b) {
return vmaxnm_f32(a, b);
}
// CHECK-LABEL: define <4 x float> @test_vmaxnmq_f32(<4 x float> %a, <4 x float> %b) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %b to <16 x i8>
-// CHECK: [[VMAXNMQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VMAXNMQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
-// CHECK: [[VMAXNMQ_V2_I:%.*]] = call <4 x float> @llvm.arm.neon.vmaxnm.v4f32(<4 x float> [[VMAXNMQ_V_I]], <4 x float> [[VMAXNMQ_V1_I]]) #2
-// CHECK: [[VMAXNMQ_V3_I:%.*]] = bitcast <4 x float> [[VMAXNMQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VMAXNMQ_V3_I]] to <4 x float>
-// CHECK: ret <4 x float> [[TMP2]]
+// CHECK: [[VMAXNMQ_V2_I:%.*]] = call <4 x float> @llvm.arm.neon.vmaxnm.v4f32(<4 x float> %a, <4 x float> %b) #2
+// CHECK: ret <4 x float> [[VMAXNMQ_V2_I]]
float32x4_t test_vmaxnmq_f32(float32x4_t a, float32x4_t b) {
return vmaxnmq_f32(a, b);
}
// CHECK-LABEL: define <2 x float> @test_vminnm_f32(<2 x float> %a, <2 x float> %b) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %b to <8 x i8>
-// CHECK: [[VMINNM_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VMINNM_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK: [[VMINNM_V2_I:%.*]] = call <2 x float> @llvm.arm.neon.vminnm.v2f32(<2 x float> [[VMINNM_V_I]], <2 x float> [[VMINNM_V1_I]]) #2
-// CHECK: [[VMINNM_V3_I:%.*]] = bitcast <2 x float> [[VMINNM_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VMINNM_V3_I]] to <2 x float>
-// CHECK: ret <2 x float> [[TMP2]]
+// CHECK: [[VMINNM_V2_I:%.*]] = call <2 x float> @llvm.arm.neon.vminnm.v2f32(<2 x float> %a, <2 x float> %b) #2
+// CHECK: ret <2 x float> [[VMINNM_V2_I]]
float32x2_t test_vminnm_f32(float32x2_t a, float32x2_t b) {
return vminnm_f32(a, b);
}
// CHECK-LABEL: define <4 x float> @test_vminnmq_f32(<4 x float> %a, <4 x float> %b) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %b to <16 x i8>
-// CHECK: [[VMINNMQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VMINNMQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
-// CHECK: [[VMINNMQ_V2_I:%.*]] = call <4 x float> @llvm.arm.neon.vminnm.v4f32(<4 x float> [[VMINNMQ_V_I]], <4 x float> [[VMINNMQ_V1_I]]) #2
-// CHECK: [[VMINNMQ_V3_I:%.*]] = bitcast <4 x float> [[VMINNMQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VMINNMQ_V3_I]] to <4 x float>
-// CHECK: ret <4 x float> [[TMP2]]
+// CHECK: [[VMINNMQ_V2_I:%.*]] = call <4 x float> @llvm.arm.neon.vminnm.v4f32(<4 x float> %a, <4 x float> %b) #2
+// CHECK: ret <4 x float> [[VMINNMQ_V2_I]]
float32x4_t test_vminnmq_f32(float32x4_t a, float32x4_t b) {
return vminnmq_f32(a, b);
}
diff --git a/test/CodeGen/arm-neon-vcvtX.c b/test/CodeGen/arm-neon-vcvtX.c
index 20cd97c858cb..4ea8fa874e48 100644
--- a/test/CodeGen/arm-neon-vcvtX.c
+++ b/test/CodeGen/arm-neon-vcvtX.c
@@ -3,144 +3,112 @@
#include <arm_neon.h>
// CHECK-LABEL: define <2 x i32> @test_vcvta_s32_f32(<2 x float> %a) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[VCVTA_S32_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VCVTA_S32_V1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vcvtas.v2i32.v2f32(<2 x float> [[VCVTA_S32_V_I]]) #2
+// CHECK: [[VCVTA_S32_V1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vcvtas.v2i32.v2f32(<2 x float> %a) #2
// CHECK: ret <2 x i32> [[VCVTA_S32_V1_I]]
int32x2_t test_vcvta_s32_f32(float32x2_t a) {
return vcvta_s32_f32(a);
}
// CHECK-LABEL: define <2 x i32> @test_vcvta_u32_f32(<2 x float> %a) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[VCVTA_U32_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VCVTA_U32_V1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vcvtau.v2i32.v2f32(<2 x float> [[VCVTA_U32_V_I]]) #2
+// CHECK: [[VCVTA_U32_V1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vcvtau.v2i32.v2f32(<2 x float> %a) #2
// CHECK: ret <2 x i32> [[VCVTA_U32_V1_I]]
uint32x2_t test_vcvta_u32_f32(float32x2_t a) {
return vcvta_u32_f32(a);
}
// CHECK-LABEL: define <4 x i32> @test_vcvtaq_s32_f32(<4 x float> %a) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[VCVTAQ_S32_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VCVTAQ_S32_V1_I:%.*]] = call <4 x i32> @llvm.arm.neon.vcvtas.v4i32.v4f32(<4 x float> [[VCVTAQ_S32_V_I]]) #2
+// CHECK: [[VCVTAQ_S32_V1_I:%.*]] = call <4 x i32> @llvm.arm.neon.vcvtas.v4i32.v4f32(<4 x float> %a) #2
// CHECK: ret <4 x i32> [[VCVTAQ_S32_V1_I]]
int32x4_t test_vcvtaq_s32_f32(float32x4_t a) {
return vcvtaq_s32_f32(a);
}
// CHECK-LABEL: define <4 x i32> @test_vcvtaq_u32_f32(<4 x float> %a) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[VCVTAQ_U32_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VCVTAQ_U32_V1_I:%.*]] = call <4 x i32> @llvm.arm.neon.vcvtau.v4i32.v4f32(<4 x float> [[VCVTAQ_U32_V_I]]) #2
+// CHECK: [[VCVTAQ_U32_V1_I:%.*]] = call <4 x i32> @llvm.arm.neon.vcvtau.v4i32.v4f32(<4 x float> %a) #2
// CHECK: ret <4 x i32> [[VCVTAQ_U32_V1_I]]
uint32x4_t test_vcvtaq_u32_f32(float32x4_t a) {
return vcvtaq_u32_f32(a);
}
// CHECK-LABEL: define <2 x i32> @test_vcvtn_s32_f32(<2 x float> %a) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[VCVTN_S32_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VCVTN_S32_V1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vcvtns.v2i32.v2f32(<2 x float> [[VCVTN_S32_V_I]]) #2
+// CHECK: [[VCVTN_S32_V1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vcvtns.v2i32.v2f32(<2 x float> %a) #2
// CHECK: ret <2 x i32> [[VCVTN_S32_V1_I]]
int32x2_t test_vcvtn_s32_f32(float32x2_t a) {
return vcvtn_s32_f32(a);
}
// CHECK-LABEL: define <2 x i32> @test_vcvtn_u32_f32(<2 x float> %a) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[VCVTN_U32_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VCVTN_U32_V1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vcvtnu.v2i32.v2f32(<2 x float> [[VCVTN_U32_V_I]]) #2
+// CHECK: [[VCVTN_U32_V1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vcvtnu.v2i32.v2f32(<2 x float> %a) #2
// CHECK: ret <2 x i32> [[VCVTN_U32_V1_I]]
uint32x2_t test_vcvtn_u32_f32(float32x2_t a) {
return vcvtn_u32_f32(a);
}
// CHECK-LABEL: define <4 x i32> @test_vcvtnq_s32_f32(<4 x float> %a) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[VCVTNQ_S32_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VCVTNQ_S32_V1_I:%.*]] = call <4 x i32> @llvm.arm.neon.vcvtns.v4i32.v4f32(<4 x float> [[VCVTNQ_S32_V_I]]) #2
+// CHECK: [[VCVTNQ_S32_V1_I:%.*]] = call <4 x i32> @llvm.arm.neon.vcvtns.v4i32.v4f32(<4 x float> %a) #2
// CHECK: ret <4 x i32> [[VCVTNQ_S32_V1_I]]
int32x4_t test_vcvtnq_s32_f32(float32x4_t a) {
return vcvtnq_s32_f32(a);
}
// CHECK-LABEL: define <4 x i32> @test_vcvtnq_u32_f32(<4 x float> %a) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[VCVTNQ_U32_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VCVTNQ_U32_V1_I:%.*]] = call <4 x i32> @llvm.arm.neon.vcvtnu.v4i32.v4f32(<4 x float> [[VCVTNQ_U32_V_I]]) #2
+// CHECK: [[VCVTNQ_U32_V1_I:%.*]] = call <4 x i32> @llvm.arm.neon.vcvtnu.v4i32.v4f32(<4 x float> %a) #2
// CHECK: ret <4 x i32> [[VCVTNQ_U32_V1_I]]
uint32x4_t test_vcvtnq_u32_f32(float32x4_t a) {
return vcvtnq_u32_f32(a);
}
// CHECK-LABEL: define <2 x i32> @test_vcvtp_s32_f32(<2 x float> %a) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[VCVTP_S32_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VCVTP_S32_V1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vcvtps.v2i32.v2f32(<2 x float> [[VCVTP_S32_V_I]]) #2
+// CHECK: [[VCVTP_S32_V1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vcvtps.v2i32.v2f32(<2 x float> %a) #2
// CHECK: ret <2 x i32> [[VCVTP_S32_V1_I]]
int32x2_t test_vcvtp_s32_f32(float32x2_t a) {
return vcvtp_s32_f32(a);
}
// CHECK-LABEL: define <2 x i32> @test_vcvtp_u32_f32(<2 x float> %a) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[VCVTP_U32_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VCVTP_U32_V1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vcvtpu.v2i32.v2f32(<2 x float> [[VCVTP_U32_V_I]]) #2
+// CHECK: [[VCVTP_U32_V1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vcvtpu.v2i32.v2f32(<2 x float> %a) #2
// CHECK: ret <2 x i32> [[VCVTP_U32_V1_I]]
uint32x2_t test_vcvtp_u32_f32(float32x2_t a) {
return vcvtp_u32_f32(a);
}
// CHECK-LABEL: define <4 x i32> @test_vcvtpq_s32_f32(<4 x float> %a) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[VCVTPQ_S32_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VCVTPQ_S32_V1_I:%.*]] = call <4 x i32> @llvm.arm.neon.vcvtps.v4i32.v4f32(<4 x float> [[VCVTPQ_S32_V_I]]) #2
+// CHECK: [[VCVTPQ_S32_V1_I:%.*]] = call <4 x i32> @llvm.arm.neon.vcvtps.v4i32.v4f32(<4 x float> %a) #2
// CHECK: ret <4 x i32> [[VCVTPQ_S32_V1_I]]
int32x4_t test_vcvtpq_s32_f32(float32x4_t a) {
return vcvtpq_s32_f32(a);
}
// CHECK-LABEL: define <4 x i32> @test_vcvtpq_u32_f32(<4 x float> %a) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[VCVTPQ_U32_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VCVTPQ_U32_V1_I:%.*]] = call <4 x i32> @llvm.arm.neon.vcvtpu.v4i32.v4f32(<4 x float> [[VCVTPQ_U32_V_I]]) #2
+// CHECK: [[VCVTPQ_U32_V1_I:%.*]] = call <4 x i32> @llvm.arm.neon.vcvtpu.v4i32.v4f32(<4 x float> %a) #2
// CHECK: ret <4 x i32> [[VCVTPQ_U32_V1_I]]
uint32x4_t test_vcvtpq_u32_f32(float32x4_t a) {
return vcvtpq_u32_f32(a);
}
// CHECK-LABEL: define <2 x i32> @test_vcvtm_s32_f32(<2 x float> %a) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[VCVTM_S32_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VCVTM_S32_V1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vcvtms.v2i32.v2f32(<2 x float> [[VCVTM_S32_V_I]]) #2
+// CHECK: [[VCVTM_S32_V1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vcvtms.v2i32.v2f32(<2 x float> %a) #2
// CHECK: ret <2 x i32> [[VCVTM_S32_V1_I]]
int32x2_t test_vcvtm_s32_f32(float32x2_t a) {
return vcvtm_s32_f32(a);
}
// CHECK-LABEL: define <2 x i32> @test_vcvtm_u32_f32(<2 x float> %a) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[VCVTM_U32_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VCVTM_U32_V1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vcvtmu.v2i32.v2f32(<2 x float> [[VCVTM_U32_V_I]]) #2
+// CHECK: [[VCVTM_U32_V1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vcvtmu.v2i32.v2f32(<2 x float> %a) #2
// CHECK: ret <2 x i32> [[VCVTM_U32_V1_I]]
uint32x2_t test_vcvtm_u32_f32(float32x2_t a) {
return vcvtm_u32_f32(a);
}
// CHECK-LABEL: define <4 x i32> @test_vcvtmq_s32_f32(<4 x float> %a) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[VCVTMQ_S32_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VCVTMQ_S32_V1_I:%.*]] = call <4 x i32> @llvm.arm.neon.vcvtms.v4i32.v4f32(<4 x float> [[VCVTMQ_S32_V_I]]) #2
+// CHECK: [[VCVTMQ_S32_V1_I:%.*]] = call <4 x i32> @llvm.arm.neon.vcvtms.v4i32.v4f32(<4 x float> %a) #2
// CHECK: ret <4 x i32> [[VCVTMQ_S32_V1_I]]
int32x4_t test_vcvtmq_s32_f32(float32x4_t a) {
return vcvtmq_s32_f32(a);
}
// CHECK-LABEL: define <4 x i32> @test_vcvtmq_u32_f32(<4 x float> %a) #0 {
-// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[VCVTMQ_U32_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VCVTMQ_U32_V1_I:%.*]] = call <4 x i32> @llvm.arm.neon.vcvtmu.v4i32.v4f32(<4 x float> [[VCVTMQ_U32_V_I]]) #2
+// CHECK: [[VCVTMQ_U32_V1_I:%.*]] = call <4 x i32> @llvm.arm.neon.vcvtmu.v4i32.v4f32(<4 x float> %a) #2
// CHECK: ret <4 x i32> [[VCVTMQ_U32_V1_I]]
uint32x4_t test_vcvtmq_u32_f32(float32x4_t a) {
return vcvtmq_u32_f32(a);
diff --git a/test/CodeGen/arm-swiftcall.c b/test/CodeGen/arm-swiftcall.c
index d54a31337085..5a7e17068b7c 100644
--- a/test/CodeGen/arm-swiftcall.c
+++ b/test/CodeGen/arm-swiftcall.c
@@ -1,7 +1,6 @@
// RUN: %clang_cc1 -triple armv7-apple-darwin9 -emit-llvm -o - %s | FileCheck %s
-
-// This isn't really testing anything ARM-specific; it's just a convenient
-// 32-bit platform.
+// RUN: %clang_cc1 -triple armv7s-apple-ios9 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple armv7k-apple-ios9 -emit-llvm -o - %s | FileCheck %s
#define SWIFTCALL __attribute__((swiftcall))
#define OUT __attribute__((swift_indirect_result))
@@ -66,6 +65,9 @@ typedef int int3 __attribute__((ext_vector_type(3)));
typedef int int4 __attribute__((ext_vector_type(4)));
typedef int int5 __attribute__((ext_vector_type(5)));
typedef int int8 __attribute__((ext_vector_type(8)));
+typedef char char16 __attribute__((ext_vector_type(16)));
+typedef short short8 __attribute__((ext_vector_type(8)));
+typedef long long long2 __attribute__((ext_vector_type(2)));
#define TEST(TYPE) \
SWIFTCALL TYPE return_##TYPE(void) { \
@@ -278,41 +280,41 @@ typedef union {
} union_het_fp;
TEST(union_het_fp)
// CHECK-LABEL: define {{.*}} @return_union_het_fp()
-// CHECK: [[RET:%.*]] = alloca [[REC:%.*]], align 4
-// CHECK: [[VAR:%.*]] = alloca [[REC]], align 4
+// 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
-// CHECK: [[FIRST:%.*]] = load i32, i32* [[T0]], align 4
+// CHECK: [[FIRST:%.*]] = load i32, i32* [[T0]], align {{(4|8)}}
// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
-// CHECK: [[SECOND:%.*]] = load i32, i32* [[T0]], align 4
+// CHECK: [[SECOND:%.*]] = load i32, i32* [[T0]], align {{(4|8)}}
// CHECK: [[T0:%.*]] = insertvalue [[UAGG:{ i32, i32 }]] undef, i32 [[FIRST]], 0
// CHECK: [[T1:%.*]] = insertvalue [[UAGG]] [[T0]], i32 [[SECOND]], 1
// CHECK: ret [[UAGG]] [[T1]]
// CHECK-LABEL: define {{.*}} @take_union_het_fp(i32, i32)
-// CHECK: [[V:%.*]] = alloca [[REC]], align 4
+// CHECK: [[V:%.*]] = alloca [[REC]], align {{(4|8)}}
// CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[V]] to [[AGG]]*
// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
-// CHECK: store i32 %0, i32* [[T0]], align 4
+// CHECK: store i32 %0, i32* [[T0]], align {{(4|8)}}
// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
-// CHECK: store i32 %1, i32* [[T0]], align 4
+// CHECK: store i32 %1, i32* [[T0]], align {{(4|8)}}
// CHECK: ret void
// CHECK-LABEL: define void @test_union_het_fp()
-// CHECK: [[TMP:%.*]] = alloca [[REC]], align 4
+// CHECK: [[TMP:%.*]] = alloca [[REC]], align {{(4|8)}}
// CHECK: [[CALL:%.*]] = call [[SWIFTCC]] [[UAGG]] @return_union_het_fp()
// CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP]] to [[AGG]]*
// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
// CHECK: [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 0
-// CHECK: store i32 [[T1]], i32* [[T0]], align 4
+// CHECK: store i32 [[T1]], i32* [[T0]], align {{(4|8)}}
// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
// CHECK: [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 1
-// CHECK: store i32 [[T1]], i32* [[T0]], align 4
+// CHECK: store i32 [[T1]], i32* [[T0]], align {{(4|8)}}
// CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP]] to [[AGG]]*
// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
-// CHECK: [[FIRST:%.*]] = load i32, i32* [[T0]], align 4
+// CHECK: [[FIRST:%.*]] = load i32, i32* [[T0]], align {{(4|8)}}
// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
-// CHECK: [[SECOND:%.*]] = load i32, i32* [[T0]], align 4
+// CHECK: [[SECOND:%.*]] = load i32, i32* [[T0]], align {{(4|8)}}
// CHECK: call [[SWIFTCC]] void @take_union_het_fp(i32 [[FIRST]], i32 [[SECOND]])
// CHECK: ret void
@@ -502,3 +504,512 @@ typedef struct {
} misaligned_int3;
TEST(misaligned_int3)
// CHECK-LABEL: define {{.*}} @take_misaligned_int3(i32, i32, i32, i32)
+
+typedef struct {
+ float f0;
+} struct_f1;
+TEST(struct_f1)
+// CHECK-LABEL: define swiftcc float @return_struct_f1()
+// CHECK-LABEL: define swiftcc void @take_struct_f1(float)
+
+typedef struct {
+ float f0;
+ float f1;
+} struct_f2;
+TEST(struct_f2)
+// CHECK-LABEL: define swiftcc { float, float } @return_struct_f2()
+// CHECK-LABEL: define swiftcc void @take_struct_f2(float, float)
+
+typedef struct {
+ float f0;
+ float f1;
+ float f2;
+} struct_f3;
+TEST(struct_f3)
+// CHECK-LABEL: define swiftcc { float, float, float } @return_struct_f3()
+// CHECK-LABEL: define swiftcc void @take_struct_f3(float, float, float)
+
+typedef struct {
+ float f0;
+ float f1;
+ float f2;
+ float f3;
+} struct_f4;
+TEST(struct_f4)
+// CHECK-LABEL: define swiftcc { float, float, float, float } @return_struct_f4()
+// CHECK-LABEL: define swiftcc void @take_struct_f4(float, float, float, float)
+
+
+typedef struct {
+ double d0;
+} struct_d1;
+TEST(struct_d1)
+// CHECK-LABEL: define swiftcc double @return_struct_d1()
+// CHECK-LABEL: define swiftcc void @take_struct_d1(double)
+
+typedef struct {
+ double d0;
+ double d1;
+} struct_d2;
+TEST(struct_d2)
+// CHECK-LABEL: define swiftcc { double, double } @return_struct_d2()
+// CHECK-LABEL: define swiftcc void @take_struct_d2(double, double)
+
+typedef struct {
+ double d0;
+ double d1;
+ double d2;
+} struct_d3;
+TEST(struct_d3)
+// CHECK-LABEL: define swiftcc { double, double, double } @return_struct_d3()
+// CHECK-LABEL: define swiftcc void @take_struct_d3(double, double, double)
+
+typedef struct {
+ double d0;
+ double d1;
+ double d2;
+ double d3;
+} struct_d4;
+TEST(struct_d4)
+// CHECK-LABEL: define swiftcc { double, double, double, double } @return_struct_d4()
+// CHECK-LABEL: define swiftcc void @take_struct_d4(double, double, double, double)
+
+typedef struct {
+ double d0;
+ double d1;
+ double d2;
+ double d3;
+ double d4;
+} struct_d5;
+TEST(struct_d5)
+// CHECK: define swiftcc void @return_struct_d5([[STRUCT5:%.*]]* noalias sret
+// CHECK: define swiftcc void @take_struct_d5([[STRUCT5]]
+
+typedef struct {
+ char c0;
+} struct_c1;
+TEST(struct_c1)
+// CHECK-LABEL: define swiftcc i8 @return_struct_c1()
+// CHECK-LABEL: define swiftcc void @take_struct_c1(i8)
+
+typedef struct {
+ char c0;
+ char c1;
+} struct_c2;
+TEST(struct_c2)
+// CHECK-LABEL: define swiftcc i16 @return_struct_c2()
+// CHECK-LABEL: define swiftcc void @take_struct_c2(i16)
+//
+
+typedef struct {
+ char c0;
+ char c1;
+ char c2;
+} struct_c3;
+TEST(struct_c3)
+// CHECK-LABEL: define swiftcc i32 @return_struct_c3()
+// CHECK-LABEL: define swiftcc void @take_struct_c3(i32)
+
+typedef struct {
+ char c0;
+ char c1;
+ char c2;
+ char c3;
+} struct_c4;
+TEST(struct_c4)
+// CHECK-LABEL: define swiftcc i32 @return_struct_c4()
+// CHECK-LABEL: define swiftcc void @take_struct_c4(i32)
+
+typedef struct {
+ char c0;
+ char c1;
+ char c2;
+ char c3;
+ char c4;
+} struct_c5;
+TEST(struct_c5)
+// CHECK-LABEL: define swiftcc { i32, i8 } @return_struct_c5()
+// CHECK-LABEL: define swiftcc void @take_struct_c5(i32, i8)
+
+typedef struct {
+ short s0;
+} struct_s1;
+TEST(struct_s1)
+// CHECK-LABEL: define swiftcc i16 @return_struct_s1()
+// CHECK-LABEL: define swiftcc void @take_struct_s1(i16)
+
+typedef struct {
+ short s0;
+ short s1;
+} struct_s2;
+TEST(struct_s2)
+// CHECK-LABEL: define swiftcc i32 @return_struct_s2()
+// CHECK-LABEL: define swiftcc void @take_struct_s2(i32)
+
+typedef struct {
+ short s0;
+ short s1;
+ short s2;
+} struct_s3;
+TEST(struct_s3)
+// CHECK-LABEL: define swiftcc { i32, i16 } @return_struct_s3()
+// CHECK-LABEL: define swiftcc void @take_struct_s3(i32, i16)
+
+typedef struct {
+ short s0;
+ short s1;
+ short s2;
+ short s3;
+} struct_s4;
+TEST(struct_s4)
+// CHECK-LABEL: define swiftcc { i32, i32 } @return_struct_s4()
+// CHECK-LABEL: define swiftcc void @take_struct_s4(i32, i32)
+
+typedef struct {
+ short s0;
+ short s1;
+ short s2;
+ short s3;
+ short s4;
+} struct_s5;
+TEST(struct_s5)
+// CHECK-LABEL: define swiftcc { i32, i32, i16 } @return_struct_s5()
+// CHECK-LABEL: define swiftcc void @take_struct_s5(i32, i32, i16)
+
+
+typedef struct {
+ int i0;
+} struct_i1;
+TEST(struct_i1)
+// CHECK-LABEL: define swiftcc i32 @return_struct_i1()
+// CHECK-LABEL: define swiftcc void @take_struct_i1(i32)
+
+typedef struct {
+ int i0;
+ int i1;
+} struct_i2;
+TEST(struct_i2)
+// CHECK-LABEL: define swiftcc { i32, i32 } @return_struct_i2()
+// CHECK-LABEL: define swiftcc void @take_struct_i2(i32, i32)
+
+typedef struct {
+ int i0;
+ int i1;
+ int i2;
+} struct_i3;
+TEST(struct_i3)
+// CHECK-LABEL: define swiftcc { i32, i32, i32 } @return_struct_i3()
+// CHECK-LABEL: define swiftcc void @take_struct_i3(i32, i32, i32)
+
+typedef struct {
+ int i0;
+ int i1;
+ int i2;
+ int i3;
+} struct_i4;
+TEST(struct_i4)
+// CHECK-LABEL: define swiftcc { i32, i32, i32, i32 } @return_struct_i4()
+// CHECK-LABEL: define swiftcc void @take_struct_i4(i32, i32, i32, i32)
+
+typedef struct {
+ long long l0;
+} struct_l1;
+TEST(struct_l1)
+// CHECK-LABEL: define swiftcc i64 @return_struct_l1()
+// CHECK-LABEL: define swiftcc void @take_struct_l1(i64)
+
+typedef struct {
+ long long l0;
+ long long l1;
+} struct_l2;
+TEST(struct_l2)
+// CHECK-LABEL: define swiftcc { i64, i64 } @return_struct_l2()
+// CHECK-LABEL: define swiftcc void @take_struct_l2(i64, i64)
+
+typedef struct {
+ long long l0;
+ long long l1;
+ long long l2;
+} struct_l3;
+TEST(struct_l3)
+// CHECK: define swiftcc void @return_struct_l3([[STRUCT:%.*]]* noalias sret
+// CHECK: define swiftcc void @take_struct_l3([[STRUCT]]
+
+typedef struct {
+ long long l0;
+ long long l1;
+ long long l2;
+ long long l3;
+} struct_l4;
+TEST(struct_l4)
+// CHECK: define swiftcc void @return_struct_l4([[STRUCT:%.*]]* noalias sret
+// CHECK: define swiftcc void @take_struct_l4([[STRUCT]]
+
+typedef struct {
+ long long l0;
+ long long l1;
+ long long l2;
+ long long l3;
+ long long l4;
+} struct_l5;
+TEST(struct_l5)
+// CHECK: define swiftcc void @return_struct_l5([[STRUCT5:%.*]]* noalias sret
+// CHECK: define swiftcc void @take_struct_l5([[STRUCT5]]*
+
+typedef struct {
+ char16 c0;
+} struct_vc1;
+TEST(struct_vc1)
+// CHECK-LABEL: define swiftcc <16 x i8> @return_struct_vc1()
+// CHECK-LABEL: define swiftcc void @take_struct_vc1(<16 x i8>)
+
+typedef struct {
+ char16 c0;
+ char16 c1;
+} struct_vc2;
+TEST(struct_vc2)
+// CHECK-LABEL: define swiftcc { <16 x i8>, <16 x i8> } @return_struct_vc2()
+// CHECK-LABEL: define swiftcc void @take_struct_vc2(<16 x i8>, <16 x i8>)
+
+typedef struct {
+ char16 c0;
+ char16 c1;
+ char16 c2;
+} struct_vc3;
+TEST(struct_vc3)
+// CHECK-LABEL: define swiftcc { <16 x i8>, <16 x i8>, <16 x i8> } @return_struct_vc3()
+// CHECK-LABEL: define swiftcc void @take_struct_vc3(<16 x i8>, <16 x i8>, <16 x i8>)
+
+typedef struct {
+ char16 c0;
+ char16 c1;
+ char16 c2;
+ char16 c3;
+} struct_vc4;
+TEST(struct_vc4)
+// CHECK-LABEL: define swiftcc { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } @return_struct_vc4()
+// CHECK-LABEL: define swiftcc void @take_struct_vc4(<16 x i8>, <16 x i8>, <16 x i8>, <16 x i8>)
+
+typedef struct {
+ char16 c0;
+ char16 c1;
+ char16 c2;
+ char16 c3;
+ char16 c4;
+} struct_vc5;
+TEST(struct_vc5)
+// CHECK: define swiftcc void @return_struct_vc5([[STRUCT:%.*]]* noalias sret
+// CHECK: define swiftcc void @take_struct_vc5([[STRUCT]]
+
+typedef struct {
+ short8 c0;
+} struct_vs1;
+TEST(struct_vs1)
+// CHECK-LABEL: define swiftcc <8 x i16> @return_struct_vs1()
+// CHECK-LABEL: define swiftcc void @take_struct_vs1(<8 x i16>)
+
+typedef struct {
+ short8 c0;
+ short8 c1;
+} struct_vs2;
+TEST(struct_vs2)
+// CHECK-LABEL: define swiftcc { <8 x i16>, <8 x i16> } @return_struct_vs2()
+// CHECK-LABEL: define swiftcc void @take_struct_vs2(<8 x i16>, <8 x i16>)
+
+typedef struct {
+ short8 c0;
+ short8 c1;
+ short8 c2;
+} struct_vs3;
+TEST(struct_vs3)
+// CHECK-LABEL: define swiftcc { <8 x i16>, <8 x i16>, <8 x i16> } @return_struct_vs3()
+// CHECK-LABEL: define swiftcc void @take_struct_vs3(<8 x i16>, <8 x i16>, <8 x i16>)
+
+typedef struct {
+ short8 c0;
+ short8 c1;
+ short8 c2;
+ short8 c3;
+} struct_vs4;
+TEST(struct_vs4)
+// CHECK-LABEL: define swiftcc { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } @return_struct_vs4()
+// CHECK-LABEL: define swiftcc void @take_struct_vs4(<8 x i16>, <8 x i16>, <8 x i16>, <8 x i16>)
+
+typedef struct {
+ short8 c0;
+ short8 c1;
+ short8 c2;
+ short8 c3;
+ short8 c4;
+} struct_vs5;
+TEST(struct_vs5)
+// CHECK: define swiftcc void @return_struct_vs5([[STRUCT:%.*]]* noalias sret
+// CHECK: define swiftcc void @take_struct_vs5([[STRUCT]]
+
+typedef struct {
+ int4 c0;
+} struct_vi1;
+TEST(struct_vi1)
+// CHECK-LABEL: define swiftcc <4 x i32> @return_struct_vi1()
+// CHECK-LABEL: define swiftcc void @take_struct_vi1(<4 x i32>)
+
+typedef struct {
+ int4 c0;
+ int4 c1;
+} struct_vi2;
+TEST(struct_vi2)
+// CHECK-LABEL: define swiftcc { <4 x i32>, <4 x i32> } @return_struct_vi2()
+// CHECK-LABEL: define swiftcc void @take_struct_vi2(<4 x i32>, <4 x i32>)
+
+typedef struct {
+ int4 c0;
+ int4 c1;
+ int4 c2;
+} struct_vi3;
+TEST(struct_vi3)
+// CHECK-LABEL: define swiftcc { <4 x i32>, <4 x i32>, <4 x i32> } @return_struct_vi3()
+// CHECK-LABEL: define swiftcc void @take_struct_vi3(<4 x i32>, <4 x i32>, <4 x i32>)
+
+typedef struct {
+ int4 c0;
+ int4 c1;
+ int4 c2;
+ int4 c3;
+} struct_vi4;
+TEST(struct_vi4)
+// CHECK-LABEL: define swiftcc { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } @return_struct_vi4()
+// CHECK-LABEL: define swiftcc void @take_struct_vi4(<4 x i32>, <4 x i32>, <4 x i32>, <4 x i32>)
+
+typedef struct {
+ int4 c0;
+ int4 c1;
+ int4 c2;
+ int4 c3;
+ int4 c4;
+} struct_vi5;
+TEST(struct_vi5)
+// CHECK: define swiftcc void @return_struct_vi5([[STRUCT:%.*]]* noalias sret
+// CHECK: define swiftcc void @take_struct_vi5([[STRUCT]]
+
+typedef struct {
+ long2 c0;
+} struct_vl1;
+TEST(struct_vl1)
+// CHECK-LABEL: define swiftcc <2 x i64> @return_struct_vl1()
+// CHECK-LABEL: define swiftcc void @take_struct_vl1(<2 x i64>)
+
+typedef struct {
+ long2 c0;
+ long2 c1;
+ long2 c2;
+ long2 c3;
+} struct_vl4;
+TEST(struct_vl4)
+// CHECK-LABEL: define swiftcc { <2 x i64>, <2 x i64>, <2 x i64>, <2 x i64> } @return_struct_vl4()
+// CHECK-LABEL: define swiftcc void @take_struct_vl4(<2 x i64>, <2 x i64>, <2 x i64>, <2 x i64>)
+
+typedef struct {
+ long2 c0;
+ long2 c1;
+ long2 c2;
+ long2 c3;
+ long2 c4;
+} struct_vl5;
+TEST(struct_vl5)
+// CHECK: define swiftcc void @return_struct_vl5([[STRUCT:%.*]]* noalias sret
+// CHECK: define swiftcc void @take_struct_vl5([[STRUCT]]
+
+typedef struct {
+ double2 c0;
+} struct_vd1;
+TEST(struct_vd1)
+// CHECK-LABEL: define swiftcc <2 x double> @return_struct_vd1()
+// CHECK-LABEL: define swiftcc void @take_struct_vd1(<2 x double>)
+
+typedef struct {
+ double2 c0;
+ double2 c1;
+ double2 c2;
+ double2 c3;
+} struct_vd4;
+TEST(struct_vd4)
+// CHECK-LABEL: define swiftcc { <2 x double>, <2 x double>, <2 x double>, <2 x double> } @return_struct_vd4()
+// CHECK-LABEL: define swiftcc void @take_struct_vd4(<2 x double>, <2 x double>, <2 x double>, <2 x double>)
+
+typedef struct {
+ double2 c0;
+ double2 c1;
+ double2 c2;
+ double2 c3;
+ double2 c4;
+} struct_vd5;
+TEST(struct_vd5)
+// CHECK: define swiftcc void @return_struct_vd5([[STRUCT:%.*]]* noalias sret
+// CHECK: define swiftcc void @take_struct_vd5([[STRUCT]]
+
+typedef struct {
+ double4 c0;
+} struct_vd41;
+TEST(struct_vd41)
+// CHECK-LABEL: define swiftcc { <2 x double>, <2 x double> } @return_struct_vd41()
+// CHECK-LABEL: define swiftcc void @take_struct_vd41(<2 x double>, <2 x double>)
+
+typedef struct {
+ double4 c0;
+ double4 c1;
+} struct_vd42;
+TEST(struct_vd42)
+// CHECK-LABEL: define swiftcc { <2 x double>, <2 x double>, <2 x double>, <2 x double> } @return_struct_vd42()
+// CHECK-LABEL: define swiftcc void @take_struct_vd42(<2 x double>, <2 x double>, <2 x double>, <2 x double>)
+
+typedef struct {
+ double4 c0;
+ double4 c1;
+ double4 c2;
+} struct_vd43;
+TEST(struct_vd43)
+// CHECK: define swiftcc void @return_struct_vd43([[STRUCT:%.*]]* noalias sret
+// CHECK: define swiftcc void @take_struct_vd43([[STRUCT]]
+
+typedef struct {
+ float4 c0;
+} struct_vf1;
+TEST(struct_vf1)
+// CHECK-LABEL: define swiftcc <4 x float> @return_struct_vf1()
+// CHECK-LABEL: define swiftcc void @take_struct_vf1(<4 x float>)
+
+typedef struct {
+ float4 c0;
+ float4 c1;
+} struct_vf2;
+TEST(struct_vf2)
+// CHECK-LABEL: define swiftcc { <4 x float>, <4 x float> } @return_struct_vf2()
+// CHECK-LABEL: define swiftcc void @take_struct_vf2(<4 x float>, <4 x float>)
+
+typedef struct {
+ float4 c0;
+ float4 c1;
+ float4 c2;
+ float4 c3;
+} struct_vf4;
+TEST(struct_vf4)
+// CHECK-LABEL: define swiftcc { <4 x float>, <4 x float>, <4 x float>, <4 x float> } @return_struct_vf4()
+// CHECK-LABEL: define swiftcc void @take_struct_vf4(<4 x float>, <4 x float>, <4 x float>, <4 x float>)
+
+typedef struct {
+ float4 c0;
+ float4 c1;
+ float4 c2;
+ float4 c3;
+ float4 c4;
+} struct_vf5;
+TEST(struct_vf5)
+// CHECK: define swiftcc void @return_struct_vf5([[STRUCT:%.*]]* noalias sret
+// CHECK: define swiftcc void @take_struct_vf5([[STRUCT]]
+
+typedef struct {
+ float8 c0;
+} struct_vf81;
+TEST(struct_vf81)
+// CHECK-LABEL: define swiftcc { <4 x float>, <4 x float> } @return_struct_vf81()
+// CHECK-LABEL: define swiftcc void @take_struct_vf81(<4 x float>, <4 x float>)
diff --git a/test/CodeGen/arm-target-features.c b/test/CodeGen/arm-target-features.c
index 189c6f701059..7437fb0e4ed2 100644
--- a/test/CodeGen/arm-target-features.c
+++ b/test/CodeGen/arm-target-features.c
@@ -29,6 +29,8 @@
// RUN: %clang_cc1 -triple thumbv8-linux-gnueabihf -target-cpu cortex-a72 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-BASIC-V8
// RUN: %clang_cc1 -triple thumbv8-linux-gnueabihf -target-cpu cortex-a73 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-BASIC-V8
// 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"
diff --git a/test/CodeGen/arm64_crypto.c b/test/CodeGen/arm64_crypto.c
index e63009a3109c..c8bd4f978eb9 100644
--- a/test/CodeGen/arm64_crypto.c
+++ b/test/CodeGen/arm64_crypto.c
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -triple arm64-apple-ios7.0 -target-feature +neon -target-feature +crypto -ffreestanding -Os -S -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple arm64-apple-ios7.0 -target-feature +neon -target-feature +crypto -ffreestanding -fexperimental-new-pass-manager -Os -S -o - %s | FileCheck %s
// REQUIRES: aarch64-registered-target
#include <arm_neon.h>
diff --git a/test/CodeGen/arm_neon_intrinsics.c b/test/CodeGen/arm_neon_intrinsics.c
index 4cc7eedffd5b..ad8587b0db2a 100644
--- a/test/CodeGen/arm_neon_intrinsics.c
+++ b/test/CodeGen/arm_neon_intrinsics.c
@@ -6,7 +6,7 @@
#include <arm_neon.h>
-// CHECK-LABEL: define <8 x i8> @test_vaba_s8(<8 x i8> %a, <8 x i8> %b, <8 x i8> %c) #0 {
+// CHECK-LABEL: @test_vaba_s8(
// CHECK: [[VABD_V_I_I:%.*]] = call <8 x i8> @llvm.arm.neon.vabds.v8i8(<8 x i8> %b, <8 x i8> %c) #4
// CHECK: [[ADD_I:%.*]] = add <8 x i8> %a, [[VABD_V_I_I]]
// CHECK: ret <8 x i8> [[ADD_I]]
@@ -14,35 +14,29 @@ int8x8_t test_vaba_s8(int8x8_t a, int8x8_t b, int8x8_t c) {
return vaba_s8(a, b, c);
}
-// CHECK-LABEL: define <4 x i16> @test_vaba_s16(<4 x i16> %a, <4 x i16> %b, <4 x i16> %c) #0 {
+// CHECK-LABEL: @test_vaba_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %c to <8 x i8>
-// CHECK: [[VABD_V_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VABD_V1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VABD_V2_I_I:%.*]] = call <4 x i16> @llvm.arm.neon.vabds.v4i16(<4 x i16> [[VABD_V_I_I]], <4 x i16> [[VABD_V1_I_I]]) #4
+// CHECK: [[VABD_V2_I_I:%.*]] = call <4 x i16> @llvm.arm.neon.vabds.v4i16(<4 x i16> %b, <4 x i16> %c) #4
// CHECK: [[VABD_V3_I_I:%.*]] = bitcast <4 x i16> [[VABD_V2_I_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VABD_V3_I_I]] to <4 x i16>
-// CHECK: [[ADD_I:%.*]] = add <4 x i16> %a, [[TMP2]]
+// CHECK: [[ADD_I:%.*]] = add <4 x i16> %a, [[VABD_V2_I_I]]
// CHECK: ret <4 x i16> [[ADD_I]]
int16x4_t test_vaba_s16(int16x4_t a, int16x4_t b, int16x4_t c) {
return vaba_s16(a, b, c);
}
-// CHECK-LABEL: define <2 x i32> @test_vaba_s32(<2 x i32> %a, <2 x i32> %b, <2 x i32> %c) #0 {
+// CHECK-LABEL: @test_vaba_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %c to <8 x i8>
-// CHECK: [[VABD_V_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VABD_V1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VABD_V2_I_I:%.*]] = call <2 x i32> @llvm.arm.neon.vabds.v2i32(<2 x i32> [[VABD_V_I_I]], <2 x i32> [[VABD_V1_I_I]]) #4
+// CHECK: [[VABD_V2_I_I:%.*]] = call <2 x i32> @llvm.arm.neon.vabds.v2i32(<2 x i32> %b, <2 x i32> %c) #4
// CHECK: [[VABD_V3_I_I:%.*]] = bitcast <2 x i32> [[VABD_V2_I_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VABD_V3_I_I]] to <2 x i32>
-// CHECK: [[ADD_I:%.*]] = add <2 x i32> %a, [[TMP2]]
+// CHECK: [[ADD_I:%.*]] = add <2 x i32> %a, [[VABD_V2_I_I]]
// CHECK: ret <2 x i32> [[ADD_I]]
int32x2_t test_vaba_s32(int32x2_t a, int32x2_t b, int32x2_t c) {
return vaba_s32(a, b, c);
}
-// CHECK-LABEL: define <8 x i8> @test_vaba_u8(<8 x i8> %a, <8 x i8> %b, <8 x i8> %c) #0 {
+// CHECK-LABEL: @test_vaba_u8(
// CHECK: [[VABD_V_I_I:%.*]] = call <8 x i8> @llvm.arm.neon.vabdu.v8i8(<8 x i8> %b, <8 x i8> %c) #4
// CHECK: [[ADD_I:%.*]] = add <8 x i8> %a, [[VABD_V_I_I]]
// CHECK: ret <8 x i8> [[ADD_I]]
@@ -50,35 +44,29 @@ uint8x8_t test_vaba_u8(uint8x8_t a, uint8x8_t b, uint8x8_t c) {
return vaba_u8(a, b, c);
}
-// CHECK-LABEL: define <4 x i16> @test_vaba_u16(<4 x i16> %a, <4 x i16> %b, <4 x i16> %c) #0 {
+// CHECK-LABEL: @test_vaba_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %c to <8 x i8>
-// CHECK: [[VABD_V_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VABD_V1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VABD_V2_I_I:%.*]] = call <4 x i16> @llvm.arm.neon.vabdu.v4i16(<4 x i16> [[VABD_V_I_I]], <4 x i16> [[VABD_V1_I_I]]) #4
+// CHECK: [[VABD_V2_I_I:%.*]] = call <4 x i16> @llvm.arm.neon.vabdu.v4i16(<4 x i16> %b, <4 x i16> %c) #4
// CHECK: [[VABD_V3_I_I:%.*]] = bitcast <4 x i16> [[VABD_V2_I_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VABD_V3_I_I]] to <4 x i16>
-// CHECK: [[ADD_I:%.*]] = add <4 x i16> %a, [[TMP2]]
+// CHECK: [[ADD_I:%.*]] = add <4 x i16> %a, [[VABD_V2_I_I]]
// CHECK: ret <4 x i16> [[ADD_I]]
uint16x4_t test_vaba_u16(uint16x4_t a, uint16x4_t b, uint16x4_t c) {
return vaba_u16(a, b, c);
}
-// CHECK-LABEL: define <2 x i32> @test_vaba_u32(<2 x i32> %a, <2 x i32> %b, <2 x i32> %c) #0 {
+// CHECK-LABEL: @test_vaba_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %c to <8 x i8>
-// CHECK: [[VABD_V_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VABD_V1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VABD_V2_I_I:%.*]] = call <2 x i32> @llvm.arm.neon.vabdu.v2i32(<2 x i32> [[VABD_V_I_I]], <2 x i32> [[VABD_V1_I_I]]) #4
+// CHECK: [[VABD_V2_I_I:%.*]] = call <2 x i32> @llvm.arm.neon.vabdu.v2i32(<2 x i32> %b, <2 x i32> %c) #4
// CHECK: [[VABD_V3_I_I:%.*]] = bitcast <2 x i32> [[VABD_V2_I_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VABD_V3_I_I]] to <2 x i32>
-// CHECK: [[ADD_I:%.*]] = add <2 x i32> %a, [[TMP2]]
+// CHECK: [[ADD_I:%.*]] = add <2 x i32> %a, [[VABD_V2_I_I]]
// CHECK: ret <2 x i32> [[ADD_I]]
uint32x2_t test_vaba_u32(uint32x2_t a, uint32x2_t b, uint32x2_t c) {
return vaba_u32(a, b, c);
}
-// CHECK-LABEL: define <16 x i8> @test_vabaq_s8(<16 x i8> %a, <16 x i8> %b, <16 x i8> %c) #0 {
+// CHECK-LABEL: @test_vabaq_s8(
// CHECK: [[VABDQ_V_I_I:%.*]] = call <16 x i8> @llvm.arm.neon.vabds.v16i8(<16 x i8> %b, <16 x i8> %c) #4
// CHECK: [[ADD_I:%.*]] = add <16 x i8> %a, [[VABDQ_V_I_I]]
// CHECK: ret <16 x i8> [[ADD_I]]
@@ -86,35 +74,29 @@ int8x16_t test_vabaq_s8(int8x16_t a, int8x16_t b, int8x16_t c) {
return vabaq_s8(a, b, c);
}
-// CHECK-LABEL: define <8 x i16> @test_vabaq_s16(<8 x i16> %a, <8 x i16> %b, <8 x i16> %c) #0 {
+// CHECK-LABEL: @test_vabaq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %c to <16 x i8>
-// CHECK: [[VABDQ_V_I_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VABDQ_V1_I_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VABDQ_V2_I_I:%.*]] = call <8 x i16> @llvm.arm.neon.vabds.v8i16(<8 x i16> [[VABDQ_V_I_I]], <8 x i16> [[VABDQ_V1_I_I]]) #4
+// CHECK: [[VABDQ_V2_I_I:%.*]] = call <8 x i16> @llvm.arm.neon.vabds.v8i16(<8 x i16> %b, <8 x i16> %c) #4
// CHECK: [[VABDQ_V3_I_I:%.*]] = bitcast <8 x i16> [[VABDQ_V2_I_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VABDQ_V3_I_I]] to <8 x i16>
-// CHECK: [[ADD_I:%.*]] = add <8 x i16> %a, [[TMP2]]
+// CHECK: [[ADD_I:%.*]] = add <8 x i16> %a, [[VABDQ_V2_I_I]]
// CHECK: ret <8 x i16> [[ADD_I]]
int16x8_t test_vabaq_s16(int16x8_t a, int16x8_t b, int16x8_t c) {
return vabaq_s16(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vabaq_s32(<4 x i32> %a, <4 x i32> %b, <4 x i32> %c) #0 {
+// CHECK-LABEL: @test_vabaq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %c to <16 x i8>
-// CHECK: [[VABDQ_V_I_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VABDQ_V1_I_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VABDQ_V2_I_I:%.*]] = call <4 x i32> @llvm.arm.neon.vabds.v4i32(<4 x i32> [[VABDQ_V_I_I]], <4 x i32> [[VABDQ_V1_I_I]]) #4
+// CHECK: [[VABDQ_V2_I_I:%.*]] = call <4 x i32> @llvm.arm.neon.vabds.v4i32(<4 x i32> %b, <4 x i32> %c) #4
// CHECK: [[VABDQ_V3_I_I:%.*]] = bitcast <4 x i32> [[VABDQ_V2_I_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VABDQ_V3_I_I]] to <4 x i32>
-// CHECK: [[ADD_I:%.*]] = add <4 x i32> %a, [[TMP2]]
+// CHECK: [[ADD_I:%.*]] = add <4 x i32> %a, [[VABDQ_V2_I_I]]
// CHECK: ret <4 x i32> [[ADD_I]]
int32x4_t test_vabaq_s32(int32x4_t a, int32x4_t b, int32x4_t c) {
return vabaq_s32(a, b, c);
}
-// CHECK-LABEL: define <16 x i8> @test_vabaq_u8(<16 x i8> %a, <16 x i8> %b, <16 x i8> %c) #0 {
+// CHECK-LABEL: @test_vabaq_u8(
// CHECK: [[VABDQ_V_I_I:%.*]] = call <16 x i8> @llvm.arm.neon.vabdu.v16i8(<16 x i8> %b, <16 x i8> %c) #4
// CHECK: [[ADD_I:%.*]] = add <16 x i8> %a, [[VABDQ_V_I_I]]
// CHECK: ret <16 x i8> [[ADD_I]]
@@ -122,36 +104,29 @@ uint8x16_t test_vabaq_u8(uint8x16_t a, uint8x16_t b, uint8x16_t c) {
return vabaq_u8(a, b, c);
}
-// CHECK-LABEL: define <8 x i16> @test_vabaq_u16(<8 x i16> %a, <8 x i16> %b, <8 x i16> %c) #0 {
+// CHECK-LABEL: @test_vabaq_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %c to <16 x i8>
-// CHECK: [[VABDQ_V_I_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VABDQ_V1_I_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VABDQ_V2_I_I:%.*]] = call <8 x i16> @llvm.arm.neon.vabdu.v8i16(<8 x i16> [[VABDQ_V_I_I]], <8 x i16> [[VABDQ_V1_I_I]]) #4
+// CHECK: [[VABDQ_V2_I_I:%.*]] = call <8 x i16> @llvm.arm.neon.vabdu.v8i16(<8 x i16> %b, <8 x i16> %c) #4
// CHECK: [[VABDQ_V3_I_I:%.*]] = bitcast <8 x i16> [[VABDQ_V2_I_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VABDQ_V3_I_I]] to <8 x i16>
-// CHECK: [[ADD_I:%.*]] = add <8 x i16> %a, [[TMP2]]
+// CHECK: [[ADD_I:%.*]] = add <8 x i16> %a, [[VABDQ_V2_I_I]]
// CHECK: ret <8 x i16> [[ADD_I]]
uint16x8_t test_vabaq_u16(uint16x8_t a, uint16x8_t b, uint16x8_t c) {
return vabaq_u16(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vabaq_u32(<4 x i32> %a, <4 x i32> %b, <4 x i32> %c) #0 {
+// CHECK-LABEL: @test_vabaq_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %c to <16 x i8>
-// CHECK: [[VABDQ_V_I_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VABDQ_V1_I_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VABDQ_V2_I_I:%.*]] = call <4 x i32> @llvm.arm.neon.vabdu.v4i32(<4 x i32> [[VABDQ_V_I_I]], <4 x i32> [[VABDQ_V1_I_I]]) #4
+// CHECK: [[VABDQ_V2_I_I:%.*]] = call <4 x i32> @llvm.arm.neon.vabdu.v4i32(<4 x i32> %b, <4 x i32> %c) #4
// CHECK: [[VABDQ_V3_I_I:%.*]] = bitcast <4 x i32> [[VABDQ_V2_I_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VABDQ_V3_I_I]] to <4 x i32>
-// CHECK: [[ADD_I:%.*]] = add <4 x i32> %a, [[TMP2]]
+// CHECK: [[ADD_I:%.*]] = add <4 x i32> %a, [[VABDQ_V2_I_I]]
// CHECK: ret <4 x i32> [[ADD_I]]
uint32x4_t test_vabaq_u32(uint32x4_t a, uint32x4_t b, uint32x4_t c) {
return vabaq_u32(a, b, c);
}
-
-// CHECK-LABEL: define <8 x i16> @test_vabal_s8(<8 x i16> %a, <8 x i8> %b, <8 x i8> %c) #0 {
+// CHECK-LABEL: @test_vabal_s8(
// CHECK: [[VABD_V_I_I_I:%.*]] = call <8 x i8> @llvm.arm.neon.vabds.v8i8(<8 x i8> %b, <8 x i8> %c) #4
// CHECK: [[VMOVL_I_I_I:%.*]] = zext <8 x i8> [[VABD_V_I_I_I]] to <8 x i16>
// CHECK: [[ADD_I:%.*]] = add <8 x i16> %a, [[VMOVL_I_I_I]]
@@ -160,41 +135,33 @@ int16x8_t test_vabal_s8(int16x8_t a, int8x8_t b, int8x8_t c) {
return vabal_s8(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vabal_s16(<4 x i32> %a, <4 x i16> %b, <4 x i16> %c) #0 {
+// CHECK-LABEL: @test_vabal_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %c to <8 x i8>
-// CHECK: [[VABD_V_I_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VABD_V1_I_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VABD_V2_I_I_I:%.*]] = call <4 x i16> @llvm.arm.neon.vabds.v4i16(<4 x i16> [[VABD_V_I_I_I]], <4 x i16> [[VABD_V1_I_I_I]]) #4
+// CHECK: [[VABD_V2_I_I_I:%.*]] = call <4 x i16> @llvm.arm.neon.vabds.v4i16(<4 x i16> %b, <4 x i16> %c) #4
// CHECK: [[VABD_V3_I_I_I:%.*]] = bitcast <4 x i16> [[VABD_V2_I_I_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VABD_V3_I_I_I]] to <4 x i16>
-// CHECK: [[TMP3:%.*]] = bitcast <4 x i16> [[TMP2]] to <8 x i8>
-// CHECK: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP3]] to <4 x i16>
-// CHECK: [[VMOVL_I_I_I:%.*]] = zext <4 x i16> [[TMP4]] to <4 x i32>
+// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> [[VABD_V2_I_I_I]] to <8 x i8>
+// CHECK: [[VMOVL_I_I_I:%.*]] = zext <4 x i16> [[VABD_V2_I_I_I]] to <4 x i32>
// CHECK: [[ADD_I:%.*]] = add <4 x i32> %a, [[VMOVL_I_I_I]]
// CHECK: ret <4 x i32> [[ADD_I]]
int32x4_t test_vabal_s16(int32x4_t a, int16x4_t b, int16x4_t c) {
return vabal_s16(a, b, c);
}
-// CHECK-LABEL: define <2 x i64> @test_vabal_s32(<2 x i64> %a, <2 x i32> %b, <2 x i32> %c) #0 {
+// CHECK-LABEL: @test_vabal_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %c to <8 x i8>
-// CHECK: [[VABD_V_I_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VABD_V1_I_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VABD_V2_I_I_I:%.*]] = call <2 x i32> @llvm.arm.neon.vabds.v2i32(<2 x i32> [[VABD_V_I_I_I]], <2 x i32> [[VABD_V1_I_I_I]]) #4
+// CHECK: [[VABD_V2_I_I_I:%.*]] = call <2 x i32> @llvm.arm.neon.vabds.v2i32(<2 x i32> %b, <2 x i32> %c) #4
// CHECK: [[VABD_V3_I_I_I:%.*]] = bitcast <2 x i32> [[VABD_V2_I_I_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VABD_V3_I_I_I]] to <2 x i32>
-// CHECK: [[TMP3:%.*]] = bitcast <2 x i32> [[TMP2]] to <8 x i8>
-// CHECK: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP3]] to <2 x i32>
-// CHECK: [[VMOVL_I_I_I:%.*]] = zext <2 x i32> [[TMP4]] to <2 x i64>
+// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> [[VABD_V2_I_I_I]] to <8 x i8>
+// CHECK: [[VMOVL_I_I_I:%.*]] = zext <2 x i32> [[VABD_V2_I_I_I]] to <2 x i64>
// CHECK: [[ADD_I:%.*]] = add <2 x i64> %a, [[VMOVL_I_I_I]]
// CHECK: ret <2 x i64> [[ADD_I]]
int64x2_t test_vabal_s32(int64x2_t a, int32x2_t b, int32x2_t c) {
return vabal_s32(a, b, c);
}
-// CHECK-LABEL: define <8 x i16> @test_vabal_u8(<8 x i16> %a, <8 x i8> %b, <8 x i8> %c) #0 {
+// CHECK-LABEL: @test_vabal_u8(
// CHECK: [[VABD_V_I_I_I:%.*]] = call <8 x i8> @llvm.arm.neon.vabdu.v8i8(<8 x i8> %b, <8 x i8> %c) #4
// CHECK: [[VMOVL_I_I_I:%.*]] = zext <8 x i8> [[VABD_V_I_I_I]] to <8 x i16>
// CHECK: [[ADD_I:%.*]] = add <8 x i16> %a, [[VMOVL_I_I_I]]
@@ -203,201 +170,161 @@ uint16x8_t test_vabal_u8(uint16x8_t a, uint8x8_t b, uint8x8_t c) {
return vabal_u8(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vabal_u16(<4 x i32> %a, <4 x i16> %b, <4 x i16> %c) #0 {
+// CHECK-LABEL: @test_vabal_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %c to <8 x i8>
-// CHECK: [[VABD_V_I_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VABD_V1_I_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VABD_V2_I_I_I:%.*]] = call <4 x i16> @llvm.arm.neon.vabdu.v4i16(<4 x i16> [[VABD_V_I_I_I]], <4 x i16> [[VABD_V1_I_I_I]]) #4
+// CHECK: [[VABD_V2_I_I_I:%.*]] = call <4 x i16> @llvm.arm.neon.vabdu.v4i16(<4 x i16> %b, <4 x i16> %c) #4
// CHECK: [[VABD_V3_I_I_I:%.*]] = bitcast <4 x i16> [[VABD_V2_I_I_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VABD_V3_I_I_I]] to <4 x i16>
-// CHECK: [[TMP3:%.*]] = bitcast <4 x i16> [[TMP2]] to <8 x i8>
-// CHECK: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP3]] to <4 x i16>
-// CHECK: [[VMOVL_I_I_I:%.*]] = zext <4 x i16> [[TMP4]] to <4 x i32>
+// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> [[VABD_V2_I_I_I]] to <8 x i8>
+// CHECK: [[VMOVL_I_I_I:%.*]] = zext <4 x i16> [[VABD_V2_I_I_I]] to <4 x i32>
// CHECK: [[ADD_I:%.*]] = add <4 x i32> %a, [[VMOVL_I_I_I]]
// CHECK: ret <4 x i32> [[ADD_I]]
uint32x4_t test_vabal_u16(uint32x4_t a, uint16x4_t b, uint16x4_t c) {
return vabal_u16(a, b, c);
}
-// CHECK-LABEL: define <2 x i64> @test_vabal_u32(<2 x i64> %a, <2 x i32> %b, <2 x i32> %c) #0 {
+// CHECK-LABEL: @test_vabal_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %c to <8 x i8>
-// CHECK: [[VABD_V_I_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VABD_V1_I_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VABD_V2_I_I_I:%.*]] = call <2 x i32> @llvm.arm.neon.vabdu.v2i32(<2 x i32> [[VABD_V_I_I_I]], <2 x i32> [[VABD_V1_I_I_I]]) #4
+// CHECK: [[VABD_V2_I_I_I:%.*]] = call <2 x i32> @llvm.arm.neon.vabdu.v2i32(<2 x i32> %b, <2 x i32> %c) #4
// CHECK: [[VABD_V3_I_I_I:%.*]] = bitcast <2 x i32> [[VABD_V2_I_I_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VABD_V3_I_I_I]] to <2 x i32>
-// CHECK: [[TMP3:%.*]] = bitcast <2 x i32> [[TMP2]] to <8 x i8>
-// CHECK: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP3]] to <2 x i32>
-// CHECK: [[VMOVL_I_I_I:%.*]] = zext <2 x i32> [[TMP4]] to <2 x i64>
+// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> [[VABD_V2_I_I_I]] to <8 x i8>
+// CHECK: [[VMOVL_I_I_I:%.*]] = zext <2 x i32> [[VABD_V2_I_I_I]] to <2 x i64>
// CHECK: [[ADD_I:%.*]] = add <2 x i64> %a, [[VMOVL_I_I_I]]
// CHECK: ret <2 x i64> [[ADD_I]]
uint64x2_t test_vabal_u32(uint64x2_t a, uint32x2_t b, uint32x2_t c) {
return vabal_u32(a, b, c);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vabd_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vabd_s8(
// CHECK: [[VABD_V_I:%.*]] = call <8 x i8> @llvm.arm.neon.vabds.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VABD_V_I]]
int8x8_t test_vabd_s8(int8x8_t a, int8x8_t b) {
return vabd_s8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vabd_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vabd_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VABD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VABD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VABD_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vabds.v4i16(<4 x i16> [[VABD_V_I]], <4 x i16> [[VABD_V1_I]]) #4
+// CHECK: [[VABD_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vabds.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VABD_V3_I:%.*]] = bitcast <4 x i16> [[VABD_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VABD_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VABD_V2_I]]
int16x4_t test_vabd_s16(int16x4_t a, int16x4_t b) {
return vabd_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vabd_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vabd_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VABD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VABD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VABD_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vabds.v2i32(<2 x i32> [[VABD_V_I]], <2 x i32> [[VABD_V1_I]]) #4
+// CHECK: [[VABD_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vabds.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VABD_V3_I:%.*]] = bitcast <2 x i32> [[VABD_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VABD_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VABD_V2_I]]
int32x2_t test_vabd_s32(int32x2_t a, int32x2_t b) {
return vabd_s32(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vabd_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vabd_u8(
// CHECK: [[VABD_V_I:%.*]] = call <8 x i8> @llvm.arm.neon.vabdu.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VABD_V_I]]
uint8x8_t test_vabd_u8(uint8x8_t a, uint8x8_t b) {
return vabd_u8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vabd_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vabd_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VABD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VABD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VABD_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vabdu.v4i16(<4 x i16> [[VABD_V_I]], <4 x i16> [[VABD_V1_I]]) #4
+// CHECK: [[VABD_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vabdu.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VABD_V3_I:%.*]] = bitcast <4 x i16> [[VABD_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VABD_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VABD_V2_I]]
uint16x4_t test_vabd_u16(uint16x4_t a, uint16x4_t b) {
return vabd_u16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vabd_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vabd_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VABD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VABD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VABD_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vabdu.v2i32(<2 x i32> [[VABD_V_I]], <2 x i32> [[VABD_V1_I]]) #4
+// CHECK: [[VABD_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vabdu.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VABD_V3_I:%.*]] = bitcast <2 x i32> [[VABD_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VABD_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VABD_V2_I]]
uint32x2_t test_vabd_u32(uint32x2_t a, uint32x2_t b) {
return vabd_u32(a, b);
}
-// CHECK-LABEL: define <2 x float> @test_vabd_f32(<2 x float> %a, <2 x float> %b) #0 {
+// CHECK-LABEL: @test_vabd_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %b to <8 x i8>
-// CHECK: [[VABD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VABD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK: [[VABD_V2_I:%.*]] = call <2 x float> @llvm.arm.neon.vabds.v2f32(<2 x float> [[VABD_V_I]], <2 x float> [[VABD_V1_I]]) #4
+// CHECK: [[VABD_V2_I:%.*]] = call <2 x float> @llvm.arm.neon.vabds.v2f32(<2 x float> %a, <2 x float> %b) #4
// CHECK: [[VABD_V3_I:%.*]] = bitcast <2 x float> [[VABD_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VABD_V3_I]] to <2 x float>
-// CHECK: ret <2 x float> [[TMP2]]
+// CHECK: ret <2 x float> [[VABD_V2_I]]
float32x2_t test_vabd_f32(float32x2_t a, float32x2_t b) {
return vabd_f32(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vabdq_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vabdq_s8(
// CHECK: [[VABDQ_V_I:%.*]] = call <16 x i8> @llvm.arm.neon.vabds.v16i8(<16 x i8> %a, <16 x i8> %b) #4
// CHECK: ret <16 x i8> [[VABDQ_V_I]]
int8x16_t test_vabdq_s8(int8x16_t a, int8x16_t b) {
return vabdq_s8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vabdq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vabdq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VABDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VABDQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VABDQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vabds.v8i16(<8 x i16> [[VABDQ_V_I]], <8 x i16> [[VABDQ_V1_I]]) #4
+// CHECK: [[VABDQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vabds.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: [[VABDQ_V3_I:%.*]] = bitcast <8 x i16> [[VABDQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VABDQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VABDQ_V2_I]]
int16x8_t test_vabdq_s16(int16x8_t a, int16x8_t b) {
return vabdq_s16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vabdq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vabdq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VABDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VABDQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VABDQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vabds.v4i32(<4 x i32> [[VABDQ_V_I]], <4 x i32> [[VABDQ_V1_I]]) #4
+// CHECK: [[VABDQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vabds.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VABDQ_V3_I:%.*]] = bitcast <4 x i32> [[VABDQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VABDQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VABDQ_V2_I]]
int32x4_t test_vabdq_s32(int32x4_t a, int32x4_t b) {
return vabdq_s32(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vabdq_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vabdq_u8(
// CHECK: [[VABDQ_V_I:%.*]] = call <16 x i8> @llvm.arm.neon.vabdu.v16i8(<16 x i8> %a, <16 x i8> %b) #4
// CHECK: ret <16 x i8> [[VABDQ_V_I]]
uint8x16_t test_vabdq_u8(uint8x16_t a, uint8x16_t b) {
return vabdq_u8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vabdq_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vabdq_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VABDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VABDQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VABDQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vabdu.v8i16(<8 x i16> [[VABDQ_V_I]], <8 x i16> [[VABDQ_V1_I]]) #4
+// CHECK: [[VABDQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vabdu.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: [[VABDQ_V3_I:%.*]] = bitcast <8 x i16> [[VABDQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VABDQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VABDQ_V2_I]]
uint16x8_t test_vabdq_u16(uint16x8_t a, uint16x8_t b) {
return vabdq_u16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vabdq_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vabdq_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VABDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VABDQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VABDQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vabdu.v4i32(<4 x i32> [[VABDQ_V_I]], <4 x i32> [[VABDQ_V1_I]]) #4
+// CHECK: [[VABDQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vabdu.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VABDQ_V3_I:%.*]] = bitcast <4 x i32> [[VABDQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VABDQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VABDQ_V2_I]]
uint32x4_t test_vabdq_u32(uint32x4_t a, uint32x4_t b) {
return vabdq_u32(a, b);
}
-// CHECK-LABEL: define <4 x float> @test_vabdq_f32(<4 x float> %a, <4 x float> %b) #0 {
+// CHECK-LABEL: @test_vabdq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %b to <16 x i8>
-// CHECK: [[VABDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VABDQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
-// CHECK: [[VABDQ_V2_I:%.*]] = call <4 x float> @llvm.arm.neon.vabds.v4f32(<4 x float> [[VABDQ_V_I]], <4 x float> [[VABDQ_V1_I]]) #4
+// CHECK: [[VABDQ_V2_I:%.*]] = call <4 x float> @llvm.arm.neon.vabds.v4f32(<4 x float> %a, <4 x float> %b) #4
// CHECK: [[VABDQ_V3_I:%.*]] = bitcast <4 x float> [[VABDQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VABDQ_V3_I]] to <4 x float>
-// CHECK: ret <4 x float> [[TMP2]]
+// CHECK: ret <4 x float> [[VABDQ_V2_I]]
float32x4_t test_vabdq_f32(float32x4_t a, float32x4_t b) {
return vabdq_f32(a, b);
}
-
-// CHECK-LABEL: define <8 x i16> @test_vabdl_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vabdl_s8(
// CHECK: [[VABD_V_I_I:%.*]] = call <8 x i8> @llvm.arm.neon.vabds.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: [[VMOVL_I_I:%.*]] = zext <8 x i8> [[VABD_V_I_I]] to <8 x i16>
// CHECK: ret <8 x i16> [[VMOVL_I_I]]
@@ -405,39 +332,31 @@ int16x8_t test_vabdl_s8(int8x8_t a, int8x8_t b) {
return vabdl_s8(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vabdl_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vabdl_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VABD_V_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VABD_V1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VABD_V2_I_I:%.*]] = call <4 x i16> @llvm.arm.neon.vabds.v4i16(<4 x i16> [[VABD_V_I_I]], <4 x i16> [[VABD_V1_I_I]]) #4
+// CHECK: [[VABD_V2_I_I:%.*]] = call <4 x i16> @llvm.arm.neon.vabds.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VABD_V3_I_I:%.*]] = bitcast <4 x i16> [[VABD_V2_I_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VABD_V3_I_I]] to <4 x i16>
-// CHECK: [[TMP3:%.*]] = bitcast <4 x i16> [[TMP2]] to <8 x i8>
-// CHECK: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP3]] to <4 x i16>
-// CHECK: [[VMOVL_I_I:%.*]] = zext <4 x i16> [[TMP4]] to <4 x i32>
+// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> [[VABD_V2_I_I]] to <8 x i8>
+// CHECK: [[VMOVL_I_I:%.*]] = zext <4 x i16> [[VABD_V2_I_I]] to <4 x i32>
// CHECK: ret <4 x i32> [[VMOVL_I_I]]
int32x4_t test_vabdl_s16(int16x4_t a, int16x4_t b) {
return vabdl_s16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vabdl_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vabdl_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VABD_V_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VABD_V1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VABD_V2_I_I:%.*]] = call <2 x i32> @llvm.arm.neon.vabds.v2i32(<2 x i32> [[VABD_V_I_I]], <2 x i32> [[VABD_V1_I_I]]) #4
+// CHECK: [[VABD_V2_I_I:%.*]] = call <2 x i32> @llvm.arm.neon.vabds.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VABD_V3_I_I:%.*]] = bitcast <2 x i32> [[VABD_V2_I_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VABD_V3_I_I]] to <2 x i32>
-// CHECK: [[TMP3:%.*]] = bitcast <2 x i32> [[TMP2]] to <8 x i8>
-// CHECK: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP3]] to <2 x i32>
-// CHECK: [[VMOVL_I_I:%.*]] = zext <2 x i32> [[TMP4]] to <2 x i64>
+// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> [[VABD_V2_I_I]] to <8 x i8>
+// CHECK: [[VMOVL_I_I:%.*]] = zext <2 x i32> [[VABD_V2_I_I]] to <2 x i64>
// CHECK: ret <2 x i64> [[VMOVL_I_I]]
int64x2_t test_vabdl_s32(int32x2_t a, int32x2_t b) {
return vabdl_s32(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vabdl_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vabdl_u8(
// CHECK: [[VABD_V_I_I:%.*]] = call <8 x i8> @llvm.arm.neon.vabdu.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: [[VMOVL_I_I:%.*]] = zext <8 x i8> [[VABD_V_I_I]] to <8 x i16>
// CHECK: ret <8 x i16> [[VMOVL_I_I]]
@@ -445,241 +364,222 @@ uint16x8_t test_vabdl_u8(uint8x8_t a, uint8x8_t b) {
return vabdl_u8(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vabdl_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vabdl_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VABD_V_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VABD_V1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VABD_V2_I_I:%.*]] = call <4 x i16> @llvm.arm.neon.vabdu.v4i16(<4 x i16> [[VABD_V_I_I]], <4 x i16> [[VABD_V1_I_I]]) #4
+// CHECK: [[VABD_V2_I_I:%.*]] = call <4 x i16> @llvm.arm.neon.vabdu.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VABD_V3_I_I:%.*]] = bitcast <4 x i16> [[VABD_V2_I_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VABD_V3_I_I]] to <4 x i16>
-// CHECK: [[TMP3:%.*]] = bitcast <4 x i16> [[TMP2]] to <8 x i8>
-// CHECK: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP3]] to <4 x i16>
-// CHECK: [[VMOVL_I_I:%.*]] = zext <4 x i16> [[TMP4]] to <4 x i32>
+// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> [[VABD_V2_I_I]] to <8 x i8>
+// CHECK: [[VMOVL_I_I:%.*]] = zext <4 x i16> [[VABD_V2_I_I]] to <4 x i32>
// CHECK: ret <4 x i32> [[VMOVL_I_I]]
uint32x4_t test_vabdl_u16(uint16x4_t a, uint16x4_t b) {
return vabdl_u16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vabdl_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vabdl_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VABD_V_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VABD_V1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VABD_V2_I_I:%.*]] = call <2 x i32> @llvm.arm.neon.vabdu.v2i32(<2 x i32> [[VABD_V_I_I]], <2 x i32> [[VABD_V1_I_I]]) #4
+// CHECK: [[VABD_V2_I_I:%.*]] = call <2 x i32> @llvm.arm.neon.vabdu.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VABD_V3_I_I:%.*]] = bitcast <2 x i32> [[VABD_V2_I_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VABD_V3_I_I]] to <2 x i32>
-// CHECK: [[TMP3:%.*]] = bitcast <2 x i32> [[TMP2]] to <8 x i8>
-// CHECK: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP3]] to <2 x i32>
-// CHECK: [[VMOVL_I_I:%.*]] = zext <2 x i32> [[TMP4]] to <2 x i64>
+// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> [[VABD_V2_I_I]] to <8 x i8>
+// CHECK: [[VMOVL_I_I:%.*]] = zext <2 x i32> [[VABD_V2_I_I]] to <2 x i64>
// CHECK: ret <2 x i64> [[VMOVL_I_I]]
uint64x2_t test_vabdl_u32(uint32x2_t a, uint32x2_t b) {
return vabdl_u32(a, b);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vabs_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vabs_s8(
// CHECK: [[VABS_I:%.*]] = call <8 x i8> @llvm.arm.neon.vabs.v8i8(<8 x i8> %a) #4
// CHECK: ret <8 x i8> [[VABS_I]]
int8x8_t test_vabs_s8(int8x8_t a) {
return vabs_s8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vabs_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vabs_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
-// CHECK: [[VABS_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VABS1_I:%.*]] = call <4 x i16> @llvm.arm.neon.vabs.v4i16(<4 x i16> [[VABS_I]]) #4
+// CHECK: [[VABS1_I:%.*]] = call <4 x i16> @llvm.arm.neon.vabs.v4i16(<4 x i16> %a) #4
// CHECK: ret <4 x i16> [[VABS1_I]]
int16x4_t test_vabs_s16(int16x4_t a) {
return vabs_s16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vabs_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vabs_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[VABS_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VABS1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vabs.v2i32(<2 x i32> [[VABS_I]]) #4
+// CHECK: [[VABS1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vabs.v2i32(<2 x i32> %a) #4
// CHECK: ret <2 x i32> [[VABS1_I]]
int32x2_t test_vabs_s32(int32x2_t a) {
return vabs_s32(a);
}
-// CHECK-LABEL: define <2 x float> @test_vabs_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vabs_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[VABS_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VABS1_I:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[VABS_I]]) #4
+// CHECK: [[VABS1_I:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> %a) #4
// CHECK: ret <2 x float> [[VABS1_I]]
float32x2_t test_vabs_f32(float32x2_t a) {
return vabs_f32(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vabsq_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vabsq_s8(
// CHECK: [[VABS_I:%.*]] = call <16 x i8> @llvm.arm.neon.vabs.v16i8(<16 x i8> %a) #4
// CHECK: ret <16 x i8> [[VABS_I]]
int8x16_t test_vabsq_s8(int8x16_t a) {
return vabsq_s8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vabsq_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vabsq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
-// CHECK: [[VABS_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VABS1_I:%.*]] = call <8 x i16> @llvm.arm.neon.vabs.v8i16(<8 x i16> [[VABS_I]]) #4
+// CHECK: [[VABS1_I:%.*]] = call <8 x i16> @llvm.arm.neon.vabs.v8i16(<8 x i16> %a) #4
// CHECK: ret <8 x i16> [[VABS1_I]]
int16x8_t test_vabsq_s16(int16x8_t a) {
return vabsq_s16(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vabsq_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vabsq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
-// CHECK: [[VABS_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VABS1_I:%.*]] = call <4 x i32> @llvm.arm.neon.vabs.v4i32(<4 x i32> [[VABS_I]]) #4
+// CHECK: [[VABS1_I:%.*]] = call <4 x i32> @llvm.arm.neon.vabs.v4i32(<4 x i32> %a) #4
// CHECK: ret <4 x i32> [[VABS1_I]]
int32x4_t test_vabsq_s32(int32x4_t a) {
return vabsq_s32(a);
}
-// CHECK-LABEL: define <4 x float> @test_vabsq_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vabsq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[VABS_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VABS1_I:%.*]] = call <4 x float> @llvm.fabs.v4f32(<4 x float> [[VABS_I]]) #4
+// CHECK: [[VABS1_I:%.*]] = call <4 x float> @llvm.fabs.v4f32(<4 x float> %a) #4
// CHECK: ret <4 x float> [[VABS1_I]]
float32x4_t test_vabsq_f32(float32x4_t a) {
return vabsq_f32(a);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vadd_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vadd_s8(
// CHECK: [[ADD_I:%.*]] = add <8 x i8> %a, %b
// CHECK: ret <8 x i8> [[ADD_I]]
int8x8_t test_vadd_s8(int8x8_t a, int8x8_t b) {
return vadd_s8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vadd_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vadd_s16(
// CHECK: [[ADD_I:%.*]] = add <4 x i16> %a, %b
// CHECK: ret <4 x i16> [[ADD_I]]
int16x4_t test_vadd_s16(int16x4_t a, int16x4_t b) {
return vadd_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vadd_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vadd_s32(
// CHECK: [[ADD_I:%.*]] = add <2 x i32> %a, %b
// CHECK: ret <2 x i32> [[ADD_I]]
int32x2_t test_vadd_s32(int32x2_t a, int32x2_t b) {
return vadd_s32(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vadd_s64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vadd_s64(
// CHECK: [[ADD_I:%.*]] = add <1 x i64> %a, %b
// CHECK: ret <1 x i64> [[ADD_I]]
int64x1_t test_vadd_s64(int64x1_t a, int64x1_t b) {
return vadd_s64(a, b);
}
-// CHECK-LABEL: define <2 x float> @test_vadd_f32(<2 x float> %a, <2 x float> %b) #0 {
+// CHECK-LABEL: @test_vadd_f32(
// CHECK: [[ADD_I:%.*]] = fadd <2 x float> %a, %b
// CHECK: ret <2 x float> [[ADD_I]]
float32x2_t test_vadd_f32(float32x2_t a, float32x2_t b) {
return vadd_f32(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vadd_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vadd_u8(
// CHECK: [[ADD_I:%.*]] = add <8 x i8> %a, %b
// CHECK: ret <8 x i8> [[ADD_I]]
uint8x8_t test_vadd_u8(uint8x8_t a, uint8x8_t b) {
return vadd_u8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vadd_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vadd_u16(
// CHECK: [[ADD_I:%.*]] = add <4 x i16> %a, %b
// CHECK: ret <4 x i16> [[ADD_I]]
uint16x4_t test_vadd_u16(uint16x4_t a, uint16x4_t b) {
return vadd_u16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vadd_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vadd_u32(
// CHECK: [[ADD_I:%.*]] = add <2 x i32> %a, %b
// CHECK: ret <2 x i32> [[ADD_I]]
uint32x2_t test_vadd_u32(uint32x2_t a, uint32x2_t b) {
return vadd_u32(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vadd_u64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vadd_u64(
// CHECK: [[ADD_I:%.*]] = add <1 x i64> %a, %b
// CHECK: ret <1 x i64> [[ADD_I]]
uint64x1_t test_vadd_u64(uint64x1_t a, uint64x1_t b) {
return vadd_u64(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vaddq_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vaddq_s8(
// CHECK: [[ADD_I:%.*]] = add <16 x i8> %a, %b
// CHECK: ret <16 x i8> [[ADD_I]]
int8x16_t test_vaddq_s8(int8x16_t a, int8x16_t b) {
return vaddq_s8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vaddq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vaddq_s16(
// CHECK: [[ADD_I:%.*]] = add <8 x i16> %a, %b
// CHECK: ret <8 x i16> [[ADD_I]]
int16x8_t test_vaddq_s16(int16x8_t a, int16x8_t b) {
return vaddq_s16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vaddq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vaddq_s32(
// CHECK: [[ADD_I:%.*]] = add <4 x i32> %a, %b
// CHECK: ret <4 x i32> [[ADD_I]]
int32x4_t test_vaddq_s32(int32x4_t a, int32x4_t b) {
return vaddq_s32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vaddq_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vaddq_s64(
// CHECK: [[ADD_I:%.*]] = add <2 x i64> %a, %b
// CHECK: ret <2 x i64> [[ADD_I]]
int64x2_t test_vaddq_s64(int64x2_t a, int64x2_t b) {
return vaddq_s64(a, b);
}
-// CHECK-LABEL: define <4 x float> @test_vaddq_f32(<4 x float> %a, <4 x float> %b) #0 {
+// CHECK-LABEL: @test_vaddq_f32(
// CHECK: [[ADD_I:%.*]] = fadd <4 x float> %a, %b
// CHECK: ret <4 x float> [[ADD_I]]
float32x4_t test_vaddq_f32(float32x4_t a, float32x4_t b) {
return vaddq_f32(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vaddq_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vaddq_u8(
// CHECK: [[ADD_I:%.*]] = add <16 x i8> %a, %b
// CHECK: ret <16 x i8> [[ADD_I]]
uint8x16_t test_vaddq_u8(uint8x16_t a, uint8x16_t b) {
return vaddq_u8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vaddq_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vaddq_u16(
// CHECK: [[ADD_I:%.*]] = add <8 x i16> %a, %b
// CHECK: ret <8 x i16> [[ADD_I]]
uint16x8_t test_vaddq_u16(uint16x8_t a, uint16x8_t b) {
return vaddq_u16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vaddq_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vaddq_u32(
// CHECK: [[ADD_I:%.*]] = add <4 x i32> %a, %b
// CHECK: ret <4 x i32> [[ADD_I]]
uint32x4_t test_vaddq_u32(uint32x4_t a, uint32x4_t b) {
return vaddq_u32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vaddq_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vaddq_u64(
// CHECK: [[ADD_I:%.*]] = add <2 x i64> %a, %b
// CHECK: ret <2 x i64> [[ADD_I]]
uint64x2_t test_vaddq_u64(uint64x2_t a, uint64x2_t b) {
return vaddq_u64(a, b);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vaddhn_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vaddhn_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VADDHN_I:%.*]] = add <8 x i16> [[TMP2]], [[TMP3]]
+// CHECK: [[VADDHN_I:%.*]] = add <8 x i16> %a, %b
// CHECK: [[VADDHN1_I:%.*]] = lshr <8 x i16> [[VADDHN_I]], <i16 8, i16 8, i16 8, i16 8, i16 8, i16 8, i16 8, i16 8>
// CHECK: [[VADDHN2_I:%.*]] = trunc <8 x i16> [[VADDHN1_I]] to <8 x i8>
// CHECK: ret <8 x i8> [[VADDHN2_I]]
@@ -687,12 +587,10 @@ int8x8_t test_vaddhn_s16(int16x8_t a, int16x8_t b) {
return vaddhn_s16(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vaddhn_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vaddhn_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VADDHN_I:%.*]] = add <4 x i32> [[TMP2]], [[TMP3]]
+// CHECK: [[VADDHN_I:%.*]] = add <4 x i32> %a, %b
// CHECK: [[VADDHN1_I:%.*]] = lshr <4 x i32> [[VADDHN_I]], <i32 16, i32 16, i32 16, i32 16>
// CHECK: [[VADDHN2_I:%.*]] = trunc <4 x i32> [[VADDHN1_I]] to <4 x i16>
// CHECK: ret <4 x i16> [[VADDHN2_I]]
@@ -700,12 +598,10 @@ int16x4_t test_vaddhn_s32(int32x4_t a, int32x4_t b) {
return vaddhn_s32(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vaddhn_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vaddhn_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VADDHN_I:%.*]] = add <2 x i64> [[TMP2]], [[TMP3]]
+// CHECK: [[VADDHN_I:%.*]] = add <2 x i64> %a, %b
// CHECK: [[VADDHN1_I:%.*]] = lshr <2 x i64> [[VADDHN_I]], <i64 32, i64 32>
// CHECK: [[VADDHN2_I:%.*]] = trunc <2 x i64> [[VADDHN1_I]] to <2 x i32>
// CHECK: ret <2 x i32> [[VADDHN2_I]]
@@ -713,12 +609,10 @@ int32x2_t test_vaddhn_s64(int64x2_t a, int64x2_t b) {
return vaddhn_s64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vaddhn_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vaddhn_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VADDHN_I:%.*]] = add <8 x i16> [[TMP2]], [[TMP3]]
+// CHECK: [[VADDHN_I:%.*]] = add <8 x i16> %a, %b
// CHECK: [[VADDHN1_I:%.*]] = lshr <8 x i16> [[VADDHN_I]], <i16 8, i16 8, i16 8, i16 8, i16 8, i16 8, i16 8, i16 8>
// CHECK: [[VADDHN2_I:%.*]] = trunc <8 x i16> [[VADDHN1_I]] to <8 x i8>
// CHECK: ret <8 x i8> [[VADDHN2_I]]
@@ -726,12 +620,10 @@ uint8x8_t test_vaddhn_u16(uint16x8_t a, uint16x8_t b) {
return vaddhn_u16(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vaddhn_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vaddhn_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VADDHN_I:%.*]] = add <4 x i32> [[TMP2]], [[TMP3]]
+// CHECK: [[VADDHN_I:%.*]] = add <4 x i32> %a, %b
// CHECK: [[VADDHN1_I:%.*]] = lshr <4 x i32> [[VADDHN_I]], <i32 16, i32 16, i32 16, i32 16>
// CHECK: [[VADDHN2_I:%.*]] = trunc <4 x i32> [[VADDHN1_I]] to <4 x i16>
// CHECK: ret <4 x i16> [[VADDHN2_I]]
@@ -739,12 +631,10 @@ uint16x4_t test_vaddhn_u32(uint32x4_t a, uint32x4_t b) {
return vaddhn_u32(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vaddhn_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vaddhn_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VADDHN_I:%.*]] = add <2 x i64> [[TMP2]], [[TMP3]]
+// CHECK: [[VADDHN_I:%.*]] = add <2 x i64> %a, %b
// CHECK: [[VADDHN1_I:%.*]] = lshr <2 x i64> [[VADDHN_I]], <i64 32, i64 32>
// CHECK: [[VADDHN2_I:%.*]] = trunc <2 x i64> [[VADDHN1_I]] to <2 x i32>
// CHECK: ret <2 x i32> [[VADDHN2_I]]
@@ -752,8 +642,7 @@ uint32x2_t test_vaddhn_u64(uint64x2_t a, uint64x2_t b) {
return vaddhn_u64(a, b);
}
-
-// CHECK-LABEL: define <8 x i16> @test_vaddl_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vaddl_s8(
// CHECK: [[VMOVL_I_I:%.*]] = sext <8 x i8> %a to <8 x i16>
// CHECK: [[VMOVL_I4_I:%.*]] = sext <8 x i8> %b to <8 x i16>
// CHECK: [[ADD_I:%.*]] = add <8 x i16> [[VMOVL_I_I]], [[VMOVL_I4_I]]
@@ -762,33 +651,29 @@ int16x8_t test_vaddl_s8(int8x8_t a, int8x8_t b) {
return vaddl_s8(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vaddl_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vaddl_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMOVL_I_I:%.*]] = sext <4 x i16> [[TMP1]] to <4 x i32>
-// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VMOVL_I4_I:%.*]] = sext <4 x i16> [[TMP3]] to <4 x i32>
+// CHECK: [[VMOVL_I_I:%.*]] = sext <4 x i16> %a to <4 x i32>
+// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
+// CHECK: [[VMOVL_I4_I:%.*]] = sext <4 x i16> %b to <4 x i32>
// CHECK: [[ADD_I:%.*]] = add <4 x i32> [[VMOVL_I_I]], [[VMOVL_I4_I]]
// CHECK: ret <4 x i32> [[ADD_I]]
int32x4_t test_vaddl_s16(int16x4_t a, int16x4_t b) {
return vaddl_s16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vaddl_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vaddl_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMOVL_I_I:%.*]] = sext <2 x i32> [[TMP1]] to <2 x i64>
-// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VMOVL_I4_I:%.*]] = sext <2 x i32> [[TMP3]] to <2 x i64>
+// CHECK: [[VMOVL_I_I:%.*]] = sext <2 x i32> %a to <2 x i64>
+// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
+// CHECK: [[VMOVL_I4_I:%.*]] = sext <2 x i32> %b to <2 x i64>
// CHECK: [[ADD_I:%.*]] = add <2 x i64> [[VMOVL_I_I]], [[VMOVL_I4_I]]
// CHECK: ret <2 x i64> [[ADD_I]]
int64x2_t test_vaddl_s32(int32x2_t a, int32x2_t b) {
return vaddl_s32(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vaddl_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vaddl_u8(
// CHECK: [[VMOVL_I_I:%.*]] = zext <8 x i8> %a to <8 x i16>
// CHECK: [[VMOVL_I4_I:%.*]] = zext <8 x i8> %b to <8 x i16>
// CHECK: [[ADD_I:%.*]] = add <8 x i16> [[VMOVL_I_I]], [[VMOVL_I4_I]]
@@ -797,34 +682,29 @@ uint16x8_t test_vaddl_u8(uint8x8_t a, uint8x8_t b) {
return vaddl_u8(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vaddl_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vaddl_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMOVL_I_I:%.*]] = zext <4 x i16> [[TMP1]] to <4 x i32>
-// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VMOVL_I4_I:%.*]] = zext <4 x i16> [[TMP3]] to <4 x i32>
+// CHECK: [[VMOVL_I_I:%.*]] = zext <4 x i16> %a to <4 x i32>
+// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
+// CHECK: [[VMOVL_I4_I:%.*]] = zext <4 x i16> %b to <4 x i32>
// CHECK: [[ADD_I:%.*]] = add <4 x i32> [[VMOVL_I_I]], [[VMOVL_I4_I]]
// CHECK: ret <4 x i32> [[ADD_I]]
uint32x4_t test_vaddl_u16(uint16x4_t a, uint16x4_t b) {
return vaddl_u16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vaddl_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vaddl_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMOVL_I_I:%.*]] = zext <2 x i32> [[TMP1]] to <2 x i64>
-// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VMOVL_I4_I:%.*]] = zext <2 x i32> [[TMP3]] to <2 x i64>
+// CHECK: [[VMOVL_I_I:%.*]] = zext <2 x i32> %a to <2 x i64>
+// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
+// CHECK: [[VMOVL_I4_I:%.*]] = zext <2 x i32> %b to <2 x i64>
// CHECK: [[ADD_I:%.*]] = add <2 x i64> [[VMOVL_I_I]], [[VMOVL_I4_I]]
// CHECK: ret <2 x i64> [[ADD_I]]
uint64x2_t test_vaddl_u32(uint32x2_t a, uint32x2_t b) {
return vaddl_u32(a, b);
}
-
-// CHECK-LABEL: define <8 x i16> @test_vaddw_s8(<8 x i16> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vaddw_s8(
// CHECK: [[VMOVL_I_I:%.*]] = sext <8 x i8> %b to <8 x i16>
// CHECK: [[ADD_I:%.*]] = add <8 x i16> %a, [[VMOVL_I_I]]
// CHECK: ret <8 x i16> [[ADD_I]]
@@ -832,27 +712,25 @@ int16x8_t test_vaddw_s8(int16x8_t a, int8x8_t b) {
return vaddw_s8(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vaddw_s16(<4 x i32> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vaddw_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMOVL_I_I:%.*]] = sext <4 x i16> [[TMP1]] to <4 x i32>
+// CHECK: [[VMOVL_I_I:%.*]] = sext <4 x i16> %b to <4 x i32>
// CHECK: [[ADD_I:%.*]] = add <4 x i32> %a, [[VMOVL_I_I]]
// CHECK: ret <4 x i32> [[ADD_I]]
int32x4_t test_vaddw_s16(int32x4_t a, int16x4_t b) {
return vaddw_s16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vaddw_s32(<2 x i64> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vaddw_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMOVL_I_I:%.*]] = sext <2 x i32> [[TMP1]] to <2 x i64>
+// CHECK: [[VMOVL_I_I:%.*]] = sext <2 x i32> %b to <2 x i64>
// CHECK: [[ADD_I:%.*]] = add <2 x i64> %a, [[VMOVL_I_I]]
// CHECK: ret <2 x i64> [[ADD_I]]
int64x2_t test_vaddw_s32(int64x2_t a, int32x2_t b) {
return vaddw_s32(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vaddw_u8(<8 x i16> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vaddw_u8(
// CHECK: [[VMOVL_I_I:%.*]] = zext <8 x i8> %b to <8 x i16>
// CHECK: [[ADD_I:%.*]] = add <8 x i16> %a, [[VMOVL_I_I]]
// CHECK: ret <8 x i16> [[ADD_I]]
@@ -860,141 +738,137 @@ uint16x8_t test_vaddw_u8(uint16x8_t a, uint8x8_t b) {
return vaddw_u8(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vaddw_u16(<4 x i32> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vaddw_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMOVL_I_I:%.*]] = zext <4 x i16> [[TMP1]] to <4 x i32>
+// CHECK: [[VMOVL_I_I:%.*]] = zext <4 x i16> %b to <4 x i32>
// CHECK: [[ADD_I:%.*]] = add <4 x i32> %a, [[VMOVL_I_I]]
// CHECK: ret <4 x i32> [[ADD_I]]
uint32x4_t test_vaddw_u16(uint32x4_t a, uint16x4_t b) {
return vaddw_u16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vaddw_u32(<2 x i64> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vaddw_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMOVL_I_I:%.*]] = zext <2 x i32> [[TMP1]] to <2 x i64>
+// CHECK: [[VMOVL_I_I:%.*]] = zext <2 x i32> %b to <2 x i64>
// CHECK: [[ADD_I:%.*]] = add <2 x i64> %a, [[VMOVL_I_I]]
// CHECK: ret <2 x i64> [[ADD_I]]
uint64x2_t test_vaddw_u32(uint64x2_t a, uint32x2_t b) {
return vaddw_u32(a, b);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vand_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vand_s8(
// CHECK: [[AND_I:%.*]] = and <8 x i8> %a, %b
// CHECK: ret <8 x i8> [[AND_I]]
int8x8_t test_vand_s8(int8x8_t a, int8x8_t b) {
return vand_s8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vand_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vand_s16(
// CHECK: [[AND_I:%.*]] = and <4 x i16> %a, %b
// CHECK: ret <4 x i16> [[AND_I]]
int16x4_t test_vand_s16(int16x4_t a, int16x4_t b) {
return vand_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vand_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vand_s32(
// CHECK: [[AND_I:%.*]] = and <2 x i32> %a, %b
// CHECK: ret <2 x i32> [[AND_I]]
int32x2_t test_vand_s32(int32x2_t a, int32x2_t b) {
return vand_s32(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vand_s64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vand_s64(
// CHECK: [[AND_I:%.*]] = and <1 x i64> %a, %b
// CHECK: ret <1 x i64> [[AND_I]]
int64x1_t test_vand_s64(int64x1_t a, int64x1_t b) {
return vand_s64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vand_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vand_u8(
// CHECK: [[AND_I:%.*]] = and <8 x i8> %a, %b
// CHECK: ret <8 x i8> [[AND_I]]
uint8x8_t test_vand_u8(uint8x8_t a, uint8x8_t b) {
return vand_u8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vand_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vand_u16(
// CHECK: [[AND_I:%.*]] = and <4 x i16> %a, %b
// CHECK: ret <4 x i16> [[AND_I]]
uint16x4_t test_vand_u16(uint16x4_t a, uint16x4_t b) {
return vand_u16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vand_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vand_u32(
// CHECK: [[AND_I:%.*]] = and <2 x i32> %a, %b
// CHECK: ret <2 x i32> [[AND_I]]
uint32x2_t test_vand_u32(uint32x2_t a, uint32x2_t b) {
return vand_u32(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vand_u64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vand_u64(
// CHECK: [[AND_I:%.*]] = and <1 x i64> %a, %b
// CHECK: ret <1 x i64> [[AND_I]]
uint64x1_t test_vand_u64(uint64x1_t a, uint64x1_t b) {
return vand_u64(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vandq_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vandq_s8(
// CHECK: [[AND_I:%.*]] = and <16 x i8> %a, %b
// CHECK: ret <16 x i8> [[AND_I]]
int8x16_t test_vandq_s8(int8x16_t a, int8x16_t b) {
return vandq_s8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vandq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vandq_s16(
// CHECK: [[AND_I:%.*]] = and <8 x i16> %a, %b
// CHECK: ret <8 x i16> [[AND_I]]
int16x8_t test_vandq_s16(int16x8_t a, int16x8_t b) {
return vandq_s16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vandq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vandq_s32(
// CHECK: [[AND_I:%.*]] = and <4 x i32> %a, %b
// CHECK: ret <4 x i32> [[AND_I]]
int32x4_t test_vandq_s32(int32x4_t a, int32x4_t b) {
return vandq_s32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vandq_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vandq_s64(
// CHECK: [[AND_I:%.*]] = and <2 x i64> %a, %b
// CHECK: ret <2 x i64> [[AND_I]]
int64x2_t test_vandq_s64(int64x2_t a, int64x2_t b) {
return vandq_s64(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vandq_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vandq_u8(
// CHECK: [[AND_I:%.*]] = and <16 x i8> %a, %b
// CHECK: ret <16 x i8> [[AND_I]]
uint8x16_t test_vandq_u8(uint8x16_t a, uint8x16_t b) {
return vandq_u8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vandq_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vandq_u16(
// CHECK: [[AND_I:%.*]] = and <8 x i16> %a, %b
// CHECK: ret <8 x i16> [[AND_I]]
uint16x8_t test_vandq_u16(uint16x8_t a, uint16x8_t b) {
return vandq_u16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vandq_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vandq_u32(
// CHECK: [[AND_I:%.*]] = and <4 x i32> %a, %b
// CHECK: ret <4 x i32> [[AND_I]]
uint32x4_t test_vandq_u32(uint32x4_t a, uint32x4_t b) {
return vandq_u32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vandq_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vandq_u64(
// CHECK: [[AND_I:%.*]] = and <2 x i64> %a, %b
// CHECK: ret <2 x i64> [[AND_I]]
uint64x2_t test_vandq_u64(uint64x2_t a, uint64x2_t b) {
return vandq_u64(a, b);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vbic_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vbic_s8(
// CHECK: [[NEG_I:%.*]] = xor <8 x i8> %b, <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>
// CHECK: [[AND_I:%.*]] = and <8 x i8> %a, [[NEG_I]]
// CHECK: ret <8 x i8> [[AND_I]]
@@ -1002,7 +876,7 @@ int8x8_t test_vbic_s8(int8x8_t a, int8x8_t b) {
return vbic_s8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vbic_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vbic_s16(
// CHECK: [[NEG_I:%.*]] = xor <4 x i16> %b, <i16 -1, i16 -1, i16 -1, i16 -1>
// CHECK: [[AND_I:%.*]] = and <4 x i16> %a, [[NEG_I]]
// CHECK: ret <4 x i16> [[AND_I]]
@@ -1010,7 +884,7 @@ int16x4_t test_vbic_s16(int16x4_t a, int16x4_t b) {
return vbic_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vbic_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vbic_s32(
// CHECK: [[NEG_I:%.*]] = xor <2 x i32> %b, <i32 -1, i32 -1>
// CHECK: [[AND_I:%.*]] = and <2 x i32> %a, [[NEG_I]]
// CHECK: ret <2 x i32> [[AND_I]]
@@ -1018,7 +892,7 @@ int32x2_t test_vbic_s32(int32x2_t a, int32x2_t b) {
return vbic_s32(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vbic_s64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vbic_s64(
// CHECK: [[NEG_I:%.*]] = xor <1 x i64> %b, <i64 -1>
// CHECK: [[AND_I:%.*]] = and <1 x i64> %a, [[NEG_I]]
// CHECK: ret <1 x i64> [[AND_I]]
@@ -1026,7 +900,7 @@ int64x1_t test_vbic_s64(int64x1_t a, int64x1_t b) {
return vbic_s64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vbic_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vbic_u8(
// CHECK: [[NEG_I:%.*]] = xor <8 x i8> %b, <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>
// CHECK: [[AND_I:%.*]] = and <8 x i8> %a, [[NEG_I]]
// CHECK: ret <8 x i8> [[AND_I]]
@@ -1034,7 +908,7 @@ uint8x8_t test_vbic_u8(uint8x8_t a, uint8x8_t b) {
return vbic_u8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vbic_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vbic_u16(
// CHECK: [[NEG_I:%.*]] = xor <4 x i16> %b, <i16 -1, i16 -1, i16 -1, i16 -1>
// CHECK: [[AND_I:%.*]] = and <4 x i16> %a, [[NEG_I]]
// CHECK: ret <4 x i16> [[AND_I]]
@@ -1042,7 +916,7 @@ uint16x4_t test_vbic_u16(uint16x4_t a, uint16x4_t b) {
return vbic_u16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vbic_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vbic_u32(
// CHECK: [[NEG_I:%.*]] = xor <2 x i32> %b, <i32 -1, i32 -1>
// CHECK: [[AND_I:%.*]] = and <2 x i32> %a, [[NEG_I]]
// CHECK: ret <2 x i32> [[AND_I]]
@@ -1050,7 +924,7 @@ uint32x2_t test_vbic_u32(uint32x2_t a, uint32x2_t b) {
return vbic_u32(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vbic_u64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vbic_u64(
// CHECK: [[NEG_I:%.*]] = xor <1 x i64> %b, <i64 -1>
// CHECK: [[AND_I:%.*]] = and <1 x i64> %a, [[NEG_I]]
// CHECK: ret <1 x i64> [[AND_I]]
@@ -1058,7 +932,7 @@ uint64x1_t test_vbic_u64(uint64x1_t a, uint64x1_t b) {
return vbic_u64(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vbicq_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vbicq_s8(
// CHECK: [[NEG_I:%.*]] = xor <16 x i8> %b, <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>
// CHECK: [[AND_I:%.*]] = and <16 x i8> %a, [[NEG_I]]
// CHECK: ret <16 x i8> [[AND_I]]
@@ -1066,7 +940,7 @@ int8x16_t test_vbicq_s8(int8x16_t a, int8x16_t b) {
return vbicq_s8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vbicq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vbicq_s16(
// CHECK: [[NEG_I:%.*]] = xor <8 x i16> %b, <i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1>
// CHECK: [[AND_I:%.*]] = and <8 x i16> %a, [[NEG_I]]
// CHECK: ret <8 x i16> [[AND_I]]
@@ -1074,7 +948,7 @@ int16x8_t test_vbicq_s16(int16x8_t a, int16x8_t b) {
return vbicq_s16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vbicq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vbicq_s32(
// CHECK: [[NEG_I:%.*]] = xor <4 x i32> %b, <i32 -1, i32 -1, i32 -1, i32 -1>
// CHECK: [[AND_I:%.*]] = and <4 x i32> %a, [[NEG_I]]
// CHECK: ret <4 x i32> [[AND_I]]
@@ -1082,7 +956,7 @@ int32x4_t test_vbicq_s32(int32x4_t a, int32x4_t b) {
return vbicq_s32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vbicq_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vbicq_s64(
// CHECK: [[NEG_I:%.*]] = xor <2 x i64> %b, <i64 -1, i64 -1>
// CHECK: [[AND_I:%.*]] = and <2 x i64> %a, [[NEG_I]]
// CHECK: ret <2 x i64> [[AND_I]]
@@ -1090,7 +964,7 @@ int64x2_t test_vbicq_s64(int64x2_t a, int64x2_t b) {
return vbicq_s64(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vbicq_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vbicq_u8(
// CHECK: [[NEG_I:%.*]] = xor <16 x i8> %b, <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>
// CHECK: [[AND_I:%.*]] = and <16 x i8> %a, [[NEG_I]]
// CHECK: ret <16 x i8> [[AND_I]]
@@ -1098,7 +972,7 @@ uint8x16_t test_vbicq_u8(uint8x16_t a, uint8x16_t b) {
return vbicq_u8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vbicq_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vbicq_u16(
// CHECK: [[NEG_I:%.*]] = xor <8 x i16> %b, <i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1>
// CHECK: [[AND_I:%.*]] = and <8 x i16> %a, [[NEG_I]]
// CHECK: ret <8 x i16> [[AND_I]]
@@ -1106,7 +980,7 @@ uint16x8_t test_vbicq_u16(uint16x8_t a, uint16x8_t b) {
return vbicq_u16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vbicq_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vbicq_u32(
// CHECK: [[NEG_I:%.*]] = xor <4 x i32> %b, <i32 -1, i32 -1, i32 -1, i32 -1>
// CHECK: [[AND_I:%.*]] = and <4 x i32> %a, [[NEG_I]]
// CHECK: ret <4 x i32> [[AND_I]]
@@ -1114,7 +988,7 @@ uint32x4_t test_vbicq_u32(uint32x4_t a, uint32x4_t b) {
return vbicq_u32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vbicq_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vbicq_u64(
// CHECK: [[NEG_I:%.*]] = xor <2 x i64> %b, <i64 -1, i64 -1>
// CHECK: [[AND_I:%.*]] = and <2 x i64> %a, [[NEG_I]]
// CHECK: ret <2 x i64> [[AND_I]]
@@ -1122,15 +996,14 @@ uint64x2_t test_vbicq_u64(uint64x2_t a, uint64x2_t b) {
return vbicq_u64(a, b);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vbsl_s8(<8 x i8> %a, <8 x i8> %b, <8 x i8> %c) #0 {
+// CHECK-LABEL: @test_vbsl_s8(
// CHECK: [[VBSL_V_I:%.*]] = call <8 x i8> @llvm.arm.neon.vbsl.v8i8(<8 x i8> %a, <8 x i8> %b, <8 x i8> %c) #4
// CHECK: ret <8 x i8> [[VBSL_V_I]]
int8x8_t test_vbsl_s8(uint8x8_t a, int8x8_t b, int8x8_t c) {
return vbsl_s8(a, b, c);
}
-// CHECK-LABEL: define <4 x i16> @test_vbsl_s16(<4 x i16> %a, <4 x i16> %b, <4 x i16> %c) #0 {
+// CHECK-LABEL: @test_vbsl_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %c to <8 x i8>
@@ -1141,7 +1014,7 @@ int16x4_t test_vbsl_s16(uint16x4_t a, int16x4_t b, int16x4_t c) {
return vbsl_s16(a, b, c);
}
-// CHECK-LABEL: define <2 x i32> @test_vbsl_s32(<2 x i32> %a, <2 x i32> %b, <2 x i32> %c) #0 {
+// CHECK-LABEL: @test_vbsl_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> %c to <8 x i8>
@@ -1152,7 +1025,7 @@ int32x2_t test_vbsl_s32(uint32x2_t a, int32x2_t b, int32x2_t c) {
return vbsl_s32(a, b, c);
}
-// CHECK-LABEL: define <1 x i64> @test_vbsl_s64(<1 x i64> %a, <1 x i64> %b, <1 x i64> %c) #0 {
+// CHECK-LABEL: @test_vbsl_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <1 x i64> %c to <8 x i8>
@@ -1163,14 +1036,14 @@ int64x1_t test_vbsl_s64(uint64x1_t a, int64x1_t b, int64x1_t c) {
return vbsl_s64(a, b, c);
}
-// CHECK-LABEL: define <8 x i8> @test_vbsl_u8(<8 x i8> %a, <8 x i8> %b, <8 x i8> %c) #0 {
+// CHECK-LABEL: @test_vbsl_u8(
// CHECK: [[VBSL_V_I:%.*]] = call <8 x i8> @llvm.arm.neon.vbsl.v8i8(<8 x i8> %a, <8 x i8> %b, <8 x i8> %c) #4
// CHECK: ret <8 x i8> [[VBSL_V_I]]
uint8x8_t test_vbsl_u8(uint8x8_t a, uint8x8_t b, uint8x8_t c) {
return vbsl_u8(a, b, c);
}
-// CHECK-LABEL: define <4 x i16> @test_vbsl_u16(<4 x i16> %a, <4 x i16> %b, <4 x i16> %c) #0 {
+// CHECK-LABEL: @test_vbsl_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %c to <8 x i8>
@@ -1181,7 +1054,7 @@ uint16x4_t test_vbsl_u16(uint16x4_t a, uint16x4_t b, uint16x4_t c) {
return vbsl_u16(a, b, c);
}
-// CHECK-LABEL: define <2 x i32> @test_vbsl_u32(<2 x i32> %a, <2 x i32> %b, <2 x i32> %c) #0 {
+// CHECK-LABEL: @test_vbsl_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> %c to <8 x i8>
@@ -1192,7 +1065,7 @@ uint32x2_t test_vbsl_u32(uint32x2_t a, uint32x2_t b, uint32x2_t c) {
return vbsl_u32(a, b, c);
}
-// CHECK-LABEL: define <1 x i64> @test_vbsl_u64(<1 x i64> %a, <1 x i64> %b, <1 x i64> %c) #0 {
+// CHECK-LABEL: @test_vbsl_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <1 x i64> %c to <8 x i8>
@@ -1203,7 +1076,7 @@ uint64x1_t test_vbsl_u64(uint64x1_t a, uint64x1_t b, uint64x1_t c) {
return vbsl_u64(a, b, c);
}
-// CHECK-LABEL: define <2 x float> @test_vbsl_f32(<2 x i32> %a, <2 x float> %b, <2 x float> %c) #0 {
+// CHECK-LABEL: @test_vbsl_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x float> %c to <8 x i8>
@@ -1214,14 +1087,14 @@ float32x2_t test_vbsl_f32(uint32x2_t a, float32x2_t b, float32x2_t c) {
return vbsl_f32(a, b, c);
}
-// CHECK-LABEL: define <8 x i8> @test_vbsl_p8(<8 x i8> %a, <8 x i8> %b, <8 x i8> %c) #0 {
+// CHECK-LABEL: @test_vbsl_p8(
// CHECK: [[VBSL_V_I:%.*]] = call <8 x i8> @llvm.arm.neon.vbsl.v8i8(<8 x i8> %a, <8 x i8> %b, <8 x i8> %c) #4
// CHECK: ret <8 x i8> [[VBSL_V_I]]
poly8x8_t test_vbsl_p8(uint8x8_t a, poly8x8_t b, poly8x8_t c) {
return vbsl_p8(a, b, c);
}
-// CHECK-LABEL: define <4 x i16> @test_vbsl_p16(<4 x i16> %a, <4 x i16> %b, <4 x i16> %c) #0 {
+// CHECK-LABEL: @test_vbsl_p16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %c to <8 x i8>
@@ -1232,14 +1105,14 @@ poly16x4_t test_vbsl_p16(uint16x4_t a, poly16x4_t b, poly16x4_t c) {
return vbsl_p16(a, b, c);
}
-// CHECK-LABEL: define <16 x i8> @test_vbslq_s8(<16 x i8> %a, <16 x i8> %b, <16 x i8> %c) #0 {
+// CHECK-LABEL: @test_vbslq_s8(
// CHECK: [[VBSLQ_V_I:%.*]] = call <16 x i8> @llvm.arm.neon.vbsl.v16i8(<16 x i8> %a, <16 x i8> %b, <16 x i8> %c) #4
// CHECK: ret <16 x i8> [[VBSLQ_V_I]]
int8x16_t test_vbslq_s8(uint8x16_t a, int8x16_t b, int8x16_t c) {
return vbslq_s8(a, b, c);
}
-// CHECK-LABEL: define <8 x i16> @test_vbslq_s16(<8 x i16> %a, <8 x i16> %b, <8 x i16> %c) #0 {
+// CHECK-LABEL: @test_vbslq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i16> %c to <16 x i8>
@@ -1250,7 +1123,7 @@ int16x8_t test_vbslq_s16(uint16x8_t a, int16x8_t b, int16x8_t c) {
return vbslq_s16(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vbslq_s32(<4 x i32> %a, <4 x i32> %b, <4 x i32> %c) #0 {
+// CHECK-LABEL: @test_vbslq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i32> %c to <16 x i8>
@@ -1261,7 +1134,7 @@ int32x4_t test_vbslq_s32(uint32x4_t a, int32x4_t b, int32x4_t c) {
return vbslq_s32(a, b, c);
}
-// CHECK-LABEL: define <2 x i64> @test_vbslq_s64(<2 x i64> %a, <2 x i64> %b, <2 x i64> %c) #0 {
+// CHECK-LABEL: @test_vbslq_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i64> %c to <16 x i8>
@@ -1272,14 +1145,14 @@ int64x2_t test_vbslq_s64(uint64x2_t a, int64x2_t b, int64x2_t c) {
return vbslq_s64(a, b, c);
}
-// CHECK-LABEL: define <16 x i8> @test_vbslq_u8(<16 x i8> %a, <16 x i8> %b, <16 x i8> %c) #0 {
+// CHECK-LABEL: @test_vbslq_u8(
// CHECK: [[VBSLQ_V_I:%.*]] = call <16 x i8> @llvm.arm.neon.vbsl.v16i8(<16 x i8> %a, <16 x i8> %b, <16 x i8> %c) #4
// CHECK: ret <16 x i8> [[VBSLQ_V_I]]
uint8x16_t test_vbslq_u8(uint8x16_t a, uint8x16_t b, uint8x16_t c) {
return vbslq_u8(a, b, c);
}
-// CHECK-LABEL: define <8 x i16> @test_vbslq_u16(<8 x i16> %a, <8 x i16> %b, <8 x i16> %c) #0 {
+// CHECK-LABEL: @test_vbslq_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i16> %c to <16 x i8>
@@ -1290,7 +1163,7 @@ uint16x8_t test_vbslq_u16(uint16x8_t a, uint16x8_t b, uint16x8_t c) {
return vbslq_u16(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vbslq_u32(<4 x i32> %a, <4 x i32> %b, <4 x i32> %c) #0 {
+// CHECK-LABEL: @test_vbslq_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i32> %c to <16 x i8>
@@ -1301,7 +1174,7 @@ uint32x4_t test_vbslq_u32(uint32x4_t a, uint32x4_t b, uint32x4_t c) {
return vbslq_u32(a, b, c);
}
-// CHECK-LABEL: define <2 x i64> @test_vbslq_u64(<2 x i64> %a, <2 x i64> %b, <2 x i64> %c) #0 {
+// CHECK-LABEL: @test_vbslq_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i64> %c to <16 x i8>
@@ -1312,7 +1185,7 @@ uint64x2_t test_vbslq_u64(uint64x2_t a, uint64x2_t b, uint64x2_t c) {
return vbslq_u64(a, b, c);
}
-// CHECK-LABEL: define <4 x float> @test_vbslq_f32(<4 x i32> %a, <4 x float> %b, <4 x float> %c) #0 {
+// CHECK-LABEL: @test_vbslq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x float> %c to <16 x i8>
@@ -1323,14 +1196,14 @@ float32x4_t test_vbslq_f32(uint32x4_t a, float32x4_t b, float32x4_t c) {
return vbslq_f32(a, b, c);
}
-// CHECK-LABEL: define <16 x i8> @test_vbslq_p8(<16 x i8> %a, <16 x i8> %b, <16 x i8> %c) #0 {
+// CHECK-LABEL: @test_vbslq_p8(
// CHECK: [[VBSLQ_V_I:%.*]] = call <16 x i8> @llvm.arm.neon.vbsl.v16i8(<16 x i8> %a, <16 x i8> %b, <16 x i8> %c) #4
// CHECK: ret <16 x i8> [[VBSLQ_V_I]]
poly8x16_t test_vbslq_p8(uint8x16_t a, poly8x16_t b, poly8x16_t c) {
return vbslq_p8(a, b, c);
}
-// CHECK-LABEL: define <8 x i16> @test_vbslq_p16(<8 x i16> %a, <8 x i16> %b, <8 x i16> %c) #0 {
+// CHECK-LABEL: @test_vbslq_p16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i16> %c to <16 x i8>
@@ -1341,100 +1214,79 @@ poly16x8_t test_vbslq_p16(uint16x8_t a, poly16x8_t b, poly16x8_t c) {
return vbslq_p16(a, b, c);
}
-
-// CHECK-LABEL: define <2 x i32> @test_vcage_f32(<2 x float> %a, <2 x float> %b) #0 {
+// CHECK-LABEL: @test_vcage_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %b to <8 x i8>
-// CHECK: [[VCAGE_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VCAGE_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK: [[VCAGE_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vacge.v2i32.v2f32(<2 x float> [[VCAGE_V_I]], <2 x float> [[VCAGE_V1_I]]) #4
+// CHECK: [[VCAGE_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vacge.v2i32.v2f32(<2 x float> %a, <2 x float> %b) #4
// CHECK: ret <2 x i32> [[VCAGE_V2_I]]
uint32x2_t test_vcage_f32(float32x2_t a, float32x2_t b) {
return vcage_f32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vcageq_f32(<4 x float> %a, <4 x float> %b) #0 {
+// CHECK-LABEL: @test_vcageq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %b to <16 x i8>
-// CHECK: [[VCAGEQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VCAGEQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
-// CHECK: [[VCAGEQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vacge.v4i32.v4f32(<4 x float> [[VCAGEQ_V_I]], <4 x float> [[VCAGEQ_V1_I]]) #4
+// CHECK: [[VCAGEQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vacge.v4i32.v4f32(<4 x float> %a, <4 x float> %b) #4
// CHECK: ret <4 x i32> [[VCAGEQ_V2_I]]
uint32x4_t test_vcageq_f32(float32x4_t a, float32x4_t b) {
return vcageq_f32(a, b);
}
-
-// CHECK-LABEL: define <2 x i32> @test_vcagt_f32(<2 x float> %a, <2 x float> %b) #0 {
+// CHECK-LABEL: @test_vcagt_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %b to <8 x i8>
-// CHECK: [[VCAGT_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VCAGT_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK: [[VCAGT_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vacgt.v2i32.v2f32(<2 x float> [[VCAGT_V_I]], <2 x float> [[VCAGT_V1_I]]) #4
+// CHECK: [[VCAGT_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vacgt.v2i32.v2f32(<2 x float> %a, <2 x float> %b) #4
// CHECK: ret <2 x i32> [[VCAGT_V2_I]]
uint32x2_t test_vcagt_f32(float32x2_t a, float32x2_t b) {
return vcagt_f32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vcagtq_f32(<4 x float> %a, <4 x float> %b) #0 {
+// CHECK-LABEL: @test_vcagtq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %b to <16 x i8>
-// CHECK: [[VCAGTQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VCAGTQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
-// CHECK: [[VCAGTQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vacgt.v4i32.v4f32(<4 x float> [[VCAGTQ_V_I]], <4 x float> [[VCAGTQ_V1_I]]) #4
+// CHECK: [[VCAGTQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vacgt.v4i32.v4f32(<4 x float> %a, <4 x float> %b) #4
// CHECK: ret <4 x i32> [[VCAGTQ_V2_I]]
uint32x4_t test_vcagtq_f32(float32x4_t a, float32x4_t b) {
return vcagtq_f32(a, b);
}
-
-// CHECK-LABEL: define <2 x i32> @test_vcale_f32(<2 x float> %a, <2 x float> %b) #0 {
+// CHECK-LABEL: @test_vcale_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %b to <8 x i8>
-// CHECK: [[VCALE_V_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK: [[VCALE_V1_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VCALE_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vacge.v2i32.v2f32(<2 x float> [[VCALE_V_I]], <2 x float> [[VCALE_V1_I]]) #4
+// CHECK: [[VCALE_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vacge.v2i32.v2f32(<2 x float> %b, <2 x float> %a) #4
// CHECK: ret <2 x i32> [[VCALE_V2_I]]
uint32x2_t test_vcale_f32(float32x2_t a, float32x2_t b) {
return vcale_f32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vcaleq_f32(<4 x float> %a, <4 x float> %b) #0 {
+// CHECK-LABEL: @test_vcaleq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %b to <16 x i8>
-// CHECK: [[VCALEQ_V_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
-// CHECK: [[VCALEQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VCALEQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vacge.v4i32.v4f32(<4 x float> [[VCALEQ_V_I]], <4 x float> [[VCALEQ_V1_I]]) #4
+// CHECK: [[VCALEQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vacge.v4i32.v4f32(<4 x float> %b, <4 x float> %a) #4
// CHECK: ret <4 x i32> [[VCALEQ_V2_I]]
uint32x4_t test_vcaleq_f32(float32x4_t a, float32x4_t b) {
return vcaleq_f32(a, b);
}
-
-// CHECK-LABEL: define <2 x i32> @test_vcalt_f32(<2 x float> %a, <2 x float> %b) #0 {
+// CHECK-LABEL: @test_vcalt_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %b to <8 x i8>
-// CHECK: [[VCALT_V_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK: [[VCALT_V1_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VCALT_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vacgt.v2i32.v2f32(<2 x float> [[VCALT_V_I]], <2 x float> [[VCALT_V1_I]]) #4
+// CHECK: [[VCALT_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vacgt.v2i32.v2f32(<2 x float> %b, <2 x float> %a) #4
// CHECK: ret <2 x i32> [[VCALT_V2_I]]
uint32x2_t test_vcalt_f32(float32x2_t a, float32x2_t b) {
return vcalt_f32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vcaltq_f32(<4 x float> %a, <4 x float> %b) #0 {
+// CHECK-LABEL: @test_vcaltq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %b to <16 x i8>
-// CHECK: [[VCALTQ_V_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
-// CHECK: [[VCALTQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VCALTQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vacgt.v4i32.v4f32(<4 x float> [[VCALTQ_V_I]], <4 x float> [[VCALTQ_V1_I]]) #4
+// CHECK: [[VCALTQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vacgt.v4i32.v4f32(<4 x float> %b, <4 x float> %a) #4
// CHECK: ret <4 x i32> [[VCALTQ_V2_I]]
uint32x4_t test_vcaltq_f32(float32x4_t a, float32x4_t b) {
return vcaltq_f32(a, b);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vceq_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vceq_s8(
// CHECK: [[CMP_I:%.*]] = icmp eq <8 x i8> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <8 x i1> [[CMP_I]] to <8 x i8>
// CHECK: ret <8 x i8> [[SEXT_I]]
@@ -1442,7 +1294,7 @@ uint8x8_t test_vceq_s8(int8x8_t a, int8x8_t b) {
return vceq_s8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vceq_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vceq_s16(
// CHECK: [[CMP_I:%.*]] = icmp eq <4 x i16> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i16>
// CHECK: ret <4 x i16> [[SEXT_I]]
@@ -1450,7 +1302,7 @@ uint16x4_t test_vceq_s16(int16x4_t a, int16x4_t b) {
return vceq_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vceq_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vceq_s32(
// CHECK: [[CMP_I:%.*]] = icmp eq <2 x i32> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <2 x i1> [[CMP_I]] to <2 x i32>
// CHECK: ret <2 x i32> [[SEXT_I]]
@@ -1458,7 +1310,7 @@ uint32x2_t test_vceq_s32(int32x2_t a, int32x2_t b) {
return vceq_s32(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vceq_f32(<2 x float> %a, <2 x float> %b) #0 {
+// CHECK-LABEL: @test_vceq_f32(
// CHECK: [[CMP_I:%.*]] = fcmp oeq <2 x float> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <2 x i1> [[CMP_I]] to <2 x i32>
// CHECK: ret <2 x i32> [[SEXT_I]]
@@ -1466,7 +1318,7 @@ uint32x2_t test_vceq_f32(float32x2_t a, float32x2_t b) {
return vceq_f32(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vceq_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vceq_u8(
// CHECK: [[CMP_I:%.*]] = icmp eq <8 x i8> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <8 x i1> [[CMP_I]] to <8 x i8>
// CHECK: ret <8 x i8> [[SEXT_I]]
@@ -1474,7 +1326,7 @@ uint8x8_t test_vceq_u8(uint8x8_t a, uint8x8_t b) {
return vceq_u8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vceq_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vceq_u16(
// CHECK: [[CMP_I:%.*]] = icmp eq <4 x i16> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i16>
// CHECK: ret <4 x i16> [[SEXT_I]]
@@ -1482,7 +1334,7 @@ uint16x4_t test_vceq_u16(uint16x4_t a, uint16x4_t b) {
return vceq_u16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vceq_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vceq_u32(
// CHECK: [[CMP_I:%.*]] = icmp eq <2 x i32> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <2 x i1> [[CMP_I]] to <2 x i32>
// CHECK: ret <2 x i32> [[SEXT_I]]
@@ -1490,7 +1342,7 @@ uint32x2_t test_vceq_u32(uint32x2_t a, uint32x2_t b) {
return vceq_u32(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vceq_p8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vceq_p8(
// CHECK: [[CMP_I:%.*]] = icmp eq <8 x i8> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <8 x i1> [[CMP_I]] to <8 x i8>
// CHECK: ret <8 x i8> [[SEXT_I]]
@@ -1498,7 +1350,7 @@ uint8x8_t test_vceq_p8(poly8x8_t a, poly8x8_t b) {
return vceq_p8(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vceqq_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vceqq_s8(
// CHECK: [[CMP_I:%.*]] = icmp eq <16 x i8> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <16 x i1> [[CMP_I]] to <16 x i8>
// CHECK: ret <16 x i8> [[SEXT_I]]
@@ -1506,7 +1358,7 @@ uint8x16_t test_vceqq_s8(int8x16_t a, int8x16_t b) {
return vceqq_s8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vceqq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vceqq_s16(
// CHECK: [[CMP_I:%.*]] = icmp eq <8 x i16> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <8 x i1> [[CMP_I]] to <8 x i16>
// CHECK: ret <8 x i16> [[SEXT_I]]
@@ -1514,7 +1366,7 @@ uint16x8_t test_vceqq_s16(int16x8_t a, int16x8_t b) {
return vceqq_s16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vceqq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vceqq_s32(
// CHECK: [[CMP_I:%.*]] = icmp eq <4 x i32> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i32>
// CHECK: ret <4 x i32> [[SEXT_I]]
@@ -1522,7 +1374,7 @@ uint32x4_t test_vceqq_s32(int32x4_t a, int32x4_t b) {
return vceqq_s32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vceqq_f32(<4 x float> %a, <4 x float> %b) #0 {
+// CHECK-LABEL: @test_vceqq_f32(
// CHECK: [[CMP_I:%.*]] = fcmp oeq <4 x float> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i32>
// CHECK: ret <4 x i32> [[SEXT_I]]
@@ -1530,7 +1382,7 @@ uint32x4_t test_vceqq_f32(float32x4_t a, float32x4_t b) {
return vceqq_f32(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vceqq_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vceqq_u8(
// CHECK: [[CMP_I:%.*]] = icmp eq <16 x i8> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <16 x i1> [[CMP_I]] to <16 x i8>
// CHECK: ret <16 x i8> [[SEXT_I]]
@@ -1538,7 +1390,7 @@ uint8x16_t test_vceqq_u8(uint8x16_t a, uint8x16_t b) {
return vceqq_u8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vceqq_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vceqq_u16(
// CHECK: [[CMP_I:%.*]] = icmp eq <8 x i16> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <8 x i1> [[CMP_I]] to <8 x i16>
// CHECK: ret <8 x i16> [[SEXT_I]]
@@ -1546,7 +1398,7 @@ uint16x8_t test_vceqq_u16(uint16x8_t a, uint16x8_t b) {
return vceqq_u16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vceqq_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vceqq_u32(
// CHECK: [[CMP_I:%.*]] = icmp eq <4 x i32> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i32>
// CHECK: ret <4 x i32> [[SEXT_I]]
@@ -1554,7 +1406,7 @@ uint32x4_t test_vceqq_u32(uint32x4_t a, uint32x4_t b) {
return vceqq_u32(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vceqq_p8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vceqq_p8(
// CHECK: [[CMP_I:%.*]] = icmp eq <16 x i8> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <16 x i1> [[CMP_I]] to <16 x i8>
// CHECK: ret <16 x i8> [[SEXT_I]]
@@ -1562,8 +1414,7 @@ uint8x16_t test_vceqq_p8(poly8x16_t a, poly8x16_t b) {
return vceqq_p8(a, b);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vcge_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vcge_s8(
// CHECK: [[CMP_I:%.*]] = icmp sge <8 x i8> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <8 x i1> [[CMP_I]] to <8 x i8>
// CHECK: ret <8 x i8> [[SEXT_I]]
@@ -1571,7 +1422,7 @@ uint8x8_t test_vcge_s8(int8x8_t a, int8x8_t b) {
return vcge_s8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vcge_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vcge_s16(
// CHECK: [[CMP_I:%.*]] = icmp sge <4 x i16> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i16>
// CHECK: ret <4 x i16> [[SEXT_I]]
@@ -1579,7 +1430,7 @@ uint16x4_t test_vcge_s16(int16x4_t a, int16x4_t b) {
return vcge_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vcge_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vcge_s32(
// CHECK: [[CMP_I:%.*]] = icmp sge <2 x i32> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <2 x i1> [[CMP_I]] to <2 x i32>
// CHECK: ret <2 x i32> [[SEXT_I]]
@@ -1587,7 +1438,7 @@ uint32x2_t test_vcge_s32(int32x2_t a, int32x2_t b) {
return vcge_s32(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vcge_f32(<2 x float> %a, <2 x float> %b) #0 {
+// CHECK-LABEL: @test_vcge_f32(
// CHECK: [[CMP_I:%.*]] = fcmp oge <2 x float> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <2 x i1> [[CMP_I]] to <2 x i32>
// CHECK: ret <2 x i32> [[SEXT_I]]
@@ -1595,7 +1446,7 @@ uint32x2_t test_vcge_f32(float32x2_t a, float32x2_t b) {
return vcge_f32(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vcge_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vcge_u8(
// CHECK: [[CMP_I:%.*]] = icmp uge <8 x i8> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <8 x i1> [[CMP_I]] to <8 x i8>
// CHECK: ret <8 x i8> [[SEXT_I]]
@@ -1603,7 +1454,7 @@ uint8x8_t test_vcge_u8(uint8x8_t a, uint8x8_t b) {
return vcge_u8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vcge_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vcge_u16(
// CHECK: [[CMP_I:%.*]] = icmp uge <4 x i16> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i16>
// CHECK: ret <4 x i16> [[SEXT_I]]
@@ -1611,7 +1462,7 @@ uint16x4_t test_vcge_u16(uint16x4_t a, uint16x4_t b) {
return vcge_u16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vcge_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vcge_u32(
// CHECK: [[CMP_I:%.*]] = icmp uge <2 x i32> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <2 x i1> [[CMP_I]] to <2 x i32>
// CHECK: ret <2 x i32> [[SEXT_I]]
@@ -1619,7 +1470,7 @@ uint32x2_t test_vcge_u32(uint32x2_t a, uint32x2_t b) {
return vcge_u32(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vcgeq_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vcgeq_s8(
// CHECK: [[CMP_I:%.*]] = icmp sge <16 x i8> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <16 x i1> [[CMP_I]] to <16 x i8>
// CHECK: ret <16 x i8> [[SEXT_I]]
@@ -1627,7 +1478,7 @@ uint8x16_t test_vcgeq_s8(int8x16_t a, int8x16_t b) {
return vcgeq_s8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vcgeq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vcgeq_s16(
// CHECK: [[CMP_I:%.*]] = icmp sge <8 x i16> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <8 x i1> [[CMP_I]] to <8 x i16>
// CHECK: ret <8 x i16> [[SEXT_I]]
@@ -1635,7 +1486,7 @@ uint16x8_t test_vcgeq_s16(int16x8_t a, int16x8_t b) {
return vcgeq_s16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vcgeq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vcgeq_s32(
// CHECK: [[CMP_I:%.*]] = icmp sge <4 x i32> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i32>
// CHECK: ret <4 x i32> [[SEXT_I]]
@@ -1643,7 +1494,7 @@ uint32x4_t test_vcgeq_s32(int32x4_t a, int32x4_t b) {
return vcgeq_s32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vcgeq_f32(<4 x float> %a, <4 x float> %b) #0 {
+// CHECK-LABEL: @test_vcgeq_f32(
// CHECK: [[CMP_I:%.*]] = fcmp oge <4 x float> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i32>
// CHECK: ret <4 x i32> [[SEXT_I]]
@@ -1651,7 +1502,7 @@ uint32x4_t test_vcgeq_f32(float32x4_t a, float32x4_t b) {
return vcgeq_f32(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vcgeq_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vcgeq_u8(
// CHECK: [[CMP_I:%.*]] = icmp uge <16 x i8> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <16 x i1> [[CMP_I]] to <16 x i8>
// CHECK: ret <16 x i8> [[SEXT_I]]
@@ -1659,7 +1510,7 @@ uint8x16_t test_vcgeq_u8(uint8x16_t a, uint8x16_t b) {
return vcgeq_u8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vcgeq_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vcgeq_u16(
// CHECK: [[CMP_I:%.*]] = icmp uge <8 x i16> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <8 x i1> [[CMP_I]] to <8 x i16>
// CHECK: ret <8 x i16> [[SEXT_I]]
@@ -1667,7 +1518,7 @@ uint16x8_t test_vcgeq_u16(uint16x8_t a, uint16x8_t b) {
return vcgeq_u16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vcgeq_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vcgeq_u32(
// CHECK: [[CMP_I:%.*]] = icmp uge <4 x i32> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i32>
// CHECK: ret <4 x i32> [[SEXT_I]]
@@ -1675,8 +1526,7 @@ uint32x4_t test_vcgeq_u32(uint32x4_t a, uint32x4_t b) {
return vcgeq_u32(a, b);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vcgt_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vcgt_s8(
// CHECK: [[CMP_I:%.*]] = icmp sgt <8 x i8> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <8 x i1> [[CMP_I]] to <8 x i8>
// CHECK: ret <8 x i8> [[SEXT_I]]
@@ -1684,7 +1534,7 @@ uint8x8_t test_vcgt_s8(int8x8_t a, int8x8_t b) {
return vcgt_s8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vcgt_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vcgt_s16(
// CHECK: [[CMP_I:%.*]] = icmp sgt <4 x i16> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i16>
// CHECK: ret <4 x i16> [[SEXT_I]]
@@ -1692,7 +1542,7 @@ uint16x4_t test_vcgt_s16(int16x4_t a, int16x4_t b) {
return vcgt_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vcgt_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vcgt_s32(
// CHECK: [[CMP_I:%.*]] = icmp sgt <2 x i32> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <2 x i1> [[CMP_I]] to <2 x i32>
// CHECK: ret <2 x i32> [[SEXT_I]]
@@ -1700,7 +1550,7 @@ uint32x2_t test_vcgt_s32(int32x2_t a, int32x2_t b) {
return vcgt_s32(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vcgt_f32(<2 x float> %a, <2 x float> %b) #0 {
+// CHECK-LABEL: @test_vcgt_f32(
// CHECK: [[CMP_I:%.*]] = fcmp ogt <2 x float> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <2 x i1> [[CMP_I]] to <2 x i32>
// CHECK: ret <2 x i32> [[SEXT_I]]
@@ -1708,7 +1558,7 @@ uint32x2_t test_vcgt_f32(float32x2_t a, float32x2_t b) {
return vcgt_f32(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vcgt_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vcgt_u8(
// CHECK: [[CMP_I:%.*]] = icmp ugt <8 x i8> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <8 x i1> [[CMP_I]] to <8 x i8>
// CHECK: ret <8 x i8> [[SEXT_I]]
@@ -1716,7 +1566,7 @@ uint8x8_t test_vcgt_u8(uint8x8_t a, uint8x8_t b) {
return vcgt_u8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vcgt_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vcgt_u16(
// CHECK: [[CMP_I:%.*]] = icmp ugt <4 x i16> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i16>
// CHECK: ret <4 x i16> [[SEXT_I]]
@@ -1724,7 +1574,7 @@ uint16x4_t test_vcgt_u16(uint16x4_t a, uint16x4_t b) {
return vcgt_u16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vcgt_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vcgt_u32(
// CHECK: [[CMP_I:%.*]] = icmp ugt <2 x i32> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <2 x i1> [[CMP_I]] to <2 x i32>
// CHECK: ret <2 x i32> [[SEXT_I]]
@@ -1732,7 +1582,7 @@ uint32x2_t test_vcgt_u32(uint32x2_t a, uint32x2_t b) {
return vcgt_u32(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vcgtq_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vcgtq_s8(
// CHECK: [[CMP_I:%.*]] = icmp sgt <16 x i8> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <16 x i1> [[CMP_I]] to <16 x i8>
// CHECK: ret <16 x i8> [[SEXT_I]]
@@ -1740,7 +1590,7 @@ uint8x16_t test_vcgtq_s8(int8x16_t a, int8x16_t b) {
return vcgtq_s8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vcgtq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vcgtq_s16(
// CHECK: [[CMP_I:%.*]] = icmp sgt <8 x i16> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <8 x i1> [[CMP_I]] to <8 x i16>
// CHECK: ret <8 x i16> [[SEXT_I]]
@@ -1748,7 +1598,7 @@ uint16x8_t test_vcgtq_s16(int16x8_t a, int16x8_t b) {
return vcgtq_s16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vcgtq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vcgtq_s32(
// CHECK: [[CMP_I:%.*]] = icmp sgt <4 x i32> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i32>
// CHECK: ret <4 x i32> [[SEXT_I]]
@@ -1756,7 +1606,7 @@ uint32x4_t test_vcgtq_s32(int32x4_t a, int32x4_t b) {
return vcgtq_s32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vcgtq_f32(<4 x float> %a, <4 x float> %b) #0 {
+// CHECK-LABEL: @test_vcgtq_f32(
// CHECK: [[CMP_I:%.*]] = fcmp ogt <4 x float> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i32>
// CHECK: ret <4 x i32> [[SEXT_I]]
@@ -1764,7 +1614,7 @@ uint32x4_t test_vcgtq_f32(float32x4_t a, float32x4_t b) {
return vcgtq_f32(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vcgtq_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vcgtq_u8(
// CHECK: [[CMP_I:%.*]] = icmp ugt <16 x i8> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <16 x i1> [[CMP_I]] to <16 x i8>
// CHECK: ret <16 x i8> [[SEXT_I]]
@@ -1772,7 +1622,7 @@ uint8x16_t test_vcgtq_u8(uint8x16_t a, uint8x16_t b) {
return vcgtq_u8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vcgtq_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vcgtq_u16(
// CHECK: [[CMP_I:%.*]] = icmp ugt <8 x i16> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <8 x i1> [[CMP_I]] to <8 x i16>
// CHECK: ret <8 x i16> [[SEXT_I]]
@@ -1780,7 +1630,7 @@ uint16x8_t test_vcgtq_u16(uint16x8_t a, uint16x8_t b) {
return vcgtq_u16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vcgtq_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vcgtq_u32(
// CHECK: [[CMP_I:%.*]] = icmp ugt <4 x i32> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i32>
// CHECK: ret <4 x i32> [[SEXT_I]]
@@ -1788,8 +1638,7 @@ uint32x4_t test_vcgtq_u32(uint32x4_t a, uint32x4_t b) {
return vcgtq_u32(a, b);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vcle_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vcle_s8(
// CHECK: [[CMP_I:%.*]] = icmp sle <8 x i8> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <8 x i1> [[CMP_I]] to <8 x i8>
// CHECK: ret <8 x i8> [[SEXT_I]]
@@ -1797,7 +1646,7 @@ uint8x8_t test_vcle_s8(int8x8_t a, int8x8_t b) {
return vcle_s8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vcle_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vcle_s16(
// CHECK: [[CMP_I:%.*]] = icmp sle <4 x i16> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i16>
// CHECK: ret <4 x i16> [[SEXT_I]]
@@ -1805,7 +1654,7 @@ uint16x4_t test_vcle_s16(int16x4_t a, int16x4_t b) {
return vcle_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vcle_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vcle_s32(
// CHECK: [[CMP_I:%.*]] = icmp sle <2 x i32> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <2 x i1> [[CMP_I]] to <2 x i32>
// CHECK: ret <2 x i32> [[SEXT_I]]
@@ -1813,7 +1662,7 @@ uint32x2_t test_vcle_s32(int32x2_t a, int32x2_t b) {
return vcle_s32(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vcle_f32(<2 x float> %a, <2 x float> %b) #0 {
+// CHECK-LABEL: @test_vcle_f32(
// CHECK: [[CMP_I:%.*]] = fcmp ole <2 x float> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <2 x i1> [[CMP_I]] to <2 x i32>
// CHECK: ret <2 x i32> [[SEXT_I]]
@@ -1821,7 +1670,7 @@ uint32x2_t test_vcle_f32(float32x2_t a, float32x2_t b) {
return vcle_f32(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vcle_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vcle_u8(
// CHECK: [[CMP_I:%.*]] = icmp ule <8 x i8> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <8 x i1> [[CMP_I]] to <8 x i8>
// CHECK: ret <8 x i8> [[SEXT_I]]
@@ -1829,7 +1678,7 @@ uint8x8_t test_vcle_u8(uint8x8_t a, uint8x8_t b) {
return vcle_u8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vcle_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vcle_u16(
// CHECK: [[CMP_I:%.*]] = icmp ule <4 x i16> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i16>
// CHECK: ret <4 x i16> [[SEXT_I]]
@@ -1837,7 +1686,7 @@ uint16x4_t test_vcle_u16(uint16x4_t a, uint16x4_t b) {
return vcle_u16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vcle_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vcle_u32(
// CHECK: [[CMP_I:%.*]] = icmp ule <2 x i32> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <2 x i1> [[CMP_I]] to <2 x i32>
// CHECK: ret <2 x i32> [[SEXT_I]]
@@ -1845,7 +1694,7 @@ uint32x2_t test_vcle_u32(uint32x2_t a, uint32x2_t b) {
return vcle_u32(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vcleq_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vcleq_s8(
// CHECK: [[CMP_I:%.*]] = icmp sle <16 x i8> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <16 x i1> [[CMP_I]] to <16 x i8>
// CHECK: ret <16 x i8> [[SEXT_I]]
@@ -1853,7 +1702,7 @@ uint8x16_t test_vcleq_s8(int8x16_t a, int8x16_t b) {
return vcleq_s8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vcleq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vcleq_s16(
// CHECK: [[CMP_I:%.*]] = icmp sle <8 x i16> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <8 x i1> [[CMP_I]] to <8 x i16>
// CHECK: ret <8 x i16> [[SEXT_I]]
@@ -1861,7 +1710,7 @@ uint16x8_t test_vcleq_s16(int16x8_t a, int16x8_t b) {
return vcleq_s16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vcleq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vcleq_s32(
// CHECK: [[CMP_I:%.*]] = icmp sle <4 x i32> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i32>
// CHECK: ret <4 x i32> [[SEXT_I]]
@@ -1869,7 +1718,7 @@ uint32x4_t test_vcleq_s32(int32x4_t a, int32x4_t b) {
return vcleq_s32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vcleq_f32(<4 x float> %a, <4 x float> %b) #0 {
+// CHECK-LABEL: @test_vcleq_f32(
// CHECK: [[CMP_I:%.*]] = fcmp ole <4 x float> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i32>
// CHECK: ret <4 x i32> [[SEXT_I]]
@@ -1877,7 +1726,7 @@ uint32x4_t test_vcleq_f32(float32x4_t a, float32x4_t b) {
return vcleq_f32(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vcleq_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vcleq_u8(
// CHECK: [[CMP_I:%.*]] = icmp ule <16 x i8> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <16 x i1> [[CMP_I]] to <16 x i8>
// CHECK: ret <16 x i8> [[SEXT_I]]
@@ -1885,7 +1734,7 @@ uint8x16_t test_vcleq_u8(uint8x16_t a, uint8x16_t b) {
return vcleq_u8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vcleq_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vcleq_u16(
// CHECK: [[CMP_I:%.*]] = icmp ule <8 x i16> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <8 x i1> [[CMP_I]] to <8 x i16>
// CHECK: ret <8 x i16> [[SEXT_I]]
@@ -1893,7 +1742,7 @@ uint16x8_t test_vcleq_u16(uint16x8_t a, uint16x8_t b) {
return vcleq_u16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vcleq_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vcleq_u32(
// CHECK: [[CMP_I:%.*]] = icmp ule <4 x i32> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i32>
// CHECK: ret <4 x i32> [[SEXT_I]]
@@ -1901,67 +1750,57 @@ uint32x4_t test_vcleq_u32(uint32x4_t a, uint32x4_t b) {
return vcleq_u32(a, b);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vcls_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vcls_s8(
// CHECK: [[VCLS_V_I:%.*]] = call <8 x i8> @llvm.arm.neon.vcls.v8i8(<8 x i8> %a) #4
// CHECK: ret <8 x i8> [[VCLS_V_I]]
int8x8_t test_vcls_s8(int8x8_t a) {
return vcls_s8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vcls_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vcls_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
-// CHECK: [[VCLS_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VCLS_V1_I:%.*]] = call <4 x i16> @llvm.arm.neon.vcls.v4i16(<4 x i16> [[VCLS_V_I]]) #4
+// CHECK: [[VCLS_V1_I:%.*]] = call <4 x i16> @llvm.arm.neon.vcls.v4i16(<4 x i16> %a) #4
// CHECK: [[VCLS_V2_I:%.*]] = bitcast <4 x i16> [[VCLS_V1_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[VCLS_V2_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP1]]
+// CHECK: ret <4 x i16> [[VCLS_V1_I]]
int16x4_t test_vcls_s16(int16x4_t a) {
return vcls_s16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vcls_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vcls_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[VCLS_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VCLS_V1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vcls.v2i32(<2 x i32> [[VCLS_V_I]]) #4
+// CHECK: [[VCLS_V1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vcls.v2i32(<2 x i32> %a) #4
// CHECK: [[VCLS_V2_I:%.*]] = bitcast <2 x i32> [[VCLS_V1_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[VCLS_V2_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP1]]
+// CHECK: ret <2 x i32> [[VCLS_V1_I]]
int32x2_t test_vcls_s32(int32x2_t a) {
return vcls_s32(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vclsq_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vclsq_s8(
// CHECK: [[VCLSQ_V_I:%.*]] = call <16 x i8> @llvm.arm.neon.vcls.v16i8(<16 x i8> %a) #4
// CHECK: ret <16 x i8> [[VCLSQ_V_I]]
int8x16_t test_vclsq_s8(int8x16_t a) {
return vclsq_s8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vclsq_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vclsq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
-// CHECK: [[VCLSQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VCLSQ_V1_I:%.*]] = call <8 x i16> @llvm.arm.neon.vcls.v8i16(<8 x i16> [[VCLSQ_V_I]]) #4
+// CHECK: [[VCLSQ_V1_I:%.*]] = call <8 x i16> @llvm.arm.neon.vcls.v8i16(<8 x i16> %a) #4
// CHECK: [[VCLSQ_V2_I:%.*]] = bitcast <8 x i16> [[VCLSQ_V1_I]] to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[VCLSQ_V2_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP1]]
+// CHECK: ret <8 x i16> [[VCLSQ_V1_I]]
int16x8_t test_vclsq_s16(int16x8_t a) {
return vclsq_s16(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vclsq_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vclsq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
-// CHECK: [[VCLSQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VCLSQ_V1_I:%.*]] = call <4 x i32> @llvm.arm.neon.vcls.v4i32(<4 x i32> [[VCLSQ_V_I]]) #4
+// CHECK: [[VCLSQ_V1_I:%.*]] = call <4 x i32> @llvm.arm.neon.vcls.v4i32(<4 x i32> %a) #4
// CHECK: [[VCLSQ_V2_I:%.*]] = bitcast <4 x i32> [[VCLSQ_V1_I]] to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[VCLSQ_V2_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP1]]
+// CHECK: ret <4 x i32> [[VCLSQ_V1_I]]
int32x4_t test_vclsq_s32(int32x4_t a) {
return vclsq_s32(a);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vclt_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vclt_s8(
// CHECK: [[CMP_I:%.*]] = icmp slt <8 x i8> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <8 x i1> [[CMP_I]] to <8 x i8>
// CHECK: ret <8 x i8> [[SEXT_I]]
@@ -1969,7 +1808,7 @@ uint8x8_t test_vclt_s8(int8x8_t a, int8x8_t b) {
return vclt_s8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vclt_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vclt_s16(
// CHECK: [[CMP_I:%.*]] = icmp slt <4 x i16> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i16>
// CHECK: ret <4 x i16> [[SEXT_I]]
@@ -1977,7 +1816,7 @@ uint16x4_t test_vclt_s16(int16x4_t a, int16x4_t b) {
return vclt_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vclt_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vclt_s32(
// CHECK: [[CMP_I:%.*]] = icmp slt <2 x i32> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <2 x i1> [[CMP_I]] to <2 x i32>
// CHECK: ret <2 x i32> [[SEXT_I]]
@@ -1985,7 +1824,7 @@ uint32x2_t test_vclt_s32(int32x2_t a, int32x2_t b) {
return vclt_s32(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vclt_f32(<2 x float> %a, <2 x float> %b) #0 {
+// CHECK-LABEL: @test_vclt_f32(
// CHECK: [[CMP_I:%.*]] = fcmp olt <2 x float> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <2 x i1> [[CMP_I]] to <2 x i32>
// CHECK: ret <2 x i32> [[SEXT_I]]
@@ -1993,7 +1832,7 @@ uint32x2_t test_vclt_f32(float32x2_t a, float32x2_t b) {
return vclt_f32(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vclt_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vclt_u8(
// CHECK: [[CMP_I:%.*]] = icmp ult <8 x i8> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <8 x i1> [[CMP_I]] to <8 x i8>
// CHECK: ret <8 x i8> [[SEXT_I]]
@@ -2001,7 +1840,7 @@ uint8x8_t test_vclt_u8(uint8x8_t a, uint8x8_t b) {
return vclt_u8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vclt_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vclt_u16(
// CHECK: [[CMP_I:%.*]] = icmp ult <4 x i16> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i16>
// CHECK: ret <4 x i16> [[SEXT_I]]
@@ -2009,7 +1848,7 @@ uint16x4_t test_vclt_u16(uint16x4_t a, uint16x4_t b) {
return vclt_u16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vclt_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vclt_u32(
// CHECK: [[CMP_I:%.*]] = icmp ult <2 x i32> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <2 x i1> [[CMP_I]] to <2 x i32>
// CHECK: ret <2 x i32> [[SEXT_I]]
@@ -2017,7 +1856,7 @@ uint32x2_t test_vclt_u32(uint32x2_t a, uint32x2_t b) {
return vclt_u32(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vcltq_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vcltq_s8(
// CHECK: [[CMP_I:%.*]] = icmp slt <16 x i8> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <16 x i1> [[CMP_I]] to <16 x i8>
// CHECK: ret <16 x i8> [[SEXT_I]]
@@ -2025,7 +1864,7 @@ uint8x16_t test_vcltq_s8(int8x16_t a, int8x16_t b) {
return vcltq_s8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vcltq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vcltq_s16(
// CHECK: [[CMP_I:%.*]] = icmp slt <8 x i16> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <8 x i1> [[CMP_I]] to <8 x i16>
// CHECK: ret <8 x i16> [[SEXT_I]]
@@ -2033,7 +1872,7 @@ uint16x8_t test_vcltq_s16(int16x8_t a, int16x8_t b) {
return vcltq_s16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vcltq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vcltq_s32(
// CHECK: [[CMP_I:%.*]] = icmp slt <4 x i32> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i32>
// CHECK: ret <4 x i32> [[SEXT_I]]
@@ -2041,7 +1880,7 @@ uint32x4_t test_vcltq_s32(int32x4_t a, int32x4_t b) {
return vcltq_s32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vcltq_f32(<4 x float> %a, <4 x float> %b) #0 {
+// CHECK-LABEL: @test_vcltq_f32(
// CHECK: [[CMP_I:%.*]] = fcmp olt <4 x float> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i32>
// CHECK: ret <4 x i32> [[SEXT_I]]
@@ -2049,7 +1888,7 @@ uint32x4_t test_vcltq_f32(float32x4_t a, float32x4_t b) {
return vcltq_f32(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vcltq_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vcltq_u8(
// CHECK: [[CMP_I:%.*]] = icmp ult <16 x i8> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <16 x i1> [[CMP_I]] to <16 x i8>
// CHECK: ret <16 x i8> [[SEXT_I]]
@@ -2057,7 +1896,7 @@ uint8x16_t test_vcltq_u8(uint8x16_t a, uint8x16_t b) {
return vcltq_u8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vcltq_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vcltq_u16(
// CHECK: [[CMP_I:%.*]] = icmp ult <8 x i16> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <8 x i1> [[CMP_I]] to <8 x i16>
// CHECK: ret <8 x i16> [[SEXT_I]]
@@ -2065,7 +1904,7 @@ uint16x8_t test_vcltq_u16(uint16x8_t a, uint16x8_t b) {
return vcltq_u16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vcltq_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vcltq_u32(
// CHECK: [[CMP_I:%.*]] = icmp ult <4 x i32> %a, %b
// CHECK: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i32>
// CHECK: ret <4 x i32> [[SEXT_I]]
@@ -2073,253 +1912,233 @@ uint32x4_t test_vcltq_u32(uint32x4_t a, uint32x4_t b) {
return vcltq_u32(a, b);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vclz_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vclz_s8(
// CHECK: [[VCLZ_V_I:%.*]] = call <8 x i8> @llvm.ctlz.v8i8(<8 x i8> %a, i1 false) #4
// CHECK: ret <8 x i8> [[VCLZ_V_I]]
int8x8_t test_vclz_s8(int8x8_t a) {
return vclz_s8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vclz_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vclz_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
-// CHECK: [[VCLZ_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VCLZ_V1_I:%.*]] = call <4 x i16> @llvm.ctlz.v4i16(<4 x i16> [[VCLZ_V_I]], i1 false) #4
+// CHECK: [[VCLZ_V1_I:%.*]] = call <4 x i16> @llvm.ctlz.v4i16(<4 x i16> %a, i1 false) #4
// CHECK: [[VCLZ_V2_I:%.*]] = bitcast <4 x i16> [[VCLZ_V1_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[VCLZ_V2_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP1]]
+// CHECK: ret <4 x i16> [[VCLZ_V1_I]]
int16x4_t test_vclz_s16(int16x4_t a) {
return vclz_s16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vclz_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vclz_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[VCLZ_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VCLZ_V1_I:%.*]] = call <2 x i32> @llvm.ctlz.v2i32(<2 x i32> [[VCLZ_V_I]], i1 false) #4
+// CHECK: [[VCLZ_V1_I:%.*]] = call <2 x i32> @llvm.ctlz.v2i32(<2 x i32> %a, i1 false) #4
// CHECK: [[VCLZ_V2_I:%.*]] = bitcast <2 x i32> [[VCLZ_V1_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[VCLZ_V2_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP1]]
+// CHECK: ret <2 x i32> [[VCLZ_V1_I]]
int32x2_t test_vclz_s32(int32x2_t a) {
return vclz_s32(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vclz_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vclz_u8(
// CHECK: [[VCLZ_V_I:%.*]] = call <8 x i8> @llvm.ctlz.v8i8(<8 x i8> %a, i1 false) #4
// CHECK: ret <8 x i8> [[VCLZ_V_I]]
uint8x8_t test_vclz_u8(uint8x8_t a) {
return vclz_u8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vclz_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vclz_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
-// CHECK: [[VCLZ_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VCLZ_V1_I:%.*]] = call <4 x i16> @llvm.ctlz.v4i16(<4 x i16> [[VCLZ_V_I]], i1 false) #4
+// CHECK: [[VCLZ_V1_I:%.*]] = call <4 x i16> @llvm.ctlz.v4i16(<4 x i16> %a, i1 false) #4
// CHECK: [[VCLZ_V2_I:%.*]] = bitcast <4 x i16> [[VCLZ_V1_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[VCLZ_V2_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP1]]
+// CHECK: ret <4 x i16> [[VCLZ_V1_I]]
uint16x4_t test_vclz_u16(uint16x4_t a) {
return vclz_u16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vclz_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vclz_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[VCLZ_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VCLZ_V1_I:%.*]] = call <2 x i32> @llvm.ctlz.v2i32(<2 x i32> [[VCLZ_V_I]], i1 false) #4
+// CHECK: [[VCLZ_V1_I:%.*]] = call <2 x i32> @llvm.ctlz.v2i32(<2 x i32> %a, i1 false) #4
// CHECK: [[VCLZ_V2_I:%.*]] = bitcast <2 x i32> [[VCLZ_V1_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[VCLZ_V2_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP1]]
+// CHECK: ret <2 x i32> [[VCLZ_V1_I]]
uint32x2_t test_vclz_u32(uint32x2_t a) {
return vclz_u32(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vclzq_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vclzq_s8(
// CHECK: [[VCLZQ_V_I:%.*]] = call <16 x i8> @llvm.ctlz.v16i8(<16 x i8> %a, i1 false) #4
// CHECK: ret <16 x i8> [[VCLZQ_V_I]]
int8x16_t test_vclzq_s8(int8x16_t a) {
return vclzq_s8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vclzq_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vclzq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
-// CHECK: [[VCLZQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VCLZQ_V1_I:%.*]] = call <8 x i16> @llvm.ctlz.v8i16(<8 x i16> [[VCLZQ_V_I]], i1 false) #4
+// CHECK: [[VCLZQ_V1_I:%.*]] = call <8 x i16> @llvm.ctlz.v8i16(<8 x i16> %a, i1 false) #4
// CHECK: [[VCLZQ_V2_I:%.*]] = bitcast <8 x i16> [[VCLZQ_V1_I]] to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[VCLZQ_V2_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP1]]
+// CHECK: ret <8 x i16> [[VCLZQ_V1_I]]
int16x8_t test_vclzq_s16(int16x8_t a) {
return vclzq_s16(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vclzq_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vclzq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
-// CHECK: [[VCLZQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VCLZQ_V1_I:%.*]] = call <4 x i32> @llvm.ctlz.v4i32(<4 x i32> [[VCLZQ_V_I]], i1 false) #4
+// CHECK: [[VCLZQ_V1_I:%.*]] = call <4 x i32> @llvm.ctlz.v4i32(<4 x i32> %a, i1 false) #4
// CHECK: [[VCLZQ_V2_I:%.*]] = bitcast <4 x i32> [[VCLZQ_V1_I]] to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[VCLZQ_V2_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP1]]
+// CHECK: ret <4 x i32> [[VCLZQ_V1_I]]
int32x4_t test_vclzq_s32(int32x4_t a) {
return vclzq_s32(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vclzq_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vclzq_u8(
// CHECK: [[VCLZQ_V_I:%.*]] = call <16 x i8> @llvm.ctlz.v16i8(<16 x i8> %a, i1 false) #4
// CHECK: ret <16 x i8> [[VCLZQ_V_I]]
uint8x16_t test_vclzq_u8(uint8x16_t a) {
return vclzq_u8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vclzq_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vclzq_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
-// CHECK: [[VCLZQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VCLZQ_V1_I:%.*]] = call <8 x i16> @llvm.ctlz.v8i16(<8 x i16> [[VCLZQ_V_I]], i1 false) #4
+// CHECK: [[VCLZQ_V1_I:%.*]] = call <8 x i16> @llvm.ctlz.v8i16(<8 x i16> %a, i1 false) #4
// CHECK: [[VCLZQ_V2_I:%.*]] = bitcast <8 x i16> [[VCLZQ_V1_I]] to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[VCLZQ_V2_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP1]]
+// CHECK: ret <8 x i16> [[VCLZQ_V1_I]]
uint16x8_t test_vclzq_u16(uint16x8_t a) {
return vclzq_u16(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vclzq_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vclzq_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
-// CHECK: [[VCLZQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VCLZQ_V1_I:%.*]] = call <4 x i32> @llvm.ctlz.v4i32(<4 x i32> [[VCLZQ_V_I]], i1 false) #4
+// CHECK: [[VCLZQ_V1_I:%.*]] = call <4 x i32> @llvm.ctlz.v4i32(<4 x i32> %a, i1 false) #4
// CHECK: [[VCLZQ_V2_I:%.*]] = bitcast <4 x i32> [[VCLZQ_V1_I]] to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[VCLZQ_V2_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP1]]
+// CHECK: ret <4 x i32> [[VCLZQ_V1_I]]
uint32x4_t test_vclzq_u32(uint32x4_t a) {
return vclzq_u32(a);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vcnt_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vcnt_u8(
// CHECK: [[VCNT_V_I:%.*]] = call <8 x i8> @llvm.ctpop.v8i8(<8 x i8> %a) #4
// CHECK: ret <8 x i8> [[VCNT_V_I]]
uint8x8_t test_vcnt_u8(uint8x8_t a) {
return vcnt_u8(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vcnt_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vcnt_s8(
// CHECK: [[VCNT_V_I:%.*]] = call <8 x i8> @llvm.ctpop.v8i8(<8 x i8> %a) #4
// CHECK: ret <8 x i8> [[VCNT_V_I]]
int8x8_t test_vcnt_s8(int8x8_t a) {
return vcnt_s8(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vcnt_p8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vcnt_p8(
// CHECK: [[VCNT_V_I:%.*]] = call <8 x i8> @llvm.ctpop.v8i8(<8 x i8> %a) #4
// CHECK: ret <8 x i8> [[VCNT_V_I]]
poly8x8_t test_vcnt_p8(poly8x8_t a) {
return vcnt_p8(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vcntq_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vcntq_u8(
// CHECK: [[VCNTQ_V_I:%.*]] = call <16 x i8> @llvm.ctpop.v16i8(<16 x i8> %a) #4
// CHECK: ret <16 x i8> [[VCNTQ_V_I]]
uint8x16_t test_vcntq_u8(uint8x16_t a) {
return vcntq_u8(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vcntq_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vcntq_s8(
// CHECK: [[VCNTQ_V_I:%.*]] = call <16 x i8> @llvm.ctpop.v16i8(<16 x i8> %a) #4
// CHECK: ret <16 x i8> [[VCNTQ_V_I]]
int8x16_t test_vcntq_s8(int8x16_t a) {
return vcntq_s8(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vcntq_p8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vcntq_p8(
// CHECK: [[VCNTQ_V_I:%.*]] = call <16 x i8> @llvm.ctpop.v16i8(<16 x i8> %a) #4
// CHECK: ret <16 x i8> [[VCNTQ_V_I]]
poly8x16_t test_vcntq_p8(poly8x16_t a) {
return vcntq_p8(a);
}
-
-// CHECK-LABEL: define <16 x i8> @test_vcombine_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vcombine_s8(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <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 <16 x i8> [[SHUFFLE_I]]
int8x16_t test_vcombine_s8(int8x8_t a, int8x8_t b) {
return vcombine_s8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vcombine_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vcombine_s16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
// CHECK: ret <8 x i16> [[SHUFFLE_I]]
int16x8_t test_vcombine_s16(int16x4_t a, int16x4_t b) {
return vcombine_s16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vcombine_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vcombine_s32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
// CHECK: ret <4 x i32> [[SHUFFLE_I]]
int32x4_t test_vcombine_s32(int32x2_t a, int32x2_t b) {
return vcombine_s32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vcombine_s64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vcombine_s64(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <1 x i64> %a, <1 x i64> %b, <2 x i32> <i32 0, i32 1>
// CHECK: ret <2 x i64> [[SHUFFLE_I]]
int64x2_t test_vcombine_s64(int64x1_t a, int64x1_t b) {
return vcombine_s64(a, b);
}
-// CHECK-LABEL: define <8 x half> @test_vcombine_f16(<4 x half> %a, <4 x half> %b) #0 {
+// CHECK-LABEL: @test_vcombine_f16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x half> %a, <4 x half> %b, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
// CHECK: ret <8 x half> [[SHUFFLE_I]]
float16x8_t test_vcombine_f16(float16x4_t a, float16x4_t b) {
return vcombine_f16(a, b);
}
-// CHECK-LABEL: define <4 x float> @test_vcombine_f32(<2 x float> %a, <2 x float> %b) #0 {
+// CHECK-LABEL: @test_vcombine_f32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x float> %a, <2 x float> %b, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
// CHECK: ret <4 x float> [[SHUFFLE_I]]
float32x4_t test_vcombine_f32(float32x2_t a, float32x2_t b) {
return vcombine_f32(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vcombine_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vcombine_u8(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <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 <16 x i8> [[SHUFFLE_I]]
uint8x16_t test_vcombine_u8(uint8x8_t a, uint8x8_t b) {
return vcombine_u8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vcombine_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vcombine_u16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
// CHECK: ret <8 x i16> [[SHUFFLE_I]]
uint16x8_t test_vcombine_u16(uint16x4_t a, uint16x4_t b) {
return vcombine_u16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vcombine_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vcombine_u32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %b, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
// CHECK: ret <4 x i32> [[SHUFFLE_I]]
uint32x4_t test_vcombine_u32(uint32x2_t a, uint32x2_t b) {
return vcombine_u32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vcombine_u64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vcombine_u64(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <1 x i64> %a, <1 x i64> %b, <2 x i32> <i32 0, i32 1>
// CHECK: ret <2 x i64> [[SHUFFLE_I]]
uint64x2_t test_vcombine_u64(uint64x1_t a, uint64x1_t b) {
return vcombine_u64(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vcombine_p8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vcombine_p8(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <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 <16 x i8> [[SHUFFLE_I]]
poly8x16_t test_vcombine_p8(poly8x8_t a, poly8x8_t b) {
return vcombine_p8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vcombine_p16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vcombine_p16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %b, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
// CHECK: ret <8 x i16> [[SHUFFLE_I]]
poly16x8_t test_vcombine_p16(poly16x4_t a, poly16x4_t b) {
return vcombine_p16(a, b);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vcreate_s8(i64 %a) #0 {
+// CHECK-LABEL: @test_vcreate_s8(
// CHECK: [[TMP0:%.*]] = bitcast i64 %a to <8 x i8>
// CHECK: [[VCLZ_V_I:%.*]] = call <8 x i8> @llvm.ctlz.v8i8(<8 x i8> [[TMP0]], i1 false) #4
// CHECK: ret <8 x i8> [[VCLZ_V_I]]
@@ -2327,45 +2146,41 @@ int8x8_t test_vcreate_s8(uint64_t a) {
return vclz_s8(vcreate_s8(a));
}
-// CHECK-LABEL: define <4 x i16> @test_vcreate_s16(i64 %a) #0 {
+// CHECK-LABEL: @test_vcreate_s16(
// CHECK: [[TMP0:%.*]] = bitcast i64 %a to <4 x i16>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[TMP0]] to <8 x i8>
-// CHECK: [[VCLZ_V_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VCLZ_V1_I:%.*]] = call <4 x i16> @llvm.ctlz.v4i16(<4 x i16> [[VCLZ_V_I]], i1 false) #4
+// CHECK: [[VCLZ_V1_I:%.*]] = call <4 x i16> @llvm.ctlz.v4i16(<4 x i16> [[TMP0]], i1 false) #4
// CHECK: [[VCLZ_V2_I:%.*]] = bitcast <4 x i16> [[VCLZ_V1_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VCLZ_V2_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VCLZ_V1_I]]
int16x4_t test_vcreate_s16(uint64_t a) {
return vclz_s16(vcreate_s16(a));
}
-// CHECK-LABEL: define <2 x i32> @test_vcreate_s32(i64 %a) #0 {
+// CHECK-LABEL: @test_vcreate_s32(
// CHECK: [[TMP0:%.*]] = bitcast i64 %a to <2 x i32>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[TMP0]] to <8 x i8>
-// CHECK: [[VCLZ_V_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VCLZ_V1_I:%.*]] = call <2 x i32> @llvm.ctlz.v2i32(<2 x i32> [[VCLZ_V_I]], i1 false) #4
+// CHECK: [[VCLZ_V1_I:%.*]] = call <2 x i32> @llvm.ctlz.v2i32(<2 x i32> [[TMP0]], i1 false) #4
// CHECK: [[VCLZ_V2_I:%.*]] = bitcast <2 x i32> [[VCLZ_V1_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VCLZ_V2_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VCLZ_V1_I]]
int32x2_t test_vcreate_s32(uint64_t a) {
return vclz_s32(vcreate_s32(a));
}
-// CHECK-LABEL: define <4 x half> @test_vcreate_f16(i64 %a) #0 {
+// CHECK-LABEL: @test_vcreate_f16(
// CHECK: [[TMP0:%.*]] = bitcast i64 %a to <4 x half>
// CHECK: ret <4 x half> [[TMP0]]
float16x4_t test_vcreate_f16(uint64_t a) {
return vcreate_f16(a);
}
-// CHECK-LABEL: define <2 x float> @test_vcreate_f32(i64 %a) #0 {
+// CHECK-LABEL: @test_vcreate_f32(
// CHECK: [[TMP0:%.*]] = bitcast i64 %a to <2 x float>
// CHECK: ret <2 x float> [[TMP0]]
float32x2_t test_vcreate_f32(uint64_t a) {
return vcreate_f32(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vcreate_u8(i64 %a) #0 {
+// CHECK-LABEL: @test_vcreate_u8(
// CHECK: [[TMP0:%.*]] = bitcast i64 %a to <8 x i8>
// CHECK: [[VCLZ_V_I:%.*]] = call <8 x i8> @llvm.ctlz.v8i8(<8 x i8> [[TMP0]], i1 false) #4
// CHECK: ret <8 x i8> [[VCLZ_V_I]]
@@ -2373,45 +2188,36 @@ uint8x8_t test_vcreate_u8(uint64_t a) {
return vclz_s8(vcreate_u8(a));
}
-// CHECK-LABEL: define <4 x i16> @test_vcreate_u16(i64 %a) #0 {
+// CHECK-LABEL: @test_vcreate_u16(
// CHECK: [[TMP0:%.*]] = bitcast i64 %a to <4 x i16>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[TMP0]] to <8 x i8>
-// CHECK: [[VCLZ_V_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VCLZ_V1_I:%.*]] = call <4 x i16> @llvm.ctlz.v4i16(<4 x i16> [[VCLZ_V_I]], i1 false) #4
+// CHECK: [[VCLZ_V1_I:%.*]] = call <4 x i16> @llvm.ctlz.v4i16(<4 x i16> [[TMP0]], i1 false) #4
// CHECK: [[VCLZ_V2_I:%.*]] = bitcast <4 x i16> [[VCLZ_V1_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VCLZ_V2_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VCLZ_V1_I]]
uint16x4_t test_vcreate_u16(uint64_t a) {
return vclz_s16(vcreate_u16(a));
}
-// CHECK-LABEL: define <2 x i32> @test_vcreate_u32(i64 %a) #0 {
+// CHECK-LABEL: @test_vcreate_u32(
// CHECK: [[TMP0:%.*]] = bitcast i64 %a to <2 x i32>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[TMP0]] to <8 x i8>
-// CHECK: [[VCLZ_V_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VCLZ_V1_I:%.*]] = call <2 x i32> @llvm.ctlz.v2i32(<2 x i32> [[VCLZ_V_I]], i1 false) #4
+// CHECK: [[VCLZ_V1_I:%.*]] = call <2 x i32> @llvm.ctlz.v2i32(<2 x i32> [[TMP0]], i1 false) #4
// CHECK: [[VCLZ_V2_I:%.*]] = bitcast <2 x i32> [[VCLZ_V1_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VCLZ_V2_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VCLZ_V1_I]]
uint32x2_t test_vcreate_u32(uint64_t a) {
return vclz_s32(vcreate_u32(a));
}
-
-// We have two ways of lowering that. Either with one 'vmov d, r, r' or
-// with two 'vmov d[],r'. LLVM does the latter. We may want to be less
-// strict about the matching pattern if it starts causing problem.
-// CHECK-LABEL: define <1 x i64> @test_vcreate_u64(i64 %a) #0 {
+// CHECK-LABEL: @test_vcreate_u64(
// CHECK: [[TMP0:%.*]] = bitcast i64 %a to <1 x i64>
// CHECK: [[ADD_I:%.*]] = add <1 x i64> [[TMP0]], [[TMP0]]
// CHECK: ret <1 x i64> [[ADD_I]]
uint64x1_t test_vcreate_u64(uint64_t a) {
uint64x1_t tmp = vcreate_u64(a);
return vadd_u64(tmp, tmp);
-
}
-// CHECK-LABEL: define <8 x i8> @test_vcreate_p8(i64 %a) #0 {
+// CHECK-LABEL: @test_vcreate_p8(
// CHECK: [[TMP0:%.*]] = bitcast i64 %a to <8 x i8>
// CHECK: [[VCNT_V_I:%.*]] = call <8 x i8> @llvm.ctpop.v8i8(<8 x i8> [[TMP0]]) #4
// CHECK: ret <8 x i8> [[VCNT_V_I]]
@@ -2419,7 +2225,7 @@ poly8x8_t test_vcreate_p8(uint64_t a) {
return vcnt_p8(vcreate_p8(a));
}
-// CHECK-LABEL: define <4 x i16> @test_vcreate_p16(i64 %a) #0 {
+// CHECK-LABEL: @test_vcreate_p16(
// CHECK: [[TMP0:%.*]] = bitcast i64 %a to <4 x i16>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[TMP0]] to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> [[TMP0]] to <8 x i8>
@@ -2432,7 +2238,7 @@ poly16x4_t test_vcreate_p16(uint64_t a) {
return vbsl_p16(tmp, tmp, tmp);
}
-// CHECK-LABEL: define <1 x i64> @test_vcreate_s64(i64 %a) #0 {
+// CHECK-LABEL: @test_vcreate_s64(
// CHECK: [[TMP0:%.*]] = bitcast i64 %a to <1 x i64>
// CHECK: [[ADD_I:%.*]] = add <1 x i64> [[TMP0]], [[TMP0]]
// CHECK: ret <1 x i64> [[ADD_I]]
@@ -2441,11 +2247,9 @@ int64x1_t test_vcreate_s64(uint64_t a) {
return vadd_s64(tmp, tmp);
}
-
-// CHECK-LABEL: define <4 x half> @test_vcvt_f16_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vcvt_f16_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[VCVT_F16_F32_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VCVT_F16_F321_I:%.*]] = call <4 x i16> @llvm.arm.neon.vcvtfp2hf(<4 x float> [[VCVT_F16_F32_I]]) #4
+// CHECK: [[VCVT_F16_F321_I:%.*]] = call <4 x i16> @llvm.arm.neon.vcvtfp2hf(<4 x float> %a) #4
// CHECK: [[VCVT_F16_F322_I:%.*]] = bitcast <4 x i16> [[VCVT_F16_F321_I]] to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[VCVT_F16_F322_I]] to <4 x half>
// CHECK: ret <4 x half> [[TMP1]]
@@ -2453,57 +2257,49 @@ float16x4_t test_vcvt_f16_f32(float32x4_t a) {
return vcvt_f16_f32(a);
}
-
-// CHECK-LABEL: define <2 x float> @test_vcvt_f32_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vcvt_f32_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VCVT_I:%.*]] = sitofp <2 x i32> [[TMP1]] to <2 x float>
+// CHECK: [[VCVT_I:%.*]] = sitofp <2 x i32> %a to <2 x float>
// CHECK: ret <2 x float> [[VCVT_I]]
float32x2_t test_vcvt_f32_s32(int32x2_t a) {
return vcvt_f32_s32(a);
}
-// CHECK-LABEL: define <2 x float> @test_vcvt_f32_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vcvt_f32_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VCVT_I:%.*]] = uitofp <2 x i32> [[TMP1]] to <2 x float>
+// CHECK: [[VCVT_I:%.*]] = uitofp <2 x i32> %a to <2 x float>
// CHECK: ret <2 x float> [[VCVT_I]]
float32x2_t test_vcvt_f32_u32(uint32x2_t a) {
return vcvt_f32_u32(a);
}
-// CHECK-LABEL: define <4 x float> @test_vcvtq_f32_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vcvtq_f32_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VCVT_I:%.*]] = sitofp <4 x i32> [[TMP1]] to <4 x float>
+// CHECK: [[VCVT_I:%.*]] = sitofp <4 x i32> %a to <4 x float>
// CHECK: ret <4 x float> [[VCVT_I]]
float32x4_t test_vcvtq_f32_s32(int32x4_t a) {
return vcvtq_f32_s32(a);
}
-// CHECK-LABEL: define <4 x float> @test_vcvtq_f32_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vcvtq_f32_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VCVT_I:%.*]] = uitofp <4 x i32> [[TMP1]] to <4 x float>
+// CHECK: [[VCVT_I:%.*]] = uitofp <4 x i32> %a to <4 x float>
// CHECK: ret <4 x float> [[VCVT_I]]
float32x4_t test_vcvtq_f32_u32(uint32x4_t a) {
return vcvtq_f32_u32(a);
}
-
-// CHECK-LABEL: define <4 x float> @test_vcvt_f32_f16(<4 x half> %a) #0 {
+// CHECK-LABEL: @test_vcvt_f32_f16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x half> %a to <8 x i8>
// CHECK: [[VCVT_F32_F16_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
// CHECK: [[VCVT_F32_F161_I:%.*]] = call <4 x float> @llvm.arm.neon.vcvthf2fp(<4 x i16> [[VCVT_F32_F16_I]]) #4
// CHECK: [[VCVT_F32_F162_I:%.*]] = bitcast <4 x float> [[VCVT_F32_F161_I]] to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[VCVT_F32_F162_I]] to <4 x float>
-// CHECK: ret <4 x float> [[TMP1]]
+// CHECK: ret <4 x float> [[VCVT_F32_F161_I]]
float32x4_t test_vcvt_f32_f16(float16x4_t a) {
return vcvt_f32_f16(a);
}
-
-// CHECK-LABEL: define <2 x float> @test_vcvt_n_f32_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vcvt_n_f32_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[VCVT_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
// CHECK: [[VCVT_N1:%.*]] = call <2 x float> @llvm.arm.neon.vcvtfxs2fp.v2f32.v2i32(<2 x i32> [[VCVT_N]], i32 1)
@@ -2512,7 +2308,7 @@ float32x2_t test_vcvt_n_f32_s32(int32x2_t a) {
return vcvt_n_f32_s32(a, 1);
}
-// CHECK-LABEL: define <2 x float> @test_vcvt_n_f32_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vcvt_n_f32_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[VCVT_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
// CHECK: [[VCVT_N1:%.*]] = call <2 x float> @llvm.arm.neon.vcvtfxu2fp.v2f32.v2i32(<2 x i32> [[VCVT_N]], i32 1)
@@ -2521,7 +2317,7 @@ float32x2_t test_vcvt_n_f32_u32(uint32x2_t a) {
return vcvt_n_f32_u32(a, 1);
}
-// CHECK-LABEL: define <4 x float> @test_vcvtq_n_f32_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vcvtq_n_f32_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[VCVT_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VCVT_N1:%.*]] = call <4 x float> @llvm.arm.neon.vcvtfxs2fp.v4f32.v4i32(<4 x i32> [[VCVT_N]], i32 3)
@@ -2530,7 +2326,7 @@ float32x4_t test_vcvtq_n_f32_s32(int32x4_t a) {
return vcvtq_n_f32_s32(a, 3);
}
-// CHECK-LABEL: define <4 x float> @test_vcvtq_n_f32_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vcvtq_n_f32_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[VCVT_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VCVT_N1:%.*]] = call <4 x float> @llvm.arm.neon.vcvtfxu2fp.v4f32.v4i32(<4 x i32> [[VCVT_N]], i32 3)
@@ -2539,8 +2335,7 @@ float32x4_t test_vcvtq_n_f32_u32(uint32x4_t a) {
return vcvtq_n_f32_u32(a, 3);
}
-
-// CHECK-LABEL: define <2 x i32> @test_vcvt_n_s32_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vcvt_n_s32_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[VCVT_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
// CHECK: [[VCVT_N1:%.*]] = call <2 x i32> @llvm.arm.neon.vcvtfp2fxs.v2i32.v2f32(<2 x float> [[VCVT_N]], i32 1)
@@ -2549,7 +2344,7 @@ int32x2_t test_vcvt_n_s32_f32(float32x2_t a) {
return vcvt_n_s32_f32(a, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vcvtq_n_s32_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vcvtq_n_s32_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[VCVT_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
// CHECK: [[VCVT_N1:%.*]] = call <4 x i32> @llvm.arm.neon.vcvtfp2fxs.v4i32.v4f32(<4 x float> [[VCVT_N]], i32 3)
@@ -2558,8 +2353,7 @@ int32x4_t test_vcvtq_n_s32_f32(float32x4_t a) {
return vcvtq_n_s32_f32(a, 3);
}
-
-// CHECK-LABEL: define <2 x i32> @test_vcvt_n_u32_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vcvt_n_u32_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[VCVT_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
// CHECK: [[VCVT_N1:%.*]] = call <2 x i32> @llvm.arm.neon.vcvtfp2fxu.v2i32.v2f32(<2 x float> [[VCVT_N]], i32 1)
@@ -2568,7 +2362,7 @@ uint32x2_t test_vcvt_n_u32_f32(float32x2_t a) {
return vcvt_n_u32_f32(a, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vcvtq_n_u32_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vcvtq_n_u32_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[VCVT_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
// CHECK: [[VCVT_N1:%.*]] = call <4 x i32> @llvm.arm.neon.vcvtfp2fxu.v4i32.v4f32(<4 x float> [[VCVT_N]], i32 3)
@@ -2577,201 +2371,193 @@ uint32x4_t test_vcvtq_n_u32_f32(float32x4_t a) {
return vcvtq_n_u32_f32(a, 3);
}
-
-// CHECK-LABEL: define <2 x i32> @test_vcvt_s32_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vcvt_s32_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VCVT_I:%.*]] = fptosi <2 x float> [[TMP1]] to <2 x i32>
+// CHECK: [[VCVT_I:%.*]] = fptosi <2 x float> %a to <2 x i32>
// CHECK: ret <2 x i32> [[VCVT_I]]
int32x2_t test_vcvt_s32_f32(float32x2_t a) {
return vcvt_s32_f32(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vcvtq_s32_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vcvtq_s32_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VCVT_I:%.*]] = fptosi <4 x float> [[TMP1]] to <4 x i32>
+// CHECK: [[VCVT_I:%.*]] = fptosi <4 x float> %a to <4 x i32>
// CHECK: ret <4 x i32> [[VCVT_I]]
int32x4_t test_vcvtq_s32_f32(float32x4_t a) {
return vcvtq_s32_f32(a);
}
-
-// CHECK-LABEL: define <2 x i32> @test_vcvt_u32_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vcvt_u32_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VCVT_I:%.*]] = fptoui <2 x float> [[TMP1]] to <2 x i32>
+// CHECK: [[VCVT_I:%.*]] = fptoui <2 x float> %a to <2 x i32>
// CHECK: ret <2 x i32> [[VCVT_I]]
uint32x2_t test_vcvt_u32_f32(float32x2_t a) {
return vcvt_u32_f32(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vcvtq_u32_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vcvtq_u32_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VCVT_I:%.*]] = fptoui <4 x float> [[TMP1]] to <4 x i32>
+// CHECK: [[VCVT_I:%.*]] = fptoui <4 x float> %a to <4 x i32>
// CHECK: ret <4 x i32> [[VCVT_I]]
uint32x4_t test_vcvtq_u32_f32(float32x4_t a) {
return vcvtq_u32_f32(a);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vdup_lane_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vdup_lane_u8(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %a, <8 x i32> <i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7>
// CHECK: ret <8 x i8> [[SHUFFLE]]
uint8x8_t test_vdup_lane_u8(uint8x8_t a) {
return vdup_lane_u8(a, 7);
}
-// CHECK-LABEL: define <4 x i16> @test_vdup_lane_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vdup_lane_u16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %a, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: ret <4 x i16> [[SHUFFLE]]
uint16x4_t test_vdup_lane_u16(uint16x4_t a) {
return vdup_lane_u16(a, 3);
}
-// CHECK-LABEL: define <2 x i32> @test_vdup_lane_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vdup_lane_u32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %a, <2 x i32> <i32 1, i32 1>
// CHECK: ret <2 x i32> [[SHUFFLE]]
uint32x2_t test_vdup_lane_u32(uint32x2_t a) {
return vdup_lane_u32(a, 1);
}
-// CHECK-LABEL: define <8 x i8> @test_vdup_lane_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vdup_lane_s8(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %a, <8 x i32> <i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7>
// CHECK: ret <8 x i8> [[SHUFFLE]]
int8x8_t test_vdup_lane_s8(int8x8_t a) {
return vdup_lane_s8(a, 7);
}
-// CHECK-LABEL: define <4 x i16> @test_vdup_lane_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vdup_lane_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %a, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: ret <4 x i16> [[SHUFFLE]]
int16x4_t test_vdup_lane_s16(int16x4_t a) {
return vdup_lane_s16(a, 3);
}
-// CHECK-LABEL: define <2 x i32> @test_vdup_lane_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vdup_lane_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %a, <2 x i32> <i32 1, i32 1>
// CHECK: ret <2 x i32> [[SHUFFLE]]
int32x2_t test_vdup_lane_s32(int32x2_t a) {
return vdup_lane_s32(a, 1);
}
-// CHECK-LABEL: define <8 x i8> @test_vdup_lane_p8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vdup_lane_p8(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %a, <8 x i32> <i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7>
// CHECK: ret <8 x i8> [[SHUFFLE]]
poly8x8_t test_vdup_lane_p8(poly8x8_t a) {
return vdup_lane_p8(a, 7);
}
-// CHECK-LABEL: define <4 x i16> @test_vdup_lane_p16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vdup_lane_p16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %a, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: ret <4 x i16> [[SHUFFLE]]
poly16x4_t test_vdup_lane_p16(poly16x4_t a) {
return vdup_lane_p16(a, 3);
}
-// CHECK-LABEL: define <2 x float> @test_vdup_lane_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vdup_lane_f32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x float> %a, <2 x float> %a, <2 x i32> <i32 1, i32 1>
// CHECK: ret <2 x float> [[SHUFFLE]]
float32x2_t test_vdup_lane_f32(float32x2_t a) {
return vdup_lane_f32(a, 1);
}
-// CHECK-LABEL: define <16 x i8> @test_vdupq_lane_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vdupq_lane_u8(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %a, <16 x i32> <i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7>
// CHECK: ret <16 x i8> [[SHUFFLE]]
uint8x16_t test_vdupq_lane_u8(uint8x8_t a) {
return vdupq_lane_u8(a, 7);
}
-// CHECK-LABEL: define <8 x i16> @test_vdupq_lane_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vdupq_lane_u16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %a, <8 x i32> <i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3>
// CHECK: ret <8 x i16> [[SHUFFLE]]
uint16x8_t test_vdupq_lane_u16(uint16x4_t a) {
return vdupq_lane_u16(a, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vdupq_lane_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vdupq_lane_u32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %a, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
// CHECK: ret <4 x i32> [[SHUFFLE]]
uint32x4_t test_vdupq_lane_u32(uint32x2_t a) {
return vdupq_lane_u32(a, 1);
}
-// CHECK-LABEL: define <16 x i8> @test_vdupq_lane_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vdupq_lane_s8(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %a, <16 x i32> <i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7>
// CHECK: ret <16 x i8> [[SHUFFLE]]
int8x16_t test_vdupq_lane_s8(int8x8_t a) {
return vdupq_lane_s8(a, 7);
}
-// CHECK-LABEL: define <8 x i16> @test_vdupq_lane_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vdupq_lane_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %a, <8 x i32> <i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3>
// CHECK: ret <8 x i16> [[SHUFFLE]]
int16x8_t test_vdupq_lane_s16(int16x4_t a) {
return vdupq_lane_s16(a, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vdupq_lane_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vdupq_lane_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %a, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
// CHECK: ret <4 x i32> [[SHUFFLE]]
int32x4_t test_vdupq_lane_s32(int32x2_t a) {
return vdupq_lane_s32(a, 1);
}
-// CHECK-LABEL: define <16 x i8> @test_vdupq_lane_p8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vdupq_lane_p8(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %a, <16 x i32> <i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7>
// CHECK: ret <16 x i8> [[SHUFFLE]]
poly8x16_t test_vdupq_lane_p8(poly8x8_t a) {
return vdupq_lane_p8(a, 7);
}
-// CHECK-LABEL: define <8 x i16> @test_vdupq_lane_p16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vdupq_lane_p16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %a, <8 x i32> <i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3>
// CHECK: ret <8 x i16> [[SHUFFLE]]
poly16x8_t test_vdupq_lane_p16(poly16x4_t a) {
return vdupq_lane_p16(a, 3);
}
-// CHECK-LABEL: define <4 x float> @test_vdupq_lane_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vdupq_lane_f32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x float> %a, <2 x float> %a, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
// CHECK: ret <4 x float> [[SHUFFLE]]
float32x4_t test_vdupq_lane_f32(float32x2_t a) {
return vdupq_lane_f32(a, 1);
}
-// CHECK-LABEL: define <1 x i64> @test_vdup_lane_s64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vdup_lane_s64(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <1 x i64> %a, <1 x i64> %a, <1 x i32> zeroinitializer
// CHECK: ret <1 x i64> [[SHUFFLE]]
int64x1_t test_vdup_lane_s64(int64x1_t a) {
return vdup_lane_s64(a, 0);
}
-// CHECK-LABEL: define <1 x i64> @test_vdup_lane_u64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vdup_lane_u64(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <1 x i64> %a, <1 x i64> %a, <1 x i32> zeroinitializer
// CHECK: ret <1 x i64> [[SHUFFLE]]
uint64x1_t test_vdup_lane_u64(uint64x1_t a) {
return vdup_lane_u64(a, 0);
}
-// CHECK-LABEL: define <2 x i64> @test_vdupq_lane_s64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vdupq_lane_s64(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <1 x i64> %a, <1 x i64> %a, <2 x i32> zeroinitializer
// CHECK: ret <2 x i64> [[SHUFFLE]]
int64x2_t test_vdupq_lane_s64(int64x1_t a) {
return vdupq_lane_s64(a, 0);
}
-// CHECK-LABEL: define <2 x i64> @test_vdupq_lane_u64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vdupq_lane_u64(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <1 x i64> %a, <1 x i64> %a, <2 x i32> zeroinitializer
// CHECK: ret <2 x i64> [[SHUFFLE]]
uint64x2_t test_vdupq_lane_u64(uint64x1_t a) {
return vdupq_lane_u64(a, 0);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vdup_n_u8(i8 zeroext %a) #0 {
+// CHECK-LABEL: @test_vdup_n_u8(
// CHECK: [[VECINIT_I:%.*]] = insertelement <8 x i8> undef, i8 %a, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <8 x i8> [[VECINIT_I]], i8 %a, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <8 x i8> [[VECINIT1_I]], i8 %a, i32 2
@@ -2785,7 +2571,7 @@ uint8x8_t test_vdup_n_u8(uint8_t a) {
return vdup_n_u8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vdup_n_u16(i16 zeroext %a) #0 {
+// CHECK-LABEL: @test_vdup_n_u16(
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i16> undef, i16 %a, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i16> [[VECINIT_I]], i16 %a, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i16> [[VECINIT1_I]], i16 %a, i32 2
@@ -2795,7 +2581,7 @@ uint16x4_t test_vdup_n_u16(uint16_t a) {
return vdup_n_u16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vdup_n_u32(i32 %a) #0 {
+// CHECK-LABEL: @test_vdup_n_u32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x i32> undef, i32 %a, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x i32> [[VECINIT_I]], i32 %a, i32 1
// CHECK: ret <2 x i32> [[VECINIT1_I]]
@@ -2803,7 +2589,7 @@ uint32x2_t test_vdup_n_u32(uint32_t a) {
return vdup_n_u32(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vdup_n_s8(i8 signext %a) #0 {
+// CHECK-LABEL: @test_vdup_n_s8(
// CHECK: [[VECINIT_I:%.*]] = insertelement <8 x i8> undef, i8 %a, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <8 x i8> [[VECINIT_I]], i8 %a, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <8 x i8> [[VECINIT1_I]], i8 %a, i32 2
@@ -2817,7 +2603,7 @@ int8x8_t test_vdup_n_s8(int8_t a) {
return vdup_n_s8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vdup_n_s16(i16 signext %a) #0 {
+// CHECK-LABEL: @test_vdup_n_s16(
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i16> undef, i16 %a, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i16> [[VECINIT_I]], i16 %a, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i16> [[VECINIT1_I]], i16 %a, i32 2
@@ -2827,7 +2613,7 @@ int16x4_t test_vdup_n_s16(int16_t a) {
return vdup_n_s16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vdup_n_s32(i32 %a) #0 {
+// CHECK-LABEL: @test_vdup_n_s32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x i32> undef, i32 %a, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x i32> [[VECINIT_I]], i32 %a, i32 1
// CHECK: ret <2 x i32> [[VECINIT1_I]]
@@ -2835,7 +2621,7 @@ int32x2_t test_vdup_n_s32(int32_t a) {
return vdup_n_s32(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vdup_n_p8(i8 signext %a) #0 {
+// CHECK-LABEL: @test_vdup_n_p8(
// CHECK: [[VECINIT_I:%.*]] = insertelement <8 x i8> undef, i8 %a, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <8 x i8> [[VECINIT_I]], i8 %a, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <8 x i8> [[VECINIT1_I]], i8 %a, i32 2
@@ -2849,7 +2635,7 @@ poly8x8_t test_vdup_n_p8(poly8_t a) {
return vdup_n_p8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vdup_n_p16(i16 signext %a) #0 {
+// CHECK-LABEL: @test_vdup_n_p16(
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i16> undef, i16 %a, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i16> [[VECINIT_I]], i16 %a, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i16> [[VECINIT1_I]], i16 %a, i32 2
@@ -2859,7 +2645,7 @@ poly16x4_t test_vdup_n_p16(poly16_t a) {
return vdup_n_p16(a);
}
-// CHECK-LABEL: define <4 x half> @test_vdup_n_f16(half* %a) #0 {
+// CHECK-LABEL: @test_vdup_n_f16(
// CHECK: [[TMP0:%.*]] = load half, half* %a, align 2
// CHECK: [[VECINIT:%.*]] = insertelement <4 x half> undef, half [[TMP0]], i32 0
// CHECK: [[VECINIT1:%.*]] = insertelement <4 x half> [[VECINIT]], half [[TMP0]], i32 1
@@ -2870,7 +2656,7 @@ float16x4_t test_vdup_n_f16(float16_t *a) {
return vdup_n_f16(*a);
}
-// CHECK-LABEL: define <2 x float> @test_vdup_n_f32(float %a) #0 {
+// CHECK-LABEL: @test_vdup_n_f32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x float> undef, float %a, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x float> [[VECINIT_I]], float %a, i32 1
// CHECK: ret <2 x float> [[VECINIT1_I]]
@@ -2878,7 +2664,7 @@ float32x2_t test_vdup_n_f32(float32_t a) {
return vdup_n_f32(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vdupq_n_u8(i8 zeroext %a) #0 {
+// CHECK-LABEL: @test_vdupq_n_u8(
// CHECK: [[VECINIT_I:%.*]] = insertelement <16 x i8> undef, i8 %a, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <16 x i8> [[VECINIT_I]], i8 %a, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <16 x i8> [[VECINIT1_I]], i8 %a, i32 2
@@ -2900,7 +2686,7 @@ uint8x16_t test_vdupq_n_u8(uint8_t a) {
return vdupq_n_u8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vdupq_n_u16(i16 zeroext %a) #0 {
+// CHECK-LABEL: @test_vdupq_n_u16(
// CHECK: [[VECINIT_I:%.*]] = insertelement <8 x i16> undef, i16 %a, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <8 x i16> [[VECINIT_I]], i16 %a, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <8 x i16> [[VECINIT1_I]], i16 %a, i32 2
@@ -2914,7 +2700,7 @@ uint16x8_t test_vdupq_n_u16(uint16_t a) {
return vdupq_n_u16(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vdupq_n_u32(i32 %a) #0 {
+// CHECK-LABEL: @test_vdupq_n_u32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i32> undef, i32 %a, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i32> [[VECINIT_I]], i32 %a, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i32> [[VECINIT1_I]], i32 %a, i32 2
@@ -2924,7 +2710,7 @@ uint32x4_t test_vdupq_n_u32(uint32_t a) {
return vdupq_n_u32(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vdupq_n_s8(i8 signext %a) #0 {
+// CHECK-LABEL: @test_vdupq_n_s8(
// CHECK: [[VECINIT_I:%.*]] = insertelement <16 x i8> undef, i8 %a, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <16 x i8> [[VECINIT_I]], i8 %a, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <16 x i8> [[VECINIT1_I]], i8 %a, i32 2
@@ -2946,7 +2732,7 @@ int8x16_t test_vdupq_n_s8(int8_t a) {
return vdupq_n_s8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vdupq_n_s16(i16 signext %a) #0 {
+// CHECK-LABEL: @test_vdupq_n_s16(
// CHECK: [[VECINIT_I:%.*]] = insertelement <8 x i16> undef, i16 %a, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <8 x i16> [[VECINIT_I]], i16 %a, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <8 x i16> [[VECINIT1_I]], i16 %a, i32 2
@@ -2960,7 +2746,7 @@ int16x8_t test_vdupq_n_s16(int16_t a) {
return vdupq_n_s16(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vdupq_n_s32(i32 %a) #0 {
+// CHECK-LABEL: @test_vdupq_n_s32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i32> undef, i32 %a, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i32> [[VECINIT_I]], i32 %a, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i32> [[VECINIT1_I]], i32 %a, i32 2
@@ -2970,7 +2756,7 @@ int32x4_t test_vdupq_n_s32(int32_t a) {
return vdupq_n_s32(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vdupq_n_p8(i8 signext %a) #0 {
+// CHECK-LABEL: @test_vdupq_n_p8(
// CHECK: [[VECINIT_I:%.*]] = insertelement <16 x i8> undef, i8 %a, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <16 x i8> [[VECINIT_I]], i8 %a, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <16 x i8> [[VECINIT1_I]], i8 %a, i32 2
@@ -2992,7 +2778,7 @@ poly8x16_t test_vdupq_n_p8(poly8_t a) {
return vdupq_n_p8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vdupq_n_p16(i16 signext %a) #0 {
+// CHECK-LABEL: @test_vdupq_n_p16(
// CHECK: [[VECINIT_I:%.*]] = insertelement <8 x i16> undef, i16 %a, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <8 x i16> [[VECINIT_I]], i16 %a, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <8 x i16> [[VECINIT1_I]], i16 %a, i32 2
@@ -3006,7 +2792,7 @@ poly16x8_t test_vdupq_n_p16(poly16_t a) {
return vdupq_n_p16(a);
}
-// CHECK-LABEL: define <8 x half> @test_vdupq_n_f16(half* %a) #0 {
+// CHECK-LABEL: @test_vdupq_n_f16(
// CHECK: [[TMP0:%.*]] = load half, half* %a, align 2
// CHECK: [[VECINIT:%.*]] = insertelement <8 x half> undef, half [[TMP0]], i32 0
// CHECK: [[VECINIT1:%.*]] = insertelement <8 x half> [[VECINIT]], half [[TMP0]], i32 1
@@ -3021,7 +2807,7 @@ float16x8_t test_vdupq_n_f16(float16_t *a) {
return vdupq_n_f16(*a);
}
-// CHECK-LABEL: define <4 x float> @test_vdupq_n_f32(float %a) #0 {
+// CHECK-LABEL: @test_vdupq_n_f32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x float> undef, float %a, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x float> [[VECINIT_I]], float %a, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x float> [[VECINIT1_I]], float %a, i32 2
@@ -3031,7 +2817,7 @@ float32x4_t test_vdupq_n_f32(float32_t a) {
return vdupq_n_f32(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vdup_n_s64(i64 %a) #0 {
+// CHECK-LABEL: @test_vdup_n_s64(
// CHECK: [[VECINIT_I:%.*]] = insertelement <1 x i64> undef, i64 %a, i32 0
// CHECK: [[ADD_I:%.*]] = add <1 x i64> [[VECINIT_I]], [[VECINIT_I]]
// CHECK: ret <1 x i64> [[ADD_I]]
@@ -3040,17 +2826,16 @@ int64x1_t test_vdup_n_s64(int64_t a) {
return vadd_s64(tmp, tmp);
}
-// CHECK-LABEL: define <1 x i64> @test_vdup_n_u64(i64 %a) #0 {
+// CHECK-LABEL: @test_vdup_n_u64(
// CHECK: [[VECINIT_I:%.*]] = insertelement <1 x i64> undef, i64 %a, i32 0
// CHECK: [[ADD_I:%.*]] = add <1 x i64> [[VECINIT_I]], [[VECINIT_I]]
// CHECK: ret <1 x i64> [[ADD_I]]
uint64x1_t test_vdup_n_u64(uint64_t a) {
int64x1_t tmp = vdup_n_u64(a);
return vadd_s64(tmp, tmp);
-
}
-// CHECK-LABEL: define <2 x i64> @test_vdupq_n_s64(i64 %a) #0 {
+// CHECK-LABEL: @test_vdupq_n_s64(
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x i64> undef, i64 %a, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x i64> [[VECINIT_I]], i64 %a, i32 1
// CHECK: [[ADD_I:%.*]] = add <2 x i64> [[VECINIT1_I]], [[VECINIT1_I]]
@@ -3060,7 +2845,7 @@ int64x2_t test_vdupq_n_s64(int64_t a) {
return vaddq_s64(tmp, tmp);
}
-// CHECK-LABEL: define <2 x i64> @test_vdupq_n_u64(i64 %a) #0 {
+// CHECK-LABEL: @test_vdupq_n_u64(
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x i64> undef, i64 %a, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x i64> [[VECINIT_I]], i64 %a, i32 1
// CHECK: [[ADD_I:%.*]] = add <2 x i64> [[VECINIT1_I]], [[VECINIT1_I]]
@@ -3070,142 +2855,140 @@ uint64x2_t test_vdupq_n_u64(uint64_t a) {
return vaddq_u64(tmp, tmp);
}
-
-// CHECK-LABEL: define <8 x i8> @test_veor_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_veor_s8(
// CHECK: [[XOR_I:%.*]] = xor <8 x i8> %a, %b
// CHECK: ret <8 x i8> [[XOR_I]]
int8x8_t test_veor_s8(int8x8_t a, int8x8_t b) {
return veor_s8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_veor_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_veor_s16(
// CHECK: [[XOR_I:%.*]] = xor <4 x i16> %a, %b
// CHECK: ret <4 x i16> [[XOR_I]]
int16x4_t test_veor_s16(int16x4_t a, int16x4_t b) {
return veor_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_veor_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_veor_s32(
// CHECK: [[XOR_I:%.*]] = xor <2 x i32> %a, %b
// CHECK: ret <2 x i32> [[XOR_I]]
int32x2_t test_veor_s32(int32x2_t a, int32x2_t b) {
return veor_s32(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_veor_s64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_veor_s64(
// CHECK: [[XOR_I:%.*]] = xor <1 x i64> %a, %b
// CHECK: ret <1 x i64> [[XOR_I]]
int64x1_t test_veor_s64(int64x1_t a, int64x1_t b) {
return veor_s64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_veor_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_veor_u8(
// CHECK: [[XOR_I:%.*]] = xor <8 x i8> %a, %b
// CHECK: ret <8 x i8> [[XOR_I]]
uint8x8_t test_veor_u8(uint8x8_t a, uint8x8_t b) {
return veor_u8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_veor_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_veor_u16(
// CHECK: [[XOR_I:%.*]] = xor <4 x i16> %a, %b
// CHECK: ret <4 x i16> [[XOR_I]]
uint16x4_t test_veor_u16(uint16x4_t a, uint16x4_t b) {
return veor_u16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_veor_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_veor_u32(
// CHECK: [[XOR_I:%.*]] = xor <2 x i32> %a, %b
// CHECK: ret <2 x i32> [[XOR_I]]
uint32x2_t test_veor_u32(uint32x2_t a, uint32x2_t b) {
return veor_u32(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_veor_u64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_veor_u64(
// CHECK: [[XOR_I:%.*]] = xor <1 x i64> %a, %b
// CHECK: ret <1 x i64> [[XOR_I]]
uint64x1_t test_veor_u64(uint64x1_t a, uint64x1_t b) {
return veor_u64(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_veorq_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_veorq_s8(
// CHECK: [[XOR_I:%.*]] = xor <16 x i8> %a, %b
// CHECK: ret <16 x i8> [[XOR_I]]
int8x16_t test_veorq_s8(int8x16_t a, int8x16_t b) {
return veorq_s8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_veorq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_veorq_s16(
// CHECK: [[XOR_I:%.*]] = xor <8 x i16> %a, %b
// CHECK: ret <8 x i16> [[XOR_I]]
int16x8_t test_veorq_s16(int16x8_t a, int16x8_t b) {
return veorq_s16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_veorq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_veorq_s32(
// CHECK: [[XOR_I:%.*]] = xor <4 x i32> %a, %b
// CHECK: ret <4 x i32> [[XOR_I]]
int32x4_t test_veorq_s32(int32x4_t a, int32x4_t b) {
return veorq_s32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_veorq_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_veorq_s64(
// CHECK: [[XOR_I:%.*]] = xor <2 x i64> %a, %b
// CHECK: ret <2 x i64> [[XOR_I]]
int64x2_t test_veorq_s64(int64x2_t a, int64x2_t b) {
return veorq_s64(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_veorq_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_veorq_u8(
// CHECK: [[XOR_I:%.*]] = xor <16 x i8> %a, %b
// CHECK: ret <16 x i8> [[XOR_I]]
uint8x16_t test_veorq_u8(uint8x16_t a, uint8x16_t b) {
return veorq_u8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_veorq_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_veorq_u16(
// CHECK: [[XOR_I:%.*]] = xor <8 x i16> %a, %b
// CHECK: ret <8 x i16> [[XOR_I]]
uint16x8_t test_veorq_u16(uint16x8_t a, uint16x8_t b) {
return veorq_u16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_veorq_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_veorq_u32(
// CHECK: [[XOR_I:%.*]] = xor <4 x i32> %a, %b
// CHECK: ret <4 x i32> [[XOR_I]]
uint32x4_t test_veorq_u32(uint32x4_t a, uint32x4_t b) {
return veorq_u32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_veorq_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_veorq_u64(
// CHECK: [[XOR_I:%.*]] = xor <2 x i64> %a, %b
// CHECK: ret <2 x i64> [[XOR_I]]
uint64x2_t test_veorq_u64(uint64x2_t a, uint64x2_t b) {
return veorq_u64(a, b);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vext_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vext_s8(
// CHECK: [[VEXT:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14>
// CHECK: ret <8 x i8> [[VEXT]]
int8x8_t test_vext_s8(int8x8_t a, int8x8_t b) {
return vext_s8(a, b, 7);
}
-// CHECK-LABEL: define <8 x i8> @test_vext_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vext_u8(
// CHECK: [[VEXT:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14>
// CHECK: ret <8 x i8> [[VEXT]]
uint8x8_t test_vext_u8(uint8x8_t a, uint8x8_t b) {
return vext_u8(a, b, 7);
}
-// CHECK-LABEL: define <8 x i8> @test_vext_p8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vext_p8(
// CHECK: [[VEXT:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %b, <8 x i32> <i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14>
// CHECK: ret <8 x i8> [[VEXT]]
poly8x8_t test_vext_p8(poly8x8_t a, poly8x8_t b) {
return vext_p8(a, b, 7);
}
-// CHECK-LABEL: define <4 x i16> @test_vext_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vext_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
@@ -3216,7 +2999,7 @@ int16x4_t test_vext_s16(int16x4_t a, int16x4_t b) {
return vext_s16(a, b, 3);
}
-// CHECK-LABEL: define <4 x i16> @test_vext_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vext_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
@@ -3227,7 +3010,7 @@ uint16x4_t test_vext_u16(uint16x4_t a, uint16x4_t b) {
return vext_u16(a, b, 3);
}
-// CHECK-LABEL: define <4 x i16> @test_vext_p16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vext_p16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
@@ -3238,7 +3021,7 @@ poly16x4_t test_vext_p16(poly16x4_t a, poly16x4_t b) {
return vext_p16(a, b, 3);
}
-// CHECK-LABEL: define <2 x i32> @test_vext_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vext_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
@@ -3249,7 +3032,7 @@ int32x2_t test_vext_s32(int32x2_t a, int32x2_t b) {
return vext_s32(a, b, 1);
}
-// CHECK-LABEL: define <2 x i32> @test_vext_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vext_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
@@ -3260,7 +3043,7 @@ uint32x2_t test_vext_u32(uint32x2_t a, uint32x2_t b) {
return vext_u32(a, b, 1);
}
-// CHECK-LABEL: define <1 x i64> @test_vext_s64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vext_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
@@ -3271,7 +3054,7 @@ int64x1_t test_vext_s64(int64x1_t a, int64x1_t b) {
return vext_s64(a, b, 0);
}
-// CHECK-LABEL: define <1 x i64> @test_vext_u64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vext_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
@@ -3282,7 +3065,7 @@ uint64x1_t test_vext_u64(uint64x1_t a, uint64x1_t b) {
return vext_u64(a, b, 0);
}
-// CHECK-LABEL: define <2 x float> @test_vext_f32(<2 x float> %a, <2 x float> %b) #0 {
+// CHECK-LABEL: @test_vext_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
@@ -3293,28 +3076,28 @@ float32x2_t test_vext_f32(float32x2_t a, float32x2_t b) {
return vext_f32(a, b, 1);
}
-// CHECK-LABEL: define <16 x i8> @test_vextq_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vextq_s8(
// CHECK: [[VEXT:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <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>
// CHECK: ret <16 x i8> [[VEXT]]
int8x16_t test_vextq_s8(int8x16_t a, int8x16_t b) {
return vextq_s8(a, b, 15);
}
-// CHECK-LABEL: define <16 x i8> @test_vextq_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vextq_u8(
// CHECK: [[VEXT:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <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>
// CHECK: ret <16 x i8> [[VEXT]]
uint8x16_t test_vextq_u8(uint8x16_t a, uint8x16_t b) {
return vextq_u8(a, b, 15);
}
-// CHECK-LABEL: define <16 x i8> @test_vextq_p8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vextq_p8(
// CHECK: [[VEXT:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %b, <16 x i32> <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>
// CHECK: ret <16 x i8> [[VEXT]]
poly8x16_t test_vextq_p8(poly8x16_t a, poly8x16_t b) {
return vextq_p8(a, b, 15);
}
-// CHECK-LABEL: define <8 x i16> @test_vextq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vextq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
@@ -3325,7 +3108,7 @@ int16x8_t test_vextq_s16(int16x8_t a, int16x8_t b) {
return vextq_s16(a, b, 7);
}
-// CHECK-LABEL: define <8 x i16> @test_vextq_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vextq_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
@@ -3336,7 +3119,7 @@ uint16x8_t test_vextq_u16(uint16x8_t a, uint16x8_t b) {
return vextq_u16(a, b, 7);
}
-// CHECK-LABEL: define <8 x i16> @test_vextq_p16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vextq_p16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
@@ -3347,7 +3130,7 @@ poly16x8_t test_vextq_p16(poly16x8_t a, poly16x8_t b) {
return vextq_p16(a, b, 7);
}
-// CHECK-LABEL: define <4 x i32> @test_vextq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vextq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
@@ -3358,7 +3141,7 @@ int32x4_t test_vextq_s32(int32x4_t a, int32x4_t b) {
return vextq_s32(a, b, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vextq_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vextq_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
@@ -3369,7 +3152,7 @@ uint32x4_t test_vextq_u32(uint32x4_t a, uint32x4_t b) {
return vextq_u32(a, b, 3);
}
-// CHECK-LABEL: define <2 x i64> @test_vextq_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vextq_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
@@ -3380,7 +3163,7 @@ int64x2_t test_vextq_s64(int64x2_t a, int64x2_t b) {
return vextq_s64(a, b, 1);
}
-// CHECK-LABEL: define <2 x i64> @test_vextq_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vextq_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
@@ -3391,7 +3174,7 @@ uint64x2_t test_vextq_u64(uint64x2_t a, uint64x2_t b) {
return vextq_u64(a, b, 1);
}
-// CHECK-LABEL: define <4 x float> @test_vextq_f32(<4 x float> %a, <4 x float> %b) #0 {
+// CHECK-LABEL: @test_vextq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
@@ -3402,155 +3185,140 @@ float32x4_t test_vextq_f32(float32x4_t a, float32x4_t b) {
return vextq_f32(a, b, 3);
}
-
-// CHECK-LABEL: define <2 x float> @test_vfma_f32(<2 x float> %a, <2 x float> %b, <2 x float> %c) #0 {
+// CHECK-LABEL: @test_vfma_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x float> %c to <8 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK: [[TMP5:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x float>
-// CHECK: [[TMP6:%.*]] = call <2 x float> @llvm.fma.v2f32(<2 x float> [[TMP4]], <2 x float> [[TMP5]], <2 x float> [[TMP3]]) #4
-// CHECK: ret <2 x float> [[TMP6]]
+// CHECK: [[TMP3:%.*]] = call <2 x float> @llvm.fma.v2f32(<2 x float> %b, <2 x float> %c, <2 x float> %a) #4
+// CHECK: ret <2 x float> [[TMP3]]
float32x2_t test_vfma_f32(float32x2_t a, float32x2_t b, float32x2_t c) {
return vfma_f32(a, b, c);
}
-// CHECK-LABEL: define <4 x float> @test_vfmaq_f32(<4 x float> %a, <4 x float> %b, <4 x float> %c) #0 {
+// CHECK-LABEL: @test_vfmaq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x float> %c to <16 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <4 x float>
-// CHECK: [[TMP6:%.*]] = call <4 x float> @llvm.fma.v4f32(<4 x float> [[TMP4]], <4 x float> [[TMP5]], <4 x float> [[TMP3]]) #4
-// CHECK: ret <4 x float> [[TMP6]]
+// CHECK: [[TMP3:%.*]] = call <4 x float> @llvm.fma.v4f32(<4 x float> %b, <4 x float> %c, <4 x float> %a) #4
+// CHECK: ret <4 x float> [[TMP3]]
float32x4_t test_vfmaq_f32(float32x4_t a, float32x4_t b, float32x4_t c) {
return vfmaq_f32(a, b, c);
}
-// CHECK-LABEL: define <2 x float> @test_vfms_f32(<2 x float> %a, <2 x float> %b, <2 x float> %c) #0 {
+// CHECK-LABEL: @test_vfms_f32(
// CHECK: [[SUB_I:%.*]] = fsub <2 x float> <float -0.000000e+00, float -0.000000e+00>, %b
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> [[SUB_I]] to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x float> %c to <8 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK: [[TMP5:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x float>
-// CHECK: [[TMP6:%.*]] = call <2 x float> @llvm.fma.v2f32(<2 x float> [[TMP4]], <2 x float> [[TMP5]], <2 x float> [[TMP3]]) #4
-// CHECK: ret <2 x float> [[TMP6]]
+// CHECK: [[TMP3:%.*]] = call <2 x float> @llvm.fma.v2f32(<2 x float> [[SUB_I]], <2 x float> %c, <2 x float> %a) #4
+// CHECK: ret <2 x float> [[TMP3]]
float32x2_t test_vfms_f32(float32x2_t a, float32x2_t b, float32x2_t c) {
return vfms_f32(a, b, c);
}
-// CHECK-LABEL: define <4 x float> @test_vfmsq_f32(<4 x float> %a, <4 x float> %b, <4 x float> %c) #0 {
+// CHECK-LABEL: @test_vfmsq_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: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> [[SUB_I]] to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x float> %c to <16 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <4 x float>
-// CHECK: [[TMP6:%.*]] = call <4 x float> @llvm.fma.v4f32(<4 x float> [[TMP4]], <4 x float> [[TMP5]], <4 x float> [[TMP3]]) #4
-// CHECK: ret <4 x float> [[TMP6]]
+// CHECK: [[TMP3:%.*]] = call <4 x float> @llvm.fma.v4f32(<4 x float> [[SUB_I]], <4 x float> %c, <4 x float> %a) #4
+// CHECK: ret <4 x float> [[TMP3]]
float32x4_t test_vfmsq_f32(float32x4_t a, float32x4_t b, float32x4_t c) {
return vfmsq_f32(a, b, c);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vget_high_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vget_high_s8(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %a, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: ret <8 x i8> [[SHUFFLE_I]]
int8x8_t test_vget_high_s8(int8x16_t a) {
return vget_high_s8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vget_high_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vget_high_s16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %a, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: ret <4 x i16> [[SHUFFLE_I]]
int16x4_t test_vget_high_s16(int16x8_t a) {
return vget_high_s16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vget_high_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vget_high_s32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %a, <2 x i32> <i32 2, i32 3>
// CHECK: ret <2 x i32> [[SHUFFLE_I]]
int32x2_t test_vget_high_s32(int32x4_t a) {
return vget_high_s32(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vget_high_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vget_high_s64(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x i64> %a, <2 x i64> %a, <1 x i32> <i32 1>
// CHECK: ret <1 x i64> [[SHUFFLE_I]]
int64x1_t test_vget_high_s64(int64x2_t a) {
return vget_high_s64(a);
}
-// CHECK-LABEL: define <4 x half> @test_vget_high_f16(<8 x half> %a) #0 {
+// CHECK-LABEL: @test_vget_high_f16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x half> %a, <8 x half> %a, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: ret <4 x half> [[SHUFFLE_I]]
float16x4_t test_vget_high_f16(float16x8_t a) {
return vget_high_f16(a);
}
-// CHECK-LABEL: define <2 x float> @test_vget_high_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vget_high_f32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x float> %a, <4 x float> %a, <2 x i32> <i32 2, i32 3>
// CHECK: ret <2 x float> [[SHUFFLE_I]]
float32x2_t test_vget_high_f32(float32x4_t a) {
return vget_high_f32(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vget_high_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vget_high_u8(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %a, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: ret <8 x i8> [[SHUFFLE_I]]
uint8x8_t test_vget_high_u8(uint8x16_t a) {
return vget_high_u8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vget_high_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vget_high_u16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %a, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: ret <4 x i16> [[SHUFFLE_I]]
uint16x4_t test_vget_high_u16(uint16x8_t a) {
return vget_high_u16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vget_high_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vget_high_u32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %a, <2 x i32> <i32 2, i32 3>
// CHECK: ret <2 x i32> [[SHUFFLE_I]]
uint32x2_t test_vget_high_u32(uint32x4_t a) {
return vget_high_u32(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vget_high_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vget_high_u64(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x i64> %a, <2 x i64> %a, <1 x i32> <i32 1>
// CHECK: ret <1 x i64> [[SHUFFLE_I]]
uint64x1_t test_vget_high_u64(uint64x2_t a) {
return vget_high_u64(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vget_high_p8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vget_high_p8(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %a, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
// CHECK: ret <8 x i8> [[SHUFFLE_I]]
poly8x8_t test_vget_high_p8(poly8x16_t a) {
return vget_high_p8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vget_high_p16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vget_high_p16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %a, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// CHECK: ret <4 x i16> [[SHUFFLE_I]]
poly16x4_t test_vget_high_p16(poly16x8_t a) {
return vget_high_p16(a);
}
-
-// CHECK-LABEL: define zeroext i8 @test_vget_lane_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vget_lane_u8(
// CHECK: [[VGET_LANE:%.*]] = extractelement <8 x i8> %a, i32 7
// CHECK: ret i8 [[VGET_LANE]]
uint8_t test_vget_lane_u8(uint8x8_t a) {
return vget_lane_u8(a, 7);
}
-// CHECK-LABEL: define zeroext i16 @test_vget_lane_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vget_lane_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
// CHECK: [[VGET_LANE:%.*]] = extractelement <4 x i16> [[TMP1]], i32 3
@@ -3559,7 +3327,7 @@ uint16_t test_vget_lane_u16(uint16x4_t a) {
return vget_lane_u16(a, 3);
}
-// CHECK-LABEL: define i32 @test_vget_lane_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vget_lane_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
// CHECK: [[VGET_LANE:%.*]] = extractelement <2 x i32> [[TMP1]], i32 1
@@ -3568,14 +3336,14 @@ uint32_t test_vget_lane_u32(uint32x2_t a) {
return vget_lane_u32(a, 1);
}
-// CHECK-LABEL: define signext i8 @test_vget_lane_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vget_lane_s8(
// CHECK: [[VGET_LANE:%.*]] = extractelement <8 x i8> %a, i32 7
// CHECK: ret i8 [[VGET_LANE]]
int8_t test_vget_lane_s8(int8x8_t a) {
return vget_lane_s8(a, 7);
}
-// CHECK-LABEL: define signext i16 @test_vget_lane_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vget_lane_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
// CHECK: [[VGET_LANE:%.*]] = extractelement <4 x i16> [[TMP1]], i32 3
@@ -3584,7 +3352,7 @@ int16_t test_vget_lane_s16(int16x4_t a) {
return vget_lane_s16(a, 3);
}
-// CHECK-LABEL: define i32 @test_vget_lane_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vget_lane_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
// CHECK: [[VGET_LANE:%.*]] = extractelement <2 x i32> [[TMP1]], i32 1
@@ -3593,14 +3361,14 @@ int32_t test_vget_lane_s32(int32x2_t a) {
return vget_lane_s32(a, 1);
}
-// CHECK-LABEL: define signext i8 @test_vget_lane_p8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vget_lane_p8(
// CHECK: [[VGET_LANE:%.*]] = extractelement <8 x i8> %a, i32 7
// CHECK: ret i8 [[VGET_LANE]]
poly8_t test_vget_lane_p8(poly8x8_t a) {
return vget_lane_p8(a, 7);
}
-// CHECK-LABEL: define signext i16 @test_vget_lane_p16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vget_lane_p16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
// CHECK: [[VGET_LANE:%.*]] = extractelement <4 x i16> [[TMP1]], i32 3
@@ -3609,7 +3377,7 @@ poly16_t test_vget_lane_p16(poly16x4_t a) {
return vget_lane_p16(a, 3);
}
-// CHECK-LABEL: define float @test_vget_lane_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vget_lane_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
// CHECK: [[VGET_LANE:%.*]] = extractelement <2 x float> [[TMP1]], i32 1
@@ -3618,7 +3386,7 @@ float32_t test_vget_lane_f32(float32x2_t a) {
return vget_lane_f32(a, 1);
}
-// CHECK-LABEL: define float @test_vget_lane_f16(<4 x half> %a) #0 {
+// CHECK-LABEL: @test_vget_lane_f16(
// CHECK: [[__REINT_242:%.*]] = alloca <4 x half>, align 8
// CHECK: [[__REINT1_242:%.*]] = alloca i16, align 2
// CHECK: store <4 x half> %a, <4 x half>* [[__REINT_242]], align 8
@@ -3636,14 +3404,14 @@ float32_t test_vget_lane_f16(float16x4_t a) {
return vget_lane_f16(a, 1);
}
-// CHECK-LABEL: define zeroext i8 @test_vgetq_lane_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vgetq_lane_u8(
// CHECK: [[VGET_LANE:%.*]] = extractelement <16 x i8> %a, i32 15
// CHECK: ret i8 [[VGET_LANE]]
uint8_t test_vgetq_lane_u8(uint8x16_t a) {
return vgetq_lane_u8(a, 15);
}
-// CHECK-LABEL: define zeroext i16 @test_vgetq_lane_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vgetq_lane_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VGET_LANE:%.*]] = extractelement <8 x i16> [[TMP1]], i32 7
@@ -3652,7 +3420,7 @@ uint16_t test_vgetq_lane_u16(uint16x8_t a) {
return vgetq_lane_u16(a, 7);
}
-// CHECK-LABEL: define i32 @test_vgetq_lane_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vgetq_lane_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VGET_LANE:%.*]] = extractelement <4 x i32> [[TMP1]], i32 3
@@ -3661,14 +3429,14 @@ uint32_t test_vgetq_lane_u32(uint32x4_t a) {
return vgetq_lane_u32(a, 3);
}
-// CHECK-LABEL: define signext i8 @test_vgetq_lane_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vgetq_lane_s8(
// CHECK: [[VGET_LANE:%.*]] = extractelement <16 x i8> %a, i32 15
// CHECK: ret i8 [[VGET_LANE]]
int8_t test_vgetq_lane_s8(int8x16_t a) {
return vgetq_lane_s8(a, 15);
}
-// CHECK-LABEL: define signext i16 @test_vgetq_lane_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vgetq_lane_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VGET_LANE:%.*]] = extractelement <8 x i16> [[TMP1]], i32 7
@@ -3677,7 +3445,7 @@ int16_t test_vgetq_lane_s16(int16x8_t a) {
return vgetq_lane_s16(a, 7);
}
-// CHECK-LABEL: define i32 @test_vgetq_lane_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vgetq_lane_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VGET_LANE:%.*]] = extractelement <4 x i32> [[TMP1]], i32 3
@@ -3686,14 +3454,14 @@ int32_t test_vgetq_lane_s32(int32x4_t a) {
return vgetq_lane_s32(a, 3);
}
-// CHECK-LABEL: define signext i8 @test_vgetq_lane_p8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vgetq_lane_p8(
// CHECK: [[VGET_LANE:%.*]] = extractelement <16 x i8> %a, i32 15
// CHECK: ret i8 [[VGET_LANE]]
poly8_t test_vgetq_lane_p8(poly8x16_t a) {
return vgetq_lane_p8(a, 15);
}
-// CHECK-LABEL: define signext i16 @test_vgetq_lane_p16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vgetq_lane_p16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VGET_LANE:%.*]] = extractelement <8 x i16> [[TMP1]], i32 7
@@ -3702,7 +3470,7 @@ poly16_t test_vgetq_lane_p16(poly16x8_t a) {
return vgetq_lane_p16(a, 7);
}
-// CHECK-LABEL: define float @test_vgetq_lane_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vgetq_lane_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
// CHECK: [[VGET_LANE:%.*]] = extractelement <4 x float> [[TMP1]], i32 3
@@ -3711,7 +3479,7 @@ float32_t test_vgetq_lane_f32(float32x4_t a) {
return vgetq_lane_f32(a, 3);
}
-// CHECK-LABEL: define float @test_vgetq_lane_f16(<8 x half> %a) #0 {
+// CHECK-LABEL: @test_vgetq_lane_f16(
// CHECK: [[__REINT_244:%.*]] = alloca <8 x half>, align 16
// CHECK: [[__REINT1_244:%.*]] = alloca i16, align 2
// CHECK: store <8 x half> %a, <8 x half>* [[__REINT_244]], align 16
@@ -3729,8 +3497,7 @@ float32_t test_vgetq_lane_f16(float16x8_t a) {
return vgetq_lane_f16(a, 3);
}
-// The optimizer is able to remove all moves now.
-// CHECK-LABEL: define i64 @test_vget_lane_s64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vget_lane_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
// CHECK: [[VGET_LANE:%.*]] = extractelement <1 x i64> [[TMP1]], i32 0
@@ -3739,8 +3506,7 @@ int64_t test_vget_lane_s64(int64x1_t a) {
return vget_lane_s64(a, 0);
}
-// The optimizer is able to remove all moves now.
-// CHECK-LABEL: define i64 @test_vget_lane_u64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vget_lane_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
// CHECK: [[VGET_LANE:%.*]] = extractelement <1 x i64> [[TMP1]], i32 0
@@ -3749,7 +3515,7 @@ uint64_t test_vget_lane_u64(uint64x1_t a) {
return vget_lane_u64(a, 0);
}
-// CHECK-LABEL: define i64 @test_vgetq_lane_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vgetq_lane_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VGET_LANE:%.*]] = extractelement <2 x i64> [[TMP1]], i32 1
@@ -3758,7 +3524,7 @@ int64_t test_vgetq_lane_s64(int64x2_t a) {
return vgetq_lane_s64(a, 1);
}
-// CHECK-LABEL: define i64 @test_vgetq_lane_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vgetq_lane_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VGET_LANE:%.*]] = extractelement <2 x i64> [[TMP1]], i32 1
@@ -3767,366 +3533,314 @@ uint64_t test_vgetq_lane_u64(uint64x2_t a) {
return vgetq_lane_u64(a, 1);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vget_low_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vget_low_s8(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %a, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
// CHECK: ret <8 x i8> [[SHUFFLE_I]]
int8x8_t test_vget_low_s8(int8x16_t a) {
return vget_low_s8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vget_low_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vget_low_s16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %a, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
// CHECK: ret <4 x i16> [[SHUFFLE_I]]
int16x4_t test_vget_low_s16(int16x8_t a) {
return vget_low_s16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vget_low_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vget_low_s32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %a, <2 x i32> <i32 0, i32 1>
// CHECK: ret <2 x i32> [[SHUFFLE_I]]
int32x2_t test_vget_low_s32(int32x4_t a) {
return vget_low_s32(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vget_low_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vget_low_s64(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x i64> %a, <2 x i64> %a, <1 x i32> zeroinitializer
// CHECK: ret <1 x i64> [[SHUFFLE_I]]
int64x1_t test_vget_low_s64(int64x2_t a) {
return vget_low_s64(a);
}
-// CHECK-LABEL: define <4 x half> @test_vget_low_f16(<8 x half> %a) #0 {
+// CHECK-LABEL: @test_vget_low_f16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x half> %a, <8 x half> %a, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
// CHECK: ret <4 x half> [[SHUFFLE_I]]
float16x4_t test_vget_low_f16(float16x8_t a) {
return vget_low_f16(a);
}
-// CHECK-LABEL: define <2 x float> @test_vget_low_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vget_low_f32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x float> %a, <4 x float> %a, <2 x i32> <i32 0, i32 1>
// CHECK: ret <2 x float> [[SHUFFLE_I]]
float32x2_t test_vget_low_f32(float32x4_t a) {
return vget_low_f32(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vget_low_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vget_low_u8(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %a, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
// CHECK: ret <8 x i8> [[SHUFFLE_I]]
uint8x8_t test_vget_low_u8(uint8x16_t a) {
return vget_low_u8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vget_low_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vget_low_u16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %a, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
// CHECK: ret <4 x i16> [[SHUFFLE_I]]
uint16x4_t test_vget_low_u16(uint16x8_t a) {
return vget_low_u16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vget_low_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vget_low_u32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %a, <2 x i32> <i32 0, i32 1>
// CHECK: ret <2 x i32> [[SHUFFLE_I]]
uint32x2_t test_vget_low_u32(uint32x4_t a) {
return vget_low_u32(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vget_low_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vget_low_u64(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x i64> %a, <2 x i64> %a, <1 x i32> zeroinitializer
// CHECK: ret <1 x i64> [[SHUFFLE_I]]
uint64x1_t test_vget_low_u64(uint64x2_t a) {
return vget_low_u64(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vget_low_p8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vget_low_p8(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %a, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
// CHECK: ret <8 x i8> [[SHUFFLE_I]]
poly8x8_t test_vget_low_p8(poly8x16_t a) {
return vget_low_p8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vget_low_p16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vget_low_p16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %a, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
// CHECK: ret <4 x i16> [[SHUFFLE_I]]
poly16x4_t test_vget_low_p16(poly16x8_t a) {
return vget_low_p16(a);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vhadd_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vhadd_s8(
// CHECK: [[VHADD_V_I:%.*]] = call <8 x i8> @llvm.arm.neon.vhadds.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VHADD_V_I]]
int8x8_t test_vhadd_s8(int8x8_t a, int8x8_t b) {
return vhadd_s8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vhadd_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vhadd_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VHADD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VHADD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VHADD_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vhadds.v4i16(<4 x i16> [[VHADD_V_I]], <4 x i16> [[VHADD_V1_I]]) #4
+// CHECK: [[VHADD_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vhadds.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VHADD_V3_I:%.*]] = bitcast <4 x i16> [[VHADD_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VHADD_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VHADD_V2_I]]
int16x4_t test_vhadd_s16(int16x4_t a, int16x4_t b) {
return vhadd_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vhadd_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vhadd_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VHADD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VHADD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VHADD_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vhadds.v2i32(<2 x i32> [[VHADD_V_I]], <2 x i32> [[VHADD_V1_I]]) #4
+// CHECK: [[VHADD_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vhadds.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VHADD_V3_I:%.*]] = bitcast <2 x i32> [[VHADD_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VHADD_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VHADD_V2_I]]
int32x2_t test_vhadd_s32(int32x2_t a, int32x2_t b) {
return vhadd_s32(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vhadd_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vhadd_u8(
// CHECK: [[VHADD_V_I:%.*]] = call <8 x i8> @llvm.arm.neon.vhaddu.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VHADD_V_I]]
uint8x8_t test_vhadd_u8(uint8x8_t a, uint8x8_t b) {
return vhadd_u8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vhadd_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vhadd_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VHADD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VHADD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VHADD_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vhaddu.v4i16(<4 x i16> [[VHADD_V_I]], <4 x i16> [[VHADD_V1_I]]) #4
+// CHECK: [[VHADD_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vhaddu.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VHADD_V3_I:%.*]] = bitcast <4 x i16> [[VHADD_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VHADD_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VHADD_V2_I]]
uint16x4_t test_vhadd_u16(uint16x4_t a, uint16x4_t b) {
return vhadd_u16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vhadd_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vhadd_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VHADD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VHADD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VHADD_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vhaddu.v2i32(<2 x i32> [[VHADD_V_I]], <2 x i32> [[VHADD_V1_I]]) #4
+// CHECK: [[VHADD_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vhaddu.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VHADD_V3_I:%.*]] = bitcast <2 x i32> [[VHADD_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VHADD_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VHADD_V2_I]]
uint32x2_t test_vhadd_u32(uint32x2_t a, uint32x2_t b) {
return vhadd_u32(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vhaddq_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vhaddq_s8(
// CHECK: [[VHADDQ_V_I:%.*]] = call <16 x i8> @llvm.arm.neon.vhadds.v16i8(<16 x i8> %a, <16 x i8> %b) #4
// CHECK: ret <16 x i8> [[VHADDQ_V_I]]
int8x16_t test_vhaddq_s8(int8x16_t a, int8x16_t b) {
return vhaddq_s8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vhaddq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vhaddq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VHADDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VHADDQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VHADDQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vhadds.v8i16(<8 x i16> [[VHADDQ_V_I]], <8 x i16> [[VHADDQ_V1_I]]) #4
+// CHECK: [[VHADDQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vhadds.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: [[VHADDQ_V3_I:%.*]] = bitcast <8 x i16> [[VHADDQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VHADDQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VHADDQ_V2_I]]
int16x8_t test_vhaddq_s16(int16x8_t a, int16x8_t b) {
return vhaddq_s16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vhaddq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vhaddq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VHADDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VHADDQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VHADDQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vhadds.v4i32(<4 x i32> [[VHADDQ_V_I]], <4 x i32> [[VHADDQ_V1_I]]) #4
+// CHECK: [[VHADDQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vhadds.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VHADDQ_V3_I:%.*]] = bitcast <4 x i32> [[VHADDQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VHADDQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VHADDQ_V2_I]]
int32x4_t test_vhaddq_s32(int32x4_t a, int32x4_t b) {
return vhaddq_s32(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vhaddq_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vhaddq_u8(
// CHECK: [[VHADDQ_V_I:%.*]] = call <16 x i8> @llvm.arm.neon.vhaddu.v16i8(<16 x i8> %a, <16 x i8> %b) #4
// CHECK: ret <16 x i8> [[VHADDQ_V_I]]
uint8x16_t test_vhaddq_u8(uint8x16_t a, uint8x16_t b) {
return vhaddq_u8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vhaddq_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vhaddq_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VHADDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VHADDQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VHADDQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vhaddu.v8i16(<8 x i16> [[VHADDQ_V_I]], <8 x i16> [[VHADDQ_V1_I]]) #4
+// CHECK: [[VHADDQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vhaddu.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: [[VHADDQ_V3_I:%.*]] = bitcast <8 x i16> [[VHADDQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VHADDQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VHADDQ_V2_I]]
uint16x8_t test_vhaddq_u16(uint16x8_t a, uint16x8_t b) {
return vhaddq_u16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vhaddq_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vhaddq_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VHADDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VHADDQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VHADDQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vhaddu.v4i32(<4 x i32> [[VHADDQ_V_I]], <4 x i32> [[VHADDQ_V1_I]]) #4
+// CHECK: [[VHADDQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vhaddu.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VHADDQ_V3_I:%.*]] = bitcast <4 x i32> [[VHADDQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VHADDQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VHADDQ_V2_I]]
uint32x4_t test_vhaddq_u32(uint32x4_t a, uint32x4_t b) {
return vhaddq_u32(a, b);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vhsub_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vhsub_s8(
// CHECK: [[VHSUB_V_I:%.*]] = call <8 x i8> @llvm.arm.neon.vhsubs.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VHSUB_V_I]]
int8x8_t test_vhsub_s8(int8x8_t a, int8x8_t b) {
return vhsub_s8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vhsub_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vhsub_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VHSUB_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VHSUB_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VHSUB_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vhsubs.v4i16(<4 x i16> [[VHSUB_V_I]], <4 x i16> [[VHSUB_V1_I]]) #4
+// CHECK: [[VHSUB_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vhsubs.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VHSUB_V3_I:%.*]] = bitcast <4 x i16> [[VHSUB_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VHSUB_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VHSUB_V2_I]]
int16x4_t test_vhsub_s16(int16x4_t a, int16x4_t b) {
return vhsub_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vhsub_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vhsub_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VHSUB_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VHSUB_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VHSUB_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vhsubs.v2i32(<2 x i32> [[VHSUB_V_I]], <2 x i32> [[VHSUB_V1_I]]) #4
+// CHECK: [[VHSUB_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vhsubs.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VHSUB_V3_I:%.*]] = bitcast <2 x i32> [[VHSUB_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VHSUB_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VHSUB_V2_I]]
int32x2_t test_vhsub_s32(int32x2_t a, int32x2_t b) {
return vhsub_s32(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vhsub_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vhsub_u8(
// CHECK: [[VHSUB_V_I:%.*]] = call <8 x i8> @llvm.arm.neon.vhsubu.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VHSUB_V_I]]
uint8x8_t test_vhsub_u8(uint8x8_t a, uint8x8_t b) {
return vhsub_u8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vhsub_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vhsub_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VHSUB_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VHSUB_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VHSUB_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vhsubu.v4i16(<4 x i16> [[VHSUB_V_I]], <4 x i16> [[VHSUB_V1_I]]) #4
+// CHECK: [[VHSUB_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vhsubu.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VHSUB_V3_I:%.*]] = bitcast <4 x i16> [[VHSUB_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VHSUB_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VHSUB_V2_I]]
uint16x4_t test_vhsub_u16(uint16x4_t a, uint16x4_t b) {
return vhsub_u16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vhsub_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vhsub_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VHSUB_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VHSUB_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VHSUB_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vhsubu.v2i32(<2 x i32> [[VHSUB_V_I]], <2 x i32> [[VHSUB_V1_I]]) #4
+// CHECK: [[VHSUB_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vhsubu.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VHSUB_V3_I:%.*]] = bitcast <2 x i32> [[VHSUB_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VHSUB_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VHSUB_V2_I]]
uint32x2_t test_vhsub_u32(uint32x2_t a, uint32x2_t b) {
return vhsub_u32(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vhsubq_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vhsubq_s8(
// CHECK: [[VHSUBQ_V_I:%.*]] = call <16 x i8> @llvm.arm.neon.vhsubs.v16i8(<16 x i8> %a, <16 x i8> %b) #4
// CHECK: ret <16 x i8> [[VHSUBQ_V_I]]
int8x16_t test_vhsubq_s8(int8x16_t a, int8x16_t b) {
return vhsubq_s8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vhsubq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vhsubq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VHSUBQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VHSUBQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VHSUBQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vhsubs.v8i16(<8 x i16> [[VHSUBQ_V_I]], <8 x i16> [[VHSUBQ_V1_I]]) #4
+// CHECK: [[VHSUBQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vhsubs.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: [[VHSUBQ_V3_I:%.*]] = bitcast <8 x i16> [[VHSUBQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VHSUBQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VHSUBQ_V2_I]]
int16x8_t test_vhsubq_s16(int16x8_t a, int16x8_t b) {
return vhsubq_s16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vhsubq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vhsubq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VHSUBQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VHSUBQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VHSUBQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vhsubs.v4i32(<4 x i32> [[VHSUBQ_V_I]], <4 x i32> [[VHSUBQ_V1_I]]) #4
+// CHECK: [[VHSUBQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vhsubs.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VHSUBQ_V3_I:%.*]] = bitcast <4 x i32> [[VHSUBQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VHSUBQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VHSUBQ_V2_I]]
int32x4_t test_vhsubq_s32(int32x4_t a, int32x4_t b) {
return vhsubq_s32(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vhsubq_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vhsubq_u8(
// CHECK: [[VHSUBQ_V_I:%.*]] = call <16 x i8> @llvm.arm.neon.vhsubu.v16i8(<16 x i8> %a, <16 x i8> %b) #4
// CHECK: ret <16 x i8> [[VHSUBQ_V_I]]
uint8x16_t test_vhsubq_u8(uint8x16_t a, uint8x16_t b) {
return vhsubq_u8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vhsubq_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vhsubq_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VHSUBQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VHSUBQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VHSUBQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vhsubu.v8i16(<8 x i16> [[VHSUBQ_V_I]], <8 x i16> [[VHSUBQ_V1_I]]) #4
+// CHECK: [[VHSUBQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vhsubu.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: [[VHSUBQ_V3_I:%.*]] = bitcast <8 x i16> [[VHSUBQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VHSUBQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VHSUBQ_V2_I]]
uint16x8_t test_vhsubq_u16(uint16x8_t a, uint16x8_t b) {
return vhsubq_u16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vhsubq_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vhsubq_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VHSUBQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VHSUBQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VHSUBQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vhsubu.v4i32(<4 x i32> [[VHSUBQ_V_I]], <4 x i32> [[VHSUBQ_V1_I]]) #4
+// CHECK: [[VHSUBQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vhsubu.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VHSUBQ_V3_I:%.*]] = bitcast <4 x i32> [[VHSUBQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VHSUBQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VHSUBQ_V2_I]]
uint32x4_t test_vhsubq_u32(uint32x4_t a, uint32x4_t b) {
return vhsubq_u32(a, b);
}
-
-// CHECK-LABEL: define <16 x i8> @test_vld1q_u8(i8* %a) #0 {
+// CHECK-LABEL: @test_vld1q_u8(
// CHECK: [[VLD1:%.*]] = call <16 x i8> @llvm.arm.neon.vld1.v16i8.p0i8(i8* %a, i32 1)
// CHECK: ret <16 x i8> [[VLD1]]
uint8x16_t test_vld1q_u8(uint8_t const * a) {
return vld1q_u8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vld1q_u16(i16* %a) #0 {
+// CHECK-LABEL: @test_vld1q_u16(
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VLD1:%.*]] = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* [[TMP0]], i32 2)
// CHECK: ret <8 x i16> [[VLD1]]
@@ -4134,7 +3848,7 @@ uint16x8_t test_vld1q_u16(uint16_t const * a) {
return vld1q_u16(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vld1q_u32(i32* %a) #0 {
+// CHECK-LABEL: @test_vld1q_u32(
// CHECK: [[TMP0:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VLD1:%.*]] = call <4 x i32> @llvm.arm.neon.vld1.v4i32.p0i8(i8* [[TMP0]], i32 4)
// CHECK: ret <4 x i32> [[VLD1]]
@@ -4142,7 +3856,7 @@ uint32x4_t test_vld1q_u32(uint32_t const * a) {
return vld1q_u32(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vld1q_u64(i64* %a) #0 {
+// CHECK-LABEL: @test_vld1q_u64(
// CHECK: [[TMP0:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VLD1:%.*]] = call <2 x i64> @llvm.arm.neon.vld1.v2i64.p0i8(i8* [[TMP0]], i32 4)
// CHECK: ret <2 x i64> [[VLD1]]
@@ -4150,14 +3864,14 @@ uint64x2_t test_vld1q_u64(uint64_t const * a) {
return vld1q_u64(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vld1q_s8(i8* %a) #0 {
+// CHECK-LABEL: @test_vld1q_s8(
// CHECK: [[VLD1:%.*]] = call <16 x i8> @llvm.arm.neon.vld1.v16i8.p0i8(i8* %a, i32 1)
// CHECK: ret <16 x i8> [[VLD1]]
int8x16_t test_vld1q_s8(int8_t const * a) {
return vld1q_s8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vld1q_s16(i16* %a) #0 {
+// CHECK-LABEL: @test_vld1q_s16(
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VLD1:%.*]] = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* [[TMP0]], i32 2)
// CHECK: ret <8 x i16> [[VLD1]]
@@ -4165,7 +3879,7 @@ int16x8_t test_vld1q_s16(int16_t const * a) {
return vld1q_s16(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vld1q_s32(i32* %a) #0 {
+// CHECK-LABEL: @test_vld1q_s32(
// CHECK: [[TMP0:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VLD1:%.*]] = call <4 x i32> @llvm.arm.neon.vld1.v4i32.p0i8(i8* [[TMP0]], i32 4)
// CHECK: ret <4 x i32> [[VLD1]]
@@ -4173,7 +3887,7 @@ int32x4_t test_vld1q_s32(int32_t const * a) {
return vld1q_s32(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vld1q_s64(i64* %a) #0 {
+// CHECK-LABEL: @test_vld1q_s64(
// CHECK: [[TMP0:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VLD1:%.*]] = call <2 x i64> @llvm.arm.neon.vld1.v2i64.p0i8(i8* [[TMP0]], i32 4)
// CHECK: ret <2 x i64> [[VLD1]]
@@ -4181,7 +3895,7 @@ int64x2_t test_vld1q_s64(int64_t const * a) {
return vld1q_s64(a);
}
-// CHECK-LABEL: define <8 x half> @test_vld1q_f16(half* %a) #0 {
+// CHECK-LABEL: @test_vld1q_f16(
// CHECK: [[TMP0:%.*]] = bitcast half* %a to i8*
// CHECK: [[VLD1:%.*]] = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* [[TMP0]], i32 2)
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> [[VLD1]] to <8 x half>
@@ -4190,7 +3904,7 @@ float16x8_t test_vld1q_f16(float16_t const * a) {
return vld1q_f16(a);
}
-// CHECK-LABEL: define <4 x float> @test_vld1q_f32(float* %a) #0 {
+// CHECK-LABEL: @test_vld1q_f32(
// CHECK: [[TMP0:%.*]] = bitcast float* %a to i8*
// CHECK: [[VLD1:%.*]] = call <4 x float> @llvm.arm.neon.vld1.v4f32.p0i8(i8* [[TMP0]], i32 4)
// CHECK: ret <4 x float> [[VLD1]]
@@ -4198,14 +3912,14 @@ float32x4_t test_vld1q_f32(float32_t const * a) {
return vld1q_f32(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vld1q_p8(i8* %a) #0 {
+// CHECK-LABEL: @test_vld1q_p8(
// CHECK: [[VLD1:%.*]] = call <16 x i8> @llvm.arm.neon.vld1.v16i8.p0i8(i8* %a, i32 1)
// CHECK: ret <16 x i8> [[VLD1]]
poly8x16_t test_vld1q_p8(poly8_t const * a) {
return vld1q_p8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vld1q_p16(i16* %a) #0 {
+// CHECK-LABEL: @test_vld1q_p16(
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VLD1:%.*]] = call <8 x i16> @llvm.arm.neon.vld1.v8i16.p0i8(i8* [[TMP0]], i32 2)
// CHECK: ret <8 x i16> [[VLD1]]
@@ -4213,14 +3927,14 @@ poly16x8_t test_vld1q_p16(poly16_t const * a) {
return vld1q_p16(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vld1_u8(i8* %a) #0 {
+// CHECK-LABEL: @test_vld1_u8(
// CHECK: [[VLD1:%.*]] = call <8 x i8> @llvm.arm.neon.vld1.v8i8.p0i8(i8* %a, i32 1)
// CHECK: ret <8 x i8> [[VLD1]]
uint8x8_t test_vld1_u8(uint8_t const * a) {
return vld1_u8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vld1_u16(i16* %a) #0 {
+// CHECK-LABEL: @test_vld1_u16(
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VLD1:%.*]] = call <4 x i16> @llvm.arm.neon.vld1.v4i16.p0i8(i8* [[TMP0]], i32 2)
// CHECK: ret <4 x i16> [[VLD1]]
@@ -4228,7 +3942,7 @@ uint16x4_t test_vld1_u16(uint16_t const * a) {
return vld1_u16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vld1_u32(i32* %a) #0 {
+// CHECK-LABEL: @test_vld1_u32(
// CHECK: [[TMP0:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VLD1:%.*]] = call <2 x i32> @llvm.arm.neon.vld1.v2i32.p0i8(i8* [[TMP0]], i32 4)
// CHECK: ret <2 x i32> [[VLD1]]
@@ -4236,7 +3950,7 @@ uint32x2_t test_vld1_u32(uint32_t const * a) {
return vld1_u32(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vld1_u64(i64* %a) #0 {
+// CHECK-LABEL: @test_vld1_u64(
// CHECK: [[TMP0:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VLD1:%.*]] = call <1 x i64> @llvm.arm.neon.vld1.v1i64.p0i8(i8* [[TMP0]], i32 4)
// CHECK: ret <1 x i64> [[VLD1]]
@@ -4244,14 +3958,14 @@ uint64x1_t test_vld1_u64(uint64_t const * a) {
return vld1_u64(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vld1_s8(i8* %a) #0 {
+// CHECK-LABEL: @test_vld1_s8(
// CHECK: [[VLD1:%.*]] = call <8 x i8> @llvm.arm.neon.vld1.v8i8.p0i8(i8* %a, i32 1)
// CHECK: ret <8 x i8> [[VLD1]]
int8x8_t test_vld1_s8(int8_t const * a) {
return vld1_s8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vld1_s16(i16* %a) #0 {
+// CHECK-LABEL: @test_vld1_s16(
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VLD1:%.*]] = call <4 x i16> @llvm.arm.neon.vld1.v4i16.p0i8(i8* [[TMP0]], i32 2)
// CHECK: ret <4 x i16> [[VLD1]]
@@ -4259,7 +3973,7 @@ int16x4_t test_vld1_s16(int16_t const * a) {
return vld1_s16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vld1_s32(i32* %a) #0 {
+// CHECK-LABEL: @test_vld1_s32(
// CHECK: [[TMP0:%.*]] = bitcast i32* %a to i8*
// CHECK: [[VLD1:%.*]] = call <2 x i32> @llvm.arm.neon.vld1.v2i32.p0i8(i8* [[TMP0]], i32 4)
// CHECK: ret <2 x i32> [[VLD1]]
@@ -4267,7 +3981,7 @@ int32x2_t test_vld1_s32(int32_t const * a) {
return vld1_s32(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vld1_s64(i64* %a) #0 {
+// CHECK-LABEL: @test_vld1_s64(
// CHECK: [[TMP0:%.*]] = bitcast i64* %a to i8*
// CHECK: [[VLD1:%.*]] = call <1 x i64> @llvm.arm.neon.vld1.v1i64.p0i8(i8* [[TMP0]], i32 4)
// CHECK: ret <1 x i64> [[VLD1]]
@@ -4275,7 +3989,7 @@ int64x1_t test_vld1_s64(int64_t const * a) {
return vld1_s64(a);
}
-// CHECK-LABEL: define <4 x half> @test_vld1_f16(half* %a) #0 {
+// CHECK-LABEL: @test_vld1_f16(
// CHECK: [[TMP0:%.*]] = bitcast half* %a to i8*
// CHECK: [[VLD1:%.*]] = call <4 x i16> @llvm.arm.neon.vld1.v4i16.p0i8(i8* [[TMP0]], i32 2)
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[VLD1]] to <4 x half>
@@ -4284,7 +3998,7 @@ float16x4_t test_vld1_f16(float16_t const * a) {
return vld1_f16(a);
}
-// CHECK-LABEL: define <2 x float> @test_vld1_f32(float* %a) #0 {
+// CHECK-LABEL: @test_vld1_f32(
// CHECK: [[TMP0:%.*]] = bitcast float* %a to i8*
// CHECK: [[VLD1:%.*]] = call <2 x float> @llvm.arm.neon.vld1.v2f32.p0i8(i8* [[TMP0]], i32 4)
// CHECK: ret <2 x float> [[VLD1]]
@@ -4292,14 +4006,14 @@ float32x2_t test_vld1_f32(float32_t const * a) {
return vld1_f32(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vld1_p8(i8* %a) #0 {
+// CHECK-LABEL: @test_vld1_p8(
// CHECK: [[VLD1:%.*]] = call <8 x i8> @llvm.arm.neon.vld1.v8i8.p0i8(i8* %a, i32 1)
// CHECK: ret <8 x i8> [[VLD1]]
poly8x8_t test_vld1_p8(poly8_t const * a) {
return vld1_p8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vld1_p16(i16* %a) #0 {
+// CHECK-LABEL: @test_vld1_p16(
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[VLD1:%.*]] = call <4 x i16> @llvm.arm.neon.vld1.v4i16.p0i8(i8* [[TMP0]], i32 2)
// CHECK: ret <4 x i16> [[VLD1]]
@@ -4307,8 +4021,7 @@ poly16x4_t test_vld1_p16(poly16_t const * a) {
return vld1_p16(a);
}
-
-// CHECK-LABEL: define <16 x i8> @test_vld1q_dup_u8(i8* %a) #0 {
+// CHECK-LABEL: @test_vld1q_dup_u8(
// CHECK: [[TMP0:%.*]] = load i8, i8* %a, align 1
// CHECK: [[TMP1:%.*]] = insertelement <16 x i8> undef, i8 [[TMP0]], i32 0
// CHECK: [[LANE:%.*]] = shufflevector <16 x i8> [[TMP1]], <16 x i8> [[TMP1]], <16 x i32> zeroinitializer
@@ -4317,7 +4030,7 @@ uint8x16_t test_vld1q_dup_u8(uint8_t const * a) {
return vld1q_dup_u8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vld1q_dup_u16(i16* %a) #0 {
+// CHECK-LABEL: @test_vld1q_dup_u16(
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i16*
// CHECK: [[TMP2:%.*]] = load i16, i16* [[TMP1]], align 2
@@ -4328,7 +4041,7 @@ uint16x8_t test_vld1q_dup_u16(uint16_t const * a) {
return vld1q_dup_u16(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vld1q_dup_u32(i32* %a) #0 {
+// CHECK-LABEL: @test_vld1q_dup_u32(
// CHECK: [[TMP0:%.*]] = bitcast i32* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i32*
// CHECK: [[TMP2:%.*]] = load i32, i32* [[TMP1]], align 4
@@ -4339,7 +4052,7 @@ uint32x4_t test_vld1q_dup_u32(uint32_t const * a) {
return vld1q_dup_u32(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vld1q_dup_u64(i64* %a) #0 {
+// CHECK-LABEL: @test_vld1q_dup_u64(
// CHECK: [[TMP0:%.*]] = bitcast i64* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i64*
// CHECK: [[TMP2:%.*]] = load i64, i64* [[TMP1]], align 4
@@ -4350,7 +4063,7 @@ uint64x2_t test_vld1q_dup_u64(uint64_t const * a) {
return vld1q_dup_u64(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vld1q_dup_s8(i8* %a) #0 {
+// CHECK-LABEL: @test_vld1q_dup_s8(
// CHECK: [[TMP0:%.*]] = load i8, i8* %a, align 1
// CHECK: [[TMP1:%.*]] = insertelement <16 x i8> undef, i8 [[TMP0]], i32 0
// CHECK: [[LANE:%.*]] = shufflevector <16 x i8> [[TMP1]], <16 x i8> [[TMP1]], <16 x i32> zeroinitializer
@@ -4359,7 +4072,7 @@ int8x16_t test_vld1q_dup_s8(int8_t const * a) {
return vld1q_dup_s8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vld1q_dup_s16(i16* %a) #0 {
+// CHECK-LABEL: @test_vld1q_dup_s16(
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i16*
// CHECK: [[TMP2:%.*]] = load i16, i16* [[TMP1]], align 2
@@ -4370,7 +4083,7 @@ int16x8_t test_vld1q_dup_s16(int16_t const * a) {
return vld1q_dup_s16(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vld1q_dup_s32(i32* %a) #0 {
+// CHECK-LABEL: @test_vld1q_dup_s32(
// CHECK: [[TMP0:%.*]] = bitcast i32* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i32*
// CHECK: [[TMP2:%.*]] = load i32, i32* [[TMP1]], align 4
@@ -4381,7 +4094,7 @@ int32x4_t test_vld1q_dup_s32(int32_t const * a) {
return vld1q_dup_s32(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vld1q_dup_s64(i64* %a) #0 {
+// CHECK-LABEL: @test_vld1q_dup_s64(
// CHECK: [[TMP0:%.*]] = bitcast i64* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i64*
// CHECK: [[TMP2:%.*]] = load i64, i64* [[TMP1]], align 4
@@ -4392,7 +4105,7 @@ int64x2_t test_vld1q_dup_s64(int64_t const * a) {
return vld1q_dup_s64(a);
}
-// CHECK-LABEL: define <8 x half> @test_vld1q_dup_f16(half* %a) #0 {
+// CHECK-LABEL: @test_vld1q_dup_f16(
// CHECK: [[TMP0:%.*]] = bitcast half* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i16*
// CHECK: [[TMP2:%.*]] = load i16, i16* [[TMP1]], align 2
@@ -4404,7 +4117,7 @@ float16x8_t test_vld1q_dup_f16(float16_t const * a) {
return vld1q_dup_f16(a);
}
-// CHECK-LABEL: define <4 x float> @test_vld1q_dup_f32(float* %a) #0 {
+// CHECK-LABEL: @test_vld1q_dup_f32(
// CHECK: [[TMP0:%.*]] = bitcast float* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to float*
// CHECK: [[TMP2:%.*]] = load float, float* [[TMP1]], align 4
@@ -4415,7 +4128,7 @@ float32x4_t test_vld1q_dup_f32(float32_t const * a) {
return vld1q_dup_f32(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vld1q_dup_p8(i8* %a) #0 {
+// CHECK-LABEL: @test_vld1q_dup_p8(
// CHECK: [[TMP0:%.*]] = load i8, i8* %a, align 1
// CHECK: [[TMP1:%.*]] = insertelement <16 x i8> undef, i8 [[TMP0]], i32 0
// CHECK: [[LANE:%.*]] = shufflevector <16 x i8> [[TMP1]], <16 x i8> [[TMP1]], <16 x i32> zeroinitializer
@@ -4424,7 +4137,7 @@ poly8x16_t test_vld1q_dup_p8(poly8_t const * a) {
return vld1q_dup_p8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vld1q_dup_p16(i16* %a) #0 {
+// CHECK-LABEL: @test_vld1q_dup_p16(
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i16*
// CHECK: [[TMP2:%.*]] = load i16, i16* [[TMP1]], align 2
@@ -4435,7 +4148,7 @@ poly16x8_t test_vld1q_dup_p16(poly16_t const * a) {
return vld1q_dup_p16(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vld1_dup_u8(i8* %a) #0 {
+// CHECK-LABEL: @test_vld1_dup_u8(
// CHECK: [[TMP0:%.*]] = load i8, i8* %a, align 1
// CHECK: [[TMP1:%.*]] = insertelement <8 x i8> undef, i8 [[TMP0]], i32 0
// CHECK: [[LANE:%.*]] = shufflevector <8 x i8> [[TMP1]], <8 x i8> [[TMP1]], <8 x i32> zeroinitializer
@@ -4444,7 +4157,7 @@ uint8x8_t test_vld1_dup_u8(uint8_t const * a) {
return vld1_dup_u8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vld1_dup_u16(i16* %a) #0 {
+// CHECK-LABEL: @test_vld1_dup_u16(
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i16*
// CHECK: [[TMP2:%.*]] = load i16, i16* [[TMP1]], align 2
@@ -4455,7 +4168,7 @@ uint16x4_t test_vld1_dup_u16(uint16_t const * a) {
return vld1_dup_u16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vld1_dup_u32(i32* %a) #0 {
+// CHECK-LABEL: @test_vld1_dup_u32(
// CHECK: [[TMP0:%.*]] = bitcast i32* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i32*
// CHECK: [[TMP2:%.*]] = load i32, i32* [[TMP1]], align 4
@@ -4466,7 +4179,7 @@ uint32x2_t test_vld1_dup_u32(uint32_t const * a) {
return vld1_dup_u32(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vld1_dup_u64(i64* %a) #0 {
+// CHECK-LABEL: @test_vld1_dup_u64(
// CHECK: [[TMP0:%.*]] = bitcast i64* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i64*
// CHECK: [[TMP2:%.*]] = load i64, i64* [[TMP1]], align 4
@@ -4477,7 +4190,7 @@ uint64x1_t test_vld1_dup_u64(uint64_t const * a) {
return vld1_dup_u64(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vld1_dup_s8(i8* %a) #0 {
+// CHECK-LABEL: @test_vld1_dup_s8(
// CHECK: [[TMP0:%.*]] = load i8, i8* %a, align 1
// CHECK: [[TMP1:%.*]] = insertelement <8 x i8> undef, i8 [[TMP0]], i32 0
// CHECK: [[LANE:%.*]] = shufflevector <8 x i8> [[TMP1]], <8 x i8> [[TMP1]], <8 x i32> zeroinitializer
@@ -4486,7 +4199,7 @@ int8x8_t test_vld1_dup_s8(int8_t const * a) {
return vld1_dup_s8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vld1_dup_s16(i16* %a) #0 {
+// CHECK-LABEL: @test_vld1_dup_s16(
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i16*
// CHECK: [[TMP2:%.*]] = load i16, i16* [[TMP1]], align 2
@@ -4497,7 +4210,7 @@ int16x4_t test_vld1_dup_s16(int16_t const * a) {
return vld1_dup_s16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vld1_dup_s32(i32* %a) #0 {
+// CHECK-LABEL: @test_vld1_dup_s32(
// CHECK: [[TMP0:%.*]] = bitcast i32* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i32*
// CHECK: [[TMP2:%.*]] = load i32, i32* [[TMP1]], align 4
@@ -4508,7 +4221,7 @@ int32x2_t test_vld1_dup_s32(int32_t const * a) {
return vld1_dup_s32(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vld1_dup_s64(i64* %a) #0 {
+// CHECK-LABEL: @test_vld1_dup_s64(
// CHECK: [[TMP0:%.*]] = bitcast i64* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i64*
// CHECK: [[TMP2:%.*]] = load i64, i64* [[TMP1]], align 4
@@ -4519,7 +4232,7 @@ int64x1_t test_vld1_dup_s64(int64_t const * a) {
return vld1_dup_s64(a);
}
-// CHECK-LABEL: define <4 x half> @test_vld1_dup_f16(half* %a) #0 {
+// CHECK-LABEL: @test_vld1_dup_f16(
// CHECK: [[TMP0:%.*]] = bitcast half* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i16*
// CHECK: [[TMP2:%.*]] = load i16, i16* [[TMP1]], align 2
@@ -4531,7 +4244,7 @@ float16x4_t test_vld1_dup_f16(float16_t const * a) {
return vld1_dup_f16(a);
}
-// CHECK-LABEL: define <2 x float> @test_vld1_dup_f32(float* %a) #0 {
+// CHECK-LABEL: @test_vld1_dup_f32(
// CHECK: [[TMP0:%.*]] = bitcast float* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to float*
// CHECK: [[TMP2:%.*]] = load float, float* [[TMP1]], align 4
@@ -4542,7 +4255,7 @@ float32x2_t test_vld1_dup_f32(float32_t const * a) {
return vld1_dup_f32(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vld1_dup_p8(i8* %a) #0 {
+// CHECK-LABEL: @test_vld1_dup_p8(
// CHECK: [[TMP0:%.*]] = load i8, i8* %a, align 1
// CHECK: [[TMP1:%.*]] = insertelement <8 x i8> undef, i8 [[TMP0]], i32 0
// CHECK: [[LANE:%.*]] = shufflevector <8 x i8> [[TMP1]], <8 x i8> [[TMP1]], <8 x i32> zeroinitializer
@@ -4551,7 +4264,7 @@ poly8x8_t test_vld1_dup_p8(poly8_t const * a) {
return vld1_dup_p8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vld1_dup_p16(i16* %a) #0 {
+// CHECK-LABEL: @test_vld1_dup_p16(
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i16*
// CHECK: [[TMP2:%.*]] = load i16, i16* [[TMP1]], align 2
@@ -4562,8 +4275,7 @@ poly16x4_t test_vld1_dup_p16(poly16_t const * a) {
return vld1_dup_p16(a);
}
-
-// CHECK-LABEL: define <16 x i8> @test_vld1q_lane_u8(i8* %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vld1q_lane_u8(
// CHECK: [[TMP0:%.*]] = load i8, i8* %a, align 1
// CHECK: [[VLD1_LANE:%.*]] = insertelement <16 x i8> %b, i8 [[TMP0]], i32 15
// CHECK: ret <16 x i8> [[VLD1_LANE]]
@@ -4571,7 +4283,7 @@ uint8x16_t test_vld1q_lane_u8(uint8_t const * a, uint8x16_t b) {
return vld1q_lane_u8(a, b, 15);
}
-// CHECK-LABEL: define <8 x i16> @test_vld1q_lane_u16(i16* %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vld1q_lane_u16(
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
@@ -4583,7 +4295,7 @@ uint16x8_t test_vld1q_lane_u16(uint16_t const * a, uint16x8_t b) {
return vld1q_lane_u16(a, b, 7);
}
-// CHECK-LABEL: define <4 x i32> @test_vld1q_lane_u32(i32* %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vld1q_lane_u32(
// CHECK: [[TMP0:%.*]] = bitcast i32* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
@@ -4595,7 +4307,7 @@ uint32x4_t test_vld1q_lane_u32(uint32_t const * a, uint32x4_t b) {
return vld1q_lane_u32(a, b, 3);
}
-// CHECK-LABEL: define <2 x i64> @test_vld1q_lane_u64(i64* %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vld1q_lane_u64(
// CHECK: [[TMP0:%.*]] = bitcast i64* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
@@ -4607,7 +4319,7 @@ uint64x2_t test_vld1q_lane_u64(uint64_t const * a, uint64x2_t b) {
return vld1q_lane_u64(a, b, 1);
}
-// CHECK-LABEL: define <16 x i8> @test_vld1q_lane_s8(i8* %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vld1q_lane_s8(
// CHECK: [[TMP0:%.*]] = load i8, i8* %a, align 1
// CHECK: [[VLD1_LANE:%.*]] = insertelement <16 x i8> %b, i8 [[TMP0]], i32 15
// CHECK: ret <16 x i8> [[VLD1_LANE]]
@@ -4615,7 +4327,7 @@ int8x16_t test_vld1q_lane_s8(int8_t const * a, int8x16_t b) {
return vld1q_lane_s8(a, b, 15);
}
-// CHECK-LABEL: define <8 x i16> @test_vld1q_lane_s16(i16* %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vld1q_lane_s16(
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
@@ -4627,7 +4339,7 @@ int16x8_t test_vld1q_lane_s16(int16_t const * a, int16x8_t b) {
return vld1q_lane_s16(a, b, 7);
}
-// CHECK-LABEL: define <4 x i32> @test_vld1q_lane_s32(i32* %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vld1q_lane_s32(
// CHECK: [[TMP0:%.*]] = bitcast i32* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
@@ -4639,7 +4351,7 @@ int32x4_t test_vld1q_lane_s32(int32_t const * a, int32x4_t b) {
return vld1q_lane_s32(a, b, 3);
}
-// CHECK-LABEL: define <2 x i64> @test_vld1q_lane_s64(i64* %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vld1q_lane_s64(
// CHECK: [[TMP0:%.*]] = bitcast i64* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
@@ -4651,7 +4363,7 @@ int64x2_t test_vld1q_lane_s64(int64_t const * a, int64x2_t b) {
return vld1q_lane_s64(a, b, 1);
}
-// CHECK-LABEL: define <8 x half> @test_vld1q_lane_f16(half* %a, <8 x half> %b) #0 {
+// CHECK-LABEL: @test_vld1q_lane_f16(
// CHECK: [[TMP0:%.*]] = bitcast half* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <8 x half> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
@@ -4664,7 +4376,7 @@ float16x8_t test_vld1q_lane_f16(float16_t const * a, float16x8_t b) {
return vld1q_lane_f16(a, b, 7);
}
-// CHECK-LABEL: define <4 x float> @test_vld1q_lane_f32(float* %a, <4 x float> %b) #0 {
+// CHECK-LABEL: @test_vld1q_lane_f32(
// CHECK: [[TMP0:%.*]] = bitcast float* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
@@ -4676,7 +4388,7 @@ float32x4_t test_vld1q_lane_f32(float32_t const * a, float32x4_t b) {
return vld1q_lane_f32(a, b, 3);
}
-// CHECK-LABEL: define <16 x i8> @test_vld1q_lane_p8(i8* %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vld1q_lane_p8(
// CHECK: [[TMP0:%.*]] = load i8, i8* %a, align 1
// CHECK: [[VLD1_LANE:%.*]] = insertelement <16 x i8> %b, i8 [[TMP0]], i32 15
// CHECK: ret <16 x i8> [[VLD1_LANE]]
@@ -4684,7 +4396,7 @@ poly8x16_t test_vld1q_lane_p8(poly8_t const * a, poly8x16_t b) {
return vld1q_lane_p8(a, b, 15);
}
-// CHECK-LABEL: define <8 x i16> @test_vld1q_lane_p16(i16* %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vld1q_lane_p16(
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
@@ -4696,7 +4408,7 @@ poly16x8_t test_vld1q_lane_p16(poly16_t const * a, poly16x8_t b) {
return vld1q_lane_p16(a, b, 7);
}
-// CHECK-LABEL: define <8 x i8> @test_vld1_lane_u8(i8* %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vld1_lane_u8(
// CHECK: [[TMP0:%.*]] = load i8, i8* %a, align 1
// CHECK: [[VLD1_LANE:%.*]] = insertelement <8 x i8> %b, i8 [[TMP0]], i32 7
// CHECK: ret <8 x i8> [[VLD1_LANE]]
@@ -4704,7 +4416,7 @@ uint8x8_t test_vld1_lane_u8(uint8_t const * a, uint8x8_t b) {
return vld1_lane_u8(a, b, 7);
}
-// CHECK-LABEL: define <4 x i16> @test_vld1_lane_u16(i16* %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vld1_lane_u16(
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
@@ -4716,7 +4428,7 @@ uint16x4_t test_vld1_lane_u16(uint16_t const * a, uint16x4_t b) {
return vld1_lane_u16(a, b, 3);
}
-// CHECK-LABEL: define <2 x i32> @test_vld1_lane_u32(i32* %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vld1_lane_u32(
// CHECK: [[TMP0:%.*]] = bitcast i32* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
@@ -4728,7 +4440,7 @@ uint32x2_t test_vld1_lane_u32(uint32_t const * a, uint32x2_t b) {
return vld1_lane_u32(a, b, 1);
}
-// CHECK-LABEL: define <1 x i64> @test_vld1_lane_u64(i64* %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vld1_lane_u64(
// CHECK: [[TMP0:%.*]] = bitcast i64* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x i64>
@@ -4740,7 +4452,7 @@ uint64x1_t test_vld1_lane_u64(uint64_t const * a, uint64x1_t b) {
return vld1_lane_u64(a, b, 0);
}
-// CHECK-LABEL: define <8 x i8> @test_vld1_lane_s8(i8* %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vld1_lane_s8(
// CHECK: [[TMP0:%.*]] = load i8, i8* %a, align 1
// CHECK: [[VLD1_LANE:%.*]] = insertelement <8 x i8> %b, i8 [[TMP0]], i32 7
// CHECK: ret <8 x i8> [[VLD1_LANE]]
@@ -4748,7 +4460,7 @@ int8x8_t test_vld1_lane_s8(int8_t const * a, int8x8_t b) {
return vld1_lane_s8(a, b, 7);
}
-// CHECK-LABEL: define <4 x i16> @test_vld1_lane_s16(i16* %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vld1_lane_s16(
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
@@ -4760,7 +4472,7 @@ int16x4_t test_vld1_lane_s16(int16_t const * a, int16x4_t b) {
return vld1_lane_s16(a, b, 3);
}
-// CHECK-LABEL: define <2 x i32> @test_vld1_lane_s32(i32* %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vld1_lane_s32(
// CHECK: [[TMP0:%.*]] = bitcast i32* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
@@ -4772,7 +4484,7 @@ int32x2_t test_vld1_lane_s32(int32_t const * a, int32x2_t b) {
return vld1_lane_s32(a, b, 1);
}
-// CHECK-LABEL: define <1 x i64> @test_vld1_lane_s64(i64* %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vld1_lane_s64(
// CHECK: [[TMP0:%.*]] = bitcast i64* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x i64>
@@ -4784,7 +4496,7 @@ int64x1_t test_vld1_lane_s64(int64_t const * a, int64x1_t b) {
return vld1_lane_s64(a, b, 0);
}
-// CHECK-LABEL: define <4 x half> @test_vld1_lane_f16(half* %a, <4 x half> %b) #0 {
+// CHECK-LABEL: @test_vld1_lane_f16(
// CHECK: [[TMP0:%.*]] = bitcast half* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x half> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
@@ -4797,7 +4509,7 @@ float16x4_t test_vld1_lane_f16(float16_t const * a, float16x4_t b) {
return vld1_lane_f16(a, b, 3);
}
-// CHECK-LABEL: define <2 x float> @test_vld1_lane_f32(float* %a, <2 x float> %b) #0 {
+// CHECK-LABEL: @test_vld1_lane_f32(
// CHECK: [[TMP0:%.*]] = bitcast float* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
@@ -4809,7 +4521,7 @@ float32x2_t test_vld1_lane_f32(float32_t const * a, float32x2_t b) {
return vld1_lane_f32(a, b, 1);
}
-// CHECK-LABEL: define <8 x i8> @test_vld1_lane_p8(i8* %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vld1_lane_p8(
// CHECK: [[TMP0:%.*]] = load i8, i8* %a, align 1
// CHECK: [[VLD1_LANE:%.*]] = insertelement <8 x i8> %b, i8 [[TMP0]], i32 7
// CHECK: ret <8 x i8> [[VLD1_LANE]]
@@ -4817,7 +4529,7 @@ poly8x8_t test_vld1_lane_p8(poly8_t const * a, poly8x8_t b) {
return vld1_lane_p8(a, b, 7);
}
-// CHECK-LABEL: define <4 x i16> @test_vld1_lane_p16(i16* %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vld1_lane_p16(
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
@@ -4829,571 +4541,304 @@ poly16x4_t test_vld1_lane_p16(poly16_t const * a, poly16x4_t b) {
return vld1_lane_p16(a, b, 3);
}
-
-// CHECK-LABEL: define void @test_vld2q_u8(%struct.uint8x16x2_t* noalias sret %agg.result, i8* %a) #0 {
+// CHECK-LABEL: @test_vld2q_u8(
// CHECK: [[__RET:%.*]] = alloca %struct.uint8x16x2_t, align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x2_t* [[__RET]] to i8*
-// CHECK: [[VLD2Q_V:%.*]] = call { <16 x i8>, <16 x i8> } @llvm.arm.neon.vld2.v16i8.p0i8(i8* %a, i32 1)
-// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8> }*
-// CHECK: store { <16 x i8>, <16 x i8> } [[VLD2Q_V]], { <16 x i8>, <16 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x16x2_t* %agg.result to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x16x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP2]], i8* [[TMP3]], i32 32, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD2Q_V:%.*]] = call { <16 x i8>, <16 x i8>
uint8x16x2_t test_vld2q_u8(uint8_t const * a) {
return vld2q_u8(a);
}
-// CHECK-LABEL: define void @test_vld2q_u16(%struct.uint16x8x2_t* noalias sret %agg.result, i16* %a) #0 {
+// CHECK-LABEL: @test_vld2q_u16(
// 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: [[VLD2Q_V:%.*]] = call { <8 x i16>, <8 x i16> } @llvm.arm.neon.vld2.v8i16.p0i8(i8* [[TMP1]], i32 2)
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16> }*
-// CHECK: store { <8 x i16>, <8 x i16> } [[VLD2Q_V]], { <8 x i16>, <8 x i16> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint16x8x2_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 32, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD2Q_V:%.*]] = call { <8 x i16>, <8 x i16>
uint16x8x2_t test_vld2q_u16(uint16_t const * a) {
return vld2q_u16(a);
}
-// CHECK-LABEL: define void @test_vld2q_u32(%struct.uint32x4x2_t* noalias sret %agg.result, i32* %a) #0 {
+// CHECK-LABEL: @test_vld2q_u32(
// 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: [[VLD2Q_V:%.*]] = call { <4 x i32>, <4 x i32> } @llvm.arm.neon.vld2.v4i32.p0i8(i8* [[TMP1]], i32 4)
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to { <4 x i32>, <4 x i32> }*
-// CHECK: store { <4 x i32>, <4 x i32> } [[VLD2Q_V]], { <4 x i32>, <4 x i32> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint32x4x2_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 32, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD2Q_V:%.*]] = call { <4 x i32>, <4 x i32>
uint32x4x2_t test_vld2q_u32(uint32_t const * a) {
return vld2q_u32(a);
}
-// CHECK-LABEL: define void @test_vld2q_s8(%struct.int8x16x2_t* noalias sret %agg.result, i8* %a) #0 {
+// CHECK-LABEL: @test_vld2q_s8(
// CHECK: [[__RET:%.*]] = alloca %struct.int8x16x2_t, align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x2_t* [[__RET]] to i8*
-// CHECK: [[VLD2Q_V:%.*]] = call { <16 x i8>, <16 x i8> } @llvm.arm.neon.vld2.v16i8.p0i8(i8* %a, i32 1)
-// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8> }*
-// CHECK: store { <16 x i8>, <16 x i8> } [[VLD2Q_V]], { <16 x i8>, <16 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x16x2_t* %agg.result to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x16x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP2]], i8* [[TMP3]], i32 32, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD2Q_V:%.*]] = call { <16 x i8>, <16 x i8>
int8x16x2_t test_vld2q_s8(int8_t const * a) {
return vld2q_s8(a);
}
-// CHECK-LABEL: define void @test_vld2q_s16(%struct.int16x8x2_t* noalias sret %agg.result, i16* %a) #0 {
+// CHECK-LABEL: @test_vld2q_s16(
// 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: [[VLD2Q_V:%.*]] = call { <8 x i16>, <8 x i16> } @llvm.arm.neon.vld2.v8i16.p0i8(i8* [[TMP1]], i32 2)
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16> }*
-// CHECK: store { <8 x i16>, <8 x i16> } [[VLD2Q_V]], { <8 x i16>, <8 x i16> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int16x8x2_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int16x8x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 32, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD2Q_V:%.*]] = call { <8 x i16>, <8 x i16>
int16x8x2_t test_vld2q_s16(int16_t const * a) {
return vld2q_s16(a);
}
-// CHECK-LABEL: define void @test_vld2q_s32(%struct.int32x4x2_t* noalias sret %agg.result, i32* %a) #0 {
+// CHECK-LABEL: @test_vld2q_s32(
// 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: [[VLD2Q_V:%.*]] = call { <4 x i32>, <4 x i32> } @llvm.arm.neon.vld2.v4i32.p0i8(i8* [[TMP1]], i32 4)
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to { <4 x i32>, <4 x i32> }*
-// CHECK: store { <4 x i32>, <4 x i32> } [[VLD2Q_V]], { <4 x i32>, <4 x i32> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int32x4x2_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int32x4x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 32, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD2Q_V:%.*]] = call { <4 x i32>, <4 x i32>
int32x4x2_t test_vld2q_s32(int32_t const * a) {
return vld2q_s32(a);
}
-// CHECK-LABEL: define void @test_vld2q_f16(%struct.float16x8x2_t* noalias sret %agg.result, half* %a) #0 {
+// CHECK-LABEL: @test_vld2q_f16(
// 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: [[VLD2Q_V:%.*]] = call { <8 x i16>, <8 x i16> } @llvm.arm.neon.vld2.v8i16.p0i8(i8* [[TMP1]], i32 2)
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16> }*
-// CHECK: store { <8 x i16>, <8 x i16> } [[VLD2Q_V]], { <8 x i16>, <8 x i16> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.float16x8x2_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x8x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 32, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD2Q_V:%.*]] = call { <8 x i16>, <8 x i16>
float16x8x2_t test_vld2q_f16(float16_t const * a) {
return vld2q_f16(a);
}
-// CHECK-LABEL: define void @test_vld2q_f32(%struct.float32x4x2_t* noalias sret %agg.result, float* %a) #0 {
+// CHECK-LABEL: @test_vld2q_f32(
// 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: [[VLD2Q_V:%.*]] = call { <4 x float>, <4 x float> } @llvm.arm.neon.vld2.v4f32.p0i8(i8* [[TMP1]], i32 4)
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to { <4 x float>, <4 x float> }*
-// CHECK: store { <4 x float>, <4 x float> } [[VLD2Q_V]], { <4 x float>, <4 x float> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.float32x4x2_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.float32x4x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 32, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD2Q_V:%.*]] = call { <4 x float>, <4 x float>
float32x4x2_t test_vld2q_f32(float32_t const * a) {
return vld2q_f32(a);
}
-// CHECK-LABEL: define void @test_vld2q_p8(%struct.poly8x16x2_t* noalias sret %agg.result, i8* %a) #0 {
+// CHECK-LABEL: @test_vld2q_p8(
// CHECK: [[__RET:%.*]] = alloca %struct.poly8x16x2_t, align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x2_t* [[__RET]] to i8*
-// CHECK: [[VLD2Q_V:%.*]] = call { <16 x i8>, <16 x i8> } @llvm.arm.neon.vld2.v16i8.p0i8(i8* %a, i32 1)
-// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <16 x i8>, <16 x i8> }*
-// CHECK: store { <16 x i8>, <16 x i8> } [[VLD2Q_V]], { <16 x i8>, <16 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x16x2_t* %agg.result to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x16x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP2]], i8* [[TMP3]], i32 32, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD2Q_V:%.*]] = call { <16 x i8>, <16 x i8>
poly8x16x2_t test_vld2q_p8(poly8_t const * a) {
return vld2q_p8(a);
}
-// CHECK-LABEL: define void @test_vld2q_p16(%struct.poly16x8x2_t* noalias sret %agg.result, i16* %a) #0 {
+// CHECK-LABEL: @test_vld2q_p16(
// 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: [[VLD2Q_V:%.*]] = call { <8 x i16>, <8 x i16> } @llvm.arm.neon.vld2.v8i16.p0i8(i8* [[TMP1]], i32 2)
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16> }*
-// CHECK: store { <8 x i16>, <8 x i16> } [[VLD2Q_V]], { <8 x i16>, <8 x i16> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.poly16x8x2_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 32, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD2Q_V:%.*]] = call { <8 x i16>, <8 x i16>
poly16x8x2_t test_vld2q_p16(poly16_t const * a) {
return vld2q_p16(a);
}
-// CHECK-LABEL: define void @test_vld2_u8(%struct.uint8x8x2_t* noalias sret %agg.result, i8* %a) #0 {
+// CHECK-LABEL: @test_vld2_u8(
// CHECK: [[__RET:%.*]] = alloca %struct.uint8x8x2_t, align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x2_t* [[__RET]] to i8*
-// CHECK: [[VLD2_V:%.*]] = call { <8 x i8>, <8 x i8> } @llvm.arm.neon.vld2.v8i8.p0i8(i8* %a, i32 1)
-// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8> }*
-// CHECK: store { <8 x i8>, <8 x i8> } [[VLD2_V]], { <8 x i8>, <8 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x8x2_t* %agg.result to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x8x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP2]], i8* [[TMP3]], i32 16, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD2_V:%.*]] = call { <8 x i8>, <8 x i8>
uint8x8x2_t test_vld2_u8(uint8_t const * a) {
return vld2_u8(a);
}
-// CHECK-LABEL: define void @test_vld2_u16(%struct.uint16x4x2_t* noalias sret %agg.result, i16* %a) #0 {
+// CHECK-LABEL: @test_vld2_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: [[VLD2_V:%.*]] = call { <4 x i16>, <4 x i16> } @llvm.arm.neon.vld2.v4i16.p0i8(i8* [[TMP1]], i32 2)
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16> } [[VLD2_V]], { <4 x i16>, <4 x i16> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint16x4x2_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 16, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD2_V:%.*]] = call { <4 x i16>, <4 x i16>
uint16x4x2_t test_vld2_u16(uint16_t const * a) {
return vld2_u16(a);
}
-// CHECK-LABEL: define void @test_vld2_u32(%struct.uint32x2x2_t* noalias sret %agg.result, i32* %a) #0 {
+// CHECK-LABEL: @test_vld2_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: [[VLD2_V:%.*]] = call { <2 x i32>, <2 x i32> } @llvm.arm.neon.vld2.v2i32.p0i8(i8* [[TMP1]], i32 4)
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to { <2 x i32>, <2 x i32> }*
-// CHECK: store { <2 x i32>, <2 x i32> } [[VLD2_V]], { <2 x i32>, <2 x i32> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint32x2x2_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 16, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD2_V:%.*]] = call { <2 x i32>, <2 x i32>
uint32x2x2_t test_vld2_u32(uint32_t const * a) {
return vld2_u32(a);
}
-// CHECK-LABEL: define void @test_vld2_u64(%struct.uint64x1x2_t* noalias sret %agg.result, i64* %a) #0 {
+// CHECK-LABEL: @test_vld2_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: [[VLD2_V:%.*]] = call { <1 x i64>, <1 x i64> } @llvm.arm.neon.vld2.v1i64.p0i8(i8* [[TMP1]], i32 4)
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to { <1 x i64>, <1 x i64> }*
-// CHECK: store { <1 x i64>, <1 x i64> } [[VLD2_V]], { <1 x i64>, <1 x i64> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint64x1x2_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint64x1x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 16, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD2_V:%.*]] = call { <1 x i64>, <1 x i64>
uint64x1x2_t test_vld2_u64(uint64_t const * a) {
return vld2_u64(a);
}
-// CHECK-LABEL: define void @test_vld2_s8(%struct.int8x8x2_t* noalias sret %agg.result, i8* %a) #0 {
+// CHECK-LABEL: @test_vld2_s8(
// CHECK: [[__RET:%.*]] = alloca %struct.int8x8x2_t, align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x2_t* [[__RET]] to i8*
-// CHECK: [[VLD2_V:%.*]] = call { <8 x i8>, <8 x i8> } @llvm.arm.neon.vld2.v8i8.p0i8(i8* %a, i32 1)
-// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8> }*
-// CHECK: store { <8 x i8>, <8 x i8> } [[VLD2_V]], { <8 x i8>, <8 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x8x2_t* %agg.result to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x8x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP2]], i8* [[TMP3]], i32 16, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD2_V:%.*]] = call { <8 x i8>, <8 x i8>
int8x8x2_t test_vld2_s8(int8_t const * a) {
return vld2_s8(a);
}
-// CHECK-LABEL: define void @test_vld2_s16(%struct.int16x4x2_t* noalias sret %agg.result, i16* %a) #0 {
+// CHECK-LABEL: @test_vld2_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: [[VLD2_V:%.*]] = call { <4 x i16>, <4 x i16> } @llvm.arm.neon.vld2.v4i16.p0i8(i8* [[TMP1]], i32 2)
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16> } [[VLD2_V]], { <4 x i16>, <4 x i16> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int16x4x2_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int16x4x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 16, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD2_V:%.*]] = call { <4 x i16>, <4 x i16>
int16x4x2_t test_vld2_s16(int16_t const * a) {
return vld2_s16(a);
}
-// CHECK-LABEL: define void @test_vld2_s32(%struct.int32x2x2_t* noalias sret %agg.result, i32* %a) #0 {
+// CHECK-LABEL: @test_vld2_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: [[VLD2_V:%.*]] = call { <2 x i32>, <2 x i32> } @llvm.arm.neon.vld2.v2i32.p0i8(i8* [[TMP1]], i32 4)
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to { <2 x i32>, <2 x i32> }*
-// CHECK: store { <2 x i32>, <2 x i32> } [[VLD2_V]], { <2 x i32>, <2 x i32> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int32x2x2_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int32x2x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 16, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD2_V:%.*]] = call { <2 x i32>, <2 x i32>
int32x2x2_t test_vld2_s32(int32_t const * a) {
return vld2_s32(a);
}
-// CHECK-LABEL: define void @test_vld2_s64(%struct.int64x1x2_t* noalias sret %agg.result, i64* %a) #0 {
+// CHECK-LABEL: @test_vld2_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: [[VLD2_V:%.*]] = call { <1 x i64>, <1 x i64> } @llvm.arm.neon.vld2.v1i64.p0i8(i8* [[TMP1]], i32 4)
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to { <1 x i64>, <1 x i64> }*
-// CHECK: store { <1 x i64>, <1 x i64> } [[VLD2_V]], { <1 x i64>, <1 x i64> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int64x1x2_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int64x1x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 16, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD2_V:%.*]] = call { <1 x i64>, <1 x i64>
int64x1x2_t test_vld2_s64(int64_t const * a) {
return vld2_s64(a);
}
-// CHECK-LABEL: define void @test_vld2_f16(%struct.float16x4x2_t* noalias sret %agg.result, half* %a) #0 {
+// CHECK-LABEL: @test_vld2_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: [[VLD2_V:%.*]] = call { <4 x i16>, <4 x i16> } @llvm.arm.neon.vld2.v4i16.p0i8(i8* [[TMP1]], i32 2)
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16> } [[VLD2_V]], { <4 x i16>, <4 x i16> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.float16x4x2_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x4x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 16, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD2_V:%.*]] = call { <4 x i16>, <4 x i16>
float16x4x2_t test_vld2_f16(float16_t const * a) {
return vld2_f16(a);
}
-// CHECK-LABEL: define void @test_vld2_f32(%struct.float32x2x2_t* noalias sret %agg.result, float* %a) #0 {
+// CHECK-LABEL: @test_vld2_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: [[VLD2_V:%.*]] = call { <2 x float>, <2 x float> } @llvm.arm.neon.vld2.v2f32.p0i8(i8* [[TMP1]], i32 4)
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to { <2 x float>, <2 x float> }*
-// CHECK: store { <2 x float>, <2 x float> } [[VLD2_V]], { <2 x float>, <2 x float> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.float32x2x2_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.float32x2x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 16, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD2_V:%.*]] = call { <2 x float>, <2 x float>
float32x2x2_t test_vld2_f32(float32_t const * a) {
return vld2_f32(a);
}
-// CHECK-LABEL: define void @test_vld2_p8(%struct.poly8x8x2_t* noalias sret %agg.result, i8* %a) #0 {
+// CHECK-LABEL: @test_vld2_p8(
// CHECK: [[__RET:%.*]] = alloca %struct.poly8x8x2_t, align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x2_t* [[__RET]] to i8*
-// CHECK: [[VLD2_V:%.*]] = call { <8 x i8>, <8 x i8> } @llvm.arm.neon.vld2.v8i8.p0i8(i8* %a, i32 1)
-// CHECK: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8> }*
-// CHECK: store { <8 x i8>, <8 x i8> } [[VLD2_V]], { <8 x i8>, <8 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x8x2_t* %agg.result to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x8x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP2]], i8* [[TMP3]], i32 16, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD2_V:%.*]] = call { <8 x i8>, <8 x i8>
poly8x8x2_t test_vld2_p8(poly8_t const * a) {
return vld2_p8(a);
}
-// CHECK-LABEL: define void @test_vld2_p16(%struct.poly16x4x2_t* noalias sret %agg.result, i16* %a) #0 {
+// CHECK-LABEL: @test_vld2_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: [[VLD2_V:%.*]] = call { <4 x i16>, <4 x i16> } @llvm.arm.neon.vld2.v4i16.p0i8(i8* [[TMP1]], i32 2)
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16> } [[VLD2_V]], { <4 x i16>, <4 x i16> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.poly16x4x2_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 16, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD2_V:%.*]] = call { <4 x i16>, <4 x i16>
poly16x4x2_t test_vld2_p16(poly16_t const * a) {
return vld2_p16(a);
}
-
-// CHECK-LABEL: define void @test_vld2_dup_u8(%struct.uint8x8x2_t* noalias sret %agg.result, i8* %a) #0 {
+// 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> } @llvm.arm.neon.vld2lane.v8i8.p0i8(i8* %a, <8 x i8> undef, <8 x i8> undef, i32 0, i32 1)
-// CHECK: [[TMP1:%.*]] = extractvalue { <8 x i8>, <8 x i8> } [[VLD_DUP]], 0
-// CHECK: [[LANE:%.*]] = shufflevector <8 x i8> [[TMP1]], <8 x i8> [[TMP1]], <8 x i32> zeroinitializer
-// CHECK: [[TMP2:%.*]] = insertvalue { <8 x i8>, <8 x i8> } [[VLD_DUP]], <8 x i8> [[LANE]], 0
-// CHECK: [[TMP3:%.*]] = extractvalue { <8 x i8>, <8 x i8> } [[TMP2]], 1
-// CHECK: [[LANE1:%.*]] = shufflevector <8 x i8> [[TMP3]], <8 x i8> [[TMP3]], <8 x i32> zeroinitializer
-// CHECK: [[TMP4:%.*]] = insertvalue { <8 x i8>, <8 x i8> } [[TMP2]], <8 x i8> [[LANE1]], 1
-// CHECK: [[TMP5:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8> }*
-// CHECK: store { <8 x i8>, <8 x i8> } [[TMP4]], { <8 x i8>, <8 x i8> }* [[TMP5]]
-// CHECK: [[TMP6:%.*]] = bitcast %struct.uint8x8x2_t* %agg.result to i8*
-// CHECK: [[TMP7:%.*]] = bitcast %struct.uint8x8x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP6]], i8* [[TMP7]], i32 16, i32 8, i1 false)
-// CHECK: ret void
+// 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: define void @test_vld2_dup_u16(%struct.uint16x4x2_t* noalias sret %agg.result, i16* %a) #0 {
+// 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> } @llvm.arm.neon.vld2lane.v4i16.p0i8(i8* [[TMP1]], <4 x i16> undef, <4 x i16> undef, i32 0, i32 2)
-// CHECK: [[TMP2:%.*]] = extractvalue { <4 x i16>, <4 x i16> } [[VLD_DUP]], 0
-// CHECK: [[LANE:%.*]] = shufflevector <4 x i16> [[TMP2]], <4 x i16> [[TMP2]], <4 x i32> zeroinitializer
-// CHECK: [[TMP3:%.*]] = insertvalue { <4 x i16>, <4 x i16> } [[VLD_DUP]], <4 x i16> [[LANE]], 0
-// CHECK: [[TMP4:%.*]] = extractvalue { <4 x i16>, <4 x i16> } [[TMP3]], 1
-// CHECK: [[LANE1:%.*]] = shufflevector <4 x i16> [[TMP4]], <4 x i16> [[TMP4]], <4 x i32> zeroinitializer
-// CHECK: [[TMP5:%.*]] = insertvalue { <4 x i16>, <4 x i16> } [[TMP3]], <4 x i16> [[LANE1]], 1
-// CHECK: [[TMP6:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16> } [[TMP5]], { <4 x i16>, <4 x i16> }* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.uint16x4x2_t* %agg.result to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP7]], i8* [[TMP8]], i32 16, i32 8, i1 false)
-// CHECK: ret void
+// 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: define void @test_vld2_dup_u32(%struct.uint32x2x2_t* noalias sret %agg.result, i32* %a) #0 {
+// 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> } @llvm.arm.neon.vld2lane.v2i32.p0i8(i8* [[TMP1]], <2 x i32> undef, <2 x i32> undef, i32 0, i32 4)
-// CHECK: [[TMP2:%.*]] = extractvalue { <2 x i32>, <2 x i32> } [[VLD_DUP]], 0
-// CHECK: [[LANE:%.*]] = shufflevector <2 x i32> [[TMP2]], <2 x i32> [[TMP2]], <2 x i32> zeroinitializer
-// CHECK: [[TMP3:%.*]] = insertvalue { <2 x i32>, <2 x i32> } [[VLD_DUP]], <2 x i32> [[LANE]], 0
-// CHECK: [[TMP4:%.*]] = extractvalue { <2 x i32>, <2 x i32> } [[TMP3]], 1
-// CHECK: [[LANE1:%.*]] = shufflevector <2 x i32> [[TMP4]], <2 x i32> [[TMP4]], <2 x i32> zeroinitializer
-// CHECK: [[TMP5:%.*]] = insertvalue { <2 x i32>, <2 x i32> } [[TMP3]], <2 x i32> [[LANE1]], 1
-// CHECK: [[TMP6:%.*]] = bitcast i8* [[TMP0]] to { <2 x i32>, <2 x i32> }*
-// CHECK: store { <2 x i32>, <2 x i32> } [[TMP5]], { <2 x i32>, <2 x i32> }* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.uint32x2x2_t* %agg.result to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP7]], i8* [[TMP8]], i32 16, i32 8, i1 false)
-// CHECK: ret void
+// 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: define void @test_vld2_dup_u64(%struct.uint64x1x2_t* noalias sret %agg.result, i64* %a) #0 {
+// 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> } @llvm.arm.neon.vld2.v1i64.p0i8(i8* [[TMP1]], i32 4)
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to { <1 x i64>, <1 x i64> }*
-// CHECK: store { <1 x i64>, <1 x i64> } [[VLD_DUP]], { <1 x i64>, <1 x i64> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint64x1x2_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint64x1x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 16, i32 8, i1 false)
-// CHECK: ret void
+// 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: define void @test_vld2_dup_s8(%struct.int8x8x2_t* noalias sret %agg.result, i8* %a) #0 {
+// 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> } @llvm.arm.neon.vld2lane.v8i8.p0i8(i8* %a, <8 x i8> undef, <8 x i8> undef, i32 0, i32 1)
-// CHECK: [[TMP1:%.*]] = extractvalue { <8 x i8>, <8 x i8> } [[VLD_DUP]], 0
-// CHECK: [[LANE:%.*]] = shufflevector <8 x i8> [[TMP1]], <8 x i8> [[TMP1]], <8 x i32> zeroinitializer
-// CHECK: [[TMP2:%.*]] = insertvalue { <8 x i8>, <8 x i8> } [[VLD_DUP]], <8 x i8> [[LANE]], 0
-// CHECK: [[TMP3:%.*]] = extractvalue { <8 x i8>, <8 x i8> } [[TMP2]], 1
-// CHECK: [[LANE1:%.*]] = shufflevector <8 x i8> [[TMP3]], <8 x i8> [[TMP3]], <8 x i32> zeroinitializer
-// CHECK: [[TMP4:%.*]] = insertvalue { <8 x i8>, <8 x i8> } [[TMP2]], <8 x i8> [[LANE1]], 1
-// CHECK: [[TMP5:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8> }*
-// CHECK: store { <8 x i8>, <8 x i8> } [[TMP4]], { <8 x i8>, <8 x i8> }* [[TMP5]]
-// CHECK: [[TMP6:%.*]] = bitcast %struct.int8x8x2_t* %agg.result to i8*
-// CHECK: [[TMP7:%.*]] = bitcast %struct.int8x8x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP6]], i8* [[TMP7]], i32 16, i32 8, i1 false)
-// CHECK: ret void
+// 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: define void @test_vld2_dup_s16(%struct.int16x4x2_t* noalias sret %agg.result, i16* %a) #0 {
+// 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> } @llvm.arm.neon.vld2lane.v4i16.p0i8(i8* [[TMP1]], <4 x i16> undef, <4 x i16> undef, i32 0, i32 2)
-// CHECK: [[TMP2:%.*]] = extractvalue { <4 x i16>, <4 x i16> } [[VLD_DUP]], 0
-// CHECK: [[LANE:%.*]] = shufflevector <4 x i16> [[TMP2]], <4 x i16> [[TMP2]], <4 x i32> zeroinitializer
-// CHECK: [[TMP3:%.*]] = insertvalue { <4 x i16>, <4 x i16> } [[VLD_DUP]], <4 x i16> [[LANE]], 0
-// CHECK: [[TMP4:%.*]] = extractvalue { <4 x i16>, <4 x i16> } [[TMP3]], 1
-// CHECK: [[LANE1:%.*]] = shufflevector <4 x i16> [[TMP4]], <4 x i16> [[TMP4]], <4 x i32> zeroinitializer
-// CHECK: [[TMP5:%.*]] = insertvalue { <4 x i16>, <4 x i16> } [[TMP3]], <4 x i16> [[LANE1]], 1
-// CHECK: [[TMP6:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16> } [[TMP5]], { <4 x i16>, <4 x i16> }* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.int16x4x2_t* %agg.result to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.int16x4x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP7]], i8* [[TMP8]], i32 16, i32 8, i1 false)
-// CHECK: ret void
+// 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: define void @test_vld2_dup_s32(%struct.int32x2x2_t* noalias sret %agg.result, i32* %a) #0 {
+// 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> } @llvm.arm.neon.vld2lane.v2i32.p0i8(i8* [[TMP1]], <2 x i32> undef, <2 x i32> undef, i32 0, i32 4)
-// CHECK: [[TMP2:%.*]] = extractvalue { <2 x i32>, <2 x i32> } [[VLD_DUP]], 0
-// CHECK: [[LANE:%.*]] = shufflevector <2 x i32> [[TMP2]], <2 x i32> [[TMP2]], <2 x i32> zeroinitializer
-// CHECK: [[TMP3:%.*]] = insertvalue { <2 x i32>, <2 x i32> } [[VLD_DUP]], <2 x i32> [[LANE]], 0
-// CHECK: [[TMP4:%.*]] = extractvalue { <2 x i32>, <2 x i32> } [[TMP3]], 1
-// CHECK: [[LANE1:%.*]] = shufflevector <2 x i32> [[TMP4]], <2 x i32> [[TMP4]], <2 x i32> zeroinitializer
-// CHECK: [[TMP5:%.*]] = insertvalue { <2 x i32>, <2 x i32> } [[TMP3]], <2 x i32> [[LANE1]], 1
-// CHECK: [[TMP6:%.*]] = bitcast i8* [[TMP0]] to { <2 x i32>, <2 x i32> }*
-// CHECK: store { <2 x i32>, <2 x i32> } [[TMP5]], { <2 x i32>, <2 x i32> }* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.int32x2x2_t* %agg.result to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.int32x2x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP7]], i8* [[TMP8]], i32 16, i32 8, i1 false)
-// CHECK: ret void
+// 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: define void @test_vld2_dup_s64(%struct.int64x1x2_t* noalias sret %agg.result, i64* %a) #0 {
+// 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> } @llvm.arm.neon.vld2.v1i64.p0i8(i8* [[TMP1]], i32 4)
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to { <1 x i64>, <1 x i64> }*
-// CHECK: store { <1 x i64>, <1 x i64> } [[VLD_DUP]], { <1 x i64>, <1 x i64> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int64x1x2_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int64x1x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 16, i32 8, i1 false)
-// CHECK: ret void
+// 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: define void @test_vld2_dup_f16(%struct.float16x4x2_t* noalias sret %agg.result, half* %a) #0 {
+// 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> } @llvm.arm.neon.vld2lane.v4i16.p0i8(i8* [[TMP1]], <4 x i16> undef, <4 x i16> undef, i32 0, i32 2)
-// CHECK: [[TMP2:%.*]] = extractvalue { <4 x i16>, <4 x i16> } [[VLD_DUP]], 0
-// CHECK: [[LANE:%.*]] = shufflevector <4 x i16> [[TMP2]], <4 x i16> [[TMP2]], <4 x i32> zeroinitializer
-// CHECK: [[TMP3:%.*]] = insertvalue { <4 x i16>, <4 x i16> } [[VLD_DUP]], <4 x i16> [[LANE]], 0
-// CHECK: [[TMP4:%.*]] = extractvalue { <4 x i16>, <4 x i16> } [[TMP3]], 1
-// CHECK: [[LANE1:%.*]] = shufflevector <4 x i16> [[TMP4]], <4 x i16> [[TMP4]], <4 x i32> zeroinitializer
-// CHECK: [[TMP5:%.*]] = insertvalue { <4 x i16>, <4 x i16> } [[TMP3]], <4 x i16> [[LANE1]], 1
-// CHECK: [[TMP6:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16> } [[TMP5]], { <4 x i16>, <4 x i16> }* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.float16x4x2_t* %agg.result to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.float16x4x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP7]], i8* [[TMP8]], i32 16, i32 8, i1 false)
-// CHECK: ret void
+// 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: define void @test_vld2_dup_f32(%struct.float32x2x2_t* noalias sret %agg.result, float* %a) #0 {
+// 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> } @llvm.arm.neon.vld2lane.v2f32.p0i8(i8* [[TMP1]], <2 x float> undef, <2 x float> undef, i32 0, i32 4)
-// CHECK: [[TMP2:%.*]] = extractvalue { <2 x float>, <2 x float> } [[VLD_DUP]], 0
-// CHECK: [[LANE:%.*]] = shufflevector <2 x float> [[TMP2]], <2 x float> [[TMP2]], <2 x i32> zeroinitializer
-// CHECK: [[TMP3:%.*]] = insertvalue { <2 x float>, <2 x float> } [[VLD_DUP]], <2 x float> [[LANE]], 0
-// CHECK: [[TMP4:%.*]] = extractvalue { <2 x float>, <2 x float> } [[TMP3]], 1
-// CHECK: [[LANE1:%.*]] = shufflevector <2 x float> [[TMP4]], <2 x float> [[TMP4]], <2 x i32> zeroinitializer
-// CHECK: [[TMP5:%.*]] = insertvalue { <2 x float>, <2 x float> } [[TMP3]], <2 x float> [[LANE1]], 1
-// CHECK: [[TMP6:%.*]] = bitcast i8* [[TMP0]] to { <2 x float>, <2 x float> }*
-// CHECK: store { <2 x float>, <2 x float> } [[TMP5]], { <2 x float>, <2 x float> }* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.float32x2x2_t* %agg.result to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.float32x2x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP7]], i8* [[TMP8]], i32 16, i32 8, i1 false)
-// CHECK: ret void
+// 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: define void @test_vld2_dup_p8(%struct.poly8x8x2_t* noalias sret %agg.result, i8* %a) #0 {
+// 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> } @llvm.arm.neon.vld2lane.v8i8.p0i8(i8* %a, <8 x i8> undef, <8 x i8> undef, i32 0, i32 1)
-// CHECK: [[TMP1:%.*]] = extractvalue { <8 x i8>, <8 x i8> } [[VLD_DUP]], 0
-// CHECK: [[LANE:%.*]] = shufflevector <8 x i8> [[TMP1]], <8 x i8> [[TMP1]], <8 x i32> zeroinitializer
-// CHECK: [[TMP2:%.*]] = insertvalue { <8 x i8>, <8 x i8> } [[VLD_DUP]], <8 x i8> [[LANE]], 0
-// CHECK: [[TMP3:%.*]] = extractvalue { <8 x i8>, <8 x i8> } [[TMP2]], 1
-// CHECK: [[LANE1:%.*]] = shufflevector <8 x i8> [[TMP3]], <8 x i8> [[TMP3]], <8 x i32> zeroinitializer
-// CHECK: [[TMP4:%.*]] = insertvalue { <8 x i8>, <8 x i8> } [[TMP2]], <8 x i8> [[LANE1]], 1
-// CHECK: [[TMP5:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8> }*
-// CHECK: store { <8 x i8>, <8 x i8> } [[TMP4]], { <8 x i8>, <8 x i8> }* [[TMP5]]
-// CHECK: [[TMP6:%.*]] = bitcast %struct.poly8x8x2_t* %agg.result to i8*
-// CHECK: [[TMP7:%.*]] = bitcast %struct.poly8x8x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP6]], i8* [[TMP7]], i32 16, i32 8, i1 false)
-// CHECK: ret void
+// 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: define void @test_vld2_dup_p16(%struct.poly16x4x2_t* noalias sret %agg.result, i16* %a) #0 {
+// 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> } @llvm.arm.neon.vld2lane.v4i16.p0i8(i8* [[TMP1]], <4 x i16> undef, <4 x i16> undef, i32 0, i32 2)
-// CHECK: [[TMP2:%.*]] = extractvalue { <4 x i16>, <4 x i16> } [[VLD_DUP]], 0
-// CHECK: [[LANE:%.*]] = shufflevector <4 x i16> [[TMP2]], <4 x i16> [[TMP2]], <4 x i32> zeroinitializer
-// CHECK: [[TMP3:%.*]] = insertvalue { <4 x i16>, <4 x i16> } [[VLD_DUP]], <4 x i16> [[LANE]], 0
-// CHECK: [[TMP4:%.*]] = extractvalue { <4 x i16>, <4 x i16> } [[TMP3]], 1
-// CHECK: [[LANE1:%.*]] = shufflevector <4 x i16> [[TMP4]], <4 x i16> [[TMP4]], <4 x i32> zeroinitializer
-// CHECK: [[TMP5:%.*]] = insertvalue { <4 x i16>, <4 x i16> } [[TMP3]], <4 x i16> [[LANE1]], 1
-// CHECK: [[TMP6:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16> } [[TMP5]], { <4 x i16>, <4 x i16> }* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.poly16x4x2_t* %agg.result to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP7]], i8* [[TMP8]], i32 16, i32 8, i1 false)
-// CHECK: ret void
+// 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: define void @test_vld2q_lane_u16(%struct.uint16x8x2_t* noalias sret %agg.result, i16* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld2q_lane_u16(
// CHECK: [[B:%.*]] = alloca %struct.uint16x8x2_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.uint16x8x2_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.uint16x8x2_t, align 16
@@ -5415,18 +4860,12 @@ poly16x4x2_t test_vld2_dup_p16(poly16_t const * a) {
// CHECK: [[TMP8:%.*]] = bitcast <8 x i16> [[TMP7]] to <16 x i8>
// CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16>
// CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16>
-// CHECK: [[VLD2Q_LANE_V:%.*]] = call { <8 x i16>, <8 x i16> } @llvm.arm.neon.vld2lane.v8i16.p0i8(i8* [[TMP4]], <8 x i16> [[TMP9]], <8 x i16> [[TMP10]], i32 7, i32 2)
-// CHECK: [[TMP11:%.*]] = bitcast i8* [[TMP3]] to { <8 x i16>, <8 x i16> }*
-// CHECK: store { <8 x i16>, <8 x i16> } [[VLD2Q_LANE_V]], { <8 x i16>, <8 x i16> }* [[TMP11]]
-// CHECK: [[TMP12:%.*]] = bitcast %struct.uint16x8x2_t* %agg.result to i8*
-// CHECK: [[TMP13:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP12]], i8* [[TMP13]], i32 32, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD2Q_LANE_V:%.*]] = call { <8 x i16>, <8 x i16>
uint16x8x2_t test_vld2q_lane_u16(uint16_t const * a, uint16x8x2_t b) {
return vld2q_lane_u16(a, b, 7);
}
-// CHECK-LABEL: define void @test_vld2q_lane_u32(%struct.uint32x4x2_t* noalias sret %agg.result, i32* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld2q_lane_u32(
// CHECK: [[B:%.*]] = alloca %struct.uint32x4x2_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.uint32x4x2_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.uint32x4x2_t, align 16
@@ -5448,18 +4887,12 @@ uint16x8x2_t test_vld2q_lane_u16(uint16_t const * a, uint16x8x2_t b) {
// CHECK: [[TMP8:%.*]] = bitcast <4 x i32> [[TMP7]] to <16 x i8>
// CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x i32>
// CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP8]] to <4 x i32>
-// CHECK: [[VLD2Q_LANE_V:%.*]] = call { <4 x i32>, <4 x i32> } @llvm.arm.neon.vld2lane.v4i32.p0i8(i8* [[TMP4]], <4 x i32> [[TMP9]], <4 x i32> [[TMP10]], i32 3, i32 4)
-// CHECK: [[TMP11:%.*]] = bitcast i8* [[TMP3]] to { <4 x i32>, <4 x i32> }*
-// CHECK: store { <4 x i32>, <4 x i32> } [[VLD2Q_LANE_V]], { <4 x i32>, <4 x i32> }* [[TMP11]]
-// CHECK: [[TMP12:%.*]] = bitcast %struct.uint32x4x2_t* %agg.result to i8*
-// CHECK: [[TMP13:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP12]], i8* [[TMP13]], i32 32, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD2Q_LANE_V:%.*]] = call { <4 x i32>, <4 x i32>
uint32x4x2_t test_vld2q_lane_u32(uint32_t const * a, uint32x4x2_t b) {
return vld2q_lane_u32(a, b, 3);
}
-// CHECK-LABEL: define void @test_vld2q_lane_s16(%struct.int16x8x2_t* noalias sret %agg.result, i16* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld2q_lane_s16(
// CHECK: [[B:%.*]] = alloca %struct.int16x8x2_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.int16x8x2_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.int16x8x2_t, align 16
@@ -5481,18 +4914,12 @@ uint32x4x2_t test_vld2q_lane_u32(uint32_t const * a, uint32x4x2_t b) {
// CHECK: [[TMP8:%.*]] = bitcast <8 x i16> [[TMP7]] to <16 x i8>
// CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16>
// CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16>
-// CHECK: [[VLD2Q_LANE_V:%.*]] = call { <8 x i16>, <8 x i16> } @llvm.arm.neon.vld2lane.v8i16.p0i8(i8* [[TMP4]], <8 x i16> [[TMP9]], <8 x i16> [[TMP10]], i32 7, i32 2)
-// CHECK: [[TMP11:%.*]] = bitcast i8* [[TMP3]] to { <8 x i16>, <8 x i16> }*
-// CHECK: store { <8 x i16>, <8 x i16> } [[VLD2Q_LANE_V]], { <8 x i16>, <8 x i16> }* [[TMP11]]
-// CHECK: [[TMP12:%.*]] = bitcast %struct.int16x8x2_t* %agg.result to i8*
-// CHECK: [[TMP13:%.*]] = bitcast %struct.int16x8x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP12]], i8* [[TMP13]], i32 32, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD2Q_LANE_V:%.*]] = call { <8 x i16>, <8 x i16>
int16x8x2_t test_vld2q_lane_s16(int16_t const * a, int16x8x2_t b) {
return vld2q_lane_s16(a, b, 7);
}
-// CHECK-LABEL: define void @test_vld2q_lane_s32(%struct.int32x4x2_t* noalias sret %agg.result, i32* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld2q_lane_s32(
// CHECK: [[B:%.*]] = alloca %struct.int32x4x2_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.int32x4x2_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.int32x4x2_t, align 16
@@ -5514,18 +4941,12 @@ int16x8x2_t test_vld2q_lane_s16(int16_t const * a, int16x8x2_t b) {
// CHECK: [[TMP8:%.*]] = bitcast <4 x i32> [[TMP7]] to <16 x i8>
// CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x i32>
// CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP8]] to <4 x i32>
-// CHECK: [[VLD2Q_LANE_V:%.*]] = call { <4 x i32>, <4 x i32> } @llvm.arm.neon.vld2lane.v4i32.p0i8(i8* [[TMP4]], <4 x i32> [[TMP9]], <4 x i32> [[TMP10]], i32 3, i32 4)
-// CHECK: [[TMP11:%.*]] = bitcast i8* [[TMP3]] to { <4 x i32>, <4 x i32> }*
-// CHECK: store { <4 x i32>, <4 x i32> } [[VLD2Q_LANE_V]], { <4 x i32>, <4 x i32> }* [[TMP11]]
-// CHECK: [[TMP12:%.*]] = bitcast %struct.int32x4x2_t* %agg.result to i8*
-// CHECK: [[TMP13:%.*]] = bitcast %struct.int32x4x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP12]], i8* [[TMP13]], i32 32, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD2Q_LANE_V:%.*]] = call { <4 x i32>, <4 x i32>
int32x4x2_t test_vld2q_lane_s32(int32_t const * a, int32x4x2_t b) {
return vld2q_lane_s32(a, b, 3);
}
-// CHECK-LABEL: define void @test_vld2q_lane_f16(%struct.float16x8x2_t* noalias sret %agg.result, half* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld2q_lane_f16(
// CHECK: [[B:%.*]] = alloca %struct.float16x8x2_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.float16x8x2_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.float16x8x2_t, align 16
@@ -5547,18 +4968,12 @@ int32x4x2_t test_vld2q_lane_s32(int32_t const * a, int32x4x2_t b) {
// CHECK: [[TMP8:%.*]] = bitcast <8 x half> [[TMP7]] to <16 x i8>
// CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16>
// CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16>
-// CHECK: [[VLD2Q_LANE_V:%.*]] = call { <8 x i16>, <8 x i16> } @llvm.arm.neon.vld2lane.v8i16.p0i8(i8* [[TMP4]], <8 x i16> [[TMP9]], <8 x i16> [[TMP10]], i32 7, i32 2)
-// CHECK: [[TMP11:%.*]] = bitcast i8* [[TMP3]] to { <8 x i16>, <8 x i16> }*
-// CHECK: store { <8 x i16>, <8 x i16> } [[VLD2Q_LANE_V]], { <8 x i16>, <8 x i16> }* [[TMP11]]
-// CHECK: [[TMP12:%.*]] = bitcast %struct.float16x8x2_t* %agg.result to i8*
-// CHECK: [[TMP13:%.*]] = bitcast %struct.float16x8x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP12]], i8* [[TMP13]], i32 32, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD2Q_LANE_V:%.*]] = call { <8 x i16>, <8 x i16>
float16x8x2_t test_vld2q_lane_f16(float16_t const * a, float16x8x2_t b) {
return vld2q_lane_f16(a, b, 7);
}
-// CHECK-LABEL: define void @test_vld2q_lane_f32(%struct.float32x4x2_t* noalias sret %agg.result, float* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld2q_lane_f32(
// CHECK: [[B:%.*]] = alloca %struct.float32x4x2_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.float32x4x2_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.float32x4x2_t, align 16
@@ -5580,18 +4995,12 @@ float16x8x2_t test_vld2q_lane_f16(float16_t const * a, float16x8x2_t b) {
// CHECK: [[TMP8:%.*]] = bitcast <4 x float> [[TMP7]] to <16 x i8>
// CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x float>
// CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP8]] to <4 x float>
-// CHECK: [[VLD2Q_LANE_V:%.*]] = call { <4 x float>, <4 x float> } @llvm.arm.neon.vld2lane.v4f32.p0i8(i8* [[TMP4]], <4 x float> [[TMP9]], <4 x float> [[TMP10]], i32 3, i32 4)
-// CHECK: [[TMP11:%.*]] = bitcast i8* [[TMP3]] to { <4 x float>, <4 x float> }*
-// CHECK: store { <4 x float>, <4 x float> } [[VLD2Q_LANE_V]], { <4 x float>, <4 x float> }* [[TMP11]]
-// CHECK: [[TMP12:%.*]] = bitcast %struct.float32x4x2_t* %agg.result to i8*
-// CHECK: [[TMP13:%.*]] = bitcast %struct.float32x4x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP12]], i8* [[TMP13]], i32 32, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD2Q_LANE_V:%.*]] = call { <4 x float>, <4 x float>
float32x4x2_t test_vld2q_lane_f32(float32_t const * a, float32x4x2_t b) {
return vld2q_lane_f32(a, b, 3);
}
-// CHECK-LABEL: define void @test_vld2q_lane_p16(%struct.poly16x8x2_t* noalias sret %agg.result, i16* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld2q_lane_p16(
// CHECK: [[B:%.*]] = alloca %struct.poly16x8x2_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.poly16x8x2_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.poly16x8x2_t, align 16
@@ -5613,18 +5022,12 @@ float32x4x2_t test_vld2q_lane_f32(float32_t const * a, float32x4x2_t b) {
// CHECK: [[TMP8:%.*]] = bitcast <8 x i16> [[TMP7]] to <16 x i8>
// CHECK: [[TMP9:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16>
// CHECK: [[TMP10:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16>
-// CHECK: [[VLD2Q_LANE_V:%.*]] = call { <8 x i16>, <8 x i16> } @llvm.arm.neon.vld2lane.v8i16.p0i8(i8* [[TMP4]], <8 x i16> [[TMP9]], <8 x i16> [[TMP10]], i32 7, i32 2)
-// CHECK: [[TMP11:%.*]] = bitcast i8* [[TMP3]] to { <8 x i16>, <8 x i16> }*
-// CHECK: store { <8 x i16>, <8 x i16> } [[VLD2Q_LANE_V]], { <8 x i16>, <8 x i16> }* [[TMP11]]
-// CHECK: [[TMP12:%.*]] = bitcast %struct.poly16x8x2_t* %agg.result to i8*
-// CHECK: [[TMP13:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP12]], i8* [[TMP13]], i32 32, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD2Q_LANE_V:%.*]] = call { <8 x i16>, <8 x i16>
poly16x8x2_t test_vld2q_lane_p16(poly16_t const * a, poly16x8x2_t b) {
return vld2q_lane_p16(a, b, 7);
}
-// CHECK-LABEL: define void @test_vld2_lane_u8(%struct.uint8x8x2_t* noalias sret %agg.result, i8* %a, [2 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld2_lane_u8(
// CHECK: [[B:%.*]] = alloca %struct.uint8x8x2_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.uint8x8x2_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.uint8x8x2_t, align 8
@@ -5641,18 +5044,12 @@ poly16x8x2_t test_vld2q_lane_p16(poly16_t const * a, poly16x8x2_t b) {
// 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]], i32 0, i32 1
// CHECK: [[TMP5:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX2]], align 8
-// CHECK: [[VLD2_LANE_V:%.*]] = call { <8 x i8>, <8 x i8> } @llvm.arm.neon.vld2lane.v8i8.p0i8(i8* %a, <8 x i8> [[TMP4]], <8 x i8> [[TMP5]], i32 7, i32 1)
-// CHECK: [[TMP6:%.*]] = bitcast i8* [[TMP3]] to { <8 x i8>, <8 x i8> }*
-// CHECK: store { <8 x i8>, <8 x i8> } [[VLD2_LANE_V]], { <8 x i8>, <8 x i8> }* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.uint8x8x2_t* %agg.result to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.uint8x8x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP7]], i8* [[TMP8]], i32 16, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD2_LANE_V:%.*]] = call { <8 x i8>, <8 x i8>
uint8x8x2_t test_vld2_lane_u8(uint8_t const * a, uint8x8x2_t b) {
return vld2_lane_u8(a, b, 7);
}
-// CHECK-LABEL: define void @test_vld2_lane_u16(%struct.uint16x4x2_t* noalias sret %agg.result, i16* %a, [2 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld2_lane_u16(
// CHECK: [[B:%.*]] = alloca %struct.uint16x4x2_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.uint16x4x2_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.uint16x4x2_t, align 8
@@ -5674,18 +5071,12 @@ uint8x8x2_t test_vld2_lane_u8(uint8_t const * a, uint8x8x2_t b) {
// CHECK: [[TMP8:%.*]] = bitcast <4 x i16> [[TMP7]] to <8 x i8>
// CHECK: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16>
// CHECK: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x i16>
-// CHECK: [[VLD2_LANE_V:%.*]] = call { <4 x i16>, <4 x i16> } @llvm.arm.neon.vld2lane.v4i16.p0i8(i8* [[TMP4]], <4 x i16> [[TMP9]], <4 x i16> [[TMP10]], i32 3, i32 2)
-// CHECK: [[TMP11:%.*]] = bitcast i8* [[TMP3]] to { <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16> } [[VLD2_LANE_V]], { <4 x i16>, <4 x i16> }* [[TMP11]]
-// CHECK: [[TMP12:%.*]] = bitcast %struct.uint16x4x2_t* %agg.result to i8*
-// CHECK: [[TMP13:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP12]], i8* [[TMP13]], i32 16, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD2_LANE_V:%.*]] = call { <4 x i16>, <4 x i16>
uint16x4x2_t test_vld2_lane_u16(uint16_t const * a, uint16x4x2_t b) {
return vld2_lane_u16(a, b, 3);
}
-// CHECK-LABEL: define void @test_vld2_lane_u32(%struct.uint32x2x2_t* noalias sret %agg.result, i32* %a, [2 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld2_lane_u32(
// CHECK: [[B:%.*]] = alloca %struct.uint32x2x2_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.uint32x2x2_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.uint32x2x2_t, align 8
@@ -5707,18 +5098,12 @@ uint16x4x2_t test_vld2_lane_u16(uint16_t const * a, uint16x4x2_t b) {
// CHECK: [[TMP8:%.*]] = bitcast <2 x i32> [[TMP7]] to <8 x i8>
// CHECK: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP6]] to <2 x i32>
// CHECK: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP8]] to <2 x i32>
-// CHECK: [[VLD2_LANE_V:%.*]] = call { <2 x i32>, <2 x i32> } @llvm.arm.neon.vld2lane.v2i32.p0i8(i8* [[TMP4]], <2 x i32> [[TMP9]], <2 x i32> [[TMP10]], i32 1, i32 4)
-// CHECK: [[TMP11:%.*]] = bitcast i8* [[TMP3]] to { <2 x i32>, <2 x i32> }*
-// CHECK: store { <2 x i32>, <2 x i32> } [[VLD2_LANE_V]], { <2 x i32>, <2 x i32> }* [[TMP11]]
-// CHECK: [[TMP12:%.*]] = bitcast %struct.uint32x2x2_t* %agg.result to i8*
-// CHECK: [[TMP13:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP12]], i8* [[TMP13]], i32 16, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD2_LANE_V:%.*]] = call { <2 x i32>, <2 x i32>
uint32x2x2_t test_vld2_lane_u32(uint32_t const * a, uint32x2x2_t b) {
return vld2_lane_u32(a, b, 1);
}
-// CHECK-LABEL: define void @test_vld2_lane_s8(%struct.int8x8x2_t* noalias sret %agg.result, i8* %a, [2 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld2_lane_s8(
// CHECK: [[B:%.*]] = alloca %struct.int8x8x2_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.int8x8x2_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.int8x8x2_t, align 8
@@ -5735,18 +5120,12 @@ uint32x2x2_t test_vld2_lane_u32(uint32_t const * a, uint32x2x2_t b) {
// 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]], i32 0, i32 1
// CHECK: [[TMP5:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX2]], align 8
-// CHECK: [[VLD2_LANE_V:%.*]] = call { <8 x i8>, <8 x i8> } @llvm.arm.neon.vld2lane.v8i8.p0i8(i8* %a, <8 x i8> [[TMP4]], <8 x i8> [[TMP5]], i32 7, i32 1)
-// CHECK: [[TMP6:%.*]] = bitcast i8* [[TMP3]] to { <8 x i8>, <8 x i8> }*
-// CHECK: store { <8 x i8>, <8 x i8> } [[VLD2_LANE_V]], { <8 x i8>, <8 x i8> }* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.int8x8x2_t* %agg.result to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.int8x8x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP7]], i8* [[TMP8]], i32 16, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD2_LANE_V:%.*]] = call { <8 x i8>, <8 x i8>
int8x8x2_t test_vld2_lane_s8(int8_t const * a, int8x8x2_t b) {
return vld2_lane_s8(a, b, 7);
}
-// CHECK-LABEL: define void @test_vld2_lane_s16(%struct.int16x4x2_t* noalias sret %agg.result, i16* %a, [2 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld2_lane_s16(
// CHECK: [[B:%.*]] = alloca %struct.int16x4x2_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.int16x4x2_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.int16x4x2_t, align 8
@@ -5768,18 +5147,12 @@ int8x8x2_t test_vld2_lane_s8(int8_t const * a, int8x8x2_t b) {
// CHECK: [[TMP8:%.*]] = bitcast <4 x i16> [[TMP7]] to <8 x i8>
// CHECK: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16>
// CHECK: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x i16>
-// CHECK: [[VLD2_LANE_V:%.*]] = call { <4 x i16>, <4 x i16> } @llvm.arm.neon.vld2lane.v4i16.p0i8(i8* [[TMP4]], <4 x i16> [[TMP9]], <4 x i16> [[TMP10]], i32 3, i32 2)
-// CHECK: [[TMP11:%.*]] = bitcast i8* [[TMP3]] to { <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16> } [[VLD2_LANE_V]], { <4 x i16>, <4 x i16> }* [[TMP11]]
-// CHECK: [[TMP12:%.*]] = bitcast %struct.int16x4x2_t* %agg.result to i8*
-// CHECK: [[TMP13:%.*]] = bitcast %struct.int16x4x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP12]], i8* [[TMP13]], i32 16, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD2_LANE_V:%.*]] = call { <4 x i16>, <4 x i16>
int16x4x2_t test_vld2_lane_s16(int16_t const * a, int16x4x2_t b) {
return vld2_lane_s16(a, b, 3);
}
-// CHECK-LABEL: define void @test_vld2_lane_s32(%struct.int32x2x2_t* noalias sret %agg.result, i32* %a, [2 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld2_lane_s32(
// CHECK: [[B:%.*]] = alloca %struct.int32x2x2_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.int32x2x2_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.int32x2x2_t, align 8
@@ -5801,18 +5174,12 @@ int16x4x2_t test_vld2_lane_s16(int16_t const * a, int16x4x2_t b) {
// CHECK: [[TMP8:%.*]] = bitcast <2 x i32> [[TMP7]] to <8 x i8>
// CHECK: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP6]] to <2 x i32>
// CHECK: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP8]] to <2 x i32>
-// CHECK: [[VLD2_LANE_V:%.*]] = call { <2 x i32>, <2 x i32> } @llvm.arm.neon.vld2lane.v2i32.p0i8(i8* [[TMP4]], <2 x i32> [[TMP9]], <2 x i32> [[TMP10]], i32 1, i32 4)
-// CHECK: [[TMP11:%.*]] = bitcast i8* [[TMP3]] to { <2 x i32>, <2 x i32> }*
-// CHECK: store { <2 x i32>, <2 x i32> } [[VLD2_LANE_V]], { <2 x i32>, <2 x i32> }* [[TMP11]]
-// CHECK: [[TMP12:%.*]] = bitcast %struct.int32x2x2_t* %agg.result to i8*
-// CHECK: [[TMP13:%.*]] = bitcast %struct.int32x2x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP12]], i8* [[TMP13]], i32 16, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD2_LANE_V:%.*]] = call { <2 x i32>, <2 x i32>
int32x2x2_t test_vld2_lane_s32(int32_t const * a, int32x2x2_t b) {
return vld2_lane_s32(a, b, 1);
}
-// CHECK-LABEL: define void @test_vld2_lane_f16(%struct.float16x4x2_t* noalias sret %agg.result, half* %a, [2 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld2_lane_f16(
// CHECK: [[B:%.*]] = alloca %struct.float16x4x2_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.float16x4x2_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.float16x4x2_t, align 8
@@ -5834,18 +5201,12 @@ int32x2x2_t test_vld2_lane_s32(int32_t const * a, int32x2x2_t b) {
// CHECK: [[TMP8:%.*]] = bitcast <4 x half> [[TMP7]] to <8 x i8>
// CHECK: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16>
// CHECK: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x i16>
-// CHECK: [[VLD2_LANE_V:%.*]] = call { <4 x i16>, <4 x i16> } @llvm.arm.neon.vld2lane.v4i16.p0i8(i8* [[TMP4]], <4 x i16> [[TMP9]], <4 x i16> [[TMP10]], i32 3, i32 2)
-// CHECK: [[TMP11:%.*]] = bitcast i8* [[TMP3]] to { <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16> } [[VLD2_LANE_V]], { <4 x i16>, <4 x i16> }* [[TMP11]]
-// CHECK: [[TMP12:%.*]] = bitcast %struct.float16x4x2_t* %agg.result to i8*
-// CHECK: [[TMP13:%.*]] = bitcast %struct.float16x4x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP12]], i8* [[TMP13]], i32 16, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD2_LANE_V:%.*]] = call { <4 x i16>, <4 x i16>
float16x4x2_t test_vld2_lane_f16(float16_t const * a, float16x4x2_t b) {
return vld2_lane_f16(a, b, 3);
}
-// CHECK-LABEL: define void @test_vld2_lane_f32(%struct.float32x2x2_t* noalias sret %agg.result, float* %a, [2 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld2_lane_f32(
// CHECK: [[B:%.*]] = alloca %struct.float32x2x2_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.float32x2x2_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.float32x2x2_t, align 8
@@ -5867,18 +5228,12 @@ float16x4x2_t test_vld2_lane_f16(float16_t const * a, float16x4x2_t b) {
// CHECK: [[TMP8:%.*]] = bitcast <2 x float> [[TMP7]] to <8 x i8>
// CHECK: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP6]] to <2 x float>
// CHECK: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP8]] to <2 x float>
-// CHECK: [[VLD2_LANE_V:%.*]] = call { <2 x float>, <2 x float> } @llvm.arm.neon.vld2lane.v2f32.p0i8(i8* [[TMP4]], <2 x float> [[TMP9]], <2 x float> [[TMP10]], i32 1, i32 4)
-// CHECK: [[TMP11:%.*]] = bitcast i8* [[TMP3]] to { <2 x float>, <2 x float> }*
-// CHECK: store { <2 x float>, <2 x float> } [[VLD2_LANE_V]], { <2 x float>, <2 x float> }* [[TMP11]]
-// CHECK: [[TMP12:%.*]] = bitcast %struct.float32x2x2_t* %agg.result to i8*
-// CHECK: [[TMP13:%.*]] = bitcast %struct.float32x2x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP12]], i8* [[TMP13]], i32 16, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD2_LANE_V:%.*]] = call { <2 x float>, <2 x float>
float32x2x2_t test_vld2_lane_f32(float32_t const * a, float32x2x2_t b) {
return vld2_lane_f32(a, b, 1);
}
-// CHECK-LABEL: define void @test_vld2_lane_p8(%struct.poly8x8x2_t* noalias sret %agg.result, i8* %a, [2 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld2_lane_p8(
// CHECK: [[B:%.*]] = alloca %struct.poly8x8x2_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.poly8x8x2_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.poly8x8x2_t, align 8
@@ -5895,18 +5250,12 @@ float32x2x2_t test_vld2_lane_f32(float32_t const * a, float32x2x2_t b) {
// 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]], i32 0, i32 1
// CHECK: [[TMP5:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX2]], align 8
-// CHECK: [[VLD2_LANE_V:%.*]] = call { <8 x i8>, <8 x i8> } @llvm.arm.neon.vld2lane.v8i8.p0i8(i8* %a, <8 x i8> [[TMP4]], <8 x i8> [[TMP5]], i32 7, i32 1)
-// CHECK: [[TMP6:%.*]] = bitcast i8* [[TMP3]] to { <8 x i8>, <8 x i8> }*
-// CHECK: store { <8 x i8>, <8 x i8> } [[VLD2_LANE_V]], { <8 x i8>, <8 x i8> }* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.poly8x8x2_t* %agg.result to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.poly8x8x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP7]], i8* [[TMP8]], i32 16, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD2_LANE_V:%.*]] = call { <8 x i8>, <8 x i8>
poly8x8x2_t test_vld2_lane_p8(poly8_t const * a, poly8x8x2_t b) {
return vld2_lane_p8(a, b, 7);
}
-// CHECK-LABEL: define void @test_vld2_lane_p16(%struct.poly16x4x2_t* noalias sret %agg.result, i16* %a, [2 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld2_lane_p16(
// CHECK: [[B:%.*]] = alloca %struct.poly16x4x2_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.poly16x4x2_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.poly16x4x2_t, align 8
@@ -5928,612 +5277,309 @@ poly8x8x2_t test_vld2_lane_p8(poly8_t const * a, poly8x8x2_t b) {
// CHECK: [[TMP8:%.*]] = bitcast <4 x i16> [[TMP7]] to <8 x i8>
// CHECK: [[TMP9:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16>
// CHECK: [[TMP10:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x i16>
-// CHECK: [[VLD2_LANE_V:%.*]] = call { <4 x i16>, <4 x i16> } @llvm.arm.neon.vld2lane.v4i16.p0i8(i8* [[TMP4]], <4 x i16> [[TMP9]], <4 x i16> [[TMP10]], i32 3, i32 2)
-// CHECK: [[TMP11:%.*]] = bitcast i8* [[TMP3]] to { <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16> } [[VLD2_LANE_V]], { <4 x i16>, <4 x i16> }* [[TMP11]]
-// CHECK: [[TMP12:%.*]] = bitcast %struct.poly16x4x2_t* %agg.result to i8*
-// CHECK: [[TMP13:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP12]], i8* [[TMP13]], i32 16, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD2_LANE_V:%.*]] = call { <4 x i16>, <4 x i16>
poly16x4x2_t test_vld2_lane_p16(poly16_t const * a, poly16x4x2_t b) {
return vld2_lane_p16(a, b, 3);
}
-
-// CHECK-LABEL: define void @test_vld3q_u8(%struct.uint8x16x3_t* noalias sret %agg.result, i8* %a) #0 {
+// CHECK-LABEL: @test_vld3q_u8(
// CHECK: [[__RET:%.*]] = alloca %struct.uint8x16x3_t, align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x3_t* [[__RET]] to i8*
-// CHECK: [[VLD3Q_V:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8> } @llvm.arm.neon.vld3.v16i8.p0i8(i8* %a, 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> } [[VLD3Q_V]], { <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x16x3_t* %agg.result to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x16x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP2]], i8* [[TMP3]], i32 48, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD3Q_V:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8>
uint8x16x3_t test_vld3q_u8(uint8_t const * a) {
return vld3q_u8(a);
}
-// CHECK-LABEL: define void @test_vld3q_u16(%struct.uint16x8x3_t* noalias sret %agg.result, i16* %a) #0 {
+// CHECK-LABEL: @test_vld3q_u16(
// 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: [[VLD3Q_V:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16> } @llvm.arm.neon.vld3.v8i16.p0i8(i8* [[TMP1]], i32 2)
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16>, <8 x i16> }*
-// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16> } [[VLD3Q_V]], { <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint16x8x3_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint16x8x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 48, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD3Q_V:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>
uint16x8x3_t test_vld3q_u16(uint16_t const * a) {
return vld3q_u16(a);
}
-// CHECK-LABEL: define void @test_vld3q_u32(%struct.uint32x4x3_t* noalias sret %agg.result, i32* %a) #0 {
+// CHECK-LABEL: @test_vld3q_u32(
// 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: [[VLD3Q_V:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32> } @llvm.arm.neon.vld3.v4i32.p0i8(i8* [[TMP1]], i32 4)
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to { <4 x i32>, <4 x i32>, <4 x i32> }*
-// CHECK: store { <4 x i32>, <4 x i32>, <4 x i32> } [[VLD3Q_V]], { <4 x i32>, <4 x i32>, <4 x i32> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint32x4x3_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint32x4x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 48, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD3Q_V:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32>
uint32x4x3_t test_vld3q_u32(uint32_t const * a) {
return vld3q_u32(a);
}
-// CHECK-LABEL: define void @test_vld3q_s8(%struct.int8x16x3_t* noalias sret %agg.result, i8* %a) #0 {
+// CHECK-LABEL: @test_vld3q_s8(
// CHECK: [[__RET:%.*]] = alloca %struct.int8x16x3_t, align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x3_t* [[__RET]] to i8*
-// CHECK: [[VLD3Q_V:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8> } @llvm.arm.neon.vld3.v16i8.p0i8(i8* %a, 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> } [[VLD3Q_V]], { <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x16x3_t* %agg.result to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x16x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP2]], i8* [[TMP3]], i32 48, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD3Q_V:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8>
int8x16x3_t test_vld3q_s8(int8_t const * a) {
return vld3q_s8(a);
}
-// CHECK-LABEL: define void @test_vld3q_s16(%struct.int16x8x3_t* noalias sret %agg.result, i16* %a) #0 {
+// CHECK-LABEL: @test_vld3q_s16(
// 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: [[VLD3Q_V:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16> } @llvm.arm.neon.vld3.v8i16.p0i8(i8* [[TMP1]], i32 2)
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16>, <8 x i16> }*
-// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16> } [[VLD3Q_V]], { <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int16x8x3_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int16x8x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 48, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD3Q_V:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>
int16x8x3_t test_vld3q_s16(int16_t const * a) {
return vld3q_s16(a);
}
-// CHECK-LABEL: define void @test_vld3q_s32(%struct.int32x4x3_t* noalias sret %agg.result, i32* %a) #0 {
+// CHECK-LABEL: @test_vld3q_s32(
// 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: [[VLD3Q_V:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32> } @llvm.arm.neon.vld3.v4i32.p0i8(i8* [[TMP1]], i32 4)
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to { <4 x i32>, <4 x i32>, <4 x i32> }*
-// CHECK: store { <4 x i32>, <4 x i32>, <4 x i32> } [[VLD3Q_V]], { <4 x i32>, <4 x i32>, <4 x i32> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int32x4x3_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int32x4x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 48, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD3Q_V:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32>
int32x4x3_t test_vld3q_s32(int32_t const * a) {
return vld3q_s32(a);
}
-// CHECK-LABEL: define void @test_vld3q_f16(%struct.float16x8x3_t* noalias sret %agg.result, half* %a) #0 {
+// CHECK-LABEL: @test_vld3q_f16(
// 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: [[VLD3Q_V:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16> } @llvm.arm.neon.vld3.v8i16.p0i8(i8* [[TMP1]], i32 2)
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16>, <8 x i16> }*
-// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16> } [[VLD3Q_V]], { <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.float16x8x3_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x8x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 48, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD3Q_V:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>
float16x8x3_t test_vld3q_f16(float16_t const * a) {
return vld3q_f16(a);
}
-// CHECK-LABEL: define void @test_vld3q_f32(%struct.float32x4x3_t* noalias sret %agg.result, float* %a) #0 {
+// CHECK-LABEL: @test_vld3q_f32(
// 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: [[VLD3Q_V:%.*]] = call { <4 x float>, <4 x float>, <4 x float> } @llvm.arm.neon.vld3.v4f32.p0i8(i8* [[TMP1]], i32 4)
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to { <4 x float>, <4 x float>, <4 x float> }*
-// CHECK: store { <4 x float>, <4 x float>, <4 x float> } [[VLD3Q_V]], { <4 x float>, <4 x float>, <4 x float> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.float32x4x3_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.float32x4x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 48, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD3Q_V:%.*]] = call { <4 x float>, <4 x float>, <4 x float>
float32x4x3_t test_vld3q_f32(float32_t const * a) {
return vld3q_f32(a);
}
-// CHECK-LABEL: define void @test_vld3q_p8(%struct.poly8x16x3_t* noalias sret %agg.result, i8* %a) #0 {
+// CHECK-LABEL: @test_vld3q_p8(
// CHECK: [[__RET:%.*]] = alloca %struct.poly8x16x3_t, align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x3_t* [[__RET]] to i8*
-// CHECK: [[VLD3Q_V:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8> } @llvm.arm.neon.vld3.v16i8.p0i8(i8* %a, 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> } [[VLD3Q_V]], { <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x16x3_t* %agg.result to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x16x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP2]], i8* [[TMP3]], i32 48, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD3Q_V:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8>
poly8x16x3_t test_vld3q_p8(poly8_t const * a) {
return vld3q_p8(a);
}
-// CHECK-LABEL: define void @test_vld3q_p16(%struct.poly16x8x3_t* noalias sret %agg.result, i16* %a) #0 {
+// CHECK-LABEL: @test_vld3q_p16(
// 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: [[VLD3Q_V:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16> } @llvm.arm.neon.vld3.v8i16.p0i8(i8* [[TMP1]], i32 2)
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to { <8 x i16>, <8 x i16>, <8 x i16> }*
-// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16> } [[VLD3Q_V]], { <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.poly16x8x3_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.poly16x8x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 48, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD3Q_V:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>
poly16x8x3_t test_vld3q_p16(poly16_t const * a) {
return vld3q_p16(a);
}
-// CHECK-LABEL: define void @test_vld3_u8(%struct.uint8x8x3_t* noalias sret %agg.result, i8* %a) #0 {
+// CHECK-LABEL: @test_vld3_u8(
// CHECK: [[__RET:%.*]] = alloca %struct.uint8x8x3_t, align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x3_t* [[__RET]] to i8*
-// CHECK: [[VLD3_V:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8> } @llvm.arm.neon.vld3.v8i8.p0i8(i8* %a, 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_V]], { <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x8x3_t* %agg.result to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x8x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP2]], i8* [[TMP3]], i32 24, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD3_V:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>
uint8x8x3_t test_vld3_u8(uint8_t const * a) {
return vld3_u8(a);
}
-// CHECK-LABEL: define void @test_vld3_u16(%struct.uint16x4x3_t* noalias sret %agg.result, i16* %a) #0 {
+// CHECK-LABEL: @test_vld3_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: [[VLD3_V:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.arm.neon.vld3.v4i16.p0i8(i8* [[TMP1]], i32 2)
-// CHECK: [[TMP2:%.*]] = 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_V]], { <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint16x4x3_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint16x4x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 24, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD3_V:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>
uint16x4x3_t test_vld3_u16(uint16_t const * a) {
return vld3_u16(a);
}
-// CHECK-LABEL: define void @test_vld3_u32(%struct.uint32x2x3_t* noalias sret %agg.result, i32* %a) #0 {
+// CHECK-LABEL: @test_vld3_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: [[VLD3_V:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32> } @llvm.arm.neon.vld3.v2i32.p0i8(i8* [[TMP1]], i32 4)
-// CHECK: [[TMP2:%.*]] = 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_V]], { <2 x i32>, <2 x i32>, <2 x i32> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint32x2x3_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint32x2x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 24, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD3_V:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32>
uint32x2x3_t test_vld3_u32(uint32_t const * a) {
return vld3_u32(a);
}
-// CHECK-LABEL: define void @test_vld3_u64(%struct.uint64x1x3_t* noalias sret %agg.result, i64* %a) #0 {
+// CHECK-LABEL: @test_vld3_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: [[VLD3_V:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64> } @llvm.arm.neon.vld3.v1i64.p0i8(i8* [[TMP1]], i32 4)
-// CHECK: [[TMP2:%.*]] = 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_V]], { <1 x i64>, <1 x i64>, <1 x i64> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint64x1x3_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint64x1x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 24, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD3_V:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64>
uint64x1x3_t test_vld3_u64(uint64_t const * a) {
return vld3_u64(a);
}
-// CHECK-LABEL: define void @test_vld3_s8(%struct.int8x8x3_t* noalias sret %agg.result, i8* %a) #0 {
+// CHECK-LABEL: @test_vld3_s8(
// CHECK: [[__RET:%.*]] = alloca %struct.int8x8x3_t, align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x3_t* [[__RET]] to i8*
-// CHECK: [[VLD3_V:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8> } @llvm.arm.neon.vld3.v8i8.p0i8(i8* %a, 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_V]], { <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x8x3_t* %agg.result to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x8x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP2]], i8* [[TMP3]], i32 24, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD3_V:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>
int8x8x3_t test_vld3_s8(int8_t const * a) {
return vld3_s8(a);
}
-// CHECK-LABEL: define void @test_vld3_s16(%struct.int16x4x3_t* noalias sret %agg.result, i16* %a) #0 {
+// CHECK-LABEL: @test_vld3_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: [[VLD3_V:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.arm.neon.vld3.v4i16.p0i8(i8* [[TMP1]], i32 2)
-// CHECK: [[TMP2:%.*]] = 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_V]], { <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int16x4x3_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int16x4x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 24, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD3_V:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>
int16x4x3_t test_vld3_s16(int16_t const * a) {
return vld3_s16(a);
}
-// CHECK-LABEL: define void @test_vld3_s32(%struct.int32x2x3_t* noalias sret %agg.result, i32* %a) #0 {
+// CHECK-LABEL: @test_vld3_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: [[VLD3_V:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32> } @llvm.arm.neon.vld3.v2i32.p0i8(i8* [[TMP1]], i32 4)
-// CHECK: [[TMP2:%.*]] = 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_V]], { <2 x i32>, <2 x i32>, <2 x i32> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int32x2x3_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int32x2x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 24, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD3_V:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32>
int32x2x3_t test_vld3_s32(int32_t const * a) {
return vld3_s32(a);
}
-// CHECK-LABEL: define void @test_vld3_s64(%struct.int64x1x3_t* noalias sret %agg.result, i64* %a) #0 {
+// CHECK-LABEL: @test_vld3_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: [[VLD3_V:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64> } @llvm.arm.neon.vld3.v1i64.p0i8(i8* [[TMP1]], i32 4)
-// CHECK: [[TMP2:%.*]] = 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_V]], { <1 x i64>, <1 x i64>, <1 x i64> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int64x1x3_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int64x1x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 24, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD3_V:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64>
int64x1x3_t test_vld3_s64(int64_t const * a) {
return vld3_s64(a);
}
-// CHECK-LABEL: define void @test_vld3_f16(%struct.float16x4x3_t* noalias sret %agg.result, half* %a) #0 {
+// CHECK-LABEL: @test_vld3_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: [[VLD3_V:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.arm.neon.vld3.v4i16.p0i8(i8* [[TMP1]], i32 2)
-// CHECK: [[TMP2:%.*]] = 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_V]], { <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.float16x4x3_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x4x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 24, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD3_V:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>
float16x4x3_t test_vld3_f16(float16_t const * a) {
return vld3_f16(a);
}
-// CHECK-LABEL: define void @test_vld3_f32(%struct.float32x2x3_t* noalias sret %agg.result, float* %a) #0 {
+// CHECK-LABEL: @test_vld3_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: [[VLD3_V:%.*]] = call { <2 x float>, <2 x float>, <2 x float> } @llvm.arm.neon.vld3.v2f32.p0i8(i8* [[TMP1]], i32 4)
-// CHECK: [[TMP2:%.*]] = 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_V]], { <2 x float>, <2 x float>, <2 x float> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.float32x2x3_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.float32x2x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 24, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD3_V:%.*]] = call { <2 x float>, <2 x float>, <2 x float>
float32x2x3_t test_vld3_f32(float32_t const * a) {
return vld3_f32(a);
}
-// CHECK-LABEL: define void @test_vld3_p8(%struct.poly8x8x3_t* noalias sret %agg.result, i8* %a) #0 {
+// CHECK-LABEL: @test_vld3_p8(
// CHECK: [[__RET:%.*]] = alloca %struct.poly8x8x3_t, align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x3_t* [[__RET]] to i8*
-// CHECK: [[VLD3_V:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8> } @llvm.arm.neon.vld3.v8i8.p0i8(i8* %a, 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_V]], { <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x8x3_t* %agg.result to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x8x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP2]], i8* [[TMP3]], i32 24, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD3_V:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>
poly8x8x3_t test_vld3_p8(poly8_t const * a) {
return vld3_p8(a);
}
-// CHECK-LABEL: define void @test_vld3_p16(%struct.poly16x4x3_t* noalias sret %agg.result, i16* %a) #0 {
+// CHECK-LABEL: @test_vld3_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: [[VLD3_V:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.arm.neon.vld3.v4i16.p0i8(i8* [[TMP1]], i32 2)
-// CHECK: [[TMP2:%.*]] = 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_V]], { <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.poly16x4x3_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.poly16x4x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 24, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD3_V:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>
poly16x4x3_t test_vld3_p16(poly16_t const * a) {
return vld3_p16(a);
}
-
-// CHECK-LABEL: define void @test_vld3_dup_u8(%struct.uint8x8x3_t* noalias sret %agg.result, i8* %a) #0 {
+// 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> } @llvm.arm.neon.vld3lane.v8i8.p0i8(i8* %a, <8 x i8> undef, <8 x i8> undef, <8 x i8> undef, i32 0, i32 1)
-// CHECK: [[TMP1:%.*]] = extractvalue { <8 x i8>, <8 x i8>, <8 x i8> } [[VLD_DUP]], 0
-// CHECK: [[LANE:%.*]] = shufflevector <8 x i8> [[TMP1]], <8 x i8> [[TMP1]], <8 x i32> zeroinitializer
-// CHECK: [[TMP2:%.*]] = insertvalue { <8 x i8>, <8 x i8>, <8 x i8> } [[VLD_DUP]], <8 x i8> [[LANE]], 0
-// CHECK: [[TMP3:%.*]] = extractvalue { <8 x i8>, <8 x i8>, <8 x i8> } [[TMP2]], 1
-// CHECK: [[LANE1:%.*]] = shufflevector <8 x i8> [[TMP3]], <8 x i8> [[TMP3]], <8 x i32> zeroinitializer
-// CHECK: [[TMP4:%.*]] = insertvalue { <8 x i8>, <8 x i8>, <8 x i8> } [[TMP2]], <8 x i8> [[LANE1]], 1
-// CHECK: [[TMP5:%.*]] = extractvalue { <8 x i8>, <8 x i8>, <8 x i8> } [[TMP4]], 2
-// CHECK: [[LANE2:%.*]] = shufflevector <8 x i8> [[TMP5]], <8 x i8> [[TMP5]], <8 x i32> zeroinitializer
-// CHECK: [[TMP6:%.*]] = insertvalue { <8 x i8>, <8 x i8>, <8 x i8> } [[TMP4]], <8 x i8> [[LANE2]], 2
-// CHECK: [[TMP7:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8>, <8 x i8> }*
-// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8> } [[TMP6]], { <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP7]]
-// CHECK: [[TMP8:%.*]] = bitcast %struct.uint8x8x3_t* %agg.result to i8*
-// CHECK: [[TMP9:%.*]] = bitcast %struct.uint8x8x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP8]], i8* [[TMP9]], i32 24, i32 8, i1 false)
-// CHECK: ret void
+// 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: define void @test_vld3_dup_u16(%struct.uint16x4x3_t* noalias sret %agg.result, i16* %a) #0 {
+// 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> } @llvm.arm.neon.vld3lane.v4i16.p0i8(i8* [[TMP1]], <4 x i16> undef, <4 x i16> undef, <4 x i16> undef, i32 0, i32 2)
-// CHECK: [[TMP2:%.*]] = extractvalue { <4 x i16>, <4 x i16>, <4 x i16> } [[VLD_DUP]], 0
-// CHECK: [[LANE:%.*]] = shufflevector <4 x i16> [[TMP2]], <4 x i16> [[TMP2]], <4 x i32> zeroinitializer
-// CHECK: [[TMP3:%.*]] = insertvalue { <4 x i16>, <4 x i16>, <4 x i16> } [[VLD_DUP]], <4 x i16> [[LANE]], 0
-// CHECK: [[TMP4:%.*]] = extractvalue { <4 x i16>, <4 x i16>, <4 x i16> } [[TMP3]], 1
-// CHECK: [[LANE1:%.*]] = shufflevector <4 x i16> [[TMP4]], <4 x i16> [[TMP4]], <4 x i32> zeroinitializer
-// CHECK: [[TMP5:%.*]] = insertvalue { <4 x i16>, <4 x i16>, <4 x i16> } [[TMP3]], <4 x i16> [[LANE1]], 1
-// CHECK: [[TMP6:%.*]] = extractvalue { <4 x i16>, <4 x i16>, <4 x i16> } [[TMP5]], 2
-// CHECK: [[LANE2:%.*]] = shufflevector <4 x i16> [[TMP6]], <4 x i16> [[TMP6]], <4 x i32> zeroinitializer
-// CHECK: [[TMP7:%.*]] = insertvalue { <4 x i16>, <4 x i16>, <4 x i16> } [[TMP5]], <4 x i16> [[LANE2]], 2
-// CHECK: [[TMP8:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16> } [[TMP7]], { <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP8]]
-// CHECK: [[TMP9:%.*]] = bitcast %struct.uint16x4x3_t* %agg.result to i8*
-// CHECK: [[TMP10:%.*]] = bitcast %struct.uint16x4x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP9]], i8* [[TMP10]], i32 24, i32 8, i1 false)
-// CHECK: ret void
+// 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: define void @test_vld3_dup_u32(%struct.uint32x2x3_t* noalias sret %agg.result, i32* %a) #0 {
+// 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> } @llvm.arm.neon.vld3lane.v2i32.p0i8(i8* [[TMP1]], <2 x i32> undef, <2 x i32> undef, <2 x i32> undef, i32 0, i32 4)
-// CHECK: [[TMP2:%.*]] = extractvalue { <2 x i32>, <2 x i32>, <2 x i32> } [[VLD_DUP]], 0
-// CHECK: [[LANE:%.*]] = shufflevector <2 x i32> [[TMP2]], <2 x i32> [[TMP2]], <2 x i32> zeroinitializer
-// CHECK: [[TMP3:%.*]] = insertvalue { <2 x i32>, <2 x i32>, <2 x i32> } [[VLD_DUP]], <2 x i32> [[LANE]], 0
-// CHECK: [[TMP4:%.*]] = extractvalue { <2 x i32>, <2 x i32>, <2 x i32> } [[TMP3]], 1
-// CHECK: [[LANE1:%.*]] = shufflevector <2 x i32> [[TMP4]], <2 x i32> [[TMP4]], <2 x i32> zeroinitializer
-// CHECK: [[TMP5:%.*]] = insertvalue { <2 x i32>, <2 x i32>, <2 x i32> } [[TMP3]], <2 x i32> [[LANE1]], 1
-// CHECK: [[TMP6:%.*]] = extractvalue { <2 x i32>, <2 x i32>, <2 x i32> } [[TMP5]], 2
-// CHECK: [[LANE2:%.*]] = shufflevector <2 x i32> [[TMP6]], <2 x i32> [[TMP6]], <2 x i32> zeroinitializer
-// CHECK: [[TMP7:%.*]] = insertvalue { <2 x i32>, <2 x i32>, <2 x i32> } [[TMP5]], <2 x i32> [[LANE2]], 2
-// CHECK: [[TMP8:%.*]] = bitcast i8* [[TMP0]] to { <2 x i32>, <2 x i32>, <2 x i32> }*
-// CHECK: store { <2 x i32>, <2 x i32>, <2 x i32> } [[TMP7]], { <2 x i32>, <2 x i32>, <2 x i32> }* [[TMP8]]
-// CHECK: [[TMP9:%.*]] = bitcast %struct.uint32x2x3_t* %agg.result to i8*
-// CHECK: [[TMP10:%.*]] = bitcast %struct.uint32x2x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP9]], i8* [[TMP10]], i32 24, i32 8, i1 false)
-// CHECK: ret void
+// 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: define void @test_vld3_dup_u64(%struct.uint64x1x3_t* noalias sret %agg.result, i64* %a) #0 {
+// 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> } @llvm.arm.neon.vld3.v1i64.p0i8(i8* [[TMP1]], i32 4)
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to { <1 x i64>, <1 x i64>, <1 x i64> }*
-// CHECK: store { <1 x i64>, <1 x i64>, <1 x i64> } [[VLD_DUP]], { <1 x i64>, <1 x i64>, <1 x i64> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint64x1x3_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint64x1x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 24, i32 8, i1 false)
-// CHECK: ret void
+// 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: define void @test_vld3_dup_s8(%struct.int8x8x3_t* noalias sret %agg.result, i8* %a) #0 {
+// 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> } @llvm.arm.neon.vld3lane.v8i8.p0i8(i8* %a, <8 x i8> undef, <8 x i8> undef, <8 x i8> undef, i32 0, i32 1)
-// CHECK: [[TMP1:%.*]] = extractvalue { <8 x i8>, <8 x i8>, <8 x i8> } [[VLD_DUP]], 0
-// CHECK: [[LANE:%.*]] = shufflevector <8 x i8> [[TMP1]], <8 x i8> [[TMP1]], <8 x i32> zeroinitializer
-// CHECK: [[TMP2:%.*]] = insertvalue { <8 x i8>, <8 x i8>, <8 x i8> } [[VLD_DUP]], <8 x i8> [[LANE]], 0
-// CHECK: [[TMP3:%.*]] = extractvalue { <8 x i8>, <8 x i8>, <8 x i8> } [[TMP2]], 1
-// CHECK: [[LANE1:%.*]] = shufflevector <8 x i8> [[TMP3]], <8 x i8> [[TMP3]], <8 x i32> zeroinitializer
-// CHECK: [[TMP4:%.*]] = insertvalue { <8 x i8>, <8 x i8>, <8 x i8> } [[TMP2]], <8 x i8> [[LANE1]], 1
-// CHECK: [[TMP5:%.*]] = extractvalue { <8 x i8>, <8 x i8>, <8 x i8> } [[TMP4]], 2
-// CHECK: [[LANE2:%.*]] = shufflevector <8 x i8> [[TMP5]], <8 x i8> [[TMP5]], <8 x i32> zeroinitializer
-// CHECK: [[TMP6:%.*]] = insertvalue { <8 x i8>, <8 x i8>, <8 x i8> } [[TMP4]], <8 x i8> [[LANE2]], 2
-// CHECK: [[TMP7:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8>, <8 x i8> }*
-// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8> } [[TMP6]], { <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP7]]
-// CHECK: [[TMP8:%.*]] = bitcast %struct.int8x8x3_t* %agg.result to i8*
-// CHECK: [[TMP9:%.*]] = bitcast %struct.int8x8x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP8]], i8* [[TMP9]], i32 24, i32 8, i1 false)
-// CHECK: ret void
+// 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: define void @test_vld3_dup_s16(%struct.int16x4x3_t* noalias sret %agg.result, i16* %a) #0 {
+// 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> } @llvm.arm.neon.vld3lane.v4i16.p0i8(i8* [[TMP1]], <4 x i16> undef, <4 x i16> undef, <4 x i16> undef, i32 0, i32 2)
-// CHECK: [[TMP2:%.*]] = extractvalue { <4 x i16>, <4 x i16>, <4 x i16> } [[VLD_DUP]], 0
-// CHECK: [[LANE:%.*]] = shufflevector <4 x i16> [[TMP2]], <4 x i16> [[TMP2]], <4 x i32> zeroinitializer
-// CHECK: [[TMP3:%.*]] = insertvalue { <4 x i16>, <4 x i16>, <4 x i16> } [[VLD_DUP]], <4 x i16> [[LANE]], 0
-// CHECK: [[TMP4:%.*]] = extractvalue { <4 x i16>, <4 x i16>, <4 x i16> } [[TMP3]], 1
-// CHECK: [[LANE1:%.*]] = shufflevector <4 x i16> [[TMP4]], <4 x i16> [[TMP4]], <4 x i32> zeroinitializer
-// CHECK: [[TMP5:%.*]] = insertvalue { <4 x i16>, <4 x i16>, <4 x i16> } [[TMP3]], <4 x i16> [[LANE1]], 1
-// CHECK: [[TMP6:%.*]] = extractvalue { <4 x i16>, <4 x i16>, <4 x i16> } [[TMP5]], 2
-// CHECK: [[LANE2:%.*]] = shufflevector <4 x i16> [[TMP6]], <4 x i16> [[TMP6]], <4 x i32> zeroinitializer
-// CHECK: [[TMP7:%.*]] = insertvalue { <4 x i16>, <4 x i16>, <4 x i16> } [[TMP5]], <4 x i16> [[LANE2]], 2
-// CHECK: [[TMP8:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16> } [[TMP7]], { <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP8]]
-// CHECK: [[TMP9:%.*]] = bitcast %struct.int16x4x3_t* %agg.result to i8*
-// CHECK: [[TMP10:%.*]] = bitcast %struct.int16x4x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP9]], i8* [[TMP10]], i32 24, i32 8, i1 false)
-// CHECK: ret void
+// 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: define void @test_vld3_dup_s32(%struct.int32x2x3_t* noalias sret %agg.result, i32* %a) #0 {
+// 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> } @llvm.arm.neon.vld3lane.v2i32.p0i8(i8* [[TMP1]], <2 x i32> undef, <2 x i32> undef, <2 x i32> undef, i32 0, i32 4)
-// CHECK: [[TMP2:%.*]] = extractvalue { <2 x i32>, <2 x i32>, <2 x i32> } [[VLD_DUP]], 0
-// CHECK: [[LANE:%.*]] = shufflevector <2 x i32> [[TMP2]], <2 x i32> [[TMP2]], <2 x i32> zeroinitializer
-// CHECK: [[TMP3:%.*]] = insertvalue { <2 x i32>, <2 x i32>, <2 x i32> } [[VLD_DUP]], <2 x i32> [[LANE]], 0
-// CHECK: [[TMP4:%.*]] = extractvalue { <2 x i32>, <2 x i32>, <2 x i32> } [[TMP3]], 1
-// CHECK: [[LANE1:%.*]] = shufflevector <2 x i32> [[TMP4]], <2 x i32> [[TMP4]], <2 x i32> zeroinitializer
-// CHECK: [[TMP5:%.*]] = insertvalue { <2 x i32>, <2 x i32>, <2 x i32> } [[TMP3]], <2 x i32> [[LANE1]], 1
-// CHECK: [[TMP6:%.*]] = extractvalue { <2 x i32>, <2 x i32>, <2 x i32> } [[TMP5]], 2
-// CHECK: [[LANE2:%.*]] = shufflevector <2 x i32> [[TMP6]], <2 x i32> [[TMP6]], <2 x i32> zeroinitializer
-// CHECK: [[TMP7:%.*]] = insertvalue { <2 x i32>, <2 x i32>, <2 x i32> } [[TMP5]], <2 x i32> [[LANE2]], 2
-// CHECK: [[TMP8:%.*]] = bitcast i8* [[TMP0]] to { <2 x i32>, <2 x i32>, <2 x i32> }*
-// CHECK: store { <2 x i32>, <2 x i32>, <2 x i32> } [[TMP7]], { <2 x i32>, <2 x i32>, <2 x i32> }* [[TMP8]]
-// CHECK: [[TMP9:%.*]] = bitcast %struct.int32x2x3_t* %agg.result to i8*
-// CHECK: [[TMP10:%.*]] = bitcast %struct.int32x2x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP9]], i8* [[TMP10]], i32 24, i32 8, i1 false)
-// CHECK: ret void
+// 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: define void @test_vld3_dup_s64(%struct.int64x1x3_t* noalias sret %agg.result, i64* %a) #0 {
+// 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> } @llvm.arm.neon.vld3.v1i64.p0i8(i8* [[TMP1]], i32 4)
-// CHECK: [[TMP2:%.*]] = bitcast i8* [[TMP0]] to { <1 x i64>, <1 x i64>, <1 x i64> }*
-// CHECK: store { <1 x i64>, <1 x i64>, <1 x i64> } [[VLD_DUP]], { <1 x i64>, <1 x i64>, <1 x i64> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int64x1x3_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int64x1x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 24, i32 8, i1 false)
-// CHECK: ret void
+// 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: define void @test_vld3_dup_f16(%struct.float16x4x3_t* noalias sret %agg.result, half* %a) #0 {
+// 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> } @llvm.arm.neon.vld3lane.v4i16.p0i8(i8* [[TMP1]], <4 x i16> undef, <4 x i16> undef, <4 x i16> undef, i32 0, i32 2)
-// CHECK: [[TMP2:%.*]] = extractvalue { <4 x i16>, <4 x i16>, <4 x i16> } [[VLD_DUP]], 0
-// CHECK: [[LANE:%.*]] = shufflevector <4 x i16> [[TMP2]], <4 x i16> [[TMP2]], <4 x i32> zeroinitializer
-// CHECK: [[TMP3:%.*]] = insertvalue { <4 x i16>, <4 x i16>, <4 x i16> } [[VLD_DUP]], <4 x i16> [[LANE]], 0
-// CHECK: [[TMP4:%.*]] = extractvalue { <4 x i16>, <4 x i16>, <4 x i16> } [[TMP3]], 1
-// CHECK: [[LANE1:%.*]] = shufflevector <4 x i16> [[TMP4]], <4 x i16> [[TMP4]], <4 x i32> zeroinitializer
-// CHECK: [[TMP5:%.*]] = insertvalue { <4 x i16>, <4 x i16>, <4 x i16> } [[TMP3]], <4 x i16> [[LANE1]], 1
-// CHECK: [[TMP6:%.*]] = extractvalue { <4 x i16>, <4 x i16>, <4 x i16> } [[TMP5]], 2
-// CHECK: [[LANE2:%.*]] = shufflevector <4 x i16> [[TMP6]], <4 x i16> [[TMP6]], <4 x i32> zeroinitializer
-// CHECK: [[TMP7:%.*]] = insertvalue { <4 x i16>, <4 x i16>, <4 x i16> } [[TMP5]], <4 x i16> [[LANE2]], 2
-// CHECK: [[TMP8:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16> } [[TMP7]], { <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP8]]
-// CHECK: [[TMP9:%.*]] = bitcast %struct.float16x4x3_t* %agg.result to i8*
-// CHECK: [[TMP10:%.*]] = bitcast %struct.float16x4x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP9]], i8* [[TMP10]], i32 24, i32 8, i1 false)
-// CHECK: ret void
+// 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: define void @test_vld3_dup_f32(%struct.float32x2x3_t* noalias sret %agg.result, float* %a) #0 {
+// 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> } @llvm.arm.neon.vld3lane.v2f32.p0i8(i8* [[TMP1]], <2 x float> undef, <2 x float> undef, <2 x float> undef, i32 0, i32 4)
-// CHECK: [[TMP2:%.*]] = extractvalue { <2 x float>, <2 x float>, <2 x float> } [[VLD_DUP]], 0
-// CHECK: [[LANE:%.*]] = shufflevector <2 x float> [[TMP2]], <2 x float> [[TMP2]], <2 x i32> zeroinitializer
-// CHECK: [[TMP3:%.*]] = insertvalue { <2 x float>, <2 x float>, <2 x float> } [[VLD_DUP]], <2 x float> [[LANE]], 0
-// CHECK: [[TMP4:%.*]] = extractvalue { <2 x float>, <2 x float>, <2 x float> } [[TMP3]], 1
-// CHECK: [[LANE1:%.*]] = shufflevector <2 x float> [[TMP4]], <2 x float> [[TMP4]], <2 x i32> zeroinitializer
-// CHECK: [[TMP5:%.*]] = insertvalue { <2 x float>, <2 x float>, <2 x float> } [[TMP3]], <2 x float> [[LANE1]], 1
-// CHECK: [[TMP6:%.*]] = extractvalue { <2 x float>, <2 x float>, <2 x float> } [[TMP5]], 2
-// CHECK: [[LANE2:%.*]] = shufflevector <2 x float> [[TMP6]], <2 x float> [[TMP6]], <2 x i32> zeroinitializer
-// CHECK: [[TMP7:%.*]] = insertvalue { <2 x float>, <2 x float>, <2 x float> } [[TMP5]], <2 x float> [[LANE2]], 2
-// CHECK: [[TMP8:%.*]] = bitcast i8* [[TMP0]] to { <2 x float>, <2 x float>, <2 x float> }*
-// CHECK: store { <2 x float>, <2 x float>, <2 x float> } [[TMP7]], { <2 x float>, <2 x float>, <2 x float> }* [[TMP8]]
-// CHECK: [[TMP9:%.*]] = bitcast %struct.float32x2x3_t* %agg.result to i8*
-// CHECK: [[TMP10:%.*]] = bitcast %struct.float32x2x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP9]], i8* [[TMP10]], i32 24, i32 8, i1 false)
-// CHECK: ret void
+// 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: define void @test_vld3_dup_p8(%struct.poly8x8x3_t* noalias sret %agg.result, i8* %a) #0 {
+// 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> } @llvm.arm.neon.vld3lane.v8i8.p0i8(i8* %a, <8 x i8> undef, <8 x i8> undef, <8 x i8> undef, i32 0, i32 1)
-// CHECK: [[TMP1:%.*]] = extractvalue { <8 x i8>, <8 x i8>, <8 x i8> } [[VLD_DUP]], 0
-// CHECK: [[LANE:%.*]] = shufflevector <8 x i8> [[TMP1]], <8 x i8> [[TMP1]], <8 x i32> zeroinitializer
-// CHECK: [[TMP2:%.*]] = insertvalue { <8 x i8>, <8 x i8>, <8 x i8> } [[VLD_DUP]], <8 x i8> [[LANE]], 0
-// CHECK: [[TMP3:%.*]] = extractvalue { <8 x i8>, <8 x i8>, <8 x i8> } [[TMP2]], 1
-// CHECK: [[LANE1:%.*]] = shufflevector <8 x i8> [[TMP3]], <8 x i8> [[TMP3]], <8 x i32> zeroinitializer
-// CHECK: [[TMP4:%.*]] = insertvalue { <8 x i8>, <8 x i8>, <8 x i8> } [[TMP2]], <8 x i8> [[LANE1]], 1
-// CHECK: [[TMP5:%.*]] = extractvalue { <8 x i8>, <8 x i8>, <8 x i8> } [[TMP4]], 2
-// CHECK: [[LANE2:%.*]] = shufflevector <8 x i8> [[TMP5]], <8 x i8> [[TMP5]], <8 x i32> zeroinitializer
-// CHECK: [[TMP6:%.*]] = insertvalue { <8 x i8>, <8 x i8>, <8 x i8> } [[TMP4]], <8 x i8> [[LANE2]], 2
-// CHECK: [[TMP7:%.*]] = bitcast i8* [[TMP0]] to { <8 x i8>, <8 x i8>, <8 x i8> }*
-// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8> } [[TMP6]], { <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP7]]
-// CHECK: [[TMP8:%.*]] = bitcast %struct.poly8x8x3_t* %agg.result to i8*
-// CHECK: [[TMP9:%.*]] = bitcast %struct.poly8x8x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP8]], i8* [[TMP9]], i32 24, i32 8, i1 false)
-// CHECK: ret void
+// 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: define void @test_vld3_dup_p16(%struct.poly16x4x3_t* noalias sret %agg.result, i16* %a) #0 {
+// 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> } @llvm.arm.neon.vld3lane.v4i16.p0i8(i8* [[TMP1]], <4 x i16> undef, <4 x i16> undef, <4 x i16> undef, i32 0, i32 2)
-// CHECK: [[TMP2:%.*]] = extractvalue { <4 x i16>, <4 x i16>, <4 x i16> } [[VLD_DUP]], 0
-// CHECK: [[LANE:%.*]] = shufflevector <4 x i16> [[TMP2]], <4 x i16> [[TMP2]], <4 x i32> zeroinitializer
-// CHECK: [[TMP3:%.*]] = insertvalue { <4 x i16>, <4 x i16>, <4 x i16> } [[VLD_DUP]], <4 x i16> [[LANE]], 0
-// CHECK: [[TMP4:%.*]] = extractvalue { <4 x i16>, <4 x i16>, <4 x i16> } [[TMP3]], 1
-// CHECK: [[LANE1:%.*]] = shufflevector <4 x i16> [[TMP4]], <4 x i16> [[TMP4]], <4 x i32> zeroinitializer
-// CHECK: [[TMP5:%.*]] = insertvalue { <4 x i16>, <4 x i16>, <4 x i16> } [[TMP3]], <4 x i16> [[LANE1]], 1
-// CHECK: [[TMP6:%.*]] = extractvalue { <4 x i16>, <4 x i16>, <4 x i16> } [[TMP5]], 2
-// CHECK: [[LANE2:%.*]] = shufflevector <4 x i16> [[TMP6]], <4 x i16> [[TMP6]], <4 x i32> zeroinitializer
-// CHECK: [[TMP7:%.*]] = insertvalue { <4 x i16>, <4 x i16>, <4 x i16> } [[TMP5]], <4 x i16> [[LANE2]], 2
-// CHECK: [[TMP8:%.*]] = bitcast i8* [[TMP0]] to { <4 x i16>, <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16> } [[TMP7]], { <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP8]]
-// CHECK: [[TMP9:%.*]] = bitcast %struct.poly16x4x3_t* %agg.result to i8*
-// CHECK: [[TMP10:%.*]] = bitcast %struct.poly16x4x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP9]], i8* [[TMP10]], i32 24, i32 8, i1 false)
-// CHECK: ret void
+// 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: define void @test_vld3q_lane_u16(%struct.uint16x8x3_t* noalias sret %agg.result, i16* %a, [6 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld3q_lane_u16(
// CHECK: [[B:%.*]] = alloca %struct.uint16x8x3_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.uint16x8x3_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.uint16x8x3_t, align 16
@@ -6560,18 +5606,12 @@ poly16x4x3_t test_vld3_dup_p16(poly16_t const * a) {
// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16>
// CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16>
// CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP10]] to <8 x i16>
-// CHECK: [[VLD3Q_LANE_V:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16> } @llvm.arm.neon.vld3lane.v8i16.p0i8(i8* [[TMP4]], <8 x i16> [[TMP11]], <8 x i16> [[TMP12]], <8 x i16> [[TMP13]], i32 7, i32 2)
-// CHECK: [[TMP14:%.*]] = bitcast i8* [[TMP3]] to { <8 x i16>, <8 x i16>, <8 x i16> }*
-// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16> } [[VLD3Q_LANE_V]], { <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP14]]
-// CHECK: [[TMP15:%.*]] = bitcast %struct.uint16x8x3_t* %agg.result to i8*
-// CHECK: [[TMP16:%.*]] = bitcast %struct.uint16x8x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP15]], i8* [[TMP16]], i32 48, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD3Q_LANE_V:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>
uint16x8x3_t test_vld3q_lane_u16(uint16_t const * a, uint16x8x3_t b) {
return vld3q_lane_u16(a, b, 7);
}
-// CHECK-LABEL: define void @test_vld3q_lane_u32(%struct.uint32x4x3_t* noalias sret %agg.result, i32* %a, [6 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld3q_lane_u32(
// CHECK: [[B:%.*]] = alloca %struct.uint32x4x3_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.uint32x4x3_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.uint32x4x3_t, align 16
@@ -6598,18 +5638,12 @@ uint16x8x3_t test_vld3q_lane_u16(uint16_t const * a, uint16x8x3_t b) {
// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x i32>
// CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP8]] to <4 x i32>
// CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP10]] to <4 x i32>
-// CHECK: [[VLD3Q_LANE_V:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32> } @llvm.arm.neon.vld3lane.v4i32.p0i8(i8* [[TMP4]], <4 x i32> [[TMP11]], <4 x i32> [[TMP12]], <4 x i32> [[TMP13]], i32 3, i32 4)
-// CHECK: [[TMP14:%.*]] = bitcast i8* [[TMP3]] to { <4 x i32>, <4 x i32>, <4 x i32> }*
-// CHECK: store { <4 x i32>, <4 x i32>, <4 x i32> } [[VLD3Q_LANE_V]], { <4 x i32>, <4 x i32>, <4 x i32> }* [[TMP14]]
-// CHECK: [[TMP15:%.*]] = bitcast %struct.uint32x4x3_t* %agg.result to i8*
-// CHECK: [[TMP16:%.*]] = bitcast %struct.uint32x4x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP15]], i8* [[TMP16]], i32 48, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD3Q_LANE_V:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32>
uint32x4x3_t test_vld3q_lane_u32(uint32_t const * a, uint32x4x3_t b) {
return vld3q_lane_u32(a, b, 3);
}
-// CHECK-LABEL: define void @test_vld3q_lane_s16(%struct.int16x8x3_t* noalias sret %agg.result, i16* %a, [6 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld3q_lane_s16(
// CHECK: [[B:%.*]] = alloca %struct.int16x8x3_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.int16x8x3_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.int16x8x3_t, align 16
@@ -6636,18 +5670,12 @@ uint32x4x3_t test_vld3q_lane_u32(uint32_t const * a, uint32x4x3_t b) {
// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16>
// CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16>
// CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP10]] to <8 x i16>
-// CHECK: [[VLD3Q_LANE_V:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16> } @llvm.arm.neon.vld3lane.v8i16.p0i8(i8* [[TMP4]], <8 x i16> [[TMP11]], <8 x i16> [[TMP12]], <8 x i16> [[TMP13]], i32 7, i32 2)
-// CHECK: [[TMP14:%.*]] = bitcast i8* [[TMP3]] to { <8 x i16>, <8 x i16>, <8 x i16> }*
-// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16> } [[VLD3Q_LANE_V]], { <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP14]]
-// CHECK: [[TMP15:%.*]] = bitcast %struct.int16x8x3_t* %agg.result to i8*
-// CHECK: [[TMP16:%.*]] = bitcast %struct.int16x8x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP15]], i8* [[TMP16]], i32 48, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD3Q_LANE_V:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>
int16x8x3_t test_vld3q_lane_s16(int16_t const * a, int16x8x3_t b) {
return vld3q_lane_s16(a, b, 7);
}
-// CHECK-LABEL: define void @test_vld3q_lane_s32(%struct.int32x4x3_t* noalias sret %agg.result, i32* %a, [6 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld3q_lane_s32(
// CHECK: [[B:%.*]] = alloca %struct.int32x4x3_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.int32x4x3_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.int32x4x3_t, align 16
@@ -6674,18 +5702,12 @@ int16x8x3_t test_vld3q_lane_s16(int16_t const * a, int16x8x3_t b) {
// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x i32>
// CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP8]] to <4 x i32>
// CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP10]] to <4 x i32>
-// CHECK: [[VLD3Q_LANE_V:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32> } @llvm.arm.neon.vld3lane.v4i32.p0i8(i8* [[TMP4]], <4 x i32> [[TMP11]], <4 x i32> [[TMP12]], <4 x i32> [[TMP13]], i32 3, i32 4)
-// CHECK: [[TMP14:%.*]] = bitcast i8* [[TMP3]] to { <4 x i32>, <4 x i32>, <4 x i32> }*
-// CHECK: store { <4 x i32>, <4 x i32>, <4 x i32> } [[VLD3Q_LANE_V]], { <4 x i32>, <4 x i32>, <4 x i32> }* [[TMP14]]
-// CHECK: [[TMP15:%.*]] = bitcast %struct.int32x4x3_t* %agg.result to i8*
-// CHECK: [[TMP16:%.*]] = bitcast %struct.int32x4x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP15]], i8* [[TMP16]], i32 48, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD3Q_LANE_V:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32>
int32x4x3_t test_vld3q_lane_s32(int32_t const * a, int32x4x3_t b) {
return vld3q_lane_s32(a, b, 3);
}
-// CHECK-LABEL: define void @test_vld3q_lane_f16(%struct.float16x8x3_t* noalias sret %agg.result, half* %a, [6 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld3q_lane_f16(
// CHECK: [[B:%.*]] = alloca %struct.float16x8x3_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.float16x8x3_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.float16x8x3_t, align 16
@@ -6712,18 +5734,12 @@ int32x4x3_t test_vld3q_lane_s32(int32_t const * a, int32x4x3_t b) {
// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16>
// CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16>
// CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP10]] to <8 x i16>
-// CHECK: [[VLD3Q_LANE_V:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16> } @llvm.arm.neon.vld3lane.v8i16.p0i8(i8* [[TMP4]], <8 x i16> [[TMP11]], <8 x i16> [[TMP12]], <8 x i16> [[TMP13]], i32 7, i32 2)
-// CHECK: [[TMP14:%.*]] = bitcast i8* [[TMP3]] to { <8 x i16>, <8 x i16>, <8 x i16> }*
-// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16> } [[VLD3Q_LANE_V]], { <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP14]]
-// CHECK: [[TMP15:%.*]] = bitcast %struct.float16x8x3_t* %agg.result to i8*
-// CHECK: [[TMP16:%.*]] = bitcast %struct.float16x8x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP15]], i8* [[TMP16]], i32 48, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD3Q_LANE_V:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>
float16x8x3_t test_vld3q_lane_f16(float16_t const * a, float16x8x3_t b) {
return vld3q_lane_f16(a, b, 7);
}
-// CHECK-LABEL: define void @test_vld3q_lane_f32(%struct.float32x4x3_t* noalias sret %agg.result, float* %a, [6 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld3q_lane_f32(
// CHECK: [[B:%.*]] = alloca %struct.float32x4x3_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.float32x4x3_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.float32x4x3_t, align 16
@@ -6750,18 +5766,12 @@ float16x8x3_t test_vld3q_lane_f16(float16_t const * a, float16x8x3_t b) {
// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x float>
// CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP8]] to <4 x float>
// CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP10]] to <4 x float>
-// CHECK: [[VLD3Q_LANE_V:%.*]] = call { <4 x float>, <4 x float>, <4 x float> } @llvm.arm.neon.vld3lane.v4f32.p0i8(i8* [[TMP4]], <4 x float> [[TMP11]], <4 x float> [[TMP12]], <4 x float> [[TMP13]], i32 3, i32 4)
-// CHECK: [[TMP14:%.*]] = bitcast i8* [[TMP3]] to { <4 x float>, <4 x float>, <4 x float> }*
-// CHECK: store { <4 x float>, <4 x float>, <4 x float> } [[VLD3Q_LANE_V]], { <4 x float>, <4 x float>, <4 x float> }* [[TMP14]]
-// CHECK: [[TMP15:%.*]] = bitcast %struct.float32x4x3_t* %agg.result to i8*
-// CHECK: [[TMP16:%.*]] = bitcast %struct.float32x4x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP15]], i8* [[TMP16]], i32 48, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD3Q_LANE_V:%.*]] = call { <4 x float>, <4 x float>, <4 x float>
float32x4x3_t test_vld3q_lane_f32(float32_t const * a, float32x4x3_t b) {
return vld3q_lane_f32(a, b, 3);
}
-// CHECK-LABEL: define void @test_vld3q_lane_p16(%struct.poly16x8x3_t* noalias sret %agg.result, i16* %a, [6 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld3q_lane_p16(
// CHECK: [[B:%.*]] = alloca %struct.poly16x8x3_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.poly16x8x3_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.poly16x8x3_t, align 16
@@ -6788,18 +5798,12 @@ float32x4x3_t test_vld3q_lane_f32(float32_t const * a, float32x4x3_t b) {
// CHECK: [[TMP11:%.*]] = bitcast <16 x i8> [[TMP6]] to <8 x i16>
// CHECK: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16>
// CHECK: [[TMP13:%.*]] = bitcast <16 x i8> [[TMP10]] to <8 x i16>
-// CHECK: [[VLD3Q_LANE_V:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16> } @llvm.arm.neon.vld3lane.v8i16.p0i8(i8* [[TMP4]], <8 x i16> [[TMP11]], <8 x i16> [[TMP12]], <8 x i16> [[TMP13]], i32 7, i32 2)
-// CHECK: [[TMP14:%.*]] = bitcast i8* [[TMP3]] to { <8 x i16>, <8 x i16>, <8 x i16> }*
-// CHECK: store { <8 x i16>, <8 x i16>, <8 x i16> } [[VLD3Q_LANE_V]], { <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP14]]
-// CHECK: [[TMP15:%.*]] = bitcast %struct.poly16x8x3_t* %agg.result to i8*
-// CHECK: [[TMP16:%.*]] = bitcast %struct.poly16x8x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP15]], i8* [[TMP16]], i32 48, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD3Q_LANE_V:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>
poly16x8x3_t test_vld3q_lane_p16(poly16_t const * a, poly16x8x3_t b) {
return vld3q_lane_p16(a, b, 7);
}
-// CHECK-LABEL: define void @test_vld3_lane_u8(%struct.uint8x8x3_t* noalias sret %agg.result, i8* %a, [3 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld3_lane_u8(
// CHECK: [[B:%.*]] = alloca %struct.uint8x8x3_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.uint8x8x3_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.uint8x8x3_t, align 8
@@ -6819,18 +5823,12 @@ poly16x8x3_t test_vld3q_lane_p16(poly16_t const * a, poly16x8x3_t b) {
// 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]], i32 0, i32 2
// CHECK: [[TMP6:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX4]], align 8
-// CHECK: [[VLD3_LANE_V:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8> } @llvm.arm.neon.vld3lane.v8i8.p0i8(i8* %a, <8 x i8> [[TMP4]], <8 x i8> [[TMP5]], <8 x i8> [[TMP6]], i32 7, i32 1)
-// CHECK: [[TMP7:%.*]] = bitcast i8* [[TMP3]] to { <8 x i8>, <8 x i8>, <8 x i8> }*
-// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8> } [[VLD3_LANE_V]], { <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP7]]
-// CHECK: [[TMP8:%.*]] = bitcast %struct.uint8x8x3_t* %agg.result to i8*
-// CHECK: [[TMP9:%.*]] = bitcast %struct.uint8x8x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP8]], i8* [[TMP9]], i32 24, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD3_LANE_V:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>
uint8x8x3_t test_vld3_lane_u8(uint8_t const * a, uint8x8x3_t b) {
return vld3_lane_u8(a, b, 7);
}
-// CHECK-LABEL: define void @test_vld3_lane_u16(%struct.uint16x4x3_t* noalias sret %agg.result, i16* %a, [3 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld3_lane_u16(
// CHECK: [[B:%.*]] = alloca %struct.uint16x4x3_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.uint16x4x3_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.uint16x4x3_t, align 8
@@ -6857,18 +5855,12 @@ uint8x8x3_t test_vld3_lane_u8(uint8_t const * a, uint8x8x3_t b) {
// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16>
// CHECK: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x i16>
// CHECK: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP10]] to <4 x i16>
-// CHECK: [[VLD3_LANE_V:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.arm.neon.vld3lane.v4i16.p0i8(i8* [[TMP4]], <4 x i16> [[TMP11]], <4 x i16> [[TMP12]], <4 x i16> [[TMP13]], i32 3, i32 2)
-// CHECK: [[TMP14:%.*]] = bitcast i8* [[TMP3]] to { <4 x i16>, <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16> } [[VLD3_LANE_V]], { <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP14]]
-// CHECK: [[TMP15:%.*]] = bitcast %struct.uint16x4x3_t* %agg.result to i8*
-// CHECK: [[TMP16:%.*]] = bitcast %struct.uint16x4x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP15]], i8* [[TMP16]], i32 24, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD3_LANE_V:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>
uint16x4x3_t test_vld3_lane_u16(uint16_t const * a, uint16x4x3_t b) {
return vld3_lane_u16(a, b, 3);
}
-// CHECK-LABEL: define void @test_vld3_lane_u32(%struct.uint32x2x3_t* noalias sret %agg.result, i32* %a, [3 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld3_lane_u32(
// CHECK: [[B:%.*]] = alloca %struct.uint32x2x3_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.uint32x2x3_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.uint32x2x3_t, align 8
@@ -6895,18 +5887,12 @@ uint16x4x3_t test_vld3_lane_u16(uint16_t const * a, uint16x4x3_t b) {
// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP6]] to <2 x i32>
// CHECK: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP8]] to <2 x i32>
// CHECK: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP10]] to <2 x i32>
-// CHECK: [[VLD3_LANE_V:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32> } @llvm.arm.neon.vld3lane.v2i32.p0i8(i8* [[TMP4]], <2 x i32> [[TMP11]], <2 x i32> [[TMP12]], <2 x i32> [[TMP13]], i32 1, i32 4)
-// CHECK: [[TMP14:%.*]] = bitcast i8* [[TMP3]] to { <2 x i32>, <2 x i32>, <2 x i32> }*
-// CHECK: store { <2 x i32>, <2 x i32>, <2 x i32> } [[VLD3_LANE_V]], { <2 x i32>, <2 x i32>, <2 x i32> }* [[TMP14]]
-// CHECK: [[TMP15:%.*]] = bitcast %struct.uint32x2x3_t* %agg.result to i8*
-// CHECK: [[TMP16:%.*]] = bitcast %struct.uint32x2x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP15]], i8* [[TMP16]], i32 24, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD3_LANE_V:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32>
uint32x2x3_t test_vld3_lane_u32(uint32_t const * a, uint32x2x3_t b) {
return vld3_lane_u32(a, b, 1);
}
-// CHECK-LABEL: define void @test_vld3_lane_s8(%struct.int8x8x3_t* noalias sret %agg.result, i8* %a, [3 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld3_lane_s8(
// CHECK: [[B:%.*]] = alloca %struct.int8x8x3_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.int8x8x3_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.int8x8x3_t, align 8
@@ -6926,18 +5912,12 @@ uint32x2x3_t test_vld3_lane_u32(uint32_t const * a, uint32x2x3_t b) {
// 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]], i32 0, i32 2
// CHECK: [[TMP6:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX4]], align 8
-// CHECK: [[VLD3_LANE_V:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8> } @llvm.arm.neon.vld3lane.v8i8.p0i8(i8* %a, <8 x i8> [[TMP4]], <8 x i8> [[TMP5]], <8 x i8> [[TMP6]], i32 7, i32 1)
-// CHECK: [[TMP7:%.*]] = bitcast i8* [[TMP3]] to { <8 x i8>, <8 x i8>, <8 x i8> }*
-// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8> } [[VLD3_LANE_V]], { <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP7]]
-// CHECK: [[TMP8:%.*]] = bitcast %struct.int8x8x3_t* %agg.result to i8*
-// CHECK: [[TMP9:%.*]] = bitcast %struct.int8x8x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP8]], i8* [[TMP9]], i32 24, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD3_LANE_V:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>
int8x8x3_t test_vld3_lane_s8(int8_t const * a, int8x8x3_t b) {
return vld3_lane_s8(a, b, 7);
}
-// CHECK-LABEL: define void @test_vld3_lane_s16(%struct.int16x4x3_t* noalias sret %agg.result, i16* %a, [3 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld3_lane_s16(
// CHECK: [[B:%.*]] = alloca %struct.int16x4x3_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.int16x4x3_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.int16x4x3_t, align 8
@@ -6964,18 +5944,12 @@ int8x8x3_t test_vld3_lane_s8(int8_t const * a, int8x8x3_t b) {
// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16>
// CHECK: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x i16>
// CHECK: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP10]] to <4 x i16>
-// CHECK: [[VLD3_LANE_V:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.arm.neon.vld3lane.v4i16.p0i8(i8* [[TMP4]], <4 x i16> [[TMP11]], <4 x i16> [[TMP12]], <4 x i16> [[TMP13]], i32 3, i32 2)
-// CHECK: [[TMP14:%.*]] = bitcast i8* [[TMP3]] to { <4 x i16>, <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16> } [[VLD3_LANE_V]], { <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP14]]
-// CHECK: [[TMP15:%.*]] = bitcast %struct.int16x4x3_t* %agg.result to i8*
-// CHECK: [[TMP16:%.*]] = bitcast %struct.int16x4x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP15]], i8* [[TMP16]], i32 24, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD3_LANE_V:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>
int16x4x3_t test_vld3_lane_s16(int16_t const * a, int16x4x3_t b) {
return vld3_lane_s16(a, b, 3);
}
-// CHECK-LABEL: define void @test_vld3_lane_s32(%struct.int32x2x3_t* noalias sret %agg.result, i32* %a, [3 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld3_lane_s32(
// CHECK: [[B:%.*]] = alloca %struct.int32x2x3_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.int32x2x3_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.int32x2x3_t, align 8
@@ -7002,18 +5976,12 @@ int16x4x3_t test_vld3_lane_s16(int16_t const * a, int16x4x3_t b) {
// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP6]] to <2 x i32>
// CHECK: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP8]] to <2 x i32>
// CHECK: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP10]] to <2 x i32>
-// CHECK: [[VLD3_LANE_V:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32> } @llvm.arm.neon.vld3lane.v2i32.p0i8(i8* [[TMP4]], <2 x i32> [[TMP11]], <2 x i32> [[TMP12]], <2 x i32> [[TMP13]], i32 1, i32 4)
-// CHECK: [[TMP14:%.*]] = bitcast i8* [[TMP3]] to { <2 x i32>, <2 x i32>, <2 x i32> }*
-// CHECK: store { <2 x i32>, <2 x i32>, <2 x i32> } [[VLD3_LANE_V]], { <2 x i32>, <2 x i32>, <2 x i32> }* [[TMP14]]
-// CHECK: [[TMP15:%.*]] = bitcast %struct.int32x2x3_t* %agg.result to i8*
-// CHECK: [[TMP16:%.*]] = bitcast %struct.int32x2x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP15]], i8* [[TMP16]], i32 24, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD3_LANE_V:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32>
int32x2x3_t test_vld3_lane_s32(int32_t const * a, int32x2x3_t b) {
return vld3_lane_s32(a, b, 1);
}
-// CHECK-LABEL: define void @test_vld3_lane_f16(%struct.float16x4x3_t* noalias sret %agg.result, half* %a, [3 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld3_lane_f16(
// CHECK: [[B:%.*]] = alloca %struct.float16x4x3_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.float16x4x3_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.float16x4x3_t, align 8
@@ -7040,18 +6008,12 @@ int32x2x3_t test_vld3_lane_s32(int32_t const * a, int32x2x3_t b) {
// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16>
// CHECK: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x i16>
// CHECK: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP10]] to <4 x i16>
-// CHECK: [[VLD3_LANE_V:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.arm.neon.vld3lane.v4i16.p0i8(i8* [[TMP4]], <4 x i16> [[TMP11]], <4 x i16> [[TMP12]], <4 x i16> [[TMP13]], i32 3, i32 2)
-// CHECK: [[TMP14:%.*]] = bitcast i8* [[TMP3]] to { <4 x i16>, <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16> } [[VLD3_LANE_V]], { <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP14]]
-// CHECK: [[TMP15:%.*]] = bitcast %struct.float16x4x3_t* %agg.result to i8*
-// CHECK: [[TMP16:%.*]] = bitcast %struct.float16x4x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP15]], i8* [[TMP16]], i32 24, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD3_LANE_V:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>
float16x4x3_t test_vld3_lane_f16(float16_t const * a, float16x4x3_t b) {
return vld3_lane_f16(a, b, 3);
}
-// CHECK-LABEL: define void @test_vld3_lane_f32(%struct.float32x2x3_t* noalias sret %agg.result, float* %a, [3 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld3_lane_f32(
// CHECK: [[B:%.*]] = alloca %struct.float32x2x3_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.float32x2x3_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.float32x2x3_t, align 8
@@ -7078,18 +6040,12 @@ float16x4x3_t test_vld3_lane_f16(float16_t const * a, float16x4x3_t b) {
// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP6]] to <2 x float>
// CHECK: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP8]] to <2 x float>
// CHECK: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP10]] to <2 x float>
-// CHECK: [[VLD3_LANE_V:%.*]] = call { <2 x float>, <2 x float>, <2 x float> } @llvm.arm.neon.vld3lane.v2f32.p0i8(i8* [[TMP4]], <2 x float> [[TMP11]], <2 x float> [[TMP12]], <2 x float> [[TMP13]], i32 1, i32 4)
-// CHECK: [[TMP14:%.*]] = bitcast i8* [[TMP3]] to { <2 x float>, <2 x float>, <2 x float> }*
-// CHECK: store { <2 x float>, <2 x float>, <2 x float> } [[VLD3_LANE_V]], { <2 x float>, <2 x float>, <2 x float> }* [[TMP14]]
-// CHECK: [[TMP15:%.*]] = bitcast %struct.float32x2x3_t* %agg.result to i8*
-// CHECK: [[TMP16:%.*]] = bitcast %struct.float32x2x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP15]], i8* [[TMP16]], i32 24, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD3_LANE_V:%.*]] = call { <2 x float>, <2 x float>, <2 x float>
float32x2x3_t test_vld3_lane_f32(float32_t const * a, float32x2x3_t b) {
return vld3_lane_f32(a, b, 1);
}
-// CHECK-LABEL: define void @test_vld3_lane_p8(%struct.poly8x8x3_t* noalias sret %agg.result, i8* %a, [3 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld3_lane_p8(
// CHECK: [[B:%.*]] = alloca %struct.poly8x8x3_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.poly8x8x3_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.poly8x8x3_t, align 8
@@ -7109,18 +6065,12 @@ float32x2x3_t test_vld3_lane_f32(float32_t const * a, float32x2x3_t b) {
// 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]], i32 0, i32 2
// CHECK: [[TMP6:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX4]], align 8
-// CHECK: [[VLD3_LANE_V:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8> } @llvm.arm.neon.vld3lane.v8i8.p0i8(i8* %a, <8 x i8> [[TMP4]], <8 x i8> [[TMP5]], <8 x i8> [[TMP6]], i32 7, i32 1)
-// CHECK: [[TMP7:%.*]] = bitcast i8* [[TMP3]] to { <8 x i8>, <8 x i8>, <8 x i8> }*
-// CHECK: store { <8 x i8>, <8 x i8>, <8 x i8> } [[VLD3_LANE_V]], { <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP7]]
-// CHECK: [[TMP8:%.*]] = bitcast %struct.poly8x8x3_t* %agg.result to i8*
-// CHECK: [[TMP9:%.*]] = bitcast %struct.poly8x8x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP8]], i8* [[TMP9]], i32 24, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD3_LANE_V:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>
poly8x8x3_t test_vld3_lane_p8(poly8_t const * a, poly8x8x3_t b) {
return vld3_lane_p8(a, b, 7);
}
-// CHECK-LABEL: define void @test_vld3_lane_p16(%struct.poly16x4x3_t* noalias sret %agg.result, i16* %a, [3 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld3_lane_p16(
// CHECK: [[B:%.*]] = alloca %struct.poly16x4x3_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.poly16x4x3_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.poly16x4x3_t, align 8
@@ -7147,642 +6097,309 @@ poly8x8x3_t test_vld3_lane_p8(poly8_t const * a, poly8x8x3_t b) {
// CHECK: [[TMP11:%.*]] = bitcast <8 x i8> [[TMP6]] to <4 x i16>
// CHECK: [[TMP12:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x i16>
// CHECK: [[TMP13:%.*]] = bitcast <8 x i8> [[TMP10]] to <4 x i16>
-// CHECK: [[VLD3_LANE_V:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.arm.neon.vld3lane.v4i16.p0i8(i8* [[TMP4]], <4 x i16> [[TMP11]], <4 x i16> [[TMP12]], <4 x i16> [[TMP13]], i32 3, i32 2)
-// CHECK: [[TMP14:%.*]] = bitcast i8* [[TMP3]] to { <4 x i16>, <4 x i16>, <4 x i16> }*
-// CHECK: store { <4 x i16>, <4 x i16>, <4 x i16> } [[VLD3_LANE_V]], { <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP14]]
-// CHECK: [[TMP15:%.*]] = bitcast %struct.poly16x4x3_t* %agg.result to i8*
-// CHECK: [[TMP16:%.*]] = bitcast %struct.poly16x4x3_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP15]], i8* [[TMP16]], i32 24, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD3_LANE_V:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>
poly16x4x3_t test_vld3_lane_p16(poly16_t const * a, poly16x4x3_t b) {
return vld3_lane_p16(a, b, 3);
}
-
-// CHECK-LABEL: define void @test_vld4q_u8(%struct.uint8x16x4_t* noalias sret %agg.result, i8* %a) #0 {
+// CHECK-LABEL: @test_vld4q_u8(
// CHECK: [[__RET:%.*]] = alloca %struct.uint8x16x4_t, align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x16x4_t* [[__RET]] to i8*
-// CHECK: [[VLD4Q_V:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } @llvm.arm.neon.vld4.v16i8.p0i8(i8* %a, 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> } [[VLD4Q_V]], { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x16x4_t* %agg.result to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x16x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP2]], i8* [[TMP3]], i32 64, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD4Q_V:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8>
uint8x16x4_t test_vld4q_u8(uint8_t const * a) {
return vld4q_u8(a);
}
-// CHECK-LABEL: define void @test_vld4q_u16(%struct.uint16x8x4_t* noalias sret %agg.result, i16* %a) #0 {
+// CHECK-LABEL: @test_vld4q_u16(
// 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: [[VLD4Q_V:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } @llvm.arm.neon.vld4.v8i16.p0i8(i8* [[TMP1]], i32 2)
-// CHECK: [[TMP2:%.*]] = 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> } [[VLD4Q_V]], { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint16x8x4_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint16x8x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 64, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD4Q_V:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16>
uint16x8x4_t test_vld4q_u16(uint16_t const * a) {
return vld4q_u16(a);
}
-// CHECK-LABEL: define void @test_vld4q_u32(%struct.uint32x4x4_t* noalias sret %agg.result, i32* %a) #0 {
+// CHECK-LABEL: @test_vld4q_u32(
// 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: [[VLD4Q_V:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } @llvm.arm.neon.vld4.v4i32.p0i8(i8* [[TMP1]], i32 4)
-// CHECK: [[TMP2:%.*]] = 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> } [[VLD4Q_V]], { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint32x4x4_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint32x4x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 64, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD4Q_V:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32>
uint32x4x4_t test_vld4q_u32(uint32_t const * a) {
return vld4q_u32(a);
}
-// CHECK-LABEL: define void @test_vld4q_s8(%struct.int8x16x4_t* noalias sret %agg.result, i8* %a) #0 {
+// CHECK-LABEL: @test_vld4q_s8(
// CHECK: [[__RET:%.*]] = alloca %struct.int8x16x4_t, align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x16x4_t* [[__RET]] to i8*
-// CHECK: [[VLD4Q_V:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } @llvm.arm.neon.vld4.v16i8.p0i8(i8* %a, 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> } [[VLD4Q_V]], { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x16x4_t* %agg.result to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x16x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP2]], i8* [[TMP3]], i32 64, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD4Q_V:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8>
int8x16x4_t test_vld4q_s8(int8_t const * a) {
return vld4q_s8(a);
}
-// CHECK-LABEL: define void @test_vld4q_s16(%struct.int16x8x4_t* noalias sret %agg.result, i16* %a) #0 {
+// CHECK-LABEL: @test_vld4q_s16(
// 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: [[VLD4Q_V:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } @llvm.arm.neon.vld4.v8i16.p0i8(i8* [[TMP1]], i32 2)
-// CHECK: [[TMP2:%.*]] = 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> } [[VLD4Q_V]], { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int16x8x4_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int16x8x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 64, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD4Q_V:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16>
int16x8x4_t test_vld4q_s16(int16_t const * a) {
return vld4q_s16(a);
}
-// CHECK-LABEL: define void @test_vld4q_s32(%struct.int32x4x4_t* noalias sret %agg.result, i32* %a) #0 {
+// CHECK-LABEL: @test_vld4q_s32(
// 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: [[VLD4Q_V:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } @llvm.arm.neon.vld4.v4i32.p0i8(i8* [[TMP1]], i32 4)
-// CHECK: [[TMP2:%.*]] = 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> } [[VLD4Q_V]], { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int32x4x4_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int32x4x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 64, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD4Q_V:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32>
int32x4x4_t test_vld4q_s32(int32_t const * a) {
return vld4q_s32(a);
}
-// CHECK-LABEL: define void @test_vld4q_f16(%struct.float16x8x4_t* noalias sret %agg.result, half* %a) #0 {
+// CHECK-LABEL: @test_vld4q_f16(
// 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: [[VLD4Q_V:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } @llvm.arm.neon.vld4.v8i16.p0i8(i8* [[TMP1]], i32 2)
-// CHECK: [[TMP2:%.*]] = 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> } [[VLD4Q_V]], { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.float16x8x4_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x8x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 64, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD4Q_V:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16>
float16x8x4_t test_vld4q_f16(float16_t const * a) {
return vld4q_f16(a);
}
-// CHECK-LABEL: define void @test_vld4q_f32(%struct.float32x4x4_t* noalias sret %agg.result, float* %a) #0 {
+// CHECK-LABEL: @test_vld4q_f32(
// 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: [[VLD4Q_V:%.*]] = call { <4 x float>, <4 x float>, <4 x float>, <4 x float> } @llvm.arm.neon.vld4.v4f32.p0i8(i8* [[TMP1]], i32 4)
-// CHECK: [[TMP2:%.*]] = 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> } [[VLD4Q_V]], { <4 x float>, <4 x float>, <4 x float>, <4 x float> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.float32x4x4_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.float32x4x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 64, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD4Q_V:%.*]] = call { <4 x float>, <4 x float>, <4 x float>, <4 x float>
float32x4x4_t test_vld4q_f32(float32_t const * a) {
return vld4q_f32(a);
}
-// CHECK-LABEL: define void @test_vld4q_p8(%struct.poly8x16x4_t* noalias sret %agg.result, i8* %a) #0 {
+// CHECK-LABEL: @test_vld4q_p8(
// CHECK: [[__RET:%.*]] = alloca %struct.poly8x16x4_t, align 16
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x16x4_t* [[__RET]] to i8*
-// CHECK: [[VLD4Q_V:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } @llvm.arm.neon.vld4.v16i8.p0i8(i8* %a, 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> } [[VLD4Q_V]], { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x16x4_t* %agg.result to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x16x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP2]], i8* [[TMP3]], i32 64, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD4Q_V:%.*]] = call { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8>
poly8x16x4_t test_vld4q_p8(poly8_t const * a) {
return vld4q_p8(a);
}
-// CHECK-LABEL: define void @test_vld4q_p16(%struct.poly16x8x4_t* noalias sret %agg.result, i16* %a) #0 {
+// CHECK-LABEL: @test_vld4q_p16(
// 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: [[VLD4Q_V:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } @llvm.arm.neon.vld4.v8i16.p0i8(i8* [[TMP1]], i32 2)
-// CHECK: [[TMP2:%.*]] = 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> } [[VLD4Q_V]], { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.poly16x8x4_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.poly16x8x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 64, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD4Q_V:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16>
poly16x8x4_t test_vld4q_p16(poly16_t const * a) {
return vld4q_p16(a);
}
-// CHECK-LABEL: define void @test_vld4_u8(%struct.uint8x8x4_t* noalias sret %agg.result, i8* %a) #0 {
+// CHECK-LABEL: @test_vld4_u8(
// CHECK: [[__RET:%.*]] = alloca %struct.uint8x8x4_t, align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.uint8x8x4_t* [[__RET]] to i8*
-// CHECK: [[VLD4_V:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } @llvm.arm.neon.vld4.v8i8.p0i8(i8* %a, 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_V]], { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.uint8x8x4_t* %agg.result to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint8x8x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP2]], i8* [[TMP3]], i32 32, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD4_V:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>
uint8x8x4_t test_vld4_u8(uint8_t const * a) {
return vld4_u8(a);
}
-// CHECK-LABEL: define void @test_vld4_u16(%struct.uint16x4x4_t* noalias sret %agg.result, i16* %a) #0 {
+// CHECK-LABEL: @test_vld4_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: [[VLD4_V:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } @llvm.arm.neon.vld4.v4i16.p0i8(i8* [[TMP1]], i32 2)
-// CHECK: [[TMP2:%.*]] = 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_V]], { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint16x4x4_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint16x4x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 32, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD4_V:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16>
uint16x4x4_t test_vld4_u16(uint16_t const * a) {
return vld4_u16(a);
}
-// CHECK-LABEL: define void @test_vld4_u32(%struct.uint32x2x4_t* noalias sret %agg.result, i32* %a) #0 {
+// CHECK-LABEL: @test_vld4_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: [[VLD4_V:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } @llvm.arm.neon.vld4.v2i32.p0i8(i8* [[TMP1]], i32 4)
-// CHECK: [[TMP2:%.*]] = 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_V]], { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint32x2x4_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint32x2x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 32, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD4_V:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32>
uint32x2x4_t test_vld4_u32(uint32_t const * a) {
return vld4_u32(a);
}
-// CHECK-LABEL: define void @test_vld4_u64(%struct.uint64x1x4_t* noalias sret %agg.result, i64* %a) #0 {
+// CHECK-LABEL: @test_vld4_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: [[VLD4_V:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> } @llvm.arm.neon.vld4.v1i64.p0i8(i8* [[TMP1]], i32 4)
-// CHECK: [[TMP2:%.*]] = 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_V]], { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint64x1x4_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint64x1x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 32, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD4_V:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64>
uint64x1x4_t test_vld4_u64(uint64_t const * a) {
return vld4_u64(a);
}
-// CHECK-LABEL: define void @test_vld4_s8(%struct.int8x8x4_t* noalias sret %agg.result, i8* %a) #0 {
+// CHECK-LABEL: @test_vld4_s8(
// CHECK: [[__RET:%.*]] = alloca %struct.int8x8x4_t, align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.int8x8x4_t* [[__RET]] to i8*
-// CHECK: [[VLD4_V:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } @llvm.arm.neon.vld4.v8i8.p0i8(i8* %a, 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_V]], { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.int8x8x4_t* %agg.result to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int8x8x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP2]], i8* [[TMP3]], i32 32, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD4_V:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>
int8x8x4_t test_vld4_s8(int8_t const * a) {
return vld4_s8(a);
}
-// CHECK-LABEL: define void @test_vld4_s16(%struct.int16x4x4_t* noalias sret %agg.result, i16* %a) #0 {
+// CHECK-LABEL: @test_vld4_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: [[VLD4_V:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } @llvm.arm.neon.vld4.v4i16.p0i8(i8* [[TMP1]], i32 2)
-// CHECK: [[TMP2:%.*]] = 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_V]], { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int16x4x4_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int16x4x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 32, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD4_V:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16>
int16x4x4_t test_vld4_s16(int16_t const * a) {
return vld4_s16(a);
}
-// CHECK-LABEL: define void @test_vld4_s32(%struct.int32x2x4_t* noalias sret %agg.result, i32* %a) #0 {
+// CHECK-LABEL: @test_vld4_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: [[VLD4_V:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } @llvm.arm.neon.vld4.v2i32.p0i8(i8* [[TMP1]], i32 4)
-// CHECK: [[TMP2:%.*]] = 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_V]], { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int32x2x4_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int32x2x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 32, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD4_V:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32>
int32x2x4_t test_vld4_s32(int32_t const * a) {
return vld4_s32(a);
}
-// CHECK-LABEL: define void @test_vld4_s64(%struct.int64x1x4_t* noalias sret %agg.result, i64* %a) #0 {
+// CHECK-LABEL: @test_vld4_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: [[VLD4_V:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> } @llvm.arm.neon.vld4.v1i64.p0i8(i8* [[TMP1]], i32 4)
-// CHECK: [[TMP2:%.*]] = 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_V]], { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int64x1x4_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int64x1x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 32, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD4_V:%.*]] = call { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64>
int64x1x4_t test_vld4_s64(int64_t const * a) {
return vld4_s64(a);
}
-// CHECK-LABEL: define void @test_vld4_f16(%struct.float16x4x4_t* noalias sret %agg.result, half* %a) #0 {
+// CHECK-LABEL: @test_vld4_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: [[VLD4_V:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } @llvm.arm.neon.vld4.v4i16.p0i8(i8* [[TMP1]], i32 2)
-// CHECK: [[TMP2:%.*]] = 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_V]], { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.float16x4x4_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.float16x4x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 32, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD4_V:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16>
float16x4x4_t test_vld4_f16(float16_t const * a) {
return vld4_f16(a);
}
-// CHECK-LABEL: define void @test_vld4_f32(%struct.float32x2x4_t* noalias sret %agg.result, float* %a) #0 {
+// CHECK-LABEL: @test_vld4_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: [[VLD4_V:%.*]] = call { <2 x float>, <2 x float>, <2 x float>, <2 x float> } @llvm.arm.neon.vld4.v2f32.p0i8(i8* [[TMP1]], i32 4)
-// CHECK: [[TMP2:%.*]] = 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_V]], { <2 x float>, <2 x float>, <2 x float>, <2 x float> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.float32x2x4_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.float32x2x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 32, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD4_V:%.*]] = call { <2 x float>, <2 x float>, <2 x float>, <2 x float>
float32x2x4_t test_vld4_f32(float32_t const * a) {
return vld4_f32(a);
}
-// CHECK-LABEL: define void @test_vld4_p8(%struct.poly8x8x4_t* noalias sret %agg.result, i8* %a) #0 {
+// CHECK-LABEL: @test_vld4_p8(
// CHECK: [[__RET:%.*]] = alloca %struct.poly8x8x4_t, align 8
// CHECK: [[TMP0:%.*]] = bitcast %struct.poly8x8x4_t* [[__RET]] to i8*
-// CHECK: [[VLD4_V:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } @llvm.arm.neon.vld4.v8i8.p0i8(i8* %a, 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_V]], { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP1]]
-// CHECK: [[TMP2:%.*]] = bitcast %struct.poly8x8x4_t* %agg.result to i8*
-// CHECK: [[TMP3:%.*]] = bitcast %struct.poly8x8x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP2]], i8* [[TMP3]], i32 32, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD4_V:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>
poly8x8x4_t test_vld4_p8(poly8_t const * a) {
return vld4_p8(a);
}
-// CHECK-LABEL: define void @test_vld4_p16(%struct.poly16x4x4_t* noalias sret %agg.result, i16* %a) #0 {
+// CHECK-LABEL: @test_vld4_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: [[VLD4_V:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } @llvm.arm.neon.vld4.v4i16.p0i8(i8* [[TMP1]], i32 2)
-// CHECK: [[TMP2:%.*]] = 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_V]], { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.poly16x4x4_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.poly16x4x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 32, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD4_V:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16>
poly16x4x4_t test_vld4_p16(poly16_t const * a) {
return vld4_p16(a);
}
-
-// CHECK-LABEL: define void @test_vld4_dup_u8(%struct.uint8x8x4_t* noalias sret %agg.result, i8* %a) #0 {
+// 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> } @llvm.arm.neon.vld4lane.v8i8.p0i8(i8* %a, <8 x i8> undef, <8 x i8> undef, <8 x i8> undef, <8 x i8> undef, i32 0, i32 1)
-// CHECK: [[TMP1:%.*]] = extractvalue { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[VLD_DUP]], 0
-// CHECK: [[LANE:%.*]] = shufflevector <8 x i8> [[TMP1]], <8 x i8> [[TMP1]], <8 x i32> zeroinitializer
-// CHECK: [[TMP2:%.*]] = insertvalue { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[VLD_DUP]], <8 x i8> [[LANE]], 0
-// CHECK: [[TMP3:%.*]] = extractvalue { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[TMP2]], 1
-// CHECK: [[LANE1:%.*]] = shufflevector <8 x i8> [[TMP3]], <8 x i8> [[TMP3]], <8 x i32> zeroinitializer
-// CHECK: [[TMP4:%.*]] = insertvalue { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[TMP2]], <8 x i8> [[LANE1]], 1
-// CHECK: [[TMP5:%.*]] = extractvalue { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[TMP4]], 2
-// CHECK: [[LANE2:%.*]] = shufflevector <8 x i8> [[TMP5]], <8 x i8> [[TMP5]], <8 x i32> zeroinitializer
-// CHECK: [[TMP6:%.*]] = insertvalue { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[TMP4]], <8 x i8> [[LANE2]], 2
-// CHECK: [[TMP7:%.*]] = extractvalue { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[TMP6]], 3
-// CHECK: [[LANE3:%.*]] = shufflevector <8 x i8> [[TMP7]], <8 x i8> [[TMP7]], <8 x i32> zeroinitializer
-// CHECK: [[TMP8:%.*]] = insertvalue { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[TMP6]], <8 x i8> [[LANE3]], 3
-// CHECK: [[TMP9:%.*]] = 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> } [[TMP8]], { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP9]]
-// CHECK: [[TMP10:%.*]] = bitcast %struct.uint8x8x4_t* %agg.result to i8*
-// CHECK: [[TMP11:%.*]] = bitcast %struct.uint8x8x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP10]], i8* [[TMP11]], i32 32, i32 8, i1 false)
-// CHECK: ret void
+// 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: define void @test_vld4_dup_u16(%struct.uint16x4x4_t* noalias sret %agg.result, i16* %a) #0 {
+// 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> } @llvm.arm.neon.vld4lane.v4i16.p0i8(i8* [[TMP1]], <4 x i16> undef, <4 x i16> undef, <4 x i16> undef, <4 x i16> undef, i32 0, i32 2)
-// CHECK: [[TMP2:%.*]] = extractvalue { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[VLD_DUP]], 0
-// CHECK: [[LANE:%.*]] = shufflevector <4 x i16> [[TMP2]], <4 x i16> [[TMP2]], <4 x i32> zeroinitializer
-// CHECK: [[TMP3:%.*]] = insertvalue { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[VLD_DUP]], <4 x i16> [[LANE]], 0
-// CHECK: [[TMP4:%.*]] = extractvalue { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[TMP3]], 1
-// CHECK: [[LANE1:%.*]] = shufflevector <4 x i16> [[TMP4]], <4 x i16> [[TMP4]], <4 x i32> zeroinitializer
-// CHECK: [[TMP5:%.*]] = insertvalue { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[TMP3]], <4 x i16> [[LANE1]], 1
-// CHECK: [[TMP6:%.*]] = extractvalue { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[TMP5]], 2
-// CHECK: [[LANE2:%.*]] = shufflevector <4 x i16> [[TMP6]], <4 x i16> [[TMP6]], <4 x i32> zeroinitializer
-// CHECK: [[TMP7:%.*]] = insertvalue { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[TMP5]], <4 x i16> [[LANE2]], 2
-// CHECK: [[TMP8:%.*]] = extractvalue { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[TMP7]], 3
-// CHECK: [[LANE3:%.*]] = shufflevector <4 x i16> [[TMP8]], <4 x i16> [[TMP8]], <4 x i32> zeroinitializer
-// CHECK: [[TMP9:%.*]] = insertvalue { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[TMP7]], <4 x i16> [[LANE3]], 3
-// CHECK: [[TMP10:%.*]] = 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> } [[TMP9]], { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP10]]
-// CHECK: [[TMP11:%.*]] = bitcast %struct.uint16x4x4_t* %agg.result to i8*
-// CHECK: [[TMP12:%.*]] = bitcast %struct.uint16x4x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP11]], i8* [[TMP12]], i32 32, i32 8, i1 false)
-// CHECK: ret void
+// 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: define void @test_vld4_dup_u32(%struct.uint32x2x4_t* noalias sret %agg.result, i32* %a) #0 {
+// 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> } @llvm.arm.neon.vld4lane.v2i32.p0i8(i8* [[TMP1]], <2 x i32> undef, <2 x i32> undef, <2 x i32> undef, <2 x i32> undef, i32 0, i32 4)
-// CHECK: [[TMP2:%.*]] = extractvalue { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[VLD_DUP]], 0
-// CHECK: [[LANE:%.*]] = shufflevector <2 x i32> [[TMP2]], <2 x i32> [[TMP2]], <2 x i32> zeroinitializer
-// CHECK: [[TMP3:%.*]] = insertvalue { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[VLD_DUP]], <2 x i32> [[LANE]], 0
-// CHECK: [[TMP4:%.*]] = extractvalue { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[TMP3]], 1
-// CHECK: [[LANE1:%.*]] = shufflevector <2 x i32> [[TMP4]], <2 x i32> [[TMP4]], <2 x i32> zeroinitializer
-// CHECK: [[TMP5:%.*]] = insertvalue { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[TMP3]], <2 x i32> [[LANE1]], 1
-// CHECK: [[TMP6:%.*]] = extractvalue { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[TMP5]], 2
-// CHECK: [[LANE2:%.*]] = shufflevector <2 x i32> [[TMP6]], <2 x i32> [[TMP6]], <2 x i32> zeroinitializer
-// CHECK: [[TMP7:%.*]] = insertvalue { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[TMP5]], <2 x i32> [[LANE2]], 2
-// CHECK: [[TMP8:%.*]] = extractvalue { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[TMP7]], 3
-// CHECK: [[LANE3:%.*]] = shufflevector <2 x i32> [[TMP8]], <2 x i32> [[TMP8]], <2 x i32> zeroinitializer
-// CHECK: [[TMP9:%.*]] = insertvalue { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[TMP7]], <2 x i32> [[LANE3]], 3
-// CHECK: [[TMP10:%.*]] = 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> } [[TMP9]], { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> }* [[TMP10]]
-// CHECK: [[TMP11:%.*]] = bitcast %struct.uint32x2x4_t* %agg.result to i8*
-// CHECK: [[TMP12:%.*]] = bitcast %struct.uint32x2x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP11]], i8* [[TMP12]], i32 32, i32 8, i1 false)
-// CHECK: ret void
+// 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: define void @test_vld4_dup_u64(%struct.uint64x1x4_t* noalias sret %agg.result, i64* %a) #0 {
+// 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> } @llvm.arm.neon.vld4.v1i64.p0i8(i8* [[TMP1]], i32 4)
-// CHECK: [[TMP2:%.*]] = 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> } [[VLD_DUP]], { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.uint64x1x4_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.uint64x1x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 32, i32 8, i1 false)
-// CHECK: ret void
+// 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: define void @test_vld4_dup_s8(%struct.int8x8x4_t* noalias sret %agg.result, i8* %a) #0 {
+// 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> } @llvm.arm.neon.vld4lane.v8i8.p0i8(i8* %a, <8 x i8> undef, <8 x i8> undef, <8 x i8> undef, <8 x i8> undef, i32 0, i32 1)
-// CHECK: [[TMP1:%.*]] = extractvalue { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[VLD_DUP]], 0
-// CHECK: [[LANE:%.*]] = shufflevector <8 x i8> [[TMP1]], <8 x i8> [[TMP1]], <8 x i32> zeroinitializer
-// CHECK: [[TMP2:%.*]] = insertvalue { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[VLD_DUP]], <8 x i8> [[LANE]], 0
-// CHECK: [[TMP3:%.*]] = extractvalue { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[TMP2]], 1
-// CHECK: [[LANE1:%.*]] = shufflevector <8 x i8> [[TMP3]], <8 x i8> [[TMP3]], <8 x i32> zeroinitializer
-// CHECK: [[TMP4:%.*]] = insertvalue { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[TMP2]], <8 x i8> [[LANE1]], 1
-// CHECK: [[TMP5:%.*]] = extractvalue { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[TMP4]], 2
-// CHECK: [[LANE2:%.*]] = shufflevector <8 x i8> [[TMP5]], <8 x i8> [[TMP5]], <8 x i32> zeroinitializer
-// CHECK: [[TMP6:%.*]] = insertvalue { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[TMP4]], <8 x i8> [[LANE2]], 2
-// CHECK: [[TMP7:%.*]] = extractvalue { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[TMP6]], 3
-// CHECK: [[LANE3:%.*]] = shufflevector <8 x i8> [[TMP7]], <8 x i8> [[TMP7]], <8 x i32> zeroinitializer
-// CHECK: [[TMP8:%.*]] = insertvalue { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[TMP6]], <8 x i8> [[LANE3]], 3
-// CHECK: [[TMP9:%.*]] = 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> } [[TMP8]], { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP9]]
-// CHECK: [[TMP10:%.*]] = bitcast %struct.int8x8x4_t* %agg.result to i8*
-// CHECK: [[TMP11:%.*]] = bitcast %struct.int8x8x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP10]], i8* [[TMP11]], i32 32, i32 8, i1 false)
-// CHECK: ret void
+// 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: define void @test_vld4_dup_s16(%struct.int16x4x4_t* noalias sret %agg.result, i16* %a) #0 {
+// 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> } @llvm.arm.neon.vld4lane.v4i16.p0i8(i8* [[TMP1]], <4 x i16> undef, <4 x i16> undef, <4 x i16> undef, <4 x i16> undef, i32 0, i32 2)
-// CHECK: [[TMP2:%.*]] = extractvalue { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[VLD_DUP]], 0
-// CHECK: [[LANE:%.*]] = shufflevector <4 x i16> [[TMP2]], <4 x i16> [[TMP2]], <4 x i32> zeroinitializer
-// CHECK: [[TMP3:%.*]] = insertvalue { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[VLD_DUP]], <4 x i16> [[LANE]], 0
-// CHECK: [[TMP4:%.*]] = extractvalue { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[TMP3]], 1
-// CHECK: [[LANE1:%.*]] = shufflevector <4 x i16> [[TMP4]], <4 x i16> [[TMP4]], <4 x i32> zeroinitializer
-// CHECK: [[TMP5:%.*]] = insertvalue { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[TMP3]], <4 x i16> [[LANE1]], 1
-// CHECK: [[TMP6:%.*]] = extractvalue { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[TMP5]], 2
-// CHECK: [[LANE2:%.*]] = shufflevector <4 x i16> [[TMP6]], <4 x i16> [[TMP6]], <4 x i32> zeroinitializer
-// CHECK: [[TMP7:%.*]] = insertvalue { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[TMP5]], <4 x i16> [[LANE2]], 2
-// CHECK: [[TMP8:%.*]] = extractvalue { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[TMP7]], 3
-// CHECK: [[LANE3:%.*]] = shufflevector <4 x i16> [[TMP8]], <4 x i16> [[TMP8]], <4 x i32> zeroinitializer
-// CHECK: [[TMP9:%.*]] = insertvalue { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[TMP7]], <4 x i16> [[LANE3]], 3
-// CHECK: [[TMP10:%.*]] = 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> } [[TMP9]], { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP10]]
-// CHECK: [[TMP11:%.*]] = bitcast %struct.int16x4x4_t* %agg.result to i8*
-// CHECK: [[TMP12:%.*]] = bitcast %struct.int16x4x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP11]], i8* [[TMP12]], i32 32, i32 8, i1 false)
-// CHECK: ret void
+// 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: define void @test_vld4_dup_s32(%struct.int32x2x4_t* noalias sret %agg.result, i32* %a) #0 {
+// 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> } @llvm.arm.neon.vld4lane.v2i32.p0i8(i8* [[TMP1]], <2 x i32> undef, <2 x i32> undef, <2 x i32> undef, <2 x i32> undef, i32 0, i32 4)
-// CHECK: [[TMP2:%.*]] = extractvalue { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[VLD_DUP]], 0
-// CHECK: [[LANE:%.*]] = shufflevector <2 x i32> [[TMP2]], <2 x i32> [[TMP2]], <2 x i32> zeroinitializer
-// CHECK: [[TMP3:%.*]] = insertvalue { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[VLD_DUP]], <2 x i32> [[LANE]], 0
-// CHECK: [[TMP4:%.*]] = extractvalue { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[TMP3]], 1
-// CHECK: [[LANE1:%.*]] = shufflevector <2 x i32> [[TMP4]], <2 x i32> [[TMP4]], <2 x i32> zeroinitializer
-// CHECK: [[TMP5:%.*]] = insertvalue { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[TMP3]], <2 x i32> [[LANE1]], 1
-// CHECK: [[TMP6:%.*]] = extractvalue { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[TMP5]], 2
-// CHECK: [[LANE2:%.*]] = shufflevector <2 x i32> [[TMP6]], <2 x i32> [[TMP6]], <2 x i32> zeroinitializer
-// CHECK: [[TMP7:%.*]] = insertvalue { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[TMP5]], <2 x i32> [[LANE2]], 2
-// CHECK: [[TMP8:%.*]] = extractvalue { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[TMP7]], 3
-// CHECK: [[LANE3:%.*]] = shufflevector <2 x i32> [[TMP8]], <2 x i32> [[TMP8]], <2 x i32> zeroinitializer
-// CHECK: [[TMP9:%.*]] = insertvalue { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } [[TMP7]], <2 x i32> [[LANE3]], 3
-// CHECK: [[TMP10:%.*]] = 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> } [[TMP9]], { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> }* [[TMP10]]
-// CHECK: [[TMP11:%.*]] = bitcast %struct.int32x2x4_t* %agg.result to i8*
-// CHECK: [[TMP12:%.*]] = bitcast %struct.int32x2x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP11]], i8* [[TMP12]], i32 32, i32 8, i1 false)
-// CHECK: ret void
+// 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: define void @test_vld4_dup_s64(%struct.int64x1x4_t* noalias sret %agg.result, i64* %a) #0 {
+// 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> } @llvm.arm.neon.vld4.v1i64.p0i8(i8* [[TMP1]], i32 4)
-// CHECK: [[TMP2:%.*]] = 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> } [[VLD_DUP]], { <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64> }* [[TMP2]]
-// CHECK: [[TMP3:%.*]] = bitcast %struct.int64x1x4_t* %agg.result to i8*
-// CHECK: [[TMP4:%.*]] = bitcast %struct.int64x1x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP3]], i8* [[TMP4]], i32 32, i32 8, i1 false)
-// CHECK: ret void
+// 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: define void @test_vld4_dup_f16(%struct.float16x4x4_t* noalias sret %agg.result, half* %a) #0 {
+// 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> } @llvm.arm.neon.vld4lane.v4i16.p0i8(i8* [[TMP1]], <4 x i16> undef, <4 x i16> undef, <4 x i16> undef, <4 x i16> undef, i32 0, i32 2)
-// CHECK: [[TMP2:%.*]] = extractvalue { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[VLD_DUP]], 0
-// CHECK: [[LANE:%.*]] = shufflevector <4 x i16> [[TMP2]], <4 x i16> [[TMP2]], <4 x i32> zeroinitializer
-// CHECK: [[TMP3:%.*]] = insertvalue { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[VLD_DUP]], <4 x i16> [[LANE]], 0
-// CHECK: [[TMP4:%.*]] = extractvalue { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[TMP3]], 1
-// CHECK: [[LANE1:%.*]] = shufflevector <4 x i16> [[TMP4]], <4 x i16> [[TMP4]], <4 x i32> zeroinitializer
-// CHECK: [[TMP5:%.*]] = insertvalue { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[TMP3]], <4 x i16> [[LANE1]], 1
-// CHECK: [[TMP6:%.*]] = extractvalue { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[TMP5]], 2
-// CHECK: [[LANE2:%.*]] = shufflevector <4 x i16> [[TMP6]], <4 x i16> [[TMP6]], <4 x i32> zeroinitializer
-// CHECK: [[TMP7:%.*]] = insertvalue { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[TMP5]], <4 x i16> [[LANE2]], 2
-// CHECK: [[TMP8:%.*]] = extractvalue { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[TMP7]], 3
-// CHECK: [[LANE3:%.*]] = shufflevector <4 x i16> [[TMP8]], <4 x i16> [[TMP8]], <4 x i32> zeroinitializer
-// CHECK: [[TMP9:%.*]] = insertvalue { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[TMP7]], <4 x i16> [[LANE3]], 3
-// CHECK: [[TMP10:%.*]] = 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> } [[TMP9]], { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP10]]
-// CHECK: [[TMP11:%.*]] = bitcast %struct.float16x4x4_t* %agg.result to i8*
-// CHECK: [[TMP12:%.*]] = bitcast %struct.float16x4x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP11]], i8* [[TMP12]], i32 32, i32 8, i1 false)
-// CHECK: ret void
+// 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: define void @test_vld4_dup_f32(%struct.float32x2x4_t* noalias sret %agg.result, float* %a) #0 {
+// 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> } @llvm.arm.neon.vld4lane.v2f32.p0i8(i8* [[TMP1]], <2 x float> undef, <2 x float> undef, <2 x float> undef, <2 x float> undef, i32 0, i32 4)
-// CHECK: [[TMP2:%.*]] = extractvalue { <2 x float>, <2 x float>, <2 x float>, <2 x float> } [[VLD_DUP]], 0
-// CHECK: [[LANE:%.*]] = shufflevector <2 x float> [[TMP2]], <2 x float> [[TMP2]], <2 x i32> zeroinitializer
-// CHECK: [[TMP3:%.*]] = insertvalue { <2 x float>, <2 x float>, <2 x float>, <2 x float> } [[VLD_DUP]], <2 x float> [[LANE]], 0
-// CHECK: [[TMP4:%.*]] = extractvalue { <2 x float>, <2 x float>, <2 x float>, <2 x float> } [[TMP3]], 1
-// CHECK: [[LANE1:%.*]] = shufflevector <2 x float> [[TMP4]], <2 x float> [[TMP4]], <2 x i32> zeroinitializer
-// CHECK: [[TMP5:%.*]] = insertvalue { <2 x float>, <2 x float>, <2 x float>, <2 x float> } [[TMP3]], <2 x float> [[LANE1]], 1
-// CHECK: [[TMP6:%.*]] = extractvalue { <2 x float>, <2 x float>, <2 x float>, <2 x float> } [[TMP5]], 2
-// CHECK: [[LANE2:%.*]] = shufflevector <2 x float> [[TMP6]], <2 x float> [[TMP6]], <2 x i32> zeroinitializer
-// CHECK: [[TMP7:%.*]] = insertvalue { <2 x float>, <2 x float>, <2 x float>, <2 x float> } [[TMP5]], <2 x float> [[LANE2]], 2
-// CHECK: [[TMP8:%.*]] = extractvalue { <2 x float>, <2 x float>, <2 x float>, <2 x float> } [[TMP7]], 3
-// CHECK: [[LANE3:%.*]] = shufflevector <2 x float> [[TMP8]], <2 x float> [[TMP8]], <2 x i32> zeroinitializer
-// CHECK: [[TMP9:%.*]] = insertvalue { <2 x float>, <2 x float>, <2 x float>, <2 x float> } [[TMP7]], <2 x float> [[LANE3]], 3
-// CHECK: [[TMP10:%.*]] = 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> } [[TMP9]], { <2 x float>, <2 x float>, <2 x float>, <2 x float> }* [[TMP10]]
-// CHECK: [[TMP11:%.*]] = bitcast %struct.float32x2x4_t* %agg.result to i8*
-// CHECK: [[TMP12:%.*]] = bitcast %struct.float32x2x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP11]], i8* [[TMP12]], i32 32, i32 8, i1 false)
-// CHECK: ret void
+// 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: define void @test_vld4_dup_p8(%struct.poly8x8x4_t* noalias sret %agg.result, i8* %a) #0 {
+// 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> } @llvm.arm.neon.vld4lane.v8i8.p0i8(i8* %a, <8 x i8> undef, <8 x i8> undef, <8 x i8> undef, <8 x i8> undef, i32 0, i32 1)
-// CHECK: [[TMP1:%.*]] = extractvalue { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[VLD_DUP]], 0
-// CHECK: [[LANE:%.*]] = shufflevector <8 x i8> [[TMP1]], <8 x i8> [[TMP1]], <8 x i32> zeroinitializer
-// CHECK: [[TMP2:%.*]] = insertvalue { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[VLD_DUP]], <8 x i8> [[LANE]], 0
-// CHECK: [[TMP3:%.*]] = extractvalue { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[TMP2]], 1
-// CHECK: [[LANE1:%.*]] = shufflevector <8 x i8> [[TMP3]], <8 x i8> [[TMP3]], <8 x i32> zeroinitializer
-// CHECK: [[TMP4:%.*]] = insertvalue { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[TMP2]], <8 x i8> [[LANE1]], 1
-// CHECK: [[TMP5:%.*]] = extractvalue { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[TMP4]], 2
-// CHECK: [[LANE2:%.*]] = shufflevector <8 x i8> [[TMP5]], <8 x i8> [[TMP5]], <8 x i32> zeroinitializer
-// CHECK: [[TMP6:%.*]] = insertvalue { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[TMP4]], <8 x i8> [[LANE2]], 2
-// CHECK: [[TMP7:%.*]] = extractvalue { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[TMP6]], 3
-// CHECK: [[LANE3:%.*]] = shufflevector <8 x i8> [[TMP7]], <8 x i8> [[TMP7]], <8 x i32> zeroinitializer
-// CHECK: [[TMP8:%.*]] = insertvalue { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } [[TMP6]], <8 x i8> [[LANE3]], 3
-// CHECK: [[TMP9:%.*]] = 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> } [[TMP8]], { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP9]]
-// CHECK: [[TMP10:%.*]] = bitcast %struct.poly8x8x4_t* %agg.result to i8*
-// CHECK: [[TMP11:%.*]] = bitcast %struct.poly8x8x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP10]], i8* [[TMP11]], i32 32, i32 8, i1 false)
-// CHECK: ret void
+// 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: define void @test_vld4_dup_p16(%struct.poly16x4x4_t* noalias sret %agg.result, i16* %a) #0 {
+// 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> } @llvm.arm.neon.vld4lane.v4i16.p0i8(i8* [[TMP1]], <4 x i16> undef, <4 x i16> undef, <4 x i16> undef, <4 x i16> undef, i32 0, i32 2)
-// CHECK: [[TMP2:%.*]] = extractvalue { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[VLD_DUP]], 0
-// CHECK: [[LANE:%.*]] = shufflevector <4 x i16> [[TMP2]], <4 x i16> [[TMP2]], <4 x i32> zeroinitializer
-// CHECK: [[TMP3:%.*]] = insertvalue { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[VLD_DUP]], <4 x i16> [[LANE]], 0
-// CHECK: [[TMP4:%.*]] = extractvalue { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[TMP3]], 1
-// CHECK: [[LANE1:%.*]] = shufflevector <4 x i16> [[TMP4]], <4 x i16> [[TMP4]], <4 x i32> zeroinitializer
-// CHECK: [[TMP5:%.*]] = insertvalue { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[TMP3]], <4 x i16> [[LANE1]], 1
-// CHECK: [[TMP6:%.*]] = extractvalue { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[TMP5]], 2
-// CHECK: [[LANE2:%.*]] = shufflevector <4 x i16> [[TMP6]], <4 x i16> [[TMP6]], <4 x i32> zeroinitializer
-// CHECK: [[TMP7:%.*]] = insertvalue { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[TMP5]], <4 x i16> [[LANE2]], 2
-// CHECK: [[TMP8:%.*]] = extractvalue { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[TMP7]], 3
-// CHECK: [[LANE3:%.*]] = shufflevector <4 x i16> [[TMP8]], <4 x i16> [[TMP8]], <4 x i32> zeroinitializer
-// CHECK: [[TMP9:%.*]] = insertvalue { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } [[TMP7]], <4 x i16> [[LANE3]], 3
-// CHECK: [[TMP10:%.*]] = 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> } [[TMP9]], { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP10]]
-// CHECK: [[TMP11:%.*]] = bitcast %struct.poly16x4x4_t* %agg.result to i8*
-// CHECK: [[TMP12:%.*]] = bitcast %struct.poly16x4x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP11]], i8* [[TMP12]], i32 32, i32 8, i1 false)
-// CHECK: ret void
+// 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: define void @test_vld4q_lane_u16(%struct.uint16x8x4_t* noalias sret %agg.result, i16* %a, [8 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld4q_lane_u16(
// CHECK: [[B:%.*]] = alloca %struct.uint16x8x4_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.uint16x8x4_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.uint16x8x4_t, align 16
@@ -7814,18 +6431,12 @@ poly16x4x4_t test_vld4_dup_p16(poly16_t const * a) {
// CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16>
// CHECK: [[TMP15:%.*]] = bitcast <16 x i8> [[TMP10]] to <8 x i16>
// CHECK: [[TMP16:%.*]] = bitcast <16 x i8> [[TMP12]] to <8 x i16>
-// CHECK: [[VLD4Q_LANE_V:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } @llvm.arm.neon.vld4lane.v8i16.p0i8(i8* [[TMP4]], <8 x i16> [[TMP13]], <8 x i16> [[TMP14]], <8 x i16> [[TMP15]], <8 x i16> [[TMP16]], i32 7, i32 2)
-// CHECK: [[TMP17:%.*]] = bitcast i8* [[TMP3]] 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> } [[VLD4Q_LANE_V]], { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP17]]
-// CHECK: [[TMP18:%.*]] = bitcast %struct.uint16x8x4_t* %agg.result to i8*
-// CHECK: [[TMP19:%.*]] = bitcast %struct.uint16x8x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP18]], i8* [[TMP19]], i32 64, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD4Q_LANE_V:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16>
uint16x8x4_t test_vld4q_lane_u16(uint16_t const * a, uint16x8x4_t b) {
return vld4q_lane_u16(a, b, 7);
}
-// CHECK-LABEL: define void @test_vld4q_lane_u32(%struct.uint32x4x4_t* noalias sret %agg.result, i32* %a, [8 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld4q_lane_u32(
// CHECK: [[B:%.*]] = alloca %struct.uint32x4x4_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.uint32x4x4_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.uint32x4x4_t, align 16
@@ -7857,18 +6468,12 @@ uint16x8x4_t test_vld4q_lane_u16(uint16_t const * a, uint16x8x4_t b) {
// CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP8]] to <4 x i32>
// CHECK: [[TMP15:%.*]] = bitcast <16 x i8> [[TMP10]] to <4 x i32>
// CHECK: [[TMP16:%.*]] = bitcast <16 x i8> [[TMP12]] to <4 x i32>
-// CHECK: [[VLD4Q_LANE_V:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } @llvm.arm.neon.vld4lane.v4i32.p0i8(i8* [[TMP4]], <4 x i32> [[TMP13]], <4 x i32> [[TMP14]], <4 x i32> [[TMP15]], <4 x i32> [[TMP16]], i32 3, i32 4)
-// CHECK: [[TMP17:%.*]] = bitcast i8* [[TMP3]] 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> } [[VLD4Q_LANE_V]], { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> }* [[TMP17]]
-// CHECK: [[TMP18:%.*]] = bitcast %struct.uint32x4x4_t* %agg.result to i8*
-// CHECK: [[TMP19:%.*]] = bitcast %struct.uint32x4x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP18]], i8* [[TMP19]], i32 64, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD4Q_LANE_V:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32>
uint32x4x4_t test_vld4q_lane_u32(uint32_t const * a, uint32x4x4_t b) {
return vld4q_lane_u32(a, b, 3);
}
-// CHECK-LABEL: define void @test_vld4q_lane_s16(%struct.int16x8x4_t* noalias sret %agg.result, i16* %a, [8 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld4q_lane_s16(
// CHECK: [[B:%.*]] = alloca %struct.int16x8x4_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.int16x8x4_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.int16x8x4_t, align 16
@@ -7900,18 +6505,12 @@ uint32x4x4_t test_vld4q_lane_u32(uint32_t const * a, uint32x4x4_t b) {
// CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16>
// CHECK: [[TMP15:%.*]] = bitcast <16 x i8> [[TMP10]] to <8 x i16>
// CHECK: [[TMP16:%.*]] = bitcast <16 x i8> [[TMP12]] to <8 x i16>
-// CHECK: [[VLD4Q_LANE_V:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } @llvm.arm.neon.vld4lane.v8i16.p0i8(i8* [[TMP4]], <8 x i16> [[TMP13]], <8 x i16> [[TMP14]], <8 x i16> [[TMP15]], <8 x i16> [[TMP16]], i32 7, i32 2)
-// CHECK: [[TMP17:%.*]] = bitcast i8* [[TMP3]] 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> } [[VLD4Q_LANE_V]], { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP17]]
-// CHECK: [[TMP18:%.*]] = bitcast %struct.int16x8x4_t* %agg.result to i8*
-// CHECK: [[TMP19:%.*]] = bitcast %struct.int16x8x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP18]], i8* [[TMP19]], i32 64, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD4Q_LANE_V:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16>
int16x8x4_t test_vld4q_lane_s16(int16_t const * a, int16x8x4_t b) {
return vld4q_lane_s16(a, b, 7);
}
-// CHECK-LABEL: define void @test_vld4q_lane_s32(%struct.int32x4x4_t* noalias sret %agg.result, i32* %a, [8 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld4q_lane_s32(
// CHECK: [[B:%.*]] = alloca %struct.int32x4x4_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.int32x4x4_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.int32x4x4_t, align 16
@@ -7943,18 +6542,12 @@ int16x8x4_t test_vld4q_lane_s16(int16_t const * a, int16x8x4_t b) {
// CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP8]] to <4 x i32>
// CHECK: [[TMP15:%.*]] = bitcast <16 x i8> [[TMP10]] to <4 x i32>
// CHECK: [[TMP16:%.*]] = bitcast <16 x i8> [[TMP12]] to <4 x i32>
-// CHECK: [[VLD4Q_LANE_V:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } @llvm.arm.neon.vld4lane.v4i32.p0i8(i8* [[TMP4]], <4 x i32> [[TMP13]], <4 x i32> [[TMP14]], <4 x i32> [[TMP15]], <4 x i32> [[TMP16]], i32 3, i32 4)
-// CHECK: [[TMP17:%.*]] = bitcast i8* [[TMP3]] 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> } [[VLD4Q_LANE_V]], { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> }* [[TMP17]]
-// CHECK: [[TMP18:%.*]] = bitcast %struct.int32x4x4_t* %agg.result to i8*
-// CHECK: [[TMP19:%.*]] = bitcast %struct.int32x4x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP18]], i8* [[TMP19]], i32 64, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD4Q_LANE_V:%.*]] = call { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32>
int32x4x4_t test_vld4q_lane_s32(int32_t const * a, int32x4x4_t b) {
return vld4q_lane_s32(a, b, 3);
}
-// CHECK-LABEL: define void @test_vld4q_lane_f16(%struct.float16x8x4_t* noalias sret %agg.result, half* %a, [8 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld4q_lane_f16(
// CHECK: [[B:%.*]] = alloca %struct.float16x8x4_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.float16x8x4_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.float16x8x4_t, align 16
@@ -7986,18 +6579,12 @@ int32x4x4_t test_vld4q_lane_s32(int32_t const * a, int32x4x4_t b) {
// CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16>
// CHECK: [[TMP15:%.*]] = bitcast <16 x i8> [[TMP10]] to <8 x i16>
// CHECK: [[TMP16:%.*]] = bitcast <16 x i8> [[TMP12]] to <8 x i16>
-// CHECK: [[VLD4Q_LANE_V:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } @llvm.arm.neon.vld4lane.v8i16.p0i8(i8* [[TMP4]], <8 x i16> [[TMP13]], <8 x i16> [[TMP14]], <8 x i16> [[TMP15]], <8 x i16> [[TMP16]], i32 7, i32 2)
-// CHECK: [[TMP17:%.*]] = bitcast i8* [[TMP3]] 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> } [[VLD4Q_LANE_V]], { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP17]]
-// CHECK: [[TMP18:%.*]] = bitcast %struct.float16x8x4_t* %agg.result to i8*
-// CHECK: [[TMP19:%.*]] = bitcast %struct.float16x8x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP18]], i8* [[TMP19]], i32 64, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD4Q_LANE_V:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16>
float16x8x4_t test_vld4q_lane_f16(float16_t const * a, float16x8x4_t b) {
return vld4q_lane_f16(a, b, 7);
}
-// CHECK-LABEL: define void @test_vld4q_lane_f32(%struct.float32x4x4_t* noalias sret %agg.result, float* %a, [8 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld4q_lane_f32(
// CHECK: [[B:%.*]] = alloca %struct.float32x4x4_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.float32x4x4_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.float32x4x4_t, align 16
@@ -8029,18 +6616,12 @@ float16x8x4_t test_vld4q_lane_f16(float16_t const * a, float16x8x4_t b) {
// CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP8]] to <4 x float>
// CHECK: [[TMP15:%.*]] = bitcast <16 x i8> [[TMP10]] to <4 x float>
// CHECK: [[TMP16:%.*]] = bitcast <16 x i8> [[TMP12]] to <4 x float>
-// CHECK: [[VLD4Q_LANE_V:%.*]] = call { <4 x float>, <4 x float>, <4 x float>, <4 x float> } @llvm.arm.neon.vld4lane.v4f32.p0i8(i8* [[TMP4]], <4 x float> [[TMP13]], <4 x float> [[TMP14]], <4 x float> [[TMP15]], <4 x float> [[TMP16]], i32 3, i32 4)
-// CHECK: [[TMP17:%.*]] = bitcast i8* [[TMP3]] 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> } [[VLD4Q_LANE_V]], { <4 x float>, <4 x float>, <4 x float>, <4 x float> }* [[TMP17]]
-// CHECK: [[TMP18:%.*]] = bitcast %struct.float32x4x4_t* %agg.result to i8*
-// CHECK: [[TMP19:%.*]] = bitcast %struct.float32x4x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP18]], i8* [[TMP19]], i32 64, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD4Q_LANE_V:%.*]] = call { <4 x float>, <4 x float>, <4 x float>, <4 x float>
float32x4x4_t test_vld4q_lane_f32(float32_t const * a, float32x4x4_t b) {
return vld4q_lane_f32(a, b, 3);
}
-// CHECK-LABEL: define void @test_vld4q_lane_p16(%struct.poly16x8x4_t* noalias sret %agg.result, i16* %a, [8 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld4q_lane_p16(
// CHECK: [[B:%.*]] = alloca %struct.poly16x8x4_t, align 16
// CHECK: [[__S1:%.*]] = alloca %struct.poly16x8x4_t, align 16
// CHECK: [[__RET:%.*]] = alloca %struct.poly16x8x4_t, align 16
@@ -8072,18 +6653,12 @@ float32x4x4_t test_vld4q_lane_f32(float32_t const * a, float32x4x4_t b) {
// CHECK: [[TMP14:%.*]] = bitcast <16 x i8> [[TMP8]] to <8 x i16>
// CHECK: [[TMP15:%.*]] = bitcast <16 x i8> [[TMP10]] to <8 x i16>
// CHECK: [[TMP16:%.*]] = bitcast <16 x i8> [[TMP12]] to <8 x i16>
-// CHECK: [[VLD4Q_LANE_V:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } @llvm.arm.neon.vld4lane.v8i16.p0i8(i8* [[TMP4]], <8 x i16> [[TMP13]], <8 x i16> [[TMP14]], <8 x i16> [[TMP15]], <8 x i16> [[TMP16]], i32 7, i32 2)
-// CHECK: [[TMP17:%.*]] = bitcast i8* [[TMP3]] 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> } [[VLD4Q_LANE_V]], { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> }* [[TMP17]]
-// CHECK: [[TMP18:%.*]] = bitcast %struct.poly16x8x4_t* %agg.result to i8*
-// CHECK: [[TMP19:%.*]] = bitcast %struct.poly16x8x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP18]], i8* [[TMP19]], i32 64, i32 16, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD4Q_LANE_V:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16>
poly16x8x4_t test_vld4q_lane_p16(poly16_t const * a, poly16x8x4_t b) {
return vld4q_lane_p16(a, b, 7);
}
-// CHECK-LABEL: define void @test_vld4_lane_u8(%struct.uint8x8x4_t* noalias sret %agg.result, i8* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld4_lane_u8(
// CHECK: [[B:%.*]] = alloca %struct.uint8x8x4_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.uint8x8x4_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.uint8x8x4_t, align 8
@@ -8106,18 +6681,12 @@ poly16x8x4_t test_vld4q_lane_p16(poly16_t const * a, poly16x8x4_t b) {
// 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]], i32 0, i32 3
// CHECK: [[TMP7:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX6]], align 8
-// CHECK: [[VLD4_LANE_V:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } @llvm.arm.neon.vld4lane.v8i8.p0i8(i8* %a, <8 x i8> [[TMP4]], <8 x i8> [[TMP5]], <8 x i8> [[TMP6]], <8 x i8> [[TMP7]], i32 7, i32 1)
-// CHECK: [[TMP8:%.*]] = bitcast i8* [[TMP3]] 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_LANE_V]], { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP8]]
-// CHECK: [[TMP9:%.*]] = bitcast %struct.uint8x8x4_t* %agg.result to i8*
-// CHECK: [[TMP10:%.*]] = bitcast %struct.uint8x8x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP9]], i8* [[TMP10]], i32 32, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD4_LANE_V:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>
uint8x8x4_t test_vld4_lane_u8(uint8_t const * a, uint8x8x4_t b) {
return vld4_lane_u8(a, b, 7);
}
-// CHECK-LABEL: define void @test_vld4_lane_u16(%struct.uint16x4x4_t* noalias sret %agg.result, i16* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld4_lane_u16(
// CHECK: [[B:%.*]] = alloca %struct.uint16x4x4_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.uint16x4x4_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.uint16x4x4_t, align 8
@@ -8149,18 +6718,12 @@ uint8x8x4_t test_vld4_lane_u8(uint8_t const * a, uint8x8x4_t b) {
// CHECK: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x i16>
// CHECK: [[TMP15:%.*]] = bitcast <8 x i8> [[TMP10]] to <4 x i16>
// CHECK: [[TMP16:%.*]] = bitcast <8 x i8> [[TMP12]] to <4 x i16>
-// CHECK: [[VLD4_LANE_V:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } @llvm.arm.neon.vld4lane.v4i16.p0i8(i8* [[TMP4]], <4 x i16> [[TMP13]], <4 x i16> [[TMP14]], <4 x i16> [[TMP15]], <4 x i16> [[TMP16]], i32 3, i32 2)
-// CHECK: [[TMP17:%.*]] = bitcast i8* [[TMP3]] 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_LANE_V]], { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP17]]
-// CHECK: [[TMP18:%.*]] = bitcast %struct.uint16x4x4_t* %agg.result to i8*
-// CHECK: [[TMP19:%.*]] = bitcast %struct.uint16x4x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP18]], i8* [[TMP19]], i32 32, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD4_LANE_V:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16>
uint16x4x4_t test_vld4_lane_u16(uint16_t const * a, uint16x4x4_t b) {
return vld4_lane_u16(a, b, 3);
}
-// CHECK-LABEL: define void @test_vld4_lane_u32(%struct.uint32x2x4_t* noalias sret %agg.result, i32* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld4_lane_u32(
// CHECK: [[B:%.*]] = alloca %struct.uint32x2x4_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.uint32x2x4_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.uint32x2x4_t, align 8
@@ -8192,18 +6755,12 @@ uint16x4x4_t test_vld4_lane_u16(uint16_t const * a, uint16x4x4_t b) {
// CHECK: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP8]] to <2 x i32>
// CHECK: [[TMP15:%.*]] = bitcast <8 x i8> [[TMP10]] to <2 x i32>
// CHECK: [[TMP16:%.*]] = bitcast <8 x i8> [[TMP12]] to <2 x i32>
-// CHECK: [[VLD4_LANE_V:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } @llvm.arm.neon.vld4lane.v2i32.p0i8(i8* [[TMP4]], <2 x i32> [[TMP13]], <2 x i32> [[TMP14]], <2 x i32> [[TMP15]], <2 x i32> [[TMP16]], i32 1, i32 4)
-// CHECK: [[TMP17:%.*]] = bitcast i8* [[TMP3]] 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_LANE_V]], { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> }* [[TMP17]]
-// CHECK: [[TMP18:%.*]] = bitcast %struct.uint32x2x4_t* %agg.result to i8*
-// CHECK: [[TMP19:%.*]] = bitcast %struct.uint32x2x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP18]], i8* [[TMP19]], i32 32, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD4_LANE_V:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32>
uint32x2x4_t test_vld4_lane_u32(uint32_t const * a, uint32x2x4_t b) {
return vld4_lane_u32(a, b, 1);
}
-// CHECK-LABEL: define void @test_vld4_lane_s8(%struct.int8x8x4_t* noalias sret %agg.result, i8* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld4_lane_s8(
// CHECK: [[B:%.*]] = alloca %struct.int8x8x4_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.int8x8x4_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.int8x8x4_t, align 8
@@ -8226,18 +6783,12 @@ uint32x2x4_t test_vld4_lane_u32(uint32_t const * a, uint32x2x4_t b) {
// 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]], i32 0, i32 3
// CHECK: [[TMP7:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX6]], align 8
-// CHECK: [[VLD4_LANE_V:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } @llvm.arm.neon.vld4lane.v8i8.p0i8(i8* %a, <8 x i8> [[TMP4]], <8 x i8> [[TMP5]], <8 x i8> [[TMP6]], <8 x i8> [[TMP7]], i32 7, i32 1)
-// CHECK: [[TMP8:%.*]] = bitcast i8* [[TMP3]] 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_LANE_V]], { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP8]]
-// CHECK: [[TMP9:%.*]] = bitcast %struct.int8x8x4_t* %agg.result to i8*
-// CHECK: [[TMP10:%.*]] = bitcast %struct.int8x8x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP9]], i8* [[TMP10]], i32 32, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD4_LANE_V:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>
int8x8x4_t test_vld4_lane_s8(int8_t const * a, int8x8x4_t b) {
return vld4_lane_s8(a, b, 7);
}
-// CHECK-LABEL: define void @test_vld4_lane_s16(%struct.int16x4x4_t* noalias sret %agg.result, i16* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld4_lane_s16(
// CHECK: [[B:%.*]] = alloca %struct.int16x4x4_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.int16x4x4_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.int16x4x4_t, align 8
@@ -8269,18 +6820,12 @@ int8x8x4_t test_vld4_lane_s8(int8_t const * a, int8x8x4_t b) {
// CHECK: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x i16>
// CHECK: [[TMP15:%.*]] = bitcast <8 x i8> [[TMP10]] to <4 x i16>
// CHECK: [[TMP16:%.*]] = bitcast <8 x i8> [[TMP12]] to <4 x i16>
-// CHECK: [[VLD4_LANE_V:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } @llvm.arm.neon.vld4lane.v4i16.p0i8(i8* [[TMP4]], <4 x i16> [[TMP13]], <4 x i16> [[TMP14]], <4 x i16> [[TMP15]], <4 x i16> [[TMP16]], i32 3, i32 2)
-// CHECK: [[TMP17:%.*]] = bitcast i8* [[TMP3]] 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_LANE_V]], { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP17]]
-// CHECK: [[TMP18:%.*]] = bitcast %struct.int16x4x4_t* %agg.result to i8*
-// CHECK: [[TMP19:%.*]] = bitcast %struct.int16x4x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP18]], i8* [[TMP19]], i32 32, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD4_LANE_V:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16>
int16x4x4_t test_vld4_lane_s16(int16_t const * a, int16x4x4_t b) {
return vld4_lane_s16(a, b, 3);
}
-// CHECK-LABEL: define void @test_vld4_lane_s32(%struct.int32x2x4_t* noalias sret %agg.result, i32* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld4_lane_s32(
// CHECK: [[B:%.*]] = alloca %struct.int32x2x4_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.int32x2x4_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.int32x2x4_t, align 8
@@ -8312,18 +6857,12 @@ int16x4x4_t test_vld4_lane_s16(int16_t const * a, int16x4x4_t b) {
// CHECK: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP8]] to <2 x i32>
// CHECK: [[TMP15:%.*]] = bitcast <8 x i8> [[TMP10]] to <2 x i32>
// CHECK: [[TMP16:%.*]] = bitcast <8 x i8> [[TMP12]] to <2 x i32>
-// CHECK: [[VLD4_LANE_V:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> } @llvm.arm.neon.vld4lane.v2i32.p0i8(i8* [[TMP4]], <2 x i32> [[TMP13]], <2 x i32> [[TMP14]], <2 x i32> [[TMP15]], <2 x i32> [[TMP16]], i32 1, i32 4)
-// CHECK: [[TMP17:%.*]] = bitcast i8* [[TMP3]] 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_LANE_V]], { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32> }* [[TMP17]]
-// CHECK: [[TMP18:%.*]] = bitcast %struct.int32x2x4_t* %agg.result to i8*
-// CHECK: [[TMP19:%.*]] = bitcast %struct.int32x2x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP18]], i8* [[TMP19]], i32 32, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD4_LANE_V:%.*]] = call { <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32>
int32x2x4_t test_vld4_lane_s32(int32_t const * a, int32x2x4_t b) {
return vld4_lane_s32(a, b, 1);
}
-// CHECK-LABEL: define void @test_vld4_lane_f16(%struct.float16x4x4_t* noalias sret %agg.result, half* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld4_lane_f16(
// CHECK: [[B:%.*]] = alloca %struct.float16x4x4_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.float16x4x4_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.float16x4x4_t, align 8
@@ -8355,18 +6894,12 @@ int32x2x4_t test_vld4_lane_s32(int32_t const * a, int32x2x4_t b) {
// CHECK: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x i16>
// CHECK: [[TMP15:%.*]] = bitcast <8 x i8> [[TMP10]] to <4 x i16>
// CHECK: [[TMP16:%.*]] = bitcast <8 x i8> [[TMP12]] to <4 x i16>
-// CHECK: [[VLD4_LANE_V:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } @llvm.arm.neon.vld4lane.v4i16.p0i8(i8* [[TMP4]], <4 x i16> [[TMP13]], <4 x i16> [[TMP14]], <4 x i16> [[TMP15]], <4 x i16> [[TMP16]], i32 3, i32 2)
-// CHECK: [[TMP17:%.*]] = bitcast i8* [[TMP3]] 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_LANE_V]], { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP17]]
-// CHECK: [[TMP18:%.*]] = bitcast %struct.float16x4x4_t* %agg.result to i8*
-// CHECK: [[TMP19:%.*]] = bitcast %struct.float16x4x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP18]], i8* [[TMP19]], i32 32, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD4_LANE_V:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16>
float16x4x4_t test_vld4_lane_f16(float16_t const * a, float16x4x4_t b) {
return vld4_lane_f16(a, b, 3);
}
-// CHECK-LABEL: define void @test_vld4_lane_f32(%struct.float32x2x4_t* noalias sret %agg.result, float* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld4_lane_f32(
// CHECK: [[B:%.*]] = alloca %struct.float32x2x4_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.float32x2x4_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.float32x2x4_t, align 8
@@ -8398,18 +6931,12 @@ float16x4x4_t test_vld4_lane_f16(float16_t const * a, float16x4x4_t b) {
// CHECK: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP8]] to <2 x float>
// CHECK: [[TMP15:%.*]] = bitcast <8 x i8> [[TMP10]] to <2 x float>
// CHECK: [[TMP16:%.*]] = bitcast <8 x i8> [[TMP12]] to <2 x float>
-// CHECK: [[VLD4_LANE_V:%.*]] = call { <2 x float>, <2 x float>, <2 x float>, <2 x float> } @llvm.arm.neon.vld4lane.v2f32.p0i8(i8* [[TMP4]], <2 x float> [[TMP13]], <2 x float> [[TMP14]], <2 x float> [[TMP15]], <2 x float> [[TMP16]], i32 1, i32 4)
-// CHECK: [[TMP17:%.*]] = bitcast i8* [[TMP3]] 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_LANE_V]], { <2 x float>, <2 x float>, <2 x float>, <2 x float> }* [[TMP17]]
-// CHECK: [[TMP18:%.*]] = bitcast %struct.float32x2x4_t* %agg.result to i8*
-// CHECK: [[TMP19:%.*]] = bitcast %struct.float32x2x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP18]], i8* [[TMP19]], i32 32, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD4_LANE_V:%.*]] = call { <2 x float>, <2 x float>, <2 x float>, <2 x float>
float32x2x4_t test_vld4_lane_f32(float32_t const * a, float32x2x4_t b) {
return vld4_lane_f32(a, b, 1);
}
-// CHECK-LABEL: define void @test_vld4_lane_p8(%struct.poly8x8x4_t* noalias sret %agg.result, i8* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld4_lane_p8(
// CHECK: [[B:%.*]] = alloca %struct.poly8x8x4_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.poly8x8x4_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.poly8x8x4_t, align 8
@@ -8432,18 +6959,12 @@ float32x2x4_t test_vld4_lane_f32(float32_t const * a, float32x2x4_t b) {
// 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]], i32 0, i32 3
// CHECK: [[TMP7:%.*]] = load <8 x i8>, <8 x i8>* [[ARRAYIDX6]], align 8
-// CHECK: [[VLD4_LANE_V:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } @llvm.arm.neon.vld4lane.v8i8.p0i8(i8* %a, <8 x i8> [[TMP4]], <8 x i8> [[TMP5]], <8 x i8> [[TMP6]], <8 x i8> [[TMP7]], i32 7, i32 1)
-// CHECK: [[TMP8:%.*]] = bitcast i8* [[TMP3]] 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_LANE_V]], { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }* [[TMP8]]
-// CHECK: [[TMP9:%.*]] = bitcast %struct.poly8x8x4_t* %agg.result to i8*
-// CHECK: [[TMP10:%.*]] = bitcast %struct.poly8x8x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP9]], i8* [[TMP10]], i32 32, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD4_LANE_V:%.*]] = call { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>
poly8x8x4_t test_vld4_lane_p8(poly8_t const * a, poly8x8x4_t b) {
return vld4_lane_p8(a, b, 7);
}
-// CHECK-LABEL: define void @test_vld4_lane_p16(%struct.poly16x4x4_t* noalias sret %agg.result, i16* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vld4_lane_p16(
// CHECK: [[B:%.*]] = alloca %struct.poly16x4x4_t, align 8
// CHECK: [[__S1:%.*]] = alloca %struct.poly16x4x4_t, align 8
// CHECK: [[__RET:%.*]] = alloca %struct.poly16x4x4_t, align 8
@@ -8475,337 +6996,268 @@ poly8x8x4_t test_vld4_lane_p8(poly8_t const * a, poly8x8x4_t b) {
// CHECK: [[TMP14:%.*]] = bitcast <8 x i8> [[TMP8]] to <4 x i16>
// CHECK: [[TMP15:%.*]] = bitcast <8 x i8> [[TMP10]] to <4 x i16>
// CHECK: [[TMP16:%.*]] = bitcast <8 x i8> [[TMP12]] to <4 x i16>
-// CHECK: [[VLD4_LANE_V:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } @llvm.arm.neon.vld4lane.v4i16.p0i8(i8* [[TMP4]], <4 x i16> [[TMP13]], <4 x i16> [[TMP14]], <4 x i16> [[TMP15]], <4 x i16> [[TMP16]], i32 3, i32 2)
-// CHECK: [[TMP17:%.*]] = bitcast i8* [[TMP3]] 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_LANE_V]], { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> }* [[TMP17]]
-// CHECK: [[TMP18:%.*]] = bitcast %struct.poly16x4x4_t* %agg.result to i8*
-// CHECK: [[TMP19:%.*]] = bitcast %struct.poly16x4x4_t* [[__RET]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP18]], i8* [[TMP19]], i32 32, i32 8, i1 false)
-// CHECK: ret void
+// CHECK: [[VLD4_LANE_V:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16>
poly16x4x4_t test_vld4_lane_p16(poly16_t const * a, poly16x4x4_t b) {
return vld4_lane_p16(a, b, 3);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vmax_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vmax_s8(
// CHECK: [[VMAX_V_I:%.*]] = call <8 x i8> @llvm.arm.neon.vmaxs.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VMAX_V_I]]
int8x8_t test_vmax_s8(int8x8_t a, int8x8_t b) {
return vmax_s8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vmax_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vmax_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VMAX_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMAX_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMAX_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vmaxs.v4i16(<4 x i16> [[VMAX_V_I]], <4 x i16> [[VMAX_V1_I]]) #4
+// CHECK: [[VMAX_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vmaxs.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VMAX_V3_I:%.*]] = bitcast <4 x i16> [[VMAX_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VMAX_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VMAX_V2_I]]
int16x4_t test_vmax_s16(int16x4_t a, int16x4_t b) {
return vmax_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vmax_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vmax_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VMAX_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMAX_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMAX_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vmaxs.v2i32(<2 x i32> [[VMAX_V_I]], <2 x i32> [[VMAX_V1_I]]) #4
+// CHECK: [[VMAX_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vmaxs.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VMAX_V3_I:%.*]] = bitcast <2 x i32> [[VMAX_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VMAX_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VMAX_V2_I]]
int32x2_t test_vmax_s32(int32x2_t a, int32x2_t b) {
return vmax_s32(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vmax_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vmax_u8(
// CHECK: [[VMAX_V_I:%.*]] = call <8 x i8> @llvm.arm.neon.vmaxu.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VMAX_V_I]]
uint8x8_t test_vmax_u8(uint8x8_t a, uint8x8_t b) {
return vmax_u8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vmax_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vmax_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VMAX_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMAX_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMAX_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vmaxu.v4i16(<4 x i16> [[VMAX_V_I]], <4 x i16> [[VMAX_V1_I]]) #4
+// CHECK: [[VMAX_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vmaxu.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VMAX_V3_I:%.*]] = bitcast <4 x i16> [[VMAX_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VMAX_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VMAX_V2_I]]
uint16x4_t test_vmax_u16(uint16x4_t a, uint16x4_t b) {
return vmax_u16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vmax_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vmax_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VMAX_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMAX_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMAX_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vmaxu.v2i32(<2 x i32> [[VMAX_V_I]], <2 x i32> [[VMAX_V1_I]]) #4
+// CHECK: [[VMAX_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vmaxu.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VMAX_V3_I:%.*]] = bitcast <2 x i32> [[VMAX_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VMAX_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VMAX_V2_I]]
uint32x2_t test_vmax_u32(uint32x2_t a, uint32x2_t b) {
return vmax_u32(a, b);
}
-// CHECK-LABEL: define <2 x float> @test_vmax_f32(<2 x float> %a, <2 x float> %b) #0 {
+// CHECK-LABEL: @test_vmax_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %b to <8 x i8>
-// CHECK: [[VMAX_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VMAX_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK: [[VMAX_V2_I:%.*]] = call <2 x float> @llvm.arm.neon.vmaxs.v2f32(<2 x float> [[VMAX_V_I]], <2 x float> [[VMAX_V1_I]]) #4
+// CHECK: [[VMAX_V2_I:%.*]] = call <2 x float> @llvm.arm.neon.vmaxs.v2f32(<2 x float> %a, <2 x float> %b) #4
// CHECK: [[VMAX_V3_I:%.*]] = bitcast <2 x float> [[VMAX_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VMAX_V3_I]] to <2 x float>
-// CHECK: ret <2 x float> [[TMP2]]
+// CHECK: ret <2 x float> [[VMAX_V2_I]]
float32x2_t test_vmax_f32(float32x2_t a, float32x2_t b) {
return vmax_f32(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vmaxq_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vmaxq_s8(
// CHECK: [[VMAXQ_V_I:%.*]] = call <16 x i8> @llvm.arm.neon.vmaxs.v16i8(<16 x i8> %a, <16 x i8> %b) #4
// CHECK: ret <16 x i8> [[VMAXQ_V_I]]
int8x16_t test_vmaxq_s8(int8x16_t a, int8x16_t b) {
return vmaxq_s8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vmaxq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vmaxq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VMAXQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VMAXQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VMAXQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vmaxs.v8i16(<8 x i16> [[VMAXQ_V_I]], <8 x i16> [[VMAXQ_V1_I]]) #4
+// CHECK: [[VMAXQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vmaxs.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: [[VMAXQ_V3_I:%.*]] = bitcast <8 x i16> [[VMAXQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VMAXQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VMAXQ_V2_I]]
int16x8_t test_vmaxq_s16(int16x8_t a, int16x8_t b) {
return vmaxq_s16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vmaxq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vmaxq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VMAXQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VMAXQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VMAXQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vmaxs.v4i32(<4 x i32> [[VMAXQ_V_I]], <4 x i32> [[VMAXQ_V1_I]]) #4
+// CHECK: [[VMAXQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vmaxs.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VMAXQ_V3_I:%.*]] = bitcast <4 x i32> [[VMAXQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VMAXQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VMAXQ_V2_I]]
int32x4_t test_vmaxq_s32(int32x4_t a, int32x4_t b) {
return vmaxq_s32(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vmaxq_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vmaxq_u8(
// CHECK: [[VMAXQ_V_I:%.*]] = call <16 x i8> @llvm.arm.neon.vmaxu.v16i8(<16 x i8> %a, <16 x i8> %b) #4
// CHECK: ret <16 x i8> [[VMAXQ_V_I]]
uint8x16_t test_vmaxq_u8(uint8x16_t a, uint8x16_t b) {
return vmaxq_u8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vmaxq_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vmaxq_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VMAXQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VMAXQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VMAXQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vmaxu.v8i16(<8 x i16> [[VMAXQ_V_I]], <8 x i16> [[VMAXQ_V1_I]]) #4
+// CHECK: [[VMAXQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vmaxu.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: [[VMAXQ_V3_I:%.*]] = bitcast <8 x i16> [[VMAXQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VMAXQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VMAXQ_V2_I]]
uint16x8_t test_vmaxq_u16(uint16x8_t a, uint16x8_t b) {
return vmaxq_u16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vmaxq_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vmaxq_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VMAXQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VMAXQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VMAXQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vmaxu.v4i32(<4 x i32> [[VMAXQ_V_I]], <4 x i32> [[VMAXQ_V1_I]]) #4
+// CHECK: [[VMAXQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vmaxu.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VMAXQ_V3_I:%.*]] = bitcast <4 x i32> [[VMAXQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VMAXQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VMAXQ_V2_I]]
uint32x4_t test_vmaxq_u32(uint32x4_t a, uint32x4_t b) {
return vmaxq_u32(a, b);
}
-// CHECK-LABEL: define <4 x float> @test_vmaxq_f32(<4 x float> %a, <4 x float> %b) #0 {
+// CHECK-LABEL: @test_vmaxq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %b to <16 x i8>
-// CHECK: [[VMAXQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VMAXQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
-// CHECK: [[VMAXQ_V2_I:%.*]] = call <4 x float> @llvm.arm.neon.vmaxs.v4f32(<4 x float> [[VMAXQ_V_I]], <4 x float> [[VMAXQ_V1_I]]) #4
+// CHECK: [[VMAXQ_V2_I:%.*]] = call <4 x float> @llvm.arm.neon.vmaxs.v4f32(<4 x float> %a, <4 x float> %b) #4
// CHECK: [[VMAXQ_V3_I:%.*]] = bitcast <4 x float> [[VMAXQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VMAXQ_V3_I]] to <4 x float>
-// CHECK: ret <4 x float> [[TMP2]]
+// CHECK: ret <4 x float> [[VMAXQ_V2_I]]
float32x4_t test_vmaxq_f32(float32x4_t a, float32x4_t b) {
return vmaxq_f32(a, b);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vmin_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vmin_s8(
// CHECK: [[VMIN_V_I:%.*]] = call <8 x i8> @llvm.arm.neon.vmins.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VMIN_V_I]]
int8x8_t test_vmin_s8(int8x8_t a, int8x8_t b) {
return vmin_s8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vmin_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vmin_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VMIN_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMIN_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMIN_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vmins.v4i16(<4 x i16> [[VMIN_V_I]], <4 x i16> [[VMIN_V1_I]]) #4
+// CHECK: [[VMIN_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vmins.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VMIN_V3_I:%.*]] = bitcast <4 x i16> [[VMIN_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VMIN_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VMIN_V2_I]]
int16x4_t test_vmin_s16(int16x4_t a, int16x4_t b) {
return vmin_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vmin_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vmin_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VMIN_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMIN_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMIN_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vmins.v2i32(<2 x i32> [[VMIN_V_I]], <2 x i32> [[VMIN_V1_I]]) #4
+// CHECK: [[VMIN_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vmins.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VMIN_V3_I:%.*]] = bitcast <2 x i32> [[VMIN_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VMIN_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VMIN_V2_I]]
int32x2_t test_vmin_s32(int32x2_t a, int32x2_t b) {
return vmin_s32(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vmin_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vmin_u8(
// CHECK: [[VMIN_V_I:%.*]] = call <8 x i8> @llvm.arm.neon.vminu.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VMIN_V_I]]
uint8x8_t test_vmin_u8(uint8x8_t a, uint8x8_t b) {
return vmin_u8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vmin_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vmin_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VMIN_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMIN_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMIN_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vminu.v4i16(<4 x i16> [[VMIN_V_I]], <4 x i16> [[VMIN_V1_I]]) #4
+// CHECK: [[VMIN_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vminu.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VMIN_V3_I:%.*]] = bitcast <4 x i16> [[VMIN_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VMIN_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VMIN_V2_I]]
uint16x4_t test_vmin_u16(uint16x4_t a, uint16x4_t b) {
return vmin_u16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vmin_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vmin_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VMIN_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMIN_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMIN_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vminu.v2i32(<2 x i32> [[VMIN_V_I]], <2 x i32> [[VMIN_V1_I]]) #4
+// CHECK: [[VMIN_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vminu.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VMIN_V3_I:%.*]] = bitcast <2 x i32> [[VMIN_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VMIN_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VMIN_V2_I]]
uint32x2_t test_vmin_u32(uint32x2_t a, uint32x2_t b) {
return vmin_u32(a, b);
}
-// CHECK-LABEL: define <2 x float> @test_vmin_f32(<2 x float> %a, <2 x float> %b) #0 {
+// CHECK-LABEL: @test_vmin_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %b to <8 x i8>
-// CHECK: [[VMIN_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VMIN_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK: [[VMIN_V2_I:%.*]] = call <2 x float> @llvm.arm.neon.vmins.v2f32(<2 x float> [[VMIN_V_I]], <2 x float> [[VMIN_V1_I]]) #4
+// CHECK: [[VMIN_V2_I:%.*]] = call <2 x float> @llvm.arm.neon.vmins.v2f32(<2 x float> %a, <2 x float> %b) #4
// CHECK: [[VMIN_V3_I:%.*]] = bitcast <2 x float> [[VMIN_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VMIN_V3_I]] to <2 x float>
-// CHECK: ret <2 x float> [[TMP2]]
+// CHECK: ret <2 x float> [[VMIN_V2_I]]
float32x2_t test_vmin_f32(float32x2_t a, float32x2_t b) {
return vmin_f32(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vminq_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vminq_s8(
// CHECK: [[VMINQ_V_I:%.*]] = call <16 x i8> @llvm.arm.neon.vmins.v16i8(<16 x i8> %a, <16 x i8> %b) #4
// CHECK: ret <16 x i8> [[VMINQ_V_I]]
int8x16_t test_vminq_s8(int8x16_t a, int8x16_t b) {
return vminq_s8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vminq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vminq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VMINQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VMINQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VMINQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vmins.v8i16(<8 x i16> [[VMINQ_V_I]], <8 x i16> [[VMINQ_V1_I]]) #4
+// CHECK: [[VMINQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vmins.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: [[VMINQ_V3_I:%.*]] = bitcast <8 x i16> [[VMINQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VMINQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VMINQ_V2_I]]
int16x8_t test_vminq_s16(int16x8_t a, int16x8_t b) {
return vminq_s16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vminq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vminq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VMINQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VMINQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VMINQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vmins.v4i32(<4 x i32> [[VMINQ_V_I]], <4 x i32> [[VMINQ_V1_I]]) #4
+// CHECK: [[VMINQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vmins.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VMINQ_V3_I:%.*]] = bitcast <4 x i32> [[VMINQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VMINQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VMINQ_V2_I]]
int32x4_t test_vminq_s32(int32x4_t a, int32x4_t b) {
return vminq_s32(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vminq_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vminq_u8(
// CHECK: [[VMINQ_V_I:%.*]] = call <16 x i8> @llvm.arm.neon.vminu.v16i8(<16 x i8> %a, <16 x i8> %b) #4
// CHECK: ret <16 x i8> [[VMINQ_V_I]]
uint8x16_t test_vminq_u8(uint8x16_t a, uint8x16_t b) {
return vminq_u8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vminq_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vminq_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VMINQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VMINQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VMINQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vminu.v8i16(<8 x i16> [[VMINQ_V_I]], <8 x i16> [[VMINQ_V1_I]]) #4
+// CHECK: [[VMINQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vminu.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: [[VMINQ_V3_I:%.*]] = bitcast <8 x i16> [[VMINQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VMINQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VMINQ_V2_I]]
uint16x8_t test_vminq_u16(uint16x8_t a, uint16x8_t b) {
return vminq_u16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vminq_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vminq_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VMINQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VMINQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VMINQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vminu.v4i32(<4 x i32> [[VMINQ_V_I]], <4 x i32> [[VMINQ_V1_I]]) #4
+// CHECK: [[VMINQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vminu.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VMINQ_V3_I:%.*]] = bitcast <4 x i32> [[VMINQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VMINQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VMINQ_V2_I]]
uint32x4_t test_vminq_u32(uint32x4_t a, uint32x4_t b) {
return vminq_u32(a, b);
}
-// CHECK-LABEL: define <4 x float> @test_vminq_f32(<4 x float> %a, <4 x float> %b) #0 {
+// CHECK-LABEL: @test_vminq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %b to <16 x i8>
-// CHECK: [[VMINQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VMINQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
-// CHECK: [[VMINQ_V2_I:%.*]] = call <4 x float> @llvm.arm.neon.vmins.v4f32(<4 x float> [[VMINQ_V_I]], <4 x float> [[VMINQ_V1_I]]) #4
+// CHECK: [[VMINQ_V2_I:%.*]] = call <4 x float> @llvm.arm.neon.vmins.v4f32(<4 x float> %a, <4 x float> %b) #4
// CHECK: [[VMINQ_V3_I:%.*]] = bitcast <4 x float> [[VMINQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VMINQ_V3_I]] to <4 x float>
-// CHECK: ret <4 x float> [[TMP2]]
+// CHECK: ret <4 x float> [[VMINQ_V2_I]]
float32x4_t test_vminq_f32(float32x4_t a, float32x4_t b) {
return vminq_f32(a, b);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vmla_s8(<8 x i8> %a, <8 x i8> %b, <8 x i8> %c) #0 {
+// CHECK-LABEL: @test_vmla_s8(
// CHECK: [[MUL_I:%.*]] = mul <8 x i8> %b, %c
// CHECK: [[ADD_I:%.*]] = add <8 x i8> %a, [[MUL_I]]
// CHECK: ret <8 x i8> [[ADD_I]]
@@ -8813,7 +7265,7 @@ int8x8_t test_vmla_s8(int8x8_t a, int8x8_t b, int8x8_t c) {
return vmla_s8(a, b, c);
}
-// CHECK-LABEL: define <4 x i16> @test_vmla_s16(<4 x i16> %a, <4 x i16> %b, <4 x i16> %c) #0 {
+// CHECK-LABEL: @test_vmla_s16(
// CHECK: [[MUL_I:%.*]] = mul <4 x i16> %b, %c
// CHECK: [[ADD_I:%.*]] = add <4 x i16> %a, [[MUL_I]]
// CHECK: ret <4 x i16> [[ADD_I]]
@@ -8821,7 +7273,7 @@ int16x4_t test_vmla_s16(int16x4_t a, int16x4_t b, int16x4_t c) {
return vmla_s16(a, b, c);
}
-// CHECK-LABEL: define <2 x i32> @test_vmla_s32(<2 x i32> %a, <2 x i32> %b, <2 x i32> %c) #0 {
+// CHECK-LABEL: @test_vmla_s32(
// CHECK: [[MUL_I:%.*]] = mul <2 x i32> %b, %c
// CHECK: [[ADD_I:%.*]] = add <2 x i32> %a, [[MUL_I]]
// CHECK: ret <2 x i32> [[ADD_I]]
@@ -8829,7 +7281,7 @@ int32x2_t test_vmla_s32(int32x2_t a, int32x2_t b, int32x2_t c) {
return vmla_s32(a, b, c);
}
-// CHECK-LABEL: define <2 x float> @test_vmla_f32(<2 x float> %a, <2 x float> %b, <2 x float> %c) #0 {
+// CHECK-LABEL: @test_vmla_f32(
// CHECK: [[MUL_I:%.*]] = fmul <2 x float> %b, %c
// CHECK: [[ADD_I:%.*]] = fadd <2 x float> %a, [[MUL_I]]
// CHECK: ret <2 x float> [[ADD_I]]
@@ -8837,7 +7289,7 @@ float32x2_t test_vmla_f32(float32x2_t a, float32x2_t b, float32x2_t c) {
return vmla_f32(a, b, c);
}
-// CHECK-LABEL: define <8 x i8> @test_vmla_u8(<8 x i8> %a, <8 x i8> %b, <8 x i8> %c) #0 {
+// CHECK-LABEL: @test_vmla_u8(
// CHECK: [[MUL_I:%.*]] = mul <8 x i8> %b, %c
// CHECK: [[ADD_I:%.*]] = add <8 x i8> %a, [[MUL_I]]
// CHECK: ret <8 x i8> [[ADD_I]]
@@ -8845,7 +7297,7 @@ uint8x8_t test_vmla_u8(uint8x8_t a, uint8x8_t b, uint8x8_t c) {
return vmla_u8(a, b, c);
}
-// CHECK-LABEL: define <4 x i16> @test_vmla_u16(<4 x i16> %a, <4 x i16> %b, <4 x i16> %c) #0 {
+// CHECK-LABEL: @test_vmla_u16(
// CHECK: [[MUL_I:%.*]] = mul <4 x i16> %b, %c
// CHECK: [[ADD_I:%.*]] = add <4 x i16> %a, [[MUL_I]]
// CHECK: ret <4 x i16> [[ADD_I]]
@@ -8853,7 +7305,7 @@ uint16x4_t test_vmla_u16(uint16x4_t a, uint16x4_t b, uint16x4_t c) {
return vmla_u16(a, b, c);
}
-// CHECK-LABEL: define <2 x i32> @test_vmla_u32(<2 x i32> %a, <2 x i32> %b, <2 x i32> %c) #0 {
+// CHECK-LABEL: @test_vmla_u32(
// CHECK: [[MUL_I:%.*]] = mul <2 x i32> %b, %c
// CHECK: [[ADD_I:%.*]] = add <2 x i32> %a, [[MUL_I]]
// CHECK: ret <2 x i32> [[ADD_I]]
@@ -8861,7 +7313,7 @@ uint32x2_t test_vmla_u32(uint32x2_t a, uint32x2_t b, uint32x2_t c) {
return vmla_u32(a, b, c);
}
-// CHECK-LABEL: define <16 x i8> @test_vmlaq_s8(<16 x i8> %a, <16 x i8> %b, <16 x i8> %c) #0 {
+// CHECK-LABEL: @test_vmlaq_s8(
// CHECK: [[MUL_I:%.*]] = mul <16 x i8> %b, %c
// CHECK: [[ADD_I:%.*]] = add <16 x i8> %a, [[MUL_I]]
// CHECK: ret <16 x i8> [[ADD_I]]
@@ -8869,7 +7321,7 @@ int8x16_t test_vmlaq_s8(int8x16_t a, int8x16_t b, int8x16_t c) {
return vmlaq_s8(a, b, c);
}
-// CHECK-LABEL: define <8 x i16> @test_vmlaq_s16(<8 x i16> %a, <8 x i16> %b, <8 x i16> %c) #0 {
+// CHECK-LABEL: @test_vmlaq_s16(
// CHECK: [[MUL_I:%.*]] = mul <8 x i16> %b, %c
// CHECK: [[ADD_I:%.*]] = add <8 x i16> %a, [[MUL_I]]
// CHECK: ret <8 x i16> [[ADD_I]]
@@ -8877,7 +7329,7 @@ int16x8_t test_vmlaq_s16(int16x8_t a, int16x8_t b, int16x8_t c) {
return vmlaq_s16(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlaq_s32(<4 x i32> %a, <4 x i32> %b, <4 x i32> %c) #0 {
+// CHECK-LABEL: @test_vmlaq_s32(
// CHECK: [[MUL_I:%.*]] = mul <4 x i32> %b, %c
// CHECK: [[ADD_I:%.*]] = add <4 x i32> %a, [[MUL_I]]
// CHECK: ret <4 x i32> [[ADD_I]]
@@ -8885,7 +7337,7 @@ int32x4_t test_vmlaq_s32(int32x4_t a, int32x4_t b, int32x4_t c) {
return vmlaq_s32(a, b, c);
}
-// CHECK-LABEL: define <4 x float> @test_vmlaq_f32(<4 x float> %a, <4 x float> %b, <4 x float> %c) #0 {
+// CHECK-LABEL: @test_vmlaq_f32(
// CHECK: [[MUL_I:%.*]] = fmul <4 x float> %b, %c
// CHECK: [[ADD_I:%.*]] = fadd <4 x float> %a, [[MUL_I]]
// CHECK: ret <4 x float> [[ADD_I]]
@@ -8893,7 +7345,7 @@ float32x4_t test_vmlaq_f32(float32x4_t a, float32x4_t b, float32x4_t c) {
return vmlaq_f32(a, b, c);
}
-// CHECK-LABEL: define <16 x i8> @test_vmlaq_u8(<16 x i8> %a, <16 x i8> %b, <16 x i8> %c) #0 {
+// CHECK-LABEL: @test_vmlaq_u8(
// CHECK: [[MUL_I:%.*]] = mul <16 x i8> %b, %c
// CHECK: [[ADD_I:%.*]] = add <16 x i8> %a, [[MUL_I]]
// CHECK: ret <16 x i8> [[ADD_I]]
@@ -8901,7 +7353,7 @@ uint8x16_t test_vmlaq_u8(uint8x16_t a, uint8x16_t b, uint8x16_t c) {
return vmlaq_u8(a, b, c);
}
-// CHECK-LABEL: define <8 x i16> @test_vmlaq_u16(<8 x i16> %a, <8 x i16> %b, <8 x i16> %c) #0 {
+// CHECK-LABEL: @test_vmlaq_u16(
// CHECK: [[MUL_I:%.*]] = mul <8 x i16> %b, %c
// CHECK: [[ADD_I:%.*]] = add <8 x i16> %a, [[MUL_I]]
// CHECK: ret <8 x i16> [[ADD_I]]
@@ -8909,7 +7361,7 @@ uint16x8_t test_vmlaq_u16(uint16x8_t a, uint16x8_t b, uint16x8_t c) {
return vmlaq_u16(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlaq_u32(<4 x i32> %a, <4 x i32> %b, <4 x i32> %c) #0 {
+// CHECK-LABEL: @test_vmlaq_u32(
// CHECK: [[MUL_I:%.*]] = mul <4 x i32> %b, %c
// CHECK: [[ADD_I:%.*]] = add <4 x i32> %a, [[MUL_I]]
// CHECK: ret <4 x i32> [[ADD_I]]
@@ -8917,8 +7369,7 @@ uint32x4_t test_vmlaq_u32(uint32x4_t a, uint32x4_t b, uint32x4_t c) {
return vmlaq_u32(a, b, c);
}
-
-// CHECK-LABEL: define <8 x i16> @test_vmlal_s8(<8 x i16> %a, <8 x i8> %b, <8 x i8> %c) #0 {
+// CHECK-LABEL: @test_vmlal_s8(
// CHECK: [[VMULL_I_I:%.*]] = call <8 x i16> @llvm.arm.neon.vmulls.v8i16(<8 x i8> %b, <8 x i8> %c) #4
// CHECK: [[ADD_I:%.*]] = add <8 x i16> %a, [[VMULL_I_I]]
// CHECK: ret <8 x i16> [[ADD_I]]
@@ -8926,31 +7377,27 @@ int16x8_t test_vmlal_s8(int16x8_t a, int8x8_t b, int8x8_t c) {
return vmlal_s8(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlal_s16(<4 x i32> %a, <4 x i16> %b, <4 x i16> %c) #0 {
+// CHECK-LABEL: @test_vmlal_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %c to <8 x i8>
-// CHECK: [[VMULL_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I_I:%.*]] = call <4 x i32> @llvm.arm.neon.vmulls.v4i32(<4 x i16> [[VMULL_I_I]], <4 x i16> [[VMULL1_I_I]]) #4
+// CHECK: [[VMULL2_I_I:%.*]] = call <4 x i32> @llvm.arm.neon.vmulls.v4i32(<4 x i16> %b, <4 x i16> %c) #4
// CHECK: [[ADD_I:%.*]] = add <4 x i32> %a, [[VMULL2_I_I]]
// CHECK: ret <4 x i32> [[ADD_I]]
int32x4_t test_vmlal_s16(int32x4_t a, int16x4_t b, int16x4_t c) {
return vmlal_s16(a, b, c);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlal_s32(<2 x i64> %a, <2 x i32> %b, <2 x i32> %c) #0 {
+// CHECK-LABEL: @test_vmlal_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %c to <8 x i8>
-// CHECK: [[VMULL_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I_I:%.*]] = call <2 x i64> @llvm.arm.neon.vmulls.v2i64(<2 x i32> [[VMULL_I_I]], <2 x i32> [[VMULL1_I_I]]) #4
+// CHECK: [[VMULL2_I_I:%.*]] = call <2 x i64> @llvm.arm.neon.vmulls.v2i64(<2 x i32> %b, <2 x i32> %c) #4
// CHECK: [[ADD_I:%.*]] = add <2 x i64> %a, [[VMULL2_I_I]]
// CHECK: ret <2 x i64> [[ADD_I]]
int64x2_t test_vmlal_s32(int64x2_t a, int32x2_t b, int32x2_t c) {
return vmlal_s32(a, b, c);
}
-// CHECK-LABEL: define <8 x i16> @test_vmlal_u8(<8 x i16> %a, <8 x i8> %b, <8 x i8> %c) #0 {
+// CHECK-LABEL: @test_vmlal_u8(
// CHECK: [[VMULL_I_I:%.*]] = call <8 x i16> @llvm.arm.neon.vmullu.v8i16(<8 x i8> %b, <8 x i8> %c) #4
// CHECK: [[ADD_I:%.*]] = add <8 x i16> %a, [[VMULL_I_I]]
// CHECK: ret <8 x i16> [[ADD_I]]
@@ -8958,146 +7405,123 @@ uint16x8_t test_vmlal_u8(uint16x8_t a, uint8x8_t b, uint8x8_t c) {
return vmlal_u8(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlal_u16(<4 x i32> %a, <4 x i16> %b, <4 x i16> %c) #0 {
+// CHECK-LABEL: @test_vmlal_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %c to <8 x i8>
-// CHECK: [[VMULL_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I_I:%.*]] = call <4 x i32> @llvm.arm.neon.vmullu.v4i32(<4 x i16> [[VMULL_I_I]], <4 x i16> [[VMULL1_I_I]]) #4
+// CHECK: [[VMULL2_I_I:%.*]] = call <4 x i32> @llvm.arm.neon.vmullu.v4i32(<4 x i16> %b, <4 x i16> %c) #4
// CHECK: [[ADD_I:%.*]] = add <4 x i32> %a, [[VMULL2_I_I]]
// CHECK: ret <4 x i32> [[ADD_I]]
uint32x4_t test_vmlal_u16(uint32x4_t a, uint16x4_t b, uint16x4_t c) {
return vmlal_u16(a, b, c);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlal_u32(<2 x i64> %a, <2 x i32> %b, <2 x i32> %c) #0 {
+// CHECK-LABEL: @test_vmlal_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %c to <8 x i8>
-// CHECK: [[VMULL_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I_I:%.*]] = call <2 x i64> @llvm.arm.neon.vmullu.v2i64(<2 x i32> [[VMULL_I_I]], <2 x i32> [[VMULL1_I_I]]) #4
+// CHECK: [[VMULL2_I_I:%.*]] = call <2 x i64> @llvm.arm.neon.vmullu.v2i64(<2 x i32> %b, <2 x i32> %c) #4
// CHECK: [[ADD_I:%.*]] = add <2 x i64> %a, [[VMULL2_I_I]]
// CHECK: ret <2 x i64> [[ADD_I]]
uint64x2_t test_vmlal_u32(uint64x2_t a, uint32x2_t b, uint32x2_t c) {
return vmlal_u32(a, b, c);
}
-
-// CHECK-LABEL: define <4 x i32> @test_vmlal_lane_s16(<4 x i32> %a, <4 x i16> %b, <4 x i16> %c) #0 {
+// CHECK-LABEL: @test_vmlal_lane_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %c, <4 x i16> %c, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vmulls.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #4
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vmulls.v4i32(<4 x i16> %b, <4 x i16> [[SHUFFLE]]) #4
// CHECK: [[ADD:%.*]] = add <4 x i32> %a, [[VMULL2_I]]
// CHECK: ret <4 x i32> [[ADD]]
int32x4_t test_vmlal_lane_s16(int32x4_t a, int16x4_t b, int16x4_t c) {
return vmlal_lane_s16(a, b, c, 3);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlal_lane_s32(<2 x i64> %a, <2 x i32> %b, <2 x i32> %c) #0 {
+// CHECK-LABEL: @test_vmlal_lane_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %c, <2 x i32> %c, <2 x i32> <i32 1, i32 1>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vmulls.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #4
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vmulls.v2i64(<2 x i32> %b, <2 x i32> [[SHUFFLE]]) #4
// CHECK: [[ADD:%.*]] = add <2 x i64> %a, [[VMULL2_I]]
// CHECK: ret <2 x i64> [[ADD]]
int64x2_t test_vmlal_lane_s32(int64x2_t a, int32x2_t b, int32x2_t c) {
return vmlal_lane_s32(a, b, c, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlal_lane_u16(<4 x i32> %a, <4 x i16> %b, <4 x i16> %c) #0 {
+// CHECK-LABEL: @test_vmlal_lane_u16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %c, <4 x i16> %c, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vmullu.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #4
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vmullu.v4i32(<4 x i16> %b, <4 x i16> [[SHUFFLE]]) #4
// CHECK: [[ADD:%.*]] = add <4 x i32> %a, [[VMULL2_I]]
// CHECK: ret <4 x i32> [[ADD]]
uint32x4_t test_vmlal_lane_u16(uint32x4_t a, uint16x4_t b, uint16x4_t c) {
return vmlal_lane_u16(a, b, c, 3);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlal_lane_u32(<2 x i64> %a, <2 x i32> %b, <2 x i32> %c) #0 {
+// CHECK-LABEL: @test_vmlal_lane_u32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %c, <2 x i32> %c, <2 x i32> <i32 1, i32 1>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vmullu.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #4
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vmullu.v2i64(<2 x i32> %b, <2 x i32> [[SHUFFLE]]) #4
// CHECK: [[ADD:%.*]] = add <2 x i64> %a, [[VMULL2_I]]
// CHECK: ret <2 x i64> [[ADD]]
uint64x2_t test_vmlal_lane_u32(uint64x2_t a, uint32x2_t b, uint32x2_t c) {
return vmlal_lane_u32(a, b, c, 1);
}
-
-// CHECK-LABEL: define <4 x i32> @test_vmlal_n_s16(<4 x i32> %a, <4 x i16> %b, i16 signext %c) #0 {
+// CHECK-LABEL: @test_vmlal_n_s16(
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i16> undef, i16 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i16> [[VECINIT_I]], i16 %c, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i16> [[VECINIT1_I]], i16 %c, i32 2
// CHECK: [[VECINIT3_I:%.*]] = insertelement <4 x i16> [[VECINIT2_I]], i16 %c, i32 3
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[VECINIT3_I]] to <8 x i8>
-// CHECK: [[VMULL_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I_I:%.*]] = call <4 x i32> @llvm.arm.neon.vmulls.v4i32(<4 x i16> [[VMULL_I_I]], <4 x i16> [[VMULL1_I_I]]) #4
+// CHECK: [[VMULL2_I_I:%.*]] = call <4 x i32> @llvm.arm.neon.vmulls.v4i32(<4 x i16> %b, <4 x i16> [[VECINIT3_I]]) #4
// CHECK: [[ADD_I:%.*]] = add <4 x i32> %a, [[VMULL2_I_I]]
// CHECK: ret <4 x i32> [[ADD_I]]
int32x4_t test_vmlal_n_s16(int32x4_t a, int16x4_t b, int16_t c) {
return vmlal_n_s16(a, b, c);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlal_n_s32(<2 x i64> %a, <2 x i32> %b, i32 %c) #0 {
+// CHECK-LABEL: @test_vmlal_n_s32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x i32> undef, i32 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x i32> [[VECINIT_I]], i32 %c, i32 1
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[VECINIT1_I]] to <8 x i8>
-// CHECK: [[VMULL_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I_I:%.*]] = call <2 x i64> @llvm.arm.neon.vmulls.v2i64(<2 x i32> [[VMULL_I_I]], <2 x i32> [[VMULL1_I_I]]) #4
+// CHECK: [[VMULL2_I_I:%.*]] = call <2 x i64> @llvm.arm.neon.vmulls.v2i64(<2 x i32> %b, <2 x i32> [[VECINIT1_I]]) #4
// CHECK: [[ADD_I:%.*]] = add <2 x i64> %a, [[VMULL2_I_I]]
// CHECK: ret <2 x i64> [[ADD_I]]
int64x2_t test_vmlal_n_s32(int64x2_t a, int32x2_t b, int32_t c) {
return vmlal_n_s32(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlal_n_u16(<4 x i32> %a, <4 x i16> %b, i16 zeroext %c) #0 {
+// CHECK-LABEL: @test_vmlal_n_u16(
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i16> undef, i16 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i16> [[VECINIT_I]], i16 %c, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i16> [[VECINIT1_I]], i16 %c, i32 2
// CHECK: [[VECINIT3_I:%.*]] = insertelement <4 x i16> [[VECINIT2_I]], i16 %c, i32 3
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[VECINIT3_I]] to <8 x i8>
-// CHECK: [[VMULL_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I_I:%.*]] = call <4 x i32> @llvm.arm.neon.vmullu.v4i32(<4 x i16> [[VMULL_I_I]], <4 x i16> [[VMULL1_I_I]]) #4
+// CHECK: [[VMULL2_I_I:%.*]] = call <4 x i32> @llvm.arm.neon.vmullu.v4i32(<4 x i16> %b, <4 x i16> [[VECINIT3_I]]) #4
// CHECK: [[ADD_I:%.*]] = add <4 x i32> %a, [[VMULL2_I_I]]
// CHECK: ret <4 x i32> [[ADD_I]]
uint32x4_t test_vmlal_n_u16(uint32x4_t a, uint16x4_t b, uint16_t c) {
return vmlal_n_u16(a, b, c);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlal_n_u32(<2 x i64> %a, <2 x i32> %b, i32 %c) #0 {
+// CHECK-LABEL: @test_vmlal_n_u32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x i32> undef, i32 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x i32> [[VECINIT_I]], i32 %c, i32 1
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[VECINIT1_I]] to <8 x i8>
-// CHECK: [[VMULL_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I_I:%.*]] = call <2 x i64> @llvm.arm.neon.vmullu.v2i64(<2 x i32> [[VMULL_I_I]], <2 x i32> [[VMULL1_I_I]]) #4
+// CHECK: [[VMULL2_I_I:%.*]] = call <2 x i64> @llvm.arm.neon.vmullu.v2i64(<2 x i32> %b, <2 x i32> [[VECINIT1_I]]) #4
// CHECK: [[ADD_I:%.*]] = add <2 x i64> %a, [[VMULL2_I_I]]
// CHECK: ret <2 x i64> [[ADD_I]]
uint64x2_t test_vmlal_n_u32(uint64x2_t a, uint32x2_t b, uint32_t c) {
return vmlal_n_u32(a, b, c);
}
-
-// CHECK-LABEL: define <4 x i16> @test_vmla_lane_s16(<4 x i16> %a, <4 x i16> %b, <4 x i16> %c) #0 {
+// CHECK-LABEL: @test_vmla_lane_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %c, <4 x i16> %c, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[MUL:%.*]] = mul <4 x i16> %b, [[SHUFFLE]]
// CHECK: [[ADD:%.*]] = add <4 x i16> %a, [[MUL]]
@@ -9106,7 +7530,7 @@ int16x4_t test_vmla_lane_s16(int16x4_t a, int16x4_t b, int16x4_t c) {
return vmla_lane_s16(a, b, c, 3);
}
-// CHECK-LABEL: define <2 x i32> @test_vmla_lane_s32(<2 x i32> %a, <2 x i32> %b, <2 x i32> %c) #0 {
+// CHECK-LABEL: @test_vmla_lane_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %c, <2 x i32> %c, <2 x i32> <i32 1, i32 1>
// CHECK: [[MUL:%.*]] = mul <2 x i32> %b, [[SHUFFLE]]
// CHECK: [[ADD:%.*]] = add <2 x i32> %a, [[MUL]]
@@ -9115,7 +7539,7 @@ int32x2_t test_vmla_lane_s32(int32x2_t a, int32x2_t b, int32x2_t c) {
return vmla_lane_s32(a, b, c, 1);
}
-// CHECK-LABEL: define <4 x i16> @test_vmla_lane_u16(<4 x i16> %a, <4 x i16> %b, <4 x i16> %c) #0 {
+// CHECK-LABEL: @test_vmla_lane_u16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %c, <4 x i16> %c, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[MUL:%.*]] = mul <4 x i16> %b, [[SHUFFLE]]
// CHECK: [[ADD:%.*]] = add <4 x i16> %a, [[MUL]]
@@ -9124,7 +7548,7 @@ uint16x4_t test_vmla_lane_u16(uint16x4_t a, uint16x4_t b, uint16x4_t c) {
return vmla_lane_u16(a, b, c, 3);
}
-// CHECK-LABEL: define <2 x i32> @test_vmla_lane_u32(<2 x i32> %a, <2 x i32> %b, <2 x i32> %c) #0 {
+// CHECK-LABEL: @test_vmla_lane_u32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %c, <2 x i32> %c, <2 x i32> <i32 1, i32 1>
// CHECK: [[MUL:%.*]] = mul <2 x i32> %b, [[SHUFFLE]]
// CHECK: [[ADD:%.*]] = add <2 x i32> %a, [[MUL]]
@@ -9133,7 +7557,7 @@ uint32x2_t test_vmla_lane_u32(uint32x2_t a, uint32x2_t b, uint32x2_t c) {
return vmla_lane_u32(a, b, c, 1);
}
-// CHECK-LABEL: define <2 x float> @test_vmla_lane_f32(<2 x float> %a, <2 x float> %b, <2 x float> %c) #0 {
+// CHECK-LABEL: @test_vmla_lane_f32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x float> %c, <2 x float> %c, <2 x i32> <i32 1, i32 1>
// CHECK: [[MUL:%.*]] = fmul <2 x float> %b, [[SHUFFLE]]
// CHECK: [[ADD:%.*]] = fadd <2 x float> %a, [[MUL]]
@@ -9142,7 +7566,7 @@ float32x2_t test_vmla_lane_f32(float32x2_t a, float32x2_t b, float32x2_t c) {
return vmla_lane_f32(a, b, c, 1);
}
-// CHECK-LABEL: define <8 x i16> @test_vmlaq_lane_s16(<8 x i16> %a, <8 x i16> %b, <4 x i16> %c) #0 {
+// CHECK-LABEL: @test_vmlaq_lane_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %c, <4 x i16> %c, <8 x i32> <i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3>
// CHECK: [[MUL:%.*]] = mul <8 x i16> %b, [[SHUFFLE]]
// CHECK: [[ADD:%.*]] = add <8 x i16> %a, [[MUL]]
@@ -9151,7 +7575,7 @@ int16x8_t test_vmlaq_lane_s16(int16x8_t a, int16x8_t b, int16x4_t c) {
return vmlaq_lane_s16(a, b, c, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlaq_lane_s32(<4 x i32> %a, <4 x i32> %b, <2 x i32> %c) #0 {
+// CHECK-LABEL: @test_vmlaq_lane_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %c, <2 x i32> %c, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
// CHECK: [[MUL:%.*]] = mul <4 x i32> %b, [[SHUFFLE]]
// CHECK: [[ADD:%.*]] = add <4 x i32> %a, [[MUL]]
@@ -9160,7 +7584,7 @@ int32x4_t test_vmlaq_lane_s32(int32x4_t a, int32x4_t b, int32x2_t c) {
return vmlaq_lane_s32(a, b, c, 1);
}
-// CHECK-LABEL: define <8 x i16> @test_vmlaq_lane_u16(<8 x i16> %a, <8 x i16> %b, <4 x i16> %c) #0 {
+// CHECK-LABEL: @test_vmlaq_lane_u16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %c, <4 x i16> %c, <8 x i32> <i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3>
// CHECK: [[MUL:%.*]] = mul <8 x i16> %b, [[SHUFFLE]]
// CHECK: [[ADD:%.*]] = add <8 x i16> %a, [[MUL]]
@@ -9169,7 +7593,7 @@ uint16x8_t test_vmlaq_lane_u16(uint16x8_t a, uint16x8_t b, uint16x4_t c) {
return vmlaq_lane_u16(a, b, c, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlaq_lane_u32(<4 x i32> %a, <4 x i32> %b, <2 x i32> %c) #0 {
+// CHECK-LABEL: @test_vmlaq_lane_u32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %c, <2 x i32> %c, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
// CHECK: [[MUL:%.*]] = mul <4 x i32> %b, [[SHUFFLE]]
// CHECK: [[ADD:%.*]] = add <4 x i32> %a, [[MUL]]
@@ -9178,7 +7602,7 @@ uint32x4_t test_vmlaq_lane_u32(uint32x4_t a, uint32x4_t b, uint32x2_t c) {
return vmlaq_lane_u32(a, b, c, 1);
}
-// CHECK-LABEL: define <4 x float> @test_vmlaq_lane_f32(<4 x float> %a, <4 x float> %b, <2 x float> %c) #0 {
+// CHECK-LABEL: @test_vmlaq_lane_f32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x float> %c, <2 x float> %c, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
// CHECK: [[MUL:%.*]] = fmul <4 x float> %b, [[SHUFFLE]]
// CHECK: [[ADD:%.*]] = fadd <4 x float> %a, [[MUL]]
@@ -9187,8 +7611,7 @@ float32x4_t test_vmlaq_lane_f32(float32x4_t a, float32x4_t b, float32x2_t c) {
return vmlaq_lane_f32(a, b, c, 1);
}
-
-// CHECK-LABEL: define <4 x i16> @test_vmla_n_s16(<4 x i16> %a, <4 x i16> %b, i16 signext %c) #0 {
+// CHECK-LABEL: @test_vmla_n_s16(
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i16> undef, i16 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i16> [[VECINIT_I]], i16 %c, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i16> [[VECINIT1_I]], i16 %c, i32 2
@@ -9200,7 +7623,7 @@ int16x4_t test_vmla_n_s16(int16x4_t a, int16x4_t b, int16_t c) {
return vmla_n_s16(a, b, c);
}
-// CHECK-LABEL: define <2 x i32> @test_vmla_n_s32(<2 x i32> %a, <2 x i32> %b, i32 %c) #0 {
+// CHECK-LABEL: @test_vmla_n_s32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x i32> undef, i32 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x i32> [[VECINIT_I]], i32 %c, i32 1
// CHECK: [[MUL_I:%.*]] = mul <2 x i32> %b, [[VECINIT1_I]]
@@ -9210,7 +7633,7 @@ int32x2_t test_vmla_n_s32(int32x2_t a, int32x2_t b, int32_t c) {
return vmla_n_s32(a, b, c);
}
-// CHECK-LABEL: define <4 x i16> @test_vmla_n_u16(<4 x i16> %a, <4 x i16> %b, i16 zeroext %c) #0 {
+// CHECK-LABEL: @test_vmla_n_u16(
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i16> undef, i16 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i16> [[VECINIT_I]], i16 %c, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i16> [[VECINIT1_I]], i16 %c, i32 2
@@ -9222,7 +7645,7 @@ uint16x4_t test_vmla_n_u16(uint16x4_t a, uint16x4_t b, uint16_t c) {
return vmla_n_u16(a, b, c);
}
-// CHECK-LABEL: define <2 x i32> @test_vmla_n_u32(<2 x i32> %a, <2 x i32> %b, i32 %c) #0 {
+// CHECK-LABEL: @test_vmla_n_u32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x i32> undef, i32 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x i32> [[VECINIT_I]], i32 %c, i32 1
// CHECK: [[MUL_I:%.*]] = mul <2 x i32> %b, [[VECINIT1_I]]
@@ -9232,7 +7655,7 @@ uint32x2_t test_vmla_n_u32(uint32x2_t a, uint32x2_t b, uint32_t c) {
return vmla_n_u32(a, b, c);
}
-// CHECK-LABEL: define <2 x float> @test_vmla_n_f32(<2 x float> %a, <2 x float> %b, float %c) #0 {
+// CHECK-LABEL: @test_vmla_n_f32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x float> undef, float %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x float> [[VECINIT_I]], float %c, i32 1
// CHECK: [[MUL_I:%.*]] = fmul <2 x float> %b, [[VECINIT1_I]]
@@ -9242,7 +7665,7 @@ float32x2_t test_vmla_n_f32(float32x2_t a, float32x2_t b, float32_t c) {
return vmla_n_f32(a, b, c);
}
-// CHECK-LABEL: define <8 x i16> @test_vmlaq_n_s16(<8 x i16> %a, <8 x i16> %b, i16 signext %c) #0 {
+// CHECK-LABEL: @test_vmlaq_n_s16(
// CHECK: [[VECINIT_I:%.*]] = insertelement <8 x i16> undef, i16 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <8 x i16> [[VECINIT_I]], i16 %c, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <8 x i16> [[VECINIT1_I]], i16 %c, i32 2
@@ -9258,7 +7681,7 @@ int16x8_t test_vmlaq_n_s16(int16x8_t a, int16x8_t b, int16_t c) {
return vmlaq_n_s16(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlaq_n_s32(<4 x i32> %a, <4 x i32> %b, i32 %c) #0 {
+// CHECK-LABEL: @test_vmlaq_n_s32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i32> undef, i32 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i32> [[VECINIT_I]], i32 %c, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i32> [[VECINIT1_I]], i32 %c, i32 2
@@ -9270,7 +7693,7 @@ int32x4_t test_vmlaq_n_s32(int32x4_t a, int32x4_t b, int32_t c) {
return vmlaq_n_s32(a, b, c);
}
-// CHECK-LABEL: define <8 x i16> @test_vmlaq_n_u16(<8 x i16> %a, <8 x i16> %b, i16 zeroext %c) #0 {
+// CHECK-LABEL: @test_vmlaq_n_u16(
// CHECK: [[VECINIT_I:%.*]] = insertelement <8 x i16> undef, i16 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <8 x i16> [[VECINIT_I]], i16 %c, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <8 x i16> [[VECINIT1_I]], i16 %c, i32 2
@@ -9286,7 +7709,7 @@ uint16x8_t test_vmlaq_n_u16(uint16x8_t a, uint16x8_t b, uint16_t c) {
return vmlaq_n_u16(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlaq_n_u32(<4 x i32> %a, <4 x i32> %b, i32 %c) #0 {
+// CHECK-LABEL: @test_vmlaq_n_u32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i32> undef, i32 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i32> [[VECINIT_I]], i32 %c, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i32> [[VECINIT1_I]], i32 %c, i32 2
@@ -9298,7 +7721,7 @@ uint32x4_t test_vmlaq_n_u32(uint32x4_t a, uint32x4_t b, uint32_t c) {
return vmlaq_n_u32(a, b, c);
}
-// CHECK-LABEL: define <4 x float> @test_vmlaq_n_f32(<4 x float> %a, <4 x float> %b, float %c) #0 {
+// CHECK-LABEL: @test_vmlaq_n_f32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x float> undef, float %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x float> [[VECINIT_I]], float %c, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x float> [[VECINIT1_I]], float %c, i32 2
@@ -9310,8 +7733,7 @@ float32x4_t test_vmlaq_n_f32(float32x4_t a, float32x4_t b, float32_t c) {
return vmlaq_n_f32(a, b, c);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vmls_s8(<8 x i8> %a, <8 x i8> %b, <8 x i8> %c) #0 {
+// CHECK-LABEL: @test_vmls_s8(
// CHECK: [[MUL_I:%.*]] = mul <8 x i8> %b, %c
// CHECK: [[SUB_I:%.*]] = sub <8 x i8> %a, [[MUL_I]]
// CHECK: ret <8 x i8> [[SUB_I]]
@@ -9319,7 +7741,7 @@ int8x8_t test_vmls_s8(int8x8_t a, int8x8_t b, int8x8_t c) {
return vmls_s8(a, b, c);
}
-// CHECK-LABEL: define <4 x i16> @test_vmls_s16(<4 x i16> %a, <4 x i16> %b, <4 x i16> %c) #0 {
+// CHECK-LABEL: @test_vmls_s16(
// CHECK: [[MUL_I:%.*]] = mul <4 x i16> %b, %c
// CHECK: [[SUB_I:%.*]] = sub <4 x i16> %a, [[MUL_I]]
// CHECK: ret <4 x i16> [[SUB_I]]
@@ -9327,7 +7749,7 @@ int16x4_t test_vmls_s16(int16x4_t a, int16x4_t b, int16x4_t c) {
return vmls_s16(a, b, c);
}
-// CHECK-LABEL: define <2 x i32> @test_vmls_s32(<2 x i32> %a, <2 x i32> %b, <2 x i32> %c) #0 {
+// CHECK-LABEL: @test_vmls_s32(
// CHECK: [[MUL_I:%.*]] = mul <2 x i32> %b, %c
// CHECK: [[SUB_I:%.*]] = sub <2 x i32> %a, [[MUL_I]]
// CHECK: ret <2 x i32> [[SUB_I]]
@@ -9335,7 +7757,7 @@ int32x2_t test_vmls_s32(int32x2_t a, int32x2_t b, int32x2_t c) {
return vmls_s32(a, b, c);
}
-// CHECK-LABEL: define <2 x float> @test_vmls_f32(<2 x float> %a, <2 x float> %b, <2 x float> %c) #0 {
+// CHECK-LABEL: @test_vmls_f32(
// CHECK: [[MUL_I:%.*]] = fmul <2 x float> %b, %c
// CHECK: [[SUB_I:%.*]] = fsub <2 x float> %a, [[MUL_I]]
// CHECK: ret <2 x float> [[SUB_I]]
@@ -9343,7 +7765,7 @@ float32x2_t test_vmls_f32(float32x2_t a, float32x2_t b, float32x2_t c) {
return vmls_f32(a, b, c);
}
-// CHECK-LABEL: define <8 x i8> @test_vmls_u8(<8 x i8> %a, <8 x i8> %b, <8 x i8> %c) #0 {
+// CHECK-LABEL: @test_vmls_u8(
// CHECK: [[MUL_I:%.*]] = mul <8 x i8> %b, %c
// CHECK: [[SUB_I:%.*]] = sub <8 x i8> %a, [[MUL_I]]
// CHECK: ret <8 x i8> [[SUB_I]]
@@ -9351,7 +7773,7 @@ uint8x8_t test_vmls_u8(uint8x8_t a, uint8x8_t b, uint8x8_t c) {
return vmls_u8(a, b, c);
}
-// CHECK-LABEL: define <4 x i16> @test_vmls_u16(<4 x i16> %a, <4 x i16> %b, <4 x i16> %c) #0 {
+// CHECK-LABEL: @test_vmls_u16(
// CHECK: [[MUL_I:%.*]] = mul <4 x i16> %b, %c
// CHECK: [[SUB_I:%.*]] = sub <4 x i16> %a, [[MUL_I]]
// CHECK: ret <4 x i16> [[SUB_I]]
@@ -9359,7 +7781,7 @@ uint16x4_t test_vmls_u16(uint16x4_t a, uint16x4_t b, uint16x4_t c) {
return vmls_u16(a, b, c);
}
-// CHECK-LABEL: define <2 x i32> @test_vmls_u32(<2 x i32> %a, <2 x i32> %b, <2 x i32> %c) #0 {
+// CHECK-LABEL: @test_vmls_u32(
// CHECK: [[MUL_I:%.*]] = mul <2 x i32> %b, %c
// CHECK: [[SUB_I:%.*]] = sub <2 x i32> %a, [[MUL_I]]
// CHECK: ret <2 x i32> [[SUB_I]]
@@ -9367,7 +7789,7 @@ uint32x2_t test_vmls_u32(uint32x2_t a, uint32x2_t b, uint32x2_t c) {
return vmls_u32(a, b, c);
}
-// CHECK-LABEL: define <16 x i8> @test_vmlsq_s8(<16 x i8> %a, <16 x i8> %b, <16 x i8> %c) #0 {
+// CHECK-LABEL: @test_vmlsq_s8(
// CHECK: [[MUL_I:%.*]] = mul <16 x i8> %b, %c
// CHECK: [[SUB_I:%.*]] = sub <16 x i8> %a, [[MUL_I]]
// CHECK: ret <16 x i8> [[SUB_I]]
@@ -9375,7 +7797,7 @@ int8x16_t test_vmlsq_s8(int8x16_t a, int8x16_t b, int8x16_t c) {
return vmlsq_s8(a, b, c);
}
-// CHECK-LABEL: define <8 x i16> @test_vmlsq_s16(<8 x i16> %a, <8 x i16> %b, <8 x i16> %c) #0 {
+// CHECK-LABEL: @test_vmlsq_s16(
// CHECK: [[MUL_I:%.*]] = mul <8 x i16> %b, %c
// CHECK: [[SUB_I:%.*]] = sub <8 x i16> %a, [[MUL_I]]
// CHECK: ret <8 x i16> [[SUB_I]]
@@ -9383,7 +7805,7 @@ int16x8_t test_vmlsq_s16(int16x8_t a, int16x8_t b, int16x8_t c) {
return vmlsq_s16(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlsq_s32(<4 x i32> %a, <4 x i32> %b, <4 x i32> %c) #0 {
+// CHECK-LABEL: @test_vmlsq_s32(
// CHECK: [[MUL_I:%.*]] = mul <4 x i32> %b, %c
// CHECK: [[SUB_I:%.*]] = sub <4 x i32> %a, [[MUL_I]]
// CHECK: ret <4 x i32> [[SUB_I]]
@@ -9391,7 +7813,7 @@ int32x4_t test_vmlsq_s32(int32x4_t a, int32x4_t b, int32x4_t c) {
return vmlsq_s32(a, b, c);
}
-// CHECK-LABEL: define <4 x float> @test_vmlsq_f32(<4 x float> %a, <4 x float> %b, <4 x float> %c) #0 {
+// CHECK-LABEL: @test_vmlsq_f32(
// CHECK: [[MUL_I:%.*]] = fmul <4 x float> %b, %c
// CHECK: [[SUB_I:%.*]] = fsub <4 x float> %a, [[MUL_I]]
// CHECK: ret <4 x float> [[SUB_I]]
@@ -9399,7 +7821,7 @@ float32x4_t test_vmlsq_f32(float32x4_t a, float32x4_t b, float32x4_t c) {
return vmlsq_f32(a, b, c);
}
-// CHECK-LABEL: define <16 x i8> @test_vmlsq_u8(<16 x i8> %a, <16 x i8> %b, <16 x i8> %c) #0 {
+// CHECK-LABEL: @test_vmlsq_u8(
// CHECK: [[MUL_I:%.*]] = mul <16 x i8> %b, %c
// CHECK: [[SUB_I:%.*]] = sub <16 x i8> %a, [[MUL_I]]
// CHECK: ret <16 x i8> [[SUB_I]]
@@ -9407,7 +7829,7 @@ uint8x16_t test_vmlsq_u8(uint8x16_t a, uint8x16_t b, uint8x16_t c) {
return vmlsq_u8(a, b, c);
}
-// CHECK-LABEL: define <8 x i16> @test_vmlsq_u16(<8 x i16> %a, <8 x i16> %b, <8 x i16> %c) #0 {
+// CHECK-LABEL: @test_vmlsq_u16(
// CHECK: [[MUL_I:%.*]] = mul <8 x i16> %b, %c
// CHECK: [[SUB_I:%.*]] = sub <8 x i16> %a, [[MUL_I]]
// CHECK: ret <8 x i16> [[SUB_I]]
@@ -9415,7 +7837,7 @@ uint16x8_t test_vmlsq_u16(uint16x8_t a, uint16x8_t b, uint16x8_t c) {
return vmlsq_u16(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlsq_u32(<4 x i32> %a, <4 x i32> %b, <4 x i32> %c) #0 {
+// CHECK-LABEL: @test_vmlsq_u32(
// CHECK: [[MUL_I:%.*]] = mul <4 x i32> %b, %c
// CHECK: [[SUB_I:%.*]] = sub <4 x i32> %a, [[MUL_I]]
// CHECK: ret <4 x i32> [[SUB_I]]
@@ -9423,8 +7845,7 @@ uint32x4_t test_vmlsq_u32(uint32x4_t a, uint32x4_t b, uint32x4_t c) {
return vmlsq_u32(a, b, c);
}
-
-// CHECK-LABEL: define <8 x i16> @test_vmlsl_s8(<8 x i16> %a, <8 x i8> %b, <8 x i8> %c) #0 {
+// CHECK-LABEL: @test_vmlsl_s8(
// CHECK: [[VMULL_I_I:%.*]] = call <8 x i16> @llvm.arm.neon.vmulls.v8i16(<8 x i8> %b, <8 x i8> %c) #4
// CHECK: [[SUB_I:%.*]] = sub <8 x i16> %a, [[VMULL_I_I]]
// CHECK: ret <8 x i16> [[SUB_I]]
@@ -9432,31 +7853,27 @@ int16x8_t test_vmlsl_s8(int16x8_t a, int8x8_t b, int8x8_t c) {
return vmlsl_s8(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlsl_s16(<4 x i32> %a, <4 x i16> %b, <4 x i16> %c) #0 {
+// CHECK-LABEL: @test_vmlsl_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %c to <8 x i8>
-// CHECK: [[VMULL_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I_I:%.*]] = call <4 x i32> @llvm.arm.neon.vmulls.v4i32(<4 x i16> [[VMULL_I_I]], <4 x i16> [[VMULL1_I_I]]) #4
+// CHECK: [[VMULL2_I_I:%.*]] = call <4 x i32> @llvm.arm.neon.vmulls.v4i32(<4 x i16> %b, <4 x i16> %c) #4
// CHECK: [[SUB_I:%.*]] = sub <4 x i32> %a, [[VMULL2_I_I]]
// CHECK: ret <4 x i32> [[SUB_I]]
int32x4_t test_vmlsl_s16(int32x4_t a, int16x4_t b, int16x4_t c) {
return vmlsl_s16(a, b, c);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlsl_s32(<2 x i64> %a, <2 x i32> %b, <2 x i32> %c) #0 {
+// CHECK-LABEL: @test_vmlsl_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %c to <8 x i8>
-// CHECK: [[VMULL_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I_I:%.*]] = call <2 x i64> @llvm.arm.neon.vmulls.v2i64(<2 x i32> [[VMULL_I_I]], <2 x i32> [[VMULL1_I_I]]) #4
+// CHECK: [[VMULL2_I_I:%.*]] = call <2 x i64> @llvm.arm.neon.vmulls.v2i64(<2 x i32> %b, <2 x i32> %c) #4
// CHECK: [[SUB_I:%.*]] = sub <2 x i64> %a, [[VMULL2_I_I]]
// CHECK: ret <2 x i64> [[SUB_I]]
int64x2_t test_vmlsl_s32(int64x2_t a, int32x2_t b, int32x2_t c) {
return vmlsl_s32(a, b, c);
}
-// CHECK-LABEL: define <8 x i16> @test_vmlsl_u8(<8 x i16> %a, <8 x i8> %b, <8 x i8> %c) #0 {
+// CHECK-LABEL: @test_vmlsl_u8(
// CHECK: [[VMULL_I_I:%.*]] = call <8 x i16> @llvm.arm.neon.vmullu.v8i16(<8 x i8> %b, <8 x i8> %c) #4
// CHECK: [[SUB_I:%.*]] = sub <8 x i16> %a, [[VMULL_I_I]]
// CHECK: ret <8 x i16> [[SUB_I]]
@@ -9464,146 +7881,123 @@ uint16x8_t test_vmlsl_u8(uint16x8_t a, uint8x8_t b, uint8x8_t c) {
return vmlsl_u8(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlsl_u16(<4 x i32> %a, <4 x i16> %b, <4 x i16> %c) #0 {
+// CHECK-LABEL: @test_vmlsl_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %c to <8 x i8>
-// CHECK: [[VMULL_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I_I:%.*]] = call <4 x i32> @llvm.arm.neon.vmullu.v4i32(<4 x i16> [[VMULL_I_I]], <4 x i16> [[VMULL1_I_I]]) #4
+// CHECK: [[VMULL2_I_I:%.*]] = call <4 x i32> @llvm.arm.neon.vmullu.v4i32(<4 x i16> %b, <4 x i16> %c) #4
// CHECK: [[SUB_I:%.*]] = sub <4 x i32> %a, [[VMULL2_I_I]]
// CHECK: ret <4 x i32> [[SUB_I]]
uint32x4_t test_vmlsl_u16(uint32x4_t a, uint16x4_t b, uint16x4_t c) {
return vmlsl_u16(a, b, c);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlsl_u32(<2 x i64> %a, <2 x i32> %b, <2 x i32> %c) #0 {
+// CHECK-LABEL: @test_vmlsl_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %c to <8 x i8>
-// CHECK: [[VMULL_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I_I:%.*]] = call <2 x i64> @llvm.arm.neon.vmullu.v2i64(<2 x i32> [[VMULL_I_I]], <2 x i32> [[VMULL1_I_I]]) #4
+// CHECK: [[VMULL2_I_I:%.*]] = call <2 x i64> @llvm.arm.neon.vmullu.v2i64(<2 x i32> %b, <2 x i32> %c) #4
// CHECK: [[SUB_I:%.*]] = sub <2 x i64> %a, [[VMULL2_I_I]]
// CHECK: ret <2 x i64> [[SUB_I]]
uint64x2_t test_vmlsl_u32(uint64x2_t a, uint32x2_t b, uint32x2_t c) {
return vmlsl_u32(a, b, c);
}
-
-// CHECK-LABEL: define <4 x i32> @test_vmlsl_lane_s16(<4 x i32> %a, <4 x i16> %b, <4 x i16> %c) #0 {
+// CHECK-LABEL: @test_vmlsl_lane_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %c, <4 x i16> %c, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vmulls.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #4
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vmulls.v4i32(<4 x i16> %b, <4 x i16> [[SHUFFLE]]) #4
// CHECK: [[SUB:%.*]] = sub <4 x i32> %a, [[VMULL2_I]]
// CHECK: ret <4 x i32> [[SUB]]
int32x4_t test_vmlsl_lane_s16(int32x4_t a, int16x4_t b, int16x4_t c) {
return vmlsl_lane_s16(a, b, c, 3);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlsl_lane_s32(<2 x i64> %a, <2 x i32> %b, <2 x i32> %c) #0 {
+// CHECK-LABEL: @test_vmlsl_lane_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %c, <2 x i32> %c, <2 x i32> <i32 1, i32 1>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vmulls.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #4
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vmulls.v2i64(<2 x i32> %b, <2 x i32> [[SHUFFLE]]) #4
// CHECK: [[SUB:%.*]] = sub <2 x i64> %a, [[VMULL2_I]]
// CHECK: ret <2 x i64> [[SUB]]
int64x2_t test_vmlsl_lane_s32(int64x2_t a, int32x2_t b, int32x2_t c) {
return vmlsl_lane_s32(a, b, c, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlsl_lane_u16(<4 x i32> %a, <4 x i16> %b, <4 x i16> %c) #0 {
+// CHECK-LABEL: @test_vmlsl_lane_u16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %c, <4 x i16> %c, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vmullu.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #4
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vmullu.v4i32(<4 x i16> %b, <4 x i16> [[SHUFFLE]]) #4
// CHECK: [[SUB:%.*]] = sub <4 x i32> %a, [[VMULL2_I]]
// CHECK: ret <4 x i32> [[SUB]]
uint32x4_t test_vmlsl_lane_u16(uint32x4_t a, uint16x4_t b, uint16x4_t c) {
return vmlsl_lane_u16(a, b, c, 3);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlsl_lane_u32(<2 x i64> %a, <2 x i32> %b, <2 x i32> %c) #0 {
+// CHECK-LABEL: @test_vmlsl_lane_u32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %c, <2 x i32> %c, <2 x i32> <i32 1, i32 1>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vmullu.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #4
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vmullu.v2i64(<2 x i32> %b, <2 x i32> [[SHUFFLE]]) #4
// CHECK: [[SUB:%.*]] = sub <2 x i64> %a, [[VMULL2_I]]
// CHECK: ret <2 x i64> [[SUB]]
uint64x2_t test_vmlsl_lane_u32(uint64x2_t a, uint32x2_t b, uint32x2_t c) {
return vmlsl_lane_u32(a, b, c, 1);
}
-
-// CHECK-LABEL: define <4 x i32> @test_vmlsl_n_s16(<4 x i32> %a, <4 x i16> %b, i16 signext %c) #0 {
+// CHECK-LABEL: @test_vmlsl_n_s16(
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i16> undef, i16 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i16> [[VECINIT_I]], i16 %c, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i16> [[VECINIT1_I]], i16 %c, i32 2
// CHECK: [[VECINIT3_I:%.*]] = insertelement <4 x i16> [[VECINIT2_I]], i16 %c, i32 3
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[VECINIT3_I]] to <8 x i8>
-// CHECK: [[VMULL_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I_I:%.*]] = call <4 x i32> @llvm.arm.neon.vmulls.v4i32(<4 x i16> [[VMULL_I_I]], <4 x i16> [[VMULL1_I_I]]) #4
+// CHECK: [[VMULL2_I_I:%.*]] = call <4 x i32> @llvm.arm.neon.vmulls.v4i32(<4 x i16> %b, <4 x i16> [[VECINIT3_I]]) #4
// CHECK: [[SUB_I:%.*]] = sub <4 x i32> %a, [[VMULL2_I_I]]
// CHECK: ret <4 x i32> [[SUB_I]]
int32x4_t test_vmlsl_n_s16(int32x4_t a, int16x4_t b, int16_t c) {
return vmlsl_n_s16(a, b, c);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlsl_n_s32(<2 x i64> %a, <2 x i32> %b, i32 %c) #0 {
+// CHECK-LABEL: @test_vmlsl_n_s32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x i32> undef, i32 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x i32> [[VECINIT_I]], i32 %c, i32 1
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[VECINIT1_I]] to <8 x i8>
-// CHECK: [[VMULL_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I_I:%.*]] = call <2 x i64> @llvm.arm.neon.vmulls.v2i64(<2 x i32> [[VMULL_I_I]], <2 x i32> [[VMULL1_I_I]]) #4
+// CHECK: [[VMULL2_I_I:%.*]] = call <2 x i64> @llvm.arm.neon.vmulls.v2i64(<2 x i32> %b, <2 x i32> [[VECINIT1_I]]) #4
// CHECK: [[SUB_I:%.*]] = sub <2 x i64> %a, [[VMULL2_I_I]]
// CHECK: ret <2 x i64> [[SUB_I]]
int64x2_t test_vmlsl_n_s32(int64x2_t a, int32x2_t b, int32_t c) {
return vmlsl_n_s32(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlsl_n_u16(<4 x i32> %a, <4 x i16> %b, i16 zeroext %c) #0 {
+// CHECK-LABEL: @test_vmlsl_n_u16(
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i16> undef, i16 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i16> [[VECINIT_I]], i16 %c, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i16> [[VECINIT1_I]], i16 %c, i32 2
// CHECK: [[VECINIT3_I:%.*]] = insertelement <4 x i16> [[VECINIT2_I]], i16 %c, i32 3
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[VECINIT3_I]] to <8 x i8>
-// CHECK: [[VMULL_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I_I:%.*]] = call <4 x i32> @llvm.arm.neon.vmullu.v4i32(<4 x i16> [[VMULL_I_I]], <4 x i16> [[VMULL1_I_I]]) #4
+// CHECK: [[VMULL2_I_I:%.*]] = call <4 x i32> @llvm.arm.neon.vmullu.v4i32(<4 x i16> %b, <4 x i16> [[VECINIT3_I]]) #4
// CHECK: [[SUB_I:%.*]] = sub <4 x i32> %a, [[VMULL2_I_I]]
// CHECK: ret <4 x i32> [[SUB_I]]
uint32x4_t test_vmlsl_n_u16(uint32x4_t a, uint16x4_t b, uint16_t c) {
return vmlsl_n_u16(a, b, c);
}
-// CHECK-LABEL: define <2 x i64> @test_vmlsl_n_u32(<2 x i64> %a, <2 x i32> %b, i32 %c) #0 {
+// CHECK-LABEL: @test_vmlsl_n_u32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x i32> undef, i32 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x i32> [[VECINIT_I]], i32 %c, i32 1
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[VECINIT1_I]] to <8 x i8>
-// CHECK: [[VMULL_I_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I_I:%.*]] = call <2 x i64> @llvm.arm.neon.vmullu.v2i64(<2 x i32> [[VMULL_I_I]], <2 x i32> [[VMULL1_I_I]]) #4
+// CHECK: [[VMULL2_I_I:%.*]] = call <2 x i64> @llvm.arm.neon.vmullu.v2i64(<2 x i32> %b, <2 x i32> [[VECINIT1_I]]) #4
// CHECK: [[SUB_I:%.*]] = sub <2 x i64> %a, [[VMULL2_I_I]]
// CHECK: ret <2 x i64> [[SUB_I]]
uint64x2_t test_vmlsl_n_u32(uint64x2_t a, uint32x2_t b, uint32_t c) {
return vmlsl_n_u32(a, b, c);
}
-
-// CHECK-LABEL: define <4 x i16> @test_vmls_lane_s16(<4 x i16> %a, <4 x i16> %b, <4 x i16> %c) #0 {
+// CHECK-LABEL: @test_vmls_lane_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %c, <4 x i16> %c, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[MUL:%.*]] = mul <4 x i16> %b, [[SHUFFLE]]
// CHECK: [[SUB:%.*]] = sub <4 x i16> %a, [[MUL]]
@@ -9612,7 +8006,7 @@ int16x4_t test_vmls_lane_s16(int16x4_t a, int16x4_t b, int16x4_t c) {
return vmls_lane_s16(a, b, c, 3);
}
-// CHECK-LABEL: define <2 x i32> @test_vmls_lane_s32(<2 x i32> %a, <2 x i32> %b, <2 x i32> %c) #0 {
+// CHECK-LABEL: @test_vmls_lane_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %c, <2 x i32> %c, <2 x i32> <i32 1, i32 1>
// CHECK: [[MUL:%.*]] = mul <2 x i32> %b, [[SHUFFLE]]
// CHECK: [[SUB:%.*]] = sub <2 x i32> %a, [[MUL]]
@@ -9621,7 +8015,7 @@ int32x2_t test_vmls_lane_s32(int32x2_t a, int32x2_t b, int32x2_t c) {
return vmls_lane_s32(a, b, c, 1);
}
-// CHECK-LABEL: define <4 x i16> @test_vmls_lane_u16(<4 x i16> %a, <4 x i16> %b, <4 x i16> %c) #0 {
+// CHECK-LABEL: @test_vmls_lane_u16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %c, <4 x i16> %c, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[MUL:%.*]] = mul <4 x i16> %b, [[SHUFFLE]]
// CHECK: [[SUB:%.*]] = sub <4 x i16> %a, [[MUL]]
@@ -9630,7 +8024,7 @@ uint16x4_t test_vmls_lane_u16(uint16x4_t a, uint16x4_t b, uint16x4_t c) {
return vmls_lane_u16(a, b, c, 3);
}
-// CHECK-LABEL: define <2 x i32> @test_vmls_lane_u32(<2 x i32> %a, <2 x i32> %b, <2 x i32> %c) #0 {
+// CHECK-LABEL: @test_vmls_lane_u32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %c, <2 x i32> %c, <2 x i32> <i32 1, i32 1>
// CHECK: [[MUL:%.*]] = mul <2 x i32> %b, [[SHUFFLE]]
// CHECK: [[SUB:%.*]] = sub <2 x i32> %a, [[MUL]]
@@ -9639,7 +8033,7 @@ uint32x2_t test_vmls_lane_u32(uint32x2_t a, uint32x2_t b, uint32x2_t c) {
return vmls_lane_u32(a, b, c, 1);
}
-// CHECK-LABEL: define <2 x float> @test_vmls_lane_f32(<2 x float> %a, <2 x float> %b, <2 x float> %c) #0 {
+// CHECK-LABEL: @test_vmls_lane_f32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x float> %c, <2 x float> %c, <2 x i32> <i32 1, i32 1>
// CHECK: [[MUL:%.*]] = fmul <2 x float> %b, [[SHUFFLE]]
// CHECK: [[SUB:%.*]] = fsub <2 x float> %a, [[MUL]]
@@ -9648,7 +8042,7 @@ float32x2_t test_vmls_lane_f32(float32x2_t a, float32x2_t b, float32x2_t c) {
return vmls_lane_f32(a, b, c, 1);
}
-// CHECK-LABEL: define <8 x i16> @test_vmlsq_lane_s16(<8 x i16> %a, <8 x i16> %b, <4 x i16> %c) #0 {
+// CHECK-LABEL: @test_vmlsq_lane_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %c, <4 x i16> %c, <8 x i32> <i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3>
// CHECK: [[MUL:%.*]] = mul <8 x i16> %b, [[SHUFFLE]]
// CHECK: [[SUB:%.*]] = sub <8 x i16> %a, [[MUL]]
@@ -9657,7 +8051,7 @@ int16x8_t test_vmlsq_lane_s16(int16x8_t a, int16x8_t b, int16x4_t c) {
return vmlsq_lane_s16(a, b, c, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlsq_lane_s32(<4 x i32> %a, <4 x i32> %b, <2 x i32> %c) #0 {
+// CHECK-LABEL: @test_vmlsq_lane_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %c, <2 x i32> %c, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
// CHECK: [[MUL:%.*]] = mul <4 x i32> %b, [[SHUFFLE]]
// CHECK: [[SUB:%.*]] = sub <4 x i32> %a, [[MUL]]
@@ -9666,7 +8060,7 @@ int32x4_t test_vmlsq_lane_s32(int32x4_t a, int32x4_t b, int32x2_t c) {
return vmlsq_lane_s32(a, b, c, 1);
}
-// CHECK-LABEL: define <8 x i16> @test_vmlsq_lane_u16(<8 x i16> %a, <8 x i16> %b, <4 x i16> %c) #0 {
+// CHECK-LABEL: @test_vmlsq_lane_u16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %c, <4 x i16> %c, <8 x i32> <i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3>
// CHECK: [[MUL:%.*]] = mul <8 x i16> %b, [[SHUFFLE]]
// CHECK: [[SUB:%.*]] = sub <8 x i16> %a, [[MUL]]
@@ -9675,7 +8069,7 @@ uint16x8_t test_vmlsq_lane_u16(uint16x8_t a, uint16x8_t b, uint16x4_t c) {
return vmlsq_lane_u16(a, b, c, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlsq_lane_u32(<4 x i32> %a, <4 x i32> %b, <2 x i32> %c) #0 {
+// CHECK-LABEL: @test_vmlsq_lane_u32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %c, <2 x i32> %c, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
// CHECK: [[MUL:%.*]] = mul <4 x i32> %b, [[SHUFFLE]]
// CHECK: [[SUB:%.*]] = sub <4 x i32> %a, [[MUL]]
@@ -9684,7 +8078,7 @@ uint32x4_t test_vmlsq_lane_u32(uint32x4_t a, uint32x4_t b, uint32x2_t c) {
return vmlsq_lane_u32(a, b, c, 1);
}
-// CHECK-LABEL: define <4 x float> @test_vmlsq_lane_f32(<4 x float> %a, <4 x float> %b, <2 x float> %c) #0 {
+// CHECK-LABEL: @test_vmlsq_lane_f32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x float> %c, <2 x float> %c, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
// CHECK: [[MUL:%.*]] = fmul <4 x float> %b, [[SHUFFLE]]
// CHECK: [[SUB:%.*]] = fsub <4 x float> %a, [[MUL]]
@@ -9693,8 +8087,7 @@ float32x4_t test_vmlsq_lane_f32(float32x4_t a, float32x4_t b, float32x2_t c) {
return vmlsq_lane_f32(a, b, c, 1);
}
-
-// CHECK-LABEL: define <4 x i16> @test_vmls_n_s16(<4 x i16> %a, <4 x i16> %b, i16 signext %c) #0 {
+// CHECK-LABEL: @test_vmls_n_s16(
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i16> undef, i16 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i16> [[VECINIT_I]], i16 %c, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i16> [[VECINIT1_I]], i16 %c, i32 2
@@ -9706,7 +8099,7 @@ int16x4_t test_vmls_n_s16(int16x4_t a, int16x4_t b, int16_t c) {
return vmls_n_s16(a, b, c);
}
-// CHECK-LABEL: define <2 x i32> @test_vmls_n_s32(<2 x i32> %a, <2 x i32> %b, i32 %c) #0 {
+// CHECK-LABEL: @test_vmls_n_s32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x i32> undef, i32 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x i32> [[VECINIT_I]], i32 %c, i32 1
// CHECK: [[MUL_I:%.*]] = mul <2 x i32> %b, [[VECINIT1_I]]
@@ -9716,7 +8109,7 @@ int32x2_t test_vmls_n_s32(int32x2_t a, int32x2_t b, int32_t c) {
return vmls_n_s32(a, b, c);
}
-// CHECK-LABEL: define <4 x i16> @test_vmls_n_u16(<4 x i16> %a, <4 x i16> %b, i16 zeroext %c) #0 {
+// CHECK-LABEL: @test_vmls_n_u16(
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i16> undef, i16 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i16> [[VECINIT_I]], i16 %c, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i16> [[VECINIT1_I]], i16 %c, i32 2
@@ -9728,7 +8121,7 @@ uint16x4_t test_vmls_n_u16(uint16x4_t a, uint16x4_t b, uint16_t c) {
return vmls_n_u16(a, b, c);
}
-// CHECK-LABEL: define <2 x i32> @test_vmls_n_u32(<2 x i32> %a, <2 x i32> %b, i32 %c) #0 {
+// CHECK-LABEL: @test_vmls_n_u32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x i32> undef, i32 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x i32> [[VECINIT_I]], i32 %c, i32 1
// CHECK: [[MUL_I:%.*]] = mul <2 x i32> %b, [[VECINIT1_I]]
@@ -9738,7 +8131,7 @@ uint32x2_t test_vmls_n_u32(uint32x2_t a, uint32x2_t b, uint32_t c) {
return vmls_n_u32(a, b, c);
}
-// CHECK-LABEL: define <2 x float> @test_vmls_n_f32(<2 x float> %a, <2 x float> %b, float %c) #0 {
+// CHECK-LABEL: @test_vmls_n_f32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x float> undef, float %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x float> [[VECINIT_I]], float %c, i32 1
// CHECK: [[MUL_I:%.*]] = fmul <2 x float> %b, [[VECINIT1_I]]
@@ -9748,7 +8141,7 @@ float32x2_t test_vmls_n_f32(float32x2_t a, float32x2_t b, float32_t c) {
return vmls_n_f32(a, b, c);
}
-// CHECK-LABEL: define <8 x i16> @test_vmlsq_n_s16(<8 x i16> %a, <8 x i16> %b, i16 signext %c) #0 {
+// CHECK-LABEL: @test_vmlsq_n_s16(
// CHECK: [[VECINIT_I:%.*]] = insertelement <8 x i16> undef, i16 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <8 x i16> [[VECINIT_I]], i16 %c, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <8 x i16> [[VECINIT1_I]], i16 %c, i32 2
@@ -9764,7 +8157,7 @@ int16x8_t test_vmlsq_n_s16(int16x8_t a, int16x8_t b, int16_t c) {
return vmlsq_n_s16(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlsq_n_s32(<4 x i32> %a, <4 x i32> %b, i32 %c) #0 {
+// CHECK-LABEL: @test_vmlsq_n_s32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i32> undef, i32 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i32> [[VECINIT_I]], i32 %c, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i32> [[VECINIT1_I]], i32 %c, i32 2
@@ -9776,7 +8169,7 @@ int32x4_t test_vmlsq_n_s32(int32x4_t a, int32x4_t b, int32_t c) {
return vmlsq_n_s32(a, b, c);
}
-// CHECK-LABEL: define <8 x i16> @test_vmlsq_n_u16(<8 x i16> %a, <8 x i16> %b, i16 zeroext %c) #0 {
+// CHECK-LABEL: @test_vmlsq_n_u16(
// CHECK: [[VECINIT_I:%.*]] = insertelement <8 x i16> undef, i16 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <8 x i16> [[VECINIT_I]], i16 %c, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <8 x i16> [[VECINIT1_I]], i16 %c, i32 2
@@ -9792,7 +8185,7 @@ uint16x8_t test_vmlsq_n_u16(uint16x8_t a, uint16x8_t b, uint16_t c) {
return vmlsq_n_u16(a, b, c);
}
-// CHECK-LABEL: define <4 x i32> @test_vmlsq_n_u32(<4 x i32> %a, <4 x i32> %b, i32 %c) #0 {
+// CHECK-LABEL: @test_vmlsq_n_u32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i32> undef, i32 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i32> [[VECINIT_I]], i32 %c, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i32> [[VECINIT1_I]], i32 %c, i32 2
@@ -9804,7 +8197,7 @@ uint32x4_t test_vmlsq_n_u32(uint32x4_t a, uint32x4_t b, uint32_t c) {
return vmlsq_n_u32(a, b, c);
}
-// CHECK-LABEL: define <4 x float> @test_vmlsq_n_f32(<4 x float> %a, <4 x float> %b, float %c) #0 {
+// CHECK-LABEL: @test_vmlsq_n_f32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x float> undef, float %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x float> [[VECINIT_I]], float %c, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x float> [[VECINIT1_I]], float %c, i32 2
@@ -9816,114 +8209,101 @@ float32x4_t test_vmlsq_n_f32(float32x4_t a, float32x4_t b, float32_t c) {
return vmlsq_n_f32(a, b, c);
}
-
-// CHECK-LABEL: define <8 x i16> @test_vmovl_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vmovl_s8(
// CHECK: [[VMOVL_I:%.*]] = sext <8 x i8> %a to <8 x i16>
// CHECK: ret <8 x i16> [[VMOVL_I]]
int16x8_t test_vmovl_s8(int8x8_t a) {
return vmovl_s8(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vmovl_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vmovl_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMOVL_I:%.*]] = sext <4 x i16> [[TMP1]] to <4 x i32>
+// CHECK: [[VMOVL_I:%.*]] = sext <4 x i16> %a to <4 x i32>
// CHECK: ret <4 x i32> [[VMOVL_I]]
int32x4_t test_vmovl_s16(int16x4_t a) {
return vmovl_s16(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vmovl_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vmovl_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMOVL_I:%.*]] = sext <2 x i32> [[TMP1]] to <2 x i64>
+// CHECK: [[VMOVL_I:%.*]] = sext <2 x i32> %a to <2 x i64>
// CHECK: ret <2 x i64> [[VMOVL_I]]
int64x2_t test_vmovl_s32(int32x2_t a) {
return vmovl_s32(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vmovl_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vmovl_u8(
// CHECK: [[VMOVL_I:%.*]] = zext <8 x i8> %a to <8 x i16>
// CHECK: ret <8 x i16> [[VMOVL_I]]
uint16x8_t test_vmovl_u8(uint8x8_t a) {
return vmovl_u8(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vmovl_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vmovl_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMOVL_I:%.*]] = zext <4 x i16> [[TMP1]] to <4 x i32>
+// CHECK: [[VMOVL_I:%.*]] = zext <4 x i16> %a to <4 x i32>
// CHECK: ret <4 x i32> [[VMOVL_I]]
uint32x4_t test_vmovl_u16(uint16x4_t a) {
return vmovl_u16(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vmovl_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vmovl_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMOVL_I:%.*]] = zext <2 x i32> [[TMP1]] to <2 x i64>
+// CHECK: [[VMOVL_I:%.*]] = zext <2 x i32> %a to <2 x i64>
// CHECK: ret <2 x i64> [[VMOVL_I]]
uint64x2_t test_vmovl_u32(uint32x2_t a) {
return vmovl_u32(a);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vmovn_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vmovn_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VMOVN_I:%.*]] = trunc <8 x i16> [[TMP1]] to <8 x i8>
+// CHECK: [[VMOVN_I:%.*]] = trunc <8 x i16> %a to <8 x i8>
// CHECK: ret <8 x i8> [[VMOVN_I]]
int8x8_t test_vmovn_s16(int16x8_t a) {
return vmovn_s16(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vmovn_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vmovn_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VMOVN_I:%.*]] = trunc <4 x i32> [[TMP1]] to <4 x i16>
+// CHECK: [[VMOVN_I:%.*]] = trunc <4 x i32> %a to <4 x i16>
// CHECK: ret <4 x i16> [[VMOVN_I]]
int16x4_t test_vmovn_s32(int32x4_t a) {
return vmovn_s32(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vmovn_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vmovn_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VMOVN_I:%.*]] = trunc <2 x i64> [[TMP1]] to <2 x i32>
+// CHECK: [[VMOVN_I:%.*]] = trunc <2 x i64> %a to <2 x i32>
// CHECK: ret <2 x i32> [[VMOVN_I]]
int32x2_t test_vmovn_s64(int64x2_t a) {
return vmovn_s64(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vmovn_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vmovn_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VMOVN_I:%.*]] = trunc <8 x i16> [[TMP1]] to <8 x i8>
+// CHECK: [[VMOVN_I:%.*]] = trunc <8 x i16> %a to <8 x i8>
// CHECK: ret <8 x i8> [[VMOVN_I]]
uint8x8_t test_vmovn_u16(uint16x8_t a) {
return vmovn_u16(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vmovn_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vmovn_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VMOVN_I:%.*]] = trunc <4 x i32> [[TMP1]] to <4 x i16>
+// CHECK: [[VMOVN_I:%.*]] = trunc <4 x i32> %a to <4 x i16>
// CHECK: ret <4 x i16> [[VMOVN_I]]
uint16x4_t test_vmovn_u32(uint32x4_t a) {
return vmovn_u32(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vmovn_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vmovn_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VMOVN_I:%.*]] = trunc <2 x i64> [[TMP1]] to <2 x i32>
+// CHECK: [[VMOVN_I:%.*]] = trunc <2 x i64> %a to <2 x i32>
// CHECK: ret <2 x i32> [[VMOVN_I]]
uint32x2_t test_vmovn_u64(uint64x2_t a) {
return vmovn_u64(a);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vmov_n_u8(i8 zeroext %a) #0 {
+// CHECK-LABEL: @test_vmov_n_u8(
// CHECK: [[VECINIT_I:%.*]] = insertelement <8 x i8> undef, i8 %a, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <8 x i8> [[VECINIT_I]], i8 %a, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <8 x i8> [[VECINIT1_I]], i8 %a, i32 2
@@ -9937,7 +8317,7 @@ uint8x8_t test_vmov_n_u8(uint8_t a) {
return vmov_n_u8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vmov_n_u16(i16 zeroext %a) #0 {
+// CHECK-LABEL: @test_vmov_n_u16(
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i16> undef, i16 %a, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i16> [[VECINIT_I]], i16 %a, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i16> [[VECINIT1_I]], i16 %a, i32 2
@@ -9947,7 +8327,7 @@ uint16x4_t test_vmov_n_u16(uint16_t a) {
return vmov_n_u16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vmov_n_u32(i32 %a) #0 {
+// CHECK-LABEL: @test_vmov_n_u32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x i32> undef, i32 %a, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x i32> [[VECINIT_I]], i32 %a, i32 1
// CHECK: ret <2 x i32> [[VECINIT1_I]]
@@ -9955,7 +8335,7 @@ uint32x2_t test_vmov_n_u32(uint32_t a) {
return vmov_n_u32(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vmov_n_s8(i8 signext %a) #0 {
+// CHECK-LABEL: @test_vmov_n_s8(
// CHECK: [[VECINIT_I:%.*]] = insertelement <8 x i8> undef, i8 %a, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <8 x i8> [[VECINIT_I]], i8 %a, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <8 x i8> [[VECINIT1_I]], i8 %a, i32 2
@@ -9969,7 +8349,7 @@ int8x8_t test_vmov_n_s8(int8_t a) {
return vmov_n_s8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vmov_n_s16(i16 signext %a) #0 {
+// CHECK-LABEL: @test_vmov_n_s16(
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i16> undef, i16 %a, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i16> [[VECINIT_I]], i16 %a, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i16> [[VECINIT1_I]], i16 %a, i32 2
@@ -9979,7 +8359,7 @@ int16x4_t test_vmov_n_s16(int16_t a) {
return vmov_n_s16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vmov_n_s32(i32 %a) #0 {
+// CHECK-LABEL: @test_vmov_n_s32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x i32> undef, i32 %a, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x i32> [[VECINIT_I]], i32 %a, i32 1
// CHECK: ret <2 x i32> [[VECINIT1_I]]
@@ -9987,7 +8367,7 @@ int32x2_t test_vmov_n_s32(int32_t a) {
return vmov_n_s32(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vmov_n_p8(i8 signext %a) #0 {
+// CHECK-LABEL: @test_vmov_n_p8(
// CHECK: [[VECINIT_I:%.*]] = insertelement <8 x i8> undef, i8 %a, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <8 x i8> [[VECINIT_I]], i8 %a, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <8 x i8> [[VECINIT1_I]], i8 %a, i32 2
@@ -10001,7 +8381,7 @@ poly8x8_t test_vmov_n_p8(poly8_t a) {
return vmov_n_p8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vmov_n_p16(i16 signext %a) #0 {
+// CHECK-LABEL: @test_vmov_n_p16(
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i16> undef, i16 %a, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i16> [[VECINIT_I]], i16 %a, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i16> [[VECINIT1_I]], i16 %a, i32 2
@@ -10011,7 +8391,7 @@ poly16x4_t test_vmov_n_p16(poly16_t a) {
return vmov_n_p16(a);
}
-// CHECK-LABEL: define <4 x half> @test_vmov_n_f16(half* %a) #0 {
+// CHECK-LABEL: @test_vmov_n_f16(
// CHECK: [[TMP0:%.*]] = load half, half* %a, align 2
// CHECK: [[VECINIT:%.*]] = insertelement <4 x half> undef, half [[TMP0]], i32 0
// CHECK: [[VECINIT1:%.*]] = insertelement <4 x half> [[VECINIT]], half [[TMP0]], i32 1
@@ -10022,7 +8402,7 @@ float16x4_t test_vmov_n_f16(float16_t *a) {
return vmov_n_f16(*a);
}
-// CHECK-LABEL: define <2 x float> @test_vmov_n_f32(float %a) #0 {
+// CHECK-LABEL: @test_vmov_n_f32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x float> undef, float %a, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x float> [[VECINIT_I]], float %a, i32 1
// CHECK: ret <2 x float> [[VECINIT1_I]]
@@ -10030,7 +8410,7 @@ float32x2_t test_vmov_n_f32(float32_t a) {
return vmov_n_f32(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vmovq_n_u8(i8 zeroext %a) #0 {
+// CHECK-LABEL: @test_vmovq_n_u8(
// CHECK: [[VECINIT_I:%.*]] = insertelement <16 x i8> undef, i8 %a, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <16 x i8> [[VECINIT_I]], i8 %a, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <16 x i8> [[VECINIT1_I]], i8 %a, i32 2
@@ -10052,7 +8432,7 @@ uint8x16_t test_vmovq_n_u8(uint8_t a) {
return vmovq_n_u8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vmovq_n_u16(i16 zeroext %a) #0 {
+// CHECK-LABEL: @test_vmovq_n_u16(
// CHECK: [[VECINIT_I:%.*]] = insertelement <8 x i16> undef, i16 %a, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <8 x i16> [[VECINIT_I]], i16 %a, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <8 x i16> [[VECINIT1_I]], i16 %a, i32 2
@@ -10066,7 +8446,7 @@ uint16x8_t test_vmovq_n_u16(uint16_t a) {
return vmovq_n_u16(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vmovq_n_u32(i32 %a) #0 {
+// CHECK-LABEL: @test_vmovq_n_u32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i32> undef, i32 %a, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i32> [[VECINIT_I]], i32 %a, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i32> [[VECINIT1_I]], i32 %a, i32 2
@@ -10076,7 +8456,7 @@ uint32x4_t test_vmovq_n_u32(uint32_t a) {
return vmovq_n_u32(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vmovq_n_s8(i8 signext %a) #0 {
+// CHECK-LABEL: @test_vmovq_n_s8(
// CHECK: [[VECINIT_I:%.*]] = insertelement <16 x i8> undef, i8 %a, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <16 x i8> [[VECINIT_I]], i8 %a, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <16 x i8> [[VECINIT1_I]], i8 %a, i32 2
@@ -10098,7 +8478,7 @@ int8x16_t test_vmovq_n_s8(int8_t a) {
return vmovq_n_s8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vmovq_n_s16(i16 signext %a) #0 {
+// CHECK-LABEL: @test_vmovq_n_s16(
// CHECK: [[VECINIT_I:%.*]] = insertelement <8 x i16> undef, i16 %a, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <8 x i16> [[VECINIT_I]], i16 %a, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <8 x i16> [[VECINIT1_I]], i16 %a, i32 2
@@ -10112,7 +8492,7 @@ int16x8_t test_vmovq_n_s16(int16_t a) {
return vmovq_n_s16(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vmovq_n_s32(i32 %a) #0 {
+// CHECK-LABEL: @test_vmovq_n_s32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i32> undef, i32 %a, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i32> [[VECINIT_I]], i32 %a, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i32> [[VECINIT1_I]], i32 %a, i32 2
@@ -10122,7 +8502,7 @@ int32x4_t test_vmovq_n_s32(int32_t a) {
return vmovq_n_s32(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vmovq_n_p8(i8 signext %a) #0 {
+// CHECK-LABEL: @test_vmovq_n_p8(
// CHECK: [[VECINIT_I:%.*]] = insertelement <16 x i8> undef, i8 %a, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <16 x i8> [[VECINIT_I]], i8 %a, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <16 x i8> [[VECINIT1_I]], i8 %a, i32 2
@@ -10144,7 +8524,7 @@ poly8x16_t test_vmovq_n_p8(poly8_t a) {
return vmovq_n_p8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vmovq_n_p16(i16 signext %a) #0 {
+// CHECK-LABEL: @test_vmovq_n_p16(
// CHECK: [[VECINIT_I:%.*]] = insertelement <8 x i16> undef, i16 %a, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <8 x i16> [[VECINIT_I]], i16 %a, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <8 x i16> [[VECINIT1_I]], i16 %a, i32 2
@@ -10158,7 +8538,7 @@ poly16x8_t test_vmovq_n_p16(poly16_t a) {
return vmovq_n_p16(a);
}
-// CHECK-LABEL: define <8 x half> @test_vmovq_n_f16(half* %a) #0 {
+// CHECK-LABEL: @test_vmovq_n_f16(
// CHECK: [[TMP0:%.*]] = load half, half* %a, align 2
// CHECK: [[VECINIT:%.*]] = insertelement <8 x half> undef, half [[TMP0]], i32 0
// CHECK: [[VECINIT1:%.*]] = insertelement <8 x half> [[VECINIT]], half [[TMP0]], i32 1
@@ -10173,7 +8553,7 @@ float16x8_t test_vmovq_n_f16(float16_t *a) {
return vmovq_n_f16(*a);
}
-// CHECK-LABEL: define <4 x float> @test_vmovq_n_f32(float %a) #0 {
+// CHECK-LABEL: @test_vmovq_n_f32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x float> undef, float %a, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x float> [[VECINIT_I]], float %a, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x float> [[VECINIT1_I]], float %a, i32 2
@@ -10183,7 +8563,7 @@ float32x4_t test_vmovq_n_f32(float32_t a) {
return vmovq_n_f32(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vmov_n_s64(i64 %a) #0 {
+// CHECK-LABEL: @test_vmov_n_s64(
// CHECK: [[VECINIT_I:%.*]] = insertelement <1 x i64> undef, i64 %a, i32 0
// CHECK: [[ADD_I:%.*]] = add <1 x i64> [[VECINIT_I]], [[VECINIT_I]]
// CHECK: ret <1 x i64> [[ADD_I]]
@@ -10192,7 +8572,7 @@ int64x1_t test_vmov_n_s64(int64_t a) {
return vadd_s64(tmp, tmp);
}
-// CHECK-LABEL: define <1 x i64> @test_vmov_n_u64(i64 %a) #0 {
+// CHECK-LABEL: @test_vmov_n_u64(
// CHECK: [[VECINIT_I:%.*]] = insertelement <1 x i64> undef, i64 %a, i32 0
// CHECK: [[ADD_I:%.*]] = add <1 x i64> [[VECINIT_I]], [[VECINIT_I]]
// CHECK: ret <1 x i64> [[ADD_I]]
@@ -10201,7 +8581,7 @@ uint64x1_t test_vmov_n_u64(uint64_t a) {
return vadd_u64(tmp, tmp);
}
-// CHECK-LABEL: define <2 x i64> @test_vmovq_n_s64(i64 %a) #0 {
+// CHECK-LABEL: @test_vmovq_n_s64(
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x i64> undef, i64 %a, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x i64> [[VECINIT_I]], i64 %a, i32 1
// CHECK: ret <2 x i64> [[VECINIT1_I]]
@@ -10209,7 +8589,7 @@ int64x2_t test_vmovq_n_s64(int64_t a) {
return vmovq_n_s64(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vmovq_n_u64(i64 %a) #0 {
+// CHECK-LABEL: @test_vmovq_n_u64(
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x i64> undef, i64 %a, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x i64> [[VECINIT_I]], i64 %a, i32 1
// CHECK: ret <2 x i64> [[VECINIT1_I]]
@@ -10217,294 +8597,264 @@ uint64x2_t test_vmovq_n_u64(uint64_t a) {
return vmovq_n_u64(a);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vmul_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vmul_s8(
// CHECK: [[MUL_I:%.*]] = mul <8 x i8> %a, %b
// CHECK: ret <8 x i8> [[MUL_I]]
int8x8_t test_vmul_s8(int8x8_t a, int8x8_t b) {
return vmul_s8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vmul_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vmul_s16(
// CHECK: [[MUL_I:%.*]] = mul <4 x i16> %a, %b
// CHECK: ret <4 x i16> [[MUL_I]]
int16x4_t test_vmul_s16(int16x4_t a, int16x4_t b) {
return vmul_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vmul_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vmul_s32(
// CHECK: [[MUL_I:%.*]] = mul <2 x i32> %a, %b
// CHECK: ret <2 x i32> [[MUL_I]]
int32x2_t test_vmul_s32(int32x2_t a, int32x2_t b) {
return vmul_s32(a, b);
}
-// CHECK-LABEL: define <2 x float> @test_vmul_f32(<2 x float> %a, <2 x float> %b) #0 {
+// CHECK-LABEL: @test_vmul_f32(
// CHECK: [[MUL_I:%.*]] = fmul <2 x float> %a, %b
// CHECK: ret <2 x float> [[MUL_I]]
float32x2_t test_vmul_f32(float32x2_t a, float32x2_t b) {
return vmul_f32(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vmul_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vmul_u8(
// CHECK: [[MUL_I:%.*]] = mul <8 x i8> %a, %b
// CHECK: ret <8 x i8> [[MUL_I]]
uint8x8_t test_vmul_u8(uint8x8_t a, uint8x8_t b) {
return vmul_u8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vmul_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vmul_u16(
// CHECK: [[MUL_I:%.*]] = mul <4 x i16> %a, %b
// CHECK: ret <4 x i16> [[MUL_I]]
uint16x4_t test_vmul_u16(uint16x4_t a, uint16x4_t b) {
return vmul_u16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vmul_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vmul_u32(
// CHECK: [[MUL_I:%.*]] = mul <2 x i32> %a, %b
// CHECK: ret <2 x i32> [[MUL_I]]
uint32x2_t test_vmul_u32(uint32x2_t a, uint32x2_t b) {
return vmul_u32(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vmulq_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vmulq_s8(
// CHECK: [[MUL_I:%.*]] = mul <16 x i8> %a, %b
// CHECK: ret <16 x i8> [[MUL_I]]
int8x16_t test_vmulq_s8(int8x16_t a, int8x16_t b) {
return vmulq_s8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vmulq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vmulq_s16(
// CHECK: [[MUL_I:%.*]] = mul <8 x i16> %a, %b
// CHECK: ret <8 x i16> [[MUL_I]]
int16x8_t test_vmulq_s16(int16x8_t a, int16x8_t b) {
return vmulq_s16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vmulq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vmulq_s32(
// CHECK: [[MUL_I:%.*]] = mul <4 x i32> %a, %b
// CHECK: ret <4 x i32> [[MUL_I]]
int32x4_t test_vmulq_s32(int32x4_t a, int32x4_t b) {
return vmulq_s32(a, b);
}
-// CHECK-LABEL: define <4 x float> @test_vmulq_f32(<4 x float> %a, <4 x float> %b) #0 {
+// CHECK-LABEL: @test_vmulq_f32(
// CHECK: [[MUL_I:%.*]] = fmul <4 x float> %a, %b
// CHECK: ret <4 x float> [[MUL_I]]
float32x4_t test_vmulq_f32(float32x4_t a, float32x4_t b) {
return vmulq_f32(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vmulq_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vmulq_u8(
// CHECK: [[MUL_I:%.*]] = mul <16 x i8> %a, %b
// CHECK: ret <16 x i8> [[MUL_I]]
uint8x16_t test_vmulq_u8(uint8x16_t a, uint8x16_t b) {
return vmulq_u8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vmulq_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vmulq_u16(
// CHECK: [[MUL_I:%.*]] = mul <8 x i16> %a, %b
// CHECK: ret <8 x i16> [[MUL_I]]
uint16x8_t test_vmulq_u16(uint16x8_t a, uint16x8_t b) {
return vmulq_u16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vmulq_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vmulq_u32(
// CHECK: [[MUL_I:%.*]] = mul <4 x i32> %a, %b
// CHECK: ret <4 x i32> [[MUL_I]]
uint32x4_t test_vmulq_u32(uint32x4_t a, uint32x4_t b) {
return vmulq_u32(a, b);
}
-
-// CHECK-LABEL: define <8 x i16> @test_vmull_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vmull_s8(
// CHECK: [[VMULL_I:%.*]] = call <8 x i16> @llvm.arm.neon.vmulls.v8i16(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i16> [[VMULL_I]]
int16x8_t test_vmull_s8(int8x8_t a, int8x8_t b) {
return vmull_s8(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vmull_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vmull_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vmulls.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #4
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vmulls.v4i32(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: ret <4 x i32> [[VMULL2_I]]
int32x4_t test_vmull_s16(int16x4_t a, int16x4_t b) {
return vmull_s16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vmull_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vmull_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vmulls.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #4
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vmulls.v2i64(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: ret <2 x i64> [[VMULL2_I]]
int64x2_t test_vmull_s32(int32x2_t a, int32x2_t b) {
return vmull_s32(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vmull_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vmull_u8(
// CHECK: [[VMULL_I:%.*]] = call <8 x i16> @llvm.arm.neon.vmullu.v8i16(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i16> [[VMULL_I]]
uint16x8_t test_vmull_u8(uint8x8_t a, uint8x8_t b) {
return vmull_u8(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vmull_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vmull_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vmullu.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #4
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vmullu.v4i32(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: ret <4 x i32> [[VMULL2_I]]
uint32x4_t test_vmull_u16(uint16x4_t a, uint16x4_t b) {
return vmull_u16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vmull_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vmull_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vmullu.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #4
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vmullu.v2i64(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: ret <2 x i64> [[VMULL2_I]]
uint64x2_t test_vmull_u32(uint32x2_t a, uint32x2_t b) {
return vmull_u32(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vmull_p8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vmull_p8(
// CHECK: [[VMULL_I:%.*]] = call <8 x i16> @llvm.arm.neon.vmullp.v8i16(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i16> [[VMULL_I]]
poly16x8_t test_vmull_p8(poly8x8_t a, poly8x8_t b) {
return vmull_p8(a, b);
}
-
-// CHECK-LABEL: define <4 x i32> @test_vmull_lane_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vmull_lane_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %b, <4 x i16> %b, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vmulls.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #4
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vmulls.v4i32(<4 x i16> %a, <4 x i16> [[SHUFFLE]]) #4
// CHECK: ret <4 x i32> [[VMULL2_I]]
int32x4_t test_vmull_lane_s16(int16x4_t a, int16x4_t b) {
return vmull_lane_s16(a, b, 3);
}
-// CHECK-LABEL: define <2 x i64> @test_vmull_lane_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vmull_lane_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %b, <2 x i32> %b, <2 x i32> <i32 1, i32 1>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vmulls.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #4
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vmulls.v2i64(<2 x i32> %a, <2 x i32> [[SHUFFLE]]) #4
// CHECK: ret <2 x i64> [[VMULL2_I]]
int64x2_t test_vmull_lane_s32(int32x2_t a, int32x2_t b) {
return vmull_lane_s32(a, b, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vmull_lane_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vmull_lane_u16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %b, <4 x i16> %b, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vmullu.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL1_I]]) #4
+// CHECK: [[VMULL2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vmullu.v4i32(<4 x i16> %a, <4 x i16> [[SHUFFLE]]) #4
// CHECK: ret <4 x i32> [[VMULL2_I]]
uint32x4_t test_vmull_lane_u16(uint16x4_t a, uint16x4_t b) {
return vmull_lane_u16(a, b, 3);
}
-// CHECK-LABEL: define <2 x i64> @test_vmull_lane_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vmull_lane_u32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %b, <2 x i32> %b, <2 x i32> <i32 1, i32 1>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vmullu.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL1_I]]) #4
+// CHECK: [[VMULL2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vmullu.v2i64(<2 x i32> %a, <2 x i32> [[SHUFFLE]]) #4
// CHECK: ret <2 x i64> [[VMULL2_I]]
uint64x2_t test_vmull_lane_u32(uint32x2_t a, uint32x2_t b) {
return vmull_lane_u32(a, b, 1);
}
-
-// CHECK-LABEL: define <4 x i32> @test_vmull_n_s16(<4 x i16> %a, i16 signext %b) #0 {
+// CHECK-LABEL: @test_vmull_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i16> undef, i16 %b, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i16> [[VECINIT_I]], i16 %b, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i16> [[VECINIT1_I]], i16 %b, i32 2
// CHECK: [[VECINIT3_I:%.*]] = insertelement <4 x i16> [[VECINIT2_I]], i16 %b, i32 3
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[VECINIT3_I]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL4_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL5_I:%.*]] = call <4 x i32> @llvm.arm.neon.vmulls.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL4_I]]) #4
+// CHECK: [[VMULL5_I:%.*]] = call <4 x i32> @llvm.arm.neon.vmulls.v4i32(<4 x i16> %a, <4 x i16> [[VECINIT3_I]]) #4
// CHECK: ret <4 x i32> [[VMULL5_I]]
int32x4_t test_vmull_n_s16(int16x4_t a, int16_t b) {
return vmull_n_s16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vmull_n_s32(<2 x i32> %a, i32 %b) #0 {
+// CHECK-LABEL: @test_vmull_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x i32> undef, i32 %b, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x i32> [[VECINIT_I]], i32 %b, i32 1
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[VECINIT1_I]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL3_I:%.*]] = call <2 x i64> @llvm.arm.neon.vmulls.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL2_I]]) #4
+// CHECK: [[VMULL3_I:%.*]] = call <2 x i64> @llvm.arm.neon.vmulls.v2i64(<2 x i32> %a, <2 x i32> [[VECINIT1_I]]) #4
// CHECK: ret <2 x i64> [[VMULL3_I]]
int64x2_t test_vmull_n_s32(int32x2_t a, int32_t b) {
return vmull_n_s32(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vmull_n_u16(<4 x i16> %a, i16 zeroext %b) #0 {
+// CHECK-LABEL: @test_vmull_n_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i16> undef, i16 %b, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i16> [[VECINIT_I]], i16 %b, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i16> [[VECINIT1_I]], i16 %b, i32 2
// CHECK: [[VECINIT3_I:%.*]] = insertelement <4 x i16> [[VECINIT2_I]], i16 %b, i32 3
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[VECINIT3_I]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMULL4_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VMULL5_I:%.*]] = call <4 x i32> @llvm.arm.neon.vmullu.v4i32(<4 x i16> [[VMULL_I]], <4 x i16> [[VMULL4_I]]) #4
+// CHECK: [[VMULL5_I:%.*]] = call <4 x i32> @llvm.arm.neon.vmullu.v4i32(<4 x i16> %a, <4 x i16> [[VECINIT3_I]]) #4
// CHECK: ret <4 x i32> [[VMULL5_I]]
uint32x4_t test_vmull_n_u16(uint16x4_t a, uint16_t b) {
return vmull_n_u16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vmull_n_u32(<2 x i32> %a, i32 %b) #0 {
+// CHECK-LABEL: @test_vmull_n_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x i32> undef, i32 %b, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x i32> [[VECINIT_I]], i32 %b, i32 1
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[VECINIT1_I]] to <8 x i8>
-// CHECK: [[VMULL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMULL2_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VMULL3_I:%.*]] = call <2 x i64> @llvm.arm.neon.vmullu.v2i64(<2 x i32> [[VMULL_I]], <2 x i32> [[VMULL2_I]]) #4
+// CHECK: [[VMULL3_I:%.*]] = call <2 x i64> @llvm.arm.neon.vmullu.v2i64(<2 x i32> %a, <2 x i32> [[VECINIT1_I]]) #4
// CHECK: ret <2 x i64> [[VMULL3_I]]
uint64x2_t test_vmull_n_u32(uint32x2_t a, uint32_t b) {
return vmull_n_u32(a, b);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vmul_p8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vmul_p8(
// CHECK: [[VMUL_V_I:%.*]] = call <8 x i8> @llvm.arm.neon.vmulp.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VMUL_V_I]]
poly8x8_t test_vmul_p8(poly8x8_t a, poly8x8_t b) {
return vmul_p8(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vmulq_p8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vmulq_p8(
// CHECK: [[VMULQ_V_I:%.*]] = call <16 x i8> @llvm.arm.neon.vmulp.v16i8(<16 x i8> %a, <16 x i8> %b) #4
// CHECK: ret <16 x i8> [[VMULQ_V_I]]
poly8x16_t test_vmulq_p8(poly8x16_t a, poly8x16_t b) {
return vmulq_p8(a, b);
}
-
-// CHECK-LABEL: define <4 x i16> @test_vmul_lane_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vmul_lane_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %b, <4 x i16> %b, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[MUL:%.*]] = mul <4 x i16> %a, [[SHUFFLE]]
// CHECK: ret <4 x i16> [[MUL]]
@@ -10512,7 +8862,7 @@ int16x4_t test_vmul_lane_s16(int16x4_t a, int16x4_t b) {
return vmul_lane_s16(a, b, 3);
}
-// CHECK-LABEL: define <2 x i32> @test_vmul_lane_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vmul_lane_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %b, <2 x i32> %b, <2 x i32> <i32 1, i32 1>
// CHECK: [[MUL:%.*]] = mul <2 x i32> %a, [[SHUFFLE]]
// CHECK: ret <2 x i32> [[MUL]]
@@ -10520,7 +8870,7 @@ int32x2_t test_vmul_lane_s32(int32x2_t a, int32x2_t b) {
return vmul_lane_s32(a, b, 1);
}
-// CHECK-LABEL: define <2 x float> @test_vmul_lane_f32(<2 x float> %a, <2 x float> %b) #0 {
+// CHECK-LABEL: @test_vmul_lane_f32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x float> %b, <2 x float> %b, <2 x i32> <i32 1, i32 1>
// CHECK: [[MUL:%.*]] = fmul <2 x float> %a, [[SHUFFLE]]
// CHECK: ret <2 x float> [[MUL]]
@@ -10528,7 +8878,7 @@ float32x2_t test_vmul_lane_f32(float32x2_t a, float32x2_t b) {
return vmul_lane_f32(a, b, 1);
}
-// CHECK-LABEL: define <4 x i16> @test_vmul_lane_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vmul_lane_u16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %b, <4 x i16> %b, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[MUL:%.*]] = mul <4 x i16> %a, [[SHUFFLE]]
// CHECK: ret <4 x i16> [[MUL]]
@@ -10536,7 +8886,7 @@ uint16x4_t test_vmul_lane_u16(uint16x4_t a, uint16x4_t b) {
return vmul_lane_u16(a, b, 3);
}
-// CHECK-LABEL: define <2 x i32> @test_vmul_lane_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vmul_lane_u32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %b, <2 x i32> %b, <2 x i32> <i32 1, i32 1>
// CHECK: [[MUL:%.*]] = mul <2 x i32> %a, [[SHUFFLE]]
// CHECK: ret <2 x i32> [[MUL]]
@@ -10544,7 +8894,7 @@ uint32x2_t test_vmul_lane_u32(uint32x2_t a, uint32x2_t b) {
return vmul_lane_u32(a, b, 1);
}
-// CHECK-LABEL: define <8 x i16> @test_vmulq_lane_s16(<8 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vmulq_lane_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %b, <4 x i16> %b, <8 x i32> <i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3>
// CHECK: [[MUL:%.*]] = mul <8 x i16> %a, [[SHUFFLE]]
// CHECK: ret <8 x i16> [[MUL]]
@@ -10552,7 +8902,7 @@ int16x8_t test_vmulq_lane_s16(int16x8_t a, int16x4_t b) {
return vmulq_lane_s16(a, b, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vmulq_lane_s32(<4 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vmulq_lane_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %b, <2 x i32> %b, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
// CHECK: [[MUL:%.*]] = mul <4 x i32> %a, [[SHUFFLE]]
// CHECK: ret <4 x i32> [[MUL]]
@@ -10560,7 +8910,7 @@ int32x4_t test_vmulq_lane_s32(int32x4_t a, int32x2_t b) {
return vmulq_lane_s32(a, b, 1);
}
-// CHECK-LABEL: define <4 x float> @test_vmulq_lane_f32(<4 x float> %a, <2 x float> %b) #0 {
+// CHECK-LABEL: @test_vmulq_lane_f32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x float> %b, <2 x float> %b, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
// CHECK: [[MUL:%.*]] = fmul <4 x float> %a, [[SHUFFLE]]
// CHECK: ret <4 x float> [[MUL]]
@@ -10568,7 +8918,7 @@ float32x4_t test_vmulq_lane_f32(float32x4_t a, float32x2_t b) {
return vmulq_lane_f32(a, b, 1);
}
-// CHECK-LABEL: define <8 x i16> @test_vmulq_lane_u16(<8 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vmulq_lane_u16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %b, <4 x i16> %b, <8 x i32> <i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3>
// CHECK: [[MUL:%.*]] = mul <8 x i16> %a, [[SHUFFLE]]
// CHECK: ret <8 x i16> [[MUL]]
@@ -10576,7 +8926,7 @@ uint16x8_t test_vmulq_lane_u16(uint16x8_t a, uint16x4_t b) {
return vmulq_lane_u16(a, b, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vmulq_lane_u32(<4 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vmulq_lane_u32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %b, <2 x i32> %b, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
// CHECK: [[MUL:%.*]] = mul <4 x i32> %a, [[SHUFFLE]]
// CHECK: ret <4 x i32> [[MUL]]
@@ -10584,8 +8934,7 @@ uint32x4_t test_vmulq_lane_u32(uint32x4_t a, uint32x2_t b) {
return vmulq_lane_u32(a, b, 1);
}
-
-// CHECK-LABEL: define <4 x i16> @test_vmul_n_s16(<4 x i16> %a, i16 signext %b) #0 {
+// CHECK-LABEL: @test_vmul_n_s16(
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i16> undef, i16 %b, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i16> [[VECINIT_I]], i16 %b, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i16> [[VECINIT1_I]], i16 %b, i32 2
@@ -10596,7 +8945,7 @@ int16x4_t test_vmul_n_s16(int16x4_t a, int16_t b) {
return vmul_n_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vmul_n_s32(<2 x i32> %a, i32 %b) #0 {
+// CHECK-LABEL: @test_vmul_n_s32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x i32> undef, i32 %b, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x i32> [[VECINIT_I]], i32 %b, i32 1
// CHECK: [[MUL_I:%.*]] = mul <2 x i32> %a, [[VECINIT1_I]]
@@ -10605,7 +8954,7 @@ int32x2_t test_vmul_n_s32(int32x2_t a, int32_t b) {
return vmul_n_s32(a, b);
}
-// CHECK-LABEL: define <2 x float> @test_vmul_n_f32(<2 x float> %a, float %b) #0 {
+// CHECK-LABEL: @test_vmul_n_f32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x float> undef, float %b, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x float> [[VECINIT_I]], float %b, i32 1
// CHECK: [[MUL_I:%.*]] = fmul <2 x float> %a, [[VECINIT1_I]]
@@ -10614,7 +8963,7 @@ float32x2_t test_vmul_n_f32(float32x2_t a, float32_t b) {
return vmul_n_f32(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vmul_n_u16(<4 x i16> %a, i16 zeroext %b) #0 {
+// CHECK-LABEL: @test_vmul_n_u16(
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i16> undef, i16 %b, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i16> [[VECINIT_I]], i16 %b, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i16> [[VECINIT1_I]], i16 %b, i32 2
@@ -10625,7 +8974,7 @@ uint16x4_t test_vmul_n_u16(uint16x4_t a, uint16_t b) {
return vmul_n_u16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vmul_n_u32(<2 x i32> %a, i32 %b) #0 {
+// CHECK-LABEL: @test_vmul_n_u32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x i32> undef, i32 %b, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x i32> [[VECINIT_I]], i32 %b, i32 1
// CHECK: [[MUL_I:%.*]] = mul <2 x i32> %a, [[VECINIT1_I]]
@@ -10634,7 +8983,7 @@ uint32x2_t test_vmul_n_u32(uint32x2_t a, uint32_t b) {
return vmul_n_u32(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vmulq_n_s16(<8 x i16> %a, i16 signext %b) #0 {
+// CHECK-LABEL: @test_vmulq_n_s16(
// CHECK: [[VECINIT_I:%.*]] = insertelement <8 x i16> undef, i16 %b, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <8 x i16> [[VECINIT_I]], i16 %b, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <8 x i16> [[VECINIT1_I]], i16 %b, i32 2
@@ -10649,7 +8998,7 @@ int16x8_t test_vmulq_n_s16(int16x8_t a, int16_t b) {
return vmulq_n_s16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vmulq_n_s32(<4 x i32> %a, i32 %b) #0 {
+// CHECK-LABEL: @test_vmulq_n_s32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i32> undef, i32 %b, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i32> [[VECINIT_I]], i32 %b, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i32> [[VECINIT1_I]], i32 %b, i32 2
@@ -10660,7 +9009,7 @@ int32x4_t test_vmulq_n_s32(int32x4_t a, int32_t b) {
return vmulq_n_s32(a, b);
}
-// CHECK-LABEL: define <4 x float> @test_vmulq_n_f32(<4 x float> %a, float %b) #0 {
+// CHECK-LABEL: @test_vmulq_n_f32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x float> undef, float %b, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x float> [[VECINIT_I]], float %b, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x float> [[VECINIT1_I]], float %b, i32 2
@@ -10671,7 +9020,7 @@ float32x4_t test_vmulq_n_f32(float32x4_t a, float32_t b) {
return vmulq_n_f32(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vmulq_n_u16(<8 x i16> %a, i16 zeroext %b) #0 {
+// CHECK-LABEL: @test_vmulq_n_u16(
// CHECK: [[VECINIT_I:%.*]] = insertelement <8 x i16> undef, i16 %b, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <8 x i16> [[VECINIT_I]], i16 %b, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <8 x i16> [[VECINIT1_I]], i16 %b, i32 2
@@ -10686,7 +9035,7 @@ uint16x8_t test_vmulq_n_u16(uint16x8_t a, uint16_t b) {
return vmulq_n_u16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vmulq_n_u32(<4 x i32> %a, i32 %b) #0 {
+// CHECK-LABEL: @test_vmulq_n_u32(
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i32> undef, i32 %b, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i32> [[VECINIT_I]], i32 %b, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i32> [[VECINIT1_I]], i32 %b, i32 2
@@ -10697,164 +9046,161 @@ uint32x4_t test_vmulq_n_u32(uint32x4_t a, uint32_t b) {
return vmulq_n_u32(a, b);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vmvn_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vmvn_s8(
// CHECK: [[NEG_I:%.*]] = xor <8 x i8> %a, <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>
// CHECK: ret <8 x i8> [[NEG_I]]
int8x8_t test_vmvn_s8(int8x8_t a) {
return vmvn_s8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vmvn_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vmvn_s16(
// CHECK: [[NEG_I:%.*]] = xor <4 x i16> %a, <i16 -1, i16 -1, i16 -1, i16 -1>
// CHECK: ret <4 x i16> [[NEG_I]]
int16x4_t test_vmvn_s16(int16x4_t a) {
return vmvn_s16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vmvn_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vmvn_s32(
// CHECK: [[NEG_I:%.*]] = xor <2 x i32> %a, <i32 -1, i32 -1>
// CHECK: ret <2 x i32> [[NEG_I]]
int32x2_t test_vmvn_s32(int32x2_t a) {
return vmvn_s32(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vmvn_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vmvn_u8(
// CHECK: [[NEG_I:%.*]] = xor <8 x i8> %a, <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>
// CHECK: ret <8 x i8> [[NEG_I]]
uint8x8_t test_vmvn_u8(uint8x8_t a) {
return vmvn_u8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vmvn_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vmvn_u16(
// CHECK: [[NEG_I:%.*]] = xor <4 x i16> %a, <i16 -1, i16 -1, i16 -1, i16 -1>
// CHECK: ret <4 x i16> [[NEG_I]]
uint16x4_t test_vmvn_u16(uint16x4_t a) {
return vmvn_u16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vmvn_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vmvn_u32(
// CHECK: [[NEG_I:%.*]] = xor <2 x i32> %a, <i32 -1, i32 -1>
// CHECK: ret <2 x i32> [[NEG_I]]
uint32x2_t test_vmvn_u32(uint32x2_t a) {
return vmvn_u32(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vmvn_p8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vmvn_p8(
// CHECK: [[NEG_I:%.*]] = xor <8 x i8> %a, <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>
// CHECK: ret <8 x i8> [[NEG_I]]
poly8x8_t test_vmvn_p8(poly8x8_t a) {
return vmvn_p8(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vmvnq_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vmvnq_s8(
// CHECK: [[NEG_I:%.*]] = xor <16 x i8> %a, <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>
// CHECK: ret <16 x i8> [[NEG_I]]
int8x16_t test_vmvnq_s8(int8x16_t a) {
return vmvnq_s8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vmvnq_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vmvnq_s16(
// CHECK: [[NEG_I:%.*]] = xor <8 x i16> %a, <i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1>
// CHECK: ret <8 x i16> [[NEG_I]]
int16x8_t test_vmvnq_s16(int16x8_t a) {
return vmvnq_s16(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vmvnq_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vmvnq_s32(
// CHECK: [[NEG_I:%.*]] = xor <4 x i32> %a, <i32 -1, i32 -1, i32 -1, i32 -1>
// CHECK: ret <4 x i32> [[NEG_I]]
int32x4_t test_vmvnq_s32(int32x4_t a) {
return vmvnq_s32(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vmvnq_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vmvnq_u8(
// CHECK: [[NEG_I:%.*]] = xor <16 x i8> %a, <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>
// CHECK: ret <16 x i8> [[NEG_I]]
uint8x16_t test_vmvnq_u8(uint8x16_t a) {
return vmvnq_u8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vmvnq_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vmvnq_u16(
// CHECK: [[NEG_I:%.*]] = xor <8 x i16> %a, <i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1>
// CHECK: ret <8 x i16> [[NEG_I]]
uint16x8_t test_vmvnq_u16(uint16x8_t a) {
return vmvnq_u16(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vmvnq_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vmvnq_u32(
// CHECK: [[NEG_I:%.*]] = xor <4 x i32> %a, <i32 -1, i32 -1, i32 -1, i32 -1>
// CHECK: ret <4 x i32> [[NEG_I]]
uint32x4_t test_vmvnq_u32(uint32x4_t a) {
return vmvnq_u32(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vmvnq_p8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vmvnq_p8(
// CHECK: [[NEG_I:%.*]] = xor <16 x i8> %a, <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>
// CHECK: ret <16 x i8> [[NEG_I]]
poly8x16_t test_vmvnq_p8(poly8x16_t a) {
return vmvnq_p8(a);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vneg_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vneg_s8(
// CHECK: [[SUB_I:%.*]] = sub <8 x i8> zeroinitializer, %a
// CHECK: ret <8 x i8> [[SUB_I]]
int8x8_t test_vneg_s8(int8x8_t a) {
return vneg_s8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vneg_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vneg_s16(
// CHECK: [[SUB_I:%.*]] = sub <4 x i16> zeroinitializer, %a
// CHECK: ret <4 x i16> [[SUB_I]]
int16x4_t test_vneg_s16(int16x4_t a) {
return vneg_s16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vneg_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vneg_s32(
// CHECK: [[SUB_I:%.*]] = sub <2 x i32> zeroinitializer, %a
// CHECK: ret <2 x i32> [[SUB_I]]
int32x2_t test_vneg_s32(int32x2_t a) {
return vneg_s32(a);
}
-// CHECK-LABEL: define <2 x float> @test_vneg_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vneg_f32(
// CHECK: [[SUB_I:%.*]] = fsub <2 x float> <float -0.000000e+00, float -0.000000e+00>, %a
// CHECK: ret <2 x float> [[SUB_I]]
float32x2_t test_vneg_f32(float32x2_t a) {
return vneg_f32(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vnegq_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vnegq_s8(
// CHECK: [[SUB_I:%.*]] = sub <16 x i8> zeroinitializer, %a
// CHECK: ret <16 x i8> [[SUB_I]]
int8x16_t test_vnegq_s8(int8x16_t a) {
return vnegq_s8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vnegq_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vnegq_s16(
// CHECK: [[SUB_I:%.*]] = sub <8 x i16> zeroinitializer, %a
// CHECK: ret <8 x i16> [[SUB_I]]
int16x8_t test_vnegq_s16(int16x8_t a) {
return vnegq_s16(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vnegq_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vnegq_s32(
// CHECK: [[SUB_I:%.*]] = sub <4 x i32> zeroinitializer, %a
// CHECK: ret <4 x i32> [[SUB_I]]
int32x4_t test_vnegq_s32(int32x4_t a) {
return vnegq_s32(a);
}
-// CHECK-LABEL: define <4 x float> @test_vnegq_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vnegq_f32(
// CHECK: [[SUB_I:%.*]] = fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, %a
// CHECK: ret <4 x float> [[SUB_I]]
float32x4_t test_vnegq_f32(float32x4_t a) {
return vnegq_f32(a);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vorn_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vorn_s8(
// CHECK: [[NEG_I:%.*]] = xor <8 x i8> %b, <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>
// CHECK: [[OR_I:%.*]] = or <8 x i8> %a, [[NEG_I]]
// CHECK: ret <8 x i8> [[OR_I]]
@@ -10862,7 +9208,7 @@ int8x8_t test_vorn_s8(int8x8_t a, int8x8_t b) {
return vorn_s8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vorn_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vorn_s16(
// CHECK: [[NEG_I:%.*]] = xor <4 x i16> %b, <i16 -1, i16 -1, i16 -1, i16 -1>
// CHECK: [[OR_I:%.*]] = or <4 x i16> %a, [[NEG_I]]
// CHECK: ret <4 x i16> [[OR_I]]
@@ -10870,7 +9216,7 @@ int16x4_t test_vorn_s16(int16x4_t a, int16x4_t b) {
return vorn_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vorn_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vorn_s32(
// CHECK: [[NEG_I:%.*]] = xor <2 x i32> %b, <i32 -1, i32 -1>
// CHECK: [[OR_I:%.*]] = or <2 x i32> %a, [[NEG_I]]
// CHECK: ret <2 x i32> [[OR_I]]
@@ -10878,7 +9224,7 @@ int32x2_t test_vorn_s32(int32x2_t a, int32x2_t b) {
return vorn_s32(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vorn_s64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vorn_s64(
// CHECK: [[NEG_I:%.*]] = xor <1 x i64> %b, <i64 -1>
// CHECK: [[OR_I:%.*]] = or <1 x i64> %a, [[NEG_I]]
// CHECK: ret <1 x i64> [[OR_I]]
@@ -10886,7 +9232,7 @@ int64x1_t test_vorn_s64(int64x1_t a, int64x1_t b) {
return vorn_s64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vorn_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vorn_u8(
// CHECK: [[NEG_I:%.*]] = xor <8 x i8> %b, <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>
// CHECK: [[OR_I:%.*]] = or <8 x i8> %a, [[NEG_I]]
// CHECK: ret <8 x i8> [[OR_I]]
@@ -10894,7 +9240,7 @@ uint8x8_t test_vorn_u8(uint8x8_t a, uint8x8_t b) {
return vorn_u8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vorn_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vorn_u16(
// CHECK: [[NEG_I:%.*]] = xor <4 x i16> %b, <i16 -1, i16 -1, i16 -1, i16 -1>
// CHECK: [[OR_I:%.*]] = or <4 x i16> %a, [[NEG_I]]
// CHECK: ret <4 x i16> [[OR_I]]
@@ -10902,7 +9248,7 @@ uint16x4_t test_vorn_u16(uint16x4_t a, uint16x4_t b) {
return vorn_u16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vorn_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vorn_u32(
// CHECK: [[NEG_I:%.*]] = xor <2 x i32> %b, <i32 -1, i32 -1>
// CHECK: [[OR_I:%.*]] = or <2 x i32> %a, [[NEG_I]]
// CHECK: ret <2 x i32> [[OR_I]]
@@ -10910,7 +9256,7 @@ uint32x2_t test_vorn_u32(uint32x2_t a, uint32x2_t b) {
return vorn_u32(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vorn_u64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vorn_u64(
// CHECK: [[NEG_I:%.*]] = xor <1 x i64> %b, <i64 -1>
// CHECK: [[OR_I:%.*]] = or <1 x i64> %a, [[NEG_I]]
// CHECK: ret <1 x i64> [[OR_I]]
@@ -10918,7 +9264,7 @@ uint64x1_t test_vorn_u64(uint64x1_t a, uint64x1_t b) {
return vorn_u64(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vornq_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vornq_s8(
// CHECK: [[NEG_I:%.*]] = xor <16 x i8> %b, <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>
// CHECK: [[OR_I:%.*]] = or <16 x i8> %a, [[NEG_I]]
// CHECK: ret <16 x i8> [[OR_I]]
@@ -10926,7 +9272,7 @@ int8x16_t test_vornq_s8(int8x16_t a, int8x16_t b) {
return vornq_s8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vornq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vornq_s16(
// CHECK: [[NEG_I:%.*]] = xor <8 x i16> %b, <i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1>
// CHECK: [[OR_I:%.*]] = or <8 x i16> %a, [[NEG_I]]
// CHECK: ret <8 x i16> [[OR_I]]
@@ -10934,7 +9280,7 @@ int16x8_t test_vornq_s16(int16x8_t a, int16x8_t b) {
return vornq_s16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vornq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vornq_s32(
// CHECK: [[NEG_I:%.*]] = xor <4 x i32> %b, <i32 -1, i32 -1, i32 -1, i32 -1>
// CHECK: [[OR_I:%.*]] = or <4 x i32> %a, [[NEG_I]]
// CHECK: ret <4 x i32> [[OR_I]]
@@ -10942,7 +9288,7 @@ int32x4_t test_vornq_s32(int32x4_t a, int32x4_t b) {
return vornq_s32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vornq_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vornq_s64(
// CHECK: [[NEG_I:%.*]] = xor <2 x i64> %b, <i64 -1, i64 -1>
// CHECK: [[OR_I:%.*]] = or <2 x i64> %a, [[NEG_I]]
// CHECK: ret <2 x i64> [[OR_I]]
@@ -10950,7 +9296,7 @@ int64x2_t test_vornq_s64(int64x2_t a, int64x2_t b) {
return vornq_s64(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vornq_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vornq_u8(
// CHECK: [[NEG_I:%.*]] = xor <16 x i8> %b, <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>
// CHECK: [[OR_I:%.*]] = or <16 x i8> %a, [[NEG_I]]
// CHECK: ret <16 x i8> [[OR_I]]
@@ -10958,7 +9304,7 @@ uint8x16_t test_vornq_u8(uint8x16_t a, uint8x16_t b) {
return vornq_u8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vornq_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vornq_u16(
// CHECK: [[NEG_I:%.*]] = xor <8 x i16> %b, <i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1>
// CHECK: [[OR_I:%.*]] = or <8 x i16> %a, [[NEG_I]]
// CHECK: ret <8 x i16> [[OR_I]]
@@ -10966,7 +9312,7 @@ uint16x8_t test_vornq_u16(uint16x8_t a, uint16x8_t b) {
return vornq_u16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vornq_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vornq_u32(
// CHECK: [[NEG_I:%.*]] = xor <4 x i32> %b, <i32 -1, i32 -1, i32 -1, i32 -1>
// CHECK: [[OR_I:%.*]] = or <4 x i32> %a, [[NEG_I]]
// CHECK: ret <4 x i32> [[OR_I]]
@@ -10974,7 +9320,7 @@ uint32x4_t test_vornq_u32(uint32x4_t a, uint32x4_t b) {
return vornq_u32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vornq_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vornq_u64(
// CHECK: [[NEG_I:%.*]] = xor <2 x i64> %b, <i64 -1, i64 -1>
// CHECK: [[OR_I:%.*]] = or <2 x i64> %a, [[NEG_I]]
// CHECK: ret <2 x i64> [[OR_I]]
@@ -10982,891 +9328,751 @@ uint64x2_t test_vornq_u64(uint64x2_t a, uint64x2_t b) {
return vornq_u64(a, b);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vorr_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vorr_s8(
// CHECK: [[OR_I:%.*]] = or <8 x i8> %a, %b
// CHECK: ret <8 x i8> [[OR_I]]
int8x8_t test_vorr_s8(int8x8_t a, int8x8_t b) {
return vorr_s8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vorr_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vorr_s16(
// CHECK: [[OR_I:%.*]] = or <4 x i16> %a, %b
// CHECK: ret <4 x i16> [[OR_I]]
int16x4_t test_vorr_s16(int16x4_t a, int16x4_t b) {
return vorr_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vorr_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vorr_s32(
// CHECK: [[OR_I:%.*]] = or <2 x i32> %a, %b
// CHECK: ret <2 x i32> [[OR_I]]
int32x2_t test_vorr_s32(int32x2_t a, int32x2_t b) {
return vorr_s32(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vorr_s64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vorr_s64(
// CHECK: [[OR_I:%.*]] = or <1 x i64> %a, %b
// CHECK: ret <1 x i64> [[OR_I]]
int64x1_t test_vorr_s64(int64x1_t a, int64x1_t b) {
return vorr_s64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vorr_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vorr_u8(
// CHECK: [[OR_I:%.*]] = or <8 x i8> %a, %b
// CHECK: ret <8 x i8> [[OR_I]]
uint8x8_t test_vorr_u8(uint8x8_t a, uint8x8_t b) {
return vorr_u8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vorr_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vorr_u16(
// CHECK: [[OR_I:%.*]] = or <4 x i16> %a, %b
// CHECK: ret <4 x i16> [[OR_I]]
uint16x4_t test_vorr_u16(uint16x4_t a, uint16x4_t b) {
return vorr_u16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vorr_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vorr_u32(
// CHECK: [[OR_I:%.*]] = or <2 x i32> %a, %b
// CHECK: ret <2 x i32> [[OR_I]]
uint32x2_t test_vorr_u32(uint32x2_t a, uint32x2_t b) {
return vorr_u32(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vorr_u64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vorr_u64(
// CHECK: [[OR_I:%.*]] = or <1 x i64> %a, %b
// CHECK: ret <1 x i64> [[OR_I]]
uint64x1_t test_vorr_u64(uint64x1_t a, uint64x1_t b) {
return vorr_u64(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vorrq_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vorrq_s8(
// CHECK: [[OR_I:%.*]] = or <16 x i8> %a, %b
// CHECK: ret <16 x i8> [[OR_I]]
int8x16_t test_vorrq_s8(int8x16_t a, int8x16_t b) {
return vorrq_s8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vorrq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vorrq_s16(
// CHECK: [[OR_I:%.*]] = or <8 x i16> %a, %b
// CHECK: ret <8 x i16> [[OR_I]]
int16x8_t test_vorrq_s16(int16x8_t a, int16x8_t b) {
return vorrq_s16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vorrq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vorrq_s32(
// CHECK: [[OR_I:%.*]] = or <4 x i32> %a, %b
// CHECK: ret <4 x i32> [[OR_I]]
int32x4_t test_vorrq_s32(int32x4_t a, int32x4_t b) {
return vorrq_s32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vorrq_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vorrq_s64(
// CHECK: [[OR_I:%.*]] = or <2 x i64> %a, %b
// CHECK: ret <2 x i64> [[OR_I]]
int64x2_t test_vorrq_s64(int64x2_t a, int64x2_t b) {
return vorrq_s64(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vorrq_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vorrq_u8(
// CHECK: [[OR_I:%.*]] = or <16 x i8> %a, %b
// CHECK: ret <16 x i8> [[OR_I]]
uint8x16_t test_vorrq_u8(uint8x16_t a, uint8x16_t b) {
return vorrq_u8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vorrq_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vorrq_u16(
// CHECK: [[OR_I:%.*]] = or <8 x i16> %a, %b
// CHECK: ret <8 x i16> [[OR_I]]
uint16x8_t test_vorrq_u16(uint16x8_t a, uint16x8_t b) {
return vorrq_u16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vorrq_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vorrq_u32(
// CHECK: [[OR_I:%.*]] = or <4 x i32> %a, %b
// CHECK: ret <4 x i32> [[OR_I]]
uint32x4_t test_vorrq_u32(uint32x4_t a, uint32x4_t b) {
return vorrq_u32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vorrq_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vorrq_u64(
// CHECK: [[OR_I:%.*]] = or <2 x i64> %a, %b
// CHECK: ret <2 x i64> [[OR_I]]
uint64x2_t test_vorrq_u64(uint64x2_t a, uint64x2_t b) {
return vorrq_u64(a, b);
}
-
-// CHECK-LABEL: define <4 x i16> @test_vpadal_s8(<4 x i16> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vpadal_s8(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
-// CHECK: [[VPADAL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VPADAL_V1_I:%.*]] = call <4 x i16> @llvm.arm.neon.vpadals.v4i16.v8i8(<4 x i16> [[VPADAL_V_I]], <8 x i8> %b) #4
+// CHECK: [[VPADAL_V1_I:%.*]] = call <4 x i16> @llvm.arm.neon.vpadals.v4i16.v8i8(<4 x i16> %a, <8 x i8> %b) #4
// CHECK: ret <4 x i16> [[VPADAL_V1_I]]
int16x4_t test_vpadal_s8(int16x4_t a, int8x8_t b) {
return vpadal_s8(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vpadal_s16(<2 x i32> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vpadal_s16(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VPADAL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VPADAL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VPADAL_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vpadals.v2i32.v4i16(<2 x i32> [[VPADAL_V_I]], <4 x i16> [[VPADAL_V1_I]]) #4
+// CHECK: [[VPADAL_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vpadals.v2i32.v4i16(<2 x i32> %a, <4 x i16> %b) #4
// CHECK: ret <2 x i32> [[VPADAL_V2_I]]
int32x2_t test_vpadal_s16(int32x2_t a, int16x4_t b) {
return vpadal_s16(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vpadal_s32(<1 x i64> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vpadal_s32(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VPADAL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
-// CHECK: [[VPADAL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VPADAL_V2_I:%.*]] = call <1 x i64> @llvm.arm.neon.vpadals.v1i64.v2i32(<1 x i64> [[VPADAL_V_I]], <2 x i32> [[VPADAL_V1_I]]) #4
+// CHECK: [[VPADAL_V2_I:%.*]] = call <1 x i64> @llvm.arm.neon.vpadals.v1i64.v2i32(<1 x i64> %a, <2 x i32> %b) #4
// CHECK: ret <1 x i64> [[VPADAL_V2_I]]
int64x1_t test_vpadal_s32(int64x1_t a, int32x2_t b) {
return vpadal_s32(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vpadal_u8(<4 x i16> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vpadal_u8(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
-// CHECK: [[VPADAL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VPADAL_V1_I:%.*]] = call <4 x i16> @llvm.arm.neon.vpadalu.v4i16.v8i8(<4 x i16> [[VPADAL_V_I]], <8 x i8> %b) #4
+// CHECK: [[VPADAL_V1_I:%.*]] = call <4 x i16> @llvm.arm.neon.vpadalu.v4i16.v8i8(<4 x i16> %a, <8 x i8> %b) #4
// CHECK: ret <4 x i16> [[VPADAL_V1_I]]
uint16x4_t test_vpadal_u8(uint16x4_t a, uint8x8_t b) {
return vpadal_u8(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vpadal_u16(<2 x i32> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vpadal_u16(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VPADAL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VPADAL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VPADAL_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vpadalu.v2i32.v4i16(<2 x i32> [[VPADAL_V_I]], <4 x i16> [[VPADAL_V1_I]]) #4
+// CHECK: [[VPADAL_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vpadalu.v2i32.v4i16(<2 x i32> %a, <4 x i16> %b) #4
// CHECK: ret <2 x i32> [[VPADAL_V2_I]]
uint32x2_t test_vpadal_u16(uint32x2_t a, uint16x4_t b) {
return vpadal_u16(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vpadal_u32(<1 x i64> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vpadal_u32(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VPADAL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
-// CHECK: [[VPADAL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VPADAL_V2_I:%.*]] = call <1 x i64> @llvm.arm.neon.vpadalu.v1i64.v2i32(<1 x i64> [[VPADAL_V_I]], <2 x i32> [[VPADAL_V1_I]]) #4
+// CHECK: [[VPADAL_V2_I:%.*]] = call <1 x i64> @llvm.arm.neon.vpadalu.v1i64.v2i32(<1 x i64> %a, <2 x i32> %b) #4
// CHECK: ret <1 x i64> [[VPADAL_V2_I]]
uint64x1_t test_vpadal_u32(uint64x1_t a, uint32x2_t b) {
return vpadal_u32(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vpadalq_s8(<8 x i16> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vpadalq_s8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
-// CHECK: [[VPADALQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VPADALQ_V1_I:%.*]] = call <8 x i16> @llvm.arm.neon.vpadals.v8i16.v16i8(<8 x i16> [[VPADALQ_V_I]], <16 x i8> %b) #4
+// CHECK: [[VPADALQ_V1_I:%.*]] = call <8 x i16> @llvm.arm.neon.vpadals.v8i16.v16i8(<8 x i16> %a, <16 x i8> %b) #4
// CHECK: ret <8 x i16> [[VPADALQ_V1_I]]
int16x8_t test_vpadalq_s8(int16x8_t a, int8x16_t b) {
return vpadalq_s8(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vpadalq_s16(<4 x i32> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vpadalq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VPADALQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VPADALQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VPADALQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vpadals.v4i32.v8i16(<4 x i32> [[VPADALQ_V_I]], <8 x i16> [[VPADALQ_V1_I]]) #4
+// CHECK: [[VPADALQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vpadals.v4i32.v8i16(<4 x i32> %a, <8 x i16> %b) #4
// CHECK: ret <4 x i32> [[VPADALQ_V2_I]]
int32x4_t test_vpadalq_s16(int32x4_t a, int16x8_t b) {
return vpadalq_s16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vpadalq_s32(<2 x i64> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vpadalq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VPADALQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VPADALQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VPADALQ_V2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vpadals.v2i64.v4i32(<2 x i64> [[VPADALQ_V_I]], <4 x i32> [[VPADALQ_V1_I]]) #4
+// CHECK: [[VPADALQ_V2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vpadals.v2i64.v4i32(<2 x i64> %a, <4 x i32> %b) #4
// CHECK: ret <2 x i64> [[VPADALQ_V2_I]]
int64x2_t test_vpadalq_s32(int64x2_t a, int32x4_t b) {
return vpadalq_s32(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vpadalq_u8(<8 x i16> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vpadalq_u8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
-// CHECK: [[VPADALQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VPADALQ_V1_I:%.*]] = call <8 x i16> @llvm.arm.neon.vpadalu.v8i16.v16i8(<8 x i16> [[VPADALQ_V_I]], <16 x i8> %b) #4
+// CHECK: [[VPADALQ_V1_I:%.*]] = call <8 x i16> @llvm.arm.neon.vpadalu.v8i16.v16i8(<8 x i16> %a, <16 x i8> %b) #4
// CHECK: ret <8 x i16> [[VPADALQ_V1_I]]
uint16x8_t test_vpadalq_u8(uint16x8_t a, uint8x16_t b) {
return vpadalq_u8(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vpadalq_u16(<4 x i32> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vpadalq_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VPADALQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VPADALQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VPADALQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vpadalu.v4i32.v8i16(<4 x i32> [[VPADALQ_V_I]], <8 x i16> [[VPADALQ_V1_I]]) #4
+// CHECK: [[VPADALQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vpadalu.v4i32.v8i16(<4 x i32> %a, <8 x i16> %b) #4
// CHECK: ret <4 x i32> [[VPADALQ_V2_I]]
uint32x4_t test_vpadalq_u16(uint32x4_t a, uint16x8_t b) {
return vpadalq_u16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vpadalq_u32(<2 x i64> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vpadalq_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VPADALQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VPADALQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VPADALQ_V2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vpadalu.v2i64.v4i32(<2 x i64> [[VPADALQ_V_I]], <4 x i32> [[VPADALQ_V1_I]]) #4
+// CHECK: [[VPADALQ_V2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vpadalu.v2i64.v4i32(<2 x i64> %a, <4 x i32> %b) #4
// CHECK: ret <2 x i64> [[VPADALQ_V2_I]]
uint64x2_t test_vpadalq_u32(uint64x2_t a, uint32x4_t b) {
return vpadalq_u32(a, b);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vpadd_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vpadd_s8(
// CHECK: [[VPADD_V_I:%.*]] = call <8 x i8> @llvm.arm.neon.vpadd.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VPADD_V_I]]
int8x8_t test_vpadd_s8(int8x8_t a, int8x8_t b) {
return vpadd_s8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vpadd_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vpadd_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VPADD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VPADD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VPADD_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vpadd.v4i16(<4 x i16> [[VPADD_V_I]], <4 x i16> [[VPADD_V1_I]]) #4
+// CHECK: [[VPADD_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vpadd.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VPADD_V3_I:%.*]] = bitcast <4 x i16> [[VPADD_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VPADD_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VPADD_V2_I]]
int16x4_t test_vpadd_s16(int16x4_t a, int16x4_t b) {
return vpadd_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vpadd_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vpadd_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VPADD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VPADD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VPADD_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vpadd.v2i32(<2 x i32> [[VPADD_V_I]], <2 x i32> [[VPADD_V1_I]]) #4
+// CHECK: [[VPADD_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vpadd.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VPADD_V3_I:%.*]] = bitcast <2 x i32> [[VPADD_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VPADD_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VPADD_V2_I]]
int32x2_t test_vpadd_s32(int32x2_t a, int32x2_t b) {
return vpadd_s32(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vpadd_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vpadd_u8(
// CHECK: [[VPADD_V_I:%.*]] = call <8 x i8> @llvm.arm.neon.vpadd.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VPADD_V_I]]
uint8x8_t test_vpadd_u8(uint8x8_t a, uint8x8_t b) {
return vpadd_u8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vpadd_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vpadd_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VPADD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VPADD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VPADD_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vpadd.v4i16(<4 x i16> [[VPADD_V_I]], <4 x i16> [[VPADD_V1_I]]) #4
+// CHECK: [[VPADD_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vpadd.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VPADD_V3_I:%.*]] = bitcast <4 x i16> [[VPADD_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VPADD_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VPADD_V2_I]]
uint16x4_t test_vpadd_u16(uint16x4_t a, uint16x4_t b) {
return vpadd_u16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vpadd_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vpadd_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VPADD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VPADD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VPADD_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vpadd.v2i32(<2 x i32> [[VPADD_V_I]], <2 x i32> [[VPADD_V1_I]]) #4
+// CHECK: [[VPADD_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vpadd.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VPADD_V3_I:%.*]] = bitcast <2 x i32> [[VPADD_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VPADD_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VPADD_V2_I]]
uint32x2_t test_vpadd_u32(uint32x2_t a, uint32x2_t b) {
return vpadd_u32(a, b);
}
-// CHECK-LABEL: define <2 x float> @test_vpadd_f32(<2 x float> %a, <2 x float> %b) #0 {
+// CHECK-LABEL: @test_vpadd_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %b to <8 x i8>
-// CHECK: [[VPADD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VPADD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK: [[VPADD_V2_I:%.*]] = call <2 x float> @llvm.arm.neon.vpadd.v2f32(<2 x float> [[VPADD_V_I]], <2 x float> [[VPADD_V1_I]]) #4
+// CHECK: [[VPADD_V2_I:%.*]] = call <2 x float> @llvm.arm.neon.vpadd.v2f32(<2 x float> %a, <2 x float> %b) #4
// CHECK: [[VPADD_V3_I:%.*]] = bitcast <2 x float> [[VPADD_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VPADD_V3_I]] to <2 x float>
-// CHECK: ret <2 x float> [[TMP2]]
+// CHECK: ret <2 x float> [[VPADD_V2_I]]
float32x2_t test_vpadd_f32(float32x2_t a, float32x2_t b) {
return vpadd_f32(a, b);
}
-
-// CHECK-LABEL: define <4 x i16> @test_vpaddl_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vpaddl_s8(
// CHECK: [[VPADDL_I:%.*]] = call <4 x i16> @llvm.arm.neon.vpaddls.v4i16.v8i8(<8 x i8> %a) #4
// CHECK: ret <4 x i16> [[VPADDL_I]]
int16x4_t test_vpaddl_s8(int8x8_t a) {
return vpaddl_s8(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vpaddl_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vpaddl_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
-// CHECK: [[VPADDL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VPADDL1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vpaddls.v2i32.v4i16(<4 x i16> [[VPADDL_I]]) #4
+// CHECK: [[VPADDL1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vpaddls.v2i32.v4i16(<4 x i16> %a) #4
// CHECK: ret <2 x i32> [[VPADDL1_I]]
int32x2_t test_vpaddl_s16(int16x4_t a) {
return vpaddl_s16(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vpaddl_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vpaddl_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[VPADDL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VPADDL1_I:%.*]] = call <1 x i64> @llvm.arm.neon.vpaddls.v1i64.v2i32(<2 x i32> [[VPADDL_I]]) #4
+// CHECK: [[VPADDL1_I:%.*]] = call <1 x i64> @llvm.arm.neon.vpaddls.v1i64.v2i32(<2 x i32> %a) #4
// CHECK: ret <1 x i64> [[VPADDL1_I]]
int64x1_t test_vpaddl_s32(int32x2_t a) {
return vpaddl_s32(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vpaddl_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vpaddl_u8(
// CHECK: [[VPADDL_I:%.*]] = call <4 x i16> @llvm.arm.neon.vpaddlu.v4i16.v8i8(<8 x i8> %a) #4
// CHECK: ret <4 x i16> [[VPADDL_I]]
uint16x4_t test_vpaddl_u8(uint8x8_t a) {
return vpaddl_u8(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vpaddl_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vpaddl_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
-// CHECK: [[VPADDL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VPADDL1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vpaddlu.v2i32.v4i16(<4 x i16> [[VPADDL_I]]) #4
+// CHECK: [[VPADDL1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vpaddlu.v2i32.v4i16(<4 x i16> %a) #4
// CHECK: ret <2 x i32> [[VPADDL1_I]]
uint32x2_t test_vpaddl_u16(uint16x4_t a) {
return vpaddl_u16(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vpaddl_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vpaddl_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[VPADDL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VPADDL1_I:%.*]] = call <1 x i64> @llvm.arm.neon.vpaddlu.v1i64.v2i32(<2 x i32> [[VPADDL_I]]) #4
+// CHECK: [[VPADDL1_I:%.*]] = call <1 x i64> @llvm.arm.neon.vpaddlu.v1i64.v2i32(<2 x i32> %a) #4
// CHECK: ret <1 x i64> [[VPADDL1_I]]
uint64x1_t test_vpaddl_u32(uint32x2_t a) {
return vpaddl_u32(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vpaddlq_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vpaddlq_s8(
// CHECK: [[VPADDL_I:%.*]] = call <8 x i16> @llvm.arm.neon.vpaddls.v8i16.v16i8(<16 x i8> %a) #4
// CHECK: ret <8 x i16> [[VPADDL_I]]
int16x8_t test_vpaddlq_s8(int8x16_t a) {
return vpaddlq_s8(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vpaddlq_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vpaddlq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
-// CHECK: [[VPADDL_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VPADDL1_I:%.*]] = call <4 x i32> @llvm.arm.neon.vpaddls.v4i32.v8i16(<8 x i16> [[VPADDL_I]]) #4
+// CHECK: [[VPADDL1_I:%.*]] = call <4 x i32> @llvm.arm.neon.vpaddls.v4i32.v8i16(<8 x i16> %a) #4
// CHECK: ret <4 x i32> [[VPADDL1_I]]
int32x4_t test_vpaddlq_s16(int16x8_t a) {
return vpaddlq_s16(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vpaddlq_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vpaddlq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
-// CHECK: [[VPADDL_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VPADDL1_I:%.*]] = call <2 x i64> @llvm.arm.neon.vpaddls.v2i64.v4i32(<4 x i32> [[VPADDL_I]]) #4
+// CHECK: [[VPADDL1_I:%.*]] = call <2 x i64> @llvm.arm.neon.vpaddls.v2i64.v4i32(<4 x i32> %a) #4
// CHECK: ret <2 x i64> [[VPADDL1_I]]
int64x2_t test_vpaddlq_s32(int32x4_t a) {
return vpaddlq_s32(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vpaddlq_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vpaddlq_u8(
// CHECK: [[VPADDL_I:%.*]] = call <8 x i16> @llvm.arm.neon.vpaddlu.v8i16.v16i8(<16 x i8> %a) #4
// CHECK: ret <8 x i16> [[VPADDL_I]]
uint16x8_t test_vpaddlq_u8(uint8x16_t a) {
return vpaddlq_u8(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vpaddlq_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vpaddlq_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
-// CHECK: [[VPADDL_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VPADDL1_I:%.*]] = call <4 x i32> @llvm.arm.neon.vpaddlu.v4i32.v8i16(<8 x i16> [[VPADDL_I]]) #4
+// CHECK: [[VPADDL1_I:%.*]] = call <4 x i32> @llvm.arm.neon.vpaddlu.v4i32.v8i16(<8 x i16> %a) #4
// CHECK: ret <4 x i32> [[VPADDL1_I]]
uint32x4_t test_vpaddlq_u16(uint16x8_t a) {
return vpaddlq_u16(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vpaddlq_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vpaddlq_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
-// CHECK: [[VPADDL_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VPADDL1_I:%.*]] = call <2 x i64> @llvm.arm.neon.vpaddlu.v2i64.v4i32(<4 x i32> [[VPADDL_I]]) #4
+// CHECK: [[VPADDL1_I:%.*]] = call <2 x i64> @llvm.arm.neon.vpaddlu.v2i64.v4i32(<4 x i32> %a) #4
// CHECK: ret <2 x i64> [[VPADDL1_I]]
uint64x2_t test_vpaddlq_u32(uint32x4_t a) {
return vpaddlq_u32(a);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vpmax_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vpmax_s8(
// CHECK: [[VPMAX_V_I:%.*]] = call <8 x i8> @llvm.arm.neon.vpmaxs.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VPMAX_V_I]]
int8x8_t test_vpmax_s8(int8x8_t a, int8x8_t b) {
return vpmax_s8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vpmax_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vpmax_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VPMAX_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VPMAX_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VPMAX_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vpmaxs.v4i16(<4 x i16> [[VPMAX_V_I]], <4 x i16> [[VPMAX_V1_I]]) #4
+// CHECK: [[VPMAX_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vpmaxs.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VPMAX_V3_I:%.*]] = bitcast <4 x i16> [[VPMAX_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VPMAX_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VPMAX_V2_I]]
int16x4_t test_vpmax_s16(int16x4_t a, int16x4_t b) {
return vpmax_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vpmax_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vpmax_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VPMAX_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VPMAX_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VPMAX_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vpmaxs.v2i32(<2 x i32> [[VPMAX_V_I]], <2 x i32> [[VPMAX_V1_I]]) #4
+// CHECK: [[VPMAX_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vpmaxs.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VPMAX_V3_I:%.*]] = bitcast <2 x i32> [[VPMAX_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VPMAX_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VPMAX_V2_I]]
int32x2_t test_vpmax_s32(int32x2_t a, int32x2_t b) {
return vpmax_s32(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vpmax_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vpmax_u8(
// CHECK: [[VPMAX_V_I:%.*]] = call <8 x i8> @llvm.arm.neon.vpmaxu.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VPMAX_V_I]]
uint8x8_t test_vpmax_u8(uint8x8_t a, uint8x8_t b) {
return vpmax_u8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vpmax_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vpmax_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VPMAX_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VPMAX_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VPMAX_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vpmaxu.v4i16(<4 x i16> [[VPMAX_V_I]], <4 x i16> [[VPMAX_V1_I]]) #4
+// CHECK: [[VPMAX_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vpmaxu.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VPMAX_V3_I:%.*]] = bitcast <4 x i16> [[VPMAX_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VPMAX_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VPMAX_V2_I]]
uint16x4_t test_vpmax_u16(uint16x4_t a, uint16x4_t b) {
return vpmax_u16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vpmax_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vpmax_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VPMAX_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VPMAX_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VPMAX_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vpmaxu.v2i32(<2 x i32> [[VPMAX_V_I]], <2 x i32> [[VPMAX_V1_I]]) #4
+// CHECK: [[VPMAX_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vpmaxu.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VPMAX_V3_I:%.*]] = bitcast <2 x i32> [[VPMAX_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VPMAX_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VPMAX_V2_I]]
uint32x2_t test_vpmax_u32(uint32x2_t a, uint32x2_t b) {
return vpmax_u32(a, b);
}
-// CHECK-LABEL: define <2 x float> @test_vpmax_f32(<2 x float> %a, <2 x float> %b) #0 {
+// CHECK-LABEL: @test_vpmax_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %b to <8 x i8>
-// CHECK: [[VPMAX_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VPMAX_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK: [[VPMAX_V2_I:%.*]] = call <2 x float> @llvm.arm.neon.vpmaxs.v2f32(<2 x float> [[VPMAX_V_I]], <2 x float> [[VPMAX_V1_I]]) #4
+// CHECK: [[VPMAX_V2_I:%.*]] = call <2 x float> @llvm.arm.neon.vpmaxs.v2f32(<2 x float> %a, <2 x float> %b) #4
// CHECK: [[VPMAX_V3_I:%.*]] = bitcast <2 x float> [[VPMAX_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VPMAX_V3_I]] to <2 x float>
-// CHECK: ret <2 x float> [[TMP2]]
+// CHECK: ret <2 x float> [[VPMAX_V2_I]]
float32x2_t test_vpmax_f32(float32x2_t a, float32x2_t b) {
return vpmax_f32(a, b);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vpmin_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vpmin_s8(
// CHECK: [[VPMIN_V_I:%.*]] = call <8 x i8> @llvm.arm.neon.vpmins.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VPMIN_V_I]]
int8x8_t test_vpmin_s8(int8x8_t a, int8x8_t b) {
return vpmin_s8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vpmin_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vpmin_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VPMIN_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VPMIN_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VPMIN_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vpmins.v4i16(<4 x i16> [[VPMIN_V_I]], <4 x i16> [[VPMIN_V1_I]]) #4
+// CHECK: [[VPMIN_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vpmins.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VPMIN_V3_I:%.*]] = bitcast <4 x i16> [[VPMIN_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VPMIN_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VPMIN_V2_I]]
int16x4_t test_vpmin_s16(int16x4_t a, int16x4_t b) {
return vpmin_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vpmin_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vpmin_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VPMIN_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VPMIN_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VPMIN_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vpmins.v2i32(<2 x i32> [[VPMIN_V_I]], <2 x i32> [[VPMIN_V1_I]]) #4
+// CHECK: [[VPMIN_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vpmins.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VPMIN_V3_I:%.*]] = bitcast <2 x i32> [[VPMIN_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VPMIN_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VPMIN_V2_I]]
int32x2_t test_vpmin_s32(int32x2_t a, int32x2_t b) {
return vpmin_s32(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vpmin_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vpmin_u8(
// CHECK: [[VPMIN_V_I:%.*]] = call <8 x i8> @llvm.arm.neon.vpminu.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VPMIN_V_I]]
uint8x8_t test_vpmin_u8(uint8x8_t a, uint8x8_t b) {
return vpmin_u8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vpmin_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vpmin_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VPMIN_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VPMIN_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VPMIN_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vpminu.v4i16(<4 x i16> [[VPMIN_V_I]], <4 x i16> [[VPMIN_V1_I]]) #4
+// CHECK: [[VPMIN_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vpminu.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VPMIN_V3_I:%.*]] = bitcast <4 x i16> [[VPMIN_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VPMIN_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VPMIN_V2_I]]
uint16x4_t test_vpmin_u16(uint16x4_t a, uint16x4_t b) {
return vpmin_u16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vpmin_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vpmin_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VPMIN_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VPMIN_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VPMIN_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vpminu.v2i32(<2 x i32> [[VPMIN_V_I]], <2 x i32> [[VPMIN_V1_I]]) #4
+// CHECK: [[VPMIN_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vpminu.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VPMIN_V3_I:%.*]] = bitcast <2 x i32> [[VPMIN_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VPMIN_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VPMIN_V2_I]]
uint32x2_t test_vpmin_u32(uint32x2_t a, uint32x2_t b) {
return vpmin_u32(a, b);
}
-// CHECK-LABEL: define <2 x float> @test_vpmin_f32(<2 x float> %a, <2 x float> %b) #0 {
+// CHECK-LABEL: @test_vpmin_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %b to <8 x i8>
-// CHECK: [[VPMIN_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VPMIN_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK: [[VPMIN_V2_I:%.*]] = call <2 x float> @llvm.arm.neon.vpmins.v2f32(<2 x float> [[VPMIN_V_I]], <2 x float> [[VPMIN_V1_I]]) #4
+// CHECK: [[VPMIN_V2_I:%.*]] = call <2 x float> @llvm.arm.neon.vpmins.v2f32(<2 x float> %a, <2 x float> %b) #4
// CHECK: [[VPMIN_V3_I:%.*]] = bitcast <2 x float> [[VPMIN_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VPMIN_V3_I]] to <2 x float>
-// CHECK: ret <2 x float> [[TMP2]]
+// CHECK: ret <2 x float> [[VPMIN_V2_I]]
float32x2_t test_vpmin_f32(float32x2_t a, float32x2_t b) {
return vpmin_f32(a, b);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vqabs_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vqabs_s8(
// CHECK: [[VQABS_V_I:%.*]] = call <8 x i8> @llvm.arm.neon.vqabs.v8i8(<8 x i8> %a) #4
// CHECK: ret <8 x i8> [[VQABS_V_I]]
int8x8_t test_vqabs_s8(int8x8_t a) {
return vqabs_s8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vqabs_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vqabs_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
-// CHECK: [[VQABS_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQABS_V1_I:%.*]] = call <4 x i16> @llvm.arm.neon.vqabs.v4i16(<4 x i16> [[VQABS_V_I]]) #4
+// CHECK: [[VQABS_V1_I:%.*]] = call <4 x i16> @llvm.arm.neon.vqabs.v4i16(<4 x i16> %a) #4
// CHECK: [[VQABS_V2_I:%.*]] = bitcast <4 x i16> [[VQABS_V1_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[VQABS_V2_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP1]]
+// CHECK: ret <4 x i16> [[VQABS_V1_I]]
int16x4_t test_vqabs_s16(int16x4_t a) {
return vqabs_s16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vqabs_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vqabs_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[VQABS_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQABS_V1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vqabs.v2i32(<2 x i32> [[VQABS_V_I]]) #4
+// CHECK: [[VQABS_V1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vqabs.v2i32(<2 x i32> %a) #4
// CHECK: [[VQABS_V2_I:%.*]] = bitcast <2 x i32> [[VQABS_V1_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[VQABS_V2_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP1]]
+// CHECK: ret <2 x i32> [[VQABS_V1_I]]
int32x2_t test_vqabs_s32(int32x2_t a) {
return vqabs_s32(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vqabsq_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vqabsq_s8(
// CHECK: [[VQABSQ_V_I:%.*]] = call <16 x i8> @llvm.arm.neon.vqabs.v16i8(<16 x i8> %a) #4
// CHECK: ret <16 x i8> [[VQABSQ_V_I]]
int8x16_t test_vqabsq_s8(int8x16_t a) {
return vqabsq_s8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vqabsq_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vqabsq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
-// CHECK: [[VQABSQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VQABSQ_V1_I:%.*]] = call <8 x i16> @llvm.arm.neon.vqabs.v8i16(<8 x i16> [[VQABSQ_V_I]]) #4
+// CHECK: [[VQABSQ_V1_I:%.*]] = call <8 x i16> @llvm.arm.neon.vqabs.v8i16(<8 x i16> %a) #4
// CHECK: [[VQABSQ_V2_I:%.*]] = bitcast <8 x i16> [[VQABSQ_V1_I]] to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[VQABSQ_V2_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP1]]
+// CHECK: ret <8 x i16> [[VQABSQ_V1_I]]
int16x8_t test_vqabsq_s16(int16x8_t a) {
return vqabsq_s16(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vqabsq_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vqabsq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
-// CHECK: [[VQABSQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQABSQ_V1_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqabs.v4i32(<4 x i32> [[VQABSQ_V_I]]) #4
+// CHECK: [[VQABSQ_V1_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqabs.v4i32(<4 x i32> %a) #4
// CHECK: [[VQABSQ_V2_I:%.*]] = bitcast <4 x i32> [[VQABSQ_V1_I]] to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[VQABSQ_V2_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP1]]
+// CHECK: ret <4 x i32> [[VQABSQ_V1_I]]
int32x4_t test_vqabsq_s32(int32x4_t a) {
return vqabsq_s32(a);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vqadd_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vqadd_s8(
// CHECK: [[VQADD_V_I:%.*]] = call <8 x i8> @llvm.arm.neon.vqadds.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VQADD_V_I]]
int8x8_t test_vqadd_s8(int8x8_t a, int8x8_t b) {
return vqadd_s8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vqadd_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqadd_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VQADD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQADD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQADD_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vqadds.v4i16(<4 x i16> [[VQADD_V_I]], <4 x i16> [[VQADD_V1_I]]) #4
+// CHECK: [[VQADD_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vqadds.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VQADD_V3_I:%.*]] = bitcast <4 x i16> [[VQADD_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQADD_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VQADD_V2_I]]
int16x4_t test_vqadd_s16(int16x4_t a, int16x4_t b) {
return vqadd_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vqadd_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqadd_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VQADD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQADD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQADD_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vqadds.v2i32(<2 x i32> [[VQADD_V_I]], <2 x i32> [[VQADD_V1_I]]) #4
+// CHECK: [[VQADD_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vqadds.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VQADD_V3_I:%.*]] = bitcast <2 x i32> [[VQADD_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQADD_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VQADD_V2_I]]
int32x2_t test_vqadd_s32(int32x2_t a, int32x2_t b) {
return vqadd_s32(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vqadd_s64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vqadd_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
-// CHECK: [[VQADD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
-// CHECK: [[VQADD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x i64>
-// CHECK: [[VQADD_V2_I:%.*]] = call <1 x i64> @llvm.arm.neon.vqadds.v1i64(<1 x i64> [[VQADD_V_I]], <1 x i64> [[VQADD_V1_I]]) #4
+// CHECK: [[VQADD_V2_I:%.*]] = call <1 x i64> @llvm.arm.neon.vqadds.v1i64(<1 x i64> %a, <1 x i64> %b) #4
// CHECK: [[VQADD_V3_I:%.*]] = bitcast <1 x i64> [[VQADD_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQADD_V3_I]] to <1 x i64>
-// CHECK: ret <1 x i64> [[TMP2]]
+// CHECK: ret <1 x i64> [[VQADD_V2_I]]
int64x1_t test_vqadd_s64(int64x1_t a, int64x1_t b) {
return vqadd_s64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vqadd_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vqadd_u8(
// CHECK: [[VQADD_V_I:%.*]] = call <8 x i8> @llvm.arm.neon.vqaddu.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VQADD_V_I]]
uint8x8_t test_vqadd_u8(uint8x8_t a, uint8x8_t b) {
return vqadd_u8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vqadd_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqadd_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VQADD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQADD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQADD_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vqaddu.v4i16(<4 x i16> [[VQADD_V_I]], <4 x i16> [[VQADD_V1_I]]) #4
+// CHECK: [[VQADD_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vqaddu.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VQADD_V3_I:%.*]] = bitcast <4 x i16> [[VQADD_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQADD_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VQADD_V2_I]]
uint16x4_t test_vqadd_u16(uint16x4_t a, uint16x4_t b) {
return vqadd_u16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vqadd_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqadd_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VQADD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQADD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQADD_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vqaddu.v2i32(<2 x i32> [[VQADD_V_I]], <2 x i32> [[VQADD_V1_I]]) #4
+// CHECK: [[VQADD_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vqaddu.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VQADD_V3_I:%.*]] = bitcast <2 x i32> [[VQADD_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQADD_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VQADD_V2_I]]
uint32x2_t test_vqadd_u32(uint32x2_t a, uint32x2_t b) {
return vqadd_u32(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vqadd_u64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vqadd_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
-// CHECK: [[VQADD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
-// CHECK: [[VQADD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x i64>
-// CHECK: [[VQADD_V2_I:%.*]] = call <1 x i64> @llvm.arm.neon.vqaddu.v1i64(<1 x i64> [[VQADD_V_I]], <1 x i64> [[VQADD_V1_I]]) #4
+// CHECK: [[VQADD_V2_I:%.*]] = call <1 x i64> @llvm.arm.neon.vqaddu.v1i64(<1 x i64> %a, <1 x i64> %b) #4
// CHECK: [[VQADD_V3_I:%.*]] = bitcast <1 x i64> [[VQADD_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQADD_V3_I]] to <1 x i64>
-// CHECK: ret <1 x i64> [[TMP2]]
+// CHECK: ret <1 x i64> [[VQADD_V2_I]]
uint64x1_t test_vqadd_u64(uint64x1_t a, uint64x1_t b) {
return vqadd_u64(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vqaddq_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vqaddq_s8(
// CHECK: [[VQADDQ_V_I:%.*]] = call <16 x i8> @llvm.arm.neon.vqadds.v16i8(<16 x i8> %a, <16 x i8> %b) #4
// CHECK: ret <16 x i8> [[VQADDQ_V_I]]
int8x16_t test_vqaddq_s8(int8x16_t a, int8x16_t b) {
return vqaddq_s8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vqaddq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqaddq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VQADDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VQADDQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VQADDQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vqadds.v8i16(<8 x i16> [[VQADDQ_V_I]], <8 x i16> [[VQADDQ_V1_I]]) #4
+// CHECK: [[VQADDQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vqadds.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: [[VQADDQ_V3_I:%.*]] = bitcast <8 x i16> [[VQADDQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQADDQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VQADDQ_V2_I]]
int16x8_t test_vqaddq_s16(int16x8_t a, int16x8_t b) {
return vqaddq_s16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vqaddq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqaddq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VQADDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQADDQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VQADDQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqadds.v4i32(<4 x i32> [[VQADDQ_V_I]], <4 x i32> [[VQADDQ_V1_I]]) #4
+// CHECK: [[VQADDQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqadds.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VQADDQ_V3_I:%.*]] = bitcast <4 x i32> [[VQADDQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQADDQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VQADDQ_V2_I]]
int32x4_t test_vqaddq_s32(int32x4_t a, int32x4_t b) {
return vqaddq_s32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vqaddq_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vqaddq_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[VQADDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQADDQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VQADDQ_V2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vqadds.v2i64(<2 x i64> [[VQADDQ_V_I]], <2 x i64> [[VQADDQ_V1_I]]) #4
+// CHECK: [[VQADDQ_V2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vqadds.v2i64(<2 x i64> %a, <2 x i64> %b) #4
// CHECK: [[VQADDQ_V3_I:%.*]] = bitcast <2 x i64> [[VQADDQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQADDQ_V3_I]] to <2 x i64>
-// CHECK: ret <2 x i64> [[TMP2]]
+// CHECK: ret <2 x i64> [[VQADDQ_V2_I]]
int64x2_t test_vqaddq_s64(int64x2_t a, int64x2_t b) {
return vqaddq_s64(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vqaddq_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vqaddq_u8(
// CHECK: [[VQADDQ_V_I:%.*]] = call <16 x i8> @llvm.arm.neon.vqaddu.v16i8(<16 x i8> %a, <16 x i8> %b) #4
// CHECK: ret <16 x i8> [[VQADDQ_V_I]]
uint8x16_t test_vqaddq_u8(uint8x16_t a, uint8x16_t b) {
return vqaddq_u8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vqaddq_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqaddq_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VQADDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VQADDQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VQADDQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vqaddu.v8i16(<8 x i16> [[VQADDQ_V_I]], <8 x i16> [[VQADDQ_V1_I]]) #4
+// CHECK: [[VQADDQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vqaddu.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: [[VQADDQ_V3_I:%.*]] = bitcast <8 x i16> [[VQADDQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQADDQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VQADDQ_V2_I]]
uint16x8_t test_vqaddq_u16(uint16x8_t a, uint16x8_t b) {
return vqaddq_u16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vqaddq_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqaddq_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VQADDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQADDQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VQADDQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqaddu.v4i32(<4 x i32> [[VQADDQ_V_I]], <4 x i32> [[VQADDQ_V1_I]]) #4
+// CHECK: [[VQADDQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqaddu.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VQADDQ_V3_I:%.*]] = bitcast <4 x i32> [[VQADDQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQADDQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VQADDQ_V2_I]]
uint32x4_t test_vqaddq_u32(uint32x4_t a, uint32x4_t b) {
return vqaddq_u32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vqaddq_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vqaddq_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[VQADDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQADDQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VQADDQ_V2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vqaddu.v2i64(<2 x i64> [[VQADDQ_V_I]], <2 x i64> [[VQADDQ_V1_I]]) #4
+// CHECK: [[VQADDQ_V2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vqaddu.v2i64(<2 x i64> %a, <2 x i64> %b) #4
// CHECK: [[VQADDQ_V3_I:%.*]] = bitcast <2 x i64> [[VQADDQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQADDQ_V3_I]] to <2 x i64>
-// CHECK: ret <2 x i64> [[TMP2]]
+// CHECK: ret <2 x i64> [[VQADDQ_V2_I]]
uint64x2_t test_vqaddq_u64(uint64x2_t a, uint64x2_t b) {
return vqaddq_u64(a, b);
}
-
-// CHECK-LABEL: define <4 x i32> @test_vqdmlal_s16(<4 x i32> %a, <4 x i16> %b, <4 x i16> %c) #0 {
+// CHECK-LABEL: @test_vqdmlal_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %c to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMLAL1_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VQDMLAL2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqdmull.v4i32(<4 x i16> [[VQDMLAL_I]], <4 x i16> [[VQDMLAL1_I]]) #4
-// CHECK: [[VQDMLAL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQDMLAL_V3_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqadds.v4i32(<4 x i32> [[VQDMLAL_V_I]], <4 x i32> [[VQDMLAL2_I]]) #4
+// CHECK: [[VQDMLAL2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqdmull.v4i32(<4 x i16> %b, <4 x i16> %c) #4
+// CHECK: [[VQDMLAL_V3_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqadds.v4i32(<4 x i32> %a, <4 x i32> [[VQDMLAL2_I]]) #4
// CHECK: ret <4 x i32> [[VQDMLAL_V3_I]]
int32x4_t test_vqdmlal_s16(int32x4_t a, int16x4_t b, int16x4_t c) {
return vqdmlal_s16(a, b, c);
}
-// CHECK-LABEL: define <2 x i64> @test_vqdmlal_s32(<2 x i64> %a, <2 x i32> %b, <2 x i32> %c) #0 {
+// CHECK-LABEL: @test_vqdmlal_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> %c to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMLAL1_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VQDMLAL2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vqdmull.v2i64(<2 x i32> [[VQDMLAL_I]], <2 x i32> [[VQDMLAL1_I]]) #4
-// CHECK: [[VQDMLAL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQDMLAL_V3_I:%.*]] = call <2 x i64> @llvm.arm.neon.vqadds.v2i64(<2 x i64> [[VQDMLAL_V_I]], <2 x i64> [[VQDMLAL2_I]]) #4
+// CHECK: [[VQDMLAL2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vqdmull.v2i64(<2 x i32> %b, <2 x i32> %c) #4
+// CHECK: [[VQDMLAL_V3_I:%.*]] = call <2 x i64> @llvm.arm.neon.vqadds.v2i64(<2 x i64> %a, <2 x i64> [[VQDMLAL2_I]]) #4
// CHECK: ret <2 x i64> [[VQDMLAL_V3_I]]
int64x2_t test_vqdmlal_s32(int64x2_t a, int32x2_t b, int32x2_t c) {
return vqdmlal_s32(a, b, c);
}
-
-// CHECK-LABEL: define <4 x i32> @test_vqdmlal_lane_s16(<4 x i32> %a, <4 x i16> %b, <4 x i16> %c) #0 {
+// CHECK-LABEL: @test_vqdmlal_lane_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %c, <4 x i16> %c, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMLAL1_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VQDMLAL2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqdmull.v4i32(<4 x i16> [[VQDMLAL_I]], <4 x i16> [[VQDMLAL1_I]]) #4
-// CHECK: [[VQDMLAL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQDMLAL_V3_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqadds.v4i32(<4 x i32> [[VQDMLAL_V_I]], <4 x i32> [[VQDMLAL2_I]]) #4
+// CHECK: [[VQDMLAL2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqdmull.v4i32(<4 x i16> %b, <4 x i16> [[SHUFFLE]]) #4
+// CHECK: [[VQDMLAL_V3_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqadds.v4i32(<4 x i32> %a, <4 x i32> [[VQDMLAL2_I]]) #4
// CHECK: ret <4 x i32> [[VQDMLAL_V3_I]]
int32x4_t test_vqdmlal_lane_s16(int32x4_t a, int16x4_t b, int16x4_t c) {
return vqdmlal_lane_s16(a, b, c, 3);
}
-// CHECK-LABEL: define <2 x i64> @test_vqdmlal_lane_s32(<2 x i64> %a, <2 x i32> %b, <2 x i32> %c) #0 {
+// CHECK-LABEL: @test_vqdmlal_lane_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %c, <2 x i32> %c, <2 x i32> <i32 1, i32 1>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMLAL1_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VQDMLAL2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vqdmull.v2i64(<2 x i32> [[VQDMLAL_I]], <2 x i32> [[VQDMLAL1_I]]) #4
-// CHECK: [[VQDMLAL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQDMLAL_V3_I:%.*]] = call <2 x i64> @llvm.arm.neon.vqadds.v2i64(<2 x i64> [[VQDMLAL_V_I]], <2 x i64> [[VQDMLAL2_I]]) #4
+// CHECK: [[VQDMLAL2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vqdmull.v2i64(<2 x i32> %b, <2 x i32> [[SHUFFLE]]) #4
+// CHECK: [[VQDMLAL_V3_I:%.*]] = call <2 x i64> @llvm.arm.neon.vqadds.v2i64(<2 x i64> %a, <2 x i64> [[VQDMLAL2_I]]) #4
// CHECK: ret <2 x i64> [[VQDMLAL_V3_I]]
int64x2_t test_vqdmlal_lane_s32(int64x2_t a, int32x2_t b, int32x2_t c) {
return vqdmlal_lane_s32(a, b, c, 1);
}
-
-// CHECK-LABEL: define <4 x i32> @test_vqdmlal_n_s16(<4 x i32> %a, <4 x i16> %b, i16 signext %c) #0 {
+// CHECK-LABEL: @test_vqdmlal_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i16> undef, i16 %c, i32 0
@@ -11874,94 +10080,73 @@ int64x2_t test_vqdmlal_lane_s32(int64x2_t a, int32x2_t b, int32x2_t c) {
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i16> [[VECINIT1_I]], i16 %c, i32 2
// CHECK: [[VECINIT3_I:%.*]] = insertelement <4 x i16> [[VECINIT2_I]], i16 %c, i32 3
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> [[VECINIT3_I]] to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMLAL4_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VQDMLAL5_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqdmull.v4i32(<4 x i16> [[VQDMLAL_I]], <4 x i16> [[VQDMLAL4_I]]) #4
-// CHECK: [[VQDMLAL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQDMLAL_V6_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqadds.v4i32(<4 x i32> [[VQDMLAL_V_I]], <4 x i32> [[VQDMLAL5_I]]) #4
+// CHECK: [[VQDMLAL5_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqdmull.v4i32(<4 x i16> %b, <4 x i16> [[VECINIT3_I]]) #4
+// CHECK: [[VQDMLAL_V6_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqadds.v4i32(<4 x i32> %a, <4 x i32> [[VQDMLAL5_I]]) #4
// CHECK: ret <4 x i32> [[VQDMLAL_V6_I]]
int32x4_t test_vqdmlal_n_s16(int32x4_t a, int16x4_t b, int16_t c) {
return vqdmlal_n_s16(a, b, c);
}
-// CHECK-LABEL: define <2 x i64> @test_vqdmlal_n_s32(<2 x i64> %a, <2 x i32> %b, i32 %c) #0 {
+// CHECK-LABEL: @test_vqdmlal_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x i32> undef, i32 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x i32> [[VECINIT_I]], i32 %c, i32 1
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> [[VECINIT1_I]] to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMLAL2_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VQDMLAL3_I:%.*]] = call <2 x i64> @llvm.arm.neon.vqdmull.v2i64(<2 x i32> [[VQDMLAL_I]], <2 x i32> [[VQDMLAL2_I]]) #4
-// CHECK: [[VQDMLAL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQDMLAL_V4_I:%.*]] = call <2 x i64> @llvm.arm.neon.vqadds.v2i64(<2 x i64> [[VQDMLAL_V_I]], <2 x i64> [[VQDMLAL3_I]]) #4
+// CHECK: [[VQDMLAL3_I:%.*]] = call <2 x i64> @llvm.arm.neon.vqdmull.v2i64(<2 x i32> %b, <2 x i32> [[VECINIT1_I]]) #4
+// CHECK: [[VQDMLAL_V4_I:%.*]] = call <2 x i64> @llvm.arm.neon.vqadds.v2i64(<2 x i64> %a, <2 x i64> [[VQDMLAL3_I]]) #4
// CHECK: ret <2 x i64> [[VQDMLAL_V4_I]]
int64x2_t test_vqdmlal_n_s32(int64x2_t a, int32x2_t b, int32_t c) {
return vqdmlal_n_s32(a, b, c);
}
-
-// CHECK-LABEL: define <4 x i32> @test_vqdmlsl_s16(<4 x i32> %a, <4 x i16> %b, <4 x i16> %c) #0 {
+// CHECK-LABEL: @test_vqdmlsl_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %c to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMLAL1_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VQDMLAL2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqdmull.v4i32(<4 x i16> [[VQDMLAL_I]], <4 x i16> [[VQDMLAL1_I]]) #4
-// CHECK: [[VQDMLSL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQDMLSL_V3_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqsubs.v4i32(<4 x i32> [[VQDMLSL_V_I]], <4 x i32> [[VQDMLAL2_I]]) #4
+// CHECK: [[VQDMLAL2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqdmull.v4i32(<4 x i16> %b, <4 x i16> %c) #4
+// CHECK: [[VQDMLSL_V3_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqsubs.v4i32(<4 x i32> %a, <4 x i32> [[VQDMLAL2_I]]) #4
// CHECK: ret <4 x i32> [[VQDMLSL_V3_I]]
int32x4_t test_vqdmlsl_s16(int32x4_t a, int16x4_t b, int16x4_t c) {
return vqdmlsl_s16(a, b, c);
}
-// CHECK-LABEL: define <2 x i64> @test_vqdmlsl_s32(<2 x i64> %a, <2 x i32> %b, <2 x i32> %c) #0 {
+// CHECK-LABEL: @test_vqdmlsl_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> %c to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMLAL1_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VQDMLAL2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vqdmull.v2i64(<2 x i32> [[VQDMLAL_I]], <2 x i32> [[VQDMLAL1_I]]) #4
-// CHECK: [[VQDMLSL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQDMLSL_V3_I:%.*]] = call <2 x i64> @llvm.arm.neon.vqsubs.v2i64(<2 x i64> [[VQDMLSL_V_I]], <2 x i64> [[VQDMLAL2_I]]) #4
+// CHECK: [[VQDMLAL2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vqdmull.v2i64(<2 x i32> %b, <2 x i32> %c) #4
+// CHECK: [[VQDMLSL_V3_I:%.*]] = call <2 x i64> @llvm.arm.neon.vqsubs.v2i64(<2 x i64> %a, <2 x i64> [[VQDMLAL2_I]]) #4
// CHECK: ret <2 x i64> [[VQDMLSL_V3_I]]
int64x2_t test_vqdmlsl_s32(int64x2_t a, int32x2_t b, int32x2_t c) {
return vqdmlsl_s32(a, b, c);
}
-
-// CHECK-LABEL: define <4 x i32> @test_vqdmlsl_lane_s16(<4 x i32> %a, <4 x i16> %b, <4 x i16> %c) #0 {
+// CHECK-LABEL: @test_vqdmlsl_lane_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %c, <4 x i16> %c, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMLAL1_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VQDMLAL2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqdmull.v4i32(<4 x i16> [[VQDMLAL_I]], <4 x i16> [[VQDMLAL1_I]]) #4
-// CHECK: [[VQDMLSL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQDMLSL_V3_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqsubs.v4i32(<4 x i32> [[VQDMLSL_V_I]], <4 x i32> [[VQDMLAL2_I]]) #4
+// CHECK: [[VQDMLAL2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqdmull.v4i32(<4 x i16> %b, <4 x i16> [[SHUFFLE]]) #4
+// CHECK: [[VQDMLSL_V3_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqsubs.v4i32(<4 x i32> %a, <4 x i32> [[VQDMLAL2_I]]) #4
// CHECK: ret <4 x i32> [[VQDMLSL_V3_I]]
int32x4_t test_vqdmlsl_lane_s16(int32x4_t a, int16x4_t b, int16x4_t c) {
return vqdmlsl_lane_s16(a, b, c, 3);
}
-// CHECK-LABEL: define <2 x i64> @test_vqdmlsl_lane_s32(<2 x i64> %a, <2 x i32> %b, <2 x i32> %c) #0 {
+// CHECK-LABEL: @test_vqdmlsl_lane_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %c, <2 x i32> %c, <2 x i32> <i32 1, i32 1>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMLAL1_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VQDMLAL2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vqdmull.v2i64(<2 x i32> [[VQDMLAL_I]], <2 x i32> [[VQDMLAL1_I]]) #4
-// CHECK: [[VQDMLSL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQDMLSL_V3_I:%.*]] = call <2 x i64> @llvm.arm.neon.vqsubs.v2i64(<2 x i64> [[VQDMLSL_V_I]], <2 x i64> [[VQDMLAL2_I]]) #4
+// CHECK: [[VQDMLAL2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vqdmull.v2i64(<2 x i32> %b, <2 x i32> [[SHUFFLE]]) #4
+// CHECK: [[VQDMLSL_V3_I:%.*]] = call <2 x i64> @llvm.arm.neon.vqsubs.v2i64(<2 x i64> %a, <2 x i64> [[VQDMLAL2_I]]) #4
// CHECK: ret <2 x i64> [[VQDMLSL_V3_I]]
int64x2_t test_vqdmlsl_lane_s32(int64x2_t a, int32x2_t b, int32x2_t c) {
return vqdmlsl_lane_s32(a, b, c, 1);
}
-
-// CHECK-LABEL: define <4 x i32> @test_vqdmlsl_n_s16(<4 x i32> %a, <4 x i16> %b, i16 signext %c) #0 {
+// CHECK-LABEL: @test_vqdmlsl_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i16> undef, i16 %c, i32 0
@@ -11969,176 +10154,137 @@ int64x2_t test_vqdmlsl_lane_s32(int64x2_t a, int32x2_t b, int32x2_t c) {
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i16> [[VECINIT1_I]], i16 %c, i32 2
// CHECK: [[VECINIT3_I:%.*]] = insertelement <4 x i16> [[VECINIT2_I]], i16 %c, i32 3
// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> [[VECINIT3_I]] to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMLAL4_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VQDMLAL5_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqdmull.v4i32(<4 x i16> [[VQDMLAL_I]], <4 x i16> [[VQDMLAL4_I]]) #4
-// CHECK: [[VQDMLSL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQDMLSL_V6_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqsubs.v4i32(<4 x i32> [[VQDMLSL_V_I]], <4 x i32> [[VQDMLAL5_I]]) #4
+// CHECK: [[VQDMLAL5_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqdmull.v4i32(<4 x i16> %b, <4 x i16> [[VECINIT3_I]]) #4
+// CHECK: [[VQDMLSL_V6_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqsubs.v4i32(<4 x i32> %a, <4 x i32> [[VQDMLAL5_I]]) #4
// CHECK: ret <4 x i32> [[VQDMLSL_V6_I]]
int32x4_t test_vqdmlsl_n_s16(int32x4_t a, int16x4_t b, int16_t c) {
return vqdmlsl_n_s16(a, b, c);
}
-// CHECK-LABEL: define <2 x i64> @test_vqdmlsl_n_s32(<2 x i64> %a, <2 x i32> %b, i32 %c) #0 {
+// CHECK-LABEL: @test_vqdmlsl_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x i32> undef, i32 %c, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x i32> [[VECINIT_I]], i32 %c, i32 1
// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> [[VECINIT1_I]] to <8 x i8>
-// CHECK: [[VQDMLAL_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMLAL2_I:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VQDMLAL3_I:%.*]] = call <2 x i64> @llvm.arm.neon.vqdmull.v2i64(<2 x i32> [[VQDMLAL_I]], <2 x i32> [[VQDMLAL2_I]]) #4
-// CHECK: [[VQDMLSL_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQDMLSL_V4_I:%.*]] = call <2 x i64> @llvm.arm.neon.vqsubs.v2i64(<2 x i64> [[VQDMLSL_V_I]], <2 x i64> [[VQDMLAL3_I]]) #4
+// CHECK: [[VQDMLAL3_I:%.*]] = call <2 x i64> @llvm.arm.neon.vqdmull.v2i64(<2 x i32> %b, <2 x i32> [[VECINIT1_I]]) #4
+// CHECK: [[VQDMLSL_V4_I:%.*]] = call <2 x i64> @llvm.arm.neon.vqsubs.v2i64(<2 x i64> %a, <2 x i64> [[VQDMLAL3_I]]) #4
// CHECK: ret <2 x i64> [[VQDMLSL_V4_I]]
int64x2_t test_vqdmlsl_n_s32(int64x2_t a, int32x2_t b, int32_t c) {
return vqdmlsl_n_s32(a, b, c);
}
-
-// CHECK-LABEL: define <4 x i16> @test_vqdmulh_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqdmulh_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VQDMULH_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQDMULH_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMULH_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vqdmulh.v4i16(<4 x i16> [[VQDMULH_V_I]], <4 x i16> [[VQDMULH_V1_I]]) #4
+// CHECK: [[VQDMULH_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vqdmulh.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VQDMULH_V3_I:%.*]] = bitcast <4 x i16> [[VQDMULH_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQDMULH_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VQDMULH_V2_I]]
int16x4_t test_vqdmulh_s16(int16x4_t a, int16x4_t b) {
return vqdmulh_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vqdmulh_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqdmulh_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VQDMULH_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQDMULH_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMULH_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vqdmulh.v2i32(<2 x i32> [[VQDMULH_V_I]], <2 x i32> [[VQDMULH_V1_I]]) #4
+// CHECK: [[VQDMULH_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vqdmulh.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VQDMULH_V3_I:%.*]] = bitcast <2 x i32> [[VQDMULH_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQDMULH_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VQDMULH_V2_I]]
int32x2_t test_vqdmulh_s32(int32x2_t a, int32x2_t b) {
return vqdmulh_s32(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vqdmulhq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqdmulhq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VQDMULHQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VQDMULHQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VQDMULHQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vqdmulh.v8i16(<8 x i16> [[VQDMULHQ_V_I]], <8 x i16> [[VQDMULHQ_V1_I]]) #4
+// CHECK: [[VQDMULHQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vqdmulh.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: [[VQDMULHQ_V3_I:%.*]] = bitcast <8 x i16> [[VQDMULHQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQDMULHQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VQDMULHQ_V2_I]]
int16x8_t test_vqdmulhq_s16(int16x8_t a, int16x8_t b) {
return vqdmulhq_s16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vqdmulhq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqdmulhq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VQDMULHQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQDMULHQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VQDMULHQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqdmulh.v4i32(<4 x i32> [[VQDMULHQ_V_I]], <4 x i32> [[VQDMULHQ_V1_I]]) #4
+// CHECK: [[VQDMULHQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqdmulh.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VQDMULHQ_V3_I:%.*]] = bitcast <4 x i32> [[VQDMULHQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQDMULHQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VQDMULHQ_V2_I]]
int32x4_t test_vqdmulhq_s32(int32x4_t a, int32x4_t b) {
return vqdmulhq_s32(a, b);
}
-
-// CHECK-LABEL: define <4 x i16> @test_vqdmulh_lane_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqdmulh_lane_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %b, <4 x i16> %b, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMULH_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQDMULH_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMULH_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vqdmulh.v4i16(<4 x i16> [[VQDMULH_V_I]], <4 x i16> [[VQDMULH_V1_I]]) #4
+// CHECK: [[VQDMULH_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vqdmulh.v4i16(<4 x i16> %a, <4 x i16> [[SHUFFLE]]) #4
// CHECK: [[VQDMULH_V3_I:%.*]] = bitcast <4 x i16> [[VQDMULH_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQDMULH_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VQDMULH_V2_I]]
int16x4_t test_vqdmulh_lane_s16(int16x4_t a, int16x4_t b) {
return vqdmulh_lane_s16(a, b, 3);
}
-// CHECK-LABEL: define <2 x i32> @test_vqdmulh_lane_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqdmulh_lane_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %b, <2 x i32> %b, <2 x i32> <i32 1, i32 1>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMULH_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQDMULH_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMULH_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vqdmulh.v2i32(<2 x i32> [[VQDMULH_V_I]], <2 x i32> [[VQDMULH_V1_I]]) #4
+// CHECK: [[VQDMULH_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vqdmulh.v2i32(<2 x i32> %a, <2 x i32> [[SHUFFLE]]) #4
// CHECK: [[VQDMULH_V3_I:%.*]] = bitcast <2 x i32> [[VQDMULH_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQDMULH_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VQDMULH_V2_I]]
int32x2_t test_vqdmulh_lane_s32(int32x2_t a, int32x2_t b) {
return vqdmulh_lane_s32(a, b, 1);
}
-// CHECK-LABEL: define <8 x i16> @test_vqdmulhq_lane_s16(<8 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqdmulhq_lane_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %b, <4 x i16> %b, <8 x i32> <i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> [[SHUFFLE]] to <16 x i8>
-// CHECK: [[VQDMULHQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VQDMULHQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VQDMULHQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vqdmulh.v8i16(<8 x i16> [[VQDMULHQ_V_I]], <8 x i16> [[VQDMULHQ_V1_I]]) #4
+// CHECK: [[VQDMULHQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vqdmulh.v8i16(<8 x i16> %a, <8 x i16> [[SHUFFLE]]) #4
// CHECK: [[VQDMULHQ_V3_I:%.*]] = bitcast <8 x i16> [[VQDMULHQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQDMULHQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VQDMULHQ_V2_I]]
int16x8_t test_vqdmulhq_lane_s16(int16x8_t a, int16x4_t b) {
return vqdmulhq_lane_s16(a, b, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vqdmulhq_lane_s32(<4 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqdmulhq_lane_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %b, <2 x i32> %b, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> [[SHUFFLE]] to <16 x i8>
-// CHECK: [[VQDMULHQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQDMULHQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VQDMULHQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqdmulh.v4i32(<4 x i32> [[VQDMULHQ_V_I]], <4 x i32> [[VQDMULHQ_V1_I]]) #4
+// CHECK: [[VQDMULHQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqdmulh.v4i32(<4 x i32> %a, <4 x i32> [[SHUFFLE]]) #4
// CHECK: [[VQDMULHQ_V3_I:%.*]] = bitcast <4 x i32> [[VQDMULHQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQDMULHQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VQDMULHQ_V2_I]]
int32x4_t test_vqdmulhq_lane_s32(int32x4_t a, int32x2_t b) {
return vqdmulhq_lane_s32(a, b, 1);
}
-
-// CHECK-LABEL: define <4 x i16> @test_vqdmulh_n_s16(<4 x i16> %a, i16 signext %b) #0 {
+// CHECK-LABEL: @test_vqdmulh_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i16> undef, i16 %b, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i16> [[VECINIT_I]], i16 %b, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i16> [[VECINIT1_I]], i16 %b, i32 2
// CHECK: [[VECINIT3_I:%.*]] = insertelement <4 x i16> [[VECINIT2_I]], i16 %b, i32 3
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[VECINIT3_I]] to <8 x i8>
-// CHECK: [[VQDMULH_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQDMULH_V4_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMULH_V5_I:%.*]] = call <4 x i16> @llvm.arm.neon.vqdmulh.v4i16(<4 x i16> [[VQDMULH_V_I]], <4 x i16> [[VQDMULH_V4_I]]) #4
+// CHECK: [[VQDMULH_V5_I:%.*]] = call <4 x i16> @llvm.arm.neon.vqdmulh.v4i16(<4 x i16> %a, <4 x i16> [[VECINIT3_I]]) #4
// CHECK: [[VQDMULH_V6_I:%.*]] = bitcast <4 x i16> [[VQDMULH_V5_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQDMULH_V6_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VQDMULH_V5_I]]
int16x4_t test_vqdmulh_n_s16(int16x4_t a, int16_t b) {
return vqdmulh_n_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vqdmulh_n_s32(<2 x i32> %a, i32 %b) #0 {
+// CHECK-LABEL: @test_vqdmulh_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x i32> undef, i32 %b, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x i32> [[VECINIT_I]], i32 %b, i32 1
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[VECINIT1_I]] to <8 x i8>
-// CHECK: [[VQDMULH_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQDMULH_V2_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMULH_V3_I:%.*]] = call <2 x i32> @llvm.arm.neon.vqdmulh.v2i32(<2 x i32> [[VQDMULH_V_I]], <2 x i32> [[VQDMULH_V2_I]]) #4
+// CHECK: [[VQDMULH_V3_I:%.*]] = call <2 x i32> @llvm.arm.neon.vqdmulh.v2i32(<2 x i32> %a, <2 x i32> [[VECINIT1_I]]) #4
// CHECK: [[VQDMULH_V4_I:%.*]] = bitcast <2 x i32> [[VQDMULH_V3_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQDMULH_V4_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VQDMULH_V3_I]]
int32x2_t test_vqdmulh_n_s32(int32x2_t a, int32_t b) {
return vqdmulh_n_s32(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vqdmulhq_n_s16(<8 x i16> %a, i16 signext %b) #0 {
+// CHECK-LABEL: @test_vqdmulhq_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[VECINIT_I:%.*]] = insertelement <8 x i16> undef, i16 %b, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <8 x i16> [[VECINIT_I]], i16 %b, i32 1
@@ -12149,420 +10295,334 @@ int32x2_t test_vqdmulh_n_s32(int32x2_t a, int32_t b) {
// CHECK: [[VECINIT6_I:%.*]] = insertelement <8 x i16> [[VECINIT5_I]], i16 %b, i32 6
// CHECK: [[VECINIT7_I:%.*]] = insertelement <8 x i16> [[VECINIT6_I]], i16 %b, i32 7
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> [[VECINIT7_I]] to <16 x i8>
-// CHECK: [[VQDMULHQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VQDMULHQ_V8_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VQDMULHQ_V9_I:%.*]] = call <8 x i16> @llvm.arm.neon.vqdmulh.v8i16(<8 x i16> [[VQDMULHQ_V_I]], <8 x i16> [[VQDMULHQ_V8_I]]) #4
+// CHECK: [[VQDMULHQ_V9_I:%.*]] = call <8 x i16> @llvm.arm.neon.vqdmulh.v8i16(<8 x i16> %a, <8 x i16> [[VECINIT7_I]]) #4
// CHECK: [[VQDMULHQ_V10_I:%.*]] = bitcast <8 x i16> [[VQDMULHQ_V9_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQDMULHQ_V10_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VQDMULHQ_V9_I]]
int16x8_t test_vqdmulhq_n_s16(int16x8_t a, int16_t b) {
return vqdmulhq_n_s16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vqdmulhq_n_s32(<4 x i32> %a, i32 %b) #0 {
+// CHECK-LABEL: @test_vqdmulhq_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i32> undef, i32 %b, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i32> [[VECINIT_I]], i32 %b, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i32> [[VECINIT1_I]], i32 %b, i32 2
// CHECK: [[VECINIT3_I:%.*]] = insertelement <4 x i32> [[VECINIT2_I]], i32 %b, i32 3
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> [[VECINIT3_I]] to <16 x i8>
-// CHECK: [[VQDMULHQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQDMULHQ_V4_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VQDMULHQ_V5_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqdmulh.v4i32(<4 x i32> [[VQDMULHQ_V_I]], <4 x i32> [[VQDMULHQ_V4_I]]) #4
+// CHECK: [[VQDMULHQ_V5_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqdmulh.v4i32(<4 x i32> %a, <4 x i32> [[VECINIT3_I]]) #4
// CHECK: [[VQDMULHQ_V6_I:%.*]] = bitcast <4 x i32> [[VQDMULHQ_V5_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQDMULHQ_V6_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VQDMULHQ_V5_I]]
int32x4_t test_vqdmulhq_n_s32(int32x4_t a, int32_t b) {
return vqdmulhq_n_s32(a, b);
}
-
-// CHECK-LABEL: define <4 x i32> @test_vqdmull_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqdmull_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VQDMULL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQDMULL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMULL_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqdmull.v4i32(<4 x i16> [[VQDMULL_V_I]], <4 x i16> [[VQDMULL_V1_I]]) #4
+// CHECK: [[VQDMULL_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqdmull.v4i32(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VQDMULL_V3_I:%.*]] = bitcast <4 x i32> [[VQDMULL_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQDMULL_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VQDMULL_V2_I]]
int32x4_t test_vqdmull_s16(int16x4_t a, int16x4_t b) {
return vqdmull_s16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vqdmull_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqdmull_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VQDMULL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQDMULL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMULL_V2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vqdmull.v2i64(<2 x i32> [[VQDMULL_V_I]], <2 x i32> [[VQDMULL_V1_I]]) #4
+// CHECK: [[VQDMULL_V2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vqdmull.v2i64(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VQDMULL_V3_I:%.*]] = bitcast <2 x i64> [[VQDMULL_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQDMULL_V3_I]] to <2 x i64>
-// CHECK: ret <2 x i64> [[TMP2]]
+// CHECK: ret <2 x i64> [[VQDMULL_V2_I]]
int64x2_t test_vqdmull_s32(int32x2_t a, int32x2_t b) {
return vqdmull_s32(a, b);
}
-
-// CHECK-LABEL: define <4 x i32> @test_vqdmull_lane_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqdmull_lane_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %b, <4 x i16> %b, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMULL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQDMULL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMULL_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqdmull.v4i32(<4 x i16> [[VQDMULL_V_I]], <4 x i16> [[VQDMULL_V1_I]]) #4
+// CHECK: [[VQDMULL_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqdmull.v4i32(<4 x i16> %a, <4 x i16> [[SHUFFLE]]) #4
// CHECK: [[VQDMULL_V3_I:%.*]] = bitcast <4 x i32> [[VQDMULL_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQDMULL_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VQDMULL_V2_I]]
int32x4_t test_vqdmull_lane_s16(int16x4_t a, int16x4_t b) {
return vqdmull_lane_s16(a, b, 3);
}
-// CHECK-LABEL: define <2 x i64> @test_vqdmull_lane_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqdmull_lane_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %b, <2 x i32> %b, <2 x i32> <i32 1, i32 1>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQDMULL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQDMULL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMULL_V2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vqdmull.v2i64(<2 x i32> [[VQDMULL_V_I]], <2 x i32> [[VQDMULL_V1_I]]) #4
+// CHECK: [[VQDMULL_V2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vqdmull.v2i64(<2 x i32> %a, <2 x i32> [[SHUFFLE]]) #4
// CHECK: [[VQDMULL_V3_I:%.*]] = bitcast <2 x i64> [[VQDMULL_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQDMULL_V3_I]] to <2 x i64>
-// CHECK: ret <2 x i64> [[TMP2]]
+// CHECK: ret <2 x i64> [[VQDMULL_V2_I]]
int64x2_t test_vqdmull_lane_s32(int32x2_t a, int32x2_t b) {
return vqdmull_lane_s32(a, b, 1);
}
-
-// CHECK-LABEL: define <4 x i32> @test_vqdmull_n_s16(<4 x i16> %a, i16 signext %b) #0 {
+// CHECK-LABEL: @test_vqdmull_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i16> undef, i16 %b, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i16> [[VECINIT_I]], i16 %b, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i16> [[VECINIT1_I]], i16 %b, i32 2
// CHECK: [[VECINIT3_I:%.*]] = insertelement <4 x i16> [[VECINIT2_I]], i16 %b, i32 3
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[VECINIT3_I]] to <8 x i8>
-// CHECK: [[VQDMULL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQDMULL_V4_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQDMULL_V5_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqdmull.v4i32(<4 x i16> [[VQDMULL_V_I]], <4 x i16> [[VQDMULL_V4_I]]) #4
+// CHECK: [[VQDMULL_V5_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqdmull.v4i32(<4 x i16> %a, <4 x i16> [[VECINIT3_I]]) #4
// CHECK: [[VQDMULL_V6_I:%.*]] = bitcast <4 x i32> [[VQDMULL_V5_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQDMULL_V6_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VQDMULL_V5_I]]
int32x4_t test_vqdmull_n_s16(int16x4_t a, int16_t b) {
return vqdmull_n_s16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vqdmull_n_s32(<2 x i32> %a, i32 %b) #0 {
+// CHECK-LABEL: @test_vqdmull_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x i32> undef, i32 %b, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x i32> [[VECINIT_I]], i32 %b, i32 1
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[VECINIT1_I]] to <8 x i8>
-// CHECK: [[VQDMULL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQDMULL_V2_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQDMULL_V3_I:%.*]] = call <2 x i64> @llvm.arm.neon.vqdmull.v2i64(<2 x i32> [[VQDMULL_V_I]], <2 x i32> [[VQDMULL_V2_I]]) #4
+// CHECK: [[VQDMULL_V3_I:%.*]] = call <2 x i64> @llvm.arm.neon.vqdmull.v2i64(<2 x i32> %a, <2 x i32> [[VECINIT1_I]]) #4
// CHECK: [[VQDMULL_V4_I:%.*]] = bitcast <2 x i64> [[VQDMULL_V3_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQDMULL_V4_I]] to <2 x i64>
-// CHECK: ret <2 x i64> [[TMP2]]
+// CHECK: ret <2 x i64> [[VQDMULL_V3_I]]
int64x2_t test_vqdmull_n_s32(int32x2_t a, int32_t b) {
return vqdmull_n_s32(a, b);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vqmovn_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vqmovn_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
-// CHECK: [[VQMOVN_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VQMOVN_V1_I:%.*]] = call <8 x i8> @llvm.arm.neon.vqmovns.v8i8(<8 x i16> [[VQMOVN_V_I]]) #4
+// CHECK: [[VQMOVN_V1_I:%.*]] = call <8 x i8> @llvm.arm.neon.vqmovns.v8i8(<8 x i16> %a) #4
// CHECK: ret <8 x i8> [[VQMOVN_V1_I]]
int8x8_t test_vqmovn_s16(int16x8_t a) {
return vqmovn_s16(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vqmovn_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vqmovn_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
-// CHECK: [[VQMOVN_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQMOVN_V1_I:%.*]] = call <4 x i16> @llvm.arm.neon.vqmovns.v4i16(<4 x i32> [[VQMOVN_V_I]]) #4
+// CHECK: [[VQMOVN_V1_I:%.*]] = call <4 x i16> @llvm.arm.neon.vqmovns.v4i16(<4 x i32> %a) #4
// CHECK: [[VQMOVN_V2_I:%.*]] = bitcast <4 x i16> [[VQMOVN_V1_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[VQMOVN_V2_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP1]]
+// CHECK: ret <4 x i16> [[VQMOVN_V1_I]]
int16x4_t test_vqmovn_s32(int32x4_t a) {
return vqmovn_s32(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vqmovn_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vqmovn_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
-// CHECK: [[VQMOVN_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQMOVN_V1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vqmovns.v2i32(<2 x i64> [[VQMOVN_V_I]]) #4
+// CHECK: [[VQMOVN_V1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vqmovns.v2i32(<2 x i64> %a) #4
// CHECK: [[VQMOVN_V2_I:%.*]] = bitcast <2 x i32> [[VQMOVN_V1_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[VQMOVN_V2_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP1]]
+// CHECK: ret <2 x i32> [[VQMOVN_V1_I]]
int32x2_t test_vqmovn_s64(int64x2_t a) {
return vqmovn_s64(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vqmovn_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vqmovn_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
-// CHECK: [[VQMOVN_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VQMOVN_V1_I:%.*]] = call <8 x i8> @llvm.arm.neon.vqmovnu.v8i8(<8 x i16> [[VQMOVN_V_I]]) #4
+// CHECK: [[VQMOVN_V1_I:%.*]] = call <8 x i8> @llvm.arm.neon.vqmovnu.v8i8(<8 x i16> %a) #4
// CHECK: ret <8 x i8> [[VQMOVN_V1_I]]
uint8x8_t test_vqmovn_u16(uint16x8_t a) {
return vqmovn_u16(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vqmovn_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vqmovn_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
-// CHECK: [[VQMOVN_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQMOVN_V1_I:%.*]] = call <4 x i16> @llvm.arm.neon.vqmovnu.v4i16(<4 x i32> [[VQMOVN_V_I]]) #4
+// CHECK: [[VQMOVN_V1_I:%.*]] = call <4 x i16> @llvm.arm.neon.vqmovnu.v4i16(<4 x i32> %a) #4
// CHECK: [[VQMOVN_V2_I:%.*]] = bitcast <4 x i16> [[VQMOVN_V1_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[VQMOVN_V2_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP1]]
+// CHECK: ret <4 x i16> [[VQMOVN_V1_I]]
uint16x4_t test_vqmovn_u32(uint32x4_t a) {
return vqmovn_u32(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vqmovn_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vqmovn_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
-// CHECK: [[VQMOVN_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQMOVN_V1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vqmovnu.v2i32(<2 x i64> [[VQMOVN_V_I]]) #4
+// CHECK: [[VQMOVN_V1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vqmovnu.v2i32(<2 x i64> %a) #4
// CHECK: [[VQMOVN_V2_I:%.*]] = bitcast <2 x i32> [[VQMOVN_V1_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[VQMOVN_V2_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP1]]
+// CHECK: ret <2 x i32> [[VQMOVN_V1_I]]
uint32x2_t test_vqmovn_u64(uint64x2_t a) {
return vqmovn_u64(a);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vqmovun_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vqmovun_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
-// CHECK: [[VQMOVUN_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VQMOVUN_V1_I:%.*]] = call <8 x i8> @llvm.arm.neon.vqmovnsu.v8i8(<8 x i16> [[VQMOVUN_V_I]]) #4
+// CHECK: [[VQMOVUN_V1_I:%.*]] = call <8 x i8> @llvm.arm.neon.vqmovnsu.v8i8(<8 x i16> %a) #4
// CHECK: ret <8 x i8> [[VQMOVUN_V1_I]]
uint8x8_t test_vqmovun_s16(int16x8_t a) {
return vqmovun_s16(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vqmovun_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vqmovun_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
-// CHECK: [[VQMOVUN_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQMOVUN_V1_I:%.*]] = call <4 x i16> @llvm.arm.neon.vqmovnsu.v4i16(<4 x i32> [[VQMOVUN_V_I]]) #4
+// CHECK: [[VQMOVUN_V1_I:%.*]] = call <4 x i16> @llvm.arm.neon.vqmovnsu.v4i16(<4 x i32> %a) #4
// CHECK: [[VQMOVUN_V2_I:%.*]] = bitcast <4 x i16> [[VQMOVUN_V1_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[VQMOVUN_V2_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP1]]
+// CHECK: ret <4 x i16> [[VQMOVUN_V1_I]]
uint16x4_t test_vqmovun_s32(int32x4_t a) {
return vqmovun_s32(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vqmovun_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vqmovun_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
-// CHECK: [[VQMOVUN_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQMOVUN_V1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vqmovnsu.v2i32(<2 x i64> [[VQMOVUN_V_I]]) #4
+// CHECK: [[VQMOVUN_V1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vqmovnsu.v2i32(<2 x i64> %a) #4
// CHECK: [[VQMOVUN_V2_I:%.*]] = bitcast <2 x i32> [[VQMOVUN_V1_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[VQMOVUN_V2_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP1]]
+// CHECK: ret <2 x i32> [[VQMOVUN_V1_I]]
uint32x2_t test_vqmovun_s64(int64x2_t a) {
return vqmovun_s64(a);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vqneg_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vqneg_s8(
// CHECK: [[VQNEG_V_I:%.*]] = call <8 x i8> @llvm.arm.neon.vqneg.v8i8(<8 x i8> %a) #4
// CHECK: ret <8 x i8> [[VQNEG_V_I]]
int8x8_t test_vqneg_s8(int8x8_t a) {
return vqneg_s8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vqneg_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vqneg_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
-// CHECK: [[VQNEG_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQNEG_V1_I:%.*]] = call <4 x i16> @llvm.arm.neon.vqneg.v4i16(<4 x i16> [[VQNEG_V_I]]) #4
+// CHECK: [[VQNEG_V1_I:%.*]] = call <4 x i16> @llvm.arm.neon.vqneg.v4i16(<4 x i16> %a) #4
// CHECK: [[VQNEG_V2_I:%.*]] = bitcast <4 x i16> [[VQNEG_V1_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[VQNEG_V2_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP1]]
+// CHECK: ret <4 x i16> [[VQNEG_V1_I]]
int16x4_t test_vqneg_s16(int16x4_t a) {
return vqneg_s16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vqneg_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vqneg_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[VQNEG_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQNEG_V1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vqneg.v2i32(<2 x i32> [[VQNEG_V_I]]) #4
+// CHECK: [[VQNEG_V1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vqneg.v2i32(<2 x i32> %a) #4
// CHECK: [[VQNEG_V2_I:%.*]] = bitcast <2 x i32> [[VQNEG_V1_I]] to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[VQNEG_V2_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP1]]
+// CHECK: ret <2 x i32> [[VQNEG_V1_I]]
int32x2_t test_vqneg_s32(int32x2_t a) {
return vqneg_s32(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vqnegq_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vqnegq_s8(
// CHECK: [[VQNEGQ_V_I:%.*]] = call <16 x i8> @llvm.arm.neon.vqneg.v16i8(<16 x i8> %a) #4
// CHECK: ret <16 x i8> [[VQNEGQ_V_I]]
int8x16_t test_vqnegq_s8(int8x16_t a) {
return vqnegq_s8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vqnegq_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vqnegq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
-// CHECK: [[VQNEGQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VQNEGQ_V1_I:%.*]] = call <8 x i16> @llvm.arm.neon.vqneg.v8i16(<8 x i16> [[VQNEGQ_V_I]]) #4
+// CHECK: [[VQNEGQ_V1_I:%.*]] = call <8 x i16> @llvm.arm.neon.vqneg.v8i16(<8 x i16> %a) #4
// CHECK: [[VQNEGQ_V2_I:%.*]] = bitcast <8 x i16> [[VQNEGQ_V1_I]] to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[VQNEGQ_V2_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP1]]
+// CHECK: ret <8 x i16> [[VQNEGQ_V1_I]]
int16x8_t test_vqnegq_s16(int16x8_t a) {
return vqnegq_s16(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vqnegq_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vqnegq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
-// CHECK: [[VQNEGQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQNEGQ_V1_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqneg.v4i32(<4 x i32> [[VQNEGQ_V_I]]) #4
+// CHECK: [[VQNEGQ_V1_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqneg.v4i32(<4 x i32> %a) #4
// CHECK: [[VQNEGQ_V2_I:%.*]] = bitcast <4 x i32> [[VQNEGQ_V1_I]] to <16 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[VQNEGQ_V2_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP1]]
+// CHECK: ret <4 x i32> [[VQNEGQ_V1_I]]
int32x4_t test_vqnegq_s32(int32x4_t a) {
return vqnegq_s32(a);
}
-
-// CHECK-LABEL: define <4 x i16> @test_vqrdmulh_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqrdmulh_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VQRDMULH_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQRDMULH_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQRDMULH_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vqrdmulh.v4i16(<4 x i16> [[VQRDMULH_V_I]], <4 x i16> [[VQRDMULH_V1_I]]) #4
+// CHECK: [[VQRDMULH_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vqrdmulh.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VQRDMULH_V3_I:%.*]] = bitcast <4 x i16> [[VQRDMULH_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQRDMULH_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VQRDMULH_V2_I]]
int16x4_t test_vqrdmulh_s16(int16x4_t a, int16x4_t b) {
return vqrdmulh_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vqrdmulh_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqrdmulh_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VQRDMULH_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQRDMULH_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQRDMULH_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vqrdmulh.v2i32(<2 x i32> [[VQRDMULH_V_I]], <2 x i32> [[VQRDMULH_V1_I]]) #4
+// CHECK: [[VQRDMULH_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vqrdmulh.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VQRDMULH_V3_I:%.*]] = bitcast <2 x i32> [[VQRDMULH_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQRDMULH_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VQRDMULH_V2_I]]
int32x2_t test_vqrdmulh_s32(int32x2_t a, int32x2_t b) {
return vqrdmulh_s32(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vqrdmulhq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqrdmulhq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VQRDMULHQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VQRDMULHQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VQRDMULHQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vqrdmulh.v8i16(<8 x i16> [[VQRDMULHQ_V_I]], <8 x i16> [[VQRDMULHQ_V1_I]]) #4
+// CHECK: [[VQRDMULHQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vqrdmulh.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: [[VQRDMULHQ_V3_I:%.*]] = bitcast <8 x i16> [[VQRDMULHQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQRDMULHQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VQRDMULHQ_V2_I]]
int16x8_t test_vqrdmulhq_s16(int16x8_t a, int16x8_t b) {
return vqrdmulhq_s16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vqrdmulhq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqrdmulhq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VQRDMULHQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQRDMULHQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VQRDMULHQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqrdmulh.v4i32(<4 x i32> [[VQRDMULHQ_V_I]], <4 x i32> [[VQRDMULHQ_V1_I]]) #4
+// CHECK: [[VQRDMULHQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqrdmulh.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VQRDMULHQ_V3_I:%.*]] = bitcast <4 x i32> [[VQRDMULHQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQRDMULHQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VQRDMULHQ_V2_I]]
int32x4_t test_vqrdmulhq_s32(int32x4_t a, int32x4_t b) {
return vqrdmulhq_s32(a, b);
}
-
-// CHECK-LABEL: define <4 x i16> @test_vqrdmulh_lane_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqrdmulh_lane_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %b, <4 x i16> %b, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQRDMULH_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQRDMULH_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQRDMULH_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vqrdmulh.v4i16(<4 x i16> [[VQRDMULH_V_I]], <4 x i16> [[VQRDMULH_V1_I]]) #4
+// CHECK: [[VQRDMULH_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vqrdmulh.v4i16(<4 x i16> %a, <4 x i16> [[SHUFFLE]]) #4
// CHECK: [[VQRDMULH_V3_I:%.*]] = bitcast <4 x i16> [[VQRDMULH_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQRDMULH_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VQRDMULH_V2_I]]
int16x4_t test_vqrdmulh_lane_s16(int16x4_t a, int16x4_t b) {
return vqrdmulh_lane_s16(a, b, 3);
}
-// CHECK-LABEL: define <2 x i32> @test_vqrdmulh_lane_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqrdmulh_lane_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %b, <2 x i32> %b, <2 x i32> <i32 1, i32 1>
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[SHUFFLE]] to <8 x i8>
-// CHECK: [[VQRDMULH_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQRDMULH_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQRDMULH_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vqrdmulh.v2i32(<2 x i32> [[VQRDMULH_V_I]], <2 x i32> [[VQRDMULH_V1_I]]) #4
+// CHECK: [[VQRDMULH_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vqrdmulh.v2i32(<2 x i32> %a, <2 x i32> [[SHUFFLE]]) #4
// CHECK: [[VQRDMULH_V3_I:%.*]] = bitcast <2 x i32> [[VQRDMULH_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQRDMULH_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VQRDMULH_V2_I]]
int32x2_t test_vqrdmulh_lane_s32(int32x2_t a, int32x2_t b) {
return vqrdmulh_lane_s32(a, b, 1);
}
-// CHECK-LABEL: define <8 x i16> @test_vqrdmulhq_lane_s16(<8 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqrdmulhq_lane_s16(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <4 x i16> %b, <4 x i16> %b, <8 x i32> <i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3>
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> [[SHUFFLE]] to <16 x i8>
-// CHECK: [[VQRDMULHQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VQRDMULHQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VQRDMULHQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vqrdmulh.v8i16(<8 x i16> [[VQRDMULHQ_V_I]], <8 x i16> [[VQRDMULHQ_V1_I]]) #4
+// CHECK: [[VQRDMULHQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vqrdmulh.v8i16(<8 x i16> %a, <8 x i16> [[SHUFFLE]]) #4
// CHECK: [[VQRDMULHQ_V3_I:%.*]] = bitcast <8 x i16> [[VQRDMULHQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQRDMULHQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VQRDMULHQ_V2_I]]
int16x8_t test_vqrdmulhq_lane_s16(int16x8_t a, int16x4_t b) {
return vqrdmulhq_lane_s16(a, b, 3);
}
-// CHECK-LABEL: define <4 x i32> @test_vqrdmulhq_lane_s32(<4 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqrdmulhq_lane_s32(
// CHECK: [[SHUFFLE:%.*]] = shufflevector <2 x i32> %b, <2 x i32> %b, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> [[SHUFFLE]] to <16 x i8>
-// CHECK: [[VQRDMULHQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQRDMULHQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VQRDMULHQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqrdmulh.v4i32(<4 x i32> [[VQRDMULHQ_V_I]], <4 x i32> [[VQRDMULHQ_V1_I]]) #4
+// CHECK: [[VQRDMULHQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqrdmulh.v4i32(<4 x i32> %a, <4 x i32> [[SHUFFLE]]) #4
// CHECK: [[VQRDMULHQ_V3_I:%.*]] = bitcast <4 x i32> [[VQRDMULHQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQRDMULHQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VQRDMULHQ_V2_I]]
int32x4_t test_vqrdmulhq_lane_s32(int32x4_t a, int32x2_t b) {
return vqrdmulhq_lane_s32(a, b, 1);
}
-
-// CHECK-LABEL: define <4 x i16> @test_vqrdmulh_n_s16(<4 x i16> %a, i16 signext %b) #0 {
+// CHECK-LABEL: @test_vqrdmulh_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i16> undef, i16 %b, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i16> [[VECINIT_I]], i16 %b, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i16> [[VECINIT1_I]], i16 %b, i32 2
// CHECK: [[VECINIT3_I:%.*]] = insertelement <4 x i16> [[VECINIT2_I]], i16 %b, i32 3
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> [[VECINIT3_I]] to <8 x i8>
-// CHECK: [[VQRDMULH_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQRDMULH_V4_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQRDMULH_V5_I:%.*]] = call <4 x i16> @llvm.arm.neon.vqrdmulh.v4i16(<4 x i16> [[VQRDMULH_V_I]], <4 x i16> [[VQRDMULH_V4_I]]) #4
+// CHECK: [[VQRDMULH_V5_I:%.*]] = call <4 x i16> @llvm.arm.neon.vqrdmulh.v4i16(<4 x i16> %a, <4 x i16> [[VECINIT3_I]]) #4
// CHECK: [[VQRDMULH_V6_I:%.*]] = bitcast <4 x i16> [[VQRDMULH_V5_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQRDMULH_V6_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VQRDMULH_V5_I]]
int16x4_t test_vqrdmulh_n_s16(int16x4_t a, int16_t b) {
return vqrdmulh_n_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vqrdmulh_n_s32(<2 x i32> %a, i32 %b) #0 {
+// CHECK-LABEL: @test_vqrdmulh_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[VECINIT_I:%.*]] = insertelement <2 x i32> undef, i32 %b, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <2 x i32> [[VECINIT_I]], i32 %b, i32 1
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> [[VECINIT1_I]] to <8 x i8>
-// CHECK: [[VQRDMULH_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQRDMULH_V2_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQRDMULH_V3_I:%.*]] = call <2 x i32> @llvm.arm.neon.vqrdmulh.v2i32(<2 x i32> [[VQRDMULH_V_I]], <2 x i32> [[VQRDMULH_V2_I]]) #4
+// CHECK: [[VQRDMULH_V3_I:%.*]] = call <2 x i32> @llvm.arm.neon.vqrdmulh.v2i32(<2 x i32> %a, <2 x i32> [[VECINIT1_I]]) #4
// CHECK: [[VQRDMULH_V4_I:%.*]] = bitcast <2 x i32> [[VQRDMULH_V3_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQRDMULH_V4_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VQRDMULH_V3_I]]
int32x2_t test_vqrdmulh_n_s32(int32x2_t a, int32_t b) {
return vqrdmulh_n_s32(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vqrdmulhq_n_s16(<8 x i16> %a, i16 signext %b) #0 {
+// CHECK-LABEL: @test_vqrdmulhq_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[VECINIT_I:%.*]] = insertelement <8 x i16> undef, i16 %b, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <8 x i16> [[VECINIT_I]], i16 %b, i32 1
@@ -12573,220 +10633,176 @@ int32x2_t test_vqrdmulh_n_s32(int32x2_t a, int32_t b) {
// CHECK: [[VECINIT6_I:%.*]] = insertelement <8 x i16> [[VECINIT5_I]], i16 %b, i32 6
// CHECK: [[VECINIT7_I:%.*]] = insertelement <8 x i16> [[VECINIT6_I]], i16 %b, i32 7
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> [[VECINIT7_I]] to <16 x i8>
-// CHECK: [[VQRDMULHQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VQRDMULHQ_V8_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VQRDMULHQ_V9_I:%.*]] = call <8 x i16> @llvm.arm.neon.vqrdmulh.v8i16(<8 x i16> [[VQRDMULHQ_V_I]], <8 x i16> [[VQRDMULHQ_V8_I]]) #4
+// CHECK: [[VQRDMULHQ_V9_I:%.*]] = call <8 x i16> @llvm.arm.neon.vqrdmulh.v8i16(<8 x i16> %a, <8 x i16> [[VECINIT7_I]]) #4
// CHECK: [[VQRDMULHQ_V10_I:%.*]] = bitcast <8 x i16> [[VQRDMULHQ_V9_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQRDMULHQ_V10_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VQRDMULHQ_V9_I]]
int16x8_t test_vqrdmulhq_n_s16(int16x8_t a, int16_t b) {
return vqrdmulhq_n_s16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vqrdmulhq_n_s32(<4 x i32> %a, i32 %b) #0 {
+// CHECK-LABEL: @test_vqrdmulhq_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[VECINIT_I:%.*]] = insertelement <4 x i32> undef, i32 %b, i32 0
// CHECK: [[VECINIT1_I:%.*]] = insertelement <4 x i32> [[VECINIT_I]], i32 %b, i32 1
// CHECK: [[VECINIT2_I:%.*]] = insertelement <4 x i32> [[VECINIT1_I]], i32 %b, i32 2
// CHECK: [[VECINIT3_I:%.*]] = insertelement <4 x i32> [[VECINIT2_I]], i32 %b, i32 3
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> [[VECINIT3_I]] to <16 x i8>
-// CHECK: [[VQRDMULHQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQRDMULHQ_V4_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VQRDMULHQ_V5_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqrdmulh.v4i32(<4 x i32> [[VQRDMULHQ_V_I]], <4 x i32> [[VQRDMULHQ_V4_I]]) #4
+// CHECK: [[VQRDMULHQ_V5_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqrdmulh.v4i32(<4 x i32> %a, <4 x i32> [[VECINIT3_I]]) #4
// CHECK: [[VQRDMULHQ_V6_I:%.*]] = bitcast <4 x i32> [[VQRDMULHQ_V5_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQRDMULHQ_V6_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VQRDMULHQ_V5_I]]
int32x4_t test_vqrdmulhq_n_s32(int32x4_t a, int32_t b) {
return vqrdmulhq_n_s32(a, b);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vqrshl_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vqrshl_s8(
// CHECK: [[VQRSHL_V_I:%.*]] = call <8 x i8> @llvm.arm.neon.vqrshifts.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VQRSHL_V_I]]
int8x8_t test_vqrshl_s8(int8x8_t a, int8x8_t b) {
return vqrshl_s8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vqrshl_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqrshl_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VQRSHL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQRSHL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQRSHL_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vqrshifts.v4i16(<4 x i16> [[VQRSHL_V_I]], <4 x i16> [[VQRSHL_V1_I]]) #4
+// CHECK: [[VQRSHL_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vqrshifts.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VQRSHL_V3_I:%.*]] = bitcast <4 x i16> [[VQRSHL_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQRSHL_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VQRSHL_V2_I]]
int16x4_t test_vqrshl_s16(int16x4_t a, int16x4_t b) {
return vqrshl_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vqrshl_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqrshl_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VQRSHL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQRSHL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQRSHL_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vqrshifts.v2i32(<2 x i32> [[VQRSHL_V_I]], <2 x i32> [[VQRSHL_V1_I]]) #4
+// CHECK: [[VQRSHL_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vqrshifts.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VQRSHL_V3_I:%.*]] = bitcast <2 x i32> [[VQRSHL_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQRSHL_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VQRSHL_V2_I]]
int32x2_t test_vqrshl_s32(int32x2_t a, int32x2_t b) {
return vqrshl_s32(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vqrshl_s64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vqrshl_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
-// CHECK: [[VQRSHL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
-// CHECK: [[VQRSHL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x i64>
-// CHECK: [[VQRSHL_V2_I:%.*]] = call <1 x i64> @llvm.arm.neon.vqrshifts.v1i64(<1 x i64> [[VQRSHL_V_I]], <1 x i64> [[VQRSHL_V1_I]]) #4
+// CHECK: [[VQRSHL_V2_I:%.*]] = call <1 x i64> @llvm.arm.neon.vqrshifts.v1i64(<1 x i64> %a, <1 x i64> %b) #4
// CHECK: [[VQRSHL_V3_I:%.*]] = bitcast <1 x i64> [[VQRSHL_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQRSHL_V3_I]] to <1 x i64>
-// CHECK: ret <1 x i64> [[TMP2]]
+// CHECK: ret <1 x i64> [[VQRSHL_V2_I]]
int64x1_t test_vqrshl_s64(int64x1_t a, int64x1_t b) {
return vqrshl_s64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vqrshl_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vqrshl_u8(
// CHECK: [[VQRSHL_V_I:%.*]] = call <8 x i8> @llvm.arm.neon.vqrshiftu.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VQRSHL_V_I]]
uint8x8_t test_vqrshl_u8(uint8x8_t a, int8x8_t b) {
return vqrshl_u8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vqrshl_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqrshl_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VQRSHL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQRSHL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQRSHL_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vqrshiftu.v4i16(<4 x i16> [[VQRSHL_V_I]], <4 x i16> [[VQRSHL_V1_I]]) #4
+// CHECK: [[VQRSHL_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vqrshiftu.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VQRSHL_V3_I:%.*]] = bitcast <4 x i16> [[VQRSHL_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQRSHL_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VQRSHL_V2_I]]
uint16x4_t test_vqrshl_u16(uint16x4_t a, int16x4_t b) {
return vqrshl_u16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vqrshl_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqrshl_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VQRSHL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQRSHL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQRSHL_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vqrshiftu.v2i32(<2 x i32> [[VQRSHL_V_I]], <2 x i32> [[VQRSHL_V1_I]]) #4
+// CHECK: [[VQRSHL_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vqrshiftu.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VQRSHL_V3_I:%.*]] = bitcast <2 x i32> [[VQRSHL_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQRSHL_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VQRSHL_V2_I]]
uint32x2_t test_vqrshl_u32(uint32x2_t a, int32x2_t b) {
return vqrshl_u32(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vqrshl_u64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vqrshl_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
-// CHECK: [[VQRSHL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
-// CHECK: [[VQRSHL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x i64>
-// CHECK: [[VQRSHL_V2_I:%.*]] = call <1 x i64> @llvm.arm.neon.vqrshiftu.v1i64(<1 x i64> [[VQRSHL_V_I]], <1 x i64> [[VQRSHL_V1_I]]) #4
+// CHECK: [[VQRSHL_V2_I:%.*]] = call <1 x i64> @llvm.arm.neon.vqrshiftu.v1i64(<1 x i64> %a, <1 x i64> %b) #4
// CHECK: [[VQRSHL_V3_I:%.*]] = bitcast <1 x i64> [[VQRSHL_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQRSHL_V3_I]] to <1 x i64>
-// CHECK: ret <1 x i64> [[TMP2]]
+// CHECK: ret <1 x i64> [[VQRSHL_V2_I]]
uint64x1_t test_vqrshl_u64(uint64x1_t a, int64x1_t b) {
return vqrshl_u64(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vqrshlq_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vqrshlq_s8(
// CHECK: [[VQRSHLQ_V_I:%.*]] = call <16 x i8> @llvm.arm.neon.vqrshifts.v16i8(<16 x i8> %a, <16 x i8> %b) #4
// CHECK: ret <16 x i8> [[VQRSHLQ_V_I]]
int8x16_t test_vqrshlq_s8(int8x16_t a, int8x16_t b) {
return vqrshlq_s8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vqrshlq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqrshlq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VQRSHLQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VQRSHLQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VQRSHLQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vqrshifts.v8i16(<8 x i16> [[VQRSHLQ_V_I]], <8 x i16> [[VQRSHLQ_V1_I]]) #4
+// CHECK: [[VQRSHLQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vqrshifts.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: [[VQRSHLQ_V3_I:%.*]] = bitcast <8 x i16> [[VQRSHLQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQRSHLQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VQRSHLQ_V2_I]]
int16x8_t test_vqrshlq_s16(int16x8_t a, int16x8_t b) {
return vqrshlq_s16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vqrshlq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqrshlq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VQRSHLQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQRSHLQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VQRSHLQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqrshifts.v4i32(<4 x i32> [[VQRSHLQ_V_I]], <4 x i32> [[VQRSHLQ_V1_I]]) #4
+// CHECK: [[VQRSHLQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqrshifts.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VQRSHLQ_V3_I:%.*]] = bitcast <4 x i32> [[VQRSHLQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQRSHLQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VQRSHLQ_V2_I]]
int32x4_t test_vqrshlq_s32(int32x4_t a, int32x4_t b) {
return vqrshlq_s32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vqrshlq_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vqrshlq_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[VQRSHLQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQRSHLQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VQRSHLQ_V2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vqrshifts.v2i64(<2 x i64> [[VQRSHLQ_V_I]], <2 x i64> [[VQRSHLQ_V1_I]]) #4
+// CHECK: [[VQRSHLQ_V2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vqrshifts.v2i64(<2 x i64> %a, <2 x i64> %b) #4
// CHECK: [[VQRSHLQ_V3_I:%.*]] = bitcast <2 x i64> [[VQRSHLQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQRSHLQ_V3_I]] to <2 x i64>
-// CHECK: ret <2 x i64> [[TMP2]]
+// CHECK: ret <2 x i64> [[VQRSHLQ_V2_I]]
int64x2_t test_vqrshlq_s64(int64x2_t a, int64x2_t b) {
return vqrshlq_s64(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vqrshlq_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vqrshlq_u8(
// CHECK: [[VQRSHLQ_V_I:%.*]] = call <16 x i8> @llvm.arm.neon.vqrshiftu.v16i8(<16 x i8> %a, <16 x i8> %b) #4
// CHECK: ret <16 x i8> [[VQRSHLQ_V_I]]
uint8x16_t test_vqrshlq_u8(uint8x16_t a, int8x16_t b) {
return vqrshlq_u8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vqrshlq_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqrshlq_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VQRSHLQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VQRSHLQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VQRSHLQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vqrshiftu.v8i16(<8 x i16> [[VQRSHLQ_V_I]], <8 x i16> [[VQRSHLQ_V1_I]]) #4
+// CHECK: [[VQRSHLQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vqrshiftu.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: [[VQRSHLQ_V3_I:%.*]] = bitcast <8 x i16> [[VQRSHLQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQRSHLQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VQRSHLQ_V2_I]]
uint16x8_t test_vqrshlq_u16(uint16x8_t a, int16x8_t b) {
return vqrshlq_u16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vqrshlq_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqrshlq_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VQRSHLQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQRSHLQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VQRSHLQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqrshiftu.v4i32(<4 x i32> [[VQRSHLQ_V_I]], <4 x i32> [[VQRSHLQ_V1_I]]) #4
+// CHECK: [[VQRSHLQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqrshiftu.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VQRSHLQ_V3_I:%.*]] = bitcast <4 x i32> [[VQRSHLQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQRSHLQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VQRSHLQ_V2_I]]
uint32x4_t test_vqrshlq_u32(uint32x4_t a, int32x4_t b) {
return vqrshlq_u32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vqrshlq_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vqrshlq_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[VQRSHLQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQRSHLQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VQRSHLQ_V2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vqrshiftu.v2i64(<2 x i64> [[VQRSHLQ_V_I]], <2 x i64> [[VQRSHLQ_V1_I]]) #4
+// CHECK: [[VQRSHLQ_V2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vqrshiftu.v2i64(<2 x i64> %a, <2 x i64> %b) #4
// CHECK: [[VQRSHLQ_V3_I:%.*]] = bitcast <2 x i64> [[VQRSHLQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQRSHLQ_V3_I]] to <2 x i64>
-// CHECK: ret <2 x i64> [[TMP2]]
+// CHECK: ret <2 x i64> [[VQRSHLQ_V2_I]]
uint64x2_t test_vqrshlq_u64(uint64x2_t a, int64x2_t b) {
return vqrshlq_u64(a, b);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vqrshrn_n_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vqrshrn_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[VQRSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VQRSHRN_N1:%.*]] = call <8 x i8> @llvm.arm.neon.vqrshiftns.v8i8(<8 x i16> [[VQRSHRN_N]], <8 x i16> <i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1>)
@@ -12795,7 +10811,7 @@ int8x8_t test_vqrshrn_n_s16(int16x8_t a) {
return vqrshrn_n_s16(a, 1);
}
-// CHECK-LABEL: define <4 x i16> @test_vqrshrn_n_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vqrshrn_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[VQRSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VQRSHRN_N1:%.*]] = call <4 x i16> @llvm.arm.neon.vqrshiftns.v4i16(<4 x i32> [[VQRSHRN_N]], <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>)
@@ -12804,7 +10820,7 @@ int16x4_t test_vqrshrn_n_s32(int32x4_t a) {
return vqrshrn_n_s32(a, 1);
}
-// CHECK-LABEL: define <2 x i32> @test_vqrshrn_n_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vqrshrn_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[VQRSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VQRSHRN_N1:%.*]] = call <2 x i32> @llvm.arm.neon.vqrshiftns.v2i32(<2 x i64> [[VQRSHRN_N]], <2 x i64> <i64 -1, i64 -1>)
@@ -12813,7 +10829,7 @@ int32x2_t test_vqrshrn_n_s64(int64x2_t a) {
return vqrshrn_n_s64(a, 1);
}
-// CHECK-LABEL: define <8 x i8> @test_vqrshrn_n_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vqrshrn_n_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[VQRSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VQRSHRN_N1:%.*]] = call <8 x i8> @llvm.arm.neon.vqrshiftnu.v8i8(<8 x i16> [[VQRSHRN_N]], <8 x i16> <i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1>)
@@ -12822,7 +10838,7 @@ uint8x8_t test_vqrshrn_n_u16(uint16x8_t a) {
return vqrshrn_n_u16(a, 1);
}
-// CHECK-LABEL: define <4 x i16> @test_vqrshrn_n_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vqrshrn_n_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[VQRSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VQRSHRN_N1:%.*]] = call <4 x i16> @llvm.arm.neon.vqrshiftnu.v4i16(<4 x i32> [[VQRSHRN_N]], <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>)
@@ -12831,7 +10847,7 @@ uint16x4_t test_vqrshrn_n_u32(uint32x4_t a) {
return vqrshrn_n_u32(a, 1);
}
-// CHECK-LABEL: define <2 x i32> @test_vqrshrn_n_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vqrshrn_n_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[VQRSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VQRSHRN_N1:%.*]] = call <2 x i32> @llvm.arm.neon.vqrshiftnu.v2i32(<2 x i64> [[VQRSHRN_N]], <2 x i64> <i64 -1, i64 -1>)
@@ -12840,8 +10856,7 @@ uint32x2_t test_vqrshrn_n_u64(uint64x2_t a) {
return vqrshrn_n_u64(a, 1);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vqrshrun_n_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vqrshrun_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[VQRSHRUN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VQRSHRUN_N1:%.*]] = call <8 x i8> @llvm.arm.neon.vqrshiftnsu.v8i8(<8 x i16> [[VQRSHRUN_N]], <8 x i16> <i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1>)
@@ -12850,7 +10865,7 @@ uint8x8_t test_vqrshrun_n_s16(int16x8_t a) {
return vqrshrun_n_s16(a, 1);
}
-// CHECK-LABEL: define <4 x i16> @test_vqrshrun_n_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vqrshrun_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[VQRSHRUN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VQRSHRUN_N1:%.*]] = call <4 x i16> @llvm.arm.neon.vqrshiftnsu.v4i16(<4 x i32> [[VQRSHRUN_N]], <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>)
@@ -12859,7 +10874,7 @@ uint16x4_t test_vqrshrun_n_s32(int32x4_t a) {
return vqrshrun_n_s32(a, 1);
}
-// CHECK-LABEL: define <2 x i32> @test_vqrshrun_n_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vqrshrun_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[VQRSHRUN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VQRSHRUN_N1:%.*]] = call <2 x i32> @llvm.arm.neon.vqrshiftnsu.v2i32(<2 x i64> [[VQRSHRUN_N]], <2 x i64> <i64 -1, i64 -1>)
@@ -12868,200 +10883,162 @@ uint32x2_t test_vqrshrun_n_s64(int64x2_t a) {
return vqrshrun_n_s64(a, 1);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vqshl_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vqshl_s8(
// CHECK: [[VQSHL_V_I:%.*]] = call <8 x i8> @llvm.arm.neon.vqshifts.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VQSHL_V_I]]
int8x8_t test_vqshl_s8(int8x8_t a, int8x8_t b) {
return vqshl_s8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vqshl_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqshl_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VQSHL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQSHL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQSHL_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vqshifts.v4i16(<4 x i16> [[VQSHL_V_I]], <4 x i16> [[VQSHL_V1_I]]) #4
+// CHECK: [[VQSHL_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vqshifts.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VQSHL_V3_I:%.*]] = bitcast <4 x i16> [[VQSHL_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQSHL_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VQSHL_V2_I]]
int16x4_t test_vqshl_s16(int16x4_t a, int16x4_t b) {
return vqshl_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vqshl_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqshl_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VQSHL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQSHL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQSHL_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vqshifts.v2i32(<2 x i32> [[VQSHL_V_I]], <2 x i32> [[VQSHL_V1_I]]) #4
+// CHECK: [[VQSHL_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vqshifts.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VQSHL_V3_I:%.*]] = bitcast <2 x i32> [[VQSHL_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQSHL_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VQSHL_V2_I]]
int32x2_t test_vqshl_s32(int32x2_t a, int32x2_t b) {
return vqshl_s32(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vqshl_s64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vqshl_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
-// CHECK: [[VQSHL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
-// CHECK: [[VQSHL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x i64>
-// CHECK: [[VQSHL_V2_I:%.*]] = call <1 x i64> @llvm.arm.neon.vqshifts.v1i64(<1 x i64> [[VQSHL_V_I]], <1 x i64> [[VQSHL_V1_I]]) #4
+// CHECK: [[VQSHL_V2_I:%.*]] = call <1 x i64> @llvm.arm.neon.vqshifts.v1i64(<1 x i64> %a, <1 x i64> %b) #4
// CHECK: [[VQSHL_V3_I:%.*]] = bitcast <1 x i64> [[VQSHL_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQSHL_V3_I]] to <1 x i64>
-// CHECK: ret <1 x i64> [[TMP2]]
+// CHECK: ret <1 x i64> [[VQSHL_V2_I]]
int64x1_t test_vqshl_s64(int64x1_t a, int64x1_t b) {
return vqshl_s64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vqshl_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vqshl_u8(
// CHECK: [[VQSHL_V_I:%.*]] = call <8 x i8> @llvm.arm.neon.vqshiftu.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VQSHL_V_I]]
uint8x8_t test_vqshl_u8(uint8x8_t a, int8x8_t b) {
return vqshl_u8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vqshl_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqshl_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VQSHL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQSHL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQSHL_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vqshiftu.v4i16(<4 x i16> [[VQSHL_V_I]], <4 x i16> [[VQSHL_V1_I]]) #4
+// CHECK: [[VQSHL_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vqshiftu.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VQSHL_V3_I:%.*]] = bitcast <4 x i16> [[VQSHL_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQSHL_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VQSHL_V2_I]]
uint16x4_t test_vqshl_u16(uint16x4_t a, int16x4_t b) {
return vqshl_u16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vqshl_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqshl_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VQSHL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQSHL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQSHL_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vqshiftu.v2i32(<2 x i32> [[VQSHL_V_I]], <2 x i32> [[VQSHL_V1_I]]) #4
+// CHECK: [[VQSHL_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vqshiftu.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VQSHL_V3_I:%.*]] = bitcast <2 x i32> [[VQSHL_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQSHL_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VQSHL_V2_I]]
uint32x2_t test_vqshl_u32(uint32x2_t a, int32x2_t b) {
return vqshl_u32(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vqshl_u64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vqshl_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
-// CHECK: [[VQSHL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
-// CHECK: [[VQSHL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x i64>
-// CHECK: [[VQSHL_V2_I:%.*]] = call <1 x i64> @llvm.arm.neon.vqshiftu.v1i64(<1 x i64> [[VQSHL_V_I]], <1 x i64> [[VQSHL_V1_I]]) #4
+// CHECK: [[VQSHL_V2_I:%.*]] = call <1 x i64> @llvm.arm.neon.vqshiftu.v1i64(<1 x i64> %a, <1 x i64> %b) #4
// CHECK: [[VQSHL_V3_I:%.*]] = bitcast <1 x i64> [[VQSHL_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQSHL_V3_I]] to <1 x i64>
-// CHECK: ret <1 x i64> [[TMP2]]
+// CHECK: ret <1 x i64> [[VQSHL_V2_I]]
uint64x1_t test_vqshl_u64(uint64x1_t a, int64x1_t b) {
return vqshl_u64(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vqshlq_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vqshlq_s8(
// CHECK: [[VQSHLQ_V_I:%.*]] = call <16 x i8> @llvm.arm.neon.vqshifts.v16i8(<16 x i8> %a, <16 x i8> %b) #4
// CHECK: ret <16 x i8> [[VQSHLQ_V_I]]
int8x16_t test_vqshlq_s8(int8x16_t a, int8x16_t b) {
return vqshlq_s8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vqshlq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqshlq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VQSHLQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VQSHLQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VQSHLQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vqshifts.v8i16(<8 x i16> [[VQSHLQ_V_I]], <8 x i16> [[VQSHLQ_V1_I]]) #4
+// CHECK: [[VQSHLQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vqshifts.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: [[VQSHLQ_V3_I:%.*]] = bitcast <8 x i16> [[VQSHLQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQSHLQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VQSHLQ_V2_I]]
int16x8_t test_vqshlq_s16(int16x8_t a, int16x8_t b) {
return vqshlq_s16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vqshlq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqshlq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VQSHLQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQSHLQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VQSHLQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqshifts.v4i32(<4 x i32> [[VQSHLQ_V_I]], <4 x i32> [[VQSHLQ_V1_I]]) #4
+// CHECK: [[VQSHLQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqshifts.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VQSHLQ_V3_I:%.*]] = bitcast <4 x i32> [[VQSHLQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQSHLQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VQSHLQ_V2_I]]
int32x4_t test_vqshlq_s32(int32x4_t a, int32x4_t b) {
return vqshlq_s32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vqshlq_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vqshlq_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[VQSHLQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQSHLQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VQSHLQ_V2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vqshifts.v2i64(<2 x i64> [[VQSHLQ_V_I]], <2 x i64> [[VQSHLQ_V1_I]]) #4
+// CHECK: [[VQSHLQ_V2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vqshifts.v2i64(<2 x i64> %a, <2 x i64> %b) #4
// CHECK: [[VQSHLQ_V3_I:%.*]] = bitcast <2 x i64> [[VQSHLQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQSHLQ_V3_I]] to <2 x i64>
-// CHECK: ret <2 x i64> [[TMP2]]
+// CHECK: ret <2 x i64> [[VQSHLQ_V2_I]]
int64x2_t test_vqshlq_s64(int64x2_t a, int64x2_t b) {
return vqshlq_s64(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vqshlq_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vqshlq_u8(
// CHECK: [[VQSHLQ_V_I:%.*]] = call <16 x i8> @llvm.arm.neon.vqshiftu.v16i8(<16 x i8> %a, <16 x i8> %b) #4
// CHECK: ret <16 x i8> [[VQSHLQ_V_I]]
uint8x16_t test_vqshlq_u8(uint8x16_t a, int8x16_t b) {
return vqshlq_u8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vqshlq_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqshlq_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VQSHLQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VQSHLQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VQSHLQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vqshiftu.v8i16(<8 x i16> [[VQSHLQ_V_I]], <8 x i16> [[VQSHLQ_V1_I]]) #4
+// CHECK: [[VQSHLQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vqshiftu.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: [[VQSHLQ_V3_I:%.*]] = bitcast <8 x i16> [[VQSHLQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQSHLQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VQSHLQ_V2_I]]
uint16x8_t test_vqshlq_u16(uint16x8_t a, int16x8_t b) {
return vqshlq_u16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vqshlq_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqshlq_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VQSHLQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQSHLQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VQSHLQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqshiftu.v4i32(<4 x i32> [[VQSHLQ_V_I]], <4 x i32> [[VQSHLQ_V1_I]]) #4
+// CHECK: [[VQSHLQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqshiftu.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VQSHLQ_V3_I:%.*]] = bitcast <4 x i32> [[VQSHLQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQSHLQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VQSHLQ_V2_I]]
uint32x4_t test_vqshlq_u32(uint32x4_t a, int32x4_t b) {
return vqshlq_u32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vqshlq_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vqshlq_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[VQSHLQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQSHLQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VQSHLQ_V2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vqshiftu.v2i64(<2 x i64> [[VQSHLQ_V_I]], <2 x i64> [[VQSHLQ_V1_I]]) #4
+// CHECK: [[VQSHLQ_V2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vqshiftu.v2i64(<2 x i64> %a, <2 x i64> %b) #4
// CHECK: [[VQSHLQ_V3_I:%.*]] = bitcast <2 x i64> [[VQSHLQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQSHLQ_V3_I]] to <2 x i64>
-// CHECK: ret <2 x i64> [[TMP2]]
+// CHECK: ret <2 x i64> [[VQSHLQ_V2_I]]
uint64x2_t test_vqshlq_u64(uint64x2_t a, int64x2_t b) {
return vqshlq_u64(a, b);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vqshlu_n_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vqshlu_n_s8(
// CHECK: [[VQSHLU_N:%.*]] = call <8 x i8> @llvm.arm.neon.vqshiftsu.v8i8(<8 x i8> %a, <8 x i8> <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1>)
// CHECK: ret <8 x i8> [[VQSHLU_N]]
uint8x8_t test_vqshlu_n_s8(int8x8_t a) {
return vqshlu_n_s8(a, 1);
}
-// CHECK-LABEL: define <4 x i16> @test_vqshlu_n_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vqshlu_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[VQSHLU_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
// CHECK: [[VQSHLU_N1:%.*]] = call <4 x i16> @llvm.arm.neon.vqshiftsu.v4i16(<4 x i16> [[VQSHLU_N]], <4 x i16> <i16 1, i16 1, i16 1, i16 1>)
@@ -13070,7 +11047,7 @@ uint16x4_t test_vqshlu_n_s16(int16x4_t a) {
return vqshlu_n_s16(a, 1);
}
-// CHECK-LABEL: define <2 x i32> @test_vqshlu_n_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vqshlu_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[VQSHLU_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
// CHECK: [[VQSHLU_N1:%.*]] = call <2 x i32> @llvm.arm.neon.vqshiftsu.v2i32(<2 x i32> [[VQSHLU_N]], <2 x i32> <i32 1, i32 1>)
@@ -13079,7 +11056,7 @@ uint32x2_t test_vqshlu_n_s32(int32x2_t a) {
return vqshlu_n_s32(a, 1);
}
-// CHECK-LABEL: define <1 x i64> @test_vqshlu_n_s64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vqshlu_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[VQSHLU_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
// CHECK: [[VQSHLU_N1:%.*]] = call <1 x i64> @llvm.arm.neon.vqshiftsu.v1i64(<1 x i64> [[VQSHLU_N]], <1 x i64> <i64 1>)
@@ -13088,14 +11065,14 @@ uint64x1_t test_vqshlu_n_s64(int64x1_t a) {
return vqshlu_n_s64(a, 1);
}
-// CHECK-LABEL: define <16 x i8> @test_vqshluq_n_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vqshluq_n_s8(
// CHECK: [[VQSHLU_N:%.*]] = call <16 x i8> @llvm.arm.neon.vqshiftsu.v16i8(<16 x i8> %a, <16 x i8> <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1>)
// CHECK: ret <16 x i8> [[VQSHLU_N]]
uint8x16_t test_vqshluq_n_s8(int8x16_t a) {
return vqshluq_n_s8(a, 1);
}
-// CHECK-LABEL: define <8 x i16> @test_vqshluq_n_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vqshluq_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[VQSHLU_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VQSHLU_N1:%.*]] = call <8 x i16> @llvm.arm.neon.vqshiftsu.v8i16(<8 x i16> [[VQSHLU_N]], <8 x i16> <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>)
@@ -13104,7 +11081,7 @@ uint16x8_t test_vqshluq_n_s16(int16x8_t a) {
return vqshluq_n_s16(a, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vqshluq_n_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vqshluq_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[VQSHLU_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VQSHLU_N1:%.*]] = call <4 x i32> @llvm.arm.neon.vqshiftsu.v4i32(<4 x i32> [[VQSHLU_N]], <4 x i32> <i32 1, i32 1, i32 1, i32 1>)
@@ -13113,7 +11090,7 @@ uint32x4_t test_vqshluq_n_s32(int32x4_t a) {
return vqshluq_n_s32(a, 1);
}
-// CHECK-LABEL: define <2 x i64> @test_vqshluq_n_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vqshluq_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[VQSHLU_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VQSHLU_N1:%.*]] = call <2 x i64> @llvm.arm.neon.vqshiftsu.v2i64(<2 x i64> [[VQSHLU_N]], <2 x i64> <i64 1, i64 1>)
@@ -13122,15 +11099,14 @@ uint64x2_t test_vqshluq_n_s64(int64x2_t a) {
return vqshluq_n_s64(a, 1);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vqshl_n_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vqshl_n_s8(
// CHECK: [[VQSHL_N:%.*]] = call <8 x i8> @llvm.arm.neon.vqshifts.v8i8(<8 x i8> %a, <8 x i8> <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1>)
// CHECK: ret <8 x i8> [[VQSHL_N]]
int8x8_t test_vqshl_n_s8(int8x8_t a) {
return vqshl_n_s8(a, 1);
}
-// CHECK-LABEL: define <4 x i16> @test_vqshl_n_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vqshl_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[VQSHL_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
// CHECK: [[VQSHL_N1:%.*]] = call <4 x i16> @llvm.arm.neon.vqshifts.v4i16(<4 x i16> [[VQSHL_N]], <4 x i16> <i16 1, i16 1, i16 1, i16 1>)
@@ -13139,7 +11115,7 @@ int16x4_t test_vqshl_n_s16(int16x4_t a) {
return vqshl_n_s16(a, 1);
}
-// CHECK-LABEL: define <2 x i32> @test_vqshl_n_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vqshl_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[VQSHL_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
// CHECK: [[VQSHL_N1:%.*]] = call <2 x i32> @llvm.arm.neon.vqshifts.v2i32(<2 x i32> [[VQSHL_N]], <2 x i32> <i32 1, i32 1>)
@@ -13148,7 +11124,7 @@ int32x2_t test_vqshl_n_s32(int32x2_t a) {
return vqshl_n_s32(a, 1);
}
-// CHECK-LABEL: define <1 x i64> @test_vqshl_n_s64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vqshl_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[VQSHL_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
// CHECK: [[VQSHL_N1:%.*]] = call <1 x i64> @llvm.arm.neon.vqshifts.v1i64(<1 x i64> [[VQSHL_N]], <1 x i64> <i64 1>)
@@ -13157,14 +11133,14 @@ int64x1_t test_vqshl_n_s64(int64x1_t a) {
return vqshl_n_s64(a, 1);
}
-// CHECK-LABEL: define <8 x i8> @test_vqshl_n_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vqshl_n_u8(
// CHECK: [[VQSHL_N:%.*]] = call <8 x i8> @llvm.arm.neon.vqshiftu.v8i8(<8 x i8> %a, <8 x i8> <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1>)
// CHECK: ret <8 x i8> [[VQSHL_N]]
uint8x8_t test_vqshl_n_u8(uint8x8_t a) {
return vqshl_n_u8(a, 1);
}
-// CHECK-LABEL: define <4 x i16> @test_vqshl_n_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vqshl_n_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[VQSHL_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
// CHECK: [[VQSHL_N1:%.*]] = call <4 x i16> @llvm.arm.neon.vqshiftu.v4i16(<4 x i16> [[VQSHL_N]], <4 x i16> <i16 1, i16 1, i16 1, i16 1>)
@@ -13173,7 +11149,7 @@ uint16x4_t test_vqshl_n_u16(uint16x4_t a) {
return vqshl_n_u16(a, 1);
}
-// CHECK-LABEL: define <2 x i32> @test_vqshl_n_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vqshl_n_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[VQSHL_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
// CHECK: [[VQSHL_N1:%.*]] = call <2 x i32> @llvm.arm.neon.vqshiftu.v2i32(<2 x i32> [[VQSHL_N]], <2 x i32> <i32 1, i32 1>)
@@ -13182,7 +11158,7 @@ uint32x2_t test_vqshl_n_u32(uint32x2_t a) {
return vqshl_n_u32(a, 1);
}
-// CHECK-LABEL: define <1 x i64> @test_vqshl_n_u64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vqshl_n_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[VQSHL_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
// CHECK: [[VQSHL_N1:%.*]] = call <1 x i64> @llvm.arm.neon.vqshiftu.v1i64(<1 x i64> [[VQSHL_N]], <1 x i64> <i64 1>)
@@ -13191,14 +11167,14 @@ uint64x1_t test_vqshl_n_u64(uint64x1_t a) {
return vqshl_n_u64(a, 1);
}
-// CHECK-LABEL: define <16 x i8> @test_vqshlq_n_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vqshlq_n_s8(
// CHECK: [[VQSHL_N:%.*]] = call <16 x i8> @llvm.arm.neon.vqshifts.v16i8(<16 x i8> %a, <16 x i8> <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1>)
// CHECK: ret <16 x i8> [[VQSHL_N]]
int8x16_t test_vqshlq_n_s8(int8x16_t a) {
return vqshlq_n_s8(a, 1);
}
-// CHECK-LABEL: define <8 x i16> @test_vqshlq_n_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vqshlq_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[VQSHL_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VQSHL_N1:%.*]] = call <8 x i16> @llvm.arm.neon.vqshifts.v8i16(<8 x i16> [[VQSHL_N]], <8 x i16> <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>)
@@ -13207,7 +11183,7 @@ int16x8_t test_vqshlq_n_s16(int16x8_t a) {
return vqshlq_n_s16(a, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vqshlq_n_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vqshlq_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[VQSHL_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VQSHL_N1:%.*]] = call <4 x i32> @llvm.arm.neon.vqshifts.v4i32(<4 x i32> [[VQSHL_N]], <4 x i32> <i32 1, i32 1, i32 1, i32 1>)
@@ -13216,7 +11192,7 @@ int32x4_t test_vqshlq_n_s32(int32x4_t a) {
return vqshlq_n_s32(a, 1);
}
-// CHECK-LABEL: define <2 x i64> @test_vqshlq_n_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vqshlq_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[VQSHL_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VQSHL_N1:%.*]] = call <2 x i64> @llvm.arm.neon.vqshifts.v2i64(<2 x i64> [[VQSHL_N]], <2 x i64> <i64 1, i64 1>)
@@ -13225,14 +11201,14 @@ int64x2_t test_vqshlq_n_s64(int64x2_t a) {
return vqshlq_n_s64(a, 1);
}
-// CHECK-LABEL: define <16 x i8> @test_vqshlq_n_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vqshlq_n_u8(
// CHECK: [[VQSHL_N:%.*]] = call <16 x i8> @llvm.arm.neon.vqshiftu.v16i8(<16 x i8> %a, <16 x i8> <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1>)
// CHECK: ret <16 x i8> [[VQSHL_N]]
uint8x16_t test_vqshlq_n_u8(uint8x16_t a) {
return vqshlq_n_u8(a, 1);
}
-// CHECK-LABEL: define <8 x i16> @test_vqshlq_n_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vqshlq_n_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[VQSHL_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VQSHL_N1:%.*]] = call <8 x i16> @llvm.arm.neon.vqshiftu.v8i16(<8 x i16> [[VQSHL_N]], <8 x i16> <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>)
@@ -13241,7 +11217,7 @@ uint16x8_t test_vqshlq_n_u16(uint16x8_t a) {
return vqshlq_n_u16(a, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vqshlq_n_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vqshlq_n_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[VQSHL_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VQSHL_N1:%.*]] = call <4 x i32> @llvm.arm.neon.vqshiftu.v4i32(<4 x i32> [[VQSHL_N]], <4 x i32> <i32 1, i32 1, i32 1, i32 1>)
@@ -13250,7 +11226,7 @@ uint32x4_t test_vqshlq_n_u32(uint32x4_t a) {
return vqshlq_n_u32(a, 1);
}
-// CHECK-LABEL: define <2 x i64> @test_vqshlq_n_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vqshlq_n_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[VQSHL_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VQSHL_N1:%.*]] = call <2 x i64> @llvm.arm.neon.vqshiftu.v2i64(<2 x i64> [[VQSHL_N]], <2 x i64> <i64 1, i64 1>)
@@ -13259,8 +11235,7 @@ uint64x2_t test_vqshlq_n_u64(uint64x2_t a) {
return vqshlq_n_u64(a, 1);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vqshrn_n_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vqshrn_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[VQSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VQSHRN_N1:%.*]] = call <8 x i8> @llvm.arm.neon.vqshiftns.v8i8(<8 x i16> [[VQSHRN_N]], <8 x i16> <i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1>)
@@ -13269,7 +11244,7 @@ int8x8_t test_vqshrn_n_s16(int16x8_t a) {
return vqshrn_n_s16(a, 1);
}
-// CHECK-LABEL: define <4 x i16> @test_vqshrn_n_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vqshrn_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[VQSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VQSHRN_N1:%.*]] = call <4 x i16> @llvm.arm.neon.vqshiftns.v4i16(<4 x i32> [[VQSHRN_N]], <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>)
@@ -13278,7 +11253,7 @@ int16x4_t test_vqshrn_n_s32(int32x4_t a) {
return vqshrn_n_s32(a, 1);
}
-// CHECK-LABEL: define <2 x i32> @test_vqshrn_n_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vqshrn_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[VQSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VQSHRN_N1:%.*]] = call <2 x i32> @llvm.arm.neon.vqshiftns.v2i32(<2 x i64> [[VQSHRN_N]], <2 x i64> <i64 -1, i64 -1>)
@@ -13287,7 +11262,7 @@ int32x2_t test_vqshrn_n_s64(int64x2_t a) {
return vqshrn_n_s64(a, 1);
}
-// CHECK-LABEL: define <8 x i8> @test_vqshrn_n_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vqshrn_n_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[VQSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VQSHRN_N1:%.*]] = call <8 x i8> @llvm.arm.neon.vqshiftnu.v8i8(<8 x i16> [[VQSHRN_N]], <8 x i16> <i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1>)
@@ -13296,7 +11271,7 @@ uint8x8_t test_vqshrn_n_u16(uint16x8_t a) {
return vqshrn_n_u16(a, 1);
}
-// CHECK-LABEL: define <4 x i16> @test_vqshrn_n_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vqshrn_n_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[VQSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VQSHRN_N1:%.*]] = call <4 x i16> @llvm.arm.neon.vqshiftnu.v4i16(<4 x i32> [[VQSHRN_N]], <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>)
@@ -13305,7 +11280,7 @@ uint16x4_t test_vqshrn_n_u32(uint32x4_t a) {
return vqshrn_n_u32(a, 1);
}
-// CHECK-LABEL: define <2 x i32> @test_vqshrn_n_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vqshrn_n_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[VQSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VQSHRN_N1:%.*]] = call <2 x i32> @llvm.arm.neon.vqshiftnu.v2i32(<2 x i64> [[VQSHRN_N]], <2 x i64> <i64 -1, i64 -1>)
@@ -13314,8 +11289,7 @@ uint32x2_t test_vqshrn_n_u64(uint64x2_t a) {
return vqshrn_n_u64(a, 1);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vqshrun_n_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vqshrun_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[VQSHRUN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VQSHRUN_N1:%.*]] = call <8 x i8> @llvm.arm.neon.vqshiftnsu.v8i8(<8 x i16> [[VQSHRUN_N]], <8 x i16> <i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1>)
@@ -13324,7 +11298,7 @@ uint8x8_t test_vqshrun_n_s16(int16x8_t a) {
return vqshrun_n_s16(a, 1);
}
-// CHECK-LABEL: define <4 x i16> @test_vqshrun_n_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vqshrun_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[VQSHRUN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VQSHRUN_N1:%.*]] = call <4 x i16> @llvm.arm.neon.vqshiftnsu.v4i16(<4 x i32> [[VQSHRUN_N]], <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>)
@@ -13333,7 +11307,7 @@ uint16x4_t test_vqshrun_n_s32(int32x4_t a) {
return vqshrun_n_s32(a, 1);
}
-// CHECK-LABEL: define <2 x i32> @test_vqshrun_n_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vqshrun_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[VQSHRUN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VQSHRUN_N1:%.*]] = call <2 x i32> @llvm.arm.neon.vqshiftnsu.v2i32(<2 x i64> [[VQSHRUN_N]], <2 x i64> <i64 -1, i64 -1>)
@@ -13342,2722 +11316,2589 @@ uint32x2_t test_vqshrun_n_s64(int64x2_t a) {
return vqshrun_n_s64(a, 1);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vqsub_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vqsub_s8(
// CHECK: [[VQSUB_V_I:%.*]] = call <8 x i8> @llvm.arm.neon.vqsubs.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VQSUB_V_I]]
int8x8_t test_vqsub_s8(int8x8_t a, int8x8_t b) {
return vqsub_s8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vqsub_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqsub_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VQSUB_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQSUB_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQSUB_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vqsubs.v4i16(<4 x i16> [[VQSUB_V_I]], <4 x i16> [[VQSUB_V1_I]]) #4
+// CHECK: [[VQSUB_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vqsubs.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VQSUB_V3_I:%.*]] = bitcast <4 x i16> [[VQSUB_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQSUB_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VQSUB_V2_I]]
int16x4_t test_vqsub_s16(int16x4_t a, int16x4_t b) {
return vqsub_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vqsub_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqsub_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VQSUB_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQSUB_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQSUB_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vqsubs.v2i32(<2 x i32> [[VQSUB_V_I]], <2 x i32> [[VQSUB_V1_I]]) #4
+// CHECK: [[VQSUB_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vqsubs.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VQSUB_V3_I:%.*]] = bitcast <2 x i32> [[VQSUB_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQSUB_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VQSUB_V2_I]]
int32x2_t test_vqsub_s32(int32x2_t a, int32x2_t b) {
return vqsub_s32(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vqsub_s64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vqsub_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
-// CHECK: [[VQSUB_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
-// CHECK: [[VQSUB_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x i64>
-// CHECK: [[VQSUB_V2_I:%.*]] = call <1 x i64> @llvm.arm.neon.vqsubs.v1i64(<1 x i64> [[VQSUB_V_I]], <1 x i64> [[VQSUB_V1_I]]) #4
+// CHECK: [[VQSUB_V2_I:%.*]] = call <1 x i64> @llvm.arm.neon.vqsubs.v1i64(<1 x i64> %a, <1 x i64> %b) #4
// CHECK: [[VQSUB_V3_I:%.*]] = bitcast <1 x i64> [[VQSUB_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQSUB_V3_I]] to <1 x i64>
-// CHECK: ret <1 x i64> [[TMP2]]
+// CHECK: ret <1 x i64> [[VQSUB_V2_I]]
int64x1_t test_vqsub_s64(int64x1_t a, int64x1_t b) {
return vqsub_s64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vqsub_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vqsub_u8(
// CHECK: [[VQSUB_V_I:%.*]] = call <8 x i8> @llvm.arm.neon.vqsubu.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VQSUB_V_I]]
uint8x8_t test_vqsub_u8(uint8x8_t a, uint8x8_t b) {
return vqsub_u8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vqsub_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqsub_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VQSUB_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VQSUB_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VQSUB_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vqsubu.v4i16(<4 x i16> [[VQSUB_V_I]], <4 x i16> [[VQSUB_V1_I]]) #4
+// CHECK: [[VQSUB_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vqsubu.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VQSUB_V3_I:%.*]] = bitcast <4 x i16> [[VQSUB_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQSUB_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VQSUB_V2_I]]
uint16x4_t test_vqsub_u16(uint16x4_t a, uint16x4_t b) {
return vqsub_u16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vqsub_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqsub_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VQSUB_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VQSUB_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VQSUB_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vqsubu.v2i32(<2 x i32> [[VQSUB_V_I]], <2 x i32> [[VQSUB_V1_I]]) #4
+// CHECK: [[VQSUB_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vqsubu.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VQSUB_V3_I:%.*]] = bitcast <2 x i32> [[VQSUB_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQSUB_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VQSUB_V2_I]]
uint32x2_t test_vqsub_u32(uint32x2_t a, uint32x2_t b) {
return vqsub_u32(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vqsub_u64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vqsub_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
-// CHECK: [[VQSUB_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
-// CHECK: [[VQSUB_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x i64>
-// CHECK: [[VQSUB_V2_I:%.*]] = call <1 x i64> @llvm.arm.neon.vqsubu.v1i64(<1 x i64> [[VQSUB_V_I]], <1 x i64> [[VQSUB_V1_I]]) #4
+// CHECK: [[VQSUB_V2_I:%.*]] = call <1 x i64> @llvm.arm.neon.vqsubu.v1i64(<1 x i64> %a, <1 x i64> %b) #4
// CHECK: [[VQSUB_V3_I:%.*]] = bitcast <1 x i64> [[VQSUB_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VQSUB_V3_I]] to <1 x i64>
-// CHECK: ret <1 x i64> [[TMP2]]
+// CHECK: ret <1 x i64> [[VQSUB_V2_I]]
uint64x1_t test_vqsub_u64(uint64x1_t a, uint64x1_t b) {
return vqsub_u64(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vqsubq_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vqsubq_s8(
// CHECK: [[VQSUBQ_V_I:%.*]] = call <16 x i8> @llvm.arm.neon.vqsubs.v16i8(<16 x i8> %a, <16 x i8> %b) #4
// CHECK: ret <16 x i8> [[VQSUBQ_V_I]]
int8x16_t test_vqsubq_s8(int8x16_t a, int8x16_t b) {
return vqsubq_s8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vqsubq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqsubq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VQSUBQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VQSUBQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VQSUBQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vqsubs.v8i16(<8 x i16> [[VQSUBQ_V_I]], <8 x i16> [[VQSUBQ_V1_I]]) #4
+// CHECK: [[VQSUBQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vqsubs.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: [[VQSUBQ_V3_I:%.*]] = bitcast <8 x i16> [[VQSUBQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQSUBQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VQSUBQ_V2_I]]
int16x8_t test_vqsubq_s16(int16x8_t a, int16x8_t b) {
return vqsubq_s16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vqsubq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqsubq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VQSUBQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQSUBQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VQSUBQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqsubs.v4i32(<4 x i32> [[VQSUBQ_V_I]], <4 x i32> [[VQSUBQ_V1_I]]) #4
+// CHECK: [[VQSUBQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqsubs.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VQSUBQ_V3_I:%.*]] = bitcast <4 x i32> [[VQSUBQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQSUBQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VQSUBQ_V2_I]]
int32x4_t test_vqsubq_s32(int32x4_t a, int32x4_t b) {
return vqsubq_s32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vqsubq_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vqsubq_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[VQSUBQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQSUBQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VQSUBQ_V2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vqsubs.v2i64(<2 x i64> [[VQSUBQ_V_I]], <2 x i64> [[VQSUBQ_V1_I]]) #4
+// CHECK: [[VQSUBQ_V2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vqsubs.v2i64(<2 x i64> %a, <2 x i64> %b) #4
// CHECK: [[VQSUBQ_V3_I:%.*]] = bitcast <2 x i64> [[VQSUBQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQSUBQ_V3_I]] to <2 x i64>
-// CHECK: ret <2 x i64> [[TMP2]]
+// CHECK: ret <2 x i64> [[VQSUBQ_V2_I]]
int64x2_t test_vqsubq_s64(int64x2_t a, int64x2_t b) {
return vqsubq_s64(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vqsubq_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vqsubq_u8(
// CHECK: [[VQSUBQ_V_I:%.*]] = call <16 x i8> @llvm.arm.neon.vqsubu.v16i8(<16 x i8> %a, <16 x i8> %b) #4
// CHECK: ret <16 x i8> [[VQSUBQ_V_I]]
uint8x16_t test_vqsubq_u8(uint8x16_t a, uint8x16_t b) {
return vqsubq_u8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vqsubq_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vqsubq_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VQSUBQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VQSUBQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VQSUBQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vqsubu.v8i16(<8 x i16> [[VQSUBQ_V_I]], <8 x i16> [[VQSUBQ_V1_I]]) #4
+// CHECK: [[VQSUBQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vqsubu.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: [[VQSUBQ_V3_I:%.*]] = bitcast <8 x i16> [[VQSUBQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQSUBQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VQSUBQ_V2_I]]
uint16x8_t test_vqsubq_u16(uint16x8_t a, uint16x8_t b) {
return vqsubq_u16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vqsubq_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vqsubq_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VQSUBQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VQSUBQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VQSUBQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqsubu.v4i32(<4 x i32> [[VQSUBQ_V_I]], <4 x i32> [[VQSUBQ_V1_I]]) #4
+// CHECK: [[VQSUBQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vqsubu.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VQSUBQ_V3_I:%.*]] = bitcast <4 x i32> [[VQSUBQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQSUBQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VQSUBQ_V2_I]]
uint32x4_t test_vqsubq_u32(uint32x4_t a, uint32x4_t b) {
return vqsubq_u32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vqsubq_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vqsubq_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[VQSUBQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VQSUBQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VQSUBQ_V2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vqsubu.v2i64(<2 x i64> [[VQSUBQ_V_I]], <2 x i64> [[VQSUBQ_V1_I]]) #4
+// CHECK: [[VQSUBQ_V2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vqsubu.v2i64(<2 x i64> %a, <2 x i64> %b) #4
// CHECK: [[VQSUBQ_V3_I:%.*]] = bitcast <2 x i64> [[VQSUBQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VQSUBQ_V3_I]] to <2 x i64>
-// CHECK: ret <2 x i64> [[TMP2]]
+// CHECK: ret <2 x i64> [[VQSUBQ_V2_I]]
uint64x2_t test_vqsubq_u64(uint64x2_t a, uint64x2_t b) {
return vqsubq_u64(a, b);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vraddhn_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vraddhn_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VRADDHN_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VRADDHN_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VRADDHN_V2_I:%.*]] = call <8 x i8> @llvm.arm.neon.vraddhn.v8i8(<8 x i16> [[VRADDHN_V_I]], <8 x i16> [[VRADDHN_V1_I]]) #4
+// CHECK: [[VRADDHN_V2_I:%.*]] = call <8 x i8> @llvm.arm.neon.vraddhn.v8i8(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: ret <8 x i8> [[VRADDHN_V2_I]]
int8x8_t test_vraddhn_s16(int16x8_t a, int16x8_t b) {
return vraddhn_s16(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vraddhn_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vraddhn_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VRADDHN_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VRADDHN_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VRADDHN_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vraddhn.v4i16(<4 x i32> [[VRADDHN_V_I]], <4 x i32> [[VRADDHN_V1_I]]) #4
+// CHECK: [[VRADDHN_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vraddhn.v4i16(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VRADDHN_V3_I:%.*]] = bitcast <4 x i16> [[VRADDHN_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRADDHN_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VRADDHN_V2_I]]
int16x4_t test_vraddhn_s32(int32x4_t a, int32x4_t b) {
return vraddhn_s32(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vraddhn_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vraddhn_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[VRADDHN_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VRADDHN_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VRADDHN_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vraddhn.v2i32(<2 x i64> [[VRADDHN_V_I]], <2 x i64> [[VRADDHN_V1_I]]) #4
+// CHECK: [[VRADDHN_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vraddhn.v2i32(<2 x i64> %a, <2 x i64> %b) #4
// CHECK: [[VRADDHN_V3_I:%.*]] = bitcast <2 x i32> [[VRADDHN_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRADDHN_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VRADDHN_V2_I]]
int32x2_t test_vraddhn_s64(int64x2_t a, int64x2_t b) {
return vraddhn_s64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vraddhn_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vraddhn_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VRADDHN_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VRADDHN_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VRADDHN_V2_I:%.*]] = call <8 x i8> @llvm.arm.neon.vraddhn.v8i8(<8 x i16> [[VRADDHN_V_I]], <8 x i16> [[VRADDHN_V1_I]]) #4
+// CHECK: [[VRADDHN_V2_I:%.*]] = call <8 x i8> @llvm.arm.neon.vraddhn.v8i8(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: ret <8 x i8> [[VRADDHN_V2_I]]
uint8x8_t test_vraddhn_u16(uint16x8_t a, uint16x8_t b) {
return vraddhn_u16(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vraddhn_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vraddhn_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VRADDHN_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VRADDHN_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VRADDHN_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vraddhn.v4i16(<4 x i32> [[VRADDHN_V_I]], <4 x i32> [[VRADDHN_V1_I]]) #4
+// CHECK: [[VRADDHN_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vraddhn.v4i16(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VRADDHN_V3_I:%.*]] = bitcast <4 x i16> [[VRADDHN_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRADDHN_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VRADDHN_V2_I]]
uint16x4_t test_vraddhn_u32(uint32x4_t a, uint32x4_t b) {
return vraddhn_u32(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vraddhn_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vraddhn_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[VRADDHN_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VRADDHN_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VRADDHN_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vraddhn.v2i32(<2 x i64> [[VRADDHN_V_I]], <2 x i64> [[VRADDHN_V1_I]]) #4
+// CHECK: [[VRADDHN_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vraddhn.v2i32(<2 x i64> %a, <2 x i64> %b) #4
// CHECK: [[VRADDHN_V3_I:%.*]] = bitcast <2 x i32> [[VRADDHN_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRADDHN_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VRADDHN_V2_I]]
uint32x2_t test_vraddhn_u64(uint64x2_t a, uint64x2_t b) {
return vraddhn_u64(a, b);
}
-
-// CHECK-LABEL: define <2 x float> @test_vrecpe_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vrecpe_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[VRECPE_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VRECPE_V1_I:%.*]] = call <2 x float> @llvm.arm.neon.vrecpe.v2f32(<2 x float> [[VRECPE_V_I]]) #4
+// CHECK: [[VRECPE_V1_I:%.*]] = call <2 x float> @llvm.arm.neon.vrecpe.v2f32(<2 x float> %a) #4
// CHECK: ret <2 x float> [[VRECPE_V1_I]]
float32x2_t test_vrecpe_f32(float32x2_t a) {
return vrecpe_f32(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vrecpe_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vrecpe_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[VRECPE_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VRECPE_V1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vrecpe.v2i32(<2 x i32> [[VRECPE_V_I]]) #4
+// CHECK: [[VRECPE_V1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vrecpe.v2i32(<2 x i32> %a) #4
// CHECK: ret <2 x i32> [[VRECPE_V1_I]]
uint32x2_t test_vrecpe_u32(uint32x2_t a) {
return vrecpe_u32(a);
}
-// CHECK-LABEL: define <4 x float> @test_vrecpeq_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vrecpeq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[VRECPEQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VRECPEQ_V1_I:%.*]] = call <4 x float> @llvm.arm.neon.vrecpe.v4f32(<4 x float> [[VRECPEQ_V_I]]) #4
+// CHECK: [[VRECPEQ_V1_I:%.*]] = call <4 x float> @llvm.arm.neon.vrecpe.v4f32(<4 x float> %a) #4
// CHECK: ret <4 x float> [[VRECPEQ_V1_I]]
float32x4_t test_vrecpeq_f32(float32x4_t a) {
return vrecpeq_f32(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vrecpeq_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vrecpeq_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
-// CHECK: [[VRECPEQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VRECPEQ_V1_I:%.*]] = call <4 x i32> @llvm.arm.neon.vrecpe.v4i32(<4 x i32> [[VRECPEQ_V_I]]) #4
+// CHECK: [[VRECPEQ_V1_I:%.*]] = call <4 x i32> @llvm.arm.neon.vrecpe.v4i32(<4 x i32> %a) #4
// CHECK: ret <4 x i32> [[VRECPEQ_V1_I]]
uint32x4_t test_vrecpeq_u32(uint32x4_t a) {
return vrecpeq_u32(a);
}
-
-// CHECK-LABEL: define <2 x float> @test_vrecps_f32(<2 x float> %a, <2 x float> %b) #0 {
+// CHECK-LABEL: @test_vrecps_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %b to <8 x i8>
-// CHECK: [[VRECPS_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VRECPS_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK: [[VRECPS_V2_I:%.*]] = call <2 x float> @llvm.arm.neon.vrecps.v2f32(<2 x float> [[VRECPS_V_I]], <2 x float> [[VRECPS_V1_I]]) #4
+// CHECK: [[VRECPS_V2_I:%.*]] = call <2 x float> @llvm.arm.neon.vrecps.v2f32(<2 x float> %a, <2 x float> %b) #4
// CHECK: [[VRECPS_V3_I:%.*]] = bitcast <2 x float> [[VRECPS_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRECPS_V3_I]] to <2 x float>
-// CHECK: ret <2 x float> [[TMP2]]
+// CHECK: ret <2 x float> [[VRECPS_V2_I]]
float32x2_t test_vrecps_f32(float32x2_t a, float32x2_t b) {
return vrecps_f32(a, b);
}
-// CHECK-LABEL: define <4 x float> @test_vrecpsq_f32(<4 x float> %a, <4 x float> %b) #0 {
+// CHECK-LABEL: @test_vrecpsq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %b to <16 x i8>
-// CHECK: [[VRECPSQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VRECPSQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
-// CHECK: [[VRECPSQ_V2_I:%.*]] = call <4 x float> @llvm.arm.neon.vrecps.v4f32(<4 x float> [[VRECPSQ_V_I]], <4 x float> [[VRECPSQ_V1_I]]) #4
+// CHECK: [[VRECPSQ_V2_I:%.*]] = call <4 x float> @llvm.arm.neon.vrecps.v4f32(<4 x float> %a, <4 x float> %b) #4
// CHECK: [[VRECPSQ_V3_I:%.*]] = bitcast <4 x float> [[VRECPSQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VRECPSQ_V3_I]] to <4 x float>
-// CHECK: ret <4 x float> [[TMP2]]
+// CHECK: ret <4 x float> [[VRECPSQ_V2_I]]
float32x4_t test_vrecpsq_f32(float32x4_t a, float32x4_t b) {
return vrecpsq_f32(a, b);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_s8_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s8_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
int8x8_t test_vreinterpret_s8_s16(int16x4_t a) {
return vreinterpret_s8_s16(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_s8_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s8_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
int8x8_t test_vreinterpret_s8_s32(int32x2_t a) {
return vreinterpret_s8_s32(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_s8_s64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s8_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
int8x8_t test_vreinterpret_s8_s64(int64x1_t a) {
return vreinterpret_s8_s64(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_s8_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s8_u8(
// CHECK: ret <8 x i8> %a
int8x8_t test_vreinterpret_s8_u8(uint8x8_t a) {
return vreinterpret_s8_u8(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_s8_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s8_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
int8x8_t test_vreinterpret_s8_u16(uint16x4_t a) {
return vreinterpret_s8_u16(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_s8_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s8_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
int8x8_t test_vreinterpret_s8_u32(uint32x2_t a) {
return vreinterpret_s8_u32(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_s8_u64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s8_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
int8x8_t test_vreinterpret_s8_u64(uint64x1_t a) {
return vreinterpret_s8_u64(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_s8_f16(<4 x half> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s8_f16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x half> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
int8x8_t test_vreinterpret_s8_f16(float16x4_t a) {
return vreinterpret_s8_f16(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_s8_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s8_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
int8x8_t test_vreinterpret_s8_f32(float32x2_t a) {
return vreinterpret_s8_f32(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_s8_p8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s8_p8(
// CHECK: ret <8 x i8> %a
int8x8_t test_vreinterpret_s8_p8(poly8x8_t a) {
return vreinterpret_s8_p8(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_s8_p16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s8_p16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
int8x8_t test_vreinterpret_s8_p16(poly16x4_t a) {
return vreinterpret_s8_p16(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_s16_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s16_s8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
int16x4_t test_vreinterpret_s16_s8(int8x8_t a) {
return vreinterpret_s16_s8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_s16_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s16_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
int16x4_t test_vreinterpret_s16_s32(int32x2_t a) {
return vreinterpret_s16_s32(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_s16_s64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s16_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
int16x4_t test_vreinterpret_s16_s64(int64x1_t a) {
return vreinterpret_s16_s64(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_s16_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s16_u8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
int16x4_t test_vreinterpret_s16_u8(uint8x8_t a) {
return vreinterpret_s16_u8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_s16_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s16_u16(
// CHECK: ret <4 x i16> %a
int16x4_t test_vreinterpret_s16_u16(uint16x4_t a) {
return vreinterpret_s16_u16(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_s16_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s16_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
int16x4_t test_vreinterpret_s16_u32(uint32x2_t a) {
return vreinterpret_s16_u32(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_s16_u64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s16_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
int16x4_t test_vreinterpret_s16_u64(uint64x1_t a) {
return vreinterpret_s16_u64(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_s16_f16(<4 x half> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s16_f16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x half> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
int16x4_t test_vreinterpret_s16_f16(float16x4_t a) {
return vreinterpret_s16_f16(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_s16_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s16_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
int16x4_t test_vreinterpret_s16_f32(float32x2_t a) {
return vreinterpret_s16_f32(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_s16_p8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s16_p8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
int16x4_t test_vreinterpret_s16_p8(poly8x8_t a) {
return vreinterpret_s16_p8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_s16_p16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s16_p16(
// CHECK: ret <4 x i16> %a
int16x4_t test_vreinterpret_s16_p16(poly16x4_t a) {
return vreinterpret_s16_p16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vreinterpret_s32_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s32_s8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <2 x i32>
// CHECK: ret <2 x i32> [[TMP0]]
int32x2_t test_vreinterpret_s32_s8(int8x8_t a) {
return vreinterpret_s32_s8(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vreinterpret_s32_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s32_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <2 x i32>
// CHECK: ret <2 x i32> [[TMP0]]
int32x2_t test_vreinterpret_s32_s16(int16x4_t a) {
return vreinterpret_s32_s16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vreinterpret_s32_s64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s32_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <2 x i32>
// CHECK: ret <2 x i32> [[TMP0]]
int32x2_t test_vreinterpret_s32_s64(int64x1_t a) {
return vreinterpret_s32_s64(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vreinterpret_s32_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s32_u8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <2 x i32>
// CHECK: ret <2 x i32> [[TMP0]]
int32x2_t test_vreinterpret_s32_u8(uint8x8_t a) {
return vreinterpret_s32_u8(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vreinterpret_s32_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s32_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <2 x i32>
// CHECK: ret <2 x i32> [[TMP0]]
int32x2_t test_vreinterpret_s32_u16(uint16x4_t a) {
return vreinterpret_s32_u16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vreinterpret_s32_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s32_u32(
// CHECK: ret <2 x i32> %a
int32x2_t test_vreinterpret_s32_u32(uint32x2_t a) {
return vreinterpret_s32_u32(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vreinterpret_s32_u64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s32_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <2 x i32>
// CHECK: ret <2 x i32> [[TMP0]]
int32x2_t test_vreinterpret_s32_u64(uint64x1_t a) {
return vreinterpret_s32_u64(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vreinterpret_s32_f16(<4 x half> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s32_f16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x half> %a to <2 x i32>
// CHECK: ret <2 x i32> [[TMP0]]
int32x2_t test_vreinterpret_s32_f16(float16x4_t a) {
return vreinterpret_s32_f16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vreinterpret_s32_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s32_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <2 x i32>
// CHECK: ret <2 x i32> [[TMP0]]
int32x2_t test_vreinterpret_s32_f32(float32x2_t a) {
return vreinterpret_s32_f32(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vreinterpret_s32_p8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s32_p8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <2 x i32>
// CHECK: ret <2 x i32> [[TMP0]]
int32x2_t test_vreinterpret_s32_p8(poly8x8_t a) {
return vreinterpret_s32_p8(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vreinterpret_s32_p16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s32_p16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <2 x i32>
// CHECK: ret <2 x i32> [[TMP0]]
int32x2_t test_vreinterpret_s32_p16(poly16x4_t a) {
return vreinterpret_s32_p16(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_s64_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s64_s8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
int64x1_t test_vreinterpret_s64_s8(int8x8_t a) {
return vreinterpret_s64_s8(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_s64_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s64_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
int64x1_t test_vreinterpret_s64_s16(int16x4_t a) {
return vreinterpret_s64_s16(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_s64_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s64_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
int64x1_t test_vreinterpret_s64_s32(int32x2_t a) {
return vreinterpret_s64_s32(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_s64_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s64_u8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
int64x1_t test_vreinterpret_s64_u8(uint8x8_t a) {
return vreinterpret_s64_u8(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_s64_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s64_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
int64x1_t test_vreinterpret_s64_u16(uint16x4_t a) {
return vreinterpret_s64_u16(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_s64_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s64_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
int64x1_t test_vreinterpret_s64_u32(uint32x2_t a) {
return vreinterpret_s64_u32(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_s64_u64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s64_u64(
// CHECK: ret <1 x i64> %a
int64x1_t test_vreinterpret_s64_u64(uint64x1_t a) {
return vreinterpret_s64_u64(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_s64_f16(<4 x half> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s64_f16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x half> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
int64x1_t test_vreinterpret_s64_f16(float16x4_t a) {
return vreinterpret_s64_f16(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_s64_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s64_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
int64x1_t test_vreinterpret_s64_f32(float32x2_t a) {
return vreinterpret_s64_f32(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_s64_p8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s64_p8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
int64x1_t test_vreinterpret_s64_p8(poly8x8_t a) {
return vreinterpret_s64_p8(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_s64_p16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_s64_p16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
int64x1_t test_vreinterpret_s64_p16(poly16x4_t a) {
return vreinterpret_s64_p16(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_u8_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u8_s8(
// CHECK: ret <8 x i8> %a
uint8x8_t test_vreinterpret_u8_s8(int8x8_t a) {
return vreinterpret_u8_s8(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_u8_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u8_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
uint8x8_t test_vreinterpret_u8_s16(int16x4_t a) {
return vreinterpret_u8_s16(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_u8_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u8_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
uint8x8_t test_vreinterpret_u8_s32(int32x2_t a) {
return vreinterpret_u8_s32(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_u8_s64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u8_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
uint8x8_t test_vreinterpret_u8_s64(int64x1_t a) {
return vreinterpret_u8_s64(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_u8_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u8_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
uint8x8_t test_vreinterpret_u8_u16(uint16x4_t a) {
return vreinterpret_u8_u16(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_u8_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u8_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
uint8x8_t test_vreinterpret_u8_u32(uint32x2_t a) {
return vreinterpret_u8_u32(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_u8_u64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u8_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
uint8x8_t test_vreinterpret_u8_u64(uint64x1_t a) {
return vreinterpret_u8_u64(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_u8_f16(<4 x half> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u8_f16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x half> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
uint8x8_t test_vreinterpret_u8_f16(float16x4_t a) {
return vreinterpret_u8_f16(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_u8_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u8_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
uint8x8_t test_vreinterpret_u8_f32(float32x2_t a) {
return vreinterpret_u8_f32(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_u8_p8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u8_p8(
// CHECK: ret <8 x i8> %a
uint8x8_t test_vreinterpret_u8_p8(poly8x8_t a) {
return vreinterpret_u8_p8(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_u8_p16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u8_p16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
uint8x8_t test_vreinterpret_u8_p16(poly16x4_t a) {
return vreinterpret_u8_p16(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_u16_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u16_s8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
uint16x4_t test_vreinterpret_u16_s8(int8x8_t a) {
return vreinterpret_u16_s8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_u16_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u16_s16(
// CHECK: ret <4 x i16> %a
uint16x4_t test_vreinterpret_u16_s16(int16x4_t a) {
return vreinterpret_u16_s16(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_u16_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u16_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
uint16x4_t test_vreinterpret_u16_s32(int32x2_t a) {
return vreinterpret_u16_s32(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_u16_s64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u16_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
uint16x4_t test_vreinterpret_u16_s64(int64x1_t a) {
return vreinterpret_u16_s64(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_u16_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u16_u8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
uint16x4_t test_vreinterpret_u16_u8(uint8x8_t a) {
return vreinterpret_u16_u8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_u16_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u16_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
uint16x4_t test_vreinterpret_u16_u32(uint32x2_t a) {
return vreinterpret_u16_u32(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_u16_u64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u16_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
uint16x4_t test_vreinterpret_u16_u64(uint64x1_t a) {
return vreinterpret_u16_u64(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_u16_f16(<4 x half> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u16_f16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x half> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
uint16x4_t test_vreinterpret_u16_f16(float16x4_t a) {
return vreinterpret_u16_f16(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_u16_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u16_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
uint16x4_t test_vreinterpret_u16_f32(float32x2_t a) {
return vreinterpret_u16_f32(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_u16_p8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u16_p8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
uint16x4_t test_vreinterpret_u16_p8(poly8x8_t a) {
return vreinterpret_u16_p8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_u16_p16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u16_p16(
// CHECK: ret <4 x i16> %a
uint16x4_t test_vreinterpret_u16_p16(poly16x4_t a) {
return vreinterpret_u16_p16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vreinterpret_u32_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u32_s8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <2 x i32>
// CHECK: ret <2 x i32> [[TMP0]]
uint32x2_t test_vreinterpret_u32_s8(int8x8_t a) {
return vreinterpret_u32_s8(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vreinterpret_u32_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u32_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <2 x i32>
// CHECK: ret <2 x i32> [[TMP0]]
uint32x2_t test_vreinterpret_u32_s16(int16x4_t a) {
return vreinterpret_u32_s16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vreinterpret_u32_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u32_s32(
// CHECK: ret <2 x i32> %a
uint32x2_t test_vreinterpret_u32_s32(int32x2_t a) {
return vreinterpret_u32_s32(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vreinterpret_u32_s64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u32_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <2 x i32>
// CHECK: ret <2 x i32> [[TMP0]]
uint32x2_t test_vreinterpret_u32_s64(int64x1_t a) {
return vreinterpret_u32_s64(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vreinterpret_u32_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u32_u8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <2 x i32>
// CHECK: ret <2 x i32> [[TMP0]]
uint32x2_t test_vreinterpret_u32_u8(uint8x8_t a) {
return vreinterpret_u32_u8(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vreinterpret_u32_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u32_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <2 x i32>
// CHECK: ret <2 x i32> [[TMP0]]
uint32x2_t test_vreinterpret_u32_u16(uint16x4_t a) {
return vreinterpret_u32_u16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vreinterpret_u32_u64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u32_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <2 x i32>
// CHECK: ret <2 x i32> [[TMP0]]
uint32x2_t test_vreinterpret_u32_u64(uint64x1_t a) {
return vreinterpret_u32_u64(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vreinterpret_u32_f16(<4 x half> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u32_f16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x half> %a to <2 x i32>
// CHECK: ret <2 x i32> [[TMP0]]
uint32x2_t test_vreinterpret_u32_f16(float16x4_t a) {
return vreinterpret_u32_f16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vreinterpret_u32_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u32_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <2 x i32>
// CHECK: ret <2 x i32> [[TMP0]]
uint32x2_t test_vreinterpret_u32_f32(float32x2_t a) {
return vreinterpret_u32_f32(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vreinterpret_u32_p8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u32_p8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <2 x i32>
// CHECK: ret <2 x i32> [[TMP0]]
uint32x2_t test_vreinterpret_u32_p8(poly8x8_t a) {
return vreinterpret_u32_p8(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vreinterpret_u32_p16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u32_p16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <2 x i32>
// CHECK: ret <2 x i32> [[TMP0]]
uint32x2_t test_vreinterpret_u32_p16(poly16x4_t a) {
return vreinterpret_u32_p16(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_u64_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u64_s8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
uint64x1_t test_vreinterpret_u64_s8(int8x8_t a) {
return vreinterpret_u64_s8(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_u64_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u64_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
uint64x1_t test_vreinterpret_u64_s16(int16x4_t a) {
return vreinterpret_u64_s16(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_u64_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u64_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
uint64x1_t test_vreinterpret_u64_s32(int32x2_t a) {
return vreinterpret_u64_s32(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_u64_s64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u64_s64(
// CHECK: ret <1 x i64> %a
uint64x1_t test_vreinterpret_u64_s64(int64x1_t a) {
return vreinterpret_u64_s64(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_u64_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u64_u8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
uint64x1_t test_vreinterpret_u64_u8(uint8x8_t a) {
return vreinterpret_u64_u8(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_u64_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u64_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
uint64x1_t test_vreinterpret_u64_u16(uint16x4_t a) {
return vreinterpret_u64_u16(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_u64_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u64_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
uint64x1_t test_vreinterpret_u64_u32(uint32x2_t a) {
return vreinterpret_u64_u32(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_u64_f16(<4 x half> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u64_f16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x half> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
uint64x1_t test_vreinterpret_u64_f16(float16x4_t a) {
return vreinterpret_u64_f16(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_u64_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u64_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
uint64x1_t test_vreinterpret_u64_f32(float32x2_t a) {
return vreinterpret_u64_f32(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_u64_p8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u64_p8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
uint64x1_t test_vreinterpret_u64_p8(poly8x8_t a) {
return vreinterpret_u64_p8(a);
}
-// CHECK-LABEL: define <1 x i64> @test_vreinterpret_u64_p16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_u64_p16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <1 x i64>
// CHECK: ret <1 x i64> [[TMP0]]
uint64x1_t test_vreinterpret_u64_p16(poly16x4_t a) {
return vreinterpret_u64_p16(a);
}
-// CHECK-LABEL: define <4 x half> @test_vreinterpret_f16_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f16_s8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <4 x half>
// CHECK: ret <4 x half> [[TMP0]]
float16x4_t test_vreinterpret_f16_s8(int8x8_t a) {
return vreinterpret_f16_s8(a);
}
-// CHECK-LABEL: define <4 x half> @test_vreinterpret_f16_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f16_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <4 x half>
// CHECK: ret <4 x half> [[TMP0]]
float16x4_t test_vreinterpret_f16_s16(int16x4_t a) {
return vreinterpret_f16_s16(a);
}
-// CHECK-LABEL: define <4 x half> @test_vreinterpret_f16_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f16_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <4 x half>
// CHECK: ret <4 x half> [[TMP0]]
float16x4_t test_vreinterpret_f16_s32(int32x2_t a) {
return vreinterpret_f16_s32(a);
}
-// CHECK-LABEL: define <4 x half> @test_vreinterpret_f16_s64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f16_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <4 x half>
// CHECK: ret <4 x half> [[TMP0]]
float16x4_t test_vreinterpret_f16_s64(int64x1_t a) {
return vreinterpret_f16_s64(a);
}
-// CHECK-LABEL: define <4 x half> @test_vreinterpret_f16_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f16_u8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <4 x half>
// CHECK: ret <4 x half> [[TMP0]]
float16x4_t test_vreinterpret_f16_u8(uint8x8_t a) {
return vreinterpret_f16_u8(a);
}
-// CHECK-LABEL: define <4 x half> @test_vreinterpret_f16_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f16_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <4 x half>
// CHECK: ret <4 x half> [[TMP0]]
float16x4_t test_vreinterpret_f16_u16(uint16x4_t a) {
return vreinterpret_f16_u16(a);
}
-// CHECK-LABEL: define <4 x half> @test_vreinterpret_f16_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f16_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <4 x half>
// CHECK: ret <4 x half> [[TMP0]]
float16x4_t test_vreinterpret_f16_u32(uint32x2_t a) {
return vreinterpret_f16_u32(a);
}
-// CHECK-LABEL: define <4 x half> @test_vreinterpret_f16_u64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f16_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <4 x half>
// CHECK: ret <4 x half> [[TMP0]]
float16x4_t test_vreinterpret_f16_u64(uint64x1_t a) {
return vreinterpret_f16_u64(a);
}
-// CHECK-LABEL: define <4 x half> @test_vreinterpret_f16_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f16_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <4 x half>
// CHECK: ret <4 x half> [[TMP0]]
float16x4_t test_vreinterpret_f16_f32(float32x2_t a) {
return vreinterpret_f16_f32(a);
}
-// CHECK-LABEL: define <4 x half> @test_vreinterpret_f16_p8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f16_p8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <4 x half>
// CHECK: ret <4 x half> [[TMP0]]
float16x4_t test_vreinterpret_f16_p8(poly8x8_t a) {
return vreinterpret_f16_p8(a);
}
-// CHECK-LABEL: define <4 x half> @test_vreinterpret_f16_p16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f16_p16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <4 x half>
// CHECK: ret <4 x half> [[TMP0]]
float16x4_t test_vreinterpret_f16_p16(poly16x4_t a) {
return vreinterpret_f16_p16(a);
}
-// CHECK-LABEL: define <2 x float> @test_vreinterpret_f32_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f32_s8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <2 x float>
// CHECK: ret <2 x float> [[TMP0]]
float32x2_t test_vreinterpret_f32_s8(int8x8_t a) {
return vreinterpret_f32_s8(a);
}
-// CHECK-LABEL: define <2 x float> @test_vreinterpret_f32_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f32_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <2 x float>
// CHECK: ret <2 x float> [[TMP0]]
float32x2_t test_vreinterpret_f32_s16(int16x4_t a) {
return vreinterpret_f32_s16(a);
}
-// CHECK-LABEL: define <2 x float> @test_vreinterpret_f32_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f32_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <2 x float>
// CHECK: ret <2 x float> [[TMP0]]
float32x2_t test_vreinterpret_f32_s32(int32x2_t a) {
return vreinterpret_f32_s32(a);
}
-// CHECK-LABEL: define <2 x float> @test_vreinterpret_f32_s64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f32_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <2 x float>
// CHECK: ret <2 x float> [[TMP0]]
float32x2_t test_vreinterpret_f32_s64(int64x1_t a) {
return vreinterpret_f32_s64(a);
}
-// CHECK-LABEL: define <2 x float> @test_vreinterpret_f32_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f32_u8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <2 x float>
// CHECK: ret <2 x float> [[TMP0]]
float32x2_t test_vreinterpret_f32_u8(uint8x8_t a) {
return vreinterpret_f32_u8(a);
}
-// CHECK-LABEL: define <2 x float> @test_vreinterpret_f32_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f32_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <2 x float>
// CHECK: ret <2 x float> [[TMP0]]
float32x2_t test_vreinterpret_f32_u16(uint16x4_t a) {
return vreinterpret_f32_u16(a);
}
-// CHECK-LABEL: define <2 x float> @test_vreinterpret_f32_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f32_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <2 x float>
// CHECK: ret <2 x float> [[TMP0]]
float32x2_t test_vreinterpret_f32_u32(uint32x2_t a) {
return vreinterpret_f32_u32(a);
}
-// CHECK-LABEL: define <2 x float> @test_vreinterpret_f32_u64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f32_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <2 x float>
// CHECK: ret <2 x float> [[TMP0]]
float32x2_t test_vreinterpret_f32_u64(uint64x1_t a) {
return vreinterpret_f32_u64(a);
}
-// CHECK-LABEL: define <2 x float> @test_vreinterpret_f32_f16(<4 x half> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f32_f16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x half> %a to <2 x float>
// CHECK: ret <2 x float> [[TMP0]]
float32x2_t test_vreinterpret_f32_f16(float16x4_t a) {
return vreinterpret_f32_f16(a);
}
-// CHECK-LABEL: define <2 x float> @test_vreinterpret_f32_p8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f32_p8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <2 x float>
// CHECK: ret <2 x float> [[TMP0]]
float32x2_t test_vreinterpret_f32_p8(poly8x8_t a) {
return vreinterpret_f32_p8(a);
}
-// CHECK-LABEL: define <2 x float> @test_vreinterpret_f32_p16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_f32_p16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <2 x float>
// CHECK: ret <2 x float> [[TMP0]]
float32x2_t test_vreinterpret_f32_p16(poly16x4_t a) {
return vreinterpret_f32_p16(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_p8_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p8_s8(
// CHECK: ret <8 x i8> %a
poly8x8_t test_vreinterpret_p8_s8(int8x8_t a) {
return vreinterpret_p8_s8(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_p8_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p8_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
poly8x8_t test_vreinterpret_p8_s16(int16x4_t a) {
return vreinterpret_p8_s16(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_p8_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p8_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
poly8x8_t test_vreinterpret_p8_s32(int32x2_t a) {
return vreinterpret_p8_s32(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_p8_s64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p8_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
poly8x8_t test_vreinterpret_p8_s64(int64x1_t a) {
return vreinterpret_p8_s64(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_p8_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p8_u8(
// CHECK: ret <8 x i8> %a
poly8x8_t test_vreinterpret_p8_u8(uint8x8_t a) {
return vreinterpret_p8_u8(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_p8_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p8_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
poly8x8_t test_vreinterpret_p8_u16(uint16x4_t a) {
return vreinterpret_p8_u16(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_p8_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p8_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
poly8x8_t test_vreinterpret_p8_u32(uint32x2_t a) {
return vreinterpret_p8_u32(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_p8_u64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p8_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
poly8x8_t test_vreinterpret_p8_u64(uint64x1_t a) {
return vreinterpret_p8_u64(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_p8_f16(<4 x half> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p8_f16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x half> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
poly8x8_t test_vreinterpret_p8_f16(float16x4_t a) {
return vreinterpret_p8_f16(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_p8_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p8_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
poly8x8_t test_vreinterpret_p8_f32(float32x2_t a) {
return vreinterpret_p8_f32(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vreinterpret_p8_p16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p8_p16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: ret <8 x i8> [[TMP0]]
poly8x8_t test_vreinterpret_p8_p16(poly16x4_t a) {
return vreinterpret_p8_p16(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_p16_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p16_s8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
poly16x4_t test_vreinterpret_p16_s8(int8x8_t a) {
return vreinterpret_p16_s8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_p16_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p16_s16(
// CHECK: ret <4 x i16> %a
poly16x4_t test_vreinterpret_p16_s16(int16x4_t a) {
return vreinterpret_p16_s16(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_p16_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p16_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
poly16x4_t test_vreinterpret_p16_s32(int32x2_t a) {
return vreinterpret_p16_s32(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_p16_s64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p16_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
poly16x4_t test_vreinterpret_p16_s64(int64x1_t a) {
return vreinterpret_p16_s64(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_p16_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p16_u8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
poly16x4_t test_vreinterpret_p16_u8(uint8x8_t a) {
return vreinterpret_p16_u8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_p16_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p16_u16(
// CHECK: ret <4 x i16> %a
poly16x4_t test_vreinterpret_p16_u16(uint16x4_t a) {
return vreinterpret_p16_u16(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_p16_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p16_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
poly16x4_t test_vreinterpret_p16_u32(uint32x2_t a) {
return vreinterpret_p16_u32(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_p16_u64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p16_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
poly16x4_t test_vreinterpret_p16_u64(uint64x1_t a) {
return vreinterpret_p16_u64(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_p16_f16(<4 x half> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p16_f16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x half> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
poly16x4_t test_vreinterpret_p16_f16(float16x4_t a) {
return vreinterpret_p16_f16(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_p16_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p16_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
poly16x4_t test_vreinterpret_p16_f32(float32x2_t a) {
return vreinterpret_p16_f32(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vreinterpret_p16_p8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpret_p16_p8(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i8> %a to <4 x i16>
// CHECK: ret <4 x i16> [[TMP0]]
poly16x4_t test_vreinterpret_p16_p8(poly8x8_t a) {
return vreinterpret_p16_p8(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_s8_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s8_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
int8x16_t test_vreinterpretq_s8_s16(int16x8_t a) {
return vreinterpretq_s8_s16(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_s8_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s8_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
int8x16_t test_vreinterpretq_s8_s32(int32x4_t a) {
return vreinterpretq_s8_s32(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_s8_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s8_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
int8x16_t test_vreinterpretq_s8_s64(int64x2_t a) {
return vreinterpretq_s8_s64(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_s8_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s8_u8(
// CHECK: ret <16 x i8> %a
int8x16_t test_vreinterpretq_s8_u8(uint8x16_t a) {
return vreinterpretq_s8_u8(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_s8_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s8_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
int8x16_t test_vreinterpretq_s8_u16(uint16x8_t a) {
return vreinterpretq_s8_u16(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_s8_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s8_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
int8x16_t test_vreinterpretq_s8_u32(uint32x4_t a) {
return vreinterpretq_s8_u32(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_s8_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s8_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
int8x16_t test_vreinterpretq_s8_u64(uint64x2_t a) {
return vreinterpretq_s8_u64(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_s8_f16(<8 x half> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s8_f16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x half> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
int8x16_t test_vreinterpretq_s8_f16(float16x8_t a) {
return vreinterpretq_s8_f16(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_s8_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s8_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
int8x16_t test_vreinterpretq_s8_f32(float32x4_t a) {
return vreinterpretq_s8_f32(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_s8_p8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s8_p8(
// CHECK: ret <16 x i8> %a
int8x16_t test_vreinterpretq_s8_p8(poly8x16_t a) {
return vreinterpretq_s8_p8(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_s8_p16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s8_p16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
int8x16_t test_vreinterpretq_s8_p16(poly16x8_t a) {
return vreinterpretq_s8_p16(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_s16_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s16_s8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
int16x8_t test_vreinterpretq_s16_s8(int8x16_t a) {
return vreinterpretq_s16_s8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_s16_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s16_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
int16x8_t test_vreinterpretq_s16_s32(int32x4_t a) {
return vreinterpretq_s16_s32(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_s16_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s16_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
int16x8_t test_vreinterpretq_s16_s64(int64x2_t a) {
return vreinterpretq_s16_s64(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_s16_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s16_u8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
int16x8_t test_vreinterpretq_s16_u8(uint8x16_t a) {
return vreinterpretq_s16_u8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_s16_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s16_u16(
// CHECK: ret <8 x i16> %a
int16x8_t test_vreinterpretq_s16_u16(uint16x8_t a) {
return vreinterpretq_s16_u16(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_s16_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s16_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
int16x8_t test_vreinterpretq_s16_u32(uint32x4_t a) {
return vreinterpretq_s16_u32(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_s16_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s16_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
int16x8_t test_vreinterpretq_s16_u64(uint64x2_t a) {
return vreinterpretq_s16_u64(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_s16_f16(<8 x half> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s16_f16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x half> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
int16x8_t test_vreinterpretq_s16_f16(float16x8_t a) {
return vreinterpretq_s16_f16(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_s16_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s16_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
int16x8_t test_vreinterpretq_s16_f32(float32x4_t a) {
return vreinterpretq_s16_f32(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_s16_p8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s16_p8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
int16x8_t test_vreinterpretq_s16_p8(poly8x16_t a) {
return vreinterpretq_s16_p8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_s16_p16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s16_p16(
// CHECK: ret <8 x i16> %a
int16x8_t test_vreinterpretq_s16_p16(poly16x8_t a) {
return vreinterpretq_s16_p16(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_s32_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s32_s8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <4 x i32>
// CHECK: ret <4 x i32> [[TMP0]]
int32x4_t test_vreinterpretq_s32_s8(int8x16_t a) {
return vreinterpretq_s32_s8(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_s32_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s32_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <4 x i32>
// CHECK: ret <4 x i32> [[TMP0]]
int32x4_t test_vreinterpretq_s32_s16(int16x8_t a) {
return vreinterpretq_s32_s16(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_s32_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s32_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <4 x i32>
// CHECK: ret <4 x i32> [[TMP0]]
int32x4_t test_vreinterpretq_s32_s64(int64x2_t a) {
return vreinterpretq_s32_s64(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_s32_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s32_u8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <4 x i32>
// CHECK: ret <4 x i32> [[TMP0]]
int32x4_t test_vreinterpretq_s32_u8(uint8x16_t a) {
return vreinterpretq_s32_u8(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_s32_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s32_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <4 x i32>
// CHECK: ret <4 x i32> [[TMP0]]
int32x4_t test_vreinterpretq_s32_u16(uint16x8_t a) {
return vreinterpretq_s32_u16(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_s32_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s32_u32(
// CHECK: ret <4 x i32> %a
int32x4_t test_vreinterpretq_s32_u32(uint32x4_t a) {
return vreinterpretq_s32_u32(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_s32_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s32_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <4 x i32>
// CHECK: ret <4 x i32> [[TMP0]]
int32x4_t test_vreinterpretq_s32_u64(uint64x2_t a) {
return vreinterpretq_s32_u64(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_s32_f16(<8 x half> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s32_f16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x half> %a to <4 x i32>
// CHECK: ret <4 x i32> [[TMP0]]
int32x4_t test_vreinterpretq_s32_f16(float16x8_t a) {
return vreinterpretq_s32_f16(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_s32_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s32_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <4 x i32>
// CHECK: ret <4 x i32> [[TMP0]]
int32x4_t test_vreinterpretq_s32_f32(float32x4_t a) {
return vreinterpretq_s32_f32(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_s32_p8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s32_p8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <4 x i32>
// CHECK: ret <4 x i32> [[TMP0]]
int32x4_t test_vreinterpretq_s32_p8(poly8x16_t a) {
return vreinterpretq_s32_p8(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_s32_p16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s32_p16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <4 x i32>
// CHECK: ret <4 x i32> [[TMP0]]
int32x4_t test_vreinterpretq_s32_p16(poly16x8_t a) {
return vreinterpretq_s32_p16(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_s64_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s64_s8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
int64x2_t test_vreinterpretq_s64_s8(int8x16_t a) {
return vreinterpretq_s64_s8(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_s64_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s64_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
int64x2_t test_vreinterpretq_s64_s16(int16x8_t a) {
return vreinterpretq_s64_s16(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_s64_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s64_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
int64x2_t test_vreinterpretq_s64_s32(int32x4_t a) {
return vreinterpretq_s64_s32(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_s64_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s64_u8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
int64x2_t test_vreinterpretq_s64_u8(uint8x16_t a) {
return vreinterpretq_s64_u8(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_s64_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s64_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
int64x2_t test_vreinterpretq_s64_u16(uint16x8_t a) {
return vreinterpretq_s64_u16(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_s64_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s64_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
int64x2_t test_vreinterpretq_s64_u32(uint32x4_t a) {
return vreinterpretq_s64_u32(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_s64_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s64_u64(
// CHECK: ret <2 x i64> %a
int64x2_t test_vreinterpretq_s64_u64(uint64x2_t a) {
return vreinterpretq_s64_u64(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_s64_f16(<8 x half> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s64_f16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x half> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
int64x2_t test_vreinterpretq_s64_f16(float16x8_t a) {
return vreinterpretq_s64_f16(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_s64_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s64_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
int64x2_t test_vreinterpretq_s64_f32(float32x4_t a) {
return vreinterpretq_s64_f32(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_s64_p8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s64_p8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
int64x2_t test_vreinterpretq_s64_p8(poly8x16_t a) {
return vreinterpretq_s64_p8(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_s64_p16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_s64_p16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
int64x2_t test_vreinterpretq_s64_p16(poly16x8_t a) {
return vreinterpretq_s64_p16(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_u8_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u8_s8(
// CHECK: ret <16 x i8> %a
uint8x16_t test_vreinterpretq_u8_s8(int8x16_t a) {
return vreinterpretq_u8_s8(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_u8_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u8_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
uint8x16_t test_vreinterpretq_u8_s16(int16x8_t a) {
return vreinterpretq_u8_s16(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_u8_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u8_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
uint8x16_t test_vreinterpretq_u8_s32(int32x4_t a) {
return vreinterpretq_u8_s32(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_u8_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u8_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
uint8x16_t test_vreinterpretq_u8_s64(int64x2_t a) {
return vreinterpretq_u8_s64(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_u8_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u8_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
uint8x16_t test_vreinterpretq_u8_u16(uint16x8_t a) {
return vreinterpretq_u8_u16(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_u8_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u8_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
uint8x16_t test_vreinterpretq_u8_u32(uint32x4_t a) {
return vreinterpretq_u8_u32(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_u8_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u8_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
uint8x16_t test_vreinterpretq_u8_u64(uint64x2_t a) {
return vreinterpretq_u8_u64(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_u8_f16(<8 x half> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u8_f16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x half> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
uint8x16_t test_vreinterpretq_u8_f16(float16x8_t a) {
return vreinterpretq_u8_f16(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_u8_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u8_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
uint8x16_t test_vreinterpretq_u8_f32(float32x4_t a) {
return vreinterpretq_u8_f32(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_u8_p8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u8_p8(
// CHECK: ret <16 x i8> %a
uint8x16_t test_vreinterpretq_u8_p8(poly8x16_t a) {
return vreinterpretq_u8_p8(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_u8_p16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u8_p16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
uint8x16_t test_vreinterpretq_u8_p16(poly16x8_t a) {
return vreinterpretq_u8_p16(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_u16_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u16_s8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
uint16x8_t test_vreinterpretq_u16_s8(int8x16_t a) {
return vreinterpretq_u16_s8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_u16_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u16_s16(
// CHECK: ret <8 x i16> %a
uint16x8_t test_vreinterpretq_u16_s16(int16x8_t a) {
return vreinterpretq_u16_s16(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_u16_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u16_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
uint16x8_t test_vreinterpretq_u16_s32(int32x4_t a) {
return vreinterpretq_u16_s32(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_u16_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u16_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
uint16x8_t test_vreinterpretq_u16_s64(int64x2_t a) {
return vreinterpretq_u16_s64(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_u16_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u16_u8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
uint16x8_t test_vreinterpretq_u16_u8(uint8x16_t a) {
return vreinterpretq_u16_u8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_u16_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u16_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
uint16x8_t test_vreinterpretq_u16_u32(uint32x4_t a) {
return vreinterpretq_u16_u32(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_u16_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u16_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
uint16x8_t test_vreinterpretq_u16_u64(uint64x2_t a) {
return vreinterpretq_u16_u64(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_u16_f16(<8 x half> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u16_f16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x half> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
uint16x8_t test_vreinterpretq_u16_f16(float16x8_t a) {
return vreinterpretq_u16_f16(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_u16_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u16_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
uint16x8_t test_vreinterpretq_u16_f32(float32x4_t a) {
return vreinterpretq_u16_f32(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_u16_p8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u16_p8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
uint16x8_t test_vreinterpretq_u16_p8(poly8x16_t a) {
return vreinterpretq_u16_p8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_u16_p16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u16_p16(
// CHECK: ret <8 x i16> %a
uint16x8_t test_vreinterpretq_u16_p16(poly16x8_t a) {
return vreinterpretq_u16_p16(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_u32_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u32_s8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <4 x i32>
// CHECK: ret <4 x i32> [[TMP0]]
uint32x4_t test_vreinterpretq_u32_s8(int8x16_t a) {
return vreinterpretq_u32_s8(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_u32_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u32_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <4 x i32>
// CHECK: ret <4 x i32> [[TMP0]]
uint32x4_t test_vreinterpretq_u32_s16(int16x8_t a) {
return vreinterpretq_u32_s16(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_u32_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u32_s32(
// CHECK: ret <4 x i32> %a
uint32x4_t test_vreinterpretq_u32_s32(int32x4_t a) {
return vreinterpretq_u32_s32(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_u32_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u32_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <4 x i32>
// CHECK: ret <4 x i32> [[TMP0]]
uint32x4_t test_vreinterpretq_u32_s64(int64x2_t a) {
return vreinterpretq_u32_s64(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_u32_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u32_u8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <4 x i32>
// CHECK: ret <4 x i32> [[TMP0]]
uint32x4_t test_vreinterpretq_u32_u8(uint8x16_t a) {
return vreinterpretq_u32_u8(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_u32_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u32_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <4 x i32>
// CHECK: ret <4 x i32> [[TMP0]]
uint32x4_t test_vreinterpretq_u32_u16(uint16x8_t a) {
return vreinterpretq_u32_u16(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_u32_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u32_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <4 x i32>
// CHECK: ret <4 x i32> [[TMP0]]
uint32x4_t test_vreinterpretq_u32_u64(uint64x2_t a) {
return vreinterpretq_u32_u64(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_u32_f16(<8 x half> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u32_f16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x half> %a to <4 x i32>
// CHECK: ret <4 x i32> [[TMP0]]
uint32x4_t test_vreinterpretq_u32_f16(float16x8_t a) {
return vreinterpretq_u32_f16(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_u32_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u32_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <4 x i32>
// CHECK: ret <4 x i32> [[TMP0]]
uint32x4_t test_vreinterpretq_u32_f32(float32x4_t a) {
return vreinterpretq_u32_f32(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_u32_p8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u32_p8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <4 x i32>
// CHECK: ret <4 x i32> [[TMP0]]
uint32x4_t test_vreinterpretq_u32_p8(poly8x16_t a) {
return vreinterpretq_u32_p8(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vreinterpretq_u32_p16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u32_p16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <4 x i32>
// CHECK: ret <4 x i32> [[TMP0]]
uint32x4_t test_vreinterpretq_u32_p16(poly16x8_t a) {
return vreinterpretq_u32_p16(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_u64_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u64_s8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
uint64x2_t test_vreinterpretq_u64_s8(int8x16_t a) {
return vreinterpretq_u64_s8(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_u64_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u64_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
uint64x2_t test_vreinterpretq_u64_s16(int16x8_t a) {
return vreinterpretq_u64_s16(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_u64_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u64_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
uint64x2_t test_vreinterpretq_u64_s32(int32x4_t a) {
return vreinterpretq_u64_s32(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_u64_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u64_s64(
// CHECK: ret <2 x i64> %a
uint64x2_t test_vreinterpretq_u64_s64(int64x2_t a) {
return vreinterpretq_u64_s64(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_u64_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u64_u8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
uint64x2_t test_vreinterpretq_u64_u8(uint8x16_t a) {
return vreinterpretq_u64_u8(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_u64_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u64_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
uint64x2_t test_vreinterpretq_u64_u16(uint16x8_t a) {
return vreinterpretq_u64_u16(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_u64_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u64_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
uint64x2_t test_vreinterpretq_u64_u32(uint32x4_t a) {
return vreinterpretq_u64_u32(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_u64_f16(<8 x half> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u64_f16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x half> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
uint64x2_t test_vreinterpretq_u64_f16(float16x8_t a) {
return vreinterpretq_u64_f16(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_u64_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u64_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
uint64x2_t test_vreinterpretq_u64_f32(float32x4_t a) {
return vreinterpretq_u64_f32(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_u64_p8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u64_p8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
uint64x2_t test_vreinterpretq_u64_p8(poly8x16_t a) {
return vreinterpretq_u64_p8(a);
}
-// CHECK-LABEL: define <2 x i64> @test_vreinterpretq_u64_p16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_u64_p16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <2 x i64>
// CHECK: ret <2 x i64> [[TMP0]]
uint64x2_t test_vreinterpretq_u64_p16(poly16x8_t a) {
return vreinterpretq_u64_p16(a);
}
-// CHECK-LABEL: define <8 x half> @test_vreinterpretq_f16_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f16_s8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <8 x half>
// CHECK: ret <8 x half> [[TMP0]]
float16x8_t test_vreinterpretq_f16_s8(int8x16_t a) {
return vreinterpretq_f16_s8(a);
}
-// CHECK-LABEL: define <8 x half> @test_vreinterpretq_f16_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f16_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <8 x half>
// CHECK: ret <8 x half> [[TMP0]]
float16x8_t test_vreinterpretq_f16_s16(int16x8_t a) {
return vreinterpretq_f16_s16(a);
}
-// CHECK-LABEL: define <8 x half> @test_vreinterpretq_f16_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f16_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <8 x half>
// CHECK: ret <8 x half> [[TMP0]]
float16x8_t test_vreinterpretq_f16_s32(int32x4_t a) {
return vreinterpretq_f16_s32(a);
}
-// CHECK-LABEL: define <8 x half> @test_vreinterpretq_f16_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f16_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <8 x half>
// CHECK: ret <8 x half> [[TMP0]]
float16x8_t test_vreinterpretq_f16_s64(int64x2_t a) {
return vreinterpretq_f16_s64(a);
}
-// CHECK-LABEL: define <8 x half> @test_vreinterpretq_f16_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f16_u8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <8 x half>
// CHECK: ret <8 x half> [[TMP0]]
float16x8_t test_vreinterpretq_f16_u8(uint8x16_t a) {
return vreinterpretq_f16_u8(a);
}
-// CHECK-LABEL: define <8 x half> @test_vreinterpretq_f16_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f16_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <8 x half>
// CHECK: ret <8 x half> [[TMP0]]
float16x8_t test_vreinterpretq_f16_u16(uint16x8_t a) {
return vreinterpretq_f16_u16(a);
}
-// CHECK-LABEL: define <8 x half> @test_vreinterpretq_f16_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f16_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <8 x half>
// CHECK: ret <8 x half> [[TMP0]]
float16x8_t test_vreinterpretq_f16_u32(uint32x4_t a) {
return vreinterpretq_f16_u32(a);
}
-// CHECK-LABEL: define <8 x half> @test_vreinterpretq_f16_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f16_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <8 x half>
// CHECK: ret <8 x half> [[TMP0]]
float16x8_t test_vreinterpretq_f16_u64(uint64x2_t a) {
return vreinterpretq_f16_u64(a);
}
-// CHECK-LABEL: define <8 x half> @test_vreinterpretq_f16_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f16_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <8 x half>
// CHECK: ret <8 x half> [[TMP0]]
float16x8_t test_vreinterpretq_f16_f32(float32x4_t a) {
return vreinterpretq_f16_f32(a);
}
-// CHECK-LABEL: define <8 x half> @test_vreinterpretq_f16_p8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f16_p8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <8 x half>
// CHECK: ret <8 x half> [[TMP0]]
float16x8_t test_vreinterpretq_f16_p8(poly8x16_t a) {
return vreinterpretq_f16_p8(a);
}
-// CHECK-LABEL: define <8 x half> @test_vreinterpretq_f16_p16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f16_p16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <8 x half>
// CHECK: ret <8 x half> [[TMP0]]
float16x8_t test_vreinterpretq_f16_p16(poly16x8_t a) {
return vreinterpretq_f16_p16(a);
}
-// CHECK-LABEL: define <4 x float> @test_vreinterpretq_f32_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f32_s8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <4 x float>
// CHECK: ret <4 x float> [[TMP0]]
float32x4_t test_vreinterpretq_f32_s8(int8x16_t a) {
return vreinterpretq_f32_s8(a);
}
-// CHECK-LABEL: define <4 x float> @test_vreinterpretq_f32_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f32_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <4 x float>
// CHECK: ret <4 x float> [[TMP0]]
float32x4_t test_vreinterpretq_f32_s16(int16x8_t a) {
return vreinterpretq_f32_s16(a);
}
-// CHECK-LABEL: define <4 x float> @test_vreinterpretq_f32_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f32_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <4 x float>
// CHECK: ret <4 x float> [[TMP0]]
float32x4_t test_vreinterpretq_f32_s32(int32x4_t a) {
return vreinterpretq_f32_s32(a);
}
-// CHECK-LABEL: define <4 x float> @test_vreinterpretq_f32_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f32_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <4 x float>
// CHECK: ret <4 x float> [[TMP0]]
float32x4_t test_vreinterpretq_f32_s64(int64x2_t a) {
return vreinterpretq_f32_s64(a);
}
-// CHECK-LABEL: define <4 x float> @test_vreinterpretq_f32_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f32_u8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <4 x float>
// CHECK: ret <4 x float> [[TMP0]]
float32x4_t test_vreinterpretq_f32_u8(uint8x16_t a) {
return vreinterpretq_f32_u8(a);
}
-// CHECK-LABEL: define <4 x float> @test_vreinterpretq_f32_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f32_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <4 x float>
// CHECK: ret <4 x float> [[TMP0]]
float32x4_t test_vreinterpretq_f32_u16(uint16x8_t a) {
return vreinterpretq_f32_u16(a);
}
-// CHECK-LABEL: define <4 x float> @test_vreinterpretq_f32_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f32_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <4 x float>
// CHECK: ret <4 x float> [[TMP0]]
float32x4_t test_vreinterpretq_f32_u32(uint32x4_t a) {
return vreinterpretq_f32_u32(a);
}
-// CHECK-LABEL: define <4 x float> @test_vreinterpretq_f32_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f32_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <4 x float>
// CHECK: ret <4 x float> [[TMP0]]
float32x4_t test_vreinterpretq_f32_u64(uint64x2_t a) {
return vreinterpretq_f32_u64(a);
}
-// CHECK-LABEL: define <4 x float> @test_vreinterpretq_f32_f16(<8 x half> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f32_f16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x half> %a to <4 x float>
// CHECK: ret <4 x float> [[TMP0]]
float32x4_t test_vreinterpretq_f32_f16(float16x8_t a) {
return vreinterpretq_f32_f16(a);
}
-// CHECK-LABEL: define <4 x float> @test_vreinterpretq_f32_p8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f32_p8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <4 x float>
// CHECK: ret <4 x float> [[TMP0]]
float32x4_t test_vreinterpretq_f32_p8(poly8x16_t a) {
return vreinterpretq_f32_p8(a);
}
-// CHECK-LABEL: define <4 x float> @test_vreinterpretq_f32_p16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_f32_p16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <4 x float>
// CHECK: ret <4 x float> [[TMP0]]
float32x4_t test_vreinterpretq_f32_p16(poly16x8_t a) {
return vreinterpretq_f32_p16(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_p8_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p8_s8(
// CHECK: ret <16 x i8> %a
poly8x16_t test_vreinterpretq_p8_s8(int8x16_t a) {
return vreinterpretq_p8_s8(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_p8_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p8_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
poly8x16_t test_vreinterpretq_p8_s16(int16x8_t a) {
return vreinterpretq_p8_s16(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_p8_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p8_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
poly8x16_t test_vreinterpretq_p8_s32(int32x4_t a) {
return vreinterpretq_p8_s32(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_p8_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p8_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
poly8x16_t test_vreinterpretq_p8_s64(int64x2_t a) {
return vreinterpretq_p8_s64(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_p8_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p8_u8(
// CHECK: ret <16 x i8> %a
poly8x16_t test_vreinterpretq_p8_u8(uint8x16_t a) {
return vreinterpretq_p8_u8(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_p8_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p8_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
poly8x16_t test_vreinterpretq_p8_u16(uint16x8_t a) {
return vreinterpretq_p8_u16(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_p8_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p8_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
poly8x16_t test_vreinterpretq_p8_u32(uint32x4_t a) {
return vreinterpretq_p8_u32(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_p8_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p8_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
poly8x16_t test_vreinterpretq_p8_u64(uint64x2_t a) {
return vreinterpretq_p8_u64(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_p8_f16(<8 x half> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p8_f16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x half> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
poly8x16_t test_vreinterpretq_p8_f16(float16x8_t a) {
return vreinterpretq_p8_f16(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_p8_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p8_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
poly8x16_t test_vreinterpretq_p8_f32(float32x4_t a) {
return vreinterpretq_p8_f32(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vreinterpretq_p8_p16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p8_p16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: ret <16 x i8> [[TMP0]]
poly8x16_t test_vreinterpretq_p8_p16(poly16x8_t a) {
return vreinterpretq_p8_p16(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_p16_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p16_s8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
poly16x8_t test_vreinterpretq_p16_s8(int8x16_t a) {
return vreinterpretq_p16_s8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_p16_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p16_s16(
// CHECK: ret <8 x i16> %a
poly16x8_t test_vreinterpretq_p16_s16(int16x8_t a) {
return vreinterpretq_p16_s16(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_p16_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p16_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
poly16x8_t test_vreinterpretq_p16_s32(int32x4_t a) {
return vreinterpretq_p16_s32(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_p16_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p16_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
poly16x8_t test_vreinterpretq_p16_s64(int64x2_t a) {
return vreinterpretq_p16_s64(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_p16_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p16_u8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
poly16x8_t test_vreinterpretq_p16_u8(uint8x16_t a) {
return vreinterpretq_p16_u8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_p16_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p16_u16(
// CHECK: ret <8 x i16> %a
poly16x8_t test_vreinterpretq_p16_u16(uint16x8_t a) {
return vreinterpretq_p16_u16(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_p16_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p16_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
poly16x8_t test_vreinterpretq_p16_u32(uint32x4_t a) {
return vreinterpretq_p16_u32(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_p16_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p16_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
poly16x8_t test_vreinterpretq_p16_u64(uint64x2_t a) {
return vreinterpretq_p16_u64(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_p16_f16(<8 x half> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p16_f16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x half> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
poly16x8_t test_vreinterpretq_p16_f16(float16x8_t a) {
return vreinterpretq_p16_f16(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_p16_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p16_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
poly16x8_t test_vreinterpretq_p16_f32(float32x4_t a) {
return vreinterpretq_p16_f32(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vreinterpretq_p16_p8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vreinterpretq_p16_p8(
// CHECK: [[TMP0:%.*]] = bitcast <16 x i8> %a to <8 x i16>
// CHECK: ret <8 x i16> [[TMP0]]
poly16x8_t test_vreinterpretq_p16_p8(poly8x16_t a) {
return vreinterpretq_p16_p8(a);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vrev16_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrev16_s8(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %a, <8 x i32> <i32 1, i32 0, i32 3, i32 2, i32 5, i32 4, i32 7, i32 6>
// CHECK: ret <8 x i8> [[SHUFFLE_I]]
int8x8_t test_vrev16_s8(int8x8_t a) {
return vrev16_s8(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vrev16_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrev16_u8(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %a, <8 x i32> <i32 1, i32 0, i32 3, i32 2, i32 5, i32 4, i32 7, i32 6>
// CHECK: ret <8 x i8> [[SHUFFLE_I]]
uint8x8_t test_vrev16_u8(uint8x8_t a) {
return vrev16_u8(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vrev16_p8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrev16_p8(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %a, <8 x i32> <i32 1, i32 0, i32 3, i32 2, i32 5, i32 4, i32 7, i32 6>
// CHECK: ret <8 x i8> [[SHUFFLE_I]]
poly8x8_t test_vrev16_p8(poly8x8_t a) {
return vrev16_p8(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vrev16q_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrev16q_s8(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %a, <16 x i32> <i32 1, i32 0, i32 3, i32 2, i32 5, i32 4, i32 7, i32 6, i32 9, i32 8, i32 11, i32 10, i32 13, i32 12, i32 15, i32 14>
// CHECK: ret <16 x i8> [[SHUFFLE_I]]
int8x16_t test_vrev16q_s8(int8x16_t a) {
return vrev16q_s8(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vrev16q_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrev16q_u8(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %a, <16 x i32> <i32 1, i32 0, i32 3, i32 2, i32 5, i32 4, i32 7, i32 6, i32 9, i32 8, i32 11, i32 10, i32 13, i32 12, i32 15, i32 14>
// CHECK: ret <16 x i8> [[SHUFFLE_I]]
uint8x16_t test_vrev16q_u8(uint8x16_t a) {
return vrev16q_u8(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vrev16q_p8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrev16q_p8(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %a, <16 x i32> <i32 1, i32 0, i32 3, i32 2, i32 5, i32 4, i32 7, i32 6, i32 9, i32 8, i32 11, i32 10, i32 13, i32 12, i32 15, i32 14>
// CHECK: ret <16 x i8> [[SHUFFLE_I]]
poly8x16_t test_vrev16q_p8(poly8x16_t a) {
return vrev16q_p8(a);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vrev32_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrev32_s8(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %a, <8 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4>
// CHECK: ret <8 x i8> [[SHUFFLE_I]]
int8x8_t test_vrev32_s8(int8x8_t a) {
return vrev32_s8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vrev32_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vrev32_s16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %a, <4 x i32> <i32 1, i32 0, i32 3, i32 2>
// CHECK: ret <4 x i16> [[SHUFFLE_I]]
int16x4_t test_vrev32_s16(int16x4_t a) {
return vrev32_s16(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vrev32_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrev32_u8(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %a, <8 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4>
// CHECK: ret <8 x i8> [[SHUFFLE_I]]
uint8x8_t test_vrev32_u8(uint8x8_t a) {
return vrev32_u8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vrev32_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vrev32_u16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %a, <4 x i32> <i32 1, i32 0, i32 3, i32 2>
// CHECK: ret <4 x i16> [[SHUFFLE_I]]
uint16x4_t test_vrev32_u16(uint16x4_t a) {
return vrev32_u16(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vrev32_p8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrev32_p8(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %a, <8 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4>
// CHECK: ret <8 x i8> [[SHUFFLE_I]]
poly8x8_t test_vrev32_p8(poly8x8_t a) {
return vrev32_p8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vrev32_p16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vrev32_p16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %a, <4 x i32> <i32 1, i32 0, i32 3, i32 2>
// CHECK: ret <4 x i16> [[SHUFFLE_I]]
poly16x4_t test_vrev32_p16(poly16x4_t a) {
return vrev32_p16(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vrev32q_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrev32q_s8(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %a, <16 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4, i32 11, i32 10, i32 9, i32 8, i32 15, i32 14, i32 13, i32 12>
// CHECK: ret <16 x i8> [[SHUFFLE_I]]
int8x16_t test_vrev32q_s8(int8x16_t a) {
return vrev32q_s8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vrev32q_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vrev32q_s16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %a, <8 x i32> <i32 1, i32 0, i32 3, i32 2, i32 5, i32 4, i32 7, i32 6>
// CHECK: ret <8 x i16> [[SHUFFLE_I]]
int16x8_t test_vrev32q_s16(int16x8_t a) {
return vrev32q_s16(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vrev32q_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrev32q_u8(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %a, <16 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4, i32 11, i32 10, i32 9, i32 8, i32 15, i32 14, i32 13, i32 12>
// CHECK: ret <16 x i8> [[SHUFFLE_I]]
uint8x16_t test_vrev32q_u8(uint8x16_t a) {
return vrev32q_u8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vrev32q_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vrev32q_u16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %a, <8 x i32> <i32 1, i32 0, i32 3, i32 2, i32 5, i32 4, i32 7, i32 6>
// CHECK: ret <8 x i16> [[SHUFFLE_I]]
uint16x8_t test_vrev32q_u16(uint16x8_t a) {
return vrev32q_u16(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vrev32q_p8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrev32q_p8(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %a, <16 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4, i32 11, i32 10, i32 9, i32 8, i32 15, i32 14, i32 13, i32 12>
// CHECK: ret <16 x i8> [[SHUFFLE_I]]
poly8x16_t test_vrev32q_p8(poly8x16_t a) {
return vrev32q_p8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vrev32q_p16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vrev32q_p16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %a, <8 x i32> <i32 1, i32 0, i32 3, i32 2, i32 5, i32 4, i32 7, i32 6>
// CHECK: ret <8 x i16> [[SHUFFLE_I]]
poly16x8_t test_vrev32q_p16(poly16x8_t a) {
return vrev32q_p16(a);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vrev64_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrev64_s8(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %a, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
// CHECK: ret <8 x i8> [[SHUFFLE_I]]
int8x8_t test_vrev64_s8(int8x8_t a) {
return vrev64_s8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vrev64_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vrev64_s16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %a, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
// CHECK: ret <4 x i16> [[SHUFFLE_I]]
int16x4_t test_vrev64_s16(int16x4_t a) {
return vrev64_s16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vrev64_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vrev64_s32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %a, <2 x i32> <i32 1, i32 0>
// CHECK: ret <2 x i32> [[SHUFFLE_I]]
int32x2_t test_vrev64_s32(int32x2_t a) {
return vrev64_s32(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vrev64_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrev64_u8(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %a, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
// CHECK: ret <8 x i8> [[SHUFFLE_I]]
uint8x8_t test_vrev64_u8(uint8x8_t a) {
return vrev64_u8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vrev64_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vrev64_u16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %a, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
// CHECK: ret <4 x i16> [[SHUFFLE_I]]
uint16x4_t test_vrev64_u16(uint16x4_t a) {
return vrev64_u16(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vrev64_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vrev64_u32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x i32> %a, <2 x i32> %a, <2 x i32> <i32 1, i32 0>
// CHECK: ret <2 x i32> [[SHUFFLE_I]]
uint32x2_t test_vrev64_u32(uint32x2_t a) {
return vrev64_u32(a);
}
-// CHECK-LABEL: define <8 x i8> @test_vrev64_p8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrev64_p8(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i8> %a, <8 x i8> %a, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
// CHECK: ret <8 x i8> [[SHUFFLE_I]]
poly8x8_t test_vrev64_p8(poly8x8_t a) {
return vrev64_p8(a);
}
-// CHECK-LABEL: define <4 x i16> @test_vrev64_p16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vrev64_p16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> %a, <4 x i16> %a, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
// CHECK: ret <4 x i16> [[SHUFFLE_I]]
poly16x4_t test_vrev64_p16(poly16x4_t a) {
return vrev64_p16(a);
}
-// CHECK-LABEL: define <2 x float> @test_vrev64_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vrev64_f32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <2 x float> %a, <2 x float> %a, <2 x i32> <i32 1, i32 0>
// CHECK: ret <2 x float> [[SHUFFLE_I]]
float32x2_t test_vrev64_f32(float32x2_t a) {
return vrev64_f32(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vrev64q_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrev64q_s8(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %a, <16 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0, i32 15, i32 14, i32 13, i32 12, i32 11, i32 10, i32 9, i32 8>
// CHECK: ret <16 x i8> [[SHUFFLE_I]]
int8x16_t test_vrev64q_s8(int8x16_t a) {
return vrev64q_s8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vrev64q_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vrev64q_s16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %a, <8 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4>
// CHECK: ret <8 x i16> [[SHUFFLE_I]]
int16x8_t test_vrev64q_s16(int16x8_t a) {
return vrev64q_s16(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vrev64q_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vrev64q_s32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %a, <4 x i32> <i32 1, i32 0, i32 3, i32 2>
// CHECK: ret <4 x i32> [[SHUFFLE_I]]
int32x4_t test_vrev64q_s32(int32x4_t a) {
return vrev64q_s32(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vrev64q_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrev64q_u8(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %a, <16 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0, i32 15, i32 14, i32 13, i32 12, i32 11, i32 10, i32 9, i32 8>
// CHECK: ret <16 x i8> [[SHUFFLE_I]]
uint8x16_t test_vrev64q_u8(uint8x16_t a) {
return vrev64q_u8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vrev64q_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vrev64q_u16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %a, <8 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4>
// CHECK: ret <8 x i16> [[SHUFFLE_I]]
uint16x8_t test_vrev64q_u16(uint16x8_t a) {
return vrev64q_u16(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vrev64q_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vrev64q_u32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x i32> %a, <4 x i32> %a, <4 x i32> <i32 1, i32 0, i32 3, i32 2>
// CHECK: ret <4 x i32> [[SHUFFLE_I]]
uint32x4_t test_vrev64q_u32(uint32x4_t a) {
return vrev64q_u32(a);
}
-// CHECK-LABEL: define <16 x i8> @test_vrev64q_p8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrev64q_p8(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <16 x i8> %a, <16 x i8> %a, <16 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0, i32 15, i32 14, i32 13, i32 12, i32 11, i32 10, i32 9, i32 8>
// CHECK: ret <16 x i8> [[SHUFFLE_I]]
poly8x16_t test_vrev64q_p8(poly8x16_t a) {
return vrev64q_p8(a);
}
-// CHECK-LABEL: define <8 x i16> @test_vrev64q_p16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vrev64q_p16(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i16> %a, <8 x i16> %a, <8 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4>
// CHECK: ret <8 x i16> [[SHUFFLE_I]]
poly16x8_t test_vrev64q_p16(poly16x8_t a) {
return vrev64q_p16(a);
}
-// CHECK-LABEL: define <4 x float> @test_vrev64q_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vrev64q_f32(
// CHECK: [[SHUFFLE_I:%.*]] = shufflevector <4 x float> %a, <4 x float> %a, <4 x i32> <i32 1, i32 0, i32 3, i32 2>
// CHECK: ret <4 x float> [[SHUFFLE_I]]
float32x4_t test_vrev64q_f32(float32x4_t a) {
return vrev64q_f32(a);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vrhadd_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vrhadd_s8(
// CHECK: [[VRHADD_V_I:%.*]] = call <8 x i8> @llvm.arm.neon.vrhadds.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VRHADD_V_I]]
int8x8_t test_vrhadd_s8(int8x8_t a, int8x8_t b) {
return vrhadd_s8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vrhadd_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vrhadd_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VRHADD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VRHADD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VRHADD_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vrhadds.v4i16(<4 x i16> [[VRHADD_V_I]], <4 x i16> [[VRHADD_V1_I]]) #4
+// CHECK: [[VRHADD_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vrhadds.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VRHADD_V3_I:%.*]] = bitcast <4 x i16> [[VRHADD_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRHADD_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VRHADD_V2_I]]
int16x4_t test_vrhadd_s16(int16x4_t a, int16x4_t b) {
return vrhadd_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vrhadd_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vrhadd_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VRHADD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VRHADD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VRHADD_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vrhadds.v2i32(<2 x i32> [[VRHADD_V_I]], <2 x i32> [[VRHADD_V1_I]]) #4
+// CHECK: [[VRHADD_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vrhadds.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VRHADD_V3_I:%.*]] = bitcast <2 x i32> [[VRHADD_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRHADD_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VRHADD_V2_I]]
int32x2_t test_vrhadd_s32(int32x2_t a, int32x2_t b) {
return vrhadd_s32(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vrhadd_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vrhadd_u8(
// CHECK: [[VRHADD_V_I:%.*]] = call <8 x i8> @llvm.arm.neon.vrhaddu.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VRHADD_V_I]]
uint8x8_t test_vrhadd_u8(uint8x8_t a, uint8x8_t b) {
return vrhadd_u8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vrhadd_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vrhadd_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VRHADD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VRHADD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VRHADD_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vrhaddu.v4i16(<4 x i16> [[VRHADD_V_I]], <4 x i16> [[VRHADD_V1_I]]) #4
+// CHECK: [[VRHADD_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vrhaddu.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VRHADD_V3_I:%.*]] = bitcast <4 x i16> [[VRHADD_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRHADD_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VRHADD_V2_I]]
uint16x4_t test_vrhadd_u16(uint16x4_t a, uint16x4_t b) {
return vrhadd_u16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vrhadd_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vrhadd_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VRHADD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VRHADD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VRHADD_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vrhaddu.v2i32(<2 x i32> [[VRHADD_V_I]], <2 x i32> [[VRHADD_V1_I]]) #4
+// CHECK: [[VRHADD_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vrhaddu.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VRHADD_V3_I:%.*]] = bitcast <2 x i32> [[VRHADD_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRHADD_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VRHADD_V2_I]]
uint32x2_t test_vrhadd_u32(uint32x2_t a, uint32x2_t b) {
return vrhadd_u32(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vrhaddq_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vrhaddq_s8(
// CHECK: [[VRHADDQ_V_I:%.*]] = call <16 x i8> @llvm.arm.neon.vrhadds.v16i8(<16 x i8> %a, <16 x i8> %b) #4
// CHECK: ret <16 x i8> [[VRHADDQ_V_I]]
int8x16_t test_vrhaddq_s8(int8x16_t a, int8x16_t b) {
return vrhaddq_s8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vrhaddq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vrhaddq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VRHADDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VRHADDQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VRHADDQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vrhadds.v8i16(<8 x i16> [[VRHADDQ_V_I]], <8 x i16> [[VRHADDQ_V1_I]]) #4
+// CHECK: [[VRHADDQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vrhadds.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: [[VRHADDQ_V3_I:%.*]] = bitcast <8 x i16> [[VRHADDQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VRHADDQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VRHADDQ_V2_I]]
int16x8_t test_vrhaddq_s16(int16x8_t a, int16x8_t b) {
return vrhaddq_s16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vrhaddq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vrhaddq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VRHADDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VRHADDQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VRHADDQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vrhadds.v4i32(<4 x i32> [[VRHADDQ_V_I]], <4 x i32> [[VRHADDQ_V1_I]]) #4
+// CHECK: [[VRHADDQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vrhadds.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VRHADDQ_V3_I:%.*]] = bitcast <4 x i32> [[VRHADDQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VRHADDQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VRHADDQ_V2_I]]
int32x4_t test_vrhaddq_s32(int32x4_t a, int32x4_t b) {
return vrhaddq_s32(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vrhaddq_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vrhaddq_u8(
// CHECK: [[VRHADDQ_V_I:%.*]] = call <16 x i8> @llvm.arm.neon.vrhaddu.v16i8(<16 x i8> %a, <16 x i8> %b) #4
// CHECK: ret <16 x i8> [[VRHADDQ_V_I]]
uint8x16_t test_vrhaddq_u8(uint8x16_t a, uint8x16_t b) {
return vrhaddq_u8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vrhaddq_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vrhaddq_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VRHADDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VRHADDQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VRHADDQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vrhaddu.v8i16(<8 x i16> [[VRHADDQ_V_I]], <8 x i16> [[VRHADDQ_V1_I]]) #4
+// CHECK: [[VRHADDQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vrhaddu.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: [[VRHADDQ_V3_I:%.*]] = bitcast <8 x i16> [[VRHADDQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VRHADDQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VRHADDQ_V2_I]]
uint16x8_t test_vrhaddq_u16(uint16x8_t a, uint16x8_t b) {
return vrhaddq_u16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vrhaddq_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vrhaddq_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VRHADDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VRHADDQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VRHADDQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vrhaddu.v4i32(<4 x i32> [[VRHADDQ_V_I]], <4 x i32> [[VRHADDQ_V1_I]]) #4
+// CHECK: [[VRHADDQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vrhaddu.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VRHADDQ_V3_I:%.*]] = bitcast <4 x i32> [[VRHADDQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VRHADDQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VRHADDQ_V2_I]]
uint32x4_t test_vrhaddq_u32(uint32x4_t a, uint32x4_t b) {
return vrhaddq_u32(a, b);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vrshl_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vrshl_s8(
// CHECK: [[VRSHL_V_I:%.*]] = call <8 x i8> @llvm.arm.neon.vrshifts.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VRSHL_V_I]]
int8x8_t test_vrshl_s8(int8x8_t a, int8x8_t b) {
return vrshl_s8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vrshl_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vrshl_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VRSHL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VRSHL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VRSHL_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vrshifts.v4i16(<4 x i16> [[VRSHL_V_I]], <4 x i16> [[VRSHL_V1_I]]) #4
+// CHECK: [[VRSHL_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vrshifts.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VRSHL_V3_I:%.*]] = bitcast <4 x i16> [[VRSHL_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRSHL_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VRSHL_V2_I]]
int16x4_t test_vrshl_s16(int16x4_t a, int16x4_t b) {
return vrshl_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vrshl_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vrshl_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VRSHL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VRSHL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VRSHL_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vrshifts.v2i32(<2 x i32> [[VRSHL_V_I]], <2 x i32> [[VRSHL_V1_I]]) #4
+// CHECK: [[VRSHL_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vrshifts.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VRSHL_V3_I:%.*]] = bitcast <2 x i32> [[VRSHL_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRSHL_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VRSHL_V2_I]]
int32x2_t test_vrshl_s32(int32x2_t a, int32x2_t b) {
return vrshl_s32(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vrshl_s64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vrshl_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
-// CHECK: [[VRSHL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
-// CHECK: [[VRSHL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x i64>
-// CHECK: [[VRSHL_V2_I:%.*]] = call <1 x i64> @llvm.arm.neon.vrshifts.v1i64(<1 x i64> [[VRSHL_V_I]], <1 x i64> [[VRSHL_V1_I]]) #4
+// CHECK: [[VRSHL_V2_I:%.*]] = call <1 x i64> @llvm.arm.neon.vrshifts.v1i64(<1 x i64> %a, <1 x i64> %b) #4
// CHECK: [[VRSHL_V3_I:%.*]] = bitcast <1 x i64> [[VRSHL_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRSHL_V3_I]] to <1 x i64>
-// CHECK: ret <1 x i64> [[TMP2]]
+// CHECK: ret <1 x i64> [[VRSHL_V2_I]]
int64x1_t test_vrshl_s64(int64x1_t a, int64x1_t b) {
return vrshl_s64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vrshl_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vrshl_u8(
// CHECK: [[VRSHL_V_I:%.*]] = call <8 x i8> @llvm.arm.neon.vrshiftu.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VRSHL_V_I]]
uint8x8_t test_vrshl_u8(uint8x8_t a, int8x8_t b) {
return vrshl_u8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vrshl_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vrshl_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VRSHL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VRSHL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VRSHL_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vrshiftu.v4i16(<4 x i16> [[VRSHL_V_I]], <4 x i16> [[VRSHL_V1_I]]) #4
+// CHECK: [[VRSHL_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vrshiftu.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VRSHL_V3_I:%.*]] = bitcast <4 x i16> [[VRSHL_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRSHL_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VRSHL_V2_I]]
uint16x4_t test_vrshl_u16(uint16x4_t a, int16x4_t b) {
return vrshl_u16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vrshl_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vrshl_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VRSHL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VRSHL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VRSHL_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vrshiftu.v2i32(<2 x i32> [[VRSHL_V_I]], <2 x i32> [[VRSHL_V1_I]]) #4
+// CHECK: [[VRSHL_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vrshiftu.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VRSHL_V3_I:%.*]] = bitcast <2 x i32> [[VRSHL_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRSHL_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VRSHL_V2_I]]
uint32x2_t test_vrshl_u32(uint32x2_t a, int32x2_t b) {
return vrshl_u32(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vrshl_u64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vrshl_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
-// CHECK: [[VRSHL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
-// CHECK: [[VRSHL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x i64>
-// CHECK: [[VRSHL_V2_I:%.*]] = call <1 x i64> @llvm.arm.neon.vrshiftu.v1i64(<1 x i64> [[VRSHL_V_I]], <1 x i64> [[VRSHL_V1_I]]) #4
+// CHECK: [[VRSHL_V2_I:%.*]] = call <1 x i64> @llvm.arm.neon.vrshiftu.v1i64(<1 x i64> %a, <1 x i64> %b) #4
// CHECK: [[VRSHL_V3_I:%.*]] = bitcast <1 x i64> [[VRSHL_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRSHL_V3_I]] to <1 x i64>
-// CHECK: ret <1 x i64> [[TMP2]]
+// CHECK: ret <1 x i64> [[VRSHL_V2_I]]
uint64x1_t test_vrshl_u64(uint64x1_t a, int64x1_t b) {
return vrshl_u64(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vrshlq_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vrshlq_s8(
// CHECK: [[VRSHLQ_V_I:%.*]] = call <16 x i8> @llvm.arm.neon.vrshifts.v16i8(<16 x i8> %a, <16 x i8> %b) #4
// CHECK: ret <16 x i8> [[VRSHLQ_V_I]]
int8x16_t test_vrshlq_s8(int8x16_t a, int8x16_t b) {
return vrshlq_s8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vrshlq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vrshlq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VRSHLQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VRSHLQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VRSHLQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vrshifts.v8i16(<8 x i16> [[VRSHLQ_V_I]], <8 x i16> [[VRSHLQ_V1_I]]) #4
+// CHECK: [[VRSHLQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vrshifts.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: [[VRSHLQ_V3_I:%.*]] = bitcast <8 x i16> [[VRSHLQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VRSHLQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VRSHLQ_V2_I]]
int16x8_t test_vrshlq_s16(int16x8_t a, int16x8_t b) {
return vrshlq_s16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vrshlq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vrshlq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VRSHLQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VRSHLQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VRSHLQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vrshifts.v4i32(<4 x i32> [[VRSHLQ_V_I]], <4 x i32> [[VRSHLQ_V1_I]]) #4
+// CHECK: [[VRSHLQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vrshifts.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VRSHLQ_V3_I:%.*]] = bitcast <4 x i32> [[VRSHLQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VRSHLQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VRSHLQ_V2_I]]
int32x4_t test_vrshlq_s32(int32x4_t a, int32x4_t b) {
return vrshlq_s32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vrshlq_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vrshlq_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[VRSHLQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VRSHLQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VRSHLQ_V2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vrshifts.v2i64(<2 x i64> [[VRSHLQ_V_I]], <2 x i64> [[VRSHLQ_V1_I]]) #4
+// CHECK: [[VRSHLQ_V2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vrshifts.v2i64(<2 x i64> %a, <2 x i64> %b) #4
// CHECK: [[VRSHLQ_V3_I:%.*]] = bitcast <2 x i64> [[VRSHLQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VRSHLQ_V3_I]] to <2 x i64>
-// CHECK: ret <2 x i64> [[TMP2]]
+// CHECK: ret <2 x i64> [[VRSHLQ_V2_I]]
int64x2_t test_vrshlq_s64(int64x2_t a, int64x2_t b) {
return vrshlq_s64(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vrshlq_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vrshlq_u8(
// CHECK: [[VRSHLQ_V_I:%.*]] = call <16 x i8> @llvm.arm.neon.vrshiftu.v16i8(<16 x i8> %a, <16 x i8> %b) #4
// CHECK: ret <16 x i8> [[VRSHLQ_V_I]]
uint8x16_t test_vrshlq_u8(uint8x16_t a, int8x16_t b) {
return vrshlq_u8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vrshlq_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vrshlq_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VRSHLQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VRSHLQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VRSHLQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vrshiftu.v8i16(<8 x i16> [[VRSHLQ_V_I]], <8 x i16> [[VRSHLQ_V1_I]]) #4
+// CHECK: [[VRSHLQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vrshiftu.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: [[VRSHLQ_V3_I:%.*]] = bitcast <8 x i16> [[VRSHLQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VRSHLQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VRSHLQ_V2_I]]
uint16x8_t test_vrshlq_u16(uint16x8_t a, int16x8_t b) {
return vrshlq_u16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vrshlq_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vrshlq_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VRSHLQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VRSHLQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VRSHLQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vrshiftu.v4i32(<4 x i32> [[VRSHLQ_V_I]], <4 x i32> [[VRSHLQ_V1_I]]) #4
+// CHECK: [[VRSHLQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vrshiftu.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VRSHLQ_V3_I:%.*]] = bitcast <4 x i32> [[VRSHLQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VRSHLQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VRSHLQ_V2_I]]
uint32x4_t test_vrshlq_u32(uint32x4_t a, int32x4_t b) {
return vrshlq_u32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vrshlq_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vrshlq_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[VRSHLQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VRSHLQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VRSHLQ_V2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vrshiftu.v2i64(<2 x i64> [[VRSHLQ_V_I]], <2 x i64> [[VRSHLQ_V1_I]]) #4
+// CHECK: [[VRSHLQ_V2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vrshiftu.v2i64(<2 x i64> %a, <2 x i64> %b) #4
// CHECK: [[VRSHLQ_V3_I:%.*]] = bitcast <2 x i64> [[VRSHLQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VRSHLQ_V3_I]] to <2 x i64>
-// CHECK: ret <2 x i64> [[TMP2]]
+// CHECK: ret <2 x i64> [[VRSHLQ_V2_I]]
uint64x2_t test_vrshlq_u64(uint64x2_t a, int64x2_t b) {
return vrshlq_u64(a, b);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vrshrn_n_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vrshrn_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[VRSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VRSHRN_N1:%.*]] = call <8 x i8> @llvm.arm.neon.vrshiftn.v8i8(<8 x i16> [[VRSHRN_N]], <8 x i16> <i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1>)
@@ -16066,7 +13907,7 @@ int8x8_t test_vrshrn_n_s16(int16x8_t a) {
return vrshrn_n_s16(a, 1);
}
-// CHECK-LABEL: define <4 x i16> @test_vrshrn_n_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vrshrn_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[VRSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VRSHRN_N1:%.*]] = call <4 x i16> @llvm.arm.neon.vrshiftn.v4i16(<4 x i32> [[VRSHRN_N]], <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>)
@@ -16075,7 +13916,7 @@ int16x4_t test_vrshrn_n_s32(int32x4_t a) {
return vrshrn_n_s32(a, 1);
}
-// CHECK-LABEL: define <2 x i32> @test_vrshrn_n_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vrshrn_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[VRSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VRSHRN_N1:%.*]] = call <2 x i32> @llvm.arm.neon.vrshiftn.v2i32(<2 x i64> [[VRSHRN_N]], <2 x i64> <i64 -1, i64 -1>)
@@ -16084,7 +13925,7 @@ int32x2_t test_vrshrn_n_s64(int64x2_t a) {
return vrshrn_n_s64(a, 1);
}
-// CHECK-LABEL: define <8 x i8> @test_vrshrn_n_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vrshrn_n_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[VRSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VRSHRN_N1:%.*]] = call <8 x i8> @llvm.arm.neon.vrshiftn.v8i8(<8 x i16> [[VRSHRN_N]], <8 x i16> <i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1>)
@@ -16093,7 +13934,7 @@ uint8x8_t test_vrshrn_n_u16(uint16x8_t a) {
return vrshrn_n_u16(a, 1);
}
-// CHECK-LABEL: define <4 x i16> @test_vrshrn_n_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vrshrn_n_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[VRSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VRSHRN_N1:%.*]] = call <4 x i16> @llvm.arm.neon.vrshiftn.v4i16(<4 x i32> [[VRSHRN_N]], <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>)
@@ -16102,7 +13943,7 @@ uint16x4_t test_vrshrn_n_u32(uint32x4_t a) {
return vrshrn_n_u32(a, 1);
}
-// CHECK-LABEL: define <2 x i32> @test_vrshrn_n_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vrshrn_n_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[VRSHRN_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VRSHRN_N1:%.*]] = call <2 x i32> @llvm.arm.neon.vrshiftn.v2i32(<2 x i64> [[VRSHRN_N]], <2 x i64> <i64 -1, i64 -1>)
@@ -16111,15 +13952,14 @@ uint32x2_t test_vrshrn_n_u64(uint64x2_t a) {
return vrshrn_n_u64(a, 1);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vrshr_n_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrshr_n_s8(
// CHECK: [[VRSHR_N:%.*]] = call <8 x i8> @llvm.arm.neon.vrshifts.v8i8(<8 x i8> %a, <8 x i8> <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>)
// CHECK: ret <8 x i8> [[VRSHR_N]]
int8x8_t test_vrshr_n_s8(int8x8_t a) {
return vrshr_n_s8(a, 1);
}
-// CHECK-LABEL: define <4 x i16> @test_vrshr_n_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vrshr_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[VRSHR_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
// CHECK: [[VRSHR_N1:%.*]] = call <4 x i16> @llvm.arm.neon.vrshifts.v4i16(<4 x i16> [[VRSHR_N]], <4 x i16> <i16 -1, i16 -1, i16 -1, i16 -1>)
@@ -16128,7 +13968,7 @@ int16x4_t test_vrshr_n_s16(int16x4_t a) {
return vrshr_n_s16(a, 1);
}
-// CHECK-LABEL: define <2 x i32> @test_vrshr_n_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vrshr_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[VRSHR_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
// CHECK: [[VRSHR_N1:%.*]] = call <2 x i32> @llvm.arm.neon.vrshifts.v2i32(<2 x i32> [[VRSHR_N]], <2 x i32> <i32 -1, i32 -1>)
@@ -16137,7 +13977,7 @@ int32x2_t test_vrshr_n_s32(int32x2_t a) {
return vrshr_n_s32(a, 1);
}
-// CHECK-LABEL: define <1 x i64> @test_vrshr_n_s64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vrshr_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[VRSHR_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
// CHECK: [[VRSHR_N1:%.*]] = call <1 x i64> @llvm.arm.neon.vrshifts.v1i64(<1 x i64> [[VRSHR_N]], <1 x i64> <i64 -1>)
@@ -16146,14 +13986,14 @@ int64x1_t test_vrshr_n_s64(int64x1_t a) {
return vrshr_n_s64(a, 1);
}
-// CHECK-LABEL: define <8 x i8> @test_vrshr_n_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrshr_n_u8(
// CHECK: [[VRSHR_N:%.*]] = call <8 x i8> @llvm.arm.neon.vrshiftu.v8i8(<8 x i8> %a, <8 x i8> <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>)
// CHECK: ret <8 x i8> [[VRSHR_N]]
uint8x8_t test_vrshr_n_u8(uint8x8_t a) {
return vrshr_n_u8(a, 1);
}
-// CHECK-LABEL: define <4 x i16> @test_vrshr_n_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vrshr_n_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[VRSHR_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
// CHECK: [[VRSHR_N1:%.*]] = call <4 x i16> @llvm.arm.neon.vrshiftu.v4i16(<4 x i16> [[VRSHR_N]], <4 x i16> <i16 -1, i16 -1, i16 -1, i16 -1>)
@@ -16162,7 +14002,7 @@ uint16x4_t test_vrshr_n_u16(uint16x4_t a) {
return vrshr_n_u16(a, 1);
}
-// CHECK-LABEL: define <2 x i32> @test_vrshr_n_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vrshr_n_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[VRSHR_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
// CHECK: [[VRSHR_N1:%.*]] = call <2 x i32> @llvm.arm.neon.vrshiftu.v2i32(<2 x i32> [[VRSHR_N]], <2 x i32> <i32 -1, i32 -1>)
@@ -16171,7 +14011,7 @@ uint32x2_t test_vrshr_n_u32(uint32x2_t a) {
return vrshr_n_u32(a, 1);
}
-// CHECK-LABEL: define <1 x i64> @test_vrshr_n_u64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vrshr_n_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[VRSHR_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
// CHECK: [[VRSHR_N1:%.*]] = call <1 x i64> @llvm.arm.neon.vrshiftu.v1i64(<1 x i64> [[VRSHR_N]], <1 x i64> <i64 -1>)
@@ -16180,14 +14020,14 @@ uint64x1_t test_vrshr_n_u64(uint64x1_t a) {
return vrshr_n_u64(a, 1);
}
-// CHECK-LABEL: define <16 x i8> @test_vrshrq_n_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrshrq_n_s8(
// CHECK: [[VRSHR_N:%.*]] = call <16 x i8> @llvm.arm.neon.vrshifts.v16i8(<16 x i8> %a, <16 x i8> <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>)
// CHECK: ret <16 x i8> [[VRSHR_N]]
int8x16_t test_vrshrq_n_s8(int8x16_t a) {
return vrshrq_n_s8(a, 1);
}
-// CHECK-LABEL: define <8 x i16> @test_vrshrq_n_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vrshrq_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[VRSHR_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VRSHR_N1:%.*]] = call <8 x i16> @llvm.arm.neon.vrshifts.v8i16(<8 x i16> [[VRSHR_N]], <8 x i16> <i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1>)
@@ -16196,7 +14036,7 @@ int16x8_t test_vrshrq_n_s16(int16x8_t a) {
return vrshrq_n_s16(a, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vrshrq_n_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vrshrq_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[VRSHR_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VRSHR_N1:%.*]] = call <4 x i32> @llvm.arm.neon.vrshifts.v4i32(<4 x i32> [[VRSHR_N]], <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>)
@@ -16205,7 +14045,7 @@ int32x4_t test_vrshrq_n_s32(int32x4_t a) {
return vrshrq_n_s32(a, 1);
}
-// CHECK-LABEL: define <2 x i64> @test_vrshrq_n_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vrshrq_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[VRSHR_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VRSHR_N1:%.*]] = call <2 x i64> @llvm.arm.neon.vrshifts.v2i64(<2 x i64> [[VRSHR_N]], <2 x i64> <i64 -1, i64 -1>)
@@ -16214,14 +14054,14 @@ int64x2_t test_vrshrq_n_s64(int64x2_t a) {
return vrshrq_n_s64(a, 1);
}
-// CHECK-LABEL: define <16 x i8> @test_vrshrq_n_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vrshrq_n_u8(
// CHECK: [[VRSHR_N:%.*]] = call <16 x i8> @llvm.arm.neon.vrshiftu.v16i8(<16 x i8> %a, <16 x i8> <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>)
// CHECK: ret <16 x i8> [[VRSHR_N]]
uint8x16_t test_vrshrq_n_u8(uint8x16_t a) {
return vrshrq_n_u8(a, 1);
}
-// CHECK-LABEL: define <8 x i16> @test_vrshrq_n_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vrshrq_n_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[VRSHR_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VRSHR_N1:%.*]] = call <8 x i16> @llvm.arm.neon.vrshiftu.v8i16(<8 x i16> [[VRSHR_N]], <8 x i16> <i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1>)
@@ -16230,7 +14070,7 @@ uint16x8_t test_vrshrq_n_u16(uint16x8_t a) {
return vrshrq_n_u16(a, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vrshrq_n_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vrshrq_n_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[VRSHR_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VRSHR_N1:%.*]] = call <4 x i32> @llvm.arm.neon.vrshiftu.v4i32(<4 x i32> [[VRSHR_N]], <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>)
@@ -16239,7 +14079,7 @@ uint32x4_t test_vrshrq_n_u32(uint32x4_t a) {
return vrshrq_n_u32(a, 1);
}
-// CHECK-LABEL: define <2 x i64> @test_vrshrq_n_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vrshrq_n_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[VRSHR_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VRSHR_N1:%.*]] = call <2 x i64> @llvm.arm.neon.vrshiftu.v2i64(<2 x i64> [[VRSHR_N]], <2 x i64> <i64 -1, i64 -1>)
@@ -16248,72 +14088,59 @@ uint64x2_t test_vrshrq_n_u64(uint64x2_t a) {
return vrshrq_n_u64(a, 1);
}
-
-// CHECK-LABEL: define <2 x float> @test_vrsqrte_f32(<2 x float> %a) #0 {
+// CHECK-LABEL: @test_vrsqrte_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
-// CHECK: [[VRSQRTE_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VRSQRTE_V1_I:%.*]] = call <2 x float> @llvm.arm.neon.vrsqrte.v2f32(<2 x float> [[VRSQRTE_V_I]]) #4
+// CHECK: [[VRSQRTE_V1_I:%.*]] = call <2 x float> @llvm.arm.neon.vrsqrte.v2f32(<2 x float> %a) #4
// CHECK: ret <2 x float> [[VRSQRTE_V1_I]]
float32x2_t test_vrsqrte_f32(float32x2_t a) {
return vrsqrte_f32(a);
}
-// CHECK-LABEL: define <2 x i32> @test_vrsqrte_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vrsqrte_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[VRSQRTE_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VRSQRTE_V1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vrsqrte.v2i32(<2 x i32> [[VRSQRTE_V_I]]) #4
+// CHECK: [[VRSQRTE_V1_I:%.*]] = call <2 x i32> @llvm.arm.neon.vrsqrte.v2i32(<2 x i32> %a) #4
// CHECK: ret <2 x i32> [[VRSQRTE_V1_I]]
uint32x2_t test_vrsqrte_u32(uint32x2_t a) {
return vrsqrte_u32(a);
}
-// CHECK-LABEL: define <4 x float> @test_vrsqrteq_f32(<4 x float> %a) #0 {
+// CHECK-LABEL: @test_vrsqrteq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
-// CHECK: [[VRSQRTEQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VRSQRTEQ_V1_I:%.*]] = call <4 x float> @llvm.arm.neon.vrsqrte.v4f32(<4 x float> [[VRSQRTEQ_V_I]]) #4
+// CHECK: [[VRSQRTEQ_V1_I:%.*]] = call <4 x float> @llvm.arm.neon.vrsqrte.v4f32(<4 x float> %a) #4
// CHECK: ret <4 x float> [[VRSQRTEQ_V1_I]]
float32x4_t test_vrsqrteq_f32(float32x4_t a) {
return vrsqrteq_f32(a);
}
-// CHECK-LABEL: define <4 x i32> @test_vrsqrteq_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vrsqrteq_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
-// CHECK: [[VRSQRTEQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VRSQRTEQ_V1_I:%.*]] = call <4 x i32> @llvm.arm.neon.vrsqrte.v4i32(<4 x i32> [[VRSQRTEQ_V_I]]) #4
+// CHECK: [[VRSQRTEQ_V1_I:%.*]] = call <4 x i32> @llvm.arm.neon.vrsqrte.v4i32(<4 x i32> %a) #4
// CHECK: ret <4 x i32> [[VRSQRTEQ_V1_I]]
uint32x4_t test_vrsqrteq_u32(uint32x4_t a) {
return vrsqrteq_u32(a);
}
-
-// CHECK-LABEL: define <2 x float> @test_vrsqrts_f32(<2 x float> %a, <2 x float> %b) #0 {
+// CHECK-LABEL: @test_vrsqrts_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %b to <8 x i8>
-// CHECK: [[VRSQRTS_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
-// CHECK: [[VRSQRTS_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK: [[VRSQRTS_V2_I:%.*]] = call <2 x float> @llvm.arm.neon.vrsqrts.v2f32(<2 x float> [[VRSQRTS_V_I]], <2 x float> [[VRSQRTS_V1_I]]) #4
+// CHECK: [[VRSQRTS_V2_I:%.*]] = call <2 x float> @llvm.arm.neon.vrsqrts.v2f32(<2 x float> %a, <2 x float> %b) #4
// CHECK: [[VRSQRTS_V3_I:%.*]] = bitcast <2 x float> [[VRSQRTS_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRSQRTS_V3_I]] to <2 x float>
-// CHECK: ret <2 x float> [[TMP2]]
+// CHECK: ret <2 x float> [[VRSQRTS_V2_I]]
float32x2_t test_vrsqrts_f32(float32x2_t a, float32x2_t b) {
return vrsqrts_f32(a, b);
}
-// CHECK-LABEL: define <4 x float> @test_vrsqrtsq_f32(<4 x float> %a, <4 x float> %b) #0 {
+// CHECK-LABEL: @test_vrsqrtsq_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %b to <16 x i8>
-// CHECK: [[VRSQRTSQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
-// CHECK: [[VRSQRTSQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
-// CHECK: [[VRSQRTSQ_V2_I:%.*]] = call <4 x float> @llvm.arm.neon.vrsqrts.v4f32(<4 x float> [[VRSQRTSQ_V_I]], <4 x float> [[VRSQRTSQ_V1_I]]) #4
+// CHECK: [[VRSQRTSQ_V2_I:%.*]] = call <4 x float> @llvm.arm.neon.vrsqrts.v4f32(<4 x float> %a, <4 x float> %b) #4
// CHECK: [[VRSQRTSQ_V3_I:%.*]] = bitcast <4 x float> [[VRSQRTSQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VRSQRTSQ_V3_I]] to <4 x float>
-// CHECK: ret <4 x float> [[TMP2]]
+// CHECK: ret <4 x float> [[VRSQRTSQ_V2_I]]
float32x4_t test_vrsqrtsq_f32(float32x4_t a, float32x4_t b) {
return vrsqrtsq_f32(a, b);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vrsra_n_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vrsra_n_s8(
// CHECK: [[TMP0:%.*]] = call <8 x i8> @llvm.arm.neon.vrshifts.v8i8(<8 x i8> %b, <8 x i8> <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>)
// CHECK: [[VRSRA_N:%.*]] = add <8 x i8> %a, [[TMP0]]
// CHECK: ret <8 x i8> [[VRSRA_N]]
@@ -16321,7 +14148,7 @@ int8x8_t test_vrsra_n_s8(int8x8_t a, int8x8_t b) {
return vrsra_n_s8(a, b, 1);
}
-// CHECK-LABEL: define <4 x i16> @test_vrsra_n_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vrsra_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
@@ -16333,7 +14160,7 @@ int16x4_t test_vrsra_n_s16(int16x4_t a, int16x4_t b) {
return vrsra_n_s16(a, b, 1);
}
-// CHECK-LABEL: define <2 x i32> @test_vrsra_n_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vrsra_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
@@ -16345,7 +14172,7 @@ int32x2_t test_vrsra_n_s32(int32x2_t a, int32x2_t b) {
return vrsra_n_s32(a, b, 1);
}
-// CHECK-LABEL: define <1 x i64> @test_vrsra_n_s64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vrsra_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
@@ -16357,7 +14184,7 @@ int64x1_t test_vrsra_n_s64(int64x1_t a, int64x1_t b) {
return vrsra_n_s64(a, b, 1);
}
-// CHECK-LABEL: define <8 x i8> @test_vrsra_n_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vrsra_n_u8(
// CHECK: [[TMP0:%.*]] = call <8 x i8> @llvm.arm.neon.vrshiftu.v8i8(<8 x i8> %b, <8 x i8> <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>)
// CHECK: [[VRSRA_N:%.*]] = add <8 x i8> %a, [[TMP0]]
// CHECK: ret <8 x i8> [[VRSRA_N]]
@@ -16365,7 +14192,7 @@ uint8x8_t test_vrsra_n_u8(uint8x8_t a, uint8x8_t b) {
return vrsra_n_u8(a, b, 1);
}
-// CHECK-LABEL: define <4 x i16> @test_vrsra_n_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vrsra_n_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
@@ -16377,7 +14204,7 @@ uint16x4_t test_vrsra_n_u16(uint16x4_t a, uint16x4_t b) {
return vrsra_n_u16(a, b, 1);
}
-// CHECK-LABEL: define <2 x i32> @test_vrsra_n_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vrsra_n_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
@@ -16389,7 +14216,7 @@ uint32x2_t test_vrsra_n_u32(uint32x2_t a, uint32x2_t b) {
return vrsra_n_u32(a, b, 1);
}
-// CHECK-LABEL: define <1 x i64> @test_vrsra_n_u64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vrsra_n_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
@@ -16401,7 +14228,7 @@ uint64x1_t test_vrsra_n_u64(uint64x1_t a, uint64x1_t b) {
return vrsra_n_u64(a, b, 1);
}
-// CHECK-LABEL: define <16 x i8> @test_vrsraq_n_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vrsraq_n_s8(
// CHECK: [[TMP0:%.*]] = call <16 x i8> @llvm.arm.neon.vrshifts.v16i8(<16 x i8> %b, <16 x i8> <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>)
// CHECK: [[VRSRA_N:%.*]] = add <16 x i8> %a, [[TMP0]]
// CHECK: ret <16 x i8> [[VRSRA_N]]
@@ -16409,7 +14236,7 @@ int8x16_t test_vrsraq_n_s8(int8x16_t a, int8x16_t b) {
return vrsraq_n_s8(a, b, 1);
}
-// CHECK-LABEL: define <8 x i16> @test_vrsraq_n_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vrsraq_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
@@ -16421,7 +14248,7 @@ int16x8_t test_vrsraq_n_s16(int16x8_t a, int16x8_t b) {
return vrsraq_n_s16(a, b, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vrsraq_n_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vrsraq_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
@@ -16433,7 +14260,7 @@ int32x4_t test_vrsraq_n_s32(int32x4_t a, int32x4_t b) {
return vrsraq_n_s32(a, b, 1);
}
-// CHECK-LABEL: define <2 x i64> @test_vrsraq_n_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vrsraq_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
@@ -16445,7 +14272,7 @@ int64x2_t test_vrsraq_n_s64(int64x2_t a, int64x2_t b) {
return vrsraq_n_s64(a, b, 1);
}
-// CHECK-LABEL: define <16 x i8> @test_vrsraq_n_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vrsraq_n_u8(
// CHECK: [[TMP0:%.*]] = call <16 x i8> @llvm.arm.neon.vrshiftu.v16i8(<16 x i8> %b, <16 x i8> <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>)
// CHECK: [[VRSRA_N:%.*]] = add <16 x i8> %a, [[TMP0]]
// CHECK: ret <16 x i8> [[VRSRA_N]]
@@ -16453,7 +14280,7 @@ uint8x16_t test_vrsraq_n_u8(uint8x16_t a, uint8x16_t b) {
return vrsraq_n_u8(a, b, 1);
}
-// CHECK-LABEL: define <8 x i16> @test_vrsraq_n_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vrsraq_n_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
@@ -16465,7 +14292,7 @@ uint16x8_t test_vrsraq_n_u16(uint16x8_t a, uint16x8_t b) {
return vrsraq_n_u16(a, b, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vrsraq_n_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vrsraq_n_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
@@ -16477,7 +14304,7 @@ uint32x4_t test_vrsraq_n_u32(uint32x4_t a, uint32x4_t b) {
return vrsraq_n_u32(a, b, 1);
}
-// CHECK-LABEL: define <2 x i64> @test_vrsraq_n_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vrsraq_n_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
@@ -16489,90 +14316,72 @@ uint64x2_t test_vrsraq_n_u64(uint64x2_t a, uint64x2_t b) {
return vrsraq_n_u64(a, b, 1);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vrsubhn_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vrsubhn_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VRSUBHN_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VRSUBHN_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VRSUBHN_V2_I:%.*]] = call <8 x i8> @llvm.arm.neon.vrsubhn.v8i8(<8 x i16> [[VRSUBHN_V_I]], <8 x i16> [[VRSUBHN_V1_I]]) #4
+// CHECK: [[VRSUBHN_V2_I:%.*]] = call <8 x i8> @llvm.arm.neon.vrsubhn.v8i8(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: ret <8 x i8> [[VRSUBHN_V2_I]]
int8x8_t test_vrsubhn_s16(int16x8_t a, int16x8_t b) {
return vrsubhn_s16(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vrsubhn_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vrsubhn_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VRSUBHN_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VRSUBHN_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VRSUBHN_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vrsubhn.v4i16(<4 x i32> [[VRSUBHN_V_I]], <4 x i32> [[VRSUBHN_V1_I]]) #4
+// CHECK: [[VRSUBHN_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vrsubhn.v4i16(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VRSUBHN_V3_I:%.*]] = bitcast <4 x i16> [[VRSUBHN_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRSUBHN_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VRSUBHN_V2_I]]
int16x4_t test_vrsubhn_s32(int32x4_t a, int32x4_t b) {
return vrsubhn_s32(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vrsubhn_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vrsubhn_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[VRSUBHN_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VRSUBHN_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VRSUBHN_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vrsubhn.v2i32(<2 x i64> [[VRSUBHN_V_I]], <2 x i64> [[VRSUBHN_V1_I]]) #4
+// CHECK: [[VRSUBHN_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vrsubhn.v2i32(<2 x i64> %a, <2 x i64> %b) #4
// CHECK: [[VRSUBHN_V3_I:%.*]] = bitcast <2 x i32> [[VRSUBHN_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRSUBHN_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VRSUBHN_V2_I]]
int32x2_t test_vrsubhn_s64(int64x2_t a, int64x2_t b) {
return vrsubhn_s64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vrsubhn_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vrsubhn_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VRSUBHN_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VRSUBHN_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VRSUBHN_V2_I:%.*]] = call <8 x i8> @llvm.arm.neon.vrsubhn.v8i8(<8 x i16> [[VRSUBHN_V_I]], <8 x i16> [[VRSUBHN_V1_I]]) #4
+// CHECK: [[VRSUBHN_V2_I:%.*]] = call <8 x i8> @llvm.arm.neon.vrsubhn.v8i8(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: ret <8 x i8> [[VRSUBHN_V2_I]]
uint8x8_t test_vrsubhn_u16(uint16x8_t a, uint16x8_t b) {
return vrsubhn_u16(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vrsubhn_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vrsubhn_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VRSUBHN_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VRSUBHN_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VRSUBHN_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vrsubhn.v4i16(<4 x i32> [[VRSUBHN_V_I]], <4 x i32> [[VRSUBHN_V1_I]]) #4
+// CHECK: [[VRSUBHN_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vrsubhn.v4i16(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VRSUBHN_V3_I:%.*]] = bitcast <4 x i16> [[VRSUBHN_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRSUBHN_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VRSUBHN_V2_I]]
uint16x4_t test_vrsubhn_u32(uint32x4_t a, uint32x4_t b) {
return vrsubhn_u32(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vrsubhn_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vrsubhn_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[VRSUBHN_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VRSUBHN_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VRSUBHN_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vrsubhn.v2i32(<2 x i64> [[VRSUBHN_V_I]], <2 x i64> [[VRSUBHN_V1_I]]) #4
+// CHECK: [[VRSUBHN_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vrsubhn.v2i32(<2 x i64> %a, <2 x i64> %b) #4
// CHECK: [[VRSUBHN_V3_I:%.*]] = bitcast <2 x i32> [[VRSUBHN_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VRSUBHN_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VRSUBHN_V2_I]]
uint32x2_t test_vrsubhn_u64(uint64x2_t a, uint64x2_t b) {
return vrsubhn_u64(a, b);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vset_lane_u8(i8 zeroext %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vset_lane_u8(
// CHECK: [[VSET_LANE:%.*]] = insertelement <8 x i8> %b, i8 %a, i32 7
// CHECK: ret <8 x i8> [[VSET_LANE]]
uint8x8_t test_vset_lane_u8(uint8_t a, uint8x8_t b) {
return vset_lane_u8(a, b, 7);
}
-// CHECK-LABEL: define <4 x i16> @test_vset_lane_u16(i16 zeroext %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vset_lane_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
// CHECK: [[VSET_LANE:%.*]] = insertelement <4 x i16> [[TMP1]], i16 %a, i32 3
@@ -16581,7 +14390,7 @@ uint16x4_t test_vset_lane_u16(uint16_t a, uint16x4_t b) {
return vset_lane_u16(a, b, 3);
}
-// CHECK-LABEL: define <2 x i32> @test_vset_lane_u32(i32 %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vset_lane_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
// CHECK: [[VSET_LANE:%.*]] = insertelement <2 x i32> [[TMP1]], i32 %a, i32 1
@@ -16590,14 +14399,14 @@ uint32x2_t test_vset_lane_u32(uint32_t a, uint32x2_t b) {
return vset_lane_u32(a, b, 1);
}
-// CHECK-LABEL: define <8 x i8> @test_vset_lane_s8(i8 signext %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vset_lane_s8(
// CHECK: [[VSET_LANE:%.*]] = insertelement <8 x i8> %b, i8 %a, i32 7
// CHECK: ret <8 x i8> [[VSET_LANE]]
int8x8_t test_vset_lane_s8(int8_t a, int8x8_t b) {
return vset_lane_s8(a, b, 7);
}
-// CHECK-LABEL: define <4 x i16> @test_vset_lane_s16(i16 signext %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vset_lane_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
// CHECK: [[VSET_LANE:%.*]] = insertelement <4 x i16> [[TMP1]], i16 %a, i32 3
@@ -16606,7 +14415,7 @@ int16x4_t test_vset_lane_s16(int16_t a, int16x4_t b) {
return vset_lane_s16(a, b, 3);
}
-// CHECK-LABEL: define <2 x i32> @test_vset_lane_s32(i32 %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vset_lane_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
// CHECK: [[VSET_LANE:%.*]] = insertelement <2 x i32> [[TMP1]], i32 %a, i32 1
@@ -16615,14 +14424,14 @@ int32x2_t test_vset_lane_s32(int32_t a, int32x2_t b) {
return vset_lane_s32(a, b, 1);
}
-// CHECK-LABEL: define <8 x i8> @test_vset_lane_p8(i8 signext %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vset_lane_p8(
// CHECK: [[VSET_LANE:%.*]] = insertelement <8 x i8> %b, i8 %a, i32 7
// CHECK: ret <8 x i8> [[VSET_LANE]]
poly8x8_t test_vset_lane_p8(poly8_t a, poly8x8_t b) {
return vset_lane_p8(a, b, 7);
}
-// CHECK-LABEL: define <4 x i16> @test_vset_lane_p16(i16 signext %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vset_lane_p16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
// CHECK: [[VSET_LANE:%.*]] = insertelement <4 x i16> [[TMP1]], i16 %a, i32 3
@@ -16631,7 +14440,7 @@ poly16x4_t test_vset_lane_p16(poly16_t a, poly16x4_t b) {
return vset_lane_p16(a, b, 3);
}
-// CHECK-LABEL: define <2 x float> @test_vset_lane_f32(float %a, <2 x float> %b) #0 {
+// CHECK-LABEL: @test_vset_lane_f32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x float> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x float>
// CHECK: [[VSET_LANE:%.*]] = insertelement <2 x float> [[TMP1]], float %a, i32 1
@@ -16640,7 +14449,7 @@ float32x2_t test_vset_lane_f32(float32_t a, float32x2_t b) {
return vset_lane_f32(a, b, 1);
}
-// CHECK-LABEL: define <4 x half> @test_vset_lane_f16(half* %a, <4 x half> %b) #0 {
+// CHECK-LABEL: @test_vset_lane_f16(
// CHECK: [[__REINT_246:%.*]] = alloca half, align 2
// CHECK: [[__REINT1_246:%.*]] = alloca <4 x half>, align 8
// CHECK: [[__REINT2_246:%.*]] = alloca <4 x i16>, align 8
@@ -16662,14 +14471,14 @@ float16x4_t test_vset_lane_f16(float16_t *a, float16x4_t b) {
return vset_lane_f16(*a, b, 1);
}
-// CHECK-LABEL: define <16 x i8> @test_vsetq_lane_u8(i8 zeroext %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsetq_lane_u8(
// CHECK: [[VSET_LANE:%.*]] = insertelement <16 x i8> %b, i8 %a, i32 15
// CHECK: ret <16 x i8> [[VSET_LANE]]
uint8x16_t test_vsetq_lane_u8(uint8_t a, uint8x16_t b) {
return vsetq_lane_u8(a, b, 15);
}
-// CHECK-LABEL: define <8 x i16> @test_vsetq_lane_u16(i16 zeroext %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsetq_lane_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VSET_LANE:%.*]] = insertelement <8 x i16> [[TMP1]], i16 %a, i32 7
@@ -16678,7 +14487,7 @@ uint16x8_t test_vsetq_lane_u16(uint16_t a, uint16x8_t b) {
return vsetq_lane_u16(a, b, 7);
}
-// CHECK-LABEL: define <4 x i32> @test_vsetq_lane_u32(i32 %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsetq_lane_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VSET_LANE:%.*]] = insertelement <4 x i32> [[TMP1]], i32 %a, i32 3
@@ -16687,14 +14496,14 @@ uint32x4_t test_vsetq_lane_u32(uint32_t a, uint32x4_t b) {
return vsetq_lane_u32(a, b, 3);
}
-// CHECK-LABEL: define <16 x i8> @test_vsetq_lane_s8(i8 signext %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsetq_lane_s8(
// CHECK: [[VSET_LANE:%.*]] = insertelement <16 x i8> %b, i8 %a, i32 15
// CHECK: ret <16 x i8> [[VSET_LANE]]
int8x16_t test_vsetq_lane_s8(int8_t a, int8x16_t b) {
return vsetq_lane_s8(a, b, 15);
}
-// CHECK-LABEL: define <8 x i16> @test_vsetq_lane_s16(i16 signext %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsetq_lane_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VSET_LANE:%.*]] = insertelement <8 x i16> [[TMP1]], i16 %a, i32 7
@@ -16703,7 +14512,7 @@ int16x8_t test_vsetq_lane_s16(int16_t a, int16x8_t b) {
return vsetq_lane_s16(a, b, 7);
}
-// CHECK-LABEL: define <4 x i32> @test_vsetq_lane_s32(i32 %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsetq_lane_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VSET_LANE:%.*]] = insertelement <4 x i32> [[TMP1]], i32 %a, i32 3
@@ -16712,14 +14521,14 @@ int32x4_t test_vsetq_lane_s32(int32_t a, int32x4_t b) {
return vsetq_lane_s32(a, b, 3);
}
-// CHECK-LABEL: define <16 x i8> @test_vsetq_lane_p8(i8 signext %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsetq_lane_p8(
// CHECK: [[VSET_LANE:%.*]] = insertelement <16 x i8> %b, i8 %a, i32 15
// CHECK: ret <16 x i8> [[VSET_LANE]]
poly8x16_t test_vsetq_lane_p8(poly8_t a, poly8x16_t b) {
return vsetq_lane_p8(a, b, 15);
}
-// CHECK-LABEL: define <8 x i16> @test_vsetq_lane_p16(i16 signext %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsetq_lane_p16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VSET_LANE:%.*]] = insertelement <8 x i16> [[TMP1]], i16 %a, i32 7
@@ -16728,7 +14537,7 @@ poly16x8_t test_vsetq_lane_p16(poly16_t a, poly16x8_t b) {
return vsetq_lane_p16(a, b, 7);
}
-// CHECK-LABEL: define <4 x float> @test_vsetq_lane_f32(float %a, <4 x float> %b) #0 {
+// CHECK-LABEL: @test_vsetq_lane_f32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x float> %b to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x float>
// CHECK: [[VSET_LANE:%.*]] = insertelement <4 x float> [[TMP1]], float %a, i32 3
@@ -16737,7 +14546,7 @@ float32x4_t test_vsetq_lane_f32(float32_t a, float32x4_t b) {
return vsetq_lane_f32(a, b, 3);
}
-// CHECK-LABEL: define <8 x half> @test_vsetq_lane_f16(half* %a, <8 x half> %b) #0 {
+// CHECK-LABEL: @test_vsetq_lane_f16(
// CHECK: [[__REINT_248:%.*]] = alloca half, align 2
// CHECK: [[__REINT1_248:%.*]] = alloca <8 x half>, align 16
// CHECK: [[__REINT2_248:%.*]] = alloca <8 x i16>, align 16
@@ -16759,8 +14568,7 @@ float16x8_t test_vsetq_lane_f16(float16_t *a, float16x8_t b) {
return vsetq_lane_f16(*a, b, 3);
}
-// The optimizer is able to get rid of all moves now.
-// CHECK-LABEL: define <1 x i64> @test_vset_lane_s64(i64 %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vset_lane_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
// CHECK: [[VSET_LANE:%.*]] = insertelement <1 x i64> [[TMP1]], i64 %a, i32 0
@@ -16769,8 +14577,7 @@ int64x1_t test_vset_lane_s64(int64_t a, int64x1_t b) {
return vset_lane_s64(a, b, 0);
}
-// The optimizer is able to get rid of all moves now.
-// CHECK-LABEL: define <1 x i64> @test_vset_lane_u64(i64 %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vset_lane_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %b to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
// CHECK: [[VSET_LANE:%.*]] = insertelement <1 x i64> [[TMP1]], i64 %a, i32 0
@@ -16779,7 +14586,7 @@ uint64x1_t test_vset_lane_u64(uint64_t a, uint64x1_t b) {
return vset_lane_u64(a, b, 0);
}
-// CHECK-LABEL: define <2 x i64> @test_vsetq_lane_s64(i64 %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vsetq_lane_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %b to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VSET_LANE:%.*]] = insertelement <2 x i64> [[TMP1]], i64 %a, i32 1
@@ -16788,7 +14595,7 @@ int64x2_t test_vsetq_lane_s64(int64_t a, int64x2_t b) {
return vsetq_lane_s64(a, b, 1);
}
-// CHECK-LABEL: define <2 x i64> @test_vsetq_lane_u64(i64 %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vsetq_lane_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %b to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VSET_LANE:%.*]] = insertelement <2 x i64> [[TMP1]], i64 %a, i32 1
@@ -16797,193 +14604,155 @@ uint64x2_t test_vsetq_lane_u64(uint64_t a, uint64x2_t b) {
return vsetq_lane_u64(a, b, 1);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vshl_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vshl_s8(
// CHECK: [[VSHL_V_I:%.*]] = call <8 x i8> @llvm.arm.neon.vshifts.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VSHL_V_I]]
int8x8_t test_vshl_s8(int8x8_t a, int8x8_t b) {
return vshl_s8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vshl_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vshl_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VSHL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VSHL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VSHL_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vshifts.v4i16(<4 x i16> [[VSHL_V_I]], <4 x i16> [[VSHL_V1_I]]) #4
+// CHECK: [[VSHL_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vshifts.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VSHL_V3_I:%.*]] = bitcast <4 x i16> [[VSHL_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VSHL_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VSHL_V2_I]]
int16x4_t test_vshl_s16(int16x4_t a, int16x4_t b) {
return vshl_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vshl_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vshl_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VSHL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VSHL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VSHL_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vshifts.v2i32(<2 x i32> [[VSHL_V_I]], <2 x i32> [[VSHL_V1_I]]) #4
+// CHECK: [[VSHL_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vshifts.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VSHL_V3_I:%.*]] = bitcast <2 x i32> [[VSHL_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VSHL_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VSHL_V2_I]]
int32x2_t test_vshl_s32(int32x2_t a, int32x2_t b) {
return vshl_s32(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vshl_s64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vshl_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
-// CHECK: [[VSHL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
-// CHECK: [[VSHL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x i64>
-// CHECK: [[VSHL_V2_I:%.*]] = call <1 x i64> @llvm.arm.neon.vshifts.v1i64(<1 x i64> [[VSHL_V_I]], <1 x i64> [[VSHL_V1_I]]) #4
+// CHECK: [[VSHL_V2_I:%.*]] = call <1 x i64> @llvm.arm.neon.vshifts.v1i64(<1 x i64> %a, <1 x i64> %b) #4
// CHECK: [[VSHL_V3_I:%.*]] = bitcast <1 x i64> [[VSHL_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VSHL_V3_I]] to <1 x i64>
-// CHECK: ret <1 x i64> [[TMP2]]
+// CHECK: ret <1 x i64> [[VSHL_V2_I]]
int64x1_t test_vshl_s64(int64x1_t a, int64x1_t b) {
return vshl_s64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vshl_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vshl_u8(
// CHECK: [[VSHL_V_I:%.*]] = call <8 x i8> @llvm.arm.neon.vshiftu.v8i8(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VSHL_V_I]]
uint8x8_t test_vshl_u8(uint8x8_t a, int8x8_t b) {
return vshl_u8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vshl_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vshl_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[VSHL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VSHL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[VSHL_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vshiftu.v4i16(<4 x i16> [[VSHL_V_I]], <4 x i16> [[VSHL_V1_I]]) #4
+// CHECK: [[VSHL_V2_I:%.*]] = call <4 x i16> @llvm.arm.neon.vshiftu.v4i16(<4 x i16> %a, <4 x i16> %b) #4
// CHECK: [[VSHL_V3_I:%.*]] = bitcast <4 x i16> [[VSHL_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VSHL_V3_I]] to <4 x i16>
-// CHECK: ret <4 x i16> [[TMP2]]
+// CHECK: ret <4 x i16> [[VSHL_V2_I]]
uint16x4_t test_vshl_u16(uint16x4_t a, int16x4_t b) {
return vshl_u16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vshl_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vshl_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[VSHL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VSHL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[VSHL_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vshiftu.v2i32(<2 x i32> [[VSHL_V_I]], <2 x i32> [[VSHL_V1_I]]) #4
+// CHECK: [[VSHL_V2_I:%.*]] = call <2 x i32> @llvm.arm.neon.vshiftu.v2i32(<2 x i32> %a, <2 x i32> %b) #4
// CHECK: [[VSHL_V3_I:%.*]] = bitcast <2 x i32> [[VSHL_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VSHL_V3_I]] to <2 x i32>
-// CHECK: ret <2 x i32> [[TMP2]]
+// CHECK: ret <2 x i32> [[VSHL_V2_I]]
uint32x2_t test_vshl_u32(uint32x2_t a, int32x2_t b) {
return vshl_u32(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vshl_u64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vshl_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
-// CHECK: [[VSHL_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
-// CHECK: [[VSHL_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x i64>
-// CHECK: [[VSHL_V2_I:%.*]] = call <1 x i64> @llvm.arm.neon.vshiftu.v1i64(<1 x i64> [[VSHL_V_I]], <1 x i64> [[VSHL_V1_I]]) #4
+// CHECK: [[VSHL_V2_I:%.*]] = call <1 x i64> @llvm.arm.neon.vshiftu.v1i64(<1 x i64> %a, <1 x i64> %b) #4
// CHECK: [[VSHL_V3_I:%.*]] = bitcast <1 x i64> [[VSHL_V2_I]] to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[VSHL_V3_I]] to <1 x i64>
-// CHECK: ret <1 x i64> [[TMP2]]
+// CHECK: ret <1 x i64> [[VSHL_V2_I]]
uint64x1_t test_vshl_u64(uint64x1_t a, int64x1_t b) {
return vshl_u64(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vshlq_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vshlq_s8(
// CHECK: [[VSHLQ_V_I:%.*]] = call <16 x i8> @llvm.arm.neon.vshifts.v16i8(<16 x i8> %a, <16 x i8> %b) #4
// CHECK: ret <16 x i8> [[VSHLQ_V_I]]
int8x16_t test_vshlq_s8(int8x16_t a, int8x16_t b) {
return vshlq_s8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vshlq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vshlq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VSHLQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VSHLQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VSHLQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vshifts.v8i16(<8 x i16> [[VSHLQ_V_I]], <8 x i16> [[VSHLQ_V1_I]]) #4
+// CHECK: [[VSHLQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vshifts.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: [[VSHLQ_V3_I:%.*]] = bitcast <8 x i16> [[VSHLQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VSHLQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VSHLQ_V2_I]]
int16x8_t test_vshlq_s16(int16x8_t a, int16x8_t b) {
return vshlq_s16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vshlq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vshlq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VSHLQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VSHLQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VSHLQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vshifts.v4i32(<4 x i32> [[VSHLQ_V_I]], <4 x i32> [[VSHLQ_V1_I]]) #4
+// CHECK: [[VSHLQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vshifts.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VSHLQ_V3_I:%.*]] = bitcast <4 x i32> [[VSHLQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VSHLQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VSHLQ_V2_I]]
int32x4_t test_vshlq_s32(int32x4_t a, int32x4_t b) {
return vshlq_s32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vshlq_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vshlq_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[VSHLQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VSHLQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VSHLQ_V2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vshifts.v2i64(<2 x i64> [[VSHLQ_V_I]], <2 x i64> [[VSHLQ_V1_I]]) #4
+// CHECK: [[VSHLQ_V2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vshifts.v2i64(<2 x i64> %a, <2 x i64> %b) #4
// CHECK: [[VSHLQ_V3_I:%.*]] = bitcast <2 x i64> [[VSHLQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VSHLQ_V3_I]] to <2 x i64>
-// CHECK: ret <2 x i64> [[TMP2]]
+// CHECK: ret <2 x i64> [[VSHLQ_V2_I]]
int64x2_t test_vshlq_s64(int64x2_t a, int64x2_t b) {
return vshlq_s64(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vshlq_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vshlq_u8(
// CHECK: [[VSHLQ_V_I:%.*]] = call <16 x i8> @llvm.arm.neon.vshiftu.v16i8(<16 x i8> %a, <16 x i8> %b) #4
// CHECK: ret <16 x i8> [[VSHLQ_V_I]]
uint8x16_t test_vshlq_u8(uint8x16_t a, int8x16_t b) {
return vshlq_u8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vshlq_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vshlq_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[VSHLQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[VSHLQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VSHLQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vshiftu.v8i16(<8 x i16> [[VSHLQ_V_I]], <8 x i16> [[VSHLQ_V1_I]]) #4
+// CHECK: [[VSHLQ_V2_I:%.*]] = call <8 x i16> @llvm.arm.neon.vshiftu.v8i16(<8 x i16> %a, <8 x i16> %b) #4
// CHECK: [[VSHLQ_V3_I:%.*]] = bitcast <8 x i16> [[VSHLQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VSHLQ_V3_I]] to <8 x i16>
-// CHECK: ret <8 x i16> [[TMP2]]
+// CHECK: ret <8 x i16> [[VSHLQ_V2_I]]
uint16x8_t test_vshlq_u16(uint16x8_t a, int16x8_t b) {
return vshlq_u16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vshlq_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vshlq_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[VSHLQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[VSHLQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VSHLQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vshiftu.v4i32(<4 x i32> [[VSHLQ_V_I]], <4 x i32> [[VSHLQ_V1_I]]) #4
+// CHECK: [[VSHLQ_V2_I:%.*]] = call <4 x i32> @llvm.arm.neon.vshiftu.v4i32(<4 x i32> %a, <4 x i32> %b) #4
// CHECK: [[VSHLQ_V3_I:%.*]] = bitcast <4 x i32> [[VSHLQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VSHLQ_V3_I]] to <4 x i32>
-// CHECK: ret <4 x i32> [[TMP2]]
+// CHECK: ret <4 x i32> [[VSHLQ_V2_I]]
uint32x4_t test_vshlq_u32(uint32x4_t a, int32x4_t b) {
return vshlq_u32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vshlq_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vshlq_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[VSHLQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[VSHLQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VSHLQ_V2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vshiftu.v2i64(<2 x i64> [[VSHLQ_V_I]], <2 x i64> [[VSHLQ_V1_I]]) #4
+// CHECK: [[VSHLQ_V2_I:%.*]] = call <2 x i64> @llvm.arm.neon.vshiftu.v2i64(<2 x i64> %a, <2 x i64> %b) #4
// CHECK: [[VSHLQ_V3_I:%.*]] = bitcast <2 x i64> [[VSHLQ_V2_I]] to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[VSHLQ_V3_I]] to <2 x i64>
-// CHECK: ret <2 x i64> [[TMP2]]
+// CHECK: ret <2 x i64> [[VSHLQ_V2_I]]
uint64x2_t test_vshlq_u64(uint64x2_t a, int64x2_t b) {
return vshlq_u64(a, b);
}
-
-// CHECK-LABEL: define <8 x i16> @test_vshll_n_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vshll_n_s8(
// CHECK: [[TMP0:%.*]] = sext <8 x i8> %a to <8 x i16>
// CHECK: [[VSHLL_N:%.*]] = shl <8 x i16> [[TMP0]], <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>
// CHECK: ret <8 x i16> [[VSHLL_N]]
@@ -16991,7 +14760,7 @@ int16x8_t test_vshll_n_s8(int8x8_t a) {
return vshll_n_s8(a, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vshll_n_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vshll_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
// CHECK: [[TMP2:%.*]] = sext <4 x i16> [[TMP1]] to <4 x i32>
@@ -17001,7 +14770,7 @@ int32x4_t test_vshll_n_s16(int16x4_t a) {
return vshll_n_s16(a, 1);
}
-// CHECK-LABEL: define <2 x i64> @test_vshll_n_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vshll_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
// CHECK: [[TMP2:%.*]] = sext <2 x i32> [[TMP1]] to <2 x i64>
@@ -17011,7 +14780,7 @@ int64x2_t test_vshll_n_s32(int32x2_t a) {
return vshll_n_s32(a, 1);
}
-// CHECK-LABEL: define <8 x i16> @test_vshll_n_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vshll_n_u8(
// CHECK: [[TMP0:%.*]] = zext <8 x i8> %a to <8 x i16>
// CHECK: [[VSHLL_N:%.*]] = shl <8 x i16> [[TMP0]], <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>
// CHECK: ret <8 x i16> [[VSHLL_N]]
@@ -17019,7 +14788,7 @@ uint16x8_t test_vshll_n_u8(uint8x8_t a) {
return vshll_n_u8(a, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vshll_n_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vshll_n_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
// CHECK: [[TMP2:%.*]] = zext <4 x i16> [[TMP1]] to <4 x i32>
@@ -17029,7 +14798,7 @@ uint32x4_t test_vshll_n_u16(uint16x4_t a) {
return vshll_n_u16(a, 1);
}
-// CHECK-LABEL: define <2 x i64> @test_vshll_n_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vshll_n_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
// CHECK: [[TMP2:%.*]] = zext <2 x i32> [[TMP1]] to <2 x i64>
@@ -17039,15 +14808,14 @@ uint64x2_t test_vshll_n_u32(uint32x2_t a) {
return vshll_n_u32(a, 1);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vshl_n_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vshl_n_s8(
// CHECK: [[VSHL_N:%.*]] = shl <8 x i8> %a, <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1>
// CHECK: ret <8 x i8> [[VSHL_N]]
int8x8_t test_vshl_n_s8(int8x8_t a) {
return vshl_n_s8(a, 1);
}
-// CHECK-LABEL: define <4 x i16> @test_vshl_n_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vshl_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
// CHECK: [[VSHL_N:%.*]] = shl <4 x i16> [[TMP1]], <i16 1, i16 1, i16 1, i16 1>
@@ -17056,7 +14824,7 @@ int16x4_t test_vshl_n_s16(int16x4_t a) {
return vshl_n_s16(a, 1);
}
-// CHECK-LABEL: define <2 x i32> @test_vshl_n_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vshl_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
// CHECK: [[VSHL_N:%.*]] = shl <2 x i32> [[TMP1]], <i32 1, i32 1>
@@ -17065,7 +14833,7 @@ int32x2_t test_vshl_n_s32(int32x2_t a) {
return vshl_n_s32(a, 1);
}
-// CHECK-LABEL: define <1 x i64> @test_vshl_n_s64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vshl_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
// CHECK: [[VSHL_N:%.*]] = shl <1 x i64> [[TMP1]], <i64 1>
@@ -17074,14 +14842,14 @@ int64x1_t test_vshl_n_s64(int64x1_t a) {
return vshl_n_s64(a, 1);
}
-// CHECK-LABEL: define <8 x i8> @test_vshl_n_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vshl_n_u8(
// CHECK: [[VSHL_N:%.*]] = shl <8 x i8> %a, <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1>
// CHECK: ret <8 x i8> [[VSHL_N]]
uint8x8_t test_vshl_n_u8(uint8x8_t a) {
return vshl_n_u8(a, 1);
}
-// CHECK-LABEL: define <4 x i16> @test_vshl_n_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vshl_n_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
// CHECK: [[VSHL_N:%.*]] = shl <4 x i16> [[TMP1]], <i16 1, i16 1, i16 1, i16 1>
@@ -17090,7 +14858,7 @@ uint16x4_t test_vshl_n_u16(uint16x4_t a) {
return vshl_n_u16(a, 1);
}
-// CHECK-LABEL: define <2 x i32> @test_vshl_n_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vshl_n_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
// CHECK: [[VSHL_N:%.*]] = shl <2 x i32> [[TMP1]], <i32 1, i32 1>
@@ -17099,7 +14867,7 @@ uint32x2_t test_vshl_n_u32(uint32x2_t a) {
return vshl_n_u32(a, 1);
}
-// CHECK-LABEL: define <1 x i64> @test_vshl_n_u64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vshl_n_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
// CHECK: [[VSHL_N:%.*]] = shl <1 x i64> [[TMP1]], <i64 1>
@@ -17108,14 +14876,14 @@ uint64x1_t test_vshl_n_u64(uint64x1_t a) {
return vshl_n_u64(a, 1);
}
-// CHECK-LABEL: define <16 x i8> @test_vshlq_n_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vshlq_n_s8(
// CHECK: [[VSHL_N:%.*]] = shl <16 x i8> %a, <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1>
// CHECK: ret <16 x i8> [[VSHL_N]]
int8x16_t test_vshlq_n_s8(int8x16_t a) {
return vshlq_n_s8(a, 1);
}
-// CHECK-LABEL: define <8 x i16> @test_vshlq_n_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vshlq_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VSHL_N:%.*]] = shl <8 x i16> [[TMP1]], <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>
@@ -17124,7 +14892,7 @@ int16x8_t test_vshlq_n_s16(int16x8_t a) {
return vshlq_n_s16(a, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vshlq_n_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vshlq_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VSHL_N:%.*]] = shl <4 x i32> [[TMP1]], <i32 1, i32 1, i32 1, i32 1>
@@ -17133,7 +14901,7 @@ int32x4_t test_vshlq_n_s32(int32x4_t a) {
return vshlq_n_s32(a, 1);
}
-// CHECK-LABEL: define <2 x i64> @test_vshlq_n_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vshlq_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VSHL_N:%.*]] = shl <2 x i64> [[TMP1]], <i64 1, i64 1>
@@ -17142,14 +14910,14 @@ int64x2_t test_vshlq_n_s64(int64x2_t a) {
return vshlq_n_s64(a, 1);
}
-// CHECK-LABEL: define <16 x i8> @test_vshlq_n_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vshlq_n_u8(
// CHECK: [[VSHL_N:%.*]] = shl <16 x i8> %a, <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1>
// CHECK: ret <16 x i8> [[VSHL_N]]
uint8x16_t test_vshlq_n_u8(uint8x16_t a) {
return vshlq_n_u8(a, 1);
}
-// CHECK-LABEL: define <8 x i16> @test_vshlq_n_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vshlq_n_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VSHL_N:%.*]] = shl <8 x i16> [[TMP1]], <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>
@@ -17158,7 +14926,7 @@ uint16x8_t test_vshlq_n_u16(uint16x8_t a) {
return vshlq_n_u16(a, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vshlq_n_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vshlq_n_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VSHL_N:%.*]] = shl <4 x i32> [[TMP1]], <i32 1, i32 1, i32 1, i32 1>
@@ -17167,7 +14935,7 @@ uint32x4_t test_vshlq_n_u32(uint32x4_t a) {
return vshlq_n_u32(a, 1);
}
-// CHECK-LABEL: define <2 x i64> @test_vshlq_n_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vshlq_n_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VSHL_N:%.*]] = shl <2 x i64> [[TMP1]], <i64 1, i64 1>
@@ -17176,8 +14944,7 @@ uint64x2_t test_vshlq_n_u64(uint64x2_t a) {
return vshlq_n_u64(a, 1);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vshrn_n_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vshrn_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[TMP2:%.*]] = ashr <8 x i16> [[TMP1]], <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>
@@ -17187,7 +14954,7 @@ int8x8_t test_vshrn_n_s16(int16x8_t a) {
return vshrn_n_s16(a, 1);
}
-// CHECK-LABEL: define <4 x i16> @test_vshrn_n_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vshrn_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[TMP2:%.*]] = ashr <4 x i32> [[TMP1]], <i32 1, i32 1, i32 1, i32 1>
@@ -17197,7 +14964,7 @@ int16x4_t test_vshrn_n_s32(int32x4_t a) {
return vshrn_n_s32(a, 1);
}
-// CHECK-LABEL: define <2 x i32> @test_vshrn_n_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vshrn_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[TMP2:%.*]] = ashr <2 x i64> [[TMP1]], <i64 1, i64 1>
@@ -17207,7 +14974,7 @@ int32x2_t test_vshrn_n_s64(int64x2_t a) {
return vshrn_n_s64(a, 1);
}
-// CHECK-LABEL: define <8 x i8> @test_vshrn_n_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vshrn_n_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[TMP2:%.*]] = lshr <8 x i16> [[TMP1]], <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>
@@ -17217,7 +14984,7 @@ uint8x8_t test_vshrn_n_u16(uint16x8_t a) {
return vshrn_n_u16(a, 1);
}
-// CHECK-LABEL: define <4 x i16> @test_vshrn_n_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vshrn_n_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[TMP2:%.*]] = lshr <4 x i32> [[TMP1]], <i32 1, i32 1, i32 1, i32 1>
@@ -17227,7 +14994,7 @@ uint16x4_t test_vshrn_n_u32(uint32x4_t a) {
return vshrn_n_u32(a, 1);
}
-// CHECK-LABEL: define <2 x i32> @test_vshrn_n_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vshrn_n_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[TMP2:%.*]] = lshr <2 x i64> [[TMP1]], <i64 1, i64 1>
@@ -17237,15 +15004,14 @@ uint32x2_t test_vshrn_n_u64(uint64x2_t a) {
return vshrn_n_u64(a, 1);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vshr_n_s8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vshr_n_s8(
// CHECK: [[VSHR_N:%.*]] = ashr <8 x i8> %a, <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1>
// CHECK: ret <8 x i8> [[VSHR_N]]
int8x8_t test_vshr_n_s8(int8x8_t a) {
return vshr_n_s8(a, 1);
}
-// CHECK-LABEL: define <4 x i16> @test_vshr_n_s16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vshr_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
// CHECK: [[VSHR_N:%.*]] = ashr <4 x i16> [[TMP1]], <i16 1, i16 1, i16 1, i16 1>
@@ -17254,7 +15020,7 @@ int16x4_t test_vshr_n_s16(int16x4_t a) {
return vshr_n_s16(a, 1);
}
-// CHECK-LABEL: define <2 x i32> @test_vshr_n_s32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vshr_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
// CHECK: [[VSHR_N:%.*]] = ashr <2 x i32> [[TMP1]], <i32 1, i32 1>
@@ -17263,7 +15029,7 @@ int32x2_t test_vshr_n_s32(int32x2_t a) {
return vshr_n_s32(a, 1);
}
-// CHECK-LABEL: define <1 x i64> @test_vshr_n_s64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vshr_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
// CHECK: [[VSHR_N:%.*]] = ashr <1 x i64> [[TMP1]], <i64 1>
@@ -17272,14 +15038,14 @@ int64x1_t test_vshr_n_s64(int64x1_t a) {
return vshr_n_s64(a, 1);
}
-// CHECK-LABEL: define <8 x i8> @test_vshr_n_u8(<8 x i8> %a) #0 {
+// CHECK-LABEL: @test_vshr_n_u8(
// CHECK: [[VSHR_N:%.*]] = lshr <8 x i8> %a, <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1>
// CHECK: ret <8 x i8> [[VSHR_N]]
uint8x8_t test_vshr_n_u8(uint8x8_t a) {
return vshr_n_u8(a, 1);
}
-// CHECK-LABEL: define <4 x i16> @test_vshr_n_u16(<4 x i16> %a) #0 {
+// CHECK-LABEL: @test_vshr_n_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
// CHECK: [[VSHR_N:%.*]] = lshr <4 x i16> [[TMP1]], <i16 1, i16 1, i16 1, i16 1>
@@ -17288,7 +15054,7 @@ uint16x4_t test_vshr_n_u16(uint16x4_t a) {
return vshr_n_u16(a, 1);
}
-// CHECK-LABEL: define <2 x i32> @test_vshr_n_u32(<2 x i32> %a) #0 {
+// CHECK-LABEL: @test_vshr_n_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
// CHECK: [[VSHR_N:%.*]] = lshr <2 x i32> [[TMP1]], <i32 1, i32 1>
@@ -17297,7 +15063,7 @@ uint32x2_t test_vshr_n_u32(uint32x2_t a) {
return vshr_n_u32(a, 1);
}
-// CHECK-LABEL: define <1 x i64> @test_vshr_n_u64(<1 x i64> %a) #0 {
+// CHECK-LABEL: @test_vshr_n_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
// CHECK: [[VSHR_N:%.*]] = lshr <1 x i64> [[TMP1]], <i64 1>
@@ -17306,14 +15072,14 @@ uint64x1_t test_vshr_n_u64(uint64x1_t a) {
return vshr_n_u64(a, 1);
}
-// CHECK-LABEL: define <16 x i8> @test_vshrq_n_s8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vshrq_n_s8(
// CHECK: [[VSHR_N:%.*]] = ashr <16 x i8> %a, <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1>
// CHECK: ret <16 x i8> [[VSHR_N]]
int8x16_t test_vshrq_n_s8(int8x16_t a) {
return vshrq_n_s8(a, 1);
}
-// CHECK-LABEL: define <8 x i16> @test_vshrq_n_s16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vshrq_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VSHR_N:%.*]] = ashr <8 x i16> [[TMP1]], <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>
@@ -17322,7 +15088,7 @@ int16x8_t test_vshrq_n_s16(int16x8_t a) {
return vshrq_n_s16(a, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vshrq_n_s32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vshrq_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VSHR_N:%.*]] = ashr <4 x i32> [[TMP1]], <i32 1, i32 1, i32 1, i32 1>
@@ -17331,7 +15097,7 @@ int32x4_t test_vshrq_n_s32(int32x4_t a) {
return vshrq_n_s32(a, 1);
}
-// CHECK-LABEL: define <2 x i64> @test_vshrq_n_s64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vshrq_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VSHR_N:%.*]] = ashr <2 x i64> [[TMP1]], <i64 1, i64 1>
@@ -17340,14 +15106,14 @@ int64x2_t test_vshrq_n_s64(int64x2_t a) {
return vshrq_n_s64(a, 1);
}
-// CHECK-LABEL: define <16 x i8> @test_vshrq_n_u8(<16 x i8> %a) #0 {
+// CHECK-LABEL: @test_vshrq_n_u8(
// CHECK: [[VSHR_N:%.*]] = lshr <16 x i8> %a, <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1>
// CHECK: ret <16 x i8> [[VSHR_N]]
uint8x16_t test_vshrq_n_u8(uint8x16_t a) {
return vshrq_n_u8(a, 1);
}
-// CHECK-LABEL: define <8 x i16> @test_vshrq_n_u16(<8 x i16> %a) #0 {
+// CHECK-LABEL: @test_vshrq_n_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
// CHECK: [[VSHR_N:%.*]] = lshr <8 x i16> [[TMP1]], <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>
@@ -17356,7 +15122,7 @@ uint16x8_t test_vshrq_n_u16(uint16x8_t a) {
return vshrq_n_u16(a, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vshrq_n_u32(<4 x i32> %a) #0 {
+// CHECK-LABEL: @test_vshrq_n_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
// CHECK: [[VSHR_N:%.*]] = lshr <4 x i32> [[TMP1]], <i32 1, i32 1, i32 1, i32 1>
@@ -17365,7 +15131,7 @@ uint32x4_t test_vshrq_n_u32(uint32x4_t a) {
return vshrq_n_u32(a, 1);
}
-// CHECK-LABEL: define <2 x i64> @test_vshrq_n_u64(<2 x i64> %a) #0 {
+// CHECK-LABEL: @test_vshrq_n_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
// CHECK: [[VSHR_N:%.*]] = lshr <2 x i64> [[TMP1]], <i64 1, i64 1>
@@ -17374,15 +15140,14 @@ uint64x2_t test_vshrq_n_u64(uint64x2_t a) {
return vshrq_n_u64(a, 1);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vsli_n_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsli_n_s8(
// CHECK: [[VSLI_N:%.*]] = call <8 x i8> @llvm.arm.neon.vshiftins.v8i8(<8 x i8> %a, <8 x i8> %b, <8 x i8> <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1>)
// CHECK: ret <8 x i8> [[VSLI_N]]
int8x8_t test_vsli_n_s8(int8x8_t a, int8x8_t b) {
return vsli_n_s8(a, b, 1);
}
-// CHECK-LABEL: define <4 x i16> @test_vsli_n_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsli_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[VSLI_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
@@ -17393,7 +15158,7 @@ int16x4_t test_vsli_n_s16(int16x4_t a, int16x4_t b) {
return vsli_n_s16(a, b, 1);
}
-// CHECK-LABEL: define <2 x i32> @test_vsli_n_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsli_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[VSLI_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
@@ -17404,7 +15169,7 @@ int32x2_t test_vsli_n_s32(int32x2_t a, int32x2_t b) {
return vsli_n_s32(a, b, 1);
}
-// CHECK-LABEL: define <1 x i64> @test_vsli_n_s64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vsli_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
// CHECK: [[VSLI_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
@@ -17415,14 +15180,14 @@ int64x1_t test_vsli_n_s64(int64x1_t a, int64x1_t b) {
return vsli_n_s64(a, b, 1);
}
-// CHECK-LABEL: define <8 x i8> @test_vsli_n_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsli_n_u8(
// CHECK: [[VSLI_N:%.*]] = call <8 x i8> @llvm.arm.neon.vshiftins.v8i8(<8 x i8> %a, <8 x i8> %b, <8 x i8> <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1>)
// CHECK: ret <8 x i8> [[VSLI_N]]
uint8x8_t test_vsli_n_u8(uint8x8_t a, uint8x8_t b) {
return vsli_n_u8(a, b, 1);
}
-// CHECK-LABEL: define <4 x i16> @test_vsli_n_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsli_n_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[VSLI_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
@@ -17433,7 +15198,7 @@ uint16x4_t test_vsli_n_u16(uint16x4_t a, uint16x4_t b) {
return vsli_n_u16(a, b, 1);
}
-// CHECK-LABEL: define <2 x i32> @test_vsli_n_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsli_n_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[VSLI_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
@@ -17444,7 +15209,7 @@ uint32x2_t test_vsli_n_u32(uint32x2_t a, uint32x2_t b) {
return vsli_n_u32(a, b, 1);
}
-// CHECK-LABEL: define <1 x i64> @test_vsli_n_u64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vsli_n_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
// CHECK: [[VSLI_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
@@ -17455,14 +15220,14 @@ uint64x1_t test_vsli_n_u64(uint64x1_t a, uint64x1_t b) {
return vsli_n_u64(a, b, 1);
}
-// CHECK-LABEL: define <8 x i8> @test_vsli_n_p8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsli_n_p8(
// CHECK: [[VSLI_N:%.*]] = call <8 x i8> @llvm.arm.neon.vshiftins.v8i8(<8 x i8> %a, <8 x i8> %b, <8 x i8> <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1>)
// CHECK: ret <8 x i8> [[VSLI_N]]
poly8x8_t test_vsli_n_p8(poly8x8_t a, poly8x8_t b) {
return vsli_n_p8(a, b, 1);
}
-// CHECK-LABEL: define <4 x i16> @test_vsli_n_p16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsli_n_p16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[VSLI_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
@@ -17473,14 +15238,14 @@ poly16x4_t test_vsli_n_p16(poly16x4_t a, poly16x4_t b) {
return vsli_n_p16(a, b, 1);
}
-// CHECK-LABEL: define <16 x i8> @test_vsliq_n_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsliq_n_s8(
// CHECK: [[VSLI_N:%.*]] = call <16 x i8> @llvm.arm.neon.vshiftins.v16i8(<16 x i8> %a, <16 x i8> %b, <16 x i8> <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1>)
// CHECK: ret <16 x i8> [[VSLI_N]]
int8x16_t test_vsliq_n_s8(int8x16_t a, int8x16_t b) {
return vsliq_n_s8(a, b, 1);
}
-// CHECK-LABEL: define <8 x i16> @test_vsliq_n_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsliq_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[VSLI_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
@@ -17491,7 +15256,7 @@ int16x8_t test_vsliq_n_s16(int16x8_t a, int16x8_t b) {
return vsliq_n_s16(a, b, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vsliq_n_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsliq_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[VSLI_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
@@ -17502,7 +15267,7 @@ int32x4_t test_vsliq_n_s32(int32x4_t a, int32x4_t b) {
return vsliq_n_s32(a, b, 1);
}
-// CHECK-LABEL: define <2 x i64> @test_vsliq_n_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vsliq_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
// CHECK: [[VSLI_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
@@ -17513,14 +15278,14 @@ int64x2_t test_vsliq_n_s64(int64x2_t a, int64x2_t b) {
return vsliq_n_s64(a, b, 1);
}
-// CHECK-LABEL: define <16 x i8> @test_vsliq_n_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsliq_n_u8(
// CHECK: [[VSLI_N:%.*]] = call <16 x i8> @llvm.arm.neon.vshiftins.v16i8(<16 x i8> %a, <16 x i8> %b, <16 x i8> <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1>)
// CHECK: ret <16 x i8> [[VSLI_N]]
uint8x16_t test_vsliq_n_u8(uint8x16_t a, uint8x16_t b) {
return vsliq_n_u8(a, b, 1);
}
-// CHECK-LABEL: define <8 x i16> @test_vsliq_n_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsliq_n_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[VSLI_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
@@ -17531,7 +15296,7 @@ uint16x8_t test_vsliq_n_u16(uint16x8_t a, uint16x8_t b) {
return vsliq_n_u16(a, b, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vsliq_n_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsliq_n_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[VSLI_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
@@ -17542,7 +15307,7 @@ uint32x4_t test_vsliq_n_u32(uint32x4_t a, uint32x4_t b) {
return vsliq_n_u32(a, b, 1);
}
-// CHECK-LABEL: define <2 x i64> @test_vsliq_n_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vsliq_n_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
// CHECK: [[VSLI_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
@@ -17553,14 +15318,14 @@ uint64x2_t test_vsliq_n_u64(uint64x2_t a, uint64x2_t b) {
return vsliq_n_u64(a, b, 1);
}
-// CHECK-LABEL: define <16 x i8> @test_vsliq_n_p8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsliq_n_p8(
// CHECK: [[VSLI_N:%.*]] = call <16 x i8> @llvm.arm.neon.vshiftins.v16i8(<16 x i8> %a, <16 x i8> %b, <16 x i8> <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1>)
// CHECK: ret <16 x i8> [[VSLI_N]]
poly8x16_t test_vsliq_n_p8(poly8x16_t a, poly8x16_t b) {
return vsliq_n_p8(a, b, 1);
}
-// CHECK-LABEL: define <8 x i16> @test_vsliq_n_p16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsliq_n_p16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[VSLI_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
@@ -17571,8 +15336,7 @@ poly16x8_t test_vsliq_n_p16(poly16x8_t a, poly16x8_t b) {
return vsliq_n_p16(a, b, 1);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vsra_n_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsra_n_s8(
// CHECK: [[VSRA_N:%.*]] = ashr <8 x i8> %b, <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1>
// CHECK: [[TMP0:%.*]] = add <8 x i8> %a, [[VSRA_N]]
// CHECK: ret <8 x i8> [[TMP0]]
@@ -17580,7 +15344,7 @@ int8x8_t test_vsra_n_s8(int8x8_t a, int8x8_t b) {
return vsra_n_s8(a, b, 1);
}
-// CHECK-LABEL: define <4 x i16> @test_vsra_n_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsra_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
@@ -17592,7 +15356,7 @@ int16x4_t test_vsra_n_s16(int16x4_t a, int16x4_t b) {
return vsra_n_s16(a, b, 1);
}
-// CHECK-LABEL: define <2 x i32> @test_vsra_n_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsra_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
@@ -17604,7 +15368,7 @@ int32x2_t test_vsra_n_s32(int32x2_t a, int32x2_t b) {
return vsra_n_s32(a, b, 1);
}
-// CHECK-LABEL: define <1 x i64> @test_vsra_n_s64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vsra_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
@@ -17616,7 +15380,7 @@ int64x1_t test_vsra_n_s64(int64x1_t a, int64x1_t b) {
return vsra_n_s64(a, b, 1);
}
-// CHECK-LABEL: define <8 x i8> @test_vsra_n_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsra_n_u8(
// CHECK: [[VSRA_N:%.*]] = lshr <8 x i8> %b, <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1>
// CHECK: [[TMP0:%.*]] = add <8 x i8> %a, [[VSRA_N]]
// CHECK: ret <8 x i8> [[TMP0]]
@@ -17624,7 +15388,7 @@ uint8x8_t test_vsra_n_u8(uint8x8_t a, uint8x8_t b) {
return vsra_n_u8(a, b, 1);
}
-// CHECK-LABEL: define <4 x i16> @test_vsra_n_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsra_n_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
@@ -17636,7 +15400,7 @@ uint16x4_t test_vsra_n_u16(uint16x4_t a, uint16x4_t b) {
return vsra_n_u16(a, b, 1);
}
-// CHECK-LABEL: define <2 x i32> @test_vsra_n_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsra_n_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
@@ -17648,7 +15412,7 @@ uint32x2_t test_vsra_n_u32(uint32x2_t a, uint32x2_t b) {
return vsra_n_u32(a, b, 1);
}
-// CHECK-LABEL: define <1 x i64> @test_vsra_n_u64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vsra_n_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
@@ -17660,7 +15424,7 @@ uint64x1_t test_vsra_n_u64(uint64x1_t a, uint64x1_t b) {
return vsra_n_u64(a, b, 1);
}
-// CHECK-LABEL: define <16 x i8> @test_vsraq_n_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsraq_n_s8(
// CHECK: [[VSRA_N:%.*]] = ashr <16 x i8> %b, <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1>
// CHECK: [[TMP0:%.*]] = add <16 x i8> %a, [[VSRA_N]]
// CHECK: ret <16 x i8> [[TMP0]]
@@ -17668,7 +15432,7 @@ int8x16_t test_vsraq_n_s8(int8x16_t a, int8x16_t b) {
return vsraq_n_s8(a, b, 1);
}
-// CHECK-LABEL: define <8 x i16> @test_vsraq_n_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsraq_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
@@ -17680,7 +15444,7 @@ int16x8_t test_vsraq_n_s16(int16x8_t a, int16x8_t b) {
return vsraq_n_s16(a, b, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vsraq_n_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsraq_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
@@ -17692,7 +15456,7 @@ int32x4_t test_vsraq_n_s32(int32x4_t a, int32x4_t b) {
return vsraq_n_s32(a, b, 1);
}
-// CHECK-LABEL: define <2 x i64> @test_vsraq_n_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vsraq_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
@@ -17704,7 +15468,7 @@ int64x2_t test_vsraq_n_s64(int64x2_t a, int64x2_t b) {
return vsraq_n_s64(a, b, 1);
}
-// CHECK-LABEL: define <16 x i8> @test_vsraq_n_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsraq_n_u8(
// CHECK: [[VSRA_N:%.*]] = lshr <16 x i8> %b, <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1>
// CHECK: [[TMP0:%.*]] = add <16 x i8> %a, [[VSRA_N]]
// CHECK: ret <16 x i8> [[TMP0]]
@@ -17712,7 +15476,7 @@ uint8x16_t test_vsraq_n_u8(uint8x16_t a, uint8x16_t b) {
return vsraq_n_u8(a, b, 1);
}
-// CHECK-LABEL: define <8 x i16> @test_vsraq_n_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsraq_n_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
@@ -17724,7 +15488,7 @@ uint16x8_t test_vsraq_n_u16(uint16x8_t a, uint16x8_t b) {
return vsraq_n_u16(a, b, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vsraq_n_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsraq_n_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
@@ -17736,7 +15500,7 @@ uint32x4_t test_vsraq_n_u32(uint32x4_t a, uint32x4_t b) {
return vsraq_n_u32(a, b, 1);
}
-// CHECK-LABEL: define <2 x i64> @test_vsraq_n_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vsraq_n_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
@@ -17748,15 +15512,14 @@ uint64x2_t test_vsraq_n_u64(uint64x2_t a, uint64x2_t b) {
return vsraq_n_u64(a, b, 1);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vsri_n_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsri_n_s8(
// CHECK: [[VSLI_N:%.*]] = call <8 x i8> @llvm.arm.neon.vshiftins.v8i8(<8 x i8> %a, <8 x i8> %b, <8 x i8> <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>)
// CHECK: ret <8 x i8> [[VSLI_N]]
int8x8_t test_vsri_n_s8(int8x8_t a, int8x8_t b) {
return vsri_n_s8(a, b, 1);
}
-// CHECK-LABEL: define <4 x i16> @test_vsri_n_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsri_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[VSLI_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
@@ -17767,7 +15530,7 @@ int16x4_t test_vsri_n_s16(int16x4_t a, int16x4_t b) {
return vsri_n_s16(a, b, 1);
}
-// CHECK-LABEL: define <2 x i32> @test_vsri_n_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsri_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[VSLI_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
@@ -17778,7 +15541,7 @@ int32x2_t test_vsri_n_s32(int32x2_t a, int32x2_t b) {
return vsri_n_s32(a, b, 1);
}
-// CHECK-LABEL: define <1 x i64> @test_vsri_n_s64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vsri_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
// CHECK: [[VSLI_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
@@ -17789,14 +15552,14 @@ int64x1_t test_vsri_n_s64(int64x1_t a, int64x1_t b) {
return vsri_n_s64(a, b, 1);
}
-// CHECK-LABEL: define <8 x i8> @test_vsri_n_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsri_n_u8(
// CHECK: [[VSLI_N:%.*]] = call <8 x i8> @llvm.arm.neon.vshiftins.v8i8(<8 x i8> %a, <8 x i8> %b, <8 x i8> <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>)
// CHECK: ret <8 x i8> [[VSLI_N]]
uint8x8_t test_vsri_n_u8(uint8x8_t a, uint8x8_t b) {
return vsri_n_u8(a, b, 1);
}
-// CHECK-LABEL: define <4 x i16> @test_vsri_n_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsri_n_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[VSLI_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
@@ -17807,7 +15570,7 @@ uint16x4_t test_vsri_n_u16(uint16x4_t a, uint16x4_t b) {
return vsri_n_u16(a, b, 1);
}
-// CHECK-LABEL: define <2 x i32> @test_vsri_n_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsri_n_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[VSLI_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
@@ -17818,7 +15581,7 @@ uint32x2_t test_vsri_n_u32(uint32x2_t a, uint32x2_t b) {
return vsri_n_u32(a, b, 1);
}
-// CHECK-LABEL: define <1 x i64> @test_vsri_n_u64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vsri_n_u64(
// CHECK: [[TMP0:%.*]] = bitcast <1 x i64> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
// CHECK: [[VSLI_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <1 x i64>
@@ -17829,14 +15592,14 @@ uint64x1_t test_vsri_n_u64(uint64x1_t a, uint64x1_t b) {
return vsri_n_u64(a, b, 1);
}
-// CHECK-LABEL: define <8 x i8> @test_vsri_n_p8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsri_n_p8(
// CHECK: [[VSLI_N:%.*]] = call <8 x i8> @llvm.arm.neon.vshiftins.v8i8(<8 x i8> %a, <8 x i8> %b, <8 x i8> <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>)
// CHECK: ret <8 x i8> [[VSLI_N]]
poly8x8_t test_vsri_n_p8(poly8x8_t a, poly8x8_t b) {
return vsri_n_p8(a, b, 1);
}
-// CHECK-LABEL: define <4 x i16> @test_vsri_n_p16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsri_n_p16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[VSLI_N:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
@@ -17847,14 +15610,14 @@ poly16x4_t test_vsri_n_p16(poly16x4_t a, poly16x4_t b) {
return vsri_n_p16(a, b, 1);
}
-// CHECK-LABEL: define <16 x i8> @test_vsriq_n_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsriq_n_s8(
// CHECK: [[VSLI_N:%.*]] = call <16 x i8> @llvm.arm.neon.vshiftins.v16i8(<16 x i8> %a, <16 x i8> %b, <16 x i8> <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>)
// CHECK: ret <16 x i8> [[VSLI_N]]
int8x16_t test_vsriq_n_s8(int8x16_t a, int8x16_t b) {
return vsriq_n_s8(a, b, 1);
}
-// CHECK-LABEL: define <8 x i16> @test_vsriq_n_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsriq_n_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[VSLI_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
@@ -17865,7 +15628,7 @@ int16x8_t test_vsriq_n_s16(int16x8_t a, int16x8_t b) {
return vsriq_n_s16(a, b, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vsriq_n_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsriq_n_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[VSLI_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
@@ -17876,7 +15639,7 @@ int32x4_t test_vsriq_n_s32(int32x4_t a, int32x4_t b) {
return vsriq_n_s32(a, b, 1);
}
-// CHECK-LABEL: define <2 x i64> @test_vsriq_n_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vsriq_n_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
// CHECK: [[VSLI_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
@@ -17887,14 +15650,14 @@ int64x2_t test_vsriq_n_s64(int64x2_t a, int64x2_t b) {
return vsriq_n_s64(a, b, 1);
}
-// CHECK-LABEL: define <16 x i8> @test_vsriq_n_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsriq_n_u8(
// CHECK: [[VSLI_N:%.*]] = call <16 x i8> @llvm.arm.neon.vshiftins.v16i8(<16 x i8> %a, <16 x i8> %b, <16 x i8> <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>)
// CHECK: ret <16 x i8> [[VSLI_N]]
uint8x16_t test_vsriq_n_u8(uint8x16_t a, uint8x16_t b) {
return vsriq_n_u8(a, b, 1);
}
-// CHECK-LABEL: define <8 x i16> @test_vsriq_n_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsriq_n_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[VSLI_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
@@ -17905,7 +15668,7 @@ uint16x8_t test_vsriq_n_u16(uint16x8_t a, uint16x8_t b) {
return vsriq_n_u16(a, b, 1);
}
-// CHECK-LABEL: define <4 x i32> @test_vsriq_n_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsriq_n_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[VSLI_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
@@ -17916,7 +15679,7 @@ uint32x4_t test_vsriq_n_u32(uint32x4_t a, uint32x4_t b) {
return vsriq_n_u32(a, b, 1);
}
-// CHECK-LABEL: define <2 x i64> @test_vsriq_n_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vsriq_n_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
// CHECK: [[VSLI_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
@@ -17927,14 +15690,14 @@ uint64x2_t test_vsriq_n_u64(uint64x2_t a, uint64x2_t b) {
return vsriq_n_u64(a, b, 1);
}
-// CHECK-LABEL: define <16 x i8> @test_vsriq_n_p8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsriq_n_p8(
// CHECK: [[VSLI_N:%.*]] = call <16 x i8> @llvm.arm.neon.vshiftins.v16i8(<16 x i8> %a, <16 x i8> %b, <16 x i8> <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>)
// CHECK: ret <16 x i8> [[VSLI_N]]
poly8x16_t test_vsriq_n_p8(poly8x16_t a, poly8x16_t b) {
return vsriq_n_p8(a, b, 1);
}
-// CHECK-LABEL: define <8 x i16> @test_vsriq_n_p16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsriq_n_p16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[VSLI_N:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
@@ -17945,15 +15708,14 @@ poly16x8_t test_vsriq_n_p16(poly16x8_t a, poly16x8_t b) {
return vsriq_n_p16(a, b, 1);
}
-
-// CHECK-LABEL: define void @test_vst1q_u8(i8* %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vst1q_u8(
// CHECK: call void @llvm.arm.neon.vst1.p0i8.v16i8(i8* %a, <16 x i8> %b, i32 1)
// CHECK: ret void
void test_vst1q_u8(uint8_t * a, uint8x16_t b) {
vst1q_u8(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_u16(i16* %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vst1q_u16(
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
@@ -17963,7 +15725,7 @@ void test_vst1q_u16(uint16_t * a, uint16x8_t b) {
vst1q_u16(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_u32(i32* %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vst1q_u32(
// CHECK: [[TMP0:%.*]] = bitcast i32* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
@@ -17973,7 +15735,7 @@ void test_vst1q_u32(uint32_t * a, uint32x4_t b) {
vst1q_u32(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_u64(i64* %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vst1q_u64(
// CHECK: [[TMP0:%.*]] = bitcast i64* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
@@ -17983,14 +15745,14 @@ void test_vst1q_u64(uint64_t * a, uint64x2_t b) {
vst1q_u64(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_s8(i8* %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vst1q_s8(
// CHECK: call void @llvm.arm.neon.vst1.p0i8.v16i8(i8* %a, <16 x i8> %b, i32 1)
// CHECK: ret void
void test_vst1q_s8(int8_t * a, int8x16_t b) {
vst1q_s8(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_s16(i16* %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vst1q_s16(
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
@@ -18000,7 +15762,7 @@ void test_vst1q_s16(int16_t * a, int16x8_t b) {
vst1q_s16(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_s32(i32* %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vst1q_s32(
// CHECK: [[TMP0:%.*]] = bitcast i32* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
@@ -18010,7 +15772,7 @@ void test_vst1q_s32(int32_t * a, int32x4_t b) {
vst1q_s32(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_s64(i64* %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vst1q_s64(
// CHECK: [[TMP0:%.*]] = bitcast i64* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
@@ -18020,7 +15782,7 @@ void test_vst1q_s64(int64_t * a, int64x2_t b) {
vst1q_s64(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_f16(half* %a, <8 x half> %b) #0 {
+// CHECK-LABEL: @test_vst1q_f16(
// CHECK: [[TMP0:%.*]] = bitcast half* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <8 x half> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
@@ -18030,7 +15792,7 @@ void test_vst1q_f16(float16_t * a, float16x8_t b) {
vst1q_f16(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_f32(float* %a, <4 x float> %b) #0 {
+// CHECK-LABEL: @test_vst1q_f32(
// CHECK: [[TMP0:%.*]] = bitcast float* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
@@ -18040,14 +15802,14 @@ void test_vst1q_f32(float32_t * a, float32x4_t b) {
vst1q_f32(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_p8(i8* %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vst1q_p8(
// CHECK: call void @llvm.arm.neon.vst1.p0i8.v16i8(i8* %a, <16 x i8> %b, i32 1)
// CHECK: ret void
void test_vst1q_p8(poly8_t * a, poly8x16_t b) {
vst1q_p8(a, b);
}
-// CHECK-LABEL: define void @test_vst1q_p16(i16* %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vst1q_p16(
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
@@ -18057,14 +15819,14 @@ void test_vst1q_p16(poly16_t * a, poly16x8_t b) {
vst1q_p16(a, b);
}
-// CHECK-LABEL: define void @test_vst1_u8(i8* %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vst1_u8(
// CHECK: call void @llvm.arm.neon.vst1.p0i8.v8i8(i8* %a, <8 x i8> %b, i32 1)
// CHECK: ret void
void test_vst1_u8(uint8_t * a, uint8x8_t b) {
vst1_u8(a, b);
}
-// CHECK-LABEL: define void @test_vst1_u16(i16* %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vst1_u16(
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
@@ -18074,7 +15836,7 @@ void test_vst1_u16(uint16_t * a, uint16x4_t b) {
vst1_u16(a, b);
}
-// CHECK-LABEL: define void @test_vst1_u32(i32* %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vst1_u32(
// CHECK: [[TMP0:%.*]] = bitcast i32* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
@@ -18084,7 +15846,7 @@ void test_vst1_u32(uint32_t * a, uint32x2_t b) {
vst1_u32(a, b);
}
-// CHECK-LABEL: define void @test_vst1_u64(i64* %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vst1_u64(
// CHECK: [[TMP0:%.*]] = bitcast i64* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x i64>
@@ -18094,14 +15856,14 @@ void test_vst1_u64(uint64_t * a, uint64x1_t b) {
vst1_u64(a, b);
}
-// CHECK-LABEL: define void @test_vst1_s8(i8* %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vst1_s8(
// CHECK: call void @llvm.arm.neon.vst1.p0i8.v8i8(i8* %a, <8 x i8> %b, i32 1)
// CHECK: ret void
void test_vst1_s8(int8_t * a, int8x8_t b) {
vst1_s8(a, b);
}
-// CHECK-LABEL: define void @test_vst1_s16(i16* %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vst1_s16(
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
@@ -18111,7 +15873,7 @@ void test_vst1_s16(int16_t * a, int16x4_t b) {
vst1_s16(a, b);
}
-// CHECK-LABEL: define void @test_vst1_s32(i32* %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vst1_s32(
// CHECK: [[TMP0:%.*]] = bitcast i32* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
@@ -18121,7 +15883,7 @@ void test_vst1_s32(int32_t * a, int32x2_t b) {
vst1_s32(a, b);
}
-// CHECK-LABEL: define void @test_vst1_s64(i64* %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vst1_s64(
// CHECK: [[TMP0:%.*]] = bitcast i64* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x i64>
@@ -18131,7 +15893,7 @@ void test_vst1_s64(int64_t * a, int64x1_t b) {
vst1_s64(a, b);
}
-// CHECK-LABEL: define void @test_vst1_f16(half* %a, <4 x half> %b) #0 {
+// CHECK-LABEL: @test_vst1_f16(
// CHECK: [[TMP0:%.*]] = bitcast half* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x half> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
@@ -18141,7 +15903,7 @@ void test_vst1_f16(float16_t * a, float16x4_t b) {
vst1_f16(a, b);
}
-// CHECK-LABEL: define void @test_vst1_f32(float* %a, <2 x float> %b) #0 {
+// CHECK-LABEL: @test_vst1_f32(
// CHECK: [[TMP0:%.*]] = bitcast float* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
@@ -18151,14 +15913,14 @@ void test_vst1_f32(float32_t * a, float32x2_t b) {
vst1_f32(a, b);
}
-// CHECK-LABEL: define void @test_vst1_p8(i8* %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vst1_p8(
// CHECK: call void @llvm.arm.neon.vst1.p0i8.v8i8(i8* %a, <8 x i8> %b, i32 1)
// CHECK: ret void
void test_vst1_p8(poly8_t * a, poly8x8_t b) {
vst1_p8(a, b);
}
-// CHECK-LABEL: define void @test_vst1_p16(i16* %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vst1_p16(
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
@@ -18168,8 +15930,7 @@ void test_vst1_p16(poly16_t * a, poly16x4_t b) {
vst1_p16(a, b);
}
-
-// CHECK-LABEL: define void @test_vst1q_lane_u8(i8* %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vst1q_lane_u8(
// CHECK: [[TMP0:%.*]] = extractelement <16 x i8> %b, i32 15
// CHECK: store i8 [[TMP0]], i8* %a, align 1
// CHECK: ret void
@@ -18177,7 +15938,7 @@ void test_vst1q_lane_u8(uint8_t * a, uint8x16_t b) {
vst1q_lane_u8(a, b, 15);
}
-// CHECK-LABEL: define void @test_vst1q_lane_u16(i16* %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vst1q_lane_u16(
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
@@ -18189,7 +15950,7 @@ void test_vst1q_lane_u16(uint16_t * a, uint16x8_t b) {
vst1q_lane_u16(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst1q_lane_u32(i32* %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vst1q_lane_u32(
// CHECK: [[TMP0:%.*]] = bitcast i32* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
@@ -18201,7 +15962,7 @@ void test_vst1q_lane_u32(uint32_t * a, uint32x4_t b) {
vst1q_lane_u32(a, b, 3);
}
-// CHECK-LABEL: define void @test_vst1q_lane_u64(i64* %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vst1q_lane_u64(
// CHECK: [[TMP0:%.*]] = bitcast i64* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
@@ -18212,7 +15973,7 @@ void test_vst1q_lane_u64(uint64_t * a, uint64x2_t b) {
vst1q_lane_u64(a, b, 1);
}
-// CHECK-LABEL: define void @test_vst1q_lane_s8(i8* %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vst1q_lane_s8(
// CHECK: [[TMP0:%.*]] = extractelement <16 x i8> %b, i32 15
// CHECK: store i8 [[TMP0]], i8* %a, align 1
// CHECK: ret void
@@ -18220,7 +15981,7 @@ void test_vst1q_lane_s8(int8_t * a, int8x16_t b) {
vst1q_lane_s8(a, b, 15);
}
-// CHECK-LABEL: define void @test_vst1q_lane_s16(i16* %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vst1q_lane_s16(
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
@@ -18232,7 +15993,7 @@ void test_vst1q_lane_s16(int16_t * a, int16x8_t b) {
vst1q_lane_s16(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst1q_lane_s32(i32* %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vst1q_lane_s32(
// CHECK: [[TMP0:%.*]] = bitcast i32* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
@@ -18244,7 +16005,7 @@ void test_vst1q_lane_s32(int32_t * a, int32x4_t b) {
vst1q_lane_s32(a, b, 3);
}
-// CHECK-LABEL: define void @test_vst1q_lane_s64(i64* %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vst1q_lane_s64(
// CHECK: [[TMP0:%.*]] = bitcast i64* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
@@ -18255,7 +16016,7 @@ void test_vst1q_lane_s64(int64_t * a, int64x2_t b) {
vst1q_lane_s64(a, b, 1);
}
-// CHECK-LABEL: define void @test_vst1q_lane_f16(half* %a, <8 x half> %b) #0 {
+// CHECK-LABEL: @test_vst1q_lane_f16(
// CHECK: [[TMP0:%.*]] = bitcast half* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <8 x half> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
@@ -18267,7 +16028,7 @@ void test_vst1q_lane_f16(float16_t * a, float16x8_t b) {
vst1q_lane_f16(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst1q_lane_f32(float* %a, <4 x float> %b) #0 {
+// CHECK-LABEL: @test_vst1q_lane_f32(
// CHECK: [[TMP0:%.*]] = bitcast float* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x float> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
@@ -18279,7 +16040,7 @@ void test_vst1q_lane_f32(float32_t * a, float32x4_t b) {
vst1q_lane_f32(a, b, 3);
}
-// CHECK-LABEL: define void @test_vst1q_lane_p8(i8* %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vst1q_lane_p8(
// CHECK: [[TMP0:%.*]] = extractelement <16 x i8> %b, i32 15
// CHECK: store i8 [[TMP0]], i8* %a, align 1
// CHECK: ret void
@@ -18287,7 +16048,7 @@ void test_vst1q_lane_p8(poly8_t * a, poly8x16_t b) {
vst1q_lane_p8(a, b, 15);
}
-// CHECK-LABEL: define void @test_vst1q_lane_p16(i16* %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vst1q_lane_p16(
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
@@ -18299,7 +16060,7 @@ void test_vst1q_lane_p16(poly16_t * a, poly16x8_t b) {
vst1q_lane_p16(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst1_lane_u8(i8* %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vst1_lane_u8(
// CHECK: [[TMP0:%.*]] = extractelement <8 x i8> %b, i32 7
// CHECK: store i8 [[TMP0]], i8* %a, align 1
// CHECK: ret void
@@ -18307,7 +16068,7 @@ void test_vst1_lane_u8(uint8_t * a, uint8x8_t b) {
vst1_lane_u8(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst1_lane_u16(i16* %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vst1_lane_u16(
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
@@ -18319,7 +16080,7 @@ void test_vst1_lane_u16(uint16_t * a, uint16x4_t b) {
vst1_lane_u16(a, b, 3);
}
-// CHECK-LABEL: define void @test_vst1_lane_u32(i32* %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vst1_lane_u32(
// CHECK: [[TMP0:%.*]] = bitcast i32* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
@@ -18331,7 +16092,7 @@ void test_vst1_lane_u32(uint32_t * a, uint32x2_t b) {
vst1_lane_u32(a, b, 1);
}
-// CHECK-LABEL: define void @test_vst1_lane_u64(i64* %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vst1_lane_u64(
// CHECK: [[TMP0:%.*]] = bitcast i64* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x i64>
@@ -18343,7 +16104,7 @@ void test_vst1_lane_u64(uint64_t * a, uint64x1_t b) {
vst1_lane_u64(a, b, 0);
}
-// CHECK-LABEL: define void @test_vst1_lane_s8(i8* %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vst1_lane_s8(
// CHECK: [[TMP0:%.*]] = extractelement <8 x i8> %b, i32 7
// CHECK: store i8 [[TMP0]], i8* %a, align 1
// CHECK: ret void
@@ -18351,7 +16112,7 @@ void test_vst1_lane_s8(int8_t * a, int8x8_t b) {
vst1_lane_s8(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst1_lane_s16(i16* %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vst1_lane_s16(
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
@@ -18363,7 +16124,7 @@ void test_vst1_lane_s16(int16_t * a, int16x4_t b) {
vst1_lane_s16(a, b, 3);
}
-// CHECK-LABEL: define void @test_vst1_lane_s32(i32* %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vst1_lane_s32(
// CHECK: [[TMP0:%.*]] = bitcast i32* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
@@ -18375,7 +16136,7 @@ void test_vst1_lane_s32(int32_t * a, int32x2_t b) {
vst1_lane_s32(a, b, 1);
}
-// CHECK-LABEL: define void @test_vst1_lane_s64(i64* %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vst1_lane_s64(
// CHECK: [[TMP0:%.*]] = bitcast i64* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <1 x i64> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <1 x i64>
@@ -18387,7 +16148,7 @@ void test_vst1_lane_s64(int64_t * a, int64x1_t b) {
vst1_lane_s64(a, b, 0);
}
-// CHECK-LABEL: define void @test_vst1_lane_f16(half* %a, <4 x half> %b) #0 {
+// CHECK-LABEL: @test_vst1_lane_f16(
// CHECK: [[TMP0:%.*]] = bitcast half* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x half> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
@@ -18399,7 +16160,7 @@ void test_vst1_lane_f16(float16_t * a, float16x4_t b) {
vst1_lane_f16(a, b, 3);
}
-// CHECK-LABEL: define void @test_vst1_lane_f32(float* %a, <2 x float> %b) #0 {
+// CHECK-LABEL: @test_vst1_lane_f32(
// CHECK: [[TMP0:%.*]] = bitcast float* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <2 x float> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
@@ -18411,7 +16172,7 @@ void test_vst1_lane_f32(float32_t * a, float32x2_t b) {
vst1_lane_f32(a, b, 1);
}
-// CHECK-LABEL: define void @test_vst1_lane_p8(i8* %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vst1_lane_p8(
// CHECK: [[TMP0:%.*]] = extractelement <8 x i8> %b, i32 7
// CHECK: store i8 [[TMP0]], i8* %a, align 1
// CHECK: ret void
@@ -18419,7 +16180,7 @@ void test_vst1_lane_p8(poly8_t * a, poly8x8_t b) {
vst1_lane_p8(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst1_lane_p16(i16* %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vst1_lane_p16(
// CHECK: [[TMP0:%.*]] = bitcast i16* %a to i8*
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
@@ -18431,8 +16192,7 @@ void test_vst1_lane_p16(poly16_t * a, poly16x4_t b) {
vst1_lane_p16(a, b, 3);
}
-
-// CHECK-LABEL: define void @test_vst2q_u8(i8* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2q_u8(
// 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
@@ -18453,7 +16213,7 @@ void test_vst2q_u8(uint8_t * a, uint8x16x2_t b) {
vst2q_u8(a, b);
}
-// CHECK-LABEL: define void @test_vst2q_u16(i16* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2q_u16(
// 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
@@ -18479,7 +16239,7 @@ void test_vst2q_u16(uint16_t * a, uint16x8x2_t b) {
vst2q_u16(a, b);
}
-// CHECK-LABEL: define void @test_vst2q_u32(i32* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2q_u32(
// 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
@@ -18505,7 +16265,7 @@ void test_vst2q_u32(uint32_t * a, uint32x4x2_t b) {
vst2q_u32(a, b);
}
-// CHECK-LABEL: define void @test_vst2q_s8(i8* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2q_s8(
// 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
@@ -18526,7 +16286,7 @@ void test_vst2q_s8(int8_t * a, int8x16x2_t b) {
vst2q_s8(a, b);
}
-// CHECK-LABEL: define void @test_vst2q_s16(i16* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2q_s16(
// 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
@@ -18552,7 +16312,7 @@ void test_vst2q_s16(int16_t * a, int16x8x2_t b) {
vst2q_s16(a, b);
}
-// CHECK-LABEL: define void @test_vst2q_s32(i32* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2q_s32(
// 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
@@ -18578,7 +16338,7 @@ void test_vst2q_s32(int32_t * a, int32x4x2_t b) {
vst2q_s32(a, b);
}
-// CHECK-LABEL: define void @test_vst2q_f16(half* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2q_f16(
// 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
@@ -18604,7 +16364,7 @@ void test_vst2q_f16(float16_t * a, float16x8x2_t b) {
vst2q_f16(a, b);
}
-// CHECK-LABEL: define void @test_vst2q_f32(float* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2q_f32(
// 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
@@ -18630,7 +16390,7 @@ void test_vst2q_f32(float32_t * a, float32x4x2_t b) {
vst2q_f32(a, b);
}
-// CHECK-LABEL: define void @test_vst2q_p8(i8* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2q_p8(
// 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
@@ -18651,7 +16411,7 @@ void test_vst2q_p8(poly8_t * a, poly8x16x2_t b) {
vst2q_p8(a, b);
}
-// CHECK-LABEL: define void @test_vst2q_p16(i16* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2q_p16(
// 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
@@ -18677,7 +16437,7 @@ void test_vst2q_p16(poly16_t * a, poly16x8x2_t b) {
vst2q_p16(a, b);
}
-// CHECK-LABEL: define void @test_vst2_u8(i8* %a, [2 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2_u8(
// 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
@@ -18698,7 +16458,7 @@ void test_vst2_u8(uint8_t * a, uint8x8x2_t b) {
vst2_u8(a, b);
}
-// CHECK-LABEL: define void @test_vst2_u16(i16* %a, [2 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2_u16(
// 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
@@ -18724,7 +16484,7 @@ void test_vst2_u16(uint16_t * a, uint16x4x2_t b) {
vst2_u16(a, b);
}
-// CHECK-LABEL: define void @test_vst2_u32(i32* %a, [2 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2_u32(
// 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
@@ -18750,7 +16510,7 @@ void test_vst2_u32(uint32_t * a, uint32x2x2_t b) {
vst2_u32(a, b);
}
-// CHECK-LABEL: define void @test_vst2_u64(i64* %a, [2 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2_u64(
// 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
@@ -18776,7 +16536,7 @@ void test_vst2_u64(uint64_t * a, uint64x1x2_t b) {
vst2_u64(a, b);
}
-// CHECK-LABEL: define void @test_vst2_s8(i8* %a, [2 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2_s8(
// 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
@@ -18797,7 +16557,7 @@ void test_vst2_s8(int8_t * a, int8x8x2_t b) {
vst2_s8(a, b);
}
-// CHECK-LABEL: define void @test_vst2_s16(i16* %a, [2 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2_s16(
// 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
@@ -18823,7 +16583,7 @@ void test_vst2_s16(int16_t * a, int16x4x2_t b) {
vst2_s16(a, b);
}
-// CHECK-LABEL: define void @test_vst2_s32(i32* %a, [2 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2_s32(
// 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
@@ -18849,7 +16609,7 @@ void test_vst2_s32(int32_t * a, int32x2x2_t b) {
vst2_s32(a, b);
}
-// CHECK-LABEL: define void @test_vst2_s64(i64* %a, [2 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2_s64(
// 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
@@ -18875,7 +16635,7 @@ void test_vst2_s64(int64_t * a, int64x1x2_t b) {
vst2_s64(a, b);
}
-// CHECK-LABEL: define void @test_vst2_f16(half* %a, [2 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2_f16(
// 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
@@ -18901,7 +16661,7 @@ void test_vst2_f16(float16_t * a, float16x4x2_t b) {
vst2_f16(a, b);
}
-// CHECK-LABEL: define void @test_vst2_f32(float* %a, [2 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2_f32(
// 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
@@ -18927,7 +16687,7 @@ void test_vst2_f32(float32_t * a, float32x2x2_t b) {
vst2_f32(a, b);
}
-// CHECK-LABEL: define void @test_vst2_p8(i8* %a, [2 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2_p8(
// 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
@@ -18948,7 +16708,7 @@ void test_vst2_p8(poly8_t * a, poly8x8x2_t b) {
vst2_p8(a, b);
}
-// CHECK-LABEL: define void @test_vst2_p16(i16* %a, [2 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2_p16(
// 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
@@ -18974,8 +16734,7 @@ void test_vst2_p16(poly16_t * a, poly16x4x2_t b) {
vst2_p16(a, b);
}
-
-// CHECK-LABEL: define void @test_vst2q_lane_u16(i16* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2q_lane_u16(
// 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
@@ -19001,7 +16760,7 @@ void test_vst2q_lane_u16(uint16_t * a, uint16x8x2_t b) {
vst2q_lane_u16(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst2q_lane_u32(i32* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2q_lane_u32(
// 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
@@ -19027,7 +16786,7 @@ void test_vst2q_lane_u32(uint32_t * a, uint32x4x2_t b) {
vst2q_lane_u32(a, b, 3);
}
-// CHECK-LABEL: define void @test_vst2q_lane_s16(i16* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2q_lane_s16(
// 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
@@ -19053,7 +16812,7 @@ void test_vst2q_lane_s16(int16_t * a, int16x8x2_t b) {
vst2q_lane_s16(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst2q_lane_s32(i32* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2q_lane_s32(
// 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
@@ -19079,7 +16838,7 @@ void test_vst2q_lane_s32(int32_t * a, int32x4x2_t b) {
vst2q_lane_s32(a, b, 3);
}
-// CHECK-LABEL: define void @test_vst2q_lane_f16(half* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2q_lane_f16(
// 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
@@ -19105,7 +16864,7 @@ void test_vst2q_lane_f16(float16_t * a, float16x8x2_t b) {
vst2q_lane_f16(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst2q_lane_f32(float* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2q_lane_f32(
// 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
@@ -19131,7 +16890,7 @@ void test_vst2q_lane_f32(float32_t * a, float32x4x2_t b) {
vst2q_lane_f32(a, b, 3);
}
-// CHECK-LABEL: define void @test_vst2q_lane_p16(i16* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2q_lane_p16(
// 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
@@ -19157,7 +16916,7 @@ void test_vst2q_lane_p16(poly16_t * a, poly16x8x2_t b) {
vst2q_lane_p16(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst2_lane_u8(i8* %a, [2 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2_lane_u8(
// 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
@@ -19178,7 +16937,7 @@ void test_vst2_lane_u8(uint8_t * a, uint8x8x2_t b) {
vst2_lane_u8(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst2_lane_u16(i16* %a, [2 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2_lane_u16(
// 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
@@ -19204,7 +16963,7 @@ void test_vst2_lane_u16(uint16_t * a, uint16x4x2_t b) {
vst2_lane_u16(a, b, 3);
}
-// CHECK-LABEL: define void @test_vst2_lane_u32(i32* %a, [2 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2_lane_u32(
// 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
@@ -19230,7 +16989,7 @@ void test_vst2_lane_u32(uint32_t * a, uint32x2x2_t b) {
vst2_lane_u32(a, b, 1);
}
-// CHECK-LABEL: define void @test_vst2_lane_s8(i8* %a, [2 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2_lane_s8(
// 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
@@ -19251,7 +17010,7 @@ void test_vst2_lane_s8(int8_t * a, int8x8x2_t b) {
vst2_lane_s8(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst2_lane_s16(i16* %a, [2 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2_lane_s16(
// 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
@@ -19277,7 +17036,7 @@ void test_vst2_lane_s16(int16_t * a, int16x4x2_t b) {
vst2_lane_s16(a, b, 3);
}
-// CHECK-LABEL: define void @test_vst2_lane_s32(i32* %a, [2 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2_lane_s32(
// 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
@@ -19303,7 +17062,7 @@ void test_vst2_lane_s32(int32_t * a, int32x2x2_t b) {
vst2_lane_s32(a, b, 1);
}
-// CHECK-LABEL: define void @test_vst2_lane_f16(half* %a, [2 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2_lane_f16(
// 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
@@ -19329,7 +17088,7 @@ void test_vst2_lane_f16(float16_t * a, float16x4x2_t b) {
vst2_lane_f16(a, b, 3);
}
-// CHECK-LABEL: define void @test_vst2_lane_f32(float* %a, [2 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2_lane_f32(
// 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
@@ -19355,7 +17114,7 @@ void test_vst2_lane_f32(float32_t * a, float32x2x2_t b) {
vst2_lane_f32(a, b, 1);
}
-// CHECK-LABEL: define void @test_vst2_lane_p8(i8* %a, [2 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2_lane_p8(
// 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
@@ -19376,7 +17135,7 @@ void test_vst2_lane_p8(poly8_t * a, poly8x8x2_t b) {
vst2_lane_p8(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst2_lane_p16(i16* %a, [2 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst2_lane_p16(
// 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
@@ -19402,8 +17161,7 @@ void test_vst2_lane_p16(poly16_t * a, poly16x4x2_t b) {
vst2_lane_p16(a, b, 3);
}
-
-// CHECK-LABEL: define void @test_vst3q_u8(i8* %a, [6 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3q_u8(
// 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
@@ -19427,7 +17185,7 @@ void test_vst3q_u8(uint8_t * a, uint8x16x3_t b) {
vst3q_u8(a, b);
}
-// CHECK-LABEL: define void @test_vst3q_u16(i16* %a, [6 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3q_u16(
// 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
@@ -19458,7 +17216,7 @@ void test_vst3q_u16(uint16_t * a, uint16x8x3_t b) {
vst3q_u16(a, b);
}
-// CHECK-LABEL: define void @test_vst3q_u32(i32* %a, [6 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3q_u32(
// 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
@@ -19489,7 +17247,7 @@ void test_vst3q_u32(uint32_t * a, uint32x4x3_t b) {
vst3q_u32(a, b);
}
-// CHECK-LABEL: define void @test_vst3q_s8(i8* %a, [6 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3q_s8(
// 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
@@ -19513,7 +17271,7 @@ void test_vst3q_s8(int8_t * a, int8x16x3_t b) {
vst3q_s8(a, b);
}
-// CHECK-LABEL: define void @test_vst3q_s16(i16* %a, [6 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3q_s16(
// 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
@@ -19544,7 +17302,7 @@ void test_vst3q_s16(int16_t * a, int16x8x3_t b) {
vst3q_s16(a, b);
}
-// CHECK-LABEL: define void @test_vst3q_s32(i32* %a, [6 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3q_s32(
// 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
@@ -19575,7 +17333,7 @@ void test_vst3q_s32(int32_t * a, int32x4x3_t b) {
vst3q_s32(a, b);
}
-// CHECK-LABEL: define void @test_vst3q_f16(half* %a, [6 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3q_f16(
// 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
@@ -19606,7 +17364,7 @@ void test_vst3q_f16(float16_t * a, float16x8x3_t b) {
vst3q_f16(a, b);
}
-// CHECK-LABEL: define void @test_vst3q_f32(float* %a, [6 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3q_f32(
// 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
@@ -19637,7 +17395,7 @@ void test_vst3q_f32(float32_t * a, float32x4x3_t b) {
vst3q_f32(a, b);
}
-// CHECK-LABEL: define void @test_vst3q_p8(i8* %a, [6 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3q_p8(
// 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
@@ -19661,7 +17419,7 @@ void test_vst3q_p8(poly8_t * a, poly8x16x3_t b) {
vst3q_p8(a, b);
}
-// CHECK-LABEL: define void @test_vst3q_p16(i16* %a, [6 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3q_p16(
// 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
@@ -19692,7 +17450,7 @@ void test_vst3q_p16(poly16_t * a, poly16x8x3_t b) {
vst3q_p16(a, b);
}
-// CHECK-LABEL: define void @test_vst3_u8(i8* %a, [3 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3_u8(
// 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
@@ -19716,7 +17474,7 @@ void test_vst3_u8(uint8_t * a, uint8x8x3_t b) {
vst3_u8(a, b);
}
-// CHECK-LABEL: define void @test_vst3_u16(i16* %a, [3 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3_u16(
// 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
@@ -19747,7 +17505,7 @@ void test_vst3_u16(uint16_t * a, uint16x4x3_t b) {
vst3_u16(a, b);
}
-// CHECK-LABEL: define void @test_vst3_u32(i32* %a, [3 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3_u32(
// 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
@@ -19778,7 +17536,7 @@ void test_vst3_u32(uint32_t * a, uint32x2x3_t b) {
vst3_u32(a, b);
}
-// CHECK-LABEL: define void @test_vst3_u64(i64* %a, [3 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3_u64(
// 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
@@ -19809,7 +17567,7 @@ void test_vst3_u64(uint64_t * a, uint64x1x3_t b) {
vst3_u64(a, b);
}
-// CHECK-LABEL: define void @test_vst3_s8(i8* %a, [3 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3_s8(
// 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
@@ -19833,7 +17591,7 @@ void test_vst3_s8(int8_t * a, int8x8x3_t b) {
vst3_s8(a, b);
}
-// CHECK-LABEL: define void @test_vst3_s16(i16* %a, [3 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3_s16(
// 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
@@ -19864,7 +17622,7 @@ void test_vst3_s16(int16_t * a, int16x4x3_t b) {
vst3_s16(a, b);
}
-// CHECK-LABEL: define void @test_vst3_s32(i32* %a, [3 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3_s32(
// 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
@@ -19895,7 +17653,7 @@ void test_vst3_s32(int32_t * a, int32x2x3_t b) {
vst3_s32(a, b);
}
-// CHECK-LABEL: define void @test_vst3_s64(i64* %a, [3 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3_s64(
// 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
@@ -19926,7 +17684,7 @@ void test_vst3_s64(int64_t * a, int64x1x3_t b) {
vst3_s64(a, b);
}
-// CHECK-LABEL: define void @test_vst3_f16(half* %a, [3 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3_f16(
// 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
@@ -19957,7 +17715,7 @@ void test_vst3_f16(float16_t * a, float16x4x3_t b) {
vst3_f16(a, b);
}
-// CHECK-LABEL: define void @test_vst3_f32(float* %a, [3 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3_f32(
// 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
@@ -19988,7 +17746,7 @@ void test_vst3_f32(float32_t * a, float32x2x3_t b) {
vst3_f32(a, b);
}
-// CHECK-LABEL: define void @test_vst3_p8(i8* %a, [3 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3_p8(
// 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
@@ -20012,7 +17770,7 @@ void test_vst3_p8(poly8_t * a, poly8x8x3_t b) {
vst3_p8(a, b);
}
-// CHECK-LABEL: define void @test_vst3_p16(i16* %a, [3 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3_p16(
// 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
@@ -20043,8 +17801,7 @@ void test_vst3_p16(poly16_t * a, poly16x4x3_t b) {
vst3_p16(a, b);
}
-
-// CHECK-LABEL: define void @test_vst3q_lane_u16(i16* %a, [6 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3q_lane_u16(
// 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
@@ -20075,7 +17832,7 @@ void test_vst3q_lane_u16(uint16_t * a, uint16x8x3_t b) {
vst3q_lane_u16(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst3q_lane_u32(i32* %a, [6 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3q_lane_u32(
// 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
@@ -20106,7 +17863,7 @@ void test_vst3q_lane_u32(uint32_t * a, uint32x4x3_t b) {
vst3q_lane_u32(a, b, 3);
}
-// CHECK-LABEL: define void @test_vst3q_lane_s16(i16* %a, [6 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3q_lane_s16(
// 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
@@ -20137,7 +17894,7 @@ void test_vst3q_lane_s16(int16_t * a, int16x8x3_t b) {
vst3q_lane_s16(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst3q_lane_s32(i32* %a, [6 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3q_lane_s32(
// 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
@@ -20168,7 +17925,7 @@ void test_vst3q_lane_s32(int32_t * a, int32x4x3_t b) {
vst3q_lane_s32(a, b, 3);
}
-// CHECK-LABEL: define void @test_vst3q_lane_f16(half* %a, [6 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3q_lane_f16(
// 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
@@ -20199,7 +17956,7 @@ void test_vst3q_lane_f16(float16_t * a, float16x8x3_t b) {
vst3q_lane_f16(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst3q_lane_f32(float* %a, [6 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3q_lane_f32(
// 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
@@ -20230,7 +17987,7 @@ void test_vst3q_lane_f32(float32_t * a, float32x4x3_t b) {
vst3q_lane_f32(a, b, 3);
}
-// CHECK-LABEL: define void @test_vst3q_lane_p16(i16* %a, [6 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3q_lane_p16(
// 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
@@ -20261,7 +18018,7 @@ void test_vst3q_lane_p16(poly16_t * a, poly16x8x3_t b) {
vst3q_lane_p16(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst3_lane_u8(i8* %a, [3 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3_lane_u8(
// 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
@@ -20285,7 +18042,7 @@ void test_vst3_lane_u8(uint8_t * a, uint8x8x3_t b) {
vst3_lane_u8(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst3_lane_u16(i16* %a, [3 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3_lane_u16(
// 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
@@ -20316,7 +18073,7 @@ void test_vst3_lane_u16(uint16_t * a, uint16x4x3_t b) {
vst3_lane_u16(a, b, 3);
}
-// CHECK-LABEL: define void @test_vst3_lane_u32(i32* %a, [3 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3_lane_u32(
// 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
@@ -20347,7 +18104,7 @@ void test_vst3_lane_u32(uint32_t * a, uint32x2x3_t b) {
vst3_lane_u32(a, b, 1);
}
-// CHECK-LABEL: define void @test_vst3_lane_s8(i8* %a, [3 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3_lane_s8(
// 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
@@ -20371,7 +18128,7 @@ void test_vst3_lane_s8(int8_t * a, int8x8x3_t b) {
vst3_lane_s8(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst3_lane_s16(i16* %a, [3 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3_lane_s16(
// 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
@@ -20402,7 +18159,7 @@ void test_vst3_lane_s16(int16_t * a, int16x4x3_t b) {
vst3_lane_s16(a, b, 3);
}
-// CHECK-LABEL: define void @test_vst3_lane_s32(i32* %a, [3 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3_lane_s32(
// 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
@@ -20433,7 +18190,7 @@ void test_vst3_lane_s32(int32_t * a, int32x2x3_t b) {
vst3_lane_s32(a, b, 1);
}
-// CHECK-LABEL: define void @test_vst3_lane_f16(half* %a, [3 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3_lane_f16(
// 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
@@ -20464,7 +18221,7 @@ void test_vst3_lane_f16(float16_t * a, float16x4x3_t b) {
vst3_lane_f16(a, b, 3);
}
-// CHECK-LABEL: define void @test_vst3_lane_f32(float* %a, [3 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3_lane_f32(
// 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
@@ -20495,7 +18252,7 @@ void test_vst3_lane_f32(float32_t * a, float32x2x3_t b) {
vst3_lane_f32(a, b, 1);
}
-// CHECK-LABEL: define void @test_vst3_lane_p8(i8* %a, [3 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3_lane_p8(
// 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
@@ -20519,7 +18276,7 @@ void test_vst3_lane_p8(poly8_t * a, poly8x8x3_t b) {
vst3_lane_p8(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst3_lane_p16(i16* %a, [3 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst3_lane_p16(
// 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
@@ -20550,8 +18307,7 @@ void test_vst3_lane_p16(poly16_t * a, poly16x4x3_t b) {
vst3_lane_p16(a, b, 3);
}
-
-// CHECK-LABEL: define void @test_vst4q_u8(i8* %a, [8 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4q_u8(
// 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
@@ -20578,7 +18334,7 @@ void test_vst4q_u8(uint8_t * a, uint8x16x4_t b) {
vst4q_u8(a, b);
}
-// CHECK-LABEL: define void @test_vst4q_u16(i16* %a, [8 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4q_u16(
// 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
@@ -20614,7 +18370,7 @@ void test_vst4q_u16(uint16_t * a, uint16x8x4_t b) {
vst4q_u16(a, b);
}
-// CHECK-LABEL: define void @test_vst4q_u32(i32* %a, [8 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4q_u32(
// 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
@@ -20650,7 +18406,7 @@ void test_vst4q_u32(uint32_t * a, uint32x4x4_t b) {
vst4q_u32(a, b);
}
-// CHECK-LABEL: define void @test_vst4q_s8(i8* %a, [8 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4q_s8(
// 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
@@ -20677,7 +18433,7 @@ void test_vst4q_s8(int8_t * a, int8x16x4_t b) {
vst4q_s8(a, b);
}
-// CHECK-LABEL: define void @test_vst4q_s16(i16* %a, [8 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4q_s16(
// 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
@@ -20713,7 +18469,7 @@ void test_vst4q_s16(int16_t * a, int16x8x4_t b) {
vst4q_s16(a, b);
}
-// CHECK-LABEL: define void @test_vst4q_s32(i32* %a, [8 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4q_s32(
// 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
@@ -20749,7 +18505,7 @@ void test_vst4q_s32(int32_t * a, int32x4x4_t b) {
vst4q_s32(a, b);
}
-// CHECK-LABEL: define void @test_vst4q_f16(half* %a, [8 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4q_f16(
// 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
@@ -20785,7 +18541,7 @@ void test_vst4q_f16(float16_t * a, float16x8x4_t b) {
vst4q_f16(a, b);
}
-// CHECK-LABEL: define void @test_vst4q_f32(float* %a, [8 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4q_f32(
// 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
@@ -20821,7 +18577,7 @@ void test_vst4q_f32(float32_t * a, float32x4x4_t b) {
vst4q_f32(a, b);
}
-// CHECK-LABEL: define void @test_vst4q_p8(i8* %a, [8 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4q_p8(
// 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
@@ -20848,7 +18604,7 @@ void test_vst4q_p8(poly8_t * a, poly8x16x4_t b) {
vst4q_p8(a, b);
}
-// CHECK-LABEL: define void @test_vst4q_p16(i16* %a, [8 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4q_p16(
// 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
@@ -20884,7 +18640,7 @@ void test_vst4q_p16(poly16_t * a, poly16x8x4_t b) {
vst4q_p16(a, b);
}
-// CHECK-LABEL: define void @test_vst4_u8(i8* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4_u8(
// 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
@@ -20911,7 +18667,7 @@ void test_vst4_u8(uint8_t * a, uint8x8x4_t b) {
vst4_u8(a, b);
}
-// CHECK-LABEL: define void @test_vst4_u16(i16* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4_u16(
// 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
@@ -20947,7 +18703,7 @@ void test_vst4_u16(uint16_t * a, uint16x4x4_t b) {
vst4_u16(a, b);
}
-// CHECK-LABEL: define void @test_vst4_u32(i32* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4_u32(
// 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
@@ -20983,7 +18739,7 @@ void test_vst4_u32(uint32_t * a, uint32x2x4_t b) {
vst4_u32(a, b);
}
-// CHECK-LABEL: define void @test_vst4_u64(i64* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4_u64(
// 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
@@ -21019,7 +18775,7 @@ void test_vst4_u64(uint64_t * a, uint64x1x4_t b) {
vst4_u64(a, b);
}
-// CHECK-LABEL: define void @test_vst4_s8(i8* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4_s8(
// 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
@@ -21046,7 +18802,7 @@ void test_vst4_s8(int8_t * a, int8x8x4_t b) {
vst4_s8(a, b);
}
-// CHECK-LABEL: define void @test_vst4_s16(i16* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4_s16(
// 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
@@ -21082,7 +18838,7 @@ void test_vst4_s16(int16_t * a, int16x4x4_t b) {
vst4_s16(a, b);
}
-// CHECK-LABEL: define void @test_vst4_s32(i32* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4_s32(
// 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
@@ -21118,7 +18874,7 @@ void test_vst4_s32(int32_t * a, int32x2x4_t b) {
vst4_s32(a, b);
}
-// CHECK-LABEL: define void @test_vst4_s64(i64* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4_s64(
// 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
@@ -21154,7 +18910,7 @@ void test_vst4_s64(int64_t * a, int64x1x4_t b) {
vst4_s64(a, b);
}
-// CHECK-LABEL: define void @test_vst4_f16(half* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4_f16(
// 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
@@ -21190,7 +18946,7 @@ void test_vst4_f16(float16_t * a, float16x4x4_t b) {
vst4_f16(a, b);
}
-// CHECK-LABEL: define void @test_vst4_f32(float* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4_f32(
// 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
@@ -21226,7 +18982,7 @@ void test_vst4_f32(float32_t * a, float32x2x4_t b) {
vst4_f32(a, b);
}
-// CHECK-LABEL: define void @test_vst4_p8(i8* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4_p8(
// 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
@@ -21253,7 +19009,7 @@ void test_vst4_p8(poly8_t * a, poly8x8x4_t b) {
vst4_p8(a, b);
}
-// CHECK-LABEL: define void @test_vst4_p16(i16* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4_p16(
// 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
@@ -21289,8 +19045,7 @@ void test_vst4_p16(poly16_t * a, poly16x4x4_t b) {
vst4_p16(a, b);
}
-
-// CHECK-LABEL: define void @test_vst4q_lane_u16(i16* %a, [8 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4q_lane_u16(
// 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
@@ -21326,7 +19081,7 @@ void test_vst4q_lane_u16(uint16_t * a, uint16x8x4_t b) {
vst4q_lane_u16(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst4q_lane_u32(i32* %a, [8 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4q_lane_u32(
// 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
@@ -21362,7 +19117,7 @@ void test_vst4q_lane_u32(uint32_t * a, uint32x4x4_t b) {
vst4q_lane_u32(a, b, 3);
}
-// CHECK-LABEL: define void @test_vst4q_lane_s16(i16* %a, [8 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4q_lane_s16(
// 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
@@ -21398,7 +19153,7 @@ void test_vst4q_lane_s16(int16_t * a, int16x8x4_t b) {
vst4q_lane_s16(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst4q_lane_s32(i32* %a, [8 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4q_lane_s32(
// 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
@@ -21434,7 +19189,7 @@ void test_vst4q_lane_s32(int32_t * a, int32x4x4_t b) {
vst4q_lane_s32(a, b, 3);
}
-// CHECK-LABEL: define void @test_vst4q_lane_f16(half* %a, [8 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4q_lane_f16(
// 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
@@ -21470,7 +19225,7 @@ void test_vst4q_lane_f16(float16_t * a, float16x8x4_t b) {
vst4q_lane_f16(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst4q_lane_f32(float* %a, [8 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4q_lane_f32(
// 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
@@ -21506,7 +19261,7 @@ void test_vst4q_lane_f32(float32_t * a, float32x4x4_t b) {
vst4q_lane_f32(a, b, 3);
}
-// CHECK-LABEL: define void @test_vst4q_lane_p16(i16* %a, [8 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4q_lane_p16(
// 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
@@ -21542,7 +19297,7 @@ void test_vst4q_lane_p16(poly16_t * a, poly16x8x4_t b) {
vst4q_lane_p16(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst4_lane_u8(i8* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4_lane_u8(
// 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
@@ -21569,7 +19324,7 @@ void test_vst4_lane_u8(uint8_t * a, uint8x8x4_t b) {
vst4_lane_u8(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst4_lane_u16(i16* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4_lane_u16(
// 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
@@ -21605,7 +19360,7 @@ void test_vst4_lane_u16(uint16_t * a, uint16x4x4_t b) {
vst4_lane_u16(a, b, 3);
}
-// CHECK-LABEL: define void @test_vst4_lane_u32(i32* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4_lane_u32(
// 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
@@ -21641,7 +19396,7 @@ void test_vst4_lane_u32(uint32_t * a, uint32x2x4_t b) {
vst4_lane_u32(a, b, 1);
}
-// CHECK-LABEL: define void @test_vst4_lane_s8(i8* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4_lane_s8(
// 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
@@ -21668,7 +19423,7 @@ void test_vst4_lane_s8(int8_t * a, int8x8x4_t b) {
vst4_lane_s8(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst4_lane_s16(i16* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4_lane_s16(
// 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
@@ -21704,7 +19459,7 @@ void test_vst4_lane_s16(int16_t * a, int16x4x4_t b) {
vst4_lane_s16(a, b, 3);
}
-// CHECK-LABEL: define void @test_vst4_lane_s32(i32* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4_lane_s32(
// 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
@@ -21740,7 +19495,7 @@ void test_vst4_lane_s32(int32_t * a, int32x2x4_t b) {
vst4_lane_s32(a, b, 1);
}
-// CHECK-LABEL: define void @test_vst4_lane_f16(half* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4_lane_f16(
// 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
@@ -21776,7 +19531,7 @@ void test_vst4_lane_f16(float16_t * a, float16x4x4_t b) {
vst4_lane_f16(a, b, 3);
}
-// CHECK-LABEL: define void @test_vst4_lane_f32(float* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4_lane_f32(
// 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
@@ -21812,7 +19567,7 @@ void test_vst4_lane_f32(float32_t * a, float32x2x4_t b) {
vst4_lane_f32(a, b, 1);
}
-// CHECK-LABEL: define void @test_vst4_lane_p8(i8* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4_lane_p8(
// 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
@@ -21839,7 +19594,7 @@ void test_vst4_lane_p8(poly8_t * a, poly8x8x4_t b) {
vst4_lane_p8(a, b, 7);
}
-// CHECK-LABEL: define void @test_vst4_lane_p16(i16* %a, [4 x i64] %b.coerce) #0 {
+// CHECK-LABEL: @test_vst4_lane_p16(
// 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
@@ -21875,140 +19630,136 @@ void test_vst4_lane_p16(poly16_t * a, poly16x4x4_t b) {
vst4_lane_p16(a, b, 3);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vsub_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsub_s8(
// CHECK: [[SUB_I:%.*]] = sub <8 x i8> %a, %b
// CHECK: ret <8 x i8> [[SUB_I]]
int8x8_t test_vsub_s8(int8x8_t a, int8x8_t b) {
return vsub_s8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vsub_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsub_s16(
// CHECK: [[SUB_I:%.*]] = sub <4 x i16> %a, %b
// CHECK: ret <4 x i16> [[SUB_I]]
int16x4_t test_vsub_s16(int16x4_t a, int16x4_t b) {
return vsub_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vsub_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsub_s32(
// CHECK: [[SUB_I:%.*]] = sub <2 x i32> %a, %b
// CHECK: ret <2 x i32> [[SUB_I]]
int32x2_t test_vsub_s32(int32x2_t a, int32x2_t b) {
return vsub_s32(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vsub_s64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vsub_s64(
// CHECK: [[SUB_I:%.*]] = sub <1 x i64> %a, %b
// CHECK: ret <1 x i64> [[SUB_I]]
int64x1_t test_vsub_s64(int64x1_t a, int64x1_t b) {
return vsub_s64(a, b);
}
-// CHECK-LABEL: define <2 x float> @test_vsub_f32(<2 x float> %a, <2 x float> %b) #0 {
+// CHECK-LABEL: @test_vsub_f32(
// CHECK: [[SUB_I:%.*]] = fsub <2 x float> %a, %b
// CHECK: ret <2 x float> [[SUB_I]]
float32x2_t test_vsub_f32(float32x2_t a, float32x2_t b) {
return vsub_f32(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vsub_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsub_u8(
// CHECK: [[SUB_I:%.*]] = sub <8 x i8> %a, %b
// CHECK: ret <8 x i8> [[SUB_I]]
uint8x8_t test_vsub_u8(uint8x8_t a, uint8x8_t b) {
return vsub_u8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vsub_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsub_u16(
// CHECK: [[SUB_I:%.*]] = sub <4 x i16> %a, %b
// CHECK: ret <4 x i16> [[SUB_I]]
uint16x4_t test_vsub_u16(uint16x4_t a, uint16x4_t b) {
return vsub_u16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vsub_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsub_u32(
// CHECK: [[SUB_I:%.*]] = sub <2 x i32> %a, %b
// CHECK: ret <2 x i32> [[SUB_I]]
uint32x2_t test_vsub_u32(uint32x2_t a, uint32x2_t b) {
return vsub_u32(a, b);
}
-// CHECK-LABEL: define <1 x i64> @test_vsub_u64(<1 x i64> %a, <1 x i64> %b) #0 {
+// CHECK-LABEL: @test_vsub_u64(
// CHECK: [[SUB_I:%.*]] = sub <1 x i64> %a, %b
// CHECK: ret <1 x i64> [[SUB_I]]
uint64x1_t test_vsub_u64(uint64x1_t a, uint64x1_t b) {
return vsub_u64(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vsubq_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsubq_s8(
// CHECK: [[SUB_I:%.*]] = sub <16 x i8> %a, %b
// CHECK: ret <16 x i8> [[SUB_I]]
int8x16_t test_vsubq_s8(int8x16_t a, int8x16_t b) {
return vsubq_s8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vsubq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsubq_s16(
// CHECK: [[SUB_I:%.*]] = sub <8 x i16> %a, %b
// CHECK: ret <8 x i16> [[SUB_I]]
int16x8_t test_vsubq_s16(int16x8_t a, int16x8_t b) {
return vsubq_s16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vsubq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsubq_s32(
// CHECK: [[SUB_I:%.*]] = sub <4 x i32> %a, %b
// CHECK: ret <4 x i32> [[SUB_I]]
int32x4_t test_vsubq_s32(int32x4_t a, int32x4_t b) {
return vsubq_s32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vsubq_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vsubq_s64(
// CHECK: [[SUB_I:%.*]] = sub <2 x i64> %a, %b
// CHECK: ret <2 x i64> [[SUB_I]]
int64x2_t test_vsubq_s64(int64x2_t a, int64x2_t b) {
return vsubq_s64(a, b);
}
-// CHECK-LABEL: define <4 x float> @test_vsubq_f32(<4 x float> %a, <4 x float> %b) #0 {
+// CHECK-LABEL: @test_vsubq_f32(
// CHECK: [[SUB_I:%.*]] = fsub <4 x float> %a, %b
// CHECK: ret <4 x float> [[SUB_I]]
float32x4_t test_vsubq_f32(float32x4_t a, float32x4_t b) {
return vsubq_f32(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vsubq_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsubq_u8(
// CHECK: [[SUB_I:%.*]] = sub <16 x i8> %a, %b
// CHECK: ret <16 x i8> [[SUB_I]]
uint8x16_t test_vsubq_u8(uint8x16_t a, uint8x16_t b) {
return vsubq_u8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vsubq_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsubq_u16(
// CHECK: [[SUB_I:%.*]] = sub <8 x i16> %a, %b
// CHECK: ret <8 x i16> [[SUB_I]]
uint16x8_t test_vsubq_u16(uint16x8_t a, uint16x8_t b) {
return vsubq_u16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vsubq_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsubq_u32(
// CHECK: [[SUB_I:%.*]] = sub <4 x i32> %a, %b
// CHECK: ret <4 x i32> [[SUB_I]]
uint32x4_t test_vsubq_u32(uint32x4_t a, uint32x4_t b) {
return vsubq_u32(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vsubq_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vsubq_u64(
// CHECK: [[SUB_I:%.*]] = sub <2 x i64> %a, %b
// CHECK: ret <2 x i64> [[SUB_I]]
uint64x2_t test_vsubq_u64(uint64x2_t a, uint64x2_t b) {
return vsubq_u64(a, b);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vsubhn_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsubhn_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VSUBHN_I:%.*]] = sub <8 x i16> [[TMP2]], [[TMP3]]
+// CHECK: [[VSUBHN_I:%.*]] = sub <8 x i16> %a, %b
// CHECK: [[VSUBHN1_I:%.*]] = lshr <8 x i16> [[VSUBHN_I]], <i16 8, i16 8, i16 8, i16 8, i16 8, i16 8, i16 8, i16 8>
// CHECK: [[VSUBHN2_I:%.*]] = trunc <8 x i16> [[VSUBHN1_I]] to <8 x i8>
// CHECK: ret <8 x i8> [[VSUBHN2_I]]
@@ -22016,12 +19767,10 @@ int8x8_t test_vsubhn_s16(int16x8_t a, int16x8_t b) {
return vsubhn_s16(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vsubhn_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsubhn_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VSUBHN_I:%.*]] = sub <4 x i32> [[TMP2]], [[TMP3]]
+// CHECK: [[VSUBHN_I:%.*]] = sub <4 x i32> %a, %b
// CHECK: [[VSUBHN1_I:%.*]] = lshr <4 x i32> [[VSUBHN_I]], <i32 16, i32 16, i32 16, i32 16>
// CHECK: [[VSUBHN2_I:%.*]] = trunc <4 x i32> [[VSUBHN1_I]] to <4 x i16>
// CHECK: ret <4 x i16> [[VSUBHN2_I]]
@@ -22029,12 +19778,10 @@ int16x4_t test_vsubhn_s32(int32x4_t a, int32x4_t b) {
return vsubhn_s32(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vsubhn_s64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vsubhn_s64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VSUBHN_I:%.*]] = sub <2 x i64> [[TMP2]], [[TMP3]]
+// CHECK: [[VSUBHN_I:%.*]] = sub <2 x i64> %a, %b
// CHECK: [[VSUBHN1_I:%.*]] = lshr <2 x i64> [[VSUBHN_I]], <i64 32, i64 32>
// CHECK: [[VSUBHN2_I:%.*]] = trunc <2 x i64> [[VSUBHN1_I]] to <2 x i32>
// CHECK: ret <2 x i32> [[VSUBHN2_I]]
@@ -22042,12 +19789,10 @@ int32x2_t test_vsubhn_s64(int64x2_t a, int64x2_t b) {
return vsubhn_s64(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vsubhn_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsubhn_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[VSUBHN_I:%.*]] = sub <8 x i16> [[TMP2]], [[TMP3]]
+// CHECK: [[VSUBHN_I:%.*]] = sub <8 x i16> %a, %b
// CHECK: [[VSUBHN1_I:%.*]] = lshr <8 x i16> [[VSUBHN_I]], <i16 8, i16 8, i16 8, i16 8, i16 8, i16 8, i16 8, i16 8>
// CHECK: [[VSUBHN2_I:%.*]] = trunc <8 x i16> [[VSUBHN1_I]] to <8 x i8>
// CHECK: ret <8 x i8> [[VSUBHN2_I]]
@@ -22055,12 +19800,10 @@ uint8x8_t test_vsubhn_u16(uint16x8_t a, uint16x8_t b) {
return vsubhn_u16(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vsubhn_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsubhn_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[VSUBHN_I:%.*]] = sub <4 x i32> [[TMP2]], [[TMP3]]
+// CHECK: [[VSUBHN_I:%.*]] = sub <4 x i32> %a, %b
// CHECK: [[VSUBHN1_I:%.*]] = lshr <4 x i32> [[VSUBHN_I]], <i32 16, i32 16, i32 16, i32 16>
// CHECK: [[VSUBHN2_I:%.*]] = trunc <4 x i32> [[VSUBHN1_I]] to <4 x i16>
// CHECK: ret <4 x i16> [[VSUBHN2_I]]
@@ -22068,12 +19811,10 @@ uint16x4_t test_vsubhn_u32(uint32x4_t a, uint32x4_t b) {
return vsubhn_u32(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vsubhn_u64(<2 x i64> %a, <2 x i64> %b) #0 {
+// CHECK-LABEL: @test_vsubhn_u64(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i64> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i64> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64>
-// CHECK: [[VSUBHN_I:%.*]] = sub <2 x i64> [[TMP2]], [[TMP3]]
+// CHECK: [[VSUBHN_I:%.*]] = sub <2 x i64> %a, %b
// CHECK: [[VSUBHN1_I:%.*]] = lshr <2 x i64> [[VSUBHN_I]], <i64 32, i64 32>
// CHECK: [[VSUBHN2_I:%.*]] = trunc <2 x i64> [[VSUBHN1_I]] to <2 x i32>
// CHECK: ret <2 x i32> [[VSUBHN2_I]]
@@ -22081,8 +19822,7 @@ uint32x2_t test_vsubhn_u64(uint64x2_t a, uint64x2_t b) {
return vsubhn_u64(a, b);
}
-
-// CHECK-LABEL: define <8 x i16> @test_vsubl_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsubl_s8(
// CHECK: [[VMOVL_I_I:%.*]] = sext <8 x i8> %a to <8 x i16>
// CHECK: [[VMOVL_I4_I:%.*]] = sext <8 x i8> %b to <8 x i16>
// CHECK: [[SUB_I:%.*]] = sub <8 x i16> [[VMOVL_I_I]], [[VMOVL_I4_I]]
@@ -22091,33 +19831,29 @@ int16x8_t test_vsubl_s8(int8x8_t a, int8x8_t b) {
return vsubl_s8(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vsubl_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsubl_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMOVL_I_I:%.*]] = sext <4 x i16> [[TMP1]] to <4 x i32>
-// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VMOVL_I4_I:%.*]] = sext <4 x i16> [[TMP3]] to <4 x i32>
+// CHECK: [[VMOVL_I_I:%.*]] = sext <4 x i16> %a to <4 x i32>
+// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
+// CHECK: [[VMOVL_I4_I:%.*]] = sext <4 x i16> %b to <4 x i32>
// CHECK: [[SUB_I:%.*]] = sub <4 x i32> [[VMOVL_I_I]], [[VMOVL_I4_I]]
// CHECK: ret <4 x i32> [[SUB_I]]
int32x4_t test_vsubl_s16(int16x4_t a, int16x4_t b) {
return vsubl_s16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vsubl_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsubl_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMOVL_I_I:%.*]] = sext <2 x i32> [[TMP1]] to <2 x i64>
-// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VMOVL_I4_I:%.*]] = sext <2 x i32> [[TMP3]] to <2 x i64>
+// CHECK: [[VMOVL_I_I:%.*]] = sext <2 x i32> %a to <2 x i64>
+// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
+// CHECK: [[VMOVL_I4_I:%.*]] = sext <2 x i32> %b to <2 x i64>
// CHECK: [[SUB_I:%.*]] = sub <2 x i64> [[VMOVL_I_I]], [[VMOVL_I4_I]]
// CHECK: ret <2 x i64> [[SUB_I]]
int64x2_t test_vsubl_s32(int32x2_t a, int32x2_t b) {
return vsubl_s32(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vsubl_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsubl_u8(
// CHECK: [[VMOVL_I_I:%.*]] = zext <8 x i8> %a to <8 x i16>
// CHECK: [[VMOVL_I4_I:%.*]] = zext <8 x i8> %b to <8 x i16>
// CHECK: [[SUB_I:%.*]] = sub <8 x i16> [[VMOVL_I_I]], [[VMOVL_I4_I]]
@@ -22126,34 +19862,29 @@ uint16x8_t test_vsubl_u8(uint8x8_t a, uint8x8_t b) {
return vsubl_u8(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vsubl_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsubl_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMOVL_I_I:%.*]] = zext <4 x i16> [[TMP1]] to <4 x i32>
-// CHECK: [[TMP2:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VMOVL_I4_I:%.*]] = zext <4 x i16> [[TMP3]] to <4 x i32>
+// CHECK: [[VMOVL_I_I:%.*]] = zext <4 x i16> %a to <4 x i32>
+// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
+// CHECK: [[VMOVL_I4_I:%.*]] = zext <4 x i16> %b to <4 x i32>
// CHECK: [[SUB_I:%.*]] = sub <4 x i32> [[VMOVL_I_I]], [[VMOVL_I4_I]]
// CHECK: ret <4 x i32> [[SUB_I]]
uint32x4_t test_vsubl_u16(uint16x4_t a, uint16x4_t b) {
return vsubl_u16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vsubl_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsubl_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMOVL_I_I:%.*]] = zext <2 x i32> [[TMP1]] to <2 x i64>
-// CHECK: [[TMP2:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VMOVL_I4_I:%.*]] = zext <2 x i32> [[TMP3]] to <2 x i64>
+// CHECK: [[VMOVL_I_I:%.*]] = zext <2 x i32> %a to <2 x i64>
+// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
+// CHECK: [[VMOVL_I4_I:%.*]] = zext <2 x i32> %b to <2 x i64>
// CHECK: [[SUB_I:%.*]] = sub <2 x i64> [[VMOVL_I_I]], [[VMOVL_I4_I]]
// CHECK: ret <2 x i64> [[SUB_I]]
uint64x2_t test_vsubl_u32(uint32x2_t a, uint32x2_t b) {
return vsubl_u32(a, b);
}
-
-// CHECK-LABEL: define <8 x i16> @test_vsubw_s8(<8 x i16> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsubw_s8(
// CHECK: [[VMOVL_I_I:%.*]] = sext <8 x i8> %b to <8 x i16>
// CHECK: [[SUB_I:%.*]] = sub <8 x i16> %a, [[VMOVL_I_I]]
// CHECK: ret <8 x i16> [[SUB_I]]
@@ -22161,27 +19892,25 @@ int16x8_t test_vsubw_s8(int16x8_t a, int8x8_t b) {
return vsubw_s8(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vsubw_s16(<4 x i32> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsubw_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMOVL_I_I:%.*]] = sext <4 x i16> [[TMP1]] to <4 x i32>
+// CHECK: [[VMOVL_I_I:%.*]] = sext <4 x i16> %b to <4 x i32>
// CHECK: [[SUB_I:%.*]] = sub <4 x i32> %a, [[VMOVL_I_I]]
// CHECK: ret <4 x i32> [[SUB_I]]
int32x4_t test_vsubw_s16(int32x4_t a, int16x4_t b) {
return vsubw_s16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vsubw_s32(<2 x i64> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsubw_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMOVL_I_I:%.*]] = sext <2 x i32> [[TMP1]] to <2 x i64>
+// CHECK: [[VMOVL_I_I:%.*]] = sext <2 x i32> %b to <2 x i64>
// CHECK: [[SUB_I:%.*]] = sub <2 x i64> %a, [[VMOVL_I_I]]
// CHECK: ret <2 x i64> [[SUB_I]]
int64x2_t test_vsubw_s32(int64x2_t a, int32x2_t b) {
return vsubw_s32(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vsubw_u8(<8 x i16> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vsubw_u8(
// CHECK: [[VMOVL_I_I:%.*]] = zext <8 x i8> %b to <8 x i16>
// CHECK: [[SUB_I:%.*]] = sub <8 x i16> %a, [[VMOVL_I_I]]
// CHECK: ret <8 x i16> [[SUB_I]]
@@ -22189,50 +19918,46 @@ uint16x8_t test_vsubw_u8(uint16x8_t a, uint8x8_t b) {
return vsubw_u8(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vsubw_u16(<4 x i32> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vsubw_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[VMOVL_I_I:%.*]] = zext <4 x i16> [[TMP1]] to <4 x i32>
+// CHECK: [[VMOVL_I_I:%.*]] = zext <4 x i16> %b to <4 x i32>
// CHECK: [[SUB_I:%.*]] = sub <4 x i32> %a, [[VMOVL_I_I]]
// CHECK: ret <4 x i32> [[SUB_I]]
uint32x4_t test_vsubw_u16(uint32x4_t a, uint16x4_t b) {
return vsubw_u16(a, b);
}
-// CHECK-LABEL: define <2 x i64> @test_vsubw_u32(<2 x i64> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vsubw_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[VMOVL_I_I:%.*]] = zext <2 x i32> [[TMP1]] to <2 x i64>
+// CHECK: [[VMOVL_I_I:%.*]] = zext <2 x i32> %b to <2 x i64>
// CHECK: [[SUB_I:%.*]] = sub <2 x i64> %a, [[VMOVL_I_I]]
// CHECK: ret <2 x i64> [[SUB_I]]
uint64x2_t test_vsubw_u32(uint64x2_t a, uint32x2_t b) {
return vsubw_u32(a, b);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vtbl1_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vtbl1_u8(
// CHECK: [[VTBL1_I:%.*]] = call <8 x i8> @llvm.arm.neon.vtbl1(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VTBL1_I]]
uint8x8_t test_vtbl1_u8(uint8x8_t a, uint8x8_t b) {
return vtbl1_u8(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vtbl1_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vtbl1_s8(
// CHECK: [[VTBL1_I:%.*]] = call <8 x i8> @llvm.arm.neon.vtbl1(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VTBL1_I]]
int8x8_t test_vtbl1_s8(int8x8_t a, int8x8_t b) {
return vtbl1_s8(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vtbl1_p8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vtbl1_p8(
// CHECK: [[VTBL1_I:%.*]] = call <8 x i8> @llvm.arm.neon.vtbl1(<8 x i8> %a, <8 x i8> %b) #4
// CHECK: ret <8 x i8> [[VTBL1_I]]
poly8x8_t test_vtbl1_p8(poly8x8_t a, uint8x8_t b) {
return vtbl1_p8(a, b);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vtbl2_u8([2 x i64] %a.coerce, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vtbl2_u8(
// CHECK: [[__P0_I:%.*]] = alloca %struct.uint8x8x2_t, align 8
// CHECK: [[A:%.*]] = alloca %struct.uint8x8x2_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint8x8x2_t, %struct.uint8x8x2_t* [[A]], i32 0, i32 0
@@ -22256,7 +19981,7 @@ uint8x8_t test_vtbl2_u8(uint8x8x2_t a, uint8x8_t b) {
return vtbl2_u8(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vtbl2_s8([2 x i64] %a.coerce, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vtbl2_s8(
// CHECK: [[__P0_I:%.*]] = alloca %struct.int8x8x2_t, align 8
// CHECK: [[A:%.*]] = alloca %struct.int8x8x2_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int8x8x2_t, %struct.int8x8x2_t* [[A]], i32 0, i32 0
@@ -22280,7 +20005,7 @@ int8x8_t test_vtbl2_s8(int8x8x2_t a, int8x8_t b) {
return vtbl2_s8(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vtbl2_p8([2 x i64] %a.coerce, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vtbl2_p8(
// CHECK: [[__P0_I:%.*]] = alloca %struct.poly8x8x2_t, align 8
// CHECK: [[A:%.*]] = alloca %struct.poly8x8x2_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly8x8x2_t, %struct.poly8x8x2_t* [[A]], i32 0, i32 0
@@ -22304,8 +20029,7 @@ poly8x8_t test_vtbl2_p8(poly8x8x2_t a, uint8x8_t b) {
return vtbl2_p8(a, b);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vtbl3_u8([3 x i64] %a.coerce, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vtbl3_u8(
// CHECK: [[__P0_I:%.*]] = alloca %struct.uint8x8x3_t, align 8
// CHECK: [[A:%.*]] = alloca %struct.uint8x8x3_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint8x8x3_t, %struct.uint8x8x3_t* [[A]], i32 0, i32 0
@@ -22332,7 +20056,7 @@ uint8x8_t test_vtbl3_u8(uint8x8x3_t a, uint8x8_t b) {
return vtbl3_u8(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vtbl3_s8([3 x i64] %a.coerce, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vtbl3_s8(
// CHECK: [[__P0_I:%.*]] = alloca %struct.int8x8x3_t, align 8
// CHECK: [[A:%.*]] = alloca %struct.int8x8x3_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int8x8x3_t, %struct.int8x8x3_t* [[A]], i32 0, i32 0
@@ -22359,7 +20083,7 @@ int8x8_t test_vtbl3_s8(int8x8x3_t a, int8x8_t b) {
return vtbl3_s8(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vtbl3_p8([3 x i64] %a.coerce, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vtbl3_p8(
// CHECK: [[__P0_I:%.*]] = alloca %struct.poly8x8x3_t, align 8
// CHECK: [[A:%.*]] = alloca %struct.poly8x8x3_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly8x8x3_t, %struct.poly8x8x3_t* [[A]], i32 0, i32 0
@@ -22386,8 +20110,7 @@ poly8x8_t test_vtbl3_p8(poly8x8x3_t a, uint8x8_t b) {
return vtbl3_p8(a, b);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vtbl4_u8([4 x i64] %a.coerce, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vtbl4_u8(
// CHECK: [[__P0_I:%.*]] = alloca %struct.uint8x8x4_t, align 8
// CHECK: [[A:%.*]] = alloca %struct.uint8x8x4_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint8x8x4_t, %struct.uint8x8x4_t* [[A]], i32 0, i32 0
@@ -22417,7 +20140,7 @@ uint8x8_t test_vtbl4_u8(uint8x8x4_t a, uint8x8_t b) {
return vtbl4_u8(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vtbl4_s8([4 x i64] %a.coerce, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vtbl4_s8(
// CHECK: [[__P0_I:%.*]] = alloca %struct.int8x8x4_t, align 8
// CHECK: [[A:%.*]] = alloca %struct.int8x8x4_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int8x8x4_t, %struct.int8x8x4_t* [[A]], i32 0, i32 0
@@ -22447,7 +20170,7 @@ int8x8_t test_vtbl4_s8(int8x8x4_t a, int8x8_t b) {
return vtbl4_s8(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vtbl4_p8([4 x i64] %a.coerce, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vtbl4_p8(
// CHECK: [[__P0_I:%.*]] = alloca %struct.poly8x8x4_t, align 8
// CHECK: [[A:%.*]] = alloca %struct.poly8x8x4_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly8x8x4_t, %struct.poly8x8x4_t* [[A]], i32 0, i32 0
@@ -22477,30 +20200,28 @@ poly8x8_t test_vtbl4_p8(poly8x8x4_t a, uint8x8_t b) {
return vtbl4_p8(a, b);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vtbx1_u8(<8 x i8> %a, <8 x i8> %b, <8 x i8> %c) #0 {
+// CHECK-LABEL: @test_vtbx1_u8(
// CHECK: [[VTBX1_I:%.*]] = call <8 x i8> @llvm.arm.neon.vtbx1(<8 x i8> %a, <8 x i8> %b, <8 x i8> %c) #4
// CHECK: ret <8 x i8> [[VTBX1_I]]
uint8x8_t test_vtbx1_u8(uint8x8_t a, uint8x8_t b, uint8x8_t c) {
return vtbx1_u8(a, b, c);
}
-// CHECK-LABEL: define <8 x i8> @test_vtbx1_s8(<8 x i8> %a, <8 x i8> %b, <8 x i8> %c) #0 {
+// CHECK-LABEL: @test_vtbx1_s8(
// CHECK: [[VTBX1_I:%.*]] = call <8 x i8> @llvm.arm.neon.vtbx1(<8 x i8> %a, <8 x i8> %b, <8 x i8> %c) #4
// CHECK: ret <8 x i8> [[VTBX1_I]]
int8x8_t test_vtbx1_s8(int8x8_t a, int8x8_t b, int8x8_t c) {
return vtbx1_s8(a, b, c);
}
-// CHECK-LABEL: define <8 x i8> @test_vtbx1_p8(<8 x i8> %a, <8 x i8> %b, <8 x i8> %c) #0 {
+// CHECK-LABEL: @test_vtbx1_p8(
// CHECK: [[VTBX1_I:%.*]] = call <8 x i8> @llvm.arm.neon.vtbx1(<8 x i8> %a, <8 x i8> %b, <8 x i8> %c) #4
// CHECK: ret <8 x i8> [[VTBX1_I]]
poly8x8_t test_vtbx1_p8(poly8x8_t a, poly8x8_t b, uint8x8_t c) {
return vtbx1_p8(a, b, c);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vtbx2_u8(<8 x i8> %a, [2 x i64] %b.coerce, <8 x i8> %c) #0 {
+// CHECK-LABEL: @test_vtbx2_u8(
// CHECK: [[__P1_I:%.*]] = alloca %struct.uint8x8x2_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.uint8x8x2_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint8x8x2_t, %struct.uint8x8x2_t* [[B]], i32 0, i32 0
@@ -22524,7 +20245,7 @@ uint8x8_t test_vtbx2_u8(uint8x8_t a, uint8x8x2_t b, uint8x8_t c) {
return vtbx2_u8(a, b, c);
}
-// CHECK-LABEL: define <8 x i8> @test_vtbx2_s8(<8 x i8> %a, [2 x i64] %b.coerce, <8 x i8> %c) #0 {
+// CHECK-LABEL: @test_vtbx2_s8(
// CHECK: [[__P1_I:%.*]] = alloca %struct.int8x8x2_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.int8x8x2_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int8x8x2_t, %struct.int8x8x2_t* [[B]], i32 0, i32 0
@@ -22548,7 +20269,7 @@ int8x8_t test_vtbx2_s8(int8x8_t a, int8x8x2_t b, int8x8_t c) {
return vtbx2_s8(a, b, c);
}
-// CHECK-LABEL: define <8 x i8> @test_vtbx2_p8(<8 x i8> %a, [2 x i64] %b.coerce, <8 x i8> %c) #0 {
+// CHECK-LABEL: @test_vtbx2_p8(
// CHECK: [[__P1_I:%.*]] = alloca %struct.poly8x8x2_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.poly8x8x2_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly8x8x2_t, %struct.poly8x8x2_t* [[B]], i32 0, i32 0
@@ -22572,8 +20293,7 @@ poly8x8_t test_vtbx2_p8(poly8x8_t a, poly8x8x2_t b, uint8x8_t c) {
return vtbx2_p8(a, b, c);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vtbx3_u8(<8 x i8> %a, [3 x i64] %b.coerce, <8 x i8> %c) #0 {
+// CHECK-LABEL: @test_vtbx3_u8(
// CHECK: [[__P1_I:%.*]] = alloca %struct.uint8x8x3_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.uint8x8x3_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint8x8x3_t, %struct.uint8x8x3_t* [[B]], i32 0, i32 0
@@ -22600,7 +20320,7 @@ uint8x8_t test_vtbx3_u8(uint8x8_t a, uint8x8x3_t b, uint8x8_t c) {
return vtbx3_u8(a, b, c);
}
-// CHECK-LABEL: define <8 x i8> @test_vtbx3_s8(<8 x i8> %a, [3 x i64] %b.coerce, <8 x i8> %c) #0 {
+// CHECK-LABEL: @test_vtbx3_s8(
// CHECK: [[__P1_I:%.*]] = alloca %struct.int8x8x3_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.int8x8x3_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int8x8x3_t, %struct.int8x8x3_t* [[B]], i32 0, i32 0
@@ -22627,7 +20347,7 @@ int8x8_t test_vtbx3_s8(int8x8_t a, int8x8x3_t b, int8x8_t c) {
return vtbx3_s8(a, b, c);
}
-// CHECK-LABEL: define <8 x i8> @test_vtbx3_p8(<8 x i8> %a, [3 x i64] %b.coerce, <8 x i8> %c) #0 {
+// CHECK-LABEL: @test_vtbx3_p8(
// CHECK: [[__P1_I:%.*]] = alloca %struct.poly8x8x3_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.poly8x8x3_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly8x8x3_t, %struct.poly8x8x3_t* [[B]], i32 0, i32 0
@@ -22654,8 +20374,7 @@ poly8x8_t test_vtbx3_p8(poly8x8_t a, poly8x8x3_t b, uint8x8_t c) {
return vtbx3_p8(a, b, c);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vtbx4_u8(<8 x i8> %a, [4 x i64] %b.coerce, <8 x i8> %c) #0 {
+// CHECK-LABEL: @test_vtbx4_u8(
// CHECK: [[__P1_I:%.*]] = alloca %struct.uint8x8x4_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.uint8x8x4_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.uint8x8x4_t, %struct.uint8x8x4_t* [[B]], i32 0, i32 0
@@ -22685,7 +20404,7 @@ uint8x8_t test_vtbx4_u8(uint8x8_t a, uint8x8x4_t b, uint8x8_t c) {
return vtbx4_u8(a, b, c);
}
-// CHECK-LABEL: define <8 x i8> @test_vtbx4_s8(<8 x i8> %a, [4 x i64] %b.coerce, <8 x i8> %c) #0 {
+// CHECK-LABEL: @test_vtbx4_s8(
// CHECK: [[__P1_I:%.*]] = alloca %struct.int8x8x4_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.int8x8x4_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.int8x8x4_t, %struct.int8x8x4_t* [[B]], i32 0, i32 0
@@ -22715,7 +20434,7 @@ int8x8_t test_vtbx4_s8(int8x8_t a, int8x8x4_t b, int8x8_t c) {
return vtbx4_s8(a, b, c);
}
-// CHECK-LABEL: define <8 x i8> @test_vtbx4_p8(<8 x i8> %a, [4 x i64] %b.coerce, <8 x i8> %c) #0 {
+// CHECK-LABEL: @test_vtbx4_p8(
// CHECK: [[__P1_I:%.*]] = alloca %struct.poly8x8x4_t, align 8
// CHECK: [[B:%.*]] = alloca %struct.poly8x8x4_t, align 8
// CHECK: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.poly8x8x4_t, %struct.poly8x8x4_t* [[B]], i32 0, i32 0
@@ -22745,16 +20464,15 @@ poly8x8_t test_vtbx4_p8(poly8x8_t a, poly8x8x4_t b, uint8x8_t c) {
return vtbx4_p8(a, b, c);
}
-
-// CHECK-LABEL: define void @test_vtrn_s8(%struct.int8x8x2_t* noalias sret %agg.result, <8 x i8> %a, <8 x i8> %b) #0 {
+// 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: [[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: store <8 x i8> [[VTRN_I]], <8 x i8>* [[TMP1]], !noalias !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]]
+// 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) #4
@@ -22763,57 +20481,53 @@ int8x8x2_t test_vtrn_s8(int8x8_t a, int8x8_t b) {
return vtrn_s8(a, b);
}
-// CHECK-LABEL: define void @test_vtrn_s16(%struct.int16x4x2_t* noalias sret %agg.result, <4 x i16> %a, <4 x i16> %b) #0 {
+// 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: [[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: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[TMP5:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VTRN_I:%.*]] = shufflevector <4 x i16> [[TMP4]], <4 x i16> [[TMP5]], <4 x i32> <i32 0, i32 4, i32 2, i32 6>
-// CHECK: store <4 x i16> [[VTRN_I]], <4 x i16>* [[TMP3]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
-// CHECK: [[VTRN1_I:%.*]] = shufflevector <4 x i16> [[TMP4]], <4 x i16> [[TMP5]], <4 x i32> <i32 1, i32 5, i32 3, i32 7>
-// CHECK: store <4 x i16> [[VTRN1_I]], <4 x i16>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.int16x4x2_t* %agg.result to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.int16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP7]], i8* [[TMP8]], i32 16, i32 8, i1 false) #4
+// 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: [[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) #4
// CHECK: ret void
int16x4x2_t test_vtrn_s16(int16x4_t a, int16x4_t b) {
return vtrn_s16(a, b);
}
-// CHECK-LABEL: define void @test_vtrn_s32(%struct.int32x2x2_t* noalias sret %agg.result, <2 x i32> %a, <2 x i32> %b) #0 {
+// 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: [[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: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[TMP5:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VTRN_I:%.*]] = shufflevector <2 x i32> [[TMP4]], <2 x i32> [[TMP5]], <2 x i32> <i32 0, i32 2>
-// CHECK: store <2 x i32> [[VTRN_I]], <2 x i32>* [[TMP3]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <2 x i32>, <2 x i32>* [[TMP3]], i32 1
-// CHECK: [[VTRN1_I:%.*]] = shufflevector <2 x i32> [[TMP4]], <2 x i32> [[TMP5]], <2 x i32> <i32 1, i32 3>
-// CHECK: store <2 x i32> [[VTRN1_I]], <2 x i32>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.int32x2x2_t* %agg.result to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.int32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP7]], i8* [[TMP8]], i32 16, i32 8, i1 false) #4
+// 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: [[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) #4
// CHECK: ret void
int32x2x2_t test_vtrn_s32(int32x2_t a, int32x2_t b) {
return vtrn_s32(a, b);
}
-// CHECK-LABEL: define void @test_vtrn_u8(%struct.uint8x8x2_t* noalias sret %agg.result, <8 x i8> %a, <8 x i8> %b) #0 {
+// 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: [[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: store <8 x i8> [[VTRN_I]], <8 x i8>* [[TMP1]], !noalias !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]]
+// 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) #4
@@ -22822,78 +20536,72 @@ uint8x8x2_t test_vtrn_u8(uint8x8_t a, uint8x8_t b) {
return vtrn_u8(a, b);
}
-// CHECK-LABEL: define void @test_vtrn_u16(%struct.uint16x4x2_t* noalias sret %agg.result, <4 x i16> %a, <4 x i16> %b) #0 {
+// 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: [[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: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[TMP5:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VTRN_I:%.*]] = shufflevector <4 x i16> [[TMP4]], <4 x i16> [[TMP5]], <4 x i32> <i32 0, i32 4, i32 2, i32 6>
-// CHECK: store <4 x i16> [[VTRN_I]], <4 x i16>* [[TMP3]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
-// CHECK: [[VTRN1_I:%.*]] = shufflevector <4 x i16> [[TMP4]], <4 x i16> [[TMP5]], <4 x i32> <i32 1, i32 5, i32 3, i32 7>
-// CHECK: store <4 x i16> [[VTRN1_I]], <4 x i16>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.uint16x4x2_t* %agg.result to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP7]], i8* [[TMP8]], i32 16, i32 8, i1 false) #4
+// 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: [[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) #4
// CHECK: ret void
uint16x4x2_t test_vtrn_u16(uint16x4_t a, uint16x4_t b) {
return vtrn_u16(a, b);
}
-// CHECK-LABEL: define void @test_vtrn_u32(%struct.uint32x2x2_t* noalias sret %agg.result, <2 x i32> %a, <2 x i32> %b) #0 {
+// 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: [[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: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[TMP5:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VTRN_I:%.*]] = shufflevector <2 x i32> [[TMP4]], <2 x i32> [[TMP5]], <2 x i32> <i32 0, i32 2>
-// CHECK: store <2 x i32> [[VTRN_I]], <2 x i32>* [[TMP3]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <2 x i32>, <2 x i32>* [[TMP3]], i32 1
-// CHECK: [[VTRN1_I:%.*]] = shufflevector <2 x i32> [[TMP4]], <2 x i32> [[TMP5]], <2 x i32> <i32 1, i32 3>
-// CHECK: store <2 x i32> [[VTRN1_I]], <2 x i32>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.uint32x2x2_t* %agg.result to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP7]], i8* [[TMP8]], i32 16, i32 8, i1 false) #4
+// 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: [[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) #4
// CHECK: ret void
uint32x2x2_t test_vtrn_u32(uint32x2_t a, uint32x2_t b) {
return vtrn_u32(a, b);
}
-// CHECK-LABEL: define void @test_vtrn_f32(%struct.float32x2x2_t* noalias sret %agg.result, <2 x float> %a, <2 x float> %b) #0 {
+// 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: [[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: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK: [[TMP5:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x float>
-// CHECK: [[VTRN_I:%.*]] = shufflevector <2 x float> [[TMP4]], <2 x float> [[TMP5]], <2 x i32> <i32 0, i32 2>
-// CHECK: store <2 x float> [[VTRN_I]], <2 x float>* [[TMP3]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <2 x float>, <2 x float>* [[TMP3]], i32 1
-// CHECK: [[VTRN1_I:%.*]] = shufflevector <2 x float> [[TMP4]], <2 x float> [[TMP5]], <2 x i32> <i32 1, i32 3>
-// CHECK: store <2 x float> [[VTRN1_I]], <2 x float>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.float32x2x2_t* %agg.result to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.float32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP7]], i8* [[TMP8]], i32 16, i32 8, i1 false) #4
+// 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: [[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) #4
// CHECK: ret void
float32x2x2_t test_vtrn_f32(float32x2_t a, float32x2_t b) {
return vtrn_f32(a, b);
}
-// CHECK-LABEL: define void @test_vtrn_p8(%struct.poly8x8x2_t* noalias sret %agg.result, <8 x i8> %a, <8 x i8> %b) #0 {
+// 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: [[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: store <8 x i8> [[VTRN_I]], <8 x i8>* [[TMP1]], !noalias !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]]
+// 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) #4
@@ -22902,36 +20610,34 @@ poly8x8x2_t test_vtrn_p8(poly8x8_t a, poly8x8_t b) {
return vtrn_p8(a, b);
}
-// CHECK-LABEL: define void @test_vtrn_p16(%struct.poly16x4x2_t* noalias sret %agg.result, <4 x i16> %a, <4 x i16> %b) #0 {
+// 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: [[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: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[TMP5:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VTRN_I:%.*]] = shufflevector <4 x i16> [[TMP4]], <4 x i16> [[TMP5]], <4 x i32> <i32 0, i32 4, i32 2, i32 6>
-// CHECK: store <4 x i16> [[VTRN_I]], <4 x i16>* [[TMP3]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
-// CHECK: [[VTRN1_I:%.*]] = shufflevector <4 x i16> [[TMP4]], <4 x i16> [[TMP5]], <4 x i32> <i32 1, i32 5, i32 3, i32 7>
-// CHECK: store <4 x i16> [[VTRN1_I]], <4 x i16>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.poly16x4x2_t* %agg.result to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP7]], i8* [[TMP8]], i32 16, i32 8, i1 false) #4
+// 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: [[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) #4
// CHECK: ret void
poly16x4x2_t test_vtrn_p16(poly16x4_t a, poly16x4_t b) {
return vtrn_p16(a, b);
}
-// CHECK-LABEL: define void @test_vtrnq_s8(%struct.int8x16x2_t* noalias sret %agg.result, <16 x i8> %a, <16 x i8> %b) #0 {
+// 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: [[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: store <16 x i8> [[VTRN_I]], <16 x i8>* [[TMP1]], !noalias !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]]
+// 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) #4
@@ -22940,57 +20646,53 @@ int8x16x2_t test_vtrnq_s8(int8x16_t a, int8x16_t b) {
return vtrnq_s8(a, b);
}
-// CHECK-LABEL: define void @test_vtrnq_s16(%struct.int16x8x2_t* noalias sret %agg.result, <8 x i16> %a, <8 x i16> %b) #0 {
+// 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: [[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: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <8 x i16>
-// CHECK: [[VTRN_I:%.*]] = shufflevector <8 x i16> [[TMP4]], <8 x i16> [[TMP5]], <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]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
-// CHECK: [[VTRN1_I:%.*]] = shufflevector <8 x i16> [[TMP4]], <8 x i16> [[TMP5]], <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>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.int16x8x2_t* %agg.result to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.int16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP7]], i8* [[TMP8]], i32 32, i32 16, i1 false) #4
+// 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: [[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) #4
// CHECK: ret void
int16x8x2_t test_vtrnq_s16(int16x8_t a, int16x8_t b) {
return vtrnq_s16(a, b);
}
-// CHECK-LABEL: define void @test_vtrnq_s32(%struct.int32x4x2_t* noalias sret %agg.result, <4 x i32> %a, <4 x i32> %b) #0 {
+// 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: [[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: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <4 x i32>
-// CHECK: [[VTRN_I:%.*]] = shufflevector <4 x i32> [[TMP4]], <4 x i32> [[TMP5]], <4 x i32> <i32 0, i32 4, i32 2, i32 6>
-// CHECK: store <4 x i32> [[VTRN_I]], <4 x i32>* [[TMP3]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <4 x i32>, <4 x i32>* [[TMP3]], i32 1
-// CHECK: [[VTRN1_I:%.*]] = shufflevector <4 x i32> [[TMP4]], <4 x i32> [[TMP5]], <4 x i32> <i32 1, i32 5, i32 3, i32 7>
-// CHECK: store <4 x i32> [[VTRN1_I]], <4 x i32>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.int32x4x2_t* %agg.result to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.int32x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP7]], i8* [[TMP8]], i32 32, i32 16, i1 false) #4
+// 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: [[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) #4
// CHECK: ret void
int32x4x2_t test_vtrnq_s32(int32x4_t a, int32x4_t b) {
return vtrnq_s32(a, b);
}
-// CHECK-LABEL: define void @test_vtrnq_u8(%struct.uint8x16x2_t* noalias sret %agg.result, <16 x i8> %a, <16 x i8> %b) #0 {
+// 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: [[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: store <16 x i8> [[VTRN_I]], <16 x i8>* [[TMP1]], !noalias !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]]
+// 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) #4
@@ -22999,78 +20701,72 @@ uint8x16x2_t test_vtrnq_u8(uint8x16_t a, uint8x16_t b) {
return vtrnq_u8(a, b);
}
-// CHECK-LABEL: define void @test_vtrnq_u16(%struct.uint16x8x2_t* noalias sret %agg.result, <8 x i16> %a, <8 x i16> %b) #0 {
+// 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: [[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: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <8 x i16>
-// CHECK: [[VTRN_I:%.*]] = shufflevector <8 x i16> [[TMP4]], <8 x i16> [[TMP5]], <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]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
-// CHECK: [[VTRN1_I:%.*]] = shufflevector <8 x i16> [[TMP4]], <8 x i16> [[TMP5]], <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>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.uint16x8x2_t* %agg.result to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP7]], i8* [[TMP8]], i32 32, i32 16, i1 false) #4
+// 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: [[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) #4
// CHECK: ret void
uint16x8x2_t test_vtrnq_u16(uint16x8_t a, uint16x8_t b) {
return vtrnq_u16(a, b);
}
-// CHECK-LABEL: define void @test_vtrnq_u32(%struct.uint32x4x2_t* noalias sret %agg.result, <4 x i32> %a, <4 x i32> %b) #0 {
+// 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: [[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: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <4 x i32>
-// CHECK: [[VTRN_I:%.*]] = shufflevector <4 x i32> [[TMP4]], <4 x i32> [[TMP5]], <4 x i32> <i32 0, i32 4, i32 2, i32 6>
-// CHECK: store <4 x i32> [[VTRN_I]], <4 x i32>* [[TMP3]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <4 x i32>, <4 x i32>* [[TMP3]], i32 1
-// CHECK: [[VTRN1_I:%.*]] = shufflevector <4 x i32> [[TMP4]], <4 x i32> [[TMP5]], <4 x i32> <i32 1, i32 5, i32 3, i32 7>
-// CHECK: store <4 x i32> [[VTRN1_I]], <4 x i32>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.uint32x4x2_t* %agg.result to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP7]], i8* [[TMP8]], i32 32, i32 16, i1 false) #4
+// 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: [[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) #4
// CHECK: ret void
uint32x4x2_t test_vtrnq_u32(uint32x4_t a, uint32x4_t b) {
return vtrnq_u32(a, b);
}
-// CHECK-LABEL: define void @test_vtrnq_f32(%struct.float32x4x2_t* noalias sret %agg.result, <4 x float> %a, <4 x float> %b) #0 {
+// 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: [[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: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <4 x float>
-// CHECK: [[VTRN_I:%.*]] = shufflevector <4 x float> [[TMP4]], <4 x float> [[TMP5]], <4 x i32> <i32 0, i32 4, i32 2, i32 6>
-// CHECK: store <4 x float> [[VTRN_I]], <4 x float>* [[TMP3]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <4 x float>, <4 x float>* [[TMP3]], i32 1
-// CHECK: [[VTRN1_I:%.*]] = shufflevector <4 x float> [[TMP4]], <4 x float> [[TMP5]], <4 x i32> <i32 1, i32 5, i32 3, i32 7>
-// CHECK: store <4 x float> [[VTRN1_I]], <4 x float>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.float32x4x2_t* %agg.result to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.float32x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP7]], i8* [[TMP8]], i32 32, i32 16, i1 false) #4
+// 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: [[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) #4
// CHECK: ret void
float32x4x2_t test_vtrnq_f32(float32x4_t a, float32x4_t b) {
return vtrnq_f32(a, b);
}
-// CHECK-LABEL: define void @test_vtrnq_p8(%struct.poly8x16x2_t* noalias sret %agg.result, <16 x i8> %a, <16 x i8> %b) #0 {
+// 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: [[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: store <16 x i8> [[VTRN_I]], <16 x i8>* [[TMP1]], !noalias !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]]
+// 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) #4
@@ -23079,29 +20775,26 @@ poly8x16x2_t test_vtrnq_p8(poly8x16_t a, poly8x16_t b) {
return vtrnq_p8(a, b);
}
-// CHECK-LABEL: define void @test_vtrnq_p16(%struct.poly16x8x2_t* noalias sret %agg.result, <8 x i16> %a, <8 x i16> %b) #0 {
+// 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: [[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: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <8 x i16>
-// CHECK: [[VTRN_I:%.*]] = shufflevector <8 x i16> [[TMP4]], <8 x i16> [[TMP5]], <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]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
-// CHECK: [[VTRN1_I:%.*]] = shufflevector <8 x i16> [[TMP4]], <8 x i16> [[TMP5]], <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>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.poly16x8x2_t* %agg.result to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP7]], i8* [[TMP8]], i32 32, i32 16, i1 false) #4
+// 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: [[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) #4
// CHECK: ret void
poly16x8x2_t test_vtrnq_p16(poly16x8_t a, poly16x8_t b) {
return vtrnq_p16(a, b);
}
-
-// CHECK-LABEL: define <8 x i8> @test_vtst_s8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vtst_s8(
// CHECK: [[TMP0:%.*]] = and <8 x i8> %a, %b
// CHECK: [[TMP1:%.*]] = icmp ne <8 x i8> [[TMP0]], zeroinitializer
// CHECK: [[VTST_I:%.*]] = sext <8 x i1> [[TMP1]] to <8 x i8>
@@ -23110,33 +20803,29 @@ uint8x8_t test_vtst_s8(int8x8_t a, int8x8_t b) {
return vtst_s8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vtst_s16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vtst_s16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[TMP4:%.*]] = and <4 x i16> [[TMP2]], [[TMP3]]
-// CHECK: [[TMP5:%.*]] = icmp ne <4 x i16> [[TMP4]], zeroinitializer
-// CHECK: [[VTST_I:%.*]] = sext <4 x i1> [[TMP5]] to <4 x i16>
+// CHECK: [[TMP2:%.*]] = and <4 x i16> %a, %b
+// CHECK: [[TMP3:%.*]] = icmp ne <4 x i16> [[TMP2]], zeroinitializer
+// CHECK: [[VTST_I:%.*]] = sext <4 x i1> [[TMP3]] to <4 x i16>
// CHECK: ret <4 x i16> [[VTST_I]]
uint16x4_t test_vtst_s16(int16x4_t a, int16x4_t b) {
return vtst_s16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vtst_s32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vtst_s32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[TMP4:%.*]] = and <2 x i32> [[TMP2]], [[TMP3]]
-// CHECK: [[TMP5:%.*]] = icmp ne <2 x i32> [[TMP4]], zeroinitializer
-// CHECK: [[VTST_I:%.*]] = sext <2 x i1> [[TMP5]] to <2 x i32>
+// CHECK: [[TMP2:%.*]] = and <2 x i32> %a, %b
+// CHECK: [[TMP3:%.*]] = icmp ne <2 x i32> [[TMP2]], zeroinitializer
+// CHECK: [[VTST_I:%.*]] = sext <2 x i1> [[TMP3]] to <2 x i32>
// CHECK: ret <2 x i32> [[VTST_I]]
uint32x2_t test_vtst_s32(int32x2_t a, int32x2_t b) {
return vtst_s32(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vtst_u8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vtst_u8(
// CHECK: [[TMP0:%.*]] = and <8 x i8> %a, %b
// CHECK: [[TMP1:%.*]] = icmp ne <8 x i8> [[TMP0]], zeroinitializer
// CHECK: [[VTST_I:%.*]] = sext <8 x i1> [[TMP1]] to <8 x i8>
@@ -23145,33 +20834,29 @@ uint8x8_t test_vtst_u8(uint8x8_t a, uint8x8_t b) {
return vtst_u8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vtst_u16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vtst_u16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[TMP4:%.*]] = and <4 x i16> [[TMP2]], [[TMP3]]
-// CHECK: [[TMP5:%.*]] = icmp ne <4 x i16> [[TMP4]], zeroinitializer
-// CHECK: [[VTST_I:%.*]] = sext <4 x i1> [[TMP5]] to <4 x i16>
+// CHECK: [[TMP2:%.*]] = and <4 x i16> %a, %b
+// CHECK: [[TMP3:%.*]] = icmp ne <4 x i16> [[TMP2]], zeroinitializer
+// CHECK: [[VTST_I:%.*]] = sext <4 x i1> [[TMP3]] to <4 x i16>
// CHECK: ret <4 x i16> [[VTST_I]]
uint16x4_t test_vtst_u16(uint16x4_t a, uint16x4_t b) {
return vtst_u16(a, b);
}
-// CHECK-LABEL: define <2 x i32> @test_vtst_u32(<2 x i32> %a, <2 x i32> %b) #0 {
+// CHECK-LABEL: @test_vtst_u32(
// CHECK: [[TMP0:%.*]] = bitcast <2 x i32> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <2 x i32> %b to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[TMP4:%.*]] = and <2 x i32> [[TMP2]], [[TMP3]]
-// CHECK: [[TMP5:%.*]] = icmp ne <2 x i32> [[TMP4]], zeroinitializer
-// CHECK: [[VTST_I:%.*]] = sext <2 x i1> [[TMP5]] to <2 x i32>
+// CHECK: [[TMP2:%.*]] = and <2 x i32> %a, %b
+// CHECK: [[TMP3:%.*]] = icmp ne <2 x i32> [[TMP2]], zeroinitializer
+// CHECK: [[VTST_I:%.*]] = sext <2 x i1> [[TMP3]] to <2 x i32>
// CHECK: ret <2 x i32> [[VTST_I]]
uint32x2_t test_vtst_u32(uint32x2_t a, uint32x2_t b) {
return vtst_u32(a, b);
}
-// CHECK-LABEL: define <8 x i8> @test_vtst_p8(<8 x i8> %a, <8 x i8> %b) #0 {
+// CHECK-LABEL: @test_vtst_p8(
// CHECK: [[TMP0:%.*]] = and <8 x i8> %a, %b
// CHECK: [[TMP1:%.*]] = icmp ne <8 x i8> [[TMP0]], zeroinitializer
// CHECK: [[VTST_I:%.*]] = sext <8 x i1> [[TMP1]] to <8 x i8>
@@ -23180,20 +20865,18 @@ uint8x8_t test_vtst_p8(poly8x8_t a, poly8x8_t b) {
return vtst_p8(a, b);
}
-// CHECK-LABEL: define <4 x i16> @test_vtst_p16(<4 x i16> %a, <4 x i16> %b) #0 {
+// CHECK-LABEL: @test_vtst_p16(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i16> %a to <8 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i16> %b to <8 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
-// CHECK: [[TMP3:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[TMP4:%.*]] = and <4 x i16> [[TMP2]], [[TMP3]]
-// CHECK: [[TMP5:%.*]] = icmp ne <4 x i16> [[TMP4]], zeroinitializer
-// CHECK: [[VTST_I:%.*]] = sext <4 x i1> [[TMP5]] to <4 x i16>
+// CHECK: [[TMP2:%.*]] = and <4 x i16> %a, %b
+// CHECK: [[TMP3:%.*]] = icmp ne <4 x i16> [[TMP2]], zeroinitializer
+// CHECK: [[VTST_I:%.*]] = sext <4 x i1> [[TMP3]] to <4 x i16>
// CHECK: ret <4 x i16> [[VTST_I]]
uint16x4_t test_vtst_p16(poly16x4_t a, poly16x4_t b) {
return vtst_p16(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vtstq_s8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vtstq_s8(
// CHECK: [[TMP0:%.*]] = and <16 x i8> %a, %b
// CHECK: [[TMP1:%.*]] = icmp ne <16 x i8> [[TMP0]], zeroinitializer
// CHECK: [[VTST_I:%.*]] = sext <16 x i1> [[TMP1]] to <16 x i8>
@@ -23202,33 +20885,29 @@ uint8x16_t test_vtstq_s8(int8x16_t a, int8x16_t b) {
return vtstq_s8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vtstq_s16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vtstq_s16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[TMP4:%.*]] = and <8 x i16> [[TMP2]], [[TMP3]]
-// CHECK: [[TMP5:%.*]] = icmp ne <8 x i16> [[TMP4]], zeroinitializer
-// CHECK: [[VTST_I:%.*]] = sext <8 x i1> [[TMP5]] to <8 x i16>
+// CHECK: [[TMP2:%.*]] = and <8 x i16> %a, %b
+// CHECK: [[TMP3:%.*]] = icmp ne <8 x i16> [[TMP2]], zeroinitializer
+// CHECK: [[VTST_I:%.*]] = sext <8 x i1> [[TMP3]] to <8 x i16>
// CHECK: ret <8 x i16> [[VTST_I]]
uint16x8_t test_vtstq_s16(int16x8_t a, int16x8_t b) {
return vtstq_s16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vtstq_s32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vtstq_s32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[TMP4:%.*]] = and <4 x i32> [[TMP2]], [[TMP3]]
-// CHECK: [[TMP5:%.*]] = icmp ne <4 x i32> [[TMP4]], zeroinitializer
-// CHECK: [[VTST_I:%.*]] = sext <4 x i1> [[TMP5]] to <4 x i32>
+// CHECK: [[TMP2:%.*]] = and <4 x i32> %a, %b
+// CHECK: [[TMP3:%.*]] = icmp ne <4 x i32> [[TMP2]], zeroinitializer
+// CHECK: [[VTST_I:%.*]] = sext <4 x i1> [[TMP3]] to <4 x i32>
// CHECK: ret <4 x i32> [[VTST_I]]
uint32x4_t test_vtstq_s32(int32x4_t a, int32x4_t b) {
return vtstq_s32(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vtstq_u8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vtstq_u8(
// CHECK: [[TMP0:%.*]] = and <16 x i8> %a, %b
// CHECK: [[TMP1:%.*]] = icmp ne <16 x i8> [[TMP0]], zeroinitializer
// CHECK: [[VTST_I:%.*]] = sext <16 x i1> [[TMP1]] to <16 x i8>
@@ -23237,33 +20916,29 @@ uint8x16_t test_vtstq_u8(uint8x16_t a, uint8x16_t b) {
return vtstq_u8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vtstq_u16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vtstq_u16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[TMP4:%.*]] = and <8 x i16> [[TMP2]], [[TMP3]]
-// CHECK: [[TMP5:%.*]] = icmp ne <8 x i16> [[TMP4]], zeroinitializer
-// CHECK: [[VTST_I:%.*]] = sext <8 x i1> [[TMP5]] to <8 x i16>
+// CHECK: [[TMP2:%.*]] = and <8 x i16> %a, %b
+// CHECK: [[TMP3:%.*]] = icmp ne <8 x i16> [[TMP2]], zeroinitializer
+// CHECK: [[VTST_I:%.*]] = sext <8 x i1> [[TMP3]] to <8 x i16>
// CHECK: ret <8 x i16> [[VTST_I]]
uint16x8_t test_vtstq_u16(uint16x8_t a, uint16x8_t b) {
return vtstq_u16(a, b);
}
-// CHECK-LABEL: define <4 x i32> @test_vtstq_u32(<4 x i32> %a, <4 x i32> %b) #0 {
+// CHECK-LABEL: @test_vtstq_u32(
// CHECK: [[TMP0:%.*]] = bitcast <4 x i32> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <4 x i32> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[TMP4:%.*]] = and <4 x i32> [[TMP2]], [[TMP3]]
-// CHECK: [[TMP5:%.*]] = icmp ne <4 x i32> [[TMP4]], zeroinitializer
-// CHECK: [[VTST_I:%.*]] = sext <4 x i1> [[TMP5]] to <4 x i32>
+// CHECK: [[TMP2:%.*]] = and <4 x i32> %a, %b
+// CHECK: [[TMP3:%.*]] = icmp ne <4 x i32> [[TMP2]], zeroinitializer
+// CHECK: [[VTST_I:%.*]] = sext <4 x i1> [[TMP3]] to <4 x i32>
// CHECK: ret <4 x i32> [[VTST_I]]
uint32x4_t test_vtstq_u32(uint32x4_t a, uint32x4_t b) {
return vtstq_u32(a, b);
}
-// CHECK-LABEL: define <16 x i8> @test_vtstq_p8(<16 x i8> %a, <16 x i8> %b) #0 {
+// CHECK-LABEL: @test_vtstq_p8(
// CHECK: [[TMP0:%.*]] = and <16 x i8> %a, %b
// CHECK: [[TMP1:%.*]] = icmp ne <16 x i8> [[TMP0]], zeroinitializer
// CHECK: [[VTST_I:%.*]] = sext <16 x i1> [[TMP1]] to <16 x i8>
@@ -23272,29 +20947,26 @@ uint8x16_t test_vtstq_p8(poly8x16_t a, poly8x16_t b) {
return vtstq_p8(a, b);
}
-// CHECK-LABEL: define <8 x i16> @test_vtstq_p16(<8 x i16> %a, <8 x i16> %b) #0 {
+// CHECK-LABEL: @test_vtstq_p16(
// CHECK: [[TMP0:%.*]] = bitcast <8 x i16> %a to <16 x i8>
// CHECK: [[TMP1:%.*]] = bitcast <8 x i16> %b to <16 x i8>
-// CHECK: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
-// CHECK: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[TMP4:%.*]] = and <8 x i16> [[TMP2]], [[TMP3]]
-// CHECK: [[TMP5:%.*]] = icmp ne <8 x i16> [[TMP4]], zeroinitializer
-// CHECK: [[VTST_I:%.*]] = sext <8 x i1> [[TMP5]] to <8 x i16>
+// CHECK: [[TMP2:%.*]] = and <8 x i16> %a, %b
+// CHECK: [[TMP3:%.*]] = icmp ne <8 x i16> [[TMP2]], zeroinitializer
+// CHECK: [[VTST_I:%.*]] = sext <8 x i1> [[TMP3]] to <8 x i16>
// CHECK: ret <8 x i16> [[VTST_I]]
uint16x8_t test_vtstq_p16(poly16x8_t a, poly16x8_t b) {
return vtstq_p16(a, b);
}
-
-// CHECK-LABEL: define void @test_vuzp_s8(%struct.int8x8x2_t* noalias sret %agg.result, <8 x i8> %a, <8 x i8> %b) #0 {
+// 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: [[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: store <8 x i8> [[VUZP_I]], <8 x i8>* [[TMP1]], !noalias !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]]
+// 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) #4
@@ -23303,57 +20975,53 @@ int8x8x2_t test_vuzp_s8(int8x8_t a, int8x8_t b) {
return vuzp_s8(a, b);
}
-// CHECK-LABEL: define void @test_vuzp_s16(%struct.int16x4x2_t* noalias sret %agg.result, <4 x i16> %a, <4 x i16> %b) #0 {
+// 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: [[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: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[TMP5:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VUZP_I:%.*]] = shufflevector <4 x i16> [[TMP4]], <4 x i16> [[TMP5]], <4 x i32> <i32 0, i32 2, i32 4, i32 6>
-// CHECK: store <4 x i16> [[VUZP_I]], <4 x i16>* [[TMP3]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
-// CHECK: [[VUZP1_I:%.*]] = shufflevector <4 x i16> [[TMP4]], <4 x i16> [[TMP5]], <4 x i32> <i32 1, i32 3, i32 5, i32 7>
-// CHECK: store <4 x i16> [[VUZP1_I]], <4 x i16>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.int16x4x2_t* %agg.result to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.int16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP7]], i8* [[TMP8]], i32 16, i32 8, i1 false) #4
+// 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: [[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) #4
// CHECK: ret void
int16x4x2_t test_vuzp_s16(int16x4_t a, int16x4_t b) {
return vuzp_s16(a, b);
}
-// CHECK-LABEL: define void @test_vuzp_s32(%struct.int32x2x2_t* noalias sret %agg.result, <2 x i32> %a, <2 x i32> %b) #0 {
+// 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: [[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: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[TMP5:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VUZP_I:%.*]] = shufflevector <2 x i32> [[TMP4]], <2 x i32> [[TMP5]], <2 x i32> <i32 0, i32 2>
-// CHECK: store <2 x i32> [[VUZP_I]], <2 x i32>* [[TMP3]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <2 x i32>, <2 x i32>* [[TMP3]], i32 1
-// CHECK: [[VUZP1_I:%.*]] = shufflevector <2 x i32> [[TMP4]], <2 x i32> [[TMP5]], <2 x i32> <i32 1, i32 3>
-// CHECK: store <2 x i32> [[VUZP1_I]], <2 x i32>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.int32x2x2_t* %agg.result to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.int32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP7]], i8* [[TMP8]], i32 16, i32 8, i1 false) #4
+// 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: [[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) #4
// CHECK: ret void
int32x2x2_t test_vuzp_s32(int32x2_t a, int32x2_t b) {
return vuzp_s32(a, b);
}
-// CHECK-LABEL: define void @test_vuzp_u8(%struct.uint8x8x2_t* noalias sret %agg.result, <8 x i8> %a, <8 x i8> %b) #0 {
+// 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: [[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: store <8 x i8> [[VUZP_I]], <8 x i8>* [[TMP1]], !noalias !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]]
+// 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) #4
@@ -23362,78 +21030,72 @@ uint8x8x2_t test_vuzp_u8(uint8x8_t a, uint8x8_t b) {
return vuzp_u8(a, b);
}
-// CHECK-LABEL: define void @test_vuzp_u16(%struct.uint16x4x2_t* noalias sret %agg.result, <4 x i16> %a, <4 x i16> %b) #0 {
+// 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: [[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: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[TMP5:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VUZP_I:%.*]] = shufflevector <4 x i16> [[TMP4]], <4 x i16> [[TMP5]], <4 x i32> <i32 0, i32 2, i32 4, i32 6>
-// CHECK: store <4 x i16> [[VUZP_I]], <4 x i16>* [[TMP3]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
-// CHECK: [[VUZP1_I:%.*]] = shufflevector <4 x i16> [[TMP4]], <4 x i16> [[TMP5]], <4 x i32> <i32 1, i32 3, i32 5, i32 7>
-// CHECK: store <4 x i16> [[VUZP1_I]], <4 x i16>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.uint16x4x2_t* %agg.result to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP7]], i8* [[TMP8]], i32 16, i32 8, i1 false) #4
+// 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: [[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) #4
// CHECK: ret void
uint16x4x2_t test_vuzp_u16(uint16x4_t a, uint16x4_t b) {
return vuzp_u16(a, b);
}
-// CHECK-LABEL: define void @test_vuzp_u32(%struct.uint32x2x2_t* noalias sret %agg.result, <2 x i32> %a, <2 x i32> %b) #0 {
+// 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: [[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: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[TMP5:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VUZP_I:%.*]] = shufflevector <2 x i32> [[TMP4]], <2 x i32> [[TMP5]], <2 x i32> <i32 0, i32 2>
-// CHECK: store <2 x i32> [[VUZP_I]], <2 x i32>* [[TMP3]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <2 x i32>, <2 x i32>* [[TMP3]], i32 1
-// CHECK: [[VUZP1_I:%.*]] = shufflevector <2 x i32> [[TMP4]], <2 x i32> [[TMP5]], <2 x i32> <i32 1, i32 3>
-// CHECK: store <2 x i32> [[VUZP1_I]], <2 x i32>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.uint32x2x2_t* %agg.result to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP7]], i8* [[TMP8]], i32 16, i32 8, i1 false) #4
+// 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: [[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) #4
// CHECK: ret void
uint32x2x2_t test_vuzp_u32(uint32x2_t a, uint32x2_t b) {
return vuzp_u32(a, b);
}
-// CHECK-LABEL: define void @test_vuzp_f32(%struct.float32x2x2_t* noalias sret %agg.result, <2 x float> %a, <2 x float> %b) #0 {
+// 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: [[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: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK: [[TMP5:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x float>
-// CHECK: [[VUZP_I:%.*]] = shufflevector <2 x float> [[TMP4]], <2 x float> [[TMP5]], <2 x i32> <i32 0, i32 2>
-// CHECK: store <2 x float> [[VUZP_I]], <2 x float>* [[TMP3]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <2 x float>, <2 x float>* [[TMP3]], i32 1
-// CHECK: [[VUZP1_I:%.*]] = shufflevector <2 x float> [[TMP4]], <2 x float> [[TMP5]], <2 x i32> <i32 1, i32 3>
-// CHECK: store <2 x float> [[VUZP1_I]], <2 x float>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.float32x2x2_t* %agg.result to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.float32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP7]], i8* [[TMP8]], i32 16, i32 8, i1 false) #4
+// 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: [[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) #4
// CHECK: ret void
float32x2x2_t test_vuzp_f32(float32x2_t a, float32x2_t b) {
return vuzp_f32(a, b);
}
-// CHECK-LABEL: define void @test_vuzp_p8(%struct.poly8x8x2_t* noalias sret %agg.result, <8 x i8> %a, <8 x i8> %b) #0 {
+// 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: [[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: store <8 x i8> [[VUZP_I]], <8 x i8>* [[TMP1]], !noalias !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]]
+// 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) #4
@@ -23442,36 +21104,34 @@ poly8x8x2_t test_vuzp_p8(poly8x8_t a, poly8x8_t b) {
return vuzp_p8(a, b);
}
-// CHECK-LABEL: define void @test_vuzp_p16(%struct.poly16x4x2_t* noalias sret %agg.result, <4 x i16> %a, <4 x i16> %b) #0 {
+// 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: [[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: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[TMP5:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VUZP_I:%.*]] = shufflevector <4 x i16> [[TMP4]], <4 x i16> [[TMP5]], <4 x i32> <i32 0, i32 2, i32 4, i32 6>
-// CHECK: store <4 x i16> [[VUZP_I]], <4 x i16>* [[TMP3]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
-// CHECK: [[VUZP1_I:%.*]] = shufflevector <4 x i16> [[TMP4]], <4 x i16> [[TMP5]], <4 x i32> <i32 1, i32 3, i32 5, i32 7>
-// CHECK: store <4 x i16> [[VUZP1_I]], <4 x i16>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.poly16x4x2_t* %agg.result to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP7]], i8* [[TMP8]], i32 16, i32 8, i1 false) #4
+// 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: [[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) #4
// CHECK: ret void
poly16x4x2_t test_vuzp_p16(poly16x4_t a, poly16x4_t b) {
return vuzp_p16(a, b);
}
-// CHECK-LABEL: define void @test_vuzpq_s8(%struct.int8x16x2_t* noalias sret %agg.result, <16 x i8> %a, <16 x i8> %b) #0 {
+// 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: [[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: store <16 x i8> [[VUZP_I]], <16 x i8>* [[TMP1]], !noalias !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]]
+// 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) #4
@@ -23480,57 +21140,53 @@ int8x16x2_t test_vuzpq_s8(int8x16_t a, int8x16_t b) {
return vuzpq_s8(a, b);
}
-// CHECK-LABEL: define void @test_vuzpq_s16(%struct.int16x8x2_t* noalias sret %agg.result, <8 x i16> %a, <8 x i16> %b) #0 {
+// 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: [[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: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <8 x i16>
-// CHECK: [[VUZP_I:%.*]] = shufflevector <8 x i16> [[TMP4]], <8 x i16> [[TMP5]], <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]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
-// CHECK: [[VUZP1_I:%.*]] = shufflevector <8 x i16> [[TMP4]], <8 x i16> [[TMP5]], <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>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.int16x8x2_t* %agg.result to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.int16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP7]], i8* [[TMP8]], i32 32, i32 16, i1 false) #4
+// 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: [[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) #4
// CHECK: ret void
int16x8x2_t test_vuzpq_s16(int16x8_t a, int16x8_t b) {
return vuzpq_s16(a, b);
}
-// CHECK-LABEL: define void @test_vuzpq_s32(%struct.int32x4x2_t* noalias sret %agg.result, <4 x i32> %a, <4 x i32> %b) #0 {
+// 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: [[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: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <4 x i32>
-// CHECK: [[VUZP_I:%.*]] = shufflevector <4 x i32> [[TMP4]], <4 x i32> [[TMP5]], <4 x i32> <i32 0, i32 2, i32 4, i32 6>
-// CHECK: store <4 x i32> [[VUZP_I]], <4 x i32>* [[TMP3]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <4 x i32>, <4 x i32>* [[TMP3]], i32 1
-// CHECK: [[VUZP1_I:%.*]] = shufflevector <4 x i32> [[TMP4]], <4 x i32> [[TMP5]], <4 x i32> <i32 1, i32 3, i32 5, i32 7>
-// CHECK: store <4 x i32> [[VUZP1_I]], <4 x i32>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.int32x4x2_t* %agg.result to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.int32x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP7]], i8* [[TMP8]], i32 32, i32 16, i1 false) #4
+// 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: [[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) #4
// CHECK: ret void
int32x4x2_t test_vuzpq_s32(int32x4_t a, int32x4_t b) {
return vuzpq_s32(a, b);
}
-// CHECK-LABEL: define void @test_vuzpq_u8(%struct.uint8x16x2_t* noalias sret %agg.result, <16 x i8> %a, <16 x i8> %b) #0 {
+// 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: [[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: store <16 x i8> [[VUZP_I]], <16 x i8>* [[TMP1]], !noalias !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]]
+// 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) #4
@@ -23539,78 +21195,72 @@ uint8x16x2_t test_vuzpq_u8(uint8x16_t a, uint8x16_t b) {
return vuzpq_u8(a, b);
}
-// CHECK-LABEL: define void @test_vuzpq_u16(%struct.uint16x8x2_t* noalias sret %agg.result, <8 x i16> %a, <8 x i16> %b) #0 {
+// 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: [[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: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <8 x i16>
-// CHECK: [[VUZP_I:%.*]] = shufflevector <8 x i16> [[TMP4]], <8 x i16> [[TMP5]], <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]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
-// CHECK: [[VUZP1_I:%.*]] = shufflevector <8 x i16> [[TMP4]], <8 x i16> [[TMP5]], <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>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.uint16x8x2_t* %agg.result to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP7]], i8* [[TMP8]], i32 32, i32 16, i1 false) #4
+// 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: [[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) #4
// CHECK: ret void
uint16x8x2_t test_vuzpq_u16(uint16x8_t a, uint16x8_t b) {
return vuzpq_u16(a, b);
}
-// CHECK-LABEL: define void @test_vuzpq_u32(%struct.uint32x4x2_t* noalias sret %agg.result, <4 x i32> %a, <4 x i32> %b) #0 {
+// 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: [[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: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <4 x i32>
-// CHECK: [[VUZP_I:%.*]] = shufflevector <4 x i32> [[TMP4]], <4 x i32> [[TMP5]], <4 x i32> <i32 0, i32 2, i32 4, i32 6>
-// CHECK: store <4 x i32> [[VUZP_I]], <4 x i32>* [[TMP3]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <4 x i32>, <4 x i32>* [[TMP3]], i32 1
-// CHECK: [[VUZP1_I:%.*]] = shufflevector <4 x i32> [[TMP4]], <4 x i32> [[TMP5]], <4 x i32> <i32 1, i32 3, i32 5, i32 7>
-// CHECK: store <4 x i32> [[VUZP1_I]], <4 x i32>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.uint32x4x2_t* %agg.result to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP7]], i8* [[TMP8]], i32 32, i32 16, i1 false) #4
+// 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: [[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) #4
// CHECK: ret void
uint32x4x2_t test_vuzpq_u32(uint32x4_t a, uint32x4_t b) {
return vuzpq_u32(a, b);
}
-// CHECK-LABEL: define void @test_vuzpq_f32(%struct.float32x4x2_t* noalias sret %agg.result, <4 x float> %a, <4 x float> %b) #0 {
+// 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: [[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: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <4 x float>
-// CHECK: [[VUZP_I:%.*]] = shufflevector <4 x float> [[TMP4]], <4 x float> [[TMP5]], <4 x i32> <i32 0, i32 2, i32 4, i32 6>
-// CHECK: store <4 x float> [[VUZP_I]], <4 x float>* [[TMP3]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <4 x float>, <4 x float>* [[TMP3]], i32 1
-// CHECK: [[VUZP1_I:%.*]] = shufflevector <4 x float> [[TMP4]], <4 x float> [[TMP5]], <4 x i32> <i32 1, i32 3, i32 5, i32 7>
-// CHECK: store <4 x float> [[VUZP1_I]], <4 x float>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.float32x4x2_t* %agg.result to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.float32x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP7]], i8* [[TMP8]], i32 32, i32 16, i1 false) #4
+// 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: [[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) #4
// CHECK: ret void
float32x4x2_t test_vuzpq_f32(float32x4_t a, float32x4_t b) {
return vuzpq_f32(a, b);
}
-// CHECK-LABEL: define void @test_vuzpq_p8(%struct.poly8x16x2_t* noalias sret %agg.result, <16 x i8> %a, <16 x i8> %b) #0 {
+// 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: [[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: store <16 x i8> [[VUZP_I]], <16 x i8>* [[TMP1]], !noalias !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]]
+// 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) #4
@@ -23619,37 +21269,34 @@ poly8x16x2_t test_vuzpq_p8(poly8x16_t a, poly8x16_t b) {
return vuzpq_p8(a, b);
}
-// CHECK-LABEL: define void @test_vuzpq_p16(%struct.poly16x8x2_t* noalias sret %agg.result, <8 x i16> %a, <8 x i16> %b) #0 {
+// 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: [[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: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <8 x i16>
-// CHECK: [[VUZP_I:%.*]] = shufflevector <8 x i16> [[TMP4]], <8 x i16> [[TMP5]], <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]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
-// CHECK: [[VUZP1_I:%.*]] = shufflevector <8 x i16> [[TMP4]], <8 x i16> [[TMP5]], <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>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.poly16x8x2_t* %agg.result to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP7]], i8* [[TMP8]], i32 32, i32 16, i1 false) #4
+// 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: [[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) #4
// CHECK: ret void
poly16x8x2_t test_vuzpq_p16(poly16x8_t a, poly16x8_t b) {
return vuzpq_p16(a, b);
}
-
-// CHECK-LABEL: define void @test_vzip_s8(%struct.int8x8x2_t* noalias sret %agg.result, <8 x i8> %a, <8 x i8> %b) #0 {
+// 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: [[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: store <8 x i8> [[VZIP_I]], <8 x i8>* [[TMP1]], !noalias !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]]
+// 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) #4
@@ -23658,57 +21305,53 @@ int8x8x2_t test_vzip_s8(int8x8_t a, int8x8_t b) {
return vzip_s8(a, b);
}
-// CHECK-LABEL: define void @test_vzip_s16(%struct.int16x4x2_t* noalias sret %agg.result, <4 x i16> %a, <4 x i16> %b) #0 {
+// 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: [[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: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[TMP5:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VZIP_I:%.*]] = shufflevector <4 x i16> [[TMP4]], <4 x i16> [[TMP5]], <4 x i32> <i32 0, i32 4, i32 1, i32 5>
-// CHECK: store <4 x i16> [[VZIP_I]], <4 x i16>* [[TMP3]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
-// CHECK: [[VZIP1_I:%.*]] = shufflevector <4 x i16> [[TMP4]], <4 x i16> [[TMP5]], <4 x i32> <i32 2, i32 6, i32 3, i32 7>
-// CHECK: store <4 x i16> [[VZIP1_I]], <4 x i16>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.int16x4x2_t* %agg.result to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.int16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP7]], i8* [[TMP8]], i32 16, i32 8, i1 false) #4
+// 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: [[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) #4
// CHECK: ret void
int16x4x2_t test_vzip_s16(int16x4_t a, int16x4_t b) {
return vzip_s16(a, b);
}
-// CHECK-LABEL: define void @test_vzip_s32(%struct.int32x2x2_t* noalias sret %agg.result, <2 x i32> %a, <2 x i32> %b) #0 {
+// 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: [[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: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[TMP5:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VZIP_I:%.*]] = shufflevector <2 x i32> [[TMP4]], <2 x i32> [[TMP5]], <2 x i32> <i32 0, i32 2>
-// CHECK: store <2 x i32> [[VZIP_I]], <2 x i32>* [[TMP3]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <2 x i32>, <2 x i32>* [[TMP3]], i32 1
-// CHECK: [[VZIP1_I:%.*]] = shufflevector <2 x i32> [[TMP4]], <2 x i32> [[TMP5]], <2 x i32> <i32 1, i32 3>
-// CHECK: store <2 x i32> [[VZIP1_I]], <2 x i32>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.int32x2x2_t* %agg.result to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.int32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP7]], i8* [[TMP8]], i32 16, i32 8, i1 false) #4
+// 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: [[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) #4
// CHECK: ret void
int32x2x2_t test_vzip_s32(int32x2_t a, int32x2_t b) {
return vzip_s32(a, b);
}
-// CHECK-LABEL: define void @test_vzip_u8(%struct.uint8x8x2_t* noalias sret %agg.result, <8 x i8> %a, <8 x i8> %b) #0 {
+// 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: [[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: store <8 x i8> [[VZIP_I]], <8 x i8>* [[TMP1]], !noalias !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]]
+// 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) #4
@@ -23717,78 +21360,72 @@ uint8x8x2_t test_vzip_u8(uint8x8_t a, uint8x8_t b) {
return vzip_u8(a, b);
}
-// CHECK-LABEL: define void @test_vzip_u16(%struct.uint16x4x2_t* noalias sret %agg.result, <4 x i16> %a, <4 x i16> %b) #0 {
+// 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: [[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: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[TMP5:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VZIP_I:%.*]] = shufflevector <4 x i16> [[TMP4]], <4 x i16> [[TMP5]], <4 x i32> <i32 0, i32 4, i32 1, i32 5>
-// CHECK: store <4 x i16> [[VZIP_I]], <4 x i16>* [[TMP3]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
-// CHECK: [[VZIP1_I:%.*]] = shufflevector <4 x i16> [[TMP4]], <4 x i16> [[TMP5]], <4 x i32> <i32 2, i32 6, i32 3, i32 7>
-// CHECK: store <4 x i16> [[VZIP1_I]], <4 x i16>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.uint16x4x2_t* %agg.result to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.uint16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP7]], i8* [[TMP8]], i32 16, i32 8, i1 false) #4
+// 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: [[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) #4
// CHECK: ret void
uint16x4x2_t test_vzip_u16(uint16x4_t a, uint16x4_t b) {
return vzip_u16(a, b);
}
-// CHECK-LABEL: define void @test_vzip_u32(%struct.uint32x2x2_t* noalias sret %agg.result, <2 x i32> %a, <2 x i32> %b) #0 {
+// 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: [[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: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32>
-// CHECK: [[TMP5:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x i32>
-// CHECK: [[VZIP_I:%.*]] = shufflevector <2 x i32> [[TMP4]], <2 x i32> [[TMP5]], <2 x i32> <i32 0, i32 2>
-// CHECK: store <2 x i32> [[VZIP_I]], <2 x i32>* [[TMP3]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <2 x i32>, <2 x i32>* [[TMP3]], i32 1
-// CHECK: [[VZIP1_I:%.*]] = shufflevector <2 x i32> [[TMP4]], <2 x i32> [[TMP5]], <2 x i32> <i32 1, i32 3>
-// CHECK: store <2 x i32> [[VZIP1_I]], <2 x i32>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.uint32x2x2_t* %agg.result to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.uint32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP7]], i8* [[TMP8]], i32 16, i32 8, i1 false) #4
+// 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: [[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) #4
// CHECK: ret void
uint32x2x2_t test_vzip_u32(uint32x2_t a, uint32x2_t b) {
return vzip_u32(a, b);
}
-// CHECK-LABEL: define void @test_vzip_f32(%struct.float32x2x2_t* noalias sret %agg.result, <2 x float> %a, <2 x float> %b) #0 {
+// 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: [[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: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x float>
-// CHECK: [[TMP5:%.*]] = bitcast <8 x i8> [[TMP2]] to <2 x float>
-// CHECK: [[VZIP_I:%.*]] = shufflevector <2 x float> [[TMP4]], <2 x float> [[TMP5]], <2 x i32> <i32 0, i32 2>
-// CHECK: store <2 x float> [[VZIP_I]], <2 x float>* [[TMP3]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <2 x float>, <2 x float>* [[TMP3]], i32 1
-// CHECK: [[VZIP1_I:%.*]] = shufflevector <2 x float> [[TMP4]], <2 x float> [[TMP5]], <2 x i32> <i32 1, i32 3>
-// CHECK: store <2 x float> [[VZIP1_I]], <2 x float>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.float32x2x2_t* %agg.result to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.float32x2x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP7]], i8* [[TMP8]], i32 16, i32 8, i1 false) #4
+// 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: [[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) #4
// CHECK: ret void
float32x2x2_t test_vzip_f32(float32x2_t a, float32x2_t b) {
return vzip_f32(a, b);
}
-// CHECK-LABEL: define void @test_vzip_p8(%struct.poly8x8x2_t* noalias sret %agg.result, <8 x i8> %a, <8 x i8> %b) #0 {
+// 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: [[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: store <8 x i8> [[VZIP_I]], <8 x i8>* [[TMP1]], !noalias !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]]
+// 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) #4
@@ -23797,36 +21434,34 @@ poly8x8x2_t test_vzip_p8(poly8x8_t a, poly8x8_t b) {
return vzip_p8(a, b);
}
-// CHECK-LABEL: define void @test_vzip_p16(%struct.poly16x4x2_t* noalias sret %agg.result, <4 x i16> %a, <4 x i16> %b) #0 {
+// 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: [[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: [[TMP4:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK: [[TMP5:%.*]] = bitcast <8 x i8> [[TMP2]] to <4 x i16>
-// CHECK: [[VZIP_I:%.*]] = shufflevector <4 x i16> [[TMP4]], <4 x i16> [[TMP5]], <4 x i32> <i32 0, i32 4, i32 1, i32 5>
-// CHECK: store <4 x i16> [[VZIP_I]], <4 x i16>* [[TMP3]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <4 x i16>, <4 x i16>* [[TMP3]], i32 1
-// CHECK: [[VZIP1_I:%.*]] = shufflevector <4 x i16> [[TMP4]], <4 x i16> [[TMP5]], <4 x i32> <i32 2, i32 6, i32 3, i32 7>
-// CHECK: store <4 x i16> [[VZIP1_I]], <4 x i16>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.poly16x4x2_t* %agg.result to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.poly16x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP7]], i8* [[TMP8]], i32 16, i32 8, i1 false) #4
+// 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: [[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) #4
// CHECK: ret void
poly16x4x2_t test_vzip_p16(poly16x4_t a, poly16x4_t b) {
return vzip_p16(a, b);
}
-// CHECK-LABEL: define void @test_vzipq_s8(%struct.int8x16x2_t* noalias sret %agg.result, <16 x i8> %a, <16 x i8> %b) #0 {
+// 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: [[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: store <16 x i8> [[VZIP_I]], <16 x i8>* [[TMP1]], !noalias !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]]
+// 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) #4
@@ -23835,57 +21470,53 @@ int8x16x2_t test_vzipq_s8(int8x16_t a, int8x16_t b) {
return vzipq_s8(a, b);
}
-// CHECK-LABEL: define void @test_vzipq_s16(%struct.int16x8x2_t* noalias sret %agg.result, <8 x i16> %a, <8 x i16> %b) #0 {
+// 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: [[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: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <8 x i16>
-// CHECK: [[VZIP_I:%.*]] = shufflevector <8 x i16> [[TMP4]], <8 x i16> [[TMP5]], <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]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
-// CHECK: [[VZIP1_I:%.*]] = shufflevector <8 x i16> [[TMP4]], <8 x i16> [[TMP5]], <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>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.int16x8x2_t* %agg.result to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.int16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP7]], i8* [[TMP8]], i32 32, i32 16, i1 false) #4
+// 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: [[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) #4
// CHECK: ret void
int16x8x2_t test_vzipq_s16(int16x8_t a, int16x8_t b) {
return vzipq_s16(a, b);
}
-// CHECK-LABEL: define void @test_vzipq_s32(%struct.int32x4x2_t* noalias sret %agg.result, <4 x i32> %a, <4 x i32> %b) #0 {
+// 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: [[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: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <4 x i32>
-// CHECK: [[VZIP_I:%.*]] = shufflevector <4 x i32> [[TMP4]], <4 x i32> [[TMP5]], <4 x i32> <i32 0, i32 4, i32 1, i32 5>
-// CHECK: store <4 x i32> [[VZIP_I]], <4 x i32>* [[TMP3]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <4 x i32>, <4 x i32>* [[TMP3]], i32 1
-// CHECK: [[VZIP1_I:%.*]] = shufflevector <4 x i32> [[TMP4]], <4 x i32> [[TMP5]], <4 x i32> <i32 2, i32 6, i32 3, i32 7>
-// CHECK: store <4 x i32> [[VZIP1_I]], <4 x i32>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.int32x4x2_t* %agg.result to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.int32x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP7]], i8* [[TMP8]], i32 32, i32 16, i1 false) #4
+// 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: [[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) #4
// CHECK: ret void
int32x4x2_t test_vzipq_s32(int32x4_t a, int32x4_t b) {
return vzipq_s32(a, b);
}
-// CHECK-LABEL: define void @test_vzipq_u8(%struct.uint8x16x2_t* noalias sret %agg.result, <16 x i8> %a, <16 x i8> %b) #0 {
+// 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: [[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: store <16 x i8> [[VZIP_I]], <16 x i8>* [[TMP1]], !noalias !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]]
+// 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) #4
@@ -23894,78 +21525,72 @@ uint8x16x2_t test_vzipq_u8(uint8x16_t a, uint8x16_t b) {
return vzipq_u8(a, b);
}
-// CHECK-LABEL: define void @test_vzipq_u16(%struct.uint16x8x2_t* noalias sret %agg.result, <8 x i16> %a, <8 x i16> %b) #0 {
+// 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: [[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: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <8 x i16>
-// CHECK: [[VZIP_I:%.*]] = shufflevector <8 x i16> [[TMP4]], <8 x i16> [[TMP5]], <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]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
-// CHECK: [[VZIP1_I:%.*]] = shufflevector <8 x i16> [[TMP4]], <8 x i16> [[TMP5]], <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>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.uint16x8x2_t* %agg.result to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.uint16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP7]], i8* [[TMP8]], i32 32, i32 16, i1 false) #4
+// 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: [[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) #4
// CHECK: ret void
uint16x8x2_t test_vzipq_u16(uint16x8_t a, uint16x8_t b) {
return vzipq_u16(a, b);
}
-// CHECK-LABEL: define void @test_vzipq_u32(%struct.uint32x4x2_t* noalias sret %agg.result, <4 x i32> %a, <4 x i32> %b) #0 {
+// 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: [[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: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <4 x i32>
-// CHECK: [[VZIP_I:%.*]] = shufflevector <4 x i32> [[TMP4]], <4 x i32> [[TMP5]], <4 x i32> <i32 0, i32 4, i32 1, i32 5>
-// CHECK: store <4 x i32> [[VZIP_I]], <4 x i32>* [[TMP3]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <4 x i32>, <4 x i32>* [[TMP3]], i32 1
-// CHECK: [[VZIP1_I:%.*]] = shufflevector <4 x i32> [[TMP4]], <4 x i32> [[TMP5]], <4 x i32> <i32 2, i32 6, i32 3, i32 7>
-// CHECK: store <4 x i32> [[VZIP1_I]], <4 x i32>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.uint32x4x2_t* %agg.result to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.uint32x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP7]], i8* [[TMP8]], i32 32, i32 16, i1 false) #4
+// 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: [[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) #4
// CHECK: ret void
uint32x4x2_t test_vzipq_u32(uint32x4_t a, uint32x4_t b) {
return vzipq_u32(a, b);
}
-// CHECK-LABEL: define void @test_vzipq_f32(%struct.float32x4x2_t* noalias sret %agg.result, <4 x float> %a, <4 x float> %b) #0 {
+// 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: [[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: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x float>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <4 x float>
-// CHECK: [[VZIP_I:%.*]] = shufflevector <4 x float> [[TMP4]], <4 x float> [[TMP5]], <4 x i32> <i32 0, i32 4, i32 1, i32 5>
-// CHECK: store <4 x float> [[VZIP_I]], <4 x float>* [[TMP3]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <4 x float>, <4 x float>* [[TMP3]], i32 1
-// CHECK: [[VZIP1_I:%.*]] = shufflevector <4 x float> [[TMP4]], <4 x float> [[TMP5]], <4 x i32> <i32 2, i32 6, i32 3, i32 7>
-// CHECK: store <4 x float> [[VZIP1_I]], <4 x float>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.float32x4x2_t* %agg.result to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.float32x4x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP7]], i8* [[TMP8]], i32 32, i32 16, i1 false) #4
+// 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: [[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) #4
// CHECK: ret void
float32x4x2_t test_vzipq_f32(float32x4_t a, float32x4_t b) {
return vzipq_f32(a, b);
}
-// CHECK-LABEL: define void @test_vzipq_p8(%struct.poly8x16x2_t* noalias sret %agg.result, <16 x i8> %a, <16 x i8> %b) #0 {
+// 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: [[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: store <16 x i8> [[VZIP_I]], <16 x i8>* [[TMP1]], !noalias !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]]
+// 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) #4
@@ -23974,25 +21599,21 @@ poly8x16x2_t test_vzipq_p8(poly8x16_t a, poly8x16_t b) {
return vzipq_p8(a, b);
}
-// CHECK-LABEL: define void @test_vzipq_p16(%struct.poly16x8x2_t* noalias sret %agg.result, <8 x i16> %a, <8 x i16> %b) #0 {
+// 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: [[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: [[TMP4:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16>
-// CHECK: [[TMP5:%.*]] = bitcast <16 x i8> [[TMP2]] to <8 x i16>
-// CHECK: [[VZIP_I:%.*]] = shufflevector <8 x i16> [[TMP4]], <8 x i16> [[TMP5]], <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]]
-// CHECK: [[TMP6:%.*]] = getelementptr inbounds <8 x i16>, <8 x i16>* [[TMP3]], i32 1
-// CHECK: [[VZIP1_I:%.*]] = shufflevector <8 x i16> [[TMP4]], <8 x i16> [[TMP5]], <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>* [[TMP6]]
-// CHECK: [[TMP7:%.*]] = bitcast %struct.poly16x8x2_t* %agg.result to i8*
-// CHECK: [[TMP8:%.*]] = bitcast %struct.poly16x8x2_t* [[__RET_I]] to i8*
-// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* [[TMP7]], i8* [[TMP8]], i32 32, i32 16, i1 false) #4
+// 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: [[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) #4
// CHECK: ret void
poly16x8x2_t test_vzipq_p16(poly16x8_t a, poly16x8_t b) {
return vzipq_p16(a, b);
}
-
-
diff --git a/test/CodeGen/asan-globals.cpp b/test/CodeGen/asan-globals.cpp
index 20c1fa702a86..93abb0023cfa 100644
--- a/test/CodeGen/asan-globals.cpp
+++ b/test/CodeGen/asan-globals.cpp
@@ -1,12 +1,13 @@
// RUN: echo "int extra_global;" > %t.extra-source.cpp
// RUN: echo "global:*blacklisted_global*" > %t.blacklist
// RUN: %clang_cc1 -include %t.extra-source.cpp -fsanitize=address -fsanitize-blacklist=%t.blacklist -emit-llvm -o - %s | FileCheck %s
-// RUN: echo "src:%s" > %t.blacklist-src
+// The blacklist file uses regexps, so Windows path backslashes.
+// RUN: echo "src:%s" | sed -e 's/\\/\\\\/g' > %t.blacklist-src
// RUN: %clang_cc1 -include %t.extra-source.cpp -fsanitize=address -fsanitize-blacklist=%t.blacklist-src -emit-llvm -o - %s | FileCheck %s --check-prefix=BLACKLIST-SRC
-// REQUIRES: shell
int global;
int dyn_init_global = global;
+int __attribute__((no_sanitize("address"))) attributed_global;
int blacklisted_global;
void func() {
@@ -14,24 +15,26 @@ void func() {
const char *literal = "Hello, world!";
}
-// CHECK: !llvm.asan.globals = !{![[EXTRA_GLOBAL:[0-9]+]], ![[GLOBAL:[0-9]+]], ![[DYN_INIT_GLOBAL:[0-9]+]], ![[BLACKLISTED_GLOBAL:[0-9]+]], ![[STATIC_VAR:[0-9]+]], ![[LITERAL:[0-9]+]]}
+// CHECK: !llvm.asan.globals = !{![[EXTRA_GLOBAL:[0-9]+]], ![[GLOBAL:[0-9]+]], ![[DYN_INIT_GLOBAL:[0-9]+]], ![[ATTR_GLOBAL:[0-9]+]], ![[BLACKLISTED_GLOBAL:[0-9]+]], ![[STATIC_VAR:[0-9]+]], ![[LITERAL:[0-9]+]]}
// CHECK: ![[EXTRA_GLOBAL]] = !{{{.*}} ![[EXTRA_GLOBAL_LOC:[0-9]+]], !"extra_global", i1 false, i1 false}
// CHECK: ![[EXTRA_GLOBAL_LOC]] = !{!"{{.*}}extra-source.cpp", i32 1, i32 5}
// CHECK: ![[GLOBAL]] = !{{{.*}} ![[GLOBAL_LOC:[0-9]+]], !"global", i1 false, i1 false}
// CHECK: ![[GLOBAL_LOC]] = !{!"{{.*}}asan-globals.cpp", i32 8, i32 5}
// CHECK: ![[DYN_INIT_GLOBAL]] = !{{{.*}} ![[DYN_INIT_LOC:[0-9]+]], !"dyn_init_global", i1 true, i1 false}
// CHECK: ![[DYN_INIT_LOC]] = !{!"{{.*}}asan-globals.cpp", i32 9, i32 5}
+// CHECK: ![[ATTR_GLOBAL]] = !{{{.*}}, null, null, i1 false, i1 true}
// CHECK: ![[BLACKLISTED_GLOBAL]] = !{{{.*}}, null, null, i1 false, i1 true}
// CHECK: ![[STATIC_VAR]] = !{{{.*}} ![[STATIC_LOC:[0-9]+]], !"static_var", i1 false, i1 false}
-// CHECK: ![[STATIC_LOC]] = !{!"{{.*}}asan-globals.cpp", i32 13, i32 14}
+// CHECK: ![[STATIC_LOC]] = !{!"{{.*}}asan-globals.cpp", i32 14, i32 14}
// CHECK: ![[LITERAL]] = !{{{.*}} ![[LITERAL_LOC:[0-9]+]], !"<string literal>", i1 false, i1 false}
-// CHECK: ![[LITERAL_LOC]] = !{!"{{.*}}asan-globals.cpp", i32 14, i32 25}
+// CHECK: ![[LITERAL_LOC]] = !{!"{{.*}}asan-globals.cpp", i32 15, i32 25}
-// BLACKLIST-SRC: !llvm.asan.globals = !{![[EXTRA_GLOBAL:[0-9]+]], ![[GLOBAL:[0-9]+]], ![[DYN_INIT_GLOBAL:[0-9]+]], ![[BLACKLISTED_GLOBAL:[0-9]+]], ![[STATIC_VAR:[0-9]+]], ![[LITERAL:[0-9]+]]}
+// BLACKLIST-SRC: !llvm.asan.globals = !{![[EXTRA_GLOBAL:[0-9]+]], ![[GLOBAL:[0-9]+]], ![[DYN_INIT_GLOBAL:[0-9]+]], ![[ATTR_GLOBAL:[0-9]+]], ![[BLACKLISTED_GLOBAL:[0-9]+]], ![[STATIC_VAR:[0-9]+]], ![[LITERAL:[0-9]+]]}
// BLACKLIST-SRC: ![[EXTRA_GLOBAL]] = !{{{.*}} ![[EXTRA_GLOBAL_LOC:[0-9]+]], !"extra_global", i1 false, i1 false}
// BLACKLIST-SRC: ![[EXTRA_GLOBAL_LOC]] = !{!"{{.*}}extra-source.cpp", i32 1, i32 5}
// BLACKLIST-SRC: ![[GLOBAL]] = !{{{.*}} null, null, i1 false, i1 true}
// BLACKLIST-SRC: ![[DYN_INIT_GLOBAL]] = !{{{.*}} null, null, i1 true, i1 true}
+// BLACKLIST-SRC: ![[ATTR_GLOBAL]] = !{{{.*}}, null, null, i1 false, i1 true}
// BLACKLIST-SRC: ![[BLACKLISTED_GLOBAL]] = !{{{.*}}, null, null, i1 false, i1 true}
// BLACKLIST-SRC: ![[STATIC_VAR]] = !{{{.*}} null, null, i1 false, i1 true}
// BLACKLIST-SRC: ![[LITERAL]] = !{{{.*}} null, null, i1 false, i1 true}
diff --git a/test/CodeGen/atomics-inlining.c b/test/CodeGen/atomics-inlining.c
index 4974f22e3a47..fc23c0b3f64f 100644
--- a/test/CodeGen/atomics-inlining.c
+++ b/test/CodeGen/atomics-inlining.c
@@ -3,7 +3,8 @@
// RUN: %clang_cc1 -triple powerpc64-linux-gnu -emit-llvm %s -o - | FileCheck %s -check-prefix=PPC64
// RUN: %clang_cc1 -triple mipsel-linux-gnu -emit-llvm %s -o - | FileCheck %s -check-prefix=MIPS32
// RUN: %clang_cc1 -triple mips64el-linux-gnu -emit-llvm %s -o - | FileCheck %s -check-prefix=MIPS64
-// RUN: %clang_cc1 -triple sparc-unknown-eabi -emit-llvm %s -o - | FileCheck %s -check-prefix=SPARC
+// RUN: %clang_cc1 -triple sparc-unknown-eabi -emit-llvm %s -o - | FileCheck %s -check-prefix=SPARCV8 -check-prefix=SPARC
+// RUN: %clang_cc1 -triple sparcv9-unknown-eabi -emit-llvm %s -o - | FileCheck %s -check-prefix=SPARCV9 -check-prefix=SPARC
unsigned char c1, c2;
unsigned short s1, s2;
@@ -99,8 +100,10 @@ void test1(void) {
// SPARC: store atomic i16 {{.*}}, i16* @s1 seq_cst
// SPARC: = load atomic i32, i32* @i1 seq_cst
// SPARC: store atomic i32 {{.*}}, i32* @i1 seq_cst
-// SPARC: = load atomic i64, i64* @ll1 seq_cst
-// SPARC: store atomic i64 {{.*}}, i64* @ll1 seq_cst
-// SPARC: call void @__atomic_load(i32 100, i8* getelementptr inbounds ([100 x i8], [100 x i8]* @a1, i32 0, i32 0), i8* getelementptr inbounds ([100 x i8], [100 x i8]* @a2, i32 0, i32 0)
-// SPARC: call void @__atomic_store(i32 100, i8* getelementptr inbounds ([100 x i8], [100 x i8]* @a1, i32 0, i32 0), i8* getelementptr inbounds ([100 x i8], [100 x i8]* @a2, i32 0, i32 0)
+// SPARCV8: call i64 @__atomic_load_8(i8* bitcast (i64* @ll1 to i8*)
+// SPARCV8: call void @__atomic_store_8(i8* bitcast (i64* @ll1 to i8*), i64
+// SPARCV9: load atomic i64, i64* @ll1 seq_cst, align 8
+// SPARCV9: store atomic i64 {{.*}}, i64* @ll1 seq_cst, align 8
+// SPARCV8: call void @__atomic_load(i32 100, i8* getelementptr inbounds ([100 x i8], [100 x i8]* @a1, i32 0, i32 0), i8* getelementptr inbounds ([100 x i8], [100 x i8]* @a2, i32 0, i32 0)
+// SPARCV8: call void @__atomic_store(i32 100, i8* getelementptr inbounds ([100 x i8], [100 x i8]* @a1, i32 0, i32 0), i8* getelementptr inbounds ([100 x i8], [100 x i8]* @a2, i32 0, i32 0)
}
diff --git a/test/CodeGen/attr-minsize.cpp b/test/CodeGen/attr-minsize.cpp
index 1e5c634dbdfc..4a26e856ff9e 100644
--- a/test/CodeGen/attr-minsize.cpp
+++ b/test/CodeGen/attr-minsize.cpp
@@ -1,9 +1,9 @@
-// RUN: %clang_cc1 -Oz -disable-llvm-optzns -emit-llvm %s -o - | FileCheck %s -check-prefix=Oz
-// RUN: %clang_cc1 -disable-llvm-optzns -emit-llvm %s -o - | FileCheck %s -check-prefix=OTHER
-// RUN: %clang_cc1 -O1 -disable-llvm-optzns -emit-llvm %s -o - | FileCheck %s -check-prefix=OTHER
-// RUN: %clang_cc1 -O2 -disable-llvm-optzns -emit-llvm %s -o - | FileCheck %s -check-prefix=OTHER
-// RUN: %clang_cc1 -O3 -disable-llvm-optzns -emit-llvm %s -o - | FileCheck %s -check-prefix=OTHER
-// RUN: %clang_cc1 -Os -disable-llvm-optzns -emit-llvm %s -o - | FileCheck %s -check-prefix=OTHER
+// RUN: %clang_cc1 -Oz -disable-llvm-passes -emit-llvm %s -o - | FileCheck %s -check-prefix=Oz
+// RUN: %clang_cc1 -disable-llvm-passes -emit-llvm %s -o - | FileCheck %s -check-prefix=OTHER
+// RUN: %clang_cc1 -O1 -disable-llvm-passes -emit-llvm %s -o - | FileCheck %s -check-prefix=OTHER
+// RUN: %clang_cc1 -O2 -disable-llvm-passes -emit-llvm %s -o - | FileCheck %s -check-prefix=OTHER
+// RUN: %clang_cc1 -O3 -disable-llvm-passes -emit-llvm %s -o - | FileCheck %s -check-prefix=OTHER
+// RUN: %clang_cc1 -Os -disable-llvm-passes -emit-llvm %s -o - | FileCheck %s -check-prefix=OTHER
// Check that we set the minsize attribute on each function
// when Oz optimization level is set.
@@ -76,4 +76,4 @@ void test5<float>(float arg);
// Oz: attributes [[MINSIZE]] = { minsize{{.*}} }
-// OTHER: attributes [[MS]] = { minsize nounwind{{.*}} }
+// OTHER: attributes [[MS]] = { minsize{{.*}} }
diff --git a/test/CodeGen/attr-mrecip.c b/test/CodeGen/attr-mrecip.c
new file mode 100644
index 000000000000..954c57ae102b
--- /dev/null
+++ b/test/CodeGen/attr-mrecip.c
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -mrecip=!sqrtf,vec-divf:3 -emit-llvm %s -o - | FileCheck %s
+
+int baz(int a) { return 4; }
+
+// CHECK: baz{{.*}} #0
+// CHECK: #0 = {{.*}}"reciprocal-estimates"="!sqrtf,vec-divf:3"
+
diff --git a/test/CodeGen/attributes.c b/test/CodeGen/attributes.c
index 7bfc3924fffc..9e5fa9f90651 100644
--- a/test/CodeGen/attributes.c
+++ b/test/CodeGen/attributes.c
@@ -90,5 +90,5 @@ void __attribute__((section(".bar"))) t22(void) {}
// CHECK: define void @t22() [[NUW]] section ".bar"
-// CHECK: attributes [[NUW]] = { nounwind{{.*}} }
-// CHECK: attributes [[NR]] = { noreturn nounwind{{.*}} }
+// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} }
+// CHECK: attributes [[NR]] = { noinline noreturn nounwind{{.*}} }
diff --git a/test/CodeGen/avx-builtins.c b/test/CodeGen/avx-builtins.c
index 650e4d280ecb..6a9f7c050b32 100644
--- a/test/CodeGen/avx-builtins.c
+++ b/test/CodeGen/avx-builtins.c
@@ -1,8 +1,6 @@
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +avx -emit-llvm -o - -Werror | FileCheck %s
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +avx -fno-signed-char -emit-llvm -o - -Werror | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +avx -emit-llvm -o - -Wall -Werror | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +avx -fno-signed-char -emit-llvm -o - -Wall -Werror | FileCheck %s
-// Don't include mm_malloc.h, it's system specific.
-#define __MM_MALLOC_H
#include <x86intrin.h>
@@ -84,13 +82,15 @@ __m256 test_mm256_blendv_ps(__m256 V1, __m256 V2, __m256 V3) {
__m256d test_mm256_broadcast_pd(__m128d* A) {
// CHECK-LABEL: test_mm256_broadcast_pd
- // CHECK: call <4 x double> @llvm.x86.avx.vbroadcastf128.pd.256(i8* %{{.*}})
+ // 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 0, i32 1>
return _mm256_broadcast_pd(A);
}
__m256 test_mm256_broadcast_ps(__m128* A) {
// CHECK-LABEL: test_mm256_broadcast_ps
- // CHECK: call <8 x float> @llvm.x86.avx.vbroadcastf128.ps.256(i8* %{{.*}})
+ // 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 0, i32 1, i32 2, i32 3>
return _mm256_broadcast_ps(A);
}
diff --git a/test/CodeGen/avx-cmp-builtins.c b/test/CodeGen/avx-cmp-builtins.c
index 30d1bd5c7aa0..7d619426653d 100644
--- a/test/CodeGen/avx-cmp-builtins.c
+++ b/test/CodeGen/avx-cmp-builtins.c
@@ -1,8 +1,6 @@
-// RUN: %clang_cc1 %s -O3 -triple=x86_64-apple-darwin -target-feature +avx -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -O3 -triple=x86_64-apple-darwin -target-feature +avx -emit-llvm -o - | FileCheck %s
// FIXME: The shufflevector instructions in test_cmpgt_sd are relying on O3 here.
-// Don't include mm_malloc.h, it's system specific.
-#define __MM_MALLOC_H
#include <immintrin.h>
diff --git a/test/CodeGen/avx-shuffle-builtins.c b/test/CodeGen/avx-shuffle-builtins.c
index 22bee33080a9..b5bac89bd1ec 100644
--- a/test/CodeGen/avx-shuffle-builtins.c
+++ b/test/CodeGen/avx-shuffle-builtins.c
@@ -1,8 +1,6 @@
-// RUN: %clang_cc1 %s -O3 -triple=x86_64-apple-darwin -target-feature +avx -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -O3 -triple=x86_64-apple-darwin -target-feature +avx -emit-llvm -o - | FileCheck %s
// FIXME: This is testing optimized generation of shuffle instructions and should be fixed.
-// Don't include mm_malloc.h, it's system specific.
-#define __MM_MALLOC_H
#include <immintrin.h>
@@ -69,9 +67,7 @@ __m128
test_mm_broadcast_ss(float const *__a) {
// CHECK-LABEL: @test_mm_broadcast_ss
// CHECK: insertelement <4 x float> {{.*}}, i32 0
- // CHECK: insertelement <4 x float> {{.*}}, i32 1
- // CHECK: insertelement <4 x float> {{.*}}, i32 2
- // CHECK: insertelement <4 x float> {{.*}}, i32 3
+ // CHECK: shufflevector <4 x float> {{.*}}, <4 x float> undef, <4 x i32> zeroinitializer
return _mm_broadcast_ss(__a);
}
@@ -79,9 +75,7 @@ __m256d
test_mm256_broadcast_sd(double const *__a) {
// CHECK-LABEL: @test_mm256_broadcast_sd
// CHECK: insertelement <4 x double> {{.*}}, i32 0
- // CHECK: insertelement <4 x double> {{.*}}, i32 1
- // CHECK: insertelement <4 x double> {{.*}}, i32 2
- // CHECK: insertelement <4 x double> {{.*}}, i32 3
+ // CHECK: shufflevector <4 x double> {{.*}}, <4 x double> undef, <4 x i32> zeroinitializer
return _mm256_broadcast_sd(__a);
}
@@ -89,13 +83,7 @@ __m256
test_mm256_broadcast_ss(float const *__a) {
// CHECK-LABEL: @test_mm256_broadcast_ss
// CHECK: insertelement <8 x float> {{.*}}, i32 0
- // CHECK: insertelement <8 x float> {{.*}}, i32 1
- // CHECK: insertelement <8 x float> {{.*}}, i32 2
- // CHECK: insertelement <8 x float> {{.*}}, i32 3
- // CHECK: insertelement <8 x float> {{.*}}, i32 4
- // CHECK: insertelement <8 x float> {{.*}}, i32 5
- // CHECK: insertelement <8 x float> {{.*}}, i32 6
- // CHECK: insertelement <8 x float> {{.*}}, i32 7
+ // CHECK: shufflevector <8 x float> {{.*}}, <8 x float> undef, <8 x i32> zeroinitializer
return _mm256_broadcast_ss(__a);
}
diff --git a/test/CodeGen/avx2-builtins.c b/test/CodeGen/avx2-builtins.c
index 1e7124537331..4ccf6e6da97b 100644
--- a/test/CodeGen/avx2-builtins.c
+++ b/test/CodeGen/avx2-builtins.c
@@ -1,8 +1,6 @@
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +avx2 -emit-llvm -o - -Werror | FileCheck %s
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +avx2 -fno-signed-char -emit-llvm -o - -Werror | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +avx2 -emit-llvm -o - -Wall -Werror | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +avx2 -fno-signed-char -emit-llvm -o - -Wall -Werror | FileCheck %s
-// Don't include mm_malloc.h, it's system specific.
-#define __MM_MALLOC_H
#include <x86intrin.h>
diff --git a/test/CodeGen/avx512-inline-asm-kregisters-basics.c b/test/CodeGen/avx512-inline-asm-kregisters-basics.c
new file mode 100644
index 000000000000..8c0cb9f53456
--- /dev/null
+++ b/test/CodeGen/avx512-inline-asm-kregisters-basics.c
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 %s -O0 -triple=x86_64-apple-darwin -target-cpu skylake-avx512 -emit-llvm -o - -Wall -Werror | FileCheck %s
+// This test checks basic inline assembly recognition of k0-k7 registers for avx512.
+
+void test_basic_inline_asm_with_k_regs() {
+ //CHECK: kandw %k1, %k2, %k3
+ asm("kandw %k1, %k2, %k3\t");
+ //CHECK: kandw %k4, %k5, %k6
+ asm("kandw %k4, %k5, %k6\t");
+ //CHECK: kandw %k7, %k0, %k1
+ asm("kandw %k7, %k0, %k1\t");
+} \ No newline at end of file
diff --git a/test/CodeGen/avx512-kconstraints-att_inline_asm.c b/test/CodeGen/avx512-kconstraints-att_inline_asm.c
new file mode 100644
index 000000000000..df93ddf7bbb9
--- /dev/null
+++ b/test/CodeGen/avx512-kconstraints-att_inline_asm.c
@@ -0,0 +1,59 @@
+// RUN: %clang_cc1 %s -O0 -triple=x86_64-apple-darwin -target-cpu skylake-avx512 -emit-llvm -o - -Wall -Werror |opt -instnamer -S |FileCheck %s
+// This test checks validity of att\gcc style inline assmebly for avx512 k and Yk constraints.
+// Also checks mask register allows flexible type (size <= 64 bit)
+
+void mask_Yk_i8(char msk){
+//CHECK: vpaddb\09 %xmm1, %xmm0, %xmm1 {$0}\09
+ asm ("vpaddb\t %%xmm1, %%xmm0, %%xmm1 %{%0%}\t"
+ : //output
+ : "Yk" (msk)); //inputs
+}
+
+void mask_Yk_i16(short msk){
+//CHECK: vpaddb\09 %xmm1, %xmm0, %xmm1 {$0}\09
+ asm ("vpaddb\t %%xmm1, %%xmm0, %%xmm1 %{%0%}\t"
+ : //output
+ : "Yk" (msk)); //inputs
+}
+
+void mask_Yk_i32(int msk){
+//CHECK: vpaddb\09 %xmm1, %xmm0, %xmm1 {$0}\09
+ asm ("vpaddb\t %%xmm1, %%xmm0, %%xmm1 %{%0%}\t"
+ : //output
+ : "Yk" (msk)); //inputs
+}
+
+void mask_Yk_i64(long long msk){
+//CHECK: vpaddb\09 %xmm1, %xmm0, %xmm1 {$0}\09
+ asm ("vpaddb\t %%xmm1, %%xmm0, %%xmm1 %{%0%}\t"
+ : //output
+ : "Yk" (msk)); //inputs
+}
+
+void k_wise_op_i8(char msk_dst,char msk_src1,char msk_src2){
+//CHECK: kandw\09$2, $1, $0
+ asm ("kandw\t%2, %1, %0"
+ : "=k" (msk_dst)
+ : "k" (msk_src1), "k" (msk_src2));
+}
+
+void k_wise_op_i16(short msk_dst, short msk_src1, short msk_src2){
+//CHECK: kandw\09$2, $1, $0
+ asm ("kandw\t%2, %1, %0"
+ : "=k" (msk_dst)
+ : "k" (msk_src1), "k" (msk_src2));
+}
+
+void k_wise_op_i32(int msk_dst, int msk_src1, int msk_src2){
+//CHECK: kandw\09$2, $1, $0
+ asm ("kandw\t%2, %1, %0"
+ : "=k" (msk_dst)
+ : "k" (msk_src1), "k" (msk_src2));
+}
+
+void k_wise_op_i64(long long msk_dst, long long msk_src1, long long msk_src2){
+//CHECK: kandw\09$2, $1, $0
+ asm ("kandw\t%2, %1, %0"
+ : "=k" (msk_dst)
+ : "k" (msk_src1), "k" (msk_src2));
+}
diff --git a/test/CodeGen/avx512-reduceIntrin.c b/test/CodeGen/avx512-reduceIntrin.c
new file mode 100644
index 000000000000..d24cd0e5634d
--- /dev/null
+++ b/test/CodeGen/avx512-reduceIntrin.c
@@ -0,0 +1,410 @@
+// RUN: %clang_cc1 -ffreestanding %s -O2 -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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ return _mm512_mask_reduce_mul_ps(__M, __W);
+}
diff --git a/test/CodeGen/avx512-reduceMinMaxIntrin.c b/test/CodeGen/avx512-reduceMinMaxIntrin.c
new file mode 100644
index 000000000000..8249b229c8f5
--- /dev/null
+++ b/test/CodeGen/avx512-reduceMinMaxIntrin.c
@@ -0,0 +1,437 @@
+// RUN: %clang_cc1 -ffreestanding %s -O2 -triple=x86_64-apple-darwin -target-cpu skylake-avx512 -emit-llvm -o - -Wall -Werror |opt -instnamer -S |FileCheck %s
+
+#include <immintrin.h>
+
+long long test_mm512_reduce_max_epi64(__m512i __W){
+ // CHECK: %shuffle1.i = shufflevector <8 x i64> %__W, <8 x i64> undef, <8 x i32> <i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef>
+ // CHECK: %tmp = icmp slt <8 x i64> %shuffle1.i, %__W
+ // CHECK: %tmp1 = select <8 x i1> %tmp, <8 x i64> %__W, <8 x i64> %shuffle1.i
+ // CHECK: %shuffle3.i = shufflevector <8 x i64> %tmp1, <8 x i64> undef, <8 x i32> <i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
+ // CHECK: %tmp2 = icmp sgt <8 x i64> %tmp1, %shuffle3.i
+ // CHECK: %tmp3 = select <8 x i1> %tmp2, <8 x i64> %tmp1, <8 x i64> %shuffle3.i
+ // CHECK: %shuffle6.i = shufflevector <8 x i64> %tmp3, <8 x i64> undef, <8 x i32> <i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
+ // CHECK: %tmp4 = icmp sgt <8 x i64> %tmp3, %shuffle6.i
+ // CHECK: %.elt.i = extractelement <8 x i1> %tmp4, i32 0
+ // CHECK: %.elt20.i = extractelement <8 x i64> %tmp3, i32 0
+ // CHECK: %shuffle6.elt.i = extractelement <8 x i64> %tmp3, i32 1
+ // CHECK: %vecext.i = select i1 %.elt.i, i64 %.elt20.i, i64 %shuffle6.elt.i
+ // CHECK: ret i64 %vecext.i
+ return _mm512_reduce_max_epi64(__W);
+}
+
+unsigned long long test_mm512_reduce_max_epu64(__m512i __W){
+ // CHECK: %shuffle1.i = shufflevector <8 x i64> %__W, <8 x i64> undef, <8 x i32> <i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef>
+ // CHECK: %tmp = icmp ult <8 x i64> %shuffle1.i, %__W
+ // CHECK: %tmp1 = select <8 x i1> %tmp, <8 x i64> %__W, <8 x i64> %shuffle1.i
+ // CHECK: %shuffle3.i = shufflevector <8 x i64> %tmp1, <8 x i64> undef, <8 x i32> <i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
+ // CHECK: %tmp2 = icmp ugt <8 x i64> %tmp1, %shuffle3.i
+ // CHECK: %tmp3 = select <8 x i1> %tmp2, <8 x i64> %tmp1, <8 x i64> %shuffle3.i
+ // CHECK: %shuffle6.i = shufflevector <8 x i64> %tmp3, <8 x i64> undef, <8 x i32> <i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
+ // CHECK: %tmp4 = icmp ugt <8 x i64> %tmp3, %shuffle6.i
+ // CHECK: %.elt.i = extractelement <8 x i1> %tmp4, i32 0
+ // CHECK: %.elt20.i = extractelement <8 x i64> %tmp3, i32 0
+ // CHECK: %shuffle6.elt.i = extractelement <8 x i64> %tmp3, i32 1
+ // CHECK: %vecext.i = select i1 %.elt.i, i64 %.elt20.i, i64 %shuffle6.elt.i
+ // CHECK: ret i64 %vecext.i
+ return _mm512_reduce_max_epu64(__W);
+}
+
+double test_mm512_reduce_max_pd(__m512d __W){
+ // CHECK: %shuffle1.i = shufflevector <8 x double> %__W, <8 x double> undef, <8 x i32> <i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef>
+ // CHECK: %tmp = tail call <8 x double> @llvm.x86.avx512.mask.max.pd.512(<8 x double> %__W, <8 x double> %shuffle1.i, <8 x double> zeroinitializer, i8 -1, i32 4) #3
+ // CHECK: %shuffle3.i = shufflevector <8 x double> %tmp, <8 x double> undef, <8 x i32> <i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
+ // CHECK: %tmp1 = tail call <8 x double> @llvm.x86.avx512.mask.max.pd.512(<8 x double> %tmp, <8 x double> %shuffle3.i, <8 x double> zeroinitializer, i8 -1, i32 4) #3
+ // CHECK: %shuffle6.i = shufflevector <8 x double> %tmp1, <8 x double> undef, <8 x i32> <i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
+ // CHECK: %tmp2 = tail call <8 x double> @llvm.x86.avx512.mask.max.pd.512(<8 x double> %tmp1, <8 x double> %shuffle6.i, <8 x double> zeroinitializer, i8 -1, i32 4) #3
+ // CHECK: %vecext.i = extractelement <8 x double> %tmp2, i32 0
+ // CHECK: ret double %vecext.i
+ return _mm512_reduce_max_pd(__W);
+}
+
+long long test_mm512_reduce_min_epi64(__m512i __W){
+ // CHECK: %shuffle1.i = shufflevector <8 x i64> %__W, <8 x i64> undef, <8 x i32> <i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef>
+ // CHECK: %tmp = icmp slt <8 x i64> %shuffle1.i, %__W
+ // CHECK: %tmp1 = select <8 x i1> %tmp, <8 x i64> %__W, <8 x i64> %shuffle1.i
+ // CHECK: %shuffle3.i = shufflevector <8 x i64> %tmp1, <8 x i64> undef, <8 x i32> <i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
+ // CHECK: %tmp2 = icmp sgt <8 x i64> %tmp1, %shuffle3.i
+ // CHECK: %tmp3 = select <8 x i1> %tmp2, <8 x i64> %tmp1, <8 x i64> %shuffle3.i
+ // CHECK: %shuffle6.i = shufflevector <8 x i64> %tmp3, <8 x i64> undef, <8 x i32> <i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
+ // CHECK: %tmp4 = icmp sgt <8 x i64> %tmp3, %shuffle6.i
+ // CHECK: %.elt.i = extractelement <8 x i1> %tmp4, i32 0
+ // CHECK: %.elt20.i = extractelement <8 x i64> %tmp3, i32 0
+ // CHECK: %shuffle6.elt.i = extractelement <8 x i64> %tmp3, i32 1
+ // CHECK: %vecext.i = select i1 %.elt.i, i64 %.elt20.i, i64 %shuffle6.elt.i
+ // CHECK: ret i64 %vecext.i
+ return _mm512_reduce_max_epi64(__W);
+}
+
+unsigned long long test_mm512_reduce_min_epu64(__m512i __W){
+ // CHECK: %shuffle1.i = shufflevector <8 x i64> %__W, <8 x i64> undef, <8 x i32> <i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef>
+ // CHECK: %tmp = icmp ult <8 x i64> %shuffle1.i, %__W
+ // CHECK: %tmp1 = select <8 x i1> %tmp, <8 x i64> %__W, <8 x i64> %shuffle1.i
+ // CHECK: %shuffle3.i = shufflevector <8 x i64> %tmp1, <8 x i64> undef, <8 x i32> <i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
+ // CHECK: %tmp2 = icmp ugt <8 x i64> %tmp1, %shuffle3.i
+ // CHECK: %tmp3 = select <8 x i1> %tmp2, <8 x i64> %tmp1, <8 x i64> %shuffle3.i
+ // CHECK: %shuffle6.i = shufflevector <8 x i64> %tmp3, <8 x i64> undef, <8 x i32> <i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
+ // CHECK: %tmp4 = icmp ugt <8 x i64> %tmp3, %shuffle6.i
+ // CHECK: %.elt.i = extractelement <8 x i1> %tmp4, i32 0
+ // CHECK: %.elt20.i = extractelement <8 x i64> %tmp3, i32 0
+ // CHECK: %shuffle6.elt.i = extractelement <8 x i64> %tmp3, i32 1
+ // CHECK: %vecext.i = select i1 %.elt.i, i64 %.elt20.i, i64 %shuffle6.elt.i
+ // CHECK: ret i64 %vecext.i
+ return _mm512_reduce_max_epu64(__W);
+}
+
+double test_mm512_reduce_min_pd(__m512d __W){
+ // CHECK: %shuffle1.i = shufflevector <8 x double> %__W, <8 x double> undef, <8 x i32> <i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef>
+ // CHECK: %tmp = tail call <8 x double> @llvm.x86.avx512.mask.min.pd.512(<8 x double> %__W, <8 x double> %shuffle1.i, <8 x double> zeroinitializer, i8 -1, i32 4) #3
+ // CHECK: %shuffle3.i = shufflevector <8 x double> %tmp, <8 x double> undef, <8 x i32> <i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
+ // CHECK: %tmp1 = tail call <8 x double> @llvm.x86.avx512.mask.min.pd.512(<8 x double> %tmp, <8 x double> %shuffle3.i, <8 x double> zeroinitializer, i8 -1, i32 4) #3
+ // CHECK: %shuffle6.i = shufflevector <8 x double> %tmp1, <8 x double> undef, <8 x i32> <i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
+ // CHECK: %tmp2 = tail call <8 x double> @llvm.x86.avx512.mask.min.pd.512(<8 x double> %tmp1, <8 x double> %shuffle6.i, <8 x double> zeroinitializer, i8 -1, i32 4) #3
+ // CHECK: %vecext.i = extractelement <8 x double> %tmp2, i32 0
+ // CHECK: ret double %vecext.i
+ return _mm512_reduce_min_pd(__W);
+}
+
+long long test_mm512_mask_reduce_max_epi64(__mmask8 __M, __m512i __W){
+ // CHECK: %tmp = bitcast i8 %__M to <8 x i1>
+ // CHECK: %tmp1 = select <8 x i1> %tmp, <8 x i64> %__W, <8 x i64> <i64 -9223372036854775808, i64 -9223372036854775808, i64 -9223372036854775808, i64 -9223372036854775808, i64 -9223372036854775808, i64 -9223372036854775808, i64 -9223372036854775808, i64 -9223372036854775808>
+ // CHECK: %shuffle1.i = shufflevector <8 x i64> %tmp1, <8 x i64> undef, <8 x i32> <i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef>
+ // CHECK: %tmp2 = icmp sgt <8 x i64> %tmp1, %shuffle1.i
+ // CHECK: %tmp3 = select <8 x i1> %tmp2, <8 x i64> %tmp1, <8 x i64> %shuffle1.i
+ // CHECK: %shuffle4.i = shufflevector <8 x i64> %tmp3, <8 x i64> undef, <8 x i32> <i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
+ // CHECK: %tmp4 = icmp sgt <8 x i64> %tmp3, %shuffle4.i
+ // CHECK: %tmp5 = select <8 x i1> %tmp4, <8 x i64> %tmp3, <8 x i64> %shuffle4.i
+ // CHECK: %shuffle7.i = shufflevector <8 x i64> %tmp5, <8 x i64> undef, <8 x i32> <i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
+ // CHECK: %tmp6 = icmp sgt <8 x i64> %tmp5, %shuffle7.i
+ // CHECK: %.elt.i = extractelement <8 x i1> %tmp6, i32 0
+ // CHECK: %.elt22.i = extractelement <8 x i64> %tmp5, i32 0
+ // CHECK: %shuffle7.elt.i = extractelement <8 x i64> %tmp5, i32 1
+ // CHECK: %vecext.i = select i1 %.elt.i, i64 %.elt22.i, i64 %shuffle7.elt.i
+ // CHECK: ret i64 %vecext.i
+ return _mm512_mask_reduce_max_epi64(__M, __W);
+}
+
+unsigned long test_mm512_mask_reduce_max_epu64(__mmask8 __M, __m512i __W){
+ // CHECK: %tmp = bitcast i8 %__M to <8 x i1>
+ // CHECK: %tmp1 = select <8 x i1> %tmp, <8 x i64> %__W, <8 x i64> zeroinitializer
+ // CHECK: %shuffle1.i = shufflevector <8 x i64> %tmp1, <8 x i64> undef, <8 x i32> <i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef>
+ // CHECK: %tmp2 = icmp ugt <8 x i64> %tmp1, %shuffle1.i
+ // CHECK: %tmp3 = select <8 x i1> %tmp2, <8 x i64> %tmp1, <8 x i64> %shuffle1.i
+ // CHECK: %shuffle4.i = shufflevector <8 x i64> %tmp3, <8 x i64> undef, <8 x i32> <i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
+ // CHECK: %tmp4 = icmp ugt <8 x i64> %tmp3, %shuffle4.i
+ // CHECK: %tmp5 = select <8 x i1> %tmp4, <8 x i64> %tmp3, <8 x i64> %shuffle4.i
+ // CHECK: %shuffle7.i = shufflevector <8 x i64> %tmp5, <8 x i64> undef, <8 x i32> <i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
+ // CHECK: %tmp6 = icmp ugt <8 x i64> %tmp5, %shuffle7.i
+ // CHECK: %.elt.i = extractelement <8 x i1> %tmp6, i32 0
+ // CHECK: %.elt22.i = extractelement <8 x i64> %tmp5, i32 0
+ // CHECK: %shuffle7.elt.i = extractelement <8 x i64> %tmp5, i32 1
+ // CHECK: %vecext.i = select i1 %.elt.i, i64 %.elt22.i, i64 %shuffle7.elt.i
+ // CHECK: ret i64 %vecext.i
+ return _mm512_mask_reduce_max_epu64(__M, __W);
+}
+
+long long test_mm512_mask_reduce_max_pd(__mmask8 __M, __m512d __W){
+ // CHECK: %tmp = bitcast i8 %__M to <8 x i1>
+ // CHECK: %tmp1 = select <8 x i1> %tmp, <8 x double> %__W, <8 x double> <double 0xFFF0000000000000, double 0xFFF0000000000000, double 0xFFF0000000000000, double 0xFFF0000000000000, double 0xFFF0000000000000, double 0xFFF0000000000000, double 0xFFF0000000000000, double 0xFFF0000000000000>
+ // CHECK: %shuffle1.i = shufflevector <8 x double> %tmp1, <8 x double> undef, <8 x i32> <i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef>
+ // CHECK: %tmp2 = tail call <8 x double> @llvm.x86.avx512.mask.max.pd.512(<8 x double> %tmp1, <8 x double> %shuffle1.i, <8 x double> zeroinitializer, i8 -1, i32 4) #3
+ // CHECK: %shuffle4.i = shufflevector <8 x double> %tmp2, <8 x double> undef, <8 x i32> <i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
+ // CHECK: %tmp3 = tail call <8 x double> @llvm.x86.avx512.mask.max.pd.512(<8 x double> %tmp2, <8 x double> %shuffle4.i, <8 x double> zeroinitializer, i8 -1, i32 4) #3
+ // CHECK: %shuffle7.i = shufflevector <8 x double> %tmp3, <8 x double> undef, <8 x i32> <i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
+ // CHECK: %tmp4 = tail call <8 x double> @llvm.x86.avx512.mask.max.pd.512(<8 x double> %tmp3, <8 x double> %shuffle7.i, <8 x double> zeroinitializer, i8 -1, i32 4) #3
+ // CHECK: %vecext.i = extractelement <8 x double> %tmp4, i32 0
+ // CHECK: %conv = fptosi double %vecext.i to i64
+ // CHECK: ret i64 %conv
+ return _mm512_mask_reduce_max_pd(__M, __W);
+}
+
+long long test_mm512_mask_reduce_min_epi64(__mmask8 __M, __m512i __W){
+ // CHECK: %tmp = bitcast i8 %__M to <8 x i1>
+ // CHECK: %tmp1 = select <8 x i1> %tmp, <8 x i64> %__W, <8 x i64> <i64 9223372036854775807, i64 9223372036854775807, i64 9223372036854775807, i64 9223372036854775807, i64 9223372036854775807, i64 9223372036854775807, i64 9223372036854775807, i64 9223372036854775807>
+ // CHECK: %shuffle1.i = shufflevector <8 x i64> %tmp1, <8 x i64> undef, <8 x i32> <i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef>
+ // CHECK: %tmp2 = icmp slt <8 x i64> %tmp1, %shuffle1.i
+ // CHECK: %tmp3 = select <8 x i1> %tmp2, <8 x i64> %tmp1, <8 x i64> %shuffle1.i
+ // CHECK: %shuffle4.i = shufflevector <8 x i64> %tmp3, <8 x i64> undef, <8 x i32> <i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
+ // CHECK: %tmp4 = icmp slt <8 x i64> %tmp3, %shuffle4.i
+ // CHECK: %tmp5 = select <8 x i1> %tmp4, <8 x i64> %tmp3, <8 x i64> %shuffle4.i
+ // CHECK: %shuffle7.i = shufflevector <8 x i64> %tmp5, <8 x i64> undef, <8 x i32> <i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
+ // CHECK: %tmp6 = icmp slt <8 x i64> %tmp5, %shuffle7.i
+ // CHECK: %.elt.i = extractelement <8 x i1> %tmp6, i32 0
+ // CHECK: %.elt22.i = extractelement <8 x i64> %tmp5, i32 0
+ // CHECK: %shuffle7.elt.i = extractelement <8 x i64> %tmp5, i32 1
+ // CHECK: %vecext.i = select i1 %.elt.i, i64 %.elt22.i, i64 %shuffle7.elt.i
+ // CHECK: ret i64 %vecext.i
+ return _mm512_mask_reduce_min_epi64(__M, __W);
+}
+
+long long test_mm512_mask_reduce_min_epu64(__mmask8 __M, __m512i __W){
+ // CHECK: %tmp = bitcast i8 %__M to <8 x i1>
+ // CHECK: %tmp1 = select <8 x i1> %tmp, <8 x i64> %__W, <8 x i64> zeroinitializer
+ // CHECK: %shuffle1.i = shufflevector <8 x i64> %tmp1, <8 x i64> undef, <8 x i32> <i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef>
+ // CHECK: %tmp2 = icmp ugt <8 x i64> %tmp1, %shuffle1.i
+ // CHECK: %tmp3 = select <8 x i1> %tmp2, <8 x i64> %tmp1, <8 x i64> %shuffle1.i
+ // CHECK: %shuffle4.i = shufflevector <8 x i64> %tmp3, <8 x i64> undef, <8 x i32> <i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
+ // CHECK: %tmp4 = icmp ugt <8 x i64> %tmp3, %shuffle4.i
+ // CHECK: %tmp5 = select <8 x i1> %tmp4, <8 x i64> %tmp3, <8 x i64> %shuffle4.i
+ // CHECK: %shuffle7.i = shufflevector <8 x i64> %tmp5, <8 x i64> undef, <8 x i32> <i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
+ // CHECK: %tmp6 = icmp ugt <8 x i64> %tmp5, %shuffle7.i
+ // CHECK: %.elt.i = extractelement <8 x i1> %tmp6, i32 0
+ // CHECK: %.elt22.i = extractelement <8 x i64> %tmp5, i32 0
+ // CHECK: %shuffle7.elt.i = extractelement <8 x i64> %tmp5, i32 1
+ // CHECK: %vecext.i = select i1 %.elt.i, i64 %.elt22.i, i64 %shuffle7.elt.i
+ // CHECK: ret i64 %vecext.i
+ return _mm512_mask_reduce_max_epu64(__M, __W);
+}
+
+double test_mm512_mask_reduce_min_pd(__mmask8 __M, __m512d __W){
+ // CHECK: %tmp = bitcast i8 %__M to <8 x i1>
+ // CHECK: %tmp1 = select <8 x i1> %tmp, <8 x double> %__W, <8 x double> <double 0x7FF0000000000000, double 0x7FF0000000000000, double 0x7FF0000000000000, double 0x7FF0000000000000, double 0x7FF0000000000000, double 0x7FF0000000000000, double 0x7FF0000000000000, double 0x7FF0000000000000>
+ // CHECK: %shuffle1.i = shufflevector <8 x double> %tmp1, <8 x double> undef, <8 x i32> <i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef>
+ // CHECK: %tmp2 = tail call <8 x double> @llvm.x86.avx512.mask.min.pd.512(<8 x double> %tmp1, <8 x double> %shuffle1.i, <8 x double> zeroinitializer, i8 -1, i32 4) #3
+ // CHECK: %shuffle4.i = shufflevector <8 x double> %tmp2, <8 x double> undef, <8 x i32> <i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
+ // CHECK: %tmp3 = tail call <8 x double> @llvm.x86.avx512.mask.min.pd.512(<8 x double> %tmp2, <8 x double> %shuffle4.i, <8 x double> zeroinitializer, i8 -1, i32 4) #3
+ // CHECK: %shuffle7.i = shufflevector <8 x double> %tmp3, <8 x double> undef, <8 x i32> <i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
+ // CHECK: %tmp4 = tail call <8 x double> @llvm.x86.avx512.mask.min.pd.512(<8 x double> %tmp3, <8 x double> %shuffle7.i, <8 x double> zeroinitializer, i8 -1, i32 4) #3
+ // CHECK: %vecext.i = extractelement <8 x double> %tmp4, i32 0
+ // CHECK: ret double %vecext.i
+ return _mm512_mask_reduce_min_pd(__M, __W);
+}
+
+int test_mm512_reduce_max_epi32(__m512i __W){
+ // CHECK: %tmp = bitcast <8 x i64> %__W to <16 x i32>
+ // CHECK: %shuffle1.i = shufflevector <16 x i32> %tmp, <16 x i32> undef, <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: %tmp1 = icmp sgt <16 x i32> %tmp, %shuffle1.i
+ // CHECK: %tmp2 = select <16 x i1> %tmp1, <16 x i32> %tmp, <16 x i32> %shuffle1.i
+ // CHECK: %shuffle3.i = shufflevector <16 x i32> %tmp2, <16 x i32> undef, <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: %tmp3 = icmp sgt <16 x i32> %tmp2, %shuffle3.i
+ // CHECK: %tmp4 = select <16 x i1> %tmp3, <16 x i32> %tmp2, <16 x i32> %shuffle3.i
+ // CHECK: %shuffle6.i = shufflevector <16 x i32> %tmp4, <16 x i32> undef, <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: %tmp5 = icmp sgt <16 x i32> %tmp4, %shuffle6.i
+ // CHECK: %tmp6 = select <16 x i1> %tmp5, <16 x i32> %tmp4, <16 x i32> %shuffle6.i
+ // CHECK: %shuffle9.i = shufflevector <16 x i32> %tmp6, <16 x i32> undef, <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: %tmp7 = icmp sgt <16 x i32> %tmp6, %shuffle9.i
+ // CHECK: %tmp8 = select <16 x i1> %tmp7, <16 x i32> %tmp6, <16 x i32> %shuffle9.i
+ // CHECK: %tmp9 = bitcast <16 x i32> %tmp8 to <8 x i64>
+ // CHECK: %vecext.i = extractelement <8 x i64> %tmp9, i32 0
+ // CHECK: %conv.i = trunc i64 %vecext.i to i32
+ // CHECK: ret i32 %conv.i
+ return _mm512_reduce_max_epi32(__W);
+}
+
+unsigned int test_mm512_reduce_max_epu32(__m512i __W){
+ // CHECK: %tmp = bitcast <8 x i64> %__W to <16 x i32>
+ // CHECK: %shuffle1.i = shufflevector <16 x i32> %tmp, <16 x i32> undef, <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: %tmp1 = icmp ugt <16 x i32> %tmp, %shuffle1.i
+ // CHECK: %tmp2 = select <16 x i1> %tmp1, <16 x i32> %tmp, <16 x i32> %shuffle1.i
+ // CHECK: %shuffle3.i = shufflevector <16 x i32> %tmp2, <16 x i32> undef, <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: %tmp3 = icmp ugt <16 x i32> %tmp2, %shuffle3.i
+ // CHECK: %tmp4 = select <16 x i1> %tmp3, <16 x i32> %tmp2, <16 x i32> %shuffle3.i
+ // CHECK: %shuffle6.i = shufflevector <16 x i32> %tmp4, <16 x i32> undef, <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: %tmp5 = icmp ugt <16 x i32> %tmp4, %shuffle6.i
+ // CHECK: %tmp6 = select <16 x i1> %tmp5, <16 x i32> %tmp4, <16 x i32> %shuffle6.i
+ // CHECK: %shuffle9.i = shufflevector <16 x i32> %tmp6, <16 x i32> undef, <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: %tmp7 = icmp ugt <16 x i32> %tmp6, %shuffle9.i
+ // CHECK: %tmp8 = select <16 x i1> %tmp7, <16 x i32> %tmp6, <16 x i32> %shuffle9.i
+ // CHECK: %tmp9 = bitcast <16 x i32> %tmp8 to <8 x i64>
+ // CHECK: %vecext.i = extractelement <8 x i64> %tmp9, i32 0
+ // CHECK: %conv.i = trunc i64 %vecext.i to i32
+ // CHECK: ret i32 %conv.i
+ return _mm512_reduce_max_epu32(__W);
+}
+
+float test_mm512_reduce_max_ps(__m512 __W){
+ // CHECK: %shuffle1.i = shufflevector <16 x float> %__W, <16 x float> undef, <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: %tmp = tail call <16 x float> @llvm.x86.avx512.mask.max.ps.512(<16 x float> %__W, <16 x float> %shuffle1.i, <16 x float> zeroinitializer, i16 -1, i32 4) #3
+ // CHECK: %shuffle3.i = shufflevector <16 x float> %tmp, <16 x float> undef, <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: %tmp1 = tail call <16 x float> @llvm.x86.avx512.mask.max.ps.512(<16 x float> %tmp, <16 x float> %shuffle3.i, <16 x float> zeroinitializer, i16 -1, i32 4) #3
+ // CHECK: %shuffle6.i = shufflevector <16 x float> %tmp1, <16 x float> undef, <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: %tmp2 = tail call <16 x float> @llvm.x86.avx512.mask.max.ps.512(<16 x float> %tmp1, <16 x float> %shuffle6.i, <16 x float> zeroinitializer, i16 -1, i32 4) #3
+ // CHECK: %shuffle9.i = shufflevector <16 x float> %tmp2, <16 x float> undef, <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: %tmp3 = tail call <16 x float> @llvm.x86.avx512.mask.max.ps.512(<16 x float> %tmp2, <16 x float> %shuffle9.i, <16 x float> zeroinitializer, i16 -1, i32 4) #3
+ // CHECK: %vecext.i = extractelement <16 x float> %tmp3, i32 0
+ // CHECK: ret float %vecext.i
+ return _mm512_reduce_max_ps(__W);
+}
+
+int test_mm512_reduce_min_epi32(__m512i __W){
+ // CHECK: %tmp = bitcast <8 x i64> %__W to <16 x i32>
+ // CHECK: %shuffle1.i = shufflevector <16 x i32> %tmp, <16 x i32> undef, <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: %tmp1 = icmp slt <16 x i32> %tmp, %shuffle1.i
+ // CHECK: %tmp2 = select <16 x i1> %tmp1, <16 x i32> %tmp, <16 x i32> %shuffle1.i
+ // CHECK: %shuffle3.i = shufflevector <16 x i32> %tmp2, <16 x i32> undef, <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: %tmp3 = icmp slt <16 x i32> %tmp2, %shuffle3.i
+ // CHECK: %tmp4 = select <16 x i1> %tmp3, <16 x i32> %tmp2, <16 x i32> %shuffle3.i
+ // CHECK: %shuffle6.i = shufflevector <16 x i32> %tmp4, <16 x i32> undef, <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: %tmp5 = icmp slt <16 x i32> %tmp4, %shuffle6.i
+ // CHECK: %tmp6 = select <16 x i1> %tmp5, <16 x i32> %tmp4, <16 x i32> %shuffle6.i
+ // CHECK: %shuffle9.i = shufflevector <16 x i32> %tmp6, <16 x i32> undef, <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: %tmp7 = icmp slt <16 x i32> %tmp6, %shuffle9.i
+ // CHECK: %tmp8 = select <16 x i1> %tmp7, <16 x i32> %tmp6, <16 x i32> %shuffle9.i
+ // CHECK: %tmp9 = bitcast <16 x i32> %tmp8 to <8 x i64>
+ // CHECK: %vecext.i = extractelement <8 x i64> %tmp9, i32 0
+ // CHECK: %conv.i = trunc i64 %vecext.i to i32
+ // CHECK: ret i32 %conv.i
+ return _mm512_reduce_min_epi32(__W);
+}
+
+unsigned int test_mm512_reduce_min_epu32(__m512i __W){
+ // CHECK: %tmp = bitcast <8 x i64> %__W to <16 x i32>
+ // CHECK: %shuffle1.i = shufflevector <16 x i32> %tmp, <16 x i32> undef, <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: %tmp1 = icmp ult <16 x i32> %tmp, %shuffle1.i
+ // CHECK: %tmp2 = select <16 x i1> %tmp1, <16 x i32> %tmp, <16 x i32> %shuffle1.i
+ // CHECK: %shuffle3.i = shufflevector <16 x i32> %tmp2, <16 x i32> undef, <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: %tmp3 = icmp ult <16 x i32> %tmp2, %shuffle3.i
+ // CHECK: %tmp4 = select <16 x i1> %tmp3, <16 x i32> %tmp2, <16 x i32> %shuffle3.i
+ // CHECK: %shuffle6.i = shufflevector <16 x i32> %tmp4, <16 x i32> undef, <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: %tmp5 = icmp ult <16 x i32> %tmp4, %shuffle6.i
+ // CHECK: %tmp6 = select <16 x i1> %tmp5, <16 x i32> %tmp4, <16 x i32> %shuffle6.i
+ // CHECK: %shuffle9.i = shufflevector <16 x i32> %tmp6, <16 x i32> undef, <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: %tmp7 = icmp ult <16 x i32> %tmp6, %shuffle9.i
+ // CHECK: %tmp8 = select <16 x i1> %tmp7, <16 x i32> %tmp6, <16 x i32> %shuffle9.i
+ // CHECK: %tmp9 = bitcast <16 x i32> %tmp8 to <8 x i64>
+ // CHECK: %vecext.i = extractelement <8 x i64> %tmp9, i32 0
+ // CHECK: %conv.i = trunc i64 %vecext.i to i32
+ // CHECK: ret i32 %conv.i
+ return _mm512_reduce_min_epu32(__W);
+}
+
+float test_mm512_reduce_min_ps(__m512 __W){
+ // CHECK: %shuffle1.i = shufflevector <16 x float> %__W, <16 x float> undef, <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: %tmp = tail call <16 x float> @llvm.x86.avx512.mask.min.ps.512(<16 x float> %__W, <16 x float> %shuffle1.i, <16 x float> zeroinitializer, i16 -1, i32 4) #3
+ // CHECK: %shuffle3.i = shufflevector <16 x float> %tmp, <16 x float> undef, <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: %tmp1 = tail call <16 x float> @llvm.x86.avx512.mask.min.ps.512(<16 x float> %tmp, <16 x float> %shuffle3.i, <16 x float> zeroinitializer, i16 -1, i32 4) #3
+ // CHECK: %shuffle6.i = shufflevector <16 x float> %tmp1, <16 x float> undef, <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: %tmp2 = tail call <16 x float> @llvm.x86.avx512.mask.min.ps.512(<16 x float> %tmp1, <16 x float> %shuffle6.i, <16 x float> zeroinitializer, i16 -1, i32 4) #3
+ // CHECK: %shuffle9.i = shufflevector <16 x float> %tmp2, <16 x float> undef, <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: %tmp3 = tail call <16 x float> @llvm.x86.avx512.mask.min.ps.512(<16 x float> %tmp2, <16 x float> %shuffle9.i, <16 x float> zeroinitializer, i16 -1, i32 4) #3
+ // CHECK: %vecext.i = extractelement <16 x float> %tmp3, i32 0
+ // CHECK: ret float %vecext.i
+ return _mm512_reduce_min_ps(__W);
+}
+
+int test_mm512_mask_reduce_max_epi32(__mmask16 __M, __m512i __W){
+ // CHECK: %tmp = bitcast <8 x i64> %__W to <16 x i32>
+ // CHECK: %tmp1 = bitcast i16 %__M to <16 x i1>
+ // CHECK: %tmp2 = select <16 x i1> %tmp1, <16 x i32> %tmp, <16 x i32> <i32 -2147483648, i32 -2147483648, i32 -2147483648, i32 -2147483648, i32 -2147483648, i32 -2147483648, i32 -2147483648, i32 -2147483648, i32 -2147483648, i32 -2147483648, i32 -2147483648, i32 -2147483648, i32 -2147483648, i32 -2147483648, i32 -2147483648, i32 -2147483648>
+ // CHECK: %shuffle1.i = shufflevector <16 x i32> %tmp2, <16 x i32> undef, <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: %tmp3 = icmp sgt <16 x i32> %tmp2, %shuffle1.i
+ // CHECK: %tmp4 = select <16 x i1> %tmp3, <16 x i32> %tmp2, <16 x i32> %shuffle1.i
+ // CHECK: %shuffle4.i = shufflevector <16 x i32> %tmp4, <16 x i32> undef, <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: %tmp5 = icmp sgt <16 x i32> %tmp4, %shuffle4.i
+ // CHECK: %tmp6 = select <16 x i1> %tmp5, <16 x i32> %tmp4, <16 x i32> %shuffle4.i
+ // CHECK: %shuffle7.i = shufflevector <16 x i32> %tmp6, <16 x i32> undef, <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: %tmp7 = icmp sgt <16 x i32> %tmp6, %shuffle7.i
+ // CHECK: %tmp8 = select <16 x i1> %tmp7, <16 x i32> %tmp6, <16 x i32> %shuffle7.i
+ // CHECK: %shuffle10.i = shufflevector <16 x i32> %tmp8, <16 x i32> undef, <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: %tmp9 = icmp sgt <16 x i32> %tmp8, %shuffle10.i
+ // CHECK: %tmp10 = select <16 x i1> %tmp9, <16 x i32> %tmp8, <16 x i32> %shuffle10.i
+ // CHECK: %tmp11 = bitcast <16 x i32> %tmp10 to <8 x i64>
+ // CHECK: %vecext.i = extractelement <8 x i64> %tmp11, i32 0
+ // CHECK: %conv.i = trunc i64 %vecext.i to i32
+ // CHECK: ret i32 %conv.i
+ return _mm512_mask_reduce_max_epi32(__M, __W);
+}
+
+unsigned int test_mm512_mask_reduce_max_epu32(__mmask16 __M, __m512i __W){
+ // CHECK: %tmp = bitcast <8 x i64> %__W to <16 x i32>
+ // CHECK: %tmp1 = bitcast i16 %__M to <16 x i1>
+ // CHECK: %tmp2 = select <16 x i1> %tmp1, <16 x i32> %tmp, <16 x i32> zeroinitializer
+ // CHECK: %shuffle1.i = shufflevector <16 x i32> %tmp2, <16 x i32> undef, <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: %tmp3 = icmp ugt <16 x i32> %tmp2, %shuffle1.i
+ // CHECK: %tmp4 = select <16 x i1> %tmp3, <16 x i32> %tmp2, <16 x i32> %shuffle1.i
+ // CHECK: %shuffle4.i = shufflevector <16 x i32> %tmp4, <16 x i32> undef, <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: %tmp5 = icmp ugt <16 x i32> %tmp4, %shuffle4.i
+ // CHECK: %tmp6 = select <16 x i1> %tmp5, <16 x i32> %tmp4, <16 x i32> %shuffle4.i
+ // CHECK: %shuffle7.i = shufflevector <16 x i32> %tmp6, <16 x i32> undef, <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: %tmp7 = icmp ugt <16 x i32> %tmp6, %shuffle7.i
+ // CHECK: %tmp8 = select <16 x i1> %tmp7, <16 x i32> %tmp6, <16 x i32> %shuffle7.i
+ // CHECK: %shuffle10.i = shufflevector <16 x i32> %tmp8, <16 x i32> undef, <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: %tmp9 = icmp ugt <16 x i32> %tmp8, %shuffle10.i
+ // CHECK: %tmp10 = select <16 x i1> %tmp9, <16 x i32> %tmp8, <16 x i32> %shuffle10.i
+ // CHECK: %tmp11 = bitcast <16 x i32> %tmp10 to <8 x i64>
+ // CHECK: %vecext.i = extractelement <8 x i64> %tmp11, i32 0
+ // CHECK: %conv.i = trunc i64 %vecext.i to i32
+ // CHECK: ret i32 %conv.i
+ return _mm512_mask_reduce_max_epu32(__M, __W);
+}
+
+float test_mm512_mask_reduce_max_ps(__mmask16 __M, __m512 __W){
+ // CHECK: %tmp = bitcast i16 %__M to <16 x i1>
+ // CHECK: %tmp1 = select <16 x i1> %tmp, <16 x float> %__W, <16 x float> <float 0xFFF0000000000000, float 0xFFF0000000000000, float 0xFFF0000000000000, float 0xFFF0000000000000, float 0xFFF0000000000000, float 0xFFF0000000000000, float 0xFFF0000000000000, float 0xFFF0000000000000, float 0xFFF0000000000000, float 0xFFF0000000000000, float 0xFFF0000000000000, float 0xFFF0000000000000, float 0xFFF0000000000000, float 0xFFF0000000000000, float 0xFFF0000000000000, float 0xFFF0000000000000>
+ // CHECK: %shuffle1.i = shufflevector <16 x float> %tmp1, <16 x float> undef, <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: %tmp2 = tail call <16 x float> @llvm.x86.avx512.mask.max.ps.512(<16 x float> %tmp1, <16 x float> %shuffle1.i, <16 x float> zeroinitializer, i16 -1, i32 4) #3
+ // CHECK: %shuffle4.i = shufflevector <16 x float> %tmp2, <16 x float> undef, <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: %tmp3 = tail call <16 x float> @llvm.x86.avx512.mask.max.ps.512(<16 x float> %tmp2, <16 x float> %shuffle4.i, <16 x float> zeroinitializer, i16 -1, i32 4) #3
+ // CHECK: %shuffle7.i = shufflevector <16 x float> %tmp3, <16 x float> undef, <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: %tmp4 = tail call <16 x float> @llvm.x86.avx512.mask.max.ps.512(<16 x float> %tmp3, <16 x float> %shuffle7.i, <16 x float> zeroinitializer, i16 -1, i32 4) #3
+ // CHECK: %shuffle10.i = shufflevector <16 x float> %tmp4, <16 x float> undef, <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: %tmp5 = tail call <16 x float> @llvm.x86.avx512.mask.max.ps.512(<16 x float> %tmp4, <16 x float> %shuffle10.i, <16 x float> zeroinitializer, i16 -1, i32 4) #3
+ // CHECK: %vecext.i = extractelement <16 x float> %tmp5, i32 0
+ // CHECK: ret float %vecext.i
+ return _mm512_mask_reduce_max_ps(__M, __W);
+}
+
+int test_mm512_mask_reduce_min_epi32(__mmask16 __M, __m512i __W){
+ // CHECK: %tmp = bitcast <8 x i64> %__W to <16 x i32>
+ // CHECK: %tmp1 = bitcast i16 %__M to <16 x i1>
+ // CHECK: %tmp2 = select <16 x i1> %tmp1, <16 x i32> %tmp, <16 x i32> <i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647>
+ // CHECK: %shuffle1.i = shufflevector <16 x i32> %tmp2, <16 x i32> undef, <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: %tmp3 = icmp slt <16 x i32> %tmp2, %shuffle1.i
+ // CHECK: %tmp4 = select <16 x i1> %tmp3, <16 x i32> %tmp2, <16 x i32> %shuffle1.i
+ // CHECK: %shuffle4.i = shufflevector <16 x i32> %tmp4, <16 x i32> undef, <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: %tmp5 = icmp slt <16 x i32> %tmp4, %shuffle4.i
+ // CHECK: %tmp6 = select <16 x i1> %tmp5, <16 x i32> %tmp4, <16 x i32> %shuffle4.i
+ // CHECK: %shuffle7.i = shufflevector <16 x i32> %tmp6, <16 x i32> undef, <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: %tmp7 = icmp slt <16 x i32> %tmp6, %shuffle7.i
+ // CHECK: %tmp8 = select <16 x i1> %tmp7, <16 x i32> %tmp6, <16 x i32> %shuffle7.i
+ // CHECK: %shuffle10.i = shufflevector <16 x i32> %tmp8, <16 x i32> undef, <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: %tmp9 = icmp slt <16 x i32> %tmp8, %shuffle10.i
+ // CHECK: %tmp10 = select <16 x i1> %tmp9, <16 x i32> %tmp8, <16 x i32> %shuffle10.i
+ // CHECK: %tmp11 = bitcast <16 x i32> %tmp10 to <8 x i64>
+ // CHECK: %vecext.i = extractelement <8 x i64> %tmp11, i32 0
+ // CHECK: %conv.i = trunc i64 %vecext.i to i32
+ // CHECK: ret i32 %conv.i
+ return _mm512_mask_reduce_min_epi32(__M, __W);
+}
+
+unsigned int test_mm512_mask_reduce_min_epu32(__mmask16 __M, __m512i __W){
+ // CHECK: %tmp = bitcast <8 x i64> %__W to <16 x i32>
+ // CHECK: %tmp1 = bitcast i16 %__M to <16 x i1>
+ // CHECK: %tmp2 = select <16 x i1> %tmp1, <16 x i32> %tmp, <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: %shuffle1.i = shufflevector <16 x i32> %tmp2, <16 x i32> undef, <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: %tmp3 = icmp ult <16 x i32> %tmp2, %shuffle1.i
+ // CHECK: %tmp4 = select <16 x i1> %tmp3, <16 x i32> %tmp2, <16 x i32> %shuffle1.i
+ // CHECK: %shuffle4.i = shufflevector <16 x i32> %tmp4, <16 x i32> undef, <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: %tmp5 = icmp ult <16 x i32> %tmp4, %shuffle4.i
+ // CHECK: %tmp6 = select <16 x i1> %tmp5, <16 x i32> %tmp4, <16 x i32> %shuffle4.i
+ // CHECK: %shuffle7.i = shufflevector <16 x i32> %tmp6, <16 x i32> undef, <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: %tmp7 = icmp ult <16 x i32> %tmp6, %shuffle7.i
+ // CHECK: %tmp8 = select <16 x i1> %tmp7, <16 x i32> %tmp6, <16 x i32> %shuffle7.i
+ // CHECK: %shuffle10.i = shufflevector <16 x i32> %tmp8, <16 x i32> undef, <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: %tmp9 = icmp ult <16 x i32> %tmp8, %shuffle10.i
+ // CHECK: %tmp10 = select <16 x i1> %tmp9, <16 x i32> %tmp8, <16 x i32> %shuffle10.i
+ // CHECK: %tmp11 = bitcast <16 x i32> %tmp10 to <8 x i64>
+ // CHECK: %vecext.i = extractelement <8 x i64> %tmp11, i32 0
+ // CHECK: %conv.i = trunc i64 %vecext.i to i32
+ // CHECK: ret i32 %conv.i
+ return _mm512_mask_reduce_min_epu32(__M, __W);
+}
+
+float test_mm512_mask_reduce_min_ps(__mmask16 __M, __m512 __W){
+ // CHECK: %tmp = bitcast i16 %__M to <16 x i1>
+ // CHECK: %tmp1 = select <16 x i1> %tmp, <16 x float> %__W, <16 x float> <float 0x7FF0000000000000, float 0x7FF0000000000000, float 0x7FF0000000000000, float 0x7FF0000000000000, float 0x7FF0000000000000, float 0x7FF0000000000000, float 0x7FF0000000000000, float 0x7FF0000000000000, float 0x7FF0000000000000, float 0x7FF0000000000000, float 0x7FF0000000000000, float 0x7FF0000000000000, float 0x7FF0000000000000, float 0x7FF0000000000000, float 0x7FF0000000000000, float 0x7FF0000000000000>
+ // CHECK: %shuffle1.i = shufflevector <16 x float> %tmp1, <16 x float> undef, <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: %tmp2 = tail call <16 x float> @llvm.x86.avx512.mask.min.ps.512(<16 x float> %tmp1, <16 x float> %shuffle1.i, <16 x float> zeroinitializer, i16 -1, i32 4) #3
+ // CHECK: %shuffle4.i = shufflevector <16 x float> %tmp2, <16 x float> undef, <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: %tmp3 = tail call <16 x float> @llvm.x86.avx512.mask.min.ps.512(<16 x float> %tmp2, <16 x float> %shuffle4.i, <16 x float> zeroinitializer, i16 -1, i32 4) #3
+ // CHECK: %shuffle7.i = shufflevector <16 x float> %tmp3, <16 x float> undef, <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: %tmp4 = tail call <16 x float> @llvm.x86.avx512.mask.min.ps.512(<16 x float> %tmp3, <16 x float> %shuffle7.i, <16 x float> zeroinitializer, i16 -1, i32 4) #3
+ // CHECK: %shuffle10.i = shufflevector <16 x float> %tmp4, <16 x float> undef, <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: %tmp5 = tail call <16 x float> @llvm.x86.avx512.mask.min.ps.512(<16 x float> %tmp4, <16 x float> %shuffle10.i, <16 x float> zeroinitializer, i16 -1, i32 4) #3
+ // CHECK: %vecext.i = extractelement <16 x float> %tmp5, i32 0
+ // CHECK: ret float %vecext.i
+ return _mm512_mask_reduce_min_ps(__M, __W);
+}
+
diff --git a/test/CodeGen/avx512bw-builtins.c b/test/CodeGen/avx512bw-builtins.c
index 1cd0a0ccb141..b4dfb5ccb9ec 100644
--- a/test/CodeGen/avx512bw-builtins.c
+++ b/test/CodeGen/avx512bw-builtins.c
@@ -1,8 +1,6 @@
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +avx512bw -emit-llvm -o - -Werror | FileCheck %s
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +avx512bw -fno-signed-char -emit-llvm -o - -Werror | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +avx512bw -emit-llvm -o - -Wall -Werror | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +avx512bw -fno-signed-char -emit-llvm -o - -Wall -Werror | FileCheck %s
-// Don't include mm_malloc.h, it's system specific.
-#define __MM_MALLOC_H
#include <immintrin.h>
@@ -378,13 +376,15 @@ __m512i test_mm512_add_epi8 (__m512i __A, __m512i __B) {
__m512i test_mm512_mask_add_epi8 (__m512i __W, __mmask64 __U, __m512i __A, __m512i __B) {
//CHECK-LABEL: @test_mm512_mask_add_epi8
- //CHECK: @llvm.x86.avx512.mask.padd.b.512
+ //CHECK: add <64 x i8> %{{.*}}, %{{.*}}
+ //CHECK: select <64 x i1> %{{.*}}, <64 x i8> %{{.*}}, <64 x i8> %{{.*}}
return _mm512_mask_add_epi8(__W, __U, __A, __B);
}
__m512i test_mm512_maskz_add_epi8 (__mmask64 __U, __m512i __A, __m512i __B) {
//CHECK-LABEL: @test_mm512_maskz_add_epi8
- //CHECK: @llvm.x86.avx512.mask.padd.b.512
+ //CHECK: add <64 x i8> %{{.*}}, %{{.*}}
+ //CHECK: select <64 x i1> %{{.*}}, <64 x i8> %{{.*}}, <64 x i8> %{{.*}}
return _mm512_maskz_add_epi8(__U, __A, __B);
}
@@ -396,13 +396,15 @@ __m512i test_mm512_sub_epi8 (__m512i __A, __m512i __B) {
__m512i test_mm512_mask_sub_epi8 (__m512i __W, __mmask64 __U, __m512i __A, __m512i __B) {
//CHECK-LABEL: @test_mm512_mask_sub_epi8
- //CHECK: @llvm.x86.avx512.mask.psub.b.512
+ //CHECK: sub <64 x i8> %{{.*}}, %{{.*}}
+ //CHECK: select <64 x i1> %{{.*}}, <64 x i8> %{{.*}}, <64 x i8> %{{.*}}
return _mm512_mask_sub_epi8(__W, __U, __A, __B);
}
__m512i test_mm512_maskz_sub_epi8 (__mmask64 __U, __m512i __A, __m512i __B) {
//CHECK-LABEL: @test_mm512_maskz_sub_epi8
- //CHECK: @llvm.x86.avx512.mask.psub.b.512
+ //CHECK: sub <64 x i8> %{{.*}}, %{{.*}}
+ //CHECK: select <64 x i1> %{{.*}}, <64 x i8> %{{.*}}, <64 x i8> %{{.*}}
return _mm512_maskz_sub_epi8(__U, __A, __B);
}
@@ -414,13 +416,15 @@ __m512i test_mm512_add_epi16 (__m512i __A, __m512i __B) {
__m512i test_mm512_mask_add_epi16 (__m512i __W, __mmask32 __U, __m512i __A, __m512i __B) {
//CHECK-LABEL: @test_mm512_mask_add_epi16
- //CHECK: @llvm.x86.avx512.mask.padd.w.512
+ //CHECK: add <32 x i16> %{{.*}}, %{{.*}}
+ //CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_mask_add_epi16(__W, __U, __A, __B);
}
__m512i test_mm512_maskz_add_epi16 (__mmask32 __U, __m512i __A, __m512i __B) {
//CHECK-LABEL: @test_mm512_maskz_add_epi16
- //CHECK: @llvm.x86.avx512.mask.padd.w.512
+ //CHECK: add <32 x i16> %{{.*}}, %{{.*}}
+ //CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_maskz_add_epi16(__U, __A, __B);
}
@@ -432,13 +436,15 @@ __m512i test_mm512_sub_epi16 (__m512i __A, __m512i __B) {
__m512i test_mm512_mask_sub_epi16 (__m512i __W, __mmask32 __U, __m512i __A, __m512i __B) {
//CHECK-LABEL: @test_mm512_mask_sub_epi16
- //CHECK: @llvm.x86.avx512.mask.psub.w.512
+ //CHECK: sub <32 x i16> %{{.*}}, %{{.*}}
+ //CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_mask_sub_epi16(__W, __U, __A, __B);
}
__m512i test_mm512_maskz_sub_epi16 (__mmask32 __U, __m512i __A, __m512i __B) {
//CHECK-LABEL: @test_mm512_maskz_sub_epi16
- //CHECK: @llvm.x86.avx512.mask.psub.w.512
+ //CHECK: sub <32 x i16> %{{.*}}, %{{.*}}
+ //CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_maskz_sub_epi16(__U, __A, __B);
}
@@ -450,13 +456,15 @@ __m512i test_mm512_mullo_epi16 (__m512i __A, __m512i __B) {
__m512i test_mm512_mask_mullo_epi16 (__m512i __W, __mmask32 __U, __m512i __A, __m512i __B) {
//CHECK-LABEL: @test_mm512_mask_mullo_epi16
- //CHECK: @llvm.x86.avx512.mask.pmull.w.512
+ //CHECK: mul <32 x i16> %{{.*}}, %{{.*}}
+ //CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_mask_mullo_epi16(__W, __U, __A, __B);
}
__m512i test_mm512_maskz_mullo_epi16 (__mmask32 __U, __m512i __A, __m512i __B) {
//CHECK-LABEL: @test_mm512_maskz_mullo_epi16
- //CHECK: @llvm.x86.avx512.mask.pmull.w.512
+ //CHECK: mul <32 x i16> %{{.*}}, %{{.*}}
+ //CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_maskz_mullo_epi16(__U, __A, __B);
}
@@ -652,137 +660,179 @@ __m512i test_mm512_maskz_avg_epu16(__mmask32 __U, __m512i __A, __m512i __B) {
}
__m512i test_mm512_max_epi8(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_max_epi8
- // CHECK: @llvm.x86.avx512.mask.pmaxs.b.512
+ // CHECK: [[CMP:%.*]] = icmp sgt <64 x i8> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <64 x i1> [[CMP]], <64 x i8> [[X]], <64 x i8> [[Y]]
return _mm512_max_epi8(__A,__B);
}
__m512i test_mm512_maskz_max_epi8(__mmask64 __M, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_max_epi8
- // CHECK: @llvm.x86.avx512.mask.pmaxs.b.512
+ // CHECK: [[CMP:%.*]] = icmp sgt <64 x i8> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <64 x i1> [[CMP]], <64 x i8> [[X]], <64 x i8> [[Y]]
+ // CHECK: select <64 x i1> {{.*}}, <64 x i8> [[RES]], <64 x i8> {{.*}}
return _mm512_maskz_max_epi8(__M,__A,__B);
}
__m512i test_mm512_mask_max_epi8(__m512i __W, __mmask64 __M, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_max_epi8
- // CHECK: @llvm.x86.avx512.mask.pmaxs.b.512
+ // CHECK: [[CMP:%.*]] = icmp sgt <64 x i8> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <64 x i1> [[CMP]], <64 x i8> [[X]], <64 x i8> [[Y]]
+ // CHECK: select <64 x i1> {{.*}}, <64 x i8> [[RES]], <64 x i8> {{.*}}
return _mm512_mask_max_epi8(__W,__M,__A,__B);
}
__m512i test_mm512_max_epi16(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_max_epi16
- // CHECK: @llvm.x86.avx512.mask.pmaxs.w.512
+ // CHECK: [[CMP:%.*]] = icmp sgt <32 x i16> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <32 x i1> [[CMP]], <32 x i16> [[X]], <32 x i16> [[Y]]
return _mm512_max_epi16(__A,__B);
}
__m512i test_mm512_maskz_max_epi16(__mmask32 __M, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_max_epi16
- // CHECK: @llvm.x86.avx512.mask.pmaxs.w.512
+ // CHECK: [[CMP:%.*]] = icmp sgt <32 x i16> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <32 x i1> [[CMP]], <32 x i16> [[X]], <32 x i16> [[Y]]
+ // CHECK: select <32 x i1> {{.*}}, <32 x i16> [[RES]], <32 x i16> {{.*}}
return _mm512_maskz_max_epi16(__M,__A,__B);
}
__m512i test_mm512_mask_max_epi16(__m512i __W, __mmask32 __M, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_max_epi16
- // CHECK: @llvm.x86.avx512.mask.pmaxs.w.512
+ // CHECK: [[CMP:%.*]] = icmp sgt <32 x i16> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <32 x i1> [[CMP]], <32 x i16> [[X]], <32 x i16> [[Y]]
+ // CHECK: select <32 x i1> {{.*}}, <32 x i16> [[RES]], <32 x i16> {{.*}}
return _mm512_mask_max_epi16(__W,__M,__A,__B);
}
__m512i test_mm512_max_epu8(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_max_epu8
- // CHECK: @llvm.x86.avx512.mask.pmaxu.b.512
+ // CHECK: [[CMP:%.*]] = icmp ugt <64 x i8> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <64 x i1> [[CMP]], <64 x i8> [[X]], <64 x i8> [[Y]]
return _mm512_max_epu8(__A,__B);
}
__m512i test_mm512_maskz_max_epu8(__mmask64 __M, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_max_epu8
- // CHECK: @llvm.x86.avx512.mask.pmaxu.b.512
+ // CHECK: [[CMP:%.*]] = icmp ugt <64 x i8> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <64 x i1> [[CMP]], <64 x i8> [[X]], <64 x i8> [[Y]]
+ // CHECK: select <64 x i1> {{.*}}, <64 x i8> [[RES]], <64 x i8> {{.*}}
return _mm512_maskz_max_epu8(__M,__A,__B);
}
__m512i test_mm512_mask_max_epu8(__m512i __W, __mmask64 __M, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_max_epu8
- // CHECK: @llvm.x86.avx512.mask.pmaxu.b.512
+ // CHECK: [[CMP:%.*]] = icmp ugt <64 x i8> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <64 x i1> [[CMP]], <64 x i8> [[X]], <64 x i8> [[Y]]
+ // CHECK: select <64 x i1> {{.*}}, <64 x i8> [[RES]], <64 x i8> {{.*}}
return _mm512_mask_max_epu8(__W,__M,__A,__B);
}
__m512i test_mm512_max_epu16(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_max_epu16
- // CHECK: @llvm.x86.avx512.mask.pmaxu.w.512
+ // CHECK: [[CMP:%.*]] = icmp ugt <32 x i16> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <32 x i1> [[CMP]], <32 x i16> [[X]], <32 x i16> [[Y]]
return _mm512_max_epu16(__A,__B);
}
__m512i test_mm512_maskz_max_epu16(__mmask32 __M, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_max_epu16
- // CHECK: @llvm.x86.avx512.mask.pmaxu.w.512
+ // CHECK: [[CMP:%.*]] = icmp ugt <32 x i16> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <32 x i1> [[CMP]], <32 x i16> [[X]], <32 x i16> [[Y]]
+ // CHECK: select <32 x i1> {{.*}}, <32 x i16> [[RES]], <32 x i16> {{.*}}
return _mm512_maskz_max_epu16(__M,__A,__B);
}
__m512i test_mm512_mask_max_epu16(__m512i __W, __mmask32 __M, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_max_epu16
- // CHECK: @llvm.x86.avx512.mask.pmaxu.w.512
+ // CHECK: [[CMP:%.*]] = icmp ugt <32 x i16> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <32 x i1> [[CMP]], <32 x i16> [[X]], <32 x i16> [[Y]]
+ // CHECK: select <32 x i1> {{.*}}, <32 x i16> [[RES]], <32 x i16> {{.*}}
return _mm512_mask_max_epu16(__W,__M,__A,__B);
}
__m512i test_mm512_min_epi8(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_min_epi8
- // CHECK: @llvm.x86.avx512.mask.pmins.b.512
+ // CHECK: [[CMP:%.*]] = icmp slt <64 x i8> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <64 x i1> [[CMP]], <64 x i8> [[X]], <64 x i8> [[Y]]
return _mm512_min_epi8(__A,__B);
}
__m512i test_mm512_maskz_min_epi8(__mmask64 __M, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_min_epi8
- // CHECK: @llvm.x86.avx512.mask.pmins.b.512
+ // CHECK: [[CMP:%.*]] = icmp slt <64 x i8> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <64 x i1> [[CMP]], <64 x i8> [[X]], <64 x i8> [[Y]]
+ // CHECK: select <64 x i1> {{.*}}, <64 x i8> [[RES]], <64 x i8> {{.*}}
return _mm512_maskz_min_epi8(__M,__A,__B);
}
__m512i test_mm512_mask_min_epi8(__m512i __W, __mmask64 __M, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_min_epi8
- // CHECK: @llvm.x86.avx512.mask.pmins.b.512
+ // CHECK: [[CMP:%.*]] = icmp slt <64 x i8> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <64 x i1> [[CMP]], <64 x i8> [[X]], <64 x i8> [[Y]]
+ // CHECK: select <64 x i1> {{.*}}, <64 x i8> [[RES]], <64 x i8> {{.*}}
return _mm512_mask_min_epi8(__W,__M,__A,__B);
}
__m512i test_mm512_min_epi16(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_min_epi16
- // CHECK: @llvm.x86.avx512.mask.pmins.w.512
+ // CHECK: [[CMP:%.*]] = icmp slt <32 x i16> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <32 x i1> [[CMP]], <32 x i16> [[X]], <32 x i16> [[Y]]
return _mm512_min_epi16(__A,__B);
}
__m512i test_mm512_maskz_min_epi16(__mmask32 __M, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_min_epi16
- // CHECK: @llvm.x86.avx512.mask.pmins.w.512
+ // CHECK: [[CMP:%.*]] = icmp slt <32 x i16> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <32 x i1> [[CMP]], <32 x i16> [[X]], <32 x i16> [[Y]]
+ // CHECK: select <32 x i1> {{.*}}, <32 x i16> [[RES]], <32 x i16> {{.*}}
return _mm512_maskz_min_epi16(__M,__A,__B);
}
__m512i test_mm512_mask_min_epi16(__m512i __W, __mmask32 __M, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_min_epi16
- // CHECK: @llvm.x86.avx512.mask.pmins.w.512
+ // CHECK: [[CMP:%.*]] = icmp slt <32 x i16> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <32 x i1> [[CMP]], <32 x i16> [[X]], <32 x i16> [[Y]]
+ // CHECK: select <32 x i1> {{.*}}, <32 x i16> [[RES]], <32 x i16> {{.*}}
return _mm512_mask_min_epi16(__W,__M,__A,__B);
}
__m512i test_mm512_min_epu8(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_min_epu8
- // CHECK: @llvm.x86.avx512.mask.pminu.b.512
+ // CHECK: [[CMP:%.*]] = icmp ult <64 x i8> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <64 x i1> [[CMP]], <64 x i8> [[X]], <64 x i8> [[Y]]
return _mm512_min_epu8(__A,__B);
}
__m512i test_mm512_maskz_min_epu8(__mmask64 __M, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_min_epu8
- // CHECK: @llvm.x86.avx512.mask.pminu.b.512
+ // CHECK: [[CMP:%.*]] = icmp ult <64 x i8> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <64 x i1> [[CMP]], <64 x i8> [[X]], <64 x i8> [[Y]]
+ // CHECK: select <64 x i1> {{.*}}, <64 x i8> [[RES]], <64 x i8> {{.*}}
return _mm512_maskz_min_epu8(__M,__A,__B);
}
__m512i test_mm512_mask_min_epu8(__m512i __W, __mmask64 __M, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_min_epu8
- // CHECK: @llvm.x86.avx512.mask.pminu.b.512
+ // CHECK: [[CMP:%.*]] = icmp ult <64 x i8> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <64 x i1> [[CMP]], <64 x i8> [[X]], <64 x i8> [[Y]]
+ // CHECK: select <64 x i1> {{.*}}, <64 x i8> [[RES]], <64 x i8> {{.*}}
return _mm512_mask_min_epu8(__W,__M,__A,__B);
}
__m512i test_mm512_min_epu16(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_min_epu16
- // CHECK: @llvm.x86.avx512.mask.pminu.w.512
+ // CHECK: [[CMP:%.*]] = icmp ult <32 x i16> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <32 x i1> [[CMP]], <32 x i16> [[X]], <32 x i16> [[Y]]
return _mm512_min_epu16(__A,__B);
}
__m512i test_mm512_maskz_min_epu16(__mmask32 __M, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_min_epu16
- // CHECK: @llvm.x86.avx512.mask.pminu.w.512
+ // CHECK: [[CMP:%.*]] = icmp ult <32 x i16> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <32 x i1> [[CMP]], <32 x i16> [[X]], <32 x i16> [[Y]]
+ // CHECK: select <32 x i1> {{.*}}, <32 x i16> [[RES]], <32 x i16> {{.*}}
return _mm512_maskz_min_epu16(__M,__A,__B);
}
__m512i test_mm512_mask_min_epu16(__m512i __W, __mmask32 __M, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_min_epu16
- // CHECK: @llvm.x86.avx512.mask.pminu.w.512
+ // CHECK: [[CMP:%.*]] = icmp ult <32 x i16> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <32 x i1> [[CMP]], <32 x i16> [[X]], <32 x i16> [[Y]]
+ // CHECK: select <32 x i1> {{.*}}, <32 x i16> [[RES]], <32 x i16> {{.*}}
return _mm512_mask_min_epu16(__W,__M,__A,__B);
}
__m512i test_mm512_shuffle_epi8(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_shuffle_epi8
- // CHECK: @llvm.x86.avx512.mask.pshuf.b.512
+ // CHECK: @llvm.x86.avx512.pshuf.b.512
return _mm512_shuffle_epi8(__A,__B);
}
__m512i test_mm512_mask_shuffle_epi8(__m512i __W, __mmask64 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_shuffle_epi8
- // CHECK: @llvm.x86.avx512.mask.pshuf.b.512
+ // CHECK: @llvm.x86.avx512.pshuf.b.512
+ // CHECK: select <64 x i1> %{{.*}}, <64 x i8> %{{.*}}, <64 x i8> %{{.*}}
return _mm512_mask_shuffle_epi8(__W,__U,__A,__B);
}
__m512i test_mm512_maskz_shuffle_epi8(__mmask64 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_shuffle_epi8
- // CHECK: @llvm.x86.avx512.mask.pshuf.b.512
+ // CHECK: @llvm.x86.avx512.pshuf.b.512
+ // CHECK: select <64 x i1> %{{.*}}, <64 x i8> %{{.*}}, <64 x i8> %{{.*}}
return _mm512_maskz_shuffle_epi8(__U,__A,__B);
}
__m512i test_mm512_subs_epi8(__m512i __A, __m512i __B) {
@@ -1079,37 +1129,41 @@ __m512i test_mm512_maskz_unpacklo_epi16(__mmask32 __U, __m512i __A, __m512i __B)
__m512i test_mm512_cvtepi8_epi16(__m256i __A) {
// CHECK-LABEL: @test_mm512_cvtepi8_epi16
- // CHECK: @llvm.x86.avx512.mask.pmovsxb.w.512
+ // CHECK: sext <32 x i8> %{{.*}} to <32 x i16>
return _mm512_cvtepi8_epi16(__A);
}
__m512i test_mm512_mask_cvtepi8_epi16(__m512i __W, __mmask32 __U, __m256i __A) {
// CHECK-LABEL: @test_mm512_mask_cvtepi8_epi16
- // CHECK: @llvm.x86.avx512.mask.pmovsxb.w.512
+ // CHECK: sext <32 x i8> %{{.*}} to <32 x i16>
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_mask_cvtepi8_epi16(__W, __U, __A);
}
__m512i test_mm512_maskz_cvtepi8_epi16(__mmask32 __U, __m256i __A) {
// CHECK-LABEL: @test_mm512_maskz_cvtepi8_epi16
- // CHECK: @llvm.x86.avx512.mask.pmovsxb.w.512
+ // CHECK: sext <32 x i8> %{{.*}} to <32 x i16>
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_maskz_cvtepi8_epi16(__U, __A);
}
__m512i test_mm512_cvtepu8_epi16(__m256i __A) {
// CHECK-LABEL: @test_mm512_cvtepu8_epi16
- // CHECK: @llvm.x86.avx512.mask.pmovzxb.w.512
+ // CHECK: zext <32 x i8> %{{.*}} to <32 x i16>
return _mm512_cvtepu8_epi16(__A);
}
__m512i test_mm512_mask_cvtepu8_epi16(__m512i __W, __mmask32 __U, __m256i __A) {
// CHECK-LABEL: @test_mm512_mask_cvtepu8_epi16
- // CHECK: @llvm.x86.avx512.mask.pmovzxb.w.512
+ // CHECK: zext <32 x i8> %{{.*}} to <32 x i16>
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_mask_cvtepu8_epi16(__W, __U, __A);
}
__m512i test_mm512_maskz_cvtepu8_epi16(__mmask32 __U, __m256i __A) {
// CHECK-LABEL: @test_mm512_maskz_cvtepu8_epi16
- // CHECK: @llvm.x86.avx512.mask.pmovzxb.w.512
+ // CHECK: zext <32 x i8> %{{.*}} to <32 x i16>
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_maskz_cvtepu8_epi16(__U, __A);
}
@@ -1155,55 +1209,61 @@ __m512i test_mm512_maskz_shufflelo_epi16(__mmask32 __U, __m512i __A) {
__m512i test_mm512_sllv_epi16(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_sllv_epi16
- // CHECK: @llvm.x86.avx512.mask.psllv
+ // CHECK: @llvm.x86.avx512.psllv.w.512(
return _mm512_sllv_epi16(__A, __B);
}
__m512i test_mm512_mask_sllv_epi16(__m512i __W, __mmask32 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_sllv_epi16
- // CHECK: @llvm.x86.avx512.mask.psllv
+ // CHECK: @llvm.x86.avx512.psllv.w.512(
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_mask_sllv_epi16(__W, __U, __A, __B);
}
__m512i test_mm512_maskz_sllv_epi16(__mmask32 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_sllv_epi16
- // CHECK: @llvm.x86.avx512.mask.psllv
+ // CHECK: @llvm.x86.avx512.psllv.w.512(
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_maskz_sllv_epi16(__U, __A, __B);
}
__m512i test_mm512_sll_epi16(__m512i __A, __m128i __B) {
// CHECK-LABEL: @test_mm512_sll_epi16
- // CHECK: @llvm.x86.avx512.mask.psll.w.512
+ // CHECK: @llvm.x86.avx512.psll.w.512
return _mm512_sll_epi16(__A, __B);
}
__m512i test_mm512_mask_sll_epi16(__m512i __W, __mmask32 __U, __m512i __A, __m128i __B) {
// CHECK-LABEL: @test_mm512_mask_sll_epi16
- // CHECK: @llvm.x86.avx512.mask.psll.w.512
+ // CHECK: @llvm.x86.avx512.psll.w.512
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_mask_sll_epi16(__W, __U, __A, __B);
}
__m512i test_mm512_maskz_sll_epi16(__mmask32 __U, __m512i __A, __m128i __B) {
// CHECK-LABEL: @test_mm512_maskz_sll_epi16
- // CHECK: @llvm.x86.avx512.mask.psll.w.512
+ // CHECK: @llvm.x86.avx512.psll.w.512
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_maskz_sll_epi16(__U, __A, __B);
}
__m512i test_mm512_slli_epi16(__m512i __A) {
// CHECK-LABEL: @test_mm512_slli_epi16
- // CHECK: @llvm.x86.avx512.mask.psll.wi.512
+ // CHECK: @llvm.x86.avx512.pslli.w.512
return _mm512_slli_epi16(__A, 5);
}
__m512i test_mm512_mask_slli_epi16(__m512i __W, __mmask32 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_mask_slli_epi16
- // CHECK: @llvm.x86.avx512.mask.psll.wi.512
+ // CHECK: @llvm.x86.avx512.pslli.w.512
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_mask_slli_epi16(__W, __U, __A, 5);
}
__m512i test_mm512_maskz_slli_epi16(__mmask32 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_maskz_slli_epi16
- // CHECK: @llvm.x86.avx512.mask.psll.wi.512
+ // CHECK: @llvm.x86.avx512.pslli.w.512
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_maskz_slli_epi16(__U, __A, 5);
}
@@ -1215,109 +1275,121 @@ __m512i test_mm512_bslli_epi128(__m512i __A) {
__m512i test_mm512_srlv_epi16(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_srlv_epi16
- // CHECK: @llvm.x86.avx512.mask.psrlv
+ // CHECK: @llvm.x86.avx512.psrlv.w.512(
return _mm512_srlv_epi16(__A, __B);
}
__m512i test_mm512_mask_srlv_epi16(__m512i __W, __mmask32 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_srlv_epi16
- // CHECK: @llvm.x86.avx512.mask.psrlv
+ // CHECK: @llvm.x86.avx512.psrlv.w.512(
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_mask_srlv_epi16(__W, __U, __A, __B);
}
__m512i test_mm512_maskz_srlv_epi16(__mmask32 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_srlv_epi16
- // CHECK: @llvm.x86.avx512.mask.psrlv
+ // CHECK: @llvm.x86.avx512.psrlv.w.512(
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_maskz_srlv_epi16(__U, __A, __B);
}
__m512i test_mm512_srav_epi16(__m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_srav_epi16
- // CHECK: @llvm.x86.avx512.mask.psrav
+ // CHECK: @llvm.x86.avx512.psrav.w.512(
return _mm512_srav_epi16(__A, __B);
}
__m512i test_mm512_mask_srav_epi16(__m512i __W, __mmask32 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_srav_epi16
- // CHECK: @llvm.x86.avx512.mask.psrav
+ // CHECK: @llvm.x86.avx512.psrav.w.512(
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_mask_srav_epi16(__W, __U, __A, __B);
}
__m512i test_mm512_maskz_srav_epi16(__mmask32 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_srav_epi16
- // CHECK: @llvm.x86.avx512.mask.psrav
+ // CHECK: @llvm.x86.avx512.psrav.w.512(
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_maskz_srav_epi16(__U, __A, __B);
}
__m512i test_mm512_sra_epi16(__m512i __A, __m128i __B) {
// CHECK-LABEL: @test_mm512_sra_epi16
- // CHECK: @llvm.x86.avx512.mask.psra.w.512
+ // CHECK: @llvm.x86.avx512.psra.w.512
return _mm512_sra_epi16(__A, __B);
}
__m512i test_mm512_mask_sra_epi16(__m512i __W, __mmask32 __U, __m512i __A, __m128i __B) {
// CHECK-LABEL: @test_mm512_mask_sra_epi16
- // CHECK: @llvm.x86.avx512.mask.psra.w.512
+ // CHECK: @llvm.x86.avx512.psra.w.512
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_mask_sra_epi16(__W, __U, __A, __B);
}
__m512i test_mm512_maskz_sra_epi16(__mmask32 __U, __m512i __A, __m128i __B) {
// CHECK-LABEL: @test_mm512_maskz_sra_epi16
- // CHECK: @llvm.x86.avx512.mask.psra.w.512
+ // CHECK: @llvm.x86.avx512.psra.w.512
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_maskz_sra_epi16(__U, __A, __B);
}
__m512i test_mm512_srai_epi16(__m512i __A) {
// CHECK-LABEL: @test_mm512_srai_epi16
- // CHECK: @llvm.x86.avx512.mask.psra.wi.512
+ // CHECK: @llvm.x86.avx512.psrai.w.512
return _mm512_srai_epi16(__A, 5);
}
__m512i test_mm512_mask_srai_epi16(__m512i __W, __mmask32 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_mask_srai_epi16
- // CHECK: @llvm.x86.avx512.mask.psra.wi.512
+ // CHECK: @llvm.x86.avx512.psrai.w.512
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_mask_srai_epi16(__W, __U, __A, 5);
}
__m512i test_mm512_maskz_srai_epi16(__mmask32 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_maskz_srai_epi16
- // CHECK: @llvm.x86.avx512.mask.psra.wi.512
+ // CHECK: @llvm.x86.avx512.psrai.w.512
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_maskz_srai_epi16(__U, __A, 5);
}
__m512i test_mm512_srl_epi16(__m512i __A, __m128i __B) {
// CHECK-LABEL: @test_mm512_srl_epi16
- // CHECK: @llvm.x86.avx512.mask.psrl.w.512
+ // CHECK: @llvm.x86.avx512.psrl.w.512
return _mm512_srl_epi16(__A, __B);
}
__m512i test_mm512_mask_srl_epi16(__m512i __W, __mmask32 __U, __m512i __A, __m128i __B) {
// CHECK-LABEL: @test_mm512_mask_srl_epi16
- // CHECK: @llvm.x86.avx512.mask.psrl.w.512
+ // CHECK: @llvm.x86.avx512.psrl.w.512
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_mask_srl_epi16(__W, __U, __A, __B);
}
__m512i test_mm512_maskz_srl_epi16(__mmask32 __U, __m512i __A, __m128i __B) {
// CHECK-LABEL: @test_mm512_maskz_srl_epi16
- // CHECK: @llvm.x86.avx512.mask.psrl.w.512
+ // CHECK: @llvm.x86.avx512.psrl.w.512
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_maskz_srl_epi16(__U, __A, __B);
}
__m512i test_mm512_srli_epi16(__m512i __A) {
// CHECK-LABEL: @test_mm512_srli_epi16
- // CHECK: @llvm.x86.avx512.mask.psrl.wi.512
+ // CHECK: @llvm.x86.avx512.psrli.w.512
return _mm512_srli_epi16(__A, 5);
}
__m512i test_mm512_mask_srli_epi16(__m512i __W, __mmask32 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_mask_srli_epi16
- // CHECK: @llvm.x86.avx512.mask.psrl.wi.512
+ // CHECK: @llvm.x86.avx512.psrli.w.512
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_mask_srli_epi16(__W, __U, __A, 5);
}
__m512i test_mm512_maskz_srli_epi16(__mmask32 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_maskz_srli_epi16
- // CHECK: @llvm.x86.avx512.mask.psrl.wi.512
+ // CHECK: @llvm.x86.avx512.psrli.w.512
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i16> %{{.*}}, <32 x i16> %{{.*}}
return _mm512_maskz_srli_epi16(__U, __A, 5);
}
diff --git a/test/CodeGen/avx512cdintrin.c b/test/CodeGen/avx512cdintrin.c
index 415a82c2c191..a28601895be1 100644
--- a/test/CodeGen/avx512cdintrin.c
+++ b/test/CodeGen/avx512cdintrin.c
@@ -1,7 +1,5 @@
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +avx512cd -emit-llvm -o - -Werror | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +avx512cd -emit-llvm -o - -Wall -Werror | FileCheck %s
-// Don't include mm_malloc.h, it's system specific.
-#define __MM_MALLOC_H
#include <immintrin.h>
diff --git a/test/CodeGen/avx512dq-builtins.c b/test/CodeGen/avx512dq-builtins.c
index 59a7cad7e3d1..f57433a3616b 100644
--- a/test/CodeGen/avx512dq-builtins.c
+++ b/test/CodeGen/avx512dq-builtins.c
@@ -1,7 +1,5 @@
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +avx512dq -emit-llvm -o - -Werror | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +avx512dq -emit-llvm -o - -Wall -Werror | FileCheck %s
-// Don't include mm_malloc.h, it's system specific.
-#define __MM_MALLOC_H
#include <immintrin.h>
@@ -13,13 +11,15 @@ __m512i test_mm512_mullo_epi64 (__m512i __A, __m512i __B) {
__m512i test_mm512_mask_mullo_epi64 (__m512i __W, __mmask8 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_mask_mullo_epi64
- // CHECK: @llvm.x86.avx512.mask.pmull.q.512
+ // CHECK: mul <8 x i64> %{{.*}}, %{{.*}}
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return (__m512i) _mm512_mask_mullo_epi64(__W, __U, __A, __B);
}
__m512i test_mm512_maskz_mullo_epi64 (__mmask8 __U, __m512i __A, __m512i __B) {
// CHECK-LABEL: @test_mm512_maskz_mullo_epi64
- // CHECK: @llvm.x86.avx512.mask.pmull.q.512
+ // CHECK: mul <8 x i64> %{{.*}}, %{{.*}}
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return (__m512i) _mm512_maskz_mullo_epi64(__U, __A, __B);
}
@@ -31,13 +31,17 @@ __m512d test_mm512_xor_pd (__m512d __A, __m512d __B) {
__m512d test_mm512_mask_xor_pd (__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) {
// CHECK-LABEL: @test_mm512_mask_xor_pd
- // CHECK: @llvm.x86.avx512.mask.xor.pd.512
+ // CHECK: xor <8 x i64>
+ // CHECK: %[[MASK:.*]] = bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %[[MASK]], <8 x double> %{{.*}}, <8 x double> %{{.*}}
return (__m512d) _mm512_mask_xor_pd(__W, __U, __A, __B);
}
__m512d test_mm512_maskz_xor_pd (__mmask8 __U, __m512d __A, __m512d __B) {
// CHECK-LABEL: @test_mm512_maskz_xor_pd
- // CHECK: @llvm.x86.avx512.mask.xor.pd.512
+ // CHECK: xor <8 x i64>
+ // CHECK: %[[MASK:.*]] = bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %[[MASK]], <8 x double> %{{.*}}, <8 x double> %{{.*}}
return (__m512d) _mm512_maskz_xor_pd(__U, __A, __B);
}
@@ -49,13 +53,17 @@ __m512 test_mm512_xor_ps (__m512 __A, __m512 __B) {
__m512 test_mm512_mask_xor_ps (__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) {
// CHECK-LABEL: @test_mm512_mask_xor_ps
- // CHECK: @llvm.x86.avx512.mask.xor.ps.512
+ // CHECK: xor <16 x i32>
+ // CHECK: %[[MASK:.*]] = bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: select <16 x i1> %[[MASK]], <16 x float> %{{.*}}, <16 x float> %{{.*}}
return (__m512) _mm512_mask_xor_ps(__W, __U, __A, __B);
}
__m512 test_mm512_maskz_xor_ps (__mmask16 __U, __m512 __A, __m512 __B) {
// CHECK-LABEL: @test_mm512_maskz_xor_ps
- // CHECK: @llvm.x86.avx512.mask.xor.ps.512
+ // CHECK: xor <16 x i32>
+ // CHECK: %[[MASK:.*]] = bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: select <16 x i1> %[[MASK]], <16 x float> %{{.*}}, <16 x float> %{{.*}}
return (__m512) _mm512_maskz_xor_ps(__U, __A, __B);
}
@@ -67,13 +75,17 @@ __m512d test_mm512_or_pd (__m512d __A, __m512d __B) {
__m512d test_mm512_mask_or_pd (__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) {
// CHECK-LABEL: @test_mm512_mask_or_pd
- // CHECK: @llvm.x86.avx512.mask.or.pd.512
+ // CHECK: or <8 x i64>
+ // CHECK: %[[MASK:.*]] = bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %[[MASK]], <8 x double> %{{.*}}, <8 x double> %{{.*}}
return (__m512d) _mm512_mask_or_pd(__W, __U, __A, __B);
}
__m512d test_mm512_maskz_or_pd (__mmask8 __U, __m512d __A, __m512d __B) {
// CHECK-LABEL: @test_mm512_maskz_or_pd
- // CHECK: @llvm.x86.avx512.mask.or.pd.512
+ // CHECK: or <8 x i64>
+ // CHECK: %[[MASK:.*]] = bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %[[MASK]], <8 x double> %{{.*}}, <8 x double> %{{.*}}
return (__m512d) _mm512_maskz_or_pd(__U, __A, __B);
}
@@ -85,13 +97,17 @@ __m512 test_mm512_or_ps (__m512 __A, __m512 __B) {
__m512 test_mm512_mask_or_ps (__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) {
// CHECK-LABEL: @test_mm512_mask_or_ps
- // CHECK: @llvm.x86.avx512.mask.or.ps.512
+ // CHECK: or <16 x i32>
+ // CHECK: %[[MASK:.*]] = bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: select <16 x i1> %[[MASK]], <16 x float> %{{.*}}, <16 x float> %{{.*}}
return (__m512) _mm512_mask_or_ps(__W, __U, __A, __B);
}
__m512 test_mm512_maskz_or_ps (__mmask16 __U, __m512 __A, __m512 __B) {
// CHECK-LABEL: @test_mm512_maskz_or_ps
- // CHECK: @llvm.x86.avx512.mask.or.ps.512
+ // CHECK: or <16 x i32>
+ // CHECK: %[[MASK:.*]] = bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: select <16 x i1> %[[MASK]], <16 x float> %{{.*}}, <16 x float> %{{.*}}
return (__m512) _mm512_maskz_or_ps(__U, __A, __B);
}
@@ -103,13 +119,17 @@ __m512d test_mm512_and_pd (__m512d __A, __m512d __B) {
__m512d test_mm512_mask_and_pd (__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) {
// CHECK-LABEL: @test_mm512_mask_and_pd
- // CHECK: @llvm.x86.avx512.mask.and.pd.512
+ // CHECK: and <8 x i64>
+ // CHECK: %[[MASK:.*]] = bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %[[MASK]], <8 x double> %{{.*}}, <8 x double> %{{.*}}
return (__m512d) _mm512_mask_and_pd(__W, __U, __A, __B);
}
__m512d test_mm512_maskz_and_pd (__mmask8 __U, __m512d __A, __m512d __B) {
// CHECK-LABEL: @test_mm512_maskz_and_pd
- // CHECK: @llvm.x86.avx512.mask.and.pd.512
+ // CHECK: and <8 x i64>
+ // CHECK: %[[MASK:.*]] = bitcast i8 %{{.*}} to <8 x i1>
+ // CHECK: select <8 x i1> %[[MASK]], <8 x double> %{{.*}}, <8 x double> %{{.*}}
return (__m512d) _mm512_maskz_and_pd(__U, __A, __B);
}
@@ -121,49 +141,63 @@ __m512 test_mm512_and_ps (__m512 __A, __m512 __B) {
__m512 test_mm512_mask_and_ps (__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) {
// CHECK-LABEL: @test_mm512_mask_and_ps
- // CHECK: @llvm.x86.avx512.mask.and.ps.512
+ // CHECK: and <16 x i32>
+ // CHECK: %[[MASK:.*]] = bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: select <16 x i1> %[[MASK]], <16 x float> %{{.*}}, <16 x float> %{{.*}}
return (__m512) _mm512_mask_and_ps(__W, __U, __A, __B);
}
__m512 test_mm512_maskz_and_ps (__mmask16 __U, __m512 __A, __m512 __B) {
// CHECK-LABEL: @test_mm512_maskz_and_ps
- // CHECK: @llvm.x86.avx512.mask.and.ps.512
+ // CHECK: and <16 x i32>
+ // CHECK: %[[MASK:.*]] = bitcast i16 %{{.*}} to <16 x i1>
+ // CHECK: select <16 x i1> %[[MASK]], <16 x float> %{{.*}}, <16 x float> %{{.*}}
return (__m512) _mm512_maskz_and_ps(__U, __A, __B);
}
__m512d test_mm512_andnot_pd (__m512d __A, __m512d __B) {
// CHECK-LABEL: @test_mm512_andnot_pd
- // CHECK: @llvm.x86.avx512.mask.andn.pd.512
+ // CHECK: xor <8 x i64> %{{.*}}, <i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 -1>
+ // CHECK: and <8 x i64>
return (__m512d) _mm512_andnot_pd(__A, __B);
}
__m512d test_mm512_mask_andnot_pd (__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) {
// CHECK-LABEL: @test_mm512_mask_andnot_pd
- // CHECK: @llvm.x86.avx512.mask.andn.pd.512
+ // CHECK: xor <8 x i64> %{{.*}}, <i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 -1>
+ // CHECK: and <8 x i64> %{{.*}}, %{{.*}}
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return (__m512d) _mm512_mask_andnot_pd(__W, __U, __A, __B);
}
__m512d test_mm512_maskz_andnot_pd (__mmask8 __U, __m512d __A, __m512d __B) {
// CHECK-LABEL: @test_mm512_maskz_andnot_pd
- // CHECK: @llvm.x86.avx512.mask.andn.pd.512
+ // CHECK: xor <8 x i64> %{{.*}}, <i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 -1, i64 -1>
+ // CHECK: and <8 x i64> %{{.*}}, %{{.*}}
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return (__m512d) _mm512_maskz_andnot_pd(__U, __A, __B);
}
__m512 test_mm512_andnot_ps (__m512 __A, __m512 __B) {
// CHECK-LABEL: @test_mm512_andnot_ps
- // CHECK: @llvm.x86.avx512.mask.andn.ps.512
+ // CHECK: xor <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: and <16 x i32>
return (__m512) _mm512_andnot_ps(__A, __B);
}
__m512 test_mm512_mask_andnot_ps (__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) {
// CHECK-LABEL: @test_mm512_mask_andnot_ps
- // CHECK: @llvm.x86.avx512.mask.andn.ps.512
+ // CHECK: xor <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: and <16 x i32> %{{.*}}, %{{.*}}
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return (__m512) _mm512_mask_andnot_ps(__W, __U, __A, __B);
}
__m512 test_mm512_maskz_andnot_ps (__mmask16 __U, __m512 __A, __m512 __B) {
// CHECK-LABEL: @test_mm512_maskz_andnot_ps
- // CHECK: @llvm.x86.avx512.mask.andn.ps.512
+ // CHECK: xor <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: and <16 x i32> %{{.*}}, %{{.*}}
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return (__m512) _mm512_maskz_andnot_ps(__U, __A, __B);
}
@@ -188,19 +222,19 @@ __m512i test_mm512_maskz_cvtpd_epi64(__mmask8 __U, __m512d __A) {
__m512i test_mm512_cvt_roundpd_epi64(__m512d __A) {
// CHECK-LABEL: @test_mm512_cvt_roundpd_epi64
// CHECK: @llvm.x86.avx512.mask.cvtpd2qq.512
- return _mm512_cvt_roundpd_epi64(__A, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_cvt_roundpd_epi64(__A, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512i test_mm512_mask_cvt_roundpd_epi64(__m512i __W, __mmask8 __U, __m512d __A) {
// CHECK-LABEL: @test_mm512_mask_cvt_roundpd_epi64
// CHECK: @llvm.x86.avx512.mask.cvtpd2qq.512
- return _mm512_mask_cvt_roundpd_epi64(__W, __U, __A, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_mask_cvt_roundpd_epi64(__W, __U, __A, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512i test_mm512_maskz_cvt_roundpd_epi64(__mmask8 __U, __m512d __A) {
// CHECK-LABEL: @test_mm512_maskz_cvt_roundpd_epi64
// CHECK: @llvm.x86.avx512.mask.cvtpd2qq.512
- return _mm512_maskz_cvt_roundpd_epi64(__U, __A, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_maskz_cvt_roundpd_epi64(__U, __A, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512i test_mm512_cvtpd_epu64(__m512d __A) {
@@ -224,19 +258,19 @@ __m512i test_mm512_maskz_cvtpd_epu64(__mmask8 __U, __m512d __A) {
__m512i test_mm512_cvt_roundpd_epu64(__m512d __A) {
// CHECK-LABEL: @test_mm512_cvt_roundpd_epu64
// CHECK: @llvm.x86.avx512.mask.cvtpd2uqq.512
- return _mm512_cvt_roundpd_epu64(__A, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_cvt_roundpd_epu64(__A, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512i test_mm512_mask_cvt_roundpd_epu64(__m512i __W, __mmask8 __U, __m512d __A) {
// CHECK-LABEL: @test_mm512_mask_cvt_roundpd_epu64
// CHECK: @llvm.x86.avx512.mask.cvtpd2uqq.512
- return _mm512_mask_cvt_roundpd_epu64(__W, __U, __A, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_mask_cvt_roundpd_epu64(__W, __U, __A, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512i test_mm512_maskz_cvt_roundpd_epu64(__mmask8 __U, __m512d __A) {
// CHECK-LABEL: @test_mm512_maskz_cvt_roundpd_epu64
// CHECK: @llvm.x86.avx512.mask.cvtpd2uqq.512
- return _mm512_maskz_cvt_roundpd_epu64(__U, __A, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_maskz_cvt_roundpd_epu64(__U, __A, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512i test_mm512_cvtps_epi64(__m256 __A) {
@@ -260,19 +294,19 @@ __m512i test_mm512_maskz_cvtps_epi64(__mmask8 __U, __m256 __A) {
__m512i test_mm512_cvt_roundps_epi64(__m256 __A) {
// CHECK-LABEL: @test_mm512_cvt_roundps_epi64
// CHECK: @llvm.x86.avx512.mask.cvtps2qq.512
- return _mm512_cvt_roundps_epi64(__A, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_cvt_roundps_epi64(__A, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512i test_mm512_mask_cvt_roundps_epi64(__m512i __W, __mmask8 __U, __m256 __A) {
// CHECK-LABEL: @test_mm512_mask_cvt_roundps_epi64
// CHECK: @llvm.x86.avx512.mask.cvtps2qq.512
- return _mm512_mask_cvt_roundps_epi64(__W, __U, __A, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_mask_cvt_roundps_epi64(__W, __U, __A, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512i test_mm512_maskz_cvt_roundps_epi64(__mmask8 __U, __m256 __A) {
// CHECK-LABEL: @test_mm512_maskz_cvt_roundps_epi64
// CHECK: @llvm.x86.avx512.mask.cvtps2qq.512
- return _mm512_maskz_cvt_roundps_epi64(__U, __A, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_maskz_cvt_roundps_epi64(__U, __A, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512i test_mm512_cvtps_epu64(__m256 __A) {
@@ -296,19 +330,19 @@ __m512i test_mm512_maskz_cvtps_epu64(__mmask8 __U, __m256 __A) {
__m512i test_mm512_cvt_roundps_epu64(__m256 __A) {
// CHECK-LABEL: @test_mm512_cvt_roundps_epu64
// CHECK: @llvm.x86.avx512.mask.cvtps2uqq.512
- return _mm512_cvt_roundps_epu64(__A, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_cvt_roundps_epu64(__A, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512i test_mm512_mask_cvt_roundps_epu64(__m512i __W, __mmask8 __U, __m256 __A) {
// CHECK-LABEL: @test_mm512_mask_cvt_roundps_epu64
// CHECK: @llvm.x86.avx512.mask.cvtps2uqq.512
- return _mm512_mask_cvt_roundps_epu64(__W, __U, __A, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_mask_cvt_roundps_epu64(__W, __U, __A, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512i test_mm512_maskz_cvt_roundps_epu64(__mmask8 __U, __m256 __A) {
// CHECK-LABEL: @test_mm512_maskz_cvt_roundps_epu64
// CHECK: @llvm.x86.avx512.mask.cvtps2uqq.512
- return _mm512_maskz_cvt_roundps_epu64(__U, __A, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_maskz_cvt_roundps_epu64(__U, __A, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512d test_mm512_cvtepi64_pd(__m512i __A) {
@@ -332,19 +366,19 @@ __m512d test_mm512_maskz_cvtepi64_pd(__mmask8 __U, __m512i __A) {
__m512d test_mm512_cvt_roundepi64_pd(__m512i __A) {
// CHECK-LABEL: @test_mm512_cvt_roundepi64_pd
// CHECK: @llvm.x86.avx512.mask.cvtqq2pd.512
- return _mm512_cvt_roundepi64_pd(__A, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_cvt_roundepi64_pd(__A, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512d test_mm512_mask_cvt_roundepi64_pd(__m512d __W, __mmask8 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_mask_cvt_roundepi64_pd
// CHECK: @llvm.x86.avx512.mask.cvtqq2pd.512
- return _mm512_mask_cvt_roundepi64_pd(__W, __U, __A, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_mask_cvt_roundepi64_pd(__W, __U, __A, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512d test_mm512_maskz_cvt_roundepi64_pd(__mmask8 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_maskz_cvt_roundepi64_pd
// CHECK: @llvm.x86.avx512.mask.cvtqq2pd.512
- return _mm512_maskz_cvt_roundepi64_pd(__U, __A, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_maskz_cvt_roundepi64_pd(__U, __A, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m256 test_mm512_cvtepi64_ps(__m512i __A) {
@@ -368,19 +402,19 @@ __m256 test_mm512_maskz_cvtepi64_ps(__mmask8 __U, __m512i __A) {
__m256 test_mm512_cvt_roundepi64_ps(__m512i __A) {
// CHECK-LABEL: @test_mm512_cvt_roundepi64_ps
// CHECK: @llvm.x86.avx512.mask.cvtqq2ps.512
- return _mm512_cvt_roundepi64_ps(__A, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_cvt_roundepi64_ps(__A, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m256 test_mm512_mask_cvt_roundepi64_ps(__m256 __W, __mmask8 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_mask_cvt_roundepi64_ps
// CHECK: @llvm.x86.avx512.mask.cvtqq2ps.512
- return _mm512_mask_cvt_roundepi64_ps(__W, __U, __A, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_mask_cvt_roundepi64_ps(__W, __U, __A, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m256 test_mm512_maskz_cvt_roundepi64_ps(__mmask8 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_maskz_cvt_roundepi64_ps
// CHECK: @llvm.x86.avx512.mask.cvtqq2ps.512
- return _mm512_maskz_cvt_roundepi64_ps(__U, __A, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_maskz_cvt_roundepi64_ps(__U, __A, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512i test_mm512_cvttpd_epi64(__m512d __A) {
@@ -404,19 +438,19 @@ __m512i test_mm512_maskz_cvttpd_epi64(__mmask8 __U, __m512d __A) {
__m512i test_mm512_cvtt_roundpd_epi64(__m512d __A) {
// CHECK-LABEL: @test_mm512_cvtt_roundpd_epi64
// CHECK: @llvm.x86.avx512.mask.cvttpd2qq.512
- return _mm512_cvtt_roundpd_epi64(__A, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_cvtt_roundpd_epi64(__A, _MM_FROUND_CUR_DIRECTION);
}
__m512i test_mm512_mask_cvtt_roundpd_epi64(__m512i __W, __mmask8 __U, __m512d __A) {
// CHECK-LABEL: @test_mm512_mask_cvtt_roundpd_epi64
// CHECK: @llvm.x86.avx512.mask.cvttpd2qq.512
- return _mm512_mask_cvtt_roundpd_epi64(__W, __U, __A, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_mask_cvtt_roundpd_epi64(__W, __U, __A, _MM_FROUND_CUR_DIRECTION);
}
__m512i test_mm512_maskz_cvtt_roundpd_epi64(__mmask8 __U, __m512d __A) {
// CHECK-LABEL: @test_mm512_maskz_cvtt_roundpd_epi64
// CHECK: @llvm.x86.avx512.mask.cvttpd2qq.512
- return _mm512_maskz_cvtt_roundpd_epi64(__U, __A, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_maskz_cvtt_roundpd_epi64(__U, __A, _MM_FROUND_CUR_DIRECTION);
}
__m512i test_mm512_cvttpd_epu64(__m512d __A) {
@@ -440,19 +474,19 @@ __m512i test_mm512_maskz_cvttpd_epu64(__mmask8 __U, __m512d __A) {
__m512i test_mm512_cvtt_roundpd_epu64(__m512d __A) {
// CHECK-LABEL: @test_mm512_cvtt_roundpd_epu64
// CHECK: @llvm.x86.avx512.mask.cvttpd2uqq.512
- return _mm512_cvtt_roundpd_epu64(__A, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_cvtt_roundpd_epu64(__A, _MM_FROUND_CUR_DIRECTION);
}
__m512i test_mm512_mask_cvtt_roundpd_epu64(__m512i __W, __mmask8 __U, __m512d __A) {
// CHECK-LABEL: @test_mm512_mask_cvtt_roundpd_epu64
// CHECK: @llvm.x86.avx512.mask.cvttpd2uqq.512
- return _mm512_mask_cvtt_roundpd_epu64(__W, __U, __A, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_mask_cvtt_roundpd_epu64(__W, __U, __A, _MM_FROUND_CUR_DIRECTION);
}
__m512i test_mm512_maskz_cvtt_roundpd_epu64(__mmask8 __U, __m512d __A) {
// CHECK-LABEL: @test_mm512_maskz_cvtt_roundpd_epu64
// CHECK: @llvm.x86.avx512.mask.cvttpd2uqq.512
- return _mm512_maskz_cvtt_roundpd_epu64(__U, __A, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_maskz_cvtt_roundpd_epu64(__U, __A, _MM_FROUND_CUR_DIRECTION);
}
__m512i test_mm512_cvttps_epi64(__m256 __A) {
@@ -476,19 +510,19 @@ __m512i test_mm512_maskz_cvttps_epi64(__mmask8 __U, __m256 __A) {
__m512i test_mm512_cvtt_roundps_epi64(__m256 __A) {
// CHECK-LABEL: @test_mm512_cvtt_roundps_epi64
// CHECK: @llvm.x86.avx512.mask.cvttps2qq.512
- return _mm512_cvtt_roundps_epi64(__A, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_cvtt_roundps_epi64(__A, _MM_FROUND_CUR_DIRECTION);
}
__m512i test_mm512_mask_cvtt_roundps_epi64(__m512i __W, __mmask8 __U, __m256 __A) {
// CHECK-LABEL: @test_mm512_mask_cvtt_roundps_epi64
// CHECK: @llvm.x86.avx512.mask.cvttps2qq.512
- return _mm512_mask_cvtt_roundps_epi64(__W, __U, __A, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_mask_cvtt_roundps_epi64(__W, __U, __A, _MM_FROUND_CUR_DIRECTION);
}
__m512i test_mm512_maskz_cvtt_roundps_epi64(__mmask8 __U, __m256 __A) {
// CHECK-LABEL: @test_mm512_maskz_cvtt_roundps_epi64
// CHECK: @llvm.x86.avx512.mask.cvttps2qq.512
- return _mm512_maskz_cvtt_roundps_epi64(__U, __A, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_maskz_cvtt_roundps_epi64(__U, __A, _MM_FROUND_CUR_DIRECTION);
}
__m512i test_mm512_cvttps_epu64(__m256 __A) {
@@ -512,19 +546,19 @@ __m512i test_mm512_maskz_cvttps_epu64(__mmask8 __U, __m256 __A) {
__m512i test_mm512_cvtt_roundps_epu64(__m256 __A) {
// CHECK-LABEL: @test_mm512_cvtt_roundps_epu64
// CHECK: @llvm.x86.avx512.mask.cvttps2uqq.512
- return _mm512_cvtt_roundps_epu64(__A, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_cvtt_roundps_epu64(__A, _MM_FROUND_CUR_DIRECTION);
}
__m512i test_mm512_mask_cvtt_roundps_epu64(__m512i __W, __mmask8 __U, __m256 __A) {
// CHECK-LABEL: @test_mm512_mask_cvtt_roundps_epu64
// CHECK: @llvm.x86.avx512.mask.cvttps2uqq.512
- return _mm512_mask_cvtt_roundps_epu64(__W, __U, __A, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_mask_cvtt_roundps_epu64(__W, __U, __A, _MM_FROUND_CUR_DIRECTION);
}
__m512i test_mm512_maskz_cvtt_roundps_epu64(__mmask8 __U, __m256 __A) {
// CHECK-LABEL: @test_mm512_maskz_cvtt_roundps_epu64
// CHECK: @llvm.x86.avx512.mask.cvttps2uqq.512
- return _mm512_maskz_cvtt_roundps_epu64(__U, __A, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_maskz_cvtt_roundps_epu64(__U, __A, _MM_FROUND_CUR_DIRECTION);
}
__m512d test_mm512_cvtepu64_pd(__m512i __A) {
@@ -548,19 +582,19 @@ __m512d test_mm512_maskz_cvtepu64_pd(__mmask8 __U, __m512i __A) {
__m512d test_mm512_cvt_roundepu64_pd(__m512i __A) {
// CHECK-LABEL: @test_mm512_cvt_roundepu64_pd
// CHECK: @llvm.x86.avx512.mask.cvtuqq2pd.512
- return _mm512_cvt_roundepu64_pd(__A, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_cvt_roundepu64_pd(__A, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512d test_mm512_mask_cvt_roundepu64_pd(__m512d __W, __mmask8 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_mask_cvt_roundepu64_pd
// CHECK: @llvm.x86.avx512.mask.cvtuqq2pd.512
- return _mm512_mask_cvt_roundepu64_pd(__W, __U, __A, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_mask_cvt_roundepu64_pd(__W, __U, __A, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512d test_mm512_maskz_cvt_roundepu64_pd(__mmask8 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_maskz_cvt_roundepu64_pd
// CHECK: @llvm.x86.avx512.mask.cvtuqq2pd.512
- return _mm512_maskz_cvt_roundepu64_pd(__U, __A, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_maskz_cvt_roundepu64_pd(__U, __A, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m256 test_mm512_cvtepu64_ps(__m512i __A) {
@@ -584,19 +618,19 @@ __m256 test_mm512_maskz_cvtepu64_ps(__mmask8 __U, __m512i __A) {
__m256 test_mm512_cvt_roundepu64_ps(__m512i __A) {
// CHECK-LABEL: @test_mm512_cvt_roundepu64_ps
// CHECK: @llvm.x86.avx512.mask.cvtuqq2ps.512
- return _mm512_cvt_roundepu64_ps(__A, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_cvt_roundepu64_ps(__A, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m256 test_mm512_mask_cvt_roundepu64_ps(__m256 __W, __mmask8 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_mask_cvt_roundepu64_ps
// CHECK: @llvm.x86.avx512.mask.cvtuqq2ps.512
- return _mm512_mask_cvt_roundepu64_ps(__W, __U, __A, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_mask_cvt_roundepu64_ps(__W, __U, __A, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m256 test_mm512_maskz_cvt_roundepu64_ps(__mmask8 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_maskz_cvt_roundepu64_ps
// CHECK: @llvm.x86.avx512.mask.cvtuqq2ps.512
- return _mm512_maskz_cvt_roundepu64_ps(__U, __A, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_maskz_cvt_roundepu64_ps(__U, __A, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m512d test_mm512_range_pd(__m512d __A, __m512d __B) {
@@ -1020,145 +1054,161 @@ __m512i test_mm512_maskz_broadcast_i64x2(__mmask8 __M, __m128i __A) {
}
__m256 test_mm512_extractf32x8_ps(__m512 __A) {
// CHECK-LABEL: @test_mm512_extractf32x8_ps
- // CHECK: @llvm.x86.avx512.mask.vextractf32x8
+ // 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: @llvm.x86.avx512.mask.vextractf32x8
+ // 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: @llvm.x86.avx512.mask.vextractf32x8
+ // 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: @llvm.x86.avx512.mask.vextractf64x2
+ // 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: @llvm.x86.avx512.mask.vextractf64x2
+ // 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: @llvm.x86.avx512.mask.vextractf64x2
+ // 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: @llvm.x86.avx512.mask.vextracti32x8
+ // 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>
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: @llvm.x86.avx512.mask.vextracti32x8
+ // 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: 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: @llvm.x86.avx512.mask.vextracti32x8
+ // 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: 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: @llvm.x86.avx512.mask.vextracti64x2
+ // 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: @llvm.x86.avx512.mask.vextracti64x2
+ // 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: @llvm.x86.avx512.mask.vextracti64x2
+ // 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);
}
__m512 test_mm512_insertf32x8(__m512 __A, __m256 __B) {
// CHECK-LABEL: @test_mm512_insertf32x8
- // CHECK: @llvm.x86.avx512.mask.insertf32x8
+ // CHECK: shufflevector <16 x float> %{{.*}}, <16 x float> %{{.*}}, <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 20, i32 21, i32 22, i32 23>
return _mm512_insertf32x8(__A, __B, 1);
}
__m512 test_mm512_mask_insertf32x8(__m512 __W, __mmask16 __U, __m512 __A, __m256 __B) {
// CHECK-LABEL: @test_mm512_mask_insertf32x8
- // CHECK: @llvm.x86.avx512.mask.insertf32x8
+ // CHECK: shufflevector <16 x float> %{{.*}}, <16 x float> %{{.*}}, <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 20, i32 21, i32 22, i32 23>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_mask_insertf32x8(__W, __U, __A, __B, 1);
}
__m512 test_mm512_maskz_insertf32x8(__mmask16 __U, __m512 __A, __m256 __B) {
// CHECK-LABEL: @test_mm512_maskz_insertf32x8
- // CHECK: @llvm.x86.avx512.mask.insertf32x8
+ // CHECK: shufflevector <16 x float> %{{.*}}, <16 x float> %{{.*}}, <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 20, i32 21, i32 22, i32 23>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_maskz_insertf32x8(__U, __A, __B, 1);
}
__m512d test_mm512_insertf64x2(__m512d __A, __m128d __B) {
// CHECK-LABEL: @test_mm512_insertf64x2
- // CHECK: @llvm.x86.avx512.mask.insertf64x2
+ // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 8, i32 9>
return _mm512_insertf64x2(__A, __B, 3);
}
__m512d test_mm512_mask_insertf64x2(__m512d __W, __mmask8 __U, __m512d __A, __m128d __B) {
// CHECK-LABEL: @test_mm512_mask_insertf64x2
- // CHECK: @llvm.x86.avx512.mask.insertf64x2
+ // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 8, i32 9>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask_insertf64x2(__W, __U, __A, __B, 3);
}
__m512d test_mm512_maskz_insertf64x2(__mmask8 __U, __m512d __A, __m128d __B) {
// CHECK-LABEL: @test_mm512_maskz_insertf64x2
- // CHECK: @llvm.x86.avx512.mask.insertf64x2
+ // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 8, i32 9>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_maskz_insertf64x2(__U, __A, __B, 3);
}
__m512i test_mm512_inserti32x8(__m512i __A, __m256i __B) {
// CHECK-LABEL: @test_mm512_inserti32x8
- // CHECK: @llvm.x86.avx512.mask.inserti32x8
+ // 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 20, i32 21, i32 22, i32 23>
return _mm512_inserti32x8(__A, __B, 1);
}
__m512i test_mm512_mask_inserti32x8(__m512i __W, __mmask16 __U, __m512i __A, __m256i __B) {
// CHECK-LABEL: @test_mm512_mask_inserti32x8
- // CHECK: @llvm.x86.avx512.mask.inserti32x8
+ // 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 20, i32 21, i32 22, i32 23>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_mask_inserti32x8(__W, __U, __A, __B, 1);
}
__m512i test_mm512_maskz_inserti32x8(__mmask16 __U, __m512i __A, __m256i __B) {
// CHECK-LABEL: @test_mm512_maskz_inserti32x8
- // CHECK: @llvm.x86.avx512.mask.inserti32x8
+ // 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 20, i32 21, i32 22, i32 23>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_maskz_inserti32x8(__U, __A, __B, 1);
}
__m512i test_mm512_inserti64x2(__m512i __A, __m128i __B) {
// CHECK-LABEL: @test_mm512_inserti64x2
- // CHECK: @llvm.x86.avx512.mask.inserti64x2
+ // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> %{{.*}}, <8 x i32> <i32 0, i32 1, i32 8, i32 9, i32 4, i32 5, i32 6, i32 7>
return _mm512_inserti64x2(__A, __B, 1);
}
__m512i test_mm512_mask_inserti64x2(__m512i __W, __mmask8 __U, __m512i __A, __m128i __B) {
// CHECK-LABEL: @test_mm512_mask_inserti64x2
- // CHECK: @llvm.x86.avx512.mask.inserti64x2
+ // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> %{{.*}}, <8 x i32> <i32 0, i32 1, i32 8, i32 9, i32 4, i32 5, i32 6, i32 7>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_mask_inserti64x2(__W, __U, __A, __B, 1);
}
__m512i test_mm512_maskz_inserti64x2(__mmask8 __U, __m512i __A, __m128i __B) {
// CHECK-LABEL: @test_mm512_maskz_inserti64x2
- // CHECK: @llvm.x86.avx512.mask.inserti64x2
+ // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> %{{.*}}, <8 x i32> <i32 0, i32 1, i32 8, i32 9, i32 4, i32 5, i32 6, i32 7>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_maskz_inserti64x2(__U, __A, __B, 1);
}
__mmask8 test_mm512_mask_fpclass_pd_mask(__mmask8 __U, __m512d __A) {
diff --git a/test/CodeGen/avx512er-builtins.c b/test/CodeGen/avx512er-builtins.c
index 7c6b050c8ae5..084e0f53825c 100644
--- a/test/CodeGen/avx512er-builtins.c
+++ b/test/CodeGen/avx512er-builtins.c
@@ -1,26 +1,24 @@
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +avx512f -target-feature +avx512er -emit-llvm -o - -Werror | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +avx512f -target-feature +avx512er -emit-llvm -o - -Wall -Werror | FileCheck %s
-// Don't include mm_malloc.h, it's system specific.
-#define __MM_MALLOC_H
#include <immintrin.h>
__m512d test_mm512_rsqrt28_round_pd(__m512d a) {
// CHECK-LABEL: @test_mm512_rsqrt28_round_pd
// CHECK: @llvm.x86.avx512.rsqrt28.pd
- return _mm512_rsqrt28_round_pd(a, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_rsqrt28_round_pd(a, _MM_FROUND_CUR_DIRECTION);
}
__m512d test_mm512_mask_rsqrt28_round_pd(__m512d s, __mmask8 m, __m512d a) {
// CHECK-LABEL: @test_mm512_mask_rsqrt28_round_pd
// CHECK: @llvm.x86.avx512.rsqrt28.pd
- return _mm512_mask_rsqrt28_round_pd(s, m, a, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_mask_rsqrt28_round_pd(s, m, a, _MM_FROUND_CUR_DIRECTION);
}
__m512d test_mm512_maskz_rsqrt28_round_pd(__mmask8 m, __m512d a) {
// CHECK-LABEL: @test_mm512_maskz_rsqrt28_round_pd
// CHECK: @llvm.x86.avx512.rsqrt28.pd
- return _mm512_maskz_rsqrt28_round_pd(m, a, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_maskz_rsqrt28_round_pd(m, a, _MM_FROUND_CUR_DIRECTION);
}
__m512d test_mm512_rsqrt28_pd(__m512d a) {
@@ -44,19 +42,19 @@ __m512d test_mm512_maskz_rsqrt28_pd(__mmask8 m, __m512d a) {
__m512 test_mm512_rsqrt28_round_ps(__m512 a) {
// CHECK-LABEL: @test_mm512_rsqrt28_round_ps
// CHECK: @llvm.x86.avx512.rsqrt28.ps
- return _mm512_rsqrt28_round_ps(a, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_rsqrt28_round_ps(a, _MM_FROUND_CUR_DIRECTION);
}
__m512 test_mm512_mask_rsqrt28_round_ps(__m512 s, __mmask16 m, __m512 a) {
// CHECK-LABEL: @test_mm512_mask_rsqrt28_round_ps
// CHECK: @llvm.x86.avx512.rsqrt28.ps
- return _mm512_mask_rsqrt28_round_ps(s, m, a, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_mask_rsqrt28_round_ps(s, m, a, _MM_FROUND_CUR_DIRECTION);
}
__m512 test_mm512_maskz_rsqrt28_round_ps(__mmask16 m, __m512 a) {
// CHECK-LABEL: @test_mm512_maskz_rsqrt28_round_ps
// CHECK: @llvm.x86.avx512.rsqrt28.ps
- return _mm512_maskz_rsqrt28_round_ps(m, a, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_maskz_rsqrt28_round_ps(m, a, _MM_FROUND_CUR_DIRECTION);
}
__m512 test_mm512_rsqrt28_ps(__m512 a) {
@@ -80,19 +78,19 @@ __m512 test_mm512_maskz_rsqrt28_ps(__mmask16 m, __m512 a) {
__m128 test_mm_rsqrt28_round_ss(__m128 a, __m128 b) {
// CHECK-LABEL: @test_mm_rsqrt28_round_ss
// CHECK: @llvm.x86.avx512.rsqrt28.ss
- return _mm_rsqrt28_round_ss(a, b, _MM_FROUND_TO_NEAREST_INT);
+ return _mm_rsqrt28_round_ss(a, b, _MM_FROUND_CUR_DIRECTION);
}
__m128 test_mm_mask_rsqrt28_round_ss(__m128 s, __mmask16 m, __m128 a, __m128 b) {
// CHECK-LABEL: @test_mm_mask_rsqrt28_round_ss
// CHECK: @llvm.x86.avx512.rsqrt28.ss
- return _mm_mask_rsqrt28_round_ss(s, m, a, b, _MM_FROUND_TO_NEAREST_INT);
+ return _mm_mask_rsqrt28_round_ss(s, m, a, b, _MM_FROUND_CUR_DIRECTION);
}
__m128 test_mm_maskz_rsqrt28_round_ss(__mmask16 m, __m128 a, __m128 b) {
// CHECK-LABEL: @test_mm_maskz_rsqrt28_round_ss
// CHECK: @llvm.x86.avx512.rsqrt28.ss
- return _mm_maskz_rsqrt28_round_ss(m, a, b, _MM_FROUND_TO_NEAREST_INT);
+ return _mm_maskz_rsqrt28_round_ss(m, a, b, _MM_FROUND_CUR_DIRECTION);
}
__m128 test_mm_rsqrt28_ss(__m128 a, __m128 b) {
@@ -116,37 +114,37 @@ __m128 test_mm_maskz_rsqrt28_ss(__mmask16 m, __m128 a, __m128 b) {
__m128d test_mm_rsqrt28_round_sd(__m128d a, __m128d b) {
// CHECK-LABEL: @test_mm_rsqrt28_round_sd
// CHECK: @llvm.x86.avx512.rsqrt28.sd
- return _mm_rsqrt28_round_sd(a, b, _MM_FROUND_TO_NEAREST_INT);
+ return _mm_rsqrt28_round_sd(a, b, _MM_FROUND_CUR_DIRECTION);
}
__m128d test_mm_mask_rsqrt28_round_sd(__m128d s, __mmask8 m, __m128d a, __m128d b) {
// CHECK-LABEL: @test_mm_mask_rsqrt28_round_sd
// CHECK: @llvm.x86.avx512.rsqrt28.sd
- return _mm_mask_rsqrt28_round_sd(s, m, a, b, _MM_FROUND_TO_NEAREST_INT);
+ return _mm_mask_rsqrt28_round_sd(s, m, a, b, _MM_FROUND_CUR_DIRECTION);
}
__m128d test_mm_maskz_rsqrt28_round_sd(__mmask8 m, __m128d a, __m128d b) {
// CHECK-LABEL: @test_mm_maskz_rsqrt28_round_sd
// CHECK: @llvm.x86.avx512.rsqrt28.sd
- return _mm_maskz_rsqrt28_round_sd(m, a, b, _MM_FROUND_TO_NEAREST_INT);
+ return _mm_maskz_rsqrt28_round_sd(m, a, b, _MM_FROUND_CUR_DIRECTION);
}
__m512d test_mm512_rcp28_round_pd(__m512d a) {
// CHECK-LABEL: @test_mm512_rcp28_round_pd
// CHECK: @llvm.x86.avx512.rcp28.pd
- return _mm512_rcp28_round_pd(a, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_rcp28_round_pd(a, _MM_FROUND_CUR_DIRECTION);
}
__m512d test_mm512_mask_rcp28_round_pd(__m512d s, __mmask8 m, __m512d a) {
// CHECK-LABEL: @test_mm512_mask_rcp28_round_pd
// CHECK: @llvm.x86.avx512.rcp28.pd
- return _mm512_mask_rcp28_round_pd(s, m, a, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_mask_rcp28_round_pd(s, m, a, _MM_FROUND_CUR_DIRECTION);
}
__m512d test_mm512_maskz_rcp28_round_pd(__mmask8 m, __m512d a) {
// CHECK-LABEL: @test_mm512_maskz_rcp28_round_pd
// CHECK: @llvm.x86.avx512.rcp28.pd
- return _mm512_maskz_rcp28_round_pd(m, a, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_maskz_rcp28_round_pd(m, a, _MM_FROUND_CUR_DIRECTION);
}
__m512d test_mm512_rcp28_pd(__m512d a) {
@@ -170,19 +168,19 @@ __m512d test_mm512_maskz_rcp28_pd(__mmask8 m, __m512d a) {
__m512 test_mm512_rcp28_round_ps(__m512 a) {
// CHECK-LABEL: @test_mm512_rcp28_round_ps
// CHECK: @llvm.x86.avx512.rcp28.ps
- return _mm512_rcp28_round_ps(a, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_rcp28_round_ps(a, _MM_FROUND_CUR_DIRECTION);
}
__m512 test_mm512_mask_rcp28_round_ps(__m512 s, __mmask16 m, __m512 a) {
// CHECK-LABEL: @test_mm512_mask_rcp28_round_ps
// CHECK: @llvm.x86.avx512.rcp28.ps
- return _mm512_mask_rcp28_round_ps(s, m, a, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_mask_rcp28_round_ps(s, m, a, _MM_FROUND_CUR_DIRECTION);
}
__m512 test_mm512_maskz_rcp28_round_ps(__mmask16 m, __m512 a) {
// CHECK-LABEL: @test_mm512_maskz_rcp28_round_ps
// CHECK: @llvm.x86.avx512.rcp28.ps
- return _mm512_maskz_rcp28_round_ps(m, a, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_maskz_rcp28_round_ps(m, a, _MM_FROUND_CUR_DIRECTION);
}
__m512 test_mm512_rcp28_ps(__m512 a) {
@@ -206,19 +204,19 @@ __m512 test_mm512_maskz_rcp28_ps(__mmask16 m, __m512 a) {
__m128 test_mm_rcp28_round_ss(__m128 a, __m128 b) {
// CHECK-LABEL: @test_mm_rcp28_round_ss
// CHECK: @llvm.x86.avx512.rcp28.ss
- return _mm_rcp28_round_ss(a, b, _MM_FROUND_TO_NEAREST_INT);
+ return _mm_rcp28_round_ss(a, b, _MM_FROUND_CUR_DIRECTION);
}
__m128 test_mm_mask_rcp28_round_ss(__m128 s, __mmask16 m, __m128 a, __m128 b) {
// CHECK-LABEL: @test_mm_mask_rcp28_round_ss
// CHECK: @llvm.x86.avx512.rcp28.ss
- return _mm_mask_rcp28_round_ss(s, m, a, b, _MM_FROUND_TO_NEAREST_INT);
+ return _mm_mask_rcp28_round_ss(s, m, a, b, _MM_FROUND_CUR_DIRECTION);
}
__m128 test_mm_maskz_rcp28_round_ss(__mmask16 m, __m128 a, __m128 b) {
// CHECK-LABEL: @test_mm_maskz_rcp28_round_ss
// CHECK: @llvm.x86.avx512.rcp28.ss
- return _mm_maskz_rcp28_round_ss(m, a, b, _MM_FROUND_TO_NEAREST_INT);
+ return _mm_maskz_rcp28_round_ss(m, a, b, _MM_FROUND_CUR_DIRECTION);
}
__m128 test_mm_rcp28_ss(__m128 a, __m128 b) {
@@ -242,19 +240,19 @@ __m128 test_mm_maskz_rcp28_ss(__mmask16 m, __m128 a, __m128 b) {
__m128d test_mm_rcp28_round_sd(__m128d a, __m128d b) {
// CHECK-LABEL: @test_mm_rcp28_round_sd
// CHECK: @llvm.x86.avx512.rcp28.sd
- return _mm_rcp28_round_sd(a, b, _MM_FROUND_TO_NEAREST_INT);
+ return _mm_rcp28_round_sd(a, b, _MM_FROUND_CUR_DIRECTION);
}
__m128d test_mm_mask_rcp28_round_sd(__m128d s, __mmask8 m, __m128d a, __m128d b) {
// CHECK-LABEL: @test_mm_mask_rcp28_round_sd
// CHECK: @llvm.x86.avx512.rcp28.sd
- return _mm_mask_rcp28_round_sd(s, m, a, b, _MM_FROUND_TO_NEAREST_INT);
+ return _mm_mask_rcp28_round_sd(s, m, a, b, _MM_FROUND_CUR_DIRECTION);
}
__m128d test_mm_maskz_rcp28_round_sd(__mmask8 m, __m128d a, __m128d b) {
// CHECK-LABEL: @test_mm_maskz_rcp28_round_sd
// CHECK: @llvm.x86.avx512.rcp28.sd
- return _mm_maskz_rcp28_round_sd(m, a, b, _MM_FROUND_TO_NEAREST_INT);
+ return _mm_maskz_rcp28_round_sd(m, a, b, _MM_FROUND_CUR_DIRECTION);
}
__m128d test_mm_rcp28_sd(__m128d a, __m128d b) {
@@ -278,19 +276,19 @@ __m128d test_mm_maskz_rcp28_sd(__mmask8 m, __m128d a, __m128d b) {
__m512d test_mm512_exp2a23_round_pd(__m512d a) {
// CHECK-LABEL: @test_mm512_exp2a23_round_pd
// CHECK: @llvm.x86.avx512.exp2.pd
- return _mm512_exp2a23_round_pd(a, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_exp2a23_round_pd(a, _MM_FROUND_CUR_DIRECTION);
}
__m512d test_mm512_mask_exp2a23_round_pd(__m512d s, __mmask8 m, __m512d a) {
// CHECK-LABEL: @test_mm512_mask_exp2a23_round_pd
// CHECK: @llvm.x86.avx512.exp2.pd
- return _mm512_mask_exp2a23_round_pd(s, m, a, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_mask_exp2a23_round_pd(s, m, a, _MM_FROUND_CUR_DIRECTION);
}
__m512d test_mm512_maskz_exp2a23_round_pd(__mmask8 m, __m512d a) {
// CHECK-LABEL: @test_mm512_maskz_exp2a23_round_pd
// CHECK: @llvm.x86.avx512.exp2.pd
- return _mm512_maskz_exp2a23_round_pd(m, a, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_maskz_exp2a23_round_pd(m, a, _MM_FROUND_CUR_DIRECTION);
}
__m512d test_mm512_exp2a23_pd(__m512d a) {
@@ -314,19 +312,19 @@ __m512d test_mm512_maskz_exp2a23_pd(__mmask8 m, __m512d a) {
__m512 test_mm512_exp2a23_round_ps(__m512 a) {
// CHECK-LABEL: @test_mm512_exp2a23_round_ps
// CHECK: @llvm.x86.avx512.exp2.ps
- return _mm512_exp2a23_round_ps(a, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_exp2a23_round_ps(a, _MM_FROUND_CUR_DIRECTION);
}
__m512 test_mm512_mask_exp2a23_round_ps(__m512 s, __mmask16 m, __m512 a) {
// CHECK-LABEL: @test_mm512_mask_exp2a23_round_ps
// CHECK: @llvm.x86.avx512.exp2.ps
- return _mm512_mask_exp2a23_round_ps(s, m, a, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_mask_exp2a23_round_ps(s, m, a, _MM_FROUND_CUR_DIRECTION);
}
__m512 test_mm512_maskz_exp2a23_round_ps(__mmask16 m, __m512 a) {
// CHECK-LABEL: @test_mm512_maskz_exp2a23_round_ps
// CHECK: @llvm.x86.avx512.exp2.ps
- return _mm512_maskz_exp2a23_round_ps(m, a, _MM_FROUND_TO_NEAREST_INT);
+ return _mm512_maskz_exp2a23_round_ps(m, a, _MM_FROUND_CUR_DIRECTION);
}
__m512 test_mm512_exp2a23_ps(__m512 a) {
diff --git a/test/CodeGen/avx512f-builtins.c b/test/CodeGen/avx512f-builtins.c
index 556c06f532cf..760783af1ce0 100644
--- a/test/CodeGen/avx512f-builtins.c
+++ b/test/CodeGen/avx512f-builtins.c
@@ -1,7 +1,5 @@
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +avx512f -emit-llvm -o - -Werror | FileCheck %s
-
-// Don't include mm_malloc.h, it's system specific.
-#define __MM_MALLOC_H
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +avx512f -emit-llvm -o - -Wall -Werror | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +avx512f -O2 -emit-llvm -o - -Wall -Werror | FileCheck %s -check-prefix=O2
#include <immintrin.h>
@@ -395,105 +393,109 @@ __mmask16 test_mm512_knot(__mmask16 a)
__m512i test_mm512_alignr_epi32(__m512i a, __m512i b)
{
// CHECK-LABEL: @test_mm512_alignr_epi32
- // CHECK: @llvm.x86.avx512.mask.valign.d.512
+ // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> <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>
return _mm512_alignr_epi32(a, b, 2);
}
__m512i test_mm512_mask_alignr_epi32(__m512i w, __mmask16 u, __m512i a, __m512i b)
{
// CHECK-LABEL: @test_mm512_mask_alignr_epi32
- // CHECK: @llvm.x86.avx512.mask.valign.d.512
+ // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> <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>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> {{.*}}
return _mm512_mask_alignr_epi32(w, u, a, b, 2);
}
__m512i test_mm512_maskz_alignr_epi32( __mmask16 u, __m512i a, __m512i b)
{
// CHECK-LABEL: @test_mm512_maskz_alignr_epi32
- // CHECK: @llvm.x86.avx512.mask.valign.d.512
+ // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> <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>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> {{.*}}
return _mm512_maskz_alignr_epi32(u, a, b, 2);
}
__m512i test_mm512_alignr_epi64(__m512i a, __m512i b)
{
// CHECK-LABEL: @test_mm512_alignr_epi64
- // CHECK: @llvm.x86.avx512.mask.valign.q.512
+ // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> %{{.*}}, <8 x i32> <i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9>
return _mm512_alignr_epi64(a, b, 2);
}
__m512i test_mm512_mask_alignr_epi64(__m512i w, __mmask8 u, __m512i a, __m512i b)
{
// CHECK-LABEL: @test_mm512_mask_alignr_epi64
- // CHECK: @llvm.x86.avx512.mask.valign.q.512
+ // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> %{{.*}}, <8 x i32> <i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> {{.*}}
return _mm512_mask_alignr_epi64(w, u, a, b, 2);
}
__m512i test_mm512_maskz_alignr_epi64( __mmask8 u, __m512i a, __m512i b)
{
// CHECK-LABEL: @test_mm512_maskz_alignr_epi64
- // CHECK: @llvm.x86.avx512.mask.valign.q.512
+ // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> %{{.*}}, <8 x i32> <i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> {{.*}}
return _mm512_maskz_alignr_epi64(u, a, b, 2);
}
__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
- return _mm512_fmadd_round_pd(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_mask_fmadd_round_pd(__A, __U, __B, __C, _MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_mask3_fmadd_round_pd(__A, __B, __C, __U, _MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_maskz_fmadd_round_pd(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_fmsub_round_pd(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_mask_fmsub_round_pd(__A, __U, __B, __C, _MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_maskz_fmsub_round_pd(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_fnmadd_round_pd(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_mask3_fnmadd_round_pd(__A, __B, __C, __U, _MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_maskz_fnmadd_round_pd(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_fnmsub_round_pd(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_maskz_fnmsub_round_pd(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT);
+ 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
@@ -558,62 +560,62 @@ __m512d test_mm512_maskz_fnmsub_pd(__mmask8 __U, __m512d __A, __m512d __B, __m51
__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
- return _mm512_fmadd_round_ps(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_mask_fmadd_round_ps(__A, __U, __B, __C, _MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_mask3_fmadd_round_ps(__A, __B, __C, __U, _MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_maskz_fmadd_round_ps(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_fmsub_round_ps(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_mask_fmsub_round_ps(__A, __U, __B, __C, _MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_maskz_fmsub_round_ps(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_fnmadd_round_ps(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_mask3_fnmadd_round_ps(__A, __B, __C, __U, _MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_maskz_fnmadd_round_ps(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_fnmsub_round_ps(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_maskz_fnmsub_round_ps(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT);
+ 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
@@ -678,37 +680,37 @@ __m512 test_mm512_maskz_fnmsub_ps(__mmask16 __U, __m512 __A, __m512 __B, __m512
__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
- return _mm512_fmaddsub_round_pd(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_mask_fmaddsub_round_pd(__A, __U, __B, __C, _MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_mask3_fmaddsub_round_pd(__A, __B, __C, __U, _MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_maskz_fmaddsub_round_pd(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_fmsubadd_round_pd(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_mask_fmsubadd_round_pd(__A, __U, __B, __C, _MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_maskz_fmsubadd_round_pd(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT);
+ 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
@@ -748,37 +750,37 @@ __m512d test_mm512_maskz_fmsubadd_pd(__mmask8 __U, __m512d __A, __m512d __B, __m
__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
- return _mm512_fmaddsub_round_ps(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_mask_fmaddsub_round_ps(__A, __U, __B, __C, _MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_mask3_fmaddsub_round_ps(__A, __B, __C, __U, _MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_maskz_fmaddsub_round_ps(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_fmsubadd_round_ps(__A, __B, __C, _MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_mask_fmsubadd_round_ps(__A, __U, __B, __C, _MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_maskz_fmsubadd_round_ps(__U, __A, __B, __C, _MM_FROUND_TO_NEAREST_INT);
+ 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
@@ -818,7 +820,7 @@ __m512 test_mm512_maskz_fmsubadd_ps(__mmask16 __U, __m512 __A, __m512 __B, __m51
__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
- return _mm512_mask3_fmsub_round_pd(__A, __B, __C, __U, _MM_FROUND_TO_NEAREST_INT);
+ 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
@@ -828,7 +830,7 @@ __m512d test_mm512_mask3_fmsub_pd(__m512d __A, __m512d __B, __m512d __C, __mmask
__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
- return _mm512_mask3_fmsub_round_ps(__A, __B, __C, __U, _MM_FROUND_TO_NEAREST_INT);
+ 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
@@ -838,7 +840,7 @@ __m512 test_mm512_mask3_fmsub_ps(__m512 __A, __m512 __B, __m512 __C, __mmask16 _
__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
- return _mm512_mask3_fmsubadd_round_pd(__A, __B, __C, __U, _MM_FROUND_TO_NEAREST_INT);
+ 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
@@ -848,7 +850,7 @@ __m512d test_mm512_mask3_fmsubadd_pd(__m512d __A, __m512d __B, __m512d __C, __mm
__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
- return _mm512_mask3_fmsubadd_round_ps(__A, __B, __C, __U, _MM_FROUND_TO_NEAREST_INT);
+ 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
@@ -858,7 +860,7 @@ __m512 test_mm512_mask3_fmsubadd_ps(__m512 __A, __m512 __B, __m512 __C, __mmask1
__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
- return _mm512_mask_fnmadd_round_pd(__A, __U, __B, __C, _MM_FROUND_TO_NEAREST_INT);
+ 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
@@ -868,7 +870,7 @@ __m512d test_mm512_mask_fnmadd_pd(__m512d __A, __mmask8 __U, __m512d __B, __m512
__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
- return _mm512_mask_fnmadd_round_ps(__A, __U, __B, __C, _MM_FROUND_TO_NEAREST_INT);
+ 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
@@ -878,12 +880,12 @@ __m512 test_mm512_mask_fnmadd_ps(__m512 __A, __mmask16 __U, __m512 __B, __m512 _
__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
- return _mm512_mask_fnmsub_round_pd(__A, __U, __B, __C, _MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_mask3_fnmsub_round_pd(__A, __B, __C, __U, _MM_FROUND_TO_NEAREST_INT);
+ 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
@@ -898,12 +900,12 @@ __m512d test_mm512_mask3_fnmsub_pd(__m512d __A, __m512d __B, __m512d __C, __mmas
__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
- return _mm512_mask_fnmsub_round_ps(__A, __U, __B, __C, _MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_mask3_fnmsub_round_ps(__A, __B, __C, __U, _MM_FROUND_TO_NEAREST_INT);
+ 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
@@ -1044,41 +1046,237 @@ __mmask8 test_mm512_mask_cmp_pd_mask(__mmask8 m, __m512d a, __m512d b) {
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
+ return _mm512_cmpeq_pd_mask(a, b);
+}
+
+__mmask8 test_mm512_cmpeq_ps_mask(__m512 a, __m512 b) {
+ // CHECK-LABEL: @test_mm512_cmpeq_ps_mask
+ // CHECK: @llvm.x86.avx512.mask.cmp.ps.512
+ 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
+ return _mm512_mask_cmpeq_pd_mask(k, a, b);
+}
+
+__mmask8 test_mm512_mask_cmpeq_ps_mask(__mmask8 k, __m512 a, __m512 b) {
+ // CHECK-LABEL: @test_mm512_mask_cmpeq_ps_mask
+ // CHECK: @llvm.x86.avx512.mask.cmp.ps.512
+ 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);
+}
+
+__mmask8 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);
+}
+
+__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
+ return _mm512_mask_cmple_pd_mask(k, a, b);
+}
+
+__mmask8 test_mm512_mask_cmple_ps_mask(__mmask8 k, __m512 a, __m512 b) {
+ // CHECK-LABEL: @test_mm512_mask_cmple_ps_mask
+ // CHECK: @llvm.x86.avx512.mask.cmp.ps.512
+ 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
+ return _mm512_cmplt_pd_mask(a, b);
+}
+
+__mmask8 test_mm512_cmplt_ps_mask(__m512 a, __m512 b) {
+ // CHECK-LABEL: @test_mm512_cmplt_ps_mask
+ // CHECK: @llvm.x86.avx512.mask.cmp.ps.512
+ 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
+ return _mm512_mask_cmplt_pd_mask(k, a, b);
+}
+
+__mmask8 test_mm512_mask_cmplt_ps_mask(__mmask8 k, __m512 a, __m512 b) {
+ // CHECK-LABEL: @test_mm512_mask_cmplt_ps_mask
+ // CHECK: @llvm.x86.avx512.mask.cmp.ps.512
+ 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
+ return _mm512_cmpneq_pd_mask(a, b);
+}
+
+__mmask8 test_mm512_cmpneq_ps_mask(__m512 a, __m512 b) {
+ // CHECK-LABEL: @test_mm512_cmpneq_ps_mask
+ // CHECK: @llvm.x86.avx512.mask.cmp.ps.512
+ 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
+ return _mm512_mask_cmpneq_pd_mask(k, a, b);
+}
+
+__mmask8 test_mm512_mask_cmpneq_ps_mask(__mmask8 k, __m512 a, __m512 b) {
+ // CHECK-LABEL: @test_mm512_mask_cmpneq_ps_mask
+ // CHECK: @llvm.x86.avx512.mask.cmp.ps.512
+ 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
+ return _mm512_cmpnle_pd_mask(a, b);
+}
+
+__mmask8 test_mm512_cmpnle_ps_mask(__m512 a, __m512 b) {
+ // CHECK-LABEL: @test_mm512_cmpnle_ps_mask
+ // CHECK: @llvm.x86.avx512.mask.cmp.ps.512
+ 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
+ return _mm512_mask_cmpnle_pd_mask(k, a, b);
+}
+
+__mmask8 test_mm512_mask_cmpnle_ps_mask(__mmask8 k, __m512 a, __m512 b) {
+ // CHECK-LABEL: @test_mm512_mask_cmpnle_ps_mask
+ // CHECK: @llvm.x86.avx512.mask.cmp.ps.512
+ 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
+ return _mm512_cmpnlt_pd_mask(a, b);
+}
+
+__mmask8 test_mm512_cmpnlt_ps_mask(__m512 a, __m512 b) {
+ // CHECK-LABEL: @test_mm512_cmpnlt_ps_mask
+ // CHECK: @llvm.x86.avx512.mask.cmp.ps.512
+ 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
+ return _mm512_mask_cmpnlt_pd_mask(k, a, b);
+}
+
+__mmask8 test_mm512_mask_cmpnlt_ps_mask(__mmask8 k, __m512 a, __m512 b) {
+ // CHECK-LABEL: @test_mm512_mask_cmpnlt_ps_mask
+ // CHECK: @llvm.x86.avx512.mask.cmp.ps.512
+ 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
+ return _mm512_cmpord_pd_mask(a, b);
+}
+
+__mmask8 test_mm512_cmpord_ps_mask(__m512 a, __m512 b) {
+ // CHECK-LABEL: @test_mm512_cmpord_ps_mask
+ // CHECK: @llvm.x86.avx512.mask.cmp.ps.512
+ 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
+ return _mm512_mask_cmpord_pd_mask(k, a, b);
+}
+
+__mmask8 test_mm512_mask_cmpord_ps_mask(__mmask8 k, __m512 a, __m512 b) {
+ // CHECK-LABEL: @test_mm512_mask_cmpord_ps_mask
+ // CHECK: @llvm.x86.avx512.mask.cmp.ps.512
+ 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
+ return _mm512_cmpunord_pd_mask(a, b);
+}
+
+__mmask8 test_mm512_cmpunord_ps_mask(__m512 a, __m512 b) {
+ // CHECK-LABEL: @test_mm512_cmpunord_ps_mask
+ // CHECK: @llvm.x86.avx512.mask.cmp.ps.512
+ 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
+ return _mm512_mask_cmpunord_pd_mask(k, a, b);
+}
+
+__mmask8 test_mm512_mask_cmpunord_ps_mask(__mmask8 k, __m512 a, __m512 b) {
+ // CHECK-LABEL: @test_mm512_mask_cmpunord_ps_mask
+ // CHECK: @llvm.x86.avx512.mask.cmp.ps.512
+ return _mm512_mask_cmpunord_ps_mask(k, a, b);
+}
+
__m256d test_mm512_extractf64x4_pd(__m512d a)
{
// CHECK-LABEL: @test_mm512_extractf64x4_pd
- // CHECK: @llvm.x86.avx512.mask.vextractf64x4.512
+ // 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
- //CHECL:@llvm.x86.avx512.mask.vextractf64x4.512
- return _mm512_mask_extractf64x4_pd( __W, __U, __A, 1);
+ // CHECK-LABEL:@test_mm512_mask_extractf64x4_pd
+ // 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
- //CHECL:@llvm.x86.avx512.mask.vextractf64x4.512
- return _mm512_maskz_extractf64x4_pd( __U, __A, 1);
+ // CHECK-LABEL:@test_mm512_maskz_extractf64x4_pd
+ // 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);
}
__m128 test_mm512_extractf32x4_ps(__m512 a)
{
// CHECK-LABEL: @test_mm512_extractf32x4_ps
- // CHECK: @llvm.x86.avx512.mask.vextractf32x4.512
+ // 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){
- //CHECK-LABEL:@test_mm512_mask_extractf32x4_ps
- //CHECL: @llvm.x86.avx512.mask.vextractf32x4.512
- return _mm512_mask_extractf32x4_ps( __W, __U, __A, 1);
+ // CHECK-LABEL:@test_mm512_mask_extractf32x4_ps
+ // 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){
- //CHECK-LABEL:@test_mm512_maskz_extractf32x4_ps
- //CHECL: @llvm.x86.avx512.mask.vextractf32x4.512
+ // CHECK-LABEL:@test_mm512_maskz_extractf32x4_ps
+ // 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);
}
@@ -1342,30 +1540,30 @@ __mmask8 test_mm512_mask_cmpneq_epu64_mask(__mmask8 __u, __m512i __a, __m512i __
return (__mmask8)_mm512_mask_cmpneq_epu64_mask(__u, __a, __b);
}
-__mmask16 test_mm512_cmp_epi32_mask(__m512i __a, __m512i __b) {
- // CHECK-LABEL: @test_mm512_cmp_epi32_mask
+__mmask16 test_mm512_cmp_eq_epi32_mask(__m512i __a, __m512i __b) {
+ // CHECK-LABEL: @test_mm512_cmp_eq_epi32_mask
// CHECK: icmp eq <16 x i32> %{{.*}}, %{{.*}}
- return (__mmask16)_mm512_cmp_epi32_mask(__a, __b, 0);
+ return (__mmask16)_mm512_cmp_epi32_mask(__a, __b, _MM_CMPINT_EQ);
}
-__mmask16 test_mm512_mask_cmp_epi32_mask(__mmask16 __u, __m512i __a, __m512i __b) {
- // CHECK-LABEL: @test_mm512_mask_cmp_epi32_mask
+__mmask16 test_mm512_mask_cmp_eq_epi32_mask(__mmask16 __u, __m512i __a, __m512i __b) {
+ // CHECK-LABEL: @test_mm512_mask_cmp_eq_epi32_mask
// CHECK: icmp eq <16 x i32> %{{.*}}, %{{.*}}
// CHECK: and <16 x i1> %{{.*}}, %{{.*}}
- return (__mmask16)_mm512_mask_cmp_epi32_mask(__u, __a, __b, 0);
+ return (__mmask16)_mm512_mask_cmp_epi32_mask(__u, __a, __b, _MM_CMPINT_EQ);
}
-__mmask8 test_mm512_cmp_epi64_mask(__m512i __a, __m512i __b) {
- // CHECK-LABEL: @test_mm512_cmp_epi64_mask
+__mmask8 test_mm512_cmp_eq_epi64_mask(__m512i __a, __m512i __b) {
+ // CHECK-LABEL: @test_mm512_cmp_eq_epi64_mask
// CHECK: icmp eq <8 x i64> %{{.*}}, %{{.*}}
- return (__mmask8)_mm512_cmp_epi64_mask(__a, __b, 0);
+ return (__mmask8)_mm512_cmp_epi64_mask(__a, __b, _MM_CMPINT_EQ);
}
-__mmask8 test_mm512_mask_cmp_epi64_mask(__mmask8 __u, __m512i __a, __m512i __b) {
- // CHECK-LABEL: @test_mm512_mask_cmp_epi64_mask
+__mmask8 test_mm512_mask_cmp_eq_epi64_mask(__mmask8 __u, __m512i __a, __m512i __b) {
+ // CHECK-LABEL: @test_mm512_mask_cmp_eq_epi64_mask
// CHECK: icmp eq <8 x i64> %{{.*}}, %{{.*}}
// CHECK: and <8 x i1> %{{.*}}, %{{.*}}
- return (__mmask8)_mm512_mask_cmp_epi64_mask(__u, __a, __b, 0);
+ return (__mmask8)_mm512_mask_cmp_epi64_mask(__u, __a, __b, _MM_CMPINT_EQ);
}
__mmask16 test_mm512_cmp_epu32_mask(__m512i __a, __m512i __b) {
@@ -1587,14 +1785,16 @@ __m512i test_mm512_andnot_epi64(__m512i __A, __m512i __B) {
__m512i test_mm512_maskz_sub_epi32 (__mmask16 __k,__m512i __A, __m512i __B) {
//CHECK-LABEL: @test_mm512_maskz_sub_epi32
- //CHECK: @llvm.x86.avx512.mask.psub.d.512
+ //CHECK: sub <16 x i32> %{{.*}}, %{{.*}}
+ //CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_maskz_sub_epi32(__k,__A,__B);
}
__m512i test_mm512_mask_sub_epi32 (__mmask16 __k,__m512i __A, __m512i __B,
__m512i __src) {
//CHECK-LABEL: @test_mm512_mask_sub_epi32
- //CHECK: @llvm.x86.avx512.mask.psub.d.512
+ //CHECK: sub <16 x i32> %{{.*}}, %{{.*}}
+ //CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_mask_sub_epi32(__src,__k,__A,__B);
}
@@ -1606,14 +1806,16 @@ __m512i test_mm512_sub_epi32(__m512i __A, __m512i __B) {
__m512i test_mm512_maskz_sub_epi64 (__mmask8 __k,__m512i __A, __m512i __B) {
//CHECK-LABEL: @test_mm512_maskz_sub_epi64
- //CHECK: @llvm.x86.avx512.mask.psub.q.512
+ //CHECK: sub <8 x i64> %{{.*}}, %{{.*}}
+ //CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_maskz_sub_epi64(__k,__A,__B);
}
__m512i test_mm512_mask_sub_epi64 (__mmask8 __k,__m512i __A, __m512i __B,
__m512i __src) {
//CHECK-LABEL: @test_mm512_mask_sub_epi64
- //CHECK: @llvm.x86.avx512.mask.psub.q.512
+ //CHECK: sub <8 x i64> %{{.*}}, %{{.*}}
+ //CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_mask_sub_epi64(__src,__k,__A,__B);
}
@@ -1625,14 +1827,16 @@ __m512i test_mm512_sub_epi64(__m512i __A, __m512i __B) {
__m512i test_mm512_maskz_add_epi32 (__mmask16 __k,__m512i __A, __m512i __B) {
//CHECK-LABEL: @test_mm512_maskz_add_epi32
- //CHECK: @llvm.x86.avx512.mask.padd.d.512
+ //CHECK: add <16 x i32> %{{.*}}, %{{.*}}
+ //CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_maskz_add_epi32(__k,__A,__B);
}
__m512i test_mm512_mask_add_epi32 (__mmask16 __k,__m512i __A, __m512i __B,
__m512i __src) {
//CHECK-LABEL: @test_mm512_mask_add_epi32
- //CHECK: @llvm.x86.avx512.mask.padd.d.512
+ //CHECK: add <16 x i32> %{{.*}}, %{{.*}}
+ //CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_mask_add_epi32(__src,__k,__A,__B);
}
@@ -1644,14 +1848,16 @@ __m512i test_mm512_add_epi32(__m512i __A, __m512i __B) {
__m512i test_mm512_maskz_add_epi64 (__mmask8 __k,__m512i __A, __m512i __B) {
//CHECK-LABEL: @test_mm512_maskz_add_epi64
- //CHECK: @llvm.x86.avx512.mask.padd.q.512
+ //CHECK: add <8 x i64> %{{.*}}, %{{.*}}
+ //CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_maskz_add_epi64(__k,__A,__B);
}
__m512i test_mm512_mask_add_epi64 (__mmask8 __k,__m512i __A, __m512i __B,
__m512i __src) {
//CHECK-LABEL: @test_mm512_mask_add_epi64
- //CHECK: @llvm.x86.avx512.mask.padd.q.512
+ //CHECK: add <8 x i64> %{{.*}}, %{{.*}}
+ //CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_mask_add_epi64(__src,__k,__A,__B);
}
@@ -1661,41 +1867,59 @@ __m512i test_mm512_add_epi64(__m512i __A, __m512i __B) {
return _mm512_add_epi64(__A,__B);
}
+__m512i test_mm512_mul_epi32(__m512i __A, __m512i __B) {
+ //CHECK-LABEL: @test_mm512_mul_epi32
+ //CHECK: @llvm.x86.avx512.pmul.dq.512
+ return _mm512_mul_epi32(__A,__B);
+}
+
__m512i test_mm512_maskz_mul_epi32 (__mmask16 __k,__m512i __A, __m512i __B) {
//CHECK-LABEL: @test_mm512_maskz_mul_epi32
- //CHECK: @llvm.x86.avx512.mask.pmul.dq.512
+ //CHECK: @llvm.x86.avx512.pmul.dq.512
+ //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) {
//CHECK-LABEL: @test_mm512_mask_mul_epi32
- //CHECK: @llvm.x86.avx512.mask.pmul.dq.512
+ //CHECK: @llvm.x86.avx512.pmul.dq.512
+ //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
+ return _mm512_mul_epu32(__A,__B);
+}
+
__m512i test_mm512_maskz_mul_epu32 (__mmask16 __k,__m512i __A, __m512i __B) {
//CHECK-LABEL: @test_mm512_maskz_mul_epu32
- //CHECK: @llvm.x86.avx512.mask.pmulu.dq.512
+ //CHECK: @llvm.x86.avx512.pmulu.dq.512
+ //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) {
//CHECK-LABEL: @test_mm512_mask_mul_epu32
- //CHECK: @llvm.x86.avx512.mask.pmulu.dq.512
+ //CHECK: @llvm.x86.avx512.pmulu.dq.512
+ //CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_mask_mul_epu32(__src,__k,__A,__B);
}
__m512i test_mm512_maskz_mullo_epi32 (__mmask16 __k,__m512i __A, __m512i __B) {
//CHECK-LABEL: @test_mm512_maskz_mullo_epi32
- //CHECK: @llvm.x86.avx512.mask.pmull.d.512
+ //CHECK: mul <16 x i32> %{{.*}}, %{{.*}}
+ //CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_maskz_mullo_epi32(__k,__A,__B);
}
__m512i test_mm512_mask_mullo_epi32 (__mmask16 __k,__m512i __A, __m512i __B, __m512i __src) {
//CHECK-LABEL: @test_mm512_mask_mullo_epi32
- //CHECK: @llvm.x86.avx512.mask.pmull.d.512
+ //CHECK: mul <16 x i32> %{{.*}}, %{{.*}}
+ //CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_mask_mullo_epi32(__src,__k,__A,__B);
}
@@ -1708,67 +1932,71 @@ __m512i test_mm512_mullo_epi32(__m512i __A, __m512i __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
- return _mm512_add_round_pd(__A,__B,_MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_mask_add_round_pd(__W,__U,__A,__B,_MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_maskz_add_round_pd(__U,__A,__B,_MM_FROUND_TO_NEAREST_INT);
+ 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) {
// CHECK-LABEL: @test_mm512_mask_add_pd
- // CHECK: @llvm.x86.avx512.mask.add.pd.512
+ // CHECK: fadd <8 x double> %{{.*}}, %{{.*}}
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask_add_pd(__W,__U,__A,__B);
}
__m512d test_mm512_maskz_add_pd(__mmask8 __U, __m512d __A, __m512d __B) {
// CHECK-LABEL: @test_mm512_maskz_add_pd
- // CHECK: @llvm.x86.avx512.mask.add.pd.512
+ // CHECK: fadd <8 x double> %{{.*}}, %{{.*}}
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_maskz_add_pd(__U,__A,__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
- return _mm512_add_round_ps(__A,__B,_MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_mask_add_round_ps(__W,__U,__A,__B,_MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_maskz_add_round_ps(__U,__A,__B,_MM_FROUND_TO_NEAREST_INT);
+ 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) {
// CHECK-LABEL: @test_mm512_mask_add_ps
- // CHECK: @llvm.x86.avx512.mask.add.ps.512
+ // CHECK: fadd <16 x float> %{{.*}}, %{{.*}}
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_mask_add_ps(__W,__U,__A,__B);
}
__m512 test_mm512_maskz_add_ps(__mmask16 __U, __m512 __A, __m512 __B) {
// CHECK-LABEL: @test_mm512_maskz_add_ps
- // CHECK: @llvm.x86.avx512.mask.add.ps.512
+ // CHECK: fadd <16 x float> %{{.*}}, %{{.*}}
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_maskz_add_ps(__U,__A,__B);
}
__m128 test_mm_add_round_ss(__m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_add_round_ss
// CHECK: @llvm.x86.avx512.mask.add.ss.round
- return _mm_add_round_ss(__A,__B,_MM_FROUND_TO_NEAREST_INT);
+ return _mm_add_round_ss(__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128 test_mm_mask_add_round_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_mask_add_round_ss
// CHECK: @llvm.x86.avx512.mask.add.ss.round
- return _mm_mask_add_round_ss(__W,__U,__A,__B,_MM_FROUND_TO_NEAREST_INT);
+ return _mm_mask_add_round_ss(__W,__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128 test_mm_maskz_add_round_ss(__mmask8 __U, __m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_maskz_add_round_ss
// CHECK: @llvm.x86.avx512.mask.add.ss.round
- return _mm_maskz_add_round_ss(__U,__A,__B,_MM_FROUND_TO_NEAREST_INT);
+ return _mm_maskz_add_round_ss(__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128 test_mm_mask_add_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_mask_add_ss
@@ -1783,17 +2011,17 @@ __m128 test_mm_maskz_add_ss(__mmask8 __U, __m128 __A, __m128 __B) {
__m128d test_mm_add_round_sd(__m128d __A, __m128d __B) {
// CHECK-LABEL: @test_mm_add_round_sd
// CHECK: @llvm.x86.avx512.mask.add.sd.round
- return _mm_add_round_sd(__A,__B,_MM_FROUND_TO_NEAREST_INT);
+ return _mm_add_round_sd(__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128d test_mm_mask_add_round_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
// CHECK-LABEL: @test_mm_mask_add_round_sd
// CHECK: @llvm.x86.avx512.mask.add.sd.round
- return _mm_mask_add_round_sd(__W,__U,__A,__B,_MM_FROUND_TO_NEAREST_INT);
+ return _mm_mask_add_round_sd(__W,__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128d test_mm_maskz_add_round_sd(__mmask8 __U, __m128d __A, __m128d __B) {
// CHECK-LABEL: @test_mm_maskz_add_round_sd
// CHECK: @llvm.x86.avx512.mask.add.sd.round
- return _mm_maskz_add_round_sd(__U,__A,__B,_MM_FROUND_TO_NEAREST_INT);
+ return _mm_maskz_add_round_sd(__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128d test_mm_mask_add_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
// CHECK-LABEL: @test_mm_mask_add_sd
@@ -1808,67 +2036,71 @@ __m128d test_mm_maskz_add_sd(__mmask8 __U, __m128d __A, __m128d __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
- return _mm512_sub_round_pd(__A,__B,_MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_mask_sub_round_pd(__W,__U,__A,__B,_MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_maskz_sub_round_pd(__U,__A,__B,_MM_FROUND_TO_NEAREST_INT);
+ 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) {
// CHECK-LABEL: @test_mm512_mask_sub_pd
- // CHECK: @llvm.x86.avx512.mask.sub.pd.512
+ // CHECK: fsub <8 x double> %{{.*}}, %{{.*}}
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask_sub_pd(__W,__U,__A,__B);
}
__m512d test_mm512_maskz_sub_pd(__mmask8 __U, __m512d __A, __m512d __B) {
// CHECK-LABEL: @test_mm512_maskz_sub_pd
- // CHECK: @llvm.x86.avx512.mask.sub.pd.512
+ // CHECK: fsub <8 x double> %{{.*}}, %{{.*}}
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_maskz_sub_pd(__U,__A,__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
- return _mm512_sub_round_ps(__A,__B,_MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_mask_sub_round_ps(__W,__U,__A,__B,_MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_maskz_sub_round_ps(__U,__A,__B,_MM_FROUND_TO_NEAREST_INT);
+ 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) {
// CHECK-LABEL: @test_mm512_mask_sub_ps
- // CHECK: @llvm.x86.avx512.mask.sub.ps.512
+ // CHECK: fsub <16 x float> %{{.*}}, %{{.*}}
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_mask_sub_ps(__W,__U,__A,__B);
}
__m512 test_mm512_maskz_sub_ps(__mmask16 __U, __m512 __A, __m512 __B) {
// CHECK-LABEL: @test_mm512_maskz_sub_ps
- // CHECK: @llvm.x86.avx512.mask.sub.ps.512
+ // CHECK: fsub <16 x float> %{{.*}}, %{{.*}}
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_maskz_sub_ps(__U,__A,__B);
}
__m128 test_mm_sub_round_ss(__m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_sub_round_ss
// CHECK: @llvm.x86.avx512.mask.sub.ss.round
- return _mm_sub_round_ss(__A,__B,_MM_FROUND_TO_NEAREST_INT);
+ return _mm_sub_round_ss(__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128 test_mm_mask_sub_round_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_mask_sub_round_ss
// CHECK: @llvm.x86.avx512.mask.sub.ss.round
- return _mm_mask_sub_round_ss(__W,__U,__A,__B,_MM_FROUND_TO_NEAREST_INT);
+ return _mm_mask_sub_round_ss(__W,__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128 test_mm_maskz_sub_round_ss(__mmask8 __U, __m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_maskz_sub_round_ss
// CHECK: @llvm.x86.avx512.mask.sub.ss.round
- return _mm_maskz_sub_round_ss(__U,__A,__B,_MM_FROUND_TO_NEAREST_INT);
+ return _mm_maskz_sub_round_ss(__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128 test_mm_mask_sub_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_mask_sub_ss
@@ -1883,17 +2115,17 @@ __m128 test_mm_maskz_sub_ss(__mmask8 __U, __m128 __A, __m128 __B) {
__m128d test_mm_sub_round_sd(__m128d __A, __m128d __B) {
// CHECK-LABEL: @test_mm_sub_round_sd
// CHECK: @llvm.x86.avx512.mask.sub.sd.round
- return _mm_sub_round_sd(__A,__B,_MM_FROUND_TO_NEAREST_INT);
+ return _mm_sub_round_sd(__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128d test_mm_mask_sub_round_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
// CHECK-LABEL: @test_mm_mask_sub_round_sd
// CHECK: @llvm.x86.avx512.mask.sub.sd.round
- return _mm_mask_sub_round_sd(__W,__U,__A,__B,_MM_FROUND_TO_NEAREST_INT);
+ return _mm_mask_sub_round_sd(__W,__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128d test_mm_maskz_sub_round_sd(__mmask8 __U, __m128d __A, __m128d __B) {
// CHECK-LABEL: @test_mm_maskz_sub_round_sd
// CHECK: @llvm.x86.avx512.mask.sub.sd.round
- return _mm_maskz_sub_round_sd(__U,__A,__B,_MM_FROUND_TO_NEAREST_INT);
+ return _mm_maskz_sub_round_sd(__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128d test_mm_mask_sub_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
// CHECK-LABEL: @test_mm_mask_sub_sd
@@ -1908,67 +2140,71 @@ __m128d test_mm_maskz_sub_sd(__mmask8 __U, __m128d __A, __m128d __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
- return _mm512_mul_round_pd(__A,__B,_MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_mask_mul_round_pd(__W,__U,__A,__B,_MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_maskz_mul_round_pd(__U,__A,__B,_MM_FROUND_TO_NEAREST_INT);
+ 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) {
// CHECK-LABEL: @test_mm512_mask_mul_pd
- // CHECK: @llvm.x86.avx512.mask.mul.pd.512
+ // CHECK: fmul <8 x double> %{{.*}}, %{{.*}}
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask_mul_pd(__W,__U,__A,__B);
}
__m512d test_mm512_maskz_mul_pd(__mmask8 __U, __m512d __A, __m512d __B) {
// CHECK-LABEL: @test_mm512_maskz_mul_pd
- // CHECK: @llvm.x86.avx512.mask.mul.pd.512
+ // CHECK: fmul <8 x double> %{{.*}}, %{{.*}}
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_maskz_mul_pd(__U,__A,__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
- return _mm512_mul_round_ps(__A,__B,_MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_mask_mul_round_ps(__W,__U,__A,__B,_MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_maskz_mul_round_ps(__U,__A,__B,_MM_FROUND_TO_NEAREST_INT);
+ 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) {
// CHECK-LABEL: @test_mm512_mask_mul_ps
- // CHECK: @llvm.x86.avx512.mask.mul.ps.512
+ // CHECK: fmul <16 x float> %{{.*}}, %{{.*}}
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_mask_mul_ps(__W,__U,__A,__B);
}
__m512 test_mm512_maskz_mul_ps(__mmask16 __U, __m512 __A, __m512 __B) {
// CHECK-LABEL: @test_mm512_maskz_mul_ps
- // CHECK: @llvm.x86.avx512.mask.mul.ps.512
+ // CHECK: fmul <16 x float> %{{.*}}, %{{.*}}
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_maskz_mul_ps(__U,__A,__B);
}
__m128 test_mm_mul_round_ss(__m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_mul_round_ss
// CHECK: @llvm.x86.avx512.mask.mul.ss.round
- return _mm_mul_round_ss(__A,__B,_MM_FROUND_TO_NEAREST_INT);
+ return _mm_mul_round_ss(__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128 test_mm_mask_mul_round_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_mask_mul_round_ss
// CHECK: @llvm.x86.avx512.mask.mul.ss.round
- return _mm_mask_mul_round_ss(__W,__U,__A,__B,_MM_FROUND_TO_NEAREST_INT);
+ return _mm_mask_mul_round_ss(__W,__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128 test_mm_maskz_mul_round_ss(__mmask8 __U, __m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_maskz_mul_round_ss
// CHECK: @llvm.x86.avx512.mask.mul.ss.round
- return _mm_maskz_mul_round_ss(__U,__A,__B,_MM_FROUND_TO_NEAREST_INT);
+ return _mm_maskz_mul_round_ss(__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128 test_mm_mask_mul_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_mask_mul_ss
@@ -1983,17 +2219,17 @@ __m128 test_mm_maskz_mul_ss(__mmask8 __U, __m128 __A, __m128 __B) {
__m128d test_mm_mul_round_sd(__m128d __A, __m128d __B) {
// CHECK-LABEL: @test_mm_mul_round_sd
// CHECK: @llvm.x86.avx512.mask.mul.sd.round
- return _mm_mul_round_sd(__A,__B,_MM_FROUND_TO_NEAREST_INT);
+ return _mm_mul_round_sd(__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128d test_mm_mask_mul_round_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
// CHECK-LABEL: @test_mm_mask_mul_round_sd
// CHECK: @llvm.x86.avx512.mask.mul.sd.round
- return _mm_mask_mul_round_sd(__W,__U,__A,__B,_MM_FROUND_TO_NEAREST_INT);
+ return _mm_mask_mul_round_sd(__W,__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128d test_mm_maskz_mul_round_sd(__mmask8 __U, __m128d __A, __m128d __B) {
// CHECK-LABEL: @test_mm_maskz_mul_round_sd
// CHECK: @llvm.x86.avx512.mask.mul.sd.round
- return _mm_maskz_mul_round_sd(__U,__A,__B,_MM_FROUND_TO_NEAREST_INT);
+ return _mm_maskz_mul_round_sd(__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128d test_mm_mask_mul_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
// CHECK-LABEL: @test_mm_mask_mul_sd
@@ -2008,17 +2244,17 @@ __m128d test_mm_maskz_mul_sd(__mmask8 __U, __m128d __A, __m128d __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
- return _mm512_div_round_pd(__A,__B,_MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_mask_div_round_pd(__W,__U,__A,__B,_MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_maskz_div_round_pd(__U,__A,__B,_MM_FROUND_TO_NEAREST_INT);
+ 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
@@ -2027,28 +2263,30 @@ __m512d test_mm512_div_pd(__m512d __a, __m512d __b) {
}
__m512d test_mm512_mask_div_pd(__m512d __w, __mmask8 __u, __m512d __a, __m512d __b) {
// CHECK-LABLE: @test_mm512_mask_div_pd
- // CHECK: @llvm.x86.avx512.mask.div.pd.512
+ // 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);
}
__m512d test_mm512_maskz_div_pd(__mmask8 __U, __m512d __A, __m512d __B) {
// CHECK-LABEL: @test_mm512_maskz_div_pd
- // CHECK: @llvm.x86.avx512.mask.div.pd.512
+ // CHECK: fdiv <8 x double> %{{.*}}, %{{.*}}
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_maskz_div_pd(__U,__A,__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
- return _mm512_div_round_ps(__A,__B,_MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_mask_div_round_ps(__W,__U,__A,__B,_MM_FROUND_TO_NEAREST_INT);
+ 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
- return _mm512_maskz_div_round_ps(__U,__A,__B,_MM_FROUND_TO_NEAREST_INT);
+ 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) {
// CHECK-LABEL: @test_mm512_div_ps
@@ -2057,28 +2295,30 @@ __m512 test_mm512_div_ps(__m512 __A, __m512 __B) {
}
__m512 test_mm512_mask_div_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) {
// CHECK-LABEL: @test_mm512_mask_div_ps
- // CHECK: @llvm.x86.avx512.mask.div.ps.512
+ // CHECK: fdiv <16 x float> %{{.*}}, %{{.*}}
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_mask_div_ps(__W,__U,__A,__B);
}
__m512 test_mm512_maskz_div_ps(__mmask16 __U, __m512 __A, __m512 __B) {
// CHECK-LABEL: @test_mm512_maskz_div_ps
- // CHECK: @llvm.x86.avx512.mask.div.ps.512
+ // CHECK: fdiv <16 x float> %{{.*}}, %{{.*}}
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_maskz_div_ps(__U,__A,__B);
}
__m128 test_mm_div_round_ss(__m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_div_round_ss
// CHECK: @llvm.x86.avx512.mask.div.ss.round
- return _mm_div_round_ss(__A,__B,_MM_FROUND_TO_NEAREST_INT);
+ return _mm_div_round_ss(__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128 test_mm_mask_div_round_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_mask_div_round_ss
// CHECK: @llvm.x86.avx512.mask.div.ss.round
- return _mm_mask_div_round_ss(__W,__U,__A,__B,_MM_FROUND_TO_NEAREST_INT);
+ return _mm_mask_div_round_ss(__W,__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128 test_mm_maskz_div_round_ss(__mmask8 __U, __m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_maskz_div_round_ss
// CHECK: @llvm.x86.avx512.mask.div.ss.round
- return _mm_maskz_div_round_ss(__U,__A,__B,_MM_FROUND_TO_NEAREST_INT);
+ return _mm_maskz_div_round_ss(__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128 test_mm_mask_div_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_mask_div_ss
@@ -2093,17 +2333,17 @@ __m128 test_mm_maskz_div_ss(__mmask8 __U, __m128 __A, __m128 __B) {
__m128d test_mm_div_round_sd(__m128d __A, __m128d __B) {
// CHECK-LABEL: @test_mm_div_round_sd
// CHECK: @llvm.x86.avx512.mask.div.sd.round
- return _mm_div_round_sd(__A,__B,_MM_FROUND_TO_NEAREST_INT);
+ return _mm_div_round_sd(__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128d test_mm_mask_div_round_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
// CHECK-LABEL: @test_mm_mask_div_round_sd
// CHECK: @llvm.x86.avx512.mask.div.sd.round
- return _mm_mask_div_round_sd(__W,__U,__A,__B,_MM_FROUND_TO_NEAREST_INT);
+ return _mm_mask_div_round_sd(__W,__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128d test_mm_maskz_div_round_sd(__mmask8 __U, __m128d __A, __m128d __B) {
// CHECK-LABEL: @test_mm_maskz_div_round_sd
// CHECK: @llvm.x86.avx512.mask.div.sd.round
- return _mm_maskz_div_round_sd(__U,__A,__B,_MM_FROUND_TO_NEAREST_INT);
+ return _mm_maskz_div_round_sd(__U,__A,__B,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
}
__m128d test_mm_mask_div_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
// CHECK-LABEL: @test_mm_mask_div_sd
@@ -2242,181 +2482,201 @@ __m512i test_mm512_undefined_epi32() {
__m512i test_mm512_cvtepi8_epi32(__m128i __A) {
// CHECK-LABEL: @test_mm512_cvtepi8_epi32
- // CHECK: @llvm.x86.avx512.mask.pmovsxb.d.512
+ // CHECK: sext <16 x i8> %{{.*}} to <16 x i32>
return _mm512_cvtepi8_epi32(__A);
}
__m512i test_mm512_mask_cvtepi8_epi32(__m512i __W, __mmask16 __U, __m128i __A) {
// CHECK-LABEL: @test_mm512_mask_cvtepi8_epi32
- // CHECK: @llvm.x86.avx512.mask.pmovsxb.d.512
+ // CHECK: sext <16 x i8> %{{.*}} to <16 x i32>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_mask_cvtepi8_epi32(__W, __U, __A);
}
__m512i test_mm512_maskz_cvtepi8_epi32(__mmask16 __U, __m128i __A) {
// CHECK-LABEL: @test_mm512_maskz_cvtepi8_epi32
- // CHECK: @llvm.x86.avx512.mask.pmovsxb.d.512
+ // CHECK: sext <16 x i8> %{{.*}} to <16 x i32>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_maskz_cvtepi8_epi32(__U, __A);
}
__m512i test_mm512_cvtepi8_epi64(__m128i __A) {
// CHECK-LABEL: @test_mm512_cvtepi8_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovsxb.q.512
+ // CHECK: sext <8 x i8> %{{.*}} to <8 x i64>
return _mm512_cvtepi8_epi64(__A);
}
__m512i test_mm512_mask_cvtepi8_epi64(__m512i __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm512_mask_cvtepi8_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovsxb.q.512
+ // CHECK: sext <8 x i8> %{{.*}} to <8 x i64>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_mask_cvtepi8_epi64(__W, __U, __A);
}
__m512i test_mm512_maskz_cvtepi8_epi64(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm512_maskz_cvtepi8_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovsxb.q.512
+ // CHECK: sext <8 x i8> %{{.*}} to <8 x i64>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_maskz_cvtepi8_epi64(__U, __A);
}
__m512i test_mm512_cvtepi32_epi64(__m256i __X) {
// CHECK-LABEL: @test_mm512_cvtepi32_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovsxd.q.512
+ // CHECK: sext <8 x i32> %{{.*}} to <8 x i64>
return _mm512_cvtepi32_epi64(__X);
}
__m512i test_mm512_mask_cvtepi32_epi64(__m512i __W, __mmask8 __U, __m256i __X) {
// CHECK-LABEL: @test_mm512_mask_cvtepi32_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovsxd.q.512
+ // CHECK: sext <8 x i32> %{{.*}} to <8 x i64>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_mask_cvtepi32_epi64(__W, __U, __X);
}
__m512i test_mm512_maskz_cvtepi32_epi64(__mmask8 __U, __m256i __X) {
// CHECK-LABEL: @test_mm512_maskz_cvtepi32_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovsxd.q.512
+ // CHECK: sext <8 x i32> %{{.*}} to <8 x i64>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_maskz_cvtepi32_epi64(__U, __X);
}
__m512i test_mm512_cvtepi16_epi32(__m256i __A) {
// CHECK-LABEL: @test_mm512_cvtepi16_epi32
- // CHECK: @llvm.x86.avx512.mask.pmovsxw.d.512
+ // CHECK: sext <16 x i16> %{{.*}} to <16 x i32>
return _mm512_cvtepi16_epi32(__A);
}
__m512i test_mm512_mask_cvtepi16_epi32(__m512i __W, __mmask16 __U, __m256i __A) {
// CHECK-LABEL: @test_mm512_mask_cvtepi16_epi32
- // CHECK: @llvm.x86.avx512.mask.pmovsxw.d.512
+ // CHECK: sext <16 x i16> %{{.*}} to <16 x i32>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_mask_cvtepi16_epi32(__W, __U, __A);
}
__m512i test_mm512_maskz_cvtepi16_epi32(__mmask16 __U, __m256i __A) {
// CHECK-LABEL: @test_mm512_maskz_cvtepi16_epi32
- // CHECK: @llvm.x86.avx512.mask.pmovsxw.d.512
+ // CHECK: sext <16 x i16> %{{.*}} to <16 x i32>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_maskz_cvtepi16_epi32(__U, __A);
}
__m512i test_mm512_cvtepi16_epi64(__m128i __A) {
// CHECK-LABEL: @test_mm512_cvtepi16_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovsxw.q.512
+ // CHECK: sext <8 x i16> %{{.*}} to <8 x i64>
return _mm512_cvtepi16_epi64(__A);
}
__m512i test_mm512_mask_cvtepi16_epi64(__m512i __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm512_mask_cvtepi16_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovsxw.q.512
+ // CHECK: sext <8 x i16> %{{.*}} to <8 x i64>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_mask_cvtepi16_epi64(__W, __U, __A);
}
__m512i test_mm512_maskz_cvtepi16_epi64(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm512_maskz_cvtepi16_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovsxw.q.512
+ // CHECK: sext <8 x i16> %{{.*}} to <8 x i64>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_maskz_cvtepi16_epi64(__U, __A);
}
__m512i test_mm512_cvtepu8_epi32(__m128i __A) {
// CHECK-LABEL: @test_mm512_cvtepu8_epi32
- // CHECK: @llvm.x86.avx512.mask.pmovzxb.d.512
+ // CHECK: zext <16 x i8> %{{.*}} to <16 x i32>
return _mm512_cvtepu8_epi32(__A);
}
__m512i test_mm512_mask_cvtepu8_epi32(__m512i __W, __mmask16 __U, __m128i __A) {
// CHECK-LABEL: @test_mm512_mask_cvtepu8_epi32
- // CHECK: @llvm.x86.avx512.mask.pmovzxb.d.512
+ // CHECK: zext <16 x i8> %{{.*}} to <16 x i32>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_mask_cvtepu8_epi32(__W, __U, __A);
}
__m512i test_mm512_maskz_cvtepu8_epi32(__mmask16 __U, __m128i __A) {
// CHECK-LABEL: @test_mm512_maskz_cvtepu8_epi32
- // CHECK: @llvm.x86.avx512.mask.pmovzxb.d.512
+ // CHECK: zext <16 x i8> %{{.*}} to <16 x i32>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_maskz_cvtepu8_epi32(__U, __A);
}
__m512i test_mm512_cvtepu8_epi64(__m128i __A) {
// CHECK-LABEL: @test_mm512_cvtepu8_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovzxb.q.512
+ // CHECK: zext <8 x i8> %{{.*}} to <8 x i64>
return _mm512_cvtepu8_epi64(__A);
}
__m512i test_mm512_mask_cvtepu8_epi64(__m512i __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm512_mask_cvtepu8_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovzxb.q.512
+ // CHECK: zext <8 x i8> %{{.*}} to <8 x i64>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_mask_cvtepu8_epi64(__W, __U, __A);
}
__m512i test_mm512_maskz_cvtepu8_epi64(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm512_maskz_cvtepu8_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovzxb.q.512
+ // CHECK: zext <8 x i8> %{{.*}} to <8 x i64>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_maskz_cvtepu8_epi64(__U, __A);
}
__m512i test_mm512_cvtepu32_epi64(__m256i __X) {
// CHECK-LABEL: @test_mm512_cvtepu32_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovzxd.q.512
+ // CHECK: zext <8 x i32> %{{.*}} to <8 x i64>
return _mm512_cvtepu32_epi64(__X);
}
__m512i test_mm512_mask_cvtepu32_epi64(__m512i __W, __mmask8 __U, __m256i __X) {
// CHECK-LABEL: @test_mm512_mask_cvtepu32_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovzxd.q.512
+ // CHECK: zext <8 x i32> %{{.*}} to <8 x i64>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_mask_cvtepu32_epi64(__W, __U, __X);
}
__m512i test_mm512_maskz_cvtepu32_epi64(__mmask8 __U, __m256i __X) {
// CHECK-LABEL: @test_mm512_maskz_cvtepu32_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovzxd.q.512
+ // CHECK: zext <8 x i32> %{{.*}} to <8 x i64>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_maskz_cvtepu32_epi64(__U, __X);
}
__m512i test_mm512_cvtepu16_epi32(__m256i __A) {
// CHECK-LABEL: @test_mm512_cvtepu16_epi32
- // CHECK: @llvm.x86.avx512.mask.pmovzxw.d.512
+ // CHECK: zext <16 x i16> %{{.*}} to <16 x i32>
return _mm512_cvtepu16_epi32(__A);
}
__m512i test_mm512_mask_cvtepu16_epi32(__m512i __W, __mmask16 __U, __m256i __A) {
// CHECK-LABEL: @test_mm512_mask_cvtepu16_epi32
- // CHECK: @llvm.x86.avx512.mask.pmovzxw.d.512
+ // CHECK: zext <16 x i16> %{{.*}} to <16 x i32>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_mask_cvtepu16_epi32(__W, __U, __A);
}
__m512i test_mm512_maskz_cvtepu16_epi32(__mmask16 __U, __m256i __A) {
// CHECK-LABEL: @test_mm512_maskz_cvtepu16_epi32
- // CHECK: @llvm.x86.avx512.mask.pmovzxw.d.512
+ // CHECK: zext <16 x i16> %{{.*}} to <16 x i32>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_maskz_cvtepu16_epi32(__U, __A);
}
__m512i test_mm512_cvtepu16_epi64(__m128i __A) {
// CHECK-LABEL: @test_mm512_cvtepu16_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovzxw.q.512
+ // CHECK: zext <8 x i16> %{{.*}} to <8 x i64>
return _mm512_cvtepu16_epi64(__A);
}
__m512i test_mm512_mask_cvtepu16_epi64(__m512i __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm512_mask_cvtepu16_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovzxw.q.512
+ // CHECK: zext <8 x i16> %{{.*}} to <8 x i64>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_mask_cvtepu16_epi64(__W, __U, __A);
}
__m512i test_mm512_maskz_cvtepu16_epi64(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm512_maskz_cvtepu16_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovzxw.q.512
+ // CHECK: zext <8 x i16> %{{.*}} to <8 x i64>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_maskz_cvtepu16_epi64(__U, __A);
}
@@ -2568,73 +2828,80 @@ __m512i test_mm512_maskz_rorv_epi64(__mmask8 __U, __m512i __A, __m512i __B) {
__m512i test_mm512_slli_epi32(__m512i __A) {
// CHECK-LABEL: @test_mm512_slli_epi32
- // CHECK: @llvm.x86.avx512.mask.psll.di.512
+ // CHECK: @llvm.x86.avx512.pslli.d.512
return _mm512_slli_epi32(__A, 5);
}
__m512i test_mm512_mask_slli_epi32(__m512i __W, __mmask16 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_mask_slli_epi32
- // CHECK: @llvm.x86.avx512.mask.psll.di.512
+ // CHECK: @llvm.x86.avx512.pslli.d.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_mask_slli_epi32(__W, __U, __A, 5);
}
__m512i test_mm512_maskz_slli_epi32(__mmask16 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_maskz_slli_epi32
- // CHECK: @llvm.x86.avx512.mask.psll.di.512
+ // CHECK: @llvm.x86.avx512.pslli.d.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_maskz_slli_epi32(__U, __A, 5);
}
__m512i test_mm512_slli_epi64(__m512i __A) {
// CHECK-LABEL: @test_mm512_slli_epi64
- // CHECK: @llvm.x86.avx512.mask.psll.qi.512
+ // CHECK: @llvm.x86.avx512.pslli.q.512
return _mm512_slli_epi64(__A, 5);
}
__m512i test_mm512_mask_slli_epi64(__m512i __W, __mmask8 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_mask_slli_epi64
- // CHECK: @llvm.x86.avx512.mask.psll.qi.512
+ // CHECK: @llvm.x86.avx512.pslli.q.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_mask_slli_epi64(__W, __U, __A, 5);
}
__m512i test_mm512_maskz_slli_epi64(__mmask8 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_maskz_slli_epi64
- // CHECK: @llvm.x86.avx512.mask.psll.qi.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_maskz_slli_epi64(__U, __A, 5);
}
__m512i test_mm512_srli_epi32(__m512i __A) {
// CHECK-LABEL: @test_mm512_srli_epi32
- // CHECK: @llvm.x86.avx512.mask.psrl.di.512
+ // CHECK: @llvm.x86.avx512.psrli.d.512
return _mm512_srli_epi32(__A, 5);
}
__m512i test_mm512_mask_srli_epi32(__m512i __W, __mmask16 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_mask_srli_epi32
- // CHECK: @llvm.x86.avx512.mask.psrl.di.512
+ // CHECK: @llvm.x86.avx512.psrli.d.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_mask_srli_epi32(__W, __U, __A, 5);
}
__m512i test_mm512_maskz_srli_epi32(__mmask16 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_maskz_srli_epi32
- // CHECK: @llvm.x86.avx512.mask.psrl.di.512
+ // CHECK: @llvm.x86.avx512.psrli.d.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_maskz_srli_epi32(__U, __A, 5);
}
__m512i test_mm512_srli_epi64(__m512i __A) {
// CHECK-LABEL: @test_mm512_srli_epi64
- // CHECK: @llvm.x86.avx512.mask.psrl.qi.512
+ // CHECK: @llvm.x86.avx512.psrli.q.512
return _mm512_srli_epi64(__A, 5);
}
__m512i test_mm512_mask_srli_epi64(__m512i __W, __mmask8 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_mask_srli_epi64
- // CHECK: @llvm.x86.avx512.mask.psrl.qi.512
+ // CHECK: @llvm.x86.avx512.psrli.q.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_mask_srli_epi64(__W, __U, __A, 5);
}
__m512i test_mm512_maskz_srli_epi64(__mmask8 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_maskz_srli_epi64
- // CHECK: @llvm.x86.avx512.mask.psrl.qi.512
+ // CHECK: @llvm.x86.avx512.psrli.q.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_maskz_srli_epi64(__U, __A, 5);
}
@@ -2721,13 +2988,13 @@ __m512d test_mm512_maskz_movedup_pd(__mmask8 __U, __m512d __A) {
int test_mm_comi_round_sd(__m128d __A, __m128d __B) {
// CHECK-LABEL: @test_mm_comi_round_sd
// CHECK: @llvm.x86.avx512.vcomi.sd
- return _mm_comi_round_sd(__A, __B, 5, 3);
+ return _mm_comi_round_sd(__A, __B, 5, _MM_FROUND_NO_EXC);
}
int test_mm_comi_round_ss(__m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_comi_round_ss
// CHECK: @llvm.x86.avx512.vcomi.ss
- return _mm_comi_round_ss(__A, __B, 5, 3);
+ return _mm_comi_round_ss(__A, __B, 5, _MM_FROUND_NO_EXC);
}
__m512d test_mm512_fixupimm_round_pd(__m512d __A, __m512d __B, __m512i __C) {
@@ -2934,11 +3201,13 @@ __m512d test_mm512_mask_unpackhi_pd(__m512d __W, __mmask8 __U, __m512d __A, __m5
// CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask_unpackhi_pd(__W, __U, __A, __B);
}
+#if __x86_64__
unsigned long long test_mm_cvt_roundsd_si64(__m128d __A) {
// CHECK-LABEL: @test_mm_cvt_roundsd_si64
// CHECK: @llvm.x86.avx512.vcvtsd2si64
return _mm_cvt_roundsd_si64(__A, _MM_FROUND_CUR_DIRECTION);
}
+#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
@@ -2956,11 +3225,13 @@ __m512d test_mm512_maskz_unpackhi_pd(__mmask8 __U, __m512d __A, __m512d __B) {
// CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_maskz_unpackhi_pd(__U, __A, __B);
}
+#if __x86_64__
long long test_mm_cvt_roundsd_i64(__m128d __A) {
// CHECK-LABEL: @test_mm_cvt_roundsd_i64
// CHECK: @llvm.x86.avx512.vcvtsd2si64
return _mm_cvt_roundsd_i64(__A, _MM_FROUND_CUR_DIRECTION);
}
+#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
@@ -3038,6 +3309,7 @@ unsigned test_mm_cvtsd_u32(__m128d __A) {
return _mm_cvtsd_u32(__A);
}
+#ifdef __x86_64__
unsigned long long test_mm_cvt_roundsd_u64(__m128d __A) {
// CHECK-LABEL: @test_mm_cvt_roundsd_u64
// CHECK: @llvm.x86.avx512.vcvtsd2usi64
@@ -3049,6 +3321,7 @@ unsigned long long test_mm_cvtsd_u64(__m128d __A) {
// CHECK: @llvm.x86.avx512.vcvtsd2usi64
return _mm_cvtsd_u64(__A);
}
+#endif
int test_mm_cvt_roundss_si32(__m128 __A) {
// CHECK-LABEL: @test_mm_cvt_roundss_si32
@@ -3062,6 +3335,7 @@ int test_mm_cvt_roundss_i32(__m128 __A) {
return _mm_cvt_roundss_i32(__A, _MM_FROUND_CUR_DIRECTION);
}
+#ifdef __x86_64__
int test_mm_cvt_roundss_si64(__m128 __A) {
// CHECK-LABEL: @test_mm_cvt_roundss_si64
// CHECK: @llvm.x86.avx512.vcvtss2si64
@@ -3073,6 +3347,7 @@ long long test_mm_cvt_roundss_i64(__m128 __A) {
// CHECK: @llvm.x86.avx512.vcvtss2si64
return _mm_cvt_roundss_i64(__A, _MM_FROUND_CUR_DIRECTION);
}
+#endif
unsigned test_mm_cvt_roundss_u32(__m128 __A) {
// CHECK-LABEL: @test_mm_cvt_roundss_u32
@@ -3086,6 +3361,7 @@ unsigned test_mm_cvtss_u32(__m128 __A) {
return _mm_cvtss_u32(__A);
}
+#ifdef __x86_64__
unsigned long long test_mm_cvt_roundss_u64(__m128 __A) {
// CHECK-LABEL: @test_mm_cvt_roundss_u64
// CHECK: @llvm.x86.avx512.vcvtss2usi64
@@ -3097,6 +3373,7 @@ unsigned long long test_mm_cvtss_u64(__m128 __A) {
// CHECK: @llvm.x86.avx512.vcvtss2usi64
return _mm_cvtss_u64(__A);
}
+#endif
int test_mm_cvtt_roundsd_i32(__m128d __A) {
// CHECK-LABEL: @test_mm_cvtt_roundsd_i32
@@ -3116,6 +3393,7 @@ int test_mm_cvttsd_i32(__m128d __A) {
return _mm_cvttsd_i32(__A);
}
+#ifdef __x86_64__
unsigned long long test_mm_cvtt_roundsd_si64(__m128d __A) {
// CHECK-LABEL: @test_mm_cvtt_roundsd_si64
// CHECK: @llvm.x86.avx512.cvttsd2si64
@@ -3133,6 +3411,7 @@ long long test_mm_cvttsd_i64(__m128d __A) {
// CHECK: @llvm.x86.avx512.cvttsd2si64
return _mm_cvttsd_i64(__A);
}
+#endif
unsigned test_mm_cvtt_roundsd_u32(__m128d __A) {
// CHECK-LABEL: @test_mm_cvtt_roundsd_u32
@@ -3146,6 +3425,7 @@ unsigned test_mm_cvttsd_u32(__m128d __A) {
return _mm_cvttsd_u32(__A);
}
+#ifdef __x86_64__
unsigned long long test_mm_cvtt_roundsd_u64(__m128d __A) {
// CHECK-LABEL: @test_mm_cvtt_roundsd_u64
// CHECK: @llvm.x86.avx512.cvttsd2usi64
@@ -3157,6 +3437,7 @@ unsigned long long test_mm_cvttsd_u64(__m128d __A) {
// CHECK: @llvm.x86.avx512.cvttsd2usi64
return _mm_cvttsd_u64(__A);
}
+#endif
int test_mm_cvtt_roundss_i32(__m128 __A) {
// CHECK-LABEL: @test_mm_cvtt_roundss_i32
@@ -3176,6 +3457,7 @@ int test_mm_cvttss_i32(__m128 __A) {
return _mm_cvttss_i32(__A);
}
+#ifdef __x86_64__
float test_mm_cvtt_roundss_i64(__m128 __A) {
// CHECK-LABEL: @test_mm_cvtt_roundss_i64
// CHECK: @llvm.x86.avx512.cvttss2si64
@@ -3193,6 +3475,7 @@ long long test_mm_cvttss_i64(__m128 __A) {
// CHECK: @llvm.x86.avx512.cvttss2si64
return _mm_cvttss_i64(__A);
}
+#endif
unsigned test_mm_cvtt_roundss_u32(__m128 __A) {
// CHECK-LABEL: @test_mm_cvtt_roundss_u32
@@ -3206,6 +3489,7 @@ unsigned test_mm_cvttss_u32(__m128 __A) {
return _mm_cvttss_u32(__A);
}
+#ifdef __x86_64__
unsigned long long test_mm_cvtt_roundss_u64(__m128 __A) {
// CHECK-LABEL: @test_mm_cvtt_roundss_u64
// CHECK: @llvm.x86.avx512.cvttss2usi64
@@ -3217,6 +3501,7 @@ unsigned long long test_mm_cvttss_u64(__m128 __A) {
// CHECK: @llvm.x86.avx512.cvttss2usi64
return _mm_cvttss_u64(__A);
}
+#endif
__m512i test_mm512_cvtt_roundps_epu32(__m512 __A)
{
@@ -3469,37 +3754,41 @@ __m512 test_mm512_maskz_permute_ps(__mmask16 __U, __m512 __X) {
__m512d test_mm512_permutevar_pd(__m512d __A, __m512i __C) {
// CHECK-LABEL: @test_mm512_permutevar_pd
- // CHECK: @llvm.x86.avx512.mask.vpermilvar.pd.512
+ // CHECK: @llvm.x86.avx512.vpermilvar.pd.512
return _mm512_permutevar_pd(__A, __C);
}
__m512d test_mm512_mask_permutevar_pd(__m512d __W, __mmask8 __U, __m512d __A, __m512i __C) {
// CHECK-LABEL: @test_mm512_mask_permutevar_pd
- // CHECK: @llvm.x86.avx512.mask.vpermilvar.pd.512
+ // CHECK: @llvm.x86.avx512.vpermilvar.pd.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask_permutevar_pd(__W, __U, __A, __C);
}
__m512d test_mm512_maskz_permutevar_pd(__mmask8 __U, __m512d __A, __m512i __C) {
// CHECK-LABEL: @test_mm512_maskz_permutevar_pd
- // CHECK: @llvm.x86.avx512.mask.vpermilvar.pd.512
+ // CHECK: @llvm.x86.avx512.vpermilvar.pd.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_maskz_permutevar_pd(__U, __A, __C);
}
__m512 test_mm512_permutevar_ps(__m512 __A, __m512i __C) {
// CHECK-LABEL: @test_mm512_permutevar_ps
- // CHECK: @llvm.x86.avx512.mask.vpermilvar.ps.512
+ // CHECK: @llvm.x86.avx512.vpermilvar.ps.512
return _mm512_permutevar_ps(__A, __C);
}
__m512 test_mm512_mask_permutevar_ps(__m512 __W, __mmask16 __U, __m512 __A, __m512i __C) {
// CHECK-LABEL: @test_mm512_mask_permutevar_ps
- // CHECK: @llvm.x86.avx512.mask.vpermilvar.ps.512
+ // CHECK: @llvm.x86.avx512.vpermilvar.ps.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_mask_permutevar_ps(__W, __U, __A, __C);
}
__m512 test_mm512_maskz_permutevar_ps(__mmask16 __U, __m512 __A, __m512i __C) {
// CHECK-LABEL: @test_mm512_maskz_permutevar_ps
- // CHECK: @llvm.x86.avx512.mask.vpermilvar.ps.512
+ // CHECK: @llvm.x86.avx512.vpermilvar.ps.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_maskz_permutevar_ps(__U, __A, __C);
}
@@ -3880,253 +4169,281 @@ __m128 test_mm_maskz_scalef_round_ss(__mmask8 __U, __m128 __A, __m128 __B){
__m512i test_mm512_srai_epi32(__m512i __A) {
// CHECK-LABEL: @test_mm512_srai_epi32
- // CHECK: @llvm.x86.avx512.mask.psra.di.512
+ // CHECK: @llvm.x86.avx512.psrai.d.512
return _mm512_srai_epi32(__A, 5);
}
__m512i test_mm512_mask_srai_epi32(__m512i __W, __mmask16 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_mask_srai_epi32
- // CHECK: @llvm.x86.avx512.mask.psra.di.512
+ // CHECK: @llvm.x86.avx512.psrai.d.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_mask_srai_epi32(__W, __U, __A, 5);
}
__m512i test_mm512_maskz_srai_epi32(__mmask16 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_maskz_srai_epi32
- // CHECK: @llvm.x86.avx512.mask.psra.di.512
+ // CHECK: @llvm.x86.avx512.psrai.d.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_maskz_srai_epi32(__U, __A, 5);
}
__m512i test_mm512_srai_epi64(__m512i __A) {
// CHECK-LABEL: @test_mm512_srai_epi64
- // CHECK: @llvm.x86.avx512.mask.psra.qi.512
+ // CHECK: @llvm.x86.avx512.psrai.q.512
return _mm512_srai_epi64(__A, 5);
}
__m512i test_mm512_mask_srai_epi64(__m512i __W, __mmask8 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_mask_srai_epi64
- // CHECK: @llvm.x86.avx512.mask.psra.qi.512
+ // CHECK: @llvm.x86.avx512.psrai.q.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_mask_srai_epi64(__W, __U, __A, 5);
}
__m512i test_mm512_maskz_srai_epi64(__mmask8 __U, __m512i __A) {
// CHECK-LABEL: @test_mm512_maskz_srai_epi64
- // CHECK: @llvm.x86.avx512.mask.psra.qi.512
+ // CHECK: @llvm.x86.avx512.psrai.q.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_maskz_srai_epi64(__U, __A, 5);
}
__m512i test_mm512_sll_epi32(__m512i __A, __m128i __B) {
// CHECK-LABEL: @test_mm512_sll_epi32
- // CHECK: @llvm.x86.avx512.mask.psll.d
+ // CHECK: @llvm.x86.avx512.psll.d.512
return _mm512_sll_epi32(__A, __B);
}
__m512i test_mm512_mask_sll_epi32(__m512i __W, __mmask16 __U, __m512i __A, __m128i __B) {
// CHECK-LABEL: @test_mm512_mask_sll_epi32
- // CHECK: @llvm.x86.avx512.mask.psll.d
+ // CHECK: @llvm.x86.avx512.psll.d.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_mask_sll_epi32(__W, __U, __A, __B);
}
__m512i test_mm512_maskz_sll_epi32(__mmask16 __U, __m512i __A, __m128i __B) {
// CHECK-LABEL: @test_mm512_maskz_sll_epi32
- // CHECK: @llvm.x86.avx512.mask.psll.d
+ // CHECK: @llvm.x86.avx512.psll.d.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_maskz_sll_epi32(__U, __A, __B);
}
__m512i test_mm512_sll_epi64(__m512i __A, __m128i __B) {
// CHECK-LABEL: @test_mm512_sll_epi64
- // CHECK: @llvm.x86.avx512.mask.psll.q
+ // CHECK: @llvm.x86.avx512.psll.q.512
return _mm512_sll_epi64(__A, __B);
}
__m512i test_mm512_mask_sll_epi64(__m512i __W, __mmask8 __U, __m512i __A, __m128i __B) {
// CHECK-LABEL: @test_mm512_mask_sll_epi64
- // CHECK: @llvm.x86.avx512.mask.psll.q
+ // CHECK: @llvm.x86.avx512.psll.q.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_mask_sll_epi64(__W, __U, __A, __B);
}
__m512i test_mm512_maskz_sll_epi64(__mmask8 __U, __m512i __A, __m128i __B) {
// CHECK-LABEL: @test_mm512_maskz_sll_epi64
- // CHECK: @llvm.x86.avx512.mask.psll.q
+ // CHECK: @llvm.x86.avx512.psll.q.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_maskz_sll_epi64(__U, __A, __B);
}
__m512i test_mm512_sllv_epi32(__m512i __X, __m512i __Y) {
// CHECK-LABEL: @test_mm512_sllv_epi32
- // CHECK: @llvm.x86.avx512.mask.psllv.d
+ // CHECK: @llvm.x86.avx512.psllv.d.512
return _mm512_sllv_epi32(__X, __Y);
}
__m512i test_mm512_mask_sllv_epi32(__m512i __W, __mmask16 __U, __m512i __X, __m512i __Y) {
// CHECK-LABEL: @test_mm512_mask_sllv_epi32
- // CHECK: @llvm.x86.avx512.mask.psllv.d
+ // CHECK: @llvm.x86.avx512.psllv.d.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_mask_sllv_epi32(__W, __U, __X, __Y);
}
__m512i test_mm512_maskz_sllv_epi32(__mmask16 __U, __m512i __X, __m512i __Y) {
// CHECK-LABEL: @test_mm512_maskz_sllv_epi32
- // CHECK: @llvm.x86.avx512.mask.psllv.d
+ // CHECK: @llvm.x86.avx512.psllv.d.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_maskz_sllv_epi32(__U, __X, __Y);
}
__m512i test_mm512_sllv_epi64(__m512i __X, __m512i __Y) {
// CHECK-LABEL: @test_mm512_sllv_epi64
- // CHECK: @llvm.x86.avx512.mask.psllv.q
+ // CHECK: @llvm.x86.avx512.psllv.q.512
return _mm512_sllv_epi64(__X, __Y);
}
__m512i test_mm512_mask_sllv_epi64(__m512i __W, __mmask8 __U, __m512i __X, __m512i __Y) {
// CHECK-LABEL: @test_mm512_mask_sllv_epi64
- // CHECK: @llvm.x86.avx512.mask.psllv.q
+ // CHECK: @llvm.x86.avx512.psllv.q.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_mask_sllv_epi64(__W, __U, __X, __Y);
}
__m512i test_mm512_maskz_sllv_epi64(__mmask8 __U, __m512i __X, __m512i __Y) {
// CHECK-LABEL: @test_mm512_maskz_sllv_epi64
- // CHECK: @llvm.x86.avx512.mask.psllv.q
+ // CHECK: @llvm.x86.avx512.psllv.q.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_maskz_sllv_epi64(__U, __X, __Y);
}
__m512i test_mm512_sra_epi32(__m512i __A, __m128i __B) {
// CHECK-LABEL: @test_mm512_sra_epi32
- // CHECK: @llvm.x86.avx512.mask.psra.d
+ // CHECK: @llvm.x86.avx512.psra.d.512
return _mm512_sra_epi32(__A, __B);
}
__m512i test_mm512_mask_sra_epi32(__m512i __W, __mmask16 __U, __m512i __A, __m128i __B) {
// CHECK-LABEL: @test_mm512_mask_sra_epi32
- // CHECK: @llvm.x86.avx512.mask.psra.d
+ // CHECK: @llvm.x86.avx512.psra.d.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_mask_sra_epi32(__W, __U, __A, __B);
}
__m512i test_mm512_maskz_sra_epi32(__mmask16 __U, __m512i __A, __m128i __B) {
// CHECK-LABEL: @test_mm512_maskz_sra_epi32
- // CHECK: @llvm.x86.avx512.mask.psra.d
+ // CHECK: @llvm.x86.avx512.psra.d.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_maskz_sra_epi32(__U, __A, __B);
}
__m512i test_mm512_sra_epi64(__m512i __A, __m128i __B) {
// CHECK-LABEL: @test_mm512_sra_epi64
- // CHECK: @llvm.x86.avx512.mask.psra.q
+ // CHECK: @llvm.x86.avx512.psra.q.512
return _mm512_sra_epi64(__A, __B);
}
__m512i test_mm512_mask_sra_epi64(__m512i __W, __mmask8 __U, __m512i __A, __m128i __B) {
// CHECK-LABEL: @test_mm512_mask_sra_epi64
- // CHECK: @llvm.x86.avx512.mask.psra.q
+ // CHECK: @llvm.x86.avx512.psra.q.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_mask_sra_epi64(__W, __U, __A, __B);
}
__m512i test_mm512_maskz_sra_epi64(__mmask8 __U, __m512i __A, __m128i __B) {
// CHECK-LABEL: @test_mm512_maskz_sra_epi64
- // CHECK: @llvm.x86.avx512.mask.psra.q
+ // CHECK: @llvm.x86.avx512.psra.q.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_maskz_sra_epi64(__U, __A, __B);
}
__m512i test_mm512_srav_epi32(__m512i __X, __m512i __Y) {
// CHECK-LABEL: @test_mm512_srav_epi32
- // CHECK: @llvm.x86.avx512.mask.psrav.d
+ // CHECK: @llvm.x86.avx512.psrav.d.512
return _mm512_srav_epi32(__X, __Y);
}
__m512i test_mm512_mask_srav_epi32(__m512i __W, __mmask16 __U, __m512i __X, __m512i __Y) {
// CHECK-LABEL: @test_mm512_mask_srav_epi32
- // CHECK: @llvm.x86.avx512.mask.psrav.d
+ // CHECK: @llvm.x86.avx512.psrav.d.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_mask_srav_epi32(__W, __U, __X, __Y);
}
__m512i test_mm512_maskz_srav_epi32(__mmask16 __U, __m512i __X, __m512i __Y) {
// CHECK-LABEL: @test_mm512_maskz_srav_epi32
- // CHECK: @llvm.x86.avx512.mask.psrav.d
+ // CHECK: @llvm.x86.avx512.psrav.d.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_maskz_srav_epi32(__U, __X, __Y);
}
__m512i test_mm512_srav_epi64(__m512i __X, __m512i __Y) {
// CHECK-LABEL: @test_mm512_srav_epi64
- // CHECK: @llvm.x86.avx512.mask.psrav.q
+ // CHECK: @llvm.x86.avx512.psrav.q.512
return _mm512_srav_epi64(__X, __Y);
}
__m512i test_mm512_mask_srav_epi64(__m512i __W, __mmask8 __U, __m512i __X, __m512i __Y) {
// CHECK-LABEL: @test_mm512_mask_srav_epi64
- // CHECK: @llvm.x86.avx512.mask.psrav.q
+ // CHECK: @llvm.x86.avx512.psrav.q.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_mask_srav_epi64(__W, __U, __X, __Y);
}
__m512i test_mm512_maskz_srav_epi64(__mmask8 __U, __m512i __X, __m512i __Y) {
// CHECK-LABEL: @test_mm512_maskz_srav_epi64
- // CHECK: @llvm.x86.avx512.mask.psrav.q
+ // CHECK: @llvm.x86.avx512.psrav.q.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_maskz_srav_epi64(__U, __X, __Y);
}
__m512i test_mm512_srl_epi32(__m512i __A, __m128i __B) {
// CHECK-LABEL: @test_mm512_srl_epi32
- // CHECK: @llvm.x86.avx512.mask.psrl.d
+ // CHECK: @llvm.x86.avx512.psrl.d.512
return _mm512_srl_epi32(__A, __B);
}
__m512i test_mm512_mask_srl_epi32(__m512i __W, __mmask16 __U, __m512i __A, __m128i __B) {
// CHECK-LABEL: @test_mm512_mask_srl_epi32
- // CHECK: @llvm.x86.avx512.mask.psrl.d
+ // CHECK: @llvm.x86.avx512.psrl.d.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_mask_srl_epi32(__W, __U, __A, __B);
}
__m512i test_mm512_maskz_srl_epi32(__mmask16 __U, __m512i __A, __m128i __B) {
// CHECK-LABEL: @test_mm512_maskz_srl_epi32
- // CHECK: @llvm.x86.avx512.mask.psrl.d
+ // CHECK: @llvm.x86.avx512.psrl.d.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_maskz_srl_epi32(__U, __A, __B);
}
__m512i test_mm512_srl_epi64(__m512i __A, __m128i __B) {
// CHECK-LABEL: @test_mm512_srl_epi64
- // CHECK: @llvm.x86.avx512.mask.psrl.q
+ // CHECK: @llvm.x86.avx512.psrl.q.512
return _mm512_srl_epi64(__A, __B);
}
__m512i test_mm512_mask_srl_epi64(__m512i __W, __mmask8 __U, __m512i __A, __m128i __B) {
// CHECK-LABEL: @test_mm512_mask_srl_epi64
- // CHECK: @llvm.x86.avx512.mask.psrl.q
+ // CHECK: @llvm.x86.avx512.psrl.q.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_mask_srl_epi64(__W, __U, __A, __B);
}
__m512i test_mm512_maskz_srl_epi64(__mmask8 __U, __m512i __A, __m128i __B) {
// CHECK-LABEL: @test_mm512_maskz_srl_epi64
- // CHECK: @llvm.x86.avx512.mask.psrl.q
+ // CHECK: @llvm.x86.avx512.psrl.q.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_maskz_srl_epi64(__U, __A, __B);
}
__m512i test_mm512_srlv_epi32(__m512i __X, __m512i __Y) {
// CHECK-LABEL: @test_mm512_srlv_epi32
- // CHECK: @llvm.x86.avx512.mask.psrlv.d
+ // CHECK: @llvm.x86.avx512.psrlv.d.512
return _mm512_srlv_epi32(__X, __Y);
}
__m512i test_mm512_mask_srlv_epi32(__m512i __W, __mmask16 __U, __m512i __X, __m512i __Y) {
// CHECK-LABEL: @test_mm512_mask_srlv_epi32
- // CHECK: @llvm.x86.avx512.mask.psrlv.d
+ // CHECK: @llvm.x86.avx512.psrlv.d.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_mask_srlv_epi32(__W, __U, __X, __Y);
}
__m512i test_mm512_maskz_srlv_epi32(__mmask16 __U, __m512i __X, __m512i __Y) {
// CHECK-LABEL: @test_mm512_maskz_srlv_epi32
- // CHECK: @llvm.x86.avx512.mask.psrlv.d
+ // CHECK: @llvm.x86.avx512.psrlv.d.512
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_maskz_srlv_epi32(__U, __X, __Y);
}
__m512i test_mm512_srlv_epi64(__m512i __X, __m512i __Y) {
// CHECK-LABEL: @test_mm512_srlv_epi64
- // CHECK: @llvm.x86.avx512.mask.psrlv.q
+ // CHECK: @llvm.x86.avx512.psrlv.q.512
return _mm512_srlv_epi64(__X, __Y);
}
__m512i test_mm512_mask_srlv_epi64(__m512i __W, __mmask8 __U, __m512i __X, __m512i __Y) {
// CHECK-LABEL: @test_mm512_mask_srlv_epi64
- // CHECK: @llvm.x86.avx512.mask.psrlv.q
+ // CHECK: @llvm.x86.avx512.psrlv.q.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_mask_srlv_epi64(__W, __U, __X, __Y);
}
__m512i test_mm512_maskz_srlv_epi64(__mmask8 __U, __m512i __X, __m512i __Y) {
// CHECK-LABEL: @test_mm512_maskz_srlv_epi64
- // CHECK: @llvm.x86.avx512.mask.psrlv.q
+ // CHECK: @llvm.x86.avx512.psrlv.q.512
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_maskz_srlv_epi64(__U, __X, __Y);
}
@@ -4844,109 +5161,121 @@ 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: @llvm.x86.avx512.mask.vextracti32x4
+ // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <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: @llvm.x86.avx512.mask.vextracti32x4
+ // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <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: @llvm.x86.avx512.mask.vextracti32x4
+ // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <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: @llvm.x86.avx512.mask.vextracti64x4
+ // 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: @llvm.x86.avx512.mask.vextracti64x4
+ // 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: @llvm.x86.avx512.mask.vextracti64x4
+ // 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);
}
__m512d test_mm512_insertf64x4(__m512d __A, __m256d __B) {
// CHECK-LABEL: @test_mm512_insertf64x4
- // CHECK: @llvm.x86.avx512.mask.insertf64x4
+ // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 8, i32 9, i32 10, i32 11>
return _mm512_insertf64x4(__A, __B, 1);
}
__m512d test_mm512_mask_insertf64x4(__m512d __W, __mmask8 __U, __m512d __A, __m256d __B) {
// CHECK-LABEL: @test_mm512_mask_insertf64x4
- // CHECK: @llvm.x86.avx512.mask.insertf64x4
+ // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 8, i32 9, i32 10, i32 11>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_mask_insertf64x4(__W, __U, __A, __B, 1);
}
__m512d test_mm512_maskz_insertf64x4(__mmask8 __U, __m512d __A, __m256d __B) {
// CHECK-LABEL: @test_mm512_maskz_insertf64x4
- // CHECK: @llvm.x86.avx512.mask.insertf64x4
+ // CHECK: shufflevector <8 x double> %{{.*}}, <8 x double> %{{.*}}, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 8, i32 9, i32 10, i32 11>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}}
return _mm512_maskz_insertf64x4(__U, __A, __B, 1);
}
__m512i test_mm512_inserti64x4(__m512i __A, __m256i __B) {
// CHECK-LABEL: @test_mm512_inserti64x4
- // CHECK: @llvm.x86.avx512.mask.inserti64x4
+ // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> %{{.*}}, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 8, i32 9, i32 10, i32 11>
return _mm512_inserti64x4(__A, __B, 1);
}
__m512i test_mm512_mask_inserti64x4(__m512i __W, __mmask8 __U, __m512i __A, __m256i __B) {
// CHECK-LABEL: @test_mm512_mask_inserti64x4
- // CHECK: @llvm.x86.avx512.mask.inserti64x4
+ // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> %{{.*}}, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 8, i32 9, i32 10, i32 11>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_mask_inserti64x4(__W, __U, __A, __B, 1);
}
__m512i test_mm512_maskz_inserti64x4(__mmask8 __U, __m512i __A, __m256i __B) {
// CHECK-LABEL: @test_mm512_maskz_inserti64x4
- // CHECK: @llvm.x86.avx512.mask.inserti64x4
+ // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> %{{.*}}, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 8, i32 9, i32 10, i32 11>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}}
return _mm512_maskz_inserti64x4(__U, __A, __B, 1);
}
__m512 test_mm512_insertf32x4(__m512 __A, __m128 __B) {
// CHECK-LABEL: @test_mm512_insertf32x4
- // CHECK: @llvm.x86.avx512.mask.insertf32x4
+ // CHECK: shufflevector <16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 16, i32 17, i32 18, i32 19, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
return _mm512_insertf32x4(__A, __B, 1);
}
__m512 test_mm512_mask_insertf32x4(__m512 __W, __mmask16 __U, __m512 __A, __m128 __B) {
// CHECK-LABEL: @test_mm512_mask_insertf32x4
- // CHECK: @llvm.x86.avx512.mask.insertf32x4
+ // CHECK: shufflevector <16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 16, i32 17, i32 18, i32 19, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_mask_insertf32x4(__W, __U, __A, __B, 1);
}
__m512 test_mm512_maskz_insertf32x4(__mmask16 __U, __m512 __A, __m128 __B) {
// CHECK-LABEL: @test_mm512_maskz_insertf32x4
- // CHECK: @llvm.x86.avx512.mask.insertf32x4
+ // CHECK: shufflevector <16 x float> %{{.*}}, <16 x float> %{{.*}}, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 16, i32 17, i32 18, i32 19, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}}
return _mm512_maskz_insertf32x4(__U, __A, __B, 1);
}
__m512i test_mm512_inserti32x4(__m512i __A, __m128i __B) {
// CHECK-LABEL: @test_mm512_inserti32x4
- // CHECK: @llvm.x86.avx512.mask.inserti32x4
+ // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 16, i32 17, i32 18, i32 19, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
return _mm512_inserti32x4(__A, __B, 1);
}
__m512i test_mm512_mask_inserti32x4(__m512i __W, __mmask16 __U, __m512i __A, __m128i __B) {
// CHECK-LABEL: @test_mm512_mask_inserti32x4
- // CHECK: @llvm.x86.avx512.mask.inserti32x4
+ // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 16, i32 17, i32 18, i32 19, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_mask_inserti32x4(__W, __U, __A, __B, 1);
}
__m512i test_mm512_maskz_inserti32x4(__mmask16 __U, __m512i __A, __m128i __B) {
// CHECK-LABEL: @test_mm512_maskz_inserti32x4
- // CHECK: @llvm.x86.avx512.mask.inserti32x4
+ // CHECK: shufflevector <16 x i32> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 16, i32 17, i32 18, i32 19, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}}
return _mm512_maskz_inserti32x4(__U, __A, __B, 1);
}
@@ -5520,13 +5849,13 @@ __m128 test_mm_maskz_fmsub_round_ss(__mmask8 __U, __m128 __A, __m128 __B, __m128
__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.vfmadd.ss
+ // CHECK: @llvm.x86.avx512.mask3.vfmsub.ss
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.vfmadd.ss
+ // CHECK: @llvm.x86.avx512.mask3.vfmsub.ss
return _mm_mask3_fmsub_round_ss(__W, __X, __Y, __U, _MM_FROUND_CUR_DIRECTION);
}
@@ -5592,13 +5921,13 @@ __m128 test_mm_maskz_fnmsub_round_ss(__mmask8 __U, __m128 __A, __m128 __B, __m12
__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.vfmadd.ss
+ // CHECK: @llvm.x86.avx512.mask3.vfnmsub.ss
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.vfmadd.ss
+ // CHECK: @llvm.x86.avx512.mask3.vfnmsub.ss
return _mm_mask3_fnmsub_round_ss(__W, __X, __Y, __U, _MM_FROUND_CUR_DIRECTION);
}
@@ -5664,13 +5993,13 @@ __m128d test_mm_maskz_fmsub_round_sd(__mmask8 __U, __m128d __A, __m128d __B, __m
__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.vfmadd.sd
+ // CHECK: @llvm.x86.avx512.mask3.vfmsub.sd
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.vfmadd.sd
+ // CHECK: @llvm.x86.avx512.mask3.vfmsub.sd
return _mm_mask3_fmsub_round_sd(__W, __X, __Y, __U, _MM_FROUND_CUR_DIRECTION);
}
@@ -5736,13 +6065,13 @@ __m128d test_mm_maskz_fnmsub_round_sd(__mmask8 __U, __m128d __A, __m128d __B, __
__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.vfmadd.sd
+ // CHECK: @llvm.x86.avx512.mask3.vfnmsub.sd
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.vfmadd.sd
+ // CHECK: @llvm.x86.avx512.mask3.vfnmsub.sd
return _mm_mask3_fnmsub_round_sd(__W, __X, __Y, __U, _MM_FROUND_CUR_DIRECTION);
}
@@ -6192,12 +6521,26 @@ __m512d test_mm512_cvtps_pd(__m256 __A) {
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
+ 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
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
+ 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
@@ -6491,6 +6834,7 @@ __m128 test_mm_maskz_cvt_roundsd_ss(__mmask8 __U, __m128 __A, __m128d __B) {
return _mm_maskz_cvt_roundsd_ss(__U, __A, __B, _MM_FROUND_CUR_DIRECTION);
}
+#ifdef __x86_64__
__m128d test_mm_cvt_roundi64_sd(__m128d __A, long long __B) {
// CHECK-LABEL: @test_mm_cvt_roundi64_sd
// CHECK: @llvm.x86.avx512.cvtsi2sd64
@@ -6502,6 +6846,7 @@ __m128d test_mm_cvt_roundsi64_sd(__m128d __A, long long __B) {
// CHECK: @llvm.x86.avx512.cvtsi2sd64
return _mm_cvt_roundsi64_sd(__A, __B, _MM_FROUND_CUR_DIRECTION);
}
+#endif
__m128 test_mm_cvt_roundsi32_ss(__m128 __A, int __B) {
// CHECK-LABEL: @test_mm_cvt_roundsi32_ss
@@ -6515,6 +6860,7 @@ __m128 test_mm_cvt_roundi32_ss(__m128 __A, int __B) {
return _mm_cvt_roundi32_ss(__A, __B, _MM_FROUND_CUR_DIRECTION);
}
+#ifdef __x86_64__
__m128 test_mm_cvt_roundsi64_ss(__m128 __A, long long __B) {
// CHECK-LABEL: @test_mm_cvt_roundsi64_ss
// CHECK: @llvm.x86.avx512.cvtsi2ss64
@@ -6526,6 +6872,7 @@ __m128 test_mm_cvt_roundi64_ss(__m128 __A, long long __B) {
// CHECK: @llvm.x86.avx512.cvtsi2ss64
return _mm_cvt_roundi64_ss(__A, __B, _MM_FROUND_CUR_DIRECTION);
}
+#endif
__m128d test_mm_cvt_roundss_sd(__m128d __A, __m128 __B) {
// CHECK-LABEL: @test_mm_cvt_roundss_sd
@@ -6551,6 +6898,7 @@ __m128d test_mm_cvtu32_sd(__m128d __A, unsigned __B) {
return _mm_cvtu32_sd(__A, __B);
}
+#ifdef __x86_64__
__m128d test_mm_cvt_roundu64_sd(__m128d __A, unsigned long long __B) {
// CHECK-LABEL: @test_mm_cvt_roundu64_sd
// CHECK: @llvm.x86.avx512.cvtusi642sd
@@ -6562,6 +6910,7 @@ __m128d test_mm_cvtu64_sd(__m128d __A, unsigned long long __B) {
// CHECK: @llvm.x86.avx512.cvtusi642sd
return _mm_cvtu64_sd(__A, __B);
}
+#endif
__m128 test_mm_cvt_roundu32_ss(__m128 __A, unsigned __B) {
// CHECK-LABEL: @test_mm_cvt_roundu32_ss
@@ -6575,6 +6924,7 @@ __m128 test_mm_cvtu32_ss(__m128 __A, unsigned __B) {
return _mm_cvtu32_ss(__A, __B);
}
+#ifdef __x86_64__
__m128 test_mm_cvt_roundu64_ss(__m128 __A, unsigned long long __B) {
// CHECK-LABEL: @test_mm_cvt_roundu64_ss
// CHECK: @llvm.x86.avx512.cvtusi642ss
@@ -6586,6 +6936,7 @@ __m128 test_mm_cvtu64_ss(__m128 __A, unsigned long long __B) {
// CHECK: @llvm.x86.avx512.cvtusi642ss
return _mm_cvtu64_ss(__A, __B);
}
+#endif
__m512i test_mm512_mask_cvttps_epu32 (__m512i __W, __mmask16 __U, __m512 __A)
{
@@ -6622,20 +6973,46 @@ __m512 test_mm512_maskz_cvtepu32_ps (__mmask16 __U, __m512i __A)
return _mm512_maskz_cvtepu32_ps (__U,__A);
}
+__m512d test_mm512_cvtepi32_pd (__m256i __A)
+{
+ // CHECK-LABEL: @test_mm512_cvtepi32_pd
+ // CHECK: sitofp <8 x i32> %{{.*}} to <8 x double>
+ return _mm512_cvtepi32_pd (__A);
+}
+
__m512d test_mm512_mask_cvtepi32_pd (__m512d __W, __mmask8 __U, __m256i __A)
{
- // CHECK-LABEL: @test_mm512_mask_cvtepi32_pd
- // CHECK: @llvm.x86.avx512.mask.cvtdq2pd.512
+ // CHECK-LABEL: @test_mm512_mask_cvtepi32_pd
+ // CHECK: sitofp <8 x i32> %{{.*}} to <8 x double>
+ // CHECK: select <8 x i1> {{.*}}, <8 x double> {{.*}}, <8 x double> {{.*}}
return _mm512_mask_cvtepi32_pd (__W,__U,__A);
}
__m512d test_mm512_maskz_cvtepi32_pd (__mmask8 __U, __m256i __A)
{
- // CHECK-LABEL: @test_mm512_maskz_cvtepi32_pd
- // CHECK: @llvm.x86.avx512.mask.cvtdq2pd.512
+ // CHECK-LABEL: @test_mm512_maskz_cvtepi32_pd
+ // CHECK: sitofp <8 x i32> %{{.*}} to <8 x double>
+ // CHECK: select <8 x i1> {{.*}}, <8 x double> {{.*}}, <8 x double> {{.*}}
return _mm512_maskz_cvtepi32_pd (__U,__A);
}
+__m512d test_mm512_cvtepi32lo_pd (__m512i __A)
+{
+ // CHECK-LABEL: @test_mm512_cvtepi32lo_pd
+ // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ // CHECK: sitofp <8 x i32> %{{.*}} to <8 x double>
+ return _mm512_cvtepi32lo_pd (__A);
+}
+
+__m512d test_mm512_mask_cvtepi32lo_pd (__m512d __W, __mmask8 __U, __m512i __A)
+{
+ // CHECK-LABEL: @test_mm512_mask_cvtepi32lo_pd
+ // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ // CHECK: sitofp <8 x i32> %{{.*}} to <8 x double>
+ // CHECK: select <8 x i1> {{.*}}, <8 x double> {{.*}}, <8 x double> {{.*}}
+ return _mm512_mask_cvtepi32lo_pd (__W, __U, __A);
+}
+
__m512 test_mm512_cvtepi32_ps (__m512i __A)
{
// CHECK-LABEL: @test_mm512_cvtepi32_ps
@@ -6657,20 +7034,46 @@ __m512 test_mm512_maskz_cvtepi32_ps (__mmask16 __U, __m512i __A)
return _mm512_maskz_cvtepi32_ps (__U,__A);
}
+__m512d test_mm512_cvtepu32_pd(__m256i __A)
+{
+ // CHECK-LABEL: @test_mm512_cvtepu32_pd
+ // CHECK: uitofp <8 x i32> %{{.*}} to <8 x double>
+ return _mm512_cvtepu32_pd(__A);
+}
+
__m512d test_mm512_mask_cvtepu32_pd (__m512d __W, __mmask8 __U, __m256i __A)
{
- // CHECK-LABEL: @test_mm512_mask_cvtepu32_pd
- // CHECK: @llvm.x86.avx512.mask.cvtudq2pd.512
+ // CHECK-LABEL: @test_mm512_mask_cvtepu32_pd
+ // CHECK: uitofp <8 x i32> %{{.*}} to <8 x double>
+ // CHECK: select <8 x i1> {{.*}}, <8 x double> {{.*}}, <8 x double> {{.*}}
return _mm512_mask_cvtepu32_pd (__W,__U,__A);
}
__m512d test_mm512_maskz_cvtepu32_pd (__mmask8 __U, __m256i __A)
{
- // CHECK-LABEL: @test_mm512_maskz_cvtepu32_pd
- // CHECK: @llvm.x86.avx512.mask.cvtudq2pd.512
+ // CHECK-LABEL: @test_mm512_maskz_cvtepu32_pd
+ // CHECK: uitofp <8 x i32> %{{.*}} to <8 x double>
+ // CHECK: select <8 x i1> {{.*}}, <8 x double> {{.*}}, <8 x double> {{.*}}
return _mm512_maskz_cvtepu32_pd (__U,__A);
}
+__m512d test_mm512_cvtepu32lo_pd (__m512i __A)
+{
+ // CHECK-LABEL: @test_mm512_cvtepu32lo_pd
+ // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ // CHECK: uitofp <8 x i32> %{{.*}} to <8 x double>
+ return _mm512_cvtepu32lo_pd (__A);
+}
+
+__m512d test_mm512_mask_cvtepu32lo_pd (__m512d __W, __mmask8 __U, __m512i __A)
+{
+ // CHECK-LABEL: @test_mm512_mask_cvtepu32lo_pd
+ // CHECK: shufflevector <8 x i64> %{{.*}}, <8 x i64> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ // CHECK: uitofp <8 x i32> %{{.*}} to <8 x double>
+ // CHECK: select <8 x i1> {{.*}}, <8 x double> {{.*}}, <8 x double> {{.*}}
+ return _mm512_mask_cvtepu32lo_pd (__W, __U, __A);
+}
+
__m256 test_mm512_cvtpd_ps (__m512d __A)
{
// CHECK-LABEL: @test_mm512_cvtpd_ps
@@ -6685,6 +7088,23 @@ __m256 test_mm512_mask_cvtpd_ps (__m256 __W, __mmask8 __U, __m512d __A)
return _mm512_mask_cvtpd_ps (__W,__U,__A);
}
+__m512d test_mm512_cvtpd_pslo(__m512 __A)
+{
+ // CHECK-LABEL: @test_mm512_cvtpd_pslo
+ // CHECK: @llvm.x86.avx512.mask.cvtpd2ps.512
+ // CHECK: zeroinitializer
+ // CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> %{{.*}}, <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 _mm512_cvtpd_pslo(__A);
+}
+
+__m512d test_mm512_mask_cvtpd_pslo(__m512 __W, __mmask8 __U, __m512d __A) {
+ // CHECK-LABEL: @test_mm512_mask_cvtpd_pslo
+ // CHECK: @llvm.x86.avx512.mask.cvtpd2ps.512
+ // CHECK: zeroinitializer
+ // CHECK: shufflevector <8 x float> %{{.*}}, <8 x float> %{{.*}}, <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 _mm512_mask_cvtpd_pslo(__W, __U, __A);
+}
+
__m256 test_mm512_maskz_cvtpd_ps (__mmask8 __U, __m512d __A)
{
// CHECK-LABEL: @test_mm512_maskz_cvtpd_ps
@@ -7069,115 +7489,211 @@ __m512d test_mm512_roundscale_round_pd(__m512d __A)
return _mm512_roundscale_round_pd(__A,3,_MM_FROUND_CUR_DIRECTION);
}
+__m512i test_mm512_max_epi32 (__m512i __A, __m512i __B)
+{
+ // CHECK-LABEL: @test_mm512_max_epi32
+ // CHECK: [[CMP:%.*]] = icmp sgt <16 x i32> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <16 x i1> [[CMP]], <16 x i32> [[X]], <16 x i32> [[Y]]
+ return _mm512_max_epi32 (__A,__B);
+}
+
__m512i test_mm512_mask_max_epi32 (__m512i __W, __mmask16 __M, __m512i __A, __m512i __B)
{
// CHECK-LABEL: @test_mm512_mask_max_epi32
- // CHECK: @llvm.x86.avx512.mask.pmaxs.d.512
+ // CHECK: [[CMP:%.*]] = icmp sgt <16 x i32> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <16 x i1> [[CMP]], <16 x i32> [[X]], <16 x i32> [[Y]]
+ // CHECK: select <16 x i1> {{.*}}, <16 x i32> [[RES]], <16 x i32> {{.*}}
return _mm512_mask_max_epi32 (__W,__M,__A,__B);
}
__m512i test_mm512_maskz_max_epi32 (__mmask16 __M, __m512i __A, __m512i __B)
{
// CHECK-LABEL: @test_mm512_maskz_max_epi32
- // CHECK: @llvm.x86.avx512.mask.pmaxs.d.512
+ // CHECK: [[CMP:%.*]] = icmp sgt <16 x i32> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <16 x i1> [[CMP]], <16 x i32> [[X]], <16 x i32> [[Y]]
+ // CHECK: select <16 x i1> {{.*}}, <16 x i32> [[RES]], <16 x i32> {{.*}}
return _mm512_maskz_max_epi32 (__M,__A,__B);
}
+__m512i test_mm512_max_epi64 (__m512i __A, __m512i __B)
+{
+ // CHECK-LABEL: @test_mm512_max_epi64
+ // CHECK: [[CMP:%.*]] = icmp sgt <8 x i64> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <8 x i1> [[CMP]], <8 x i64> [[X]], <8 x i64> [[Y]]
+ return _mm512_max_epi64 (__A,__B);
+}
+
__m512i test_mm512_mask_max_epi64 (__m512i __W, __mmask8 __M, __m512i __A, __m512i __B)
{
// CHECK-LABEL: @test_mm512_mask_max_epi64
- // CHECK: @llvm.x86.avx512.mask.pmaxs.q.512
+ // CHECK: [[CMP:%.*]] = icmp sgt <8 x i64> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <8 x i1> [[CMP]], <8 x i64> [[X]], <8 x i64> [[Y]]
+ // CHECK: select <8 x i1> {{.*}}, <8 x i64> [[RES]], <8 x i64> {{.*}}
return _mm512_mask_max_epi64 (__W,__M,__A,__B);
}
__m512i test_mm512_maskz_max_epi64 (__mmask8 __M, __m512i __A, __m512i __B)
{
// CHECK-LABEL: @test_mm512_maskz_max_epi64
- // CHECK: @llvm.x86.avx512.mask.pmaxs.q.512
+ // CHECK: [[CMP:%.*]] = icmp sgt <8 x i64> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <8 x i1> [[CMP]], <8 x i64> [[X]], <8 x i64> [[Y]]
+ // CHECK: select <8 x i1> {{.*}}, <8 x i64> [[RES]], <8 x i64> {{.*}}
return _mm512_maskz_max_epi64 (__M,__A,__B);
}
+__m512i test_mm512_max_epu64 (__m512i __A, __m512i __B)
+{
+ // CHECK-LABEL: @test_mm512_max_epu64
+ // CHECK: [[CMP:%.*]] = icmp ugt <8 x i64> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <8 x i1> [[CMP]], <8 x i64> [[X]], <8 x i64> [[Y]]
+ return _mm512_max_epu64 (__A,__B);
+}
+
__m512i test_mm512_mask_max_epu64 (__m512i __W, __mmask8 __M, __m512i __A, __m512i __B)
{
// CHECK-LABEL: @test_mm512_mask_max_epu64
- // CHECK: @llvm.x86.avx512.mask.pmaxu.q.512
+ // CHECK: [[CMP:%.*]] = icmp ugt <8 x i64> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <8 x i1> [[CMP]], <8 x i64> [[X]], <8 x i64> [[Y]]
+ // CHECK: select <8 x i1> {{.*}}, <8 x i64> [[RES]], <8 x i64> {{.*}}
return _mm512_mask_max_epu64 (__W,__M,__A,__B);
}
__m512i test_mm512_maskz_max_epu64 (__mmask8 __M, __m512i __A, __m512i __B)
{
// CHECK-LABEL: @test_mm512_maskz_max_epu64
- // CHECK: @llvm.x86.avx512.mask.pmaxu.q.512
+ // CHECK: [[CMP:%.*]] = icmp ugt <8 x i64> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <8 x i1> [[CMP]], <8 x i64> [[X]], <8 x i64> [[Y]]
+ // CHECK: select <8 x i1> {{.*}}, <8 x i64> [[RES]], <8 x i64> {{.*}}
return _mm512_maskz_max_epu64 (__M,__A,__B);
}
+__m512i test_mm512_max_epu32 (__m512i __A, __m512i __B)
+{
+ // CHECK-LABEL: @test_mm512_max_epu32
+ // CHECK: [[CMP:%.*]] = icmp ugt <16 x i32> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <16 x i1> [[CMP]], <16 x i32> [[X]], <16 x i32> [[Y]]
+ return _mm512_max_epu32 (__A,__B);
+}
+
__m512i test_mm512_mask_max_epu32 (__m512i __W, __mmask16 __M, __m512i __A, __m512i __B)
{
// CHECK-LABEL: @test_mm512_mask_max_epu32
- // CHECK: @llvm.x86.avx512.mask.pmaxu.d.512
+ // CHECK: [[CMP:%.*]] = icmp ugt <16 x i32> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <16 x i1> [[CMP]], <16 x i32> [[X]], <16 x i32> [[Y]]
+ // CHECK: select <16 x i1> {{.*}}, <16 x i32> [[RES]], <16 x i32> {{.*}}
return _mm512_mask_max_epu32 (__W,__M,__A,__B);
}
__m512i test_mm512_maskz_max_epu32 (__mmask16 __M, __m512i __A, __m512i __B)
{
// CHECK-LABEL: @test_mm512_maskz_max_epu32
- // CHECK: @llvm.x86.avx512.mask.pmaxu.d.512
+ // CHECK: [[CMP:%.*]] = icmp ugt <16 x i32> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <16 x i1> [[CMP]], <16 x i32> [[X]], <16 x i32> [[Y]]
+ // CHECK: select <16 x i1> {{.*}}, <16 x i32> [[RES]], <16 x i32> {{.*}}
return _mm512_maskz_max_epu32 (__M,__A,__B);
}
+__m512i test_mm512_min_epi32 (__m512i __A, __m512i __B)
+{
+ // CHECK-LABEL: @test_mm512_min_epi32
+ // CHECK: [[CMP:%.*]] = icmp slt <16 x i32> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <16 x i1> [[CMP]], <16 x i32> [[X]], <16 x i32> [[Y]]
+ return _mm512_min_epi32 (__A,__B);
+}
+
__m512i test_mm512_mask_min_epi32 (__m512i __W, __mmask16 __M, __m512i __A, __m512i __B)
{
// CHECK-LABEL: @test_mm512_mask_min_epi32
- // CHECK: @llvm.x86.avx512.mask.pmins.d.512
+ // CHECK: [[CMP:%.*]] = icmp slt <16 x i32> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <16 x i1> [[CMP]], <16 x i32> [[X]], <16 x i32> [[Y]]
+ // CHECK: select <16 x i1> {{.*}}, <16 x i32> [[RES]], <16 x i32> {{.*}}
return _mm512_mask_min_epi32 (__W,__M,__A,__B);
}
__m512i test_mm512_maskz_min_epi32 (__mmask16 __M, __m512i __A, __m512i __B)
{
// CHECK-LABEL: @test_mm512_maskz_min_epi32
- // CHECK: @llvm.x86.avx512.mask.pmins.d.512
+ // CHECK: [[CMP:%.*]] = icmp slt <16 x i32> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <16 x i1> [[CMP]], <16 x i32> [[X]], <16 x i32> [[Y]]
+ // CHECK: select <16 x i1> {{.*}}, <16 x i32> [[RES]], <16 x i32> {{.*}}
return _mm512_maskz_min_epi32 (__M,__A,__B);
}
+__m512i test_mm512_min_epu32 (__m512i __A, __m512i __B)
+{
+ // CHECK-LABEL: @test_mm512_min_epu32
+ // CHECK: [[CMP:%.*]] = icmp ult <16 x i32> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <16 x i1> [[CMP]], <16 x i32> [[X]], <16 x i32> [[Y]]
+ return _mm512_min_epu32 (__A,__B);
+}
+
__m512i test_mm512_mask_min_epu32 (__m512i __W, __mmask16 __M, __m512i __A, __m512i __B)
{
// CHECK-LABEL: @test_mm512_mask_min_epu32
- // CHECK: @llvm.x86.avx512.mask.pminu.d.512
+ // CHECK: [[CMP:%.*]] = icmp ult <16 x i32> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <16 x i1> [[CMP]], <16 x i32> [[X]], <16 x i32> [[Y]]
+ // CHECK: select <16 x i1> {{.*}}, <16 x i32> [[RES]], <16 x i32> {{.*}}
return _mm512_mask_min_epu32 (__W,__M,__A,__B);
}
__m512i test_mm512_maskz_min_epu32 (__mmask16 __M, __m512i __A, __m512i __B)
{
// CHECK-LABEL: @test_mm512_maskz_min_epu32
- // CHECK: @llvm.x86.avx512.mask.pminu.d.512
+ // CHECK: [[CMP:%.*]] = icmp ult <16 x i32> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <16 x i1> [[CMP]], <16 x i32> [[X]], <16 x i32> [[Y]]
+ // CHECK: select <16 x i1> {{.*}}, <16 x i32> [[RES]], <16 x i32> {{.*}}
return _mm512_maskz_min_epu32 (__M,__A,__B);
}
+__m512i test_mm512_min_epi64 (__m512i __A, __m512i __B)
+{
+ // CHECK-LABEL: @test_mm512_min_epi64
+ // CHECK: [[CMP:%.*]] = icmp slt <8 x i64> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <8 x i1> [[CMP]], <8 x i64> [[X]], <8 x i64> [[Y]]
+ return _mm512_min_epi64 (__A,__B);
+}
+
__m512i test_mm512_mask_min_epi64 (__m512i __W, __mmask8 __M, __m512i __A, __m512i __B)
{
// CHECK-LABEL: @test_mm512_mask_min_epi64
- // CHECK: @llvm.x86.avx512.mask.pmins.q.512
+ // CHECK: [[CMP:%.*]] = icmp slt <8 x i64> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <8 x i1> [[CMP]], <8 x i64> [[X]], <8 x i64> [[Y]]
+ // CHECK: select <8 x i1> {{.*}}, <8 x i64> [[RES]], <8 x i64> {{.*}}
return _mm512_mask_min_epi64 (__W,__M,__A,__B);
}
__m512i test_mm512_maskz_min_epi64 (__mmask8 __M, __m512i __A, __m512i __B)
{
// CHECK-LABEL: @test_mm512_maskz_min_epi64
- // CHECK: @llvm.x86.avx512.mask.pmins.q.512
+ // CHECK: [[CMP:%.*]] = icmp slt <8 x i64> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <8 x i1> [[CMP]], <8 x i64> [[X]], <8 x i64> [[Y]]
+ // CHECK: select <8 x i1> {{.*}}, <8 x i64> [[RES]], <8 x i64> {{.*}}
return _mm512_maskz_min_epi64 (__M,__A,__B);
}
+__m512i test_mm512_min_epu64 (__m512i __A, __m512i __B)
+{
+ // CHECK-LABEL: @test_mm512_min_epu64
+ // CHECK: [[CMP:%.*]] = icmp ult <8 x i64> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <8 x i1> [[CMP]], <8 x i64> [[X]], <8 x i64> [[Y]]
+ return _mm512_min_epu64 (__A,__B);
+}
+
__m512i test_mm512_mask_min_epu64 (__m512i __W, __mmask8 __M, __m512i __A, __m512i __B)
{
// CHECK-LABEL: @test_mm512_mask_min_epu64
- // CHECK: @llvm.x86.avx512.mask.pminu.q.512
+ // CHECK: [[CMP:%.*]] = icmp ult <8 x i64> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <8 x i1> [[CMP]], <8 x i64> [[X]], <8 x i64> [[Y]]
+ // CHECK: select <8 x i1> {{.*}}, <8 x i64> [[RES]], <8 x i64> {{.*}}
return _mm512_mask_min_epu64 (__W,__M,__A,__B);
}
__m512i test_mm512_maskz_min_epu64 (__mmask8 __M, __m512i __A, __m512i __B)
{
// CHECK-LABEL: @test_mm512_maskz_min_epu64
- // CHECK: @llvm.x86.avx512.mask.pminu.q.512
+ // CHECK: [[CMP:%.*]] = icmp ult <8 x i64> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <8 x i1> [[CMP]], <8 x i64> [[X]], <8 x i64> [[Y]]
+ // CHECK: select <8 x i1> {{.*}}, <8 x i64> [[RES]], <8 x i64> {{.*}}
return _mm512_maskz_min_epu64 (__M,__A,__B);
}
@@ -7256,12 +7772,14 @@ __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
//CHECK: @llvm.x86.avx512.mask.pbroadcast.q.gpr.512
return _mm512_mask_set1_epi64 (__O, __M, __A);
}
+#endif
__m512i test_mm512_set_epi64 (long long __A, long long __B, long long __C,
long long __D, long long __E, long long __F,
@@ -7443,11 +7961,13 @@ int test_mm_cvtss_i32(__m128 A) {
return _mm_cvtss_i32(A);
}
+#ifdef __x86_64__
long long test_mm_cvtss_i64(__m128 A) {
// CHECK-LABEL: test_mm_cvtss_i64
// CHECK: call i64 @llvm.x86.sse.cvtss2si64(<4 x float> %{{.*}})
return _mm_cvtss_i64(A);
}
+#endif
__m128d test_mm_cvti32_sd(__m128d A, int B) {
// CHECK-LABEL: test_mm_cvti32_sd
@@ -7456,12 +7976,14 @@ __m128d test_mm_cvti32_sd(__m128d A, int B) {
return _mm_cvti32_sd(A, B);
}
+#ifdef __x86_64__
__m128d test_mm_cvti64_sd(__m128d A, long long B) {
// CHECK-LABEL: test_mm_cvti64_sd
// CHECK: sitofp i64 %{{.*}} to double
// CHECK: insertelement <2 x double> %{{.*}}, double %{{.*}}, i32 0
return _mm_cvti64_sd(A, B);
}
+#endif
__m128 test_mm_cvti32_ss(__m128 A, int B) {
// CHECK-LABEL: test_mm_cvti32_ss
@@ -7470,12 +7992,14 @@ __m128 test_mm_cvti32_ss(__m128 A, int B) {
return _mm_cvti32_ss(A, B);
}
+#ifdef __x86_64__
__m128 test_mm_cvti64_ss(__m128 A, long long B) {
// CHECK-LABEL: test_mm_cvti64_ss
// CHECK: sitofp i64 %{{.*}} to float
// CHECK: insertelement <4 x float> %{{.*}}, float %{{.*}}, i32 0
return _mm_cvti64_ss(A, B);
}
+#endif
int test_mm_cvtsd_i32(__m128d A) {
// CHECK-LABEL: test_mm_cvtsd_i32
@@ -7483,11 +8007,13 @@ int test_mm_cvtsd_i32(__m128d A) {
return _mm_cvtsd_i32(A);
}
+#ifdef __x86_64__
long long test_mm_cvtsd_i64(__m128d A) {
// CHECK-LABEL: test_mm_cvtsd_i64
// CHECK: call i64 @llvm.x86.sse2.cvtsd2si64(<2 x double> %{{.*}})
return _mm_cvtsd_i64(A);
}
+#endif
__m128d test_mm_mask_cvtss_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128 __B) {
// CHECK-LABEL: @test_mm_mask_cvtss_sd
@@ -7549,6 +8075,143 @@ __m512d test_mm512_setzero_pd()
return _mm512_setzero_pd();
}
+__mmask16 test_mm512_int2mask(int __a)
+{
+ // O2-LABEL: test_mm512_int2mask
+ // O2: trunc i32 %__a to i16
+ return _mm512_int2mask(__a);
+}
+
+int test_mm512_mask2int(__mmask16 __a)
+{
+ // O2-LABEL: test_mm512_mask2int
+ // O2: zext i16 %__a to i32
+ return _mm512_mask2int(__a);
+}
+
+__m128 test_mm_mask_move_ss (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B)
+{
+ // O2-LABEL: @test_mm_mask_move_ss
+ // O2: %[[M:.*]] = and i8 %__U, 1
+ // O2: %[[M2:.*]] = icmp ne i8 %[[M]], 0
+ // O2: %[[ELM1:.*]] = extractelement <4 x float> %__B, i32 0
+ // O2: %[[ELM2:.*]] = extractelement <4 x float> %__W, i32 0
+ // O2: %[[SEL:.*]] = select i1 %[[M2]], float %[[ELM1]], float %[[ELM2]]
+ // O2: %[[RES:.*]] = insertelement <4 x float> %__A, float %[[SEL]], i32 0
+ // O2: ret <4 x float> %[[RES]]
+ return _mm_mask_move_ss ( __W, __U, __A, __B);
+}
+
+__m128 test_mm_maskz_move_ss (__mmask8 __U, __m128 __A, __m128 __B)
+{
+ // O2-LABEL: @test_mm_maskz_move_ss
+ // O2: %[[M:.*]] = and i8 %__U, 1
+ // O2: %[[M2:.*]] = icmp ne i8 %[[M]], 0
+ // O2: %[[ELM1:.*]] = extractelement <4 x float> %__B, i32 0
+ // O2: %[[SEL:.*]] = select i1 %[[M2]], float %[[ELM1]], float 0.0
+ // O2: %[[RES:.*]] = insertelement <4 x float> %__A, float %[[SEL]], i32 0
+ // O2: ret <4 x float> %[[RES]]
+ return _mm_maskz_move_ss (__U, __A, __B);
+}
+
+__m128d test_mm_mask_move_sd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B)
+{
+ // O2-LABEL: @test_mm_mask_move_sd
+ // O2: %[[M:.*]] = and i8 %__U, 1
+ // O2: %[[M2:.*]] = icmp ne i8 %[[M]], 0
+ // O2: %[[ELM1:.*]] = extractelement <2 x double> %__B, i32 0
+ // O2: %[[ELM2:.*]] = extractelement <2 x double> %__W, i32 0
+ // O2: %[[SEL:.*]] = select i1 %[[M2]], double %[[ELM1]], double %[[ELM2]]
+ // O2: %[[RES:.*]] = insertelement <2 x double> %__A, double %[[SEL]], i32 0
+ // O2: ret <2 x double> %[[RES]]
+ return _mm_mask_move_sd ( __W, __U, __A, __B);
+}
+
+__m128d test_mm_maskz_move_sd (__mmask8 __U, __m128d __A, __m128d __B)
+{
+ // O2-LABEL: @test_mm_maskz_move_sd
+ // O2: %[[M:.*]] = and i8 %__U, 1
+ // O2: %[[M2:.*]] = icmp ne i8 %[[M]], 0
+ // O2: %[[ELM1:.*]] = extractelement <2 x double> %__B, i32 0
+ // O2: %[[SEL:.*]] = select i1 %[[M2]], double %[[ELM1]], double 0.0
+ // O2: %[[RES:.*]] = insertelement <2 x double> %__A, double %[[SEL]], i32 0
+ // O2: ret <2 x double> %[[RES]]
+ return _mm_maskz_move_sd (__U, __A, __B);
+}
+
+void test_mm_mask_store_ss(float * __P, __mmask8 __U, __m128 __A)
+{
+ // O2-LABEL: @test_mm_mask_store_ss
+ // O2: %[[CAST:.*]] = bitcast float* %__P to <16 x float>*
+ // O2: %[[SHUFFLE:.*]] = shufflevector <4 x float> %__A, <4 x float> undef, <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>
+ // O2: %[[MASK1:.*]] = and i8 %__U, 1
+ // O2: %[[MASK2:.*]] = zext i8 %[[MASK1]] to i16
+ // O2: %[[MASK3:.*]] = bitcast i16 %[[MASK2]] to <16 x i1>
+ // O2: tail call void @llvm.masked.store.v16f32.p0v16f32(<16 x float> %[[SHUFFLE]], <16 x float>* %[[CAST]], i32 16, <16 x i1> %[[MASK3]])
+ _mm_mask_store_ss(__P, __U, __A);
+}
+
+void test_mm_mask_store_sd(double * __P, __mmask8 __U, __m128d __A)
+{
+ // O2-LABEL: @test_mm_mask_store_sd
+ // O2: %[[CAST:.*]] = bitcast double* %__P to <8 x double>*
+ // O2: %[[SHUFFLE:.*]] = shufflevector <2 x double> %__A, <2 x double> undef, <8 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
+ // O2: %[[MASK1:.*]] = and i8 %__U, 1
+ // O2: %[[MASK2:.*]] = bitcast i8 %[[MASK1]] to <8 x i1>
+ // O2: tail call void @llvm.masked.store.v8f64.p0v8f64(<8 x double> %[[SHUFFLE]], <8 x double>* %[[CAST]], i32 16, <8 x i1> %[[MASK2]])
+ _mm_mask_store_sd(__P, __U, __A);
+}
+
+__m128 test_mm_mask_load_ss(__m128 __A, __mmask8 __U, const float* __W)
+{
+ // O2-LABEL: @test_mm_mask_load_ss
+ // O2: %[[SHUF:.*]] = shufflevector <4 x float> %__A, <4 x float> <float 0.000000e+00, float undef, float undef, float undef>, <4 x i32> <i32 0, i32 4, i32 4, i32 4>
+ // O2: %[[PTR:.*]] = bitcast float* %__W to <16 x float>*
+ // O2: %[[SHUF2:.*]] = shufflevector <4 x float> %[[SHUF]], <4 x float> undef, <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>
+ // O2: %[[AND:.*]] = and i8 %__U, 1
+ // O2: %[[MASK:.*]] = zext i8 %[[AND]] to i16
+ // O2: %[[MASK2:.*]] = bitcast i16 %[[MASK]] to <16 x i1>
+ // O2: %[[RES:.*]] = tail call <16 x float> @llvm.masked.load.v16f32.p0v16f32(<16 x float>* %[[PTR]], i32 16, <16 x i1> %[[MASK2]], <16 x float> %[[SHUF2]])
+ // O2: shufflevector <16 x float> %[[RES]], <16 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ return _mm_mask_load_ss(__A, __U, __W);
+}
+
+__m128 test_mm_maskz_load_ss (__mmask8 __U, const float * __W)
+{
+ // O2-LABEL: @test_mm_maskz_load_ss
+ // O2: %[[PTR:.*]] = bitcast float* %__W to <16 x float>*
+ // O2: %[[AND:.*]] = and i8 %__U, 1
+ // O2: %[[MASK:.*]] = zext i8 %[[AND]] to i16
+ // O2: %[[MASK2:.*]] = bitcast i16 %[[MASK]] to <16 x i1>
+ // O2: %[[RES:.*]] = tail call <16 x float> @llvm.masked.load.v16f32.p0v16f32(<16 x float>* %[[PTR]], i32 16, <16 x i1> %[[MASK2]], <16 x float> zeroinitializer)
+ // O2: shufflevector <16 x float> %[[RES]], <16 x float> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ return _mm_maskz_load_ss (__U, __W);
+}
+
+__m128d test_mm_mask_load_sd (__m128d __A, __mmask8 __U, const double * __W)
+{
+ // O2-LABEL: @test_mm_mask_load_sd
+ // O2: %[[SHUF:.*]] = insertelement <2 x double> %__A, double 0.000000e+00, i32 1
+ // O2: %[[PTR:.*]] = bitcast double* %__W to <8 x double>*
+ // O2: %[[SHUF2:.*]] = shufflevector <2 x double> %[[SHUF]], <2 x double> undef, <8 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
+ // O2: %[[AND:.*]] = and i8 %__U, 1
+ // O2: %[[MASK:.*]] = bitcast i8 %[[AND]] to <8 x i1>
+ // O2: %[[RES:.*]] = tail call <8 x double> @llvm.masked.load.v8f64.p0v8f64(<8 x double>* %[[PTR]], i32 16, <8 x i1> %[[MASK]], <8 x double> %[[SHUF2]])
+ // O2: shufflevector <8 x double> %[[RES]], <8 x double> undef, <2 x i32> <i32 0, i32 1>
+ return _mm_mask_load_sd (__A, __U, __W);
+}
+
+__m128d test_mm_maskz_load_sd (__mmask8 __U, const double * __W)
+{
+ // O2-LABEL: @test_mm_maskz_load_sd
+ // O2: %[[PTR:.*]] = bitcast double* %__W to <8 x double>*
+ // O2: %[[AND:.*]] = and i8 %__U, 1
+ // O2: %[[MASK:.*]] = bitcast i8 %[[AND]] to <8 x i1>
+ // O2: %[[RES:.*]] = tail call <8 x double> @llvm.masked.load.v8f64.p0v8f64(<8 x double>* %[[PTR]], i32 16, <8 x i1> %[[MASK]], <8 x double> zeroinitializer)
+ // O2: shufflevector <8 x double> %[[RES]], <8 x double> undef, <2 x i32> <i32 0, i32 1>
+ return _mm_maskz_load_sd (__U, __W);
+}
+
__m512d test_mm512_abs_pd(__m512d a){
// CHECK-LABEL: @test_mm512_abs_pd
// CHECK: and <8 x i64>
diff --git a/test/CodeGen/avx512ifma-builtins.c b/test/CodeGen/avx512ifma-builtins.c
index 366d3bec319b..311d6989bf0d 100644
--- a/test/CodeGen/avx512ifma-builtins.c
+++ b/test/CodeGen/avx512ifma-builtins.c
@@ -1,7 +1,5 @@
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +avx512ifma -emit-llvm -o - -Werror | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +avx512ifma -emit-llvm -o - -Wall -Werror | FileCheck %s
-// Don't include mm_malloc.h, it's system specific.
-#define __MM_MALLOC_H
#include <immintrin.h>
diff --git a/test/CodeGen/avx512ifmavl-builtins.c b/test/CodeGen/avx512ifmavl-builtins.c
index b38c1a8953ad..c59af0ec6d06 100644
--- a/test/CodeGen/avx512ifmavl-builtins.c
+++ b/test/CodeGen/avx512ifmavl-builtins.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +avx512ifma -target-feature +avx512vl -emit-llvm -o - -Werror | FileCheck %s
+// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +avx512ifma -target-feature +avx512vl -emit-llvm -o - -Wall -Werror | FileCheck %s
#define __MM_MALLOC_H
diff --git a/test/CodeGen/avx512pf-builtins.c b/test/CodeGen/avx512pf-builtins.c
index 16b27e915136..19ee083eae2d 100644
--- a/test/CodeGen/avx512pf-builtins.c
+++ b/test/CodeGen/avx512pf-builtins.c
@@ -1,7 +1,5 @@
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +avx512pf -emit-llvm -o - -Werror | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +avx512pf -emit-llvm -o - -Wall -Werror | FileCheck %s
-// Don't include mm_malloc.h, it's system specific.
-#define __MM_MALLOC_H
#include <immintrin.h>
diff --git a/test/CodeGen/avx512vbmi-builtins.c b/test/CodeGen/avx512vbmi-builtins.c
index 3fe97fd536b9..0816bce3a6de 100644
--- a/test/CodeGen/avx512vbmi-builtins.c
+++ b/test/CodeGen/avx512vbmi-builtins.c
@@ -1,7 +1,5 @@
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +avx512vbmi -emit-llvm -o - -Werror | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +avx512vbmi -emit-llvm -o - -Wall -Werror | FileCheck %s
-// Don't include mm_malloc.h, it's system specific.
-#define __MM_MALLOC_H
#include <immintrin.h>
diff --git a/test/CodeGen/avx512vbmivl-builtin.c b/test/CodeGen/avx512vbmivl-builtin.c
index 549c9656c0de..b114720758aa 100644
--- a/test/CodeGen/avx512vbmivl-builtin.c
+++ b/test/CodeGen/avx512vbmivl-builtin.c
@@ -1,7 +1,5 @@
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +avx512vbmi -target-feature +avx512vl -target-feature +avx512bw -emit-llvm -o - -Werror | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +avx512vbmi -target-feature +avx512vl -target-feature +avx512bw -emit-llvm -o - -Wall -Werror | FileCheck %s
-// Don't include mm_malloc.h, it's system specific.
-#define __MM_MALLOC_H
#include <immintrin.h>
diff --git a/test/CodeGen/avx512vl-builtins.c b/test/CodeGen/avx512vl-builtins.c
index 2b6ec3733830..fe4ebe12ddd4 100644
--- a/test/CodeGen/avx512vl-builtins.c
+++ b/test/CodeGen/avx512vl-builtins.c
@@ -1,7 +1,5 @@
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +avx512f -target-feature +avx512vl -emit-llvm -o - -Werror | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +avx512f -target-feature +avx512vl -emit-llvm -o - -Wall -Werror | FileCheck %s
-// Don't include mm_malloc.h, it's system specific.
-#define __MM_MALLOC_H
#include <immintrin.h>
@@ -501,56 +499,56 @@ __mmask8 test_mm256_mask_cmpneq_epu64_mask(__mmask8 __u, __m256i __a, __m256i __
return (__mmask8)_mm256_mask_cmpneq_epu64_mask(__u, __a, __b);
}
-__mmask8 test_mm_cmp_epi32_mask(__m128i __a, __m128i __b) {
- // CHECK-LABEL: @test_mm_cmp_epi32_mask
+__mmask8 test_mm_cmp_eq_epi32_mask(__m128i __a, __m128i __b) {
+ // CHECK-LABEL: @test_mm_cmp_eq_epi32_mask
// CHECK: icmp eq <4 x i32> %{{.*}}, %{{.*}}
- return (__mmask8)_mm_cmp_epi32_mask(__a, __b, 0);
+ return (__mmask8)_mm_cmp_epi32_mask(__a, __b, _MM_CMPINT_EQ);
}
-__mmask8 test_mm_mask_cmp_epi32_mask(__mmask8 __u, __m128i __a, __m128i __b) {
- // CHECK-LABEL: @test_mm_mask_cmp_epi32_mask
- // CHECK: icmp eq <4 x i32> %{{.*}}, %{{.*}}
+__mmask8 test_mm_mask_cmp_lt_epi32_mask(__mmask8 __u, __m128i __a, __m128i __b) {
+ // CHECK-LABEL: @test_mm_mask_cmp_lt_epi32_mask
+ // CHECK: icmp slt <4 x i32> %{{.*}}, %{{.*}}
// CHECK: and <4 x i1> %{{.*}}, %{{.*}}
- return (__mmask8)_mm_mask_cmp_epi32_mask(__u, __a, __b, 0);
+ return (__mmask8)_mm_mask_cmp_epi32_mask(__u, __a, __b, _MM_CMPINT_LT);
}
-__mmask8 test_mm_cmp_epi64_mask(__m128i __a, __m128i __b) {
- // CHECK-LABEL: @test_mm_cmp_epi64_mask
- // CHECK: icmp eq <2 x i64> %{{.*}}, %{{.*}}
- return (__mmask8)_mm_cmp_epi64_mask(__a, __b, 0);
+__mmask8 test_mm_cmp_lt_epi64_mask(__m128i __a, __m128i __b) {
+ // CHECK-LABEL: @test_mm_cmp_lt_epi64_mask
+ // CHECK: icmp slt <2 x i64> %{{.*}}, %{{.*}}
+ return (__mmask8)_mm_cmp_epi64_mask(__a, __b, _MM_CMPINT_LT);
}
-__mmask8 test_mm_mask_cmp_epi64_mask(__mmask8 __u, __m128i __a, __m128i __b) {
- // CHECK-LABEL: @test_mm_mask_cmp_epi64_mask
+__mmask8 test_mm_mask_cmp_eq_epi64_mask(__mmask8 __u, __m128i __a, __m128i __b) {
+ // CHECK-LABEL: @test_mm_mask_cmp_eq_epi64_mask
// CHECK: icmp eq <2 x i64> %{{.*}}, %{{.*}}
// CHECK: and <2 x i1> %{{.*}}, %{{.*}}
- return (__mmask8)_mm_mask_cmp_epi64_mask(__u, __a, __b, 0);
+ return (__mmask8)_mm_mask_cmp_epi64_mask(__u, __a, __b, _MM_CMPINT_EQ);
}
-__mmask8 test_mm256_cmp_epi32_mask(__m256i __a, __m256i __b) {
- // CHECK-LABEL: @test_mm256_cmp_epi32_mask
+__mmask8 test_mm256_cmp_eq_epi32_mask(__m256i __a, __m256i __b) {
+ // CHECK-LABEL: @test_mm256_cmp_eq_epi32_mask
// CHECK: icmp eq <8 x i32> %{{.*}}, %{{.*}}
- return (__mmask8)_mm256_cmp_epi32_mask(__a, __b, 0);
+ return (__mmask8)_mm256_cmp_epi32_mask(__a, __b, _MM_CMPINT_EQ);
}
-__mmask8 test_mm256_mask_cmp_epi32_mask(__mmask8 __u, __m256i __a, __m256i __b) {
- // CHECK-LABEL: @test_mm256_mask_cmp_epi32_mask
- // CHECK: icmp eq <8 x i32> %{{.*}}, %{{.*}}
+__mmask8 test_mm256_mask_cmp_le_epi32_mask(__mmask8 __u, __m256i __a, __m256i __b) {
+ // CHECK-LABEL: @test_mm256_mask_cmp_le_epi32_mask
+ // CHECK: icmp sle <8 x i32> %{{.*}}, %{{.*}}
// CHECK: and <8 x i1> %{{.*}}, %{{.*}}
- return (__mmask8)_mm256_mask_cmp_epi32_mask(__u, __a, __b, 0);
+ return (__mmask8)_mm256_mask_cmp_epi32_mask(__u, __a, __b, _MM_CMPINT_LE);
}
-__mmask8 test_mm256_cmp_epi64_mask(__m256i __a, __m256i __b) {
- // CHECK-LABEL: @test_mm256_cmp_epi64_mask
+__mmask8 test_mm256_cmp_eq_epi64_mask(__m256i __a, __m256i __b) {
+ // CHECK-LABEL: @test_mm256_cmp_eq_epi64_mask
// CHECK: icmp eq <4 x i64> %{{.*}}, %{{.*}}
- return (__mmask8)_mm256_cmp_epi64_mask(__a, __b, 0);
+ return (__mmask8)_mm256_cmp_epi64_mask(__a, __b, _MM_CMPINT_EQ);
}
-__mmask8 test_mm256_mask_cmp_epi64_mask(__mmask8 __u, __m256i __a, __m256i __b) {
- // CHECK-LABEL: @test_mm256_mask_cmp_epi64_mask
+__mmask8 test_mm256_mask_cmp_eq_epi64_mask(__mmask8 __u, __m256i __a, __m256i __b) {
+ // CHECK-LABEL: @test_mm256_mask_cmp_eq_epi64_mask
// CHECK: icmp eq <4 x i64> %{{.*}}, %{{.*}}
// CHECK: and <4 x i1> %{{.*}}, %{{.*}}
- return (__mmask8)_mm256_mask_cmp_epi64_mask(__u, __a, __b, 0);
+ return (__mmask8)_mm256_mask_cmp_epi64_mask(__u, __a, __b, _MM_CMPINT_EQ);
}
__mmask8 test_mm_cmp_epu32_mask(__m128i __a, __m128i __b) {
@@ -608,118 +606,136 @@ __mmask8 test_mm256_mask_cmp_epu64_mask(__mmask8 __u, __m256i __a, __m256i __b)
__m256i test_mm256_mask_add_epi32 (__m256i __W, __mmask8 __U, __m256i __A,
__m256i __B) {
//CHECK-LABEL: @test_mm256_mask_add_epi32
- //CHECK: @llvm.x86.avx512.mask.padd.d.256
+ //CHECK: add <8 x i32> %{{.*}}, %{{.*}}
+ //CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_mask_add_epi32(__W, __U, __A, __B);
}
__m256i test_mm256_maskz_add_epi32 (__mmask8 __U, __m256i __A, __m256i __B) {
//CHECK-LABEL: @test_mm256_maskz_add_epi32
- //CHECK: @llvm.x86.avx512.mask.padd.d.256
+ //CHECK: add <8 x i32> %{{.*}}, %{{.*}}
+ //CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_maskz_add_epi32(__U, __A, __B);
}
__m256i test_mm256_mask_add_epi64 (__m256i __W, __mmask8 __U, __m256i __A,
__m256i __B) {
//CHECK-LABEL: @test_mm256_mask_add_epi64
- //CHECK: @llvm.x86.avx512.mask.padd.q.256
+ //CHECK: add <4 x i64> %{{.*}}, %{{.*}}
+ //CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_mask_add_epi64(__W,__U,__A,__B);
}
__m256i test_mm256_maskz_add_epi64 (__mmask8 __U, __m256i __A, __m256i __B) {
//CHECK-LABEL: @test_mm256_maskz_add_epi64
- //CHECK: @llvm.x86.avx512.mask.padd.q.256
+ //CHECK: add <4 x i64> %{{.*}}, %{{.*}}
+ //CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_maskz_add_epi64 (__U,__A,__B);
}
__m256i test_mm256_mask_sub_epi32 (__m256i __W, __mmask8 __U, __m256i __A,
__m256i __B) {
//CHECK-LABEL: @test_mm256_mask_sub_epi32
- //CHECK: @llvm.x86.avx512.mask.psub.d.256
+ //CHECK: sub <8 x i32> %{{.*}}, %{{.*}}
+ //CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_mask_sub_epi32 (__W,__U,__A,__B);
}
__m256i test_mm256_maskz_sub_epi32 (__mmask8 __U, __m256i __A, __m256i __B) {
//CHECK-LABEL: @test_mm256_maskz_sub_epi32
- //CHECK: @llvm.x86.avx512.mask.psub.d.256
+ //CHECK: sub <8 x i32> %{{.*}}, %{{.*}}
+ //CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_maskz_sub_epi32 (__U,__A,__B);
}
__m256i test_mm256_mask_sub_epi64 (__m256i __W, __mmask8 __U, __m256i __A,
__m256i __B) {
//CHECK-LABEL: @test_mm256_mask_sub_epi64
- //CHECK: @llvm.x86.avx512.mask.psub.q.256
+ //CHECK: sub <4 x i64> %{{.*}}, %{{.*}}
+ //CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_mask_sub_epi64 (__W,__U,__A,__B);
}
__m256i test_mm256_maskz_sub_epi64 (__mmask8 __U, __m256i __A, __m256i __B) {
//CHECK-LABEL: @test_mm256_maskz_sub_epi64
- //CHECK: @llvm.x86.avx512.mask.psub.q.256
+ //CHECK: sub <4 x i64> %{{.*}}, %{{.*}}
+ //CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_maskz_sub_epi64 (__U,__A,__B);
}
__m128i test_mm_mask_add_epi32 (__m128i __W, __mmask8 __U, __m128i __A,
__m128i __B) {
//CHECK-LABEL: @test_mm_mask_add_epi32
- //CHECK: @llvm.x86.avx512.mask.padd.d.128
+ //CHECK: add <4 x i32> %{{.*}}, %{{.*}}
+ //CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_mask_add_epi32(__W,__U,__A,__B);
}
__m128i test_mm_maskz_add_epi32 (__mmask8 __U, __m128i __A, __m128i __B) {
//CHECK-LABEL: @test_mm_maskz_add_epi32
- //CHECK: @llvm.x86.avx512.mask.padd.d.128
+ //CHECK: add <4 x i32> %{{.*}}, %{{.*}}
+ //CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_maskz_add_epi32 (__U,__A,__B);
}
__m128i test_mm_mask_add_epi64 (__m128i __W, __mmask8 __U, __m128i __A,
__m128i __B) {
-//CHECK-LABEL: @test_mm_mask_add_epi64
- //CHECK: @llvm.x86.avx512.mask.padd.q.128
+ //CHECK-LABEL: @test_mm_mask_add_epi64
+ //CHECK: add <2 x i64> %{{.*}}, %{{.*}}
+ //CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_mask_add_epi64 (__W,__U,__A,__B);
}
__m128i test_mm_maskz_add_epi64 (__mmask8 __U, __m128i __A, __m128i __B) {
//CHECK-LABEL: @test_mm_maskz_add_epi64
- //CHECK: @llvm.x86.avx512.mask.padd.q.128
+ //CHECK: add <2 x i64> %{{.*}}, %{{.*}}
+ //CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_maskz_add_epi64 (__U,__A,__B);
}
__m128i test_mm_mask_sub_epi32 (__m128i __W, __mmask8 __U, __m128i __A,
__m128i __B) {
//CHECK-LABEL: @test_mm_mask_sub_epi32
- //CHECK: @llvm.x86.avx512.mask.psub.d.128
+ //CHECK: sub <4 x i32> %{{.*}}, %{{.*}}
+ //CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_mask_sub_epi32(__W, __U, __A, __B);
}
__m128i test_mm_maskz_sub_epi32 (__mmask8 __U, __m128i __A, __m128i __B) {
//CHECK-LABEL: @test_mm_maskz_sub_epi32
- //CHECK: @llvm.x86.avx512.mask.psub.d.128
+ //CHECK: sub <4 x i32> %{{.*}}, %{{.*}}
+ //CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_maskz_sub_epi32(__U, __A, __B);
}
__m128i test_mm_mask_sub_epi64 (__m128i __W, __mmask8 __U, __m128i __A,
__m128i __B) {
//CHECK-LABEL: @test_mm_mask_sub_epi64
- //CHECK: @llvm.x86.avx512.mask.psub.q.128
+ //CHECK: sub <2 x i64> %{{.*}}, %{{.*}}
+ //CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_mask_sub_epi64 (__W, __U, __A, __B);
}
__m128i test_mm_maskz_sub_epi64 (__mmask8 __U, __m128i __A, __m128i __B) {
//CHECK-LABEL: @test_mm_maskz_sub_epi64
- //CHECK: @llvm.x86.avx512.mask.psub.q.128
+ //CHECK: sub <2 x i64> %{{.*}}, %{{.*}}
+ //CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_maskz_sub_epi64 (__U, __A, __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.avx512.mask.pmul.dq.256
+ //CHECK: @llvm.x86.avx2.pmul.dq
+ //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.avx512.mask.pmul.dq.256
+ //CHECK: @llvm.x86.avx2.pmul.dq
+ //CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_maskz_mul_epi32(__M, __X, __Y);
}
@@ -727,65 +743,75 @@ __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.avx512.mask.pmul.dq.128
+ //CHECK: @llvm.x86.sse41.pmuldq
+ //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.avx512.mask.pmul.dq.128
+ //CHECK: @llvm.x86.sse41.pmuldq
+ //CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_maskz_mul_epi32(__M, __X, __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.avx512.mask.pmulu.dq.256
+ //CHECK: @llvm.x86.avx2.pmulu.dq
+ //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.avx512.mask.pmulu.dq.256
+ //CHECK: @llvm.x86.avx2.pmulu.dq
+ //CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_maskz_mul_epu32(__M, __X, __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.avx512.mask.pmulu.dq.128
+ //CHECK: @llvm.x86.sse2.pmulu.dq
+ //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.avx512.mask.pmulu.dq.128
+ //CHECK: @llvm.x86.sse2.pmulu.dq
+ //CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_maskz_mul_epu32(__M, __X, __Y);
}
__m128i test_mm_maskz_mullo_epi32 (__mmask8 __M, __m128i __A, __m128i __B) {
//CHECK-LABEL: @test_mm_maskz_mullo_epi32
- //CHECK: @llvm.x86.avx512.mask.pmull.d.128
+ //CHECK: mul <4 x i32> %{{.*}}, %{{.*}}
+ //CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_maskz_mullo_epi32(__M, __A, __B);
}
__m128i test_mm_mask_mullo_epi32 (__m128i __W, __mmask8 __M, __m128i __A,
__m128i __B) {
//CHECK-LABEL: @test_mm_mask_mullo_epi32
- //CHECK: @llvm.x86.avx512.mask.pmull.d.128
+ //CHECK: mul <4 x i32> %{{.*}}, %{{.*}}
+ //CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_mask_mullo_epi32(__W, __M, __A, __B);
}
__m256i test_mm256_maskz_mullo_epi32 (__mmask8 __M, __m256i __A, __m256i __B) {
//CHECK-LABEL: @test_mm256_maskz_mullo_epi32
- //CHECK: @llvm.x86.avx512.mask.pmull.d.256
+ //CHECK: mul <8 x i32> %{{.*}}, %{{.*}}
+ //CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_maskz_mullo_epi32(__M, __A, __B);
}
__m256i test_mm256_mask_mullo_epi32 (__m256i __W, __mmask8 __M, __m256i __A,
__m256i __B) {
//CHECK-LABEL: @test_mm256_mask_mullo_epi32
- //CHECK: @llvm.x86.avx512.mask.pmull.d.256
+ //CHECK: mul <8 x i32> %{{.*}}, %{{.*}}
+ //CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_mask_mullo_epi32(__W, __M, __A, __B);
}
@@ -1503,42 +1529,50 @@ __m256 test_mm256_mask3_fnmsub_ps(__m256 __A, __m256 __B, __m256 __C, __mmask8 _
__m128d test_mm_mask_add_pd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
// CHECK-LABEL: @test_mm_mask_add_pd
- // CHECK: @llvm.x86.avx512.mask.add.pd.128
+ // CHECK: fadd <2 x double> %{{.*}}, %{{.*}}
+ // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return _mm_mask_add_pd(__W,__U,__A,__B);
}
__m128d test_mm_maskz_add_pd(__mmask8 __U, __m128d __A, __m128d __B) {
// CHECK-LABEL: @test_mm_maskz_add_pd
- // CHECK: @llvm.x86.avx512.mask.add.pd.128
+ // CHECK: fadd <2 x double> %{{.*}}, %{{.*}}
+ // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return _mm_maskz_add_pd(__U,__A,__B);
}
__m256d test_mm256_mask_add_pd(__m256d __W, __mmask8 __U, __m256d __A, __m256d __B) {
// CHECK-LABEL: @test_mm256_mask_add_pd
- // CHECK: @llvm.x86.avx512.mask.add.pd.256
+ // CHECK: fadd <4 x double> %{{.*}}, %{{.*}}
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_mask_add_pd(__W,__U,__A,__B);
}
__m256d test_mm256_maskz_add_pd(__mmask8 __U, __m256d __A, __m256d __B) {
// CHECK-LABEL: @test_mm256_maskz_add_pd
- // CHECK: @llvm.x86.avx512.mask.add.pd.256
+ // CHECK: fadd <4 x double> %{{.*}}, %{{.*}}
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_maskz_add_pd(__U,__A,__B);
}
-__m128 test_mm_mask_add_ps(__m128 __W, __mmask16 __U, __m128 __A, __m128 __B) {
+__m128 test_mm_mask_add_ps(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_mask_add_ps
- // CHECK: @llvm.x86.avx512.mask.add.ps.128
+ // CHECK: fadd <4 x float> %{{.*}}, %{{.*}}
+ // 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) {
// CHECK-LABEL: @test_mm_maskz_add_ps
- // CHECK: @llvm.x86.avx512.mask.add.ps.128
+ // CHECK: fadd <4 x float> %{{.*}}, %{{.*}}
+ // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return _mm_maskz_add_ps(__U,__A,__B);
}
-__m256 test_mm256_mask_add_ps(__m256 __W, __mmask16 __U, __m256 __A, __m256 __B) {
+__m256 test_mm256_mask_add_ps(__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) {
// CHECK-LABEL: @test_mm256_mask_add_ps
- // CHECK: @llvm.x86.avx512.mask.add.ps.256
+ // CHECK: fadd <8 x float> %{{.*}}, %{{.*}}
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_mask_add_ps(__W,__U,__A,__B);
}
-__m256 test_mm256_maskz_add_ps(__mmask16 __U, __m256 __A, __m256 __B) {
+__m256 test_mm256_maskz_add_ps(__mmask8 __U, __m256 __A, __m256 __B) {
// CHECK-LABEL: @test_mm256_maskz_add_ps
- // CHECK: @llvm.x86.avx512.mask.add.ps.256
+ // CHECK: fadd <8 x float> %{{.*}}, %{{.*}}
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_maskz_add_ps(__U,__A,__B);
}
__m128i test_mm_mask_blend_epi32(__mmask8 __U, __m128i __A, __m128i __W) {
@@ -1703,23 +1737,29 @@ void test_mm256_mask_compressstoreu_epi32(void *__P, __mmask8 __U, __m256i __A)
}
__m128d test_mm_mask_cvtepi32_pd(__m128d __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_cvtepi32_pd
- // CHECK: @llvm.x86.avx512.mask.cvtdq2pd.128
- return _mm_mask_cvtepi32_pd(__W,__U,__A);
+ // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <2 x i32> <i32 0, i32 1>
+ // CHECK: sitofp <2 x i32> %{{.*}} to <2 x double>
+ // CHECK: select <2 x i1> {{.*}}, <2 x double> {{.*}}, <2 x double> {{.*}}
+ return _mm_mask_cvtepi32_pd(__W,__U,__A);
}
__m128d test_mm_maskz_cvtepi32_pd(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_maskz_cvtepi32_pd
- // CHECK: @llvm.x86.avx512.mask.cvtdq2pd.128
- return _mm_maskz_cvtepi32_pd(__U,__A);
+ // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <2 x i32> <i32 0, i32 1>
+ // CHECK: sitofp <2 x i32> %{{.*}} to <2 x double>
+ // CHECK: select <2 x i1> {{.*}}, <2 x double> {{.*}}, <2 x double> {{.*}}
+ return _mm_maskz_cvtepi32_pd(__U,__A);
}
__m256d test_mm256_mask_cvtepi32_pd(__m256d __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm256_mask_cvtepi32_pd
- // CHECK: @llvm.x86.avx512.mask.cvtdq2pd.256
- return _mm256_mask_cvtepi32_pd(__W,__U,__A);
+ // CHECK: sitofp <4 x i32> %{{.*}} to <4 x double>
+ // CHECK: select <4 x i1> {{.*}}, <4 x double> {{.*}}, <4 x double> {{.*}}
+ return _mm256_mask_cvtepi32_pd(__W,__U,__A);
}
__m256d test_mm256_maskz_cvtepi32_pd(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm256_maskz_cvtepi32_pd
- // CHECK: @llvm.x86.avx512.mask.cvtdq2pd.256
- return _mm256_maskz_cvtepi32_pd(__U,__A);
+ // CHECK: sitofp <4 x i32> %{{.*}} to <4 x double>
+ // CHECK: select <4 x i1> {{.*}}, <4 x double> {{.*}}, <4 x double> {{.*}}
+ return _mm256_maskz_cvtepi32_pd(__U,__A);
}
__m128 test_mm_mask_cvtepi32_ps(__m128 __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_cvtepi32_ps
@@ -1983,33 +2023,40 @@ __m256i test_mm256_maskz_cvttps_epu32(__mmask8 __U, __m256 __A) {
}
__m128d test_mm_cvtepu32_pd(__m128i __A) {
// CHECK-LABEL: @test_mm_cvtepu32_pd
- // CHECK: @llvm.x86.avx512.mask.cvtudq2pd.128
- return _mm_cvtepu32_pd(__A);
+ // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <2 x i32> <i32 0, i32 1>
+ // CHECK: uitofp <2 x i32> %{{.*}} to <2 x double>
+ return _mm_cvtepu32_pd(__A);
}
__m128d test_mm_mask_cvtepu32_pd(__m128d __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_cvtepu32_pd
- // CHECK: @llvm.x86.avx512.mask.cvtudq2pd.128
- return _mm_mask_cvtepu32_pd(__W,__U,__A);
+ // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <2 x i32> <i32 0, i32 1>
+ // CHECK: uitofp <2 x i32> %{{.*}} to <2 x double>
+ // CHECK: select <2 x i1> {{.*}}, <2 x double> {{.*}}, <2 x double> {{.*}}
+ return _mm_mask_cvtepu32_pd(__W,__U,__A);
}
__m128d test_mm_maskz_cvtepu32_pd(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_maskz_cvtepu32_pd
- // CHECK: @llvm.x86.avx512.mask.cvtudq2pd.128
- return _mm_maskz_cvtepu32_pd(__U,__A);
+ // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <2 x i32> <i32 0, i32 1>
+ // CHECK: uitofp <2 x i32> %{{.*}} to <2 x double>
+ // CHECK: select <2 x i1> {{.*}}, <2 x double> {{.*}}, <2 x double> {{.*}}
+ return _mm_maskz_cvtepu32_pd(__U,__A);
}
__m256d test_mm256_cvtepu32_pd(__m128i __A) {
// CHECK-LABEL: @test_mm256_cvtepu32_pd
- // CHECK: @llvm.x86.avx512.mask.cvtudq2pd.256
- return _mm256_cvtepu32_pd(__A);
+ // CHECK: uitofp <4 x i32> %{{.*}} to <4 x double>
+ return _mm256_cvtepu32_pd(__A);
}
__m256d test_mm256_mask_cvtepu32_pd(__m256d __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm256_mask_cvtepu32_pd
- // CHECK: @llvm.x86.avx512.mask.cvtudq2pd.256
- return _mm256_mask_cvtepu32_pd(__W,__U,__A);
+ // CHECK: uitofp <4 x i32> %{{.*}} to <4 x double>
+ // CHECK: select <4 x i1> {{.*}}, <4 x double> {{.*}}, <4 x double> {{.*}}
+ return _mm256_mask_cvtepu32_pd(__W,__U,__A);
}
__m256d test_mm256_maskz_cvtepu32_pd(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm256_maskz_cvtepu32_pd
- // CHECK: @llvm.x86.avx512.mask.cvtudq2pd.256
- return _mm256_maskz_cvtepu32_pd(__U,__A);
+ // CHECK: uitofp <4 x i32> %{{.*}} to <4 x double>
+ // CHECK: select <4 x i1> {{.*}}, <4 x double> {{.*}}, <4 x double> {{.*}}
+ return _mm256_maskz_cvtepu32_pd(__U,__A);
}
__m128 test_mm_cvtepu32_ps(__m128i __A) {
// CHECK-LABEL: @test_mm_cvtepu32_ps
@@ -2043,42 +2090,50 @@ __m256 test_mm256_maskz_cvtepu32_ps(__mmask8 __U, __m256i __A) {
}
__m128d test_mm_mask_div_pd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
// CHECK-LABEL: @test_mm_mask_div_pd
- // CHECK: @llvm.x86.avx512.mask.div.pd.128
+ // CHECK: fdiv <2 x double> %{{.*}}, %{{.*}}
+ // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return _mm_mask_div_pd(__W,__U,__A,__B);
}
__m128d test_mm_maskz_div_pd(__mmask8 __U, __m128d __A, __m128d __B) {
// CHECK-LABEL: @test_mm_maskz_div_pd
- // CHECK: @llvm.x86.avx512.mask.div.pd.128
+ // CHECK: fdiv <2 x double> %{{.*}}, %{{.*}}
+ // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return _mm_maskz_div_pd(__U,__A,__B);
}
__m256d test_mm256_mask_div_pd(__m256d __W, __mmask8 __U, __m256d __A, __m256d __B) {
// CHECK-LABEL: @test_mm256_mask_div_pd
- // CHECK: @llvm.x86.avx512.mask.div.pd.256
+ // CHECK: fdiv <4 x double> %{{.*}}, %{{.*}}
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_mask_div_pd(__W,__U,__A,__B);
}
__m256d test_mm256_maskz_div_pd(__mmask8 __U, __m256d __A, __m256d __B) {
// CHECK-LABEL: @test_mm256_maskz_div_pd
- // CHECK: @llvm.x86.avx512.mask.div.pd.256
+ // CHECK: fdiv <4 x double> %{{.*}}, %{{.*}}
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_maskz_div_pd(__U,__A,__B);
}
__m128 test_mm_mask_div_ps(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_mask_div_ps
- // CHECK: @llvm.x86.avx512.mask.div.ps.128
+ // CHECK: fdiv <4 x float> %{{.*}}, %{{.*}}
+ // 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(__mmask8 __U, __m128 __A, __m128 __B) {
+__m128 test_mm_maskz_div_ps(__mmask16 __U, __m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_maskz_div_ps
- // CHECK: @llvm.x86.avx512.mask.div.ps.128
+ // CHECK: fdiv <4 x float> %{{.*}}, %{{.*}}
+ // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return _mm_maskz_div_ps(__U,__A,__B);
}
__m256 test_mm256_mask_div_ps(__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) {
// CHECK-LABEL: @test_mm256_mask_div_ps
- // CHECK: @llvm.x86.avx512.mask.div.ps.256
+ // CHECK: fdiv <8 x float> %{{.*}}, %{{.*}}
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_mask_div_ps(__W,__U,__A,__B);
}
__m256 test_mm256_maskz_div_ps(__mmask8 __U, __m256 __A, __m256 __B) {
// CHECK-LABEL: @test_mm256_maskz_div_ps
- // CHECK: @llvm.x86.avx512.mask.div.ps.256
+ // CHECK: fdiv <8 x float> %{{.*}}, %{{.*}}
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_maskz_div_ps(__U,__A,__B);
}
__m128d test_mm_mask_expand_pd(__m128d __W, __mmask8 __U, __m128d __A) {
@@ -2303,142 +2358,170 @@ __m256 test_mm256_maskz_getexp_ps(__mmask8 __U, __m256 __A) {
}
__m128d test_mm_mask_max_pd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
// CHECK-LABEL: @test_mm_mask_max_pd
- // CHECK: @llvm.x86.avx512.mask.max.pd
+ // CHECK: @llvm.x86.sse2.max.pd
+ // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return _mm_mask_max_pd(__W,__U,__A,__B);
}
__m128d test_mm_maskz_max_pd(__mmask8 __U, __m128d __A, __m128d __B) {
// CHECK-LABEL: @test_mm_maskz_max_pd
- // CHECK: @llvm.x86.avx512.mask.max.pd
+ // CHECK: @llvm.x86.sse2.max.pd
+ // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return _mm_maskz_max_pd(__U,__A,__B);
}
__m256d test_mm256_mask_max_pd(__m256d __W, __mmask8 __U, __m256d __A, __m256d __B) {
// CHECK-LABEL: @test_mm256_mask_max_pd
- // CHECK: @llvm.x86.avx512.mask.max.pd.256
+ // CHECK: @llvm.x86.avx.max.pd.256
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_mask_max_pd(__W,__U,__A,__B);
}
__m256d test_mm256_maskz_max_pd(__mmask8 __U, __m256d __A, __m256d __B) {
// CHECK-LABEL: @test_mm256_maskz_max_pd
- // CHECK: @llvm.x86.avx512.mask.max.pd.256
+ // CHECK: @llvm.x86.avx.max.pd.256
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_maskz_max_pd(__U,__A,__B);
}
__m128 test_mm_mask_max_ps(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_mask_max_ps
- // CHECK: @llvm.x86.avx512.mask.max.ps
+ // CHECK: @llvm.x86.sse.max.ps
+ // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return _mm_mask_max_ps(__W,__U,__A,__B);
}
__m128 test_mm_maskz_max_ps(__mmask8 __U, __m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_maskz_max_ps
- // CHECK: @llvm.x86.avx512.mask.max.ps
+ // CHECK: @llvm.x86.sse.max.ps
+ // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return _mm_maskz_max_ps(__U,__A,__B);
}
__m256 test_mm256_mask_max_ps(__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) {
// CHECK-LABEL: @test_mm256_mask_max_ps
- // CHECK: @llvm.x86.avx512.mask.max.ps.256
+ // CHECK: @llvm.x86.avx.max.ps.256
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_mask_max_ps(__W,__U,__A,__B);
}
__m256 test_mm256_maskz_max_ps(__mmask8 __U, __m256 __A, __m256 __B) {
// CHECK-LABEL: @test_mm256_maskz_max_ps
- // CHECK: @llvm.x86.avx512.mask.max.ps.256
+ // CHECK: @llvm.x86.avx.max.ps.256
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_maskz_max_ps(__U,__A,__B);
}
__m128d test_mm_mask_min_pd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
// CHECK-LABEL: @test_mm_mask_min_pd
- // CHECK: @llvm.x86.avx512.mask.min.pd
+ // CHECK: @llvm.x86.sse2.min.pd
+ // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return _mm_mask_min_pd(__W,__U,__A,__B);
}
__m128d test_mm_maskz_min_pd(__mmask8 __U, __m128d __A, __m128d __B) {
// CHECK-LABEL: @test_mm_maskz_min_pd
- // CHECK: @llvm.x86.avx512.mask.min.pd
+ // CHECK: @llvm.x86.sse2.min.pd
+ // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return _mm_maskz_min_pd(__U,__A,__B);
}
__m256d test_mm256_mask_min_pd(__m256d __W, __mmask8 __U, __m256d __A, __m256d __B) {
// CHECK-LABEL: @test_mm256_mask_min_pd
- // CHECK: @llvm.x86.avx512.mask.min.pd.256
+ // CHECK: @llvm.x86.avx.min.pd.256
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_mask_min_pd(__W,__U,__A,__B);
}
__m256d test_mm256_maskz_min_pd(__mmask8 __U, __m256d __A, __m256d __B) {
// CHECK-LABEL: @test_mm256_maskz_min_pd
- // CHECK: @llvm.x86.avx512.mask.min.pd.256
+ // CHECK: @llvm.x86.avx.min.pd.256
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_maskz_min_pd(__U,__A,__B);
}
__m128 test_mm_mask_min_ps(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_mask_min_ps
- // CHECK: @llvm.x86.avx512.mask.min.ps
+ // CHECK: @llvm.x86.sse.min.ps
+ // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return _mm_mask_min_ps(__W,__U,__A,__B);
}
__m128 test_mm_maskz_min_ps(__mmask8 __U, __m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_maskz_min_ps
- // CHECK: @llvm.x86.avx512.mask.min.ps
+ // CHECK: @llvm.x86.sse.min.ps
+ // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return _mm_maskz_min_ps(__U,__A,__B);
}
__m256 test_mm256_mask_min_ps(__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) {
// CHECK-LABEL: @test_mm256_mask_min_ps
- // CHECK: @llvm.x86.avx512.mask.min.ps.256
+ // CHECK: @llvm.x86.avx.min.ps.256
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_mask_min_ps(__W,__U,__A,__B);
}
__m256 test_mm256_maskz_min_ps(__mmask8 __U, __m256 __A, __m256 __B) {
// CHECK-LABEL: @test_mm256_maskz_min_ps
- // CHECK: @llvm.x86.avx512.mask.min.ps.256
+ // CHECK: @llvm.x86.avx.min.ps.256
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_maskz_min_ps(__U,__A,__B);
}
__m128d test_mm_mask_mul_pd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
// CHECK-LABEL: @test_mm_mask_mul_pd
- // CHECK: @llvm.x86.avx512.mask.mul.pd
+ // CHECK: fmul <2 x double> %{{.*}}, %{{.*}}
+ // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return _mm_mask_mul_pd(__W,__U,__A,__B);
}
__m128d test_mm_maskz_mul_pd(__mmask8 __U, __m128d __A, __m128d __B) {
// CHECK-LABEL: @test_mm_maskz_mul_pd
- // CHECK: @llvm.x86.avx512.mask.mul.pd
+ // CHECK: fmul <2 x double> %{{.*}}, %{{.*}}
+ // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return _mm_maskz_mul_pd(__U,__A,__B);
}
__m256d test_mm256_mask_mul_pd(__m256d __W, __mmask8 __U, __m256d __A, __m256d __B) {
// CHECK-LABEL: @test_mm256_mask_mul_pd
- // CHECK: @llvm.x86.avx512.mask.mul.pd.256
+ // CHECK: fmul <4 x double> %{{.*}}, %{{.*}}
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_mask_mul_pd(__W,__U,__A,__B);
}
__m256d test_mm256_maskz_mul_pd(__mmask8 __U, __m256d __A, __m256d __B) {
// CHECK-LABEL: @test_mm256_maskz_mul_pd
- // CHECK: @llvm.x86.avx512.mask.mul.pd.256
+ // CHECK: fmul <4 x double> %{{.*}}, %{{.*}}
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_maskz_mul_pd(__U,__A,__B);
}
__m128 test_mm_mask_mul_ps(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_mask_mul_ps
- // CHECK: @llvm.x86.avx512.mask.mul.ps
+ // CHECK: fmul <4 x float> %{{.*}}, %{{.*}}
+ // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return _mm_mask_mul_ps(__W,__U,__A,__B);
}
__m128 test_mm_maskz_mul_ps(__mmask8 __U, __m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_maskz_mul_ps
- // CHECK: @llvm.x86.avx512.mask.mul.ps
+ // CHECK: fmul <4 x float> %{{.*}}, %{{.*}}
+ // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return _mm_maskz_mul_ps(__U,__A,__B);
}
__m256 test_mm256_mask_mul_ps(__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) {
// CHECK-LABEL: @test_mm256_mask_mul_ps
- // CHECK: @llvm.x86.avx512.mask.mul.ps.256
+ // CHECK: fmul <8 x float> %{{.*}}, %{{.*}}
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_mask_mul_ps(__W,__U,__A,__B);
}
__m256 test_mm256_maskz_mul_ps(__mmask8 __U, __m256 __A, __m256 __B) {
// CHECK-LABEL: @test_mm256_maskz_mul_ps
- // CHECK: @llvm.x86.avx512.mask.mul.ps.256
+ // CHECK: fmul <8 x float> %{{.*}}, %{{.*}}
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_maskz_mul_ps(__U,__A,__B);
}
__m128i test_mm_mask_abs_epi32(__m128i __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_abs_epi32
- // CHECK: @llvm.x86.avx512.mask.pabs.d.128
+ // CHECK: @llvm.x86.ssse3.pabs.d.128
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_mask_abs_epi32(__W,__U,__A);
}
__m128i test_mm_maskz_abs_epi32(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_maskz_abs_epi32
- // CHECK: @llvm.x86.avx512.mask.pabs.d.128
+ // CHECK: @llvm.x86.ssse3.pabs.d.128
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_maskz_abs_epi32(__U,__A);
}
__m256i test_mm256_mask_abs_epi32(__m256i __W, __mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_mask_abs_epi32
- // CHECK: @llvm.x86.avx512.mask.pabs.d.256
+ // CHECK: @llvm.x86.avx2.pabs.d
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_mask_abs_epi32(__W,__U,__A);
}
__m256i test_mm256_maskz_abs_epi32(__mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_maskz_abs_epi32
- // CHECK: @llvm.x86.avx512.mask.pabs.d.256
+ // CHECK: @llvm.x86.avx2.pabs.d
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_maskz_abs_epi32(__U,__A);
}
__m128i test_mm_abs_epi64(__m128i __A) {
@@ -2473,202 +2556,274 @@ __m256i test_mm256_maskz_abs_epi64(__mmask8 __U, __m256i __A) {
}
__m128i test_mm_maskz_max_epi32(__mmask8 __M, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_max_epi32
- // CHECK: @llvm.x86.avx512.mask.pmaxs.d.128
+ // CHECK: [[CMP:%.*]] = icmp sgt <4 x i32> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <4 x i1> [[CMP]], <4 x i32> [[X]], <4 x i32> [[Y]]
+ // CHECK: select <4 x i1> {{.*}}, <4 x i32> [[RES]], <4 x i32> {{.*}}
return _mm_maskz_max_epi32(__M,__A,__B);
}
__m128i test_mm_mask_max_epi32(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_max_epi32
- // CHECK: @llvm.x86.avx512.mask.pmaxs.d.128
+ // CHECK: [[CMP:%.*]] = icmp sgt <4 x i32> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <4 x i1> [[CMP]], <4 x i32> [[X]], <4 x i32> [[Y]]
+ // CHECK: select <4 x i1> {{.*}}, <4 x i32> [[RES]], <4 x i32> {{.*}}
return _mm_mask_max_epi32(__W,__M,__A,__B);
}
__m256i test_mm256_maskz_max_epi32(__mmask8 __M, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_max_epi32
- // CHECK: @llvm.x86.avx512.mask.pmaxs.d.256
+ // CHECK: [[CMP:%.*]] = icmp sgt <8 x i32> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <8 x i1> [[CMP]], <8 x i32> [[X]], <8 x i32> [[Y]]
+ // CHECK: select <8 x i1> {{.*}}, <8 x i32> [[RES]], <8 x i32> {{.*}}
return _mm256_maskz_max_epi32(__M,__A,__B);
}
__m256i test_mm256_mask_max_epi32(__m256i __W, __mmask8 __M, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_max_epi32
- // CHECK: @llvm.x86.avx512.mask.pmaxs.d.256
+ // CHECK: [[CMP:%.*]] = icmp sgt <8 x i32> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <8 x i1> [[CMP]], <8 x i32> [[X]], <8 x i32> [[Y]]
+ // CHECK: select <8 x i1> {{.*}}, <8 x i32> [[RES]], <8 x i32> {{.*}}
return _mm256_mask_max_epi32(__W,__M,__A,__B);
}
__m128i test_mm_maskz_max_epi64(__mmask8 __M, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_max_epi64
- // CHECK: @llvm.x86.avx512.mask.pmaxs.q.128
+ // CHECK: [[CMP:%.*]] = icmp sgt <2 x i64> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <2 x i1> [[CMP]], <2 x i64> [[X]], <2 x i64> [[Y]]
+ // CHECK: select <2 x i1> {{.*}}, <2 x i64> [[RES]], <2 x i64> {{.*}}
return _mm_maskz_max_epi64(__M,__A,__B);
}
__m128i test_mm_mask_max_epi64(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_max_epi64
- // CHECK: @llvm.x86.avx512.mask.pmaxs.q.128
+ // CHECK: [[CMP:%.*]] = icmp sgt <2 x i64> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <2 x i1> [[CMP]], <2 x i64> [[X]], <2 x i64> [[Y]]
+ // CHECK: select <2 x i1> {{.*}}, <2 x i64> [[RES]], <2 x i64> {{.*}}
return _mm_mask_max_epi64(__W,__M,__A,__B);
}
__m128i test_mm_max_epi64(__m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_max_epi64
- // CHECK: @llvm.x86.avx512.mask.pmaxs.q.128
+ // CHECK: [[CMP:%.*]] = icmp sgt <2 x i64> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <2 x i1> [[CMP]], <2 x i64> [[X]], <2 x i64> [[Y]]
return _mm_max_epi64(__A,__B);
}
__m256i test_mm256_maskz_max_epi64(__mmask8 __M, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_max_epi64
- // CHECK: @llvm.x86.avx512.mask.pmaxs.q.256
+ // CHECK: [[CMP:%.*]] = icmp sgt <4 x i64> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <4 x i1> [[CMP]], <4 x i64> [[X]], <4 x i64> [[Y]]
+ // CHECK: select <4 x i1> {{.*}}, <4 x i64> [[RES]], <4 x i64> {{.*}}
return _mm256_maskz_max_epi64(__M,__A,__B);
}
__m256i test_mm256_mask_max_epi64(__m256i __W, __mmask8 __M, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_max_epi64
- // CHECK: @llvm.x86.avx512.mask.pmaxs.q.256
+ // CHECK: [[CMP:%.*]] = icmp sgt <4 x i64> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <4 x i1> [[CMP]], <4 x i64> [[X]], <4 x i64> [[Y]]
+ // CHECK: select <4 x i1> {{.*}}, <4 x i64> [[RES]], <4 x i64> {{.*}}
return _mm256_mask_max_epi64(__W,__M,__A,__B);
}
__m256i test_mm256_max_epi64(__m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_max_epi64
- // CHECK: @llvm.x86.avx512.mask.pmaxs.q.256
+ // CHECK: [[CMP:%.*]] = icmp sgt <4 x i64> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <4 x i1> [[CMP]], <4 x i64> [[X]], <4 x i64> [[Y]]
return _mm256_max_epi64(__A,__B);
}
__m128i test_mm_maskz_max_epu32(__mmask8 __M, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_max_epu32
- // CHECK: @llvm.x86.avx512.mask.pmaxu.d.128
+ // CHECK: [[CMP:%.*]] = icmp ugt <4 x i32> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <4 x i1> [[CMP]], <4 x i32> [[X]], <4 x i32> [[Y]]
+ // CHECK: select <4 x i1> {{.*}}, <4 x i32> [[RES]], <4 x i32> {{.*}}
return _mm_maskz_max_epu32(__M,__A,__B);
}
__m128i test_mm_mask_max_epu32(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_max_epu32
- // CHECK: @llvm.x86.avx512.mask.pmaxu.d.128
+ // CHECK: [[CMP:%.*]] = icmp ugt <4 x i32> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <4 x i1> [[CMP]], <4 x i32> [[X]], <4 x i32> [[Y]]
+ // CHECK: select <4 x i1> {{.*}}, <4 x i32> [[RES]], <4 x i32> {{.*}}
return _mm_mask_max_epu32(__W,__M,__A,__B);
}
__m256i test_mm256_maskz_max_epu32(__mmask8 __M, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_max_epu32
- // CHECK: @llvm.x86.avx512.mask.pmaxu.d.256
+ // CHECK: [[CMP:%.*]] = icmp ugt <8 x i32> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <8 x i1> [[CMP]], <8 x i32> [[X]], <8 x i32> [[Y]]
+ // CHECK: select <8 x i1> {{.*}}, <8 x i32> [[RES]], <8 x i32> {{.*}}
return _mm256_maskz_max_epu32(__M,__A,__B);
}
__m256i test_mm256_mask_max_epu32(__m256i __W, __mmask8 __M, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_max_epu32
- // CHECK: @llvm.x86.avx512.mask.pmaxu.d.256
+ // CHECK: [[CMP:%.*]] = icmp ugt <8 x i32> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <8 x i1> [[CMP]], <8 x i32> [[X]], <8 x i32> [[Y]]
+ // CHECK: select <8 x i1> {{.*}}, <8 x i32> [[RES]], <8 x i32> {{.*}}
return _mm256_mask_max_epu32(__W,__M,__A,__B);
}
__m128i test_mm_maskz_max_epu64(__mmask8 __M, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_max_epu64
- // CHECK: @llvm.x86.avx512.mask.pmaxu.q.128
+ // CHECK: [[CMP:%.*]] = icmp ugt <2 x i64> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <2 x i1> [[CMP]], <2 x i64> [[X]], <2 x i64> [[Y]]
+ // CHECK: select <2 x i1> {{.*}}, <2 x i64> [[RES]], <2 x i64> {{.*}}
return _mm_maskz_max_epu64(__M,__A,__B);
}
__m128i test_mm_max_epu64(__m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_max_epu64
- // CHECK: @llvm.x86.avx512.mask.pmaxu.q.128
+ // CHECK: [[CMP:%.*]] = icmp ugt <2 x i64> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <2 x i1> [[CMP]], <2 x i64> [[X]], <2 x i64> [[Y]]
return _mm_max_epu64(__A,__B);
}
__m128i test_mm_mask_max_epu64(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_max_epu64
- // CHECK: @llvm.x86.avx512.mask.pmaxu.q.128
+ // CHECK: [[CMP:%.*]] = icmp ugt <2 x i64> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <2 x i1> [[CMP]], <2 x i64> [[X]], <2 x i64> [[Y]]
+ // CHECK: select <2 x i1> {{.*}}, <2 x i64> [[RES]], <2 x i64> {{.*}}
return _mm_mask_max_epu64(__W,__M,__A,__B);
}
__m256i test_mm256_maskz_max_epu64(__mmask8 __M, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_max_epu64
- // CHECK: @llvm.x86.avx512.mask.pmaxu.q.256
+ // CHECK: [[CMP:%.*]] = icmp ugt <4 x i64> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <4 x i1> [[CMP]], <4 x i64> [[X]], <4 x i64> [[Y]]
+ // CHECK: select <4 x i1> {{.*}}, <4 x i64> [[RES]], <4 x i64> {{.*}}
return _mm256_maskz_max_epu64(__M,__A,__B);
}
__m256i test_mm256_max_epu64(__m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_max_epu64
- // CHECK: @llvm.x86.avx512.mask.pmaxu.q.256
+ // CHECK: [[CMP:%.*]] = icmp ugt <4 x i64> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <4 x i1> [[CMP]], <4 x i64> [[X]], <4 x i64> [[Y]]
return _mm256_max_epu64(__A,__B);
}
__m256i test_mm256_mask_max_epu64(__m256i __W, __mmask8 __M, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_max_epu64
- // CHECK: @llvm.x86.avx512.mask.pmaxu.q.256
+ // CHECK: [[CMP:%.*]] = icmp ugt <4 x i64> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <4 x i1> [[CMP]], <4 x i64> [[X]], <4 x i64> [[Y]]
+ // CHECK: select <4 x i1> {{.*}}, <4 x i64> [[RES]], <4 x i64> {{.*}}
return _mm256_mask_max_epu64(__W,__M,__A,__B);
}
__m128i test_mm_maskz_min_epi32(__mmask8 __M, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_min_epi32
- // CHECK: @llvm.x86.avx512.mask.pmins.d.128
+ // CHECK: [[CMP:%.*]] = icmp slt <4 x i32> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <4 x i1> [[CMP]], <4 x i32> [[X]], <4 x i32> [[Y]]
+ // CHECK: select <4 x i1> {{.*}}, <4 x i32> [[RES]], <4 x i32> {{.*}}
return _mm_maskz_min_epi32(__M,__A,__B);
}
__m128i test_mm_mask_min_epi32(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_min_epi32
- // CHECK: @llvm.x86.avx512.mask.pmins.d.128
+ // CHECK: [[CMP:%.*]] = icmp slt <4 x i32> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <4 x i1> [[CMP]], <4 x i32> [[X]], <4 x i32> [[Y]]
+ // CHECK: select <4 x i1> {{.*}}, <4 x i32> [[RES]], <4 x i32> {{.*}}
return _mm_mask_min_epi32(__W,__M,__A,__B);
}
__m256i test_mm256_maskz_min_epi32(__mmask8 __M, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_min_epi32
- // CHECK: @llvm.x86.avx512.mask.pmins.d.256
+ // CHECK: [[CMP:%.*]] = icmp slt <8 x i32> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <8 x i1> [[CMP]], <8 x i32> [[X]], <8 x i32> [[Y]]
+ // CHECK: select <8 x i1> {{.*}}, <8 x i32> [[RES]], <8 x i32> {{.*}}
return _mm256_maskz_min_epi32(__M,__A,__B);
}
__m256i test_mm256_mask_min_epi32(__m256i __W, __mmask8 __M, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_min_epi32
- // CHECK: @llvm.x86.avx512.mask.pmins.d.256
+ // CHECK: [[CMP:%.*]] = icmp slt <8 x i32> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <8 x i1> [[CMP]], <8 x i32> [[X]], <8 x i32> [[Y]]
+ // CHECK: select <8 x i1> {{.*}}, <8 x i32> [[RES]], <8 x i32> {{.*}}
return _mm256_mask_min_epi32(__W,__M,__A,__B);
}
__m128i test_mm_min_epi64(__m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_min_epi64
- // CHECK: @llvm.x86.avx512.mask.pmins.q.128
+ // CHECK: [[CMP:%.*]] = icmp slt <2 x i64> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <2 x i1> [[CMP]], <2 x i64> [[X]], <2 x i64> [[Y]]
return _mm_min_epi64(__A,__B);
}
__m128i test_mm_mask_min_epi64(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_min_epi64
- // CHECK: @llvm.x86.avx512.mask.pmins.q.128
+ // CHECK: [[CMP:%.*]] = icmp slt <2 x i64> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <2 x i1> [[CMP]], <2 x i64> [[X]], <2 x i64> [[Y]]
+ // CHECK: select <2 x i1> {{.*}}, <2 x i64> [[RES]], <2 x i64> {{.*}}
return _mm_mask_min_epi64(__W,__M,__A,__B);
}
__m128i test_mm_maskz_min_epi64(__mmask8 __M, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_min_epi64
- // CHECK: @llvm.x86.avx512.mask.pmins.q.128
+ // CHECK: [[CMP:%.*]] = icmp slt <2 x i64> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <2 x i1> [[CMP]], <2 x i64> [[X]], <2 x i64> [[Y]]
+ // CHECK: select <2 x i1> {{.*}}, <2 x i64> [[RES]], <2 x i64> {{.*}}
return _mm_maskz_min_epi64(__M,__A,__B);
}
__m256i test_mm256_min_epi64(__m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_min_epi64
- // CHECK: @llvm.x86.avx512.mask.pmins.q.256
+ // CHECK: [[CMP:%.*]] = icmp slt <4 x i64> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <4 x i1> [[CMP]], <4 x i64> [[X]], <4 x i64> [[Y]]
return _mm256_min_epi64(__A,__B);
}
__m256i test_mm256_mask_min_epi64(__m256i __W, __mmask8 __M, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_min_epi64
- // CHECK: @llvm.x86.avx512.mask.pmins.q.256
+ // CHECK: [[CMP:%.*]] = icmp slt <4 x i64> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <4 x i1> [[CMP]], <4 x i64> [[X]], <4 x i64> [[Y]]
+ // CHECK: select <4 x i1> {{.*}}, <4 x i64> [[RES]], <4 x i64> {{.*}}
return _mm256_mask_min_epi64(__W,__M,__A,__B);
}
__m256i test_mm256_maskz_min_epi64(__mmask8 __M, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_min_epi64
- // CHECK: @llvm.x86.avx512.mask.pmins.q.256
+ // CHECK: [[CMP:%.*]] = icmp slt <4 x i64> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <4 x i1> [[CMP]], <4 x i64> [[X]], <4 x i64> [[Y]]
+ // CHECK: select <4 x i1> {{.*}}, <4 x i64> [[RES]], <4 x i64> {{.*}}
return _mm256_maskz_min_epi64(__M,__A,__B);
}
__m128i test_mm_maskz_min_epu32(__mmask8 __M, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_min_epu32
- // CHECK: @llvm.x86.avx512.mask.pminu.d.128
+ // CHECK: [[CMP:%.*]] = icmp ult <4 x i32> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <4 x i1> [[CMP]], <4 x i32> [[X]], <4 x i32> [[Y]]
+ // CHECK: select <4 x i1> {{.*}}, <4 x i32> [[RES]], <4 x i32> {{.*}}
return _mm_maskz_min_epu32(__M,__A,__B);
}
__m128i test_mm_mask_min_epu32(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_min_epu32
- // CHECK: @llvm.x86.avx512.mask.pminu.d.128
+ // CHECK: [[CMP:%.*]] = icmp ult <4 x i32> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <4 x i1> [[CMP]], <4 x i32> [[X]], <4 x i32> [[Y]]
+ // CHECK: select <4 x i1> {{.*}}, <4 x i32> [[RES]], <4 x i32> {{.*}}
return _mm_mask_min_epu32(__W,__M,__A,__B);
}
__m256i test_mm256_maskz_min_epu32(__mmask8 __M, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_min_epu32
- // CHECK: @llvm.x86.avx512.mask.pminu.d.256
+ // CHECK: [[CMP:%.*]] = icmp ult <8 x i32> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <8 x i1> [[CMP]], <8 x i32> [[X]], <8 x i32> [[Y]]
+ // CHECK: select <8 x i1> {{.*}}, <8 x i32> [[RES]], <8 x i32> {{.*}}
return _mm256_maskz_min_epu32(__M,__A,__B);
}
__m256i test_mm256_mask_min_epu32(__m256i __W, __mmask8 __M, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_min_epu32
- // CHECK: @llvm.x86.avx512.mask.pminu.d.256
+ // CHECK: [[CMP:%.*]] = icmp ult <8 x i32> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <8 x i1> [[CMP]], <8 x i32> [[X]], <8 x i32> [[Y]]
+ // CHECK: select <8 x i1> {{.*}}, <8 x i32> [[RES]], <8 x i32> {{.*}}
return _mm256_mask_min_epu32(__W,__M,__A,__B);
}
__m128i test_mm_min_epu64(__m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_min_epu64
- // CHECK: @llvm.x86.avx512.mask.pminu.q.128
+ // CHECK: [[CMP:%.*]] = icmp ult <2 x i64> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <2 x i1> [[CMP]], <2 x i64> [[X]], <2 x i64> [[Y]]
return _mm_min_epu64(__A,__B);
}
__m128i test_mm_mask_min_epu64(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_min_epu64
- // CHECK: @llvm.x86.avx512.mask.pminu.q.128
+ // CHECK: [[CMP:%.*]] = icmp ult <2 x i64> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <2 x i1> [[CMP]], <2 x i64> [[X]], <2 x i64> [[Y]]
+ // CHECK: select <2 x i1> {{.*}}, <2 x i64> [[RES]], <2 x i64> {{.*}}
return _mm_mask_min_epu64(__W,__M,__A,__B);
}
__m128i test_mm_maskz_min_epu64(__mmask8 __M, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_min_epu64
- // CHECK: @llvm.x86.avx512.mask.pminu.q.128
+ // CHECK: [[CMP:%.*]] = icmp ult <2 x i64> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <2 x i1> [[CMP]], <2 x i64> [[X]], <2 x i64> [[Y]]
+ // CHECK: select <2 x i1> {{.*}}, <2 x i64> [[RES]], <2 x i64> {{.*}}
return _mm_maskz_min_epu64(__M,__A,__B);
}
__m256i test_mm256_min_epu64(__m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_min_epu64
- // CHECK: @llvm.x86.avx512.mask.pminu.q.256
+ // CHECK: [[CMP:%.*]] = icmp ult <4 x i64> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <4 x i1> [[CMP]], <4 x i64> [[X]], <4 x i64> [[Y]]
return _mm256_min_epu64(__A,__B);
}
__m256i test_mm256_mask_min_epu64(__m256i __W, __mmask8 __M, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_min_epu64
- // CHECK: @llvm.x86.avx512.mask.pminu.q.256
+ // CHECK: [[CMP:%.*]] = icmp ult <4 x i64> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <4 x i1> [[CMP]], <4 x i64> [[X]], <4 x i64> [[Y]]
+ // CHECK: select <4 x i1> {{.*}}, <4 x i64> [[RES]], <4 x i64> {{.*}}
return _mm256_mask_min_epu64(__W,__M,__A,__B);
}
__m256i test_mm256_maskz_min_epu64(__mmask8 __M, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_min_epu64
- // CHECK: @llvm.x86.avx512.mask.pminu.q.256
+ // CHECK: [[CMP:%.*]] = icmp ult <4 x i64> [[X:%.*]], [[Y:%.*]]
+ // CHECK-NEXT: [[RES:%.*]] = select <4 x i1> [[CMP]], <4 x i64> [[X]], <4 x i64> [[Y]]
+ // CHECK: select <4 x i1> {{.*}}, <4 x i64> [[RES]], <4 x i64> {{.*}}
return _mm256_maskz_min_epu64(__M,__A,__B);
}
__m128d test_mm_roundscale_pd(__m128d __A) {
@@ -2953,82 +3108,98 @@ 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.avx512.mask.sqrt.pd.128
+ // CHECK: @llvm.x86.sse2.sqrt.pd
+ // 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.avx512.mask.sqrt.pd.128
+ // CHECK: @llvm.x86.sse2.sqrt.pd
+ // 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.avx512.mask.sqrt.pd.256
+ // CHECK: @llvm.x86.avx.sqrt.pd.256
+ // 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.avx512.mask.sqrt.pd.256
+ // CHECK: @llvm.x86.avx.sqrt.pd.256
+ // 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.avx512.mask.sqrt.ps.128
+ // CHECK: @llvm.x86.sse.sqrt.ps
+ // 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.avx512.mask.sqrt.ps.128
+ // CHECK: @llvm.x86.sse.sqrt.ps
+ // 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.avx512.mask.sqrt.ps.256
+ // CHECK: @llvm.x86.avx.sqrt.ps.256
+ // 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.avx512.mask.sqrt.ps.256
+ // CHECK: @llvm.x86.avx.sqrt.ps.256
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_maskz_sqrt_ps(__U,__A);
}
__m128d test_mm_mask_sub_pd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
// CHECK-LABEL: @test_mm_mask_sub_pd
- // CHECK: @llvm.x86.avx512.mask.sub.pd.128
+ // CHECK: fsub <2 x double> %{{.*}}, %{{.*}}
+ // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return _mm_mask_sub_pd(__W,__U,__A,__B);
}
__m128d test_mm_maskz_sub_pd(__mmask8 __U, __m128d __A, __m128d __B) {
// CHECK-LABEL: @test_mm_maskz_sub_pd
- // CHECK: @llvm.x86.avx512.mask.sub.pd.128
+ // CHECK: fsub <2 x double> %{{.*}}, %{{.*}}
+ // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return _mm_maskz_sub_pd(__U,__A,__B);
}
__m256d test_mm256_mask_sub_pd(__m256d __W, __mmask8 __U, __m256d __A, __m256d __B) {
// CHECK-LABEL: @test_mm256_mask_sub_pd
- // CHECK: @llvm.x86.avx512.mask.sub.pd.256
+ // CHECK: fsub <4 x double> %{{.*}}, %{{.*}}
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_mask_sub_pd(__W,__U,__A,__B);
}
__m256d test_mm256_maskz_sub_pd(__mmask8 __U, __m256d __A, __m256d __B) {
// CHECK-LABEL: @test_mm256_maskz_sub_pd
- // CHECK: @llvm.x86.avx512.mask.sub.pd.256
+ // CHECK: fsub <4 x double> %{{.*}}, %{{.*}}
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_maskz_sub_pd(__U,__A,__B);
}
-__m128 test_mm_mask_sub_ps(__m128 __W, __mmask16 __U, __m128 __A, __m128 __B) {
+__m128 test_mm_mask_sub_ps(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_mask_sub_ps
- // CHECK: @llvm.x86.avx512.mask.sub.ps.128
+ // CHECK: fsub <4 x float> %{{.*}}, %{{.*}}
+ // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return _mm_mask_sub_ps(__W,__U,__A,__B);
}
-__m128 test_mm_maskz_sub_ps(__mmask16 __U, __m128 __A, __m128 __B) {
+__m128 test_mm_maskz_sub_ps(__mmask8 __U, __m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_maskz_sub_ps
- // CHECK: @llvm.x86.avx512.mask.sub.ps.128
+ // CHECK: fsub <4 x float> %{{.*}}, %{{.*}}
+ // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return _mm_maskz_sub_ps(__U,__A,__B);
}
-__m256 test_mm256_mask_sub_ps(__m256 __W, __mmask16 __U, __m256 __A, __m256 __B) {
+__m256 test_mm256_mask_sub_ps(__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) {
// CHECK-LABEL: @test_mm256_mask_sub_ps
- // CHECK: @llvm.x86.avx512.mask.sub.ps.256
+ // CHECK: fsub <8 x float> %{{.*}}, %{{.*}}
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_mask_sub_ps(__W,__U,__A,__B);
}
-__m256 test_mm256_maskz_sub_ps(__mmask16 __U, __m256 __A, __m256 __B) {
+__m256 test_mm256_maskz_sub_ps(__mmask8 __U, __m256 __A, __m256 __B) {
// CHECK-LABEL: @test_mm256_maskz_sub_ps
- // CHECK: @llvm.x86.avx512.mask.sub.ps.256
+ // CHECK: fsub <8 x float> %{{.*}}, %{{.*}}
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_maskz_sub_ps(__U,__A,__B);
}
__m128i test_mm_mask2_permutex2var_epi32(__m128i __A, __m128i __I, __mmask8 __U, __m128i __B) {
@@ -3194,241 +3365,281 @@ __m256i test_mm256_maskz_permutex2var_epi64(__mmask8 __U, __m256i __A, __m256i _
__m128i test_mm_mask_cvtepi8_epi32(__m128i __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_cvtepi8_epi32
- // CHECK: @llvm.x86.avx512.mask.pmovsxb.d.128
+ // CHECK: sext <4 x i8> %{{.*}} to <4 x i32>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_mask_cvtepi8_epi32(__W, __U, __A);
}
__m128i test_mm_maskz_cvtepi8_epi32(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_maskz_cvtepi8_epi32
- // CHECK: @llvm.x86.avx512.mask.pmovsxb.d.128
+ // CHECK: sext <4 x i8> %{{.*}} to <4 x i32>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_maskz_cvtepi8_epi32(__U, __A);
}
__m256i test_mm256_mask_cvtepi8_epi32(__m256i __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm256_mask_cvtepi8_epi32
- // CHECK: @llvm.x86.avx512.mask.pmovsxb.d.256
+ // CHECK: sext <8 x i8> %{{.*}} to <8 x i32>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_mask_cvtepi8_epi32(__W, __U, __A);
}
__m256i test_mm256_maskz_cvtepi8_epi32(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm256_maskz_cvtepi8_epi32
- // CHECK: @llvm.x86.avx512.mask.pmovsxb.d.256
+ // CHECK: sext <8 x i8> %{{.*}} to <8 x i32>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_maskz_cvtepi8_epi32(__U, __A);
}
__m128i test_mm_mask_cvtepi8_epi64(__m128i __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_cvtepi8_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovsxb.q.128
+ // CHECK: sext <2 x i8> %{{.*}} to <2 x i64>
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_mask_cvtepi8_epi64(__W, __U, __A);
}
__m128i test_mm_maskz_cvtepi8_epi64(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_maskz_cvtepi8_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovsxb.q.128
+ // CHECK: sext <2 x i8> %{{.*}} to <2 x i64>
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_maskz_cvtepi8_epi64(__U, __A);
}
__m256i test_mm256_mask_cvtepi8_epi64(__m256i __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm256_mask_cvtepi8_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovsxb.q.256
+ // CHECK: sext <4 x i8> %{{.*}} to <4 x i64>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_mask_cvtepi8_epi64(__W, __U, __A);
}
__m256i test_mm256_maskz_cvtepi8_epi64(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm256_maskz_cvtepi8_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovsxb.q.256
+ // CHECK: sext <4 x i8> %{{.*}} to <4 x i64>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_maskz_cvtepi8_epi64(__U, __A);
}
__m128i test_mm_mask_cvtepi32_epi64(__m128i __W, __mmask8 __U, __m128i __X) {
// CHECK-LABEL: @test_mm_mask_cvtepi32_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovsxd.q.128
+ // CHECK: sext <2 x i32> %{{.*}} to <2 x i64>
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_mask_cvtepi32_epi64(__W, __U, __X);
}
__m128i test_mm_maskz_cvtepi32_epi64(__mmask8 __U, __m128i __X) {
// CHECK-LABEL: @test_mm_maskz_cvtepi32_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovsxd.q.128
+ // CHECK: sext <2 x i32> %{{.*}} to <2 x i64>
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_maskz_cvtepi32_epi64(__U, __X);
}
__m256i test_mm256_mask_cvtepi32_epi64(__m256i __W, __mmask8 __U, __m128i __X) {
// CHECK-LABEL: @test_mm256_mask_cvtepi32_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovsxd.q.256
+ // CHECK: sext <4 x i32> %{{.*}} to <4 x i64>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_mask_cvtepi32_epi64(__W, __U, __X);
}
__m256i test_mm256_maskz_cvtepi32_epi64(__mmask8 __U, __m128i __X) {
// CHECK-LABEL: @test_mm256_maskz_cvtepi32_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovsxd.q.256
+ // CHECK: sext <4 x i32> %{{.*}} to <4 x i64>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_maskz_cvtepi32_epi64(__U, __X);
}
__m128i test_mm_mask_cvtepi16_epi32(__m128i __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_cvtepi16_epi32
- // CHECK: @llvm.x86.avx512.mask.pmovsxw.d.128
+ // CHECK: sext <4 x i16> %{{.*}} to <4 x i32>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_mask_cvtepi16_epi32(__W, __U, __A);
}
__m128i test_mm_maskz_cvtepi16_epi32(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_maskz_cvtepi16_epi32
- // CHECK: @llvm.x86.avx512.mask.pmovsxw.d.128
+ // CHECK: sext <4 x i16> %{{.*}} to <4 x i32>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_maskz_cvtepi16_epi32(__U, __A);
}
__m256i test_mm256_mask_cvtepi16_epi32(__m256i __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm256_mask_cvtepi16_epi32
- // CHECK: @llvm.x86.avx512.mask.pmovsxw.d.256
+ // CHECK: sext <8 x i16> %{{.*}} to <8 x i32>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_mask_cvtepi16_epi32(__W, __U, __A);
}
__m256i test_mm256_maskz_cvtepi16_epi32(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm256_maskz_cvtepi16_epi32
- // CHECK: @llvm.x86.avx512.mask.pmovsxw.d.256
+ // CHECK: sext <8 x i16> %{{.*}} to <8 x i32>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_maskz_cvtepi16_epi32(__U, __A);
}
__m128i test_mm_mask_cvtepi16_epi64(__m128i __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_cvtepi16_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovsxw.q.128
+ // CHECK: sext <2 x i16> %{{.*}} to <2 x i64>
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_mask_cvtepi16_epi64(__W, __U, __A);
}
__m128i test_mm_maskz_cvtepi16_epi64(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_maskz_cvtepi16_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovsxw.q.128
+ // CHECK: sext <2 x i16> %{{.*}} to <2 x i64>
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_maskz_cvtepi16_epi64(__U, __A);
}
__m256i test_mm256_mask_cvtepi16_epi64(__m256i __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm256_mask_cvtepi16_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovsxw.q.256
+ // CHECK: sext <4 x i16> %{{.*}} to <4 x i64>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_mask_cvtepi16_epi64(__W, __U, __A);
}
__m256i test_mm256_maskz_cvtepi16_epi64(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm256_maskz_cvtepi16_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovsxw.q.256
+ // CHECK: sext <4 x i16> %{{.*}} to <4 x i64>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_maskz_cvtepi16_epi64(__U, __A);
}
__m128i test_mm_mask_cvtepu8_epi32(__m128i __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_cvtepu8_epi32
- // CHECK: @llvm.x86.avx512.mask.pmovzxb.d.128
+ // CHECK: zext <4 x i8> %{{.*}} to <4 x i32>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_mask_cvtepu8_epi32(__W, __U, __A);
}
__m128i test_mm_maskz_cvtepu8_epi32(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_maskz_cvtepu8_epi32
- // CHECK: @llvm.x86.avx512.mask.pmovzxb.d.128
+ // CHECK: zext <4 x i8> %{{.*}} to <4 x i32>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_maskz_cvtepu8_epi32(__U, __A);
}
__m256i test_mm256_mask_cvtepu8_epi32(__m256i __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm256_mask_cvtepu8_epi32
- // CHECK: @llvm.x86.avx512.mask.pmovzxb.d.256
+ // CHECK: zext <8 x i8> %{{.*}} to <8 x i32>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_mask_cvtepu8_epi32(__W, __U, __A);
}
__m256i test_mm256_maskz_cvtepu8_epi32(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm256_maskz_cvtepu8_epi32
- // CHECK: @llvm.x86.avx512.mask.pmovzxb.d.256
+ // CHECK: zext <8 x i8> %{{.*}} to <8 x i32>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_maskz_cvtepu8_epi32(__U, __A);
}
__m128i test_mm_mask_cvtepu8_epi64(__m128i __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_cvtepu8_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovzxb.q.128
+ // CHECK: zext <2 x i8> %{{.*}} to <2 x i64>
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_mask_cvtepu8_epi64(__W, __U, __A);
}
__m128i test_mm_maskz_cvtepu8_epi64(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_maskz_cvtepu8_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovzxb.q.128
+ // CHECK: zext <2 x i8> %{{.*}} to <2 x i64>
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_maskz_cvtepu8_epi64(__U, __A);
}
__m256i test_mm256_mask_cvtepu8_epi64(__m256i __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm256_mask_cvtepu8_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovzxb.q.256
+ // CHECK: zext <4 x i8> %{{.*}} to <4 x i64>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_mask_cvtepu8_epi64(__W, __U, __A);
}
__m256i test_mm256_maskz_cvtepu8_epi64(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm256_maskz_cvtepu8_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovzxb.q.256
+ // CHECK: zext <4 x i8> %{{.*}} to <4 x i64>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_maskz_cvtepu8_epi64(__U, __A);
}
__m128i test_mm_mask_cvtepu32_epi64(__m128i __W, __mmask8 __U, __m128i __X) {
// CHECK-LABEL: @test_mm_mask_cvtepu32_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovzxd.q.128
+ // CHECK: zext <2 x i32> %{{.*}} to <2 x i64>
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_mask_cvtepu32_epi64(__W, __U, __X);
}
__m128i test_mm_maskz_cvtepu32_epi64(__mmask8 __U, __m128i __X) {
// CHECK-LABEL: @test_mm_maskz_cvtepu32_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovzxd.q.128
+ // CHECK: zext <2 x i32> %{{.*}} to <2 x i64>
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_maskz_cvtepu32_epi64(__U, __X);
}
__m256i test_mm256_mask_cvtepu32_epi64(__m256i __W, __mmask8 __U, __m128i __X) {
// CHECK-LABEL: @test_mm256_mask_cvtepu32_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovzxd.q.256
+ // CHECK: zext <4 x i32> %{{.*}} to <4 x i64>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_mask_cvtepu32_epi64(__W, __U, __X);
}
__m256i test_mm256_maskz_cvtepu32_epi64(__mmask8 __U, __m128i __X) {
// CHECK-LABEL: @test_mm256_maskz_cvtepu32_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovzxd.q.256
+ // CHECK: zext <4 x i32> %{{.*}} to <4 x i64>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_maskz_cvtepu32_epi64(__U, __X);
}
__m128i test_mm_mask_cvtepu16_epi32(__m128i __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_cvtepu16_epi32
- // CHECK: @llvm.x86.avx512.mask.pmovzxw.d.128
+ // CHECK: zext <4 x i16> %{{.*}} to <4 x i32>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_mask_cvtepu16_epi32(__W, __U, __A);
}
__m128i test_mm_maskz_cvtepu16_epi32(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_maskz_cvtepu16_epi32
- // CHECK: @llvm.x86.avx512.mask.pmovzxw.d.128
+ // CHECK: zext <4 x i16> %{{.*}} to <4 x i32>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_maskz_cvtepu16_epi32(__U, __A);
}
__m256i test_mm256_mask_cvtepu16_epi32(__m256i __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm256_mask_cvtepu16_epi32
- // CHECK: @llvm.x86.avx512.mask.pmovzxw.d.256
+ // CHECK: zext <8 x i16> %{{.*}} to <8 x i32>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_mask_cvtepu16_epi32(__W, __U, __A);
}
__m256i test_mm256_maskz_cvtepu16_epi32(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm256_maskz_cvtepu16_epi32
- // CHECK: @llvm.x86.avx512.mask.pmovzxw.d.256
+ // CHECK: zext <8 x i16> %{{.*}} to <8 x i32>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_maskz_cvtepu16_epi32(__U, __A);
}
__m128i test_mm_mask_cvtepu16_epi64(__m128i __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_cvtepu16_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovzxw.q.128
+ // CHECK: zext <2 x i16> %{{.*}} to <2 x i64>
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_mask_cvtepu16_epi64(__W, __U, __A);
}
__m128i test_mm_maskz_cvtepu16_epi64(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_maskz_cvtepu16_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovzxw.q.128
+ // CHECK: zext <2 x i16> %{{.*}} to <2 x i64>
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_maskz_cvtepu16_epi64(__U, __A);
}
__m256i test_mm256_mask_cvtepu16_epi64(__m256i __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm256_mask_cvtepu16_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovzxw.q.256
+ // CHECK: zext <4 x i16> %{{.*}} to <4 x i64>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_mask_cvtepu16_epi64(__W, __U, __A);
}
__m256i test_mm256_maskz_cvtepu16_epi64(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm256_maskz_cvtepu16_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovzxw.q.256
+ // CHECK: zext <4 x i16> %{{.*}} to <4 x i64>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_maskz_cvtepu16_epi64(__U, __A);
}
@@ -3723,253 +3934,405 @@ __m256i test_mm256_maskz_rorv_epi64(__mmask8 __U, __m256i __A, __m256i __B) {
__m128i test_mm_mask_sllv_epi64(__m128i __W, __mmask8 __U, __m128i __X, __m128i __Y) {
// CHECK-LABEL: @test_mm_mask_sllv_epi64
- // CHECK: @llvm.x86.avx512.mask.psllv
+ // CHECK: @llvm.x86.avx2.psllv.q
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_mask_sllv_epi64(__W, __U, __X, __Y);
}
__m128i test_mm_maskz_sllv_epi64(__mmask8 __U, __m128i __X, __m128i __Y) {
// CHECK-LABEL: @test_mm_maskz_sllv_epi64
- // CHECK: @llvm.x86.avx512.mask.psllv
+ // CHECK: @llvm.x86.avx2.psllv.q
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_maskz_sllv_epi64(__U, __X, __Y);
}
__m256i test_mm256_mask_sllv_epi64(__m256i __W, __mmask8 __U, __m256i __X, __m256i __Y) {
// CHECK-LABEL: @test_mm256_mask_sllv_epi64
- // CHECK: @llvm.x86.avx512.mask.psllv
+ // CHECK: @llvm.x86.avx2.psllv.q.256
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_mask_sllv_epi64(__W, __U, __X, __Y);
}
__m256i test_mm256_maskz_sllv_epi64(__mmask8 __U, __m256i __X, __m256i __Y) {
// CHECK-LABEL: @test_mm256_maskz_sllv_epi64
- // CHECK: @llvm.x86.avx512.mask.psllv
+ // CHECK: @llvm.x86.avx2.psllv.q.256
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_maskz_sllv_epi64(__U, __X, __Y);
}
__m128i test_mm_mask_sllv_epi32(__m128i __W, __mmask8 __U, __m128i __X, __m128i __Y) {
// CHECK-LABEL: @test_mm_mask_sllv_epi32
- // CHECK: @llvm.x86.avx512.mask.psllv
+ // CHECK: @llvm.x86.avx2.psllv.d
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_mask_sllv_epi32(__W, __U, __X, __Y);
}
__m128i test_mm_maskz_sllv_epi32(__mmask8 __U, __m128i __X, __m128i __Y) {
// CHECK-LABEL: @test_mm_maskz_sllv_epi32
- // CHECK: @llvm.x86.avx512.mask.psllv
+ // CHECK: @llvm.x86.avx2.psllv.d
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_maskz_sllv_epi32(__U, __X, __Y);
}
__m256i test_mm256_mask_sllv_epi32(__m256i __W, __mmask8 __U, __m256i __X, __m256i __Y) {
// CHECK-LABEL: @test_mm256_mask_sllv_epi32
- // CHECK: @llvm.x86.avx512.mask.psllv
+ // CHECK: @llvm.x86.avx2.psllv.d.256
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_mask_sllv_epi32(__W, __U, __X, __Y);
}
__m256i test_mm256_maskz_sllv_epi32(__mmask8 __U, __m256i __X, __m256i __Y) {
// CHECK-LABEL: @test_mm256_maskz_sllv_epi32
- // CHECK: @llvm.x86.avx512.mask.psllv
+ // CHECK: @llvm.x86.avx2.psllv.d.256
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_maskz_sllv_epi32(__U, __X, __Y);
}
__m128i test_mm_mask_srlv_epi64(__m128i __W, __mmask8 __U, __m128i __X, __m128i __Y) {
// CHECK-LABEL: @test_mm_mask_srlv_epi64
- // CHECK: @llvm.x86.avx512.mask.psrlv
+ // CHECK: @llvm.x86.avx2.psrlv.q
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_mask_srlv_epi64(__W, __U, __X, __Y);
}
__m128i test_mm_maskz_srlv_epi64(__mmask8 __U, __m128i __X, __m128i __Y) {
// CHECK-LABEL: @test_mm_maskz_srlv_epi64
- // CHECK: @llvm.x86.avx512.mask.psrlv
+ // CHECK: @llvm.x86.avx2.psrlv.q
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_maskz_srlv_epi64(__U, __X, __Y);
}
__m256i test_mm256_mask_srlv_epi64(__m256i __W, __mmask8 __U, __m256i __X, __m256i __Y) {
// CHECK-LABEL: @test_mm256_mask_srlv_epi64
- // CHECK: @llvm.x86.avx512.mask.psrlv
+ // CHECK: @llvm.x86.avx2.psrlv.q.256
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_mask_srlv_epi64(__W, __U, __X, __Y);
}
__m256i test_mm256_maskz_srlv_epi64(__mmask8 __U, __m256i __X, __m256i __Y) {
// CHECK-LABEL: @test_mm256_maskz_srlv_epi64
- // CHECK: @llvm.x86.avx512.mask.psrlv
+ // CHECK: @llvm.x86.avx2.psrlv.q.256
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_maskz_srlv_epi64(__U, __X, __Y);
}
__m128i test_mm_mask_srlv_epi32(__m128i __W, __mmask8 __U, __m128i __X, __m128i __Y) {
// CHECK-LABEL: @test_mm_mask_srlv_epi32
- // CHECK: @llvm.x86.avx512.mask.psrlv
+ // CHECK: @llvm.x86.avx2.psrlv.d
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_mask_srlv_epi32(__W, __U, __X, __Y);
}
__m128i test_mm_maskz_srlv_epi32(__mmask8 __U, __m128i __X, __m128i __Y) {
// CHECK-LABEL: @test_mm_maskz_srlv_epi32
- // CHECK: @llvm.x86.avx512.mask.psrlv
+ // CHECK: @llvm.x86.avx2.psrlv.d
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_maskz_srlv_epi32(__U, __X, __Y);
}
__m256i test_mm256_mask_srlv_epi32(__m256i __W, __mmask8 __U, __m256i __X, __m256i __Y) {
// CHECK-LABEL: @test_mm256_mask_srlv_epi32
- // CHECK: @llvm.x86.avx512.mask.psrlv
+ // CHECK: @llvm.x86.avx2.psrlv.d.256
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_mask_srlv_epi32(__W, __U, __X, __Y);
}
__m256i test_mm256_maskz_srlv_epi32(__mmask8 __U, __m256i __X, __m256i __Y) {
// CHECK-LABEL: @test_mm256_maskz_srlv_epi32
- // CHECK: @llvm.x86.avx512.mask.psrlv
+ // CHECK: @llvm.x86.avx2.psrlv.d.256
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_maskz_srlv_epi32(__U, __X, __Y);
}
__m128i test_mm_mask_srl_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_srl_epi32
- // CHECK: @llvm.x86.avx512.mask.psrl.d.128
+ // CHECK: @llvm.x86.sse2.psrl.d
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_mask_srl_epi32(__W, __U, __A, __B);
}
__m128i test_mm_maskz_srl_epi32(__mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_srl_epi32
- // CHECK: @llvm.x86.avx512.mask.psrl.d.128
+ // CHECK: @llvm.x86.sse2.psrl.d
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_maskz_srl_epi32(__U, __A, __B);
}
__m256i test_mm256_mask_srl_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m128i __B) {
// CHECK-LABEL: @test_mm256_mask_srl_epi32
- // CHECK: @llvm.x86.avx512.mask.psrl.d.256
+ // CHECK: @llvm.x86.avx2.psrl.d
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_mask_srl_epi32(__W, __U, __A, __B);
}
__m256i test_mm256_maskz_srl_epi32(__mmask8 __U, __m256i __A, __m128i __B) {
// CHECK-LABEL: @test_mm256_maskz_srl_epi32
- // CHECK: @llvm.x86.avx512.mask.psrl.d.256
+ // CHECK: @llvm.x86.avx2.psrl.d
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_maskz_srl_epi32(__U, __A, __B);
}
__m128i test_mm_mask_srli_epi32(__m128i __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_srli_epi32
- // CHECK: @llvm.x86.avx512.mask.psrl.di.128
+ // CHECK: @llvm.x86.sse2.psrli.d
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_mask_srli_epi32(__W, __U, __A, 5);
}
__m128i test_mm_maskz_srli_epi32(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_maskz_srli_epi32
- // CHECK: @llvm.x86.avx512.mask.psrl.di.128
+ // CHECK: @llvm.x86.sse2.psrli.d
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_maskz_srli_epi32(__U, __A, 5);
}
__m256i test_mm256_mask_srli_epi32(__m256i __W, __mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_mask_srli_epi32
- // CHECK: @llvm.x86.avx512.mask.psrl.di.256
+ // CHECK: @llvm.x86.avx2.psrli.d
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_mask_srli_epi32(__W, __U, __A, 5);
}
__m256i test_mm256_maskz_srli_epi32(__mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_maskz_srli_epi32
- // CHECK: @llvm.x86.avx512.mask.psrl.di.256
+ // CHECK: @llvm.x86.avx2.psrli.d
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_maskz_srli_epi32(__U, __A, 5);
}
__m128i test_mm_mask_srl_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_srl_epi64
- // CHECK: @llvm.x86.avx512.mask.psrl.q.128
+ // CHECK: @llvm.x86.sse2.psrl.q
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_mask_srl_epi64(__W, __U, __A, __B);
}
__m128i test_mm_maskz_srl_epi64(__mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_srl_epi64
- // CHECK: @llvm.x86.avx512.mask.psrl.q.128
+ // CHECK: @llvm.x86.sse2.psrl.q
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_maskz_srl_epi64(__U, __A, __B);
}
__m256i test_mm256_mask_srl_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m128i __B) {
// CHECK-LABEL: @test_mm256_mask_srl_epi64
- // CHECK: @llvm.x86.avx512.mask.psrl.q.256
+ // CHECK: @llvm.x86.avx2.psrl.q
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_mask_srl_epi64(__W, __U, __A, __B);
}
__m256i test_mm256_maskz_srl_epi64(__mmask8 __U, __m256i __A, __m128i __B) {
// CHECK-LABEL: @test_mm256_maskz_srl_epi64
- // CHECK: @llvm.x86.avx512.mask.psrl.q.256
+ // CHECK: @llvm.x86.avx2.psrl.q
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_maskz_srl_epi64(__U, __A, __B);
}
__m128i test_mm_mask_srli_epi64(__m128i __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_srli_epi64
- // CHECK: @llvm.x86.avx512.mask.psrl.qi.128
+ // CHECK: @llvm.x86.sse2.psrli.q
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_mask_srli_epi64(__W, __U, __A, 5);
}
__m128i test_mm_maskz_srli_epi64(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_maskz_srli_epi64
- // CHECK: @llvm.x86.avx512.mask.psrl.qi.128
+ // CHECK: @llvm.x86.sse2.psrli.q
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_maskz_srli_epi64(__U, __A, 5);
}
__m256i test_mm256_mask_srli_epi64(__m256i __W, __mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_mask_srli_epi64
- // CHECK: @llvm.x86.avx512.mask.psrl.qi.256
+ // CHECK: @llvm.x86.avx2.psrli.q
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_mask_srli_epi64(__W, __U, __A, 5);
}
__m256i test_mm256_maskz_srli_epi64(__mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_maskz_srli_epi64
- // CHECK: @llvm.x86.avx512.mask.psrl.qi.256
+ // CHECK: @llvm.x86.avx2.psrli.q
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_maskz_srli_epi64(__U, __A, 5);
}
+__m128i test_mm_mask_sll_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_mask_sll_epi32
+ // CHECK: @llvm.x86.sse2.psll.d
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
+ return _mm_mask_sll_epi32(__W, __U, __A, __B);
+}
+
+__m128i test_mm_maskz_sll_epi32(__mmask8 __U, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_maskz_sll_epi32
+ // CHECK: @llvm.x86.sse2.psll.d
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
+ return _mm_maskz_sll_epi32(__U, __A, __B);
+}
+
+__m256i test_mm256_mask_sll_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm256_mask_sll_epi32
+ // CHECK: @llvm.x86.avx2.psll.d
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
+ return _mm256_mask_sll_epi32(__W, __U, __A, __B);
+}
+
+__m256i test_mm256_maskz_sll_epi32(__mmask8 __U, __m256i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm256_maskz_sll_epi32
+ // CHECK: @llvm.x86.avx2.psll.d
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
+ return _mm256_maskz_sll_epi32(__U, __A, __B);
+}
+
+__m128i test_mm_mask_slli_epi32(__m128i __W, __mmask8 __U, __m128i __A) {
+ // CHECK-LABEL: @test_mm_mask_slli_epi32
+ // CHECK: @llvm.x86.sse2.pslli.d
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
+ return _mm_mask_slli_epi32(__W, __U, __A, 5);
+}
+
+__m128i test_mm_maskz_slli_epi32(__mmask8 __U, __m128i __A) {
+ // CHECK-LABEL: @test_mm_maskz_slli_epi32
+ // CHECK: @llvm.x86.sse2.pslli.d
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
+ return _mm_maskz_slli_epi32(__U, __A, 5);
+}
+
+__m256i test_mm256_mask_slli_epi32(__m256i __W, __mmask8 __U, __m256i __A) {
+ // CHECK-LABEL: @test_mm256_mask_slli_epi32
+ // CHECK: @llvm.x86.avx2.pslli.d
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
+ return _mm256_mask_slli_epi32(__W, __U, __A, 5);
+}
+
+__m256i test_mm256_maskz_slli_epi32(__mmask8 __U, __m256i __A) {
+ // CHECK-LABEL: @test_mm256_maskz_slli_epi32
+ // CHECK: @llvm.x86.avx2.pslli.d
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
+ return _mm256_maskz_slli_epi32(__U, __A, 5);
+}
+
+__m128i test_mm_mask_sll_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_mask_sll_epi64
+ // CHECK: @llvm.x86.sse2.psll.q
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
+ return _mm_mask_sll_epi64(__W, __U, __A, __B);
+}
+
+__m128i test_mm_maskz_sll_epi64(__mmask8 __U, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_maskz_sll_epi64
+ // CHECK: @llvm.x86.sse2.psll.q
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
+ return _mm_maskz_sll_epi64(__U, __A, __B);
+}
+
+__m256i test_mm256_mask_sll_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm256_mask_sll_epi64
+ // CHECK: @llvm.x86.avx2.psll.q
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
+ return _mm256_mask_sll_epi64(__W, __U, __A, __B);
+}
+
+__m256i test_mm256_maskz_sll_epi64(__mmask8 __U, __m256i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm256_maskz_sll_epi64
+ // CHECK: @llvm.x86.avx2.psll.q
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
+ return _mm256_maskz_sll_epi64(__U, __A, __B);
+}
+
+__m128i test_mm_mask_slli_epi64(__m128i __W, __mmask8 __U, __m128i __A) {
+ // CHECK-LABEL: @test_mm_mask_slli_epi64
+ // CHECK: @llvm.x86.sse2.pslli.q
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
+ return _mm_mask_slli_epi64(__W, __U, __A, 5);
+}
+
+__m128i test_mm_maskz_slli_epi64(__mmask8 __U, __m128i __A) {
+ // CHECK-LABEL: @test_mm_maskz_slli_epi64
+ // CHECK: @llvm.x86.sse2.pslli.q
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
+ return _mm_maskz_slli_epi64(__U, __A, 5);
+}
+
+__m256i test_mm256_mask_slli_epi64(__m256i __W, __mmask8 __U, __m256i __A) {
+ // CHECK-LABEL: @test_mm256_mask_slli_epi64
+ // CHECK: @llvm.x86.avx2.pslli.q
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
+ return _mm256_mask_slli_epi64(__W, __U, __A, 5);
+}
+
+__m256i test_mm256_maskz_slli_epi64(__mmask8 __U, __m256i __A) {
+ // CHECK-LABEL: @test_mm256_maskz_slli_epi64
+ // CHECK: @llvm.x86.avx2.pslli.q
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
+ return _mm256_maskz_slli_epi64(__U, __A, 5);
+}
+
__m128i test_mm_mask_srav_epi32(__m128i __W, __mmask8 __U, __m128i __X, __m128i __Y) {
// CHECK-LABEL: @test_mm_mask_srav_epi32
- // CHECK: @llvm.x86.avx512.mask.psrav
+ // CHECK: @llvm.x86.avx2.psrav.d
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_mask_srav_epi32(__W, __U, __X, __Y);
}
__m128i test_mm_maskz_srav_epi32(__mmask8 __U, __m128i __X, __m128i __Y) {
// CHECK-LABEL: @test_mm_maskz_srav_epi32
- // CHECK: @llvm.x86.avx512.mask.psrav
+ // CHECK: @llvm.x86.avx2.psrav.d
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_maskz_srav_epi32(__U, __X, __Y);
}
__m256i test_mm256_mask_srav_epi32(__m256i __W, __mmask8 __U, __m256i __X, __m256i __Y) {
// CHECK-LABEL: @test_mm256_mask_srav_epi32
- // CHECK: @llvm.x86.avx512.mask.psrav
+ // CHECK: @llvm.x86.avx2.psrav.d.256
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_mask_srav_epi32(__W, __U, __X, __Y);
}
__m256i test_mm256_maskz_srav_epi32(__mmask8 __U, __m256i __X, __m256i __Y) {
// CHECK-LABEL: @test_mm256_maskz_srav_epi32
- // CHECK: @llvm.x86.avx512.mask.psrav
+ // CHECK: @llvm.x86.avx2.psrav.d.256
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_maskz_srav_epi32(__U, __X, __Y);
}
__m128i test_mm_srav_epi64(__m128i __X, __m128i __Y) {
// CHECK-LABEL: @test_mm_srav_epi64
- // CHECK: @llvm.x86.avx512.mask.psrav.q.128
+ // CHECK: @llvm.x86.avx512.psrav.q.128
return _mm_srav_epi64(__X, __Y);
}
__m128i test_mm_mask_srav_epi64(__m128i __W, __mmask8 __U, __m128i __X, __m128i __Y) {
// CHECK-LABEL: @test_mm_mask_srav_epi64
- // CHECK: @llvm.x86.avx512.mask.psrav.q.128
+ // CHECK: @llvm.x86.avx512.psrav.q.128
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_mask_srav_epi64(__W, __U, __X, __Y);
}
__m128i test_mm_maskz_srav_epi64(__mmask8 __U, __m128i __X, __m128i __Y) {
// CHECK-LABEL: @test_mm_maskz_srav_epi64
- // CHECK: @llvm.x86.avx512.mask.psrav.q.128
+ // CHECK: @llvm.x86.avx512.psrav.q.128
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_maskz_srav_epi64(__U, __X, __Y);
}
__m256i test_mm256_srav_epi64(__m256i __X, __m256i __Y) {
// CHECK-LABEL: @test_mm256_srav_epi64
- // CHECK: @llvm.x86.avx512.mask.psrav.q.256
+ // CHECK: @llvm.x86.avx512.psrav.q.256
return _mm256_srav_epi64(__X, __Y);
}
__m256i test_mm256_mask_srav_epi64(__m256i __W, __mmask8 __U, __m256i __X, __m256i __Y) {
// CHECK-LABEL: @test_mm256_mask_srav_epi64
- // CHECK: @llvm.x86.avx512.mask.psrav.q.256
+ // CHECK: @llvm.x86.avx512.psrav.q.256
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_mask_srav_epi64(__W, __U, __X, __Y);
}
__m256i test_mm256_maskz_srav_epi64(__mmask8 __U, __m256i __X, __m256i __Y) {
// CHECK-LABEL: @test_mm256_maskz_srav_epi64
- // CHECK: @llvm.x86.avx512.mask.psrav.q.256
+ // CHECK: @llvm.x86.avx512.psrav.q.256
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_maskz_srav_epi64(__U, __X, __Y);
}
@@ -4145,6 +4508,7 @@ __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: @llvm.x86.avx512.mask.pbroadcast.q.gpr.128
@@ -4168,6 +4532,7 @@ __m256i test_mm256_maskz_set1_epi64(__mmask8 __M, long long __A) {
// CHECK: @llvm.x86.avx512.mask.pbroadcast.q.gpr.256
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
@@ -4699,49 +5064,57 @@ __m256 test_mm256_maskz_permute_ps(__mmask8 __U, __m256 __X) {
__m128d test_mm_mask_permutevar_pd(__m128d __W, __mmask8 __U, __m128d __A, __m128i __C) {
// CHECK-LABEL: @test_mm_mask_permutevar_pd
- // CHECK: @llvm.x86.avx512.mask.vpermilvar.pd
+ // CHECK: @llvm.x86.avx.vpermilvar.pd
+ // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return _mm_mask_permutevar_pd(__W, __U, __A, __C);
}
__m128d test_mm_maskz_permutevar_pd(__mmask8 __U, __m128d __A, __m128i __C) {
// CHECK-LABEL: @test_mm_maskz_permutevar_pd
- // CHECK: @llvm.x86.avx512.mask.vpermilvar.pd
+ // CHECK: @llvm.x86.avx.vpermilvar.pd
+ // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return _mm_maskz_permutevar_pd(__U, __A, __C);
}
__m256d test_mm256_mask_permutevar_pd(__m256d __W, __mmask8 __U, __m256d __A, __m256i __C) {
// CHECK-LABEL: @test_mm256_mask_permutevar_pd
- // CHECK: @llvm.x86.avx512.mask.vpermilvar.pd.256
+ // CHECK: @llvm.x86.avx.vpermilvar.pd.256
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_mask_permutevar_pd(__W, __U, __A, __C);
}
__m256d test_mm256_maskz_permutevar_pd(__mmask8 __U, __m256d __A, __m256i __C) {
// CHECK-LABEL: @test_mm256_maskz_permutevar_pd
- // CHECK: @llvm.x86.avx512.mask.vpermilvar.pd.256
+ // CHECK: @llvm.x86.avx.vpermilvar.pd.256
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_maskz_permutevar_pd(__U, __A, __C);
}
__m128 test_mm_mask_permutevar_ps(__m128 __W, __mmask8 __U, __m128 __A, __m128i __C) {
// CHECK-LABEL: @test_mm_mask_permutevar_ps
- // CHECK: @llvm.x86.avx512.mask.vpermilvar.ps
+ // CHECK: @llvm.x86.avx.vpermilvar.ps
+ // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return _mm_mask_permutevar_ps(__W, __U, __A, __C);
}
__m128 test_mm_maskz_permutevar_ps(__mmask8 __U, __m128 __A, __m128i __C) {
// CHECK-LABEL: @test_mm_maskz_permutevar_ps
- // CHECK: @llvm.x86.avx512.mask.vpermilvar.ps
+ // CHECK: @llvm.x86.avx.vpermilvar.ps
+ // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return _mm_maskz_permutevar_ps(__U, __A, __C);
}
__m256 test_mm256_mask_permutevar_ps(__m256 __W, __mmask8 __U, __m256 __A, __m256i __C) {
// CHECK-LABEL: @test_mm256_mask_permutevar_ps
- // CHECK: @llvm.x86.avx512.mask.vpermilvar.ps.256
+ // CHECK: @llvm.x86.avx.vpermilvar.ps.256
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_mask_permutevar_ps(__W, __U, __A, __C);
}
__m256 test_mm256_maskz_permutevar_ps(__mmask8 __U, __m256 __A, __m256i __C) {
// CHECK-LABEL: @test_mm256_maskz_permutevar_ps
- // CHECK: @llvm.x86.avx512.mask.vpermilvar.ps.256
+ // CHECK: @llvm.x86.avx.vpermilvar.ps.256
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_maskz_permutevar_ps(__U, __A, __C);
}
@@ -4954,121 +5327,137 @@ __m256i test_mm256_maskz_unpacklo_epi64(__mmask8 __U, __m256i __A, __m256i __B)
__m128i test_mm_mask_sra_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_sra_epi32
- // CHECK: @llvm.x86.avx512.mask.psra.d.128
+ // CHECK: @llvm.x86.sse2.psra.d
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_mask_sra_epi32(__W, __U, __A, __B);
}
__m128i test_mm_maskz_sra_epi32(__mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_sra_epi32
- // CHECK: @llvm.x86.avx512.mask.psra.d.128
+ // CHECK: @llvm.x86.sse2.psra.d
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_maskz_sra_epi32(__U, __A, __B);
}
__m256i test_mm256_mask_sra_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m128i __B) {
// CHECK-LABEL: @test_mm256_mask_sra_epi32
- // CHECK: @llvm.x86.avx512.mask.psra.d.256
+ // CHECK: @llvm.x86.avx2.psra.d
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_mask_sra_epi32(__W, __U, __A, __B);
}
__m256i test_mm256_maskz_sra_epi32(__mmask8 __U, __m256i __A, __m128i __B) {
// CHECK-LABEL: @test_mm256_maskz_sra_epi32
- // CHECK: @llvm.x86.avx512.mask.psra.d.256
+ // CHECK: @llvm.x86.avx2.psra.d
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_maskz_sra_epi32(__U, __A, __B);
}
__m128i test_mm_mask_srai_epi32(__m128i __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_srai_epi32
- // CHECK: @llvm.x86.avx512.mask.psra.di.128
+ // CHECK: @llvm.x86.sse2.psrai.d
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_mask_srai_epi32(__W, __U, __A, 5);
}
__m128i test_mm_maskz_srai_epi32(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_maskz_srai_epi32
- // CHECK: @llvm.x86.avx512.mask.psra.di.128
+ // CHECK: @llvm.x86.sse2.psrai.d
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_maskz_srai_epi32(__U, __A, 5);
}
__m256i test_mm256_mask_srai_epi32(__m256i __W, __mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_mask_srai_epi32
- // CHECK: @llvm.x86.avx512.mask.psra.di.256
+ // CHECK: @llvm.x86.avx2.psrai.d
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_mask_srai_epi32(__W, __U, __A, 5);
}
__m256i test_mm256_maskz_srai_epi32(__mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_maskz_srai_epi32
- // CHECK: @llvm.x86.avx512.mask.psra.di.256
+ // CHECK: @llvm.x86.avx2.psrai.d
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_maskz_srai_epi32(__U, __A, 5);
}
__m128i test_mm_sra_epi64(__m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_sra_epi64
- // CHECK: @llvm.x86.avx512.mask.psra.q.128
+ // CHECK: @llvm.x86.avx512.psra.q.128
return _mm_sra_epi64(__A, __B);
}
__m128i test_mm_mask_sra_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_sra_epi64
- // CHECK: @llvm.x86.avx512.mask.psra.q.128
+ // CHECK: @llvm.x86.avx512.psra.q.128
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_mask_sra_epi64(__W, __U, __A, __B);
}
__m128i test_mm_maskz_sra_epi64(__mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_sra_epi64
- // CHECK: @llvm.x86.avx512.mask.psra.q.128
+ // CHECK: @llvm.x86.avx512.psra.q.128
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_maskz_sra_epi64(__U, __A, __B);
}
__m256i test_mm256_sra_epi64(__m256i __A, __m128i __B) {
// CHECK-LABEL: @test_mm256_sra_epi64
- // CHECK: @llvm.x86.avx512.mask.psra.q.256
+ // CHECK: @llvm.x86.avx512.psra.q.256
return _mm256_sra_epi64(__A, __B);
}
__m256i test_mm256_mask_sra_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m128i __B) {
// CHECK-LABEL: @test_mm256_mask_sra_epi64
- // CHECK: @llvm.x86.avx512.mask.psra.q.256
+ // CHECK: @llvm.x86.avx512.psra.q.256
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_mask_sra_epi64(__W, __U, __A, __B);
}
__m256i test_mm256_maskz_sra_epi64(__mmask8 __U, __m256i __A, __m128i __B) {
// CHECK-LABEL: @test_mm256_maskz_sra_epi64
- // CHECK: @llvm.x86.avx512.mask.psra.q.256
+ // CHECK: @llvm.x86.avx512.psra.q.256
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_maskz_sra_epi64(__U, __A, __B);
}
__m128i test_mm_srai_epi64(__m128i __A) {
// CHECK-LABEL: @test_mm_srai_epi64
- // CHECK: @llvm.x86.avx512.mask.psra.qi.128
+ // CHECK: @llvm.x86.avx512.psrai.q.128
return _mm_srai_epi64(__A, 5);
}
__m128i test_mm_mask_srai_epi64(__m128i __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_srai_epi64
- // CHECK: @llvm.x86.avx512.mask.psra.qi.128
+ // CHECK: @llvm.x86.avx512.psrai.q.128
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_mask_srai_epi64(__W, __U, __A, 5);
}
__m128i test_mm_maskz_srai_epi64(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_maskz_srai_epi64
- // CHECK: @llvm.x86.avx512.mask.psra.qi.128
+ // CHECK: @llvm.x86.avx512.psrai.q.128
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_maskz_srai_epi64(__U, __A, 5);
}
__m256i test_mm256_srai_epi64(__m256i __A) {
// CHECK-LABEL: @test_mm256_srai_epi64
- // CHECK: @llvm.x86.avx512.mask.psra.qi.256
+ // CHECK: @llvm.x86.avx512.psrai.q.256
return _mm256_srai_epi64(__A, 5);
}
__m256i test_mm256_mask_srai_epi64(__m256i __W, __mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_mask_srai_epi64
- // CHECK: @llvm.x86.avx512.mask.psra.qi.256
+ // CHECK: @llvm.x86.avx512.psrai.q.256
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_mask_srai_epi64(__W, __U, __A, 5);
}
__m256i test_mm256_maskz_srai_epi64(__mmask8 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_maskz_srai_epi64
- // CHECK: @llvm.x86.avx512.mask.psra.qi.256
+ // CHECK: @llvm.x86.avx512.psrai.q.256
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_maskz_srai_epi64(__U, __A, 5);
}
@@ -6199,73 +6588,81 @@ 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: @llvm.x86.avx512.mask.vextractf32x4
+ // 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: @llvm.x86.avx512.mask.vextractf32x4
+ // 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: @llvm.x86.avx512.mask.vextractf32x4
+ // 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: @llvm.x86.avx512.mask.vextracti32x4
+ // CHECK: shufflevector <8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <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: @llvm.x86.avx512.mask.vextracti32x4
+ // CHECK: shufflevector <8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <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: @llvm.x86.avx512.mask.vextracti32x4
+ // CHECK: shufflevector <8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <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);
}
__m256 test_mm256_insertf32x4(__m256 __A, __m128 __B) {
// CHECK-LABEL: @test_mm256_insertf32x4
- // CHECK: @llvm.x86.avx512.mask.insertf32x4
+ // 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_insertf32x4(__A, __B, 1);
}
__m256 test_mm256_mask_insertf32x4(__m256 __W, __mmask8 __U, __m256 __A, __m128 __B) {
// CHECK-LABEL: @test_mm256_mask_insertf32x4
- // CHECK: @llvm.x86.avx512.mask.insertf32x4
+ // 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>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_mask_insertf32x4(__W, __U, __A, __B, 1);
}
__m256 test_mm256_maskz_insertf32x4(__mmask8 __U, __m256 __A, __m128 __B) {
// CHECK-LABEL: @test_mm256_maskz_insertf32x4
- // CHECK: @llvm.x86.avx512.mask.insertf32x4
+ // 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>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return _mm256_maskz_insertf32x4(__U, __A, __B, 1);
}
__m256i test_mm256_inserti32x4(__m256i __A, __m128i __B) {
// CHECK-LABEL: @test_mm256_inserti32x4
- // CHECK: @llvm.x86.avx512.mask.inserti32x4
+ // 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_inserti32x4(__A, __B, 1);
}
__m256i test_mm256_mask_inserti32x4(__m256i __W, __mmask8 __U, __m256i __A, __m128i __B) {
// CHECK-LABEL: @test_mm256_mask_inserti32x4
- // CHECK: @llvm.x86.avx512.mask.inserti32x4
+ // 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>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_mask_inserti32x4(__W, __U, __A, __B, 1);
}
__m256i test_mm256_maskz_inserti32x4(__mmask8 __U, __m256i __A, __m128i __B) {
// CHECK-LABEL: @test_mm256_maskz_inserti32x4
- // CHECK: @llvm.x86.avx512.mask.inserti32x4
+ // 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>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_maskz_inserti32x4(__U, __A, __B, 1);
}
@@ -6545,73 +6942,81 @@ __m256i test_mm256_mask_permutexvar_epi32(__m256i __W, __mmask8 __M, __m256i __X
__m128i test_mm_alignr_epi32(__m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_alignr_epi32
- // CHECK: @llvm.x86.avx512.mask.valign.d.128
+ // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> <i32 1, i32 2, i32 3, i32 4>
return _mm_alignr_epi32(__A, __B, 1);
}
__m128i test_mm_mask_alignr_epi32(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_alignr_epi32
- // CHECK: @llvm.x86.avx512.mask.valign.d.128
+ // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> <i32 1, i32 2, i32 3, i32 4>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_mask_alignr_epi32(__W, __U, __A, __B, 1);
}
__m128i test_mm_maskz_alignr_epi32(__mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_alignr_epi32
- // CHECK: @llvm.x86.avx512.mask.valign.d.128
+ // CHECK: shufflevector <4 x i32> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> <i32 1, i32 2, i32 3, i32 4>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_maskz_alignr_epi32(__U, __A, __B, 1);
}
__m256i test_mm256_alignr_epi32(__m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_alignr_epi32
- // CHECK: @llvm.x86.avx512.mask.valign.d.256
+ // CHECK: shufflevector <8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> <i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8>
return _mm256_alignr_epi32(__A, __B, 1);
}
__m256i test_mm256_mask_alignr_epi32(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_alignr_epi32
- // CHECK: @llvm.x86.avx512.mask.valign.d.256
+ // CHECK: shufflevector <8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> <i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_mask_alignr_epi32(__W, __U, __A, __B, 1);
}
__m256i test_mm256_maskz_alignr_epi32(__mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_alignr_epi32
- // CHECK: @llvm.x86.avx512.mask.valign.d.256
+ // CHECK: shufflevector <8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> <i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_maskz_alignr_epi32(__U, __A, __B, 1);
}
__m128i test_mm_alignr_epi64(__m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_alignr_epi64
- // CHECK: @llvm.x86.avx512.mask.valign.q.128
+ // CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <2 x i32> <i32 1, i32 2>
return _mm_alignr_epi64(__A, __B, 1);
}
__m128i test_mm_mask_alignr_epi64(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_alignr_epi64
- // CHECK: @llvm.x86.avx512.mask.valign.q.128
+ // CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <2 x i32> <i32 1, i32 2>
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_mask_alignr_epi64(__W, __U, __A, __B, 1);
}
__m128i test_mm_maskz_alignr_epi64(__mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_alignr_epi64
- // CHECK: @llvm.x86.avx512.mask.valign.q.128
+ // CHECK: shufflevector <2 x i64> %{{.*}}, <2 x i64> %{{.*}}, <2 x i32> <i32 1, i32 2>
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return _mm_maskz_alignr_epi64(__U, __A, __B, 1);
}
__m256i test_mm256_alignr_epi64(__m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_alignr_epi64
- // CHECK: @llvm.x86.avx512.mask.valign.q.256
+ // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> %{{.*}}, <4 x i32> <i32 1, i32 2, i32 3, i32 4>
return _mm256_alignr_epi64(__A, __B, 1);
}
__m256i test_mm256_mask_alignr_epi64(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_alignr_epi64
- // CHECK: @llvm.x86.avx512.mask.valign.q.256
+ // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> %{{.*}}, <4 x i32> <i32 1, i32 2, i32 3, i32 4>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_mask_alignr_epi64(__W, __U, __A, __B, 1);
}
__m256i test_mm256_maskz_alignr_epi64(__mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_alignr_epi64
- // CHECK: @llvm.x86.avx512.mask.valign.q.256
+ // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> %{{.*}}, <4 x i32> <i32 1, i32 2, i32 3, i32 4>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_maskz_alignr_epi64(__U, __A, __B, 1);
}
diff --git a/test/CodeGen/avx512vlbw-builtins.c b/test/CodeGen/avx512vlbw-builtins.c
index 6bfa09f5d1c6..fe363c9ffde5 100644
--- a/test/CodeGen/avx512vlbw-builtins.c
+++ b/test/CodeGen/avx512vlbw-builtins.c
@@ -1,8 +1,6 @@
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +avx512bw -target-feature +avx512vl -emit-llvm -o - -Werror | FileCheck %s
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +avx512bw -target-feature +avx512vl -fno-signed-char -emit-llvm -o - -Werror | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +avx512bw -target-feature +avx512vl -emit-llvm -o - -Wall -Werror | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +avx512bw -target-feature +avx512vl -fno-signed-char -emit-llvm -o - -Wall -Werror | FileCheck %s
-// Don't include mm_malloc.h, it's system specific.
-#define __MM_MALLOC_H
#include <immintrin.h>
@@ -737,119 +735,140 @@ __mmask16 test_mm256_mask_cmp_epu16_mask(__mmask16 __u, __m256i __a, __m256i __b
__m256i test_mm256_mask_add_epi8 (__m256i __W, __mmask32 __U, __m256i __A, __m256i __B){
//CHECK-LABEL: @test_mm256_mask_add_epi8
- //CHECK: @llvm.x86.avx512.mask.padd.b.256
+ //CHECK: add <32 x i8> %{{.*}}, %{{.*}}
+ //CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
return _mm256_mask_add_epi8(__W, __U , __A, __B);
}
__m256i test_mm256_maskz_add_epi8 (__mmask32 __U, __m256i __A, __m256i __B) {
//CHECK-LABEL: @test_mm256_maskz_add_epi8
- //CHECK: @llvm.x86.avx512.mask.padd.b.256
+ //CHECK: add <32 x i8> %{{.*}}, %{{.*}}
+ //CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
return _mm256_maskz_add_epi8(__U , __A, __B);
}
__m256i test_mm256_mask_add_epi16 (__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) {
//CHECK-LABEL: @test_mm256_mask_add_epi16
- //CHECK: @llvm.x86.avx512.mask.padd.w.256
+ //CHECK: add <16 x i16> %{{.*}}, %{{.*}}
+ //CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_mask_add_epi16(__W, __U , __A, __B);
}
__m256i test_mm256_maskz_add_epi16 (__mmask16 __U, __m256i __A, __m256i __B) {
//CHECK-LABEL: @test_mm256_maskz_add_epi16
- //CHECK: @llvm.x86.avx512.mask.padd.w.256
+ //CHECK: add <16 x i16> %{{.*}}, %{{.*}}
+ //CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_maskz_add_epi16(__U , __A, __B);
}
__m256i test_mm256_mask_sub_epi8 (__m256i __W, __mmask32 __U, __m256i __A, __m256i __B) {
//CHECK-LABEL: @test_mm256_mask_sub_epi8
- //CHECK: @llvm.x86.avx512.mask.psub.b.256
+ //CHECK: sub <32 x i8> %{{.*}}, %{{.*}}
+ //CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
return _mm256_mask_sub_epi8(__W, __U , __A, __B);
}
__m256i test_mm256_maskz_sub_epi8 (__mmask32 __U, __m256i __A, __m256i __B) {
//CHECK-LABEL: @test_mm256_maskz_sub_epi8
- //CHECK: @llvm.x86.avx512.mask.psub.b.256
+ //CHECK: sub <32 x i8> %{{.*}}, %{{.*}}
+ //CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
return _mm256_maskz_sub_epi8(__U , __A, __B);
}
__m256i test_mm256_mask_sub_epi16 (__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) {
//CHECK-LABEL: @test_mm256_mask_sub_epi16
- //CHECK: @llvm.x86.avx512.mask.psub.w.256
+ //CHECK: sub <16 x i16> %{{.*}}, %{{.*}}
+ //CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_mask_sub_epi16(__W, __U , __A, __B);
}
__m256i test_mm256_maskz_sub_epi16 (__mmask16 __U, __m256i __A, __m256i __B) {
//CHECK-LABEL: @test_mm256_maskz_sub_epi16
- //CHECK: @llvm.x86.avx512.mask.psub.w.256
+ //CHECK: sub <16 x i16> %{{.*}}, %{{.*}}
+ //CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_maskz_sub_epi16(__U , __A, __B);
}
+
__m128i test_mm_mask_add_epi8 (__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) {
//CHECK-LABEL: @test_mm_mask_add_epi8
- //CHECK: @llvm.x86.avx512.mask.padd.b.128
+ //CHECK: add <16 x i8> %{{.*}}, %{{.*}}
+ //CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
return _mm_mask_add_epi8(__W, __U , __A, __B);
}
__m128i test_mm_maskz_add_epi8 (__mmask16 __U, __m128i __A, __m128i __B) {
//CHECK-LABEL: @test_mm_maskz_add_epi8
- //CHECK: @llvm.x86.avx512.mask.padd.b.128
+ //CHECK: add <16 x i8> %{{.*}}, %{{.*}}
+ //CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
return _mm_maskz_add_epi8(__U , __A, __B);
}
__m128i test_mm_mask_add_epi16 (__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
//CHECK-LABEL: @test_mm_mask_add_epi16
- //CHECK: @llvm.x86.avx512.mask.padd.w.128
+ //CHECK: add <8 x i16> %{{.*}}, %{{.*}}
+ //CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_mask_add_epi16(__W, __U , __A, __B);
}
__m128i test_mm_maskz_add_epi16 (__mmask8 __U, __m128i __A, __m128i __B) {
//CHECK-LABEL: @test_mm_maskz_add_epi16
- //CHECK: @llvm.x86.avx512.mask.padd.w.128
+ //CHECK: add <8 x i16> %{{.*}}, %{{.*}}
+ //CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_maskz_add_epi16(__U , __A, __B);
}
__m128i test_mm_mask_sub_epi8 (__m128i __W, __mmask16 __U, __m128i __A, __m128i __B) {
//CHECK-LABEL: @test_mm_mask_sub_epi8
- //CHECK: @llvm.x86.avx512.mask.psub.b.128
+ //CHECK: sub <16 x i8> %{{.*}}, %{{.*}}
+ //CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
return _mm_mask_sub_epi8(__W, __U , __A, __B);
}
__m128i test_mm_maskz_sub_epi8 (__mmask16 __U, __m128i __A, __m128i __B) {
//CHECK-LABEL: @test_mm_maskz_sub_epi8
- //CHECK: @llvm.x86.avx512.mask.psub.b.128
+ //CHECK: sub <16 x i8> %{{.*}}, %{{.*}}
+ //CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
return _mm_maskz_sub_epi8(__U , __A, __B);
}
__m128i test_mm_mask_sub_epi16 (__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
//CHECK-LABEL: @test_mm_mask_sub_epi16
- //CHECK: @llvm.x86.avx512.mask.psub.w.128
+ //CHECK: sub <8 x i16> %{{.*}}, %{{.*}}
+ //CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_mask_sub_epi16(__W, __U , __A, __B);
}
__m128i test_mm_maskz_sub_epi16 (__mmask8 __U, __m128i __A, __m128i __B) {
//CHECK-LABEL: @test_mm_maskz_sub_epi16
- //CHECK: @llvm.x86.avx512.mask.psub.w.128
+ //CHECK: sub <8 x i16> %{{.*}}, %{{.*}}
+ //CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_maskz_sub_epi16(__U , __A, __B);
}
__m256i test_mm256_mask_mullo_epi16 (__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) {
//CHECK-LABEL: @test_mm256_mask_mullo_epi16
- //CHECK: @llvm.x86.avx512.mask.pmull.w.256
+ //CHECK: mul <16 x i16> %{{.*}}, %{{.*}}
+ //CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_mask_mullo_epi16(__W, __U , __A, __B);
}
__m256i test_mm256_maskz_mullo_epi16 (__mmask16 __U, __m256i __A, __m256i __B) {
//CHECK-LABEL: @test_mm256_maskz_mullo_epi16
- //CHECK: @llvm.x86.avx512.mask.pmull.w.256
+ //CHECK: mul <16 x i16> %{{.*}}, %{{.*}}
+ //CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_maskz_mullo_epi16(__U , __A, __B);
}
__m128i test_mm_mask_mullo_epi16 (__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
//CHECK-LABEL: @test_mm_mask_mullo_epi16
- //CHECK: @llvm.x86.avx512.mask.pmull.w.128
+ //CHECK: mul <8 x i16> %{{.*}}, %{{.*}}
+ //CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_mask_mullo_epi16(__W, __U , __A, __B);
}
__m128i test_mm_maskz_mullo_epi16 (__mmask8 __U, __m128i __A, __m128i __B) {
//CHECK-LABEL: @test_mm_maskz_mullo_epi16
- //CHECK: @llvm.x86.avx512.mask.pmull.w.128
+ //CHECK: mul <8 x i16> %{{.*}}, %{{.*}}
+ //CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_maskz_mullo_epi16(__U , __A, __B);
}
@@ -879,519 +898,651 @@ __m256i test_mm256_mask_blend_epi16(__mmask16 __U, __m256i __A, __m256i __W) {
__m128i test_mm_mask_abs_epi8(__m128i __W, __mmask16 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_abs_epi8
- // CHECK: @llvm.x86.avx512.mask.pabs.b.128
+ // CHECK: @llvm.x86.ssse3.pabs.b
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
return _mm_mask_abs_epi8(__W,__U,__A);
}
__m128i test_mm_maskz_abs_epi8(__mmask16 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_maskz_abs_epi8
- // CHECK: @llvm.x86.avx512.mask.pabs.b.128
+ // CHECK: @llvm.x86.ssse3.pabs.b
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
return _mm_maskz_abs_epi8(__U,__A);
}
__m256i test_mm256_mask_abs_epi8(__m256i __W, __mmask32 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_mask_abs_epi8
- // CHECK: @llvm.x86.avx512.mask.pabs.b.256
+ // CHECK: @llvm.x86.avx2.pabs.b
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
return _mm256_mask_abs_epi8(__W,__U,__A);
}
__m256i test_mm256_maskz_abs_epi8(__mmask32 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_maskz_abs_epi8
- // CHECK: @llvm.x86.avx512.mask.pabs.b.256
+ // CHECK: @llvm.x86.avx2.pabs.b
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
return _mm256_maskz_abs_epi8(__U,__A);
}
__m128i test_mm_mask_abs_epi16(__m128i __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_abs_epi16
- // CHECK: @llvm.x86.avx512.mask.pabs.w.128
+ // CHECK: @llvm.x86.ssse3.pabs.w
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_mask_abs_epi16(__W,__U,__A);
}
__m128i test_mm_maskz_abs_epi16(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_maskz_abs_epi16
- // CHECK: @llvm.x86.avx512.mask.pabs.w.128
+ // CHECK: @llvm.x86.ssse3.pabs.w
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_maskz_abs_epi16(__U,__A);
}
__m256i test_mm256_mask_abs_epi16(__m256i __W, __mmask16 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_mask_abs_epi16
- // CHECK: @llvm.x86.avx512.mask.pabs.w.256
+ // CHECK: @llvm.x86.avx2.pabs.w
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_mask_abs_epi16(__W,__U,__A);
}
__m256i test_mm256_maskz_abs_epi16(__mmask16 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_maskz_abs_epi16
- // CHECK: @llvm.x86.avx512.mask.pabs.w.256
+ // CHECK: @llvm.x86.avx2.pabs.w
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_maskz_abs_epi16(__U,__A);
}
__m128i test_mm_maskz_packs_epi32(__mmask8 __M, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_packs_epi32
- // CHECK: @llvm.x86.avx512.mask.packssdw.128
+ // CHECK: @llvm.x86.sse2.packssdw
+ // 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) {
// CHECK-LABEL: @test_mm_mask_packs_epi32
- // CHECK: @llvm.x86.avx512.mask.packssdw.128
+ // CHECK: @llvm.x86.sse2.packssdw
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_mask_packs_epi32(__W,__M,__A,__B);
}
__m256i test_mm256_maskz_packs_epi32(__mmask16 __M, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_packs_epi32
- // CHECK: @llvm.x86.avx512.mask.packssdw.256
+ // CHECK: @llvm.x86.avx2.packssdw
+ // 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) {
// CHECK-LABEL: @test_mm256_mask_packs_epi32
- // CHECK: @llvm.x86.avx512.mask.packssdw.256
+ // CHECK: @llvm.x86.avx2.packssdw
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_mask_packs_epi32(__W,__M,__A,__B);
}
__m128i test_mm_maskz_packs_epi16(__mmask16 __M, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_packs_epi16
- // CHECK: @llvm.x86.avx512.mask.packsswb.128
+ // CHECK: @llvm.x86.sse2.packsswb
+ // 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) {
// CHECK-LABEL: @test_mm_mask_packs_epi16
- // CHECK: @llvm.x86.avx512.mask.packsswb.128
+ // CHECK: @llvm.x86.sse2.packsswb
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
return _mm_mask_packs_epi16(__W,__M,__A,__B);
}
__m256i test_mm256_maskz_packs_epi16(__mmask32 __M, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_packs_epi16
- // CHECK: @llvm.x86.avx512.mask.packsswb.256
+ // CHECK: @llvm.x86.avx2.packsswb
+ // 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) {
// CHECK-LABEL: @test_mm256_mask_packs_epi16
- // CHECK: @llvm.x86.avx512.mask.packsswb.256
+ // 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) {
// CHECK-LABEL: @test_mm_mask_packus_epi32
- // CHECK: @llvm.x86.avx512.mask.packusdw.128
+ // CHECK: @llvm.x86.sse41.packusdw
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_mask_packus_epi32(__W,__M,__A,__B);
}
__m128i test_mm_maskz_packus_epi32(__mmask8 __M, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_packus_epi32
- // CHECK: @llvm.x86.avx512.mask.packusdw.128
+ // CHECK: @llvm.x86.sse41.packusdw
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_maskz_packus_epi32(__M,__A,__B);
}
__m256i test_mm256_maskz_packus_epi32(__mmask16 __M, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_packus_epi32
- // CHECK: @llvm.x86.avx512.mask.packusdw.256
+ // CHECK: @llvm.x86.avx2.packusdw
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_maskz_packus_epi32(__M,__A,__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.avx512.mask.packusdw.256
+ // CHECK: @llvm.x86.avx2.packusdw
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_mask_packus_epi32(__W,__M,__A,__B);
}
__m128i test_mm_maskz_packus_epi16(__mmask16 __M, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_packus_epi16
- // CHECK: @llvm.x86.avx512.mask.packuswb.128
+ // CHECK: @llvm.x86.sse2.packuswb
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
return _mm_maskz_packus_epi16(__M,__A,__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.avx512.mask.packuswb.128
+ // CHECK: @llvm.x86.sse2.packuswb
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
return _mm_mask_packus_epi16(__W,__M,__A,__B);
}
__m256i test_mm256_maskz_packus_epi16(__mmask32 __M, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_packus_epi16
- // CHECK: @llvm.x86.avx512.mask.packuswb.256
+ // CHECK: @llvm.x86.avx2.packuswb
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
return _mm256_maskz_packus_epi16(__M,__A,__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.avx512.mask.packuswb.256
+ // 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) {
// CHECK-LABEL: @test_mm_mask_adds_epi8
- // CHECK: @llvm.x86.avx512.mask.padds.b.128
+ // CHECK: @llvm.x86.sse2.padds.b
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
return _mm_mask_adds_epi8(__W,__U,__A,__B);
}
__m128i test_mm_maskz_adds_epi8(__mmask16 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_adds_epi8
- // CHECK: @llvm.x86.avx512.mask.padds.b.128
+ // CHECK: @llvm.x86.sse2.padds.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) {
// CHECK-LABEL: @test_mm256_mask_adds_epi8
- // CHECK: @llvm.x86.avx512.mask.padds.b.256
+ // CHECK: @llvm.x86.avx2.padds.b
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
return _mm256_mask_adds_epi8(__W,__U,__A,__B);
}
__m256i test_mm256_maskz_adds_epi8(__mmask32 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_adds_epi8
- // CHECK: @llvm.x86.avx512.mask.padds.b.256
+ // CHECK: @llvm.x86.avx2.padds.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) {
// CHECK-LABEL: @test_mm_mask_adds_epi16
- // CHECK: @llvm.x86.avx512.mask.padds.w.128
+ // CHECK: @llvm.x86.sse2.padds.w
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_mask_adds_epi16(__W,__U,__A,__B);
}
__m128i test_mm_maskz_adds_epi16(__mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_adds_epi16
- // CHECK: @llvm.x86.avx512.mask.padds.w.128
+ // CHECK: @llvm.x86.sse2.padds.w
+ // 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) {
// CHECK-LABEL: @test_mm256_mask_adds_epi16
- // CHECK: @llvm.x86.avx512.mask.padds.w.256
+ // CHECK: @llvm.x86.avx2.padds.w
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_mask_adds_epi16(__W,__U,__A,__B);
}
__m256i test_mm256_maskz_adds_epi16(__mmask16 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_adds_epi16
- // CHECK: @llvm.x86.avx512.mask.padds.w.256
+ // CHECK: @llvm.x86.avx2.padds.w
+ // 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) {
// CHECK-LABEL: @test_mm_mask_adds_epu8
- // CHECK: @llvm.x86.avx512.mask.paddus.b.128
+ // CHECK: @llvm.x86.sse2.paddus.b
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
return _mm_mask_adds_epu8(__W,__U,__A,__B);
}
__m128i test_mm_maskz_adds_epu8(__mmask16 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_adds_epu8
- // CHECK: @llvm.x86.avx512.mask.paddus.b.128
+ // CHECK: @llvm.x86.sse2.paddus.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) {
// CHECK-LABEL: @test_mm256_mask_adds_epu8
- // CHECK: @llvm.x86.avx512.mask.paddus.b.256
+ // CHECK: @llvm.x86.avx2.paddus.b
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
return _mm256_mask_adds_epu8(__W,__U,__A,__B);
}
__m256i test_mm256_maskz_adds_epu8(__mmask32 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_adds_epu8
- // CHECK: @llvm.x86.avx512.mask.paddus.b.256
+ // CHECK: @llvm.x86.avx2.paddus.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) {
// CHECK-LABEL: @test_mm_mask_adds_epu16
- // CHECK: @llvm.x86.avx512.mask.paddus.w.128
+ // CHECK: @llvm.x86.sse2.paddus.w
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_mask_adds_epu16(__W,__U,__A,__B);
}
__m128i test_mm_maskz_adds_epu16(__mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_adds_epu16
- // CHECK: @llvm.x86.avx512.mask.paddus.w.128
+ // CHECK: @llvm.x86.sse2.paddus.w
+ // 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) {
// CHECK-LABEL: @test_mm256_mask_adds_epu16
- // CHECK: @llvm.x86.avx512.mask.paddus.w.256
+ // CHECK: @llvm.x86.avx2.paddus.w
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_mask_adds_epu16(__W,__U,__A,__B);
}
__m256i test_mm256_maskz_adds_epu16(__mmask16 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_adds_epu16
- // CHECK: @llvm.x86.avx512.mask.paddus.w.256
+ // CHECK: @llvm.x86.avx2.paddus.w
+ // 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) {
// CHECK-LABEL: @test_mm_mask_avg_epu8
- // CHECK: @llvm.x86.avx512.mask.pavg.b.128
+ // CHECK: @llvm.x86.sse2.pavg.b
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
return _mm_mask_avg_epu8(__W,__U,__A,__B);
}
__m128i test_mm_maskz_avg_epu8(__mmask16 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_avg_epu8
- // CHECK: @llvm.x86.avx512.mask.pavg.b.128
+ // CHECK: @llvm.x86.sse2.pavg.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) {
// CHECK-LABEL: @test_mm256_mask_avg_epu8
- // CHECK: @llvm.x86.avx512.mask.pavg.b.256
+ // CHECK: @llvm.x86.avx2.pavg.b
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
return _mm256_mask_avg_epu8(__W,__U,__A,__B);
}
__m256i test_mm256_maskz_avg_epu8(__mmask32 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_avg_epu8
- // CHECK: @llvm.x86.avx512.mask.pavg.b.256
+ // CHECK: @llvm.x86.avx2.pavg.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) {
// CHECK-LABEL: @test_mm_mask_avg_epu16
- // CHECK: @llvm.x86.avx512.mask.pavg.w.128
+ // CHECK: @llvm.x86.sse2.pavg.w
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_mask_avg_epu16(__W,__U,__A,__B);
}
__m128i test_mm_maskz_avg_epu16(__mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_avg_epu16
- // CHECK: @llvm.x86.avx512.mask.pavg.w.128
+ // CHECK: @llvm.x86.sse2.pavg.w
+ // 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) {
// CHECK-LABEL: @test_mm256_mask_avg_epu16
- // CHECK: @llvm.x86.avx512.mask.pavg.w.256
+ // CHECK: @llvm.x86.avx2.pavg.w
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_mask_avg_epu16(__W,__U,__A,__B);
}
__m256i test_mm256_maskz_avg_epu16(__mmask16 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_avg_epu16
- // CHECK: @llvm.x86.avx512.mask.pavg.w.256
+ // CHECK: @llvm.x86.avx2.pavg.w
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_maskz_avg_epu16(__U,__A,__B);
}
__m128i test_mm_maskz_max_epi8(__mmask16 __M, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_max_epi8
- // CHECK: @llvm.x86.avx512.mask.pmaxs.b.128
+ // 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]]
+ // 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) {
// CHECK-LABEL: @test_mm_mask_max_epi8
- // CHECK: @llvm.x86.avx512.mask.pmaxs.b.128
+ // 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]]
+ // CHECK: select <16 x i1> {{.*}}, <16 x i8> [[RES]], <16 x i8> {{.*}}
return _mm_mask_max_epi8(__W,__M,__A,__B);
}
__m256i test_mm256_maskz_max_epi8(__mmask32 __M, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_max_epi8
- // CHECK: @llvm.x86.avx512.mask.pmaxs.b.256
+ // 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]]
+ // 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) {
// CHECK-LABEL: @test_mm256_mask_max_epi8
- // CHECK: @llvm.x86.avx512.mask.pmaxs.b.256
+ // 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]]
+ // CHECK: select <32 x i1> {{.*}}, <32 x i8> [[RES]], <32 x i8> {{.*}}
return _mm256_mask_max_epi8(__W,__M,__A,__B);
}
__m128i test_mm_maskz_max_epi16(__mmask8 __M, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_max_epi16
- // CHECK: @llvm.x86.avx512.mask.pmaxs.w.128
+ // 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]]
+ // 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) {
// CHECK-LABEL: @test_mm_mask_max_epi16
- // CHECK: @llvm.x86.avx512.mask.pmaxs.w.128
+ // 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]]
+ // CHECK: select <8 x i1> {{.*}}, <8 x i16> [[RES]], <8 x i16> {{.*}}
return _mm_mask_max_epi16(__W,__M,__A,__B);
}
__m256i test_mm256_maskz_max_epi16(__mmask16 __M, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_max_epi16
- // CHECK: @llvm.x86.avx512.mask.pmaxs.w.256
+ // 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]]
+ // 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) {
// CHECK-LABEL: @test_mm256_mask_max_epi16
- // CHECK: @llvm.x86.avx512.mask.pmaxs.w.256
+ // 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]]
+ // CHECK: select <16 x i1> {{.*}}, <16 x i16> [[RES]], <16 x i16> {{.*}}
return _mm256_mask_max_epi16(__W,__M,__A,__B);
}
__m128i test_mm_maskz_max_epu8(__mmask16 __M, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_max_epu8
- // CHECK: @llvm.x86.avx512.mask.pmaxu.b.128
+ // 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]]
+ // 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) {
// CHECK-LABEL: @test_mm_mask_max_epu8
- // CHECK: @llvm.x86.avx512.mask.pmaxu.b.128
+ // 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]]
+ // CHECK: select <16 x i1> {{.*}}, <16 x i8> [[RES]], <16 x i8> {{.*}}
return _mm_mask_max_epu8(__W,__M,__A,__B);
}
__m256i test_mm256_maskz_max_epu8(__mmask32 __M, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_max_epu8
- // CHECK: @llvm.x86.avx512.mask.pmaxu.b.256
+ // 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]]
+ // 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) {
// CHECK-LABEL: @test_mm256_mask_max_epu8
- // CHECK: @llvm.x86.avx512.mask.pmaxu.b.256
+ // 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]]
+ // CHECK: select <32 x i1> {{.*}}, <32 x i8> [[RES]], <32 x i8> {{.*}}
return _mm256_mask_max_epu8(__W,__M,__A,__B);
}
__m128i test_mm_maskz_max_epu16(__mmask8 __M, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_max_epu16
- // CHECK: @llvm.x86.avx512.mask.pmaxu.w.128
+ // 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]]
+ // 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) {
// CHECK-LABEL: @test_mm_mask_max_epu16
- // CHECK: @llvm.x86.avx512.mask.pmaxu.w.128
+ // 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]]
+ // CHECK: select <8 x i1> {{.*}}, <8 x i16> [[RES]], <8 x i16> {{.*}}
return _mm_mask_max_epu16(__W,__M,__A,__B);
}
__m256i test_mm256_maskz_max_epu16(__mmask16 __M, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_max_epu16
- // CHECK: @llvm.x86.avx512.mask.pmaxu.w.256
+ // 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]]
+ // 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) {
// CHECK-LABEL: @test_mm256_mask_max_epu16
- // CHECK: @llvm.x86.avx512.mask.pmaxu.w.256
+ // 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]]
+ // CHECK: select <16 x i1> {{.*}}, <16 x i16> [[RES]], <16 x i16> {{.*}}
return _mm256_mask_max_epu16(__W,__M,__A,__B);
}
__m128i test_mm_maskz_min_epi8(__mmask16 __M, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_min_epi8
- // CHECK: @llvm.x86.avx512.mask.pmins.b.128
+ // 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]]
+ // 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) {
// CHECK-LABEL: @test_mm_mask_min_epi8
- // CHECK: @llvm.x86.avx512.mask.pmins.b.128
+ // 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]]
+ // CHECK: select <16 x i1> {{.*}}, <16 x i8> [[RES]], <16 x i8> {{.*}}
return _mm_mask_min_epi8(__W,__M,__A,__B);
}
__m256i test_mm256_maskz_min_epi8(__mmask32 __M, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_min_epi8
- // CHECK: @llvm.x86.avx512.mask.pmins.b.256
+ // 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]]
+ // 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) {
// CHECK-LABEL: @test_mm256_mask_min_epi8
- // CHECK: @llvm.x86.avx512.mask.pmins.b.256
+ // 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]]
+ // CHECK: select <32 x i1> {{.*}}, <32 x i8> [[RES]], <32 x i8> {{.*}}
return _mm256_mask_min_epi8(__W,__M,__A,__B);
}
__m128i test_mm_maskz_min_epi16(__mmask8 __M, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_min_epi16
- // CHECK: @llvm.x86.avx512.mask.pmins.w.128
+ // 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]]
+ // 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) {
// CHECK-LABEL: @test_mm_mask_min_epi16
- // CHECK: @llvm.x86.avx512.mask.pmins.w.128
+ // 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]]
+ // CHECK: select <8 x i1> {{.*}}, <8 x i16> [[RES]], <8 x i16> {{.*}}
return _mm_mask_min_epi16(__W,__M,__A,__B);
}
__m256i test_mm256_maskz_min_epi16(__mmask16 __M, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_min_epi16
- // CHECK: @llvm.x86.avx512.mask.pmins.w.256
+ // 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]]
+ // 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) {
// CHECK-LABEL: @test_mm256_mask_min_epi16
- // CHECK: @llvm.x86.avx512.mask.pmins.w.256
+ // 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]]
+ // CHECK: select <16 x i1> {{.*}}, <16 x i16> [[RES]], <16 x i16> {{.*}}
return _mm256_mask_min_epi16(__W,__M,__A,__B);
}
__m128i test_mm_maskz_min_epu8(__mmask16 __M, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_min_epu8
- // CHECK: @llvm.x86.avx512.mask.pminu.b.128
+ // 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]]
+ // 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) {
// CHECK-LABEL: @test_mm_mask_min_epu8
- // CHECK: @llvm.x86.avx512.mask.pminu.b.128
+ // 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]]
+ // CHECK: select <16 x i1> {{.*}}, <16 x i8> [[RES]], <16 x i8> {{.*}}
return _mm_mask_min_epu8(__W,__M,__A,__B);
}
__m256i test_mm256_maskz_min_epu8(__mmask32 __M, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_min_epu8
- // CHECK: @llvm.x86.avx512.mask.pminu.b.256
+ // 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]]
+ // 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) {
// CHECK-LABEL: @test_mm256_mask_min_epu8
- // CHECK: @llvm.x86.avx512.mask.pminu.b.256
+ // 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]]
+ // CHECK: select <32 x i1> {{.*}}, <32 x i8> [[RES]], <32 x i8> {{.*}}
return _mm256_mask_min_epu8(__W,__M,__A,__B);
}
__m128i test_mm_maskz_min_epu16(__mmask8 __M, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_min_epu16
- // CHECK: @llvm.x86.avx512.mask.pminu.w.128
+ // 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]]
+ // 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) {
// CHECK-LABEL: @test_mm_mask_min_epu16
- // CHECK: @llvm.x86.avx512.mask.pminu.w.128
+ // 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]]
+ // CHECK: select <8 x i1> {{.*}}, <8 x i16> [[RES]], <8 x i16> {{.*}}
return _mm_mask_min_epu16(__W,__M,__A,__B);
}
__m256i test_mm256_maskz_min_epu16(__mmask16 __M, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_min_epu16
- // CHECK: @llvm.x86.avx512.mask.pminu.w.256
+ // 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_maskz_min_epu16(__M,__A,__B);
}
__m256i test_mm256_mask_min_epu16(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_min_epu16
- // CHECK: @llvm.x86.avx512.mask.pminu.w.256
+ // 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) {
// CHECK-LABEL: @test_mm_mask_shuffle_epi8
- // CHECK: @llvm.x86.avx512.mask.pshuf.b.128
+ // CHECK: @llvm.x86.ssse3.pshuf.b
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
return _mm_mask_shuffle_epi8(__W,__U,__A,__B);
}
__m128i test_mm_maskz_shuffle_epi8(__mmask16 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_shuffle_epi8
- // CHECK: @llvm.x86.avx512.mask.pshuf.b.128
+ // CHECK: @llvm.x86.ssse3.pshuf.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) {
// CHECK-LABEL: @test_mm256_mask_shuffle_epi8
- // CHECK: @llvm.x86.avx512.mask.pshuf.b.256
+ // CHECK: @llvm.x86.avx2.pshuf.b
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
return _mm256_mask_shuffle_epi8(__W,__U,__A,__B);
}
__m256i test_mm256_maskz_shuffle_epi8(__mmask32 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_shuffle_epi8
- // CHECK: @llvm.x86.avx512.mask.pshuf.b.256
+ // CHECK: @llvm.x86.avx2.pshuf.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) {
// CHECK-LABEL: @test_mm_mask_subs_epi8
- // CHECK: @llvm.x86.avx512.mask.psubs.b.128
+ // CHECK: @llvm.x86.sse2.psubs.b
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
return _mm_mask_subs_epi8(__W,__U,__A,__B);
}
__m128i test_mm_maskz_subs_epi8(__mmask16 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_subs_epi8
- // CHECK: @llvm.x86.avx512.mask.psubs.b.128
+ // CHECK: @llvm.x86.sse2.psubs.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) {
// CHECK-LABEL: @test_mm256_mask_subs_epi8
- // CHECK: @llvm.x86.avx512.mask.psubs.b.256
+ // CHECK: @llvm.x86.avx2.psubs.b
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
return _mm256_mask_subs_epi8(__W,__U,__A,__B);
}
__m256i test_mm256_maskz_subs_epi8(__mmask32 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_subs_epi8
- // CHECK: @llvm.x86.avx512.mask.psubs.b.256
+ // CHECK: @llvm.x86.avx2.psubs.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) {
// CHECK-LABEL: @test_mm_mask_subs_epi16
- // CHECK: @llvm.x86.avx512.mask.psubs.w.128
+ // CHECK: @llvm.x86.sse2.psubs.w
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_mask_subs_epi16(__W,__U,__A,__B);
}
__m128i test_mm_maskz_subs_epi16(__mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_subs_epi16
- // CHECK: @llvm.x86.avx512.mask.psubs.w.128
+ // CHECK: @llvm.x86.sse2.psubs.w
+ // 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) {
// CHECK-LABEL: @test_mm256_mask_subs_epi16
- // CHECK: @llvm.x86.avx512.mask.psubs.w.256
+ // CHECK: @llvm.x86.avx2.psubs.w
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_mask_subs_epi16(__W,__U,__A,__B);
}
__m256i test_mm256_maskz_subs_epi16(__mmask16 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_subs_epi16
- // CHECK: @llvm.x86.avx512.mask.psubs.w.256
+ // CHECK: @llvm.x86.avx2.psubs.w
+ // 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) {
// CHECK-LABEL: @test_mm_mask_subs_epu8
- // CHECK: @llvm.x86.avx512.mask.psubus.b.128
+ // CHECK: @llvm.x86.sse2.psubus.b
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i8> %{{.*}}, <16 x i8> %{{.*}}
return _mm_mask_subs_epu8(__W,__U,__A,__B);
}
__m128i test_mm_maskz_subs_epu8(__mmask16 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_subs_epu8
- // CHECK: @llvm.x86.avx512.mask.psubus.b.128
+ // CHECK: @llvm.x86.sse2.psubus.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) {
// CHECK-LABEL: @test_mm256_mask_subs_epu8
- // CHECK: @llvm.x86.avx512.mask.psubus.b.256
+ // CHECK: @llvm.x86.avx2.psubus.b
+ // CHECK: select <32 x i1> %{{.*}}, <32 x i8> %{{.*}}, <32 x i8> %{{.*}}
return _mm256_mask_subs_epu8(__W,__U,__A,__B);
}
__m256i test_mm256_maskz_subs_epu8(__mmask32 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_subs_epu8
- // CHECK: @llvm.x86.avx512.mask.psubus.b.256
+ // CHECK: @llvm.x86.avx2.psubus.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) {
// CHECK-LABEL: @test_mm_mask_subs_epu16
- // CHECK: @llvm.x86.avx512.mask.psubus.w.128
+ // CHECK: @llvm.x86.sse2.psubus.w
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_mask_subs_epu16(__W,__U,__A,__B);
}
__m128i test_mm_maskz_subs_epu16(__mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_subs_epu16
- // CHECK: @llvm.x86.avx512.mask.psubus.w.128
+ // CHECK: @llvm.x86.sse2.psubus.w
+ // 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) {
// CHECK-LABEL: @test_mm256_mask_subs_epu16
- // CHECK: @llvm.x86.avx512.mask.psubus.w.256
+ // CHECK: @llvm.x86.avx2.psubus.w
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_mask_subs_epu16(__W,__U,__A,__B);
}
__m256i test_mm256_maskz_subs_epu16(__mmask16 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_subs_epu16
- // CHECK: @llvm.x86.avx512.mask.psubus.w.256
+ // CHECK: @llvm.x86.avx2.psubus.w
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_maskz_subs_epu16(__U,__A,__B);
}
@@ -1439,49 +1590,57 @@ __m256i test_mm256_maskz_permutex2var_epi16(__mmask16 __U, __m256i __A,
}
__m128i test_mm_mask_maddubs_epi16(__m128i __W, __mmask8 __U, __m128i __X, __m128i __Y) {
// CHECK-LABEL: @test_mm_mask_maddubs_epi16
- // CHECK: @llvm.x86.avx512.mask.pmaddubs.w.128
+ // CHECK: @llvm.x86.ssse3.pmadd.ub.sw
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_mask_maddubs_epi16(__W, __U, __X, __Y);
}
__m128i test_mm_maskz_maddubs_epi16(__mmask8 __U, __m128i __X, __m128i __Y) {
// CHECK-LABEL: @test_mm_maskz_maddubs_epi16
- // CHECK: @llvm.x86.avx512.mask.pmaddubs.w.128
+ // CHECK: @llvm.x86.ssse3.pmadd.ub.sw
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_maskz_maddubs_epi16(__U, __X, __Y);
}
__m256i test_mm256_mask_maddubs_epi16(__m256i __W, __mmask16 __U, __m256i __X, __m256i __Y) {
// CHECK-LABEL: @test_mm256_mask_maddubs_epi16
- // CHECK: @llvm.x86.avx512.mask.pmaddubs.w.256
+ // CHECK: @llvm.x86.avx2.pmadd.ub.sw
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_mask_maddubs_epi16(__W, __U, __X, __Y);
}
__m256i test_mm256_maskz_maddubs_epi16(__mmask16 __U, __m256i __X, __m256i __Y) {
// CHECK-LABEL: @test_mm256_maskz_maddubs_epi16
- // CHECK: @llvm.x86.avx512.mask.pmaddubs.w.256
+ // CHECK: @llvm.x86.avx2.pmadd.ub.sw
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_maskz_maddubs_epi16(__U, __X, __Y);
}
__m128i test_mm_mask_madd_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_madd_epi16
- // CHECK: @llvm.x86.avx512.mask.pmaddw.d.128
+ // CHECK: @llvm.x86.sse2.pmadd.wd
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_mask_madd_epi16(__W, __U, __A, __B);
}
__m128i test_mm_maskz_madd_epi16(__mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_madd_epi16
- // CHECK: @llvm.x86.avx512.mask.pmaddw.d.128
+ // CHECK: @llvm.x86.sse2.pmadd.wd
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm_maskz_madd_epi16(__U, __A, __B);
}
__m256i test_mm256_mask_madd_epi16(__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_madd_epi16
- // CHECK: @llvm.x86.avx512.mask.pmaddw.d.256
+ // CHECK: @llvm.x86.avx2.pmadd.wd
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_mask_madd_epi16(__W, __U, __A, __B);
}
__m256i test_mm256_maskz_madd_epi16(__mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_madd_epi16
- // CHECK: @llvm.x86.avx512.mask.pmaddw.d.256
+ // CHECK: @llvm.x86.avx2.pmadd.wd
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> %{{.*}}
return _mm256_maskz_madd_epi16(__U, __A, __B);
}
@@ -1595,73 +1754,85 @@ __m128i test_mm256_maskz_cvtepi16_epi8(__mmask16 __M, __m256i __A) {
__m128i test_mm_mask_mulhrs_epi16(__m128i __W, __mmask8 __U, __m128i __X, __m128i __Y) {
// CHECK-LABEL: @test_mm_mask_mulhrs_epi16
- // CHECK: @llvm.x86.avx512.mask.pmul.hr.sw.128
+ // CHECK: @llvm.x86.ssse3.pmul.hr.sw
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_mask_mulhrs_epi16(__W, __U, __X, __Y);
}
__m128i test_mm_maskz_mulhrs_epi16(__mmask8 __U, __m128i __X, __m128i __Y) {
// CHECK-LABEL: @test_mm_maskz_mulhrs_epi16
- // CHECK: @llvm.x86.avx512.mask.pmul.hr.sw.128
+ // CHECK: @llvm.x86.ssse3.pmul.hr.sw
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_maskz_mulhrs_epi16(__U, __X, __Y);
}
__m256i test_mm256_mask_mulhrs_epi16(__m256i __W, __mmask16 __U, __m256i __X, __m256i __Y) {
// CHECK-LABEL: @test_mm256_mask_mulhrs_epi16
- // CHECK: @llvm.x86.avx512.mask.pmul.hr.sw.256
+ // CHECK: @llvm.x86.avx2.pmul.hr.sw
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_mask_mulhrs_epi16(__W, __U, __X, __Y);
}
__m256i test_mm256_maskz_mulhrs_epi16(__mmask16 __U, __m256i __X, __m256i __Y) {
// CHECK-LABEL: @test_mm256_maskz_mulhrs_epi16
- // CHECK: @llvm.x86.avx512.mask.pmul.hr.sw.256
+ // CHECK: @llvm.x86.avx2.pmul.hr.sw
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_maskz_mulhrs_epi16(__U, __X, __Y);
}
__m128i test_mm_mask_mulhi_epu16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_mulhi_epu16
- // CHECK: @llvm.x86.avx512.mask.pmulhu.w.128
+ // CHECK: @llvm.x86.sse2.pmulhu.w
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_mask_mulhi_epu16(__W, __U, __A, __B);
}
__m128i test_mm_maskz_mulhi_epu16(__mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_mulhi_epu16
- // CHECK: @llvm.x86.avx512.mask.pmulhu.w.128
+ // CHECK: @llvm.x86.sse2.pmulhu.w
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_maskz_mulhi_epu16(__U, __A, __B);
}
__m256i test_mm256_mask_mulhi_epu16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_mulhi_epu16
- // CHECK: @llvm.x86.avx512.mask.pmulhu.w.256
+ // CHECK: @llvm.x86.avx2.pmulhu.w
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_mask_mulhi_epu16(__W, __U, __A, __B);
}
__m256i test_mm256_maskz_mulhi_epu16(__mmask16 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_mulhi_epu16
- // CHECK: @llvm.x86.avx512.mask.pmulhu.w.256
+ // CHECK: @llvm.x86.avx2.pmulhu.w
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_maskz_mulhi_epu16(__U, __A, __B);
}
__m128i test_mm_mask_mulhi_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_mulhi_epi16
- // CHECK: @llvm.x86.avx512.mask.pmulh.w.128
+ // CHECK: @llvm.x86.sse2.pmulh.w
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_mask_mulhi_epi16(__W, __U, __A, __B);
}
__m128i test_mm_maskz_mulhi_epi16(__mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_mulhi_epi16
- // CHECK: @llvm.x86.avx512.mask.pmulh.w.128
+ // CHECK: @llvm.x86.sse2.pmulh.w
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_maskz_mulhi_epi16(__U, __A, __B);
}
__m256i test_mm256_mask_mulhi_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_mulhi_epi16
- // CHECK: @llvm.x86.avx512.mask.pmulh.w.256
+ // CHECK: @llvm.x86.avx2.pmulh.w
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_mask_mulhi_epi16(__W, __U, __A, __B);
}
__m256i test_mm256_maskz_mulhi_epi16(__mmask16 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_mulhi_epi16
- // CHECK: @llvm.x86.avx512.mask.pmulh.w.256
+ // CHECK: @llvm.x86.avx2.pmulh.w
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_maskz_mulhi_epi16(__U, __A, __B);
}
@@ -1779,256 +1950,348 @@ __m256i test_mm256_maskz_unpacklo_epi16(__mmask16 __U, __m256i __A, __m256i __B)
__m128i test_mm_mask_cvtepi8_epi16(__m128i __W, __mmask32 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_cvtepi8_epi16
- // CHECK: @llvm.x86.avx512.mask.pmovsxb.w.128
+ // CHECK: sext <8 x i8> %{{.*}} to <8 x i16>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_mask_cvtepi8_epi16(__W, __U, __A);
}
__m128i test_mm_maskz_cvtepi8_epi16(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_maskz_cvtepi8_epi16
- // CHECK: @llvm.x86.avx512.mask.pmovsxb.w.128
+ // CHECK: sext <8 x i8> %{{.*}} to <8 x i16>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_maskz_cvtepi8_epi16(__U, __A);
}
__m256i test_mm256_mask_cvtepi8_epi16(__m256i __W, __mmask32 __U, __m128i __A) {
// CHECK-LABEL: @test_mm256_mask_cvtepi8_epi16
- // CHECK: @llvm.x86.avx512.mask.pmovsxb.w.256
+ // CHECK: sext <16 x i8> %{{.*}} to <16 x i16>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_mask_cvtepi8_epi16(__W, __U, __A);
}
__m256i test_mm256_maskz_cvtepi8_epi16(__mmask16 __U, __m128i __A) {
// CHECK-LABEL: @test_mm256_maskz_cvtepi8_epi16
- // CHECK: @llvm.x86.avx512.mask.pmovsxb.w.256
+ // CHECK: sext <16 x i8> %{{.*}} to <16 x i16>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_maskz_cvtepi8_epi16(__U, __A);
}
-__m128i test_mm_mask_cvtepu8_epi32(__m128i __W, __mmask8 __U, __m128i __A) {
- // CHECK-LABEL: @test_mm_mask_cvtepu8_epi32
- // CHECK: @llvm.x86.avx512.mask.pmovzxb.d.128
- return _mm_mask_cvtepu8_epi32(__W, __U, __A);
-}
-
-__m128i test_mm_maskz_cvtepu8_epi32(__mmask8 __U, __m128i __A) {
- // CHECK-LABEL: @test_mm_maskz_cvtepu8_epi32
- // CHECK: @llvm.x86.avx512.mask.pmovzxb.d.128
- return _mm_maskz_cvtepu8_epi32(__U, __A);
-}
-
-__m256i test_mm256_mask_cvtepu8_epi32(__m256i __W, __mmask8 __U, __m128i __A) {
- // CHECK-LABEL: @test_mm256_mask_cvtepu8_epi32
- // CHECK: @llvm.x86.avx512.mask.pmovzxb.d.256
- return _mm256_mask_cvtepu8_epi32(__W, __U, __A);
-}
-
-__m256i test_mm256_maskz_cvtepu8_epi32(__mmask8 __U, __m128i __A) {
- // CHECK-LABEL: @test_mm256_maskz_cvtepu8_epi32
- // CHECK: @llvm.x86.avx512.mask.pmovzxb.d.256
- return _mm256_maskz_cvtepu8_epi32(__U, __A);
-}
-
-__m128i test_mm_mask_cvtepu8_epi64(__m128i __W, __mmask8 __U, __m128i __A) {
- // CHECK-LABEL: @test_mm_mask_cvtepu8_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovzxb.q.128
- return _mm_mask_cvtepu8_epi64(__W, __U, __A);
-}
-
-__m128i test_mm_maskz_cvtepu8_epi64(__mmask8 __U, __m128i __A) {
- // CHECK-LABEL: @test_mm_maskz_cvtepu8_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovzxb.q.128
- return _mm_maskz_cvtepu8_epi64(__U, __A);
-}
-
-__m256i test_mm256_mask_cvtepu8_epi64(__m256i __W, __mmask8 __U, __m128i __A) {
- // CHECK-LABEL: @test_mm256_mask_cvtepu8_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovzxb.q.256
- return _mm256_mask_cvtepu8_epi64(__W, __U, __A);
-}
-
-__m256i test_mm256_maskz_cvtepu8_epi64(__mmask8 __U, __m128i __A) {
- // CHECK-LABEL: @test_mm256_maskz_cvtepu8_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovzxb.q.256
- return _mm256_maskz_cvtepu8_epi64(__U, __A);
-}
-
-__m128i test_mm_mask_cvtepu32_epi64(__m128i __W, __mmask8 __U, __m128i __X) {
- // CHECK-LABEL: @test_mm_mask_cvtepu32_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovzxd.q.128
- return _mm_mask_cvtepu32_epi64(__W, __U, __X);
-}
-
-__m128i test_mm_maskz_cvtepu32_epi64(__mmask8 __U, __m128i __X) {
- // CHECK-LABEL: @test_mm_maskz_cvtepu32_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovzxd.q.128
- return _mm_maskz_cvtepu32_epi64(__U, __X);
-}
-
-__m256i test_mm256_mask_cvtepu32_epi64(__m256i __W, __mmask8 __U, __m128i __X) {
- // CHECK-LABEL: @test_mm256_mask_cvtepu32_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovzxd.q.256
- return _mm256_mask_cvtepu32_epi64(__W, __U, __X);
-}
-
-__m256i test_mm256_maskz_cvtepu32_epi64(__mmask8 __U, __m128i __X) {
- // CHECK-LABEL: @test_mm256_maskz_cvtepu32_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovzxd.q.256
- return _mm256_maskz_cvtepu32_epi64(__U, __X);
-}
-
-__m128i test_mm_mask_cvtepu16_epi32(__m128i __W, __mmask8 __U, __m128i __A) {
- // CHECK-LABEL: @test_mm_mask_cvtepu16_epi32
- // CHECK: @llvm.x86.avx512.mask.pmovzxw.d.128
- return _mm_mask_cvtepu16_epi32(__W, __U, __A);
-}
-
-__m128i test_mm_maskz_cvtepu16_epi32(__mmask8 __U, __m128i __A) {
- // CHECK-LABEL: @test_mm_maskz_cvtepu16_epi32
- // CHECK: @llvm.x86.avx512.mask.pmovzxw.d.128
- return _mm_maskz_cvtepu16_epi32(__U, __A);
-}
-
-__m256i test_mm256_mask_cvtepu16_epi32(__m256i __W, __mmask8 __U, __m128i __A) {
- // CHECK-LABEL: @test_mm256_mask_cvtepu16_epi32
- // CHECK: @llvm.x86.avx512.mask.pmovzxw.d.256
- return _mm256_mask_cvtepu16_epi32(__W, __U, __A);
-}
-
-__m256i test_mm256_maskz_cvtepu16_epi32(__mmask8 __U, __m128i __A) {
- // CHECK-LABEL: @test_mm256_maskz_cvtepu16_epi32
- // CHECK: @llvm.x86.avx512.mask.pmovzxw.d.256
- return _mm256_maskz_cvtepu16_epi32(__U, __A);
-}
-
-__m128i test_mm_mask_cvtepu16_epi64(__m128i __W, __mmask8 __U, __m128i __A) {
- // CHECK-LABEL: @test_mm_mask_cvtepu16_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovzxw.q.128
- return _mm_mask_cvtepu16_epi64(__W, __U, __A);
-}
-
-__m128i test_mm_maskz_cvtepu16_epi64(__mmask8 __U, __m128i __A) {
- // CHECK-LABEL: @test_mm_maskz_cvtepu16_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovzxw.q.128
- return _mm_maskz_cvtepu16_epi64(__U, __A);
-}
-
-__m256i test_mm256_mask_cvtepu16_epi64(__m256i __W, __mmask8 __U, __m128i __A) {
- // CHECK-LABEL: @test_mm256_mask_cvtepu16_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovzxw.q.256
- return _mm256_mask_cvtepu16_epi64(__W, __U, __A);
-}
-
-__m256i test_mm256_maskz_cvtepu16_epi64(__mmask8 __U, __m128i __A) {
- // CHECK-LABEL: @test_mm256_maskz_cvtepu16_epi64
- // CHECK: @llvm.x86.avx512.mask.pmovzxw.q.256
- return _mm256_maskz_cvtepu16_epi64(__U, __A);
-}
-
__m128i test_mm_mask_cvtepu8_epi16(__m128i __W, __mmask32 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_cvtepu8_epi16
- // CHECK: @llvm.x86.avx512.mask.pmovzxb.w.128
+ // CHECK: zext <8 x i8> %{{.*}} to <8 x i16>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_mask_cvtepu8_epi16(__W, __U, __A);
}
__m128i test_mm_maskz_cvtepu8_epi16(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_maskz_cvtepu8_epi16
- // CHECK: @llvm.x86.avx512.mask.pmovzxb.w.128
+ // CHECK: zext <8 x i8> %{{.*}} to <8 x i16>
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_maskz_cvtepu8_epi16(__U, __A);
}
__m256i test_mm256_mask_cvtepu8_epi16(__m256i __W, __mmask32 __U, __m128i __A) {
// CHECK-LABEL: @test_mm256_mask_cvtepu8_epi16
- // CHECK: @llvm.x86.avx512.mask.pmovzxb.w.256
+ // CHECK: zext <16 x i8> %{{.*}} to <16 x i16>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_mask_cvtepu8_epi16(__W, __U, __A);
}
__m256i test_mm256_maskz_cvtepu8_epi16(__mmask16 __U, __m128i __A) {
// CHECK-LABEL: @test_mm256_maskz_cvtepu8_epi16
- // CHECK: @llvm.x86.avx512.mask.pmovzxb.w.256
+ // CHECK: zext <16 x i8> %{{.*}} to <16 x i16>
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_maskz_cvtepu8_epi16(__U, __A);
}
__m256i test_mm256_sllv_epi16(__m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_sllv_epi16
- // CHECK: @llvm.x86.avx512.mask.psllv
+ // CHECK: @llvm.x86.avx512.psllv.w.256(
return _mm256_sllv_epi16(__A, __B);
}
__m256i test_mm256_mask_sllv_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_sllv_epi16
- // CHECK: @llvm.x86.avx512.mask.psllv
+ // CHECK: @llvm.x86.avx512.psllv.w.256(
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_mask_sllv_epi16(__W, __U, __A, __B);
}
__m256i test_mm256_maskz_sllv_epi16(__mmask16 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_sllv_epi16
- // CHECK: @llvm.x86.avx512.mask.psllv
+ // CHECK: @llvm.x86.avx512.psllv.w.256(
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_maskz_sllv_epi16(__U, __A, __B);
}
__m128i test_mm_sllv_epi16(__m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_sllv_epi16
- // CHECK: @llvm.x86.avx512.mask.psllv
+ // CHECK: @llvm.x86.avx512.psllv.w.128(
return _mm_sllv_epi16(__A, __B);
}
__m128i test_mm_mask_sllv_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_sllv_epi16
- // CHECK: @llvm.x86.avx512.mask.psllv
+ // CHECK: @llvm.x86.avx512.psllv.w.128(
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_mask_sllv_epi16(__W, __U, __A, __B);
}
__m128i test_mm_maskz_sllv_epi16(__mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_sllv_epi16
- // CHECK: @llvm.x86.avx512.mask.psllv
+ // CHECK: @llvm.x86.avx512.psllv.w.128(
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_maskz_sllv_epi16(__U, __A, __B);
}
__m128i test_mm_mask_sll_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_sll_epi16
- // CHECK: @llvm.x86.avx512.mask.psll.w.128
+ // CHECK: @llvm.x86.sse2.psll.w
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_mask_sll_epi16(__W, __U, __A, __B);
}
__m128i test_mm_maskz_sll_epi16(__mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_sll_epi16
- // CHECK: @llvm.x86.avx512.mask.psll.w.128
+ // CHECK: @llvm.x86.sse2.psll.w
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_maskz_sll_epi16(__U, __A, __B);
}
__m256i test_mm256_mask_sll_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m128i __B) {
// CHECK-LABEL: @test_mm256_mask_sll_epi16
- // CHECK: @llvm.x86.avx512.mask.psll.w.256
+ // CHECK: @llvm.x86.avx2.psll.w
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_mask_sll_epi16(__W, __U, __A, __B);
}
__m256i test_mm256_maskz_sll_epi16(__mmask16 __U, __m256i __A, __m128i __B) {
// CHECK-LABEL: @test_mm256_maskz_sll_epi16
- // CHECK: @llvm.x86.avx512.mask.psll.w.256
+ // CHECK: @llvm.x86.avx2.psll.w
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_maskz_sll_epi16(__U, __A, __B);
}
__m128i test_mm_mask_slli_epi16(__m128i __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_slli_epi16
- // CHECK: @llvm.x86.avx512.mask.psll.wi.128
+ // CHECK: @llvm.x86.sse2.pslli.w
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_mask_slli_epi16(__W, __U, __A, 5);
}
__m128i test_mm_maskz_slli_epi16(__mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_maskz_slli_epi16
- // CHECK: @llvm.x86.avx512.mask.psll.wi.128
+ // CHECK: @llvm.x86.sse2.pslli.w
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
return _mm_maskz_slli_epi16(__U, __A, 5);
}
__m256i test_mm256_mask_slli_epi16(__m256i __W, __mmask16 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_mask_slli_epi16
- // CHECK: @llvm.x86.avx512.mask.psll.wi.256
+ // CHECK: @llvm.x86.avx2.pslli.w
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_mask_slli_epi16(__W, __U, __A, 5);
}
__m256i test_mm256_maskz_slli_epi16(__mmask16 __U, __m256i __A) {
// CHECK-LABEL: @test_mm256_maskz_slli_epi16
- // CHECK: @llvm.x86.avx512.mask.psll.wi.256
+ // CHECK: @llvm.x86.avx2.pslli.w
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
return _mm256_maskz_slli_epi16(__U, __A, 5);
}
+__m256i test_mm256_srlv_epi16(__m256i __A, __m256i __B) {
+ // CHECK-LABEL: @test_mm256_srlv_epi16
+ // CHECK: @llvm.x86.avx512.psrlv.w.256(
+ return _mm256_srlv_epi16(__A, __B);
+}
+
+__m256i test_mm256_mask_srlv_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) {
+ // CHECK-LABEL: @test_mm256_mask_srlv_epi16
+ // CHECK: @llvm.x86.avx512.psrlv.w.256(
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
+ return _mm256_mask_srlv_epi16(__W, __U, __A, __B);
+}
+
+__m256i test_mm256_maskz_srlv_epi16(__mmask16 __U, __m256i __A, __m256i __B) {
+ // CHECK-LABEL: @test_mm256_maskz_srlv_epi16
+ // CHECK: @llvm.x86.avx512.psrlv.w.256(
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
+ return _mm256_maskz_srlv_epi16(__U, __A, __B);
+}
+
+__m128i test_mm_srlv_epi16(__m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_srlv_epi16
+ // CHECK: @llvm.x86.avx512.psrlv.w.128(
+ return _mm_srlv_epi16(__A, __B);
+}
+
+__m128i test_mm_mask_srlv_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_mask_srlv_epi16
+ // CHECK: @llvm.x86.avx512.psrlv.w.128(
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
+ return _mm_mask_srlv_epi16(__W, __U, __A, __B);
+}
+
+__m128i test_mm_maskz_srlv_epi16(__mmask8 __U, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_maskz_srlv_epi16
+ // CHECK: @llvm.x86.avx512.psrlv.w.128(
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
+ return _mm_maskz_srlv_epi16(__U, __A, __B);
+}
+
+__m128i test_mm_mask_srl_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_mask_srl_epi16
+ // CHECK: @llvm.x86.sse2.psrl.w
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
+ return _mm_mask_srl_epi16(__W, __U, __A, __B);
+}
+
+__m128i test_mm_maskz_srl_epi16(__mmask8 __U, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_maskz_srl_epi16
+ // CHECK: @llvm.x86.sse2.psrl.w
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
+ return _mm_maskz_srl_epi16(__U, __A, __B);
+}
+
+__m256i test_mm256_mask_srl_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm256_mask_srl_epi16
+ // CHECK: @llvm.x86.avx2.psrl.w
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
+ return _mm256_mask_srl_epi16(__W, __U, __A, __B);
+}
+
+__m256i test_mm256_maskz_srl_epi16(__mmask16 __U, __m256i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm256_maskz_srl_epi16
+ // CHECK: @llvm.x86.avx2.psrl.w
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
+ return _mm256_maskz_srl_epi16(__U, __A, __B);
+}
+
+__m128i test_mm_mask_srli_epi16(__m128i __W, __mmask8 __U, __m128i __A) {
+ // CHECK-LABEL: @test_mm_mask_srli_epi16
+ // CHECK: @llvm.x86.sse2.psrli.w
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
+ return _mm_mask_srli_epi16(__W, __U, __A, 5);
+}
+
+__m128i test_mm_maskz_srli_epi16(__mmask8 __U, __m128i __A) {
+ // CHECK-LABEL: @test_mm_maskz_srli_epi16
+ // CHECK: @llvm.x86.sse2.psrli.w
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
+ return _mm_maskz_srli_epi16(__U, __A, 5);
+}
+
+__m256i test_mm256_mask_srli_epi16(__m256i __W, __mmask16 __U, __m256i __A) {
+ // CHECK-LABEL: @test_mm256_mask_srli_epi16
+ // CHECK: @llvm.x86.avx2.psrli.w
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
+ return _mm256_mask_srli_epi16(__W, __U, __A, 5);
+}
+
+__m256i test_mm256_maskz_srli_epi16(__mmask16 __U, __m256i __A) {
+ // CHECK-LABEL: @test_mm256_maskz_srli_epi16
+ // CHECK: @llvm.x86.avx2.psrli.w
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
+ return _mm256_maskz_srli_epi16(__U, __A, 5);
+}
+
+__m256i test_mm256_srav_epi16(__m256i __A, __m256i __B) {
+ // CHECK-LABEL: @test_mm256_srav_epi16
+ // CHECK: @llvm.x86.avx512.psrav.w.256(
+ return _mm256_srav_epi16(__A, __B);
+}
+
+__m256i test_mm256_mask_srav_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m256i __B) {
+ // CHECK-LABEL: @test_mm256_mask_srav_epi16
+ // CHECK: @llvm.x86.avx512.psrav.w.256(
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
+ return _mm256_mask_srav_epi16(__W, __U, __A, __B);
+}
+
+__m256i test_mm256_maskz_srav_epi16(__mmask16 __U, __m256i __A, __m256i __B) {
+ // CHECK-LABEL: @test_mm256_maskz_srav_epi16
+ // CHECK: @llvm.x86.avx512.psrav.w.256(
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
+ return _mm256_maskz_srav_epi16(__U, __A, __B);
+}
+
+__m128i test_mm_srav_epi16(__m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_srav_epi16
+ // CHECK: @llvm.x86.avx512.psrav.w.128(
+ return _mm_srav_epi16(__A, __B);
+}
+
+__m128i test_mm_mask_srav_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_mask_srav_epi16
+ // CHECK: @llvm.x86.avx512.psrav.w.128(
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
+ return _mm_mask_srav_epi16(__W, __U, __A, __B);
+}
+
+__m128i test_mm_maskz_srav_epi16(__mmask8 __U, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_maskz_srav_epi16
+ // CHECK: @llvm.x86.avx512.psrav.w.128(
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
+ return _mm_maskz_srav_epi16(__U, __A, __B);
+}
+
+__m128i test_mm_mask_sra_epi16(__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_mask_sra_epi16
+ // CHECK: @llvm.x86.sse2.psra.w
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
+ return _mm_mask_sra_epi16(__W, __U, __A, __B);
+}
+
+__m128i test_mm_maskz_sra_epi16(__mmask8 __U, __m128i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm_maskz_sra_epi16
+ // CHECK: @llvm.x86.sse2.psra.w
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
+ return _mm_maskz_sra_epi16(__U, __A, __B);
+}
+
+__m256i test_mm256_mask_sra_epi16(__m256i __W, __mmask16 __U, __m256i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm256_mask_sra_epi16
+ // CHECK: @llvm.x86.avx2.psra.w
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
+ return _mm256_mask_sra_epi16(__W, __U, __A, __B);
+}
+
+__m256i test_mm256_maskz_sra_epi16(__mmask16 __U, __m256i __A, __m128i __B) {
+ // CHECK-LABEL: @test_mm256_maskz_sra_epi16
+ // CHECK: @llvm.x86.avx2.psra.w
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
+ return _mm256_maskz_sra_epi16(__U, __A, __B);
+}
+
+__m128i test_mm_mask_srai_epi16(__m128i __W, __mmask8 __U, __m128i __A) {
+ // CHECK-LABEL: @test_mm_mask_srai_epi16
+ // CHECK: @llvm.x86.sse2.psrai.w
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
+ return _mm_mask_srai_epi16(__W, __U, __A, 5);
+}
+
+__m128i test_mm_maskz_srai_epi16(__mmask8 __U, __m128i __A) {
+ // CHECK-LABEL: @test_mm_maskz_srai_epi16
+ // CHECK: @llvm.x86.sse2.psrai.w
+ // CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
+ return _mm_maskz_srai_epi16(__U, __A, 5);
+}
+
+__m256i test_mm256_mask_srai_epi16(__m256i __W, __mmask16 __U, __m256i __A) {
+ // CHECK-LABEL: @test_mm256_mask_srai_epi16
+ // CHECK: @llvm.x86.avx2.psrai.w
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
+ return _mm256_mask_srai_epi16(__W, __U, __A, 5);
+}
+
+__m256i test_mm256_maskz_srai_epi16(__mmask16 __U, __m256i __A) {
+ // CHECK-LABEL: @test_mm256_maskz_srai_epi16
+ // CHECK: @llvm.x86.avx2.psrai.w
+ // CHECK: select <16 x i1> %{{.*}}, <16 x i16> %{{.*}}, <16 x i16> %{{.*}}
+ return _mm256_maskz_srai_epi16(__U, __A, 5);
+}
+
__m128i test_mm_mask_mov_epi16(__m128i __W, __mmask8 __U, __m128i __A) {
// CHECK-LABEL: @test_mm_mask_mov_epi16
// CHECK: select <8 x i1> %{{.*}}, <8 x i16> %{{.*}}, <8 x i16> %{{.*}}
diff --git a/test/CodeGen/avx512vlcd-builtins.c b/test/CodeGen/avx512vlcd-builtins.c
index f69da039a4fb..643f24f1d22c 100644
--- a/test/CodeGen/avx512vlcd-builtins.c
+++ b/test/CodeGen/avx512vlcd-builtins.c
@@ -1,7 +1,5 @@
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +avx512vl -target-feature +avx512cd -emit-llvm -o - -Werror | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +avx512vl -target-feature +avx512cd -emit-llvm -o - -Wall -Werror | FileCheck %s
-// Don't include mm_malloc.h, it's system specific.
-#define __MM_MALLOC_H
#include <immintrin.h>
diff --git a/test/CodeGen/avx512vldq-builtins.c b/test/CodeGen/avx512vldq-builtins.c
index fa1e0623e193..6834b6f46b28 100644
--- a/test/CodeGen/avx512vldq-builtins.c
+++ b/test/CodeGen/avx512vldq-builtins.c
@@ -1,7 +1,5 @@
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +avx512dq -target-feature +avx512vl -emit-llvm -o - -Werror | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +avx512dq -target-feature +avx512vl -emit-llvm -o - -Wall -Werror | FileCheck %s
-// Don't include mm_malloc.h, it's system specific.
-#define __MM_MALLOC_H
#include <immintrin.h>
@@ -13,13 +11,15 @@ __m256i test_mm256_mullo_epi64 (__m256i __A, __m256i __B) {
__m256i test_mm256_mask_mullo_epi64 (__m256i __W, __mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_mask_mullo_epi64
- // CHECK: @llvm.x86.avx512.mask.pmull.q.256
+ // CHECK: mul <4 x i64> %{{.*}}, %{{.*}}
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return (__m256i) _mm256_mask_mullo_epi64 ( __W, __U, __A, __B);
}
__m256i test_mm256_maskz_mullo_epi64 (__mmask8 __U, __m256i __A, __m256i __B) {
// CHECK-LABEL: @test_mm256_maskz_mullo_epi64
- // CHECK: @llvm.x86.avx512.mask.pmull.q.256
+ // CHECK: mul <4 x i64> %{{.*}}, %{{.*}}
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return (__m256i) _mm256_maskz_mullo_epi64 (__U, __A, __B);
}
@@ -31,205 +31,247 @@ __m128i test_mm_mullo_epi64 (__m128i __A, __m128i __B) {
__m128i test_mm_mask_mullo_epi64 (__m128i __W, __mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_mask_mullo_epi64
- // CHECK: @llvm.x86.avx512.mask.pmull.q.128
+ // CHECK: mul <2 x i64> %{{.*}}, %{{.*}}
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return (__m128i) _mm_mask_mullo_epi64 ( __W, __U, __A, __B);
}
__m128i test_mm_maskz_mullo_epi64 (__mmask8 __U, __m128i __A, __m128i __B) {
// CHECK-LABEL: @test_mm_maskz_mullo_epi64
- // CHECK: @llvm.x86.avx512.mask.pmull.q.128
+ // CHECK: mul <2 x i64> %{{.*}}, %{{.*}}
+ // CHECK: select <2 x i1> %{{.*}}, <2 x i64> %{{.*}}, <2 x i64> %{{.*}}
return (__m128i) _mm_maskz_mullo_epi64 (__U, __A, __B);
}
__m256d test_mm256_mask_andnot_pd (__m256d __W, __mmask8 __U, __m256d __A, __m256d __B) {
// CHECK-LABEL: @test_mm256_mask_andnot_pd
- // CHECK: @llvm.x86.avx512.mask.andn.pd.256
+ // CHECK: xor <4 x i64> %{{.*}}, <i64 -1, i64 -1, i64 -1, i64 -1>
+ // CHECK: and <4 x i64> %{{.*}}, %{{.*}}
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return (__m256d) _mm256_mask_andnot_pd ( __W, __U, __A, __B);
}
__m256d test_mm256_maskz_andnot_pd (__mmask8 __U, __m256d __A, __m256d __B) {
// CHECK-LABEL: @test_mm256_maskz_andnot_pd
- // CHECK: @llvm.x86.avx512.mask.andn.pd.256
+ // CHECK: xor <4 x i64> %{{.*}}, <i64 -1, i64 -1, i64 -1, i64 -1>
+ // CHECK: and <4 x i64> %{{.*}}, %{{.*}}
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return (__m256d) _mm256_maskz_andnot_pd (__U, __A, __B);
}
__m128d test_mm_mask_andnot_pd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
// CHECK-LABEL: @test_mm_mask_andnot_pd
- // CHECK: @llvm.x86.avx512.mask.andn.pd.128
+ // CHECK: xor <2 x i64> %{{.*}}, <i64 -1, i64 -1>
+ // CHECK: and <2 x i64> %{{.*}}, %{{.*}}
+ // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return (__m128d) _mm_mask_andnot_pd ( __W, __U, __A, __B);
}
__m128d test_mm_maskz_andnot_pd (__mmask8 __U, __m128d __A, __m128d __B) {
// CHECK-LABEL: @test_mm_maskz_andnot_pd
- // CHECK: @llvm.x86.avx512.mask.andn.pd.128
+ // CHECK: xor <2 x i64> %{{.*}}, <i64 -1, i64 -1>
+ // CHECK: and <2 x i64> %{{.*}}, %{{.*}}
+ // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return (__m128d) _mm_maskz_andnot_pd (__U, __A, __B);
}
__m256 test_mm256_mask_andnot_ps (__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) {
// CHECK-LABEL: @test_mm256_mask_andnot_ps
- // CHECK: @llvm.x86.avx512.mask.andn.ps.256
+ // CHECK: xor <8 x i32> %{{.*}}, <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1>
+ // CHECK: and <8 x i32> %{{.*}}, %{{.*}}
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return (__m256) _mm256_mask_andnot_ps ( __W, __U, __A, __B);
}
__m256 test_mm256_maskz_andnot_ps (__mmask8 __U, __m256 __A, __m256 __B) {
// CHECK-LABEL: @test_mm256_maskz_andnot_ps
- // CHECK: @llvm.x86.avx512.mask.andn.ps.256
+ // CHECK: xor <8 x i32> %{{.*}}, <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1>
+ // CHECK: and <8 x i32> %{{.*}}, %{{.*}}
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return (__m256) _mm256_maskz_andnot_ps (__U, __A, __B);
}
__m128 test_mm_mask_andnot_ps (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_mask_andnot_ps
- // CHECK: @llvm.x86.avx512.mask.andn.ps.128
+ // CHECK: xor <4 x i32> %{{.*}}, <i32 -1, i32 -1, i32 -1, i32 -1>
+ // CHECK: and <4 x i32> %{{.*}}, %{{.*}}
+ // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return (__m128) _mm_mask_andnot_ps ( __W, __U, __A, __B);
}
__m128 test_mm_maskz_andnot_ps (__mmask8 __U, __m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_maskz_andnot_ps
- // CHECK: @llvm.x86.avx512.mask.andn.ps.128
+ // CHECK: xor <4 x i32> %{{.*}}, <i32 -1, i32 -1, i32 -1, i32 -1>
+ // CHECK: and <4 x i32> %{{.*}}, %{{.*}}
+ // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return (__m128) _mm_maskz_andnot_ps (__U, __A, __B);
}
__m256d test_mm256_mask_and_pd (__m256d __W, __mmask8 __U, __m256d __A, __m256d __B) {
// CHECK-LABEL: @test_mm256_mask_and_pd
- // CHECK: @llvm.x86.avx512.mask.and.pd.256
+ // CHECK: and <4 x i64> %{{.*}}, %{{.*}}
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return (__m256d) _mm256_mask_and_pd ( __W, __U, __A, __B);
}
__m256d test_mm256_maskz_and_pd (__mmask8 __U, __m256d __A, __m256d __B) {
// CHECK-LABEL: @test_mm256_maskz_and_pd
- // CHECK: @llvm.x86.avx512.mask.and.pd.256
+ // CHECK: and <4 x i64> %{{.*}}, %{{.*}}
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return (__m256d) _mm256_maskz_and_pd (__U, __A, __B);
}
__m128d test_mm_mask_and_pd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
// CHECK-LABEL: @test_mm_mask_and_pd
- // CHECK: @llvm.x86.avx512.mask.and.pd.128
+ // CHECK: and <2 x i64> %{{.*}}, %{{.*}}
+ // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return (__m128d) _mm_mask_and_pd ( __W, __U, __A, __B);
}
__m128d test_mm_maskz_and_pd (__mmask8 __U, __m128d __A, __m128d __B) {
// CHECK-LABEL: @test_mm_maskz_and_pd
- // CHECK: @llvm.x86.avx512.mask.and.pd.128
+ // CHECK: and <2 x i64> %{{.*}}, %{{.*}}
+ // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return (__m128d) _mm_maskz_and_pd (__U, __A, __B);
}
__m256 test_mm256_mask_and_ps (__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) {
// CHECK-LABEL: @test_mm256_mask_and_ps
- // CHECK: @llvm.x86.avx512.mask.and.ps.256
+ // CHECK: and <8 x i32> %{{.*}}, %{{.*}}
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return (__m256) _mm256_mask_and_ps ( __W, __U, __A, __B);
}
__m256 test_mm256_maskz_and_ps (__mmask8 __U, __m256 __A, __m256 __B) {
// CHECK-LABEL: @test_mm256_maskz_and_ps
- // CHECK: @llvm.x86.avx512.mask.and.ps.256
+ // CHECK: and <8 x i32> %{{.*}}, %{{.*}}
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return (__m256) _mm256_maskz_and_ps (__U, __A, __B);
}
__m128 test_mm_mask_and_ps (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_mask_and_ps
- // CHECK: @llvm.x86.avx512.mask.and.ps.128
+ // CHECK: and <4 x i32> %{{.*}}, %{{.*}}
+ // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return (__m128) _mm_mask_and_ps ( __W, __U, __A, __B);
}
__m128 test_mm_maskz_and_ps (__mmask8 __U, __m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_maskz_and_ps
- // CHECK: @llvm.x86.avx512.mask.and.ps.128
+ // CHECK: and <4 x i32> %{{.*}}, %{{.*}}
+ // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return (__m128) _mm_maskz_and_ps (__U, __A, __B);
}
__m256d test_mm256_mask_xor_pd (__m256d __W, __mmask8 __U, __m256d __A, __m256d __B) {
// CHECK-LABEL: @test_mm256_mask_xor_pd
- // CHECK: @llvm.x86.avx512.mask.xor.pd.256
+ // CHECK: xor <4 x i64> %{{.*}}, %{{.*}}
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return (__m256d) _mm256_mask_xor_pd ( __W, __U, __A, __B);
}
__m256d test_mm256_maskz_xor_pd (__mmask8 __U, __m256d __A, __m256d __B) {
// CHECK-LABEL: @test_mm256_maskz_xor_pd
- // CHECK: @llvm.x86.avx512.mask.xor.pd.256
+ // CHECK: xor <4 x i64> %{{.*}}, %{{.*}}
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return (__m256d) _mm256_maskz_xor_pd (__U, __A, __B);
}
__m128d test_mm_mask_xor_pd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
// CHECK-LABEL: @test_mm_mask_xor_pd
- // CHECK: @llvm.x86.avx512.mask.xor.pd.128
+ // CHECK: xor <2 x i64> %{{.*}}, %{{.*}}
+ // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return (__m128d) _mm_mask_xor_pd ( __W, __U, __A, __B);
}
__m128d test_mm_maskz_xor_pd (__mmask8 __U, __m128d __A, __m128d __B) {
// CHECK-LABEL: @test_mm_maskz_xor_pd
- // CHECK: @llvm.x86.avx512.mask.xor.pd.128
+ // CHECK: xor <2 x i64> %{{.*}}, %{{.*}}
+ // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return (__m128d) _mm_maskz_xor_pd (__U, __A, __B);
}
__m256 test_mm256_mask_xor_ps (__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) {
// CHECK-LABEL: @test_mm256_mask_xor_ps
- // CHECK: @llvm.x86.avx512.mask.xor.ps.256
+ // CHECK: xor <8 x i32> %{{.*}}, %{{.*}}
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return (__m256) _mm256_mask_xor_ps ( __W, __U, __A, __B);
}
__m256 test_mm256_maskz_xor_ps (__mmask8 __U, __m256 __A, __m256 __B) {
// CHECK-LABEL: @test_mm256_maskz_xor_ps
- // CHECK: @llvm.x86.avx512.mask.xor.ps.256
+ // CHECK: xor <8 x i32> %{{.*}}, %{{.*}}
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return (__m256) _mm256_maskz_xor_ps (__U, __A, __B);
}
__m128 test_mm_mask_xor_ps (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_mask_xor_ps
- // CHECK: @llvm.x86.avx512.mask.xor.ps.128
- return (__m128) _mm_mask_xor_ps ( __W, __U, __A, __B);
+ // CHECK: xor <4 x i32> %{{.*}}, %{{.*}}
+ // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
+ return (__m128) _mm_mask_xor_ps ( __W, __U, __A, __B);
}
__m128 test_mm_maskz_xor_ps (__mmask8 __U, __m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_maskz_xor_ps
- // CHECK: @llvm.x86.avx512.mask.xor.ps.128
+ // CHECK: xor <4 x i32> %{{.*}}, %{{.*}}
+ // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return (__m128) _mm_maskz_xor_ps (__U, __A, __B);
}
__m256d test_mm256_mask_or_pd (__m256d __W, __mmask8 __U, __m256d __A, __m256d __B) {
// CHECK-LABEL: @test_mm256_mask_or_pd
- // CHECK: @llvm.x86.avx512.mask.or.pd.256
+ // CHECK: or <4 x i64> %{{.*}}, %{{.*}}
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return (__m256d) _mm256_mask_or_pd ( __W, __U, __A, __B);
}
__m256d test_mm256_maskz_or_pd (__mmask8 __U, __m256d __A, __m256d __B) {
// CHECK-LABEL: @test_mm256_maskz_or_pd
- // CHECK: @llvm.x86.avx512.mask.or.pd.256
+ // CHECK: or <4 x i64> %{{.*}}, %{{.*}}
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return (__m256d) _mm256_maskz_or_pd (__U, __A, __B);
}
__m128d test_mm_mask_or_pd (__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) {
// CHECK-LABEL: @test_mm_mask_or_pd
- // CHECK: @llvm.x86.avx512.mask.or.pd.128
+ // CHECK: or <2 x i64> %{{.*}}, %{{.*}}
+ // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return (__m128d) _mm_mask_or_pd ( __W, __U, __A, __B);
}
__m128d test_mm_maskz_or_pd (__mmask8 __U, __m128d __A, __m128d __B) {
// CHECK-LABEL: @test_mm_maskz_or_pd
- // CHECK: @llvm.x86.avx512.mask.or.pd.128
+ // CHECK: or <2 x i64> %{{.*}}, %{{.*}}
+ // CHECK: select <2 x i1> %{{.*}}, <2 x double> %{{.*}}, <2 x double> %{{.*}}
return (__m128d) _mm_maskz_or_pd (__U, __A, __B);
}
__m256 test_mm256_mask_or_ps (__m256 __W, __mmask8 __U, __m256 __A, __m256 __B) {
// CHECK-LABEL: @test_mm256_mask_or_ps
- // CHECK: @llvm.x86.avx512.mask.or.ps.256
+ // CHECK: or <8 x i32> %{{.*}}, %{{.*}}
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return (__m256) _mm256_mask_or_ps ( __W, __U, __A, __B);
}
__m256 test_mm256_maskz_or_ps (__mmask8 __U, __m256 __A, __m256 __B) {
// CHECK-LABEL: @test_mm256_maskz_or_ps
- // CHECK: @llvm.x86.avx512.mask.or.ps.256
+ // CHECK: or <8 x i32> %{{.*}}, %{{.*}}
+ // CHECK: select <8 x i1> %{{.*}}, <8 x float> %{{.*}}, <8 x float> %{{.*}}
return (__m256) _mm256_maskz_or_ps (__U, __A, __B);
}
__m128 test_mm_mask_or_ps (__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_mask_or_ps
- // CHECK: @llvm.x86.avx512.mask.or.ps.128
+ // CHECK: or <4 x i32> %{{.*}}, %{{.*}}
+ // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return (__m128) _mm_mask_or_ps ( __W, __U, __A, __B);
}
__m128 test_mm_maskz_or_ps (__mmask8 __U, __m128 __A, __m128 __B) {
// CHECK-LABEL: @test_mm_maskz_or_ps
- // CHECK: @llvm.x86.avx512.mask.or.ps.128
+ // CHECK: or <4 x i32> %{{.*}}, %{{.*}}
+ // CHECK: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return (__m128) _mm_maskz_or_ps(__U, __A, __B);
}
@@ -950,73 +992,81 @@ __m256i test_mm256_maskz_broadcast_i64x2(__mmask8 __M, __m128i __A) {
__m128d test_mm256_extractf64x2_pd(__m256d __A) {
// CHECK-LABEL: @test_mm256_extractf64x2_pd
- // CHECK: @llvm.x86.avx512.mask.vextractf64x2
+ // 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: @llvm.x86.avx512.mask.vextractf64x2
+ // 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: @llvm.x86.avx512.mask.vextractf64x2
+ // 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: @llvm.x86.avx512.mask.vextracti64x2
+ // 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: @llvm.x86.avx512.mask.vextracti64x2
+ // 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: @llvm.x86.avx512.mask.vextracti64x2
+ // 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);
}
__m256d test_mm256_insertf64x2(__m256d __A, __m128d __B) {
// CHECK-LABEL: @test_mm256_insertf64x2
- // CHECK: @llvm.x86.avx512.mask.insertf64x2
+ // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
return _mm256_insertf64x2(__A, __B, 1);
}
__m256d test_mm256_mask_insertf64x2(__m256d __W, __mmask8 __U, __m256d __A, __m128d __B) {
// CHECK-LABEL: @test_mm256_mask_insertf64x2
- // CHECK: @llvm.x86.avx512.mask.insertf64x2
+ // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_mask_insertf64x2(__W, __U, __A, __B, 1);
}
__m256d test_mm256_maskz_insertf64x2(__mmask8 __U, __m256d __A, __m128d __B) {
// CHECK-LABEL: @test_mm256_maskz_insertf64x2
- // CHECK: @llvm.x86.avx512.mask.insertf64x2
+ // CHECK: shufflevector <4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm256_maskz_insertf64x2(__U, __A, __B, 1);
}
__m256i test_mm256_inserti64x2(__m256i __A, __m128i __B) {
// CHECK-LABEL: @test_mm256_inserti64x2
- // CHECK: @llvm.x86.avx512.mask.inserti64x2
+ // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
return _mm256_inserti64x2(__A, __B, 1);
}
__m256i test_mm256_mask_inserti64x2(__m256i __W, __mmask8 __U, __m256i __A, __m128i __B) {
// CHECK-LABEL: @test_mm256_mask_inserti64x2
- // CHECK: @llvm.x86.avx512.mask.inserti64x2
+ // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_mask_inserti64x2(__W, __U, __A, __B, 1);
}
__m256i test_mm256_maskz_inserti64x2(__mmask8 __U, __m256i __A, __m128i __B) {
// CHECK-LABEL: @test_mm256_maskz_inserti64x2
- // CHECK: @llvm.x86.avx512.mask.inserti64x2
+ // CHECK: shufflevector <4 x i64> %{{.*}}, <4 x i64> %{{.*}}, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
+ // CHECK: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm256_maskz_inserti64x2(__U, __A, __B, 1);
}
diff --git a/test/CodeGen/bitscan-builtins.c b/test/CodeGen/bitscan-builtins.c
index ae817e815749..71e49845f896 100644
--- a/test/CodeGen/bitscan-builtins.c
+++ b/test/CodeGen/bitscan-builtins.c
@@ -1,7 +1,5 @@
-// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s
-// Don't include mm_malloc.h, it's system specific.
-#define __MM_MALLOC_H
#include <immintrin.h>
int test_bit_scan_forward(int a) {
diff --git a/test/CodeGen/block-with-perdefinedexpr.cpp b/test/CodeGen/block-with-perdefinedexpr.cpp
new file mode 100644
index 000000000000..890c2d635856
--- /dev/null
+++ b/test/CodeGen/block-with-perdefinedexpr.cpp
@@ -0,0 +1,87 @@
+// RUN: %clang_cc1 %s -emit-llvm -o - -fblocks -triple x86_64-apple-darwin10 -std=c++11 | FileCheck %s
+
+void bar() {
+ // CHECK-DAG: @__FUNCTION__.___Z3barv_block_invoke = private unnamed_addr constant [17 x i8] c"bar_block_invoke\00", align 1
+ const char * (^block1)() = ^() {
+ return __FUNCTION__;
+ };
+ // CHECK-DAG: @__FUNCTION__.___Z3barv_block_invoke_2 = private unnamed_addr constant [19 x i8] c"bar_block_invoke_2\00", align 1
+ const char * (^block2)() = ^() {
+ return __FUNCTION__;
+ };
+}
+
+void baz() {
+ // CHECK-DAG: @__PRETTY_FUNCTION__.___Z3bazv_block_invoke = private unnamed_addr constant [24 x i8] c"void baz()_block_invoke\00", align 1
+ const char * (^block1)() = ^() {
+ return __PRETTY_FUNCTION__;
+ };
+ // CHECK-DAG: @__PRETTY_FUNCTION__.___Z3bazv_block_invoke_2 = private unnamed_addr constant [26 x i8] c"void baz()_block_invoke_2\00", align 1
+ const char * (^block2)() = ^() {
+ return __PRETTY_FUNCTION__;
+ };
+}
+
+namespace foonamespace {
+class Foo {
+public:
+ Foo() {
+ // CHECK-DAG: @__PRETTY_FUNCTION__.___ZN12foonamespace3FooC2Ev_block_invoke = private unnamed_addr constant [38 x i8] c"foonamespace::Foo::Foo()_block_invoke\00", align 1
+ const char * (^block1)() = ^() {
+ return __PRETTY_FUNCTION__;
+ };
+ // CHECK-DAG: @__PRETTY_FUNCTION__.___ZN12foonamespace3FooC2Ev_block_invoke_2 = private unnamed_addr constant [40 x i8] c"foonamespace::Foo::Foo()_block_invoke_2\00", align 1
+ const char * (^block2)() = ^() {
+ return __PRETTY_FUNCTION__;
+ };
+ // CHECK-DAG: @__func__.___ZN12foonamespace3FooC2Ev_block_invoke_3 = private unnamed_addr constant [19 x i8] c"Foo_block_invoke_3\00", align 1
+ const char * (^block3)() = ^() {
+ return __func__;
+ };
+ bar();
+ inside_lambda();
+ }
+ ~Foo() {
+ // CHECK-DAG: @__func__.___ZN12foonamespace3FooD2Ev_block_invoke = private unnamed_addr constant [18 x i8] c"~Foo_block_invoke\00", align 1
+ const char * (^block1)() = ^() {
+ return __func__;
+ };
+ // CHECK-DAG: @__PRETTY_FUNCTION__.___ZN12foonamespace3FooD2Ev_block_invoke_2 = private unnamed_addr constant [41 x i8] c"foonamespace::Foo::~Foo()_block_invoke_2\00", align 1
+ const char * (^block2)() = ^() {
+ return __PRETTY_FUNCTION__;
+ };
+ }
+ void bar() {
+ // CHECK-DAG: @__PRETTY_FUNCTION__.___ZN12foonamespace3Foo3barEv_block_invoke = private unnamed_addr constant [43 x i8] c"void foonamespace::Foo::bar()_block_invoke\00", align 1
+ const char * (^block1)() = ^() {
+ return __PRETTY_FUNCTION__;
+ };
+ // CHECK-DAG: @__PRETTY_FUNCTION__.___ZN12foonamespace3Foo3barEv_block_invoke_2 = private unnamed_addr constant [45 x i8] c"void foonamespace::Foo::bar()_block_invoke_2\00", align 1
+ const char * (^block2)() = ^() {
+ return __PRETTY_FUNCTION__;
+ };
+ // CHECK-DAG: @__func__.___ZN12foonamespace3Foo3barEv_block_invoke_3 = private unnamed_addr constant [19 x i8] c"bar_block_invoke_3\00", align 1
+ const char * (^block3)() = ^() {
+ return __func__;
+ };
+ }
+ void inside_lambda() {
+ auto lambda = []() {
+ // CHECK-DAG: @__PRETTY_FUNCTION__.___ZZN12foonamespace3Foo13inside_lambdaEvENKUlvE_clEv_block_invoke = private unnamed_addr constant [92 x i8] c"auto foonamespace::Foo::inside_lambda()::(anonymous class)::operator()() const_block_invoke\00", align 1
+ const char * (^block1)() = ^() {
+ return __PRETTY_FUNCTION__;
+ };
+ // CHECK-DAG: @__PRETTY_FUNCTION__.___ZZN12foonamespace3Foo13inside_lambdaEvENKUlvE_clEv_block_invoke_2 = private unnamed_addr constant [94 x i8] c"auto foonamespace::Foo::inside_lambda()::(anonymous class)::operator()() const_block_invoke_2\00", align 1
+ const char * (^block2)() = ^() {
+ return __PRETTY_FUNCTION__;
+ };
+ // CHECK-DAG: @__func__.___ZZN12foonamespace3Foo13inside_lambdaEvENKUlvE_clEv_block_invoke_3 = private unnamed_addr constant [26 x i8] c"operator()_block_invoke_3\00", align 1
+ const char * (^block3)() = ^() {
+ return __func__;
+ };
+ };
+ lambda();
+ }
+};
+Foo f;
+}
diff --git a/test/CodeGen/blocks-opencl.cl b/test/CodeGen/blocks-opencl.cl
index 61c479b7b98e..12513331e9d4 100644
--- a/test/CodeGen/blocks-opencl.cl
+++ b/test/CodeGen/blocks-opencl.cl
@@ -5,7 +5,7 @@
void dummy(float (^const op)(float)) {
}
-// CHECK: i8 addrspace(3)* getelementptr inbounds ([9 x i8], [9 x i8] addrspace(3)* @.str, i32 0, i32 0)
+// CHECK: i8 addrspace(2)* getelementptr inbounds ([9 x i8], [9 x i8] addrspace(2)* @.str, i32 0, i32 0)
kernel void test_block()
{
diff --git a/test/CodeGen/bmi-builtins.c b/test/CodeGen/bmi-builtins.c
index b9e22f9b20f5..f78e3fdd4a17 100644
--- a/test/CodeGen/bmi-builtins.c
+++ b/test/CodeGen/bmi-builtins.c
@@ -1,7 +1,5 @@
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +bmi -emit-llvm -o - -Werror | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +bmi -emit-llvm -o - -Wall -Werror | FileCheck %s
-// Don't include mm_malloc.h, it's system specific.
-#define __MM_MALLOC_H
#include <x86intrin.h>
diff --git a/test/CodeGen/bmi2-builtins.c b/test/CodeGen/bmi2-builtins.c
index b4e3fec79a47..3a5d5e756ddb 100644
--- a/test/CodeGen/bmi2-builtins.c
+++ b/test/CodeGen/bmi2-builtins.c
@@ -1,8 +1,6 @@
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +bmi2 -emit-llvm -o - | FileCheck %s
-// RUN: %clang_cc1 %s -triple=i386-apple-darwin -target-feature +bmi2 -emit-llvm -o - | FileCheck %s --check-prefix=B32
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +bmi2 -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -triple=i386-apple-darwin -target-feature +bmi2 -emit-llvm -o - | FileCheck %s --check-prefix=B32
-// Don't include mm_malloc.h, it's system specific.
-#define __MM_MALLOC_H
#include <x86intrin.h>
diff --git a/test/CodeGen/bool_test.c b/test/CodeGen/bool_test.c
index b48da3748e60..ead8854e284b 100644
--- a/test/CodeGen/bool_test.c
+++ b/test/CodeGen/bool_test.c
@@ -1,5 +1,5 @@
// REQUIRES: powerpc-registered-target
-// RUN: %clang_cc1 -triple powerpc-apple-macosx10.4.0 -emit-llvm -o - %s -O2 -disable-llvm-optzns | FileCheck %s
+// RUN: %clang_cc1 -triple powerpc-apple-macosx10.4.0 -emit-llvm -o - %s -O2 -disable-llvm-passes | FileCheck %s
int boolsize = sizeof(_Bool);
// CHECK: boolsize = global i32 4, align 4
diff --git a/test/CodeGen/builtin-clflushopt.c b/test/CodeGen/builtin-clflushopt.c
index 7248d378a4e1..e98c2aaba573 100644
--- a/test/CodeGen/builtin-clflushopt.c
+++ b/test/CodeGen/builtin-clflushopt.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +clflushopt -emit-llvm -o - -Werror | FileCheck %s
+// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +clflushopt -emit-llvm -o - -Wall -Werror | FileCheck %s
#define __MM_MALLOC_H
#include <immintrin.h>
diff --git a/test/CodeGen/builtin-expect.c b/test/CodeGen/builtin-expect.c
index 560625ed2439..2d4970021732 100644
--- a/test/CodeGen/builtin-expect.c
+++ b/test/CodeGen/builtin-expect.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s -O1 -disable-llvm-optzns | FileCheck %s --check-prefix=ALL --check-prefix=O1
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s -O1 -disable-llvm-passes | FileCheck %s --check-prefix=ALL --check-prefix=O1
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s -O0 | FileCheck %s --check-prefix=ALL --check-prefix=O0
// In all tests, make sure that no expect is generated if optimizations are off.
diff --git a/test/CodeGen/builtin-unpredictable.c b/test/CodeGen/builtin-unpredictable.c
index 653f231cad27..30709b0cac68 100644
--- a/test/CodeGen/builtin-unpredictable.c
+++ b/test/CodeGen/builtin-unpredictable.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -disable-llvm-optzns -o - %s -O1 | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -disable-llvm-passes -o - %s -O1 | FileCheck %s
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s -O0 | FileCheck %s --check-prefix=CHECK_O0
// When optimizing, the builtin should be converted to metadata.
diff --git a/test/CodeGen/builtins-ms.c b/test/CodeGen/builtins-ms.c
index 0676e9df7a7d..a33b57de8ddf 100644
--- a/test/CodeGen/builtins-ms.c
+++ b/test/CodeGen/builtins-ms.c
@@ -1,9 +1,16 @@
// RUN: %clang_cc1 %s -emit-llvm -o - -fms-extensions -triple i686-pc-win32 | FileCheck %s
-// CHECK-LABEL: define void @test_alloca
+// CHECK-LABEL: define void @test_alloca(
void capture(void *);
void test_alloca(int n) {
capture(_alloca(n));
- // CHECK: %[[arg:.*]] = alloca i8, i32 %
+ // CHECK: %[[arg:.*]] = alloca i8, i32 %{{.*}}, align 16
+ // CHECK: call void @capture(i8* %[[arg]])
+}
+
+// CHECK-LABEL: define 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
// CHECK: call void @capture(i8* %[[arg]])
}
diff --git a/test/CodeGen/builtins-nvptx.c b/test/CodeGen/builtins-nvptx.c
index cd21361140bc..b0d646a51fec 100644
--- a/test/CodeGen/builtins-nvptx.c
+++ b/test/CodeGen/builtins-nvptx.c
@@ -1,8 +1,12 @@
// REQUIRES: nvptx-registered-target
-// RUN: %clang_cc1 -triple nvptx-unknown-unknown -fcuda-is-device -S -emit-llvm -o - -x cuda %s | \
-// RUN: FileCheck -check-prefix=CHECK -check-prefix=LP32 %s
-// RUN: %clang_cc1 -triple nvptx64-unknown-unknown -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_60 \
+// RUN: -fcuda-is-device -S -emit-llvm -o - -x cuda %s \
+// RUN: | FileCheck -check-prefix=CHECK -check-prefix=LP32 %s
+// 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 nvptx-unknown-unknown -target-cpu sm_53 \
+// RUN: -DERROR_CHECK -fcuda-is-device -S -o /dev/null -x cuda -verify %s
#define __device__ __attribute__((device))
#define __global__ __attribute__((global))
@@ -191,8 +195,9 @@ __shared__ long long sll;
// Check for atomic intrinsics
// CHECK-LABEL: nvvm_atom
-__device__ void nvvm_atom(float *fp, float f, int *ip, int i, unsigned int *uip, unsigned ui, long *lp, long l,
- long long *llp, long long ll) {
+__device__ void nvvm_atom(float *fp, float f, double *dfp, double df, int *ip,
+ int i, unsigned int *uip, unsigned ui, long *lp,
+ long l, long long *llp, long long ll) {
// CHECK: atomicrmw add
__nvvm_atom_add_gen_i(ip, i);
// CHECK: atomicrmw add
@@ -280,6 +285,255 @@ __device__ void nvvm_atom(float *fp, float f, int *ip, int i, unsigned int *uip,
// CHECK: call i32 @llvm.nvvm.atomic.load.dec.32.p0i32
__nvvm_atom_dec_gen_ui(uip, ui);
+
+ //////////////////////////////////////////////////////////////////
+ // Atomics with scope (only supported on sm_60+).
+
+#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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __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}}
+ __nvvm_atom_sys_cas_gen_ll(&sll, ll, 0);
+#endif
+
// CHECK: ret
}
diff --git a/test/CodeGen/builtins-ppc-altivec.c b/test/CodeGen/builtins-ppc-altivec.c
index 1edf99f8681c..3b75cb49c3fe 100644
--- a/test/CodeGen/builtins-ppc-altivec.c
+++ b/test/CodeGen/builtins-ppc-altivec.c
@@ -45,6 +45,7 @@ unsigned short param_us;
int param_i;
unsigned int param_ui;
float param_f;
+signed long long param_sll;
int res_sc;
int res_uc;
@@ -88,6 +89,43 @@ void test1() {
// CHECK-NOALTIVEC: error: use of undeclared identifier 'vf'
// CHECK-NOALTIVEC: vf = vec_abs(vf)
+ vsc = vec_nabs(vsc);
+// CHECK: sub <16 x i8> zeroinitializer
+// CHECK: @llvm.ppc.altivec.vminsb
+// CHECK-LE: sub <16 x i8> zeroinitializer
+// CHECK-LE: @llvm.ppc.altivec.vminsb
+
+ vs = vec_nabs(vs);
+// CHECK: sub <8 x i16> zeroinitializer
+// CHECK: @llvm.ppc.altivec.vminsh
+// CHECK-LE: sub <8 x i16> zeroinitializer
+// CHECK-LE: @llvm.ppc.altivec.vminsh
+
+ vi = vec_nabs(vi);
+// CHECK: sub <4 x i32> zeroinitializer
+// CHECK: @llvm.ppc.altivec.vminsw
+// CHECK-LE: sub <4 x i32> zeroinitializer
+// CHECK-LE: @llvm.ppc.altivec.vminsw
+
+ res_vi = vec_neg(vi);
+// CHECK: sub <4 x i32> zeroinitializer, {{%[0-9]+}}
+// CHECK-LE: sub <4 x i32> zeroinitializer, {{%[0-9]+}}
+// CHECK-NOALTIVEC: error: use of undeclared identifier 'vi'
+// CHECK-NOALTIVEC: vi = vec_neg(vi);
+
+ res_vs = vec_neg(vs);
+// CHECK: sub <8 x i16> zeroinitializer, {{%[0-9]+}}
+// CHECK-LE: sub <8 x i16> zeroinitializer, {{%[0-9]+}}
+// CHECK-NOALTIVEC: error: use of undeclared identifier 'vs'
+// CHECK-NOALTIVEC: res_vs = vec_neg(vs);
+
+ res_vsc = vec_neg(vsc);
+// CHECK: sub <16 x i8> zeroinitializer, {{%[0-9]+}}
+// CHECK-LE: sub <16 x i8> zeroinitializer, {{%[0-9]+}}
+// CHECK-NOALTIVEC: error: use of undeclared identifier 'vsc'
+// CHECK-NOALTIVEC: res_vsc = vec_neg(vsc);
+
+
/* vec_abs */
vsc = vec_abss(vsc);
// CHECK: @llvm.ppc.altivec.vsubsbs
@@ -184,6 +222,22 @@ void test1() {
// CHECK: fadd <4 x float>
// CHECK-LE: fadd <4 x float>
+ res_vi = vec_adde(vi, vi, vi);
+// CHECK: and <4 x i32>
+// CHECK: add <4 x i32>
+// CHECK: add <4 x i32>
+// CHECK-LE: and <4 x i32>
+// CHECK-LE: add <4 x i32>
+// CHECK-LE: add <4 x i32>
+
+ res_vui = vec_adde(vui, vui, vui);
+// CHECK: and <4 x i32>
+// CHECK: add <4 x i32>
+// CHECK: add <4 x i32>
+// CHECK-LE: and <4 x i32>
+// CHECK-LE: add <4 x i32>
+// CHECK-LE: add <4 x i32>
+
res_vsc = vec_vaddubm(vsc, vsc);
// CHECK: add <16 x i8>
// CHECK-LE: add <16 x i8>
@@ -938,6 +992,14 @@ void test2() {
// CHECK: @llvm.ppc.altivec.vcmpequb
// CHECK-LE: @llvm.ppc.altivec.vcmpequb
+ res_vbc = vec_cmpeq(vbc, vbc);
+// CHECK: @llvm.ppc.altivec.vcmpequb
+// CHECK-LE: @llvm.ppc.altivec.vcmpequb
+
+ res_vbc = vec_cmpeq(vbc, vbc);
+// CHECK: @llvm.ppc.altivec.vcmpequb
+// CHECK-LE: @llvm.ppc.altivec.vcmpequb
+
res_vbs = vec_cmpeq(vs, vs);
// CHECK: @llvm.ppc.altivec.vcmpequh
// CHECK-LE: @llvm.ppc.altivec.vcmpequh
@@ -946,6 +1008,14 @@ void test2() {
// CHECK: @llvm.ppc.altivec.vcmpequh
// CHECK-LE: @llvm.ppc.altivec.vcmpequh
+ res_vbs = vec_cmpeq(vbs, vbs);
+// CHECK: @llvm.ppc.altivec.vcmpequh
+// CHECK-LE: @llvm.ppc.altivec.vcmpequh
+
+ res_vbs = vec_cmpeq(vbs, vbs);
+// CHECK: @llvm.ppc.altivec.vcmpequh
+// CHECK-LE: @llvm.ppc.altivec.vcmpequh
+
res_vbi = vec_cmpeq(vi, vi);
// CHECK: @llvm.ppc.altivec.vcmpequw
// CHECK-LE: @llvm.ppc.altivec.vcmpequw
@@ -954,6 +1024,14 @@ void test2() {
// CHECK: @llvm.ppc.altivec.vcmpequw
// CHECK-LE: @llvm.ppc.altivec.vcmpequw
+ res_vbi = vec_cmpeq(vbi, vbi);
+// CHECK: @llvm.ppc.altivec.vcmpequw
+// CHECK-LE: @llvm.ppc.altivec.vcmpequw
+
+ res_vbi = vec_cmpeq(vbi, vbi);
+// CHECK: @llvm.ppc.altivec.vcmpequw
+// CHECK-LE: @llvm.ppc.altivec.vcmpequw
+
res_vbi = vec_cmpeq(vf, vf);
// CHECK: @llvm.ppc.altivec.vcmpeqfp
// CHECK-LE: @llvm.ppc.altivec.vcmpeqfp
@@ -1148,6 +1226,22 @@ void test6() {
// CHECK: @llvm.ppc.altivec.vctuxs
// CHECK-LE: @llvm.ppc.altivec.vctuxs
+ res_vi = vec_signed(vf);
+// CHECK: fptosi <4 x float>
+// CHECK-LE: fptosi <4 x float>
+
+ res_vui = vec_unsigned(vf);
+// CHECK: fptoui <4 x float>
+// CHECK-LE: fptoui <4 x float>
+
+ res_vf = vec_float(vi);
+// CHECK: sitofp <4 x i32>
+// CHECK-LE: sitofp <4 x i32>
+
+ res_vf = vec_float(vui);
+// CHECK: uitofp <4 x i32>
+// CHECK-LE: uitofp <4 x i32>
+
/* vec_div */
res_vsc = vec_div(vsc, vsc);
// CHECK: sdiv <16 x i8>
@@ -3499,6 +3593,79 @@ void test6() {
// CHECK-LE: sub nsw i32 31
// CHECK-LE: @llvm.ppc.altivec.vperm
+ /* vec_sldw */
+ res_vsc = vec_sldw(vsc, vsc, 0);
+ // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1
+ // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2
+ // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3
+ // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15
+ // CHECK: @llvm.ppc.altivec.vperm
+ // CHECK-LE: sub nsw i32 16
+ // CHECK-LE: sub nsw i32 17
+ // CHECK-LE: sub nsw i32 18
+ // CHECK-LE: sub nsw i32 31
+ // CHECK-LE: @llvm.ppc.altivec.vperm
+
+ res_vuc = vec_sldw(vuc, vuc, 0);
+ // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1
+ // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2
+ // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3
+ // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15
+ // CHECK: @llvm.ppc.altivec.vperm
+ // CHECK-LE: sub nsw i32 16
+ // CHECK-LE: sub nsw i32 17
+ // CHECK-LE: sub nsw i32 18
+ // CHECK-LE: sub nsw i32 31
+ // CHECK-LE: @llvm.ppc.altivec.vperm
+
+ res_vi = vec_sldw(vi, vi, 0);
+ // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1
+ // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2
+ // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3
+ // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15
+ // CHECK: @llvm.ppc.altivec.vperm
+ // CHECK-LE: sub nsw i32 16
+ // CHECK-LE: sub nsw i32 17
+ // CHECK-LE: sub nsw i32 18
+ // CHECK-LE: sub nsw i32 31
+ // CHECK-LE: @llvm.ppc.altivec.vperm
+
+ res_vui = vec_sldw(vui, vui, 0);
+ // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1
+ // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2
+ // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3
+ // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15
+ // CHECK: @llvm.ppc.altivec.vperm
+ // CHECK-LE: sub nsw i32 16
+ // CHECK-LE: sub nsw i32 17
+ // CHECK-LE: sub nsw i32 18
+ // CHECK-LE: sub nsw i32 31
+ // CHECK-LE: @llvm.ppc.altivec.vperm
+
+ res_vs = vec_sldw(vs, vs, 0);
+ // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1
+ // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2
+ // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3
+ // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15
+ // CHECK: @llvm.ppc.altivec.vperm
+ // CHECK-LE: sub nsw i32 16
+ // CHECK-LE: sub nsw i32 17
+ // CHECK-LE: sub nsw i32 18
+ // CHECK-LE: sub nsw i32 31
+ // CHECK-LE: @llvm.ppc.altivec.vperm
+
+ res_vus = vec_sldw(vus, vus, 0);
+ // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1
+ // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2
+ // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3
+ // CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15
+ // CHECK: @llvm.ppc.altivec.vperm
+ // CHECK-LE: sub nsw i32 16
+ // CHECK-LE: sub nsw i32 17
+ // CHECK-LE: sub nsw i32 18
+ // CHECK-LE: sub nsw i32 31
+ // CHECK-LE: @llvm.ppc.altivec.vperm
+
res_vsc = vec_vsldoi(vsc, vsc, 0);
// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1
// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2
@@ -5159,6 +5326,8 @@ void test6() {
// CHECK: fsub <4 x float>
// CHECK-LE: fsub <4 x float>
+
+
res_vsc = vec_vsububm(vsc, vsc);
// CHECK: sub <16 x i8>
// CHECK-LE: sub <16 x i8>
@@ -5240,6 +5409,10 @@ void test6() {
// CHECK: @llvm.ppc.altivec.vsubcuw
// CHECK-LE: @llvm.ppc.altivec.vsubcuw
+ res_vi = vec_subc(vi, vi);
+// CHECK: @llvm.ppc.altivec.vsubcuw
+// CHECK-LE: @llvm.ppc.altivec.vsubcuw
+
res_vui = vec_vsubcuw(vui, vui);
// CHECK: @llvm.ppc.altivec.vsubcuw
// CHECK-LE: @llvm.ppc.altivec.vsubcuw
@@ -5317,6 +5490,26 @@ void test6() {
// CHECK: @llvm.ppc.altivec.vsubuws
// CHECK-LE: @llvm.ppc.altivec.vsubuws
+ res_vi = vec_sube(vi, vi, vi);
+// CHECK: and <4 x i32>
+// CHECK: xor <4 x i32> {{%[0-9]+}}, <i32 -1, i32 -1, i32 -1, i32 -1>
+// CHECK: add <4 x i32>
+// CHECK: add <4 x i32>
+// CHECK-LE: and <4 x i32>
+// CHECK-LE: xor <4 x i32> {{%[0-9]+}}, <i32 -1, i32 -1, i32 -1, i32 -1>
+// CHECK-LE: add <4 x i32>
+// CHECK-LE: add <4 x i32>
+
+ res_vui = vec_sube(vui, vui, vui);
+// CHECK: and <4 x i32>
+// CHECK: xor <4 x i32> {{%[0-9]+}}, <i32 -1, i32 -1, i32 -1, i32 -1>
+// CHECK: add <4 x i32>
+// CHECK: add <4 x i32>
+// CHECK-LE: and <4 x i32>
+// CHECK-LE: xor <4 x i32> {{%[0-9]+}}, <i32 -1, i32 -1, i32 -1, i32 -1>
+// CHECK-LE: add <4 x i32>
+// CHECK-LE: add <4 x i32>
+
res_vsc = vec_vsubsbs(vsc, vsc);
// CHECK: @llvm.ppc.altivec.vsubsbs
// CHECK-LE: @llvm.ppc.altivec.vsubsbs
@@ -8996,3 +9189,274 @@ void test7() {
// CHECK: @llvm.ppc.altivec.vcmpgefp.p(i32 2
// CHECK-LE: @llvm.ppc.altivec.vcmpgefp.p(i32 2
}
+
+/* ------------------------------ optional ---------------------------------- */
+void test8() {
+// CHECK-LABEL: define void @test8
+// CHECK-LE-LABEL: define void @test8
+ res_vbc = vec_reve(vbc);
+ // CHECK: shufflevector <16 x i8> %{{[0-9]+}}, <16 x i8> %{{[0-9]+}}, <16 x i32> <i32 15, i32 14, i32 13, i32 12, i32 11, i32 10, i32 9, i32 8, i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
+ // CHECK-LE: shufflevector <16 x i8> %{{[0-9]+}}, <16 x i8> %{{[0-9]+}}, <16 x i32> <i32 15, i32 14, i32 13, i32 12, i32 11, i32 10, i32 9, i32 8, i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
+
+ res_vsc = vec_reve(vsc);
+ // CHECK: shufflevector <16 x i8> %{{[0-9]+}}, <16 x i8> %{{[0-9]+}}, <16 x i32> <i32 15, i32 14, i32 13, i32 12, i32 11, i32 10, i32 9, i32 8, i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
+ // CHECK-LE: shufflevector <16 x i8> %{{[0-9]+}}, <16 x i8> %{{[0-9]+}}, <16 x i32> <i32 15, i32 14, i32 13, i32 12, i32 11, i32 10, i32 9, i32 8, i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
+
+ res_vuc = vec_reve(vuc);
+ // CHECK: shufflevector <16 x i8> %{{[0-9]+}}, <16 x i8> %{{[0-9]+}}, <16 x i32> <i32 15, i32 14, i32 13, i32 12, i32 11, i32 10, i32 9, i32 8, i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
+ // CHECK-LE: shufflevector <16 x i8> %{{[0-9]+}}, <16 x i8> %{{[0-9]+}}, <16 x i32> <i32 15, i32 14, i32 13, i32 12, i32 11, i32 10, i32 9, i32 8, i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
+
+ res_vbi = vec_reve(vbi);
+ // CHECK: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
+ // CHECK-LE: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
+
+ res_vi = vec_reve(vi);
+ // CHECK: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
+ // CHECK-LE: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
+
+ res_vui = vec_reve(vui);
+ // CHECK: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
+ // CHECK-LE: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
+
+ res_vbs = vec_reve(vbs);
+ // CHECK: shufflevector <8 x i16> %{{[0-9]+}}, <8 x i16> %{{[0-9]+}}, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
+ // CHECK-LE: shufflevector <8 x i16> %{{[0-9]+}}, <8 x i16> %{{[0-9]+}}, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
+
+ res_vbs = vec_reve(vs);
+ // CHECK: shufflevector <8 x i16> %{{[0-9]+}}, <8 x i16> %{{[0-9]+}}, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
+ // CHECK-LE: shufflevector <8 x i16> %{{[0-9]+}}, <8 x i16> %{{[0-9]+}}, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
+
+ res_vbs = vec_reve(vus);
+ // CHECK: shufflevector <8 x i16> %{{[0-9]+}}, <8 x i16> %{{[0-9]+}}, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
+ // CHECK-LE: shufflevector <8 x i16> %{{[0-9]+}}, <8 x i16> %{{[0-9]+}}, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
+
+ res_vf = vec_reve(vf);
+ // CHECK: shufflevector <4 x float> %{{[0-9]+}}, <4 x float> %{{[0-9]+}}, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
+ // CHECK-LE: shufflevector <4 x float> %{{[0-9]+}}, <4 x float> %{{[0-9]+}}, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
+
+ res_vbc = vec_revb(vbc);
+// CHECK: [[T1:%.+]] = load <16 x i8>, <16 x i8>* @vbc, align 16
+// CHECK: store <16 x i8> [[T1]], <16 x i8>* [[T2:%.+]], align 16
+// CHECK: [[T3:%.+]] = load <16 x i8>, <16 x i8>* [[T2]], align 16
+// CHECK: store <16 x i8> [[T3]], <16 x i8>* @res_vbc, align 16
+// CHECK-LE: [[T1:%.+]] = load <16 x i8>, <16 x i8>* @vbc, align 16
+// CHECK-LE: store <16 x i8> [[T1]], <16 x i8>* [[T2:%.+]], align 16
+// CHECK-LE: [[T3:%.+]] = load <16 x i8>, <16 x i8>* [[T2]], align 16
+// CHECK-LE: store <16 x i8> [[T3]], <16 x i8>* @res_vbc, align 16
+
+ res_vsc = vec_revb(vsc);
+// CHECK: [[T1:%.+]] = load <16 x i8>, <16 x i8>* @vsc, align 16
+// CHECK: store <16 x i8> [[T1]], <16 x i8>* [[T2:%.+]], align 16
+// CHECK: [[T3:%.+]] = load <16 x i8>, <16 x i8>* [[T2]], align 16
+// CHECK: store <16 x i8> [[T3]], <16 x i8>* @res_vsc, align 16
+// CHECK-LE: [[T1:%.+]] = load <16 x i8>, <16 x i8>* @vsc, align 16
+// CHECK-LE: store <16 x i8> [[T1]], <16 x i8>* [[T2:%.+]], align 16
+// CHECK-LE: [[T3:%.+]] = load <16 x i8>, <16 x i8>* [[T2]], align 16
+// CHECK-LE: store <16 x i8> [[T3]], <16 x i8>* @res_vsc, align 16
+
+ res_vuc = vec_revb(vuc);
+// CHECK: [[T1:%.+]] = load <16 x i8>, <16 x i8>* @vuc, align 16
+// CHECK: store <16 x i8> [[T1]], <16 x i8>* [[T2:%.+]], align 16
+// CHECK: [[T3:%.+]] = load <16 x i8>, <16 x i8>* [[T2]], align 16
+// CHECK: store <16 x i8> [[T3]], <16 x i8>* @res_vuc, align 16
+// CHECK-LE: [[T1:%.+]] = load <16 x i8>, <16 x i8>* @vuc, align 16
+// CHECK-LE: store <16 x i8> [[T1]], <16 x i8>* [[T2:%.+]], align 16
+// CHECK-LE: [[T3:%.+]] = load <16 x i8>, <16 x i8>* [[T2]], align 16
+// CHECK-LE: store <16 x i8> [[T3]], <16 x i8>* @res_vuc, align 16
+
+ res_vbs = vec_revb(vbs);
+// CHECK: store <16 x i8> <i8 1, i8 0, i8 3, i8 2, i8 5, i8 4, i8 7, i8 6, i8 9, i8 8, i8 11, i8 10, i8 13, i8 12, i8 15, i8 14>, <16 x i8>* {{%.+}}, align 16
+// CHECK: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{%.+}}, <4 x i32> {{%.+}}, <16 x i8> {{%.+}})
+// CHECK-LE: store <16 x i8> <i8 1, i8 0, i8 3, i8 2, i8 5, i8 4, i8 7, i8 6, i8 9, i8 8, i8 11, i8 10, i8 13, i8 12, i8 15, i8 14>, <16 x i8>* {{%.+}}, align 16
+// CHECK-LE: store <16 x i8> <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>, <16 x i8>* {{%.+}}, align 16
+// CHECK-LE: xor <16 x i8>
+// CHECK-LE: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{%.+}}, <4 x i32> {{%.+}}, <16 x i8> {{%.+}})
+
+ res_vs = vec_revb(vs);
+// CHECK: store <16 x i8> <i8 1, i8 0, i8 3, i8 2, i8 5, i8 4, i8 7, i8 6, i8 9, i8 8, i8 11, i8 10, i8 13, i8 12, i8 15, i8 14>, <16 x i8>* {{%.+}}, align 16
+// CHECK: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{%.+}}, <4 x i32> {{%.+}}, <16 x i8> {{%.+}})
+// CHECK-LE: store <16 x i8> <i8 1, i8 0, i8 3, i8 2, i8 5, i8 4, i8 7, i8 6, i8 9, i8 8, i8 11, i8 10, i8 13, i8 12, i8 15, i8 14>, <16 x i8>* {{%.+}}, align 16
+// CHECK-LE: store <16 x i8> <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>, <16 x i8>* {{%.+}}, align 16
+// CHECK-LE: xor <16 x i8>
+// CHECK-LE: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{%.+}}, <4 x i32> {{%.+}}, <16 x i8> {{%.+}})
+
+ res_vus = vec_revb(vus);
+// CHECK: store <16 x i8> <i8 1, i8 0, i8 3, i8 2, i8 5, i8 4, i8 7, i8 6, i8 9, i8 8, i8 11, i8 10, i8 13, i8 12, i8 15, i8 14>, <16 x i8>* {{%.+}}, align 16
+// CHECK: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{%.+}}, <4 x i32> {{%.+}}, <16 x i8> {{%.+}})
+// CHECK-LE: store <16 x i8> <i8 1, i8 0, i8 3, i8 2, i8 5, i8 4, i8 7, i8 6, i8 9, i8 8, i8 11, i8 10, i8 13, i8 12, i8 15, i8 14>, <16 x i8>* {{%.+}}, align 16
+// CHECK-LE: store <16 x i8> <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>, <16 x i8>* {{%.+}}, align 16
+// CHECK-LE: xor <16 x i8>
+// CHECK-LE: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{%.+}}, <4 x i32> {{%.+}}, <16 x i8> {{%.+}})
+
+ res_vbi = vec_revb(vbi);
+// CHECK: store <16 x i8> <i8 3, i8 2, i8 1, i8 0, i8 7, i8 6, i8 5, i8 4, i8 11, i8 10, i8 9, i8 8, i8 15, i8 14, i8 13, i8 12>, <16 x i8>* {{%.+}}, align 16
+// CHECK: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{%.+}}, <4 x i32> {{%.+}}, <16 x i8> {{%.+}})
+// CHECK-LE: store <16 x i8> <i8 3, i8 2, i8 1, i8 0, i8 7, i8 6, i8 5, i8 4, i8 11, i8 10, i8 9, i8 8, i8 15, i8 14, i8 13, i8 12>, <16 x i8>* {{%.+}}, align 16
+// CHECK-LE: store <16 x i8> <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>, <16 x i8>* {{%.+}}, align 16
+// CHECK-LE: xor <16 x i8>
+// CHECK-LE: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{%.+}}, <4 x i32> {{%.+}}, <16 x i8> {{%.+}})
+
+ res_vi = vec_revb(vi);
+// CHECK: store <16 x i8> <i8 3, i8 2, i8 1, i8 0, i8 7, i8 6, i8 5, i8 4, i8 11, i8 10, i8 9, i8 8, i8 15, i8 14, i8 13, i8 12>, <16 x i8>* {{%.+}}, align 16
+// CHECK: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{%.+}}, <4 x i32> {{%.+}}, <16 x i8> {{%.+}})
+// CHECK-LE: store <16 x i8> <i8 3, i8 2, i8 1, i8 0, i8 7, i8 6, i8 5, i8 4, i8 11, i8 10, i8 9, i8 8, i8 15, i8 14, i8 13, i8 12>, <16 x i8>* {{%.+}}, align 16
+// CHECK-LE: store <16 x i8> <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>, <16 x i8>* {{%.+}}, align 16
+// CHECK-LE: xor <16 x i8>
+// CHECK-LE: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{%.+}}, <4 x i32> {{%.+}}, <16 x i8> {{%.+}})
+
+ res_vui = vec_revb(vui);
+// CHECK: store <16 x i8> <i8 3, i8 2, i8 1, i8 0, i8 7, i8 6, i8 5, i8 4, i8 11, i8 10, i8 9, i8 8, i8 15, i8 14, i8 13, i8 12>, <16 x i8>* {{%.+}}, align 16
+// CHECK: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{%.+}}, <4 x i32> {{%.+}}, <16 x i8> {{%.+}})
+// CHECK-LE: store <16 x i8> <i8 3, i8 2, i8 1, i8 0, i8 7, i8 6, i8 5, i8 4, i8 11, i8 10, i8 9, i8 8, i8 15, i8 14, i8 13, i8 12>, <16 x i8>* {{%.+}}, align 16
+// CHECK-LE: store <16 x i8> <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>, <16 x i8>* {{%.+}}, align 16
+// CHECK-LE: xor <16 x i8>
+// CHECK-LE: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{%.+}}, <4 x i32> {{%.+}}, <16 x i8> {{%.+}})
+
+ res_vf = vec_revb(vf);
+// CHECK: store <16 x i8> <i8 3, i8 2, i8 1, i8 0, i8 7, i8 6, i8 5, i8 4, i8 11, i8 10, i8 9, i8 8, i8 15, i8 14, i8 13, i8 12>, <16 x i8>* {{%.+}}, align 16
+// CHECK: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{%.+}}, <4 x i32> {{%.+}}, <16 x i8> {{%.+}})
+// CHECK-LE: store <16 x i8> <i8 3, i8 2, i8 1, i8 0, i8 7, i8 6, i8 5, i8 4, i8 11, i8 10, i8 9, i8 8, i8 15, i8 14, i8 13, i8 12>, <16 x i8>* {{%.+}}, align 16
+// CHECK-LE: store <16 x i8> <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>, <16 x i8>* {{%.+}}, align 16
+// CHECK-LE: xor <16 x i8>
+// CHECK-LE: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{%.+}}, <4 x i32> {{%.+}}, <16 x i8> {{%.+}})
+}
+
+/* ------------------------------ vec_xl ------------------------------------ */
+void test9() {
+ // CHECK-LABEL: define void @test9
+ // CHECK-LE-LABEL: define void @test9
+ res_vsc = vec_xl(param_sll, &param_sc);
+ // CHECK: load <16 x i8>, <16 x i8>* %{{[0-9]+}}, align 16
+ // CHECK-LE: load <16 x i8>, <16 x i8>* %{{[0-9]+}}, align 16
+
+ res_vuc = vec_xl(param_sll, &param_uc);
+ // CHECK: load <16 x i8>, <16 x i8>* %{{[0-9]+}}, align 16
+ // CHECK-LE: load <16 x i8>, <16 x i8>* %{{[0-9]+}}, align 16
+
+ res_vs = vec_xl(param_sll, &param_s);
+ // CHECK: load <8 x i16>, <8 x i16>* %{{[0-9]+}}, align 16
+ // CHECK-LE: load <8 x i16>, <8 x i16>* %{{[0-9]+}}, align 16
+
+ res_vus = vec_xl(param_sll, &param_us);
+ // CHECK: load <8 x i16>, <8 x i16>* %{{[0-9]+}}, align 16
+ // CHECK-LE: load <8 x i16>, <8 x i16>* %{{[0-9]+}}, align 16
+
+ res_vi = vec_xl(param_sll, &param_i);
+ // CHECK: load <4 x i32>, <4 x i32>* %{{[0-9]+}}, align 16
+ // CHECK-LE: load <4 x i32>, <4 x i32>* %{{[0-9]+}}, align 16
+
+ res_vui = vec_xl(param_sll, &param_ui);
+ // CHECK: load <4 x i32>, <4 x i32>* %{{[0-9]+}}, align 16
+ // CHECK-LE: load <4 x i32>, <4 x i32>* %{{[0-9]+}}, align 16
+
+ res_vf = vec_xl(param_sll, &param_f);
+ // CHECK: load <4 x float>, <4 x float>* %{{[0-9]+}}, align 16
+ // CHECK-LE: load <4 x float>, <4 x float>* %{{[0-9]+}}, align 16
+}
+
+/* ------------------------------ vec_xst ----------------------------------- */
+void test10() {
+ // CHECK-LABEL: define void @test10
+ // CHECK-LE-LABEL: define void @test10
+ vec_xst(vsc, param_sll, &param_sc);
+ // CHECK: store <16 x i8> %{{[0-9]+}}, <16 x i8>* %{{[0-9]+}}, align 16
+ // CHECK-LE: store <16 x i8> %{{[0-9]+}}, <16 x i8>* %{{[0-9]+}}, align 16
+
+ vec_xst(vuc, param_sll, &param_uc);
+ // CHECK: store <16 x i8> %{{[0-9]+}}, <16 x i8>* %{{[0-9]+}}, align 16
+ // CHECK-LE: store <16 x i8> %{{[0-9]+}}, <16 x i8>* %{{[0-9]+}}, align 16
+
+ vec_xst(vs, param_sll, &param_s);
+ // CHECK: store <8 x i16> %{{[0-9]+}}, <8 x i16>* %{{[0-9]+}}, align 16
+ // CHECK-LE: store <8 x i16> %{{[0-9]+}}, <8 x i16>* %{{[0-9]+}}, align 16
+
+ vec_xst(vus, param_sll, &param_us);
+ // CHECK: store <8 x i16> %{{[0-9]+}}, <8 x i16>* %{{[0-9]+}}, align 16
+ // CHECK-LE: store <8 x i16> %{{[0-9]+}}, <8 x i16>* %{{[0-9]+}}, align 16
+
+ vec_xst(vi, param_sll, &param_i);
+ // CHECK: store <4 x i32> %{{[0-9]+}}, <4 x i32>* %{{[0-9]+}}, align 16
+ // CHECK-LE: store <4 x i32> %{{[0-9]+}}, <4 x i32>* %{{[0-9]+}}, align 16
+
+ vec_xst(vui, param_sll, &param_ui);
+ // CHECK: store <4 x i32> %{{[0-9]+}}, <4 x i32>* %{{[0-9]+}}, align 16
+ // CHECK-LE: store <4 x i32> %{{[0-9]+}}, <4 x i32>* %{{[0-9]+}}, align 16
+
+ vec_xst(vf, param_sll, &param_f);
+ // CHECK: store <4 x float> %{{[0-9]+}}, <4 x float>* %{{[0-9]+}}, align 16
+ // CHECK-LE: store <4 x float> %{{[0-9]+}}, <4 x float>* %{{[0-9]+}}, align 16
+}
+
+/* ----------------------------- vec_xl_be ---------------------------------- */
+void test11() {
+ // CHECK-LABEL: define void @test11
+ // CHECK-LE-LABEL: define void @test11
+ res_vsc = vec_xl_be(param_sll, &param_sc);
+ // CHECK: load <16 x i8>, <16 x i8>* %{{[0-9]+}}, align 16
+ // CHECK-LE: call <2 x double> @llvm.ppc.vsx.lxvd2x.be(i8* %{{[0-9]+}})
+ // CHECK-LE: shufflevector <16 x i8> %{{[0-9]+}}, <16 x i8> %{{[0-9]+}}, <16 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0, i32 15, i32 14, i32 13, i32 12, i32 11, i32 10, i32 9, i32 8>
+
+ res_vuc = vec_xl_be(param_sll, &param_uc);
+ // CHECK: load <16 x i8>, <16 x i8>* %{{[0-9]+}}, align 16
+ // CHECK-LE: call <2 x double> @llvm.ppc.vsx.lxvd2x.be(i8* %{{[0-9]+}})
+ // CHECK-LE: shufflevector <16 x i8> %{{[0-9]+}}, <16 x i8> %{{[0-9]+}}, <16 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0, i32 15, i32 14, i32 13, i32 12, i32 11, i32 10, i32 9, i32 8>
+
+ res_vs = vec_xl_be(param_sll, &param_s);
+ // CHECK: load <8 x i16>, <8 x i16>* %{{[0-9]+}}, align 16
+ // CHECK-LE: call <2 x double> @llvm.ppc.vsx.lxvd2x.be(i8* %{{[0-9]+}})
+ // CHECK-LE: shufflevector <8 x i16> %{{[0-9]+}}, <8 x i16> %{{[0-9]+}}, <8 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4>
+
+ res_vus = vec_xl_be(param_sll, &param_us);
+ // CHECK: load <8 x i16>, <8 x i16>* %{{[0-9]+}}, align 16
+ // CHECK-LE: call <2 x double> @llvm.ppc.vsx.lxvd2x.be(i8* %{{[0-9]+}})
+ // CHECK-LE: shufflevector <8 x i16> %{{[0-9]+}}, <8 x i16> %{{[0-9]+}}, <8 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4>
+
+ res_vi = vec_xl_be(param_sll, &param_i);
+ // CHECK: load <4 x i32>, <4 x i32>* %{{[0-9]+}}, align 16
+ // CHECK-LE: call <4 x i32> @llvm.ppc.vsx.lxvw4x.be(i8* %{{[0-9]+}})
+
+ res_vui = vec_xl_be(param_sll, &param_ui);
+ // CHECK: load <4 x i32>, <4 x i32>* %{{[0-9]+}}, align 16
+ // CHECK-LE: call <4 x i32> @llvm.ppc.vsx.lxvw4x.be(i8* %{{[0-9]+}})
+
+ res_vf = vec_xl_be(param_sll, &param_f);
+ // CHECK: load <4 x float>, <4 x float>* %{{[0-9]+}}, align 16
+ // CHECK-LE: call <4 x i32> @llvm.ppc.vsx.lxvw4x.be(i8* %{{[0-9]+}})
+}
+
+/* ----------------------------- vec_xst_be --------------------------------- */
+void test12() {
+ // CHECK-LABEL: define void @test12
+ // CHECK-LE-LABEL: define void @test12
+ vec_xst_be(vsc, param_sll, &param_sc);
+ // CHECK: store <16 x i8> %{{[0-9]+}}, <16 x i8>* %{{[0-9]+}}, align 16
+ // CHECK-LE: shufflevector <16 x i8> %{{[0-9]+}}, <16 x i8> %{{[0-9]+}}, <16 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0, i32 15, i32 14, i32 13, i32 12, i32 11, i32 10, i32 9, i32 8>
+ // CHECK-LE: call void @llvm.ppc.vsx.stxvd2x.be(<2 x double> %{{[0-9]+}}, i8* %{{[0-9]+}})
+
+ vec_xst_be(vuc, param_sll, &param_uc);
+ // CHECK: store <16 x i8> %{{[0-9]+}}, <16 x i8>* %{{[0-9]+}}, align 16
+ // CHECK-LE: shufflevector <16 x i8> %{{[0-9]+}}, <16 x i8> %{{[0-9]+}}, <16 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0, i32 15, i32 14, i32 13, i32 12, i32 11, i32 10, i32 9, i32 8>
+ // CHECK-LE: call void @llvm.ppc.vsx.stxvd2x.be(<2 x double> %{{[0-9]+}}, i8* %{{[0-9]+}})
+
+ vec_xst_be(vs, param_sll, &param_s);
+ // CHECK: store <8 x i16> %{{[0-9]+}}, <8 x i16>* %{{[0-9]+}}, align 16
+ // CHECK-LE: shufflevector <8 x i16> %{{[0-9]+}}, <8 x i16> %{{[0-9]+}}, <8 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4>
+ // CHECK-LE: call void @llvm.ppc.vsx.stxvd2x.be(<2 x double> %{{[0-9]+}}, i8* %{{[0-9]+}})
+
+ vec_xst_be(vus, param_sll, &param_us);
+ // CHECK: store <8 x i16> %{{[0-9]+}}, <8 x i16>* %{{[0-9]+}}, align 16
+ // CHECK-LE: shufflevector <8 x i16> %{{[0-9]+}}, <8 x i16> %{{[0-9]+}}, <8 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4>
+ // CHECK-LE: call void @llvm.ppc.vsx.stxvd2x.be(<2 x double> %{{[0-9]+}}, i8* %{{[0-9]+}})
+
+ vec_xst_be(vi, param_sll, &param_i);
+ // CHECK: store <4 x i32> %{{[0-9]+}}, <4 x i32>* %{{[0-9]+}}, align 16
+ // CHECK-LE: call void @llvm.ppc.vsx.stxvw4x.be(<4 x i32> %{{[0-9]+}}, i8* %{{[0-9]+}})
+
+ vec_xst_be(vui, param_sll, &param_ui);
+ // CHECK: store <4 x i32> %{{[0-9]+}}, <4 x i32>* %{{[0-9]+}}, align 16
+ // CHECK-LE: call void @llvm.ppc.vsx.stxvw4x.be(<4 x i32> %{{[0-9]+}}, i8* %{{[0-9]+}})
+
+ vec_xst_be(vf, param_sll, &param_f);
+ // CHECK: store <4 x float> %{{[0-9]+}}, <4 x float>* %{{[0-9]+}}, align 16
+ // CHECK-LE: call void @llvm.ppc.vsx.stxvw4x.be(<4 x i32> %{{[0-9]+}}, i8* %{{[0-9]+}})
+}
diff --git a/test/CodeGen/builtins-ppc-crypto.c b/test/CodeGen/builtins-ppc-crypto.c
index 60bdc4982d92..eaf568b09fb9 100644
--- a/test/CodeGen/builtins-ppc-crypto.c
+++ b/test/CodeGen/builtins-ppc-crypto.c
@@ -108,6 +108,30 @@ vector unsigned long long test_vpermxord(void)
// CHECK: @llvm.ppc.altivec.crypto.vpermxor
}
+// CHECK-LABEL: test_vpermxorbc
+vector bool char test_vpermxorbc(vector bool char a,
+ vector bool char b,
+ vector bool char c) {
+ return vec_permxor(a, b, c);
+// CHECK: @llvm.ppc.altivec.crypto.vpermxor
+}
+
+// CHECK-LABEL: test_vpermxorsc
+vector signed char test_vpermxorsc(vector signed char a,
+ vector signed char b,
+ vector signed char c) {
+ return vec_permxor(a, b, c);
+// CHECK: @llvm.ppc.altivec.crypto.vpermxor
+}
+
+// CHECK-LABEL: test_vpermxoruc
+vector unsigned char test_vpermxoruc(vector unsigned char a,
+ vector unsigned char b,
+ vector unsigned char c) {
+ return vec_permxor(a, b, c);
+// CHECK: @llvm.ppc.altivec.crypto.vpermxor
+}
+
// CHECK-LABEL: define <2 x i64> @test_vcipher
vector unsigned long long test_vcipher(void)
{
diff --git a/test/CodeGen/builtins-ppc-p8vector.c b/test/CodeGen/builtins-ppc-p8vector.c
index 096e3e1bb6b5..97a663c2f28f 100644
--- a/test/CodeGen/builtins-ppc-p8vector.c
+++ b/test/CodeGen/builtins-ppc-p8vector.c
@@ -73,13 +73,6 @@ void test1() {
// CHECK-LE: call <2 x i64> @llvm.ppc.altivec.vmaxsd(<2 x i64> %{{[0-9]*}}, <2 x i64>
// CHECK-PPC: error: call to 'vec_abs' is ambiguous
- res_vd = vec_abs(vda);
-// CHECK: call <2 x double> @llvm.fabs.v2f64(<2 x double> %{{.*}})
-// CHECK: store <2 x double> %{{.*}}, <2 x double>* @res_vd
-// CHECK-LE: call <2 x double> @llvm.fabs.v2f64(<2 x double> %{{.*}})
-// CHECK-LE: store <2 x double> %{{.*}}, <2 x double>* @res_vd
-// CHECK-PPC: error: call to 'vec_abs' is ambiguous
-
/* vec_add */
res_vsll = vec_add(vsll, vsll);
// CHECK: add <2 x i64>
@@ -136,6 +129,26 @@ void test1() {
// CHECK-LE: @llvm.ppc.altivec.vperm
// CHECK-PPC: warning: implicit declaration of function 'vec_mergee'
+ res_vbll = vec_mergee(vbll, vbll);
+// CHECK: @llvm.ppc.altivec.vperm
+// CHECK-LE: @llvm.ppc.altivec.vperm
+
+ res_vsll = vec_mergee(vsll, vsll);
+// CHECK: @llvm.ppc.altivec.vperm
+// CHECK-LE: @llvm.ppc.altivec.vperm
+
+ res_vull = vec_mergee(vull, vull);
+// CHECK: @llvm.ppc.altivec.vperm
+// CHECK-LE: @llvm.ppc.altivec.vperm
+
+ res_vf = vec_mergee(vfa, vfa);
+// CHECK: @llvm.ppc.altivec.vperm
+// CHECK-LE: @llvm.ppc.altivec.vperm
+
+ res_vd = vec_mergee(vda, vda);
+// CHECK: @llvm.ppc.altivec.vperm
+// CHECK-LE: @llvm.ppc.altivec.vperm
+
/* vec_mergeo */
res_vbi = vec_mergeo(vbi, vbi);
// CHECK: @llvm.ppc.altivec.vperm
@@ -151,6 +164,11 @@ void test1() {
// CHECK-PPC: warning: implicit declaration of function 'vec_mergeo'
/* vec_cmpeq */
+ res_vbll = vec_cmpeq(vbll, vbll);
+// CHECK: @llvm.ppc.altivec.vcmpequd
+// CHECK-LE: @llvm.ppc.altivec.vcmpequd
+// CHECK-PPC: error: call to 'vec_cmpeq' is ambiguous
+
res_vbll = vec_cmpeq(vsll, vsll);
// CHECK: @llvm.ppc.altivec.vcmpequd
// CHECK-LE: @llvm.ppc.altivec.vcmpequd
@@ -205,15 +223,6 @@ void test1() {
// CHECK-LE: call <2 x i64> @llvm.ppc.altivec.vcmpgtud(<2 x i64> %{{[0-9]*}}, <2 x i64> %{{[0-9]*}})
// CHECK-PPC: error: call to 'vec_cmplt' is ambiguous
- /* vec_double */
- res_vd = vec_double(vsll);
-// CHECK: sitofp i64 {{.+}} to double
-// CHECK-BE: sitofp i64 {{.+}} to double
-
- res_vd = vec_double(vull);
-// CHECK: uitofp i64 {{.+}} to double
-// CHECK-BE: uitofp i64 {{.+}} to double
-
/* vec_eqv */
res_vsc = vec_eqv(vsc, vsc);
// CHECK: [[T1:%.+]] = bitcast <16 x i8> {{.+}} to <4 x i32>
@@ -1266,6 +1275,12 @@ void test1() {
// CHECK-LE: [[T1:%.+]] = and <4 x i32>
// CHECK-LE: xor <4 x i32> [[T1]], <i32 -1, i32 -1, i32 -1, i32 -1>
+ res_vf = vec_nand(vfa, vfa);
+// CHECK: [[T1:%.+]] = and <4 x i32>
+// CHECK: xor <4 x i32> [[T1]], <i32 -1, i32 -1, i32 -1, i32 -1>
+// CHECK-LE: [[T1:%.+]] = and <4 x i32>
+// CHECK-LE: xor <4 x i32> [[T1]], <i32 -1, i32 -1, i32 -1, i32 -1>
+
res_vsll = vec_nand(vsll, vsll);
// CHECK: [[T1:%.+]] = and <2 x i64>
// CHECK: xor <2 x i64> [[T1]], <i64 -1, i64 -1>
@@ -1284,6 +1299,12 @@ void test1() {
// CHECK-LE: [[T1:%.+]] = and <2 x i64>
// CHECK-LE: xor <2 x i64> [[T1]], <i64 -1, i64 -1>
+ res_vd = vec_nand(vda, vda);
+// CHECK: [[T1:%.+]] = and <2 x i64>
+// CHECK: xor <2 x i64> [[T1]], <i64 -1, i64 -1>
+// CHECK-LE: [[T1:%.+]] = and <2 x i64>
+// CHECK-LE: xor <2 x i64> [[T1]], <i64 -1, i64 -1>
+
/* vec_orc */
res_vsc = vec_orc(vsc, vsc);
// CHECK: [[T1:%.+]] = xor <16 x i8> {{%.+}}, <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>
@@ -1412,6 +1433,18 @@ void test1() {
// CHECK-LE: [[T1:%.+]] = xor <4 x i32> {{%.+}}, <i32 -1, i32 -1, i32 -1, i32 -1>
// CHECK-LE: or <4 x i32> {{%.+}}, [[T1]]
+ res_vf = vec_orc(vbi, vfa);
+// CHECK: [[T1:%.+]] = xor <4 x i32> {{%.+}}, <i32 -1, i32 -1, i32 -1, i32 -1>
+// CHECK: or <4 x i32> {{%.+}}, [[T1]]
+// CHECK-LE: [[T1:%.+]] = xor <4 x i32> {{%.+}}, <i32 -1, i32 -1, i32 -1, i32 -1>
+// CHECK-LE: or <4 x i32> {{%.+}}, [[T1]]
+
+ res_vf = vec_orc(vfa, vbi);
+// CHECK: [[T1:%.+]] = xor <4 x i32> {{%.+}}, <i32 -1, i32 -1, i32 -1, i32 -1>
+// CHECK: or <4 x i32> {{%.+}}, [[T1]]
+// CHECK-LE: [[T1:%.+]] = xor <4 x i32> {{%.+}}, <i32 -1, i32 -1, i32 -1, i32 -1>
+// CHECK-LE: or <4 x i32> {{%.+}}, [[T1]]
+
res_vsll = vec_orc(vsll, vsll);
// CHECK: [[T1:%.+]] = xor <2 x i64> {{%.+}}, <i64 -1, i64 -1>
// CHECK: or <2 x i64> {{%.+}}, [[T1]]
@@ -1454,6 +1487,18 @@ void test1() {
// CHECK-LE: [[T1:%.+]] = xor <2 x i64> {{%.+}}, <i64 -1, i64 -1>
// CHECK-LE: or <2 x i64> {{%.+}}, [[T1]]
+ res_vd = vec_orc(vbll, vda);
+// CHECK: [[T1:%.+]] = xor <2 x i64> {{%.+}}, <i64 -1, i64 -1>
+// CHECK: or <2 x i64> {{%.+}}, [[T1]]
+// CHECK-LE: [[T1:%.+]] = xor <2 x i64> {{%.+}}, <i64 -1, i64 -1>
+// CHECK-LE: or <2 x i64> {{%.+}}, [[T1]]
+
+ res_vd = vec_orc(vda, vbll);
+// CHECK: [[T1:%.+]] = xor <2 x i64> {{%.+}}, <i64 -1, i64 -1>
+// CHECK: or <2 x i64> {{%.+}}, [[T1]]
+// CHECK-LE: [[T1:%.+]] = xor <2 x i64> {{%.+}}, <i64 -1, i64 -1>
+// CHECK-LE: or <2 x i64> {{%.+}}, [[T1]]
+
/* vec_sub */
res_vsll = vec_sub(vsll, vsll);
// CHECK: sub <2 x i64>
@@ -1504,4 +1549,77 @@ void test1() {
// CHECK: llvm.ppc.altivec.vbpermq
// CHECK-LE: llvm.ppc.altivec.vbpermq
// CHECK-PPC: warning: implicit declaration of function 'vec_bperm'
+
+ res_vsll = vec_neg(vsll);
+// CHECK: sub <2 x i64> zeroinitializer, {{%[0-9]+}}
+// CHECK-LE: sub <2 x i64> zeroinitializer, {{%[0-9]+}}
+// CHECK_PPC: call to 'vec_neg' is ambiguous
+
+
+}
+
+
+vector signed int test_vec_addec_signed (vector signed int a, vector signed int b, vector signed int c) {
+ return vec_addec(a, b, c);
+// CHECK-LABEL: @test_vec_addec_signed
+// CHECK: icmp slt i32 {{%[0-9]+}}, 4
+// CHECK: extractelement
+// CHECK: extractelement
+// CHECK: extractelement
+// CHECK: and i32 {{%[0-9]+}}, 1
+// CHECK: zext
+// CHECK: zext
+// CHECK: zext
+// CHECK: add i64
+// CHECK: add i64
+// CHECK: lshr i64
+// CHECK: and i64
+// CHECK: trunc i64 {{%[0-9]+}} to i32
+// CHECK: zext i32
+// CHECK: trunc i64 {{%[0-9]+}} to i32
+// CHECK: sext i32
+// CHECK: add nsw i32
+// CHECK: br label
+// CHECK: ret <4 x i32>
+
+}
+
+
+vector unsigned int test_vec_addec_unsigned (vector unsigned int a, vector unsigned int b, vector unsigned int c) {
+ return vec_addec(a, b, c);
+
+// CHECK-LABEL: @test_vec_addec_unsigned
+// CHECK: icmp slt i32 {{%[0-9]+}}, 4
+// CHECK: extractelement
+// CHECK: and i32
+// CHECK: extractelement
+// CHECK: zext i32
+// CHECK: extractelement
+// CHECK: zext i32
+// CHECK: zext i32
+// CHECK: add i64
+// CHECK: lshr i64
+// CHECK: and i64
+// CHECK: trunc i64 {{%[0-9]+}} to i32
+// CHECK: zext i32
+// CHECK: trunc i64 {{%[0-9]+}} to i32
+// CHECK: sext i32
+// CHECK: add nsw i32
+// CHECK: br label
+// CHECK: ret <4 x i32>
+}
+
+vector signed int test_vec_subec_signed (vector signed int a, vector signed int b, vector signed int c) {
+ return vec_subec(a, b, c);
+// CHECK-LABEL: @test_vec_subec_signed
+// CHECK: xor <4 x i32> {{%[0-9]+}}, <i32 -1, i32 -1, i32 -1, i32 -1>
+// CHECK: ret <4 x i32>
+}
+
+vector unsigned int test_vec_subec_unsigned (vector unsigned int a, vector unsigned int b, vector unsigned int c) {
+ return vec_subec(a, b, c);
+
+// CHECK-LABEL: @test_vec_subec_unsigned
+// CHECK: xor <4 x i32> {{%[0-9]+}}, <i32 -1, i32 -1, i32 -1, i32 -1>
+// CHECK: ret <4 x i32>
}
diff --git a/test/CodeGen/builtins-ppc-p9vector.c b/test/CodeGen/builtins-ppc-p9vector.c
new file mode 100644
index 000000000000..f70d2f9f1504
--- /dev/null
+++ b/test/CodeGen/builtins-ppc-p9vector.c
@@ -0,0 +1,1182 @@
+// REQUIRES: powerpc-registered-target
+// RUN: %clang_cc1 -faltivec -target-feature +power9-vector \
+// RUN: -triple powerpc64-unknown-unknown -emit-llvm %s \
+// RUN: -o - | FileCheck %s -check-prefix=CHECK-BE
+
+// RUN: %clang_cc1 -faltivec -target-feature +power9-vector \
+// RUN: -triple powerpc64le-unknown-unknown -emit-llvm %s \
+// RUN: -o - | FileCheck %s
+
+#include <altivec.h>
+
+vector signed char vsca, vscb;
+vector unsigned char vuca, vucb;
+vector bool char vbca, vbcb;
+vector signed short vssa, vssb;
+vector unsigned short vusa, vusb;
+vector bool short vbsa, vbsb;
+vector signed int vsia, vsib;
+vector unsigned int vuia, vuib;
+vector bool int vbia, vbib;
+vector signed long long vsla, vslb;
+vector unsigned long long vula, vulb;
+vector bool long long vbla, vblb;
+vector float vfa, vfb;
+vector double vda, vdb;
+vector unsigned __int128 vui128a, vui128b;
+vector signed __int128 vsi128a, vsi128b;
+
+float f[4] = { 23.4f, 56.7f, 89.0f, 12.3f };
+double d[2] = { 23.4, 56.7 };
+signed char sc[16] = { -8, 9, -10, 11, -12, 13, -14, 15,
+ -0, 1, -2, 3, -4, 5, -6, 7 };
+unsigned char uc[16] = { 8, 9, 10, 11, 12, 13, 14, 15,
+ 0, 1, 2, 3, 4, 5, 6, 7 };
+signed short ss[8] = { -1, 2, -3, 4, -5, 6, -7, 8 };
+unsigned short us[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
+signed int si[4] = { -1, 2, -3, 4 };
+unsigned int ui[4] = { 0, 1, 2, 3 };
+signed long sl[2] = { -1L, 2L };
+unsigned long ul[2] = { 1L, 2L };
+signed long long sll[2] = { 1LL, 1LL };
+unsigned long long ull[2] = { -1LL, 1LL };
+signed __int128 sint128[1] = { -1 };
+unsigned __int128 uint128[1] = { 1 };
+
+unsigned test1(void) {
+// CHECK-BE: @llvm.ppc.altivec.vcmpequb(<16 x i8>
+// CHECK-BE: @llvm.ctlz.v2i64(<2 x i64>
+// CHECK-BE: extractelement <2 x i64>
+// CHECK-BE: icmp eq i64 {{.*}}, 64
+// CHECK-BE: extractelement <2 x i64>
+// CHECK-BE: add i64 {{.*}}, 64
+// CHECK-BE: lshr i64 {{.*}}, 3
+// CHECK: @llvm.ppc.altivec.vcmpequb(<16 x i8>
+// CHECK: @llvm.cttz.v2i64(<2 x i64>
+// CHECK: extractelement <2 x i64>
+// CHECK: icmp eq i64 {{.*}}, 64
+// CHECK: extractelement <2 x i64>
+// CHECK: add i64 {{.*}}, 64
+// CHECK: lshr i64 {{.*}}, 3
+ return vec_first_match_index (vsca, vscb);
+}
+unsigned test2(void) {
+// CHECK-BE: @llvm.ppc.altivec.vcmpequb(<16 x i8>
+// CHECK-BE: @llvm.ctlz.v2i64(<2 x i64>
+// CHECK-BE: extractelement <2 x i64>
+// CHECK-BE: icmp eq i64 {{.*}}, 64
+// CHECK-BE: extractelement <2 x i64>
+// CHECK-BE: add i64 {{.*}}, 64
+// CHECK-BE: lshr i64 {{.*}}, 3
+// CHECK: @llvm.ppc.altivec.vcmpequb(<16 x i8>
+// CHECK: @llvm.cttz.v2i64(<2 x i64>
+// CHECK: extractelement <2 x i64>
+// CHECK: icmp eq i64 {{.*}}, 64
+// CHECK: extractelement <2 x i64>
+// CHECK: add i64 {{.*}}, 64
+// CHECK: lshr i64 {{.*}}, 3
+ return vec_first_match_index (vuca, vucb);
+}
+unsigned test3(void) {
+// CHECK-BE: @llvm.ppc.altivec.vcmpequw(<4 x i32>
+// CHECK-BE: @llvm.ctlz.v2i64(<2 x i64>
+// CHECK-BE: extractelement <2 x i64>
+// CHECK-BE: icmp eq i64 {{.*}}, 64
+// CHECK-BE: extractelement <2 x i64>
+// CHECK-BE: add i64 {{.*}}, 64
+// CHECK-BE: lshr i64 {{.*}}, 5
+// CHECK: @llvm.ppc.altivec.vcmpequw(<4 x i32>
+// CHECK: @llvm.cttz.v2i64(<2 x i64>
+// CHECK: extractelement <2 x i64>
+// CHECK: icmp eq i64 {{.*}}, 64
+// CHECK: extractelement <2 x i64>
+// CHECK: add i64 {{.*}}, 64
+// CHECK: lshr i64 {{.*}}, 5
+ return vec_first_match_index (vsia, vsib);
+}
+unsigned test4(void) {
+// CHECK-BE: @llvm.ppc.altivec.vcmpequw(<4 x i32>
+// CHECK-BE: @llvm.ctlz.v2i64(<2 x i64>
+// CHECK-BE: extractelement <2 x i64>
+// CHECK-BE: icmp eq i64 {{.*}}, 64
+// CHECK-BE: extractelement <2 x i64>
+// CHECK-BE: add i64 {{.*}}, 64
+// CHECK-BE: lshr i64 {{.*}}, 5
+// CHECK: @llvm.ppc.altivec.vcmpequw(<4 x i32>
+// CHECK: @llvm.cttz.v2i64(<2 x i64>
+// CHECK: extractelement <2 x i64>
+// CHECK: icmp eq i64 {{.*}}, 64
+// CHECK: extractelement <2 x i64>
+// CHECK: add i64 {{.*}}, 64
+// CHECK: lshr i64 {{.*}}, 5
+ return vec_first_match_index (vuia, vuib);
+}
+unsigned test5(void) {
+// CHECK-BE: @llvm.ppc.altivec.vcmpequh(<8 x i16>
+// CHECK-BE: @llvm.ctlz.v2i64(<2 x i64>
+// CHECK-BE: extractelement <2 x i64>
+// CHECK-BE: icmp eq i64 {{.*}}, 64
+// CHECK-BE: extractelement <2 x i64>
+// CHECK-BE: add i64 {{.*}}, 64
+// CHECK-BE: lshr i64 {{.*}}, 4
+// CHECK: @llvm.ppc.altivec.vcmpequh(<8 x i16>
+// CHECK: @llvm.cttz.v2i64(<2 x i64>
+// CHECK: extractelement <2 x i64>
+// CHECK: icmp eq i64 {{.*}}, 64
+// CHECK: extractelement <2 x i64>
+// CHECK: add i64 {{.*}}, 64
+// CHECK: lshr i64 {{.*}}, 4
+ return vec_first_match_index (vssa, vssb);
+}
+unsigned test6(void) {
+// CHECK-BE: @llvm.ppc.altivec.vcmpequh(<8 x i16>
+// CHECK-BE: @llvm.ctlz.v2i64(<2 x i64>
+// CHECK-BE: extractelement <2 x i64>
+// CHECK-BE: icmp eq i64 {{.*}}, 64
+// CHECK-BE: extractelement <2 x i64>
+// CHECK-BE: add i64 {{.*}}, 64
+// CHECK-BE: lshr i64 {{.*}}, 4
+// CHECK: @llvm.ppc.altivec.vcmpequh(<8 x i16>
+// CHECK: @llvm.cttz.v2i64(<2 x i64>
+// CHECK: extractelement <2 x i64>
+// CHECK: icmp eq i64 {{.*}}, 64
+// CHECK: extractelement <2 x i64>
+// CHECK: add i64 {{.*}}, 64
+// CHECK: lshr i64 {{.*}}, 4
+ return vec_first_match_index (vusa, vusb);
+}
+unsigned test7(void) {
+// CHECK-BE: @llvm.ppc.altivec.vcmpequb(<16 x i8>
+// CHECK-BE: @llvm.ppc.altivec.vcmpequb(<16 x i8>
+// CHECK-BE: or <16 x i8>
+// CHECK-BE: @llvm.ppc.altivec.vcmpequb(<16 x i8>
+// CHECK-BE: or <16 x i8>
+// CHECK-BE: @llvm.ctlz.v2i64(<2 x i64>
+// CHECK-BE: extractelement <2 x i64>
+// CHECK-BE: icmp eq i64 {{.*}}, 64
+// CHECK-BE: extractelement <2 x i64>
+// CHECK-BE: add i64 {{.*}}, 64
+// CHECK-BE: lshr i64 {{.*}}, 3
+// CHECK: @llvm.ppc.altivec.vcmpequb(<16 x i8>
+// CHECK: @llvm.ppc.altivec.vcmpequb(<16 x i8>
+// CHECK: or <16 x i8>
+// CHECK: @llvm.ppc.altivec.vcmpequb(<16 x i8>
+// CHECK: or <16 x i8>
+// CHECK: @llvm.cttz.v2i64(<2 x i64>
+// CHECK: extractelement <2 x i64>
+// CHECK: icmp eq i64 {{.*}}, 64
+// CHECK: extractelement <2 x i64>
+// CHECK: add i64 {{.*}}, 64
+// CHECK: lshr i64 {{.*}}, 3
+ return vec_first_match_or_eos_index (vsca, vscb);
+}
+unsigned test8(void) {
+// CHECK-BE: @llvm.ppc.altivec.vcmpequb(<16 x i8>
+// CHECK-BE: @llvm.ppc.altivec.vcmpequb(<16 x i8>
+// CHECK-BE: or <16 x i8>
+// CHECK-BE: @llvm.ppc.altivec.vcmpequb(<16 x i8>
+// CHECK-BE: or <16 x i8>
+// CHECK-BE: @llvm.ctlz.v2i64(<2 x i64>
+// CHECK-BE: extractelement <2 x i64>
+// CHECK-BE: icmp eq i64 {{.*}}, 64
+// CHECK-BE: extractelement <2 x i64>
+// CHECK-BE: add i64 {{.*}}, 64
+// CHECK-BE: lshr i64 {{.*}}, 3
+// CHECK: @llvm.ppc.altivec.vcmpequb(<16 x i8>
+// CHECK: @llvm.ppc.altivec.vcmpequb(<16 x i8>
+// CHECK: or <16 x i8>
+// CHECK: @llvm.ppc.altivec.vcmpequb(<16 x i8>
+// CHECK: or <16 x i8>
+// CHECK: @llvm.cttz.v2i64(<2 x i64>
+// CHECK: extractelement <2 x i64>
+// CHECK: icmp eq i64 {{.*}}, 64
+// CHECK: extractelement <2 x i64>
+// CHECK: add i64 {{.*}}, 64
+// CHECK: lshr i64 {{.*}}, 3
+ return vec_first_match_or_eos_index (vuca, vucb);
+}
+unsigned test9(void) {
+// CHECK-BE: @llvm.ppc.altivec.vcmpequw(<4 x i32>
+// CHECK-BE: @llvm.ppc.altivec.vcmpequw(<4 x i32>
+// CHECK-BE: or <4 x i32>
+// CHECK-BE: @llvm.ppc.altivec.vcmpequw(<4 x i32>
+// CHECK-BE: or <4 x i32>
+// CHECK-BE: @llvm.ctlz.v2i64(<2 x i64>
+// CHECK-BE: extractelement <2 x i64>
+// CHECK-BE: icmp eq i64 {{.*}}, 64
+// CHECK-BE: extractelement <2 x i64>
+// CHECK-BE: add i64 {{.*}}, 64
+// CHECK-BE: lshr i64 {{.*}}, 5
+// CHECK: @llvm.ppc.altivec.vcmpequw(<4 x i32>
+// CHECK: @llvm.ppc.altivec.vcmpequw(<4 x i32>
+// CHECK: or <4 x i32>
+// CHECK: @llvm.ppc.altivec.vcmpequw(<4 x i32>
+// CHECK: or <4 x i32>
+// CHECK: @llvm.cttz.v2i64(<2 x i64>
+// CHECK: extractelement <2 x i64>
+// CHECK: icmp eq i64 {{.*}}, 64
+// CHECK: extractelement <2 x i64>
+// CHECK: add i64 {{.*}}, 64
+// CHECK: lshr i64 {{.*}}, 5
+ return vec_first_match_or_eos_index (vsia, vsib);
+}
+unsigned test10(void) {
+// CHECK-BE: @llvm.ppc.altivec.vcmpequw(<4 x i32>
+// CHECK-BE: @llvm.ppc.altivec.vcmpequw(<4 x i32>
+// CHECK-BE: or <4 x i32>
+// CHECK-BE: @llvm.ppc.altivec.vcmpequw(<4 x i32>
+// CHECK-BE: or <4 x i32>
+// CHECK-BE: @llvm.ctlz.v2i64(<2 x i64>
+// CHECK-BE: extractelement <2 x i64>
+// CHECK-BE: icmp eq i64 {{.*}}, 64
+// CHECK-BE: extractelement <2 x i64>
+// CHECK-BE: add i64 {{.*}}, 64
+// CHECK-BE: lshr i64 {{.*}}, 5
+// CHECK: @llvm.ppc.altivec.vcmpequw(<4 x i32>
+// CHECK: @llvm.ppc.altivec.vcmpequw(<4 x i32>
+// CHECK: or <4 x i32>
+// CHECK: @llvm.ppc.altivec.vcmpequw(<4 x i32>
+// CHECK: or <4 x i32>
+// CHECK: @llvm.cttz.v2i64(<2 x i64>
+// CHECK: extractelement <2 x i64>
+// CHECK: icmp eq i64 {{.*}}, 64
+// CHECK: extractelement <2 x i64>
+// CHECK: add i64 {{.*}}, 64
+// CHECK: lshr i64 {{.*}}, 5
+ return vec_first_match_or_eos_index (vuia, vuib);
+}
+unsigned test11(void) {
+// CHECK-BE: @llvm.ppc.altivec.vcmpequh(<8 x i16>
+// CHECK-BE: @llvm.ppc.altivec.vcmpequh(<8 x i16>
+// CHECK-BE: or <8 x i16>
+// CHECK-BE: @llvm.ppc.altivec.vcmpequh(<8 x i16>
+// CHECK-BE: or <8 x i16>
+// CHECK-BE: @llvm.ctlz.v2i64(<2 x i64>
+// CHECK-BE: extractelement <2 x i64>
+// CHECK-BE: icmp eq i64 {{.*}}, 64
+// CHECK-BE: extractelement <2 x i64>
+// CHECK-BE: add i64 {{.*}}, 64
+// CHECK-BE: lshr i64 {{.*}}, 4
+// CHECK: @llvm.ppc.altivec.vcmpequh(<8 x i16>
+// CHECK: @llvm.ppc.altivec.vcmpequh(<8 x i16>
+// CHECK: or <8 x i16>
+// CHECK: @llvm.ppc.altivec.vcmpequh(<8 x i16>
+// CHECK: or <8 x i16>
+// CHECK: @llvm.cttz.v2i64(<2 x i64>
+// CHECK: extractelement <2 x i64>
+// CHECK: icmp eq i64 {{.*}}, 64
+// CHECK: extractelement <2 x i64>
+// CHECK: add i64 {{.*}}, 64
+// CHECK: lshr i64 {{.*}}, 4
+ return vec_first_match_or_eos_index (vssa, vssb);
+}
+unsigned test12(void) {
+// CHECK-BE: @llvm.ppc.altivec.vcmpequh(<8 x i16>
+// CHECK-BE: @llvm.ppc.altivec.vcmpequh(<8 x i16>
+// CHECK-BE: or <8 x i16>
+// CHECK-BE: @llvm.ppc.altivec.vcmpequh(<8 x i16>
+// CHECK-BE: or <8 x i16>
+// CHECK-BE: @llvm.ctlz.v2i64(<2 x i64>
+// CHECK-BE: extractelement <2 x i64>
+// CHECK-BE: icmp eq i64 {{.*}}, 64
+// CHECK-BE: extractelement <2 x i64>
+// CHECK-BE: add i64 {{.*}}, 64
+// CHECK-BE: lshr i64 {{.*}}, 4
+// CHECK: @llvm.ppc.altivec.vcmpequh(<8 x i16>
+// CHECK: @llvm.ppc.altivec.vcmpequh(<8 x i16>
+// CHECK: or <8 x i16>
+// CHECK: @llvm.ppc.altivec.vcmpequh(<8 x i16>
+// CHECK: or <8 x i16>
+// CHECK: @llvm.cttz.v2i64(<2 x i64>
+// CHECK: extractelement <2 x i64>
+// CHECK: icmp eq i64 {{.*}}, 64
+// CHECK: extractelement <2 x i64>
+// CHECK: add i64 {{.*}}, 64
+// CHECK: lshr i64 {{.*}}, 4
+ return vec_first_match_or_eos_index (vusa, vusb);
+}
+unsigned test13(void) {
+// CHECK-BE: @llvm.ppc.altivec.vcmpneb(<16 x i8>
+// CHECK-BE: @llvm.ctlz.v2i64(<2 x i64>
+// CHECK-BE: extractelement <2 x i64>
+// CHECK-BE: icmp eq i64 {{.*}}, 64
+// CHECK-BE: extractelement <2 x i64>
+// CHECK-BE: add i64 {{.*}}, 64
+// CHECK-BE: lshr i64 {{.*}}, 3
+// CHECK: @llvm.ppc.altivec.vcmpneb(<16 x i8>
+// CHECK: @llvm.cttz.v2i64(<2 x i64>
+// CHECK: extractelement <2 x i64>
+// CHECK: icmp eq i64 {{.*}}, 64
+// CHECK: extractelement <2 x i64>
+// CHECK: add i64 {{.*}}, 64
+// CHECK: lshr i64 {{.*}}, 3
+ return vec_first_mismatch_index (vsca, vscb);
+}
+unsigned test14(void) {
+// CHECK-BE: @llvm.ppc.altivec.vcmpneb(<16 x i8>
+// CHECK-BE: @llvm.ctlz.v2i64(<2 x i64>
+// CHECK-BE: extractelement <2 x i64>
+// CHECK-BE: icmp eq i64 {{.*}}, 64
+// CHECK-BE: extractelement <2 x i64>
+// CHECK-BE: add i64 {{.*}}, 64
+// CHECK-BE: lshr i64 {{.*}}, 3
+// CHECK: @llvm.ppc.altivec.vcmpneb(<16 x i8>
+// CHECK: @llvm.cttz.v2i64(<2 x i64>
+// CHECK: extractelement <2 x i64>
+// CHECK: icmp eq i64 {{.*}}, 64
+// CHECK: extractelement <2 x i64>
+// CHECK: add i64 {{.*}}, 64
+// CHECK: lshr i64 {{.*}}, 3
+ return vec_first_mismatch_index (vuca, vucb);
+}
+unsigned test15(void) {
+// CHECK-BE: @llvm.ppc.altivec.vcmpnew(<4 x i32>
+// CHECK-BE: @llvm.ctlz.v2i64(<2 x i64>
+// CHECK-BE: extractelement <2 x i64>
+// CHECK-BE: icmp eq i64 {{.*}}, 64
+// CHECK-BE: extractelement <2 x i64>
+// CHECK-BE: add i64 {{.*}}, 64
+// CHECK-BE: lshr i64 {{.*}}, 5
+// CHECK: @llvm.ppc.altivec.vcmpnew(<4 x i32>
+// CHECK: @llvm.cttz.v2i64(<2 x i64>
+// CHECK: extractelement <2 x i64>
+// CHECK: icmp eq i64 {{.*}}, 64
+// CHECK: extractelement <2 x i64>
+// CHECK: add i64 {{.*}}, 64
+// CHECK: lshr i64 {{.*}}, 5
+ return vec_first_mismatch_index (vsia, vsib);
+}
+unsigned test16(void) {
+// CHECK-BE: @llvm.ppc.altivec.vcmpnew(<4 x i32>
+// CHECK-BE: @llvm.ctlz.v2i64(<2 x i64>
+// CHECK-BE: extractelement <2 x i64>
+// CHECK-BE: icmp eq i64 {{.*}}, 64
+// CHECK-BE: extractelement <2 x i64>
+// CHECK-BE: add i64 {{.*}}, 64
+// CHECK-BE: lshr i64 {{.*}}, 5
+// CHECK: @llvm.ppc.altivec.vcmpnew(<4 x i32>
+// CHECK: @llvm.cttz.v2i64(<2 x i64>
+// CHECK: extractelement <2 x i64>
+// CHECK: icmp eq i64 {{.*}}, 64
+// CHECK: extractelement <2 x i64>
+// CHECK: add i64 {{.*}}, 64
+// CHECK: lshr i64 {{.*}}, 5
+ return vec_first_mismatch_index (vuia, vuib);
+}
+unsigned test17(void) {
+// CHECK-BE: @llvm.ppc.altivec.vcmpneh(<8 x i16>
+// CHECK-BE: @llvm.ctlz.v2i64(<2 x i64>
+// CHECK-BE: extractelement <2 x i64>
+// CHECK-BE: icmp eq i64 {{.*}}, 64
+// CHECK-BE: extractelement <2 x i64>
+// CHECK-BE: add i64 {{.*}}, 64
+// CHECK-BE: lshr i64 {{.*}}, 4
+// CHECK: @llvm.ppc.altivec.vcmpneh(<8 x i16>
+// CHECK: @llvm.cttz.v2i64(<2 x i64>
+// CHECK: extractelement <2 x i64>
+// CHECK: icmp eq i64 {{.*}}, 64
+// CHECK: extractelement <2 x i64>
+// CHECK: add i64 {{.*}}, 64
+// CHECK: lshr i64 {{.*}}, 4
+ return vec_first_mismatch_index (vssa, vssb);
+}
+unsigned test18(void) {
+// CHECK-BE: @llvm.ppc.altivec.vcmpneh(<8 x i16>
+// CHECK-BE: @llvm.ctlz.v2i64(<2 x i64>
+// CHECK-BE: extractelement <2 x i64>
+// CHECK-BE: icmp eq i64 {{.*}}, 64
+// CHECK-BE: extractelement <2 x i64>
+// CHECK-BE: add i64 {{.*}}, 64
+// CHECK-BE: lshr i64 {{.*}}, 4
+// CHECK: @llvm.ppc.altivec.vcmpneh(<8 x i16>
+// CHECK: @llvm.cttz.v2i64(<2 x i64>
+// CHECK: extractelement <2 x i64>
+// CHECK: icmp eq i64 {{.*}}, 64
+// CHECK: extractelement <2 x i64>
+// CHECK: add i64 {{.*}}, 64
+// CHECK: lshr i64 {{.*}}, 4
+ return vec_first_mismatch_index (vusa, vusb);
+}
+unsigned test19(void) {
+// CHECK-BE: @llvm.ppc.altivec.vcmpnezb(<16 x i8>
+// CHECK-BE: @llvm.ctlz.v2i64(<2 x i64>
+// CHECK-BE: extractelement <2 x i64>
+// CHECK-BE: icmp eq i64 {{.*}}, 64
+// CHECK-BE: extractelement <2 x i64>
+// CHECK-BE: add i64 {{.*}}, 64
+// CHECK-BE: lshr i64 {{.*}}, 3
+// CHECK: @llvm.ppc.altivec.vcmpnezb(<16 x i8>
+// CHECK: @llvm.cttz.v2i64(<2 x i64>
+// CHECK: extractelement <2 x i64>
+// CHECK: icmp eq i64 {{.*}}, 64
+// CHECK: extractelement <2 x i64>
+// CHECK: add i64 {{.*}}, 64
+// CHECK: lshr i64 {{.*}}, 3
+ return vec_first_mismatch_or_eos_index (vsca, vscb);
+}
+unsigned test20(void) {
+// CHECK-BE: @llvm.ppc.altivec.vcmpnezb(<16 x i8>
+// CHECK-BE: @llvm.ctlz.v2i64(<2 x i64>
+// CHECK-BE: extractelement <2 x i64>
+// CHECK-BE: icmp eq i64 {{.*}}, 64
+// CHECK-BE: extractelement <2 x i64>
+// CHECK-BE: add i64 {{.*}}, 64
+// CHECK-BE: lshr i64 {{.*}}, 3
+// CHECK: @llvm.ppc.altivec.vcmpnezb(<16 x i8>
+// CHECK: @llvm.cttz.v2i64(<2 x i64>
+// CHECK: extractelement <2 x i64>
+// CHECK: icmp eq i64 {{.*}}, 64
+// CHECK: extractelement <2 x i64>
+// CHECK: add i64 {{.*}}, 64
+// CHECK: lshr i64 {{.*}}, 3
+ return vec_first_mismatch_or_eos_index (vuca, vucb);
+}
+unsigned test21(void) {
+// CHECK-BE: @llvm.ppc.altivec.vcmpnezw(<4 x i32>
+// CHECK-BE: @llvm.ctlz.v2i64(<2 x i64>
+// CHECK-BE: extractelement <2 x i64>
+// CHECK-BE: icmp eq i64 {{.*}}, 64
+// CHECK-BE: extractelement <2 x i64>
+// CHECK-BE: add i64 {{.*}}, 64
+// CHECK-BE: lshr i64 {{.*}}, 5
+// CHECK: @llvm.ppc.altivec.vcmpnezw(<4 x i32>
+// CHECK: @llvm.cttz.v2i64(<2 x i64>
+// CHECK: extractelement <2 x i64>
+// CHECK: icmp eq i64 {{.*}}, 64
+// CHECK: extractelement <2 x i64>
+// CHECK: add i64 {{.*}}, 64
+// CHECK: lshr i64 {{.*}}, 5
+ return vec_first_mismatch_or_eos_index (vsia, vsib);
+}
+unsigned test22(void) {
+// CHECK-BE: @llvm.ppc.altivec.vcmpnezw(<4 x i32>
+// CHECK-BE: @llvm.ctlz.v2i64(<2 x i64>
+// CHECK-BE: extractelement <2 x i64>
+// CHECK-BE: icmp eq i64 {{.*}}, 64
+// CHECK-BE: extractelement <2 x i64>
+// CHECK-BE: add i64 {{.*}}, 64
+// CHECK-BE: lshr i64 {{.*}}, 5
+// CHECK: @llvm.ppc.altivec.vcmpnezw(<4 x i32>
+// CHECK: @llvm.cttz.v2i64(<2 x i64>
+// CHECK: extractelement <2 x i64>
+// CHECK: icmp eq i64 {{.*}}, 64
+// CHECK: extractelement <2 x i64>
+// CHECK: add i64 {{.*}}, 64
+// CHECK: lshr i64 {{.*}}, 5
+ return vec_first_mismatch_or_eos_index (vuia, vuib);
+}
+unsigned test23(void) {
+// CHECK-BE: @llvm.ppc.altivec.vcmpnezh(<8 x i16>
+// CHECK-BE: @llvm.ctlz.v2i64(<2 x i64>
+// CHECK-BE: extractelement <2 x i64>
+// CHECK-BE: icmp eq i64 {{.*}}, 64
+// CHECK-BE: extractelement <2 x i64>
+// CHECK-BE: add i64 {{.*}}, 64
+// CHECK-BE: lshr i64 {{.*}}, 4
+// CHECK: @llvm.ppc.altivec.vcmpnezh(<8 x i16>
+// CHECK: @llvm.cttz.v2i64(<2 x i64>
+// CHECK: extractelement <2 x i64>
+// CHECK: icmp eq i64 {{.*}}, 64
+// CHECK: extractelement <2 x i64>
+// CHECK: add i64 {{.*}}, 64
+// CHECK: lshr i64 {{.*}}, 4
+ return vec_first_mismatch_or_eos_index (vssa, vssb);
+}
+unsigned test24(void) {
+// CHECK-BE: @llvm.ppc.altivec.vcmpnezh(<8 x i16>
+// CHECK-BE: @llvm.ctlz.v2i64(<2 x i64>
+// CHECK-BE: extractelement <2 x i64>
+// CHECK-BE: icmp eq i64 {{.*}}, 64
+// CHECK-BE: extractelement <2 x i64>
+// CHECK-BE: add i64 {{.*}}, 64
+// CHECK-BE: lshr i64 {{.*}}, 4
+// CHECK: @llvm.ppc.altivec.vcmpnezh(<8 x i16>
+// CHECK: @llvm.cttz.v2i64(<2 x i64>
+// CHECK: extractelement <2 x i64>
+// CHECK: icmp eq i64 {{.*}}, 64
+// CHECK: extractelement <2 x i64>
+// CHECK: add i64 {{.*}}, 64
+// CHECK: lshr i64 {{.*}}, 4
+ return vec_first_mismatch_or_eos_index (vusa, vusb);
+}
+vector bool char test25(void) {
+// CHECK-BE: @llvm.ppc.altivec.vcmpneb(<16 x i8>
+// CHECK-BE-NEXT: ret <16 x i8>
+// CHECK: @llvm.ppc.altivec.vcmpneb(<16 x i8>
+// CHECK-NEXT: ret <16 x i8>
+ return vec_cmpne (vbca, vbcb);
+}
+vector bool char test26(void) {
+// CHECK-BE: @llvm.ppc.altivec.vcmpneb(<16 x i8>
+// CHECK-BE-NEXT: ret <16 x i8>
+// CHECK: @llvm.ppc.altivec.vcmpneb(<16 x i8>
+// CHECK-NEXT: ret <16 x i8>
+ return vec_cmpne (vsca, vscb);
+}
+vector bool char test27(void) {
+// CHECK-BE: @llvm.ppc.altivec.vcmpneb(<16 x i8>
+// CHECK-BE-NEXT: ret <16 x i8>
+// CHECK: @llvm.ppc.altivec.vcmpneb(<16 x i8>
+// CHECK-NEXT: ret <16 x i8>
+ return vec_cmpne (vuca, vucb);
+}
+vector bool int test28(void) {
+// CHECK-BE: @llvm.ppc.altivec.vcmpnew(<4 x i32>
+// CHECK-BE-NEXT: ret <4 x i32>
+// CHECK: @llvm.ppc.altivec.vcmpnew(<4 x i32>
+// CHECK-NEXT: ret <4 x i32>
+ return vec_cmpne (vbia, vbib);
+}
+vector bool int test29(void) {
+// CHECK-BE: @llvm.ppc.altivec.vcmpnew(<4 x i32>
+// CHECK-BE-NEXT: ret <4 x i32>
+// CHECK: @llvm.ppc.altivec.vcmpnew(<4 x i32>
+// CHECK-NEXT: ret <4 x i32>
+ return vec_cmpne (vsia, vsib);
+}
+vector bool int test30(void) {
+// CHECK-BE: @llvm.ppc.altivec.vcmpnew(<4 x i32>
+// CHECK-BE-NEXT: ret <4 x i32>
+// CHECK: @llvm.ppc.altivec.vcmpnew(<4 x i32>
+// CHECK-NEXT: ret <4 x i32>
+ return vec_cmpne (vuia, vuib);
+}
+vector bool long long test31(void) {
+// CHECK-BE: @llvm.ppc.altivec.vcmpequd(<2 x i64>
+// CHECK-BE: xor <2 x i64>
+// CHECK-BE-NEXT: ret <2 x i64>
+// CHECK: @llvm.ppc.altivec.vcmpequd(<2 x i64>
+// CHECK: xor <2 x i64>
+// CHECK-NEXT: ret <2 x i64>
+ return vec_cmpne (vbla, vblb);
+}
+vector bool long long test32(void) {
+// CHECK-BE: @llvm.ppc.altivec.vcmpequd(<2 x i64>
+// CHECK-BE: xor <2 x i64>
+// CHECK-BE-NEXT: ret <2 x i64>
+// CHECK: @llvm.ppc.altivec.vcmpequd(<2 x i64>
+// CHECK: xor <2 x i64>
+// CHECK-NEXT: ret <2 x i64>
+ return vec_cmpne (vsla, vslb);
+}
+vector bool long long test33(void) {
+// CHECK-BE: @llvm.ppc.altivec.vcmpequd(<2 x i64>
+// CHECK-BE: xor <2 x i64>
+// CHECK-BE-NEXT: ret <2 x i64>
+// CHECK: @llvm.ppc.altivec.vcmpequd(<2 x i64>
+// CHECK: xor <2 x i64>
+// CHECK-NEXT: ret <2 x i64>
+ return vec_cmpne (vula, vulb);
+}
+vector bool short test34(void) {
+// CHECK-BE: @llvm.ppc.altivec.vcmpneh(<8 x i16>
+// CHECK-BE-NEXT: ret <8 x i16>
+// CHECK: @llvm.ppc.altivec.vcmpneh(<8 x i16>
+// CHECK-NEXT: ret <8 x i16>
+ return vec_cmpne (vbsa, vbsb);
+}
+vector bool short test35(void) {
+// CHECK-BE: @llvm.ppc.altivec.vcmpneh(<8 x i16>
+// CHECK-BE-NEXT: ret <8 x i16>
+// CHECK: @llvm.ppc.altivec.vcmpneh(<8 x i16>
+// CHECK-NEXT: ret <8 x i16>
+ return vec_cmpne (vssa, vssb);
+}
+vector bool short test36(void) {
+// CHECK-BE: @llvm.ppc.altivec.vcmpneh(<8 x i16>
+// CHECK-BE-NEXT: ret <8 x i16>
+// CHECK: @llvm.ppc.altivec.vcmpneh(<8 x i16>
+// CHECK-NEXT: ret <8 x i16>
+ return vec_cmpne (vusa, vusb);
+}
+vector bool long long test37(void) {
+// CHECK-BE: @llvm.ppc.altivec.vcmpequd(<2 x i64>
+// CHECK-BE: xor <2 x i64>
+// CHECK-BE-NEXT: ret <2 x i64>
+// CHECK: @llvm.ppc.altivec.vcmpequd(<2 x i64>
+// CHECK: xor <2 x i64>
+// CHECK-NEXT: ret <2 x i64>
+ return vec_cmpne (vda, vdb);
+}
+vector bool int test38(void) {
+// CHECK-BE: @llvm.ppc.altivec.vcmpnew(<4 x i32>
+// CHECK-BE-NEXT: ret <4 x i32>
+// CHECK: @llvm.ppc.altivec.vcmpnew(<4 x i32>
+// CHECK-NEXT: ret <4 x i32>
+ return vec_cmpne (vfa, vfb);
+}
+vector signed char test39(void) {
+// CHECK-BE: @llvm.cttz.v16i8(<16 x i8>
+// CHECK-BE-NEXT: ret <16 x i8>
+// CHECK: @llvm.cttz.v16i8(<16 x i8>
+// CHECK-NEXT: ret <16 x i8>
+ return vec_cnttz (vsca);
+}
+vector unsigned char test40(void) {
+// CHECK-BE: @llvm.cttz.v16i8(<16 x i8>
+// CHECK-BE-NEXT: ret <16 x i8>
+// CHECK: @llvm.cttz.v16i8(<16 x i8>
+// CHECK-NEXT: ret <16 x i8>
+ return vec_cnttz (vuca);
+}
+vector signed int test41(void) {
+// CHECK-BE: @llvm.cttz.v4i32(<4 x i32>
+// CHECK-BE-NEXT: ret <4 x i32>
+// CHECK: @llvm.cttz.v4i32(<4 x i32>
+// CHECK-NEXT: ret <4 x i32>
+ return vec_cnttz (vsia);
+}
+vector unsigned int test42(void) {
+// CHECK-BE: @llvm.cttz.v4i32(<4 x i32>
+// CHECK-BE-NEXT: ret <4 x i32>
+// CHECK: @llvm.cttz.v4i32(<4 x i32>
+// CHECK-NEXT: ret <4 x i32>
+ return vec_cnttz (vuia);
+}
+vector signed long long test43(void) {
+// CHECK-BE: @llvm.cttz.v2i64(<2 x i64>
+// CHECK-BE-NEXT: ret <2 x i64>
+// CHECK: @llvm.cttz.v2i64(<2 x i64>
+// CHECK-NEXT: ret <2 x i64>
+ return vec_cnttz (vsla);
+}
+vector unsigned long long test44(void) {
+// CHECK-BE: @llvm.cttz.v2i64(<2 x i64>
+// CHECK-BE-NEXT: ret <2 x i64>
+// CHECK: @llvm.cttz.v2i64(<2 x i64>
+// CHECK-NEXT: ret <2 x i64>
+ return vec_cnttz (vula);
+}
+vector signed short test45(void) {
+// CHECK-BE: @llvm.cttz.v8i16(<8 x i16>
+// CHECK-BE-NEXT: ret <8 x i16>
+// CHECK: @llvm.cttz.v8i16(<8 x i16>
+// CHECK-NEXT: ret <8 x i16>
+ return vec_cnttz (vssa);
+}
+vector unsigned short test46(void) {
+// CHECK-BE: @llvm.cttz.v8i16(<8 x i16>
+// CHECK-BE-NEXT: ret <8 x i16>
+// CHECK: @llvm.cttz.v8i16(<8 x i16>
+// CHECK-NEXT: ret <8 x i16>
+ return vec_cnttz (vusa);
+}
+vector unsigned char test47(void) {
+// CHECK-BE: @llvm.ctpop.v16i8(<16 x i8>
+// CHECK-BE-NEXT: ret <16 x i8>
+// CHECK: @llvm.ctpop.v16i8(<16 x i8>
+// CHECK-NEXT: ret <16 x i8>
+ return vec_popcnt (vsca);
+}
+vector unsigned char test48(void) {
+// CHECK-BE: @llvm.ctpop.v16i8(<16 x i8>
+// CHECK-BE-NEXT: ret <16 x i8>
+// CHECK: @llvm.ctpop.v16i8(<16 x i8>
+// CHECK-NEXT: ret <16 x i8>
+ return vec_popcnt (vuca);
+}
+vector unsigned int test49(void) {
+// CHECK-BE: @llvm.ctpop.v4i32(<4 x i32>
+// CHECK-BE-NEXT: ret <4 x i32>
+// CHECK: @llvm.ctpop.v4i32(<4 x i32>
+// CHECK-NEXT: ret <4 x i32>
+ return vec_popcnt (vsia);
+}
+vector unsigned int test50(void) {
+// CHECK-BE: @llvm.ctpop.v4i32(<4 x i32>
+// CHECK-BE-NEXT: ret <4 x i32>
+// CHECK: @llvm.ctpop.v4i32(<4 x i32>
+// CHECK-NEXT: ret <4 x i32>
+ return vec_popcnt (vuia);
+}
+vector unsigned long long test51(void) {
+// CHECK-BE: @llvm.ctpop.v2i64(<2 x i64>
+// CHECK-BE-NEXT: ret <2 x i64>
+// CHECK: @llvm.ctpop.v2i64(<2 x i64>
+// CHECK-NEXT: ret <2 x i64>
+ return vec_popcnt (vsla);
+}
+vector unsigned long long test52(void) {
+// CHECK-BE: @llvm.ctpop.v2i64(<2 x i64>
+// CHECK-BE-NEXT: ret <2 x i64>
+// CHECK: @llvm.ctpop.v2i64(<2 x i64>
+// CHECK-NEXT: ret <2 x i64>
+ return vec_popcnt (vula);
+}
+vector unsigned short test53(void) {
+// CHECK-BE: @llvm.ctpop.v8i16(<8 x i16>
+// CHECK-BE-NEXT: ret <8 x i16>
+// CHECK: @llvm.ctpop.v8i16(<8 x i16>
+// CHECK-NEXT: ret <8 x i16>
+ return vec_popcnt (vssa);
+}
+vector unsigned short test54(void) {
+// CHECK-BE: @llvm.ctpop.v8i16(<8 x i16>
+// CHECK-BE-NEXT: ret <8 x i16>
+// CHECK: @llvm.ctpop.v8i16(<8 x i16>
+// CHECK-NEXT: ret <8 x i16>
+ return vec_popcnt (vusa);
+}
+vector double test55(void) {
+// CHECK-BE: @llvm.ppc.vsx.xviexpdp(<2 x i64> %{{.+}}, <2 x i64>
+// CHECK-BE-NEXT: ret <2 x double>
+// CHECK: @llvm.ppc.vsx.xviexpdp(<2 x i64> %{{.+}}, <2 x i64>
+// CHECK-NEXT: ret <2 x double>
+ return vec_insert_exp (vda,vulb);
+}
+vector double test56(void) {
+// CHECK-BE: @llvm.ppc.vsx.xviexpdp(<2 x i64> %{{.+}}, <2 x i64>
+// CHECK-BE-NEXT: ret <2 x double>
+// CHECK: @llvm.ppc.vsx.xviexpdp(<2 x i64> %{{.+}}, <2 x i64>
+// CHECK-NEXT: ret <2 x double>
+ return vec_insert_exp (vula, vulb);
+}
+vector float test57(void) {
+// CHECK-BE: @llvm.ppc.vsx.xviexpsp(<4 x i32> %{{.+}}, <4 x i32>
+// CHECK-BE-NEXT: ret <4 x float>
+// CHECK: @llvm.ppc.vsx.xviexpsp(<4 x i32> %{{.+}}, <4 x i32>
+// CHECK-NEXT: ret <4 x float>
+ return vec_insert_exp (vfa,vuib);
+}
+vector float test58(void) {
+// CHECK-BE: @llvm.ppc.vsx.xviexpsp(<4 x i32> %{{.+}}, <4 x i32>
+// CHECK-BE-NEXT: ret <4 x float>
+// CHECK: @llvm.ppc.vsx.xviexpsp(<4 x i32> %{{.+}}, <4 x i32>
+// CHECK-NEXT: ret <4 x float>
+ return vec_insert_exp (vuia,vuib);
+}
+signed int test59(void) {
+// CHECK-BE: @llvm.ppc.altivec.vclzlsbb(<16 x i8>
+// CHECK-BE-NEXT: ret i32
+// CHECK-LE: @llvm.ppc.altivec.vctzlsbb(<16 x i8>
+// CHECK-LE-NEXT: ret i32
+ return vec_cntlz_lsbb (vuca);
+}
+signed int test60(void) {
+// CHECK-BE: @llvm.ppc.altivec.vclzlsbb(<16 x i8>
+// CHECK-BE-NEXT: ret i32
+// CHECK-LE: @llvm.ppc.altivec.vctzlsbb(<16 x i8>
+// CHECK-LE-NEXT: ret i32
+ return vec_cntlz_lsbb (vsca);
+}
+signed int test61(void) {
+// CHECK-BE: @llvm.ppc.altivec.vctzlsbb(<16 x i8>
+// CHECK-BE-NEXT: ret i32
+// CHECK-LE: @llvm.ppc.altivec.vclzlsbb(<16 x i8>
+// CHECK-LE-NEXT: ret i32
+ return vec_cnttz_lsbb (vsca);
+}
+signed int test62(void) {
+// CHECK-BE: @llvm.ppc.altivec.vctzlsbb(<16 x i8>
+// CHECK-BE-NEXT: ret i32
+// CHECK-LE: @llvm.ppc.altivec.vclzlsbb(<16 x i8>
+// CHECK-LE-NEXT: ret i32
+ return vec_cnttz_lsbb (vuca);
+}
+vector unsigned int test63(void) {
+// CHECK-BE: @llvm.ppc.altivec.vprtybw(<4 x i32>
+// CHECK-BE-NEXT: ret <4 x i32>
+// CHECK: @llvm.ppc.altivec.vprtybw(<4 x i32>
+// CHECK-NEXT: ret <4 x i32>
+ return vec_parity_lsbb (vuia);
+}
+vector unsigned int test64(void) {
+// CHECK-BE: @llvm.ppc.altivec.vprtybw(<4 x i32>
+// CHECK-BE-NEXT: ret <4 x i32>
+// CHECK: @llvm.ppc.altivec.vprtybw(<4 x i32>
+// CHECK-NEXT: ret <4 x i32>
+ return vec_parity_lsbb (vsia);
+}
+vector unsigned long long test65(void) {
+// CHECK-BE: @llvm.ppc.altivec.vprtybd(<2 x i64>
+// CHECK-BE-NEXT: ret <2 x i64>
+// CHECK: @llvm.ppc.altivec.vprtybd(<2 x i64>
+// CHECK-NEXT: ret <2 x i64>
+ return vec_parity_lsbb (vula);
+}
+vector unsigned long long test66(void) {
+// CHECK-BE: @llvm.ppc.altivec.vprtybd(<2 x i64>
+// CHECK-BE-NEXT: ret <2 x i64>
+// CHECK: @llvm.ppc.altivec.vprtybd(<2 x i64>
+// CHECK-NEXT: ret <2 x i64>
+ return vec_parity_lsbb (vsla);
+}
+vector unsigned __int128 test67(void) {
+// CHECK-BE: @llvm.ppc.altivec.vprtybq(<1 x i128>
+// CHECK-BE-NEXT: ret <1 x i128>
+// CHECK: @llvm.ppc.altivec.vprtybq(<1 x i128>
+// CHECK-NEXT: ret <1 x i128>
+ return vec_parity_lsbb (vui128a);
+}
+vector unsigned __int128 test68(void) {
+// CHECK-BE: @llvm.ppc.altivec.vprtybq(<1 x i128>
+// CHECK-BE-NEXT: ret <1 x i128>
+// CHECK: @llvm.ppc.altivec.vprtybq(<1 x i128>
+// CHECK-NEXT: ret <1 x i128>
+ return vec_parity_lsbb (vsi128a);
+}
+vector unsigned char test69(void) {
+// CHECK-BE: call <16 x i8> @llvm.ppc.altivec.vabsdub(<16 x i8> {{.+}}, <16 x i8> {{.+}})
+// CHECK: call <16 x i8> @llvm.ppc.altivec.vabsdub(<16 x i8> {{.+}}, <16 x i8> {{.+}})
+ return vec_absd(vuca, vucb);
+}
+vector unsigned short test70(void) {
+// CHECK-BE: call <8 x i16> @llvm.ppc.altivec.vabsduh(<8 x i16> {{.+}}, <8 x i16> {{.+}})
+// CHECK: call <8 x i16> @llvm.ppc.altivec.vabsduh(<8 x i16> {{.+}}, <8 x i16> {{.+}})
+ return vec_absd(vusa, vusb);
+}
+vector unsigned int test71(void) {
+// CHECK-BE: call <4 x i32> @llvm.ppc.altivec.vabsduw(<4 x i32> {{.+}}, <4 x i32> {{.+}})
+// CHECK: call <4 x i32> @llvm.ppc.altivec.vabsduw(<4 x i32> {{.+}}, <4 x i32> {{.+}})
+ return vec_absd(vuia, vuib);
+}
+vector unsigned char test72(void) {
+// CHECK-BE: @llvm.ppc.altivec.vslv(<16 x i8>
+// CHECK-BE-NEXT: ret <16 x i8>
+// CHECK: @llvm.ppc.altivec.vslv(<16 x i8>
+// CHECK-NEXT: ret <16 x i8>
+ return vec_slv (vuca, vucb);
+}
+vector unsigned char test73(void) {
+// CHECK-BE: @llvm.ppc.altivec.vsrv(<16 x i8>
+// CHECK-BE-NEXT: ret <16 x i8>
+// CHECK: @llvm.ppc.altivec.vsrv(<16 x i8>
+// CHECK-NEXT: ret <16 x i8>
+ return vec_srv (vuca, vucb);
+}
+vector unsigned short test74(void) {
+// CHECK-BE: @llvm.ppc.vsx.xvcvsphp(<4 x float>
+// CHECK-BE: @llvm.ppc.vsx.xvcvsphp(<4 x float>
+// CHECK-BE: @llvm.ppc.altivec.vperm
+// CHECK: @llvm.ppc.vsx.xvcvsphp(<4 x float>
+// CHECK: @llvm.ppc.vsx.xvcvsphp(<4 x float>
+// CHECK: @llvm.ppc.altivec.vperm
+ return vec_pack_to_short_fp32(vfa, vfb);
+}
+vector unsigned int test75(void) {
+// CHECK-BE: @llvm.ppc.altivec.vrlwmi(<4 x i32
+// CHECK-BE-NEXT: ret <4 x i32>
+// CHECK: @llvm.ppc.altivec.vrlwmi(<4 x i32
+// CHECK-NEXT: ret <4 x i32>
+ return vec_rlmi(vuia, vuia, vuia);
+}
+vector unsigned long long test76(void) {
+// CHECK-BE: @llvm.ppc.altivec.vrldmi(<2 x i64
+// CHECK-BE-NEXT: ret <2 x i64>
+// CHECK: @llvm.ppc.altivec.vrldmi(<2 x i64
+// CHECK-NEXT: ret <2 x i64>
+ return vec_rlmi(vula, vula, vula);
+}
+vector unsigned int test77(void) {
+// CHECK-BE: @llvm.ppc.altivec.vrlwnm(<4 x i32
+// CHECK-BE: and <4 x i32
+// CHECK-BE: ret <4 x i32>
+// CHECK: @llvm.ppc.altivec.vrlwnm(<4 x i32
+// CHECK: and <4 x i32
+// CHECK: ret <4 x i32>
+ return vec_rlnm(vuia, vuia, vuia);
+}
+vector unsigned long long test78(void) {
+// CHECK-BE: @llvm.ppc.altivec.vrldnm(<2 x i64
+// CHECK-BE: and <2 x i64
+// CHECK-BE-NEXT: ret <2 x i64>
+// CHECK: @llvm.ppc.altivec.vrldnm(<2 x i64
+// CHECK: and <2 x i64
+// CHECK-NEXT: ret <2 x i64>
+ return vec_rlnm(vula, vula, vula);
+}
+vector double test79(void) {
+// CHECK-BE: extractelement <4 x float>
+// CHECK-BE: fpext float
+// CHECK-BE: insertelement <2 x double>
+// CHECK-BE: extractelement <4 x float>
+// CHECK-BE: fpext float
+// CHECK-BE: insertelement <2 x double>
+// CHECK: extractelement <4 x float>
+// CHECK: fpext float
+// CHECK: insertelement <2 x double>
+// CHECK: extractelement <4 x float>
+// CHECK: fpext float
+// CHECK: insertelement <2 x double>
+ return vec_unpackh(vfa);
+}
+vector double test80(void) {
+// CHECK-BE: extractelement <4 x float>
+// CHECK-BE: fpext float
+// CHECK-BE: insertelement <2 x double>
+// CHECK-BE: extractelement <4 x float>
+// CHECK-BE: fpext float
+// CHECK-BE: insertelement <2 x double>
+// CHECK: extractelement <4 x float>
+// CHECK: fpext float
+// CHECK: insertelement <2 x double>
+// CHECK: extractelement <4 x float>
+// CHECK: fpext float
+// CHECK: insertelement <2 x double>
+ return vec_unpackl(vfa);
+}
+vector double test81(void) {
+ // CHECK: extractelement <2 x double>
+ // CHECK: fptrunc double
+ // CHECK: insertelement <4 x float>
+ // CHECK: extractelement <2 x double>
+ // CHECK: fptrunc double
+ // CHECK: insertelement <4 x float>
+ // CHECK: extractelement <2 x double>
+ // CHECK: fptrunc double
+ // CHECK: insertelement <4 x float>
+ // CHECK: extractelement <2 x double>
+ // CHECK: fptrunc double
+ // CHECK: insertelement <4 x float>
+ // CHECK-LE: extractelement <2 x double>
+ // CHECK-LE: fptrunc double
+ // CHECK-LE: insertelement <4 x float>
+ // CHECK-LE: extractelement <2 x double>
+ // CHECK-LE: fptrunc double
+ // CHECK-LE: insertelement <4 x float>
+ // CHECK-LE: extractelement <2 x double>
+ // CHECK-LE: fptrunc double
+ // CHECK-LE: insertelement <4 x float>
+ // CHECK-LE: extractelement <2 x double>
+ // CHECK-LE: fptrunc double
+ // CHECK-LE: insertelement <4 x float>
+ return vec_pack(vda, vdb);
+}
+vector unsigned int test82(void) {
+// CHECK-BE: @llvm.ppc.vsx.xvxexpsp(<4 x float> {{.+}})
+// CHECK-BE-NEXT: ret <4 x i32>
+// CHECK: @llvm.ppc.vsx.xvxexpsp(<4 x float> {{.+}})
+// CHECK-NEXT: ret <4 x i32>
+ return vec_extract_exp(vfa);
+}
+vector unsigned long long test83(void) {
+// CHECK-BE: @llvm.ppc.vsx.xvxexpdp(<2 x double> {{.+}})
+// CHECK-BE-NEXT: ret <2 x i64>
+// CHECK: @llvm.ppc.vsx.xvxexpdp(<2 x double> {{.+}})
+// CHECK-NEXT: ret <2 x i64>
+ return vec_extract_exp(vda);
+}
+vector unsigned int test84(void) {
+// CHECK-BE: @llvm.ppc.vsx.xvxsigsp(<4 x float> {{.+}})
+// CHECK-BE-NEXT: ret <4 x i32>
+// CHECK: @llvm.ppc.vsx.xvxsigsp(<4 x float> {{.+}})
+// CHECK-NEXT: ret <4 x i32>
+ return vec_extract_sig(vfa);
+}
+vector unsigned long long test85(void) {
+// CHECK-BE: @llvm.ppc.vsx.xvxsigdp(<2 x double> {{.+}})
+// CHECK-BE-NEXT: ret <2 x i64>
+// CHECK: @llvm.ppc.vsx.xvxsigdp(<2 x double> {{.+}})
+// CHECK-NEXT: ret <2 x i64>
+ return vec_extract_sig(vda);
+}
+vector bool int test86(void) {
+// CHECK-BE: @llvm.ppc.vsx.xvtstdcsp(<4 x float> {{.+}}, i32 127)
+// CHECK-BE-NEXT: ret <4 x i32>
+// CHECK: @llvm.ppc.vsx.xvtstdcsp(<4 x float> {{.+}}, i32 127)
+// CHECK-NEXT: ret <4 x i32>
+ return vec_test_data_class(vfa, __VEC_CLASS_FP_NOT_NORMAL);
+}
+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: @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);
+}
+vector unsigned char test88(void) {
+// CHECK-BE: @llvm.ppc.vsx.lxvl(i8* %{{.+}}, i64
+// CHECK-BE-NEXT-NEXT: ret <16 x i8>
+// CHECK: @llvm.ppc.vsx.lxvl(i8* %{{.+}}, i64
+// CHECK-NEXT-NEXT: ret <16 x i8>
+ return vec_xl_len(uc,0);
+}
+vector signed char test89(void) {
+// CHECK-BE: @llvm.ppc.vsx.lxvl(i8* %{{.+}}, i64
+// CHECK-BE-NEXT-NEXT: ret <16 x i8>
+// CHECK: @llvm.ppc.vsx.lxvl(i8* %{{.+}}, i64
+// CHECK-NEXT-NEXT: ret <16 x i8>
+ return vec_xl_len(sc,0);
+}
+vector unsigned short test90(void) {
+// CHECK-BE: @llvm.ppc.vsx.lxvl(i8* %{{.+}}, i64
+// CHECK-BE-NEXT-NEXT: ret <8 x i16>
+// CHECK: @llvm.ppc.vsx.lxvl(i8* %{{.+}}, i64
+// CHECK-NEXT-NEXT: ret <8 x i16>
+ return vec_xl_len(us,0);
+}
+vector signed short test91(void) {
+// CHECK-BE: @llvm.ppc.vsx.lxvl(i8* %{{.+}}, i64
+// CHECK-BE-NEXT-NEXT: ret <8 x i16>
+// CHECK: @llvm.ppc.vsx.lxvl(i8* %{{.+}}, i64
+// CHECK-NEXT-NEXT: ret <8 x i16>
+ return vec_xl_len(ss,0);
+}
+vector unsigned int test92(void) {
+// CHECK-BE: @llvm.ppc.vsx.lxvl(i8* %{{.+}}, i64
+// CHECK-BE-NEXT: ret <4 x i32>
+// CHECK: @llvm.ppc.vsx.lxvl(i8* %{{.+}}, i64
+// CHECK-NEXT: ret <4 x i32>
+ return vec_xl_len(ui,0);
+}
+
+vector signed int test93(void) {
+// CHECK-BE: @llvm.ppc.vsx.lxvl(i8* %{{.+}}, i64
+// CHECK-BE-NEXT: ret <4 x i32>
+// CHECK: @llvm.ppc.vsx.lxvl(i8* %{{.+}}, i64
+// CHECK-NEXT: ret <4 x i32>
+ return vec_xl_len(si,0);
+}
+
+vector float test94(void) {
+// CHECK-BE: @llvm.ppc.vsx.lxvl(i8* %{{.+}}, i64
+// CHECK-BE-NEXT-NEXT: ret <4 x i32>
+// CHECK: @llvm.ppc.vsx.lxvl(i8* %{{.+}}, i64
+// CHECK-NEXT-NEXT: ret <4 x i32>
+ return vec_xl_len(f,0);
+}
+
+vector unsigned long long test95(void) {
+// CHECK-BE: @llvm.ppc.vsx.lxvl(i8* %{{.+}}, i64
+// CHECK-BE-NEXT-NEXT: ret <2 x i64>
+// CHECK: @llvm.ppc.vsx.lxvl(i8* %{{.+}}, i64
+// CHECK-NEXT-NEXT: ret <2 x i64>
+ return vec_xl_len(ull,0);
+}
+
+vector signed long long test96(void) {
+// CHECK-BE: @llvm.ppc.vsx.lxvl(i8* %{{.+}}, i64
+// CHECK-BE-NEXT-NEXT: ret <2 x i64>
+// CHECK: @llvm.ppc.vsx.lxvl(i8* %{{.+}}, i64
+// CHECK-NEXT-NEXT: ret <2 x i64>
+ return vec_xl_len(sll,0);
+}
+
+vector double test97(void) {
+// CHECK-BE: @llvm.ppc.vsx.lxvl(i8* %{{.+}}, i64
+// CHECK-BE-NEXT-NEXT: ret <2 x i64>
+// CHECK: @llvm.ppc.vsx.lxvl(i8* %{{.+}}, i64
+// CHECK-NEXT-NEXT: ret <2 x i64>
+ return vec_xl_len(d,0);
+}
+
+vector unsigned __int128 test98(void) {
+// CHECK-BE: @llvm.ppc.vsx.lxvl(i8* %{{.+}}, i64
+// CHECK-BE-NEXT-NEXT: ret <1 x i128>
+// CHECK: @llvm.ppc.vsx.lxvl(i8* %{{.+}}, i64
+// CHECK-NEXT-NEXT: ret <1 x i128>
+ return vec_xl_len(uint128,0);
+}
+
+vector signed __int128 test99(void) {
+// CHECK-BE: @llvm.ppc.vsx.lxvl(i8* %{{.+}}, i64
+// CHECK-BE-NEXT-NEXT: ret <1 x i128>
+// CHECK: @llvm.ppc.vsx.lxvl(i8* %{{.+}}, i64
+// CHECK-NEXT-NEXT: ret <1 x i128>
+ return vec_xl_len(sint128,0);
+}
+
+void test100(void) {
+// CHECK-BE: @llvm.ppc.vsx.stxvl(<4 x i32> %{{.+}}, i8* %{{.+}}, i64
+// CHECK: @llvm.ppc.vsx.stxvl(<4 x i32> %{{.+}}, i8* %{{.+}}, i64
+ return vec_xst_len(vuca,uc,0);
+}
+
+void test101(void) {
+// CHECK-BE: @llvm.ppc.vsx.stxvl(<4 x i32> %{{.+}}, i8* %{{.+}}, i64
+// CHECK: @llvm.ppc.vsx.stxvl(<4 x i32> %{{.+}}, i8* %{{.+}}, i64
+ return vec_xst_len(vsca,sc,0);
+}
+
+void test102(void) {
+// CHECK-BE: @llvm.ppc.vsx.stxvl(<4 x i32> %{{.+}}, i8* %{{.+}}, i64
+// CHECK: @llvm.ppc.vsx.stxvl(<4 x i32> %{{.+}}, i8* %{{.+}}, i64
+ return vec_xst_len(vusa,us,0);
+}
+
+void test103(void) {
+// CHECK-BE: @llvm.ppc.vsx.stxvl(<4 x i32> %{{.+}}, i8* %{{.+}}, i64
+// CHECK: @llvm.ppc.vsx.stxvl(<4 x i32> %{{.+}}, i8* %{{.+}}, i64
+ return vec_xst_len(vssa,ss,0);
+}
+
+void test104(void) {
+// CHECK-BE: @llvm.ppc.vsx.stxvl(<4 x i32> %{{.+}}, i8* %{{.+}}, i64
+// CHECK: @llvm.ppc.vsx.stxvl(<4 x i32> %{{.+}}, i8* %{{.+}}, i64
+ return vec_xst_len(vuia,ui,0);
+}
+
+void test105(void) {
+// CHECK-BE: @llvm.ppc.vsx.stxvl(<4 x i32> %{{.+}}, i8* %{{.+}}, i64
+// CHECK: @llvm.ppc.vsx.stxvl(<4 x i32> %{{.+}}, i8* %{{.+}}, i64
+ return vec_xst_len(vsia,si,0);
+}
+
+void test106(void) {
+// CHECK-BE: @llvm.ppc.vsx.stxvl(<4 x i32> %{{.+}}, i8* %{{.+}}, i64
+// CHECK: @llvm.ppc.vsx.stxvl(<4 x i32> %{{.+}}, i8* %{{.+}}, i64
+ return vec_xst_len(vfa,f,0);
+}
+
+void test107(void) {
+// CHECK-BE: @llvm.ppc.vsx.stxvl(<4 x i32> %{{.+}}, i8* %{{.+}}, i64
+// CHECK: @llvm.ppc.vsx.stxvl(<4 x i32> %{{.+}}, i8* %{{.+}}, i64
+ return vec_xst_len(vula,ull,0);
+}
+
+void test108(void) {
+// CHECK-BE: @llvm.ppc.vsx.stxvl(<4 x i32> %{{.+}}, i8* %{{.+}}, i64
+// CHECK: @llvm.ppc.vsx.stxvl(<4 x i32> %{{.+}}, i8* %{{.+}}, i64
+ return vec_xst_len(vsla,sll,0);
+}
+
+void test109(void) {
+// CHECK-BE: @llvm.ppc.vsx.stxvl(<4 x i32> %{{.+}}, i8* %{{.+}}, i64
+// CHECK: @llvm.ppc.vsx.stxvl(<4 x i32> %{{.+}}, i8* %{{.+}}, i64
+ return vec_xst_len(vda,d,0);
+}
+
+void test110(void) {
+// CHECK-BE: @llvm.ppc.vsx.stxvl(<4 x i32> %{{.+}}, i8* %{{.+}}, i64
+// CHECK: @llvm.ppc.vsx.stxvl(<4 x i32> %{{.+}}, i8* %{{.+}}, i64
+ return vec_xst_len(vui128a,uint128,0);
+}
+
+void test111(void) {
+// CHECK-BE: @llvm.ppc.vsx.stxvl(<4 x i32> %{{.+}}, i8* %{{.+}}, i64
+// CHECK: @llvm.ppc.vsx.stxvl(<4 x i32> %{{.+}}, i8* %{{.+}}, i64
+ return vec_xst_len(vsi128a,sint128,0);
+}
+
+vector unsigned char test112(void) {
+// CHECK-BE: @llvm.ppc.vsx.lxvll(i8* %{{.+}}, i64
+// CHECK: @llvm.ppc.vsx.lxvll(i8* %{{.+}}, i64
+// CHECK: @llvm.ppc.altivec.lvsr(i8* %{{.+}}
+// CHECK: @llvm.ppc.altivec.vperm
+ return vec_xl_len_r(uc,0);
+}
+void test113(void) {
+// CHECK-BE: @llvm.ppc.vsx.stxvll(<4 x i32> %{{.+}}, i8* %{{.+}}, i64
+// CHECK: @llvm.ppc.altivec.lvsl(i8* %{{.+}}
+// CHECK: @llvm.ppc.altivec.vperm
+// CHECK: @llvm.ppc.vsx.stxvll(<4 x i32> %{{.+}}, i8* %{{.+}}, i64
+ return vec_xst_len_r(vuca,uc,0);
+}
+vector float test114(void) {
+// CHECK-BE: shufflevector <8 x i16> {{.+}}, <8 x i16> {{.+}}, <8 x i32> <i32 undef, i32 0, i32 undef, i32 1, i32 undef, i32 2, i32 undef, i32 3>
+// CHECK-BE: @llvm.ppc.vsx.xvcvhpsp(<8 x i16> {{.+}})
+// CHECK-BE-NEXT: ret <4 x float>
+// CHECK-LE: shufflevector <8 x i16> {{.+}}, <8 x i16> {{.+}}, <8 x i32> <i32 0, i32 undef, i32 1, i32 undef, i32 2, i32 undef, i32 3, i32 undef>
+// CHECK-LE: @llvm.ppc.vsx.xvcvhpsp(<8 x i16> {{.+}})
+// CHECK-LE-NEXT: ret <4 x float>
+ return vec_extract_fp32_from_shorth(vusa);
+}
+vector float test115(void) {
+// CHECK-BE: shufflevector <8 x i16> {{.+}}, <8 x i16> {{.+}}, <8 x i32> <i32 undef, i32 4, i32 undef, i32 5, i32 undef, i32 6, i32 undef, i32 7>
+// CHECK-BE: @llvm.ppc.vsx.xvcvhpsp(<8 x i16> {{.+}})
+// CHECK-BE-NEXT: ret <4 x float>
+// CHECK-LE: shufflevector <8 x i16> {{.+}}, <8 x i16> {{.+}}, <8 x i32> <i32 4, i32 undef, i32 5, i32 undef, i32 6, i32 undef, i32 7, i32 undef>
+// CHECK-LE: @llvm.ppc.vsx.xvcvhpsp(<8 x i16> {{.+}})
+// CHECK-LE-NEXT: ret <4 x float>
+ return vec_extract_fp32_from_shortl(vusa);
+}
diff --git a/test/CodeGen/builtins-ppc-quadword.c b/test/CodeGen/builtins-ppc-quadword.c
index f381642c422f..3e168c8b1be6 100644
--- a/test/CodeGen/builtins-ppc-quadword.c
+++ b/test/CodeGen/builtins-ppc-quadword.c
@@ -15,6 +15,12 @@ vector signed __int128 vlll = { -1 };
// CHECK-PPC: error: __int128 is not supported on this target
vector unsigned __int128 vulll = { 1 };
+signed long long param_sll;
+// CHECK-PPC: error: __int128 is not supported on this target
+signed __int128 param_lll;
+// CHECK-PPC: error: __int128 is not supported on this target
+unsigned __int128 param_ulll;
+
// CHECK-PPC: error: __int128 is not supported on this target
vector signed __int128 res_vlll;
// CHECK-PPC: error: __int128 is not supported on this target
@@ -119,11 +125,32 @@ void test1() {
// CHECK-LE: @llvm.ppc.altivec.vsubeuqm
// CHECK-PPC: error: assigning to '__vector __int128' (vector of 1 '__int128' value) from incompatible type 'int'
+ /* vec_sube */
+ res_vlll = vec_sube(vlll, vlll, vlll);
+// CHECK: @llvm.ppc.altivec.vsubeuqm
+// CHECK-LE: @llvm.ppc.altivec.vsubeuqm
+// CHECK-PPC: error: call to 'vec_sube' is ambiguous
+
+ res_vulll = vec_sube(vulll, vulll, vulll);
+// CHECK: @llvm.ppc.altivec.vsubeuqm
+// CHECK-LE: @llvm.ppc.altivec.vsubeuqm
+// CHECK-PPC: error: call to 'vec_sube' is ambiguous
+
+ res_vlll = vec_sube(vlll, vlll, vlll);
+// CHECK: @llvm.ppc.altivec.vsubeuqm
+// CHECK-LE: @llvm.ppc.altivec.vsubeuqm
+// CHECK-PPC: error: call to 'vec_sube' is ambiguous
+
res_vulll = vec_vsubeuqm(vulll, vulll, vulll);
// CHECK: @llvm.ppc.altivec.vsubeuqm
// CHECK-LE: @llvm.ppc.altivec.vsubeuqm
// CHECK-PPC: error: assigning to '__vector unsigned __int128' (vector of 1 'unsigned __int128' value) from incompatible type 'int'
+ res_vulll = vec_sube(vulll, vulll, vulll);
+// CHECK: @llvm.ppc.altivec.vsubeuqm
+// CHECK-LE: @llvm.ppc.altivec.vsubeuqm
+// CHECK-PPC: error: call to 'vec_sube' is ambiguous
+
/* vec_subc */
res_vlll = vec_subc(vlll, vlll);
// CHECK: @llvm.ppc.altivec.vsubcuq
@@ -150,11 +177,73 @@ void test1() {
res_vlll = vec_vsubecuq(vlll, vlll, vlll);
// CHECK: @llvm.ppc.altivec.vsubecuq
// CHECK-LE: @llvm.ppc.altivec.vsubecuq
-// CHECK-PPC: error: assigning to '__vector __int128' (vector of 1 '__int128' value) from incompatible type 'int'
+// CHECK-PPC: error: assigning to '__vector __int128' (vector of 1 '__int128' value) from incompatible type 'int'
res_vulll = vec_vsubecuq(vulll, vulll, vulll);
// CHECK: @llvm.ppc.altivec.vsubecuq
// CHECK-LE: @llvm.ppc.altivec.vsubecuq
+// CHECK-PPC: error: assigning to '__vector unsigned __int128' (vector of 1 'unsigned __int128' value) from incompatible type 'int'
+
+ res_vlll = vec_subec(vlll, vlll, vlll);
+// CHECK: @llvm.ppc.altivec.vsubecuq
+// CHECK-LE: @llvm.ppc.altivec.vsubecuq
+// CHECK-PPC: error: assigning to '__vector __int128' (vector of 1 '__int128' value) from incompatible type 'int'
+
+ res_vulll = vec_subec(vulll, vulll, vulll);
+// CHECK: @llvm.ppc.altivec.vsubecuq
+// CHECK-LE: @llvm.ppc.altivec.vsubecuq
// CHECK-PPC: error: assigning to '__vector unsigned __int128' (vector of 1 'unsigned __int128' value) from incompatible type 'int'
+ res_vulll = vec_revb(vulll);
+// CHECK: store <16 x i8> <i8 15, i8 14, i8 13, i8 12, i8 11, i8 10, i8 9, i8 8, i8 7, i8 6, i8 5, i8 4, i8 3, i8 2, i8 1, i8 0>, <16 x i8>* {{%.+}}, align 16
+// CHECK: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{%.+}}, <4 x i32> {{%.+}}, <16 x i8> {{%.+}})
+// CHECK-LE: store <16 x i8> <i8 15, i8 14, i8 13, i8 12, i8 11, i8 10, i8 9, i8 8, i8 7, i8 6, i8 5, i8 4, i8 3, i8 2, i8 1, i8 0>, <16 x i8>* {{%.+}}, align 16
+// CHECK-LE: store <16 x i8> <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>, <16 x i8>* {{%.+}}, align 16
+// CHECK-LE: xor <16 x i8>
+// CHECK-LE: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{%.+}}, <4 x i32> {{%.+}}, <16 x i8> {{%.+}})
+// CHECK_PPC: error: call to 'vec_revb' is ambiguous
+
+ /* vec_xl */
+ res_vlll = vec_xl(param_sll, &param_lll);
+ // CHECK: load <1 x i128>, <1 x i128>* %{{[0-9]+}}, align 16
+ // CHECK-LE: load <1 x i128>, <1 x i128>* %{{[0-9]+}}, align 16
+ // CHECK-PPC: error: call to 'vec_xl' is ambiguous
+
+ res_vulll = vec_xl(param_sll, &param_ulll);
+ // CHECK: load <1 x i128>, <1 x i128>* %{{[0-9]+}}, align 16
+ // CHECK-LE: load <1 x i128>, <1 x i128>* %{{[0-9]+}}, align 16
+ // CHECK-PPC: error: call to 'vec_xl' is ambiguous
+
+ /* vec_xst */
+ vec_xst(vlll, param_sll, &param_lll);
+ // CHECK: store <1 x i128> %{{[0-9]+}}, <1 x i128>* %{{[0-9]+}}, align 16
+ // CHECK-LE: store <1 x i128> %{{[0-9]+}}, <1 x i128>* %{{[0-9]+}}, align 16
+ // CHECK-PPC: error: call to 'vec_xst' is ambiguous
+
+ vec_xst(vulll, param_sll, &param_ulll);
+ // CHECK: store <1 x i128> %{{[0-9]+}}, <1 x i128>* %{{[0-9]+}}, align 16
+ // CHECK-LE: store <1 x i128> %{{[0-9]+}}, <1 x i128>* %{{[0-9]+}}, align 16
+ // CHECK-PPC: error: call to 'vec_xst' is ambiguous
+
+ /* vec_xl_be */
+ res_vlll = vec_xl_be(param_sll, &param_lll);
+ // CHECK: load <1 x i128>, <1 x i128>* %{{[0-9]+}}, align 16
+ // CHECK-LE: load <1 x i128>, <1 x i128>* %{{[0-9]+}}, align 16
+ // CHECK-PPC: error: call to 'vec_xl' is ambiguous
+
+ res_vulll = vec_xl_be(param_sll, &param_ulll);
+ // CHECK: load <1 x i128>, <1 x i128>* %{{[0-9]+}}, align 16
+ // CHECK-LE: load <1 x i128>, <1 x i128>* %{{[0-9]+}}, align 16
+ // CHECK-PPC: error: call to 'vec_xl' is ambiguous
+
+ /* vec_xst_be */
+ vec_xst_be(vlll, param_sll, &param_lll);
+ // CHECK: store <1 x i128> %{{[0-9]+}}, <1 x i128>* %{{[0-9]+}}, align 16
+ // CHECK-LE: store <1 x i128> %{{[0-9]+}}, <1 x i128>* %{{[0-9]+}}, align 16
+ // CHECK-PPC: error: call to 'vec_xst' is ambiguous
+
+ vec_xst_be(vulll, param_sll, &param_ulll);
+ // CHECK: store <1 x i128> %{{[0-9]+}}, <1 x i128>* %{{[0-9]+}}, align 16
+ // CHECK-LE: store <1 x i128> %{{[0-9]+}}, <1 x i128>* %{{[0-9]+}}, align 16
+ // CHECK-PPC: error: call to 'vec_xst' is ambiguous
}
diff --git a/test/CodeGen/builtins-ppc-vsx.c b/test/CodeGen/builtins-ppc-vsx.c
index e58afdd94dab..16c72c404d9c 100644
--- a/test/CodeGen/builtins-ppc-vsx.c
+++ b/test/CodeGen/builtins-ppc-vsx.c
@@ -21,6 +21,7 @@ vector bool long long vbll = { 1, 0 };
vector signed long long vsll = { 255LL, -937LL };
vector unsigned long long vull = { 1447LL, 2894LL };
double d = 23.4;
+signed long long sll = 618LL;
float af[4] = {23.4f, 56.7f, 89.0f, 12.3f};
double ad[2] = {23.4, 56.7};
signed char asc[16] = { -8, 9, -10, 11, -12, 13, -14, 15,
@@ -31,8 +32,8 @@ signed short ass[8] = { -1, 2, -3, 4, -5, 6, -7, 8 };
unsigned short aus[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
signed int asi[4] = { -1, 2, -3, 4 };
unsigned int aui[4] = { 0, 1, 2, 3 };
-signed long asl[2] = { -1L, 2L };
-unsigned long aul[2] = { 1L, 2L };
+signed long long asll[2] = { -1L, 2L };
+unsigned long long aull[2] = { 1L, 2L };
vector float res_vf;
vector double res_vd;
@@ -69,6 +70,18 @@ void test1() {
// CHECK: call <4 x float> @llvm.fabs.v4f32(<4 x float> %{{[0-9]*}})
// CHECK-LE: call <4 x float> @llvm.fabs.v4f32(<4 x float> %{{[0-9]*}})
+ res_vd = vec_abs(vd);
+// CHECK: call <2 x double> @llvm.fabs.v2f64(<2 x double> %{{[0-9]*}})
+// CHECK-LE: call <2 x double> @llvm.fabs.v2f64(<2 x double> %{{[0-9]*}})
+
+ res_vf = vec_nabs(vf);
+// CHECK: [[VEC:%[0-9]+]] = call <4 x float> @llvm.fabs.v4f32(<4 x float> %{{[0-9]*}})
+// CHECK-NEXT: fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, [[VEC]]
+
+ res_vd = vec_nabs(vd);
+// CHECK: [[VECD:%[0-9]+]] = call <2 x double> @llvm.fabs.v2f64(<2 x double> %{{[0-9]*}})
+// CHECK: fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, [[VECD]]
+
dummy();
// CHECK: call void @dummy()
// CHECK-LE: call void @dummy()
@@ -1080,4 +1093,602 @@ void test1() {
// CHECK: fmul <2 x double>
// CHECK-LE: uitofp <2 x i64> %{{.*}} to <2 x double>
// CHECK-LE: fmul <2 x double>
+
+ res_vsll = vec_signed(vd);
+// CHECK: fptosi <2 x double>
+// CHECK-LE: fptosi <2 x double>
+
+ res_vsi = vec_signed2(vd, vd);
+// CHECK: extractelement <2 x double>
+// CHECK: fptosi double
+// CHECK: insertelement <4 x i32>
+// CHECK: extractelement <2 x double>
+// CHECK: fptosi double
+// CHECK: insertelement <4 x i32>
+// CHECK: extractelement <2 x double>
+// CHECK: fptosi double
+// CHECK: insertelement <4 x i32>
+// CHECK: extractelement <2 x double>
+// CHECK: fptosi double
+// CHECK: insertelement <4 x i32>
+// CHECK-LE: extractelement <2 x double>
+// CHECK-LE: fptosi double
+// CHECK-LE: insertelement <4 x i32>
+// CHECK-LE: extractelement <2 x double>
+// CHECK-LE: fptosi double
+// CHECK-LE: insertelement <4 x i32>
+// CHECK-LE: extractelement <2 x double>
+// CHECK-LE: fptosi double
+// CHECK-LE: insertelement <4 x i32>
+// CHECK-LE: extractelement <2 x double>
+// CHECK-LE: fptosi double
+// CHECK-LE: insertelement <4 x i32>
+
+ res_vsi = vec_signede(vd);
+// CHECK: @llvm.ppc.vsx.xvcvdpsxws(<2 x double>
+// CHECK-LE: @llvm.ppc.vsx.xvcvdpsxws(<2 x double>
+// CHECK-LE: sub nsw i32 16
+// CHECK-LE: sub nsw i32 17
+// CHECK-LE: sub nsw i32 18
+// CHECK-LE: sub nsw i32 31
+// CHECK-LE: @llvm.ppc.altivec.vperm
+
+ res_vsi = vec_signedo(vd);
+// CHECK: @llvm.ppc.vsx.xvcvdpsxws(<2 x double>
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15
+// CHECK: @llvm.ppc.altivec.vperm
+// CHECK-LE: @llvm.ppc.vsx.xvcvdpsxws(<2 x double>
+
+ res_vull = vec_unsigned(vd);
+// CHECK: fptoui <2 x double>
+// CHECK-LE: fptoui <2 x double>
+
+ res_vui = vec_unsigned2(vd, vd);
+// CHECK: extractelement <2 x double>
+// CHECK: fptoui double
+// CHECK: insertelement <4 x i32>
+// CHECK: extractelement <2 x double>
+// CHECK: fptoui double
+// CHECK: insertelement <4 x i32>
+// CHECK: extractelement <2 x double>
+// CHECK: fptoui double
+// CHECK: insertelement <4 x i32>
+// CHECK: extractelement <2 x double>
+// CHECK: fptoui double
+// CHECK: insertelement <4 x i32>
+// CHECK-LE: extractelement <2 x double>
+// CHECK-LE: fptoui double
+// CHECK-LE: insertelement <4 x i32>
+// CHECK-LE: extractelement <2 x double>
+// CHECK-LE: fptoui double
+// CHECK-LE: insertelement <4 x i32>
+// CHECK-LE: extractelement <2 x double>
+// CHECK-LE: fptoui double
+// CHECK-LE: insertelement <4 x i32>
+// CHECK-LE: extractelement <2 x double>
+// CHECK-LE: fptoui double
+// CHECK-LE: insertelement <4 x i32>
+
+ res_vui = vec_unsignede(vd);
+// CHECK: @llvm.ppc.vsx.xvcvdpuxws(<2 x double>
+// CHECK-LE: @llvm.ppc.vsx.xvcvdpuxws(<2 x double>
+// CHECK-LE: sub nsw i32 16
+// CHECK-LE: sub nsw i32 17
+// CHECK-LE: sub nsw i32 18
+// CHECK-LE: sub nsw i32 31
+// CHECK-LE: @llvm.ppc.altivec.vperm
+
+ res_vui = vec_unsignedo(vd);
+// CHECK: @llvm.ppc.vsx.xvcvdpuxws(<2 x double>
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15
+// CHECK: @llvm.ppc.altivec.vperm
+// CHECK-LE: @llvm.ppc.vsx.xvcvdpuxws(<2 x double>
+
+ res_vf = vec_float2(vsll, vsll);
+// CHECK: extractelement <2 x i64>
+// CHECK: sitofp i64
+// CHECK: insertelement <4 x float>
+// CHECK: extractelement <2 x i64>
+// CHECK: sitofp i64
+// CHECK: insertelement <4 x float>
+// CHECK: extractelement <2 x i64>
+// CHECK: sitofp i64
+// CHECK: insertelement <4 x float>
+// CHECK: extractelement <2 x i64>
+// CHECK: sitofp i64
+// CHECK: insertelement <4 x float>
+// CHECK-LE: extractelement <2 x i64>
+// CHECK-LE: sitofp i64
+// CHECK-LE: insertelement <4 x float>
+// CHECK-LE: extractelement <2 x i64>
+// CHECK-LE: sitofp i64
+// CHECK-LE: insertelement <4 x float>
+// CHECK-LE: extractelement <2 x i64>
+// CHECK-LE: sitofp i64
+// CHECK-LE: insertelement <4 x float>
+// CHECK-LE: extractelement <2 x i64>
+// CHECK-LE: sitofp i64
+// CHECK-LE: insertelement <4 x float>
+
+ res_vf = vec_float2(vull, vull);
+// CHECK: extractelement <2 x i64>
+// CHECK: uitofp i64
+// CHECK: insertelement <4 x float>
+// CHECK: extractelement <2 x i64>
+// CHECK: uitofp i64
+// CHECK: insertelement <4 x float>
+// CHECK: extractelement <2 x i64>
+// CHECK: uitofp i64
+// CHECK: insertelement <4 x float>
+// CHECK: extractelement <2 x i64>
+// CHECK: uitofp i64
+// CHECK: insertelement <4 x float>
+// CHECK-LE: extractelement <2 x i64>
+// CHECK-LE: uitofp i64
+// CHECK-LE: insertelement <4 x float>
+// CHECK-LE: extractelement <2 x i64>
+// CHECK-LE: uitofp i64
+// CHECK-LE: insertelement <4 x float>
+// CHECK-LE: extractelement <2 x i64>
+// CHECK-LE: uitofp i64
+// CHECK-LE: insertelement <4 x float>
+// CHECK-LE: extractelement <2 x i64>
+// CHECK-LE: uitofp i64
+// CHECK-LE: insertelement <4 x float>
+
+ res_vf = vec_float2(vd, vd);
+// CHECK: extractelement <2 x double>
+// CHECK: fptrunc double
+// CHECK: insertelement <4 x float>
+// CHECK: extractelement <2 x double>
+// CHECK: fptrunc double
+// CHECK: insertelement <4 x float>
+// CHECK: extractelement <2 x double>
+// CHECK: fptrunc double
+// CHECK: insertelement <4 x float>
+// CHECK: extractelement <2 x double>
+// CHECK: fptrunc double
+// CHECK: insertelement <4 x float>
+// CHECK-LE: extractelement <2 x double>
+// CHECK-LE: fptrunc double
+// CHECK-LE: insertelement <4 x float>
+// CHECK-LE: extractelement <2 x double>
+// CHECK-LE: fptrunc double
+// CHECK-LE: insertelement <4 x float>
+// CHECK-LE: extractelement <2 x double>
+// CHECK-LE: fptrunc double
+// CHECK-LE: insertelement <4 x float>
+// CHECK-LE: extractelement <2 x double>
+// CHECK-LE: fptrunc double
+// CHECK-LE: insertelement <4 x float>
+
+ res_vf = vec_floate(vsll);
+// CHECK: @llvm.ppc.vsx.xvcvsxdsp
+// CHECK-LE: @llvm.ppc.vsx.xvcvsxdsp
+// CHECK-LE: sub nsw i32 16
+// CHECK-LE: sub nsw i32 17
+// CHECK-LE: sub nsw i32 18
+// CHECK-LE: sub nsw i32 31
+// CHECK-LE: @llvm.ppc.altivec.vperm
+
+ res_vf = vec_floate(vull);
+// CHECK: @llvm.ppc.vsx.xvcvuxdsp
+// CHECK-LE: @llvm.ppc.vsx.xvcvuxdsp
+// CHECK-LE: sub nsw i32 16
+// CHECK-LE: sub nsw i32 17
+// CHECK-LE: sub nsw i32 18
+// CHECK-LE: sub nsw i32 31
+// CHECK-LE: @llvm.ppc.altivec.vperm
+
+ res_vf = vec_floate(vd);
+// CHECK: @llvm.ppc.vsx.xvcvdpsp
+// CHECK-LE: @llvm.ppc.vsx.xvcvdpsp
+// CHECK-LE: sub nsw i32 16
+// CHECK-LE: sub nsw i32 17
+// CHECK-LE: sub nsw i32 18
+// CHECK-LE: sub nsw i32 31
+// CHECK-LE: @llvm.ppc.altivec.vperm
+
+ res_vf = vec_floato(vsll);
+// CHECK: @llvm.ppc.vsx.xvcvsxdsp
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15
+// CHECK: @llvm.ppc.altivec.vperm
+// CHECK-LE: @llvm.ppc.vsx.xvcvsxdsp
+
+ res_vf = vec_floato(vull);
+// CHECK: @llvm.ppc.vsx.xvcvuxdsp
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15
+// CHECK: @llvm.ppc.altivec.vperm
+// CHECK-LE: @llvm.ppc.vsx.xvcvuxdsp
+
+ res_vf = vec_floato(vd);
+// CHECK: @llvm.ppc.vsx.xvcvdpsp
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15
+// CHECK: @llvm.ppc.altivec.vperm
+// CHECK-LE: @llvm.ppc.vsx.xvcvdpsp
+
+ res_vd = vec_double(vsll);
+// CHECK: sitofp <2 x i64>
+// CHECK-LE: sitofp <2 x i64>
+
+ res_vd = vec_double(vull);
+// CHECK: uitofp <2 x i64>
+// CHECK-LE: uitofp <2 x i64>
+
+ res_vd = vec_doublee(vsi);
+// CHECK: @llvm.ppc.vsx.xvcvsxwdp(<4 x i32
+// CHECK-LE: sub nsw i32 16
+// CHECK-LE: sub nsw i32 17
+// CHECK-LE: sub nsw i32 18
+// CHECK-LE: sub nsw i32 31
+// CHECK-LE: @llvm.ppc.altivec.vperm
+// CHECK-LE: @llvm.ppc.vsx.xvcvsxwdp(<4 x i32
+
+ res_vd = vec_doublee(vui);
+// CHECK: @llvm.ppc.vsx.xvcvuxwdp(<4 x i32
+// CHECK-LE: sub nsw i32 16
+// CHECK-LE: sub nsw i32 17
+// CHECK-LE: sub nsw i32 18
+// CHECK-LE: sub nsw i32 31
+// CHECK-LE: @llvm.ppc.altivec.vperm
+// CHECK-LE: @llvm.ppc.vsx.xvcvuxwdp(<4 x i32
+
+ res_vd = vec_doublee(vf);
+// CHECK: @llvm.ppc.vsx.xvcvspdp(<4 x float
+// CHECK-LE: sub nsw i32 16
+// CHECK-LE: sub nsw i32 17
+// CHECK-LE: sub nsw i32 18
+// CHECK-LE: sub nsw i32 31
+// CHECK-LE: @llvm.ppc.altivec.vperm
+// CHECK-LE: @llvm.ppc.vsx.xvcvspdp(<4 x float
+
+ res_vd = vec_doubleh(vsi);
+// CHECK: extractelement <4 x i32>
+// CHECK: sitofp i32
+// CHECK: insertelement <2 x double>
+// CHECK: extractelement <4 x i32>
+// CHECK: sitofp i32
+// CHECK: insertelement <2 x double>
+// CHECK-LE: extractelement <4 x i32>
+// CHECK-LE: sitofp i32
+// CHECK-LE: insertelement <2 x double>
+// CHECK-LE: extractelement <4 x i32>
+// CHECK-LE: sitofp i32
+// CHECK-LE: insertelement <2 x double>
+
+ res_vd = vec_doubleh(vui);
+// CHECK: extractelement <4 x i32>
+// CHECK: uitofp i32
+// CHECK: insertelement <2 x double>
+// CHECK: extractelement <4 x i32>
+// CHECK: uitofp i32
+// CHECK: insertelement <2 x double>
+// CHECK-LE: extractelement <4 x i32>
+// CHECK-LE: uitofp i32
+// CHECK-LE: insertelement <2 x double>
+// CHECK-LE: extractelement <4 x i32>
+// CHECK-LE: uitofp i32
+// CHECK-LE: insertelement <2 x double>
+
+ res_vd = vec_doubleh(vf);
+// CHECK: extractelement <4 x float>
+// CHECK: fpext float
+// CHECK: insertelement <2 x double>
+// CHECK: extractelement <4 x float>
+// CHECK: fpext float
+// CHECK: insertelement <2 x double>
+// CHECK-LE: extractelement <4 x float>
+// CHECK-LE: fpext float
+// CHECK-LE: insertelement <2 x double>
+// CHECK-LE: extractelement <4 x float>
+// CHECK-LE: fpext float
+// CHECK-LE: insertelement <2 x double>
+
+ res_vd = vec_doublel(vsi);
+// CHECK: extractelement <4 x i32>
+// CHECK: sitofp i32
+// CHECK: insertelement <2 x double>
+// CHECK: extractelement <4 x i32>
+// CHECK: sitofp i32
+// CHECK: insertelement <2 x double>
+// CHECK-LE: extractelement <4 x i32>
+// CHECK-LE: sitofp i32
+// CHECK-LE: insertelement <2 x double>
+// CHECK-LE: extractelement <4 x i32>
+// CHECK-LE: sitofp i32
+// CHECK-LE: insertelement <2 x double>
+
+ res_vd = vec_doublel(vui);
+// CHECK: extractelement <4 x i32>
+// CHECK: uitofp i32
+// CHECK: insertelement <2 x double>
+// CHECK: extractelement <4 x i32>
+// CHECK: uitofp i32
+// CHECK: insertelement <2 x double>
+// CHECK-LE: extractelement <4 x i32>
+// CHECK-LE: uitofp i32
+// CHECK-LE: insertelement <2 x double>
+// CHECK-LE: extractelement <4 x i32>
+// CHECK-LE: uitofp i32
+// CHECK-LE: insertelement <2 x double>
+
+ res_vd = vec_doublel(vf);
+// CHECK: extractelement <4 x float>
+// CHECK: fpext float
+// CHECK: insertelement <2 x double>
+// CHECK: extractelement <4 x float>
+// CHECK: fpext float
+// CHECK: insertelement <2 x double>
+// CHECK-LE: extractelement <4 x float>
+// CHECK-LE: fpext float
+// CHECK-LE: insertelement <2 x double>
+// CHECK-LE: extractelement <4 x float>
+// CHECK-LE: fpext float
+// CHECK-LE: insertelement <2 x double>
+
+ res_vd = vec_doubleo(vsi);
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15
+// CHECK: @llvm.ppc.altivec.vperm
+// CHECK: @llvm.ppc.vsx.xvcvsxwdp(<4 x i32>
+// CHECK-LE: @llvm.ppc.vsx.xvcvsxwdp(<4 x i32>
+
+ res_vd = vec_doubleo(vui);
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15
+// CHECK: @llvm.ppc.altivec.vperm
+// CHECK: @llvm.ppc.vsx.xvcvuxwdp(<4 x i32>
+// CHECK-LE: @llvm.ppc.vsx.xvcvuxwdp(<4 x i32>
+
+ res_vd = vec_doubleo(vf);
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15
+// CHECK: @llvm.ppc.altivec.vperm
+// CHECK: @llvm.ppc.vsx.xvcvspdp(<4 x float>
+// CHECK-LE: @llvm.ppc.vsx.xvcvspdp(<4 x float>
+
+ res_vbll = vec_reve(vbll);
+// CHECK: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> <i32 1, i32 0>
+// CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> <i32 1, i32 0>
+
+ res_vsll = vec_reve(vsll);
+// CHECK: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> <i32 1, i32 0>
+// CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> <i32 1, i32 0>
+
+ res_vull = vec_reve(vull);
+// CHECK: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> <i32 1, i32 0>
+// CHECK-LE: shufflevector <2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}, <2 x i32> <i32 1, i32 0>
+
+ res_vd = vec_reve(vd);
+// CHECK: shufflevector <2 x double> %{{[0-9]+}}, <2 x double> %{{[0-9]+}}, <2 x i32> <i32 1, i32 0>
+// CHECK-LE: shufflevector <2 x double> %{{[0-9]+}}, <2 x double> %{{[0-9]+}}, <2 x i32> <i32 1, i32 0>
+
+ res_vbll = vec_revb(vbll);
+// CHECK: store <16 x i8> <i8 7, i8 6, i8 5, i8 4, i8 3, i8 2, i8 1, i8 0, i8 15, i8 14, i8 13, i8 12, i8 11, i8 10, i8 9, i8 8>, <16 x i8>* {{%.+}}, align 16
+// CHECK: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{%.+}}, <4 x i32> {{%.+}}, <16 x i8> {{%.+}})
+// CHECK-LE: store <16 x i8> <i8 7, i8 6, i8 5, i8 4, i8 3, i8 2, i8 1, i8 0, i8 15, i8 14, i8 13, i8 12, i8 11, i8 10, i8 9, i8 8>, <16 x i8>* {{%.+}}, align 16
+// CHECK-LE: store <16 x i8> <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>, <16 x i8>* {{%.+}}, align 16
+// CHECK-LE: xor <16 x i8>
+// CHECK-LE: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{%.+}}, <4 x i32> {{%.+}}, <16 x i8> {{%.+}})
+
+ res_vsll = vec_revb(vsll);
+// CHECK: store <16 x i8> <i8 7, i8 6, i8 5, i8 4, i8 3, i8 2, i8 1, i8 0, i8 15, i8 14, i8 13, i8 12, i8 11, i8 10, i8 9, i8 8>, <16 x i8>* {{%.+}}, align 16
+// CHECK: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{%.+}}, <4 x i32> {{%.+}}, <16 x i8> {{%.+}})
+// CHECK-LE: store <16 x i8> <i8 7, i8 6, i8 5, i8 4, i8 3, i8 2, i8 1, i8 0, i8 15, i8 14, i8 13, i8 12, i8 11, i8 10, i8 9, i8 8>, <16 x i8>* {{%.+}}, align 16
+// CHECK-LE: store <16 x i8> <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>, <16 x i8>* {{%.+}}, align 16
+// CHECK-LE: xor <16 x i8>
+// CHECK-LE: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{%.+}}, <4 x i32> {{%.+}}, <16 x i8> {{%.+}})
+
+ res_vull = vec_revb(vull);
+// CHECK: store <16 x i8> <i8 7, i8 6, i8 5, i8 4, i8 3, i8 2, i8 1, i8 0, i8 15, i8 14, i8 13, i8 12, i8 11, i8 10, i8 9, i8 8>, <16 x i8>* {{%.+}}, align 16
+// CHECK: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{%.+}}, <4 x i32> {{%.+}}, <16 x i8> {{%.+}})
+// CHECK-LE: store <16 x i8> <i8 7, i8 6, i8 5, i8 4, i8 3, i8 2, i8 1, i8 0, i8 15, i8 14, i8 13, i8 12, i8 11, i8 10, i8 9, i8 8>, <16 x i8>* {{%.+}}, align 16
+// CHECK-LE: store <16 x i8> <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>, <16 x i8>* {{%.+}}, align 16
+// CHECK-LE: xor <16 x i8>
+// CHECK-LE: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{%.+}}, <4 x i32> {{%.+}}, <16 x i8> {{%.+}})
+
+ res_vd = vec_revb(vd);
+// CHECK: store <16 x i8> <i8 7, i8 6, i8 5, i8 4, i8 3, i8 2, i8 1, i8 0, i8 15, i8 14, i8 13, i8 12, i8 11, i8 10, i8 9, i8 8>, <16 x i8>* {{%.+}}, align 16
+// CHECK: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{%.+}}, <4 x i32> {{%.+}}, <16 x i8> {{%.+}})
+// CHECK-LE: store <16 x i8> <i8 7, i8 6, i8 5, i8 4, i8 3, i8 2, i8 1, i8 0, i8 15, i8 14, i8 13, i8 12, i8 11, i8 10, i8 9, i8 8>, <16 x i8>* {{%.+}}, align 16
+// CHECK-LE: store <16 x i8> <i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1, i8 -1>, <16 x i8>* {{%.+}}, align 16
+// CHECK-LE: xor <16 x i8>
+// CHECK-LE: call <4 x i32> @llvm.ppc.altivec.vperm(<4 x i32> {{%.+}}, <4 x i32> {{%.+}}, <16 x i8> {{%.+}})
+
+ res_vbll = vec_sld(vbll, vbll, 0);
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15
+// CHECK: @llvm.ppc.altivec.vperm
+// CHECK-LE: sub nsw i32 16
+// CHECK-LE: sub nsw i32 17
+// CHECK-LE: sub nsw i32 18
+// CHECK-LE: sub nsw i32 31
+// CHECK-LE: @llvm.ppc.altivec.vperm
+
+ res_vsll = vec_sld(vsll, vsll, 0);
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15
+// CHECK: @llvm.ppc.altivec.vperm
+// CHECK-LE: sub nsw i32 16
+// CHECK-LE: sub nsw i32 17
+// CHECK-LE: sub nsw i32 18
+// CHECK-LE: sub nsw i32 31
+// CHECK-LE: @llvm.ppc.altivec.vperm
+
+ res_vull = vec_sld(vull, vull, 0);
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15
+// CHECK: @llvm.ppc.altivec.vperm
+// CHECK-LE: sub nsw i32 16
+// CHECK-LE: sub nsw i32 17
+// CHECK-LE: sub nsw i32 18
+// CHECK-LE: sub nsw i32 31
+// CHECK-LE: @llvm.ppc.altivec.vperm
+
+ res_vd = vec_sld(vd, vd, 0);
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15
+// CHECK: @llvm.ppc.altivec.vperm
+// CHECK-LE: sub nsw i32 16
+// CHECK-LE: sub nsw i32 17
+// CHECK-LE: sub nsw i32 18
+// CHECK-LE: sub nsw i32 31
+// CHECK-LE: @llvm.ppc.altivec.vperm
+
+ res_vsll = vec_sldw(vsll, vsll, 0);
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15
+// CHECK: @llvm.ppc.altivec.vperm
+// CHECK-LE: sub nsw i32 16
+// CHECK-LE: sub nsw i32 17
+// CHECK-LE: sub nsw i32 18
+// CHECK-LE: sub nsw i32 31
+// CHECK-LE: @llvm.ppc.altivec.vperm
+
+ res_vull = vec_sldw(vull, vull, 0);
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 1
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 2
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 3
+// CHECK: add nsw i32 {{[0-9a-zA-Z%.]+}}, 15
+// CHECK: @llvm.ppc.altivec.vperm
+// CHECK-LE: sub nsw i32 16
+// CHECK-LE: sub nsw i32 17
+// CHECK-LE: sub nsw i32 18
+// CHECK-LE: sub nsw i32 31
+// CHECK-LE: @llvm.ppc.altivec.vperm
+
+ res_vsll = vec_sll(vsll, vuc);
+// CHECK: @llvm.ppc.altivec.vsl
+// CHECK-LE: @llvm.ppc.altivec.vsl
+
+res_vull = vec_sll(vull, vuc);
+// CHECK: @llvm.ppc.altivec.vsl
+// CHECK-LE: @llvm.ppc.altivec.vsl
+
+res_vsll = vec_slo(vsll, vsc);
+// CHECK: @llvm.ppc.altivec.vslo
+// CHECK-LE: @llvm.ppc.altivec.vslo
+
+ res_vsll = vec_slo(vsll, vuc);
+// CHECK: @llvm.ppc.altivec.vslo
+// CHECK-LE: @llvm.ppc.altivec.vslo
+
+ res_vull = vec_slo(vull, vsc);
+// CHECK: @llvm.ppc.altivec.vslo
+// CHECK-LE: @llvm.ppc.altivec.vslo
+
+ res_vull = vec_slo(vull, vuc);
+// CHECK: @llvm.ppc.altivec.vslo
+// CHECK-LE: @llvm.ppc.altivec.vslo
+
+ res_vsll = vec_srl(vsll, vuc);
+// CHECK: @llvm.ppc.altivec.vsr
+// CHECK-LE: @llvm.ppc.altivec.vsr
+
+ res_vull = vec_srl(vull, vuc);
+// CHECK: @llvm.ppc.altivec.vsr
+// CHECK-LE: @llvm.ppc.altivec.vsr
+
+ res_vsll = vec_sro(vsll, vsc);
+// CHECK: @llvm.ppc.altivec.vsro
+// CHECK-LE: @llvm.ppc.altivec.vsro
+
+ res_vsll = vec_sro(vsll, vuc);
+// CHECK: @llvm.ppc.altivec.vsro
+// CHECK-LE: @llvm.ppc.altivec.vsro
+
+ res_vull = vec_sro(vull, vsc);
+// CHECK: @llvm.ppc.altivec.vsro
+// CHECK-LE: @llvm.ppc.altivec.vsro
+
+ res_vull = vec_sro(vull, vuc);
+// CHECK: @llvm.ppc.altivec.vsro
+// CHECK-LE: @llvm.ppc.altivec.vsro
+
+res_vsll = vec_xl(sll, asll);
+// CHECK: load <2 x i64>, <2 x i64>* %{{[0-9]+}}, align 16
+// CHECK-LE: load <2 x i64>, <2 x i64>* %{{[0-9]+}}, align 16
+
+res_vull = vec_xl(sll, aull);
+// CHECK: load <2 x i64>, <2 x i64>* %{{[0-9]+}}, align 16
+// CHECK-LE: load <2 x i64>, <2 x i64>* %{{[0-9]+}}, align 16
+
+res_vd = vec_xl(sll, ad);
+// CHECK: load <2 x double>, <2 x double>* %{{[0-9]+}}, align 16
+// CHECK-LE: load <2 x double>, <2 x double>* %{{[0-9]+}}, align 16
+
+vec_xst(vsll, sll, asll);
+// CHECK: store <2 x i64> %{{[0-9]+}}, <2 x i64>* %{{[0-9]+}}, align 16
+// CHECK-LE: store <2 x i64> %{{[0-9]+}}, <2 x i64>* %{{[0-9]+}}, align 16
+
+vec_xst(vull, sll, aull);
+// CHECK: store <2 x i64> %{{[0-9]+}}, <2 x i64>* %{{[0-9]+}}, align 16
+// CHECK-LE: store <2 x i64> %{{[0-9]+}}, <2 x i64>* %{{[0-9]+}}, align 16
+
+vec_xst(vd, sll, ad);
+// CHECK: store <2 x double> %{{[0-9]+}}, <2 x double>* %{{[0-9]+}}, align 16
+// CHECK-LE: store <2 x double> %{{[0-9]+}}, <2 x double>* %{{[0-9]+}}, align 16
+
+res_vsll = vec_xl_be(sll, asll);
+// CHECK: load <2 x i64>, <2 x i64>* %{{[0-9]+}}, align 16
+// CHECK-LE: call <2 x double> @llvm.ppc.vsx.lxvd2x.be(i8* %{{[0-9]+}})
+
+res_vull = vec_xl_be(sll, aull);
+// CHECK: load <2 x i64>, <2 x i64>* %{{[0-9]+}}, align 16
+// CHECK-LE: call <2 x double> @llvm.ppc.vsx.lxvd2x.be(i8* %{{[0-9]+}})
+
+res_vd = vec_xl_be(sll, ad);
+// CHECK: load <2 x double>, <2 x double>* %{{[0-9]+}}, align 16
+// CHECK-LE: call <2 x double> @llvm.ppc.vsx.lxvd2x.be(i8* %{{[0-9]+}})
+
+vec_xst_be(vsll, sll, asll);
+// CHECK: store <2 x i64> %{{[0-9]+}}, <2 x i64>* %{{[0-9]+}}, align 16
+// CHECK-LE: call void @llvm.ppc.vsx.stxvd2x.be(<2 x double> %{{[0-9]+}}, i8* %{{[0-9]+}})
+
+vec_xst_be(vull, sll, aull);
+// CHECK: store <2 x i64> %{{[0-9]+}}, <2 x i64>* %{{[0-9]+}}, align 16
+// CHECK-LE: call void @llvm.ppc.vsx.stxvd2x.be(<2 x double> %{{[0-9]+}}, i8* %{{[0-9]+}})
+
+vec_xst_be(vd, sll, ad);
+// CHECK: store <2 x double> %{{[0-9]+}}, <2 x double>* %{{[0-9]+}}, align 16
+// CHECK-LE: call void @llvm.ppc.vsx.stxvd2x.be(<2 x double> %{{[0-9]+}}, i8* %{{[0-9]+}})
+
+ res_vf = vec_neg(vf);
+// CHECK: fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, {{%[0-9]+}}
+// CHECK-LE: fsub <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, {{%[0-9]+}}
+
+ res_vd = vec_neg(vd);
+// CHECK: fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, {{%[0-9]+}}
+// CHECK-LE: fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, {{%[0-9]+}}
}
diff --git a/test/CodeGen/builtins-systemz-zvector-error.c b/test/CodeGen/builtins-systemz-zvector-error.c
index 8d5380dac161..b28e8d9bc1fc 100644
--- a/test/CodeGen/builtins-systemz-zvector-error.c
+++ b/test/CodeGen/builtins-systemz-zvector-error.c
@@ -233,38 +233,27 @@ void test_core(void) {
// expected-note@vecintrin.h:* 1 {{must be a constant integer from 0 to 1}}
vsc = vec_load_bndry(cptrsc, idx); // expected-error {{no matching function}}
- // expected-note@vecintrin.h:* 8 {{candidate function not viable}}
- // expected-note@vecintrin.h:* 1 {{must be a constant power of 2 from 64 to 4096}}
+ // expected-note@vecintrin.h:* 9 {{must be a constant power of 2 from 64 to 4096}}
vsc = vec_load_bndry(cptrsc, 200); // expected-error {{no matching function}}
- // expected-note@vecintrin.h:* 8 {{candidate function not viable}}
- // expected-note@vecintrin.h:* 1 {{must be a constant power of 2 from 64 to 4096}}
+ // expected-note@vecintrin.h:* 9 {{must be a constant power of 2 from 64 to 4096}}
vsc = vec_load_bndry(cptrsc, 32); // expected-error {{no matching function}}
- // expected-note@vecintrin.h:* 8 {{candidate function not viable}}
- // expected-note@vecintrin.h:* 1 {{must be a constant power of 2 from 64 to 4096}}
+ // expected-note@vecintrin.h:* 9 {{must be a constant power of 2 from 64 to 4096}}
vsc = vec_load_bndry(cptrsc, 8192); // expected-error {{no matching function}}
- // expected-note@vecintrin.h:* 8 {{candidate function not viable}}
- // expected-note@vecintrin.h:* 1 {{must be a constant power of 2 from 64 to 4096}}
+ // expected-note@vecintrin.h:* 9 {{must be a constant power of 2 from 64 to 4096}}
vuc = vec_load_bndry(cptruc, idx); // expected-error {{no matching function}}
- // expected-note@vecintrin.h:* 8 {{candidate function not viable}}
- // expected-note@vecintrin.h:* 1 {{must be a constant power of 2 from 64 to 4096}}
+ // expected-note@vecintrin.h:* 9 {{must be a constant power of 2 from 64 to 4096}}
vss = vec_load_bndry(cptrss, idx); // expected-error {{no matching function}}
- // expected-note@vecintrin.h:* 8 {{candidate function not viable}}
- // expected-note@vecintrin.h:* 1 {{must be a constant power of 2 from 64 to 4096}}
+ // expected-note@vecintrin.h:* 9 {{must be a constant power of 2 from 64 to 4096}}
vus = vec_load_bndry(cptrus, idx); // expected-error {{no matching function}}
- // expected-note@vecintrin.h:* 8 {{candidate function not viable}}
- // expected-note@vecintrin.h:* 1 {{must be a constant power of 2 from 64 to 4096}}
+ // expected-note@vecintrin.h:* 9 {{must be a constant power of 2 from 64 to 4096}}
vsi = vec_load_bndry(cptrsi, idx); // expected-error {{no matching function}}
- // expected-note@vecintrin.h:* 8 {{candidate function not viable}}
- // expected-note@vecintrin.h:* 1 {{must be a constant power of 2 from 64 to 4096}}
+ // expected-note@vecintrin.h:* 9 {{must be a constant power of 2 from 64 to 4096}}
vui = vec_load_bndry(cptrui, idx); // expected-error {{no matching function}}
- // expected-note@vecintrin.h:* 8 {{candidate function not viable}}
- // expected-note@vecintrin.h:* 1 {{must be a constant power of 2 from 64 to 4096}}
+ // expected-note@vecintrin.h:* 9 {{must be a constant power of 2 from 64 to 4096}}
vsl = vec_load_bndry(cptrsl, idx); // expected-error {{no matching function}}
- // expected-note@vecintrin.h:* 8 {{candidate function not viable}}
- // expected-note@vecintrin.h:* 1 {{must be a constant power of 2 from 64 to 4096}}
+ // expected-note@vecintrin.h:* 9 {{must be a constant power of 2 from 64 to 4096}}
vul = vec_load_bndry(cptrul, idx); // expected-error {{no matching function}}
- // expected-note@vecintrin.h:* 8 {{candidate function not viable}}
- // expected-note@vecintrin.h:* 1 {{must be a constant power of 2 from 64 to 4096}}
+ // expected-note@vecintrin.h:* 9 {{must be a constant power of 2 from 64 to 4096}}
vuc = vec_genmask(idx); // expected-error {{no matching function}}
// expected-note@vecintrin.h:* {{must be a constant integer}}
diff --git a/test/CodeGen/builtins-x86.c b/test/CodeGen/builtins-x86.c
index 8fa24e668f74..ec8a8bf868c5 100644
--- a/test/CodeGen/builtins-x86.c
+++ b/test/CodeGen/builtins-x86.c
@@ -262,7 +262,9 @@ void f0() {
tmp_i = __builtin_ia32_vec_ext_v2si(tmp_V2i, 0);
(void) __builtin_ia32_ldmxcsr(tmp_Ui);
+ (void) _mm_setcsr(tmp_Ui);
tmp_Ui = __builtin_ia32_stmxcsr();
+ tmp_Ui = _mm_getcsr();
(void)__builtin_ia32_fxsave(tmp_vp);
(void)__builtin_ia32_fxsave64(tmp_vp);
(void)__builtin_ia32_fxrstor(tmp_vp);
@@ -290,6 +292,7 @@ void f0() {
tmp_i = __builtin_ia32_cvttss2si(tmp_V4f);
tmp_i = __builtin_ia32_rdtsc();
+ tmp_i = __rdtsc();
tmp_i = __builtin_ia32_rdtscp(&tmp_Ui);
tmp_LLi = __builtin_ia32_rdpmc(tmp_i);
#ifdef USE_64
@@ -304,6 +307,7 @@ void f0() {
tmp_i = __builtin_ia32_pmovmskb(tmp_V8c);
(void) __builtin_ia32_movntq(tmp_V1LLip, tmp_V1LLi);
(void) __builtin_ia32_sfence();
+ (void) _mm_sfence();
tmp_V4s = __builtin_ia32_psadbw(tmp_V8c, tmp_V8c);
tmp_V4f = __builtin_ia32_rcpps(tmp_V4f);
@@ -339,8 +343,13 @@ void f0() {
tmp_V4i = __builtin_ia32_cvtps2dq(tmp_V4f);
tmp_V4i = __builtin_ia32_cvttps2dq(tmp_V4f);
(void) __builtin_ia32_clflush(tmp_vCp);
+ (void) _mm_clflush(tmp_vCp);
(void) __builtin_ia32_lfence();
+ (void) _mm_lfence();
(void) __builtin_ia32_mfence();
+ (void) _mm_mfence();
+ (void) __builtin_ia32_pause();
+ (void) _mm_pause();
tmp_V4s = __builtin_ia32_psllwi(tmp_V4s, tmp_i);
tmp_V2i = __builtin_ia32_pslldi(tmp_V2i, tmp_i);
tmp_V1LLi = __builtin_ia32_psllqi(tmp_V1LLi, tmp_i);
diff --git a/test/CodeGen/builtins.c b/test/CodeGen/builtins.c
index 405f2199af19..390c2e35bf9d 100644
--- a/test/CodeGen/builtins.c
+++ b/test/CodeGen/builtins.c
@@ -220,6 +220,10 @@ void test_float_builtins(float F, double D, long double LD) {
// CHECK: call float @llvm.fabs.f32(float
// CHECK: fcmp one float {{.*}}, 0x7FF0000000000000
+ res = finite(D);
+ // CHECK: call double @llvm.fabs.f64(double
+ // CHECK: fcmp one double {{.*}}, 0x7FF0000000000000
+
res = __builtin_isnormal(F);
// CHECK: fcmp oeq float
// CHECK: call float @llvm.fabs.f32(float
@@ -353,6 +357,7 @@ void test_float_builtin_ops(float F, double D, long double LD) {
// __builtin_longjmp isn't supported on all platforms, so only test it on X86.
#ifdef __x86_64__
+
// CHECK-LABEL: define void @test_builtin_longjmp
void test_builtin_longjmp(void **buffer) {
// CHECK: [[BITCAST:%.*]] = bitcast
@@ -360,6 +365,7 @@ void test_builtin_longjmp(void **buffer) {
__builtin_longjmp(buffer, 1);
// CHECK-NEXT: unreachable
}
+
#endif
// CHECK-LABEL: define i64 @test_builtin_readcyclecounter
@@ -367,3 +373,234 @@ long long test_builtin_readcyclecounter() {
// CHECK: call i64 @llvm.readcyclecounter()
return __builtin_readcyclecounter();
}
+
+// Behavior of __builtin_os_log differs between platforms, so only test on X86
+#ifdef __x86_64__
+
+// CHECK-LABEL: define void @test_builtin_os_log
+// CHECK: (i8* [[BUF:%.*]], i32 [[I:%.*]], i8* [[DATA:%.*]])
+void test_builtin_os_log(void *buf, int i, const char *data) {
+ volatile int len;
+ // CHECK: store i8* [[BUF]], i8** [[BUF_ADDR:%.*]], align 8
+ // CHECK: store i32 [[I]], i32* [[I_ADDR:%.*]], align 4
+ // CHECK: store i8* [[DATA]], i8** [[DATA_ADDR:%.*]], align 8
+
+ // CHECK: store volatile i32 34
+ len = __builtin_os_log_format_buffer_size("%d %{public}s %{private}.16P", i, data, data);
+
+ // CHECK: [[BUF2:%.*]] = load i8*, i8** [[BUF_ADDR]]
+ // CHECK: [[SUMMARY:%.*]] = getelementptr i8, i8* [[BUF2]], i64 0
+ // CHECK: store i8 3, i8* [[SUMMARY]]
+ // CHECK: [[NUM_ARGS:%.*]] = getelementptr i8, i8* [[BUF2]], i64 1
+ // CHECK: store i8 4, i8* [[NUM_ARGS]]
+ //
+ // CHECK: [[ARG1_DESC:%.*]] = getelementptr i8, i8* [[BUF2]], i64 2
+ // CHECK: store i8 0, i8* [[ARG1_DESC]]
+ // CHECK: [[ARG1_SIZE:%.*]] = getelementptr i8, i8* [[BUF2]], i64 3
+ // CHECK: store i8 4, i8* [[ARG1_SIZE]]
+ // CHECK: [[ARG1:%.*]] = getelementptr i8, i8* [[BUF2]], i64 4
+ // CHECK: [[ARG1_INT:%.*]] = bitcast i8* [[ARG1]] to i32*
+ // CHECK: [[I2:%.*]] = load i32, i32* [[I_ADDR]]
+ // CHECK: store i32 [[I2]], i32* [[ARG1_INT]]
+
+ // CHECK: [[ARG2_DESC:%.*]] = getelementptr i8, i8* [[BUF2]], i64 8
+ // CHECK: store i8 34, i8* [[ARG2_DESC]]
+ // CHECK: [[ARG2_SIZE:%.*]] = getelementptr i8, i8* [[BUF2]], i64 9
+ // CHECK: store i8 8, i8* [[ARG2_SIZE]]
+ // CHECK: [[ARG2:%.*]] = getelementptr i8, i8* [[BUF2]], i64 10
+ // CHECK: [[ARG2_PTR:%.*]] = bitcast i8* [[ARG2]] to i8**
+ // CHECK: [[DATA2:%.*]] = load i8*, i8** [[DATA_ADDR]]
+ // CHECK: store i8* [[DATA2]], i8** [[ARG2_PTR]]
+
+ // CHECK: [[ARG3_DESC:%.*]] = getelementptr i8, i8* [[BUF2]], i64 18
+ // CHECK: store i8 17, i8* [[ARG3_DESC]]
+ // CHECK: [[ARG3_SIZE:%.*]] = getelementptr i8, i8* [[BUF2]], i64 19
+ // CHECK: store i8 4, i8* [[ARG3_SIZE]]
+ // CHECK: [[ARG3:%.*]] = getelementptr i8, i8* [[BUF2]], i64 20
+ // CHECK: [[ARG3_INT:%.*]] = bitcast i8* [[ARG3]] to i32*
+ // CHECK: store i32 16, i32* [[ARG3_INT]]
+
+ // CHECK: [[ARG4_DESC:%.*]] = getelementptr i8, i8* [[BUF2]], i64 24
+ // CHECK: store i8 49, i8* [[ARG4_DESC]]
+ // CHECK: [[ARG4_SIZE:%.*]] = getelementptr i8, i8* [[BUF2]], i64 25
+ // CHECK: store i8 8, i8* [[ARG4_SIZE]]
+ // CHECK: [[ARG4:%.*]] = getelementptr i8, i8* [[BUF2]], i64 26
+ // CHECK: [[ARG4_PTR:%.*]] = bitcast i8* [[ARG4]] to i8**
+ // CHECK: [[DATA3:%.*]] = load i8*, i8** [[DATA_ADDR]]
+ // CHECK: store i8* [[DATA3]], i8** [[ARG4_PTR]]
+
+ __builtin_os_log_format(buf, "%d %{public}s %{private}.16P", i, data, data);
+}
+
+// CHECK-LABEL: define void @test_builtin_os_log_errno
+// CHECK: (i8* [[BUF:%.*]], i8* [[DATA:%.*]])
+void test_builtin_os_log_errno(void *buf, const char *data) {
+ volatile int len;
+ // CHECK: store i8* [[BUF]], i8** [[BUF_ADDR:%.*]], align 8
+ // CHECK: store i8* [[DATA]], i8** [[DATA_ADDR:%.*]], align 8
+
+ // CHECK: store volatile i32 2
+ len = __builtin_os_log_format_buffer_size("%S");
+
+ // CHECK: [[BUF2:%.*]] = load i8*, i8** [[BUF_ADDR]]
+ // CHECK: [[SUMMARY:%.*]] = getelementptr i8, i8* [[BUF2]], i64 0
+ // CHECK: store i8 2, i8* [[SUMMARY]]
+ // CHECK: [[NUM_ARGS:%.*]] = getelementptr i8, i8* [[BUF2]], i64 1
+ // CHECK: store i8 1, i8* [[NUM_ARGS]]
+
+ // CHECK: [[ARG1_DESC:%.*]] = getelementptr i8, i8* [[BUF2]], i64 2
+ // CHECK: store i8 96, i8* [[ARG1_DESC]]
+ // CHECK: [[ARG1_SIZE:%.*]] = getelementptr i8, i8* [[BUF2]], i64 3
+ // CHECK: store i8 0, i8* [[ARG1_SIZE]]
+ // CHECK: [[ARG1:%.*]] = getelementptr i8, i8* [[BUF2]], i64 4
+ // CHECK: [[ARG1_INT:%.*]] = bitcast i8* [[ARG1]] to i32*
+ // CHECK: store i32 0, i32* [[ARG1_INT]]
+
+ __builtin_os_log_format(buf, "%m");
+}
+
+// CHECK-LABEL: define void @test_builtin_os_log_wide
+// CHECK: (i8* [[BUF:%.*]], i8* [[DATA:%.*]], i32* [[STR:%.*]])
+typedef int wchar_t;
+void test_builtin_os_log_wide(void *buf, const char *data, wchar_t *str) {
+ volatile int len;
+ // CHECK: store i8* [[BUF]], i8** [[BUF_ADDR:%.*]], align 8
+ // CHECK: store i8* [[DATA]], i8** [[DATA_ADDR:%.*]], align 8
+ // CHECK: store i32* [[STR]], i32** [[STR_ADDR:%.*]],
+
+ // CHECK: store volatile i32 12
+ len = __builtin_os_log_format_buffer_size("%S", str);
+
+ // CHECK: [[BUF2:%.*]] = load i8*, i8** [[BUF_ADDR]]
+ // CHECK: [[SUMMARY:%.*]] = getelementptr i8, i8* [[BUF2]], i64 0
+ // CHECK: store i8 2, i8* [[SUMMARY]]
+ // CHECK: [[NUM_ARGS:%.*]] = getelementptr i8, i8* [[BUF2]], i64 1
+ // CHECK: store i8 1, i8* [[NUM_ARGS]]
+
+ // CHECK: [[ARG1_DESC:%.*]] = getelementptr i8, i8* [[BUF2]], i64 2
+ // CHECK: store i8 80, i8* [[ARG1_DESC]]
+ // CHECK: [[ARG1_SIZE:%.*]] = getelementptr i8, i8* [[BUF2]], i64 3
+ // CHECK: store i8 8, i8* [[ARG1_SIZE]]
+ // CHECK: [[ARG1:%.*]] = getelementptr i8, i8* [[BUF2]], i64 4
+ // CHECK: [[ARG1_PTR:%.*]] = bitcast i8* [[ARG1]] to i32**
+ // CHECK: [[STR2:%.*]] = load i32*, i32** [[STR_ADDR]]
+ // CHECK: store i32* [[STR2]], i32** [[ARG1_PTR]]
+
+ __builtin_os_log_format(buf, "%S", str);
+}
+
+// CHECK-LABEL: define void @test_builtin_os_log_precision_width
+// CHECK: (i8* [[BUF:%.*]], i8* [[DATA:%.*]], i32 [[PRECISION:%.*]], i32 [[WIDTH:%.*]])
+void test_builtin_os_log_precision_width(void *buf, const char *data,
+ int precision, int width) {
+ volatile int len;
+ // CHECK: store i8* [[BUF]], i8** [[BUF_ADDR:%.*]], align 8
+ // CHECK: store i8* [[DATA]], i8** [[DATA_ADDR:%.*]], align 8
+ // CHECK: store i32 [[PRECISION]], i32* [[PRECISION_ADDR:%.*]], align 4
+ // CHECK: store i32 [[WIDTH]], i32* [[WIDTH_ADDR:%.*]], align 4
+
+ // CHECK: store volatile i32 24,
+ len = __builtin_os_log_format_buffer_size("Hello %*.*s World", precision, width, data);
+
+ // CHECK: [[BUF2:%.*]] = load i8*, i8** [[BUF_ADDR]]
+ // CHECK: [[SUMMARY:%.*]] = getelementptr i8, i8* [[BUF2]], i64 0
+ // CHECK: store i8 2, i8* [[SUMMARY]]
+ // CHECK: [[NUM_ARGS:%.*]] = getelementptr i8, i8* [[BUF2]], i64 1
+ // CHECK: store i8 3, i8* [[NUM_ARGS]]
+
+ // CHECK: [[ARG1_DESC:%.*]] = getelementptr i8, i8* [[BUF2]], i64 2
+ // CHECK: store i8 0, i8* [[ARG1_DESC]]
+ // CHECK: [[ARG1_SIZE:%.*]] = getelementptr i8, i8* [[BUF2]], i64 3
+ // CHECK: store i8 4, i8* [[ARG1_SIZE]]
+ // CHECK: [[ARG1:%.*]] = getelementptr i8, i8* [[BUF2]], i64 4
+ // CHECK: [[ARG1_INT:%.*]] = bitcast i8* [[ARG1]] to i32*
+ // CHECK: [[ARG1_VAL:%.*]] = load i32, i32* [[PRECISION_ADDR]]
+ // CHECK: store i32 [[ARG1_VAL]], i32* [[ARG1_INT]]
+
+ // CHECK: [[ARG2_DESC:%.*]] = getelementptr i8, i8* [[BUF2]], i64 8
+ // CHECK: store i8 16, i8* [[ARG2_DESC]]
+ // CHECK: [[ARG2_SIZE:%.*]] = getelementptr i8, i8* [[BUF2]], i64 9
+ // CHECK: store i8 4, i8* [[ARG2_SIZE]]
+ // CHECK: [[ARG2:%.*]] = getelementptr i8, i8* [[BUF2]], i64 10
+ // CHECK: [[ARG2_INT:%.*]] = bitcast i8* [[ARG2]] to i32*
+ // CHECK: [[ARG2_VAL:%.*]] = load i32, i32* [[WIDTH_ADDR]]
+ // CHECK: store i32 [[ARG2_VAL]], i32* [[ARG2_INT]]
+
+ // CHECK: [[ARG3_DESC:%.*]] = getelementptr i8, i8* [[BUF2]], i64 14
+ // CHECK: store i8 32, i8* [[ARG3_DESC]]
+ // CHECK: [[ARG3_SIZE:%.*]] = getelementptr i8, i8* [[BUF2]], i64 15
+ // CHECK: store i8 8, i8* [[ARG3_SIZE]]
+ // CHECK: [[ARG3:%.*]] = getelementptr i8, i8* [[BUF2]], i64 16
+ // CHECK: [[ARG3_PTR:%.*]] = bitcast i8* [[ARG3]] to i8**
+ // CHECK: [[DATA2:%.*]] = load i8*, i8** [[DATA_ADDR]]
+ // CHECK: store i8* [[DATA2]], i8** [[ARG3_PTR]]
+
+ __builtin_os_log_format(buf, "Hello %*.*s World", precision, width, data);
+}
+
+// CHECK-LABEL: define void @test_builtin_os_log_invalid
+// CHECK: (i8* [[BUF:%.*]], i32 [[DATA:%.*]])
+void test_builtin_os_log_invalid(void *buf, int data) {
+ volatile int len;
+ // CHECK: store i8* [[BUF]], i8** [[BUF_ADDR:%.*]], align 8
+ // CHECK: store i32 [[DATA]], i32* [[DATA_ADDR:%.*]]
+
+ // CHECK: store volatile i32 8,
+ len = __builtin_os_log_format_buffer_size("invalid specifier %: %d even a trailing one%", data);
+
+ // CHECK: [[BUF2:%.*]] = load i8*, i8** [[BUF_ADDR]]
+ // CHECK: [[SUMMARY:%.*]] = getelementptr i8, i8* [[BUF2]], i64 0
+ // CHECK: store i8 0, i8* [[SUMMARY]]
+ // CHECK: [[NUM_ARGS:%.*]] = getelementptr i8, i8* [[BUF2]], i64 1
+ // CHECK: store i8 1, i8* [[NUM_ARGS]]
+
+ // CHECK: [[ARG1_DESC:%.*]] = getelementptr i8, i8* [[BUF2]], i64 2
+ // CHECK: store i8 0, i8* [[ARG1_DESC]]
+ // CHECK: [[ARG1_SIZE:%.*]] = getelementptr i8, i8* [[BUF2]], i64 3
+ // CHECK: store i8 4, i8* [[ARG1_SIZE]]
+ // CHECK: [[ARG1:%.*]] = getelementptr i8, i8* [[BUF2]], i64 4
+ // CHECK: [[ARG1_INT:%.*]] = bitcast i8* [[ARG1]] to i32*
+ // CHECK: [[ARG1_VAL:%.*]] = load i32, i32* [[DATA_ADDR]]
+ // CHECK: store i32 [[ARG1_VAL]], i32* [[ARG1_INT]]
+
+ __builtin_os_log_format(buf, "invalid specifier %: %d even a trailing one%", data);
+}
+
+// CHECK-LABEL: define void @test_builtin_os_log_percent
+// CHECK: (i8* [[BUF:%.*]], i8* [[DATA1:%.*]], i8* [[DATA2:%.*]])
+// Check that the %% which does not consume any argument is correctly handled
+void test_builtin_os_log_percent(void *buf, const char *data1, const char *data2) {
+ volatile int len;
+ // CHECK: store i8* [[BUF]], i8** [[BUF_ADDR:%.*]], align 8
+ // CHECK: store i8* [[DATA1]], i8** [[DATA1_ADDR:%.*]], align 8
+ // CHECK: store i8* [[DATA2]], i8** [[DATA2_ADDR:%.*]], align 8
+ // CHECK: store volatile i32 22
+ len = __builtin_os_log_format_buffer_size("%s %% %s", data1, data2);
+
+ // CHECK: [[BUF2:%.*]] = load i8*, i8** [[BUF_ADDR]]
+ // CHECK: [[SUMMARY:%.*]] = getelementptr i8, i8* [[BUF2]], i64 0
+ // CHECK: store i8 2, i8* [[SUMMARY]]
+ // CHECK: [[NUM_ARGS:%.*]] = getelementptr i8, i8* [[BUF2]], i64 1
+ // CHECK: store i8 2, i8* [[NUM_ARGS]]
+ //
+ // CHECK: [[ARG1_DESC:%.*]] = getelementptr i8, i8* [[BUF2]], i64 2
+ // CHECK: store i8 32, i8* [[ARG1_DESC]]
+ // CHECK: [[ARG1_SIZE:%.*]] = getelementptr i8, i8* [[BUF2]], i64 3
+ // CHECK: store i8 8, i8* [[ARG1_SIZE]]
+ // CHECK: [[ARG1:%.*]] = getelementptr i8, i8* [[BUF2]], i64 4
+ // CHECK: [[ARG1_PTR:%.*]] = bitcast i8* [[ARG1]] to i8**
+ // CHECK: [[DATA1:%.*]] = load i8*, i8** [[DATA1_ADDR]]
+ // CHECK: store i8* [[DATA1]], i8** [[ARG1_PTR]]
+ //
+ // CHECK: [[ARG2_DESC:%.*]] = getelementptr i8, i8* [[BUF2]], i64 12
+ // CHECK: store i8 32, i8* [[ARG2_DESC]]
+ // CHECK: [[ARG2_SIZE:%.*]] = getelementptr i8, i8* [[BUF2]], i64 13
+ // CHECK: store i8 8, i8* [[ARG2_SIZE]]
+ // CHECK: [[ARG2:%.*]] = getelementptr i8, i8* [[BUF2]], i64 14
+ // CHECK: [[ARG2_PTR:%.*]] = bitcast i8* [[ARG2]] to i8**
+ // CHECK: [[DATA2:%.*]] = load i8*, i8** [[DATA2_ADDR]]
+ // CHECK: store i8* [[DATA2]], i8** [[ARG2_PTR]]
+ __builtin_os_log_format(buf, "%s %% %s", data1, data2);
+}
+
+#endif \ No newline at end of file
diff --git a/test/CodeGen/captured-statements-nested.c b/test/CodeGen/captured-statements-nested.c
index b81705b8ad89..c078f72d51b2 100644
--- a/test/CodeGen/captured-statements-nested.c
+++ b/test/CodeGen/captured-statements-nested.c
@@ -69,7 +69,7 @@ void test_nest_captured_stmt(int param, int size, int param_arr[size]) {
// CHECK1-NEXT: getelementptr inbounds %struct.A, %struct.A*
// CHECK1-NEXT: store i8 99
//
- // CHECK1: [[SIZE_ADDR_REF:%.*]] = getelementptr inbounds [[T]], [[T]]* {{.*}}, i{{.+}} 0, i{{.+}} 7
+ // CHECK1-DAG: [[SIZE_ADDR_REF:%.*]] = getelementptr inbounds [[T]], [[T]]* {{.*}}, i{{.+}} 0, i{{.+}} 7
// CHECK1-DAG: [[SIZE_ADDR:%.*]] = load i{{.+}}*, i{{.+}}** [[SIZE_ADDR_REF]]
// CHECK1-DAG: [[SIZE:%.*]] = load i{{.+}}, i{{.+}}* [[SIZE_ADDR]]
// CHECK1-DAG: [[PARAM_ARR_IDX:%.*]] = sub nsw i{{.+}} [[SIZE]], 1
@@ -79,7 +79,7 @@ void test_nest_captured_stmt(int param, int size, int param_arr[size]) {
// CHECK1-DAG: [[PARAM_ARR_SIZE_MINUS_1_ADDR:%.*]] = getelementptr inbounds i{{.+}}, i{{.+}}* [[PARAM_ARR]], i{{.*}}
// CHECK1: store i{{.+}} 2, i{{.+}}* [[PARAM_ARR_SIZE_MINUS_1_ADDR]]
//
- // CHECK1: [[Z_ADDR_REF:%.*]] = getelementptr inbounds [[T]], [[T]]* {{.*}}, i{{.+}} 0, i{{.+}} 2
+ // CHECK1-DAG: [[Z_ADDR_REF:%.*]] = getelementptr inbounds [[T]], [[T]]* {{.*}}, i{{.+}} 0, i{{.+}} 2
// CHECK1-DAG: [[Z_ADDR:%.*]] = load %struct.A*, %struct.A** [[Z_ADDR_REF]]
// CHECK1-DAG: [[Z_A_ADDR:%.*]] = getelementptr inbounds %struct.A, %struct.A* [[Z_ADDR]], i{{.+}} 0, i{{.+}} 0
// CHECK1-DAG: [[ARR_IDX_2:%.*]] = load i{{.+}}, i{{.+}}* [[Z_A_ADDR]]
diff --git a/test/CodeGen/cfi-icall-cross-dso2.c b/test/CodeGen/cfi-icall-cross-dso2.c
new file mode 100644
index 000000000000..acc72a7ee766
--- /dev/null
+++ b/test/CodeGen/cfi-icall-cross-dso2.c
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -O1 -fblocks \
+// RUN: -fsanitize=cfi-icall -fsanitize-cfi-cross-dso \
+// RUN: -emit-llvm -o - %s | FileCheck %s
+
+// CHECK: define void @f() {{.*}} !type !{{.*}} !type !{{.*}}
+void f(void);
+void (*pf)(void) = f;
+void f(void) { }
+
+// Check that we do not crash on non-FunctionDecl definitions.
+void (^g)(void) = ^{};
diff --git a/test/CodeGen/cleanup-destslot-simple.c b/test/CodeGen/cleanup-destslot-simple.c
index 9b9f74eb2184..848a8dc847a9 100644
--- a/test/CodeGen/cleanup-destslot-simple.c
+++ b/test/CodeGen/cleanup-destslot-simple.c
@@ -13,8 +13,8 @@ int test() {
return *p;
// CHECK: [[X:%.*]] = alloca i32
// CHECK: [[P:%.*]] = alloca i32*
-// LIFETIME: call void @llvm.lifetime.start(i64 4, i8* %{{.*}}){{( #[0-9]+)?}}, !dbg
-// LIFETIME: call void @llvm.lifetime.start(i64 8, i8* %{{.*}}){{( #[0-9]+)?}}, !dbg
+// LIFETIME: call void @llvm.lifetime.start(i64 4, i8* nonnull %{{.*}}){{( #[0-9]+)?}}, !dbg
+// LIFETIME: call void @llvm.lifetime.start(i64 8, i8* nonnull %{{.*}}){{( #[0-9]+)?}}, !dbg
// CHECK-NOT: store i32 %{{.*}}, i32* %cleanup.dest.slot
// LIFETIME: call void @llvm.lifetime.end(i64 8, {{.*}}){{( #[0-9]+)?}}, !dbg
// LIFETIME: call void @llvm.lifetime.end(i64 4, {{.*}}){{( #[0-9]+)?}}, !dbg
diff --git a/test/CodeGen/code-coverage.c b/test/CodeGen/code-coverage.c
index 1b87d649dd97..80307f49ef34 100644
--- a/test/CodeGen/code-coverage.c
+++ b/test/CodeGen/code-coverage.c
@@ -1,5 +1,6 @@
// RUN: %clang_cc1 -emit-llvm -disable-red-zone -femit-coverage-data %s -o - | FileCheck %s
// 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>
@@ -28,3 +29,6 @@ int test1(int a) {
// CHECK: void @__llvm_gcov_init() unnamed_addr [[NRZ]]
// CHECK: attributes [[NRZ]] = { {{.*}}noredzone{{.*}} }
+
+// GCOV_FILE_INFO: !llvm.gcov = !{![[GCOV:[0-9]+]]}
+// GCOV_FILE_INFO: ![[GCOV]] = !{!"aaa.gcno", !"bbb.gcda", !{{[0-9]+}}}
diff --git a/test/CodeGen/compound-literal.c b/test/CodeGen/compound-literal.c
index 85138bfaf5e0..6507341ce2c1 100644
--- a/test/CodeGen/compound-literal.c
+++ b/test/CodeGen/compound-literal.c
@@ -1,5 +1,10 @@
// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm %s -o - | FileCheck %s
+// Capture the type and name so matching later is cleaner.
+struct CompoundTy { int a; };
+// CHECK: @MyCLH = constant [[MY_CLH:[^,]+]]
+const struct CompoundTy *const MyCLH = &(struct CompoundTy){3};
+
int* a = &(int){1};
struct s {int a, b, c;} * b = &(struct s) {1, 2, 3};
_Complex double * x = &(_Complex double){1.0f};
@@ -66,3 +71,14 @@ struct G g(int x, int y, int z) {
// CHECK-NEXT: [[T0:%.*]] = load i48, i48* [[COERCE_TEMP]]
// CHECK-NEXT: ret i48 [[T0]]
}
+
+// We had a bug where we'd emit a new GlobalVariable for each time we used a
+// const pointer to a variable initialized by a compound literal.
+// CHECK-LABEL: define i32 @compareMyCLH() #0
+int compareMyCLH() {
+ // CHECK: store i8* bitcast ([[MY_CLH]] to i8*)
+ const void *a = MyCLH;
+ // CHECK: store i8* bitcast ([[MY_CLH]] to i8*)
+ const void *b = MyCLH;
+ return a == b;
+}
diff --git a/test/CodeGen/dbg-const-int128.c b/test/CodeGen/dbg-const-int128.c
new file mode 100644
index 000000000000..966c22705500
--- /dev/null
+++ b/test/CodeGen/dbg-const-int128.c
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -S -emit-llvm -debug-info-kind=limited %s -o - | FileCheck %s
+// CHECK: !DIGlobalVariable({{.*}}
+// CHECK-NOT: expr:
+
+static const __uint128_t ro = 18446744073709551615;
+
+void bar(__uint128_t);
+void foo() { bar(ro); }
diff --git a/test/CodeGen/debug-info-atomic.c b/test/CodeGen/debug-info-atomic.c
new file mode 100644
index 000000000000..3de0d3585d29
--- /dev/null
+++ b/test/CodeGen/debug-info-atomic.c
@@ -0,0 +1,8 @@
+// RUN: %clang -g -c -std=c11 -S -emit-llvm -o - %s | FileCheck %s
+
+// CHECK: !DIGlobalVariable(name: "i"
+// CHECK-SAME: type: ![[T:.*]], isLocal: false, isDefinition: true)
+// CHECK: ![[T]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[BT:.*]])
+// CHECK: ![[BT]] = !DIDerivedType(tag: DW_TAG_atomic_type, baseType: ![[BTT:.*]])
+// CHECK: ![[BTT]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+_Atomic const int i;
diff --git a/test/CodeGen/debug-info-file-checksum.c b/test/CodeGen/debug-info-file-checksum.c
new file mode 100644
index 000000000000..2750800d41ea
--- /dev/null
+++ b/test/CodeGen/debug-info-file-checksum.c
@@ -0,0 +1,5 @@
+// RUN: %clang -emit-llvm -S -g -gcodeview -x c %S/Inputs/debug-info-file-checksum.c -o - | FileCheck %s
+
+// Check that "checksum" is created correctly for the compiled file.
+
+// CHECK: !DIFile(filename:{{.*}}, directory:{{.*}}, checksumkind: CSK_MD5, checksum: "a3b7d27af071accdeccaa933fc603608")
diff --git a/test/CodeGen/debug-info-global-constant.c b/test/CodeGen/debug-info-global-constant.c
new file mode 100644
index 000000000000..4175f24675e5
--- /dev/null
+++ b/test/CodeGen/debug-info-global-constant.c
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -emit-llvm -debug-info-kind=standalone \
+// RUN: -triple %itanium_abi_triple %s -o - | FileCheck %s
+
+// Debug info for a global constant whose address is taken should be emitted
+// exactly once.
+
+// CHECK: @i = internal constant i32 1, align 4, !dbg ![[I:[0-9]+]]
+// CHECK: ![[I]] = !DIGlobalVariableExpression(var: ![[VAR:.*]], expr: ![[EXPR:[0-9]+]])
+// CHECK: ![[VAR]] = distinct !DIGlobalVariable(name: "i",
+// CHECK: !DICompileUnit({{.*}}globals: ![[GLOBALS:[0-9]+]])
+// CHECK: ![[GLOBALS]] = !{![[I]]}
+// CHECK: ![[EXPR]] = !DIExpression(DW_OP_constu, 1, DW_OP_stack_value)
+static const int i = 1;
+
+void g(const int *, int);
+void f() {
+ g(&i, i);
+}
diff --git a/test/CodeGen/debug-info-imported-entity.cpp b/test/CodeGen/debug-info-imported-entity.cpp
index 105cc3dc5371..c7935eda48c5 100644
--- a/test/CodeGen/debug-info-imported-entity.cpp
+++ b/test/CodeGen/debug-info-imported-entity.cpp
@@ -3,9 +3,7 @@
namespace std { class A; }
using std::A; using ::A;
-
-// CHECK: [[CompileUnit:![0-9]+]] = distinct !DICompileUnit({{.+}} imports: [[Imports:![0-9]+]])
+// CHECK: [[CompileUnit:![0-9]+]] = distinct !DICompileUnit({{.+}} imports: [[Imports:![0-9]+]]
// CHECK: [[Imports]] = !{[[ImportedEntity:![0-9]+]]}
// CHECK: [[ImportedEntity]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[CompileUnit]], entity: [[STDA:![0-9]+]], line: 4)
// CHECK: [[STDA]] = !DICompositeType(tag: DW_TAG_class_type, name: "A",
-
diff --git a/test/CodeGen/debug-info-packed-struct.c b/test/CodeGen/debug-info-packed-struct.c
index 8c1a0d4cfdb3..6441a740e379 100644
--- a/test/CodeGen/debug-info-packed-struct.c
+++ b/test/CodeGen/debug-info-packed-struct.c
@@ -1,9 +1,9 @@
// RUN: %clang_cc1 -x c -debug-info-kind=limited -emit-llvm -triple x86_64-apple-darwin -o - %s | FileCheck %s
+// CHECK: %struct.layout3 = type <{ i8, [3 x i8], %struct.size8_pack4, i8, [3 x i8] }>
// CHECK: %struct.layout0 = type { i8, %struct.size8, i8 }
// CHECK: %struct.layout1 = type <{ i8, %struct.size8_anon, i8, [2 x i8] }>
// CHECK: %struct.layout2 = type <{ i8, %struct.size8_pack1, i8 }>
-// CHECK: %struct.layout3 = type <{ i8, [3 x i8], %struct.size8_pack4, i8, [3 x i8] }>
// ---------------------------------------------------------------------
// Not packed.
@@ -19,9 +19,9 @@ struct layout0 {
};
// CHECK: l0_ofs0
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "l0_ofs8",
-// CHECK-SAME: {{.*}}size: 64, align: 64, offset: 64)
+// CHECK-SAME: {{.*}}size: 64, offset: 64)
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "l0_ofs16",
-// CHECK-SAME: {{.*}}size: 1, align: 32, offset: 128, flags: DIFlagBitField, extraData: i64 128)
+// CHECK-SAME: {{.*}}size: 1, offset: 128, flags: DIFlagBitField, extraData: i64 128)
// ---------------------------------------------------------------------
@@ -38,9 +38,9 @@ struct layout1 {
};
// CHECK: l1_ofs0
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "l1_ofs1",
-// CHECK-SAME: {{.*}}size: 64, align: 8, offset: 8)
+// CHECK-SAME: {{.*}}size: 64, offset: 8)
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "l1_ofs9",
-// CHECK-SAME: {{.*}}size: 1, align: 32, offset: 72, flags: DIFlagBitField, extraData: i64 72)
+// CHECK-SAME: {{.*}}size: 1, offset: 72, flags: DIFlagBitField, extraData: i64 72)
// ---------------------------------------------------------------------
@@ -59,9 +59,9 @@ struct layout2 {
#pragma pack()
// CHECK: l2_ofs0
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "l2_ofs1",
-// CHECK-SAME: {{.*}}size: 64, align: 8, offset: 8)
+// CHECK-SAME: {{.*}}size: 64, offset: 8)
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "l2_ofs9",
-// CHECK-SAME: {{.*}}size: 1, align: 32, offset: 72, flags: DIFlagBitField, extraData: i64 72)
+// CHECK-SAME: {{.*}}size: 1, offset: 72, flags: DIFlagBitField, extraData: i64 72)
@@ -81,11 +81,11 @@ struct layout3 {
#pragma pack()
// CHECK: l3_ofs0
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "l3_ofs4",
-// CHECK-SAME: {{.*}}size: 64, align: 32, offset: 32)
+// CHECK-SAME: {{.*}}size: 64, offset: 32)
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "l3_ofs12",
-// CHECK-SAME: {{.*}}size: 1, align: 32, offset: 96, flags: DIFlagBitField, extraData: i64 96)
+// CHECK-SAME: {{.*}}size: 1, offset: 96, flags: DIFlagBitField, extraData: i64 96)
+struct layout3 l3;
struct layout0 l0;
struct layout1 l1;
struct layout2 l2;
-struct layout3 l3;
diff --git a/test/CodeGen/debug-info-static-const-fp.c b/test/CodeGen/debug-info-static-const-fp.c
new file mode 100644
index 000000000000..4dfe057f2b6e
--- /dev/null
+++ b/test/CodeGen/debug-info-static-const-fp.c
@@ -0,0 +1,54 @@
+// RUN: %clang_cc1 -emit-llvm -O0 -debug-info-kind=limited %s -o - | \
+// RUN: FileCheck --check-prefixes CHECK %s
+
+// RUN: %clang_cc1 -triple hexagon-unknown--elf -emit-llvm -O0 -debug-info-kind=limited %s -o - | \
+// RUN: FileCheck --check-prefixes CHECK,CHECK-LDsm %s
+
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -O0 -debug-info-kind=limited %s -o - | \
+// RUN: FileCheck --check-prefixes CHECK,CHECK-LDlg %s
+
+// Per PR26619, check that for referenced static const of floating-point type,
+// we emit its constant value in debug info.
+//
+// NOTE that __fp16 is assumed to be 16 bits, float is assumed to be
+// 32 bits, and double is assumed to be 64 bits. Size of long double
+// is not known (for example, it is 64 bits for hexagon-unknown--elf,
+// but 128 bits for x86_64-unknown-linux-gnu). Therefore, we specify
+// target triples where it has a known size, and check accordingly:
+// for the absence of a constant (CHECK-LDlg) when the size exceeds 64
+// bits, and for the presence of a constant (CHECK-LDsm) but not its
+// value when the size does not exceed 64 bits.
+//
+// NOTE that PR26619 is not yet fixed for types greater than 64 bits.
+
+static const __fp16 hVal = 29/13.0f; // 2.2307692307692307692 (2.23046875)
+
+static const float fVal = -147/17.0f; // -8.6470588235294117647 (-8.64705849)
+
+static const double dVal = 19637/7.0; // 2805.2857142857142857 (2805.2857142857142)
+
+static const long double ldVal = 3/1234567.0L; // 2.4300017739012949479e-06 (<depends on size of long double>)
+
+int main() {
+ return hVal + fVal + dVal + ldVal;
+}
+
+// CHECK: !DIGlobalVariableExpression(var: [[HVAL:.*]], expr: [[HEXPR:.*]])
+// CHECK: [[HVAL]] = distinct !DIGlobalVariable(name: "hVal",
+// CHECK-SAME: isLocal: true, isDefinition: true
+// CHECK: [[HEXPR]] = !DIExpression(DW_OP_constu, 16502, DW_OP_stack_value)
+
+// CHECK: !DIGlobalVariableExpression(var: [[FVAL:.*]], expr: [[FEXPR:.*]])
+// CHECK: [[FVAL]] = distinct !DIGlobalVariable(name: "fVal",
+// CHECK-SAME: isLocal: true, isDefinition: true
+// CHECK: [[FEXPR]] = !DIExpression(DW_OP_constu, 3238681178, DW_OP_stack_value)
+
+// CHECK: !DIGlobalVariableExpression(var: [[DVAL:.*]], expr: [[DEXPR:.*]])
+// CHECK: [[DVAL]] = distinct !DIGlobalVariable(name: "dVal",
+// CHECK-SAME: isLocal: true, isDefinition: true
+// CHECK: [[DEXPR]] = !DIExpression(DW_OP_constu, 4658387303597904457, DW_OP_stack_value)
+
+// CHECK-LDlg-DAG: [[LDVAL:.*]] = distinct !DIGlobalVariable(name: "ldVal", {{.*}}, isLocal: true, isDefinition: true)
+// CHECK-LDlg-DAG: !DIGlobalVariableExpression(var: [[LDVAL]])
+// CHECK-LDsm-DAG: [[LDVAL:.*]] = distinct !DIGlobalVariable(name: "ldVal", {{.*}}, isLocal: true, isDefinition: true)
+// CHECK-LDsm-DAG: !DIGlobalVariableExpression(var: [[LDVAL]], expr:
diff --git a/test/CodeGen/debug-info-static.c b/test/CodeGen/debug-info-static.c
index fbe2a0098f70..016f1e6e6cc5 100644
--- a/test/CodeGen/debug-info-static.c
+++ b/test/CodeGen/debug-info-static.c
@@ -1,6 +1,9 @@
// RUN: %clang_cc1 -debug-info-kind=limited -emit-llvm -o - %s | FileCheck %s
-// CHECK: !DIGlobalVariable({{.*}}variable: i32* @f.xyzzy
+// CHECK: @f.xyzzy = internal global i32 0, align 4, !dbg [[XYZZY:![0-9]+]]
+
+// CHECK: [[XYZZY]] = !DIGlobalVariableExpression(var: [[VAR:.*]])
+// CHECK: [[VAR]] = distinct !DIGlobalVariable
void f(void)
{
static int xyzzy;
diff --git a/test/CodeGen/debug-info-vector.c b/test/CodeGen/debug-info-vector.c
index 6b27573578c2..93e63926c93d 100644
--- a/test/CodeGen/debug-info-vector.c
+++ b/test/CodeGen/debug-info-vector.c
@@ -6,6 +6,6 @@ v4si a;
// Test that we get an array type that's also a vector out of debug.
// CHECK: !DICompositeType(tag: DW_TAG_array_type,
// CHECK-SAME: baseType: ![[INT:[0-9]+]]
-// CHECK-SAME: size: 128, align: 128
+// CHECK-SAME: size: 128
// CHECK-SAME: DIFlagVector
// CHECK: ![[INT]] = !DIBasicType(name: "int"
diff --git a/test/CodeGen/decl-in-prototype.c b/test/CodeGen/decl-in-prototype.c
index 15efa6551bc3..426adf4b765c 100644
--- a/test/CodeGen/decl-in-prototype.c
+++ b/test/CodeGen/decl-in-prototype.c
@@ -1,4 +1,4 @@
-// RUN: %clang -target i386-unknown-unknown -emit-llvm -S -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple i386-linux -debug-info-kind=limited -emit-llvm -o - %s | FileCheck %s
const int AA = 5;
@@ -19,3 +19,8 @@ int f(void (*g)(), enum {AA,BB} h) {
// CHECK: ret i32 0
return AA;
}
+
+// This used to crash with debug info enabled.
+int pr31366(struct { enum { a = 1 } b; } c) {
+ return a;
+}
diff --git a/test/CodeGen/denormalfpmode.c b/test/CodeGen/denormalfpmode.c
new file mode 100644
index 000000000000..b0013daefbf8
--- /dev/null
+++ b/test/CodeGen/denormalfpmode.c
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -S -fdenormal-fp-math=ieee %s -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-IEEE
+// RUN: %clang_cc1 -S -fdenormal-fp-math=preserve-sign %s -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-PS
+// RUN: %clang_cc1 -S -fdenormal-fp-math=positive-zero %s -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-PZ
+
+// CHECK-LABEL: main
+// CHECK-IEEE: attributes #0 = {{.*}}"denormal-fp-math"="ieee"{{.*}}
+// CHECK-PS: attributes #0 = {{.*}}"denormal-fp-math"="preserve-sign"{{.*}}
+// CHECK-PZ: attributes #0 = {{.*}}"denormal-fp-math"="positive-zero"{{.*}}
+
+int main() {
+ return 0;
+}
diff --git a/test/CodeGen/dwarf-version.c b/test/CodeGen/dwarf-version.c
index 2171ed6ad97d..cee0f031e130 100644
--- a/test/CodeGen/dwarf-version.c
+++ b/test/CodeGen/dwarf-version.c
@@ -4,7 +4,13 @@
// RUN: %clang -target x86_64-linux-gnu -gdwarf-5 -S -emit-llvm -o - %s | FileCheck %s --check-prefix=VER5
// RUN: %clang -target x86_64-linux-gnu -g -S -emit-llvm -o - %s | FileCheck %s --check-prefix=VER4
// RUN: %clang -target x86_64-linux-gnu -gdwarf -S -emit-llvm -o - %s | FileCheck %s --check-prefix=VER4
-// RUN: %clang -target x86_64-apple-darwin -g -S -emit-llvm -o - %s | FileCheck %s --check-prefix=VER2
+
+// The -isysroot is used as a hack to avoid LIT messing with the SDKROOT
+// environment variable which indirecty overrides the version in the target
+// triple used here.
+// RUN: %clang -target x86_64-apple-macosx10.11 -g -S -emit-llvm -o - %s -isysroot %t | FileCheck %s --check-prefix=VER4
+// RUN: %clang -target x86_64-apple-darwin14 -g -S -emit-llvm -o - %s -isysroot %t | FileCheck %s --check-prefix=VER2
+
// RUN: %clang -target powerpc-unknown-openbsd -g -S -emit-llvm -o - %s | FileCheck %s --check-prefix=VER2
// RUN: %clang -target powerpc-unknown-freebsd -g -S -emit-llvm -o - %s | FileCheck %s --check-prefix=VER2
// RUN: %clang -target i386-pc-solaris -g -S -emit-llvm -o - %s | FileCheck %s --check-prefix=VER2
diff --git a/test/CodeGen/ext-vector.c b/test/CodeGen/ext-vector.c
index 0b78e97fbb36..beb58827ea13 100644
--- a/test/CodeGen/ext-vector.c
+++ b/test/CodeGen/ext-vector.c
@@ -301,3 +301,40 @@ void test17(void) {
char valC;
char16 destVal = valC ? valA : valB;
}
+
+typedef __attribute__(( ext_vector_type(16) )) float float16;
+
+float16 vec16, vec16_2;
+
+// CHECK: @test_rgba
+void test_rgba() {
+ // CHECK: fadd <4 x float>
+ vec4_2 = vec4.abgr + vec4;
+
+ // CHECK: shufflevector {{.*}} <i32 0, i32 1>
+ vec2 = vec4.rg;
+ // CHECK: shufflevector {{.*}} <i32 2, i32 3>
+ vec2_2 = vec4.ba;
+ // CHECK: extractelement {{.*}} 2
+ f = vec4.b;
+ // CHECK: shufflevector {{.*}} <i32 2, i32 2, i32 2, i32 2>
+ vec4_2 = vec4_2.bbbb;
+
+ // CHECK: insertelement {{.*}} 0
+ vec2.r = f;
+ // CHECK: shufflevector {{.*}} <i32 1, i32 0>
+ vec2.gr = vec2;
+
+ // CHECK: extractelement {{.*}} 0
+ f = vec4_2.rg.r;
+ // CHECK: shufflevector {{.*}} <i32 2, i32 1, i32 0>
+ // CHECK: shufflevector {{.*}} <i32 0, i32 1, i32 2, i32 undef>
+ // CHECK: shufflevector {{.*}} <i32 4, i32 5, i32 6, i32 3>
+ vec4.rgb = vec4.bgr;
+
+ // CHECK: extractelement {{.*}} 11
+ // CHECK: insertelement {{.*}} 2
+ vec4.b = vec16.sb;
+ // CHECK: shufflevector {{.*}} <i32 10, i32 11, i32 12, i32 13>
+ vec4_2 = vec16.sabcd;
+}
diff --git a/test/CodeGen/f16c-builtins.c b/test/CodeGen/f16c-builtins.c
index e99c0d00d4b3..e4933e9f9bf3 100644
--- a/test/CodeGen/f16c-builtins.c
+++ b/test/CodeGen/f16c-builtins.c
@@ -1,7 +1,5 @@
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +f16c -emit-llvm -o - -Werror | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +f16c -emit-llvm -o - -Wall -Werror | FileCheck %s
-// Don't include mm_malloc.h, it's system specific.
-#define __MM_MALLOC_H
#include <x86intrin.h>
diff --git a/test/CodeGen/fixup-depth-overflow.c b/test/CodeGen/fixup-depth-overflow.c
index be8f54284ec7..af452d05b643 100644
--- a/test/CodeGen/fixup-depth-overflow.c
+++ b/test/CodeGen/fixup-depth-overflow.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -O1 -disable-llvm-optzns -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -O1 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s
#define M if (x) goto L1;
#define M10 M M M M M M M M M M
diff --git a/test/CodeGen/fma-builtins.c b/test/CodeGen/fma-builtins.c
index 922f12b8b3d3..91a2efe7637e 100644
--- a/test/CodeGen/fma-builtins.c
+++ b/test/CodeGen/fma-builtins.c
@@ -1,7 +1,5 @@
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +fma -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +fma -emit-llvm -o - | FileCheck %s
-// Don't include mm_malloc.h, it's system specific.
-#define __MM_MALLOC_H
#include <immintrin.h>
diff --git a/test/CodeGen/fma4-builtins.c b/test/CodeGen/fma4-builtins.c
index 69cbcd83d370..3ca5fac68892 100644
--- a/test/CodeGen/fma4-builtins.c
+++ b/test/CodeGen/fma4-builtins.c
@@ -1,7 +1,5 @@
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +fma4 -emit-llvm -o - -Werror | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +fma4 -emit-llvm -o - -Wall -Werror | FileCheck %s
-// Don't include mm_malloc.h, it's system specific.
-#define __MM_MALLOC_H
#include <x86intrin.h>
diff --git a/test/CodeGen/fsgsbase-builtins.c b/test/CodeGen/fsgsbase-builtins.c
index 5e9ba8c9dde4..25f4b311a596 100644
--- a/test/CodeGen/fsgsbase-builtins.c
+++ b/test/CodeGen/fsgsbase-builtins.c
@@ -1,7 +1,5 @@
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +fsgsbase -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +fsgsbase -emit-llvm -o - | FileCheck %s
-// Don't include mm_malloc.h, it's system specific.
-#define __MM_MALLOC_H
#include <x86intrin.h>
diff --git a/test/CodeGen/func-in-block.c b/test/CodeGen/func-in-block.c
index 503695f8c378..937390c1cdb6 100644
--- a/test/CodeGen/func-in-block.c
+++ b/test/CodeGen/func-in-block.c
@@ -15,5 +15,5 @@ int main()
return 0; // not reached
}
-// CHECK: @__func__.__main_block_invoke = private unnamed_addr constant [20 x i8] c"__main_block_invoke\00"
-// CHECK: call void @PRINTF({{.*}}@__func__.__main_block_invoke
+// CHECK: @__func__.__main_block_invoke = private unnamed_addr constant [18 x i8] c"main_block_invoke\00"
+// CHECK: call void @PRINTF({{.*}}@__func__.__main_block_invoke
diff --git a/test/CodeGen/function-attributes.c b/test/CodeGen/function-attributes.c
index 8f682a715d73..2139f6fe6546 100644
--- a/test/CodeGen/function-attributes.c
+++ b/test/CodeGen/function-attributes.c
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm -disable-llvm-optzns -Os -o - %s | FileCheck %s
-// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm -disable-llvm-optzns -Os -std=c99 -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm -disable-llvm-passes -Os -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm -disable-llvm-passes -Os -std=c99 -o - %s | FileCheck %s
// CHECK: define signext i8 @f0(i32 %x) [[NUW:#[0-9]+]]
// CHECK: define zeroext i8 @f1(i32 %x) [[NUW]]
// CHECK: define void @f2(i8 signext %x) [[NUW]]
diff --git a/test/CodeGen/incomplete-function-type-2.c b/test/CodeGen/incomplete-function-type-2.c
index 41dd5fec4b25..4ed065a5f868 100644
--- a/test/CodeGen/incomplete-function-type-2.c
+++ b/test/CodeGen/incomplete-function-type-2.c
@@ -16,4 +16,4 @@ void test10_foo(test10_F3 p1)
p1(0.0);
}
-// CHECK: attributes [[NUW]] = { nounwind{{.*}} }
+// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} }
diff --git a/test/CodeGen/inline-optim.c b/test/CodeGen/inline-optim.c
index f8b355afd9c1..c6038de173f5 100644
--- a/test/CodeGen/inline-optim.c
+++ b/test/CodeGen/inline-optim.c
@@ -1,9 +1,15 @@
// Make sure -finline-functions family flags are behaving correctly.
-
+//
+// REQUIRES: x86-registered-target
+//
// RUN: %clang_cc1 -triple i686-pc-win32 -emit-llvm %s -o - | FileCheck -check-prefix=NOINLINE %s
+// RUN: %clang_cc1 -triple i686-pc-win32 -fexperimental-new-pass-manager -emit-llvm %s -o - | FileCheck -check-prefix=NOINLINE %s
// RUN: %clang_cc1 -triple i686-pc-win32 -O3 -fno-inline-functions -emit-llvm %s -o - | FileCheck -check-prefix=NOINLINE %s
-// RUN: %clang_cc1 -triple i686-pc-win32 -finline-hint-functions -emit-llvm %s -o - | FileCheck -check-prefix=HINT %s
-// RUN: %clang_cc1 -triple i686-pc-win32 -finline-functions -emit-llvm %s -o - | FileCheck -check-prefix=INLINE %s
+// RUN: %clang_cc1 -triple i686-pc-win32 -fexperimental-new-pass-manager -O3 -fno-inline-functions -emit-llvm %s -o - | FileCheck -check-prefix=NOINLINE %s
+// RUN: %clang_cc1 -triple i686-pc-win32 -O3 -finline-hint-functions -emit-llvm %s -o - | FileCheck -check-prefix=HINT %s
+// RUN: %clang_cc1 -triple i686-pc-win32 -fexperimental-new-pass-manager -O3 -finline-hint-functions -emit-llvm %s -o - | FileCheck -check-prefix=HINT %s
+// RUN: %clang_cc1 -triple i686-pc-win32 -O3 -finline-functions -emit-llvm %s -o - | FileCheck -check-prefix=INLINE %s
+// RUN: %clang_cc1 -triple i686-pc-win32 -fexperimental-new-pass-manager -O3 -finline-functions -emit-llvm %s -o - | FileCheck -check-prefix=INLINE %s
inline int inline_hint(int a, int b) { return(a+b); }
diff --git a/test/CodeGen/inline.c b/test/CodeGen/inline.c
index fe7efe36e653..e17b251df000 100644
--- a/test/CodeGen/inline.c
+++ b/test/CodeGen/inline.c
@@ -1,5 +1,8 @@
+// REQUIRES: x86-registered-target
+//
// RUN: echo "GNU89 tests:"
-// RUN: %clang_cc1 %s -triple i386-unknown-unknown -O1 -disable-llvm-optzns -emit-llvm -o - -std=gnu89 | FileCheck %s --check-prefix=CHECK1
+// RUN: %clang_cc1 %s -triple i386-unknown-unknown -O1 -disable-llvm-passes -emit-llvm -o - -std=gnu89 | FileCheck %s --check-prefix=CHECK1
+// RUN: %clang_cc1 %s -triple i386-unknown-unknown -fexperimental-new-pass-manager -O1 -disable-llvm-passes -emit-llvm -o - -std=gnu89 | FileCheck %s --check-prefix=CHECK1
// CHECK1-LABEL: define i32 @foo()
// CHECK1-LABEL: define i32 @bar()
// CHECK1-LABEL: define void @unreferenced1()
@@ -21,7 +24,8 @@
// CHECK1-LABEL: define available_externally void @gnu_ei_inline()
// RUN: echo "C99 tests:"
-// RUN: %clang_cc1 %s -triple i386-unknown-unknown -O1 -disable-llvm-optzns -emit-llvm -o - -std=gnu99 | FileCheck %s --check-prefix=CHECK2
+// RUN: %clang_cc1 %s -triple i386-unknown-unknown -O1 -disable-llvm-passes -emit-llvm -o - -std=gnu99 | FileCheck %s --check-prefix=CHECK2
+// RUN: %clang_cc1 %s -triple i386-unknown-unknown -fexperimental-new-pass-manager -O1 -disable-llvm-passes -emit-llvm -o - -std=gnu99 | FileCheck %s --check-prefix=CHECK2
// CHECK2-LABEL: define i32 @ei()
// CHECK2-LABEL: define i32 @bar()
// CHECK2-NOT: unreferenced1
@@ -43,7 +47,8 @@
// CHECK2-LABEL: define available_externally void @gnu_ei_inline()
// RUN: echo "C++ tests:"
-// RUN: %clang_cc1 -x c++ %s -triple i386-unknown-unknown -O1 -disable-llvm-optzns -emit-llvm -o - -std=c++98 | FileCheck %s --check-prefix=CHECK3
+// RUN: %clang_cc1 -x c++ %s -triple i386-unknown-unknown -O1 -disable-llvm-passes -emit-llvm -o - -std=c++98 | FileCheck %s --check-prefix=CHECK3
+// RUN: %clang_cc1 -x c++ %s -triple i386-unknown-unknown -fexperimental-new-pass-manager -O1 -disable-llvm-passes -emit-llvm -o - -std=c++98 | FileCheck %s --check-prefix=CHECK3
// CHECK3-LABEL: define i32 @_Z3barv()
// CHECK3-LABEL: define linkonce_odr i32 @_Z3foov()
// CHECK3-NOT: unreferenced
@@ -53,7 +58,8 @@
// CHECK3-LABEL: define linkonce_odr i32 @_Z2eiv()
// RUN: echo "MS C Mode tests:"
-// RUN: %clang_cc1 %s -triple i386-pc-win32 -O1 -disable-llvm-optzns -emit-llvm -o - -std=c99 | FileCheck %s --check-prefix=CHECK4
+// 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()
diff --git a/test/CodeGen/lifetime2.c b/test/CodeGen/lifetime2.c
index ffff5cca12f0..0d22282fdd43 100644
--- a/test/CodeGen/lifetime2.c
+++ b/test/CodeGen/lifetime2.c
@@ -1,8 +1,9 @@
-// RUN: %clang -S -emit-llvm -o - -O2 %s | FileCheck %s -check-prefix=O2
-// RUN: %clang -S -emit-llvm -o - -O0 %s | FileCheck %s -check-prefix=O0
+// RUN: %clang -S -emit-llvm -o - -O2 %s | FileCheck %s -check-prefixes=CHECK,O2
+// RUN: %clang -S -emit-llvm -o - -O0 %s | FileCheck %s -check-prefixes=CHECK,O0
extern int bar(char *A, int n);
+// CHECK-LABEL: @foo
// O0-NOT: @llvm.lifetime.start
int foo (int n) {
if (n) {
@@ -15,3 +16,76 @@ int foo (int n) {
return bar(A, 2);
}
}
+
+// CHECK-LABEL: @no_goto_bypass
+void no_goto_bypass() {
+ // O2: @llvm.lifetime.start(i64 1
+ char x;
+l1:
+ bar(&x, 1);
+ // O2: @llvm.lifetime.start(i64 5
+ // O2: @llvm.lifetime.end(i64 5
+ char y[5];
+ bar(y, 5);
+ goto l1;
+ // Infinite loop
+ // O2-NOT: @llvm.lifetime.end(i64 1
+}
+
+// CHECK-LABEL: @goto_bypass
+void goto_bypass() {
+ {
+ // O2-NOT: @llvm.lifetime.start(i64 1
+ // O2-NOT: @llvm.lifetime.end(i64 1
+ char x;
+ l1:
+ bar(&x, 1);
+ }
+ goto l1;
+}
+
+// CHECK-LABEL: @no_switch_bypass
+void no_switch_bypass(int n) {
+ switch (n) {
+ case 1: {
+ // O2: @llvm.lifetime.start(i64 1
+ // O2: @llvm.lifetime.end(i64 1
+ char x;
+ bar(&x, 1);
+ break;
+ }
+ case 2:
+ n = n;
+ // O2: @llvm.lifetime.start(i64 5
+ // O2: @llvm.lifetime.end(i64 5
+ char y[5];
+ bar(y, 5);
+ break;
+ }
+}
+
+// CHECK-LABEL: @switch_bypass
+void switch_bypass(int n) {
+ switch (n) {
+ case 1:
+ n = n;
+ // O2-NOT: @llvm.lifetime.start(i64 1
+ // O2-NOT: @llvm.lifetime.end(i64 1
+ char x;
+ bar(&x, 1);
+ break;
+ case 2:
+ bar(&x, 1);
+ break;
+ }
+}
+
+// CHECK-LABEL: @indirect_jump
+void indirect_jump(int n) {
+ char x;
+ // O2-NOT: @llvm.lifetime
+ void *T[] = {&&L};
+ goto *T[n];
+L:
+ bar(&x, 1);
+}
diff --git a/test/CodeGen/lzcnt-builtins.c b/test/CodeGen/lzcnt-builtins.c
index 2f8308670bb7..cc5d458c7630 100644
--- a/test/CodeGen/lzcnt-builtins.c
+++ b/test/CodeGen/lzcnt-builtins.c
@@ -1,7 +1,5 @@
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +lzcnt -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +lzcnt -emit-llvm -o - | FileCheck %s
-// Don't include mm_malloc.h, it's system specific.
-#define __MM_MALLOC_H
#include <x86intrin.h>
diff --git a/test/CodeGen/mangle-blocks.c b/test/CodeGen/mangle-blocks.c
index 0023f53b3490..e8de92d8b400 100644
--- a/test/CodeGen/mangle-blocks.c
+++ b/test/CodeGen/mangle-blocks.c
@@ -11,13 +11,13 @@ void (^mangle(void))(void) {
};
}
-// CHECK: @__func__.__mangle_block_invoke_2 = private unnamed_addr constant [24 x i8] c"__mangle_block_invoke_2\00", align 1
+// CHECK: @__func__.__mangle_block_invoke_2 = private unnamed_addr constant [22 x i8] c"mangle_block_invoke_2\00", align 1
// CHECK: @.str = private unnamed_addr constant {{.*}}, align 1
// CHECK: @.str.1 = private unnamed_addr constant [7 x i8] c"mangle\00", align 1
// CHECK: define internal void @__mangle_block_invoke(i8* %.block_descriptor)
// CHECK: define internal void @__mangle_block_invoke_2(i8* %.block_descriptor){{.*}}{
-// CHECK: call void @__assert_rtn(i8* getelementptr inbounds ([24 x i8], [24 x i8]* @__func__.__mangle_block_invoke_2, i32 0, i32 0), i8* getelementptr inbounds {{.*}}, i32 9, i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.1, i32 0, i32 0))
+// CHECK: call void @__assert_rtn(i8* getelementptr inbounds ([22 x i8], [22 x i8]* @__func__.__mangle_block_invoke_2, i32 0, i32 0), i8* getelementptr inbounds {{.*}}, i32 9, i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.1, i32 0, i32 0))
// CHECK: }
diff --git a/test/CodeGen/may-alias.c b/test/CodeGen/may-alias.c
index 520b7abea6c1..41eda8587068 100644
--- a/test/CodeGen/may-alias.c
+++ b/test/CodeGen/may-alias.c
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -Werror -triple i386-unknown-unknown -emit-llvm -O1 -no-struct-path-tbaa -disable-llvm-optzns -o - %s | FileCheck %s
-// RUN: %clang_cc1 -Werror -triple i386-unknown-unknown -emit-llvm -O1 -disable-llvm-optzns -o - %s | FileCheck %s -check-prefix=PATH
+// 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
// Types with the may_alias attribute should be considered equivalent
// to char for aliasing.
diff --git a/test/CodeGen/mcount.c b/test/CodeGen/mcount.c
index 99dc90795b5e..7f915841952e 100644
--- a/test/CodeGen/mcount.c
+++ b/test/CodeGen/mcount.c
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -pg -triple i386-unknown-unknown -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -pg -triple i386-unknown-unknown -emit-llvm -O2 -o - %s | FileCheck %s
// RUN: %clang_cc1 -pg -triple powerpc-unknown-gnu-linux -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-PREFIXED %s
// RUN: %clang_cc1 -pg -triple powerpc64-unknown-gnu-linux -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-PREFIXED %s
// RUN: %clang_cc1 -pg -triple powerpc64le-unknown-gnu-linux -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-PREFIXED %s
@@ -12,7 +13,20 @@
// RUN: %clang_cc1 -pg -triple powerpc64le-netbsd -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-PREFIXED %s
// RUN: %clang_cc1 -pg -triple sparc-netbsd -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-PREFIXED %s
// RUN: %clang_cc1 -pg -triple sparc64-netbsd -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-PREFIXED %s
-void foo(void) {
-// CHECK: call void @mcount()
-// CHECK-PREFIXED: call void @_mcount()
+// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s -check-prefix=NO-MCOUNT
+
+int bar(void) {
+ return 0;
}
+
+int foo(void) {
+ return bar();
+}
+
+int main(void) {
+ return foo();
+}
+
+// CHECK: attributes #{{[0-9]+}} = { {{.*}}"counting-function"="mcount"{{.*}} }
+// CHECK-PREFIXED: attributes #{{[0-9]+}} = { {{.*}}"counting-function"="_mcount"{{.*}} }
+// NO-MCOUNT-NOT: attributes #{{[0-9]}} = { {{.*}}"counting-function"={{.*}} }
diff --git a/test/CodeGen/mips16-attr.c b/test/CodeGen/mips16-attr.c
index 18799be6f0d7..128a1bdb8ebd 100644
--- a/test/CodeGen/mips16-attr.c
+++ b/test/CodeGen/mips16-attr.c
@@ -11,7 +11,7 @@ void __attribute__((nomips16)) nofoo (void) {
// CHECK: define void @nofoo() [[NOMIPS16:#[0-9]+]]
-// CHECK: attributes [[MIPS16]] = { nounwind {{.*}} "mips16" {{.*}} }
+// CHECK: attributes [[MIPS16]] = { noinline nounwind {{.*}} "mips16" {{.*}} }
-// CHECK: attributes [[NOMIPS16]] = { nounwind {{.*}} "nomips16" {{.*}} }
+// CHECK: attributes [[NOMIPS16]] = { noinline nounwind {{.*}} "nomips16" {{.*}} }
diff --git a/test/CodeGen/mmx-builtins.c b/test/CodeGen/mmx-builtins.c
index 2bf497d58aaf..ddc6f66548ae 100644
--- a/test/CodeGen/mmx-builtins.c
+++ b/test/CodeGen/mmx-builtins.c
@@ -1,8 +1,6 @@
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +ssse3 -emit-llvm -o - -Werror | FileCheck %s
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +ssse3 -fno-signed-char -emit-llvm -o - -Werror | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +ssse3 -emit-llvm -o - -Wall -Werror | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +ssse3 -fno-signed-char -emit-llvm -o - -Wall -Werror | FileCheck %s
-// Don't include mm_malloc.h, it's system specific.
-#define __MM_MALLOC_H
#include <x86intrin.h>
diff --git a/test/CodeGen/mozilla-ms-inline-asm.c b/test/CodeGen/mozilla-ms-inline-asm.c
index b8b7a2d677dd..3335a87fefe5 100644
--- a/test/CodeGen/mozilla-ms-inline-asm.c
+++ b/test/CodeGen/mozilla-ms-inline-asm.c
@@ -20,7 +20,7 @@ void invoke(void* that, unsigned methodIndex,
// CHECK: call void asm sideeffect inteldialect
// CHECK: mov edx,dword ptr $1
// CHECK: test edx,edx
-// CHECK: jz {{[^_]*}}__MSASMLABEL_.0__noparams
+// CHECK: jz {{[^_]*}}__MSASMLABEL_.${:uid}__noparams
// ^ Can't use {{.*}} here because the matching is greedy.
// CHECK: mov eax,edx
// CHECK: shl eax,$$3
@@ -28,7 +28,7 @@ void invoke(void* that, unsigned methodIndex,
// CHECK: mov ecx,esp
// CHECK: push dword ptr $0
// CHECK: call dword ptr $2
-// CHECK: {{.*}}__MSASMLABEL_.0__noparams:
+// CHECK: {{.*}}__MSASMLABEL_.${:uid}__noparams:
// CHECK: mov ecx,dword ptr $3
// CHECK: push ecx
// CHECK: mov edx,[ecx]
diff --git a/test/CodeGen/mrtd.c b/test/CodeGen/mrtd.c
index 8d2aeeec49df..e526e0ba0041 100644
--- a/test/CodeGen/mrtd.c
+++ b/test/CodeGen/mrtd.c
@@ -25,4 +25,4 @@ void quux(int a1, int a2, int a3) {
// CHECK-LABEL: define x86_stdcallcc void @quux
// CHECK: call void (i32, ...) @qux
-// CHECK: attributes [[NUW]] = { nounwind{{.*}} }
+// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} }
diff --git a/test/CodeGen/ms-barriers-intrinsics.c b/test/CodeGen/ms-barriers-intrinsics.c
new file mode 100644
index 000000000000..b0dfc3042a6e
--- /dev/null
+++ b/test/CodeGen/ms-barriers-intrinsics.c
@@ -0,0 +1,39 @@
+// RUN: %clang_cc1 -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \
+// RUN: -triple i686--windows -emit-llvm %s -o - \
+// RUN: | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-I386
+// RUN: %clang_cc1 -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \
+// RUN: -triple x86_64--windows -emit-llvm %s -o - \
+// RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-X64
+
+// intrin.h needs size_t, but -ffreestanding prevents us from getting it from
+// stddef.h. Work around it with this typedef.
+typedef __SIZE_TYPE__ size_t;
+
+#include <intrin.h>
+
+void test_ReadWriteBarrier() { _ReadWriteBarrier(); }
+// CHECK-LABEL: define void @test_ReadWriteBarrier
+// CHECK: fence singlethread seq_cst
+// CHECK: ret void
+// CHECK: }
+
+void test_ReadBarrier() { _ReadBarrier(); }
+// CHECK-LABEL: define void @test_ReadBarrier
+// CHECK: fence singlethread seq_cst
+// CHECK: ret void
+// CHECK: }
+
+void test_WriteBarrier() { _WriteBarrier(); }
+// CHECK-LABEL: define void @test_WriteBarrier
+// CHECK: fence singlethread seq_cst
+// CHECK: ret void
+// CHECK: }
+
+#if defined(__x86_64__)
+void test__faststorefence() { __faststorefence(); }
+// CHECK-X64-LABEL: define void @test__faststorefence
+// CHECK-X64: fence seq_cst
+// CHECK-X64: ret void
+// CHECK-X64: }
+#endif
+
diff --git a/test/CodeGen/ms-declspecs.c b/test/CodeGen/ms-declspecs.c
index 91f5aa210485..4842050e5be5 100644
--- a/test/CodeGen/ms-declspecs.c
+++ b/test/CodeGen/ms-declspecs.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple i386-pc-win32 %s -emit-llvm -fms-compatibility -o - | FileCheck %s
+// RUN: %clang_cc1 -triple i386-pc-win32 %s -emit-llvm -fms-compatibility -O2 -disable-llvm-optzns -o - | FileCheck %s
__declspec(selectany) int x1 = 1;
const __declspec(selectany) int x2 = 2;
diff --git a/test/CodeGen/ms-inline-asm.c b/test/CodeGen/ms-inline-asm.c
index ad9e4f361b70..6efc09aec51d 100644
--- a/test/CodeGen/ms-inline-asm.c
+++ b/test/CodeGen/ms-inline-asm.c
@@ -47,7 +47,7 @@ void t6(void) {
void t7() {
__asm {
- int 0x2c ; } asm comments are fun! }{
+ int 0x2cU ; } asm comments are fun! }{
}
__asm {
{
@@ -56,7 +56,7 @@ void t7() {
}
__asm {}
// CHECK: t7
-// CHECK: call void asm sideeffect inteldialect "int $$0x2c", "~{dirflag},~{fpsr},~{flags}"()
+// CHECK: call void asm sideeffect inteldialect "int $$0x2cU", "~{dirflag},~{fpsr},~{flags}"()
// CHECK: call void asm sideeffect inteldialect "", "~{dirflag},~{fpsr},~{flags}"()
}
@@ -171,8 +171,8 @@ void t17() {
// CHECK: t17
__asm _emit 0x4A
// CHECK: .byte 0x4A
- __asm _emit 0x43
-// CHECK: .byte 0x43
+ __asm _emit 0x43L
+// CHECK: .byte 0x43L
__asm _emit 0x4B
// CHECK: .byte 0x4B
__asm _EMIT 0x4B
@@ -219,11 +219,11 @@ void t20() {
void t21() {
__asm {
__asm push ebx
- __asm mov ebx, 0x07
+ __asm mov ebx, 07H
__asm pop ebx
}
// CHECK: t21
-// CHECK: call void asm sideeffect inteldialect "push ebx\0A\09mov ebx, $$0x07\0A\09pop ebx", "~{ebx},~{esp},~{dirflag},~{fpsr},~{flags}"()
+// CHECK: call void asm sideeffect inteldialect "push ebx\0A\09mov ebx, $$07H\0A\09pop ebx", "~{ebx},~{esp},~{dirflag},~{fpsr},~{flags}"()
}
extern void t22_helper(int x);
@@ -249,7 +249,7 @@ void t23() {
the_label:
}
// CHECK: t23
-// CHECK: call void asm sideeffect inteldialect "{{.*}}__MSASMLABEL_.0__the_label:", "~{dirflag},~{fpsr},~{flags}"()
+// CHECK: call void asm sideeffect inteldialect "{{.*}}__MSASMLABEL_.${:uid}__the_label:", "~{dirflag},~{fpsr},~{flags}"()
}
void t24_helper(void) {}
@@ -262,15 +262,15 @@ void t24() {
void t25() {
// CHECK: t25
__asm mov eax, 0ffffffffh
-// CHECK: mov eax, $$4294967295
- __asm mov eax, 0fh
+// CHECK: mov eax, $$0ffffffffh
+ __asm mov eax, 0fhU
// CHECK: mov eax, $$15
__asm mov eax, 0a2h
+// CHECK: mov eax, $$0a2h
+ __asm mov eax, 10100010b
+// CHECK: mov eax, $$10100010b
+ __asm mov eax, 10100010BU
// CHECK: mov eax, $$162
- __asm mov eax, 0xa2h
-// CHECK: mov eax, $$0xa2h
- __asm mov eax, 0xa2
-// CHECK: mov eax, $$0xa2
// CHECK: "~{eax},~{dirflag},~{fpsr},~{flags}"()
}
@@ -595,7 +595,7 @@ void label1() {
jmp label
}
// CHECK-LABEL: define void @label1()
- // CHECK: call void asm sideeffect inteldialect "{{.*}}__MSASMLABEL_.1__label:\0A\09jmp {{.*}}__MSASMLABEL_.1__label", "~{dirflag},~{fpsr},~{flags}"() [[ATTR1:#[0-9]+]]
+ // CHECK: call void asm sideeffect inteldialect "{{.*}}__MSASMLABEL_.${:uid}__label:\0A\09jmp {{.*}}__MSASMLABEL_.${:uid}__label", "~{dirflag},~{fpsr},~{flags}"() [[ATTR1:#[0-9]+]]
}
void label2() {
@@ -604,7 +604,7 @@ void label2() {
label:
}
// CHECK-LABEL: define void @label2
- // CHECK: call void asm sideeffect inteldialect "jmp {{.*}}__MSASMLABEL_.2__label\0A\09{{.*}}__MSASMLABEL_.2__label:", "~{dirflag},~{fpsr},~{flags}"()
+ // CHECK: call void asm sideeffect inteldialect "jmp {{.*}}__MSASMLABEL_.${:uid}__label\0A\09{{.*}}__MSASMLABEL_.${:uid}__label:", "~{dirflag},~{fpsr},~{flags}"()
}
void label3() {
@@ -613,7 +613,7 @@ void label3() {
mov eax, label
}
// CHECK-LABEL: define void @label3
- // CHECK: call void asm sideeffect inteldialect "{{.*}}__MSASMLABEL_.3__label:\0A\09mov eax, {{.*}}__MSASMLABEL_.3__label", "~{eax},~{dirflag},~{fpsr},~{flags}"()
+ // CHECK: call void asm sideeffect inteldialect "{{.*}}__MSASMLABEL_.${:uid}__label:\0A\09mov eax, {{.*}}__MSASMLABEL_.${:uid}__label", "~{eax},~{dirflag},~{fpsr},~{flags}"()
}
void label4() {
@@ -622,7 +622,7 @@ void label4() {
mov eax, [label]
}
// CHECK-LABEL: define void @label4
- // CHECK: call void asm sideeffect inteldialect "{{.*}}__MSASMLABEL_.4__label:\0A\09mov eax, {{.*}}__MSASMLABEL_.4__label", "~{eax},~{dirflag},~{fpsr},~{flags}"()
+ // CHECK: call void asm sideeffect inteldialect "{{.*}}__MSASMLABEL_.${:uid}__label:\0A\09mov eax, {{.*}}__MSASMLABEL_.${:uid}__label", "~{eax},~{dirflag},~{fpsr},~{flags}"()
}
void label5() {
@@ -631,7 +631,16 @@ void label5() {
dollar_label$:
}
// CHECK-LABEL: define void @label5
- // CHECK: call void asm sideeffect inteldialect "jmp {{.*}}__MSASMLABEL_.5__dollar_label$$\0A\09{{.*}}__MSASMLABEL_.5__dollar_label$$:", "~{dirflag},~{fpsr},~{flags}"()
+ // CHECK: call void asm sideeffect inteldialect "jmp {{.*}}__MSASMLABEL_.${:uid}__dollar_label$$\0A\09{{.*}}__MSASMLABEL_.${:uid}__dollar_label$$:", "~{dirflag},~{fpsr},~{flags}"()
+}
+
+void label6(){
+ __asm {
+ jmp short label
+ label:
+ }
+ // CHECK-LABEL: define void @label6
+ // CHECK: call void asm sideeffect inteldialect "jmp {{.*}}__MSASMLABEL_.${:uid}__label\0A\09{{.*}}__MSASMLABEL_.${:uid}__label:", "~{dirflag},~{fpsr},~{flags}"()
}
typedef union _LARGE_INTEGER {
@@ -653,4 +662,6 @@ int test_indirect_field(LARGE_INTEGER LargeInteger) {
// CHECK: call i32 asm sideeffect inteldialect "mov eax, dword ptr $1",
// MS ASM containing labels must not be duplicated (PR23715).
-// CHECK: attributes [[ATTR1]] = { {{.*}}noduplicate{{.*}} }
+// CHECK: attributes [[ATTR1]] = {
+// CHECK-NOT: noduplicate
+// CHECK-SAME: }{{$}}
diff --git a/test/CodeGen/ms-inline-asm.cpp b/test/CodeGen/ms-inline-asm.cpp
index 123a0e3d6d3d..424c1992cc2c 100644
--- a/test/CodeGen/ms-inline-asm.cpp
+++ b/test/CodeGen/ms-inline-asm.cpp
@@ -126,14 +126,14 @@ void t7_using() {
void t8() {
__asm some_label:
// CHECK-LABEL: define void @_Z2t8v()
- // CHECK: call void asm sideeffect inteldialect "L__MSASMLABEL_.1__some_label:", "~{dirflag},~{fpsr},~{flags}"()
+ // CHECK: call void asm sideeffect inteldialect "L__MSASMLABEL_.${:uid}__some_label:", "~{dirflag},~{fpsr},~{flags}"()
struct A {
static void g() {
__asm jmp some_label ; This should jump forwards
__asm some_label:
__asm nop
// CHECK-LABEL: define internal void @_ZZ2t8vEN1A1gEv()
- // CHECK: call void asm sideeffect inteldialect "jmp L__MSASMLABEL_.2__some_label\0A\09L__MSASMLABEL_.2__some_label:\0A\09nop", "~{dirflag},~{fpsr},~{flags}"()
+ // CHECK: call void asm sideeffect inteldialect "jmp L__MSASMLABEL_.${:uid}__some_label\0A\09L__MSASMLABEL_.${:uid}__some_label:\0A\09nop", "~{dirflag},~{fpsr},~{flags}"()
}
};
A::g();
diff --git a/test/CodeGen/ms-intrinsics-rotations.c b/test/CodeGen/ms-intrinsics-rotations.c
new file mode 100644
index 000000000000..65d25cbe85eb
--- /dev/null
+++ b/test/CodeGen/ms-intrinsics-rotations.c
@@ -0,0 +1,181 @@
+// RUN: %clang_cc1 -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \
+// RUN: -triple i686--windows -emit-llvm %s -o - \
+// RUN: | FileCheck %s --check-prefixes CHECK,CHECK-32BIT-LONG
+// RUN: %clang_cc1 -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \
+// RUN: -triple thumbv7--windows -emit-llvm %s -o - \
+// RUN: | FileCheck %s --check-prefixes CHECK,CHECK-32BIT-LONG
+// RUN: %clang_cc1 -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \
+// RUN: -triple x86_64--windows -emit-llvm %s -o - \
+// RUN: | FileCheck %s --check-prefixes CHECK,CHECK-32BIT-LONG
+// RUN: %clang_cc1 -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \
+// RUN: -triple i686--linux -emit-llvm %s -o - \
+// RUN: | FileCheck %s --check-prefixes CHECK,CHECK-32BIT-LONG
+// RUN: %clang_cc1 -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \
+// RUN: -triple x86_64--linux -emit-llvm %s -o - \
+// RUN: | FileCheck %s --check-prefixes CHECK,CHECK-64BIT-LONG
+
+// rotate left
+
+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: ret i8 [[RESULT]]
+// CHECK }
+
+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: ret i16 [[RESULT]]
+// CHECK }
+
+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: ret i32 [[RESULT]]
+// CHECK }
+
+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: ret i32 [[RESULT]]
+// CHECK-32BIT-LONG }
+
+// CHECK-64BIT-LONG: i64 @test_lrotl
+// CHECK-64BIT-LONG: [[SHIFT:%[0-9]+]] = and i64 %{{[0-9]+}}, 63
+// CHECK-64BIT-LONG: [[NEGSHIFT:%[0-9]+]] = sub i64 64, [[SHIFT]]
+// CHECK-64BIT-LONG: [[HIGH:%[0-9]+]] = shl i64 [[VALUE:%[0-9]+]], [[SHIFT]]
+// CHECK-64BIT-LONG: [[LOW:%[0-9]+]] = lshr i64 [[VALUE]], [[NEGSHIFT]]
+// CHECK-64BIT-LONG: [[ROTATED:%[0-9]+]] = or i64 [[HIGH]], [[LOW]]
+// CHECK-64BIT-LONG: [[ISZERO:%[0-9]+]] = icmp eq i64 [[SHIFT]], 0
+// CHECK-64BIT-LONG: [[RESULT:%[0-9]+]] = select i1 [[ISZERO]], i64 [[VALUE]], i64 [[ROTATED]]
+// CHECK-64BIT-LONG: ret i64 [[RESULT]]
+// CHECK-64BIT-LONG }
+
+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: ret i64 [[RESULT]]
+// CHECK }
+
+// rotate right
+
+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 }
+
+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 }
+
+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: ret i32 [[RESULT]]
+// CHECK }
+
+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: ret i32 [[RESULT]]
+// CHECK-32BIT-LONG }
+
+// CHECK-64BIT-LONG: i64 @test_lrotr
+// CHECK-64BIT-LONG: [[SHIFT:%[0-9]+]] = and i64 %{{[0-9]+}}, 63
+// CHECK-64BIT-LONG: [[NEGSHIFT:%[0-9]+]] = sub i64 64, [[SHIFT]]
+// CHECK-64BIT-LONG: [[LOW:%[0-9]+]] = lshr i64 [[VALUE:%[0-9]+]], [[SHIFT]]
+// CHECK-64BIT-LONG: [[HIGH:%[0-9]+]] = shl i64 [[VALUE]], [[NEGSHIFT]]
+// CHECK-64BIT-LONG: [[ROTATED:%[0-9]+]] = or i64 [[HIGH]], [[LOW]]
+// CHECK-64BIT-LONG: [[ISZERO:%[0-9]+]] = icmp eq i64 [[SHIFT]], 0
+// CHECK-64BIT-LONG: [[RESULT:%[0-9]+]] = select i1 [[ISZERO]], i64 [[VALUE]], i64 [[ROTATED]]
+// CHECK-64BIT-LONG: ret i64 [[RESULT]]
+// CHECK-64BIT-LONG }
+
+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: ret i64 [[RESULT]]
+// CHECK }
diff --git a/test/CodeGen/ms-intrinsics.c b/test/CodeGen/ms-intrinsics.c
index ceaa847e9987..25eae44e0272 100644
--- a/test/CodeGen/ms-intrinsics.c
+++ b/test/CodeGen/ms-intrinsics.c
@@ -1,12 +1,12 @@
// RUN: %clang_cc1 -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \
// RUN: -triple i686--windows -Oz -emit-llvm %s -o - \
-// RUN: | FileCheck %s -check-prefix CHECK -check-prefix CHECK-I386
+// RUN: | FileCheck %s -check-prefixes CHECK,CHECK-I386,CHECK-INTEL
// RUN: %clang_cc1 -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \
// RUN: -triple thumbv7--windows -Oz -emit-llvm %s -o - \
-// RUN: | FileCheck %s
+// RUN: | FileCheck %s --check-prefixes CHECK,CHECK-ARM-X64
// RUN: %clang_cc1 -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \
// RUN: -triple x86_64--windows -Oz -emit-llvm %s -o - \
-// RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-X64
+// RUN: | FileCheck %s --check-prefixes CHECK,CHECK-X64,CHECK-ARM-X64,CHECK-INTEL
// intrin.h needs size_t, but -ffreestanding prevents us from getting it from
// stddef.h. Work around it with this typedef.
@@ -14,6 +14,100 @@ typedef __SIZE_TYPE__ size_t;
#include <intrin.h>
+#if defined(__i386__) || defined(__x86_64__)
+void test__stosb(unsigned char *Dest, unsigned char Data, size_t Count) {
+ return __stosb(Dest, Data, 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: 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: ret void
+// CHECK-X64: }
+#endif
+
+void *test_ReturnAddress() {
+ return _ReturnAddress();
+}
+// CHECK-LABEL: define{{.*}}i8* @test_ReturnAddress()
+// CHECK: = tail call i8* @llvm.returnaddress(i32 0)
+// CHECK: ret i8*
+
+#if defined(__i386__) || defined(__x86_64__)
+void *test_AddressOfReturnAddress() {
+ return _AddressOfReturnAddress();
+}
+// CHECK-INTEL-LABEL: define i8* @test_AddressOfReturnAddress()
+// CHECK-INTEL: = tail call i8* @llvm.addressofreturnaddress()
+// CHECK-INTEL: ret i8*
+#endif
+
+unsigned char test_BitScanForward(unsigned long *Index, unsigned long Mask) {
+ return _BitScanForward(Index, Mask);
+}
+// CHECK: define{{.*}}i8 @test_BitScanForward(i32* {{[a-z_ ]*}}%Index, i32 {{[a-z_ ]*}}%Mask){{.*}}{
+// CHECK: [[ISNOTZERO:%[a-z0-9._]+]] = icmp eq i32 %Mask, 0
+// CHECK: br i1 [[ISNOTZERO]], label %[[END_LABEL:[a-z0-9._]+]], label %[[ISNOTZERO_LABEL:[a-z0-9._]+]]
+// CHECK: [[END_LABEL]]:
+// CHECK: [[RESULT:%[a-z0-9._]+]] = phi i8 [ 0, %[[ISZERO_LABEL:[a-z0-9._]+]] ], [ 1, %[[ISNOTZERO_LABEL]] ]
+// CHECK: ret i8 [[RESULT]]
+// CHECK: [[ISNOTZERO_LABEL]]:
+// CHECK: [[INDEX:%[0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %Mask, i1 true)
+// CHECK: store i32 [[INDEX]], i32* %Index, align 4
+// CHECK: br label %[[END_LABEL]]
+
+unsigned char test_BitScanReverse(unsigned long *Index, unsigned long Mask) {
+ return _BitScanReverse(Index, Mask);
+}
+// CHECK: define{{.*}}i8 @test_BitScanReverse(i32* {{[a-z_ ]*}}%Index, i32 {{[a-z_ ]*}}%Mask){{.*}}{
+// CHECK: [[ISNOTZERO:%[0-9]+]] = icmp eq i32 %Mask, 0
+// CHECK: br i1 [[ISNOTZERO]], label %[[END_LABEL:[a-z0-9._]+]], label %[[ISNOTZERO_LABEL:[a-z0-9._]+]]
+// CHECK: [[END_LABEL]]:
+// CHECK: [[RESULT:%[a-z0-9._]+]] = phi i8 [ 0, %[[ISZERO_LABEL:[a-z0-9._]+]] ], [ 1, %[[ISNOTZERO_LABEL]] ]
+// CHECK: ret i8 [[RESULT]]
+// CHECK: [[ISNOTZERO_LABEL]]:
+// CHECK: [[REVINDEX:%[0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %Mask, i1 true)
+// CHECK: [[INDEX:%[0-9]+]] = xor i32 [[REVINDEX]], 31
+// CHECK: store i32 [[INDEX]], i32* %Index, align 4
+// CHECK: br label %[[END_LABEL]]
+
+#if defined(__x86_64__) || defined(__arm__)
+unsigned char test_BitScanForward64(unsigned long *Index, unsigned __int64 Mask) {
+ return _BitScanForward64(Index, Mask);
+}
+// CHECK-ARM-X64: define{{.*}}i8 @test_BitScanForward64(i32* {{[a-z_ ]*}}%Index, i64 {{[a-z_ ]*}}%Mask){{.*}}{
+// CHECK-ARM-X64: [[ISNOTZERO:%[a-z0-9._]+]] = icmp eq i64 %Mask, 0
+// CHECK-ARM-X64: br i1 [[ISNOTZERO]], label %[[END_LABEL:[a-z0-9._]+]], label %[[ISNOTZERO_LABEL:[a-z0-9._]+]]
+// CHECK-ARM-X64: [[END_LABEL]]:
+// CHECK-ARM-X64: [[RESULT:%[a-z0-9._]+]] = phi i8 [ 0, %[[ISZERO_LABEL:[a-z0-9._]+]] ], [ 1, %[[ISNOTZERO_LABEL]] ]
+// CHECK-ARM-X64: ret i8 [[RESULT]]
+// CHECK-ARM-X64: [[ISNOTZERO_LABEL]]:
+// CHECK-ARM-X64: [[INDEX:%[0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %Mask, i1 true)
+// CHECK-ARM-X64: [[TRUNC_INDEX:%[0-9]+]] = trunc i64 [[INDEX]] to i32
+// CHECK-ARM-X64: store i32 [[TRUNC_INDEX]], i32* %Index, align 4
+// CHECK-ARM-X64: br label %[[END_LABEL]]
+
+unsigned char test_BitScanReverse64(unsigned long *Index, unsigned __int64 Mask) {
+ return _BitScanReverse64(Index, Mask);
+}
+// CHECK-ARM-X64: define{{.*}}i8 @test_BitScanReverse64(i32* {{[a-z_ ]*}}%Index, i64 {{[a-z_ ]*}}%Mask){{.*}}{
+// CHECK-ARM-X64: [[ISNOTZERO:%[0-9]+]] = icmp eq i64 %Mask, 0
+// CHECK-ARM-X64: br i1 [[ISNOTZERO]], label %[[END_LABEL:[a-z0-9._]+]], label %[[ISNOTZERO_LABEL:[a-z0-9._]+]]
+// CHECK-ARM-X64: [[END_LABEL]]:
+// CHECK-ARM-X64: [[RESULT:%[a-z0-9._]+]] = phi i8 [ 0, %[[ISZERO_LABEL:[a-z0-9._]+]] ], [ 1, %[[ISNOTZERO_LABEL]] ]
+// CHECK-ARM-X64: ret i8 [[RESULT]]
+// CHECK-ARM-X64: [[ISNOTZERO_LABEL]]:
+// CHECK-ARM-X64: [[REVINDEX:%[0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %Mask, i1 true)
+// CHECK-ARM-X64: [[TRUNC_REVINDEX:%[0-9]+]] = trunc i64 [[REVINDEX]] to i32
+// CHECK-ARM-X64: [[INDEX:%[0-9]+]] = xor i32 [[TRUNC_REVINDEX]], 63
+// CHECK-ARM-X64: store i32 [[INDEX]], i32* %Index, align 4
+// CHECK-ARM-X64: br label %[[END_LABEL]]
+#endif
+
void *test_InterlockedExchangePointer(void * volatile *Target, void *Value) {
return _InterlockedExchangePointer(Target, Value);
}
@@ -41,33 +135,287 @@ void *test_InterlockedCompareExchangePointer(void * volatile *Destination,
// CHECK: ret i8* %[[RESULT:[0-9]+]]
// CHECK: }
-long test_InterlockedExchange(long *Target, long Value) {
- return _InterlockedExchange(Target, Value);
+char test_InterlockedExchange8(char volatile *value, char mask) {
+ return _InterlockedExchange8(value, mask);
}
+// CHECK: define{{.*}}i8 @test_InterlockedExchange8(i8*{{[a-z_ ]*}}%value, i8{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK: [[RESULT:%[0-9]+]] = atomicrmw xchg i8* %value, i8 %mask seq_cst
+// CHECK: ret i8 [[RESULT:%[0-9]+]]
+// CHECK: }
-// CHECK: define{{.*}}i32 @test_InterlockedExchange(i32* {{[a-z_ ]*}}%Target, i32 %Value){{.*}}{
-// CHECK: %[[EXCHANGE:[0-9]+]] = atomicrmw xchg i32* %Target, i32 %Value seq_cst
-// CHECK: ret i32 %[[EXCHANGE:[0-9]+]]
+short test_InterlockedExchange16(short volatile *value, short mask) {
+ return _InterlockedExchange16(value, mask);
+}
+// CHECK: define{{.*}}i16 @test_InterlockedExchange16(i16*{{[a-z_ ]*}}%value, i16{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK: [[RESULT:%[0-9]+]] = atomicrmw xchg i16* %value, i16 %mask seq_cst
+// CHECK: ret i16 [[RESULT:%[0-9]+]]
// CHECK: }
-#if defined(__i386__)
-long test__readfsdword(unsigned long Offset) {
- return __readfsdword(Offset);
+long test_InterlockedExchange(long volatile *value, long mask) {
+ return _InterlockedExchange(value, mask);
}
+// CHECK: define{{.*}}i32 @test_InterlockedExchange(i32*{{[a-z_ ]*}}%value, i32{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK: [[RESULT:%[0-9]+]] = atomicrmw xchg i32* %value, i32 %mask seq_cst
+// CHECK: ret i32 [[RESULT:%[0-9]+]]
+// CHECK: }
-// CHECK-I386: define 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]+]]
-// CHECK-I386: }
-#endif
+char test_InterlockedExchangeAdd8(char volatile *value, char mask) {
+ return _InterlockedExchangeAdd8(value, mask);
+}
+// CHECK: define{{.*}}i8 @test_InterlockedExchangeAdd8(i8*{{[a-z_ ]*}}%value, i8{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK: [[RESULT:%[0-9]+]] = atomicrmw add i8* %value, i8 %mask seq_cst
+// CHECK: ret i8 [[RESULT:%[0-9]+]]
+// CHECK: }
-#if defined(__x86_64__)
-unsigned __int64 test__umulh(unsigned __int64 a, unsigned __int64 b) {
- return __umulh(a, b);
+short test_InterlockedExchangeAdd16(short volatile *value, short mask) {
+ return _InterlockedExchangeAdd16(value, mask);
}
-// CHECK-X64-LABEL: define i64 @test__umulh(i64 %a, i64 %b)
-// CHECK-X64: = mul nuw i128 %
+// CHECK: define{{.*}}i16 @test_InterlockedExchangeAdd16(i16*{{[a-z_ ]*}}%value, i16{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK: [[RESULT:%[0-9]+]] = atomicrmw add i16* %value, i16 %mask seq_cst
+// CHECK: ret i16 [[RESULT:%[0-9]+]]
+// CHECK: }
-#endif
+long test_InterlockedExchangeAdd(long volatile *value, long mask) {
+ return _InterlockedExchangeAdd(value, mask);
+}
+// CHECK: define{{.*}}i32 @test_InterlockedExchangeAdd(i32*{{[a-z_ ]*}}%value, i32{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK: [[RESULT:%[0-9]+]] = atomicrmw add i32* %value, i32 %mask seq_cst
+// CHECK: ret i32 [[RESULT:%[0-9]+]]
+// CHECK: }
+
+char test_InterlockedExchangeSub8(char volatile *value, char mask) {
+ return _InterlockedExchangeSub8(value, mask);
+}
+// CHECK: define{{.*}}i8 @test_InterlockedExchangeSub8(i8*{{[a-z_ ]*}}%value, i8{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK: [[RESULT:%[0-9]+]] = atomicrmw sub i8* %value, i8 %mask seq_cst
+// CHECK: ret i8 [[RESULT:%[0-9]+]]
+// CHECK: }
+
+short test_InterlockedExchangeSub16(short volatile *value, short mask) {
+ return _InterlockedExchangeSub16(value, mask);
+}
+// CHECK: define{{.*}}i16 @test_InterlockedExchangeSub16(i16*{{[a-z_ ]*}}%value, i16{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK: [[RESULT:%[0-9]+]] = atomicrmw sub i16* %value, i16 %mask seq_cst
+// CHECK: ret i16 [[RESULT:%[0-9]+]]
+// CHECK: }
+
+long test_InterlockedExchangeSub(long volatile *value, long mask) {
+ return _InterlockedExchangeSub(value, mask);
+}
+// CHECK: define{{.*}}i32 @test_InterlockedExchangeSub(i32*{{[a-z_ ]*}}%value, i32{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK: [[RESULT:%[0-9]+]] = atomicrmw sub i32* %value, i32 %mask seq_cst
+// CHECK: ret i32 [[RESULT:%[0-9]+]]
+// CHECK: }
+
+char test_InterlockedOr8(char volatile *value, char mask) {
+ return _InterlockedOr8(value, mask);
+}
+// CHECK: define{{.*}}i8 @test_InterlockedOr8(i8*{{[a-z_ ]*}}%value, i8{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK: [[RESULT:%[0-9]+]] = atomicrmw or i8* %value, i8 %mask seq_cst
+// CHECK: ret i8 [[RESULT:%[0-9]+]]
+// CHECK: }
+
+short test_InterlockedOr16(short volatile *value, short mask) {
+ return _InterlockedOr16(value, mask);
+}
+// CHECK: define{{.*}}i16 @test_InterlockedOr16(i16*{{[a-z_ ]*}}%value, i16{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK: [[RESULT:%[0-9]+]] = atomicrmw or i16* %value, i16 %mask seq_cst
+// CHECK: ret i16 [[RESULT:%[0-9]+]]
+// CHECK: }
+
+long test_InterlockedOr(long volatile *value, long mask) {
+ return _InterlockedOr(value, mask);
+}
+// CHECK: define{{.*}}i32 @test_InterlockedOr(i32*{{[a-z_ ]*}}%value, i32{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK: [[RESULT:%[0-9]+]] = atomicrmw or i32* %value, i32 %mask seq_cst
+// CHECK: ret i32 [[RESULT:%[0-9]+]]
+// CHECK: }
+
+char test_InterlockedXor8(char volatile *value, char mask) {
+ return _InterlockedXor8(value, mask);
+}
+// CHECK: define{{.*}}i8 @test_InterlockedXor8(i8*{{[a-z_ ]*}}%value, i8{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK: [[RESULT:%[0-9]+]] = atomicrmw xor i8* %value, i8 %mask seq_cst
+// CHECK: ret i8 [[RESULT:%[0-9]+]]
+// CHECK: }
+
+short test_InterlockedXor16(short volatile *value, short mask) {
+ return _InterlockedXor16(value, mask);
+}
+// CHECK: define{{.*}}i16 @test_InterlockedXor16(i16*{{[a-z_ ]*}}%value, i16{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK: [[RESULT:%[0-9]+]] = atomicrmw xor i16* %value, i16 %mask seq_cst
+// CHECK: ret i16 [[RESULT:%[0-9]+]]
+// CHECK: }
+
+long test_InterlockedXor(long volatile *value, long mask) {
+ return _InterlockedXor(value, mask);
+}
+// CHECK: define{{.*}}i32 @test_InterlockedXor(i32*{{[a-z_ ]*}}%value, i32{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK: [[RESULT:%[0-9]+]] = atomicrmw xor i32* %value, i32 %mask seq_cst
+// CHECK: ret i32 [[RESULT:%[0-9]+]]
+// CHECK: }
+
+char test_InterlockedAnd8(char volatile *value, char mask) {
+ return _InterlockedAnd8(value, mask);
+}
+// CHECK: define{{.*}}i8 @test_InterlockedAnd8(i8*{{[a-z_ ]*}}%value, i8{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK: [[RESULT:%[0-9]+]] = atomicrmw and i8* %value, i8 %mask seq_cst
+// CHECK: ret i8 [[RESULT:%[0-9]+]]
+// CHECK: }
+
+short test_InterlockedAnd16(short volatile *value, short mask) {
+ return _InterlockedAnd16(value, mask);
+}
+// CHECK: define{{.*}}i16 @test_InterlockedAnd16(i16*{{[a-z_ ]*}}%value, i16{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK: [[RESULT:%[0-9]+]] = atomicrmw and i16* %value, i16 %mask seq_cst
+// CHECK: ret i16 [[RESULT:%[0-9]+]]
+// CHECK: }
+
+long test_InterlockedAnd(long volatile *value, long mask) {
+ return _InterlockedAnd(value, mask);
+}
+// CHECK: define{{.*}}i32 @test_InterlockedAnd(i32*{{[a-z_ ]*}}%value, i32{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK: [[RESULT:%[0-9]+]] = atomicrmw and i32* %value, i32 %mask seq_cst
+// CHECK: ret i32 [[RESULT:%[0-9]+]]
+// CHECK: }
+
+char test_InterlockedCompareExchange8(char volatile *Destination, char Exchange, char Comperand) {
+ return _InterlockedCompareExchange8(Destination, Exchange, Comperand);
+}
+// CHECK: define{{.*}}i8 @test_InterlockedCompareExchange8(i8*{{[a-z_ ]*}}%Destination, i8{{[a-z_ ]*}}%Exchange, i8{{[a-z_ ]*}}%Comperand){{.*}}{
+// CHECK: [[TMP:%[0-9]+]] = cmpxchg volatile i8* %Destination, i8 %Comperand, i8 %Exchange seq_cst seq_cst
+// CHECK: [[RESULT:%[0-9]+]] = extractvalue { i8, i1 } [[TMP]], 0
+// CHECK: ret i8 [[RESULT]]
+// CHECK: }
+
+short test_InterlockedCompareExchange16(short volatile *Destination, short Exchange, short Comperand) {
+ return _InterlockedCompareExchange16(Destination, Exchange, Comperand);
+}
+// CHECK: define{{.*}}i16 @test_InterlockedCompareExchange16(i16*{{[a-z_ ]*}}%Destination, i16{{[a-z_ ]*}}%Exchange, i16{{[a-z_ ]*}}%Comperand){{.*}}{
+// CHECK: [[TMP:%[0-9]+]] = cmpxchg volatile i16* %Destination, i16 %Comperand, i16 %Exchange seq_cst seq_cst
+// CHECK: [[RESULT:%[0-9]+]] = extractvalue { i16, i1 } [[TMP]], 0
+// CHECK: ret i16 [[RESULT]]
+// CHECK: }
+
+long test_InterlockedCompareExchange(long volatile *Destination, long Exchange, long Comperand) {
+ return _InterlockedCompareExchange(Destination, Exchange, Comperand);
+}
+// CHECK: define{{.*}}i32 @test_InterlockedCompareExchange(i32*{{[a-z_ ]*}}%Destination, i32{{[a-z_ ]*}}%Exchange, i32{{[a-z_ ]*}}%Comperand){{.*}}{
+// CHECK: [[TMP:%[0-9]+]] = cmpxchg volatile i32* %Destination, i32 %Comperand, i32 %Exchange seq_cst seq_cst
+// CHECK: [[RESULT:%[0-9]+]] = extractvalue { i32, i1 } [[TMP]], 0
+// CHECK: ret i32 [[RESULT]]
+// CHECK: }
+
+__int64 test_InterlockedCompareExchange64(__int64 volatile *Destination, __int64 Exchange, __int64 Comperand) {
+ return _InterlockedCompareExchange64(Destination, Exchange, Comperand);
+}
+// CHECK: define{{.*}}i64 @test_InterlockedCompareExchange64(i64*{{[a-z_ ]*}}%Destination, i64{{[a-z_ ]*}}%Exchange, i64{{[a-z_ ]*}}%Comperand){{.*}}{
+// CHECK: [[TMP:%[0-9]+]] = cmpxchg volatile i64* %Destination, i64 %Comperand, i64 %Exchange seq_cst seq_cst
+// CHECK: [[RESULT:%[0-9]+]] = extractvalue { i64, i1 } [[TMP]], 0
+// CHECK: ret i64 [[RESULT]]
+// CHECK: }
+
+short test_InterlockedIncrement16(short volatile *Addend) {
+ return _InterlockedIncrement16(Addend);
+}
+// CHECK: define{{.*}}i16 @test_InterlockedIncrement16(i16*{{[a-z_ ]*}}%Addend){{.*}}{
+// CHECK: [[TMP:%[0-9]+]] = atomicrmw add i16* %Addend, i16 1 seq_cst
+// CHECK: [[RESULT:%[0-9]+]] = add i16 [[TMP]], 1
+// CHECK: ret i16 [[RESULT]]
+// CHECK: }
+
+long test_InterlockedIncrement(long volatile *Addend) {
+ return _InterlockedIncrement(Addend);
+}
+// CHECK: define{{.*}}i32 @test_InterlockedIncrement(i32*{{[a-z_ ]*}}%Addend){{.*}}{
+// CHECK: [[TMP:%[0-9]+]] = atomicrmw add i32* %Addend, i32 1 seq_cst
+// CHECK: [[RESULT:%[0-9]+]] = add i32 [[TMP]], 1
+// CHECK: ret i32 [[RESULT]]
+// CHECK: }
+
+short test_InterlockedDecrement16(short volatile *Addend) {
+ return _InterlockedDecrement16(Addend);
+}
+// CHECK: define{{.*}}i16 @test_InterlockedDecrement16(i16*{{[a-z_ ]*}}%Addend){{.*}}{
+// CHECK: [[TMP:%[0-9]+]] = atomicrmw sub i16* %Addend, i16 1 seq_cst
+// CHECK: [[RESULT:%[0-9]+]] = add i16 [[TMP]], -1
+// CHECK: ret i16 [[RESULT]]
+// CHECK: }
+
+long test_InterlockedDecrement(long volatile *Addend) {
+ return _InterlockedDecrement(Addend);
+}
+// CHECK: define{{.*}}i32 @test_InterlockedDecrement(i32*{{[a-z_ ]*}}%Addend){{.*}}{
+// CHECK: [[TMP:%[0-9]+]] = atomicrmw sub i32* %Addend, i32 1 seq_cst
+// CHECK: [[RESULT:%[0-9]+]] = add i32 [[TMP]], -1
+// CHECK: ret i32 [[RESULT]]
+// CHECK: }
+
+#if defined(__x86_64__) || defined(__arm__)
+__int64 test_InterlockedExchange64(__int64 volatile *value, __int64 mask) {
+ return _InterlockedExchange64(value, mask);
+}
+// CHECK-ARM-X64: define{{.*}}i64 @test_InterlockedExchange64(i64*{{[a-z_ ]*}}%value, i64{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-X64: [[RESULT:%[0-9]+]] = atomicrmw xchg i64* %value, i64 %mask seq_cst
+// CHECK-ARM-X64: ret i64 [[RESULT:%[0-9]+]]
+// CHECK-ARM-X64: }
+
+__int64 test_InterlockedExchangeAdd64(__int64 volatile *value, __int64 mask) {
+ return _InterlockedExchangeAdd64(value, mask);
+}
+// CHECK-ARM-X64: define{{.*}}i64 @test_InterlockedExchangeAdd64(i64*{{[a-z_ ]*}}%value, i64{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-X64: [[RESULT:%[0-9]+]] = atomicrmw add i64* %value, i64 %mask seq_cst
+// CHECK-ARM-X64: ret i64 [[RESULT:%[0-9]+]]
+// CHECK-ARM-X64: }
+__int64 test_InterlockedExchangeSub64(__int64 volatile *value, __int64 mask) {
+ return _InterlockedExchangeSub64(value, mask);
+}
+// CHECK-ARM-X64: define{{.*}}i64 @test_InterlockedExchangeSub64(i64*{{[a-z_ ]*}}%value, i64{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-X64: [[RESULT:%[0-9]+]] = atomicrmw sub i64* %value, i64 %mask seq_cst
+// CHECK-ARM-X64: ret i64 [[RESULT:%[0-9]+]]
+// CHECK-ARM-X64: }
+
+__int64 test_InterlockedOr64(__int64 volatile *value, __int64 mask) {
+ return _InterlockedOr64(value, mask);
+}
+// CHECK-ARM-X64: define{{.*}}i64 @test_InterlockedOr64(i64*{{[a-z_ ]*}}%value, i64{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-X64: [[RESULT:%[0-9]+]] = atomicrmw or i64* %value, i64 %mask seq_cst
+// CHECK-ARM-X64: ret i64 [[RESULT:%[0-9]+]]
+// CHECK-ARM-X64: }
+
+__int64 test_InterlockedXor64(__int64 volatile *value, __int64 mask) {
+ return _InterlockedXor64(value, mask);
+}
+// CHECK-ARM-X64: define{{.*}}i64 @test_InterlockedXor64(i64*{{[a-z_ ]*}}%value, i64{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-X64: [[RESULT:%[0-9]+]] = atomicrmw xor i64* %value, i64 %mask seq_cst
+// CHECK-ARM-X64: ret i64 [[RESULT:%[0-9]+]]
+// CHECK-ARM-X64: }
+
+__int64 test_InterlockedAnd64(__int64 volatile *value, __int64 mask) {
+ return _InterlockedAnd64(value, mask);
+}
+// CHECK-ARM-X64: define{{.*}}i64 @test_InterlockedAnd64(i64*{{[a-z_ ]*}}%value, i64{{[a-z_ ]*}}%mask){{.*}}{
+// CHECK-ARM-X64: [[RESULT:%[0-9]+]] = atomicrmw and i64* %value, i64 %mask seq_cst
+// CHECK-ARM-X64: ret i64 [[RESULT:%[0-9]+]]
+// CHECK-ARM-X64: }
+
+__int64 test_InterlockedIncrement64(__int64 volatile *Addend) {
+ return _InterlockedIncrement64(Addend);
+}
+// CHECK-ARM-X64: define{{.*}}i64 @test_InterlockedIncrement64(i64*{{[a-z_ ]*}}%Addend){{.*}}{
+// CHECK-ARM-X64: [[TMP:%[0-9]+]] = atomicrmw add i64* %Addend, i64 1 seq_cst
+// CHECK-ARM-X64: [[RESULT:%[0-9]+]] = add i64 [[TMP]], 1
+// CHECK-ARM-X64: ret i64 [[RESULT]]
+// CHECK-ARM-X64: }
+
+__int64 test_InterlockedDecrement64(__int64 volatile *Addend) {
+ return _InterlockedDecrement64(Addend);
+}
+// CHECK-ARM-X64: define{{.*}}i64 @test_InterlockedDecrement64(i64*{{[a-z_ ]*}}%Addend){{.*}}{
+// CHECK-ARM-X64: [[TMP:%[0-9]+]] = atomicrmw sub i64* %Addend, i64 1 seq_cst
+// CHECK-ARM-X64: [[RESULT:%[0-9]+]] = add i64 [[TMP]], -1
+// CHECK-ARM-X64: ret i64 [[RESULT]]
+// CHECK-ARM-X64: }
+
+#endif
diff --git a/test/CodeGen/ms-mm-align.c b/test/CodeGen/ms-mm-align.c
index 7130c74b2905..f3ed49dcd5d6 100644
--- a/test/CodeGen/ms-mm-align.c
+++ b/test/CodeGen/ms-mm-align.c
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 -target-feature +sse \
// RUN: -triple i686--windows -emit-llvm %s -o - \
-// RUN: | FileCheck %s -check-prefix CHECK
+// RUN: | FileCheck %s
// intrin.h needs size_t, but -ffreestanding prevents us from getting it from
// stddef.h. Work around it with this typedef.
diff --git a/test/CodeGen/ms-volatile-arm.c b/test/CodeGen/ms-volatile-arm.c
new file mode 100644
index 000000000000..065e624a4c04
--- /dev/null
+++ b/test/CodeGen/ms-volatile-arm.c
@@ -0,0 +1,13 @@
+// REQUIRES: arm-registered-target
+// RUN: %clang_cc1 -triple thumbv7-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
new file mode 100644
index 000000000000..e635220e8c13
--- /dev/null
+++ b/test/CodeGen/ms-x86-intrinsics.c
@@ -0,0 +1,74 @@
+// RUN: %clang_cc1 -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \
+// RUN: -triple i686--windows -Oz -emit-llvm %s -o - \
+// RUN: | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-I386
+// RUN: %clang_cc1 -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \
+// RUN: -triple x86_64--windows -Oz -emit-llvm %s -o - \
+// RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-X64
+
+#if defined(__i386__)
+long test__readfsdword(unsigned long Offset) {
+ return __readfsdword(Offset);
+}
+
+// CHECK-I386-LABEL: define 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]+]]
+// CHECK-I386: }
+#endif
+
+__int64 test__emul(int a, int b) {
+ return __emul(a, b);
+}
+// CHECK-LABEL: define 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]]
+// CHECK: ret i64 [[RES]]
+
+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: [[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]]
+// CHECK: ret i64 [[RES]]
+
+#if defined(__x86_64__)
+__int64 test__mulh(__int64 a, __int64 b) {
+ return __mulh(a, b);
+}
+// CHECK-X64-LABEL: define 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: = mul nuw i128 %
+
+__int64 test_mul128(__int64 Multiplier,
+ __int64 Multiplicand,
+ __int64 *HighProduct) {
+ return _mul128(Multiplier, Multiplicand, HighProduct);
+}
+// CHECK-X64-LABEL: define 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 %
+// CHECK-X64: store i64 %
+// CHECK-X64: ret i64 %
+
+unsigned __int64 test_umul128(unsigned __int64 Multiplier,
+ unsigned __int64 Multiplicand,
+ 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: = zext i64 %Multiplier to i128
+// CHECK-X64: = zext i64 %Multiplicand to i128
+// CHECK-X64: = mul nuw i128 %
+// CHECK-X64: store i64 %
+// CHECK-X64: ret i64 %
+#endif
diff --git a/test/CodeGen/ms_abi.c b/test/CodeGen/ms_abi.c
index 2cca24901b9a..97f66b29c517 100644
--- a/test/CodeGen/ms_abi.c
+++ b/test/CodeGen/ms_abi.c
@@ -45,24 +45,27 @@ void __attribute__((ms_abi)) f4(int a, ...) {
// WIN64-NEXT: %[[AP_NEXT:.*]] = getelementptr inbounds i8, i8* %[[AP_CUR]], i64 8
// WIN64-NEXT: store i8* %[[AP_NEXT]], i8** %[[AP]]
// WIN64-NEXT: bitcast i8* %[[AP_CUR]] to i32*
+ // FIXME: These are different now. We probably need __builtin_ms_va_arg.
double _Complex c = __builtin_va_arg(ap, double _Complex);
// FREEBSD: %[[AP_CUR2:.*]] = load i8*, i8** %[[AP]]
// FREEBSD-NEXT: %[[AP_NEXT2:.*]] = getelementptr inbounds i8, i8* %[[AP_CUR2]], i64 16
// FREEBSD-NEXT: store i8* %[[AP_NEXT2]], i8** %[[AP]]
// FREEBSD-NEXT: bitcast i8* %[[AP_CUR2]] to { double, double }*
// WIN64: %[[AP_CUR2:.*]] = load i8*, i8** %[[AP]]
- // WIN64-NEXT: %[[AP_NEXT2:.*]] = getelementptr inbounds i8, i8* %[[AP_CUR2]], i64 16
+ // WIN64-NEXT: %[[AP_NEXT2:.*]] = getelementptr inbounds i8, i8* %[[AP_CUR2]], i64 8
// WIN64-NEXT: store i8* %[[AP_NEXT2]], i8** %[[AP]]
- // WIN64-NEXT: bitcast i8* %[[AP_CUR2]] to { double, double }*
+ // WIN64-NEXT: %[[CUR2:.*]] = bitcast i8* %[[AP_CUR2]] to { double, double }**
+ // WIN64-NEXT: load { double, double }*, { double, double }** %[[CUR2]]
struct foo d = __builtin_va_arg(ap, struct foo);
// FREEBSD: %[[AP_CUR3:.*]] = load i8*, i8** %[[AP]]
// FREEBSD-NEXT: %[[AP_NEXT3:.*]] = getelementptr inbounds i8, i8* %[[AP_CUR3]], i64 16
// FREEBSD-NEXT: store i8* %[[AP_NEXT3]], i8** %[[AP]]
// FREEBSD-NEXT: bitcast i8* %[[AP_CUR3]] to %[[STRUCT_FOO]]*
// WIN64: %[[AP_CUR3:.*]] = load i8*, i8** %[[AP]]
- // WIN64-NEXT: %[[AP_NEXT3:.*]] = getelementptr inbounds i8, i8* %[[AP_CUR3]], i64 16
+ // WIN64-NEXT: %[[AP_NEXT3:.*]] = getelementptr inbounds i8, i8* %[[AP_CUR3]], i64 8
// WIN64-NEXT: store i8* %[[AP_NEXT3]], i8** %[[AP]]
- // WIN64-NEXT: bitcast i8* %[[AP_CUR3]] to %[[STRUCT_FOO]]*
+ // WIN64-NEXT: %[[CUR3:.*]] = bitcast i8* %[[AP_CUR3]] to %[[STRUCT_FOO]]*
+ // WIN64-NEXT: load %[[STRUCT_FOO]]*, %[[STRUCT_FOO]]** %[[CUR3]]
__builtin_ms_va_list ap2;
__builtin_ms_va_copy(ap2, ap);
// FREEBSD: %[[AP_VAL:.*]] = load i8*, i8** %[[AP]]
@@ -88,12 +91,12 @@ void f5(int a, ...) {
// WIN64-NEXT: bitcast i8* %[[AP_CUR]] to i32*
double _Complex c = __builtin_va_arg(ap, double _Complex);
// WIN64: %[[AP_CUR2:.*]] = load i8*, i8** %[[AP]]
- // WIN64-NEXT: %[[AP_NEXT2:.*]] = getelementptr inbounds i8, i8* %[[AP_CUR2]], i64 16
+ // WIN64-NEXT: %[[AP_NEXT2:.*]] = getelementptr inbounds i8, i8* %[[AP_CUR2]], i64 8
// WIN64-NEXT: store i8* %[[AP_NEXT2]], i8** %[[AP]]
// WIN64-NEXT: bitcast i8* %[[AP_CUR2]] to { double, double }*
struct foo d = __builtin_va_arg(ap, struct foo);
// WIN64: %[[AP_CUR3:.*]] = load i8*, i8** %[[AP]]
- // WIN64-NEXT: %[[AP_NEXT3:.*]] = getelementptr inbounds i8, i8* %[[AP_CUR3]], i64 16
+ // WIN64-NEXT: %[[AP_NEXT3:.*]] = getelementptr inbounds i8, i8* %[[AP_CUR3]], i64 8
// WIN64-NEXT: store i8* %[[AP_NEXT3]], i8** %[[AP]]
// WIN64-NEXT: bitcast i8* %[[AP_CUR3]] to %[[STRUCT_FOO]]*
__builtin_va_list ap2;
@@ -124,7 +127,7 @@ void __attribute__((sysv_abi)) f6(__builtin_ms_va_list ap) {
// FREEBSD-NEXT: store i8* %[[AP_NEXT2]], i8** %[[AP]]
// FREEBSD-NEXT: bitcast i8* %[[AP_CUR2]] to { double, double }*
// WIN64: %[[AP_CUR2:.*]] = load i8*, i8** %[[AP]]
- // WIN64-NEXT: %[[AP_NEXT2:.*]] = getelementptr inbounds i8, i8* %[[AP_CUR2]], i64 16
+ // WIN64-NEXT: %[[AP_NEXT2:.*]] = getelementptr inbounds i8, i8* %[[AP_CUR2]], i64 8
// WIN64-NEXT: store i8* %[[AP_NEXT2]], i8** %[[AP]]
// WIN64-NEXT: bitcast i8* %[[AP_CUR2]] to { double, double }*
struct foo d = __builtin_va_arg(ap, struct foo);
@@ -133,7 +136,7 @@ void __attribute__((sysv_abi)) f6(__builtin_ms_va_list ap) {
// FREEBSD-NEXT: store i8* %[[AP_NEXT3]], i8** %[[AP]]
// FREEBSD-NEXT: bitcast i8* %[[AP_CUR3]] to %[[STRUCT_FOO]]*
// WIN64: %[[AP_CUR3:.*]] = load i8*, i8** %[[AP]]
- // WIN64-NEXT: %[[AP_NEXT3:.*]] = getelementptr inbounds i8, i8* %[[AP_CUR3]], i64 16
+ // WIN64-NEXT: %[[AP_NEXT3:.*]] = getelementptr inbounds i8, i8* %[[AP_CUR3]], i64 8
// WIN64-NEXT: store i8* %[[AP_NEXT3]], i8** %[[AP]]
// WIN64-NEXT: bitcast i8* %[[AP_CUR3]] to %[[STRUCT_FOO]]*
__builtin_ms_va_list ap2;
diff --git a/test/CodeGen/nobuiltin.c b/test/CodeGen/nobuiltin.c
index 7cc8164c6f12..f80c3c332ab4 100644
--- a/test/CodeGen/nobuiltin.c
+++ b/test/CodeGen/nobuiltin.c
@@ -1,17 +1,21 @@
-// RUN: %clang_cc1 -fno-builtin -O1 -S -o - %s | FileCheck %s
-// RUN: %clang_cc1 -fno-builtin-memset -O1 -S -o - %s | FileCheck -check-prefix=MEMSET %s
+// REQUIRES: x86-registered-target
+
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -O1 -S -o - %s | FileCheck -check-prefix=STRCPY -check-prefix=MEMSET %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fno-builtin -O1 -S -o - %s | FileCheck -check-prefix=NOSTRCPY -check-prefix=NOMEMSET %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fno-builtin-memset -O1 -S -o - %s | FileCheck -check-prefix=STRCPY -check-prefix=NOMEMSET %s
void PR13497() {
char content[2];
// make sure we don't optimize this call to strcpy()
- // CHECK: __strcpy_chk
+ // STRCPY-NOT: __strcpy_chk
+ // NOSTRCPY: __strcpy_chk
__builtin___strcpy_chk(content, "", 1);
}
void PR4941(char *s) {
// Make sure we don't optimize this loop to a memset().
- // MEMSET-LABEL: PR4941:
- // MEMSET-NOT: memset
+ // NOMEMSET-NOT: memset
+ // MEMSET: memset
for (unsigned i = 0; i < 8192; ++i)
s[i] = 0;
}
diff --git a/test/CodeGen/noexceptionsfpmath.c b/test/CodeGen/noexceptionsfpmath.c
new file mode 100644
index 000000000000..a22e285bb72a
--- /dev/null
+++ b/test/CodeGen/noexceptionsfpmath.c
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -S -fno-trapping-math %s -emit-llvm -o - | FileCheck %s
+
+// CHECK-LABEL: main
+// CHECK: attributes #0 = {{.*}}"no-trapping-math"="true"{{.*}}
+
+int main() {
+ return 0;
+}
diff --git a/test/CodeGen/object-size.c b/test/CodeGen/object-size.c
index 6aee57375a48..a3f3bce92956 100644
--- a/test/CodeGen/object-size.c
+++ b/test/CodeGen/object-size.c
@@ -276,7 +276,7 @@ void test23(struct Test23Ty *p) {
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false)
gi = __builtin_object_size(&p->t[5], 0);
- // CHECK: store i32 20
+ // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false)
gi = __builtin_object_size(&p->t[5], 1);
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true)
gi = __builtin_object_size(&p->t[5], 2);
@@ -444,7 +444,7 @@ void test29(struct DynStructVar *dv, struct DynStruct0 *d0,
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false)
gi = __builtin_object_size(ss->snd, 0);
- // CHECK: store i32 2
+ // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false)
gi = __builtin_object_size(ss->snd, 1);
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true)
gi = __builtin_object_size(ss->snd, 2);
@@ -505,7 +505,7 @@ void test31() {
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false)
gi = __builtin_object_size(ds1[9].snd, 1);
- // CHECK: store i32 2
+ // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false)
gi = __builtin_object_size(&ss[9].snd[0], 1);
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false)
@@ -517,3 +517,22 @@ void test31() {
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false)
gi = __builtin_object_size(&dsv[9].snd[0], 1);
}
+
+// CHECK-LABEL: @PR30346
+void PR30346() {
+ struct sa_family_t {};
+ struct sockaddr {
+ struct sa_family_t sa_family;
+ char sa_data[14];
+ };
+
+ struct sockaddr *sa;
+ // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false)
+ gi = __builtin_object_size(sa->sa_data, 0);
+ // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false)
+ gi = __builtin_object_size(sa->sa_data, 1);
+ // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true)
+ gi = __builtin_object_size(sa->sa_data, 2);
+ // CHECK: store i32 14
+ gi = __builtin_object_size(sa->sa_data, 3);
+}
diff --git a/test/CodeGen/opt-record.c b/test/CodeGen/opt-record.c
new file mode 100644
index 000000000000..3bc3c41f7840
--- /dev/null
+++ b/test/CodeGen/opt-record.c
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -O3 -triple x86_64-unknown-linux-gnu -target-cpu x86-64 %s -o %t -dwarf-column-info -opt-record-file %t.yaml -emit-obj
+// RUN: cat %t.yaml | FileCheck %s
+// RUN: llvm-profdata merge %S/Inputs/opt-record.proftext -o %t.profdata
+// RUN: %clang_cc1 -O3 -triple x86_64-unknown-linux-gnu -target-cpu x86-64 -fprofile-instrument-use-path=%t.profdata %s -o %t -dwarf-column-info -opt-record-file %t.yaml -emit-obj
+// RUN: cat %t.yaml | FileCheck -check-prefix=CHECK -check-prefix=CHECK-PGO %s
+// REQUIRES: x86-registered-target
+
+void bar();
+void foo() { bar(); }
+
+void Test(int *res, int *c, int *d, int *p, int n) {
+ int i;
+
+#pragma clang loop vectorize(assume_safety)
+ for (i = 0; i < 1600; i++) {
+ res[i] = (p[i] == 0) ? res[i] : res[i] + d[i];
+ }
+}
+
+// CHECK: --- !Missed
+// CHECK: Pass: inline
+// CHECK: Name: NoDefinition
+// CHECK: DebugLoc:
+// CHECK: Function: foo
+// CHECK-PGO: Hotness:
+
+// CHECK: --- !Passed
+// CHECK: Pass: loop-vectorize
+// CHECK: Name: Vectorized
+// CHECK: DebugLoc:
+// CHECK: Function: Test
+// CHECK-PGO: Hotness:
+
diff --git a/test/CodeGen/overloadable.c b/test/CodeGen/overloadable.c
index 634820cfe743..1feb12f5b579 100644
--- a/test/CodeGen/overloadable.c
+++ b/test/CodeGen/overloadable.c
@@ -59,3 +59,38 @@ void foo() {
// CHECK: @_Z13addrof_singlePc
void *vp3 = &addrof_single;
}
+
+
+void ovl_bar(char *) __attribute__((overloadable));
+void ovl_bar(int) __attribute__((overloadable));
+
+// CHECK-LABEL: define void @bar
+void bar() {
+ char charbuf[1];
+ unsigned char ucharbuf[1];
+
+ // CHECK: call void @_Z7ovl_barPc
+ ovl_bar(charbuf);
+ // CHECK: call void @_Z7ovl_barPc
+ ovl_bar(ucharbuf);
+}
+
+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
+void baz() {
+ unsigned int j;
+ // Initial rules for incompatible pointer conversions made this overload
+ // ambiguous.
+ // CHECK: call void @_Z7ovl_bazPjj
+ ovl_baz(&j, 0);
+ // CHECK: call void @_Z7ovl_bazPjj
+ ovl_baz(&j, 0u);
+
+ // CHECK: call void @_Z8ovl_baz2jPj
+ ovl_baz2(0, &j);
+ // CHECK: call void @_Z8ovl_baz2jPj
+ ovl_baz2(0u, &j);
+}
diff --git a/test/CodeGen/pass-object-size.c b/test/CodeGen/pass-object-size.c
index 6e2bc2090eda..6f5827befa71 100644
--- a/test/CodeGen/pass-object-size.c
+++ b/test/CodeGen/pass-object-size.c
@@ -59,7 +59,8 @@ void test1() {
// CHECK-LABEL: define void @test2
void test2(struct Foo *t) {
- // CHECK: call i32 @ObjectSize1(i8* %{{.*}}, i64 36)
+ // CHECK: [[VAR:%[0-9]+]] = call i64 @llvm.objectsize
+ // CHECK: call i32 @ObjectSize1(i8* %{{.*}}, i64 [[VAR]])
gi = ObjectSize1(&t->t[1]);
// CHECK: call i32 @ObjectSize3(i8* %{{.*}}, i64 36)
gi = ObjectSize3(&t->t[1]);
@@ -168,7 +169,8 @@ void test4(struct Foo *t) {
// CHECK: call i32 @_Z27NoViableOverloadObjectSize0PvU17pass_object_size0(i8* %{{.*}}, i64 %{{.*}})
gi = NoViableOverloadObjectSize0(&t[1].t[1]);
- // CHECK: call i32 @_Z27NoViableOverloadObjectSize1PvU17pass_object_size1(i8* %{{.*}}, i64 36)
+ // CHECK: [[VAR:%[0-9]+]] = call i64 @llvm.objectsize
+ // CHECK: call i32 @_Z27NoViableOverloadObjectSize1PvU17pass_object_size1(i8* %{{.*}}, i64 [[VAR]])
gi = NoViableOverloadObjectSize1(&t[1].t[1]);
// CHECK: call i32 @_Z27NoViableOverloadObjectSize2PvU17pass_object_size2(i8* %{{.*}}, i64 %{{.*}})
gi = NoViableOverloadObjectSize2(&t[1].t[1]);
@@ -274,7 +276,8 @@ void test7() {
// CHECK-LABEL: define void @test8
void test8(struct Foo *t) {
- // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 36)
+ // CHECK: [[VAR:%[0-9]+]] = call i64 @llvm.objectsize
+ // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 [[VAR]])
gi = AsmObjectSize1(&t[1].t[1]);
// CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 36)
gi = AsmObjectSize3(&t[1].t[1]);
diff --git a/test/CodeGen/pclmul-builtins.c b/test/CodeGen/pclmul-builtins.c
index ebca89903747..44300f645a9d 100644
--- a/test/CodeGen/pclmul-builtins.c
+++ b/test/CodeGen/pclmul-builtins.c
@@ -1,7 +1,5 @@
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +pclmul -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +pclmul -emit-llvm -o - | FileCheck %s
-// Don't include mm_malloc.h, it's system specific.
-#define __MM_MALLOC_H
#include <wmmintrin.h>
diff --git a/test/CodeGen/pgo-sample.c b/test/CodeGen/pgo-sample.c
index c955edfab7a4..e7d2fa61aa1e 100644
--- a/test/CodeGen/pgo-sample.c
+++ b/test/CodeGen/pgo-sample.c
@@ -2,8 +2,5 @@
//
// Ensure Pass PGOInstrumentationGenPass is invoked.
// RUN: %clang_cc1 -O2 -fprofile-sample-use=%S/Inputs/pgo-sample.prof %s -mllvm -debug-pass=Structure -emit-llvm -o - 2>&1 | FileCheck %s
-// CHECK: Simplify the CFG
-// CHECK: SROA
-// CHECK: Combine redundant instructions
// CHECK: Remove unused exception handling info
// CHECK: Sample profile pass
diff --git a/test/CodeGen/pku.c b/test/CodeGen/pku.c
index 30565a83d6b3..cb02b03ffe0e 100644
--- a/test/CodeGen/pku.c
+++ b/test/CodeGen/pku.c
@@ -1,7 +1,5 @@
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +pku -emit-llvm -o - -Werror | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +pku -emit-llvm -o - -Wall -Werror | FileCheck %s
-// Don't include mm_malloc.h, it's system specific.
-#define __MM_MALLOC_H
#include <immintrin.h>
diff --git a/test/CodeGen/popcnt-builtins.c b/test/CodeGen/popcnt-builtins.c
index 5ae40c7a7688..656a20f98605 100644
--- a/test/CodeGen/popcnt-builtins.c
+++ b/test/CodeGen/popcnt-builtins.c
@@ -1,7 +1,5 @@
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +popcnt -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +popcnt -emit-llvm -o - | FileCheck %s
-// Don't include mm_malloc.h, it's system specific.
-#define __MM_MALLOC_H
#include <x86intrin.h>
diff --git a/test/CodeGen/ppc64-complex-parms.c b/test/CodeGen/ppc64-complex-parms.c
index 3f2a0c21420f..32163fa4a995 100644
--- a/test/CodeGen/ppc64-complex-parms.c
+++ b/test/CodeGen/ppc64-complex-parms.c
@@ -180,4 +180,4 @@ void bar_long_long(void) {
// CHECK: %[[VAR77:[A-Za-z0-9.]+]] = load i64, i64* %[[VAR76]], align 8
// CHECK: %{{[A-Za-z0-9.]+}} = call i64 @foo_long_long(i64 %[[VAR75]], i64 %[[VAR77]])
-// CHECK: attributes [[NUW]] = { nounwind{{.*}} }
+// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} }
diff --git a/test/CodeGen/ppc64-complex-return.c b/test/CodeGen/ppc64-complex-return.c
index cdb0ed6e47a6..02bfe82d4efe 100644
--- a/test/CodeGen/ppc64-complex-return.c
+++ b/test/CodeGen/ppc64-complex-return.c
@@ -126,4 +126,4 @@ long long bar_long_long(void) {
// CHECK: extractvalue { i64, i64 } [[VAR8]], 1
-// CHECK: attributes [[NUW]] = { nounwind{{.*}} }
+// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} }
diff --git a/test/CodeGen/ppc64-dwarf.c b/test/CodeGen/ppc64-dwarf.c
new file mode 100644
index 000000000000..679bded453a8
--- /dev/null
+++ b/test/CodeGen/ppc64-dwarf.c
@@ -0,0 +1,129 @@
+// RUN: %clang_cc1 -triple powerpc64-unknown-unknown -emit-llvm %s -o - | FileCheck %s
+static unsigned char dwarf_reg_size_table[1024];
+
+int test() {
+ __builtin_init_dwarf_reg_size_table(dwarf_reg_size_table);
+
+ return __builtin_dwarf_sp_column();
+}
+
+// CHECK-LABEL: define signext i32 @test()
+// CHECK: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 0), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 1), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 2), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 3), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 4), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 5), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 6), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 7), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 8), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 9), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 10), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 11), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 12), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 13), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 14), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 15), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 16), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 17), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 18), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 19), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 20), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 21), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 22), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 23), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 24), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 25), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 26), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 27), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 28), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 29), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 30), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 31), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 32), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 33), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 34), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 35), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 36), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 37), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 38), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 39), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 40), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 41), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 42), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 43), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 44), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 45), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 46), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 47), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 48), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 49), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 50), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 51), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 52), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 53), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 54), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 55), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 56), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 57), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 58), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 59), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 60), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 61), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 62), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 63), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 64), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 65), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 66), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 67), align 1
+// CHECK-NEXT: store i8 4, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 68), align 1
+// CHECK-NEXT: store i8 4, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 69), align 1
+// CHECK-NEXT: store i8 4, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 70), align 1
+// CHECK-NEXT: store i8 4, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 71), align 1
+// CHECK-NEXT: store i8 4, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 72), align 1
+// CHECK-NEXT: store i8 4, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 73), align 1
+// CHECK-NEXT: store i8 4, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 74), align 1
+// CHECK-NEXT: store i8 4, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 75), align 1
+// CHECK-NEXT: store i8 4, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 76), align 1
+// CHECK-NEXT: store i8 16, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 77), align 1
+// CHECK-NEXT: store i8 16, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 78), align 1
+// CHECK-NEXT: store i8 16, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 79), align 1
+// CHECK-NEXT: store i8 16, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 80), align 1
+// CHECK-NEXT: store i8 16, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 81), align 1
+// CHECK-NEXT: store i8 16, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 82), align 1
+// CHECK-NEXT: store i8 16, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 83), align 1
+// CHECK-NEXT: store i8 16, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 84), align 1
+// CHECK-NEXT: store i8 16, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 85), align 1
+// CHECK-NEXT: store i8 16, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 86), align 1
+// CHECK-NEXT: store i8 16, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 87), align 1
+// CHECK-NEXT: store i8 16, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 88), align 1
+// CHECK-NEXT: store i8 16, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 89), align 1
+// CHECK-NEXT: store i8 16, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 90), align 1
+// CHECK-NEXT: store i8 16, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 91), align 1
+// CHECK-NEXT: store i8 16, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 92), align 1
+// CHECK-NEXT: store i8 16, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 93), align 1
+// CHECK-NEXT: store i8 16, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 94), align 1
+// CHECK-NEXT: store i8 16, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 95), align 1
+// CHECK-NEXT: store i8 16, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 96), align 1
+// CHECK-NEXT: store i8 16, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 97), align 1
+// CHECK-NEXT: store i8 16, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 98), align 1
+// CHECK-NEXT: store i8 16, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 99), align 1
+// CHECK-NEXT: store i8 16, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 100), align 1
+// CHECK-NEXT: store i8 16, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 101), align 1
+// CHECK-NEXT: store i8 16, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 102), align 1
+// CHECK-NEXT: store i8 16, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 103), align 1
+// CHECK-NEXT: store i8 16, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 104), align 1
+// CHECK-NEXT: store i8 16, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 105), align 1
+// CHECK-NEXT: store i8 16, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 106), align 1
+// CHECK-NEXT: store i8 16, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 107), align 1
+// CHECK-NEXT: store i8 16, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 108), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 109), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 110), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 111), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 112), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 113), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 114), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 115), align 1
+// CHECK-NEXT: store i8 8, i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @dwarf_reg_size_table, i32 0, i32 116), align 1
+// CHECK-NEXT: ret i32 1
+
diff --git a/test/CodeGen/ppc64-extend.c b/test/CodeGen/ppc64-extend.c
index 52e5f136dd95..6b596b47d374 100644
--- a/test/CodeGen/ppc64-extend.c
+++ b/test/CodeGen/ppc64-extend.c
@@ -13,4 +13,4 @@ int f3(void) { return 0; }
unsigned int f4(void) { return 0; }
// CHECK: define zeroext i32 @f4() [[NUW]]
-// CHECK: attributes [[NUW]] = { nounwind{{.*}} }
+// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} }
diff --git a/test/CodeGen/ppc64-soft-float.c b/test/CodeGen/ppc64-soft-float.c
new file mode 100644
index 000000000000..95b18292319d
--- /dev/null
+++ b/test/CodeGen/ppc64-soft-float.c
@@ -0,0 +1,171 @@
+// RUN: %clang_cc1 -msoft-float -mfloat-abi soft -triple powerpc64le-unknown-linux-gnu -emit-llvm -o - %s | FileCheck -check-prefix=CHECK -check-prefix=CHECK-LE %s
+// RUN: %clang_cc1 -msoft-float -mfloat-abi soft -triple powerpc64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck -check-prefix=CHECK -check-prefix=CHECK-BE %s
+
+// Test float returns and params.
+
+// CHECK: define float @func_p1(float %x)
+float func_p1(float x) { return x; }
+
+// CHECK: define double @func_p2(double %x)
+double func_p2(double x) { return x; }
+
+// CHECK: define ppc_fp128 @func_p3(ppc_fp128 %x)
+long double func_p3(long double x) { return x; }
+
+// Test homogeneous float aggregate passing and returning.
+
+struct f1 { float f[1]; };
+struct f2 { float f[2]; };
+struct f3 { float f[3]; };
+struct f4 { float f[4]; };
+struct f5 { float f[5]; };
+struct f6 { float f[6]; };
+struct f7 { float f[7]; };
+struct f8 { float f[8]; };
+struct f9 { float f[9]; };
+
+struct fab { float a; float b; };
+struct fabc { float a; float b; float c; };
+
+struct f2a2b { float a[2]; float b[2]; };
+
+// CHECK-LE: define i32 @func_f1(float inreg %x.coerce)
+// CHECK-BE: define void @func_f1(%struct.f1* noalias sret %agg.result, float inreg %x.coerce)
+struct f1 func_f1(struct f1 x) { return x; }
+
+// CHECK-LE: define i64 @func_f2(i64 %x.coerce)
+// CHECK-BE: define void @func_f2(%struct.f2* noalias sret %agg.result, i64 %x.coerce)
+struct f2 func_f2(struct f2 x) { return x; }
+
+// CHECK-LE: define { i64, i64 } @func_f3([2 x i64] %x.coerce)
+// CHECK-BE: define void @func_f3(%struct.f3* noalias sret %agg.result, [2 x i64] %x.coerce)
+struct f3 func_f3(struct f3 x) { return x; }
+
+// CHECK-LE: define { i64, i64 } @func_f4([2 x i64] %x.coerce)
+// CHECK-BE: define void @func_f4(%struct.f4* noalias sret %agg.result, [2 x i64] %x.coerce)
+struct f4 func_f4(struct f4 x) { return x; }
+
+// CHECK: define void @func_f5(%struct.f5* noalias sret %agg.result, [3 x i64] %x.coerce)
+struct f5 func_f5(struct f5 x) { return x; }
+
+// CHECK: define void @func_f6(%struct.f6* noalias sret %agg.result, [3 x i64] %x.coerce)
+struct f6 func_f6(struct f6 x) { return x; }
+
+// CHECK: define void @func_f7(%struct.f7* noalias sret %agg.result, [4 x i64] %x.coerce)
+struct f7 func_f7(struct f7 x) { return x; }
+
+// CHECK: define void @func_f8(%struct.f8* noalias sret %agg.result, [4 x i64] %x.coerce)
+struct f8 func_f8(struct f8 x) { return x; }
+
+// CHECK: define void @func_f9(%struct.f9* noalias sret %agg.result, [5 x i64] %x.coerce)
+struct f9 func_f9(struct f9 x) { return x; }
+
+// CHECK-LE: define i64 @func_fab(i64 %x.coerce)
+// CHECK-BE: define void @func_fab(%struct.fab* noalias sret %agg.result, i64 %x.coerce)
+struct fab func_fab(struct fab x) { return x; }
+
+// CHECK-LE: define { i64, i64 } @func_fabc([2 x i64] %x.coerce)
+// CHECK-BE: define void @func_fabc(%struct.fabc* noalias sret %agg.result, [2 x i64] %x.coerce)
+struct fabc func_fabc(struct fabc x) { return x; }
+
+// CHECK-LE: define { i64, i64 } @func_f2a2b([2 x i64] %x.coerce)
+// CHECK-BE: define void @func_f2a2b(%struct.f2a2b* noalias sret %agg.result, [2 x i64] %x.coerce)
+struct f2a2b func_f2a2b(struct f2a2b x) { return x; }
+
+// CHECK-LABEL: @call_f1
+// CHECK-BE: %[[TMP0:[^ ]+]] = alloca %struct.f1, align 4
+// CHECK: %[[TMP:[^ ]+]] = load float, float* getelementptr inbounds (%struct.f1, %struct.f1* @global_f1, i32 0, i32 0, i32 0), align 4
+// CHECK-LE: call i32 @func_f1(float inreg %[[TMP]])
+// CHECK-BE: call void @func_f1(%struct.f1* sret %[[TMP0]], float inreg %[[TMP]])
+struct f1 global_f1;
+void call_f1(void) { global_f1 = func_f1(global_f1); }
+
+// CHECK-LABEL: @call_f2
+// CHECK-BE: %[[TMP0:[^ ]+]] = alloca %struct.f2, align 4
+// CHECK: %[[TMP:[^ ]+]] = load i64, i64* bitcast (%struct.f2* @global_f2 to i64*), align 4
+// CHECK-LE: call i64 @func_f2(i64 %[[TMP]])
+// CHECK-BE: call void @func_f2(%struct.f2* sret %[[TMP0]], i64 %[[TMP]])
+struct f2 global_f2;
+void call_f2(void) { global_f2 = func_f2(global_f2); }
+
+// CHECK-LABEL: @call_f3
+// 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: %[[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]])
+struct f3 global_f3;
+void call_f3(void) { global_f3 = func_f3(global_f3); }
+
+// CHECK-LABEL: @call_f4
+// CHECK-BE: %[[TMP0:[^ ]+]] = alloca %struct.f4, align 4
+// CHECK: %[[TMP:[^ ]+]] = load [2 x i64], [2 x i64]* bitcast (%struct.f4* @global_f4 to [2 x i64]*), align 4
+// CHECK-LE: call { i64, i64 } @func_f4([2 x i64] %[[TMP]])
+// CHECK-BE: call void @func_f4(%struct.f4* sret %[[TMP0]], [2 x i64] %[[TMP]])
+struct f4 global_f4;
+void call_f4(void) { global_f4 = func_f4(global_f4); }
+
+// CHECK-LABEL: @call_f5
+// 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: %[[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;
+void call_f5(void) { global_f5 = func_f5(global_f5); }
+
+// CHECK-LABEL: @call_f6
+// CHECK: %[[TMP0:[^ ]+]] = alloca %struct.f6, align 4
+// CHECK: %[[TMP:[^ ]+]] = load [3 x i64], [3 x i64]* bitcast (%struct.f6* @global_f6 to [3 x i64]*), align 4
+// CHECK: call void @func_f6(%struct.f6* sret %[[TMP0]], [3 x i64] %[[TMP]])
+struct f6 global_f6;
+void call_f6(void) { global_f6 = func_f6(global_f6); }
+
+// CHECK-LABEL: @call_f7
+// 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: %[[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;
+void call_f7(void) { global_f7 = func_f7(global_f7); }
+
+// CHECK-LABEL: @call_f8
+// CHECK: %[[TMP0:[^ ]+]] = alloca %struct.f8, align 4
+// CHECK: %[[TMP:[^ ]+]] = load [4 x i64], [4 x i64]* bitcast (%struct.f8* @global_f8 to [4 x i64]*), align 4
+// CHECK: call void @func_f8(%struct.f8* sret %[[TMP0]], [4 x i64] %[[TMP]])
+struct f8 global_f8;
+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: %[[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;
+void call_f9(void) { global_f9 = func_f9(global_f9); }
+
+// CHECK-LABEL: @call_fab
+// CHECK: %[[TMP0:[^ ]+]] = alloca %struct.fab, align 4
+// CHECK: %[[TMP:[^ ]+]] = load i64, i64* bitcast (%struct.fab* @global_fab to i64*), align 4
+// CHECK-LE: %call = call i64 @func_fab(i64 %[[TMP]])
+// CHECK-BE: call void @func_fab(%struct.fab* sret %[[TMP0]], i64 %[[TMP]])
+struct fab global_fab;
+void call_fab(void) { global_fab = func_fab(global_fab); }
+
+// CHECK-LABEL: @call_fabc
+// 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: %[[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]])
+struct fabc global_fabc;
+void call_fabc(void) { global_fabc = func_fabc(global_fabc); }
+
diff --git a/test/CodeGen/ppc64-struct-onevect.c b/test/CodeGen/ppc64-struct-onevect.c
index 34f4cc0753ac..8cd4126912a5 100644
--- a/test/CodeGen/ppc64-struct-onevect.c
+++ b/test/CodeGen/ppc64-struct-onevect.c
@@ -9,5 +9,5 @@ v4sf foo (struct s a) {
return a.v;
}
-// CHECK-LABEL: define <4 x float> @foo(<4 x float> inreg %a.coerce)
+// CHECK-LABEL: define <4 x float> @foo(<4 x float> inreg returned %a.coerce)
// CHECK: ret <4 x float> %a.coerce
diff --git a/test/CodeGen/pr27892.c b/test/CodeGen/pr27892.c
index 694ce9eb0a52..57722c4671ab 100644
--- a/test/CodeGen/pr27892.c
+++ b/test/CodeGen/pr27892.c
@@ -7,7 +7,7 @@ long test1(long *p) {
// CHECK: %[[p_addr:.*]] = alloca i64*, align 8
// CHECK: store i64* %p, i64** %[[p_addr]], align 8
// CHECK: %[[p_load:.*]] = load i64*, i64** %[[p_addr]], align 8
-// CHECK: %[[atomic_add:.*]] = atomicrmw volatile add i64* %[[p_load]], i64 1 seq_cst
+// CHECK: %[[atomic_add:.*]] = atomicrmw add i64* %[[p_load]], i64 1 seq_cst
// CHECK: %[[res:.*]] = add i64 %[[atomic_add]], 1
// CHECK: ret i64 %[[res]]
@@ -18,6 +18,6 @@ long test2(long *p) {
// CHECK: %[[p_addr:.*]] = alloca i64*, align 8
// CHECK: store i64* %p, i64** %[[p_addr]], align 8
// CHECK: %[[p_load:.*]] = load i64*, i64** %[[p_addr]], align 8
-// CHECK: %[[atomic_sub:.*]] = atomicrmw volatile sub i64* %[[p_load]], i64 1 seq_cst
+// CHECK: %[[atomic_sub:.*]] = atomicrmw sub i64* %[[p_load]], i64 1 seq_cst
// CHECK: %[[res:.*]] = sub i64 %[[atomic_sub]], 1
// CHECK: ret i64 %[[res]]
diff --git a/test/CodeGen/prefetchw-builtins.c b/test/CodeGen/prefetchw-builtins.c
index 8a50325ea18f..53416de46ff4 100644
--- a/test/CodeGen/prefetchw-builtins.c
+++ b/test/CodeGen/prefetchw-builtins.c
@@ -1,7 +1,5 @@
-// RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-feature +prfchw -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding -triple x86_64-unknown-unknown -target-feature +prfchw -emit-llvm -o - %s | FileCheck %s
-// Don't include mm_malloc.h, it's system specific.
-#define __MM_MALLOC_H
#include <x86intrin.h>
diff --git a/test/CodeGen/rd-builtins.c b/test/CodeGen/rd-builtins.c
index 5cad90390941..0d7cd04d6f26 100644
--- a/test/CodeGen/rd-builtins.c
+++ b/test/CodeGen/rd-builtins.c
@@ -1,7 +1,5 @@
-// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s
-// Don't include mm_malloc.h, it's system specific.
-#define __MM_MALLOC_H
#include <x86intrin.h>
diff --git a/test/CodeGen/rdrand-builtins.c b/test/CodeGen/rdrand-builtins.c
index 15414a334580..936502b77483 100644
--- a/test/CodeGen/rdrand-builtins.c
+++ b/test/CodeGen/rdrand-builtins.c
@@ -1,7 +1,5 @@
-// RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-feature +rdrnd -target-feature +rdseed -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding -triple x86_64-unknown-unknown -target-feature +rdrnd -target-feature +rdseed -emit-llvm -o - %s | FileCheck %s
-// Don't include mm_malloc.h, it's system specific.
-#define __MM_MALLOC_H
#include <x86intrin.h>
diff --git a/test/CodeGen/regcall.c b/test/CodeGen/regcall.c
new file mode 100644
index 000000000000..350a82d33963
--- /dev/null
+++ b/test/CodeGen/regcall.c
@@ -0,0 +1,120 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - -ffreestanding -triple=i386-pc-win32 | FileCheck %s --check-prefix=Win32
+// RUN: %clang_cc1 -emit-llvm %s -o - -ffreestanding -triple=x86_64-pc-win32 | FileCheck %s --check-prefix=Win64
+// RUN: %clang_cc1 -emit-llvm %s -o - -ffreestanding -triple=i386-pc-linux-gnu | FileCheck %s --check-prefix=Lin32
+// RUN: %clang_cc1 -emit-llvm %s -o - -ffreestanding -triple=x86_64-pc-linux-gnu | FileCheck %s --check-prefix=Lin64
+
+#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)
+// 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)
+// 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)
+// 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)
+// 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)
+// 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)
+
+struct HFA2 { double x, y; };
+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)
+// 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)
+
+// 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 __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)
+// 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)
+// 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)
+
+// 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 __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)
+// 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()
+// Lin32: define x86_regcallcc %struct.HFA2 @__regcall3__hfa5()
+// Lin64: define x86_regcallcc %struct.HFA2 @__regcall3__hfa5()
+
+typedef float __attribute__((vector_size(16))) v4f32;
+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)
+// 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)
+// 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)
+// 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)
+
+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)
+// 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)
+// 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/renderscript.c b/test/CodeGen/renderscript.c
index d47750a7736e..5482d36f583d 100644
--- a/test/CodeGen/renderscript.c
+++ b/test/CodeGen/renderscript.c
@@ -23,3 +23,118 @@ _Static_assert(_Alignof(long) == LONG_WIDTH_AND_ALIGN, "sizeof long is wrong");
long test_long(long v) {
return v + 1;
}
+
+// =============================================================================
+// Test coercion of aggregate argument or return value into integer arrays
+// =============================================================================
+
+// =============================================================================
+// aggregate parameter <= 4 bytes: coerced to [a x iNN] for both 32-bit and
+// 64-bit RenderScript
+// ==============================================================================
+
+typedef struct {char c1, c2, c3; } sChar3;
+typedef struct {short s; char c;} sShortChar;
+
+// CHECK-RS32: void @argChar3([3 x i8] %s.coerce)
+// CHECK-RS64: void @argChar3([3 x i8] %s.coerce)
+void argChar3(sChar3 s) {}
+
+// CHECK-RS32: void @argShortChar([2 x i16] %s.coerce)
+// CHECK-RS64: void @argShortChar([2 x i16] %s.coerce)
+void argShortChar(sShortChar s) {}
+
+// =============================================================================
+// aggregate return value <= 4 bytes: coerced to [a x iNN] for both 32-bit and
+// 64-bit RenderScript
+// =============================================================================
+
+// CHECK-RS32: [3 x i8] @retChar3()
+// CHECK-RS64: [3 x i8] @retChar3()
+sChar3 retChar3() { sChar3 r; return r; }
+
+// CHECK-RS32: [2 x i16] @retShortChar()
+// CHECK-RS64: [2 x i16] @retShortChar()
+sShortChar retShortChar() { sShortChar r; return r; }
+
+// =============================================================================
+// aggregate parameter <= 16 bytes: coerced to [a x iNN] for both 32-bit and
+// 64-bit RenderScript
+// =============================================================================
+
+typedef struct {short s1; char c; short s2; } sShortCharShort;
+typedef struct {int i; short s; char c; } sIntShortChar;
+typedef struct {long l; int i; } sLongInt;
+
+// CHECK-RS32: void @argShortCharShort([3 x i16] %s.coerce)
+// CHECK-RS64: void @argShortCharShort([3 x i16] %s.coerce)
+void argShortCharShort(sShortCharShort s) {}
+
+// CHECK-RS32: void @argIntShortChar([2 x i32] %s.coerce)
+// CHECK-RS64: void @argIntShortChar([2 x i32] %s.coerce)
+void argIntShortChar(sIntShortChar s) {}
+
+// CHECK-RS32: void @argLongInt([2 x i64] %s.coerce)
+// CHECK-RS64: void @argLongInt([2 x i64] %s.coerce)
+void argLongInt(sLongInt s) {}
+
+// =============================================================================
+// aggregate return value <= 16 bytes: returned on stack for 32-bit RenderScript
+// and coerced to [a x iNN] for 64-bit RenderScript
+// =============================================================================
+
+// CHECK-RS32: void @retShortCharShort(%struct.sShortCharShort* noalias sret %agg.result)
+// CHECK-RS64: [3 x i16] @retShortCharShort()
+sShortCharShort retShortCharShort() { sShortCharShort r; return r; }
+
+// CHECK-RS32: void @retIntShortChar(%struct.sIntShortChar* noalias sret %agg.result)
+// CHECK-RS64: [2 x i32] @retIntShortChar()
+sIntShortChar retIntShortChar() { sIntShortChar r; return r; }
+
+// CHECK-RS32: void @retLongInt(%struct.sLongInt* noalias sret %agg.result)
+// CHECK-RS64: [2 x i64] @retLongInt()
+sLongInt retLongInt() { sLongInt r; return r; }
+
+// =============================================================================
+// aggregate parameter <= 64 bytes: coerced to [a x iNN] for 32-bit RenderScript
+// and passed on the stack for 64-bit RenderScript
+// =============================================================================
+
+typedef struct {int i1, i2, i3, i4, i5; } sInt5;
+typedef struct {long l1, l2; char c; } sLong2Char;
+
+// CHECK-RS32: void @argInt5([5 x i32] %s.coerce)
+// CHECK-RS64: void @argInt5(%struct.sInt5* %s)
+void argInt5(sInt5 s) {}
+
+// CHECK-RS32: void @argLong2Char([3 x i64] %s.coerce)
+// CHECK-RS64: void @argLong2Char(%struct.sLong2Char* %s)
+void argLong2Char(sLong2Char s) {}
+
+// =============================================================================
+// aggregate return value <= 64 bytes: returned on stack for both 32-bit and
+// 64-bit RenderScript
+// =============================================================================
+
+// CHECK-RS32: void @retInt5(%struct.sInt5* noalias sret %agg.result)
+// CHECK-RS64: void @retInt5(%struct.sInt5* noalias sret %agg.result)
+sInt5 retInt5() { sInt5 r; return r;}
+
+// CHECK-RS32: void @retLong2Char(%struct.sLong2Char* noalias sret %agg.result)
+// CHECK-RS64: void @retLong2Char(%struct.sLong2Char* noalias sret %agg.result)
+sLong2Char retLong2Char() { sLong2Char r; return r;}
+
+// =============================================================================
+// aggregate parameters and return values > 64 bytes: passed and returned on the
+// stack for both 32-bit and 64-bit RenderScript
+// =============================================================================
+
+typedef struct {long l1, l2, l3, l4, l5, l6, l7, l8, l9; } sLong9;
+
+// CHECK-RS32: void @argLong9(%struct.sLong9* byval align 8 %s)
+// CHECK-RS64: void @argLong9(%struct.sLong9* %s)
+void argLong9(sLong9 s) {}
+
+// CHECK-RS32: void @retLong9(%struct.sLong9* noalias sret %agg.result)
+// CHECK-RS64: void @retLong9(%struct.sLong9* noalias sret %agg.result)
+sLong9 retLong9() { sLong9 r; return r; }
diff --git a/test/CodeGen/rtm-builtins.c b/test/CodeGen/rtm-builtins.c
index 5cf3237d83e8..44952a07cd77 100644
--- a/test/CodeGen/rtm-builtins.c
+++ b/test/CodeGen/rtm-builtins.c
@@ -1,7 +1,5 @@
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +rtm -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +rtm -emit-llvm -o - | FileCheck %s
-// Don't include mm_malloc.h, it's system specific.
-#define __MM_MALLOC_H
#include <immintrin.h>
diff --git a/test/CodeGen/sanitize-init-order.cpp b/test/CodeGen/sanitize-init-order.cpp
index ee53f7b0771e..894f75e96739 100644
--- a/test/CodeGen/sanitize-init-order.cpp
+++ b/test/CodeGen/sanitize-init-order.cpp
@@ -1,12 +1,11 @@
// RUN: %clang_cc1 -fsanitize=address -emit-llvm -o - %s | FileCheck %s
// Test blacklist functionality.
-// RUN: echo "src:%s=init" > %t-file.blacklist
+// RUN: echo "src:%s=init" | sed -e 's/\\/\\\\/g' > %t-file.blacklist
// RUN: echo "type:PODWithCtorAndDtor=init" > %t-type.blacklist
// RUN: echo "type:NS::PODWithCtor=init" >> %t-type.blacklist
// RUN: %clang_cc1 -fsanitize=address -fsanitize-blacklist=%t-file.blacklist -emit-llvm -o - %s | FileCheck %s --check-prefix=BLACKLIST
// RUN: %clang_cc1 -fsanitize=address -fsanitize-blacklist=%t-type.blacklist -emit-llvm -o - %s | FileCheck %s --check-prefix=BLACKLIST
-// REQUIRES: shell
struct PODStruct {
int x;
diff --git a/test/CodeGen/sanitize-thread-attr.cpp b/test/CodeGen/sanitize-thread-attr.cpp
index 46cab4dbf92f..4e0e28e5e304 100644
--- a/test/CodeGen/sanitize-thread-attr.cpp
+++ b/test/CodeGen/sanitize-thread-attr.cpp
@@ -1,10 +1,8 @@
// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s | FileCheck -check-prefix=WITHOUT %s
// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s -fsanitize=thread | FileCheck -check-prefix=TSAN %s
-// RUN: echo "src:%s" > %t
+// RUN: echo "src:%s" | sed -e 's/\\/\\\\/g' > %t
// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s -fsanitize=thread -fsanitize-blacklist=%t | FileCheck -check-prefix=BL %s
-// REQUIRES: shell
-
// The sanitize_thread attribute should be attached to functions
// when ThreadSanitizer is enabled, unless no_sanitize_thread attribute
// is present.
@@ -56,9 +54,9 @@ int global2 = *(int*)((char*)&global1+1);
// BL: @__cxx_global_var_init{{.*}}[[NOATTR:#[0-9]+]]
// TSAN: @__cxx_global_var_init{{.*}}[[WITH:#[0-9]+]]
-// WITHOUT: attributes [[NOATTR]] = { nounwind{{.*}} }
+// WITHOUT: attributes [[NOATTR]] = { noinline nounwind{{.*}} }
-// BL: attributes [[NOATTR]] = { nounwind{{.*}} }
+// BL: attributes [[NOATTR]] = { noinline nounwind{{.*}} }
-// TSAN: attributes [[NOATTR]] = { nounwind{{.*}} }
-// TSAN: attributes [[WITH]] = { nounwind sanitize_thread{{.*}} }
+// TSAN: attributes [[NOATTR]] = { noinline nounwind{{.*}} }
+// TSAN: attributes [[WITH]] = { noinline nounwind sanitize_thread{{.*}} }
diff --git a/test/CodeGen/sanitize-thread-no-checking-at-run-time.m b/test/CodeGen/sanitize-thread-no-checking-at-run-time.m
new file mode 100644
index 000000000000..098b7cf72ffd
--- /dev/null
+++ b/test/CodeGen/sanitize-thread-no-checking-at-run-time.m
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -x objective-c++ -emit-llvm -o - %s | FileCheck -check-prefix=WITHOUT %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -x objective-c++ -emit-llvm -o - %s -fsanitize=thread | FileCheck -check-prefix=TSAN %s
+
+__attribute__((objc_root_class))
+@interface NSObject
+- (void)dealloc;
+@end
+
+class NeedCleanup {
+public:
+ ~NeedCleanup() __attribute__((no_sanitize("thread"))) {}
+};
+
+@interface MyObject : NSObject {
+ NeedCleanup v;
+};
++ (void) initialize;
+- (void) dealloc;
+@end
+
+@implementation MyObject
++ (void)initialize {
+}
+- (void)dealloc {
+ [super dealloc];
+}
+@end
+
+// WITHOUT-NOT: "sanitize_thread_no_checking_at_run_time"
+
+// TSAN: initialize{{.*}}) [[ATTR:#[0-9]+]]
+// TSAN: dealloc{{.*}}) [[ATTR:#[0-9]+]]
+// TSAN: cxx_destruct{{.*}}) [[ATTR:#[0-9]+]]
+// TSAN: attributes [[ATTR]] = { noinline nounwind {{.*}} "sanitize_thread_no_checking_at_run_time" {{.*}} }
diff --git a/test/CodeGen/sha-builtins.c b/test/CodeGen/sha-builtins.c
index 9c14a1ea7f0a..ede1a6bf7b1f 100644
--- a/test/CodeGen/sha-builtins.c
+++ b/test/CodeGen/sha-builtins.c
@@ -1,7 +1,5 @@
-// RUN: %clang_cc1 %s -triple=x86_64-unknown-unknown -target-feature +sha -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-unknown-unknown -target-feature +sha -emit-llvm -o - | FileCheck %s
-// Don't include mm_malloc.h, it's system specific.
-#define __MM_MALLOC_H
#include <immintrin.h>
diff --git a/test/CodeGen/split-debug-filename.c b/test/CodeGen/split-debug-filename.c
index 63970a83df10..43daeada96ab 100644
--- a/test/CodeGen/split-debug-filename.c
+++ b/test/CodeGen/split-debug-filename.c
@@ -1,7 +1,7 @@
-// RUN: %clang -target x86_64-linux-gnu -gsplit-dwarf -S -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -debug-info-kind=limited -split-dwarf-file foo.dwo -S -emit-llvm -o - %s | FileCheck %s
int main (void) {
return 0;
}
// Testing to ensure that the dwo name gets output into the compile unit.
-// CHECK: split-debug-filename.dwo
+// CHECK: !DICompileUnit({{.*}}, splitDebugFilename: "foo.dwo"
diff --git a/test/CodeGen/split-debug-inlining.c b/test/CodeGen/split-debug-inlining.c
new file mode 100644
index 000000000000..4a306d43e952
--- /dev/null
+++ b/test/CodeGen/split-debug-inlining.c
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -debug-info-kind=limited -fno-split-dwarf-inlining -S -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -debug-info-kind=limited -S -emit-llvm -o - %s | FileCheck --check-prefix=ABSENT %s
+void f(void) {}
+// Verify that disabling split debug inlining info is propagated to the debug
+// info metadata.
+// CHECK: !DICompileUnit({{.*}}, splitDebugInlining: false
+// ABSENT-NOT: splitDebugInlining
diff --git a/test/CodeGen/sse-builtins.c b/test/CodeGen/sse-builtins.c
index 6f313b825c9a..27b016f66517 100644
--- a/test/CodeGen/sse-builtins.c
+++ b/test/CodeGen/sse-builtins.c
@@ -1,7 +1,5 @@
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +sse -emit-llvm -o - -Werror | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +sse -emit-llvm -o - -Wall -Werror | FileCheck %s
-// Don't include mm_malloc.h, it's system specific.
-#define __MM_MALLOC_H
#include <x86intrin.h>
diff --git a/test/CodeGen/sse.c b/test/CodeGen/sse.c
index 1e8c5dbe5dec..1191f55f81e7 100644
--- a/test/CodeGen/sse.c
+++ b/test/CodeGen/sse.c
@@ -1,8 +1,6 @@
-// RUN: %clang_cc1 -O3 -triple x86_64-apple-macosx10.8.0 -target-feature +sse4.1 -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding -O3 -triple x86_64-apple-macosx10.8.0 -target-feature +sse4.1 -emit-llvm %s -o - | FileCheck %s
// FIXME: This test currently depends on optimization - it should be rewritten to avoid it.
-// Don't include mm_malloc.h, it's system specific.
-#define __MM_MALLOC_H
#include <emmintrin.h>
diff --git a/test/CodeGen/sse2-builtins.c b/test/CodeGen/sse2-builtins.c
index ee9dca7d4451..48c703685479 100644
--- a/test/CodeGen/sse2-builtins.c
+++ b/test/CodeGen/sse2-builtins.c
@@ -1,8 +1,6 @@
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +sse2 -emit-llvm -o - -Werror | FileCheck %s
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +sse2 -fno-signed-char -emit-llvm -o - -Werror | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +sse2 -emit-llvm -o - -Wall -Werror | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +sse2 -fno-signed-char -emit-llvm -o - -Wall -Werror | FileCheck %s
-// Don't include mm_malloc.h, it's system specific.
-#define __MM_MALLOC_H
#include <x86intrin.h>
@@ -73,7 +71,7 @@ __m128i test_mm_adds_epu16(__m128i A, __m128i B) {
__m128d test_mm_and_pd(__m128d A, __m128d B) {
// CHECK-LABEL: test_mm_and_pd
- // CHECK: and <4 x i32>
+ // CHECK: and <2 x i64>
return _mm_and_pd(A, B);
}
@@ -85,8 +83,8 @@ __m128i test_mm_and_si128(__m128i A, __m128i B) {
__m128d test_mm_andnot_pd(__m128d A, __m128d B) {
// CHECK-LABEL: test_mm_andnot_pd
- // CHECK: xor <4 x i32> %{{.*}}, <i32 -1, i32 -1, i32 -1, i32 -1>
- // CHECK: and <4 x i32>
+ // CHECK: xor <2 x i64> %{{.*}}, <i64 -1, i64 -1>
+ // CHECK: and <2 x i64>
return _mm_andnot_pd(A, B);
}
@@ -845,7 +843,7 @@ __m128i test_mm_mullo_epi16(__m128i A, __m128i B) {
__m128d test_mm_or_pd(__m128d A, __m128d B) {
// CHECK-LABEL: test_mm_or_pd
- // CHECK: or <4 x i32> %{{.*}}, %{{.*}}
+ // CHECK: or <2 x i64> %{{.*}}, %{{.*}}
return _mm_or_pd(A, B);
}
@@ -1529,7 +1527,7 @@ __m128d test_mm_unpacklo_pd(__m128d A, __m128d B) {
__m128d test_mm_xor_pd(__m128d A, __m128d B) {
// CHECK-LABEL: test_mm_xor_pd
- // CHECK: xor <4 x i32> %{{.*}}, %{{.*}}
+ // CHECK: xor <2 x i64> %{{.*}}, %{{.*}}
return _mm_xor_pd(A, B);
}
diff --git a/test/CodeGen/sse3-builtins.c b/test/CodeGen/sse3-builtins.c
index b046c431fd50..46a7bbbb91e2 100644
--- a/test/CodeGen/sse3-builtins.c
+++ b/test/CodeGen/sse3-builtins.c
@@ -1,7 +1,5 @@
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +sse3 -emit-llvm -o - -Werror | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +sse3 -emit-llvm -o - -Wall -Werror | FileCheck %s
-// Don't include mm_malloc.h, it's system specific.
-#define __MM_MALLOC_H
#include <x86intrin.h>
diff --git a/test/CodeGen/sse41-builtins.c b/test/CodeGen/sse41-builtins.c
index ad24ecd5ed1b..adf9609b68f9 100644
--- a/test/CodeGen/sse41-builtins.c
+++ b/test/CodeGen/sse41-builtins.c
@@ -1,8 +1,6 @@
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +sse4.1 -emit-llvm -o - -Werror | FileCheck %s
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +sse4.1 -fno-signed-char -emit-llvm -o - -Werror | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +sse4.1 -emit-llvm -o - -Wall -Werror | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +sse4.1 -fno-signed-char -emit-llvm -o - -Wall -Werror | FileCheck %s
-// Don't include mm_malloc.h, it's system specific.
-#define __MM_MALLOC_H
#include <x86intrin.h>
diff --git a/test/CodeGen/sse42-builtins.c b/test/CodeGen/sse42-builtins.c
index 00f7ff93afe2..523db1a3416e 100644
--- a/test/CodeGen/sse42-builtins.c
+++ b/test/CodeGen/sse42-builtins.c
@@ -1,8 +1,6 @@
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +sse4.2 -emit-llvm -o - -Werror | FileCheck %s
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +sse4.2 -fno-signed-char -emit-llvm -o - -Werror | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +sse4.2 -emit-llvm -o - -Wall -Werror | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +sse4.2 -fno-signed-char -emit-llvm -o - -Wall -Werror | FileCheck %s
-// Don't include mm_malloc.h, it's system specific.
-#define __MM_MALLOC_H
#include <x86intrin.h>
diff --git a/test/CodeGen/sse4a-builtins.c b/test/CodeGen/sse4a-builtins.c
index 0604423fe17e..3d36a7dfa007 100644
--- a/test/CodeGen/sse4a-builtins.c
+++ b/test/CodeGen/sse4a-builtins.c
@@ -1,7 +1,5 @@
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +sse4a -emit-llvm -o - -Werror | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +sse4a -emit-llvm -o - -Wall -Werror | FileCheck %s
-// Don't include mm_malloc.h, it's system specific.
-#define __MM_MALLOC_H
#include <x86intrin.h>
diff --git a/test/CodeGen/ssse3-builtins.c b/test/CodeGen/ssse3-builtins.c
index 673387c066b2..b2279e277cd2 100644
--- a/test/CodeGen/ssse3-builtins.c
+++ b/test/CodeGen/ssse3-builtins.c
@@ -1,7 +1,5 @@
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +ssse3 -emit-llvm -o - -Werror | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +ssse3 -emit-llvm -o - -Wall -Werror | FileCheck %s
-// Don't include mm_malloc.h, it's system specific.
-#define __MM_MALLOC_H
#include <x86intrin.h>
diff --git a/test/CodeGen/systemz-abi-vector.c b/test/CodeGen/systemz-abi-vector.c
index 1d1f302e6324..455e3bbcced2 100644
--- a/test/CodeGen/systemz-abi-vector.c
+++ b/test/CodeGen/systemz-abi-vector.c
@@ -4,6 +4,8 @@
// RUN: -emit-llvm -o - %s | FileCheck --check-prefix=CHECK-VECTOR %s
// RUN: %clang_cc1 -triple s390x-linux-gnu -target-cpu z13 \
// RUN: -emit-llvm -o - %s | FileCheck --check-prefix=CHECK-VECTOR %s
+// RUN: %clang_cc1 -triple s390x-linux-gnu -target-cpu arch11 \
+// RUN: -emit-llvm -o - %s | FileCheck --check-prefix=CHECK-VECTOR %s
// Vector types
diff --git a/test/CodeGen/systemz-abi.c b/test/CodeGen/systemz-abi.c
index 375d02a35889..17fdb9e322c8 100644
--- a/test/CodeGen/systemz-abi.c
+++ b/test/CodeGen/systemz-abi.c
@@ -4,6 +4,8 @@
// RUN: -emit-llvm -o - %s | FileCheck %s
// RUN: %clang_cc1 -triple s390x-linux-gnu -target-cpu z13 \
// RUN: -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple s390x-linux-gnu -target-cpu arch11 \
+// RUN: -emit-llvm -o - %s | FileCheck %s
// Scalar types
diff --git a/test/CodeGen/target-data.c b/test/CodeGen/target-data.c
index c12ad2c1c977..1e8ce6a2fd12 100644
--- a/test/CodeGen/target-data.c
+++ b/test/CodeGen/target-data.c
@@ -169,6 +169,8 @@
// RUN: %clang_cc1 -triple s390x-unknown -target-cpu z13 -o - -emit-llvm %s | \
// RUN: FileCheck %s -check-prefix=SYSTEMZ-VECTOR
+// RUN: %clang_cc1 -triple s390x-unknown -target-cpu arch11 -o - -emit-llvm %s | \
+// RUN: FileCheck %s -check-prefix=SYSTEMZ-VECTOR
// SYSTEMZ-VECTOR: target datalayout = "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64"
// RUN: %clang_cc1 -triple msp430-unknown -o - -emit-llvm %s | \
@@ -177,7 +179,11 @@
// RUN: %clang_cc1 -triple tce-unknown -o - -emit-llvm %s | \
// RUN: FileCheck %s -check-prefix=TCE
-// TCE: target datalayout = "E-p:32:32-i8:8:32-i16:16:32-i64:32-f64:32-v64:32-v128:32-a:0:32-n32"
+// TCE: target datalayout = "E-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:32:32-v128:32:32-v256:32:32-v512:32:32-v1024:32:32-a0:0:32-n32"
+
+// RUN: %clang_cc1 -triple tcele-unknown -o - -emit-llvm %s | \
+// RUN: FileCheck %s -check-prefix=TCELE
+// TCELE: target datalayout = "e-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:32:32-v128:32:32-v256:32:32-v512:32:32-v1024:32:32-a0:0:32-n32"
// RUN: %clang_cc1 -triple spir-unknown -o - -emit-llvm %s | \
// RUN: FileCheck %s -check-prefix=SPIR
diff --git a/test/CodeGen/tbaa-class.cpp b/test/CodeGen/tbaa-class.cpp
index 7172e05d9e34..9b614a19e8b0 100644
--- a/test/CodeGen/tbaa-class.cpp
+++ b/test/CodeGen/tbaa-class.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin -O1 -no-struct-path-tbaa -disable-llvm-optzns %s -emit-llvm -o - | FileCheck %s
-// RUN: %clang_cc1 -triple x86_64-apple-darwin -O1 -disable-llvm-optzns %s -emit-llvm -o - | FileCheck %s -check-prefix=PATH
+// 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
// Test TBAA metadata generated by front-end.
typedef unsigned char uint8_t;
diff --git a/test/CodeGen/tbaa-ms-abi.cpp b/test/CodeGen/tbaa-ms-abi.cpp
index 878e1b610b59..51100b18c3d4 100644
--- a/test/CodeGen/tbaa-ms-abi.cpp
+++ b/test/CodeGen/tbaa-ms-abi.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple i686-pc-win32 -disable-llvm-optzns -emit-llvm -o - -O1 %s | FileCheck %s
+// RUN: %clang_cc1 -triple i686-pc-win32 -disable-llvm-passes -emit-llvm -o - -O1 %s | FileCheck %s
//
// Test that TBAA works in the Microsoft C++ ABI. We used to error out while
// attempting to mangle RTTI.
diff --git a/test/CodeGen/tbaa.cpp b/test/CodeGen/tbaa.cpp
index 432c41e10793..10e64875476c 100644
--- a/test/CodeGen/tbaa.cpp
+++ b/test/CodeGen/tbaa.cpp
@@ -1,7 +1,7 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin -O1 -no-struct-path-tbaa -disable-llvm-optzns %s -emit-llvm -o - | FileCheck %s
-// RUN: %clang_cc1 -triple x86_64-apple-darwin -O1 -disable-llvm-optzns %s -emit-llvm -o - | FileCheck %s -check-prefix=PATH
-// RUN: %clang_cc1 -triple x86_64-apple-darwin -O0 -disable-llvm-optzns %s -emit-llvm -o - | FileCheck %s -check-prefix=NO-TBAA
-// RUN: %clang_cc1 -triple x86_64-apple-darwin -O1 -relaxed-aliasing -disable-llvm-optzns %s -emit-llvm -o - | FileCheck %s -check-prefix=NO-TBAA
+// 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 -O0 -disable-llvm-passes %s -emit-llvm -o - | FileCheck %s -check-prefix=NO-TBAA
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -O1 -relaxed-aliasing -disable-llvm-passes %s -emit-llvm -o - | FileCheck %s -check-prefix=NO-TBAA
// Test TBAA metadata generated by front-end.
//
// NO-TBAA-NOT: !tbaa
diff --git a/test/CodeGen/tbm-builtins.c b/test/CodeGen/tbm-builtins.c
index c8a9382ed17d..8e031408a4b6 100644
--- a/test/CodeGen/tbm-builtins.c
+++ b/test/CodeGen/tbm-builtins.c
@@ -1,10 +1,8 @@
-// RUN: %clang_cc1 %s -O3 -triple=x86_64-unknown-unknown -target-feature +tbm -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -O3 -triple=x86_64-unknown-unknown -target-feature +tbm -emit-llvm -o - | FileCheck %s
// FIXME: The code generation checks for add/sub and/or are depending on the optimizer.
// The REQUIRES keyword will be removed when the FIXME is complete.
// REQUIRES: x86-registered-target
-// Don't include mm_malloc.h, it's system specific.
-#define __MM_MALLOC_H
#include <x86intrin.h>
diff --git a/test/CodeGen/temporary-lifetime-exceptions.cpp b/test/CodeGen/temporary-lifetime-exceptions.cpp
index 17e21683f22c..f435560c9759 100644
--- a/test/CodeGen/temporary-lifetime-exceptions.cpp
+++ b/test/CodeGen/temporary-lifetime-exceptions.cpp
@@ -9,16 +9,16 @@ A Baz(const A&);
void Test1() {
// CHECK-LABEL: @_Z5Test1v(
// CHECK: getelementptr
- // CHECK-NEXT: call void @llvm.lifetime.start(i64 1, i8* [[TMP:[^ ]+]])
+ // CHECK-NEXT: call void @llvm.lifetime.start(i64 1, i8* nonnull [[TMP:[^ ]+]])
// CHECK-NEXT: getelementptr
- // CHECK-NEXT: call void @llvm.lifetime.start(i64 1, i8* [[TMP1:[^ ]+]])
+ // CHECK-NEXT: call void @llvm.lifetime.start(i64 1, i8* nonnull [[TMP1:[^ ]+]])
// Normal exit
- // CHECK: call void @llvm.lifetime.end(i64 1, i8* [[TMP1]])
- // CHECK-NEXT: call void @llvm.lifetime.end(i64 1, i8* [[TMP]])
+ // CHECK: call void @llvm.lifetime.end(i64 1, i8* nonnull [[TMP1]])
+ // CHECK-NEXT: call void @llvm.lifetime.end(i64 1, i8* nonnull [[TMP]])
// Exception exit
- // CHECK: call void @llvm.lifetime.end(i64 1, i8* [[TMP1]])
- // CHECK-NEXT: call void @llvm.lifetime.end(i64 1, i8* [[TMP]])
+ // CHECK: call void @llvm.lifetime.end(i64 1, i8* nonnull [[TMP1]])
+ // CHECK-NEXT: call void @llvm.lifetime.end(i64 1, i8* nonnull [[TMP]])
Baz(Baz(A()));
}
diff --git a/test/CodeGen/temporary-lifetime.cpp b/test/CodeGen/temporary-lifetime.cpp
index f6dd3e0b2a53..f105a441a367 100644
--- a/test/CodeGen/temporary-lifetime.cpp
+++ b/test/CodeGen/temporary-lifetime.cpp
@@ -21,27 +21,27 @@ T Baz();
void Test1() {
// CHECK-DTOR-LABEL: Test1
- // CHECK-DTOR: call void @llvm.lifetime.start(i64 1024, i8* %[[ADDR:[0-9]+]])
+ // CHECK-DTOR: call void @llvm.lifetime.start(i64 1024, i8* nonnull %[[ADDR:[0-9]+]])
// CHECK-DTOR: call void @_ZN1AC1Ev(%struct.A* nonnull %[[VAR:[^ ]+]])
// CHECK-DTOR: call void @_Z3FooIRK1AEvOT_
// CHECK-DTOR: call void @_ZN1AD1Ev(%struct.A* nonnull %[[VAR]])
- // CHECK-DTOR: call void @llvm.lifetime.end(i64 1024, i8* %[[ADDR]])
- // CHECK-DTOR: call void @llvm.lifetime.start(i64 1024, i8* %[[ADDR:[0-9]+]])
+ // CHECK-DTOR: call void @llvm.lifetime.end(i64 1024, i8* nonnull %[[ADDR]])
+ // CHECK-DTOR: call void @llvm.lifetime.start(i64 1024, i8* nonnull %[[ADDR:[0-9]+]])
// CHECK-DTOR: call void @_ZN1AC1Ev(%struct.A* nonnull %[[VAR:[^ ]+]])
// CHECK-DTOR: call void @_Z3FooIRK1AEvOT_
// CHECK-DTOR: call void @_ZN1AD1Ev(%struct.A* nonnull %[[VAR]])
- // CHECK-DTOR: call void @llvm.lifetime.end(i64 1024, i8* %[[ADDR]])
+ // CHECK-DTOR: call void @llvm.lifetime.end(i64 1024, i8* nonnull %[[ADDR]])
// CHECK-DTOR: }
// CHECK-NO-DTOR-LABEL: Test1
- // CHECK-NO-DTOR: call void @llvm.lifetime.start(i64 1024, i8* %[[ADDR:[0-9]+]])
+ // CHECK-NO-DTOR: call void @llvm.lifetime.start(i64 1024, i8* nonnull %[[ADDR:[0-9]+]])
// CHECK-NO-DTOR: call void @_ZN1AC1Ev(%struct.A* nonnull %[[VAR:[^ ]+]])
// CHECK-NO-DTOR: call void @_Z3FooIRK1AEvOT_
- // CHECK-NO-DTOR: call void @llvm.lifetime.end(i64 1024, i8* %[[ADDR]])
- // CHECK-NO-DTOR: call void @llvm.lifetime.start(i64 1024, i8* %[[ADDR:[0-9]+]])
+ // CHECK-NO-DTOR: call void @llvm.lifetime.end(i64 1024, i8* nonnull %[[ADDR]])
+ // CHECK-NO-DTOR: call void @llvm.lifetime.start(i64 1024, i8* nonnull %[[ADDR:[0-9]+]])
// CHECK-NO-DTOR: call void @_ZN1AC1Ev(%struct.A* nonnull %[[VAR:[^ ]+]])
// CHECK-NO-DTOR: call void @_Z3FooIRK1AEvOT_
- // CHECK-NO-DTOR: call void @llvm.lifetime.end(i64 1024, i8* %[[ADDR]])
+ // CHECK-NO-DTOR: call void @llvm.lifetime.end(i64 1024, i8* nonnull %[[ADDR]])
// CHECK-NO-DTOR: }
{
const A &a = A{};
@@ -55,27 +55,27 @@ void Test1() {
void Test2() {
// CHECK-DTOR-LABEL: Test2
- // CHECK-DTOR: call void @llvm.lifetime.start(i64 1024, i8* %[[ADDR1:[0-9]+]])
+ // CHECK-DTOR: call void @llvm.lifetime.start(i64 1024, i8* nonnull %[[ADDR1:[0-9]+]])
// CHECK-DTOR: call void @_ZN1AC1Ev(%struct.A* nonnull %[[VAR1:[^ ]+]])
// CHECK-DTOR: call void @_Z3FooIRK1AEvOT_
- // CHECK-DTOR: call void @llvm.lifetime.start(i64 1024, i8* %[[ADDR2:[0-9]+]])
+ // CHECK-DTOR: call void @llvm.lifetime.start(i64 1024, i8* nonnull %[[ADDR2:[0-9]+]])
// CHECK-DTOR: call void @_ZN1AC1Ev(%struct.A* nonnull %[[VAR2:[^ ]+]])
// CHECK-DTOR: call void @_Z3FooIRK1AEvOT_
// CHECK-DTOR: call void @_ZN1AD1Ev(%struct.A* nonnull %[[VAR2]])
- // CHECK-DTOR: call void @llvm.lifetime.end(i64 1024, i8* %[[ADDR2]])
+ // CHECK-DTOR: call void @llvm.lifetime.end(i64 1024, i8* nonnull %[[ADDR2]])
// CHECK-DTOR: call void @_ZN1AD1Ev(%struct.A* nonnull %[[VAR1]])
- // CHECK-DTOR: call void @llvm.lifetime.end(i64 1024, i8* %[[ADDR1]])
+ // CHECK-DTOR: call void @llvm.lifetime.end(i64 1024, i8* nonnull %[[ADDR1]])
// CHECK-DTOR: }
// CHECK-NO-DTOR-LABEL: Test2
- // CHECK-NO-DTOR: call void @llvm.lifetime.start(i64 1024, i8* %[[ADDR1:[0-9]+]])
+ // CHECK-NO-DTOR: call void @llvm.lifetime.start(i64 1024, i8* nonnull %[[ADDR1:[0-9]+]])
// CHECK-NO-DTOR: call void @_ZN1AC1Ev(%struct.A* nonnull %[[VAR1:[^ ]+]])
// CHECK-NO-DTOR: call void @_Z3FooIRK1AEvOT_
- // CHECK-NO-DTOR: call void @llvm.lifetime.start(i64 1024, i8* %[[ADDR2:[0-9]+]])
+ // CHECK-NO-DTOR: call void @llvm.lifetime.start(i64 1024, i8* nonnull %[[ADDR2:[0-9]+]])
// CHECK-NO-DTOR: call void @_ZN1AC1Ev(%struct.A* nonnull %[[VAR2:[^ ]+]])
// CHECK-NO-DTOR: call void @_Z3FooIRK1AEvOT_
- // CHECK-NO-DTOR: call void @llvm.lifetime.end(i64 1024, i8* %[[ADDR2]])
- // CHECK-NO-DTOR: call void @llvm.lifetime.end(i64 1024, i8* %[[ADDR1]])
+ // CHECK-NO-DTOR: call void @llvm.lifetime.end(i64 1024, i8* nonnull %[[ADDR2]])
+ // CHECK-NO-DTOR: call void @llvm.lifetime.end(i64 1024, i8* nonnull %[[ADDR1]])
// CHECK-NO-DTOR: }
const A &a = A{};
Foo(a);
@@ -135,16 +135,16 @@ int Test5() {
void Test6() {
// CHECK-DTOR-LABEL: Test6
- // CHECK-DTOR: call void @llvm.lifetime.start(i64 {{[0-9]+}}, i8* %[[ADDR:[0-9]+]])
+ // CHECK-DTOR: call void @llvm.lifetime.start(i64 {{[0-9]+}}, i8* nonnull %[[ADDR:[0-9]+]])
// CHECK-DTOR: call i32 @_Z3BazIiET_v()
// CHECK-DTOR: store
// CHECK-DTOR: call void @_Z3FooIiEvOT_
- // CHECK-DTOR: call void @llvm.lifetime.end(i64 {{[0-9]+}}, i8* %[[ADDR]])
- // CHECK-DTOR: call void @llvm.lifetime.start(i64 {{[0-9]+}}, i8* %[[ADDR:[0-9]+]])
+ // CHECK-DTOR: call void @llvm.lifetime.end(i64 {{[0-9]+}}, i8* nonnull %[[ADDR]])
+ // CHECK-DTOR: call void @llvm.lifetime.start(i64 {{[0-9]+}}, i8* nonnull %[[ADDR:[0-9]+]])
// CHECK-DTOR: call i32 @_Z3BazIiET_v()
// CHECK-DTOR: store
// CHECK-DTOR: call void @_Z3FooIiEvOT_
- // CHECK-DTOR: call void @llvm.lifetime.end(i64 {{[0-9]+}}, i8* %[[ADDR]])
+ // CHECK-DTOR: call void @llvm.lifetime.end(i64 {{[0-9]+}}, i8* nonnull %[[ADDR]])
// CHECK-DTOR: }
Foo(Baz<int>());
Foo(Baz<int>());
@@ -152,16 +152,16 @@ void Test6() {
void Test7() {
// CHECK-DTOR-LABEL: Test7
- // CHECK-DTOR: call void @llvm.lifetime.start(i64 1024, i8* %[[ADDR:[0-9]+]])
+ // CHECK-DTOR: call void @llvm.lifetime.start(i64 1024, i8* nonnull %[[ADDR:[0-9]+]])
// CHECK-DTOR: call void @_Z3BazI1AET_v({{.*}} %[[SLOT:[^ ]+]])
// CHECK-DTOR: call void @_Z3FooI1AEvOT_({{.*}} %[[SLOT]])
// CHECK-DTOR: call void @_ZN1AD1Ev(%struct.A* nonnull %[[SLOT]])
- // CHECK-DTOR: call void @llvm.lifetime.end(i64 1024, i8* %[[ADDR]])
- // CHECK-DTOR: call void @llvm.lifetime.start(i64 1024, i8* %[[ADDR:[0-9]+]])
+ // CHECK-DTOR: call void @llvm.lifetime.end(i64 1024, i8* nonnull %[[ADDR]])
+ // CHECK-DTOR: call void @llvm.lifetime.start(i64 1024, i8* nonnull %[[ADDR:[0-9]+]])
// CHECK-DTOR: call void @_Z3BazI1AET_v({{.*}} %[[SLOT:[^ ]+]])
// CHECK-DTOR: call void @_Z3FooI1AEvOT_({{.*}} %[[SLOT]])
// CHECK-DTOR: call void @_ZN1AD1Ev(%struct.A* nonnull %[[SLOT]])
- // CHECK-DTOR: call void @llvm.lifetime.end(i64 1024, i8* %[[ADDR]])
+ // CHECK-DTOR: call void @llvm.lifetime.end(i64 1024, i8* nonnull %[[ADDR]])
// CHECK-DTOR: }
Foo(Baz<A>());
Foo(Baz<A>());
diff --git a/test/CodeGen/thinlto_backend.ll b/test/CodeGen/thinlto_backend.ll
index 0fb2643e037d..89f4fc407fbc 100644
--- a/test/CodeGen/thinlto_backend.ll
+++ b/test/CodeGen/thinlto_backend.ll
@@ -9,8 +9,8 @@
; CHECK-WARNING: error: invalid argument '-fthinlto-index={{.*}}' only allowed with '-x ir'
; Ensure we get expected error for missing index file
-; RUN: %clang -O2 -o %t3.o -x ir %t1.o -c -fthinlto-index=bad.thinlto.bc 2>&1 | FileCheck %s -check-prefix=CHECK-ERROR
-; CHECK-ERROR: Error loading index file 'bad.thinlto.bc'
+; RUN: %clang -O2 -o %t4.o -x ir %t1.o -c -fthinlto-index=bad.thinlto.bc 2>&1 | FileCheck %s -check-prefix=CHECK-ERROR1
+; CHECK-ERROR1: Error loading index file 'bad.thinlto.bc'
; 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
@@ -18,6 +18,11 @@
; CHECK-OBJ: T f1
; CHECK-OBJ-NOT: U f2
+; Ensure we get expected error for input files without summaries
+; RUN: opt -o %t2.o %s
+; RUN: %clang -target x86_64-unknown-linux-gnu -O2 -o %t3.o -x ir %t1.o -c -fthinlto-index=%t.thinlto.bc 2>&1 | FileCheck %s -check-prefix=CHECK-ERROR2
+; CHECK-ERROR2: Error loading imported file '{{.*}}': Could not find module summary
+
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
diff --git a/test/CodeGen/ubsan-blacklist.c b/test/CodeGen/ubsan-blacklist.c
index f6e38822bff8..666003bd9233 100644
--- a/test/CodeGen/ubsan-blacklist.c
+++ b/test/CodeGen/ubsan-blacklist.c
@@ -1,13 +1,10 @@
// Verify ubsan doesn't emit checks for blacklisted functions and files
// RUN: echo "fun:hash" > %t-func.blacklist
-// RUN: echo "src:%s" > %t-file.blacklist
+// RUN: echo "src:%s" | sed -e 's/\\/\\\\/g' > %t-file.blacklist
// RUN: %clang_cc1 -fsanitize=unsigned-integer-overflow -emit-llvm %s -o - | FileCheck %s --check-prefix=DEFAULT
// RUN: %clang_cc1 -fsanitize=unsigned-integer-overflow -fsanitize-blacklist=%t-func.blacklist -emit-llvm %s -o - | FileCheck %s --check-prefix=FUNC
// RUN: %clang_cc1 -fsanitize=unsigned-integer-overflow -fsanitize-blacklist=%t-file.blacklist -emit-llvm %s -o - | FileCheck %s --check-prefix=FILE
-// FIXME: %t-file.blacklist contains DOSish paths.
-// REQUIRES: shell
-
unsigned i;
// DEFAULT: @hash
diff --git a/test/CodeGen/unwind-attr.c b/test/CodeGen/unwind-attr.c
index 527237578ee4..2065653e0de4 100644
--- a/test/CodeGen/unwind-attr.c
+++ b/test/CodeGen/unwind-attr.c
@@ -23,7 +23,7 @@ __attribute__((weak)) int test2(void) {
return 0;
}
-// CHECK: attributes [[TF]] = { "{{.*}} }
-// CHECK: attributes [[NUW]] = { nounwind{{.*}} }
+// CHECK: attributes [[TF]] = { noinline "{{.*}} }
+// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} }
-// CHECK-NOEXC: attributes [[NUW]] = { nounwind{{.*}} }
+// CHECK-NOEXC: attributes [[NUW]] = { noinline nounwind{{.*}} }
diff --git a/test/CodeGen/vecshift.c b/test/CodeGen/vecshift.c
new file mode 100644
index 000000000000..1fa047cd30b9
--- /dev/null
+++ b/test/CodeGen/vecshift.c
@@ -0,0 +1,162 @@
+// RUN: %clang_cc1 -Wno-error-vec-elem-size -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -Wno-error-vec-elem-size -DEXT -emit-llvm %s -o - | FileCheck %s
+
+#ifdef EXT
+typedef __attribute__((__ext_vector_type__(8))) char vector_char8;
+typedef __attribute__((__ext_vector_type__(8))) short vector_short8;
+typedef __attribute__((__ext_vector_type__(8))) int vector_int8;
+typedef __attribute__((__ext_vector_type__(8))) unsigned char vector_uchar8;
+typedef __attribute__((__ext_vector_type__(8))) unsigned short vector_ushort8;
+typedef __attribute__((__ext_vector_type__(8))) unsigned int vector_uint8;
+typedef __attribute__((__ext_vector_type__(4))) char vector_char4;
+typedef __attribute__((__ext_vector_type__(4))) short vector_short4;
+typedef __attribute__((__ext_vector_type__(4))) int vector_int4;
+typedef __attribute__((__ext_vector_type__(4))) unsigned char vector_uchar4;
+typedef __attribute__((__ext_vector_type__(4))) unsigned short vector_ushort4;
+typedef __attribute__((__ext_vector_type__(4))) unsigned int vector_uint4;
+#else
+typedef __attribute__((vector_size(8))) char vector_char8;
+typedef __attribute__((vector_size(16))) short vector_short8;
+typedef __attribute__((vector_size(32))) int vector_int8;
+typedef __attribute__((vector_size(8))) unsigned char vector_uchar8;
+typedef __attribute__((vector_size(16))) unsigned short vector_ushort8;
+typedef __attribute__((vector_size(32))) unsigned int vector_uint8;
+typedef __attribute__((vector_size(4))) char vector_char4;
+typedef __attribute__((vector_size(4))) short vector_short4;
+typedef __attribute__((vector_size(16))) int vector_int4;
+typedef __attribute__((vector_size(4))) unsigned char vector_uchar4;
+typedef __attribute__((vector_size(8))) unsigned short vector_ushort4;
+typedef __attribute__((vector_size(16))) unsigned int vector_uint4;
+#endif
+
+char c;
+short s;
+int i;
+unsigned char uc;
+unsigned short us;
+unsigned int ui;
+vector_char8 vc8;
+vector_short8 vs8;
+vector_int8 vi8;
+vector_uchar8 vuc8;
+vector_ushort8 vus8;
+vector_uint8 vui8;
+vector_char4 vc4;
+vector_short4 vs4;
+vector_int4 vi4;
+vector_uchar4 vuc4;
+vector_ushort4 vus4;
+vector_uint4 vui4;
+
+void foo() {
+ vc8 = 1 << vc8;
+// CHECK: [[t0:%.+]] = load <8 x i8>, <8 x i8>* {{@.+}},
+// CHECK: shl <8 x i8> <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1>, [[t0]]
+ vuc8 = 1 << vuc8;
+// CHECK: [[t1:%.+]] = load <8 x i8>, <8 x i8>* {{@.+}},
+// CHECK: shl <8 x i8> <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1>, [[t1]]
+ vi8 = 1 << vi8;
+// CHECK: [[t2:%.+]] = load <8 x i32>, <8 x i32>* {{@.+}},
+// CHECK: shl <8 x i32> <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>, [[t2]]
+ vui8 = 1 << vui8;
+// CHECK: [[t3:%.+]] = load <8 x i32>, <8 x i32>* {{@.+}},
+// CHECK: shl <8 x i32> <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>, [[t3]]
+ vs8 = 1 << vs8;
+// CHECK: [[t4:%.+]] = load <8 x i16>, <8 x i16>* {{@.+}},
+// CHECK: shl <8 x i16> <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>, [[t4]]
+ vus8 = 1 << vus8;
+// CHECK: [[t5:%.+]] = load <8 x i16>, <8 x i16>* {{@.+}},
+// CHECK: shl <8 x i16> <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>, [[t5]]
+
+ vc8 = c << vc8;
+// CHECK: [[t6:%.+]] = load i8, i8* @c,
+// CHECK: [[splat_splatinsert:%.+]] = insertelement <8 x i8> undef, i8 [[t6]], i32 0
+// CHECK: [[splat_splat:%.+]] = shufflevector <8 x i8> [[splat_splatinsert]], <8 x i8> undef, <8 x i32> zeroinitializer
+// CHECK: [[t7:%.+]] = load <8 x i8>, <8 x i8>* {{@.+}},
+// CHECK: shl <8 x i8> [[splat_splat]], [[t7]]
+ vuc8 = i << vuc8;
+// CHECK: [[t8:%.+]] = load i32, i32* @i,
+// CHECK: [[tconv:%.+]] = trunc i32 [[t8]] to i8
+// CHECK: [[splat_splatinsert7:%.+]] = insertelement <8 x i8> undef, i8 [[tconv]], i32 0
+// CHECK: [[splat_splat8:%.+]] = shufflevector <8 x i8> [[splat_splatinsert7]], <8 x i8> undef, <8 x i32> zeroinitializer
+// CHECK: [[t9:%.+]] = load <8 x i8>, <8 x i8>* {{@.+}},
+// CHECK: shl <8 x i8> [[splat_splat8]], [[t9]]
+ vi8 = uc << vi8;
+// CHECK: [[t10:%.+]] = load i8, i8* @uc,
+// CHECK: [[conv10:%.+]] = zext i8 [[t10]] to i32
+// CHECK: [[splat_splatinsert11:%.+]] = insertelement <8 x i32> undef, i32 [[conv10]], i32 0
+// CHECK: [[splat_splat12:%.+]] = shufflevector <8 x i32> [[splat_splatinsert11]], <8 x i32> undef, <8 x i32> zeroinitializer
+// CHECK: [[t11:%.+]] = load <8 x i32>, <8 x i32>* {{@.+}},
+// CHECK: shl <8 x i32> [[splat_splat12]], [[t11]]
+ vui8 = us << vui8;
+// CHECK: [[t12:%.+]] = load i16, i16* @us,
+// CHECK: [[conv14:%.+]] = zext i16 [[t12]] to i32
+// CHECK: [[splat_splatinsert15:%.+]] = insertelement <8 x i32> undef, i32 [[conv14]], i32 0
+// CHECK: [[splat_splat16:%.+]] = shufflevector <8 x i32> [[splat_splatinsert15]], <8 x i32> undef, <8 x i32> zeroinitializer
+// CHECK: [[t13:%.+]] = load <8 x i32>, <8 x i32>* {{@.+}},
+// CHECK: shl <8 x i32> [[splat_splat16]], [[t13]]
+ vs8 = ui << vs8;
+// CHECK: [[t14:%.+]] = load i32, i32* @ui,
+// CHECK: [[conv18:%.+]] = trunc i32 [[t14]] to i16
+// CHECK: [[splat_splatinsert19:%.+]] = insertelement <8 x i16> undef, i16 [[conv18]], i32 0
+// CHECK: [[splat_splat20:%.+]] = shufflevector <8 x i16> [[splat_splatinsert19]], <8 x i16> undef, <8 x i32> zeroinitializer
+// CHECK: [[t15:%.+]] = load <8 x i16>, <8 x i16>* {{@.+}},
+// CHECK: shl <8 x i16> [[splat_splat20]], [[t15]]
+ vus8 = 1 << vus8;
+// CHECK: [[t16:%.+]] = load <8 x i16>, <8 x i16>* {{@.+}},
+// CHECK: [[shl22:%.+]] = shl <8 x i16> <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>, [[t16]]
+
+ vc8 = vc8 << vc8;
+// CHECK: [[t17:%.+]] = load <8 x i8>, <8 x i8>* {{@.+}},
+// CHECK: [[t18:%.+]] = load <8 x i8>, <8 x i8>* {{@.+}},
+// CHECK: shl <8 x i8> [[t17]], [[t18]]
+ vi8 = vi8 << vuc8;
+// CHECK: [[t19:%.+]] = load <8 x i32>, <8 x i32>* {{@.+}},
+// CHECK: [[t20:%.+]] = load <8 x i8>, <8 x i8>* {{@.+}},
+// CHECK: [[shprom:%.+]] = zext <8 x i8> [[t20]] to <8 x i32>
+// CHECK: shl <8 x i32> [[t19]], [[shprom]]
+ vuc8 = vuc8 << vi8;
+// CHECK: [[t21:%.+]] = load <8 x i8>, <8 x i8>* {{@.+}},
+// CHECK: [[t22:%.+]] = load <8 x i32>, <8 x i32>* {{@.+}},
+// CHECK: [[sh_prom25:%.+]] = trunc <8 x i32> [[t22]] to <8 x i8>
+// CHECK: shl <8 x i8> [[t21]], [[sh_prom25]]
+ vus8 = vus8 << vui8;
+// CHECK: [[t23:%.+]] = load <8 x i16>, <8 x i16>* {{@.+}},
+// CHECK: [[t24:%.+]] = load <8 x i32>, <8 x i32>* {{@.+}},
+// CHECK: [[sh_prom27:%.+]] = trunc <8 x i32> [[t24]] to <8 x i16>
+// CHECK: shl <8 x i16> [[t23]], [[sh_prom27]]
+ vui8 = vui8 << vs8;
+// CHECK: [[t25:%.+]] = load <8 x i32>, <8 x i32>* {{@.+}},
+// CHECK: [[t26:%.+]] = load <8 x i16>, <8 x i16>* {{@.+}},
+// CHECK: [[sh_prom29:%.+]] = zext <8 x i16> [[t26]] to <8 x i32>
+// CHECK: shl <8 x i32> [[t25]], [[sh_prom29]]
+
+ vui8 <<= s;
+// CHECK: [[t27:%.+]] = load i16, i16* @s,
+// CHECK: [[conv40:%.+]] = sext i16 [[t27]] to i32
+// CHECK: [[splat_splatinsert41:%.+]] = insertelement <8 x i32> undef, i32 [[conv40]], i32 0
+// CHECK: [[splat_splat42:%.+]] = shufflevector <8 x i32> [[splat_splatinsert41]], <8 x i32> undef, <8 x i32> zeroinitializer
+// CHECK: [[t28:%.+]] = load <8 x i32>, <8 x i32>* {{@.+}},
+// CHECK: shl <8 x i32> [[t28]], [[splat_splat42]]
+ vi8 <<= us;
+// CHECK: [[t29:%.+]] = load i16, i16* @us,
+// CHECK: [[conv44:%.+]] = zext i16 [[t29]] to i32
+// CHECK: [[splat_splatinsert45:%.+]] = insertelement <8 x i32> undef, i32 [[conv44]], i32 0
+// CHECK: [[splat_splat46:%.+]] = shufflevector <8 x i32> [[splat_splatinsert45]], <8 x i32> undef, <8 x i32> zeroinitializer
+// CHECK: [[t30:%.+]] = load <8 x i32>, <8 x i32>* {{@.+}},
+// CHECK: shl <8 x i32> [[t30]], [[splat_splat46]]
+ vus8 <<= i;
+// CHECK: [[t31:%.+]] = load i32, i32* @i,
+// CHECK: [[splat_splatinsert48:%.+]] = insertelement <8 x i32> undef, i32 [[t31]], i32 0
+// CHECK: [[splat_splat49:%.+]] = shufflevector <8 x i32> [[splat_splatinsert48]], <8 x i32> undef, <8 x i32> zeroinitializer
+// CHECK: [[t32:%.+]] = load <8 x i16>, <8 x i16>* {{@.+}},
+// CHECK: [[sh_prom50:%.+]] = trunc <8 x i32> [[splat_splat49]] to <8 x i16>
+// CHECK: shl <8 x i16> [[t32]], [[sh_prom50]]
+ vs8 <<= ui;
+// CHECK: [[t33:%.+]] = load i32, i32* @ui,
+// CHECK: [[splat_splatinsert52:%.+]] = insertelement <8 x i32> undef, i32 [[t33]], i32 0
+// CHECK: [[splat_splat53:%.+]] = shufflevector <8 x i32> [[splat_splatinsert52]], <8 x i32> undef, <8 x i32> zeroinitializer
+// CHECK: [[t34:%.+]] = load <8 x i16>, <8 x i16>* {{@.+}},
+// CHECK: [[sh_prom54:%.+]] = trunc <8 x i32> [[splat_splat53]] to <8 x i16>
+// CHECK: shl <8 x i16> [[t34]], [[sh_prom54]]
+}
diff --git a/test/CodeGen/vector.c b/test/CodeGen/vector.c
index 14f507972639..ebaea841aa85 100644
--- a/test/CodeGen/vector.c
+++ b/test/CodeGen/vector.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -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 core2 -debug-info-kind=limited -emit-llvm %s -o - | FileCheck %s
typedef short __v4hi __attribute__ ((__vector_size__ (8)));
void test1() {
@@ -20,8 +20,6 @@ void test3 ( vec4* a, char b, float c ) {
-// Don't include mm_malloc.h, it's system specific.
-#define __MM_MALLOC_H
#include <mmintrin.h>
diff --git a/test/CodeGen/windows-on-arm-itanium-thread-local.c b/test/CodeGen/windows-on-arm-itanium-thread-local.c
new file mode 100644
index 000000000000..7f12c367d91b
--- /dev/null
+++ b/test/CodeGen/windows-on-arm-itanium-thread-local.c
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -triple thumbv7--windows-itanium -fdeclspec -fms-compatibility -fms-compatibility-version=19.0 -S -emit-llvm -o - %s | FileCheck %s
+
+__declspec(thread) static void *c;
+void f(void *p) {
+ c = p;
+}
+
+// CHECK-LABEL: @f(i8* %p)
+// CHECK-NOT: call i8** @_ZTWL1c()
+// CHECK: call arm_aapcs_vfpcc i8** @_ZTWL1c()
+
diff --git a/test/CodeGen/windows-on-arm-stack-probe-size.c b/test/CodeGen/windows-on-arm-stack-probe-size.c
index c072566d7125..15bdacd6ee46 100644
--- a/test/CodeGen/windows-on-arm-stack-probe-size.c
+++ b/test/CodeGen/windows-on-arm-stack-probe-size.c
@@ -5,7 +5,7 @@
// RUN: | FileCheck %s -check-prefix CHECK-4096
// RUN: %clang_cc1 -triple thumbv7-windows-itanium -fms-extensions -O2 -emit-llvm %s -o - \
-// RUN: | FileCheck %s -check-prefix CHECK
+// RUN: | FileCheck %s
__declspec(dllimport) void initialise(signed char buffer[4096]);
diff --git a/test/CodeGen/windows-swiftcall.c b/test/CodeGen/windows-swiftcall.c
new file mode 100644
index 000000000000..f76b2fd3a40f
--- /dev/null
+++ b/test/CodeGen/windows-swiftcall.c
@@ -0,0 +1,458 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-windows -emit-llvm -target-cpu core2 -o - %s | FileCheck %s
+
+#define SWIFTCALL __attribute__((swiftcall))
+#define OUT __attribute__((swift_indirect_result))
+#define ERROR __attribute__((swift_error_result))
+#define CONTEXT __attribute__((swift_context))
+
+// CHECK: [[STRUCT2_RESULT:@.*]] = private {{.*}} constant [[STRUCT2_TYPE:%.*]] { i32 0, i8 0, i8 undef, i8 0, float 0.000000e+00, float 0.000000e+00 }
+
+/*****************************************************************************/
+/****************************** PARAMETER ABIS *******************************/
+/*****************************************************************************/
+
+SWIFTCALL void indirect_result_1(OUT int *arg0, OUT float *arg1) {}
+// CHECK-LABEL: define {{.*}} void @indirect_result_1(i32* noalias sret align 4 dereferenceable(4){{.*}}, float* noalias align 4 dereferenceable(4){{.*}})
+
+// TODO: maybe this shouldn't suppress sret.
+SWIFTCALL int indirect_result_2(OUT int *arg0, OUT float *arg1) { __builtin_unreachable(); }
+// CHECK-LABEL: define {{.*}} i32 @indirect_result_2(i32* noalias align 4 dereferenceable(4){{.*}}, float* noalias align 4 dereferenceable(4){{.*}})
+
+typedef struct { char array[1024]; } struct_reallybig;
+SWIFTCALL struct_reallybig indirect_result_3(OUT int *arg0, OUT float *arg1) { __builtin_unreachable(); }
+// CHECK-LABEL: define {{.*}} void @indirect_result_3({{.*}}* noalias sret {{.*}}, i32* noalias align 4 dereferenceable(4){{.*}}, float* noalias align 4 dereferenceable(4){{.*}})
+
+SWIFTCALL void context_1(CONTEXT void *self) {}
+// CHECK-LABEL: define {{.*}} void @context_1(i8* swiftself
+
+SWIFTCALL void context_2(void *arg0, CONTEXT void *self) {}
+// CHECK-LABEL: define {{.*}} void @context_2(i8*{{.*}}, i8* swiftself
+
+SWIFTCALL void context_error_1(CONTEXT int *self, ERROR float **error) {}
+// CHECK-LABEL: define {{.*}} void @context_error_1(i32* swiftself{{.*}}, float** swifterror)
+// CHECK: [[TEMP:%.*]] = alloca float*, align 8
+// CHECK: [[T0:%.*]] = load float*, float** [[ERRORARG:%.*]], align 8
+// CHECK: store float* [[T0]], float** [[TEMP]], align 8
+// CHECK: [[T0:%.*]] = load float*, float** [[TEMP]], align 8
+// CHECK: store float* [[T0]], float** [[ERRORARG]], align 8
+void test_context_error_1() {
+ int x;
+ float *error;
+ context_error_1(&x, &error);
+}
+// CHECK-LABEL: define void @test_context_error_1()
+// CHECK: [[X:%.*]] = alloca i32, align 4
+// CHECK: [[ERROR:%.*]] = alloca float*, align 8
+// CHECK: [[TEMP:%.*]] = alloca swifterror float*, align 8
+// CHECK: [[T0:%.*]] = load float*, float** [[ERROR]], align 8
+// CHECK: store float* [[T0]], float** [[TEMP]], align 8
+// CHECK: call [[SWIFTCC:swiftcc]] void @context_error_1(i32* swiftself [[X]], float** swifterror [[TEMP]])
+// CHECK: [[T0:%.*]] = load float*, float** [[TEMP]], align 8
+// CHECK: store float* [[T0]], float** [[ERROR]], align 8
+
+SWIFTCALL void context_error_2(short s, CONTEXT int *self, ERROR float **error) {}
+// CHECK-LABEL: define {{.*}} void @context_error_2(i16{{.*}}, i32* swiftself{{.*}}, float** swifterror)
+
+/*****************************************************************************/
+/********************************** LOWERING *********************************/
+/*****************************************************************************/
+
+typedef float float4 __attribute__((ext_vector_type(4)));
+typedef float float8 __attribute__((ext_vector_type(8)));
+typedef double double2 __attribute__((ext_vector_type(2)));
+typedef double double4 __attribute__((ext_vector_type(4)));
+typedef int int3 __attribute__((ext_vector_type(3)));
+typedef int int4 __attribute__((ext_vector_type(4)));
+typedef int int5 __attribute__((ext_vector_type(5)));
+typedef int int8 __attribute__((ext_vector_type(8)));
+
+#define TEST(TYPE) \
+ SWIFTCALL TYPE return_##TYPE(void) { \
+ TYPE result = {}; \
+ return result; \
+ } \
+ SWIFTCALL void take_##TYPE(TYPE v) { \
+ } \
+ void test_##TYPE() { \
+ take_##TYPE(return_##TYPE()); \
+ }
+
+/*****************************************************************************/
+/*********************************** STRUCTS *********************************/
+/*****************************************************************************/
+
+typedef struct {
+} struct_empty;
+TEST(struct_empty);
+// CHECK-LABEL: define {{.*}} @return_struct_empty()
+// CHECK: ret void
+// CHECK-LABEL: define {{.*}} @take_struct_empty()
+// CHECK: ret void
+
+typedef struct {
+ int x;
+ char c0;
+ char c1;
+ float f0;
+ float f1;
+} struct_1;
+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
+// CHECK: [[GEP1:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1
+// CHECK: [[T1:%.*]] = load i64, i64* [[GEP1]], align 4
+// CHECK: [[R0:%.*]] = insertvalue { i64, i64 } undef, i64 [[T0]], 0
+// 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: [[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
+// CHECK: store i64 %0, i64* [[GEP0]], align 4
+// CHECK: [[GEP1:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1
+// CHECK: store i64 %1, i64* [[GEP1]], align 4
+// CHECK: ret void
+// CHECK: }
+// CHECK-LABEL: define 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 }*
+// CHECK: [[GEP0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0
+// CHECK: [[E0:%.*]] = extractvalue { i64, i64 } [[RET]], 0
+// CHECK: store i64 [[E0]], i64* [[GEP0]], align 4
+// CHECK: [[GEP1:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1
+// CHECK: [[E1:%.*]] = extractvalue { i64, i64 } [[RET]], 1
+// CHECK: store i64 [[E1]], i64* [[GEP1]], align 4
+// CHECK: [[CAST2:%.*]] = bitcast [[STRUCT1]]* [[AGG]] to { i64, i64 }*
+// CHECK: [[GEP2:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST2]], i32 0, i32 0
+// CHECK: [[V0:%.*]] = load i64, i64* [[GEP2]], align 4
+// CHECK: [[GEP3:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST2]], i32 0, i32 1
+// CHECK: [[V1:%.*]] = load i64, i64* [[GEP3]], align 4
+// CHECK: call swiftcc void @take_struct_1(i64 [[V0]], i64 [[V1]])
+// CHECK: ret void
+// CHECK: }
+
+typedef struct {
+ int x;
+ char c0;
+ __attribute__((aligned(2))) char c1;
+ float f0;
+ float f1;
+} struct_2;
+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: 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
+// CHECK: [[GEP1:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1
+// CHECK: [[T1:%.*]] = load i64, i64* [[GEP1]], align 4
+// CHECK: [[R0:%.*]] = insertvalue { i64, i64 } undef, i64 [[T0]], 0
+// 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: [[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
+// CHECK: store i64 %0, i64* [[GEP0]], align 4
+// CHECK: [[GEP1:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1
+// CHECK: store i64 %1, i64* [[GEP1]], align 4
+// CHECK: ret void
+// CHECK: }
+// CHECK-LABEL: define 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 }*
+// CHECK: [[GEP:%.*]] = getelementptr inbounds {{.*}} [[CAST_TMP]], i32 0, i32 0
+// CHECK: [[T0:%.*]] = extractvalue { i64, i64 } [[CALL]], 0
+// CHECK: store i64 [[T0]], i64* [[GEP]], align 4
+// CHECK: [[GEP:%.*]] = getelementptr inbounds {{.*}} [[CAST_TMP]], i32 0, i32 1
+// CHECK: [[T0:%.*]] = extractvalue { i64, i64 } [[CALL]], 1
+// CHECK: store i64 [[T0]], i64* [[GEP]], align 4
+// CHECK: [[CAST:%.*]] = bitcast [[STRUCT2_TYPE]]* [[TMP]] to { i64, i64 }*
+// CHECK: [[GEP:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0
+// CHECK: [[R0:%.*]] = load i64, i64* [[GEP]], align 4
+// CHECK: [[GEP:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1
+// CHECK: [[R1:%.*]] = load i64, i64* [[GEP]], align 4
+// CHECK: call swiftcc void @take_struct_2(i64 [[R0]], i64 [[R1]])
+// CHECK: ret void
+// CHECK: }
+
+// There's no way to put a field randomly in the middle of an otherwise
+// empty storage unit in C, so that case has to be tested in C++, which
+// can use empty structs to introduce arbitrary padding. (In C, they end up
+// with size 0 and so don't affect layout.)
+
+// Misaligned data rule.
+typedef struct {
+ char c0;
+ __attribute__((packed)) float f;
+} struct_misaligned_1;
+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 { 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: [[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: [[AGG:%.*]] = alloca [[STRUCT:%.*]], align 1
+// CHECK: [[CALL:%.*]] = call swiftcc i64 @return_struct_misaligned_1()
+// CHECK: [[T0:%.*]] = bitcast [[STRUCT]]* [[AGG]] to { i64 }*
+// CHECK: [[T1:%.*]] = getelementptr inbounds { i64 }, { i64 }* [[T0]], i32 0, i32 0
+// CHECK: store i64 [[CALL]], i64* [[T1]], align 1
+// CHECK: [[T0:%.*]] = bitcast [[STRUCT]]* [[AGG]] to { i64 }*
+// CHECK: [[T1:%.*]] = getelementptr inbounds { i64 }, { i64 }* [[T0]], i32 0, i32 0
+// CHECK: [[P:%.*]] = load i64, i64* [[T1]], align 1
+// CHECK: call swiftcc void @take_struct_misaligned_1(i64 [[P]])
+// CHECK: ret void
+// CHECK: }
+
+// Too many scalars.
+typedef struct {
+ long long x[5];
+} struct_big_1;
+TEST(struct_big_1)
+
+// CHECK-LABEL: define {{.*}} void @return_struct_big_1({{.*}} noalias sret
+
+// Should not be byval.
+// CHECK-LABEL: define {{.*}} void @take_struct_big_1({{.*}}*{{( %.*)?}})
+
+/*****************************************************************************/
+/********************************* TYPE MERGING ******************************/
+/*****************************************************************************/
+
+typedef union {
+ float f;
+ double d;
+} union_het_fp;
+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 { 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: [[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: [[AGG:%.*]] = alloca [[UNION:%.*]], align 8
+// CHECK: [[CALL:%.*]] = call swiftcc i64 @return_union_het_fp()
+// CHECK: [[T0:%.*]] = bitcast [[UNION]]* [[AGG]] to { i64 }*
+// CHECK: [[T1:%.*]] = getelementptr inbounds { i64 }, { i64 }* [[T0]], i32 0, i32 0
+// CHECK: store i64 [[CALL]], i64* [[T1]], align 8
+// CHECK: [[T0:%.*]] = bitcast [[UNION]]* [[AGG]] to { i64 }*
+// CHECK: [[T1:%.*]] = getelementptr inbounds { i64 }, { i64 }* [[T0]], i32 0, i32 0
+// CHECK: [[V0:%.*]] = load i64, i64* [[T1]], align 8
+// CHECK: call swiftcc void @take_union_het_fp(i64 [[V0]])
+// CHECK: ret void
+// CHECK: }
+
+
+typedef union {
+ float f1;
+ float f2;
+} union_hom_fp;
+TEST(union_hom_fp)
+// CHECK-LABEL: define 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 }]]*
+// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
+// CHECK: store float [[CALL]], float* [[T0]], align 4
+// CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP]] to [[AGG]]*
+// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
+// CHECK: [[FIRST:%.*]] = load float, float* [[T0]], align 4
+// CHECK: call [[SWIFTCC]] void @take_union_hom_fp(float [[FIRST]])
+// CHECK: ret void
+
+typedef union {
+ float f1;
+ float4 fv2;
+} union_hom_fp_partial;
+TEST(union_hom_fp_partial)
+// CHECK: define 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 }*
+// CHECK: [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0
+// CHECK: [[T1:%.*]] = extractvalue { i64, i64 } [[CALL]], 0
+// CHECK: store i64 [[T1]], i64* [[T0]], align 16
+// CHECK: [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1
+// CHECK: [[T1:%.*]] = extractvalue { i64, i64 } [[CALL]], 1
+// CHECK: store i64 [[T1]], i64* [[T0]], align 8
+// CHECK: [[CAST:%.*]] = bitcast [[UNION]]* [[AGG]] to { i64, i64 }*
+// CHECK: [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0
+// CHECK: [[V0:%.*]] = load i64, i64* [[T0]], align 16
+// CHECK: [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1
+// CHECK: [[V1:%.*]] = load i64, i64* [[T0]], align 8
+// CHECK: call swiftcc void @take_union_hom_fp_partial(i64 [[V0]], i64 [[V1]])
+// CHECK: ret void
+// CHECK: }
+
+typedef union {
+ struct { int x, y; } f1;
+ float4 fv2;
+} union_het_fpv_partial;
+TEST(union_het_fpv_partial)
+// CHECK-LABEL: define 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 }*
+// CHECK: [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0
+// CHECK: [[T1:%.*]] = extractvalue { i64, i64 } [[CALL]], 0
+// CHECK: store i64 [[T1]], i64* [[T0]], align 16
+// CHECK: [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1
+// CHECK: [[T1:%.*]] = extractvalue { i64, i64 } [[CALL]], 1
+// CHECK: store i64 [[T1]], i64* [[T0]], align 8
+// CHECK: [[CAST:%.*]] = bitcast [[UNION]]* [[AGG]] to { i64, i64 }*
+// CHECK: [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0
+// CHECK: [[V0:%.*]] = load i64, i64* [[T0]], align 16
+// CHECK: [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1
+// CHECK: [[V1:%.*]] = load i64, i64* [[T0]], align 8
+// CHECK: call swiftcc void @take_union_het_fpv_partial(i64 [[V0]], i64 [[V1]])
+// CHECK: ret void
+// CHECK: }
+
+/*****************************************************************************/
+/****************************** VECTOR LEGALIZATION **************************/
+/*****************************************************************************/
+
+TEST(int4)
+// CHECK-LABEL: define {{.*}} <4 x i32> @return_int4()
+// CHECK-LABEL: define {{.*}} @take_int4(<4 x i32>
+
+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
+// CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[RET]] to [[AGG:{ <4 x i32>, <4 x i32> }]]*
+// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
+// CHECK: [[FIRST:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align
+// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
+// CHECK: [[SECOND:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align
+// CHECK: [[T0:%.*]] = insertvalue [[UAGG:{ <4 x i32>, <4 x i32> }]] undef, <4 x i32> [[FIRST]], 0
+// CHECK: [[T1:%.*]] = insertvalue [[UAGG]] [[T0]], <4 x i32> [[SECOND]], 1
+// CHECK: ret [[UAGG]] [[T1]]
+// CHECK-LABEL: define {{.*}} @take_int8(<4 x i32>, <4 x i32>)
+// CHECK: [[V:%.*]] = alloca [[REC]], align
+// CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[V]] to [[AGG]]*
+// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
+// CHECK: store <4 x i32> %0, <4 x i32>* [[T0]], align
+// 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: [[TMP1:%.*]] = alloca [[REC]], align
+// CHECK: [[TMP2:%.*]] = alloca [[REC]], align
+// CHECK: [[CALL:%.*]] = call [[SWIFTCC]] [[UAGG]] @return_int8()
+// CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP1]] to [[AGG]]*
+// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
+// CHECK: [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 0
+// CHECK: store <4 x i32> [[T1]], <4 x i32>* [[T0]], align
+// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
+// CHECK: [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 1
+// CHECK: store <4 x i32> [[T1]], <4 x i32>* [[T0]], align
+// CHECK: [[V:%.*]] = load [[REC]], [[REC]]* [[TMP1]], align
+// CHECK: store [[REC]] [[V]], [[REC]]* [[TMP2]], align
+// CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP2]] to [[AGG]]*
+// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
+// CHECK: [[FIRST:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align
+// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
+// CHECK: [[SECOND:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align
+// CHECK: call [[SWIFTCC]] void @take_int8(<4 x i32> [[FIRST]], <4 x i32> [[SECOND]])
+// CHECK: ret void
+
+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
+// CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[RET]] to [[AGG:{ <4 x i32>, i32 }]]*
+// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
+// CHECK: [[FIRST:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align
+// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
+// CHECK: [[SECOND:%.*]] = load i32, i32* [[T0]], align
+// CHECK: [[T0:%.*]] = insertvalue [[UAGG:{ <4 x i32>, i32 }]] undef, <4 x i32> [[FIRST]], 0
+// CHECK: [[T1:%.*]] = insertvalue [[UAGG]] [[T0]], i32 [[SECOND]], 1
+// CHECK: ret [[UAGG]] [[T1]]
+// CHECK-LABEL: define {{.*}} @take_int5(<4 x i32>, i32)
+// CHECK: [[V:%.*]] = alloca [[REC]], align
+// CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[V]] to [[AGG]]*
+// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
+// CHECK: store <4 x i32> %0, <4 x i32>* [[T0]], align
+// 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: [[TMP1:%.*]] = alloca [[REC]], align
+// CHECK: [[TMP2:%.*]] = alloca [[REC]], align
+// CHECK: [[CALL:%.*]] = call [[SWIFTCC]] [[UAGG]] @return_int5()
+// CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP1]] to [[AGG]]*
+// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
+// CHECK: [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 0
+// CHECK: store <4 x i32> [[T1]], <4 x i32>* [[T0]], align
+// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
+// CHECK: [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 1
+// CHECK: store i32 [[T1]], i32* [[T0]], align
+// CHECK: [[V:%.*]] = load [[REC]], [[REC]]* [[TMP1]], align
+// CHECK: store [[REC]] [[V]], [[REC]]* [[TMP2]], align
+// CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP2]] to [[AGG]]*
+// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
+// CHECK: [[FIRST:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align
+// CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1
+// CHECK: [[SECOND:%.*]] = load i32, i32* [[T0]], align
+// CHECK: call [[SWIFTCC]] void @take_int5(<4 x i32> [[FIRST]], i32 [[SECOND]])
+// CHECK: ret void
+
+typedef struct {
+ int x;
+ int3 v __attribute__((packed));
+} misaligned_int3;
+TEST(misaligned_int3)
+// CHECK-LABEL: define swiftcc void @take_misaligned_int3(i64, i64)
diff --git a/test/CodeGen/x86-inline-asm-v-constraint.c b/test/CodeGen/x86-inline-asm-v-constraint.c
new file mode 100644
index 000000000000..d335e4b6a0f7
--- /dev/null
+++ b/test/CodeGen/x86-inline-asm-v-constraint.c
@@ -0,0 +1,30 @@
+// RUN: %clang_cc1 %s -triple x86_64-unknown-linux-gnu -emit-llvm -target-cpu x86-64 -o - |opt -instnamer -S |FileCheck %s --check-prefix SSE
+// RUN: %clang_cc1 %s -triple x86_64-unknown-linux-gnu -emit-llvm -target-cpu skylake -D AVX -o -|opt -instnamer -S | FileCheck %s --check-prefixes AVX,SSE
+// RUN: %clang_cc1 %s -triple x86_64-unknown-linux-gnu -emit-llvm -target-cpu skylake-avx512 -D AVX512 -D AVX -o -|opt -instnamer -S | FileCheck %s --check-prefixes AVX512,AVX,SSE
+// RUN: %clang_cc1 %s -triple x86_64-unknown-linux-gnu -emit-llvm -target-cpu knl -D AVX -D AVX512 -o - |opt -instnamer -S | FileCheck %s --check-prefixes AVX512,AVX,SSE
+
+typedef float __m128 __attribute__ ((vector_size (16)));
+typedef float __m256 __attribute__ ((vector_size (32)));
+typedef float __m512 __attribute__ ((vector_size (64)));
+
+// SSE: call <4 x float> asm "vmovhlps $1, $2, $0", "=v,v,v,~{dirflag},~{fpsr},~{flags}"(i64 %tmp, <4 x float> %tmp1)
+__m128 testXMM(__m128 _xmm0, long _l) {
+ __asm__("vmovhlps %1, %2, %0" :"=v"(_xmm0) : "v"(_l), "v"(_xmm0));
+ return _xmm0;
+}
+
+// AVX: call <8 x float> asm "vmovsldup $1, $0", "=v,v,~{dirflag},~{fpsr},~{flags}"(<8 x float> %tmp)
+__m256 testYMM(__m256 _ymm0) {
+#ifdef AVX
+ __asm__("vmovsldup %1, %0" :"=v"(_ymm0) : "v"(_ymm0));
+#endif
+ return _ymm0;
+}
+
+// AVX512: call <16 x float> asm "vpternlogd $$0, $1, $2, $0", "=v,v,v,~{dirflag},~{fpsr},~{flags}"(<16 x float> %tmp, <16 x float> %tmp1)
+__m512 testZMM(__m512 _zmm0, __m512 _zmm1) {
+#ifdef AVX512
+ __asm__("vpternlogd $0, %1, %2, %0" :"=v"(_zmm0) : "v"(_zmm1), "v"(_zmm0));
+#endif
+ return _zmm0;
+}
diff --git a/test/CodeGen/x86_32-xsave.c b/test/CodeGen/x86_32-xsave.c
index da5d38a49f1b..b475d63fb357 100644
--- a/test/CodeGen/x86_32-xsave.c
+++ b/test/CodeGen/x86_32-xsave.c
@@ -1,18 +1,18 @@
-// RUN: %clang_cc1 %s -DTEST_XSAVE -O0 -triple=i686-unknown-unknown -target-feature +xsave -emit-llvm -o - -Werror | FileCheck %s --check-prefix=XSAVE
-// RUN: %clang_cc1 %s -DTEST_XSAVE -O0 -triple=i686-unknown-unknown -target-feature +xsave -fno-signed-char -emit-llvm -o - -Werror | FileCheck %s --check-prefix=XSAVE
+// RUN: %clang_cc1 %s -DTEST_XSAVE -O0 -triple=i686-unknown-unknown -target-feature +xsave -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefix=XSAVE
+// RUN: %clang_cc1 %s -DTEST_XSAVE -O0 -triple=i686-unknown-unknown -target-feature +xsave -fno-signed-char -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefix=XSAVE
-// RUN: %clang_cc1 %s -DTEST_XSAVEOPT -O0 -triple=i686-unknown-unknown -target-feature +xsave -target-feature +xsaveopt -emit-llvm -o - -Werror | FileCheck %s --check-prefix=XSAVEOPT
-// RUN: %clang_cc1 %s -DTEST_XSAVEOPT -O0 -triple=i686-unknown-unknown -target-feature +xsave -target-feature +xsaveopt -fno-signed-char -emit-llvm -o - -Werror | FileCheck %s --check-prefix=XSAVEOPT
+// RUN: %clang_cc1 %s -DTEST_XSAVEOPT -O0 -triple=i686-unknown-unknown -target-feature +xsave -target-feature +xsaveopt -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefix=XSAVEOPT
+// RUN: %clang_cc1 %s -DTEST_XSAVEOPT -O0 -triple=i686-unknown-unknown -target-feature +xsave -target-feature +xsaveopt -fno-signed-char -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefix=XSAVEOPT
-// RUN: %clang_cc1 %s -DTEST_XSAVEC -O0 -triple=i686-unknown-unknown -target-feature +xsave -target-feature +xsavec -emit-llvm -o - -Werror | FileCheck %s --check-prefix=XSAVEC
-// RUN: %clang_cc1 %s -DTEST_XSAVEC -O0 -triple=i686-unknown-unknown -target-feature +xsave -target-feature +xsavec -fno-signed-char -emit-llvm -o - -Werror | FileCheck %s --check-prefix=XSAVEC
+// RUN: %clang_cc1 %s -DTEST_XSAVEC -O0 -triple=i686-unknown-unknown -target-feature +xsave -target-feature +xsavec -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefix=XSAVEC
+// RUN: %clang_cc1 %s -DTEST_XSAVEC -O0 -triple=i686-unknown-unknown -target-feature +xsave -target-feature +xsavec -fno-signed-char -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefix=XSAVEC
-// RUN: %clang_cc1 %s -DTEST_XSAVES -O0 -triple=i686-unknown-unknown -target-feature +xsave -target-feature +xsaves -emit-llvm -o - -Werror | FileCheck %s --check-prefix=XSAVES
-// RUN: %clang_cc1 %s -DTEST_XSAVES -O0 -triple=i686-unknown-unknown -target-feature +xsave -target-feature +xsaves -fno-signed-char -emit-llvm -o - -Werror | FileCheck %s --check-prefix=XSAVES
+// RUN: %clang_cc1 %s -DTEST_XSAVES -O0 -triple=i686-unknown-unknown -target-feature +xsave -target-feature +xsaves -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefix=XSAVES
+// RUN: %clang_cc1 %s -DTEST_XSAVES -O0 -triple=i686-unknown-unknown -target-feature +xsave -target-feature +xsaves -fno-signed-char -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefix=XSAVES
void test() {
- unsigned long long tmp_ULLi;
- void* tmp_vp;
+ unsigned long long tmp_ULLi = 0;
+ void* tmp_vp = 0;
#ifdef TEST_XSAVE
// XSAVE: [[tmp_vp_1:%[0-9a-zA-z]+]] = load i8*, i8** %tmp_vp, align 4
diff --git a/test/CodeGen/x86_64-arguments.c b/test/CodeGen/x86_64-arguments.c
index a2d60cc6b1ab..9f375d780c94 100644
--- a/test/CodeGen/x86_64-arguments.c
+++ b/test/CodeGen/x86_64-arguments.c
@@ -470,13 +470,14 @@ typedef struct {
s512 x55;
__m512 x56;
-// Even on AVX512, aggregates of size larger than four eightbytes have class
-// MEMORY (AVX512 draft 0.3 3.2.3p2 Rule 1).
+// On AVX512, aggregates which contain a __m512 type are classified as SSE/SSEUP
+// as per https://github.com/hjl-tools/x86-psABI/commit/30f9c9 3.2.3p2 Rule 1
//
-// CHECK: declare void @f55(%struct.s512* byval align 64)
+// AVX512: declare void @f55(<16 x float>)
+// NO-AVX512: declare void @f55(%struct.s512* byval align 64)
void f55(s512 x);
-// However, __m512 has type SSE/SSEUP on AVX512.
+// __m512 has type SSE/SSEUP on AVX512.
//
// AVX512: declare void @f56(<16 x float>)
// NO-AVX512: declare void @f56(<16 x float>* byval align 64)
@@ -535,3 +536,12 @@ void f64() {
f64_helper(x64, x64, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0i);
f64_helper(x64, x64, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0i);
}
+
+struct t65 {
+ __m256 m;
+ int : 0;
+};
+// SSE-LABEL: @f65(%struct.t65* byval align 32 %{{[^,)]+}})
+// AVX: @f65(<8 x float> %{{[^,)]+}})
+void f65(struct t65 a0) {
+}
diff --git a/test/CodeGen/x86_64-xsave.c b/test/CodeGen/x86_64-xsave.c
index ecdb7252e362..496e982b99c5 100644
--- a/test/CodeGen/x86_64-xsave.c
+++ b/test/CodeGen/x86_64-xsave.c
@@ -1,18 +1,18 @@
-// RUN: %clang_cc1 %s -DTEST_XSAVE -O0 -triple=x86_64-unknown-unknown -target-feature +xsave -emit-llvm -o - -Werror | FileCheck %s --check-prefix=XSAVE
-// RUN: %clang_cc1 %s -DTEST_XSAVE -O0 -triple=x86_64-unknown-unknown -target-feature +xsave -fno-signed-char -emit-llvm -o - -Werror | FileCheck %s --check-prefix=XSAVE
+// RUN: %clang_cc1 %s -DTEST_XSAVE -O0 -triple=x86_64-unknown-unknown -target-feature +xsave -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefix=XSAVE
+// RUN: %clang_cc1 %s -DTEST_XSAVE -O0 -triple=x86_64-unknown-unknown -target-feature +xsave -fno-signed-char -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefix=XSAVE
-// RUN: %clang_cc1 %s -DTEST_XSAVEOPT -O0 -triple=x86_64-unknown-unknown -target-feature +xsave -target-feature +xsaveopt -emit-llvm -o - -Werror | FileCheck %s --check-prefix=XSAVEOPT
-// RUN: %clang_cc1 %s -DTEST_XSAVEOPT -O0 -triple=x86_64-unknown-unknown -target-feature +xsave -target-feature +xsaveopt -fno-signed-char -emit-llvm -o - -Werror | FileCheck %s --check-prefix=XSAVEOPT
+// RUN: %clang_cc1 %s -DTEST_XSAVEOPT -O0 -triple=x86_64-unknown-unknown -target-feature +xsave -target-feature +xsaveopt -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefix=XSAVEOPT
+// RUN: %clang_cc1 %s -DTEST_XSAVEOPT -O0 -triple=x86_64-unknown-unknown -target-feature +xsave -target-feature +xsaveopt -fno-signed-char -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefix=XSAVEOPT
-// RUN: %clang_cc1 %s -DTEST_XSAVEC -O0 -triple=x86_64-unknown-unknown -target-feature +xsave -target-feature +xsavec -emit-llvm -o - -Werror | FileCheck %s --check-prefix=XSAVEC
-// RUN: %clang_cc1 %s -DTEST_XSAVEC -O0 -triple=x86_64-unknown-unknown -target-feature +xsave -target-feature +xsavec -fno-signed-char -emit-llvm -o - -Werror | FileCheck %s --check-prefix=XSAVEC
+// RUN: %clang_cc1 %s -DTEST_XSAVEC -O0 -triple=x86_64-unknown-unknown -target-feature +xsave -target-feature +xsavec -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefix=XSAVEC
+// RUN: %clang_cc1 %s -DTEST_XSAVEC -O0 -triple=x86_64-unknown-unknown -target-feature +xsave -target-feature +xsavec -fno-signed-char -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefix=XSAVEC
-// RUN: %clang_cc1 %s -DTEST_XSAVES -O0 -triple=x86_64-unknown-unknown -target-feature +xsave -target-feature +xsaves -emit-llvm -o - -Werror | FileCheck %s --check-prefix=XSAVES
-// RUN: %clang_cc1 %s -DTEST_XSAVES -O0 -triple=x86_64-unknown-unknown -target-feature +xsave -target-feature +xsaves -fno-signed-char -emit-llvm -o - -Werror | FileCheck %s --check-prefix=XSAVES
+// RUN: %clang_cc1 %s -DTEST_XSAVES -O0 -triple=x86_64-unknown-unknown -target-feature +xsave -target-feature +xsaves -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefix=XSAVES
+// RUN: %clang_cc1 %s -DTEST_XSAVES -O0 -triple=x86_64-unknown-unknown -target-feature +xsave -target-feature +xsaves -fno-signed-char -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefix=XSAVES
void test() {
- unsigned long long tmp_ULLi;
- void* tmp_vp;
+ unsigned long long tmp_ULLi = 0;
+ void* tmp_vp = 0;
#ifdef TEST_XSAVE
// XSAVE: [[tmp_vp_1:%[0-9a-zA-z]+]] = load i8*, i8** %tmp_vp, align 8
diff --git a/test/CodeGen/x86_inlineasm_curly_bracket_escape.c b/test/CodeGen/x86_inlineasm_curly_bracket_escape.c
new file mode 100644
index 000000000000..503c13e61379
--- /dev/null
+++ b/test/CodeGen/x86_inlineasm_curly_bracket_escape.c
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-cpu skylake-avx512 -O0 -S -emit-llvm -o - -Wall -Werror | FileCheck %s
+// This test checks validity of inline assembly using curly brackets syntax
+// for extended inline asm.
+
+void test_curly_brackets() {
+ //CHECK: %xmm1,%xmm0,%xmm1 {%k1}{z}
+ asm("vpaddb\t %%xmm1,%%xmm0,%%xmm1 %{%%k1%}%{z%}\t":::);
+} \ No newline at end of file
diff --git a/test/CodeGen/xop-builtins.c b/test/CodeGen/xop-builtins.c
index 3b1d1ef39cfc..da9a3b925de2 100644
--- a/test/CodeGen/xop-builtins.c
+++ b/test/CodeGen/xop-builtins.c
@@ -1,8 +1,6 @@
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +xop -emit-llvm -o - -Werror | FileCheck %s
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -target-feature +xop -fno-signed-char -emit-llvm -o - -Werror | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +xop -emit-llvm -o - -Wall -Werror | FileCheck %s
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +xop -fno-signed-char -emit-llvm -o - -Wall -Werror | FileCheck %s
-// Don't include mm_malloc.h, it's system specific.
-#define __MM_MALLOC_H
#include <x86intrin.h>
diff --git a/test/CodeGen/xray-attributes-supported-arm.cpp b/test/CodeGen/xray-attributes-supported-arm.cpp
new file mode 100644
index 000000000000..3104f285bfb3
--- /dev/null
+++ b/test/CodeGen/xray-attributes-supported-arm.cpp
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 %s -fxray-instrument -std=c++11 -x c++ -emit-llvm -o - -triple arm-unknown-linux-gnu | FileCheck %s
+
+// Make sure that the LLVM attribute for XRay-annotated functions do show up.
+[[clang::xray_always_instrument]] void foo() {
+// CHECK: define void @_Z3foov() #0
+};
+
+[[clang::xray_never_instrument]] void bar() {
+// CHECK: define void @_Z3barv() #1
+};
+
+// CHECK: #0 = {{.*}}"function-instrument"="xray-always"
+// CHECK: #1 = {{.*}}"function-instrument"="xray-never"
diff --git a/test/CodeGenCUDA/convergent.cu b/test/CodeGenCUDA/convergent.cu
index 6827c57d29fb..62818f9e5af4 100644
--- a/test/CodeGenCUDA/convergent.cu
+++ b/test/CodeGenCUDA/convergent.cu
@@ -36,8 +36,8 @@ __host__ __device__ void bar() {
// DEVICE: attributes [[BAZ_ATTR]] = {
// DEVICE-SAME: convergent
// DEVICE-SAME: }
-// DEVICE: attributes [[CALL_ATTR]] = { convergent }
-// DEVICE: attributes [[ASM_ATTR]] = { convergent
+// DEVICE-DAG: attributes [[CALL_ATTR]] = { convergent
+// DEVICE-DAG: attributes [[ASM_ATTR]] = { convergent
// HOST: declare void @_Z3bazv() [[BAZ_ATTR:#[0-9]+]]
// HOST: attributes [[BAZ_ATTR]] = {
diff --git a/test/CodeGenCUDA/cuda-builtin-vars.cu b/test/CodeGenCUDA/cuda-builtin-vars.cu
index c2159f5af141..c1edff936a0d 100644
--- a/test/CodeGenCUDA/cuda-builtin-vars.cu
+++ b/test/CodeGenCUDA/cuda-builtin-vars.cu
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 "-triple" "nvptx-nvidia-cuda" -emit-llvm -fcuda-is-device -o - %s | FileCheck %s
-#include "cuda_builtin_vars.h"
+#include "__clang_cuda_builtin_vars.h"
// CHECK: define void @_Z6kernelPi(i32* %out)
__attribute__((global))
diff --git a/test/CodeGenCUDA/device-stub.cu b/test/CodeGenCUDA/device-stub.cu
index 5979ba3fce60..3376803c5020 100644
--- a/test/CodeGenCUDA/device-stub.cu
+++ b/test/CodeGenCUDA/device-stub.cu
@@ -45,10 +45,12 @@ void use_pointers() {
// * constant unnamed string with the kernel name
// CHECK: private unnamed_addr constant{{.*}}kernelfunc{{.*}}\00"
// * constant unnamed string with GPU binary
-// CHECK: private unnamed_addr constant{{.*}}\00"
+// CHECK: private unnamed_addr constant{{.*GPU binary would be here.*}}\00"
+// CHECK-SAME: section ".nv_fatbin", align 8
// * constant struct that wraps GPU binary
// CHECK: @__cuda_fatbin_wrapper = internal constant { i32, i32, i8*, i8* }
-// CHECK: { i32 1180844977, i32 1, {{.*}}, i8* null }
+// CHECK-SAME: { i32 1180844977, i32 1, {{.*}}, i8* null }
+// CHECK-SAME: section ".nvFatBinSegment"
// * 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.
diff --git a/test/CodeGenCUDA/device-var-init.cu b/test/CodeGenCUDA/device-var-init.cu
index 6f2d9294131f..0f4c64813406 100644
--- a/test/CodeGenCUDA/device-var-init.cu
+++ b/test/CodeGenCUDA/device-var-init.cu
@@ -182,9 +182,9 @@ __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) #6
- // CHECK-NEXT: call void @_ZN7T_F_NEDD1Ev(%struct.T_F_NED* %t_f_ned) #6
- // CHECK-NEXT: call void @_ZN7T_B_NEDD1Ev(%struct.T_B_NED* %t_b_ned) #6
+ // 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)
diff --git a/test/CodeGenCUDA/function-overload.cu b/test/CodeGenCUDA/function-overload.cu
index 380304af8222..c82b2e96f6c3 100644
--- a/test/CodeGenCUDA/function-overload.cu
+++ b/test/CodeGenCUDA/function-overload.cu
@@ -16,8 +16,6 @@ int x;
struct s_cd_dh {
__host__ s_cd_dh() { x = 11; }
__device__ s_cd_dh() { x = 12; }
- __host__ ~s_cd_dh() { x = 21; }
- __device__ ~s_cd_dh() { x = 22; }
};
struct s_cd_hd {
@@ -38,7 +36,6 @@ void wrapper() {
// CHECK-BOTH: call void @_ZN7s_cd_hdC1Ev
// CHECK-BOTH: call void @_ZN7s_cd_hdD1Ev(
- // CHECK-BOTH: call void @_ZN7s_cd_dhD1Ev(
}
// CHECK-BOTH: ret void
@@ -56,8 +53,3 @@ void wrapper() {
// CHECK-BOTH: define linkonce_odr void @_ZN7s_cd_hdD2Ev(
// CHECK-BOTH: store i32 32,
// CHECK-BOTH: ret void
-
-// CHECK-BOTH: define linkonce_odr void @_ZN7s_cd_dhD2Ev(
-// CHECK-HOST: store i32 21,
-// CHECK-DEVICE: store i32 22,
-// CHECK-BOTH: ret void
diff --git a/test/CodeGenCUDA/host-device-calls-host.cu b/test/CodeGenCUDA/host-device-calls-host.cu
deleted file mode 100644
index 94796a3c233c..000000000000
--- a/test/CodeGenCUDA/host-device-calls-host.cu
+++ /dev/null
@@ -1,32 +0,0 @@
-// RUN: %clang_cc1 %s -triple nvptx-unknown-unknown -fcuda-is-device -Wno-cuda-compat -emit-llvm -o - | FileCheck %s
-
-#include "Inputs/cuda.h"
-
-extern "C"
-void host_function() {}
-
-// CHECK-LABEL: define void @hd_function_a
-extern "C"
-__host__ __device__ void hd_function_a() {
- // CHECK: call void @host_function
- host_function();
-}
-
-// CHECK: declare void @host_function
-
-// CHECK-LABEL: define void @hd_function_b
-extern "C"
-__host__ __device__ void hd_function_b(bool b) { if (b) host_function(); }
-
-// CHECK-LABEL: define void @device_function_b
-extern "C"
-__device__ void device_function_b() { hd_function_b(false); }
-
-// CHECK-LABEL: define void @global_function
-extern "C"
-__global__ void global_function() {
- // CHECK: call void @device_function_b
- device_function_b();
-}
-
-// CHECK: !{{[0-9]+}} = !{void ()* @global_function, !"kernel", i32 1}
diff --git a/test/CodeGenCUDA/kernel-args-alignment.cu b/test/CodeGenCUDA/kernel-args-alignment.cu
new file mode 100644
index 000000000000..4bd5eb1bb1ff
--- /dev/null
+++ b/test/CodeGenCUDA/kernel-args-alignment.cu
@@ -0,0 +1,36 @@
+// RUN: %clang_cc1 --std=c++11 -triple x86_64-unknown-linux-gnu -emit-llvm -o - %s | \
+// RUN: FileCheck -check-prefix HOST -check-prefix CHECK %s
+
+// RUN: %clang_cc1 --std=c++11 -fcuda-is-device -triple nvptx64-nvidia-cuda \
+// RUN: -emit-llvm -o - %s | FileCheck -check-prefix DEVICE -check-prefix CHECK %s
+
+#include "Inputs/cuda.h"
+
+struct U {
+ short x;
+} __attribute__((packed));
+
+struct S {
+ int *ptr;
+ char a;
+ U u;
+};
+
+// Clang should generate a packed LLVM struct for S (denoted by the <>s),
+// otherwise this test isn't interesting.
+// CHECK: %struct.S = type <{ i32*, i8, %struct.U, [5 x i8] }>
+
+static_assert(alignof(S) == 8, "Unexpected alignment.");
+
+// HOST-LABEL: @_Z6kernelc1SPi
+// Marshalled kernel args should be:
+// 1. offset 0, width 1
+// 2. offset 8 (because alignof(S) == 8), width 16
+// 3. offset 24, width 8
+// HOST: call i32 @cudaSetupArgument({{[^,]*}}, i64 1, i64 0)
+// HOST: call i32 @cudaSetupArgument({{[^,]*}}, i64 16, i64 8)
+// HOST: call i32 @cudaSetupArgument({{[^,]*}}, i64 8, i64 24)
+
+// DEVICE-LABEL: @_Z6kernelc1SPi
+// DEVICE-SAME: i8{{[^,]*}}, %struct.S* byval align 8{{[^,]*}}, i32*
+__global__ void kernel(char a, S s, int *b) {}
diff --git a/test/CodeGenCUDA/launch-bounds.cu b/test/CodeGenCUDA/launch-bounds.cu
index 6c369c6f3f0d..dda647ef3617 100644
--- a/test/CodeGenCUDA/launch-bounds.cu
+++ b/test/CodeGenCUDA/launch-bounds.cu
@@ -36,7 +36,7 @@ Kernel3()
{
}
-template void Kernel3<MAX_THREADS_PER_BLOCK>();
+template __global__ void Kernel3<MAX_THREADS_PER_BLOCK>();
// CHECK: !{{[0-9]+}} = !{void ()* @{{.*}}Kernel3{{.*}}, !"maxntidx", i32 256}
template <int max_threads_per_block, int min_blocks_per_mp>
@@ -45,7 +45,7 @@ __launch_bounds__(max_threads_per_block, min_blocks_per_mp)
Kernel4()
{
}
-template void Kernel4<MAX_THREADS_PER_BLOCK, MIN_BLOCKS_PER_MP>();
+template __global__ void Kernel4<MAX_THREADS_PER_BLOCK, MIN_BLOCKS_PER_MP>();
// CHECK: !{{[0-9]+}} = !{void ()* @{{.*}}Kernel4{{.*}}, !"maxntidx", i32 256}
// CHECK: !{{[0-9]+}} = !{void ()* @{{.*}}Kernel4{{.*}}, !"minctasm", i32 2}
@@ -58,7 +58,7 @@ __launch_bounds__(max_threads_per_block + constint,
Kernel5()
{
}
-template void Kernel5<MAX_THREADS_PER_BLOCK, MIN_BLOCKS_PER_MP>();
+template __global__ void Kernel5<MAX_THREADS_PER_BLOCK, MIN_BLOCKS_PER_MP>();
// CHECK: !{{[0-9]+}} = !{void ()* @{{.*}}Kernel5{{.*}}, !"maxntidx", i32 356}
// CHECK: !{{[0-9]+}} = !{void ()* @{{.*}}Kernel5{{.*}}, !"minctasm", i32 258}
diff --git a/test/CodeGenCUDA/nothrow.cu b/test/CodeGenCUDA/nothrow.cu
new file mode 100644
index 000000000000..f001b57981fa
--- /dev/null
+++ b/test/CodeGenCUDA/nothrow.cu
@@ -0,0 +1,39 @@
+// RUN: %clang_cc1 -std=c++11 -fcxx-exceptions -fexceptions -fcuda-is-device \
+// RUN: -triple nvptx-nvidia-cuda -emit-llvm -disable-llvm-passes -o - %s | \
+// RUN: FileCheck -check-prefix DEVICE %s
+
+// RUN: %clang_cc1 -std=c++11 -fcxx-exceptions -fexceptions \
+// RUN: -triple x86_64-unknown-linux-gnu -emit-llvm -disable-llvm-passes -o - %s | \
+// RUN: FileCheck -check-prefix HOST %s
+
+#include "Inputs/cuda.h"
+
+__host__ __device__ void f();
+
+// HOST: define void @_Z7host_fnv() [[HOST_ATTR:#[0-9]+]]
+void host_fn() { f(); }
+
+// DEVICE: define void @_Z3foov() [[DEVICE_ATTR:#[0-9]+]]
+__device__ void foo() {
+ // DEVICE: call void @_Z1fv
+ f();
+}
+
+// DEVICE: define void @_Z12foo_noexceptv() [[DEVICE_ATTR:#[0-9]+]]
+__device__ void foo_noexcept() noexcept {
+ // DEVICE: call void @_Z1fv
+ f();
+}
+
+// This is nounwind only on the device side.
+// CHECK: define void @_Z3foov() [[DEVICE_ATTR:#[0-9]+]]
+__host__ __device__ void bar() { f(); }
+
+// DEVICE: define void @_Z3bazv() [[DEVICE_ATTR:#[0-9]+]]
+__global__ void baz() { f(); }
+
+// DEVICE: attributes [[DEVICE_ATTR]] = {
+// DEVICE-SAME: nounwind
+// HOST: attributes [[HOST_ATTR]] = {
+// HOST-NOT: nounwind
+// HOST-SAME: }
diff --git a/test/CodeGenCXX/PR26569.cpp b/test/CodeGenCXX/PR26569.cpp
index 3e2d2ffeba14..859b6e26f0c4 100644
--- a/test/CodeGenCXX/PR26569.cpp
+++ b/test/CodeGenCXX/PR26569.cpp
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 -triple i686-pc-win32 -fms-extensions -emit-llvm -O1 -disable-llvm-optzns %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple i686-pc-win32 -fms-extensions -emit-llvm -O1 -disable-llvm-passes %s -o - | FileCheck %s
-class A {
+class __declspec(dllimport) A {
virtual void m_fn1();
};
template <typename>
@@ -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*] [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*] [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*] [i8* bitcast (%rtti.CompleteObjectLocator* @"\01??_R4A@@6B@" to i8*), i8* bitcast (void (%class.A*)* @"\01?m_fn1@A@@EAEXXZ" to i8*)], comdat($"\01??_7A@@6B@")
+// 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: @"\01??_7C@@6B@" = dllexport unnamed_addr alias i8*, getelementptr inbounds ([2 x i8*], [2 x i8*]* @[[VTABLE_C]], 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 1)
-// CHECK-DAG: @"\01??_7A@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ([2 x i8*], [2 x i8*]* @[[VTABLE_A]], i32 0, i32 1)
+// 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: @"\01??_8?$B@H@@7B@" = available_externally dllimport unnamed_addr constant [2 x i32] [i32 0, i32 4]
diff --git a/test/CodeGenCXX/alias-available-externally.cpp b/test/CodeGenCXX/alias-available-externally.cpp
new file mode 100644
index 000000000000..473e93be0a75
--- /dev/null
+++ b/test/CodeGenCXX/alias-available-externally.cpp
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -O1 -std=c++11 -emit-llvm -triple %itanium_abi_triple -disable-llvm-passes -o - %s | FileCheck %s
+// Clang should not generate alias to available_externally definitions.
+// Check that the destructor of Foo is defined.
+// The destructors have different return type for different targets.
+// CHECK: define linkonce_odr {{.*}} @_ZN3FooD2Ev
+template <class CharT>
+struct String {
+ String() {}
+ ~String();
+};
+
+template <class CharT>
+inline __attribute__((visibility("hidden"), always_inline))
+String<CharT>::~String() {}
+
+extern template struct String<char>;
+
+struct Foo : public String<char> { Foo() { String<char> s; } };
+
+Foo f;
diff --git a/test/CodeGenCXX/alloc-size.cpp b/test/CodeGenCXX/alloc-size.cpp
new file mode 100644
index 000000000000..e93e231b70e8
--- /dev/null
+++ b/test/CodeGenCXX/alloc-size.cpp
@@ -0,0 +1,72 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -O0 %s -o - 2>&1 -std=c++11 | FileCheck %s
+
+namespace templates {
+void *my_malloc(int N) __attribute__((alloc_size(1)));
+void *my_calloc(int N, int M) __attribute__((alloc_size(1, 2)));
+
+struct MyType {
+ int arr[4];
+};
+
+template <typename T> int callMalloc();
+
+template <typename T, int N> int callCalloc();
+
+// CHECK-LABEL: define i32 @_ZN9templates6testItEv()
+int testIt() {
+ // CHECK: call i32 @_ZN9templates10callMallocINS_6MyTypeEEEiv
+ // CHECK: call i32 @_ZN9templates10callCallocINS_6MyTypeELi4EEEiv
+ return callMalloc<MyType>() + callCalloc<MyType, 4>();
+}
+
+// CHECK-LABEL: define linkonce_odr i32
+// @_ZN9templates10callMallocINS_6MyTypeEEEiv
+template <typename T> int callMalloc() {
+ static_assert(sizeof(T) == 16, "");
+ // CHECK: ret i32 16
+ return __builtin_object_size(my_malloc(sizeof(T)), 0);
+}
+
+// CHECK-LABEL: define linkonce_odr i32
+// @_ZN9templates10callCallocINS_6MyTypeELi4EEEiv
+template <typename T, int N> int callCalloc() {
+ static_assert(sizeof(T) * N == 64, "");
+ // CHECK: ret i32 64
+ return __builtin_object_size(my_malloc(sizeof(T) * N), 0);
+}
+}
+
+namespace templated_alloc_size {
+using size_t = unsigned long;
+
+// We don't need bodies for any of these, because they're only used in
+// __builtin_object_size, and that shouldn't need anything but a function
+// decl with alloc_size on it.
+template <typename T>
+T *my_malloc(size_t N = sizeof(T)) __attribute__((alloc_size(1)));
+
+template <typename T>
+T *my_calloc(size_t M, size_t N = sizeof(T)) __attribute__((alloc_size(2, 1)));
+
+template <size_t N>
+void *dependent_malloc(size_t NT = N) __attribute__((alloc_size(1)));
+
+template <size_t N, size_t M>
+void *dependent_calloc(size_t NT = N, size_t MT = M)
+ __attribute__((alloc_size(1, 2)));
+
+template <typename T, size_t M>
+void *dependent_calloc2(size_t NT = sizeof(T), size_t MT = M)
+ __attribute__((alloc_size(1, 2)));
+
+// CHECK-LABEL: define i32 @_ZN20templated_alloc_size6testItEv
+int testIt() {
+ // 122 = 4 + 5*4 + 6 + 7*8 + 4*9
+ // CHECK: ret i32 122
+ return __builtin_object_size(my_malloc<int>(), 0) +
+ __builtin_object_size(my_calloc<int>(5), 0) +
+ __builtin_object_size(dependent_malloc<6>(), 0) +
+ __builtin_object_size(dependent_calloc<7, 8>(), 0) +
+ __builtin_object_size(dependent_calloc2<int, 9>(), 0);
+}
+}
diff --git a/test/CodeGenCXX/apple-kext-indirect-call-2.cpp b/test/CodeGenCXX/apple-kext-indirect-call-2.cpp
index d441b78140e7..3b2cda8b583b 100644
--- a/test/CodeGenCXX/apple-kext-indirect-call-2.cpp
+++ b/test/CodeGenCXX/apple-kext-indirect-call-2.cpp
@@ -1,9 +1,9 @@
// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fapple-kext -fno-rtti -emit-llvm -o - %s | FileCheck %s
-// CHECK: @_ZTV1A = unnamed_addr constant [4 x i8*] [i8* null, i8* null, i8* bitcast (i8* (%struct.A*)* @_ZNK1A3abcEv to i8*), i8* null]
-// CHECK: @_ZTV4Base = unnamed_addr constant [4 x i8*] [i8* null, i8* null, i8* bitcast (i8* (%struct.Base*)* @_ZNK4Base3abcEv to i8*), i8* null]
-// CHECK: @_ZTV8Derived2 = unnamed_addr constant [5 x i8*] [i8* null, i8* null, i8* null, i8* bitcast (i8* (%struct.Derived2*)* @_ZNK8Derived23efgEv to i8*), i8* null]
-// CHECK: @_ZTV2D2 = unnamed_addr constant [5 x i8*] [i8* null, i8* null, i8* null, i8* bitcast (i8* (%struct.D2*)* @_ZNK2D23abcEv to i8*), i8* null]
+// CHECK: @_ZTV1A = unnamed_addr constant { [4 x i8*] } { [4 x i8*] [i8* null, i8* null, i8* bitcast (i8* (%struct.A*)* @_ZNK1A3abcEv to i8*), i8* null] }
+// CHECK: @_ZTV4Base = unnamed_addr constant { [4 x i8*] } { [4 x i8*] [i8* null, i8* null, i8* bitcast (i8* (%struct.Base*)* @_ZNK4Base3abcEv to i8*), i8* null] }
+// CHECK: @_ZTV8Derived2 = unnamed_addr constant { [5 x i8*] } { [5 x i8*] [i8* null, i8* null, i8* null, i8* bitcast (i8* (%struct.Derived2*)* @_ZNK8Derived23efgEv to i8*), i8* null] }
+// CHECK: @_ZTV2D2 = unnamed_addr constant { [5 x i8*] } { [5 x i8*] [i8* null, i8* null, i8* null, i8* bitcast (i8* (%struct.D2*)* @_ZNK2D23abcEv to i8*), i8* null] }
struct A {
virtual const char* abc(void) const;
@@ -18,7 +18,7 @@ struct B : virtual A {
void B::VF() {}
void FUNC(B* p) {
-// CHECK: [[T1:%.*]] = load i8* (%struct.A*)*, i8* (%struct.A*)** getelementptr inbounds (i8* (%struct.A*)*, i8* (%struct.A*)** bitcast ([4 x i8*]* @_ZTV1A to i8* (%struct.A*)**), i64 2)
+// CHECK: [[T1:%.*]] = load i8* (%struct.A*)*, i8* (%struct.A*)** getelementptr inbounds (i8* (%struct.A*)*, i8* (%struct.A*)** bitcast ({ [4 x i8*] }* @_ZTV1A to i8* (%struct.A*)**), i64 2)
// CHECK-NEXT: [[T2:%.*]] = call i8* [[T1]]
const char* c = p->A::abc();
}
@@ -33,7 +33,7 @@ struct Derived : public Base {
};
void FUNC1(Derived* p) {
-// CHECK: [[U1:%.*]] = load i8* (%struct.Base*)*, i8* (%struct.Base*)** getelementptr inbounds (i8* (%struct.Base*)*, i8* (%struct.Base*)** bitcast ([4 x i8*]* @_ZTV4Base to i8* (%struct.Base*)**), i64 2)
+// CHECK: [[U1:%.*]] = load i8* (%struct.Base*)*, i8* (%struct.Base*)** getelementptr inbounds (i8* (%struct.Base*)*, i8* (%struct.Base*)** bitcast ({ [4 x i8*] }* @_ZTV4Base to i8* (%struct.Base*)**), i64 2)
// CHECK-NEXT: [[U2:%.*]] = call i8* [[U1]]
char* c = p->Base::abc();
}
@@ -49,7 +49,7 @@ struct Derived2 : virtual Base2 {
char* Derived2::efg(void) const { return 0; }
void FUNC2(Derived2* p) {
-// CHECK: [[V1:%.*]] = load i8* (%struct.Derived2*)*, i8* (%struct.Derived2*)** getelementptr inbounds (i8* (%struct.Derived2*)*, i8* (%struct.Derived2*)** bitcast ([5 x i8*]* @_ZTV8Derived2 to i8* (%struct.Derived2*)**), i64 3)
+// CHECK: [[V1:%.*]] = load i8* (%struct.Derived2*)*, i8* (%struct.Derived2*)** getelementptr inbounds (i8* (%struct.Derived2*)*, i8* (%struct.Derived2*)** bitcast ({ [5 x i8*] }* @_ZTV8Derived2 to i8* (%struct.Derived2*)**), i64 3)
// CHECK-NEXT: [[V2:%.*]] = call i8* [[V1]]
char* c = p->Derived2::efg();
}
@@ -70,7 +70,7 @@ struct Sub : D1, D2 {
char* D2::abc(void) const { return 0; }
void FUNC3(Sub* p) {
-// CHECK: [[W1:%.*]] = load i8* (%struct.D2*)*, i8* (%struct.D2*)** getelementptr inbounds (i8* (%struct.D2*)*, i8* (%struct.D2*)** bitcast ([5 x i8*]* @_ZTV2D2 to i8* (%struct.D2*)**), i64 3)
+// CHECK: [[W1:%.*]] = load i8* (%struct.D2*)*, i8* (%struct.D2*)** getelementptr inbounds (i8* (%struct.D2*)*, i8* (%struct.D2*)** bitcast ({ [5 x i8*] }* @_ZTV2D2 to i8* (%struct.D2*)**), i64 3)
// CHECK-NEXT: [[W2:%.*]] = call i8* [[W1]]
char* c = p->D2::abc();
}
diff --git a/test/CodeGenCXX/apple-kext-indirect-call.cpp b/test/CodeGenCXX/apple-kext-indirect-call.cpp
index e4c03b5da50b..ac0e3f4d39c6 100644
--- a/test/CodeGenCXX/apple-kext-indirect-call.cpp
+++ b/test/CodeGenCXX/apple-kext-indirect-call.cpp
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fapple-kext -emit-llvm -o - %s | FileCheck %s
-// CHECK: @_ZTV5TemplIiE = internal unnamed_addr constant [5 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTI5TemplIiE to i8*), i8* bitcast (void (%struct.Templ*)* @_ZN5TemplIiE1fEv to i8*), i8* bitcast (void (%struct.Templ*)* @_ZN5TemplIiE1gEv to i8*), i8* null]
+// CHECK: @_ZTV5TemplIiE = internal unnamed_addr constant { [5 x i8*] } { [5 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTI5TemplIiE to i8*), i8* bitcast (void (%struct.Templ*)* @_ZN5TemplIiE1fEv to i8*), i8* bitcast (void (%struct.Templ*)* @_ZN5TemplIiE1gEv to i8*), i8* null] }
struct Base {
virtual void abc(void) const;
@@ -12,7 +12,7 @@ void FUNC(Base* p) {
p->Base::abc();
}
-// CHECK: getelementptr inbounds (void (%struct.Base*)*, void (%struct.Base*)** bitcast ([4 x i8*]* @_ZTV4Base to void (%struct.Base*)**), i64 2)
+// CHECK: getelementptr inbounds (void (%struct.Base*)*, void (%struct.Base*)** bitcast ({ [4 x i8*] }* @_ZTV4Base to void (%struct.Base*)**), i64 2)
// CHECK-NOT: call void @_ZNK4Base3abcEv
template<class T>
@@ -37,6 +37,6 @@ void f(SubTempl<int>* t) {
t->Templ::f();
}
-// CHECK: getelementptr inbounds (void (%struct.Templ*)*, void (%struct.Templ*)** bitcast ([5 x i8*]* @_ZTV5TemplIiE to void (%struct.Templ*)**), i64 2)
+// CHECK: getelementptr inbounds (void (%struct.Templ*)*, void (%struct.Templ*)** bitcast ({ [5 x i8*] }* @_ZTV5TemplIiE to void (%struct.Templ*)**), i64 2)
// CHECK: define internal void @_ZN5TemplIiE1fEv(%struct.Templ* %this)
// CHECK: define internal void @_ZN5TemplIiE1gEv(%struct.Templ* %this)
diff --git a/test/CodeGenCXX/apple-kext-indirect-virtual-dtor-call.cpp b/test/CodeGenCXX/apple-kext-indirect-virtual-dtor-call.cpp
index 5f6bdb230fe7..4cfa88d99455 100644
--- a/test/CodeGenCXX/apple-kext-indirect-virtual-dtor-call.cpp
+++ b/test/CodeGenCXX/apple-kext-indirect-virtual-dtor-call.cpp
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fapple-kext -fno-rtti -emit-llvm -o - %s | FileCheck %s
-// CHECK: @_ZTV5TemplIiE = internal unnamed_addr constant [7 x i8*] [i8* null, i8* null, i8* bitcast (void (%struct.Templ*)* @_ZN5TemplIiED1Ev to i8*), i8* bitcast (void (%struct.Templ*)* @_ZN5TemplIiED0Ev to i8*), i8* bitcast (void (%struct.Templ*)* @_ZN5TemplIiE1fEv to i8*), i8* bitcast (void (%struct.Templ*)* @_ZN5TemplIiE1gEv to i8*), i8* null]
+// CHECK: @_ZTV5TemplIiE = internal unnamed_addr constant { [7 x i8*] } { [7 x i8*] [i8* null, i8* null, i8* bitcast (void (%struct.Templ*)* @_ZN5TemplIiED1Ev to i8*), i8* bitcast (void (%struct.Templ*)* @_ZN5TemplIiED0Ev to i8*), i8* bitcast (void (%struct.Templ*)* @_ZN5TemplIiE1fEv to i8*), i8* bitcast (void (%struct.Templ*)* @_ZN5TemplIiE1gEv to i8*), i8* null] }
struct B1 {
virtual ~B1();
@@ -12,10 +12,10 @@ void DELETE(B1 *pb1) {
pb1->B1::~B1();
}
// CHECK-LABEL: define void @_ZN2B1D0Ev
-// CHECK: [[T1:%.*]] = load void (%struct.B1*)*, void (%struct.B1*)** getelementptr inbounds (void (%struct.B1*)*, void (%struct.B1*)** bitcast ([5 x i8*]* @_ZTV2B1 to void (%struct.B1*)**), i64 2)
+// CHECK: [[T1:%.*]] = load void (%struct.B1*)*, void (%struct.B1*)** getelementptr inbounds (void (%struct.B1*)*, void (%struct.B1*)** bitcast ({ [5 x i8*] }* @_ZTV2B1 to void (%struct.B1*)**), i64 2)
// CHECK-NEXT: call void [[T1]](%struct.B1* [[T2:%.*]])
// CHECK-LABEL: define void @_Z6DELETEP2B1
-// CHECK: [[T3:%.*]] = load void (%struct.B1*)*, void (%struct.B1*)** getelementptr inbounds (void (%struct.B1*)*, void (%struct.B1*)** bitcast ([5 x i8*]* @_ZTV2B1 to void (%struct.B1*)**), i64 2)
+// CHECK: [[T3:%.*]] = load void (%struct.B1*)*, void (%struct.B1*)** getelementptr inbounds (void (%struct.B1*)*, void (%struct.B1*)** bitcast ({ [5 x i8*] }* @_ZTV2B1 to void (%struct.B1*)**), i64 2)
// CHECK-NEXT: call void [[T3]](%struct.B1* [[T4:%.*]])
template<class T>
@@ -42,7 +42,7 @@ void f(SubTempl<int>* t) {
t->Templ::~Templ();
}
-// CHECK: getelementptr inbounds (void (%struct.Templ*)*, void (%struct.Templ*)** bitcast ([7 x i8*]* @_ZTV5TemplIiE to void (%struct.Templ*)**), i64 2)
+// CHECK: getelementptr inbounds (void (%struct.Templ*)*, void (%struct.Templ*)** bitcast ({ [7 x i8*] }* @_ZTV5TemplIiE to void (%struct.Templ*)**), i64 2)
// CHECK: declare void @_ZN5TemplIiED0Ev(%struct.Templ*)
// CHECK: define internal void @_ZN5TemplIiE1fEv(%struct.Templ* %this)
// CHECK: define internal void @_ZN5TemplIiE1gEv(%struct.Templ* %this)
diff --git a/test/CodeGenCXX/arm-swiftcall.cpp b/test/CodeGenCXX/arm-swiftcall.cpp
index 535350c808d3..5c932c77b1da 100644
--- a/test/CodeGenCXX/arm-swiftcall.cpp
+++ b/test/CodeGenCXX/arm-swiftcall.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple armv7-apple-darwin9 -emit-llvm -o - %s -Wno-return-type-c-linkage | FileCheck %s
+// RUN: %clang_cc1 -triple armv7-apple-darwin9 -emit-llvm -o - %s -Wno-return-type-c-linkage -std=c++03 | FileCheck %s -check-prefixes=CHECK
// This isn't really testing anything ARM-specific; it's just a convenient
// 32-bit platform.
diff --git a/test/CodeGenCXX/arm64.cpp b/test/CodeGenCXX/arm64.cpp
index 19f72726e690..80438397c3f2 100644
--- a/test/CodeGenCXX/arm64.cpp
+++ b/test/CodeGenCXX/arm64.cpp
@@ -84,3 +84,39 @@ namespace test2 {
// CHECK-GLOBALS-DAG: @_ZTIN5test21EIiEE = weak_odr constant { {{.*}}, i8* inttoptr (i64 add (i64 ptrtoint ([14 x i8]* @_ZTSN5test21EIiEE to i64), i64 -9223372036854775808) to i8*) }
}
+
+// ARM64 reserves the top half of the vtable offset in virtual
+// member pointers.
+namespace test3 {
+ struct A {
+ virtual void foo();
+ virtual void bar();
+ };
+
+ // The offset half of the pointer is still initialized to zero.
+ // CHECK-GLOBALS-DAG: @_ZN5test34mptrE = global { i64, i64 } { i64 0, i64 1 }
+ void (A::*mptr)() = &A::foo;
+
+ // CHECK-LABEL: define void @_ZN5test34testEv()
+ // CHECK: [[TEMP:%.*]] = alloca [[A:.*]], align 8
+ // CHECK: [[MEMPTR:%.*]] = load { i64, i64 }, { i64, i64 }* @_ZN5test34mptrE, align 8
+ // CHECK: [[ADJUST_AND_IS_VIRTUAL:%.*]] = extractvalue { i64, i64 } [[MEMPTR]], 1
+ // CHECK: [[ADJUST:%.*]] = ashr i64 [[ADJUST_AND_IS_VIRTUAL]], 1
+ // CHECK: [[T0:%.*]] = bitcast [[A]]* [[TEMP]] to i8*
+ // CHECK: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i64 [[ADJUST]]
+ // CHECK: [[ADJUSTED:%.*]] = bitcast i8* [[T1]] to [[A]]*
+ // CHECK: [[MEMBER:%.*]] = extractvalue { i64, i64 } [[MEMPTR]], 0
+ // CHECK: [[T0:%.*]] = and i64 [[ADJUST_AND_IS_VIRTUAL]], 1
+ // CHECK: [[IS_VIRTUAL:%.*]] = icmp ne i64 [[T0]], 0
+ // CHECK: br i1 [[IS_VIRTUAL]],
+ // CHECK: [[T0:%.*]] = bitcast [[A]]* [[ADJUSTED]] to i8**
+ // CHECK: [[VPTR:%.*]] = load i8*, i8** [[T0]], align 8
+ // CHECK: [[TRUNC:%.*]] = trunc i64 [[MEMBER]] to i32
+ // CHECK: [[ZEXT:%.*]] = zext i32 [[TRUNC]] to i64
+ // CHECK: [[T0:%.*]] = getelementptr i8, i8* [[VPTR]], i64 [[ZEXT]]
+ // CHECK: [[T1:%.*]] = bitcast i8* [[T0]] to void ([[A]]*)**
+ // CHECK: load void ([[A]]*)*, void ([[A]]*)** [[T1]],
+ void test() {
+ (A().*mptr)();
+ }
+}
diff --git a/test/CodeGenCXX/atomicinit.cpp b/test/CodeGenCXX/atomicinit.cpp
index 96f44d52f286..4c30ec35212f 100644
--- a/test/CodeGenCXX/atomicinit.cpp
+++ b/test/CodeGenCXX/atomicinit.cpp
@@ -51,8 +51,8 @@ struct AtomicBoolMember {
};
// CHECK-LABEL: define void @_ZN16AtomicBoolMemberC2Eb
-// CHECK: {{zext i1.*to i8}}
-// CHECK-NEXT: store i8
+// CHECK: zext i1 {{.*}} to i8
+// CHECK: store i8
// CHECK-NEXT: ret void
AtomicBoolMember::AtomicBoolMember(bool b) : ab(b) { }
diff --git a/test/CodeGenCXX/attr.cpp b/test/CodeGenCXX/attr.cpp
index 67993b4227a1..7f5595f6f044 100644
--- a/test/CodeGenCXX/attr.cpp
+++ b/test/CodeGenCXX/attr.cpp
@@ -31,4 +31,4 @@ int test1() { return 10; }
// CHECK at top of file
extern "C" int test2() __attribute__((alias("_Z5test1v")));
-// CHECK: attributes [[NUW]] = { nounwind{{.*}} }
+// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} }
diff --git a/test/CodeGenCXX/block-in-ctor-dtor.cpp b/test/CodeGenCXX/block-in-ctor-dtor.cpp
index 0dc0ab00437f..0ec9db1db728 100644
--- a/test/CodeGenCXX/block-in-ctor-dtor.cpp
+++ b/test/CodeGenCXX/block-in-ctor-dtor.cpp
@@ -42,7 +42,5 @@ X::~X() {
// CHECK-LABEL: define internal void @___ZN4ZoneD2Ev_block_invoke_
// CHECK-LABEL: define internal void @___ZN1XC2Ev_block_invoke
// CHECK-LABEL: define internal void @___ZN1XC2Ev_block_invoke_
-// CHECK-LABEL: define internal void @___ZN1XC1Ev_block_invoke
-// CHECK-LABEL: define internal void @___ZN1XC1Ev_block_invoke_
// CHECK-LABEL: define internal void @___ZN1XD2Ev_block_invoke
// CHECK-LABEL: define internal void @___ZN1XD2Ev_block_invoke_
diff --git a/test/CodeGenCXX/builtins-arm-exclusive.cpp b/test/CodeGenCXX/builtins-arm-exclusive.cpp
new file mode 100644
index 000000000000..06f7a023adec
--- /dev/null
+++ b/test/CodeGenCXX/builtins-arm-exclusive.cpp
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 -Wall -Werror -triple thumbv8-linux-gnueabi -fno-signed-char -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -Wall -Werror -triple arm64-apple-ios7.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-ARM64
+
+bool b;
+
+// CHECK-LABEL: @_Z10test_ldrexv()
+// CHECK: call i32 @llvm.arm.ldrex.p0i8(i8* @b)
+
+// CHECK-ARM64-LABEL: @_Z10test_ldrexv()
+// CHECK-ARM64: call i64 @llvm.aarch64.ldxr.p0i8(i8* @b)
+
+void test_ldrex() {
+ b = __builtin_arm_ldrex(&b);
+}
+
+// CHECK-LABEL: @_Z10tset_strexv()
+// CHECK: %{{.*}} = call i32 @llvm.arm.strex.p0i8(i32 1, i8* @b)
+
+// CHECK-ARM64-LABEL: @_Z10tset_strexv()
+// CHECK-ARM64: %{{.*}} = call i32 @llvm.aarch64.stxr.p0i8(i64 1, i8* @b)
+
+void tset_strex() {
+ __builtin_arm_strex(true, &b);
+}
diff --git a/test/CodeGenCXX/catch-undef-behavior.cpp b/test/CodeGenCXX/catch-undef-behavior.cpp
index 3ca7f6d65ad4..179c33412267 100644
--- a/test/CodeGenCXX/catch-undef-behavior.cpp
+++ b/test/CodeGenCXX/catch-undef-behavior.cpp
@@ -277,13 +277,13 @@ int array_index(const int (&a)[4], int n) {
int multi_array_index(int n, int m) {
int arr[4][6];
- // CHECK: %[[IDX2_OK:.*]] = icmp ult i64 %{{.*}}, 6
- // CHECK: br i1 %[[IDX2_OK]]
- // CHECK: call void @__ubsan_handle_out_of_bounds(
-
// CHECK: %[[IDX1_OK:.*]] = icmp ult i64 %{{.*}}, 4
// CHECK: br i1 %[[IDX1_OK]]
// CHECK: call void @__ubsan_handle_out_of_bounds(
+
+ // CHECK: %[[IDX2_OK:.*]] = icmp ult i64 %{{.*}}, 6
+ // CHECK: br i1 %[[IDX2_OK]]
+ // CHECK: call void @__ubsan_handle_out_of_bounds(
return arr[n][m];
}
diff --git a/test/CodeGenCXX/cfi-cross-dso.cpp b/test/CodeGenCXX/cfi-cross-dso.cpp
index d67927d4d2ed..bfa0705c6f8f 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*] } {{.*}}@"\01??_R4B@?A@@6B@"{{.*}}@"\01?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/compound-literals.cpp b/test/CodeGenCXX/compound-literals.cpp
index 69632a7de2f4..a9882bc6d241 100644
--- a/test/CodeGenCXX/compound-literals.cpp
+++ b/test/CodeGenCXX/compound-literals.cpp
@@ -12,6 +12,9 @@ struct Y {
X x;
};
+// CHECK: @.compoundliteral = internal global [5 x i32] [i32 1, i32 2, i32 3, i32 4, i32 5], align 4
+// CHECK: @q = global i32* getelementptr inbounds ([5 x i32], [5 x i32]* @.compoundliteral, i32 0, i32 0), align 4
+
// CHECK-LABEL: define i32 @_Z1fv()
int f() {
// CHECK: [[LVALUE:%[a-z0-9.]+]] = alloca
@@ -38,20 +41,45 @@ int g() {
return v[0];
}
+// GCC's compound-literals-in-C++ extension lifetime-extends a compound literal
+// (or a C++11 list-initialized temporary!) if:
+// - it is at global scope
+// - it has array type
+// - it has a constant initializer
+
struct Z { int i[3]; };
int *p = (Z){ {1, 2, 3} }.i;
// CHECK: define {{.*}}__cxx_global_var_init()
-// CHECK: store i32* getelementptr inbounds (%struct.Z, %struct.Z* @.compoundliteral, i32 0, i32 0, i32 0), i32** @p
+// CHECK: alloca %struct.Z
+// CHECK: store i32* %{{.*}}, i32** @p
+int *q = (int [5]){1, 2, 3, 4, 5};
+// (constant initialization, checked above)
-int *PR21912_1 = (int []){};
+extern int n;
+int *r = (int [5]){1, 2, 3, 4, 5} + n;
// CHECK-LABEL: define {{.*}}__cxx_global_var_init.1()
-// CHECK: store i32* getelementptr inbounds ([0 x i32], [0 x i32]* @.compoundliteral.2, i32 0, i32 0), i32** @PR21912_1
+// CHECK: %[[PTR:.*]] = getelementptr inbounds i32, i32* getelementptr inbounds ([5 x i32], [5 x i32]* @.compoundliteral.2, i32 0, i32 0), i32 %
+// CHECK: store i32* %[[PTR]], i32** @r
+
+int *PR21912_1 = (int []){} + n;
+// CHECK-LABEL: define {{.*}}__cxx_global_var_init.3()
+// CHECK: %[[PTR:.*]] = getelementptr inbounds i32, i32* getelementptr inbounds ([0 x i32], [0 x i32]* @.compoundliteral.4, i32 0, i32 0), i32 %
+// CHECK: store i32* %[[PTR]], i32** @PR21912_1
union PR21912Ty {
long long l;
double d;
};
-union PR21912Ty *PR21912_2 = (union PR21912Ty[]){{.d = 2.0}, {.l = 3}};
-// CHECK-LABEL: define {{.*}}__cxx_global_var_init.3()
-// CHECK: store %union.PR21912Ty* getelementptr inbounds ([2 x %union.PR21912Ty], [2 x %union.PR21912Ty]* bitcast (<{ { double }, %union.PR21912Ty }>* @.compoundliteral.4 to [2 x %union.PR21912Ty]*), i32 0, i32 0), %union.PR21912Ty** @PR21912_2
+union PR21912Ty *PR21912_2 = (union PR21912Ty[]){{.d = 2.0}, {.l = 3}} + n;
+// CHECK-LABEL: define {{.*}}__cxx_global_var_init.5()
+// CHECK: %[[PTR:.*]] = getelementptr inbounds %union.PR21912Ty, %union.PR21912Ty* getelementptr inbounds ([2 x %union.PR21912Ty], [2 x %union.PR21912Ty]* bitcast (<{ { double }, %union.PR21912Ty }>* @.compoundliteral.6 to [2 x %union.PR21912Ty]*), i32 0, i32 0), i32 %
+// CHECK: store %union.PR21912Ty* %[[PTR]], %union.PR21912Ty** @PR21912_2, align 4
+
+// This compound literal should have local scope.
+int computed_with_lambda = [] {
+ int *array = (int[]) { 1, 3, 5, 7 };
+ return array[0];
+}();
+// CHECK-LABEL: define internal i32 @{{.*}}clEv
+// CHECK: alloca [4 x i32]
diff --git a/test/CodeGenCXX/const-init-cxx11.cpp b/test/CodeGenCXX/const-init-cxx11.cpp
index 0c2193fb07f2..c4962bc08ad6 100644
--- a/test/CodeGenCXX/const-init-cxx11.cpp
+++ b/test/CodeGenCXX/const-init-cxx11.cpp
@@ -343,13 +343,13 @@ namespace VirtualMembers {
constexpr E() : B(3), c{'b','y','e'} {}
char c[3];
};
- // CHECK: @_ZN14VirtualMembers1eE = global { i8**, double, i32, i8**, double, [5 x i8], i16, i8**, double, [5 x i8], [3 x i8] } { i8** getelementptr inbounds ([11 x i8*], [11 x i8*]* @_ZTVN14VirtualMembers1EE, i32 0, i32 2), double 1.000000e+00, i32 64, i8** getelementptr inbounds ([11 x i8*], [11 x i8*]* @_ZTVN14VirtualMembers1EE, i32 0, i32 5), double 2.000000e+00, [5 x i8] c"hello", i16 5, i8** getelementptr inbounds ([11 x i8*], [11 x i8*]* @_ZTVN14VirtualMembers1EE, i32 0, i32 9), double 3.000000e+00, [5 x i8] c"world", [3 x i8] c"bye" }
+ // CHECK: @_ZN14VirtualMembers1eE = global { i8**, double, i32, i8**, double, [5 x i8], i16, i8**, double, [5 x i8], [3 x i8] } { i8** getelementptr inbounds ({ [3 x i8*], [4 x i8*], [4 x i8*] }, { [3 x i8*], [4 x i8*], [4 x i8*] }* @_ZTVN14VirtualMembers1EE, i32 0, inrange i32 0, i32 2), double 1.000000e+00, i32 64, i8** getelementptr inbounds ({ [3 x i8*], [4 x i8*], [4 x i8*] }, { [3 x i8*], [4 x i8*], [4 x i8*] }* @_ZTVN14VirtualMembers1EE, i32 0, inrange i32 1, i32 2), double 2.000000e+00, [5 x i8] c"hello", i16 5, i8** getelementptr inbounds ({ [3 x i8*], [4 x i8*], [4 x i8*] }, { [3 x i8*], [4 x i8*], [4 x i8*] }* @_ZTVN14VirtualMembers1EE, i32 0, inrange i32 2, i32 2), double 3.000000e+00, [5 x i8] c"world", [3 x i8] c"bye" }
E e;
struct nsMemoryImpl {
virtual void f();
};
- // CHECK: @_ZN14VirtualMembersL13sGlobalMemoryE = internal global { i8** } { i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN14VirtualMembers12nsMemoryImplE, i32 0, i32 2) }
+ // CHECK: @_ZN14VirtualMembersL13sGlobalMemoryE = internal global { i8** } { i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTVN14VirtualMembers12nsMemoryImplE, i32 0, inrange i32 0, i32 2) }
__attribute__((used))
static nsMemoryImpl sGlobalMemory;
@@ -360,7 +360,7 @@ namespace VirtualMembers {
T t;
};
- // CHECK: @_ZN14VirtualMembers1tE = global { i8**, i32 } { i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN14VirtualMembers13TemplateClassIiEE, i32 0, i32 2), i32 42 }
+ // CHECK: @_ZN14VirtualMembers1tE = global { i8**, i32 } { i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTVN14VirtualMembers13TemplateClassIiEE, i32 0, inrange i32 0, i32 2), i32 42 }
TemplateClass<int> t;
}
diff --git a/test/CodeGenCXX/constructor-destructor-return-this.cpp b/test/CodeGenCXX/constructor-destructor-return-this.cpp
index 9d47d1706bbe..164fda3c1c38 100644
--- a/test/CodeGenCXX/constructor-destructor-return-this.cpp
+++ b/test/CodeGenCXX/constructor-destructor-return-this.cpp
@@ -111,7 +111,7 @@ D::~D() { }
// 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*)
+// CHECKMS-LABEL: define x86_thiscallcc void @"\01??1D@@UAE@XZ"(%class.D* %this)
class E {
public:
diff --git a/test/CodeGenCXX/constructor-init.cpp b/test/CodeGenCXX/constructor-init.cpp
index c78534a218de..fe15ccf8fef5 100644
--- a/test/CodeGenCXX/constructor-init.cpp
+++ b/test/CodeGenCXX/constructor-init.cpp
@@ -95,14 +95,14 @@ namespace InitVTable {
// CHECK-LABEL: define void @_ZN10InitVTable1BC2Ev(%"struct.InitVTable::B"* %this) unnamed_addr
// CHECK: [[T0:%.*]] = bitcast [[B:%.*]]* [[THIS:%.*]] to i32 (...)***
- // CHECK-NEXT: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN10InitVTable1BE, i32 0, i32 2) to i32 (...)**), i32 (...)*** [[T0]]
+ // CHECK-NEXT: store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTVN10InitVTable1BE, i32 0, inrange i32 0, i32 2) to i32 (...)**), i32 (...)*** [[T0]]
// CHECK: [[VTBL:%.*]] = load i32 ([[B]]*)**, i32 ([[B]]*)*** {{%.*}}
// CHECK-NEXT: [[FNP:%.*]] = getelementptr inbounds i32 ([[B]]*)*, i32 ([[B]]*)** [[VTBL]], i64 0
// CHECK-NEXT: [[FN:%.*]] = load i32 ([[B]]*)*, i32 ([[B]]*)** [[FNP]]
// CHECK-NEXT: [[ARG:%.*]] = call i32 [[FN]]([[B]]* [[THIS]])
// CHECK-NEXT: call void @_ZN10InitVTable1AC2Ei({{.*}}* {{%.*}}, i32 [[ARG]])
// CHECK-NEXT: [[T0:%.*]] = bitcast [[B]]* [[THIS]] to i32 (...)***
- // CHECK-NEXT: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN10InitVTable1BE, i32 0, i32 2) to i32 (...)**), i32 (...)*** [[T0]]
+ // CHECK-NEXT: store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTVN10InitVTable1BE, i32 0, inrange i32 0, i32 2) to i32 (...)**), i32 (...)*** [[T0]]
// CHECK-NEXT: ret void
B::B() : A(foo()) {}
@@ -110,7 +110,7 @@ namespace InitVTable {
// CHECK: [[ARG:%.*]] = add nsw i32 {{%.*}}, 5
// CHECK-NEXT: call void @_ZN10InitVTable1AC2Ei({{.*}}* {{%.*}}, i32 [[ARG]])
// CHECK-NEXT: [[T0:%.*]] = bitcast [[B]]* {{%.*}} to i32 (...)***
- // CHECK-NEXT: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN10InitVTable1BE, i32 0, i32 2) to i32 (...)**), i32 (...)*** [[T0]]
+ // CHECK-NEXT: store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTVN10InitVTable1BE, i32 0, inrange i32 0, i32 2) to i32 (...)**), i32 (...)*** [[T0]]
// CHECK-NEXT: ret void
B::B(int x) : A(x + 5) {}
}
@@ -207,20 +207,17 @@ namespace PR10720 {
// CHECK-PR10720-LABEL: define linkonce_odr void @_ZN7PR107205pair2C2ERKS0_
// CHECK-PR10720-NOT: ret
- // CHECK-PR10720: load
- // CHECK-PR10720: icmp ult
- // CHECK-PR10720-NEXT: br i1
// CHECK-PR10720: call void @_ZN7PR107201XC1ERKS0_
- // CHECK-PR10720-NEXT: br label
+ // CHECK-PR10720: icmp eq
+ // CHECK-PR10720-NEXT: br i1
// CHECK-PR10720: ret void
// CHECK-PR10720-LABEL: define linkonce_odr void @_ZN7PR107205pair2C2EOS0_
// CHECK-PR10720-NOT: ret
// CHECK-PR10720: load
- // CHECK-PR10720: icmp ult
- // CHECK-PR10720-NEXT: br i1
// CHECK-PR10720: call void @_ZN7PR107201XC1EOS0_
- // CHECK-PR10720-NEXT: br label
+ // CHECK-PR10720: icmp eq
+ // CHECK-PR10720-NEXT: br i1
// CHECK-PR10720: ret void
pair2(pair2&&) = default;
diff --git a/test/CodeGenCXX/copy-constructor-elim-2.cpp b/test/CodeGenCXX/copy-constructor-elim-2.cpp
index c263b7ebf952..26b6b4851f5a 100644
--- a/test/CodeGenCXX/copy-constructor-elim-2.cpp
+++ b/test/CodeGenCXX/copy-constructor-elim-2.cpp
@@ -74,3 +74,23 @@ namespace PR12139 {
return a.value;
}
}
+
+namespace ElidableCallIsNotCopyCtor {
+ struct A { A(const A&); };
+ struct B : A {
+ B(B&);
+ B(A);
+ B(int);
+ };
+ void f() {
+ // Here, we construct via B(int) then B(A). The B(A) construction is
+ // elidable, but we don't have an AST representation for the case where we
+ // must elide not only a constructor call but also some argument
+ // conversions, so we don't elide it.
+ // CHECK-LABEL: define void @_ZN25ElidableCallIsNotCopyCtor1fEv(
+ // CHECK: call {{.*}} @_ZN25ElidableCallIsNotCopyCtor1BC1Ei(
+ // CHECK: call {{.*}} @_ZN25ElidableCallIsNotCopyCtor1AC1ERKS0_(
+ // CHECK: call {{.*}} @_ZN25ElidableCallIsNotCopyCtor1BC1ENS_1AE(
+ B b = 0;
+ }
+}
diff --git a/test/CodeGenCXX/copy-constructor-synthesis-2.cpp b/test/CodeGenCXX/copy-constructor-synthesis-2.cpp
index 9790ca882c6b..9d7e18e80f67 100644
--- a/test/CodeGenCXX/copy-constructor-synthesis-2.cpp
+++ b/test/CodeGenCXX/copy-constructor-synthesis-2.cpp
@@ -24,4 +24,4 @@ struct A { virtual void a(); };
A x(A& y) { return y; }
// CHECK: define linkonce_odr {{.*}} @_ZN1AC1ERKS_(%struct.A* {{.*}}%this, %struct.A* dereferenceable({{[0-9]+}})) unnamed_addr
-// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1A, i32 0, i32 2) to i32 (...)**)
+// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTV1A, i32 0, inrange i32 0, i32 2) to i32 (...)**)
diff --git a/test/CodeGenCXX/copy-constructor-synthesis.cpp b/test/CodeGenCXX/copy-constructor-synthesis.cpp
index 4928c61488e9..5a2cc1440f74 100644
--- a/test/CodeGenCXX/copy-constructor-synthesis.cpp
+++ b/test/CodeGenCXX/copy-constructor-synthesis.cpp
@@ -166,7 +166,7 @@ void f(B b1) {
// CHECK-LABEL: define linkonce_odr void @_ZN12rdar138169401AC2ERKS0_(
// CHECK: [[THIS:%.*]] = load [[A]]*, [[A]]**
// CHECK-NEXT: [[T0:%.*]] = bitcast [[A]]* [[THIS]] to i32 (...)***
-// CHECK-NEXT: store i32 (...)** bitcast (i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @_ZTVN12rdar138169401AE, i32 0, i32 2) to i32 (...)**), i32 (...)*** [[T0]]
+// CHECK-NEXT: store i32 (...)** bitcast (i8** getelementptr inbounds ({ [4 x i8*] }, { [4 x i8*] }* @_ZTVN12rdar138169401AE, i32 0, inrange i32 0, i32 2) to i32 (...)**), i32 (...)*** [[T0]]
// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[A]], [[A]]* [[THIS]], i32 0, i32 1
// CHECK-NEXT: [[OTHER:%.*]] = load [[A]]*, [[A]]**
// CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[A]], [[A]]* [[OTHER]], i32 0, i32 1
diff --git a/test/CodeGenCXX/ctor-dtor-alias.cpp b/test/CodeGenCXX/ctor-dtor-alias.cpp
index 018e958aab53..6826ee5796ca 100644
--- a/test/CodeGenCXX/ctor-dtor-alias.cpp
+++ b/test/CodeGenCXX/ctor-dtor-alias.cpp
@@ -1,6 +1,6 @@
// 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 -O1 -disable-llvm-optzns > %t
+// 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
// RUN: FileCheck --check-prefix=CHECK3 --input-file=%t %s
@@ -8,7 +8,7 @@
// RUN: FileCheck --check-prefix=CHECK5 --input-file=%t %s
// RUN: FileCheck --check-prefix=CHECK6 --input-file=%t %s
-// RUN: %clang_cc1 %s -triple i686-pc-windows-gnu -emit-llvm -o - -mconstructor-aliases -O1 -disable-llvm-optzns | FileCheck --check-prefix=COFF %s
+// 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
@@ -172,7 +172,7 @@ void zed() {
}
}
-// CHECK5: @_ZTV1C = linkonce_odr unnamed_addr constant [4 x i8*] [{{[^@]*}}@_ZTI1C {{[^@]*}}@_ZN1CD2Ev {{[^@]*}}@_ZN1CD0Ev {{[^@]*}}]
+// CHECK5: @_ZTV1C = linkonce_odr unnamed_addr constant { [4 x i8*] } {{[^@]*}}@_ZTI1C {{[^@]*}}@_ZN1CD2Ev {{[^@]*}}@_ZN1CD0Ev {{[^@]*}}]
// r194296 replaced C::~C with B::~B without emitting the later.
class A {
diff --git a/test/CodeGenCXX/cxx11-exception-spec.cpp b/test/CodeGenCXX/cxx11-exception-spec.cpp
index 6a3a394e047a..fbff07802676 100644
--- a/test/CodeGenCXX/cxx11-exception-spec.cpp
+++ b/test/CodeGenCXX/cxx11-exception-spec.cpp
@@ -121,7 +121,7 @@ void j() {
}
// CHECK: attributes [[NONE]] = { {{.*}} }
-// CHECK: attributes [[NUW]] = { nounwind{{.*}} }
+// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} }
// CHECK: attributes [[NUW2]] = { nounwind{{.*}} }
diff --git a/test/CodeGenCXX/cxx11-noreturn.cpp b/test/CodeGenCXX/cxx11-noreturn.cpp
index b876bb9661ba..58a5a377133a 100644
--- a/test/CodeGenCXX/cxx11-noreturn.cpp
+++ b/test/CodeGenCXX/cxx11-noreturn.cpp
@@ -7,4 +7,4 @@ int g();
while (g()) {}
}
-// CHECK: attributes [[NR]] = { noreturn nounwind{{.*}} }
+// CHECK: attributes [[NR]] = { noinline noreturn nounwind{{.*}} }
diff --git a/test/CodeGenCXX/cxx1y-initializer-aggregate.cpp b/test/CodeGenCXX/cxx1y-initializer-aggregate.cpp
index 50629b590562..6d0ae8a09e65 100644
--- a/test/CodeGenCXX/cxx1y-initializer-aggregate.cpp
+++ b/test/CodeGenCXX/cxx1y-initializer-aggregate.cpp
@@ -51,8 +51,8 @@ C n{};
// CHECK: store i32 0, i32* getelementptr inbounds ({{.*}} @a, i32 0, i32 0)
// CHECK: store i8* {{.*}} @[[STR_A]]{{.*}}, i8** getelementptr inbounds ({{.*}} @a, i32 0, i32 1)
-// CHECK: load i32, i32* getelementptr inbounds ({{.*}} @a, i32 0, i32 0)
// CHECK: load i8*, i8** getelementptr inbounds ({{.*}} @a, i32 0, i32 1)
+// CHECK: load i32, i32* getelementptr inbounds ({{.*}} @a, i32 0, i32 0)
// CHECK: getelementptr inbounds i8, i8* %{{.*}}, {{.*}} %{{.*}}
// CHECK: store i8 %{{.*}}, i8* getelementptr inbounds ({{.*}} @a, i32 0, i32 2)
// CHECK: call i32 @_ZN1A1fEv({{.*}} @a)
diff --git a/test/CodeGenCXX/cxx1y-variable-template-linkage.cpp b/test/CodeGenCXX/cxx1y-variable-template-linkage.cpp
index 8c0b8c22096d..bc775568aaf1 100644
--- a/test/CodeGenCXX/cxx1y-variable-template-linkage.cpp
+++ b/test/CodeGenCXX/cxx1y-variable-template-linkage.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -std=c++1y -O1 -disable-llvm-optzns %s -o - | FileCheck %s -check-prefix=CHECKA -check-prefix=CHECK
-// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -std=c++1y -O1 -disable-llvm-optzns -fcxx-exceptions %s -o - | FileCheck %s -check-prefix=CHECKB -check-prefix=CHECK
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -std=c++1y -O1 -disable-llvm-passes %s -o - | FileCheck %s -check-prefix=CHECKA -check-prefix=CHECK
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -std=c++1y -O1 -disable-llvm-passes -fcxx-exceptions %s -o - | FileCheck %s -check-prefix=CHECKB -check-prefix=CHECK
// expected-no-diagnostics
// The variable template specialization x<Foo> generated in each file
diff --git a/test/CodeGenCXX/cxx1z-aligned-allocation.cpp b/test/CodeGenCXX/cxx1z-aligned-allocation.cpp
new file mode 100644
index 000000000000..437597d963b0
--- /dev/null
+++ b/test/CodeGenCXX/cxx1z-aligned-allocation.cpp
@@ -0,0 +1,206 @@
+// Check that delete exprs call aligned (de)allocation functions if
+// -faligned-allocation is passed in both C++11 and C++14.
+// RUN: %clang_cc1 -std=c++11 -fexceptions -fsized-deallocation -faligned-allocation %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s
+// RUN: %clang_cc1 -std=c++14 -fexceptions -fsized-deallocation -faligned-allocation %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s
+// RUN: %clang_cc1 -std=c++1z -fexceptions -fsized-deallocation %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s
+
+// Check that we don't used aligned (de)allocation without -faligned-allocation or C++1z.
+// RUN: %clang_cc1 -std=c++14 -DUNALIGNED -fexceptions %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s --check-prefix=CHECK-UNALIGNED
+// RUN: %clang_cc1 -std=c++1z -DUNALIGNED -fexceptions -fno-aligned-allocation %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s --check-prefix=CHECK-UNALIGNED
+
+// CHECK-UNALIGNED-NOT: _Znwm_St11align_val_t
+// CHECK-UNALIGNED-NOT: _Znam_St11align_val_t
+// CHECK-UNALIGNED-NOT: _ZdlPv_St11align_val_t
+// CHECK-UNALIGNED-NOT: _ZdaPv_St11align_val_t
+// CHECK-UNALIGNED-NOT: _ZdlPvm_St11align_val_t
+// CHECK-UNALIGNED-NOT: _ZdaPvm_St11align_val_t
+
+typedef decltype(sizeof(0)) size_t;
+namespace std { enum class align_val_t : size_t {}; }
+
+#define OVERALIGNED alignas(__STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2)
+
+// Global new and delete.
+// ======================
+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)
+void *a0() { return new A; }
+
+// CHECK-LABEL: define {{.*}} @_Z2a1l(
+// CHECK: %[[ALLOC:.*]] = call i8* @_ZnamSt11align_val_t(i64 %{{.*}}, i64 32)
+// No array cookie.
+// CHECK-NOT: store
+// CHECK: invoke void @_ZN1AC1Ev(
+// CHECK: call void @_ZdaPvSt11align_val_t(i8* %[[ALLOC]], i64 32)
+void *a1(long n) { return new A[n]; }
+
+// CHECK-LABEL: define {{.*}} @_Z2a2P1A(
+// CHECK: call void @_ZdlPvmSt11align_val_t(i8* %{{.*}}, i64 512, i64 32) #9
+void a2(A *p) { delete p; }
+
+// CHECK-LABEL: define {{.*}} @_Z2a3P1A(
+// CHECK: call void @_ZdaPvSt11align_val_t(i8* %{{.*}}, i64 32) #9
+void a3(A *p) { delete[] p; }
+
+
+// Class-specific usual new and delete.
+// ====================================
+struct OVERALIGNED B {
+ B();
+ // These are just a distraction. We should ignore them.
+ void *operator new(size_t);
+ void operator delete(void*, size_t);
+ void operator delete[](void*, size_t);
+
+ void *operator new(size_t, std::align_val_t);
+ void operator delete(void*, std::align_val_t);
+ void operator delete[](void*, std::align_val_t);
+
+ int n[128];
+};
+
+// CHECK-LABEL: define {{.*}} @_Z2b0v()
+// CHECK: %[[ALLOC:.*]] = call i8* @_ZN1BnwEmSt11align_val_t(i64 512, i64 32)
+// CHECK: call void @_ZN1BdlEPvSt11align_val_t(i8* %[[ALLOC]], i64 32)
+void *b0() { return new B; }
+
+// CHECK-LABEL: define {{.*}} @_Z2b1l(
+// CHECK: %[[ALLOC:.*]] = call i8* @_ZnamSt11align_val_t(i64 %{{.*}}, i64 32)
+// No array cookie.
+// CHECK-NOT: store
+// CHECK: invoke void @_ZN1BC1Ev(
+// CHECK: call void @_ZN1BdaEPvSt11align_val_t(i8* %[[ALLOC]], i64 32)
+void *b1(long n) { return new B[n]; }
+
+// CHECK-LABEL: define {{.*}} @_Z2b2P1B(
+// CHECK: call void @_ZN1BdlEPvSt11align_val_t(i8* %{{.*}}, i64 32)
+void b2(B *p) { delete p; }
+
+// CHECK-LABEL: define {{.*}} @_Z2b3P1B(
+// CHECK: call void @_ZN1BdaEPvSt11align_val_t(i8* %{{.*}}, i64 32)
+void b3(B *p) { delete[] p; }
+
+struct OVERALIGNED C {
+ C();
+ void *operator new[](size_t, std::align_val_t);
+ void operator delete[](void*, size_t, std::align_val_t);
+
+ // It doesn't matter that we have an unaligned operator delete[] that doesn't
+ // want the size. What matters is that the aligned one does.
+ void operator delete[](void*);
+};
+
+// This one has an array cookie.
+// CHECK-LABEL: define {{.*}} @_Z2b4l(
+// CHECK: call {{.*}} @llvm.umul.with.overflow{{.*}}i64 32
+// CHECK: call {{.*}} @llvm.uadd.with.overflow{{.*}}i64 32
+// CHECK: %[[ALLOC:.*]] = call i8* @_ZN1CnaEmSt11align_val_t(i64 %{{.*}}, i64 32)
+// CHECK: store
+// CHECK: call void @_ZN1CC1Ev(
+//
+// Note, we're still calling a placement allocation function, and there is no
+// matching placement operator delete. =(
+// FIXME: This seems broken.
+// CHECK-NOT: call void @_ZN1CdaEPvmSt11align_val_t(
+#ifndef UNALIGNED
+void *b4(long n) { return new C[n]; }
+#endif
+
+// CHECK-LABEL: define {{.*}} @_Z2b5P1C(
+// CHECK: mul i64{{.*}} 32
+// CHECK: add i64{{.*}} 32
+// CHECK: call void @_ZN1CdaEPvmSt11align_val_t(
+void b5(C *p) { delete[] p; }
+
+
+// Global placement new.
+// =====================
+
+struct Q { int n; } q;
+void *operator new(size_t, Q);
+void *operator new(size_t, std::align_val_t, Q);
+void operator delete(void*, Q);
+void operator delete(void*, std::align_val_t, Q);
+
+// CHECK-LABEL: define {{.*}} @_Z2c0v(
+// CHECK: %[[ALLOC:.*]] = call i8* @_ZnwmSt11align_val_t1Q(i64 512, i64 32, i32 %
+// CHECK: call void @_ZdlPvSt11align_val_t1Q(i8* %[[ALLOC]], i64 32, i32 %
+void *c0() { return new (q) A; }
+
+
+// Class-specific placement new.
+// =============================
+
+struct OVERALIGNED D {
+ D();
+ void *operator new(size_t, Q);
+ void *operator new(size_t, std::align_val_t, Q);
+ void operator delete(void*, Q);
+ void operator delete(void*, std::align_val_t, Q);
+};
+
+// CHECK-LABEL: define {{.*}} @_Z2d0v(
+// CHECK: %[[ALLOC:.*]] = call i8* @_ZN1DnwEmSt11align_val_t1Q(i64 32, i64 32, i32 %
+// CHECK: call void @_ZN1DdlEPvSt11align_val_t1Q(i8* %[[ALLOC]], i64 32, i32 %
+void *d0() { return new (q) D; }
+
+
+// Calling aligned new with placement syntax.
+// ==========================================
+
+#ifndef UNALIGNED
+// CHECK-LABEL: define {{.*}} @_Z2e0v(
+// CHECK: %[[ALLOC:.*]] = call i8* @_ZnwmSt11align_val_t(i64 512, i64 5)
+// CHECK: call void @_ZdlPvSt11align_val_t(i8* %[[ALLOC]], i64 5)
+void *e0() { return new (std::align_val_t(5)) A; }
+
+// CHECK-LABEL: define {{.*}} @_Z2e1v(
+// CHECK: %[[ALLOC:.*]] = call i8* @_ZN1BnwEmSt11align_val_t(i64 512, i64 5)
+// CHECK: call void @_ZN1BdlEPvSt11align_val_t(i8* %[[ALLOC]], i64 5)
+void *e1() { return new (std::align_val_t(5)) B; }
+#endif
+
+// Variadic placement/non-placement allocation functions.
+// ======================================================
+
+struct OVERALIGNED F {
+ F();
+ void *operator new(size_t, ...);
+ void operator delete(void*, ...);
+ int n[128];
+};
+
+// CHECK-LABEL: define {{.*}} @_Z2f0v(
+// CHECK: %[[ALLOC:.*]] = call i8* (i64, ...) @_ZN1FnwEmz(i64 512, i64 32)
+// Non-placement allocation function, uses normal deallocation lookup which
+// cares about whether a parameter has type std::align_val_t.
+// CHECK: call void (i8*, ...) @_ZN1FdlEPvz(i8* %[[ALLOC]])
+void *f0() { return new F; }
+
+// CHECK-LABEL: define {{.*}} @_Z2f1v(
+// CHECK: %[[ALLOC:.*]] = call i8* (i64, ...) @_ZN1FnwEmz(i64 512, i64 32, i32 %
+// Placement allocation function, uses placement deallocation matching, which
+// passes same arguments and therefore includes alignment.
+// CHECK: call void (i8*, ...) @_ZN1FdlEPvz(i8* %[[ALLOC]], i64 32, i32 %
+void *f1() { return new (q) F; }
+
+struct OVERALIGNED G {
+ G();
+ void *operator new(size_t, std::align_val_t, ...);
+ void operator delete(void*, std::align_val_t, ...);
+ int n[128];
+};
+#ifndef UNALIGNED
+// CHECK-LABEL: define {{.*}} @_Z2g0v
+// CHECK: %[[ALLOC:.*]] = call i8* (i64, i64, ...) @_ZN1GnwEmSt11align_val_tz(i64 512, i64 32)
+// CHECK: call void (i8*, i64, ...) @_ZN1GdlEPvSt11align_val_tz(i8* %[[ALLOC]], i64 32)
+void *g0() { return new G; }
+
+// CHECK-LABEL: define {{.*}} @_Z2g1v
+// CHECK: %[[ALLOC:.*]] = call i8* (i64, i64, ...) @_ZN1GnwEmSt11align_val_tz(i64 512, i64 32, i32 %
+// CHECK: call void (i8*, i64, ...) @_ZN1GdlEPvSt11align_val_tz(i8* %[[ALLOC]], i64 32, i32 %
+void *g1() { return new (q) G; }
+#endif
diff --git a/test/CodeGenCXX/cxx1z-constexpr-if.cpp b/test/CodeGenCXX/cxx1z-constexpr-if.cpp
index 80a397f51e9a..14695363b331 100644
--- a/test/CodeGenCXX/cxx1z-constexpr-if.cpp
+++ b/test/CodeGenCXX/cxx1z-constexpr-if.cpp
@@ -2,7 +2,15 @@
void should_be_used_1();
void should_be_used_2();
+void should_be_used_3();
void should_not_be_used();
+
+struct A {
+ constexpr explicit operator bool() const {
+ return true;
+ }
+};
+
void f() {
if constexpr (false)
should_not_be_used();
@@ -15,7 +23,12 @@ void f() {
goto foo;
foo: should_not_be_used();
}
+ if constexpr (A())
+ should_be_used_3();
+ else
+ should_not_be_used();
}
// CHECK: should_be_used_1
// CHECK: should_be_used_2
+// CHECK: should_be_used_3
diff --git a/test/CodeGenCXX/cxx1z-copy-omission.cpp b/test/CodeGenCXX/cxx1z-copy-omission.cpp
new file mode 100644
index 000000000000..234e4b12589c
--- /dev/null
+++ b/test/CodeGenCXX/cxx1z-copy-omission.cpp
@@ -0,0 +1,81 @@
+// RUN: %clang_cc1 -std=c++1z -emit-llvm -triple x86_64-linux-gnu -o - %s | FileCheck %s
+
+struct A {
+ A(int);
+ A(A&&);
+ A(const A&);
+ ~A();
+
+ int arr[10];
+};
+
+A f();
+void h();
+
+// CHECK-LABEL: define {{.*}} @_Z1gv(
+void g() {
+ // CHECK: %[[A:.*]] = alloca
+ // CHECK-NOT: alloca
+ // CHECK-NOT: call
+ // CHECK: call {{.*}} @_Z1fv({{.*}}* sret %[[A]])
+ A a = A( A{ f() } );
+ // CHECK-NOT: call
+
+ // CHECK: call void @_Z1hv(
+ h();
+ // CHECK-NOT: call
+
+ // CHECK: call void @_ZN1AD1Ev({{.*}}* %[[A]])
+ // CHECK-NOT: call
+ // CHECK-LABEL: }
+}
+
+void f(A);
+
+// CHECK-LABEL: define {{.*}} @_Z1hv(
+void h() {
+ // CHECK: %[[A:.*]] = alloca
+ // CHECK-NOT: alloca
+ // CHECK-NOT: call
+
+ // CHECK: call {{.*}} @_Z1fv({{.*}}* sret %[[A]])
+ // CHECK-NOT: call
+ // CHECK: call {{.*}} @_Z1f1A({{.*}}* %[[A]])
+ f(f());
+ // CHECK-NOT: call
+ // CHECK: call void @_ZN1AD1Ev({{.*}}* %[[A]])
+
+ // CHECK: call void @_Z1hv(
+ h();
+
+ // CHECK-NOT: call
+ // CHECK-LABEL: }
+}
+
+// We still pass classes with trivial copy/move constructors and destructors in
+// registers, even if the copy is formally omitted.
+struct B {
+ B(int);
+ int n;
+};
+
+B fB();
+void fB(B);
+
+// CHECK-LABEL: define {{.*}} @_Z1iv(
+void i() {
+ // CHECK: %[[B:.*]] = alloca
+ // CHECK-NOT: alloca
+ // CHECK-NOT: call
+
+ // CHECK: %[[B_N:.*]] = call i32 @_Z2fBv()
+ // CHECK-NOT: call
+ // CHECK: store i32 %[[B_N]],
+ // CHECK-NOT: call
+ // CHECK: %[[B_N:.*]] = load i32
+ // CHECK-NOT: call
+ // CHECK: call void @_Z2fB1B(i32 %[[B_N]])
+ fB(fB());
+
+ // CHECK-LABEL: }
+}
diff --git a/test/CodeGenCXX/cxx1z-decomposition.cpp b/test/CodeGenCXX/cxx1z-decomposition.cpp
new file mode 100644
index 000000000000..b9212006053b
--- /dev/null
+++ b/test/CodeGenCXX/cxx1z-decomposition.cpp
@@ -0,0 +1,118 @@
+// RUN: %clang_cc1 -std=c++1z -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s
+
+namespace std {
+ using size_t = decltype(sizeof(0));
+ template<typename> struct tuple_size;
+ template<size_t, typename> struct tuple_element;
+}
+
+struct Y { int n; };
+struct X { X(); X(Y); X(const X&); ~X(); };
+
+struct A { int a : 13; bool b; };
+
+struct B {};
+template<> struct std::tuple_size<B> { enum { value = 2 }; };
+template<> struct std::tuple_element<0,B> { using type = X; };
+template<> struct std::tuple_element<1,B> { using type = const int&; };
+template<int N> auto get(B) {
+ if constexpr (N == 0)
+ return Y();
+ else
+ return 0.0;
+}
+
+using C = int[2];
+
+typedef int D __attribute__((ext_vector_type(2)));
+
+using E = _Complex int;
+
+template<typename T> T &make();
+
+// CHECK: @_ZDC2a12a2E = global {{.*}} zeroinitializer, align 4
+auto [a1, a2] = make<A>();
+// CHECK: @_ZDC2b12b2E = global {{.*}} zeroinitializer, align 1
+// CHECK: @b1 = global {{.*}}* null, align 8
+// CHECK: @_ZGR2b1_ = internal global {{.*}} zeroinitializer, align 1
+// CHECK: @b2 = global i32* null, align 8
+// CHECK: @_ZGR2b2_ = internal global i32 0, align 4
+auto [b1, b2] = make<B>();
+// CHECK: @_ZDC2c12c2E = global [2 x i32]* null, align 8
+auto &[c1, c2] = make<C>();
+// CHECK: @_ZDC2d12d2E = global <2 x i32> zeroinitializer, align 8
+auto [d1, d2] = make<D>();
+// CHECK: @_ZDC2e12e2E = global { i32, i32 } zeroinitializer, align 4
+auto [e1, e2] = make<E>();
+
+// CHECK: call {{.*}}* @_Z4makeI1AERT_v()
+// CHECK: call {{.*}}memcpy{{.*}}@_ZDC2a12a2E
+
+// CHECK: @_Z4makeI1BERT_v()
+// CHECK: call i32 @_Z3getILi0EEDa1B()
+// CHECK: call void @_ZN1XC1E1Y({{.*}}* @_ZGR2b1_, i32
+// CHECK: call i32 @__cxa_atexit({{.*}}@_ZN1XD1Ev{{.*}}@_ZGR2b1_
+// CHECK: store {{.*}}* @_ZGR2b1_,
+//
+// CHECK: call double @_Z3getILi1EEDa1B()
+// CHECK: fptosi double %{{.*}} to i32
+// CHECK: store i32 %{{.*}}, i32* @_ZGR2b2_
+// CHECK: store i32* @_ZGR2b2_, i32** @b2
+
+// CHECK: call {{.*}}* @_Z4makeIA2_iERT_v()
+// CHECK: store {{.*}}, [2 x i32]** @_ZDC2c12c2E
+
+// CHECK: call {{.*}}* @_Z4makeIDv2_iERT_v()
+// CHECK: store {{.*}}, <2 x i32>* @_ZDC2d12d2E, align 8
+
+// CHECK: call {{.*}}* @_Z4makeICiERT_v()
+// CHECK: store i32 %{{.*}}, i32* getelementptr inbounds ({ i32, i32 }, { i32, i32 }* @_ZDC2e12e2E, i32 0, i32 0)
+// CHECK: store i32 %{{.*}}, i32* getelementptr inbounds ({ i32, i32 }, { i32, i32 }* @_ZDC2e12e2E, i32 0, i32 1)
+
+// CHECK: define i32 @_Z12test_globalsv()
+int test_globals() {
+ return a2 + b2 + c2 + d2 + e2;
+ // CHECK: load i8, i8* getelementptr inbounds (%struct.A, %struct.A* @_ZDC2a12a2E, i32 0, i32 1)
+ //
+ // CHECK: %[[b2:.*]] = load i32*, i32** @b2
+ // CHECK: load i32, i32* %[[b2]]
+ //
+ // CHECK: %[[c1c2:.*]] = load [2 x i32]*, [2 x i32]** @_ZDC2c12c2E
+ // CHECK: %[[c2:.*]] = getelementptr inbounds [2 x i32], [2 x i32]* %[[c1c2]], i64 0, i64 1
+ // CHECK: load i32, i32* %[[c2]]
+ //
+ // CHECK: %[[d1d2:.*]] = load <2 x i32>, <2 x i32>* @_ZDC2d12d2E
+ // CHECK: extractelement <2 x i32> %[[d1d2]], i32 1
+ //
+ // CHECK: load i32, i32* getelementptr inbounds ({ i32, i32 }, { i32, i32 }* @_ZDC2e12e2E, i32 0, i32 1)
+}
+
+// CHECK: define i32 @_Z11test_localsv()
+int test_locals() {
+ auto [b1, b2] = make<B>();
+
+ // CHECK: @_Z4makeI1BERT_v()
+ // CHECK: call i32 @_Z3getILi0EEDa1B()
+ // CHECK: call void @_ZN1XC1E1Y({{.*}}* %[[b1:.*]], i32
+ //
+ // CHECK: call double @_Z3getILi1EEDa1B()
+ // CHECK: %[[cvt:.*]] = fptosi double %{{.*}} to i32
+ // CHECK: store i32 %[[cvt]], i32* %[[b2:.*]],
+ // CHECK: store i32* %[[b2]], i32** %[[b2ref:.*]],
+
+ return b2;
+ // CHECK: %[[b2:.*]] = load i32*, i32** %[[b2ref]]
+ // CHECK: load i32, i32* %[[b2]]
+
+ // CHECK: call {{.*}}@_ZN1XD1Ev({{.*}}%[[b1]])
+}
+
+// CHECK: define void @_Z13test_bitfieldR1A(
+void test_bitfield(A &a) {
+ auto &[a1, a2] = a;
+ a1 = 5;
+ // CHECK: load i16, i16* %[[BITFIELD:.*]],
+ // CHECK: and i16 %{{.*}}, -8192
+ // CHECK: or i16 %{{.*}}, 5
+ // CHECK: store i16 %{{.*}}, i16* %[[BITFIELD]],
+}
diff --git a/test/CodeGenCXX/cxx1z-eval-order.cpp b/test/CodeGenCXX/cxx1z-eval-order.cpp
new file mode 100644
index 000000000000..1106719a4748
--- /dev/null
+++ b/test/CodeGenCXX/cxx1z-eval-order.cpp
@@ -0,0 +1,271 @@
+// RUN: %clang_cc1 -std=c++1z %s -emit-llvm -o - -triple %itanium_abi_triple | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-ITANIUM
+// RUN: %clang_cc1 -std=c++1z %s -emit-llvm -o - -triple i686-windows | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-WINDOWS
+// RUN: %clang_cc1 -std=c++1z %s -emit-llvm -o - -triple x86_64-windows | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-WINDOWS
+
+struct B;
+struct A {
+ A();
+ A(const A&);
+
+ void operator[](B b);
+
+ int a_member_f(B);
+};
+struct B {
+ B();
+ ~B();
+};
+
+struct C {
+ operator int *();
+ A *operator->();
+ void operator->*(A);
+ friend void operator->*(C, B);
+
+ friend void operator<<(C, B);
+ friend void operator>>(C, B);
+ void operator<<(A);
+ void operator>>(A);
+
+ void operator=(A);
+ void operator+=(A);
+ friend void operator+=(C, B);
+
+ void operator,(A);
+ friend void operator,(C, B);
+
+ void operator&&(A);
+ void operator||(A);
+ friend void operator&&(C, B);
+ friend void operator||(C, B);
+};
+
+A make_a();
+A *make_a_ptr();
+int A::*make_mem_ptr_a();
+void (A::*make_mem_fn_ptr_a())();
+B make_b();
+C make_c();
+void side_effect();
+
+void callee(A);
+void (*get_f())(A);
+
+
+// CHECK-LABEL: define {{.*}}@{{.*}}postfix_before_args{{.*}}(
+void postfix_before_args() {
+ // CHECK: call {{.*}}@{{.*}}get_f{{.*}}(
+ // CHECK-ITANIUM: call {{.*}}@_ZN1AC1Ev(
+ // CHECK-WINDOWS: call {{.*}}@"\01??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: call {{.*}}@{{.*}}callee{{.*}}(
+ (side_effect(), callee)(A{});
+// CHECK: }
+}
+
+
+// CHECK-LABEL: define {{.*}}@{{.*}}dot_lhs_before_rhs{{.*}}(
+void dot_lhs_before_rhs() {
+ // CHECK: call {{.*}}@{{.*}}make_a{{.*}}(
+ // CHECK: call {{.*}}@{{.*}}make_b{{.*}}(
+ // CHECK: call {{.*}}@{{.*}}a_member_f{{.*}}(
+ make_a().a_member_f(make_b());
+
+ // CHECK: call {{.*}}@{{.*}}make_a_ptr{{.*}}(
+ // CHECK: call {{.*}}@{{.*}}make_b{{.*}}(
+ // CHECK: call {{.*}}@{{.*}}a_member_f{{.*}}(
+ make_a_ptr()->a_member_f(make_b());
+
+ // CHECK: call {{.*}}@{{.*}}make_c{{.*}}(
+ // CHECK: call {{.*}}@{{.*}}make_b{{.*}}(
+ // CHECK: call {{.*}}@{{.*}}a_member_f{{.*}}(
+ make_c()->a_member_f(make_b());
+// CHECK: }
+}
+
+
+// CHECK-LABEL: define {{.*}}@{{.*}}array_lhs_before_rhs{{.*}}(
+void array_lhs_before_rhs() {
+ int (&get_arr())[10];
+ extern int get_index();
+
+ // CHECK: call {{.*}}@{{.*}}get_arr{{.*}}(
+ // CHECK: call {{.*}}@{{.*}}get_index{{.*}}(
+ get_arr()[get_index()] = 0;
+
+ // CHECK: call {{.*}}@{{.*}}get_index{{.*}}(
+ // CHECK: call {{.*}}@{{.*}}get_arr{{.*}}(
+ get_index()[get_arr()] = 0;
+
+ // CHECK: call {{.*}}@{{.*}}make_a{{.*}}(
+ // CHECK: call {{.*}}@{{.*}}make_b{{.*}}(
+ // CHECK: call
+ make_a()[make_b()];
+
+ // CHECK: call {{.*}}@{{.*}}make_c{{.*}}(
+ // CHECK: call {{.*}}@{{.*}}get_index{{.*}}(
+ // CHECK: call
+ make_c()[get_index()] = 0;
+
+ // CHECK: call {{.*}}@{{.*}}get_index{{.*}}(
+ // CHECK: call {{.*}}@{{.*}}make_c{{.*}}(
+ // CHECK: call
+ get_index()[make_c()] = 0;
+// CHECK: }
+}
+
+
+void *operator new(decltype(sizeof(0)), C);
+
+// CHECK-LABEL: define {{.*}}@{{.*}}alloc_before_init{{.*}}(
+void alloc_before_init() {
+ struct Q { Q(A) {} };
+ // CHECK-ITANIUM: call {{.*}}@_Znw{{.*}}(
+ // CHECK-WINDOWS: call {{.*}}@"\01??2@YAP{{EAX_K|AXI}}@Z"(
+ // CHECK: call {{.*}}@{{.*}}make_a{{.*}}(
+ delete new Q(make_a());
+
+ // CHECK: call {{.*}}@{{.*}}make_c{{.*}}(
+ // CHECK: call {{.*}}@{{.*}}make_a{{.*}}(
+ new (make_c()) Q(make_a());
+// CHECK: }
+}
+
+
+// CHECK-LABEL: define {{.*}}@{{.*}}dotstar_lhs_before_rhs{{.*}}(
+int dotstar_lhs_before_rhs() {
+ // CHECK: call {{.*}}@{{.*}}make_a{{.*}}(
+ // CHECK: call {{.*}}@{{.*}}make_mem_ptr_a{{.*}}(
+ int a = make_a().*make_mem_ptr_a();
+
+ // CHECK: call {{.*}}@{{.*}}make_a_ptr{{.*}}(
+ // CHECK: call {{.*}}@{{.*}}make_mem_ptr_a{{.*}}(
+ int b = make_a_ptr()->*make_mem_ptr_a();
+
+ // CHECK: call {{.*}}@{{.*}}make_c{{.*}}(
+ // CHECK: call {{.*}}@{{.*}}make_a{{.*}}(
+ make_c()->*make_a();
+
+ // FIXME: For MS ABI, the order of destruction of parameters here will not be
+ // reverse construction order (parameters are destroyed left-to-right in the
+ // callee). That sadly seems unavoidable; the rules are not implementable as
+ // specified. If we changed parameter destruction order for these functions
+ // to right-to-left, we could make the destruction order match for all cases
+ // other than indirect calls, but we can't completely avoid the problem.
+ //
+ // CHECK: call {{.*}}@{{.*}}make_c{{.*}}(
+ // CHECK: call {{.*}}@{{.*}}make_b{{.*}}(
+ make_c()->*make_b();
+
+ // CHECK: call {{.*}}@{{.*}}make_a{{.*}}(
+ // CHECK: call {{.*}}@{{.*}}make_mem_fn_ptr_a{{.*}}(
+ // CHECK: call
+ (make_a().*make_mem_fn_ptr_a())();
+
+ // CHECK: call {{.*}}@{{.*}}make_a_ptr{{.*}}(
+ // CHECK: call {{.*}}@{{.*}}make_mem_fn_ptr_a{{.*}}(
+ // CHECK: call
+ (make_a_ptr()->*make_mem_fn_ptr_a())();
+
+ return a + b;
+// CHECK: }
+}
+
+
+// CHECK-LABEL: define {{.*}}@{{.*}}assign_rhs_before_lhs{{.*}}(
+void assign_rhs_before_lhs() {
+ extern int &lhs_ref(), rhs();
+
+ // CHECK: call {{.*}}@{{.*}}rhs{{.*}}(
+ // CHECK: call {{.*}}@{{.*}}lhs_ref{{.*}}(
+ lhs_ref() = rhs();
+
+ // CHECK: call {{.*}}@{{.*}}rhs{{.*}}(
+ // CHECK: call {{.*}}@{{.*}}lhs_ref{{.*}}(
+ lhs_ref() += rhs();
+
+ // CHECK: call {{.*}}@{{.*}}rhs{{.*}}(
+ // CHECK: call {{.*}}@{{.*}}lhs_ref{{.*}}(
+ lhs_ref() %= rhs();
+
+ // CHECK: call {{.*}}@{{.*}}make_a{{.*}}(
+ // CHECK: call {{.*}}@{{.*}}make_c{{.*}}(
+ make_c() = make_a();
+
+ // CHECK: call {{.*}}@{{.*}}make_a{{.*}}(
+ // CHECK: call {{.*}}@{{.*}}make_c{{.*}}(
+ make_c() += make_a();
+
+ // CHECK: call {{.*}}@{{.*}}make_b{{.*}}(
+ // CHECK: call {{.*}}@{{.*}}make_c{{.*}}(
+ make_c() += make_b();
+// CHECK: }
+}
+
+// CHECK-LABEL: define {{.*}}@{{.*}}shift_lhs_before_rhs{{.*}}(
+void shift_lhs_before_rhs() {
+ extern int lhs(), rhs();
+
+ // CHECK: call {{.*}}@{{.*}}lhs{{.*}}(
+ // CHECK: call {{.*}}@{{.*}}rhs{{.*}}(
+ (void)(lhs() << rhs());
+
+ // CHECK: call {{.*}}@{{.*}}lhs{{.*}}(
+ // CHECK: call {{.*}}@{{.*}}rhs{{.*}}(
+ (void)(lhs() >> rhs());
+
+ // CHECK: call {{.*}}@{{.*}}make_c{{.*}}(
+ // CHECK: call {{.*}}@{{.*}}make_a{{.*}}(
+ make_c() << make_a();
+
+ // CHECK: call {{.*}}@{{.*}}make_c{{.*}}(
+ // CHECK: call {{.*}}@{{.*}}make_a{{.*}}(
+ make_c() >> make_a();
+
+ // FIXME: This is not correct for Windows ABIs, see above.
+ // CHECK: call {{.*}}@{{.*}}make_c{{.*}}(
+ // CHECK: call {{.*}}@{{.*}}make_b{{.*}}(
+ make_c() << make_b();
+
+ // CHECK: call {{.*}}@{{.*}}make_c{{.*}}(
+ // CHECK: call {{.*}}@{{.*}}make_b{{.*}}(
+ make_c() >> make_b();
+// CHECK: }
+}
+
+// CHECK-LABEL: define {{.*}}@{{.*}}comma_lhs_before_rhs{{.*}}(
+void comma_lhs_before_rhs() {
+ // CHECK: call {{.*}}@{{.*}}make_c{{.*}}(
+ // CHECK: call {{.*}}@{{.*}}make_a{{.*}}(
+ make_c() , make_a();
+
+ // FIXME: This is not correct for Windows ABIs, see above.
+ // CHECK: call {{.*}}@{{.*}}make_c{{.*}}(
+ // CHECK: call {{.*}}@{{.*}}make_b{{.*}}(
+ make_c() , make_b();
+}
+
+// CHECK-LABEL: define {{.*}}@{{.*}}andor_lhs_before_rhs{{.*}}(
+void andor_lhs_before_rhs() {
+ // CHECK: call {{.*}}@{{.*}}make_c{{.*}}(
+ // CHECK: call {{.*}}@{{.*}}make_a{{.*}}(
+ make_c() && make_a();
+
+ // CHECK: call {{.*}}@{{.*}}make_c{{.*}}(
+ // CHECK: call {{.*}}@{{.*}}make_a{{.*}}(
+ make_c() || make_a();
+
+ // FIXME: This is not correct for Windows ABIs, see above.
+ // CHECK: call {{.*}}@{{.*}}make_c{{.*}}(
+ // CHECK: call {{.*}}@{{.*}}make_b{{.*}}(
+ make_c() && make_b();
+
+ // CHECK: call {{.*}}@{{.*}}make_c{{.*}}(
+ // CHECK: call {{.*}}@{{.*}}make_b{{.*}}(
+ make_c() || make_b();
+}
diff --git a/test/CodeGenCXX/cxx1z-noexcept-function-type.cpp b/test/CodeGenCXX/cxx1z-noexcept-function-type.cpp
new file mode 100644
index 000000000000..d2d06fbd2654
--- /dev/null
+++ b/test/CodeGenCXX/cxx1z-noexcept-function-type.cpp
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -fexceptions -fcxx-exceptions -std=c++1z -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s
+
+// CHECK-LABEL: define {{.*}} @_Z11builtin_newm(
+// CHECK: call {{.*}} @_Znwm(
+void *builtin_new(unsigned long n) { return __builtin_operator_new(n); }
+
+// CHECK-LABEL: define {{.*}} @_Z14builtin_deletePv(
+// CHECK: call {{.*}} @_ZdlPv(
+void builtin_delete(void *p) { return __builtin_operator_delete(p); }
diff --git a/test/CodeGenCXX/debug-info-access.cpp b/test/CodeGenCXX/debug-info-access.cpp
index 41b7f71fcecb..82f29ea4d38a 100644
--- a/test/CodeGenCXX/debug-info-access.cpp
+++ b/test/CodeGenCXX/debug-info-access.cpp
@@ -39,6 +39,6 @@ private:
// CHECK-SAME: flags: DIFlagPrototyped,
void free() {}
+U u;
A a;
B b;
-U u;
diff --git a/test/CodeGenCXX/debug-info-alias.cpp b/test/CodeGenCXX/debug-info-alias.cpp
index 90476439e782..8c3f8447de69 100644
--- a/test/CodeGenCXX/debug-info-alias.cpp
+++ b/test/CodeGenCXX/debug-info-alias.cpp
@@ -14,8 +14,6 @@ bar
}
// CHECK: !DIGlobalVariable(name: "bi",{{.*}} type: [[BINT:![0-9]+]]
-// CHECK: [[BINT]] = !DIDerivedType(tag: DW_TAG_typedef, name: "bar<int>"
-// CHECK-SAME: line: 42,
x::bar<int> bi;
// CHECK: !DIGlobalVariable(name: "bf",{{.*}} type: [[BFLOAT:![0-9]+]]
// CHECK: [[BFLOAT]] = !DIDerivedType(tag: DW_TAG_typedef, name: "bar<float>"
@@ -37,3 +35,6 @@ tv<int> *tvp;
using v = void;
// CHECK: !DIDerivedType(tag: DW_TAG_typedef, name: "v"
v *vp;
+
+// CHECK: [[BINT]] = !DIDerivedType(tag: DW_TAG_typedef, name: "bar<int>"
+// CHECK-SAME: line: 42,
diff --git a/test/CodeGenCXX/debug-info-anon-namespace.cpp b/test/CodeGenCXX/debug-info-anon-namespace.cpp
index 4e3e08af2b74..79298deaf8b1 100644
--- a/test/CodeGenCXX/debug-info-anon-namespace.cpp
+++ b/test/CodeGenCXX/debug-info-anon-namespace.cpp
@@ -19,8 +19,9 @@ int *b2 = &a2;
// PS4: [[NS:![0-9]+]] = !DINamespace
+// PS4: [[CU:![0-9]+]] = distinct !DICompileUnit
// PS4: [[NS2:![0-9]+]] = !DINamespace
-// PS4: !DIImportedEntity(tag: DW_TAG_imported_module, scope: !0, entity: [[NS]])
+// PS4: !DIImportedEntity(tag: DW_TAG_imported_module, scope: [[CU]], entity: [[NS]])
// PS4: !DIImportedEntity(tag: DW_TAG_imported_module, scope: [[NS]], entity: [[NS2]], line: {{[0-9]+}})
// NON-PS4-NOT: !DIImportedEntity
diff --git a/test/CodeGenCXX/debug-info-anon-union-vars.cpp b/test/CodeGenCXX/debug-info-anon-union-vars.cpp
index b844d429447b..61b3c7c0526c 100644
--- a/test/CodeGenCXX/debug-info-anon-union-vars.cpp
+++ b/test/CodeGenCXX/debug-info-anon-union-vars.cpp
@@ -45,8 +45,8 @@ void instantiate(int x) {
}
// CHECK: !DIGlobalVariable(name: "c",{{.*}} file: [[FILE:.*]], line: 6,{{.*}} isLocal: true, isDefinition: true
-// CHECK: [[FILE]] = !DIFile(filename: "{{.*}}debug-info-anon-union-vars.cpp",
// CHECK: !DIGlobalVariable(name: "d",{{.*}} file: [[FILE]], line: 6,{{.*}} isLocal: true, isDefinition: true
+// CHECK: [[FILE]] = !DIFile(filename: "{{.*}}debug-info-anon-union-vars.cpp",
// CHECK: !DIGlobalVariable(name: "a",{{.*}} file: [[FILE]], line: 6,{{.*}} isLocal: true, isDefinition: true
// CHECK: !DIGlobalVariable(name: "b",{{.*}} file: [[FILE]], line: 6,{{.*}} isLocal: true, isDefinition: true
// CHECK: !DIGlobalVariable(name: "result", {{.*}} isLocal: false, isDefinition: true
diff --git a/test/CodeGenCXX/debug-info-calling-conventions.cpp b/test/CodeGenCXX/debug-info-calling-conventions.cpp
index 51d801e35ef6..db7fbd23405d 100644
--- a/test/CodeGenCXX/debug-info-calling-conventions.cpp
+++ b/test/CodeGenCXX/debug-info-calling-conventions.cpp
@@ -8,7 +8,7 @@ void A::thiscallcc() {}
// CHECK: !DISubprogram(name: "thiscallcc", {{.*}} type: ![[thiscallty:[^,]*]], {{.*}})
// CHECK: ![[thiscallty]] = !DISubroutineType(cc: DW_CC_BORLAND_thiscall, types: ![[thisargs:[^,)]*]])
// CHECK: ![[thisargs]] = !{null, ![[thisptrty:[^,}]*]]}
-// CHECK: ![[thisptrty]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !{{.*}}, size: 32, align: 32, flags: DIFlagArtificial | DIFlagObjectPointer)
+// CHECK: ![[thisptrty]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !{{.*}}, size: 32, flags: DIFlagArtificial | DIFlagObjectPointer)
void cdeclcc() {}
void __fastcall fastcallcc() {}
diff --git a/test/CodeGenCXX/debug-info-class-nolimit.cpp b/test/CodeGenCXX/debug-info-class-nolimit.cpp
index ce47f9fa495a..0b3b38dd17b1 100644
--- a/test/CodeGenCXX/debug-info-class-nolimit.cpp
+++ b/test/CodeGenCXX/debug-info-class-nolimit.cpp
@@ -1,8 +1,26 @@
-// RUN: %clang_cc1 -triple x86_64-unk-unk -debug-info-kind=standalone -o - -emit-llvm %s | FileCheck %s
-// On Darwin, "full" debug info is the default, so really these tests are
-// identical, as cc1 no longer chooses the effective value of DebugInfoKind.
// 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
+// assertion in CodeView emission on Windows with some dllexport stuff, but it's
+// more general than that.
+
+struct UnicodeString;
+UnicodeString *force_fwd_decl;
+struct UnicodeString {
+private:
+ virtual ~UnicodeString();
+};
+struct UseCompleteType {
+ UseCompleteType();
+ ~UseCompleteType();
+ UnicodeString currencySpcAfterSym[1];
+};
+UseCompleteType require_complete;
+// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "UnicodeString"
+// CHECK-NOT: DIFlagFwdDecl
+// CHECK-SAME: ){{$}}
+
namespace rdar14101097_1 { // see also PR16214
// Check that we emit debug info for the definition of a struct if the
// definition is available, even if it's used via a pointer wrapped in a
diff --git a/test/CodeGenCXX/debug-info-class.cpp b/test/CodeGenCXX/debug-info-class.cpp
index d03c0845dd6b..d572eef68abf 100644
--- a/test/CodeGenCXX/debug-info-class.cpp
+++ b/test/CodeGenCXX/debug-info-class.cpp
@@ -122,6 +122,7 @@ int main(int argc, char **argv) {
// CHECK: [[C_DTOR]] = !DISubprogram(name: "~C"
// CHECK: [[D:![0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "D"
+// CHECK-NOT: size:
// CHECK-SAME: DIFlagFwdDecl
// CHECK-SAME: identifier: "_ZTS1D"
// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "E"
diff --git a/test/CodeGenCXX/debug-info-codeview-injected-class.cpp b/test/CodeGenCXX/debug-info-codeview-injected-class.cpp
new file mode 100644
index 000000000000..b421b2bf8bd9
--- /dev/null
+++ b/test/CodeGenCXX/debug-info-codeview-injected-class.cpp
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 %s -std=c++11 -triple=i686-pc-windows-msvc -debug-info-kind=limited -gcodeview -emit-llvm -o - | FileCheck %s
+
+// The injected class names in this test were accidentally making it into our
+// nested class record debug info. Make sure they don't appear there.
+
+// PR28790
+
+struct A {
+ const char *m_fn1();
+ template <typename> class B;
+ template <typename> class C;
+ template <typename FunctionIdT> class C<B<FunctionIdT>>;
+};
+const char *A::m_fn1() { return nullptr; }
+
+// CHECK: ![[A:[^ ]*]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "A",
+// CHECK-SAME: elements: ![[elements:[0-9]+]]
+
+// CHECK: ![[elements]] = !{![[m_fn1:[0-9]+]]}
+
+// CHECK: ![[m_fn1]] = !DISubprogram(name: "m_fn1",
diff --git a/test/CodeGenCXX/debug-info-cxx1y.cpp b/test/CodeGenCXX/debug-info-cxx1y.cpp
index 36b3e09180c6..403424e2d6a8 100644
--- a/test/CodeGenCXX/debug-info-cxx1y.cpp
+++ b/test/CodeGenCXX/debug-info-cxx1y.cpp
@@ -3,9 +3,6 @@
// CHECK: imports: [[IMPS:![0-9]*]]
// CHECK: [[EMPTY:![0-9]*]] = !{}
-// CHECK: [[FOO:![0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "foo",
-// CHECK-SAME: elements: [[EMPTY]]
-
// CHECK: [[IMPS]] = !{[[IMP:![0-9]*]]}
// CHECK: [[IMP]] = !DIImportedEntity(
// CHECK-SAME: entity: [[F3:![0-9]*]]
@@ -15,6 +12,9 @@
// CHECK: [[TYPE_LIST]] = !{[[INT:![0-9]*]]}
// CHECK: [[INT]] = !DIBasicType(name: "int"
+// CHECK: [[FOO:![0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "foo",
+// CHECK-SAME: elements: [[EMPTY]]
+
// FIXME: The context of this definition should be the CU/file scope, not the class.
// CHECK: !DISubprogram(name: "func", {{.*}} scope: [[FOO]]
// CHECK-SAME: type: [[SUBROUTINE_TYPE]]
diff --git a/test/CodeGenCXX/debug-info-dllimport-base-class.cpp b/test/CodeGenCXX/debug-info-dllimport-base-class.cpp
new file mode 100644
index 000000000000..855ecaaa4c90
--- /dev/null
+++ b/test/CodeGenCXX/debug-info-dllimport-base-class.cpp
@@ -0,0 +1,53 @@
+// RUN: %clang_cc1 -triple i386-pc-windows -emit-llvm -gcodeview -debug-info-kind=limited -fms-compatibility %s -x c++ -o - | FileCheck %s
+
+// Ensure we emit debug info for the full definition of base classes that will
+// be imported from a DLL. Otherwise, the debugger wouldn't be able to show the
+// members.
+
+// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "ImportedAfterCompletion",
+// CHECK-NOT: DIFlagFwdDecl
+// CHECK-SAME: ){{$}}
+
+// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "OutOfLineCtor",
+// CHECK-SAME: DIFlagFwdDecl
+// CHECK-SAME: ){{$}}
+
+// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "ImportedBase",
+// CHECK-NOT: DIFlagFwdDecl
+// CHECK-SAME: ){{$}}
+
+// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "ImportedMethod",
+// CHECK-NOT: DIFlagFwdDecl
+// CHECK-SAME: ){{$}}
+
+
+struct ImportedAfterCompletion;
+ImportedAfterCompletion *force_fwd_decl;
+struct __declspec(dllimport) ImportedAfterCompletion {
+ virtual ~ImportedAfterCompletion();
+};
+
+struct OutOfLineCtor {
+ OutOfLineCtor();
+ virtual void Foo();
+};
+
+struct __declspec(dllimport) ImportedBase {
+ ImportedBase();
+ virtual void Foo();
+};
+
+struct DerivedFromImported : public ImportedBase {};
+
+struct ImportedMethod {
+ ImportedMethod();
+ virtual void Foo();
+ static void __declspec(dllimport) create();
+};
+
+int main() {
+ ImportedAfterCompletion c;
+ OutOfLineCtor o;
+ DerivedFromImported d;
+ ImportedMethod m;
+}
diff --git a/test/CodeGenCXX/debug-info-dup-fwd-decl.cpp b/test/CodeGenCXX/debug-info-dup-fwd-decl.cpp
index f7a2cfe7bae6..3b23ebf7dedc 100644
--- a/test/CodeGenCXX/debug-info-dup-fwd-decl.cpp
+++ b/test/CodeGenCXX/debug-info-dup-fwd-decl.cpp
@@ -19,6 +19,6 @@ protected:
Test t;
-// CHECK: !DIDerivedType(tag: DW_TAG_pointer_type
// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "data"
+// CHECK: !DIDerivedType(tag: DW_TAG_pointer_type
// CHECK-NOT: !DICompositeType(tag: DW_TAG_structure_type, name: "data"
diff --git a/test/CodeGenCXX/debug-info-enum-class.cpp b/test/CodeGenCXX/debug-info-enum-class.cpp
index 44daf412d3ac..b615d5b09626 100644
--- a/test/CodeGenCXX/debug-info-enum-class.cpp
+++ b/test/CodeGenCXX/debug-info-enum-class.cpp
@@ -13,7 +13,7 @@ D d;
// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "A"
// CHECK-SAME: line: 3
// CHECK-SAME: baseType: ![[INT:[0-9]+]]
-// CHECK-SAME: size: 32, align: 32
+// CHECK-SAME: size: 32
// CHECK-NOT: offset:
// CHECK-NOT: flags:
// CHECK-SAME: ){{$}}
@@ -21,7 +21,7 @@ D d;
// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "B"
// CHECK-SAME: line: 4
// CHECK-SAME: baseType: ![[ULONG:[0-9]+]]
-// CHECK-SAME: size: 64, align: 64
+// CHECK-SAME: size: 64
// CHECK-NOT: offset:
// CHECK-NOT: flags:
// CHECK-SAME: ){{$}}
@@ -29,7 +29,7 @@ D d;
// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "C"
// CHECK-SAME: line: 5
// CHECK-NOT: baseType:
-// CHECK-SAME: size: 32, align: 32
+// CHECK-SAME: size: 32
// CHECK-NOT: offset:
// CHECK-NOT: flags:
// CHECK-SAME: ){{$}}
@@ -91,7 +91,7 @@ void f2(E) {
// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "D"
// CHECK-SAME: line: 6
-// CHECK-SAME: size: 16, align: 16
+// CHECK-SAME: size: 16
// CHECK-NOT: offset:
// CHECK-SAME: flags: DIFlagFwdDecl
diff --git a/test/CodeGenCXX/debug-info-flex-member.cpp b/test/CodeGenCXX/debug-info-flex-member.cpp
deleted file mode 100644
index 8dcdaeb935d0..000000000000
--- a/test/CodeGenCXX/debug-info-flex-member.cpp
+++ /dev/null
@@ -1,9 +0,0 @@
-// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -triple x86_64-apple-darwin %s -o - | FileCheck %s
-
-// CHECK: !DISubrange(count: -1)
-
-struct StructName {
- int member[];
-};
-
-struct StructName SN;
diff --git a/test/CodeGenCXX/debug-info-global.cpp b/test/CodeGenCXX/debug-info-global.cpp
index 795602380d20..5abc050431d1 100644
--- a/test/CodeGenCXX/debug-info-global.cpp
+++ b/test/CodeGenCXX/debug-info-global.cpp
@@ -15,7 +15,8 @@ int f1() {
// CHECK: [[GLOBALS]] = !{[[CNST:![0-9]*]]}
-// CHECK: [[CNST]] = distinct !DIGlobalVariable(name: "cnst",
-// CHECK-SAME: scope: [[NS:![0-9]*]]
+// CHECK: [[CNST]] = !DIGlobalVariableExpression(var: [[CNSTV:.*]], expr:
+// CHECK: [[CNSTV]] = distinct !DIGlobalVariable(name: "cnst",
+// CHECK-SAME: scope: [[NS:![0-9]*]]
// CHECK: [[NS]] = !DINamespace(name: "ns"
diff --git a/test/CodeGenCXX/debug-info-indirect-field-decl.cpp b/test/CodeGenCXX/debug-info-indirect-field-decl.cpp
index 70b233cac4dc..126e1f6bd1b8 100644
--- a/test/CodeGenCXX/debug-info-indirect-field-decl.cpp
+++ b/test/CodeGenCXX/debug-info-indirect-field-decl.cpp
@@ -11,13 +11,13 @@ struct Bar {
// CHECK: !DIDerivedType(tag: DW_TAG_member, scope:
// CHECK-SAME: line: [[@LINE+4]]
// CHECK-SAME: baseType: ![[UNION:[0-9]+]]
- // CHECK-SAME: size: 32, align: 32, offset: 32
+ // CHECK-SAME: size: 32, offset: 32
// CHECK: ![[UNION]] = distinct !DICompositeType(tag: DW_TAG_union_type,{{.*}} identifier: "_ZTSN3BarUt_E")
union {
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "i2",
// CHECK-SAME: line: [[@LINE+5]]
// CHECK-SAME: baseType: ![[INT]]
- // CHECK-SAME: size: 32, align: 32
+ // CHECK-SAME: size: 32
// CHECK-NOT: offset:
// CHECK-SAME: ){{$}}
int i2;
diff --git a/test/CodeGenCXX/debug-info-line-if.cpp b/test/CodeGenCXX/debug-info-line-if.cpp
index b3f9c32e0911..41770b135619 100644
--- a/test/CodeGenCXX/debug-info-line-if.cpp
+++ b/test/CodeGenCXX/debug-info-line-if.cpp
@@ -53,15 +53,19 @@ int main() {
// CHECK-DAG: [[DBG3]] = !DILocation(line: 300, scope: !{{.*}})
// CHECK-DAG: [[DBG4]] = !DILocation(line: 401, scope: !{{.*}})
- // CHECK-DAG: [[L1]] = distinct !{[[L1]], [[LDBG1:![0-9]*]]}
- // CHECK-DAG: [[LDBG1]] = !DILocation(line: 100, scope: !{{.*}})
+ // CHECK-DAG: [[L1]] = distinct !{[[L1]], [[SLDBG1:![0-9]*]], [[ELDBG1:![0-9]*]]}
+ // CHECK-DAG: [[SLDBG1]] = !DILocation(line: 100, scope: !{{.*}})
+ // CHECK-DAG: [[ELDBG1]] = !DILocation(line: 104, scope: !{{.*}})
- // CHECK-DAG: [[L2]] = distinct !{[[L2]], [[LDBG2:![0-9]*]]}
- // CHECK-DAG: [[LDBG2]] = !DILocation(line: 200, scope: !{{.*}})
+ // CHECK-DAG: [[L2]] = distinct !{[[L2]], [[SLDBG2:![0-9]*]], [[ELDBG2:![0-9]*]]}
+ // CHECK-DAG: [[SLDBG2]] = !DILocation(line: 200, scope: !{{.*}})
+ // CHECK-DAG: [[ELDBG2]] = !DILocation(line: 204, scope: !{{.*}})
- // CHECK-DAG: [[L3]] = distinct !{[[L3]], [[LDBG3:![0-9]*]]}
- // CHECK-DAG: [[LDBG3]] = !DILocation(line: 300, scope: !{{.*}})
+ // CHECK-DAG: [[L3]] = distinct !{[[L3]], [[SLDBG3:![0-9]*]], [[ELDBG3:![0-9]*]]}
+ // CHECK-DAG: [[SLDBG3]] = !DILocation(line: 300, scope: !{{.*}})
+ // CHECK-DAG: [[ELDBG3]] = !DILocation(line: 304, scope: !{{.*}})
- // CHECK-DAG: [[L4]] = distinct !{[[L4]], [[LDBG4:![0-9]*]]}
- // CHECK-DAG: [[LDBG4]] = !DILocation(line: 401, scope: !{{.*}})
+ // CHECK-DAG: [[L4]] = distinct !{[[L4]], [[SLDBG4:![0-9]*]], [[ELDBG4:![0-9]*]]}
+ // CHECK-DAG: [[SLDBG4]] = !DILocation(line: 401, scope: !{{.*}})
+ // CHECK-DAG: [[ELDBG4]] = !DILocation(line: 405, scope: !{{.*}})
}
diff --git a/test/CodeGenCXX/debug-info-line.cpp b/test/CodeGenCXX/debug-info-line.cpp
index 11653040109c..a1c4ef9eea25 100644
--- a/test/CodeGenCXX/debug-info-line.cpp
+++ b/test/CodeGenCXX/debug-info-line.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -w -debug-info-kind=line-tables-only -std=c++11 -fexceptions -fcxx-exceptions -S -emit-llvm %s -o - -triple %itanium_abi_triple | FileCheck %s
-// RUN: %clang_cc1 -w -debug-info-kind=line-tables-only -std=c++11 -fexceptions -fcxx-exceptions -S -emit-llvm %s -o - -triple i686-linux-gnu | FileCheck %s
+// RUN: %clang_cc1 -w -debug-info-kind=line-tables-only -std=c++11 -fexceptions -fcxx-exceptions -S -mllvm -no-discriminators -emit-llvm %s -o - -triple %itanium_abi_triple | FileCheck %s
+// RUN: %clang_cc1 -w -debug-info-kind=line-tables-only -std=c++11 -fexceptions -fcxx-exceptions -S -mllvm -no-discriminators -emit-llvm %s -o - -triple i686-linux-gnu | FileCheck %s
int &src();
int *sink();
diff --git a/test/CodeGenCXX/debug-info-loops.cpp b/test/CodeGenCXX/debug-info-loops.cpp
new file mode 100644
index 000000000000..69948ea0f880
--- /dev/null
+++ b/test/CodeGenCXX/debug-info-loops.cpp
@@ -0,0 +1,49 @@
+// RUN: %clang -g -gcolumn-info -std=c++11 -S -emit-llvm %s -o - | FileCheck %s
+extern int v[2];
+int a = 0, b = 0;
+int main() {
+#line 100
+ for (int x : v) {
+ if (x)
+ ++b;
+ else
+ ++a;
+ }
+
+ // CHECK: br label {{.*}}, !dbg [[DBG1:![0-9]*]], !llvm.loop [[L1:![0-9]*]]
+
+#line 200
+ while (a)
+ if (b)
+ ++b;
+ else
+ ++a;
+ // CHECK: br label {{.*}}, !dbg [[DBG2:![0-9]*]], !llvm.loop [[L2:![0-9]*]]
+
+#line 300
+ for (unsigned i = 0; i < 100; i++) {
+ a++;
+ for (int y : v)
+ ++b;
+ }
+
+ // CHECK: br label {{.*}}, !dbg [[DBG3:![0-9]*]], !llvm.loop [[L3:![0-9]*]]
+ // CHECK: br label {{.*}}, !dbg [[DBG3:![0-9]*]], !llvm.loop [[L4:![0-9]*]]
+
+
+ // CHECK-DAG: [[L1]] = distinct !{[[L1]], [[SLDBG1:![0-9]*]], [[ELDBG1:![0-9]*]]}
+ // CHECK-DAG: [[SLDBG1]] = !DILocation(line: 100, column: 3, scope: !{{.*}})
+ // CHECK-DAG: [[ELDBG1]] = !DILocation(line: 105, column: 3, scope: !{{.*}})
+
+ // CHECK-DAG: [[L2]] = distinct !{[[L2]], [[SLDBG2:![0-9]*]], [[ELDBG2:![0-9]*]]}
+ // CHECK-DAG: [[SLDBG2]] = !DILocation(line: 200, column: 3, scope: !{{.*}})
+ // CHECK-DAG: [[ELDBG2]] = !DILocation(line: 204, column: 9, scope: !{{.*}})
+
+ // CHECK-DAG: [[L3]] = distinct !{[[L3]], [[SLDBG3:![0-9]*]], [[ELDBG3:![0-9]*]]}
+ // CHECK-DAG: [[SLDBG3]] = !DILocation(line: 302, column: 5, scope: !{{.*}})
+ // CHECK-DAG: [[ELDBG3]] = !DILocation(line: 303, column: 9, scope: !{{.*}})
+ //
+ // CHECK-DAG: [[L4]] = distinct !{[[L4]], [[SLDBG4:![0-9]*]], [[ELDBG4:![0-9]*]]}
+ // CHECK-DAG: [[SLDBG4]] = !DILocation(line: 300, column: 3, scope: !{{.*}})
+ // CHECK-DAG: [[ELDBG4]] = !DILocation(line: 304, column: 3, scope: !{{.*}})
+}
diff --git a/test/CodeGenCXX/debug-info-method.cpp b/test/CodeGenCXX/debug-info-method.cpp
index 73d8b928269a..e0f9a284f2cf 100644
--- a/test/CodeGenCXX/debug-info-method.cpp
+++ b/test/CodeGenCXX/debug-info-method.cpp
@@ -1,10 +1,10 @@
// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -std=c++11 -debug-info-kind=limited %s -o - | FileCheck %s
+// CHECK: !DIDerivedType(tag: DW_TAG_ptr_to_member_type
// CHECK: ![[A:[0-9]+]] = distinct !DICompositeType(tag: DW_TAG_class_type, name: "A",{{.*}} identifier: "_ZTS1A")
// CHECK: !DISubprogram(name: "foo", linkageName: "_ZN1A3fooEiS_3$_0"
// CHECK-SAME: DIFlagProtected
// CHECK: ![[THISTYPE:[0-9]+]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[A]]
// CHECK-SAME: DIFlagArtificial
-// CHECK: !DIDerivedType(tag: DW_TAG_ptr_to_member_type
// CHECK: !DIDerivedType(tag: DW_TAG_ptr_to_member_type, baseType: ![[MEMFUNTYPE:[0-9]+]]
// CHECK: ![[MEMFUNTYPE]] = !DISubroutineType({{(cc: DW_CC_BORLAND_thiscall, )?}}types: ![[MEMFUNARGS:[0-9]+]])
// CHECK: ![[MEMFUNARGS]] = {{.*}}, ![[THISTYPE]],
diff --git a/test/CodeGenCXX/debug-info-ms-abi.cpp b/test/CodeGenCXX/debug-info-ms-abi.cpp
index a146ce94176e..1bf8bab5f41c 100644
--- a/test/CodeGenCXX/debug-info-ms-abi.cpp
+++ b/test/CodeGenCXX/debug-info-ms-abi.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -triple=i686-pc-windows-msvc -debug-info-kind=limited -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -triple=i686-pc-windows-msvc -debug-info-kind=limited -gcodeview -emit-llvm -o - | FileCheck %s
// Tests that certain miscellaneous features work in the MS ABI.
@@ -11,20 +11,30 @@ struct Foo {
Foo f;
Foo::Nested n;
+// CHECK: ![[Nested:[0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Nested",
+// CHECK-SAME: identifier: ".?AUNested@Foo@@"
+
// CHECK: ![[Foo:[^ ]*]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Foo",
+// CHECK-SAME: elements: ![[elements:[0-9]+]]
// CHECK-SAME: identifier: ".?AUFoo@@"
-// CHECK: !DISubprogram(name: "f",
+// CHECK: ![[elements]] = !{![[vshape:[0-9]+]], ![[vptr:[0-9]+]], ![[Nested]], ![[f:[0-9]+]], ![[g:[0-9]+]], ![[h:[0-9]+]]}
+
+// CHECK: ![[vshape]] = !DIDerivedType(tag: DW_TAG_pointer_type, name: "__vtbl_ptr_type", baseType: null, size: 96)
+
+// CHECK: ![[vptr]] = !DIDerivedType(tag: DW_TAG_member, name: "_vptr$Foo",
+// CHECK-SAME: baseType: ![[vptr_ty:[0-9]+]],
+
+// CHECK: ![[vptr_ty]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[vshape]], size: 32
+
+// CHECK: ![[f]] = !DISubprogram(name: "f",
// CHECK-SAME: containingType: ![[Foo]], virtuality: DW_VIRTUALITY_virtual, virtualIndex: 0,
// CHECK-SAME: flags: DIFlagPrototyped | DIFlagIntroducedVirtual,
-// CHECK: !DISubprogram(name: "g",
+// CHECK: ![[g]] = !DISubprogram(name: "g",
// CHECK-SAME: containingType: ![[Foo]], virtuality: DW_VIRTUALITY_virtual, virtualIndex: 1,
// CHECK-SAME: flags: DIFlagPrototyped | DIFlagIntroducedVirtual,
-// CHECK: !DISubprogram(name: "h",
+// CHECK: ![[h]] = !DISubprogram(name: "h",
// CHECK-SAME: containingType: ![[Foo]], virtuality: DW_VIRTUALITY_virtual, virtualIndex: 2,
// CHECK-SAME: flags: DIFlagPrototyped | DIFlagIntroducedVirtual,
-
-// CHECK: distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Nested",
-// CHECK-SAME: identifier: ".?AUNested@Foo@@"
diff --git a/test/CodeGenCXX/debug-info-ms-anonymous-tag.cpp b/test/CodeGenCXX/debug-info-ms-anonymous-tag.cpp
index cef1eb8c5a09..5e2cb2190f0d 100644
--- a/test/CodeGenCXX/debug-info-ms-anonymous-tag.cpp
+++ b/test/CodeGenCXX/debug-info-ms-anonymous-tag.cpp
@@ -4,7 +4,6 @@ typedef struct {
} test1;
test1 gv1;
-// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "test1"
struct {
} test2;
@@ -18,3 +17,5 @@ test3 gv3;
void *use_test3 = &gv3;
// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "<unnamed-type-test3>"
+
+// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "test1"
diff --git a/test/CodeGenCXX/debug-info-ms-bitfields.cpp b/test/CodeGenCXX/debug-info-ms-bitfields.cpp
index 07d4c0c6c78a..e42330143bba 100644
--- a/test/CodeGenCXX/debug-info-ms-bitfields.cpp
+++ b/test/CodeGenCXX/debug-info-ms-bitfields.cpp
@@ -7,4 +7,4 @@ struct S {
short x : 8;
} s;
-// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "x", {{.*}}, size: 8, align: 16, offset: 16, flags: DIFlagBitField, extraData: i64 8)
+// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "x", {{.*}}, size: 8, offset: 16, flags: DIFlagBitField, extraData: i64 8)
diff --git a/test/CodeGenCXX/debug-info-ms-ptr-to-member.cpp b/test/CodeGenCXX/debug-info-ms-ptr-to-member.cpp
index 4b9f2a146896..1f4c90484b89 100644
--- a/test/CodeGenCXX/debug-info-ms-ptr-to-member.cpp
+++ b/test/CodeGenCXX/debug-info-ms-ptr-to-member.cpp
@@ -23,7 +23,6 @@ int Incomplete::**ppmd;
void (Incomplete::**ppmf)();
// CHECK: distinct !DIGlobalVariable(name: "pmd_a", {{.*}} type: ![[pmd_a:[^, ]*]], {{.*}})
-// CHECK: ![[pmd_a]] = !DIDerivedType(tag: DW_TAG_ptr_to_member_type, baseType: !{{.*}}, size: 32, flags: DIFlagSingleInheritance, {{.*}})
// CHECK: distinct !DIGlobalVariable(name: "pmd_b", {{.*}} type: ![[pmd_b:[^, ]*]], {{.*}})
// CHECK: ![[pmd_b]] = !DIDerivedType(tag: DW_TAG_ptr_to_member_type, baseType: !{{.*}}, size: 32, flags: DIFlagMultipleInheritance, {{.*}})
// CHECK: distinct !DIGlobalVariable(name: "pmd_c", {{.*}} type: ![[pmd_c:[^, ]*]], {{.*}})
@@ -45,8 +44,10 @@ void (Incomplete::**ppmf)();
// CHECK-SAME: ){{$}}
// CHECK: distinct !DIGlobalVariable(name: "ppmd", {{.*}} type: ![[ppmd:[^, ]*]], {{.*}})
-// CHECK: ![[ppmd]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[ppmd2:[^ ]*]], size: 64, align: 64)
+// CHECK: ![[ppmd]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[ppmd2:[^ ]*]], size: 64)
// CHECK: ![[ppmd2]] = !DIDerivedType(tag: DW_TAG_ptr_to_member_type, baseType: !{{[0-9]*}}, extraData: !{{[0-9]*}}){{$}}
// CHECK: distinct !DIGlobalVariable(name: "ppmf", {{.*}} type: ![[ppmf:[^, ]*]], {{.*}})
-// CHECK: ![[ppmf]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[ppmf2:[^ ]*]], size: 64, align: 64)
+// CHECK: ![[ppmf]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[ppmf2:[^ ]*]], size: 64)
// CHECK: ![[ppmf2]] = !DIDerivedType(tag: DW_TAG_ptr_to_member_type, baseType: !{{[0-9]*}}, extraData: !{{[0-9]*}}){{$}}
+
+// CHECK: ![[pmd_a]] = !DIDerivedType(tag: DW_TAG_ptr_to_member_type, baseType: !{{.*}}, size: 32, flags: DIFlagSingleInheritance, {{.*}})
diff --git a/test/CodeGenCXX/debug-info-ms-vbase.cpp b/test/CodeGenCXX/debug-info-ms-vbase.cpp
new file mode 100644
index 000000000000..3de3a751cba1
--- /dev/null
+++ b/test/CodeGenCXX/debug-info-ms-vbase.cpp
@@ -0,0 +1,68 @@
+// RUN: %clang_cc1 %s -triple=i686-pc-windows-msvc -debug-info-kind=limited -gcodeview -emit-llvm -o - | FileCheck %s
+
+// Tests virtual bases in the MS ABI.
+
+// CHECK: ![[NoPrimaryBase:[0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "NoPrimaryBase",
+// CHECK-SAME: elements: ![[elements:[0-9]+]]
+
+// 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: ![[HasVirtualMethod]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "HasVirtualMethod"
+
+// CHECK: ![[HasPrimaryBase:[0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "HasPrimaryBase",
+// CHECK-SAME: elements: ![[elements:[0-9]+]]
+
+// 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: ![[SecondaryVTable]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "SecondaryVTable"
+
+// CHECK: ![[HasVirtualMethod_base]] = !DIDerivedType(tag: DW_TAG_inheritance, scope: ![[HasPrimaryBase]], baseType: ![[HasVirtualMethod]])
+
+// CHECK: ![[HasIndirectVirtualBase:[0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "HasIndirectVirtualBase"
+// CHECK-SAME: elements: ![[elements:[0-9]+]]
+
+// CHECK: !DIDerivedType(tag: DW_TAG_inheritance, scope: ![[HasIndirectVirtualBase]], baseType: ![[HasPrimaryBase]]
+// CHECK-NOT: DIFlagIndirectVirtualBase
+// CHECK-SAME: )
+
+// CHECK: !DIDerivedType(tag: DW_TAG_inheritance, scope: ![[HasIndirectVirtualBase]], baseType: ![[SecondaryVTable]]
+// CHECK-SAME: flags:
+// CHECK-SAME: DIFlagIndirectVirtualBase
+
+// CHECK: ![[DynamicNoVFPtr:[0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "DynamicNoVFPtr",
+// CHECK-SAME: elements: ![[elements:[0-9]+]]
+
+// 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: ![[POD]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "POD"
+
+struct POD { int pod; };
+
+struct DynamicNoVFPtr : virtual POD { };
+
+DynamicNoVFPtr dynamic_no_vfptr;
+
+struct HasVirtualMethod { virtual void f(); };
+
+struct NoPrimaryBase : virtual HasVirtualMethod { };
+
+NoPrimaryBase no_primary_base;
+
+struct SecondaryVTable { virtual void g(); };
+
+struct HasPrimaryBase : virtual SecondaryVTable, HasVirtualMethod { };
+
+HasPrimaryBase has_primary_base;
+
+struct HasIndirectVirtualBase : public HasPrimaryBase {};
+
+HasIndirectVirtualBase has_indirect_virtual_base;
diff --git a/test/CodeGenCXX/debug-info-namespace.cpp b/test/CodeGenCXX/debug-info-namespace.cpp
index 060a5cea636c..c75c40766a37 100644
--- a/test/CodeGenCXX/debug-info-namespace.cpp
+++ b/test/CodeGenCXX/debug-info-namespace.cpp
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 -debug-info-kind=limited -S -emit-llvm %s -o - | FileCheck %s
-// RUN: %clang_cc1 -debug-info-kind=line-tables-only -S -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-GMLT %s
-// RUN: %clang_cc1 -debug-info-kind=standalone -S -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-NOLIMIT %s
+// RUN: %clang_cc1 -std=c++11 -debug-info-kind=limited -S -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -std=c++11 -debug-info-kind=line-tables-only -S -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-GMLT %s
+// RUN: %clang_cc1 -std=c++11 -debug-info-kind=standalone -S -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-NOLIMIT %s
namespace A {
#line 1 "foo.cpp"
@@ -49,14 +49,15 @@ using B::i;
namespace B {
int var_fwd = i;
}
+inline namespace I {
+int var_i;
+}
}
void B::func_fwd() {}
// This should work even if 'i' and 'func' were declarations & not definitions,
// but it doesn't yet.
-// CHECK: [[CU:![0-9]+]] = distinct !DICompileUnit(
-// CHECK-SAME: imports: [[MODULES:![0-9]*]]
// CHECK: [[I:![0-9]+]] = distinct !DIGlobalVariable(name: "i",{{.*}} scope: [[NS:![0-9]+]],
// CHECK: [[NS]] = !DINamespace(name: "B", scope: [[CTXT:![0-9]+]], file: [[FOOCPP:![0-9]+]], line: 1)
// CHECK: [[FOOCPP]] = !DIFile(filename: "foo.cpp"
@@ -65,6 +66,10 @@ void B::func_fwd() {}
// CHECK: [[VAR_FWD:![0-9]+]] = distinct !DIGlobalVariable(name: "var_fwd",{{.*}} scope: [[NS]],
// CHECK-SAME: line: 44
// CHECK-SAME: isDefinition: true
+// CHECK: distinct !DIGlobalVariable(name: "var_i",{{.*}} scope: [[INLINE:![0-9]+]],
+// CHECK: [[INLINE]] = !DINamespace(name: "I", scope: [[CTXT]], file: [[FOOCPP]], line: 46, exportSymbols: true)
+// CHECK: [[CU:![0-9]+]] = distinct !DICompileUnit(
+// CHECK-SAME: imports: [[MODULES:![0-9]*]]
// CHECK: [[MODULES]] = !{[[M1:![0-9]+]], [[M2:![0-9]+]], [[M3:![0-9]+]], [[M4:![0-9]+]], [[M5:![0-9]+]], [[M6:![0-9]+]], [[M7:![0-9]+]], [[M8:![0-9]+]], [[M9:![0-9]+]], [[M10:![0-9]+]], [[M11:![0-9]+]], [[M12:![0-9]+]], [[M13:![0-9]+]], [[M14:![0-9]+]], [[M15:![0-9]+]], [[M16:![0-9]+]], [[M17:![0-9]+]]}
// CHECK: [[M1]] = !DIImportedEntity(tag: DW_TAG_imported_module, scope: [[CTXT]], entity: [[NS]], line: 15)
@@ -101,7 +106,7 @@ void B::func_fwd() {}
// CHECK-SAME: scope: [[NS]], file: [[FOOCPP]], line: 9
// CHECK: [[M15]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[VAR_FWD:![0-9]+]]
// CHECK: [[M16]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[FUNC_FWD:![0-9]+]]
-// CHECK: [[FUNC_FWD]] = distinct !DISubprogram(name: "func_fwd",{{.*}} line: 47,{{.*}} isDefinition: true
+// CHECK: [[FUNC_FWD]] = distinct !DISubprogram(name: "func_fwd",{{.*}} line: 50,{{.*}} isDefinition: true
// CHECK: [[M17]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[CTXT]], entity: [[I]]
// CHECK-GMLT: [[CU:![0-9]+]] = distinct !DICompileUnit(
diff --git a/test/CodeGenCXX/debug-info-rvalue-ref.cpp b/test/CodeGenCXX/debug-info-rvalue-ref.cpp
index edb93ae46cda..de0f65ad9a02 100644
--- a/test/CodeGenCXX/debug-info-rvalue-ref.cpp
+++ b/test/CodeGenCXX/debug-info-rvalue-ref.cpp
@@ -8,5 +8,5 @@ void foo (int &&i)
printf("%d\n", i);
}
-// CHECK: !DIDerivedType(tag: DW_TAG_rvalue_reference_type, baseType: ![[INT:[0-9]+]], size: 64, align: 64)
+// CHECK: !DIDerivedType(tag: DW_TAG_rvalue_reference_type, baseType: ![[INT:[0-9]+]], size: 64)
// CHECK: ![[INT]] = !DIBasicType(name: "int"
diff --git a/test/CodeGenCXX/debug-info-static-member.cpp b/test/CodeGenCXX/debug-info-static-member.cpp
index ed8ae015cfc3..c777ccb2aba2 100644
--- a/test/CodeGenCXX/debug-info-static-member.cpp
+++ b/test/CodeGenCXX/debug-info-static-member.cpp
@@ -3,6 +3,10 @@
// 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]+]]
+
enum X {
Y
};
@@ -28,6 +32,10 @@ public:
// why the definition of "a" comes before the declarations while
// "b" and "c" come after.
+// CHECK: [[A]] = !DIGlobalVariableExpression(var: [[AV:.*]])
+// CHECK: [[AV]] = distinct !DIGlobalVariable(name: "a",
+// CHECK-SAME: declaration: ![[DECL_A:[0-9]+]])
+//
// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "X"{{.*}}, identifier: "_ZTS1X")
// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "anon_static_decl_struct"
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "anon_static_decl_var"
@@ -36,16 +44,24 @@ public:
// CHECK-SAME: ){{$}}
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "static_decl_templ_var"
-// CHECK: !DIGlobalVariable(name: "a", {{.*}}variable: i32* @_ZN1C1aE, declaration: ![[DECL_A:[0-9]+]])
int C::a = 4;
-// CHECK: ![[DECL_A]] = !DIDerivedType(tag: DW_TAG_member, name: "a"
+// CHECK: [[B]] = !DIGlobalVariableExpression(var: [[BV:.*]])
+// CHECK: [[BV]] = distinct !DIGlobalVariable(name: "b",
+// CHECK-SAME: declaration: ![[DECL_B:[0-9]+]])
+// CHECK: ![[DECL_B]] = !DIDerivedType(tag: DW_TAG_member, name: "b"
// CHECK-NOT: size:
// CHECK-NOT: align:
// CHECK-NOT: offset:
-// CHECK-SAME: flags: DIFlagStaticMember)
+// CHECK-SAME: flags: DIFlagProtected | DIFlagStaticMember)
//
// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "C"{{.*}}, identifier: "_ZTS1C")
//
+// CHECK: ![[DECL_A]] = !DIDerivedType(tag: DW_TAG_member, name: "a"
+// CHECK-NOT: size:
+// CHECK-NOT: align:
+// CHECK-NOT: offset:
+// CHECK-SAME: flags: DIFlagStaticMember)
+//
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "const_a"
// CHECK-NOT: size:
// CHECK-NOT: align:
@@ -53,12 +69,6 @@ int C::a = 4;
// CHECK-SAME: flags: DIFlagStaticMember,
// CHECK-SAME: extraData: i1 true)
-// CHECK: ![[DECL_B:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "b"
-// CHECK-NOT: size:
-// CHECK-NOT: align:
-// CHECK-NOT: offset:
-// CHECK-SAME: flags: DIFlagProtected | DIFlagStaticMember)
-//
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "const_b"
// CHECK-NOT: size:
// CHECK-NOT: align:
@@ -82,9 +92,9 @@ int C::a = 4;
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "x_a"
// CHECK-SAME: flags: DIFlagPublic | DIFlagStaticMember)
-// CHECK: !DIGlobalVariable(name: "b", {{.*}}variable: i32* @_ZN1C1bE, declaration: ![[DECL_B]])
int C::b = 2;
-// CHECK: !DIGlobalVariable(name: "c", {{.*}}variable: i32* @_ZN1C1cE, declaration: ![[DECL_C]])
+// CHECK: [[C]] = !DIGlobalVariableExpression(var: [[CV:.*]])
+// CHECK: [[CV]] = distinct !DIGlobalVariable(name: "c", {{.*}} declaration: ![[DECL_C]])
int C::c = 1;
int main()
diff --git a/test/CodeGenCXX/debug-info-template-explicit-specialization.cpp b/test/CodeGenCXX/debug-info-template-explicit-specialization.cpp
index 08146c25263b..c8d8a1de855d 100644
--- a/test/CodeGenCXX/debug-info-template-explicit-specialization.cpp
+++ b/test/CodeGenCXX/debug-info-template-explicit-specialization.cpp
@@ -22,9 +22,6 @@ struct b {
};
extern template class b<int>;
b<int> bi;
-// CHECK: DICompositeType(tag: DW_TAG_structure_type, name: "b<int>"
-// CHECK-NOT: DIFlagFwdDecl
-// CHECK-SAME: ){{$}}
template <typename T>
struct c {
@@ -116,3 +113,7 @@ template <>
struct k<int>;
template struct k<int>;
// CHECK-NOT: !DICompositeType(tag: DW_TAG_structure_type, name: "k<int>"
+
+// CHECK: DICompositeType(tag: DW_TAG_structure_type, name: "b<int>"
+// CHECK-NOT: DIFlagFwdDecl
+// CHECK-SAME: ){{$}}
diff --git a/test/CodeGenCXX/debug-info-template-member.cpp b/test/CodeGenCXX/debug-info-template-member.cpp
index 88f024b59abf..2b840745ffeb 100644
--- a/test/CodeGenCXX/debug-info-template-member.cpp
+++ b/test/CodeGenCXX/debug-info-template-member.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -triple x86_64-apple-darwin %s -o - | FileCheck %s
+// CHECK: @x = global %"struct.outer<foo>::inner" zeroinitializer, align 4, !dbg [[X:![0-9]+]]
+
struct MyClass {
template <int i> int add(int j) {
return i + j;
@@ -17,9 +19,9 @@ inline int add3(int x) {
}
// The compile unit pulls in the global variables first.
-// CHECK: !DIGlobalVariable(name: "x",
-// CHECK-SAME: type: ![[OUTER_FOO_INNER_ID:[0-9]+]]
-// CHECK-SAME: variable: %"struct.outer<foo>::inner"* @x
+// CHECK: [[X]] = !DIGlobalVariableExpression(var: [[XV:.*]])
+// CHECK: [[XV]] = distinct !DIGlobalVariable(name: "x",
+// CHECK-SAME: type: ![[OUTER_FOO_INNER_ID:[0-9]+]]
// CHECK: ![[OUTER_FOO_INNER_ID:[0-9]*]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "inner"{{.*}}, identifier:
// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "foo"
@@ -38,7 +40,7 @@ inline int add3(int x) {
// CHECK: [[C_MEM]] = !{[[C_VPTR:![0-9]*]], [[C_FUNC:![0-9]*]]}
// CHECK: [[C_VPTR]] = !DIDerivedType(tag: DW_TAG_member, name: "_vptr$MyClass"
-// CHECK: [[C_FUNC]] = !DISubprogram(name: "func",{{.*}} line: 7,
+// CHECK: [[C_FUNC]] = !DISubprogram(name: "func",{{.*}} line: 9,
// CHECK: !DISubprogram(name: "add<2>"
// CHECK-SAME: scope: [[C]]
diff --git a/test/CodeGenCXX/debug-info-template-quals.cpp b/test/CodeGenCXX/debug-info-template-quals.cpp
index 7a0d0d4a2755..cfee78d97493 100644
--- a/test/CodeGenCXX/debug-info-template-quals.cpp
+++ b/test/CodeGenCXX/debug-info-template-quals.cpp
@@ -17,10 +17,10 @@ void foo (const char *c) {
// CHECK: [[P:![0-9]*]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: [[CON:![0-9]*]]
// CHECK: [[CON]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: [[CH:![0-9]*]]
-// CHECK: [[CH]] = !DIBasicType(name: "char", size: 8, align: 8, encoding: DW_ATE_signed_char)
+// CHECK: [[CH]] = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
// CHECK: [[BS:.*]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "basic_string<char>"
// CHECK-SAME: line: 4
-// CHECK-SAME: size: 8, align: 8
+// CHECK-SAME: size: 8
// CHECK: [[TYPE:![0-9]*]] = !DISubroutineType(types: [[ARGS:.*]])
// CHECK: [[ARGS]] = !{!{{.*}}, !{{.*}}, [[P]], [[R:.*]]}
diff --git a/test/CodeGenCXX/debug-info-template.cpp b/test/CodeGenCXX/debug-info-template.cpp
index d35bb70fa713..54fac0b36eec 100644
--- a/test/CodeGenCXX/debug-info-template.cpp
+++ b/test/CodeGenCXX/debug-info-template.cpp
@@ -1,5 +1,9 @@
// 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: !DICompileUnit(
// CHECK: [[EMPTY:![0-9]*]] = !{}
@@ -18,13 +22,12 @@ struct TC {
};
};
-// CHECK: [[INT:![0-9]+]] = !DIBasicType(name: "int"
int glb;
void func();
-// CHECK: !DIGlobalVariable(name: "tci",
-// CHECK-SAME: type: ![[TCNESTED:[0-9]+]]
-// CHECK-SAME: variable: %"struct.TC<unsigned int, 2, &glb, &foo::e, &foo::f, &foo::g, 1, 2, 3>::nested"* @tci
+// CHECK: [[TCI]] = !DIGlobalVariableExpression(var: [[TCIV:.*]])
+// CHECK: [[TCIV]] = distinct !DIGlobalVariable(name: "tci",
+// CHECK-SAME: type: ![[TCNESTED:[0-9]+]]
// CHECK: ![[TCNESTED]] ={{.*}}!DICompositeType(tag: DW_TAG_structure_type, name: "nested",
// CHECK-SAME: scope: ![[TC:[0-9]+]],
@@ -39,7 +42,8 @@ TC
2,
// CHECK: [[TCARG3]] = !DITemplateValueParameter(name: "x", type: [[CINTPTR:![0-9]*]], value: i32* @glb)
// CHECK: [[CINTPTR]] = !DIDerivedType(tag: DW_TAG_pointer_type, {{.*}}baseType: [[CINT:![0-9]+]]
-// CHECK: [[CINT]] = !DIDerivedType(tag: DW_TAG_const_type, {{.*}}baseType: [[INT]]
+// CHECK: [[CINT]] = !DIDerivedType(tag: DW_TAG_const_type, {{.*}}baseType: [[INT:![0-9]+]]
+// CHECK: [[INT]] = !DIBasicType(name: "int"
&glb,
// CHECK: [[TCARG4]] = !DITemplateValueParameter(name: "a", type: [[MEMINTPTR:![0-9]*]], value: i64 8)
// CHECK: [[MEMINTPTR]] = !DIDerivedType(tag: DW_TAG_ptr_to_member_type, {{.*}}baseType: [[INT]], {{.*}}extraData: ![[FOO:[0-9]+]])
@@ -59,7 +63,7 @@ TC
// CHECK: [[FARG1]] = !DIDerivedType(tag: DW_TAG_pointer_type,
// CHECK-SAME: baseType: ![[FOO]]
// CHECK-NOT: line:
-// CHECK-SAME: size: 64, align: 64
+// CHECK-SAME: size: 64
// CHECK-NOT: offset: 0
// CHECK-SAME: DIFlagArtificial
// CHECK: [[FUNTYPE:![0-9]*]] = !DISubroutineType(types: [[FUNARGS:![0-9]*]])
@@ -80,9 +84,9 @@ TC
// CHECK: [[TCARG7_3]] = !DITemplateValueParameter(type: [[INT]], value: i32 3)
3>::nested tci;
-// CHECK: !DIGlobalVariable(name: "tcn"
-// CHECK-SAME: type: ![[TCNT:[0-9]+]]
-// CHECK-SAME: variable: %struct.TC* @tcn
+// CHECK: [[TCN]] = !DIGlobalVariableExpression(var: [[TCNV:.*]])
+// CHECK: [[TCNV]] = distinct !DIGlobalVariable(name: "tcn"
+// CHECK-SAME: type: ![[TCNT:[0-9]+]]
TC
// CHECK: ![[TCNT]] ={{.*}}!DICompositeType(tag: DW_TAG_structure_type, name: "TC<int, -3, nullptr, nullptr, nullptr, nullptr>"
// CHECK-SAME: templateParams: [[TCNARGS:![0-9]*]]
@@ -121,9 +125,9 @@ template <template <typename> class tmpl, int &lvr, int &&rvr>
struct NN {
};
-// CHECK: !DIGlobalVariable(name: "nn"
-// CHECK-SAME: type: ![[NNT:[0-9]+]]
-// CHECK-SAME: variable: %struct.NN* @nn
+// CHECK: [[NN]] = !DIGlobalVariableExpression(var: [[NNV:.*]])
+// CHECK: [[NNV]] = distinct !DIGlobalVariable(name: "nn"
+// CHECK-SAME: type: ![[NNT:[0-9]+]]
// FIXME: these parameters should probably be rendered as 'glb' rather than
// '&glb', since they're references, not pointers.
@@ -150,7 +154,7 @@ PaddingAtEnd PaddedObj = {};
// CHECK-SAME: templateParams: [[PTOARGS:![0-9]*]]
// CHECK: [[PTOARGS]] = !{[[PTOARG1:![0-9]*]]}
// CHECK: [[PTOARG1]] = !DITemplateValueParameter(type: [[CONST_PADDINGATEND_PTR:![0-9]*]], value: %struct.PaddingAtEnd* @PaddedObj)
-// CHECK: [[CONST_PADDINGATEND_PTR]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[PADDINGATEND]], size: 64, align: 64)
+// CHECK: [[CONST_PADDINGATEND_PTR]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[PADDINGATEND]], size: 64)
template <PaddingAtEnd *>
struct PaddingAtEndTemplate {
};
diff --git a/test/CodeGenCXX/debug-info-thunk-msabi.cpp b/test/CodeGenCXX/debug-info-thunk-msabi.cpp
new file mode 100644
index 000000000000..5c705ac0ac13
--- /dev/null
+++ b/test/CodeGenCXX/debug-info-thunk-msabi.cpp
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 %s -triple i386-pc-windows-msvc19.0.0 -emit-llvm \
+// RUN: -debug-info-kind=line-tables-only -fms-extensions -o - | FileCheck %s
+class __declspec(dllexport) A {
+ A(int * = new int) {}
+};
+// CHECK: define {{.*}}void @"\01??_FA@@AAEXXZ"
+// CHECK-SAME: !dbg ![[SP:[0-9]+]]
+// CHECK-NOT: {{ret }}
+// CHECK: call x86_thiscallcc %class.A* @"\01??0A@@AAE@PAH@Z"
+// CHECK-SAME: !dbg ![[DBG:[0-9]+]]
+// CHECK: ret void, !dbg
+//
+// CHECK: ![[SP]] = distinct !DISubprogram(
+// CHECK-SAME: line: 4
+// CHECK-SAME: isDefinition: true
+// CHECK-SAME: DIFlagArtificial
+// CHECK-SAME: ){{$}}
+//
+// CHECK: ![[DBG]] = !DILocation(line: 0
diff --git a/test/CodeGenCXX/debug-info-thunk.cpp b/test/CodeGenCXX/debug-info-thunk.cpp
index cd00ec937318..f7d16f493256 100644
--- a/test/CodeGenCXX/debug-info-thunk.cpp
+++ b/test/CodeGenCXX/debug-info-thunk.cpp
@@ -13,8 +13,17 @@ struct C : A, B {
};
void C::f() { }
-
-// CHECK: !DISubprogram(linkageName: "_ZThn{{[48]}}_N1C1fEv"
+// 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]]
+//
+// CHECK: ![[SP]] = distinct !DISubprogram(linkageName: "_ZThn{{[48]}}_N1C1fEv"
// CHECK-SAME: line: 15
// CHECK-SAME: isDefinition: true
+// CHECK-SAME: DIFlagArtificial
// CHECK-SAME: ){{$}}
+//
+// CHECK: ![[DBG]] = !DILocation(line: 0
diff --git a/test/CodeGenCXX/debug-info-union.cpp b/test/CodeGenCXX/debug-info-union.cpp
index 19e67418f9dc..cffe6e961cd4 100644
--- a/test/CodeGenCXX/debug-info-union.cpp
+++ b/test/CodeGenCXX/debug-info-union.cpp
@@ -12,7 +12,7 @@ E e;
// CHECK: !DICompositeType(tag: DW_TAG_union_type, name: "E"
// CHECK-SAME: line: 3
-// CHECK-SAME: size: 32, align: 32
+// CHECK-SAME: size: 32
// CHECK-NOT: offset:
// CHECK-SAME: {{$}}
// CHECK: !DISubprogram(name: "bb"{{.*}}, line: 6
diff --git a/test/CodeGenCXX/debug-info-uuid.cpp b/test/CodeGenCXX/debug-info-uuid.cpp
index a304f37078b6..70b205ad0993 100644
--- a/test/CodeGenCXX/debug-info-uuid.cpp
+++ b/test/CodeGenCXX/debug-info-uuid.cpp
@@ -1,6 +1,18 @@
// RUN: %clang_cc1 -emit-llvm -fms-extensions -triple=x86_64-pc-win32 -debug-info-kind=limited %s -o - -std=c++11 | FileCheck %s
// RUN: %clang_cc1 -emit-llvm -fms-extensions -triple=x86_64-unknown-unknown -debug-info-kind=limited %s -o - -std=c++11 2>&1 | FileCheck %s --check-prefix=CHECK-ITANIUM
+// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "tmpl_guid2<__uuidof(uuid)>"
+// CHECK-SAME: templateParams: [[TGI2ARGS:![0-9]*]]
+// CHECK: [[TGI2ARGS]] = !{[[TGI2ARG1:![0-9]*]]}
+// CHECK: [[TGI2ARG1]] = !DITemplateValueParameter(
+// CHECK-SAME: type: [[CONST_GUID_REF:![0-9]*]]
+// CHECK-SAME: value: { i32, i16, i16, [8 x i8] }* @_GUID_12345678_1234_1234_1234_1234567890ab
+// CHECK: [[CONST_GUID_REF]] = !DIDerivedType(tag: DW_TAG_reference_type,
+// CHECK-SAME: baseType: [[CONST_GUID:![0-9]*]]
+// CHECK: [[CONST_GUID]] = !DIDerivedType(tag: DW_TAG_const_type
+// CHECK-SAME: baseType: [[GUID:![0-9]*]]
+// CHECK: [[GUID]] = !DICompositeType(tag: DW_TAG_structure_type, name: "_GUID"
+
// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "tmpl_guid<&__uuidof(uuid)>"
// CHECK-SAME: templateParams: [[TGIARGS:![0-9]*]]
// CHECK: [[TGIARGS]] = !{[[TGIARG1:![0-9]*]]}
@@ -10,24 +22,11 @@
// CHECK: [[CONST_GUID_PTR]] = !DIDerivedType(tag: DW_TAG_pointer_type
// CHECK-SAME: baseType: [[CONST_GUID:![0-9]*]]
// CHECK-SAME: size: 64
-// CHECK-SAME: align: 64
-// CHECK: [[CONST_GUID]] = !DIDerivedType(tag: DW_TAG_const_type
-// CHECK-SAME: baseType: [[GUID:![0-9]*]]
-// CHECK: [[GUID]] = !DICompositeType(tag: DW_TAG_structure_type, name: "_GUID"
-
-// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "tmpl_guid2<__uuidof(uuid)>"
-// CHECK-SAME: templateParams: [[TGI2ARGS:![0-9]*]]
-// CHECK: [[TGI2ARGS]] = !{[[TGI2ARG1:![0-9]*]]}
-// CHECK: [[TGI2ARG1]] = !DITemplateValueParameter(
-// CHECK-SAME: type: [[CONST_GUID_REF:![0-9]*]]
-// CHECK-SAME: value: { i32, i16, i16, [8 x i8] }* @_GUID_12345678_1234_1234_1234_1234567890ab
-// CHECK: [[CONST_GUID_REF]] = !DIDerivedType(tag: DW_TAG_reference_type,
-// CHECK-SAME: baseType: [[CONST_GUID:![0-9]*]]
-// CHECK-ITANIUM: !DICompositeType(tag: DW_TAG_structure_type, name: "tmpl_guid<&__uuidof(uuid)>"
-// CHECK-ITANIUM-SAME: identifier: "_ZTS9tmpl_guidIXadu8__uuidoft4uuidEE"
// CHECK-ITANIUM: !DICompositeType(tag: DW_TAG_structure_type, name: "tmpl_guid2<__uuidof(uuid)>"
// CHECK-ITANIUM-SAME: identifier: "_ZTS10tmpl_guid2IXu8__uuidoft4uuidEE"
+// CHECK-ITANIUM: !DICompositeType(tag: DW_TAG_structure_type, name: "tmpl_guid<&__uuidof(uuid)>"
+// CHECK-ITANIUM-SAME: identifier: "_ZTS9tmpl_guidIXadu8__uuidoft4uuidEE"
struct _GUID;
template <const _GUID *>
diff --git a/test/CodeGenCXX/debug-info-vla.cpp b/test/CodeGenCXX/debug-info-vla.cpp
new file mode 100644
index 000000000000..88f3a3f55dab
--- /dev/null
+++ b/test/CodeGenCXX/debug-info-vla.cpp
@@ -0,0 +1,20 @@
+// RUN: %clang -target x86_64-unknown-unknown -fverbose-asm -g -O0 -S -emit-llvm %s -o - -std=c++11 | FileCheck %s
+
+
+void f(int m) {
+ int x[3][m];
+}
+
+int (*fp)(int[][*]) = nullptr;
+
+// CHECK: !DICompositeType(tag: DW_TAG_array_type,
+// CHECK-NOT: size:
+// CHECK-SAME: elements: [[ELEM_TYPE:![0-9]+]]
+// CHECK: [[ELEM_TYPE]] = !{[[NOCOUNT:.*]]}
+// CHECK: [[NOCOUNT]] = !DISubrange(count: -1)
+//
+// CHECK: !DICompositeType(tag: DW_TAG_array_type,
+// CHECK-NOT: size:
+// CHECK-SAME: elements: [[ELEM_TYPE:![0-9]+]]
+// CHECK: [[ELEM_TYPE]] = !{[[THREE:.*]], [[NOCOUNT]]}
+// CHECK: [[THREE]] = !DISubrange(count: 3)
diff --git a/test/CodeGenCXX/debug-info-windows-dtor.cpp b/test/CodeGenCXX/debug-info-windows-dtor.cpp
index e5a51abae68b..8eb744a61bc7 100644
--- a/test/CodeGenCXX/debug-info-windows-dtor.cpp
+++ b/test/CodeGenCXX/debug-info-windows-dtor.cpp
@@ -19,4 +19,4 @@ template struct AB<int>;
// CHECK: define
// CHECK: [[THUNK_VEC_DEL_DTOR]] = distinct !DISubprogram
-// CHECK: [[THUNK_LOC]] = !DILocation(line: 15, scope: [[THUNK_VEC_DEL_DTOR]])
+// CHECK: [[THUNK_LOC]] = !DILocation(line: 0, scope: [[THUNK_VEC_DEL_DTOR]])
diff --git a/test/CodeGenCXX/debug-info-zero-length-arrays.cpp b/test/CodeGenCXX/debug-info-zero-length-arrays.cpp
index dc7558aa3935..9f8eab624b40 100644
--- a/test/CodeGenCXX/debug-info-zero-length-arrays.cpp
+++ b/test/CodeGenCXX/debug-info-zero-length-arrays.cpp
@@ -10,7 +10,6 @@ A a;
// CHECK-SAME: baseType: [[ARRAY_TYPE:![0-9]+]]
// CHECK: [[ARRAY_TYPE]] = !DICompositeType(tag: DW_TAG_array_type,
// CHECK-NOT: size:
-// CHECK-SAME: align: 32
// CHECK-SAME: elements: [[ELEM_TYPE:![0-9]+]]
// CHECK: [[ELEM_TYPE]] = !{[[SUBRANGE:.*]]}
// CHECK: [[SUBRANGE]] = !DISubrange(count: -1)
diff --git a/test/CodeGenCXX/debug-info.cpp b/test/CodeGenCXX/debug-info.cpp
index 2e8d5fd5f137..9575a5129e3d 100644
--- a/test/CodeGenCXX/debug-info.cpp
+++ b/test/CodeGenCXX/debug-info.cpp
@@ -1,14 +1,16 @@
// RUN: %clang_cc1 -triple x86_64-none-linux-gnu -emit-llvm -debug-info-kind=limited %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=BOTH
// RUN: %clang_cc1 -triple i686-pc-windows-msvc -emit-llvm -debug-info-kind=limited %s -o - | FileCheck %s --check-prefix=MSVC --check-prefix=BOTH
+// CHECK: @_ZN6pr96081xE = global [3 x i8]* null, align 8, !dbg [[X:![0-9]+]]
+
// CHECK: define void @_ZN7pr147634funcENS_3fooE
// CHECK: call void @llvm.dbg.declare({{.*}}, metadata ![[F:[0-9]+]], metadata ![[EXPR:[0-9]+]])
// !llvm.dbg.cu pulls in globals and their types first.
// CHECK-NOT: !DIGlobalVariable(name: "c"
-// CHECK: !DIGlobalVariable(name: "x", linkageName: "_ZN6pr96081xE"
-// CHECK-SAME: type: [[INCARRAYPTR:![0-9]*]]
-// CHECK-SAME: variable: [3 x i8]** @_ZN6pr96081xE
+// CHECK: [[X]] = !DIGlobalVariableExpression(var: [[XV:!.*]])
+// CHECK: [[XV]] = distinct !DIGlobalVariable(name: "x", linkageName: "_ZN6pr96081xE"
+// CHECK-SAME: type: [[INCARRAYPTR:![0-9]*]]
// CHECK: [[INCARRAYPTR]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: [[INCARRAY:![0-9]+]]
// CHECK: [[INCARRAY]] = !DICompositeType(tag: DW_TAG_array_type
// CHECK-NOT: line:
@@ -67,8 +69,8 @@ namespace VirtualBase {
struct A { int a; };
struct B : virtual A { int b; };
// BOTH: ![[VBASE_B:[0-9]+]] ={{.*}}!DICompositeType(tag: DW_TAG_structure_type, name: "B",{{.*}} line: [[@LINE-1]],
-// MSVC-SAME: size: 96, align: 32
-// CHECK-SAME: size: 128, align: 64,
+// MSVC-SAME: size: 96
+// CHECK-SAME: size: 128,
// BOTH-NOT: offset:
// BOTH-NOT: DIFlagFwdDecl
// BOTH-SAME: elements: [[VBASE_B_DEF:![0-9]+]]
diff --git a/test/CodeGenCXX/debug-lambda-expressions.cpp b/test/CodeGenCXX/debug-lambda-expressions.cpp
index b01f770bdd97..1717fc468656 100644
--- a/test/CodeGenCXX/debug-lambda-expressions.cpp
+++ b/test/CodeGenCXX/debug-lambda-expressions.cpp
@@ -15,6 +15,12 @@ struct D { D(); D(const D&); int x; };
int d(int x) { D y[10]; return [x,y] { return y[x].x; }(); }
// Randomness for file. -- 6
+
+// VAR:
+// CHECK: !DIGlobalVariable(name: "var"
+// CHECK-SAME: line: [[VAR_LINE:[0-9]+]]
+// CHECK-SAME: type: ![[VAR_T:[0-9]+]]
+
// CHECK: [[FILE:.*]] = !DIFile(filename: "{{.*}}debug-lambda-expressions.cpp",
// CVAR:
@@ -26,10 +32,6 @@ int d(int x) { D y[10]; return [x,y] { return y[x].x; }(); }
// CHECK-SAME: elements: ![[CVAR_ARGS:[0-9]+]]
// CHECK: ![[CVAR_ARGS]] = !{!{{[0-9]+}}}
-// VAR:
-// CHECK: !DIGlobalVariable(name: "var"
-// CHECK-SAME: line: [[VAR_LINE:[0-9]+]]
-// CHECK-SAME: type: ![[VAR_T:[0-9]+]]
// CHECK: ![[VAR_T]] = distinct !DICompositeType(tag: DW_TAG_class_type
// CHECK-SAME: line: [[VAR_LINE]],
// CHECK-SAME: elements: ![[VAR_ARGS:[0-9]+]]
diff --git a/test/CodeGenCXX/debug-lambda-this.cpp b/test/CodeGenCXX/debug-lambda-this.cpp
index 4af3d81983b2..eecbac6520ac 100644
--- a/test/CodeGenCXX/debug-lambda-this.cpp
+++ b/test/CodeGenCXX/debug-lambda-this.cpp
@@ -13,10 +13,10 @@ int D::d(int x) {
}
// CHECK: ![[D:[0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "D",
-// CHECK: ![[POINTER:.*]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[D]], size: 64, align: 64)
+// CHECK: ![[POINTER:.*]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[D]], size: 64)
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "this",
// CHECK-SAME: line: 11
// CHECK-SAME: baseType: ![[POINTER]]
-// CHECK-SAME: size: 64, align: 64
+// CHECK-SAME: size: 64
// CHECK-NOT: offset: 0
// CHECK-SAME: ){{$}}
diff --git a/test/CodeGenCXX/default-arg-temps.cpp b/test/CodeGenCXX/default-arg-temps.cpp
index 6a7f43a51287..f7b46818e39d 100644
--- a/test/CodeGenCXX/default-arg-temps.cpp
+++ b/test/CodeGenCXX/default-arg-temps.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 | FileCheck %s
+// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 | FileCheck %s
struct T {
T();
@@ -71,3 +71,10 @@ namespace test1 {
D d;
}
+
+namespace test2 {
+ // CHECK: define linkonce_odr void @_ZN5test21AIiED2Ev(
+ template <typename T> struct A { A() {} ~A() {} };
+ template <typename> void f(const A<int> & = {}) {}
+ void g() { f<int>(); }
+}
diff --git a/test/CodeGenCXX/derived-to-base.cpp b/test/CodeGenCXX/derived-to-base.cpp
index c69b45630ef6..3bd5e35615ac 100644
--- a/test/CodeGenCXX/derived-to-base.cpp
+++ b/test/CodeGenCXX/derived-to-base.cpp
@@ -46,4 +46,4 @@ namespace test3 {
}
}
-// CHECK: attributes [[NUW]] = { nounwind{{.*}} }
+// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} }
diff --git a/test/CodeGenCXX/destructors.cpp b/test/CodeGenCXX/destructors.cpp
index d6aabee58b9e..b082908b2c94 100644
--- a/test/CodeGenCXX/destructors.cpp
+++ b/test/CodeGenCXX/destructors.cpp
@@ -1,11 +1,16 @@
-// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o - -mconstructor-aliases -fcxx-exceptions -fexceptions -O1 -disable-llvm-optzns > %t
+// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o - -mconstructor-aliases -fcxx-exceptions -fexceptions -O1 -disable-llvm-passes -std=c++03 > %t
// RUN: FileCheck --check-prefix=CHECK1 --input-file=%t %s
// RUN: FileCheck --check-prefix=CHECK2 --input-file=%t %s
// RUN: FileCheck --check-prefix=CHECK3 --input-file=%t %s
-// RUN: FileCheck --check-prefix=CHECK4 --input-file=%t %s
-// RUN: FileCheck --check-prefix=CHECK5 --input-file=%t %s
-// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o - -fcxx-exceptions -fexceptions -O1 -disable-llvm-optzns -std=c++11 > %t2
-// RUN: FileCheck --check-prefix=CHECK6 --input-file=%t2 %s
+// RUN: FileCheck --check-prefixes=CHECK4,CHECK4v03 --input-file=%t %s
+// RUN: FileCheck --check-prefixes=CHECK5,CHECK5v03 --input-file=%t %s
+// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o - -mconstructor-aliases -fcxx-exceptions -fexceptions -O1 -disable-llvm-passes -std=c++11 > %t2
+// RUN: FileCheck --check-prefix=CHECK1 --input-file=%t2 %s
+// RUN: FileCheck --check-prefix=CHECK2v11 --input-file=%t2 %s
+// RUN: FileCheck --check-prefix=CHECK3 --input-file=%t2 %s
+// RUN: FileCheck --check-prefixes=CHECK4,CHECK4v11 --input-file=%t2 %s
+// RUN: FileCheck --check-prefixes=CHECK5,CHECK5v11 --input-file=%t2 %s
+// RUN: FileCheck --check-prefix=CHECK6 --input-file=%t2 %s
// REQUIRES: asserts
struct A {
@@ -98,6 +103,12 @@ namespace test0 {
// CHECK2: invoke void @_ZN5test04BaseD2Ev
// 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: define void @_ZN5test01AD2Ev(%"struct.test0::A"* %this) unnamed_addr
+// CHECK2v11: call void @_ZN5test06MemberD1Ev
+// CHECK2v11: call void @_ZN5test04BaseD2Ev
+
struct B : Base, virtual VBase {
Member M;
~B();
@@ -111,6 +122,10 @@ namespace test0 {
// CHECK2: invoke void @_ZN5test04BaseD2Ev
// CHECK2: unwind label [[BASE_UNWIND:%[a-zA-Z0-9.]+]]
+// CHECK2v11-LABEL: define void @_ZN5test01BD2Ev(%"struct.test0::B"* %this, i8** %vtt) unnamed_addr
+// CHECK2v11: call void @_ZN5test06MemberD1Ev
+// CHECK2v11: call void @_ZN5test04BaseD2Ev
+
// CHECK2-LABEL: define void @_ZN5test01BD1Ev(%"struct.test0::B"* %this) unnamed_addr
// CHECK2: invoke void @_ZN5test06MemberD1Ev
// CHECK2: unwind label [[MEM_UNWIND:%[a-zA-Z0-9.]+]]
@@ -118,6 +133,11 @@ namespace test0 {
// CHECK2: unwind label [[BASE_UNWIND:%[a-zA-Z0-9.]+]]
// CHECK2: invoke void @_ZN5test05VBaseD2Ev
// CHECK2: unwind label [[VBASE_UNWIND:%[a-zA-Z0-9.]+]]
+
+// CHECK2v11-LABEL: define void @_ZN5test01BD1Ev(%"struct.test0::B"* %this) unnamed_addr
+// CHECK2v11: call void @_ZN5test06MemberD1Ev
+// CHECK2v11: call void @_ZN5test04BaseD2Ev
+// CHECK2v11: call void @_ZN5test05VBaseD2Ev
}
// Test base-class aliasing.
@@ -189,19 +209,22 @@ namespace test3 {
}
// CHECK4-LABEL: define internal void @_ZN5test312_GLOBAL__N_11CD2Ev(%"struct.test3::(anonymous namespace)::C"* %this) unnamed_addr
- // CHECK4: invoke void @_ZN5test31BD2Ev(
+ // CHECK4v03: invoke void @_ZN5test31BD2Ev(
+ // CHECK4v11: call void @_ZN5test31BD2Ev(
// CHECK4: call void @_ZN5test31AD2Ev(
// CHECK4: ret void
// CHECK4-LABEL: define internal void @_ZN5test312_GLOBAL__N_11DD0Ev(%"struct.test3::(anonymous namespace)::D"* %this) unnamed_addr
- // CHECK4-SAME: personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
- // CHECK4: invoke void {{.*}} @_ZN5test312_GLOBAL__N_11CD2Ev
+ // CHECK4v03-SAME: personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+ // CHECK4v03: invoke void {{.*}} @_ZN5test312_GLOBAL__N_11CD2Ev
+ // CHECK4v11: call void {{.*}} @_ZN5test312_GLOBAL__N_11CD2Ev
// CHECK4: call void @_ZdlPv({{.*}}) [[NUW:#[0-9]+]]
// CHECK4: ret void
- // CHECK4: landingpad { i8*, i32 }
- // CHECK4-NEXT: cleanup
- // CHECK4: call void @_ZdlPv({{.*}}) [[NUW]]
- // CHECK4: resume { i8*, i32 }
+ // CHECK4v03: landingpad { i8*, i32 }
+ // CHECK4v03-NEXT: cleanup
+ // CHECK4v03: call void @_ZdlPv({{.*}}) [[NUW]]
+ // CHECK4v03: resume { i8*, i32 }
+ // CHECK4v11-NOT: landingpad
// CHECK4-LABEL: define internal void @_ZThn8_N5test312_GLOBAL__N_11DD1Ev(
// CHECK4: getelementptr inbounds i8, i8* {{.*}}, i64 -8
@@ -214,14 +237,15 @@ namespace test3 {
// CHECK4: ret void
// CHECK4-LABEL: define internal void @_ZN5test312_GLOBAL__N_11CD0Ev(%"struct.test3::(anonymous namespace)::C"* %this) unnamed_addr
- // CHECK4-SAME: personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
- // CHECK4: invoke void @_ZN5test312_GLOBAL__N_11CD2Ev(
+ // CHECK4v03-SAME: personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+ // CHECK4v03: invoke void @_ZN5test312_GLOBAL__N_11CD2Ev(
+ // CHECK4v11: call void @_ZN5test312_GLOBAL__N_11CD2Ev(
// CHECK4: call void @_ZdlPv({{.*}}) [[NUW]]
// CHECK4: ret void
- // CHECK4: landingpad { i8*, i32 }
- // CHECK4-NEXT: cleanup
- // CHECK4: call void @_ZdlPv({{.*}}) [[NUW]]
- // CHECK4: resume { i8*, i32 }
+ // CHECK4v03: landingpad { i8*, i32 }
+ // CHECK4v03-NEXT: cleanup
+ // CHECK4v03: call void @_ZdlPv({{.*}}) [[NUW]]
+ // CHECK4v03: resume { i8*, i32 }
// CHECK4-LABEL: define internal void @_ZThn8_N5test312_GLOBAL__N_11CD1Ev(
// CHECK4: getelementptr inbounds i8, i8* {{.*}}, i64 -8
@@ -282,8 +306,8 @@ namespace test5 {
// CHECK5-LABEL: define void @_ZN5test53fooEv()
// CHECK5: [[ELEMS:%.*]] = alloca [5 x [[A:%.*]]], align
- // CHECK5-NEXT: [[EXN:%.*]] = alloca i8*
- // CHECK5-NEXT: [[SEL:%.*]] = alloca i32
+ // CHECK5v03-NEXT: [[EXN:%.*]] = alloca i8*
+ // CHECK5v03-NEXT: [[SEL:%.*]] = alloca i32
// CHECK5-NEXT: [[PELEMS:%.*]] = bitcast [5 x [[A]]]* [[ELEMS]] to i8*
// CHECK5-NEXT: call void @llvm.lifetime.start(i64 5, i8* [[PELEMS]])
// CHECK5-NEXT: [[BEGIN:%.*]] = getelementptr inbounds [5 x [[A]]], [5 x [[A]]]* [[ELEMS]], i32 0, i32 0
@@ -291,19 +315,22 @@ namespace test5 {
// CHECK5-NEXT: br label
// CHECK5: [[POST:%.*]] = phi [[A]]* [ [[END]], {{%.*}} ], [ [[ELT:%.*]], {{%.*}} ]
// CHECK5-NEXT: [[ELT]] = getelementptr inbounds [[A]], [[A]]* [[POST]], i64 -1
- // CHECK5-NEXT: invoke void @_ZN5test51AD1Ev([[A]]* [[ELT]])
+ // CHECK5v03-NEXT: invoke void @_ZN5test51AD1Ev([[A]]* [[ELT]])
+ // CHECK5v11-NEXT: call void @_ZN5test51AD1Ev([[A]]* [[ELT]])
// CHECK5: [[T0:%.*]] = icmp eq [[A]]* [[ELT]], [[BEGIN]]
// CHECK5-NEXT: br i1 [[T0]],
// CHECK5: call void @llvm.lifetime.end
// CHECK5-NEXT: ret void
// lpad
- // CHECK5: [[EMPTY:%.*]] = icmp eq [[A]]* [[BEGIN]], [[ELT]]
- // CHECK5-NEXT: br i1 [[EMPTY]]
- // CHECK5: [[AFTER:%.*]] = phi [[A]]* [ [[ELT]], {{%.*}} ], [ [[CUR:%.*]], {{%.*}} ]
- // CHECK5-NEXT: [[CUR:%.*]] = getelementptr inbounds [[A]], [[A]]* [[AFTER]], i64 -1
- // CHECK5-NEXT: invoke void @_ZN5test51AD1Ev([[A]]* [[CUR]])
- // CHECK5: [[DONE:%.*]] = icmp eq [[A]]* [[CUR]], [[BEGIN]]
- // CHECK5-NEXT: br i1 [[DONE]],
+ // CHECK5v03: [[EMPTY:%.*]] = icmp eq [[A]]* [[BEGIN]], [[ELT]]
+ // CHECK5v03-NEXT: br i1 [[EMPTY]]
+ // CHECK5v03: [[AFTER:%.*]] = phi [[A]]* [ [[ELT]], {{%.*}} ], [ [[CUR:%.*]], {{%.*}} ]
+ // CHECK5v03-NEXT: [[CUR:%.*]] = getelementptr inbounds [[A]], [[A]]* [[AFTER]], i64 -1
+ // CHECK5v03-NEXT: invoke void @_ZN5test51AD1Ev([[A]]* [[CUR]])
+ // CHECK5v03: [[DONE:%.*]] = icmp eq [[A]]* [[CUR]], [[BEGIN]]
+ // CHECK5v03-NEXT: br i1 [[DONE]],
+ // CHECK5v11-NOT: landingpad
+ // CHECK5v11: }
void foo() {
A elems[5];
}
@@ -334,25 +361,34 @@ namespace test6 {
C::~C() { opaque(); }
// CHECK5-LABEL: define void @_ZN5test61CD2Ev(%"struct.test6::C"* %this, i8** %vtt) unnamed_addr
// CHECK5: invoke void @_ZN5test66opaqueEv
- // CHECK5: invoke void @_ZN5test61AD1Ev
- // CHECK5: invoke void @_ZN5test61AD1Ev
- // CHECK5: invoke void @_ZN5test61AD1Ev
- // CHECK5: invoke void @_ZN5test61BILj1EED2Ev
+ // CHECK5v03: invoke void @_ZN5test61AD1Ev
+ // CHECK5v03: invoke void @_ZN5test61AD1Ev
+ // CHECK5v03: invoke void @_ZN5test61AD1Ev
+ // CHECK5v03: invoke void @_ZN5test61BILj1EED2Ev
+ // CHECK5v11: call void @_ZN5test61AD1Ev
+ // CHECK5v11: call void @_ZN5test61AD1Ev
+ // CHECK5v11: call void @_ZN5test61AD1Ev
+ // CHECK5v11: call void @_ZN5test61BILj1EED2Ev
// CHECK5: call void @_ZN5test61BILj0EED2Ev
// CHECK5: ret void
- // CHECK5: invoke void @_ZN5test61AD1Ev
- // CHECK5: invoke void @_ZN5test61AD1Ev
- // CHECK5: invoke void @_ZN5test61AD1Ev
- // CHECK5: invoke void @_ZN5test61BILj1EED2Ev
- // CHECK5: invoke void @_ZN5test61BILj0EED2Ev
+ // CHECK5v03: invoke void @_ZN5test61AD1Ev
+ // CHECK5v03: invoke void @_ZN5test61AD1Ev
+ // CHECK5v03: invoke void @_ZN5test61AD1Ev
+ // CHECK5v03: invoke void @_ZN5test61BILj1EED2Ev
+ // CHECK5v03: invoke void @_ZN5test61BILj0EED2Ev
// CHECK5-LABEL: define void @_ZN5test61CD1Ev(%"struct.test6::C"* %this) unnamed_addr
- // CHECK5: invoke void @_ZN5test61CD2Ev
- // CHECK5: invoke void @_ZN5test61BILj3EED2Ev
- // CHECK5: call void @_ZN5test61BILj2EED2Ev
- // CHECK5: ret void
- // CHECK5: invoke void @_ZN5test61BILj3EED2Ev
- // CHECK5: invoke void @_ZN5test61BILj2EED2Ev
+ // CHECK5v03: invoke void @_ZN5test61CD2Ev
+ // CHECK5v03: invoke void @_ZN5test61BILj3EED2Ev
+ // CHECK5v03: call void @_ZN5test61BILj2EED2Ev
+ // CHECK5v03: ret void
+ // CHECK5v03: invoke void @_ZN5test61BILj3EED2Ev
+ // CHECK5v03: invoke void @_ZN5test61BILj2EED2Ev
+
+ // CHECK5v11: call void @_ZN5test61CD2Ev
+ // CHECK5v11: call void @_ZN5test61BILj3EED2Ev
+ // CHECK5v11: call void @_ZN5test61BILj2EED2Ev
+ // CHECK5v11: ret void
}
// PR 9197
@@ -369,7 +405,8 @@ namespace test7 {
// Verify that this doesn't get emitted as an alias
// CHECK5-LABEL: define void @_ZN5test71BD2Ev(
- // CHECK5: invoke void @_ZN5test71DD1Ev(
+ // CHECK5v03: invoke void @_ZN5test71DD1Ev(
+ // CHECK5v11: call void @_ZN5test71DD1Ev(
// CHECK5: call void @_ZN5test71AD2Ev(
B::~B() {}
}
@@ -394,7 +431,8 @@ namespace test8 {
// CHECK5: call void @_ZN5test81AC1Ev([[A]]* [[X]])
// CHECK5-NEXT: br label
// CHECK5: invoke void @_ZN5test81AC1Ev([[A]]* [[Y]])
- // CHECK5: invoke void @_ZN5test81AD1Ev([[A]]* [[Y]])
+ // CHECK5v03: invoke void @_ZN5test81AD1Ev([[A]]* [[Y]])
+ // CHECK5v11: call void @_ZN5test81AD1Ev([[A]]* [[Y]])
// CHECK5-NOT: switch
// CHECK5: invoke void @_ZN5test83dieEv()
// CHECK5: unreachable
diff --git a/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp b/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp
index 193ee5f80406..b90620ab600f 100644
--- a/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp
+++ b/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp
@@ -225,3 +225,19 @@ namespace Test9 {
return -static_cast<RA&>(*x);
}
}
+
+namespace Test10 {
+ struct A {
+ virtual int f();
+ };
+
+ struct B : A {
+ int f() final;
+ };
+
+ // CHECK-LABEL: define i32 @_ZN6Test101fEPNS_1BE
+ int f(B *b) {
+ // CHECK: call i32 @_ZN6Test101B1fEv
+ return static_cast<A *>(b)->f();
+ }
+}
diff --git a/test/CodeGenCXX/devirtualize-virtual-function-calls.cpp b/test/CodeGenCXX/devirtualize-virtual-function-calls.cpp
index 911ddeedd236..b4c39f3fcff5 100644
--- a/test/CodeGenCXX/devirtualize-virtual-function-calls.cpp
+++ b/test/CodeGenCXX/devirtualize-virtual-function-calls.cpp
@@ -1,8 +1,11 @@
-// RUN: %clang_cc1 %s -triple armv7-none-eabi -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -std=c++98 %s -triple armv7-none-eabi -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -std=c++11 %s -triple armv7-none-eabi -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -std=c++1z %s -triple armv7-none-eabi -emit-llvm -o - | FileCheck %s
struct A {
virtual void f();
virtual void f_const() const;
+ virtual void g();
A h();
};
@@ -37,6 +40,64 @@ void f(A a, A *ap, A& ar) {
(a).f();
}
+struct D : A { virtual void g(); };
+struct XD { D d; };
+
+D gd();
+
+void fd(D d, XD xd, D *p) {
+ // CHECK: call void @_ZN1A1fEv(%struct.A*
+ d.f();
+
+ // CHECK: call void @_ZN1D1gEv(%struct.D*
+ d.g();
+
+ // CHECK: call void @_ZN1A1fEv
+ D().f();
+
+ // CHECK: call void @_ZN1D1gEv
+ D().g();
+
+ // CHECK: call void @_ZN1A1fEv
+ gd().f();
+
+ // CHECK: call void @_ZNK1A7f_constEv
+ d.f_const();
+
+ // CHECK: call void @_ZN1A1fEv
+ (d).f();
+
+ // CHECK: call void @_ZN1A1fEv
+ (true, d).f();
+
+ // CHECK: call void @_ZN1D1gEv
+ (true, d).g();
+
+ // CHECK: call void @_ZN1A1fEv
+ xd.d.f();
+
+ // CHECK: call void @_ZN1A1fEv
+ XD().d.f();
+
+ // CHECK: call void @_ZN1A1fEv
+ D XD::*mp;
+ (xd.*mp).f();
+
+ // CHECK: call void @_ZN1D1gEv
+ (xd.*mp).g();
+
+ // Can't devirtualize this; we have no guarantee that p points to a D here,
+ // due to the "single object is considered to be an array of one element"
+ // rule.
+ // CHECK: call void %
+ p[0].f();
+
+ // FIXME: We can devirtualize this, by C++1z [expr.add]/6 (if the array
+ // element type and the pointee type are not similar, behavior is undefined).
+ // CHECK: call void %
+ p[1].f();
+}
+
struct B {
virtual void f();
~B();
@@ -100,3 +161,37 @@ namespace test4 {
p->fish.eat();
}
}
+
+// Do not devirtualize to pure virtual function calls.
+namespace test5 {
+ struct X {
+ virtual void f() = 0;
+ };
+ struct Y {};
+ // CHECK-LABEL: define {{.*}} @_ZN5test51f
+ void f(Y &y, X Y::*p) {
+ // CHECK-NOT: call {{.*}} @_ZN5test51X1fEv
+ // CHECK: call void %
+ (y.*p).f();
+ };
+
+ struct Z final {
+ virtual void f() = 0;
+ };
+ // CHECK-LABEL: define {{.*}} @_ZN5test51g
+ void g(Z &z) {
+ // CHECK-NOT: call {{.*}} @_ZN5test51Z1fEv
+ // CHECK: call void %
+ z.f();
+ }
+
+ struct Q {
+ virtual void f() final = 0;
+ };
+ // CHECK-LABEL: define {{.*}} @_ZN5test51h
+ void h(Q &q) {
+ // CHECK-NOT: call {{.*}} @_ZN5test51Q1fEv
+ // CHECK: call void %
+ q.f();
+ }
+}
diff --git a/test/CodeGenCXX/dllexport.cpp b/test/CodeGenCXX/dllexport.cpp
index 7cef7c2d127e..eb9ca79b7b40 100644
--- a/test/CodeGenCXX/dllexport.cpp
+++ b/test/CodeGenCXX/dllexport.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O1 -mconstructor-aliases -disable-llvm-optzns -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-optzns -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 --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 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
@@ -612,9 +612,9 @@ void W::foo() {}
// Copy ctor:
// M32-DAG: define weak_odr dllexport x86_thiscallcc %struct.W* @"\01??0W@@QAE@ABU0@@Z"
// vftable:
-// M32-DAG: [[W_VTABLE:@.*]] = private unnamed_addr constant [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 1)
-// G32-DAG: @_ZTV1W = dllexport unnamed_addr constant [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* @"\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*)] }
struct __declspec(dllexport) X : public virtual W {};
// vbtable:
@@ -771,6 +771,13 @@ USEMEMFUNC(ExplicitInstantiationDeclExportedDefTemplate<int>, f);
// 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
+template <typename T> struct ImplicitInstantiationExplicitInstantiationDefExportedTemplate { void f() {} };
+ImplicitInstantiationExplicitInstantiationDefExportedTemplate<int> ImplicitInstantiationExplicitInstantiationDefExportedTemplateInstance;
+template class __declspec(dllexport) ImplicitInstantiationExplicitInstantiationDefExportedTemplate<int>;
+USEMEMFUNC(ImplicitInstantiationExplicitInstantiationDefExportedTemplate<int>, f);
+// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?f@?$ImplicitInstantiationExplicitInstantiationDefExportedTemplate@H@@QAEXXZ"
+// G32-DAG: define weak_odr x86_thiscallcc void @_ZN61ImplicitInstantiationExplicitInstantiationDefExportedTemplateIiE1fEv
+
namespace { struct InternalLinkageType {}; }
struct __declspec(dllexport) PR23308 {
void f(InternalLinkageType*);
diff --git a/test/CodeGenCXX/dllimport-members.cpp b/test/CodeGenCXX/dllimport-members.cpp
index 1fed1bf0acf1..19d9e1dfe7b6 100644
--- a/test/CodeGenCXX/dllimport-members.cpp
+++ b/test/CodeGenCXX/dllimport-members.cpp
@@ -44,7 +44,7 @@ void useSpecials() {
}
// Used to force non-trivial special members.
-struct ForceNonTrivial {
+struct __declspec(dllimport) ForceNonTrivial {
ForceNonTrivial();
~ForceNonTrivial();
ForceNonTrivial(const ForceNonTrivial&);
diff --git a/test/CodeGenCXX/dllimport-rtti.cpp b/test/CodeGenCXX/dllimport-rtti.cpp
index 4baee50fcff3..91e747ae1c15 100644
--- a/test/CodeGenCXX/dllimport-rtti.cpp
+++ b/test/CodeGenCXX/dllimport-rtti.cpp
@@ -1,11 +1,11 @@
-// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -std=c++1y -fms-extensions -O1 -disable-llvm-optzns -o - %s | FileCheck %s --check-prefix=MSVC
-// RUN: %clang_cc1 -triple i686-windows-gnu -emit-llvm -std=c++1y -fms-extensions -O1 -disable-llvm-optzns -o - %s | FileCheck %s --check-prefix=GNU
+// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -std=c++1y -fms-extensions -O1 -disable-llvm-passes -o - %s | FileCheck %s --check-prefix=MSVC
+// RUN: %clang_cc1 -triple i686-windows-gnu -emit-llvm -std=c++1y -fms-extensions -O1 -disable-llvm-passes -o - %s | FileCheck %s --check-prefix=GNU
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 1)
+// 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
diff --git a/test/CodeGenCXX/dllimport.cpp b/test/CodeGenCXX/dllimport.cpp
index aff240f28769..4ec14b72109f 100644
--- a/test/CodeGenCXX/dllimport.cpp
+++ b/test/CodeGenCXX/dllimport.cpp
@@ -2,8 +2,8 @@
// RUN: %clang_cc1 -triple x86_64-windows-msvc -fno-rtti -fno-threadsafe-statics -fms-extensions -emit-llvm -std=c++1y -O0 -o - %s -DMSABI -w | FileCheck --check-prefix=MSC --check-prefix=M64 %s
// RUN: %clang_cc1 -triple i686-windows-gnu -fno-rtti -fno-threadsafe-statics -fms-extensions -emit-llvm -std=c++1y -O0 -o - %s -w | FileCheck --check-prefix=GNU --check-prefix=G32 %s
// RUN: %clang_cc1 -triple x86_64-windows-gnu -fno-rtti -fno-threadsafe-statics -fms-extensions -emit-llvm -std=c++1y -O0 -o - %s -w | FileCheck --check-prefix=GNU --check-prefix=G64 %s
-// RUN: %clang_cc1 -triple i686-windows-msvc -fno-rtti -fno-threadsafe-statics -fms-extensions -fms-compatibility-version=18.00 -emit-llvm -std=c++1y -O1 -disable-llvm-optzns -o - %s -DMSABI -w | FileCheck --check-prefix=MO1 --check-prefix=M18 %s
-// RUN: %clang_cc1 -triple i686-windows-msvc -fno-rtti -fno-threadsafe-statics -fms-extensions -fms-compatibility-version=19.00 -emit-llvm -std=c++1y -O1 -disable-llvm-optzns -o - %s -DMSABI -w | FileCheck --check-prefix=MO1 --check-prefix=M19 %s
+// RUN: %clang_cc1 -triple i686-windows-msvc -fno-rtti -fno-threadsafe-statics -fms-extensions -fms-compatibility-version=18.00 -emit-llvm -std=c++1y -O1 -disable-llvm-passes -o - %s -DMSABI -w | FileCheck --check-prefix=MO1 --check-prefix=M18 %s
+// RUN: %clang_cc1 -triple i686-windows-msvc -fno-rtti -fno-threadsafe-statics -fms-extensions -fms-compatibility-version=19.00 -emit-llvm -std=c++1y -O1 -disable-llvm-passes -o - %s -DMSABI -w | FileCheck --check-prefix=MO1 --check-prefix=M19 %s
// RUN: %clang_cc1 -triple i686-windows-gnu -fno-rtti -fno-threadsafe-statics -fms-extensions -emit-llvm -std=c++1y -O1 -o - %s -w | FileCheck --check-prefix=GO1 %s
// CHECK-NOT doesn't play nice with CHECK-DAG, so use separate run lines.
@@ -347,6 +347,17 @@ __declspec(dllimport) inline int *ReferencingImportedDelete() { delete (int*)nul
// MO1-DAG: define available_externally dllimport i32* @"\01?ReferencingImportedDelete@@YAPAHXZ"
USE(ReferencingImportedNew)
USE(ReferencingImportedDelete)
+struct ClassWithDtor { ~ClassWithDtor() {} };
+struct __declspec(dllimport) ClassWithNonDllImportField { ClassWithDtor t; };
+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*)
+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)
// A dllimport function with a TLS variable must not be available_externally.
__declspec(dllimport) inline void FunctionWithTLSVar() { static __thread int x = 42; }
@@ -620,15 +631,15 @@ 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*] [i8* bitcast (void (%struct.W*)* @"\01?foo@W@@UAEXXZ" to i8*)]
-// GO1-DAG: @_ZTV1W = available_externally dllimport unnamed_addr constant [3 x i8*] [i8* null, i8* null, i8* bitcast (void (%struct.W*)* @_ZN1W3fooEv to i8*)]
+// 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*)] }
+// 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 {
constexpr KeyFuncClass() {}
virtual void foo();
};
extern constexpr KeyFuncClass keyFuncClassVar = {};
-// G32-DAG: @_ZTV12KeyFuncClass = external dllimport unnamed_addr constant [3 x i8*]
+// G32-DAG: @_ZTV12KeyFuncClass = external dllimport unnamed_addr constant { [3 x i8*] }
struct __declspec(dllimport) X : public virtual W {};
USECLASS(X)
@@ -658,7 +669,7 @@ namespace Vtordisp {
// Don't dllimport the vtordisp.
// MO1-DAG: define linkonce_odr x86_thiscallcc void @"\01?f@?$C@H@Vtordisp@@$4PPPPPPPM@A@AEXXZ"
- class Base {
+ class __declspec(dllimport) Base {
virtual void f() {}
};
template <typename T>
@@ -734,7 +745,7 @@ namespace PR21355 {
// S::~S is a key function, so we would ordinarily emit a strong definition for
// the vtable. However, S is imported, so the vtable should be too.
- // GNU-DAG: @_ZTVN7PR213551SE = available_externally dllimport unnamed_addr constant [4 x i8*]
+ // GNU-DAG: @_ZTVN7PR213551SE = available_externally dllimport unnamed_addr constant { [4 x i8*] }
}
namespace PR21366 {
@@ -756,7 +767,7 @@ 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: @"\01??_S?$A@H@PR27319@@6B@" = linkonce_odr unnamed_addr constant { [1 x i8*] }
}
// MS ignores DLL attributes on partial specializations.
diff --git a/test/CodeGenCXX/empty-classes.cpp b/test/CodeGenCXX/empty-classes.cpp
index e27a961e123a..5727d5918291 100644
--- a/test/CodeGenCXX/empty-classes.cpp
+++ b/test/CodeGenCXX/empty-classes.cpp
@@ -96,3 +96,24 @@ namespace rdar20621065 {
// Type checked at the top of the file.
B b;
};
+
+// This test used to crash when CGRecordLayout::getNonVirtualBaseLLVMFieldNo was called.
+namespace record_layout {
+struct X0 {
+ int x[0];
+};
+
+template<typename>
+struct X2 : X0 {
+};
+
+template<typename>
+struct X3 : X2<int> {
+ X3() : X2<int>() {}
+};
+
+
+void test0() {
+ X3<int>();
+}
+}
diff --git a/test/CodeGenCXX/enable_if.cpp b/test/CodeGenCXX/enable_if.cpp
index e17695b413b6..4e7707aaeed9 100644
--- a/test/CodeGenCXX/enable_if.cpp
+++ b/test/CodeGenCXX/enable_if.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-pc-linux-gnu| FileCheck %s
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-pc-linux-gnu | FileCheck %s
// Test address-of overloading logic
int test5(int);
diff --git a/test/CodeGenCXX/exceptions-seh.cpp b/test/CodeGenCXX/exceptions-seh.cpp
index 589bc2265760..7a11a1e50582 100644
--- a/test/CodeGenCXX/exceptions-seh.cpp
+++ b/test/CodeGenCXX/exceptions-seh.cpp
@@ -2,7 +2,7 @@
// RUN: -o - -mconstructor-aliases -fcxx-exceptions -fexceptions | \
// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CXXEH
// RUN: %clang_cc1 -std=c++11 -fblocks -fms-extensions %s -triple=x86_64-windows-msvc -emit-llvm \
-// RUN: -o - -mconstructor-aliases -O1 -disable-llvm-optzns | \
+// RUN: -o - -mconstructor-aliases -O1 -disable-llvm-passes | \
// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=NOCXX
extern "C" unsigned long _exception_code();
diff --git a/test/CodeGenCXX/explicit-instantiation.cpp b/test/CodeGenCXX/explicit-instantiation.cpp
index 7e00d78e4834..fb5711878764 100644
--- a/test/CodeGenCXX/explicit-instantiation.cpp
+++ b/test/CodeGenCXX/explicit-instantiation.cpp
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -emit-llvm -triple i686-pc-linux-gnu -std=c++1y -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NO-OPT
-// RUN: %clang_cc1 -emit-llvm -triple i686-pc-linux-gnu -std=c++1y -O3 -disable-llvm-optzns -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-OPT
+// RUN: %clang_cc1 -emit-llvm -triple i686-pc-linux-gnu -std=c++1y -O3 -disable-llvm-passes -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-OPT
// RUN: %clang_cc1 -emit-llvm -triple i686-pc-win32 -std=c++1y -o - %s | FileCheck %s --check-prefix=CHECK-MS
// This check logically is attached to 'template int S<int>::i;' below.
diff --git a/test/CodeGenCXX/global-dtor-no-atexit.cpp b/test/CodeGenCXX/global-dtor-no-atexit.cpp
index 9860412b1bda..862194126ba8 100644
--- a/test/CodeGenCXX/global-dtor-no-atexit.cpp
+++ b/test/CodeGenCXX/global-dtor-no-atexit.cpp
@@ -43,4 +43,4 @@ void func() {
static A a1, a2;
}
-// CHECK: attributes [[NUW]] = { nounwind{{.*}} }
+// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} }
diff --git a/test/CodeGenCXX/global-init.cpp b/test/CodeGenCXX/global-init.cpp
index e806af9eacb4..291b43cac0a0 100644
--- a/test/CodeGenCXX/global-init.cpp
+++ b/test/CodeGenCXX/global-init.cpp
@@ -18,9 +18,6 @@ struct D { ~D(); };
// CHECK: @__dso_handle = external global i8
// CHECK: @c = global %struct.C zeroinitializer, align 8
-// It's okay if we ever implement the IR-generation optimization to remove this.
-// CHECK: @_ZN5test3L3varE = internal constant i8* getelementptr inbounds ([7 x i8], [7 x i8]*
-
// PR6205: The casts should not require global initializers
// CHECK: @_ZN6PR59741cE = external global %"struct.PR5974::C"
// CHECK: @_ZN6PR59741aE = global %"struct.PR5974::A"* getelementptr inbounds (%"struct.PR5974::C", %"struct.PR5974::C"* @_ZN6PR59741cE, i32 0, i32 0)
@@ -171,6 +168,8 @@ namespace test7 {
const int b3 = B().n;
// CHECK-NOT: @_ZN5test7L2c1E
+ // CHECK: call void @llvm.memset{{.*}} @_ZN5test7L2c1E
+ // CHECK-NOT: @_ZN5test7L2c1E
// CHECK: @_ZN5test7L2c2E
// CHECK-NOT: @_ZN5test7L2c3E
// CHECK: @_ZN5test7L2c4E
@@ -205,8 +204,8 @@ namespace test7 {
// rdar://problem/8090834: this should be nounwind
// CHECK-NOEXC: define internal void @_GLOBAL__sub_I_global_init.cpp() [[NUW:#[0-9]+]] section "__TEXT,__StaticInit,regular,pure_instructions" {
-// CHECK-NOEXC: attributes [[NUW]] = { nounwind{{.*}} }
+// CHECK-NOEXC: attributes [[NUW]] = { noinline nounwind{{.*}} }
// PR21811: attach the appropriate attribute to the global init function
// CHECK-FP: define internal void @_GLOBAL__sub_I_global_init.cpp() [[NUX:#[0-9]+]] section "__TEXT,__StaticInit,regular,pure_instructions" {
-// CHECK-FP: attributes [[NUX]] = { nounwind {{.*}}"no-frame-pointer-elim-non-leaf"{{.*}} }
+// CHECK-FP: attributes [[NUX]] = { noinline nounwind {{.*}}"no-frame-pointer-elim-non-leaf"{{.*}} }
diff --git a/test/CodeGenCXX/implicit-copy-constructor.cpp b/test/CodeGenCXX/implicit-copy-constructor.cpp
index d0224131c4da..3f8665aa3b4d 100644
--- a/test/CodeGenCXX/implicit-copy-constructor.cpp
+++ b/test/CodeGenCXX/implicit-copy-constructor.cpp
@@ -48,12 +48,14 @@ void f(D d) {
// CHECK: call void @_ZN1BC2ERS_
// CHECK: {{call void @llvm.memcpy.p0i8.p0i8.i64.*i64 28}}
// CHECK: call void @_ZN1BC1ERS_
-// CHECK: br
-// CHECK: {{icmp ult.*, 2}}
-// CHECK: {{icmp ult.*, 3}}
+// CHECK: br label
// CHECK: call void @_ZN1AC1Ev
// CHECK: call void @_ZN1CC1ERS_1A
// CHECK: call void @_ZN1AD1Ev
+// CHECK: {{icmp eq.*, 3}}
+// CHECK: br i1
+// CHECK: {{icmp eq.*, 2}}
+// CHECK: br i1
// CHECK: {{call void @llvm.memcpy.p0i8.p0i8.i64.*i64 300}}
// CHECK: ret void
diff --git a/test/CodeGenCXX/init-invariant.cpp b/test/CodeGenCXX/init-invariant.cpp
index 71eb7dd73492..815287c8e116 100644
--- a/test/CodeGenCXX/init-invariant.cpp
+++ b/test/CodeGenCXX/init-invariant.cpp
@@ -1,12 +1,12 @@
// RUN: %clang_cc1 -triple i686-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O0
// RUN: %clang_cc1 -triple i686-linux-gnu -emit-llvm %s -O1 -o - | FileCheck %s
-// Check that we add an llvm.invariant.start to mark when a global becomes
+// Check that we add an llvm.invariant.start.p0i8 to mark when a global becomes
// read-only. If globalopt can fold the initializer, it will then mark the
// variable as constant.
// Do not produce markers at -O0.
-// CHECK-O0-NOT: llvm.invariant.start
+// CHECK-O0-NOT: llvm.invariant.start.p0i8
struct A {
A();
@@ -42,19 +42,19 @@ void e() {
}
// CHECK: call void @_ZN1AC1Ev({{.*}}* nonnull @a)
-// CHECK: call {{.*}}@llvm.invariant.start(i64 4, i8* bitcast ({{.*}} @a to i8*))
+// CHECK: call {{.*}}@llvm.invariant.start.p0i8(i64 4, i8* bitcast ({{.*}} @a to i8*))
// CHECK: call void @_ZN1BC1Ev({{.*}}* nonnull @b)
-// CHECK-NOT: call {{.*}}@llvm.invariant.start(i64 4, i8* bitcast ({{.*}} @b to i8*))
+// CHECK-NOT: call {{.*}}@llvm.invariant.start.p0i8(i64 4, i8* bitcast ({{.*}} @b to i8*))
// CHECK: call void @_ZN1CC1Ev({{.*}}* nonnull @c)
-// CHECK-NOT: call {{.*}}@llvm.invariant.start(i64 4, i8* bitcast ({{.*}} @c to i8*))
+// CHECK-NOT: call {{.*}}@llvm.invariant.start.p0i8(i64 4, i8* bitcast ({{.*}} @c to i8*))
// CHECK: call i32 @_Z1fv(
// CHECK: store {{.*}}, i32* @d
-// CHECK: call {{.*}}@llvm.invariant.start(i64 4, i8* bitcast ({{.*}} @d to i8*))
+// CHECK: call {{.*}}@llvm.invariant.start.p0i8(i64 4, i8* bitcast ({{.*}} @d to i8*))
// CHECK-LABEL: define void @_Z1ev(
// CHECK: call void @_ZN1AC1Ev(%struct.A* nonnull @_ZZ1evE1a)
-// CHECK: call {{.*}}@llvm.invariant.start(i64 4, i8* {{.*}}bitcast ({{.*}} @_ZZ1evE1a to i8*))
+// CHECK: call {{.*}}@llvm.invariant.start.p0i8(i64 4, i8* {{.*}}bitcast ({{.*}} @_ZZ1evE1a to i8*))
// CHECK-NOT: llvm.invariant.end
diff --git a/test/CodeGenCXX/inline-dllexport-member.cpp b/test/CodeGenCXX/inline-dllexport-member.cpp
index 2160f32e0b4f..66ef459bd80b 100644
--- a/test/CodeGenCXX/inline-dllexport-member.cpp
+++ b/test/CodeGenCXX/inline-dllexport-member.cpp
@@ -1,11 +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]+]]
+
struct __declspec(dllexport) s {
static const unsigned int ui = 0;
};
-// CHECK: ![[SCOPE:[0-9]+]] = distinct !DICompileUnit(
-// CHECK: !DIGlobalVariable(name: "ui", linkageName: "\01?ui@s@@2IB", scope: ![[SCOPE]],
-// CHECK-SAME: variable: i32* @"\01?ui@s@@2IB"
+// CHECK: [[UI]] = !DIGlobalVariableExpression(var: [[UIV:.*]])
+// CHECK: [[UIV]] = distinct !DIGlobalVariable(name: "ui", linkageName: "\01?ui@s@@2IB", scope: ![[SCOPE:[0-9]+]],
+// CHECK: ![[SCOPE]] = distinct !DICompileUnit(
diff --git a/test/CodeGenCXX/inline-hint.cpp b/test/CodeGenCXX/inline-hint.cpp
index 9c14032f9f69..c4de751ba76e 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 -finline-functions -emit-llvm -disable-llvm-optzns -o - | FileCheck %s --check-prefix=CHECK --check-prefix=SUITABLE
-// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-linux -finline-hint-functions -emit-llvm -disable-llvm-optzns -o - | FileCheck %s --check-prefix=CHECK --check-prefix=HINTED
-// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-linux -fno-inline -emit-llvm -disable-llvm-optzns -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 %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
// Force non-trivial implicit constructors/destructors/operators for B by having explicit ones for A
struct A {
diff --git a/test/CodeGenCXX/invariant.group-for-vptrs.cpp b/test/CodeGenCXX/invariant.group-for-vptrs.cpp
index ca737ee23fb4..5c763538088b 100644
--- a/test/CodeGenCXX/invariant.group-for-vptrs.cpp
+++ b/test/CodeGenCXX/invariant.group-for-vptrs.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -emit-llvm %s -fstrict-vtable-pointers -O1 -o - -disable-llvm-optzns | FileCheck %s
+// RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -emit-llvm %s -fstrict-vtable-pointers -O1 -o - -disable-llvm-passes | FileCheck %s
struct A {
virtual void foo();
@@ -23,7 +23,7 @@ void testExternallyVisible() {
// CHECK: load {{.*}} !invariant.group ![[A_MD]]
a2->foo();
}
-// CHECK-LABEL: }
+// CHECK-LABEL: {{^}}}
namespace {
@@ -52,7 +52,7 @@ void testInternallyVisible(bool p) {
// Checking A::A()
// CHECK-LABEL: define linkonce_odr void @_ZN1AC2Ev(
// CHECK: store {{.*}}, !invariant.group ![[A_MD]]
-// CHECK-LABEL: }
+// CHECK-LABEL: {{^}}}
// Checking D::D()
// CHECK-LABEL: define linkonce_odr void @_ZN1DC2Ev(
diff --git a/test/CodeGenCXX/key-function-vtable.cpp b/test/CodeGenCXX/key-function-vtable.cpp
index f6aa16e51a97..028017c176ad 100644
--- a/test/CodeGenCXX/key-function-vtable.cpp
+++ b/test/CodeGenCXX/key-function-vtable.cpp
@@ -44,8 +44,8 @@ inline void X1::f() { }
void use_X1() { X1 x1; }
// CHECK-DAG: @_ZTV2X1 = linkonce_odr unnamed_addr constant
-// CHECK-DAG: @_ZTV5testa = unnamed_addr constant [3 x i8*] [i8* null
-// CHECK-DAG: @_ZTV5testc = linkonce_odr unnamed_addr constant [3 x i8*] [i8* null
-// CHECK-DAG: @_ZTV5testb = linkonce_odr unnamed_addr constant [3 x i8*] [i8* null
-// CHECK-DAG: @_ZTV5teste = linkonce_odr unnamed_addr constant [3 x i8*] [i8* null
-// CHECK-DAG: @_ZTVN12_GLOBAL__N_15testgE = internal unnamed_addr constant [3 x i8*] [i8* null
+// CHECK-DAG: @_ZTV5testa = unnamed_addr constant { [3 x i8*] } { [3 x i8*] [i8* null
+// CHECK-DAG: @_ZTV5testc = linkonce_odr unnamed_addr constant { [3 x i8*] } { [3 x i8*] [i8* null
+// CHECK-DAG: @_ZTV5testb = linkonce_odr unnamed_addr constant { [3 x i8*] } { [3 x i8*] [i8* null
+// CHECK-DAG: @_ZTV5teste = linkonce_odr unnamed_addr constant { [3 x i8*] } { [3 x i8*] [i8* null
+// CHECK-DAG: @_ZTVN12_GLOBAL__N_15testgE = internal unnamed_addr constant { [3 x i8*] } { [3 x i8*] [i8* null
diff --git a/test/CodeGenCXX/lambda-expressions.cpp b/test/CodeGenCXX/lambda-expressions.cpp
index f59d360314e4..2c625daaf831 100644
--- a/test/CodeGenCXX/lambda-expressions.cpp
+++ b/test/CodeGenCXX/lambda-expressions.cpp
@@ -54,12 +54,14 @@ int c(int x) { return [&x]{return x;}(); }
// CHECK: ret i32
struct D { D(); D(const D&); int x; };
-int d(int x) { D y[10]; [x,y] { return y[x].x; }(); }
+int d(int x) { D y[10]; return [x,y] { return y[x].x; }(); }
// CHECK-LABEL: define i32 @_Z1di
// CHECK: call void @_ZN1DC1Ev
-// CHECK: icmp ult i64 %{{.*}}, 10
+// CHECK: br label
// CHECK: call void @_ZN1DC1ERKS_
+// CHECK: icmp eq i64 %{{.*}}, 10
+// CHECK: br i1
// CHECK: call i32 @"_ZZ1diENK3$_4clEv"
// CHECK-LABEL: define internal i32 @"_ZZ1diENK3$_4clEv"
// CHECK: load i32, i32*
@@ -67,7 +69,7 @@ int d(int x) { D y[10]; [x,y] { return y[x].x; }(); }
// CHECK: ret i32
struct E { E(); E(const E&); ~E(); int x; };
-int e(E a, E b, bool cond) { [a,b,cond](){ return (cond ? a : b).x; }(); }
+int e(E a, E b, bool cond) { return [a,b,cond](){ return (cond ? a : b).x; }(); }
// CHECK-LABEL: define i32 @_Z1e1ES_b
// CHECK: call void @_ZN1EC1ERKS_
// CHECK: invoke void @_ZN1EC1ERKS_
@@ -116,6 +118,72 @@ int *PR22071_fun() {
return [&] { return &y; }();
}
+namespace pr28595 {
+ struct Temp {
+ Temp();
+ ~Temp() noexcept(false);
+ };
+ struct A {
+ A();
+ A(const A &a, const Temp &temp = Temp());
+ ~A();
+ };
+
+ void after_init() noexcept;
+
+ // CHECK-LABEL: define void @_ZN7pr285954testEv()
+ void test() {
+ // CHECK: %[[SRC:.*]] = alloca [3 x [5 x %[[A:.*]]]], align 1
+ A array[3][5];
+
+ // Skip over the initialization loop.
+ // CHECK: call {{.*}}after_init
+ after_init();
+
+ // CHECK: %[[DST_0:.*]] = getelementptr {{.*}} [3 x [5 x %[[A]]]]* %[[DST:.*]], i64 0, i64 0
+ // CHECK: br label
+ // CHECK: %[[I:.*]] = phi i64 [ 0, %{{.*}} ], [ %[[I_NEXT:.*]], {{.*}} ]
+ // CHECK: %[[DST_I:.*]] = getelementptr {{.*}} [5 x %[[A]]]* %[[DST_0]], i64 %[[I]]
+ // CHECK: %[[SRC_I:.*]] = getelementptr {{.*}} [3 x [5 x %[[A]]]]* %[[SRC]], i64 0, i64 %[[I]]
+ //
+ // CHECK: %[[DST_I_0:.*]] = getelementptr {{.*}} [5 x %[[A]]]* %[[DST_I]], i64 0, i64 0
+ // CHECK: br label
+ // CHECK: %[[J:.*]] = phi i64 [ 0, %{{.*}} ], [ %[[J_NEXT:.*]], {{.*}} ]
+ // CHECK: %[[DST_I_J:.*]] = getelementptr {{.*}} %[[A]]* %[[DST_I_0]], i64 %[[J]]
+ // CHECK: %[[DST_0_0:.*]] = bitcast [5 x %[[A]]]* %[[DST_0]] to %[[A]]*
+ // CHECK: %[[SRC_I_J:.*]] = getelementptr {{.*}} [5 x %[[A]]]* %[[SRC_I]], i64 0, i64 %[[J]]
+ //
+ // CHECK: invoke void @_ZN7pr285954TempC1Ev
+ // CHECK: invoke void @_ZN7pr285951AC1ERKS0_RKNS_4TempE
+ // CHECK: invoke void @_ZN7pr285954TempD1Ev
+ //
+ // CHECK: add nuw i64 %[[J]], 1
+ // CHECK: icmp eq
+ // CHECK: br i1
+ //
+ // CHECK: add nuw i64 %[[I]], 1
+ // CHECK: icmp eq
+ // CHECK: br i1
+ //
+ // CHECK: ret void
+ //
+ // CHECK: landingpad
+ // CHECK: landingpad
+ // CHECK: br label %[[CLEANUP:.*]]{{$}}
+ // CHECK: landingpad
+ // CHECK: invoke void @_ZN7pr285954TempD1Ev
+ // CHECK: br label %[[CLEANUP]]
+ //
+ // CHECK: [[CLEANUP]]:
+ // CHECK: icmp eq %[[A]]* %[[DST_0_0]], %[[DST_I_J]]
+ // CHECK: %[[T0:.*]] = phi %[[A]]*
+ // CHECK: %[[T1:.*]] = getelementptr inbounds %[[A]], %[[A]]* %[[T0]], i64 -1
+ // CHECK: call void @_ZN7pr285951AD1Ev(%[[A]]* %[[T1]])
+ // CHECK: icmp eq %[[A]]* %[[T1]], %[[DST_0_0]]
+ (void) [array]{};
+ }
+}
+
// CHECK-LABEL: define internal void @"_ZZ1e1ES_bEN3$_5D2Ev"
// CHECK-LABEL: define internal i32 @"_ZZ1fvEN3$_68__invokeEii"
@@ -126,9 +194,9 @@ int *PR22071_fun() {
// CHECK-NEXT: call i32 @"_ZZ1fvENK3$_6clEii"
// CHECK-NEXT: ret i32
-// CHECK-LABEL: define internal void @"_ZZ1hvEN4$_108__invokeEv"(%struct.A* noalias sret %agg.result) {{.*}} {
+// CHECK-LABEL: define internal void @"_ZZ1hvEN4$_118__invokeEv"(%struct.A* noalias sret %agg.result) {{.*}} {
// CHECK-NOT: =
-// CHECK: call void @"_ZZ1hvENK4$_10clEv"(%struct.A* sret %agg.result,
+// CHECK: call void @"_ZZ1hvENK4$_11clEv"(%struct.A* sret %agg.result,
// CHECK-NEXT: ret void
struct A { ~A(); };
void h() {
diff --git a/test/CodeGenCXX/linkage.cpp b/test/CodeGenCXX/linkage.cpp
index 60e53c6444e2..69b426269ccd 100644
--- a/test/CodeGenCXX/linkage.cpp
+++ b/test/CodeGenCXX/linkage.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -std=c++11 -O1 -disable-llvm-optzns %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -std=c++11 -O1 -disable-llvm-passes %s -o - | FileCheck %s
namespace test1 {
// CHECK-DAG: define linkonce_odr void @_ZN5test11fIZNS_1gEvE1SEEvT_(
diff --git a/test/CodeGenCXX/main-norecurse.cpp b/test/CodeGenCXX/main-norecurse.cpp
index 0f3640260962..a98677ce6f59 100644
--- a/test/CodeGenCXX/main-norecurse.cpp
+++ b/test/CodeGenCXX/main-norecurse.cpp
@@ -5,4 +5,4 @@ int main(int argc, char **argv) {
return 1;
}
-// CHECK: attributes #0 = { norecurse{{.*}} }
+// CHECK: attributes #0 = { noinline norecurse{{.*}} }
diff --git a/test/CodeGenCXX/mangle-abi-tag.cpp b/test/CodeGenCXX/mangle-abi-tag.cpp
index 385a16f26a51..a653ff42228a 100644
--- a/test/CodeGenCXX/mangle-abi-tag.cpp
+++ b/test/CodeGenCXX/mangle-abi-tag.cpp
@@ -203,3 +203,32 @@ void f18_test() {
}
// A18::operator A[abi:A][abi:B]() but GCC adds the same tags twice!
// CHECK-DAG: define linkonce_odr {{.+}} @_ZN3A18cv1AB1AB1BEv(
+
+namespace N19 {
+ class A {};
+ class __attribute__((abi_tag("B"))) B {};
+ class D {};
+ class F {};
+
+ template<typename T, B F(T, D)>
+ class C {};
+
+ B foo(A, D);
+}
+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_(
+
+namespace pr30440 {
+
+template<class F> void g(F);
+template<class ...A> auto h(A ...a)->decltype (g (0, g < a > (a) ...)) {
+}
+// CHECK-DAG: define {{.*}} @_ZN7pr304401hIJEEEDTcl1gLi0Espcl1gIL_ZZNS_1hEDpT_E1aEEfp_EEES2_(
+
+void pr30440_test () {
+ h();
+}
+
+}
diff --git a/test/CodeGenCXX/mangle-exception-spec.cpp b/test/CodeGenCXX/mangle-exception-spec.cpp
new file mode 100644
index 000000000000..15f7a8b6cb50
--- /dev/null
+++ b/test/CodeGenCXX/mangle-exception-spec.cpp
@@ -0,0 +1,49 @@
+// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -Wno-dynamic-exception-spec | FileCheck %s --check-prefix CHECK --check-prefix CHECK-CXX11
+// RUN: %clang_cc1 -std=c++1z -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -Wno-dynamic-exception-spec | FileCheck %s --check-prefix CHECK --check-prefix CHECK-CXX17
+
+// CHECK: define {{.*}} @_Z1aPFivE(
+void a(int() throw(int, float)) {}
+// CHECK-CXX11: define {{.*}} @_Z1bPFivE(
+// CHECK-CXX17: define {{.*}} @_Z1bPDoFivE(
+void b(int() noexcept) {}
+// CHECK-CXX11: define {{.*}} @_Z1cPFivE(
+// CHECK-CXX17: define {{.*}} @_Z1cPDoFivE(
+void c(int() throw()) {}
+// CHECK: define {{.*}} @_Z1dPFivE(
+void d(int() noexcept(false)) {}
+// CHECK-CXX11: define {{.*}} @_Z1ePFivE(
+// CHECK-CXX17: define {{.*}} @_Z1ePDoFivE(
+void e(int() noexcept(true)) {}
+
+template<bool B> void f(int() noexcept(B)) {}
+// CHECK: define {{.*}} @_Z1fILb0EEvPDOT_EFivE(
+template void f<false>(int());
+// CHECK: define {{.*}} @_Z1fILb1EEvPDOT_EFivE(
+template void f<true>(int() noexcept);
+
+template<typename...T> void g(int() throw(T...)) {}
+// CHECK: define {{.*}} @_Z1gIJEEvPDwDpT_EFivE(
+template void g<>(int() noexcept);
+// CHECK: define {{.*}} @_Z1gIJfEEvPDwDpT_EFivE(
+template void g<float>(int());
+
+// We consider the exception specifications in parameter and return type here
+// to be different.
+template<typename...T> auto h(int() throw(int, T...)) -> int (*)() throw(T..., int) { return nullptr; }
+// CHECK: define {{.*}} @_Z1hIJEEPDwDpT_iEFivEPDwiS1_EFivE(
+template auto h<>(int()) -> int (*)();
+// CHECK: define {{.*}} @_Z1hIJfEEPDwDpT_iEFivEPDwiS1_EFivE(
+template auto h<float>(int()) -> int (*)();
+
+// FIXME: The C++11 manglings here are wrong; they should be the same as the
+// C++17 manglings.
+// The mangler mishandles substitutions for instantiation-dependent types that
+// differ only in type sugar that is not relevant for mangling. (In this case,
+// the types differ in presence/absence of ParenType nodes under the pointer.)
+template<typename...T> auto i(int() throw(int, T...)) -> int (*)() throw(int, T...) { return nullptr; }
+// CHECK-CXX11: define {{.*}} @_Z1iIJEEPDwiDpT_EFivEPS2_(
+// CHECK-CXX17: define {{.*}} @_Z1iIJEEPDwiDpT_EFivES3_(
+template auto i<>(int()) -> int (*)();
+// CHECK-CXX11: define {{.*}} @_Z1iIJfEEPDwiDpT_EFivEPS2_(
+// CHECK-CXX17: define {{.*}} @_Z1iIJfEEPDwiDpT_EFivES3_(
+template auto i<float>(int()) -> int (*)();
diff --git a/test/CodeGenCXX/mangle-lambdas.cpp b/test/CodeGenCXX/mangle-lambdas.cpp
index 051cfdc3a221..15987ebe46bd 100644
--- a/test/CodeGenCXX/mangle-lambdas.cpp
+++ b/test/CodeGenCXX/mangle-lambdas.cpp
@@ -173,6 +173,16 @@ namespace PR12123 {
// CHECK-LABEL: define linkonce_odr dereferenceable({{[0-9]+}}) %"struct.PR12123::A"* @_ZZN7PR121231B1fERKSt9type_infoEd_NKUlvE_clEv
+// CHECK-LABEL: define {{.*}} @_Z{{[0-9]*}}testVarargsLambdaNumberingv(
+inline int testVarargsLambdaNumbering() {
+ // CHECK: testVarargsLambdaNumberingvE{{.*}}UlzE_
+ auto a = [](...) { static int n; return ++n; };
+ // CHECK: testVarargsLambdaNumberingvE{{.*}}UlvE_
+ auto b = []() { static int n; return ++n; };
+ return a() + b();
+}
+int k = testVarargsLambdaNumbering();
+
// Check linkage of the various lambdas.
// CHECK-LABEL: define linkonce_odr i32 @_ZZ11inline_funciENKUlvE_clEv
// CHECK: ret i32 1
diff --git a/test/CodeGenCXX/mangle-ms-cxx11.cpp b/test/CodeGenCXX/mangle-ms-cxx11.cpp
index 8e2577b03e26..819b0d9c9d0d 100644
--- a/test/CodeGenCXX/mangle-ms-cxx11.cpp
+++ b/test/CodeGenCXX/mangle-ms-cxx11.cpp
@@ -318,3 +318,32 @@ void unaligned_foo8_S::unaligned_foo8() volatile __unaligned {}
// CHECK-DAG: @"\01?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"(
+ int *x = []() {
+ static int white;
+ // CHECK-DAG: @"\01?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"(
+ int *y = []() {
+ static int black;
+ // CHECK-DAG: @"\01?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"(
+};
+A a;
+
+int call_it = (A::default_args(), 1);
+}
+
+enum { enumerator };
+void f(decltype(enumerator)) {}
+// CHECK-DAG: define void @"\01?f@@YAXW4<unnamed-enum-enumerator>@@@Z"(
diff --git a/test/CodeGenCXX/mangle-unnamed.cpp b/test/CodeGenCXX/mangle-unnamed.cpp
index a62bdd5393c4..43b7bd79537d 100644
--- a/test/CodeGenCXX/mangle-unnamed.cpp
+++ b/test/CodeGenCXX/mangle-unnamed.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin10 | FileCheck %s
+// RUN: %clang_cc1 -std=c++98 -emit-llvm %s -o - -triple=x86_64-apple-darwin10 | FileCheck %s
+// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=x86_64-apple-darwin10 | FileCheck %s
struct S {
virtual ~S() { }
diff --git a/test/CodeGenCXX/mangle.cpp b/test/CodeGenCXX/mangle.cpp
index 5d757102ed25..3a94071294d3 100644
--- a/test/CodeGenCXX/mangle.cpp
+++ b/test/CodeGenCXX/mangle.cpp
@@ -1111,3 +1111,17 @@ void fn(T, __underlying_type(T)) {}
template void fn<E>(E, __underlying_type(E));
// CHECK-LABEL: @_ZN6test552fnINS_1EEEEvT_U3eutS2_
}
+
+namespace test56 {
+ struct A { A *operator->(); int n; } a;
+ template<int N> void f(decltype(a->n + N)) {}
+ // CHECK-LABEL: @_ZN6test561fILi0EEEvDTplptL_ZNS_1aEE1nT_E
+ template void f<0>(int);
+}
+
+namespace test57 {
+ struct X { template <int N> int f(); } x;
+ template<int N> void f(decltype(x.f<0>() + N)) {}
+ // CHECK-LABEL: @_ZN6test571fILi0EEEvDTplcldtL_ZNS_1xEE1fIXLi0EEEET_E
+ template void f<0>(int);
+}
diff --git a/test/CodeGenCXX/microsoft-abi-array-cookies.cpp b/test/CodeGenCXX/microsoft-abi-array-cookies.cpp
index 9ef1879ce5f2..146a6c8eda06 100644
--- a/test/CodeGenCXX/microsoft-abi-array-cookies.cpp
+++ b/test/CodeGenCXX/microsoft-abi-array-cookies.cpp
@@ -68,4 +68,4 @@ struct S {
void delete_s(S *s) { delete[] s; }
}
-// CHECK: attributes [[NUW]] = { nounwind{{.*}} }
+// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} }
diff --git a/test/CodeGenCXX/microsoft-abi-constexpr-vs-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-constexpr-vs-inheritance.cpp
index 319f39c3ff48..6972dacd774f 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: @"\01?a@@3UA@@A" = global { { [1 x i8*] }*, i32 } { { [1 x i8*] }* @"\01??_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: @"\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 }
diff --git a/test/CodeGenCXX/microsoft-abi-eh-catch.cpp b/test/CodeGenCXX/microsoft-abi-eh-catch.cpp
index ac1321efeae2..6e18b92e0f41 100644
--- a/test/CodeGenCXX/microsoft-abi-eh-catch.cpp
+++ b/test/CodeGenCXX/microsoft-abi-eh-catch.cpp
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=x86_64-pc-windows-msvc \
// RUN: -mconstructor-aliases -fexceptions -fcxx-exceptions \
-// RUN: -O1 -disable-llvm-optzns \
+// RUN: -O1 -disable-llvm-passes \
// RUN: | FileCheck -check-prefix WIN64 %s
extern "C" void might_throw();
diff --git a/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp b/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp
index 004dc45652e4..79ac1e12173b 100644
--- a/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp
+++ b/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fexceptions -fcxx-exceptions -fno-rtti | FileCheck -check-prefix WIN32 -check-prefix WIN32-O0 %s
-// RUN: %clang_cc1 -std=c++11 -emit-llvm -O3 -disable-llvm-optzns %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fexceptions -fcxx-exceptions -fno-rtti | FileCheck -check-prefix WIN32 -check-prefix WIN32-O3 -check-prefix WIN32-LIFETIME %s
+// RUN: %clang_cc1 -std=c++11 -emit-llvm -O3 -disable-llvm-passes %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fexceptions -fcxx-exceptions -fno-rtti | FileCheck -check-prefix WIN32 -check-prefix WIN32-O3 -check-prefix WIN32-LIFETIME %s
struct A {
A();
@@ -278,3 +278,38 @@ void f() {
// WIN32-LIFETIME: %[[bc2:.*]] = bitcast %"struct.lifetime_marker::C"* %[[c]] to i8*
// WIN32-LIFETIME: call void @llvm.lifetime.end(i64 1, i8* %[[bc2]])
}
+
+struct class_2 {
+ class_2();
+ virtual ~class_2();
+};
+struct class_1 : virtual class_2 {
+ class_1(){throw "Unhandled exception";}
+ virtual ~class_1() {}
+};
+struct class_0 : class_1 {
+ class_0() ;
+ virtual ~class_0() {}
+};
+
+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: 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
+ // WIN32: br i1 %[[SHOULD_CALL_VBASE_CTORS]], label %[[INIT_VBASES:.*]], label %[[SKIP_VBASES:.*]]
+ // WIN32: [[INIT_VBASES]]
+ // WIN32: br label %[[SKIP_VBASES]]
+ // WIN32: [[SKIP_VBASES]]
+// ehcleanup:
+ // WIN32: %[[CLEANUPPAD:.*]] = cleanuppad within none []
+ // WIN32-NEXT: bitcast %{{.*}}* %{{.*}} to i8*
+ // WIN32-NEXT: getelementptr inbounds i8, i8* %{{.*}}, i{{.*}} {{.}}
+ // WIN32-NEXT: bitcast i8* %{{.*}} to %{{.*}}*
+ // 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: br label %[[SKIP_VBASE]]
+ // WIN32: [[SKIP_VBASE]]
+}
diff --git a/test/CodeGenCXX/microsoft-abi-extern-template.cpp b/test/CodeGenCXX/microsoft-abi-extern-template.cpp
index de46d5b5c37c..c69b4f5b8d86 100644
--- a/test/CodeGenCXX/microsoft-abi-extern-template.cpp
+++ b/test/CodeGenCXX/microsoft-abi-extern-template.cpp
@@ -1,11 +1,11 @@
-// RUN: %clang_cc1 -fno-rtti-data -O1 -disable-llvm-optzns %s -emit-llvm -o - -triple x86_64-windows-msvc | FileCheck %s
+// RUN: %clang_cc1 -fno-rtti-data -O1 -disable-llvm-passes %s -emit-llvm -o - -triple x86_64-windows-msvc | FileCheck %s
// 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*] [
+// 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-SAME: ], comdat
+// 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* %{{.*}})
diff --git a/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp
index 34cb85ec28d1..f9db2680e336 100644
--- a/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp
+++ b/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp
@@ -150,35 +150,35 @@ void emit_ctors() {
Left l;
// CHECK: define {{.*}} @"\01??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*] }* @"\01??_7Left@@6B@" to i32 (...)**)
// CHECK: ret
Right r;
// CHECK: define {{.*}} @"\01??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*] }* @"\01??_7Right@@6B@" to i32 (...)**)
// CHECK: ret
ChildOverride co;
// CHECK: define {{.*}} @"\01??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*] }* @"\01??_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*] }* @"\01??_7ChildOverride@@6BRight@@@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
// CHECK: ret
GrandchildOverride gc;
// CHECK: define {{.*}} @"\01??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*] }* @"\01??_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*] }* @"\01??_7GrandchildOverride@@6BRight@@@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
// CHECK: ret
}
diff --git a/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp b/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
index f7dc52406740..7eea41c8712e 100644
--- a/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
+++ b/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
@@ -1,6 +1,7 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-linux | FileCheck -check-prefix LINUX %s
-// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fno-rtti | FileCheck -check-prefix WIN32 %s
-// RUN: %clang_cc1 -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=i386-pc-linux | FileCheck -check-prefix LINUX %s
+// 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
struct Empty {};
@@ -92,6 +93,9 @@ 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)
+// 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)
SmallWithVftable small_with_vftable_return() { return SmallWithVftable(); }
// LINUX-LABEL: define void @_Z25small_with_vftable_returnv(%struct.SmallWithVftable* noalias sret %agg.result)
@@ -102,6 +106,7 @@ 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)
// Returning a large struct that doesn't fit into a register.
Big big_return() { return Big(); }
@@ -114,22 +119,26 @@ 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)
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)
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)
// 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)
void packed_arg(Packed s) {}
// LINUX-LABEL: define void @_Z10packed_arg6Packed(%struct.Packed* byval align 4 %s)
@@ -145,6 +154,11 @@ void small_arg_with_dtor(SmallWithDtor s) {}
// WIN64: call void @"\01??1SmallWithDtor@@QEAA@XZ"
// WIN64: }
+// 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: }
+
void call_small_arg_with_dtor() {
small_arg_with_dtor(SmallWithDtor());
}
@@ -211,6 +225,7 @@ 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)
void big_arg(Big s) {}
// LINUX-LABEL: define void @_Z7big_arg3Big(%struct.Big* byval align 4 %s)
@@ -386,3 +401,30 @@ void fn2(FnPtr1 a, SmallWithDtor b) { fn1(a, b); };
// 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]])
+
+namespace pr30293 {
+// Virtual methods living in a secondary vtable take i8* as their 'this'
+// parameter because the 'this' parameter on entry points to the secondary
+// vptr. We used to have a bug where we didn't apply this rule consistently,
+// and it would cause assertion failures when used with inalloca.
+struct A {
+ virtual void f();
+};
+struct B {
+ virtual void __cdecl h(SmallWithDtor);
+};
+struct C final : A, B {
+ void g();
+ void __cdecl h(SmallWithDtor);
+ void f();
+};
+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)
+
+// WIN64-LABEL: define void @"\01?g@C@pr30293@@QEAAXXZ"(%"struct.pr30293::C"* %this)
+// WIN64: declare void @"\01?h@C@pr30293@@UEAAXUSmallWithDtor@@@Z"(i8*, i32)
+}
diff --git a/test/CodeGenCXX/microsoft-abi-structors-alias.cpp b/test/CodeGenCXX/microsoft-abi-structors-alias.cpp
index 08df374f2fc9..4eb757af3f8b 100644
--- a/test/CodeGenCXX/microsoft-abi-structors-alias.cpp
+++ b/test/CodeGenCXX/microsoft-abi-structors-alias.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -fno-rtti -mconstructor-aliases -O1 -disable-llvm-optzns | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -fno-rtti -mconstructor-aliases -O1 -disable-llvm-passes | FileCheck %s
namespace test1 {
template <typename T> class A {
diff --git a/test/CodeGenCXX/microsoft-abi-structors.cpp b/test/CodeGenCXX/microsoft-abi-structors.cpp
index a576f0c3d7e3..6397eeb7313f 100644
--- a/test/CodeGenCXX/microsoft-abi-structors.cpp
+++ b/test/CodeGenCXX/microsoft-abi-structors.cpp
@@ -77,7 +77,7 @@ 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*] }* @"\01??_7C@basic@@6B@" to i32 (...)**), i32 (...)*** [[THIS_PTR]]
}
void call_complete_dtor(C *obj_ptr) {
@@ -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 x86_thiscallcc void @"\01??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
diff --git a/test/CodeGenCXX/microsoft-abi-vftables.cpp b/test/CodeGenCXX/microsoft-abi-vftables.cpp
index 0c9b58bbb4d4..968955f4ee1b 100644
--- a/test/CodeGenCXX/microsoft-abi-vftables.cpp
+++ b/test/CodeGenCXX/microsoft-abi-vftables.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 %s -fno-rtti -triple=i386-pc-win32 -fms-extensions -emit-llvm -o - -O1 -disable-llvm-optzns | FileCheck %s -check-prefix=NO-RTTI
-// RUN: %clang_cc1 %s -triple=i386-pc-win32 -fms-extensions -emit-llvm -o - -O1 -disable-llvm-optzns | FileCheck %s -check-prefix=RTTI
+// 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
@@ -8,38 +8,38 @@ struct S {
virtual ~S();
} s;
-// RTTI-DAG: [[VTABLE_S:@.*]] = private unnamed_addr constant [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 1)
+// 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)
-// NO-RTTI-DAG: @"\01??_7S@@6B@" = linkonce_odr unnamed_addr constant [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GS@@UAEPAXI@Z" to i8*)]
+// 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*)] }
struct __declspec(dllimport) U {
virtual ~U();
} u;
-// RTTI-DAG: [[VTABLE_U:@.*]] = private unnamed_addr constant [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 1)
+// 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)
-// NO-RTTI-DAG: @"\01??_SU@@6B@" = linkonce_odr unnamed_addr constant [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GU@@UAEPAXI@Z" to i8*)]
+// 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*)] }
struct __declspec(dllexport) V {
virtual ~V();
} v;
-// RTTI-DAG: [[VTABLE_V:@.*]] = private unnamed_addr constant [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 1)
+// 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)
-// NO-RTTI-DAG: @"\01??_7V@@6B@" = weak_odr dllexport unnamed_addr constant [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GV@@UAEPAXI@Z" to i8*)]
+// 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*)] }
namespace {
struct W {
virtual ~W() {}
} w;
}
-// RTTI-DAG: [[VTABLE_W:@.*]] = private unnamed_addr constant [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 1)
+// 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)
-// NO-RTTI-DAG: @"\01??_7W@?A@@6B@" = internal unnamed_addr constant [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GW@?A@@UAEPAXI@Z" to i8*)]
+// 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*)] }
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*] [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 1)
+// 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)
-// NO-RTTI-DAG: @"\01??_7?$Y@H@@6B@" = linkonce_odr unnamed_addr constant [1 x i8*] [i8* bitcast (i8* (%struct.Y*, i32)* @"\01??_G?$Y@H@@UAEPAXI@Z" to i8*)], comdat
+// 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
diff --git a/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp
index 480ae8cfbbec..416aefa6b715 100644
--- a/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp
+++ b/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp
@@ -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*] }* @"\01??_7B@@6B@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
// Initialize vtorDisp:
// CHECK: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
@@ -66,7 +66,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*] }* @"\01??_7B@@6B@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
// Initialize vtorDisp:
// CHECK: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
@@ -245,9 +245,9 @@ 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"
// 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*] }* @"\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 %{{.*}}, i32* %{{.*}}
// CHECK: store i32 %{{.*}}, i32* %{{.*}}
@@ -283,7 +283,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 x86_thiscallcc void @"\01??1D@diamond@@UAE@XZ"(%"struct.diamond::D"*{{.*}})
// CHECK: %[[ARG_i8:.*]] = bitcast %"struct.diamond::D"* %{{.*}} to i8*
// CHECK: %[[THIS_i8:.*]] = getelementptr inbounds i8, i8* %[[ARG_i8]], i32 -24
// CHECK: %[[THIS:.*]] = bitcast i8* %[[THIS_i8]] to %"struct.diamond::D"*
@@ -397,7 +397,7 @@ C::~C() {
// 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*] }* @"\01??_7C@test4@@6BB@1@@" to i32 (...)**), i32 (...)*** %[[VFPTR_i8]]
foo(this);
// CHECK: ret
@@ -432,7 +432,7 @@ E::~E() {
// 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*] }* @"\01??_7E@test4@@6BD@1@@" to i32 (...)**), i32 (...)*** %[[VFPTR_i8]]
foo(this);
}
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 aaee39c51db6..b97c432f5e02 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
@@ -177,3 +177,26 @@ void fop(C &c) {
}
}
+
+namespace pr30293 {
+struct NonTrivial {
+ ~NonTrivial();
+ int x;
+};
+struct A { virtual void f(); };
+struct B { virtual void __cdecl g(NonTrivial); };
+struct C final : A, B {
+ void f() override;
+ void __cdecl g(NonTrivial) override;
+};
+C *whatsthis;
+void C::f() { g(NonTrivial()); }
+void C::g(NonTrivial o) {
+ whatsthis = this;
+}
+
+// BITCODE-LABEL: define void @"\01?g@C@pr30293@@UAAXUNonTrivial@2@@Z"(<{ i8*, %"struct.pr30293::NonTrivial" }>* inalloca)
+// BITCODE: %[[this1:[^ ]*]] = load i8*, i8** %[[thisaddr:[^ ]*]], align 4
+// BITCODE-NEXT: %[[this2:[^ ]*]] = getelementptr inbounds i8, i8* %[[this1]], i32 -4
+// BITCODE-NEXT: store i8* %[[this2]], i8** %[[thisaddr]], align 4
+}
diff --git a/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp b/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp
index d22344840c19..2bf7da58ea9c 100644
--- a/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp
+++ b/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp
@@ -26,7 +26,7 @@ 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-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"
@@ -44,7 +44,7 @@ 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-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"
@@ -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: @"\01??_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: @"\01??_7K@test2@@6B@" = linkonce_odr unnamed_addr constant { [3 x i8*] }
}
@@ -124,7 +124,7 @@ struct C : virtual A, B {
C::C() {}
-// GLOBALS-LABEL: @"\01??_7C@pr20479@@6B@" = linkonce_odr unnamed_addr constant [2 x i8*]
+// 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"
}
@@ -151,7 +151,7 @@ struct C : virtual A, virtual B {
C::C() {}
-// GLOBALS-LABEL: @"\01??_7C@pr21073@@6B@" = linkonce_odr unnamed_addr constant [2 x i8*]
+// 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"
}
@@ -168,7 +168,7 @@ 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-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"
}
@@ -196,7 +196,7 @@ 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-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"
diff --git a/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp
index aa39d6de615a..738c15d89d21 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: @"\01??_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: @"\01??_7B@@6B@" = linkonce_odr unnamed_addr constant { [5 x i8*] }
void use(B *obj) { obj->f(); }
struct C {
@@ -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: @"\01??_7D@@6B@" = linkonce_odr unnamed_addr constant { [2 x i8*] }
void use(D *obj) { obj->f(); }
struct E : 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: @"\01??_7F@@6B@" = linkonce_odr unnamed_addr constant { [5 x i8*] }
void use(F *obj) { obj->i(); }
struct G : E {
@@ -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*] [i8* bitcast (void ()* @_purecall to i8*)]
+ // EMITS-VFTABLE-DAG: @"\01??_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.cpp b/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp
index 83f8114bae99..342a584182cc 100644
--- a/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp
+++ b/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp
@@ -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*] [i8* bitcast (void ()* @_purecall to i8*)]
+ // MANGLING-DAG: @"\01??_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: @"\01??_7C@pr21031_1@@6BB@1@@" = {{.*}} constant { [1 x i8*] }
+// MANGLING-DAG: @"\01??_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: @"\01??_7C@pr21031_2@@6BA@1@@" = {{.*}} constant { [1 x i8*] }
+// MANGLING-DAG: @"\01??_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: @"\01??_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: @"\01??_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: @"\01??_7D@pr21064@@6B@" = {{.*}} constant { [1 x i8*] }
}
diff --git a/test/CodeGenCXX/microsoft-interface.cpp b/test/CodeGenCXX/microsoft-interface.cpp
index 8f4670a6946a..5f3a94a494b7 100644
--- a/test/CodeGenCXX/microsoft-interface.cpp
+++ b/test/CodeGenCXX/microsoft-interface.cpp
@@ -17,7 +17,7 @@ int fn() {
return s.test();
}
-// CHECK: @_ZTV1S = linkonce_odr unnamed_addr constant [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 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: call x86_thiscallcc void @_ZN1SC1Ev(%struct.S* %s)
@@ -31,10 +31,10 @@ int fn() {
// CHECK-LABEL: define linkonce_odr 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, i32 2) to i32 (...)**), i32 (...)*** %{{[.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: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1I, i32 0, i32 2) to i32 (...)**), i32 (...)*** %{{[.0-9A-Z_a-z]+}}
+// 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: ret i32 1
diff --git a/test/CodeGenCXX/microsoft-no-rtti-data.cpp b/test/CodeGenCXX/microsoft-no-rtti-data.cpp
index 68fdf0586c0d..05255909ced3 100644
--- a/test/CodeGenCXX/microsoft-no-rtti-data.cpp
+++ b/test/CodeGenCXX/microsoft-no-rtti-data.cpp
@@ -2,7 +2,7 @@
// 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*] [i8* bitcast ({{.*}} @"\01??_GS@@UAEPAXI@Z" to i8*)], comdat
+// CHECK: @"\01??_7S@@6B@" = linkonce_odr unnamed_addr constant { [1 x i8*] } { [1 x i8*] [i8* bitcast ({{.*}} @"\01??_GS@@UAEPAXI@Z" to i8*)] }, comdat
struct type_info;
namespace std { using ::type_info; }
diff --git a/test/CodeGenCXX/microsoft-uuidof.cpp b/test/CodeGenCXX/microsoft-uuidof.cpp
index 62e4b880ad46..9b4ff68d9aa8 100644
--- a/test/CodeGenCXX/microsoft-uuidof.cpp
+++ b/test/CodeGenCXX/microsoft-uuidof.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -emit-llvm %s -o - -DDEFINE_GUID -triple=i386-pc-linux -fms-extensions | FileCheck %s --check-prefix=CHECK-DEFINE-GUID
+// RUN: %clang_cc1 -emit-llvm %s -o - -DDEFINE_GUID -DBRACKET_ATTRIB -triple=i386-pc-linux -fms-extensions | FileCheck %s --check-prefix=CHECK-DEFINE-GUID
// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-linux -fms-extensions | FileCheck %s
// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-pc-linux -fms-extensions | FileCheck %s --check-prefix=CHECK-64
// RUN: %clang_cc1 -emit-llvm %s -o - -DDEFINE_GUID -DWRONG_GUID -triple=i386-pc-linux -fms-extensions | FileCheck %s --check-prefix=CHECK-DEFINE-WRONG-GUID
@@ -17,10 +18,17 @@ struct _GUID {
#endif
typedef struct _GUID GUID;
+#ifdef BRACKET_ATTRIB
+[uuid(12345678-1234-1234-1234-1234567890aB)] struct S1 { } s1;
+[uuid(87654321-4321-4321-4321-ba0987654321)] struct S2 { };
+[uuid({12345678-1234-1234-1234-1234567890ac})] struct Curly;
+[uuid({12345678-1234-1234-1234-1234567890ac})] struct Curly;
+#else
struct __declspec(uuid("12345678-1234-1234-1234-1234567890aB")) S1 { } s1;
struct __declspec(uuid("87654321-4321-4321-4321-ba0987654321")) S2 { };
struct __declspec(uuid("{12345678-1234-1234-1234-1234567890ac}")) Curly;
struct __declspec(uuid("{12345678-1234-1234-1234-1234567890ac}")) Curly;
+#endif
#ifdef DEFINE_GUID
// Make sure we can properly generate code when the UUID has curly braces on it.
diff --git a/test/CodeGenCXX/modules-ts.cppm b/test/CodeGenCXX/modules-ts.cppm
new file mode 100644
index 000000000000..da3bcb2174a7
--- /dev/null
+++ b/test/CodeGenCXX/modules-ts.cppm
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -fmodules-ts -std=c++1z -triple=x86_64-linux-gnu -emit-module-interface %s -o %t.pcm
+// RUN: %clang_cc1 -fmodules-ts -std=c++1z -triple=x86_64-linux-gnu %t.pcm -emit-llvm -o - | FileCheck %s
+
+module FooBar;
+
+export {
+ // CHECK-LABEL: define i32 @_Z1fv(
+ int f() { return 0; }
+}
+
+// FIXME: Emit global variables and their initializers with this TU.
+// Emit an initialization function that other TUs can call, with guard variable.
+
+// FIXME: Mangle non-exported symbols so they don't collide with
+// non-exported symbols from other modules?
+
+// FIXME: Formally-internal-linkage symbols that are used from an exported
+// symbol need a mangled name and external linkage.
+
+// FIXME: const-qualified variables don't have implicit internal linkage when owned by a module.
diff --git a/test/CodeGenCXX/ms-inline-asm-return.cpp b/test/CodeGenCXX/ms-inline-asm-return.cpp
index 1219c617ddc7..51671c0bcdaa 100644
--- a/test/CodeGenCXX/ms-inline-asm-return.cpp
+++ b/test/CodeGenCXX/ms-inline-asm-return.cpp
@@ -50,8 +50,8 @@ char f_i8() {
bool f_i1() {
__asm {
- mov eax, 1
- mov edx, 1
+ mov eax, 1L
+ mov edx, 1U
}
}
// CHECK-LABEL: define zeroext i1 @f_i1()
@@ -80,12 +80,12 @@ struct EightChars {
};
EightChars f_s8() {
__asm {
- mov eax, 0x01010101
- mov edx, 0x01010101
+ mov eax, 01010101h
+ mov edx, 01010101b
}
}
// CHECK-LABEL: define i64 @f_s8()
-// CHECK: %[[r:[^ ]*]] = call i64 asm sideeffect inteldialect "mov eax, $$0x01010101\0A\09mov edx, $$0x01010101", "=A,~{eax},{{.*}}"
+// CHECK: %[[r:[^ ]*]] = call i64 asm sideeffect inteldialect "mov eax, $$01010101h\0A\09mov edx, $$01010101b", "=A,~{eax},{{.*}}"
// CHECK: store i64 %[[r]], i64* %{{.*}}
// CHECK: %[[r_i64:[^ ]*]] = load i64, i64* %{{.*}}
// CHECK: ret i64 %[[r_i64]]
diff --git a/test/CodeGenCXX/ms-thread_local.cpp b/test/CodeGenCXX/ms-thread_local.cpp
index c29473fd6fca..5183ab5c32e1 100644
--- a/test/CodeGenCXX/ms-thread_local.cpp
+++ b/test/CodeGenCXX/ms-thread_local.cpp
@@ -26,3 +26,8 @@ A f() {
(void)b;
return c;
}
+
+// CHECK: !llvm.module.flags = !{{{.*}}}
+// CHECK: !{{[0-9]+}} = !{i32 6, !"Linker Options", ![[link_opts:[0-9]+]]}
+// CHECK: ![[link_opts]] = !{![[dyn_tls_init:[0-9]+]]}
+// CHECK: ![[dyn_tls_init]] = !{!"/include:___dyn_tls_init@12"}
diff --git a/test/CodeGenCXX/naked.cpp b/test/CodeGenCXX/naked.cpp
new file mode 100644
index 000000000000..34f22b3636b5
--- /dev/null
+++ b/test/CodeGenCXX/naked.cpp
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-windows -emit-llvm %s -o - | FileCheck %s
+
+class TestNaked {
+public:
+ void NakedFunction();
+};
+
+__attribute__((naked)) void TestNaked::NakedFunction() {
+ // CHECK-LABEL: define {{(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 602f93c34f01..0429ae770bc8 100644
--- a/test/CodeGenCXX/new-array-init.cpp
+++ b/test/CodeGenCXX/new-array-init.cpp
@@ -1,5 +1,8 @@
// RUN: %clang_cc1 -std=c++11 -triple i386-unknown-unknown %s -emit-llvm -o - | FileCheck %s
+// CHECK: @[[ABC4:.*]] = {{.*}} constant [4 x i8] c"abc\00"
+// CHECK: @[[ABC15:.*]] = {{.*}} constant [15 x i8] c"abc\00\00\00\00
+
// CHECK-LABEL: define void @_Z2fni
void fn(int n) {
// CHECK: icmp ult i{{32|64}} %{{[^ ]+}}, 3
@@ -11,13 +14,6 @@ void fn(int n) {
new int[n] { 1, 2, 3 };
}
-// CHECK-LABEL: define void @_Z15const_underflowv
-void const_underflow() {
- // CHECK-NOT: icmp ult i{{32|64}} %{{[^ ]+}}, 3
- // CHECK: call i8* @_Zna{{.}}(i{{32|64}} -1)
- new int[2] { 1, 2, 3 };
-}
-
// CHECK-LABEL: define void @_Z11const_exactv
void const_exact() {
// CHECK-NOT: icmp ult i{{32|64}} %{{[^ ]+}}, 3
@@ -46,3 +42,77 @@ void check_array_value_init() {
// CHECK: icmp eq
// CHECK: br i1
}
+
+// CHECK-LABEL: define void @_Z15string_nonconsti
+void string_nonconst(int n) {
+ // CHECK: icmp slt i{{32|64}} %{{[^ ]+}}, 4
+ // 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: %[[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]],
+ new char[n] { "abc" };
+}
+
+// CHECK-LABEL: define void @_Z12string_exactv
+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-NOT: memset
+ new char[4] { "abc" };
+}
+
+// CHECK-LABEL: define void @_Z17string_sufficientv
+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-NOT: memset
+ new char[15] { "abc" };
+}
+
+// CHECK-LABEL: define void @_Z10aggr_exactv
+void aggr_exact() {
+ // CHECK-NOT: icmp
+ // CHECK: %[[MEM:.*]] = call i8* @_Zna{{.}}(i{{32|64}} 16)
+ // CHECK: %[[PTR0:.*]] = bitcast i8* %[[MEM]] to %[[AGGR:.*]]*
+ // CHECK: %[[FIELD:.*]] = getelementptr inbounds %[[AGGR]], %[[AGGR]]* %[[PTR0]], i32 0, i32 0{{$}}
+ // CHECK: store i32 1, i32* %[[FIELD]]
+ // CHECK: %[[FIELD:.*]] = getelementptr inbounds %[[AGGR]], %[[AGGR]]* %[[PTR0]], i32 0, i32 1{{$}}
+ // CHECK: store i32 2, i32* %[[FIELD]]
+ // CHECK: %[[PTR1:.*]] = getelementptr inbounds %[[AGGR]], %[[AGGR]]* %[[PTR0]], i32 1{{$}}
+ // CHECK: %[[FIELD:.*]] = getelementptr inbounds %[[AGGR]], %[[AGGR]]* %[[PTR1]], i32 0, i32 0{{$}}
+ // CHECK: store i32 3, i32* %[[FIELD]]
+ // CHECK: %[[FIELD:.*]] = getelementptr inbounds %[[AGGR]], %[[AGGR]]* %[[PTR1]], i32 0, i32 1{{$}}
+ // CHECK: store i32 0, i32* %[[FIELD]]
+ // CHECK-NOT: store
+ // CHECK-NOT: memset
+ struct Aggr { int a, b; };
+ new Aggr[2] { 1, 2, 3 };
+}
+
+// CHECK-LABEL: define void @_Z15aggr_sufficienti
+void aggr_sufficient(int n) {
+ // CHECK: icmp ult i32 %{{.*}}, 2
+ // CHECK: %[[MEM:.*]] = call i8* @_Zna{{.}}(
+ // CHECK: %[[PTR0:.*]] = bitcast i8* %[[MEM]] to %[[AGGR:.*]]*
+ // CHECK: %[[FIELD:.*]] = getelementptr inbounds %[[AGGR]], %[[AGGR]]* %[[PTR0]], i32 0, i32 0{{$}}
+ // CHECK: store i32 1, i32* %[[FIELD]]
+ // CHECK: %[[FIELD:.*]] = getelementptr inbounds %[[AGGR]], %[[AGGR]]* %[[PTR0]], i32 0, i32 1{{$}}
+ // CHECK: store i32 2, i32* %[[FIELD]]
+ // CHECK: %[[PTR1:.*]] = getelementptr inbounds %[[AGGR]], %[[AGGR]]* %[[PTR0]], i32 1{{$}}
+ // CHECK: %[[FIELD:.*]] = getelementptr inbounds %[[AGGR]], %[[AGGR]]* %[[PTR1]], i32 0, i32 0{{$}}
+ // CHECK: store i32 3, i32* %[[FIELD]]
+ // CHECK: %[[FIELD:.*]] = getelementptr inbounds %[[AGGR]], %[[AGGR]]* %[[PTR1]], i32 0, i32 1{{$}}
+ // CHECK: store i32 0, i32* %[[FIELD]]
+ // 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]],
+ struct Aggr { int a, b; };
+ new Aggr[n] { 1, 2, 3 };
+}
diff --git a/test/CodeGenCXX/no-exceptions.cpp b/test/CodeGenCXX/no-exceptions.cpp
index ceb3b8e80396..b970ef2c5a27 100644
--- a/test/CodeGenCXX/no-exceptions.cpp
+++ b/test/CodeGenCXX/no-exceptions.cpp
@@ -11,4 +11,4 @@ void f() throw (int) {
// CHECK: ret void
}
-// CHECK: attributes [[NUW]] = { nounwind{{.*}} }
+// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} }
diff --git a/test/CodeGenCXX/nrvo.cpp b/test/CodeGenCXX/nrvo.cpp
index 8744d141dddc..d02206abae50 100644
--- a/test/CodeGenCXX/nrvo.cpp
+++ b/test/CodeGenCXX/nrvo.cpp
@@ -1,5 +1,6 @@
// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm -O1 -o - %s | FileCheck %s
-// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm -O1 -fcxx-exceptions -fexceptions -o - %s | FileCheck --check-prefix=CHECK-EH %s
+// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm -O1 -fcxx-exceptions -fexceptions -std=c++03 -o - %s | FileCheck --check-prefixes=CHECK-EH,CHECK-EH-03 %s
+// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm -O1 -fcxx-exceptions -fexceptions -std=c++11 -o - %s | FileCheck --check-prefixes=CHECK-EH,CHECK-EH-11 %s
// Test code generation for the named return value optimization.
class X {
@@ -91,16 +92,18 @@ X test2(bool B) {
// -> %eh.cleanup
// %lpad1: landing pad for return copy ctors, EH cleanup for 'y'
- // CHECK-EH: invoke {{.*}} @_ZN1XD1Ev
+ // CHECK-EH-03: invoke {{.*}} @_ZN1XD1Ev
// -> %eh.cleanup, %terminate.lpad
+ // CHECK-EH-11: call {{.*}} @_ZN1XD1Ev
// %if.end: returning 'y'
// CHECK-EH: invoke {{.*}} @_ZN1XC1ERKS_
// -> %cleanup, %lpad1
// %cleanup: normal cleanup for 'y'
- // CHECK-EH: invoke {{.*}} @_ZN1XD1Ev
+ // CHECK-EH-03: invoke {{.*}} @_ZN1XD1Ev
// -> %invoke.cont11, %lpad
+ // CHECK-EH-11: call {{.*}} @_ZN1XD1Ev
// %invoke.cont11: normal cleanup for 'x'
// CHECK-EH: call void @llvm.lifetime.end
@@ -109,19 +112,20 @@ X test2(bool B) {
// CHECK-EH-NEXT: ret void
// %eh.cleanup: EH cleanup for 'x'
- // CHECK-EH: invoke {{.*}} @_ZN1XD1Ev
+ // CHECK-EH-03: invoke {{.*}} @_ZN1XD1Ev
// -> %invoke.cont17, %terminate.lpad
+ // CHECK-EH-11: call {{.*}} @_ZN1XD1Ev
// %invoke.cont17: rethrow block for %eh.cleanup.
// This really should be elsewhere in the function.
// CHECK-EH: resume { i8*, i32 }
// %terminate.lpad: terminate landing pad.
- // CHECK-EH: [[T0:%.*]] = landingpad { i8*, i32 }
- // CHECK-EH-NEXT: catch i8* null
- // CHECK-EH-NEXT: [[T1:%.*]] = extractvalue { i8*, i32 } [[T0]], 0
- // CHECK-EH-NEXT: call void @__clang_call_terminate(i8* [[T1]]) [[NR_NUW:#[0-9]+]]
- // CHECK-EH-NEXT: unreachable
+ // CHECK-EH-03: [[T0:%.*]] = landingpad { i8*, i32 }
+ // CHECK-EH-03-NEXT: catch i8* null
+ // CHECK-EH-03-NEXT: [[T1:%.*]] = extractvalue { i8*, i32 } [[T0]], 0
+ // CHECK-EH-03-NEXT: call void @__clang_call_terminate(i8* [[T1]]) [[NR_NUW:#[0-9]+]]
+ // CHECK-EH-03-NEXT: unreachable
}
@@ -178,11 +182,11 @@ X test6() {
return a;
// CHECK: [[A:%.*]] = alloca [[X:%.*]], align 8
// CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds %class.X, %class.X* [[A]], i32 0, i32 0
- // CHECK-NEXT: call void @llvm.lifetime.start(i64 1, i8* [[PTR]])
+ // CHECK-NEXT: call void @llvm.lifetime.start(i64 1, i8* nonnull [[PTR]])
// CHECK-NEXT: call {{.*}} @_ZN1XC1Ev([[X]]* nonnull [[A]])
// CHECK-NEXT: call {{.*}} @_ZN1XC1ERKS_([[X]]* {{%.*}}, [[X]]* nonnull dereferenceable({{[0-9]+}}) [[A]])
// CHECK-NEXT: call {{.*}} @_ZN1XD1Ev([[X]]* nonnull [[A]])
- // CHECK-NEXT: call void @llvm.lifetime.end(i64 1, i8* [[PTR]])
+ // CHECK-NEXT: call void @llvm.lifetime.end(i64 1, i8* nonnull [[PTR]])
// CHECK-NEXT: ret void
}
@@ -217,4 +221,4 @@ Y<int> test9() {
// CHECK-LABEL: define linkonce_odr void @_ZN1YIiE1fEv
// CHECK: tail call {{.*}} @_ZN1YIiEC1Ev
-// CHECK-EH: attributes [[NR_NUW]] = { noreturn nounwind }
+// CHECK-EH-03: attributes [[NR_NUW]] = { noreturn nounwind }
diff --git a/test/CodeGenCXX/optnone-class-members.cpp b/test/CodeGenCXX/optnone-class-members.cpp
index 751f3dd2bf08..70e3ee76e60a 100644
--- a/test/CodeGenCXX/optnone-class-members.cpp
+++ b/test/CodeGenCXX/optnone-class-members.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 < %s -triple %itanium_abi_triple -fms-extensions -emit-llvm -x c++ | FileCheck %s
+// RUN: %clang_cc1 < %s -triple %itanium_abi_triple -fms-extensions -O2 -disable-llvm-optzns -emit-llvm -x c++ | FileCheck %s
// Test attribute 'optnone' on methods:
// -- member functions;
diff --git a/test/CodeGenCXX/optnone-def-decl.cpp b/test/CodeGenCXX/optnone-def-decl.cpp
index 0240189c5089..4008bbe685f3 100644
--- a/test/CodeGenCXX/optnone-def-decl.cpp
+++ b/test/CodeGenCXX/optnone-def-decl.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -triple %itanium_abi_triple -fms-extensions -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -triple %itanium_abi_triple -fms-extensions -O2 -disable-llvm-optzns -emit-llvm -o - | FileCheck %s
// Test optnone on both function declarations and function definitions.
// Verify also that we don't generate invalid IR functions with
diff --git a/test/CodeGenCXX/partial-destruction.cpp b/test/CodeGenCXX/partial-destruction.cpp
index 4097fbfaa19c..a5a2f40eb071 100644
--- a/test/CodeGenCXX/partial-destruction.cpp
+++ b/test/CodeGenCXX/partial-destruction.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - -fcxx-exceptions -fexceptions | FileCheck %s
+// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - -fcxx-exceptions -fexceptions -std=c++03 | FileCheck %s -check-prefixes=CHECK,CHECKv03
+// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - -fcxx-exceptions -fexceptions -std=c++11 | FileCheck %s -check-prefixes=CHECK,CHECKv11
// Test IR generation for partial destruction of aggregates.
@@ -45,7 +46,8 @@ namespace test0 {
// CHECK-NEXT: br label
// CHECK: [[ED_AFTER:%.*]] = phi [[A]]* [ [[ED_END]], {{%.*}} ], [ [[ED_CUR:%.*]], {{%.*}} ]
// CHECK-NEXT: [[ED_CUR]] = getelementptr inbounds [[A]], [[A]]* [[ED_AFTER]], i64 -1
- // CHECK-NEXT: invoke void @_ZN5test01AD1Ev([[A]]* [[ED_CUR]])
+ // CHECKv03-NEXT: invoke void @_ZN5test01AD1Ev([[A]]* [[ED_CUR]])
+ // CHECKv11-NEXT: call void @_ZN5test01AD1Ev([[A]]* [[ED_CUR]])
// CHECK: [[T0:%.*]] = icmp eq [[A]]* [[ED_CUR]], [[ED_BEGIN]]
// CHECK-NEXT: br i1 [[T0]],
// CHECK: ret void
@@ -58,7 +60,8 @@ namespace test0 {
// CHECK-NEXT: br i1 [[T0]],
// CHECK: [[E_AFTER:%.*]] = phi [[A]]* [ [[PARTIAL_END]], {{%.*}} ], [ [[E_CUR:%.*]], {{%.*}} ]
// CHECK-NEXT: [[E_CUR]] = getelementptr inbounds [[A]], [[A]]* [[E_AFTER]], i64 -1
- // CHECK-NEXT: invoke void @_ZN5test01AD1Ev([[A]]* [[E_CUR]])
+ // CHECKv03-NEXT: invoke void @_ZN5test01AD1Ev([[A]]* [[E_CUR]])
+ // CHECKv11-NEXT: call void @_ZN5test01AD1Ev([[A]]* [[E_CUR]])
// CHECK: [[T0:%.*]] = icmp eq [[A]]* [[E_CUR]], [[E_BEGIN]]
// CHECK-NEXT: br i1 [[T0]],
@@ -73,20 +76,21 @@ namespace test0 {
// FIXME: There's some really bad block ordering here which causes
// the partial destroy for the primary normal destructor to fall
// within the primary EH destructor.
- // CHECK: landingpad { i8*, i32 }
- // CHECK-NEXT: cleanup
- // CHECK: [[T0:%.*]] = icmp eq [[A]]* [[ED_BEGIN]], [[ED_CUR]]
- // CHECK-NEXT: br i1 [[T0]]
- // CHECK: [[EDD_AFTER:%.*]] = phi [[A]]* [ [[ED_CUR]], {{%.*}} ], [ [[EDD_CUR:%.*]], {{%.*}} ]
- // CHECK-NEXT: [[EDD_CUR]] = getelementptr inbounds [[A]], [[A]]* [[EDD_AFTER]], i64 -1
- // CHECK-NEXT: invoke void @_ZN5test01AD1Ev([[A]]* [[EDD_CUR]])
- // CHECK: [[T0:%.*]] = icmp eq [[A]]* [[EDD_CUR]], [[ED_BEGIN]]
- // CHECK-NEXT: br i1 [[T0]]
+ // CHECKv03: landingpad { i8*, i32 }
+ // CHECKv03-NEXT: cleanup
+ // CHECKv03: [[T0:%.*]] = icmp eq [[A]]* [[ED_BEGIN]], [[ED_CUR]]
+ // CHECKv03-NEXT: br i1 [[T0]]
+ // CHECKv03: [[EDD_AFTER:%.*]] = phi [[A]]* [ [[ED_CUR]], {{%.*}} ], [ [[EDD_CUR:%.*]], {{%.*}} ]
+ // CHECKv03-NEXT: [[EDD_CUR]] = getelementptr inbounds [[A]], [[A]]* [[EDD_AFTER]], i64 -1
+ // CHECKv03-NEXT: invoke void @_ZN5test01AD1Ev([[A]]* [[EDD_CUR]])
+ // CHECKv03: [[T0:%.*]] = icmp eq [[A]]* [[EDD_CUR]], [[ED_BEGIN]]
+ // CHECKv03-NEXT: br i1 [[T0]]
// Back to the primary EH destructor.
// CHECK: [[E_AFTER:%.*]] = phi [[A]]* [ [[E_END]], {{%.*}} ], [ [[E_CUR:%.*]], {{%.*}} ]
// CHECK-NEXT: [[E_CUR]] = getelementptr inbounds [[A]], [[A]]* [[E_AFTER]], i64 -1
- // CHECK-NEXT: invoke void @_ZN5test01AD1Ev([[A]]* [[E_CUR]])
+ // CHECKv03-NEXT: invoke void @_ZN5test01AD1Ev([[A]]* [[E_CUR]])
+ // CHECKv11-NEXT: call void @_ZN5test01AD1Ev([[A]]* [[E_CUR]])
// CHECK: [[T0:%.*]] = icmp eq [[A]]* [[E_CUR]], [[E0]]
// CHECK-NEXT: br i1 [[T0]],
@@ -120,8 +124,10 @@ namespace test1 {
// CHECK-NEXT: cleanup
// CHECK: landingpad { i8*, i32 }
// CHECK-NEXT: cleanup
- // CHECK: invoke void @_ZN5test11AD1Ev([[A]]* [[Y]])
- // CHECK: invoke void @_ZN5test11AD1Ev([[A]]* [[X]])
+ // CHECKv03: invoke void @_ZN5test11AD1Ev([[A]]* [[Y]])
+ // CHECKv03: invoke void @_ZN5test11AD1Ev([[A]]* [[X]])
+ // CHECKv11: call void @_ZN5test11AD1Ev([[A]]* [[Y]])
+ // CHECKv11: call void @_ZN5test11AD1Ev([[A]]* [[X]])
}
namespace test2 {
@@ -153,7 +159,8 @@ namespace test2 {
// CHECK-NEXT: br i1 [[EMPTY]],
// CHECK: [[PAST:%.*]] = phi [[A]]* [ [[CUR]], {{%.*}} ], [ [[DEL:%.*]], {{%.*}} ]
// CHECK-NEXT: [[DEL]] = getelementptr inbounds [[A]], [[A]]* [[PAST]], i64 -1
- // CHECK-NEXT: invoke void @_ZN5test21AD1Ev([[A]]* [[DEL]])
+ // CHECKv03-NEXT: invoke void @_ZN5test21AD1Ev([[A]]* [[DEL]])
+ // CHECKv11-NEXT: call void @_ZN5test21AD1Ev([[A]]* [[DEL]])
// CHECK: [[T0:%.*]] = icmp eq [[A]]* [[DEL]], [[BEGIN]]
// CHECK-NEXT: br i1 [[T0]],
}
diff --git a/test/CodeGenCXX/pr24097.cpp b/test/CodeGenCXX/pr24097.cpp
index 122bf88506d3..cdf78d20cbda 100644
--- a/test/CodeGenCXX/pr24097.cpp
+++ b/test/CodeGenCXX/pr24097.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -triple=x86_64-pc-linux -fvisibility hidden -emit-llvm -O1 -disable-llvm-optzns -o - | FileCheck %s
+// RUN: %clang_cc1 %s -triple=x86_64-pc-linux -fvisibility hidden -emit-llvm -O1 -disable-llvm-passes -o - | FileCheck %s
struct Filter {
virtual void Foo();
diff --git a/test/CodeGenCXX/pr30731.cpp b/test/CodeGenCXX/pr30731.cpp
new file mode 100644
index 000000000000..078f21ceda4f
--- /dev/null
+++ b/test/CodeGenCXX/pr30731.cpp
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -triple i386-pc-win32 -emit-llvm -flto -std=c++11 -o - %s | FileCheck %s
+
+struct A {
+ virtual ~A();
+};
+
+struct B {};
+
+struct C {
+ virtual void f();
+};
+
+struct S : A, virtual B, C {
+ void f() override;
+};
+
+void f(S* s) { s->f(); }
+
+// CHECK-LABEL: define void @"\01?f@@YAXPAUS@@@Z"
+// CHECK: call
+// CHECK: ret void
diff --git a/test/CodeGenCXX/pragma-loop-distribute.cpp b/test/CodeGenCXX/pragma-loop-distribute.cpp
new file mode 100644
index 000000000000..a6925593b818
--- /dev/null
+++ b/test/CodeGenCXX/pragma-loop-distribute.cpp
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -emit-llvm -o - %s | FileCheck %s
+
+void while_test(int *List, int Length, int *List2, int Length2) {
+ // CHECK: define {{.*}} @_Z10while_test
+ int i = 0;
+
+#pragma clang loop distribute(enable)
+ while (i < Length) {
+ // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_1:.*]]
+ List[i] = i * 2;
+ i++;
+ }
+
+ i = 0;
+ while (i < Length2) {
+ // CHECK-NOT: br label {{.*}}, !llvm.loop
+ List2[i] = i * 2;
+ i++;
+ }
+}
+
+// CHECK: ![[LOOP_1]] = distinct !{![[LOOP_1]], ![[DISTRIBUTE_ENABLE:.*]]}
+// CHECK: ![[DISTRIBUTE_ENABLE]] = !{!"llvm.loop.distribute.enable", i1 true}
diff --git a/test/CodeGenCXX/pragma-loop-safety.cpp b/test/CodeGenCXX/pragma-loop-safety.cpp
index 393f0a3e43fe..c6ce82737d0b 100644
--- a/test/CodeGenCXX/pragma-loop-safety.cpp
+++ b/test/CodeGenCXX/pragma-loop-safety.cpp
@@ -10,12 +10,12 @@ void vectorize_test(int *List, int Length) {
#pragma clang loop vectorize(assume_safety) interleave(disable) unroll(disable)
for (int i = 0; i < Length; i++) {
// CHECK: [[RHIV1:.+]] = load i32, i32* [[IV1]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP1_ID]]
- // CHECK-NEXT: [[CALC1:.+]] = mul nsw i32[[RHIV1]], 2
- // CHECK-NEXT: [[SIV1:.+]] = load i32, i32* [[IV1]]{{.*}}!llvm.mem.parallel_loop_access ![[LOOP1_ID]]
- // CHECK-NEXT: [[INDEX1:.+]] = sext i32[[SIV1]] to i64
- // CHECK-NEXT: [[ARRAY1:.+]] = load i32*, i32** [[LIST1:.*]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP1_ID]]
- // CHECK-NEXT: [[PTR1:.+]] = getelementptr inbounds i32, i32*[[ARRAY1]], i64[[INDEX1]]
- // CHECK-NEXT: store i32[[CALC1]], i32*[[PTR1]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP1_ID]]
+ // CHECK-DAG: [[CALC1:.+]] = mul nsw i32[[RHIV1]], 2
+ // CHECK-DAG: [[SIV1:.+]] = load i32, i32* [[IV1]]{{.*}}!llvm.mem.parallel_loop_access ![[LOOP1_ID]]
+ // CHECK-DAG: [[INDEX1:.+]] = sext i32[[SIV1]] to i64
+ // CHECK-DAG: [[ARRAY1:.+]] = load i32*, i32** [[LIST1:.*]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP1_ID]]
+ // CHECK-DAG: [[PTR1:.+]] = getelementptr inbounds i32, i32*[[ARRAY1]], i64[[INDEX1]]
+ // CHECK: store i32[[CALC1]], i32*[[PTR1]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP1_ID]]
// CHECK-NEXT: br label [[LOOP1_INC:[^,]+]]
List[i] = i * 2;
@@ -33,12 +33,12 @@ void interleave_test(int *List, int Length) {
#pragma clang loop interleave(assume_safety) vectorize(disable) unroll(disable)
for (int i = 0; i < Length; i++) {
// CHECK: [[RHIV2:.+]] = load i32, i32* [[IV2]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP2_ID]]
- // CHECK-NEXT: [[CALC2:.+]] = mul nsw i32[[RHIV2]], 2
- // CHECK-NEXT: [[SIV2:.+]] = load i32, i32* [[IV2]]{{.*}}!llvm.mem.parallel_loop_access ![[LOOP2_ID]]
- // CHECK-NEXT: [[INDEX2:.+]] = sext i32[[SIV2]] to i64
- // CHECK-NEXT: [[ARRAY2:.+]] = load i32*, i32** [[LIST2:.*]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP2_ID]]
- // CHECK-NEXT: [[PTR2:.+]] = getelementptr inbounds i32, i32*[[ARRAY2]], i64[[INDEX2]]
- // CHECK-NEXT: store i32[[CALC2]], i32*[[PTR2]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP2_ID]]
+ // CHECK-DAG: [[CALC2:.+]] = mul nsw i32[[RHIV2]], 2
+ // CHECK-DAG: [[SIV2:.+]] = load i32, i32* [[IV2]]{{.*}}!llvm.mem.parallel_loop_access ![[LOOP2_ID]]
+ // CHECK-DAG: [[INDEX2:.+]] = sext i32[[SIV2]] to i64
+ // CHECK-DAG: [[ARRAY2:.+]] = load i32*, i32** [[LIST2:.*]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP2_ID]]
+ // CHECK-DAG: [[PTR2:.+]] = getelementptr inbounds i32, i32*[[ARRAY2]], i64[[INDEX2]]
+ // CHECK: store i32[[CALC2]], i32*[[PTR2]], {{.*}}!llvm.mem.parallel_loop_access ![[LOOP2_ID]]
// CHECK-NEXT: br label [[LOOP2_INC:[^,]+]]
List[i] = i * 2;
diff --git a/test/CodeGenCXX/predefined-expr-cxx14.cpp b/test/CodeGenCXX/predefined-expr-cxx14.cpp
index 1f035757dea9..dd531e3112b6 100644
--- a/test/CodeGenCXX/predefined-expr-cxx14.cpp
+++ b/test/CodeGenCXX/predefined-expr-cxx14.cpp
@@ -17,8 +17,8 @@
// CHECK-DAG: @__func__._ZN24ClassInTopLevelNamespace25topLevelNamespaceFunctionEv = private unnamed_addr constant [26 x i8] c"topLevelNamespaceFunction\00"
// CHECK-DAG: @__PRETTY_FUNCTION__._ZN24ClassInTopLevelNamespace25topLevelNamespaceFunctionEv = private unnamed_addr constant [60 x i8] c"auto *ClassInTopLevelNamespace::topLevelNamespaceFunction()\00"
-// CHECK-DAG: @__func__.___ZN16ClassBlockConstrD2Ev_block_invoke = private unnamed_addr constant [41 x i8] c"___ZN16ClassBlockConstrD2Ev_block_invoke\00"
-// CHECK-DAG: @__func__.___ZN16ClassBlockConstrC2Ev_block_invoke = private unnamed_addr constant [41 x i8] c"___ZN16ClassBlockConstrC2Ev_block_invoke\00"
+// CHECK-DAG: @__func__.___ZN16ClassBlockConstrD2Ev_block_invoke = private unnamed_addr constant [31 x i8] c"~ClassBlockConstr_block_invoke\00"
+// CHECK-DAG: @__func__.___ZN16ClassBlockConstrC2Ev_block_invoke = private unnamed_addr constant [30 x i8] c"ClassBlockConstr_block_invoke\00"
int printf(const char * _Format, ...);
diff --git a/test/CodeGenCXX/reference-cast.cpp b/test/CodeGenCXX/reference-cast.cpp
index 02498a36a180..54faa6488116 100644
--- a/test/CodeGenCXX/reference-cast.cpp
+++ b/test/CodeGenCXX/reference-cast.cpp
@@ -193,4 +193,4 @@ namespace PR10650 {
// CHECK: store i64
}
-// CHECK: attributes [[NUW]] = { nounwind{{.*}} }
+// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} }
diff --git a/test/CodeGenCXX/regcall.cpp b/test/CodeGenCXX/regcall.cpp
new file mode 100644
index 000000000000..0cc6ad009324
--- /dev/null
+++ b/test/CodeGenCXX/regcall.cpp
@@ -0,0 +1,97 @@
+// 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
+
+int __regcall foo(int i);
+
+int main()
+{
+ int p = 0, _data;
+ auto lambda = [&](int parameter) -> int {
+ _data = foo(parameter);
+ return _data;
+ };
+ 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"
+
+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"
+
+// used to give a body to test_class functions
+static int x = 0;
+class test_class {
+ int a;
+public:
+#ifndef WIN_TEST
+ __regcall
+#endif
+ test_class(){++x;}
+ // 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"
+
+#ifndef WIN_TEST
+ __regcall
+#endif
+ ~test_class(){--x;}
+ // 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@@QEAA@XZ"
+ // CHECK-WIN32-DAG: define linkonce_odr x86_thiscallcc void @"\01??_Dtest_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"
+ 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"
+
+ 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"
+};
+
+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"
+
+test_class __regcall operator""_test_class (unsigned long long) { ++x; return test_class{};}
+// CHECK-LIN64-DAG: define x86_regcallcc %class.test_class @_Zli11_test_classy(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"
+
+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"
+
+// class to force generation of functions
+void force_gen() {
+ test_class t;
+ test_class t2 = 12_test_class;
+ t += t2;
+ auto t3 = 100_test_class;
+ t3.tempFunc(1);
+ freeTempFunc(1);
+ t3.do_thing();
+}
diff --git a/test/CodeGenCXX/rtti-mingw64.cpp b/test/CodeGenCXX/rtti-mingw64.cpp
new file mode 100644
index 000000000000..818b11b64bc5
--- /dev/null
+++ b/test/CodeGenCXX/rtti-mingw64.cpp
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -triple x86_64-windows-gnu %s -emit-llvm -o - | FileCheck %s
+struct A { int a; };
+struct B : virtual A { int b; };
+B b;
+
+// CHECK: @_ZTI1B = linkonce_odr 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,
+// CHECK-SAME: i32 1,
+// CHECK-SAME: i8* bitcast ({ i8*, i8* }* @_ZTI1A to i8*),
+// This i64 is important, it should be an i64, not an i32.
+// CHECK-SAME: i64 -6141 }, comdat
diff --git a/test/CodeGenCXX/rtti-qualfn.cpp b/test/CodeGenCXX/rtti-qualfn.cpp
new file mode 100644
index 000000000000..329cd50547ab
--- /dev/null
+++ b/test/CodeGenCXX/rtti-qualfn.cpp
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -std=c++1z -I%S %s -triple x86_64-linux-gnu -emit-llvm -o - -fcxx-exceptions | FileCheck %s
+
+#include "typeinfo"
+
+struct A {};
+
+// CHECK-DAG: @_ZTIFvvE = linkonce_odr constant { i8*, i8* } { i8* bitcast (i8** getelementptr inbounds (i8*, i8** @_ZTVN10__cxxabiv120__function_type_infoE, i64 2) to i8*), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @_ZTSFvvE, i32 0, i32 0) }, comdat
+// CHECK-DAG: @_ZTIPDoFvvE = linkonce_odr constant { i8*, i8*, i32, i8* } { i8* bitcast (i8** getelementptr inbounds (i8*, i8** @_ZTVN10__cxxabiv119__pointer_type_infoE, i64 2) to i8*), i8* getelementptr inbounds ([8 x i8], [8 x i8]* @_ZTSPDoFvvE, i32 0, i32 0), i32 64, i8* bitcast ({ i8*, i8* }* @_ZTIFvvE to i8*) }, comdat
+auto &ti_noexcept_ptr = typeid(void (A::*)() noexcept);
+// CHECK-DAG: @_ZTIM1ADoFvvE = linkonce_odr constant { i8*, i8*, i32, i8*, i8* } { i8* bitcast (i8** getelementptr inbounds (i8*, i8** @_ZTVN10__cxxabiv129__pointer_to_member_type_infoE, i64 2) to i8*), i8* getelementptr inbounds ([10 x i8], [10 x i8]* @_ZTSM1ADoFvvE, i32 0, i32 0), i32 64, i8* bitcast ({ i8*, i8* }* @_ZTIFvvE to i8*), i8* bitcast ({ i8*, i8* }* @_ZTI1A to i8*) }, comdat
+auto &ti_noexcept_memptr = typeid(void (A::*)() noexcept);
+
+// CHECK-LABEL: define void @_Z1fv(
+__attribute__((noreturn)) void f() noexcept {
+ // CHECK: call void @__cxa_throw({{.*}}@_ZTIPDoFvvE
+ throw f;
+}
+
+// CHECK-LABEL: define void @_Z1gM1ADoFvvE(
+void g(__attribute__((noreturn)) void (A::*p)() noexcept) {
+ // CHECK: call void @__cxa_throw({{.*}}@_ZTIM1ADoFvvE
+ throw p;
+}
diff --git a/test/CodeGenCXX/runtime-dllstorage.cpp b/test/CodeGenCXX/runtime-dllstorage.cpp
new file mode 100644
index 000000000000..76c002c0e407
--- /dev/null
+++ b/test/CodeGenCXX/runtime-dllstorage.cpp
@@ -0,0 +1,158 @@
+// 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
+// %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-DYNAMIC-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
+
+#if defined(IMPORT_DECLARATIONS)
+namespace __cxxabiv1 {
+extern "C" {
+__declspec(dllimport) void __cxa_guard_acquire(unsigned long long *);
+__declspec(dllimport) unsigned char *__cxa_allocate_exception(unsigned long);
+}
+extern "C" __declspec(dllimport) void __cxa_guard_release(unsigned long long *);
+}
+namespace std {
+__declspec(dllimport) __declspec(noreturn) void terminate();
+}
+#elif defined(EXPORT_DECLARATIONS)
+namespace __cxxabiv1 {
+extern "C" {
+__declspec(dllexport) void __cxa_guard_acquire(unsigned long long *);
+__declspec(dllexport) unsigned char *__cxa_allocate_exception(unsigned long);
+}
+extern "C" void __declspec(dllexport) __cxa_guard_release(unsigned long long *);
+}
+namespace std {
+__declspec(dllexport) __declspec(noreturn) void terminate();
+}
+#elif defined(DECL)
+namespace __cxxabiv1 {
+extern "C" unsigned char *__cxa_allocate_exception(unsigned long);
+}
+namespace std {
+__declspec(noreturn) void terminate();
+}
+#else
+namespace std {
+__declspec(noreturn) void terminate();
+}
+#endif
+
+struct s {
+ s() = default;
+ s(unsigned char) { throw 0; }
+ int m() const;
+};
+
+struct t {
+ ~t();
+ int m() const;
+};
+
+struct u {
+ ~u();
+};
+
+s o;
+thread_local t t;
+u v;
+__declspec(thread) s q;
+
+void __declspec(noinline) f() {
+ throw 0;
+}
+
+void g();
+void __declspec(noinline) h() {
+ try {
+ g();
+ } catch (const int &) {
+ return;
+ } catch (...) {
+ throw;
+ }
+}
+
+void i() {
+ s r(static_cast<unsigned char>('\t'));
+}
+
+int j() {
+ static thread_local struct t v;
+ static struct t *w = new struct t;
+ return w->m() ? v.m() : w->m();
+}
+
+void k() noexcept {
+ g();
+}
+
+void l() {
+ std::terminate();
+}
+
+// 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-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-IA-DAG: declare 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*)
+// CHECK-DYNAMIC-IA-DAG: declare dllimport i32 @__cxa_atexit(void (i8*)*, i8*, i8*)
+// CHECK-DYNAMIC-IA-DECL-DAG: declare i8* @__cxa_allocate_exception(i32)
+// CHECK-DYNAMIC-IA-NODECL-DAG: declare dllimport i8* @__cxa_allocate_exception(i32)
+// CHECK-DYNAMIC-IA-IMPORT-DAG: declare dllimport i8* @__cxa_allocate_exception(i32)
+// CHECK-DYNAMIC-IA-EXPORT-DAG: declare dllimport i8* @__cxa_allocate_exception(i32)
+// CHECK-DYNAMIC-IA-DAG: declare dllimport void @__cxa_throw(i8*, i8*, i8*)
+// CHECK-DYNAMIC-DECL-IA-DAG: declare dllimport i32 @__cxa_guard_acquire(i64*)
+// 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-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-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()
+
diff --git a/test/CodeGenCXX/sanitize-dtor-bit-field.cpp b/test/CodeGenCXX/sanitize-dtor-bit-field.cpp
index d4497f6aac0b..19c46ba64a98 100644
--- a/test/CodeGenCXX/sanitize-dtor-bit-field.cpp
+++ b/test/CodeGenCXX/sanitize-dtor-bit-field.cpp
@@ -1,6 +1,6 @@
// Test -fsanitize-memory-use-after-dtor
-// RUN: %clang_cc1 -O0 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s
-// RUN: %clang_cc1 -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -O0 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-passes -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-passes -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s
// 24 bytes total
struct Packed {
diff --git a/test/CodeGenCXX/sanitize-dtor-derived-class.cpp b/test/CodeGenCXX/sanitize-dtor-derived-class.cpp
index f3134711824d..618096aeebd7 100644
--- a/test/CodeGenCXX/sanitize-dtor-derived-class.cpp
+++ b/test/CodeGenCXX/sanitize-dtor-derived-class.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s
-// RUN: %clang_cc1 -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-passes -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-passes -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s
// Base dtor poisons members
// Complete dtor poisons vtable ptr after destroying members and
diff --git a/test/CodeGenCXX/sanitize-dtor-tail-call.cpp b/test/CodeGenCXX/sanitize-dtor-tail-call.cpp
index de2fd8c75c88..d6f5719c8bf3 100644
--- a/test/CodeGenCXX/sanitize-dtor-tail-call.cpp
+++ b/test/CodeGenCXX/sanitize-dtor-tail-call.cpp
@@ -1,6 +1,6 @@
// Test -fsanitize-memory-use-after-dtor
-// RUN: %clang_cc1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s
-// RUN: %clang_cc1 -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-passes -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-passes -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s
struct Simple {
int x_;
diff --git a/test/CodeGenCXX/sanitize-dtor-trivial.cpp b/test/CodeGenCXX/sanitize-dtor-trivial.cpp
index 39f580af97e7..9e328c0a2895 100644
--- a/test/CodeGenCXX/sanitize-dtor-trivial.cpp
+++ b/test/CodeGenCXX/sanitize-dtor-trivial.cpp
@@ -1,6 +1,6 @@
// Test -fsanitize-memory-use-after-dtor
-// RUN: %clang_cc1 -O0 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s
-// RUN: %clang_cc1 -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -O0 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-passes -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-passes -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s
// TODO Success pending on resolution of issue:
// https://github.com/google/sanitizers/issues/596
diff --git a/test/CodeGenCXX/sanitize-dtor-vtable.cpp b/test/CodeGenCXX/sanitize-dtor-vtable.cpp
index 78be7949c32c..2318ef0d8003 100644
--- a/test/CodeGenCXX/sanitize-dtor-vtable.cpp
+++ b/test/CodeGenCXX/sanitize-dtor-vtable.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -O0 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s
-// RUN: %clang_cc1 -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-optzns -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -O0 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-passes -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -disable-llvm-passes -std=c++11 -triple=x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s
class A {
public:
diff --git a/test/CodeGenCXX/skip-vtable-pointer-initialization.cpp b/test/CodeGenCXX/skip-vtable-pointer-initialization.cpp
index 4734c02bc52e..83a2d617e878 100644
--- a/test/CodeGenCXX/skip-vtable-pointer-initialization.cpp
+++ b/test/CodeGenCXX/skip-vtable-pointer-initialization.cpp
@@ -11,7 +11,7 @@ struct A {
};
// CHECK-LABEL: define void @_ZN5Test11AD2Ev
-// CHECK-NOT: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5Test11AE, i64 0, i64 2) to i32 (...)**), i32 (...)***
+// CHECK-NOT: store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTVN5Test11AE, i64 0, i64 2) to i32 (...)**), i32 (...)***
A::~A()
{
}
@@ -27,7 +27,7 @@ struct A {
};
// CHECK-LABEL: define void @_ZN5Test21AD2Ev
-// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5Test21AE, i32 0, i32 2) to i32 (...)**), i32 (...)***
+// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTVN5Test21AE, i32 0, inrange i32 0, i32 2) to i32 (...)**), i32 (...)***
A::~A() {
f();
}
@@ -50,7 +50,7 @@ struct A {
};
// CHECK-LABEL: define void @_ZN5Test31AD2Ev
-// CHECK-NOT: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5Test31AE, i32 0, i32 2) to i32 (...)**), i32 (...)***
+// CHECK-NOT: store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTVN5Test31AE, i32 0, inrange i32 0, i32 2) to i32 (...)**), i32 (...)***
A::~A() {
}
@@ -76,7 +76,7 @@ struct A {
};
// CHECK-LABEL: define void @_ZN5Test41AD2Ev
-// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5Test41AE, i32 0, i32 2) to i32 (...)**), i32 (...)***
+// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTVN5Test41AE, i32 0, inrange i32 0, i32 2) to i32 (...)**), i32 (...)***
A::~A()
{
}
@@ -100,7 +100,7 @@ struct A {
};
// CHECK-LABEL: define void @_ZN5Test51AD2Ev
-// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5Test51AE, i32 0, i32 2) to i32 (...)**), i32 (...)***
+// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTVN5Test51AE, i32 0, inrange i32 0, i32 2) to i32 (...)**), i32 (...)***
A::~A()
{
}
@@ -128,7 +128,7 @@ struct A {
};
// CHECK-LABEL: define void @_ZN5Test61AD2Ev
-// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5Test61AE, i32 0, i32 2) to i32 (...)**), i32 (...)***
+// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTVN5Test61AE, i32 0, inrange i32 0, i32 2) to i32 (...)**), i32 (...)***
A::~A()
{
}
@@ -154,7 +154,7 @@ struct A {
};
// CHECK-LABEL: define void @_ZN5Test71AD2Ev
-// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5Test71AE, i32 0, i32 2) to i32 (...)**), i32 (...)***
+// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTVN5Test71AE, i32 0, inrange i32 0, i32 2) to i32 (...)**), i32 (...)***
A::~A()
{
}
@@ -180,7 +180,7 @@ struct A {
};
// CHECK-LABEL: define void @_ZN5Test81AD2Ev
-// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5Test81AE, i32 0, i32 2) to i32 (...)**), i32 (...)***
+// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTVN5Test81AE, i32 0, inrange i32 0, i32 2) to i32 (...)**), i32 (...)***
A::~A()
{
}
diff --git a/test/CodeGenCXX/stack-reuse-miscompile.cpp b/test/CodeGenCXX/stack-reuse-miscompile.cpp
index 63d15fd1e8c9..3b860a573955 100644
--- a/test/CodeGenCXX/stack-reuse-miscompile.cpp
+++ b/test/CodeGenCXX/stack-reuse-miscompile.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang -S -target armv7l-unknown-linux-gnueabihf -emit-llvm -O1 -mllvm -disable-llvm-optzns -S %s -o - | FileCheck %s
+// 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
diff --git a/test/CodeGenCXX/stack-reuse.cpp b/test/CodeGenCXX/stack-reuse.cpp
index d6340ef2c10b..8325604391ae 100644
--- a/test/CodeGenCXX/stack-reuse.cpp
+++ b/test/CodeGenCXX/stack-reuse.cpp
@@ -132,8 +132,8 @@ void large_auto_object() {
int large_combiner_test(S_large s) {
// CHECK-LABEL: define i32 @large_combiner_test
-// CHECK: [[T1:%.*]] = alloca %struct.Combiner
// CHECK: [[T2:%.*]] = alloca %struct.Combiner
+// CHECK: [[T1:%.*]] = alloca %struct.Combiner
// CHECK: [[T3:%.*]] = call %struct.Combiner* @_ZN8CombinerC1E7S_large(%struct.Combiner* nonnull [[T1]], [9 x i32] %s.coerce)
// CHECK: call void @_ZN8Combiner1fEv(%struct.Combiner* nonnull sret [[T2]], %struct.Combiner* nonnull [[T1]])
// CHECK: [[T4:%.*]] = getelementptr inbounds %struct.Combiner, %struct.Combiner* [[T2]], i32 0, i32 0, i32 0, i32 0
diff --git a/test/CodeGenCXX/strict-vtable-pointers.cpp b/test/CodeGenCXX/strict-vtable-pointers.cpp
index 33f63994d7c0..21f85b1c5772 100644
--- a/test/CodeGenCXX/strict-vtable-pointers.cpp
+++ b/test/CodeGenCXX/strict-vtable-pointers.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -fstrict-vtable-pointers -disable-llvm-optzns -O2 -emit-llvm -o %t.ll
+// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -fstrict-vtable-pointers -disable-llvm-passes -O2 -emit-llvm -o %t.ll
// RUN: FileCheck --check-prefix=CHECK-CTORS %s < %t.ll
// RUN: FileCheck --check-prefix=CHECK-NEW %s < %t.ll
// RUN: FileCheck --check-prefix=CHECK-DTORS %s < %t.ll
@@ -54,7 +54,7 @@ struct DynamicFrom2Virtuals :
// CHECK-NEW-LABEL: define void @_Z12LocalObjectsv()
// CHECK-NEW-NOT: @llvm.invariant.group.barrier(
-// CHECK-NEW-LABEL: }
+// CHECK-NEW-LABEL: {{^}}}
void LocalObjects() {
DynamicBase1 DB;
DB.foo();
@@ -82,12 +82,12 @@ void LocalObjects() {
struct DynamicFromVirtualStatic1;
// CHECK-CTORS-LABEL: define linkonce_odr void @_ZN25DynamicFromVirtualStatic1C1Ev
// CHECK-CTORS-NOT: @llvm.invariant.group.barrier(
-// CHECK-CTORS-LABEL: }
+// CHECK-CTORS-LABEL: {{^}}}
struct DynamicFrom2Virtuals;
// CHECK-CTORS-LABEL: define linkonce_odr void @_ZN20DynamicFrom2VirtualsC1Ev
// CHECK-CTORS: call i8* @llvm.invariant.group.barrier(
-// CHECK-CTORS-LABEL: }
+// CHECK-CTORS-LABEL: {{^}}}
// CHECK-NEW-LABEL: define void @_Z9Pointers1v()
@@ -97,7 +97,7 @@ struct DynamicFrom2Virtuals;
// CHECK-NEW: %[[THIS3:.*]] = call i8* @llvm.invariant.group.barrier(i8* %[[THIS2:.*]])
// CHECK-NEW: %[[THIS4:.*]] = bitcast i8* %[[THIS3]] to %[[DynamicDerived:.*]]*
// CHECK-NEW: call void @_ZN14DynamicDerivedC1Ev(%[[DynamicDerived:.*]]* %[[THIS4]])
-// CHECK-NEW-LABEL: }
+// CHECK-NEW-LABEL: {{^}}}
void Pointers1() {
DynamicBase1 *DB = new DynamicBase1;
DB->foo();
@@ -113,7 +113,7 @@ void Pointers1() {
// CHECK-NEW: call void @_ZN14DynamicDerivedC1Ev(
// CHECK-NEW: call i8* @llvm.invariant.group.barrier(
// CHECK-NEW: call void @_ZN12DynamicBase1C1Ev(
-// CHECK-NEW-LABEL: }
+// CHECK-NEW-LABEL: {{^}}}
void HackingObjects() {
DynamicBase1 DB;
DB.foo();
@@ -132,7 +132,7 @@ void HackingObjects() {
struct DynamicBase1;
// CHECK-CTORS-LABEL: define linkonce_odr void @_ZN12DynamicBase1C2Ev(
// CHECK-CTORS-NOT: call i8* @llvm.invariant.group.barrier(
-// CHECK-CTORS-LABEL: }
+// CHECK-CTORS-LABEL: {{^}}}
struct DynamicDerived;
@@ -147,7 +147,7 @@ struct DynamicDerived;
// CHECK-CTORS: %[[THIS5:.*]] = bitcast %struct.DynamicDerived* %[[THIS0]] to i32 (...)***
// CHECK-CTORS: store {{.*}} %[[THIS5]]
-// CHECK-CTORS-LABEL: }
+// CHECK-CTORS-LABEL: {{^}}}
struct DynamicDerivedMultiple;
// CHECK-CTORS-LABEL: define linkonce_odr void @_ZN22DynamicDerivedMultipleC2Ev(
@@ -166,49 +166,49 @@ struct DynamicDerivedMultiple;
// CHECK-CTORS: %[[THIS10:.*]] = bitcast %struct.DynamicDerivedMultiple* %[[THIS0]] to i32 (...)***
-// CHECK-CTORS: store {{.*}} @_ZTV22DynamicDerivedMultiple, i32 0, i32 2) {{.*}} %[[THIS10]]
+// CHECK-CTORS: store {{.*}} @_ZTV22DynamicDerivedMultiple, i32 0, inrange i32 0, i32 2) {{.*}} %[[THIS10]]
// CHECK-CTORS: %[[THIS11:.*]] = bitcast %struct.DynamicDerivedMultiple* %[[THIS0]] to i8*
// 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, i32 6) {{.*}} %[[THIS12]]
-// CHECK-CTORS-LABEL: }
+// 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(
-// CHECK-CTORS-LABEL: }
+// CHECK-CTORS-LABEL: {{^}}}
/** DTORS **/
// CHECK-DTORS-LABEL: define linkonce_odr void @_ZN10StaticBaseD2Ev(
// CHECK-DTORS-NOT: call i8* @llvm.invariant.group.barrier(
-// CHECK-DTORS-LABEL: }
+// CHECK-DTORS-LABEL: {{^}}}
// CHECK-DTORS-LABEL: define linkonce_odr void @_ZN25DynamicFromVirtualStatic2D2Ev(
// CHECK-DTORS-NOT: invariant.barrier
-// CHECK-DTORS-LABEL: }
+// CHECK-DTORS-LABEL: {{^}}}
// CHECK-DTORS-LABEL: define linkonce_odr void @_ZN17DynamicFromStaticD2Ev
// CHECK-DTORS-NOT: call i8* @llvm.invariant.group.barrier(
-// CHECK-DTORS-LABEL: }
+// 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(
-// CHECK-DTORS-LABEL: }
+// CHECK-DTORS-LABEL: {{^}}}
// CHECK-DTORS-LABEL: define linkonce_odr void @_ZN12DynamicBase1D2Ev
// CHECK-DTORS: call i8* @llvm.invariant.group.barrier(
-// CHECK-DTORS-LABEL: }
+// CHECK-DTORS-LABEL: {{^}}}
// CHECK-DTORS-LABEL: define linkonce_odr void @_ZN14DynamicDerivedD2Ev
// CHECK-DTORS-NOT: call i8* @llvm.invariant.group.barrier(
-// CHECK-DTORS-LABEL: }
+// CHECK-DTORS-LABEL: {{^}}}
// CHECK-LINK-REQ: !llvm.module.flags = !{![[FIRST:.*]], ![[SEC:.*]]{{.*}}}
diff --git a/test/CodeGenCXX/template-instantiation.cpp b/test/CodeGenCXX/template-instantiation.cpp
index 90b8099f0a26..3d0ce234371f 100644
--- a/test/CodeGenCXX/template-instantiation.cpp
+++ b/test/CodeGenCXX/template-instantiation.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -O1 -disable-llvm-optzns -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -O1 -disable-llvm-passes -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
// CHECK: @_ZN7PR100011xE = global
// CHECK-NOT: @_ZN7PR100014kBarE = external global i32
diff --git a/test/CodeGenCXX/temporaries.cpp b/test/CodeGenCXX/temporaries.cpp
index c537124c468c..bad51ba353cd 100644
--- a/test/CodeGenCXX/temporaries.cpp
+++ b/test/CodeGenCXX/temporaries.cpp
@@ -779,6 +779,36 @@ namespace MultipleExtension {
}
}
+namespace ArrayAccess {
+ struct A { A(int); ~A(); };
+ void g();
+ void f() {
+ using T = A[3];
+
+ // CHECK: call void @_ZN11ArrayAccess1AC1Ei({{.*}}, i32 1
+ // CHECK-NOT: @_ZN11ArrayAccess1AD
+ // CHECK: call void @_ZN11ArrayAccess1AC1Ei({{.*}}, i32 2
+ // CHECK-NOT: @_ZN11ArrayAccess1AD
+ // CHECK: call void @_ZN11ArrayAccess1AC1Ei({{.*}}, i32 3
+ // CHECK-NOT: @_ZN11ArrayAccess1AD
+ A &&a = T{1, 2, 3}[1];
+
+ // CHECK: call void @_ZN11ArrayAccess1AC1Ei({{.*}}, i32 4
+ // CHECK-NOT: @_ZN11ArrayAccess1AD
+ // CHECK: call void @_ZN11ArrayAccess1AC1Ei({{.*}}, i32 5
+ // CHECK-NOT: @_ZN11ArrayAccess1AD
+ // CHECK: call void @_ZN11ArrayAccess1AC1Ei({{.*}}, i32 6
+ // CHECK-NOT: @_ZN11ArrayAccess1AD
+ A &&b = 2[T{4, 5, 6}];
+
+ // CHECK: call void @_ZN11ArrayAccess1gEv(
+ g();
+
+ // CHECK: call void @_ZN11ArrayAccess1AD
+ // CHECK: call void @_ZN11ArrayAccess1AD
+ }
+}
+
namespace PR14130 {
struct S { S(int); };
struct U { S &&s; };
diff --git a/test/CodeGenCXX/threadsafe-statics.cpp b/test/CodeGenCXX/threadsafe-statics.cpp
index 9aecc2d0db68..7cb7003fc0ca 100644
--- a/test/CodeGenCXX/threadsafe-statics.cpp
+++ b/test/CodeGenCXX/threadsafe-statics.cpp
@@ -22,6 +22,6 @@ void g() {
// NO-TSS-NOT: call void @__cxa_guard_release
// NO-TSS: ret void
-// WITH-TSS: attributes [[NUW]] = { nounwind{{.*}} }
+// WITH-TSS: attributes [[NUW]] = { noinline nounwind{{.*}} }
-// NO-TSS: attributes [[NUW]] = { nounwind{{.*}} }
+// NO-TSS: attributes [[NUW]] = { noinline nounwind{{.*}} }
diff --git a/test/CodeGenCXX/thunks.cpp b/test/CodeGenCXX/thunks.cpp
index 3a598b90afe1..26e166c7bf4c 100644
--- a/test/CodeGenCXX/thunks.cpp
+++ b/test/CodeGenCXX/thunks.cpp
@@ -1,9 +1,5 @@
-// RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables -emit-llvm -o %t
-// RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables -emit-llvm -o %t.opt -O1 -disable-llvm-optzns
-// RUN: FileCheck %s < %t
-// RUN: FileCheck %s < %t.opt
-// RUN: FileCheck --check-prefix=CHECK-NONOPT %s < %t
-// RUN: FileCheck --check-prefix=CHECK-OPT %s < %t.opt
+// RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables -emit-llvm -o - | FileCheck --check-prefix=CHECK --check-prefix=CHECK-NONOPT %s
+// RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables -emit-llvm -o - -O1 -disable-llvm-passes | FileCheck --check-prefix=CHECK --check-prefix=CHECK-OPT %s
namespace Test1 {
@@ -405,4 +401,5 @@ D::~D() {}
// CHECK-OPT-LABEL: define linkonce_odr void @_ZN6Test101C3fooEv
// CHECK-OPT-LABEL: define linkonce_odr void @_ZThn8_N6Test101C3fooEv
-// CHECK: attributes [[NUW]] = { nounwind uwtable{{.*}} }
+// CHECK-NONOPT: attributes [[NUW]] = { noinline nounwind uwtable{{.*}} }
+// CHECK-OPT: attributes [[NUW]] = { nounwind uwtable{{.*}} }
diff --git a/test/CodeGenCXX/ubsan-devirtualized-calls.cpp b/test/CodeGenCXX/ubsan-devirtualized-calls.cpp
new file mode 100644
index 000000000000..bc8861aa8314
--- /dev/null
+++ b/test/CodeGenCXX/ubsan-devirtualized-calls.cpp
@@ -0,0 +1,81 @@
+// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -emit-llvm -fsanitize=vptr %s -o - | FileCheck %s
+
+struct Base1 {
+ virtual void f1() {}
+};
+
+struct Base2 {
+ virtual void f1() {}
+};
+
+struct Derived1 final : Base1 {
+ void f1() override {}
+};
+
+struct Derived2 final : Base1, Base2 {
+ void f1() override {}
+};
+
+struct Derived3 : Base1 {
+ void f1() override /* nofinal */ {}
+};
+
+struct Derived4 final : Base1 {
+ void f1() override final {}
+};
+
+// CHECK: [[UBSAN_TI_DERIVED1_1:@[0-9]+]] = private unnamed_addr global {{.*}} i8* bitcast {{.*}} @_ZTI8Derived1 to i8*
+// CHECK: [[UBSAN_TI_DERIVED2_1:@[0-9]+]] = private unnamed_addr global {{.*}} i8* bitcast {{.*}} @_ZTI8Derived2 to i8*
+// CHECK: [[UBSAN_TI_DERIVED2_2:@[0-9]+]] = private unnamed_addr global {{.*}} i8* bitcast {{.*}} @_ZTI8Derived2 to i8*
+// CHECK: [[UBSAN_TI_DERIVED3:@[0-9]+]] = private unnamed_addr global {{.*}} i8* bitcast {{.*}} @_ZTI8Derived3 to i8*
+// CHECK: [[UBSAN_TI_BASE1:@[0-9]+]] = private unnamed_addr global {{.*}} i8* bitcast {{.*}} @_ZTI5Base1 to i8*
+// 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
+void t1() {
+ Derived1 d1;
+ static_cast<Base1 *>(&d1)->f1(); //< Devirt Base1::f1 to Derived1::f1.
+ // CHECK: %[[D1:[0-9]+]] = ptrtoint %struct.Derived1* %d1 to i{{[0-9]+}}, !nosanitize
+ // CHECK-NEXT: call void @__ubsan_handle_dynamic_type_cache{{[_a-z]*}}({{.*}} [[UBSAN_TI_DERIVED1_1]] {{.*}}, i{{[0-9]+}} %[[D1]]
+}
+
+// CHECK-LABEL: define void @_Z2t2v
+void t2() {
+ Derived2 d2;
+ static_cast<Base1 *>(&d2)->f1(); //< Devirt Base1::f1 to Derived2::f1.
+ // CHECK: %[[D2_1:[0-9]+]] = ptrtoint %struct.Derived2* %d2 to i{{[0-9]+}}, !nosanitize
+ // 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
+void t3() {
+ Derived2 d2;
+ static_cast<Base2 *>(&d2)->f1(); //< Devirt Base2::f1 to Derived2::f1.
+ // CHECK: %[[D2_2:[0-9]+]] = ptrtoint %struct.Derived2* %d2 to i{{[0-9]+}}, !nosanitize
+ // 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
+void t4() {
+ Base1 p;
+ Derived3 *badp = static_cast<Derived3 *>(&p); //< Check that &p isa Derived3.
+ // CHECK: %[[P1:[0-9]+]] = ptrtoint %struct.Derived3* {{%[0-9]+}} to i{{[0-9]+}}, !nosanitize
+ // CHECK-NEXT: call void @__ubsan_handle_dynamic_type_cache{{[_a-z]*}}({{.*}} [[UBSAN_TI_DERIVED3]] {{.*}}, i{{[0-9]+}} %[[P1]]
+
+ static_cast<Base1 *>(badp)->f1(); //< No devirt, test 'badp isa Base1'.
+ // CHECK: %[[BADP1:[0-9]+]] = ptrtoint %struct.Base1* {{%[0-9]+}} to i{{[0-9]+}}, !nosanitize
+ // CHECK-NEXT: call void @__ubsan_handle_dynamic_type_cache{{[_a-z]*}}({{.*}} [[UBSAN_TI_BASE1]] {{.*}}, i{{[0-9]+}} %[[BADP1]]
+}
+
+// CHECK-LABEL: define void @_Z2t5v
+void t5() {
+ Base1 p;
+ Derived4 *badp = static_cast<Derived4 *>(&p); //< Check that &p isa Derived4.
+ // CHECK: %[[P1:[0-9]+]] = ptrtoint %struct.Derived4* {{%[0-9]+}} to i{{[0-9]+}}, !nosanitize
+ // CHECK-NEXT: call void @__ubsan_handle_dynamic_type_cache{{[_a-z]*}}({{.*}} [[UBSAN_TI_DERIVED4_1]] {{.*}}, i{{[0-9]+}} %[[P1]]
+
+ static_cast<Base1 *>(badp)->f1(); //< Devirt Base1::f1 to Derived4::f1.
+ // CHECK: %[[BADP1:[0-9]+]] = ptrtoint %struct.Derived4* {{%[0-9]+}} to i{{[0-9]+}}, !nosanitize
+ // CHECK-NEXT: call void @__ubsan_handle_dynamic_type_cache{{[_a-z]*}}({{.*}} [[UBSAN_TI_DERIVED4_2]] {{.*}}, i{{[0-9]+}} %[[BADP1]]
+}
diff --git a/test/CodeGenCXX/ubsan-vtable-checks.cpp b/test/CodeGenCXX/ubsan-vtable-checks.cpp
new file mode 100644
index 000000000000..80af77d4ea6d
--- /dev/null
+++ b/test/CodeGenCXX/ubsan-vtable-checks.cpp
@@ -0,0 +1,40 @@
+// 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=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=vptr %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-VPTR --check-prefix=MSABI
+struct T {
+ virtual ~T() {}
+ virtual int v() { return 1; }
+};
+
+struct U : T {
+ ~U();
+ virtual int v() { return 2; }
+};
+
+U::~U() {}
+
+// ITANIUM: define i32 @_Z5get_vP1T
+// MSABI: define i32 @"\01?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*{{.*}})***
+ // CHECK-NULL: [[UBSAN_CMP_RES:%[0-9]+]] = icmp ne %struct.T* %{{[_a-z0-9]+}}, null
+ // CHECK-NULL-NEXT: br i1 [[UBSAN_CMP_RES]], label %{{.*}}, label %{{.*}}
+ // CHECK-NULL: call void @__ubsan_handle_type_mismatch_abort
+ // Second, we check that vtable is actually loaded once the type check is done.
+ // CHECK-NULL: load {{.*}} (%struct.T*{{.*}})**, {{.*}} (%struct.T*{{.*}})***
+ return t->v();
+}
+
+// ITANIUM: define void @_Z9delete_itP1T
+// MSABI: define void @"\01?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*{{.*}})***
+ // CHECK-VPTR: br i1 {{.*}} label %{{.*}}
+ // CHECK-VPTR: call void @__ubsan_handle_dynamic_type_cache_miss_abort
+ // Second, we check that vtable is actually loaded once the type check is done.
+ // CHECK-VPTR: load {{.*}} (%struct.T*{{.*}})**, {{.*}} (%struct.T*{{.*}})***
+ delete t;
+}
diff --git a/test/CodeGenCXX/uncopyable-args.cpp b/test/CodeGenCXX/uncopyable-args.cpp
index c1d284a74185..307a5cf11b6b 100644
--- a/test/CodeGenCXX/uncopyable-args.cpp
+++ b/test/CodeGenCXX/uncopyable-args.cpp
@@ -204,3 +204,77 @@ void bar() {
// WIN64-LABEL: declare void @"\01?foo@two_copy_ctors@@YAXUB@1@@Z"(%"struct.two_copy_ctors::B"*)
}
+
+namespace definition_only {
+struct A {
+ A();
+ A(A &&o);
+ void *p;
+};
+void *foo(A a) { return a.p; }
+// WIN64-LABEL: define i8* @"\01?foo@definition_only@@YAPEAXUA@1@@Z"(%"struct.definition_only::A"*
+}
+
+namespace deleted_by_member {
+struct B {
+ B();
+ B(B &&o);
+ void *p;
+};
+struct A {
+ A();
+ B b;
+};
+void *foo(A a) { return a.b.p; }
+// WIN64-LABEL: define i8* @"\01?foo@deleted_by_member@@YAPEAXUA@1@@Z"(%"struct.deleted_by_member::A"*
+}
+
+namespace deleted_by_base {
+struct B {
+ B();
+ B(B &&o);
+ void *p;
+};
+struct A : B {
+ A();
+};
+void *foo(A a) { return a.p; }
+// WIN64-LABEL: define i8* @"\01?foo@deleted_by_base@@YAPEAXUA@1@@Z"(%"struct.deleted_by_base::A"*
+}
+
+namespace deleted_by_member_copy {
+struct B {
+ B();
+ B(const B &o) = delete;
+ void *p;
+};
+struct A {
+ A();
+ B b;
+};
+void *foo(A a) { return a.b.p; }
+// WIN64-LABEL: define i8* @"\01?foo@deleted_by_member_copy@@YAPEAXUA@1@@Z"(%"struct.deleted_by_member_copy::A"*
+}
+
+namespace deleted_by_base_copy {
+struct B {
+ B();
+ B(const B &o) = delete;
+ void *p;
+};
+struct A : B {
+ A();
+};
+void *foo(A a) { return a.p; }
+// WIN64-LABEL: define i8* @"\01?foo@deleted_by_base_copy@@YAPEAXUA@1@@Z"(%"struct.deleted_by_base_copy::A"*
+}
+
+namespace explicit_delete {
+struct A {
+ A();
+ A(const A &o) = delete;
+ void *p;
+};
+// WIN64-LABEL: define i8* @"\01?foo@explicit_delete@@YAPEAXUA@1@@Z"(%"struct.explicit_delete::A"*
+void *foo(A a) { return a.p; }
+}
diff --git a/test/CodeGenCXX/value-init.cpp b/test/CodeGenCXX/value-init.cpp
index 735dc6163990..fc4e0d3a55e0 100644
--- a/test/CodeGenCXX/value-init.cpp
+++ b/test/CodeGenCXX/value-init.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %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
struct A {
virtual ~A();
@@ -315,6 +315,14 @@ namespace PR20256 {
// CHECK: }
}
+// CHECK-LABEL: define {{.*}}@_Z20explicitly_defaultedv
+int explicitly_defaulted() {
+ struct A { A() = default; int n; };
+ // CHECK: call void @llvm.memset
+ A a = A();
+ return a.n;
+} // CHECK-LABEL: }
+
// CHECK-LABEL: define linkonce_odr void @_ZN8zeroinit2X3IiEC2Ev(%"struct.zeroinit::X3"* %this) unnamed_addr
// CHECK: call void @llvm.memset.p0i8.i64
// CHECK-NEXT: call void @_ZN8zeroinit2X2IiEC2Ev
diff --git a/test/CodeGenCXX/virtual-base-cast.cpp b/test/CodeGenCXX/virtual-base-cast.cpp
index 554e80d3cf21..b2f2b4f2b319 100644
--- a/test/CodeGenCXX/virtual-base-cast.cpp
+++ b/test/CodeGenCXX/virtual-base-cast.cpp
@@ -82,4 +82,4 @@ BB* d() { return y; }
// MSVC: add nsw i32 4, %[[offset]]
// MSVC: }
-// CHECK: attributes [[NUW]] = { nounwind{{.*}} }
+// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} }
diff --git a/test/CodeGenCXX/virtual-destructor-calls.cpp b/test/CodeGenCXX/virtual-destructor-calls.cpp
index e13adfcc85cf..2e63daac31de 100644
--- a/test/CodeGenCXX/virtual-destructor-calls.cpp
+++ b/test/CodeGenCXX/virtual-destructor-calls.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin10 -mconstructor-aliases -O1 -disable-llvm-optzns | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin10 -mconstructor-aliases -O1 -disable-llvm-passes | FileCheck %s
struct Member {
~Member();
diff --git a/test/CodeGenCXX/virtual-function-calls.cpp b/test/CodeGenCXX/virtual-function-calls.cpp
index 0a6fc6b3f284..22944d94ca88 100644
--- a/test/CodeGenCXX/virtual-function-calls.cpp
+++ b/test/CodeGenCXX/virtual-function-calls.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 %s -triple %itanium_abi_triple -std=c++11 -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -triple %itanium_abi_triple -std=c++11 -emit-llvm -o - -fstrict-vtable-pointers -O1 | FileCheck --check-prefix=CHECK-INVARIANT %s
// PR5021
namespace PR5021 {
@@ -42,10 +43,14 @@ namespace VirtualNoreturn {
[[noreturn]] virtual void f();
};
- // CHECK: @_ZN15VirtualNoreturn1f
+ // CHECK-LABEL: @_ZN15VirtualNoreturn1f
+ // CHECK-INVARIANT-LABEL: define void @_ZN15VirtualNoreturn1f
void f(A *p) {
p->f();
// CHECK: call {{.*}}void %{{[^#]*$}}
// CHECK-NOT: unreachable
+ // CHECK-INVARIANT: load {{.*}} !invariant.load ![[EMPTY_NODE:[0-9]+]]
}
}
+
+// CHECK-INVARIANT: ![[EMPTY_NODE]] = !{}
diff --git a/test/CodeGenCXX/visibility-inlines-hidden.cpp b/test/CodeGenCXX/visibility-inlines-hidden.cpp
index 7c0757b2829a..6ea234807ec2 100644
--- a/test/CodeGenCXX/visibility-inlines-hidden.cpp
+++ b/test/CodeGenCXX/visibility-inlines-hidden.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple i386-unknown-unknown -std=c++11 -fvisibility-inlines-hidden -emit-llvm -o - %s -O2 -disable-llvm-optzns | FileCheck %s
+// RUN: %clang_cc1 -triple i386-unknown-unknown -std=c++11 -fvisibility-inlines-hidden -emit-llvm -o - %s -O2 -disable-llvm-passes | FileCheck %s
// The trickery with optimization in the run line is to get IR
// generation to emit available_externally function bodies, but not
diff --git a/test/CodeGenCXX/vla-lambda-capturing.cpp b/test/CodeGenCXX/vla-lambda-capturing.cpp
index 44b6a2506d14..5081f1447d27 100644
--- a/test/CodeGenCXX/vla-lambda-capturing.cpp
+++ b/test/CodeGenCXX/vla-lambda-capturing.cpp
@@ -125,11 +125,11 @@ int main() {
// CHECK: [[SIZE2:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[SIZE2_REF]]
// CHECK: [[SIZE1_REF:%.+]] = getelementptr inbounds [[CAP_TYPE3]], [[CAP_TYPE3]]* [[THIS]], i{{[0-9]+}} 0, i{{[0-9]+}} 2
// CHECK: [[SIZE1:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[SIZE1_REF]]
+// CHECK: [[BUFFER1_ADDR_REF:%.+]] = getelementptr inbounds [[CAP_TYPE3]], [[CAP_TYPE3]]* [[THIS]], i{{[0-9]+}} 0, i{{[0-9]+}} 3
+// CHECK: [[BUFFER1_ADDR:%.+]] = load [[INTPTR_T]]*, [[INTPTR_T]]** [[BUFFER1_ADDR_REF]]
// CHECK: [[N_ADDR_REF:%.+]] = getelementptr inbounds [[CAP_TYPE3]], [[CAP_TYPE3]]* [[THIS]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
// CHECK: [[N_ADDR:%.+]] = load [[INTPTR_T]]*, [[INTPTR_T]]** [[N_ADDR_REF]]
// CHECK: [[N:%.+]] = load [[INTPTR_T]], [[INTPTR_T]]* [[N_ADDR]]
-// CHECK: [[BUFFER1_ADDR_REF:%.+]] = getelementptr inbounds [[CAP_TYPE3]], [[CAP_TYPE3]]* [[THIS]], i{{[0-9]+}} 0, i{{[0-9]+}} 3
-// CHECK: [[BUFFER1_ADDR:%.+]] = load [[INTPTR_T]]*, [[INTPTR_T]]** [[BUFFER1_ADDR_REF]]
// CHECK: [[ELEM_OFFSET:%.+]] = mul {{.*}} i{{[0-9]+}} [[N]], [[SIZE1]]
// CHECK: [[ELEM_ADDR:%.+]] = getelementptr inbounds [[INTPTR_T]], [[INTPTR_T]]* [[BUFFER1_ADDR]], i{{[0-9]+}} [[ELEM_OFFSET]]
// CHECK: [[SIZEOF:%.+]] = mul {{.*}} i{{[0-9]+}} {{[0-9]+}}, [[SIZE1]]
diff --git a/test/CodeGenCXX/vtable-align.cpp b/test/CodeGenCXX/vtable-align.cpp
index f1f10c07df2d..1b82cbc085c9 100644
--- a/test/CodeGenCXX/vtable-align.cpp
+++ b/test/CodeGenCXX/vtable-align.cpp
@@ -9,6 +9,6 @@ struct A {
void A::f() {}
-// CHECK-32: @_ZTV1A = unnamed_addr constant [5 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTI1A to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A1fEv to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A1gEv to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A1hEv to i8*)], align 4
+// CHECK-32: @_ZTV1A = unnamed_addr constant { [5 x i8*] } { [5 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTI1A to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A1fEv to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A1gEv to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A1hEv to i8*)] }, align 4
-// CHECK-64: @_ZTV1A = unnamed_addr constant [5 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTI1A to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A1fEv to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A1gEv to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A1hEv to i8*)], align 8
+// CHECK-64: @_ZTV1A = unnamed_addr constant { [5 x i8*] } { [5 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTI1A to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A1fEv to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A1gEv to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A1hEv to i8*)] }, align 8
diff --git a/test/CodeGenCXX/vtable-assume-load.cpp b/test/CodeGenCXX/vtable-assume-load.cpp
index 819b09d70e3d..b0857c29c654 100644
--- a/test/CodeGenCXX/vtable-assume-load.cpp
+++ b/test/CodeGenCXX/vtable-assume-load.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o %t.ll -O1 -disable-llvm-optzns -fms-extensions -fstrict-vtable-pointers
-// RUN: %clang_cc1 %s -triple i686-pc-win32 -emit-llvm -o %t.ms.ll -O1 -disable-llvm-optzns -fms-extensions -fstrict-vtable-pointers
+// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o %t.ll -O1 -disable-llvm-passes -fms-extensions -fstrict-vtable-pointers
+// RUN: %clang_cc1 %s -triple i686-pc-win32 -emit-llvm -o %t.ms.ll -O1 -disable-llvm-passes -fms-extensions -fstrict-vtable-pointers
// FIXME: Assume load should not require -fstrict-vtable-pointers
// RUN: FileCheck --check-prefix=CHECK1 --input-file=%t.ll %s
@@ -27,9 +27,9 @@ void g(A *a) { a->foo(); }
// CHECK1-LABEL: define void @_ZN5test14fooAEv()
// CHECK1: call void @_ZN5test11AC1Ev(%"struct.test1::A"*
// CHECK1: %[[VTABLE:.*]] = load i8**, i8*** %{{.*}}
-// CHECK1: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5test11AE, i32 0, i32 2)
+// CHECK1: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTVN5test11AE, i32 0, inrange i32 0, i32 2)
// CHECK1: call void @llvm.assume(i1 %[[CMP]])
-// CHECK1-LABEL: }
+// CHECK1-LABEL: {{^}}}
void fooA() {
A a;
@@ -39,9 +39,9 @@ void fooA() {
// CHECK1-LABEL: define void @_ZN5test14fooBEv()
// CHECK1: call void @_ZN5test11BC1Ev(%"struct.test1::B"* %{{.*}})
// CHECK1: %[[VTABLE:.*]] = load i8**, i8*** %{{.*}}
-// CHECK1: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5test11BE, i32 0, i32 2)
+// CHECK1: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTVN5test11BE, i32 0, inrange i32 0, i32 2)
// CHECK1: call void @llvm.assume(i1 %[[CMP]])
-// CHECK1-LABEL: }
+// CHECK1-LABEL: {{^}}}
void fooB() {
B b;
@@ -50,7 +50,7 @@ void fooB() {
// there should not be any assumes in the ctor that calls base ctor
// CHECK1-LABEL: define linkonce_odr void @_ZN5test11BC2Ev(%"struct.test1::B"*
// CHECK1-NOT: @llvm.assume(
-// CHECK1-LABEL: }
+// CHECK1-LABEL: {{^}}}
}
namespace test2 {
struct A {
@@ -73,18 +73,18 @@ void h(B *b) { b->bar(); }
// CHECK2-LABEL: define void @_ZN5test24testEv()
// CHECK2: call void @_ZN5test21CC1Ev(%"struct.test2::C"*
// CHECK2: %[[VTABLE:.*]] = load i8**, i8*** {{.*}}
-// CHECK2: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr inbounds ([6 x i8*], [6 x i8*]* @_ZTVN5test21CE, i32 0, i32 2)
+// CHECK2: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr inbounds ({ [3 x i8*], [3 x i8*] }, { [3 x i8*], [3 x i8*] }* @_ZTVN5test21CE, i32 0, inrange i32 0, i32 2)
// CHECK2: call void @llvm.assume(i1 %[[CMP]])
// CHECK2: %[[V2:.*]] = bitcast %"struct.test2::C"* %{{.*}} to i8*
// CHECK2: %[[ADD_PTR:.*]] = getelementptr inbounds i8, i8* %[[V2]], i64 8
// CHECK2: %[[V3:.*]] = bitcast i8* %[[ADD_PTR]] to i8***
// CHECK2: %[[VTABLE2:.*]] = load i8**, i8*** %[[V3]]
-// CHECK2: %[[CMP2:.*]] = icmp eq i8** %[[VTABLE2]], getelementptr inbounds ([6 x i8*], [6 x i8*]* @_ZTVN5test21CE, i32 0, i32 5)
+// CHECK2: %[[CMP2:.*]] = icmp eq i8** %[[VTABLE2]], getelementptr inbounds ({ [3 x i8*], [3 x i8*] }, { [3 x i8*], [3 x i8*] }* @_ZTVN5test21CE, i32 0, inrange i32 1, i32 2)
// CHECK2: call void @llvm.assume(i1 %[[CMP2]])
// CHECK2: call void @_ZN5test21gEPNS_1AE(
-// CHECK2-LABEL: }
+// CHECK2-LABEL: {{^}}}
void test() {
C c;
@@ -111,7 +111,7 @@ void g(B *a) { a->foo(); }
// CHECK3-LABEL: define void @_ZN5test34testEv()
// CHECK3: call void @_ZN5test31CC1Ev(%"struct.test3::C"*
-// CHECK3: %[[CMP:.*]] = icmp eq i8** %{{.*}}, getelementptr inbounds ([4 x i8*], [4 x i8*]* @_ZTVN5test31CE, i32 0, i32 3)
+// CHECK3: %[[CMP:.*]] = icmp eq i8** %{{.*}}, getelementptr inbounds ({ [4 x i8*] }, { [4 x i8*] }* @_ZTVN5test31CE, i32 0, inrange i32 0, i32 3)
// CHECK3: call void @llvm.assume(i1 %[[CMP]])
// CHECK3-LABLEL: }
void test() {
@@ -140,13 +140,13 @@ void g(C *c) { c->foo(); }
// CHECK4-LABEL: define void @_ZN5test44testEv()
// CHECK4: call void @_ZN5test41CC1Ev(%"struct.test4::C"*
// CHECK4: %[[VTABLE:.*]] = load i8**, i8*** %{{.*}}
-// CHECK4: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr inbounds ([5 x i8*], [5 x i8*]* @_ZTVN5test41CE, i32 0, i32 4)
+// CHECK4: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr inbounds ({ [5 x i8*] }, { [5 x i8*] }* @_ZTVN5test41CE, i32 0, inrange i32 0, i32 4)
// CHECK4: call void @llvm.assume(i1 %[[CMP]]
// CHECK4: %[[VTABLE2:.*]] = load i8**, i8*** %{{.*}}
-// CHECK4: %[[CMP2:.*]] = icmp eq i8** %[[VTABLE2]], getelementptr inbounds ([5 x i8*], [5 x i8*]* @_ZTVN5test41CE, i32 0, i32 4)
+// CHECK4: %[[CMP2:.*]] = icmp eq i8** %[[VTABLE2]], getelementptr inbounds ({ [5 x i8*] }, { [5 x i8*] }* @_ZTVN5test41CE, i32 0, inrange i32 0, i32 4)
// CHECK4: call void @llvm.assume(i1 %[[CMP2]])
-// CHECK4-LABEL: }
+// CHECK4-LABEL: {{^}}}
void test() {
C c;
@@ -166,7 +166,7 @@ void g(S &s) { s.foo(); }
// CHECK-MS-LABEL: define void @"\01?test@testMS@@YAXXZ"()
// CHECK-MS: call x86_thiscallcc %"struct.testMS::S"* @"\01??0S@testMS@@QAE@XZ"(
// CHECK-MS-NOT: @llvm.assume
-// CHECK-MS-LABEL: }
+// CHECK-MS-LABEL: {{^}}}
void test() {
S s;
@@ -196,7 +196,7 @@ struct B : A {
// CHECK6-LABEL: call void @_ZN5test61BC1Ev(
// CHECK6-NOT: call void @llvm.assume(
-// CHECK6-LABEL: }
+// CHECK6-LABEL: {{^}}}
void g() {
A *a = new A;
B *b = new B;
@@ -216,7 +216,7 @@ void A::foo() {}
// CHECK7-LABEL: define void @_ZN5test71gEv()
// CHECK7: call void @_ZN5test71AC1Ev(
// CHECK7: call void @llvm.assume(
-// CHECK7-LABEL: }
+// CHECK7-LABEL: {{^}}}
void g() {
A *a = new A();
a->bar();
@@ -259,7 +259,7 @@ struct E : A {
// CHECK8-LABEL: define void @_ZN5test81bEv()
// CHECK8: call void @llvm.assume(
-// CHECK8-LABEL: }
+// CHECK8-LABEL: {{^}}}
void b() {
B b;
b.bar();
@@ -270,7 +270,7 @@ void b() {
// defined here) it would be correct to refer to it.
// CHECK8-LABEL: define void @_ZN5test81cEv()
// CHECK8-NOT: call void @llvm.assume(
-// CHECK8-LABEL: }
+// CHECK8-LABEL: {{^}}}
void c() {
C c;
c.bar();
@@ -279,7 +279,7 @@ void c() {
// FIXME: We could generate assumption loads here.
// CHECK8-LABEL: define void @_ZN5test81dEv()
// CHECK8-NOT: call void @llvm.assume(
-// CHECK8-LABEL: }
+// CHECK8-LABEL: {{^}}}
void d() {
D d;
d.bar();
@@ -287,7 +287,7 @@ void d() {
// CHECK8-LABEL: define void @_ZN5test81eEv()
// CHECK8: call void @llvm.assume(
-// CHECK8-LABEL: }
+// CHECK8-LABEL: {{^}}}
void e() {
E e;
e.bar();
diff --git a/test/CodeGenCXX/vtable-available-externally.cpp b/test/CodeGenCXX/vtable-available-externally.cpp
index f38d177666e6..ae81959a75e9 100644
--- a/test/CodeGenCXX/vtable-available-externally.cpp
+++ b/test/CodeGenCXX/vtable-available-externally.cpp
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -emit-llvm -o %t
-// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -O2 -disable-llvm-optzns -emit-llvm -o %t.opt
+// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -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
diff --git a/test/CodeGenCXX/vtable-layout.cpp b/test/CodeGenCXX/vtable-layout.cpp
index ca5384d6e031..4a47e3c9d2e8 100644
--- a/test/CodeGenCXX/vtable-layout.cpp
+++ b/test/CodeGenCXX/vtable-layout.cpp
@@ -1919,6 +1919,8 @@ namespace Test40 {
virtual int i(int);
virtual int i();
};
+ // Force C's vtable to be generated.
+ int C::f() { return 1; }
class D : C {};
diff --git a/test/CodeGenCXX/vtable-linkage.cpp b/test/CodeGenCXX/vtable-linkage.cpp
index 0b556d10c3e8..c4ebf75b999a 100644
--- a/test/CodeGenCXX/vtable-linkage.cpp
+++ b/test/CodeGenCXX/vtable-linkage.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 %s -triple=x86_64-pc-linux -emit-llvm -o %t
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -disable-llvm-optzns -O3 -emit-llvm -o %t.opt
+// RUN: %clang_cc1 %s -triple=x86_64-pc-linux -emit-llvm -std=c++03 -o %t.03
+// RUN: %clang_cc1 %s -triple=x86_64-pc-linux -emit-llvm -std=c++11 -o %t.11
+// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -disable-llvm-passes -O3 -emit-llvm -o %t.opt
// RUN: FileCheck %s < %t
+// RUN: FileCheck %s < %t.03
+// RUN: FileCheck %s < %t.11
// RUN: FileCheck --check-prefix=CHECK-OPT %s < %t.opt
namespace {
@@ -33,6 +37,11 @@ void D::f() { }
static struct : D { } e;
+// Force 'e' to be constructed and therefore have a vtable defined.
+void use_e() {
+ e.f();
+}
+
// The destructor is the key function.
template<typename T>
struct E {
diff --git a/test/CodeGenCXX/vtable-pointer-initialization.cpp b/test/CodeGenCXX/vtable-pointer-initialization.cpp
index 130a55cf6218..49c8de4ea4f5 100644
--- a/test/CodeGenCXX/vtable-pointer-initialization.cpp
+++ b/test/CodeGenCXX/vtable-pointer-initialization.cpp
@@ -21,13 +21,13 @@ struct A : Base {
// CHECK-LABEL: define void @_ZN1AC2Ev(%struct.A* %this) unnamed_addr
// CHECK: call void @_ZN4BaseC2Ev(
-// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1A, i32 0, i32 2) to i32 (...)**)
+// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTV1A, i32 0, inrange i32 0, i32 2) to i32 (...)**)
// CHECK: call void @_ZN5FieldC1Ev(
// CHECK: ret void
A::A() { }
// CHECK-LABEL: define void @_ZN1AD2Ev(%struct.A* %this) unnamed_addr
-// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1A, i32 0, i32 2) to i32 (...)**)
+// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTV1A, i32 0, inrange i32 0, i32 2) to i32 (...)**)
// CHECK: call void @_ZN5FieldD1Ev(
// CHECK: call void @_ZN4BaseD2Ev(
// CHECK: ret void
@@ -49,12 +49,12 @@ void f() { B b; }
// CHECK-LABEL: define linkonce_odr void @_ZN1BC2Ev(%struct.B* %this) unnamed_addr
// CHECK: call void @_ZN4BaseC2Ev(
-// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1B, i32 0, i32 2) to i32 (...)**)
+// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTV1B, i32 0, inrange i32 0, i32 2) to i32 (...)**)
// CHECK: call void @_ZN5FieldC1Ev
// CHECK: ret void
// CHECK-LABEL: define linkonce_odr void @_ZN1BD2Ev(%struct.B* %this) unnamed_addr
-// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1B, i32 0, i32 2) to i32 (...)**)
+// CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTV1B, i32 0, inrange i32 0, i32 2) to i32 (...)**)
// CHECK: call void @_ZN5FieldD1Ev(
// CHECK: call void @_ZN4BaseD2Ev(
// CHECK: ret void
diff --git a/test/CodeGenCXX/vtt-layout.cpp b/test/CodeGenCXX/vtt-layout.cpp
index 7ff93dd451c9..a5f7802577c8 100644
--- a/test/CodeGenCXX/vtt-layout.cpp
+++ b/test/CodeGenCXX/vtt-layout.cpp
@@ -78,11 +78,12 @@ namespace Test6 {
}
}
-// CHECK: @_ZTTN5Test11BE = unnamed_addr constant [1 x i8*] [i8* bitcast (i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @_ZTVN5Test11BE, i32 0, i32 3) to i8*)]
-// CHECK: @_ZTVN5Test51AE = unnamed_addr constant [4 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTIN5Test51AE to i8*), i8* bitcast (void ()* @__cxa_pure_virtual to i8*), i8* bitcast (void (%"struct.Test5::A"*)* @_ZN5Test51A6anchorEv to i8*)]
-// CHECK: @_ZTVN5Test61AE = unnamed_addr constant [4 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTIN5Test61AE to i8*), i8* bitcast (void ()* @__cxa_deleted_virtual to i8*), i8* bitcast (void (%"struct.Test6::A"*)* @_ZN5Test61A6anchorEv to i8*)]
-// CHECK: @_ZTTN5Test21CE = linkonce_odr unnamed_addr constant [2 x i8*] [i8* bitcast (i8** getelementptr inbounds ([5 x i8*], [5 x i8*]* @_ZTVN5Test21CE, i32 0, i32 4) to i8*), i8* bitcast (i8** getelementptr inbounds ([5 x i8*], [5 x i8*]* @_ZTVN5Test21CE, i32 0, i32 4) to i8*)]
-// CHECK: @_ZTTN5Test31DE = linkonce_odr unnamed_addr constant [13 x i8*] [i8* bitcast (i8** getelementptr inbounds ([19 x i8*], [19 x i8*]* @_ZTVN5Test31DE, i32 0, i32 5) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*], [7 x i8*]* @_ZTCN5Test31DE0_NS_2C1E, i32 0, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*], [7 x i8*]* @_ZTCN5Test31DE0_NS_2C1E, i32 0, i32 6) to i8*), i8* bitcast (i8** getelementptr inbounds ([14 x i8*], [14 x i8*]* @_ZTCN5Test31DE16_NS_2C2E, i32 0, i32 6) to i8*), i8* bitcast (i8** getelementptr inbounds ([14 x i8*], [14 x i8*]* @_ZTCN5Test31DE16_NS_2C2E, i32 0, i32 6) to i8*), i8* bitcast (i8** getelementptr inbounds ([14 x i8*], [14 x i8*]* @_ZTCN5Test31DE16_NS_2C2E, i32 0, i32 10) to i8*), i8* bitcast (i8** getelementptr inbounds ([14 x i8*], [14 x i8*]* @_ZTCN5Test31DE16_NS_2C2E, i32 0, i32 13) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*], [19 x i8*]* @_ZTVN5Test31DE, i32 0, i32 15) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*], [19 x i8*]* @_ZTVN5Test31DE, i32 0, i32 11) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*], [19 x i8*]* @_ZTVN5Test31DE, i32 0, i32 11) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*], [19 x i8*]* @_ZTVN5Test31DE, i64 1, i32 0) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*], [7 x i8*]* @_ZTCN5Test31DE64_NS_2V2E, i32 0, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*], [7 x i8*]* @_ZTCN5Test31DE64_NS_2V2E, i32 0, i32 6) to i8*)]
-// CHECK: @_ZTTN5Test41DE = linkonce_odr unnamed_addr constant [19 x i8*] [i8* bitcast (i8** getelementptr inbounds ([25 x i8*], [25 x i8*]* @_ZTVN5Test41DE, i32 0, i32 6) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*], [11 x i8*]* @_ZTCN5Test41DE0_NS_2C1E, i32 0, i32 4) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*], [11 x i8*]* @_ZTCN5Test41DE0_NS_2C1E, i32 0, i32 7) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*], [11 x i8*]* @_ZTCN5Test41DE0_NS_2C1E, i32 0, i32 10) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*], [19 x i8*]* @_ZTCN5Test41DE16_NS_2C2E, i32 0, i32 7) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*], [19 x i8*]* @_ZTCN5Test41DE16_NS_2C2E, i32 0, i32 7) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*], [19 x i8*]* @_ZTCN5Test41DE16_NS_2C2E, i32 0, i32 12) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*], [19 x i8*]* @_ZTCN5Test41DE16_NS_2C2E, i32 0, i32 15) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*], [19 x i8*]* @_ZTCN5Test41DE16_NS_2C2E, i32 0, i32 18) to i8*), i8* bitcast (i8** getelementptr inbounds ([25 x i8*], [25 x i8*]* @_ZTVN5Test41DE, i32 0, i32 17) to i8*), i8* bitcast (i8** getelementptr inbounds ([25 x i8*], [25 x i8*]* @_ZTVN5Test41DE, i32 0, i32 20) to i8*), i8* bitcast (i8** getelementptr inbounds ([25 x i8*], [25 x i8*]* @_ZTVN5Test41DE, i32 0, i32 13) to i8*), i8* bitcast (i8** getelementptr inbounds ([25 x i8*], [25 x i8*]* @_ZTVN5Test41DE, i32 0, i32 13) to i8*), i8* bitcast (i8** getelementptr inbounds ([25 x i8*], [25 x i8*]* @_ZTVN5Test41DE, i64 1, i32 0) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*], [7 x i8*]* @_ZTCN5Test41DE40_NS_2V1E, i32 0, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*], [7 x i8*]* @_ZTCN5Test41DE40_NS_2V1E, i32 0, i32 6) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*], [11 x i8*]* @_ZTCN5Test41DE72_NS_2V2E, i32 0, i32 4) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*], [11 x i8*]* @_ZTCN5Test41DE72_NS_2V2E, i32 0, i32 7) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*], [11 x i8*]* @_ZTCN5Test41DE72_NS_2V2E, i32 0, i32 10) to i8*)]
+// CHECK: @_ZTTN5Test11BE = unnamed_addr constant [1 x i8*] [i8* bitcast (i8** getelementptr inbounds ({ [4 x i8*] }, { [4 x i8*] }* @_ZTVN5Test11BE, i32 0, inrange i32 0, i32 3) to i8*)]
+// CHECK: @_ZTVN5Test51AE = unnamed_addr constant { [4 x i8*] } { [4 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTIN5Test51AE to i8*), i8* bitcast (void ()* @__cxa_pure_virtual to i8*), i8* bitcast (void (%"struct.Test5::A"*)* @_ZN5Test51A6anchorEv to i8*)] }
+// CHECK: @_ZTVN5Test61AE = unnamed_addr constant { [4 x i8*] } { [4 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTIN5Test61AE to i8*), i8* bitcast (void ()* @__cxa_deleted_virtual to i8*), i8* bitcast (void (%"struct.Test6::A"*)* @_ZN5Test61A6anchorEv to i8*)] }
+// CHECK: @_ZTTN5Test21CE = linkonce_odr unnamed_addr constant [2 x i8*] [i8* bitcast (i8** getelementptr inbounds ({ [5 x i8*] }, { [5 x i8*] }* @_ZTVN5Test21CE, i32 0, inrange i32 0, i32 4) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [5 x i8*] }, { [5 x i8*] }* @_ZTVN5Test21CE, i32 0, inrange i32 0, i32 4) to i8*)]
+// CHECK: @_ZTTN5Test31DE = linkonce_odr unnamed_addr constant [13 x i8*] [i8* bitcast (i8** getelementptr inbounds ({ [5 x i8*], [7 x i8*], [4 x i8*], [3 x i8*] }, { [5 x i8*], [7 x i8*], [4 x i8*], [3 x i8*] }* @_ZTVN5Test31DE, i32 0, inrange i32 0, i32 5) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [3 x i8*], [4 x i8*] }, { [3 x i8*], [4 x i8*] }* @_ZTCN5Test31DE0_NS_2C1E, i32 0, inrange i32 0, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [3 x i8*], [4 x i8*] }, { [3 x i8*], [4 x i8*] }* @_ZTCN5Test31DE0_NS_2C1E, i32 0, inrange i32 1, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [7 x i8*], [3 x i8*], [4 x i8*] }, { [7 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test31DE16_NS_2C2E, i32 0, inrange i32 0, i32 6) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [7 x i8*], [3 x i8*], [4 x i8*] }, { [7 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test31DE16_NS_2C2E, i32 0, inrange i32 0, i32 6) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [7 x i8*], [3 x i8*], [4 x i8*] }, { [7 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test31DE16_NS_2C2E, i32 0, inrange i32 1, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [7 x i8*], [3 x i8*], [4 x i8*] }, { [7 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test31DE16_NS_2C2E, i32 0, inrange i32 2, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [5 x i8*], [7 x i8*], [4 x i8*], [3 x i8*] }, { [5 x i8*], [7 x i8*], [4 x i8*], [3 x i8*] }* @_ZTVN5Test31DE, i32 0, inrange i32 2, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [5 x i8*], [7 x i8*], [4 x i8*], [3 x i8*] }, { [5 x i8*], [7 x i8*], [4 x i8*], [3 x i8*] }* @_ZTVN5Test31DE, i32 0, inrange i32 1, i32 6) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [5 x i8*], [7 x i8*], [4 x i8*], [3 x i8*] }, { [5 x i8*], [7 x i8*], [4 x i8*], [3 x i8*] }* @_ZTVN5Test31DE, i32 0, inrange i32 1, i32 6) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [5 x i8*], [7 x i8*], [4 x i8*], [3 x i8*] }, { [5 x i8*], [7 x i8*], [4 x i8*], [3 x i8*] }* @_ZTVN5Test31DE, i32 0, inrange i32 3, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [3 x i8*], [4 x i8*] }, { [3 x i8*], [4 x i8*] }* @_ZTCN5Test31DE64_NS_2V2E, i32 0, inrange i32 0, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [3 x i8*], [4 x i8*] }, { [3 x i8*], [4 x i8*] }* @_ZTCN5Test31DE64_NS_2V2E, i32 0, inrange i32 1, i32 3) to i8*)]
+// CHECK: @_ZTVN5Test41DE = linkonce_odr unnamed_addr constant { [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] } { [6 x i8*] [i8* inttoptr (i64 72 to i8*), i8* inttoptr (i64 16 to i8*), i8* inttoptr (i64 56 to i8*), i8* inttoptr (i64 40 to i8*), i8* null, i8* bitcast ({ i8*, i8*, i32, i32, i8*, i64, i8*, i64, i8*, i64 }* @_ZTIN5Test41DE to i8*)], [8 x i8*] [i8* inttoptr (i64 40 to i8*), i8* inttoptr (i64 24 to i8*), i8* inttoptr (i64 56 to i8*), i8* null, i8* null, i8* inttoptr (i64 -16 to i8*), i8* bitcast ({ i8*, i8*, i32, i32, i8*, i64, i8*, i64, i8*, i64 }* @_ZTIN5Test41DE to i8*), i8* bitcast (void (%"class.Test4::V3"*)* @_ZN5Test42V31gEv to i8*)], [3 x i8*] [i8* inttoptr (i64 16 to i8*), i8* inttoptr (i64 -40 to i8*), i8* bitcast ({ i8*, i8*, i32, i32, i8*, i64, i8*, i64, i8*, i64 }* @_ZTIN5Test41DE to i8*)], [4 x i8*] [i8* null, i8* inttoptr (i64 -56 to i8*), i8* bitcast ({ i8*, i8*, i32, i32, i8*, i64, i8*, i64, i8*, i64 }* @_ZTIN5Test41DE to i8*), i8* bitcast (void (%"class.Test4::A2"*)* @_ZN5Test42A21fEv to i8*)], [4 x i8*] [i8* inttoptr (i64 -16 to i8*), i8* inttoptr (i64 -32 to i8*), i8* inttoptr (i64 -72 to i8*), i8* bitcast ({ i8*, i8*, i32, i32, i8*, i64, i8*, i64, i8*, i64 }* @_ZTIN5Test41DE to i8*)] }
+// CHECK: @_ZTTN5Test41DE = linkonce_odr unnamed_addr constant [19 x i8*] [i8* bitcast (i8** getelementptr inbounds ({ [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] }, { [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] }* @_ZTVN5Test41DE, i32 0, inrange i32 0, i32 6) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [4 x i8*], [3 x i8*], [4 x i8*] }, { [4 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE0_NS_2C1E, i32 0, inrange i32 0, i32 4) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [4 x i8*], [3 x i8*], [4 x i8*] }, { [4 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE0_NS_2C1E, i32 0, inrange i32 1, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [4 x i8*], [3 x i8*], [4 x i8*] }, { [4 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE0_NS_2C1E, i32 0, inrange i32 2, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [8 x i8*], [4 x i8*], [3 x i8*], [4 x i8*] }, { [8 x i8*], [4 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE16_NS_2C2E, i32 0, inrange i32 0, i32 7) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [8 x i8*], [4 x i8*], [3 x i8*], [4 x i8*] }, { [8 x i8*], [4 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE16_NS_2C2E, i32 0, inrange i32 0, i32 7) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [8 x i8*], [4 x i8*], [3 x i8*], [4 x i8*] }, { [8 x i8*], [4 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE16_NS_2C2E, i32 0, inrange i32 1, i32 4) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [8 x i8*], [4 x i8*], [3 x i8*], [4 x i8*] }, { [8 x i8*], [4 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE16_NS_2C2E, i32 0, inrange i32 2, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [8 x i8*], [4 x i8*], [3 x i8*], [4 x i8*] }, { [8 x i8*], [4 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE16_NS_2C2E, i32 0, inrange i32 3, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] }, { [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] }* @_ZTVN5Test41DE, i32 0, inrange i32 2, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] }, { [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] }* @_ZTVN5Test41DE, i32 0, inrange i32 3, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] }, { [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] }* @_ZTVN5Test41DE, i32 0, inrange i32 1, i32 7) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] }, { [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] }* @_ZTVN5Test41DE, i32 0, inrange i32 1, i32 7) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] }, { [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] }* @_ZTVN5Test41DE, i32 0, inrange i32 4, i32 4) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [3 x i8*], [4 x i8*] }, { [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE40_NS_2V1E, i32 0, inrange i32 0, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [3 x i8*], [4 x i8*] }, { [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE40_NS_2V1E, i32 0, inrange i32 1, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [4 x i8*], [3 x i8*], [4 x i8*] }, { [4 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE72_NS_2V2E, i32 0, inrange i32 0, i32 4) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [4 x i8*], [3 x i8*], [4 x i8*] }, { [4 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE72_NS_2V2E, i32 0, inrange i32 1, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [4 x i8*], [3 x i8*], [4 x i8*] }, { [4 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE72_NS_2V2E, i32 0, inrange i32 2, i32 3) to i8*)]
// CHECK: declare void @__cxa_pure_virtual() unnamed_addr
// CHECK: declare void @__cxa_deleted_virtual() unnamed_addr
diff --git a/test/CodeGenCXX/wasm-args-returns.cpp b/test/CodeGenCXX/wasm-args-returns.cpp
index 2b80430014d0..24adc8e08761 100644
--- a/test/CodeGenCXX/wasm-args-returns.cpp
+++ b/test/CodeGenCXX/wasm-args-returns.cpp
@@ -14,7 +14,7 @@
struct one_field { double d; };
test(one_field);
-// CHECK: define double @_Z7forward9one_field(double %{{.*}})
+// CHECK: define double @_Z7forward9one_field(double returned %{{.*}})
//
// CHECK: define void @_Z14test_one_fieldv()
// CHECK: %[[call:.*]] = tail call double @_Z13def_one_fieldv()
@@ -89,7 +89,7 @@ struct one_bitfield {
int d:3;
};
test(one_bitfield);
-// CHECK: define i32 @_Z7forward12one_bitfield(i32 %{{.*}})
+// CHECK: define i32 @_Z7forward12one_bitfield(i32 returned %{{.*}})
//
// CHECK: define void @_Z17test_one_bitfieldv()
// CHECK: %[[call:.*]] = tail call i32 @_Z16def_one_bitfieldv()
diff --git a/test/CodeGenCXX/windows-implicit-dllexport-template-specialization.cpp b/test/CodeGenCXX/windows-implicit-dllexport-template-specialization.cpp
new file mode 100644
index 000000000000..c2f2a0773e90
--- /dev/null
+++ b/test/CodeGenCXX/windows-implicit-dllexport-template-specialization.cpp
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -std=c++11 -triple i686-windows -fdeclspec -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MS
+// RUN: %clang_cc1 -std=c++11 -triple i686-windows-itanium -fdeclspec -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-IA
+
+template <typename>
+struct s {};
+
+template <typename T_>
+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-IA: dllexport {{.*}} @_ZN1tIcEaSERKS0_
+// CHECK-IA: dllexport {{.*}} @_ZN1sIcEaSERKS0_
+
diff --git a/test/CodeGenCXX/windows-itanium-dllexport.cpp b/test/CodeGenCXX/windows-itanium-dllexport.cpp
new file mode 100644
index 000000000000..92cca2444287
--- /dev/null
+++ b/test/CodeGenCXX/windows-itanium-dllexport.cpp
@@ -0,0 +1,30 @@
+// RUN: %clang_cc1 -emit-llvm -triple i686-windows-itanium -fdeclspec %s -o - | FileCheck %s
+
+struct __declspec(dllexport) s {
+ void f() {}
+};
+
+// CHECK: define {{.*}} dllexport {{.*}} @_ZN1saSERKS_
+// CHECK: define {{.*}} dllexport {{.*}} @_ZN1s1fEv
+
+template <class T>
+class c {
+ void f() {}
+};
+
+template class __declspec(dllexport) c<int>;
+
+// CHECK: define {{.*}} dllexport {{.*}} @_ZN1cIiEaSERKS0_
+// CHECK: define {{.*}} dllexport {{.*}} @_ZN1cIiE1fEv
+
+extern template class c<char>;
+template class __declspec(dllexport) c<char>;
+
+// CHECK: define {{.*}} dllexport {{.*}} @_ZN1cIcEaSERKS0_
+// CHECK: define {{.*}} dllexport {{.*}} @_ZN1cIcE1fEv
+
+c<double> g;
+template class __declspec(dllexport) c<double>;
+
+// CHECK: define {{.*}} dllexport {{.*}} @_ZN1cIdEaSERKS0_
+// CHECK: define {{.*}} dllexport {{.*}} @_ZN1cIdE1fEv
diff --git a/test/CodeGenCXX/windows-itanium-type-info.cpp b/test/CodeGenCXX/windows-itanium-type-info.cpp
new file mode 100644
index 000000000000..ad89318f599e
--- /dev/null
+++ b/test/CodeGenCXX/windows-itanium-type-info.cpp
@@ -0,0 +1,40 @@
+// RUN: %clang_cc1 -triple i686-windows-itanium -fdeclspec -fcxx-exceptions -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple i686-windows-itanium -fdeclspec -fcxx-exceptions -fno-rtti -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-EH-IMPORT
+
+namespace __cxxabiv1 {
+class __declspec(dllexport) __fundamental_type_info {
+public:
+ virtual ~__fundamental_type_info();
+};
+
+__fundamental_type_info::~__fundamental_type_info() {}
+}
+
+struct __declspec(dllimport) base {
+ virtual void method();
+};
+struct __declspec(dllexport) derived : base {
+ virtual ~derived();
+};
+derived::~derived() {
+ method();
+}
+
+void f() {
+ throw base();
+}
+
+// CHECK-DAG: @_ZTIi = dllexport constant
+// CHECK-DAG: @_ZTSi = dllexport constant
+
+// CHECK-DAG: @_ZTI7derived = dllexport constant
+// CHECK-DAG: @_ZTS7derived = dllexport constant
+// CHECK-DAG: @_ZTV7derived = dllexport unnamed_addr constant
+
+// CHECK-DAG: @_ZTI4base = external dllimport constant
+// CHECK-DAG: @_ZTS4base = external dllimport constant
+// CHECK-NOT: @_ZTV4base = external dllimport constant
+
+// CHECK-EH-IMPORT: @_ZTS4base = linkonce_odr constant
+// CHECK-EH-IMPORT: @_ZTI4base = linkonce_odr constant
+
diff --git a/test/CodeGenCoroutines/coro-alloc.cpp b/test/CodeGenCoroutines/coro-alloc.cpp
new file mode 100644
index 000000000000..7dbbdd31be08
--- /dev/null
+++ b/test/CodeGenCoroutines/coro-alloc.cpp
@@ -0,0 +1,114 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fcoroutines-ts -std=c++14 -emit-llvm %s -o - -disable-llvm-passes | FileCheck %s
+
+namespace std {
+namespace experimental {
+template <typename... T>
+struct coroutine_traits; // expected-note {{declared here}}
+}
+}
+
+struct suspend_always {
+ bool await_ready() { return false; }
+ void await_suspend() {}
+ void await_resume() {}
+};
+
+struct global_new_delete_tag {};
+
+template<>
+struct std::experimental::coroutine_traits<void, global_new_delete_tag> {
+ struct promise_type {
+ void get_return_object() {}
+ suspend_always initial_suspend() { return {}; }
+ suspend_always final_suspend() { return {}; }
+ void return_void() {}
+ };
+};
+
+// CHECK-LABEL: f0(
+extern "C" void f0(global_new_delete_tag) {
+ // CHECK: %[[ID:.+]] = call token @llvm.coro.id(i32 16
+ // CHECK: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64()
+ // CHECK: call i8* @_Znwm(i64 %[[SIZE]])
+
+ // CHECK: %[[FRAME:.+]] = call i8* @llvm.coro.frame()
+ // CHECK: %[[MEM:.+]] = call i8* @llvm.coro.free(token %[[ID]], i8* %[[FRAME]])
+ // CHECK: call void @_ZdlPv(i8* %[[MEM]])
+ co_await suspend_always{};
+}
+
+struct promise_new_tag {};
+
+template<>
+struct std::experimental::coroutine_traits<void, promise_new_tag> {
+ struct promise_type {
+ void *operator new(unsigned long);
+ void get_return_object() {}
+ suspend_always initial_suspend() { return {}; }
+ suspend_always final_suspend() { return {}; }
+ void return_void() {}
+ };
+};
+
+// CHECK-LABEL: f1(
+extern "C" void f1(promise_new_tag ) {
+ // CHECK: %[[ID:.+]] = call token @llvm.coro.id(i32 16
+ // CHECK: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64()
+ // CHECK: call i8* @_ZNSt12experimental16coroutine_traitsIJv15promise_new_tagEE12promise_typenwEm(i64 %[[SIZE]])
+
+ // CHECK: %[[FRAME:.+]] = call i8* @llvm.coro.frame()
+ // CHECK: %[[MEM:.+]] = call i8* @llvm.coro.free(token %[[ID]], i8* %[[FRAME]])
+ // CHECK: call void @_ZdlPv(i8* %[[MEM]])
+ co_await suspend_always{};
+}
+
+struct promise_delete_tag {};
+
+template<>
+struct std::experimental::coroutine_traits<void, promise_delete_tag> {
+ struct promise_type {
+ void operator delete(void*);
+ void get_return_object() {}
+ suspend_always initial_suspend() { return {}; }
+ suspend_always final_suspend() { return {}; }
+ void return_void() {}
+ };
+};
+
+// CHECK-LABEL: f2(
+extern "C" void f2(promise_delete_tag) {
+ // CHECK: %[[ID:.+]] = call token @llvm.coro.id(i32 16
+ // CHECK: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64()
+ // CHECK: call i8* @_Znwm(i64 %[[SIZE]])
+
+ // CHECK: %[[FRAME:.+]] = call i8* @llvm.coro.frame()
+ // CHECK: %[[MEM:.+]] = call i8* @llvm.coro.free(token %[[ID]], i8* %[[FRAME]])
+ // CHECK: call void @_ZNSt12experimental16coroutine_traitsIJv18promise_delete_tagEE12promise_typedlEPv(i8* %[[MEM]])
+ co_await suspend_always{};
+}
+
+struct promise_sized_delete_tag {};
+
+template<>
+struct std::experimental::coroutine_traits<void, promise_sized_delete_tag> {
+ struct promise_type {
+ void operator delete(void*, unsigned long);
+ void get_return_object() {}
+ suspend_always initial_suspend() { return {}; }
+ suspend_always final_suspend() { return {}; }
+ void return_void() {}
+ };
+};
+
+// CHECK-LABEL: f3(
+extern "C" void f3(promise_sized_delete_tag) {
+ // CHECK: %[[ID:.+]] = call token @llvm.coro.id(i32 16
+ // CHECK: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64()
+ // CHECK: call i8* @_Znwm(i64 %[[SIZE]])
+
+ // CHECK: %[[FRAME:.+]] = call i8* @llvm.coro.frame()
+ // CHECK: %[[MEM:.+]] = call i8* @llvm.coro.free(token %[[ID]], i8* %[[FRAME]])
+ // CHECK: %[[SIZE2:.+]] = call i64 @llvm.coro.size.i64()
+ // CHECK: call void @_ZNSt12experimental16coroutine_traitsIJv24promise_sized_delete_tagEE12promise_typedlEPvm(i8* %[[MEM]], i64 %[[SIZE2]])
+ co_await suspend_always{};
+}
diff --git a/test/CodeGenCoroutines/coro-builtins-err.c b/test/CodeGenCoroutines/coro-builtins-err.c
new file mode 100644
index 000000000000..dfd2542886bc
--- /dev/null
+++ b/test/CodeGenCoroutines/coro-builtins-err.c
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc18.0.0 -fcoroutines-ts -emit-llvm %s -o - -verify
+
+void f() {
+ __builtin_coro_alloc(); // expected-error {{this builtin expect that __builtin_coro_id}}
+ __builtin_coro_begin(0); // expected-error {{this builtin expect that __builtin_coro_id}}
+ __builtin_coro_free(0); // expected-error {{this builtin expect that __builtin_coro_id}}
+
+ __builtin_coro_id(32, 0, 0, 0);
+ __builtin_coro_id(32, 0, 0, 0); // expected-error {{only one __builtin_coro_id}}
+}
diff --git a/test/CodeGenCoroutines/coro-builtins.c b/test/CodeGenCoroutines/coro-builtins.c
new file mode 100644
index 000000000000..5c3e6c3a6bdf
--- /dev/null
+++ b/test/CodeGenCoroutines/coro-builtins.c
@@ -0,0 +1,56 @@
+// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc18.0.0 -fcoroutines-ts -emit-llvm %s -o - -disable-llvm-passes | FileCheck %s
+
+void *myAlloc(long long);
+
+// CHECK-LABEL: f(
+void f(int n) {
+ // CHECK: %n.addr = alloca i32
+ // CHECK: %n_copy = alloca i32
+ // CHECK: %promise = alloca i32
+ int n_copy;
+ int promise;
+
+ // CHECK: %[[PROM_ADDR:.+]] = bitcast i32* %promise to i8*
+ // CHECK-NEXT: %[[COROID:.+]] = call token @llvm.coro.id(i32 32, i8* %[[PROM_ADDR]], i8* null, i8* null)
+ __builtin_coro_id(32, &promise, 0, 0);
+
+ // CHECK-NEXT: call i1 @llvm.coro.alloc(token %[[COROID]])
+ __builtin_coro_alloc();
+
+ // CHECK-NEXT: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64()
+ // CHECK-NEXT: %[[MEM:.+]] = call i8* @myAlloc(i64 %[[SIZE]])
+ // CHECK-NEXT: %[[BEG:.+]] = call i8* @llvm.coro.begin(token %[[COROID]], i8* %[[MEM]])
+ __builtin_coro_begin(myAlloc(__builtin_coro_size()));
+
+ // CHECK-NEXT: %[[FRAME1:.+]] = call i8* @llvm.coro.frame()
+ // CHECK-NEXT: call void @llvm.coro.resume(i8* %[[FRAME1]])
+ __builtin_coro_resume(__builtin_coro_frame());
+
+ // CHECK-NEXT: %[[FRAME2:.+]] = call i8* @llvm.coro.frame()
+ // CHECK-NEXT: call void @llvm.coro.destroy(i8* %[[FRAME2]])
+ __builtin_coro_destroy(__builtin_coro_frame());
+
+ // CHECK-NEXT: %[[FRAME3:.+]] = call i8* @llvm.coro.frame()
+ // CHECK-NEXT: call i1 @llvm.coro.done(i8* %[[FRAME3]])
+ __builtin_coro_done(__builtin_coro_frame());
+
+ // CHECK-NEXT: %[[FRAME4:.+]] = call i8* @llvm.coro.frame()
+ // CHECK-NEXT: call i8* @llvm.coro.promise(i8* %[[FRAME4]], i32 48, i1 false)
+ __builtin_coro_promise(__builtin_coro_frame(), 48, 0);
+
+ // CHECK-NEXT: %[[FRAME5:.+]] = call i8* @llvm.coro.frame()
+ // CHECK-NEXT: call i8* @llvm.coro.free(token %[[COROID]], i8* %[[FRAME5]])
+ __builtin_coro_free(__builtin_coro_frame());
+
+ // CHECK-NEXT: %[[FRAME6:.+]] = call i8* @llvm.coro.frame()
+ // CHECK-NEXT: call void @llvm.coro.end(i8* %[[FRAME6]], i1 false)
+ __builtin_coro_end(__builtin_coro_frame(), 0);
+
+ // CHECK-NEXT: call i8 @llvm.coro.suspend(token none, i1 true)
+ __builtin_coro_suspend(1);
+
+ // CHECK-NEXT: %[[N_ADDR:.+]] = bitcast i32* %n.addr to i8*
+ // CHECK-NEXT: %[[N_COPY_ADDR:.+]] = bitcast i32* %n_copy to i8*
+ // CHECK-NEXT: call i1 @llvm.coro.param(i8* %[[N_ADDR]], i8* %[[N_COPY_ADDR]])
+ __builtin_coro_param(&n, &n_copy);
+}
diff --git a/test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp b/test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp
new file mode 100644
index 000000000000..1921c06e5af0
--- /dev/null
+++ b/test/CodeGenCoroutines/microsoft-abi-operator-coawait.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc18.0.0 -fcoroutines-ts -emit-llvm %s -o - -std=c++14 -disable-llvm-passes | FileCheck %s
+struct no_suspend {
+ bool await_ready() { return true; }
+ template <typename F> void await_suspend(F) {}
+ void await_resume() {}
+};
+
+struct A {
+ no_suspend operator co_await() { return {}; }
+};
+
+struct B {};
+
+no_suspend operator co_await(B const&) { return {}; }
+
+// CHECK-LABEL: f(
+extern "C" void f() {
+ A a;
+ B b;
+ // CHECK: call void @"\01??__LA@@QEAA?AUno_suspend@@XZ"(
+ a.operator co_await();
+ // CHECK-NEXT: call i8 @"\01??__L@YA?AUno_suspend@@AEBUB@@@Z"(
+ operator co_await(b);
+}
+
diff --git a/test/CodeGenObjC/2010-02-01-utf16-with-null.m b/test/CodeGenObjC/2010-02-01-utf16-with-null.m
index 7c103f2ba6d4..097a3ea2b403 100644
--- a/test/CodeGenObjC/2010-02-01-utf16-with-null.m
+++ b/test/CodeGenObjC/2010-02-01-utf16-with-null.m
@@ -2,6 +2,6 @@
// rdar://7589850
// CHECK: @.str = private unnamed_addr constant [9 x i16] [i16 103, i16 111, i16 111, i16 100, i16 0, i16 98, i16 121, i16 101, i16 0], section "__TEXT,__ustring", align 2
-// CHECK: @_unnamed_cfstring_ = private constant %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 2000, i8* bitcast ([9 x i16]* @.str to i8*), i32 8 }, section "__DATA,__cfstring"
+// CHECK: @_unnamed_cfstring_ = private global %struct.__NSConstantString_tag { i32* getelementptr inbounds ([0 x i32], [0 x i32]* @__CFConstantStringClassReference, i32 0, i32 0), i32 2000, i8* bitcast ([9 x i16]* @.str to i8*), i32 8 }, section "__DATA,__cfstring"
// CHECK: @P = global i8* bitcast (%struct.__NSConstantString_tag* @_unnamed_cfstring_ to i8*), align 4
void *P = @"good\0bye";
diff --git a/test/CodeGenObjC/arc-blocks.m b/test/CodeGenObjC/arc-blocks.m
index 30f9271bd9dc..f67136b7b226 100644
--- a/test/CodeGenObjC/arc-blocks.m
+++ b/test/CodeGenObjC/arc-blocks.m
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -O2 -disable-llvm-optzns -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -O2 -disable-llvm-passes -o - %s | FileCheck %s
// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=CHECK-UNOPT %s
// This shouldn't crash.
diff --git a/test/CodeGenObjC/arc-bridged-cast.m b/test/CodeGenObjC/arc-bridged-cast.m
index f48985303132..97a45c5a2f10 100644
--- a/test/CodeGenObjC/arc-bridged-cast.m
+++ b/test/CodeGenObjC/arc-bridged-cast.m
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -O2 -disable-llvm-optzns -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -O2 -disable-llvm-passes -o - %s | FileCheck %s
typedef const void *CFTypeRef;
typedef const struct __CFString *CFStringRef;
diff --git a/test/CodeGenObjC/arc-linetable-autorelease.m b/test/CodeGenObjC/arc-linetable-autorelease.m
index 6812e8a6de83..26a779b8d6db 100644
--- a/test/CodeGenObjC/arc-linetable-autorelease.m
+++ b/test/CodeGenObjC/arc-linetable-autorelease.m
@@ -30,10 +30,11 @@ NSRect NSMakeRect(CGFloat x, CGFloat y, CGFloat w, CGFloat h);
// CHECK: define {{.*}}_createBezierPathWithWidth
// CHECK: load {{.*}} %path, align {{.*}}, !dbg ![[RET:[0-9]+]]
// CHECK: call void @objc_storeStrong{{.*}} !dbg ![[ARC:[0-9]+]]
- // CHECK: call {{.*}} @objc_autoreleaseReturnValue{{.*}} !dbg ![[ARC]]
+ // CHECK: call {{.*}} @objc_autoreleaseReturnValue{{.*}} !dbg ![[ARC1:[0-9]+]]
// CHECK: ret {{.*}} !dbg ![[ARC]]
// CHECK: ![[RET]] = !DILocation(line: [[@LINE+1]], scope: !{{.*}})
return path;
- // CHECK: ![[ARC]] = !DILocation(line: [[@LINE+1]], scope: !{{.*}})
+ // CHECK: ![[ARC]] = !DILocation(line: [[@LINE+2]], scope: !{{.*}})
+ // CHECK: ![[ARC1]] = !DILocation(line: [[@LINE+1]], scope: !{{.*}})
}
@end
diff --git a/test/CodeGenObjC/arc-literals.m b/test/CodeGenObjC/arc-literals.m
index ab6c82b743fc..74e231c765bf 100644
--- a/test/CodeGenObjC/arc-literals.m
+++ b/test/CodeGenObjC/arc-literals.m
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -I %S/Inputs -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -O2 -disable-llvm-optzns -o - %s | FileCheck %s
+// RUN: %clang_cc1 -I %S/Inputs -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -O2 -disable-llvm-passes -o - %s | FileCheck %s
#include "literal-support.h"
diff --git a/test/CodeGenObjC/arc-no-arc-exceptions.m b/test/CodeGenObjC/arc-no-arc-exceptions.m
index f147b64c4841..3338ad8477bc 100644
--- a/test/CodeGenObjC/arc-no-arc-exceptions.m
+++ b/test/CodeGenObjC/arc-no-arc-exceptions.m
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-arc -fblocks -fexceptions -fobjc-exceptions -O2 -disable-llvm-optzns -o - %s | FileCheck %s
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-arc -fblocks -fexceptions -fobjc-exceptions -disable-llvm-optzns -o - %s | FileCheck -check-prefix=NO-METADATA %s
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-arc -fblocks -fexceptions -fobjc-exceptions -O2 -disable-llvm-optzns -o - %s -fobjc-arc-exceptions | FileCheck -check-prefix=NO-METADATA %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-arc -fblocks -fexceptions -fobjc-exceptions -O2 -disable-llvm-passes -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-arc -fblocks -fexceptions -fobjc-exceptions -disable-llvm-passes -o - %s | FileCheck -check-prefix=NO-METADATA %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-arc -fblocks -fexceptions -fobjc-exceptions -O2 -disable-llvm-passes -o - %s -fobjc-arc-exceptions | FileCheck -check-prefix=NO-METADATA %s
// The front-end should emit clang.arc.no_objc_arc_exceptions in -fobjc-arc-exceptions
// mode when optimization is enabled, and not otherwise.
diff --git a/test/CodeGenObjC/arc-precise-lifetime.m b/test/CodeGenObjC/arc-precise-lifetime.m
index 42a048307948..eb3111c68a5a 100644
--- a/test/CodeGenObjC/arc-precise-lifetime.m
+++ b/test/CodeGenObjC/arc-precise-lifetime.m
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -O2 -disable-llvm-optzns -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -O2 -disable-llvm-passes -o - %s | FileCheck %s
#define PRECISE_LIFETIME __attribute__((objc_precise_lifetime))
diff --git a/test/CodeGenObjC/arc-ternary-op.m b/test/CodeGenObjC/arc-ternary-op.m
index c6bbab28a2e8..883fcd366622 100644
--- a/test/CodeGenObjC/arc-ternary-op.m
+++ b/test/CodeGenObjC/arc-ternary-op.m
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -O2 -disable-llvm-optzns -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -O2 -disable-llvm-passes -o - %s | FileCheck %s
void test0(_Bool cond) {
id test0_helper(void) __attribute__((ns_returns_retained));
diff --git a/test/CodeGenObjC/arc-unsafeclaim.m b/test/CodeGenObjC/arc-unsafeclaim.m
index cda00b0a2f5e..01329df0f791 100644
--- a/test/CodeGenObjC/arc-unsafeclaim.m
+++ b/test/CodeGenObjC/arc-unsafeclaim.m
@@ -1,13 +1,16 @@
// Make sure it works on x86-64.
// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -fobjc-runtime=macosx-10.11 -fobjc-arc -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-UNOPTIMIZED
+// Make sure it works on x86-32.
+// RUN: %clang_cc1 -triple i386-apple-darwin11 -fobjc-runtime=macosx-fragile-10.11 -fobjc-arc -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-UNOPTIMIZED -check-prefix=CHECK-MARKED
+
// Make sure it works on ARM.
// RUN: %clang_cc1 -triple arm64-apple-ios9 -fobjc-runtime=ios-9.0 -fobjc-arc -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-UNOPTIMIZED -check-prefix=CHECK-MARKED
-// RUN: %clang_cc1 -triple arm64-apple-ios9 -fobjc-runtime=ios-9.0 -fobjc-arc -O -disable-llvm-optzns -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-OPTIMIZED
+// RUN: %clang_cc1 -triple arm64-apple-ios9 -fobjc-runtime=ios-9.0 -fobjc-arc -O -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-OPTIMIZED
// Make sure it works on ARM64.
// RUN: %clang_cc1 -triple armv7-apple-ios9 -fobjc-runtime=ios-9.0 -fobjc-arc -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-UNOPTIMIZED -check-prefix=CHECK-MARKED
-// RUN: %clang_cc1 -triple armv7-apple-ios9 -fobjc-runtime=ios-9.0 -fobjc-arc -O -disable-llvm-optzns -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-OPTIMIZED
+// RUN: %clang_cc1 -triple armv7-apple-ios9 -fobjc-runtime=ios-9.0 -fobjc-arc -O -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-OPTIMIZED
// Make sure that it's implicitly disabled if the runtime version isn't high enough.
// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-runtime=macosx-10.10 -fobjc-arc -emit-llvm -o - %s | FileCheck %s -check-prefix=DISABLED
diff --git a/test/CodeGenObjC/arc.m b/test/CodeGenObjC/arc.m
index f756df1460f3..87cf667b4e5e 100644
--- a/test/CodeGenObjC/arc.m
+++ b/test/CodeGenObjC/arc.m
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -O2 -disable-llvm-optzns -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -O2 -disable-llvm-passes -o - %s | FileCheck %s
// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=CHECK-GLOBALS %s
// rdar://13129783. Check both native/non-native arc platforms. Here we check
diff --git a/test/CodeGenObjC/block-byref-debuginfo.m b/test/CodeGenObjC/block-byref-debuginfo.m
index f11566634294..3ddb376dde65 100644
--- a/test/CodeGenObjC/block-byref-debuginfo.m
+++ b/test/CodeGenObjC/block-byref-debuginfo.m
@@ -5,7 +5,6 @@
// expression (256) that locates it inside of the byref descriptor:
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "foo",
// CHECK-NOT: line:
-// CHECK-SAME: align: 64
// CHECK-SAME: offset: 256
struct Foo {
diff --git a/test/CodeGenObjC/boxing.m b/test/CodeGenObjC/boxing.m
index f205764a0f21..42dd33337f1e 100644
--- a/test/CodeGenObjC/boxing.m
+++ b/test/CodeGenObjC/boxing.m
@@ -53,17 +53,17 @@ typedef signed char BOOL;
+ (id)stringWithUTF8String:(const char *)nullTerminatedCString;
@end
-// CHECK: [[WithIntMeth:@.*]] = private global [15 x i8] c"numberWithInt:\00"
+// CHECK: [[WithIntMeth:@.*]] = private unnamed_addr constant [15 x i8] c"numberWithInt:\00"
// CHECK: [[WithIntSEL:@.*]] = private externally_initialized global i8* getelementptr inbounds ([15 x i8], [15 x i8]* [[WithIntMeth]]
-// CHECK: [[WithCharMeth:@.*]] = private global [16 x i8] c"numberWithChar:\00"
+// CHECK: [[WithCharMeth:@.*]] = private unnamed_addr constant [16 x i8] c"numberWithChar:\00"
// CHECK: [[WithCharSEL:@.*]] = private externally_initialized global i8* getelementptr inbounds ([16 x i8], [16 x i8]* [[WithCharMeth]]
-// CHECK: [[WithBoolMeth:@.*]] = private global [16 x i8] c"numberWithBool:\00"
+// CHECK: [[WithBoolMeth:@.*]] = private unnamed_addr constant [16 x i8] c"numberWithBool:\00"
// CHECK: [[WithBoolSEL:@.*]] = private externally_initialized global i8* getelementptr inbounds ([16 x i8], [16 x i8]* [[WithBoolMeth]]
-// CHECK: [[WithIntegerMeth:@.*]] = private global [19 x i8] c"numberWithInteger:\00"
+// CHECK: [[WithIntegerMeth:@.*]] = private unnamed_addr constant [19 x i8] c"numberWithInteger:\00"
// CHECK: [[WithIntegerSEL:@.*]] = private externally_initialized global i8* getelementptr inbounds ([19 x i8], [19 x i8]* [[WithIntegerMeth]]
-// CHECK: [[WithUnsignedIntegerMeth:@.*]] = private global [27 x i8] c"numberWithUnsignedInteger:\00"
+// CHECK: [[WithUnsignedIntegerMeth:@.*]] = private unnamed_addr constant [27 x i8] c"numberWithUnsignedInteger:\00"
// CHECK: [[WithUnsignedIntegerSEL:@.*]] = private externally_initialized global i8* getelementptr inbounds ([27 x i8], [27 x i8]* [[WithUnsignedIntegerMeth]]
-// CHECK: [[stringWithUTF8StringMeth:@.*]] = private global [22 x i8] c"stringWithUTF8String:\00"
+// CHECK: [[stringWithUTF8StringMeth:@.*]] = private unnamed_addr constant [22 x i8] c"stringWithUTF8String:\00"
// CHECK: [[stringWithUTF8StringSEL:@.*]] = private externally_initialized global i8* getelementptr inbounds ([22 x i8], [22 x i8]* [[stringWithUTF8StringMeth]]
int main() {
diff --git a/test/CodeGenObjC/complex-property.m b/test/CodeGenObjC/complex-property.m
index bed0ca661155..a5572958a643 100644
--- a/test/CodeGenObjC/complex-property.m
+++ b/test/CodeGenObjC/complex-property.m
@@ -13,8 +13,8 @@ void f0(A *a) {
a.y += a1;
}
-// CHECK-LP64: private global [13 x i8] c"COMPLEX_PROP
-// CHECK-LP64: private global [17 x i8] c"setCOMPLEX_PROP
+// CHECK-LP64: private unnamed_addr constant [13 x i8] c"COMPLEX_PROP
+// CHECK-LP64: private unnamed_addr constant [17 x i8] c"setCOMPLEX_PROP
// rdar: // 7351147
@interface B
diff --git a/test/CodeGenObjC/debug-info-block-type.m b/test/CodeGenObjC/debug-info-block-type.m
index 565bc86e8b8a..4bdd18035ee0 100644
--- a/test/CodeGenObjC/debug-info-block-type.m
+++ b/test/CodeGenObjC/debug-info-block-type.m
@@ -17,6 +17,6 @@ int main()
SomeKindOfPredicate p = ^BOOL(id obj) { return obj != nil; };
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "__FuncPtr",
// CHECK-SAME: line: [[@LINE-2]]
- // CHECK-SAME: size: 64, align: 64, offset: 128,
+ // CHECK-SAME: size: 64, offset: 128,
return p(nil);
}
diff --git a/test/CodeGenObjC/debug-info-ivars-extension.m b/test/CodeGenObjC/debug-info-ivars-extension.m
index 0709d2ad24d3..2091b56b9a35 100644
--- a/test/CodeGenObjC/debug-info-ivars-extension.m
+++ b/test/CodeGenObjC/debug-info-ivars-extension.m
@@ -30,7 +30,7 @@ void gorf (I* pg) {
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "a"
// CHECK-SAME: line: 7
// CHECK-SAME: baseType: ![[INT:[0-9]+]]
-// CHECK-SAME: size: 32, align: 32
+// CHECK-SAME: size: 32
// CHECK-NOT: offset:
// CHECK-SAME: flags: DIFlagPublic
// CHECK: ![[INT]] = !DIBasicType(name: "int"
@@ -42,6 +42,6 @@ void gorf (I* pg) {
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "b"
// CHECK-SAME: line: 18
// CHECK-SAME: baseType: ![[INT]]
-// CHECK-SAME: size: 32, align: 32
+// CHECK-SAME: size: 32
// CHECK-NOT: offset:
// CHECK-SAME: flags: DIFlagPublic
diff --git a/test/CodeGenObjC/debug-info-ivars-private.m b/test/CodeGenObjC/debug-info-ivars-private.m
index f533ef3adc20..583868e1b1c0 100644
--- a/test/CodeGenObjC/debug-info-ivars-private.m
+++ b/test/CodeGenObjC/debug-info-ivars-private.m
@@ -35,13 +35,13 @@ __attribute((objc_root_class)) @interface NSObject {
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "foo"
// CHECK-SAME: line: 14
// CHECK-SAME: baseType: ![[INT:[0-9]+]]
-// CHECK-SAME: size: 32, align: 32,
+// CHECK-SAME: size: 32,
// CHECK-NOT: offset:
// CHECK-SAME: flags: DIFlagProtected
// CHECK: ![[INT]] = !DIBasicType(name: "int"
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "bar"
// CHECK-SAME: line: 27
// CHECK-SAME: baseType: ![[INT:[0-9]+]]
-// CHECK-SAME: size: 32, align: 32,
+// CHECK-SAME: size: 32,
// CHECK-NOT: offset:
// CHECK-SAME: flags: DIFlagPrivate
diff --git a/test/CodeGenObjC/debug-info-ivars.m b/test/CodeGenObjC/debug-info-ivars.m
index c6e544ae1c1c..996562dae25f 100644
--- a/test/CodeGenObjC/debug-info-ivars.m
+++ b/test/CodeGenObjC/debug-info-ivars.m
@@ -21,24 +21,24 @@ __attribute((objc_root_class)) @interface NSObject {
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "i"
// CHECK-SAME: line: 10
// CHECK-SAME: baseType: ![[INT:[0-9]+]]
-// CHECK-SAME: size: 32, align: 32,
+// CHECK-SAME: size: 32,
// CHECK-NOT: offset:
// CHECK-SAME: flags: DIFlagProtected
// CHECK: ![[INT]] = !DIBasicType(name: "int"
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "flag_1"
// CHECK-SAME: line: 11
// CHECK-SAME: baseType: ![[UNSIGNED:[0-9]+]]
-// CHECK-SAME: size: 9, align: 32,
+// CHECK-SAME: size: 9,
// CHECK-NOT: offset:
// CHECK-SAME: flags: DIFlagProtected
// CHECK: ![[UNSIGNED]] = !DIBasicType(name: "unsigned int"
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "flag_2"
// CHECK-SAME: line: 12
// CHECK-SAME: baseType: ![[UNSIGNED]]
-// CHECK-SAME: size: 9, align: 32, offset: 1,
+// CHECK-SAME: size: 9, offset: 1,
// CHECK-SAME: flags: DIFlagProtected
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "flag_3"
// CHECK-SAME: line: 14
// CHECK-SAME: baseType: ![[UNSIGNED]]
-// CHECK-SAME: size: 9, align: 32, offset: 3,
+// CHECK-SAME: size: 9, offset: 3,
// CHECK-SAME: flags: DIFlagProtected
diff --git a/test/CodeGenObjC/encode-cstyle-method.m b/test/CodeGenObjC/encode-cstyle-method.m
index d0a99215b9a5..cb1e6773fd56 100644
--- a/test/CodeGenObjC/encode-cstyle-method.m
+++ b/test/CodeGenObjC/encode-cstyle-method.m
@@ -8,4 +8,4 @@
@implementation Foo
- (id)test:(id )one, id two {return two; } @end
-// CHECK-LP64: private global [11 x i8] c"@24@0:8@16
+// CHECK-LP64: private unnamed_addr constant [11 x i8] c"@24@0:8@16
diff --git a/test/CodeGenObjC/encode-test-6.m b/test/CodeGenObjC/encode-test-6.m
index 02895e74d266..bbd29cbdc943 100644
--- a/test/CodeGenObjC/encode-test-6.m
+++ b/test/CodeGenObjC/encode-test-6.m
@@ -14,8 +14,8 @@ typedef struct {} Z;
-(void)foo:(Z)a: (char*)b : (Z)c : (double) d {}
@end
-// CHECK: private global [14 x i8] c"v16@0:8{?=}16
-// CHECK: private global [26 x i8] c"v32@0:8{?=}16*16{?=}24d24
+// CHECK: private unnamed_addr constant [14 x i8] c"v16@0:8{?=}16
+// CHECK: private unnamed_addr constant [26 x i8] c"v32@0:8{?=}16*16{?=}24d24
// rdar://13190095
@@ -34,7 +34,7 @@ typedef BABugExample BABugExampleRedefinition;
@synthesize property = _property;
@end
-// CHECK: private global [24 x i8] c"^{BABugExample=@}16
+// CHECK: private unnamed_addr constant [24 x i8] c"^{BABugExample=@}16
// rdar://14408244
@class SCNCamera;
@@ -52,7 +52,7 @@ typedef struct
C3DCameraStorage _storage;
}
@end
-// CHECK: private global [39 x i8] c"{?=\22presentationInstance\22^{SCNCamera}}\00"
+// CHECK: private unnamed_addr constant [39 x i8] c"{?=\22presentationInstance\22^{SCNCamera}}\00"
// rdar://16655340
int i;
diff --git a/test/CodeGenObjC/encode-test.m b/test/CodeGenObjC/encode-test.m
index 710e65be62da..7f0e76fc3ffd 100644
--- a/test/CodeGenObjC/encode-test.m
+++ b/test/CodeGenObjC/encode-test.m
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -triple i686-apple-darwin9 -fobjc-runtime=macosx-fragile-10.5 -emit-llvm -o %t %s
// RUN: FileCheck < %t %s
//
-// CHECK: @OBJC_METH_VAR_TYPE_.34 = private global [16 x i8] c"v12@0:4[3[4@]]8\00"
+// CHECK: @OBJC_METH_VAR_TYPE_{{.*}} = private unnamed_addr constant [16 x i8] c"v12@0:4[3[4@]]8\00"
@class Int1;
diff --git a/test/CodeGenObjC/exceptions.m b/test/CodeGenObjC/exceptions.m
index 56c9a0e907be..28515c54f32f 100644
--- a/test/CodeGenObjC/exceptions.m
+++ b/test/CodeGenObjC/exceptions.m
@@ -83,7 +83,7 @@ void f3() {
// CHECK: [[X:%.*]] = alloca i32
// CHECK: [[XPTR:%.*]] = bitcast i32* [[X]] to i8*
- // CHECK: call void @llvm.lifetime.start(i64 4, i8* [[XPTR]])
+ // CHECK: call void @llvm.lifetime.start(i64 4, i8* nonnull [[XPTR]])
// CHECK: store i32 0, i32* [[X]]
int x = 0;
diff --git a/test/CodeGenObjC/fragile-arc.m b/test/CodeGenObjC/fragile-arc.m
index ecb955bd34ac..2bf813d4615b 100644
--- a/test/CodeGenObjC/fragile-arc.m
+++ b/test/CodeGenObjC/fragile-arc.m
@@ -16,9 +16,9 @@
// GLOBALS-LABEL @OBJC_METACLASS_A
// Strong layout: scan the first word.
-// GLOBALS: @OBJC_CLASS_NAME_{{.*}} = private global [2 x i8] c"\01\00"
+// GLOBALS: @OBJC_CLASS_NAME_{{.*}} = private unnamed_addr constant [2 x i8] c"\01\00"
// Weak layout: skip the first word, scan the second word.
-// GLOBALS: @OBJC_CLASS_NAME_{{.*}} = private global [2 x i8] c"\11\00"
+// GLOBALS: @OBJC_CLASS_NAME_{{.*}} = private unnamed_addr constant [2 x i8] c"\11\00"
// 0x04002001
// ^ is compiled by ARC (controls interpretation of layouts)
@@ -119,9 +119,9 @@
// GLOBALS-LABEL: @OBJC_METACLASS_C
// Strong layout: skip five, scan four, skip three, scan seven
// 'T' == 0x54, '7' == 0x37
-// GLOBALS: @OBJC_CLASS_NAME_{{.*}} = private global [3 x i8] c"T7\00"
+// GLOBALS: @OBJC_CLASS_NAME_{{.*}} = private unnamed_addr constant [3 x i8] c"T7\00"
// Weak layout: skip nine, scan three
-// GLOBALS: @OBJC_CLASS_NAME_{{.*}} = private global [2 x i8] c"\93\00"
+// GLOBALS: @OBJC_CLASS_NAME_{{.*}} = private unnamed_addr constant [2 x i8] c"\93\00"
extern void useBlock(void (^block)(void));
diff --git a/test/CodeGenObjC/gnu-exceptions.m b/test/CodeGenObjC/gnu-exceptions.m
index 76e9e1ded3c4..2407f8fc6c50 100644
--- a/test/CodeGenObjC/gnu-exceptions.m
+++ b/test/CodeGenObjC/gnu-exceptions.m
@@ -32,4 +32,4 @@ void test0() {
log(1);
}
-// CHECK: attributes [[TF]] = { "{{.*}} }
+// CHECK: attributes [[TF]] = { noinline "{{.*}} }
diff --git a/test/CodeGenObjC/ivar-layout-64.m b/test/CodeGenObjC/ivar-layout-64.m
index 0866704ecf92..d3ffdfe444c8 100644
--- a/test/CodeGenObjC/ivar-layout-64.m
+++ b/test/CodeGenObjC/ivar-layout-64.m
@@ -33,9 +33,9 @@ __weak B *f2;
@property int p3;
@end
-// CHECK: @OBJC_CLASS_NAME_{{.*}} = private global {{.*}} c"C\00"
-// CHECK: @OBJC_CLASS_NAME_{{.*}} = private global {{.*}} c"\11p\00"
-// CHECK: @OBJC_CLASS_NAME_{{.*}} = private global {{.*}} c"!`\00"
+// CHECK: @OBJC_CLASS_NAME_{{.*}} = private unnamed_addr constant {{.*}} c"C\00"
+// CHECK: @OBJC_CLASS_NAME_{{.*}} = private unnamed_addr constant {{.*}} c"\11p\00"
+// CHECK: @OBJC_CLASS_NAME_{{.*}} = private unnamed_addr constant {{.*}} c"!`\00"
@implementation C
@@ -48,9 +48,9 @@ __weak B *f2;
@property (assign) __weak id p2;
@end
-// CHECK: @OBJC_CLASS_NAME_{{.*}} = private global {{.*}} c"A\00"
-// CHECK: @OBJC_CLASS_NAME_{{.*}} = private global {{.*}} c"\11q\10\00"
-// CHECK: @OBJC_CLASS_NAME_{{.*}} = private global {{.*}} c"!q\00"
+// CHECK: @OBJC_CLASS_NAME_{{.*}} = private unnamed_addr constant {{.*}} c"A\00"
+// CHECK: @OBJC_CLASS_NAME_{{.*}} = private unnamed_addr constant {{.*}} c"\11q\10\00"
+// CHECK: @OBJC_CLASS_NAME_{{.*}} = private unnamed_addr constant {{.*}} c"!q\00"
@implementation A
@synthesize p0 = _p0;
@@ -62,9 +62,9 @@ __weak B *f2;
@property int p3;
@end
-// CHECK: @OBJC_CLASS_NAME_{{.*}} = private global {{.*}} c"D\00"
-// CHECK: @OBJC_CLASS_NAME_{{.*}} = private global {{.*}} c"\11p\00"
-// CHECK: @OBJC_CLASS_NAME_{{.*}} = private global {{.*}} c"!`\00"
+// CHECK: @OBJC_CLASS_NAME_{{.*}} = private unnamed_addr constant {{.*}} c"D\00"
+// CHECK: @OBJC_CLASS_NAME_{{.*}} = private unnamed_addr constant {{.*}} c"\11p\00"
+// CHECK: @OBJC_CLASS_NAME_{{.*}} = private unnamed_addr constant {{.*}} c"!`\00"
@implementation D
@synthesize p3 = _p3;
@@ -89,8 +89,8 @@ typedef unsigned int FSCatalogInfoBitmap;
}
@end
-// CHECK: @OBJC_CLASS_NAME_{{.*}} = private global {{.*}} c"NSFileLocationComponent\00"
-// CHECK: @OBJC_CLASS_NAME_{{.*}} = private global {{.*}} c"\01\14\00"
+// CHECK: @OBJC_CLASS_NAME_{{.*}} = private unnamed_addr constant {{.*}} c"NSFileLocationComponent\00"
+// CHECK: @OBJC_CLASS_NAME_{{.*}} = private unnamed_addr constant {{.*}} c"\01\14\00"
@implementation NSFileLocationComponent @end
@@ -108,8 +108,8 @@ typedef unsigned int FSCatalogInfoBitmap;
}
@end
-// CHECK: @OBJC_CLASS_NAME_{{.*}} = private global {{.*}} c"Foo\00"
-// CHECK: @OBJC_CLASS_NAME_{{.*}} = private global {{.*}} c"\02\10\00"
+// CHECK: @OBJC_CLASS_NAME_{{.*}} = private unnamed_addr constant {{.*}} c"Foo\00"
+// CHECK: @OBJC_CLASS_NAME_{{.*}} = private unnamed_addr constant {{.*}} c"\02\10\00"
@implementation Foo @end
@@ -124,8 +124,8 @@ struct __attribute__((packed)) PackedStruct {
}
@end
@implementation Packed @end
-// CHECK: @OBJC_CLASS_NAME_{{.*}} = private global {{.*}} c"Packed\00"
-// CHECK: @OBJC_CLASS_NAME_{{.*}} = private global {{.*}} c"\01 \00"
+// CHECK: @OBJC_CLASS_NAME_{{.*}} = private unnamed_addr constant {{.*}} c"Packed\00"
+// CHECK: @OBJC_CLASS_NAME_{{.*}} = private unnamed_addr constant {{.*}} c"\01 \00"
// ' ' == 0x20
// Ensure that layout descends into anonymous unions and structs.
@@ -142,8 +142,8 @@ struct __attribute__((packed)) PackedStruct {
}
@end
@implementation AnonymousUnion @end
-// CHECK: @OBJC_CLASS_NAME_{{.*}} = private global {{.*}} c"AnonymousUnion\00"
-// CHECK: @OBJC_CLASS_NAME_{{.*}} = private global {{.*}} c"\02\00"
+// CHECK: @OBJC_CLASS_NAME_{{.*}} = private unnamed_addr constant {{.*}} c"AnonymousUnion\00"
+// CHECK: @OBJC_CLASS_NAME_{{.*}} = private unnamed_addr constant {{.*}} c"\02\00"
@interface AnonymousStruct : NSObject {
struct {
@@ -155,7 +155,7 @@ struct __attribute__((packed)) PackedStruct {
}
@end
@implementation AnonymousStruct @end
-// CHECK: @OBJC_CLASS_NAME_{{.*}} = private global {{.*}} c"AnonymousStruct\00"
-// CHECK: @OBJC_CLASS_NAME_{{.*}} = private global {{.*}} c"\02\10\00"
-// CHECK: @OBJC_CLASS_NAME_{{.*}} = private global {{.*}} c"!\00"
+// CHECK: @OBJC_CLASS_NAME_{{.*}} = private unnamed_addr constant {{.*}} c"AnonymousStruct\00"
+// CHECK: @OBJC_CLASS_NAME_{{.*}} = private unnamed_addr constant {{.*}} c"\02\10\00"
+// CHECK: @OBJC_CLASS_NAME_{{.*}} = private unnamed_addr constant {{.*}} c"!\00"
// '!' == 0x21
diff --git a/test/CodeGenObjC/mangle-blocks.m b/test/CodeGenObjC/mangle-blocks.m
index 3d6e56a1501d..4cc320403322 100644
--- a/test/CodeGenObjC/mangle-blocks.m
+++ b/test/CodeGenObjC/mangle-blocks.m
@@ -17,13 +17,12 @@ void __assert_rtn(const char *, const char *, int, const char *);
}
@end
-// CHECK: @"__func__.__14-[Test mangle]_block_invoke_2" = private unnamed_addr constant [34 x i8] c"__14-[Test mangle]_block_invoke_2\00", align 1
+// CHECK: @"__func__.__14-[Test mangle]_block_invoke_2" = private unnamed_addr constant [30 x i8] c"-[Test mangle]_block_invoke_2\00", align 1
// CHECK: @.str = private unnamed_addr constant {{.*}}, align 1
// CHECK: @.str.1 = private unnamed_addr constant [7 x i8] c"mangle\00", align 1
// CHECK: define internal void @"__14-[Test mangle]_block_invoke"(i8* %.block_descriptor)
// CHECK: define internal void @"__14-[Test mangle]_block_invoke_2"(i8* %.block_descriptor){{.*}}{
-// CHECK: call void @__assert_rtn(i8* getelementptr inbounds ([34 x i8], [34 x i8]* @"__func__.__14-[Test mangle]_block_invoke_2", i32 0, i32 0), i8* getelementptr inbounds {{.*}}, i32 14, i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.1, i32 0, i32 0))
+// CHECK: call void @__assert_rtn(i8* getelementptr inbounds ([30 x i8], [30 x i8]* @"__func__.__14-[Test mangle]_block_invoke_2", i32 0, i32 0), i8* getelementptr inbounds {{.*}}, i32 14, i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.1, i32 0, i32 0))
// CHECK: }
-
diff --git a/test/CodeGenObjC/metadata-symbols-32.m b/test/CodeGenObjC/metadata-symbols-32.m
index c75f6411e874..ac5a6384a466 100644
--- a/test/CodeGenObjC/metadata-symbols-32.m
+++ b/test/CodeGenObjC/metadata-symbols-32.m
@@ -2,11 +2,10 @@
// CHECK: .lazy_reference .objc_class_name_J0
-// CHECK: @OBJC_METH_VAR_NAME_{{[0-9]*}} = private global {{.*}}section "__TEXT,__cstring,cstring_literals", align 1
-// CHECK: @OBJC_METH_VAR_TYPE_{{[0-9]*}} = private global {{.*}}section "__TEXT,__cstring,cstring_literals", align 1
-// CHECK: @"\01l_OBJC_PROTOCOLEXT_P" = private global
-// CHECK-NOT: section
-// CHECK: @OBJC_CLASS_NAME_{{[0-9]*}} = private global {{.*}}section "__TEXT,__cstring,cstring_literals", align 1
+// CHECK: @OBJC_METH_VAR_TYPE_{{.*}} = private unnamed_addr constant {{.*}}section "__TEXT,__cstring,cstring_literals", align 1
+// CHECK: @"\01l_OBJC_PROTOCOLEXT_P" = private global {{.*}}}, align
+// CHECK: @OBJC_CLASS_NAME_{{[0-9]*}} = private unnamed_addr constant {{.*}}section "__TEXT,__cstring,cstring_literals", align 1
+// CHECK: @OBJC_METH_VAR_NAME_{{.*}} = private unnamed_addr constant {{.*}}section "__TEXT,__cstring,cstring_literals", align 1
// CHECK: @OBJC_PROTOCOL_INSTANCE_METHODS_P = private global {{.*}}section "__OBJC,__cat_inst_meth,regular,no_dead_strip", align 4
// CHECK: @OBJC_PROTOCOL_CLASS_METHODS_P = private global {{.*}}section "__OBJC,__cat_cls_meth,regular,no_dead_strip", align 4
// CHECK: @OBJC_PROTOCOL_P = private global {{.*}}section "__OBJC,__protocol,regular,no_dead_strip", align 4
@@ -15,7 +14,7 @@
// CHECK: @OBJC_METACLASS_A = private global {{.*}}section "__OBJC,__meta_class,regular,no_dead_strip", align 4
// CHECK: @OBJC_INSTANCE_VARIABLES_A = private global {{.*}}section "__OBJC,__instance_vars,regular,no_dead_strip", align 4
// CHECK: @OBJC_INSTANCE_METHODS_A = private global {{.*}}section "__OBJC,__inst_meth,regular,no_dead_strip", align 4
-// CHECK: @OBJC_PROP_NAME_ATTR_{{[0-9]*}} = private global {{.*}}section "__TEXT,__cstring,cstring_literals", align 1
+// CHECK: @OBJC_PROP_NAME_ATTR_{{[0-9]*}} = private unnamed_addr constant {{.*}}section "__TEXT,__cstring,cstring_literals", align 1
// CHECK: @"\01l_OBJC_$_PROP_LIST_A" = private global {{.*}}section "__OBJC,__property,regular,no_dead_strip", align 4
// CHECK: @OBJC_CLASSEXT_A = private global {{.*}}section "__OBJC,__class_ext,regular,no_dead_strip", align 4
// CHECK: @OBJC_CLASS_A = private global {{.*}}section "__OBJC,__class,regular,no_dead_strip", align 4
diff --git a/test/CodeGenObjC/metadata-symbols-64.m b/test/CodeGenObjC/metadata-symbols-64.m
index 9b7423746388..5139cd8fdedf 100644
--- a/test/CodeGenObjC/metadata-symbols-64.m
+++ b/test/CodeGenObjC/metadata-symbols-64.m
@@ -5,9 +5,9 @@
// CHECK: @_objc_empty_vtable = external global
// CHECK: @"OBJC_CLASS_$_A" = global
// CHECK: @"OBJC_METACLASS_$_A" = global {{.*}} section "__DATA, __objc_data", align 8
-// CHECK: @OBJC_CLASS_NAME_{{[0-9]*}} = private global {{.*}} section "__TEXT,__objc_classname,cstring_literals", align 1
-// CHECK: @OBJC_METH_VAR_NAME_{{[0-9]*}} = private global {{.*}} section "__TEXT,__objc_methname,cstring_literals", align 1
-// CHECK: @OBJC_METH_VAR_TYPE_{{[0-9]*}} = private global {{.*}} section "__TEXT,__objc_methtype,cstring_literals", align 1
+// CHECK: @OBJC_CLASS_NAME_{{[0-9]*}} = private unnamed_addr constant {{.*}} section "__TEXT,__objc_classname,cstring_literals", align 1
+// CHECK: @OBJC_METH_VAR_NAME_{{[0-9]*}} = private unnamed_addr constant {{.*}} section "__TEXT,__objc_methname,cstring_literals", align 1
+// CHECK: @OBJC_METH_VAR_TYPE_{{[0-9]*}} = private unnamed_addr constant {{.*}} section "__TEXT,__objc_methtype,cstring_literals", align 1
// CHECK: @"\01l_OBJC_$_CLASS_METHODS_A" = private global {{.*}} section "__DATA, __objc_const", align 8
// CHECK: @"\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_P" = private global {{.*}} section "__DATA, __objc_const", align 8
// CHECK: @"\01l_OBJC_$_PROTOCOL_CLASS_METHODS_P" = private global {{.*}} section "__DATA, __objc_const", align 8
@@ -17,7 +17,7 @@
// CHECK: @"\01l_OBJC_METACLASS_RO_$_A" = private global {{.*}} section "__DATA, __objc_const", align 8
// CHECK: @"\01l_OBJC_$_INSTANCE_METHODS_A" = private global {{.*}} section "__DATA, __objc_const", align 8
// CHECK: @"\01l_OBJC_$_INSTANCE_VARIABLES_A" = private global {{.*}} section "__DATA, __objc_const", align 8
-// CHECK: @OBJC_PROP_NAME_ATTR_{{[0-9]*}} = private global {{.*}} section "__TEXT,__cstring,cstring_literals", align 1
+// CHECK: @OBJC_PROP_NAME_ATTR_{{[0-9]*}} = private unnamed_addr constant {{.*}} section "__TEXT,__cstring,cstring_literals", align 1
// CHECK: @"\01l_OBJC_$_PROP_LIST_A" = private global {{.*}} section "__DATA, __objc_const", align 8
// CHECK: @"\01l_OBJC_CLASS_RO_$_A" = private global {{.*}} section "__DATA, __objc_const", align 8
// CHECK: @"\01l_OBJC_$_CATEGORY_INSTANCE_METHODS_A_$_Cat" = private global {{.*}} section "__DATA, __objc_const", align 8
diff --git a/test/CodeGenObjC/nsvalue-objc-boxable-ios-arc.m b/test/CodeGenObjC/nsvalue-objc-boxable-ios-arc.m
index 75e04dbd0272..bab6e27bb345 100644
--- a/test/CodeGenObjC/nsvalue-objc-boxable-ios-arc.m
+++ b/test/CodeGenObjC/nsvalue-objc-boxable-ios-arc.m
@@ -1,11 +1,11 @@
-// RUN: %clang_cc1 -I %S/Inputs -triple armv7-apple-ios8.0.0 -emit-llvm -fobjc-arc -O2 -disable-llvm-optzns -o - %s | FileCheck %s
+// RUN: %clang_cc1 -I %S/Inputs -triple armv7-apple-ios8.0.0 -emit-llvm -fobjc-arc -O2 -disable-llvm-passes -o - %s | FileCheck %s
#import "nsvalue-boxed-expressions-support.h"
// CHECK: [[CLASS:@.*]] = external global %struct._class_t
// CHECK: [[NSVALUE:@.*]] = {{.*}}[[CLASS]]{{.*}}
// CHECK: [[RANGE_STR:.*]] = {{.*}}_NSRange=II{{.*}}
-// CHECK: [[METH:@.*]] = private global{{.*}}valueWithBytes:objCType:{{.*}}
+// CHECK: [[METH:@.*]] = private unnamed_addr constant {{.*}}valueWithBytes:objCType:{{.*}}
// CHECK: [[VALUE_SEL:@.*]] = {{.*}}[[METH]]{{.*}}
// CHECK: [[POINT_STR:.*]] = {{.*}}CGPoint=dd{{.*}}
// CHECK: [[SIZE_STR:.*]] = {{.*}}CGSize=dd{{.*}}
diff --git a/test/CodeGenObjC/nsvalue-objc-boxable-ios.m b/test/CodeGenObjC/nsvalue-objc-boxable-ios.m
index 3443babdc9d0..dbbe0f40813d 100644
--- a/test/CodeGenObjC/nsvalue-objc-boxable-ios.m
+++ b/test/CodeGenObjC/nsvalue-objc-boxable-ios.m
@@ -1,11 +1,11 @@
-// RUN: %clang_cc1 -I %S/Inputs -triple armv7-apple-ios8.0.0 -emit-llvm -O2 -disable-llvm-optzns -o - %s | FileCheck %s
+// RUN: %clang_cc1 -I %S/Inputs -triple armv7-apple-ios8.0.0 -emit-llvm -O2 -disable-llvm-passes -o - %s | FileCheck %s
#import "nsvalue-boxed-expressions-support.h"
// CHECK: [[CLASS:@.*]] = external global %struct._class_t
// CHECK: [[NSVALUE:@.*]] = {{.*}}[[CLASS]]{{.*}}
// CHECK: [[RANGE_STR:.*]] = {{.*}}_NSRange=II{{.*}}
-// CHECK: [[METH:@.*]] = private global{{.*}}valueWithBytes:objCType:{{.*}}
+// CHECK: [[METH:@.*]] = private unnamed_addr constant {{.*}}valueWithBytes:objCType:{{.*}}
// CHECK: [[VALUE_SEL:@.*]] = {{.*}}[[METH]]{{.*}}
// CHECK: [[POINT_STR:.*]] = {{.*}}CGPoint=dd{{.*}}
// CHECK: [[SIZE_STR:.*]] = {{.*}}CGSize=dd{{.*}}
diff --git a/test/CodeGenObjC/nsvalue-objc-boxable-mac-arc.m b/test/CodeGenObjC/nsvalue-objc-boxable-mac-arc.m
index 92c91d7d3810..a2b4dfd6d9d2 100644
--- a/test/CodeGenObjC/nsvalue-objc-boxable-mac-arc.m
+++ b/test/CodeGenObjC/nsvalue-objc-boxable-mac-arc.m
@@ -1,11 +1,11 @@
-// RUN: %clang_cc1 -I %S/Inputs -triple x86_64-apple-macosx -emit-llvm -fobjc-arc -O2 -disable-llvm-optzns -o - %s | FileCheck %s
+// RUN: %clang_cc1 -I %S/Inputs -triple x86_64-apple-macosx -emit-llvm -fobjc-arc -O2 -disable-llvm-passes -o - %s | FileCheck %s
#import "nsvalue-boxed-expressions-support.h"
// CHECK: [[CLASS:@.*]] = external global %struct._class_t
// CHECK: [[NSVALUE:@.*]] = {{.*}}[[CLASS]]{{.*}}
// CHECK: [[RANGE_STR:.*]] = {{.*}}_NSRange=QQ{{.*}}
-// CHECK: [[METH:@.*]] = private global{{.*}}valueWithBytes:objCType:{{.*}}
+// CHECK: [[METH:@.*]] = private unnamed_addr constant {{.*}}valueWithBytes:objCType:{{.*}}
// CHECK: [[VALUE_SEL:@.*]] = {{.*}}[[METH]]{{.*}}
// CHECK: [[POINT_STR:.*]] = {{.*}}_NSPoint=dd{{.*}}
// CHECK: [[SIZE_STR:.*]] = {{.*}}_NSSize=dd{{.*}}
diff --git a/test/CodeGenObjC/nsvalue-objc-boxable-mac.m b/test/CodeGenObjC/nsvalue-objc-boxable-mac.m
index da0ae7a57108..6305b6b583fb 100644
--- a/test/CodeGenObjC/nsvalue-objc-boxable-mac.m
+++ b/test/CodeGenObjC/nsvalue-objc-boxable-mac.m
@@ -1,11 +1,11 @@
-// RUN: %clang_cc1 -I %S/Inputs -triple x86_64-apple-macosx -emit-llvm -O2 -disable-llvm-optzns -o - %s | FileCheck %s
+// RUN: %clang_cc1 -I %S/Inputs -triple x86_64-apple-macosx -emit-llvm -O2 -disable-llvm-passes -o - %s | FileCheck %s
#import "nsvalue-boxed-expressions-support.h"
// CHECK: [[CLASS:@.*]] = external global %struct._class_t
// CHECK: [[NSVALUE:@.*]] = {{.*}}[[CLASS]]{{.*}}
// CHECK: [[RANGE_STR:.*]] = {{.*}}_NSRange=QQ{{.*}}
-// CHECK: [[METH:@.*]] = private global{{.*}}valueWithBytes:objCType:{{.*}}
+// CHECK: [[METH:@.*]] = private unnamed_addr constant {{.*}}valueWithBytes:objCType:{{.*}}
// CHECK: [[VALUE_SEL:@.*]] = {{.*}}[[METH]]{{.*}}
// CHECK: [[POINT_STR:.*]] = {{.*}}_NSPoint=dd{{.*}}
// CHECK: [[SIZE_STR:.*]] = {{.*}}_NSSize=dd{{.*}}
diff --git a/test/CodeGenObjC/nullptr-assert.m b/test/CodeGenObjC/nullptr-assert.m
new file mode 100644
index 000000000000..06e50db35c4d
--- /dev/null
+++ b/test/CodeGenObjC/nullptr-assert.m
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -Wno-objc-root-class -o /dev/null -triple x86_64-- -emit-llvm %s
+// REQUIRES: asserts
+// Verify there is no assertion.
+
+@interface A
+@end
+
+extern A *a;
+
+@interface X
+@end
+
+@implementation X
+
+-(void)test {
+ struct S {
+ A *a;
+ int b;
+ };
+ struct S s[] = {{a, 0}, {(void *)0, 0}};
+}
+@end
diff --git a/test/CodeGenObjC/objc-asm-attribute-test.m b/test/CodeGenObjC/objc-asm-attribute-test.m
index 7b3a64deb74c..c988eae654e6 100644
--- a/test/CodeGenObjC/objc-asm-attribute-test.m
+++ b/test/CodeGenObjC/objc-asm-attribute-test.m
@@ -59,9 +59,9 @@ id Test16877359() {
// CHECK: @"OBJC_CLASS_$_MySecretNamespace.Message" = global %struct._class_t
// CHECK: @"OBJC_METACLASS_$_MySecretNamespace.Message" = global %struct._class_t
-// CHECK: private global [42 x i8] c"T@\22MySecretNamespace.Message\22,&,V_msgProp\00"
-// CHECK: private global [76 x i8] c"T@\22MySecretNamespace.Message<MySecretNamespace.Protocol3>\22,&,V_msgProtoProp\00"
-// CHECK: private global [50 x i8] c"T@\22<MySecretNamespace.Protocol3>\22,&,V_idProtoProp\00"
+// CHECK: private unnamed_addr constant [42 x i8] c"T@\22MySecretNamespace.Message\22,&,V_msgProp\00"
+// CHECK: private unnamed_addr constant [76 x i8] c"T@\22MySecretNamespace.Message<MySecretNamespace.Protocol3>\22,&,V_msgProtoProp\00"
+// CHECK: private unnamed_addr constant [50 x i8] c"T@\22<MySecretNamespace.Protocol3>\22,&,V_idProtoProp\00"
// CHECK: @"OBJC_CLASS_$_foo" = external global %struct._class_t
// CHECK: define internal i8* @"\01-[Message MyMethod]"
diff --git a/test/CodeGenObjC/objc-literal-tests.m b/test/CodeGenObjC/objc-literal-tests.m
index 03286e24563e..aa576d4e8a3d 100644
--- a/test/CodeGenObjC/objc-literal-tests.m
+++ b/test/CodeGenObjC/objc-literal-tests.m
@@ -94,4 +94,4 @@ void baz(void) {
bar(^(void) { return YES; });
}
-// CHECK: attributes [[NUW]] = { {{(norecurse )?}}nounwind{{.*}} }
+// CHECK: attributes [[NUW]] = { noinline {{(norecurse )?}}nounwind{{.*}} }
diff --git a/test/CodeGenObjC/os_log.m b/test/CodeGenObjC/os_log.m
new file mode 100644
index 000000000000..5d48783de472
--- /dev/null
+++ b/test/CodeGenObjC/os_log.m
@@ -0,0 +1,39 @@
+// RUN: %clang_cc1 %s -emit-llvm -o - -triple x86_64-darwin-apple -fobjc-arc -O2 | FileCheck %s
+
+// Make sure we emit clang.arc.use before calling objc_release as part of the
+// cleanup. This way we make sure the object will not be released until the
+// end of the full expression.
+
+// rdar://problem/24528966
+
+@class NSString;
+extern __attribute__((visibility("default"))) NSString *GenString();
+
+// Behavior of __builtin_os_log differs between platforms, so only test on X86
+#ifdef __x86_64__
+// CHECK-LABEL: define i8* @test_builtin_os_log
+void *test_builtin_os_log(void *buf) {
+ return __builtin_os_log_format(buf, "capabilities: %@", GenString());
+
+ // CHECK: store i8 2, i8*
+ // CHECK: [[NUM_ARGS:%.*]] = getelementptr i8, i8* {{.*}}, i64 1
+ // CHECK: store i8 1, i8* [[NUM_ARGS]]
+ //
+ // CHECK: [[ARG1_DESC:%.*]] = getelementptr i8, i8* {{.*}}, i64 2
+ // CHECK: store i8 64, i8* [[ARG1_DESC]]
+ // CHECK: [[ARG1_SIZE:%.*]] = getelementptr i8, i8* {{.*}}, i64 3
+ // CHECK: store i8 8, i8* [[ARG1_SIZE]]
+ // CHECK: [[ARG1:%.*]] = getelementptr i8, i8* {{.*}}, i64 4
+ // CHECK: [[ARG1_CAST:%.*]] = bitcast i8* [[ARG1]] to
+
+ // CHECK: [[STRING:%.*]] = {{.*}} call {{.*}} @GenString()
+ // CHECK: [[STRING_CAST:%.*]] = bitcast {{.*}} [[STRING]] to
+ // CHECK: call {{.*}} @objc_retainAutoreleasedReturnValue(i8* [[STRING_CAST]])
+ // CHECK: store {{.*}} [[STRING]], {{.*}} [[ARG1_CAST]]
+
+ // CHECK: call void (...) @clang.arc.use({{.*}} [[STRING]])
+ // CHECK: call void @objc_release(i8* [[STRING_CAST]])
+ // CHECK: ret i8*
+}
+
+#endif
diff --git a/test/CodeGenObjC/property-list-in-extension.m b/test/CodeGenObjC/property-list-in-extension.m
index 878745e73e4d..0c930c22820a 100644
--- a/test/CodeGenObjC/property-list-in-extension.m
+++ b/test/CodeGenObjC/property-list-in-extension.m
@@ -17,7 +17,7 @@ __attribute__((objc_root_class))
@end
// Metadata for _myprop should be present, and PROP_LIST for Foo should have
// only one entry.
-// CHECK: = private global [12 x i8] c"Ti,V_myprop\00",
+// CHECK: = private unnamed_addr constant [12 x i8] c"Ti,V_myprop\00",
// CHECK: @"\01l_OBJC_$_PROP_LIST_Foo" = private global { i32, i32, [1 x %struct._prop_t] }
// Readonly property in interface made readwrite in a category:
@@ -40,8 +40,8 @@ __attribute__((objc_root_class))
// Metadata for _evolvingprop should be present, and PROP_LIST for FooRO should
// still have only one entry, and the one entry should point to the version of
// the property with a getter and setter.
-// CHECK: [[evolvinggetter:@OBJC_PROP_NAME_ATTR[^ ]+]] = private global [13 x i8] c"evolvingprop\00"
-// CHECK: [[evolvingsetter:@OBJC_PROP_NAME_ATTR[^ ]+]] = private global [18 x i8] c"Ti,V_evolvingprop\00",
-// CHECK: [[booleanmetadata:@OBJC_PROP_NAME_ATTR[^ ]+]] = private global [34 x i8] c"Ti,N,GisBooleanProp,V_booleanProp\00"
-// CHECK: [[weakmetadata:@OBJC_PROP_NAME_ATTR[^ ]+]] = private global [23 x i8] c"T@\22Foo\22,W,N,V_weakProp\00"
+// CHECK: [[evolvinggetter:@OBJC_PROP_NAME_ATTR[^ ]+]] = private unnamed_addr constant [13 x i8] c"evolvingprop\00"
+// CHECK: [[evolvingsetter:@OBJC_PROP_NAME_ATTR[^ ]+]] = private unnamed_addr constant [18 x i8] c"Ti,V_evolvingprop\00",
+// CHECK: [[booleanmetadata:@OBJC_PROP_NAME_ATTR[^ ]+]] = private unnamed_addr constant [34 x i8] c"Ti,N,GisBooleanProp,V_booleanProp\00"
+// CHECK: [[weakmetadata:@OBJC_PROP_NAME_ATTR[^ ]+]] = private unnamed_addr constant [23 x i8] c"T@\22Foo\22,W,N,V_weakProp\00"
// CHECK: @"\01l_OBJC_$_PROP_LIST_FooRO" = private global { i32, i32, [3 x %struct._prop_t] }{{.*}}[[evolvinggetter]]{{.*}}[[evolvingsetter]]{{.*}}[[booleanmetadata]]
diff --git a/test/CodeGenObjC/protocol-comdat.m b/test/CodeGenObjC/protocol-comdat.m
new file mode 100644
index 000000000000..65e1b9fa2c82
--- /dev/null
+++ b/test/CodeGenObjC/protocol-comdat.m
@@ -0,0 +1,20 @@
+// RUN: %clang -cc1 -triple thumbv7--windows-itanium -fobjc-runtime=ios -emit-llvm -o - %s -Wno-objc-root-class | FileCheck %s
+
+@protocol P
+- (void) method;
+@end
+
+@interface I<P>
+@end
+
+@implementation I
+- (void) method { }
+@end
+
+
+// CHECK: $"\01l_OBJC_PROTOCOL_$_P" = comdat any
+// CHECK: $"\01l_OBJC_LABEL_PROTOCOL_$_P" = comdat any
+
+// CHECK: @"\01l_OBJC_PROTOCOL_$_P" = {{.*}}, comdat
+// CHECK: @"\01l_OBJC_LABEL_PROTOCOL_$_P" = {{.*}}, comdat
+
diff --git a/test/CodeGenObjC/reorder-synthesized-ivars.m b/test/CodeGenObjC/reorder-synthesized-ivars.m
index 958d447b983c..ef1bb79bcccb 100644
--- a/test/CodeGenObjC/reorder-synthesized-ivars.m
+++ b/test/CodeGenObjC/reorder-synthesized-ivars.m
@@ -38,21 +38,21 @@ typedef signed char BOOL;
}
@end
-// CHECK: @{{.*}} = private global [10 x i8] c"_boolean1
-// CHECK-NEXT: @{{.*}} = private global [10 x i8] c"_boolean2
-// CHECK-NEXT: @{{.*}} = private global [10 x i8] c"_boolean3
-// CHECK-NEXT: @{{.*}} = private global [10 x i8] c"_boolean4
-// CHECK-NEXT: @{{.*}} = private global [10 x i8] c"_boolean5
-// CHECK-NEXT: @{{.*}} = private global [10 x i8] c"_boolean6
-// CHECK-NEXT: @{{.*}} = private global [10 x i8] c"_boolean7
-// CHECK-NEXT: @{{.*}} = private global [10 x i8] c"_boolean8
-// CHECK-NEXT: @{{.*}} = private global [10 x i8] c"_boolean9
-// CHECK-NEXT: @{{.*}} = private global [9 x i8] c"_object1
-// CHECK-NEXT: @{{.*}} = private global [9 x i8] c"_object2
-// CHECK-NEXT: @{{.*}} = private global [9 x i8] c"_object3
-// CHECK-NEXT: @{{.*}} = private global [9 x i8] c"_object4
-// CHECK-NEXT: @{{.*}} = private global [9 x i8] c"_object5
-// CHECK-NEXT: @{{.*}} = private global [9 x i8] c"_object6
-// CHECK-NEXT: @{{.*}} = private global [9 x i8] c"_object7
-// CHECK-NEXT: @{{.*}} = private global [9 x i8] c"_object8
-// CHECK-NEXT: @{{.*}} = private global [9 x i8] c"_object9
+// CHECK: @{{.*}} = private unnamed_addr constant [10 x i8] c"_boolean1
+// CHECK-NEXT: @{{.*}} = private unnamed_addr constant [10 x i8] c"_boolean2
+// CHECK-NEXT: @{{.*}} = private unnamed_addr constant [10 x i8] c"_boolean3
+// CHECK-NEXT: @{{.*}} = private unnamed_addr constant [10 x i8] c"_boolean4
+// CHECK-NEXT: @{{.*}} = private unnamed_addr constant [10 x i8] c"_boolean5
+// CHECK-NEXT: @{{.*}} = private unnamed_addr constant [10 x i8] c"_boolean6
+// CHECK-NEXT: @{{.*}} = private unnamed_addr constant [10 x i8] c"_boolean7
+// CHECK-NEXT: @{{.*}} = private unnamed_addr constant [10 x i8] c"_boolean8
+// CHECK-NEXT: @{{.*}} = private unnamed_addr constant [10 x i8] c"_boolean9
+// CHECK-NEXT: @{{.*}} = private unnamed_addr constant [9 x i8] c"_object1
+// CHECK-NEXT: @{{.*}} = private unnamed_addr constant [9 x i8] c"_object2
+// CHECK-NEXT: @{{.*}} = private unnamed_addr constant [9 x i8] c"_object3
+// CHECK-NEXT: @{{.*}} = private unnamed_addr constant [9 x i8] c"_object4
+// CHECK-NEXT: @{{.*}} = private unnamed_addr constant [9 x i8] c"_object5
+// CHECK-NEXT: @{{.*}} = private unnamed_addr constant [9 x i8] c"_object6
+// CHECK-NEXT: @{{.*}} = private unnamed_addr constant [9 x i8] c"_object7
+// CHECK-NEXT: @{{.*}} = private unnamed_addr constant [9 x i8] c"_object8
+// CHECK-NEXT: @{{.*}} = private unnamed_addr constant [9 x i8] c"_object9
diff --git a/test/CodeGenObjC/runtime-abi-match.m b/test/CodeGenObjC/runtime-abi-match.m
new file mode 100644
index 000000000000..ef391724ece0
--- /dev/null
+++ b/test/CodeGenObjC/runtime-abi-match.m
@@ -0,0 +1,25 @@
+// RUN: %clang -target armv7-windows -fobjc-runtime=ios -O1 -fexceptions -S -emit-llvm %s -o - | FileCheck %s
+// REQUIRES: arm-registered-target
+
+void (*f)(id);
+void (*g)(void);
+void h(void);
+
+@interface NSNumber
++ (NSNumber *)numberWithInt:(int)i;
+@end
+
+void i(void) {
+ @try {
+ @throw(@1);
+ } @catch (id i) {
+ (*f)(i);
+ (*g)();
+ }
+}
+
+// CHECK: call arm_aapcs_vfpcc i8* @objc_begin_catch
+// CHECK: call arm_aapcs_vfpcc void @objc_end_catch
+// CHECK-NOT: call i8* @objc_begin_catch
+// CHECK-NOT: call void @objc_end_catch
+
diff --git a/test/CodeGenObjC/section-name.m b/test/CodeGenObjC/section-name.m
new file mode 100644
index 000000000000..46775a905b7d
--- /dev/null
+++ b/test/CodeGenObjC/section-name.m
@@ -0,0 +1,45 @@
+// RUN: %clang_cc1 -triple thumbv7--windows-itanium -fdeclspec -fobjc-runtime=ios -emit-llvm -o - %s -Wno-objc-root-class | FileCheck %s
+
+@protocol Protocol
+- (void) protocol_method;
+@end
+
+__declspec(dllexport)
+@interface Interface<Protocol>
+@property(assign) id property;
++ (void) class_method;
+- (void) instance_method;
+@end
+
+
+@implementation Interface
++ (void) class_method {
+}
+
+- (void) protocol_method {
+}
+
+- (void) instance_method {
+}
+@end
+
+@implementation Interface(Category)
+- (void) category_method {
+}
+@end
+
+// CHECK-NOT: @"OBJC_IVAR_$_Interface._property" = {{.*}} section "__DATA, __objc_ivar"
+// CHECK-NOT: @"OBJC_CLASS_$_Interface" = {{.*}} section "__DATA, __objc_data"
+// CHECK-NOT: @"OBJC_METACLASS_$_Interface" = {{.*}} section "__DATA, __objc_data"
+// CHECK-NOT: @"\01l_OBJC_$_CLASS_METHODS_Interface" = {{.*}} section "__DATA, __objc_const"
+// CHECK-NOT: @"\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_Protocol" = {{.*}} section "__DATA, __objc_const"
+// CHECK-NOT: @"\01l_OBJC_$_PROTOCOL_METHOD_TYPES_Protocol" = {{.*}} section "__DATA, __objc_const"
+// CHECK-NOT: @"\01l_OBJC_CLASS_PROTOCOLS_$_Interface" = {{.*}} section "__DATA, __objc_const"
+// CHECK-NOT: @"\01l_OBJC_METACLASS_RO_$_" = {{.*}} section "__DATA, __objc_const"
+// CHECK-NOT: @"\01l_OBJC_$_INSTANCE_METHODS_Interface" = {{.*}} section "__DATA, __objc_const"
+// CHECK-NOT: @"\01l_OBJC_$_INSTANCE_VARIABLES_Interface" = {{.*}} section "__DATA, __objc_const"
+// CHECK-NOT: @"\01l_OBJC_$_PROP_LIST_Interface" = {{.*}} section "__DATA, __objc_const"
+// CHECK-NOT: @"\01l_OBJC_CLASS_RO_$_Interface" = {{.*}} section "__DATA, __objc_const"
+// CHECK-NOT: @"\01l_OBJC_$_CATEGORY_INSTANCE_METHODS_Interface_$_Category" = {{.*}} section "__DATA, __objc_const"
+// CHECK-NOT: @"\01l_OBJC_$_CATEGORY_Interface_$_Category" = {{.*}} section "__DATA, __objc_const"
+
diff --git a/test/CodeGenObjC/tentative-cfconstantstring.m b/test/CodeGenObjC/tentative-cfconstantstring.m
index 9ff1a0a2fce2..bb76b033cf5f 100644
--- a/test/CodeGenObjC/tentative-cfconstantstring.m
+++ b/test/CodeGenObjC/tentative-cfconstantstring.m
@@ -32,7 +32,7 @@ static inline void _inlineFunction() {
@end
// CHECK: @__CFConstantStringClassReference = common global [24 x i32] zeroinitializer, align 16
-// CHECK: @_unnamed_cfstring_{{.*}} = private constant %struct.__NSConstantString_tag { i32* getelementptr inbounds ([24 x i32], [24 x i32]* @__CFConstantStringClassReference, i32 0, i32 0)
+// CHECK: @_unnamed_cfstring_{{.*}} = private global %struct.__NSConstantString_tag { i32* getelementptr inbounds ([24 x i32], [24 x i32]* @__CFConstantStringClassReference, i32 0, i32 0)
// CHECK-LABEL: define internal void @_inlineFunction()
// CHECK: [[ZERO:%.*]] = load %struct._class_t*, %struct._class_t** @"OBJC_CLASSLIST_REFERENCES_
diff --git a/test/CodeGenObjC/ubsan-array-bounds.m b/test/CodeGenObjC/ubsan-array-bounds.m
new file mode 100644
index 000000000000..38d1eb310d21
--- /dev/null
+++ b/test/CodeGenObjC/ubsan-array-bounds.m
@@ -0,0 +1,59 @@
+// RUN: %clang_cc1 -x objective-c -emit-llvm -triple x86_64-apple-macosx10.10.0 -Wno-objc-root-class -fsanitize=array-bounds %s -o - | FileCheck %s
+
+@interface FlexibleArray1 {
+@public
+ char chars[0];
+}
+@end
+@implementation FlexibleArray1
+@end
+
+// CHECK-LABEL: test_FlexibleArray1
+char test_FlexibleArray1(FlexibleArray1 *FA1) {
+ // CHECK-NOT: !nosanitize
+ return FA1->chars[1];
+ // CHECK: }
+}
+
+@interface FlexibleArray2 {
+@public
+ char chars[0];
+}
+@end
+@implementation FlexibleArray2 {
+@public
+ char chars2[0];
+}
+@end
+
+// CHECK-LABEL: test_FlexibleArray2_1
+char test_FlexibleArray2_1(FlexibleArray2 *FA2) {
+ // CHECK: !nosanitize
+ return FA2->chars[1];
+ // CHECK: }
+}
+
+// CHECK-LABEL: test_FlexibleArray2_2
+char test_FlexibleArray2_2(FlexibleArray2 *FA2) {
+ // CHECK-NOT: !nosanitize
+ return FA2->chars2[1];
+ // CHECK: }
+}
+
+@interface FlexibleArray3 {
+@public
+ char chars[0];
+}
+@end
+@implementation FlexibleArray3 {
+@public
+ int i;
+}
+@end
+
+// CHECK-LABEL: test_FlexibleArray3
+char test_FlexibleArray3(FlexibleArray3 *FA3) {
+ // CHECK: !nosanitize
+ return FA3->chars[1];
+ // CHECK: }
+}
diff --git a/test/CodeGenObjC/ubsan-bool.m b/test/CodeGenObjC/ubsan-bool.m
new file mode 100644
index 000000000000..6d6c08358d07
--- /dev/null
+++ b/test/CodeGenObjC/ubsan-bool.m
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -x objective-c -emit-llvm -triple x86_64-apple-macosx10.10.0 -fsanitize=bool %s -o - | FileCheck %s -check-prefixes=SHARED,OBJC
+// RUN: %clang_cc1 -x objective-c++ -emit-llvm -triple x86_64-apple-macosx10.10.0 -fsanitize=bool %s -o - | FileCheck %s -check-prefixes=SHARED,OBJC
+// RUN: %clang_cc1 -x c -emit-llvm -triple x86_64-apple-macosx10.10.0 -fsanitize=bool %s -o - | FileCheck %s -check-prefixes=SHARED,C
+
+typedef signed char BOOL;
+
+// SHARED-LABEL: f1
+BOOL f1() {
+ // OBJC: call void @__ubsan_handle_load_invalid_value
+ // C-NOT: call void @__ubsan_handle_load_invalid_value
+ BOOL a = 2;
+ return a + 1;
+}
diff --git a/test/CodeGenObjC/unqual-copy-restore.m b/test/CodeGenObjC/unqual-copy-restore.m
new file mode 100644
index 000000000000..09915f7ce6a8
--- /dev/null
+++ b/test/CodeGenObjC/unqual-copy-restore.m
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 %s -fobjc-arc -S -emit-llvm -o /dev/null
+
+// rdar://problem/28488427 - Don't crash if the argument type and the parameter
+// type in an indirect copy restore expression have different qualification.
+@protocol P1
+@end
+
+typedef int handler(id<P1> *const p);
+
+int main() {
+ id<P1> i1 = 0;
+ handler *func = 0;
+ return func(&i1);
+}
diff --git a/test/CodeGenObjCXX/arc-attrs.mm b/test/CodeGenObjCXX/arc-attrs.mm
index 0f0610f1721d..0b64d775660a 100644
--- a/test/CodeGenObjCXX/arc-attrs.mm
+++ b/test/CodeGenObjCXX/arc-attrs.mm
@@ -46,3 +46,24 @@ void templateTest() {
// CHECK-NEXT: call void @objc_storeStrong(i8** [[X]], i8* null)
// CHECK-NEXT: ret void
}
+
+// PR27887
+struct ForwardConsumed {
+ ForwardConsumed(__attribute__((ns_consumed)) id x);
+};
+
+ForwardConsumed::ForwardConsumed(__attribute__((ns_consumed)) id x) {}
+
+// CHECK: define void @_ZN15ForwardConsumedC2EP11objc_object(
+// CHECK-NOT: objc_retain
+// CHECK: store i8* {{.*}}, i8** [[X:%.*]],
+// CHECK-NOT: [[X]]
+// CHECK: call void @objc_storeStrong(i8** [[X]], i8* null)
+
+// CHECK: define void @_ZN15ForwardConsumedC1EP11objc_object(
+// CHECK-NOT: objc_retain
+// CHECK: store i8* {{.*}}, i8** [[X:%.*]],
+// CHECK: [[T0:%.*]] = load i8*, i8** [[X]],
+// CHECK-NEXT: store i8* null, i8** [[X]],
+// CHECK-NEXT: call void @_ZN15ForwardConsumedC2EP11objc_object({{.*}}, i8* [[T0]])
+// CHECK: call void @objc_storeStrong(i8** [[X]], i8* null)
diff --git a/test/CodeGenObjCXX/arc-blocks.mm b/test/CodeGenObjCXX/arc-blocks.mm
index 50579d7a0e4d..2bae18a19b3f 100644
--- a/test/CodeGenObjCXX/arc-blocks.mm
+++ b/test/CodeGenObjCXX/arc-blocks.mm
@@ -2,7 +2,7 @@
// CHECK: [[A:.*]] = type { i64, [10 x i8*] }
-// CHECK: [[LAYOUT0:@.*]] = private global [3 x i8] c" 9\00"
+// CHECK: [[LAYOUT0:@.*]] = private unnamed_addr constant [3 x i8] c" 9\00"
// rdar://13045269
// If a __block variable requires extended layout information *and*
diff --git a/test/CodeGenObjCXX/arc-constexpr.mm b/test/CodeGenObjCXX/arc-constexpr.mm
new file mode 100644
index 000000000000..786e2cb8f2cc
--- /dev/null
+++ b/test/CodeGenObjCXX/arc-constexpr.mm
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-arc -o - -std=c++11 %s | FileCheck %s
+
+// CHECK: %[[TYPE:[a-z0-9]+]] = type opaque
+// CHECK: @[[CFSTRING:[a-z0-9_]+]] = private global %struct.__NSConstantString_tag
+
+// CHECK: define void @_Z5test1v
+// CHECK: %[[ALLOCA:[A-Z]+]] = alloca %[[TYPE]]*
+// CHECK: %[[V0:[0-9]+]] = call i8* @objc_retain(i8* bitcast (%struct.__NSConstantString_tag* @[[CFSTRING]]
+// CHECK: %[[V1:[0-9]+]] = bitcast i8* %[[V0]] to %[[TYPE]]*
+// CHECK: store %[[TYPE]]* %[[V1]], %[[TYPE]]** %[[ALLOCA]]
+// CHECK: %[[V2:[0-9]+]] = bitcast %[[TYPE]]** %[[ALLOCA]]
+// CHECK: call void @objc_storeStrong(i8** %[[V2]], i8* null)
+
+@class NSString;
+
+void test1() {
+ constexpr NSString *S = @"abc";
+}
diff --git a/test/CodeGenObjCXX/arc-cxx11-init-list.mm b/test/CodeGenObjCXX/arc-cxx11-init-list.mm
index 27442f813044..c3723c619ab0 100644
--- a/test/CodeGenObjCXX/arc-cxx11-init-list.mm
+++ b/test/CodeGenObjCXX/arc-cxx11-init-list.mm
@@ -1,9 +1,9 @@
// RUN: %clang_cc1 -triple armv7-ios5.0 -std=c++11 -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 constant %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"
+// 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"
// CHECK: @[[STR1:.*]] = private unnamed_addr constant [5 x i8] c"str1\00", section "__TEXT,__cstring,cstring_literals"
-// CHECK: @[[UNNAMED_CFSTRING1:.*]] = private constant %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]* @[[STR1]], i32 0, i32 0), i32 4 }, section "__DATA,__cfstring"
+// CHECK: @[[UNNAMED_CFSTRING1:.*]] = 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]* @[[STR1]], i32 0, i32 0), i32 4 }, section "__DATA,__cfstring"
// CHECK: @[[REFTMP:.*]] = private constant [2 x i8*] [i8* bitcast (%struct.__NSConstantString_tag* @[[UNNAMED_CFSTRING0]] to i8*), i8* bitcast (%struct.__NSConstantString_tag* @[[UNNAMED_CFSTRING1]] to i8*)]
typedef __SIZE_TYPE__ size_t;
diff --git a/test/CodeGenObjCXX/arc-globals.mm b/test/CodeGenObjCXX/arc-globals.mm
index c8be8c023938..a03ac9948bd3 100644
--- a/test/CodeGenObjCXX/arc-globals.mm
+++ b/test/CodeGenObjCXX/arc-globals.mm
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -O2 -disable-llvm-optzns -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -O2 -disable-llvm-passes -o - %s | FileCheck %s
// Test that we're properly retaining lifetime-qualified pointers
// initialized statically and wrapping up those initialization in an
diff --git a/test/CodeGenObjCXX/arc-move.mm b/test/CodeGenObjCXX/arc-move.mm
index d1710e291b09..7437d6b6c7f9 100644
--- a/test/CodeGenObjCXX/arc-move.mm
+++ b/test/CodeGenObjCXX/arc-move.mm
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -O2 -std=c++11 -disable-llvm-optzns -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -O2 -std=c++11 -disable-llvm-passes -o - %s | FileCheck %s
// define void @_Z11simple_moveRU8__strongP11objc_objectS2_
void simple_move(__strong id &x, __strong id &y) {
diff --git a/test/CodeGenObjCXX/arc-new-delete.mm b/test/CodeGenObjCXX/arc-new-delete.mm
index 141f40195782..9fb57819901f 100644
--- a/test/CodeGenObjCXX/arc-new-delete.mm
+++ b/test/CodeGenObjCXX/arc-new-delete.mm
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -fobjc-arc -fobjc-runtime-has-weak -fblocks -triple x86_64-apple-darwin10.0.0 -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=UNOPT
-// RUN: %clang_cc1 -fobjc-arc -fobjc-runtime-has-weak -fblocks -triple x86_64-apple-darwin10.0.0 -emit-llvm -o - %s -O -disable-llvm-optzns | FileCheck %s -check-prefix=CHECK -check-prefix=OPT
+// RUN: %clang_cc1 -fobjc-arc -fobjc-runtime-has-weak -fblocks -triple x86_64-apple-darwin10.0.0 -emit-llvm -o - %s -O -disable-llvm-passes | FileCheck %s -check-prefix=CHECK -check-prefix=OPT
typedef __strong id strong_id;
typedef __weak id weak_id;
diff --git a/test/CodeGenObjCXX/arc-references.mm b/test/CodeGenObjCXX/arc-references.mm
index 8397abeb676b..c62df4e49bb6 100644
--- a/test/CodeGenObjCXX/arc-references.mm
+++ b/test/CodeGenObjCXX/arc-references.mm
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-runtime-has-weak -fblocks -fobjc-arc -O2 -disable-llvm-optzns -o - %s | FileCheck %s
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-runtime-has-weak -fblocks -fobjc-arc -O2 -disable-llvm-passes -o - %s | FileCheck %s
@interface A
@end
diff --git a/test/CodeGenObjCXX/arc-special-member-functions.mm b/test/CodeGenObjCXX/arc-special-member-functions.mm
index df3c22916f57..af161ddc5ad5 100644
--- a/test/CodeGenObjCXX/arc-special-member-functions.mm
+++ b/test/CodeGenObjCXX/arc-special-member-functions.mm
@@ -141,10 +141,9 @@ void test_ObjCBlockMember_copy_assign(ObjCBlockMember m1, ObjCBlockMember m2) {
// Implicitly-generated copy constructor for ObjCArrayMember
// CHECK-LABEL: define linkonce_odr void @_ZN15ObjCArrayMemberC2ERKS_
-// CHECK: br i1
// CHECK: call i8* @objc_retain
// CHECK-NEXT: store i8*
-// CHECK-NEXT: br label
+// CHECK: br i1
// CHECK: ret
// Implicitly-generated default constructor for ObjCBlockMember
diff --git a/test/CodeGenObjCXX/arc.mm b/test/CodeGenObjCXX/arc.mm
index e3a6349afaf0..b9d2c4de2fcd 100644
--- a/test/CodeGenObjCXX/arc.mm
+++ b/test/CodeGenObjCXX/arc.mm
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-runtime-has-weak -fblocks -fobjc-arc -O2 -disable-llvm-optzns -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-runtime-has-weak -fblocks -fobjc-arc -O2 -disable-llvm-passes -o - %s | FileCheck %s
struct NSFastEnumerationState;
@interface NSArray
diff --git a/test/CodeGenObjCXX/debug-info-cyclic.mm b/test/CodeGenObjCXX/debug-info-cyclic.mm
index 13dd5ab6e100..2fb1611c904d 100644
--- a/test/CodeGenObjCXX/debug-info-cyclic.mm
+++ b/test/CodeGenObjCXX/debug-info-cyclic.mm
@@ -3,7 +3,7 @@
struct B {
// CHECK: ![[B:[0-9]+]] ={{.*}}!DICompositeType(tag: DW_TAG_structure_type, name: "B"
// CHECK-SAME: line: [[@LINE-2]],
-// CHECK-SAME: size: 8, align: 8,
+// CHECK-SAME: size: 8,
// CHECK-NOT: offset:
// CHECK-NOT: DIFlagFwdDecl
// CHECK-SAME: elements: ![[BMEMBERS:[0-9]+]]
diff --git a/test/CodeGenObjCXX/destroy.mm b/test/CodeGenObjCXX/destroy.mm
index 5d797d32d42e..371f729afad2 100644
--- a/test/CodeGenObjCXX/destroy.mm
+++ b/test/CodeGenObjCXX/destroy.mm
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-arc -disable-llvm-optzns -o - %s | FileCheck %s
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-arc -disable-llvm-passes -o - %s | FileCheck %s
// rdar://18249673
@class MyObject;
diff --git a/test/CodeGenObjCXX/encode.mm b/test/CodeGenObjCXX/encode.mm
index e0171efbed8a..5bb4a1ecfa9b 100644
--- a/test/CodeGenObjCXX/encode.mm
+++ b/test/CodeGenObjCXX/encode.mm
@@ -213,7 +213,7 @@ public:
dynamic_class dynamic_class_ivar;
}
@end
-// CHECK: private global [41 x i8] c"{dynamic_class=\22_vptr$dynamic_class\22^^?}\00"
+// CHECK: private unnamed_addr constant [41 x i8] c"{dynamic_class=\22_vptr$dynamic_class\22^^?}\00"
namespace PR17142 {
struct A { virtual ~A(); };
@@ -224,3 +224,24 @@ namespace PR17142 {
// CHECK: @_ZN7PR171421xE = constant [14 x i8] c"{E=^^?i^^?ii}\00"
extern const char x[] = @encode(E);
}
+
+// This test used to cause infinite recursion.
+template<typename T>
+struct S {
+ typedef T Ty;
+ Ty *t;
+};
+
+@interface N
+{
+ S<N> a;
+}
+@end
+
+@implementation N
+@end
+
+const char *expand_struct() {
+ // CHECK: @{{.*}} = private unnamed_addr constant [16 x i8] c"{N={S<N>=^{N}}}\00"
+ return @encode(N);
+}
diff --git a/test/CodeGenObjCXX/exceptions-legacy.mm b/test/CodeGenObjCXX/exceptions-legacy.mm
index dac259d91cb5..bfc8d640b710 100644
--- a/test/CodeGenObjCXX/exceptions-legacy.mm
+++ b/test/CodeGenObjCXX/exceptions-legacy.mm
@@ -16,8 +16,8 @@ void test0(id obj) {
// Enter the @synchronized block.
// CHECK: call i32 @objc_sync_enter(i8* [[OBJ:%.*]])
// CHECK: call void @objc_exception_try_enter([[BUF_T:%.*]]* nonnull [[BUF:%.*]])
-// CHECK-NEXT: [[T0:%.*]] = getelementptr [[BUF_T]], [[BUF_T]]* [[BUF]], i32 0, i32 0, i32 0
-// CHECK-NEXT: [[T1:%.*]] = call i32 @_setjmp(i32* [[T0]])
+// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[BUF_T]], [[BUF_T]]* [[BUF]], i32 0, i32 0, i32 0
+// CHECK-NEXT: [[T1:%.*]] = call i32 @_setjmp(i32* nonnull [[T0]])
// CHECK-NEXT: [[T2:%.*]] = icmp eq i32 [[T1]], 0
// CHECK-NEXT: br i1 [[T2]],
@@ -55,8 +55,8 @@ void test1(id obj, bool *failed) {
// CHECK-LABEL: define void @_Z5test1P11objc_objectPb(
// Enter the @try block.
// CHECK: call void @objc_exception_try_enter([[BUF_T]]* nonnull [[BUF:%.*]])
-// CHECK-NEXT: [[T0:%.*]] = getelementptr [[BUF_T]], [[BUF_T]]* [[BUF]], i32 0, i32 0, i32 0
-// CHECK-NEXT: [[T1:%.*]] = call i32 @_setjmp(i32* [[T0]])
+// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[BUF_T]], [[BUF_T]]* [[BUF]], i32 0, i32 0, i32 0
+// CHECK-NEXT: [[T1:%.*]] = call i32 @_setjmp(i32* nonnull [[T0]])
// CHECK-NEXT: [[T2:%.*]] = icmp eq i32 [[T1]], 0
// CHECK-NEXT: br i1 [[T2]],
diff --git a/test/CodeGenObjCXX/implicit-copy-constructor.mm b/test/CodeGenObjCXX/implicit-copy-constructor.mm
index 6c56616f04cf..e1c7b8ded0e6 100644
--- a/test/CodeGenObjCXX/implicit-copy-constructor.mm
+++ b/test/CodeGenObjCXX/implicit-copy-constructor.mm
@@ -49,12 +49,14 @@ void f(D d) {
// CHECK: call void @_ZN1BC2ERS_
// CHECK: {{call void @llvm.memcpy.p0i8.p0i8.i64.*i64 24}}
// CHECK: call void @_ZN1BC1ERS_
-// CHECK: br
-// CHECK: {{icmp ult.*, 2}}
-// CHECK: {{icmp ult.*, 3}}
+// CHECK: br label
// CHECK: call void @_ZN1AC1Ev
// CHECK: call void @_ZN1CC1ERS_1A
// CHECK: call void @_ZN1AD1Ev
+// CHECK: {{icmp eq.*, 3}}
+// CHECK: br i1
+// CHECK: {{icmp eq.*, 2}}
+// CHECK: br i1
// CHECK: {{call.*@objc_memmove_collectable}}
// CHECK: {{call void @llvm.memcpy.p0i8.p0i8.i64.*i64 12}}
// CHECK: ret void
diff --git a/test/CodeGenObjCXX/lambda-expressions.mm b/test/CodeGenObjCXX/lambda-expressions.mm
index 0c309c0a4e61..7ac7a2137fb4 100644
--- a/test/CodeGenObjCXX/lambda-expressions.mm
+++ b/test/CodeGenObjCXX/lambda-expressions.mm
@@ -4,8 +4,10 @@
typedef int (^fp)();
fp f() { auto x = []{ return 3; }; return x; }
-// MRC: @OBJC_METH_VAR_NAME{{.*}} = private global [5 x i8] c"copy\00"
-// MRC: @OBJC_METH_VAR_NAME{{.*}} = private global [12 x i8] c"autorelease\00"
+// ARC: %[[LAMBDACLASS:.*]] = type { i32 }
+
+// MRC: @OBJC_METH_VAR_NAME{{.*}} = private unnamed_addr constant [5 x i8] c"copy\00"
+// MRC: @OBJC_METH_VAR_NAME{{.*}} = private unnamed_addr constant [12 x i8] c"autorelease\00"
// MRC-LABEL: define i32 ()* @_Z1fv(
// MRC-LABEL: define internal i32 ()* @"_ZZ1fvENK3$_0cvU13block_pointerFivEEv"
// MRC: store i8* bitcast (i8** @_NSConcreteStackBlock to i8*)
@@ -60,6 +62,40 @@ void take_block(void (^block)()) { block(); }
}
@end
+// ARC: define void @_ZN13LambdaCapture4foo1ERi(i32* dereferenceable(4) %{{.*}})
+// ARC: %[[CAPTURE0:.*]] = getelementptr inbounds %[[LAMBDACLASS]], %[[LAMBDACLASS]]* %{{.*}}, i32 0, i32 0
+// ARC: store i32 %{{.*}}, i32* %[[CAPTURE0]]
+
+// ARC: define internal void @"_ZZN13LambdaCapture4foo1ERiENK3$_3clEv"(%[[LAMBDACLASS]]* %{{.*}})
+// ARC: %[[BLOCK:.*]] = alloca <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i32 }>
+// ARC: %[[CAPTURE1:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i32 }>, <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i32 }>* %[[BLOCK]], i32 0, i32 5
+// ARC: store i32 %{{.*}}, i32* %[[CAPTURE1]]
+
+// ARC: define internal void @"___ZZN13LambdaCapture4foo1ERiENK3$_3clEv_block_invoke"
+// ARC: %[[CAPTURE2:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i32 }>, <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i32 }>* %{{.*}}, i32 0, i32 5
+// ARC: store i32 %{{.*}}, i32* %[[CAPTURE2]]
+
+// ARC: define internal void @"___ZZN13LambdaCapture4foo1ERiENK3$_3clEv_block_invoke_2"(i8* %{{.*}})
+// ARC: %[[CAPTURE3:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i32 }>, <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i32 }>* %{{.*}}, i32 0, i32 5
+// ARC: %[[V1:.*]] = load i32, i32* %[[CAPTURE3]]
+// ARC: store i32 %[[V1]], i32* @_ZN13LambdaCapture1iE
+
+namespace LambdaCapture {
+ int i;
+ void foo1(int &a) {
+ auto lambda = [a]{
+ auto block1 = ^{
+ auto block2 = ^{
+ i = a;
+ };
+ block2();
+ };
+ block1();
+ };
+ lambda();
+ }
+}
+
// ARC-LABEL: define linkonce_odr i32 ()* @_ZZNK13StaticMembersIfE1fMUlvE_clEvENKUlvE_cvU13block_pointerFivEEv
// Check lines for BlockInLambda test below
@@ -89,5 +125,5 @@ namespace BlockInLambda {
}
-// ARC: attributes [[NUW]] = { nounwind{{.*}} }
-// MRC: attributes [[NUW]] = { nounwind{{.*}} }
+// ARC: attributes [[NUW]] = { noinline nounwind{{.*}} }
+// MRC: attributes [[NUW]] = { noinline nounwind{{.*}} }
diff --git a/test/CodeGenObjCXX/literals.mm b/test/CodeGenObjCXX/literals.mm
index 4d1b5019412a..682add3cb531 100644
--- a/test/CodeGenObjCXX/literals.mm
+++ b/test/CodeGenObjCXX/literals.mm
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -I %S/Inputs -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-arc-exceptions -O2 -disable-llvm-optzns -o - %s | FileCheck %s
+// RUN: %clang_cc1 -I %S/Inputs -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-arc-exceptions -O2 -disable-llvm-passes -o - %s | FileCheck %s
#include "literal-support.h"
diff --git a/test/CodeGenObjCXX/property-object-reference-2.mm b/test/CodeGenObjCXX/property-object-reference-2.mm
index 925cc52f9092..230fe485895f 100644
--- a/test/CodeGenObjCXX/property-object-reference-2.mm
+++ b/test/CodeGenObjCXX/property-object-reference-2.mm
@@ -44,8 +44,8 @@ struct TCPPObject
// CHECK: ret void
// CHECK-LABEL: define internal void @__assign_helper_atomic_property_(%struct.TCPPObject*, %struct.TCPPObject*) #
-// CHECK: [[TWO:%.*]] = load %struct.TCPPObject*, %struct.TCPPObject** [[ADDR:%.*]], align 8
// CHECK: [[THREE:%.*]] = load %struct.TCPPObject*, %struct.TCPPObject** [[ADDR1:%.*]], align 8
+// CHECK: [[TWO:%.*]] = load %struct.TCPPObject*, %struct.TCPPObject** [[ADDR:%.*]], align 8
// CHECK: [[CALL:%.*]] = call dereferenceable({{[0-9]+}}) %struct.TCPPObject* @_ZN10TCPPObjectaSERKS_(%struct.TCPPObject* [[TWO]], %struct.TCPPObject* dereferenceable({{[0-9]+}}) [[THREE]])
// CHECK: ret void
diff --git a/test/CodeGenOpenCL/address-space-constant-initializers.cl b/test/CodeGenOpenCL/address-space-constant-initializers.cl
index 44c4ddf87800..45c64c2f716b 100644
--- a/test/CodeGenOpenCL/address-space-constant-initializers.cl
+++ b/test/CodeGenOpenCL/address-space-constant-initializers.cl
@@ -11,8 +11,8 @@ typedef struct {
__constant float* constant_float_ptr;
} ConstantArrayPointerStruct;
-// CHECK: %struct.ConstantArrayPointerStruct = type { float addrspace(3)* }
-// CHECK: addrspace(3) constant %struct.ConstantArrayPointerStruct { float addrspace(3)* bitcast (i8 addrspace(3)* getelementptr (i8, i8 addrspace(3)* bitcast (%struct.ArrayStruct addrspace(3)* @constant_array_struct to i8 addrspace(3)*), i64 4) to float addrspace(3)*) }
+// 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)*) }
// Bug 18567
__constant ConstantArrayPointerStruct constant_array_pointer_struct = {
&constant_array_struct.f
diff --git a/test/CodeGenOpenCL/address-spaces-mangling.cl b/test/CodeGenOpenCL/address-spaces-mangling.cl
index edb53fc35821..3c74c718c2a2 100644
--- a/test/CodeGenOpenCL/address-spaces-mangling.cl
+++ b/test/CodeGenOpenCL/address-spaces-mangling.cl
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 %s -ffake-address-space-map -faddress-space-map-mangling=yes -triple %itanium_abi_triple -emit-llvm -o - | FileCheck -check-prefix=ASMANG %s
// RUN: %clang_cc1 %s -ffake-address-space-map -faddress-space-map-mangling=no -triple %itanium_abi_triple -emit-llvm -o - | FileCheck -check-prefix=NOASMANG %s
+// We check that the address spaces are mangled the same in both version of OpenCL
+// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=CL2.0 -emit-llvm -o - | FileCheck -check-prefix=OCL-20 %s
+// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=CL1.2 -emit-llvm -o - | FileCheck -check-prefix=OCL-12 %s
+
// We can't name this f as private is equivalent to default
// no specifier given address space so we get multiple definition
// warnings, but we do want it for comparison purposes.
@@ -8,23 +12,33 @@ __attribute__((overloadable))
void ff(int *arg) { }
// ASMANG: @_Z2ffPi
// NOASMANG: @_Z2ffPi
+// OCL-20-DAG: @_Z2ffPU3AS4i
+// OCL-12-DAG: @_Z2ffPi
__attribute__((overloadable))
void f(private int *arg) { }
// ASMANG: @_Z1fPi
// NOASMANG: @_Z1fPi
+// OCL-20-DAG: @_Z1fPi
+// OCL-12-DAG: @_Z1fPi
__attribute__((overloadable))
void f(global int *arg) { }
// ASMANG: @_Z1fPU3AS1i
// NOASMANG: @_Z1fPU8CLglobali
+// OCL-20-DAG: @_Z1fPU3AS1i
+// OCL-12-DAG: @_Z1fPU3AS1i
__attribute__((overloadable))
void f(local int *arg) { }
-// ASMANG: @_Z1fPU3AS2i
+// ASMANG: @_Z1fPU3AS3i
// NOASMANG: @_Z1fPU7CLlocali
+// OCL-20-DAG: @_Z1fPU3AS3i
+// OCL-12-DAG: @_Z1fPU3AS3i
__attribute__((overloadable))
void f(constant int *arg) { }
-// ASMANG: @_Z1fPU3AS3i
+// ASMANG: @_Z1fPU3AS2i
// NOASMANG: @_Z1fPU10CLconstanti
+// OCL-20-DAG: @_Z1fPU3AS2i
+// OCL-12-DAG: @_Z1fPU3AS2i
diff --git a/test/CodeGenOpenCL/address-spaces.cl b/test/CodeGenOpenCL/address-spaces.cl
index 68fa02dadb26..3b34986d8936 100644
--- a/test/CodeGenOpenCL/address-spaces.cl
+++ b/test/CodeGenOpenCL/address-spaces.cl
@@ -7,10 +7,10 @@ void f__p(__private int *arg) {}
// CHECK: i32 addrspace(1)* %arg
void f__g(__global int *arg) {}
-// CHECK: i32 addrspace(2)* %arg
+// CHECK: i32 addrspace(3)* %arg
void f__l(__local int *arg) {}
-// CHECK: i32 addrspace(3)* %arg
+// CHECK: i32 addrspace(2)* %arg
void f__c(__constant int *arg) {}
// CHECK: i32* %arg
@@ -19,10 +19,10 @@ void fp(private int *arg) {}
// CHECK: i32 addrspace(1)* %arg
void fg(global int *arg) {}
-// CHECK: i32 addrspace(2)* %arg
+// CHECK: i32 addrspace(3)* %arg
void fl(local int *arg) {}
-// CHECK: i32 addrspace(3)* %arg
+// CHECK: i32 addrspace(2)* %arg
void fc(constant int *arg) {}
#ifdef CL20
diff --git a/test/CodeGenOpenCL/amdgpu-abi-struct-coerce.cl b/test/CodeGenOpenCL/amdgpu-abi-struct-coerce.cl
new file mode 100644
index 000000000000..f37fe6623992
--- /dev/null
+++ b/test/CodeGenOpenCL/amdgpu-abi-struct-coerce.cl
@@ -0,0 +1,66 @@
+// REQUIRES: amdgpu-registered-target
+// RUN: %clang_cc1 -triple amdgcn-unknown-unknown -S -emit-llvm -o - %s | FileCheck %s
+
+// CHECK-NOT: %struct.single_element_struct_arg = type { i32 }
+typedef struct single_element_struct_arg
+{
+ int i;
+} single_element_struct_arg_t;
+
+// CHECK: %struct.struct_arg = type { i32, float, i32 }
+typedef struct struct_arg
+{
+ int i1;
+ float f;
+ int i2;
+} struct_arg_t;
+
+// CHECK: %struct.struct_of_arrays_arg = type { [2 x i32], float, [4 x i32], [3 x float], i32 }
+typedef struct struct_of_arrays_arg
+{
+ int i1[2];
+ float f1;
+ int i2[4];
+ float f2[3];
+ int i3;
+} struct_of_arrays_arg_t;
+
+// CHECK: %struct.struct_of_structs_arg = type { i32, float, %struct.struct_arg, i32 }
+typedef struct struct_of_structs_arg
+{
+ int i1;
+ float f1;
+ struct_arg_t s1;
+ int i2;
+} struct_of_structs_arg_t;
+
+// CHECK-LABEL: @test_single_element_struct_arg
+// CHECK: i32 %arg1.coerce
+__kernel void test_single_element_struct_arg(single_element_struct_arg_t arg1)
+{
+}
+
+// CHECK-LABEL: @test_struct_arg
+// CHECK: %struct.struct_arg %arg1.coerce
+__kernel void test_struct_arg(struct_arg_t arg1)
+{
+}
+
+// CHECK-LABEL: @test_struct_of_arrays_arg
+// CHECK: %struct.struct_of_arrays_arg %arg1.coerce
+__kernel void test_struct_of_arrays_arg(struct_of_arrays_arg_t arg1)
+{
+}
+
+// CHECK-LABEL: @test_struct_of_structs_arg
+// CHECK: %struct.struct_of_structs_arg %arg1.coerce
+__kernel void test_struct_of_structs_arg(struct_of_structs_arg_t arg1)
+{
+}
+
+// CHECK-LABEL: @test_non_kernel_struct_arg
+// CHECK-NOT: %struct.struct_arg %arg1.coerce
+// CHECK: %struct.struct_arg* byval
+void test_non_kernel_struct_arg(struct_arg_t arg1)
+{
+}
diff --git a/test/CodeGenOpenCL/amdgpu-attrs.cl b/test/CodeGenOpenCL/amdgpu-attrs.cl
new file mode 100644
index 000000000000..4ca85d316104
--- /dev/null
+++ b/test/CodeGenOpenCL/amdgpu-attrs.cl
@@ -0,0 +1,166 @@
+// RUN: %clang_cc1 -triple amdgcn-- -target-cpu tahiti -O0 -emit-llvm -o - %s | FileCheck %s
+// 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
+kernel void flat_work_group_size_0_0() {}
+__attribute__((amdgpu_waves_per_eu(0))) // expected-no-diagnostics
+kernel void waves_per_eu_0() {}
+__attribute__((amdgpu_waves_per_eu(0, 0))) // expected-no-diagnostics
+kernel void waves_per_eu_0_0() {}
+__attribute__((amdgpu_num_sgpr(0))) // expected-no-diagnostics
+kernel void num_sgpr0() {}
+__attribute__((amdgpu_num_vgpr(0))) // expected-no-diagnostics
+kernel void num_vgpr0() {}
+
+__attribute__((amdgpu_flat_work_group_size(0, 0), amdgpu_waves_per_eu(0))) // expected-no-diagnostics
+kernel void flat_work_group_size_0_0_waves_per_eu_0() {}
+__attribute__((amdgpu_flat_work_group_size(0, 0), amdgpu_waves_per_eu(0, 0))) // expected-no-diagnostics
+kernel void flat_work_group_size_0_0_waves_per_eu_0_0() {}
+__attribute__((amdgpu_flat_work_group_size(0, 0), amdgpu_num_sgpr(0))) // expected-no-diagnostics
+kernel void flat_work_group_size_0_0_num_sgpr_0() {}
+__attribute__((amdgpu_flat_work_group_size(0, 0), amdgpu_num_vgpr(0))) // expected-no-diagnostics
+kernel void flat_work_group_size_0_0_num_vgpr_0() {}
+__attribute__((amdgpu_waves_per_eu(0), amdgpu_num_sgpr(0))) // expected-no-diagnostics
+kernel void waves_per_eu_0_num_sgpr_0() {}
+__attribute__((amdgpu_waves_per_eu(0), amdgpu_num_vgpr(0))) // expected-no-diagnostics
+kernel void waves_per_eu_0_num_vgpr_0() {}
+__attribute__((amdgpu_waves_per_eu(0, 0), amdgpu_num_sgpr(0))) // expected-no-diagnostics
+kernel void waves_per_eu_0_0_num_sgpr_0() {}
+__attribute__((amdgpu_waves_per_eu(0, 0), amdgpu_num_vgpr(0))) // expected-no-diagnostics
+kernel void waves_per_eu_0_0_num_vgpr_0() {}
+__attribute__((amdgpu_num_sgpr(0), amdgpu_num_vgpr(0))) // expected-no-diagnostics
+kernel void num_sgpr_0_num_vgpr_0() {}
+
+__attribute__((amdgpu_flat_work_group_size(0, 0), amdgpu_waves_per_eu(0), amdgpu_num_sgpr(0))) // expected-no-diagnostics
+kernel void flat_work_group_size_0_0_waves_per_eu_0_num_sgpr_0() {}
+__attribute__((amdgpu_flat_work_group_size(0, 0), amdgpu_waves_per_eu(0), amdgpu_num_vgpr(0))) // expected-no-diagnostics
+kernel void flat_work_group_size_0_0_waves_per_eu_0_num_vgpr_0() {}
+__attribute__((amdgpu_flat_work_group_size(0, 0), amdgpu_waves_per_eu(0, 0), amdgpu_num_sgpr(0))) // expected-no-diagnostics
+kernel void flat_work_group_size_0_0_waves_per_eu_0_0_num_sgpr_0() {}
+__attribute__((amdgpu_flat_work_group_size(0, 0), amdgpu_waves_per_eu(0, 0), amdgpu_num_vgpr(0))) // expected-no-diagnostics
+kernel void flat_work_group_size_0_0_waves_per_eu_0_0_num_vgpr_0() {}
+
+__attribute__((amdgpu_flat_work_group_size(0, 0), amdgpu_waves_per_eu(0), amdgpu_num_sgpr(0), amdgpu_num_vgpr(0))) // expected-no-diagnostics
+kernel void flat_work_group_size_0_0_waves_per_eu_0_num_sgpr_0_num_vgpr_0() {}
+__attribute__((amdgpu_flat_work_group_size(0, 0), amdgpu_waves_per_eu(0, 0), amdgpu_num_sgpr(0), amdgpu_num_vgpr(0))) // expected-no-diagnostics
+kernel void flat_work_group_size_0_0_waves_per_eu_0_0_num_sgpr_0_num_vgpr_0() {}
+
+__attribute__((amdgpu_flat_work_group_size(32, 64))) // expected-no-diagnostics
+kernel void flat_work_group_size_32_64() {
+// CHECK: define amdgpu_kernel void @flat_work_group_size_32_64() [[FLAT_WORK_GROUP_SIZE_32_64:#[0-9]+]]
+}
+__attribute__((amdgpu_waves_per_eu(2))) // expected-no-diagnostics
+kernel void waves_per_eu_2() {
+// CHECK: define amdgpu_kernel void @waves_per_eu_2() [[WAVES_PER_EU_2:#[0-9]+]]
+}
+__attribute__((amdgpu_waves_per_eu(2, 4))) // expected-no-diagnostics
+kernel void waves_per_eu_2_4() {
+// CHECK: define amdgpu_kernel void @waves_per_eu_2_4() [[WAVES_PER_EU_2_4:#[0-9]+]]
+}
+__attribute__((amdgpu_num_sgpr(32))) // expected-no-diagnostics
+kernel void num_sgpr_32() {
+// CHECK: define amdgpu_kernel void @num_sgpr_32() [[NUM_SGPR_32:#[0-9]+]]
+}
+__attribute__((amdgpu_num_vgpr(64))) // expected-no-diagnostics
+kernel void num_vgpr_64() {
+// CHECK: define amdgpu_kernel void @num_vgpr_64() [[NUM_VGPR_64:#[0-9]+]]
+}
+
+__attribute__((amdgpu_flat_work_group_size(32, 64), amdgpu_waves_per_eu(2))) // expected-no-diagnostics
+kernel void flat_work_group_size_32_64_waves_per_eu_2() {
+// CHECK: define amdgpu_kernel void @flat_work_group_size_32_64_waves_per_eu_2() [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2:#[0-9]+]]
+}
+__attribute__((amdgpu_flat_work_group_size(32, 64), amdgpu_waves_per_eu(2, 4))) // expected-no-diagnostics
+kernel void flat_work_group_size_32_64_waves_per_eu_2_4() {
+// CHECK: define amdgpu_kernel void @flat_work_group_size_32_64_waves_per_eu_2_4() [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_4:#[0-9]+]]
+}
+__attribute__((amdgpu_flat_work_group_size(32, 64), amdgpu_num_sgpr(32))) // expected-no-diagnostics
+kernel void flat_work_group_size_32_64_num_sgpr_32() {
+// CHECK: define amdgpu_kernel void @flat_work_group_size_32_64_num_sgpr_32() [[FLAT_WORK_GROUP_SIZE_32_64_NUM_SGPR_32:#[0-9]+]]
+}
+__attribute__((amdgpu_flat_work_group_size(32, 64), amdgpu_num_vgpr(64))) // expected-no-diagnostics
+kernel void flat_work_group_size_32_64_num_vgpr_64() {
+// CHECK: define amdgpu_kernel void @flat_work_group_size_32_64_num_vgpr_64() [[FLAT_WORK_GROUP_SIZE_32_64_NUM_VGPR_64:#[0-9]+]]
+}
+__attribute__((amdgpu_waves_per_eu(2), amdgpu_num_sgpr(32))) // expected-no-diagnostics
+kernel void waves_per_eu_2_num_sgpr_32() {
+// CHECK: define amdgpu_kernel void @waves_per_eu_2_num_sgpr_32() [[WAVES_PER_EU_2_NUM_SGPR_32:#[0-9]+]]
+}
+__attribute__((amdgpu_waves_per_eu(2), amdgpu_num_vgpr(64))) // expected-no-diagnostics
+kernel void waves_per_eu_2_num_vgpr_64() {
+// CHECK: define amdgpu_kernel void @waves_per_eu_2_num_vgpr_64() [[WAVES_PER_EU_2_NUM_VGPR_64:#[0-9]+]]
+}
+__attribute__((amdgpu_waves_per_eu(2, 4), amdgpu_num_sgpr(32))) // expected-no-diagnostics
+kernel void waves_per_eu_2_4_num_sgpr_32() {
+// CHECK: define amdgpu_kernel void @waves_per_eu_2_4_num_sgpr_32() [[WAVES_PER_EU_2_4_NUM_SGPR_32:#[0-9]+]]
+}
+__attribute__((amdgpu_waves_per_eu(2, 4), amdgpu_num_vgpr(64))) // expected-no-diagnostics
+kernel void waves_per_eu_2_4_num_vgpr_64() {
+// CHECK: define amdgpu_kernel void @waves_per_eu_2_4_num_vgpr_64() [[WAVES_PER_EU_2_4_NUM_VGPR_64:#[0-9]+]]
+}
+__attribute__((amdgpu_num_sgpr(32), amdgpu_num_vgpr(64))) // expected-no-diagnostics
+kernel void num_sgpr_32_num_vgpr_64() {
+// CHECK: define amdgpu_kernel void @num_sgpr_32_num_vgpr_64() [[NUM_SGPR_32_NUM_VGPR_64:#[0-9]+]]
+}
+
+__attribute__((amdgpu_flat_work_group_size(32, 64), amdgpu_waves_per_eu(2), amdgpu_num_sgpr(32)))
+kernel void flat_work_group_size_32_64_waves_per_eu_2_num_sgpr_32() {
+// CHECK: define amdgpu_kernel void @flat_work_group_size_32_64_waves_per_eu_2_num_sgpr_32() [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_NUM_SGPR_32:#[0-9]+]]
+}
+__attribute__((amdgpu_flat_work_group_size(32, 64), amdgpu_waves_per_eu(2), amdgpu_num_vgpr(64)))
+kernel void flat_work_group_size_32_64_waves_per_eu_2_num_vgpr_64() {
+// CHECK: define amdgpu_kernel void @flat_work_group_size_32_64_waves_per_eu_2_num_vgpr_64() [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_NUM_VGPR_64:#[0-9]+]]
+}
+__attribute__((amdgpu_flat_work_group_size(32, 64), amdgpu_waves_per_eu(2, 4), amdgpu_num_sgpr(32)))
+kernel void flat_work_group_size_32_64_waves_per_eu_2_4_num_sgpr_32() {
+// CHECK: define amdgpu_kernel void @flat_work_group_size_32_64_waves_per_eu_2_4_num_sgpr_32() [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_4_NUM_SGPR_32:#[0-9]+]]
+}
+__attribute__((amdgpu_flat_work_group_size(32, 64), amdgpu_waves_per_eu(2, 4), amdgpu_num_vgpr(64)))
+kernel void flat_work_group_size_32_64_waves_per_eu_2_4_num_vgpr_64() {
+// CHECK: define amdgpu_kernel void @flat_work_group_size_32_64_waves_per_eu_2_4_num_vgpr_64() [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_4_NUM_VGPR_64:#[0-9]+]]
+}
+
+__attribute__((amdgpu_flat_work_group_size(32, 64), amdgpu_waves_per_eu(2), amdgpu_num_sgpr(32), amdgpu_num_vgpr(64))) // expected-no-diagnostics
+kernel void flat_work_group_size_32_64_waves_per_eu_2_num_sgpr_32_num_vgpr_64() {
+// CHECK: define amdgpu_kernel void @flat_work_group_size_32_64_waves_per_eu_2_num_sgpr_32_num_vgpr_64() [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_NUM_SGPR_32_NUM_VGPR_64:#[0-9]+]]
+}
+__attribute__((amdgpu_flat_work_group_size(32, 64), amdgpu_waves_per_eu(2, 4), amdgpu_num_sgpr(32), amdgpu_num_vgpr(64))) // expected-no-diagnostics
+kernel void flat_work_group_size_32_64_waves_per_eu_2_4_num_sgpr_32_num_vgpr_64() {
+// CHECK: define amdgpu_kernel void @flat_work_group_size_32_64_waves_per_eu_2_4_num_sgpr_32_num_vgpr_64() [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_4_NUM_SGPR_32_NUM_VGPR_64:#[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"
+
+// CHECK-NOT: "amdgpu-flat-work-group-size"="0,0"
+// CHECK-NOT: "amdgpu-waves-per-eu"="0"
+// CHECK-NOT: "amdgpu-waves-per-eu"="0,0"
+// CHECK-NOT: "amdgpu-num-sgpr"="0"
+// CHECK-NOT: "amdgpu-num-vgpr"="0"
+
+// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64]] = { noinline nounwind "amdgpu-flat-work-group-size"="32,64"
+// CHECK-DAG: attributes [[WAVES_PER_EU_2]] = { noinline nounwind "amdgpu-waves-per-eu"="2"
+// CHECK-DAG: attributes [[WAVES_PER_EU_2_4]] = { noinline nounwind "amdgpu-waves-per-eu"="2,4"
+// CHECK-DAG: attributes [[NUM_SGPR_32]] = { noinline nounwind "amdgpu-num-sgpr"="32"
+// CHECK-DAG: attributes [[NUM_VGPR_64]] = { noinline nounwind "amdgpu-num-vgpr"="64"
+
+// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2]] = { noinline nounwind "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]] = { noinline nounwind "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]] = { noinline nounwind "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-sgpr"="32"
+// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_NUM_VGPR_64]] = { noinline nounwind "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-vgpr"="64"
+// CHECK-DAG: attributes [[WAVES_PER_EU_2_NUM_SGPR_32]] = { noinline nounwind "amdgpu-num-sgpr"="32" "amdgpu-waves-per-eu"="2"
+// CHECK-DAG: attributes [[WAVES_PER_EU_2_NUM_VGPR_64]] = { noinline nounwind "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2"
+// CHECK-DAG: attributes [[WAVES_PER_EU_2_4_NUM_SGPR_32]] = { noinline nounwind "amdgpu-num-sgpr"="32" "amdgpu-waves-per-eu"="2,4"
+// CHECK-DAG: attributes [[WAVES_PER_EU_2_4_NUM_VGPR_64]] = { noinline nounwind "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2,4"
+// CHECK-DAG: attributes [[NUM_SGPR_32_NUM_VGPR_64]] = { noinline nounwind "amdgpu-num-sgpr"="32" "amdgpu-num-vgpr"="64"
+
+// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_NUM_SGPR_32]] = { noinline nounwind "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]] = { noinline nounwind "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]] = { noinline nounwind "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]] = { noinline nounwind "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]] = { noinline nounwind "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]] = { noinline nounwind "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-sgpr"="32" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2,4"
diff --git a/test/CodeGenOpenCL/amdgpu-nullptr.cl b/test/CodeGenOpenCL/amdgpu-nullptr.cl
new file mode 100644
index 000000000000..2d36fa90a6ab
--- /dev/null
+++ b/test/CodeGenOpenCL/amdgpu-nullptr.cl
@@ -0,0 +1,534 @@
+// RUN: %clang_cc1 %s -cl-std=CL2.0 -include opencl-c.h -triple amdgcn -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -O0 -cl-std=CL2.0 -include opencl-c.h -triple amdgcn -emit-llvm -o - | FileCheck --check-prefix=NOOPT %s
+
+typedef struct {
+ private char *p1;
+ local char *p2;
+ constant char *p3;
+ global char *p4;
+ generic char *p5;
+} StructTy1;
+
+typedef struct {
+ constant char *p3;
+ global char *p4;
+ generic char *p5;
+} StructTy2;
+
+// LLVM requests global variable with common linkage to be initialized with zeroinitializer, therefore use -fno-common
+// to suppress common linkage for tentative definition.
+
+// Test 0 as initializer.
+
+// CHECK: @private_p = local_unnamed_addr addrspace(1) global i8* addrspacecast (i8 addrspace(4)* null to i8*), 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
+local char *local_p = 0;
+
+// CHECK: @global_p = local_unnamed_addr addrspace(1) global i8 addrspace(1)* null, align 4
+global char *global_p = 0;
+
+// CHECK: @constant_p = local_unnamed_addr addrspace(1) global i8 addrspace(2)* null, align 4
+constant char *constant_p = 0;
+
+// CHECK: @generic_p = local_unnamed_addr addrspace(1) global i8 addrspace(4)* null, align 4
+generic char *generic_p = 0;
+
+// Test NULL as initializer.
+
+// CHECK: @private_p_NULL = local_unnamed_addr addrspace(1) global i8* addrspacecast (i8 addrspace(4)* null to i8*), 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
+local char *local_p_NULL = NULL;
+
+// CHECK: @global_p_NULL = local_unnamed_addr addrspace(1) global i8 addrspace(1)* null, align 4
+global char *global_p_NULL = NULL;
+
+// CHECK: @constant_p_NULL = local_unnamed_addr addrspace(1) global i8 addrspace(2)* null, align 4
+constant char *constant_p_NULL = NULL;
+
+// CHECK: @generic_p_NULL = local_unnamed_addr addrspace(1) global i8 addrspace(4)* null, align 4
+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 4
+generic int *fold_generic = (global int*)(generic float*)(private char*)0;
+
+// CHECK: @fold_priv = local_unnamed_addr addrspace(1) global i16* addrspacecast (i16 addrspace(4)* null to i16*), 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 9 to i8*), align 4
+private char *fold_priv_arith = (private char*)0 + 10;
+
+// CHECK: @fold_int = local_unnamed_addr addrspace(1) global i32 13, align 4
+int fold_int = (int)(private void*)(generic char*)(global int*)0 + 14;
+
+// CHECK: @fold_int2 = local_unnamed_addr addrspace(1) global i32 12, align 4
+int fold_int2 = (int) ((private void*)0 + 13);
+
+// CHECK: @fold_int3 = local_unnamed_addr addrspace(1) global i32 -1, align 4
+int fold_int3 = (int) ((private int*)0);
+
+// CHECK: @fold_int4 = local_unnamed_addr addrspace(1) global i32 7, align 4
+int fold_int4 = (int) &((private int*)0)[2];
+
+// CHECK: @fold_int5 = local_unnamed_addr addrspace(1) global i32 3, align 4
+int fold_int5 = (int) &((private StructTy1*)0)->p2;
+
+// Test static variable initialization.
+
+// NOOPT: @test_static_var.sp1 = internal addrspace(1) global i8* addrspacecast (i8 addrspace(4)* null to i8*), align 4
+// NOOPT: @test_static_var.sp2 = internal addrspace(1) global i8* addrspacecast (i8 addrspace(4)* null to i8*), align 4
+// NOOPT: @test_static_var.sp3 = internal addrspace(1) global i8* addrspacecast (i8 addrspace(4)* null to i8*), align 4
+// NOOPT: @test_static_var.sp4 = internal addrspace(1) global i8* null, align 4
+// NOOPT: @test_static_var.sp5 = internal addrspace(1) global i8* null, align 4
+// NOOPT: @test_static_var.SS1 = internal addrspace(1) global %struct.StructTy1 { i8* addrspacecast (i8 addrspace(4)* null to i8*), 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 4
+// NOOPT: @test_static_var.SS2 = internal addrspace(1) global %struct.StructTy2 zeroinitializer, align 4
+
+void test_static_var(void) {
+ static private char *sp1 = 0;
+ static private char *sp2 = NULL;
+ static private char *sp3;
+ static private char *sp4 = (private char*)((void)0, 0);
+ const int x = 0;
+ static private char *sp5 = (private char*)x;
+ static StructTy1 SS1;
+ static StructTy2 SS2;
+}
+
+// Test function-scope variable initialization.
+// NOOPT-LABEL: test_func_scope_var
+// NOOPT: store i8* addrspacecast (i8 addrspace(4)* null to i8*), i8** %sp1, align 4
+// NOOPT: store i8* addrspacecast (i8 addrspace(4)* null to i8*), 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.SS1 to i8 addrspace(2)*), i64 32, i32 4, i1 false)
+// NOOPT: %[[SS2:.*]] = bitcast %struct.StructTy2* %SS2 to i8*
+// NOOPT: call void @llvm.memset.p0i8.i64(i8* %[[SS2]], i8 0, i64 24, i32 4, i1 false)
+
+void test_func_scope_var(void) {
+ private char *sp1 = 0;
+ private char *sp2 = NULL;
+ private char *sp3 = (private char*)((void)0, 0);
+ const int x = 0;
+ private char *sp4 = (private char*)x;
+ StructTy1 SS1 = {0, 0, 0, 0, 0};
+ StructTy2 SS2 = {0, 0, 0};
+}
+
+// Test default initialization of pointers.
+
+// Tentative definition of global variables with non-zero initializer
+// cannot have common linkage since common linkage requires zero initialization
+// and does not have explicit section.
+
+// CHECK: @p1 = weak local_unnamed_addr addrspace(1) global i8* addrspacecast (i8 addrspace(4)* null to i8*), 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
+local char *p2;
+
+// CHECK: @p3 = common local_unnamed_addr addrspace(1) global i8 addrspace(2)* null, align 4
+constant char *p3;
+
+// CHECK: @p4 = common local_unnamed_addr addrspace(1) global i8 addrspace(1)* null, align 4
+global char *p4;
+
+// CHECK: @p5 = common local_unnamed_addr addrspace(1) global i8 addrspace(4)* null, align 4
+generic char *p5;
+
+// Test default initialization of sturcture.
+
+// CHECK: @S1 = weak local_unnamed_addr addrspace(1) global %struct.StructTy1 { i8* addrspacecast (i8 addrspace(4)* null to i8*), 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 4
+StructTy1 S1;
+
+// CHECK: @S2 = common local_unnamed_addr addrspace(1) global %struct.StructTy2 zeroinitializer, align 4
+StructTy2 S2;
+
+// Test default initialization of array.
+// CHECK: @A1 = weak local_unnamed_addr addrspace(1) global [2 x %struct.StructTy1] [%struct.StructTy1 { i8* addrspacecast (i8 addrspace(4)* null to i8*), 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* addrspacecast (i8 addrspace(4)* null to i8*), 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 4
+StructTy1 A1[2];
+
+// CHECK: @A2 = common local_unnamed_addr addrspace(1) global [2 x %struct.StructTy2] zeroinitializer, align 4
+StructTy2 A2[2];
+
+// Test comparison with 0.
+
+// CHECK-LABEL: cmp_private
+// CHECK: icmp eq i8* %p, addrspacecast (i8 addrspace(4)* null to i8*)
+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)*)
+void cmp_local(local char* p) {
+ if (p != 0)
+ *p = 0;
+}
+
+// CHECK-LABEL: cmp_global
+// CHECK: icmp eq i8 addrspace(1)* %p, null
+void cmp_global(global char* p) {
+ if (p != 0)
+ *p = 0;
+}
+
+// CHECK-LABEL: cmp_constant
+// CHECK: icmp eq i8 addrspace(2)* %p, null
+char cmp_constant(constant char* p) {
+ if (p != 0)
+ return *p;
+ else
+ return 0;
+}
+
+// CHECK-LABEL: cmp_generic
+// CHECK: icmp eq i8 addrspace(4)* %p, null
+void cmp_generic(generic char* p) {
+ if (p != 0)
+ *p = 0;
+}
+
+// Test comparison with NULL.
+
+// CHECK-LABEL: cmp_NULL_private
+// CHECK: icmp eq i8* %p, addrspacecast (i8 addrspace(4)* null to i8*)
+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)*)
+void cmp_NULL_local(local char* p) {
+ if (p != NULL)
+ *p = 0;
+}
+
+// CHECK-LABEL: cmp_NULL_global
+// CHECK: icmp eq i8 addrspace(1)* %p, null
+void cmp_NULL_global(global char* p) {
+ if (p != NULL)
+ *p = 0;
+}
+
+// CHECK-LABEL: cmp_NULL_constant
+// CHECK: icmp eq i8 addrspace(2)* %p, null
+char cmp_NULL_constant(constant char* p) {
+ if (p != NULL)
+ return *p;
+ else
+ return 0;
+}
+
+// CHECK-LABEL: cmp_NULL_generic
+// CHECK: icmp eq i8 addrspace(4)* %p, null
+void cmp_NULL_generic(generic char* p) {
+ if (p != NULL)
+ *p = 0;
+}
+
+// Test storage 0 as null pointer.
+// CHECK-LABEL: test_storage_null_pointer
+// CHECK: store i8* addrspacecast (i8 addrspace(4)* null to i8*), 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
+void test_storage_null_pointer(private char** arg_private,
+ local char** arg_local,
+ global char** arg_global,
+ constant char** arg_constant,
+ generic char** arg_generic) {
+ *arg_private = 0;
+ *arg_local = 0;
+ *arg_global = 0;
+ *arg_constant = 0;
+ *arg_generic = 0;
+}
+
+// Test storage NULL as null pointer.
+// CHECK-LABEL: test_storage_null_pointer_NULL
+// CHECK: store i8* addrspacecast (i8 addrspace(4)* null to i8*), 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
+void test_storage_null_pointer_NULL(private char** arg_private,
+ local char** arg_local,
+ global char** arg_global,
+ constant char** arg_constant,
+ generic char** arg_generic) {
+ *arg_private = NULL;
+ *arg_local = NULL;
+ *arg_global = NULL;
+ *arg_constant = NULL;
+ *arg_generic = NULL;
+}
+
+// Test pass null pointer to function as argument.
+void test_pass_null_pointer_arg_calee(private char* arg_private,
+ local char* arg_local,
+ global char* arg_global,
+ constant char* arg_constant,
+ generic char* arg_generic);
+
+// CHECK-LABEL: test_pass_null_pointer_arg
+// CHECK: call void @test_pass_null_pointer_arg_calee(i8* addrspacecast (i8 addrspace(4)* null to i8*), 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* addrspacecast (i8 addrspace(4)* null to i8*), i8 addrspace(3)* addrspacecast (i8 addrspace(4)* null to i8 addrspace(3)*), i8 addrspace(1)* null, i8 addrspace(2)* null, i8 addrspace(4)* 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);
+}
+
+// Test cast null pointer to size_t.
+void test_cast_null_pointer_to_sizet_calee(size_t arg_private,
+ size_t arg_local,
+ size_t arg_global,
+ size_t arg_constant,
+ size_t arg_generic);
+
+// CHECK-LABEL: test_cast_null_pointer_to_sizet
+// CHECK: call void @test_cast_null_pointer_to_sizet_calee(i64 ptrtoint (i8* addrspacecast (i8 addrspace(4)* null to i8*) to i64), 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 ptrtoint (i8* addrspacecast (i8 addrspace(4)* null to i8*) to i64), i64 ptrtoint (i8 addrspace(3)* addrspacecast (i8 addrspace(4)* 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),
+ (size_t)((global char*)0),
+ (size_t)((constant char*)0),
+ (size_t)((generic char*)0));
+ test_cast_null_pointer_to_sizet_calee((size_t)((private char*)NULL),
+ (size_t)((local char*)NULL),
+ (size_t)((global char*)NULL),
+ (size_t)((constant char*)0), // NULL cannot be casted to constant pointer since it is defined as a generic pointer
+ (size_t)((generic char*)NULL));
+}
+
+// Test comparision 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; }
+#define TEST_EQNN(addr1, addr2) int test_eqNN_##addr1##_##addr2(void) { return (addr1 char*)0 == (addr2 char*)NULL; }
+#define TEST_NE00(addr1, addr2) int test_ne00_##addr1##_##addr2(void) { return (addr1 char*)0 != (addr2 char*)0; }
+#define TEST_NE0N(addr1, addr2) int test_ne0N_##addr1##_##addr2(void) { return (addr1 char*)0 != (addr2 char*)NULL; }
+#define TEST_NEN0(addr1, addr2) int test_neN0_##addr1##_##addr2(void) { return (addr1 char*)NULL != (addr2 char*)0; }
+#define TEST_NENN(addr1, addr2) int test_neNN_##addr1##_##addr2(void) { return (addr1 char*)0 != (addr2 char*)NULL; }
+#define TEST(addr1, addr2) \
+ TEST_EQ00(addr1, addr2) \
+ TEST_EQ0N(addr1, addr2) \
+ TEST_EQN0(addr1, addr2) \
+ TEST_EQNN(addr1, addr2) \
+ TEST_NE00(addr1, addr2) \
+ TEST_NE0N(addr1, addr2) \
+ TEST_NEN0(addr1, addr2) \
+ TEST_NENN(addr1, addr2)
+
+// CHECK-LABEL: test_eq00_generic_private
+// CHECK: ret i32 1
+// CHECK-LABEL: test_eq0N_generic_private
+// CHECK: ret i32 1
+// CHECK-LABEL: test_eqN0_generic_private
+// CHECK: ret i32 1
+// CHECK-LABEL: test_eqNN_generic_private
+// CHECK: ret i32 1
+// CHECK-LABEL: test_ne00_generic_private
+// CHECK: ret i32 0
+// CHECK-LABEL: test_ne0N_generic_private
+// CHECK: ret i32 0
+// CHECK-LABEL: test_neN0_generic_private
+// CHECK: ret i32 0
+// CHECK-LABEL: test_neNN_generic_private
+// CHECK: ret i32 0
+TEST(generic, private)
+
+// CHECK-LABEL: test_eq00_generic_local
+// CHECK: ret i32 1
+// CHECK-LABEL: test_eq0N_generic_local
+// CHECK: ret i32 1
+// CHECK-LABEL: test_eqN0_generic_local
+// CHECK: ret i32 1
+// CHECK-LABEL: test_eqNN_generic_local
+// CHECK: ret i32 1
+// CHECK-LABEL: test_ne00_generic_local
+// CHECK: ret i32 0
+// CHECK-LABEL: test_ne0N_generic_local
+// CHECK: ret i32 0
+// CHECK-LABEL: test_neN0_generic_local
+// CHECK: ret i32 0
+// CHECK-LABEL: test_neNN_generic_local
+// CHECK: ret i32 0
+TEST(generic, local)
+
+// CHECK-LABEL: test_eq00_generic_global
+// CHECK: ret i32 1
+// CHECK-LABEL: test_eq0N_generic_global
+// CHECK: ret i32 1
+// CHECK-LABEL: test_eqN0_generic_global
+// CHECK: ret i32 1
+// CHECK-LABEL: test_eqNN_generic_global
+// CHECK: ret i32 1
+// CHECK-LABEL: test_ne00_generic_global
+// CHECK: ret i32 0
+// CHECK-LABEL: test_ne0N_generic_global
+// CHECK: ret i32 0
+// CHECK-LABEL: test_neN0_generic_global
+// CHECK: ret i32 0
+// CHECK-LABEL: test_neNN_generic_global
+// CHECK: ret i32 0
+TEST(generic, global)
+
+// CHECK-LABEL: test_eq00_generic_generic
+// CHECK: ret i32 1
+// CHECK-LABEL: test_eq0N_generic_generic
+// CHECK: ret i32 1
+// CHECK-LABEL: test_eqN0_generic_generic
+// CHECK: ret i32 1
+// CHECK-LABEL: test_eqNN_generic_generic
+// CHECK: ret i32 1
+// CHECK-LABEL: test_ne00_generic_generic
+// CHECK: ret i32 0
+// CHECK-LABEL: test_ne0N_generic_generic
+// CHECK: ret i32 0
+// CHECK-LABEL: test_neN0_generic_generic
+// CHECK: ret i32 0
+// CHECK-LABEL: test_neNN_generic_generic
+// CHECK: ret i32 0
+TEST(generic, generic)
+
+// CHECK-LABEL: test_eq00_constant_constant
+// CHECK: ret i32 1
+TEST_EQ00(constant, constant)
+
+// Test cast to bool.
+
+// CHECK-LABEL: cast_bool_private
+// CHECK: icmp eq i8* %p, addrspacecast (i8 addrspace(4)* null to i8*)
+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)*)
+void cast_bool_local(local char* p) {
+ if (p)
+ *p = 0;
+}
+
+// CHECK-LABEL: cast_bool_global
+// CHECK: icmp eq i8 addrspace(1)* %p, null
+void cast_bool_global(global char* p) {
+ if (p)
+ *p = 0;
+}
+
+// CHECK-LABEL: cast_bool_constant
+// CHECK: icmp eq i8 addrspace(2)* %p, null
+char cast_bool_constant(constant char* p) {
+ if (p)
+ return *p;
+ else
+ return 0;
+}
+
+// CHECK-LABEL: cast_bool_generic
+// CHECK: icmp eq i8 addrspace(4)* %p, null
+void cast_bool_generic(generic char* p) {
+ if (p)
+ *p = 0;
+}
+
+// Test initialize a struct using memset.
+// For large structures which is mostly zero, clang generats llvm.memset for
+// the zero part and store for non-zero members.
+typedef struct {
+ long a, b, c, d;
+ private char *p;
+} StructTy3;
+
+// CHECK-LABEL: test_memset
+// CHECK: call void @llvm.memset.p0i8.i64(i8* {{.*}}, i8 0, i64 32, i32 8, i1 false)
+// CHECK: store i8* addrspacecast (i8 addrspace(4)* null to i8*), i8** {{.*}}
+StructTy3 test_memset(void) {
+ StructTy3 S3 = {0, 0, 0, 0, 0};
+ return S3;
+}
+
+// Test casting literal 0 to pointer.
+// A 0 literal casted to pointer should become a null pointer.
+
+// CHECK-LABEL: test_cast_0_to_ptr
+// CHECK: ret i32* addrspacecast (i32 addrspace(4)* null to i32*)
+private int* test_cast_0_to_ptr(void) {
+ return (private int*)0;
+}
+
+// Test casting non-literal integer with 0 value to pointer.
+// A non-literal integer expression with 0 value is casted to a pointer with
+// zero value.
+
+// CHECK-LABEL: test_cast_int_to_ptr1
+// CHECK: ret i32* null
+private int* test_cast_int_to_ptr1(void) {
+ return (private int*)((void)0, 0);
+}
+
+// CHECK-LABEL: test_cast_int_to_ptr2
+// CHECK: ret i32* null
+private int* test_cast_int_to_ptr2(void) {
+ int x = 0;
+ return (private int*)x;
+}
+
+// Test logical operations.
+// CHECK-LABEL: test_not_nullptr
+// CHECK: ret i32 1
+int test_not_nullptr(void) {
+ return !(private char*)NULL;
+}
+
+// CHECK-LABEL: test_and_nullptr
+// CHECK: ret i32 0
+int test_and_nullptr(int a) {
+ return a && ((private char*)NULL);
+}
+
+// CHECK-LABEL: test_not_ptr
+// CHECK: %[[lnot:.*]] = icmp eq i8* %p, addrspacecast (i8 addrspace(4)* null to i8*)
+// CHECK: %[[lnot_ext:.*]] = zext i1 %[[lnot]] to i32
+// CHECK: ret i32 %[[lnot_ext]]
+int test_not_ptr(private char* p) {
+ return !p;
+}
+// CHECK-LABEL: test_and_ptr
+// CHECK: %[[tobool:.*]] = icmp ne i8* %p1, addrspacecast (i8 addrspace(4)* null to i8*)
+// CHECK: %[[tobool1:.*]] = icmp ne i8 addrspace(3)* %p2, addrspacecast (i8 addrspace(4)* null to i8 addrspace(3)*)
+// CHECK: %[[res:.*]] = and i1 %[[tobool]], %[[tobool1]]
+// CHECK: %[[land_ext:.*]] = zext i1 %[[res]] to i32
+// CHECK: ret i32 %[[land_ext]]
+int test_and_ptr(private char* p1, local char* p2) {
+ return p1 && p2;
+}
+
+// Test folding of null pointer in function scope.
+// NOOPT-LABEL: test_fold
+// NOOPT: call void @test_fold_callee
+// NOOPT: store i32 addrspace(1)* null, i32 addrspace(1)** %glob, align 4
+// NOOPT: %{{.*}} = sub i64 %{{.*}}, 0
+// NOOPT: call void @test_fold_callee
+// NOOPT: %{{.*}} = add nsw i64 %{{.*}}, sext (i32 ptrtoint (i32* addrspacecast (i32 addrspace(4)* null to i32*) to i32) to i64)
+// NOOPT: %{{.*}} = sub nsw i64 %{{.*}}, 1
+void test_fold_callee(void);
+void test_fold(void) {
+ global int* glob = (test_fold_callee(), (global int*)(generic char*)0);
+ long x = glob - (global int*)(generic char*)0;
+ x = x + (int)(test_fold_callee(), (private int*)(generic char*)(global short*)0);
+ x = x - (int)((private int*)0 == (private int*)(generic char*)0);
+}
diff --git a/test/CodeGenOpenCL/amdgpu-num-gpr-attr.cl b/test/CodeGenOpenCL/amdgpu-num-gpr-attr.cl
deleted file mode 100644
index 589d00d1eaa4..000000000000
--- a/test/CodeGenOpenCL/amdgpu-num-gpr-attr.cl
+++ /dev/null
@@ -1,48 +0,0 @@
-// RUN: %clang_cc1 -triple amdgcn-- -target-cpu tahiti -O0 -emit-llvm -o - %s | FileCheck %s
-// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O0 -emit-llvm -verify -o - %s | FileCheck -check-prefix=X86 %s
-
-// Make sure this is silently accepted on other targets.
-
-__attribute__((amdgpu_num_vgpr(64))) // expected-no-diagnostics
-kernel void test_num_vgpr64() {
-// CHECK: define amdgpu_kernel void @test_num_vgpr64() [[ATTR_VGPR64:#[0-9]+]]
-}
-
-__attribute__((amdgpu_num_sgpr(32))) // expected-no-diagnostics
-kernel void test_num_sgpr32() {
-// CHECK: define amdgpu_kernel void @test_num_sgpr32() [[ATTR_SGPR32:#[0-9]+]]
-}
-
-__attribute__((amdgpu_num_vgpr(64), amdgpu_num_sgpr(32))) // expected-no-diagnostics
-kernel void test_num_vgpr64_sgpr32() {
-// CHECK: define amdgpu_kernel void @test_num_vgpr64_sgpr32() [[ATTR_VGPR64_SGPR32:#[0-9]+]]
-
-}
-
-__attribute__((amdgpu_num_sgpr(20), amdgpu_num_vgpr(40))) // expected-no-diagnostics
-kernel void test_num_sgpr20_vgpr40() {
-// CHECK: define amdgpu_kernel void @test_num_sgpr20_vgpr40() [[ATTR_SGPR20_VGPR40:#[0-9]+]]
-}
-
-__attribute__((amdgpu_num_vgpr(0))) // expected-no-diagnostics
-kernel void test_num_vgpr0() {
-}
-
-__attribute__((amdgpu_num_sgpr(0))) // expected-no-diagnostics
-kernel void test_num_sgpr0() {
-}
-
-__attribute__((amdgpu_num_vgpr(0), amdgpu_num_sgpr(0))) // expected-no-diagnostics
-kernel void test_num_vgpr0_sgpr0() {
-}
-
-
-// X86-NOT: "amdgpu_num_vgpr"
-// X86-NOT: "amdgpu_num_sgpr"
-
-// CHECK-NOT: "amdgpu_num_vgpr"="0"
-// CHECK-NOT: "amdgpu_num_sgpr"="0"
-// CHECK-DAG: attributes [[ATTR_VGPR64]] = { nounwind "amdgpu_num_vgpr"="64"
-// CHECK-DAG: attributes [[ATTR_SGPR32]] = { nounwind "amdgpu_num_sgpr"="32"
-// CHECK-DAG: attributes [[ATTR_VGPR64_SGPR32]] = { nounwind "amdgpu_num_sgpr"="32" "amdgpu_num_vgpr"="64"
-// CHECK-DAG: attributes [[ATTR_SGPR20_VGPR40]] = { nounwind "amdgpu_num_sgpr"="20" "amdgpu_num_vgpr"="40"
diff --git a/test/CodeGenOpenCL/as_type.cl b/test/CodeGenOpenCL/as_type.cl
index 7fc3b02bdc75..51e82e3fef8e 100644
--- a/test/CodeGenOpenCL/as_type.cl
+++ b/test/CodeGenOpenCL/as_type.cl
@@ -51,7 +51,7 @@ int f6(char4 x) {
return __builtin_astype(x, int);
}
-//CHECK: define spir_func <3 x i8> @f7(<3 x i8> %[[x:.*]])
+//CHECK: define spir_func <3 x i8> @f7(<3 x i8> returned %[[x:.*]])
//CHECK-NOT: bitcast
//CHECK-NOT: shufflevector
//CHECK: ret <3 x i8> %[[x]]
@@ -66,3 +66,42 @@ char3 f7(char3 x) {
int3 f8(char16 x) {
return __builtin_astype(x, int3);
}
+
+//CHECK: define spir_func i32 addrspace(1)* @addr_cast(i32* readnone %[[x:.*]])
+//CHECK: %[[cast:.*]] = addrspacecast i32* %[[x]] to i32 addrspace(1)*
+//CHECK: ret i32 addrspace(1)* %[[cast]]
+global int* addr_cast(int *x) {
+ return __builtin_astype(x, global int*);
+}
+
+//CHECK: define spir_func i32 addrspace(1)* @int_to_ptr(i32 %[[x:.*]])
+//CHECK: %[[cast:.*]] = inttoptr i32 %[[x]] to i32 addrspace(1)*
+//CHECK: ret i32 addrspace(1)* %[[cast]]
+global int* int_to_ptr(int x) {
+ return __builtin_astype(x, global int*);
+}
+
+//CHECK: define spir_func i32 @ptr_to_int(i32* %[[x:.*]])
+//CHECK: %[[cast:.*]] = ptrtoint i32* %[[x]] to i32
+//CHECK: ret i32 %[[cast]]
+int ptr_to_int(int *x) {
+ return __builtin_astype(x, int);
+}
+
+//CHECK: define spir_func <3 x i8> @ptr_to_char3(i32* %[[x:.*]])
+//CHECK: %[[cast1:.*]] = ptrtoint i32* %[[x]] to i32
+//CHECK: %[[cast2:.*]] = bitcast i32 %[[cast1]] to <4 x i8>
+//CHECK: %[[astype:.*]] = shufflevector <4 x i8> %[[cast2]], <4 x i8> undef, <3 x i32> <i32 0, i32 1, i32 2>
+//CHECK: ret <3 x i8> %[[astype]]
+char3 ptr_to_char3(int *x) {
+ return __builtin_astype(x, char3);
+}
+
+//CHECK: define spir_func i32* @char3_to_ptr(<3 x i8> %[[x:.*]])
+//CHECK: %[[astype:.*]] = shufflevector <3 x i8> %[[x]], <3 x i8> undef, <4 x i32> <i32 0, i32 1, i32 2, i32 undef>
+//CHECK: %[[cast1:.*]] = bitcast <4 x i8> %[[astype]] to i32
+//CHECK: %[[cast2:.*]] = inttoptr i32 %[[cast1]] to i32*
+//CHECK: ret i32* %[[cast2]]
+int* char3_to_ptr(char3 x) {
+ return __builtin_astype(x, int*);
+}
diff --git a/test/CodeGenOpenCL/builtins-amdgcn-error.cl b/test/CodeGenOpenCL/builtins-amdgcn-error.cl
deleted file mode 100644
index 89c3e490ecdd..000000000000
--- a/test/CodeGenOpenCL/builtins-amdgcn-error.cl
+++ /dev/null
@@ -1,18 +0,0 @@
-// REQUIRES: amdgpu-registered-target
-// RUN: %clang_cc1 -triple amdgcn-unknown-amdhsa -target-cpu tahiti -verify -S -o - %s
-
-// FIXME: We only get one error if the functions are the other order in the
-// file.
-
-typedef unsigned long ulong;
-
-ulong test_s_memrealtime()
-{
- return __builtin_amdgcn_s_memrealtime(); // expected-error {{'__builtin_amdgcn_s_memrealtime' needs target feature s-memrealtime}}
-}
-
-void test_s_sleep(int x)
-{
- __builtin_amdgcn_s_sleep(x); // expected-error {{argument to '__builtin_amdgcn_s_sleep' must be a constant integer}}
-}
-
diff --git a/test/CodeGenOpenCL/builtins-amdgcn-vi.cl b/test/CodeGenOpenCL/builtins-amdgcn-vi.cl
index cda87a8e1ed1..0c88fdfb724d 100644
--- a/test/CodeGenOpenCL/builtins-amdgcn-vi.cl
+++ b/test/CodeGenOpenCL/builtins-amdgcn-vi.cl
@@ -1,8 +1,79 @@
// REQUIRES: amdgpu-registered-target
// RUN: %clang_cc1 -triple amdgcn-unknown-unknown -target-cpu tonga -S -emit-llvm -o - %s | FileCheck %s
+#pragma OPENCL EXTENSION cl_khr_fp16 : enable
+
typedef unsigned long ulong;
+// CHECK-LABEL: @test_div_fixup_f16
+// CHECK: call half @llvm.amdgcn.div.fixup.f16
+void test_div_fixup_f16(global half* out, half a, half b, half c)
+{
+ *out = __builtin_amdgcn_div_fixuph(a, b, c);
+}
+
+// CHECK-LABEL: @test_rcp_f16
+// CHECK: call half @llvm.amdgcn.rcp.f16
+void test_rcp_f16(global half* out, half a)
+{
+ *out = __builtin_amdgcn_rcph(a);
+}
+
+// CHECK-LABEL: @test_rsq_f16
+// CHECK: call half @llvm.amdgcn.rsq.f16
+void test_rsq_f16(global half* out, half a)
+{
+ *out = __builtin_amdgcn_rsqh(a);
+}
+
+// CHECK-LABEL: @test_sin_f16
+// CHECK: call half @llvm.amdgcn.sin.f16
+void test_sin_f16(global half* out, half a)
+{
+ *out = __builtin_amdgcn_sinh(a);
+}
+
+// CHECK-LABEL: @test_cos_f16
+// CHECK: call half @llvm.amdgcn.cos.f16
+void test_cos_f16(global half* out, half a)
+{
+ *out = __builtin_amdgcn_cosh(a);
+}
+
+// CHECK-LABEL: @test_ldexp_f16
+// CHECK: call half @llvm.amdgcn.ldexp.f16
+void test_ldexp_f16(global half* out, half a, int b)
+{
+ *out = __builtin_amdgcn_ldexph(a, b);
+}
+
+// CHECK-LABEL: @test_frexp_mant_f16
+// CHECK: call half @llvm.amdgcn.frexp.mant.f16
+void test_frexp_mant_f16(global half* out, half a)
+{
+ *out = __builtin_amdgcn_frexp_manth(a);
+}
+
+// CHECK-LABEL: @test_frexp_exp_f16
+// CHECK: call i16 @llvm.amdgcn.frexp.exp.i16.f16
+void test_frexp_exp_f16(global short* out, half a)
+{
+ *out = __builtin_amdgcn_frexp_exph(a);
+}
+
+// CHECK-LABEL: @test_fract_f16
+// CHECK: call half @llvm.amdgcn.fract.f16
+void test_fract_f16(global half* out, half a)
+{
+ *out = __builtin_amdgcn_fracth(a);
+}
+
+// CHECK-LABEL: @test_class_f16
+// CHECK: call i1 @llvm.amdgcn.class.f16
+void test_class_f16(global half* out, half a, int b)
+{
+ *out = __builtin_amdgcn_classh(a, b);
+}
// CHECK-LABEL: @test_s_memrealtime
// CHECK: call i64 @llvm.amdgcn.s.memrealtime()
diff --git a/test/CodeGenOpenCL/builtins-amdgcn.cl b/test/CodeGenOpenCL/builtins-amdgcn.cl
index 6cac2a44bc79..ce566b6e876a 100644
--- a/test/CodeGenOpenCL/builtins-amdgcn.cl
+++ b/test/CodeGenOpenCL/builtins-amdgcn.cl
@@ -4,6 +4,7 @@
#pragma OPENCL EXTENSION cl_khr_fp64 : enable
typedef unsigned long ulong;
+typedef unsigned int uint;
// CHECK-LABEL: @test_div_scale_f64
// CHECK: call { double, i1 } @llvm.amdgcn.div.scale.f64(double %a, double %b, i1 true)
@@ -165,14 +166,14 @@ void test_frexp_mant_f64(global double* out, double a)
}
// CHECK-LABEL: @test_frexp_exp_f32
-// CHECK: call i32 @llvm.amdgcn.frexp.exp.f32
+// CHECK: call i32 @llvm.amdgcn.frexp.exp.i32.f32
void test_frexp_exp_f32(global int* out, float a)
{
*out = __builtin_amdgcn_frexp_expf(a);
}
// CHECK-LABEL: @test_frexp_exp_f64
-// CHECK: call i32 @llvm.amdgcn.frexp.exp.f64
+// CHECK: call i32 @llvm.amdgcn.frexp.exp.i32.f64
void test_frexp_exp_f64(global int* out, double a)
{
*out = __builtin_amdgcn_frexp_exp(a);
@@ -199,6 +200,55 @@ void test_lerp(global int* out, int a, int b, int c)
*out = __builtin_amdgcn_lerp(a, b, c);
}
+// CHECK-LABEL: @test_sicmp_i32
+// CHECK: call i64 @llvm.amdgcn.icmp.i32(i32 %a, i32 %b, i32 32)
+void test_sicmp_i32(global ulong* out, int a, int b)
+{
+ *out = __builtin_amdgcn_sicmp(a, b, 32);
+}
+
+// CHECK-LABEL: @test_uicmp_i32
+// CHECK: call i64 @llvm.amdgcn.icmp.i32(i32 %a, i32 %b, i32 32)
+void test_uicmp_i32(global ulong* out, uint a, uint b)
+{
+ *out = __builtin_amdgcn_uicmp(a, b, 32);
+}
+
+// CHECK-LABEL: @test_sicmp_i64
+// CHECK: call i64 @llvm.amdgcn.icmp.i64(i64 %a, i64 %b, i32 38)
+void test_sicmp_i64(global ulong* out, long a, long b)
+{
+ *out = __builtin_amdgcn_sicmpl(a, b, 39-1);
+}
+
+// CHECK-LABEL: @test_uicmp_i64
+// CHECK: call i64 @llvm.amdgcn.icmp.i64(i64 %a, i64 %b, i32 35)
+void test_uicmp_i64(global ulong* out, ulong a, ulong b)
+{
+ *out = __builtin_amdgcn_uicmpl(a, b, 30+5);
+}
+
+// CHECK-LABEL: @test_ds_swizzle
+// CHECK: call i32 @llvm.amdgcn.ds.swizzle(i32 %a, i32 32)
+void test_ds_swizzle(global int* out, int a)
+{
+ *out = __builtin_amdgcn_ds_swizzle(a, 32);
+}
+
+// CHECK-LABEL: @test_fcmp_f32
+// CHECK: call i64 @llvm.amdgcn.fcmp.f32(float %a, float %b, i32 5)
+void test_fcmp_f32(global ulong* out, float a, float b)
+{
+ *out = __builtin_amdgcn_fcmpf(a, b, 5);
+}
+
+// CHECK-LABEL: @test_fcmp_f64
+// CHECK: call i64 @llvm.amdgcn.fcmp.f64(double %a, double %b, i32 6)
+void test_fcmp_f64(global ulong* out, double a, double b)
+{
+ *out = __builtin_amdgcn_fcmp(a, b, 3+3);
+}
+
// CHECK-LABEL: @test_class_f32
// CHECK: call i1 @llvm.amdgcn.class.f32
void test_class_f32(global float* out, float a, int b)
@@ -220,6 +270,13 @@ void test_s_barrier()
__builtin_amdgcn_s_barrier();
}
+// CHECK-LABEL: @test_wave_barrier
+// CHECK: call void @llvm.amdgcn.wave.barrier(
+void test_wave_barrier()
+{
+ __builtin_amdgcn_wave_barrier();
+}
+
// CHECK-LABEL: @test_s_memtime
// CHECK: call i64 @llvm.amdgcn.s.memtime()
void test_s_memtime(global ulong* out)
@@ -236,6 +293,24 @@ void test_s_sleep()
__builtin_amdgcn_s_sleep(15);
}
+// CHECK-LABEL: @test_s_incperflevel
+// CHECK: call void @llvm.amdgcn.s.incperflevel(i32 1)
+// CHECK: call void @llvm.amdgcn.s.incperflevel(i32 15)
+void test_s_incperflevel()
+{
+ __builtin_amdgcn_s_incperflevel(1);
+ __builtin_amdgcn_s_incperflevel(15);
+}
+
+// CHECK-LABEL: @test_s_decperflevel
+// CHECK: call void @llvm.amdgcn.s.decperflevel(i32 1)
+// CHECK: call void @llvm.amdgcn.s.decperflevel(i32 15)
+void test_s_decperflevel()
+{
+ __builtin_amdgcn_s_decperflevel(1);
+ __builtin_amdgcn_s_decperflevel(15);
+}
+
// CHECK-LABEL: @test_cubeid(
// CHECK: call float @llvm.amdgcn.cubeid(float %a, float %b, float %c)
void test_cubeid(global float* out, float a, float b, float c) {
diff --git a/test/CodeGenOpenCL/cast_image.cl b/test/CodeGenOpenCL/cast_image.cl
new file mode 100644
index 000000000000..479404a91371
--- /dev/null
+++ b/test/CodeGenOpenCL/cast_image.cl
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -emit-llvm -o - -triple amdgcn--amdhsa %s | FileCheck --check-prefix=AMDGCN %s
+// RUN: %clang_cc1 -emit-llvm -o - -triple spir-unknown-unknown %s | FileCheck --check-prefix=SPIR %s
+
+#ifdef __AMDGCN__
+
+constant int* convert(image2d_t img) {
+ // AMDGCN: bitcast %opencl.image2d_ro_t addrspace(2)* %img to i32 addrspace(2)*
+ return __builtin_astype(img, constant int*);
+}
+
+#else
+
+global int* convert(image2d_t img) {
+ // SPIR: bitcast %opencl.image2d_ro_t addrspace(1)* %img to i32 addrspace(1)*
+ return __builtin_astype(img, global int*);
+}
+
+#endif
diff --git a/test/CodeGenOpenCL/cl20-device-side-enqueue.cl b/test/CodeGenOpenCL/cl20-device-side-enqueue.cl
index 783ce0254a1a..add13b9e3fc4 100644
--- a/test/CodeGenOpenCL/cl20-device-side-enqueue.cl
+++ b/test/CodeGenOpenCL/cl20-device-side-enqueue.cl
@@ -1,110 +1,147 @@
-// RUN: %clang_cc1 %s -cl-std=CL2.0 -ffake-address-space-map -O0 -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -cl-std=CL2.0 -ffake-address-space-map -O0 -emit-llvm -o - -triple "spir-unknown-unknown" | FileCheck %s --check-prefix=COMMON --check-prefix=B32
+// RUN: %clang_cc1 %s -cl-std=CL2.0 -ffake-address-space-map -O0 -emit-llvm -o - -triple "spir64-unknown-unknown" | FileCheck %s --check-prefix=COMMON --check-prefix=B64
typedef void (^bl_t)(local void *);
+// N.B. The check here only exists to set BL_GLOBAL
+// COMMON: @block_G = {{.*}}bitcast ([[BL_GLOBAL:[^@]+@__block_literal_global(\.[0-9]+)?]]
const bl_t block_G = (bl_t) ^ (local void *a) {};
kernel void device_side_enqueue(global int *a, global int *b, int i) {
- // CHECK: %default_queue = alloca %opencl.queue_t*
+ // COMMON: %default_queue = alloca %opencl.queue_t*
queue_t default_queue;
- // CHECK: %flags = alloca i32
+ // COMMON: %flags = alloca i32
unsigned flags = 0;
- // CHECK: %ndrange = alloca %opencl.ndrange_t*
+ // COMMON: %ndrange = alloca %opencl.ndrange_t*
ndrange_t ndrange;
- // CHECK: %clk_event = alloca %opencl.clk_event_t*
+ // COMMON: %clk_event = alloca %opencl.clk_event_t*
clk_event_t clk_event;
- // CHECK: %event_wait_list = alloca %opencl.clk_event_t*
+ // COMMON: %event_wait_list = alloca %opencl.clk_event_t*
clk_event_t event_wait_list;
- // CHECK: %event_wait_list2 = alloca [1 x %opencl.clk_event_t*]
+ // COMMON: %event_wait_list2 = alloca [1 x %opencl.clk_event_t*]
clk_event_t event_wait_list2[] = {clk_event};
- // CHECK: [[DEF_Q:%[0-9]+]] = load %opencl.queue_t*, %opencl.queue_t** %default_queue
- // CHECK: [[FLAGS:%[0-9]+]] = load i32, i32* %flags
- // CHECK: [[NDR:%[0-9]+]] = load %opencl.ndrange_t*, %opencl.ndrange_t** %ndrange
- // CHECK: [[BL:%[0-9]+]] = bitcast <{ i8*, i32, i32, i8*, %struct.__block_descriptor addrspace(3)*, i32{{.*}}, i32{{.*}}, i32{{.*}} }>* %block to void ()*
- // CHECK: [[BL_I8:%[0-9]+]] = bitcast void ()* [[BL]] to i8*
- // CHECK: call i32 @__enqueue_kernel_basic(%opencl.queue_t* [[DEF_Q]], i32 [[FLAGS]], %opencl.ndrange_t* [[NDR]], i8* [[BL_I8]])
+ // COMMON: [[DEF_Q:%[0-9]+]] = load %opencl.queue_t{{.*}}*, %opencl.queue_t{{.*}}** %default_queue
+ // COMMON: [[FLAGS:%[0-9]+]] = load i32, i32* %flags
+ // COMMON: [[NDR:%[0-9]+]] = load %opencl.ndrange_t*, %opencl.ndrange_t** %ndrange
+ // COMMON: [[BL:%[0-9]+]] = bitcast <{ i8*, i32, i32, i8*, %struct.__block_descriptor addrspace(2)*, i32{{.*}}, i32{{.*}}, i32{{.*}} }>* %block to void ()*
+ // COMMON: [[BL_I8:%[0-9]+]] = bitcast void ()* [[BL]] to i8*
+ // COMMON: call i32 @__enqueue_kernel_basic(%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %opencl.ndrange_t* [[NDR]], i8* [[BL_I8]])
enqueue_kernel(default_queue, flags, ndrange,
^(void) {
a[i] = b[i];
});
- // CHECK: [[DEF_Q:%[0-9]+]] = load %opencl.queue_t*, %opencl.queue_t** %default_queue
- // CHECK: [[FLAGS:%[0-9]+]] = load i32, i32* %flags
- // CHECK: [[NDR:%[0-9]+]] = load %opencl.ndrange_t*, %opencl.ndrange_t** %ndrange
- // CHECK: [[BL:%[0-9]+]] = bitcast <{ i8*, i32, i32, i8*, %struct.__block_descriptor addrspace(3)*, i32{{.*}}, i32{{.*}}, i32{{.*}} }>* %block3 to void ()*
- // CHECK: [[BL_I8:%[0-9]+]] = bitcast void ()* [[BL]] to i8*
- // CHECK: call i32 @__enqueue_kernel_basic_events(%opencl.queue_t* [[DEF_Q]], i32 [[FLAGS]], %opencl.ndrange_t* [[NDR]], i32 2, %opencl.clk_event_t** %event_wait_list, %opencl.clk_event_t** %clk_event, i8* [[BL_I8]])
+ // COMMON: [[DEF_Q:%[0-9]+]] = load %opencl.queue_t{{.*}}*, %opencl.queue_t{{.*}}** %default_queue
+ // COMMON: [[FLAGS:%[0-9]+]] = load i32, i32* %flags
+ // COMMON: [[NDR:%[0-9]+]] = load %opencl.ndrange_t*, %opencl.ndrange_t** %ndrange
+ // 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: [[BL:%[0-9]+]] = bitcast <{ i8*, i32, i32, i8*, %struct.__block_descriptor addrspace(2)*, i32{{.*}}, i32{{.*}}, i32{{.*}} }>* %block3 to void ()*
+ // COMMON: [[BL_I8:%[0-9]+]] = bitcast void ()* [[BL]] to i8*
+ // COMMON: call i32 @__enqueue_kernel_basic_events(%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %opencl.ndrange_t* {{.*}}, i32 2, %opencl.clk_event_t{{.*}}* addrspace(4)* [[WAIT_EVNT]], %opencl.clk_event_t{{.*}}* addrspace(4)* [[EVNT]], i8* [[BL_I8]])
enqueue_kernel(default_queue, flags, ndrange, 2, &event_wait_list, &clk_event,
^(void) {
a[i] = b[i];
});
- // CHECK: [[DEF_Q:%[0-9]+]] = load %opencl.queue_t*, %opencl.queue_t** %default_queue
- // CHECK: [[FLAGS:%[0-9]+]] = load i32, i32* %flags
- // CHECK: [[NDR:%[0-9]+]] = load %opencl.ndrange_t*, %opencl.ndrange_t** %ndrange
- // CHECK: call i32 (%opencl.queue_t*, i32, %opencl.ndrange_t*, i8*, i32, ...) @__enqueue_kernel_vaargs(%opencl.queue_t* [[DEF_Q]], i32 [[FLAGS]], %opencl.ndrange_t* [[NDR]], i8* bitcast ({ i8**, i32, i32, i8*, %struct.__block_descriptor addrspace(3)* }* @__block_literal_global{{(.[0-9]+)?}} to i8*), i32 1, i32 256)
+ // COMMON: [[DEF_Q:%[0-9]+]] = load %opencl.queue_t{{.*}}*, %opencl.queue_t{{.*}}** %default_queue
+ // COMMON: [[FLAGS:%[0-9]+]] = load i32, i32* %flags
+ // COMMON: [[NDR:%[0-9]+]] = load %opencl.ndrange_t*, %opencl.ndrange_t** %ndrange
+ // B32: call i32 (%opencl.queue_t{{.*}}*, i32, %opencl.ndrange_t*, i8*, i32, ...) @__enqueue_kernel_vaargs(%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %opencl.ndrange_t* [[NDR]], i8* bitcast ({ i8**, i32, i32, i8*, %struct.__block_descriptor addrspace(2)* }* @__block_literal_global{{(.[0-9]+)?}} to i8*), i32 1, i32 256)
+ // B64: call i32 (%opencl.queue_t{{.*}}*, i32, %opencl.ndrange_t*, i8*, i32, ...) @__enqueue_kernel_vaargs(%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %opencl.ndrange_t* [[NDR]], i8* bitcast ({ i8**, i32, i32, i8*, %struct.__block_descriptor addrspace(2)* }* @__block_literal_global{{(.[0-9]+)?}} to i8*), i32 1, i64 256)
enqueue_kernel(default_queue, flags, ndrange,
^(local void *p) {
return;
},
256);
char c;
- // CHECK: [[DEF_Q:%[0-9]+]] = load %opencl.queue_t*, %opencl.queue_t** %default_queue
- // CHECK: [[FLAGS:%[0-9]+]] = load i32, i32* %flags
- // CHECK: [[NDR:%[0-9]+]] = load %opencl.ndrange_t*, %opencl.ndrange_t** %ndrange
- // CHECK: [[SIZE:%[0-9]+]] = zext i8 {{%[0-9]+}} to i32
- // CHECK: call i32 (%opencl.queue_t*, i32, %opencl.ndrange_t*, i8*, i32, ...) @__enqueue_kernel_vaargs(%opencl.queue_t* [[DEF_Q]], i32 [[FLAGS]], %opencl.ndrange_t* [[NDR]], i8* bitcast ({ i8**, i32, i32, i8*, %struct.__block_descriptor addrspace(3)* }* @__block_literal_global{{(.[0-9]+)?}} to i8*), i32 1, i32 [[SIZE]])
+ // COMMON: [[DEF_Q:%[0-9]+]] = load %opencl.queue_t{{.*}}*, %opencl.queue_t{{.*}}** %default_queue
+ // COMMON: [[FLAGS:%[0-9]+]] = load i32, i32* %flags
+ // COMMON: [[NDR:%[0-9]+]] = load %opencl.ndrange_t*, %opencl.ndrange_t** %ndrange
+ // B32: [[SIZE:%[0-9]+]] = zext i8 {{%[0-9]+}} to i32
+ // B32: call i32 (%opencl.queue_t{{.*}}*, i32, %opencl.ndrange_t*, i8*, i32, ...) @__enqueue_kernel_vaargs(%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %opencl.ndrange_t* [[NDR]], i8* bitcast ({ i8**, i32, i32, i8*, %struct.__block_descriptor addrspace(2)* }* @__block_literal_global{{(.[0-9]+)?}} to i8*), i32 1, i32 [[SIZE]])
+ // B64: [[SIZE:%[0-9]+]] = zext i8 {{%[0-9]+}} to i64
+ // B64: call i32 (%opencl.queue_t{{.*}}*, i32, %opencl.ndrange_t*, i8*, i32, ...) @__enqueue_kernel_vaargs(%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %opencl.ndrange_t* [[NDR]], i8* bitcast ({ i8**, i32, i32, i8*, %struct.__block_descriptor addrspace(2)* }* @__block_literal_global{{(.[0-9]+)?}} to i8*), i32 1, i64 [[SIZE]])
enqueue_kernel(default_queue, flags, ndrange,
^(local void *p) {
return;
},
c);
- // CHECK: [[DEF_Q:%[0-9]+]] = load %opencl.queue_t*, %opencl.queue_t** %default_queue
- // CHECK: [[FLAGS:%[0-9]+]] = load i32, i32* %flags
- // CHECK: [[NDR:%[0-9]+]] = load %opencl.ndrange_t*, %opencl.ndrange_t** %ndrange
- // CHECK: [[AD:%arraydecay[0-9]*]] = getelementptr inbounds [1 x %opencl.clk_event_t*], [1 x %opencl.clk_event_t*]* %event_wait_list2, i32 0, i32 0
- // CHECK: call i32 (%opencl.queue_t*, i32, %opencl.ndrange_t*, i32, %opencl.clk_event_t**, %opencl.clk_event_t**, i8*, i32, ...) @__enqueue_kernel_events_vaargs(%opencl.queue_t* [[DEF_Q]], i32 [[FLAGS]], %opencl.ndrange_t* [[NDR]], i32 2, %opencl.clk_event_t** [[AD]], %opencl.clk_event_t** %clk_event, i8* bitcast ({ i8**, i32, i32, i8*, %struct.__block_descriptor addrspace(3)* }* @__block_literal_global{{(.[0-9]+)?}} to i8*), i32 1, i32 256)
+ // COMMON: [[DEF_Q:%[0-9]+]] = load %opencl.queue_t{{.*}}*, %opencl.queue_t{{.*}}** %default_queue
+ // COMMON: [[FLAGS:%[0-9]+]] = load i32, i32* %flags
+ // COMMON: [[NDR:%[0-9]+]] = load %opencl.ndrange_t*, %opencl.ndrange_t** %ndrange
+ // COMMON: [[AD:%arraydecay[0-9]*]] = getelementptr inbounds [1 x %opencl.clk_event_t*], [1 x %opencl.clk_event_t*]* %event_wait_list2, i32 0, i32 0
+ // COMMON: [[WAIT_EVNT:%[0-9]+]] = addrspacecast %opencl.clk_event_t{{.*}}** [[AD]] 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)*
+ // B32: call i32 (%opencl.queue_t{{.*}}*, i32, %opencl.ndrange_t*, i32, %opencl.clk_event_t{{.*}}* addrspace(4)*, %opencl.clk_event_t{{.*}}* addrspace(4)*, i8*, i32, ...) @__enqueue_kernel_events_vaargs(%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %opencl.ndrange_t* {{.*}}, i32 2, %opencl.clk_event_t{{.*}} [[WAIT_EVNT]], %opencl.clk_event_t{{.*}} [[EVNT]], i8* bitcast ({ i8**, i32, i32, i8*, %struct.__block_descriptor addrspace(2)* }* @__block_literal_global{{(.[0-9]+)?}} to i8*), i32 1, i32 256)
+ // B64: call i32 (%opencl.queue_t{{.*}}*, i32, %opencl.ndrange_t*, i32, %opencl.clk_event_t{{.*}}* addrspace(4)*, %opencl.clk_event_t{{.*}}* addrspace(4)*, i8*, i32, ...) @__enqueue_kernel_events_vaargs(%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %opencl.ndrange_t* {{.*}}, i32 2, %opencl.clk_event_t{{.*}} [[WAIT_EVNT]], %opencl.clk_event_t{{.*}} [[EVNT]], i8* bitcast ({ i8**, i32, i32, i8*, %struct.__block_descriptor addrspace(2)* }* @__block_literal_global{{(.[0-9]+)?}} to i8*), i32 1, i64 256)
enqueue_kernel(default_queue, flags, ndrange, 2, event_wait_list2, &clk_event,
^(local void *p) {
return;
},
256);
- // CHECK: [[DEF_Q:%[0-9]+]] = load %opencl.queue_t*, %opencl.queue_t** %default_queue
- // CHECK: [[FLAGS:%[0-9]+]] = load i32, i32* %flags
- // CHECK: [[NDR:%[0-9]+]] = load %opencl.ndrange_t*, %opencl.ndrange_t** %ndrange
- // CHECK: [[AD:%arraydecay[0-9]*]] = getelementptr inbounds [1 x %opencl.clk_event_t*], [1 x %opencl.clk_event_t*]* %event_wait_list2, i32 0, i32 0
- // CHECK: [[SIZE:%[0-9]+]] = zext i8 {{%[0-9]+}} to i32
- // CHECK: call i32 (%opencl.queue_t*, i32, %opencl.ndrange_t*, i32, %opencl.clk_event_t**, %opencl.clk_event_t**, i8*, i32, ...) @__enqueue_kernel_events_vaargs(%opencl.queue_t* [[DEF_Q]], i32 [[FLAGS]], %opencl.ndrange_t* [[NDR]], i32 2, %opencl.clk_event_t** [[AD]], %opencl.clk_event_t** %clk_event, i8* bitcast ({ i8**, i32, i32, i8*, %struct.__block_descriptor addrspace(3)* }* @__block_literal_global{{(.[0-9]+)?}} to i8*), i32 1, i32 [[SIZE]])
+ // COMMON: [[DEF_Q:%[0-9]+]] = load %opencl.queue_t{{.*}}*, %opencl.queue_t{{.*}}** %default_queue
+ // COMMON: [[FLAGS:%[0-9]+]] = load i32, i32* %flags
+ // COMMON: [[NDR:%[0-9]+]] = load %opencl.ndrange_t*, %opencl.ndrange_t** %ndrange
+ // COMMON: [[AD:%arraydecay[0-9]*]] = getelementptr inbounds [1 x %opencl.clk_event_t*], [1 x %opencl.clk_event_t*]* %event_wait_list2, i32 0, i32 0
+ // COMMON: [[WAIT_EVNT:%[0-9]+]] = addrspacecast %opencl.clk_event_t{{.*}}** [[AD]] 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)*
+ // B32: [[SIZE:%[0-9]+]] = zext i8 {{%[0-9]+}} to i32
+ // B32: call i32 (%opencl.queue_t{{.*}}*, i32, %opencl.ndrange_t*, i32, %opencl.clk_event_t{{.*}}* addrspace(4)*, %opencl.clk_event_t{{.*}}* addrspace(4)*, i8*, i32, ...) @__enqueue_kernel_events_vaargs(%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %opencl.ndrange_t* {{.*}}, i32 2, %opencl.clk_event_t{{.*}}* addrspace(4)* [[WAIT_EVNT]], %opencl.clk_event_t{{.*}}* addrspace(4)* [[EVNT]], i8* bitcast ({ i8**, i32, i32, i8*, %struct.__block_descriptor addrspace(2)* }* @__block_literal_global{{(.[0-9]+)?}} to i8*), i32 1, i32 [[SIZE]])
+ // B64: [[SIZE:%[0-9]+]] = zext i8 {{%[0-9]+}} to i64
+ // B64: call i32 (%opencl.queue_t{{.*}}*, i32, %opencl.ndrange_t*, i32, %opencl.clk_event_t{{.*}}* addrspace(4)*, %opencl.clk_event_t{{.*}}* addrspace(4)*, i8*, i32, ...) @__enqueue_kernel_events_vaargs(%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %opencl.ndrange_t* {{.*}}, i32 2, %opencl.clk_event_t{{.*}}* addrspace(4)* [[WAIT_EVNT]], %opencl.clk_event_t{{.*}}* addrspace(4)* [[EVNT]], i8* bitcast ({ i8**, i32, i32, i8*, %struct.__block_descriptor addrspace(2)* }* @__block_literal_global{{(.[0-9]+)?}} to i8*), i32 1, i64 [[SIZE]])
enqueue_kernel(default_queue, flags, ndrange, 2, event_wait_list2, &clk_event,
^(local void *p) {
return;
},
c);
+ long l;
+ // COMMON: [[DEF_Q:%[0-9]+]] = load %opencl.queue_t{{.*}}*, %opencl.queue_t{{.*}}** %default_queue
+ // COMMON: [[FLAGS:%[0-9]+]] = load i32, i32* %flags
+ // COMMON: [[NDR:%[0-9]+]] = load %opencl.ndrange_t*, %opencl.ndrange_t** %ndrange
+ // B32: [[SIZE:%[0-9]+]] = trunc i64 {{%[0-9]+}} to i32
+ // B32: call i32 (%opencl.queue_t{{.*}}*, i32, %opencl.ndrange_t*, i8*, i32, ...) @__enqueue_kernel_vaargs(%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %opencl.ndrange_t* [[NDR]], i8* bitcast ({ i8**, i32, i32, i8*, %struct.__block_descriptor addrspace(2)* }* @__block_literal_global{{(.[0-9]+)?}} to i8*), i32 1, i32 [[SIZE]])
+ // B64: [[SIZE:%[0-9]+]] = load i64, i64* %l
+ // B64: call i32 (%opencl.queue_t{{.*}}*, i32, %opencl.ndrange_t*, i8*, i32, ...) @__enqueue_kernel_vaargs(%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %opencl.ndrange_t* [[NDR]], i8* bitcast ({ i8**, i32, i32, i8*, %struct.__block_descriptor addrspace(2)* }* @__block_literal_global{{(.[0-9]+)?}} to i8*), i32 1, i64 [[SIZE]])
+ enqueue_kernel(default_queue, flags, ndrange,
+ ^(local void *p) {
+ return;
+ },
+ l);
+
+ // COMMON: [[DEF_Q:%[0-9]+]] = load %opencl.queue_t*, %opencl.queue_t** %default_queue
+ // COMMON: [[FLAGS:%[0-9]+]] = load i32, i32* %flags
+ // COMMON: [[NDR:%[0-9]+]] = load %opencl.ndrange_t*, %opencl.ndrange_t** %ndrange
+ // B32: call i32 (%opencl.queue_t{{.*}}*, i32, %opencl.ndrange_t*, i8*, i32, ...) @__enqueue_kernel_vaargs(%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %opencl.ndrange_t* [[NDR]], i8* bitcast ({ i8**, i32, i32, i8*, %struct.__block_descriptor addrspace(2)* }* @__block_literal_global{{(.[0-9]+)?}} to i8*), i32 1, i32 0)
+ // B64: call i32 (%opencl.queue_t{{.*}}*, i32, %opencl.ndrange_t*, i8*, i32, ...) @__enqueue_kernel_vaargs(%opencl.queue_t{{.*}}* [[DEF_Q]], i32 [[FLAGS]], %opencl.ndrange_t* [[NDR]], i8* bitcast ({ i8**, i32, i32, i8*, %struct.__block_descriptor addrspace(2)* }* @__block_literal_global{{(.[0-9]+)?}} to i8*), i32 1, i64 4294967296)
+ enqueue_kernel(default_queue, flags, ndrange,
+ ^(local void *p) {
+ return;
+ },
+ 4294967296L);
+
+ // 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 ()* bitcast ([[BL_A:[^@]+@__block_literal_global.[0-9]+]] to void ()*), void ()** %block_A
void (^const block_A)(void) = ^{
return;
};
+
+ // COMMON: store void (i8 addrspace(3)*)* bitcast ([[BL_B:[^@]+@__block_literal_global.[0-9]+]] to void (i8 addrspace(3)*)*), void (i8 addrspace(3)*)** %block_B
void (^const block_B)(local void *) = ^(local void *a) {
return;
};
- // CHECK: [[BL:%[0-9]+]] = load void ()*, void ()** %block_A
- // CHECK: [[BL_I8:%[0-9]+]] = bitcast void ()* [[BL]] to i8*
- // CHECK: call i32 @__get_kernel_work_group_size_impl(i8* [[BL_I8]])
+ // COMMON: call i32 @__get_kernel_work_group_size_impl(i8* bitcast ([[BL_A]] to i8*))
unsigned size = get_kernel_work_group_size(block_A);
- // CHECK: [[BL:%[0-9]+]] = load void (i8 addrspace(2)*)*, void (i8 addrspace(2)*)** %block_B
- // CHECK: [[BL_I8:%[0-9]+]] = bitcast void (i8 addrspace(2)*)* [[BL]] to i8*
- // CHECK: call i32 @__get_kernel_work_group_size_impl(i8* [[BL_I8]])
+ // COMMON: call i32 @__get_kernel_work_group_size_impl(i8* bitcast ([[BL_B]] to i8*))
size = get_kernel_work_group_size(block_B);
- // CHECK: [[BL:%[0-9]+]] = load void ()*, void ()** %block_A
- // CHECK: [[BL_I8:%[0-9]+]] = bitcast void ()* [[BL]] to i8*
- // CHECK: call i32 @__get_kernel_preferred_work_group_multiple_impl(i8* [[BL_I8]])
+ // COMMON: call i32 @__get_kernel_preferred_work_group_multiple_impl(i8* bitcast ([[BL_A]] to i8*))
size = get_kernel_preferred_work_group_size_multiple(block_A);
- // CHECK: [[BL:%[0-9]+]] = load void (i8 addrspace(2)*)*, void (i8 addrspace(2)*)* addrspace(1)* @block_G
- // CHECK: [[BL_I8:%[0-9]+]] = bitcast void (i8 addrspace(2)*)* [[BL]] to i8*
- // CHECK: call i32 @__get_kernel_preferred_work_group_multiple_impl(i8* [[BL_I8]])
+ // COMMON: call i32 @__get_kernel_preferred_work_group_multiple_impl(i8* bitcast ([[BL_GLOBAL]] to i8*))
size = get_kernel_preferred_work_group_size_multiple(block_G);
}
diff --git a/test/CodeGenOpenCL/const-str-array-decay.cl b/test/CodeGenOpenCL/const-str-array-decay.cl
index af8c35542f3b..353aa3a9a083 100644
--- a/test/CodeGenOpenCL/const-str-array-decay.cl
+++ b/test/CodeGenOpenCL/const-str-array-decay.cl
@@ -6,6 +6,6 @@ kernel void str_array_decy() {
test_func("Test string literal");
}
-// CHECK: i8 addrspace(3)* getelementptr inbounds ([20 x i8], [20 x i8] addrspace(3)*
+// CHECK: i8 addrspace(2)* getelementptr inbounds ([20 x i8], [20 x i8] addrspace(2)*
// CHECK-NOT: addrspacecast
diff --git a/test/CodeGenOpenCL/constant-addr-space-globals.cl b/test/CodeGenOpenCL/constant-addr-space-globals.cl
index f81a51458c42..4f0d1ea23e56 100644
--- a/test/CodeGenOpenCL/constant-addr-space-globals.cl
+++ b/test/CodeGenOpenCL/constant-addr-space-globals.cl
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -cl-opt-disable -ffake-address-space-map -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -triple "spir64-unknown-unknown" -cl-opt-disable -ffake-address-space-map -emit-llvm -o - | FileCheck %s
// CHECK: @array = addrspace({{[0-9]+}}) constant
__constant float array[2] = {0.0f, 1.0f};
@@ -6,3 +6,22 @@ __constant float array[2] = {0.0f, 1.0f};
kernel void test(global float *out) {
*out = array[0];
}
+
+// Test that we don't use directly initializers for const aggregates
+// but create a copy in the original address space (unless a variable itself is
+// in the constant address space).
+
+void foo(constant const int *p1, const int *p2, const int *p3);
+// CHECK: @k.arr1 = internal addrspace(2) constant [3 x i32] [i32 1, i32 2, i32 3]
+// CHECK: @k.arr2 = private unnamed_addr addrspace(2) constant [3 x i32] [i32 4, i32 5, i32 6]
+// CHECK: @k.arr3 = private unnamed_addr addrspace(2) constant [3 x i32] [i32 7, i32 8, i32 9]
+kernel void k(void) {
+ // CHECK-NOT: %arr1 = alloca [3 x i32]
+ constant const int arr1[] = {1, 2, 3};
+ // CHECK: %arr2 = alloca [3 x i32]
+ const int arr2[] = {4, 5, 6};
+ // CHECK: %arr3 = alloca [3 x i32]
+ int arr3[] = {7, 8, 9};
+
+ foo(arr1, arr2, arr3);
+}
diff --git a/test/CodeGenOpenCL/convergent.cl b/test/CodeGenOpenCL/convergent.cl
new file mode 100644
index 000000000000..c6bcb52a6d75
--- /dev/null
+++ b/test/CodeGenOpenCL/convergent.cl
@@ -0,0 +1,118 @@
+// RUN: %clang_cc1 -triple spir-unknown-unknown -emit-llvm %s -o - | opt -instnamer -S | FileCheck %s
+
+void convfun(void) __attribute__((convergent));
+void non_convfun(void);
+void nodupfun(void) __attribute__((noduplicate));
+
+void f(void);
+void g(void);
+
+// Test two if's are merged and non_convfun duplicated.
+// The LLVM IR is equivalent to:
+// if (a) {
+// f();
+// non_convfun();
+// g();
+// } else {
+// non_convfun();
+// }
+//
+// CHECK: define spir_func void @test_merge_if(i32 %[[a:.+]])
+// CHECK: %[[tobool:.+]] = icmp eq i32 %[[a]], 0
+// CHECK: br i1 %[[tobool]], label %[[if_end3_critedge:.+]], label %[[if_then:.+]]
+// CHECK: [[if_then]]:
+// CHECK: tail call spir_func void @f()
+// CHECK: tail call spir_func void @non_convfun()
+// CHECK: tail call spir_func void @g()
+// CHECK: br label %[[if_end3:.+]]
+// CHECK: [[if_end3_critedge]]:
+// CHECK: tail call spir_func void @non_convfun()
+// CHECK: br label %[[if_end3]]
+// CHECK: [[if_end3]]:
+// CHECK-LABEL: ret void
+
+void test_merge_if(int a) {
+ if (a) {
+ f();
+ }
+ non_convfun();
+ if (a) {
+ g();
+ }
+}
+
+// CHECK-DAG: declare spir_func void @f()
+// CHECK-DAG: declare spir_func void @non_convfun()
+// CHECK-DAG: declare spir_func void @g()
+
+// Test two if's are not merged.
+// CHECK: define spir_func void @test_no_merge_if(i32 %[[a:.+]])
+// CHECK: %[[tobool:.+]] = icmp eq i32 %[[a]], 0
+// CHECK: br i1 %[[tobool]], label %[[if_end:.+]], label %[[if_then:.+]]
+// CHECK: [[if_then]]:
+// CHECK: tail call spir_func void @f()
+// CHECK-NOT: call spir_func void @convfun()
+// CHECK-NOT: call spir_func void @g()
+// CHECK: br label %[[if_end]]
+// CHECK: [[if_end]]:
+// CHECK: %[[tobool_pr:.+]] = phi i1 [ true, %[[if_then]] ], [ false, %{{.+}} ]
+// CHECK: tail call spir_func void @convfun() #[[attr5:.+]]
+// CHECK: br i1 %[[tobool_pr]], label %[[if_then2:.+]], label %[[if_end3:.+]]
+// CHECK: [[if_then2]]:
+// CHECK: tail call spir_func void @g()
+// CHECK: br label %[[if_end3:.+]]
+// CHECK: [[if_end3]]:
+// CHECK-LABEL: ret void
+
+void test_no_merge_if(int a) {
+ if (a) {
+ f();
+ }
+ convfun();
+ if(a) {
+ g();
+ }
+}
+
+// CHECK: declare spir_func void @convfun(){{[^#]*}} #[[attr2:[0-9]+]]
+
+// Test loop is unrolled for convergent function.
+// CHECK-LABEL: define spir_func void @test_unroll()
+// CHECK: tail call spir_func void @convfun() #[[attr5:[0-9]+]]
+// CHECK: tail call spir_func void @convfun() #[[attr5]]
+// CHECK: tail call spir_func void @convfun() #[[attr5]]
+// CHECK: tail call spir_func void @convfun() #[[attr5]]
+// CHECK: tail call spir_func void @convfun() #[[attr5]]
+// CHECK: tail call spir_func void @convfun() #[[attr5]]
+// CHECK: tail call spir_func void @convfun() #[[attr5]]
+// CHECK: tail call spir_func void @convfun() #[[attr5]]
+// CHECK: tail call spir_func void @convfun() #[[attr5]]
+// CHECK: tail call spir_func void @convfun() #[[attr5]]
+// CHECK-LABEL: ret void
+
+void test_unroll() {
+ for (int i = 0; i < 10; i++)
+ convfun();
+}
+
+// Test loop is not unrolled for noduplicate function.
+// CHECK-LABEL: define spir_func void @test_not_unroll()
+// CHECK: br label %[[for_body:.+]]
+// CHECK: [[for_cond_cleanup:.+]]:
+// CHECK: ret void
+// CHECK: [[for_body]]:
+// CHECK: tail call spir_func void @nodupfun() #[[attr6:[0-9]+]]
+// CHECK-NOT: call spir_func void @nodupfun()
+// CHECK: br i1 %{{.+}}, label %[[for_body]], label %[[for_cond_cleanup]]
+
+void test_not_unroll() {
+ for (int i = 0; i < 10; i++)
+ nodupfun();
+}
+
+// CHECK: declare spir_func void @nodupfun(){{[^#]*}} #[[attr3:[0-9]+]]
+
+// CHECK-DAG: attributes #[[attr2]] = { {{[^}]*}}convergent{{[^}]*}} }
+// CHECK-DAG: attributes #[[attr3]] = { {{[^}]*}}noduplicate{{[^}]*}} }
+// CHECK-DAG: attributes #[[attr5]] = { {{[^}]*}}convergent{{[^}]*}} }
+// CHECK-DAG: attributes #[[attr6]] = { {{[^}]*}}noduplicate{{[^}]*}} }
diff --git a/test/CodeGenOpenCL/denorms-are-zero.cl b/test/CodeGenOpenCL/denorms-are-zero.cl
index 488004fa4fc3..f398218b4fd7 100644
--- a/test/CodeGenOpenCL/denorms-are-zero.cl
+++ b/test/CodeGenOpenCL/denorms-are-zero.cl
@@ -1,5 +1,19 @@
// 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-denormals -cl-denorms-are-zero -o - -triple amdgcn--amdhsa -target-cpu fiji %s | FileCheck --check-prefix=CHECK-FEATURE %s
-// This test just checks that the -cl-denorms-are-zero argument is accepted
+// 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 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.
+
+// CHECK-DENORM-LABEL: define void @f()
+// CHECK-DENORM: attributes #{{[0-9]*}} = {{{[^}]*}} "target-features"="{{[^"]*}}+fp64-denormals,{{[^"]*}}-fp32-denormals{{[^"]*}}"
+// CHECK-LABEL: define void @f()
+// CHECK: attributes #{{[0-9]*}} = {{{[^}]*}} "target-features"="{{[^"]*}}+fp64-denormals,{{[^"]*}}-fp32-denormals{{[^"]*}}"
+// CHECK-FEATURE-LABEL: define void @f()
+// CHECK-FEATURE: attributes #{{[0-9]*}} = {{{[^}]*}} "target-features"="{{[^"]*}}+fp32-denormals,{{[^"]*}}-fp64-denormals{{[^"]*}}"
+void f() {}
diff --git a/test/CodeGenOpenCL/extension-begin.cl b/test/CodeGenOpenCL/extension-begin.cl
new file mode 100644
index 000000000000..1d5f78965f34
--- /dev/null
+++ b/test/CodeGenOpenCL/extension-begin.cl
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 %s -triple spir-unknown-unknown -emit-llvm -o - | FileCheck %s
+
+__attribute__((overloadable)) void f(int x);
+
+#pragma OPENCL EXTENSION my_ext : begin
+
+__attribute__((overloadable)) void f(long x);
+
+#pragma OPENCL EXTENSION my_ext : end
+
+#pragma OPENCL EXTENSION my_ext : enable
+
+//CHECK: define spir_func void @test_f1(i64 %x)
+//CHECK: call spir_func void @_Z1fl(i64 %{{.*}})
+void test_f1(long x) {
+ f(x);
+}
+
+#pragma OPENCL EXTENSION my_ext : disable
+
+//CHECK: define spir_func void @test_f2(i64 %x)
+//CHECK: call spir_func void @_Z1fi(i32 %{{.*}})
+void test_f2(long x) {
+ f(x);
+}
diff --git a/test/CodeGenOpenCL/fpmath.cl b/test/CodeGenOpenCL/fpmath.cl
index 88df3bf166ab..8908861ace8e 100644
--- a/test/CodeGenOpenCL/fpmath.cl
+++ b/test/CodeGenOpenCL/fpmath.cl
@@ -1,25 +1,51 @@
-// RUN: %clang_cc1 %s -emit-llvm -o - -triple spir-unknown-unknown | FileCheck %s
+// RUN: %clang_cc1 %s -emit-llvm -o - -triple spir-unknown-unknown | FileCheck --check-prefix=CHECK --check-prefix=NODIVOPT %s
+// RUN: %clang_cc1 %s -emit-llvm -o - -triple spir-unknown-unknown -cl-fp32-correctly-rounded-divide-sqrt | FileCheck --check-prefix=CHECK --check-prefix=DIVOPT %s
+// RUN: %clang_cc1 %s -emit-llvm -o - -DNOFP64 -cl-std=CL1.2 -triple r600-unknown-unknown -target-cpu r600 -pedantic | FileCheck --check-prefix=CHECK-FLT %s
+// RUN: %clang_cc1 %s -emit-llvm -o - -DFP64 -cl-std=CL1.2 -triple spir-unknown-unknown -pedantic | FileCheck --check-prefix=CHECK-DBL %s
typedef __attribute__(( ext_vector_type(4) )) float float4;
float spscalardiv(float a, float b) {
// CHECK: @spscalardiv
- // CHECK: fdiv{{.*}}, !fpmath ![[MD:[0-9]+]]
+ // CHECK: #[[ATTR:[0-9]+]]
+ // CHECK: fdiv{{.*}},
+ // NODIVOPT: !fpmath ![[MD:[0-9]+]]
+ // DIVOPT-NOT: !fpmath ![[MD:[0-9]+]]
return a / b;
}
float4 spvectordiv(float4 a, float4 b) {
// CHECK: @spvectordiv
- // CHECK: fdiv{{.*}}, !fpmath ![[MD]]
+ // CHECK: #[[ATTR]]
+ // CHECK: fdiv{{.*}},
+ // NODIVOPT: !fpmath ![[MD]]
+ // DIVOPT-NOT: !fpmath ![[MD]]
return a / b;
}
-#pragma OPENCL EXTENSION cl_khr_fp64 : enable
+#if __OPENCL_C_VERSION__ >=120
+void printf(constant char* fmt, ...);
+
+void testdbllit(long *val) {
+ // CHECK-FLT: float 2.000000e+01
+ // CHECK-DBL: double 2.000000e+01
+ printf("%f", 20.0);
+}
+#endif
+
+#ifndef NOFP64
+#pragma OPENCL EXTENSION cl_khr_fp64 : enable
double dpscalardiv(double a, double b) {
// CHECK: @dpscalardiv
+ // CHECK: #[[ATTR]]
// CHECK-NOT: !fpmath
return a / b;
}
+#endif
-// CHECK: ![[MD]] = !{float 2.500000e+00}
+// CHECK: attributes #[[ATTR]] = {
+// NODIVOPT: "correctly-rounded-divide-sqrt-fp-math"="false"
+// DIVOPT: "correctly-rounded-divide-sqrt-fp-math"="true"
+// CHECK: }
+// NODIVOPT: ![[MD]] = !{float 2.500000e+00}
diff --git a/test/CodeGenOpenCL/kernel-arg-info.cl b/test/CodeGenOpenCL/kernel-arg-info.cl
index 5a5c8f9d6c5f..32017f85df8c 100644
--- a/test/CodeGenOpenCL/kernel-arg-info.cl
+++ b/test/CodeGenOpenCL/kernel-arg-info.cl
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 %s -emit-llvm -o - -triple spir-unknown-unknown | FileCheck %s
-// RUN: %clang_cc1 %s -emit-llvm -o - -triple spir-unknown-unknown -cl-kernel-arg-info | FileCheck %s -check-prefix ARGINFO
+// RUN: %clang_cc1 %s -cl-std=CL2.0 -emit-llvm -o - -triple spir-unknown-unknown | FileCheck %s
+// RUN: %clang_cc1 %s -cl-std=CL2.0 -emit-llvm -o - -triple spir-unknown-unknown -cl-kernel-arg-info | FileCheck %s -check-prefix ARGINFO
kernel void foo(__global int * restrict X, const int Y,
volatile int anotherArg, __constant float * restrict Z) {
@@ -14,7 +14,7 @@ kernel void foo(__global int * restrict X, const int Y,
// CHECK-NOT: !kernel_arg_name
// ARGINFO: !kernel_arg_name ![[MD15:[0-9]+]]
-kernel void foo2(read_only image1d_t img1, image2d_t img2, write_only image2d_array_t img3) {
+kernel void foo2(read_only image1d_t img1, image2d_t img2, write_only image2d_array_t img3, read_write image1d_t img4) {
}
// CHECK: define spir_kernel void @foo2{{[^!]+}}
// CHECK: !kernel_arg_addr_space ![[MD21:[0-9]+]]
@@ -65,11 +65,11 @@ kernel void foo5(myImage img1, write_only image1d_t img2) {
// CHECK: ![[MD13]] = !{!"int*", !"int", !"int", !"float*"}
// CHECK: ![[MD14]] = !{!"restrict", !"const", !"volatile", !"restrict const"}
// ARGINFO: ![[MD15]] = !{!"X", !"Y", !"anotherArg", !"Z"}
-// CHECK: ![[MD21]] = !{i32 1, i32 1, i32 1}
-// CHECK: ![[MD22]] = !{!"read_only", !"read_only", !"write_only"}
-// CHECK: ![[MD23]] = !{!"__read_only image1d_t", !"__read_only image2d_t", !"__write_only image2d_array_t"}
-// CHECK: ![[MD24]] = !{!"", !"", !""}
-// ARGINFO: ![[MD25]] = !{!"img1", !"img2", !"img3"}
+// CHECK: ![[MD21]] = !{i32 1, i32 1, i32 1, i32 1}
+// CHECK: ![[MD22]] = !{!"read_only", !"read_only", !"write_only", !"read_write"}
+// CHECK: ![[MD23]] = !{!"image1d_t", !"image2d_t", !"image2d_array_t", !"image1d_t"}
+// CHECK: ![[MD24]] = !{!"", !"", !"", !""}
+// ARGINFO: ![[MD25]] = !{!"img1", !"img2", !"img3", !"img4"}
// CHECK: ![[MD31]] = !{i32 1}
// CHECK: ![[MD32]] = !{!"none"}
// CHECK: ![[MD33]] = !{!"half*"}
@@ -82,7 +82,7 @@ kernel void foo5(myImage img1, write_only image1d_t img2) {
// CHECK: ![[MD45]] = !{!"", !""}
// ARGINFO: ![[MD46]] = !{!"X", !"Y"}
// CHECK: ![[MD51]] = !{!"read_only", !"write_only"}
-// CHECK: ![[MD52]] = !{!"myImage", !"__write_only image1d_t"}
-// CHECK: ![[MD53]] = !{!"__read_only image1d_t", !"__write_only image1d_t"}
+// CHECK: ![[MD52]] = !{!"myImage", !"image1d_t"}
+// CHECK: ![[MD53]] = !{!"image1d_t", !"image1d_t"}
// ARGINFO: ![[MD54]] = !{!"img1", !"img2"}
diff --git a/test/CodeGenOpenCL/local-initializer-undef.cl b/test/CodeGenOpenCL/local-initializer-undef.cl
index 5d34f56b821d..f209b1f6b449 100644
--- a/test/CodeGenOpenCL/local-initializer-undef.cl
+++ b/test/CodeGenOpenCL/local-initializer-undef.cl
@@ -6,10 +6,10 @@ typedef struct Foo {
float z;
} Foo;
-// CHECK-DAG: @test.lds_int = internal addrspace(2) global i32 undef
-// CHECK-DAG: @test.lds_int_arr = internal addrspace(2) global [128 x i32] undef
-// CHECK-DAG: @test.lds_struct = internal addrspace(2) global %struct.Foo undef
-// CHECK-DAG: @test.lds_struct_arr = internal addrspace(2) global [64 x %struct.Foo] undef
+// CHECK-DAG: @test.lds_int = internal addrspace(3) global i32 undef
+// CHECK-DAG: @test.lds_int_arr = internal addrspace(3) global [128 x i32] undef
+// CHECK-DAG: @test.lds_struct = internal addrspace(3) global %struct.Foo undef
+// CHECK-DAG: @test.lds_struct_arr = internal addrspace(3) global [64 x %struct.Foo] undef
__kernel void test()
{
__local int lds_int;
diff --git a/test/CodeGenOpenCL/local.cl b/test/CodeGenOpenCL/local.cl
index da371f8e4648..6f44b684e94b 100644
--- a/test/CodeGenOpenCL/local.cl
+++ b/test/CodeGenOpenCL/local.cl
@@ -3,7 +3,7 @@
void func(local int*);
__kernel void foo(void) {
- // CHECK: @foo.i = internal addrspace(2) global i32 undef
+ // CHECK: @foo.i = internal addrspace(3) global i32 undef
__local int i;
func(&i);
}
diff --git a/test/CodeGenOpenCL/memcpy.cl b/test/CodeGenOpenCL/memcpy.cl
index cb27803adf41..5911b5c5aa63 100644
--- a/test/CodeGenOpenCL/memcpy.cl
+++ b/test/CodeGenOpenCL/memcpy.cl
@@ -2,7 +2,7 @@
// CHECK-LABEL: @test
// CHECK-NOT: addrspacecast
-// CHECK: call void @llvm.memcpy.p1i8.p3i8
+// CHECK: call void @llvm.memcpy.p1i8.p2i8
kernel void test(global float *g, constant float *c) {
__builtin_memcpy(g, c, 32);
}
diff --git a/test/CodeGenOpenCL/null_queue.cl b/test/CodeGenOpenCL/null_queue.cl
new file mode 100644
index 000000000000..cdcd7eef2ed4
--- /dev/null
+++ b/test/CodeGenOpenCL/null_queue.cl
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -O0 -cl-std=CL2.0 -emit-llvm %s -o - | FileCheck %s
+extern queue_t get_default_queue();
+
+bool compare() {
+ return 0 == get_default_queue() &&
+ get_default_queue() == 0;
+ // CHECK: icmp eq %opencl.queue_t* null, %{{.*}}
+ // CHECK: icmp eq %opencl.queue_t* %{{.*}}, null
+}
+
+void func(queue_t q);
+
+void init() {
+ queue_t q = 0;
+ func(0);
+ // CHECK: store %opencl.queue_t* null, %opencl.queue_t** %q
+ // CHECK: call void @func(%opencl.queue_t* null)
+}
diff --git a/test/CodeGenOpenCL/opencl_types.cl b/test/CodeGenOpenCL/opencl_types.cl
index 5691b27fbe52..73c57b73098f 100644
--- a/test/CodeGenOpenCL/opencl_types.cl
+++ b/test/CodeGenOpenCL/opencl_types.cl
@@ -1,40 +1,54 @@
-// RUN: %clang_cc1 %s -emit-llvm -o - -O0 | FileCheck %s
+// RUN: %clang_cc1 %s -triple "spir-unknown-unknown" -emit-llvm -o - -O0 | FileCheck %s --check-prefix=CHECK-SPIR
+// RUN: %clang_cc1 %s -triple "amdgcn--amdhsa" -emit-llvm -o - -O0 | FileCheck %s --check-prefix=CHECK-AMDGCN
-constant sampler_t glb_smp = 7;
-// CHECK: constant i32 7
+#define CLK_ADDRESS_CLAMP_TO_EDGE 2
+#define CLK_NORMALIZED_COORDS_TRUE 1
+#define CLK_FILTER_NEAREST 0x10
+#define CLK_FILTER_LINEAR 0x20
+
+constant sampler_t glb_smp = CLK_ADDRESS_CLAMP_TO_EDGE|CLK_NORMALIZED_COORDS_TRUE|CLK_FILTER_NEAREST;
+// CHECK-SPIR-NOT: constant i32
void fnc1(image1d_t img) {}
-// CHECK: @fnc1(%opencl.image1d_ro_t*
+// CHECK-SPIR: @fnc1(%opencl.image1d_ro_t addrspace(1)*
+// CHECK-AMDGCN: @fnc1(%opencl.image1d_ro_t addrspace(2)*
void fnc1arr(image1d_array_t img) {}
-// CHECK: @fnc1arr(%opencl.image1d_array_ro_t*
+// CHECK-SPIR: @fnc1arr(%opencl.image1d_array_ro_t addrspace(1)*
+// CHECK-AMDGCN: @fnc1arr(%opencl.image1d_array_ro_t addrspace(2)*
void fnc1buff(image1d_buffer_t img) {}
-// CHECK: @fnc1buff(%opencl.image1d_buffer_ro_t*
+// CHECK-SPIR: @fnc1buff(%opencl.image1d_buffer_ro_t addrspace(1)*
+// CHECK-AMDGCN: @fnc1buff(%opencl.image1d_buffer_ro_t addrspace(2)*
void fnc2(image2d_t img) {}
-// CHECK: @fnc2(%opencl.image2d_ro_t*
+// CHECK-SPIR: @fnc2(%opencl.image2d_ro_t addrspace(1)*
+// CHECK-AMDGCN: @fnc2(%opencl.image2d_ro_t addrspace(2)*
void fnc2arr(image2d_array_t img) {}
-// CHECK: @fnc2arr(%opencl.image2d_array_ro_t*
+// CHECK-SPIR: @fnc2arr(%opencl.image2d_array_ro_t addrspace(1)*
+// CHECK-AMDGCN: @fnc2arr(%opencl.image2d_array_ro_t addrspace(2)*
void fnc3(image3d_t img) {}
-// CHECK: @fnc3(%opencl.image3d_ro_t*
+// CHECK-SPIR: @fnc3(%opencl.image3d_ro_t addrspace(1)*
+// CHECK-AMDGCN: @fnc3(%opencl.image3d_ro_t addrspace(2)*
void fnc4smp(sampler_t s) {}
-// CHECK-LABEL: define {{.*}}void @fnc4smp(i32
+// CHECK-SPIR-LABEL: define {{.*}}void @fnc4smp(%opencl.sampler_t addrspace(2)*
+// CHECK-AMDGCN-LABEL: define {{.*}}void @fnc4smp(%opencl.sampler_t addrspace(2)*
kernel void foo(image1d_t img) {
- sampler_t smp = 5;
- // CHECK: alloca i32
+ sampler_t smp = CLK_ADDRESS_CLAMP_TO_EDGE|CLK_NORMALIZED_COORDS_TRUE|CLK_FILTER_LINEAR;
+ // CHECK-SPIR: alloca %opencl.sampler_t addrspace(2)*
event_t evt;
- // CHECK: alloca %opencl.event_t*
- // CHECK: store i32 5,
+ // CHECK-SPIR: alloca %opencl.event_t*
+ // CHECK-SPIR: store %opencl.sampler_t addrspace(2)*
fnc4smp(smp);
- // CHECK: call {{.*}}void @fnc4smp(i32
+ // CHECK-SPIR: call {{.*}}void @fnc4smp(%opencl.sampler_t addrspace(2)*
fnc4smp(glb_smp);
- // CHECK: call {{.*}}void @fnc4smp(i32
+ // CHECK-SPIR: call {{.*}}void @fnc4smp(%opencl.sampler_t addrspace(2)*
}
void __attribute__((overloadable)) bad1(image1d_t b, image2d_t c, image2d_t d) {}
-// CHECK-LABEL: @{{_Z4bad114ocl_image1d_ro14ocl_image2d_roS0_|"\\01\?bad1@@\$\$J0YAXPAUocl_image1d_ro@@PAUocl_image2d_ro@@1@Z"}}
+// 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)*{{.*}})
diff --git a/test/CodeGenOpenCL/partial_initializer.cl b/test/CodeGenOpenCL/partial_initializer.cl
new file mode 100644
index 000000000000..454c82f89299
--- /dev/null
+++ b/test/CodeGenOpenCL/partial_initializer.cl
@@ -0,0 +1,66 @@
+// RUN: %clang_cc1 -triple spir-unknown-unknown -cl-std=CL2.0 -emit-llvm %s -O0 -o - | FileCheck %s
+
+typedef __attribute__(( ext_vector_type(2) )) int int2;
+typedef __attribute__(( ext_vector_type(4) )) int int4;
+
+// CHECK: %struct.StrucTy = type { i32, i32, i32 }
+
+// CHECK: @GA = addrspace(1) global [6 x [6 x float]] {{[[][[]}}6 x float] [float 1.000000e+00, float 2.000000e+00, float 0.000000e+00, float 0.000000e+00, float 0.000000e+00, float 0.000000e+00],
+// CHECK: [6 x float] zeroinitializer, [6 x float] zeroinitializer, [6 x float] zeroinitializer, [6 x float] zeroinitializer, [6 x float] zeroinitializer], align 4
+float GA[6][6] = {1.0f, 2.0f};
+
+typedef struct {
+ int x;
+ int y;
+ int z;
+} StrucTy;
+
+// CHECK: @GS = addrspace(1) global %struct.StrucTy { i32 1, i32 2, i32 0 }, align 4
+StrucTy GS = {1, 2};
+
+// CHECK: @GV1 = addrspace(1) global <4 x i32> <i32 1, i32 2, i32 3, i32 4>, align 16
+int4 GV1 = (int4)((int2)(1,2),3,4);
+
+// CHECK: @GV2 = addrspace(1) global <4 x i32> <i32 1, i32 1, i32 1, i32 1>, align 16
+int4 GV2 = (int4)(1);
+
+// CHECK: @f.S = private unnamed_addr addrspace(2) constant %struct.StrucTy { i32 1, i32 2, i32 0 }, align 4
+
+// CHECK-LABEL: define spir_func void @f()
+void f(void) {
+ // CHECK: %[[A:.*]] = alloca [6 x [6 x float]], align 4
+ // CHECK: %[[S:.*]] = alloca %struct.StrucTy, align 4
+ // CHECK: %[[V1:.*]] = alloca <4 x i32>, align 16
+ // CHECK: %[[compoundliteral:.*]] = alloca <4 x i32>, align 16
+ // CHECK: %[[compoundliteral1:.*]] = alloca <2 x i32>, align 8
+ // 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: %[[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]]
+ 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)
+ StrucTy S = {1, 2};
+
+ // CHECK: store <2 x i32> <i32 1, i32 2>, <2 x i32>* %[[compoundliteral1]], align 8
+ // CHECK: %[[v6:.*]] = load <2 x i32>, <2 x i32>* %[[compoundliteral1]], align 8
+ // CHECK: %[[vext:.*]] = shufflevector <2 x i32> %[[v6]], <2 x i32> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
+ // CHECK: %[[vecinit:.*]] = shufflevector <4 x i32> %[[vext]], <4 x i32> undef, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef>
+ // CHECK: %[[vecinit2:.*]] = insertelement <4 x i32> %[[vecinit]], i32 3, i32 2
+ // CHECK: %[[vecinit3:.*]] = insertelement <4 x i32> %[[vecinit2]], i32 4, i32 3
+ // CHECK: store <4 x i32> %[[vecinit3]], <4 x i32>* %[[compoundliteral]], align 16
+ // CHECK: %[[v7:.*]] = load <4 x i32>, <4 x i32>* %[[compoundliteral]], align 16
+ // CHECK: store <4 x i32> %[[v7]], <4 x i32>* %[[V1]], align 16
+ int4 V1 = (int4)((int2)(1,2),3,4);
+
+ // CHECK: store <4 x i32> <i32 1, i32 1, i32 1, i32 1>, <4 x i32>* %[[V2]], align 16
+ int4 V2 = (int4)(1);
+}
+
diff --git a/test/CodeGenOpenCL/pipe_builtin.cl b/test/CodeGenOpenCL/pipe_builtin.cl
index db6893ebf55d..a9b4ab630cef 100644
--- a/test/CodeGenOpenCL/pipe_builtin.cl
+++ b/test/CodeGenOpenCL/pipe_builtin.cl
@@ -4,58 +4,74 @@
// CHECK: %opencl.reserve_id_t = type opaque
void test1(read_only pipe int p, global int *ptr) {
- // CHECK: call i32 @__read_pipe_2(%opencl.pipe_t* %{{.*}}, i8* %{{.*}})
+ // CHECK: call i32 @__read_pipe_2(%opencl.pipe_t* %{{.*}}, i8* %{{.*}}, i32 4, i32 4)
read_pipe(p, ptr);
- // CHECK: call %opencl.reserve_id_t* @__reserve_read_pipe(%opencl.pipe_t* %{{.*}}, i32 {{.*}})
+ // CHECK: call %opencl.reserve_id_t* @__reserve_read_pipe(%opencl.pipe_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* %{{.*}})
+ // CHECK: call i32 @__read_pipe_4(%opencl.pipe_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* %{{.*}})
+ // CHECK: call void @__commit_read_pipe(%opencl.pipe_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* %{{.*}})
+ // CHECK: call i32 @__write_pipe_2(%opencl.pipe_t* %{{.*}}, i8* %{{.*}}, i32 4, i32 4)
write_pipe(p, ptr);
- // CHECK: call %opencl.reserve_id_t* @__reserve_write_pipe(%opencl.pipe_t* %{{.*}}, i32 {{.*}})
+ // CHECK: call %opencl.reserve_id_t* @__reserve_write_pipe(%opencl.pipe_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* %{{.*}})
+ // CHECK: call i32 @__write_pipe_4(%opencl.pipe_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* %{{.*}})
+ // CHECK: call void @__commit_write_pipe(%opencl.pipe_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 {{.*}})
+ // CHECK: call %opencl.reserve_id_t* @__work_group_reserve_read_pipe(%opencl.pipe_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* %{{.*}})
+ // CHECK: call void @__work_group_commit_read_pipe(%opencl.pipe_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 {{.*}})
+ // CHECK: call %opencl.reserve_id_t* @__work_group_reserve_write_pipe(%opencl.pipe_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* %{{.*}})
+ // CHECK: call void @__work_group_commit_write_pipe(%opencl.pipe_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 {{.*}})
+ // CHECK: call %opencl.reserve_id_t* @__sub_group_reserve_read_pipe(%opencl.pipe_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* %{{.*}})
+ // CHECK: call void @__sub_group_commit_read_pipe(%opencl.pipe_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 {{.*}})
+ // CHECK: call %opencl.reserve_id_t* @__sub_group_reserve_write_pipe(%opencl.pipe_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* %{{.*}})
+ // CHECK: call void @__sub_group_commit_write_pipe(%opencl.pipe_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* %{{.*}})
+ // CHECK: call i32 @__get_pipe_num_packets(%opencl.pipe_t* %{{.*}}, i32 4, i32 4)
*ptr = get_pipe_num_packets(p);
- // CHECK: call i32 @__get_pipe_max_packets(%opencl.pipe_t* %{{.*}})
+ // CHECK: call i32 @__get_pipe_max_packets(%opencl.pipe_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) {
+ // 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
+ if (read_pipe(r, ptr)) *ptr = -1;
+ // 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
+ if (get_pipe_num_packets(r)) *ptr = -1;
+ // CHECK: %[[M:[0-9]+]] = call i32 @__get_pipe_max_packets
+ // CHECK: icmp ne i32 %[[M]], 0
+ if (get_pipe_max_packets(w)) *ptr = -1;
+}
diff --git a/test/CodeGenOpenCL/pipe_types.cl b/test/CodeGenOpenCL/pipe_types.cl
index b9c411b5fcb6..f5b42e2a490f 100644
--- a/test/CodeGenOpenCL/pipe_types.cl
+++ b/test/CodeGenOpenCL/pipe_types.cl
@@ -41,7 +41,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* %{{.*}})
+ // CHECK: call i32 @__read_pipe_2(%opencl.pipe_t* %{{.*}}, i8* %{{.*}}, i32 16, i32 8)
read_pipe (SPipe, SDst);
- // CHECK: call i32 @__read_pipe_2(%opencl.pipe_t* %{{.*}}, i8* %{{.*}})
+ // CHECK: call i32 @__read_pipe_2(%opencl.pipe_t* %{{.*}}, i8* %{{.*}}, i32 16, i32 8)
}
diff --git a/test/CodeGenOpenCL/private-array-initialization.cl b/test/CodeGenOpenCL/private-array-initialization.cl
new file mode 100644
index 000000000000..a7d4a9891977
--- /dev/null
+++ b/test/CodeGenOpenCL/private-array-initialization.cl
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 %s -triple spir-unknown-unknown -O0 -emit-llvm -o - | FileCheck %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)
+}
diff --git a/test/CodeGenOpenCL/sampler.cl b/test/CodeGenOpenCL/sampler.cl
new file mode 100644
index 000000000000..6fc8c2c68446
--- /dev/null
+++ b/test/CodeGenOpenCL/sampler.cl
@@ -0,0 +1,57 @@
+// RUN: %clang_cc1 %s -emit-llvm -triple spir-unknown-unknown -o - -O0 | FileCheck %s
+//
+// This test covers 5 cases of sampler initialzation:
+// 1. function argument passing
+// 1a. argument is a file-scope variable
+// 1b. argument is a function-scope variable
+// 1c. argument is one of caller function's parameters
+// 2. variable initialization
+// 2a. initializing a file-scope variable
+// 2b. initializing a function-scope variable
+
+#define CLK_ADDRESS_CLAMP_TO_EDGE 2
+#define CLK_NORMALIZED_COORDS_TRUE 1
+#define CLK_FILTER_NEAREST 0x10
+#define CLK_FILTER_LINEAR 0x20
+
+// CHECK: %opencl.sampler_t = type opaque
+
+// Case 2a
+constant sampler_t glb_smp = CLK_ADDRESS_CLAMP_TO_EDGE | CLK_NORMALIZED_COORDS_TRUE | CLK_FILTER_LINEAR;
+// CHECK-NOT: glb_smp
+
+void fnc4smp(sampler_t s) {}
+// CHECK: define spir_func void @fnc4smp(%opencl.sampler_t addrspace(2)* %
+
+kernel void foo(sampler_t smp_par) {
+ // CHECK-LABEL: define spir_kernel void @foo(%opencl.sampler_t addrspace(2)* %smp_par)
+ // CHECK: [[smp_par_ptr:%[A-Za-z0-9_\.]+]] = alloca %opencl.sampler_t addrspace(2)*
+
+ // Case 2b
+ sampler_t smp = CLK_ADDRESS_CLAMP_TO_EDGE | CLK_NORMALIZED_COORDS_TRUE | CLK_FILTER_NEAREST;
+ // CHECK: [[smp_ptr:%[A-Za-z0-9_\.]+]] = alloca %opencl.sampler_t addrspace(2)*
+ // CHECK: [[SAMP:%[0-9]+]] = call %opencl.sampler_t addrspace(2)* @__translate_sampler_initializer(i32 19)
+ // CHECK: store %opencl.sampler_t addrspace(2)* [[SAMP]], %opencl.sampler_t addrspace(2)** [[smp_ptr]]
+
+ // Case 1b
+ fnc4smp(smp);
+ // CHECK-NOT: call %opencl.sampler_t addrspace(2)* @__translate_sampler_initializer(i32 19)
+ // CHECK: [[SAMP:%[0-9]+]] = load %opencl.sampler_t addrspace(2)*, %opencl.sampler_t addrspace(2)** [[smp_ptr]]
+ // CHECK: call spir_func void @fnc4smp(%opencl.sampler_t addrspace(2)* [[SAMP]])
+
+ // Case 1b
+ fnc4smp(smp);
+ // CHECK-NOT: call %opencl.sampler_t addrspace(2)* @__translate_sampler_initializer(i32 19)
+ // CHECK: [[SAMP:%[0-9]+]] = load %opencl.sampler_t addrspace(2)*, %opencl.sampler_t addrspace(2)** [[smp_ptr]]
+ // CHECK: call spir_func void @fnc4smp(%opencl.sampler_t addrspace(2)* [[SAMP]])
+
+ // Case 1a
+ fnc4smp(glb_smp);
+ // CHECK: [[SAMP:%[0-9]+]] = call %opencl.sampler_t addrspace(2)* @__translate_sampler_initializer(i32 35)
+ // CHECK: call spir_func void @fnc4smp(%opencl.sampler_t addrspace(2)* [[SAMP]])
+
+ // Case 1c
+ fnc4smp(smp_par);
+ // CHECK: [[SAMP:%[0-9]+]] = load %opencl.sampler_t addrspace(2)*, %opencl.sampler_t addrspace(2)** [[smp_par_ptr]]
+ // CHECK: call spir_func void @fnc4smp(%opencl.sampler_t addrspace(2)* [[SAMP]])
+}
diff --git a/test/CodeGenOpenCL/size_t.cl b/test/CodeGenOpenCL/size_t.cl
new file mode 100644
index 000000000000..ed941e01852d
--- /dev/null
+++ b/test/CodeGenOpenCL/size_t.cl
@@ -0,0 +1,110 @@
+// 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
+
+//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
+size_t test_ptrtoint_private(private char* x) {
+ return (size_t)x;
+}
+
+//SZ32: define{{.*}} i32 @test_ptrtoint_global(i8 addrspace(1)* %x)
+//SZ32: ptrtoint i8 addrspace(1)* %{{.*}} to i32
+//SZ64: define{{.*}} i64 @test_ptrtoint_global(i8 addrspace(1)* %x)
+//SZ64: ptrtoint i8 addrspace(1)* %{{.*}} to i64
+intptr_t test_ptrtoint_global(global char* x) {
+ return (intptr_t)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
+uintptr_t test_ptrtoint_constant(constant char* x) {
+ return (uintptr_t)x;
+}
+
+//SZ32: define{{.*}} i32 @test_ptrtoint_local(i8 addrspace(3)* %x)
+//SZ32: ptrtoint i8 addrspace(3)* %{{.*}} to i32
+//SZ64: define{{.*}} i64 @test_ptrtoint_local(i8 addrspace(3)* %x)
+//SZ64: ptrtoint i8 addrspace(3)* %{{.*}} to i64
+size_t test_ptrtoint_local(local char* x) {
+ return (size_t)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
+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: inttoptr i64 %{{.*}} to i8*
+private char* test_inttoptr_private(size_t x) {
+ return (private char*)x;
+}
+
+//SZ32: define{{.*}} i8 addrspace(1)* @test_inttoptr_global(i32 %x)
+//SZ32: inttoptr i32 %{{.*}} to i8 addrspace(1)*
+//SZ64: define{{.*}} i8 addrspace(1)* @test_inttoptr_global(i64 %x)
+//SZ64: inttoptr i64 %{{.*}} to i8 addrspace(1)*
+global char* test_inttoptr_global(size_t x) {
+ return (global char*)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
+//SZ64ONLY: getelementptr inbounds i8, i8 addrspace(3)* %{{.*}}, i64
+local char* test_add_local(local char* x, ptrdiff_t y) {
+ return x + y;
+}
+
+//SZ32: define{{.*}} i8 addrspace(1)* @test_add_global(i8 addrspace(1)* %x, i32 %y)
+//SZ32: getelementptr inbounds i8, i8 addrspace(1)* %{{.*}}, i32
+//SZ64: define{{.*}} i8 addrspace(1)* @test_add_global(i8 addrspace(1)* %x, i64 %y)
+//SZ64: getelementptr inbounds i8, i8 addrspace(1)* %{{.*}}, i64
+global char* test_add_global(global char* x, ptrdiff_t y) {
+ return x + y;
+}
+
+//SZ32: define{{.*}} i32 @test_sub_local(i8 addrspace(3)* %x, i8 addrspace(3)* %y)
+//SZ32: ptrtoint i8 addrspace(3)* %{{.*}} to i32
+//SZ32: ptrtoint i8 addrspace(3)* %{{.*}} to i32
+//SZ64: define{{.*}} i64 @test_sub_local(i8 addrspace(3)* %x, i8 addrspace(3)* %y)
+//SZ64: ptrtoint i8 addrspace(3)* %{{.*}} to i64
+//SZ64: ptrtoint i8 addrspace(3)* %{{.*}} to i64
+ptrdiff_t test_sub_local(local char* x, local char *y) {
+ return x - 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
+ptrdiff_t test_sub_private(private char* x, private char *y) {
+ return x - 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
+ptrdiff_t test_sub_mix(private char* x, generic char *y) {
+ return x - y;
+}
+
diff --git a/test/CodeGenOpenCL/spir_version.cl b/test/CodeGenOpenCL/spir_version.cl
index 215b4d7a4023..8a191282b3c7 100644
--- a/test/CodeGenOpenCL/spir_version.cl
+++ b/test/CodeGenOpenCL/spir_version.cl
@@ -1,18 +1,34 @@
-// RUN: %clang_cc1 %s -triple "spir-unknown-unknown" -emit-llvm -o - | FileCheck %s --check-prefix=CL10
-// RUN: %clang_cc1 %s -triple "spir-unknown-unknown" -emit-llvm -o - -cl-std=CL1.2 | FileCheck %s --check-prefix=CL12
-// RUN: %clang_cc1 %s -triple "spir-unknown-unknown" -emit-llvm -o - -cl-std=CL2.0 | FileCheck %s --check-prefix=CL20
-// RUN: %clang_cc1 %s -triple "spir64-unknown-unknown" -emit-llvm -o - | FileCheck %s --check-prefix=CL10
-// RUN: %clang_cc1 %s -triple "spir64-unknown-unknown" -emit-llvm -o - -cl-std=CL1.2 | FileCheck %s --check-prefix=CL12
-// RUN: %clang_cc1 %s -triple "spir64-unknown-unknown" -emit-llvm -o - -cl-std=CL2.0 | FileCheck %s --check-prefix=CL20
+// RUN: %clang_cc1 %s -triple "spir-unknown-unknown" -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-SPIR-CL10
+// RUN: %clang_cc1 %s -triple "spir-unknown-unknown" -emit-llvm -o - -cl-std=CL1.2 | FileCheck %s --check-prefix=CHECK-SPIR-CL12
+// RUN: %clang_cc1 %s -triple "spir-unknown-unknown" -emit-llvm -o - -cl-std=CL2.0 | FileCheck %s --check-prefix=CHECK-SPIR-CL20
+// RUN: %clang_cc1 %s -triple "spir64-unknown-unknown" -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-SPIR-CL10
+// RUN: %clang_cc1 %s -triple "spir64-unknown-unknown" -emit-llvm -o - -cl-std=CL1.2 | FileCheck %s --check-prefix=CHECK-SPIR-CL12
+// RUN: %clang_cc1 %s -triple "spir64-unknown-unknown" -emit-llvm -o - -cl-std=CL2.0 | FileCheck %s --check-prefix=CHECK-SPIR-CL20
+
+// RUN: %clang_cc1 %s -triple "amdgcn--amdhsa" -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-AMDGCN-CL10
+// RUN: %clang_cc1 %s -triple "amdgcn--amdhsa" -emit-llvm -o - -cl-std=CL1.2 | FileCheck %s --check-prefix=CHECK-AMDGCN-CL12
+// RUN: %clang_cc1 %s -triple "amdgcn--amdhsa" -emit-llvm -o - -cl-std=CL2.0 | FileCheck %s --check-prefix=CHECK-AMDGCN-CL20
+
kernel void foo() {}
-// CL10: !opencl.spir.version = !{[[SPIR:![0-9]+]]}
-// CL10: !opencl.ocl.version = !{[[OCL:![0-9]+]]}
-// CL10: [[SPIR]] = !{i32 2, i32 0}
-// CL10: [[OCL]] = !{i32 1, i32 0}
-// CL12: !opencl.spir.version = !{[[SPIR:![0-9]+]]}
-// CL12: !opencl.ocl.version = !{[[OCL:![0-9]+]]}
-// CL12: [[SPIR]] = !{i32 2, i32 0}
-// CL12: [[OCL]] = !{i32 1, i32 2}
-// CL20: !opencl.spir.version = !{[[SPIR:![0-9]+]]}
-// CL20: !opencl.ocl.version = !{[[SPIR:![0-9]+]]}
-// CL20: [[SPIR]] = !{i32 2, i32 0}
+
+// CHECK-SPIR-CL10: !opencl.spir.version = !{[[SPIR:![0-9]+]]}
+// CHECK-SPIR-CL10: !opencl.ocl.version = !{[[OCL:![0-9]+]]}
+// CHECK-SPIR-CL10: [[SPIR]] = !{i32 1, i32 2}
+// CHECK-SPIR-CL10: [[OCL]] = !{i32 1, i32 0}
+// CHECK-SPIR-CL12: !opencl.spir.version = !{[[VER:![0-9]+]]}
+// CHECK-SPIR-CL12: !opencl.ocl.version = !{[[VER]]}
+// CHECK-SPIR-CL12: [[VER]] = !{i32 1, i32 2}
+
+// CHECK-SPIR-CL20: !opencl.spir.version = !{[[VER:![0-9]+]]}
+// CHECK-SPIR-CL20: !opencl.ocl.version = !{[[VER]]}
+// CHECK-SPIR-CL20: [[VER]] = !{i32 2, i32 0}
+
+// CHECK-AMDGCN-CL10-NOT: !opencl.spir.version
+// CHECK-AMDGCN-CL10: !opencl.ocl.version = !{[[OCL:![0-9]+]]}
+// CHECK-AMDGCN-CL10: [[OCL]] = !{i32 1, i32 0}
+// CHECK-AMDGCN-CL12-NOT: !opencl.spir.version
+// CHECK-AMDGCN-CL12: !opencl.ocl.version = !{[[OCL:![0-9]+]]}
+// CHECK-AMDGCN-CL12: [[OCL]] = !{i32 1, i32 2}
+// CHECK-AMDGCN-CL20-NOT: !opencl.spir.version
+// CHECK-AMDGCN-CL20: !opencl.ocl.version = !{[[OCL:![0-9]+]]}
+// CHECK-AMDGCN-CL20: [[OCL]] = !{i32 2, i32 0}
diff --git a/test/CodeGenOpenCL/str_literals.cl b/test/CodeGenOpenCL/str_literals.cl
index 1c0acd155dac..8fe5cefc8d75 100644
--- a/test/CodeGenOpenCL/str_literals.cl
+++ b/test/CodeGenOpenCL/str_literals.cl
@@ -3,7 +3,7 @@
__constant char * __constant x = "hello world";
__constant char * __constant y = "hello world";
-// CHECK: unnamed_addr addrspace(3) constant
-// CHECK-NOT: addrspace(3) unnamed_addr constant
-// CHECK: @x = addrspace(3) constant i8 addrspace(3)*
-// CHECK: @y = addrspace(3) constant i8 addrspace(3)*
+// CHECK: unnamed_addr addrspace(2) constant
+// CHECK-NOT: addrspace(2) unnamed_addr constant
+// CHECK: @x = addrspace(2) constant i8 addrspace(2)*
+// CHECK: @y = addrspace(2) constant i8 addrspace(2)*
diff --git a/test/CodeGenOpenCL/unroll-hint.cl b/test/CodeGenOpenCL/unroll-hint.cl
index a86762e02b54..6a9ba87a5eb0 100644
--- a/test/CodeGenOpenCL/unroll-hint.cl
+++ b/test/CodeGenOpenCL/unroll-hint.cl
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -emit-llvm -O0 -cl-std=CL2.0 -o - %s | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -O0 -cl-std=CL1.2 -o - %s | FileCheck %s
/*** for ***/
void for_count()
diff --git a/test/Coverage/ast-print-func.cpp b/test/Coverage/ast-print-func.cpp
new file mode 100644
index 000000000000..46083a75de42
--- /dev/null
+++ b/test/Coverage/ast-print-func.cpp
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -ast-print -std=c++14 %s -o %t.1.cpp
+// RUN: %clang_cc1 -ast-print -std=c++14 %t.1.cpp -o %t.2.cpp
+// RUN: diff %t.1.cpp %t.2.cpp
+
+auto func_01(int, char) -> double;
+
+auto func_02(int x) -> int { return 2 + x; }
+
+void func_03() {
+ extern void g(), h();
+ return;
+}
diff --git a/test/Coverage/ast-print-temp-class.cpp b/test/Coverage/ast-print-temp-class.cpp
new file mode 100644
index 000000000000..f6b94efb927f
--- /dev/null
+++ b/test/Coverage/ast-print-temp-class.cpp
@@ -0,0 +1,64 @@
+// RUN: %clang_cc1 -ast-print -std=c++14 %s -v -o %t.1.cpp
+// RUN: %clang_cc1 -ast-print -std=c++14 %t.1.cpp -o %t.2.cpp
+// RUN: diff %t.1.cpp %t.2.cpp
+
+// Specializations
+
+template<typename T> class C0 {};
+template<> class C0<long> {};
+template<> class C0<long*> {};
+C0<int> c0;
+
+template<int N> class C1 {};
+template<> class C1<11> {};
+C1<2> c1a;
+C1<4> c1b;
+
+template<typename T> class C2a {};
+template<typename T> class C2b {};
+template<template<typename T> class TC> class C2 {};
+template<> class C2<C2a> {};
+C2<C2b> c2;
+
+
+// Default arguments
+
+template<typename T = int> class C10 {};
+template<int N = 10> class C11 {};
+template<typename T, int N = 22> class C12a {};
+//FIXME: template<template<typename T, int N> class TC = C12a> class C12 {};
+//FIXME: template<template<typename T> class TC = C12a> class C13 {};
+
+
+// Partial specializations
+
+template<typename T, typename U> struct C20 {
+ T a;
+ U b;
+};
+template<typename T> struct C20<T, int> {
+ T a;
+};
+
+template<int N, typename U> struct C21 {
+ U a;
+ U b[N];
+};
+template<int N> struct C21<N, int> {
+ int a[N];
+};
+
+template<template<typename T2> class TC, typename U> struct C22 {
+ TC<U> a;
+ U b;
+};
+template<template<typename T2> class TC> struct C22<TC, int> {
+ TC<int> a;
+};
+
+
+// Declaration only
+template<typename T> class C30;
+template<> class C30<long>;
+template<> class C30<long*>;
+extern C30<int> c30;
diff --git a/test/Coverage/ast-print-temp-func.cpp b/test/Coverage/ast-print-temp-func.cpp
new file mode 100644
index 000000000000..37c8298b7756
--- /dev/null
+++ b/test/Coverage/ast-print-temp-func.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -ast-print -std=c++14 %s -o %t.1.cpp
+// RUN: %clang_cc1 -ast-print -std=c++14 %t.1.cpp -o %t.2.cpp
+// RUN: diff %t.1.cpp %t.2.cpp
+
+template<typename T> void func_01();
+template<typename T> void func_01() {}
+template<> void func_01<int>() {}
+template<> void func_01<long>() {}
+template<typename T> void func_01();
+
+void main_01() {
+ func_01<int*>();
+ func_01<char>();
+}
+
+template<typename T> void func_02();
+template<typename T> void func_02();
+template<> void func_02<int>();
+template<> void func_02<long>();
+template<typename T> void func_02();
+
+void main_02() {
+ func_02<int*>();
+ func_02<char>();
+}
diff --git a/test/Coverage/ast-printing.c b/test/Coverage/ast-printing.c
index ecaf3abeaa8a..eb22f92e66d7 100644
--- a/test/Coverage/ast-printing.c
+++ b/test/Coverage/ast-printing.c
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only %s
-// RUN: %clang_cc1 -ast-print %s
+// RUN: %clang_cc1 -ast-print %s -o %t.1.c
+// RUN: %clang_cc1 -ast-print %t.1.c -o %t.2.c
+// RUN: diff %t.1.c %t.2.c
// RUN: %clang_cc1 -ast-dump %s
// RUN: %clang_cc1 -print-decl-contexts %s
diff --git a/test/Coverage/ast-printing.cpp b/test/Coverage/ast-printing.cpp
index 3205078758f1..5cff09defcff 100644
--- a/test/Coverage/ast-printing.cpp
+++ b/test/Coverage/ast-printing.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only %s
-// RUN: %clang_cc1 -ast-print %s
+// RUN: %clang_cc1 -ast-print %s -o %t.1.cpp
+// RUN: %clang_cc1 -ast-print %t.1.cpp -o %t.2.cpp
+// RUN: diff %t.1.cpp %t.2.cpp
// RUN: %clang_cc1 -ast-dump %s
// RUN: %clang_cc1 -print-decl-contexts %s
// RUN: %clang_cc1 -fdump-record-layouts %s
diff --git a/test/CoverageMapping/abspath.cpp b/test/CoverageMapping/abspath.cpp
new file mode 100644
index 000000000000..667172e32cf4
--- /dev/null
+++ b/test/CoverageMapping/abspath.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -fprofile-instrument=clang -fcoverage-mapping -emit-llvm -main-file-name abspath.cpp %S/Inputs/../abspath.cpp -o - | FileCheck -check-prefix=RMDOTS %s
+
+// RMDOTS: @__llvm_coverage_mapping = {{.*}}"\01
+// RMDOTS-NOT: Inputs
+// RMDOTS: "
+
+// RUN: cd %T && mkdir -p test && cd test
+// RUN: echo "void f1() {}" > f1.c
+// RUN: %clang_cc1 -fprofile-instrument=clang -fcoverage-mapping -emit-llvm -main-file-name abspath.cpp ../test/f1.c -o - | FileCheck -check-prefix=RELPATH %s
+
+// RELPATH: @__llvm_coverage_mapping = {{.*}}"\01
+// RELPATH: {{[/\\]}}{{.*}}{{[/\\][^/\\]*}}test{{[/\\][^/\\]*}}f1.c
+// RELPATH: "
+
+void f1() {}
diff --git a/test/CoverageMapping/if.c b/test/CoverageMapping/if.cpp
index 69544f68cfe2..95e6d8abe63e 100644
--- a/test/CoverageMapping/if.c
+++ b/test/CoverageMapping/if.cpp
@@ -1,5 +1,16 @@
-// RUN: %clang_cc1 -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only -main-file-name if.c %s | FileCheck %s
+// RUN: %clang_cc1 -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only -std=c++1z -triple %itanium_abi_triple -main-file-name if.cpp %s | FileCheck %s
+int nop() { return 0; }
+
+// CHECK-LABEL: _Z3foov:
+void foo() { // CHECK-NEXT: [[@LINE]]:12 -> [[@LINE+5]]:2 = #0
+ if (int j = true ? nop() // CHECK-NEXT: [[@LINE]]:22 -> [[@LINE]]:27 = #2
+ : nop(); // CHECK-NEXT: [[@LINE]]:22 -> [[@LINE]]:27 = (#0 - #2)
+ j) // CHECK-NEXT: [[@LINE]]:7 -> [[@LINE]]:8 = #0
+ ++j; // CHECK-NEXT: [[@LINE]]:5 -> [[@LINE]]:8 = #1
+}
+
+// CHECK-LABEL: main:
int main() { // CHECK: File 0, [[@LINE]]:12 -> {{[0-9]+}}:2 = #0
int i = 0;
// CHECK-NEXT: File 0, [[@LINE+1]]:6 -> [[@LINE+1]]:12 = #0
diff --git a/test/CoverageMapping/macroception.c b/test/CoverageMapping/macroception.c
index 784874164187..7c142ef5afde 100644
--- a/test/CoverageMapping/macroception.c
+++ b/test/CoverageMapping/macroception.c
@@ -11,7 +11,6 @@
int main() M1
return 0;
}
-// CHECK-NEXT: File 1, 4:12 -> 4:14 = #0
// CHECK-NEXT: Expansion,File 1, 4:12 -> 4:14 = #0
// CHECK-NEXT: File 2, 3:12 -> 3:13 = #0
@@ -21,7 +20,6 @@ int main() M1
void func2() {
int x = 0;
M11
-// CHECK-NEXT: File 1, 6:13 -> 6:16 = #0
// CHECK-NEXT: Expansion,File 1, 6:13 -> 6:16 = #0
// CHECK-NEXT: File 2, 5:13 -> 5:14 = #0
@@ -32,9 +30,7 @@ M11
void func3() M1
int x = 0;
M11
-// CHECK-NEXT: File 1, 4:12 -> 4:14 = #0
// CHECK-NEXT: Expansion,File 1, 4:12 -> 4:14 = #0
-// CHECK-NEXT: File 2, 6:13 -> 6:16 = #0
// CHECK-NEXT: Expansion,File 2, 6:13 -> 6:16 = #0
// CHECK-NEXT: File 3, 3:12 -> 3:13 = #0
// CHECK-NEXT: File 4, 5:13 -> 5:14 = #0
@@ -44,9 +40,7 @@ M11
// CHECK-NEXT: File 0, [[@LINE+2]]:16 -> [[@LINE+2]]:20 = #0
// CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:17 -> [[@LINE+1]]:20 = #0
void func4() M1 M11
-// CHECK-NEXT: File 1, 4:12 -> 4:14 = #0
// CHECK-NEXT: Expansion,File 1, 4:12 -> 4:14 = #0
-// CHECK-NEXT: File 2, 6:13 -> 6:16 = #0
// CHECK-NEXT: Expansion,File 2, 6:13 -> 6:16 = #0
// CHECK-NEXT: File 3, 3:12 -> 3:13 = #0
// CHECK-NEXT: File 4, 5:13 -> 5:14 = #0
diff --git a/test/CoverageMapping/macros.c b/test/CoverageMapping/macros.c
index f6339614397b..60164be91d7c 100644
--- a/test/CoverageMapping/macros.c
+++ b/test/CoverageMapping/macros.c
@@ -3,6 +3,7 @@
#define MACRO return; bar()
#define MACRO_2 bar()
#define MACRO_1 return; MACRO_2
+#define MACRO_3 MACRO_2
void bar() {}
@@ -24,7 +25,6 @@ void func2() { // CHECK-NEXT: File 0, [[@LINE]]:14 -> [[@LINE+5]]:2 = #0
i = 2;
}
// CHECK-NEXT: File 1, 5:17 -> 5:32 = #0
-// CHECK-NEXT: File 1, 5:25 -> 5:32 = 0
// CHECK-NEXT: Expansion,File 1, 5:25 -> 5:32 = 0
// CHECK-NEXT: File 2, 4:17 -> 4:22 = 0
@@ -36,8 +36,29 @@ void func3() { // CHECK-NEXT: File 0, [[@LINE]]:14 -> [[@LINE+3]]:2 = #0
// CHECK-NEXT: File 1, 4:17 -> 4:22 = #0
// CHECK-NEXT: File 2, 4:17 -> 4:22 = #0
+// CHECK-NEXT: func4
+void func4() { // CHECK-NEXT: File 0, [[@LINE]]:14 -> [[@LINE+6]]:2 = #0
+ int i = 0;
+ while (i++ < 10) // CHECK-NEXT: File 0, [[@LINE]]:10 -> [[@LINE]]:18 = (#0 + #1)
+ if (i < 5) // CHECK-NEXT: File 0, [[@LINE]]:5 -> [[@LINE+2]]:14 = #1
+ // CHECK-NEXT: File 0, [[@LINE-1]]:9 -> [[@LINE-1]]:14 = #1
+ MACRO_2; // CHECK-NEXT: Expansion,File 0, [[@LINE]]:7 -> [[@LINE]]:14 = #2
+}
+// CHECK-NEXT: File 1, 4:17 -> 4:22 = #2
+// CHECK-NOT: File 1
+
+// CHECK-NEXT: func5
+void func5() { // CHECK-NEXT: File 0, [[@LINE]]:14 -> [[@LINE+4]]:2 = #0
+ int i = 0;
+ if (i > 5) // CHECK-NEXT: File 0, [[@LINE]]:7 -> [[@LINE]]:12 = #0
+ MACRO_3; // CHECK-NEXT: Expansion,File 0, [[@LINE]]:5 -> [[@LINE]]:12 = #1
+}
+// CHECK-NEXT: Expansion,File 1, 6:17 -> 6:24 = #1
+// CHECK-NEXT: File 2, 4:17 -> 4:22 = #1
+
int main(int argc, const char *argv[]) {
func();
func2();
func3();
+ func4();
}
diff --git a/test/CoverageMapping/switch.c b/test/CoverageMapping/switch.cpp
index 6aa2b31426f1..312f26ca16e4 100644
--- a/test/CoverageMapping/switch.c
+++ b/test/CoverageMapping/switch.cpp
@@ -1,44 +1,53 @@
-// RUN: %clang_cc1 -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only -main-file-name switch.c %s | FileCheck %s
+// RUN: %clang_cc1 -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only -std=c++1z -triple %itanium_abi_triple -main-file-name switch.cpp %s | FileCheck %s
+
// CHECK: foo
void foo(int i) { // CHECK-NEXT: File 0, [[@LINE]]:17 -> [[@LINE+8]]:2 = #0
- switch(i) { // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+5]]:4 = #1
+ switch(i) {
case 1: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+3]]:10 = #2
return;
case 2: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:10 = #3
break;
}
- int x = 0;
+ int x = 0; // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:2 = #1
}
-void nop() {}
+int nop() { return 0; }
// CHECK: bar
void bar(int i) { // CHECK-NEXT: File 0, [[@LINE]]:17 -> [[@LINE+20]]:2 = #0
- switch (i) // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:6 = #1
+ switch (i)
; // CHECK-NEXT: File 0, [[@LINE]]:5 -> [[@LINE]]:6 = 0
- switch (i) { // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:4 = #2
+ switch (i) { // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+16]]:2 = #1
}
- switch (i) // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:10 = #3
+ switch (i) // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+13]]:2 = #2
nop(); // CHECK-NEXT: File 0, [[@LINE]]:5 -> [[@LINE]]:10 = 0
- switch (i) // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+2]]:10 = #4
+ switch (i) // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+10]]:2 = #3
case 1: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:10 = #5
nop();
- switch (i) { // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+4]]:4 = #6
+ switch (i) { // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+6]]:2 = #4
nop(); // CHECK-NEXT: File 0, [[@LINE]]:5 -> [[@LINE+2]]:10 = 0
case 1: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:10 = #7
nop();
}
- nop();
+ nop(); // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:2 = #6
+}
+
+ // CHECK: baz
+void baz() { // CHECK-NEXT: File 0, [[@LINE]]:12 -> [[@LINE+5]]:2 = #0
+ switch (int i = true ? nop() // CHECK-NEXT: [[@LINE]]:26 -> [[@LINE]]:31 = #2
+ : nop(); // CHECK-NEXT: [[@LINE]]:26 -> [[@LINE]]:31 = (#0 - #2)
+ i) {}
+ nop(); // CHECK-NEXT: [[@LINE]]:3 -> [[@LINE+1]]:2 = #1
}
// CHECK-NEXT: main
-int main() { // CHECK-NEXT: File 0, [[@LINE]]:12 -> [[@LINE+34]]:2 = #0
+int main() { // CHECK-NEXT: File 0, [[@LINE]]:12 -> [[@LINE+35]]:2 = #0
int i = 0;
- switch(i) { // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+9]]:4 = #1
+ switch(i) {
case 0: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+7]]:10 = #2
i = 1;
break;
@@ -48,7 +57,7 @@ int main() { // CHECK-NEXT: File 0, [[@LINE]]:12 -> [[@LINE+34]]:2 = #0
default: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:10 = #4
break;
}
- switch(i) { // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+8]]:4 = #5
+ switch(i) { // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+23]]:2 = #1
case 0: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+6]]:10 = #6
i = 1;
break;
@@ -58,7 +67,7 @@ int main() { // CHECK-NEXT: File 0, [[@LINE]]:12 -> [[@LINE+34]]:2 = #0
break;
}
- switch(i) { // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+7]]:4 = #9
+ switch(i) { // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+13]]:2 = #5
case 1: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+5]]:11 = #10
case 2: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+4]]:11 = (#10 + #11)
i = 11;
@@ -67,7 +76,8 @@ int main() { // CHECK-NEXT: File 0, [[@LINE]]:12 -> [[@LINE+34]]:2 = #0
i = 99;
}
- foo(1);
+ foo(1); // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+3]]:11 = #9
bar(1);
+ baz();
return 0;
}
diff --git a/test/CoverageMapping/switchmacro.c b/test/CoverageMapping/switchmacro.c
index f83d26fd1688..55f93d8f60c0 100644
--- a/test/CoverageMapping/switchmacro.c
+++ b/test/CoverageMapping/switchmacro.c
@@ -4,7 +4,7 @@
// CHECK: foo
int foo(int i) { // CHECK-NEXT: File 0, [[@LINE]]:16 -> {{[0-9]+}}:2 = #0
- switch (i) { // CHECK-NEXT: File 0, [[@LINE]]:3 -> {{[0-9]+}}:4 = #1
+ switch (i) {
default: // CHECK-NEXT: File 0, [[@LINE]]:3 -> {{[0-9]+}}:11 = #2
if (i == 1) // CHECK-NEXT: File 0, [[@LINE]]:9 -> [[@LINE]]:15 = #2
return 0; // CHECK-NEXT: File 0, [[@LINE]]:7 -> [[@LINE]]:15 = #3
diff --git a/test/Driver/Inputs/CUDA/usr/local/cuda/nvvm/libdevice/libdevice.compute_20.10.bc b/test/Driver/Inputs/CUDA-macosx/usr/local/cuda/bin/.keep
index e69de29bb2d1..e69de29bb2d1 100644
--- a/test/Driver/Inputs/CUDA/usr/local/cuda/nvvm/libdevice/libdevice.compute_20.10.bc
+++ b/test/Driver/Inputs/CUDA-macosx/usr/local/cuda/bin/.keep
diff --git a/test/Driver/Inputs/basic_android_tree/lib/gcc/mipsel-linux-android/4.4.3/mips-r6/crtbegin.o b/test/Driver/Inputs/CUDA-macosx/usr/local/cuda/include/.keep
index e69de29bb2d1..e69de29bb2d1 100644
--- a/test/Driver/Inputs/basic_android_tree/lib/gcc/mipsel-linux-android/4.4.3/mips-r6/crtbegin.o
+++ b/test/Driver/Inputs/CUDA-macosx/usr/local/cuda/include/.keep
diff --git a/test/Driver/Inputs/basic_android_tree/lib/gcc/mipsel-linux-android/4.4.3/mips-r6/crtbeginS.o b/test/Driver/Inputs/CUDA-macosx/usr/local/cuda/lib/.keep
index e69de29bb2d1..e69de29bb2d1 100644
--- a/test/Driver/Inputs/basic_android_tree/lib/gcc/mipsel-linux-android/4.4.3/mips-r6/crtbeginS.o
+++ b/test/Driver/Inputs/CUDA-macosx/usr/local/cuda/lib/.keep
diff --git a/test/Driver/Inputs/basic_android_tree/lib/gcc/mipsel-linux-android/4.4.3/mips-r6/crtbeginT.o b/test/Driver/Inputs/CUDA-macosx/usr/local/cuda/nvvm/libdevice/libdevice.compute_30.10.bc
index e69de29bb2d1..e69de29bb2d1 100644
--- a/test/Driver/Inputs/basic_android_tree/lib/gcc/mipsel-linux-android/4.4.3/mips-r6/crtbeginT.o
+++ b/test/Driver/Inputs/CUDA-macosx/usr/local/cuda/nvvm/libdevice/libdevice.compute_30.10.bc
diff --git a/test/Driver/Inputs/basic_android_tree/lib/gcc/mipsel-linux-android/4.4.3/mips-r6/crtend.o b/test/Driver/Inputs/CUDA-macosx/usr/local/cuda/nvvm/libdevice/libdevice.compute_35.10.bc
index e69de29bb2d1..e69de29bb2d1 100644
--- a/test/Driver/Inputs/basic_android_tree/lib/gcc/mipsel-linux-android/4.4.3/mips-r6/crtend.o
+++ b/test/Driver/Inputs/CUDA-macosx/usr/local/cuda/nvvm/libdevice/libdevice.compute_35.10.bc
diff --git a/test/Driver/Inputs/basic_android_tree/lib/gcc/mipsel-linux-android/4.4.3/mips-r6/crtendS.o b/test/Driver/Inputs/CUDA/usr/local/cuda/nvvm/libdevice/libdevice.compute_30.10.bc
index e69de29bb2d1..e69de29bb2d1 100644
--- a/test/Driver/Inputs/basic_android_tree/lib/gcc/mipsel-linux-android/4.4.3/mips-r6/crtendS.o
+++ b/test/Driver/Inputs/CUDA/usr/local/cuda/nvvm/libdevice/libdevice.compute_30.10.bc
diff --git a/test/Driver/Inputs/CUDA_80/usr/local/cuda/nvvm/libdevice/libdevice.compute_30.10.bc b/test/Driver/Inputs/CUDA_80/usr/local/cuda/nvvm/libdevice/libdevice.compute_30.10.bc
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/CUDA_80/usr/local/cuda/nvvm/libdevice/libdevice.compute_30.10.bc
diff --git a/test/Driver/Inputs/CUDA_80/usr/local/cuda/nvvm/libdevice/libdevice.compute_50.10.bc b/test/Driver/Inputs/CUDA_80/usr/local/cuda/nvvm/libdevice/libdevice.compute_50.10.bc
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/CUDA_80/usr/local/cuda/nvvm/libdevice/libdevice.compute_50.10.bc
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/lib/gcc/mips64el-linux-android/4.9/32/mips-r1/crtbegin.o b/test/Driver/Inputs/basic_android_ndk_tree/lib/gcc/mips64el-linux-android/4.9/32/mips-r1/crtbegin.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/lib/gcc/mips64el-linux-android/4.9/32/mips-r1/crtbegin.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/lib/gcc/mips64el-linux-android/4.9/32/mips-r1/crtend.o b/test/Driver/Inputs/basic_android_ndk_tree/lib/gcc/mips64el-linux-android/4.9/32/mips-r1/crtend.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/lib/gcc/mips64el-linux-android/4.9/32/mips-r1/crtend.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/lib/gcc/mips64el-linux-android/4.9/32/mips-r2/crtbegin.o b/test/Driver/Inputs/basic_android_ndk_tree/lib/gcc/mips64el-linux-android/4.9/32/mips-r2/crtbegin.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/lib/gcc/mips64el-linux-android/4.9/32/mips-r2/crtbegin.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/lib/gcc/mips64el-linux-android/4.9/32/mips-r2/crtend.o b/test/Driver/Inputs/basic_android_ndk_tree/lib/gcc/mips64el-linux-android/4.9/32/mips-r2/crtend.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/lib/gcc/mips64el-linux-android/4.9/32/mips-r2/crtend.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/lib/gcc/mips64el-linux-android/4.9/32/mips-r6/crtbegin.o b/test/Driver/Inputs/basic_android_ndk_tree/lib/gcc/mips64el-linux-android/4.9/32/mips-r6/crtbegin.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/lib/gcc/mips64el-linux-android/4.9/32/mips-r6/crtbegin.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/lib/gcc/mips64el-linux-android/4.9/32/mips-r6/crtend.o b/test/Driver/Inputs/basic_android_ndk_tree/lib/gcc/mips64el-linux-android/4.9/32/mips-r6/crtend.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/lib/gcc/mips64el-linux-android/4.9/32/mips-r6/crtend.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/lib/gcc/mips64el-linux-android/4.9/crtbegin.o b/test/Driver/Inputs/basic_android_ndk_tree/lib/gcc/mips64el-linux-android/4.9/crtbegin.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/lib/gcc/mips64el-linux-android/4.9/crtbegin.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/lib/gcc/mips64el-linux-android/4.9/crtend.o b/test/Driver/Inputs/basic_android_ndk_tree/lib/gcc/mips64el-linux-android/4.9/crtend.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/lib/gcc/mips64el-linux-android/4.9/crtend.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/lib/gcc/mips64el-linux-android/4.9/include/.keep b/test/Driver/Inputs/basic_android_ndk_tree/lib/gcc/mips64el-linux-android/4.9/include/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/lib/gcc/mips64el-linux-android/4.9/include/.keep
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/mips64el-linux-android/bin/.keep b/test/Driver/Inputs/basic_android_ndk_tree/mips64el-linux-android/bin/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/mips64el-linux-android/bin/.keep
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/mips64el-linux-android/lib/.keep b/test/Driver/Inputs/basic_android_ndk_tree/mips64el-linux-android/lib/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/mips64el-linux-android/lib/.keep
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/mips64el-linux-android/lib64/.keep b/test/Driver/Inputs/basic_android_ndk_tree/mips64el-linux-android/lib64/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/mips64el-linux-android/lib64/.keep
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/mips64el-linux-android/libr2/.keep b/test/Driver/Inputs/basic_android_ndk_tree/mips64el-linux-android/libr2/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/mips64el-linux-android/libr2/.keep
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/mips64el-linux-android/libr6/.keep b/test/Driver/Inputs/basic_android_ndk_tree/mips64el-linux-android/libr6/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/mips64el-linux-android/libr6/.keep
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/mipsel-linux-android/libr2/.keep b/test/Driver/Inputs/basic_android_ndk_tree/mipsel-linux-android/libr2/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/mipsel-linux-android/libr2/.keep
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/mipsel-linux-android/libr6/.keep b/test/Driver/Inputs/basic_android_ndk_tree/mipsel-linux-android/libr6/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/mipsel-linux-android/libr6/.keep
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr2/crtbegin_dynamic.o b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr2/crtbegin_dynamic.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr2/crtbegin_dynamic.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr2/crtbegin_so.o b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr2/crtbegin_so.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr2/crtbegin_so.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr2/crtbegin_static.o b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr2/crtbegin_static.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr2/crtbegin_static.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/sysroot/usr/libr2/crtend_android.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr2/crtend_android.o
diff --git a/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr2/crtend_so.o b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr2/crtend_so.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr2/crtend_so.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/sysroot/usr/libr6/crtbegin_dynamic.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr6/crtbegin_dynamic.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/sysroot/usr/libr6/crtbegin_so.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr6/crtbegin_so.o
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/libr6/crtbegin_static.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr6/crtbegin_static.o
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/libr6/crtend_android.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr6/crtend_android.o
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/libr6/crtend_so.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_ndk_tree/sysroot/usr/libr6/crtend_so.o
diff --git a/test/Driver/Inputs/basic_myriad_tree/bin/.keep b/test/Driver/Inputs/basic_myriad_tree/bin/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/basic_myriad_tree/bin/.keep
diff --git a/test/Driver/Inputs/gentoo_linux_gcc_multi_version_tree/etc/env.d/gcc/config-x86_64-pc-linux-gnu b/test/Driver/Inputs/gentoo_linux_gcc_multi_version_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_multi_version_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_multi_version_tree/etc/env.d/gcc/x86_64-pc-linux-gnu-4.9.3 b/test/Driver/Inputs/gentoo_linux_gcc_multi_version_tree/etc/env.d/gcc/x86_64-pc-linux-gnu-4.9.3
new file mode 100644
index 000000000000..9ff406284fae
--- /dev/null
+++ b/test/Driver/Inputs/gentoo_linux_gcc_multi_version_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.3"
+ROOTPATH="/usr/x86_64-pc-linux-gnu/gcc-bin/4.9.3"
+GCC_PATH="/usr/x86_64-pc-linux-gnu/gcc-bin/4.9.3"
+LDPATH="/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3:/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/32"
+MANPATH="/usr/share/gcc-data/x86_64-pc-linux-gnu/4.9.3/man"
+INFOPATH="/usr/share/gcc-data/x86_64-pc-linux-gnu/4.9.3/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_multi_version_tree/etc/gentoo-release b/test/Driver/Inputs/gentoo_linux_gcc_multi_version_tree/etc/gentoo-release
new file mode 100644
index 000000000000..5f0944f7d9a7
--- /dev/null
+++ b/test/Driver/Inputs/gentoo_linux_gcc_multi_version_tree/etc/gentoo-release
@@ -0,0 +1 @@
+Gentoo Base System release 2.3
diff --git a/test/Driver/Inputs/gentoo_linux_gcc_multi_version_tree/usr/include/.keep b/test/Driver/Inputs/gentoo_linux_gcc_multi_version_tree/usr/include/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/gentoo_linux_gcc_multi_version_tree/usr/include/.keep
diff --git a/test/Driver/Inputs/gentoo_linux_gcc_multi_version_tree/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/32/crtbegin.o b/test/Driver/Inputs/gentoo_linux_gcc_multi_version_tree/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/32/crtbegin.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/gentoo_linux_gcc_multi_version_tree/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/32/crtbegin.o
diff --git a/test/Driver/Inputs/gentoo_linux_gcc_multi_version_tree/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/crtbegin.o b/test/Driver/Inputs/gentoo_linux_gcc_multi_version_tree/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/crtbegin.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/gentoo_linux_gcc_multi_version_tree/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/crtbegin.o
diff --git a/test/Driver/Inputs/gentoo_linux_gcc_multi_version_tree/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/include/g++-v4.9.3/.keep b/test/Driver/Inputs/gentoo_linux_gcc_multi_version_tree/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/include/g++-v4.9.3/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/gentoo_linux_gcc_multi_version_tree/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/include/g++-v4.9.3/.keep
diff --git a/test/Driver/Inputs/gentoo_linux_gcc_multi_version_tree/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/x32/crtbegin.o b/test/Driver/Inputs/gentoo_linux_gcc_multi_version_tree/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/x32/crtbegin.o
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/gentoo_linux_gcc_multi_version_tree/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/x32/crtbegin.o
diff --git a/test/Driver/Inputs/gentoo_linux_gcc_multi_version_tree/usr/lib/gcc/x86_64-pc-linux-gnu/5.4.0/32/crtbegin.o b/test/Driver/Inputs/gentoo_linux_gcc_multi_version_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_multi_version_tree/usr/lib/gcc/x86_64-pc-linux-gnu/5.4.0/32/crtbegin.o
diff --git a/test/Driver/Inputs/gentoo_linux_gcc_multi_version_tree/usr/lib/gcc/x86_64-pc-linux-gnu/5.4.0/crtbegin.o b/test/Driver/Inputs/gentoo_linux_gcc_multi_version_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_multi_version_tree/usr/lib/gcc/x86_64-pc-linux-gnu/5.4.0/crtbegin.o
diff --git a/test/Driver/Inputs/gentoo_linux_gcc_multi_version_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_multi_version_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_multi_version_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_multi_version_tree/usr/lib/gcc/x86_64-pc-linux-gnu/5.4.0/x32/crtbegin.o b/test/Driver/Inputs/gentoo_linux_gcc_multi_version_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_multi_version_tree/usr/lib/gcc/x86_64-pc-linux-gnu/5.4.0/x32/crtbegin.o
diff --git a/test/Driver/Inputs/gentoo_linux_gcc_multi_version_tree/usr/x86_64-pc-linux-gnu/lib/.keep b/test/Driver/Inputs/gentoo_linux_gcc_multi_version_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_multi_version_tree/usr/x86_64-pc-linux-gnu/lib/.keep
diff --git a/test/Driver/Inputs/hexagon_tree/Tools/bin/.keep b/test/Driver/Inputs/hexagon_tree/Tools/bin/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/hexagon_tree/Tools/bin/.keep
diff --git a/test/Driver/Inputs/hexagon_tree/Tools/bin/readme b/test/Driver/Inputs/hexagon_tree/Tools/bin/readme
new file mode 100644
index 000000000000..6e2cef0143f5
--- /dev/null
+++ b/test/Driver/Inputs/hexagon_tree/Tools/bin/readme
@@ -0,0 +1,4 @@
+Git does not record empty directories. Create a dummy file in each directory
+here. Strictly speaking, putting dummy files in leaf directories should be
+sufficient, but adding them everywhere reduces the risk of repeating the same
+problem in case new directories are added.
diff --git a/test/Driver/Inputs/hexagon_tree/Tools/readme b/test/Driver/Inputs/hexagon_tree/Tools/readme
new file mode 100644
index 000000000000..6e2cef0143f5
--- /dev/null
+++ b/test/Driver/Inputs/hexagon_tree/Tools/readme
@@ -0,0 +1,4 @@
+Git does not record empty directories. Create a dummy file in each directory
+here. Strictly speaking, putting dummy files in leaf directories should be
+sufficient, but adding them everywhere reduces the risk of repeating the same
+problem in case new directories are added.
diff --git a/test/Driver/Inputs/hexagon_tree/Tools/target/.keep b/test/Driver/Inputs/hexagon_tree/Tools/target/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/hexagon_tree/Tools/target/.keep
diff --git a/test/Driver/Inputs/hexagon_tree/Tools/target/hexagon/include/c++/readme b/test/Driver/Inputs/hexagon_tree/Tools/target/hexagon/include/c++/readme
new file mode 100644
index 000000000000..6e2cef0143f5
--- /dev/null
+++ b/test/Driver/Inputs/hexagon_tree/Tools/target/hexagon/include/c++/readme
@@ -0,0 +1,4 @@
+Git does not record empty directories. Create a dummy file in each directory
+here. Strictly speaking, putting dummy files in leaf directories should be
+sufficient, but adding them everywhere reduces the risk of repeating the same
+problem in case new directories are added.
diff --git a/test/Driver/Inputs/hexagon_tree/Tools/target/hexagon/include/readme b/test/Driver/Inputs/hexagon_tree/Tools/target/hexagon/include/readme
new file mode 100644
index 000000000000..6e2cef0143f5
--- /dev/null
+++ b/test/Driver/Inputs/hexagon_tree/Tools/target/hexagon/include/readme
@@ -0,0 +1,4 @@
+Git does not record empty directories. Create a dummy file in each directory
+here. Strictly speaking, putting dummy files in leaf directories should be
+sufficient, but adding them everywhere reduces the risk of repeating the same
+problem in case new directories are added.
diff --git a/test/Driver/Inputs/hexagon_tree/Tools/target/hexagon/readme b/test/Driver/Inputs/hexagon_tree/Tools/target/hexagon/readme
new file mode 100644
index 000000000000..6e2cef0143f5
--- /dev/null
+++ b/test/Driver/Inputs/hexagon_tree/Tools/target/hexagon/readme
@@ -0,0 +1,4 @@
+Git does not record empty directories. Create a dummy file in each directory
+here. Strictly speaking, putting dummy files in leaf directories should be
+sufficient, but adding them everywhere reduces the risk of repeating the same
+problem in case new directories are added.
diff --git a/test/Driver/Inputs/hexagon_tree/Tools/target/readme b/test/Driver/Inputs/hexagon_tree/Tools/target/readme
new file mode 100644
index 000000000000..6e2cef0143f5
--- /dev/null
+++ b/test/Driver/Inputs/hexagon_tree/Tools/target/readme
@@ -0,0 +1,4 @@
+Git does not record empty directories. Create a dummy file in each directory
+here. Strictly speaking, putting dummy files in leaf directories should be
+sufficient, but adding them everywhere reduces the risk of repeating the same
+problem in case new directories are added.
diff --git a/test/Driver/Inputs/rewrite-1.map b/test/Driver/Inputs/rewrite-1.map
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/rewrite-1.map
diff --git a/test/Driver/Inputs/rewrite-2.map b/test/Driver/Inputs/rewrite-2.map
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/rewrite-2.map
diff --git a/test/Driver/Inputs/rewrite.map b/test/Driver/Inputs/rewrite.map
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Driver/Inputs/rewrite.map
diff --git a/test/Driver/XRay/lit.local.cfg b/test/Driver/XRay/lit.local.cfg
new file mode 100644
index 000000000000..34040d226150
--- /dev/null
+++ b/test/Driver/XRay/lit.local.cfg
@@ -0,0 +1,2 @@
+target_triple_components = config.target_triple.split('-')
+config.available_features.update(target_triple_components)
diff --git a/test/Driver/XRay/xray-instrument-cpu.c b/test/Driver/XRay/xray-instrument-cpu.c
new file mode 100644
index 000000000000..613342063a40
--- /dev/null
+++ b/test/Driver/XRay/xray-instrument-cpu.c
@@ -0,0 +1,4 @@
+// RUN: not %clang -o /dev/null -v -fxray-instrument -c %s
+// XFAIL: amd64-, x86_64-, x86_64h-, arm, aarch64, arm64
+// REQUIRES: linux
+typedef int a;
diff --git a/test/Driver/XRay/xray-instrument-os.c b/test/Driver/XRay/xray-instrument-os.c
new file mode 100644
index 000000000000..86b109b6dbfe
--- /dev/null
+++ b/test/Driver/XRay/xray-instrument-os.c
@@ -0,0 +1,4 @@
+// RUN: not %clang -o /dev/null -v -fxray-instrument -c %s
+// XFAIL: -linux-
+// REQUIRES-ANY: amd64, x86_64, x86_64h, arm, aarch64, arm64
+typedef int a;
diff --git a/test/Driver/aarch64-cpus.c b/test/Driver/aarch64-cpus.c
index 3a9116dde84a..88edcc5fc8d8 100644
--- a/test/Driver/aarch64-cpus.c
+++ b/test/Driver/aarch64-cpus.c
@@ -96,12 +96,52 @@
// RUN: %clang -target aarch64_be -mlittle-endian -mtune=exynos-m1 -### -c %s 2>&1 | FileCheck -check-prefix=M1 %s
// M1: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "exynos-m1"
+// RUN: %clang -target aarch64 -mcpu=exynos-m2 -### -c %s 2>&1 | FileCheck -check-prefix=M2 %s
+// RUN: %clang -target aarch64 -mlittle-endian -mcpu=exynos-m2 -### -c %s 2>&1 | FileCheck -check-prefix=M2 %s
+// RUN: %clang -target aarch64_be -mlittle-endian -mcpu=exynos-m2 -### -c %s 2>&1 | FileCheck -check-prefix=M2 %s
+// RUN: %clang -target aarch64 -mtune=exynos-m2 -### -c %s 2>&1 | FileCheck -check-prefix=M2 %s
+// RUN: %clang -target aarch64 -mlittle-endian -mtune=exynos-m2 -### -c %s 2>&1 | FileCheck -check-prefix=M2 %s
+// RUN: %clang -target aarch64_be -mlittle-endian -mtune=exynos-m2 -### -c %s 2>&1 | FileCheck -check-prefix=M2 %s
+// M2: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "exynos-m2"
+
+// RUN: %clang -target aarch64_be -mcpu=exynos-m3 -### -c %s 2>&1 | FileCheck -check-prefix=M3 %s
+// RUN: %clang -target aarch64 -mbig-endian -mcpu=exynos-m3 -### -c %s 2>&1 | FileCheck -check-prefix=M3 %s
+// RUN: %clang -target aarch64_be -mbig-endian -mcpu=exynos-m3 -### -c %s 2>&1 | FileCheck -check-prefix=M3 %s
+// RUN: %clang -target aarch64_be -mtune=exynos-m3 -### -c %s 2>&1 | FileCheck -check-prefix=M3 %s
+// RUN: %clang -target aarch64 -mbig-endian -mtune=exynos-m3 -### -c %s 2>&1 | FileCheck -check-prefix=M3 %s
+// RUN: %clang -target aarch64_be -mbig-endian -mtune=exynos-m3 -### -c %s 2>&1 | FileCheck -check-prefix=M3 %s
+// M3: "-cc1"{{.*}} "-triple" "aarch64_be{{.*}}" "-target-cpu" "exynos-m3"
+
// 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 %s
// RUN: %clang -target arm64 -mlittle-endian -mtune=exynos-m1 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-M1 %s
// ARM64-M1: "-cc1"{{.*}} "-triple" "arm64{{.*}}" "-target-cpu" "exynos-m1"
+// RUN: %clang -target arm64 -mcpu=exynos-m2 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-M2 %s
+// RUN: %clang -target arm64 -mlittle-endian -mcpu=exynos-m2 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-M2 %s
+// RUN: %clang -target arm64 -mtune=exynos-m2 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-M2 %s
+// RUN: %clang -target arm64 -mlittle-endian -mtune=exynos-m2 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-M2 %s
+// ARM64-M2: "-cc1"{{.*}} "-triple" "arm64{{.*}}" "-target-cpu" "exynos-m2"
+
+// RUN: %clang -target arm64 -mcpu=exynos-m3 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-M3 %s
+// RUN: %clang -target arm64 -mlittle-endian -mcpu=exynos-m3 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-M3 %s
+// RUN: %clang -target arm64 -mtune=exynos-m3 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-M3 %s
+// RUN: %clang -target arm64 -mlittle-endian -mtune=exynos-m3 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-M3 %s
+// ARM64-M3: "-cc1"{{.*}} "-triple" "arm64{{.*}}" "-target-cpu" "exynos-m3"
+
+// 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 %s
+// RUN: %clang -target aarch64 -mlittle-endian -mtune=falkor -### -c %s 2>&1 | FileCheck -check-prefix=FALKOR %s
+// FALKOR: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "falkor"
+
+// RUN: %clang -target arm64 -mcpu=falkor -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-FALKOR %s
+// RUN: %clang -target arm64 -mlittle-endian -mcpu=falkor -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-FALKOR %s
+// RUN: %clang -target arm64 -mtune=falkor -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-FALKOR %s
+// RUN: %clang -target arm64 -mlittle-endian -mtune=falkor -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-FALKOR %s
+// ARM64-FALKOR: "-cc1"{{.*}} "-triple" "arm64{{.*}}" "-target-cpu" "falkor"
+
// RUN: %clang -target aarch64 -mcpu=kryo -### -c %s 2>&1 | FileCheck -check-prefix=KRYO %s
// RUN: %clang -target aarch64 -mlittle-endian -mcpu=kryo -### -c %s 2>&1 | FileCheck -check-prefix=KRYO %s
// RUN: %clang -target aarch64 -mtune=kryo -### -c %s 2>&1 | FileCheck -check-prefix=KRYO %s
@@ -117,16 +157,20 @@
// RUN: %clang -target aarch64 -mcpu=vulcan -### -c %s 2>&1 | FileCheck -check-prefix=VULCAN %s
// RUN: %clang -target aarch64 -mlittle-endian -mcpu=vulcan -### -c %s 2>&1 | FileCheck -check-prefix=VULCAN %s
// RUN: %clang -target aarch64_be -mlittle-endian -mcpu=vulcan -### -c %s 2>&1 | FileCheck -check-prefix=VULCAN %s
-// RUN: %clang -target aarch64 -mtune=vulcan -### -c %s 2>&1 | FileCheck -check-prefix=VULCAN %s
-// RUN: %clang -target aarch64 -mlittle-endian -mtune=vulcan -### -c %s 2>&1 | FileCheck -check-prefix=VULCAN %s
-// RUN: %clang -target aarch64_be -mlittle-endian -mtune=vulcan -### -c %s 2>&1 | FileCheck -check-prefix=VULCAN %s
-// VULCAN: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "vulcan"
+// RUN: %clang -target aarch64 -mtune=vulcan -### -c %s 2>&1 | FileCheck -check-prefix=VULCAN-TUNE %s
+// RUN: %clang -target aarch64 -mlittle-endian -mtune=vulcan -### -c %s 2>&1 | FileCheck -check-prefix=VULCAN-TUNE %s
+// RUN: %clang -target aarch64_be -mlittle-endian -mtune=vulcan -### -c %s 2>&1 | FileCheck -check-prefix=VULCAN-TUNE %s
+// VULCAN: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "vulcan" "-target-feature" "+v8.1a"
+// VULCAN-TUNE: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "vulcan"
+// VULCAN-TUNE-NOT: +v8.1a
// RUN: %clang -target arm64 -mcpu=vulcan -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-VULCAN %s
// RUN: %clang -target arm64 -mlittle-endian -mcpu=vulcan -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-VULCAN %s
-// RUN: %clang -target arm64 -mtune=vulcan -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-VULCAN %s
-// RUN: %clang -target arm64 -mlittle-endian -mtune=vulcan -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-VULCAN %s
-// ARM64-VULCAN: "-cc1"{{.*}} "-triple" "arm64{{.*}}" "-target-cpu" "vulcan"
+// RUN: %clang -target arm64 -mtune=vulcan -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-VULCAN-TUNE %s
+// RUN: %clang -target arm64 -mlittle-endian -mtune=vulcan -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-VULCAN-TUNE %s
+// ARM64-VULCAN: "-cc1"{{.*}} "-triple" "arm64{{.*}}" "-target-cpu" "vulcan" "-target-feature" "+v8.1a"
+// ARM64-VULCAN-TUNE: "-cc1"{{.*}} "-triple" "arm64{{.*}}" "-target-cpu" "vulcan"
+// ARM64-VULCAN-TUNE-NOT: +v8.1a
// RUN: %clang -target aarch64_be -### -c %s 2>&1 | FileCheck -check-prefix=GENERIC-BE %s
// RUN: %clang -target aarch64 -mbig-endian -### -c %s 2>&1 | FileCheck -check-prefix=GENERIC-BE %s
@@ -181,6 +225,22 @@
// RUN: %clang -target aarch64_be -mbig-endian -mtune=exynos-m1 -### -c %s 2>&1 | FileCheck -check-prefix=M1-BE %s
// M1-BE: "-cc1"{{.*}} "-triple" "aarch64_be{{.*}}" "-target-cpu" "exynos-m1"
+// RUN: %clang -target aarch64_be -mcpu=exynos-m2 -### -c %s 2>&1 | FileCheck -check-prefix=M2-BE %s
+// RUN: %clang -target aarch64 -mbig-endian -mcpu=exynos-m2 -### -c %s 2>&1 | FileCheck -check-prefix=M2-BE %s
+// RUN: %clang -target aarch64_be -mbig-endian -mcpu=exynos-m2 -### -c %s 2>&1 | FileCheck -check-prefix=M2-BE %s
+// RUN: %clang -target aarch64_be -mtune=exynos-m2 -### -c %s 2>&1 | FileCheck -check-prefix=M2-BE %s
+// RUN: %clang -target aarch64 -mbig-endian -mtune=exynos-m2 -### -c %s 2>&1 | FileCheck -check-prefix=M2-BE %s
+// RUN: %clang -target aarch64_be -mbig-endian -mtune=exynos-m2 -### -c %s 2>&1 | FileCheck -check-prefix=M2-BE %s
+// M2-BE: "-cc1"{{.*}} "-triple" "aarch64_be{{.*}}" "-target-cpu" "exynos-m2"
+
+// RUN: %clang -target aarch64_be -mcpu=exynos-m3 -### -c %s 2>&1 | FileCheck -check-prefix=M3-BE %s
+// RUN: %clang -target aarch64 -mbig-endian -mcpu=exynos-m3 -### -c %s 2>&1 | FileCheck -check-prefix=M3-BE %s
+// RUN: %clang -target aarch64_be -mbig-endian -mcpu=exynos-m3 -### -c %s 2>&1 | FileCheck -check-prefix=M3-BE %s
+// RUN: %clang -target aarch64_be -mtune=exynos-m3 -### -c %s 2>&1 | FileCheck -check-prefix=M3-BE %s
+// RUN: %clang -target aarch64 -mbig-endian -mtune=exynos-m3 -### -c %s 2>&1 | FileCheck -check-prefix=M3-BE %s
+// RUN: %clang -target aarch64_be -mbig-endian -mtune=exynos-m3 -### -c %s 2>&1 | FileCheck -check-prefix=M3-BE %s
+// M3-BE: "-cc1"{{.*}} "-triple" "aarch64_be{{.*}}" "-target-cpu" "exynos-m3"
+
// RUN: %clang -target aarch64_be -mcpu=vulcan -### -c %s 2>&1 | FileCheck -check-prefix=VULCAN-BE %s
// RUN: %clang -target aarch64 -mbig-endian -mcpu=vulcan -### -c %s 2>&1 | FileCheck -check-prefix=VULCAN-BE %s
// RUN: %clang -target aarch64_be -mbig-endian -mcpu=vulcan -### -c %s 2>&1 | FileCheck -check-prefix=VULCAN-BE %s
diff --git a/test/Driver/analyzer-target-enabled-checkers.cpp b/test/Driver/analyzer-target-enabled-checkers.cpp
new file mode 100644
index 000000000000..e1706f675c3b
--- /dev/null
+++ b/test/Driver/analyzer-target-enabled-checkers.cpp
@@ -0,0 +1,60 @@
+// Tests for static analyzer checkers that the driver enables by default based
+// on the target triple.
+
+// RUN: %clang -### -target x86_64-apple-darwin10 --analyze %s 2>&1 | FileCheck --check-prefix=CHECK-DARWIN %s
+
+// CHECK-DARWIN: "-analyzer-checker=core"
+// CHECK-DARWIN-SAME: "-analyzer-checker=apiModeling"
+// CHECK-DARWIN-SAME: "-analyzer-checker=unix"
+// CHECK-DARWIN-SAME: "-analyzer-checker=osx"
+// CHECK-DARWIN-SAME: "-analyzer-checker=deadcode"
+// CHECK-DARWIN-SAME: "-analyzer-checker=cplusplus"
+// CHECK-DARWIN-SAME: "-analyzer-checker=security.insecureAPI.UncheckedReturn"
+// CHECK-DARWIN-SAME: "-analyzer-checker=security.insecureAPI.getpw"
+// CHECK-DARWIN-SAME: "-analyzer-checker=security.insecureAPI.gets"
+// CHECK-DARWIN-SAME: "-analyzer-checker=security.insecureAPI.mktemp"
+// CHECK-DARWIN-SAME: "-analyzer-checker=security.insecureAPI.mkstemp"
+// CHECK-DARWIN-SAME: "-analyzer-checker=security.insecureAPI.vfork"
+// CHECK-DARWIN-SAME: "-analyzer-checker=nullability.NullPassedToNonnull"
+// CHECK-DARWIN-SAME: "-analyzer-checker=nullability.NullReturnedFromNonnull"
+
+
+// RUN: %clang -### -target x86_64-unknown-linux --analyze %s 2>&1 | FileCheck --check-prefix=CHECK-LINUX %s
+
+// CHECK-LINUX: "-analyzer-checker=core"
+// CHECK-LINUX-SAME: "-analyzer-checker=apiModeling"
+// CHECK-LINUX-SAME: "-analyzer-checker=unix"
+// CHECK-LINUX-NOT: "-analyzer-checker=osx"
+// CHECK-LINUX-SAME: "-analyzer-checker=deadcode"
+// CHECK-LINUX-SAME: "-analyzer-checker=cplusplus"
+// CHECK-LINUX-SAME: "-analyzer-checker=security.insecureAPI.UncheckedReturn"
+// CHECK-LINUX-SAME: "-analyzer-checker=security.insecureAPI.getpw"
+// CHECK-LINUX-SAME: "-analyzer-checker=security.insecureAPI.gets"
+// CHECK-LINUX-SAME: "-analyzer-checker=security.insecureAPI.mktemp"
+// CHECK-LINUX-SAME: "-analyzer-checker=security.insecureAPI.mkstemp"
+// CHECK-LINUX-SAME: "-analyzer-checker=security.insecureAPI.vfork"
+// CHECK-LINUX-SAME: "-analyzer-checker=nullability.NullPassedToNonnull"
+// CHECK-LINUX-SAME: "-analyzer-checker=nullability.NullReturnedFromNonnull"
+
+
+// RUN: %clang -### -target x86_64-windows --analyze %s 2>&1 | FileCheck --check-prefix=CHECK-WINDOWS %s
+
+// CHECK-WINDOWS: "-analyzer-checker=core"
+// CHECK-WINDOWS-SAME: "-analyzer-checker=apiModeling"
+// CHECK-WINDOWS-SAME: "-analyzer-checker=unix.API"
+// CHECK-WINDOWS-SAME: "-analyzer-checker=unix.Malloc"
+// CHECK-WINDOWS-SAME: "-analyzer-checker=unix.MallocSizeof"
+// CHECK-WINDOWS-SAME: "-analyzer-checker=unix.MismatchedDeallocator"
+// CHECK-WINDOWS-SAME: "-analyzer-checker=unix.cstring.BadSizeArg"
+// CHECK-WINDOWS-SAME: "-analyzer-checker=unix.cstring.NullArg"
+// CHECK-WINDOWS-NOT: "-analyzer-checker=osx"
+// CHECK-WINDOWS-SAME: "-analyzer-checker=deadcode"
+// CHECK-WINDOWS-SAME: "-analyzer-checker=cplusplus"
+// CHECK-WINDOWS-SAME: "-analyzer-checker=security.insecureAPI.UncheckedReturn"
+// CHECK-WINDOWS-SAME: "-analyzer-checker=security.insecureAPI.getpw"
+// CHECK-WINDOWS-SAME: "-analyzer-checker=security.insecureAPI.gets"
+// CHECK-WINDOWS-SAME: "-analyzer-checker=security.insecureAPI.mktemp"
+// CHECK-WINDOWS-SAME: "-analyzer-checker=security.insecureAPI.mkstemp"
+// CHECK-WINDOWS-SAME: "-analyzer-checker=security.insecureAPI.vfork"
+// CHECK-WINDOWS-SAME: "-analyzer-checker=nullability.NullPassedToNonnull"
+// CHECK-WINDOWS-SAME: "-analyzer-checker=nullability.NullReturnedFromNonnull"
diff --git a/test/Driver/android-aarch64-link.cpp b/test/Driver/android-aarch64-link.cpp
new file mode 100644
index 000000000000..2c4cfb9898eb
--- /dev/null
+++ b/test/Driver/android-aarch64-link.cpp
@@ -0,0 +1,17 @@
+// Check that we automatically add relevant linker flags for Android aarch64.
+
+// RUN: %clang -target aarch64-none-linux-android \
+// RUN: -### -v %s 2> %t
+// RUN: FileCheck -check-prefix=GENERIC-ARM < %t %s
+//
+// RUN: %clang -target aarch64-none-linux-android \
+// RUN: -mcpu=cortex-a53 -### -v %s 2> %t
+// RUN: FileCheck -check-prefix=CORTEX-A53 < %t %s
+//
+// RUN: %clang -target aarch64-none-linux-android \
+// RUN: -mcpu=cortex-a57 -### -v %s 2> %t
+// RUN: FileCheck -check-prefix=CORTEX-A57 < %t %s
+//
+// GENERIC-ARM: --fix-cortex-a53-843419
+// CORTEX-A53: --fix-cortex-a53-843419
+// CORTEX-A57-NOT: --fix-cortex-a53-843419
diff --git a/test/Driver/android-ndk-standalone.cpp b/test/Driver/android-ndk-standalone.cpp
index 1ca044d58b86..7fe6d3c3c2ca 100644
--- a/test/Driver/android-ndk-standalone.cpp
+++ b/test/Driver/android-ndk-standalone.cpp
@@ -237,15 +237,14 @@
// RUN: | FileCheck --check-prefix=CHECK-MIPSR2 %s
// CHECK-MIPSR2: {{.*}}clang{{.*}}" "-cc1"
// CHECK-MIPSR2: "-internal-isystem" "{{.*}}/include/c++/4.9"
-// NOT-YET-CHECK-MIPSR2: "-internal-isystem" "{{.*}}/include/c++/4.9/mipsel-linux-android/mips-r2"
-// CHECK-MIPSR2: "-internal-isystem" "{{.*}}/include/c++/4.9/mipsel-linux-android"
+// 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"
-// CHECK-MIPSR2: "-L{{.*}}/sysroot/usr/lib"
+// 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 \
@@ -255,15 +254,48 @@
// RUN: | FileCheck --check-prefix=CHECK-MIPSR6 %s
// CHECK-MIPSR6: {{.*}}clang{{.*}}" "-cc1"
// CHECK-MIPSR6: "-internal-isystem" "{{.*}}/include/c++/4.9"
-// NOT-YET-CHECK-MIPSR6: "-internal-isystem" "{{.*}}/include/c++/4.9/mipsel-linux-android/mips-r6"
-// CHECK-MIPSR6: "-internal-isystem" "{{.*}}/include/c++/4.9/mipsel-linux-android"
+// 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"
-// CHECK-MIPSR6: "-L{{.*}}/sysroot/usr/lib"
+// 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 \
diff --git a/test/Driver/android-standalone.cpp b/test/Driver/android-standalone.cpp
index 047f1707c999..0f8cf0b1355e 100644
--- a/test/Driver/android-standalone.cpp
+++ b/test/Driver/android-standalone.cpp
@@ -93,19 +93,3 @@
// CHECK-MIPSR2-A: "-L{{.*}}/lib/gcc/mipsel-linux-android/4.4.3/mips-r2"
// CHECK-MIPSR2-A: "-L{{.*}}/lib/gcc/mipsel-linux-android/4.4.3/../../../../mipsel-linux-android/lib"
// CHECK-MIPSR2-A: "-L{{.*}}/sysroot/usr/lib"
-//
-// 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_tree \
-// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \
-// RUN: | FileCheck --check-prefix=CHECK-MIPSR6 %s
-// CHECK-MIPSR6: {{.*}}clang{{.*}}" "-cc1"
-// CHECK-MIPSR6: "-internal-isystem" "{{.*}}/mipsel-linux-android/include/c++/4.4.3"
-// CHECK-MIPSR6: "-internal-isystem" "{{.*}}/mipsel-linux-android/include/c++/4.4.3/mipsel-linux-android"
-// 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.4.3/mips-r6"
-// CHECK-MIPSR6: "-L{{.*}}/lib/gcc/mipsel-linux-android/4.4.3/../../../../mipsel-linux-android/lib"
-// CHECK-MIPSR6: "-L{{.*}}/sysroot/usr/lib"
diff --git a/test/Driver/arm-cortex-cpus.c b/test/Driver/arm-cortex-cpus.c
index 4783a10596a8..91268538e72f 100644
--- a/test/Driver/arm-cortex-cpus.c
+++ b/test/Driver/arm-cortex-cpus.c
@@ -146,6 +146,27 @@
// RUN: %clang -target arm -mlittle-endian -march=armv8-a -mlittle-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V8A %s
// CHECK-V8A: "-cc1"{{.*}} "-triple" "armv8-{{.*}}" "-target-cpu" "cortex-a53"
+// RUN: %clang -target armv8r-linux-gnueabi -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V8R %s
+// RUN: %clang -target arm -march=armv8r -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V8R %s
+// RUN: %clang -target arm -march=armv8-r -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V8R %s
+// CHECK-V8R: "-cc1"{{.*}} "-triple" "armv8r-{{.*}} "-target-cpu" "cortex-r52"
+
+// RUN: %clang -target armv8r-linux-gnueabi -mbig-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V8R-BIG %s
+// RUN: %clang -target arm -march=armv8r -mbig-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V8R-BIG %s
+// RUN: %clang -target arm -march=armv8-r -mbig-endian -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V8R-BIG %s
+// CHECK-V8R-BIG: "-cc1"{{.*}} "-triple" "armebv8r-{{.*}} "-target-cpu" "cortex-r52"
+
+// RUN: %clang -target armv8r-linux-gnueabi -mthumb -### -c %s 2>&1 | \
+// RUN: FileCheck -check-prefix=CHECK-V8R-THUMB %s
+// RUN: %clang -target arm -march=armv8r -mthumb -### -c %s 2>&1 | \
+// RUN: FileCheck -check-prefix=CHECK-V8R-THUMB %s
+// CHECK-V8R-THUMB: "-cc1"{{.*}} "-triple" "thumbv8r-{{.*}} "-target-cpu" "cortex-r52"
+// RUN: %clang -target armv8r-linux-gnueabi -mthumb -mbig-endian -### -c %s 2>&1 | \
+// RUN: FileCheck -check-prefix=CHECK-V8R-THUMB-BIG %s
+// RUN: %clang -target arm -march=armv8r -mthumb -mbig-endian -### -c %s 2>&1 | \
+// RUN: FileCheck -check-prefix=CHECK-V8R-THUMB-BIG %s
+// CHECK-V8R-THUMB-BIG: "-cc1"{{.*}} "-triple" "thumbebv8r-{{.*}} "-target-cpu" "cortex-r52"
+
// RUN: %clang -mcpu=generic -target armv8 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V8A-GENERIC %s
// RUN: %clang -mcpu=generic -target arm -march=armv8 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V8A-GENERIC %s
// RUN: %clang -mcpu=generic -target armv8a -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-V8A-GENERIC %s
@@ -303,7 +324,10 @@
// ================== Check that a bogus CPU gives an error
// RUN: %clang -target arm -mcpu=bogus -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BOGUS-CPU %s
+// RUN: %clang -target armv8-apple-darwin -arch arm64 -mcpu=bogus -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BOGUS-CPU %s
// CHECK-BOGUS-CPU: error: {{.*}} does not support '-mcpu=bogus'
+// RUN: %clang -target armv8-apple-darwin -arch arm64 -mtune=bogus -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BOGUS-TUNE %s
+// CHECK-BOGUS-TUNE: error: {{.*}} does not support '-mtune=bogus'
// ================== Check default Architecture on each ARM11 CPU
// RUN: %clang -target arm-linux-gnueabi -mcpu=arm1136j-s -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV6 %s
@@ -470,6 +494,8 @@
// 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
@@ -477,6 +503,8 @@
// 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 -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
// CHECK-CPUV8A: "-cc1"{{.*}} "-triple" "armv8-{{.*}}
// RUN: %clang -target armeb -mcpu=cortex-a32 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A %s
@@ -486,6 +514,8 @@
// 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
@@ -493,8 +523,13 @@
// 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 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
// CHECK-BE-CPUV8A: "-cc1"{{.*}} "-triple" "armebv8-{{.*}}
+// RUN: %clang -target arm-linux-gnueabi -mcpu=cortex-r52 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8R %s
+// CHECK-CPUV8R: "-cc1"{{.*}} "-triple" "armv8r-{{.*}}
+
// RUN: %clang -target arm -mcpu=cortex-a32 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s
// RUN: %clang -target arm -mcpu=cortex-a35 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s
// RUN: %clang -target arm -mcpu=cortex-a53 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV8A-THUMB %s
@@ -502,6 +537,8 @@
// 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
@@ -509,6 +546,8 @@
// 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 -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
// CHECK-CPUV8A-THUMB: "-cc1"{{.*}} "-triple" "thumbv8-{{.*}}
// RUN: %clang -target armeb -mcpu=cortex-a32 -mthumb -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BE-CPUV8A-THUMB %s
@@ -518,6 +557,8 @@
// 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
@@ -525,6 +566,8 @@
// 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 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
// CHECK-BE-CPUV8A-THUMB: "-cc1"{{.*}} "-triple" "thumbebv8-{{.*}}
// RUN: %clang -target armv8a-arm-none-eabi -mcpu=cortex-a73 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CORTEX-A73 %s
diff --git a/test/Driver/arm-execute-only.c b/test/Driver/arm-execute-only.c
new file mode 100644
index 000000000000..7010bbc837a0
--- /dev/null
+++ b/test/Driver/arm-execute-only.c
@@ -0,0 +1,99 @@
+// RUN: %clang -target armv6t2-eabi -### %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY
+
+// RUN: %clang -target armv6t2-eabi -### -mexecute-only %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-EXECUTE-ONLY
+
+// RUN: %clang -target armv6t2-eabi -### -mexecute-only -mno-execute-only %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY
+
+// RUN: %clang -target armv7m-eabi -### %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY
+
+// RUN: %clang -target armv7m-eabi -### -mexecute-only %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-EXECUTE-ONLY
+
+// RUN: %clang -target armv7m-eabi -### -mexecute-only -mno-execute-only %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY
+
+// RUN: %clang -target armv8m.base-eabi -### %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY
+
+// RUN: %clang -target armv8m.base-eabi -### -mexecute-only %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-EXECUTE-ONLY
+
+// RUN: %clang -target armv8m.base-eabi -### -mexecute-only -mno-execute-only %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY
+
+// RUN: %clang -target armv8m.main-eabi -### %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY
+
+// RUN: %clang -target armv8m.main-eabi -### -mexecute-only %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-EXECUTE-ONLY
+
+// RUN: %clang -target armv8m.main-eabi -### -mexecute-only -mno-execute-only %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY
+
+// RUN: not %clang -c -target thumbv6m-eabi -mexecute-only %s 2>&1 | \
+// RUN: FileCheck --check-prefix CHECK-EXECUTE-ONLY-NOT-SUPPORTED %s
+
+// RUN: not %clang -target armv8m.main-eabi -mexecute-only -mno-movt %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-EXECUTE-ONLY-NO-MOVT
+
+// RUN: not %clang -target armv8m.main-eabi -mexecute-only -mlong-calls %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-EXECUTE-ONLY-LONG-CALLS
+
+
+// -mpure-code flag for GCC compatibility
+// RUN: %clang -target armv6t2-eabi -### %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY
+
+// RUN: %clang -target armv6t2-eabi -### -mpure-code %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-EXECUTE-ONLY
+
+// RUN: %clang -target armv6t2-eabi -### -mpure-code -mno-pure-code %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY
+
+// RUN: %clang -target armv7m-eabi -### %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY
+
+// RUN: %clang -target armv7m-eabi -### -mpure-code %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-EXECUTE-ONLY
+
+// RUN: %clang -target armv7m-eabi -### -mpure-code -mno-pure-code %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY
+
+// RUN: %clang -target armv8m.base-eabi -### %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY
+
+// RUN: %clang -target armv8m.base-eabi -### -mpure-code %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-EXECUTE-ONLY
+
+// RUN: %clang -target armv8m.base-eabi -### -mpure-code -mno-pure-code %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY
+
+// RUN: %clang -target armv8m.main-eabi -### %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY
+
+// RUN: %clang -target armv8m.main-eabi -### -mpure-code %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-EXECUTE-ONLY
+
+// RUN: %clang -target armv8m.main-eabi -### -mpure-code -mno-pure-code %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY
+
+// RUN: not %clang -c -target thumbv6m-eabi -mpure-code %s 2>&1 | \
+// RUN: FileCheck --check-prefix CHECK-EXECUTE-ONLY-NOT-SUPPORTED %s
+
+// RUN: not %clang -target armv8m.main-eabi -mpure-code -mno-movt %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-EXECUTE-ONLY-NO-MOVT
+
+// RUN: not %clang -target armv8m.main-eabi -mpure-code -mlong-calls %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-EXECUTE-ONLY-LONG-CALLS
+
+//
+// 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-implicit-it.s b/test/Driver/arm-implicit-it.s
new file mode 100644
index 000000000000..48e4bdbe8c95
--- /dev/null
+++ b/test/Driver/arm-implicit-it.s
@@ -0,0 +1,24 @@
+// RUN: %clang -target armv7--none-eabi -### %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-DEFAULT
+
+// RUN: %clang -target armv7--none-eabi -mimplicit-it=arm -### %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-ARM
+
+// RUN: %clang -target armv7--none-eabi -mimplicit-it=thumb -### %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-THUMB
+
+// RUN: %clang -target armv7--none-eabi -mimplicit-it=never -### %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-NEVER
+
+// RUN: %clang -target armv7--none-eabi -mimplicit-it=always -### %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-ALWAYS
+
+// RUN: %clang -target armv7--none-eabi -mimplicit-it=thisisnotavalidoption -### %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-INVALID
+
+// CHECK-DEFAULT-NOT: "-arm-implicit-it
+// CHECK-ARM: "-arm-implicit-it=arm"
+// CHECK-THUMB: "-arm-implicit-it=thumb"
+// CHECK-NEVER: "-arm-implicit-it=never"
+// CHECK-ALWAYS: "-arm-implicit-it=always"
+// CHECK-INVALID: error: unsupported argument 'thisisnotavalidoption' to option 'mimplicit-it='
diff --git a/test/Driver/cc1-response-files.c b/test/Driver/cc1-response-files.c
index f47e6448a6ca..fbeda06fd453 100644
--- a/test/Driver/cc1-response-files.c
+++ b/test/Driver/cc1-response-files.c
@@ -1,2 +1,2 @@
-// RUN: %clang @%S/Inputs/cc1-response.txt -fsyntax-only -disable-llvm-optzns
+// RUN: %clang @%S/Inputs/cc1-response.txt -fsyntax-only -disable-llvm-passes
int main() {}
diff --git a/test/Driver/cl-fallback.c b/test/Driver/cl-fallback.c
index e73f7c03c263..2e5698ce9f9f 100644
--- a/test/Driver/cl-fallback.c
+++ b/test/Driver/cl-fallback.c
@@ -46,6 +46,12 @@
// GS: cl.exe
// GS: "/GS-"
+// RUN: %clang_cl /fallback /Zc:threadSafeInit -### -- %s 2>&1 | FileCheck -check-prefix=ThreadSafe %s
+// ThreadSafe: /Zc:threadSafeInit
+
+// RUN: %clang_cl /fallback /Zc:threadSafeInit- -### -- %s 2>&1 | FileCheck -check-prefix=NonThreadSafe %s
+// NonThreadSafe: /Zc:threadSafeInit-
+
// RUN: %clang_cl /fallback /Od -### -- %s 2>&1 | FileCheck -check-prefix=O0 %s
// O0: cl.exe
// O0: "/Od"
diff --git a/test/Driver/cl-link.c b/test/Driver/cl-link.c
index 026c43383cb9..b195676250e8 100644
--- a/test/Driver/cl-link.c
+++ b/test/Driver/cl-link.c
@@ -51,3 +51,6 @@
// NONEXISTENT: link.exe
// NONEXISTENT: "/libpath:somepath"
// NONEXISTENT: nonexistent
+
+// RUN: %clang_cl /Tc%s -fuse-ld=lld -### 2>&1 | FileCheck --check-prefix=USE_LLD %s
+// USE_LLD: lld-link.exe
diff --git a/test/Driver/cl-options.c b/test/Driver/cl-options.c
index 4d9416b1f87c..013b6524352e 100644
--- a/test/Driver/cl-options.c
+++ b/test/Driver/cl-options.c
@@ -50,6 +50,28 @@
// fpstrict-NOT: -menable-unsafe-fp-math
// fpstrict-NOT: -ffast-math
+// RUN: %clang_cl /Z7 -gcolumn-info -### -- %s 2>&1 | FileCheck -check-prefix=gcolumn %s
+// gcolumn: -dwarf-column-info
+
+// RUN: %clang_cl /Z7 -gno-column-info -### -- %s 2>&1 | FileCheck -check-prefix=gnocolumn %s
+// gnocolumn-NOT: -dwarf-column-info
+
+// RUN: %clang_cl /Z7 -### -- %s 2>&1 | FileCheck -check-prefix=gdefcolumn %s
+// gdefcolumn-NOT: -dwarf-column-info
+
+// RUN: %clang_cl -### /FA -fprofile-instr-generate -- %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-GENERATE %s
+// RUN: %clang_cl -### /FA -fprofile-instr-generate=/tmp/somefile.profraw -- %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-GENERATE-FILE %s
+// RUN: %clang_cl -### /FA -fprofile-instr-generate -fprofile-instr-use -- %s 2>&1 | FileCheck -check-prefix=CHECK-NO-MIX-GEN-USE %s
+// RUN: %clang_cl -### /FA -fprofile-instr-generate -fprofile-instr-use=file -- %s 2>&1 | FileCheck -check-prefix=CHECK-NO-MIX-GEN-USE %s
+// CHECK-PROFILE-GENERATE: "-fprofile-instrument=clang"
+// CHECK-PROFILE-GENERATE-FILE: "-fprofile-instrument-path=/tmp/somefile.profraw"
+// CHECK-NO-MIX-GEN-USE: '{{[a-z=-]*}}' not allowed with '{{[a-z=-]*}}'
+
+// RUN: %clang_cl -### /FA -fprofile-instr-use -- %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-USE %s
+// RUN: %clang_cl -### /FA -fprofile-instr-use=/tmp/somefile.prof -- %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-USE-FILE %s
+// CHECK-PROFILE-USE: "-fprofile-instrument-use-path=default.profdata"
+// CHECK-PROFILE-USE-FILE: "-fprofile-instrument-use-path=/tmp/somefile.prof"
+
// RUN: %clang_cl /GA -### -- %s 2>&1 | FileCheck -check-prefix=GA %s
// GA: -ftls-model=local-exec
@@ -171,10 +193,24 @@
// RUN: %clang_cl /EP /showIncludes -### -- %s 2>&1 | FileCheck -check-prefix=showIncludes_E %s
// showIncludes_E: 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
+// source-charset-utf-16: invalid value 'utf-16'
+
+// /execution-charset: should warn on everything except UTF-8.
+// RUN: %clang_cl /execution-charset:utf-16 -### -- %s 2>&1 | FileCheck -check-prefix=execution-charset-utf-16 %s
+// execution-charset-utf-16: invalid value 'utf-16'
+//
// RUN: %clang_cl /Umymacro -### -- %s 2>&1 | FileCheck -check-prefix=U %s
// RUN: %clang_cl /U mymacro -### -- %s 2>&1 | FileCheck -check-prefix=U %s
// U: "-U" "mymacro"
+// RUN: %clang_cl /validate-charset -### -- %s 2>&1 | FileCheck -check-prefix=validate-charset %s
+// validate-charset: -Winvalid-source-encoding
+
+// RUN: %clang_cl /validate-charset- -### -- %s 2>&1 | FileCheck -check-prefix=validate-charset_ %s
+// validate-charset_: -Wno-invalid-source-encoding
+
// RUN: %clang_cl /vd2 -### -- %s 2>&1 | FileCheck -check-prefix=VD2 %s
// VD2: -vtordisp-mode=2
@@ -276,6 +312,7 @@
// RUN: /d2FastFail \
// RUN: /d2Zi+ \
// RUN: /errorReport:foo \
+// RUN: /execution-charset:utf-8 \
// RUN: /FC \
// RUN: /Fdfoo \
// RUN: /FS \
@@ -288,6 +325,8 @@
// RUN: /RTC1 \
// RUN: /sdl \
// RUN: /sdl- \
+// RUN: /source-charset:utf-8 \
+// RUN: /utf-8 \
// RUN: /vmg \
// RUN: /volatile:iso \
// RUN: /w12345 \
@@ -325,7 +364,6 @@
// RUN: /FAs \
// RUN: /FAu \
// RUN: /favor:blend \
-// RUN: /FC \
// RUN: /Fifoo \
// RUN: /Fmfoo \
// RUN: /FpDebug\main.pch \
@@ -432,10 +470,10 @@
// BreproDefault: "-mincremental-linker-compatible"
// RUN: %clang_cl /Brepro- /Brepro /c '-###' -- %s 2>&1 | FileCheck -check-prefix=Brepro %s
-// Brepro: "-mincremental-linker-compatible"
+// Brepro-NOT: "-mincremental-linker-compatible"
// RUN: %clang_cl /Brepro /Brepro- /c '-###' -- %s 2>&1 | FileCheck -check-prefix=Brepro_ %s
-// Brepro_-NOT: "-mincremental-linker-compatible"
+// Brepro_: "-mincremental-linker-compatible"
// This test was super sneaky: "/Z7" means "line-tables", but "-gdwarf" occurs
// later on the command line, so it should win. Interestingly the cc1 arguments
@@ -468,6 +506,8 @@
// RUN: env CL="/Gy" _CL_="/Gy- -- %s" %clang_cl -### 2>&1 | FileCheck -check-prefix=ENV-_CL_ %s
// ENV-_CL_-NOT: "-ffunction-sections"
+// RUN: env CL="%s" _CL_="%s" not %clang --rsp-quoting=windows -c
+
// Accept "core" clang options.
// (/Zs is for syntax-only, -Werror makes it fail hard on unknown options)
// RUN: %clang_cl \
@@ -477,6 +517,7 @@
// RUN: -fdiagnostics-color \
// RUN: -fno-diagnostics-color \
// RUN: -fdiagnostics-parseable-fixits \
+// RUN: -fdiagnostics-absolute-paths \
// RUN: -ferror-limit=10 \
// RUN: -fmsc-version=1800 \
// RUN: -fno-strict-aliasing \
@@ -486,10 +527,14 @@
// RUN: -fno-ms-compatibility \
// RUN: -fms-extensions \
// RUN: -fno-ms-extensions \
-// RUN: -mllvm -disable-llvm-optzns \
-// RUN: -resource-dir \
+// RUN: -mllvm -disable-llvm-passes \
+// RUN: -resource-dir asdf \
+// RUN: -resource-dir=asdf \
// RUN: -Wunused-variable \
// RUN: -fmacro-backtrace-limit=0 \
+// RUN: -fstandalone-debug \
+// RUN: -flimit-debug-info \
+// RUN: -flto \
// RUN: -Werror /Zs -- %s 2>&1
diff --git a/test/Driver/cl-outputs.c b/test/Driver/cl-outputs.c
index bf6b43172625..d79a577788b9 100644
--- a/test/Driver/cl-outputs.c
+++ b/test/Driver/cl-outputs.c
@@ -2,12 +2,14 @@
// command-line option, e.g. on Mac where %s is commonly under /Users.
// RUN: %clang_cl /c -### -- %s 2>&1 | FileCheck -check-prefix=DEFAULT %s
+// RUN: %clang_cl /c -flto -### -- %s 2>&1 | FileCheck -check-prefix=DEFAULT %s
// DEFAULT: "-o" "cl-outputs.obj"
// RUN: %clang_cl /Fo -### -- %s 2>&1 | FileCheck -check-prefix=FoEMPTY %s
// FoEMPTY: "-o" "cl-outputs.obj"
// RUN: %clang_cl /Foa -### -- %s 2>&1 | FileCheck -check-prefix=FoNAME %s
+// RUN: %clang_cl /Foa -flto -### -- %s 2>&1 | FileCheck -check-prefix=FoNAME %s
// FoNAME: "-o" "a.obj"
// RUN: %clang_cl /Foa.ext /Fob.ext -### -- %s 2>&1 | FileCheck -check-prefix=FoNAMEEXT %s
diff --git a/test/Driver/cl-pch.c b/test/Driver/cl-pch.c
index 3372c184bbf3..36d83a11242d 100644
--- a/test/Driver/cl-pch.c
+++ b/test/Driver/cl-pch.c
@@ -1,3 +1,8 @@
+// REQUIRES: system-windows
+//
+// RUN: rm -rf %t
+// RUN: mkdir %t
+//
// Note: %s and %S must be preceded by --, otherwise it may be interpreted as a
// command-line option, e.g. on Mac where %s is commonly under /Users.
@@ -5,41 +10,37 @@
// a few things for .c inputs.
// /Yc with a .c file should build a c pch file.
-// RUN: %clang_cl -Werror /Ycpchfile.h /FIpchfile.h /c -### -- %s 2>&1 \
+// RUN: %clang_cl -Werror /Yc%S/Inputs/pchfile.h /FI%S/Inputs/pchfile.h /c /Fo%t/pchfile.obj /Fp%t/pchfile.pch -v -- %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-YC %s
-// CHECK-YC: cc1
-// CHECK-YC: -emit-pch
-// CHECK-YC: -o
-// CHECK-YC: pchfile.pch
-// CHECK-YC: -x
-// CHECK-YC: "c"
+// CHECK-YC: cc1{{.* .*}}-emit-pch
+// CHECK-YC-SAME: -o
+// CHECK-YC-SAME: pchfile.pch
+// CHECK-YC-SAME: -x
+// CHECK-YC-SAME: c-header
// But not if /TP changes the input language to C++.
-// RUN: %clang_cl /TP -Werror /Ycpchfile.h /FIpchfile.h /c -### -- %s 2>&1 \
+// RUN: %clang_cl /TP -Werror /Yc%S/Inputs/pchfile.h /FI%S/Inputs/pchfile.h /c /Fo%t/pchfile.obj /Fp%t/pchfile.pch -v -- %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-YCTP %s
-// CHECK-YCTP: cc1
-// CHECK-YCTP: -emit-pch
-// CHECK-YCTP: -o
-// CHECK-YCTP: pchfile.pch
-// CHECK-YCTP: -x
-// CHECK-YCTP: "c++"
+// CHECK-YCTP: cc1{{.* .*}}-emit-pch
+// CHECK-YCTP-SAME: -o
+// CHECK-YCTP-SAME: pchfile.pch
+// CHECK-YCTP-SAME: -x
+// CHECK-YCTP-SAME: c++-header
// Except if a later /TC changes it back.
-// RUN: %clang_cl -Werror /Ycpchfile.h /FIpchfile.h /c -### -- %s 2>&1 \
+// RUN: %clang_cl -Werror /Yc%S/Inputs/pchfile.h /FI%S/Inputs/pchfile.h /c /Fo%t/pchfile.obj /Fp%t/pchfile.pch -v -- %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-YCTPTC %s
-// CHECK-YCTPTC: cc1
-// CHECK-YCTPTC: -emit-pch
-// CHECK-YCTPTC: -o
-// CHECK-YCTPTC: pchfile.pch
-// CHECK-YCTPTC: -x
-// CHECK-YCTPTC: "c"
+// CHECK-YCTPTC: cc1{{.* .*}}-emit-pch
+// CHECK-YCTPTC-SAME: -o
+// CHECK-YCTPTC-SAME: pchfile.pch
+// CHECK-YCTPTC-SAME: -x
+// CHECK-YCTPTC-SAME: c-header
// Also check lower-case /Tp flag.
-// RUN: %clang_cl -Werror /Tp%s /Ycpchfile.h /FIpchfile.h /c -### 2>&1 \
+// RUN: %clang_cl -Werror /Tp%s /Yc%S/Inputs/pchfile.h /FI%S/Inputs/pchfile.h /c /Fo%t/pchfile.obj /Fp%t/pchfile.pch -v 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-YCTp %s
-// CHECK-YCTp: cc1
-// CHECK-YCTp: -emit-pch
-// CHECK-YCTp: -o
-// CHECK-YCTp: pchfile.pch
-// CHECK-YCTp: -x
-// CHECK-YCTp: "c++"
+// CHECK-YCTp: cc1{{.* .*}}-emit-pch
+// CHECK-YCTp-SAME: -o
+// CHECK-YCTp-SAME: pchfile.pch
+// CHECK-YCTp-SAME: -x
+// CHECK-YCTp-SAME: c++-header
diff --git a/test/Driver/cl-pch.cpp b/test/Driver/cl-pch.cpp
index 8d701da5b0b2..2503c9737335 100644
--- a/test/Driver/cl-pch.cpp
+++ b/test/Driver/cl-pch.cpp
@@ -10,7 +10,7 @@
// CHECK-YC: -o
// CHECK-YC: pchfile.pch
// CHECK-YC: -x
-// CHECK-YC: "c++"
+// CHECK-YC: "c++-header"
// 2. Use .pch file.
// CHECK-YC: cc1
// CHECK-YC: -emit-obj
@@ -158,7 +158,7 @@
// CHECK-YCFIFIFI: -o
// CHECK-YCFIFIFI: foo2.pch
// CHECK-YCFIFIFI: -x
-// CHECK-YCFIFIFI: "c++"
+// CHECK-YCFIFIFI: "c++-header"
// CHECK-YCFIFIFI: foo2.h
// 2. Use .pch file: Inlucdes foo2.pch and foo3.h
// CHECK-YCFIFIFI: cc1
@@ -313,7 +313,7 @@
// RUN: | FileCheck -check-prefix=CHECK-NoSource %s
// CHECK-NoSource: file.prof:{{.*}}input unused
-// ...but if an explicit file turns the file into a source file, handle it:
+// ...but if an explicit flag turns the file into a source file, handle it:
// RUN: %clang_cl /TP -Werror /Ycpchfile.h /FIpchfile.h /c -### -- %S/Inputs/file.prof 2>&1 \
// RUN: | FileCheck -check-prefix=CHECK-NoSourceTP %s
// CHECK-NoSourceTP: cc1
diff --git a/test/Driver/clang-g-opts.c b/test/Driver/clang-g-opts.c
index 32b8d429ea1c..a26fb29652b4 100644
--- a/test/Driver/clang-g-opts.c
+++ b/test/Driver/clang-g-opts.c
@@ -22,7 +22,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: | FileCheck --check-prefix=CHECK-WITH-G-DWARF2 %s
+// 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
// RUN: %clang -### -S %s -g0 -g -target x86_64-pc-freebsd10.0 2>&1 \
@@ -34,3 +34,6 @@
// CHECK-WITH-G: "-debug-info-kind=limited"
// CHECK-WITH-G: "-dwarf-version=4"
// CHECK-WITH-G-DWARF2: "-dwarf-version=2"
+
+// CHECK-WITH-G-STANDALONE: "-debug-info-kind=standalone"
+// CHECK-WITH-G-STANDALONE: "-dwarf-version=2"
diff --git a/test/Driver/clang-offload-bundler.c b/test/Driver/clang-offload-bundler.c
new file mode 100644
index 000000000000..adf13f59d46f
--- /dev/null
+++ b/test/Driver/clang-offload-bundler.c
@@ -0,0 +1,260 @@
+// REQUIRES: x86-registered-target
+// REQUIRES: powerpc-registered-target
+
+//
+// Generate all the types of files we can bundle.
+//
+// RUN: %clang -O0 -target powerpc64le-ibm-linux-gnu %s -E -o %t.i
+// RUN: %clangxx -O0 -target powerpc64le-ibm-linux-gnu -x c++ %s -E -o %t.ii
+// RUN: %clang -O0 -target powerpc64le-ibm-linux-gnu %s -S -emit-llvm -o %t.ll
+// RUN: %clang -O0 -target powerpc64le-ibm-linux-gnu %s -c -emit-llvm -o %t.bc
+// RUN: %clang -O0 -target powerpc64le-ibm-linux-gnu %s -S -o %t.s
+// RUN: %clang -O0 -target powerpc64le-ibm-linux-gnu %s -c -o %t.o
+// RUN: %clang -O0 -target powerpc64le-ibm-linux-gnu %s -emit-ast -o %t.ast
+
+//
+// Generate an empty file to help with the checks of empty files.
+//
+// RUN: touch %t.empty
+
+//
+// Generate a couple of files to bundle with.
+//
+// RUN: echo 'Content of device file 1' > %t.tgt1
+// RUN: echo 'Content of device file 2' > %t.tgt2
+
+//
+// Check help message.
+//
+// RUN: clang-offload-bundler --help | FileCheck %s --check-prefix CK-HELP
+// CK-HELP: {{.*}}OVERVIEW: A tool to bundle several input files of the specified type <type>
+// CK-HELP: {{.*}}referring to the same source file but different targets into a single
+// CK-HELP: {{.*}}one. The resulting file can also be unbundled into different files by
+// CK-HELP: {{.*}}this tool if -unbundle is provided.
+// CK-HELP: {{.*}}USAGE: clang-offload-bundler [options]
+// CK-HELP: {{.*}}-inputs=<string> - [<input file>,...]
+// CK-HELP: {{.*}}-outputs=<string> - [<output file>,...]
+// CK-HELP: {{.*}}-targets=<string> - [<offload kind>-<target triple>,...]
+// CK-HELP: {{.*}}-type=<string> - Type of the files to be bundled/unbundled.
+// CK-HELP: {{.*}}Current supported types are:
+// CK-HELP: {{.*}}i {{.*}}- cpp-output
+// CK-HELP: {{.*}}ii {{.*}}- c++-cpp-output
+// CK-HELP: {{.*}}ll {{.*}}- llvm
+// CK-HELP: {{.*}}bc {{.*}}- llvm-bc
+// CK-HELP: {{.*}}s {{.*}}- assembler
+// CK-HELP: {{.*}}o {{.*}}- object
+// CK-HELP: {{.*}}gch {{.*}}- precompiled-header
+// CK-HELP: {{.*}}ast {{.*}}- clang AST file
+// CK-HELP: {{.*}}-unbundle {{.*}}- Unbundle bundled file into several output files.
+
+//
+// Check errors.
+//
+// RUN: not clang-offload-bundler -type=i -targets=host-powerpc64le-ibm-linux-gnu,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -inputs=%t.i,%t.tgt1,%t.tgt2 -outputs=%t.bundle.i -unbundle 2>&1 | FileCheck %s --check-prefix CK-ERR1
+// CK-ERR1: error: only one input file supported in unbundling mode.
+// CK-ERR1: error: number of output files and targets should match in unbundling mode.
+
+// RUN: not clang-offload-bundler -type=i -targets=host-powerpc64le-ibm-linux-gnu,openmp-powerpc64le-ibm-linux-gnu -inputs=%t.i,%t.tgt1,%t.tgt2 -outputs=%t.bundle.i 2>&1 | FileCheck %s --check-prefix CK-ERR2
+// RUN: not clang-offload-bundler -type=i -targets=host-powerpc64le-ibm-linux-gnu,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -inputs=%t.i,%t.tgt1 -outputs=%t.bundle.i 2>&1 | FileCheck %s --check-prefix CK-ERR2
+// CK-ERR2: error: number of input files and targets should match in bundling mode.
+
+// RUN: not clang-offload-bundler -type=i -targets=host-powerpc64le-ibm-linux-gnu,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -outputs=%t.i,%t.tgt1,%t.tgt2 -inputs=%t.bundle.i 2>&1 | FileCheck %s --check-prefix CK-ERR3
+// CK-ERR3: error: only one output file supported in bundling mode.
+// CK-ERR3: error: number of input files and targets should match in bundling mode.
+
+// RUN: not clang-offload-bundler -type=i -targets=host-powerpc64le-ibm-linux-gnu,openmp-powerpc64le-ibm-linux-gnu -outputs=%t.i,%t.tgt1,%t.tgt2 -inputs=%t.bundle.i -unbundle 2>&1 | FileCheck %s --check-prefix CK-ERR4
+// RUN: not clang-offload-bundler -type=i -targets=host-powerpc64le-ibm-linux-gnu,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -outputs=%t.i,%t.tgt1 -inputs=%t.bundle.i -unbundle 2>&1 | FileCheck %s --check-prefix CK-ERR4
+// CK-ERR4: error: number of output files and targets should match in unbundling mode.
+
+// RUN: not clang-offload-bundler -type=i -targets=host-powerpc64le-ibm-linux-gnu,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -inputs=%t.i,%t.tgt1,%t.tgt2.notexist -outputs=%t.bundle.i 2>&1 | FileCheck %s --check-prefix CK-ERR5
+// RUN: not clang-offload-bundler -type=i -targets=host-powerpc64le-ibm-linux-gnu,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -outputs=%t.i,%t.tgt1,%t.tgt2 -inputs=%t.bundle.i.notexist -unbundle 2>&1 | FileCheck %s --check-prefix CK-ERR5
+// CK-ERR5: error: Can't open file {{.+}}.notexist: {{N|n}}o such file or directory
+
+// RUN: not clang-offload-bundler -type=invalid -targets=host-powerpc64le-ibm-linux-gnu,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -inputs=%t.i,%t.tgt1,%t.tgt2 -outputs=%t.bundle.i 2>&1 | FileCheck %s --check-prefix CK-ERR6
+// CK-ERR6: error: invalid file type specified.
+
+// RUN: not clang-offload-bundler 2>&1 | FileCheck %s --check-prefix CK-ERR7
+// CK-ERR7-DAG: clang-offload-bundler: for the -type option: must be specified at least once!
+// CK-ERR7-DAG: clang-offload-bundler: for the -inputs option: must be specified at least once!
+// CK-ERR7-DAG: clang-offload-bundler: for the -outputs option: must be specified at least once!
+// CK-ERR7-DAG: clang-offload-bundler: for the -targets option: must be specified at least once!
+
+// RUN: not clang-offload-bundler -type=i -targets=hxst-powerpcxxle-ibm-linux-gnu,openxp-pxxerpc64le-ibm-linux-gnu,xpenmp-x86_xx-pc-linux-gnu -inputs=%t.i,%t.tgt1,%t.tgt2 -outputs=%t.bundle.i 2>&1 | FileCheck %s --check-prefix CK-ERR8
+// CK-ERR8: error: invalid target 'hxst-powerpcxxle-ibm-linux-gnu', unknown offloading kind 'hxst', unknown target triple 'powerpcxxle-ibm-linux-gnu'.
+// CK-ERR8: error: invalid target 'openxp-pxxerpc64le-ibm-linux-gnu', unknown offloading kind 'openxp', unknown target triple 'pxxerpc64le-ibm-linux-gnu'.
+// CK-ERR8: error: invalid target 'xpenmp-x86_xx-pc-linux-gnu', unknown offloading kind 'xpenmp', unknown target triple 'x86_xx-pc-linux-gnu'.
+
+// RUN: not clang-offload-bundler -type=i -targets=openmp-powerpc64le-linux,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -inputs=%t.i,%t.tgt1,%t.tgt2 -outputs=%t.bundle.i 2>&1 | FileCheck %s --check-prefix CK-ERR9A
+// RUN: not clang-offload-bundler -type=i -targets=host-powerpc64le-ibm-linux-gnu,host-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -inputs=%t.i,%t.tgt1,%t.tgt2 -outputs=%t.bundle.i 2>&1 | FileCheck %s --check-prefix CK-ERR9B
+// CK-ERR9A: error: expecting exactly one host target but got 0.
+// CK-ERR9B: error: expecting exactly one host target but got 2.
+
+//
+// Check text bundle. This is a readable format, so we check for the format we expect to find.
+//
+// RUN: clang-offload-bundler -type=i -targets=host-powerpc64le-ibm-linux-gnu,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -inputs=%t.i,%t.tgt1,%t.tgt2 -outputs=%t.bundle3.i
+// RUN: clang-offload-bundler -type=ii -targets=host-powerpc64le-ibm-linux-gnu,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -inputs=%t.ii,%t.tgt1,%t.tgt2 -outputs=%t.bundle3.ii
+// RUN: clang-offload-bundler -type=ll -targets=host-powerpc64le-ibm-linux-gnu,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -inputs=%t.ll,%t.tgt1,%t.tgt2 -outputs=%t.bundle3.ll
+// RUN: clang-offload-bundler -type=s -targets=host-powerpc64le-ibm-linux-gnu,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -inputs=%t.s,%t.tgt1,%t.tgt2 -outputs=%t.bundle3.s
+// RUN: clang-offload-bundler -type=s -targets=openmp-powerpc64le-ibm-linux-gnu,host-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -inputs=%t.tgt1,%t.s,%t.tgt2 -outputs=%t.bundle3.unordered.s
+// RUN: FileCheck %s --input-file %t.bundle3.i --check-prefix CK-TEXTI
+// RUN: FileCheck %s --input-file %t.bundle3.ii --check-prefix CK-TEXTI
+// RUN: FileCheck %s --input-file %t.bundle3.ll --check-prefix CK-TEXTLL
+// RUN: FileCheck %s --input-file %t.bundle3.s --check-prefix CK-TEXTS
+// RUN: FileCheck %s --input-file %t.bundle3.unordered.s --check-prefix CK-TEXTS-UNORDERED
+
+// CK-TEXTI: // __CLANG_OFFLOAD_BUNDLE____START__ host-powerpc64le-ibm-linux-gnu
+// CK-TEXTI: int A = 0;
+// CK-TEXTI: test_func(void)
+// CK-TEXTI: // __CLANG_OFFLOAD_BUNDLE____END__ host-powerpc64le-ibm-linux-gnu
+// CK-TEXTI: // __CLANG_OFFLOAD_BUNDLE____START__ openmp-powerpc64le-ibm-linux-gnu
+// CK-TEXTI: Content of device file 1
+// CK-TEXTI: // __CLANG_OFFLOAD_BUNDLE____END__ openmp-powerpc64le-ibm-linux-gnu
+// CK-TEXTI: // __CLANG_OFFLOAD_BUNDLE____START__ openmp-x86_64-pc-linux-gnu
+// CK-TEXTI: Content of device file 2
+// CK-TEXTI: // __CLANG_OFFLOAD_BUNDLE____END__ openmp-x86_64-pc-linux-gnu
+
+// CK-TEXTLL: ; __CLANG_OFFLOAD_BUNDLE____START__ host-powerpc64le-ibm-linux-gnu
+// CK-TEXTLL: @A = global i32 0
+// CK-TEXTLL: define {{.*}}@test_func()
+// CK-TEXTLL: ; __CLANG_OFFLOAD_BUNDLE____END__ host-powerpc64le-ibm-linux-gnu
+// CK-TEXTLL: ; __CLANG_OFFLOAD_BUNDLE____START__ openmp-powerpc64le-ibm-linux-gnu
+// CK-TEXTLL: Content of device file 1
+// CK-TEXTLL: ; __CLANG_OFFLOAD_BUNDLE____END__ openmp-powerpc64le-ibm-linux-gnu
+// CK-TEXTLL: ; __CLANG_OFFLOAD_BUNDLE____START__ openmp-x86_64-pc-linux-gnu
+// CK-TEXTLL: Content of device file 2
+// CK-TEXTLL: ; __CLANG_OFFLOAD_BUNDLE____END__ openmp-x86_64-pc-linux-gnu
+
+// CK-TEXTS: # __CLANG_OFFLOAD_BUNDLE____START__ host-powerpc64le-ibm-linux-gnu
+// CK-TEXTS: .globl {{.*}}test_func
+// CK-TEXTS: .globl {{.*}}A
+// CK-TEXTS: # __CLANG_OFFLOAD_BUNDLE____END__ host-powerpc64le-ibm-linux-gnu
+// CK-TEXTS: # __CLANG_OFFLOAD_BUNDLE____START__ openmp-powerpc64le-ibm-linux-gnu
+// CK-TEXTS: Content of device file 1
+// CK-TEXTS: # __CLANG_OFFLOAD_BUNDLE____END__ openmp-powerpc64le-ibm-linux-gnu
+// CK-TEXTS: # __CLANG_OFFLOAD_BUNDLE____START__ openmp-x86_64-pc-linux-gnu
+// CK-TEXTS: Content of device file 2
+// CK-TEXTS: # __CLANG_OFFLOAD_BUNDLE____END__ openmp-x86_64-pc-linux-gnu
+
+// CK-TEXTS-UNORDERED: # __CLANG_OFFLOAD_BUNDLE____START__ openmp-powerpc64le-ibm-linux-gnu
+// CK-TEXTS-UNORDERED: Content of device file 1
+// CK-TEXTS-UNORDERED: # __CLANG_OFFLOAD_BUNDLE____END__ openmp-powerpc64le-ibm-linux-gnu
+// CK-TEXTS-UNORDERED: # __CLANG_OFFLOAD_BUNDLE____START__ host-powerpc64le-ibm-linux-gnu
+// CK-TEXTS-UNORDERED: .globl {{.*}}test_func
+// CK-TEXTS-UNORDERED: .globl {{.*}}A
+// CK-TEXTS-UNORDERED: # __CLANG_OFFLOAD_BUNDLE____END__ host-powerpc64le-ibm-linux-gnu
+// CK-TEXTS-UNORDERED: # __CLANG_OFFLOAD_BUNDLE____START__ openmp-x86_64-pc-linux-gnu
+// CK-TEXTS-UNORDERED: Content of device file 2
+// CK-TEXTS-UNORDERED: # __CLANG_OFFLOAD_BUNDLE____END__ openmp-x86_64-pc-linux-gnu
+
+//
+// Check text unbundle. Check if we get the exact same content that we bundled before for each file.
+//
+// RUN: clang-offload-bundler -type=i -targets=host-powerpc64le-ibm-linux-gnu,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -outputs=%t.res.i,%t.res.tgt1,%t.res.tgt2 -inputs=%t.bundle3.i -unbundle
+// RUN: diff %t.i %t.res.i
+// RUN: diff %t.tgt1 %t.res.tgt1
+// RUN: diff %t.tgt2 %t.res.tgt2
+// RUN: clang-offload-bundler -type=ii -targets=host-powerpc64le-ibm-linux-gnu,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -outputs=%t.res.ii,%t.res.tgt1,%t.res.tgt2 -inputs=%t.bundle3.ii -unbundle
+// RUN: diff %t.ii %t.res.ii
+// RUN: diff %t.tgt1 %t.res.tgt1
+// RUN: diff %t.tgt2 %t.res.tgt2
+// RUN: clang-offload-bundler -type=ll -targets=host-powerpc64le-ibm-linux-gnu,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -outputs=%t.res.ll,%t.res.tgt1,%t.res.tgt2 -inputs=%t.bundle3.ll -unbundle
+// RUN: diff %t.ll %t.res.ll
+// RUN: diff %t.tgt1 %t.res.tgt1
+// RUN: diff %t.tgt2 %t.res.tgt2
+// RUN: clang-offload-bundler -type=s -targets=host-powerpc64le-ibm-linux-gnu,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -outputs=%t.res.s,%t.res.tgt1,%t.res.tgt2 -inputs=%t.bundle3.s -unbundle
+// RUN: diff %t.s %t.res.s
+// RUN: diff %t.tgt1 %t.res.tgt1
+// RUN: diff %t.tgt2 %t.res.tgt2
+// RUN: clang-offload-bundler -type=s -targets=openmp-powerpc64le-ibm-linux-gnu,host-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -outputs=%t.res.tgt1,%t.res.s,%t.res.tgt2 -inputs=%t.bundle3.s -unbundle
+// RUN: diff %t.s %t.res.s
+// RUN: diff %t.tgt1 %t.res.tgt1
+// RUN: diff %t.tgt2 %t.res.tgt2
+
+// Check if we can unbundle a file with no magic strings.
+// RUN: clang-offload-bundler -type=s -targets=host-powerpc64le-ibm-linux-gnu,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -outputs=%t.res.s,%t.res.tgt1,%t.res.tgt2 -inputs=%t.s -unbundle
+// RUN: diff %t.s %t.res.s
+// RUN: diff %t.empty %t.res.tgt1
+// RUN: diff %t.empty %t.res.tgt2
+// RUN: clang-offload-bundler -type=s -targets=openmp-powerpc64le-ibm-linux-gnu,host-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -outputs=%t.res.tgt1,%t.res.s,%t.res.tgt2 -inputs=%t.s -unbundle
+// RUN: diff %t.s %t.res.s
+// RUN: diff %t.empty %t.res.tgt1
+// RUN: diff %t.empty %t.res.tgt2
+
+//
+// Check binary bundle/unbundle. The content that we have before bundling must be the same we have after unbundling.
+//
+// RUN: clang-offload-bundler -type=bc -targets=host-powerpc64le-ibm-linux-gnu,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -inputs=%t.bc,%t.tgt1,%t.tgt2 -outputs=%t.bundle3.bc
+// RUN: clang-offload-bundler -type=gch -targets=host-powerpc64le-ibm-linux-gnu,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -inputs=%t.ast,%t.tgt1,%t.tgt2 -outputs=%t.bundle3.gch
+// RUN: clang-offload-bundler -type=ast -targets=host-powerpc64le-ibm-linux-gnu,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -inputs=%t.ast,%t.tgt1,%t.tgt2 -outputs=%t.bundle3.ast
+// RUN: clang-offload-bundler -type=ast -targets=openmp-powerpc64le-ibm-linux-gnu,host-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -inputs=%t.tgt1,%t.ast,%t.tgt2 -outputs=%t.bundle3.unordered.ast
+// RUN: clang-offload-bundler -type=bc -targets=host-powerpc64le-ibm-linux-gnu,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -outputs=%t.res.bc,%t.res.tgt1,%t.res.tgt2 -inputs=%t.bundle3.bc -unbundle
+// RUN: diff %t.bc %t.res.bc
+// RUN: diff %t.tgt1 %t.res.tgt1
+// RUN: diff %t.tgt2 %t.res.tgt2
+// RUN: clang-offload-bundler -type=gch -targets=host-powerpc64le-ibm-linux-gnu,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -outputs=%t.res.gch,%t.res.tgt1,%t.res.tgt2 -inputs=%t.bundle3.gch -unbundle
+// RUN: diff %t.ast %t.res.gch
+// RUN: diff %t.tgt1 %t.res.tgt1
+// RUN: diff %t.tgt2 %t.res.tgt2
+// RUN: clang-offload-bundler -type=ast -targets=host-powerpc64le-ibm-linux-gnu,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -outputs=%t.res.ast,%t.res.tgt1,%t.res.tgt2 -inputs=%t.bundle3.ast -unbundle
+// RUN: diff %t.ast %t.res.ast
+// RUN: diff %t.tgt1 %t.res.tgt1
+// RUN: diff %t.tgt2 %t.res.tgt2
+// RUN: clang-offload-bundler -type=ast -targets=openmp-powerpc64le-ibm-linux-gnu,host-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -outputs=%t.res.tgt1,%t.res.ast,%t.res.tgt2 -inputs=%t.bundle3.ast -unbundle
+// RUN: diff %t.ast %t.res.ast
+// RUN: diff %t.tgt1 %t.res.tgt1
+// RUN: diff %t.tgt2 %t.res.tgt2
+// RUN: clang-offload-bundler -type=ast -targets=openmp-powerpc64le-ibm-linux-gnu,host-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -outputs=%t.res.tgt1,%t.res.ast,%t.res.tgt2 -inputs=%t.bundle3.unordered.ast -unbundle
+// RUN: diff %t.ast %t.res.ast
+// RUN: diff %t.tgt1 %t.res.tgt1
+// RUN: diff %t.tgt2 %t.res.tgt2
+
+// Check if we can unbundle a file with no magic strings.
+// RUN: clang-offload-bundler -type=bc -targets=host-powerpc64le-ibm-linux-gnu,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -outputs=%t.res.bc,%t.res.tgt1,%t.res.tgt2 -inputs=%t.bc -unbundle
+// RUN: diff %t.bc %t.res.bc
+// RUN: diff %t.empty %t.res.tgt1
+// RUN: diff %t.empty %t.res.tgt2
+// RUN: clang-offload-bundler -type=bc -targets=openmp-powerpc64le-ibm-linux-gnu,host-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -outputs=%t.res.tgt1,%t.res.bc,%t.res.tgt2 -inputs=%t.bc -unbundle
+// RUN: diff %t.bc %t.res.bc
+// RUN: diff %t.empty %t.res.tgt1
+// RUN: diff %t.empty %t.res.tgt2
+
+//
+// Check object bundle/unbundle. The content should be bundled into an ELF
+// section (we are using a PowerPC little-endian host which uses ELF). We
+// have an already bundled file to check the unbundle and do a dry run on the
+// bundling as it cannot be tested in all host platforms that will run these
+// tests.
+//
+
+// RUN: clang-offload-bundler -type=o -targets=host-powerpc64le-ibm-linux-gnu,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -inputs=%t.o,%t.tgt1,%t.tgt2 -outputs=%t.bundle3.o -### -dump-temporary-files 2>&1 \
+// RUN: | FileCheck %s --check-prefix CK-OBJ-CMD
+// CK-OBJ-CMD: private constant [1 x i8] zeroinitializer, section "__CLANG_OFFLOAD_BUNDLE__host-powerpc64le-ibm-linux-gnu"
+// CK-OBJ-CMD: private constant [{{[0-9]+}} x i8] c"Content of device file 1{{.+}}", section "__CLANG_OFFLOAD_BUNDLE__openmp-powerpc64le-ibm-linux-gnu"
+// CK-OBJ-CMD: private constant [{{[0-9]+}} x i8] c"Content of device file 2{{.+}}", section "__CLANG_OFFLOAD_BUNDLE__openmp-x86_64-pc-linux-gnu"
+// CK-OBJ-CMD: clang{{(.exe)?}}" "-r" "-target" "powerpc64le-ibm-linux-gnu" "-o" "{{.+}}.o" "{{.+}}.o" "{{.+}}.bc" "-nostdlib"
+
+// RUN: clang-offload-bundler -type=o -targets=host-powerpc64le-ibm-linux-gnu,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -outputs=%t.res.o,%t.res.tgt1,%t.res.tgt2 -inputs=%s.o -unbundle
+// RUN: diff %s.o %t.res.o
+// RUN: diff %t.tgt1 %t.res.tgt1
+// RUN: diff %t.tgt2 %t.res.tgt2
+// RUN: clang-offload-bundler -type=o -targets=openmp-powerpc64le-ibm-linux-gnu,host-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -outputs=%t.res.tgt1,%t.res.o,%t.res.tgt2 -inputs=%s.o -unbundle
+// RUN: diff %s.o %t.res.o
+// RUN: diff %t.tgt1 %t.res.tgt1
+// RUN: diff %t.tgt2 %t.res.tgt2
+
+// Check if we can unbundle a file with no magic strings.
+// RUN: clang-offload-bundler -type=o -targets=host-powerpc64le-ibm-linux-gnu,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -outputs=%t.res.o,%t.res.tgt1,%t.res.tgt2 -inputs=%t.o -unbundle
+// RUN: diff %t.o %t.res.o
+// RUN: diff %t.empty %t.res.tgt1
+// RUN: diff %t.empty %t.res.tgt2
+// RUN: clang-offload-bundler -type=o -targets=openmp-powerpc64le-ibm-linux-gnu,host-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -outputs=%t.res.tgt1,%t.res.o,%t.res.tgt2 -inputs=%t.o -unbundle
+// RUN: diff %t.o %t.res.o
+// RUN: diff %t.empty %t.res.tgt1
+// RUN: diff %t.empty %t.res.tgt2
+
+// Some code so that we can create a binary out of this file.
+int A = 0;
+void test_func(void) {
+ ++A;
+}
diff --git a/test/Driver/clang-offload-bundler.c.o b/test/Driver/clang-offload-bundler.c.o
new file mode 100644
index 000000000000..2cdba14ecb27
--- /dev/null
+++ b/test/Driver/clang-offload-bundler.c.o
Binary files differ
diff --git a/test/Driver/clang-translation.c b/test/Driver/clang-translation.c
index cc3cd1b58b1f..7c7b2f05f1dc 100644
--- a/test/Driver/clang-translation.c
+++ b/test/Driver/clang-translation.c
@@ -11,19 +11,36 @@
// I386: "hidden"
// I386: "-o"
// I386: clang-translation
+
// RUN: %clang -target i386-apple-darwin9 -### -S %s -o %t.s 2>&1 | \
// RUN: FileCheck -check-prefix=YONAH %s
+// RUN: %clang -target i386-apple-macosx10.11 -### -S %s -o %t.s 2>&1 | \
+// RUN: FileCheck -check-prefix=YONAH %s
// YONAH: "-target-cpu"
// YONAH: "yonah"
+
// RUN: %clang -target x86_64-apple-darwin9 -### -S %s -o %t.s 2>&1 | \
// RUN: FileCheck -check-prefix=CORE2 %s
+// RUN: %clang -target x86_64-apple-macosx10.11 -### -S %s -o %t.s 2>&1 | \
+// RUN: FileCheck -check-prefix=CORE2 %s
// CORE2: "-target-cpu"
// CORE2: "core2"
+
// RUN: %clang -target x86_64h-apple-darwin -### -S %s -o %t.s 2>&1 | \
// RUN: FileCheck -check-prefix=AVX2 %s
+// RUN: %clang -target x86_64h-apple-macosx10.12 -### -S %s -o %t.s 2>&1 | \
+// RUN: FileCheck -check-prefix=AVX2 %s
// AVX2: "-target-cpu"
// AVX2: "core-avx2"
+// RUN: %clang -target i386-apple-macosx10.12 -### -S %s -o %t.s 2>&1 | \
+// RUN: FileCheck -check-prefix=PENRYN %s
+// RUN: %clang -target x86_64-apple-macosx10.12 -### -S %s -o %t.s 2>&1 | \
+// RUN: FileCheck -check-prefix=PENRYN %s
+// PENRYN: "-target-cpu"
+// PENRYN: "penryn"
+
+
// RUN: %clang -target x86_64-apple-darwin10 -### -S %s -arch armv7 2>&1 | \
// RUN: FileCheck -check-prefix=ARMV7_DEFAULT %s
// ARMV7_DEFAULT: clang
diff --git a/test/Driver/clang_f_opts.c b/test/Driver/clang_f_opts.c
index ea5b8d1ecd52..9056621721b7 100644
--- a/test/Driver/clang_f_opts.c
+++ b/test/Driver/clang_f_opts.c
@@ -66,6 +66,16 @@
// CHECK-PROFILE-ARCS: "-femit-coverage-data"
// CHECK-NO-PROFILE-ARCS-NOT: "-femit-coverage-data"
+// RUN: %clang -### -S -fprofile-dir=abc %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-DIR-UNUSED %s
+// RUN: %clang -### -S -ftest-coverage -fprofile-dir=abc %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-DIR-UNUSED %s
+// RUN: %clang -### -S -fprofile-arcs -fprofile-dir=abc %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-DIR %s
+// RUN: %clang -### -S --coverage -fprofile-dir=abc %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-DIR %s
+// RUN: %clang -### -S -fprofile-arcs -fno-profile-arcs -fprofile-dir=abc %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-DIR-NEITHER %s
+// CHECK-PROFILE-DIR: "-coverage-data-file" "abc
+// CHECK-PROFILE-DIR-UNUSED: argument unused
+// CHECK-PROFILE-DIR-UNUSED-NOT: "-coverage-data-file" "abc
+// CHECK-PROFILE-DIR-NEITHER-NOT: argument unused
+
// RUN: %clang -### -S -fprofile-generate %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-GENERATE-LLVM %s
// RUN: %clang -### -S -fprofile-instr-generate %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-GENERATE %s
// RUN: %clang -### -S -fprofile-generate=/some/dir %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-GENERATE-DIR %s
@@ -99,7 +109,7 @@
// RUN: %clang -### -S -fprofile-instr-generate -fcoverage-mapping -fno-coverage-mapping %s 2>&1 | FileCheck -check-prefix=CHECK-DISABLE-COVERAGE %s
// CHECK-PROFILE-GENERATE: "-fprofile-instrument=clang"
// CHECK-PROFILE-GENERATE-LLVM: "-fprofile-instrument=llvm"
-// CHECK-PROFILE-GENERATE-DIR: "-fprofile-instrument-path=/some/dir{{/|\\\\}}default.profraw"
+// CHECK-PROFILE-GENERATE-DIR: "-fprofile-instrument-path=/some/dir{{/|\\\\}}{{.*}}"
// CHECK-PROFILE-GENERATE-FILE: "-fprofile-instrument-path=/tmp/somefile.profraw"
// CHECK-NO-MIX-GEN-USE: '{{[a-z=-]*}}' not allowed with '{{[a-z=-]*}}'
// CHECK-NO-MIX-GENERATE: '{{[a-z=-]*}}' not allowed with '{{[a-z=-]*}}'
@@ -212,7 +222,6 @@
// RUN: -fdefer-pop -fno-defer-pop \
// RUN: -fprefetch-loop-arrays -fno-prefetch-loop-arrays \
// RUN: -fprofile-correction -fno-profile-correction \
-// RUN: -fprofile-dir=bar \
// RUN: -fprofile-values -fno-profile-values \
// RUN: -frounding-math -fno-rounding-math \
// RUN: -fsee -fno-see \
@@ -290,7 +299,6 @@
// RUN: -fkeep-inline-functions \
// RUN: -fno-keep-inline-functions \
// RUN: -freorder-blocks \
-// RUN: -fprofile-dir=/rand/dir \
// RUN: -falign-functions \
// RUN: -falign-functions=1 \
// RUN: -ffloat-store \
@@ -357,7 +365,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 '-fprofile-dir=/rand/dir' 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
@@ -462,3 +469,11 @@
// CHECK-WCHAR2: -fshort-wchar
// CHECK-WCHAR2-NOT: -fno-short-wchar
// DELIMITERS: {{^ *"}}
+
+// RUN: %clang -### -fno-experimental-new-pass-manager -fexperimental-new-pass-manager %s 2>&1 | FileCheck --check-prefix=CHECK-PM --check-prefix=CHECK-NEW-PM %s
+// RUN: %clang -### -fexperimental-new-pass-manager -fno-experimental-new-pass-manager %s 2>&1 | FileCheck --check-prefix=CHECK-PM --check-prefix=CHECK-NO-NEW-PM %s
+// CHECK-PM-NOT: argument unused
+// CHECK-NEW-PM: -fexperimental-new-pass-manager
+// CHECK-NEW-PM-NOT: -fno-experimental-new-pass-manager
+// CHECK-NO-NEW-PM: -fno-experimental-new-pass-manager
+// CHECK-NO-NEW-PM-NOT: -fexperimental-new-pass-manager
diff --git a/test/Driver/compilation_database.c b/test/Driver/compilation_database.c
new file mode 100644
index 000000000000..d5bafd41a647
--- /dev/null
+++ b/test/Driver/compilation_database.c
@@ -0,0 +1,11 @@
+// RUN: cd "%T"
+// RUN: %clang -MD -MP --sysroot=somewhere -c -x c %s -xc++ %s -Wall -MJ - -no-canonical-prefixes 2>&1 | FileCheck %s
+// RUN: not %clang -c -x c %s -MJ %s/non-existant -no-canonical-prefixes 2>&1 | FileCheck --check-prefix=ERROR %s
+
+// CHECK: { "directory": "{{.*}}", "file": "[[SRC:[^"]+[/|\\]compilation_database.c]]", "output": "compilation_database.o", "arguments": ["{{[^"]*}}clang{{[^"]*}}", "-xc", "[[SRC]]", "--sysroot=somewhere", "-c", "-Wall",{{.*}} "--target={{[^"]+}}"]},
+// CHECK: { "directory": "{{.*}}", "file": "[[SRC:[^"]+[/|\\]compilation_database.c]]", "output": "compilation_database.o", "arguments": ["{{[^"]*}}clang{{[^"]*}}", "-xc++", "[[SRC]]", "--sysroot=somewhere", "-c", "-Wall",{{.*}} "--target={{[^"]+}}"]},
+// ERROR: error: compilation database '{{.*}}/non-existant' could not be opened:
+
+int main(void) {
+ return 0;
+}
diff --git a/test/Driver/coroutines.c b/test/Driver/coroutines.c
new file mode 100644
index 000000000000..d61023450ad1
--- /dev/null
+++ b/test/Driver/coroutines.c
@@ -0,0 +1,6 @@
+// RUN: %clang -### %s 2>&1 | FileCheck -check-prefix=CHECK-NO-CORO %s
+// RUN: %clang -fcoroutines-ts -### %s 2>&1 | FileCheck -check-prefix=CHECK-NO-CORO %s
+// RUN: %clang -fno-coroutines-ts -### %s 2>&1 | FileCheck -check-prefix=CHECK-NO-CORO %s
+// RUN: %clang -fno-coroutines-ts -fcoroutines-ts -### %s 2>&1 | FileCheck -check-prefix=CHECK-NO-CORO %s
+// CHECK-NO-CORO-NOT: -fcoroutines-ts
+
diff --git a/test/Driver/coroutines.cpp b/test/Driver/coroutines.cpp
new file mode 100644
index 000000000000..99e0ff57dda2
--- /dev/null
+++ b/test/Driver/coroutines.cpp
@@ -0,0 +1,9 @@
+// RUN: %clang -### %s 2>&1 | FileCheck -check-prefix=CHECK-NO-CORO %s
+// RUN: %clang -fcoroutines-ts -fno-coroutines-ts -### %s 2>&1 | FileCheck -check-prefix=CHECK-NO-CORO %s
+// RUN: %clang -fno-coroutines-ts -### %s 2>&1 | FileCheck -check-prefix=CHECK-NO-CORO %s
+// CHECK-NO-CORO-NOT: -fcoroutines-ts
+
+// RUN: %clang -fcoroutines-ts -### %s 2>&1 | FileCheck -check-prefix=CHECK-HAS-CORO %s
+// RUN: %clang -fno-coroutines-ts -fcoroutines-ts -### %s 2>&1 | FileCheck -check-prefix=CHECK-HAS-CORO %s
+// CHECK-HAS-CORO: -fcoroutines-ts
+
diff --git a/test/Driver/coverage_no_integrated_as.c b/test/Driver/coverage_no_integrated_as.c
index 9a0a0c203e7d..9acab9bbd172 100644
--- a/test/Driver/coverage_no_integrated_as.c
+++ b/test/Driver/coverage_no_integrated_as.c
@@ -17,7 +17,7 @@
// RUN: %clang -### -c -fprofile-arcs -no-integrated-as %s -o foo/bar.o 2>&1 | FileCheck -check-prefix=CHECK-GCNO-LOCATION-REL-PATH %s
-// CHECK-GCNO-DEFAULT-LOCATION: "-coverage-file" "{{.*}}{{/|\\\\}}coverage_no_integrated_as.c"
-// CHECK-GCNO-DEFAULT-LOCATION-NOT: "-coverage-file" "/tmp/{{.*}}/coverage_no_integrated_as.c"
-// CHECK-GCNO-LOCATION: "-coverage-file" "{{.*}}/foo/bar.o"
-// CHECK-GCNO-LOCATION-REL-PATH: "-coverage-file" "{{.*}}{{/|\\\\}}foo/bar.o"
+// CHECK-GCNO-DEFAULT-LOCATION: "-coverage-notes-file" "{{.*}}{{/|\\\\}}coverage_no_integrated_as.c"
+// CHECK-GCNO-DEFAULT-LOCATION-NOT: "-coverage-notes-file" "/tmp/{{.*}}/coverage_no_integrated_as.c"
+// CHECK-GCNO-LOCATION: "-coverage-notes-file" "{{.*}}/foo/bar.gcno"
+// CHECK-GCNO-LOCATION-REL-PATH: "-coverage-notes-file" "{{.*}}{{/|\\\\}}foo/bar.gcno"
diff --git a/test/Driver/crash-report-crashfile.m b/test/Driver/crash-report-crashfile.m
new file mode 100644
index 000000000000..71f6e7a9e129
--- /dev/null
+++ b/test/Driver/crash-report-crashfile.m
@@ -0,0 +1,17 @@
+// REQUIRES: crash-recovery, shell, system-darwin
+// 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
+
+@import simple;
+const int x = MODULE_MACRO;
+
+// CHECK: Preprocessed source(s) and associated run script(s) are located at:
+// CHECK-NEXT: note: diagnostic msg: {{.*}}.m
+// CHECK-NEXT: note: diagnostic msg: {{.*}}.cache
+// CHECK-NEXT: note: diagnostic msg: {{.*}}.sh
+// CHECK-NEXT: note: diagnostic msg: Crash backtrace is located in
+// CHECK-NEXT: note: diagnostic msg: {{.*}}Library/Logs/DiagnosticReports{{.*}}
diff --git a/test/Driver/cuda-bad-arch.cu b/test/Driver/cuda-bad-arch.cu
index f92bdcebd0d5..cbc2d11f90e6 100644
--- a/test/Driver/cuda-bad-arch.cu
+++ b/test/Driver/cuda-bad-arch.cu
@@ -19,4 +19,9 @@
// 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.
+// RUN: %clang -### --cuda-host-only -target nvptx-nvidia-cuda -c %s 2>&1 \
+// RUN: | FileCheck -check-prefix HOST_NVPTX %s
+
// OK-NOT: error: Unsupported CUDA gpu architecture
+// HOST_NVPTX: error: unsupported use of NVPTX for host compilation.
diff --git a/test/Driver/cuda-bindings.cu b/test/Driver/cuda-bindings.cu
new file mode 100644
index 000000000000..ae9053ed159f
--- /dev/null
+++ b/test/Driver/cuda-bindings.cu
@@ -0,0 +1,137 @@
+// Tests the bindings generated for a CUDA offloading target for different
+// combinations of:
+// - Number of gpu architectures;
+// - Host/device-only compilation;
+// - User-requested final phase - binary or assembly.
+// It parallels cuda-phases.cu test, but verifies whether output file is temporary or not.
+
+// It's hard to check whether file name is temporary in a portable
+// way. Instead we check whether we've generated a permanent name on
+// device side, which appends '-device-cuda-<triple>' suffix.
+
+// REQUIRES: clang-driver
+// REQUIRES: powerpc-registered-target
+// REQUIRES: nvptx-registered-target
+
+//
+// Test single gpu architecture with complete compilation.
+// No intermediary device files should have "-device-cuda..." in the name.
+//
+// RUN: %clang -target powerpc64le-ibm-linux-gnu -ccc-print-bindings --cuda-gpu-arch=sm_30 %s 2>&1 \
+// RUN: | FileCheck -check-prefix=BIN %s
+// BIN: # "nvptx64-nvidia-cuda" - "clang",{{.*}} output:
+// BIN-NOT: cuda-bindings-device-cuda-nvptx64
+// BIN: # "nvptx64-nvidia-cuda" - "NVPTX::Assembler",{{.*}} output:
+// BIN-NOT: cuda-bindings-device-cuda-nvptx64
+// BIN: # "nvptx64-nvidia-cuda" - "NVPTX::Linker",{{.*}} output:
+// BIN-NOT: cuda-bindings-device-cuda-nvptx64
+// BIN: # "powerpc64le-ibm-linux-gnu" - "clang",{{.*}} output:
+// BIN-NOT: cuda-bindings-device-cuda-nvptx64
+// BIN: # "powerpc64le-ibm-linux-gnu" - "GNU::Linker", inputs:{{.*}}, output: "a.out"
+
+//
+// Test single gpu architecture up to the assemble phase.
+//
+// RUN: %clang -target powerpc64le-ibm-linux-gnu -ccc-print-bindings --cuda-gpu-arch=sm_30 %s -S 2>&1 \
+// RUN: | FileCheck -check-prefix=ASM %s
+// ASM-DAG: # "nvptx64-nvidia-cuda" - "clang",{{.*}} output: "cuda-bindings-cuda-nvptx64-nvidia-cuda-sm_30.s"
+// ASM-DAG: # "powerpc64le-ibm-linux-gnu" - "clang",{{.*}} output: "cuda-bindings.s"
+
+//
+// Test two gpu architectures with complete compilation.
+//
+// RUN: %clang -target powerpc64le-ibm-linux-gnu -ccc-print-bindings --cuda-gpu-arch=sm_30 --cuda-gpu-arch=sm_35 %s 2>&1 \
+// RUN: | FileCheck -check-prefix=BIN2 %s
+// BIN2: # "nvptx64-nvidia-cuda" - "clang",{{.*}} output:
+// BIN2-NOT: cuda-bindings-device-cuda-nvptx64
+// BIN2: # "nvptx64-nvidia-cuda" - "NVPTX::Assembler",{{.*}} output:
+// BIN2-NOT: cuda-bindings-device-cuda-nvptx64
+// BIN2: # "nvptx64-nvidia-cuda" - "clang",{{.*}} output:
+// BIN2-NOT: cuda-bindings-device-cuda-nvptx64
+// BIN2: # "nvptx64-nvidia-cuda" - "NVPTX::Assembler",{{.*}} output:
+// BIN2-NOT: cuda-bindings-device-cuda-nvptx64
+// BIN2: # "nvptx64-nvidia-cuda" - "NVPTX::Linker",{{.*}} output:
+// BIN2-NOT: cuda-bindings-device-cuda-nvptx64
+// BIN2: # "powerpc64le-ibm-linux-gnu" - "clang",{{.*}} output:
+// BIN2-NOT: cuda-bindings-device-cuda-nvptx64
+// BIN2: # "powerpc64le-ibm-linux-gnu" - "GNU::Linker", inputs:{{.*}}, output: "a.out"
+
+//
+// Test two gpu architectures up to the assemble phase.
+//
+// RUN: %clang -target powerpc64le-ibm-linux-gnu -ccc-print-bindings \
+// RUN: --cuda-gpu-arch=sm_30 --cuda-gpu-arch=sm_35 %s -S 2>&1 \
+// RUN: | FileCheck -check-prefix=ASM2 %s
+// ASM2-DAG: # "nvptx64-nvidia-cuda" - "clang",{{.*}} output: "cuda-bindings-cuda-nvptx64-nvidia-cuda-sm_30.s"
+// ASM2-DAG: # "nvptx64-nvidia-cuda" - "clang",{{.*}} output: "cuda-bindings-cuda-nvptx64-nvidia-cuda-sm_35.s"
+// ASM2-DAG: # "powerpc64le-ibm-linux-gnu" - "clang",{{.*}} output: "cuda-bindings.s"
+
+//
+// Test one or more gpu architecture with complete compilation in host-only
+// compilation mode.
+//
+// RUN: %clang -target powerpc64le-ibm-linux-gnu -ccc-print-bindings \
+// RUN: --cuda-gpu-arch=sm_30 %s --cuda-host-only 2>&1 \
+// RUN: | FileCheck -check-prefix=HBIN %s
+// RUN: %clang -target powerpc64le-ibm-linux-gnu -ccc-print-bindings \
+// RUN: --cuda-gpu-arch=sm_30 --cuda-gpu-arch=sm_35 %s --cuda-host-only 2>&1 \
+// RUN: | FileCheck -check-prefix=HBIN %s
+// HBIN: # "powerpc64le-ibm-linux-gnu" - "clang",{{.*}} output:
+// HBIN-NOT: cuda-bindings-device-cuda-nvptx64
+// HBIN: # "powerpc64le-ibm-linux-gnu" - "GNU::Linker", inputs:{{.*}}, output: "a.out"
+
+//
+// Test one or more gpu architecture up to the assemble phase in host-only
+// compilation mode.
+//
+// RUN: %clang -target powerpc64le-ibm-linux-gnu -ccc-print-bindings \
+// RUN: --cuda-gpu-arch=sm_30 %s --cuda-host-only -S 2>&1 \
+// RUN: | FileCheck -check-prefix=HASM %s
+// RUN: %clang -target powerpc64le-ibm-linux-gnu -ccc-print-bindings \
+// RUN: --cuda-gpu-arch=sm_30 --cuda-gpu-arch=sm_35 %s --cuda-host-only -S 2>&1 \
+// RUN: | FileCheck -check-prefix=HASM %s
+// HASM: # "powerpc64le-ibm-linux-gnu" - "clang",{{.*}} output: "cuda-bindings.s"
+
+//
+// Test single gpu architecture with complete compilation in device-only
+// compilation mode.
+//
+// RUN: %clang -target powerpc64le-ibm-linux-gnu -ccc-print-bindings \
+// RUN: --cuda-gpu-arch=sm_30 %s --cuda-device-only 2>&1 \
+// RUN: | FileCheck -check-prefix=DBIN %s
+// DBIN: # "nvptx64-nvidia-cuda" - "clang",{{.*}} output:
+// DBIN-NOT: cuda-bindings-device-cuda-nvptx64
+// DBIN: # "nvptx64-nvidia-cuda" - "NVPTX::Assembler",{{.*}} output: "cuda-bindings-cuda-nvptx64-nvidia-cuda-sm_30.o"
+
+//
+// Test single gpu architecture up to the assemble phase in device-only
+// compilation mode.
+//
+// RUN: %clang -target powerpc64le-ibm-linux-gnu -ccc-print-bindings \
+// RUN: --cuda-gpu-arch=sm_30 %s --cuda-device-only -S 2>&1 \
+// RUN: | FileCheck -check-prefix=DASM %s
+// DASM: # "nvptx64-nvidia-cuda" - "clang",{{.*}} output: "cuda-bindings-cuda-nvptx64-nvidia-cuda-sm_30.s"
+
+//
+// Test two gpu architectures with complete compilation in device-only
+// compilation mode.
+//
+// RUN: %clang -target powerpc64le-ibm-linux-gnu -ccc-print-bindings \
+// RUN: --cuda-gpu-arch=sm_30 --cuda-gpu-arch=sm_35 %s --cuda-device-only 2>&1 \
+// RUN: | FileCheck -check-prefix=DBIN2 %s
+// DBIN2: # "nvptx64-nvidia-cuda" - "clang",{{.*}} output:
+// DBIN2-NOT: cuda-bindings-device-cuda-nvptx64
+// DBIN2: # "nvptx64-nvidia-cuda" - "NVPTX::Assembler",{{.*}} output: "cuda-bindings-cuda-nvptx64-nvidia-cuda-sm_30.o"
+// DBIN2: # "nvptx64-nvidia-cuda" - "clang",{{.*}} output:
+// DBIN2-NOT: cuda-bindings-device-cuda-nvptx64
+// DBIN2: # "nvptx64-nvidia-cuda" - "NVPTX::Assembler",{{.*}} output: "cuda-bindings-cuda-nvptx64-nvidia-cuda-sm_35.o"
+
+//
+// Test two gpu architectures up to the assemble phase in device-only
+// compilation mode.
+//
+// RUN: %clang -target powerpc64le-ibm-linux-gnu -ccc-print-bindings \
+// RUN: --cuda-gpu-arch=sm_30 --cuda-gpu-arch=sm_35 %s --cuda-device-only -S 2>&1 \
+// RUN: | FileCheck -check-prefix=DASM2 %s
+// DASM2: # "nvptx64-nvidia-cuda" - "clang",{{.*}} output: "cuda-bindings-cuda-nvptx64-nvidia-cuda-sm_30.s"
+// DASM2: # "nvptx64-nvidia-cuda" - "clang",{{.*}} output: "cuda-bindings-cuda-nvptx64-nvidia-cuda-sm_35.s"
diff --git a/test/Driver/cuda-detect.cu b/test/Driver/cuda-detect.cu
index d8fba06605e9..aaef89ac453d 100644
--- a/test/Driver/cuda-detect.cu
+++ b/test/Driver/cuda-detect.cu
@@ -5,60 +5,138 @@
// # 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: %clang -v --target=i386-apple-macosx \
+// RUN: --sysroot=%S/no-cuda-there 2>&1 | FileCheck %s -check-prefix NOCUDA
+
// RUN: %clang -v --target=i386-unknown-linux \
// RUN: --sysroot=%S/Inputs/CUDA 2>&1 | FileCheck %s
+// RUN: %clang -v --target=i386-apple-macosx \
+// RUN: --sysroot=%S/Inputs/CUDA 2>&1 | FileCheck %s
+
// RUN: %clang -v --target=i386-unknown-linux \
// RUN: --cuda-path=%S/Inputs/CUDA/usr/local/cuda 2>&1 | FileCheck %s
+// RUN: %clang -v --target=i386-apple-macosx \
+// RUN: --cuda-path=%S/Inputs/CUDA/usr/local/cuda 2>&1 | FileCheck %s
-// Make sure we map libdevice bitcode files to proper GPUs.
+// Make sure we map libdevice bitcode files to proper GPUs. These
+// tests use Inputs/CUDA_80 which has full set of libdevice files.
+// However, libdevice mapping only matches CUDA-7.x at the moment.
+// sm_2x, sm_32 -> compute_20
// RUN: %clang -### -v --target=i386-unknown-linux --cuda-gpu-arch=sm_21 \
+// RUN: --cuda-path=%S/Inputs/CUDA_80/usr/local/cuda %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix COMMON \
+// RUN: -check-prefix LIBDEVICE -check-prefix LIBDEVICE20
+// RUN: %clang -### -v --target=i386-unknown-linux --cuda-gpu-arch=sm_32 \
+// RUN: --cuda-path=%S/Inputs/CUDA_80/usr/local/cuda %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix COMMON \
+// RUN: -check-prefix LIBDEVICE -check-prefix LIBDEVICE20
+// sm_30, sm_6x map to compute_30.
+// RUN: %clang -### -v --target=i386-unknown-linux --cuda-gpu-arch=sm_30 \
+// RUN: --cuda-path=%S/Inputs/CUDA_80/usr/local/cuda %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix COMMON \
+// RUN: -check-prefix LIBDEVICE -check-prefix LIBDEVICE30
+// sm_5x is a special case. Maps to compute_30 for cuda-7.x only.
+// RUN: %clang -### -v --target=i386-unknown-linux --cuda-gpu-arch=sm_50 \
// RUN: --cuda-path=%S/Inputs/CUDA/usr/local/cuda %s 2>&1 \
// RUN: | FileCheck %s -check-prefix COMMON \
-// RUN: -check-prefix LIBDEVICE -check-prefix LIBDEVICE21
+// RUN: -check-prefix LIBDEVICE -check-prefix LIBDEVICE30
+// RUN: %clang -### -v --target=i386-unknown-linux --cuda-gpu-arch=sm_60 \
+// RUN: --cuda-path=%S/Inputs/CUDA_80/usr/local/cuda %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix COMMON \
+// RUN: -check-prefix LIBDEVICE -check-prefix LIBDEVICE30
+// sm_35 and sm_37 -> compute_35
// RUN: %clang -### -v --target=i386-unknown-linux --cuda-gpu-arch=sm_35 \
-// RUN: --cuda-path=%S/Inputs/CUDA/usr/local/cuda %s 2>&1 \
+// RUN: --cuda-path=%S/Inputs/CUDA_80/usr/local/cuda %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix COMMON -check-prefix CUDAINC \
+// RUN: -check-prefix LIBDEVICE -check-prefix LIBDEVICE35
+// RUN: %clang -### -v --target=i386-unknown-linux --cuda-gpu-arch=sm_37 \
+// RUN: --cuda-path=%S/Inputs/CUDA_80/usr/local/cuda %s 2>&1 \
// RUN: | FileCheck %s -check-prefix COMMON -check-prefix CUDAINC \
// RUN: -check-prefix LIBDEVICE -check-prefix LIBDEVICE35
+// sm_5x -> compute_50 for CUDA-8.0 and newer.
+// RUN: %clang -### -v --target=i386-unknown-linux --cuda-gpu-arch=sm_50 \
+// RUN: --cuda-path=%S/Inputs/CUDA_80/usr/local/cuda %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix COMMON \
+// RUN: -check-prefix LIBDEVICE -check-prefix LIBDEVICE50
+
// Verify that -nocudainc prevents adding include path to CUDA headers.
// RUN: %clang -### -v --target=i386-unknown-linux --cuda-gpu-arch=sm_35 \
// RUN: -nocudainc --cuda-path=%S/Inputs/CUDA/usr/local/cuda %s 2>&1 \
// RUN: | FileCheck %s -check-prefix COMMON -check-prefix NOCUDAINC \
// RUN: -check-prefix LIBDEVICE -check-prefix LIBDEVICE35
+// RUN: %clang -### -v --target=i386-apple-macosx --cuda-gpu-arch=sm_35 \
+// RUN: -nocudainc --cuda-path=%S/Inputs/CUDA/usr/local/cuda %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix COMMON -check-prefix NOCUDAINC \
+// RUN: -check-prefix LIBDEVICE -check-prefix LIBDEVICE35
+
// We should not add any CUDA include paths if there's no valid CUDA installation
// RUN: %clang -### -v --target=i386-unknown-linux --cuda-gpu-arch=sm_35 \
// RUN: --cuda-path=%S/no-cuda-there %s 2>&1 \
// RUN: | FileCheck %s -check-prefix COMMON -check-prefix NOCUDAINC
+// RUN: %clang -### -v --target=i386-apple-macosx --cuda-gpu-arch=sm_35 \
+// RUN: --cuda-path=%S/no-cuda-there %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix COMMON -check-prefix NOCUDAINC
-// Verify that no options related to bitcode linking are passes if
-// there's no bitcode file.
-// RUN: %clang -### -v --target=i386-unknown-linux --cuda-gpu-arch=sm_30 \
+// Verify that we get an error if there's no libdevice library to link with.
+// NOTE: Inputs/CUDA deliberately does *not* have libdevice.compute_20 for this purpose.
+// RUN: %clang -### -v --target=i386-unknown-linux --cuda-gpu-arch=sm_20 \
// RUN: --cuda-path=%S/Inputs/CUDA/usr/local/cuda %s 2>&1 \
-// RUN: | FileCheck %s -check-prefix COMMON -check-prefix NOLIBDEVICE
-// .. or if we explicitly passed -nocudalib
+// RUN: | FileCheck %s -check-prefix COMMON -check-prefix MISSINGLIBDEVICE
+// RUN: %clang -### -v --target=i386-apple-macosx --cuda-gpu-arch=sm_20 \
+// RUN: --cuda-path=%S/Inputs/CUDA/usr/local/cuda %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix COMMON -check-prefix MISSINGLIBDEVICE
+
+// Verify that -nocudalib prevents linking libdevice bitcode in.
// RUN: %clang -### -v --target=i386-unknown-linux --cuda-gpu-arch=sm_35 \
// RUN: -nocudalib --cuda-path=%S/Inputs/CUDA/usr/local/cuda %s 2>&1 \
// RUN: | FileCheck %s -check-prefix COMMON -check-prefix NOLIBDEVICE
+// RUN: %clang -### -v --target=i386-apple-macosx --cuda-gpu-arch=sm_35 \
+// RUN: -nocudalib --cuda-path=%S/Inputs/CUDA/usr/local/cuda %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix COMMON -check-prefix NOLIBDEVICE
+
// Verify that we don't add include paths, link with libdevice or
// -include __clang_cuda_runtime_wrapper.h without valid CUDA installation.
// RUN: %clang -### -v --target=i386-unknown-linux --cuda-gpu-arch=sm_35 \
// RUN: --cuda-path=%S/no-cuda-there %s 2>&1 \
// RUN: | FileCheck %s -check-prefix COMMON \
// RUN: -check-prefix NOCUDAINC -check-prefix NOLIBDEVICE
+// RUN: %clang -### -v --target=i386-apple-macosx --cuda-gpu-arch=sm_35 \
+// RUN: --cuda-path=%S/no-cuda-there %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix COMMON \
+// RUN: -check-prefix NOCUDAINC -check-prefix NOLIBDEVICE
+
+// Verify that C++ include paths are passed for both host and device frontends.
+// RUN: %clang -### -no-canonical-prefixes -target x86_64-linux-gnu %s \
+// RUN: --stdlib=libstdc++ --sysroot=%S/Inputs/ubuntu_14.04_multiarch_tree2 \
+// RUN: --gcc-toolchain="" 2>&1 \
+// RUN: | FileCheck %s --check-prefix CHECK-CXXINCLUDE
// CHECK: Found CUDA installation: {{.*}}/Inputs/CUDA/usr/local/cuda
// NOCUDA-NOT: Found CUDA installation:
+// MISSINGLIBDEVICE: error: cannot find libdevice for sm_20.
+
// COMMON: "-triple" "nvptx-nvidia-cuda"
// COMMON-SAME: "-fcuda-is-device"
// LIBDEVICE-SAME: "-mlink-cuda-bitcode"
// NOLIBDEVICE-NOT: "-mlink-cuda-bitcode"
-// LIBDEVICE21-SAME: libdevice.compute_20.10.bc
+// LIBDEVICE20-SAME: libdevice.compute_20.10.bc
+// LIBDEVICE30-SAME: libdevice.compute_30.10.bc
// LIBDEVICE35-SAME: libdevice.compute_35.10.bc
+// LIBDEVICE50-SAME: libdevice.compute_50.10.bc
// NOLIBDEVICE-NOT: libdevice.compute_{{.*}}.bc
// LIBDEVICE-SAME: "-target-feature" "+ptx42"
// NOLIBDEVICE-NOT: "-target-feature" "+ptx42"
-// CUDAINC-SAME: "-internal-isystem" "{{.*}}/Inputs/CUDA/usr/local/cuda/include"
+// CUDAINC-SAME: "-internal-isystem" "{{.*}}/Inputs/CUDA{{[_0-9]+}}/usr/local/cuda/include"
// NOCUDAINC-NOT: "-internal-isystem" "{{.*}}/cuda/include"
// CUDAINC-SAME: "-include" "__clang_cuda_runtime_wrapper.h"
// NOCUDAINC-NOT: "-include" "__clang_cuda_runtime_wrapper.h"
+// -internal-externc-isystem flags must come *after* the cuda include flags,
+// because we must search the cuda include directory first.
+// CUDAINC-SAME: "-internal-externc-isystem"
// COMMON-SAME: "-x" "cuda"
+// CHECK-CXXINCLUDE: clang{{.*}} "-cc1" "-triple" "nvptx64-nvidia-cuda"
+// CHECK-CXXINCLUDE-SAME: {{.*}}"-internal-isystem" "{{.+}}/include/c++/4.8"
+// CHECK-CXXINCLUDE: clang{{.*}} "-cc1" "-triple" "x86_64--linux-gnu"
+// CHECK-CXXINCLUDE-SAME: {{.*}}"-internal-isystem" "{{.+}}/include/c++/4.8"
+// CHECK-CXXINCLUDE: ld{{.*}}"
diff --git a/test/Driver/cuda-external-tools.cu b/test/Driver/cuda-external-tools.cu
index 280c60966bd0..f0f5c154c977 100644
--- a/test/Driver/cuda-external-tools.cu
+++ b/test/Driver/cuda-external-tools.cu
@@ -1,4 +1,5 @@
-// Tests that ptxas and fatbinary are correctly during CUDA compilation.
+// Tests that ptxas and fatbinary are invoked correctly during CUDA
+// compilation.
//
// REQUIRES: clang-driver
// REQUIRES: x86-registered-target
@@ -56,6 +57,14 @@
// RUN: | FileCheck -check-prefix SM20 -check-prefix PTXAS-EXTRA \
// RUN: -check-prefix 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: %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
+
// Match clang job that produces PTX assembly.
// CHECK: "-cc1" "-triple" "nvptx64-nvidia-cuda"
// SM20: "-target-cpu" "sm_20"
diff --git a/test/Driver/cuda-macosx.cu b/test/Driver/cuda-macosx.cu
new file mode 100644
index 000000000000..ad0bcf756e31
--- /dev/null
+++ b/test/Driver/cuda-macosx.cu
@@ -0,0 +1,8 @@
+// REQUIRES: clang-driver
+// REQUIRES: x86-registered-target
+// REQUIRES: nvptx-registered-target
+//
+// RUN: %clang -v --target=i386-apple-macosx \
+// RUN: --sysroot=%S/Inputs/CUDA-macosx 2>&1 | FileCheck %s
+
+// CHECK: Found CUDA installation: {{.*}}/Inputs/CUDA-macosx/usr/local/cuda
diff --git a/test/Driver/cuda-no-sanitizers.cu b/test/Driver/cuda-no-sanitizers.cu
new file mode 100644
index 000000000000..a466b42d8c42
--- /dev/null
+++ b/test/Driver/cuda-no-sanitizers.cu
@@ -0,0 +1,13 @@
+// Check that -fsanitize=foo doesn't get passed down to device-side
+// compilation.
+//
+// REQUIRES: clang-driver
+//
+// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-gpu-arch=sm_20 -fsanitize=address %s 2>&1 | \
+// RUN: FileCheck %s
+
+// CHECK-NOT: error: unsupported option '-fsanitize=address'
+// CHECK-DAG: "-fcuda-is-device"
+// CHECK-NOT: "-fsanitize=address"
+// CHECK-DAG: "-triple" "x86_64--linux-gnu"
+// CHECK: "-fsanitize=address"
diff --git a/test/Driver/cuda-options.cu b/test/Driver/cuda-options.cu
index 5d650761fb22..c4bfda903d9e 100644
--- a/test/Driver/cuda-options.cu
+++ b/test/Driver/cuda-options.cu
@@ -64,9 +64,9 @@
// Verify that --cuda-gpu-arch option passes the correct GPU archtecture to
// device compilation.
-// RUN: %clang -### -target x86_64-linux-gnu --cuda-gpu-arch=sm_35 -c %s 2>&1 \
+// 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 \
-// RUN: -check-prefix DEVICE-SM35 -check-prefix HOST \
+// RUN: -check-prefix DEVICE-SM30 -check-prefix HOST \
// RUN: -check-prefix INCLUDES-DEVICE -check-prefix NOLINK %s
// Verify that there is one device-side compilation per --cuda-gpu-arch args
@@ -74,8 +74,8 @@
// 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-SM35 \
-// RUN: -check-prefix DEVICE2-SM30 -check-prefix HOST \
+// 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
@@ -92,6 +92,65 @@
// RUN: -check-prefix HOST -check-prefix HOST-NOSAVE \
// 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
+// 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
+// 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
+// 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 \
+// RUN: --no-cuda-gpu-arch=sm_35 --no-cuda-gpu-arch=sm_30 \
+// RUN: -c %s 2>&1 \
+// RUN: | FileCheck -check-prefixes ARCH-SM20,NOARCH-SM30,NOARCH-SM35 %s
+
+// d) --no-cuda-gpu-arch=X is a no-op if there's no 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_50 \
+// RUN: -c %s 2>&1 \
+// RUN: | FileCheck -check-prefixes NOARCH-SM20,ARCH-SM30,ARCH-SM35 %s
+
+// e) --no-cuda-gpu-arch=X does not affect following --cuda-gpu-arch=X
+// RUN: %clang -### -target x86_64-linux-gnu --cuda-device-only \
+// RUN: --no-cuda-gpu-arch=sm_35 --no-cuda-gpu-arch=sm_30 \
+// RUN: --cuda-gpu-arch=sm_35 --cuda-gpu-arch=sm_30 \
+// RUN: -c %s 2>&1 \
+// RUN: | FileCheck -check-prefixes NOARCH-SM20,ARCH-SM30,ARCH-SM35 %s
+
+// f) --no-cuda-gpu-arch=all negates all preceding --cuda-gpu-arch=X
+// RUN: %clang -### -target x86_64-linux-gnu --cuda-device-only \
+// RUN: --cuda-gpu-arch=sm_20 --cuda-gpu-arch=sm_30 \
+// RUN: --no-cuda-gpu-arch=all \
+// RUN: --cuda-gpu-arch=sm_35 \
+// RUN: -c %s 2>&1 \
+// RUN: | FileCheck -check-prefixes NOARCH-SM20,NOARCH-SM30,ARCH-SM35 %s
+
+// g) There's no --cuda-gpu-arch=all
+// RUN: %clang -### -target x86_64-linux-gnu --cuda-device-only \
+// RUN: --cuda-gpu-arch=all \
+// RUN: -c %s 2>&1 \
+// RUN: | FileCheck -check-prefix ARCHALLERROR %s
+
+// ARCH-SM20: "-cc1"{{.*}}"-target-cpu" "sm_20"
+// NOARCH-SM20-NOT: "-cc1"{{.*}}"-target-cpu" "sm_20"
+// ARCH-SM30: "-cc1"{{.*}}"-target-cpu" "sm_30"
+// NOARCH-SM30-NOT: "-cc1"{{.*}}"-target-cpu" "sm_30"
+// ARCH-SM35: "-cc1"{{.*}}"-target-cpu" "sm_35"
+// NOARCH-SM35-NOT: "-cc1"{{.*}}"-target-cpu" "sm_35"
+// ARCHALLERROR: error: Unsupported CUDA gpu architecture: all
+
// Match device-side preprocessor and compiler phases with -save-temps.
// DEVICE-SAVE: "-cc1" "-triple" "nvptx64-nvidia-cuda"
// DEVICE-SAVE-SAME: "-aux-triple" "x86_64--linux-gnu"
@@ -107,14 +166,14 @@
// DEVICE: "-cc1" "-triple" "nvptx64-nvidia-cuda"
// DEVICE-NOSAVE-SAME: "-aux-triple" "x86_64--linux-gnu"
// DEVICE-SAME: "-fcuda-is-device"
-// DEVICE-SM35-SAME: "-target-cpu" "sm_35"
+// DEVICE-SM30-SAME: "-target-cpu" "sm_30"
// DEVICE-SAME: "-o" "[[PTXFILE:[^"]*]]"
// DEVICE-NOSAVE-SAME: "-x" "cuda"
// DEVICE-SAVE-SAME: "-x" "ir"
// Match the call to ptxas (which assembles PTX to SASS).
// DEVICE:ptxas
-// DEVICE-SM35-DAG: "--gpu-name" "sm_35"
+// DEVICE-SM30-DAG: "--gpu-name" "sm_30"
// DEVICE-DAG: "--output-file" "[[CUBINFILE:[^"]*]]"
// DEVICE-DAG: "[[PTXFILE]]"
@@ -122,7 +181,7 @@
// DEVICE2: "-cc1" "-triple" "nvptx64-nvidia-cuda"
// DEVICE2-SAME: "-aux-triple" "x86_64--linux-gnu"
// DEVICE2-SAME: "-fcuda-is-device"
-// DEVICE2-SM30-SAME: "-target-cpu" "sm_30"
+// DEVICE2-SM35-SAME: "-target-cpu" "sm_35"
// DEVICE2-SAME: "-o" "[[GPUBINARY2:[^"]*]]"
// DEVICE2-SAME: "-x" "cuda"
diff --git a/test/Driver/cuda-output-asm.cu b/test/Driver/cuda-output-asm.cu
index af62478ac27e..8ca87a5caa5c 100644
--- a/test/Driver/cuda-output-asm.cu
+++ b/test/Driver/cuda-output-asm.cu
@@ -1,4 +1,4 @@
-// Tests CUDA compilation with -S.
+// Tests CUDA compilation with -S and -emit-llvm.
// REQUIRES: clang-driver
// REQUIRES: x86-registered-target
@@ -26,4 +26,8 @@
// RUN: %clang -### -S -target x86_64-linux-gnu --cuda-device-only \
// RUN: --cuda-gpu-arch=sm_20 --cuda-gpu-arch=sm_30 -o foo.s %s 2>&1 \
// RUN: | FileCheck -check-prefix MULTIPLE-OUTPUT-FILES %s
+// RUN: %clang -### -emit-llvm -c -target x86_64-linux-gnu -o foo.s %s 2>&1 \
+// RUN: | FileCheck -check-prefix MULTIPLE-OUTPUT-FILES %s
// MULTIPLE-OUTPUT-FILES: error: cannot specify -o when generating multiple output files
+// Make sure we do not get duplicate diagnostics.
+// MULTIPLE-OUTPUT-FILES-NOT: error: cannot specify -o when generating multiple output files
diff --git a/test/Driver/cuda-phases.cu b/test/Driver/cuda-phases.cu
new file mode 100644
index 000000000000..6d5d2251ade2
--- /dev/null
+++ b/test/Driver/cuda-phases.cu
@@ -0,0 +1,201 @@
+// Tests the phases generated for a CUDA offloading target for different
+// combinations of:
+// - Number of gpu architectures;
+// - Host/device-only compilation;
+// - User-requested final phase - binary or assembly.
+
+// REQUIRES: clang-driver
+// REQUIRES: powerpc-registered-target
+// REQUIRES: nvptx-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)
+
+//
+// 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)
+
+//
+// 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)
+
+//
+// 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)
+
+//
+// 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)
+//
+// 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)
+
+//
+// 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)
+
+//
+// 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)
+
+//
+// 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
+
+//
+// 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
+
+//
+// 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
+
+//
+// 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
diff --git a/test/Driver/cuda-ptxas-path.cu b/test/Driver/cuda-ptxas-path.cu
new file mode 100644
index 000000000000..3ac5932b067a
--- /dev/null
+++ b/test/Driver/cuda-ptxas-path.cu
@@ -0,0 +1,12 @@
+// REQUIRES: clang-driver
+// REQUIRES: x86-registered-target
+// REQUIRES: nvptx-registered-target
+
+// RUN: %clang -### --target=i386-unknown-linux \
+// RUN: --cuda-path=%S/Inputs/CUDA_80/usr/local/cuda \
+// RUN: --ptxas-path=/some/path/to/ptxas %s 2>&1 \
+// RUN: | FileCheck %s
+
+// CHECK-NOT: "ptxas"
+// CHECK: "/some/path/to/ptxas"
+// CHECK-SAME: "--gpu-name" "sm_20"
diff --git a/test/Driver/cuda-simple.cu b/test/Driver/cuda-simple.cu
index 3dc0babea7b0..fbc5aa141335 100644
--- a/test/Driver/cuda-simple.cu
+++ b/test/Driver/cuda-simple.cu
@@ -1,6 +1,6 @@
// Verify that we can parse a simple CUDA file with or without -save-temps
// http://llvm.org/PR22936
-// RUN: %clang -nocudainc -Werror -fsyntax-only -c %s
+// RUN: %clang -nocudainc -nocudalib -Werror -fsyntax-only -c %s
//
// Verify that we pass -x cuda-cpp-output to compiler after
// preprocessing a CUDA file
diff --git a/test/Driver/cuda-version-check.cu b/test/Driver/cuda-version-check.cu
index 65bdd16f96de..cb2ac7994f75 100644
--- a/test/Driver/cuda-version-check.cu
+++ b/test/Driver/cuda-version-check.cu
@@ -39,6 +39,15 @@
// RUN: --no-cuda-version-check %s | \
// RUN: FileCheck %s --check-prefix=OK
+// We need to make sure the version check is done only for the device toolchain,
+// 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 -v -### --cuda-gpu-arch=sm_60 --cuda-host-only --sysroot=%S/Inputs/CUDA -S 2>&1 %s | \
+// RUN: FileCheck %s --check-prefix=OK
+// RUN: %clang -v -### --cuda-gpu-arch=sm_60 --cuda-device-only --sysroot=%S/Inputs/CUDA -S 2>&1 %s | \
+// RUN: FileCheck %s --check-prefix=ERR_SM60
+
// OK-NOT: error: GPU arch
// OK_SM35-NOT: error: GPU arch sm_35
diff --git a/test/Driver/cuda_phases.cu b/test/Driver/cuda_phases.cu
deleted file mode 100644
index 6cfb61aba72a..000000000000
--- a/test/Driver/cuda_phases.cu
+++ /dev/null
@@ -1,206 +0,0 @@
-// Tests the phases generated for a CUDA offloading target for different
-// combinations of:
-// - Number of gpu architectures;
-// - Host/device-only compilation;
-// - User-requested final phase - binary or assembly.
-
-// REQUIRES: clang-driver
-// REQUIRES: powerpc-registered-target
-// REQUIRES: nvptx-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: 0: input, "{{.*}}cuda_phases.cu", cuda, (host-cuda)
-// BIN: 1: preprocessor, {0}, cuda-cpp-output, (host-cuda)
-// BIN: 2: compiler, {1}, ir, (host-cuda)
-// BIN: 3: input, "{{.*}}cuda_phases.cu", cuda, (device-cuda, sm_30)
-// BIN: 4: preprocessor, {3}, cuda-cpp-output, (device-cuda, sm_30)
-// BIN: 5: compiler, {4}, ir, (device-cuda, sm_30)
-// BIN: 6: backend, {5}, assembler, (device-cuda, sm_30)
-// BIN: 7: assembler, {6}, object, (device-cuda, sm_30)
-// BIN: 8: offload, "device-cuda (nvptx64-nvidia-cuda:sm_30)" {7}, object
-// BIN: 9: offload, "device-cuda (nvptx64-nvidia-cuda:sm_30)" {6}, assembler
-// BIN: 10: linker, {8, 9}, cuda-fatbin, (device-cuda)
-// BIN: 11: offload, "host-cuda (powerpc64le-ibm-linux-gnu)" {2}, "device-cuda (nvptx64-nvidia-cuda)" {10}, ir
-// BIN: 12: backend, {11}, assembler, (host-cuda)
-// BIN: 13: assembler, {12}, object, (host-cuda)
-// BIN: 14: linker, {13}, image, (host-cuda)
-
-//
-// 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: 0: input, "{{.*}}cuda_phases.cu", cuda, (device-cuda, sm_30)
-// ASM: 1: preprocessor, {0}, cuda-cpp-output, (device-cuda, sm_30)
-// ASM: 2: compiler, {1}, ir, (device-cuda, sm_30)
-// ASM: 3: backend, {2}, assembler, (device-cuda, sm_30)
-// ASM: 4: offload, "device-cuda (nvptx64-nvidia-cuda:sm_30)" {3}, assembler
-// ASM: 5: input, "{{.*}}cuda_phases.cu", cuda, (host-cuda)
-// ASM: 6: preprocessor, {5}, cuda-cpp-output, (host-cuda)
-// ASM: 7: compiler, {6}, ir, (host-cuda)
-// ASM: 8: backend, {7}, assembler, (host-cuda)
-
-//
-// 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: 0: input, "{{.*}}cuda_phases.cu", cuda, (host-cuda)
-// BIN2: 1: preprocessor, {0}, cuda-cpp-output, (host-cuda)
-// BIN2: 2: compiler, {1}, ir, (host-cuda)
-// BIN2: 3: input, "{{.*}}cuda_phases.cu", cuda, (device-cuda, sm_30)
-// BIN2: 4: preprocessor, {3}, cuda-cpp-output, (device-cuda, sm_30)
-// BIN2: 5: compiler, {4}, ir, (device-cuda, sm_30)
-// BIN2: 6: backend, {5}, assembler, (device-cuda, sm_30)
-// BIN2: 7: assembler, {6}, object, (device-cuda, sm_30)
-// BIN2: 8: offload, "device-cuda (nvptx64-nvidia-cuda:sm_30)" {7}, object
-// BIN2: 9: offload, "device-cuda (nvptx64-nvidia-cuda:sm_30)" {6}, assembler
-// BIN2: 10: input, "{{.*}}cuda_phases.cu", cuda, (device-cuda, sm_35)
-// BIN2: 11: preprocessor, {10}, cuda-cpp-output, (device-cuda, sm_35)
-// BIN2: 12: compiler, {11}, ir, (device-cuda, sm_35)
-// BIN2: 13: backend, {12}, assembler, (device-cuda, sm_35)
-// BIN2: 14: assembler, {13}, object, (device-cuda, sm_35)
-// BIN2: 15: offload, "device-cuda (nvptx64-nvidia-cuda:sm_35)" {14}, object
-// BIN2: 16: offload, "device-cuda (nvptx64-nvidia-cuda:sm_35)" {13}, assembler
-// BIN2: 17: linker, {8, 9, 15, 16}, cuda-fatbin, (device-cuda)
-// BIN2: 18: offload, "host-cuda (powerpc64le-ibm-linux-gnu)" {2}, "device-cuda (nvptx64-nvidia-cuda)" {17}, ir
-// BIN2: 19: backend, {18}, assembler, (host-cuda)
-// BIN2: 20: assembler, {19}, object, (host-cuda)
-// BIN2: 21: linker, {20}, image, (host-cuda)
-
-//
-// 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: 0: input, "{{.*}}cuda_phases.cu", cuda, (device-cuda, sm_30)
-// ASM2: 1: preprocessor, {0}, cuda-cpp-output, (device-cuda, sm_30)
-// ASM2: 2: compiler, {1}, ir, (device-cuda, sm_30)
-// ASM2: 3: backend, {2}, assembler, (device-cuda, sm_30)
-// ASM2: 4: offload, "device-cuda (nvptx64-nvidia-cuda:sm_30)" {3}, assembler
-// ASM2: 5: input, "{{.*}}cuda_phases.cu", cuda, (device-cuda, sm_35)
-// ASM2: 6: preprocessor, {5}, cuda-cpp-output, (device-cuda, sm_35)
-// ASM2: 7: compiler, {6}, ir, (device-cuda, sm_35)
-// ASM2: 8: backend, {7}, assembler, (device-cuda, sm_35)
-// ASM2: 9: offload, "device-cuda (nvptx64-nvidia-cuda:sm_35)" {8}, assembler
-// ASM2: 10: input, "{{.*}}cuda_phases.cu", cuda, (host-cuda)
-// ASM2: 11: preprocessor, {10}, cuda-cpp-output, (host-cuda)
-// ASM2: 12: compiler, {11}, ir, (host-cuda)
-// ASM2: 13: backend, {12}, assembler, (host-cuda)
-
-//
-// 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: 0: input, "{{.*}}cuda_phases.cu", cuda, (host-cuda)
-// HBIN: 1: preprocessor, {0}, cuda-cpp-output, (host-cuda)
-// HBIN: 2: compiler, {1}, ir, (host-cuda)
-// HBIN: 3: offload, "host-cuda (powerpc64le-ibm-linux-gnu)" {2}, ir
-// HBIN: 4: backend, {3}, assembler, (host-cuda)
-// HBIN: 5: assembler, {4}, object, (host-cuda)
-// HBIN: 6: linker, {5}, image, (host-cuda)
-
-//
-// 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: 0: input, "{{.*}}cuda_phases.cu", cuda, (host-cuda)
-// HASM: 1: preprocessor, {0}, cuda-cpp-output, (host-cuda)
-// HASM: 2: compiler, {1}, ir, (host-cuda)
-// HASM: 3: offload, "host-cuda (powerpc64le-ibm-linux-gnu)" {2}, ir
-// HASM: 4: backend, {3}, assembler, (host-cuda)
-
-//
-// 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: 0: input, "{{.*}}cuda_phases.cu", cuda, (host-cuda)
-// HBIN2: 1: preprocessor, {0}, cuda-cpp-output, (host-cuda)
-// HBIN2: 2: compiler, {1}, ir, (host-cuda)
-// HBIN2: 3: offload, "host-cuda (powerpc64le-ibm-linux-gnu)" {2}, ir
-// HBIN2: 4: backend, {3}, assembler, (host-cuda)
-// HBIN2: 5: assembler, {4}, object, (host-cuda)
-// HBIN2: 6: linker, {5}, image, (host-cuda)
-
-//
-// 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: 0: input, "{{.*}}cuda_phases.cu", cuda, (host-cuda)
-// HASM2: 1: preprocessor, {0}, cuda-cpp-output, (host-cuda)
-// HASM2: 2: compiler, {1}, ir, (host-cuda)
-// HASM2: 3: offload, "host-cuda (powerpc64le-ibm-linux-gnu)" {2}, ir
-// HASM2: 4: backend, {3}, assembler, (host-cuda)
-
-//
-// 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: 0: input, "{{.*}}cuda_phases.cu", cuda, (device-cuda, sm_30)
-// DBIN: 1: preprocessor, {0}, cuda-cpp-output, (device-cuda, sm_30)
-// DBIN: 2: compiler, {1}, ir, (device-cuda, sm_30)
-// DBIN: 3: backend, {2}, assembler, (device-cuda, sm_30)
-// DBIN: 4: assembler, {3}, object, (device-cuda, sm_30)
-// DBIN: 5: offload, "device-cuda (nvptx64-nvidia-cuda:sm_30)" {4}, 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: 0: input, "{{.*}}cuda_phases.cu", cuda, (device-cuda, sm_30)
-// DASM: 1: preprocessor, {0}, cuda-cpp-output, (device-cuda, sm_30)
-// DASM: 2: compiler, {1}, ir, (device-cuda, sm_30)
-// DASM: 3: backend, {2}, assembler, (device-cuda, sm_30)
-// DASM: 4: offload, "device-cuda (nvptx64-nvidia-cuda:sm_30)" {3}, 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: 0: input, "{{.*}}cuda_phases.cu", cuda, (device-cuda, sm_30)
-// DBIN2: 1: preprocessor, {0}, cuda-cpp-output, (device-cuda, sm_30)
-// DBIN2: 2: compiler, {1}, ir, (device-cuda, sm_30)
-// DBIN2: 3: backend, {2}, assembler, (device-cuda, sm_30)
-// DBIN2: 4: assembler, {3}, object, (device-cuda, sm_30)
-// DBIN2: 5: offload, "device-cuda (nvptx64-nvidia-cuda:sm_30)" {4}, object
-// DBIN2: 6: input, "{{.*}}cuda_phases.cu", cuda, (device-cuda, sm_35)
-// DBIN2: 7: preprocessor, {6}, cuda-cpp-output, (device-cuda, sm_35)
-// DBIN2: 8: compiler, {7}, ir, (device-cuda, sm_35)
-// DBIN2: 9: backend, {8}, assembler, (device-cuda, sm_35)
-// DBIN2: 10: assembler, {9}, object, (device-cuda, sm_35)
-// DBIN2: 11: offload, "device-cuda (nvptx64-nvidia-cuda:sm_35)" {10}, 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: 0: input, "{{.*}}cuda_phases.cu", cuda, (device-cuda, sm_30)
-// DASM2: 1: preprocessor, {0}, cuda-cpp-output, (device-cuda, sm_30)
-// DASM2: 2: compiler, {1}, ir, (device-cuda, sm_30)
-// DASM2: 3: backend, {2}, assembler, (device-cuda, sm_30)
-// DASM2: 4: offload, "device-cuda (nvptx64-nvidia-cuda:sm_30)" {3}, assembler
-// DASM2: 5: input, "{{.*}}cuda_phases.cu", cuda, (device-cuda, sm_35)
-// DASM2: 6: preprocessor, {5}, cuda-cpp-output, (device-cuda, sm_35)
-// DASM2: 7: compiler, {6}, ir, (device-cuda, sm_35)
-// DASM2: 8: backend, {7}, assembler, (device-cuda, sm_35)
-// DASM2: 9: offload, "device-cuda (nvptx64-nvidia-cuda:sm_35)" {8}, assembler
diff --git a/test/Driver/darwin-debug-flags.c b/test/Driver/darwin-debug-flags.c
index 6ba374523096..e37680e7f94a 100644
--- a/test/Driver/darwin-debug-flags.c
+++ b/test/Driver/darwin-debug-flags.c
@@ -5,7 +5,7 @@
// <rdar://problem/12955296>
// RUN: %clang -### -target i386-apple-darwin9 -c -g %t.s 2>&1 | FileCheck -check-prefix=P %s
-// CHECK: !0 = distinct !DICompileUnit(
+// CHECK: distinct !DICompileUnit(
// CHECK-SAME: flags:
// CHECK-SAME: -I path\5C with\5C \5C\5Cspaces
// CHECK-SAME: -g -Os
diff --git a/test/Driver/darwin-iphone-defaults.m b/test/Driver/darwin-iphone-defaults.m
index 63bbbe0a9c33..d98416d57142 100644
--- a/test/Driver/darwin-iphone-defaults.m
+++ b/test/Driver/darwin-iphone-defaults.m
@@ -26,4 +26,4 @@ void f1() {
[I1 alloc];
}
-// CHECK: attributes [[F0]] = { ssp{{.*}} }
+// CHECK: attributes [[F0]] = { noinline ssp{{.*}} }
diff --git a/test/Driver/darwin-ld-dedup.c b/test/Driver/darwin-ld-dedup.c
new file mode 100644
index 000000000000..a06ca7bebe57
--- /dev/null
+++ b/test/Driver/darwin-ld-dedup.c
@@ -0,0 +1,46 @@
+// REQUIRES: system-darwin
+
+// -no_deduplicate is only present from ld64 version 262 and later.
+// RUN: %clang -target x86_64-apple-darwin10 -### %s \
+// RUN: -mlinker-version=261 -O0 2>&1 | FileCheck -check-prefix=LINK_DEDUP %s
+
+// Add -no_deduplicate when either -O0 or -O1 is explicitly specified
+// RUN: %clang -target x86_64-apple-darwin10 -### %s \
+// RUN: -mlinker-version=262 -O0 2>&1 | FileCheck -check-prefix=LINK_NODEDUP %s
+// RUN: %clang -target x86_64-apple-darwin10 -### %s \
+// RUN: -mlinker-version=262 -O1 2>&1 | FileCheck -check-prefix=LINK_NODEDUP %s
+
+// RUN: %clang -target x86_64-apple-darwin10 -### %s \
+// RUN: -mlinker-version=262 -O2 2>&1 | FileCheck -check-prefix=LINK_DEDUP %s
+// RUN: %clang -target x86_64-apple-darwin10 -### %s \
+// RUN: -mlinker-version=262 -O3 2>&1 | FileCheck -check-prefix=LINK_DEDUP %s
+// RUN: %clang -target x86_64-apple-darwin10 -### %s \
+// RUN: -mlinker-version=262 -Os 2>&1 | FileCheck -check-prefix=LINK_DEDUP %s
+// RUN: %clang -target x86_64-apple-darwin10 -### %s \
+// RUN: -mlinker-version=262 -O4 2>&1 | FileCheck -check-prefix=LINK_DEDUP %s
+// RUN: %clang -target x86_64-apple-darwin10 -### %s \
+// RUN: -mlinker-version=262 -Ofast 2>&1 | FileCheck -check-prefix=LINK_DEDUP %s
+
+// Add -no_deduplicate when no -O option is specified *and* this is a compile+link
+// (implicit -O0)
+// RUN: %clang -target x86_64-apple-darwin10 -### %s \
+// RUN: -mlinker-version=262 2>&1 | FileCheck -check-prefix=LINK_NODEDUP %s
+
+// Do *not* add -no_deduplicate when no -O option is specified and this is just a link
+// (since we can't imply -O0)
+// RUN: rm -f %t.o %t.bin
+// RUN: %clang -target x86_64-apple-darwin10 -c -o %t.o %s
+// RUN: %clang -target x86_64-apple-darwin10 %t.o -### -mlinker-version=262 \
+// RUN: -o %t.bin 2>&1 | FileCheck -check-prefix=LINK_DEDUP %s
+// RUN: %clang -target x86_64-apple-darwin10 %t.o -### -mlinker-version=262 \
+// RUN: -O0 -o %t.bin 2>&1 | FileCheck -check-prefix=LINK_NODEDUP %s
+// RUN: %clang -target x86_64-apple-darwin10 %t.o -### -mlinker-version=262 \
+// RUN: -O1 -o %t.bin 2>&1 | FileCheck -check-prefix=LINK_NODEDUP %s
+// RUN: %clang -target x86_64-apple-darwin10 %t.o -### -mlinker-version=262 \
+// RUN: -O2 -o %t.bin 2>&1 | FileCheck -check-prefix=LINK_DEDUP %s
+
+// LINK_NODEDUP: {{ld(.exe)?"}}
+// LINK_NODEDUP: "-no_deduplicate"
+
+// LINK_DEDUP: {{ld(.exe)?"}}
+// LINK_DEDUP-NOT: "-no_deduplicate"
diff --git a/test/Driver/darwin-ld-lto.c b/test/Driver/darwin-ld-lto.c
index 6b9b79bd011a..21c2214b771f 100644
--- a/test/Driver/darwin-ld-lto.c
+++ b/test/Driver/darwin-ld-lto.c
@@ -2,6 +2,9 @@
// Check that ld gets "-lto_library".
+// RUN: mkdir -p %T/bin
+// RUN: mkdir -p %T/lib
+// RUN: touch %T/lib/libLTO.dylib
// RUN: %clang -target x86_64-apple-darwin10 -### %s \
// RUN: -ccc-install-dir %T/bin -mlinker-version=133 2> %t.log
// RUN: FileCheck -check-prefix=LINK_LTOLIB_PATH %s -input-file %t.log
diff --git a/test/Driver/darwin-ld.c b/test/Driver/darwin-ld.c
index a7681fad8b63..36e7ee53551e 100644
--- a/test/Driver/darwin-ld.c
+++ b/test/Driver/darwin-ld.c
@@ -327,3 +327,17 @@
// LINK_VERSION_DIGITS: invalid version number in '-mlinker-version=133.3.0.1.2.6'
// LINK_VERSION_DIGITS: invalid version number in '-mlinker-version=133.3.0.1.a'
// LINK_VERSION_DIGITS: invalid version number in '-mlinker-version=133.3.0.1a'
+
+// Check that we're passing -lto-pass-remarks-output for LTO
+// RUN: %clang -target x86_64-apple-darwin12 %t.o -fsave-optimization-record -### -o foo/bar.out 2> %t.log
+// RUN: FileCheck -check-prefix=PASS_REMARKS_OUTPUT %s < %t.log
+// PASS_REMARKS_OUTPUT: "-mllvm" "-lto-pass-remarks-output" "-mllvm" "foo/bar.out.opt.yaml"
+// PASS_REMARKS_OUTPUT-NOT: -lto-pass-remarks-with-hotness
+
+// RUN: %clang -target x86_64-apple-darwin12 %t.o -fsave-optimization-record -### 2> %t.log
+// RUN: FileCheck -check-prefix=PASS_REMARKS_OUTPUT_NO_O %s < %t.log
+// PASS_REMARKS_OUTPUT_NO_O: "-mllvm" "-lto-pass-remarks-output" "-mllvm" "a.out.opt.yaml"
+
+// RUN: %clang -target x86_64-apple-darwin12 %t.o -fsave-optimization-record -fprofile-instr-use=blah -### -o foo/bar.out 2> %t.log
+// 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"
diff --git a/test/Driver/darwin-multiarch-arm.c b/test/Driver/darwin-multiarch-arm.c
index 32d4c1f3826b..0ea5c4bf9a69 100644
--- a/test/Driver/darwin-multiarch-arm.c
+++ b/test/Driver/darwin-multiarch-arm.c
@@ -9,6 +9,6 @@
// CHECK:"-cc1" "-triple" "thumbv7s-apple-ios5.0.0"
// CHECK-SAME: "-o" "[[CC_OUT2:[^"]*]]"
// CHECK:ld{{(\.exe)?}}" {{.*}} "-o" "[[LD_OUT2:[^"]*]]" {{.*}} "[[CC_OUT2]]"
-// CHECK:lipo"
+// CHECK:lipo{{(\.exe)?}}"
// CHECK-DAG: "[[LD_OUT1]]"
// CHECK-DAG: "[[LD_OUT2]]"
diff --git a/test/Driver/darwin-objc-gc.m b/test/Driver/darwin-objc-gc.m
deleted file mode 100644
index aac6dc16c372..000000000000
--- a/test/Driver/darwin-objc-gc.m
+++ /dev/null
@@ -1,19 +0,0 @@
-// Check that we warn, but accept, -fobjc-gc for iPhone OS.
-
-// RUN: %clang -target i386-apple-darwin9 -miphoneos-version-min=3.0 -stdlib=platform -fobjc-gc -flto -S -o %t %s 2> %t.err
-// RUN: FileCheck --check-prefix=IPHONE_OBJC_GC_LL %s < %t
-// RUN: FileCheck --check-prefix=IPHONE_OBJC_GC_STDERR %s < %t.err
-
-// IPHONE_OBJC_GC_LL: define void @f0
-// IPHONE_OBJC_GC_LL-NOT: objc_assign_ivar
-// IPHONE_OBJC_GC_LL: }
-
-// IPHONE_OBJC_GC_STDERR: warning: Objective-C garbage collection is not supported on this platform, ignoring '-fobjc-gc'
-
-@interface A {
-@public
- id x;
-}
-@end
-
-void f0(A *a, id x) { a->x = x; }
diff --git a/test/Driver/darwin-stdlib.cpp b/test/Driver/darwin-stdlib.cpp
index c9be6075bb07..26cbf2bde346 100644
--- a/test/Driver/darwin-stdlib.cpp
+++ b/test/Driver/darwin-stdlib.cpp
@@ -1,3 +1,7 @@
+// This test will fail if CLANG_DEFAULT_CXX_STDLIB is set to anything different
+// than the platform default. (see https://llvm.org/bugs/show_bug.cgi?id=30548)
+// XFAIL: default-cxx-stdlib-set
+
// RUN: %clang -target x86_64-apple-darwin -arch arm64 -miphoneos-version-min=7.0 %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LIBCXX
// RUN: %clang -target x86_64-apple-darwin -mmacosx-version-min=10.8 %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LIBSTDCXX
// RUN: %clang -target x86_64-apple-darwin -mmacosx-version-min=10.9 %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-LIBCXX
diff --git a/test/Driver/debug-options.c b/test/Driver/debug-options.c
index 0ccacd0fc6c7..94c769fa37d3 100644
--- a/test/Driver/debug-options.c
+++ b/test/Driver/debug-options.c
@@ -1,6 +1,7 @@
// Check to make sure clang is somewhat picky about -g options.
// rdar://10383444
+// Linux.
// RUN: %clang -### -c -g %s -target x86_64-linux-gnu 2>&1 \
// RUN: | FileCheck -check-prefix=G -check-prefix=G_GDB %s
// RUN: %clang -### -c -g2 %s -target x86_64-linux-gnu 2>&1 \
@@ -16,21 +17,50 @@
// RUN: %clang -### -c -glldb %s -target x86_64-linux-gnu 2>&1 \
// RUN: | FileCheck -check-prefix=G -check-prefix=G_LLDB %s
// RUN: %clang -### -c -gsce %s -target x86_64-linux-gnu 2>&1 \
-// RUN: | FileCheck -check-prefix=G -check-prefix=G_SCE %s
+// Darwin.
+// RUN: | FileCheck -check-prefix=G -check-prefix=G_SCE %s
// RUN: %clang -### -c -g %s -target x86_64-apple-darwin 2>&1 \
-// RUN: | FileCheck -check-prefix=G_DARWIN -check-prefix=G_LLDB %s
-// RUN: %clang -### -c -g2 %s -target x86_64-apple-darwin 2>&1 \
-// RUN: | FileCheck -check-prefix=G_DARWIN %s
-// RUN: %clang -### -c -g3 %s -target x86_64-apple-darwin 2>&1 \
-// RUN: | FileCheck -check-prefix=G_DARWIN %s
-// RUN: %clang -### -c -ggdb %s -target x86_64-apple-darwin 2>&1 \
-// RUN: | FileCheck -check-prefix=G_DARWIN -check-prefix=G_GDB %s
-// RUN: %clang -### -c -ggdb1 %s -target x86_64-apple-darwin 2>&1 \
-// RUN: | FileCheck -check-prefix=GLTO_ONLY_DWARF2 %s
-// RUN: %clang -### -c -ggdb3 %s -target x86_64-apple-darwin 2>&1 \
-// RUN: | FileCheck -check-prefix=G_DARWIN %s
+// RUN: | FileCheck -check-prefix=G_STANDALONE \
+// RUN: -check-prefix=G_DWARF2 \
+// RUN: -check-prefix=G_LLDB %s
+// RUN: %clang -### -c -g %s -target x86_64-apple-darwin16 2>&1 \
+// RUN: | FileCheck -check-prefix=G_STANDALONE \
+// RUN: -check-prefix=G_DWARF4 \
+// RUN: -check-prefix=G_LLDB %s
+// RUN: %clang -### -c -g2 %s -target x86_64-apple-darwin16 2>&1 \
+// RUN: | FileCheck -check-prefix=G_STANDALONE \
+// RUN: -check-prefix=G_DWARF4 %s
+// RUN: %clang -### -c -g3 %s -target x86_64-apple-darwin16 2>&1 \
+// RUN: | FileCheck -check-prefix=G_STANDALONE \
+// RUN: -check-prefix=G_DWARF4 %s
+// RUN: %clang -### -c -ggdb %s -target x86_64-apple-darwin16 2>&1 \
+// RUN: | FileCheck -check-prefix=G_STANDALONE \
+// RUN: -check-prefix=G_DWARF4 \
+// RUN: -check-prefix=G_GDB %s
+// RUN: %clang -### -c -ggdb1 %s -target x86_64-apple-darwin16 2>&1 \
+// RUN: | FileCheck -check-prefix=GLTO_ONLY %s
+// RUN: %clang -### -c -ggdb3 %s -target x86_64-apple-darwin16 2>&1 \
+// RUN: | FileCheck -check-prefix=G_STANDALONE \
+// RUN: -check-prefix=G_DWARF4 %s
+// RUN: %clang -### -c -g %s -target x86_64-apple-macosx10.11 2>&1 \
+// RUN: | FileCheck -check-prefix=G_STANDALONE \
+// RUN: -check-prefix=G_DWARF4 %s
+// RUN: %clang -### -c -g %s -target x86_64-apple-macosx10.10 2>&1 \
+// RUN: | FileCheck -check-prefix=G_ONLY_DWARF2 %s
+// RUN: %clang -### -c -g %s -target armv7-apple-ios9.0 2>&1 \
+// RUN: | FileCheck -check-prefix=G_STANDALONE \
+// RUN: -check-prefix=G_DWARF4 %s
+// RUN: %clang -### -c -g %s -target armv7-apple-ios8.0 2>&1 \
+// RUN: | FileCheck -check-prefix=G_ONLY_DWARF2 %s
+// RUN: %clang -### -c -g %s -target armv7k-apple-watchos 2>&1 \
+// RUN: | FileCheck -check-prefix=G_STANDALONE \
+// RUN: -check-prefix=G_DWARF4 %s
+// RUN: %clang -### -c -g %s -target arm64-apple-tvos9.0 2>&1 \
+// RUN: | FileCheck -check-prefix=G_STANDALONE \
+// RUN: -check-prefix=G_DWARF4 %s
+// FreeBSD.
// RUN: %clang -### -c -g %s -target x86_64-pc-freebsd10.0 2>&1 \
// RUN: | FileCheck -check-prefix=G_GDB %s
@@ -47,7 +77,8 @@
// RUN: %clang -### -c %s -g -gcolumn-info -target x86_64-scei-ps4 2>&1 \
// RUN: | FileCheck -check-prefix=CI %s
-// RUN: %clang -### -c -gdwarf-2 %s 2>&1 | FileCheck -check-prefix=G_D2 %s
+// RUN: %clang -### -c -gdwarf-2 %s 2>&1 \
+// RUN: | FileCheck -check-prefix=G_ONLY_DWARF2 %s
//
// RUN: %clang -### -c -gfoo %s 2>&1 | FileCheck -check-prefix=G_NO %s
// RUN: %clang -### -c -g -g0 %s 2>&1 | FileCheck -check-prefix=G_NO %s
@@ -68,15 +99,15 @@
// RUN: %clang -### -c -gline-tables-only %s 2>&1 \
// RUN: | FileCheck -check-prefix=GLTO_ONLY %s
// RUN: %clang -### -c -gline-tables-only %s -target x86_64-apple-darwin 2>&1 \
-// RUN: | FileCheck -check-prefix=GLTO_ONLY_DWARF2 %s
+// RUN: | FileCheck -check-prefix=GLTO_ONLY %s
// RUN: %clang -### -c -gline-tables-only %s -target i686-pc-openbsd 2>&1 \
// RUN: | FileCheck -check-prefix=GLTO_ONLY_DWARF2 %s
// RUN: %clang -### -c -gline-tables-only %s -target x86_64-pc-freebsd10.0 2>&1 \
// RUN: | FileCheck -check-prefix=GLTO_ONLY_DWARF2 %s
// RUN: %clang -### -c -gline-tables-only -g %s -target x86_64-linux-gnu 2>&1 \
// RUN: | FileCheck -check-prefix=G_ONLY %s
-// RUN: %clang -### -c -gline-tables-only -g %s -target x86_64-apple-darwin 2>&1 \
-// RUN: | FileCheck -check-prefix=G_ONLY_DWARF2 %s
+// RUN: %clang -### -c -gline-tables-only -g %s -target x86_64-apple-darwin16 2>&1 \
+// RUN: | FileCheck -check-prefix=G_STANDALONE -check-prefix=G_DWARF4 %s
// RUN: %clang -### -c -gline-tables-only -g %s -target i686-pc-openbsd 2>&1 \
// RUN: | FileCheck -check-prefix=G_ONLY_DWARF2 %s
// RUN: %clang -### -c -gline-tables-only -g %s -target x86_64-pc-freebsd10.0 2>&1 \
@@ -109,12 +140,18 @@
// RUN: %clang -### -gmodules %s 2>&1 \
// RUN: | FileCheck -check-prefix=GEXTREFS %s
//
+// RUN: %clang -### -gmodules -g %s 2>&1 \
+// RUN: | FileCheck -check-prefix=GEXTREFS %s
+//
+// RUN: %clang -### -gline-tables-only -gmodules %s 2>&1 \
+// RUN: | FileCheck -check-prefix=GEXTREFS %s
+//
+// RUN: %clang -### -gmodules -gline-tables-only %s 2>&1 \
+// RUN: | FileCheck -check-prefix=GLTO_ONLY %s
+//
// G: "-cc1"
// G: "-debug-info-kind=limited"
//
-// G_DARWIN: "-cc1"
-// G_DARWIN: "-dwarf-version=2"
-//
// NOG_PS4: "-cc1"
// NOG_PS4-NOT "-dwarf-version=
// NOG_PS4: "-generate-arange-section"
@@ -124,14 +161,13 @@
// G_PS4: "-dwarf-version=
// G_PS4: "-generate-arange-section"
//
-// G_D2: "-cc1"
-// G_D2: "-dwarf-version=2"
-//
// G_NO: "-cc1"
// G_NO-NOT: -debug-info-kind=
//
// GLTO_ONLY: "-cc1"
+// GLTO_ONLY-NOT: "-dwarf-ext-refs"
// GLTO_ONLY: "-debug-info-kind=line-tables-only"
+// GLTO_ONLY-NOT: "-dwarf-ext-refs"
//
// GLTO_ONLY_DWARF2: "-cc1"
// GLTO_ONLY_DWARF2: "-debug-info-kind=line-tables-only"
@@ -140,16 +176,20 @@
// G_ONLY: "-cc1"
// G_ONLY: "-debug-info-kind=limited"
//
-// G_GDB: "-debugger-tuning=gdb"
-// G_LLDB: "-debugger-tuning=lldb"
-// G_SCE: "-debugger-tuning=sce"
-//
// These tests assert that "-gline-tables-only" "-g" uses the latter,
// but otherwise not caring about the DebugInfoKind.
// G_ONLY_DWARF2: "-cc1"
// G_ONLY_DWARF2: "-debug-info-kind={{standalone|limited}}"
// G_ONLY_DWARF2: "-dwarf-version=2"
//
+// G_STANDALONE: "-cc1"
+// G_STANDALONE: "-debug-info-kind=standalone"
+// G_DWARF4: "-dwarf-version=4"
+//
+// G_GDB: "-debugger-tuning=gdb"
+// G_LLDB: "-debugger-tuning=lldb"
+// G_SCE: "-debugger-tuning=sce"
+//
// This tests asserts that "-gline-tables-only" "-g0" disables debug info.
// GLTO_NO: "-cc1"
// GLTO_NO-NOT: -debug-info-kind=
diff --git a/test/Driver/defsym.s b/test/Driver/defsym.s
new file mode 100644
index 000000000000..4d914ac7365c
--- /dev/null
+++ b/test/Driver/defsym.s
@@ -0,0 +1,37 @@
+// RUN: %clang -### -c -integrated-as %s \
+// RUN: -Wa,-defsym,abc=5 -Wa,-defsym,xyz=0xa \
+// RUN: 2>&1 | FileCheck %s --check-prefix=CHECK-DEFSYM1
+
+// RUN: %clang -### -c -no-integrated-as -target x86_64-unknown-unknown %s \
+// RUN: -Wa,-defsym,abc=5 -Wa,-defsym,xyz=0xa \
+// RUN: 2>&1 | FileCheck %s --check-prefix=CHECK-DEFSYM1
+
+// CHECK-DEFSYM1: "-defsym"
+// CHECK-DEFSYM1: "abc=5"
+// CHECK-DEFSYM1: "-defsym"
+// CHECK-DEFSYM1: "xyz=0xa"
+
+// RUN: not %clang -c -integrated-as -o /dev/null %s \
+// RUN: -Wa,-defsym,abc= \
+// RUN: 2>&1 | FileCheck %s --check-prefix=CHECK-DEFSYM-ERR1
+// CHECK-DEFSYM-ERR1: error: defsym must be of the form: sym=value: abc=
+
+// RUN: not %clang -c -integrated-as -o /dev/null %s \
+// RUN: -Wa,-defsym,=123 \
+// RUN: 2>&1 | FileCheck %s --check-prefix=CHECK-DEFSYM-ERR2
+// CHECK-DEFSYM-ERR2: error: defsym must be of the form: sym=value: =123
+
+// RUN: not %clang -c -integrated-as -o /dev/null %s \
+// RUN: -Wa,-defsym,abc=1a2b3c \
+// RUN: 2>&1 | FileCheck %s --check-prefix=CHECK-DEFSYM-ERR3
+// CHECK-DEFSYM-ERR3: error: Value is not an integer: 1a2b3c
+
+// RUN: not %clang -c -integrated-as -o /dev/null %s \
+// RUN: -Wa,-defsym \
+// RUN: 2>&1 | FileCheck %s --check-prefix=CHECK-DEFSYM-ERR4
+
+// RUN: not %clang -c -integrated-as -o /dev/null %s \
+// RUN: -Wa,-defsym, \
+// RUN: 2>&1 | FileCheck %s --check-prefix=CHECK-DEFSYM-ERR4
+
+// CHECK-DEFSYM-ERR4: error: defsym must be of the form: sym=value: -defsym
diff --git a/test/Driver/denormal-fp-math.c b/test/Driver/denormal-fp-math.c
new file mode 100644
index 000000000000..95ff232b0d15
--- /dev/null
+++ b/test/Driver/denormal-fp-math.c
@@ -0,0 +1,12 @@
+// RUN: %clang -### -target arm-unknown-linux-gnu -c %s -fdenormal-fp-math=ieee -v 2>&1 | FileCheck -check-prefix=CHECK-IEEE %s
+// RUN: %clang -### -target arm-unknown-linux-gnu -c %s -fdenormal-fp-math=preserve-sign -v 2>&1 | FileCheck -check-prefix=CHECK-PS %s
+// RUN: %clang -### -target arm-unknown-linux-gnu -c %s -fdenormal-fp-math=positive-zero -v 2>&1 | FileCheck -check-prefix=CHECK-PZ %s
+// RUN: %clang -### -target arm-unknown-linux-gnu -c %s -fdenormal-fp-math=ieee -fno-fast-math -v 2>&1 | FileCheck -check-prefix=CHECK-NO-UNSAFE %s
+// RUN: %clang -### -target arm-unknown-linux-gnu -c %s -fdenormal-fp-math=ieee -fno-unsafe-math-optimizations -v 2>&1 | FileCheck -check-prefix=CHECK-NO-UNSAFE %s
+// RUN: not %clang -target arm-unknown-linux-gnu -c %s -fdenormal-fp-math=foo -v 2>&1 | FileCheck -check-prefix=CHECK-INVALID %s
+
+// CHECK-IEEE: "-fdenormal-fp-math=ieee"
+// CHECK-PS: "-fdenormal-fp-math=preserve-sign"
+// CHECK-PZ: "-fdenormal-fp-math=positive-zero"
+// CHECK-NO-UNSAFE-NOT: "-fdenormal-fp-math=ieee"
+// CHECK-INVALID: error: invalid value 'foo' in '-fdenormal-fp-math=foo'
diff --git a/test/Driver/embed-bitcode.c b/test/Driver/embed-bitcode.c
index da60da3fff7b..36314e664093 100644
--- a/test/Driver/embed-bitcode.c
+++ b/test/Driver/embed-bitcode.c
@@ -41,3 +41,15 @@
// CHECK-MARKER: -fembed-bitcode=marker
// CHECK-MARKER-NOT: -cc1
+// RUN: %clang -target armv7-apple-darwin -miphoneos-version-min=6.0 %s -fembed-bitcode=all -fintegrated-as 2>&1 -### | FileCheck %s -check-prefix=CHECK-LINKER
+// RUN: %clang -target armv7-apple-darwin -miphoneos-version-min=6.0 %s -fembed-bitcode=marker -fintegrated-as 2>&1 -### | FileCheck %s -check-prefix=CHECK-LINKER
+// RUN: %clang -target armv7-apple-darwin -miphoneos-version-min=6.0 %s -flto=full -fembed-bitcode=bitcode -fintegrated-as 2>&1 -### | FileCheck %s -check-prefix=CHECK-LINKER
+// RUN: %clang -target armv7-apple-darwin -miphoneos-version-min=6.0 %s -flto=thin -fembed-bitcode=bitcode -fintegrated-as 2>&1 -### | FileCheck %s -check-prefix=CHECK-LINKER
+// RUN: %clang -target armv7-apple-darwin -miphoneos-version-min=6.0 %s -fembed-bitcode=off -fintegrated-as 2>&1 -### | FileCheck %s -check-prefix=CHECK-NO-LINKER
+// CHECK-LINKER: ld
+// CHECK-LINKER: -bitcode_bundle
+// CHECK-NO-LINKER-NOT: -bitcode_bundle
+
+// RUN: %clang -target armv7-apple-darwin -miphoneos-version-min=5.0 %s -fembed-bitcode -### 2>&1 | \
+// RUN: FileCheck %s -check-prefix=CHECK-PLATFORM-UNSUPPORTED
+// CHECK-PLATFORM-UNSUPPORTED: -fembed-bitcode is not supported on versions of iOS prior to 6.0
diff --git a/test/Driver/esan.c b/test/Driver/esan.c
index 795104114065..f734bef12455 100644
--- a/test/Driver/esan.c
+++ b/test/Driver/esan.c
@@ -6,6 +6,10 @@
// RUN: %clang -O1 -target x86_64-unknown-linux -fsanitize=efficiency-working-set %s -S -emit-llvm -o - | FileCheck %s
// RUN: %clang -O2 -target x86_64-unknown-linux -fsanitize=efficiency-working-set %s -S -emit-llvm -o - | FileCheck %s
// RUN: %clang -O3 -target x86_64-unknown-linux -fsanitize=efficiency-working-set %s -S -emit-llvm -o - | FileCheck %s
+// RUN: %clang -target mips64-unknown-linux -fsanitize=efficiency-cache-frag %s -S -emit-llvm -o - | FileCheck %s
+// RUN: %clang -target mips64-unknown-linux -fsanitize=efficiency-working-set %s -S -emit-llvm -o - | FileCheck %s
+// RUN: %clang -target mips64el-unknown-linux -fsanitize=efficiency-cache-frag %s -S -emit-llvm -o - | FileCheck %s
+// RUN: %clang -target mips64el-unknown-linux -fsanitize=efficiency-working-set %s -S -emit-llvm -o - | FileCheck %s
// Verify that -fsanitize=efficiency-* invokes esan instrumentation.
int foo(int *a) { return *a; }
diff --git a/test/Driver/fast-math.c b/test/Driver/fast-math.c
index 24c30386da12..025651d0a395 100644
--- a/test/Driver/fast-math.c
+++ b/test/Driver/fast-math.c
@@ -231,3 +231,7 @@
// CHECK-NO-UNSAFE-MATH: "-cc1"
// CHECK-NO-UNSAFE-MATH-NOT: "-menable-unsafe-fp-math"
// CHECK-NO-UNSAFE-MATH: "-o"
+//
+// 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"
diff --git a/test/Driver/frame-pointer-elim.c b/test/Driver/frame-pointer-elim.c
index 139c0ccb952a..e1d816ea9fd1 100644
--- a/test/Driver/frame-pointer-elim.c
+++ b/test/Driver/frame-pointer-elim.c
@@ -35,10 +35,30 @@
// RUN: FileCheck --check-prefix=OMIT_LEAF %s
// OMIT_LEAF: "-momit-leaf-frame-pointer"
+// RUN: %clang -### -target armv7s-apple-ios -fomit-frame-pointer %s 2>&1 | \
+// RUN: FileCheck --check-prefix=WARN-OMIT-7S %s
+// WARN-OMIT-7S: warning: optimization flag '-fomit-frame-pointer' is not supported for target 'armv7s'
+// WARN-OMIT-7S: "-mdisable-fp-elim"
+// WARN-OMIT-7S-NOT: "-momit-leaf-frame-pointer"
+
+// RUN: %clang -### -target armv7k-apple-watchos -fomit-frame-pointer %s 2>&1 | \
+// RUN: FileCheck --check-prefix=WARN-OMIT-7K %s
+// WARN-OMIT-7K: warning: optimization flag '-fomit-frame-pointer' is not supported for target 'armv7k'
+// WARN-OMIT-7K: "-mdisable-fp-elim"
+// WARN-OMIT-7K-NOT: "-momit-leaf-frame-pointer"
+
+// RUN: %clang -### -target armv7s-apple-ios8.0 -momit-leaf-frame-pointer %s 2>&1 | \
+// RUN: FileCheck --check-prefix=WARN-OMIT-LEAF-7S %s
+// WARN-OMIT-LEAF-7S: warning: optimization flag '-momit-leaf-frame-pointer' is not supported for target 'armv7s'
+// WARN-OMIT-LEAF-7S: "-mdisable-fp-elim"
+// WARN-OMIT-LEAF-7S-NOT: "-momit-leaf-frame-pointer"
+
// On the PS4, we default to omitting the frame pointer on leaf functions
// (OMIT_LEAF check line is above)
// RUN: %clang -### -target x86_64-scei-ps4 -S %s 2>&1 | \
// RUN: FileCheck --check-prefix=OMIT_LEAF %s
+// RUN: %clang -### -target x86_64-scei-ps4 -S -O2 %s 2>&1 | \
+// RUN: FileCheck --check-prefix=OMIT_LEAF %s
void f0() {}
void f1() { f0(); }
diff --git a/test/Driver/fsanitize-blacklist.c b/test/Driver/fsanitize-blacklist.c
index 9edbbaf2bd8d..adf776fcae73 100644
--- a/test/Driver/fsanitize-blacklist.c
+++ b/test/Driver/fsanitize-blacklist.c
@@ -1,7 +1,7 @@
// General blacklist usage.
// PR12920
-// REQUIRES: clang-driver, shell
+// REQUIRES: clang-driver
// Make sure we don't match the -NOT lines with the linker invocation.
// Delimiters match the start of the cc1 and the start of the linker lines
diff --git a/test/Driver/fsanitize-coverage.c b/test/Driver/fsanitize-coverage.c
index 16c5dfe09937..b04e71e90c92 100644
--- a/test/Driver/fsanitize-coverage.c
+++ b/test/Driver/fsanitize-coverage.c
@@ -40,11 +40,13 @@
// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-coverage=func -fno-sanitize=address %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-SAN-DISABLED
// CHECK-SANITIZE-COVERAGE-SAN-DISABLED-NOT: argument unused
-// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-coverage=edge,indirect-calls,trace-bb,trace-pc,trace-cmp,8bit-counters %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-FEATURES
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-coverage=edge,indirect-calls,trace-bb,trace-pc,trace-cmp,8bit-counters,trace-div,trace-gep %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANITIZE-COVERAGE-FEATURES
// CHECK-SANITIZE-COVERAGE-FEATURES: -fsanitize-coverage-type=3
// CHECK-SANITIZE-COVERAGE-FEATURES: -fsanitize-coverage-indirect-calls
// CHECK-SANITIZE-COVERAGE-FEATURES: -fsanitize-coverage-trace-bb
// CHECK-SANITIZE-COVERAGE-FEATURES: -fsanitize-coverage-trace-cmp
+// CHECK-SANITIZE-COVERAGE-FEATURES: -fsanitize-coverage-trace-div
+// CHECK-SANITIZE-COVERAGE-FEATURES: -fsanitize-coverage-trace-gep
// CHECK-SANITIZE-COVERAGE-FEATURES: -fsanitize-coverage-8bit-counters
// CHECK-SANITIZE-COVERAGE-FEATURES: -fsanitize-coverage-trace-pc
@@ -70,6 +72,14 @@
// CHECK-TRACE_PC_FUNC: -fsanitize-coverage-type=1
// CHECK-TRACE_PC_FUNC: -fsanitize-coverage-trace-pc
+// RUN: %clang -target x86_64-linux-gnu -fsanitize-coverage=trace-pc-guard %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TRACE_PC_GUARD_EDGE
+// RUN: %clang -target x86_64-linux-gnu -fsanitize-coverage=edge,trace-pc-guard %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TRACE_PC_GUARD_EDGE
+// CHECK-TRACE_PC_GUARD_EDGE: -fsanitize-coverage-type=3
+// CHECK-TRACE_PC_GUARD_EDGE: -fsanitize-coverage-trace-pc-guard
+// RUN: %clang -target x86_64-linux-gnu -fsanitize-coverage=func,trace-pc-guard %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TRACE_PC_GUARD_FUNC
+// CHECK-TRACE_PC_GUARD_FUNC: -fsanitize-coverage-type=1
+// CHECK-TRACE_PC_GUARD_FUNC: -fsanitize-coverage-trace-pc-guard
+
// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-coverage=trace-cmp,indirect-calls %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-TYPE-NECESSARY
// CHECK-NO-TYPE-NECESSARY-NOT: error:
// CHECK-NO-TYPE-NECESSARY: -fsanitize-coverage-indirect-calls
diff --git a/test/Driver/fsanitize.c b/test/Driver/fsanitize.c
index b0cef81bc254..25aea01aae5d 100644
--- a/test/Driver/fsanitize.c
+++ b/test/Driver/fsanitize.c
@@ -108,14 +108,20 @@
// RUN: %clang -target x86_64-linux-gnu -fsanitize=efficiency-working-set,kernel-address -pie -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANE-SANKA
// CHECK-SANE-SANKA: '-fsanitize=efficiency-{{.*}}' not allowed with '-fsanitize=kernel-address'
-// RUN: %clang -target x86_64-linux-gnu -fsanitize-address-use-after-scope %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ONLY-USE-AFTER-SCOPE
-// CHECK-ONLY-USE-AFTER-SCOPE: '-fsanitize-address-use-after-scope' only allowed with '-fsanitize=address'
-
// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-address-use-after-scope %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-USE-AFTER-SCOPE
// CHECK-USE-AFTER-SCOPE: -cc1{{.*}}-fsanitize-address-use-after-scope
-// RUN: %clang -target x86_64-linux-gnu -fsanitize=address %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-NO-USE-AFTER-SCOPE
-// CHECK-ASAN-NO-USE-AFTER-SCOPE-NOT: -cc1{{.*}}-fsanitize-address-use-after-scope
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fno-sanitize-address-use-after-scope %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-USE-AFTER-SCOPE-OFF
+// CHECK-USE-AFTER-SCOPE-OFF-NOT: -cc1{{.*}}address-use-after-scope
+
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fno-sanitize-address-use-after-scope -fsanitize-address-use-after-scope %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-USE-AFTER-SCOPE-BOTH
+// CHECK-USE-AFTER-SCOPE-BOTH: -cc1{{.*}}-fsanitize-address-use-after-scope
+
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-address-use-after-scope -fno-sanitize-address-use-after-scope %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-USE-AFTER-SCOPE-BOTH-OFF
+// CHECK-USE-AFTER-SCOPE-BOTH-OFF-NOT: -cc1{{.*}}address-use-after-scope
+
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=address %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-WITHOUT-USE-AFTER-SCOPE
+// CHECK-ASAN-WITHOUT-USE-AFTER-SCOPE-NOT: -cc1{{.*}}address-use-after-scope
// RUN: %clang -target x86_64-linux-gnu -fsanitize-memory-track-origins -pie %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ONLY-TRACK-ORIGINS
// CHECK-ONLY-TRACK-ORIGINS: warning: argument unused during compilation: '-fsanitize-memory-track-origins'
@@ -272,6 +278,35 @@
// RUN: %clang -target i386-apple-tvossimulator -fsanitize=thread %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-I386-TVOSSIMULATOR
// CHECK-TSAN-I386-TVOSSIMULATOR: unsupported option '-fsanitize=thread' for target 'i386-apple-tvossimulator'
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=thread -fsanitize-thread-memory-access %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-MEMORY-ACCESS
+// CHECK-TSAN-MEMORY-ACCESS-NOT: -cc1{{.*}}tsan-instrument-memory-accesses=0
+// CHECK-TSAN-MEMORY-ACCESS-NOT: -cc1{{.*}}tsan-instrument-memintrinsics=0
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=thread -fno-sanitize-thread-memory-access %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-MEMORY-ACCESS-OFF
+// CHECK-TSAN-MEMORY-ACCESS-OFF: -cc1{{.*}}tsan-instrument-memory-accesses=0{{.*}}tsan-instrument-memintrinsics=0
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=thread -fno-sanitize-thread-memory-access -fsanitize-thread-memory-access %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-MEMORY-ACCESS-BOTH
+// CHECK-TSAN-MEMORY-ACCESS-BOTH-NOT: -cc1{{.*}}tsan-instrument-memory-accesses=0
+// CHECK-TSAN-MEMORY-ACCESS-BOTH-NOT: -cc1{{.*}}tsan-instrument-memintrinsics=0
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=thread -fsanitize-thread-memory-access -fno-sanitize-thread-memory-access %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-MEMORY-ACCESS-BOTH-OFF
+// CHECK-TSAN-MEMORY-ACCESS-BOTH-OFF: -cc1{{.*}}tsan-instrument-memory-accesses=0{{.*}}tsan-instrument-memintrinsics=0
+
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=thread -fsanitize-thread-func-entry-exit %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-FUNC-ENTRY-EXIT
+// CHECK-TSAN-FUNC-ENTRY-EXIT-NOT: -cc1{{.*}}tsan-instrument-func-entry-exit=0
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=thread -fno-sanitize-thread-func-entry-exit %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-FUNC-ENTRY-EXIT-OFF
+// CHECK-TSAN-FUNC-ENTRY-EXIT-OFF: -cc1{{.*}}tsan-instrument-func-entry-exit=0
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=thread -fno-sanitize-thread-func-entry-exit -fsanitize-thread-func-entry-exit %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-FUNC-ENTRY-EXIT-BOTH
+// CHECK-TSAN-FUNC-ENTRY-EXIT-BOTH-NOT: -cc1{{.*}}tsan-instrument-func-entry-exit=0
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=thread -fsanitize-thread-func-entry-exit -fno-sanitize-thread-func-entry-exit %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-FUNC-ENTRY-EXIT-BOTH-OFF
+// CHECK-TSAN-FUNC-ENTRY-EXIT-BOTH-OFF: -cc1{{.*}}tsan-instrument-func-entry-exit=0
+
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=thread -fsanitize-thread-atomics %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-ATOMICS
+// CHECK-TSAN-ATOMICS-NOT: -cc1{{.*}}tsan-instrument-atomics=0
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=thread -fno-sanitize-thread-atomics %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-ATOMICS-OFF
+// CHECK-TSAN-ATOMICS-OFF: -cc1{{.*}}tsan-instrument-atomics=0
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=thread -fno-sanitize-thread-atomics -fsanitize-thread-atomics %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-ATOMICS-BOTH
+// CHECK-TSAN-ATOMICS-BOTH-NOT: -cc1{{.*}}tsan-instrument-atomics=0
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=thread -fsanitize-thread-atomics -fno-sanitize-thread-atomics %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-TSAN-ATOMICS-BOTH-OFF
+// CHECK-TSAN-ATOMICS-BOTH-OFF: -cc1{{.*}}tsan-instrument-atomics=0
+
// RUN: %clang -target x86_64-apple-darwin10 -fsanitize=function %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FSAN-DARWIN
// CHECK-FSAN-DARWIN: unsupported option '-fsanitize=function' for target 'x86_64-apple-darwin10'
@@ -322,6 +357,10 @@
// 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
// RUN: %clang -target x86_64-linux-gnu -flto -fvisibility=hidden -fsanitize=cfi-vcall -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI-VCALL
+// RUN: %clang -target arm-linux-gnu -fvisibility=hidden -fsanitize=cfi -flto -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI
+// 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-DCAST: -emit-llvm-bc{{.*}}-fsanitize=cfi-derived-cast
// CHECK-CFI-UCAST: -emit-llvm-bc{{.*}}-fsanitize=cfi-unrelated-cast
@@ -391,6 +430,7 @@
// 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
// RUN: %clang -target aarch64-linux-android -fsanitize=safe-stack -### %s 2>&1 | FileCheck %s -check-prefix=NO-SP
+// 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: "-fsanitize=safe-stack"
diff --git a/test/Driver/fuchsia.c b/test/Driver/fuchsia.c
new file mode 100644
index 000000000000..229b58828d0f
--- /dev/null
+++ b/test/Driver/fuchsia.c
@@ -0,0 +1,40 @@
+// RUN: %clang %s -### -no-canonical-prefixes --target=x86_64-unknown-fuchsia \
+// RUN: --sysroot=%S/platform 2>&1 | FileCheck %s
+// CHECK: {{.*}}clang{{.*}}" "-cc1"
+// CHECK: "-fuse-init-array"
+// CHECK: "-isysroot" "[[SYSROOT:[^"]+]]"
+// CHECK: "-internal-externc-isystem" "[[SYSROOT]]{{/|\\\\}}include"
+// CHECK: {{.*}}lld{{.*}}" "-flavor" "gnu"
+// CHECK: "--sysroot=[[SYSROOT]]"
+// CHECK: "-pie"
+// CHECK: "--build-id"
+// CHECK: "-dynamic-linker" "ld.so.1"
+// CHECK: Scrt1.o
+// CHECK-NOT: crti.o
+// CHECK-NOT: crtbegin.o
+// CHECK: "-L[[SYSROOT]]/lib"
+// CHECK: "{{.*[/\\]}}libclang_rt.builtins-x86_64.a"
+// CHECK: "-lc"
+// CHECK-NOT: crtend.o
+// CHECK-NOT: crtn.o
+
+// RUN: %clang %s -### --target=x86_64-unknown-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: | 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: | 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: | FileCheck %s -check-prefix=CHECK-RELOCATABLE
+// CHECK-RELOCATABLE-NOT: "-pie"
+// CHECK-RELOCATABLE-NOT: "--build-id"
+// CHECK-RELOCATABLE: "-r"
diff --git a/test/Driver/fuchsia.cpp b/test/Driver/fuchsia.cpp
new file mode 100644
index 000000000000..275891d52c30
--- /dev/null
+++ b/test/Driver/fuchsia.cpp
@@ -0,0 +1,33 @@
+// RUN: %clangxx %s -### -no-canonical-prefixes --target=x86_64-unknown-fuchsia \
+// RUN: --sysroot=%S/platform 2>&1 | FileCheck %s
+// CHECK: {{.*}}clang{{.*}}" "-cc1"
+// CHECK: "-fuse-init-array"
+// CHECK: "-isysroot" "[[SYSROOT:[^"]+]]"
+// CHECK: "-internal-isystem" "[[SYSROOT]]{{/|\\\\}}include{{/|\\\\}}c++{{/|\\\\}}v1"
+// CHECK: "-internal-externc-isystem" "[[SYSROOT]]{{/|\\\\}}include"
+// CHECK: {{.*}}lld{{.*}}" "-flavor" "gnu"
+// CHECK: "--sysroot=[[SYSROOT]]"
+// CHECK: "-pie"
+// CHECK: "--build-id"
+// CHECK: "-dynamic-linker" "ld.so.1"
+// CHECK: Scrt1.o
+// CHECK-NOT: crti.o
+// CHECK-NOT: crtbegin.o
+// CHECK: "-L[[SYSROOT]]/lib"
+// CHECK: "-lc++" "-lc++abi" "-lunwind" "-lm"
+// CHECK: "{{.*[/\\]}}libclang_rt.builtins-x86_64.a"
+// CHECK: "-lc"
+// CHECK-NOT: crtend.o
+// CHECK-NOT: crtn.o
+
+// RUN: %clangxx %s -### --target=x86_64-unknown-fuchsia -stdlib=libstdc++ 2>&1 \
+// RUN: | FileCheck %s -check-prefix=CHECK-STDLIB
+// CHECK-STDLIB: error: invalid library name in argument '-stdlib=libstdc++'
+
+// RUN: %clangxx %s -### --target=x86_64-unknown-fuchsia -static-libstdc++ 2>&1 \
+// RUN: | FileCheck %s -check-prefix=CHECK-STATIC
+// CHECK-STATIC: "-Bstatic"
+// CHECK-STATIC: "-lc++" "-lc++abi" "-lunwind"
+// CHECK-STATIC: "-Bdynamic"
+// CHECK-STATIC: "-lm"
+// CHECK-STATIC: "-lc"
diff --git a/test/Driver/gold-lto-sections.c b/test/Driver/gold-lto-sections.c
new file mode 100644
index 000000000000..83d72cf7f97b
--- /dev/null
+++ b/test/Driver/gold-lto-sections.c
@@ -0,0 +1,8 @@
+// RUN: touch %t.o
+//
+// RUN: %clang -target x86_64-unknown-linux -### %t.o -flto 2>&1 \
+// RUN: -Wl,-plugin-opt=foo -O3 \
+// RUN: -ffunction-sections -fdata-sections \
+// RUN: | FileCheck %s
+// CHECK: "-plugin-opt=-function-sections"
+// CHECK: "-plugin-opt=-data-sections"
diff --git a/test/Driver/hexagon-long-calls.c b/test/Driver/hexagon-long-calls.c
new file mode 100644
index 000000000000..e88922a3c236
--- /dev/null
+++ b/test/Driver/hexagon-long-calls.c
@@ -0,0 +1,15 @@
+// RUN: %clang -target hexagon -### %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-DEFAULT
+
+// RUN: %clang -target hexagon -### -mlong-calls %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-LONG-CALLS
+
+// RUN: %clang -target hexagon -### -mlong-calls -mno-long-calls %s 2>&1 \
+// RUN: | FileCheck %s -check-prefix CHECK-NO-LONG-CALLS
+
+// CHECK-DEFAULT-NOT: "-target-feature" "+long-calls"
+
+// CHECK-LONG-CALLS: "-target-feature" "+long-calls"
+
+// CHECK-NO-LONG-CALLS-NOT: "-target-feature" "+long-calls"
+
diff --git a/test/Driver/integrated-as.s b/test/Driver/integrated-as.s
index 5316f522dab2..1dcd4f611a3a 100644
--- a/test/Driver/integrated-as.s
+++ b/test/Driver/integrated-as.s
@@ -1,52 +1,52 @@
-// RUN: %clang -### -c -integrated-as %s 2>&1 | FileCheck %s
+// RUN: %clang -### -target x86_64--- -c -integrated-as %s 2>&1 | FileCheck %s
// CHECK: cc1as
// CHECK-NOT: -relax-all
-// RUN: %clang -### -c -integrated-as -Wa,-L %s 2>&1 | FileCheck --check-prefix=OPT_L %s
+// RUN: %clang -### -target x86_64--- -c -integrated-as -Wa,-L %s 2>&1 | FileCheck --check-prefix=OPT_L %s
// OPT_L: msave-temp-labels
// Test that -I params in -Wa, and -Xassembler args are passed to integrated assembler
-// RUN: %clang -### -c -integrated-as %s -Wa,-I,foo_dir 2>&1 | FileCheck --check-prefix=WA_INCLUDE1 %s
+// RUN: %clang -### -target x86_64--- -c -integrated-as %s -Wa,-I,foo_dir 2>&1 | FileCheck --check-prefix=WA_INCLUDE1 %s
// WA_INCLUDE1: cc1as
// WA_INCLUDE1: "-I" "foo_dir"
-// RUN: %clang -### -c -integrated-as %s -Wa,-Ifoo_dir 2>&1 | FileCheck --check-prefix=WA_INCLUDE2 %s
+// RUN: %clang -### -target x86_64--- -c -integrated-as %s -Wa,-Ifoo_dir 2>&1 | FileCheck --check-prefix=WA_INCLUDE2 %s
// WA_INCLUDE2: cc1as
// WA_INCLUDE2: "-Ifoo_dir"
-// RUN: %clang -### -c -integrated-as %s -Wa,-I -Wa,foo_dir 2>&1 | FileCheck --check-prefix=WA_INCLUDE3 %s
+// RUN: %clang -### -target x86_64--- -c -integrated-as %s -Wa,-I -Wa,foo_dir 2>&1 | FileCheck --check-prefix=WA_INCLUDE3 %s
// WA_INCLUDE3: cc1as
// WA_INCLUDE3: "-I" "foo_dir"
-// RUN: %clang -### -c -integrated-as %s -Xassembler -I -Xassembler foo_dir 2>&1 | FileCheck --check-prefix=XA_INCLUDE1 %s
+// RUN: %clang -### -target x86_64--- -c -integrated-as %s -Xassembler -I -Xassembler foo_dir 2>&1 | FileCheck --check-prefix=XA_INCLUDE1 %s
// XA_INCLUDE1: cc1as
// XA_INCLUDE1: "-I" "foo_dir"
-// RUN: %clang -### -c -integrated-as %s -Xassembler -Ifoo_dir 2>&1 | FileCheck --check-prefix=XA_INCLUDE2 %s
+// RUN: %clang -### -target x86_64--- -c -integrated-as %s -Xassembler -Ifoo_dir 2>&1 | FileCheck --check-prefix=XA_INCLUDE2 %s
// XA_INCLUDE2: cc1as
// XA_INCLUDE2: "-Ifoo_dir"
-// RUN: %clang -### -c -integrated-as %s -gdwarf-4 -gdwarf-2 2>&1 | FileCheck --check-prefix=DWARF2 %s
+// RUN: %clang -### -target x86_64--- -c -integrated-as %s -gdwarf-4 -gdwarf-2 2>&1 | FileCheck --check-prefix=DWARF2 %s
// DWARF2: "-debug-info-kind=limited" "-dwarf-version=2"
-// RUN: %clang -### -c -integrated-as %s -gdwarf-3 2>&1 | FileCheck --check-prefix=DWARF3 %s
+// RUN: %clang -### -target x86_64--- -c -integrated-as %s -gdwarf-3 2>&1 | FileCheck --check-prefix=DWARF3 %s
// DWARF3: "-debug-info-kind=limited" "-dwarf-version=3"
-// RUN: %clang -### -c -integrated-as %s -gdwarf-4 2>&1 | FileCheck --check-prefix=DWARF4 %s
+// RUN: %clang -### -target x86_64--- -c -integrated-as %s -gdwarf-4 2>&1 | FileCheck --check-prefix=DWARF4 %s
// DWARF4: "-debug-info-kind=limited" "-dwarf-version=4"
-// RUN: %clang -### -c -integrated-as %s -Xassembler -gdwarf-2 2>&1 | FileCheck --check-prefix=DWARF2XASSEMBLER %s
+// RUN: %clang -### -target x86_64--- -c -integrated-as %s -Xassembler -gdwarf-2 2>&1 | FileCheck --check-prefix=DWARF2XASSEMBLER %s
// DWARF2XASSEMBLER: "-debug-info-kind=limited" "-dwarf-version=2"
-// RUN: %clang -### -c -integrated-as %s -Wa,-gdwarf-2 2>&1 | FileCheck --check-prefix=DWARF2WA %s
+// RUN: %clang -### -target x86_64--- -c -integrated-as %s -Wa,-gdwarf-2 2>&1 | FileCheck --check-prefix=DWARF2WA %s
// DWARF2WA: "-debug-info-kind=limited" "-dwarf-version=2"
// A dwarf version number that driver can't parse is just stuffed in.
-// RUN: %clang -### -c -integrated-as %s -Wa,-gdwarf-huh 2>&1 | FileCheck --check-prefix=BOGODWARF %s
+// RUN: %clang -### -target x86_64--- -c -integrated-as %s -Wa,-gdwarf-huh 2>&1 | FileCheck --check-prefix=BOGODWARF %s
// BOGODWARF: "-gdwarf-huh"
-// RUN: %clang -### -x assembler -c -integrated-as %s -I myincludedir 2>&1 | FileCheck --check-prefix=INCLUDEPATH %s
+// RUN: %clang -### -target x86_64--- -x assembler -c -integrated-as %s -I myincludedir 2>&1 | FileCheck --check-prefix=INCLUDEPATH %s
// INCLUDEPATH: "-I" "myincludedir"
-// RUN: %clang -### -x assembler -c -fPIC -integrated-as %s 2>&1 | FileCheck --check-prefix=PIC %s
+// RUN: %clang -### -target x86_64--- -x assembler -c -fPIC -integrated-as %s 2>&1 | FileCheck --check-prefix=PIC %s
// PIC: "-mrelocation-model" "pic"
diff --git a/test/Driver/linux-header-search.cpp b/test/Driver/linux-header-search.cpp
index 5f6ac504a036..274895fb4fad 100644
--- a/test/Driver/linux-header-search.cpp
+++ b/test/Driver/linux-header-search.cpp
@@ -301,6 +301,48 @@
// CHECK-GENTOO-4-9-3: "-internal-externc-isystem" "[[SYSROOT]]/include"
// CHECK-GENTOO-4-9-3: "-internal-externc-isystem" "[[SYSROOT]]/usr/include"
//
+// Test support for Gentoo's gcc-config -- clang should prefer the older
+// (4.9.3) version over the newer (5.4.0) due to preference specified
+// in /etc/env.d/gcc/x86_64-pc-linux-gnu.
+// 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_multi_version_tree \
+// RUN: --gcc-toolchain="" \
+// RUN: | FileCheck --check-prefix=CHECK-GENTOO-4-9-3 %s
+//
+// Test that gcc-config support does not break multilib.
+// 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_multi_version_tree \
+// RUN: --gcc-toolchain="" \
+// RUN: | FileCheck --check-prefix=CHECK-GENTOO-4-9-3-X32 %s
+// CHECK-GENTOO-4-9-3-X32: "{{.*}}clang{{.*}}" "-cc1"
+// CHECK-GENTOO-4-9-3-X32: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]"
+// CHECK-GENTOO-4-9-3-X32: "-isysroot" "[[SYSROOT:[^"]+]]"
+// CHECK-GENTOO-4-9-3-X32: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/include/g++-v4.9.3"
+// CHECK-GENTOO-4-9-3-X32: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/include/g++-v4.9.3/x86_64-pc-linux-gnu/x32"
+// CHECK-GENTOO-4-9-3-X32: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/include/g++-v4.9.3/backward"
+// CHECK-GENTOO-4-9-3-X32: "-internal-isystem" "[[SYSROOT]]/usr/local/include"
+// CHECK-GENTOO-4-9-3-X32: "-internal-isystem" "[[RESOURCE_DIR]]{{/|\\\\}}include"
+// CHECK-GENTOO-4-9-3-X32: "-internal-externc-isystem" "[[SYSROOT]]/include"
+// CHECK-GENTOO-4-9-3-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_multi_version_tree \
+// RUN: --gcc-toolchain="" \
+// RUN: | FileCheck --check-prefix=CHECK-GENTOO-4-9-3-32 %s
+// CHECK-GENTOO-4-9-3-32: "{{.*}}clang{{.*}}" "-cc1"
+// CHECK-GENTOO-4-9-3-32: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]"
+// CHECK-GENTOO-4-9-3-32: "-isysroot" "[[SYSROOT:[^"]+]]"
+// CHECK-GENTOO-4-9-3-32: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/include/g++-v4.9.3"
+// CHECK-GENTOO-4-9-3-32: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/include/g++-v4.9.3/x86_64-pc-linux-gnu/32"
+// CHECK-GENTOO-4-9-3-32: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/include/g++-v4.9.3/backward"
+// CHECK-GENTOO-4-9-3-32: "-internal-isystem" "[[SYSROOT]]/usr/local/include"
+// CHECK-GENTOO-4-9-3-32: "-internal-isystem" "[[RESOURCE_DIR]]{{/|\\\\}}include"
+// CHECK-GENTOO-4-9-3-32: "-internal-externc-isystem" "[[SYSROOT]]/include"
+// CHECK-GENTOO-4-9-3-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 f9f4b482c920..8fa71a507bf9 100644
--- a/test/Driver/linux-ld.c
+++ b/test/Driver/linux-ld.c
@@ -16,7 +16,7 @@
// CHECK-LD-32: "-L[[SYSROOT]]/usr/lib"
//
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: --target=x86_64-unknown-linux \
+// RUN: --target=x86_64-unknown-linux -rtlib=platform \
// RUN: --gcc-toolchain="" \
// RUN: --sysroot=%S/Inputs/basic_linux_tree \
// RUN: | FileCheck --check-prefix=CHECK-LD-64 %s
@@ -36,7 +36,7 @@
// CHECK-LD-64: "-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-gnux32 \
+// RUN: --target=x86_64-unknown-linux-gnux32 -rtlib=platform \
// RUN: --gcc-toolchain="" \
// RUN: --sysroot=%S/Inputs/basic_linux_tree \
// RUN: | FileCheck --check-prefix=CHECK-LD-X32 %s
@@ -86,7 +86,7 @@
// CHECK-LD-RT-ANDROID: libclang_rt.builtins-arm-android.a"
//
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: --target=x86_64-unknown-linux \
+// RUN: --target=x86_64-unknown-linux -rtlib=platform \
// RUN: --gcc-toolchain="" \
// RUN: --sysroot=%S/Inputs/basic_linux_tree \
// RUN: --rtlib=libgcc \
@@ -107,7 +107,7 @@
// CHECK-LD-GCC: "-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 \
+// RUN: --target=x86_64-unknown-linux -rtlib=platform \
// RUN: -static-libgcc \
// RUN: --gcc-toolchain="" \
// RUN: --sysroot=%S/Inputs/basic_linux_tree \
@@ -128,7 +128,7 @@
// CHECK-LD-64-STATIC-LIBGCC: "-lgcc" "-lgcc_eh"
//
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: --target=x86_64-unknown-linux \
+// RUN: --target=x86_64-unknown-linux -rtlib=platform \
// RUN: -static \
// RUN: --gcc-toolchain="" \
// RUN: --sysroot=%S/Inputs/basic_linux_tree \
@@ -149,7 +149,7 @@
//
// Check that flags can be combined. The -static dominates.
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: --target=x86_64-unknown-linux \
+// RUN: --target=x86_64-unknown-linux -rtlib=platform \
// RUN: -static-libgcc -static \
// RUN: --gcc-toolchain="" \
// RUN: --sysroot=%S/Inputs/basic_linux_tree \
@@ -1004,42 +1004,42 @@
//
// Test linker invocation on Android.
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: --target=arm-linux-androideabi \
+// RUN: --target=arm-linux-androideabi -rtlib=platform \
// RUN: --gcc-toolchain="" \
// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \
// RUN: | FileCheck --check-prefix=CHECK-ANDROID %s
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: --target=arm-linux-android \
+// RUN: --target=arm-linux-android -rtlib=platform \
// RUN: --gcc-toolchain="" \
// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \
// RUN: | FileCheck --check-prefix=CHECK-ANDROID %s
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: --target=aarch64-linux-android \
+// RUN: --target=aarch64-linux-android -rtlib=platform \
// RUN: --gcc-toolchain="" \
// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \
// RUN: | FileCheck --check-prefix=CHECK-ANDROID %s
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: --target=arm64-linux-android \
+// RUN: --target=arm64-linux-android -rtlib=platform \
// RUN: --gcc-toolchain="" \
// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \
// RUN: | FileCheck --check-prefix=CHECK-ANDROID %s
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: --target=mipsel-linux-android \
+// RUN: --target=mipsel-linux-android -rtlib=platform \
// RUN: --gcc-toolchain="" \
// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \
// RUN: | FileCheck --check-prefix=CHECK-ANDROID %s
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: --target=mips64el-linux-android \
+// RUN: --target=mips64el-linux-android -rtlib=platform \
// RUN: --gcc-toolchain="" \
// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \
// RUN: | FileCheck --check-prefix=CHECK-ANDROID %s
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: --target=i686-linux-android \
+// RUN: --target=i686-linux-android -rtlib=platform \
// RUN: --gcc-toolchain="" \
// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \
// RUN: | FileCheck --check-prefix=CHECK-ANDROID %s
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: --target=x86_64-linux-android \
+// RUN: --target=x86_64-linux-android -rtlib=platform \
// RUN: --gcc-toolchain="" \
// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \
// RUN: | FileCheck --check-prefix=CHECK-ANDROID %s
@@ -1052,48 +1052,48 @@
// CHECK-ANDROID-NOT: "gcc_s"
// CHECK-ANDROID: "{{.*}}{{/|\\\\}}crtend_android.o"
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: --target=arm-linux-androideabi \
+// RUN: --target=arm-linux-androideabi -rtlib=platform \
// RUN: --gcc-toolchain="" \
// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \
// RUN: -shared \
// RUN: | FileCheck --check-prefix=CHECK-ANDROID-SO %s
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: --target=arm-linux-android \
+// RUN: --target=arm-linux-android -rtlib=platform \
// RUN: --gcc-toolchain="" \
// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \
// RUN: -shared \
// RUN: | FileCheck --check-prefix=CHECK-ANDROID-SO %s
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: --target=aarch64-linux-android \
+// RUN: --target=aarch64-linux-android -rtlib=platform \
// RUN: --gcc-toolchain="" \
// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \
// RUN: -shared \
// RUN: | FileCheck --check-prefix=CHECK-ANDROID-SO %s
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: --target=arm64-linux-android \
+// RUN: --target=arm64-linux-android -rtlib=platform \
// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \
// RUN: -shared \
// RUN: | FileCheck --check-prefix=CHECK-ANDROID-SO %s
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: --target=mipsel-linux-android \
+// RUN: --target=mipsel-linux-android -rtlib=platform \
// RUN: --gcc-toolchain="" \
// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \
// RUN: -shared \
// RUN: | FileCheck --check-prefix=CHECK-ANDROID-SO %s
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: --target=mips64el-linux-android \
+// RUN: --target=mips64el-linux-android -rtlib=platform \
// RUN: --gcc-toolchain="" \
// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \
// RUN: -shared \
// RUN: | FileCheck --check-prefix=CHECK-ANDROID-SO %s
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: --target=i686-linux-android \
+// RUN: --target=i686-linux-android -rtlib=platform \
// RUN: --gcc-toolchain="" \
// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \
// RUN: -shared \
// RUN: | FileCheck --check-prefix=CHECK-ANDROID-SO %s
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: --target=x86_64-linux-android \
+// RUN: --target=x86_64-linux-android -rtlib=platform \
// RUN: --gcc-toolchain="" \
// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \
// RUN: -shared \
@@ -1108,47 +1108,47 @@
// CHECK-ANDROID-SO-NOT: "gcc_s"
// CHECK-ANDROID-SO: "{{.*}}{{/|\\\\}}crtend_so.o"
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: --target=arm-linux-androideabi \
+// RUN: --target=arm-linux-androideabi -rtlib=platform \
// RUN: --gcc-toolchain="" \
// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \
// RUN: -static \
// RUN: | FileCheck --check-prefix=CHECK-ANDROID-STATIC %s
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: --target=arm-linux-android \
+// RUN: --target=arm-linux-android -rtlib=platform \
// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \
// RUN: -static \
// RUN: | FileCheck --check-prefix=CHECK-ANDROID-STATIC %s
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: --target=aarch64-linux-android \
+// RUN: --target=aarch64-linux-android -rtlib=platform \
// RUN: --gcc-toolchain="" \
// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \
// RUN: -static \
// RUN: | FileCheck --check-prefix=CHECK-ANDROID-STATIC %s
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: --target=arm64-linux-android \
+// RUN: --target=arm64-linux-android -rtlib=platform \
// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \
// RUN: -static \
// RUN: | FileCheck --check-prefix=CHECK-ANDROID-STATIC %s
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: --target=mipsel-linux-android \
+// RUN: --target=mipsel-linux-android -rtlib=platform \
// RUN: --gcc-toolchain="" \
// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \
// RUN: -static \
// RUN: | FileCheck --check-prefix=CHECK-ANDROID-STATIC %s
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: --target=mips64el-linux-android \
+// RUN: --target=mips64el-linux-android -rtlib=platform \
// RUN: --gcc-toolchain="" \
// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \
// RUN: -static \
// RUN: | FileCheck --check-prefix=CHECK-ANDROID-STATIC %s
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: --target=i686-linux-android \
+// RUN: --target=i686-linux-android -rtlib=platform \
// RUN: --gcc-toolchain="" \
// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \
// RUN: -static \
// RUN: | FileCheck --check-prefix=CHECK-ANDROID-STATIC %s
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: --target=x86_64-linux-android \
+// RUN: --target=x86_64-linux-android -rtlib=platform \
// RUN: --gcc-toolchain="" \
// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \
// RUN: -static \
@@ -1162,49 +1162,49 @@
// CHECK-ANDROID-STATIC-NOT: "gcc_s"
// CHECK-ANDROID-STATIC: "{{.*}}{{/|\\\\}}crtend_android.o"
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: --target=arm-linux-androideabi \
+// RUN: --target=arm-linux-androideabi -rtlib=platform \
// RUN: --gcc-toolchain="" \
// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \
// RUN: -pie \
// RUN: | FileCheck --check-prefix=CHECK-ANDROID-PIE %s
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: --target=arm-linux-android \
+// RUN: --target=arm-linux-android -rtlib=platform \
// RUN: --gcc-toolchain="" \
// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \
// RUN: -pie \
// RUN: | FileCheck --check-prefix=CHECK-ANDROID-PIE %s
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: --target=aarch64-linux-android \
+// RUN: --target=aarch64-linux-android -rtlib=platform \
// RUN: --gcc-toolchain="" \
// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \
// RUN: -pie \
// RUN: | FileCheck --check-prefix=CHECK-ANDROID-PIE %s
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: --target=arm64-linux-android \
+// RUN: --target=arm64-linux-android -rtlib=platform \
// RUN: --gcc-toolchain="" \
// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \
// RUN: -pie \
// RUN: | FileCheck --check-prefix=CHECK-ANDROID-PIE %s
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: --target=mipsel-linux-android \
+// RUN: --target=mipsel-linux-android -rtlib=platform \
// RUN: --gcc-toolchain="" \
// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \
// RUN: -pie \
// RUN: | FileCheck --check-prefix=CHECK-ANDROID-PIE %s
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: --target=mips64el-linux-android \
+// RUN: --target=mips64el-linux-android -rtlib=platform \
// RUN: --gcc-toolchain="" \
// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \
// RUN: -pie \
// RUN: | FileCheck --check-prefix=CHECK-ANDROID-PIE %s
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: --target=i686-linux-android \
+// RUN: --target=i686-linux-android -rtlib=platform \
// RUN: --gcc-toolchain="" \
// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \
// RUN: -pie \
// RUN: | FileCheck --check-prefix=CHECK-ANDROID-PIE %s
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: --target=x86_64-linux-android \
+// RUN: --target=x86_64-linux-android -rtlib=platform \
// RUN: --gcc-toolchain="" \
// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \
// RUN: -pie \
@@ -1613,24 +1613,36 @@
// RUN: --target=thumb-pc-linux-musleabihf \
// RUN: | FileCheck --check-prefix=CHECK-MUSL-ARMHF %s
// RUN: %clang %s -### -o %t.o 2>&1 \
+// RUN: --target=thumbv7-pc-linux-musleabi -mhard-float \
+// RUN: | FileCheck --check-prefix=CHECK-MUSL-ARMHF %s
+// RUN: %clang %s -### -o %t.o 2>&1 \
// RUN: --target=thumbeb-pc-linux-musleabi \
// RUN: | FileCheck --check-prefix=CHECK-MUSL-ARMEB %s
// RUN: %clang %s -### -o %t.o 2>&1 \
// RUN: --target=thumbeb-pc-linux-musleabihf \
// RUN: | FileCheck --check-prefix=CHECK-MUSL-ARMEBHF %s
// RUN: %clang %s -### -o %t.o 2>&1 \
+// RUN: --target=thumbv7eb-pc-linux-musleabi -mhard-float \
+// RUN: | FileCheck --check-prefix=CHECK-MUSL-ARMEBHF %s
+// RUN: %clang %s -### -o %t.o 2>&1 \
// RUN: --target=arm-pc-linux-musleabi \
// RUN: | FileCheck --check-prefix=CHECK-MUSL-ARM %s
// RUN: %clang %s -### -o %t.o 2>&1 \
// RUN: --target=arm-pc-linux-musleabihf \
// RUN: | FileCheck --check-prefix=CHECK-MUSL-ARMHF %s
// RUN: %clang %s -### -o %t.o 2>&1 \
+// RUN: --target=armv7-pc-linux-musleabi -mhard-float \
+// RUN: | FileCheck --check-prefix=CHECK-MUSL-ARMHF %s
+// RUN: %clang %s -### -o %t.o 2>&1 \
// RUN: --target=armeb-pc-linux-musleabi \
// RUN: | FileCheck --check-prefix=CHECK-MUSL-ARMEB %s
// RUN: %clang %s -### -o %t.o 2>&1 \
// RUN: --target=armeb-pc-linux-musleabihf \
// RUN: | FileCheck --check-prefix=CHECK-MUSL-ARMEBHF %s
// RUN: %clang %s -### -o %t.o 2>&1 \
+// RUN: --target=armv7eb-pc-linux-musleabi -mhard-float \
+// RUN: | FileCheck --check-prefix=CHECK-MUSL-ARMEBHF %s
+// RUN: %clang %s -### -o %t.o 2>&1 \
// RUN: --target=aarch64-pc-linux-musleabi \
// RUN: | FileCheck --check-prefix=CHECK-MUSL-AARCH64 %s
// RUN: %clang %s -### -o %t.o 2>&1 \
@@ -1650,3 +1662,56 @@
// CHECK-MUSL-ARMEBHF: "-dynamic-linker" "/lib/ld-musl-armebhf.so.1"
// CHECK-MUSL-AARCH64: "-dynamic-linker" "/lib/ld-musl-aarch64.so.1"
// CHECK-MUSL-AARCH64_BE: "-dynamic-linker" "/lib/ld-musl-aarch64_be.so.1"
+
+// Check whether multilib gcc install works fine on Gentoo with gcc-config
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN: --target=x86_64-unknown-linux-gnu -rtlib=platform \
+// RUN: --sysroot=%S/Inputs/gentoo_linux_gcc_multi_version_tree \
+// RUN: --gcc-toolchain="" \
+// RUN: | FileCheck --check-prefix=CHECK-LD-GENTOO %s
+// CHECK-LD-GENTOO-NOT: warning:
+// CHECK-LD-GENTOO: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
+// CHECK-LD-GENTOO: "--eh-frame-hdr"
+// CHECK-LD-GENTOO: "-m" "elf_x86_64"
+// CHECK-LD-GENTOO: "-dynamic-linker"
+// CHECK-LD-GENTOO: "{{.*}}/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3{{/|\\\\}}crtbegin.o"
+// CHECK-LD-GENTOO: "-L[[SYSROOT]]/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3"
+// CHECK-LD-GENTOO: "-L[[SYSROOT]]/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/../../../../x86_64-pc-linux-gnu/lib"
+// CHECK-LD-GENTOO: "-L[[SYSROOT]]/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/../../.."
+// CHECK-LD-GENTOO: "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed"
+// CHECK-LD-GENTOO: "-lc"
+// CHECK-LD-GENTOO: "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed"
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN: --target=i686-unknown-linux-gnu -rtlib=platform \
+// RUN: --sysroot=%S/Inputs/gentoo_linux_gcc_multi_version_tree \
+// RUN: --gcc-toolchain="" \
+// RUN: | FileCheck --check-prefix=CHECK-LD-GENTOO-32 %s
+// CHECK-LD-GENTOO-32-NOT: warning:
+// CHECK-LD-GENTOO-32: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
+// CHECK-LD-GENTOO-32: "--eh-frame-hdr"
+// CHECK-LD-GENTOO-32: "-m" "elf_i386"
+// CHECK-LD-GENTOO-32: "-dynamic-linker"
+// CHECK-LD-GENTOO-32: "{{.*}}/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/32{{/|\\\\}}crtbegin.o"
+// CHECK-LD-GENTOO-32: "-L[[SYSROOT]]/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/32"
+// CHECK-LD-GENTOO-32: "-L[[SYSROOT]]/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/../../../../x86_64-pc-linux-gnu/lib"
+// CHECK-LD-GENTOO-32: "-L[[SYSROOT]]/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/../../.."
+// CHECK-LD-GENTOO-32: "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed"
+// CHECK-LD-GENTOO-32: "-lc"
+// CHECK-LD-GENTOO-32: "-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-gnux32 -rtlib=platform \
+// RUN: --sysroot=%S/Inputs/gentoo_linux_gcc_multi_version_tree \
+// RUN: --gcc-toolchain="" \
+// RUN: | FileCheck --check-prefix=CHECK-LD-GENTOO-X32 %s
+// CHECK-LD-GENTOO-X32-NOT: warning:
+// CHECK-LD-GENTOO-X32: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
+// CHECK-LD-GENTOO-X32: "--eh-frame-hdr"
+// CHECK-LD-GENTOO-X32: "-m" "elf32_x86_64"
+// CHECK-LD-GENTOO-X32: "-dynamic-linker"
+// CHECK-LD-GENTOO-X32: "{{.*}}/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/x32{{/|\\\\}}crtbegin.o"
+// CHECK-LD-GENTOO-X32: "-L[[SYSROOT]]/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/x32"
+// CHECK-LD-GENTOO-X32: "-L[[SYSROOT]]/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/../../../../x86_64-pc-linux-gnu/lib"
+// CHECK-LD-GENTOO-X32: "-L[[SYSROOT]]/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/../../.."
+// 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"
diff --git a/test/Driver/lto-jobs.c b/test/Driver/lto-jobs.c
new file mode 100644
index 000000000000..539867713b07
--- /dev/null
+++ b/test/Driver/lto-jobs.c
@@ -0,0 +1,11 @@
+// Confirm that -flto-jobs=N is passed to linker
+
+// RUN: %clang -target x86_64-unknown-linux -### %s -flto=thin -flto-jobs=5 2> %t
+// RUN: FileCheck -check-prefix=CHECK-LINK-THIN-JOBS-ACTION < %t %s
+//
+// CHECK-LINK-THIN-JOBS-ACTION: "-plugin-opt=jobs=5"
+
+// RUN: %clang -target x86_64-apple-darwin13.3.0 -### %s -flto=thin -flto-jobs=5 2> %t
+// RUN: FileCheck -check-prefix=CHECK-LINK-THIN-JOBS2-ACTION < %t %s
+//
+// CHECK-LINK-THIN-JOBS2-ACTION: "-mllvm" "-threads=5"
diff --git a/test/Driver/masm.s b/test/Driver/masm.s
new file mode 100644
index 000000000000..b77e8369b846
--- /dev/null
+++ b/test/Driver/masm.s
@@ -0,0 +1,11 @@
+// RUN: %clang -target i386-unknown-linux -masm=intel -c %s -### 2>&1 | FileCheck --check-prefix=CHECK-INTEL %s
+// RUN: %clang -target i386-unknown-linux -masm=att -c %s -### 2>&1 | FileCheck --check-prefix=CHECK-ATT %s
+// RUN: %clang -target i386-unknown-linux -c -masm=somerequired %s -### 2>&1 | FileCheck --check-prefix=CHECK-SOMEREQUIRED %s
+// RUN: %clang -target arm-unknown-eabi -c -masm=intel %s -### 2>&1 | FileCheck --check-prefix=CHECK-ARM %s
+
+// 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'
+.text
+mov al, 0
diff --git a/test/Driver/miamcu-opt.c b/test/Driver/miamcu-opt.c
index 7f96998837e9..577bd3772d47 100644
--- a/test/Driver/miamcu-opt.c
+++ b/test/Driver/miamcu-opt.c
@@ -1,13 +1,13 @@
// REQUIRES: clang-driver
// REQUIRES: x86-registered-target
//
-// RUN: %clang -miamcu -no-canonical-prefixes %s -### -o %t.o 2>&1 | FileCheck %s
-// RUN: %clang -miamcu -no-canonical-prefixes -m32 %s -### -o %t.o 2>&1 | FileCheck %s
-// RUN: %clang -miamcu -no-canonical-prefixes -target x86_64-unknown-linux-gnu %s -### -o %t.o 2>&1 | FileCheck %s
-// RUN: %clang -mno-iamcu -miamcu -no-canonical-prefixes %s -### -o %t.o 2>&1 | FileCheck %s
-// RUN: %clang -miamcu -no-canonical-prefixes -m64 %s -### -o %t.o 2>&1 | FileCheck %s -check-prefix=M64
-// RUN: %clang -miamcu -no-canonical-prefixes -dynamic %s -### -o %t.o 2>&1 | FileCheck %s -check-prefix=DYNAMIC
-// RUN: %clang -miamcu -no-canonical-prefixes -target armv8-eabi %s -### -o %t.o 2>&1 | FileCheck %s -check-prefix=NOT-X86
+// RUN: %clang -miamcu -rtlib=platform -no-canonical-prefixes %s -### -o %t.o 2>&1 | FileCheck %s
+// RUN: %clang -miamcu -rtlib=platform -no-canonical-prefixes -m32 %s -### -o %t.o 2>&1 | FileCheck %s
+// RUN: %clang -miamcu -rtlib=platform -no-canonical-prefixes -target x86_64-unknown-linux-gnu %s -### -o %t.o 2>&1 | FileCheck %s
+// RUN: %clang -mno-iamcu -miamcu -rtlib=platform -no-canonical-prefixes %s -### -o %t.o 2>&1 | FileCheck %s
+// RUN: %clang -miamcu -rtlib=platform -no-canonical-prefixes -m64 %s -### -o %t.o 2>&1 | FileCheck %s -check-prefix=M64
+// RUN: %clang -miamcu -rtlib=platform -no-canonical-prefixes -dynamic %s -### -o %t.o 2>&1 | FileCheck %s -check-prefix=DYNAMIC
+// RUN: %clang -miamcu -rtlib=platform -no-canonical-prefixes -target armv8-eabi %s -### -o %t.o 2>&1 | FileCheck %s -check-prefix=NOT-X86
// RUN: %clang -miamcu -mno-iamcu -no-canonical-prefixes -target x86_64-unknown-linux-gnu %s -### -o %t.o 2>&1 | FileCheck %s -check-prefix=MNOIAMCU
// M64: error: invalid argument '-miamcu' not allowed with '-m64'
diff --git a/test/Driver/miamcu-opt.cpp b/test/Driver/miamcu-opt.cpp
index 6c8d7552bc13..b63c4555b0c8 100644
--- a/test/Driver/miamcu-opt.cpp
+++ b/test/Driver/miamcu-opt.cpp
@@ -1,3 +1,3 @@
-// RUN: %clang -miamcu %s -### -o %t.o 2>&1 | FileCheck %s
+// RUN: %clang -miamcu -rtlib=platform %s -### -o %t.o 2>&1 | FileCheck %s
// CHECK: error: the clang compiler does not support 'C++ for IAMCU'
diff --git a/test/Driver/mingw-libgcc.c b/test/Driver/mingw-libgcc.c
index 75a569644215..1d45c91651de 100644
--- a/test/Driver/mingw-libgcc.c
+++ b/test/Driver/mingw-libgcc.c
@@ -2,24 +2,24 @@
// 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 -### %s 2>&1 | FileCheck -check-prefix=CHECK_STATIC %s
-// RUN: %clang -static -v -target i686-pc-windows-gnu -### %s 2>&1 | FileCheck -check-prefix=CHECK_STATIC %s
-// RUN: %clang -static-libgcc -v -target i686-pc-windows-gnu -### %s 2>&1 | FileCheck -check-prefix=CHECK_STATIC %s
-// RUN: %clang -static -shared -v -target i686-pc-windows-gnu -### %s 2>&1 | FileCheck -check-prefix=CHECK_STATIC %s
-// RUN: %clang -static-libgcc -shared -v -target i686-pc-windows-gnu -### %s 2>&1 | FileCheck -check-prefix=CHECK_STATIC %s
+// 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
// gcc, dynamic
-// RUN: %clang -shared -v -target i686-pc-windows-gnu -### %s 2>&1 | FileCheck -check-prefix=CHECK_DYNAMIC %s
+// RUN: %clang -shared -v -target i686-pc-windows-gnu -rtlib=platform -### %s 2>&1 | FileCheck -check-prefix=CHECK_DYNAMIC %s
// g++, static
-// RUN: %clang -static --driver-mode=g++ -v -target i686-pc-windows-gnu -### %s 2>&1 | FileCheck -check-prefix=CHECK_STATIC %s
-// RUN: %clang -static-libgcc --driver-mode=g++ -v -target i686-pc-windows-gnu -### %s 2>&1 | FileCheck -check-prefix=CHECK_STATIC %s
-// RUN: %clang -static -shared --driver-mode=g++ -v -target i686-pc-windows-gnu -### %s 2>&1 | FileCheck -check-prefix=CHECK_STATIC %s
-// RUN: %clang -static-libgcc -shared --driver-mode=g++ -v -target i686-pc-windows-gnu -### %s 2>&1 | FileCheck -check-prefix=CHECK_STATIC %s
+// RUN: %clang -static --driver-mode=g++ -v -target i686-pc-windows-gnu -rtlib=platform -### %s 2>&1 | FileCheck -check-prefix=CHECK_STATIC %s
+// RUN: %clang -static-libgcc --driver-mode=g++ -v -target i686-pc-windows-gnu -rtlib=platform -### %s 2>&1 | FileCheck -check-prefix=CHECK_STATIC %s
+// RUN: %clang -static -shared --driver-mode=g++ -v -target i686-pc-windows-gnu -rtlib=platform -### %s 2>&1 | FileCheck -check-prefix=CHECK_STATIC %s
+// RUN: %clang -static-libgcc -shared --driver-mode=g++ -v -target i686-pc-windows-gnu -rtlib=platform -### %s 2>&1 | FileCheck -check-prefix=CHECK_STATIC %s
// g++, dynamic
-// RUN: %clang --driver-mode=g++ -v -target i686-pc-windows-gnu -### %s 2>&1 | FileCheck -check-prefix=CHECK_DYNAMIC %s
-// RUN: %clang -shared --driver-mode=g++ -v -target i686-pc-windows-gnu -### %s 2>&1 | FileCheck -check-prefix=CHECK_DYNAMIC %s
+// 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_STATIC: "-lgcc" "-lgcc_eh"
// CHECK_DYNAMIC: "-lgcc_s" "-lgcc"
diff --git a/test/Driver/mingw.cpp b/test/Driver/mingw.cpp
index 8dc5b96034ce..c939c7a33b18 100644
--- a/test/Driver/mingw.cpp
+++ b/test/Driver/mingw.cpp
@@ -1,9 +1,9 @@
-// RUN: %clang -target i686-windows-gnu -c -### --sysroot=%S/Inputs/mingw_clang_tree/mingw32 %s 2>&1 | FileCheck -check-prefix=CHECK_MINGW_CLANG_TREE %s
+// RUN: %clang -target i686-windows-gnu -rtlib=platform -c -### --sysroot=%S/Inputs/mingw_clang_tree/mingw32 %s 2>&1 | FileCheck -check-prefix=CHECK_MINGW_CLANG_TREE %s
// CHECK_MINGW_CLANG_TREE: "{{.*}}/Inputs/mingw_clang_tree/mingw32{{/|\\\\}}i686-w64-mingw32{{/|\\\\}}include"
// CHECK_MINGW_CLANG_TREE: "{{.*}}/Inputs/mingw_clang_tree/mingw32{{/|\\\\}}include"
-// RUN: %clang -target i686-pc-windows-gnu -stdlib=libstdc++ -c -### --sysroot=%S/Inputs/mingw_mingw_org_tree/mingw %s 2>&1 | FileCheck -check-prefix=CHECK_MINGW_ORG_TREE %s
+// 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"
// CHECK_MINGW_ORG_TREE: "{{.*}}{{/|\\\\}}Inputs/mingw_mingw_org_tree/mingw{{/|\\\\}}lib{{/|\\\\}}gcc{{/|\\\\}}mingw32{{/|\\\\}}4.8.1{{/|\\\\}}include{{/|\\\\}}c++{{/|\\\\}}backward"
@@ -13,7 +13,7 @@
// CHECK_MINGW_ORG_TREE: {{.*}}/Inputs/mingw_mingw_org_tree/mingw{{/|\\\\}}include
-// RUN: %clang -target i686-pc-windows-gnu -stdlib=libstdc++ -c -### --sysroot=%S/Inputs/mingw_mingw_builds_tree/mingw32 %s 2>&1 | FileCheck -check-prefix=CHECK_MINGW_BUILDS_TREE %s
+// RUN: %clang -target i686-pc-windows-gnu -rtlib=platform -stdlib=libstdc++ -c -### --sysroot=%S/Inputs/mingw_mingw_builds_tree/mingw32 %s 2>&1 | FileCheck -check-prefix=CHECK_MINGW_BUILDS_TREE %s
// CHECK_MINGW_BUILDS_TREE: "{{.*}}/Inputs/mingw_mingw_builds_tree/mingw32{{/|\\\\}}i686-w64-mingw32{{/|\\\\}}include{{/|\\\\}}c++"
// CHECK_MINGW_BUILDS_TREE: "{{.*}}/Inputs/mingw_mingw_builds_tree/mingw32{{/|\\\\}}i686-w64-mingw32{{/|\\\\}}include{{/|\\\\}}c++{{/|\\\\}}i686-w64-mingw32"
// CHECK_MINGW_BUILDS_TREE: "{{.*}}/Inputs/mingw_mingw_builds_tree/mingw32{{/|\\\\}}i686-w64-mingw32{{/|\\\\}}include{{/|\\\\}}c++{{/|\\\\}}backward"
@@ -22,7 +22,7 @@
// CHECK_MINGW_BUILDS_TREE: "{{.*}}/Inputs/mingw_mingw_builds_tree/mingw32{{/|\\\\}}i686-w64-mingw32{{/|\\\\}}include"
-// RUN: %clang -target i686-pc-windows-gnu -stdlib=libstdc++ -c -### --sysroot=%S/Inputs/mingw_msys2_tree/msys64/mingw32 %s 2>&1 | FileCheck -check-prefix=CHECK_MINGW_MSYS_TREE %s
+// RUN: %clang -target i686-pc-windows-gnu -rtlib=platform -stdlib=libstdc++ -c -### --sysroot=%S/Inputs/mingw_msys2_tree/msys64/mingw32 %s 2>&1 | FileCheck -check-prefix=CHECK_MINGW_MSYS_TREE %s
// CHECK_MINGW_MSYS_TREE: "{{.*}}/Inputs/mingw_msys2_tree/msys64{{/|\\\\}}mingw32{{/|\\\\}}include{{/|\\\\}}c++{{/|\\\\}}4.9.2"
// CHECK_MINGW_MSYS_TREE: "{{.*}}/Inputs/mingw_msys2_tree/msys64/mingw32{{/|\\\\}}include{{/|\\\\}}c++{{/|\\\\}}4.9.2{{/|\\\\}}i686-w64-mingw32"
// CHECK_MINGW_MSYS_TREE: "{{.*}}/Inputs/mingw_msys2_tree/msys64/mingw32{{/|\\\\}}include{{/|\\\\}}c++{{/|\\\\}}4.9.2{{/|\\\\}}backward"
@@ -32,7 +32,7 @@
// CHECK_MINGW_MSYS_TREE: "{{.*}}/Inputs/mingw_msys2_tree/msys64/mingw32{{/|\\\\}}include"
-// RUN: %clang -target x86_64-pc-windows-gnu -stdlib=libstdc++ -c -### --sysroot=%S/Inputs/mingw_opensuse_tree/usr %s 2>&1 | FileCheck -check-prefix=CHECK_MINGW_OPENSUSE_TREE %s
+// RUN: %clang -target x86_64-pc-windows-gnu -rtlib=platform -stdlib=libstdc++ -c -### --sysroot=%S/Inputs/mingw_opensuse_tree/usr %s 2>&1 | FileCheck -check-prefix=CHECK_MINGW_OPENSUSE_TREE %s
// CHECK_MINGW_OPENSUSE_TREE: "{{.*}}/Inputs/mingw_opensuse_tree/usr{{/|\\\\}}lib64{{/|\\\\}}gcc{{/|\\\\}}x86_64-w64-mingw32{{/|\\\\}}5.1.0{{/|\\\\}}include{{/|\\\\}}c++"
// CHECK_MINGW_OPENSUSE_TREE: "{{.*}}/Inputs/mingw_opensuse_tree/usr{{/|\\\\}}lib64{{/|\\\\}}gcc{{/|\\\\}}x86_64-w64-mingw32{{/|\\\\}}5.1.0{{/|\\\\}}include{{/|\\\\}}c++{{/|\\\\}}x86_64-w64-mingw32"
// CHECK_MINGW_OPENSUSE_TREE: "{{.*}}/Inputs/mingw_opensuse_tree/usr{{/|\\\\}}lib64{{/|\\\\}}gcc{{/|\\\\}}x86_64-w64-mingw32{{/|\\\\}}5.1.0{{/|\\\\}}include{{/|\\\\}}c++{{/|\\\\}}backward"
@@ -41,7 +41,7 @@
// CHECK_MINGW_OPENSUSE_TREE: "{{.*}}/Inputs/mingw_opensuse_tree/usr{{/|\\\\}}lib64{{/|\\\\}}gcc{{/|\\\\}}x86_64-w64-mingw32{{/|\\\\}}5.1.0{{/|\\\\}}include-fixed"
-// RUN: %clang -target i686-pc-windows-gnu -stdlib=libstdc++ -c -### --sysroot=%S/Inputs/mingw_arch_tree/usr %s 2>&1 | FileCheck -check-prefix=CHECK_MINGW_ARCH_TREE %s
+// RUN: %clang -target i686-pc-windows-gnu -rtlib=platform -stdlib=libstdc++ -c -### --sysroot=%S/Inputs/mingw_arch_tree/usr %s 2>&1 | FileCheck -check-prefix=CHECK_MINGW_ARCH_TREE %s
// CHECK_MINGW_ARCH_TREE: "{{.*}}/Inputs/mingw_arch_tree/usr{{/|\\\\}}i686-w64-mingw32{{/|\\\\}}include{{/|\\\\}}c++{{/|\\\\}}5.1.0"
// CHECK_MINGW_ARCH_TREE: "{{.*}}/Inputs/mingw_arch_tree/usr{{/|\\\\}}i686-w64-mingw32{{/|\\\\}}include{{/|\\\\}}c++{{/|\\\\}}5.1.0{{/|\\\\}}i686-w64-mingw32"
// CHECK_MINGW_ARCH_TREE: "{{.*}}/Inputs/mingw_arch_tree/usr{{/|\\\\}}i686-w64-mingw32{{/|\\\\}}include{{/|\\\\}}c++{{/|\\\\}}5.1.0{{/|\\\\}}backward"
@@ -50,7 +50,7 @@
// CHECK_MINGW_ARCH_TREE: "{{.*}}/Inputs/mingw_arch_tree/usr{{/|\\\\}}i686-w64-mingw32{{/|\\\\}}include"
-// RUN: %clang -target x86_64-pc-windows-gnu -stdlib=libstdc++ -c -### --sysroot=%S/Inputs/mingw_ubuntu_tree/usr %s 2>&1 | FileCheck -check-prefix=CHECK_MINGW_UBUNTU_TREE %s
+// RUN: %clang -target x86_64-pc-windows-gnu -rtlib=platform -stdlib=libstdc++ -c -### --sysroot=%S/Inputs/mingw_ubuntu_tree/usr %s 2>&1 | FileCheck -check-prefix=CHECK_MINGW_UBUNTU_TREE %s
// CHECK_MINGW_UBUNTU_TREE: "{{.*}}/Inputs/mingw_ubuntu_tree/usr{{/|\\\\}}include{{/|\\\\}}c++{{/|\\\\}}4.8"
// 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"
diff --git a/test/Driver/mips-cs.cpp b/test/Driver/mips-cs.cpp
index bca2ab9fa26f..6ef4c5d4350c 100644
--- a/test/Driver/mips-cs.cpp
+++ b/test/Driver/mips-cs.cpp
@@ -1,3 +1,5 @@
+// REQUIRES: mips-registered-target
+//
// Check frontend and linker invocations on Mentor Graphics MIPS toolchain.
//
// = Big-endian, hard float
diff --git a/test/Driver/mips-fsf.cpp b/test/Driver/mips-fsf.cpp
index 68ee490a88ac..b94da6978916 100644
--- a/test/Driver/mips-fsf.cpp
+++ b/test/Driver/mips-fsf.cpp
@@ -1,3 +1,5 @@
+// REQUIRES: mips-registered-target
+
// Check frontend and linker invocations on FSF MIPS toolchain.
//
// = Big-endian, mips32, hard float
diff --git a/test/Driver/mips-img-v2.cpp b/test/Driver/mips-img-v2.cpp
index 34cf3d726e2d..69250b716e5b 100644
--- a/test/Driver/mips-img-v2.cpp
+++ b/test/Driver/mips-img-v2.cpp
@@ -1,3 +1,5 @@
+// REQUIRES: mips-registered-target
+
// Check frontend and linker invocations on the IMG v2 MIPS toolchain.
// -EB -mips32r6 -mhard-float -mabi=32
diff --git a/test/Driver/mips-img.cpp b/test/Driver/mips-img.cpp
index 9d8cfba13ef6..c97bb9478e7c 100644
--- a/test/Driver/mips-img.cpp
+++ b/test/Driver/mips-img.cpp
@@ -1,3 +1,5 @@
+// REQUIRES: mips-registered-target
+
// Check frontend and linker invocations on the IMG MIPS toolchain.
//
// = Big-endian, mips32r6
diff --git a/test/Driver/mips-mti-linux.c b/test/Driver/mips-mti-linux.c
index e3560e204406..4835d798c269 100644
--- a/test/Driver/mips-mti-linux.c
+++ b/test/Driver/mips-mti-linux.c
@@ -8,7 +8,7 @@
// = Big-endian, mips32r2, hard float
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: --target=mips-mti-linux -mips32r2 -mhard-float \
+// RUN: --target=mips-mti-linux -mips32r2 -mhard-float -rtlib=platform \
// RUN: --sysroot=%S/Inputs/mips_mti_linux/sysroot \
// RUN: | FileCheck --check-prefix=CHECK-BE-HF-32R2 %s
//
@@ -26,7 +26,7 @@
// = Little-endian, mips32r2, hard float
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: --target=mips-mti-linux -mips32r2 -EL -mhard-float \
+// RUN: --target=mips-mti-linux -mips32r2 -EL -mhard-float -rtlib=platform \
// RUN: --sysroot=%S/Inputs/mips_mti_linux/sysroot \
// RUN: | FileCheck --check-prefix=CHECK-LE-HF-32R2 %s
//
diff --git a/test/Driver/modules-ts.cpp b/test/Driver/modules-ts.cpp
new file mode 100644
index 000000000000..0fdc61b6f9ce
--- /dev/null
+++ b/test/Driver/modules-ts.cpp
@@ -0,0 +1,38 @@
+// Check compiling a module interface to a .pcm file.
+//
+// RUN: %clang -fmodules-ts -x c++-module --precompile %s -Dimplementation= -o %t.pcm -v 2>&1 | FileCheck %s --check-prefix=CHECK-PRECOMPILE
+//
+// CHECK-PRECOMPILE: -cc1 {{.*}} -emit-module-interface
+// CHECK-PRECOMPILE-SAME: -o {{.*}}.pcm
+// CHECK-PRECOMPILE-SAME: -x c++-module
+// CHECK-PRECOMPILE-SAME: modules-ts.cpp
+
+// Check compiling a .pcm file to a .o file.
+//
+// RUN: %clang -fmodules-ts %t.pcm -c -o %t.pcm.o -v 2>&1 | FileCheck %s --check-prefix=CHECK-COMPILE
+//
+// CHECK-COMPILE: -cc1 {{.*}} -emit-obj
+// CHECK-COMPILE-SAME: -o {{.*}}.pcm.o
+// CHECK-COMPILE-SAME: -x pcm
+// CHECK-COMPILE-SAME: {{.*}}.pcm
+
+// Check use of a .pcm file in another compilation.
+//
+// RUN: %clang -fmodules-ts -fmodule-file=%t.pcm %s -c -o %t.o -v 2>&1 | FileCheck %s --check-prefix=CHECK-USE
+//
+// CHECK-USE: -cc1
+// CHECK-USE-SAME: -emit-obj
+// CHECK-USE-SAME: -fmodule-file={{.*}}.pcm
+// CHECK-USE-SAME: -o {{.*}}.o{{"?}} {{.*}}-x c++
+// CHECK-USE-SAME: modules-ts.cpp
+
+// Check combining precompile and compile steps works.
+//
+// RUN: %clang -fmodules-ts -x c++-module %s -Dimplementation= -c -o %t.pcm.o -v 2>&1 | FileCheck %s --check-prefix=CHECK-PRECOMPILE --check-prefix=CHECK-COMPILE
+
+// Check that .cppm is treated as a module implicitly.
+// RUN: cp %s %t.cppm
+// RUN: %clang -fmodules-ts --precompile %t.cppm -Dimplementation= -o %t.pcm -v 2>&1 | FileCheck %s --check-prefix=CHECK-PRECOMPILE
+
+// Note, we use -Dimplementation= to make this a valid module interface unit when building the interface.
+module implementation foo;
diff --git a/test/Driver/modules.m b/test/Driver/modules.m
index 0f2d4d5bb0b4..e08de94d0e86 100644
--- a/test/Driver/modules.m
+++ b/test/Driver/modules.m
@@ -33,11 +33,28 @@
// 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 -### %s 2>&1 | FileCheck -check-prefix=MODULES_DISABLE_DIAGNOSTIC_VALIDATION_DEFAULT %s
+// MODULES_DISABLE_DIAGNOSTIC_VALIDATION_DEFAULT-NOT: -fmodules-disable-diagnostic-validation
+
+// RUN: %clang -fmodules-disable-diagnostic-validation -### %s 2>&1 | FileCheck -check-prefix=MODULES_DISABLE_DIAGNOSTIC_VALIDATION %s
+// MODULES_DISABLE_DIAGNOSTIC_VALIDATION: -fmodules-disable-diagnostic-validation
+
+// RUN: %clang -fmodules -### %s 2>&1 | FileCheck -check-prefix=MODULES_PREBUILT_PATH_DEFAULT %s
+// MODULES_PREBUILT_PATH_DEFAULT-NOT: -fprebuilt-module-path
+
+// RUN: %clang -fmodules -fprebuilt-module-path=foo -fprebuilt-module-path=bar -### %s 2>&1 | FileCheck -check-prefix=MODULES_PREBUILT_PATH %s
+// MODULES_PREBUILT_PATH: "-fprebuilt-module-path=foo"
+// MODULES_PREBUILT_PATH: "-fprebuilt-module-path=bar"
+
// RUN: %clang -fmodules -fmodule-map-file=foo.map -fmodule-map-file=bar.map -### %s 2>&1 | FileCheck -check-prefix=CHECK-MODULE-MAP-FILES %s
// CHECK-MODULE-MAP-FILES: "-fmodules"
// CHECK-MODULE-MAP-FILES: "-fmodule-map-file=foo.map"
// CHECK-MODULE-MAP-FILES: "-fmodule-map-file=bar.map"
+// RUN: %clang -fmodules -fbuiltin-module-map -### %s 2>&1 | FileCheck -check-prefix=CHECK-BUILTIN-MODULE-MAP %s
+// CHECK-BUILTIN-MODULE-MAP: "-fmodules"
+// CHECK-BUILTIN-MODULE-MAP: "-fmodule-map-file={{.*}}include{{/|\\\\}}module.modulemap"
+
// RUN: %clang -fmodules -fmodule-file=foo.pcm -fmodule-file=bar.pcm -### %s 2>&1 | FileCheck -check-prefix=CHECK-MODULE-FILES %s
// CHECK-MODULE-FILES: "-fmodules"
// CHECK-MODULE-FILES: "-fmodule-file=foo.pcm"
diff --git a/test/Driver/montavista-gcc-toolchain.c b/test/Driver/montavista-gcc-toolchain.c
index da76e9579439..402e53b63c5a 100644
--- a/test/Driver/montavista-gcc-toolchain.c
+++ b/test/Driver/montavista-gcc-toolchain.c
@@ -1,6 +1,6 @@
// Test that the montavista gcc-toolchain is correctly detected
//
-// RUN: %clang -print-libgcc-file-name 2>&1 \
+// RUN: %clang -rtlib=platform -print-libgcc-file-name 2>&1 \
// RUN: --target=i686-montavista-linux \
// RUN: --gcc-toolchain=%S/Inputs/montavista_i686_tree/usr \
// RUN: | FileCheck %s
diff --git a/test/Driver/msc-version.c b/test/Driver/msc-version.c
index 924633508bcd..7e71b9cac8ea 100644
--- a/test/Driver/msc-version.c
+++ b/test/Driver/msc-version.c
@@ -55,3 +55,12 @@
// CHECK-MSC-15-NOT: "-fmsc-version=150020706"
// CHECK-MSC-15: "-fms-compatibility-version=15.0.20706"
+//
+// Verify default version with -fms-extensions
+//
+
+// RUN: %clang -target i686-windows -fms-extensions -dM -E - </dev/null -o - | FileCheck %s -check-prefix CHECK-MS-EXTENSIONS
+
+// CHECK-MS-EXTENSIONS: _MSC_BUILD 1
+// CHECK-MS-EXTENSIONS: _MSC_FULL_VER {{.+}}
+// CHECK-MS-EXTENSIONS: _MSC_VER {{..}}00
diff --git a/test/Driver/msvc-triple.c b/test/Driver/msvc-triple.c
index cb0c338f8415..42bd02a158ea 100644
--- a/test/Driver/msvc-triple.c
+++ b/test/Driver/msvc-triple.c
@@ -1,7 +1,9 @@
// RUN: %clang -target i686-pc-windows-msvc19 -S -emit-llvm %s -o - | FileCheck %s --check-prefix=TARGET-19
// RUN: %clang -target i686-pc-windows-msvc -S -emit-llvm %s -o - -fms-compatibility-version=19 | FileCheck %s --check-prefix=OVERRIDE-19
// RUN: %clang -target i686-pc-windows-msvc-elf -S -emit-llvm %s -o - | FileCheck %s --check-prefix=ELF-DEFAULT
+// RUN: %clang -target i686-pc-windows-msvc -S -emit-llvm %s -o - | FileCheck %s --check-prefix=DEFAULT
// TARGET-19: target triple = "i686-pc-windows-msvc19.0.0"
// OVERRIDE-19: target triple = "i686-pc-windows-msvc19.0.0"
// ELF-DEFAULT: target triple = "i686-pc-windows-msvc{{.*}}-elf"
+// DEFAULT: target triple = "i686-pc-windows-msvc{{[^-]+}}"
diff --git a/test/Driver/myriad-toolchain.c b/test/Driver/myriad-toolchain.c
index 3e580ac77e31..971e5d3e6961 100644
--- a/test/Driver/myriad-toolchain.c
+++ b/test/Driver/myriad-toolchain.c
@@ -1,15 +1,16 @@
// RUN: %clang -no-canonical-prefixes -### -target sparc-myriad-rtems-elf %s \
+// RUN: -ccc-install-dir %S/Inputs/basic_myriad_tree/bin \
// RUN: --gcc-toolchain=%S/Inputs/basic_myriad_tree 2>&1 | FileCheck %s -check-prefix=LINK_WITH_RTEMS
// LINK_WITH_RTEMS: Inputs{{.*}}crti.o
// LINK_WITH_RTEMS: Inputs{{.*}}crtbegin.o
-// LINK_WITH_RTEMS: "-L{{.*}}Inputs/basic_myriad_tree/lib/gcc/sparc-myriad-elf/4.8.2/../../..{{/|\\\\}}../sparc-myriad-elf/lib"
// LINK_WITH_RTEMS: "-L{{.*}}Inputs/basic_myriad_tree/lib/gcc/sparc-myriad-elf/4.8.2"
-// LINK_WITH_RTEMS: "--start-group" "-lc" "-lrtemscpu" "-lrtemsbsp" "--end-group" "-lgcc"
+// LINK_WITH_RTEMS: "-L{{.*}}Inputs/basic_myriad_tree/bin/../sparc-myriad-elf/lib"
+// LINK_WITH_RTEMS: "--start-group" "-lc" "-lgcc" "-lrtemscpu" "-lrtemsbsp" "--end-group"
// LINK_WITH_RTEMS: Inputs{{.*}}crtend.o
// LINK_WITH_RTEMS: Inputs{{.*}}crtn.o
// RUN: %clang -c -no-canonical-prefixes -### -target sparc-myriad-rtems-elf -x c++ %s \
-// RUN: --gcc-toolchain=%S/Inputs/basic_myriad_tree 2>&1 | FileCheck %s -check-prefix=COMPILE_CXX
+// RUN: -stdlib=libstdc++ --gcc-toolchain=%S/Inputs/basic_myriad_tree 2>&1 | FileCheck %s -check-prefix=COMPILE_CXX
// COMPILE_CXX: "-internal-isystem" "{{.*}}/Inputs/basic_myriad_tree/lib/gcc/sparc-myriad-elf/4.8.2/../../../../sparc-myriad-elf/include/c++/4.8.2"
// COMPILE_CXX: "-internal-isystem" "{{.*}}/Inputs/basic_myriad_tree/lib/gcc/sparc-myriad-elf/4.8.2/../../../../sparc-myriad-elf/include/c++/4.8.2/sparc-myriad-elf"
// COMPILE_CXX: "-internal-isystem" "{{.*}}/Inputs/basic_myriad_tree/lib/gcc/sparc-myriad-elf/4.8.2/../../../../sparc-myriad-elf/include/c++/4.8.2/backward"
@@ -50,8 +51,9 @@
// RUN: | FileCheck %s -check-prefix=INCLUDES
// INCLUDES: "-iquote" "quotepath" "-isystem" "syspath"
+// -fno-split-dwarf-inlining is consumed but not passed to moviCompile.
// RUN: %clang -target shave-myriad -c -### %s -g -fno-inline-functions \
-// RUN: -fno-inline-functions-called-once -Os -Wall -MF dep.d \
+// RUN: -fno-inline-functions-called-once -Os -Wall -MF dep.d -fno-split-dwarf-inlining \
// RUN: -ffunction-sections 2>&1 | FileCheck %s -check-prefix=PASSTHRU_OPTIONS
// PASSTHRU_OPTIONS: "-g" "-fno-inline-functions" "-fno-inline-functions-called-once"
// PASSTHRU_OPTIONS: "-Os" "-Wall" "-MF" "dep.d" "-ffunction-sections"
@@ -68,8 +70,11 @@
// RUN: | FileCheck %s -check-prefix=PREPROCESS
// PREPROCESS: "-E" "-DMYRIAD2" "-I" "foo"
-// RUN: %clang -target sparc-myriad -### --driver-mode=g++ %s 2>&1 | FileCheck %s --check-prefix=STDLIBCXX
-// STDLIBCXX: "-lstdc++" "-lc" "-lgcc"
+// RUN: %clang -stdlib=platform -target sparc-myriad -### --driver-mode=g++ %s 2>&1 | FileCheck %s --check-prefix=LIBSTDCXX
+// LIBSTDCXX: "-lstdc++" "-lc" "-lgcc"
+
+// RUN: %clang -stdlib=libc++ -### -target sparcel-myriad -S -x c++ %s 2>&1 | FileCheck %s -check-prefix=LIBCXX
+// LIBCXX: "-internal-isystem" "{{.*}}/../include/c++/v1"
// RUN: %clang -target sparc-myriad -### -nostdlib %s 2>&1 | FileCheck %s --check-prefix=NOSTDLIB
// NOSTDLIB-NOT: crtbegin.o
diff --git a/test/Driver/nostdlib.c b/test/Driver/nostdlib.c
index 6e7bc0eb93ec..7269312acba9 100644
--- a/test/Driver/nostdlib.c
+++ b/test/Driver/nostdlib.c
@@ -6,24 +6,24 @@
// Most of the toolchains would check for -nostartfiles and -nostdlib
// in a short-circuiting boolean expression, so if both of the preceding
// options were present, the second would warn about being unused.
-// RUN: %clang -### -nostartfiles -nostdlib -target i386-apple-darwin %s \
+// RUN: %clang -### -Wno-liblto -nostartfiles -nostdlib -target i386-apple-darwin %s \
// RUN: 2>&1 | FileCheck %s -check-prefix=ARGSCLAIMED
// ARGSCLAIMED-NOT: warning:
// In the presence of -nostdlib, the standard libraries should not be
// passed down to link line
-// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN: %clang -no-canonical-prefixes %s -### -Wno-liblto -o %t.o 2>&1 \
// RUN: -target i686-pc-linux-gnu -nostdlib --rtlib=compiler-rt \
// RUN: -resource-dir=%S/Inputs/resource_dir -lclang_rt.builtins-i686 \
// RUN: | FileCheck --check-prefix=CHECK-LINUX-NOSTDLIB %s
//
-// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN: %clang -no-canonical-prefixes %s -### -Wno-liblto -o %t.o 2>&1 \
// RUN: -target i686-pc-linux-gnu --rtlib=compiler-rt -nostdlib \
// RUN: -resource-dir=%S/Inputs/resource_dir -lclang_rt.builtins-i686 \
// RUN: | FileCheck --check-prefix=CHECK-LINUX-NOSTDLIB %s
//
-// RUN: %clang -target x86_64-pc-windows-msvc -nostdlib --rtlib=compiler-rt -### %s 2>&1 | FileCheck %s -check-prefix CHECK-MSVC-NOSTDLIB
-// RUN: %clang -target x86_64-pc-windows-msvc --rtlib=compiler-rt -nostdlib -### %s 2>&1 | FileCheck %s -check-prefix CHECK-MSVC-NOSTDLIB
+// RUN: %clang -target x86_64-pc-windows-msvc -nostdlib --rtlib=compiler-rt -### -Wno-liblto %s 2>&1 | FileCheck %s -check-prefix CHECK-MSVC-NOSTDLIB
+// RUN: %clang -target x86_64-pc-windows-msvc --rtlib=compiler-rt -nostdlib -### -Wno-liblto %s 2>&1 | FileCheck %s -check-prefix CHECK-MSVC-NOSTDLIB
//
// CHECK-LINUX-NOSTDLIB: warning: argument unused during compilation: '--rtlib=compiler-rt'
// CHECK-LINUX-NOSTDLIB: "{{(.*[^.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
diff --git a/test/Driver/offloading-interoperability.c b/test/Driver/offloading-interoperability.c
new file mode 100644
index 000000000000..ab5132297aab
--- /dev/null
+++ b/test/Driver/offloading-interoperability.c
@@ -0,0 +1,17 @@
+// REQUIRES: clang-driver
+// REQUIRES: powerpc-registered-target
+// REQUIRES: nvptx-registered-target
+
+//
+// Verify that CUDA device commands do not get OpenMP flags.
+//
+// RUN: %clang -no-canonical-prefixes -### -x cuda -target powerpc64le-linux-gnu -std=c++11 --cuda-gpu-arch=sm_35 -fopenmp=libomp %s 2>&1 \
+// RUN: | FileCheck %s --check-prefix NO-OPENMP-FLAGS-FOR-CUDA-DEVICE
+//
+// NO-OPENMP-FLAGS-FOR-CUDA-DEVICE: clang{{.*}}" "-cc1" "-triple" "nvptx64-nvidia-cuda"
+// NO-OPENMP-FLAGS-FOR-CUDA-DEVICE-NOT: -fopenmp
+// NO-OPENMP-FLAGS-FOR-CUDA-DEVICE-NEXT: ptxas" "-m64"
+// NO-OPENMP-FLAGS-FOR-CUDA-DEVICE-NEXT: fatbinary" "--cuda" "-64"
+// NO-OPENMP-FLAGS-FOR-CUDA-DEVICE-NEXT: clang{{.*}}" "-cc1" "-triple" "powerpc64le--linux-gnu"
+// NO-OPENMP-FLAGS-FOR-CUDA-DEVICE: -fopenmp
+// NO-OPENMP-FLAGS-FOR-CUDA-DEVICE-NEXT: {{ld(.exe)?"}} {{.*}}"-m" "elf64lppc"
diff --git a/test/Driver/opencl.cl b/test/Driver/opencl.cl
index b2656c2c501d..d68d424b6e36 100644
--- a/test/Driver/opencl.cl
+++ b/test/Driver/opencl.cl
@@ -12,6 +12,7 @@
// RUN: %clang -S -### -cl-mad-enable %s 2>&1 | FileCheck --check-prefix=CHECK-MAD-ENABLE %s
// 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: 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
@@ -29,6 +30,7 @@
// CHECK-MAD-ENABLE: "-cc1" {{.*}} "-cl-mad-enable"
// 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-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.c b/test/Driver/openmp-offload.c
new file mode 100644
index 000000000000..097dc7d17faa
--- /dev/null
+++ b/test/Driver/openmp-offload.c
@@ -0,0 +1,589 @@
+///
+/// Perform several driver tests for OpenMP offloading
+///
+
+// REQUIRES: clang-driver
+// REQUIRES: x86-registered-target
+// REQUIRES: powerpc-registered-target
+// REQUIRES: nvptx-registered-target
+
+/// ###########################################################################
+
+/// Check whether an invalid OpenMP target is specified:
+// RUN: %clang -### -fopenmp=libomp -fopenmp-targets=aaa-bbb-ccc-ddd %s 2>&1 \
+// RUN: | FileCheck -check-prefix=CHK-INVALID-TARGET %s
+// CHK-INVALID-TARGET: error: OpenMP target is invalid: 'aaa-bbb-ccc-ddd'
+
+/// ###########################################################################
+
+/// Check warning for empty -fopenmp-targets
+// RUN: %clang -### -fopenmp=libomp -fopenmp-targets= %s 2>&1 \
+// RUN: | FileCheck -check-prefix=CHK-EMPTY-OMPTARGETS %s
+// CHK-EMPTY-OMPTARGETS: warning: joined argument expects additional value: '-fopenmp-targets='
+
+/// ###########################################################################
+
+/// Check error for no -fopenmp option
+// RUN: %clang -### -fopenmp-targets=powerpc64le-ibm-linux-gnu %s 2>&1 \
+// RUN: | FileCheck -check-prefix=CHK-NO-FOPENMP %s
+// RUN: %clang -### -fopenmp=libgomp -fopenmp-targets=powerpc64le-ibm-linux-gnu %s 2>&1 \
+// RUN: | FileCheck -check-prefix=CHK-NO-FOPENMP %s
+// CHK-NO-FOPENMP: error: The option -fopenmp-targets must be used in conjunction with a -fopenmp option compatible with offloading, please use -fopenmp=libomp or -fopenmp=libiomp5.
+
+/// ###########################################################################
+
+/// Check warning for duplicate offloading targets.
+// RUN: %clang -### -ccc-print-phases -fopenmp=libomp -fopenmp-targets=powerpc64le-ibm-linux-gnu,powerpc64le-ibm-linux-gnu %s 2>&1 \
+// RUN: | FileCheck -check-prefix=CHK-DUPLICATES %s
+// CHK-DUPLICATES: warning: The OpenMP offloading target 'powerpc64le-ibm-linux-gnu' is similar to target 'powerpc64le-ibm-linux-gnu' already specified - will be ignored.
+
+/// ###########################################################################
+
+/// Check the phases graph when using a single target, different from the host.
+/// We should have an offload action joining the host compile and device
+/// preprocessor and another one joining the device linking outputs to the host
+/// action.
+// RUN: %clang -ccc-print-phases -fopenmp=libomp -target powerpc64le-ibm-linux-gnu -fopenmp-targets=x86_64-pc-linux-gnu %s 2>&1 \
+// RUN: | FileCheck -check-prefix=CHK-PHASES %s
+// CHK-PHASES: 0: input, "[[INPUT:.+\.c]]", c, (host-openmp)
+// CHK-PHASES: 1: preprocessor, {0}, cpp-output, (host-openmp)
+// CHK-PHASES: 2: compiler, {1}, ir, (host-openmp)
+// CHK-PHASES: 3: backend, {2}, assembler, (host-openmp)
+// CHK-PHASES: 4: assembler, {3}, object, (host-openmp)
+// CHK-PHASES: 5: linker, {4}, image, (host-openmp)
+// CHK-PHASES: 6: input, "[[INPUT]]", c, (device-openmp)
+// CHK-PHASES: 7: preprocessor, {6}, cpp-output, (device-openmp)
+// CHK-PHASES: 8: compiler, {7}, ir, (device-openmp)
+// CHK-PHASES: 9: offload, "host-openmp (powerpc64le-ibm-linux-gnu)" {2}, "device-openmp (x86_64-pc-linux-gnu)" {8}, ir
+// CHK-PHASES: 10: backend, {9}, assembler, (device-openmp)
+// CHK-PHASES: 11: assembler, {10}, object, (device-openmp)
+// CHK-PHASES: 12: linker, {11}, image, (device-openmp)
+// CHK-PHASES: 13: offload, "host-openmp (powerpc64le-ibm-linux-gnu)" {5}, "device-openmp (x86_64-pc-linux-gnu)" {12}, image
+
+/// ###########################################################################
+
+/// Check the phases when using multiple targets. Here we also add a library to
+/// make sure it is treated as input by the device.
+// RUN: %clang -ccc-print-phases -lsomelib -fopenmp=libomp -target powerpc64-ibm-linux-gnu -fopenmp-targets=x86_64-pc-linux-gnu,powerpc64-ibm-linux-gnu %s 2>&1 \
+// RUN: | FileCheck -check-prefix=CHK-PHASES-LIB %s
+// CHK-PHASES-LIB: 0: input, "somelib", object, (host-openmp)
+// CHK-PHASES-LIB: 1: input, "[[INPUT:.+\.c]]", c, (host-openmp)
+// CHK-PHASES-LIB: 2: preprocessor, {1}, cpp-output, (host-openmp)
+// CHK-PHASES-LIB: 3: compiler, {2}, ir, (host-openmp)
+// CHK-PHASES-LIB: 4: backend, {3}, assembler, (host-openmp)
+// CHK-PHASES-LIB: 5: assembler, {4}, object, (host-openmp)
+// CHK-PHASES-LIB: 6: linker, {0, 5}, image, (host-openmp)
+// CHK-PHASES-LIB: 7: input, "somelib", object, (device-openmp)
+// CHK-PHASES-LIB: 8: input, "[[INPUT]]", c, (device-openmp)
+// CHK-PHASES-LIB: 9: preprocessor, {8}, cpp-output, (device-openmp)
+// CHK-PHASES-LIB: 10: compiler, {9}, ir, (device-openmp)
+// CHK-PHASES-LIB: 11: offload, "host-openmp (powerpc64-ibm-linux-gnu)" {3}, "device-openmp (x86_64-pc-linux-gnu)" {10}, ir
+// CHK-PHASES-LIB: 12: backend, {11}, assembler, (device-openmp)
+// CHK-PHASES-LIB: 13: assembler, {12}, object, (device-openmp)
+// CHK-PHASES-LIB: 14: linker, {7, 13}, image, (device-openmp)
+// CHK-PHASES-LIB: 15: input, "somelib", object, (device-openmp)
+// CHK-PHASES-LIB: 16: input, "[[INPUT]]", c, (device-openmp)
+// CHK-PHASES-LIB: 17: preprocessor, {16}, cpp-output, (device-openmp)
+// CHK-PHASES-LIB: 18: compiler, {17}, ir, (device-openmp)
+// CHK-PHASES-LIB: 19: offload, "host-openmp (powerpc64-ibm-linux-gnu)" {3}, "device-openmp (powerpc64-ibm-linux-gnu)" {18}, ir
+// CHK-PHASES-LIB: 20: backend, {19}, assembler, (device-openmp)
+// CHK-PHASES-LIB: 21: assembler, {20}, object, (device-openmp)
+// CHK-PHASES-LIB: 22: linker, {15, 21}, image, (device-openmp)
+// CHK-PHASES-LIB: 23: offload, "host-openmp (powerpc64-ibm-linux-gnu)" {6}, "device-openmp (x86_64-pc-linux-gnu)" {14}, "device-openmp (powerpc64-ibm-linux-gnu)" {22}, image
+
+
+/// ###########################################################################
+
+/// Check the phases when using multiple targets and multiple source files
+// RUN: echo " " > %t.c
+// RUN: %clang -ccc-print-phases -lsomelib -fopenmp=libomp -target powerpc64-ibm-linux-gnu -fopenmp-targets=x86_64-pc-linux-gnu,powerpc64-ibm-linux-gnu %s %t.c 2>&1 \
+// RUN: | FileCheck -check-prefix=CHK-PHASES-FILES %s
+// CHK-PHASES-FILES: 0: input, "somelib", object, (host-openmp)
+// CHK-PHASES-FILES: 1: input, "[[INPUT1:.+\.c]]", c, (host-openmp)
+// CHK-PHASES-FILES: 2: preprocessor, {1}, cpp-output, (host-openmp)
+// CHK-PHASES-FILES: 3: compiler, {2}, ir, (host-openmp)
+// CHK-PHASES-FILES: 4: backend, {3}, assembler, (host-openmp)
+// CHK-PHASES-FILES: 5: assembler, {4}, object, (host-openmp)
+// CHK-PHASES-FILES: 6: input, "[[INPUT2:.+\.c]]", c, (host-openmp)
+// CHK-PHASES-FILES: 7: preprocessor, {6}, cpp-output, (host-openmp)
+// CHK-PHASES-FILES: 8: compiler, {7}, ir, (host-openmp)
+// CHK-PHASES-FILES: 9: backend, {8}, assembler, (host-openmp)
+// CHK-PHASES-FILES: 10: assembler, {9}, object, (host-openmp)
+// CHK-PHASES-FILES: 11: linker, {0, 5, 10}, image, (host-openmp)
+// CHK-PHASES-FILES: 12: input, "somelib", object, (device-openmp)
+// CHK-PHASES-FILES: 13: input, "[[INPUT1]]", c, (device-openmp)
+// CHK-PHASES-FILES: 14: preprocessor, {13}, cpp-output, (device-openmp)
+// CHK-PHASES-FILES: 15: compiler, {14}, ir, (device-openmp)
+// CHK-PHASES-FILES: 16: offload, "host-openmp (powerpc64-ibm-linux-gnu)" {3}, "device-openmp (x86_64-pc-linux-gnu)" {15}, ir
+// CHK-PHASES-FILES: 17: backend, {16}, assembler, (device-openmp)
+// CHK-PHASES-FILES: 18: assembler, {17}, object, (device-openmp)
+// CHK-PHASES-FILES: 19: input, "[[INPUT2]]", c, (device-openmp)
+// CHK-PHASES-FILES: 20: preprocessor, {19}, cpp-output, (device-openmp)
+// CHK-PHASES-FILES: 21: compiler, {20}, ir, (device-openmp)
+// CHK-PHASES-FILES: 22: offload, "host-openmp (powerpc64-ibm-linux-gnu)" {8}, "device-openmp (x86_64-pc-linux-gnu)" {21}, ir
+// CHK-PHASES-FILES: 23: backend, {22}, assembler, (device-openmp)
+// CHK-PHASES-FILES: 24: assembler, {23}, object, (device-openmp)
+// CHK-PHASES-FILES: 25: linker, {12, 18, 24}, image, (device-openmp)
+// CHK-PHASES-FILES: 26: input, "somelib", object, (device-openmp)
+// CHK-PHASES-FILES: 27: input, "[[INPUT1]]", c, (device-openmp)
+// CHK-PHASES-FILES: 28: preprocessor, {27}, cpp-output, (device-openmp)
+// CHK-PHASES-FILES: 29: compiler, {28}, ir, (device-openmp)
+// CHK-PHASES-FILES: 30: offload, "host-openmp (powerpc64-ibm-linux-gnu)" {3}, "device-openmp (powerpc64-ibm-linux-gnu)" {29}, ir
+// CHK-PHASES-FILES: 31: backend, {30}, assembler, (device-openmp)
+// CHK-PHASES-FILES: 32: assembler, {31}, object, (device-openmp)
+// CHK-PHASES-FILES: 33: input, "[[INPUT2]]", c, (device-openmp)
+// CHK-PHASES-FILES: 34: preprocessor, {33}, cpp-output, (device-openmp)
+// CHK-PHASES-FILES: 35: compiler, {34}, ir, (device-openmp)
+// CHK-PHASES-FILES: 36: offload, "host-openmp (powerpc64-ibm-linux-gnu)" {8}, "device-openmp (powerpc64-ibm-linux-gnu)" {35}, ir
+// CHK-PHASES-FILES: 37: backend, {36}, assembler, (device-openmp)
+// CHK-PHASES-FILES: 38: assembler, {37}, object, (device-openmp)
+// CHK-PHASES-FILES: 39: linker, {26, 32, 38}, image, (device-openmp)
+// CHK-PHASES-FILES: 40: offload, "host-openmp (powerpc64-ibm-linux-gnu)" {11}, "device-openmp (x86_64-pc-linux-gnu)" {25}, "device-openmp (powerpc64-ibm-linux-gnu)" {39}, image
+
+/// ###########################################################################
+
+/// Check the phases graph when using a single GPU target, and check the OpenMP
+/// and CUDA phases are articulated correctly.
+// RUN: %clang -ccc-print-phases -fopenmp=libomp -target powerpc64le-ibm-linux-gnu -fopenmp-targets=nvptx64-nvidia-cuda -x cuda %s 2>&1 \
+// RUN: | FileCheck -check-prefix=CHK-PHASES-WITH-CUDA %s
+// CHK-PHASES-WITH-CUDA: 0: input, "[[INPUT:.+\.c]]", cuda, (host-cuda-openmp)
+// CHK-PHASES-WITH-CUDA: 1: preprocessor, {0}, cuda-cpp-output, (host-cuda-openmp)
+// CHK-PHASES-WITH-CUDA: 2: compiler, {1}, ir, (host-cuda-openmp)
+// CHK-PHASES-WITH-CUDA: 3: input, "[[INPUT]]", cuda, (device-cuda, sm_20)
+// CHK-PHASES-WITH-CUDA: 4: preprocessor, {3}, cuda-cpp-output, (device-cuda, sm_20)
+// CHK-PHASES-WITH-CUDA: 5: compiler, {4}, ir, (device-cuda, sm_20)
+// CHK-PHASES-WITH-CUDA: 6: backend, {5}, assembler, (device-cuda, sm_20)
+// CHK-PHASES-WITH-CUDA: 7: assembler, {6}, object, (device-cuda, sm_20)
+// CHK-PHASES-WITH-CUDA: 8: offload, "device-cuda (nvptx64-nvidia-cuda:sm_20)" {7}, object
+// CHK-PHASES-WITH-CUDA: 9: offload, "device-cuda (nvptx64-nvidia-cuda:sm_20)" {6}, assembler
+// CHK-PHASES-WITH-CUDA: 10: linker, {8, 9}, cuda-fatbin, (device-cuda)
+// CHK-PHASES-WITH-CUDA: 11: offload, "host-cuda-openmp (powerpc64le-ibm-linux-gnu)" {2}, "device-cuda (nvptx64-nvidia-cuda)" {10}, ir
+// CHK-PHASES-WITH-CUDA: 12: backend, {11}, assembler, (host-cuda-openmp)
+// CHK-PHASES-WITH-CUDA: 13: assembler, {12}, object, (host-cuda-openmp)
+// CHK-PHASES-WITH-CUDA: 14: linker, {13}, image, (host-cuda-openmp)
+// CHK-PHASES-WITH-CUDA: 15: input, "[[INPUT]]", cuda, (device-openmp)
+// CHK-PHASES-WITH-CUDA: 16: preprocessor, {15}, cuda-cpp-output, (device-openmp)
+// CHK-PHASES-WITH-CUDA: 17: compiler, {16}, ir, (device-openmp)
+// CHK-PHASES-WITH-CUDA: 18: offload, "host-cuda-openmp (powerpc64le-ibm-linux-gnu)" {2}, "device-openmp (nvptx64-nvidia-cuda)" {17}, ir
+// CHK-PHASES-WITH-CUDA: 19: backend, {18}, assembler, (device-openmp)
+// CHK-PHASES-WITH-CUDA: 20: assembler, {19}, object, (device-openmp)
+// CHK-PHASES-WITH-CUDA: 21: linker, {20}, image, (device-openmp)
+// CHK-PHASES-WITH-CUDA: 22: offload, "host-cuda-openmp (powerpc64le-ibm-linux-gnu)" {14}, "device-openmp (nvptx64-nvidia-cuda)" {21}, image
+
+/// ###########################################################################
+
+/// Check of the commands passed to each tool when using valid OpenMP targets.
+/// Here we also check that offloading does not break the use of integrated
+/// assembler. It does however preclude the merge of the host compile and
+/// backend phases. There are also two offloading specific options:
+/// -fopenmp-is-device: will tell the frontend that it will generate code for a
+/// target.
+/// -fopenmp-host-ir-file-path: specifies the host IR file that can be loaded by
+/// the target code generation to gather information about which declaration
+/// really need to be emitted.
+/// We use -fopenmp-dump-offload-linker-script to dump the linker script and
+/// check its contents.
+///
+// RUN: %clang -### -fopenmp=libomp -o %t.out -target powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %s -fopenmp-dump-offload-linker-script -no-canonical-prefixes 2>&1 \
+// RUN: | FileCheck -check-prefix=CHK-COMMANDS -check-prefix=CHK-LKS -check-prefix=CHK-LKS-REG %s
+// RUN: %clang -### -fopenmp=libomp -o %t.out -target powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %s -save-temps -fopenmp-dump-offload-linker-script -no-canonical-prefixes 2>&1 \
+// RUN: | FileCheck -check-prefix=CHK-COMMANDS-ST -check-prefix=CHK-LKS -check-prefix=CHK-LKS-ST %s
+
+// Make sure we are not dumping the script unless the user requested it.
+// RUN: %clang -### -fopenmp=libomp -o %t.out -target powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %s -no-canonical-prefixes 2>&1 \
+// RUN: | FileCheck -check-prefix=CHK-LKS-NODUMP %s
+// RUN: %clang -### -fopenmp=libomp -o %t.out -target powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %s -save-temps -no-canonical-prefixes 2>&1 \
+// RUN: | FileCheck -check-prefix=CHK-LKS-NODUMP %s
+
+//
+// Check the linker script contains what we expect.
+//
+// CHK-LKS: /*
+// CHK-LKS: OpenMP Offload Linker Script
+// CHK-LKS: *** Automatically generated by Clang ***
+// CHK-LKS-NODUMP-NOT: OpenMP Offload Linker Script.
+// CHK-LKS: */
+// CHK-LKS: TARGET(binary)
+// CHK-LKS-REG: INPUT([[T1BIN:.+\.out]])
+// CHK-LKS-REG: INPUT([[T2BIN:.+\.out]])
+// CHK-LKS-ST: INPUT([[T1BIN:.+\.out-openmp-powerpc64le-ibm-linux-gnu]])
+// CHK-LKS-ST: INPUT([[T2BIN:.+\.out-openmp-x86_64-pc-linux-gnu]])
+// CHK-LKS: SECTIONS
+// CHK-LKS: {
+// CHK-LKS: .omp_offloading :
+// CHK-LKS: ALIGN(0x10)
+// CHK-LKS: {
+// CHK-LKS: . = ALIGN(0x10);
+// CHK-LKS: PROVIDE_HIDDEN(.omp_offloading.img_start.powerpc64le-ibm-linux-gnu = .);
+// CHK-LKS: [[T1BIN]]
+// CHK-LKS: PROVIDE_HIDDEN(.omp_offloading.img_end.powerpc64le-ibm-linux-gnu = .);
+// CHK-LKS: . = ALIGN(0x10);
+// CHK-LKS: PROVIDE_HIDDEN(.omp_offloading.img_start.x86_64-pc-linux-gnu = .);
+// CHK-LKS: [[T2BIN]]
+// CHK-LKS: PROVIDE_HIDDEN(.omp_offloading.img_end.x86_64-pc-linux-gnu = .);
+// CHK-LKS: }
+// CHK-LKS: .omp_offloading.entries :
+// CHK-LKS: ALIGN(0x10)
+// CHK-LKS: SUBALIGN(0x01)
+// CHK-LKS: {
+// CHK-LKS: PROVIDE_HIDDEN(.omp_offloading.entries_begin = .);
+// CHK-LKS: *(.omp_offloading.entries)
+// CHK-LKS: PROVIDE_HIDDEN(.omp_offloading.entries_end = .);
+// CHK-LKS: }
+// CHK-LKS: }
+// CHK-LKS: INSERT BEFORE .data
+
+//
+// Generate host BC file.
+//
+// CHK-COMMANDS: clang{{.*}}" "-cc1" "-triple" "powerpc64le--linux" "-emit-llvm-bc" {{.*}}"-o" "
+// CHK-COMMANDS-SAME: [[HOSTBC:[^\\/]+\.bc]]" "-x" "c" "
+// CHK-COMMANDS-SAME: [[INPUT:[^\\/]+\.c]]" "-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu"
+// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le--linux" "-E" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-COMMANDS-ST-SAME: [[HOSTPP:[^\\/]+\.i]]" "-x" "c" "
+// CHK-COMMANDS-ST-SAME: [[INPUT:[^\\/]+\.c]]"
+// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le--linux" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-COMMANDS-ST-SAME: [[HOSTBC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[HOSTPP]]" "-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu"
+
+//
+// Compile for the powerpc device.
+//
+// CHK-COMMANDS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-emit-obj" {{.*}}"-pic-level" "2" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-COMMANDS-SAME: [[T1OBJ:[^\\/]+\.o]]" "-x" "c" "{{.*}}[[INPUT]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]"
+// CHK-COMMANDS: ld{{(\.exe)?}}" {{.*}}"-o" "
+// CHK-COMMANDS-SAME: [[T1BIN:[^\\/]+\.out]]" {{.*}}"{{.*}}[[T1OBJ]]"
+// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-E" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-COMMANDS-ST-SAME: [[T1PP:[^\\/]+\.i]]" "-x" "c" "{{.*}}[[INPUT]]"
+// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-emit-llvm-bc" {{.*}}"-pic-level" "2" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-COMMANDS-ST-SAME: [[T1BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T1PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]"
+// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-COMMANDS-ST-SAME: [[T1ASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[T1BC]]"
+// CHK-COMMANDS-ST: clang{{.*}}" "-cc1as" "-triple" "powerpc64le-ibm-linux-gnu" "-filetype" "obj" {{.*}}"-o" "
+// CHK-COMMANDS-ST-SAME: [[T1OBJ:[^\\/]+\.o]]" "{{.*}}[[T1ASM]]"
+// CHK-COMMANDS-ST: ld{{(\.exe)?}}" {{.*}}"-shared" {{.*}}"-o" "
+// CHK-COMMANDS-ST-SAME: [[T1BIN:[^\\/]+\.out-openmp-powerpc64le-ibm-linux-gnu]]" {{.*}}"{{.*}}[[T1OBJ]]"
+//
+// Compile for the x86 device.
+//
+// CHK-COMMANDS: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-emit-obj" {{.*}}"-pic-level" "2" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-COMMANDS-SAME: [[T2OBJ:[^\\/]+\.o]]" "-x" "c" "{{.*}}[[INPUT]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]"
+// CHK-COMMANDS: ld{{(\.exe)?}}" {{.*}}"-o" "
+// CHK-COMMANDS-SAME: [[T2BIN:[^\\/]+\.out]]" {{.*}}"{{.*}}[[T2OBJ]]"
+// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-E" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-COMMANDS-ST-SAME: [[T2PP:[^\\/]+\.i]]" "-x" "c" "{{.*}}[[INPUT]]"
+// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-emit-llvm-bc" {{.*}}"-pic-level" "2" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-COMMANDS-ST-SAME: [[T2BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T2PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]"
+// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-COMMANDS-ST-SAME: [[T2ASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[T2BC]]"
+// CHK-COMMANDS-ST: clang{{.*}}" "-cc1as" "-triple" "x86_64-pc-linux-gnu" "-filetype" "obj" {{.*}}"-o" "
+// CHK-COMMANDS-ST-SAME: [[T2OBJ:[^\\/]+\.o]]" "{{.*}}[[T2ASM]]"
+// CHK-COMMANDS-ST: ld{{(\.exe)?}}" {{.*}}"-shared" {{.*}}"-o" "
+// CHK-COMMANDS-ST-SAME: [[T2BIN:[^\\/]+\.out-openmp-x86_64-pc-linux-gnu]]" {{.*}}"{{.*}}[[T2OBJ]]"
+
+//
+// Generate host object from the BC file and link using the linker script.
+//
+// CHK-COMMANDS: clang{{.*}}" "-cc1" "-triple" "powerpc64le--linux" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-COMMANDS-SAME: [[HOSTOBJ:[^\\/]+\.o]]" "-x" "ir" "{{.*}}[[HOSTBC]]"
+// CHK-COMMANDS: ld{{(\.exe)?}}" {{.*}}"-o" "
+// CHK-COMMANDS-SAME: [[HOSTBIN:[^\\/]+\.out]]" {{.*}}"-lomptarget" {{.*}}"-T" "
+// CHK-COMMANDS-SAME: [[HOSTLK:[^\\/]+\.lk]]"
+// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le--linux" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-COMMANDS-ST-SAME: [[HOSTASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[HOSTBC]]"
+// CHK-COMMANDS-ST: clang{{.*}}" "-cc1as" "-triple" "powerpc64le--linux" "-filetype" "obj" {{.*}}"-o" "
+// CHK-COMMANDS-ST-SAME: [[HOSTOBJ:[^\\/]+\.o]]" "{{.*}}[[HOSTASM]]"
+// CHK-COMMANDS-ST: ld{{(\.exe)?}}" {{.*}}"-o" "
+// CHK-COMMANDS-ST-SAME: [[HOSTBIN:[^\\/]+\.out]]" {{.*}}"-lomptarget" {{.*}}"-T" "
+// CHK-COMMANDS-ST-SAME: [[HOSTLK:[^\\/]+\.lk]]"
+
+
+/// ###########################################################################
+
+/// Check separate compilation with offloading - bundling actions
+// RUN: %clang -### -ccc-print-phases -fopenmp=libomp -c -o %t.o -lsomelib -target powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %s -no-canonical-prefixes 2>&1 \
+// RUN: | FileCheck -check-prefix=CHK-BUACTIONS %s
+
+// CHK-BUACTIONS: 0: input, "[[INPUT:.+\.c]]", c, (host-openmp)
+// CHK-BUACTIONS: 1: preprocessor, {0}, cpp-output, (host-openmp)
+// CHK-BUACTIONS: 2: compiler, {1}, ir, (host-openmp)
+// CHK-BUACTIONS: 3: input, "[[INPUT]]", c, (device-openmp)
+// CHK-BUACTIONS: 4: preprocessor, {3}, cpp-output, (device-openmp)
+// CHK-BUACTIONS: 5: compiler, {4}, ir, (device-openmp)
+// CHK-BUACTIONS: 6: offload, "host-openmp (powerpc64le--linux)" {2}, "device-openmp (powerpc64le-ibm-linux-gnu)" {5}, ir
+// CHK-BUACTIONS: 7: backend, {6}, assembler, (device-openmp)
+// CHK-BUACTIONS: 8: assembler, {7}, object, (device-openmp)
+// CHK-BUACTIONS: 9: offload, "device-openmp (powerpc64le-ibm-linux-gnu)" {8}, object
+// CHK-BUACTIONS: 10: input, "[[INPUT]]", c, (device-openmp)
+// CHK-BUACTIONS: 11: preprocessor, {10}, cpp-output, (device-openmp)
+// CHK-BUACTIONS: 12: compiler, {11}, ir, (device-openmp)
+// CHK-BUACTIONS: 13: offload, "host-openmp (powerpc64le--linux)" {2}, "device-openmp (x86_64-pc-linux-gnu)" {12}, ir
+// CHK-BUACTIONS: 14: backend, {13}, assembler, (device-openmp)
+// CHK-BUACTIONS: 15: assembler, {14}, object, (device-openmp)
+// CHK-BUACTIONS: 16: offload, "device-openmp (x86_64-pc-linux-gnu)" {15}, object
+// CHK-BUACTIONS: 17: backend, {2}, assembler, (host-openmp)
+// CHK-BUACTIONS: 18: assembler, {17}, object, (host-openmp)
+// CHK-BUACTIONS: 19: clang-offload-bundler, {9, 16, 18}, object, (host-openmp)
+
+/// ###########################################################################
+
+/// Check separate compilation with offloading - unbundling actions
+// RUN: touch %t.i
+// RUN: %clang -### -ccc-print-phases -fopenmp=libomp -o %t.out -lsomelib -target powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %t.i -no-canonical-prefixes 2>&1 \
+// RUN: | FileCheck -check-prefix=CHK-UBACTIONS %s
+
+// CHK-UBACTIONS: 0: input, "somelib", object, (host-openmp)
+// CHK-UBACTIONS: 1: input, "[[INPUT:.+\.i]]", cpp-output, (host-openmp)
+// CHK-UBACTIONS: 2: clang-offload-unbundler, {1}, cpp-output, (host-openmp)
+// CHK-UBACTIONS: 3: compiler, {2}, ir, (host-openmp)
+// CHK-UBACTIONS: 4: backend, {3}, assembler, (host-openmp)
+// CHK-UBACTIONS: 5: assembler, {4}, object, (host-openmp)
+// CHK-UBACTIONS: 6: linker, {0, 5}, image, (host-openmp)
+// CHK-UBACTIONS: 7: input, "somelib", object, (device-openmp)
+// CHK-UBACTIONS: 8: compiler, {2}, ir, (device-openmp)
+// CHK-UBACTIONS: 9: offload, "host-openmp (powerpc64le--linux)" {3}, "device-openmp (powerpc64le-ibm-linux-gnu)" {8}, ir
+// CHK-UBACTIONS: 10: backend, {9}, assembler, (device-openmp)
+// CHK-UBACTIONS: 11: assembler, {10}, object, (device-openmp)
+// CHK-UBACTIONS: 12: linker, {7, 11}, image, (device-openmp)
+// CHK-UBACTIONS: 13: input, "somelib", object, (device-openmp)
+// CHK-UBACTIONS: 14: compiler, {2}, ir, (device-openmp)
+// CHK-UBACTIONS: 15: offload, "host-openmp (powerpc64le--linux)" {3}, "device-openmp (x86_64-pc-linux-gnu)" {14}, ir
+// CHK-UBACTIONS: 16: backend, {15}, assembler, (device-openmp)
+// CHK-UBACTIONS: 17: assembler, {16}, object, (device-openmp)
+// CHK-UBACTIONS: 18: linker, {13, 17}, image, (device-openmp)
+// CHK-UBACTIONS: 19: offload, "host-openmp (powerpc64le--linux)" {6}, "device-openmp (powerpc64le-ibm-linux-gnu)" {12}, "device-openmp (x86_64-pc-linux-gnu)" {18}, image
+
+/// ###########################################################################
+
+/// Check separate compilation with offloading - unbundling/bundling actions
+// RUN: touch %t.i
+// RUN: %clang -### -ccc-print-phases -fopenmp=libomp -c -o %t.o -lsomelib -target powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %t.i -no-canonical-prefixes 2>&1 \
+// RUN: | FileCheck -check-prefix=CHK-UBUACTIONS %s
+
+// CHK-UBUACTIONS: 0: input, "[[INPUT:.+\.i]]", cpp-output, (host-openmp)
+// CHK-UBUACTIONS: 1: clang-offload-unbundler, {0}, cpp-output, (host-openmp)
+// CHK-UBUACTIONS: 2: compiler, {1}, ir, (host-openmp)
+// CHK-UBUACTIONS: 3: compiler, {1}, ir, (device-openmp)
+// CHK-UBUACTIONS: 4: offload, "host-openmp (powerpc64le--linux)" {2}, "device-openmp (powerpc64le-ibm-linux-gnu)" {3}, ir
+// CHK-UBUACTIONS: 5: backend, {4}, assembler, (device-openmp)
+// CHK-UBUACTIONS: 6: assembler, {5}, object, (device-openmp)
+// CHK-UBUACTIONS: 7: offload, "device-openmp (powerpc64le-ibm-linux-gnu)" {6}, object
+// CHK-UBUACTIONS: 8: compiler, {1}, ir, (device-openmp)
+// CHK-UBUACTIONS: 9: offload, "host-openmp (powerpc64le--linux)" {2}, "device-openmp (x86_64-pc-linux-gnu)" {8}, ir
+// CHK-UBUACTIONS: 10: backend, {9}, assembler, (device-openmp)
+// CHK-UBUACTIONS: 11: assembler, {10}, object, (device-openmp)
+// CHK-UBUACTIONS: 12: offload, "device-openmp (x86_64-pc-linux-gnu)" {11}, object
+// CHK-UBUACTIONS: 13: backend, {2}, assembler, (host-openmp)
+// CHK-UBUACTIONS: 14: assembler, {13}, object, (host-openmp)
+// CHK-UBUACTIONS: 15: clang-offload-bundler, {7, 12, 14}, object, (host-openmp)
+
+/// ###########################################################################
+
+/// Check separate compilation with offloading - bundling jobs construct
+// RUN: %clang -### -fopenmp=libomp -c -o %t.o -lsomelib -target powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %s -no-canonical-prefixes 2>&1 \
+// RUN: | FileCheck -check-prefix=CHK-BUJOBS %s
+// RUN: %clang -### -fopenmp=libomp -c -o %t.o -lsomelib -target powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %s -save-temps -no-canonical-prefixes 2>&1 \
+// RUN: | FileCheck -check-prefix=CHK-BUJOBS-ST %s
+
+// Create host BC.
+// CHK-BUJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le--linux" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-BUJOBS-SAME: [[HOSTBC:[^\\/]+\.bc]]" "-x" "c" "
+// CHK-BUJOBS-SAME: [[INPUT:[^\\/]+\.c]]" "-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu"
+
+// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le--linux" "-E" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-BUJOBS-ST-SAME: [[HOSTPP:[^\\/]+\.i]]" "-x" "c" "
+// CHK-BUJOBS-ST-SAME: [[INPUT:[^\\/]+\.c]]"
+// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le--linux" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-BUJOBS-ST-SAME: [[HOSTBC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[HOSTPP]]" "-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu"
+
+// Create target 1 object.
+// CHK-BUJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-BUJOBS-SAME: [[T1OBJ:[^\\/]+\.o]]" "-x" "c" "{{.*}}[[INPUT]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]"
+// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-E" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-BUJOBS-ST-SAME: [[T1PP:[^\\/]+\.i]]" "-x" "c" "{{.*}}[[INPUT]]"
+// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-BUJOBS-ST-SAME: [[T1BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T1PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]"
+// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-BUJOBS-ST-SAME: [[T1ASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[T1BC]]"
+// CHK-BUJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "powerpc64le-ibm-linux-gnu" "-filetype" "obj" {{.*}}"-o" "
+// CHK-BUJOBS-ST-SAME: [[T1OBJ:[^\\/]+\.o]]" "{{.*}}[[T1ASM]]"
+
+// Create target 2 object.
+// CHK-BUJOBS: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-BUJOBS-SAME: [[T2OBJ:[^\\/]+\.o]]" "-x" "c" "{{.*}}[[INPUT]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]"
+// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-E" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-BUJOBS-ST-SAME: [[T2PP:[^\\/]+\.i]]" "-x" "c" "{{.*}}[[INPUT]]"
+// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-BUJOBS-ST-SAME: [[T2BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T2PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]"
+// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-BUJOBS-ST-SAME: [[T2ASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[T2BC]]"
+// CHK-BUJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "x86_64-pc-linux-gnu" "-filetype" "obj" {{.*}}"-o" "
+// CHK-BUJOBS-ST-SAME: [[T2OBJ:[^\\/]+\.o]]" "{{.*}}[[T2ASM]]"
+
+// Create host object and bundle.
+// CHK-BUJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le--linux" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-BUJOBS-SAME: [[HOSTOBJ:[^\\/]+\.o]]" "-x" "ir" "{{.*}}[[HOSTBC]]"
+// CHK-BUJOBS: clang-offload-bundler{{.*}}" "-type=o" "-targets=openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu,host-powerpc64le--linux" "-outputs=
+// CHK-BUJOBS-SAME: [[RES:[^\\/]+\.o]]" "-inputs={{.*}}[[T1OBJ]],{{.*}}[[T2OBJ]],{{.*}}[[HOSTOBJ]]"
+// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le--linux" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-BUJOBS-ST-SAME: [[HOSTASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[HOSTBC]]"
+// CHK-BUJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "powerpc64le--linux" "-filetype" "obj" {{.*}}"-o" "
+// CHK-BUJOBS-ST-SAME: [[HOSTOBJ:[^\\/]+\.o]]" "{{.*}}[[HOSTASM]]"
+// CHK-BUJOBS-ST: clang-offload-bundler{{.*}}" "-type=o" "-targets=openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu,host-powerpc64le--linux" "-outputs=
+// CHK-BUJOBS-ST-SAME: [[RES:[^\\/]+\.o]]" "-inputs={{.*}}[[T1OBJ]],{{.*}}[[T2OBJ]],{{.*}}[[HOSTOBJ]]"
+
+/// ###########################################################################
+
+/// Check separate compilation with offloading - unbundling jobs construct
+// RUN: touch %t.i
+// RUN: %clang -### -fopenmp=libomp -o %t.out -lsomelib -target powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %t.i -no-canonical-prefixes 2>&1 \
+// RUN: | FileCheck -check-prefix=CHK-UBJOBS %s
+// RUN: %clang -### -fopenmp=libomp -o %t.out -lsomelib -target powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %t.i -save-temps -no-canonical-prefixes 2>&1 \
+// RUN: | FileCheck -check-prefix=CHK-UBJOBS-ST %s
+// RUN: touch %t.o
+// RUN: %clang -### -fopenmp=libomp -o %t.out -lsomelib -target powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %t.o -no-canonical-prefixes 2>&1 \
+// RUN: | FileCheck -check-prefix=CHK-UBJOBS2 %s
+// RUN: %clang -### -fopenmp=libomp -o %t.out -lsomelib -target powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %t.o -save-temps -no-canonical-prefixes 2>&1 \
+// RUN: | FileCheck -check-prefix=CHK-UBJOBS2-ST %s
+
+// Unbundle and create host BC.
+// CHK-UBJOBS: clang-offload-bundler{{.*}}" "-type=i" "-targets=host-powerpc64le--linux,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu" "-inputs=
+// CHK-UBJOBS-SAME: [[INPUT:[^\\/]+\.i]]" "-outputs=
+// CHK-UBJOBS-SAME: [[HOSTPP:[^\\/]+\.i]],
+// CHK-UBJOBS-SAME: [[T1PP:[^\\/]+\.i]],
+// CHK-UBJOBS-SAME: [[T2PP:[^\\/]+\.i]]" "-unbundle"
+// CHK-UBJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le--linux" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBJOBS-SAME: [[HOSTBC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[HOSTPP]]" "-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu"
+// CHK-UBJOBS-ST: clang-offload-bundler{{.*}}" "-type=i" "-targets=host-powerpc64le--linux,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu" "-inputs=
+// CHK-UBJOBS-ST-SAME: [[INPUT:[^\\/]+\.i]]" "-outputs=
+// CHK-UBJOBS-ST-SAME: [[HOSTPP:[^\\/,]+\.i]],
+// CHK-UBJOBS-ST-SAME: [[T1PP:[^\\/,]+\.i]],
+// CHK-UBJOBS-ST-SAME: [[T2PP:[^\\/,]+\.i]]" "-unbundle"
+// CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le--linux" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBJOBS-ST-SAME: [[HOSTBC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[HOSTPP]]" "-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu"
+
+// Create target 1 object.
+// CHK-UBJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBJOBS-SAME: [[T1OBJ:[^\\/]+\.o]]" "-x" "cpp-output" "{{.*}}[[T1PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]"
+// CHK-UBJOBS: ld{{(\.exe)?}}" {{.*}}"-o" "
+// CHK-UBJOBS-SAME: [[T1BIN:[^\\/]+\.out]]" {{.*}}"{{.*}}[[T1OBJ]]"
+// CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBJOBS-ST-SAME: [[T1BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T1PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]"
+// CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBJOBS-ST-SAME: [[T1ASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[T1BC]]"
+// CHK-UBJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "powerpc64le-ibm-linux-gnu" "-filetype" "obj" {{.*}}"-o" "
+// CHK-UBJOBS-ST-SAME: [[T1OBJ:[^\\/]+\.o]]" "{{.*}}[[T1ASM]]"
+// CHK-UBJOBS-ST: ld{{(\.exe)?}}" {{.*}}"-o" "
+// CHK-UBJOBS-ST-SAME: [[T1BIN:[^\\/]+\.out-openmp-powerpc64le-ibm-linux-gnu]]" {{.*}}"{{.*}}[[T1OBJ]]"
+
+// Create target 2 object.
+// CHK-UBJOBS: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBJOBS-SAME: [[T2OBJ:[^\\/]+\.o]]" "-x" "cpp-output" "{{.*}}[[T2PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]"
+// CHK-UBJOBS: ld{{(\.exe)?}}" {{.*}}"-o" "
+// CHK-UBJOBS-SAME: [[T2BIN:[^\\/]+\.out]]" {{.*}}"{{.*}}[[T2OBJ]]"
+// CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBJOBS-ST-SAME: [[T2BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T2PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]"
+// CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBJOBS-ST-SAME: [[T2ASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[T2BC]]"
+// CHK-UBJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "x86_64-pc-linux-gnu" "-filetype" "obj" {{.*}}"-o" "
+// CHK-UBJOBS-ST-SAME: [[T2OBJ:[^\\/]+\.o]]" "{{.*}}[[T2ASM]]"
+// CHK-UBJOBS-ST: ld{{(\.exe)?}}" {{.*}}"-o" "
+// CHK-UBJOBS-ST-SAME: [[T2BIN:[^\\/]+\.out-openmp-x86_64-pc-linux-gnu]]" {{.*}}"{{.*}}[[T2OBJ]]"
+
+// Create binary.
+// CHK-UBJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le--linux" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBJOBS-SAME: [[HOSTOBJ:[^\\/]+\.o]]" "-x" "ir" "{{.*}}[[HOSTBC]]"
+// CHK-UBJOBS: ld{{(\.exe)?}}" {{.*}}"-o" "
+// CHK-UBJOBS-SAME: [[HOSTBIN:[^\\/]+\.out]]" {{.*}}"{{.*}}[[HOSTOBJ]]" {{.*}}"-T" "
+// CHK-UBJOBS-SAME: [[LKS:[^\\/]+\.lk]]"
+// CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le--linux" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBJOBS-ST-SAME: [[HOSTASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[HOSTBC]]"
+// CHK-UBJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "powerpc64le--linux" "-filetype" "obj" {{.*}}"-o" "
+// CHK-UBJOBS-ST-SAME: [[HOSTOBJ:[^\\/]+\.o]]" "{{.*}}[[HOSTASM]]"
+// CHK-UBJOBS-ST: ld{{(\.exe)?}}" {{.*}}"-o" "
+// CHK-UBJOBS-ST-SAME: [[HOSTBIN:[^\\/]+\.out]]" {{.*}}"{{.*}}[[HOSTOBJ]]" {{.*}}"-T" "
+// CHK-UBJOBS-ST-SAME: [[LKS:[^\\/]+\.lk]]"
+
+// Unbundle object file.
+// CHK-UBJOBS2: clang-offload-bundler{{.*}}" "-type=o" "-targets=host-powerpc64le--linux,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu" "-inputs=
+// CHK-UBJOBS2-SAME: [[INPUT:[^\\/]+\.o]]" "-outputs=
+// CHK-UBJOBS2-SAME: [[HOSTOBJ:[^\\/]+\.o]],
+// CHK-UBJOBS2-SAME: [[T1OBJ:[^\\/]+\.o]],
+// CHK-UBJOBS2-SAME: [[T2OBJ:[^\\/]+\.o]]" "-unbundle"
+// CHK-UBJOBS2: ld{{(\.exe)?}}" {{.*}}"-o" "
+// CHK-UBJOBS2-SAME: [[T1BIN:[^\\/]+\.out]]" {{.*}}"{{.*}}[[T1OBJ]]"
+// CHK-UBJOBS2: ld{{(\.exe)?}}" {{.*}}"-o" "
+// CHK-UBJOBS2-SAME: [[T2BIN:[^\\/]+\.out]]" {{.*}}"{{.*}}[[T2OBJ]]"
+// CHK-UBJOBS2: ld{{(\.exe)?}}" {{.*}}"-o" "
+// CHK-UBJOBS2-SAME: [[HOSTBIN:[^\\/]+\.out]]" {{.*}}"{{.*}}[[HOSTOBJ]]" {{.*}}"-T" "
+// CHK-UBJOBS2-SAME: [[LKS:[^\\/]+\.lk]]"
+// CHK-UBJOBS2-ST: clang-offload-bundler{{.*}}" "-type=o" "-targets=host-powerpc64le--linux,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu" "-inputs=
+// CHK-UBJOBS2-ST-SAME: [[INPUT:[^\\/]+\.o]]" "-outputs=
+// CHK-UBJOBS2-ST-SAME: [[HOSTOBJ:[^\\/,]+\.o]],
+// CHK-UBJOBS2-ST-SAME: [[T1OBJ:[^\\/,]+\.o]],
+// CHK-UBJOBS2-ST-SAME: [[T2OBJ:[^\\/,]+\.o]]" "-unbundle"
+// CHK-UBJOBS2-ST: ld{{(\.exe)?}}" {{.*}}"-o" "
+// CHK-UBJOBS2-ST-SAME: [[T1BIN:[^\\/]+\.out-openmp-powerpc64le-ibm-linux-gnu]]" {{.*}}"{{.*}}[[T1OBJ]]"
+// CHK-UBJOBS2-ST: ld{{(\.exe)?}}" {{.*}}"-o" "
+// CHK-UBJOBS2-ST-SAME: [[T2BIN:[^\\/]+\.out-openmp-x86_64-pc-linux-gnu]]" {{.*}}"{{.*}}[[T2OBJ]]"
+// CHK-UBJOBS2-ST: ld{{(\.exe)?}}" {{.*}}"-o" "
+// CHK-UBJOBS2-ST-SAME: [[HOSTBIN:[^\\/]+\.out]]" {{.*}}"{{.*}}[[HOSTOBJ]]" {{.*}}"-T" "
+// CHK-UBJOBS2-ST-SAME: [[LKS:[^\\/]+\.lk]]"
+
+/// ###########################################################################
+
+/// Check separate compilation with offloading - unbundling/bundling jobs
+/// construct
+// RUN: touch %t.i
+// RUN: %clang -### -fopenmp=libomp -c %t.o -lsomelib -target powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %t.i -no-canonical-prefixes 2>&1 \
+// RUN: | FileCheck -check-prefix=CHK-UBUJOBS %s
+// RUN: %clang -### -fopenmp=libomp -c %t.o -lsomelib -target powerpc64le-linux -fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu %t.i -save-temps -no-canonical-prefixes 2>&1 \
+// RUN: | FileCheck -check-prefix=CHK-UBUJOBS-ST %s
+
+// Unbundle and create host BC.
+// CHK-UBUJOBS: clang-offload-bundler{{.*}}" "-type=i" "-targets=host-powerpc64le--linux,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu" "-inputs=
+// CHK-UBUJOBS-SAME: [[INPUT:[^\\/]+\.i]]" "-outputs=
+// CHK-UBUJOBS-SAME: [[HOSTPP:[^\\/]+\.i]],
+// CHK-UBUJOBS-SAME: [[T1PP:[^\\/]+\.i]],
+// CHK-UBUJOBS-SAME: [[T2PP:[^\\/]+\.i]]" "-unbundle"
+// CHK-UBUJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le--linux" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBUJOBS-SAME: [[HOSTBC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[HOSTPP]]" "-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu"
+
+// CHK-UBUJOBS-ST: clang-offload-bundler{{.*}}" "-type=i" "-targets=host-powerpc64le--linux,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu" "-inputs=
+// CHK-UBUJOBS-ST-SAME: [[INPUT:[^\\/]+\.i]]" "-outputs=
+// CHK-UBUJOBS-ST-SAME: [[HOSTPP:[^\\/,]+\.i]],
+// CHK-UBUJOBS-ST-SAME: [[T1PP:[^\\/,]+\.i]],
+// CHK-UBUJOBS-ST-SAME: [[T2PP:[^\\/,]+\.i]]" "-unbundle"
+// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le--linux" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBUJOBS-ST-SAME: [[HOSTBC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[HOSTPP]]" "-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu"
+
+// Create target 1 object.
+// CHK-UBUJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBUJOBS-SAME: [[T1OBJ:[^\\/]+\.o]]" "-x" "cpp-output" "{{.*}}[[T1PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]"
+// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBUJOBS-ST-SAME: [[T1BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T1PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]"
+// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBUJOBS-ST-SAME: [[T1ASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[T1BC]]"
+// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "powerpc64le-ibm-linux-gnu" "-filetype" "obj" {{.*}}"-o" "
+// CHK-UBUJOBS-ST-SAME: [[T1OBJ:[^\\/]+\.o]]" "{{.*}}[[T1ASM]]"
+
+// Create target 2 object.
+// CHK-UBUJOBS: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBUJOBS-SAME: [[T2OBJ:[^\\/]+\.o]]" "-x" "cpp-output" "{{.*}}[[T2PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]"
+// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBUJOBS-ST-SAME: [[T2BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T2PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]"
+// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBUJOBS-ST-SAME: [[T2ASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[T2BC]]"
+// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "x86_64-pc-linux-gnu" "-filetype" "obj" {{.*}}"-o" "
+// CHK-UBUJOBS-ST-SAME: [[T2OBJ:[^\\/]+\.o]]" "{{.*}}[[T2ASM]]"
+
+// Create binary.
+// CHK-UBUJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le--linux" "-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBUJOBS-SAME: [[HOSTOBJ:[^\\/]+\.o]]" "-x" "ir" "{{.*}}[[HOSTBC]]"
+// CHK-UBUJOBS: clang-offload-bundler{{.*}}" "-type=o" "-targets=openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu,host-powerpc64le--linux" "-outputs=
+// CHK-UBUJOBS-SAME: [[RES:[^\\/]+\.o]]" "-inputs={{.*}}[[T1OBJ]],{{.*}}[[T2OBJ]],{{.*}}[[HOSTOBJ]]"
+// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le--linux" "-S" {{.*}}"-fopenmp" {{.*}}"-o" "
+// CHK-UBUJOBS-ST-SAME: [[HOSTASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[HOSTBC]]"
+// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "powerpc64le--linux" "-filetype" "obj" {{.*}}"-o" "
+// CHK-UBUJOBS-ST-SAME: [[HOSTOBJ:[^\\/]+\.o]]" "{{.*}}[[HOSTASM]]"
+// CHK-UBUJOBS-ST: clang-offload-bundler{{.*}}" "-type=o" "-targets=openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu,host-powerpc64le--linux" "-outputs=
+// CHK-UBUJOBS-ST-SAME: [[RES:[^\\/]+\.o]]" "-inputs={{.*}}[[T1OBJ]],{{.*}}[[T2OBJ]],{{.*}}[[HOSTOBJ]]"
diff --git a/test/Driver/opt-record.c b/test/Driver/opt-record.c
new file mode 100644
index 000000000000..6e684878d448
--- /dev/null
+++ b/test/Driver/opt-record.c
@@ -0,0 +1,18 @@
+// RUN: %clang -### -S -o FOO -fsave-optimization-record %s 2>&1 | FileCheck %s
+// RUN: %clang -### -c -o FOO -fsave-optimization-record %s 2>&1 | FileCheck %s
+// RUN: %clang -### -c -fsave-optimization-record %s 2>&1 | FileCheck %s -check-prefix=CHECK-NO-O
+// RUN: %clang -### -fsave-optimization-record %s 2>&1 | FileCheck %s -check-prefix=CHECK-NO-O
+// RUN: %clang -### -S -fsave-optimization-record -x cuda -nocudainc -nocudalib %s 2>&1 | FileCheck %s -check-prefix=CHECK-NO-O -check-prefix=CHECK-CUDA-DEV
+// RUN: %clang -### -fsave-optimization-record -x cuda -nocudainc -nocudalib %s 2>&1 | FileCheck %s -check-prefix=CHECK-NO-O -check-prefix=CHECK-CUDA-DEV
+// RUN: %clang -### -S -o FOO -fsave-optimization-record -foptimization-record-file=BAR.txt %s 2>&1 | FileCheck %s -check-prefix=CHECK-EQ
+
+// CHECK: "-cc1"
+// CHECK: "-opt-record-file" "FOO.opt.yaml"
+
+// CHECK-NO-O: "-cc1"
+// CHECK-NO-O-DAG: "-opt-record-file" "opt-record.opt.yaml"
+// CHECK-CUDA-DEV-DAG: "-opt-record-file" "opt-record-cuda-{{nvptx64|nvptx}}-nvidia-cuda-sm_20.opt.yaml"
+
+// CHECK-EQ: "-cc1"
+// CHECK-EQ: "-opt-record-file" "BAR.txt"
+
diff --git a/test/Driver/ppc-abi.c b/test/Driver/ppc-abi.c
index 958fd7741669..cebc90d3f99a 100644
--- a/test/Driver/ppc-abi.c
+++ b/test/Driver/ppc-abi.c
@@ -24,7 +24,10 @@
// RUN: %clang -target powerpc64le-unknown-linux-gnu %s -### -o %t.o 2>&1 \
// RUN: -mabi=altivec | FileCheck -check-prefix=CHECK-ELFv2 %s
+// CHECK-ELFv1: "-mrelocation-model" "pic" "-pic-level" "2"
// CHECK-ELFv1: "-target-abi" "elfv1"
+// CHECK-ELFv1-QPX: "-mrelocation-model" "pic" "-pic-level" "2"
// CHECK-ELFv1-QPX: "-target-abi" "elfv1-qpx"
+// CHECK-ELFv2: "-mrelocation-model" "pic" "-pic-level" "2"
// CHECK-ELFv2: "-target-abi" "elfv2"
diff --git a/test/Driver/ppc-dependent-options.cpp b/test/Driver/ppc-dependent-options.cpp
index b4dcaf6d9bf0..9fb812dc218f 100644
--- a/test/Driver/ppc-dependent-options.cpp
+++ b/test/Driver/ppc-dependent-options.cpp
@@ -42,6 +42,18 @@
// RUN: -mcpu=power6 -std=c++11 -mdirect-move %s 2>&1 | FileCheck %s \
// RUN: -check-prefix=CHECK-VSX
+// RUN: not %clang -target powerpc64le-unknown-unknown -fsyntax-only \
+// RUN: -mcpu=power9 -std=c++11 %s 2>&1 | FileCheck %s \
+// RUN: -check-prefix=CHECK-DEFAULT-P9
+
+// RUN: not %clang -target powerpc64le-unknown-unknown -fsyntax-only \
+// RUN: -mcpu=power9 -std=c++11 -mno-vsx -mpower9-vector %s 2>&1 | \
+// RUN: FileCheck %s -check-prefix=CHECK-NVSX-P9V
+
+// RUN: not %clang -target powerpc64le-unknown-unknown -fsyntax-only \
+// RUN: -mcpu=power9 -std=c++11 -mno-vsx -mfloat128 %s 2>&1 | \
+// RUN: FileCheck %s -check-prefix=CHECK-NVSX-FLT128
+
#ifdef __VSX__
static_assert(false, "VSX enabled");
#endif
@@ -50,13 +62,21 @@ static_assert(false, "VSX enabled");
static_assert(false, "P8V enabled");
#endif
-#if !defined(__VSX__) && !defined(__POWER8_VECTOR__)
+#ifdef __POWER9_VECTOR__
+static_assert(false, "P9V enabled");
+#endif
+
+#if !defined(__VSX__) && !defined(__POWER8_VECTOR__) && \
+ !defined(__POWER9_VECTOR__)
static_assert(false, "Neither enabled");
#endif
// CHECK-DEFAULT: VSX enabled
// CHECK-DEFAULT: P8V enabled
+// CHECK-DEFAULT-P9: P9V enabled
// CHECK-NVSX-P8V: error: option '-mpower8-vector' cannot be specified with '-mno-vsx'
+// CHECK-NVSX-P9V: error: option '-mpower9-vector' cannot be specified with '-mno-vsx'
+// CHECK-NVSX-FLT128: error: option '-mfloat128' cannot be specified with '-mno-vsx'
// CHECK-NVSX-DMV: error: option '-mdirect-move' cannot be specified with '-mno-vsx'
// CHECK-NVSX: Neither enabled
// CHECK-VSX: VSX enabled
diff --git a/test/Driver/ppc-features.cpp b/test/Driver/ppc-features.cpp
index 34c1ce5cc4db..e32a51a8337d 100644
--- a/test/Driver/ppc-features.cpp
+++ b/test/Driver/ppc-features.cpp
@@ -14,27 +14,27 @@
// check -msoft-float option for ppc32
// RUN: %clang -target powerpc-unknown-linux-gnu %s -msoft-float -### -o %t.o 2>&1 | FileCheck --check-prefix=CHECK-SOFTFLOAT %s
-// CHECK-SOFTFLOAT: "-target-feature" "+soft-float"
+// CHECK-SOFTFLOAT: "-target-feature" "-hard-float"
// check -mfloat-abi=soft option for ppc32
// RUN: %clang -target powerpc-unknown-linux-gnu %s -mfloat-abi=soft -### -o %t.o 2>&1 | FileCheck --check-prefix=CHECK-FLOATABISOFT %s
-// CHECK-FLOATABISOFT: "-target-feature" "+soft-float"
+// CHECK-FLOATABISOFT: "-target-feature" "-hard-float"
// check -mhard-float option for ppc32
// RUN: %clang -target powerpc-unknown-linux-gnu %s -mhard-float -### -o %t.o 2>&1 | FileCheck --check-prefix=CHECK-HARDFLOAT %s
-// CHECK-HARDFLOAT-NOT: "-target-feature" "+soft-float"
+// CHECK-HARDFLOAT-NOT: "-target-feature" "-hard-float"
// check -mfloat-abi=hard option for ppc32
// RUN: %clang -target powerpc-unknown-linux-gnu %s -mfloat-abi=hard -### -o %t.o 2>&1 | FileCheck --check-prefix=CHECK-FLOATABIHARD %s
-// CHECK-FLOATABIHARD-NOT: "-target-feature" "+soft-float"
+// CHECK-FLOATABIHARD-NOT: "-target-feature" "-hard-float"
// check combine -mhard-float -msoft-float option for ppc32
// RUN: %clang -target powerpc-unknown-linux-gnu %s -mhard-float -msoft-float -### -o %t.o 2>&1 | FileCheck --check-prefix=CHECK-HARDSOFT %s
-// CHECK-HARDSOFT: "-target-feature" "+soft-float"
+// CHECK-HARDSOFT: "-target-feature" "-hard-float"
// check combine -msoft-float -mhard-float option for ppc32
// 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" "+soft-float"
+// CHECK-SOFTHARD-NOT: "-target-feature" "-hard-float"
// 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
@@ -42,19 +42,19 @@
// check -msoft-float option for ppc64
// RUN: %clang -target powerpc64-unknown-linux-gnu %s -msoft-float -### -o %t.o 2>&1 | FileCheck --check-prefix=CHECK-SOFTFLOAT64 %s
-// CHECK-SOFTFLOAT64: error: invalid float ABI 'soft float is not supported for ppc64'
+// CHECK-SOFTFLOAT64: "-target-feature" "-hard-float"
// check -mfloat-abi=soft option for ppc64
// RUN: %clang -target powerpc64-unknown-linux-gnu %s -mfloat-abi=soft -### -o %t.o 2>&1 | FileCheck --check-prefix=CHECK-FLOATABISOFT64 %s
-// CHECK-FLOATABISOFT64: error: invalid float ABI 'soft float is not supported for ppc64'
+// CHECK-FLOATABISOFT64: "-target-feature" "-hard-float"
// check -msoft-float option for ppc64
// RUN: %clang -target powerpc64le-unknown-linux-gnu %s -msoft-float -### -o %t.o 2>&1 | FileCheck --check-prefix=CHECK-SOFTFLOAT64le %s
-// CHECK-SOFTFLOAT64le: error: invalid float ABI 'soft float is not supported for ppc64'
+// CHECK-SOFTFLOAT64le: "-target-feature" "-hard-float"
// check -mfloat-abi=soft option for ppc64
// RUN: %clang -target powerpc64le-unknown-linux-gnu %s -mfloat-abi=soft -### -o %t.o 2>&1 | FileCheck --check-prefix=CHECK-FLOATABISOFT64le %s
-// CHECK-FLOATABISOFT64le: error: invalid float ABI 'soft float is not supported for ppc64'
+// CHECK-FLOATABISOFT64le: "-target-feature" "-hard-float"
// CHECK: invalid argument '-faltivec' only allowed with 'ppc/ppc64/ppc64le'
@@ -163,6 +163,12 @@
// RUN: %clang -target powerpc64-unknown-linux-gnu %s -mno-crbits -mcrbits -### -o %t.o 2>&1 | FileCheck -check-prefix=CHECK-CRBITS %s
// CHECK-CRBITS: "-target-feature" "+crbits"
+// RUN: %clang -target powerpc64-unknown-linux-gnu %s -mno-longcall -### -o %t.o 2>&1 | FileCheck -check-prefix=CHECK-NOLONGCALL %s
+// CHECK-NOLONGCALL: "-target-feature" "-longcall"
+
+// RUN: %clang -target powerpc64-unknown-linux-gnu %s -mno-longcall -mlongcall -### -o %t.o 2>&1 | FileCheck -check-prefix=CHECK-LONGCALL %s
+// CHECK-LONGCALL: "-target-feature" "+longcall"
+
// RUN: %clang -target powerpc64-unknown-linux-gnu %s -mno-invariant-function-descriptors -### -o %t.o 2>&1 | FileCheck -check-prefix=CHECK-NOINVFUNCDESC %s
// CHECK-NOINVFUNCDESC: "-target-feature" "-invariant-function-descriptors"
diff --git a/test/Driver/preserve-as-comments.c b/test/Driver/preserve-as-comments.c
new file mode 100644
index 000000000000..7e623e403f1f
--- /dev/null
+++ b/test/Driver/preserve-as-comments.c
@@ -0,0 +1,2 @@
+// RUN: %clang -S -fno-preserve-as-comments %s -### 2>&1 | FileCheck %s
+// CHECK: "-fno-preserve-as-comments"
diff --git a/test/Driver/print-libgcc-file-name-clangrt.c b/test/Driver/print-libgcc-file-name-clangrt.c
new file mode 100644
index 000000000000..9f8120c31d90
--- /dev/null
+++ b/test/Driver/print-libgcc-file-name-clangrt.c
@@ -0,0 +1,11 @@
+// Test that -print-libgcc-file-name correctly respects -rtlib=compiler-rt.
+
+// RUN: %clang -rtlib=compiler-rt -print-libgcc-file-name 2>&1 \
+// RUN: --target=x86_64-pc-linux \
+// RUN: | FileCheck --check-prefix=CHECK-CLANGRT-X8664 %s
+// CHECK-CLANGRT-X8664: libclang_rt.builtins-x86_64.a
+
+// RUN: %clang -rtlib=compiler-rt -print-libgcc-file-name 2>&1 \
+// RUN: --target=i686-pc-linux \
+// RUN: | FileCheck --check-prefix=CHECK-CLANGRT-I686 %s
+// CHECK-CLANGRT-I686: libclang_rt.builtins-i686.a
diff --git a/test/Driver/print-libgcc-file-name-libgcc.c b/test/Driver/print-libgcc-file-name-libgcc.c
new file mode 100644
index 000000000000..3ca8fb900e3a
--- /dev/null
+++ b/test/Driver/print-libgcc-file-name-libgcc.c
@@ -0,0 +1,7 @@
+// Test that -print-libgcc-file-name correctly respects -rtlib=libgcc.
+
+// REQUIRES: libgcc
+
+// RUN: %clang -rtlib=libgcc -print-libgcc-file-name 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-LIBGCC %s
+// CHECK-LIBGCC: libgcc.a
diff --git a/test/Driver/response-file-extra-whitespace.c b/test/Driver/response-file-extra-whitespace.c
index 93b32bb50542..77d811c58d08 100644
--- a/test/Driver/response-file-extra-whitespace.c
+++ b/test/Driver/response-file-extra-whitespace.c
@@ -3,7 +3,7 @@
// some joined arguments (like "-x c") across lines to ensure that regular
// clang (not clang-cl) can process it correctly.
//
-// RUN: echo -en "-x\r\nc\r\n-DTEST\r\n" > %t.0.txt
+// RUN: printf " -x\r\nc\r\n-DTEST\r\n" > %t.0.txt
// RUN: %clang -E @%t.0.txt %s -v 2>&1 | FileCheck %s -check-prefix=SHORT
// SHORT: extern int it_works;
diff --git a/test/Driver/rewrite-map-files.c b/test/Driver/rewrite-map-files.c
new file mode 100644
index 000000000000..fe04fbaa1f42
--- /dev/null
+++ b/test/Driver/rewrite-map-files.c
@@ -0,0 +1,2 @@
+// RUN: %clang -### -frewrite-map-file %t.map -c %s -o /dev/null 2>&1 | FileCheck %s
+// CHECK: error: no such file or directory:
diff --git a/test/Driver/ropi-rwpi.c b/test/Driver/ropi-rwpi.c
new file mode 100644
index 000000000000..61fb8beff126
--- /dev/null
+++ b/test/Driver/ropi-rwpi.c
@@ -0,0 +1,38 @@
+// RUN: %clang -target arm-none-eabi -### -c %s 2>&1 | FileCheck --check-prefix=STATIC %s
+// RUN: %clang -target arm-none-eabi -fropi -### -c %s 2>&1 | FileCheck --check-prefix=ROPI %s
+// RUN: %clang -target arm-none-eabi -frwpi -### -c %s 2>&1 | FileCheck --check-prefix=RWPI %s
+// RUN: %clang -target arm-none-eabi -fropi -frwpi -### -c %s 2>&1 | FileCheck --check-prefix=ROPI-RWPI %s
+
+// RUN: %clang -target armeb-none-eabi -fropi -### -c %s 2>&1 | FileCheck --check-prefix=ROPI %s
+// RUN: %clang -target thumb-none-eabi -fropi -### -c %s 2>&1 | FileCheck --check-prefix=ROPI %s
+// RUN: %clang -target thumbeb-none-eabi -fropi -### -c %s 2>&1 | FileCheck --check-prefix=ROPI %s
+
+// RUN: %clang -target x86_64-linux-gnu -fropi -### -c %s 2>&1 | FileCheck --check-prefix=ROPI-NON-ARM %s
+// RUN: %clang -target x86_64-linux-gnu -frwpi -### -c %s 2>&1 | FileCheck --check-prefix=RWPI-NON-ARM %s
+// RUN: %clang -target x86_64-linux-gnu -fropi -frwpi -### -c %s 2>&1 | FileCheck --check-prefix=ROPI-NON-ARM --check-prefix=RWPI-NON-ARM %s
+
+// RUN: %clang -target arm-none-eabi -fpic -fropi -### -c %s 2>&1 | FileCheck --check-prefix=PIC %s
+// RUN: %clang -target arm-none-eabi -fpie -frwpi -### -c %s 2>&1 | FileCheck --check-prefix=PIC %s
+// RUN: %clang -target arm-none-eabi -fPIC -fropi -frwpi -### -c %s 2>&1 | FileCheck --check-prefix=PIC %s
+// RUN: %clang -target arm-none-eabi -fno-pic -fropi -### -c %s 2>&1 | FileCheck --check-prefix=ROPI %s
+
+// RUN: %clang -target arm-none-eabi -x c++ -fropi -### -c %s 2>&1 | FileCheck --check-prefix=CXX %s
+// RUN: %clang -target arm-none-eabi -x c++ -frwpi -### -c %s 2>&1 | FileCheck --check-prefix=RWPI %s
+// RUN: %clang -target arm-none-eabi -x c++ -fropi -frwpi -### -c %s 2>&1 | FileCheck --check-prefix=CXX %s
+// RUN: %clang -target arm-none-eabi -x c++ -fallow-unsupported -fropi -### -c %s 2>&1 | FileCheck --check-prefix=ROPI %s
+
+
+// STATIC: "-mrelocation-model" "static"
+
+// ROPI: "-mrelocation-model" "ropi"
+
+// RWPI: "-mrelocation-model" "rwpi"
+
+// ROPI-RWPI: "-mrelocation-model" "ropi-rwpi"
+
+// ROPI-NON-ARM: error: unsupported option '-fropi' for target 'x86_64--linux-gnu'
+// RWPI-NON-ARM: error: unsupported option '-frwpi' for target 'x86_64--linux-gnu'
+
+// PIC: error: embedded and GOT-based position independence are incompatible
+
+// CXX: error: ROPI is not compatible with c++
diff --git a/test/Driver/sanitizer-ld.c b/test/Driver/sanitizer-ld.c
index 4d4ea293a68e..91798b91b343 100644
--- a/test/Driver/sanitizer-ld.c
+++ b/test/Driver/sanitizer-ld.c
@@ -151,6 +151,15 @@
// CHECK-ASAN-ANDROID-SHARED: libclang_rt.asan-arm-android.so"
// CHECK-ASAN-ANDROID-SHARED-NOT: "-lpthread"
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN: -target sparcel-myriad-rtems-elf -fsanitize=address \
+// RUN: --sysroot=%S/Inputs/basic_myriad_tree \
+// RUN: | FileCheck --check-prefix=CHECK-ASAN-MYRIAD %s
+//
+// CHECK-ASAN-MYRIAD: "{{(.*[^.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
+// CHECK-ASAN-MYRIAD-NOT: "-lc"
+// CHECK-ASAN-MYRIAD: libclang_rt.asan-sparcel.a"
+
// RUN: %clangxx -no-canonical-prefixes %s -### -o %t.o 2>&1 \
// RUN: -target x86_64-unknown-linux -stdlib=platform -lstdc++ \
// RUN: -fsanitize=thread \
@@ -280,10 +289,24 @@
//
// CHECK-LSAN-LINUX: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
// CHECK-LSAN-LINUX-NOT: "-lc"
+// CHECK-LSAN-LINUX-NOT: libclang_rt.ubsan
// CHECK-LSAN-LINUX: libclang_rt.lsan-x86_64.a"
// CHECK-LSAN-LINUX: "-lpthread"
// CHECK-LSAN-LINUX: "-ldl"
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN: -target x86_64-unknown-linux -fsanitize=leak -fsanitize-coverage=func \
+// RUN: --sysroot=%S/Inputs/basic_linux_tree \
+// RUN: | FileCheck --check-prefix=CHECK-LSAN-COV-LINUX %s
+//
+// CHECK-LSAN-COV-LINUX: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
+// CHECK-LSAN-COV-LINUX-NOT: "-lc"
+// CHECK-LSAN-COV-LINUX-NOT: libclang_rt.ubsan
+// CHECK-LSAV-COV-LINUX: libclang_rt.lsan-x86_64.a"
+// CHECK-LSAN-COV-LINUX-NOT: libclang_rt.ubsan
+// CHECK-LSAN-COV-LINUX: "-lpthread"
+// CHECK-LSAN-COV-LINUX: "-ldl"
+
// RUN: %clang -fsanitize=leak,address %s -### -o %t.o 2>&1 \
// RUN: -target x86_64-unknown-linux \
// RUN: --sysroot=%S/Inputs/basic_linux_tree \
@@ -343,7 +366,7 @@
// CFI by itself does not link runtime libraries.
// RUN: %clang -fsanitize=cfi %s -### -o %t.o 2>&1 \
-// RUN: -target x86_64-unknown-linux \
+// RUN: -target x86_64-unknown-linux -rtlib=platform \
// RUN: --sysroot=%S/Inputs/basic_linux_tree \
// RUN: | FileCheck --check-prefix=CHECK-CFI-LINUX %s
// CHECK-CFI-LINUX: "{{.*}}ld{{(.exe)?}}"
@@ -365,6 +388,7 @@
// 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: -export-dynamic
// Cross-DSO CFI with diagnostics links just the CFI runtime.
// RUN: %clang -fsanitize=cfi -fsanitize-cfi-cross-dso %s -### -o %t.o 2>&1 \
@@ -374,6 +398,7 @@
// 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: -export-dynamic
// RUN: %clangxx -fsanitize=address %s -### -o %t.o 2>&1 \
// RUN: -mmacosx-version-min=10.6 \
@@ -439,7 +464,7 @@
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o -shared 2>&1 \
// RUN: -target arm-linux-androideabi -fsanitize=safe-stack \
// RUN: --sysroot=%S/Inputs/basic_android_tree \
-// RUN: | FileCheck --check-prefix=CHECK-SAFESTACK-ANDROID-ARM %s
+// RUN: | FileCheck --check-prefix=CHECK-SAFESTACK-SHARED-ANDROID-ARM %s
//
// CHECK-SAFESTACK-SHARED-ANDROID-ARM: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
// CHECK-SAFESTACK-SHARED-ANDROID-ARM-NOT: libclang_rt.safestack
@@ -452,6 +477,26 @@
// CHECK-SAFESTACK-ANDROID-AARCH64: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
// CHECK-SAFESTACK-ANDROID-AARCH64-NOT: libclang_rt.safestack
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN: -target arm-linux-androideabi -fsanitize=cfi \
+// RUN: --sysroot=%S/Inputs/basic_android_tree \
+// RUN: | FileCheck --check-prefix=CHECK-CFI-ANDROID %s
+//
+// CHECK-CFI-ANDROID: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
+// CHECK-CFI-ANDROID-NOT: libclang_rt.cfi
+// CHECK-CFI-ANDROID-NOT: __cfi_check
+
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN: -target arm-linux-androideabi -fsanitize=cfi \
+// RUN: -fsanitize-cfi-cross-dso \
+// RUN: --sysroot=%S/Inputs/basic_android_tree \
+// RUN: | FileCheck --check-prefix=CHECK-CROSSDSO-CFI-ANDROID %s
+//
+// CHECK-CROSSDSO-CFI-ANDROID: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
+// CHECK-CROSSDSO-CFI-ANDROID-NOT: libclang_rt.cfi
+// CHECK-CROSSDSO-CFI-ANDROID: -export-dynamic-symbol=__cfi_check
+// CHECK-CROSSDSO-CFI-ANDROID-NOT: libclang_rt.cfi
+
// RUN: %clang -fsanitize=undefined %s -### -o %t.o 2>&1 \
// RUN: -target x86_64-scei-ps4 \
// RUN: -shared \
diff --git a/test/Driver/save-stats.c b/test/Driver/save-stats.c
new file mode 100644
index 000000000000..5c21544ce31f
--- /dev/null
+++ b/test/Driver/save-stats.c
@@ -0,0 +1,20 @@
+// RUN: %clang -target x86_64-apple-darwin -save-stats %s -### 2>&1 | FileCheck %s
+// RUN: %clang -target x86_64-apple-darwin -save-stats=cwd %s -### 2>&1 | FileCheck %s
+// CHECK: "-stats-file=save-stats.stats"
+// CHECK: "{{.*}}save-stats.c"
+
+// RUN: %clang -target x86_64-apple-darwin -S %s -### 2>&1 | FileCheck %s -check-prefix=NO-STATS
+// NO-STATS-NO: -stats-file
+// NO-STATS: "{{.*}}save-stats.c"
+// NO-STATS-NO: -stats-file
+
+// RUN: %clang -target x86_64-apple-darwin -save-stats=obj -c -o obj/dir/save-stats.o %s -### 2>&1 | FileCheck %s -check-prefix=CHECK-OBJ
+// CHECK-OBJ: "-stats-file=obj/dir{{/|\\\\}}save-stats.stats"
+// CHECK-OBJ: "-o" "obj/dir{{/|\\\\}}save-stats.o"
+
+// RUN: %clang -target x86_64-apple-darwin -save-stats=obj -c %s -### 2>&1 | FileCheck %s -check-prefix=CHECK-OBJ-NOO
+// CHECK-OBJ-NOO: "-stats-file=save-stats.stats"
+// CHECK-OBJ-NOO: "-o" "save-stats.o"
+
+// 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'
diff --git a/test/Driver/show-option-names.c b/test/Driver/show-option-names.c
new file mode 100644
index 000000000000..9843a4371f14
--- /dev/null
+++ b/test/Driver/show-option-names.c
@@ -0,0 +1,7 @@
+// REQUIRES: x86-registered-target
+
+// RUN: %clang -target x86_64-apple-darwin -fsyntax-only -isysroot /FOO %s 2>&1 | FileCheck --check-prefix=CHECK-SHOW-OPTION-NAMES %s
+// CHECK-SHOW-OPTION-NAMES: warning: no such sysroot directory: '{{([A-Za-z]:.*)?}}/FOO' [-Wmissing-sysroot]
+
+// RUN: %clang -target x86_64-apple-darwin -fsyntax-only -fno-diagnostics-show-option -isysroot /FOO %s 2>&1 | FileCheck --check-prefix=CHECK-NO-SHOW-OPTION-NAMES %s
+// CHECK-NO-SHOW-OPTION-NAMES: warning: no such sysroot directory: '{{([A-Za-z]:.*)?}}/FOO'{{$}}
diff --git a/test/Driver/split-debug.c b/test/Driver/split-debug.c
index ed6685209398..eaa1e990c04c 100644
--- a/test/Driver/split-debug.c
+++ b/test/Driver/split-debug.c
@@ -33,11 +33,32 @@
//
// CHECK-IAS: objcopy
+// RUN: %clang -target x86_64-unknown-linux-gnu -gsplit-dwarf -gmlt -fno-split-dwarf-inlining -S -### %s 2> %t
+// RUN: FileCheck -check-prefix=CHECK-GMLT-WITH-SPLIT < %t %s
+//
+// CHECK-GMLT-WITH-SPLIT: "-split-dwarf=Enable"
+// CHECK-GMLT-WITH-SPLIT: "-debug-info-kind=line-tables-only"
+// CHECK-GMLT-WITH-SPLIT: "-split-dwarf-file"
+
+// RUN: %clang -target x86_64-unknown-linux-gnu -gmlt -gsplit-dwarf -fno-split-dwarf-inlining -S -### %s 2> %t
+// RUN: FileCheck -check-prefix=CHECK-SPLIT-WITH-GMLT < %t %s
+//
+// CHECK-SPLIT-WITH-GMLT: "-split-dwarf=Enable"
+// CHECK-SPLIT-WITH-GMLT: "-debug-info-kind=line-tables-only"
+// CHECK-SPLIT-WITH-GMLT: "-split-dwarf-file"
+
+// RUN: %clang -target x86_64-unknown-linux-gnu -gsplit-dwarf -fno-split-dwarf-inlining -S -### %s 2> %t
+// RUN: FileCheck -check-prefix=CHECK-SPLIT-WITH-NOINL < %t %s
+//
+// CHECK-SPLIT-WITH-NOINL: "-split-dwarf=Enable"
+// CHECK-SPLIT-WITH-NOINL: "-debug-info-kind=limited"
+// CHECK-SPLIT-WITH-NOINL: "-split-dwarf-file"
+
// RUN: %clang -target x86_64-unknown-linux-gnu -gsplit-dwarf -gmlt -S -### %s 2> %t
// RUN: FileCheck -check-prefix=CHECK-GMLT-OVER-SPLIT < %t %s
//
-// CHECK-GMLT-OVER-SPLIT: "-debug-info-kind=line-tables-only"
// CHECK-GMLT-OVER-SPLIT-NOT: "-split-dwarf=Enable"
+// CHECK-GMLT-OVER-SPLIT: "-debug-info-kind=line-tables-only"
// CHECK-GMLT-OVER-SPLIT-NOT: "-split-dwarf-file"
// RUN: %clang -target x86_64-unknown-linux-gnu -gmlt -gsplit-dwarf -S -### %s 2> %t
@@ -46,11 +67,18 @@
// CHECK-SPLIT-OVER-GMLT: "-split-dwarf=Enable" "-debug-info-kind=limited"
// CHECK-SPLIT-OVER-GMLT: "-split-dwarf-file"
-// RUN: %clang -target x86_64-unknown-linux-gnu -gsplit-dwarf -g0 -S -### %s 2> %t
+// RUN: %clang -target x86_64-unknown-linux-gnu -gsplit-dwarf -g0 -fno-split-dwarf-inlining -S -### %s 2> %t
// RUN: FileCheck -check-prefix=CHECK-G0-OVER-SPLIT < %t %s
//
+// CHECK-G0-OVER-SPLIT-NOT: "-split-dwarf=Enable"
// CHECK-G0-OVER-SPLIT-NOT: "-debug-info-kind
+// CHECK-G0-OVER-SPLIT-NOT: "-split-dwarf-file"
+
+// RUN: %clang -target x86_64-unknown-linux-gnu -gsplit-dwarf -g0 -S -### %s 2> %t
+// RUN: FileCheck -check-prefix=CHECK-G0-OVER-SPLIT < %t %s
+//
// CHECK-G0-OVER-SPLIT-NOT: "-split-dwarf=Enable"
+// CHECK-G0-OVER-SPLIT-NOT: "-debug-info-kind
// CHECK-G0-OVER-SPLIT-NOT: "-split-dwarf-file"
// RUN: %clang -target x86_64-unknown-linux-gnu -g0 -gsplit-dwarf -S -### %s 2> %t
diff --git a/test/Driver/stack-protector.c b/test/Driver/stack-protector.c
index 487af569f248..6769b65f6382 100644
--- a/test/Driver/stack-protector.c
+++ b/test/Driver/stack-protector.c
@@ -32,3 +32,31 @@
// RUN: %clang -target x86_64-scei-ps4 -fstack-protector --param ssp-buffer-size=16 -### %s 2>&1 | FileCheck %s -check-prefix=SSP-PS4-BUF
// SSP-PS4-BUF: "-stack-protector" "2"
// SSP-PS4-BUF: "-stack-protector-buffer-size" "16"
+
+// Test default stack protector values for Darwin platforms
+
+// RUN: %clang -target armv7k-apple-watchos2.0 -### %s 2>&1 | FileCheck %s -check-prefix=SSP_WATCHOS
+// SSP_WATCHOS: "-stack-protector" "1"
+// RUN: %clang -target arm64-apple-ios8.0.0 -### %s 2>&1 | FileCheck %s -check-prefix=SSP_IOS
+// SSP_IOS: "-stack-protector" "1"
+// RUN: %clang -target x86_64-apple-darwin10 -mmacosx-version-min=10.6 -### %s 2>&1 | FileCheck %s -check-prefix=SSP_MACOSX
+// SSP_MACOSX: "-stack-protector" "1"
+// RUN: %clang -target x86_64-apple-darwin10 -mmacosx-version-min=10.5 -### %s 2>&1 | FileCheck %s -check-prefix=SSP_MACOSX_10_5
+// SSP_MACOSX_10_5: "-stack-protector" "1"
+// RUN: %clang -target x86_64-apple-darwin10 -mmacosx-version-min=10.5 -mkernel -### %s 2>&1 | FileCheck %s -check-prefix=SSP_MACOSX_KERNEL
+// SSP_MACOSX_KERNEL-NOT: "-stack-protector"
+// RUN: %clang -target x86_64-apple-darwin10 -mmacosx-version-min=10.6 -### %s 2>&1 | FileCheck %s -check-prefix=SSP_MACOSX_10_6_KERNEL
+// SSP_MACOSX_10_6_KERNEL: "-stack-protector" "1"
+
+// Test default stack protector values for Darwin platforms with -ffreestanding
+
+// RUN: %clang -ffreestanding -target armv7k-apple-watchos2.0 -### %s 2>&1 | FileCheck %s -check-prefix=SSP_FREE_WATCHOS
+// SSP_FREE_WATCHOS-NOT: "-stack-protector"
+// RUN: %clang -ffreestanding -target arm64-apple-ios8.0.0 -### %s 2>&1 | FileCheck %s -check-prefix=SSP_FREE_IOS
+// SSP_FREE_IOS-NOT: "-stack-protector"
+// RUN: %clang -ffreestanding -target x86_64-apple-darwin10 -mmacosx-version-min=10.6 -### %s 2>&1 | FileCheck %s -check-prefix=SSP_FREE_MACOSX
+// SSP_FREE_MACOSX-NOT: "-stack-protector"
+// RUN: %clang -ffreestanding -target x86_64-apple-darwin10 -mmacosx-version-min=10.5 -### %s 2>&1 | FileCheck %s -check-prefix=SSP_FREE_MACOSX_10_5
+// SSP_FREE_MACOSX_10_5-NOT: "-stack-protector"
+// RUN: %clang -ffreestanding -target x86_64-apple-darwin10 -mmacosx-version-min=10.6 -### %s 2>&1 | FileCheck %s -check-prefix=SSP_FREE_MACOSX_10_6_KERNEL
+// SSP_FREE_MACOSX_10_6_KERNEL-NOT: "-stack-protector"
diff --git a/test/Driver/sysroot.c b/test/Driver/sysroot.c
index 3080f76e0316..4e9ed2bf6b68 100644
--- a/test/Driver/sysroot.c
+++ b/test/Driver/sysroot.c
@@ -1,3 +1,5 @@
+// REQUIRES: x86-registered-target
+//
// Check that --sysroot= also applies to header search paths.
// RUN: %clang -target i386-unk-unk --sysroot=/FOO -### -E %s 2> %t1
// RUN: FileCheck --check-prefix=CHECK-SYSROOTEQ < %t1 %s
diff --git a/test/Driver/systemz-march.c b/test/Driver/systemz-march.c
index ffc126f14fe1..a5df1f482d1e 100644
--- a/test/Driver/systemz-march.c
+++ b/test/Driver/systemz-march.c
@@ -2,12 +2,22 @@
// RUN: not %clang -target s390x -S -emit-llvm -march=z9 %s -o - 2>&1 | FileCheck --check-prefix=CHECK-Z9 %s
// RUN: %clang -target s390x -### -S -emit-llvm -march=z10 %s 2>&1 | FileCheck --check-prefix=CHECK-Z10 %s
+// RUN: %clang -target s390x -### -S -emit-llvm -march=arch8 %s 2>&1 | FileCheck --check-prefix=CHECK-ARCH8 %s
// RUN: %clang -target s390x -### -S -emit-llvm -march=z196 %s 2>&1 | FileCheck --check-prefix=CHECK-Z196 %s
+// RUN: %clang -target s390x -### -S -emit-llvm -march=arch9 %s 2>&1 | FileCheck --check-prefix=CHECK-ARCH9 %s
// RUN: %clang -target s390x -### -S -emit-llvm -march=zEC12 %s 2>&1 | FileCheck --check-prefix=CHECK-ZEC12 %s
+// RUN: %clang -target s390x -### -S -emit-llvm -march=arch10 %s 2>&1 | FileCheck --check-prefix=CHECK-ARCH10 %s
+// RUN: %clang -target s390x -### -S -emit-llvm -march=z13 %s 2>&1 | FileCheck --check-prefix=CHECK-Z13 %s
+// RUN: %clang -target s390x -### -S -emit-llvm -march=arch11 %s 2>&1 | FileCheck --check-prefix=CHECK-ARCH11 %s
// CHECK-Z9: error: unknown target CPU 'z9'
// CHECK-Z10: "-target-cpu" "z10"
+// CHECK-ARCH8: "-target-cpu" "arch8"
// CHECK-Z196: "-target-cpu" "z196"
+// CHECK-ARCH9: "-target-cpu" "arch9"
// CHECK-ZEC12: "-target-cpu" "zEC12"
+// CHECK-ARCH10: "-target-cpu" "arch10"
+// CHECK-Z13: "-target-cpu" "z13"
+// CHECK-ARCH11: "-target-cpu" "arch11"
int x;
diff --git a/test/Driver/unsupported-target-arch.c b/test/Driver/unsupported-target-arch.c
new file mode 100644
index 000000000000..7c55850f4994
--- /dev/null
+++ b/test/Driver/unsupported-target-arch.c
@@ -0,0 +1,25 @@
+// Tests that clang does not crash with invalid architectures in target triples.
+//
+// RUN: not %clang --target=noarch-unknown-linux -o %t.o %s 2> %t.err
+// RUN: FileCheck --input-file=%t.err --check-prefix=CHECK-NOARCH-LINUX %s
+// CHECK-NOARCH-LINUX: error: unknown target triple 'noarch-unknown-linux', please use -triple or -arch
+//
+// RUN: not %clang --target=noarch-unknown-darwin -o %t.o %s 2> %t.err
+// RUN: FileCheck --input-file=%t.err --check-prefix=CHECK-NOARCH-DARWIN %s
+// CHECK-NOARCH-DARWIN: error: unknown target triple 'unknown-unknown-macosx{{.+}}', please use -triple or -arch
+//
+// RUN: not %clang --target=noarch-unknown-windows -o %t.o %s 2> %t.err
+// RUN: FileCheck --input-file=%t.err --check-prefix=CHECK-NOARCH-WINDOWS %s
+// CHECK-NOARCH-WINDOWS: error: unknown target triple 'noarch-unknown-windows-{{.+}}', please use -triple or -arch
+//
+// RUN: not %clang --target=noarch-unknown-freebsd -o %t.o %s 2> %t.err
+// RUN: FileCheck --input-file=%t.err --check-prefix=CHECK-NOARCH-FREEBSD %s
+// CHECK-NOARCH-FREEBSD: error: unknown target triple 'noarch-unknown-freebsd', please use -triple or -arch
+//
+// RUN: not %clang --target=noarch-unknown-netbsd -o %t.o %s 2> %t.err
+// RUN: FileCheck --input-file=%t.err --check-prefix=CHECK-NOARCH-NETBSD %s
+// CHECK-NOARCH-NETBSD: error: unknown target triple 'noarch-unknown-netbsd', please use -triple or -arch
+//
+// RUN: not %clang --target=noarch-unknown-nacl -o %t.o %s 2> %t.err
+// RUN: FileCheck --input-file=%t.err --check-prefix=CHECK-NOARCH-NACL %s
+// CHECK-NOARCH-NACL: error: the target architecture 'noarch' is not supported by the target 'Native Client'
diff --git a/test/Driver/warning-options.cpp b/test/Driver/warning-options.cpp
index 4d9e1f7466de..7b9d4ab53a32 100644
--- a/test/Driver/warning-options.cpp
+++ b/test/Driver/warning-options.cpp
@@ -4,5 +4,5 @@
// LARGE_VALUE_COPY_JOINED: -Wlarge-by-value-copy=128
// Check that -isysroot warns on nonexistent paths.
-// RUN: %clang -### -c -target i386-apple-darwin10 -isysroot /FOO %s 2>&1 | FileCheck --check-prefix=CHECK-ISYSROOT %s
-// CHECK-ISYSROOT: warning: no such sysroot directory: '{{([A-Za-z]:.*)?}}/FOO'
+// RUN: %clang -### -c -target i386-apple-darwin10 -isysroot %T/warning-options %s 2>&1 | FileCheck --check-prefix=CHECK-ISYSROOT %s
+// CHECK-ISYSROOT: warning: no such sysroot directory: '{{.*}}/warning-options'
diff --git a/test/Driver/windows-cross.c b/test/Driver/windows-cross.c
index 3812287c8aa9..84ef2df75d6f 100644
--- a/test/Driver/windows-cross.c
+++ b/test/Driver/windows-cross.c
@@ -1,4 +1,4 @@
-// RUN: %clang -### -target armv7-windows-itanium --sysroot %S/Inputs/Windows/ARM/8.1 -B %S/Inputs/Windows/ARM/8.1/usr/bin -stdlib=libstdc++ -o /dev/null %s 2>&1 \
+// RUN: %clang -### -target armv7-windows-itanium --sysroot %S/Inputs/Windows/ARM/8.1 -B %S/Inputs/Windows/ARM/8.1/usr/bin -stdlib=libstdc++ -rtlib=platform -o /dev/null %s 2>&1 \
// RUN: | FileCheck %s --check-prefix CHECK-BASIC
// CHECK-BASIC: armv7-windows-itanium-ld" "--sysroot={{.*}}/Inputs/Windows/ARM/8.1" "-m" "thumb2pe" "-Bdynamic" "--entry" "mainCRTStartup" "--allow-multiple-definition" "-o" "{{[^"]*}}" "{{.*}}/Inputs/Windows/ARM/8.1/usr/lib/crtbegin.obj" "-L{{.*}}/Inputs/Windows/ARM/8.1/usr/lib" "-L{{.*}}/Inputs/Windows/ARM/8.1/usr/lib/gcc" "{{.*}}.o" "-lmsvcrt" "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed"
diff --git a/test/Driver/windows-pic.cpp b/test/Driver/windows-pic.cpp
new file mode 100644
index 000000000000..3b77a7cc5a33
--- /dev/null
+++ b/test/Driver/windows-pic.cpp
@@ -0,0 +1,59 @@
+// RUN: %clang -### -target i686-windows -fPIC %s 2>&1 | FileCheck -check-prefix CHECK-PIC-ERROR %s
+// RUN: %clang -### -target i686-windows -fpic %s 2>&1 | FileCheck -check-prefix CHECK-pic-ERROR %s
+// RUN: %clang -### -target i686-windows -fPIE %s 2>&1 | FileCheck -check-prefix CHECK-PIE-ERROR %s
+// RUN: %clang -### -target i686-windows -fpie %s 2>&1 | FileCheck -check-prefix CHECK-pie-ERROR %s
+// RUN: %clang -### -target i686-windows -fPIC -fno-pic %s
+// RUN: %clang -### -target i686-windows -Fpic -fno-pic %s
+// RUN: %clang -### -target i686-windows -fPIE -fno-pie %s
+// RUN: %clang -### -target i686-windows -fpie -fno-pie %s
+
+// RUN: %clang -### -target i686-windows-itanium -fPIC %s 2>&1 | FileCheck -check-prefix CHECK-PIC-ERROR %s
+// RUN: %clang -### -target i686-windows-itanium -fpic %s 2>&1 | FileCheck -check-prefix CHECK-pic-ERROR %s
+// RUN: %clang -### -target i686-windows-itanium -fPIE %s 2>&1 | FileCheck -check-prefix CHECK-PIE-ERROR %s
+// RUN: %clang -### -target i686-windows-itanium -fpie %s 2>&1 | FileCheck -check-prefix CHECK-pie-ERROR %s
+// RUN: %clang -### -target i686-windows-itanium -fPIC -fno-pic %s
+// RUN: %clang -### -target i686-windows-itanium -Fpic -fno-pic %s
+// RUN: %clang -### -target i686-windows-itanium -fPIE -fno-pie %s
+// RUN: %clang -### -target i686-windows-itanium -fpie -fno-pie %s
+
+// RUN: %clang -### -target i686-windows-gnu -fPIC %s 2>&1 | FileCheck -check-prefix CHECK-PIC-ERROR %s
+// RUN: %clang -### -target i686-windows-gnu -fpic %s 2>&1 | FileCheck -check-prefix CHECK-pic-ERROR %s
+// RUN: %clang -### -target i686-windows-gnu -fPIE %s 2>&1 | FileCheck -check-prefix CHECK-PIE-ERROR %s
+// RUN: %clang -### -target i686-windows-gnu -fpie %s 2>&1 | FileCheck -check-prefix CHECK-pie-ERROR %s
+// RUN: %clang -### -target i686-windows-gnu -fPIC -fno-pic %s
+// RUN: %clang -### -target i686-windows-gnu -Fpic -fno-pic %s
+// RUN: %clang -### -target i686-windows-gnu -fPIE -fno-pie %s
+// RUN: %clang -### -target i686-windows-gnu -fpie -fno-pie %s
+
+// RUN: %clang -### -target x86_64-windows -fPIC %s 2>&1 | FileCheck -check-prefix CHECK-PIC-ERROR %s
+// RUN: %clang -### -target x86_64-windows -fpic %s 2>&1 | FileCheck -check-prefix CHECK-pic-ERROR %s
+// RUN: %clang -### -target x86_64-windows -fPIE %s 2>&1 | FileCheck -check-prefix CHECK-PIE-ERROR %s
+// RUN: %clang -### -target x86_64-windows -fpie %s 2>&1 | FileCheck -check-prefix CHECK-pie-ERROR %s
+// RUN: %clang -### -target x86_64-windows -fPIC -fno-pic %s
+// RUN: %clang -### -target x86_64-windows -Fpic -fno-pic %s
+// RUN: %clang -### -target x86_64-windows -fPIE -fno-pie %s
+// RUN: %clang -### -target x86_64-windows -fpie -fno-pie %s
+
+// RUN: %clang -### -target x86_64-windows-itanium -fPIC %s 2>&1 | FileCheck -check-prefix CHECK-PIC-ERROR %s
+// RUN: %clang -### -target x86_64-windows-itanium -fpic %s 2>&1 | FileCheck -check-prefix CHECK-pic-ERROR %s
+// RUN: %clang -### -target x86_64-windows-itanium -fPIE %s 2>&1 | FileCheck -check-prefix CHECK-PIE-ERROR %s
+// RUN: %clang -### -target x86_64-windows-itanium -fpie %s 2>&1 | FileCheck -check-prefix CHECK-pie-ERROR %s
+// RUN: %clang -### -target x86_64-windows-itanium -fPIC -fno-pic %s
+// RUN: %clang -### -target x86_64-windows-itanium -Fpic -fno-pic %s
+// RUN: %clang -### -target x86_64-windows-itanium -fPIE -fno-pie %s
+// RUN: %clang -### -target x86_64-windows-itanium -fpie -fno-pie %s
+
+// RUN: %clang -### -target x86_64-windows-gnu -fPIC %s 2>&1 | FileCheck -check-prefix CHECK-PIC-ERROR %s
+// RUN: %clang -### -target x86_64-windows-gnu -fpic %s 2>&1 | FileCheck -check-prefix CHECK-pic-ERROR %s
+// RUN: %clang -### -target x86_64-windows-gnu -fPIE %s 2>&1 | FileCheck -check-prefix CHECK-PIE-ERROR %s
+// RUN: %clang -### -target x86_64-windows-gnu -fpie %s 2>&1 | FileCheck -check-prefix CHECK-pie-ERROR %s
+// RUN: %clang -### -target x86_64-windows-gnu -fPIC -fno-pic %s
+// RUN: %clang -### -target x86_64-windows-gnu -Fpic -fno-pic %s
+// RUN: %clang -### -target x86_64-windows-gnu -fPIE -fno-pie %s
+// RUN: %clang -### -target x86_64-windows-gnu -fpie -fno-pie %s
+
+// CHECK-PIC-ERROR: unsupported option '-fPIC' for target '{{.*}}
+// CHECK-pic-ERROR: unsupported option '-fpic' for target '{{.*}}
+// CHECK-PIE-ERROR: unsupported option '-fPIE' for target '{{.*}}
+// CHECK-pie-ERROR: unsupported option '-fpie' for target '{{.*}}
+
diff --git a/test/Driver/windows-thumb.s b/test/Driver/windows-thumb.s
new file mode 100644
index 000000000000..afe5b2d4bca3
--- /dev/null
+++ b/test/Driver/windows-thumb.s
@@ -0,0 +1,2 @@
+; RUN: %clang -target armv7-windows -c -### %s 2>&1 | FileCheck %s
+; CHECK: "-triple" "thumbv7-
diff --git a/test/FixIt/Inputs/nullability.h b/test/FixIt/Inputs/nullability.h
new file mode 100644
index 000000000000..bdfa01e49909
--- /dev/null
+++ b/test/FixIt/Inputs/nullability.h
@@ -0,0 +1,27 @@
+int * _Nonnull forceNullabilityWarnings(void);
+
+void arrayParameter(int x[]); // expected-warning {{array parameter is missing a nullability type specifier}}
+// expected-note@-1 {{insert '_Nullable'}}
+// expected-note@-2 {{insert '_Nonnull'}}
+// CHECK: fix-it:"{{.*}}nullability.h":{[[@LINE-3]]:27-[[@LINE-3]]:27}:"_Nullable"
+// CHECK: fix-it:"{{.*}}nullability.h":{[[@LINE-4]]:27-[[@LINE-4]]:27}:"_Nonnull"
+
+void arrayParameterWithSize(int x[5]); // expected-warning {{array parameter is missing a nullability type specifier}}
+// expected-note@-1 {{insert '_Nullable'}}
+// expected-note@-2 {{insert '_Nonnull'}}
+// CHECK: fix-it:"{{.*}}nullability.h":{[[@LINE-3]]:35-[[@LINE-3]]:35}:"_Nullable "
+// CHECK: fix-it:"{{.*}}nullability.h":{[[@LINE-4]]:35-[[@LINE-4]]:35}:"_Nonnull "
+
+void arrayParameterWithStar(int x[*]); // expected-warning {{array parameter is missing a nullability type specifier}}
+// expected-note@-1 {{insert '_Nullable'}}
+// expected-note@-2 {{insert '_Nonnull'}}
+// CHECK: fix-it:"{{.*}}nullability.h":{[[@LINE-3]]:35-[[@LINE-3]]:35}:"_Nullable "
+// CHECK: fix-it:"{{.*}}nullability.h":{[[@LINE-4]]:35-[[@LINE-4]]:35}:"_Nonnull "
+
+
+// No fix-its on either the macro definition or instantiation.
+// CHECK-NOT: fix-it:"{{.*}}nullability.h":{[[@LINE+2]]
+// CHECK-NOT: fix-it:"{{.*}}nullability.h":{[[@LINE+2]]
+#define PTR(X) X *
+PTR(int) a; // expected-warning{{pointer is missing a nullability type specifier}}
+#undef PTR
diff --git a/test/FixIt/fixit.cpp b/test/FixIt/fixit.cpp
index 686cc23d6354..c43aac98623c 100644
--- a/test/FixIt/fixit.cpp
+++ b/test/FixIt/fixit.cpp
@@ -1,8 +1,12 @@
-// RUN: %clang_cc1 -pedantic -Wall -Wno-comment -verify -fcxx-exceptions -x c++ %s
+// RUN: %clang_cc1 -pedantic -Wall -Wno-comment -verify -fcxx-exceptions -x c++ -std=c++98 %s
+// RUN: cp %s %t-98
+// RUN: not %clang_cc1 -pedantic -Wall -Wno-comment -fcxx-exceptions -fixit -x c++ -std=c++98 %t-98
+// RUN: %clang_cc1 -fsyntax-only -pedantic -Wall -Werror -Wno-comment -fcxx-exceptions -x c++ -std=c++98 %t-98
// RUN: not %clang_cc1 -fsyntax-only -fdiagnostics-parseable-fixits -x c++ -std=c++11 %s 2>&1 | FileCheck %s
-// RUN: cp %s %t
-// RUN: not %clang_cc1 -pedantic -Wall -Wno-comment -fcxx-exceptions -fixit -x c++ %t
-// RUN: %clang_cc1 -fsyntax-only -pedantic -Wall -Werror -Wno-comment -fcxx-exceptions -x c++ %t
+// RUN: %clang_cc1 -pedantic -Wall -Wno-comment -verify -fcxx-exceptions -x c++ -std=c++11 %s
+// RUN: cp %s %t-11
+// RUN: not %clang_cc1 -pedantic -Wall -Wno-comment -fcxx-exceptions -fixit -x c++ -std=c++11 %t-11
+// RUN: %clang_cc1 -fsyntax-only -pedantic -Wall -Werror -Wno-comment -fcxx-exceptions -x c++ -std=c++11 %t-11
/* This is a test of the various code modification hints that are
provided as part of warning or extension diagnostics. All of the
@@ -21,7 +25,11 @@ static void C1::g() { } // expected-error{{'static' can only be specified inside
template<int Value> struct CT { template<typename> struct Inner; }; // expected-note{{previous use is here}}
+// FIXME: In C++11 this gets 'expected unqualified-id' which fixit can't fix.
+// Probably parses as `CT<10> > 2 > ct;` rather than `CT<(10 >> 2)> ct;`.
+#if __cplusplus < 201103L
CT<10 >> 2> ct; // expected-warning{{require parentheses}}
+#endif
class C3 {
public:
@@ -41,7 +49,11 @@ protected:
};
class B : public A {
+#if __cplusplus >= 201103L
+ A::foo; // expected-error{{ISO C++11 does not allow access declarations}}
+#else
A::foo; // expected-warning{{access declarations are deprecated}}
+#endif
};
void f() throw(); // expected-note{{previous}}
@@ -285,8 +297,10 @@ namespace greatergreater {
void (*p)() = &t<int>;
(void)(&t<int>==p); // expected-error {{use '> ='}}
(void)(&t<int>>=p); // expected-error {{use '> >'}}
+#if __cplusplus < 201103L
(void)(&t<S<int>>>=p); // expected-error {{use '> >'}}
(Shr)&t<S<int>>>>=p; // expected-error {{use '> >'}}
+#endif
// FIXME: We correct this to '&t<int> > >= p;' not '&t<int> >>= p;'
//(Shr)&t<int>>>=p;
diff --git a/test/FixIt/nullability.mm b/test/FixIt/nullability.mm
new file mode 100644
index 000000000000..815c84419243
--- /dev/null
+++ b/test/FixIt/nullability.mm
@@ -0,0 +1,78 @@
+// RUN: %clang_cc1 -fsyntax-only -fblocks -std=gnu++11 -I %S/Inputs -verify %s
+// RUN: not %clang_cc1 -fdiagnostics-parseable-fixits -fblocks -std=gnu++11 -I %S/Inputs %s >%t.txt 2>&1
+// RUN: FileCheck %s < %t.txt
+// RUN: FileCheck %S/Inputs/nullability.h < %t.txt
+
+#include "nullability.h"
+
+#pragma clang assume_nonnull begin
+
+extern void *array[2]; // expected-warning {{inferring '_Nonnull' for pointer type within array is deprecated}}
+// CHECK: fix-it:"{{.*}}nullability.mm":{[[@LINE-1]]:14-[[@LINE-1]]:14}:" _Nonnull "
+
+extern void* array2[2]; // expected-warning {{inferring '_Nonnull' for pointer type within array is deprecated}}
+// CHECK: fix-it:"{{.*}}nullability.mm":{[[@LINE-1]]:13-[[@LINE-1]]:13}:" _Nonnull"
+
+extern void *nestedArray[2][3]; // expected-warning {{inferring '_Nonnull' for pointer type within array is deprecated}}
+// CHECK: fix-it:"{{.*}}nullability.mm":{[[@LINE-1]]:14-[[@LINE-1]]:14}:" _Nonnull "
+
+// No fix-its on either the macro definition or instantiation.
+// CHECK-NOT: fix-it:"{{.*}}nullability.mm":{[[@LINE+2]]
+// CHECK-NOT: fix-it:"{{.*}}nullability.mm":{[[@LINE+2]]
+#define PTR(X) X *
+extern PTR(void) array[2]; // expected-warning {{inferring '_Nonnull' for pointer type within array is deprecated}}
+
+
+typedef const void *CFTypeRef;
+
+extern CFTypeRef typedefArray[2]; // expected-warning {{inferring '_Nonnull' for pointer type within array is deprecated}}
+// CHECK: fix-it:"{{.*}}nullability.mm":{[[@LINE-1]]:17-[[@LINE-1]]:17}:" _Nonnull"
+
+
+extern void *&ref; // expected-warning {{inferring '_Nonnull' for pointer type within reference is deprecated}}
+// CHECK: fix-it:"{{.*}}nullability.mm":{[[@LINE-1]]:14-[[@LINE-1]]:14}:"_Nonnull"
+
+extern void * &ref2; // expected-warning {{inferring '_Nonnull' for pointer type within reference is deprecated}}
+// CHECK: fix-it:"{{.*}}nullability.mm":{[[@LINE-1]]:14-[[@LINE-1]]:14}:" _Nonnull"
+
+extern void *&&ref3; // expected-warning {{inferring '_Nonnull' for pointer type within reference is deprecated}}
+// CHECK: fix-it:"{{.*}}nullability.mm":{[[@LINE-1]]:14-[[@LINE-1]]:14}:"_Nonnull"
+
+extern void * &&ref4; // expected-warning {{inferring '_Nonnull' for pointer type within reference is deprecated}}
+// CHECK: fix-it:"{{.*}}nullability.mm":{[[@LINE-1]]:14-[[@LINE-1]]:14}:" _Nonnull"
+
+extern void *(&arrayRef)[2]; // expected-warning {{inferring '_Nonnull' for pointer type within array is deprecated}}
+// CHECK: fix-it:"{{.*}}nullability.mm":{[[@LINE-1]]:14-[[@LINE-1]]:14}:"_Nonnull"
+
+extern void * (&arrayRef2)[2]; // expected-warning {{inferring '_Nonnull' for pointer type within array is deprecated}}
+// CHECK: fix-it:"{{.*}}nullability.mm":{[[@LINE-1]]:14-[[@LINE-1]]:14}:" _Nonnull"
+
+extern CFTypeRef &typedefRef; // expected-warning {{inferring '_Nonnull' for pointer type within reference is deprecated}}
+// CHECK: fix-it:"{{.*}}nullability.mm":{[[@LINE-1]]:17-[[@LINE-1]]:17}:" _Nonnull"
+extern CFTypeRef& typedefRef2; // expected-warning {{inferring '_Nonnull' for pointer type within reference is deprecated}}
+// CHECK: fix-it:"{{.*}}nullability.mm":{[[@LINE-1]]:17-[[@LINE-1]]:17}:" _Nonnull "
+
+
+void arrayNameless(void *[]); // expected-warning {{inferring '_Nonnull' for pointer type within array is deprecated}}
+// CHECK: fix-it:"{{.*}}nullability.mm":{[[@LINE-1]]:26-[[@LINE-1]]:26}:"_Nonnull"
+
+void arrayNameless2(void * []); // expected-warning {{inferring '_Nonnull' for pointer type within array is deprecated}}
+// CHECK: fix-it:"{{.*}}nullability.mm":{[[@LINE-1]]:27-[[@LINE-1]]:27}:" _Nonnull"
+
+void arrayNamelessTypedef(CFTypeRef[]); // expected-warning {{inferring '_Nonnull' for pointer type within array is deprecated}}
+// CHECK: fix-it:"{{.*}}nullability.mm":{[[@LINE-1]]:36-[[@LINE-1]]:36}:" _Nonnull "
+
+void arrayNamelessTypedef2(CFTypeRef []); // expected-warning {{inferring '_Nonnull' for pointer type within array is deprecated}}
+// CHECK: fix-it:"{{.*}}nullability.mm":{[[@LINE-1]]:37-[[@LINE-1]]:37}:" _Nonnull"
+
+
+extern int (*pointerToArray)[2]; // no-warning
+int checkTypePTA = pointerToArray; // expected-error {{cannot initialize a variable of type 'int' with an lvalue of type 'int (* _Nonnull)[2]'}}
+
+int **arrayOfNestedPointers[2]; // no-warning
+int checkTypeANP = arrayOfNestedPointers; // expected-error {{cannot initialize a variable of type 'int' with an lvalue of type 'int **[2]'}}
+
+CFTypeRef *arrayOfNestedPointersTypedef[2]; // no-warning
+int checkTypeANPT = arrayOfNestedPointersTypedef; // expected-error {{cannot initialize a variable of type 'int' with an lvalue of type 'CFTypeRef *[2]'}}
+
+#pragma clang assume_nonnull end
diff --git a/test/Format/remove-duplicate-includes.cpp b/test/Format/remove-duplicate-includes.cpp
new file mode 100644
index 000000000000..dedb1f4d7ae7
--- /dev/null
+++ b/test/Format/remove-duplicate-includes.cpp
@@ -0,0 +1,14 @@
+// RUN: grep -Ev "// *[A-Z-]+:" %s \
+// RUN: | clang-format -style="{BasedOnStyle: LLVM, SortIncludes: true}" -lines=1:5 \
+// RUN: | FileCheck -strict-whitespace %s
+// CHECK: {{^#include\ <a>$}}
+#include <a>
+// CHECK: {{^#include\ <b>$}}
+#include <b>
+#include <a>
+#include <b>
+#include <b>
+{
+// CHECK: {{^\ \ int x\ \ ;$}}
+ int x ;
+}
diff --git a/test/Frontend/Inputs/absolute-paths.h b/test/Frontend/Inputs/absolute-paths.h
new file mode 100644
index 000000000000..5e682c734707
--- /dev/null
+++ b/test/Frontend/Inputs/absolute-paths.h
@@ -0,0 +1,3 @@
+int f() {
+ // Oops, no return.
+}
diff --git a/test/Frontend/Inputs/optimization-remark-with-hotness.proftext b/test/Frontend/Inputs/optimization-remark-with-hotness.proftext
new file mode 100644
index 000000000000..af111d6d06bb
--- /dev/null
+++ b/test/Frontend/Inputs/optimization-remark-with-hotness.proftext
@@ -0,0 +1,25 @@
+foo
+# Func Hash:
+0
+# Num Counters:
+1
+# Counter Values:
+30
+
+bar
+# Func Hash:
+0
+# Num Counters:
+1
+# Counter Values:
+30
+
+main
+# Func Hash:
+4
+# Num Counters:
+2
+# Counter Values:
+1
+30
+
diff --git a/test/Frontend/aarch64-target-cpu.c b/test/Frontend/aarch64-target-cpu.c
new file mode 100644
index 000000000000..90546472caf1
--- /dev/null
+++ b/test/Frontend/aarch64-target-cpu.c
@@ -0,0 +1,14 @@
+// Ensure we support the various CPU names.
+//
+// RUN: %clang_cc1 -triple aarch64-unknown-unknown -target-cpu cortex-a35 -verify %s
+// RUN: %clang_cc1 -triple aarch64-unknown-unknown -target-cpu cortex-a53 -verify %s
+// RUN: %clang_cc1 -triple aarch64-unknown-unknown -target-cpu cortex-a57 -verify %s
+// RUN: %clang_cc1 -triple aarch64-unknown-unknown -target-cpu cortex-a72 -verify %s
+// RUN: %clang_cc1 -triple aarch64-unknown-unknown -target-cpu cortex-a73 -verify %s
+// RUN: %clang_cc1 -triple aarch64-unknown-unknown -target-cpu cyclone -verify %s
+// RUN: %clang_cc1 -triple aarch64-unknown-unknown -target-cpu exynos-m1 -verify %s
+// RUN: %clang_cc1 -triple aarch64-unknown-unknown -target-cpu generic -verify %s
+// RUN: %clang_cc1 -triple aarch64-unknown-unknown -target-cpu kryo -verify %s
+// RUN: %clang_cc1 -triple aarch64-unknown-unknown -target-cpu vulcan -verify %s
+//
+// expected-no-diagnostics
diff --git a/test/Frontend/absolute-paths.c b/test/Frontend/absolute-paths.c
new file mode 100644
index 000000000000..478216294ae6
--- /dev/null
+++ b/test/Frontend/absolute-paths.c
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -fsyntax-only -I %S/Inputs/SystemHeaderPrefix/.. %s 2>&1 | FileCheck -check-prefix=NORMAL -check-prefix=CHECK %s
+// RUN: %clang_cc1 -fsyntax-only -I %S/Inputs/SystemHeaderPrefix/.. -fdiagnostics-absolute-paths %s 2>&1 | FileCheck -check-prefix=ABSOLUTE -check-prefix=CHECK %s
+
+#include "absolute-paths.h"
+
+// Check whether the diagnostic from the header above includes the dummy
+// directory in the path.
+// NORMAL: SystemHeaderPrefix
+// ABSOLUTE-NOT: SystemHeaderPrefix
+// CHECK: warning: control reaches end of non-void function
+
+
+// For files which don't exist, just print the filename.
+#line 123 "non-existant.c"
+int g() {}
+// NORMAL: non-existant.c:123:10: warning: control reaches end of non-void function
+// ABSOLUTE: non-existant.c:123:10: warning: control reaches end of non-void function
diff --git a/test/Frontend/gnu-mcount.c b/test/Frontend/gnu-mcount.c
index c279b89ddadf..690a103ed9ec 100644
--- a/test/Frontend/gnu-mcount.c
+++ b/test/Frontend/gnu-mcount.c
@@ -1,3 +1,5 @@
+// REQUIRES: arm-registered-target,aarch64-registered-target
+
// RUN: %clang -target armv7-unknown-none-eabi -pg -S -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK -check-prefix CHECK-ARM-EABI
// RUN: %clang -target armv7-unknown-none-eabi -pg -meabi gnu -S -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK -check-prefix CHECK-ARM-EABI-MEABI-GNU
// RUN: %clang -target aarch64-unknown-none-eabi -pg -S -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK -check-prefix CHECK-ARM64-EABI
@@ -44,35 +46,35 @@ int f() {
}
// CHECK-LABEL: f
-// CHECK-ARM-IOS-NOT: call void @_mcount()
-// CHECK-ARM-IOS-NOT: call void @"\01__gnu_mcount_nc"()
-// CHECK-ARM-EABI: call void @"\01mcount"()
-// CHECK-ARM-EABI-NOT: call void @"\01__gnu_mcount_nc"()
-// CHECK-ARM64-EABI: call void @mcount()
-// CHECK-ARM64-EABI-MEABI-GNU: call void @"\01_mcount"()
-// CHECK-ARM64-EABI-NOT: call void @"\01__gnu_mcount_nc"()
-// CHECK-ARM-EABI-FREEBSD: call void @__mcount()
-// CHECK-ARM-EABI-FREEBSD-NOT: call void @"\01__gnu_mcount_nc"()
-// CHECK-ARM64-EABI-FREEBSD: call void @.mcount()
-// CHECK-ARM64-EABI-FREEBSD-NOT: call void @"\01__gnu_mcount_nc"()
-// CHECK-ARM-EABI-NETBSD: call void @_mcount()
-// CHECK-ARM-EABI-NETBSD-NOT: call void @"\01__gnu_mcount_nc"()
-// CHECK-ARM-EABI-OPENBSD: call void @__mcount()
-// CHECK-ARM-EABI-OPENBSD-NOT: call void @"\01__gnu_mcount_nc"()
-// CHECK-ARM64-EABI-OPENBSD: call void @mcount()
-// CHECK-ARM64-EABI-OPENBSD-NOT: call void @"\01__gnu_mcount_nc"()
-// CHECK-ARM-EABI-MEABI-GNU-NOT: call void @mcount()
-// CHECK-ARM-EABI-MEABI-GNU: call void @"\01__gnu_mcount_nc"()
-// CHECK-ARM-EABI-BITRIG: call void @__mcount()
-// CHECK-ARM-EABI-BITRIG-NOT: call void @"\01__gnu_mcount_nc"()
-// CHECK-ARM54-EABI-BITRIG: call void @mcount()
-// CHECK-ARM54-EABI-BITRIG-NOT: call void @"\01__gnu_mcount_nc"()
-// CHECK-ARM-EABI-RTEMS: call void @mcount()
-// CHECK-ARM-EABI-RTEMS-NOT: call void @"\01__gnu_mcount_nc"()
-// CHECK-ARM64-EABI-RTEMS: call void @mcount()
-// CHECK-ARM64-EABI-RTEMS-NOT: call void @"\01__gnu_mcount_nc"()
-// CHECK-ARM-EABI-CLOUDABI: call void @mcount()
-// CHECK-ARM-EABI-CLOUDABI-NOT: call void @"\01__gnu_mcount_nc"()
-// CHECK-ARM64-EABI-CLOUDABI: call void @mcount()
-// CHECK-ARM64-EABI-CLOUDABI-NOT: call void @"\01__gnu_mcount_nc"()
+// CHECK-ARM-IOS-NOT: attributes #{{[0-9]+}} = { {{.*}}"counting-function"="_mcount"{{.*}} }
+// CHECK-ARM-IOS-NOT: attributes #{{[0-9]+}} = { {{.*}}"counting-function"="\01__gnu_mcount_nc"{{.*}} }
+// CHECK-ARM-EABI: attributes #{{[0-9]+}} = { {{.*}}"counting-function"="\01mcount"{{.*}} }
+// CHECK-ARM-EABI-NOT: attributes #{{[0-9]+}} = { {{.*}}"counting-function"="\01__gnu_mcount_nc"{{.*}} }
+// CHECK-ARM64-EABI: attributes #{{[0-9]+}} = { {{.*}}"counting-function"="mcount"{{.*}} }
+// CHECK-ARM64-EABI-MEABI-GNU: attributes #{{[0-9]+}} = { {{.*}}"counting-function"="\01_mcount"{{.*}} }
+// CHECK-ARM64-EABI-NOT: attributes #{{[0-9]+}} = { {{.*}}"counting-function"="\01__gnu_mcount_nc"{{.*}} }
+// CHECK-ARM-EABI-FREEBSD: attributes #{{[0-9]+}} = { {{.*}}"counting-function"="__mcount"{{.*}} }
+// CHECK-ARM-EABI-FREEBSD-NOT: attributes #{{[0-9]+}} = { {{.*}}"counting-function"="\01__gnu_mcount_nc"{{.*}} }
+// CHECK-ARM64-EABI-FREEBSD: attributes #{{[0-9]+}} = { {{.*}}"counting-function"=".mcount"{{.*}} }
+// CHECK-ARM64-EABI-FREEBSD-NOT: attributes #{{[0-9]+}} = { {{.*}}"counting-function"="\01__gnu_mcount_nc"{{.*}} }
+// CHECK-ARM-EABI-NETBSD: attributes #{{[0-9]+}} = { {{.*}}"counting-function"="_mcount"{{.*}} }
+// CHECK-ARM-EABI-NETBSD-NOT: attributes #{{[0-9]+}} = { {{.*}}"counting-function"="\01__gnu_mcount_nc"{{.*}} }
+// CHECK-ARM-EABI-OPENBSD: attributes #{{[0-9]+}} = { {{.*}}"counting-function"="__mcount"{{.*}} }
+// CHECK-ARM-EABI-OPENBSD-NOT: attributes #{{[0-9]+}} = { {{.*}}"counting-function"="\01__gnu_mcount_nc"{{.*}} }
+// CHECK-ARM64-EABI-OPENBSD: attributes #{{[0-9]+}} = { {{.*}}"counting-function"="mcount"{{.*}} }
+// CHECK-ARM64-EABI-OPENBSD-NOT: attributes #{{[0-9]+}} = { {{.*}}"counting-function"="\01__gnu_mcount_nc"{{.*}} }
+// CHECK-ARM-EABI-MEABI-GNU-NOT: attributes #{{[0-9]+}} = { {{.*}}"counting-function"="mcount"{{.*}} }
+// CHECK-ARM-EABI-MEABI-GNU: attributes #{{[0-9]+}} = { {{.*}}"counting-function"="\01__gnu_mcount_nc"{{.*}} }
+// CHECK-ARM-EABI-BITRIG: attributes #{{[0-9]+}} = { {{.*}}"counting-function"="__mcount"{{.*}} }
+// CHECK-ARM-EABI-BITRIG-NOT: attributes #{{[0-9]+}} = { {{.*}}"counting-function"="\01__gnu_mcount_nc"{{.*}} }
+// CHECK-ARM54-EABI-BITRIG: attributes #{{[0-9]+}} = { {{.*}}"counting-function"="mcount"{{.*}} }
+// CHECK-ARM54-EABI-BITRIG-NOT: attributes #{{[0-9]+}} = { {{.*}}"counting-function"="\01__gnu_mcount_nc"{{.*}} }
+// CHECK-ARM-EABI-RTEMS: attributes #{{[0-9]+}} = { {{.*}}"counting-function"="mcount"{{.*}} }
+// CHECK-ARM-EABI-RTEMS-NOT: attributes #{{[0-9]+}} = { {{.*}}"counting-function"="\01__gnu_mcount_nc"{{.*}} }
+// CHECK-ARM64-EABI-RTEMS: attributes #{{[0-9]+}} = { {{.*}}"counting-function"="mcount"{{.*}} }
+// CHECK-ARM64-EABI-RTEMS-NOT: attributes #{{[0-9]+}} = { {{.*}}"counting-function"="\01__gnu_mcount_nc"{{.*}} }
+// CHECK-ARM-EABI-CLOUDABI: attributes #{{[0-9]+}} = { {{.*}}"counting-function"="mcount"{{.*}} }
+// CHECK-ARM-EABI-CLOUDABI-NOT: attributes #{{[0-9]+}} = { {{.*}}"counting-function"="\01__gnu_mcount_nc"{{.*}} }
+// CHECK-ARM64-EABI-CLOUDABI: attributes #{{[0-9]+}} = { {{.*}}"counting-function"="mcount"{{.*}} }
+// CHECK-ARM64-EABI-CLOUDABI-NOT: attributes #{{[0-9]+}} = { {{.*}}"counting-function"="\01__gnu_mcount_nc"{{.*}} }
diff --git a/test/Frontend/include-duplicate-removal.c b/test/Frontend/include-duplicate-removal.c
new file mode 100644
index 000000000000..fb02cd7e48c3
--- /dev/null
+++ b/test/Frontend/include-duplicate-removal.c
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -v -I%S/Inputs -iquote %S/Inputs/SystemHeaderPrefix -isystem %S/Inputs/SystemHeaderPrefix -isystem %S/Inputs/SystemHeaderPrefix %s 2>&1 | FileCheck %s
+
+#include <test.h>
+
+// CHECK: ignoring duplicate directory
+// CHECK-SAME: Inputs/SystemHeaderPrefix"{{$}}
+
+// CHECK: #include "..."
+// CHECK-NEXT: {{.*}}Inputs/SystemHeaderPrefix{{$}}
+// CHECK-NEXT: #include <...>
+// CHECK-NEXT: {{.*}}Inputs{{$}}
+// CHECK-NEXT: {{.*}}Inputs/SystemHeaderPrefix{{$}}
diff --git a/test/Frontend/int128.cpp b/test/Frontend/int128.cpp
new file mode 100644
index 000000000000..145144a03d61
--- /dev/null
+++ b/test/Frontend/int128.cpp
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -x c -std=gnu99 -dM -E -triple x86_64-pc-linux %s | FileCheck -check-prefix=NO %s
+// RUN: %clang_cc1 -x c++ -std=c++11 -dM -E -triple x86_64-pc-linux %s | FileCheck -check-prefix=NO %s
+// RUN: %clang_cc1 -x c++ -std=gnu++11 -dM -E -triple i686-pc-linux %s | FileCheck -check-prefix=NO %s
+// RUN: %clang_cc1 -x c++ -std=gnu++11 -dM -E -triple x86_64-pc-linux %s | FileCheck -check-prefix=YES %s
+// RUN: %clang_cc1 -x c++ -std=gnu++1y -dM -E -triple x86_64-pc-linux %s | FileCheck -check-prefix=YES %s
+// PR23156
+
+// NO-NOT: __GLIBCXX_TYPE_INT_N_0
+// NO-NOT: __GLIBCXX_BITSIZE_INT_N_0
+// YES-DAG: __GLIBCXX_TYPE_INT_N_0
+// YES-DAG: __GLIBCXX_BITSIZE_INT_N_0
diff --git a/test/Frontend/objc-bool-is-bool.m b/test/Frontend/objc-bool-is-bool.m
new file mode 100644
index 000000000000..464fe2ea8c0c
--- /dev/null
+++ b/test/Frontend/objc-bool-is-bool.m
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -fsyntax-only -E -dM -triple=armv7k-apple-watchos %s | FileCheck --check-prefix=BOOL %s
+// RUN: %clang_cc1 -fsyntax-only -E -dM -triple=x86_64-apple-darwin16 %s | FileCheck --check-prefix=CHAR %s
+// RUN: %clang_cc1 -x c -fsyntax-only -E -dM -triple=x86_64-apple-darwin16 %s | FileCheck --check-prefix=NONE %s
+
+// rdar://21170440
+
+// BOOL: #define __OBJC_BOOL_IS_BOOL 1
+// BOOL-NOT: #define __OBJC_BOOL_IS_BOOL 0
+
+// CHAR: #define __OBJC_BOOL_IS_BOOL 0
+// CHAR-NOT: #define __OBJC_BOOL_IS_BOOL 1
+
+// NONE-NOT: __OBJC_BOOL_IS_BOOL
diff --git a/test/Frontend/optimization-remark-with-hotness.c b/test/Frontend/optimization-remark-with-hotness.c
new file mode 100644
index 000000000000..4c27e866f4ce
--- /dev/null
+++ b/test/Frontend/optimization-remark-with-hotness.c
@@ -0,0 +1,45 @@
+// RUN: llvm-profdata merge \
+// RUN: %S/Inputs/optimization-remark-with-hotness.proftext \
+// RUN: -o %t.profdata
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name \
+// RUN: optimization-remark-with-hotness.c %s -emit-llvm-only \
+// RUN: -fprofile-instrument-use-path=%t.profdata -Rpass=inline \
+// RUN: -Rpass-analysis=inline -fdiagnostics-show-hotness -verify
+// The clang version of the previous test.
+// RUN: %clang -target x86_64-apple-macosx10.9 %s -c -emit-llvm -o /dev/null \
+// RUN: -fprofile-instr-use=%t.profdata -Rpass=inline \
+// RUN: -Rpass-analysis=inline -fdiagnostics-show-hotness -Xclang -verify
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name \
+// RUN: optimization-remark-with-hotness.c %s -emit-llvm-only \
+// RUN: -fprofile-instrument-use-path=%t.profdata -Rpass=inline \
+// RUN: -Rpass-analysis=inline 2>&1 | FileCheck -check-prefix=HOTNESS_OFF %s
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name \
+// RUN: optimization-remark-with-hotness.c %s -emit-llvm-only \
+// RUN: -fprofile-instrument-use-path=%t.profdata -Rpass=inline \
+// RUN: -Rpass-analysis=inline -Rno-pass-with-hotness 2>&1 | FileCheck \
+// RUN: -check-prefix=HOTNESS_OFF %s
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name \
+// RUN: optimization-remark-with-hotness.c %s -emit-llvm-only \
+// RUN: -Rpass=inline -Rpass-analysis=inline -fdiagnostics-show-hotness 2>&1 \
+// RUN: | FileCheck -check-prefix=NO_PGO %s
+
+int foo(int x, int y) __attribute__((always_inline));
+int foo(int x, int y) { return x + y; }
+
+int sum = 0;
+
+void bar(int x) {
+ // HOTNESS_OFF: foo inlined into bar
+ // HOTNESS_OFF-NOT: hotness:
+ // NO_PGO: '-fdiagnostics-show-hotness' requires profile-guided optimization information
+ // expected-remark@+2 {{foo should always be inlined (cost=always) (hotness: 30)}}
+ // expected-remark@+1 {{foo inlined into bar (hotness: 30)}}
+ sum += foo(x, x - 2);
+}
+
+int main(int argc, const char *argv[]) {
+ for (int i = 0; i < 30; i++)
+ // expected-remark@+1 {{bar should never be inlined}}
+ bar(argc);
+ return sum;
+}
diff --git a/test/Frontend/plugin-vs-debug-info.cpp b/test/Frontend/plugin-vs-debug-info.cpp
new file mode 100644
index 000000000000..27631e5ba578
--- /dev/null
+++ b/test/Frontend/plugin-vs-debug-info.cpp
@@ -0,0 +1,32 @@
+// This test uses PrintFunctionNames with -fdelayed-template-parsing because it
+// happens to use a RecursiveASTVisitor that forces deserialization of AST
+// files.
+//
+// RUN: %clang_cc1 -triple %itanium_abi_triple -fdelayed-template-parsing \
+// RUN: -std=c++14 -emit-pch -o %t.pch %s
+// RUN: %clang_cc1 -triple %itanium_abi_triple \
+// RUN: -load %llvmshlibdir/PrintFunctionNames%pluginext \
+// RUN: -add-plugin print-fns -std=c++14 -include-pch %t.pch %s -emit-llvm \
+// RUN: -fdelayed-template-parsing -debug-info-kind=limited \
+// RUN: -o %t.ll 2>&1 | FileCheck --check-prefix=DECLS %s
+// RUN: FileCheck --check-prefix=IR %s < %t.ll
+//
+// REQUIRES: plugins, examples
+
+// DECLS: top-level-decl: "func"
+
+// IR: define {{.*}}void @_Z4funcv()
+
+#ifndef HEADER
+#define HEADER
+
+struct nullopt_t {
+ constexpr explicit nullopt_t(int) {}
+};
+constexpr nullopt_t nullopt(0);
+
+#else
+
+void func() { }
+
+#endif
diff --git a/test/Frontend/stats-file.c b/test/Frontend/stats-file.c
new file mode 100644
index 000000000000..1869eb3f76ae
--- /dev/null
+++ b/test/Frontend/stats-file.c
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -emit-llvm -o /dev/null -stats-file=%t %s
+// RUN: FileCheck -input-file=%t %s
+// CHECK: {
+// ... here come some json values ...
+// CHECK: }
+
+// RUN: %clang_cc1 -emit-llvm -o %t -stats-file=%S/doesnotexist/bla %s 2>&1 | FileCheck -check-prefix=OUTPUTFAIL %s
+// OUTPUTFAIL: warning: unable to open statistics output file '{{.*}}doesnotexist{{.}}bla': '{{[Nn]}}o such file or directory'
diff --git a/test/Headers/Inputs/usr/include/float.h b/test/Headers/Inputs/usr/include/float.h
new file mode 100644
index 000000000000..9dab891b9723
--- /dev/null
+++ b/test/Headers/Inputs/usr/include/float.h
@@ -0,0 +1,6 @@
+#ifndef SYSFLOAT_H
+#define SYSFLOAT_H
+
+#define FLT_HAS_SUBNORM 1
+
+#endif /* SYSFLOAT_H */
diff --git a/test/Headers/float-darwin.c b/test/Headers/float-darwin.c
new file mode 100644
index 000000000000..54bac1ac630f
--- /dev/null
+++ b/test/Headers/float-darwin.c
@@ -0,0 +1,13 @@
+// REQUIRES: system-darwin
+// RUN: %clang -target x86_64-apple-darwin10 -fsyntax-only -std=c11 -isysroot %S/Inputs %s
+#include <float.h>
+
+// Test the #include_next on float.h works on Darwin.
+#ifndef FLT_HAS_SUBNORM
+ #error "FLT_HAS_SUBNORM not defined"
+#endif
+
+// Test that definition from builtin are also present.
+#ifndef FLT_MAX
+ #error "FLT_MAX not defined"
+#endif
diff --git a/test/Headers/ms-intrin.cpp b/test/Headers/ms-intrin.cpp
index c69742855381..d410b1d95f50 100644
--- a/test/Headers/ms-intrin.cpp
+++ b/test/Headers/ms-intrin.cpp
@@ -38,7 +38,6 @@ void f() {
__movsd(0, 0, 0);
__movsw(0, 0, 0);
- __stosb(0, 0, 0);
__stosd(0, 0, 0);
__stosw(0, 0, 0);
@@ -52,6 +51,7 @@ void f() {
__cpuidex(info, 0, 0);
_xgetbv(0);
__halt();
+ __nop();
__readmsr(0);
// FIXME: Call these in 64-bit too once the intrinsics have been fixed to
@@ -60,4 +60,8 @@ void f() {
__readcr3();
__writecr3(0);
#endif
+
+#ifdef _M_ARM
+ __dmb(_ARM_BARRIER_ISHST);
+#endif
}
diff --git a/test/Headers/opencl-c-header.cl b/test/Headers/opencl-c-header.cl
index 37239357bc09..457a6193d41a 100644
--- a/test/Headers/opencl-c-header.cl
+++ b/test/Headers/opencl-c-header.cl
@@ -1,33 +1,6 @@
// RUN: %clang_cc1 -triple spir-unknown-unknown -internal-isystem ../../lib/Headers -include opencl-c.h -emit-llvm -o - %s | FileCheck %s
// RUN: %clang_cc1 -triple spir-unknown-unknown -internal-isystem ../../lib/Headers -include opencl-c.h -emit-llvm -o - %s -cl-std=CL1.1| FileCheck %s
-// RUN: %clang_cc1 -triple spir-unknown-unknown -internal-isystem ../../lib/Headers -include opencl-c.h -emit-llvm -o - %s -cl-std=CL1.2| FileCheck %s
-// RUN: %clang_cc1 -triple spir-unknown-unknown -internal-isystem ../../lib/Headers -include opencl-c.h -fblocks -emit-llvm -o - %s -cl-std=CL2.0| FileCheck --check-prefix=CHECK20 %s
-// RUN: %clang_cc1 -triple spir64-unknown-unknown -internal-isystem ../../lib/Headers -include opencl-c.h -emit-llvm -o - %s | FileCheck %s
-// RUN: %clang_cc1 -triple spir64-unknown-unknown -internal-isystem ../../lib/Headers -include opencl-c.h -emit-llvm -o - %s -cl-std=CL1.1| FileCheck %s
-// RUN: %clang_cc1 -triple spir64-unknown-unknown -internal-isystem ../../lib/Headers -include opencl-c.h -emit-llvm -o - %s -cl-std=CL1.2| FileCheck %s
-// RUN: %clang_cc1 -triple spir64-unknown-unknown -internal-isystem ../../lib/Headers -include opencl-c.h -fblocks -emit-llvm -o - %s -cl-std=CL2.0| FileCheck --check-prefix=CHECK20 %s
-// RUN: %clang_cc1 -triple amdgcn-unknown-amdhsa -internal-isystem ../../lib/Headers -include opencl-c.h -emit-llvm -o - %s | FileCheck %s
-// RUN: %clang_cc1 -triple amdgcn-unknown-amdhsa -internal-isystem ../../lib/Headers -include opencl-c.h -emit-llvm -o - %s -cl-std=CL1.1| FileCheck %s
-// RUN: %clang_cc1 -triple amdgcn-unknown-amdhsa -internal-isystem ../../lib/Headers -include opencl-c.h -emit-llvm -o - %s -cl-std=CL1.2| FileCheck %s
-// RUN: %clang_cc1 -triple amdgcn-unknown-amdhsa -internal-isystem ../../lib/Headers -include opencl-c.h -fblocks -emit-llvm -o - %s -cl-std=CL2.0| FileCheck --check-prefix=CHECK20 %s
-// RUN: %clang_cc1 -triple ppc64-unknown-unknown -internal-isystem ../../lib/Headers -include opencl-c.h -emit-llvm -o - %s | FileCheck %s
-// RUN: %clang_cc1 -triple ppc64-unknown-unknown -internal-isystem ../../lib/Headers -include opencl-c.h -emit-llvm -o - %s -cl-std=CL1.1| FileCheck %s
-// RUN: %clang_cc1 -triple ppc64-unknown-unknown -internal-isystem ../../lib/Headers -include opencl-c.h -emit-llvm -o - %s -cl-std=CL1.2| FileCheck %s
-// RUN: %clang_cc1 -triple ppc64-unknown-unknown -internal-isystem ../../lib/Headers -include opencl-c.h -fblocks -emit-llvm -o - %s -cl-std=CL2.0| FileCheck --check-prefix=CHECK20 %s
-// RUN: %clang_cc1 -triple powerpc-unknown-unknown -internal-isystem ../../lib/Headers -include opencl-c.h -emit-llvm -o - %s | FileCheck %s
-// RUN: %clang_cc1 -triple powerpc-unknown-unknown -internal-isystem ../../lib/Headers -include opencl-c.h -emit-llvm -o - %s -cl-std=CL1.1| FileCheck %s
-// RUN: %clang_cc1 -triple powerpc-unknown-unknown -internal-isystem ../../lib/Headers -include opencl-c.h -emit-llvm -o - %s -cl-std=CL1.2| FileCheck %s
-// RUN: %clang_cc1 -triple powerpc-unknown-unknown -internal-isystem ../../lib/Headers -include opencl-c.h -fblocks -emit-llvm -o - %s -cl-std=CL2.0| FileCheck --check-prefix=CHECK20 %s
-// RUN: %clang_cc1 -triple nvptx-unknown-unknown -internal-isystem ../../lib/Headers -include opencl-c.h -emit-llvm -o - %s | FileCheck %s
-// RUN: %clang_cc1 -triple nvptx-unknown-unknown -internal-isystem ../../lib/Headers -include opencl-c.h -emit-llvm -o - %s -cl-std=CL1.1| FileCheck %s
-// RUN: %clang_cc1 -triple nvptx-unknown-unknown -internal-isystem ../../lib/Headers -include opencl-c.h -emit-llvm -o - %s -cl-std=CL1.2| FileCheck %s
-// RUN: %clang_cc1 -triple nvptx-unknown-unknown -internal-isystem ../../lib/Headers -include opencl-c.h -fblocks -emit-llvm -o - %s -cl-std=CL2.0| FileCheck --check-prefix=CHECK20 %s
-// RUN: %clang_cc1 -triple nvptx64-unknown-unknown -internal-isystem ../../lib/Headers -include opencl-c.h -emit-llvm -o - %s | FileCheck %s
-// RUN: %clang_cc1 -triple nvptx64-unknown-unknown -internal-isystem ../../lib/Headers -include opencl-c.h -emit-llvm -o - %s -cl-std=CL1.1| FileCheck %s
-// RUN: %clang_cc1 -triple nvptx64-unknown-unknown -internal-isystem ../../lib/Headers -include opencl-c.h -emit-llvm -o - %s -cl-std=CL1.2| FileCheck %s
-// RUN: %clang_cc1 -triple nvptx64-unknown-unknown -internal-isystem ../../lib/Headers -include opencl-c.h -fblocks -emit-llvm -o - %s -cl-std=CL2.0| FileCheck --check-prefix=CHECK20 %s
-// RUN: %clang_cc1 -triple x86_64-unknown-unknown -finclude-default-header -emit-llvm -o - %s | FileCheck %s
// CHECK: _Z16convert_char_rtec
// CHECK-NOT: _Z3ctzc
// CHECK20: _Z3ctzc
@@ -68,12 +41,10 @@
// Check cached module works for different OpenCL versions.
// RUN: rm -rf %t
// RUN: mkdir -p %t
-// RUN: %clang_cc1 -triple spir-unknown-unknown -emit-llvm -o - -finclude-default-header -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -ftime-report %s 2>&1 | FileCheck --check-prefix=CHECK --check-prefix=CHECK-MOD %s
-// RUN: %clang_cc1 -triple spir-unknown-unknown -emit-llvm -o - -cl-std=CL2.0 -finclude-default-header -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -ftime-report %s 2>&1 | FileCheck --check-prefix=CHECK20 --check-prefix=CHECK-MOD %s
-// RUN: %clang_cc1 -triple amdgcn--amdhsa -emit-llvm -o - -cl-std=CL2.0 -finclude-default-header -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -ftime-report %s 2>&1 | FileCheck --check-prefix=CHECK20 --check-prefix=CHECK-MOD %s
+// RUN: %clang_cc1 -triple spir64-unknown-unknown -emit-llvm -o - -cl-std=CL1.2 -finclude-default-header -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -ftime-report %s 2>&1 | FileCheck --check-prefix=CHECK --check-prefix=CHECK-MOD %s
+// RUN: %clang_cc1 -triple amdgcn--amdhsa -emit-llvm -o - -cl-std=CL2.0 -finclude-default-header -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -ftime-report %s 2>&1 | FileCheck --check-prefix=CHECK20 --check-prefix=CHECK-MOD %s
// RUN: chmod u-w %t
-// RUN: %clang_cc1 -triple spir-unknown-unknown -emit-llvm -o - -finclude-default-header -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -ftime-report %s 2>&1 | FileCheck --check-prefix=CHECK --check-prefix=CHECK-MOD %s
-// RUN: %clang_cc1 -triple spir-unknown-unknown -emit-llvm -o - -cl-std=CL2.0 -finclude-default-header -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -ftime-report %s 2>&1 | FileCheck --check-prefix=CHECK20 --check-prefix=CHECK-MOD %s
+// RUN: %clang_cc1 -triple spir64-unknown-unknown -emit-llvm -o - -cl-std=CL1.2 -finclude-default-header -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -ftime-report %s 2>&1 | FileCheck --check-prefix=CHECK --check-prefix=CHECK-MOD %s
// RUN: %clang_cc1 -triple amdgcn--amdhsa -emit-llvm -o - -cl-std=CL2.0 -finclude-default-header -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -ftime-report %s 2>&1 | FileCheck --check-prefix=CHECK20 --check-prefix=CHECK-MOD %s
// RUN: chmod u+w %t
diff --git a/test/Headers/stdatomic.c b/test/Headers/stdatomic.c
new file mode 100644
index 000000000000..76112cfe40ea
--- /dev/null
+++ b/test/Headers/stdatomic.c
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 -std=c11 -E %s | FileCheck %s
+#include <stdatomic.h>
+
+int bool_lock_free = ATOMIC_BOOL_LOCK_FREE;
+// CHECK: bool_lock_free = {{ *[012] *;}}
+
+int char_lock_free = ATOMIC_CHAR_LOCK_FREE;
+// CHECK: char_lock_free = {{ *[012] *;}}
+
+int char16_t_lock_free = ATOMIC_CHAR16_T_LOCK_FREE;
+// CHECK: char16_t_lock_free = {{ *[012] *;}}
+
+int char32_t_lock_free = ATOMIC_CHAR32_T_LOCK_FREE;
+// CHECK: char32_t_lock_free = {{ *[012] *;}}
+
+int wchar_t_lock_free = ATOMIC_WCHAR_T_LOCK_FREE;
+// CHECK: wchar_t_lock_free = {{ *[012] *;}}
+
+int short_lock_free = ATOMIC_SHORT_LOCK_FREE;
+// CHECK: short_lock_free = {{ *[012] *;}}
+
+int int_lock_free = ATOMIC_INT_LOCK_FREE;
+// CHECK: int_lock_free = {{ *[012] *;}}
+
+int long_lock_free = ATOMIC_LONG_LOCK_FREE;
+// CHECK: long_lock_free = {{ *[012] *;}}
+
+int llong_lock_free = ATOMIC_LLONG_LOCK_FREE;
+// CHECK: llong_lock_free = {{ *[012] *;}}
+
+int pointer_lock_free = ATOMIC_POINTER_LOCK_FREE;
+// CHECK: pointer_lock_free = {{ *[012] *;}}
diff --git a/test/Headers/x86intrin.cpp b/test/Headers/x86intrin.cpp
new file mode 100644
index 000000000000..11d442db3d2c
--- /dev/null
+++ b/test/Headers/x86intrin.cpp
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -fsyntax-only -ffreestanding %s -verify
+// expected-no-diagnostics
+
+#if defined(i386) || defined(__x86_64__)
+
+// Include the metaheader that includes all x86 intrinsic headers.
+extern "C++" {
+#include <x86intrin.h>
+}
+
+#endif
diff --git a/test/Import/clang-flags/Inputs/S.c b/test/Import/clang-flags/Inputs/S.c
new file mode 100644
index 000000000000..742dac8a35b4
--- /dev/null
+++ b/test/Import/clang-flags/Inputs/S.c
@@ -0,0 +1,2 @@
+STRUCT S {
+};
diff --git a/test/Import/clang-flags/test.c b/test/Import/clang-flags/test.c
new file mode 100644
index 000000000000..7a19ea7ff648
--- /dev/null
+++ b/test/Import/clang-flags/test.c
@@ -0,0 +1,5 @@
+// RUN: clang-import-test -import %S/Inputs/S.c -expression %s -Xcc -DSTRUCT=struct
+void expr() {
+ STRUCT S MyS;
+ void *MyPtr = &MyS;
+}
diff --git a/test/Import/empty-struct/Inputs/S.c b/test/Import/empty-struct/Inputs/S.c
new file mode 100644
index 000000000000..8c90352bc463
--- /dev/null
+++ b/test/Import/empty-struct/Inputs/S.c
@@ -0,0 +1,2 @@
+struct S {
+};
diff --git a/test/Import/empty-struct/test.c b/test/Import/empty-struct/test.c
new file mode 100644
index 000000000000..d51a69706dcd
--- /dev/null
+++ b/test/Import/empty-struct/test.c
@@ -0,0 +1,5 @@
+// RUN: clang-import-test -import %S/Inputs/S.c -expression %s
+void expr() {
+ struct S MyS;
+ void *MyPtr = &MyS;
+}
diff --git a/test/Import/error-in-expression/Inputs/S.c b/test/Import/error-in-expression/Inputs/S.c
new file mode 100644
index 000000000000..8c90352bc463
--- /dev/null
+++ b/test/Import/error-in-expression/Inputs/S.c
@@ -0,0 +1,2 @@
+struct S {
+};
diff --git a/test/Import/error-in-expression/test.c b/test/Import/error-in-expression/test.c
new file mode 100644
index 000000000000..65d3b4a5dcb0
--- /dev/null
+++ b/test/Import/error-in-expression/test.c
@@ -0,0 +1,6 @@
+// RUN: not clang-import-test -import %S/Inputs/S.c -expression %s 2>&1 | FileCheck %s
+// CHECK: {{.*}}no viable conversion{{.*}}
+void expr() {
+ struct S MyS;
+ void *MyPtr = MyS;
+}
diff --git a/test/Import/error-in-import/Inputs/S.c b/test/Import/error-in-import/Inputs/S.c
new file mode 100644
index 000000000000..23ca763f6798
--- /dev/null
+++ b/test/Import/error-in-import/Inputs/S.c
@@ -0,0 +1,2 @@
+struct S [
+];
diff --git a/test/Import/error-in-import/test.c b/test/Import/error-in-import/test.c
new file mode 100644
index 000000000000..197d4e30426a
--- /dev/null
+++ b/test/Import/error-in-import/test.c
@@ -0,0 +1,6 @@
+// RUN: not clang-import-test -import %S/Inputs/S.c -expression %s 2>&1 | FileCheck %s
+// CHECK: {{.*}}expected unqualified-id{{.*}}
+void expr() {
+ struct S MyS;
+ void *MyPtr = &MyS;
+}
diff --git a/test/Import/missing-import/test.c b/test/Import/missing-import/test.c
new file mode 100644
index 000000000000..acf6389cc5fc
--- /dev/null
+++ b/test/Import/missing-import/test.c
@@ -0,0 +1,6 @@
+// RUN: not clang-import-test -import %S/Inputs/S.c -expression %s 2>&1 | FileCheck %s
+// CHECK: {{.*}}Couldn't open{{.*}}Inputs/S.c{{.*}}
+void expr() {
+ struct S MyS;
+ void *MyPtr = &MyS;
+}
diff --git a/test/Index/Core/designated-inits.c b/test/Index/Core/designated-inits.c
new file mode 100644
index 000000000000..24bb9a9acdf0
--- /dev/null
+++ b/test/Index/Core/designated-inits.c
@@ -0,0 +1,33 @@
+// RUN: c-index-test core -print-source-symbols -- %s -target x86_64-apple-macosx10.7 | FileCheck %s
+
+struct MyStruct {
+ int myfield;
+};
+
+enum {
+ MyValToSet;
+};
+
+// CHECK: [[@LINE+1]]:14 | struct/C | MyStruct |
+const struct MyStruct _MyStruct[]
+ [16]
+ [3]
+ [3]
+ [2]
+ [2] = {
+ [0] = {
+ [0] = {
+ [0] = {
+ [0][0] = {
+ [0] = {
+ // CHECK: [[@LINE+2]]:14 | field/C | myfield | {{.*}} | Ref |
+ // CHECK: [[@LINE+1]]:24 | enumerator/C | MyValToSet |
+ .myfield = MyValToSet,
+ // CHECK-NOT: | field/C | myfield |
+ // CHECK-NOT: | enumerator/C | MyValToSet |
+ },
+ },
+ },
+ },
+ },
+};
diff --git a/test/Index/Core/index-source.cpp b/test/Index/Core/index-source.cpp
index 75c6396da553..7db5d531f43d 100644
--- a/test/Index/Core/index-source.cpp
+++ b/test/Index/Core/index-source.cpp
@@ -1,9 +1,42 @@
-// RUN: c-index-test core -print-source-symbols -- %s -target x86_64-apple-macosx10.7 | FileCheck %s
+// RUN: c-index-test core -print-source-symbols -- %s -std=c++14 -target x86_64-apple-macosx10.7 | FileCheck %s
template <typename TemplArg>
class TemplCls {
-// CHECK: [[@LINE-1]]:7 | class/C++ | TemplCls | c:@ST>1#T@TemplCls | <no-cgname> | Def | rel: 0
+// CHECK: [[@LINE-1]]:7 | class(Gen)/C++ | TemplCls | c:@ST>1#T@TemplCls | <no-cgname> | Def | rel: 0
+public:
TemplCls(int x);
// CHECK: [[@LINE-1]]:3 | constructor/C++ | TemplCls | c:@ST>1#T@TemplCls@F@TemplCls#I# | <no-cgname> | Decl,RelChild | rel: 1
// CHECK-NEXT: RelChild | TemplCls | c:@ST>1#T@TemplCls
};
+
+TemplCls<int> gtv(0);
+// CHECK: [[@LINE-1]]:1 | class(Gen)/C++ | TemplCls | c:@ST>1#T@TemplCls | <no-cgname> | Ref | rel: 0
+
+template <typename T>
+class BT {
+ struct KLR {
+ int idx;
+ };
+
+ // CHECK: [[@LINE+1]]:7 | instance-method/C++ | foo |
+ KLR foo() {
+ return { .idx = 0 }; // Make sure this doesn't trigger a crash.
+ }
+};
+
+// CHECK: [[@LINE+1]]:23 | type-alias/C | size_t |
+typedef unsigned long size_t;
+// CHECK: [[@LINE+2]]:7 | function/C | operator new | c:@F@operator new#l# | __Znwm |
+// CHECK: [[@LINE+1]]:20 | type-alias/C | size_t | {{.*}} | Ref |
+void* operator new(size_t sz);
+
+// CHECK: [[@LINE+1]]:37 | variable(Gen)/C++ | tmplVar | c:index-source.cpp@VT>1#T@tmplVar | __ZL7tmplVar | Def | rel: 0
+template<typename T> static const T tmplVar = T(0);
+// CHECK: [[@LINE+1]]:29 | variable(Gen,TS)/C++ | tmplVar | c:index-source.cpp@tmplVar>#I | __ZL7tmplVarIiE | Def | rel: 0
+template<> static const int tmplVar<int> = 0;
+// CHECK: [[@LINE+2]]:5 | variable/C | gvi | c:@gvi | _gvi | Def | rel: 0
+// CHECK: [[@LINE+1]]:11 | variable(Gen,TS)/C++ | tmplVar | c:index-source.cpp@tmplVar>#I | __ZL7tmplVarIiE | Ref,Read | rel: 0
+int gvi = tmplVar<int>;
+// CHECK: [[@LINE+2]]:5 | variable/C | gvf | c:@gvf | _gvf | Def | rel: 0
+// CHECK: [[@LINE+1]]:11 | variable(Gen)/C++ | tmplVar | c:index-source.cpp@VT>1#T@tmplVar | __ZL7tmplVar | Ref,Read | rel: 0
+int gvf = tmplVar<float>;
diff --git a/test/Index/Core/index-source.m b/test/Index/Core/index-source.m
index 2e9c01c02d48..fc1b6232cfe8 100644
--- a/test/Index/Core/index-source.m
+++ b/test/Index/Core/index-source.m
@@ -95,13 +95,57 @@ extern int setjmp(jmp_buf);
@interface I3
@property (readwrite) id prop;
+// CHECK: [[@LINE+3]]:1 | instance-method/ObjC | prop | c:objc(cs)I3(im)prop | -[I3 prop] | Decl,Dyn,RelChild,RelAcc | rel: 2
+// CHECK-NEXT: RelChild | I3 | c:objc(cs)I3
+// CHECK-NEXT: RelAcc | prop | c:objc(cs)I3(py)prop
-(id)prop;
+// CHECK: [[@LINE+3]]:1 | instance-method/ObjC | setProp: | c:objc(cs)I3(im)setProp: | -[I3 setProp:] | Decl,Dyn,RelChild,RelAcc | rel: 2
+// CHECK-NEXT: RelChild | I3 | c:objc(cs)I3
+// CHECK-NEXT: RelAcc | prop | c:objc(cs)I3(py)prop
-(void)setProp:(id)p;
@end
+// CHECK: [[@LINE+1]]:17 | class/ObjC | I3 | c:objc(cs)I3 | <no-cgname> | Def | rel: 0
@implementation I3
// CHECK: [[@LINE+3]]:13 | instance-property/ObjC | prop | c:objc(cs)I3(py)prop | <no-cgname> | Ref | rel: 0
// CHECK: [[@LINE+2]]:13 | instance-method/ObjC | prop | c:objc(cs)I3(im)prop | -[I3 prop] | Def,RelChild | rel: 1
// CHECK: [[@LINE+1]]:13 | instance-method/ObjC | setProp: | c:objc(cs)I3(im)setProp: | -[I3 setProp:] | Def,RelChild | rel: 1
@synthesize prop = _prop;
@end
+
+// CHECK: [[@LINE+5]]:12 | class/ObjC | I3 | c:objc(cs)I3 | _OBJC_CLASS_$_I3 | Ref,RelExt | rel: 1
+// CHECK-NEXT: RelExt | bar | c:objc(cy)I3@bar
+// CHECK: [[@LINE+3]]:15 | extension/ObjC | bar | c:objc(cy)I3@bar | <no-cgname> | Decl | rel: 0
+// CHECK: [[@LINE+2]]:21 | protocol/ObjC | Prot1 | c:objc(pl)Prot1 | <no-cgname> | Ref,RelBase | rel: 1
+// CHECK-NEXT: RelBase | bar | c:objc(cy)I3@bar
+@interface I3(bar) <Prot1>
+@end
+
+// CHECK: [[@LINE+2]]:17 | class/ObjC | I3 | c:objc(cs)I3 | _OBJC_CLASS_$_I3 | Ref | rel: 0
+// CHECK: [[@LINE+1]]:20 | extension/ObjC | I3 | c:objc(cy)I3@bar | <no-cgname> | Def | rel: 0
+@implementation I3(bar)
+@end
+
+// CHECK: [[@LINE+1]]:12 | extension/ObjC | <no-name> | <no-usr> | <no-cgname> | Decl | rel: 0
+@interface NonExistent()
+@end
+
+@interface MyGenCls<ObjectType> : Base
+@end
+
+@protocol MyEnumerating
+@end
+
+// CHECK: [[@LINE+4]]:41 | type-alias/C | MyEnumerator | c:index-source.m@T@MyEnumerator | <no-cgname> | Def | rel: 0
+// CHECK: [[@LINE+3]]:26 | protocol/ObjC | MyEnumerating | c:objc(pl)MyEnumerating | <no-cgname> | Ref | rel: 0
+// CHECK: [[@LINE+2]]:9 | class/ObjC | MyGenCls | c:objc(cs)MyGenCls | _OBJC_CLASS_$_MyGenCls | Ref | rel: 0
+// CHECK: [[@LINE+1]]:18 | class/ObjC | Base | c:objc(cs)Base | _OBJC_CLASS_$_Base | Ref | rel: 0
+typedef MyGenCls<Base *><MyEnumerating> MyEnumerator;
+
+// CHECK: [[@LINE+5]]:12 | class/ObjC | PermanentEnumerator | c:objc(cs)PermanentEnumerator | _OBJC_CLASS_$_PermanentEnumerator | Decl | rel: 0
+// CHECK: [[@LINE+4]]:34 | class/ObjC | MyGenCls | c:objc(cs)MyGenCls | _OBJC_CLASS_$_MyGenCls | Ref,RelBase | rel: 1
+// CHECK-NEXT: RelBase | PermanentEnumerator | c:objc(cs)PermanentEnumerator
+// CHECK: [[@LINE+2]]:34 | protocol/ObjC | MyEnumerating | c:objc(pl)MyEnumerating | <no-cgname> | Ref,RelBase | rel: 1
+// CHECK-NEXT: RelBase | PermanentEnumerator | c:objc(cs)PermanentEnumerator
+@interface PermanentEnumerator : MyEnumerator
+@end
diff --git a/test/Index/Core/index-subkinds.m b/test/Index/Core/index-subkinds.m
index e668d84ffa89..38be73b31e91 100644
--- a/test/Index/Core/index-subkinds.m
+++ b/test/Index/Core/index-subkinds.m
@@ -26,10 +26,13 @@
-(void)testIt2 {}
@end
-// CHECK: [[@LINE+1]]:12 | extension/ObjC | cat | c:objc(cy)MyTestCase@cat | <no-cgname> | Decl | rel: 0
+// CHECK: [[@LINE+3]]:12 | class(test)/ObjC | MyTestCase | c:objc(cs)MyTestCase | _OBJC_CLASS_$_MyTestCase | Ref,RelExt | rel: 1
+// CHECK-NEXT: RelExt | cat | c:objc(cy)MyTestCase@cat
+// CHECK: [[@LINE+1]]:23 | extension/ObjC | cat | c:objc(cy)MyTestCase@cat | <no-cgname> | Decl | rel: 0
@interface MyTestCase(cat)
@end
-// CHECK: [[@LINE+1]]:17 | extension/ObjC | MyTestCase | c:objc(cy)MyTestCase@cat | <no-cgname> | Def | rel: 0
+// CHECK: [[@LINE+2]]:17 | class(test)/ObjC | MyTestCase | c:objc(cs)MyTestCase | _OBJC_CLASS_$_MyTestCase | Ref | rel: 0
+// CHECK: [[@LINE+1]]:28 | extension/ObjC | MyTestCase | c:objc(cy)MyTestCase@cat | <no-cgname> | Def | rel: 0
@implementation MyTestCase(cat)
// CHECK: [[@LINE+1]]:1 | instance-method(test)/ObjC | testInCat | c:objc(cs)MyTestCase(im)testInCat | -[MyTestCase(cat) testInCat] | Def,Dyn,RelChild | rel: 1
- (void)testInCat {}
@@ -38,7 +41,8 @@
@class NSButton;
@interface IBCls
-// CHECK: [[@LINE+2]]:34 | instance-method/ObjC | prop | c:objc(cs)IBCls(im)prop | -[IBCls prop] | Decl,Dyn,RelChild | rel: 1
+
+// CHECK: [[@LINE+2]]:34 | instance-method/ObjC | prop | c:objc(cs)IBCls(im)prop | -[IBCls prop] | Decl,Dyn,RelChild,RelAcc | rel: 2
// CHECK: [[@LINE+1]]:34 | instance-property(IB)/ObjC | prop | c:objc(cs)IBCls(py)prop | <no-cgname> | Decl,RelChild | rel: 1
@property (readonly) IBOutlet id prop;
// CHECK: [[@LINE+1]]:54 | instance-property(IB,IBColl)/ObjC | propColl | c:objc(cs)IBCls(py)propColl | <no-cgname> | Decl,RelChild | rel: 1
@@ -46,3 +50,11 @@
// CHECK: [[@LINE+1]]:1 | instance-method(IB)/ObjC | doIt | c:objc(cs)IBCls(im)doIt | -[IBCls doIt] | Decl,Dyn,RelChild | rel: 1
-(IBAction)doIt;
@end
+
+
+#define GKInspectable __attribute__((annotate("gk_inspectable")))
+
+@interface GKI
+// CHECK: [[@LINE+1]]:40 | instance-property(GKI)/ObjC | gkIntProp | c:objc(cs)GKI(py)gkIntProp | <no-cgname> | Decl,RelChild | rel: 1
+@property (readonly) GKInspectable int gkIntProp;
+@end
diff --git a/test/Index/annotate-tokens.c b/test/Index/annotate-tokens.c
index c72e4f725fcc..08e7a9a02f8f 100644
--- a/test/Index/annotate-tokens.c
+++ b/test/Index/annotate-tokens.c
@@ -239,3 +239,7 @@ void test() {
// CHECK-RANGE2: Identifier: "reg" [68:3 - 68:6] DeclRefExpr=reg:67:7
// CHECK-RANGE2: Punctuation: "." [68:6 - 68:7] MemberRefExpr=field:62:9
// CHECK-RANGE2: Identifier: "field" [68:7 - 68:12] MemberRefExpr=field:62:9
+
+// RUN: c-index-test -test-annotate-tokens=%s:68:15:68:16 %s | FileCheck %s -check-prefix=CHECK-RANGE3
+// CHECK-RANGE3: Literal: "1" [68:15 - 68:16] IntegerLiteral=
+// CHECK-RANGE3-NOT: Punctuation: ";"
diff --git a/test/Index/comment-cplus-decls.cpp b/test/Index/comment-cplus-decls.cpp
index 002482ed0f35..d4f968f5fbf0 100644
--- a/test/Index/comment-cplus-decls.cpp
+++ b/test/Index/comment-cplus-decls.cpp
@@ -40,7 +40,7 @@ protected:
data* reserved;
};
// CHECK: <Declaration>class Test {}</Declaration>
-// CHECK: <Declaration>Test() : reserved(new Test::data())</Declaration>
+// CHECK: <Declaration>Test() : reserved(new Test::data()) {}</Declaration>
// CHECK: <Declaration>unsigned int getID() const</Declaration>
// CHECK: <Declaration>~Test()</Declaration>
// CHECK: <Declaration>Test::data *reserved</Declaration>
diff --git a/test/Index/comment-to-html-xml-conversion.cpp b/test/Index/comment-to-html-xml-conversion.cpp
index 6c10efedeaf0..9e25ff1b3ace 100644
--- a/test/Index/comment-to-html-xml-conversion.cpp
+++ b/test/Index/comment-to-html-xml-conversion.cpp
@@ -813,7 +813,7 @@ void comment_to_xml_conversion_10(T aaa, U bbb);
template<>
void comment_to_xml_conversion_10(int aaa, int bbb);
-// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-2]]:6: FunctionDecl=comment_to_xml_conversion_10:{{.*}} FullCommentAsXML=[<Function templateKind="specialization" file="{{[^"]+}}comment-to-html-xml-conversion.cpp" line="[[@LINE-2]]" column="6"><Name>comment_to_xml_conversion_10</Name><USR>c:@F@comment_to_xml_conversion_10&lt;#I#I&gt;#I#I#</USR><Declaration>void comment_to_xml_conversion_10(int aaa, int bbb)</Declaration><Abstract><Para> Aaa.</Para></Abstract></Function>]
+// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-2]]:6: FunctionDecl=comment_to_xml_conversion_10:{{.*}} FullCommentAsXML=[<Function templateKind="specialization" file="{{[^"]+}}comment-to-html-xml-conversion.cpp" line="[[@LINE-2]]" column="6"><Name>comment_to_xml_conversion_10</Name><USR>c:@F@comment_to_xml_conversion_10&lt;#I#I&gt;#I#I#</USR><Declaration>template &lt;&gt; void comment_to_xml_conversion_10&lt;int, int&gt;(int aaa, int bbb)</Declaration><Abstract><Para> Aaa.</Para></Abstract></Function>]
/// Aaa.
template<typename T, typename U>
@@ -825,13 +825,13 @@ class comment_to_xml_conversion_11 { };
template<typename T>
class comment_to_xml_conversion_11<T, int> { };
-// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-2]]:7: ClassTemplatePartialSpecialization=comment_to_xml_conversion_11:{{.*}} FullCommentAsXML=[<Class templateKind="partialSpecialization" file="{{[^"]+}}comment-to-html-xml-conversion.cpp" line="[[@LINE-2]]" column="7"><Name>comment_to_xml_conversion_11</Name><USR>c:@SP&gt;1#T@comment_to_xml_conversion_11&gt;#t0.0#I</USR><Declaration>class comment_to_xml_conversion_11 {}</Declaration><Abstract><Para> Aaa.</Para></Abstract></Class>]
+// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-2]]:7: ClassTemplatePartialSpecialization=comment_to_xml_conversion_11:{{.*}} FullCommentAsXML=[<Class templateKind="partialSpecialization" file="{{[^"]+}}comment-to-html-xml-conversion.cpp" line="[[@LINE-2]]" column="7"><Name>comment_to_xml_conversion_11</Name><USR>c:@SP&gt;1#T@comment_to_xml_conversion_11&gt;#t0.0#I</USR><Declaration>template &lt;typename T&gt; class comment_to_xml_conversion_11&lt;T, int&gt; {}</Declaration><Abstract><Para> Aaa.</Para></Abstract></Class>]
/// Aaa.
template<>
class comment_to_xml_conversion_11<int, int> { };
-// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-2]]:7: ClassDecl=comment_to_xml_conversion_11:{{.*}} FullCommentAsXML=[<Class templateKind="specialization" file="{{[^"]+}}comment-to-html-xml-conversion.cpp" line="[[@LINE-2]]" column="7"><Name>comment_to_xml_conversion_11</Name><USR>c:@S@comment_to_xml_conversion_11&gt;#I#I</USR><Declaration>class comment_to_xml_conversion_11 {}</Declaration><Abstract><Para> Aaa.</Para></Abstract></Class>]
+// CHECK: comment-to-html-xml-conversion.cpp:[[@LINE-2]]:7: ClassDecl=comment_to_xml_conversion_11:{{.*}} FullCommentAsXML=[<Class templateKind="specialization" file="{{[^"]+}}comment-to-html-xml-conversion.cpp" line="[[@LINE-2]]" column="7"><Name>comment_to_xml_conversion_11</Name><USR>c:@S@comment_to_xml_conversion_11&gt;#I#I</USR><Declaration>template &lt;&gt; class comment_to_xml_conversion_11&lt;int, int&gt; {}</Declaration><Abstract><Para> Aaa.</Para></Abstract></Class>]
/// Aaa.
int comment_to_xml_conversion_12;
diff --git a/test/Index/complete-block-properties.m b/test/Index/complete-block-properties.m
new file mode 100644
index 000000000000..d166147294e1
--- /dev/null
+++ b/test/Index/complete-block-properties.m
@@ -0,0 +1,88 @@
+// Note: the run lines follow their respective tests, since line/column
+// matter in this test.
+
+// Block invocations should be presented when completing properties in
+// standalone statements.
+// rdar://28846196
+
+typedef int Foo;
+typedef void (^FooBlock)(Foo *someParameter);
+typedef int (^BarBlock)(int *);
+
+@interface Obj
+
+@property (readwrite, nonatomic, copy) void (^block)();
+@property (readonly, nonatomic, copy) int (^performA)();
+@property (readonly, nonatomic, copy) int (^performB)(int x, int y);
+@property (readwrite, nonatomic, copy) Foo (^blocker)(int x, Foo y, FooBlock foo);
+
+@end
+
+
+@interface Test : Obj
+
+@property (readonly, nonatomic, copy) FooBlock fooBlock;
+@property (readonly, nonatomic, copy) BarBlock barBlock;
+@property (readonly, nonatomic, copy) Test * (^getObject)(int index);
+@property (readwrite, nonatomic) int foo;
+
+@end
+
+@implementation Test
+
+- (void)test {
+ self.foo = 2;
+ int x = self.performA(); self.foo = 2;
+ self.getObject(0).foo = 2;
+}
+
+// RUN: c-index-test -code-completion-at=%s:34:8 %s | FileCheck -check-prefix=CHECK-CC1 %s
+// RUN: c-index-test -code-completion-at=%s:35:33 %s | FileCheck -check-prefix=CHECK-CC1 %s
+// RUN: c-index-test -code-completion-at=%s:36:21 %s | FileCheck -check-prefix=CHECK-CC1 %s
+//CHECK-CC1: ObjCPropertyDecl:{ResultType int}{TypedText barBlock}{LeftParen (}{Placeholder int *}{RightParen )} (35)
+//CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType void}{TypedText block}{LeftParen (}{RightParen )} (35)
+//CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType void (^)()}{TypedText block}{Equal = }{Placeholder ^(void)} (38)
+//CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType Foo}{TypedText blocker}{LeftParen (}{Placeholder int x}{Comma , }{Placeholder Foo y}{Comma , }{Placeholder ^(Foo *someParameter)foo}{RightParen )} (35)
+//CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType Foo (^)(int, Foo, FooBlock)}{TypedText blocker}{Equal = }{Placeholder ^Foo(int x, Foo y, FooBlock foo)} (38)
+//CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType int}{TypedText foo} (35)
+//CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType void}{TypedText fooBlock}{LeftParen (}{Placeholder Foo *someParameter}{RightParen )} (35)
+//CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType Test *}{TypedText getObject}{LeftParen (}{Placeholder int index}{RightParen )} (35)
+//CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType int}{TypedText performA}{LeftParen (}{RightParen )} (35)
+//CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType int}{TypedText performB}{LeftParen (}{Placeholder int x}{Comma , }{Placeholder int y}{RightParen )} (35)
+
+@end
+
+// rdar://25224416
+
+@interface NoQualifierParens
+
+@property(copy) void (^blockProperty)(void);
+@property BarBlock blockProperty2;
+
+@end
+
+void noQualifierParens(NoQualifierParens *f) {
+ [f setBlockProperty: ^{}];
+}
+
+// RUN: c-index-test -code-completion-at=%s:65:6 %s | FileCheck -check-prefix=CHECK-CC2 %s
+//CHECK-CC2: ObjCInstanceMethodDecl:{ResultType void (^)(void)}{TypedText blockProperty} (35)
+//CHECK-CC2-NEXT: ObjCInstanceMethodDecl:{ResultType BarBlock}{TypedText blockProperty2} (35)
+//CHECK-CC2-NEXT: ObjCInstanceMethodDecl:{ResultType void}{TypedText setBlockProperty2:}{Placeholder BarBlock blockProperty2} (35)
+//CHECK-CC2-NEXT: ObjCInstanceMethodDecl:{ResultType void}{TypedText setBlockProperty:}{Placeholder void (^)(void)blockProperty} (35)
+
+@interface ClassProperties
+
+@property(class) void (^explicit)();
+@property(class, readonly) void (^explicitReadonly)();
+
+@end
+
+void classBlockProperties() {
+ ClassProperties.explicit;
+}
+
+// RUN: c-index-test -code-completion-at=%s:82:19 %s | FileCheck -check-prefix=CHECK-CC3 %s
+//CHECK-CC3: ObjCPropertyDecl:{ResultType void}{TypedText explicit}{LeftParen (}{RightParen )} (35)
+//CHECK-CC3-NEXT: ObjCPropertyDecl:{ResultType void (^)()}{TypedText explicit}{Equal = }{Placeholder ^(void)} (38)
+//CHECK-CC3-NEXT: ObjCPropertyDecl:{ResultType void}{TypedText explicitReadonly}{LeftParen (}{RightParen )} (35)
diff --git a/test/Index/complete-block-property-assignment.m b/test/Index/complete-block-property-assignment.m
new file mode 100644
index 000000000000..ced3b7fa1302
--- /dev/null
+++ b/test/Index/complete-block-property-assignment.m
@@ -0,0 +1,68 @@
+// Note: the run lines follow their respective tests, since line/column
+// matter in this test.
+
+// rdar://28481726
+
+void func(int x);
+typedef int Foo;
+typedef void (^FooBlock)(Foo *someParameter);
+
+@interface Obj
+@property (readwrite, nonatomic, copy) void (^onAction)(Obj *object);
+@property (readwrite, nonatomic) int foo;
+@end
+
+@interface Test : Obj
+@property (readwrite, nonatomic, copy) FooBlock onEventHandler;
+@property (readonly, nonatomic, copy) void (^onReadonly)(int *someParameter);
+@property (readonly, nonatomic, strong) Obj *obj;
+@end
+
+@implementation Test
+
+#define SELFY self
+
+- (void)test {
+ self.foo = 2;
+ [self takeInt: 2]; self.foo = 2;
+ /* Comment */ self.foo = 2;
+ SELFY.foo = 2
+}
+
+// RUN: c-index-test -code-completion-at=%s:26:8 %s | FileCheck -check-prefix=CHECK-CC1 %s
+// RUN: c-index-test -code-completion-at=%s:27:27 %s | FileCheck -check-prefix=CHECK-CC1 %s
+// RUN: c-index-test -code-completion-at=%s:28:22 %s | FileCheck -check-prefix=CHECK-CC1 %s
+// RUN: c-index-test -code-completion-at=%s:29:9 %s | FileCheck -check-prefix=CHECK-CC1 %s
+// CHECK-CC1: ObjCPropertyDecl:{ResultType int}{TypedText foo} (35)
+// CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType Obj *}{TypedText obj} (35)
+// CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType void}{TypedText onAction}{LeftParen (}{Placeholder Obj *object}{RightParen )} (35)
+// CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType void (^)(Obj *)}{TypedText onAction}{Equal = }{Placeholder ^(Obj *object)} (38)
+// CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType void}{TypedText onEventHandler}{LeftParen (}{Placeholder Foo *someParameter}{RightParen )} (35)
+// CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType FooBlock}{TypedText onEventHandler}{Equal = }{Placeholder ^(Foo *someParameter)} (38)
+// CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType void}{TypedText onReadonly}{LeftParen (}{Placeholder int *someParameter}{RightParen )} (35)
+
+- (void) takeInt:(int)x { }
+
+- (int) testFailures {
+ (self.foo);
+ int x = self.foo;
+ [self takeInt: self.foo];
+ if (self.foo) {
+ func(self.foo);
+ }
+ return self.foo;
+}
+
+// RUN: c-index-test -code-completion-at=%s:47:9 %s | FileCheck -check-prefix=CHECK-NO %s
+// RUN: c-index-test -code-completion-at=%s:48:16 %s | FileCheck -check-prefix=CHECK-NO %s
+// RUN: c-index-test -code-completion-at=%s:49:23 %s | FileCheck -check-prefix=CHECK-NO %s
+// RUN: c-index-test -code-completion-at=%s:50:12 %s | FileCheck -check-prefix=CHECK-NO %s
+// RUN: c-index-test -code-completion-at=%s:51:15 %s | FileCheck -check-prefix=CHECK-NO %s
+// RUN: c-index-test -code-completion-at=%s:53:15 %s | FileCheck -check-prefix=CHECK-NO %s
+// CHECK-NO: ObjCPropertyDecl:{ResultType int}{TypedText foo} (35)
+// CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType Obj *}{TypedText obj} (35)
+// CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType void (^)(Obj *)}{TypedText onAction} (35)
+// CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType FooBlock}{TypedText onEventHandler} (35)
+// CHECK-NO-NEXT: ObjCPropertyDecl:{ResultType void (^)(int *)}{TypedText onReadonly} (35)
+
+@end
diff --git a/test/Index/complete-kvc.m b/test/Index/complete-kvc.m
index 336d41d759a1..6adea0c57518 100644
--- a/test/Index/complete-kvc.m
+++ b/test/Index/complete-kvc.m
@@ -97,7 +97,7 @@ typedef signed char BOOL;
// RUN: c-index-test -code-completion-at=%s:41:3 %s | FileCheck -check-prefix=CHECK-CC2 %s
// CHECK-CC2: ObjCClassMethodDecl:{LeftParen (}{Text BOOL}{RightParen )}{TypedText automaticallyNotifiesObserversOfArrayProperty} (40)
// CHECK-CC2: ObjCClassMethodDecl:{LeftParen (}{Text BOOL}{RightParen )}{TypedText automaticallyNotifiesObserversOfMutableArrayProperty} (40)
-// CHECK-CC2: ObjCClassMethodDecl:{LeftParen (}{Text NSSet *}{RightParen )}{TypedText keyPathsForValuesAffectingMutableArrayProperty} (40)
+// CHECK-CC2: ObjCClassMethodDecl:{LeftParen (}{Text NSSet<NSString *> *}{RightParen )}{TypedText keyPathsForValuesAffectingMutableArrayProperty} (40)
// RUN: c-index-test -code-completion-at=%s:52:8 %s | FileCheck -check-prefix=CHECK-CC3 %s
// CHECK-CC3: ObjCInstanceMethodDecl:{TypedText countOfIntProperty} (55)
diff --git a/test/Index/complete-method-decls.m b/test/Index/complete-method-decls.m
index 41134081e155..8a1714226664 100644
--- a/test/Index/complete-method-decls.m
+++ b/test/Index/complete-method-decls.m
@@ -195,7 +195,7 @@ typedef A *MyObjectRef;
// CHECK-CCG: NotImplemented:{TypedText void} (50)
// CHECK-CCG: NotImplemented:{TypedText volatile} (50)
// RUN: c-index-test -code-completion-at=%s:60:24 %s | FileCheck -check-prefix=CHECK-CCF %s
-// RUN: c-index-test -code-completion-at=%s:60:26 %s | FileCheck -check-prefix=CHECK-CCH %s
+// RUN: c-index-test -code-completion-at=%s:60:27 %s | FileCheck -check-prefix=CHECK-CCH %s
// CHECK-CCH: ObjCInterfaceDecl:{TypedText A} (50)
// CHECK-CCH: ObjCInterfaceDecl:{TypedText B} (50)
// CHECK-CCH: NotImplemented:{TypedText bycopy} (40)
diff --git a/test/Index/complete-objc-message-id.m b/test/Index/complete-objc-message-id.m
index 415e0ff02195..044c82851d99 100644
--- a/test/Index/complete-objc-message-id.m
+++ b/test/Index/complete-objc-message-id.m
@@ -68,7 +68,7 @@ void message_qualified_id(id<P2> ip2) {
// CHECK-SELECTOR-PREF: ObjCClassMethodDecl:{ResultType id}{TypedText new} (35)
// CHECK-SELECTOR-PREF: ObjCClassMethodDecl:{ResultType Class}{TypedText superclass} (35)
-// RUN: c-index-test -code-completion-at=%s:46:7 %s | FileCheck -check-prefix=CHECK-INSTANCE-QUAL-ID %s
-// RUN: c-index-test -code-completion-at=%s:47:7 %s | FileCheck -check-prefix=CHECK-INSTANCE-QUAL-ID %s
+// RUN: c-index-test -code-completion-at=%s:46:8 %s | FileCheck -check-prefix=CHECK-INSTANCE-QUAL-ID %s
+// RUN: c-index-test -code-completion-at=%s:47:8 %s | FileCheck -check-prefix=CHECK-INSTANCE-QUAL-ID %s
// CHECK-INSTANCE-QUAL-ID: ObjCInstanceMethodDecl:{ResultType int}{TypedText P1_method1} (37)
// CHECK-INSTANCE-QUAL-ID: ObjCInstanceMethodDecl:{ResultType int}{TypedText P2_method1} (35)
diff --git a/test/Index/complete-objc-message.m b/test/Index/complete-objc-message.m
index 193f1f8bf228..e3fce6bc20f8 100644
--- a/test/Index/complete-objc-message.m
+++ b/test/Index/complete-objc-message.m
@@ -218,13 +218,13 @@ void test_Nullability(Nullability *n, A* a) {
// CHECK-CC2-NEXT: Container Kind: ObjCInterfaceDecl
// CHECK-CC2-NEXT: Container is complete
// CHECK-CC2-NEXT: Container USR: c:objc(cs)Foo
-// RUN: c-index-test -code-completion-at=%s:61:16 %s | FileCheck -check-prefix=CHECK-CC3 %s
+// RUN: c-index-test -code-completion-at=%s:61:17 %s | FileCheck -check-prefix=CHECK-CC3 %s
// CHECK-CC3: ObjCClassMethodDecl:{ResultType int}{TypedText MyClassMethod:}{Placeholder (id)}
// CHECK-CC3: ObjCClassMethodDecl:{ResultType int}{TypedText MyPrivateMethod}
-// RUN: c-index-test -code-completion-at=%s:65:16 %s | FileCheck -check-prefix=CHECK-CC4 %s
+// RUN: c-index-test -code-completion-at=%s:65:17 %s | FileCheck -check-prefix=CHECK-CC4 %s
// CHECK-CC4: ObjCInstanceMethodDecl:{ResultType int}{TypedText MyInstMethod:}{Placeholder (id)}{HorizontalSpace }{TypedText second:}{Placeholder (id)}
// CHECK-CC4: ObjCInstanceMethodDecl:{ResultType int}{TypedText MyPrivateInstMethod}
-// RUN: c-index-test -code-completion-at=%s:74:9 %s | FileCheck -check-prefix=CHECK-CC5 %s
+// RUN: c-index-test -code-completion-at=%s:74:10 %s | FileCheck -check-prefix=CHECK-CC5 %s
// CHECK-CC5: ObjCInstanceMethodDecl:{ResultType int}{TypedText MyInstMethod:}{Placeholder (id)}{HorizontalSpace }{TypedText second:}{Placeholder (id)}
// CHECK-CC5: ObjCInstanceMethodDecl:{ResultType int}{TypedText MySubInstMethod}
// RUN: c-index-test -code-completion-at=%s:82:8 %s | FileCheck -check-prefix=CHECK-CC6 %s
@@ -311,7 +311,7 @@ void test_Nullability(Nullability *n, A* a) {
// CHECK-CCI: ObjCInstanceMethodDecl:{ResultType void}{TypedText method1} (37)
// CHECK-CCI: ObjCInstanceMethodDecl:{ResultType void}{TypedText method2} (35)
-// RUN: c-index-test -code-completion-at=%s:150:5 %s | FileCheck -check-prefix=CHECK-REDUNDANT %s
+// RUN: c-index-test -code-completion-at=%s:150:6 %s | FileCheck -check-prefix=CHECK-REDUNDANT %s
// CHECK-REDUNDANT: ObjCInstanceMethodDecl:{ResultType void}{TypedText method2} (35)
// CHECK-REDUNDANT-NOT: ObjCInstanceMethodDecl:{ResultType void}{TypedText method2}
// CHECK-REDUNDANT: ObjCInstanceMethodDecl:{ResultType void}{TypedText method3} (35)
diff --git a/test/Index/complete-properties.m b/test/Index/complete-properties.m
index a4450563698e..0c49819ac2a7 100644
--- a/test/Index/complete-properties.m
+++ b/test/Index/complete-properties.m
@@ -94,3 +94,84 @@ id test(I3 *i3) {
// RUN: c-index-test -code-completion-at=%s:57:13 -fobjc-nonfragile-abi %s | FileCheck -check-prefix=CHECK-CC8 %s
// CHECK-CC8: ObjCPropertyDecl:{ResultType int}{TypedText Prop5} (35)
+
+@interface ClassProperties
+
+@property int instanceProperty;
+@property(class) int explicit;
+@property(class, readonly) int explicitReadonly;
+
++ (int)implicit;
++ (int)setImplicit:(int)x;
+
++ (int)implicitReadonly;
+
++ (void)noProperty;
+
+- (int)implicitInstance;
+
++ (int)shadowedImplicit;
+
+@end
+
+@interface ClassProperties (Category)
+
++ (int)implicitInCategory;
+
+@end
+
+@protocol ProtocolClassProperties
+
+@property(class, readonly) int explicitInProtocol;
+
+@end
+
+@interface SubClassProperties: ClassProperties <ProtocolClassProperties>
+
+@property(class) ClassProperties *shadowedImplicit;
+
+@end
+
+@implementation SubClassProperties
+
+-(void) foo {
+ super.instanceProperty;
+}
+
+@end
+
+void classProperties() {
+ (void)ClassProperties.implicit;
+ (void)SubClassProperties.explicit;
+}
+
+// RUN: c-index-test -code-completion-at=%s:144:25 -fobjc-nonfragile-abi %s | FileCheck -check-prefix=CHECK-CC9 %s
+// CHECK-CC9: ObjCPropertyDecl:{ResultType int}{TypedText explicit} (35)
+// CHECK-CC9-NEXT: ObjCPropertyDecl:{ResultType int}{TypedText explicitReadonly} (35)
+// CHECK-CC9-NEXT: ObjCClassMethodDecl:{ResultType int}{TypedText implicit} (37)
+// CHECK-CC9-NEXT: ObjCClassMethodDecl:{ResultType int}{TypedText implicitInCategory} (37)
+// CHECK-CC9-NEXT: ObjCClassMethodDecl:{ResultType int}{TypedText implicitReadonly} (37)
+// CHECK-CC9-NEXT: ObjCClassMethodDecl:{ResultType int}{TypedText shadowedImplicit} (37)
+// CHECK-CC9-NOT: implicitInstance
+// CHECK-CC9-NOT: noProperty
+// CHECK-CC9-NOT: instanceProperty
+
+// RUN: c-index-test -code-completion-at=%s:145:28 -fobjc-nonfragile-abi %s | FileCheck -check-prefix=CHECK-CC10 %s
+// CHECK-CC10: ObjCPropertyDecl:{ResultType int}{TypedText explicit} (35)
+// CHECK-CC10-NEXT: ObjCPropertyDecl:{ResultType int}{TypedText explicitInProtocol} (35)
+// CHECK-CC10-NEXT: ObjCPropertyDecl:{ResultType int}{TypedText explicitReadonly} (35)
+// CHECK-CC10-NEXT: ObjCClassMethodDecl:{ResultType int}{TypedText implicit} (37)
+// CHECK-CC10-NEXT: ObjCClassMethodDecl:{ResultType int}{TypedText implicitInCategory} (37)
+// CHECK-CC10-NEXT: ObjCClassMethodDecl:{ResultType int}{TypedText implicitReadonly} (37)
+// CHECK-CC10-NEXT: ObjCPropertyDecl:{ResultType ClassProperties *}{TypedText shadowedImplicit} (35)
+// CHECK-CC10-NOT: implicitInstance
+// CHECK-CC10-NOT: noProperty
+// CHECK-CC10-NOT: instanceProperty
+
+// RUN: c-index-test -code-completion-at=%s:138:9 -fobjc-nonfragile-abi %s | FileCheck -check-prefix=CHECK-CC11 %s
+// CHECK-CC11-NOT: explicit
+// CHECK-CC11-NOT: explicitReadonly
+// CHECK-CC11-NOT: implicit
+// CHECK-CC11-NOT: implicitReadonly
+// CHECK-CC11-NOT: shadowedImplicit
+// CHECK-CC11-NOT: implicitInCategory
diff --git a/test/Index/complete-recovery.m b/test/Index/complete-recovery.m
index ec5bf8af6ab1..bd920eb3ac6e 100644
--- a/test/Index/complete-recovery.m
+++ b/test/Index/complete-recovery.m
@@ -26,7 +26,7 @@
// Test case for fix committed in r145441.
// RUN: env CINDEXTEST_CODE_COMPLETE_PATTERNS=1 c-index-test -code-completion-at=%s:9:20 %s -fms-compatibility | FileCheck -check-prefix=CHECK-CC1 %s
-// RUN: env CINDEXTEST_CODE_COMPLETE_PATTERNS=1 c-index-test -code-completion-at=%s:10:24 %s | FileCheck -check-prefix=CHECK-CC2 %s
+// RUN: env CINDEXTEST_CODE_COMPLETE_PATTERNS=1 c-index-test -code-completion-at=%s:10:25 %s | FileCheck -check-prefix=CHECK-CC2 %s
// CHECK-CC2: NotImplemented:{ResultType char[]}{TypedText @encode}{LeftParen (}{Placeholder type-name}{RightParen )}
// CHECK-CC2: NotImplemented:{TypedText _Bool}
// CHECK-CC2: VarDecl:{ResultType A *}{TypedText a}
diff --git a/test/Index/complete-super.m b/test/Index/complete-super.m
index be7edfdef834..952ffbc6fd00 100644
--- a/test/Index/complete-super.m
+++ b/test/Index/complete-super.m
@@ -60,7 +60,7 @@ typedef int Bool;
// RUN: c-index-test -code-completion-at=%s:20:16 %s | FileCheck -check-prefix=CHECK-ADD-TO %s
// CHECK-ADD-TO: ObjCInstanceMethodDecl:{ResultType void}{Informative add:}{TypedText to:}{Placeholder b} (20)
-// RUN: c-index-test -code-completion-at=%s:24:28 %s | FileCheck -check-prefix=CHECK-SELECTOR-FIRST %s
+// RUN: c-index-test -code-completion-at=%s:24:29 %s | FileCheck -check-prefix=CHECK-SELECTOR-FIRST %s
// CHECK-SELECTOR-FIRST: ObjCClassMethodDecl:{ResultType void}{Informative select:}{TypedText first:}{Placeholder a}{HorizontalSpace }{Text second:}{Placeholder b} (20)
// Check "super" completion at the third identifier
@@ -69,7 +69,7 @@ typedef int Bool;
// Check "super" completion with missing '['.
// RUN: c-index-test -code-completion-at=%s:25:10 %s | FileCheck -check-prefix=CHECK-SELECTOR-SELECTOR %s
-// RUN: c-index-test -code-completion-at=%s:25:28 %s | FileCheck -check-prefix=CHECK-SELECTOR-FIRST %s
+// RUN: c-index-test -code-completion-at=%s:25:29 %s | FileCheck -check-prefix=CHECK-SELECTOR-FIRST %s
// RUN: c-index-test -code-completion-at=%s:25:37 %s | FileCheck -check-prefix=CHECK-SELECTOR-SECOND %s
// Check "super" completion for a method declared in a category.
diff --git a/test/Index/evaluate-cursor.cpp b/test/Index/evaluate-cursor.cpp
index 28a9c368795a..39fc9db98a3e 100644
--- a/test/Index/evaluate-cursor.cpp
+++ b/test/Index/evaluate-cursor.cpp
@@ -15,6 +15,12 @@ void goo() {
int a = __LINE__;
}
+unsigned long long foo_int = 1ull << 60;
+
+unsigned long long HUGE = 1ull << 63;
+
+long long HUGE_NEG = -(1ll << 35);
+
// RUN: c-index-test -evaluate-cursor-at=%s:4:7 \
// RUN: -evaluate-cursor-at=%s:8:7 \
// RUN: -evaluate-cursor-at=%s:8:11 -std=c++11 %s | FileCheck %s
@@ -28,3 +34,11 @@ void goo() {
// CHECK-MACRO: [function macro]
// CHECK-MACRO: [function macro]
// CHECK-MACRO: [builtin macro]
+
+// RUN: c-index-test -evaluate-cursor-at=%s:18:20 \
+// RUN: -evaluate-cursor-at=%s:20:20 \
+// RUN: -evaluate-cursor-at=%s:22:11 \
+// RUN: -std=c++11 %s | FileCheck -check-prefix=CHECK-LONG %s
+// CHECK-LONG: unsigned, Value: 1152921504606846976
+// CHECK-LONG: unsigned, Value: 9223372036854775808
+// CHECK-LONG: Value: -34359738368
diff --git a/test/Index/get-cursor.cpp b/test/Index/get-cursor.cpp
index a2c46937e48e..27f75938fedd 100644
--- a/test/Index/get-cursor.cpp
+++ b/test/Index/get-cursor.cpp
@@ -143,6 +143,8 @@ void test(TestColl coll) {
}
}
+const int operator""_toint(unsigned long long val) { return int(val); }
+
// RUN: c-index-test -cursor-at=%s:6:4 %s | FileCheck -check-prefix=CHECK-COMPLETION-1 %s
// CHECK-COMPLETION-1: CXXConstructor=X:6:3
// CHECK-COMPLETION-1-NEXT: Completion string: {TypedText X}{LeftParen (}{Placeholder int}{Comma , }{Placeholder int}{RightParen )}
@@ -207,7 +209,7 @@ void test(TestColl coll) {
// 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 -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 -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])
@@ -254,6 +256,7 @@ void test(TestColl coll) {
// CHECK-SPELLING: 129:6 CXXMethod=operator->:129:6 Extent=[129:3 - 129:18] Spelling=operator-> ([129:6 - 129:16])
// CHECK-SPELLING: 130:6 CXXMethod=operator():130:6 (const) Extent=[130:3 - 130:37] Spelling=operator() ([130:6 - 130:16])
// CHECK-SPELLING: 132:12 CXXConversion=operator bool:132:12 (const) Extent=[132:3 - 132:33] Spelling=operator bool ([132:12 - 132:25])
+// CHECK-SPELLING: 146:11 FunctionDecl=operator""_toint:146:11 (Definition) Extent=[146:1 - 146:72] Spelling=operator""_toint ([146:11 - 146:27])
// 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])
diff --git a/test/Index/keep-going.cpp b/test/Index/keep-going.cpp
index a25d1c4b0412..82987c6cf133 100644
--- a/test/Index/keep-going.cpp
+++ b/test/Index/keep-going.cpp
@@ -19,10 +19,10 @@ class C : public A<float> { };
// CHECK: FieldDecl=a:4:13 (Definition) [type=T] [typekind=Unexposed] [canonicaltype=type-parameter-0-0] [canonicaltypekind=Unexposed] [isPOD=0]
// CHECK: TypeRef=T:3:16 [type=T] [typekind=Unexposed] [canonicaltype=type-parameter-0-0] [canonicaltypekind=Unexposed] [isPOD=0]
// CHECK: ClassDecl=B:6:7 (Definition) [type=B] [typekind=Record] [isPOD=0]
-// CHECK: C++ base class specifier=A<int>:4:7 [access=public isVirtual=false] [type=A<int>] [typekind=Unexposed] [canonicaltype=A<int>] [canonicaltypekind=Record] [templateargs/1= [type=int] [typekind=Int]] [isPOD=0] [nbFields=1]
+// CHECK: C++ base class specifier=A<int>:4:7 [access=public isVirtual=false] [type=A<int>] [typekind=Unexposed] [templateargs/1= [type=int] [typekind=Int]] [canonicaltype=A<int>] [canonicaltypekind=Record] [canonicaltemplateargs/1= [type=int] [typekind=Int]] [isPOD=0] [nbFields=1]
// CHECK: TemplateRef=A:4:7 [type=] [typekind=Invalid] [isPOD=0]
// CHECK: ClassDecl=C:10:7 (Definition) [type=C] [typekind=Record] [isPOD=0]
-// CHECK: C++ base class specifier=A<float>:4:7 [access=public isVirtual=false] [type=A<float>] [typekind=Unexposed] [canonicaltype=A<float>] [canonicaltypekind=Record] [templateargs/1= [type=float] [typekind=Float]] [isPOD=0] [nbFields=1]
+// CHECK: C++ base class specifier=A<float>:4:7 [access=public isVirtual=false] [type=A<float>] [typekind=Unexposed] [templateargs/1= [type=float] [typekind=Float]] [canonicaltype=A<float>] [canonicaltypekind=Record] [canonicaltemplateargs/1= [type=float] [typekind=Float]] [isPOD=0] [nbFields=1]
// CHECK: TemplateRef=A:4:7 [type=] [typekind=Invalid] [isPOD=0]
// CHECK-DIAG: keep-going.cpp:1:10: error: 'missing1.h' file not found
diff --git a/test/Index/load-classes.cpp b/test/Index/load-classes.cpp
index f527db521089..8b1ed317e3be 100644
--- a/test/Index/load-classes.cpp
+++ b/test/Index/load-classes.cpp
@@ -18,13 +18,18 @@ private:
virtual void virtualMemberFunction();
virtual void pureVirtualMemberFunction() = 0;
+
+ friend void friendFunction();
+ template <typename T>
+ friend void friendFunctionTemplate();
+ friend class F;
};
X::X(int value) {
}
// RUN: c-index-test -test-load-source all %s | FileCheck %s
-// CHECK: load-classes.cpp:3:8: StructDecl=X:3:8 (Definition) Extent=[3:1 - 21:2]
+// CHECK: load-classes.cpp:3:8: StructDecl=X:3:8 (Definition) Extent=[3:1 - 26:2]
// CHECK: load-classes.cpp:4:3: CXXConstructor=X:4:3 (converting constructor) Extent=[4:3 - 4:15] [access=public]
// FIXME: missing TypeRef in the constructor name
// CHECK: load-classes.cpp:4:9: ParmDecl=value:4:9 (Definition) Extent=[4:5 - 4:14]
@@ -46,7 +51,14 @@ X::X(int value) {
// CHECK: load-classes.cpp:16:21: TemplateTypeParameter=T:16:21 (Definition) Extent=[16:12 - 16:22] [access=public]
// CHECK: load-classes.cpp:19:16: CXXMethod=virtualMemberFunction:19:16 (virtual) Extent=[19:3 - 19:39] [access=private]
// CHECK: load-classes.cpp:20:16: CXXMethod=pureVirtualMemberFunction:20:16 (virtual) (pure) Extent=[20:3 - 20:47] [access=private]
-// CHECK: load-classes.cpp:23:4: CXXConstructor=X:23:4 (Definition) (converting constructor) Extent=[23:1 - 24:2] [access=public]
-// CHECK: load-classes.cpp:23:1: TypeRef=struct X:3:8 Extent=[23:1 - 23:2]
-// CHECK: load-classes.cpp:23:10: ParmDecl=value:23:10 (Definition) Extent=[23:6 - 23:15]
-// CHECK: load-classes.cpp:23:17: CompoundStmt= Extent=[23:17 - 24:2]
+// CHECK: load-classes.cpp:22:15: FriendDecl=:22:15 Extent=[22:3 - 22:31] [access=public]
+// CHECK: load-classes.cpp:22:15: FunctionDecl=friendFunction:22:15 Extent=[22:3 - 22:31] [access=public]
+// CHECK: load-classes.cpp:24:15: FriendDecl=:24:15 Extent=[23:3 - 24:39] [access=public]
+// CHECK: load-classes.cpp:24:15: FunctionTemplate=friendFunctionTemplate:24:15 Extent=[23:3 - 24:39] [access=public]
+// CHECK: load-classes.cpp:23:22: TemplateTypeParameter=T:23:22 (Definition) Extent=[23:13 - 23:23] [access=public]
+// CHECK: load-classes.cpp:25:10: FriendDecl=:25:10 Extent=[25:3 - 25:17] [access=public]
+// CHECK: load-classes.cpp:25:16: TypeRef=class F:25:16 Extent=[25:16 - 25:17]
+// CHECK: load-classes.cpp:28:4: CXXConstructor=X:28:4 (Definition) (converting constructor) Extent=[28:1 - 29:2] [access=public]
+// CHECK: load-classes.cpp:28:1: TypeRef=struct X:3:8 Extent=[28:1 - 28:2]
+// CHECK: load-classes.cpp:28:10: ParmDecl=value:28:10 (Definition) Extent=[28:6 - 28:15]
+// CHECK: load-classes.cpp:28:17: CompoundStmt= Extent=[28:17 - 29:2]
diff --git a/test/Index/load-staticassert.cpp b/test/Index/load-staticassert.cpp
new file mode 100644
index 000000000000..04e45c2d7471
--- /dev/null
+++ b/test/Index/load-staticassert.cpp
@@ -0,0 +1,11 @@
+
+static_assert(2 + 2 == 4, "Simple maths");
+
+// RUN: c-index-test -test-load-source all -fno-delayed-template-parsing -std=c++11 %s | FileCheck %s
+// CHECK: load-staticassert.cpp:2:1: StaticAssert=:2:1 (Definition) Extent=[2:1 - 2:42]
+// CHECK: load-staticassert.cpp:2:15: BinaryOperator= Extent=[2:15 - 2:25]
+// CHECK: load-staticassert.cpp:2:15: BinaryOperator= Extent=[2:15 - 2:20]
+// CHECK: load-staticassert.cpp:2:15: IntegerLiteral= Extent=[2:15 - 2:16]
+// CHECK: load-staticassert.cpp:2:19: IntegerLiteral= Extent=[2:19 - 2:20]
+// CHECK: load-staticassert.cpp:2:24: IntegerLiteral= Extent=[2:24 - 2:25]
+// CHECK: load-staticassert.cpp:2:27: StringLiteral="Simple maths" Extent=[2:27 - 2:41]
diff --git a/test/Index/pr20320.cpp b/test/Index/pr20320.cpp
new file mode 100644
index 000000000000..cb54cea642a3
--- /dev/null
+++ b/test/Index/pr20320.cpp
@@ -0,0 +1,2 @@
+// RUN: env CINDEXTEST_EDITING=1 c-index-test -test-load-source-reparse 5 local -x c++ %s
+#include "pr20320.h"
diff --git a/test/Index/pr20320.h b/test/Index/pr20320.h
new file mode 100644
index 000000000000..9dbb7303df2d
--- /dev/null
+++ b/test/Index/pr20320.h
@@ -0,0 +1,14 @@
+#ifndef pr20320_h
+#define pr20320_h
+
+template<>
+struct S< ::Number::One>
+{
+};
+
+template<>
+struct S< ::Number::Two>
+{
+};
+
+#endif
diff --git a/test/Index/print-type.cpp b/test/Index/print-type.cpp
index 44fc11c365a4..784733f421b4 100644
--- a/test/Index/print-type.cpp
+++ b/test/Index/print-type.cpp
@@ -56,6 +56,20 @@ auto autoBlob = new Blob();
auto autoFunction(){return int();}
decltype(auto) autoInt = 5;
+template <typename T>
+using TypeAlias = outer::Qux<T>;
+
+struct TypeAliasUser { TypeAlias<int> foo; };
+
+template<typename T>
+struct Specialization {};
+
+template<>
+struct Specialization<int>;
+
+Specialization<Specialization<bool>& > templRefParam;
+auto autoTemplRefParam = templRefParam;
+
// RUN: c-index-test -test-print-type %s -std=c++14 | FileCheck %s
// CHECK: Namespace=outer:1:11 (Definition) [type=] [typekind=Invalid] [isPOD=0]
// CHECK: ClassTemplate=Foo:4:8 (Definition) [type=] [typekind=Invalid] [isPOD=0]
@@ -95,11 +109,11 @@ decltype(auto) autoInt = 5;
// CHECK: TypedefDecl=OtherType:25:18 (Definition) [type=OtherType] [typekind=Typedef] [canonicaltype=double] [canonicaltypekind=Double] [isPOD=1]
// CHECK: TypedefDecl=ArrayType:26:15 (Definition) [type=ArrayType] [typekind=Typedef] [canonicaltype=int [5]] [canonicaltypekind=ConstantArray] [isPOD=1]
// CHECK: IntegerLiteral= [type=int] [typekind=Int] [isPOD=1]
-// CHECK: FieldDecl=baz:27:20 (Definition) [type=Baz<int, 1, Foo>] [typekind=Unexposed] [canonicaltype=outer::Baz<int, 1, Foo>] [canonicaltypekind=Record] [templateargs/3= [type=int] [typekind=Int]] [isPOD=1]
+// CHECK: FieldDecl=baz:27:20 (Definition) [type=Baz<int, 1, Foo>] [typekind=Unexposed] [templateargs/3= [type=int] [typekind=Int]] [canonicaltype=outer::Baz<int, 1, Foo>] [canonicaltypekind=Record] [canonicaltemplateargs/3= [type=int] [typekind=Int]] [isPOD=1]
// CHECK: TemplateRef=Baz:9:8 [type=] [typekind=Invalid] [isPOD=0]
// CHECK: IntegerLiteral= [type=int] [typekind=Int] [isPOD=1]
// CHECK: TemplateRef=Foo:4:8 [type=] [typekind=Invalid] [isPOD=0]
-// CHECK: FieldDecl=qux:28:29 (Definition) [type=Qux<int, char *, Foo<int> >] [typekind=Unexposed] [canonicaltype=outer::Qux<int, char *, outer::Foo<int> >] [canonicaltypekind=Record] [templateargs/1=] [isPOD=1]
+// CHECK: FieldDecl=qux:28:29 (Definition) [type=Qux<int, char *, Foo<int> >] [typekind=Unexposed] [templateargs/3= [type=int] [typekind=Int] [type=char *] [typekind=Pointer] [type=Foo<int>] [typekind=Unexposed]] [canonicaltype=outer::Qux<int, char *, outer::Foo<int> >] [canonicaltypekind=Record] [canonicaltemplateargs/3= [type=int] [typekind=Int] [type=char *] [typekind=Pointer] [type=outer::Foo<int>] [typekind=Record]] [isPOD=1]
// CHECK: TemplateRef=Qux:12:8 [type=] [typekind=Invalid] [isPOD=0]
// CHECK: TemplateRef=Foo:4:8 [type=] [typekind=Invalid] [isPOD=0]
// CHECK: FunctionTemplate=tbar:35:3 [type=T (int)] [typekind=FunctionProto] [canonicaltype=type-parameter-0-0 (int)] [canonicaltypekind=FunctionProto] [resulttype=T] [resulttypekind=Unexposed] [isPOD=0]
@@ -148,3 +162,16 @@ decltype(auto) autoInt = 5;
// CHECK: UnexposedExpr= [type=int] [typekind=Int] [isPOD=1]
// CHECK: VarDecl=autoInt:57:16 (Definition) [type=int] [typekind=Auto] [canonicaltype=int] [canonicaltypekind=Int] [isPOD=1]
// CHECK: IntegerLiteral= [type=int] [typekind=Int] [isPOD=1]
+// CHECK: TypeAliasTemplateDecl=TypeAlias:60:1 (Definition) [type=] [typekind=Invalid] [isPOD=0]
+// CHECK: TemplateTypeParameter=T:59:20 (Definition) [type=T] [typekind=Unexposed] [canonicaltype=type-parameter-0-0] [canonicaltypekind=Unexposed] [isPOD=0]
+// CHECK: FieldDecl=foo:62:39 (Definition) [type=TypeAlias<int>] [typekind=Unexposed] [templateargs/1= [type=int] [typekind=Int]] [canonicaltype=outer::Qux<int>] [canonicaltypekind=Record] [canonicaltemplateargs/1= [type=int] [typekind=Int]] [isPOD=1]
+// CHECK: TemplateRef=TypeAlias:60:1 [type=] [typekind=Invalid] [isPOD=0]
+// CHECK: ClassTemplate=Specialization:65:8 (Definition) [type=] [typekind=Invalid] [isPOD=0]
+// CHECK: TemplateTypeParameter=T:64:19 (Definition) [type=T] [typekind=Unexposed] [canonicaltype=type-parameter-0-0] [canonicaltypekind=Unexposed] [isPOD=0]
+// CHECK: StructDecl=Specialization:68:8 [Specialization of Specialization:65:8] [type=Specialization<int>] [typekind=Record] [templateargs/1= [type=int] [typekind=Int]] [isPOD=0]
+// CHECK: VarDecl=templRefParam:70:40 (Definition) [type=Specialization<Specialization<bool> &>] [typekind=Unexposed] [templateargs/1= [type=Specialization<bool> &] [typekind=LValueReference]] [canonicaltype=Specialization<Specialization<bool> &>] [canonicaltypekind=Record] [canonicaltemplateargs/1= [type=Specialization<bool> &] [typekind=LValueReference]] [isPOD=1]
+// CHECK: TemplateRef=Specialization:65:8 [type=] [typekind=Invalid] [isPOD=0]
+// CHECK: CallExpr=Specialization:65:8 [type=Specialization<Specialization<bool> &>] [typekind=Unexposed] [templateargs/1= [type=Specialization<bool> &] [typekind=LValueReference]] [canonicaltype=Specialization<Specialization<bool> &>] [canonicaltypekind=Record] [canonicaltemplateargs/1= [type=Specialization<bool> &] [typekind=LValueReference]] [isPOD=1]
+// CHECK: VarDecl=autoTemplRefParam:71:6 (Definition) [type=Specialization<Specialization<bool> &>] [typekind=Auto] [templateargs/1= [type=Specialization<bool> &] [typekind=LValueReference]] [canonicaltype=Specialization<Specialization<bool> &>] [canonicaltypekind=Record] [canonicaltemplateargs/1= [type=Specialization<bool> &] [typekind=LValueReference]] [isPOD=1]
+// CHECK: UnexposedExpr=templRefParam:70:40 [type=const Specialization<Specialization<bool> &>] [typekind=Unexposed] const [templateargs/1= [type=Specialization<bool> &] [typekind=LValueReference]] [canonicaltype=const Specialization<Specialization<bool> &>] [canonicaltypekind=Record] [canonicaltemplateargs/1= [type=Specialization<bool> &] [typekind=LValueReference]] [isPOD=1]
+// CHECK: DeclRefExpr=templRefParam:70:40 [type=Specialization<Specialization<bool> &>] [typekind=Unexposed] [templateargs/1= [type=Specialization<bool> &] [typekind=LValueReference]] [canonicaltype=Specialization<Specialization<bool> &>] [canonicaltypekind=Record] [canonicaltemplateargs/1= [type=Specialization<bool> &] [typekind=LValueReference]] [isPOD=1]
diff --git a/test/Lexer/coroutines.cpp b/test/Lexer/coroutines.cpp
index 86d5f969374d..186c84b36ed6 100644
--- a/test/Lexer/coroutines.cpp
+++ b/test/Lexer/coroutines.cpp
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -fsyntax-only %s
-// RUN: %clang_cc1 -fcoroutines -DCORO -fsyntax-only %s
+// RUN: %clang_cc1 -fcoroutines-ts -DCORO -fsyntax-only %s
#ifdef CORO
#define CORO_KEYWORD(NAME) _Static_assert(!__is_identifier(NAME), #NAME)
diff --git a/test/Lexer/cxx-features.cpp b/test/Lexer/cxx-features.cpp
index e047ec3dfb13..5fc1722e942b 100644
--- a/test/Lexer/cxx-features.cpp
+++ b/test/Lexer/cxx-features.cpp
@@ -1,10 +1,11 @@
-// RUN: %clang_cc1 -std=c++98 -verify %s
-// RUN: %clang_cc1 -std=c++11 -verify %s
-// RUN: %clang_cc1 -std=c++1y -fsized-deallocation -verify %s
-// RUN: %clang_cc1 -std=c++14 -fsized-deallocation -verify %s
-// RUN: %clang_cc1 -std=c++1z -fsized-deallocation -verify %s
-// RUN: %clang_cc1 -std=c++1z -fsized-deallocation -fconcepts-ts -DCONCEPTS_TS=1 -verify %s
-// RUN: %clang_cc1 -fcoroutines -DCOROUTINES -verify %s
+// 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 -fno-rtti -verify %s -DNO_EXCEPTIONS -DNO_RTTI
+// RUN: %clang_cc1 -fcoroutines-ts -DNO_EXCEPTIONS -DCOROUTINES -verify %s
// expected-no-diagnostics
@@ -19,10 +20,85 @@
#define check(macro, cxx98, cxx11, cxx14, cxx1z) cxx1z == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx1z
#endif
+// --- C++17 features ---
+
+#if check(variadic_using, 0, 0, 0, 201611) // FIXME: provisional name
+#error "wrong value for __cpp_variadic_using"
+#endif
+
+#if check(hex_float, 0, 0, 0, 201603)
+#error "wrong value for __cpp_hex_float"
+#endif
+
+#if check(inline_variables, 0, 0, 0, 201606) // FIXME: provisional name
+#error "wrong value for __cpp_inline_variables"
+#endif
+
+#if check(aligned_new, 0, 0, 0, 201606) // FIXME: provisional name
+#error "wrong value for __cpp_aligned_new"
+#endif
+
+#if check(noexcept_function_type, 0, 0, 0, 201510)
+#error "wrong value for __cpp_noexcept_function_type"
+#endif
+
+#if check(fold_expressions, 0, 0, 0, 201603)
+#error "wrong value for __cpp_fold_expressions"
+#endif
+
+#if check(capture_star_this, 0, 0, 0, 201603)
+#error "wrong value for __cpp_capture_star_this"
+#endif
+
+// FIXME: bump __cpp_constexpr to 201603 for constexpr lambda support
+
+#if check(if_constexpr, 0, 0, 0, 201606) // FIXME: provisional name
+#error "wrong value for __cpp_if_constexpr"
+#endif
+
+// range_based_for checked below
+
+// static_assert checked below
+
+#if check(template_auto, 0, 0, 0, 201606) // FIXME: provisional name
+#error "wrong value for __cpp_template_auto"
+#endif
+
+#if check(namespace_attributes, 0, 0, 0, 201411)
+// FIXME: allowed without warning in C++14 and C++11
+#error "wrong value for __cpp_namespace_attributes"
+#endif
+
+#if check(enumerator_attributes, 0, 0, 0, 201411)
+// FIXME: allowed without warning in C++14 and C++11
+#error "wrong value for __cpp_enumerator_attributes"
+#endif
+
+#if check(nested_namespace_definitions, 0, 0, 0, 201411)
+#error "wrong value for __cpp_nested_namespace_definitions"
+#endif
+
+// inheriting_constructors checked below
+
+#if check(aggregate_bases, 0, 0, 0, 201603)
+#error "wrong value for __cpp_aggregate_bases"
+#endif
+
+#if check(structured_bindings, 0, 0, 0, 201606)
+#error "wrong value for __cpp_structured_bindings"
+#endif
+
+#if check(nontype_template_args, 0, 0, 0, 201411)
+#error "wrong value for __cpp_nontype_template_args"
+#endif
+
+// --- C++14 features ---
+
#if check(binary_literals, 0, 0, 201304, 201304)
#error "wrong value for __cpp_binary_literals"
#endif
+// (Removed from SD-6.)
#if check(digit_separators, 0, 0, 201309, 201309)
#error "wrong value for __cpp_digit_separators"
#endif
@@ -39,9 +115,7 @@
#error "wrong value for __cpp_sized_deallocation"
#endif
-#if check(constexpr, 0, 200704, 201304, 201304)
-#error "wrong value for __cpp_constexpr"
-#endif
+// constexpr checked below
#if check(decltype_auto, 0, 0, 201304, 201304)
#error "wrong value for __cpp_decltype_auto"
@@ -63,6 +137,8 @@
#error "wrong value for __cpp_variable_templates"
#endif
+// --- C++11 features ---
+
#if check(unicode_characters, 0, 200704, 200704, 200704)
#error "wrong value for __cpp_unicode_characters"
#endif
@@ -83,11 +159,15 @@
#error "wrong value for __cpp_lambdas"
#endif
-#if check(range_based_for, 0, 200907, 200907, 200907)
+#if check(constexpr, 0, 200704, 201304, 201304)
+#error "wrong value for __cpp_constexpr"
+#endif
+
+#if check(range_based_for, 0, 200907, 200907, 201603)
#error "wrong value for __cpp_range_based_for"
#endif
-#if check(static_assert, 0, 200410, 200410, 200410)
+#if check(static_assert, 0, 200410, 200410, 201411)
#error "wrong value for __cpp_static_assert"
#endif
@@ -119,7 +199,7 @@
#error "wrong value for __cpp_nsdmi"
#endif
-#if check(inheriting_constructors, 0, 200802, 200802, 200802)
+#if check(inheriting_constructors, 0, 201511, 201511, 201511)
#error "wrong value for __cpp_inheriting_constructors"
#endif
@@ -131,6 +211,18 @@
#error "wrong value for __cpp_alias_templates"
#endif
+// --- C++98 features ---
+
+#if defined(NO_RTTI) ? check(rtti, 0, 0, 0, 0) : check(rtti, 199711, 199711, 199711, 199711)
+#error "wrong value for __cpp_rtti"
+#endif
+
+#if defined(NO_EXCEPTIONS) ? check(exceptions, 0, 0, 0, 0) : check(exceptions, 199711, 199711, 199711, 199711)
+#error "wrong value for __cpp_exceptions"
+#endif
+
+// --- TS features --
+
#if check(experimental_concepts, 0, 0, CONCEPTS_TS, CONCEPTS_TS)
#error "wrong value for __cpp_experimental_concepts"
#endif
diff --git a/test/Lexer/modules-ts.cpp b/test/Lexer/modules-ts.cpp
new file mode 100644
index 000000000000..06be17c53666
--- /dev/null
+++ b/test/Lexer/modules-ts.cpp
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -fsyntax-only %s
+// RUN: %clang_cc1 -fmodules-ts -DMODULES -fsyntax-only %s
+
+#ifdef MODULES
+#define MODULES_KEYWORD(NAME) _Static_assert(!__is_identifier(NAME), #NAME)
+#else
+#define MODULES_KEYWORD(NAME) _Static_assert(__is_identifier(NAME), #NAME)
+#endif
+
+MODULES_KEYWORD(import);
+MODULES_KEYWORD(module);
diff --git a/test/Misc/amdgcn.languageOptsOpenCL.cl b/test/Misc/amdgcn.languageOptsOpenCL.cl
index 3d1f9b4d9826..6a07fc98069c 100644
--- a/test/Misc/amdgcn.languageOptsOpenCL.cl
+++ b/test/Misc/amdgcn.languageOptsOpenCL.cl
@@ -181,20 +181,49 @@
#pragma OPENCL EXTENSION cl_khr_egl_image: enable
// expected-warning@-1{{unsupported OpenCL extension 'cl_khr_egl_image' - ignoring}}
+#if (__OPENCL_C_VERSION__ >= 200)
+#ifndef cl_khr_mipmap_image
+#error "Missing cl_khr_mipmap_image define"
+#endif
+#else
+#ifdef cl_khr_mipmap_image
+#error "Incorrect cl_khr_mipmap_image define"
+#endif
+// expected-warning@+2{{unsupported OpenCL extension 'cl_khr_mipmap_image' - ignoring}}
+#endif
+#pragma OPENCL EXTENSION cl_khr_mipmap_image: enable
+
#ifdef cl_khr_srgb_image_writes
#error "Incorrect cl_khr_srgb_image_writes define"
#endif
#pragma OPENCL EXTENSION cl_khr_srgb_image_writes: enable
// expected-warning@-1{{unsupported OpenCL extension 'cl_khr_srgb_image_writes' - ignoring}}
+#if (__OPENCL_C_VERSION__ >= 200)
+#ifndef cl_khr_subgroups
+#error "Missing cl_khr_subgroups define"
+#endif
+#else
#ifdef cl_khr_subgroups
#error "Incorrect cl_khr_subgroups define"
#endif
+// expected-warning@+2{{unsupported OpenCL extension 'cl_khr_subgroups' - ignoring}}
+#endif
#pragma OPENCL EXTENSION cl_khr_subgroups: enable
-// expected-warning@-1{{unsupported OpenCL extension 'cl_khr_subgroups' - ignoring}}
#ifdef cl_khr_terminate_context
#error "Incorrect cl_khr_terminate_context define"
#endif
#pragma OPENCL EXTENSION cl_khr_terminate_context: enable
// expected-warning@-1{{unsupported OpenCL extension 'cl_khr_terminate_context' - ignoring}}
+
+#ifndef cl_amd_media_ops
+#error "Missing cl_amd_media_ops define"
+#endif
+#pragma OPENCL EXTENSION cl_amd_media_ops: enable
+
+#ifndef cl_amd_media_ops2
+#error "Missing cl_amd_media_ops2 define"
+#endif
+#pragma OPENCL EXTENSION cl_amd_media_ops2: enable
+
diff --git a/test/Misc/ast-dump-color.cpp b/test/Misc/ast-dump-color.cpp
index 852d68979400..bc01d4932f77 100644
--- a/test/Misc/ast-dump-color.cpp
+++ b/test/Misc/ast-dump-color.cpp
@@ -95,9 +95,9 @@ struct Invalid {
//CHECK: {{^}}[[Blue]]| | `-[[RESET]][[BLUE]]NoInlineAttr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:18[[RESET]]>
//CHECK: {{^}}[[Blue]]| |-[[RESET]][[GREEN]]CXXConstructorDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:28:8[[RESET]]> [[Yellow]]col:8[[RESET]] implicit used constexpr[[CYAN]] Invalid[[RESET]] [[Green]]'void (void) noexcept'[[RESET]] inline
//CHECK: {{^}}[[Blue]]| | `-[[RESET]][[MAGENTA]]CompoundStmt[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:8[[RESET]]>
-//CHECK: {{^}}[[Blue]]| |-[[RESET]][[GREEN]]CXXConstructorDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:8[[RESET]]> [[Yellow]]col:8[[RESET]] implicit constexpr[[CYAN]] Invalid[[RESET]] [[Green]]'void (const struct Invalid &)'[[RESET]] inline noexcept-unevaluated 0x{{[0-9a-fA-F]*}}
+//CHECK: {{^}}[[Blue]]| |-[[RESET]][[GREEN]]CXXConstructorDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:8[[RESET]]> [[Yellow]]col:8[[RESET]] implicit constexpr[[CYAN]] Invalid[[RESET]] [[Green]]'void (const struct Invalid &)'[[RESET]] inline default trivial noexcept-unevaluated 0x{{[0-9a-fA-F]*}}
//CHECK: {{^}}[[Blue]]| | `-[[RESET]][[GREEN]]ParmVarDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:8[[RESET]]> [[Yellow]]col:8[[RESET]] [[Green]]'const struct Invalid &'[[RESET]]
-//CHECK: {{^}}[[Blue]]| `-[[RESET]][[GREEN]]CXXConstructorDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:8[[RESET]]> [[Yellow]]col:8[[RESET]] implicit constexpr[[CYAN]] Invalid[[RESET]] [[Green]]'void (struct Invalid &&)'[[RESET]] inline noexcept-unevaluated 0x{{[0-9a-fA-F]*}}
+//CHECK: {{^}}[[Blue]]| `-[[RESET]][[GREEN]]CXXConstructorDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:8[[RESET]]> [[Yellow]]col:8[[RESET]] implicit constexpr[[CYAN]] Invalid[[RESET]] [[Green]]'void (struct Invalid &&)'[[RESET]] inline default trivial noexcept-unevaluated 0x{{[0-9a-fA-F]*}}
//CHECK: {{^}}[[Blue]]| `-[[RESET]][[GREEN]]ParmVarDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:8[[RESET]]> [[Yellow]]col:8[[RESET]] [[Green]]'struct Invalid &&'[[RESET]]
//CHECK: {{^}}[[Blue]]`-[[RESET]][[GREEN]]VarDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:1[[RESET]], [[Yellow]]line:30:3[[RESET]]> [[Yellow]]col:3[[RESET]][[CYAN]] Invalid[[RESET]] [[Green]]'struct Invalid':'struct Invalid'[[RESET]]
//CHECK: {{^}}[[Blue]] `-[[RESET]][[MAGENTA]]CXXConstructExpr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:3[[RESET]]> [[Green]]'struct Invalid':'struct Invalid'[[RESET]][[Cyan]][[RESET]][[Cyan]][[RESET]] [[Green]]'void (void) noexcept'[[RESET]]
diff --git a/test/Misc/ast-dump-decl.c b/test/Misc/ast-dump-decl.c
index 7d39e6b315c8..45edea26b4f8 100644
--- a/test/Misc/ast-dump-decl.c
+++ b/test/Misc/ast-dump-decl.c
@@ -102,16 +102,22 @@ struct testIndirectFieldDecl {
// CHECK-NEXT: Field{{.*}} ''
// CHECK-NEXT: Field{{.*}} 'TestIndirectFieldDecl'
+// FIXME: It would be nice to dump the enum and its enumerators.
int TestFunctionDecl(int x, enum { e } y) {
return x;
}
// CHECK: FunctionDecl{{.*}} TestFunctionDecl 'int (int, enum {{.*}})'
-// CHECK-NEXT: EnumDecl
-// CHECK-NEXT: EnumConstantDecl{{.*}} e
// CHECK-NEXT: ParmVarDecl{{.*}} x
// CHECK-NEXT: ParmVarDecl{{.*}} y
// CHECK-NEXT: CompoundStmt
+// FIXME: It would be nice to 'Enum' and 'e'.
+int TestFunctionDecl2(enum Enum { e } x) { return x; }
+// CHECK: FunctionDecl{{.*}} TestFunctionDecl2 'int (enum {{.*}})'
+// CHECK-NEXT: ParmVarDecl{{.*}} x
+// CHECK-NEXT: CompoundStmt
+
+
int TestFunctionDeclProto(int x);
// CHECK: FunctionDecl{{.*}} TestFunctionDeclProto 'int (int)'
// CHECK-NEXT: ParmVarDecl{{.*}} x
diff --git a/test/Misc/ast-dump-decl.cpp b/test/Misc/ast-dump-decl.cpp
index 9e94a308194b..1cfcd509efab 100644
--- a/test/Misc/ast-dump-decl.cpp
+++ b/test/Misc/ast-dump-decl.cpp
@@ -223,6 +223,10 @@ namespace testClassTemplateDecl {
class D { };
template<typename T> class TestClassTemplate {
+ public:
+ TestClassTemplate();
+ ~TestClassTemplate();
+ int j();
int i;
};
@@ -252,10 +256,18 @@ namespace testClassTemplateDecl {
// CHECK-NEXT: TemplateTypeParmDecl
// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate
// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate
+// CHECK-NEXT: AccessSpecDecl{{.*}} public
+// CHECK-NEXT: CXXConstructorDecl{{.*}} <line:{{.*}}:5, col:23>
+// CHECK-NEXT: CXXDestructorDecl{{.*}} <line:{{.*}}:5, col:24>
+// CHECK-NEXT: CXXMethodDecl{{.*}} <line:{{.*}}:5, col:11>
// CHECK-NEXT: FieldDecl{{.*}} i
// CHECK-NEXT: ClassTemplateSpecializationDecl{{.*}} class TestClassTemplate
// CHECK-NEXT: TemplateArgument{{.*}}A
// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate
+// CHECK-NEXT: AccessSpecDecl{{.*}} public
+// CHECK-NEXT: CXXConstructorDecl{{.*}} <line:{{.*}}:5, col:23>
+// CHECK-NEXT: CXXDestructorDecl{{.*}} <line:{{.*}}:5, col:24>
+// CHECK-NEXT: CXXMethodDecl{{.*}} <line:{{.*}}:5, col:11>
// CHECK-NEXT: FieldDecl{{.*}} i
// CHECK: ClassTemplateSpecialization{{.*}} 'TestClassTemplate'
// CHECK-NEXT: ClassTemplateSpecialization{{.*}} 'TestClassTemplate'
@@ -269,11 +281,19 @@ namespace testClassTemplateDecl {
// CHECK: ClassTemplateSpecializationDecl{{.*}} class TestClassTemplate
// CHECK-NEXT: TemplateArgument{{.*}}C
// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate
+// CHECK-NEXT: AccessSpecDecl{{.*}} public
+// CHECK-NEXT: CXXConstructorDecl{{.*}} <line:{{.*}}:5, col:23>
+// CHECK-NEXT: CXXDestructorDecl{{.*}} <line:{{.*}}:5, col:24>
+// CHECK-NEXT: CXXMethodDecl{{.*}} <line:{{.*}}:5, col:11>
// CHECK-NEXT: FieldDecl{{.*}} i
// CHECK: ClassTemplateSpecializationDecl{{.*}} class TestClassTemplate
// CHECK-NEXT: TemplateArgument{{.*}}D
// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate
+// CHECK-NEXT: AccessSpecDecl{{.*}} public
+// CHECK-NEXT: CXXConstructorDecl{{.*}} <line:{{.*}}:5, col:23>
+// CHECK-NEXT: CXXDestructorDecl{{.*}} <line:{{.*}}:5, col:24>
+// CHECK-NEXT: CXXMethodDecl{{.*}} <line:{{.*}}:5, col:11>
// CHECK-NEXT: FieldDecl{{.*}} i
// CHECK: ClassTemplatePartialSpecializationDecl{{.*}} class TestClassTemplatePartial
diff --git a/test/Misc/ast-dump-pipe.cl b/test/Misc/ast-dump-pipe.cl
index 1690e5c17a05..ceed2f6f8992 100644
--- a/test/Misc/ast-dump-pipe.cl
+++ b/test/Misc/ast-dump-pipe.cl
@@ -1,4 +1,12 @@
// RUN: %clang_cc1 -triple spir64 -cl-std=CL2.0 -ast-dump -ast-dump-filter pipetype %s | FileCheck -strict-whitespace %s
typedef pipe int pipetype;
-// CHECK: PipeType {{.*}} 'pipe int'
+// CHECK: PipeType {{.*}} 'read_only pipe int'
+// CHECK-NEXT: BuiltinType {{.*}} 'int'
+
+typedef read_only pipe int pipetype2;
+// CHECK: PipeType {{.*}} 'read_only pipe int'
+// CHECK-NEXT: BuiltinType {{.*}} 'int'
+
+typedef write_only pipe int pipetype3;
+// CHECK: PipeType {{.*}} 'write_only pipe int'
// CHECK-NEXT: BuiltinType {{.*}} 'int'
diff --git a/test/Misc/ast-dump-stmt.cpp b/test/Misc/ast-dump-stmt.cpp
index 96921ff7b6e1..55b9b5fa9531 100644
--- a/test/Misc/ast-dump-stmt.cpp
+++ b/test/Misc/ast-dump-stmt.cpp
@@ -65,3 +65,19 @@ void TestDependentAllocationExpr() {
// CHECK: FunctionTemplateDecl {{.*}} TestDependentAllocationExpr
// CHECK: CXXNewExpr {{.*'T \*'$}}
// CHECK: CXXDeleteExpr {{.*'void'$}}
+
+template <typename T>
+class DependentScopeMemberExprWrapper {
+ T member;
+};
+
+template <typename T>
+void TestDependentScopeMemberExpr() {
+ DependentScopeMemberExprWrapper<T> obj;
+ obj.member = T();
+ (&obj)->member = T();
+}
+
+// CHECK: FunctionTemplateDecl {{.*}} TestDependentScopeMemberExpr
+// CHECK: CXXDependentScopeMemberExpr {{.*}} lvalue .member
+// CHECK: CXXDependentScopeMemberExpr {{.*}} lvalue ->member
diff --git a/test/Misc/ast-dump-templates.cpp b/test/Misc/ast-dump-templates.cpp
index 022d5c41127c..eb493b427765 100644
--- a/test/Misc/ast-dump-templates.cpp
+++ b/test/Misc/ast-dump-templates.cpp
@@ -21,24 +21,24 @@ void baz() {
double z = foo<2, double, 3>().getSum();
}
-// Template instantiation - foo
-// Since the order of instantiation may vary during runs, run FileCheck twice
-// to make sure each instantiation is in the correct spot.
-// CHECK1: template <int X = 5, typename Y = int, int Z = 5> struct foo {
-// CHECK2: template <int X = 2, typename Y = double, int Z = 3> struct foo {
-
// Template definition - foo
// CHECK1: template <int X, typename Y, int Z = 5> struct foo {
// CHECK2: template <int X, typename Y, int Z = 5> struct foo {
-// Template instantiation - bar
-// CHECK1: template <int A = 5, typename B = int> int bar()
-// CHECK2: template <int A = 5, typename B = int> int bar()
+// Template instantiation - foo
+// Since the order of instantiation may vary during runs, run FileCheck twice
+// to make sure each instantiation is in the correct spot.
+// CHECK1: template<> struct foo<5, int, 5> {
+// CHECK2: template<> struct foo<2, double, 3> {
// Template definition - bar
// CHECK1: template <int A, typename B> B bar()
// CHECK2: template <int A, typename B> B bar()
+// Template instantiation - bar
+// CHECK1: template<> int bar<5, int>()
+// CHECK2: template<> int bar<5, int>()
+
// CHECK1-LABEL: template <typename ...T> struct A {
// CHECK1-NEXT: template <T ...x[3]> struct B {
template <typename ...T> struct A {
diff --git a/test/Misc/ast-dump-wchar.cpp b/test/Misc/ast-dump-wchar.cpp
index 9768bc89007a..339295c133d1 100644
--- a/test/Misc/ast-dump-wchar.cpp
+++ b/test/Misc/ast-dump-wchar.cpp
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -std=c++11 -ast-dump %s -triple x86_64-linux-gnu | FileCheck %s
-char c8[] = u8"test\0\\\"\t\a\b\234";
-// CHECK: StringLiteral {{.*}} lvalue u8"test\000\\\"\t\a\b\234"
+char c8[] = u8"test\0\\\"\a\b\f\n\r\t\v\234";
+// CHECK: StringLiteral {{.*}} lvalue u8"test\000\\\"\a\b\f\n\r\t\v\234"
char16_t c16[] = u"test\0\\\"\t\a\b\234\u1234";
// CHECK: StringLiteral {{.*}} lvalue u"test\000\\\"\t\a\b\234\u1234"
diff --git a/test/Misc/ast-print-objectivec.m b/test/Misc/ast-print-objectivec.m
index 6293b43f55e4..e419237bbbac 100644
--- a/test/Misc/ast-print-objectivec.m
+++ b/test/Misc/ast-print-objectivec.m
@@ -39,3 +39,9 @@
// CHECK: }
// CHECK: @end
+
+@class C1;
+struct __attribute__((objc_bridge_related(C1,,))) S1;
+
+// CHECK: @class C1;
+// CHECK: struct __attribute__((objc_bridge_related(C1, , ))) S1;
diff --git a/test/Misc/backend-optimization-failure-nodbg.cpp b/test/Misc/backend-optimization-failure-nodbg.cpp
index 1e847185e81c..aba37de231af 100644
--- a/test/Misc/backend-optimization-failure-nodbg.cpp
+++ b/test/Misc/backend-optimization-failure-nodbg.cpp
@@ -4,7 +4,7 @@
// Test verifies optimization failures generated by the backend are handled
// correctly by clang. LLVM tests verify all of the failure conditions.
-void test_switch(int *A, int *B, int Length) { /* expected-warning {{loop not vectorized: failed explicitly specified loop vectorization}} */
+void test_switch(int *A, int *B, int Length, int J) { /* expected-warning {{loop not vectorized: failed explicitly specified loop vectorization}} */
#pragma clang loop vectorize(enable) unroll(disable)
for (int i = 0; i < Length; i++) {
switch (A[i]) {
@@ -12,7 +12,7 @@ void test_switch(int *A, int *B, int Length) { /* expected-warning {{loop not ve
B[i] = 1;
break;
case 1:
- B[i] = 2;
+ B[J] = 2;
break;
default:
B[i] = 3;
diff --git a/test/Misc/backend-optimization-failure.cpp b/test/Misc/backend-optimization-failure.cpp
index bb50e96aaa57..1657c0cb91d5 100644
--- a/test/Misc/backend-optimization-failure.cpp
+++ b/test/Misc/backend-optimization-failure.cpp
@@ -4,7 +4,7 @@
// Test verifies optimization failures generated by the backend are handled
// correctly by clang. LLVM tests verify all of the failure conditions.
-void test_switch(int *A, int *B, int Length) {
+void test_switch(int *A, int *B, int Length,int J) {
#pragma clang loop vectorize(enable) unroll(disable)
for (int i = 0; i < Length; i++) {
/* expected-warning@-1 {{loop not vectorized: failed explicitly specified loop vectorization}} */ switch (A[i]) {
@@ -12,7 +12,7 @@ void test_switch(int *A, int *B, int Length) {
B[i] = 1;
break;
case 1:
- B[i] = 2;
+ B[J] = 2;
break;
default:
B[i] = 3;
diff --git a/test/Misc/backend-stack-frame-diagnostics.cpp b/test/Misc/backend-stack-frame-diagnostics.cpp
index 1d865e7646e9..a850f2253959 100644
--- a/test/Misc/backend-stack-frame-diagnostics.cpp
+++ b/test/Misc/backend-stack-frame-diagnostics.cpp
@@ -8,7 +8,7 @@
// Test that link invocations don't emit an "argument unused during compilation" diagnostic.
// RUN: touch %t.o
-// RUN: %clang -Werror -Wframe-larger-than=0 %t.o -### 2>&1 | not grep ' error: '
+// RUN: %clang -Werror -Wno-liblto -Wframe-larger-than=0 %t.o -### 2>&1 | not grep ' error: '
// TODO: Support rich backend diagnostics for Objective-C methods.
diff --git a/test/Misc/diag-template-diffing.cpp b/test/Misc/diag-template-diffing.cpp
index a4f29cc8c7f0..780839899282 100644
--- a/test/Misc/diag-template-diffing.cpp
+++ b/test/Misc/diag-template-diffing.cpp
@@ -1492,3 +1492,8 @@ void run(A_reg<float> reg, A_ptr<float> ptr, A_ref<float> ref) {
// CHECK-NOELIDE-NOTREE: {{[0-9]*}} errors generated.
// CHECK-ELIDE-TREE: {{[0-9]*}} errors generated.
// CHECK-NOELIDE-TREE: {{[0-9]*}} errors generated.
+
+namespace pr30831 {
+ template <typename T> struct A { static A<T> const a; };
+ template <typename T> A<T> A<T>::a = A<T>();
+}
diff --git a/test/Misc/warning-flags.c b/test/Misc/warning-flags.c
index 69e820542ab7..be02e12e2cbb 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 (84):
+CHECK: Warnings without flags (78):
CHECK-NEXT: ext_excess_initializers
CHECK-NEXT: ext_excess_initializers_in_char_array_initializer
CHECK-NEXT: ext_expected_semi_decl_list
@@ -31,14 +31,12 @@ 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_cond_incompatible_operands_nonstandard
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
CHECK-NEXT: pp_out_of_date_dependency
CHECK-NEXT: pp_poisoning_existing_macro
-CHECK-NEXT: w_asm_qualifier_ignored
CHECK-NEXT: warn_accessor_property_type_mismatch
CHECK-NEXT: warn_arcmt_nsalloc_realloc
CHECK-NEXT: warn_asm_label_on_auto_decl
@@ -56,17 +54,14 @@ CHECK-NEXT: warn_delete_array_type
CHECK-NEXT: warn_double_const_requires_fp64
CHECK-NEXT: warn_drv_assuming_mfloat_abi_is
CHECK-NEXT: warn_drv_clang_unsupported
-CHECK-NEXT: warn_drv_objc_gc_unsupported
CHECK-NEXT: warn_drv_pch_not_first_include
CHECK-NEXT: warn_dup_category_def
-CHECK-NEXT: warn_duplicate_protocol_def
CHECK-NEXT: warn_enum_value_overflow
CHECK-NEXT: warn_expected_qualified_after_typename
CHECK-NEXT: warn_extraneous_char_constant
CHECK-NEXT: warn_fe_cc_log_diagnostics_failure
CHECK-NEXT: warn_fe_cc_print_header_failure
CHECK-NEXT: warn_fe_macro_contains_embedded_newline
-CHECK-NEXT: warn_file_asm_volatile
CHECK-NEXT: warn_ignoring_ftabstop_value
CHECK-NEXT: warn_implements_nscopying
CHECK-NEXT: warn_incompatible_qualified_id
@@ -83,7 +78,6 @@ CHECK-NEXT: warn_not_compound_assign
CHECK-NEXT: warn_objc_property_copy_missing_on_block
CHECK-NEXT: warn_objc_protocol_qualifier_missing_id
CHECK-NEXT: warn_on_superclass_use
-CHECK-NEXT: warn_partial_specs_not_deducible
CHECK-NEXT: warn_pp_convert_to_positive
CHECK-NEXT: warn_pp_expr_overflow
CHECK-NEXT: warn_pp_line_decimal
diff --git a/test/Modules/ExtDebugInfo.cpp b/test/Modules/ExtDebugInfo.cpp
index dbf79f4ff148..c39bce950664 100644
--- a/test/Modules/ExtDebugInfo.cpp
+++ b/test/Modules/ExtDebugInfo.cpp
@@ -1,5 +1,5 @@
// RUN: rm -rf %t
-// Test that only forward declarations are emitted for types dfined in modules.
+// Test that only forward declarations are emitted for types defined in modules.
// Modules:
// RUN: %clang_cc1 -x objective-c++ -std=c++11 -debug-info-kind=standalone \
@@ -63,24 +63,22 @@ struct Specialized<int>::Member definedLocally2;
template <class T> struct FwdDeclTemplateMember<T>::Member { T t; };
TypedefFwdDeclTemplateMember tdfdtm;
+SpecializedBase definedLocally3;
+extern template class WithSpecializedBase<int>;
+WithSpecializedBase<int> definedLocally4;
+
void foo() {
anon.i = GlobalStruct.i = GlobalUnion.i = GlobalEnum;
}
-
-// CHECK: ![[STRUCT:.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Struct",
+// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "Enum",
// CHECK-SAME: scope: ![[NS:[0-9]+]],
// CHECK-SAME: flags: DIFlagFwdDecl,
-// CHECK-SAME: identifier: "_ZTSN8DebugCXX6StructE")
+// CHECK-SAME: identifier: "_ZTSN8DebugCXX4EnumE")
// CHECK: ![[NS]] = !DINamespace(name: "DebugCXX", scope: ![[MOD:[0-9]+]],
// CHECK: ![[MOD]] = !DIModule(scope: null, name: {{.*}}DebugCXX
-// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "Enum",
-// CHECK-SAME: scope: ![[NS]],
-// CHECK-SAME: flags: DIFlagFwdDecl,
-// CHECK-SAME: identifier: "_ZTSN8DebugCXX4EnumE")
-
// This type is anchored in the module by an explicit template instantiation.
// CHECK: !DICompositeType(tag: DW_TAG_class_type,
// CHECK-SAME: name: "Template<long, DebugCXX::traits<long> >",
@@ -103,6 +101,7 @@ void foo() {
// CHECK: !DICompositeType(tag: DW_TAG_class_type,
// CHECK-SAME: name: "Template<float, DebugCXX::traits<float> >",
// CHECK-SAME: scope: ![[NS]],
+// CHECK-SAME: elements:
// CHECK-SAME: templateParams:
// CHECK-SAME: identifier: "_ZTSN8DebugCXX8TemplateIfNS_6traitsIfEEEE")
@@ -112,14 +111,20 @@ void foo() {
// CHECK-SAME: identifier: "_ZTSN8DebugCXX6traitsIfEE")
-// This type is anchored in the module by an explicit template instantiation.
+// This type is anchored in the module via a function argument,
+// but we don't know this (yet).
// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "A<void>",
// CHECK-SAME: scope: ![[NS]],
-// CHECK-SAME: flags: DIFlagFwdDecl,
+// CHECK-SAME: elements:
// CHECK-SAME: identifier: "_ZTSN8DebugCXX1AIJvEEE")
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "static_member",
-// CHECK-SAME: scope: ![[STRUCT]]
+// CHECK-SAME: scope: ![[STRUCT:[0-9]*]]
+
+// CHECK: ![[STRUCT]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Struct",
+// CHECK-SAME: scope: ![[NS]],
+// CHECK-SAME: flags: DIFlagFwdDecl,
+// CHECK-SAME: identifier: "_ZTSN8DebugCXX6StructE")
// CHECK: !DICompositeType(tag: DW_TAG_union_type,
// CHECK-SAME: flags: DIFlagFwdDecl,
@@ -133,6 +138,7 @@ void foo() {
// This one isn't.
// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "Template1<void *>",
+// CHECK-SAME: elements:
// CHECK-SAME: templateParams:
// CHECK-SAME: identifier: "_ZTS9Template1IPvE")
@@ -142,6 +148,7 @@ void foo() {
// CHECK-SAME: identifier: "_ZTS9Template1IiE")
// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "FwdDeclTemplate<int>",
+// CHECK-SAME: elements:
// CHECK-SAME: templateParams:
// CHECK-SAME: identifier: "_ZTS15FwdDeclTemplateIiE")
@@ -160,6 +167,19 @@ void foo() {
// CHECK-SAME: elements:
// CHECK-SAME: identifier: "_ZTSN21FwdDeclTemplateMemberIiE6MemberE")
+// This type is defined locally and forward-declared in the module.
+// CHECK: !DIDerivedType(tag: DW_TAG_typedef, name: "SpecializedBase",
+// CHECK-SAME: baseType: ![[SPECIALIZEDBASE:.*]])
+// CHECK: ![[SPECIALIZEDBASE]] =
+// CHECK-SAME: !DICompositeType(tag: DW_TAG_class_type,
+// CHECK-SAME: name: "WithSpecializedBase<float>",
+// CHECK-SAME: elements:
+// CHECK-SAME: identifier: "_ZTS19WithSpecializedBaseIfE")
+
+// This type is explicitly specialized locally.
+// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "WithSpecializedBase<int>",
+// CHECK-SAME: elements:
+// CHECK-SAME: identifier: "_ZTS19WithSpecializedBaseIiE")
// CHECK: !DIGlobalVariable(name: "anon_enum", {{.*}}, type: ![[ANON_ENUM:[0-9]+]]
// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, scope: ![[NS]],
@@ -181,7 +201,7 @@ void foo() {
// CHECK-SAME: name: "InAnonymousNamespace", {{.*}}DIFlagFwdDecl)
-// CHECK: !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !0, entity: ![[STRUCT]], line: 27)
+// CHECK: !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !{{[0-9]+}}, entity: ![[STRUCT]], line: 27)
// CHECK: !DICompileUnit(
// CHECK-SAME: splitDebugFilename:
diff --git a/test/Modules/ExtDebugInfo.m b/test/Modules/ExtDebugInfo.m
index 71ca853fb7d9..41247b00a49f 100644
--- a/test/Modules/ExtDebugInfo.m
+++ b/test/Modules/ExtDebugInfo.m
@@ -34,14 +34,8 @@ int foo(ObjCClass *c) {
return [c property];
}
-// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "ObjCClassWithPrivateIVars",
-// CHECK-SAME: flags: DIFlagObjcClassComplete
-
// CHECK: ![[MOD:.*]] = !DIModule(scope: null, name: "DebugObjC
-// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "hidden_ivar",
-// CHECK-SAME: flags: DIFlagPrivate)
-
// CHECK: !DIGlobalVariable(name: "GlobalUnion",
// CHECK-SAME: type: ![[GLOBAL_UNION:[0-9]+]]
// CHECK: ![[GLOBAL_UNION]] = distinct !DICompositeType(tag: DW_TAG_union_type,
@@ -52,10 +46,11 @@ int foo(ObjCClass *c) {
// CHECK: ![[GLOBAL_STRUCT]] = distinct !DICompositeType(tag: DW_TAG_structure_type,
// CHECK-SAME: elements: !{{[0-9]+}})
-// CHECK: !DIDerivedType(tag: DW_TAG_typedef, name: "TypedefUnion",
-// CHECK-SAME: baseType: ![[TD_UNION:.*]])
-// CHECK: ![[TD_UNION]] = !DICompositeType(tag: DW_TAG_union_type,
-// CHECK-SAME: flags: DIFlagFwdDecl)
+// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "ObjCClassWithPrivateIVars",
+// CHECK-SAME: flags: DIFlagObjcClassComplete
+
+// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "hidden_ivar",
+// CHECK-SAME: flags: DIFlagPrivate)
// CHECK: !DIDerivedType(tag: DW_TAG_typedef, name: "TypedefEnum",
// CHECK-SAME: baseType: ![[TD_ENUM:.*]])
@@ -67,6 +62,11 @@ int foo(ObjCClass *c) {
// CHECK: ![[TD_STRUCT]] = !DICompositeType(tag: DW_TAG_structure_type,
// CHECK-SAME: flags: DIFlagFwdDecl)
+// CHECK: !DIDerivedType(tag: DW_TAG_typedef, name: "TypedefUnion",
+// CHECK-SAME: baseType: ![[TD_UNION:.*]])
+// CHECK: ![[TD_UNION]] = !DICompositeType(tag: DW_TAG_union_type,
+// CHECK-SAME: flags: DIFlagFwdDecl)
+
// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "ObjCClass",
// CHECK-SAME: scope: ![[MOD]],
// CHECK-SAME: flags: DIFlagFwdDecl)
diff --git a/test/Modules/Inputs/DebugCXX.h b/test/Modules/Inputs/DebugCXX.h
index 793ad209f8bf..c9cd68f30c46 100644
--- a/test/Modules/Inputs/DebugCXX.h
+++ b/test/Modules/Inputs/DebugCXX.h
@@ -105,3 +105,9 @@ template <> struct Specialized<int> {
template <class T> struct FwdDeclTemplateMember { struct Member; };
typedef FwdDeclTemplateMember<int>::Member TypedefFwdDeclTemplateMember;
+
+// Base class specialized on the class itself.
+template <typename Derived> class BaseTemplate {};
+template <typename T>
+class WithSpecializedBase : public BaseTemplate<WithSpecializedBase<T>> {};
+typedef WithSpecializedBase<float> SpecializedBase;
diff --git a/test/Modules/Inputs/DebugNestedA.h b/test/Modules/Inputs/DebugNestedA.h
new file mode 100644
index 000000000000..58dc2a7df749
--- /dev/null
+++ b/test/Modules/Inputs/DebugNestedA.h
@@ -0,0 +1,8 @@
+/* -*- C++ -*- */
+template <typename T> class Base {};
+template <typename T> struct A : public Base<A<T>> {
+ void f();
+};
+
+class F {};
+typedef A<F> AF;
diff --git a/test/Modules/Inputs/DebugNestedB.h b/test/Modules/Inputs/DebugNestedB.h
new file mode 100644
index 000000000000..7f75d0946e20
--- /dev/null
+++ b/test/Modules/Inputs/DebugNestedB.h
@@ -0,0 +1,7 @@
+/* -*- C++ -*- */
+#include "DebugNestedA.h"
+class C {
+ void run(AF &af) {
+ af.f();
+ }
+};
diff --git a/test/Modules/Inputs/DiagOutOfDate.h b/test/Modules/Inputs/DiagOutOfDate.h
new file mode 100644
index 000000000000..f86587a83964
--- /dev/null
+++ b/test/Modules/Inputs/DiagOutOfDate.h
@@ -0,0 +1 @@
+const int a = 1;
diff --git a/test/Modules/Inputs/GNUAsm/NeedsGNUInlineAsm.framework/Headers/NeedsGNUInlineAsm.h b/test/Modules/Inputs/GNUAsm/NeedsGNUInlineAsm.framework/Headers/NeedsGNUInlineAsm.h
new file mode 100644
index 000000000000..7978a767e633
--- /dev/null
+++ b/test/Modules/Inputs/GNUAsm/NeedsGNUInlineAsm.framework/Headers/NeedsGNUInlineAsm.h
@@ -0,0 +1 @@
+// NeedsGNUInlineAsm.h
diff --git a/test/Modules/Inputs/GNUAsm/NeedsGNUInlineAsm.framework/Headers/asm.h b/test/Modules/Inputs/GNUAsm/NeedsGNUInlineAsm.framework/Headers/asm.h
new file mode 100644
index 000000000000..da52f829c372
--- /dev/null
+++ b/test/Modules/Inputs/GNUAsm/NeedsGNUInlineAsm.framework/Headers/asm.h
@@ -0,0 +1 @@
+__asm("foo");
diff --git a/test/Modules/Inputs/GNUAsm/NeedsGNUInlineAsm.framework/module.map b/test/Modules/Inputs/GNUAsm/NeedsGNUInlineAsm.framework/module.map
new file mode 100644
index 000000000000..a9536100d611
--- /dev/null
+++ b/test/Modules/Inputs/GNUAsm/NeedsGNUInlineAsm.framework/module.map
@@ -0,0 +1,8 @@
+framework module NeedsGNUInlineAsm {
+ header "NeedsGNUInlineAsm.h"
+
+ explicit module Asm {
+ requires gnuinlineasm
+ header "asm.h"
+ }
+}
diff --git a/test/Modules/Inputs/PR27699/Subdir/a.h b/test/Modules/Inputs/PR27699/Subdir/a.h
new file mode 100644
index 000000000000..6c36a1a100be
--- /dev/null
+++ b/test/Modules/Inputs/PR27699/Subdir/a.h
@@ -0,0 +1 @@
+#include "streambuf"
diff --git a/test/Modules/Inputs/PR27699/Subdir/b.h b/test/Modules/Inputs/PR27699/Subdir/b.h
new file mode 100644
index 000000000000..6c36a1a100be
--- /dev/null
+++ b/test/Modules/Inputs/PR27699/Subdir/b.h
@@ -0,0 +1 @@
+#include "streambuf"
diff --git a/test/Modules/Inputs/PR27699/module.modulemap b/test/Modules/Inputs/PR27699/module.modulemap
new file mode 100644
index 000000000000..1f58ca06753e
--- /dev/null
+++ b/test/Modules/Inputs/PR27699/module.modulemap
@@ -0,0 +1 @@
+module a { umbrella "Subdir" module * {export *} }
diff --git a/test/Modules/Inputs/PR27699/streambuf b/test/Modules/Inputs/PR27699/streambuf
new file mode 100644
index 000000000000..30ea73d230d1
--- /dev/null
+++ b/test/Modules/Inputs/PR27699/streambuf
@@ -0,0 +1,7 @@
+ #ifndef STREAMBUF
+ #define STREAMBUF
+ template <typename> struct basic_streambuf {
+ basic_streambuf(const basic_streambuf &);
+ };
+template <typename T> basic_streambuf<T>::basic_streambuf(const basic_streambuf &) = default;
+#endif
diff --git a/test/Modules/Inputs/PR28438/a.h b/test/Modules/Inputs/PR28438/a.h
new file mode 100644
index 000000000000..a7e26ac6cdb1
--- /dev/null
+++ b/test/Modules/Inputs/PR28438/a.h
@@ -0,0 +1 @@
+#define FOO
diff --git a/test/Modules/Inputs/PR28438/b1.h b/test/Modules/Inputs/PR28438/b1.h
new file mode 100644
index 000000000000..262976e357fb
--- /dev/null
+++ b/test/Modules/Inputs/PR28438/b1.h
@@ -0,0 +1,2 @@
+#define FOO
+#include "a.h"
diff --git a/test/Modules/Inputs/PR28438/b2.h b/test/Modules/Inputs/PR28438/b2.h
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/Modules/Inputs/PR28438/b2.h
diff --git a/test/Modules/Inputs/PR28438/module.modulemap b/test/Modules/Inputs/PR28438/module.modulemap
new file mode 100644
index 000000000000..cb77d47b6cec
--- /dev/null
+++ b/test/Modules/Inputs/PR28438/module.modulemap
@@ -0,0 +1,2 @@
+module A { header "a.h" export * }
+module B { module B1 { header "b1.h" export * } module B2 { header "b2.h" export * } }
diff --git a/test/Modules/Inputs/PR28752/Subdir1/b.h b/test/Modules/Inputs/PR28752/Subdir1/b.h
new file mode 100644
index 000000000000..4d8de217d77d
--- /dev/null
+++ b/test/Modules/Inputs/PR28752/Subdir1/b.h
@@ -0,0 +1,4 @@
+#include <vector>
+
+template<typename T> struct A { static bool b; };
+template<typename T> bool A<T>::b;
diff --git a/test/Modules/Inputs/PR28752/Subdir1/c.h b/test/Modules/Inputs/PR28752/Subdir1/c.h
new file mode 100644
index 000000000000..38822fb9cf21
--- /dev/null
+++ b/test/Modules/Inputs/PR28752/Subdir1/c.h
@@ -0,0 +1,2 @@
+template<typename T> struct A { static bool b; };
+template<typename T> bool A<T>::b;
diff --git a/test/Modules/Inputs/PR28752/Subdir1/module.modulemap b/test/Modules/Inputs/PR28752/Subdir1/module.modulemap
new file mode 100644
index 000000000000..8d3bfe996f5f
--- /dev/null
+++ b/test/Modules/Inputs/PR28752/Subdir1/module.modulemap
@@ -0,0 +1,5 @@
+module b {
+ module "b.h" { header "b.h" export * }
+ module "c.h" { header "c.h" export * }
+ export *
+}
diff --git a/test/Modules/Inputs/PR28752/a.h b/test/Modules/Inputs/PR28752/a.h
new file mode 100644
index 000000000000..3b3a25f213f2
--- /dev/null
+++ b/test/Modules/Inputs/PR28752/a.h
@@ -0,0 +1 @@
+#include <vector>
diff --git a/test/Modules/Inputs/PR28752/module.modulemap b/test/Modules/Inputs/PR28752/module.modulemap
new file mode 100644
index 000000000000..caf888fc474c
--- /dev/null
+++ b/test/Modules/Inputs/PR28752/module.modulemap
@@ -0,0 +1 @@
+module a { header "a.h" export * }
diff --git a/test/Modules/Inputs/PR28752/vector b/test/Modules/Inputs/PR28752/vector
new file mode 100644
index 000000000000..fc5dafae1f91
--- /dev/null
+++ b/test/Modules/Inputs/PR28752/vector
@@ -0,0 +1,28 @@
+#ifndef VECTOR
+#define VECTOR
+template <bool, typename> struct B;
+template <typename _Tp> struct B<true, _Tp> { typedef _Tp type; };
+namespace std {
+template <typename> struct D {
+
+ template <typename _Alloc2> struct F {
+ static const bool value = 0;
+ };
+
+ template <typename _Alloc2>
+ typename B<F<_Alloc2>::value, _Alloc2>::type _S_select(_Alloc2);
+ template <typename _Alloc2>
+ static
+ typename B<!F<_Alloc2>::value, _Alloc2>::type _S_select(_Alloc2);
+};
+template <typename _Alloc>
+template <typename _Alloc2>
+const bool D<_Alloc>::F<_Alloc2>::value;
+
+template <typename> class vector {
+public:
+ vector(int);
+ vector(vector &) : vector(D<bool>::_S_select((bool)0)) {}
+};
+}
+#endif // VECTOR \ No newline at end of file
diff --git a/test/Modules/Inputs/PR28794/LibAHeader.h b/test/Modules/Inputs/PR28794/LibAHeader.h
new file mode 100644
index 000000000000..31aa02e848bd
--- /dev/null
+++ b/test/Modules/Inputs/PR28794/LibAHeader.h
@@ -0,0 +1,12 @@
+#ifndef LIB_A_HEADER
+#define LIB_A_HEADER
+
+typedef __SIZE_TYPE__ size_t;
+
+template <typename = int, size_t SlabSize = 4096, size_t = SlabSize>
+class BumpPtrAllocatorImpl;
+
+template <typename T, size_t SlabSize, size_t SizeThreshold>
+void * operator new(size_t, BumpPtrAllocatorImpl<T, SlabSize, SizeThreshold> &);
+
+#endif // LIB_A_HEADER
diff --git a/test/Modules/Inputs/PR28794/Subdir/Empty.h b/test/Modules/Inputs/PR28794/Subdir/Empty.h
new file mode 100644
index 000000000000..8b137891791f
--- /dev/null
+++ b/test/Modules/Inputs/PR28794/Subdir/Empty.h
@@ -0,0 +1 @@
+
diff --git a/test/Modules/Inputs/PR28794/Subdir/LibBHeader.h b/test/Modules/Inputs/PR28794/Subdir/LibBHeader.h
new file mode 100644
index 000000000000..811c2404fac6
--- /dev/null
+++ b/test/Modules/Inputs/PR28794/Subdir/LibBHeader.h
@@ -0,0 +1,12 @@
+#ifndef LIB_B_HEADER
+#define LIB_B_HEADER
+
+#include "LibAHeader.h"
+
+template <typename T, size_t SlabSize, size_t SizeThreshold>
+void *operator new(size_t, BumpPtrAllocatorImpl<T, SlabSize, SizeThreshold> &) {
+ struct S {};
+ return (void*)0xdead;
+}
+
+#endif // LIB_B_HEADER
diff --git a/test/Modules/Inputs/PR28794/module.modulemap b/test/Modules/Inputs/PR28794/module.modulemap
new file mode 100644
index 000000000000..389c01acfd9c
--- /dev/null
+++ b/test/Modules/Inputs/PR28794/module.modulemap
@@ -0,0 +1,3 @@
+module M {
+ umbrella "Subdir" module * {export *}
+}
diff --git a/test/Modules/Inputs/PR28812/Textual.h b/test/Modules/Inputs/PR28812/Textual.h
new file mode 100644
index 000000000000..769962e08792
--- /dev/null
+++ b/test/Modules/Inputs/PR28812/Textual.h
@@ -0,0 +1,11 @@
+#ifndef T_H
+#define T_H
+
+template <typename ValueType> struct VarStreamArray;
+
+template <typename ValueType> struct VarStreamArrayIterator {
+ VarStreamArrayIterator(VarStreamArray<ValueType>) {}
+ bool HasError{};
+};
+
+#endif // T_H
diff --git a/test/Modules/Inputs/PR28812/a.h b/test/Modules/Inputs/PR28812/a.h
new file mode 100644
index 000000000000..0d9da60c91c2
--- /dev/null
+++ b/test/Modules/Inputs/PR28812/a.h
@@ -0,0 +1 @@
+#include "Textual.h"
diff --git a/test/Modules/Inputs/PR28812/b.h b/test/Modules/Inputs/PR28812/b.h
new file mode 100644
index 000000000000..0d9da60c91c2
--- /dev/null
+++ b/test/Modules/Inputs/PR28812/b.h
@@ -0,0 +1 @@
+#include "Textual.h"
diff --git a/test/Modules/Inputs/PR28812/module.modulemap b/test/Modules/Inputs/PR28812/module.modulemap
new file mode 100644
index 000000000000..d2d2b4a0c345
--- /dev/null
+++ b/test/Modules/Inputs/PR28812/module.modulemap
@@ -0,0 +1,6 @@
+module "A" {
+ header "a.h"
+}
+module "B" {
+ header "b.h"
+}
diff --git a/test/Modules/Inputs/cxx-header.h b/test/Modules/Inputs/cxx-header.h
index 7ed777512290..ee52c639116a 100644
--- a/test/Modules/Inputs/cxx-header.h
+++ b/test/Modules/Inputs/cxx-header.h
@@ -1 +1,4 @@
-int f();
+#ifndef CXX_HEADER_H
+#define CXX_HEADER_H
+inline int f() { return 0; }
+#endif
diff --git a/test/Modules/Inputs/implicit-private-with-different-name/A.framework/Headers/a.h b/test/Modules/Inputs/implicit-private-with-different-name/A.framework/Headers/a.h
new file mode 100644
index 000000000000..8b4b1987450a
--- /dev/null
+++ b/test/Modules/Inputs/implicit-private-with-different-name/A.framework/Headers/a.h
@@ -0,0 +1 @@
+extern int APUBLIC;
diff --git a/test/Modules/Inputs/implicit-private-with-different-name/A.framework/Headers/aprivate.h b/test/Modules/Inputs/implicit-private-with-different-name/A.framework/Headers/aprivate.h
new file mode 100644
index 000000000000..760d901aa366
--- /dev/null
+++ b/test/Modules/Inputs/implicit-private-with-different-name/A.framework/Headers/aprivate.h
@@ -0,0 +1 @@
+extern int APRIVATE;
diff --git a/test/Modules/Inputs/implicit-private-with-different-name/A.framework/Modules/module.modulemap b/test/Modules/Inputs/implicit-private-with-different-name/A.framework/Modules/module.modulemap
new file mode 100644
index 000000000000..95eabf90a968
--- /dev/null
+++ b/test/Modules/Inputs/implicit-private-with-different-name/A.framework/Modules/module.modulemap
@@ -0,0 +1,4 @@
+framework module A {
+ header "a.h"
+ export *
+}
diff --git a/test/Modules/Inputs/implicit-private-with-different-name/A.framework/Modules/module.private.modulemap b/test/Modules/Inputs/implicit-private-with-different-name/A.framework/Modules/module.private.modulemap
new file mode 100644
index 000000000000..020d5d31d856
--- /dev/null
+++ b/test/Modules/Inputs/implicit-private-with-different-name/A.framework/Modules/module.private.modulemap
@@ -0,0 +1,4 @@
+framework module APrivate {
+ header "aprivate.h"
+ export *
+}
diff --git a/test/Modules/Inputs/libc-libcxx/include/c++/math.h b/test/Modules/Inputs/libc-libcxx/include/c++/math.h
new file mode 100644
index 000000000000..890db371de66
--- /dev/null
+++ b/test/Modules/Inputs/libc-libcxx/include/c++/math.h
@@ -0,0 +1,2 @@
+#include_next <math.h>
+template<typename T> T abs(T t) { return (t < 0) ? -t : t; }
diff --git a/test/Modules/Inputs/libc-libcxx/include/c++/module.modulemap b/test/Modules/Inputs/libc-libcxx/include/c++/module.modulemap
new file mode 100644
index 000000000000..fd15779e934a
--- /dev/null
+++ b/test/Modules/Inputs/libc-libcxx/include/c++/module.modulemap
@@ -0,0 +1,4 @@
+module "libc++" {
+ module math { header "math.h" export * }
+ module stdlib { header "stdlib.h" export * }
+}
diff --git a/test/Modules/Inputs/libc-libcxx/include/c++/stdlib.h b/test/Modules/Inputs/libc-libcxx/include/c++/stdlib.h
new file mode 100644
index 000000000000..6e736cbbaa06
--- /dev/null
+++ b/test/Modules/Inputs/libc-libcxx/include/c++/stdlib.h
@@ -0,0 +1 @@
+#include_next "stdlib.h"
diff --git a/test/Modules/Inputs/libc-libcxx/include/math.h b/test/Modules/Inputs/libc-libcxx/include/math.h
new file mode 100644
index 000000000000..380ab41ca0a2
--- /dev/null
+++ b/test/Modules/Inputs/libc-libcxx/include/math.h
@@ -0,0 +1 @@
+int abs(int);
diff --git a/test/Modules/Inputs/libc-libcxx/include/module.modulemap b/test/Modules/Inputs/libc-libcxx/include/module.modulemap
new file mode 100644
index 000000000000..744f5450b11a
--- /dev/null
+++ b/test/Modules/Inputs/libc-libcxx/include/module.modulemap
@@ -0,0 +1,4 @@
+module libc [no_undeclared_includes] {
+ module math { header "math.h" export * }
+ module stdlib { header "stdlib.h" export * }
+}
diff --git a/test/Modules/Inputs/libc-libcxx/include/stdlib.h b/test/Modules/Inputs/libc-libcxx/include/stdlib.h
new file mode 100644
index 000000000000..a84546e5bc83
--- /dev/null
+++ b/test/Modules/Inputs/libc-libcxx/include/stdlib.h
@@ -0,0 +1 @@
+#include <math.h>
diff --git a/test/Modules/Inputs/libc-libcxx/sysroot/Frameworks/A.framework/Headers/A.h b/test/Modules/Inputs/libc-libcxx/sysroot/Frameworks/A.framework/Headers/A.h
new file mode 100644
index 000000000000..2ee00c1129a3
--- /dev/null
+++ b/test/Modules/Inputs/libc-libcxx/sysroot/Frameworks/A.framework/Headers/A.h
@@ -0,0 +1,15 @@
+#ifndef __my_a
+#define __my_a
+
+#include <A/int.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+typedef int_fast32_t my_a;
+}
+
+#endif
diff --git a/test/Modules/Inputs/libc-libcxx/sysroot/Frameworks/A.framework/Headers/int.h b/test/Modules/Inputs/libc-libcxx/sysroot/Frameworks/A.framework/Headers/int.h
new file mode 100644
index 000000000000..340315ed9f56
--- /dev/null
+++ b/test/Modules/Inputs/libc-libcxx/sysroot/Frameworks/A.framework/Headers/int.h
@@ -0,0 +1,14 @@
+#ifndef __my_int
+#define __my_int
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+typedef int_fast32_t myint;
+}
+
+#endif
diff --git a/test/Modules/Inputs/libc-libcxx/sysroot/Frameworks/A.framework/Modules/module.modulemap b/test/Modules/Inputs/libc-libcxx/sysroot/Frameworks/A.framework/Modules/module.modulemap
new file mode 100644
index 000000000000..1e91233a90ce
--- /dev/null
+++ b/test/Modules/Inputs/libc-libcxx/sysroot/Frameworks/A.framework/Modules/module.modulemap
@@ -0,0 +1,4 @@
+framework module A [extern_c] {
+ umbrella header "A.h"
+ export *
+}
diff --git a/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/__config b/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/__config
new file mode 100644
index 000000000000..eacda4840060
--- /dev/null
+++ b/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/__config
@@ -0,0 +1,6 @@
+#ifndef _LIBCPP_CONFIG
+#define _LIBCPP_CONFIG
+
+#define __LIBCXX_CONFIG
+
+#endif
diff --git a/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/math.h b/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/math.h
new file mode 100644
index 000000000000..f761b910f3ef
--- /dev/null
+++ b/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/math.h
@@ -0,0 +1,7 @@
+#ifndef LIBCXX_MATH_H
+#define LIBCXX_MATH_H
+
+#include_next <math.h>
+template<typename T> T abs(T t) { return (t < 0) ? -t : t; }
+
+#endif
diff --git a/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/module.modulemap b/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/module.modulemap
new file mode 100644
index 000000000000..b06142a61a20
--- /dev/null
+++ b/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/module.modulemap
@@ -0,0 +1,10 @@
+module "libc++" {
+ module math { header "math.h" export * }
+ module stdlib { header "stdlib.h" export * }
+ module stddef { header "stddef.h" export * }
+ module stdio { textual header "stdio.h" export * }
+ // FIXME: remove "textual" from stdint module below once the issue
+ // between umbrella headers and builtins is resolved.
+ module stdint { textual header "stdint.h" export * }
+ module __config { header "__config" export * }
+}
diff --git a/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/stddef.h b/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/stddef.h
new file mode 100644
index 000000000000..bd42008e1695
--- /dev/null
+++ b/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/stddef.h
@@ -0,0 +1,6 @@
+#ifndef LIBCXX_STDDEF_H
+#define LIBCXX_STDDEF_H
+
+#include <__config>
+
+#endif
diff --git a/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/stdint.h b/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/stdint.h
new file mode 100644
index 000000000000..7a68441bc3d2
--- /dev/null
+++ b/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/stdint.h
@@ -0,0 +1,6 @@
+#ifndef LIBCXX_STDINT_H
+#define LIBCXX_STDINT_H
+
+#include_next "stdint.h"
+
+#endif
diff --git a/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/stdio.h b/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/stdio.h
new file mode 100644
index 000000000000..399fce17534d
--- /dev/null
+++ b/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/stdio.h
@@ -0,0 +1,6 @@
+#ifndef LIBCXX_STDIO_H
+#define LIBCXX_STDIO_H
+
+#include <__config>
+
+#endif
diff --git a/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/stdlib.h b/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/stdlib.h
new file mode 100644
index 000000000000..5053e0581b0c
--- /dev/null
+++ b/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/stdlib.h
@@ -0,0 +1,6 @@
+#ifndef LIBCXX_STDLIB_H
+#define LIBCXX_STDLIB_H
+
+#include_next "stdlib.h"
+
+#endif
diff --git a/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/math.h b/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/math.h
new file mode 100644
index 000000000000..380ab41ca0a2
--- /dev/null
+++ b/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/math.h
@@ -0,0 +1 @@
+int abs(int);
diff --git a/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/module.modulemap b/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/module.modulemap
new file mode 100644
index 000000000000..7244cb0987e7
--- /dev/null
+++ b/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/module.modulemap
@@ -0,0 +1,8 @@
+module libc [no_undeclared_includes] {
+ module math { header "math.h" export * }
+ module stdlib { header "stdlib.h" export * }
+ module stddef { header "stddef.h" export * }
+ module stdint { header "stdint.h" export * }
+ module stdio { header "stdio.h" export * }
+ module util { header "util.h" export * }
+}
diff --git a/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/stddef.h b/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/stddef.h
new file mode 100644
index 000000000000..eca72412a651
--- /dev/null
+++ b/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/stddef.h
@@ -0,0 +1 @@
+// stddef.h
diff --git a/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/stdint.h b/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/stdint.h
new file mode 100644
index 000000000000..8d6c6fe237da
--- /dev/null
+++ b/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/stdint.h
@@ -0,0 +1,22 @@
+typedef char int_least8_t;
+typedef short int_least16_t;
+typedef int int_least32_t;
+typedef long long int int_least64_t;
+typedef unsigned char uint_least8_t;
+typedef unsigned short uint_least16_t;
+typedef unsigned int uint_least32_t;
+typedef unsigned long long uint_least64_t;
+
+typedef char int_fast8_t;
+typedef short int_fast16_t;
+typedef int int_fast32_t;
+typedef long long int int_fast64_t;
+typedef unsigned char uint_fast8_t;
+typedef unsigned short uint_fast16_t;
+typedef unsigned int uint_fast32_t;
+typedef unsigned long long uint_fast64_t;
+
+typedef int * intptr_t;
+typedef unsigned int * uintptr_t;
+typedef int intmax_t;
+typedef unsigned int uintmax_t;
diff --git a/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/stdio.h b/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/stdio.h
new file mode 100644
index 000000000000..0b7bdeba9e11
--- /dev/null
+++ b/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/stdio.h
@@ -0,0 +1,4 @@
+#ifndef DARWIN_STDIO_H
+#define DARWIN_STDIO_H
+
+#endif
diff --git a/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/stdlib.h b/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/stdlib.h
new file mode 100644
index 000000000000..a84546e5bc83
--- /dev/null
+++ b/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/stdlib.h
@@ -0,0 +1 @@
+#include <math.h>
diff --git a/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/util.h b/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/util.h
new file mode 100644
index 000000000000..22e95fcf9b6e
--- /dev/null
+++ b/test/Modules/Inputs/libc-libcxx/sysroot/usr/include/util.h
@@ -0,0 +1,6 @@
+#ifndef DARWIN_UTIL_H
+#define DARWIN_UTIL_H
+
+#include <stdio.h>
+
+#endif
diff --git a/test/Modules/Inputs/lookup-assert/Base.h b/test/Modules/Inputs/lookup-assert/Base.h
new file mode 100644
index 000000000000..67e66183ca1a
--- /dev/null
+++ b/test/Modules/Inputs/lookup-assert/Base.h
@@ -0,0 +1,3 @@
+@interface BaseInterface
+- (void) test;
+@end
diff --git a/test/Modules/Inputs/lookup-assert/Derive.h b/test/Modules/Inputs/lookup-assert/Derive.h
new file mode 100644
index 000000000000..313a96188d2e
--- /dev/null
+++ b/test/Modules/Inputs/lookup-assert/Derive.h
@@ -0,0 +1,3 @@
+#include "Base.h"
+@interface DerivedInterface : BaseInterface
+@end
diff --git a/test/Modules/Inputs/lookup-assert/H3.h b/test/Modules/Inputs/lookup-assert/H3.h
new file mode 100644
index 000000000000..3d8f878905df
--- /dev/null
+++ b/test/Modules/Inputs/lookup-assert/H3.h
@@ -0,0 +1 @@
+#include "Base.h"
diff --git a/test/Modules/Inputs/lookup-assert/module.map b/test/Modules/Inputs/lookup-assert/module.map
new file mode 100644
index 000000000000..e8a89eb095a4
--- /dev/null
+++ b/test/Modules/Inputs/lookup-assert/module.map
@@ -0,0 +1,4 @@
+module X {
+ header "H3.h"
+ export *
+}
diff --git a/test/Modules/Inputs/merge-decl-context/a.h b/test/Modules/Inputs/merge-decl-context/a.h
index 7be90b1535de..a0b58a7d6ddc 100644
--- a/test/Modules/Inputs/merge-decl-context/a.h
+++ b/test/Modules/Inputs/merge-decl-context/a.h
@@ -24,5 +24,6 @@ inline A<int> ff(int i) {
struct Aggregate {
int member;
};
+bool operator==(Aggregate, Aggregate) = delete;
#endif
diff --git a/test/Modules/Inputs/merge-fn-prototype-tags/a.h b/test/Modules/Inputs/merge-fn-prototype-tags/a.h
new file mode 100644
index 000000000000..8dd717cba624
--- /dev/null
+++ b/test/Modules/Inputs/merge-fn-prototype-tags/a.h
@@ -0,0 +1,2 @@
+#include "c.h"
+void ftw(struct stat);
diff --git a/test/Modules/Inputs/merge-fn-prototype-tags/b.h b/test/Modules/Inputs/merge-fn-prototype-tags/b.h
new file mode 100644
index 000000000000..566381f2edf5
--- /dev/null
+++ b/test/Modules/Inputs/merge-fn-prototype-tags/b.h
@@ -0,0 +1 @@
+struct stat;
diff --git a/test/Modules/Inputs/merge-fn-prototype-tags/c.h b/test/Modules/Inputs/merge-fn-prototype-tags/c.h
new file mode 100644
index 000000000000..cb5262417434
--- /dev/null
+++ b/test/Modules/Inputs/merge-fn-prototype-tags/c.h
@@ -0,0 +1,4 @@
+#ifndef _STAT_H_
+#define _STAT_H_
+struct stat {};
+#endif
diff --git a/test/Modules/Inputs/merge-fn-prototype-tags/module.modulemap b/test/Modules/Inputs/merge-fn-prototype-tags/module.modulemap
new file mode 100644
index 000000000000..b324f05abf1a
--- /dev/null
+++ b/test/Modules/Inputs/merge-fn-prototype-tags/module.modulemap
@@ -0,0 +1,5 @@
+module M {
+ header "a.h"
+ module mod_c { header "c.h" }
+ header "b.h"
+}
diff --git a/test/Modules/Inputs/merge-template-pattern-visibility/a.h b/test/Modules/Inputs/merge-template-pattern-visibility/a.h
index 7f9b6497e725..e6592027611c 100644
--- a/test/Modules/Inputs/merge-template-pattern-visibility/a.h
+++ b/test/Modules/Inputs/merge-template-pattern-visibility/a.h
@@ -3,3 +3,4 @@ template<typename T> struct B;
template<typename, typename> struct A {};
template<typename T> struct B : A<T> {};
+template<typename T> inline auto C(T) {}
diff --git a/test/Modules/Inputs/merge-template-pattern-visibility/b.h b/test/Modules/Inputs/merge-template-pattern-visibility/b.h
index 5ed18e7e7c5d..41b52d5e6abb 100644
--- a/test/Modules/Inputs/merge-template-pattern-visibility/b.h
+++ b/test/Modules/Inputs/merge-template-pattern-visibility/b.h
@@ -3,7 +3,18 @@ template<typename T> struct B;
template<typename, typename> struct A {};
template<typename T> struct B : A<T> {};
+template<typename T> inline auto C(T) {}
inline void f() {
B<int> bi;
+ C(0);
+}
+
+namespace CrossModuleMerge {
+ template<typename, typename = int> struct A;
+ template<typename T> struct B;
+
+ template<typename, typename> struct A {};
+ template<typename T> struct B : A<T> {};
+ template<typename T> inline auto C(T) {}
}
diff --git a/test/Modules/Inputs/merge-template-pattern-visibility/c.h b/test/Modules/Inputs/merge-template-pattern-visibility/c.h
new file mode 100644
index 000000000000..db80eda1ea6d
--- /dev/null
+++ b/test/Modules/Inputs/merge-template-pattern-visibility/c.h
@@ -0,0 +1,9 @@
+namespace CrossModuleMerge {
+ template<typename, typename = int> struct A;
+ template<typename T> struct B;
+
+ template<typename, typename> struct A {};
+ template<typename T> struct B : A<T> {};
+ template<typename T> inline auto C(T) {}
+}
+
diff --git a/test/Modules/Inputs/merge-template-pattern-visibility/d.h b/test/Modules/Inputs/merge-template-pattern-visibility/d.h
new file mode 100644
index 000000000000..464f0f5bbed9
--- /dev/null
+++ b/test/Modules/Inputs/merge-template-pattern-visibility/d.h
@@ -0,0 +1 @@
+// d.h: empty
diff --git a/test/Modules/Inputs/merge-template-pattern-visibility/module.modulemap b/test/Modules/Inputs/merge-template-pattern-visibility/module.modulemap
index ba97abbaa8ec..e00d1b9551ee 100644
--- a/test/Modules/Inputs/merge-template-pattern-visibility/module.modulemap
+++ b/test/Modules/Inputs/merge-template-pattern-visibility/module.modulemap
@@ -2,3 +2,7 @@ module X {
module A { header "a.h" }
module B { header "b.h" }
}
+module Y {
+ module C { header "c.h" }
+ module D { header "d.h" }
+}
diff --git a/test/Modules/Inputs/merge-template-specializations/a.h b/test/Modules/Inputs/merge-template-specializations/a.h
new file mode 100644
index 000000000000..fb05647c0aa9
--- /dev/null
+++ b/test/Modules/Inputs/merge-template-specializations/a.h
@@ -0,0 +1 @@
+template<unsigned> class SmallString {};
diff --git a/test/Modules/Inputs/merge-template-specializations/b.h b/test/Modules/Inputs/merge-template-specializations/b.h
new file mode 100644
index 000000000000..96ce2bb1d8d6
--- /dev/null
+++ b/test/Modules/Inputs/merge-template-specializations/b.h
@@ -0,0 +1,2 @@
+#include "a.h"
+void f(SmallString<256>&);
diff --git a/test/Modules/Inputs/merge-template-specializations/c.h b/test/Modules/Inputs/merge-template-specializations/c.h
new file mode 100644
index 000000000000..100463a2f7f2
--- /dev/null
+++ b/test/Modules/Inputs/merge-template-specializations/c.h
@@ -0,0 +1,3 @@
+#include "a.h"
+struct X { SmallString<256> ss; };
+#include "b.h"
diff --git a/test/Modules/Inputs/merge-template-specializations/module.modulemap b/test/Modules/Inputs/merge-template-specializations/module.modulemap
new file mode 100644
index 000000000000..77e0a89e39a0
--- /dev/null
+++ b/test/Modules/Inputs/merge-template-specializations/module.modulemap
@@ -0,0 +1,3 @@
+module a { header "a.h" export * }
+module b { header "b.h" export * }
+module c { header "c.h" export * }
diff --git a/test/Modules/Inputs/merge-var-template-def/a.h b/test/Modules/Inputs/merge-var-template-def/a.h
new file mode 100644
index 000000000000..6b414b3031fb
--- /dev/null
+++ b/test/Modules/Inputs/merge-var-template-def/a.h
@@ -0,0 +1,8 @@
+#ifndef A_H
+#define A_H
+template<typename T, T v>
+struct S { static constexpr T value = v; };
+template<typename T, T v>
+constexpr T S<T, v>::value;
+
+#endif
diff --git a/test/Modules/Inputs/merge-var-template-def/b1.h b/test/Modules/Inputs/merge-var-template-def/b1.h
new file mode 100644
index 000000000000..35cab9d01c8e
--- /dev/null
+++ b/test/Modules/Inputs/merge-var-template-def/b1.h
@@ -0,0 +1,9 @@
+#ifndef B1_H
+#define B1_H
+template<typename T, T v>
+struct S { static constexpr T value = v; };
+template<typename T, T v>
+constexpr T S<T, v>::value;
+
+#include "a.h"
+#endif
diff --git a/test/Modules/Inputs/merge-var-template-def/b2.h b/test/Modules/Inputs/merge-var-template-def/b2.h
new file mode 100644
index 000000000000..6ab87c2fa718
--- /dev/null
+++ b/test/Modules/Inputs/merge-var-template-def/b2.h
@@ -0,0 +1,9 @@
+#ifndef B2_H
+#define B2_H
+
+template<typename T, T v>
+struct S { static constexpr T value = v; };
+template<typename T, T v>
+constexpr T S<T, v>::value;
+
+#endif
diff --git a/test/Modules/Inputs/merge-var-template-def/module.modulemap b/test/Modules/Inputs/merge-var-template-def/module.modulemap
new file mode 100644
index 000000000000..b2c96bd82177
--- /dev/null
+++ b/test/Modules/Inputs/merge-var-template-def/module.modulemap
@@ -0,0 +1,5 @@
+module a { header "a.h" export * }
+module b {
+ module b1 { header "b1.h" export * }
+ module b2 { header "b2.h" export * }
+}
diff --git a/test/Modules/Inputs/module.map b/test/Modules/Inputs/module.map
index 6846690c8498..2beb942861a4 100644
--- a/test/Modules/Inputs/module.map
+++ b/test/Modules/Inputs/module.map
@@ -418,3 +418,17 @@ module Empty {}
module MacroFabs1 {
header "MacroFabs1.h"
}
+
+module DiagOutOfDate {
+ header "DiagOutOfDate.h"
+}
+
+module DebugNestedA {
+ header "DebugNestedA.h"
+ export *
+}
+
+module DebugNestedB {
+ header "DebugNestedB.h"
+ export *
+}
diff --git a/test/Modules/Inputs/objc-category-2/Base.h b/test/Modules/Inputs/objc-category-2/Base.h
new file mode 100644
index 000000000000..9bd8b17a87e6
--- /dev/null
+++ b/test/Modules/Inputs/objc-category-2/Base.h
@@ -0,0 +1,3 @@
+@interface DVTSourceModel // expected-error {{duplicate interface definition for class}} \
+ // expected-note {{previous definition is here}}
+@end
diff --git a/test/Modules/Inputs/objc-category-2/Category.h b/test/Modules/Inputs/objc-category-2/Category.h
new file mode 100644
index 000000000000..7cde9fb64cc7
--- /dev/null
+++ b/test/Modules/Inputs/objc-category-2/Category.h
@@ -0,0 +1,4 @@
+#include "Base.h"
+@interface DVTSourceModel(Additions)
+- (int)test:(int)item;
+@end
diff --git a/test/Modules/Inputs/objc-category-2/H3.h b/test/Modules/Inputs/objc-category-2/H3.h
new file mode 100644
index 000000000000..3d8f878905df
--- /dev/null
+++ b/test/Modules/Inputs/objc-category-2/H3.h
@@ -0,0 +1 @@
+#include "Base.h"
diff --git a/test/Modules/Inputs/objc-category-2/module.map b/test/Modules/Inputs/objc-category-2/module.map
new file mode 100644
index 000000000000..833b189a338a
--- /dev/null
+++ b/test/Modules/Inputs/objc-category-2/module.map
@@ -0,0 +1,4 @@
+module X {
+ header "Category.h"
+ export *
+}
diff --git a/test/Modules/Inputs/objc-category-3/Base.h b/test/Modules/Inputs/objc-category-3/Base.h
new file mode 100644
index 000000000000..44094643b348
--- /dev/null
+++ b/test/Modules/Inputs/objc-category-3/Base.h
@@ -0,0 +1,2 @@
+@interface DVTSourceModel
+@end
diff --git a/test/Modules/Inputs/objc-category-3/Category.h b/test/Modules/Inputs/objc-category-3/Category.h
new file mode 100644
index 000000000000..7cde9fb64cc7
--- /dev/null
+++ b/test/Modules/Inputs/objc-category-3/Category.h
@@ -0,0 +1,4 @@
+#include "Base.h"
+@interface DVTSourceModel(Additions)
+- (int)test:(int)item;
+@end
diff --git a/test/Modules/Inputs/objc-category-3/Category_B.h b/test/Modules/Inputs/objc-category-3/Category_B.h
new file mode 100644
index 000000000000..d67f94b3a9c6
--- /dev/null
+++ b/test/Modules/Inputs/objc-category-3/Category_B.h
@@ -0,0 +1,4 @@
+#include "Base.h"
+@interface DVTSourceModel(AdditionsB)
+- (int)testB:(int)item matchingMask:(int)mask;
+@end
diff --git a/test/Modules/Inputs/objc-category-3/H3.h b/test/Modules/Inputs/objc-category-3/H3.h
new file mode 100644
index 000000000000..3d8f878905df
--- /dev/null
+++ b/test/Modules/Inputs/objc-category-3/H3.h
@@ -0,0 +1 @@
+#include "Base.h"
diff --git a/test/Modules/Inputs/objc-category-3/module.map b/test/Modules/Inputs/objc-category-3/module.map
new file mode 100644
index 000000000000..c53d5dc6efaa
--- /dev/null
+++ b/test/Modules/Inputs/objc-category-3/module.map
@@ -0,0 +1,4 @@
+module X {
+ header "Category_B.h"
+ export *
+}
diff --git a/test/Modules/Inputs/objc-category/Base.h b/test/Modules/Inputs/objc-category/Base.h
new file mode 100644
index 000000000000..44094643b348
--- /dev/null
+++ b/test/Modules/Inputs/objc-category/Base.h
@@ -0,0 +1,2 @@
+@interface DVTSourceModel
+@end
diff --git a/test/Modules/Inputs/objc-category/Category.h b/test/Modules/Inputs/objc-category/Category.h
new file mode 100644
index 000000000000..7cde9fb64cc7
--- /dev/null
+++ b/test/Modules/Inputs/objc-category/Category.h
@@ -0,0 +1,4 @@
+#include "Base.h"
+@interface DVTSourceModel(Additions)
+- (int)test:(int)item;
+@end
diff --git a/test/Modules/Inputs/objc-category/H3.h b/test/Modules/Inputs/objc-category/H3.h
new file mode 100644
index 000000000000..3d8f878905df
--- /dev/null
+++ b/test/Modules/Inputs/objc-category/H3.h
@@ -0,0 +1 @@
+#include "Base.h"
diff --git a/test/Modules/Inputs/objc-category/module.map b/test/Modules/Inputs/objc-category/module.map
new file mode 100644
index 000000000000..e8a89eb095a4
--- /dev/null
+++ b/test/Modules/Inputs/objc-category/module.map
@@ -0,0 +1,4 @@
+module X {
+ header "H3.h"
+ export *
+}
diff --git a/test/Modules/Inputs/objc-hidden/FakeUnavailableObjCFramework.framework/Headers/FakeUnavailableObjCFramework.h b/test/Modules/Inputs/objc-hidden/FakeUnavailableObjCFramework.framework/Headers/FakeUnavailableObjCFramework.h
new file mode 100644
index 000000000000..2ae08a3e5915
--- /dev/null
+++ b/test/Modules/Inputs/objc-hidden/FakeUnavailableObjCFramework.framework/Headers/FakeUnavailableObjCFramework.h
@@ -0,0 +1,7 @@
+#include <X.h>
+
+__attribute__((availability(macosx,introduced=1066.0))) __attribute__((availability(ios,introduced=1066.0)))
+@interface UnavailableObjCClass : NSObject
+- (void)someMethod;
+@end
+
diff --git a/test/Modules/Inputs/objc-hidden/FakeUnavailableObjCFramework.framework/Modules/module.modulemap b/test/Modules/Inputs/objc-hidden/FakeUnavailableObjCFramework.framework/Modules/module.modulemap
new file mode 100644
index 000000000000..e99c0fa5059e
--- /dev/null
+++ b/test/Modules/Inputs/objc-hidden/FakeUnavailableObjCFramework.framework/Modules/module.modulemap
@@ -0,0 +1,5 @@
+framework module FakeUnavailableObjCFramework {
+ umbrella header "FakeUnavailableObjCFramework.h"
+ // Do not export to test hidden decls.
+ // export *
+}
diff --git a/test/Modules/Inputs/objc-hidden/System/X.h b/test/Modules/Inputs/objc-hidden/System/X.h
new file mode 100644
index 000000000000..c86cc58a1ebb
--- /dev/null
+++ b/test/Modules/Inputs/objc-hidden/System/X.h
@@ -0,0 +1,5 @@
+@protocol NSObject
+@property (readonly) int hash;
+@end
+@interface NSObject <NSObject>
+@end
diff --git a/test/Modules/Inputs/objc-hidden/System/module.map b/test/Modules/Inputs/objc-hidden/System/module.map
new file mode 100644
index 000000000000..8fe4c92a1738
--- /dev/null
+++ b/test/Modules/Inputs/objc-hidden/System/module.map
@@ -0,0 +1,4 @@
+module X {
+ header "X.h"
+ export *
+}
diff --git a/test/Modules/Inputs/objc-initializer/X.h b/test/Modules/Inputs/objc-initializer/X.h
new file mode 100644
index 000000000000..e7182a89f6b4
--- /dev/null
+++ b/test/Modules/Inputs/objc-initializer/X.h
@@ -0,0 +1,3 @@
+@interface NSString
+@end
+static const NSString * const kSimDeviceIOGetInterface = @"simdeviceio_get_interface";
diff --git a/test/Modules/Inputs/objc-initializer/module.modulemap b/test/Modules/Inputs/objc-initializer/module.modulemap
new file mode 100644
index 000000000000..bc76ace10654
--- /dev/null
+++ b/test/Modules/Inputs/objc-initializer/module.modulemap
@@ -0,0 +1,7 @@
+module X {
+ module T {
+ header "X.h"
+ export *
+ }
+ export *
+}
diff --git a/test/Modules/Inputs/objc-method-redecl.h b/test/Modules/Inputs/objc-method-redecl.h
new file mode 100644
index 000000000000..95c6533fad9e
--- /dev/null
+++ b/test/Modules/Inputs/objc-method-redecl.h
@@ -0,0 +1,4 @@
+@interface T
+- (void)test;
+- (void)test;
+@end
diff --git a/test/Modules/Inputs/pch-import-module-out-of-date.pch b/test/Modules/Inputs/pch-import-module-out-of-date.pch
new file mode 100644
index 000000000000..93a446cbcf2f
--- /dev/null
+++ b/test/Modules/Inputs/pch-import-module-out-of-date.pch
@@ -0,0 +1 @@
+@import DiagOutOfDate;
diff --git a/test/Modules/Inputs/prebuilt-module/a.h b/test/Modules/Inputs/prebuilt-module/a.h
new file mode 100644
index 000000000000..f86587a83964
--- /dev/null
+++ b/test/Modules/Inputs/prebuilt-module/a.h
@@ -0,0 +1 @@
+const int a = 1;
diff --git a/test/Modules/Inputs/prebuilt-module/module.modulemap b/test/Modules/Inputs/prebuilt-module/module.modulemap
new file mode 100644
index 000000000000..54459bde5ba3
--- /dev/null
+++ b/test/Modules/Inputs/prebuilt-module/module.modulemap
@@ -0,0 +1 @@
+module prebuilt { header "a.h" }
diff --git a/test/Modules/Inputs/templates-left.h b/test/Modules/Inputs/templates-left.h
index cbe89434f9f3..4f7abeef1fa0 100644
--- a/test/Modules/Inputs/templates-left.h
+++ b/test/Modules/Inputs/templates-left.h
@@ -70,3 +70,5 @@ namespace EmitDefaultedSpecialMembers {
inline int *getStaticDataMemberLeft() {
return WithUndefinedStaticDataMember<int[]>::undefined;
}
+
+inline WithAttributes<int> make_with_attributes_left() { return WithAttributes<int>(); }
diff --git a/test/Modules/Inputs/templates-right.h b/test/Modules/Inputs/templates-right.h
index 32487c60c269..bb3f7c30182a 100644
--- a/test/Modules/Inputs/templates-right.h
+++ b/test/Modules/Inputs/templates-right.h
@@ -51,3 +51,5 @@ void outOfLineInlineUseRightH(void (OutOfLineInline<int>::*)() = &OutOfLineInlin
inline int *getStaticDataMemberRight() {
return WithUndefinedStaticDataMember<int[]>::undefined;
}
+
+inline WithAttributes<int> make_with_attributes_right() { return WithAttributes<int>(); }
diff --git a/test/Modules/Inputs/templates-top.h b/test/Modules/Inputs/templates-top.h
index a08268352399..207d705432e8 100644
--- a/test/Modules/Inputs/templates-top.h
+++ b/test/Modules/Inputs/templates-top.h
@@ -58,3 +58,8 @@ namespace EmitDefaultedSpecialMembers {
template<typename T> struct WithUndefinedStaticDataMember {
static T undefined;
};
+
+template<typename T> struct __attribute__((packed, aligned(2))) WithAttributes {
+ T value;
+};
+WithAttributes<int> *get_with_attributes();
diff --git a/test/Modules/Inputs/unused-global-init/init.h b/test/Modules/Inputs/unused-global-init/init.h
new file mode 100644
index 000000000000..29a932ae65b4
--- /dev/null
+++ b/test/Modules/Inputs/unused-global-init/init.h
@@ -0,0 +1 @@
+struct Init { Init(); ~Init(); } init;
diff --git a/test/Modules/Inputs/unused-global-init/module.modulemap b/test/Modules/Inputs/unused-global-init/module.modulemap
new file mode 100644
index 000000000000..c40f0efeb5e3
--- /dev/null
+++ b/test/Modules/Inputs/unused-global-init/module.modulemap
@@ -0,0 +1,3 @@
+module used { header "used.h" }
+module unused { header "unused.h" }
+module init { module a { header "init.h" } module b { header "other.h" } }
diff --git a/test/Modules/Inputs/unused-global-init/other.h b/test/Modules/Inputs/unused-global-init/other.h
new file mode 100644
index 000000000000..c6be1ad4c43d
--- /dev/null
+++ b/test/Modules/Inputs/unused-global-init/other.h
@@ -0,0 +1 @@
+// other.h
diff --git a/test/Modules/Inputs/unused-global-init/unused.h b/test/Modules/Inputs/unused-global-init/unused.h
new file mode 100644
index 000000000000..06c2a44ba21f
--- /dev/null
+++ b/test/Modules/Inputs/unused-global-init/unused.h
@@ -0,0 +1 @@
+// unused.h
diff --git a/test/Modules/Inputs/unused-global-init/used.h b/test/Modules/Inputs/unused-global-init/used.h
new file mode 100644
index 000000000000..689a13f4c8d3
--- /dev/null
+++ b/test/Modules/Inputs/unused-global-init/used.h
@@ -0,0 +1,2 @@
+// used.h
+#include "init.h"
diff --git a/test/Modules/ModuleDebugInfo.cpp b/test/Modules/ModuleDebugInfo.cpp
index 998d36327ef5..71b05e5aeb8b 100644
--- a/test/Modules/ModuleDebugInfo.cpp
+++ b/test/Modules/ModuleDebugInfo.cpp
@@ -1,7 +1,7 @@
// Test that (the same) debug info is emitted for an Objective-C++
// module and a C++ precompiled header.
-// REQUIRES: asserts, shell
+// REQUIRES: asserts
// Modules:
// RUN: rm -rf %t
@@ -49,6 +49,7 @@
// This type is anchored by a function parameter.
// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "A<void>"
+// CHECK-SAME: elements:
// CHECK-SAME: templateParams:
// CHECK-SAME: identifier: "_ZTSN8DebugCXX1AIJvEEE")
@@ -58,6 +59,7 @@
// This type is anchored by an explicit template instantiation.
// CHECK: !DICompositeType(tag: DW_TAG_class_type,
// CHECK-SAME: name: "Template<int, DebugCXX::traits<int> >"
+// CHECK-SAME: elements:
// CHECK-SAME: templateParams:
// CHECK-SAME: identifier: "_ZTSN8DebugCXX8TemplateIiNS_6traitsIiEEEE")
@@ -66,11 +68,13 @@
// CHECK-SAME: identifier: "_ZTSN8DebugCXX6traitsIiEE")
// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "traits<float>"
+// CHECK-SAME: elements:
// CHECK-SAME: templateParams:
// CHECK-SAME: identifier: "_ZTSN8DebugCXX6traitsIfEE")
// CHECK: !DICompositeType(tag: DW_TAG_class_type,
// CHECK-SAME: name: "Template<long, DebugCXX::traits<long> >"
+// CHECK-SAME: elements:
// CHECK-SAME: templateParams:
// CHECK-SAME: identifier: "_ZTSN8DebugCXX8TemplateIlNS_6traitsIlEEEE")
@@ -121,7 +125,7 @@
// CHECK-SAME: flags: DIFlagFwdDecl,
// CHECK-SAME: identifier: "_ZTS9Template1IPvE")
-// Explicit instatiation.
+// Explicit instantiation.
// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "Template1<int>",
// CHECK-SAME: templateParams:
// CHECK-SAME: identifier: "_ZTS9Template1IiE")
@@ -135,4 +139,10 @@
// CHECK-SAME: flags: DIFlagFwdDecl
// CHECK-SAME: identifier: "_ZTSN21FwdDeclTemplateMemberIiE6MemberE")
+// CHECK: !DIDerivedType(tag: DW_TAG_typedef, name: "SpecializedBase",
+// CHECK-SAME: baseType: ![[SPECIALIZEDBASE:.*]])
+// CHECK: ![[SPECIALIZEDBASE]] = !DICompositeType(tag: DW_TAG_class_type,
+// CHECK-SAME: name: "WithSpecializedBase<float>",
+// CHECK-SAME: flags: DIFlagFwdDecl,
+
// CHECK-NEG-NOT: !DICompositeType(tag: DW_TAG_structure_type, name: "PureForwardDecl"
diff --git a/test/Modules/ModuleDebugInfo.m b/test/Modules/ModuleDebugInfo.m
index ce35c7c8361f..d1a0e8d5e80a 100644
--- a/test/Modules/ModuleDebugInfo.m
+++ b/test/Modules/ModuleDebugInfo.m
@@ -1,7 +1,7 @@
// Test that debug info is emitted for an Objective-C module and
// a precompiled header.
-// REQUIRES: asserts, shell
+// REQUIRES: asserts
// Modules:
// RUN: rm -rf %t
diff --git a/test/Modules/ModuleModuleDebugInfo.cpp b/test/Modules/ModuleModuleDebugInfo.cpp
new file mode 100644
index 000000000000..abc4bfd56b15
--- /dev/null
+++ b/test/Modules/ModuleModuleDebugInfo.cpp
@@ -0,0 +1,18 @@
+// RUN: rm -rf %t
+
+// RUN: %clang_cc1 -x objective-c++ -std=c++11 -debug-info-kind=standalone \
+// RUN: -dwarf-ext-refs -fmodules \
+// RUN: -fmodule-format=obj -fimplicit-module-maps -DMODULES \
+// RUN: -triple %itanium_abi_triple \
+// RUN: -fmodules-cache-path=%t %s -I %S/Inputs -I %t -emit-llvm -o - \
+// RUN: | FileCheck %s
+
+#include "DebugNestedB.h"
+AF af; // This type is not anchored in the module.
+
+// CHECK: !DIDerivedType(tag: DW_TAG_typedef, name: "AF",
+// CHECK-SAME: baseType: ![[AF:.*]])
+
+// CHECK: ![[AF]] = {{.*}}!DICompositeType(tag: DW_TAG_structure_type, name: "A<F>",
+// CHECK-SAME: elements:
+
diff --git a/test/Modules/compiler_builtins.m b/test/Modules/compiler_builtins.m
index bffbcc6ddee5..a5e6315cedc8 100644
--- a/test/Modules/compiler_builtins.m
+++ b/test/Modules/compiler_builtins.m
@@ -1,6 +1,7 @@
// RUN: rm -rf %t
// RUN: %clang_cc1 -fsyntax-only -fmodules -fimplicit-module-maps -fmodules-cache-path=%t %s -I%S/Inputs/System/usr/include -verify
// RUN: %clang_cc1 -fsyntax-only -std=c99 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t %s -I%S/Inputs/System/usr/include -verify
+// RUN: %clang_cc1 -fsyntax-only -fmodules -fmodule-map-file=%resource_dir/module.modulemap -fmodules-cache-path=%t %s -I%S/Inputs/System/usr/include -verify
// expected-no-diagnostics
#ifdef __SSE__
diff --git a/test/Modules/compiler_builtins_x86.c b/test/Modules/compiler_builtins_x86.c
new file mode 100644
index 000000000000..1b4d42177ab0
--- /dev/null
+++ b/test/Modules/compiler_builtins_x86.c
@@ -0,0 +1,7 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -triple i686-unknown-unknown -fsyntax-only -fmodules -fimplicit-module-maps -fmodules-cache-path=%t %s -verify -ffreestanding
+// RUN: %clang_cc1 -triple i686-unknown-unknown -fsyntax-only -fmodules -fmodule-map-file=%resource_dir/module.modulemap -fmodules-cache-path=%t %s -verify -ffreestanding
+// expected-no-diagnostics
+
+#include<x86intrin.h>
+
diff --git a/test/Modules/config-mismatch.cpp b/test/Modules/config-mismatch.cpp
new file mode 100644
index 000000000000..9ddc513cd178
--- /dev/null
+++ b/test/Modules/config-mismatch.cpp
@@ -0,0 +1,13 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: echo 'module M { header "foo.h" header "bar.h" }' > %t/map
+// RUN: echo 'template<typename T> void f(T t) { int n; t.f(n); }' > %t/foo.h
+// RUN: touch %t/bar.h
+// RUN: %clang_cc1 -fmodules -fmodules-local-submodule-visibility -x c++ %t/map -emit-module -fmodule-name=M -o %t/pcm
+// RUN: %clang_cc1 -fmodules -fmodules-local-submodule-visibility -fmodule-map-file=%t/map -fmodule-file=%t/pcm -I%t %s -fsyntax-only -fexceptions -Wno-module-file-config-mismatch -verify
+// RUN: rm %t/bar.h
+// RUN: %clang_cc1 -fmodules -fmodules-local-submodule-visibility -fmodule-map-file=%t/map -fmodule-file=%t/pcm -I%t %s -fsyntax-only -fexceptions -Wno-module-file-config-mismatch -verify
+#include "foo.h"
+namespace n { // expected-note {{begins here}}
+#include "foo.h" // expected-error {{redundant #include of module 'M' appears within namespace}}
+}
diff --git a/test/Modules/crash-vfs-headermaps.m b/test/Modules/crash-vfs-headermaps.m
new file mode 100644
index 000000000000..4f88f3ba1197
--- /dev/null
+++ b/test/Modules/crash-vfs-headermaps.m
@@ -0,0 +1,55 @@
+// 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: echo '// Foo.h' > %t/i/Foo.framework/Headers/Foo.h
+
+// RUN: not env FORCE_CLANG_DIAGNOSTICS_CRASH= TMPDIR=%t TEMP=%t TMP=%t \
+// RUN: %clang -fsyntax-only -fmodules -fmodules-cache-path=%t/m %s \
+// RUN: -I %t/i/foo.hmap -F %t/i 2>&1 | FileCheck %s
+
+// RUN: FileCheck --check-prefix=CHECKSH %s -input-file %t/crash-vfs-*.sh
+// RUN: FileCheck --check-prefix=CHECKYAML %s -input-file \
+// RUN: %t/crash-vfs-*.cache/vfs/vfs.yaml
+
+#include "Foo.h"
+#include "Foo.h"
+
+// CHECK: Preprocessed source(s) and associated run script(s) are located at:
+// CHECK-NEXT: note: diagnostic msg: {{.*}}.m
+// CHECK-NEXT: note: diagnostic msg: {{.*}}.cache
+
+// CHECKSH: # Crash reproducer
+// CHECKSH-NEXT: # Driver args: "-fsyntax-only"
+// CHECKSH-NEXT: # Original command: {{.*$}}
+// CHECKSH-NEXT: "-cc1"
+// CHECKSH: "-I" "/[[INCPATH:.*]]/foo.hmap"
+// CHECKSH: "crash-vfs-{{[^ ]*}}.m"
+// CHECKSH: "-ivfsoverlay" "crash-vfs-{{[^ ]*}}.cache/vfs/vfs.yaml"
+// CHECKSH: "-fmodules-cache-path=crash-vfs-{{[^ ]*}}.cache/repro-modules"
+
+// CHECKYAML: 'case-sensitive':
+// CHECKYAML-NEXT: 'use-external-names': 'false',
+// CHECKYAML-NEXT: 'overlay-relative': 'true',
+// CHECKYAML-NEXT: 'ignore-non-existent-contents': 'false'
+// CHECKYAML: 'type': 'directory'
+// CHECKYAML: 'name': "/[[PATH:.*]]/Foo.framework/Headers",
+// CHECKYAML-NEXT: 'contents': [
+// CHECKYAML-NEXT: {
+// CHECKYAML-NEXT: 'type': 'file',
+// CHECKYAML-NEXT: 'name': "Foo.h",
+// CHECKYAML-NEXT: 'external-contents': "/[[PATH]]/Foo.framework/Headers/Foo.h"
+// CHECKYAML: 'type': 'directory'
+// CHECKYAML: 'name': "/[[PATH:.*]]/i",
+// CHECKYAML-NEXT: 'contents': [
+// CHECKYAML-NEXT: {
+// CHECKYAML-NEXT: 'type': 'file',
+// CHECKYAML-NEXT: 'name': "foo.hmap",
+// CHECKYAML-NEXT: 'external-contents': "/[[PATH]]/i/foo.hmap"
diff --git a/test/Modules/crash-vfs-include-pch.m b/test/Modules/crash-vfs-include-pch.m
new file mode 100644
index 000000000000..78a8e149a41b
--- /dev/null
+++ b/test/Modules/crash-vfs-include-pch.m
@@ -0,0 +1,43 @@
+// REQUIRES: crash-recovery, shell, system-darwin
+//
+// RUN: rm -rf %t
+// RUN: mkdir -p %t/m %t/out
+
+// RUN: %clang_cc1 -x objective-c-header -emit-pch %S/Inputs/pch-used.h \
+// RUN: -o %t/out/pch-used.h.pch -fmodules -fimplicit-module-maps \
+// RUN: -fmodules-cache-path=%t/cache -O0 \
+// RUN: -isystem %S/Inputs/System/usr/include
+
+// RUN: not env FORCE_CLANG_DIAGNOSTICS_CRASH= TMPDIR=%t TEMP=%t TMP=%t \
+// RUN: %clang %s -E -include-pch %t/out/pch-used.h.pch -fmodules -nostdlibinc \
+// RUN: -fimplicit-module-maps -fmodules-cache-path=%t/cache -O0 \
+// RUN: -Xclang -fno-validate-pch -isystem %S/Inputs/System/usr/include \
+// RUN: -o %t/output.E 2>&1 | FileCheck %s
+
+// RUN: FileCheck --check-prefix=CHECKSH %s -input-file %t/crash-vfs-*.sh
+// RUN: FileCheck --check-prefix=CHECKYAML %s -input-file \
+// RUN: %t/crash-vfs-*.cache/vfs/vfs.yaml
+
+void f() { SPXTrace(); }
+void g() { double x = DBL_MAX; }
+
+// CHECK: Preprocessed source(s) and associated run script(s) are located at:
+// CHECK-NEXT: note: diagnostic msg: {{.*}}.m
+// CHECK-NEXT: note: diagnostic msg: {{.*}}.cache
+
+// CHECKSH: "-include-pch" "/[[INCPATH:.*]]/out/pch-used.h.pch"
+// CHECKSH: "crash-vfs-{{[^ ]*}}.m"
+// CHECKSH: "-ivfsoverlay" "crash-vfs-{{[^ ]*}}.cache/vfs/vfs.yaml"
+// CHECKSH: "-fmodules-cache-path=crash-vfs-{{[^ ]*}}.cache/repro-modules"
+
+// CHECKYAML: 'case-sensitive':
+// CHECKYAML-NEXT: 'use-external-names': 'false',
+// CHECKYAML-NEXT: 'overlay-relative': 'true',
+// CHECKYAML-NEXT: 'ignore-non-existent-contents': 'false'
+// CHECKYAML: 'type': 'directory'
+// CHECKYAML: 'name': "/[[PATH:.*]]/out",
+// CHECKYAML-NEXT: 'contents': [
+// CHECKYAML-NEXT: {
+// CHECKYAML-NEXT: 'type': 'file',
+// CHECKYAML-NEXT: 'name': "pch-used.h.pch",
+// CHECKYAML-NEXT: 'external-contents': "/[[PATH]]/out/pch-used.h.pch"
diff --git a/test/Modules/crash-vfs-ivfsoverlay.m b/test/Modules/crash-vfs-ivfsoverlay.m
new file mode 100644
index 000000000000..abbc0151a8cf
--- /dev/null
+++ b/test/Modules/crash-vfs-ivfsoverlay.m
@@ -0,0 +1,45 @@
+// REQUIRES: crash-recovery, shell, system-darwin
+
+// RUN: rm -rf %t
+// RUN: mkdir -p %t/m
+// RUN: cp %S/../VFS/Inputs/actual_module2.map %t/actual_module2.map
+// RUN: sed -e "s:INPUT_DIR:%t:g" -e "s:OUT_DIR:%t/example:g" \
+// RUN: %S/../VFS/Inputs/vfsoverlay2.yaml > %t/srcvfs.yaml
+
+// RUN: not env FORCE_CLANG_DIAGNOSTICS_CRASH= TMPDIR=%t TEMP=%t TMP=%t \
+// RUN: %clang -fsyntax-only -nostdinc %s \
+// RUN: -I %S/Inputs/crash-recovery/usr/include \
+// RUN: -ivfsoverlay %t/srcvfs.yaml \
+// RUN: -fmodules -fmodules-cache-path=%t/m/ 2>&1 | FileCheck %s
+
+// RUN: FileCheck --check-prefix=CHECKSH %s -input-file %t/crash-vfs-*.sh
+// RUN: FileCheck --check-prefix=CHECKYAML %s -input-file \
+// RUN: %t/crash-vfs-*.cache/vfs/vfs.yaml
+// RUN: find %t/crash-vfs-*.cache/vfs | \
+// RUN: grep "%t/actual_module2.map" | count 1
+
+#include <stdio.h>
+
+// CHECK: Preprocessed source(s) and associated run script(s) are located at:
+// CHECK-NEXT: note: diagnostic msg: {{.*}}.m
+// CHECK-NEXT: note: diagnostic msg: {{.*}}.cache
+
+// CHECKSH: # Crash reproducer
+// CHECKSH-NEXT: # Driver args: "-fsyntax-only"
+// CHECKSH-NEXT: # Original command: {{.*$}}
+// CHECKSH-NEXT: "-cc1"
+// CHECKSH: "crash-vfs-{{[^ ]*}}.m"
+// CHECKSH: "-ivfsoverlay" "crash-vfs-{{[^ ]*}}.cache/vfs/vfs.yaml"
+// CHECKSH: "-fmodules-cache-path=crash-vfs-{{[^ ]*}}.cache/repro-modules"
+
+// CHECKYAML: 'case-sensitive':
+// CHECKYAML-NEXT: 'use-external-names': 'false',
+// CHECKYAML-NEXT: 'overlay-relative': 'true',
+// CHECKYAML-NEXT: 'ignore-non-existent-contents': 'false'
+// CHECKYAML: 'type': 'directory'
+// CHECKYAML: 'name': "/[[PATH:.*]]/example"
+// CHECKYAML: 'contents': [
+// CHECKYAML-NEXT: {
+// CHECKYAML-NEXT: 'type': 'file',
+// CHECKYAML-NEXT: 'name': "module.map",
+// CHECKYAML-NEXT: 'external-contents': "/[[OTHERPATH:.*]]/actual_module2.map"
diff --git a/test/Modules/crash-vfs-path-emptydir-entries.m b/test/Modules/crash-vfs-path-emptydir-entries.m
index 01560984ff71..e44714bee7f6 100644
--- a/test/Modules/crash-vfs-path-emptydir-entries.m
+++ b/test/Modules/crash-vfs-path-emptydir-entries.m
@@ -37,7 +37,7 @@
// CHECKSH-NOT: "-fmodules-cache-path="
// CHECKSH: "crash-vfs-{{[^ ]*}}.m"
// CHECKSH: "-ivfsoverlay" "crash-vfs-{{[^ ]*}}.cache/vfs/vfs.yaml"
-// CHECKSH: "-fmodules-cache-path=crash-vfs-{{[^ ]*}}.cache/modules"
+// CHECKSH: "-fmodules-cache-path=crash-vfs-{{[^ ]*}}.cache/repro-modules"
// CHECKYAML: 'type': 'directory',
// CHECKYAML: 'name': "",
diff --git a/test/Modules/crash-vfs-path-symlink-component.m b/test/Modules/crash-vfs-path-symlink-component.m
index 6a41188b271a..5be492514a09 100644
--- a/test/Modules/crash-vfs-path-symlink-component.m
+++ b/test/Modules/crash-vfs-path-symlink-component.m
@@ -38,7 +38,7 @@
// CHECKSH-NOT: "-fmodules-cache-path="
// CHECKSH: "crash-vfs-{{[^ ]*}}.m"
// CHECKSH: "-ivfsoverlay" "crash-vfs-{{[^ ]*}}.cache/vfs/vfs.yaml"
-// CHECKSH: "-fmodules-cache-path=crash-vfs-{{[^ ]*}}.cache/modules"
+// CHECKSH: "-fmodules-cache-path=crash-vfs-{{[^ ]*}}.cache/repro-modules"
// CHECKYAML: 'case-sensitive':
// CHECKYAML-NEXT: 'use-external-names': 'false',
diff --git a/test/Modules/crash-vfs-path-symlink-topheader.m b/test/Modules/crash-vfs-path-symlink-topheader.m
index 72b666a8127c..51a14c69c077 100644
--- a/test/Modules/crash-vfs-path-symlink-topheader.m
+++ b/test/Modules/crash-vfs-path-symlink-topheader.m
@@ -39,7 +39,7 @@
// CHECKSH-NOT: "-fmodules-cache-path="
// CHECKSH: "crash-vfs-{{[^ ]*}}.m"
// CHECKSH: "-ivfsoverlay" "crash-vfs-{{[^ ]*}}.cache/vfs/vfs.yaml"
-// CHECKSH: "-fmodules-cache-path=crash-vfs-{{[^ ]*}}.cache/modules"
+// CHECKSH: "-fmodules-cache-path=crash-vfs-{{[^ ]*}}.cache/repro-modules"
// CHECKYAML: 'type': 'directory',
// CHECKYAML: 'name': "",
diff --git a/test/Modules/crash-vfs-path-traversal.m b/test/Modules/crash-vfs-path-traversal.m
index 3377de47d0b2..cc56e53cf1bf 100644
--- a/test/Modules/crash-vfs-path-traversal.m
+++ b/test/Modules/crash-vfs-path-traversal.m
@@ -35,7 +35,7 @@
// CHECKSH-NOT: "-fmodules-cache-path="
// CHECKSH: "crash-vfs-{{[^ ]*}}.m"
// CHECKSH: "-ivfsoverlay" "crash-vfs-{{[^ ]*}}.cache/vfs/vfs.yaml"
-// CHECKSH: "-fmodules-cache-path=crash-vfs-{{[^ ]*}}.cache/modules"
+// CHECKSH: "-fmodules-cache-path=crash-vfs-{{[^ ]*}}.cache/repro-modules"
// CHECKYAML: 'case-sensitive':
// CHECKYAML-NEXT: 'use-external-names': 'false',
diff --git a/test/Modules/crash-vfs-relative-incdir.m b/test/Modules/crash-vfs-relative-incdir.m
new file mode 100644
index 000000000000..63cd9827c013
--- /dev/null
+++ b/test/Modules/crash-vfs-relative-incdir.m
@@ -0,0 +1,57 @@
+// REQUIRES: crash-recovery, shell, system-darwin
+
+// RUN: rm -rf %t
+// RUN: mkdir -p %t/m
+// RUN: cd %S/Inputs/crash-recovery/usr
+
+// RUN: not env FORCE_CLANG_DIAGNOSTICS_CRASH= TMPDIR=%t TEMP=%t TMP=%t \
+// RUN: %clang -fsyntax-only -nostdinc %s -Iinclude \
+// RUN: -fmodules -fmodules-cache-path=%t/m/ 2>&1 | FileCheck %s
+
+// RUN: FileCheck --check-prefix=CHECKSRC %s -input-file %t/crash-vfs-*.m
+// RUN: FileCheck --check-prefix=CHECKSH %s -input-file %t/crash-vfs-*.sh
+// RUN: FileCheck --check-prefix=CHECKYAML %s -input-file \
+// RUN: %t/crash-vfs-*.cache/vfs/vfs.yaml
+// RUN: find %t/crash-vfs-*.cache/vfs | \
+// RUN: grep "Inputs/crash-recovery/usr/include/stdio.h" | count 1
+
+#include <stdio.h>
+
+// CHECK: Preprocessed source(s) and associated run script(s) are located at:
+// CHECK-NEXT: note: diagnostic msg: {{.*}}.m
+// CHECK-NEXT: note: diagnostic msg: {{.*}}.cache
+
+// CHECKSRC: @import cstd.stdio;
+
+// CHECKSH: # Crash reproducer
+// CHECKSH-NEXT: # Driver args: "-fsyntax-only"
+// CHECKSH-NEXT: # Original command: {{.*$}}
+// CHECKSH-NEXT: "-cc1"
+// CHECKSH: "-resource-dir"
+// CHECKSH: "-I" "/[[INCPATH:.*]]/include"
+// CHECKSH: "crash-vfs-{{[^ ]*}}.m"
+// CHECKSH: "-ivfsoverlay" "crash-vfs-{{[^ ]*}}.cache/vfs/vfs.yaml"
+// CHECKSH: "-fmodules-cache-path=crash-vfs-{{[^ ]*}}.cache/repro-modules"
+
+// CHECKYAML: 'case-sensitive':
+// CHECKYAML-NEXT: 'use-external-names': 'false',
+// CHECKYAML-NEXT: 'overlay-relative': 'true',
+// CHECKYAML-NEXT: 'ignore-non-existent-contents': 'false'
+// CHECKYAML: 'type': 'directory'
+// CHECKYAML: 'name': "/[[PATH:.*]]/Inputs/crash-recovery/usr/include",
+// CHECKYAML-NEXT: 'contents': [
+// CHECKYAML-NEXT: {
+// CHECKYAML-NEXT: 'type': 'file',
+// CHECKYAML-NEXT: 'name': "module.map",
+// CHECKYAML-NOT: 'external-contents': "{{[^ ]*}}.cache
+// CHECKYAML-NEXT: 'external-contents': "/[[PATH]]/Inputs/crash-recovery/usr/include/module.map"
+// CHECKYAML-NEXT: },
+
+// Run the reproducer script - regular exit code is enough to test it works.
+// Note that we don't yet support reusing the modules pcm; what we do
+// support is re-building the modules relying solely on the header files dumped
+// inside .cache/vfs, mapped by .cache/vfs/vfs.yaml.
+
+// RUN: cd %t
+// RUN: chmod 755 crash-vfs-*.sh
+// RUN: ./crash-vfs-*.sh
diff --git a/test/Modules/crash-vfs-relative-overlay.m b/test/Modules/crash-vfs-relative-overlay.m
index 870987c58abd..54ba13bbca39 100644
--- a/test/Modules/crash-vfs-relative-overlay.m
+++ b/test/Modules/crash-vfs-relative-overlay.m
@@ -34,7 +34,7 @@
// CHECKSH: "-isysroot" "{{[^"]*}}/i/"
// CHECKSH: "crash-vfs-{{[^ ]*}}.m"
// CHECKSH: "-ivfsoverlay" "crash-vfs-{{[^ ]*}}.cache/vfs/vfs.yaml"
-// CHECKSH: "-fmodules-cache-path=crash-vfs-{{[^ ]*}}.cache/modules"
+// CHECKSH: "-fmodules-cache-path=crash-vfs-{{[^ ]*}}.cache/repro-modules"
// CHECKYAML: 'case-sensitive':
// CHECKYAML-NEXT: 'use-external-names': 'false',
diff --git a/test/Modules/crash-vfs-run-reproducer.m b/test/Modules/crash-vfs-run-reproducer.m
index d0eaa931c976..72771a2f9479 100644
--- a/test/Modules/crash-vfs-run-reproducer.m
+++ b/test/Modules/crash-vfs-run-reproducer.m
@@ -31,11 +31,12 @@
// CHECKSH: "-isysroot" "{{[^"]*}}/i/"
// CHECKSH: "crash-vfs-{{[^ ]*}}.m"
// CHECKSH: "-ivfsoverlay" "crash-vfs-{{[^ ]*}}.cache/vfs/vfs.yaml"
-// CHECKSH: "-fmodules-cache-path=crash-vfs-{{[^ ]*}}.cache/modules"
+// CHECKSH: "-fmodules-cache-path=crash-vfs-{{[^ ]*}}.cache/repro-modules"
// CHECKYAML: 'case-sensitive':
// CHECKYAML-NEXT: 'use-external-names': 'false',
// CHECKYAML-NEXT: 'overlay-relative': 'true',
+// CHECKYAML-NEXT: 'ignore-non-existent-contents': 'false'
// CHECKYAML: 'type': 'directory'
// CHECKYAML: 'name': "/[[PATH:.*]]/Inputs/crash-recovery/usr/include",
// CHECKYAML-NEXT: 'contents': [
@@ -52,6 +53,5 @@
// inside .cache/vfs, mapped by .cache/vfs/vfs.yaml.
// RUN: cd %t
-// RUN: rm -rf crash-vfs-run-reproducer-*.cache/modules/*
// RUN: chmod 755 crash-vfs-*.sh
// RUN: ./crash-vfs-*.sh
diff --git a/test/Modules/cstd.m b/test/Modules/cstd.m
index 7df727d2efcb..2182140d5db0 100644
--- a/test/Modules/cstd.m
+++ b/test/Modules/cstd.m
@@ -1,5 +1,5 @@
// RUN: rm -rf %t
-// RUN: %clang_cc1 -fsyntax-only -isystem %S/Inputs/System/usr/include -ffreestanding -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -D__need_wint_t -Werror=implicit-function-declaration %s
+// RUN: %clang_cc1 -fsyntax-only -internal-isystem %S/Inputs/System/usr/include -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -D__need_wint_t -Werror=implicit-function-declaration %s
@import uses_other_constants;
const double other_value = DBL_MAX;
diff --git a/test/Modules/cxx-irgen.cpp b/test/Modules/cxx-irgen.cpp
index 75fb2c1495e9..6cc32adc5254 100644
--- a/test/Modules/cxx-irgen.cpp
+++ b/test/Modules/cxx-irgen.cpp
@@ -1,6 +1,6 @@
// RUN: rm -rf %t
-// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -x objective-c++ -std=c++11 -fmodules-cache-path=%t -I %S/Inputs -triple %itanium_abi_triple -disable-llvm-optzns -emit-llvm -o - %s | FileCheck %s
-// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -x objective-c++ -std=c++11 -fmodules-cache-path=%t -I %S/Inputs -triple %itanium_abi_triple -disable-llvm-optzns -emit-llvm -debug-info-kind=limited -o - %s | FileCheck %s
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -x objective-c++ -std=c++11 -fmodules-cache-path=%t -I %S/Inputs -triple %itanium_abi_triple -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -x objective-c++ -std=c++11 -fmodules-cache-path=%t -I %S/Inputs -triple %itanium_abi_triple -disable-llvm-passes -emit-llvm -debug-info-kind=limited -o - %s | FileCheck %s
// FIXME: When we have a syntax for modules in C++, use that.
@import cxx_irgen_top;
diff --git a/test/Modules/cxx-templates.cpp b/test/Modules/cxx-templates.cpp
index 12dfdd0546eb..401b7704900b 100644
--- a/test/Modules/cxx-templates.cpp
+++ b/test/Modules/cxx-templates.cpp
@@ -195,8 +195,8 @@ namespace hidden_specializations {
cls<void>::nested_cls_t<int> *nk2; // ok
cls<void>::nested_cls_t<char> *nk3; // ok
cls<int> uk1; // expected-error 1+{{explicit specialization of 'cls<int>' must be imported}} expected-error 1+{{definition of}}
- cls<int*> uk3; // expected-error 1+{{partial specialization of 'cls<type-parameter-0-0 *>' must be imported}} expected-error 1+{{definition of}}
- cls<char*> uk4; // expected-error 1+{{partial specialization of 'cls<type-parameter-0-0 *>' must be imported}} expected-error 1+{{definition of}}
+ cls<int*> uk3; // expected-error 1+{{partial specialization of 'cls<T *>' must be imported}} expected-error 1+{{definition of}}
+ cls<char*> uk4; // expected-error 1+{{partial specialization of 'cls<T *>' must be imported}} expected-error 1+{{definition of}}
cls<void>::nested_cls unk1; // expected-error 1+{{explicit specialization of 'nested_cls' must be imported}} expected-error 1+{{definition of}}
cls<void>::nested_cls_t<int> unk2; // expected-error 1+{{explicit specialization of 'nested_cls_t' must be imported}} expected-error 1+{{definition of}}
cls<void>::nested_cls_t<char> unk3; // expected-error 1+{{explicit specialization of 'nested_cls_t' must be imported}}
@@ -211,8 +211,8 @@ namespace hidden_specializations {
(void)sizeof(var<void>); // ok
(void)sizeof(var<char>); // ok
(void)sizeof(var<int>); // expected-error 1+{{explicit specialization of 'var<int>' must be imported}}
- (void)sizeof(var<int*>); // expected-error 1+{{partial specialization of 'var<type-parameter-0-0 *>' must be imported}}
- (void)sizeof(var<char*>); // expected-error 1+{{partial specialization of 'var<type-parameter-0-0 *>' must be imported}}
+ (void)sizeof(var<int*>); // expected-error 1+{{partial specialization of 'var<T *>' must be imported}}
+ (void)sizeof(var<char*>); // expected-error 1+{{partial specialization of 'var<T *>' must be imported}}
(void)sizeof(cls<void>::nested_var); // ok
(void)cls<void>::nested_var; // expected-error 1+{{explicit specialization of 'nested_var' must be imported}}
(void)sizeof(cls<void>::nested_var_t<int>); // expected-error 1+{{explicit specialization of 'nested_var_t' must be imported}}
@@ -224,10 +224,10 @@ namespace hidden_specializations {
int cls<int>::nested_var; // expected-error 1+{{explicit specialization of 'cls<int>' must be imported}} expected-error 1+{{definition of}}
enum cls<int>::nested_enum : int {}; // expected-error 1+{{explicit specialization of 'cls<int>' must be imported}} expected-error 1+{{definition of}}
- template<typename T> void cls<T*>::nested_fn() {} // expected-error 1+{{partial specialization of 'cls<type-parameter-0-0 *>' must be imported}}
- template<typename T> struct cls<T*>::nested_cls {}; // expected-error 1+{{partial specialization of 'cls<type-parameter-0-0 *>' must be imported}}
- template<typename T> int cls<T*>::nested_var; // expected-error 1+{{partial specialization of 'cls<type-parameter-0-0 *>' must be imported}}
- template<typename T> enum cls<T*>::nested_enum : int {}; // expected-error 1+{{partial specialization of 'cls<type-parameter-0-0 *>' must be imported}}
+ template<typename T> void cls<T*>::nested_fn() {} // expected-error 1+{{partial specialization of 'cls<T *>' must be imported}}
+ template<typename T> struct cls<T*>::nested_cls {}; // expected-error 1+{{partial specialization of 'cls<T *>' must be imported}}
+ template<typename T> int cls<T*>::nested_var; // expected-error 1+{{partial specialization of 'cls<T *>' must be imported}}
+ template<typename T> enum cls<T*>::nested_enum : int {}; // expected-error 1+{{partial specialization of 'cls<T *>' must be imported}}
}
namespace Std {
@@ -249,10 +249,10 @@ namespace Std {
// CHECK-DUMP: ClassTemplateDecl {{.*}} <{{.*[/\\]}}cxx-templates-common.h:1:1, {{.*}}> col:{{.*}} in cxx_templates_common SomeTemplate
// CHECK-DUMP: ClassTemplateSpecializationDecl {{.*}} prev {{.*}} SomeTemplate
-// CHECK-DUMP-NEXT: TemplateArgument type 'char [1]'
-// CHECK-DUMP: ClassTemplateSpecializationDecl {{.*}} SomeTemplate definition
-// CHECK-DUMP-NEXT: TemplateArgument type 'char [1]'
-// CHECK-DUMP: ClassTemplateSpecializationDecl {{.*}} prev {{.*}} SomeTemplate
// CHECK-DUMP-NEXT: TemplateArgument type 'char [2]'
// CHECK-DUMP: ClassTemplateSpecializationDecl {{.*}} SomeTemplate definition
// CHECK-DUMP-NEXT: TemplateArgument type 'char [2]'
+// CHECK-DUMP: ClassTemplateSpecializationDecl {{.*}} prev {{.*}} SomeTemplate
+// CHECK-DUMP-NEXT: TemplateArgument type 'char [1]'
+// CHECK-DUMP: ClassTemplateSpecializationDecl {{.*}} SomeTemplate definition
+// CHECK-DUMP-NEXT: TemplateArgument type 'char [1]'
diff --git a/test/Modules/dependency-dump-dependent-module.m b/test/Modules/dependency-dump-dependent-module.m
index df7f5326bb6c..2430726d3ae5 100644
--- a/test/Modules/dependency-dump-dependent-module.m
+++ b/test/Modules/dependency-dump-dependent-module.m
@@ -14,9 +14,3 @@
// VFS: 'name': "Sub2.h"
@import AlsoDependsOnModule;
-
-// FIXME: This fails on win32 due to ERROR_FILENAME_EXCED_RANGE
-// if the working directory is too deep.
-// We should make Win32/Path.inc capable of long pathnames with '\\?\'.
-// For now, this is suppressed on win32.
-// REQUIRES: shell
diff --git a/test/Modules/diagnostic-options-out-of-date.m b/test/Modules/diagnostic-options-out-of-date.m
new file mode 100644
index 000000000000..ed9e8e1fe183
--- /dev/null
+++ b/test/Modules/diagnostic-options-out-of-date.m
@@ -0,0 +1,12 @@
+// RUN: rm -rf %t
+// Build A.pcm
+// RUN: %clang_cc1 -Werror -Wno-conversion -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -I %S/Inputs %s -fmodules-disable-diagnostic-validation
+// Build pch that imports A.pcm
+// RUN: %clang_cc1 -Werror -Wno-conversion -emit-pch -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -o %t.pch -I %S/Inputs -x objective-c-header %S/Inputs/pch-import-module-out-of-date.pch -fmodules-disable-diagnostic-validation
+// Make sure that we don't rebuild A.pcm and overwrite the original A.pcm that the pch imports
+// RUN: %clang_cc1 -Werror -Wconversion -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -I %S/Inputs %s -fmodules-disable-diagnostic-validation
+// Make sure we don't error out when using the pch
+// RUN: %clang_cc1 -Werror -Wno-conversion -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -fsyntax-only -I %S/Inputs -include-pch %t.pch %s -verify -fmodules-disable-diagnostic-validation
+// expected-no-diagnostics
+
+@import DiagOutOfDate;
diff --git a/test/Modules/embed-files.cpp b/test/Modules/embed-files.cpp
index f300558dd7f7..8e5a16e54400 100644
--- a/test/Modules/embed-files.cpp
+++ b/test/Modules/embed-files.cpp
@@ -10,6 +10,10 @@
//
// RUN: %clang_cc1 -fmodules -I%t -fmodules-embed-all-files %t/modulemap -fmodule-name=a -x c++ -emit-module -o %t/a.pcm
// RUN: %clang_cc1 -fmodules -I%t -fmodules-embed-all-files %t/modulemap -fmodule-name=b -x c++ -emit-module -o %t/b.pcm
+// FIXME: This test is flaky on Windows because attempting to delete a file
+// after writing it just doesn't seem to work well, at least not in the lit
+// shell.
+// REQUIRES: shell
// RUN: rm %t/x.h
// RUN: %clang_cc1 -fmodules -I%t -fmodule-map-file=%t/modulemap -fmodule-file=%t/a.pcm -fmodule-file=%t/b.pcm %s -verify
#include "a.h"
@@ -19,3 +23,4 @@ char t; // expected-error {{different type}}
#include "b.h"
char t; // expected-error {{different type}}
// expected-note@t.h:1 {{here}}
+
diff --git a/test/Modules/empty.modulemap b/test/Modules/empty.modulemap
index 0d1718409d55..aa9eba66a4f8 100644
--- a/test/Modules/empty.modulemap
+++ b/test/Modules/empty.modulemap
@@ -14,7 +14,6 @@
// RUN: diff %t/base.pcm %t/check.pcm
//
// We expect an empty module to be less than 30KB (and at least 10K, for now).
-// REQUIRES: shell
// RUN: wc -c %t/base.pcm | FileCheck --check-prefix=CHECK-SIZE %s
// CHECK-SIZE: {{(^|[^0-9])[12][0-9][0-9][0-9][0-9]($|[^0-9])}}
diff --git a/test/Modules/explicit-build-extra-files.cpp b/test/Modules/explicit-build-extra-files.cpp
index 6cec420832d6..965aea13ae13 100644
--- a/test/Modules/explicit-build-extra-files.cpp
+++ b/test/Modules/explicit-build-extra-files.cpp
@@ -1,5 +1,3 @@
-// REQUIRES: shell
-//
// RUN: rm -rf %t
// RUN: mkdir %t
// RUN: cd %t
diff --git a/test/Modules/explicit-build.cpp b/test/Modules/explicit-build.cpp
index a6f6a6268c15..16eb604708c9 100644
--- a/test/Modules/explicit-build.cpp
+++ b/test/Modules/explicit-build.cpp
@@ -167,7 +167,7 @@
// RUN: -fmodule-file=%t/nonexistent.pcm \
// RUN: %s 2>&1 | FileCheck --check-prefix=CHECK-NO-FILE %s
//
-// CHECK-NO-FILE: fatal error: module file '{{.*}}nonexistent.pcm' not found
+// CHECK-NO-FILE: fatal error: module file '{{.*}}nonexistent.pcm' not found: module file not found
// RUN: mv %t/a.pcm %t/a-tmp.pcm
// RUN: not %clang_cc1 -x c++ -std=c++11 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -Rmodule-build -fno-modules-error-recovery \
@@ -199,6 +199,6 @@
// RUN: -fmodule-file=%t/c.pcm \
// RUN: %s -DHAVE_A -DHAVE_B -DHAVE_C 2>&1 | FileCheck --check-prefix=CHECK-MISMATCHED-B %s
//
-// CHECK-MISMATCHED-B: fatal error: module file '{{.*}}b.pcm' is out of date and needs to be rebuilt
+// CHECK-MISMATCHED-B: fatal error: module file '{{.*}}b.pcm' is out of date and needs to be rebuilt: module file out of date
// CHECK-MISMATCHED-B-NEXT: note: imported by module 'c'
// CHECK-MISMATCHED-B-NOT: note:
diff --git a/test/Modules/global-init.cpp b/test/Modules/global-init.cpp
new file mode 100644
index 000000000000..fb42464dcc92
--- /dev/null
+++ b/test/Modules/global-init.cpp
@@ -0,0 +1,19 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+//
+// RUN: echo '#pragma once' > %t/a.h
+// RUN: echo 'struct A { A() {} int f() const; } const a;' >> %t/a.h
+//
+// RUN: echo '#include "a.h"' > %t/b.h
+//
+// RUN: echo 'module M { module b { header "b.h" export * } module a { header "a.h" export * } }' > %t/map
+//
+// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -fmodule-map-file=%t/map -I%t %s -emit-llvm -o - -triple %itanium_abi_triple | FileCheck %s
+
+#include "b.h"
+
+// CHECK: @_ZL1a = internal global
+// CHECK: call {{.*}} @_ZN1AC1Ev({{.*}}@_ZL1a
+// CHECK: call {{.*}} @_ZNK1A1fEv({{.*}}@_ZL1a
+// CHECK: store {{.*}} @x
+int x = a.f();
diff --git a/test/Modules/implicit-private-with-different-name.m b/test/Modules/implicit-private-with-different-name.m
new file mode 100644
index 000000000000..3d8f937973f0
--- /dev/null
+++ b/test/Modules/implicit-private-with-different-name.m
@@ -0,0 +1,20 @@
+// RUN: rm -rf %t
+
+// Build PCH using A, with adjacent private module APrivate, which winds up being implicitly referenced
+// RUN: %clang_cc1 -verify -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F %S/Inputs/implicit-private-with-different-name -emit-pch -o %t-A.pch %s
+
+// Use the PCH with no explicit way to resolve PrivateA, still pick it up through MODULE_DIRECTORY reference in PCH control block
+// RUN: %clang_cc1 -verify -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F %S/Inputs/implicit-private-with-different-name -include-pch %t-A.pch %s -fsyntax-only
+
+// Check the fixit
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F %S/Inputs/implicit-private-with-different-name -include-pch %t-A.pch %s -fsyntax-only -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
+
+// expected-warning@Inputs/implicit-private-with-different-name/A.framework/Modules/module.private.modulemap:1{{top-level module 'APrivate' in private module map, expected a submodule of 'A'}}
+// expected-note@Inputs/implicit-private-with-different-name/A.framework/Modules/module.private.modulemap:1{{make 'APrivate' a submodule of 'A' to ensure it can be found by name}}
+// CHECK: fix-it:"{{.*}}module.private.modulemap":{1:18-1:26}:"A.Private"
+
+#ifndef HEADER
+#define HEADER
+#import "A/aprivate.h"
+const int *y = &APRIVATE;
+#endif
diff --git a/test/Modules/incomplete-module.m b/test/Modules/incomplete-module.m
index e338a40c9ab5..ffb2708c6f81 100644
--- a/test/Modules/incomplete-module.m
+++ b/test/Modules/incomplete-module.m
@@ -2,7 +2,7 @@
// RUN: rm -rf %t
// RUN: %clang_cc1 -fmodules-cache-path=%t -Wincomplete-module -fmodules -fimplicit-module-maps -I %S/Inputs %s 2>&1 | FileCheck %s
-// CHECK: warning: include of non-modular header inside module 'incomplete_mod'
+// CHECK: warning: include of non-modular header inside module 'incomplete_mod': {{'.*incomplete_mod_missing.h'}}
// RUN: rm -rf %t
// RUN: not %clang_cc1 -fmodules-cache-path=%t -fmodules-strict-decluse -fmodules -fimplicit-module-maps -I %S/Inputs %s 2>&1 | FileCheck %s -check-prefix=DECLUSE
diff --git a/test/Modules/lambda-context.cpp b/test/Modules/lambda-context.cpp
new file mode 100644
index 000000000000..6ce482c2b763
--- /dev/null
+++ b/test/Modules/lambda-context.cpp
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -fmodules -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fmodules -std=c++11 -include-pch %t %s -verify
+//
+// This test checks for a bug in the deserialization code that was only
+// reachable with modules enabled, but actually building and using modules is
+// not necessary in order to trigger it, so we just use PCH here to make the
+// test simpler.
+
+#ifndef HEADER_INCLUDED
+#define HEADER_INCLUDED
+
+struct X { template <typename T> X(T) {} };
+struct Y { Y(X x = [] {}); };
+
+#else
+
+// This triggers us to load the specialization of X::X for Y's lambda. That
+// lambda's context decl must not be loaded as a result of loading the lambda,
+// as that would hit a deserialization cycle.
+X x = [] {}; // expected-no-diagnostics
+
+#endif
diff --git a/test/Modules/libc-libcxx.cpp b/test/Modules/libc-libcxx.cpp
new file mode 100644
index 000000000000..1f6a86b7782a
--- /dev/null
+++ b/test/Modules/libc-libcxx.cpp
@@ -0,0 +1,10 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -x c++ -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -I %S/Inputs/libc-libcxx/include/c++ -I %S/Inputs/libc-libcxx/include %s -verify
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -x c++ -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -fmodules-local-submodule-visibility -nostdinc++ -isystem %S/Inputs/libc-libcxx/sysroot/usr/include/c++/v1 -isystem %S/Inputs/libc-libcxx/sysroot/usr/include -fsyntax-only %s -verify
+// expected-no-diagnostics
+
+#include "math.h"
+
+int n = abs(0);
+float f = abs<float>(0.f);
diff --git a/test/Modules/lookup-assert.m b/test/Modules/lookup-assert.m
new file mode 100644
index 000000000000..2697fb15d018
--- /dev/null
+++ b/test/Modules/lookup-assert.m
@@ -0,0 +1,10 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -I %S/Inputs/lookup-assert %s -verify
+// expected-no-diagnostics
+
+#include "Derive.h"
+#import <H3.h>
+@implementation DerivedInterface
+- (void)test {
+}
+@end
diff --git a/test/Modules/merge-fn-prototype-tags.c b/test/Modules/merge-fn-prototype-tags.c
new file mode 100644
index 000000000000..f43f1dc49d9e
--- /dev/null
+++ b/test/Modules/merge-fn-prototype-tags.c
@@ -0,0 +1,8 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -x c -I%S/Inputs/merge-fn-prototype-tags -verify %s
+// RUN: %clang_cc1 -fmodules -fmodule-map-file=%S/Inputs/merge-fn-prototype-tags/module.modulemap -fmodules-cache-path=%t -x c -I%S/Inputs/merge-fn-prototype-tags -verify %s
+
+#include "c.h"
+void mmalloc_attach() { struct stat sbuf; }
+
+// expected-no-diagnostics
diff --git a/test/Modules/merge-name-for-linkage.cpp b/test/Modules/merge-name-for-linkage.cpp
index da1664ca343d..75534bd661b9 100644
--- a/test/Modules/merge-name-for-linkage.cpp
+++ b/test/Modules/merge-name-for-linkage.cpp
@@ -2,6 +2,7 @@
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I%S/Inputs/merge-name-for-linkage -verify %s
// expected-no-diagnostics
typedef union {} pthread_mutex_t;
+typedef pthread_mutex_t pthread_mutex_t;
#include "a.h"
pthread_mutex_t x;
#include "b.h"
diff --git a/test/Modules/merge-template-pattern-visibility.cpp b/test/Modules/merge-template-pattern-visibility.cpp
index db759b5a46a1..ec5aa26c68d8 100644
--- a/test/Modules/merge-template-pattern-visibility.cpp
+++ b/test/Modules/merge-template-pattern-visibility.cpp
@@ -1,4 +1,18 @@
// RUN: rm -rf %t
-// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -fno-modules-error-recovery \
+// RUN: %clang_cc1 -fmodules -fno-modules-error-recovery -std=c++14 \
// RUN: -fmodule-name=X -emit-module %S/Inputs/merge-template-pattern-visibility/module.modulemap -x c++ \
-// RUN: -fmodules-local-submodule-visibility
+// RUN: -fmodules-local-submodule-visibility -o %t/X.pcm
+// RUN: %clang_cc1 -fmodules -fno-modules-error-recovery -std=c++14 \
+// RUN: -fmodule-name=Y -emit-module %S/Inputs/merge-template-pattern-visibility/module.modulemap -x c++ \
+// RUN: -fmodules-local-submodule-visibility -o %t/Y.pcm
+// RUN: %clang_cc1 -fmodules -fno-modules-error-recovery -std=c++14 -fmodule-file=%t/X.pcm -fmodule-file=%t/Y.pcm \
+// RUN: -fmodules-local-submodule-visibility -verify %s -I%S/Inputs/merge-template-pattern-visibility
+
+#include "b.h"
+#include "d.h"
+
+// expected-no-diagnostics
+void g() {
+ CrossModuleMerge::B<int> bi;
+ CrossModuleMerge::C(0);
+}
diff --git a/test/Modules/merge-template-specializations.cpp b/test/Modules/merge-template-specializations.cpp
new file mode 100644
index 000000000000..25db93fbbb20
--- /dev/null
+++ b/test/Modules/merge-template-specializations.cpp
@@ -0,0 +1,5 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -fimplicit-module-maps -fmodules-local-submodule-visibility -I%S/Inputs/merge-template-specializations -std=c++11 -verify %s
+// expected-no-diagnostics
+#include "c.h"
+X x;
diff --git a/test/Modules/merge-var-template-def.cpp b/test/Modules/merge-var-template-def.cpp
new file mode 100644
index 000000000000..97a72a194d9d
--- /dev/null
+++ b/test/Modules/merge-var-template-def.cpp
@@ -0,0 +1,7 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -I%S/Inputs/merge-var-template-def -std=c++11 -verify %s
+// RUN: %clang_cc1 -I%S/Inputs/merge-var-template-def -std=c++11 -verify -fmodules -Werror=undefined-internal -fmodules-local-submodule-visibility -fmodules-cache-path=%t -fimplicit-module-maps %s
+// expected-no-diagnostics
+
+#include "b2.h"
+const bool *y = &S<bool, false>::value;
diff --git a/test/Modules/module-file-modified.c b/test/Modules/module-file-modified.c
new file mode 100644
index 000000000000..85018b521e28
--- /dev/null
+++ b/test/Modules/module-file-modified.c
@@ -0,0 +1,11 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: echo 'int foo = 0;' > %t/a.h
+// RUN: echo 'module A { header "a.h" }' > %t/m.modulemap
+// RUN: %clang_cc1 -fmodules -emit-module -fmodule-name=A -x c %t/m.modulemap -o %t/m.pcm
+// RUN: echo 'int bar;' > %t/a.h
+// RUN: not %clang_cc1 -fmodules -fmodule-file=%t/m.pcm -fmodule-map-file=%t/m.modulemap -x c %s -I%t -fsyntax-only 2>&1 | FileCheck %s
+#include "a.h"
+int foo = 0; // redefinition of 'foo'
+// CHECK: fatal error: file {{.*}} has been modified since the module file {{.*}} was built
+// REQUIRES: shell
diff --git a/test/Modules/module_file_info.m b/test/Modules/module_file_info.m
index 8693d2b89497..fa841b75926c 100644
--- a/test/Modules/module_file_info.m
+++ b/test/Modules/module_file_info.m
@@ -1,10 +1,17 @@
@import DependsOnModule;
-// RUN: rm -rf %t
-// RUN: %clang_cc1 -w -Wunused -fmodules -fimplicit-module-maps -fdisable-module-hash -fmodules-cache-path=%t -F %S/Inputs -DBLARG -DWIBBLE=WOBBLE -fmodule-feature myfeature %s
+// RUN: rm -rf %t %t-obj
+// RUN: %clang_cc1 -w -Wunused -fmodules -fmodule-format=raw -fimplicit-module-maps -fdisable-module-hash -fmodules-cache-path=%t -F %S/Inputs -DBLARG -DWIBBLE=WOBBLE -fmodule-feature myfeature %s
// RUN: %clang_cc1 -module-file-info %t/DependsOnModule.pcm | FileCheck %s
+// RUN: %clang_cc1 -module-file-info %t/DependsOnModule.pcm | FileCheck %s --check-prefix=RAW
+// RUN: %clang_cc1 -w -Wunused -fmodules -fmodule-format=obj -fimplicit-module-maps -fdisable-module-hash -fmodules-cache-path=%t-obj -F %S/Inputs -DBLARG -DWIBBLE=WOBBLE -fmodule-feature myfeature %s
+// RUN: %clang_cc1 -module-file-info %t-obj/DependsOnModule.pcm | FileCheck %s
+// RUN: %clang_cc1 -module-file-info %t-obj/DependsOnModule.pcm | FileCheck %s --check-prefix=OBJ
+
+// RAW: Module format: raw
+// OBJ: Module format: obj
// CHECK: Generated by this Clang:
// CHECK: Module name: DependsOnModule
diff --git a/test/Modules/no-stale-modtime.m b/test/Modules/no-stale-modtime.m
index b90daf123ef0..c7ff21c22a9f 100644
--- a/test/Modules/no-stale-modtime.m
+++ b/test/Modules/no-stale-modtime.m
@@ -7,9 +7,13 @@
// RUN: echo '@import l; @import r;' > %t/b.h
// RUN: echo '@import t; // fromt l' > %t/l.h
// RUN: echo '@import t; // fromt r' > %t/r.h
-// RUN: echo '// top' > %t/t.h
-// RUN: echo 'module b { header "b.h" } module l { header "l.h" }' > %t/module.map
-// RUN: echo 'module r { header "r.h" } module t { header "t.h" }' >> %t/module.map
+
+// RUN: echo '// top' > %t/t.h-1
+// RUN: cat %t/t.h-1 > %t/t.h
+
+// RUN: echo 'module b { header "b.h" } module l { header "l.h" }' > %t/module.map-1
+// RUN: echo 'module r { header "r.h" } module t { header "t.h" }' > %t/module.map-2
+// RUN: cat %t/module.map-1 %t/module.map-2 > %t/module.map
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -fdisable-module-hash \
// RUN: -I %t -fsyntax-only %s -Rmodule-build 2>&1 \
@@ -18,7 +22,9 @@
// RUN: -I %t -fsyntax-only %s -Rmodule-build -verify
// Add an identifier to ensure everything depending on t is out of date
-// RUN: echo 'extern int a;' >> %t/t.h
+// RUN: echo 'extern int a;' > %t/t.h-2
+// RUN: cat %t/t.h-1 %t/t.h-2 > %t/t.h
+
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -fdisable-module-hash \
// RUN: -I %t -fsyntax-only %s -Rmodule-build 2>&1 \
// RUN: | FileCheck -check-prefix=REBUILD-ALL %s
diff --git a/test/Modules/objc-category-2.m b/test/Modules/objc-category-2.m
new file mode 100644
index 000000000000..3a6f52d6105a
--- /dev/null
+++ b/test/Modules/objc-category-2.m
@@ -0,0 +1,12 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -I %S/Inputs/objc-category-2 %s -verify -fobjc-arc
+
+// We have a definition of category and the base interface imported from a
+// module, definition for the base interface is also textually included.
+// Currently we emit an error "duplicate interface definition".
+#import <Category.h>
+#include "H3.h"
+
+void test(DVTSourceModel *m) {
+ [m test:1];
+}
diff --git a/test/Modules/objc-category-3.m b/test/Modules/objc-category-3.m
new file mode 100644
index 000000000000..b5162bffbfef
--- /dev/null
+++ b/test/Modules/objc-category-3.m
@@ -0,0 +1,14 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -I %S/Inputs/objc-category-3 %s -verify -fobjc-arc
+// expected-no-diagnostics
+
+// We have a definition of the base interface textually included from
+// Category.h, the definition is also in the module that includes the base
+// interface. We should be able to see both categories in the TU.
+#include "Category.h"
+#import <Category_B.h>
+
+void test(DVTSourceModel *m) {
+ [m test:1];
+ [m testB:1 matchingMask:2];
+}
diff --git a/test/Modules/objc-category.m b/test/Modules/objc-category.m
new file mode 100644
index 000000000000..944c7ea625dc
--- /dev/null
+++ b/test/Modules/objc-category.m
@@ -0,0 +1,13 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -I %S/Inputs/objc-category %s -verify -fobjc-arc
+// expected-no-diagnostics
+
+// We have a definition of the base interface textually included from
+// Category.h, the definition is also in the module that includes the base
+// interface. We should be able to see the category in the TU.
+#include "Category.h"
+#import <H3.h>
+
+void test(DVTSourceModel *m) {
+ [m test:1];
+}
diff --git a/test/Modules/objc-hidden.m b/test/Modules/objc-hidden.m
new file mode 100644
index 000000000000..6e40e0d7d191
--- /dev/null
+++ b/test/Modules/objc-hidden.m
@@ -0,0 +1,11 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fsyntax-only -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -I %S/Inputs/objc-hidden/System -F %S/Inputs/objc-hidden -verify -x objective-c %s
+// expected-no-diagnostics
+
+// Make sure we don't crash with hidden decls.
+@import FakeUnavailableObjCFramework;
+
+@implementation UnavailableObjCClass
+- (void)someMethod { }
+@end
+
diff --git a/test/Modules/objc-initializer.m b/test/Modules/objc-initializer.m
new file mode 100644
index 000000000000..adb7a06a2bf6
--- /dev/null
+++ b/test/Modules/objc-initializer.m
@@ -0,0 +1,15 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -I %S/Inputs/objc-initializer %s -emit-llvm -o - -fobjc-arc | FileCheck %s
+// RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -I %S/Inputs/objc-initializer %s -emit-llvm -o - -fobjc-arc -DIMPORT_TOP | FileCheck %s
+// CHECK: kSimDeviceIOGetInterface = internal constant {{.*}} bitcast
+
+#ifdef IMPORT_TOP
+@import X;
+#else
+#import <X.h>
+#endif
+
+void test2(const NSString*);
+void test() {
+ test2(kSimDeviceIOGetInterface);
+}
diff --git a/test/Modules/objc-method-redecl.m b/test/Modules/objc-method-redecl.m
new file mode 100644
index 000000000000..f7acda5450d6
--- /dev/null
+++ b/test/Modules/objc-method-redecl.m
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -x objective-c-header -emit-pch %S/Inputs/objc-method-redecl.h -o %t.pch -Wno-objc-root-class
+// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -x objective-c -include-pch %t.pch %s -verify -Wno-objc-root-class
+// expected-no-diagnostics
+
+@implementation T
+- (void)test {
+}
+@end
diff --git a/test/Modules/odr.cpp b/test/Modules/odr.cpp
index 30143968ffb2..9cdbb4f0806d 100644
--- a/test/Modules/odr.cpp
+++ b/test/Modules/odr.cpp
@@ -15,9 +15,9 @@ bool b = F<int>{0} == F<int>{1};
int x = f() + g();
// expected-note@a.h:5 {{definition has no member 'e2'}}
-// expected-note@b.h:3 {{declaration of 'f' does not match}}
-// expected-note@b.h:1 {{definition has no member 'n'}}
+// expected-note@a.h:3 {{declaration of 'f' does not match}}
+// expected-note@a.h:1 {{definition has no member 'm'}}
// expected-error@b.h:5 {{'E::e2' from module 'b' is not present in definition of 'E' in module 'a'}}
-// expected-error@a.h:3 {{'Y::f' from module 'a' is not present in definition of 'Y' in module 'b'}}
-// expected-error@a.h:2 {{'Y::n' from module 'a' is not present in definition of 'Y' in module 'b'}}
+// expected-error@b.h:3 {{'Y::f' from module 'b' is not present in definition of 'Y' in module 'a'}}
+// expected-error@b.h:2 {{'Y::m' from module 'b' is not present in definition of 'Y' in module 'a'}}
diff --git a/test/Modules/pr27699.cpp b/test/Modules/pr27699.cpp
new file mode 100644
index 000000000000..0a17fcba56ff
--- /dev/null
+++ b/test/Modules/pr27699.cpp
@@ -0,0 +1,9 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -std=c++11 -I%S/Inputs/PR27699 -verify %s
+// RUN: %clang_cc1 -std=c++11 -fmodules -fmodule-map-file=%S/Inputs/PR27699/module.modulemap -fmodules-cache-path=%t -fmodules-local-submodule-visibility -I%S/Inputs/PR27699 -verify %s
+
+#include "Subdir/a.h"
+#include "Subdir/b.h"
+
+// expected-no-diagnostics
+
diff --git a/test/Modules/pr28438.cpp b/test/Modules/pr28438.cpp
new file mode 100644
index 000000000000..43c9ea549da5
--- /dev/null
+++ b/test/Modules/pr28438.cpp
@@ -0,0 +1,7 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fsyntax-only -verify %s -fmodules -fmodules-cache-path=%t -I%S/Inputs/PR28438 -fimplicit-module-maps
+
+#include "a.h"
+#include "b2.h"
+
+FOO // expected-no-diagnostics
diff --git a/test/Modules/pr28752.cpp b/test/Modules/pr28752.cpp
new file mode 100644
index 000000000000..1c7896152c9f
--- /dev/null
+++ b/test/Modules/pr28752.cpp
@@ -0,0 +1,22 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -std=c++11 -nostdsysteminc -I%S/Inputs/PR28752 -verify %s
+// RUN: %clang_cc1 -std=c++11 -nostdsysteminc -fmodules -fmodule-map-file=%S/Inputs/PR28752/Subdir1/module.modulemap -fmodule-map-file=%S/Inputs/PR28752/module.modulemap -fmodules-cache-path=%t -I%S/Inputs/PR28752 -I%S/Inputs/PR28752/Subdir1 -verify %s -fmodules-local-submodule-visibility
+
+#include "a.h"
+#include "Subdir1/c.h"
+#include <vector>
+
+class TClingClassInfo {
+ std::vector<int> fIterStack;
+};
+
+TClingClassInfo *a;
+class TClingBaseClassInfo {
+ TClingBaseClassInfo() { new TClingClassInfo(*a); }
+};
+
+namespace { struct Q; }
+bool *p = &A<Q>::b;
+
+// expected-no-diagnostics
+
diff --git a/test/Modules/pr28812.cpp b/test/Modules/pr28812.cpp
new file mode 100644
index 000000000000..78267d2a4b44
--- /dev/null
+++ b/test/Modules/pr28812.cpp
@@ -0,0 +1,22 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -std=c++11 -nostdsysteminc -I%S/Inputs/PR28812 -verify %s
+// RUN: %clang_cc1 -std=c++11 -nostdsysteminc -fmodules -fimplicit-module-maps \
+// RUN: -fmodules-cache-path=%t -I%S/Inputs/PR28812 -verify %s
+
+template <typename> struct VarStreamArrayIterator;
+template <typename ValueType>
+struct VarStreamArray {
+ typedef VarStreamArrayIterator<ValueType> Iterator;
+ Iterator begin() { return Iterator(*this); }
+};
+
+#include "Textual.h"
+
+#include "a.h"
+#include "b.h"
+
+VarStreamArray<int> a;
+auto b = a.begin();
+
+// expected-no-diagnostics
+
diff --git a/test/Modules/prebuilt-module.m b/test/Modules/prebuilt-module.m
new file mode 100644
index 000000000000..d5012e0e85f3
--- /dev/null
+++ b/test/Modules/prebuilt-module.m
@@ -0,0 +1,10 @@
+// RUN: rm -rf %t
+//
+// RUN: %clang_cc1 -fmodules -x objective-c -I %S/Inputs/prebuilt-module -emit-module %S/Inputs/prebuilt-module/module.modulemap -fmodule-name=prebuilt -o %t/prebuilt.pcm
+// RUN: %clang_cc1 -fmodules -fprebuilt-module-path=%t/ -fdisable-module-hash %s -verify
+
+// expected-no-diagnostics
+@import prebuilt;
+int test() {
+ return a;
+}
diff --git a/test/Modules/prune.m b/test/Modules/prune.m
index 6676407c9acd..58992f9c006d 100644
--- a/test/Modules/prune.m
+++ b/test/Modules/prune.m
@@ -5,9 +5,6 @@
@import Module;
#endif
-// We need 'touch' and 'find' for this test to work.
-// REQUIRES: shell
-
// Clear out the module cache
// RUN: rm -rf %t
// Run Clang twice so we end up creating the timestamp file (the second time).
@@ -28,7 +25,7 @@
// Set the DependsOnModule access time back more than four days.
// This shouldn't prune anything, because the timestamp has been updated, so
// the pruning mechanism won't fire.
-// RUN: find %t -name DependsOnModule*.pcm | xargs touch -a -t 201101010000
+// RUN: find %t -name DependsOnModule*.pcm | sed -e 's/\\/\//g' | xargs touch -a -t 201101010000
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -F %S/Inputs -fmodules-cache-path=%t -fmodules -fmodules-prune-interval=172800 -fmodules-prune-after=345600 %s -verify
// RUN: ls %t | grep modules.timestamp
// RUN: ls -R %t | grep ^Module.*pcm
@@ -37,7 +34,7 @@
// Set both timestamp and DependsOnModule.pcm back beyond the cutoff.
// This should trigger pruning, which will remove DependsOnModule but not Module.
// RUN: touch -m -a -t 201101010000 %t/modules.timestamp
-// RUN: find %t -name DependsOnModule*.pcm | xargs touch -a -t 201101010000
+// RUN: find %t -name DependsOnModule*.pcm | sed -e 's/\\/\//g' | xargs touch -a -t 201101010000
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -F %S/Inputs -fmodules-cache-path=%t -fmodules -fmodules-prune-interval=172800 -fmodules-prune-after=345600 %s -verify
// RUN: ls %t | grep modules.timestamp
// RUN: ls -R %t | grep ^Module.*pcm
diff --git a/test/Modules/redundant-include.mm b/test/Modules/redundant-include.mm
new file mode 100644
index 000000000000..d736022699c3
--- /dev/null
+++ b/test/Modules/redundant-include.mm
@@ -0,0 +1,12 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -I%S/Inputs %s -verify
+// RUN: %clang_cc1 -fmodules-cache-path=%t -fimplicit-module-maps -I%S/Inputs %s -verify
+
+#include "cxx-header.h"
+void includeNotAtTopLevel() { // expected-note {{function 'includeNotAtTopLevel' begins here}}
+ #include "cxx-header.h" // expected-error {{redundant #include of module 'cxx_library' appears within function 'includeNotAtTopLevel'}}
+}
+
+namespace NS { // expected-note {{begins here}}
+ #include "cxx-header.h" // expected-error {{redundant #include of module 'cxx_library' appears within namespace 'NS'}}
+}
diff --git a/test/Modules/requires-gnuinlineasm.m b/test/Modules/requires-gnuinlineasm.m
new file mode 100644
index 000000000000..80b1b18d0742
--- /dev/null
+++ b/test/Modules/requires-gnuinlineasm.m
@@ -0,0 +1,16 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules \
+// RUN: -fimplicit-module-maps -F %S/Inputs/GNUAsm %s \
+// RUN: -fno-gnu-inline-asm -DNO_ASM_INLINE -verify
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules \
+// RUN: -fimplicit-module-maps -F %S/Inputs/GNUAsm %s \
+// RUN: -DASM_INLINE -verify
+
+#ifdef NO_ASM_INLINE
+@import NeedsGNUInlineAsm.Asm; // expected-error{{module 'NeedsGNUInlineAsm.Asm' requires feature 'gnuinlineasm'}}
+#endif
+
+#ifdef ASM_INLINE
+@import NeedsGNUInlineAsm.Asm; // expected-no-diagnostics
+#endif
diff --git a/test/Modules/signal.m b/test/Modules/signal.m
index 37a35506447d..4d0885e56c8b 100644
--- a/test/Modules/signal.m
+++ b/test/Modules/signal.m
@@ -1,4 +1,4 @@
-// REQUIRES: crash-recovery,shell
+// REQUIRES: crash-recovery
// RUN: rm -rf %t
// Crash building module.
diff --git a/test/Modules/stress-objc.m b/test/Modules/stress-objc.m
new file mode 100644
index 000000000000..edbebd3576a9
--- /dev/null
+++ b/test/Modules/stress-objc.m
@@ -0,0 +1,22 @@
+// RUN: cd %S
+
+// RUN: %clang_cc1 -emit-pch -x objective-c-header %s -o %t_c00.pch -fno-pch-timestamp
+// RUN: %clang_cc1 -emit-pch -x objective-c-header %s -o %t_c00_1.pch -fno-pch-timestamp
+// RUN: diff %t_c00.pch %t_c00_1.pch
+
+// RUN: %clang_cc1 -emit-pch -x objective-c-header %s -o %t_c00_2.pch -fno-pch-timestamp
+// RUN: diff %t_c00.pch %t_c00_2.pch
+
+// RUN: %clang_cc1 -emit-pch -x objective-c-header %s -o %t_c00_3.pch -fno-pch-timestamp
+// RUN: diff %t_c00.pch %t_c00_3.pch
+
+// RUN: %clang_cc1 -emit-pch -x objective-c-header %s -o %t_c00_4.pch -fno-pch-timestamp
+// RUN: diff %t_c00.pch %t_c00_4.pch
+
+// RUN: %clang_cc1 -emit-pch -x objective-c-header %s -o %t_c00_5.pch -fno-pch-timestamp
+// RUN: diff %t_c00.pch %t_c00_5.pch
+
+@protocol NSObject
+- (void)doesNotRecognizeSelector:(SEL)aSelector;
+- (id)forwardingTargetForSelector:(SEL)aSelector;
+@end
diff --git a/test/Modules/templates.mm b/test/Modules/templates.mm
index 190084ad2b74..79e975a1ad12 100644
--- a/test/Modules/templates.mm
+++ b/test/Modules/templates.mm
@@ -12,10 +12,10 @@ void testInlineRedeclEarly() {
@import templates_right;
-// CHECK-DAG: @list_left = global %class.List { %"struct.List<int>::node"* null, i32 8 }, align 8
-// CHECK-DAG: @list_right = global %class.List { %"struct.List<int>::node"* null, i32 12 }, align 8
-// CHECK-DAG: @_ZZ15testMixedStructvE1l = {{.*}} constant %class.List { %{{.*}}* null, i32 1 }, align 8
-// CHECK-DAG: @_ZZ15testMixedStructvE1r = {{.*}} constant %class.List { %{{.*}}* null, i32 2 }, align 8
+// CHECK-DAG: @list_left = global %[[LIST:.*]] { %[[LISTNODE:.*]]* null, i32 8 }, align 8
+// CHECK-DAG: @list_right = global %[[LIST]] { %[[LISTNODE]]* null, i32 12 }, align 8
+// CHECK-DAG: @_ZZ15testMixedStructvE1l = {{.*}} constant %[[LIST]] { %{{.*}}* null, i32 1 }, align 8
+// CHECK-DAG: @_ZZ15testMixedStructvE1r = {{.*}} constant %[[LIST]] { %{{.*}}* null, i32 2 }, align 8
// CHECK-DAG: @_ZN29WithUndefinedStaticDataMemberIA_iE9undefinedE = external global
void testTemplateClasses() {
@@ -116,4 +116,9 @@ void testStaticDataMember() {
(void) getStaticDataMemberRight();
}
-
+void testWithAttributes() {
+ auto a = make_with_attributes_left();
+ auto b = make_with_attributes_right();
+ static_assert(alignof(decltype(a)) == 2, "");
+ static_assert(alignof(decltype(b)) == 2, "");
+}
diff --git a/test/Modules/umbrella-header-include-builtin.mm b/test/Modules/umbrella-header-include-builtin.mm
new file mode 100644
index 000000000000..75b9c905ff00
--- /dev/null
+++ b/test/Modules/umbrella-header-include-builtin.mm
@@ -0,0 +1,6 @@
+// REQUIRES: system-darwin
+
+// RUN: rm -rf %t
+// RUN: %clang -cc1 -fsyntax-only -nostdinc++ -isysroot %S/Inputs/libc-libcxx/sysroot -isystem %S/Inputs/libc-libcxx/sysroot/usr/include/c++/v1 -F%S/Inputs/libc-libcxx/sysroot/Frameworks -std=c++11 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -x objective-c++ %s
+
+#include <A/A.h>
diff --git a/test/Modules/unused-global-init.cpp b/test/Modules/unused-global-init.cpp
new file mode 100644
index 000000000000..3bd7a7f5a627
--- /dev/null
+++ b/test/Modules/unused-global-init.cpp
@@ -0,0 +1,37 @@
+// RUN: rm -rf %t
+//
+// RUN: %clang_cc1 -fmodules -fno-implicit-modules -x c++ -I %S/Inputs/unused-global-init -triple %itanium_abi_triple -emit-module %S/Inputs/unused-global-init/module.modulemap -fmodule-name=init -o %t/init.pcm
+// RUN: %clang_cc1 -fmodules -fno-implicit-modules -x c++ -I %S/Inputs/unused-global-init -triple %itanium_abi_triple -emit-module %S/Inputs/unused-global-init/module.modulemap -fmodule-name=unused -o %t/unused.pcm -fmodule-file=%t/init.pcm
+// RUN: %clang_cc1 -fmodules -fno-implicit-modules -x c++ -I %S/Inputs/unused-global-init -triple %itanium_abi_triple -emit-module %S/Inputs/unused-global-init/module.modulemap -fmodule-name=used -o %t/used.pcm -fmodule-file=%t/init.pcm
+//
+// No module file: init.h performs init.
+// RUN: %clang_cc1 -fmodules -fno-implicit-modules -x c++ -I %S/Inputs/unused-global-init -triple %itanium_abi_triple -emit-llvm -o - %s -DINIT | FileCheck --check-prefix=CHECK-INIT %s
+// RUN: %clang_cc1 -fmodules -fno-implicit-modules -x c++ -I %S/Inputs/unused-global-init -triple %itanium_abi_triple -emit-llvm -o - %s -DUSED | FileCheck --check-prefix=CHECK-INIT %s
+// RUN: %clang_cc1 -fmodules -fno-implicit-modules -x c++ -I %S/Inputs/unused-global-init -triple %itanium_abi_triple -emit-llvm -o - %s -DOTHER -DUNUSED | FileCheck --check-prefix=CHECK-NO-INIT %s
+//
+// With module files: if there is a transitive import of any part of the
+// module, we run its global initializers (even if the imported piece is not
+// visible here).
+// RUN: %clang_cc1 -fmodules -fno-implicit-modules -x c++ -I %S/Inputs/unused-global-init -triple %itanium_abi_triple -emit-llvm -o - %s -fmodule-file=%t/used.pcm -fmodule-file=%t/unused.pcm -DINIT | FileCheck --check-prefix=CHECK-INIT %s
+// RUN: %clang_cc1 -fmodules -fno-implicit-modules -x c++ -I %S/Inputs/unused-global-init -triple %itanium_abi_triple -emit-llvm -o - %s -fmodule-file=%t/used.pcm -fmodule-file=%t/unused.pcm -DOTHER | FileCheck --check-prefix=CHECK-NO-INIT %s
+// RUN: %clang_cc1 -fmodules -fno-implicit-modules -x c++ -I %S/Inputs/unused-global-init -triple %itanium_abi_triple -emit-llvm -o - %s -fmodule-file=%t/used.pcm -fmodule-file=%t/unused.pcm -DUSED | FileCheck --check-prefix=CHECK-INIT %s
+// RUN: %clang_cc1 -fmodules -fno-implicit-modules -x c++ -I %S/Inputs/unused-global-init -triple %itanium_abi_triple -emit-llvm -o - %s -fmodule-file=%t/used.pcm -fmodule-file=%t/unused.pcm -DUNUSED | FileCheck --check-prefix=CHECK-NO-INIT %s
+
+#ifdef INIT
+#include "init.h"
+#endif
+
+#ifdef OTHER
+#include "other.h"
+#endif
+
+#ifdef USED
+#include "used.h"
+#endif
+
+#ifdef UNUSED
+#include "unused.h"
+#endif
+
+// CHECK-INIT: call {{.*}}@_ZN4InitC
+// CHECK-NO-INIT-NOT: call {{.*}}@_ZN4InitC
diff --git a/test/OpenMP/atomic_ast_print.cpp b/test/OpenMP/atomic_ast_print.cpp
index 961c1e69b1fc..f1fc7c8e559e 100644
--- a/test/OpenMP/atomic_ast_print.cpp
+++ b/test/OpenMP/atomic_ast_print.cpp
@@ -43,7 +43,7 @@ T foo(T argc) {
return T();
}
-// CHECK: int a = int();
+// CHECK: T a = T();
// CHECK-NEXT: #pragma omp atomic
// CHECK-NEXT: a++;
// CHECK-NEXT: #pragma omp atomic read
@@ -74,7 +74,7 @@ T foo(T argc) {
// CHECK-NEXT: a = b;
// CHECK-NEXT: b++;
// CHECK-NEXT: }
-// CHECK: T a = T();
+// CHECK: int a = int();
// CHECK-NEXT: #pragma omp atomic
// CHECK-NEXT: a++;
// CHECK-NEXT: #pragma omp atomic read
diff --git a/test/OpenMP/atomic_capture_codegen.cpp b/test/OpenMP/atomic_capture_codegen.cpp
index f91da3e80f54..0a22e4276b53 100644
--- a/test/OpenMP/atomic_capture_codegen.cpp
+++ b/test/OpenMP/atomic_capture_codegen.cpp
@@ -2,7 +2,6 @@
// 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
// expected-no-diagnostics
-// REQUIRES: x86-registered-target
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/atomic_messages.c b/test/OpenMP/atomic_messages.c
index 8182465494ba..7b3178bba49f 100644
--- a/test/OpenMP/atomic_messages.c
+++ b/test/OpenMP/atomic_messages.c
@@ -313,6 +313,8 @@ int captureint() {
#pragma omp atomic capture
{c = a; a++;}
#pragma omp atomic capture
+ {c = a; (a)++;}
+#pragma omp atomic capture
{++a;c = a;}
#pragma omp atomic capture
{c = a;a--;}
@@ -321,6 +323,8 @@ int captureint() {
#pragma omp atomic capture
{c = a; a += b;}
#pragma omp atomic capture
+ {c = a; (a) += b;}
+#pragma omp atomic capture
{a %= b; c = a;}
#pragma omp atomic capture
{c = a; a *= b;}
diff --git a/test/OpenMP/atomic_messages.cpp b/test/OpenMP/atomic_messages.cpp
index 7f78ad443da6..efb368d1a7c0 100644
--- a/test/OpenMP/atomic_messages.cpp
+++ b/test/OpenMP/atomic_messages.cpp
@@ -453,6 +453,8 @@ T capture() {
#pragma omp atomic capture
{c = a; a++;}
#pragma omp atomic capture
+ {c = a; (a)++;}
+#pragma omp atomic capture
{++a;c = a;}
#pragma omp atomic capture
{c = a;a--;}
@@ -461,6 +463,8 @@ T capture() {
#pragma omp atomic capture
{c = a; a += b;}
#pragma omp atomic capture
+ {c = a; (a) += b;}
+#pragma omp atomic capture
{a %= b; c = a;}
#pragma omp atomic capture
{c = a; a *= b;}
diff --git a/test/OpenMP/atomic_update_codegen.cpp b/test/OpenMP/atomic_update_codegen.cpp
index 063b76d7ff54..8c02a43d64e3 100644
--- a/test/OpenMP/atomic_update_codegen.cpp
+++ b/test/OpenMP/atomic_update_codegen.cpp
@@ -2,7 +2,6 @@
// 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
// expected-no-diagnostics
-// REQUIRES: x86-registered-target
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/barrier_ast_print.cpp b/test/OpenMP/barrier_ast_print.cpp
index 062df80a226e..fd03a9ab0ffe 100644
--- a/test/OpenMP/barrier_ast_print.cpp
+++ b/test/OpenMP/barrier_ast_print.cpp
@@ -23,12 +23,12 @@ T tmain(T argc) {
}
return a + argc;
}
+// CHECK: static T a;
+// CHECK-NEXT: #pragma omp barrier
// CHECK: static int a;
// CHECK-NEXT: #pragma omp barrier
// CHECK: static char a;
// CHECK-NEXT: #pragma omp barrier
-// CHECK: static T a;
-// CHECK-NEXT: #pragma omp barrier
// CHECK-NEXT: switch (argc) {
// CHECK-NEXT: case 0:
// CHECK-NEXT: #pragma omp barrier
diff --git a/test/OpenMP/barrier_codegen.cpp b/test/OpenMP/barrier_codegen.cpp
index 398b96f44e8a..f335935050c6 100644
--- a/test/OpenMP/barrier_codegen.cpp
+++ b/test/OpenMP/barrier_codegen.cpp
@@ -2,7 +2,6 @@
// 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
// expected-no-diagnostics
-// REQUIRES: x86-registered-target
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/cancel_ast_print.cpp b/test/OpenMP/cancel_ast_print.cpp
index 007237a7fb98..be550843706c 100644
--- a/test/OpenMP/cancel_ast_print.cpp
+++ b/test/OpenMP/cancel_ast_print.cpp
@@ -1,6 +1,6 @@
-// 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 -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
// expected-no-diagnostics
#ifndef HEADER
diff --git a/test/OpenMP/cancel_codegen.cpp b/test/OpenMP/cancel_codegen.cpp
index a09214c9319c..69acb3d4906e 100644
--- a/test/OpenMP/cancel_codegen.cpp
+++ b/test/OpenMP/cancel_codegen.cpp
@@ -1,8 +1,7 @@
-// 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 -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
// expected-no-diagnostics
-// REQUIRES: x86-registered-target
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/cancel_if_messages.cpp b/test/OpenMP/cancel_if_messages.cpp
index 8d1afc9ecddf..426ac49cfdfe 100644
--- a/test/OpenMP/cancel_if_messages.cpp
+++ b/test/OpenMP/cancel_if_messages.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ferror-limit 100 %s
void foo() {
}
@@ -24,7 +24,7 @@ int tmain(T argc, S **argv) {
#pragma omp cancel parallel if (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp cancel parallel if (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp cancel parallel if(argc)
- #pragma omp cancel parallel if(cancel // expected-warning {{missing ':' after directive name modifier - ignoring}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ #pragma omp cancel parallel if(cancel // expected-error {{use of undeclared identifier 'cancel'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp cancel parallel if(cancel : // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp cancel parallel if(cancel : argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp cancel parallel if(cancel : argc)
@@ -52,7 +52,7 @@ int main(int argc, char **argv) {
#pragma omp cancel parallel if (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp cancel parallel if (1 0) // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp cancel parallel if(if(tmain(argc, argv) // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
- #pragma omp cancel parallel if(cancel // expected-warning {{missing ':' after directive name modifier - ignoring}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ #pragma omp cancel parallel if(cancel // expected-error {{use of undeclared identifier 'cancel'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp cancel parallel if(cancel : // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp cancel parallel if(cancel : argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp cancel parallel if(cancel : argc)
diff --git a/test/OpenMP/cancellation_point_codegen.cpp b/test/OpenMP/cancellation_point_codegen.cpp
index 91e6c6994916..c87d4015ef73 100644
--- a/test/OpenMP/cancellation_point_codegen.cpp
+++ b/test/OpenMP/cancellation_point_codegen.cpp
@@ -2,7 +2,6 @@
// 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
// expected-no-diagnostics
-// REQUIRES: x86-registered-target
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/critical_ast_print.cpp b/test/OpenMP/critical_ast_print.cpp
index 7189fddd7186..0579d030a8bc 100644
--- a/test/OpenMP/critical_ast_print.cpp
+++ b/test/OpenMP/critical_ast_print.cpp
@@ -9,6 +9,14 @@
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: a = 2;
+// CHECK-NEXT: ++a;
+// 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)
template <typename T, int N>
int tmain (T argc, char **argv) {
T b = argc, c, d, e, f, g;
@@ -22,9 +30,9 @@ int tmain (T argc, char **argv) {
++a;
#pragma omp critical (the_name) hint(N)
foo();
-// CHECK-NEXT: #pragma omp critical (the_name) hint(N)
+// CHECK-NEXT: #pragma omp critical (the_name) hint(4)
// CHECK-NEXT: foo();
-// CHECK-NEXT: return N;
+// CHECK-NEXT: return 4;
return N;
}
diff --git a/test/OpenMP/critical_codegen.cpp b/test/OpenMP/critical_codegen.cpp
index be749a65f0cb..f4e449a22370 100644
--- a/test/OpenMP/critical_codegen.cpp
+++ b/test/OpenMP/critical_codegen.cpp
@@ -3,7 +3,6 @@
// 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
// expected-no-diagnostics
-// REQUIRES: x86-registered-target
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/declare_reduction_ast_print.cpp b/test/OpenMP/declare_reduction_ast_print.cpp
index 26b2ff96ac02..816ff7937663 100644
--- a/test/OpenMP/declare_reduction_ast_print.cpp
+++ b/test/OpenMP/declare_reduction_ast_print.cpp
@@ -10,13 +10,12 @@
// CHECK: #pragma omp declare reduction (+ : int : omp_out *= omp_in)
// CHECK-NEXT: #pragma omp declare reduction (+ : char : omp_out *= omp_in)
-// CHECK: #pragma omp declare reduction (fun : int : omp_out += omp_in) initializer(omp_priv = omp_orig + 15)
-
template <class T>
class SSS {
public:
#pragma omp declare reduction(fun : T : omp_out += omp_in) initializer(omp_priv = omp_orig + 15)
// CHECK: #pragma omp declare reduction (fun : T : omp_out += omp_in) initializer(omp_priv = omp_orig + 15)
+ // CHECK: #pragma omp declare reduction (fun : int : omp_out += omp_in) initializer(omp_priv = omp_orig + 15)
};
SSS<int> d;
@@ -26,18 +25,18 @@ void init(SSS<int> &lhs, SSS<int> rhs);
#pragma omp declare reduction(fun : SSS < int > : omp_out = omp_in) initializer(init(omp_priv, omp_orig))
// CHECK: #pragma omp declare reduction (fun : SSS<int> : omp_out = omp_in) initializer(init(omp_priv, omp_orig))
-// CHECK: template <typename T = int> int foo(int a) {
-// CHECK: #pragma omp declare reduction (fun : int : omp_out += omp_in) initializer(omp_priv = omp_orig + 15);
+// CHECK: template <typename T> T foo(T a) {
+// CHECK: #pragma omp declare reduction (fun : T : omp_out += omp_in) initializer(omp_priv = omp_orig + 15);
// CHECK: {
-// CHECK: #pragma omp declare reduction (fun : int : omp_out += omp_in) initializer(omp_priv = omp_orig + 15);
+// CHECK: #pragma omp declare reduction (fun : T : omp_out += omp_in) initializer(omp_priv = omp_orig + 15);
// CHECK: }
// CHECK: return a;
// CHECK: }
-// CHECK: template <typename T> T foo(T a) {
-// CHECK: #pragma omp declare reduction (fun : T : omp_out += omp_in) initializer(omp_priv = omp_orig + 15);
+// CHECK: template<> int foo<int>(int a) {
+// CHECK: #pragma omp declare reduction (fun : int : omp_out += omp_in) initializer(omp_priv = omp_orig + 15);
// CHECK: {
-// CHECK: #pragma omp declare reduction (fun : T : omp_out += omp_in) initializer(omp_priv = omp_orig + 15);
+// CHECK: #pragma omp declare reduction (fun : int : omp_out += omp_in) initializer(omp_priv = omp_orig + 15);
// CHECK: }
// CHECK: return a;
// CHECK: }
diff --git a/test/OpenMP/declare_reduction_codegen.c b/test/OpenMP/declare_reduction_codegen.c
index ecb97269d4db..579b664a512a 100644
--- a/test/OpenMP/declare_reduction_codegen.c
+++ b/test/OpenMP/declare_reduction_codegen.c
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 -verify -fopenmp -x c -emit-llvm %s -triple %itanium_abi_triple -o - -femit-all-decls -disable-llvm-optzns | FileCheck %s
-// RUN: %clang_cc1 -fopenmp -x c -triple %itanium_abi_triple -emit-pch -o %t %s -femit-all-decls -disable-llvm-optzns
-// RUN: %clang_cc1 -fopenmp -x c -triple %itanium_abi_triple -include-pch %t -verify %s -emit-llvm -o - -femit-all-decls -disable-llvm-optzns | FileCheck --check-prefix=CHECK-LOAD %s
+// 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
// expected-no-diagnostics
#ifndef HEADER
diff --git a/test/OpenMP/declare_reduction_codegen.cpp b/test/OpenMP/declare_reduction_codegen.cpp
index a18e73f8a10f..11ce4300118c 100644
--- a/test/OpenMP/declare_reduction_codegen.cpp
+++ b/test/OpenMP/declare_reduction_codegen.cpp
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -emit-llvm %s -triple %itanium_abi_triple -fexceptions -fcxx-exceptions -o - -femit-all-decls -disable-llvm-optzns | 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-optzns
-// 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-optzns | FileCheck --check-prefix=CHECK-LOAD %s
+// 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
// expected-no-diagnostics
#ifndef HEADER
diff --git a/test/OpenMP/declare_simd_ast_print.cpp b/test/OpenMP/declare_simd_ast_print.cpp
index 5a32e61d9922..632e038e221d 100644
--- a/test/OpenMP/declare_simd_ast_print.cpp
+++ b/test/OpenMP/declare_simd_ast_print.cpp
@@ -22,18 +22,16 @@ template <class C> void h(C *hp, C *hp2, C *hq, C *lin) {
}
// CHECK: #pragma omp declare simd aligned(hp) aligned(hp2)
-// CHECK-NEXT: template <class C = int> void h(int *hp, int *hp2, int *hq, int *lin) {
-// CHECK-NEXT: h((float *)hp, (float *)hp2, (float *)hq, (float *)lin);
+// CHECK-NEXT: template <class C> void h(C *hp, C *hp2, C *hq, C *lin) {
// CHECK-NEXT: }
-// CHECK: #pragma omp declare simd aligned(hp) aligned(hp2)
-// CHECK-NEXT: template <class C = float> void h(float *hp, float *hp2, float *hq, float *lin) {
+// CHECK: #pragma omp declare simd aligned(hp) aligned(hp2)
+// CHECK-NEXT: template<> void h<float>(float *hp, float *hp2, float *hq, float *lin) {
// CHECK-NEXT: }
-// CHECK: #pragma omp declare simd aligned(hp) aligned(hp2)
-// CHECK: template <class C> void h(C *hp, C *hp2, C *hq, C *lin) {
+// CHECK-NEXT: template<> void h<int>(int *hp, int *hp2, int *hq, int *lin) {
+// CHECK-NEXT: h((float *)hp, (float *)hp2, (float *)hq, (float *)lin);
// CHECK-NEXT: }
-//
// Explicit specialization with <C=int>.
// Pragmas need to be same, otherwise standard says that's undefined behavior.
@@ -75,11 +73,11 @@ private:
int x[10];
};
-// CHECK: template <int X = 16, typename T = float> class TVV {
-// CHECK: #pragma omp declare simd
-// CHECK-NEXT: int tadd(int a, int b);
-// CHECK: #pragma omp declare simd aligned(a: 16 * 2) aligned(b) linear(ref(b): 16)
-// CHECK-NEXT: float taddpf(float *a, float *&b) {
+// CHECK: template <int X, typename T> class TVV {
+// CHECK: #pragma omp declare simd simdlen(X)
+// CHECK-NEXT: int tadd(int a, int b) {
+// CHECK: #pragma omp declare simd aligned(a: X * 2) aligned(b) linear(ref(b): X)
+// CHECK-NEXT: float taddpf(float *a, T *&b) {
// CHECK-NEXT: return *a + *b;
// CHECK-NEXT: }
// CHECK: #pragma omp declare simd
@@ -91,20 +89,18 @@ private:
template <int X, typename T>
class TVV {
public:
-// CHECK: template <int X, typename T> class TVV {
+// CHECK: template<> class TVV<16, float> {
#pragma omp declare simd simdlen(X)
int tadd(int a, int b) { return a + b; }
-// CHECK: #pragma omp declare simd simdlen(X)
-// CHECK-NEXT: int tadd(int a, int b) {
-// CHECK-NEXT: return a + b;
-// CHECK-NEXT: }
+// CHECK: #pragma omp declare simd simdlen(16)
+// CHECK-NEXT: int tadd(int a, int b);
#pragma omp declare simd aligned(a : X * 2) aligned(b) linear(ref(b): X)
float taddpf(float *a, T *&b) { return *a + *b; }
-// CHECK: #pragma omp declare simd aligned(a: X * 2) aligned(b)
-// CHECK-NEXT: float taddpf(float *a, T *&b) {
+// CHECK: #pragma omp declare simd aligned(a: 16 * 2) aligned(b) linear(ref(b): 16)
+// CHECK-NEXT: float taddpf(float *a, float *&b) {
// CHECK-NEXT: return *a + *b;
// CHECK-NEXT: }
@@ -123,10 +119,10 @@ private:
};
// CHECK: };
-// CHECK: #pragma omp declare simd simdlen(64) aligned(b: 64 * 2) linear(uval(c): 64)
-// CHECK: template <int N = 64> void foo(int (&b)[64], float *&c)
// CHECK: #pragma omp declare simd simdlen(N) aligned(b: N * 2) linear(uval(c): N)
// CHECK: template <int N> void foo(int (&b)[N], float *&c)
+// CHECK: #pragma omp declare simd simdlen(64) aligned(b: 64 * 2) linear(uval(c): 64)
+// CHECK: template<> void foo<64>(int (&b)[64], float *&c)
#pragma omp declare simd simdlen(N) aligned(b : N * 2) linear(uval(c): N)
template <int N>
void foo(int (&b)[N], float *&c);
diff --git a/test/OpenMP/declare_simd_codegen.cpp b/test/OpenMP/declare_simd_codegen.cpp
index 4ed7fb2801b8..47e951999b6a 100644
--- a/test/OpenMP/declare_simd_codegen.cpp
+++ b/test/OpenMP/declare_simd_codegen.cpp
@@ -2,7 +2,6 @@
// 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
// expected-no-diagnostics
-// REQUIRES: x86-registered-target
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/declare_target_ast_print.cpp b/test/OpenMP/declare_target_ast_print.cpp
index 78a9cf634af8..591844b79498 100644
--- a/test/OpenMP/declare_target_ast_print.cpp
+++ b/test/OpenMP/declare_target_ast_print.cpp
@@ -34,7 +34,12 @@ void foo_cpp() {}
#pragma omp declare target
template <class T>
struct C {
-// CHECK: template <class T = int> struct C
+// CHECK: template <class T> struct C {
+// CHECK: #pragma omp declare target
+// CHECK-NEXT: static T ts;
+// CHECK-NEXT: #pragma omp end declare target
+
+// CHECK: template<> struct C<int>
T t;
// CHECK-NEXT: int t;
static T ts;
@@ -59,11 +64,6 @@ struct C {
// CHECK: #pragma omp end declare target
};
-// CHECK: template <class T> struct C {
-// CHECK: #pragma omp declare target
-// CHECK-NEXT: static T ts;
-// CHECK-NEXT: #pragma omp end declare target
-
template<class T>
T C<T>::ts = 1;
// CHECK: #pragma omp declare target
diff --git a/test/OpenMP/distribute_ast_print.cpp b/test/OpenMP/distribute_ast_print.cpp
index 5748fc79ed67..d4a9df938f56 100644
--- a/test/OpenMP/distribute_ast_print.cpp
+++ b/test/OpenMP/distribute_ast_print.cpp
@@ -41,13 +41,13 @@ public:
// CHECK: #pragma omp target
// CHECK-NEXT: #pragma omp teams
-// CHECK-NEXT: #pragma omp distribute private(this->a) private(this->a) private(this->S::a)
-// CHECK: #pragma omp target
-// CHECK-NEXT: #pragma omp teams
// CHECK-NEXT: #pragma omp distribute private(this->a) private(this->a) private(T::a)
// CHECK: #pragma omp target
// CHECK-NEXT: #pragma omp teams
// CHECK-NEXT: #pragma omp distribute private(this->a) private(this->a)
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams
+// CHECK-NEXT: #pragma omp distribute private(this->a) private(this->a) private(this->S::a)
class S8 : public S7<S> {
S8() {}
diff --git a/test/OpenMP/distribute_dist_schedule_ast_print.cpp b/test/OpenMP/distribute_dist_schedule_ast_print.cpp
index 32389ef1496e..b06a56e3ee35 100644
--- a/test/OpenMP/distribute_dist_schedule_ast_print.cpp
+++ b/test/OpenMP/distribute_dist_schedule_ast_print.cpp
@@ -57,6 +57,7 @@ T tmain(T argc) {
}
int main (int argc, char **argv) {
+// CHECK: int main(int argc, char **argv) {
int b = argc, c, d, e, f, g;
static int a;
// CHECK: static int a;
diff --git a/test/OpenMP/distribute_parallel_for_ast_print.cpp b/test/OpenMP/distribute_parallel_for_ast_print.cpp
index 993cc2a7151f..874345b67327 100644
--- a/test/OpenMP/distribute_parallel_for_ast_print.cpp
+++ b/test/OpenMP/distribute_parallel_for_ast_print.cpp
@@ -1,6 +1,6 @@
-// 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 -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
// expected-no-diagnostics
#ifndef HEADER
@@ -37,9 +37,9 @@ public:
}
};
-// CHECK: #pragma omp distribute parallel for private(this->a) private(this->a) private(this->S::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)
class S8 : public S7<S> {
S8() {}
diff --git a/test/OpenMP/distribute_parallel_for_if_messages.cpp b/test/OpenMP/distribute_parallel_for_if_messages.cpp
index c864340a46bf..5e9d9ad9e1f2 100644
--- a/test/OpenMP/distribute_parallel_for_if_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_if_messages.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ferror-limit 100 %s
void foo() {
}
@@ -58,7 +58,7 @@ int tmain(T argc, S **argv) {
for (i = 0; i < argc; ++i) foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for if(parallel // expected-warning {{missing ':' after directive name modifier - ignoring}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp distribute parallel for if(parallel // expected-error {{use of undeclared identifier 'parallel'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target
#pragma omp teams
@@ -144,7 +144,7 @@ int main(int argc, char **argv) {
for (i = 0; i < argc; ++i) foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for if(parallel // expected-warning {{missing ':' after directive name modifier - ignoring}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp distribute parallel for if(parallel // expected-error {{use of undeclared identifier 'parallel'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target
#pragma omp teams
diff --git a/test/OpenMP/distribute_parallel_for_simd_aligned_messages.cpp b/test/OpenMP/distribute_parallel_for_simd_aligned_messages.cpp
index 9c9f3dda281a..f865e0be424f 100644
--- a/test/OpenMP/distribute_parallel_for_simd_aligned_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_simd_aligned_messages.cpp
@@ -166,7 +166,8 @@ template<class I, class C> int foomain(I argc, C **argv) {
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for simd aligned (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+// FIXME: Should argc really be a pointer?
+#pragma omp distribute parallel for simd aligned (*argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
for (I k = 0; k < argc; ++k) ++k;
#pragma omp target
diff --git a/test/OpenMP/distribute_parallel_for_simd_ast_print.cpp b/test/OpenMP/distribute_parallel_for_simd_ast_print.cpp
index 56809dcd8bd2..6ed3f2192258 100644
--- a/test/OpenMP/distribute_parallel_for_simd_ast_print.cpp
+++ b/test/OpenMP/distribute_parallel_for_simd_ast_print.cpp
@@ -1,6 +1,6 @@
-// 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 -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
// expected-no-diagnostics
#ifndef HEADER
@@ -37,9 +37,9 @@ public:
}
};
-// CHECK: #pragma omp distribute parallel for simd private(this->a) private(this->a) private(this->S::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)
+// CHECK: #pragma omp distribute parallel for simd private(this->a) private(this->a) private(this->S::a)
class S8 : public S7<S> {
S8() {}
diff --git a/test/OpenMP/distribute_parallel_for_simd_if_messages.cpp b/test/OpenMP/distribute_parallel_for_simd_if_messages.cpp
index 01236b5563ab..c6957b9a868b 100644
--- a/test/OpenMP/distribute_parallel_for_simd_if_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_simd_if_messages.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ferror-limit 100 %s
void foo() {
}
@@ -58,7 +58,7 @@ int tmain(T argc, S **argv) {
for (i = 0; i < argc; ++i) foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for simd if(parallel // expected-warning {{missing ':' after directive name modifier - ignoring}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp distribute parallel for simd if(parallel // expected-error {{use of undeclared identifier 'parallel'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target
#pragma omp teams
@@ -144,7 +144,7 @@ int main(int argc, char **argv) {
for (i = 0; i < argc; ++i) foo();
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for simd if(parallel // expected-warning {{missing ':' after directive name modifier - ignoring}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp distribute parallel for simd if(parallel // expected-error {{use of undeclared identifier 'parallel'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target
#pragma omp teams
diff --git a/test/OpenMP/distribute_simd_aligned_messages.cpp b/test/OpenMP/distribute_simd_aligned_messages.cpp
index 59e5be271d0b..10beb7198a6f 100644
--- a/test/OpenMP/distribute_simd_aligned_messages.cpp
+++ b/test/OpenMP/distribute_simd_aligned_messages.cpp
@@ -166,7 +166,8 @@ template<class I, class C> int foomain(I argc, C **argv) {
#pragma omp target
#pragma omp teams
-#pragma omp distribute simd aligned (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+// FIXME: Should argc really be a pointer?
+#pragma omp distribute simd aligned (*argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
for (I k = 0; k < argc; ++k) ++k;
#pragma omp target
diff --git a/test/OpenMP/distribute_simd_ast_print.cpp b/test/OpenMP/distribute_simd_ast_print.cpp
index 04358150b994..6d2e916292f5 100644
--- a/test/OpenMP/distribute_simd_ast_print.cpp
+++ b/test/OpenMP/distribute_simd_ast_print.cpp
@@ -37,9 +37,9 @@ public:
}
};
-// CHECK: #pragma omp distribute simd private(this->a) private(this->a) private(this->S::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)
class S8 : public S7<S> {
S8() {}
diff --git a/test/OpenMP/flush_ast_print.cpp b/test/OpenMP/flush_ast_print.cpp
index 081c5345033d..f3af47bce321 100644
--- a/test/OpenMP/flush_ast_print.cpp
+++ b/test/OpenMP/flush_ast_print.cpp
@@ -15,13 +15,13 @@ T tmain(T argc) {
#pragma omp flush(a)
return a + argc;
}
-// CHECK: static int a;
+// CHECK: static T a;
// CHECK-NEXT: #pragma omp flush
// CHECK-NEXT: #pragma omp flush (a)
-// CHECK: static char a;
+// CHECK: static int a;
// CHECK-NEXT: #pragma omp flush
// CHECK-NEXT: #pragma omp flush (a)
-// CHECK: static T a;
+// CHECK: static char a;
// CHECK-NEXT: #pragma omp flush
// CHECK-NEXT: #pragma omp flush (a)
diff --git a/test/OpenMP/flush_codegen.cpp b/test/OpenMP/flush_codegen.cpp
index d0ab9f1525a8..89636a5bd87a 100644
--- a/test/OpenMP/flush_codegen.cpp
+++ b/test/OpenMP/flush_codegen.cpp
@@ -2,7 +2,6 @@
// 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
// expected-no-diagnostics
-// REQUIRES: x86-registered-target
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/for_ast_print.cpp b/test/OpenMP/for_ast_print.cpp
index 182b395c13ca..f489b217de96 100644
--- a/test/OpenMP/for_ast_print.cpp
+++ b/test/OpenMP/for_ast_print.cpp
@@ -50,15 +50,15 @@ public:
}
};
-// CHECK: #pragma omp for private(this->a) private(this->a) private(this->S::a)
-// CHECK: #pragma omp for lastprivate(this->a) lastprivate(this->a) lastprivate(this->S::a)
-// CHECK: #pragma omp for linear(val(this->c))
// CHECK: #pragma omp for private(this->a) private(this->a) private(T::a)
// CHECK: #pragma omp for lastprivate(this->a) lastprivate(this->a) lastprivate(T::a)
// CHECK: #pragma omp for linear(val(this->c))
// CHECK: #pragma omp for private(this->a) private(this->a)
// CHECK: #pragma omp for lastprivate(this->a) lastprivate(this->a)
// CHECK: #pragma omp for linear(uval(this->b))
+// CHECK: #pragma omp for private(this->a) private(this->a) private(this->S::a)
+// CHECK: #pragma omp for lastprivate(this->a) lastprivate(this->a) lastprivate(this->S::a)
+// CHECK: #pragma omp for linear(val(this->c))
class S8 : public S7<S> {
S8() {}
@@ -137,6 +137,7 @@ T tmain(T argc) {
}
int main(int argc, char **argv) {
+// CHECK: int main(int argc, char **argv) {
int b = argc, c, d, e, f, g;
static int a;
// CHECK: static int a;
diff --git a/test/OpenMP/for_codegen.cpp b/test/OpenMP/for_codegen.cpp
index 1d24403a09fb..b27bd7b1dbe5 100644
--- a/test/OpenMP/for_codegen.cpp
+++ b/test/OpenMP/for_codegen.cpp
@@ -2,11 +2,13 @@
// 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
//
// expected-no-diagnostics
-// REQUIRES: x86-registered-target
#ifndef HEADER
#define HEADER
+// PROF-INSTR-PATH: constant [25 x i8] c"for_codegen-test.profraw\00"
+
// CHECK: [[IDENT_T_TY:%.+]] = type { i32, i32, i32, i32, i8* }
// CHECK-DAG: [[IMPLICIT_BARRIER_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 66, i32 0, i32 0, i8*
// CHECK-DAG: [[I:@.+]] = global i8 1,
diff --git a/test/OpenMP/for_firstprivate_codegen.cpp b/test/OpenMP/for_firstprivate_codegen.cpp
index 3c6f37229f22..1e1d404b48db 100644
--- a/test/OpenMP/for_firstprivate_codegen.cpp
+++ b/test/OpenMP/for_firstprivate_codegen.cpp
@@ -4,7 +4,6 @@
// 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
// expected-no-diagnostics
-// REQUIRES: x86-registered-target
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/for_lastprivate_codegen.cpp b/test/OpenMP/for_lastprivate_codegen.cpp
index 75f59f7d406d..f0fba042c58a 100644
--- a/test/OpenMP/for_lastprivate_codegen.cpp
+++ b/test/OpenMP/for_lastprivate_codegen.cpp
@@ -4,7 +4,6 @@
// 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
// expected-no-diagnostics
-// REQUIRES: x86-registered-target
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/for_linear_codegen.cpp b/test/OpenMP/for_linear_codegen.cpp
index 0ad45f5b7054..acadccbce389 100644
--- a/test/OpenMP/for_linear_codegen.cpp
+++ b/test/OpenMP/for_linear_codegen.cpp
@@ -4,7 +4,6 @@
// 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
// expected-no-diagnostics
-// REQUIRES: x86-registered-target
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/for_private_codegen.cpp b/test/OpenMP/for_private_codegen.cpp
index e8f4d3f4c830..5bad8d00688d 100644
--- a/test/OpenMP/for_private_codegen.cpp
+++ b/test/OpenMP/for_private_codegen.cpp
@@ -4,7 +4,6 @@
// 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
// expected-no-diagnostics
-// REQUIRES: x86-registered-target
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/for_reduction_codegen.cpp b/test/OpenMP/for_reduction_codegen.cpp
index 5dcc4b2622b2..274546b06547 100644
--- a/test/OpenMP/for_reduction_codegen.cpp
+++ b/test/OpenMP/for_reduction_codegen.cpp
@@ -4,7 +4,6 @@
// 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
// expected-no-diagnostics
-// REQUIRES: x86-registered-target
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/for_reduction_codegen_UDR.cpp b/test/OpenMP/for_reduction_codegen_UDR.cpp
index da384294e238..699e06dda85a 100644
--- a/test/OpenMP/for_reduction_codegen_UDR.cpp
+++ b/test/OpenMP/for_reduction_codegen_UDR.cpp
@@ -2,7 +2,6 @@
// 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
// expected-no-diagnostics
-// REQUIRES: x86-registered-target
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/for_simd_aligned_messages.cpp b/test/OpenMP/for_simd_aligned_messages.cpp
index cef83c30e239..1d0918e449f3 100644
--- a/test/OpenMP/for_simd_aligned_messages.cpp
+++ b/test/OpenMP/for_simd_aligned_messages.cpp
@@ -121,7 +121,8 @@ template<class I, class C> int foomain(I argc, C **argv) {
for (I k = 0; k < argc; ++k) ++k;
#pragma omp for simd aligned (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
for (I k = 0; k < argc; ++k) ++k;
- #pragma omp for simd aligned (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+// FIXME: Should argc really be a pointer?
+ #pragma omp for simd aligned (*argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
for (I k = 0; k < argc; ++k) ++k;
#pragma omp for simd aligned (argc : 5) // expected-warning {{aligned clause will be ignored because the requested alignment is not a power of 2}}
for (I k = 0; k < argc; ++k) ++k;
diff --git a/test/OpenMP/for_simd_ast_print.cpp b/test/OpenMP/for_simd_ast_print.cpp
index 54f0d4676134..befad16e0951 100644
--- a/test/OpenMP/for_simd_ast_print.cpp
+++ b/test/OpenMP/for_simd_ast_print.cpp
@@ -33,9 +33,9 @@ public:
}
};
-// CHECK: #pragma omp for simd private(this->a) private(this->a) private(this->S1::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)
class S8 : public S7<S1> {
S8() {}
@@ -125,7 +125,7 @@ template<int LEN> struct S2 {
};
// S2<4>::func is called below in main.
-// CHECK: template <int LEN = 4> struct S2 {
+// CHECK: template<> struct S2<4> {
// CHECK-NEXT: static void func(int n, float *a, float *b, float *c) {
// CHECK-NEXT: int k1 = 0, k2 = 0;
// CHECK-NEXT: #pragma omp for simd safelen(4) linear(k1,k2: 4) aligned(a: 4) simdlen(4)
diff --git a/test/OpenMP/for_simd_codegen.cpp b/test/OpenMP/for_simd_codegen.cpp
index fb282d0511bb..89f779db33cd 100644
--- a/test/OpenMP/for_simd_codegen.cpp
+++ b/test/OpenMP/for_simd_codegen.cpp
@@ -2,7 +2,6 @@
// 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
-// REQUIRES: x86-registered-target
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -17,12 +16,12 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK: [[UB_VAL:%.+]] = load i32, i32* [[UB]],
// CHECK: [[CMP:%.+]] = icmp sgt i32 [[UB_VAL]], 5
// CHECK: br i1 [[CMP]], label %[[TRUE:.+]], label %[[FALSE:[^,]+]]
-// CHECK: [[TRUE]]
+// CHECK: [[TRUE]]:
// CHECK: br label %[[SWITCH:[^,]+]]
-// CHECK: [[FALSE]]
+// CHECK: [[FALSE]]:
// CHECK: [[UB_VAL:%.+]] = load i32, i32* [[UB]],
// CHECK: br label %[[SWITCH]]
-// CHECK: [[SWITCH]]
+// CHECK: [[SWITCH]]:
// CHECK: [[UP:%.+]] = phi i32 [ 5, %[[TRUE]] ], [ [[UB_VAL]], %[[FALSE]] ]
// CHECK: store i32 [[UP]], i32* [[UB]],
// CHECK: [[LB_VAL:%.+]] = load i32, i32* [[LB]],
@@ -33,7 +32,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: [[CMP:%.+]] = icmp sle i32 [[IV]], [[UB_VAL]]
// CHECK-NEXT: br i1 [[CMP]], label %[[SIMPLE_LOOP1_BODY:.+]], label %[[SIMPLE_LOOP1_END:[^,]+]]
for (int i = 3; i < 32; i += 5) {
-// CHECK: [[SIMPLE_LOOP1_BODY]]
+// CHECK: [[SIMPLE_LOOP1_BODY]]:
// Start of body: calculate i from IV:
// CHECK: [[IV1_1:%.+]] = load i32, i32* [[OMP_IV]]{{.*}}
// CHECK: [[CALC_I_1:%.+]] = mul nsw i32 [[IV1_1]], 5
@@ -48,7 +47,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: store i32 [[ADD1_2]], i32* [[OMP_IV]]
// br label %{{.+}}, !llvm.loop !{{.+}}
}
-// CHECK: [[SIMPLE_LOOP1_END]]
+// CHECK: [[SIMPLE_LOOP1_END]]:
// CHECK: call void @__kmpc_for_static_fini(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK: call void @__kmpc_barrier(%ident_t* {{.+}}, i32 %{{.+}})
@@ -64,7 +63,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK: [[NEXT:%.+]] = call i32 @__kmpc_dispatch_next_4(%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]]
+// CHECK: [[CONT]]:
// CHECK: [[LB_VAL:%.+]] = load i32, i32* [[LB]],
// CHECK: store i32 [[LB_VAL]], i32* [[OMP_IV2:%[^,]+]],
@@ -73,7 +72,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: [[CMP2:%.+]] = icmp sle i32 [[IV2]], [[UB_VAL]]
// CHECK-NEXT: br i1 [[CMP2]], label %[[SIMPLE_LOOP2_BODY:.+]], label %[[SIMPLE_LOOP2_END:[^,]+]]
for (int i = 10; i > 1; i--) {
-// CHECK: [[SIMPLE_LOOP2_BODY]]
+// CHECK: [[SIMPLE_LOOP2_BODY]]:
// Start of body: calculate i from IV:
// CHECK: [[IV2_0:%.+]] = load i32, i32* [[OMP_IV2]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP2_ID]]
// FIXME: It is interesting, why the following "mul 1" was not constant folded?
@@ -95,7 +94,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: store i32 [[ADD2_2]], i32* [[OMP_IV2]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP2_ID]]
// br label {{.+}}, !llvm.loop ![[SIMPLE_LOOP2_ID]]
}
-// CHECK: [[SIMPLE_LOOP2_END]]
+// CHECK: [[SIMPLE_LOOP2_END]]:
//
// Update linear vars after loop, as the loop was operating on a private version.
// CHECK: [[LIN0_2:%.+]] = load i64, i64* [[LIN0]]
@@ -121,12 +120,12 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK: [[UB_VAL:%.+]] = load i64, i64* [[UB]],
// CHECK: [[CMP:%.+]] = icmp ugt i64 [[UB_VAL]], 3
// CHECK: br i1 [[CMP]], label %[[TRUE:.+]], label %[[FALSE:[^,]+]]
-// CHECK: [[TRUE]]
+// CHECK: [[TRUE]]:
// CHECK: br label %[[SWITCH:[^,]+]]
-// CHECK: [[FALSE]]
+// CHECK: [[FALSE]]:
// CHECK: [[UB_VAL:%.+]] = load i64, i64* [[UB]],
// CHECK: br label %[[SWITCH]]
-// CHECK: [[SWITCH]]
+// CHECK: [[SWITCH]]:
// CHECK: [[UP:%.+]] = phi i64 [ 3, %[[TRUE]] ], [ [[UB_VAL]], %[[FALSE]] ]
// CHECK: store i64 [[UP]], i64* [[UB]],
// CHECK: [[LB_VAL:%.+]] = load i64, i64* [[LB]],
@@ -137,7 +136,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: [[CMP3:%.+]] = icmp ule i64 [[IV3]], [[UB_VAL]]
// CHECK-NEXT: br i1 [[CMP3]], label %[[SIMPLE_LOOP3_BODY:.+]], label %[[SIMPLE_LOOP3_END:[^,]+]]
for (unsigned long long it = 2000; it >= 600; it-=400) {
-// CHECK: [[SIMPLE_LOOP3_BODY]]
+// CHECK: [[SIMPLE_LOOP3_BODY]]:
// Start of body: calculate it from IV:
// CHECK: [[IV3_0:%.+]] = load i64, i64* [[OMP_IV3]]
// CHECK-NEXT: [[LC_IT_1:%.+]] = mul i64 [[IV3_0]], 400
@@ -163,7 +162,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: [[ADD3_2:%.+]] = add i64 [[IV3_2]], 1
// CHECK-NEXT: store i64 [[ADD3_2]], i64* [[OMP_IV3]]
}
-// CHECK: [[SIMPLE_LOOP3_END]]
+// CHECK: [[SIMPLE_LOOP3_END]]:
// CHECK: call void @__kmpc_for_static_fini(%ident_t* {{.+}}, i32 %{{.+}})
//
// Linear start and step are used to calculate final value of the linear variables.
@@ -179,12 +178,12 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK: [[UB_VAL:%.+]] = load i32, i32* [[UB]],
// CHECK: [[CMP:%.+]] = icmp sgt i32 [[UB_VAL]], 3
// CHECK: br i1 [[CMP]], label %[[TRUE:.+]], label %[[FALSE:[^,]+]]
-// CHECK: [[TRUE]]
+// CHECK: [[TRUE]]:
// CHECK: br label %[[SWITCH:[^,]+]]
-// CHECK: [[FALSE]]
+// CHECK: [[FALSE]]:
// CHECK: [[UB_VAL:%.+]] = load i32, i32* [[UB]],
// CHECK: br label %[[SWITCH]]
-// CHECK: [[SWITCH]]
+// CHECK: [[SWITCH]]:
// CHECK: [[UP:%.+]] = phi i32 [ 3, %[[TRUE]] ], [ [[UB_VAL]], %[[FALSE]] ]
// CHECK: store i32 [[UP]], i32* [[UB]],
// CHECK: [[LB_VAL:%.+]] = load i32, i32* [[LB]],
@@ -195,7 +194,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: [[CMP4:%.+]] = icmp sle i32 [[IV4]], [[UB_VAL]]
// CHECK-NEXT: br i1 [[CMP4]], label %[[SIMPLE_LOOP4_BODY:.+]], label %[[SIMPLE_LOOP4_END:[^,]+]]
for (short it = 6; it <= 20; it-=-4) {
-// CHECK: [[SIMPLE_LOOP4_BODY]]
+// CHECK: [[SIMPLE_LOOP4_BODY]]:
// Start of body: calculate it from IV:
// CHECK: [[IV4_0:%.+]] = load i32, i32* [[OMP_IV4]]
// CHECK-NEXT: [[LC_IT_1:%.+]] = mul nsw i32 [[IV4_0]], 4
@@ -207,7 +206,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: [[ADD4_2:%.+]] = add nsw i32 [[IV4_2]], 1
// CHECK-NEXT: store i32 [[ADD4_2]], i32* [[OMP_IV4]]
}
-// CHECK: [[SIMPLE_LOOP4_END]]
+// CHECK: [[SIMPLE_LOOP4_END]]:
// CHECK: call void @__kmpc_for_static_fini(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK: call void @__kmpc_barrier(%ident_t* {{.+}}, i32 %{{.+}})
@@ -216,12 +215,12 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK: [[UB_VAL:%.+]] = load i32, i32* [[UB]],
// CHECK: [[CMP:%.+]] = icmp sgt i32 [[UB_VAL]], 25
// CHECK: br i1 [[CMP]], label %[[TRUE:.+]], label %[[FALSE:[^,]+]]
-// CHECK: [[TRUE]]
+// CHECK: [[TRUE]]:
// CHECK: br label %[[SWITCH:[^,]+]]
-// CHECK: [[FALSE]]
+// CHECK: [[FALSE]]:
// CHECK: [[UB_VAL:%.+]] = load i32, i32* [[UB]],
// CHECK: br label %[[SWITCH]]
-// CHECK: [[SWITCH]]
+// CHECK: [[SWITCH]]:
// CHECK: [[UP:%.+]] = phi i32 [ 25, %[[TRUE]] ], [ [[UB_VAL]], %[[FALSE]] ]
// CHECK: store i32 [[UP]], i32* [[UB]],
// CHECK: [[LB_VAL:%.+]] = load i32, i32* [[LB]],
@@ -232,7 +231,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: [[CMP5:%.+]] = icmp sle i32 [[IV5]], [[UB_VAL]]
// CHECK-NEXT: br i1 [[CMP5]], label %[[SIMPLE_LOOP5_BODY:.+]], label %[[SIMPLE_LOOP5_END:[^,]+]]
for (unsigned char it = 'z'; it >= 'a'; it+=-1) {
-// CHECK: [[SIMPLE_LOOP5_BODY]]
+// CHECK: [[SIMPLE_LOOP5_BODY]]:
// Start of body: calculate it from IV:
// CHECK: [[IV5_0:%.+]] = load i32, i32* [[OMP_IV5]]
// CHECK-NEXT: [[IV5_1:%.+]] = mul nsw i32 [[IV5_0]], 1
@@ -244,7 +243,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: [[ADD5_2:%.+]] = add nsw i32 [[IV5_2]], 1
// CHECK-NEXT: store i32 [[ADD5_2]], i32* [[OMP_IV5]]
}
-// CHECK: [[SIMPLE_LOOP5_END]]
+// CHECK: [[SIMPLE_LOOP5_END]]:
// CHECK: call void @__kmpc_for_static_fini(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK: call void @__kmpc_barrier(%ident_t* {{.+}}, i32 %{{.+}})
@@ -263,25 +262,25 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK: [[UB_VAL:%.+]] = load i64, i64* [[UB]],
// CHECK: [[CMP:%.+]] = icmp sgt i64 [[UB_VAL]], 6
// CHECK: br i1 [[CMP]], label %[[TRUE:.+]], label %[[FALSE:[^,]+]]
-// CHECK: [[TRUE]]
+// CHECK: [[TRUE]]:
// CHECK: br label %[[SWITCH:[^,]+]]
-// CHECK: [[FALSE]]
+// CHECK: [[FALSE]]:
// CHECK: [[UB_VAL:%.+]] = load i64, i64* [[UB]],
// CHECK: br label %[[SWITCH]]
-// CHECK: [[SWITCH]]
+// CHECK: [[SWITCH]]:
// CHECK: [[UP:%.+]] = phi i64 [ 6, %[[TRUE]] ], [ [[UB_VAL]], %[[FALSE]] ]
// CHECK: store i64 [[UP]], i64* [[UB]],
// CHECK: [[LB_VAL:%.+]] = load i64, i64* [[LB]],
// CHECK: store i64 [[LB_VAL]], i64* [[OMP_IV7:%[^,]+]],
// CHECK: br label %[[SIMD_LOOP7_COND:[^,]+]]
-// CHECK: [[SIMD_LOOP7_COND]]
+// CHECK: [[SIMD_LOOP7_COND]]:
// CHECK-NEXT: [[IV7:%.+]] = load i64, i64* [[OMP_IV7]]
// CHECK-NEXT: [[UB_VAL:%.+]] = load i64, i64* [[UB]]
// CHECK-NEXT: [[CMP7:%.+]] = icmp sle i64 [[IV7]], [[UB_VAL]]
// CHECK-NEXT: br i1 [[CMP7]], label %[[SIMPLE_LOOP7_BODY:.+]], label %[[SIMPLE_LOOP7_END:[^,]+]]
for (long long i = -10; i < 10; i += 3) {
-// CHECK: [[SIMPLE_LOOP7_BODY]]
+// CHECK: [[SIMPLE_LOOP7_BODY]]:
// Start of body: calculate i from IV:
// CHECK: [[IV7_0:%.+]] = load i64, i64* [[OMP_IV7]]
// CHECK-NEXT: [[LC_IT_1:%.+]] = mul nsw i64 [[IV7_0]], 3
@@ -295,7 +294,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: [[ADD7_2:%.+]] = add nsw i64 [[IV7_2]], 1
// CHECK-NEXT: store i64 [[ADD7_2]], i64* [[OMP_IV7]]
}
-// CHECK: [[SIMPLE_LOOP7_END]]
+// CHECK: [[SIMPLE_LOOP7_END]]:
// CHECK: call void @__kmpc_for_static_fini(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK: load i32, i32*
// CHECK: icmp ne i32 %{{.+}}, 0
@@ -316,25 +315,25 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK: [[UB_VAL:%.+]] = load i64, i64* [[UB]],
// CHECK: [[CMP:%.+]] = icmp sgt i64 [[UB_VAL]], 6
// CHECK: br i1 [[CMP]], label %[[TRUE:.+]], label %[[FALSE:[^,]+]]
-// CHECK: [[TRUE]]
+// CHECK: [[TRUE]]:
// CHECK: br label %[[SWITCH:[^,]+]]
-// CHECK: [[FALSE]]
+// CHECK: [[FALSE]]:
// CHECK: [[UB_VAL:%.+]] = load i64, i64* [[UB]],
// CHECK: br label %[[SWITCH]]
-// CHECK: [[SWITCH]]
+// CHECK: [[SWITCH]]:
// CHECK: [[UP:%.+]] = phi i64 [ 6, %[[TRUE]] ], [ [[UB_VAL]], %[[FALSE]] ]
// CHECK: store i64 [[UP]], i64* [[UB]],
// CHECK: [[LB_VAL:%.+]] = load i64, i64* [[LB]],
// CHECK: store i64 [[LB_VAL]], i64* [[OMP_IV8:%[^,]+]],
// CHECK: br label %[[SIMD_LOOP8_COND:[^,]+]]
-// CHECK: [[SIMD_LOOP8_COND]]
+// CHECK: [[SIMD_LOOP8_COND]]:
// CHECK-NEXT: [[IV8:%.+]] = load i64, i64* [[OMP_IV8]]
// CHECK-NEXT: [[UB_VAL:%.+]] = load i64, i64* [[UB]]
// CHECK-NEXT: [[CMP8:%.+]] = icmp sle i64 [[IV8]], [[UB_VAL]]
// CHECK-NEXT: br i1 [[CMP8]], label %[[SIMPLE_LOOP8_BODY:.+]], label %[[SIMPLE_LOOP8_END:[^,]+]]
for (long long i = -10; i < 10; i += 3) {
-// CHECK: [[SIMPLE_LOOP8_BODY]]
+// CHECK: [[SIMPLE_LOOP8_BODY]]:
// Start of body: calculate i from IV:
// CHECK: [[IV8_0:%.+]] = load i64, i64* [[OMP_IV8]]
// CHECK-NEXT: [[LC_IT_1:%.+]] = mul nsw i64 [[IV8_0]], 3
@@ -347,7 +346,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: [[ADD8_2:%.+]] = add nsw i64 [[IV8_2]], 1
// CHECK-NEXT: store i64 [[ADD8_2]], i64* [[OMP_IV8]]
}
-// CHECK: [[SIMPLE_LOOP8_END]]
+// CHECK: [[SIMPLE_LOOP8_END]]:
// CHECK: call void @__kmpc_for_static_fini(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK: call i32 @__kmpc_reduce(
// CHECK: [[R_PRIV_VAL:%.+]] = load i32, i32* [[R_PRIV]],
@@ -377,12 +376,12 @@ int templ1(T a, T *z) {
// CHECK: [[UB_VAL:%.+]] = load i64, i64* [[UB]],
// CHECK: [[CMP:%.+]] = icmp sgt i64 [[UB_VAL]], 15
// CHECK: br i1 [[CMP]], label %[[TRUE:.+]], label %[[FALSE:[^,]+]]
-// CHECK: [[TRUE]]
+// CHECK: [[TRUE]]:
// CHECK: br label %[[SWITCH:[^,]+]]
-// CHECK: [[FALSE]]
+// CHECK: [[FALSE]]:
// CHECK: [[UB_VAL:%.+]] = load i64, i64* [[UB]],
// CHECK: br label %[[SWITCH]]
-// CHECK: [[SWITCH]]
+// CHECK: [[SWITCH]]:
// CHECK: [[UP:%.+]] = phi i64 [ 15, %[[TRUE]] ], [ [[UB_VAL]], %[[FALSE]] ]
// CHECK: store i64 [[UP]], i64* [[UB]],
// CHECK: [[LB_VAL:%.+]] = load i64, i64* [[LB]],
@@ -394,7 +393,7 @@ int templ1(T a, T *z) {
// CHECK-NEXT: [[UB_VAL:%.+]] = load i64, i64* [[UB]]
// CHECK-NEXT: [[CMP1:%.+]] = icmp sle i64 [[IV]], [[UB_VAL]]
// CHECK-NEXT: br i1 [[CMP1]], label %[[T1_BODY:.+]], label %[[T1_END:[^,]+]]
-// CHECK: [[T1_BODY]]
+// CHECK: [[T1_BODY]]:
// Loop counters i and j updates:
// CHECK: [[IV1:%.+]] = load i64, i64* [[T1_OMP_IV]]
// CHECK-NEXT: [[I_1:%.+]] = sdiv i64 [[IV1]], 4
@@ -412,7 +411,7 @@ int templ1(T a, T *z) {
// CHECK-NEXT: [[INC:%.+]] = add nsw i64 [[IV3]], 1
// CHECK-NEXT: store i64 [[INC]], i64* [[T1_OMP_IV]]
// CHECK-NEXT: br label {{%.+}}
-// CHECK: [[T1_END]]
+// CHECK: [[T1_END]]:
// CHECK: call void @__kmpc_for_static_fini(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK: call void @__kmpc_barrier(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK: ret i32 0
@@ -469,13 +468,13 @@ void iter_simple(IterDouble ia, IterDouble ib, IterDouble ic) {
// CHECK-DAG: [[OMP_LAST_IT_VAL:%.+]] = load i32, i32* [[OMP_LAST_IT]],
// CHECK: [[CMP:%.+]] = icmp sgt i32 [[UB_VAL]], [[OMP_LAST_IT_VAL]]
// CHECK: br i1 [[CMP]], label %[[TRUE:.+]], label %[[FALSE:[^,]+]]
-// CHECK: [[TRUE]]
+// CHECK: [[TRUE]]:
// CHECK: [[OMP_LAST_IT_VAL:%.+]] = load i32, i32* [[OMP_LAST_IT]],
// CHECK: br label %[[SWITCH:[^,]+]]
-// CHECK: [[FALSE]]
+// CHECK: [[FALSE]]:
// CHECK: [[UB_VAL:%.+]] = load i32, i32* [[UB]],
// CHECK: br label %[[SWITCH]]
-// CHECK: [[SWITCH]]
+// CHECK: [[SWITCH]]:
// CHECK: [[UP:%.+]] = phi i32 [ [[OMP_LAST_IT_VAL]], %[[TRUE]] ], [ [[UB_VAL]], %[[FALSE]] ]
// CHECK: store i32 [[UP]], i32* [[UB]],
// CHECK: [[LB_VAL:%.+]] = load i32, i32* [[LB]],
@@ -486,7 +485,7 @@ void iter_simple(IterDouble ia, IterDouble ib, IterDouble ic) {
// CHECK-NEXT: [[CMP:%.+]] = icmp sle i32 [[IV]], [[UB_VAL]]
// CHECK-NEXT: br i1 [[CMP]], label %[[IT_BODY:[^,]+]], label %[[IT_END:[^,]+]]
for (IterDouble i = ia; i < ib; ++i) {
-// CHECK: [[IT_BODY]]
+// CHECK: [[IT_BODY]]:
// Start of body: calculate i from index:
// CHECK: [[IV1:%.+]] = load i32, i32* [[IT_OMP_IV]]
// Call of operator+ (i, IV).
@@ -504,7 +503,7 @@ void iter_simple(IterDouble ia, IterDouble ib, IterDouble ic) {
// CHECK-NEXT: store i32 [[ADD2]], i32* [[IT_OMP_IV]]
// br label %{{.*}}, !llvm.loop ![[ITER_LOOP_ID]]
}
-// CHECK: [[IT_END]]
+// CHECK: [[IT_END]]:
// CHECK: call void @__kmpc_for_static_fini(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK: call void @__kmpc_barrier(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK: ret void
@@ -521,12 +520,12 @@ void collapsed(float *a, float *b, float *c, float *d) {
// CHECK: [[UB_VAL:%.+]] = load i32, i32* [[UB]],
// CHECK: [[CMP:%.+]] = icmp ugt i32 [[UB_VAL]], 119
// CHECK: br i1 [[CMP]], label %[[TRUE:.+]], label %[[FALSE:[^,]+]]
-// CHECK: [[TRUE]]
+// CHECK: [[TRUE]]:
// CHECK: br label %[[SWITCH:[^,]+]]
-// CHECK: [[FALSE]]
+// CHECK: [[FALSE]]:
// CHECK: [[UB_VAL:%.+]] = load i32, i32* [[UB]],
// CHECK: br label %[[SWITCH]]
-// CHECK: [[SWITCH]]
+// CHECK: [[SWITCH]]:
// CHECK: [[UP:%.+]] = phi i32 [ 119, %[[TRUE]] ], [ [[UB_VAL]], %[[FALSE]] ]
// CHECK: store i32 [[UP]], i32* [[UB]],
// CHECK: [[LB_VAL:%.+]] = load i32, i32* [[LB]],
@@ -543,7 +542,7 @@ void collapsed(float *a, float *b, float *c, float *d) {
for (int k = 3; k <= 6; k++) // 4 iterations
for (l = 4; l < 9; ++l) // 5 iterations
{
-// CHECK: [[COLL1_BODY]]
+// CHECK: [[COLL1_BODY]]:
// Start of body: calculate i from index:
// CHECK: [[IV1:%.+]] = load i32, i32* [[OMP_IV]]
// Calculation of the loop counters values.
@@ -578,7 +577,7 @@ void collapsed(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: [[ADD2:%.+]] = add i32 [[IV2]], 1
// CHECK-NEXT: store i32 [[ADD2]], i32* [[OMP_IV]]
// br label %{{[^,]+}}, !llvm.loop ![[COLL1_LOOP_ID]]
-// CHECK: [[COLL1_END]]
+// CHECK: [[COLL1_END]]:
}
// i,j,l are updated; k is not updated.
// CHECK: call void @__kmpc_for_static_fini(%ident_t* {{.+}}, i32 %{{.+}})
@@ -610,13 +609,13 @@ void widened(float *a, float *b, float *c, float *d) {
// CHECK-DAG: [[OMP_LAST_IT_VAL:%.+]] = load i64, i64* [[OMP_LAST_IT]],
// CHECK: [[CMP:%.+]] = icmp sgt i64 [[UB_VAL]], [[OMP_LAST_IT_VAL]]
// CHECK: br i1 [[CMP]], label %[[TRUE:.+]], label %[[FALSE:[^,]+]]
-// CHECK: [[TRUE]]
+// CHECK: [[TRUE]]:
// CHECK: [[OMP_LAST_IT_VAL:%.+]] = load i64, i64* [[OMP_LAST_IT]],
// CHECK: br label %[[SWITCH:[^,]+]]
-// CHECK: [[FALSE]]
+// CHECK: [[FALSE]]:
// CHECK: [[UB_VAL:%.+]] = load i64, i64* [[UB]],
// CHECK: br label %[[SWITCH]]
-// CHECK: [[SWITCH]]
+// CHECK: [[SWITCH]]:
// CHECK: [[UP:%.+]] = phi i64 [ [[OMP_LAST_IT_VAL]], %[[TRUE]] ], [ [[UB_VAL]], %[[FALSE]] ]
// CHECK: store i64 [[UP]], i64* [[UB]],
// CHECK: [[LB_VAL:%.+]] = load i64, i64* [[LB]],
@@ -631,7 +630,7 @@ void widened(float *a, float *b, float *c, float *d) {
for (i = 1; i < 3; i++) // 2 iterations
for (j = 0; j < foo(); j++) // foo() iterations
{
-// CHECK: [[WIDE1_BODY]]
+// CHECK: [[WIDE1_BODY]]:
// Start of body: calculate i from index:
// CHECK: [[IV1:%.+]] = load i64, i64* [[OMP_IV]]
// Calculation of the loop counters values...
@@ -655,7 +654,7 @@ void widened(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: store i64 [[ADD2]], i64* [[OMP_IV]]
//
// br label %{{[^,]+}}, !llvm.loop ![[WIDE1_LOOP_ID]]
-// CHECK: [[WIDE1_END]]
+// CHECK: [[WIDE1_END]]:
}
// i,j are updated.
// CHECK: store i32 3, i32* [[I:%[^,]+]]
diff --git a/test/OpenMP/linking.c b/test/OpenMP/linking.c
index 81706d4f6201..7b3059242370 100644
--- a/test/OpenMP/linking.c
+++ b/test/OpenMP/linking.c
@@ -4,42 +4,42 @@
// FIXME: Replace DEFAULT_OPENMP_LIB below with the value chosen at configure time.
//
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: -fopenmp -target i386-unknown-linux \
+// RUN: -fopenmp -target i386-unknown-linux -rtlib=platform \
// RUN: | FileCheck --check-prefix=CHECK-LD-32 %s
// CHECK-LD-32: "{{.*}}ld{{(.exe)?}}"
// CHECK-LD-32: "-l[[DEFAULT_OPENMP_LIB:[^"]*]]" "-lgcc"
// CHECK-LD-32: "-lpthread" "-lc"
//
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: -fopenmp -target x86_64-unknown-linux \
+// RUN: -fopenmp -target x86_64-unknown-linux -rtlib=platform \
// RUN: | FileCheck --check-prefix=CHECK-LD-64 %s
// CHECK-LD-64: "{{.*}}ld{{(.exe)?}}"
// CHECK-LD-64: "-l[[DEFAULT_OPENMP_LIB:[^"]*]]" "-lgcc"
// CHECK-LD-64: "-lpthread" "-lc"
//
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: -fopenmp=libgomp -target i386-unknown-linux \
+// RUN: -fopenmp=libgomp -target i386-unknown-linux -rtlib=platform \
// RUN: | FileCheck --check-prefix=CHECK-GOMP-LD-32 %s
// CHECK-GOMP-LD-32: "{{.*}}ld{{(.exe)?}}"
// CHECK-GOMP-LD-32: "-lgomp" "-lrt" "-lgcc"
// CHECK-GOMP-LD-32: "-lpthread" "-lc"
//
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: -fopenmp=libgomp -target x86_64-unknown-linux \
+// RUN: -fopenmp=libgomp -target x86_64-unknown-linux -rtlib=platform \
// RUN: | FileCheck --check-prefix=CHECK-GOMP-LD-64 %s
// CHECK-GOMP-LD-64: "{{.*}}ld{{(.exe)?}}"
// CHECK-GOMP-LD-64: "-lgomp" "-lrt" "-lgcc"
// CHECK-GOMP-LD-64: "-lpthread" "-lc"
//
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: -fopenmp -target i386-unknown-linux \
+// RUN: -fopenmp -target i386-unknown-linux -rtlib=platform \
// RUN: | FileCheck --check-prefix=CHECK-IOMP5-LD-32 %s
// CHECK-IOMP5-LD-32: "{{.*}}ld{{(.exe)?}}"
// CHECK-IOMP5-LD-32: "-l[[DEFAULT_OPENMP_LIB:[^"]*]]" "-lgcc"
// CHECK-IOMP5-LD-32: "-lpthread" "-lc"
//
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: -fopenmp -target x86_64-unknown-linux \
+// RUN: -fopenmp -target x86_64-unknown-linux -rtlib=platform \
// RUN: | FileCheck --check-prefix=CHECK-IOMP5-LD-64 %s
// CHECK-IOMP5-LD-64: "{{.*}}ld{{(.exe)?}}"
// CHECK-IOMP5-LD-64: "-l[[DEFAULT_OPENMP_LIB:[^"]*]]" "-lgcc"
@@ -57,6 +57,7 @@
//
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
// RUN: -fopenmp -fopenmp=libgomp -target i386-unknown-linux \
+// RUN: -rtlib=platform \
// RUN: | FileCheck --check-prefix=CHECK-LD-OVERRIDE-32 %s
// CHECK-LD-OVERRIDE-32: "{{.*}}ld{{(.exe)?}}"
// CHECK-LD-OVERRIDE-32: "-lgomp" "-lrt" "-lgcc"
@@ -64,13 +65,14 @@
//
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
// RUN: -fopenmp -fopenmp=libgomp -target x86_64-unknown-linux \
+// RUN: -rtlib=platform \
// RUN: | FileCheck --check-prefix=CHECK-LD-OVERRIDE-64 %s
// CHECK-LD-OVERRIDE-64: "{{.*}}ld{{(.exe)?}}"
// CHECK-LD-OVERRIDE-64: "-lgomp" "-lrt" "-lgcc"
// CHECK-LD-OVERRIDE-64: "-lpthread" "-lc"
//
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: -fopenmp=libomp -target x86_64-msvc-win32 \
+// RUN: -fopenmp=libomp -target x86_64-msvc-win32 -rtlib=platform \
// RUN: | FileCheck --check-prefix=CHECK-MSVC-LINK-64 %s
// CHECK-MSVC-LINK-64: link.exe
// CHECK-MSVC-LINK-64-SAME: -nodefaultlib:vcomp.lib
@@ -79,7 +81,7 @@
// CHECK-MSVC-LINK-64-SAME: -defaultlib:libomp.lib
//
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
-// RUN: -fopenmp=libiomp5 -target x86_64-msvc-win32 \
+// RUN: -fopenmp=libiomp5 -target x86_64-msvc-win32 -rtlib=platform \
// RUN: | FileCheck --check-prefix=CHECK-MSVC-ILINK-64 %s
// CHECK-MSVC-ILINK-64: link.exe
// CHECK-MSVC-ILINK-64-SAME: -nodefaultlib:vcomp.lib
diff --git a/test/OpenMP/master_codegen.cpp b/test/OpenMP/master_codegen.cpp
index b491fb921c5c..ad92a13e14cf 100644
--- a/test/OpenMP/master_codegen.cpp
+++ b/test/OpenMP/master_codegen.cpp
@@ -3,7 +3,6 @@
// 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
// expected-no-diagnostics
-// REQUIRES: x86-registered-target
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/nesting_of_regions.cpp b/test/OpenMP/nesting_of_regions.cpp
index b6082e7447dd..a97505b1c3c1 100644
--- a/test/OpenMP/nesting_of_regions.cpp
+++ b/test/OpenMP/nesting_of_regions.cpp
@@ -155,7 +155,54 @@ void foo() {
for (int i = 0; i < 10; ++i)
;
}
-
+#pragma omp parallel
+ {
+#pragma omp target simd // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp parallel
+ {
+#pragma omp teams distribute // expected-error {{region cannot be closely nested inside 'parallel' region; perhaps you forget to enclose 'omp teams distribute' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp parallel
+ {
+#pragma omp teams distribute simd // expected-error {{region cannot be closely nested inside 'parallel' region; perhaps you forget to enclose 'omp teams distribute simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp parallel
+ {
+#pragma omp teams distribute parallel for simd // expected-error {{region cannot be closely nested inside 'parallel' region; perhaps you forget to enclose 'omp teams distribute parallel for simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp parallel
+ {
+#pragma omp teams distribute parallel for // expected-error {{region cannot be closely nested inside 'parallel' region; perhaps you forget to enclose 'omp teams distribute parallel for' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp parallel
+ {
+#pragma omp target teams // OK
+ ++a;
+ }
+#pragma omp parallel
+ {
+#pragma omp target teams distribute // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp parallel
+ {
+#pragma omp target teams distribute parallel for // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+
// SIMD DIRECTIVE
#pragma omp simd
for (int i = 0; i < 10; ++i) {
@@ -347,7 +394,54 @@ void foo() {
for (int j = 0; j < 10; ++j)
;
}
-
+#pragma omp simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ ++a;
+ }
+#pragma omp simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute parallel for // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+
// FOR DIRECTIVE
#pragma omp for
for (int i = 0; i < 10; ++i) {
@@ -552,6 +646,53 @@ void foo() {
for (int j = 0; j < 10; ++j)
;
}
+#pragma omp for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target simd // OK
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute // expected-error {{region cannot be closely nested inside 'for' region; perhaps you forget to enclose 'omp teams distribute' directive into a target region?}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute simd // expected-error {{region cannot be closely nested inside 'for' region; perhaps you forget to enclose 'omp teams distribute simd' directive into a target region?}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for simd // expected-error {{region cannot be closely nested inside 'for' region; perhaps you forget to enclose 'omp teams distribute parallel for simd' directive into a target region?}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for // expected-error {{region cannot be closely nested inside 'for' region; perhaps you forget to enclose 'omp teams distribute parallel for' directive into a target region?}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams // OK
+ ++a;
+ }
+#pragma omp for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute // OK
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute parallel for // OK
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
// FOR SIMD DIRECTIVE
#pragma omp for simd
@@ -745,6 +886,53 @@ void foo() {
for (int j = 0; j < 10; ++j)
;
}
+#pragma omp for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ a++;
+ }
+#pragma omp for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute parallel for // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
// SECTIONS DIRECTIVE
#pragma omp sections
@@ -955,6 +1143,53 @@ void foo() {
for (int i = 0; i < 10; ++i)
;
}
+#pragma omp sections
+ {
+#pragma omp target simd // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp sections
+ {
+#pragma omp teams distribute // expected-error {{region cannot be closely nested inside 'sections' region; perhaps you forget to enclose 'omp teams distribute' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp sections
+ {
+#pragma omp teams distribute simd // expected-error {{region cannot be closely nested inside 'sections' region; perhaps you forget to enclose 'omp teams distribute simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp sections
+ {
+#pragma omp teams distribute parallel for simd // expected-error {{region cannot be closely nested inside 'sections' region; perhaps you forget to enclose 'omp teams distribute parallel for simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp sections
+ {
+#pragma omp teams distribute parallel for // expected-error {{region cannot be closely nested inside 'sections' region; perhaps you forget to enclose 'omp teams distribute parallel for' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp sections
+ {
+#pragma omp target teams // OK
+ ++a;
+ }
+#pragma omp sections
+ {
+#pragma omp target teams distribute // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp sections
+ {
+#pragma omp target teams distribute parallel for // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
// SECTION DIRECTIVE
#pragma omp section // expected-error {{orphaned 'omp section' directives are prohibited, it must be closely nested to a sections region}}
@@ -1222,6 +1457,61 @@ void foo() {
for (int i = 0; i < 10; ++i)
;
}
+#pragma omp sections
+ {
+#pragma omp section
+#pragma omp target simd // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp sections
+ {
+#pragma omp section
+#pragma omp teams distribute // expected-error {{region cannot be closely nested inside 'section' region; perhaps you forget to enclose 'omp teams distribute' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp sections
+ {
+#pragma omp section
+#pragma omp teams distribute simd // expected-error {{region cannot be closely nested inside 'section' region; perhaps you forget to enclose 'omp teams distribute simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp sections
+ {
+#pragma omp section
+#pragma omp teams distribute parallel for simd // expected-error {{region cannot be closely nested inside 'section' region; perhaps you forget to enclose 'omp teams distribute parallel for simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp sections
+ {
+#pragma omp section
+#pragma omp teams distribute parallel for // expected-error {{region cannot be closely nested inside 'section' region; perhaps you forget to enclose 'omp teams distribute parallel for' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp sections
+ {
+#pragma omp section
+#pragma omp target teams // OK
+ ++a;
+ }
+#pragma omp sections
+ {
+#pragma omp section
+#pragma omp target teams distribute // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp sections
+ {
+#pragma omp section
+#pragma omp target teams distribute parallel for // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
// SINGLE DIRECTIVE
#pragma omp single
@@ -1418,6 +1708,53 @@ void foo() {
for (int i = 0; i < 10; ++i)
;
}
+#pragma omp single
+ {
+#pragma omp target simd // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp single
+ {
+#pragma omp teams distribute // expected-error {{region cannot be closely nested inside 'single' region; perhaps you forget to enclose 'omp teams distribute' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp single
+ {
+#pragma omp teams distribute simd // expected-error {{region cannot be closely nested inside 'single' region; perhaps you forget to enclose 'omp teams distribute simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp single
+ {
+#pragma omp teams distribute parallel for simd // expected-error {{region cannot be closely nested inside 'single' region; perhaps you forget to enclose 'omp teams distribute parallel for simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp single
+ {
+#pragma omp teams distribute parallel for // expected-error {{region cannot be closely nested inside 'single' region; perhaps you forget to enclose 'omp teams distribute parallel for' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp single
+ {
+#pragma omp target teams // OK
+ ++a;
+ }
+#pragma omp single
+ {
+#pragma omp target teams distribute // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp single
+ {
+#pragma omp target teams distribute parallel for // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
// MASTER DIRECTIVE
#pragma omp master
@@ -1614,6 +1951,53 @@ void foo() {
for (int i = 0; i < 10; ++i)
;
}
+#pragma omp master
+ {
+#pragma omp target simd // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp master
+ {
+#pragma omp teams distribute // expected-error {{region cannot be closely nested inside 'master' region; perhaps you forget to enclose 'omp teams distribute' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp master
+ {
+#pragma omp teams distribute simd // expected-error {{region cannot be closely nested inside 'master' region; perhaps you forget to enclose 'omp teams distribute simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp master
+ {
+#pragma omp teams distribute parallel for simd // expected-error {{region cannot be closely nested inside 'master' region; perhaps you forget to enclose 'omp teams distribute parallel for simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp master
+ {
+#pragma omp teams distribute parallel for // expected-error {{region cannot be closely nested inside 'master' region; perhaps you forget to enclose 'omp teams distribute parallel for' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp master
+ {
+#pragma omp target teams // OK
+ a++;
+ }
+#pragma omp master
+ {
+#pragma omp target teams distribute // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp master
+ {
+#pragma omp target teams distribute parallel for // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
// CRITICAL DIRECTIVE
#pragma omp critical
@@ -1824,6 +2208,53 @@ void foo() {
for (int i = 0; i < 10; ++i)
;
}
+#pragma omp critical
+ {
+#pragma omp target simd // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp critical
+ {
+#pragma omp teams distribute // expected-error {{region cannot be closely nested inside 'critical' region; perhaps you forget to enclose 'omp teams distribute' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp critical
+ {
+#pragma omp teams distribute simd // expected-error {{region cannot be closely nested inside 'critical' region; perhaps you forget to enclose 'omp teams distribute simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp critical
+ {
+#pragma omp teams distribute parallel for simd // expected-error {{region cannot be closely nested inside 'critical' region; perhaps you forget to enclose 'omp teams distribute parallel for simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp critical
+ {
+#pragma omp teams distribute parallel for // expected-error {{region cannot be closely nested inside 'critical' region; perhaps you forget to enclose 'omp teams distribute parallel for' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp critical
+ {
+#pragma omp target teams // OK
+ a++;
+ }
+#pragma omp critical
+ {
+#pragma omp target teams distribute // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp critical
+ {
+#pragma omp target teams distribute parallel for // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
// PARALLEL FOR DIRECTIVE
#pragma omp parallel for
@@ -2034,6 +2465,53 @@ void foo() {
for (int j = 0; j < 10; ++j)
;
}
+#pragma omp parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target simd // OK
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute // expected-error {{region cannot be closely nested inside 'parallel for' region; perhaps you forget to enclose 'omp teams distribute' directive into a target region?}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute simd // expected-error {{region cannot be closely nested inside 'parallel for' region; perhaps you forget to enclose 'omp teams distribute simd' directive into a target region?}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for simd // expected-error {{region cannot be closely nested inside 'parallel for' region; perhaps you forget to enclose 'omp teams distribute parallel for simd' directive into a target region?}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for // expected-error {{region cannot be closely nested inside 'parallel for' region; perhaps you forget to enclose 'omp teams distribute parallel for' directive into a target region?}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams // OK
+ a++;
+ }
+#pragma omp parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute // OK
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute parallel for // OK
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
// PARALLEL FOR SIMD DIRECTIVE
#pragma omp parallel for simd
@@ -2245,6 +2723,53 @@ void foo() {
for (int j = 0; j < 10; ++j)
;
}
+#pragma omp parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ a++;
+ }
+#pragma omp parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute parallel for // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
// PARALLEL SECTIONS DIRECTIVE
#pragma omp parallel sections
@@ -2444,6 +2969,53 @@ void foo() {
for (int i = 0; i < 10; ++i)
;
}
+#pragma omp parallel sections
+ {
+#pragma omp target simd // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp parallel sections
+ {
+#pragma omp teams distribute // expected-error {{region cannot be closely nested inside 'parallel sections' region; perhaps you forget to enclose 'omp teams distribute' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp parallel sections
+ {
+#pragma omp teams distribute simd // expected-error {{region cannot be closely nested inside 'parallel sections' region; perhaps you forget to enclose 'omp teams distribute simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp parallel sections
+ {
+#pragma omp teams distribute parallel for simd // expected-error {{region cannot be closely nested inside 'parallel sections' region; perhaps you forget to enclose 'omp teams distribute parallel for simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp parallel sections
+ {
+#pragma omp teams distribute parallel for // expected-error {{region cannot be closely nested inside 'parallel sections' region; perhaps you forget to enclose 'omp teams distribute parallel for' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp parallel sections
+ {
+#pragma omp target teams // OK
+ a++;
+ }
+#pragma omp parallel sections
+ {
+#pragma omp target teams distribute // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp parallel sections
+ {
+#pragma omp target teams distribute parallel for // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
// TASK DIRECTIVE
#pragma omp task
@@ -2590,6 +3162,53 @@ void foo() {
for (int i = 0; i < 10; ++i)
;
}
+#pragma omp task
+ {
+#pragma omp target simd // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp task
+ {
+#pragma omp teams distribute // expected-error {{region cannot be closely nested inside 'task' region; perhaps you forget to enclose 'omp teams distribute' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp task
+ {
+#pragma omp teams distribute simd // expected-error {{region cannot be closely nested inside 'task' region; perhaps you forget to enclose 'omp teams distribute simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp task
+ {
+#pragma omp teams distribute parallel for simd // expected-error {{region cannot be closely nested inside 'task' region; perhaps you forget to enclose 'omp teams distribute parallel for simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp task
+ {
+#pragma omp teams distribute parallel for // expected-error {{region cannot be closely nested inside 'task' region; perhaps you forget to enclose 'omp teams distribute parallel for' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp task
+ {
+#pragma omp target teams // OK
+ a++;
+ }
+#pragma omp task
+ {
+#pragma omp target teams distribute // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp task
+ {
+#pragma omp target teams distribute parallel for // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
// ORDERED DIRECTIVE
#pragma omp ordered
@@ -2807,6 +3426,53 @@ void foo() {
for (int i = 0; i < 10; ++i)
;
}
+#pragma omp ordered
+ {
+#pragma omp target simd // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp ordered
+ {
+#pragma omp teams distribute // expected-error {{region cannot be closely nested inside 'ordered' region; perhaps you forget to enclose 'omp teams distribute' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp ordered
+ {
+#pragma omp teams distribute simd // expected-error {{region cannot be closely nested inside 'ordered' region; perhaps you forget to enclose 'omp teams distribute simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp ordered
+ {
+#pragma omp teams distribute parallel for simd // expected-error {{region cannot be closely nested inside 'ordered' region; perhaps you forget to enclose 'omp teams distribute parallel for simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp ordered
+ {
+#pragma omp teams distribute parallel for // expected-error {{region cannot be closely nested inside 'ordered' region; perhaps you forget to enclose 'omp teams distribute parallel for' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp ordered
+ {
+#pragma omp target teams // OK
+ a++;
+ }
+#pragma omp ordered
+ {
+#pragma omp target teams distribute // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp ordered
+ {
+#pragma omp target teams distribute parallel for // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
// ATOMIC DIRECTIVE
#pragma omp atomic
@@ -3052,6 +3718,69 @@ void foo() {
for (int i = 0; i < 10; ++i)
;
}
+#pragma omp atomic
+ // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
+ // expected-note@+1 {{expected an expression statement}}
+ {
+#pragma omp target simd // expected-error {{OpenMP constructs may not be nested inside an atomic region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp atomic
+ // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
+ // expected-note@+1 {{expected an expression statement}}
+ {
+#pragma omp teams distribute // expected-error {{OpenMP constructs may not be nested inside an atomic region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp atomic
+ // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
+ // expected-note@+1 {{expected an expression statement}}
+ {
+#pragma omp teams distribute simd // expected-error {{OpenMP constructs may not be nested inside an atomic region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp atomic
+ // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
+ // expected-note@+1 {{expected an expression statement}}
+ {
+#pragma omp teams distribute parallel for simd // expected-error {{OpenMP constructs may not be nested inside an atomic region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp atomic
+ // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
+ // expected-note@+1 {{expected an expression statement}}
+ {
+#pragma omp teams distribute parallel for // expected-error {{OpenMP constructs may not be nested inside an atomic region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp atomic
+ // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
+ // expected-note@+1 {{expected an expression statement}}
+ {
+#pragma omp target teams // expected-error {{OpenMP constructs may not be nested inside an atomic region}}
+ a++;
+ }
+#pragma omp atomic
+ // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
+ // expected-note@+1 {{expected an expression statement}}
+ {
+#pragma omp target teams distribute // expected-error {{OpenMP constructs may not be nested inside an atomic region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp atomic
+ // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
+ // expected-note@+1 {{expected an expression statement}}
+ {
+#pragma omp target teams distribute parallel for // expected-error {{OpenMP constructs may not be nested inside an atomic region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
// TARGET DIRECTIVE
#pragma omp target
@@ -3214,6 +3943,54 @@ void foo() {
for (int i = 0; i < 10; ++i)
;
}
+#pragma omp target
+ {
+#pragma omp target simd // expected-error {{region cannot be nested inside 'target' region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+ {
+#pragma omp teams distribute // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+ {
+#pragma omp teams distribute simd // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+ {
+#pragma omp teams distribute parallel for simd // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+ {
+#pragma omp teams distribute parallel for // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+ {
+#pragma omp target teams // expected-error {{region cannot be nested inside 'target' region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+ {
+#pragma omp target teams distribute // expected-error {{region cannot be nested inside 'target' region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+ {
+#pragma omp target teams distribute parallel for // expected-error {{region cannot be nested inside 'target' region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
// TARGET PARALLEL DIRECTIVE
#pragma omp target parallel
@@ -3370,6 +4147,53 @@ void foo() {
for (int i = 0; i < 10; ++i)
;
}
+#pragma omp target parallel
+ {
+#pragma omp target simd // expected-error {{region cannot be nested inside 'target parallel' region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target parallel
+ {
+#pragma omp teams distribute // expected-error {{region cannot be closely nested inside 'target parallel' region; perhaps you forget to enclose 'omp teams distribute' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target parallel
+ {
+#pragma omp teams distribute simd // expected-error {{region cannot be closely nested inside 'target parallel' region; perhaps you forget to enclose 'omp teams distribute simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target parallel
+ {
+#pragma omp teams distribute parallel for simd // expected-error {{region cannot be closely nested inside 'target parallel' region; perhaps you forget to enclose 'omp teams distribute parallel for simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target parallel
+ {
+#pragma omp teams distribute parallel for // expected-error {{region cannot be closely nested inside 'target parallel' region; perhaps you forget to enclose 'omp teams distribute parallel for' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target parallel
+ {
+#pragma omp target teams // expected-error {{region cannot be nested inside 'target parallel' region}}
+ a++;
+ }
+#pragma omp target parallel
+ {
+#pragma omp target teams distribute // expected-error {{region cannot be nested inside 'target parallel' region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target parallel
+ {
+#pragma omp target teams distribute parallel for // expected-error {{region cannot be nested inside 'target parallel' region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
// TARGET PARALLEL FOR DIRECTIVE
#pragma omp target parallel for
@@ -3580,8 +4404,57 @@ void foo() {
for (int j = 0; j < 10; ++j)
;
}
+#pragma omp target parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target simd // expected-error {{region cannot be nested inside 'target parallel for' region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp target parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute // expected-error {{region cannot be closely nested inside 'target parallel for' region; perhaps you forget to enclose 'omp teams distribute' directive into a target region?}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp target parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute simd // expected-error {{region cannot be closely nested inside 'target parallel for' region; perhaps you forget to enclose 'omp teams distribute simd' directive into a target region?}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp target parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for simd // expected-error {{region cannot be closely nested inside 'target parallel for' region; perhaps you forget to enclose 'omp teams distribute parallel for simd' directive into a target region?}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp target parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for // expected-error {{region cannot be closely nested inside 'target parallel for' region; perhaps you forget to enclose 'omp teams distribute parallel for' directive into a target region?}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp target parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams // expected-error {{region cannot be nested inside 'target parallel for' region}}
+ a++;
+ }
+#pragma omp target parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute // expected-error {{region cannot be nested inside 'target parallel for' region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp target parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute parallel for // expected-error {{region cannot be nested inside 'target parallel for' region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
// TEAMS DIRECTIVE
+#pragma omp teams // expected-error {{orphaned 'omp teams' directives are prohibited; perhaps you forget to enclose the directive into a target region?}}
+ bar();
#pragma omp target
#pragma omp teams
#pragma omp parallel
@@ -3691,7 +4564,7 @@ void foo() {
#pragma omp target
#pragma omp teams
{
-#pragma omp target // expected-error {{region cannot be closely nested inside 'teams' region; perhaps you forget to enclose 'omp target' directive into a parallel region?}}
+#pragma omp target // expected-error {{region cannot be nested inside 'target' region}}
++a;
}
#pragma omp target
@@ -3708,13 +4581,13 @@ void foo() {
#pragma omp target
#pragma omp teams
{
-#pragma omp target enter data map(to: a) // expected-error {{region cannot be closely nested inside 'teams' region; perhaps you forget to enclose 'omp target enter data' directive into a parallel region?}}
+#pragma omp target enter data map(to: a) // expected-error {{region cannot be nested inside 'target' region}}
++a;
}
#pragma omp target
#pragma omp teams
{
-#pragma omp target exit data map(from: a) // expected-error {{region cannot be closely nested inside 'teams' region; perhaps you forget to enclose 'omp target exit data' directive into a parallel region?}}
+#pragma omp target exit data map(from: a) // expected-error {{region cannot be nested inside 'target' region}}
++a;
}
#pragma omp target
@@ -3746,7 +4619,7 @@ void foo() {
#pragma omp target
#pragma omp teams
{
-#pragma omp target update to(a) // expected-error {{region cannot be closely nested inside 'teams' region; perhaps you forget to enclose 'omp target update' directive into a parallel region?}}
+#pragma omp target update to(a) // expected-error {{region cannot be nested inside 'target' region}}
}
#pragma omp target
#pragma omp teams
@@ -3778,6 +4651,61 @@ void foo() {
for (int j = 0; j < 10; ++j)
;
}
+#pragma omp target
+#pragma omp teams
+ {
+#pragma omp target simd // expected-error {{region cannot be nested inside 'target' region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams
+ {
+#pragma omp teams distribute // expected-error {{region cannot be closely nested inside 'teams' region; perhaps you forget to enclose 'omp teams distribute' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams
+ {
+#pragma omp teams distribute simd // expected-error {{region cannot be closely nested inside 'teams' region; perhaps you forget to enclose 'omp teams distribute simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams
+ {
+#pragma omp teams distribute parallel for simd // expected-error {{region cannot be closely nested inside 'teams' region; perhaps you forget to enclose 'omp teams distribute parallel for simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams
+ {
+#pragma omp teams distribute parallel for // expected-error {{region cannot be closely nested inside 'teams' region; perhaps you forget to enclose 'omp teams distribute parallel for' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams
+ {
+#pragma omp target teams // expected-error {{region cannot be nested inside 'target' region}}
+ a++;
+ }
+#pragma omp target
+#pragma omp teams
+ {
+#pragma omp target teams distribute // expected-error {{region cannot be nested inside 'target' region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams
+ {
+#pragma omp target teams distribute parallel for // expected-error {{region cannot be nested inside 'target' region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
// TASKLOOP DIRECTIVE
#pragma omp taskloop
@@ -3979,6 +4907,53 @@ void foo() {
for (int j = 0; j < 10; ++j)
++a;
}
+#pragma omp taskloop
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target simd // OK
+ for (int j = 0; j < 10; ++j)
+ ++a;
+ }
+#pragma omp taskloop
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute // expected-error {{region cannot be closely nested inside 'taskloop' region; perhaps you forget to enclose 'omp teams distribute' directive into a target region?}}
+ for (int j = 0; j < 10; ++j)
+ ++a;
+ }
+#pragma omp taskloop
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute simd // expected-error {{region cannot be closely nested inside 'taskloop' region; perhaps you forget to enclose 'omp teams distribute simd' directive into a target region?}}
+ for (int j = 0; j < 10; ++j)
+ ++a;
+ }
+#pragma omp taskloop
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for simd // expected-error {{region cannot be closely nested inside 'taskloop' region; perhaps you forget to enclose 'omp teams distribute parallel for simd' directive into a target region?}}
+ for (int j = 0; j < 10; ++j)
+ ++a;
+ }
+#pragma omp taskloop
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for // expected-error {{region cannot be closely nested inside 'taskloop' region; perhaps you forget to enclose 'omp teams distribute parallel for' directive into a target region?}}
+ for (int j = 0; j < 10; ++j)
+ ++a;
+ }
+#pragma omp taskloop
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams // OK
+ ++a;
+ }
+#pragma omp taskloop
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute // OK
+ for (int j = 0; j < 10; ++j)
+ ++a;
+ }
+#pragma omp taskloop
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute parallel for // OK
+ for (int j = 0; j < 10; ++j)
+ ++a;
+ }
// DISTRIBUTE DIRECTIVE
#pragma omp target
@@ -4204,6 +5179,69 @@ void foo() {
#pragma omp target update to(a) // expected-error {{region cannot be nested inside 'target' region}}
++a;
}
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target simd // expected-error {{region cannot be nested inside 'target' region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute // expected-error {{region cannot be closely nested inside 'distribute' region; perhaps you forget to enclose 'omp teams distribute' directive into a target region?}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute simd // expected-error {{region cannot be closely nested inside 'distribute' region; perhaps you forget to enclose 'omp teams distribute simd' directive into a target region?}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for simd // expected-error {{region cannot be closely nested inside 'distribute' region; perhaps you forget to enclose 'omp teams distribute parallel for simd' directive into a target region?}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for // expected-error {{region cannot be closely nested inside 'distribute' region; perhaps you forget to enclose 'omp teams distribute parallel for' directive into a target region?}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams // expected-error {{region cannot be nested inside 'target' region}}
+ a++;
+ }
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute // expected-error {{region cannot be nested inside 'target' region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute parallel for // expected-error {{region cannot be nested inside 'target' region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
// DISTRIBUTE PARALLEL FOR DIRECTIVE
#pragma omp target
@@ -4445,6 +5483,61 @@ void foo() {
for (int i = 0; i < 10; ++i)
;
}
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute // expected-error {{region cannot be closely nested inside 'distribute parallel for' region; perhaps you forget to enclose 'omp teams distribute' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute simd // expected-error {{region cannot be closely nested inside 'distribute parallel for' region; perhaps you forget to enclose 'omp teams distribute simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for simd // expected-error {{region cannot be closely nested inside 'distribute parallel for' region; perhaps you forget to enclose 'omp teams distribute parallel for simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for // expected-error {{region cannot be closely nested inside 'distribute parallel for' region; perhaps you forget to enclose 'omp teams distribute parallel for' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams // expected-error {{region cannot be nested inside 'target' region}}
+ a++;
+ }
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute // expected-error {{region cannot be nested inside 'target' region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute parallel for // expected-error {{region cannot be nested inside 'target' region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
// DISTRIBUTE PARALLEL FOR SIMD DIRECTIVE
#pragma omp target
@@ -4686,6 +5779,2277 @@ void foo() {
for (int i = 0; i < 10; ++i)
++a;
}
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute parallel for // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+
+// TARGET SIMD DIRECTIVE
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp distribute parallel for simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp distribute // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp for // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp simd // expected-warning {{OpenMP only allows an ordered construct with the simd clause nested in a simd construct}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp for simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp sections // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp section // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp single // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp master // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp critical // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+#pragma omp single
+ {
+ bar();
+ }
+ }
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel for // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel for simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel sections // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp task // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp taskyield // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ bar();
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp barrier // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ bar();
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp taskwait // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ bar();
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp flush // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ bar();
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp ordered // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ bar();
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp atomic // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ ++a;
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ ++a;
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target parallel // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ ++a;
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target parallel for // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target enter data map(to: a) // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ ++a;
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target exit data map(from: a) // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ ++a;
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ ++a;
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target update to(a) // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ ++a;
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp distribute simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute parallel for // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+
+// TEAMS DISTRIBUTE DIRECTIVE
+#pragma omp teams distribute // expected-error {{orphaned 'omp teams distribute' directives are prohibited; perhaps you forget to enclose the directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp distribute parallel for simd // expected-error {{region cannot be closely nested inside 'teams distribute' region; perhaps you forget to enclose 'omp distribute parallel for simd' directive into a teams region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp distribute // expected-error {{region cannot be closely nested inside 'teams distribute' region; perhaps you forget to enclose 'omp distribute' directive into a teams region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp for // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp simd // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp for simd // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp sections // OK
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp section // expected-error {{'omp section' directive must be closely nested to a sections region, not a teams distribute region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp single // OK
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp master // OK
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp critical // OK
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel // OK
+ {
+#pragma omp single
+ {
+ bar();
+ }
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel for // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel for simd // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel sections // OK
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp task // OK
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp taskyield // OK
+ bar();
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp barrier // OK
+ bar();
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp taskwait // OK
+ bar();
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp flush // OK
+ bar();
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp ordered // expected-error {{region cannot be closely nested inside 'teams distribute' region; perhaps you forget to enclose 'omp ordered' directive into a for or a parallel for region with 'ordered' clause?}}
+ bar();
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp atomic // OK
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target // expected-error {{region cannot be nested inside 'target' region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target parallel // expected-error {{region cannot be nested inside 'target' region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target parallel for // expected-error {{region cannot be nested inside 'target' region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target enter data map(to: a) // expected-error {{region cannot be nested inside 'target' region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target exit data map(from: a) // expected-error {{region cannot be nested inside 'target' region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams // expected-error {{region cannot be closely nested inside 'teams distribute' region; perhaps you forget to enclose 'omp teams' directive into a target region?}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target update to(a) // expected-error {{region cannot be nested inside 'target' region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp distribute simd // expected-error {{region cannot be closely nested inside 'teams distribute' region; perhaps you forget to enclose 'omp distribute simd' directive into a teams region?}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target simd // expected-error {{region cannot be nested inside 'target' region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute // expected-error {{region cannot be closely nested inside 'teams distribute' region; perhaps you forget to enclose 'omp teams distribute' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute simd // expected-error {{region cannot be closely nested inside 'teams distribute' region; perhaps you forget to enclose 'omp teams distribute simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for simd // expected-error {{region cannot be closely nested inside 'teams distribute' region; perhaps you forget to enclose 'omp teams distribute parallel for simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute parallel for // expected-error {{region cannot be nested inside 'target' region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+
+// TEAMS DISTRIBUTE DIRECTIVE
+#pragma omp teams distribute // expected-error {{orphaned 'omp teams distribute' directives are prohibited; perhaps you forget to enclose the directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp distribute parallel for simd // expected-error {{region cannot be closely nested inside 'teams distribute' region; perhaps you forget to enclose 'omp distribute parallel for simd' directive into a teams region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp distribute // expected-error {{region cannot be closely nested inside 'teams distribute' region; perhaps you forget to enclose 'omp distribute' directive into a teams region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp for // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp simd // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp for simd // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp sections // OK
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp section // expected-error {{'omp section' directive must be closely nested to a sections region, not a teams distribute region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp single // OK
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp master // OK
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp critical // OK
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel // OK
+ {
+#pragma omp single
+ {
+ bar();
+ }
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel for // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel for simd // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel sections // OK
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp task // OK
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp taskyield // OK
+ bar();
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp barrier // OK
+ bar();
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp taskwait // OK
+ bar();
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp flush // OK
+ bar();
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp ordered // expected-error {{region cannot be closely nested inside 'teams distribute' region; perhaps you forget to enclose 'omp ordered' directive into a for or a parallel for region with 'ordered' clause?}}
+ bar();
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp atomic // OK
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target // expected-error {{region cannot be nested inside 'target' region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target parallel // expected-error {{region cannot be nested inside 'target' region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target parallel for // expected-error {{region cannot be nested inside 'target' region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target enter data map(to: a) // expected-error {{region cannot be nested inside 'target' region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target exit data map(from: a) // expected-error {{region cannot be nested inside 'target' region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams // expected-error {{region cannot be closely nested inside 'teams distribute' region; perhaps you forget to enclose 'omp teams' directive into a target region?}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target update to(a) // expected-error {{region cannot be nested inside 'target' region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp distribute simd // expected-error {{region cannot be closely nested inside 'teams distribute' region; perhaps you forget to enclose 'omp distribute simd' directive into a teams region?}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target simd // expected-error {{region cannot be nested inside 'target' region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute // expected-error {{region cannot be closely nested inside 'teams distribute' region; perhaps you forget to enclose 'omp teams distribute' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute simd // expected-error {{region cannot be closely nested inside 'teams distribute' region; perhaps you forget to enclose 'omp teams distribute simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for simd // expected-error {{region cannot be closely nested inside 'teams distribute' region; perhaps you forget to enclose 'omp teams distribute parallel for simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for // expected-error {{region cannot be closely nested inside 'teams distribute' region; perhaps you forget to enclose 'omp teams distribute parallel for' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams // expected-error {{region cannot be nested inside 'target' region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute // expected-error {{region cannot be nested inside 'target' region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute parallel for // expected-error {{region cannot be nested inside 'target' region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+
+// TEAMS DISTRIBUTE SIMD DIRECTIVE
+#pragma omp teams distribute simd // expected-error {{orphaned 'omp teams distribute simd' directives are prohibited; perhaps you forget to enclose the directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp distribute parallel for simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp distribute // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp for // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp simd // expected-warning {{OpenMP only allows an ordered construct with the simd clause nested in a simd construct}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp for simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp sections // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp section // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp single // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp master // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp critical // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+#pragma omp single
+ {
+ bar();
+ }
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel for // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel for simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel sections // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp task // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp taskyield // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ bar();
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp barrier // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ bar();
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp taskwait // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ bar();
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp flush // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ bar();
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp ordered // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ bar();
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp atomic // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target parallel // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target parallel for // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target enter data map(to: a) // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target exit data map(from: a) // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target update to(a) // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp distribute simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute parallel for // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+
+// TEAMS DISTRIBUTE PARALLEL FOR SIMD DIRECTIVE
+#pragma omp teams distribute parallel for simd // expected-error {{orphaned 'omp teams distribute parallel for simd' directives are prohibited; perhaps you forget to enclose the directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp distribute parallel for simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp distribute // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp for // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp simd // expected-warning {{OpenMP only allows an ordered construct with the simd clause nested in a simd construct}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp for simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp sections // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp section // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp single // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp master // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp critical // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+#pragma omp single
+ {
+ bar();
+ }
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel for // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel for simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel sections // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp task // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp taskyield // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ bar();
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp barrier // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ bar();
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp taskwait // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ bar();
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp flush // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ bar();
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp ordered // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ bar();
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp atomic // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target parallel // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target parallel for // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target enter data map(to: a) // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target exit data map(from: a) // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target update to(a) // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp distribute simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute parallel for // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+
+// TEAMS DISTRIBUTE PARALLEL FOR DIRECTIVE
+#pragma omp teams distribute parallel for // expected-error {{orphaned 'omp teams distribute parallel for' directives are prohibited; perhaps you forget to enclose the directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp distribute parallel for simd // expected-error {{region cannot be closely nested inside 'teams distribute parallel for' region; perhaps you forget to enclose 'omp distribute parallel for simd' directive into a teams region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp distribute // expected-error {{region cannot be closely nested inside 'teams distribute parallel for' region; perhaps you forget to enclose 'omp distribute' directive into a teams region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp for // expected-error {{region cannot be closely nested inside 'teams distribute parallel for' region; perhaps you forget to enclose 'omp for' directive into a parallel region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp simd // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp for simd // expected-error {{region cannot be closely nested inside 'teams distribute parallel for' region; perhaps you forget to enclose 'omp for simd' directive into a parallel region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp sections // expected-error {{region cannot be closely nested inside 'teams distribute parallel for' region; perhaps you forget to enclose 'omp sections' directive into a parallel region?}}
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp section // expected-error {{'omp section' directive must be closely nested to a sections region, not a teams distribute parallel for region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp single // expected-error {{region cannot be closely nested inside 'teams distribute parallel for' region; perhaps you forget to enclose 'omp single' directive into a parallel region?}}
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp master // expected-error {{region cannot be closely nested inside 'teams distribute parallel for' region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp critical // OK
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel // OK
+ {
+#pragma omp single
+ {
+ bar();
+ }
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel for // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel for simd // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel sections // OK
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp task // OK
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp taskyield // OK
+ bar();
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp barrier // expected-error {{region cannot be closely nested inside 'teams distribute parallel for' region}}
+ bar();
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp taskwait // OK
+ bar();
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp flush // OK
+ bar();
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp ordered // expected-error {{region cannot be closely nested inside 'teams distribute parallel for' region; perhaps you forget to enclose 'omp ordered' directive into a for or a parallel for region with 'ordered' clause?}}
+ bar();
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp atomic // OK
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target // expected-error {{region cannot be nested inside 'target' region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target parallel // expected-error {{region cannot be nested inside 'target' region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target parallel for // expected-error {{region cannot be nested inside 'target' region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target enter data map(to: a) // expected-error {{region cannot be nested inside 'target' region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target exit data map(from: a) // expected-error {{region cannot be nested inside 'target' region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams // expected-error {{region cannot be closely nested inside 'teams distribute parallel for' region; perhaps you forget to enclose 'omp teams' directive into a target region?}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target update to(a) // expected-error {{region cannot be nested inside 'target' region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp distribute simd // expected-error {{region cannot be closely nested inside 'teams distribute parallel for' region; perhaps you forget to enclose 'omp distribute simd' directive into a teams region?}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target simd // expected-error {{region cannot be nested inside 'target' region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute // expected-error {{region cannot be closely nested inside 'teams distribute parallel for' region; perhaps you forget to enclose 'omp teams distribute' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute simd // expected-error {{region cannot be closely nested inside 'teams distribute parallel for' region; perhaps you forget to enclose 'omp teams distribute simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for simd // expected-error {{region cannot be closely nested inside 'teams distribute parallel for' region; perhaps you forget to enclose 'omp teams distribute parallel for simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for // expected-error {{region cannot be closely nested inside 'teams distribute parallel for' region; perhaps you forget to enclose 'omp teams distribute parallel for' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams // expected-error {{region cannot be nested inside 'target' region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute // expected-error {{region cannot be nested inside 'target' region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute parallel for // expected-error {{region cannot be nested inside 'target' region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+
+// TARGET TEAMS DIRECTIVE
+#pragma omp target teams
+#pragma omp parallel
+ bar();
+#pragma omp target teams
+#pragma omp for // expected-error {{region cannot be closely nested inside 'target teams' region; perhaps you forget to enclose 'omp for' directive into a parallel region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams
+#pragma omp simd // expected-error {{region cannot be closely nested inside 'target teams' region; perhaps you forget to enclose 'omp simd' directive into a parallel region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams
+#pragma omp for simd // expected-error {{region cannot be closely nested inside 'target teams' region; perhaps you forget to enclose 'omp for simd' directive into a parallel region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams
+#pragma omp sections // expected-error {{region cannot be closely nested inside 'target teams' region; perhaps you forget to enclose 'omp sections' directive into a parallel region?}}
+ {
+ bar();
+ }
+#pragma omp target teams
+#pragma omp section // expected-error {{'omp section' directive must be closely nested to a sections region, not a target teams region}}
+ {
+ bar();
+ }
+#pragma omp target teams
+#pragma omp single // expected-error {{region cannot be closely nested inside 'target teams' region; perhaps you forget to enclose 'omp single' directive into a parallel region?}}
+ bar();
+
+#pragma omp target teams
+#pragma omp master // expected-error {{region cannot be closely nested inside 'target teams' region; perhaps you forget to enclose 'omp master' directive into a parallel region?}}
+ {
+ bar();
+ }
+#pragma omp target teams
+#pragma omp critical // expected-error {{region cannot be closely nested inside 'target teams' region; perhaps you forget to enclose 'omp critical' directive into a parallel region?}}
+ {
+ bar();
+ }
+#pragma omp target teams
+#pragma omp parallel for
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams
+#pragma omp parallel for simd
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams
+#pragma omp parallel sections
+ {
+ bar();
+ }
+#pragma omp target teams
+#pragma omp task // expected-error {{region cannot be closely nested inside 'target teams' region; perhaps you forget to enclose 'omp task' directive into a parallel region?}}
+ {
+ bar();
+ }
+#pragma omp target teams
+ {
+#pragma omp taskyield // expected-error {{region cannot be closely nested inside 'target teams' region; perhaps you forget to enclose 'omp taskyield' directive into a parallel region?}}
+ bar();
+ }
+#pragma omp target teams
+ {
+#pragma omp barrier // expected-error {{region cannot be closely nested inside 'target teams' region; perhaps you forget to enclose 'omp barrier' directive into a parallel region?}}
+ bar();
+ }
+#pragma omp target teams
+ {
+#pragma omp taskwait // expected-error {{region cannot be closely nested inside 'target teams' region; perhaps you forget to enclose 'omp taskwait' directive into a parallel region?}}
+ bar();
+ }
+#pragma omp target teams
+ {
+#pragma omp flush // expected-error {{region cannot be closely nested inside 'target teams' region; perhaps you forget to enclose 'omp flush' directive into a parallel region?}}
+ bar();
+ }
+#pragma omp target teams
+ {
+#pragma omp ordered // expected-error {{region cannot be closely nested inside 'target teams' region; perhaps you forget to enclose 'omp ordered' directive into a for or a parallel for region with 'ordered' clause?}}
+ bar();
+ }
+#pragma omp target teams
+ {
+#pragma omp atomic // expected-error {{region cannot be closely nested inside 'target teams' region; perhaps you forget to enclose 'omp atomic' directive into a parallel region?}}
+ ++a;
+ }
+#pragma omp target teams
+ {
+#pragma omp target // expected-error {{region cannot be nested inside 'target teams' region}}
+ ++a;
+ }
+#pragma omp target teams
+ {
+#pragma omp target parallel // expected-error {{region cannot be nested inside 'target teams' region}}
+ ++a;
+ }
+#pragma omp target teams
+#pragma omp target parallel for // expected-error {{region cannot be nested inside 'target teams' region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams
+ {
+#pragma omp target enter data map(to: a) // expected-error {{region cannot be nested inside 'target teams' region}}
+ }
+#pragma omp target teams
+ {
+#pragma omp target exit data map(from: a) // expected-error {{region cannot be nested inside 'target teams' region}}
+ }
+#pragma omp target teams
+ {
+#pragma omp teams // expected-error {{region cannot be closely nested inside 'target teams' region; perhaps you forget to enclose 'omp teams' directive into a target region?}}
+ ++a;
+ }
+#pragma omp target teams
+ {
+#pragma omp taskloop // expected-error {{region cannot be closely nested inside 'target teams' region; perhaps you forget to enclose 'omp taskloop' directive into a parallel region?}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target teams
+#pragma omp distribute
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams
+ {
+#pragma omp target update to(a) // expected-error {{region cannot be nested inside 'target teams' region}}
+ ++a;
+ }
+#pragma omp target teams
+#pragma omp distribute parallel for
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams
+ {
+#pragma omp distribute parallel for
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp distribute parallel for
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp target teams
+ {
+#pragma omp distribute parallel for simd
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp distribute parallel for simd
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp target teams
+ {
+#pragma omp distribute simd
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp distribute simd
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp target teams
+ {
+#pragma omp target simd // expected-error {{region cannot be nested inside 'target teams' region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams
+ {
+#pragma omp teams distribute // expected-error {{region cannot be closely nested inside 'target teams' region; perhaps you forget to enclose 'omp teams distribute' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams
+ {
+#pragma omp teams distribute simd // expected-error {{region cannot be closely nested inside 'target teams' region; perhaps you forget to enclose 'omp teams distribute simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams
+ {
+#pragma omp teams distribute parallel for simd // expected-error {{region cannot be closely nested inside 'target teams' region; perhaps you forget to enclose 'omp teams distribute parallel for simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams
+ {
+#pragma omp teams distribute parallel for // expected-error {{region cannot be closely nested inside 'target teams' region; perhaps you forget to enclose 'omp teams distribute parallel for' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams
+ {
+#pragma omp target teams // expected-error {{region cannot be nested inside 'target teams' region}}
+ a++;
+ }
+#pragma omp target teams
+ {
+#pragma omp target teams distribute // expected-error {{region cannot be nested inside 'target teams' region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams
+ {
+#pragma omp target teams distribute parallel for // expected-error {{region cannot be nested inside 'target teams' region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+
+// TARGET TEAMS DISTRIBUTE DIRECTIVE
+#pragma omp target teams distribute // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp distribute parallel for simd // expected-error {{region cannot be closely nested inside 'target teams distribute' region; perhaps you forget to enclose 'omp distribute parallel for simd' directive into a teams region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp distribute // expected-error {{region cannot be closely nested inside 'target teams distribute' region; perhaps you forget to enclose 'omp distribute' directive into a teams region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp for // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp simd // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp for simd // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp sections // OK
+ {
+ bar();
+ }
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp section // expected-error {{'omp section' directive must be closely nested to a sections region, not a target teams distribute region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp single // OK
+ {
+ bar();
+ }
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp master // OK
+ {
+ bar();
+ }
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp critical // OK
+ {
+ bar();
+ }
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel // OK
+ {
+#pragma omp single
+ {
+ bar();
+ }
+ }
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel for // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel for simd // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel sections // OK
+ {
+ bar();
+ }
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp task // OK
+ {
+ bar();
+ }
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp taskyield // OK
+ bar();
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp barrier // OK
+ bar();
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp taskwait // OK
+ bar();
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp flush // OK
+ bar();
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp ordered // expected-error {{region cannot be closely nested inside 'target teams distribute' region; perhaps you forget to enclose 'omp ordered' directive into a for or a parallel for region with 'ordered' clause?}}
+ bar();
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp atomic // OK
+ ++a;
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target // expected-error {{region cannot be nested inside 'target teams distribute' region}}
+ ++a;
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target parallel // expected-error {{region cannot be nested inside 'target teams distribute' region}}
+ ++a;
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target parallel for // expected-error {{region cannot be nested inside 'target teams distribute' region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target enter data map(to: a) // expected-error {{region cannot be nested inside 'target teams distribute' region}}
+ ++a;
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target exit data map(from: a) // expected-error {{region cannot be nested inside 'target teams distribute' region}}
+ ++a;
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams // expected-error {{region cannot be closely nested inside 'target teams distribute' region; perhaps you forget to enclose 'omp teams' directive into a target region?}}
+ ++a;
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target update to(a) // expected-error {{region cannot be nested inside 'target teams distribute' region}}
+ ++a;
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp distribute simd // expected-error {{region cannot be closely nested inside 'target teams distribute' region; perhaps you forget to enclose 'omp distribute simd' directive into a teams region?}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target simd // expected-error {{region cannot be nested inside 'target teams distribute' region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute // expected-error {{region cannot be closely nested inside 'target teams distribute' region; perhaps you forget to enclose 'omp teams distribute' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute simd // expected-error {{region cannot be closely nested inside 'target teams distribute' region; perhaps you forget to enclose 'omp teams distribute simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for simd // expected-error {{region cannot be closely nested inside 'target teams distribute' region; perhaps you forget to enclose 'omp teams distribute parallel for simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for // expected-error {{region cannot be closely nested inside 'target teams distribute' region; perhaps you forget to enclose 'omp teams distribute parallel for' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams // expected-error {{region cannot be nested inside 'target teams distribute' region}}
+ a++;
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute // expected-error {{region cannot be nested inside 'target teams distribute' region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute parallel for // expected-error {{region cannot be nested inside 'target teams distribute' region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+
+// TARGET TEAMS DISTRIBUTE PARALLEL FOR DIRECTIVE
+#pragma omp target teams distribute parallel for // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp distribute parallel for simd // expected-error {{region cannot be closely nested inside 'target teams distribute parallel for' region; perhaps you forget to enclose 'omp distribute parallel for simd' directive into a teams region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp distribute // expected-error {{region cannot be closely nested inside 'target teams distribute parallel for' region; perhaps you forget to enclose 'omp distribute' directive into a teams region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp for // expected-error {{region cannot be closely nested inside 'target teams distribute parallel for' region; perhaps you forget to enclose 'omp for' directive into a parallel region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp simd // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp for simd // expected-error {{region cannot be closely nested inside 'target teams distribute parallel for' region; perhaps you forget to enclose 'omp for simd' directive into a parallel region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp sections // expected-error {{region cannot be closely nested inside 'target teams distribute parallel for' region; perhaps you forget to enclose 'omp sections' directive into a parallel region?}}
+ {
+ bar();
+ }
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp section // expected-error {{'omp section' directive must be closely nested to a sections region, not a target teams distribute parallel for region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp single // expected-error {{region cannot be closely nested inside 'target teams distribute parallel for' region; perhaps you forget to enclose 'omp single' directive into a parallel region?}}
+ {
+ bar();
+ }
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp master // expected-error {{region cannot be closely nested inside 'target teams distribute parallel for' region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp critical // OK
+ {
+ bar();
+ }
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel // OK
+ {
+#pragma omp single
+ {
+ bar();
+ }
+ }
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel for // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel for simd // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel sections // OK
+ {
+ bar();
+ }
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp task // OK
+ {
+ bar();
+ }
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp taskyield // OK
+ bar();
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp barrier // expected-error {{region cannot be closely nested inside 'target teams distribute parallel for' region}}
+ bar();
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp taskwait // OK
+ bar();
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp flush // OK
+ bar();
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp ordered // expected-error {{region cannot be closely nested inside 'target teams distribute parallel for' region; perhaps you forget to enclose 'omp ordered' directive into a for or a parallel for region with 'ordered' clause?}}
+ bar();
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp atomic // OK
+ ++a;
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target // expected-error {{region cannot be nested inside 'target teams distribute parallel for' region}}
+ ++a;
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target parallel // expected-error {{region cannot be nested inside 'target teams distribute parallel for' region}}
+ ++a;
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target parallel for // expected-error {{region cannot be nested inside 'target teams distribute parallel for' region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target enter data map(to: a) // expected-error {{region cannot be nested inside 'target teams distribute parallel for' region}}
+ ++a;
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target exit data map(from: a) // expected-error {{region cannot be nested inside 'target teams distribute parallel for' region}}
+ ++a;
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams // expected-error {{region cannot be closely nested inside 'target teams distribute parallel for' region; perhaps you forget to enclose 'omp teams' directive into a target region?}}
+ ++a;
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target update to(a) // expected-error {{region cannot be nested inside 'target teams distribute parallel for' region}}
+ ++a;
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp distribute simd // expected-error {{region cannot be closely nested inside 'target teams distribute parallel for' region; perhaps you forget to enclose 'omp distribute simd' directive into a teams region?}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target simd // expected-error {{region cannot be nested inside 'target teams distribute parallel for' region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute // expected-error {{region cannot be closely nested inside 'target teams distribute parallel for' region; perhaps you forget to enclose 'omp teams distribute' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute simd // expected-error {{region cannot be closely nested inside 'target teams distribute parallel for' region; perhaps you forget to enclose 'omp teams distribute simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for simd // expected-error {{region cannot be closely nested inside 'target teams distribute parallel for' region; perhaps you forget to enclose 'omp teams distribute parallel for simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for // expected-error {{region cannot be closely nested inside 'target teams distribute parallel for' region; perhaps you forget to enclose 'omp teams distribute parallel for' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams // expected-error {{region cannot be nested inside 'target teams distribute parallel for' region}}
+ a++;
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute // expected-error {{region cannot be nested inside 'target teams distribute parallel for' region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute parallel for // expected-error {{region cannot be nested inside 'target teams distribute parallel for' region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+
}
void foo() {
@@ -4839,6 +8203,53 @@ void foo() {
for (int i = 0; i < 10; ++i)
;
}
+#pragma omp parallel
+ {
+#pragma omp target simd // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp parallel
+ {
+#pragma omp teams distribute // expected-error {{region cannot be closely nested inside 'parallel' region; perhaps you forget to enclose 'omp teams distribute' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp parallel
+ {
+#pragma omp teams distribute simd // expected-error {{region cannot be closely nested inside 'parallel' region; perhaps you forget to enclose 'omp teams distribute simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp parallel
+ {
+#pragma omp teams distribute parallel for simd // expected-error {{region cannot be closely nested inside 'parallel' region; perhaps you forget to enclose 'omp teams distribute parallel for simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp parallel
+ {
+#pragma omp teams distribute parallel for // expected-error {{region cannot be closely nested inside 'parallel' region; perhaps you forget to enclose 'omp teams distribute parallel for' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp parallel
+ {
+#pragma omp target teams // OK
+ a++;
+ }
+#pragma omp parallel
+ {
+#pragma omp target teams distribute // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp parallel
+ {
+#pragma omp target teams distribute parallel for // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
// SIMD DIRECTIVE
#pragma omp simd
@@ -5015,6 +8426,53 @@ void foo() {
for (int j = 0; j < 10; ++j)
;
}
+#pragma omp simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ a++;
+ }
+#pragma omp simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute parallel for // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
// FOR DIRECTIVE
#pragma omp for
@@ -5211,6 +8669,53 @@ void foo() {
for (int j = 0; j < 10; ++j)
;
}
+#pragma omp for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target simd // OK
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute // expected-error {{region cannot be closely nested inside 'for' region; perhaps you forget to enclose 'omp teams distribute' directive into a target region?}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute simd // expected-error {{region cannot be closely nested inside 'for' region; perhaps you forget to enclose 'omp teams distribute simd' directive into a target region?}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for simd // expected-error {{region cannot be closely nested inside 'for' region; perhaps you forget to enclose 'omp teams distribute parallel for simd' directive into a target region?}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for // expected-error {{region cannot be closely nested inside 'for' region; perhaps you forget to enclose 'omp teams distribute parallel for' directive into a target region?}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams // OK
+ a++;
+ }
+#pragma omp for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute // OK
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute parallel for // OK
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
// FOR SIMD DIRECTIVE
#pragma omp for simd
@@ -5387,6 +8892,53 @@ void foo() {
for (int j = 0; j < 10; ++j)
;
}
+#pragma omp for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ a++;
+ }
+#pragma omp for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute parallel for // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
// SECTIONS DIRECTIVE
#pragma omp sections
@@ -5572,6 +9124,53 @@ void foo() {
for (int i = 0; i < 10; ++i)
;
}
+#pragma omp sections
+ {
+#pragma omp target simd // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp sections
+ {
+#pragma omp teams distribute // expected-error {{region cannot be closely nested inside 'sections' region; perhaps you forget to enclose 'omp teams distribute' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp sections
+ {
+#pragma omp teams distribute simd // expected-error {{region cannot be closely nested inside 'sections' region; perhaps you forget to enclose 'omp teams distribute simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp sections
+ {
+#pragma omp teams distribute parallel for simd // expected-error {{region cannot be closely nested inside 'sections' region; perhaps you forget to enclose 'omp teams distribute parallel for simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp sections
+ {
+#pragma omp teams distribute parallel for // expected-error {{region cannot be closely nested inside 'sections' region; perhaps you forget to enclose 'omp teams distribute parallel for' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp sections
+ {
+#pragma omp target teams // OK
+ a++;
+ }
+#pragma omp sections
+ {
+#pragma omp target teams distribute // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp sections
+ {
+#pragma omp target teams distribute parallel for // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
// SECTION DIRECTIVE
#pragma omp section // expected-error {{orphaned 'omp section' directives are prohibited, it must be closely nested to a sections region}}
@@ -5849,6 +9448,61 @@ void foo() {
for (int i = 0; i < 10; ++i)
;
}
+#pragma omp sections
+ {
+#pragma omp section
+#pragma omp target simd // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp sections
+ {
+#pragma omp section
+#pragma omp teams distribute // expected-error {{region cannot be closely nested inside 'section' region; perhaps you forget to enclose 'omp teams distribute' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp sections
+ {
+#pragma omp section
+#pragma omp teams distribute simd // expected-error {{region cannot be closely nested inside 'section' region; perhaps you forget to enclose 'omp teams distribute simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp sections
+ {
+#pragma omp section
+#pragma omp teams distribute parallel for simd // expected-error {{region cannot be closely nested inside 'section' region; perhaps you forget to enclose 'omp teams distribute parallel for simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp sections
+ {
+#pragma omp section
+#pragma omp teams distribute parallel for // expected-error {{region cannot be closely nested inside 'section' region; perhaps you forget to enclose 'omp teams distribute parallel for' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp sections
+ {
+#pragma omp section
+#pragma omp target teams // OK
+ a++;
+ }
+#pragma omp sections
+ {
+#pragma omp section
+#pragma omp target teams distribute // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp sections
+ {
+#pragma omp section
+#pragma omp target teams distribute parallel for // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
// SINGLE DIRECTIVE
#pragma omp single
@@ -6035,6 +9689,53 @@ void foo() {
for (int i = 0; i < 10; ++i)
;
}
+#pragma omp single
+ {
+#pragma omp target simd // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp single
+ {
+#pragma omp teams distribute // expected-error {{region cannot be closely nested inside 'single' region; perhaps you forget to enclose 'omp teams distribute' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp single
+ {
+#pragma omp teams distribute simd // expected-error {{region cannot be closely nested inside 'single' region; perhaps you forget to enclose 'omp teams distribute simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp single
+ {
+#pragma omp teams distribute parallel for simd // expected-error {{region cannot be closely nested inside 'single' region; perhaps you forget to enclose 'omp teams distribute parallel for simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp single
+ {
+#pragma omp teams distribute parallel for // expected-error {{region cannot be closely nested inside 'single' region; perhaps you forget to enclose 'omp teams distribute parallel for' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp single
+ {
+#pragma omp target teams // oK
+ a++;
+ }
+#pragma omp single
+ {
+#pragma omp target teams distribute // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp single
+ {
+#pragma omp target teams distribute parallel for // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
// MASTER DIRECTIVE
#pragma omp master
@@ -6231,6 +9932,53 @@ void foo() {
for (int i = 0; i < 10; ++i)
;
}
+#pragma omp master
+ {
+#pragma omp target simd // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp master
+ {
+#pragma omp teams distribute // expected-error {{region cannot be closely nested inside 'master' region; perhaps you forget to enclose 'omp teams distribute' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp master
+ {
+#pragma omp teams distribute simd // expected-error {{region cannot be closely nested inside 'master' region; perhaps you forget to enclose 'omp teams distribute simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp master
+ {
+#pragma omp teams distribute parallel for simd // expected-error {{region cannot be closely nested inside 'master' region; perhaps you forget to enclose 'omp teams distribute parallel for simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp master
+ {
+#pragma omp teams distribute parallel for // expected-error {{region cannot be closely nested inside 'master' region; perhaps you forget to enclose 'omp teams distribute parallel for' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp master
+ {
+#pragma omp target teams // OK
+ a++;
+ }
+#pragma omp master
+ {
+#pragma omp target teams distribute // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp master
+ {
+#pragma omp target teams distribute parallel for // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
// CRITICAL DIRECTIVE
#pragma omp critical
@@ -6446,6 +10194,53 @@ void foo() {
for (int i = 0; i < 10; ++i)
;
}
+#pragma omp critical
+ {
+#pragma omp target simd // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp critical
+ {
+#pragma omp teams distribute // expected-error {{region cannot be closely nested inside 'critical' region; perhaps you forget to enclose 'omp teams distribute' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp critical
+ {
+#pragma omp teams distribute simd // expected-error {{region cannot be closely nested inside 'critical' region; perhaps you forget to enclose 'omp teams distribute simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp critical
+ {
+#pragma omp teams distribute parallel for simd // expected-error {{region cannot be closely nested inside 'critical' region; perhaps you forget to enclose 'omp teams distribute parallel for simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp critical
+ {
+#pragma omp teams distribute parallel for // expected-error {{region cannot be closely nested inside 'critical' region; perhaps you forget to enclose 'omp teams distribute parallel for' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp critical
+ {
+#pragma omp target teams // OK
+ a++;
+ }
+#pragma omp critical
+ {
+#pragma omp target teams distribute // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp critical
+ {
+#pragma omp target teams distribute parallel for // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
// PARALLEL FOR DIRECTIVE
#pragma omp parallel for
@@ -6657,6 +10452,53 @@ void foo() {
for (int j = 0; j < 10; ++j)
;
}
+#pragma omp parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target simd // OK
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute // expected-error {{region cannot be closely nested inside 'parallel for' region; perhaps you forget to enclose 'omp teams distribute' directive into a target region?}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute simd // expected-error {{region cannot be closely nested inside 'parallel for' region; perhaps you forget to enclose 'omp teams distribute simd' directive into a target region?}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for simd // expected-error {{region cannot be closely nested inside 'parallel for' region; perhaps you forget to enclose 'omp teams distribute parallel for simd' directive into a target region?}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for // expected-error {{region cannot be closely nested inside 'parallel for' region; perhaps you forget to enclose 'omp teams distribute parallel for' directive into a target region?}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams // OK
+ a++;
+ }
+#pragma omp parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute // OK
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute parallel for // OK
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
// PARALLEL FOR SIMD DIRECTIVE
#pragma omp parallel for simd
@@ -6868,6 +10710,53 @@ void foo() {
for (int j = 0; j < 10; ++j)
;
}
+#pragma omp parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ a++;
+ }
+#pragma omp parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute parallel for // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
// PARALLEL SECTIONS DIRECTIVE
#pragma omp parallel sections
@@ -7063,6 +10952,53 @@ void foo() {
for (int i = 0; i < 10; ++i)
;
}
+#pragma omp parallel sections
+ {
+#pragma omp target simd // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp parallel sections
+ {
+#pragma omp teams distribute // expected-error {{region cannot be closely nested inside 'parallel sections' region; perhaps you forget to enclose 'omp teams distribute' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp parallel sections
+ {
+#pragma omp teams distribute simd // expected-error {{region cannot be closely nested inside 'parallel sections' region; perhaps you forget to enclose 'omp teams distribute simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp parallel sections
+ {
+#pragma omp teams distribute parallel for simd // expected-error {{region cannot be closely nested inside 'parallel sections' region; perhaps you forget to enclose 'omp teams distribute parallel for simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp parallel sections
+ {
+#pragma omp teams distribute parallel for // expected-error {{region cannot be closely nested inside 'parallel sections' region; perhaps you forget to enclose 'omp teams distribute parallel for' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp parallel sections
+ {
+#pragma omp target teams // OK
+ a++;
+ }
+#pragma omp parallel sections
+ {
+#pragma omp target teams distribute // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp parallel sections
+ {
+#pragma omp target teams distribute parallel for // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
// TASK DIRECTIVE
#pragma omp task
@@ -7208,6 +11144,53 @@ void foo() {
for (int i = 0; i < 10; ++i)
;
}
+#pragma omp task
+ {
+#pragma omp target simd // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp task
+ {
+#pragma omp teams distribute // expected-error {{region cannot be closely nested inside 'task' region; perhaps you forget to enclose 'omp teams distribute' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp task
+ {
+#pragma omp teams distribute simd // expected-error {{region cannot be closely nested inside 'task' region; perhaps you forget to enclose 'omp teams distribute simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp task
+ {
+#pragma omp teams distribute parallel for simd // expected-error {{region cannot be closely nested inside 'task' region; perhaps you forget to enclose 'omp teams distribute parallel for simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp task
+ {
+#pragma omp teams distribute parallel for // expected-error {{region cannot be closely nested inside 'task' region; perhaps you forget to enclose 'omp teams distribute parallel for' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp task
+ {
+#pragma omp target teams // OK
+ a++;
+ }
+#pragma omp task
+ {
+#pragma omp target teams distribute // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp task
+ {
+#pragma omp target teams distribute parallel for // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
// ATOMIC DIRECTIVE
#pragma omp atomic
@@ -7452,6 +11435,69 @@ void foo() {
for (int i = 0; i < 10; ++i)
;
}
+#pragma omp atomic
+ // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
+ // expected-note@+1 {{expected an expression statement}}
+ {
+#pragma omp target simd // expected-error {{OpenMP constructs may not be nested inside an atomic region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp atomic
+ // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
+ // expected-note@+1 {{expected an expression statement}}
+ {
+#pragma omp teams distribute // expected-error {{OpenMP constructs may not be nested inside an atomic region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp atomic
+ // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
+ // expected-note@+1 {{expected an expression statement}}
+ {
+#pragma omp teams distribute simd // expected-error {{OpenMP constructs may not be nested inside an atomic region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp atomic
+ // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
+ // expected-note@+1 {{expected an expression statement}}
+ {
+#pragma omp teams distribute parallel for simd // expected-error {{OpenMP constructs may not be nested inside an atomic region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp atomic
+ // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
+ // expected-note@+1 {{expected an expression statement}}
+ {
+#pragma omp teams distribute parallel for // expected-error {{OpenMP constructs may not be nested inside an atomic region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp atomic
+ // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
+ // expected-note@+1 {{expected an expression statement}}
+ {
+#pragma omp target teams // expected-error {{OpenMP constructs may not be nested inside an atomic region}}
+ a++;
+ }
+#pragma omp atomic
+ // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
+ // expected-note@+1 {{expected an expression statement}}
+ {
+#pragma omp target teams distribute // expected-error {{OpenMP constructs may not be nested inside an atomic region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp atomic
+ // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
+ // expected-note@+1 {{expected an expression statement}}
+ {
+#pragma omp target teams distribute parallel for // expected-error {{OpenMP constructs may not be nested inside an atomic region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
// TARGET DIRECTIVE
#pragma omp target
@@ -7611,6 +11657,53 @@ void foo() {
for (int i = 0; i < 10; ++i)
;
}
+#pragma omp target
+ {
+#pragma omp target simd // expected-error {{region cannot be nested inside 'target' region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+ {
+#pragma omp teams distribute // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+ {
+#pragma omp teams distribute simd // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+ {
+#pragma omp teams distribute parallel for simd // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+ {
+#pragma omp teams distribute parallel for // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+ {
+#pragma omp target teams // expected-error {{region cannot be nested inside 'target' region}}
+ a++;
+ }
+#pragma omp target
+ {
+#pragma omp target teams distribute // expected-error {{region cannot be nested inside 'target' region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+ {
+#pragma omp target teams distribute parallel for // expected-error {{region cannot be nested inside 'target' region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
// TARGET PARALLEL DIRECTIVE
#pragma omp target parallel
@@ -7767,6 +11860,53 @@ void foo() {
for (int i = 0; i < 10; ++i)
;
}
+#pragma omp target parallel
+ {
+#pragma omp target simd // expected-error {{region cannot be nested inside 'target parallel' regio}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target parallel
+ {
+#pragma omp teams distribute // expected-error {{region cannot be closely nested inside 'target parallel' region; perhaps you forget to enclose 'omp teams distribute' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target parallel
+ {
+#pragma omp teams distribute simd // expected-error {{region cannot be closely nested inside 'target parallel' region; perhaps you forget to enclose 'omp teams distribute simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target parallel
+ {
+#pragma omp teams distribute parallel for simd // expected-error {{region cannot be closely nested inside 'target parallel' region; perhaps you forget to enclose 'omp teams distribute parallel for simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target parallel
+ {
+#pragma omp teams distribute parallel for // expected-error {{region cannot be closely nested inside 'target parallel' region; perhaps you forget to enclose 'omp teams distribute parallel for' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target parallel
+ {
+#pragma omp target teams // expected-error {{region cannot be nested inside 'target parallel' region}}
+ a++;
+ }
+#pragma omp target parallel
+ {
+#pragma omp target teams distribute // expected-error {{region cannot be nested inside 'target parallel' region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target parallel
+ {
+#pragma omp target teams distribute parallel for // expected-error {{region cannot be nested inside 'target parallel' region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
// TARGET PARALLEL FOR DIRECTIVE
#pragma omp target parallel for
@@ -7978,6 +12118,53 @@ void foo() {
for (int j = 0; j < 10; ++j)
;
}
+#pragma omp target parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target simd // expected-error {{region cannot be nested inside 'target parallel for' region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp target parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute // expected-error {{region cannot be closely nested inside 'target parallel for' region; perhaps you forget to enclose 'omp teams distribute' directive into a target region?}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp target parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute simd // expected-error {{region cannot be closely nested inside 'target parallel for' region; perhaps you forget to enclose 'omp teams distribute simd' directive into a target region?}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp target parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for simd // expected-error {{region cannot be closely nested inside 'target parallel for' region; perhaps you forget to enclose 'omp teams distribute parallel for simd' directive into a target region?}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp target parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for // expected-error {{region cannot be closely nested inside 'target parallel for' region; perhaps you forget to enclose 'omp teams distribute parallel for' directive into a target region?}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp target parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams // expected-error {{region cannot be nested inside 'target parallel for' region}}
+ a++;
+ }
+#pragma omp target parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute // expected-error {{region cannot be nested inside 'target parallel for' region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp target parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute parallel for // expected-error {{region cannot be nested inside 'target parallel for' region}}
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
// TEAMS DIRECTIVE
#pragma omp target
@@ -8089,7 +12276,7 @@ void foo() {
#pragma omp target
#pragma omp teams
{
-#pragma omp target // expected-error {{region cannot be closely nested inside 'teams' region; perhaps you forget to enclose 'omp target' directive into a parallel region?}}
+#pragma omp target // expected-error {{region cannot be nested inside 'target' region}}
++a;
}
#pragma omp target
@@ -8106,12 +12293,12 @@ void foo() {
#pragma omp target
#pragma omp teams
{
-#pragma omp target enter data map(to: a) // expected-error {{region cannot be closely nested inside 'teams' region; perhaps you forget to enclose 'omp target enter data' directive into a parallel region?}}
+#pragma omp target enter data map(to: a) // expected-error {{region cannot be nested inside 'target' region}}
}
#pragma omp target
#pragma omp teams
{
-#pragma omp target exit data map(from: a) // expected-error {{region cannot be closely nested inside 'teams' region; perhaps you forget to enclose 'omp target exit data' directive into a parallel region?}}
+#pragma omp target exit data map(from: a) // expected-error {{region cannot be nested inside 'target' region}}
}
#pragma omp target
#pragma omp teams
@@ -8142,7 +12329,7 @@ void foo() {
#pragma omp target
#pragma omp teams
{
-#pragma omp target update to(a) // expected-error {{region cannot be closely nested inside 'teams' region; perhaps you forget to enclose 'omp target update' directive into a parallel region?}}
+#pragma omp target update to(a) // expected-error {{region cannot be nested inside 'target' region}}
++a;
}
#pragma omp target
@@ -8180,6 +12367,61 @@ void foo() {
for (int j = 0; j < 10; ++j)
;
}
+#pragma omp target
+#pragma omp teams
+ {
+#pragma omp target simd // expected-error {{region cannot be nested inside 'target' region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams
+ {
+#pragma omp teams distribute // expected-error {{region cannot be closely nested inside 'teams' region; perhaps you forget to enclose 'omp teams distribute' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams
+ {
+#pragma omp teams distribute simd // expected-error {{region cannot be closely nested inside 'teams' region; perhaps you forget to enclose 'omp teams distribute simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams
+ {
+#pragma omp teams distribute parallel for simd // expected-error {{region cannot be closely nested inside 'teams' region; perhaps you forget to enclose 'omp teams distribute parallel for simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams
+ {
+#pragma omp teams distribute parallel for // expected-error {{region cannot be closely nested inside 'teams' region; perhaps you forget to enclose 'omp teams distribute parallel for' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams
+ {
+#pragma omp target teams // expected-error {{region cannot be nested inside 'target' region}}
+ a++;
+ }
+#pragma omp target
+#pragma omp teams
+ {
+#pragma omp target teams distribute // expected-error {{region cannot be nested inside 'target' region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams
+ {
+#pragma omp target teams distribute parallel for // expected-error {{region cannot be nested inside 'target' region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
// TASKLOOP DIRECTIVE
#pragma omp taskloop
@@ -8381,6 +12623,53 @@ void foo() {
for (int i = 0; i < 10; ++i)
;
}
+#pragma omp taskloop
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target simd // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp taskloop
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute // expected-error {{region cannot be closely nested inside 'taskloop' region; perhaps you forget to enclose 'omp teams distribute' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp taskloop
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute simd // expected-error {{region cannot be closely nested inside 'taskloop' region; perhaps you forget to enclose 'omp teams distribute simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp taskloop
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for simd // expected-error {{region cannot be closely nested inside 'taskloop' region; perhaps you forget to enclose 'omp teams distribute parallel for simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp taskloop
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for // expected-error {{region cannot be closely nested inside 'taskloop' region; perhaps you forget to enclose 'omp teams distribute parallel for' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp taskloop
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams // OK
+ a++;
+ }
+#pragma omp taskloop
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp taskloop
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute parallel for // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
// DISTRIBUTE DIRECTIVE
#pragma omp target
@@ -8585,7 +12874,6 @@ void foo() {
#pragma omp teams // expected-error {{region cannot be closely nested inside 'distribute' region; perhaps you forget to enclose 'omp teams' directive into a target region?}}
++a;
}
- return foo<int>();
#pragma omp target
#pragma omp teams
#pragma omp distribute
@@ -8631,8 +12919,56 @@ void foo() {
for (int i = 0; i < 10; ++i)
++a;
}
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target simd // expected-error {{region cannot be nested inside 'target' region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target parallel for simd // expected-error {{region cannot be nested inside 'target' region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target parallel for // expected-error {{region cannot be nested inside 'target' region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams // expected-error {{region cannot be nested inside 'target' region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute // expected-error {{region cannot be nested inside 'target' region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute parallel for // expected-error {{region cannot be nested inside 'target' region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
- // DISTRIBUTE PARALLEL FOR DIRECTIVE
+// DISTRIBUTE PARALLEL FOR DIRECTIVE
#pragma omp target
#pragma omp teams
#pragma omp distribute parallel for
@@ -8844,7 +13180,6 @@ void foo() {
#pragma omp teams // expected-error {{region cannot be closely nested inside 'distribute parallel for' region; perhaps you forget to enclose 'omp teams' directive into a target region?}}
++a;
}
- return foo<int>();
#pragma omp target
#pragma omp teams
#pragma omp distribute parallel for
@@ -8874,6 +13209,69 @@ void foo() {
for (int i = 0; i < 10; ++i)
++a;
}
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target simd // expected-error {{region cannot be nested inside 'target' region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute // expected-error {{region cannot be closely nested inside 'distribute parallel for' region; perhaps you forget to enclose 'omp teams distribute' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute simd // expected-error {{region cannot be closely nested inside 'distribute parallel for' region; perhaps you forget to enclose 'omp teams distribute simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for simd // expected-error {{region cannot be closely nested inside 'distribute parallel for' region; perhaps you forget to enclose 'omp teams distribute parallel for simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for // expected-error {{region cannot be closely nested inside 'distribute parallel for' region; perhaps you forget to enclose 'omp teams distribute parallel for' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams // expected-error {{region cannot be nested inside 'target' region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute // expected-error {{region cannot be nested inside 'target' region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute parallel for // expected-error {{region cannot be nested inside 'target' region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
// DISTRIBUTE PARALLEL FOR SIMD DIRECTIVE
#pragma omp target
@@ -9078,7 +13476,6 @@ void foo() {
#pragma omp teams // expected-error {{OpenMP constructs may not be nested inside a simd region}}
++a;
}
- return foo<int>();
#pragma omp target
#pragma omp teams
#pragma omp distribute parallel for simd
@@ -9108,6 +13505,69 @@ void foo() {
for (int i = 0; i < 10; ++i)
;
}
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ a++;
+ }
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute parallel for // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
// DISTRIBUTE SIMD DIRECTIVE
#pragma omp target
@@ -9312,7 +13772,6 @@ void foo() {
#pragma omp teams // expected-error {{OpenMP constructs may not be nested inside a simd region}}
++a;
}
- return foo<int>();
#pragma omp target
#pragma omp teams
#pragma omp distribute simd
@@ -9342,4 +13801,2039 @@ void foo() {
for (int i = 0; i < 10; ++i)
;
}
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ a++;
+ }
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute parallel for // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+
+// TARGET SIMD DIRECTIVE
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp distribute parallel for simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp distribute // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp for // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp simd // expected-warning {{OpenMP only allows an ordered construct with the simd clause nested in a simd construct}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp for simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp sections // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp section // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp single // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp master // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp critical // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+#pragma omp single
+ {
+ bar();
+ }
+ }
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel for // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel for simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel sections // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp task // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp taskyield // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ bar();
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp barrier // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ bar();
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp taskwait // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ bar();
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp flush // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ bar();
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp ordered // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ bar();
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp atomic // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ ++a;
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ ++a;
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target parallel // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ ++a;
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ ++a;
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target enter data map(to: a) // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ ++a;
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target exit data map(from: a) // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ ++a;
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target update to(a) // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ ++a;
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp distribute simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ a++;
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute parallel for // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+
+// TEAMS DISTRIBUTE DIRECTIVE
+#pragma omp teams distribute // expected-error {{orphaned 'omp teams distribute' directives are prohibited; perhaps you forget to enclose the directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp distribute parallel for simd // expected-error {{region cannot be closely nested inside 'teams distribute' region; perhaps you forget to enclose 'omp distribute parallel for simd' directive into a teams region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp distribute // expected-error {{region cannot be closely nested inside 'teams distribute' region; perhaps you forget to enclose 'omp distribute' directive into a teams region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp for // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp simd // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp for simd // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp sections // OK
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp section // expected-error {{'omp section' directive must be closely nested to a sections region, not a teams distribute region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp single // OK
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp master // OK
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp critical // OK
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel // OK
+ {
+#pragma omp single
+ {
+ bar();
+ }
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel for // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel for simd // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel sections // OK
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp task // OK
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp taskyield // OK
+ bar();
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp barrier // OK
+ bar();
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp taskwait // OK
+ bar();
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp flush // OK
+ bar();
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp ordered // expected-error {{region cannot be closely nested inside 'teams distribute' region; perhaps you forget to enclose 'omp ordered' directive into a for or a parallel for region with 'ordered' clause?}}
+ bar();
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp atomic // OK
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target // expected-error {{region cannot be nested inside 'target' region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target parallel // expected-error {{region cannot be nested inside 'target' region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target parallel for // expected-error {{region cannot be nested inside 'target' region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target enter data map(to: a) // expected-error {{region cannot be nested inside 'target' region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target exit data map(from: a) // expected-error {{region cannot be nested inside 'target' region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams // expected-error {{region cannot be closely nested inside 'teams distribute' region; perhaps you forget to enclose 'omp teams' directive into a target region?}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target update to(a) // expected-error {{region cannot be nested inside 'target' region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp distribute simd // expected-error {{region cannot be closely nested inside 'teams distribute' region; perhaps you forget to enclose 'omp distribute simd' directive into a teams region?}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target simd // expected-error {{region cannot be nested inside 'target' region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute // expected-error {{region cannot be closely nested inside 'teams distribute' region; perhaps you forget to enclose 'omp teams distribute' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute simd // expected-error {{region cannot be closely nested inside 'teams distribute' region; perhaps you forget to enclose 'omp teams distribute simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for simd // expected-error {{region cannot be closely nested inside 'teams distribute' region; perhaps you forget to enclose 'omp teams distribute parallel for simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for // expected-error {{region cannot be closely nested inside 'teams distribute' region; perhaps you forget to enclose 'omp teams distribute parallel for' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams // expected-error {{region cannot be nested inside 'target' region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute // expected-error {{region cannot be nested inside 'target' region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute parallel for // expected-error {{region cannot be nested inside 'target' region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+
+// TEAMS DISTRIBUTE SIMD DIRECTIVE
+#pragma omp teams distribute simd // expected-error {{orphaned 'omp teams distribute simd' directives are prohibited; perhaps you forget to enclose the directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp distribute parallel for simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp distribute // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp for // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp simd // expected-warning {{OpenMP only allows an ordered construct with the simd clause nested in a simd construct}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp for simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp sections // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp section // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp single // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp master // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp critical // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+#pragma omp single
+ {
+ bar();
+ }
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel for // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel for simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel sections // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp task // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp taskyield // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ bar();
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp barrier // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ bar();
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp taskwait // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ bar();
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp flush // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ bar();
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp ordered // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ bar();
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp atomic // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target parallel // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target parallel for // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target enter data map(to: a) // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target exit data map(from: a) // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target update to(a) // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp distribute simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute parallel for // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+
+// TEAMS DISTRIBUTE PARALLEL FOR SIMD DIRECTIVE
+#pragma omp teams distribute parallel for simd // expected-error {{orphaned 'omp teams distribute parallel for simd' directives are prohibited; perhaps you forget to enclose the directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp distribute parallel for simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp distribute // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp for // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp simd // expected-warning {{OpenMP only allows an ordered construct with the simd clause nested in a simd construct}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp for simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp sections // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp section // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp single // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp master // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp critical // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+#pragma omp single
+ {
+ bar();
+ }
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel for // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel for simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel sections // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp task // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp taskyield // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ bar();
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp barrier // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ bar();
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp taskwait // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ bar();
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp flush // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ bar();
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp ordered // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ bar();
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp atomic // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target parallel // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target parallel for // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target enter data map(to: a) // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target exit data map(from: a) // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target update to(a) // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp distribute simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for simd // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute parallel for // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+
+// TEAMS DISTRIBUTE PARALLEL FOR DIRECTIVE
+#pragma omp teams distribute parallel for // expected-error {{orphaned 'omp teams distribute parallel for' directives are prohibited; perhaps you forget to enclose the directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp distribute parallel for simd // expected-error {{region cannot be closely nested inside 'teams distribute parallel for' region; perhaps you forget to enclose 'omp distribute parallel for simd' directive into a teams region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp distribute // expected-error {{region cannot be closely nested inside 'teams distribute parallel for' region; perhaps you forget to enclose 'omp distribute' directive into a teams region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp for // expected-error {{region cannot be closely nested inside 'teams distribute parallel for' region; perhaps you forget to enclose 'omp for' directive into a parallel region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp simd // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp for simd // expected-error {{region cannot be closely nested inside 'teams distribute parallel for' region; perhaps you forget to enclose 'omp for simd' directive into a parallel region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp sections // expected-error {{region cannot be closely nested inside 'teams distribute parallel for' region; perhaps you forget to enclose 'omp sections' directive into a parallel region?}}
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp section // expected-error {{'omp section' directive must be closely nested to a sections region, not a teams distribute parallel for region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp single // expected-error {{region cannot be closely nested inside 'teams distribute parallel for' region; perhaps you forget to enclose 'omp single' directive into a parallel region?}}
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp master // expected-error {{region cannot be closely nested inside 'teams distribute parallel for' region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp critical // OK
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel // OK
+ {
+#pragma omp single
+ {
+ bar();
+ }
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel for // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel for simd // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel sections // OK
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp task // OK
+ {
+ bar();
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp taskyield // OK
+ bar();
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp barrier // expected-error {{region cannot be closely nested inside 'teams distribute parallel for' region}}
+ bar();
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp taskwait // OK
+ bar();
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp flush // OK
+ bar();
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp ordered // expected-error {{region cannot be closely nested inside 'teams distribute parallel for' region; perhaps you forget to enclose 'omp ordered' directive into a for or a parallel for region with 'ordered' clause?}}
+ bar();
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp atomic // OK
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target // expected-error {{region cannot be nested inside 'target' region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target parallel // expected-error {{region cannot be nested inside 'target' region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target parallel for // expected-error {{region cannot be nested inside 'target' region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target enter data map(to: a) // expected-error {{region cannot be nested inside 'target' region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target exit data map(from: a) // expected-error {{region cannot be nested inside 'target' region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams // expected-error {{region cannot be closely nested inside 'teams distribute parallel for' region; perhaps you forget to enclose 'omp teams' directive into a target region?}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target update to(a) // expected-error {{region cannot be nested inside 'target' region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp distribute simd // expected-error {{region cannot be closely nested inside 'teams distribute parallel for' region; perhaps you forget to enclose 'omp distribute simd' directive into a teams region?}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target simd // expected-error {{region cannot be nested inside 'target' region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute // expected-error {{region cannot be closely nested inside 'teams distribute parallel for' region; perhaps you forget to enclose 'omp teams distribute' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute simd // expected-error {{region cannot be closely nested inside 'teams distribute parallel for' region; perhaps you forget to enclose 'omp teams distribute simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for simd // expected-error {{region cannot be closely nested inside 'teams distribute parallel for' region; perhaps you forget to enclose 'omp teams distribute parallel for simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for // expected-error {{region cannot be closely nested inside 'teams distribute parallel for' region; perhaps you forget to enclose 'omp teams distribute parallel for' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams // expected-error {{region cannot be nested inside 'target' region}}
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute // expected-error {{region cannot be nested inside 'target' region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute parallel for // expected-error {{region cannot be nested inside 'target' region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+
+// TARGET TEAMS DIRECTIVE
+#pragma omp target teams
+#pragma omp parallel
+ bar();
+#pragma omp target teams
+#pragma omp for // expected-error {{region cannot be closely nested inside 'target teams' region; perhaps you forget to enclose 'omp for' directive into a parallel region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams
+#pragma omp simd // expected-error {{region cannot be closely nested inside 'target teams' region; perhaps you forget to enclose 'omp simd' directive into a parallel region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams
+#pragma omp for simd // expected-error {{region cannot be closely nested inside 'target teams' region; perhaps you forget to enclose 'omp for simd' directive into a parallel region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams
+#pragma omp sections // expected-error {{region cannot be closely nested inside 'target teams' region; perhaps you forget to enclose 'omp sections' directive into a parallel region?}}
+ {
+ bar();
+ }
+#pragma omp target teams
+#pragma omp section // expected-error {{'omp section' directive must be closely nested to a sections region, not a target teams region}}
+ {
+ bar();
+ }
+#pragma omp target teams
+#pragma omp single // expected-error {{region cannot be closely nested inside 'target teams' region; perhaps you forget to enclose 'omp single' directive into a parallel region?}}
+ bar();
+
+#pragma omp target teams
+#pragma omp master // expected-error {{region cannot be closely nested inside 'target teams' region; perhaps you forget to enclose 'omp master' directive into a parallel region?}}
+ {
+ bar();
+ }
+#pragma omp target teams
+#pragma omp critical // expected-error {{region cannot be closely nested inside 'target teams' region; perhaps you forget to enclose 'omp critical' directive into a parallel region?}}
+ {
+ bar();
+ }
+#pragma omp target teams
+#pragma omp parallel for
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams
+#pragma omp parallel for simd
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams
+#pragma omp parallel sections
+ {
+ bar();
+ }
+#pragma omp target teams
+#pragma omp task // expected-error {{region cannot be closely nested inside 'target teams' region; perhaps you forget to enclose 'omp task' directive into a parallel region?}}
+ {
+ bar();
+ }
+#pragma omp target teams
+ {
+#pragma omp taskyield // expected-error {{region cannot be closely nested inside 'target teams' region; perhaps you forget to enclose 'omp taskyield' directive into a parallel region?}}
+ bar();
+ }
+#pragma omp target teams
+ {
+#pragma omp barrier // expected-error {{region cannot be closely nested inside 'target teams' region; perhaps you forget to enclose 'omp barrier' directive into a parallel region?}}
+ bar();
+ }
+#pragma omp target teams
+ {
+#pragma omp taskwait // expected-error {{region cannot be closely nested inside 'target teams' region; perhaps you forget to enclose 'omp taskwait' directive into a parallel region?}}
+ bar();
+ }
+#pragma omp target teams
+ {
+#pragma omp flush // expected-error {{region cannot be closely nested inside 'target teams' region; perhaps you forget to enclose 'omp flush' directive into a parallel region?}}
+ bar();
+ }
+#pragma omp target teams
+ {
+#pragma omp ordered // expected-error {{region cannot be closely nested inside 'target teams' region; perhaps you forget to enclose 'omp ordered' directive into a for or a parallel for region with 'ordered' clause?}}
+ bar();
+ }
+#pragma omp target teams
+ {
+#pragma omp atomic // expected-error {{region cannot be closely nested inside 'target teams' region; perhaps you forget to enclose 'omp atomic' directive into a parallel region?}}
+ ++a;
+ }
+#pragma omp target teams
+ {
+#pragma omp target // expected-error {{region cannot be nested inside 'target teams' region}}
+ ++a;
+ }
+#pragma omp target teams
+ {
+#pragma omp target parallel // expected-error {{region cannot be nested inside 'target teams' region}}
+ ++a;
+ }
+#pragma omp target teams
+#pragma omp target parallel for // expected-error {{region cannot be nested inside 'target teams' region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams
+ {
+#pragma omp target enter data map(to: a) // expected-error {{region cannot be nested inside 'target teams' region}}
+ }
+#pragma omp target teams
+ {
+#pragma omp target exit data map(from: a) // expected-error {{region cannot be nested inside 'target teams' region}}
+ }
+#pragma omp target teams
+ {
+#pragma omp teams // expected-error {{region cannot be closely nested inside 'target teams' region; perhaps you forget to enclose 'omp teams' directive into a target region?}}
+ ++a;
+ }
+#pragma omp target teams
+ {
+#pragma omp taskloop // expected-error {{region cannot be closely nested inside 'target teams' region; perhaps you forget to enclose 'omp taskloop' directive into a parallel region?}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target teams
+#pragma omp distribute
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams
+ {
+#pragma omp target update to(a) // expected-error {{region cannot be nested inside 'target teams' region}}
+ ++a;
+ }
+#pragma omp target teams
+#pragma omp distribute parallel for
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams
+ {
+#pragma omp distribute parallel for
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp distribute parallel for
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp target teams
+ {
+#pragma omp distribute parallel for simd
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp distribute parallel for simd
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp target teams
+ {
+#pragma omp distribute simd
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp distribute simd
+ for (int j = 0; j < 10; ++j)
+ ;
+ }
+#pragma omp target teams
+ {
+#pragma omp target simd // expected-error {{region cannot be nested inside 'target teams' region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams
+ {
+#pragma omp teams distribute // expected-error {{region cannot be closely nested inside 'target teams' region; perhaps you forget to enclose 'omp teams distribute' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams
+ {
+#pragma omp teams distribute simd // expected-error {{region cannot be closely nested inside 'target teams' region; perhaps you forget to enclose 'omp teams distribute simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams
+ {
+#pragma omp teams distribute parallel for simd // expected-error {{region cannot be closely nested inside 'target teams' region; perhaps you forget to enclose 'omp teams distribute parallel for simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams
+ {
+#pragma omp teams distribute parallel for // expected-error {{region cannot be closely nested inside 'target teams' region; perhaps you forget to enclose 'omp teams distribute parallel for' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams
+ {
+#pragma omp target teams // expected-error {{region cannot be nested inside 'target teams' region}}
+ a++;
+ }
+#pragma omp target teams
+ {
+#pragma omp target teams distribute // expected-error {{region cannot be nested inside 'target teams' region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams
+ {
+#pragma omp target teams distribute parallel for // expected-error {{region cannot be nested inside 'target teams' region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+
+// TARGET TEAMS DISTRIBUTE DIRECTIVE
+#pragma omp target teams distribute // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp distribute parallel for simd // expected-error {{region cannot be closely nested inside 'target teams distribute' region; perhaps you forget to enclose 'omp distribute parallel for simd' directive into a teams region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp distribute // expected-error {{region cannot be closely nested inside 'target teams distribute' region; perhaps you forget to enclose 'omp distribute' directive into a teams region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp for // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp simd // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp for simd // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp sections // OK
+ {
+ bar();
+ }
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp section // expected-error {{'omp section' directive must be closely nested to a sections region, not a target teams distribute region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp single // OK
+ {
+ bar();
+ }
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp master // OK
+ {
+ bar();
+ }
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp critical // OK
+ {
+ bar();
+ }
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel // OK
+ {
+#pragma omp single
+ {
+ bar();
+ }
+ }
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel for // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel for simd // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel sections // OK
+ {
+ bar();
+ }
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp task // OK
+ {
+ bar();
+ }
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp taskyield // OK
+ bar();
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp barrier // OK
+ bar();
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp taskwait // OK
+ bar();
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp flush // OK
+ bar();
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp ordered // expected-error {{region cannot be closely nested inside 'target teams distribute' region; perhaps you forget to enclose 'omp ordered' directive into a for or a parallel for region with 'ordered' clause?}}
+ bar();
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp atomic // OK
+ ++a;
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target // expected-error {{region cannot be nested inside 'target teams distribute' region}}
+ ++a;
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target parallel // expected-error {{region cannot be nested inside 'target teams distribute' region}}
+ ++a;
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target parallel for // expected-error {{region cannot be nested inside 'target teams distribute' region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target enter data map(to: a) // expected-error {{region cannot be nested inside 'target teams distribute' region}}
+ ++a;
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target exit data map(from: a) // expected-error {{region cannot be nested inside 'target teams distribute' region}}
+ ++a;
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams // expected-error {{region cannot be closely nested inside 'target teams distribute' region; perhaps you forget to enclose 'omp teams' directive into a target region?}}
+ ++a;
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target update to(a) // expected-error {{region cannot be nested inside 'target teams distribute' region}}
+ ++a;
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp distribute simd // expected-error {{region cannot be closely nested inside 'target teams distribute' region; perhaps you forget to enclose 'omp distribute simd' directive into a teams region?}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target simd // expected-error {{region cannot be nested inside 'target teams distribute' region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute // expected-error {{region cannot be closely nested inside 'target teams distribute' region; perhaps you forget to enclose 'omp teams distribute' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute simd // expected-error {{region cannot be closely nested inside 'target teams distribute' region; perhaps you forget to enclose 'omp teams distribute simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for simd // expected-error {{region cannot be closely nested inside 'target teams distribute' region; perhaps you forget to enclose 'omp teams distribute parallel for simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for // expected-error {{region cannot be closely nested inside 'target teams distribute' region; perhaps you forget to enclose 'omp teams distribute parallel for' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams // expected-error {{region cannot be nested inside 'target teams distribute' region}}
+ ++a;
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute // expected-error {{region cannot be nested inside 'target teams distribute' region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute parallel for // expected-error {{region cannot be nested inside 'target teams distribute' region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+
+// TARGET TEAMS DISTRIBUTE PARALLEL FOR DIRECTIVE
+#pragma omp target teams distribute parallel for // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp distribute parallel for simd // expected-error {{region cannot be closely nested inside 'target teams distribute parallel for' region; perhaps you forget to enclose 'omp distribute parallel for simd' directive into a teams region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp distribute // expected-error {{region cannot be closely nested inside 'target teams distribute parallel for' region; perhaps you forget to enclose 'omp distribute' directive into a teams region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp for // expected-error {{region cannot be closely nested inside 'target teams distribute parallel for' region; perhaps you forget to enclose 'omp for' directive into a parallel region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp simd // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp for simd // expected-error {{region cannot be closely nested inside 'target teams distribute parallel for' region; perhaps you forget to enclose 'omp for simd' directive into a parallel region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp sections // expected-error {{region cannot be closely nested inside 'target teams distribute parallel for' region; perhaps you forget to enclose 'omp sections' directive into a parallel region?}}
+ {
+ bar();
+ }
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp section // expected-error {{'omp section' directive must be closely nested to a sections region, not a target teams distribute parallel for region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp single // expected-error {{region cannot be closely nested inside 'target teams distribute parallel for' region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp master // expected-error {{region cannot be closely nested inside 'target teams distribute parallel for' region}}
+ {
+ bar();
+ }
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp critical // OK
+ {
+ bar();
+ }
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel // OK
+ {
+#pragma omp single
+ {
+ bar();
+ }
+ }
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel for // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel for simd // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp parallel sections // OK
+ {
+ bar();
+ }
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp task // OK
+ {
+ bar();
+ }
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp taskyield // OK
+ bar();
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp barrier // expected-error {{region cannot be closely nested inside 'target teams distribute parallel for' region}}
+ bar();
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp taskwait // OK
+ bar();
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp flush // OK
+ bar();
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp ordered // expected-error {{region cannot be closely nested inside 'target teams distribute parallel for' region; perhaps you forget to enclose 'omp ordered' directive into a for or a parallel for region with 'ordered' clause?}}
+ bar();
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp atomic // OK
+ ++a;
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target // expected-error {{region cannot be nested inside 'target teams distribute parallel for' region}}
+ ++a;
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target parallel // expected-error {{region cannot be nested inside 'target teams distribute parallel for' region}}
+ ++a;
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target parallel for // expected-error {{region cannot be nested inside 'target teams distribute parallel for' region}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target enter data map(to: a) // expected-error {{region cannot be nested inside 'target teams distribute parallel for' region}}
+ ++a;
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target exit data map(from: a) // expected-error {{region cannot be nested inside 'target teams distribute parallel for' region}}
+ ++a;
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams // expected-error {{region cannot be closely nested inside 'target teams distribute parallel for' region; perhaps you forget to enclose 'omp teams' directive into a target region?}}
+ ++a;
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target update to(a) // expected-error {{region cannot be nested inside 'target teams distribute parallel for' region}}
+ ++a;
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp distribute simd // expected-error {{region cannot be closely nested inside 'target teams distribute parallel for' region; perhaps you forget to enclose 'omp distribute simd' directive into a teams region?}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target simd // expected-error {{region cannot be nested inside 'target teams distribute parallel for' region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute // expected-error {{region cannot be closely nested inside 'target teams distribute parallel for' region; perhaps you forget to enclose 'omp teams distribute' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute simd // expected-error {{region cannot be closely nested inside 'target teams distribute parallel for' region; perhaps you forget to enclose 'omp teams distribute simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for simd // expected-error {{region cannot be closely nested inside 'target teams distribute parallel for' region; perhaps you forget to enclose 'omp teams distribute parallel for simd' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp teams distribute parallel for // expected-error {{region cannot be closely nested inside 'target teams distribute parallel for' region; perhaps you forget to enclose 'omp teams distribute parallel for' directive into a target region?}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams // expected-error {{region cannot be nested inside 'target teams distribute parallel for' region}}
+ ++a;
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute // expected-error {{region cannot be nested inside 'target teams distribute parallel for' region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp target teams distribute parallel for // expected-error {{region cannot be nested inside 'target teams distribute parallel for' region}}
+ for (int i = 0; i < 10; ++i)
+ ++a;
+ }
+
+ return foo<int>();
}
+
diff --git a/test/OpenMP/nvptx_target_codegen.cpp b/test/OpenMP/nvptx_target_codegen.cpp
index c4df636367d3..287089d7c45e 100644
--- a/test/OpenMP/nvptx_target_codegen.cpp
+++ b/test/OpenMP/nvptx_target_codegen.cpp
@@ -3,6 +3,7 @@
// 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
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -25,7 +26,7 @@ int foo(int n) {
double cn[5][n];
TT<long long, char> d;
- // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+foo.+l86}}_worker()
+ // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+foo.+l87}}_worker()
// CHECK: br label {{%?}}[[AWAIT_WORK:.+]]
//
// CHECK: [[AWAIT_WORK]]
@@ -53,7 +54,7 @@ int foo(int n) {
// CHECK: [[EXIT]]
// CHECK: ret void
- // CHECK: define {{.*}}void [[T1:@__omp_offloading_.+foo.+l86]]()
+ // CHECK: define {{.*}}void [[T1:@__omp_offloading_.+foo.+l87]]()
// CHECK: [[NTID:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
// CHECK: [[WS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize()
// CHECK: [[A:%.+]] = sub i32 [[WS]], 1
@@ -68,7 +69,7 @@ int foo(int n) {
// CHECK: br i1 [[IS_WORKER]], label {{%?}}[[WORKER:.+]], label {{%?}}[[MASTER:.+]]
//
// CHECK: [[WORKER]]
- // CHECK: call void [[T1]]_worker()
+ // CHECK: {{call|invoke}} void [[T1]]_worker()
// CHECK: br label {{%?}}[[EXIT]]
//
// CHECK: [[MASTER]]
@@ -92,7 +93,7 @@ int foo(int n) {
{
}
- // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+foo.+l157}}_worker()
+ // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+foo.+l158}}_worker()
// CHECK: br label {{%?}}[[AWAIT_WORK:.+]]
//
// CHECK: [[AWAIT_WORK]]
@@ -120,7 +121,7 @@ int foo(int n) {
// CHECK: [[EXIT]]
// CHECK: ret void
- // CHECK: define {{.*}}void [[T3:@__omp_offloading_.+foo.+l157]](i[[SZ:32|64]] [[ARG1:%.+]])
+ // CHECK: define {{.*}}void [[T3:@__omp_offloading_.+foo.+l158]](i[[SZ:32|64]] [[ARG1:%[^)]+]])
// 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*
@@ -138,7 +139,7 @@ int foo(int n) {
// CHECK: br i1 [[IS_WORKER]], label {{%?}}[[WORKER:.+]], label {{%?}}[[MASTER:.+]]
//
// CHECK: [[WORKER]]
- // CHECK: call void [[T3]]_worker()
+ // CHECK: {{call|invoke}} void [[T3]]_worker()
// CHECK: br label {{%?}}[[EXIT]]
//
// CHECK: [[MASTER]]
@@ -159,7 +160,7 @@ int foo(int n) {
aa += 1;
}
- // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+foo.+l260}}_worker()
+ // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+foo.+l261}}_worker()
// CHECK: br label {{%?}}[[AWAIT_WORK:.+]]
//
// CHECK: [[AWAIT_WORK]]
@@ -187,7 +188,7 @@ int foo(int n) {
// CHECK: [[EXIT]]
// CHECK: ret void
- // CHECK: define {{.*}}void [[T4:@__omp_offloading_.+foo.+l260]](i[[SZ]]
+ // CHECK: define {{.*}}void [[T4:@__omp_offloading_.+foo.+l261]](i[[SZ]]
// Create local storage for each capture.
// CHECK: [[LOCAL_A:%.+]] = alloca i[[SZ]]
// CHECK: [[LOCAL_B:%.+]] = alloca [10 x float]*
@@ -232,7 +233,7 @@ int foo(int n) {
// CHECK: br i1 [[IS_WORKER]], label {{%?}}[[WORKER:.+]], label {{%?}}[[MASTER:.+]]
//
// CHECK: [[WORKER]]
- // CHECK: call void [[T4]]_worker()
+ // CHECK: {{call|invoke}} void [[T4]]_worker()
// CHECK: br label {{%?}}[[EXIT]]
//
// CHECK: [[MASTER]]
@@ -337,7 +338,7 @@ int bar(int n){
return a;
}
- // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+static.+l297}}_worker()
+ // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+static.+l298}}_worker()
// CHECK: br label {{%?}}[[AWAIT_WORK:.+]]
//
// CHECK: [[AWAIT_WORK]]
@@ -365,7 +366,7 @@ int bar(int n){
// CHECK: [[EXIT]]
// CHECK: ret void
- // CHECK: define {{.*}}void [[T5:@__omp_offloading_.+static.+l297]](i[[SZ]]
+ // CHECK: define {{.*}}void [[T5:@__omp_offloading_.+static.+l298]](i[[SZ]]
// Create local storage for each capture.
// CHECK: [[LOCAL_A:%.+]] = alloca i[[SZ]]
// CHECK: [[LOCAL_AA:%.+]] = alloca i[[SZ]]
@@ -395,7 +396,7 @@ int bar(int n){
// CHECK: br i1 [[IS_WORKER]], label {{%?}}[[WORKER:.+]], label {{%?}}[[MASTER:.+]]
//
// CHECK: [[WORKER]]
- // CHECK: call void [[T5]]_worker()
+ // CHECK: {{call|invoke}} void [[T5]]_worker()
// CHECK: br label {{%?}}[[EXIT]]
//
// CHECK: [[MASTER]]
@@ -419,7 +420,7 @@ int bar(int n){
- // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+S1.+l315}}_worker()
+ // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+S1.+l316}}_worker()
// CHECK: br label {{%?}}[[AWAIT_WORK:.+]]
//
// CHECK: [[AWAIT_WORK]]
@@ -447,7 +448,7 @@ int bar(int n){
// CHECK: [[EXIT]]
// CHECK: ret void
- // CHECK: define {{.*}}void [[T6:@__omp_offloading_.+S1.+l315]](
+ // CHECK: define {{.*}}void [[T6:@__omp_offloading_.+S1.+l316]](
// Create local storage for each capture.
// CHECK: [[LOCAL_THIS:%.+]] = alloca [[S1:%struct.*]]*
// CHECK: [[LOCAL_B:%.+]] = alloca i[[SZ]]
@@ -479,7 +480,7 @@ int bar(int n){
// CHECK: br i1 [[IS_WORKER]], label {{%?}}[[WORKER:.+]], label {{%?}}[[MASTER:.+]]
//
// CHECK: [[WORKER]]
- // CHECK: call void [[T6]]_worker()
+ // CHECK: {{call|invoke}} void [[T6]]_worker()
// CHECK: br label {{%?}}[[EXIT]]
//
// CHECK: [[MASTER]]
@@ -502,7 +503,7 @@ int bar(int n){
- // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l280}}_worker()
+ // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l281}}_worker()
// CHECK: br label {{%?}}[[AWAIT_WORK:.+]]
//
// CHECK: [[AWAIT_WORK]]
@@ -530,7 +531,7 @@ int bar(int n){
// CHECK: [[EXIT]]
// CHECK: ret void
- // CHECK: define {{.*}}void [[T7:@__omp_offloading_.+template.+l280]](i[[SZ]]
+ // CHECK: define {{.*}}void [[T7:@__omp_offloading_.+template.+l281]](i[[SZ]]
// Create local storage for each capture.
// CHECK: [[LOCAL_A:%.+]] = alloca i[[SZ]]
// CHECK: [[LOCAL_AA:%.+]] = alloca i[[SZ]]
@@ -557,7 +558,7 @@ int bar(int n){
// CHECK: br i1 [[IS_WORKER]], label {{%?}}[[WORKER:.+]], label {{%?}}[[MASTER:.+]]
//
// CHECK: [[WORKER]]
- // CHECK: call void [[T7]]_worker()
+ // CHECK: {{call|invoke}} void [[T7]]_worker()
// CHECK: br label {{%?}}[[EXIT]]
//
// CHECK: [[MASTER]]
diff --git a/test/OpenMP/ordered_ast_print.cpp b/test/OpenMP/ordered_ast_print.cpp
index 97fe7007e262..c7baa9ce0421 100644
--- a/test/OpenMP/ordered_ast_print.cpp
+++ b/test/OpenMP/ordered_ast_print.cpp
@@ -51,7 +51,7 @@ T tmain (T argc) {
return (0);
}
-// CHECK: static int a;
+// CHECK: static T a;
// CHECK-NEXT: #pragma omp for ordered
// CHECK-NEXT: for (int i = 0; i < argc; ++i)
// CHECK-NEXT: #pragma omp ordered
@@ -85,10 +85,10 @@ T tmain (T argc) {
// CHECK-NEXT: #pragma omp parallel for ordered(1)
// CHECK-NEXT: for (int i = 0; i < argc; ++i) {
// CHECK-NEXT: #pragma omp ordered depend(source)
-// CHECK-NEXT: #pragma omp ordered depend(sink : i + 3)
+// CHECK-NEXT: #pragma omp ordered depend(sink : i + N)
// CHECK-NEXT: a = 2;
// CHECK-NEXT: }
-// CHECK: static T a;
+// CHECK: static int a;
// CHECK-NEXT: #pragma omp for ordered
// CHECK-NEXT: for (int i = 0; i < argc; ++i)
// CHECK-NEXT: #pragma omp ordered
@@ -122,7 +122,7 @@ T tmain (T argc) {
// CHECK-NEXT: #pragma omp parallel for ordered(1)
// CHECK-NEXT: for (int i = 0; i < argc; ++i) {
// CHECK-NEXT: #pragma omp ordered depend(source)
-// CHECK-NEXT: #pragma omp ordered depend(sink : i + N)
+// CHECK-NEXT: #pragma omp ordered depend(sink : i + 3)
// CHECK-NEXT: a = 2;
// CHECK-NEXT: }
diff --git a/test/OpenMP/ordered_codegen.cpp b/test/OpenMP/ordered_codegen.cpp
index daa6211b4c03..bd7c07051b04 100644
--- a/test/OpenMP/ordered_codegen.cpp
+++ b/test/OpenMP/ordered_codegen.cpp
@@ -1,7 +1,6 @@
// 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
-// REQUIRES: x86-registered-target
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/ordered_doacross_codegen.cpp b/test/OpenMP/ordered_doacross_codegen.cpp
index d1fe99d4b826..28b02c35358b 100644
--- a/test/OpenMP/ordered_doacross_codegen.cpp
+++ b/test/OpenMP/ordered_doacross_codegen.cpp
@@ -1,7 +1,6 @@
// 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
-// REQUIRES: x86-registered-target
// expected-no-diagnostics
#ifndef HEADER
diff --git a/test/OpenMP/parallel_ast_print.cpp b/test/OpenMP/parallel_ast_print.cpp
index 8a1533959e36..1e24c6e059bd 100644
--- a/test/OpenMP/parallel_ast_print.cpp
+++ b/test/OpenMP/parallel_ast_print.cpp
@@ -1,6 +1,6 @@
-// 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 -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
// expected-no-diagnostics
#ifndef HEADER
@@ -58,10 +58,6 @@ public:
}
};
-// CHECK: #pragma omp parallel private(this->a) private(this->a) private(this->S1::a)
-// CHECK: #pragma omp parallel firstprivate(this->a) firstprivate(this->a) firstprivate(this->S1::a)
-// CHECK: #pragma omp parallel shared(this->a) shared(this->a) shared(this->S1::a)
-// CHECK: #pragma omp parallel reduction(+: this->a) reduction(*: this->b[:])
// CHECK: #pragma omp parallel private(this->a) private(this->a) private(T::a)
// CHECK: #pragma omp parallel firstprivate(this->a) firstprivate(this->a) firstprivate(T::a)
// CHECK: #pragma omp parallel shared(this->a) shared(this->a) shared(T::a)
@@ -70,6 +66,10 @@ public:
// CHECK: #pragma omp parallel firstprivate(this->a) firstprivate(this->a)
// CHECK: #pragma omp parallel shared(this->a) shared(this->a)
// CHECK: #pragma omp parallel reduction(&&: this->a) reduction(^: this->b[s.a.a])
+// CHECK: #pragma omp parallel private(this->a) private(this->a) private(this->S1::a)
+// CHECK: #pragma omp parallel firstprivate(this->a) firstprivate(this->a) firstprivate(this->S1::a)
+// CHECK: #pragma omp parallel shared(this->a) shared(this->a) shared(this->S1::a)
+// CHECK: #pragma omp parallel reduction(+: this->a) reduction(*: this->b[:])
class S8 : public S7<S1> {
S8() {}
@@ -122,18 +122,18 @@ struct S {
#pragma omp threadprivate(TS)
};
-// CHECK: template <class T = int> struct S {
+// CHECK: template <class T> struct S {
+// CHECK: static T TS;
+// CHECK-NEXT: #pragma omp threadprivate(S::TS)
+// CHECK: };
+// CHECK: template<> struct S<int> {
// CHECK: static int TS;
// CHECK-NEXT: #pragma omp threadprivate(S<int>::TS)
// CHECK-NEXT: }
-// CHECK: template <class T = long> struct S {
+// CHECK: template<> struct S<long> {
// CHECK: static long TS;
// CHECK-NEXT: #pragma omp threadprivate(S<long>::TS)
// CHECK-NEXT: }
-// CHECK: template <class T> struct S {
-// CHECK: static T TS;
-// CHECK-NEXT: #pragma omp threadprivate(S::TS)
-// CHECK: };
template <typename T, int C>
T tmain(T argc, T *argv) {
@@ -150,7 +150,18 @@ T tmain(T argc, T *argv) {
return 0;
}
-// CHECK: template <typename T = int, int C = 5> int tmain(int argc, int *argv) {
+// CHECK: template <typename T, int C> 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: T arr[C][10], arr1[C];
+// 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) proc_bind(master) reduction(+: c,arr1[argc]) reduction(max: e,arr[:C][0:10])
+// CHECK-NEXT: foo()
+// CHECK-NEXT: #pragma omp parallel if(C) num_threads(s) proc_bind(close) reduction(^: e,f,arr[0:C][:argc]) reduction(&&: g)
+// CHECK-NEXT: foo()
+// CHECK: template<> int tmain<int, 5>(int argc, int *argv) {
// CHECK-NEXT: int b = argc, c, d, e, f, g;
// CHECK-NEXT: static int a;
// CHECK-NEXT: S<int> s;
@@ -161,7 +172,7 @@ T tmain(T argc, T *argv) {
// CHECK-NEXT: foo()
// CHECK-NEXT: #pragma omp parallel if(5) num_threads(s) proc_bind(close) reduction(^: e,f,arr[0:5][:argc]) reduction(&&: g)
// CHECK-NEXT: foo()
-// CHECK: template <typename T = long, int C = 1> long tmain(long argc, long *argv) {
+// CHECK: template<> long tmain<long, 1>(long argc, long *argv) {
// CHECK-NEXT: long b = argc, c, d, e, f, g;
// CHECK-NEXT: static long a;
// CHECK-NEXT: S<long> s;
@@ -172,17 +183,6 @@ T tmain(T argc, T *argv) {
// CHECK-NEXT: foo()
// CHECK-NEXT: #pragma omp parallel if(1) num_threads(s) proc_bind(close) reduction(^: e,f,arr[0:1][:argc]) reduction(&&: g)
// CHECK-NEXT: foo()
-// CHECK: template <typename T, int C> 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: T arr[C][10], arr1[C];
-// 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) proc_bind(master) reduction(+: c,arr1[argc]) reduction(max: e,arr[:C][0:10])
-// CHECK-NEXT: foo()
-// CHECK-NEXT: #pragma omp parallel if(C) num_threads(s) proc_bind(close) reduction(^: e,f,arr[0:C][:argc]) reduction(&&: g)
-// CHECK-NEXT: foo()
enum Enum { };
diff --git a/test/OpenMP/parallel_codegen.cpp b/test/OpenMP/parallel_codegen.cpp
index 41a050100bd0..c43533c6c194 100644
--- a/test/OpenMP/parallel_codegen.cpp
+++ b/test/OpenMP/parallel_codegen.cpp
@@ -2,7 +2,6 @@
// 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
// expected-no-diagnostics
-// REQUIRES: x86-registered-target
#ifndef HEADER
#define HEADER
// CHECK-DAG: %ident_t = type { i32, i32, i32, i32, i8* }
diff --git a/test/OpenMP/parallel_for_ast_print.cpp b/test/OpenMP/parallel_for_ast_print.cpp
index 2476ee87605a..3c36bd80523c 100644
--- a/test/OpenMP/parallel_for_ast_print.cpp
+++ b/test/OpenMP/parallel_for_ast_print.cpp
@@ -1,6 +1,6 @@
-// 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 -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
// expected-no-diagnostics
#ifndef HEADER
@@ -35,9 +35,9 @@ public:
}
};
-// CHECK: #pragma omp parallel for private(this->a) private(this->a) private(this->S::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)
class S8 : public S7<S> {
S8() {}
diff --git a/test/OpenMP/parallel_for_codegen.cpp b/test/OpenMP/parallel_for_codegen.cpp
index 036fa37cf91b..1324ee67b615 100644
--- a/test/OpenMP/parallel_for_codegen.cpp
+++ b/test/OpenMP/parallel_for_codegen.cpp
@@ -3,7 +3,6 @@
// 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
-// REQUIRES: x86-registered-target
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/parallel_for_if_messages.cpp b/test/OpenMP/parallel_for_if_messages.cpp
index 2b7a5f7e2b3e..b5a7fdcd1ab5 100644
--- a/test/OpenMP/parallel_for_if_messages.cpp
+++ b/test/OpenMP/parallel_for_if_messages.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ferror-limit 100 %s
void foo() {
}
@@ -34,7 +34,7 @@ int tmain(T argc, S **argv) {
for (i = 0; i < argc; ++i) foo();
#pragma omp parallel for if(argc)
for (i = 0; i < argc; ++i) foo();
- #pragma omp parallel for if(parallel // expected-warning {{missing ':' after directive name modifier - ignoring}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ #pragma omp parallel for if(parallel // expected-error {{use of undeclared identifier 'parallel'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
for (i = 0; i < argc; ++i) foo();
#pragma omp parallel for if(parallel : // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
for (i = 0; i < argc; ++i) foo();
@@ -78,7 +78,7 @@ int main(int argc, char **argv) {
for (i = 0; i < argc; ++i) foo();
#pragma omp parallel for if(if(tmain(argc, argv) // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
for (i = 0; i < argc; ++i) foo();
- #pragma omp parallel for if(parallel // expected-warning {{missing ':' after directive name modifier - ignoring}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ #pragma omp parallel for if(parallel // expected-error {{use of undeclared identifier 'parallel'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
for (i = 0; i < argc; ++i) foo();
#pragma omp parallel for if(parallel : // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
for (i = 0; i < argc; ++i) foo();
diff --git a/test/OpenMP/parallel_for_linear_codegen.cpp b/test/OpenMP/parallel_for_linear_codegen.cpp
index 940d6032a14a..d0968d7cd146 100644
--- a/test/OpenMP/parallel_for_linear_codegen.cpp
+++ b/test/OpenMP/parallel_for_linear_codegen.cpp
@@ -4,7 +4,6 @@
// 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
// expected-no-diagnostics
-// REQUIRES: x86-registered-target
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/parallel_for_simd_aligned_messages.cpp b/test/OpenMP/parallel_for_simd_aligned_messages.cpp
index 2ccdf0697624..fc0f88cc38f8 100644
--- a/test/OpenMP/parallel_for_simd_aligned_messages.cpp
+++ b/test/OpenMP/parallel_for_simd_aligned_messages.cpp
@@ -121,7 +121,8 @@ template<class I, class C> int foomain(I argc, C **argv) {
for (I k = 0; k < argc; ++k) ++k;
#pragma omp parallel for simd aligned (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
for (I k = 0; k < argc; ++k) ++k;
- #pragma omp parallel for simd aligned (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+// FIXME: Should argc really be a pointer?
+ #pragma omp parallel for simd aligned (*argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
for (I k = 0; k < argc; ++k) ++k;
#pragma omp parallel for simd aligned (argc : 5) // expected-warning {{aligned clause will be ignored because the requested alignment is not a power of 2}}
for (I k = 0; k < argc; ++k) ++k;
diff --git a/test/OpenMP/parallel_for_simd_ast_print.cpp b/test/OpenMP/parallel_for_simd_ast_print.cpp
index cdd1b73b5903..2668961892f3 100644
--- a/test/OpenMP/parallel_for_simd_ast_print.cpp
+++ b/test/OpenMP/parallel_for_simd_ast_print.cpp
@@ -1,6 +1,6 @@
-// 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 -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
// expected-no-diagnostics
#ifndef HEADER
@@ -35,9 +35,9 @@ public:
}
};
-// CHECK: #pragma omp parallel for simd private(this->a) private(this->a) private(this->S1::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)
class S8 : public S7<S1> {
S8() {}
@@ -126,7 +126,7 @@ template<int LEN> struct S2 {
};
// S2<4>::func is called below in main.
-// CHECK: template <int LEN = 4> struct S2 {
+// CHECK: template<> struct S2<4> {
// CHECK-NEXT: static void func(int n, float *a, float *b, float *c) {
// CHECK-NEXT: int k1 = 0, k2 = 0;
// CHECK-NEXT: #pragma omp parallel for simd safelen(4) linear(k1,k2: 4) aligned(a: 4) simdlen(4)
diff --git a/test/OpenMP/parallel_for_simd_codegen.cpp b/test/OpenMP/parallel_for_simd_codegen.cpp
index 9a6ad2f06f61..06d96353ee9b 100644
--- a/test/OpenMP/parallel_for_simd_codegen.cpp
+++ b/test/OpenMP/parallel_for_simd_codegen.cpp
@@ -2,7 +2,6 @@
// 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
-// REQUIRES: x86-registered-target
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -30,12 +29,12 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK: [[UB_VAL:%.+]] = load i32, i32* [[UB]],
// CHECK: [[CMP:%.+]] = icmp sgt i32 [[UB_VAL]], 5
// CHECK: br i1 [[CMP]], label %[[TRUE:.+]], label %[[FALSE:[^,]+]]
-// CHECK: [[TRUE]]
+// CHECK: [[TRUE]]:
// CHECK: br label %[[SWITCH:[^,]+]]
-// CHECK: [[FALSE]]
+// CHECK: [[FALSE]]:
// CHECK: [[UB_VAL:%.+]] = load i32, i32* [[UB]],
// CHECK: br label %[[SWITCH]]
-// CHECK: [[SWITCH]]
+// CHECK: [[SWITCH]]:
// CHECK: [[UP:%.+]] = phi i32 [ 5, %[[TRUE]] ], [ [[UB_VAL]], %[[FALSE]] ]
// CHECK: store i32 [[UP]], i32* [[UB]],
// CHECK: [[LB_VAL:%.+]] = load i32, i32* [[LB]],
@@ -46,7 +45,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: [[CMP:%.+]] = icmp sle i32 [[IV]], [[UB_VAL]]
// CHECK-NEXT: br i1 [[CMP]], label %[[SIMPLE_LOOP1_BODY:.+]], label %[[SIMPLE_LOOP1_END:[^,]+]]
for (int i = 3; i < 32; i += 5) {
-// CHECK: [[SIMPLE_LOOP1_BODY]]
+// CHECK: [[SIMPLE_LOOP1_BODY]]:
// Start of body: calculate i from IV:
// CHECK: [[IV1_1:%.+]] = load i32, i32* [[OMP_IV]]
// CHECK: [[CALC_I_1:%.+]] = mul nsw i32 [[IV1_1]], 5
@@ -61,7 +60,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: store i32 [[ADD1_2]], i32* [[OMP_IV]]
// br label %{{.+}}, !llvm.loop !{{.+}}
}
-// CHECK: [[SIMPLE_LOOP1_END]]
+// CHECK: [[SIMPLE_LOOP1_END]]:
// CHECK: call void @__kmpc_for_static_fini(%ident_t* {{.+}}, i32 %{{.+}})
long long k = get_val();
@@ -74,7 +73,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK: [[NEXT:%.+]] = call i32 @__kmpc_dispatch_next_4(%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]]
+// CHECK: [[CONT]]:
// CHECK: [[LB_VAL:%.+]] = load i32, i32* [[LB]],
// CHECK: store i32 [[LB_VAL]], i32* [[OMP_IV2:%[^,]+]],
@@ -83,7 +82,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: [[CMP2:%.+]] = icmp sle i32 [[IV2]], [[UB_VAL]]
// CHECK-NEXT: br i1 [[CMP2]], label %[[SIMPLE_LOOP2_BODY:.+]], label %[[SIMPLE_LOOP2_END:[^,]+]]
for (int i = 10; i > 1; i--) {
-// CHECK: [[SIMPLE_LOOP2_BODY]]
+// CHECK: [[SIMPLE_LOOP2_BODY]]:
// Start of body: calculate i from IV:
// CHECK: [[IV2_0:%.+]] = load i32, i32* [[OMP_IV2]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP2_ID]]
// FIXME: It is interesting, why the following "mul 1" was not constant folded?
@@ -105,7 +104,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: store i32 [[ADD2_2]], i32* [[OMP_IV2]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP2_ID]]
// br label {{.+}}, !llvm.loop ![[SIMPLE_LOOP2_ID]]
}
-// CHECK: [[SIMPLE_LOOP2_END]]
+// CHECK: [[SIMPLE_LOOP2_END]]:
//
// Update linear vars after loop, as the loop was operating on a private version.
// CHECK: [[LIN0_2:%.+]] = load i64, i64* [[LIN0]]
@@ -130,12 +129,12 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK: [[UB_VAL:%.+]] = load i64, i64* [[UB]],
// CHECK: [[CMP:%.+]] = icmp ugt i64 [[UB_VAL]], 3
// CHECK: br i1 [[CMP]], label %[[TRUE:.+]], label %[[FALSE:[^,]+]]
-// CHECK: [[TRUE]]
+// CHECK: [[TRUE]]:
// CHECK: br label %[[SWITCH:[^,]+]]
-// CHECK: [[FALSE]]
+// CHECK: [[FALSE]]:
// CHECK: [[UB_VAL:%.+]] = load i64, i64* [[UB]],
// CHECK: br label %[[SWITCH]]
-// CHECK: [[SWITCH]]
+// CHECK: [[SWITCH]]:
// CHECK: [[UP:%.+]] = phi i64 [ 3, %[[TRUE]] ], [ [[UB_VAL]], %[[FALSE]] ]
// CHECK: store i64 [[UP]], i64* [[UB]],
// CHECK: [[LB_VAL:%.+]] = load i64, i64* [[LB]],
@@ -146,7 +145,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: [[CMP3:%.+]] = icmp ule i64 [[IV3]], [[UB_VAL]]
// CHECK-NEXT: br i1 [[CMP3]], label %[[SIMPLE_LOOP3_BODY:.+]], label %[[SIMPLE_LOOP3_END:[^,]+]]
for (unsigned long long it = 2000; it >= 600; it-=400) {
-// CHECK: [[SIMPLE_LOOP3_BODY]]
+// CHECK: [[SIMPLE_LOOP3_BODY]]:
// Start of body: calculate it from IV:
// CHECK: [[IV3_0:%.+]] = load i64, i64* [[OMP_IV3]]
// CHECK-NEXT: [[LC_IT_1:%.+]] = mul i64 [[IV3_0]], 400
@@ -172,7 +171,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: [[ADD3_2:%.+]] = add i64 [[IV3_2]], 1
// CHECK-NEXT: store i64 [[ADD3_2]], i64* [[OMP_IV3]]
}
-// CHECK: [[SIMPLE_LOOP3_END]]
+// CHECK: [[SIMPLE_LOOP3_END]]:
// CHECK: call void @__kmpc_for_static_fini(%ident_t* {{.+}}, i32 %{{.+}})
//
// Linear start and step are used to calculate final value of the linear variables.
@@ -187,12 +186,12 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK: [[UB_VAL:%.+]] = load i32, i32* [[UB]],
// CHECK: [[CMP:%.+]] = icmp sgt i32 [[UB_VAL]], 3
// CHECK: br i1 [[CMP]], label %[[TRUE:.+]], label %[[FALSE:[^,]+]]
-// CHECK: [[TRUE]]
+// CHECK: [[TRUE]]:
// CHECK: br label %[[SWITCH:[^,]+]]
-// CHECK: [[FALSE]]
+// CHECK: [[FALSE]]:
// CHECK: [[UB_VAL:%.+]] = load i32, i32* [[UB]],
// CHECK: br label %[[SWITCH]]
-// CHECK: [[SWITCH]]
+// CHECK: [[SWITCH]]:
// CHECK: [[UP:%.+]] = phi i32 [ 3, %[[TRUE]] ], [ [[UB_VAL]], %[[FALSE]] ]
// CHECK: store i32 [[UP]], i32* [[UB]],
// CHECK: [[LB_VAL:%.+]] = load i32, i32* [[LB]],
@@ -203,7 +202,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: [[CMP4:%.+]] = icmp sle i32 [[IV4]], [[UB_VAL]]
// CHECK-NEXT: br i1 [[CMP4]], label %[[SIMPLE_LOOP4_BODY:.+]], label %[[SIMPLE_LOOP4_END:[^,]+]]
for (short it = 6; it <= 20; it-=-4) {
-// CHECK: [[SIMPLE_LOOP4_BODY]]
+// CHECK: [[SIMPLE_LOOP4_BODY]]:
// Start of body: calculate it from IV:
// CHECK: [[IV4_0:%.+]] = load i32, i32* [[OMP_IV4]]
// CHECK-NEXT: [[LC_IT_1:%.+]] = mul nsw i32 [[IV4_0]], 4
@@ -215,7 +214,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: [[ADD4_2:%.+]] = add nsw i32 [[IV4_2]], 1
// CHECK-NEXT: store i32 [[ADD4_2]], i32* [[OMP_IV4]]
}
-// CHECK: [[SIMPLE_LOOP4_END]]
+// CHECK: [[SIMPLE_LOOP4_END]]:
// CHECK: call void @__kmpc_for_static_fini(%ident_t* {{.+}}, i32 %{{.+}})
#pragma omp parallel for simd
@@ -223,12 +222,12 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK: [[UB_VAL:%.+]] = load i32, i32* [[UB]],
// CHECK: [[CMP:%.+]] = icmp sgt i32 [[UB_VAL]], 25
// CHECK: br i1 [[CMP]], label %[[TRUE:.+]], label %[[FALSE:[^,]+]]
-// CHECK: [[TRUE]]
+// CHECK: [[TRUE]]:
// CHECK: br label %[[SWITCH:[^,]+]]
-// CHECK: [[FALSE]]
+// CHECK: [[FALSE]]:
// CHECK: [[UB_VAL:%.+]] = load i32, i32* [[UB]],
// CHECK: br label %[[SWITCH]]
-// CHECK: [[SWITCH]]
+// CHECK: [[SWITCH]]:
// CHECK: [[UP:%.+]] = phi i32 [ 25, %[[TRUE]] ], [ [[UB_VAL]], %[[FALSE]] ]
// CHECK: store i32 [[UP]], i32* [[UB]],
// CHECK: [[LB_VAL:%.+]] = load i32, i32* [[LB]],
@@ -239,7 +238,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: [[CMP5:%.+]] = icmp sle i32 [[IV5]], [[UB_VAL]]
// CHECK-NEXT: br i1 [[CMP5]], label %[[SIMPLE_LOOP5_BODY:.+]], label %[[SIMPLE_LOOP5_END:[^,]+]]
for (unsigned char it = 'z'; it >= 'a'; it+=-1) {
-// CHECK: [[SIMPLE_LOOP5_BODY]]
+// CHECK: [[SIMPLE_LOOP5_BODY]]:
// Start of body: calculate it from IV:
// CHECK: [[IV5_0:%.+]] = load i32, i32* [[OMP_IV5]]
// CHECK-NEXT: [[IV5_1:%.+]] = mul nsw i32 [[IV5_0]], 1
@@ -251,7 +250,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: [[ADD5_2:%.+]] = add nsw i32 [[IV5_2]], 1
// CHECK-NEXT: store i32 [[ADD5_2]], i32* [[OMP_IV5]]
}
-// CHECK: [[SIMPLE_LOOP5_END]]
+// CHECK: [[SIMPLE_LOOP5_END]]:
// CHECK: call void @__kmpc_for_static_fini(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK-NOT: mul i32 %{{.+}}, 10
@@ -267,25 +266,25 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK: [[UB_VAL:%.+]] = load i64, i64* [[UB]],
// CHECK: [[CMP:%.+]] = icmp sgt i64 [[UB_VAL]], 6
// CHECK: br i1 [[CMP]], label %[[TRUE:.+]], label %[[FALSE:[^,]+]]
-// CHECK: [[TRUE]]
+// CHECK: [[TRUE]]:
// CHECK: br label %[[SWITCH:[^,]+]]
-// CHECK: [[FALSE]]
+// CHECK: [[FALSE]]:
// CHECK: [[UB_VAL:%.+]] = load i64, i64* [[UB]],
// CHECK: br label %[[SWITCH]]
-// CHECK: [[SWITCH]]
+// CHECK: [[SWITCH]]:
// CHECK: [[UP:%.+]] = phi i64 [ 6, %[[TRUE]] ], [ [[UB_VAL]], %[[FALSE]] ]
// CHECK: store i64 [[UP]], i64* [[UB]],
// CHECK: [[LB_VAL:%.+]] = load i64, i64* [[LB]],
// CHECK: store i64 [[LB_VAL]], i64* [[OMP_IV7:%[^,]+]],
// CHECK: br label %[[SIMD_LOOP7_COND:[^,]+]]
-// CHECK: [[SIMD_LOOP7_COND]]
+// CHECK: [[SIMD_LOOP7_COND]]:
// CHECK-NEXT: [[IV7:%.+]] = load i64, i64* [[OMP_IV7]]
// CHECK-NEXT: [[UB_VAL:%.+]] = load i64, i64* [[UB]]
// CHECK-NEXT: [[CMP7:%.+]] = icmp sle i64 [[IV7]], [[UB_VAL]]
// CHECK-NEXT: br i1 [[CMP7]], label %[[SIMPLE_LOOP7_BODY:.+]], label %[[SIMPLE_LOOP7_END:[^,]+]]
for (long long i = -10; i < 10; i += 3) {
-// CHECK: [[SIMPLE_LOOP7_BODY]]
+// CHECK: [[SIMPLE_LOOP7_BODY]]:
// Start of body: calculate i from IV:
// CHECK: [[IV7_0:%.+]] = load i64, i64* [[OMP_IV7]]
// CHECK-NEXT: [[LC_IT_1:%.+]] = mul nsw i64 [[IV7_0]], 3
@@ -299,7 +298,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: [[ADD7_2:%.+]] = add nsw i64 [[IV7_2]], 1
// CHECK-NEXT: store i64 [[ADD7_2]], i64* [[OMP_IV7]]
}
-// CHECK: [[SIMPLE_LOOP7_END]]
+// CHECK: [[SIMPLE_LOOP7_END]]:
// CHECK: call void @__kmpc_for_static_fini(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK: load i32, i32*
// CHECK: icmp ne i32 %{{.+}}, 0
@@ -317,25 +316,25 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK: [[UB_VAL:%.+]] = load i64, i64* [[UB]],
// CHECK: [[CMP:%.+]] = icmp sgt i64 [[UB_VAL]], 6
// CHECK: br i1 [[CMP]], label %[[TRUE:.+]], label %[[FALSE:[^,]+]]
-// CHECK: [[TRUE]]
+// CHECK: [[TRUE]]:
// CHECK: br label %[[SWITCH:[^,]+]]
-// CHECK: [[FALSE]]
+// CHECK: [[FALSE]]:
// CHECK: [[UB_VAL:%.+]] = load i64, i64* [[UB]],
// CHECK: br label %[[SWITCH]]
-// CHECK: [[SWITCH]]
+// CHECK: [[SWITCH]]:
// CHECK: [[UP:%.+]] = phi i64 [ 6, %[[TRUE]] ], [ [[UB_VAL]], %[[FALSE]] ]
// CHECK: store i64 [[UP]], i64* [[UB]],
// CHECK: [[LB_VAL:%.+]] = load i64, i64* [[LB]],
// CHECK: store i64 [[LB_VAL]], i64* [[OMP_IV8:%[^,]+]],
// CHECK: br label %[[SIMD_LOOP8_COND:[^,]+]]
-// CHECK: [[SIMD_LOOP8_COND]]
+// CHECK: [[SIMD_LOOP8_COND]]:
// CHECK-NEXT: [[IV8:%.+]] = load i64, i64* [[OMP_IV8]]
// CHECK-NEXT: [[UB_VAL:%.+]] = load i64, i64* [[UB]]
// CHECK-NEXT: [[CMP8:%.+]] = icmp sle i64 [[IV8]], [[UB_VAL]]
// CHECK-NEXT: br i1 [[CMP8]], label %[[SIMPLE_LOOP8_BODY:.+]], label %[[SIMPLE_LOOP8_END:[^,]+]]
for (long long i = -10; i < 10; i += 3) {
-// CHECK: [[SIMPLE_LOOP8_BODY]]
+// CHECK: [[SIMPLE_LOOP8_BODY]]:
// Start of body: calculate i from IV:
// CHECK: [[IV8_0:%.+]] = load i64, i64* [[OMP_IV8]]
// CHECK-NEXT: [[LC_IT_1:%.+]] = mul nsw i64 [[IV8_0]], 3
@@ -348,7 +347,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: [[ADD8_2:%.+]] = add nsw i64 [[IV8_2]], 1
// CHECK-NEXT: store i64 [[ADD8_2]], i64* [[OMP_IV8]]
}
-// CHECK: [[SIMPLE_LOOP8_END]]
+// CHECK: [[SIMPLE_LOOP8_END]]:
// CHECK: call void @__kmpc_for_static_fini(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK: call i32 @__kmpc_reduce_nowait(
// CHECK: [[R_PRIV_VAL:%.+]] = load i32, i32* [[R_PRIV]],
@@ -426,13 +425,13 @@ void iter_simple(IterDouble ia, IterDouble ib, IterDouble ic) {
// CHECK-DAG: [[OMP_LAST_IT_VAL:%.+]] = load i32, i32* [[OMP_LAST_IT]],
// CHECK: [[CMP:%.+]] = icmp sgt i32 [[UB_VAL]], [[OMP_LAST_IT_VAL]]
// CHECK: br i1 [[CMP]], label %[[TRUE:.+]], label %[[FALSE:[^,]+]]
-// CHECK: [[TRUE]]
+// CHECK: [[TRUE]]:
// CHECK: [[OMP_LAST_IT_VAL:%.+]] = load i32, i32* [[OMP_LAST_IT]],
// CHECK: br label %[[SWITCH:[^,]+]]
-// CHECK: [[FALSE]]
+// CHECK: [[FALSE]]:
// CHECK: [[UB_VAL:%.+]] = load i32, i32* [[UB]],
// CHECK: br label %[[SWITCH]]
-// CHECK: [[SWITCH]]
+// CHECK: [[SWITCH]]:
// CHECK: [[UP:%.+]] = phi i32 [ [[OMP_LAST_IT_VAL]], %[[TRUE]] ], [ [[UB_VAL]], %[[FALSE]] ]
// CHECK: store i32 [[UP]], i32* [[UB]],
// CHECK: [[LB_VAL:%.+]] = load i32, i32* [[LB]],
@@ -443,7 +442,7 @@ void iter_simple(IterDouble ia, IterDouble ib, IterDouble ic) {
// CHECK-NEXT: [[CMP:%.+]] = icmp sle i32 [[IV]], [[UB_VAL]]
// CHECK-NEXT: br i1 [[CMP]], label %[[IT_BODY:[^,]+]], label %[[IT_END:[^,]+]]
for (IterDouble i = ia; i < ib; ++i) {
-// CHECK: [[IT_BODY]]
+// CHECK: [[IT_BODY]]:
// Start of body: calculate i from index:
// CHECK: [[IV1:%.+]] = load i32, i32* [[IT_OMP_IV]]
// Call of operator+ (i, IV).
@@ -461,7 +460,7 @@ void iter_simple(IterDouble ia, IterDouble ib, IterDouble ic) {
// CHECK-NEXT: store i32 [[ADD2]], i32* [[IT_OMP_IV]]
// br label %{{.*}}, !llvm.loop ![[ITER_LOOP_ID]]
}
-// CHECK: [[IT_END]]
+// CHECK: [[IT_END]]:
// CHECK: call void @__kmpc_for_static_fini(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK: ret void
}
@@ -477,12 +476,12 @@ void collapsed(float *a, float *b, float *c, float *d) {
// CHECK: [[UB_VAL:%.+]] = load i32, i32* [[UB]],
// CHECK: [[CMP:%.+]] = icmp ugt i32 [[UB_VAL]], 119
// CHECK: br i1 [[CMP]], label %[[TRUE:.+]], label %[[FALSE:[^,]+]]
-// CHECK: [[TRUE]]
+// CHECK: [[TRUE]]:
// CHECK: br label %[[SWITCH:[^,]+]]
-// CHECK: [[FALSE]]
+// CHECK: [[FALSE]]:
// CHECK: [[UB_VAL:%.+]] = load i32, i32* [[UB]],
// CHECK: br label %[[SWITCH]]
-// CHECK: [[SWITCH]]
+// CHECK: [[SWITCH]]:
// CHECK: [[UP:%.+]] = phi i32 [ 119, %[[TRUE]] ], [ [[UB_VAL]], %[[FALSE]] ]
// CHECK: store i32 [[UP]], i32* [[UB]],
// CHECK: [[LB_VAL:%.+]] = load i32, i32* [[LB]],
@@ -499,7 +498,7 @@ void collapsed(float *a, float *b, float *c, float *d) {
for (int k = 3; k <= 6; k++) // 4 iterations
for (l = 4; l < 9; ++l) // 5 iterations
{
-// CHECK: [[COLL1_BODY]]
+// CHECK: [[COLL1_BODY]]:
// Start of body: calculate i from index:
// CHECK: [[IV1:%.+]] = load i32, i32* [[OMP_IV]]
// Calculation of the loop counters values.
@@ -534,7 +533,7 @@ void collapsed(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: [[ADD2:%.+]] = add i32 [[IV2]], 1
// CHECK-NEXT: store i32 [[ADD2]], i32* [[OMP_IV]]
// br label %{{[^,]+}}, !llvm.loop ![[COLL1_LOOP_ID]]
-// CHECK: [[COLL1_END]]
+// CHECK: [[COLL1_END]]:
}
// i,j,l are updated; k is not updated.
// CHECK: call void @__kmpc_for_static_fini(%ident_t* {{.+}}, i32 %{{.+}})
@@ -563,13 +562,13 @@ void widened(float *a, float *b, float *c, float *d) {
// CHECK-DAG: [[OMP_LAST_IT_VAL:%.+]] = load i64, i64* [[OMP_LAST_IT]],
// CHECK: [[CMP:%.+]] = icmp sgt i64 [[UB_VAL]], [[OMP_LAST_IT_VAL]]
// CHECK: br i1 [[CMP]], label %[[TRUE:.+]], label %[[FALSE:[^,]+]]
-// CHECK: [[TRUE]]
+// CHECK: [[TRUE]]:
// CHECK: [[OMP_LAST_IT_VAL:%.+]] = load i64, i64* [[OMP_LAST_IT]],
// CHECK: br label %[[SWITCH:[^,]+]]
-// CHECK: [[FALSE]]
+// CHECK: [[FALSE]]:
// CHECK: [[UB_VAL:%.+]] = load i64, i64* [[UB]],
// CHECK: br label %[[SWITCH]]
-// CHECK: [[SWITCH]]
+// CHECK: [[SWITCH]]:
// CHECK: [[UP:%.+]] = phi i64 [ [[OMP_LAST_IT_VAL]], %[[TRUE]] ], [ [[UB_VAL]], %[[FALSE]] ]
// CHECK: store i64 [[UP]], i64* [[UB]],
// CHECK: [[LB_VAL:%.+]] = load i64, i64* [[LB]],
@@ -584,7 +583,7 @@ void widened(float *a, float *b, float *c, float *d) {
for (i = 1; i < 3; i++) // 2 iterations
for (j = 0; j < foo(); j++) // foo() iterations
{
-// CHECK: [[WIDE1_BODY]]
+// CHECK: [[WIDE1_BODY]]:
// Start of body: calculate i from index:
// CHECK: [[IV1:%.+]] = load i64, i64* [[OMP_IV]]
// Calculation of the loop counters values...
@@ -608,7 +607,7 @@ void widened(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: store i64 [[ADD2]], i64* [[OMP_IV]]
//
// br label %{{[^,]+}}, !llvm.loop ![[WIDE1_LOOP_ID]]
-// CHECK: [[WIDE1_END]]
+// CHECK: [[WIDE1_END]]:
}
// i,j are updated.
// CHECK: store i32 3, i32* [[I:%[^,]+]]
@@ -624,12 +623,12 @@ void widened(float *a, float *b, float *c, float *d) {
// CHECK: [[UB_VAL:%.+]] = load i64, i64* [[UB]],
// CHECK: [[CMP:%.+]] = icmp sgt i64 [[UB_VAL]], 15
// CHECK: br i1 [[CMP]], label %[[TRUE:.+]], label %[[FALSE:[^,]+]]
-// CHECK: [[TRUE]]
+// CHECK: [[TRUE]]:
// CHECK: br label %[[SWITCH:[^,]+]]
-// CHECK: [[FALSE]]
+// CHECK: [[FALSE]]:
// CHECK: [[UB_VAL:%.+]] = load i64, i64* [[UB]],
// CHECK: br label %[[SWITCH]]
-// CHECK: [[SWITCH]]
+// CHECK: [[SWITCH]]:
// CHECK: [[UP:%.+]] = phi i64 [ 15, %[[TRUE]] ], [ [[UB_VAL]], %[[FALSE]] ]
// CHECK: store i64 [[UP]], i64* [[UB]],
// CHECK: [[LB_VAL:%.+]] = load i64, i64* [[LB]],
@@ -640,7 +639,7 @@ void widened(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: [[UB_VAL:%.+]] = load i64, i64* [[UB]]
// CHECK-NEXT: [[CMP1:%.+]] = icmp sle i64 [[IV]], [[UB_VAL]]
// CHECK-NEXT: br i1 [[CMP1]], label %[[T1_BODY:.+]], label %[[T1_END:[^,]+]]
-// CHECK: [[T1_BODY]]
+// CHECK: [[T1_BODY]]:
// Loop counters i and j updates:
// CHECK: [[IV1:%.+]] = load i64, i64* [[T1_OMP_IV]]
// CHECK-NEXT: [[I_1:%.+]] = sdiv i64 [[IV1]], 4
@@ -658,7 +657,7 @@ void widened(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: [[INC:%.+]] = add nsw i64 [[IV3]], 1
// CHECK-NEXT: store i64 [[INC]], i64*
// CHECK-NEXT: br label {{%.+}}
-// CHECK: [[T1_END]]
+// CHECK: [[T1_END]]:
// CHECK: call void @__kmpc_for_static_fini(%ident_t* {{.+}}, i32 %{{.+}})
// CHECK: ret void
//
diff --git a/test/OpenMP/parallel_for_simd_if_messages.cpp b/test/OpenMP/parallel_for_simd_if_messages.cpp
index 829b825aaf50..7842524fa40d 100644
--- a/test/OpenMP/parallel_for_simd_if_messages.cpp
+++ b/test/OpenMP/parallel_for_simd_if_messages.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 %s
void foo() {
}
@@ -34,7 +34,7 @@ int tmain(T argc, S **argv) {
for (i = 0; i < argc; ++i) foo();
#pragma omp parallel for simd if(argc)
for (i = 0; i < argc; ++i) foo();
- #pragma omp parallel for simd if(parallel // expected-warning {{missing ':' after directive name modifier - ignoring}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ #pragma omp parallel for simd if(parallel // expected-error {{use of undeclared identifier 'parallel'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
for (i = 0; i < argc; ++i) foo();
#pragma omp parallel for simd if(parallel : // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
for (i = 0; i < argc; ++i) foo();
@@ -78,7 +78,7 @@ int main(int argc, char **argv) {
for (i = 0; i < argc; ++i) foo();
#pragma omp parallel for simd if(if(tmain(argc, argv) // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
for (i = 0; i < argc; ++i) foo();
- #pragma omp parallel for simd if(parallel // expected-warning {{missing ':' after directive name modifier - ignoring}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ #pragma omp parallel for simd if(parallel // expected-error {{use of undeclared identifier 'parallel'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
for (i = 0; i < argc; ++i) foo();
#pragma omp parallel for simd if(parallel : // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
for (i = 0; i < argc; ++i) foo();
diff --git a/test/OpenMP/parallel_if_codegen.cpp b/test/OpenMP/parallel_if_codegen.cpp
index 9ecf57211f85..af154c0e36dd 100644
--- a/test/OpenMP/parallel_if_codegen.cpp
+++ b/test/OpenMP/parallel_if_codegen.cpp
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck %s
-// 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 --check-prefix=CHECK %s
+// 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 --check-prefix=CHECK %s
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/parallel_if_messages.cpp b/test/OpenMP/parallel_if_messages.cpp
index 1ffc567b5916..094e83b63145 100644
--- a/test/OpenMP/parallel_if_messages.cpp
+++ b/test/OpenMP/parallel_if_messages.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ferror-limit 100 %s
void foo() {
}
@@ -22,7 +22,7 @@ int tmain(T argc, S **argv) {
#pragma omp parallel if (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp parallel if (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp parallel if(argc)
- #pragma omp parallel if(parallel // expected-warning {{missing ':' after directive name modifier - ignoring}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ #pragma omp parallel if(parallel // expected-error {{use of undeclared identifier 'parallel'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp parallel if(parallel : // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp parallel if(parallel : argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp parallel if(parallel : argc)
@@ -47,7 +47,7 @@ int main(int argc, char **argv) {
#pragma omp parallel if (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp parallel if (1 0) // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp parallel if(if(tmain(argc, argv) // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
- #pragma omp parallel if(parallel // expected-warning {{missing ':' after directive name modifier - ignoring}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ #pragma omp parallel if(parallel // expected-error {{use of undeclared identifier 'parallel'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp parallel if(parallel : // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp parallel if(parallel : argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp parallel if(parallel : argc)
diff --git a/test/OpenMP/parallel_private_codegen.cpp b/test/OpenMP/parallel_private_codegen.cpp
index 1498d456dfa5..fbb9b18d5df5 100644
--- a/test/OpenMP/parallel_private_codegen.cpp
+++ b/test/OpenMP/parallel_private_codegen.cpp
@@ -4,7 +4,6 @@
// 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
// expected-no-diagnostics
-// REQUIRES: x86-registered-target
#ifndef HEADER
#define HEADER
template <class T>
diff --git a/test/OpenMP/parallel_reduction_codegen.cpp b/test/OpenMP/parallel_reduction_codegen.cpp
index 703750c2337f..e42776c740b5 100644
--- a/test/OpenMP/parallel_reduction_codegen.cpp
+++ b/test/OpenMP/parallel_reduction_codegen.cpp
@@ -3,7 +3,6 @@
// 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
-// REQUIRES: x86-registered-target
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/parallel_sections_ast_print.cpp b/test/OpenMP/parallel_sections_ast_print.cpp
index a66b75ea6d79..da3bd48201a0 100644
--- a/test/OpenMP/parallel_sections_ast_print.cpp
+++ b/test/OpenMP/parallel_sections_ast_print.cpp
@@ -1,6 +1,6 @@
-// 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 -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
// expected-no-diagnostics
#ifndef HEADER
@@ -15,18 +15,18 @@ struct S {
#pragma omp threadprivate(TS)
};
-// CHECK: template <class T = int> struct S {
+// CHECK: template <class T> struct S {
+// CHECK: static T TS;
+// CHECK-NEXT: #pragma omp threadprivate(S::TS)
+// CHECK: };
+// CHECK: template<> struct S<int> {
// CHECK: static int TS;
// CHECK-NEXT: #pragma omp threadprivate(S<int>::TS)
// CHECK-NEXT: }
-// CHECK: template <class T = long> struct S {
+// CHECK: template<> struct S<long> {
// CHECK: static long TS;
// CHECK-NEXT: #pragma omp threadprivate(S<long>::TS)
// CHECK-NEXT: }
-// CHECK: template <class T> struct S {
-// CHECK: static T TS;
-// CHECK-NEXT: #pragma omp threadprivate(S::TS)
-// CHECK: };
template <typename T, int C>
T tmain(T argc, T *argv) {
@@ -50,55 +50,55 @@ T tmain(T argc, T *argv) {
return 0;
}
-// CHECK: template <typename T = int, int C = 5> int tmain(int argc, int *argv) {
-// CHECK-NEXT: int b = argc, c, d, e, f, g;
-// CHECK-NEXT: static int a;
-// CHECK-NEXT: S<int> s;
+// CHECK: template <typename T, int C> 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: {
// CHECK-NEXT: a = 2;
// CHECK-NEXT: }
-// CHECK-NEXT: #pragma omp parallel sections default(none) private(argc,b) firstprivate(argv) shared(d) if(parallel: argc > 0) num_threads(5) copyin(S<int>::TS) proc_bind(master) reduction(+: c) reduction(max: e)
+// CHECK-NEXT: #pragma omp parallel sections default(none) private(argc,b) firstprivate(argv) shared(d) if(parallel: argc > 0) num_threads(C) copyin(S<T>::TS) proc_bind(master) reduction(+: c) reduction(max: e)
// CHECK-NEXT: {
// CHECK-NEXT: foo();
// CHECK-NEXT: }
-// CHECK-NEXT: #pragma omp parallel sections if(5) num_threads(s) proc_bind(close) reduction(^: e,f) reduction(&&: g) lastprivate(b,c)
+// CHECK-NEXT: #pragma omp parallel sections if(C) num_threads(s) proc_bind(close) reduction(^: e,f) reduction(&&: g) lastprivate(b,c)
// CHECK-NEXT: {
// CHECK-NEXT: foo();
// CHECK-NEXT: #pragma omp section
// CHECK-NEXT: foo();
// CHECK-NEXT: }
-// CHECK: template <typename T = long, int C = 1> long tmain(long argc, long *argv) {
-// CHECK-NEXT: long b = argc, c, d, e, f, g;
-// CHECK-NEXT: static long a;
-// CHECK-NEXT: S<long> s;
+// CHECK: template<> int tmain<int, 5>(int argc, int *argv) {
+// CHECK-NEXT: int b = argc, c, d, e, f, g;
+// CHECK-NEXT: static int a;
+// CHECK-NEXT: S<int> s;
// CHECK-NEXT: #pragma omp parallel sections
// CHECK-NEXT: {
// CHECK-NEXT: a = 2;
// CHECK-NEXT: }
-// CHECK-NEXT: #pragma omp parallel sections default(none) private(argc,b) firstprivate(argv) shared(d) if(parallel: argc > 0) num_threads(1) copyin(S<long>::TS) proc_bind(master) reduction(+: c) reduction(max: e)
+// CHECK-NEXT: #pragma omp parallel sections default(none) private(argc,b) firstprivate(argv) shared(d) if(parallel: argc > 0) num_threads(5) copyin(S<int>::TS) proc_bind(master) reduction(+: c) reduction(max: e)
// CHECK-NEXT: {
// CHECK-NEXT: foo();
// CHECK-NEXT: }
-// CHECK-NEXT: #pragma omp parallel sections if(1) num_threads(s) proc_bind(close) reduction(^: e,f) reduction(&&: g) lastprivate(b,c)
+// CHECK-NEXT: #pragma omp parallel sections if(5) num_threads(s) proc_bind(close) reduction(^: e,f) reduction(&&: g) lastprivate(b,c)
// CHECK-NEXT: {
// CHECK-NEXT: foo();
// CHECK-NEXT: #pragma omp section
// CHECK-NEXT: foo();
// CHECK-NEXT: }
-// CHECK: template <typename T, int C> 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: template<> long tmain<long, 1>(long argc, long *argv) {
+// CHECK-NEXT: long b = argc, c, d, e, f, g;
+// CHECK-NEXT: static long a;
+// CHECK-NEXT: S<long> s;
// CHECK-NEXT: #pragma omp parallel sections
// CHECK-NEXT: {
// CHECK-NEXT: a = 2;
// CHECK-NEXT: }
-// CHECK-NEXT: #pragma omp parallel sections default(none) private(argc,b) firstprivate(argv) shared(d) if(parallel: argc > 0) num_threads(C) copyin(S<T>::TS) proc_bind(master) reduction(+: c) reduction(max: e)
+// CHECK-NEXT: #pragma omp parallel sections default(none) private(argc,b) firstprivate(argv) shared(d) if(parallel: argc > 0) num_threads(1) copyin(S<long>::TS) proc_bind(master) reduction(+: c) reduction(max: e)
// CHECK-NEXT: {
// CHECK-NEXT: foo();
// CHECK-NEXT: }
-// CHECK-NEXT: #pragma omp parallel sections if(C) num_threads(s) proc_bind(close) reduction(^: e,f) reduction(&&: g) lastprivate(b,c)
+// CHECK-NEXT: #pragma omp parallel sections if(1) num_threads(s) proc_bind(close) reduction(^: e,f) reduction(&&: g) lastprivate(b,c)
// CHECK-NEXT: {
// CHECK-NEXT: foo();
// CHECK-NEXT: #pragma omp section
diff --git a/test/OpenMP/parallel_sections_codegen.cpp b/test/OpenMP/parallel_sections_codegen.cpp
index bc7e1982dcb3..6fc687d0c503 100644
--- a/test/OpenMP/parallel_sections_codegen.cpp
+++ b/test/OpenMP/parallel_sections_codegen.cpp
@@ -2,7 +2,6 @@
// 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
// expected-no-diagnostics
-// REQUIRES: x86-registered-target
#ifndef HEADER
#define HEADER
// CHECK-LABEL: foo
diff --git a/test/OpenMP/parallel_sections_if_messages.cpp b/test/OpenMP/parallel_sections_if_messages.cpp
index c2e3f5ec99bd..ce067a254fea 100644
--- a/test/OpenMP/parallel_sections_if_messages.cpp
+++ b/test/OpenMP/parallel_sections_if_messages.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ferror-limit 100 %s
void foo() {
}
diff --git a/test/OpenMP/sections_ast_print.cpp b/test/OpenMP/sections_ast_print.cpp
index ea96be3ff08a..7fecd5b77771 100644
--- a/test/OpenMP/sections_ast_print.cpp
+++ b/test/OpenMP/sections_ast_print.cpp
@@ -27,6 +27,7 @@ T tmain(T argc) {
}
int main(int argc, char **argv) {
+// CHECK: int main(int argc, char **argv) {
int b = argc, c, d, e, f, g;
static int a;
// CHECK: static int a;
diff --git a/test/OpenMP/sections_codegen.cpp b/test/OpenMP/sections_codegen.cpp
index 291f05927d86..65747e7b912f 100644
--- a/test/OpenMP/sections_codegen.cpp
+++ b/test/OpenMP/sections_codegen.cpp
@@ -2,7 +2,6 @@
// 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
// expected-no-diagnostics
-// REQUIRES: x86-registered-target
#ifndef HEADER
#define HEADER
// CHECK: [[IMPLICIT_BARRIER_SECTIONS_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 194, i32 0, i32 0, i8*
diff --git a/test/OpenMP/sections_firstprivate_codegen.cpp b/test/OpenMP/sections_firstprivate_codegen.cpp
index 51d0c7b61834..a5426f8bf956 100644
--- a/test/OpenMP/sections_firstprivate_codegen.cpp
+++ b/test/OpenMP/sections_firstprivate_codegen.cpp
@@ -4,7 +4,6 @@
// 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
// expected-no-diagnostics
-// REQUIRES: x86-registered-target
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/sections_lastprivate_codegen.cpp b/test/OpenMP/sections_lastprivate_codegen.cpp
index 6ee9f63b4bdd..c9a224db2370 100644
--- a/test/OpenMP/sections_lastprivate_codegen.cpp
+++ b/test/OpenMP/sections_lastprivate_codegen.cpp
@@ -4,7 +4,6 @@
// 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
// expected-no-diagnostics
-// REQUIRES: x86-registered-target
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/sections_private_codegen.cpp b/test/OpenMP/sections_private_codegen.cpp
index b81265516935..337a0bfe3ec1 100644
--- a/test/OpenMP/sections_private_codegen.cpp
+++ b/test/OpenMP/sections_private_codegen.cpp
@@ -4,7 +4,6 @@
// 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
// expected-no-diagnostics
-// REQUIRES: x86-registered-target
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/sections_reduction_codegen.cpp b/test/OpenMP/sections_reduction_codegen.cpp
index b52d2ee3ec37..8c474d575e0a 100644
--- a/test/OpenMP/sections_reduction_codegen.cpp
+++ b/test/OpenMP/sections_reduction_codegen.cpp
@@ -4,7 +4,6 @@
// 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
// expected-no-diagnostics
-// REQUIRES: x86-registered-target
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/simd_aligned_messages.cpp b/test/OpenMP/simd_aligned_messages.cpp
index 9515a0bca68f..81aec960f269 100644
--- a/test/OpenMP/simd_aligned_messages.cpp
+++ b/test/OpenMP/simd_aligned_messages.cpp
@@ -121,7 +121,8 @@ template<class I, class C> int foomain(I argc, C **argv) {
for (I k = 0; k < argc; ++k) ++k;
#pragma omp simd aligned (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
for (I k = 0; k < argc; ++k) ++k;
- #pragma omp simd aligned (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+// FIXME: Should argc really be a pointer?
+ #pragma omp simd aligned (*argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
for (I k = 0; k < argc; ++k) ++k;
#pragma omp simd aligned (argc : 5) // expected-warning {{aligned clause will be ignored because the requested alignment is not a power of 2}}
for (I k = 0; k < argc; ++k) ++k;
diff --git a/test/OpenMP/simd_ast_print.cpp b/test/OpenMP/simd_ast_print.cpp
index 99c00c6dca81..9fcd459f4956 100644
--- a/test/OpenMP/simd_ast_print.cpp
+++ b/test/OpenMP/simd_ast_print.cpp
@@ -35,8 +35,8 @@ 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)
class S8 : public S7<SS> {
S8() {}
@@ -129,7 +129,7 @@ template<int LEN> struct S2 {
};
// S2<4>::func is called below in main.
-// CHECK: template <int LEN = 4> struct S2 {
+// CHECK: template<> struct S2<4> {
// CHECK-NEXT: static void func(int n, float *a, float *b, float *c) {
// CHECK-NEXT: int k1 = 0, k2 = 0;
// CHECK-NEXT: #pragma omp simd safelen(4) linear(k1,k2: 4) aligned(a: 4) simdlen(4)
diff --git a/test/OpenMP/simd_codegen.cpp b/test/OpenMP/simd_codegen.cpp
index 29828b39173c..47f2433f0bbc 100644
--- a/test/OpenMP/simd_codegen.cpp
+++ b/test/OpenMP/simd_codegen.cpp
@@ -2,7 +2,6 @@
// 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
-// REQUIRES: x86-registered-target
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
@@ -21,7 +20,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: [[CMP:%.+]] = icmp slt i32 [[IV]], 6
// CHECK-NEXT: br i1 [[CMP]], label %[[SIMPLE_LOOP1_BODY:.+]], label %[[SIMPLE_LOOP1_END:[^,]+]]
for (int i = 3; i < 32; i += 5) {
-// CHECK: [[SIMPLE_LOOP1_BODY]]
+// CHECK: [[SIMPLE_LOOP1_BODY]]:
// Start of body: calculate i from IV:
// CHECK: [[IV1_1:%.+]] = load i32, i32* [[OMP_IV]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP1_ID]]
// CHECK: [[CALC_I_1:%.+]] = mul nsw i32 [[IV1_1]], 5
@@ -36,7 +35,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: store i32 [[ADD1_2]], i32* [[OMP_IV]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP1_ID]]
// br label %{{.+}}, !llvm.loop !{{.+}}
}
-// CHECK: [[SIMPLE_LOOP1_END]]
+// CHECK: [[SIMPLE_LOOP1_END]]:
long long k = get_val();
@@ -51,7 +50,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: [[CMP2:%.+]] = icmp slt i32 [[IV2]], 9
// CHECK-NEXT: br i1 [[CMP2]], label %[[SIMPLE_LOOP2_BODY:.+]], label %[[SIMPLE_LOOP2_END:[^,]+]]
for (int i = 10; i > 1; i--) {
-// CHECK: [[SIMPLE_LOOP2_BODY]]
+// CHECK: [[SIMPLE_LOOP2_BODY]]:
// Start of body: calculate i from IV:
// CHECK: [[IV2_0:%.+]] = load i32, i32* [[OMP_IV2]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP2_ID]]
// FIXME: It is interesting, why the following "mul 1" was not constant folded?
@@ -73,7 +72,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: store i32 [[ADD2_2]], i32* [[OMP_IV2]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP2_ID]]
// br label {{.+}}, !llvm.loop ![[SIMPLE_LOOP2_ID]]
}
-// CHECK: [[SIMPLE_LOOP2_END]]
+// CHECK: [[SIMPLE_LOOP2_END]]:
//
// Update linear vars after loop, as the loop was operating on a private version.
// CHECK: [[LIN0_2:%.+]] = load i64, i64* [[LIN0]]
@@ -101,7 +100,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: [[CMP3:%.+]] = icmp ult i64 [[IV3]], 4
// CHECK-NEXT: br i1 [[CMP3]], label %[[SIMPLE_LOOP3_BODY:.+]], label %[[SIMPLE_LOOP3_END:[^,]+]]
for (unsigned long long it = 2000; it >= 600; it-=400) {
-// CHECK: [[SIMPLE_LOOP3_BODY]]
+// CHECK: [[SIMPLE_LOOP3_BODY]]:
// Start of body: calculate it from IV:
// CHECK: [[IV3_0:%.+]] = load i64, i64* [[OMP_IV3]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP3_ID]]
// CHECK-NEXT: [[LC_IT_1:%.+]] = mul i64 [[IV3_0]], 400
@@ -127,7 +126,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: [[ADD3_2:%.+]] = add i64 [[IV3_2]], 1
// CHECK-NEXT: store i64 [[ADD3_2]], i64* [[OMP_IV3]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP3_ID]]
}
-// CHECK: [[SIMPLE_LOOP3_END]]
+// CHECK: [[SIMPLE_LOOP3_END]]:
//
// Linear start and step are used to calculate final value of the linear variables.
// CHECK: [[LINSTART:.+]] = load i32, i32* [[LIN_START]]
@@ -143,7 +142,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: [[CMP4:%.+]] = icmp slt i32 [[IV4]], 4
// CHECK-NEXT: br i1 [[CMP4]], label %[[SIMPLE_LOOP4_BODY:.+]], label %[[SIMPLE_LOOP4_END:[^,]+]]
for (short it = 6; it <= 20; it-=-4) {
-// CHECK: [[SIMPLE_LOOP4_BODY]]
+// CHECK: [[SIMPLE_LOOP4_BODY]]:
// Start of body: calculate it from IV:
// CHECK: [[IV4_0:%.+]] = load i32, i32* [[OMP_IV4]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP4_ID]]
// CHECK-NEXT: [[LC_IT_1:%.+]] = mul nsw i32 [[IV4_0]], 4
@@ -155,7 +154,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: [[ADD4_2:%.+]] = add nsw i32 [[IV4_2]], 1
// CHECK-NEXT: store i32 [[ADD4_2]], i32* [[OMP_IV4]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP4_ID]]
}
-// CHECK: [[SIMPLE_LOOP4_END]]
+// CHECK: [[SIMPLE_LOOP4_END]]:
#pragma omp simd
// CHECK: store i32 0, i32* [[OMP_IV5:%[^,]+]]
@@ -164,7 +163,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: [[CMP5:%.+]] = icmp slt i32 [[IV5]], 26
// CHECK-NEXT: br i1 [[CMP5]], label %[[SIMPLE_LOOP5_BODY:.+]], label %[[SIMPLE_LOOP5_END:[^,]+]]
for (unsigned char it = 'z'; it >= 'a'; it+=-1) {
-// CHECK: [[SIMPLE_LOOP5_BODY]]
+// CHECK: [[SIMPLE_LOOP5_BODY]]:
// Start of body: calculate it from IV:
// CHECK: [[IV5_0:%.+]] = load i32, i32* [[OMP_IV5]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP5_ID]]
// CHECK-NEXT: [[IV5_1:%.+]] = mul nsw i32 [[IV5_0]], 1
@@ -176,7 +175,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: [[ADD5_2:%.+]] = add nsw i32 [[IV5_2]], 1
// CHECK-NEXT: store i32 [[ADD5_2]], i32* [[OMP_IV5]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP5_ID]]
}
-// CHECK: [[SIMPLE_LOOP5_END]]
+// CHECK: [[SIMPLE_LOOP5_END]]:
// CHECK-NOT: mul i32 %{{.+}}, 10
#pragma omp simd
@@ -189,12 +188,12 @@ void simple(float *a, float *b, float *c, float *d) {
#pragma omp simd lastprivate(A)
// CHECK: store i64 0, i64* [[OMP_IV7:%[^,]+]]
// CHECK: br label %[[SIMD_LOOP7_COND:[^,]+]]
-// CHECK: [[SIMD_LOOP7_COND]]
+// CHECK: [[SIMD_LOOP7_COND]]:
// CHECK-NEXT: [[IV7:%.+]] = load i64, i64* [[OMP_IV7]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP7_ID:[0-9]+]]
// CHECK-NEXT: [[CMP7:%.+]] = icmp slt i64 [[IV7]], 7
// CHECK-NEXT: br i1 [[CMP7]], label %[[SIMPLE_LOOP7_BODY:.+]], label %[[SIMPLE_LOOP7_END:[^,]+]]
for (long long i = -10; i < 10; i += 3) {
-// CHECK: [[SIMPLE_LOOP7_BODY]]
+// CHECK: [[SIMPLE_LOOP7_BODY]]:
// Start of body: calculate i from IV:
// CHECK: [[IV7_0:%.+]] = load i64, i64* [[OMP_IV7]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP7_ID]]
// CHECK-NEXT: [[LC_IT_1:%.+]] = mul nsw i64 [[IV7_0]], 3
@@ -208,7 +207,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: [[ADD7_2:%.+]] = add nsw i64 [[IV7_2]], 1
// CHECK-NEXT: store i64 [[ADD7_2]], i64* [[OMP_IV7]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP7_ID]]
}
-// CHECK: [[SIMPLE_LOOP7_END]]
+// CHECK: [[SIMPLE_LOOP7_END]]:
// CHECK-NEXT: store i64 11, i64*
// CHECK-NEXT: [[A_PRIV_VAL:%.+]] = load i32, i32* [[A_PRIV]],
// CHECK-NEXT: store i32 [[A_PRIV_VAL]], i32* [[A]],
@@ -219,12 +218,12 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK: store i32 1, i32* [[R_PRIV:%[^,]+]],
#pragma omp simd reduction(*:R)
// CHECK: br label %[[SIMD_LOOP8_COND:[^,]+]]
-// CHECK: [[SIMD_LOOP8_COND]]
+// CHECK: [[SIMD_LOOP8_COND]]:
// CHECK-NEXT: [[IV8:%.+]] = load i64, i64* [[OMP_IV8]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP8_ID:[0-9]+]]
// CHECK-NEXT: [[CMP8:%.+]] = icmp slt i64 [[IV8]], 7
// CHECK-NEXT: br i1 [[CMP8]], label %[[SIMPLE_LOOP8_BODY:.+]], label %[[SIMPLE_LOOP8_END:[^,]+]]
for (long long i = -10; i < 10; i += 3) {
-// CHECK: [[SIMPLE_LOOP8_BODY]]
+// CHECK: [[SIMPLE_LOOP8_BODY]]:
// Start of body: calculate i from IV:
// CHECK: [[IV8_0:%.+]] = load i64, i64* [[OMP_IV8]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP8_ID]]
// CHECK-NEXT: [[LC_IT_1:%.+]] = mul nsw i64 [[IV8_0]], 3
@@ -237,7 +236,7 @@ void simple(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: [[ADD8_2:%.+]] = add nsw i64 [[IV8_2]], 1
// CHECK-NEXT: store i64 [[ADD8_2]], i64* [[OMP_IV8]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP8_ID]]
}
-// CHECK: [[SIMPLE_LOOP8_END]]
+// CHECK: [[SIMPLE_LOOP8_END]]:
// CHECK-DAG: [[R_VAL:%.+]] = load i32, i32* [[R]],
// CHECK-DAG: [[R_PRIV_VAL:%.+]] = load i32, i32* [[R_PRIV]],
// CHECK: [[RED:%.+]] = mul nsw i32 [[R_VAL]], [[R_PRIV_VAL]]
@@ -265,7 +264,7 @@ int templ1(T a, T *z) {
// CHECK: [[IV:%.+]] = load i64, i64* [[T1_OMP_IV]]{{.*}}!llvm.mem.parallel_loop_access ![[T1_ID:[0-9]+]]
// CHECK-NEXT: [[CMP1:%.+]] = icmp slt i64 [[IV]], 16
// CHECK-NEXT: br i1 [[CMP1]], label %[[T1_BODY:.+]], label %[[T1_END:[^,]+]]
-// CHECK: [[T1_BODY]]
+// CHECK: [[T1_BODY]]:
// Loop counters i and j updates:
// CHECK: [[IV1:%.+]] = load i64, i64* [[T1_OMP_IV]]{{.*}}!llvm.mem.parallel_loop_access ![[T1_ID]]
// CHECK-NEXT: [[I_1:%.+]] = sdiv i64 [[IV1]], 4
@@ -283,7 +282,7 @@ int templ1(T a, T *z) {
// CHECK-NEXT: [[INC:%.+]] = add nsw i64 [[IV3]], 1
// CHECK-NEXT: store i64 [[INC]], i64* [[T1_OMP_IV]]{{.*}}!llvm.mem.parallel_loop_access ![[T1_ID]]
// CHECK-NEXT: br label {{%.+}}
-// CHECK: [[T1_END]]
+// CHECK: [[T1_END]]:
// CHECK: ret i32 0
//
void inst_templ1() {
@@ -340,7 +339,7 @@ void iter_simple(IterDouble ia, IterDouble ib, IterDouble ic) {
// CHECK-NEXT: [[CMP:%.+]] = icmp slt i32 [[IV]], [[NUM_IT]]
// CHECK-NEXT: br i1 [[CMP]], label %[[IT_BODY:[^,]+]], label %[[IT_END:[^,]+]]
for (IterDouble i = ia; i < ib; ++i) {
-// CHECK: [[IT_BODY]]
+// CHECK: [[IT_BODY]]:
// Start of body: calculate i from index:
// CHECK: [[IV1:%.+]] = load i32, i32* [[IT_OMP_IV]]{{.+}}!llvm.mem.parallel_loop_access ![[ITER_LOOP_ID]]
// Call of operator+ (i, IV).
@@ -358,7 +357,7 @@ void iter_simple(IterDouble ia, IterDouble ib, IterDouble ic) {
// CHECK-NEXT: store i32 [[ADD2]], i32* [[IT_OMP_IV]]{{.+}}!llvm.mem.parallel_loop_access ![[ITER_LOOP_ID]]
// br label %{{.*}}, !llvm.loop ![[ITER_LOOP_ID]]
}
-// CHECK: [[IT_END]]
+// CHECK: [[IT_END]]:
// CHECK: ret void
}
@@ -381,7 +380,7 @@ void collapsed(float *a, float *b, float *c, float *d) {
for (int k = 3; k <= 6; k++) // 4 iterations
for (l = 4; l < 9; ++l) // 5 iterations
{
-// CHECK: [[COLL1_BODY]]
+// CHECK: [[COLL1_BODY]]:
// Start of body: calculate i from index:
// CHECK: [[IV1:%.+]] = load i32, i32* [[OMP_IV]]{{.+}}!llvm.mem.parallel_loop_access ![[COLL1_LOOP_ID]]
// Calculation of the loop counters values.
@@ -416,7 +415,7 @@ void collapsed(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: [[ADD2:%.+]] = add i32 [[IV2]], 1
// CHECK-NEXT: store i32 [[ADD2]], i32* [[OMP_IV]]{{.*}}!llvm.mem.parallel_loop_access ![[COLL1_LOOP_ID]]
// br label %{{[^,]+}}, !llvm.loop ![[COLL1_LOOP_ID]]
-// CHECK: [[COLL1_END]]
+// CHECK: [[COLL1_END]]:
}
// i,j,l are updated; k is not updated.
// CHECK: store i32 3, i32*
@@ -449,7 +448,7 @@ void widened(float *a, float *b, float *c, float *d) {
for (i = 1; i < 3; i++) // 2 iterations
for (j = 0; j < foo(); j++) // foo() iterations
{
-// CHECK: [[WIDE1_BODY]]
+// CHECK: [[WIDE1_BODY]]:
// Start of body: calculate i from index:
// CHECK: [[IV1:%.+]] = load i64, i64* [[OMP_IV]]{{.+}}!llvm.mem.parallel_loop_access ![[WIDE1_LOOP_ID]]
// Calculation of the loop counters values...
@@ -473,7 +472,7 @@ void widened(float *a, float *b, float *c, float *d) {
// CHECK-NEXT: store i64 [[ADD2]], i64* [[OMP_IV]]{{.*}}!llvm.mem.parallel_loop_access ![[WIDE1_LOOP_ID]]
//
// br label %{{[^,]+}}, !llvm.loop ![[WIDE1_LOOP_ID]]
-// CHECK: [[WIDE1_END]]
+// CHECK: [[WIDE1_END]]:
}
// i,j are updated.
// CHECK: store i32 3, i32* [[I:%[^,]+]]
@@ -505,7 +504,7 @@ void linear(float *a) {
// CHECK-NEXT: [[CMP2:%.+]] = icmp slt i32 [[IV]], 9
// CHECK-NEXT: br i1 [[CMP2]], label %[[SIMPLE_LOOP_BODY:.+]], label %[[SIMPLE_LOOP_END:[^,]+]]
for (int i = 10; i > 1; i--) {
-// CHECK: [[SIMPLE_LOOP_BODY]]
+// CHECK: [[SIMPLE_LOOP_BODY]]:
// Start of body: calculate i from IV:
// CHECK: [[IV_0:%.+]] = load i32, i32* [[OMP_IV]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP_ID]]
// FIXME: It is interesting, why the following "mul 1" was not constant folded?
@@ -527,7 +526,7 @@ void linear(float *a) {
// CHECK-NEXT: store i32 [[ADD2_2]], i32* [[OMP_IV]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP_ID]]
// br label {{.+}}, !llvm.loop ![[SIMPLE_LOOP_ID]]
}
-// CHECK: [[SIMPLE_LOOP_END]]
+// CHECK: [[SIMPLE_LOOP_END]]:
//
// Update linear vars after loop, as the loop was operating on a private version.
// CHECK: [[K_REF:%.+]] = load i64*, i64** [[K_ADDR_REF]],
@@ -550,7 +549,7 @@ void linear(float *a) {
// CHECK-NEXT: [[CMP2:%.+]] = icmp slt i32 [[IV]], 9
// CHECK-NEXT: br i1 [[CMP2]], label %[[SIMPLE_LOOP_BODY:.+]], label %[[SIMPLE_LOOP_END:[^,]+]]
for (int i = 10; i > 1; i--) {
-// CHECK: [[SIMPLE_LOOP_BODY]]
+// CHECK: [[SIMPLE_LOOP_BODY]]:
// Start of body: calculate i from IV:
// CHECK: [[IV_0:%.+]] = load i32, i32* [[OMP_IV]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP_ID]]
// FIXME: It is interesting, why the following "mul 1" was not constant folded?
@@ -572,7 +571,7 @@ void linear(float *a) {
// CHECK-NEXT: store i32 [[ADD2_2]], i32* [[OMP_IV]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP_ID]]
// br label {{.+}}, !llvm.loop ![[SIMPLE_LOOP_ID]]
}
-// CHECK: [[SIMPLE_LOOP_END]]
+// CHECK: [[SIMPLE_LOOP_END]]:
//
// Update linear vars after loop, as the loop was operating on a private version.
// CHECK: [[K_REF:%.+]] = load i64*, i64** [[K_ADDR_REF]],
@@ -591,7 +590,7 @@ void linear(float *a) {
// CHECK-NEXT: [[CMP2:%.+]] = icmp slt i32 [[IV]], 9
// CHECK-NEXT: br i1 [[CMP2]], label %[[SIMPLE_LOOP_BODY:.+]], label %[[SIMPLE_LOOP_END:[^,]+]]
for (int i = 10; i > 1; i--) {
-// CHECK: [[SIMPLE_LOOP_BODY]]
+// CHECK: [[SIMPLE_LOOP_BODY]]:
// Start of body: calculate i from IV:
// CHECK: [[IV_0:%.+]] = load i32, i32* [[OMP_IV]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP_ID]]
// FIXME: It is interesting, why the following "mul 1" was not constant folded?
@@ -613,7 +612,7 @@ void linear(float *a) {
// CHECK-NEXT: store i32 [[ADD2_2]], i32* [[OMP_IV]]{{.*}}!llvm.mem.parallel_loop_access ![[SIMPLE_LOOP_ID]]
// br label {{.+}}, !llvm.loop ![[SIMPLE_LOOP_ID]]
}
-// CHECK: [[SIMPLE_LOOP_END]]
+// CHECK: [[SIMPLE_LOOP_END]]:
//
// Update linear vars after loop, as the loop was operating on a private version.
// CHECK: [[LIN0_2:%.+]] = load i64, i64* [[LIN0]]
diff --git a/test/OpenMP/single_ast_print.cpp b/test/OpenMP/single_ast_print.cpp
index d30b7feb02c5..e819ab9e14a5 100644
--- a/test/OpenMP/single_ast_print.cpp
+++ b/test/OpenMP/single_ast_print.cpp
@@ -57,6 +57,7 @@ T tmain(T argc) {
}
int main(int argc, char **argv) {
+// CHECK: int main(int argc, char **argv) {
int b = argc, c, d, e, f, g;
static int a;
SS ss(a);
diff --git a/test/OpenMP/single_codegen.cpp b/test/OpenMP/single_codegen.cpp
index a2140c2eda78..892e16032417 100644
--- a/test/OpenMP/single_codegen.cpp
+++ b/test/OpenMP/single_codegen.cpp
@@ -4,7 +4,6 @@
// 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
// expected-no-diagnostics
-// REQUIRES: x86-registered-target
#ifndef ARRAY
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/single_firstprivate_codegen.cpp b/test/OpenMP/single_firstprivate_codegen.cpp
index 537ae76f1277..9f059e970470 100644
--- a/test/OpenMP/single_firstprivate_codegen.cpp
+++ b/test/OpenMP/single_firstprivate_codegen.cpp
@@ -4,7 +4,6 @@
// 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
// expected-no-diagnostics
-// REQUIRES: x86-registered-target
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/single_private_codegen.cpp b/test/OpenMP/single_private_codegen.cpp
index c98c5ea1dd67..6d47cb50dc59 100644
--- a/test/OpenMP/single_private_codegen.cpp
+++ b/test/OpenMP/single_private_codegen.cpp
@@ -4,7 +4,6 @@
// 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
// expected-no-diagnostics
-// REQUIRES: x86-registered-target
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/target_ast_print.cpp b/test/OpenMP/target_ast_print.cpp
index e093e29979ba..032a39fe5e82 100644
--- a/test/OpenMP/target_ast_print.cpp
+++ b/test/OpenMP/target_ast_print.cpp
@@ -1,6 +1,6 @@
-// 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 -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
// expected-no-diagnostics
#ifndef HEADER
@@ -34,13 +34,13 @@ T tmain(T argc, T *argv) {
return 0;
}
-// CHECK: template <typename T = int, int C = 5> int tmain(int argc, int *argv) {
-// CHECK-NEXT: int i, j, a[20]
+// 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: foo();
// CHECK-NEXT: #pragma omp target if(target: argc > 0)
// CHECK-NEXT: foo()
-// CHECK-NEXT: #pragma omp target if(5)
+// CHECK-NEXT: #pragma omp target if(C)
// CHECK-NEXT: foo()
// CHECK-NEXT: #pragma omp target map(tofrom: i)
// CHECK-NEXT: foo()
@@ -56,13 +56,13 @@ T tmain(T argc, T *argv) {
// CHECK-NEXT: foo()
// CHECK-NEXT: #pragma omp target defaultmap(tofrom: scalar)
// CHECK-NEXT: foo()
-// CHECK: template <typename T = char, int C = 1> char tmain(char argc, char *argv) {
-// CHECK-NEXT: char i, j, a[20]
+// CHECK: template<> int tmain<int, 5>(int argc, int *argv) {
+// CHECK-NEXT: int i, j, a[20]
// CHECK-NEXT: #pragma omp target
// CHECK-NEXT: foo();
// CHECK-NEXT: #pragma omp target if(target: argc > 0)
// CHECK-NEXT: foo()
-// CHECK-NEXT: #pragma omp target if(1)
+// CHECK-NEXT: #pragma omp target if(5)
// CHECK-NEXT: foo()
// CHECK-NEXT: #pragma omp target map(tofrom: i)
// CHECK-NEXT: foo()
@@ -78,13 +78,13 @@ T tmain(T argc, T *argv) {
// CHECK-NEXT: foo()
// CHECK-NEXT: #pragma omp target defaultmap(tofrom: scalar)
// CHECK-NEXT: foo()
-// CHECK: template <typename T, int C> T tmain(T argc, T *argv) {
-// CHECK-NEXT: T i, j, a[20]
+// CHECK: template<> char tmain<char, 1>(char argc, char *argv) {
+// CHECK-NEXT: char i, j, a[20]
// CHECK-NEXT: #pragma omp target
// CHECK-NEXT: foo();
// CHECK-NEXT: #pragma omp target if(target: argc > 0)
// CHECK-NEXT: foo()
-// CHECK-NEXT: #pragma omp target if(C)
+// CHECK-NEXT: #pragma omp target if(1)
// CHECK-NEXT: foo()
// CHECK-NEXT: #pragma omp target map(tofrom: i)
// CHECK-NEXT: foo()
diff --git a/test/OpenMP/target_data_ast_print.cpp b/test/OpenMP/target_data_ast_print.cpp
index ed7a96541196..bb55ea30d532 100644
--- a/test/OpenMP/target_data_ast_print.cpp
+++ b/test/OpenMP/target_data_ast_print.cpp
@@ -1,6 +1,6 @@
-// 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 -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
// expected-no-diagnostics
#ifndef HEADER
@@ -46,8 +46,8 @@ T tmain(T argc, T *argv) {
return 0;
}
-// CHECK: template <typename T = int, int C = 5> int tmain(int argc, int *argv) {
-// CHECK-NEXT: int i, j, b, c, d, e, x[20];
+// 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: i = argc;
// CHECK-NEXT: #pragma omp target data map(to: c) if(target data: j > 0)
@@ -68,8 +68,8 @@ T tmain(T argc, T *argv) {
// CHECK-NEXT: {
// CHECK-NEXT: #pragma omp target map(always,alloc: e)
// CHECK-NEXT: foo();
-// CHECK: template <typename T = char, int C = 1> char tmain(char argc, char *argv) {
-// CHECK-NEXT: char i, j, b, c, d, e, x[20];
+// CHECK: template<> int tmain<int, 5>(int argc, int *argv) {
+// CHECK-NEXT: int i, j, b, c, d, e, x[20];
// 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)
@@ -90,8 +90,8 @@ T tmain(T argc, T *argv) {
// CHECK-NEXT: {
// CHECK-NEXT: #pragma omp target map(always,alloc: e)
// CHECK-NEXT: foo();
-// CHECK: template <typename T, int C> T tmain(T argc, T *argv) {
-// CHECK-NEXT: T i, j, b, c, d, e, x[20];
+// CHECK: template<> char tmain<char, 1>(char argc, char *argv) {
+// CHECK-NEXT: char i, j, b, c, d, e, x[20];
// 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)
diff --git a/test/OpenMP/target_data_if_messages.cpp b/test/OpenMP/target_data_if_messages.cpp
index ec6fe2692153..229d7f564738 100644
--- a/test/OpenMP/target_data_if_messages.cpp
+++ b/test/OpenMP/target_data_if_messages.cpp
@@ -1,4 +1,4 @@
-// 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 -fopenmp-version=45 -ferror-limit 100 -o - %s
void foo() {
}
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 4e3253b2798f..ce1ec1d2799a 100644
--- a/test/OpenMP/target_data_use_device_ptr_ast_print.cpp
+++ b/test/OpenMP/target_data_use_device_ptr_ast_print.cpp
@@ -110,7 +110,7 @@ T tmain(T argc) {
return 0;
}
-// CHECK: template <typename T = int> int tmain(int argc) {
+// CHECK: template<> int tmain<int>(int argc) {
// CHECK-NEXT: int i;
// CHECK-NEXT: int &j = i;
// CHECK-NEXT: int *k = &j;
@@ -120,7 +120,7 @@ T tmain(T argc) {
// CHECK-NEXT: }
// CHECK-NEXT: #pragma omp target data map(tofrom: i) use_device_ptr(z)
-// CHECK: template <typename T = int *> int *tmain(int *argc) {
+// CHECK: template<> int *tmain<int *>(int *argc) {
// CHECK-NEXT: int *i;
// CHECK-NEXT: int *&j = i;
// CHECK-NEXT: int **k = &j;
diff --git a/test/OpenMP/target_data_use_device_ptr_codegen.cpp b/test/OpenMP/target_data_use_device_ptr_codegen.cpp
new file mode 100644
index 000000000000..c4b389a4cbb8
--- /dev/null
+++ b/test/OpenMP/target_data_use_device_ptr_codegen.cpp
@@ -0,0 +1,464 @@
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+///==========================================================================///
+// 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 -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 -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
+#ifdef CK1
+
+double *g;
+
+// CK1: @g = global double*
+// CK1: [[MTYPE00:@.+]] = {{.*}}constant [1 x i32] [i32 99]
+// CK1: [[MTYPE01:@.+]] = {{.*}}constant [1 x i32] [i32 99]
+// CK1: [[MTYPE03:@.+]] = {{.*}}constant [1 x i32] [i32 99]
+// CK1: [[MTYPE04:@.+]] = {{.*}}constant [1 x i32] [i32 99]
+// CK1: [[MTYPE05:@.+]] = {{.*}}constant [1 x i32] [i32 99]
+// CK1: [[MTYPE06:@.+]] = {{.*}}constant [1 x i32] [i32 99]
+// CK1: [[MTYPE07:@.+]] = {{.*}}constant [1 x i32] [i32 99]
+// CK1: [[MTYPE08:@.+]] = {{.*}}constant [2 x i32] [{{i32 35, i32 99|i32 99, i32 35}}]
+// CK1: [[MTYPE09:@.+]] = {{.*}}constant [2 x i32] [i32 99, i32 99]
+// CK1: [[MTYPE10:@.+]] = {{.*}}constant [2 x i32] [i32 99, i32 99]
+// CK1: [[MTYPE11:@.+]] = {{.*}}constant [2 x i32] [i32 96, i32 35]
+// CK1: [[MTYPE12:@.+]] = {{.*}}constant [2 x i32] [i32 96, i32 35]
+
+// CK1-LABEL: @_Z3foo
+template<typename T>
+void foo(float *&lr, T *&tr) {
+ float *l;
+ T *t;
+
+ // CK1-DAG: [[RVAL:%.+]] = bitcast double* [[T:%.+]] to i8*
+ // CK1-DAG: [[T]] = load double*, double** [[DECL:@g]],
+ // CK1: [[BP:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* %{{.+}}, i32 0, i32 0
+ // CK1: store i8* [[RVAL]], i8** [[BP]],
+ // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE00]]
+ // CK1: [[CBP:%.+]] = bitcast i8** [[BP]] to double**
+ // CK1: [[VAL:%.+]] = load double*, double** [[CBP]],
+ // CK1-NOT: store double* [[VAL]], double** [[DECL]],
+ // CK1: store double* [[VAL]], double** [[PVT:%.+]],
+ // CK1: [[TT:%.+]] = load double*, double** [[PVT]],
+ // CK1: getelementptr inbounds double, double* [[TT]], i32 1
+ #pragma omp target data map(g[:10]) use_device_ptr(g)
+ {
+ ++g;
+ }
+ // CK1: call void @__tgt_target_data_end{{.+}}[[MTYPE00]]
+ // CK1: [[TTT:%.+]] = load double*, double** [[DECL]],
+ // CK1: getelementptr inbounds double, double* [[TTT]], i32 1
+ ++g;
+
+ // CK1-DAG: [[RVAL:%.+]] = bitcast float* [[T1:%.+]] to i8*
+ // CK1-DAG: [[T1]] = load float*, float** [[DECL:%.+]],
+ // CK1: [[BP:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* %{{.+}}, i32 0, i32 0
+ // CK1: store i8* [[RVAL]], i8** [[BP]],
+ // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE01]]
+ // CK1: [[CBP:%.+]] = bitcast i8** [[BP]] to float**
+ // CK1: [[VAL:%.+]] = load float*, float** [[CBP]],
+ // CK1-NOT: store float* [[VAL]], float** [[DECL]],
+ // CK1: store float* [[VAL]], float** [[PVT:%.+]],
+ // CK1: [[TT1:%.+]] = load float*, float** [[PVT]],
+ // CK1: getelementptr inbounds float, float* [[TT1]], i32 1
+ #pragma omp target data map(l[:10]) use_device_ptr(l)
+ {
+ ++l;
+ }
+ // CK1: call void @__tgt_target_data_end{{.+}}[[MTYPE01]]
+ // CK1: [[TTT:%.+]] = load float*, float** [[DECL]],
+ // CK1: getelementptr inbounds float, float* [[TTT]], i32 1
+ ++l;
+
+ // CK1-NOT: call void @__tgt_target
+ // CK1: [[TTT:%.+]] = load float*, float** [[DECL]],
+ // CK1: getelementptr inbounds float, float* [[TTT]], i32 1
+ #pragma omp target data map(l[:10]) use_device_ptr(l) if(0)
+ {
+ ++l;
+ }
+ // CK1-NOT: call void @__tgt_target
+ // CK1: [[TTT:%.+]] = load float*, float** [[DECL]],
+ // CK1: getelementptr inbounds float, float* [[TTT]], i32 1
+ ++l;
+
+ // CK1-DAG: [[RVAL:%.+]] = bitcast float* [[T1:%.+]] to i8*
+ // CK1-DAG: [[T1]] = load float*, float** [[DECL:%.+]],
+ // CK1: [[BP:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* %{{.+}}, i32 0, i32 0
+ // CK1: store i8* [[RVAL]], i8** [[BP]],
+ // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE03]]
+ // CK1: [[CBP:%.+]] = bitcast i8** [[BP]] to float**
+ // CK1: [[VAL:%.+]] = load float*, float** [[CBP]],
+ // CK1-NOT: store float* [[VAL]], float** [[DECL]],
+ // CK1: store float* [[VAL]], float** [[PVT:%.+]],
+ // CK1: [[TT1:%.+]] = load float*, float** [[PVT]],
+ // CK1: getelementptr inbounds float, float* [[TT1]], i32 1
+ #pragma omp target data map(l[:10]) use_device_ptr(l) if(1)
+ {
+ ++l;
+ }
+ // CK1: call void @__tgt_target_data_end{{.+}}[[MTYPE03]]
+ // CK1: [[TTT:%.+]] = load float*, float** [[DECL]],
+ // CK1: getelementptr inbounds float, float* [[TTT]], i32 1
+ ++l;
+
+ // CK1: [[CMP:%.+]] = icmp ne float* %{{.+}}, null
+ // CK1: br i1 [[CMP]], label %[[BTHEN:.+]], label %[[BELSE:.+]]
+
+ // CK1: [[BTHEN]]:
+ // CK1-DAG: [[RVAL:%.+]] = bitcast float* [[T1:%.+]] to i8*
+ // CK1-DAG: [[T1]] = load float*, float** [[DECL:%.+]],
+ // CK1: [[BP:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* %{{.+}}, i32 0, i32 0
+ // CK1: store i8* [[RVAL]], i8** [[BP]],
+ // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE04]]
+ // CK1: [[CBP:%.+]] = bitcast i8** [[BP]] to float**
+ // CK1: [[VAL:%.+]] = load float*, float** [[CBP]],
+ // CK1-NOT: store float* [[VAL]], float** [[DECL]],
+ // CK1: store float* [[VAL]], float** [[PVT:%.+]],
+ // CK1: [[TT1:%.+]] = load float*, float** [[PVT]],
+ // CK1: getelementptr inbounds float, float* [[TT1]], i32 1
+ // CK1: br label %[[BEND:.+]]
+
+ // CK1: [[BELSE]]:
+ // CK1: [[TTT:%.+]] = load float*, float** [[DECL]],
+ // CK1: getelementptr inbounds float, float* [[TTT]], i32 1
+ // CK1: br label %[[BEND]]
+ #pragma omp target data map(l[:10]) use_device_ptr(l) if(lr != 0)
+ {
+ ++l;
+ }
+ // CK1: [[BEND]]:
+ // CK1: [[CMP:%.+]] = icmp ne float* %{{.+}}, null
+ // CK1: br i1 [[CMP]], label %[[BTHEN:.+]], label %[[BELSE:.+]]
+
+ // CK1: [[BTHEN]]:
+ // CK1: call void @__tgt_target_data_end{{.+}}[[MTYPE04]]
+ // CK1: br label %[[BEND:.+]]
+
+ // CK1: [[BELSE]]:
+ // CK1: br label %[[BEND]]
+
+ // CK1: [[BEND]]:
+ // CK1: [[TTT:%.+]] = load float*, float** [[DECL]],
+ // CK1: getelementptr inbounds float, float* [[TTT]], i32 1
+ ++l;
+
+ // CK1-DAG: [[RVAL:%.+]] = bitcast float* [[T1:%.+]] to i8*
+ // CK1-DAG: [[T1]] = load float*, float** [[T2:%.+]],
+ // CK1-DAG: [[T2]] = load float**, float*** [[DECL:%.+]],
+ // CK1: [[BP:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* %{{.+}}, i32 0, i32 0
+ // CK1: store i8* [[RVAL]], i8** [[BP]],
+ // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE05]]
+ // CK1: [[CBP:%.+]] = bitcast i8** [[BP]] to float**
+ // CK1: [[VAL:%.+]] = load float*, float** [[CBP]],
+ // CK1: store float* [[VAL]], float** [[PVTV:%.+]],
+ // CK1-NOT: store float** [[PVTV]], float*** [[DECL]],
+ // CK1: store float** [[PVTV]], float*** [[PVT:%.+]],
+ // CK1: [[TT1:%.+]] = load float**, float*** [[PVT]],
+ // CK1: [[TT2:%.+]] = load float*, float** [[TT1]],
+ // CK1: getelementptr inbounds float, float* [[TT2]], i32 1
+ #pragma omp target data map(lr[:10]) use_device_ptr(lr)
+ {
+ ++lr;
+ }
+ // CK1: call void @__tgt_target_data_end{{.+}}[[MTYPE05]]
+ // CK1: [[TTT:%.+]] = load float**, float*** [[DECL]],
+ // CK1: [[TTTT:%.+]] = load float*, float** [[TTT]],
+ // CK1: getelementptr inbounds float, float* [[TTTT]], i32 1
+ ++lr;
+
+ // CK1-DAG: [[RVAL:%.+]] = bitcast i32* [[T1:%.+]] to i8*
+ // CK1-DAG: [[T1]] = load i32*, i32** [[DECL:%.+]],
+ // CK1: [[BP:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* %{{.+}}, i32 0, i32 0
+ // CK1: store i8* [[RVAL]], i8** [[BP]],
+ // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE06]]
+ // CK1: [[CBP:%.+]] = bitcast i8** [[BP]] to i32**
+ // CK1: [[VAL:%.+]] = load i32*, i32** [[CBP]],
+ // CK1-NOT: store i32* [[VAL]], i32** [[DECL]],
+ // CK1: store i32* [[VAL]], i32** [[PVT:%.+]],
+ // CK1: [[TT1:%.+]] = load i32*, i32** [[PVT]],
+ // CK1: getelementptr inbounds i32, i32* [[TT1]], i32 1
+ #pragma omp target data map(t[:10]) use_device_ptr(t)
+ {
+ ++t;
+ }
+ // CK1: call void @__tgt_target_data_end{{.+}}[[MTYPE06]]
+ // CK1: [[TTT:%.+]] = load i32*, i32** [[DECL]],
+ // CK1: getelementptr inbounds i32, i32* [[TTT]], i32 1
+ ++t;
+
+ // CK1-DAG: [[RVAL:%.+]] = bitcast i32* [[T1:%.+]] to i8*
+ // CK1-DAG: [[T1]] = load i32*, i32** [[T2:%.+]],
+ // CK1-DAG: [[T2]] = load i32**, i32*** [[DECL:%.+]],
+ // CK1: [[BP:%.+]] = getelementptr inbounds [1 x i8*], [1 x i8*]* %{{.+}}, i32 0, i32 0
+ // CK1: store i8* [[RVAL]], i8** [[BP]],
+ // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE07]]
+ // CK1: [[CBP:%.+]] = bitcast i8** [[BP]] to i32**
+ // CK1: [[VAL:%.+]] = load i32*, i32** [[CBP]],
+ // CK1: store i32* [[VAL]], i32** [[PVTV:%.+]],
+ // CK1-NOT: store i32** [[PVTV]], i32*** [[DECL]],
+ // CK1: store i32** [[PVTV]], i32*** [[PVT:%.+]],
+ // CK1: [[TT1:%.+]] = load i32**, i32*** [[PVT]],
+ // CK1: [[TT2:%.+]] = load i32*, i32** [[TT1]],
+ // CK1: getelementptr inbounds i32, i32* [[TT2]], i32 1
+ #pragma omp target data map(tr[:10]) use_device_ptr(tr)
+ {
+ ++tr;
+ }
+ // CK1: call void @__tgt_target_data_end{{.+}}[[MTYPE07]]
+ // CK1: [[TTT:%.+]] = load i32**, i32*** [[DECL]],
+ // CK1: [[TTTT:%.+]] = load i32*, i32** [[TTT]],
+ // CK1: getelementptr inbounds i32, i32* [[TTTT]], i32 1
+ ++tr;
+
+ // CK1-DAG: [[RVAL:%.+]] = bitcast float* [[T1:%.+]] to i8*
+ // CK1-DAG: [[T1]] = load float*, float** [[DECL:%.+]],
+ // CK1: [[BP:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* %{{.+}}, i32 0, i32
+ // CK1: store i8* [[RVAL]], i8** [[BP]],
+ // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE08]]
+ // CK1: [[CBP:%.+]] = bitcast i8** [[BP]] to float**
+ // CK1: [[VAL:%.+]] = load float*, float** [[CBP]],
+ // CK1-NOT: store float* [[VAL]], float** [[DECL]],
+ // CK1: store float* [[VAL]], float** [[PVT:%.+]],
+ // CK1: [[TT1:%.+]] = load float*, float** [[PVT]],
+ // CK1: getelementptr inbounds float, float* [[TT1]], i32 1
+ #pragma omp target data map(l[:10], t[:10]) use_device_ptr(l)
+ {
+ ++l; ++t;
+ }
+ // CK1: call void @__tgt_target_data_end{{.+}}[[MTYPE08]]
+ // CK1: [[TTT:%.+]] = load float*, float** [[DECL]],
+ // CK1: getelementptr inbounds float, float* [[TTT]], i32 1
+ ++l; ++t;
+
+
+ // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE09]]
+ // CK1: [[_CBP:%.+]] = bitcast i8** {{%.+}} to float**
+ // CK1: [[_VAL:%.+]] = load float*, float** [[_CBP]],
+ // CK1: store float* [[_VAL]], float** [[_PVT:%.+]],
+ // CK1: [[CBP:%.+]] = bitcast i8** {{%.+}} to i32**
+ // CK1: [[VAL:%.+]] = load i32*, i32** [[CBP]],
+ // CK1: store i32* [[VAL]], i32** [[PVT:%.+]],
+ // CK1: [[_TT1:%.+]] = load float*, float** [[_PVT]],
+ // CK1: getelementptr inbounds float, float* [[_TT1]], i32 1
+ // CK1: [[TT1:%.+]] = load i32*, i32** [[PVT]],
+ // CK1: getelementptr inbounds i32, i32* [[TT1]], i32 1
+ #pragma omp target data map(l[:10], t[:10]) use_device_ptr(l) use_device_ptr(t)
+ {
+ ++l; ++t;
+ }
+ // CK1: call void @__tgt_target_data_end{{.+}}[[MTYPE09]]
+ // CK1: [[_TTT:%.+]] = load float*, float** {{%.+}},
+ // CK1: getelementptr inbounds float, float* [[_TTT]], i32 1
+ // CK1: [[TTT:%.+]] = load i32*, i32** {{%.+}},
+ // CK1: getelementptr inbounds i32, i32* [[TTT]], i32 1
+ ++l; ++t;
+
+ // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE10]]
+ // CK1: [[_CBP:%.+]] = bitcast i8** {{%.+}} to float**
+ // CK1: [[_VAL:%.+]] = load float*, float** [[_CBP]],
+ // CK1: store float* [[_VAL]], float** [[_PVT:%.+]],
+ // CK1: [[CBP:%.+]] = bitcast i8** {{%.+}} to i32**
+ // CK1: [[VAL:%.+]] = load i32*, i32** [[CBP]],
+ // CK1: store i32* [[VAL]], i32** [[PVT:%.+]],
+ // CK1: [[_TT1:%.+]] = load float*, float** [[_PVT]],
+ // CK1: getelementptr inbounds float, float* [[_TT1]], i32 1
+ // CK1: [[TT1:%.+]] = load i32*, i32** [[PVT]],
+ // CK1: getelementptr inbounds i32, i32* [[TT1]], i32 1
+ #pragma omp target data map(l[:10], t[:10]) use_device_ptr(l,t)
+ {
+ ++l; ++t;
+ }
+ // CK1: call void @__tgt_target_data_end{{.+}}[[MTYPE10]]
+ // CK1: [[_TTT:%.+]] = load float*, float** {{%.+}},
+ // CK1: getelementptr inbounds float, float* [[_TTT]], i32 1
+ // CK1: [[TTT:%.+]] = load i32*, i32** {{%.+}},
+ // CK1: getelementptr inbounds i32, i32* [[TTT]], i32 1
+ ++l; ++t;
+
+ // CK1-DAG: [[RVAL:%.+]] = bitcast i32* [[T1:%.+]] to i8*
+ // CK1-DAG: [[T1]] = load i32*, i32** [[DECL:%.+]],
+ // CK1: [[BP:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* %{{.+}}, i32 0, i32 0
+ // CK1: store i8* [[RVAL]], i8** [[BP]],
+ // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE11]]
+ // CK1: [[CBP:%.+]] = bitcast i8** [[BP]] to i32**
+ // CK1: [[VAL:%.+]] = load i32*, i32** [[CBP]],
+ // CK1-NOT: store i32* [[VAL]], i32** [[DECL]],
+ // CK1: store i32* [[VAL]], i32** [[PVT:%.+]],
+ // CK1: [[TT1:%.+]] = load i32*, i32** [[PVT]],
+ // CK1: getelementptr inbounds i32, i32* [[TT1]], i32 1
+ #pragma omp target data map(l[:10]) use_device_ptr(t)
+ {
+ ++l; ++t;
+ }
+ // CK1: call void @__tgt_target_data_end{{.+}}[[MTYPE11]]
+ // CK1: [[TTT:%.+]] = load i32*, i32** [[DECL]],
+ // CK1: getelementptr inbounds i32, i32* [[TTT]], i32 1
+ ++l; ++t;
+
+ // CK1-DAG: [[RVAL:%.+]] = bitcast i32* [[T1:%.+]] to i8*
+ // CK1-DAG: [[T1]] = load i32*, i32** [[T2:%.+]],
+ // CK1-DAG: [[T2]] = load i32**, i32*** [[DECL:%.+]],
+ // CK1: [[BP:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* %{{.+}}, i32 0, i32 0
+ // CK1: store i8* [[RVAL]], i8** [[BP]],
+ // CK1: call void @__tgt_target_data_begin{{.+}}[[MTYPE12]]
+ // CK1: [[CBP:%.+]] = bitcast i8** [[BP]] to i32**
+ // CK1: [[VAL:%.+]] = load i32*, i32** [[CBP]],
+ // CK1: store i32* [[VAL]], i32** [[PVTV:%.+]],
+ // CK1-NOT: store i32** [[PVTV]], i32*** [[DECL]],
+ // CK1: store i32** [[PVTV]], i32*** [[PVT:%.+]],
+ // CK1: [[TT1:%.+]] = load i32**, i32*** [[PVT]],
+ // CK1: [[TT2:%.+]] = load i32*, i32** [[TT1]],
+ // CK1: getelementptr inbounds i32, i32* [[TT2]], i32 1
+ #pragma omp target data map(l[:10]) use_device_ptr(tr)
+ {
+ ++l; ++tr;
+ }
+ // CK1: call void @__tgt_target_data_end{{.+}}[[MTYPE12]]
+ // CK1: [[TTT:%.+]] = load i32**, i32*** [[DECL]],
+ // CK1: [[TTTT:%.+]] = load i32*, i32** [[TTT]],
+ // CK1: getelementptr inbounds i32, i32* [[TTTT]], i32 1
+ ++l; ++tr;
+
+}
+
+void bar(float *&a, int *&b) {
+ foo<int>(a,b);
+}
+
+#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 -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 -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
+#ifdef CK2
+
+// CK2: [[ST:%.+]] = type { double*, double** }
+// CK2: [[MTYPE00:@.+]] = {{.*}}constant [2 x i32] [i32 35, i32 83]
+// CK2: [[MTYPE01:@.+]] = {{.*}}constant [3 x i32] [i32 32, i32 19, i32 83]
+// CK2: [[MTYPE02:@.+]] = {{.*}}constant [2 x i32] [i32 96, i32 35]
+// CK2: [[MTYPE03:@.+]] = {{.*}}constant [4 x i32] [i32 96, i32 32, i32 19, i32 83]
+
+template <typename T>
+struct ST {
+ T *a;
+ double *&b;
+ ST(double *&b) : a(0), b(b) {}
+
+ // CK2-LABEL: @{{.*}}foo{{.*}}
+ void foo(double *&arg) {
+ int *la = 0;
+
+ // CK2: [[BP:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* %{{.+}}, i32 0, i32 1
+ // CK2: store i8* [[RVAL:%.+]], i8** [[BP]],
+ // CK2: call void @__tgt_target_data_begin{{.+}}[[MTYPE00]]
+ // CK2: [[CBP:%.+]] = bitcast i8** [[BP]] to double**
+ // CK2: [[VAL:%.+]] = load double*, double** [[CBP]],
+ // 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
+ #pragma omp target data map(a[:10]) use_device_ptr(a)
+ {
+ a++;
+ }
+ // CK2: call void @__tgt_target_data_end{{.+}}[[MTYPE00]]
+ // CK2: [[DECL:%.+]] = getelementptr inbounds [[ST]], [[ST]]* %this1, i32 0, i32 0
+ // CK2: [[TTT:%.+]] = load double*, double** [[DECL]],
+ // CK2: getelementptr inbounds double, double* [[TTT]], i32 1
+ a++;
+
+ // CK2: [[BP:%.+]] = getelementptr inbounds [3 x i8*], [3 x i8*]* %{{.+}}, i32 0, i32 2
+ // CK2: store i8* [[RVAL:%.+]], i8** [[BP]],
+ // CK2: call void @__tgt_target_data_begin{{.+}}[[MTYPE01]]
+ // CK2: [[CBP:%.+]] = bitcast i8** [[BP]] to double**
+ // CK2: [[VAL:%.+]] = load double*, double** [[CBP]],
+ // 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
+ #pragma omp target data map(b[:10]) use_device_ptr(b)
+ {
+ b++;
+ }
+ // CK2: call void @__tgt_target_data_end{{.+}}[[MTYPE01]]
+ // CK2: [[DECL:%.+]] = getelementptr inbounds [[ST]], [[ST]]* %{{.+}}, i32 0, i32 1
+ // CK2: [[TTT:%.+]] = load double**, double*** [[DECL]],
+ // CK2: [[TTTT:%.+]] = load double*, double** [[TTT]],
+ // CK2: getelementptr inbounds double, double* [[TTTT]], i32 1
+ b++;
+
+ // CK2: [[BP:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* %{{.+}}, i32 0, i32 0
+ // CK2: store i8* [[RVAL:%.+]], i8** [[BP]],
+ // CK2: call void @__tgt_target_data_begin{{.+}}[[MTYPE02]]
+ // CK2: [[CBP:%.+]] = bitcast i8** [[BP]] to double**
+ // CK2: [[VAL:%.+]] = load double*, double** [[CBP]],
+ // 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
+ #pragma omp target data map(la[:10]) use_device_ptr(a)
+ {
+ a++;
+ la++;
+ }
+ // CK2: call void @__tgt_target_data_end{{.+}}[[MTYPE02]]
+ // CK2: [[DECL:%.+]] = getelementptr inbounds [[ST]], [[ST]]* %this1, i32 0, i32 0
+ // CK2: [[TTT:%.+]] = load double*, double** [[DECL]],
+ // CK2: getelementptr inbounds double, double* [[TTT]], i32 1
+ a++;
+ la++;
+
+ // CK2: [[BP:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* %{{.+}}, i32 0, i32 0
+ // CK2: store i8* [[RVAL:%.+]], i8** [[BP]],
+ // CK2: [[_BP:%.+]] = getelementptr inbounds [4 x i8*], [4 x i8*]* %{{.+}}, i32 0, i32 3
+ // CK2: store i8* [[_RVAL:%.+]], i8** [[_BP]],
+ // CK2: call void @__tgt_target_data_begin{{.+}}[[MTYPE03]]
+ // CK2: [[CBP:%.+]] = bitcast i8** [[BP]] to double**
+ // CK2: [[VAL:%.+]] = load double*, double** [[CBP]],
+ // CK2: store double* [[VAL]], double** [[PVT:%.+]],
+ // CK2: store double** [[PVT]], double*** [[PVT2:%.+]],
+ // CK2: [[_CBP:%.+]] = bitcast i8** [[_BP]] to double**
+ // CK2: [[_VAL:%.+]] = load double*, double** [[_CBP]],
+ // 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: getelementptr inbounds double, double* [[_TT2]], i32 1
+ #pragma omp target data map(b[:10]) use_device_ptr(a, b)
+ {
+ a++;
+ b++;
+ }
+ // CK2: call void @__tgt_target_data_end{{.+}}[[MTYPE03]]
+ // CK2: [[DECL:%.+]] = getelementptr inbounds [[ST]], [[ST]]* %this1, i32 0, i32 0
+ // CK2: [[TTT:%.+]] = load double*, double** [[DECL]],
+ // CK2: getelementptr inbounds double, double* [[TTT]], i32 1
+ // CK2: [[_DECL:%.+]] = getelementptr inbounds [[ST]], [[ST]]* %this1, i32 0, i32 1
+ // CK2: [[_TTT:%.+]] = load double**, double*** [[_DECL]],
+ // CK2: [[_TTTT:%.+]] = load double*, double** [[_TTT]],
+ // CK2: getelementptr inbounds double, double* [[_TTTT]], i32 1
+ a++;
+ b++;
+ }
+};
+
+void bar(double *arg){
+ ST<double> A(arg);
+ A.foo(arg);
+ ++arg;
+}
+#endif
+#endif
diff --git a/test/OpenMP/target_depend_messages.cpp b/test/OpenMP/target_depend_messages.cpp
index c13a3edaf699..48bd94180c1e 100644
--- a/test/OpenMP/target_depend_messages.cpp
+++ b/test/OpenMP/target_depend_messages.cpp
@@ -66,7 +66,7 @@ int main(int argc, char **argv, char *env[]) {
foo();
#pragma omp target depend (in : argv[0:-1]) // expected-error {{section length is evaluated to a negative value -1}}
foo();
- #pragma omp target depend (in : argv[-1:0]) // expected-error {{section lower bound is evaluated to a negative value -1}}
+ #pragma omp target depend (in : argv[-1:0])
foo();
#pragma omp target depend (in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
foo();
diff --git a/test/OpenMP/target_enter_data_ast_print.cpp b/test/OpenMP/target_enter_data_ast_print.cpp
index 10ec92528499..865cc7f1c17e 100644
--- a/test/OpenMP/target_enter_data_ast_print.cpp
+++ b/test/OpenMP/target_enter_data_ast_print.cpp
@@ -1,6 +1,6 @@
-// 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 -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
// expected-no-diagnostics
#ifndef HEADER
@@ -62,8 +62,8 @@ T tmain(T argc, T *argv) {
return 0;
}
-// CHECK: template <typename T = int, int C = 5> int tmain(int argc, int *argv) {
-// CHECK-NEXT: int i, j, b, c, d, e, x[20];
+// 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) if(target enter data: j > 0)
@@ -89,8 +89,8 @@ T tmain(T argc, T *argv) {
// CHECK-NEXT: #pragma omp target enter data nowait map(alloc: x[0:10],c) depend(in : argc,argv[i:argc],x[:])
// CHECK-NEXT: #pragma omp target enter data nowait depend(in : argc,argv[i:argc],x[:]) map(to: c) map(alloc: d)
// CHECK-NEXT: #pragma omp target enter data nowait map(always,alloc: e) depend(in : argc,argv[i:argc],x[:])
-// CHECK: template <typename T = char, int C = 1> char tmain(char argc, char *argv) {
-// CHECK-NEXT: char i, j, b, c, d, e, x[20];
+// CHECK: template<> int tmain<int, 5>(int argc, int *argv) {
+// CHECK-NEXT: int 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) if(target enter data: j > 0)
@@ -116,8 +116,8 @@ T tmain(T argc, T *argv) {
// CHECK-NEXT: #pragma omp target enter data nowait map(alloc: x[0:10],c) depend(in : argc,argv[i:argc],x[:])
// CHECK-NEXT: #pragma omp target enter data nowait depend(in : argc,argv[i:argc],x[:]) map(to: c) map(alloc: d)
// CHECK-NEXT: #pragma omp target enter data nowait map(always,alloc: e) depend(in : argc,argv[i:argc],x[:])
-// CHECK: template <typename T, int C> T tmain(T argc, T *argv) {
-// CHECK-NEXT: T i, j, b, c, d, e, x[20];
+// CHECK: template<> char tmain<char, 1>(char argc, char *argv) {
+// CHECK-NEXT: char 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) if(target enter data: j > 0)
diff --git a/test/OpenMP/target_enter_data_depend_messages.cpp b/test/OpenMP/target_enter_data_depend_messages.cpp
index 84254b5c312a..4aa122355ba5 100644
--- a/test/OpenMP/target_enter_data_depend_messages.cpp
+++ b/test/OpenMP/target_enter_data_depend_messages.cpp
@@ -68,7 +68,7 @@ int tmain(T argc, S **argv, R *env[]) {
foo();
#pragma omp target enter data map(to: i) depend (in : argv[0:-1]) // expected-error {{section length is evaluated to a negative value -1}}
foo();
- #pragma omp target enter data map(to: i) depend (in : argv[-1:0]) // expected-error {{section lower bound is evaluated to a negative value -1}}
+ #pragma omp target enter data map(to: i) depend (in : argv[-1:0])
foo();
#pragma omp target enter data map(to: i) depend (in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
foo();
@@ -143,7 +143,7 @@ int main(int argc, char **argv, char *env[]) {
foo();
#pragma omp target enter data map(to: i) depend (in : argv[0:-1]) // expected-error {{section length is evaluated to a negative value -1}}
foo();
- #pragma omp target enter data map(to: i) depend (in : argv[-1:0]) // expected-error {{section lower bound is evaluated to a negative value -1}}
+ #pragma omp target enter data map(to: i) depend (in : argv[-1:0])
foo();
#pragma omp target enter data map(to: i) depend (in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
foo();
diff --git a/test/OpenMP/target_enter_data_if_messages.cpp b/test/OpenMP/target_enter_data_if_messages.cpp
index 0d18af187b19..137ff9751617 100644
--- a/test/OpenMP/target_enter_data_if_messages.cpp
+++ b/test/OpenMP/target_enter_data_if_messages.cpp
@@ -1,4 +1,4 @@
-// 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 -fopenmp-version=45 -ferror-limit 100 -o - %s
void foo() {
}
diff --git a/test/OpenMP/target_exit_data_ast_print.cpp b/test/OpenMP/target_exit_data_ast_print.cpp
index e2c6d7fd65ce..a2f5d641f3cc 100644
--- a/test/OpenMP/target_exit_data_ast_print.cpp
+++ b/test/OpenMP/target_exit_data_ast_print.cpp
@@ -1,6 +1,6 @@
-// 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 -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
// expected-no-diagnostics
#ifndef HEADER
@@ -66,8 +66,8 @@ T tmain(T argc, T *argv) {
return 0;
}
-// CHECK: template <typename T = int, int C = 5> int tmain(int argc, int *argv) {
-// CHECK-NEXT: int i, j, b, c, d, e, x[20];
+// 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) if(target exit data: j > 0)
@@ -95,8 +95,8 @@ T tmain(T argc, T *argv) {
// CHECK-NEXT: #pragma omp target exit data nowait map(release: x[0:10],c) depend(in : argc,argv[i:argc],x[:])
// CHECK-NEXT: #pragma omp target exit data nowait map(from: c) depend(in : argc,argv[i:argc],x[:]) map(release: d)
// CHECK-NEXT: #pragma omp target exit data depend(in : argc,argv[i:argc],x[:]) nowait map(always,release: e)
-// CHECK: template <typename T = char, int C = 1> char tmain(char argc, char *argv) {
-// CHECK-NEXT: char i, j, b, c, d, e, x[20];
+// CHECK: template<> int tmain<int, 5>(int argc, int *argv) {
+// CHECK-NEXT: int 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) if(target exit data: j > 0)
@@ -124,8 +124,8 @@ T tmain(T argc, T *argv) {
// CHECK-NEXT: #pragma omp target exit data nowait map(release: x[0:10],c) depend(in : argc,argv[i:argc],x[:])
// CHECK-NEXT: #pragma omp target exit data nowait map(from: c) depend(in : argc,argv[i:argc],x[:]) map(release: d)
// CHECK-NEXT: #pragma omp target exit data depend(in : argc,argv[i:argc],x[:]) nowait map(always,release: e)
-// CHECK: template <typename T, int C> T tmain(T argc, T *argv) {
-// CHECK-NEXT: T i, j, b, c, d, e, x[20];
+// CHECK: template<> char tmain<char, 1>(char argc, char *argv) {
+// CHECK-NEXT: char 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) if(target exit data: j > 0)
diff --git a/test/OpenMP/target_exit_data_depend_messages.cpp b/test/OpenMP/target_exit_data_depend_messages.cpp
index 4c59b6205f18..cdefbeed08bd 100644
--- a/test/OpenMP/target_exit_data_depend_messages.cpp
+++ b/test/OpenMP/target_exit_data_depend_messages.cpp
@@ -68,7 +68,7 @@ int tmain(T argc, S **argv, R *env[]) {
foo();
#pragma omp target exit data map(from: i) depend (in : argv[0:-1]) // expected-error {{section length is evaluated to a negative value -1}}
foo();
- #pragma omp target exit data map(from: i) depend (in : argv[-1:0]) // expected-error {{section lower bound is evaluated to a negative value -1}}
+ #pragma omp target exit data map(from: i) depend (in : argv[-1:0])
foo();
#pragma omp target exit data map(from: i) depend (in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
foo();
@@ -143,7 +143,7 @@ int main(int argc, char **argv, char *env[]) {
foo();
#pragma omp target exit data map(from: i) depend (in : argv[0:-1]) // expected-error {{section length is evaluated to a negative value -1}}
foo();
- #pragma omp target exit data map(from: i) depend (in : argv[-1:0]) // expected-error {{section lower bound is evaluated to a negative value -1}}
+ #pragma omp target exit data map(from: i) depend (in : argv[-1:0])
foo();
#pragma omp target exit data map(from: i) depend (in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
foo();
diff --git a/test/OpenMP/target_exit_data_if_messages.cpp b/test/OpenMP/target_exit_data_if_messages.cpp
index cc674e6933cc..6d5ada14e9da 100644
--- a/test/OpenMP/target_exit_data_if_messages.cpp
+++ b/test/OpenMP/target_exit_data_if_messages.cpp
@@ -1,4 +1,4 @@
-// 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 -fopenmp-version=45 -ferror-limit 100 -o - %s
void foo() {
}
diff --git a/test/OpenMP/target_if_messages.cpp b/test/OpenMP/target_if_messages.cpp
index 189256e60fea..14b6a5fbf938 100644
--- a/test/OpenMP/target_if_messages.cpp
+++ b/test/OpenMP/target_if_messages.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp -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 f519235a0b36..8e56aa24d9bd 100644
--- a/test/OpenMP/target_is_device_ptr_ast_print.cpp
+++ b/test/OpenMP/target_is_device_ptr_ast_print.cpp
@@ -172,7 +172,7 @@ T tmain(T argc) {
return 0;
}
-// CHECK: template <typename T = int> int tmain(int argc) {
+// CHECK: template<> int tmain<int>(int argc) {
// CHECK-NEXT: const int da[5] = {0};
// CHECK-NEXT: S6 h[10];
// CHECK-NEXT: auto &rh = h;
@@ -202,7 +202,7 @@ T tmain(T argc) {
// CHECK-NEXT: }
// CHECK-NEXT: #pragma omp target is_device_ptr(da)
-// CHECK: template <typename T = int *> int *tmain(int *argc) {
+// CHECK: template<> int *tmain<int *>(int *argc) {
// CHECK-NEXT: int *const da[5] = {0};
// CHECK-NEXT: S6 h[10];
// CHECK-NEXT: auto &rh = h;
diff --git a/test/OpenMP/target_is_device_ptr_codegen.cpp b/test/OpenMP/target_is_device_ptr_codegen.cpp
new file mode 100644
index 000000000000..6c807294835a
--- /dev/null
+++ b/test/OpenMP/target_is_device_ptr_codegen.cpp
@@ -0,0 +1,293 @@
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+
+///==========================================================================///
+// 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 -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 -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
+#ifdef CK1
+
+double *g;
+
+// CK1: @g = global double*
+// CK1: [[SIZES00:@.+]] = {{.+}}constant [1 x i[[sz:64|32]]] [i{{64|32}} {{8|4}}]
+// CK1: [[TYPES00:@.+]] = {{.+}}constant [1 x i32] [i32 288]
+
+// CK1: [[SIZES01:@.+]] = {{.+}}constant [1 x i[[sz]]] [i[[sz]] {{8|4}}]
+// CK1: [[TYPES01:@.+]] = {{.+}}constant [1 x i32] [i32 288]
+
+// CK1: [[SIZES02:@.+]] = {{.+}}constant [1 x i[[sz]]] [i[[sz]] {{8|4}}]
+// CK1: [[TYPES02:@.+]] = {{.+}}constant [1 x i32] [i32 288]
+
+// CK1: [[SIZES03:@.+]] = {{.+}}constant [1 x i[[sz]]] [i[[sz]] {{8|4}}]
+// CK1: [[TYPES03:@.+]] = {{.+}}constant [1 x i32] [i32 288]
+
+// CK1: [[SIZES04:@.+]] = {{.+}}constant [1 x i[[sz]]] [i[[sz]] {{8|4}}]
+// CK1: [[TYPES04:@.+]] = {{.+}}constant [1 x i32] [i32 288]
+
+// CK1: [[SIZES05:@.+]] = {{.+}}constant [1 x i[[sz]]] [i[[sz]] {{8|4}}]
+// CK1: [[TYPES05:@.+]] = {{.+}}constant [1 x i32] [i32 288]
+
+// CK1: [[SIZES06:@.+]] = {{.+}}constant [2 x i[[sz]]] [i[[sz]] {{8|4}}, i[[sz]] {{8|4}}]
+// CK1: [[TYPES06:@.+]] = {{.+}}constant [2 x i32] [i32 288, i32 288]
+
+// CK1-LABEL: @_Z3foo
+template<typename T>
+void foo(float *&lr, T *&tr) {
+ float *l;
+ T *t;
+
+ // CK1-DAG: call i32 @__tgt_target(i32 {{.+}}, i8* {{.+}}, i32 1, i8** [[BPGEP:%[0-9]+]], i8** [[PGEP:%[0-9]+]], {{.+}}[[SIZES00]]{{.+}}, {{.+}}[[TYPES00]]{{.+}})
+ // CK1-DAG: [[BPGEP]] = getelementptr inbounds {{.+}}[[BPS:%[^,]+]], i32 0, i32 0
+ // CK1-DAG: [[PGEP]] = getelementptr inbounds {{.+}}[[PS:%[^,]+]], i32 0, i32 0
+ // CK1-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 0
+ // CK1-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 0
+ // CK1-DAG: store i8* [[VALBP:%.+]], i8** [[BP1]],
+ // CK1-DAG: store i8* [[VALP:%.+]], i8** [[P1]],
+ // CK1-DAG: [[VALBP]] = bitcast double* [[VAL:%.+]] to i8*
+ // CK1-DAG: [[VALP]] = bitcast double* [[VAL]] to i8*
+ // CK1-DAG: [[VAL]] = load double*, double** [[ADDR:@g]],
+
+ // CK1: call void [[KERNEL:@.+]](double* [[VAL]])
+ #pragma omp target is_device_ptr(g)
+ {
+ ++g;
+ }
+
+ // CK1-DAG: call i32 @__tgt_target(i32 {{.+}}, i8* {{.+}}, i32 1, i8** [[BPGEP:%[0-9]+]], i8** [[PGEP:%[0-9]+]], {{.+}}[[SIZES01]]{{.+}}, {{.+}}[[TYPES01]]{{.+}})
+ // CK1-DAG: [[BPGEP]] = getelementptr inbounds {{.+}}[[BPS:%[^,]+]], i32 0, i32 0
+ // CK1-DAG: [[PGEP]] = getelementptr inbounds {{.+}}[[PS:%[^,]+]], i32 0, i32 0
+ // CK1-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 0
+ // CK1-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 0
+ // CK1-DAG: store i8* [[VALBP:%.+]], i8** [[BP1]],
+ // CK1-DAG: store i8* [[VALP:%.+]], i8** [[P1]],
+ // CK1-DAG: [[VALBP]] = bitcast float* [[VAL:%.+]] to i8*
+ // CK1-DAG: [[VALP]] = bitcast float* [[VAL]] to i8*
+ // CK1-DAG: [[VAL]] = load float*, float** [[ADDR:%.+]],
+
+ // CK1: call void [[KERNEL:@.+]](float* [[VAL]])
+ #pragma omp target is_device_ptr(l)
+ {
+ ++l;
+ }
+
+ // CK1-DAG: call i32 @__tgt_target(i32 {{.+}}, i8* {{.+}}, i32 1, i8** [[BPGEP:%[0-9]+]], i8** [[PGEP:%[0-9]+]], {{.+}}[[SIZES02]]{{.+}}, {{.+}}[[TYPES02]]{{.+}})
+ // CK1-DAG: [[BPGEP]] = getelementptr inbounds {{.+}}[[BPS:%[^,]+]], i32 0, i32 0
+ // CK1-DAG: [[PGEP]] = getelementptr inbounds {{.+}}[[PS:%[^,]+]], i32 0, i32 0
+ // CK1-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 0
+ // CK1-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 0
+ // CK1-DAG: store i8* [[VALBP:%.+]], i8** [[BP1]],
+ // CK1-DAG: store i8* [[VALP:%.+]], i8** [[P1]],
+ // CK1-DAG: [[VALBP]] = bitcast i32* [[VAL:%.+]] to i8*
+ // CK1-DAG: [[VALP]] = bitcast i32* [[VAL]] to i8*
+ // CK1-DAG: [[VAL]] = load i32*, i32** [[ADDR:%.+]],
+
+ // CK1: call void [[KERNEL:@.+]](i32* [[VAL]])
+ #pragma omp target is_device_ptr(t)
+ {
+ ++t;
+ }
+
+ // CK1-DAG: call i32 @__tgt_target(i32 {{.+}}, i8* {{.+}}, i32 1, i8** [[BPGEP:%[0-9]+]], i8** [[PGEP:%[0-9]+]], {{.+}}[[SIZES03]]{{.+}}, {{.+}}[[TYPES03]]{{.+}})
+ // CK1-DAG: [[BPGEP]] = getelementptr inbounds {{.+}}[[BPS:%[^,]+]], i32 0, i32 0
+ // CK1-DAG: [[PGEP]] = getelementptr inbounds {{.+}}[[PS:%[^,]+]], i32 0, i32 0
+ // CK1-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 0
+ // CK1-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 0
+ // CK1-DAG: store i8* [[VALBP:%.+]], i8** [[BP1]],
+ // CK1-DAG: store i8* [[VALP:%.+]], i8** [[P1]],
+ // CK1-DAG: [[VALBP]] = bitcast float* [[VAL:%.+]] to i8*
+ // CK1-DAG: [[VALP]] = bitcast float* [[VAL]] to i8*
+ // CK1-DAG: [[VAL]] = load float*, float** [[ADDR:%.+]],
+ // CK1-DAG: [[ADDR]] = load float**, float*** [[ADDR2:%.+]],
+
+ // CK1: call void [[KERNEL:@.+]](float* [[VAL]])
+ #pragma omp target is_device_ptr(lr)
+ {
+ ++lr;
+ }
+
+ // CK1-DAG: call i32 @__tgt_target(i32 {{.+}}, i8* {{.+}}, i32 1, i8** [[BPGEP:%[0-9]+]], i8** [[PGEP:%[0-9]+]], {{.+}}[[SIZES04]]{{.+}}, {{.+}}[[TYPES04]]{{.+}})
+ // CK1-DAG: [[BPGEP]] = getelementptr inbounds {{.+}}[[BPS:%[^,]+]], i32 0, i32 0
+ // CK1-DAG: [[PGEP]] = getelementptr inbounds {{.+}}[[PS:%[^,]+]], i32 0, i32 0
+ // CK1-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 0
+ // CK1-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 0
+ // CK1-DAG: store i8* [[VALBP:%.+]], i8** [[BP1]],
+ // CK1-DAG: store i8* [[VALP:%.+]], i8** [[P1]],
+ // CK1-DAG: [[VALBP]] = bitcast i32* [[VAL:%.+]] to i8*
+ // CK1-DAG: [[VALP]] = bitcast i32* [[VAL]] to i8*
+ // CK1-DAG: [[VAL]] = load i32*, i32** [[ADDR:%.+]],
+ // CK1-DAG: [[ADDR]] = load i32**, i32*** [[ADDR2:%.+]],
+
+ // CK1: call void [[KERNEL:@.+]](i32* [[VAL]])
+ #pragma omp target is_device_ptr(tr)
+ {
+ ++tr;
+ }
+
+ // CK1-DAG: call i32 @__tgt_target(i32 {{.+}}, i8* {{.+}}, i32 1, i8** [[BPGEP:%[0-9]+]], i8** [[PGEP:%[0-9]+]], {{.+}}[[SIZES05]]{{.+}}, {{.+}}[[TYPES05]]{{.+}})
+ // CK1-DAG: [[BPGEP]] = getelementptr inbounds {{.+}}[[BPS:%[^,]+]], i32 0, i32 0
+ // CK1-DAG: [[PGEP]] = getelementptr inbounds {{.+}}[[PS:%[^,]+]], i32 0, i32 0
+ // CK1-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 0
+ // CK1-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 0
+ // CK1-DAG: store i8* [[VALBP:%.+]], i8** [[BP1]],
+ // CK1-DAG: store i8* [[VALP:%.+]], i8** [[P1]],
+ // CK1-DAG: [[VALBP]] = bitcast i32* [[VAL:%.+]] to i8*
+ // CK1-DAG: [[VALP]] = bitcast i32* [[VAL]] to i8*
+ // CK1-DAG: [[VAL]] = load i32*, i32** [[ADDR:%.+]],
+ // CK1-DAG: [[ADDR]] = load i32**, i32*** [[ADDR2:%.+]],
+
+ // CK1: call void [[KERNEL:@.+]](i32* [[VAL]])
+ #pragma omp target is_device_ptr(tr,lr)
+ {
+ ++tr;
+ }
+
+ // CK1-DAG: call i32 @__tgt_target(i32 {{.+}}, i8* {{.+}}, i32 2, i8** [[BPGEP:%[0-9]+]], i8** [[PGEP:%[0-9]+]], {{.+}}[[SIZES06]]{{.+}}, {{.+}}[[TYPES06]]{{.+}})
+ // CK1-DAG: [[BPGEP]] = getelementptr inbounds {{.+}}[[BPS:%[^,]+]], i32 0, i32 0
+ // CK1-DAG: [[PGEP]] = getelementptr inbounds {{.+}}[[PS:%[^,]+]], i32 0, i32 0
+ // CK1-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 0
+ // CK1-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 0
+ // CK1-DAG: store i8* [[VALBP:%.+]], i8** [[BP1]],
+ // CK1-DAG: store i8* [[VALP:%.+]], i8** [[P1]],
+ // CK1-DAG: [[VALBP]] = bitcast i32* [[VAL:%.+]] to i8*
+ // CK1-DAG: [[VALP]] = bitcast i32* [[VAL]] to i8*
+ // CK1-DAG: [[VAL]] = load i32*, i32** [[ADDR:%.+]],
+ // CK1-DAG: [[ADDR]] = load i32**, i32*** [[ADDR2:%.+]],
+
+ // CK1-DAG: [[_BP1:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 1
+ // CK1-DAG: [[_P1:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 1
+ // CK1-DAG: store i8* [[_VALBP:%.+]], i8** [[_BP1]],
+ // CK1-DAG: store i8* [[_VALP:%.+]], i8** [[_P1]],
+ // CK1-DAG: [[_VALBP]] = bitcast float* [[_VAL:%.+]] to i8*
+ // CK1-DAG: [[_VALP]] = bitcast float* [[_VAL]] to i8*
+ // CK1-DAG: [[_VAL]] = load float*, float** [[_ADDR:%.+]],
+ // CK1-DAG: [[_ADDR]] = load float**, float*** [[_ADDR2:%.+]],
+
+ // CK1: call void [[KERNEL:@.+]](i32* [[VAL]], float* [[_VAL]])
+ #pragma omp target is_device_ptr(tr,lr)
+ {
+ ++tr,++lr;
+ }
+}
+
+void bar(float *&a, int *&b) {
+ foo<int>(a,b);
+}
+
+#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 -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 -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
+#ifdef CK2
+
+// CK2: [[ST:%.+]] = type { double*, double** }
+
+// CK2: [[SIZE00:@.+]] = {{.+}}constant [1 x i[[sz:64|32]]] [i{{64|32}} {{8|4}}]
+// CK2: [[MTYPE00:@.+]] = {{.+}}constant [1 x i32] [i32 33]
+
+// CK2: [[SIZE01:@.+]] = {{.+}}constant [2 x i[[sz]]] [i[[sz]] {{8|4}}, i[[sz]] {{8|4}}]
+// CK2: [[MTYPE01:@.+]] = {{.+}}constant [2 x i32] [i32 32, i32 17]
+
+// CK2: [[SIZE02:@.+]] = {{.+}}constant [3 x i[[sz]]] [i[[sz]] {{8|4}}, i[[sz]] {{8|4}}, i[[sz]] {{8|4}}]
+// CK2: [[MTYPE02:@.+]] = {{.+}}constant [3 x i32] [i32 33, i32 0, i32 17]
+
+template <typename T>
+struct ST {
+ T *a;
+ double *&b;
+ ST(double *&b) : a(0), b(b) {}
+
+ // CK2-LABEL: @{{.*}}foo{{.*}}
+ void foo(double *&arg) {
+ int *la = 0;
+
+ // CK2-DAG: call i32 @__tgt_target(i32 {{[^,]+}}, i8* {{[^,]+}}, i32 1, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[SIZE00]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[MTYPE00]]{{.+}})
+ // 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: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]]
+ // CK2-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]]
+ // CK2-DAG: [[CBPVAL0]] = bitcast [[ST]]* [[VAR0:%.+]] to i8*
+ // CK2-DAG: [[CPVAL0]] = bitcast double** [[SEC0:%.+]] to i8*
+ // CK2-DAG: [[SEC0]] = getelementptr {{.*}}[[ST]]* [[VAR0]], i{{.+}} 0, i{{.+}} 0
+ #pragma omp target is_device_ptr(a)
+ {
+ a++;
+ }
+
+ // CK2-DAG: call i32 @__tgt_target(i32 {{[^,]+}}, i8* {{[^,]+}}, i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[SIZE01]], {{.+}}getelementptr {{.+}}[2 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: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]]
+ // CK2-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]]
+ // CK2-DAG: [[CBPVAL0]] = bitcast [[ST]]* [[VAR0:%.+]] to i8*
+ // CK2-DAG: [[CPVAL0]] = bitcast double*** [[SEC0:%.+]] to i8*
+ // 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: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]]
+ // CK2-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]]
+ // CK2-DAG: [[CBPVAL1]] = bitcast double*** [[SEC0]] to i8*
+ // CK2-DAG: [[CPVAL1]] = bitcast double** [[SEC1:%.+]] to i8*
+ // CK2-DAG: [[SEC1]] = load double**, double*** [[SEC0]]
+ #pragma omp target is_device_ptr(b)
+ {
+ b++;
+ }
+
+ // CK2-DAG: call i32 @__tgt_target(i32 {{[^,]+}}, i8* {{[^,]+}}, i32 3, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[3 x i{{.+}}]* [[SIZE02]], {{.+}}getelementptr {{.+}}[3 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: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]]
+ // CK2-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]]
+ // CK2-DAG: [[CBPVAL0]] = bitcast [[ST]]* [[VAR0:%.+]] to i8*
+ // CK2-DAG: [[CPVAL0]] = bitcast double*** [[SEC0:%.+]] to i8*
+ // 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: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]]
+ // CK2-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]]
+ // CK2-DAG: [[CBPVAL1]] = bitcast double*** [[SEC0]] to i8*
+ // CK2-DAG: [[CPVAL1]] = bitcast double** [[SEC1:%.+]] to i8*
+ // 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: store i8* [[CBPVAL2:%[^,]+]], i8** [[BP2]]
+ // CK2-DAG: store i8* [[CPVAL2:%[^,]+]], i8** [[P2]]
+ // CK2-DAG: [[CBPVAL2]] = bitcast [[ST]]* [[VAR2:%.+]] to i8*
+ // CK2-DAG: [[CPVAL2]] = bitcast double** [[SEC2:%.+]] to i8*
+ // CK2-DAG: [[SEC2]] = getelementptr {{.*}}[[ST]]* [[VAR2]], i{{.+}} 0, i{{.+}} 0
+ #pragma omp target is_device_ptr(a, b)
+ {
+ a++;
+ b++;
+ }
+ }
+};
+
+void bar(double *arg){
+ ST<double> A(arg);
+ A.foo(arg);
+ ++arg;
+}
+#endif
+#endif
diff --git a/test/OpenMP/target_is_device_ptr_messages.cpp b/test/OpenMP/target_is_device_ptr_messages.cpp
index 634e16114e1b..8cd1426081ab 100644
--- a/test/OpenMP/target_is_device_ptr_messages.cpp
+++ b/test/OpenMP/target_is_device_ptr_messages.cpp
@@ -142,6 +142,7 @@ T tmain(T argc) {
T *&z = k;
T aa[10];
auto &raa = aa;
+ S6 *ps;
#pragma omp target is_device_ptr // expected-error {{expected '(' after 'is_device_ptr'}}
{}
#pragma omp target is_device_ptr( // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}}
@@ -178,6 +179,22 @@ T tmain(T argc) {
{}
#pragma omp target is_device_ptr(da) // OK
{}
+#pragma omp target map(ps) is_device_ptr(ps) // expected-error{{variable already marked as mapped in current construct}} expected-note{{used here}}
+ {}
+#pragma omp target is_device_ptr(ps) map(ps) // expected-error{{variable already marked as mapped in current construct}} expected-note{{used here}}
+ {}
+#pragma omp target map(ps->a) is_device_ptr(ps) // expected-error{{variable already marked as mapped in current construct}} expected-note{{used here}}
+ {}
+#pragma omp target is_device_ptr(ps) map(ps->a) // expected-error{{pointer cannot be mapped along with a section derived from itself}} expected-note{{used here}}
+ {}
+#pragma omp target is_device_ptr(ps) firstprivate(ps) // expected-error{{firstprivate variable cannot be in a is_device_ptr clause in '#pragma omp target' directive}}
+ {}
+#pragma omp target firstprivate(ps) is_device_ptr(ps) // expected-error{{firstprivate variable cannot be in a is_device_ptr clause in '#pragma omp target' directive}} expected-note{{defined as firstprivate}}
+ {}
+#pragma omp target is_device_ptr(ps) private(ps) // expected-error{{private variable cannot be in a is_device_ptr clause in '#pragma omp target' directive}}
+ {}
+#pragma omp target private(ps) is_device_ptr(ps) // expected-error{{private variable cannot be in a is_device_ptr clause in '#pragma omp target' directive}} expected-note{{defined as private}}
+ {}
return 0;
}
@@ -194,6 +211,7 @@ int main(int argc, char **argv) {
int *&z = k;
int aa[10];
auto &raa = aa;
+ S6 *ps;
#pragma omp target is_device_ptr // expected-error {{expected '(' after 'is_device_ptr'}}
{}
#pragma omp target is_device_ptr( // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}}
@@ -230,5 +248,21 @@ int main(int argc, char **argv) {
{}
#pragma omp target is_device_ptr(da) // OK
{}
+#pragma omp target map(ps) is_device_ptr(ps) // expected-error{{variable already marked as mapped in current construct}} expected-note{{used here}}
+ {}
+#pragma omp target is_device_ptr(ps) map(ps) // expected-error{{variable already marked as mapped in current construct}} expected-note{{used here}}
+ {}
+#pragma omp target map(ps->a) is_device_ptr(ps) // expected-error{{variable already marked as mapped in current construct}} expected-note{{used here}}
+ {}
+#pragma omp target is_device_ptr(ps) map(ps->a) // expected-error{{pointer cannot be mapped along with a section derived from itself}} expected-note{{used here}}
+ {}
+#pragma omp target is_device_ptr(ps) firstprivate(ps) // expected-error{{firstprivate variable cannot be in a is_device_ptr clause in '#pragma omp target' directive}}
+ {}
+#pragma omp target firstprivate(ps) is_device_ptr(ps) // expected-error{{firstprivate variable cannot be in a is_device_ptr clause in '#pragma omp target' directive}} expected-note{{defined as firstprivate}}
+ {}
+#pragma omp target is_device_ptr(ps) private(ps) // expected-error{{private variable cannot be in a is_device_ptr clause in '#pragma omp target' directive}}
+ {}
+#pragma omp target private(ps) is_device_ptr(ps) // expected-error{{private variable cannot be in a is_device_ptr clause in '#pragma omp target' directive}} expected-note{{defined as private}}
+ {}
return tmain<int, 3>(argc); // expected-note {{in instantiation of function template specialization 'tmain<int, 3>' requested here}}
}
diff --git a/test/OpenMP/target_map_codegen.cpp b/test/OpenMP/target_map_codegen.cpp
index 678e774566c1..72c7257a0ea7 100644
--- a/test/OpenMP/target_map_codegen.cpp
+++ b/test/OpenMP/target_map_codegen.cpp
@@ -60,12 +60,15 @@ void implicit_maps_integer (int a){
// 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
#ifdef CK2
-// CK2-DAG: [[SIZES:@.+]] = {{.+}}constant [1 x i[[sz:64|32]]] [i{{64|32}} 4]
+// 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-DAG: [[TYPES:@.+]] = {{.+}}constant [1 x i32] [i32 288]
+// CK2: [[TYPES:@.+]] = {{.+}}constant [1 x i32] [i32 288]
+// CK2: [[SIZES2:@.+]] = {{.+}}constant [1 x i[[sz]]] zeroinitializer
+// Map types: OMP_MAP_IS_PTR = 32
+// CK2: [[TYPES2:@.+]] = {{.+}}constant [1 x i32] [i32 32]
-// CK2-LABEL: implicit_maps_integer_reference
-void implicit_maps_integer_reference (int a){
+// CK2-LABEL: implicit_maps_reference
+void implicit_maps_reference (int a, int *b){
int &i = a;
// CK2-DAG: call i32 @__tgt_target(i32 {{.+}}, i8* {{.+}}, i32 1, i8** [[BPGEP:%[0-9]+]], i8** [[PGEP:%[0-9]+]], {{.+}}[[SIZES]]{{.+}}, {{.+}}[[TYPES]]{{.+}})
// CK2-DAG: [[BPGEP]] = getelementptr inbounds {{.+}}[[BPS:%[^,]+]], i32 0, i32 0
@@ -85,6 +88,25 @@ void implicit_maps_integer_reference (int a){
{
++i;
}
+
+ int *&p = b;
+ // CK2-DAG: call i32 @__tgt_target(i32 {{.+}}, i8* {{.+}}, i32 1, i8** [[BPGEP:%[0-9]+]], i8** [[PGEP:%[0-9]+]], {{.+}}[[SIZES2]]{{.+}}, {{.+}}[[TYPES2]]{{.+}})
+ // CK2-DAG: [[BPGEP]] = getelementptr inbounds {{.+}}[[BPS:%[^,]+]], i32 0, i32 0
+ // CK2-DAG: [[PGEP]] = getelementptr inbounds {{.+}}[[PS:%[^,]+]], i32 0, i32 0
+ // CK2-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BPS]], i32 0, i32 0
+ // CK2-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[PS]], i32 0, i32 0
+ // CK2-DAG: store i8* [[VALBP:%.+]], i8** [[BP1]],
+ // CK2-DAG: store i8* [[VALP:%.+]], i8** [[P1]],
+ // CK2-DAG: [[VALBP]] = bitcast i32* [[VAL:%.+]] to i8*
+ // CK2-DAG: [[VALP]] = bitcast i32* [[VAL]] to i8*
+ // CK2-DAG: [[VAL]] = load i32*, i32** [[ADDR:%.+]],
+ // CK2-DAG: [[ADDR]] = load i32**, i32*** [[ADDR2:%.+]],
+
+ // CK2: call void [[KERNEL2:@.+]](i32* [[VAL]])
+ #pragma omp target
+ {
+ ++p;
+ }
}
// CK2: define internal void [[KERNEL]](i[[sz]] [[ARG:%.+]])
@@ -99,6 +121,14 @@ void implicit_maps_integer_reference (int a){
// CK2-32: [[RVAL:%.+]] = load i32*, i32** [[REF]],
// CK2-32: {{.+}} = load i32, i32* [[RVAL]],
+// CK2: define internal void [[KERNEL2]](i32* [[ARG:%.+]])
+// CK2: [[ADDR:%.+]] = alloca i32*,
+// CK2: [[REF:%.+]] = alloca i32**,
+// CK2: store i32* [[ARG]], i32** [[ADDR]],
+// CK2: store i32** [[ADDR]], i32*** [[REF]],
+// CK2: [[T:%.+]] = load i32**, i32*** [[REF]],
+// CK2: [[TT:%.+]] = load i32*, i32** [[T]],
+// 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
@@ -4473,4 +4503,256 @@ void zero_size_section_and_private_maps (int ii){
// CK27: define {{.+}}[[CALL06]]
// 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 -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 -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
+#ifdef CK28
+
+// CK28: [[SIZE00:@.+]] = private {{.*}}constant [1 x i[[Z:64|32]]] [i[[Z:64|32]] {{8|4}}]
+// CK28: [[MTYPE00:@.+]] = private {{.*}}constant [1 x i32] [i32 35]
+
+// CK28: [[SIZE01:@.+]] = private {{.*}}constant [1 x i[[Z]]] [i[[Z]] 400]
+// CK28: [[MTYPE01:@.+]] = private {{.*}}constant [1 x i32] [i32 35]
+
+// CK28-LABEL: explicit_maps_pointer_references
+void explicit_maps_pointer_references (int *p){
+ int *&a = p;
+
+ // Region 00
+ // CK28-DAG: call i32 @__tgt_target(i32 {{[^,]+}}, i8* {{[^,]+}}, i32 1, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[SIZE00]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[MTYPE00]]{{.+}})
+ // CK28-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]]
+ // CK28-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
+
+ // CK28-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
+ // CK28-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
+ // CK28-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]]
+ // CK28-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]]
+ // CK28-DAG: [[CBPVAL0]] = bitcast i32** [[VAR0:%.+]] to i8*
+ // CK28-DAG: [[CPVAL0]] = bitcast i32** [[VAR1:%.+]] to i8*
+ // CK28-DAG: [[VAR0]] = load i32**, i32*** [[VAR00:%.+]],
+ // CK28-DAG: [[VAR1]] = load i32**, i32*** [[VAR11:%.+]],
+
+ // CK28: call void [[CALL00:@.+]](i32** {{[^,]+}})
+ #pragma omp target map(a)
+ {
+ ++a;
+ }
+
+ // Region 01
+ // CK28-DAG: call i32 @__tgt_target(i32 {{[^,]+}}, i8* {{[^,]+}}, i32 1, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[SIZE01]], {{.+}}getelementptr {{.+}}[1 x i{{.+}}]* [[MTYPE01]]{{.+}})
+ // CK28-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]]
+ // CK28-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
+
+ // CK28-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
+ // CK28-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
+ // CK28-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]]
+ // CK28-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]]
+ // CK28-DAG: [[CBPVAL0]] = bitcast i32* [[VAR0:%.+]] to i8*
+ // CK28-DAG: [[CPVAL0]] = bitcast i32* [[VAR1:%.+]] to i8*
+ // CK28-DAG: [[VAR0]] = load i32*, i32** [[VAR00:%.+]],
+ // CK28-DAG: [[VAR00]] = load i32**, i32*** [[VAR000:%.+]],
+ // CK28-DAG: [[VAR1]] = getelementptr inbounds i32, i32* [[VAR11:%.+]], i{{64|32}} 2
+ // CK28-DAG: [[VAR11]] = load i32*, i32** [[VAR111:%.+]],
+ // CK28-DAG: [[VAR111]] = load i32**, i32*** [[VAR1111:%.+]],
+
+ // CK28: call void [[CALL01:@.+]](i32* {{[^,]+}})
+ #pragma omp target map(a[2:100])
+ {
+ ++a;
+ }
+}
+#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 -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 -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
+#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 i32] [i32 35, i32 16, i32 19, i32 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 i32] [i32 32, i32 19, i32 19, i32 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 i32] [i32 32, i32 19, i32 16, i32 19, i32 19]
+
+struct SSA{
+ double *p;
+ double *&pr;
+ SSA(double *&pr) : pr(pr) {}
+};
+
+struct SSB{
+ SSA *p;
+ SSA *&pr;
+ SSB(SSA *&pr) : pr(pr) {}
+
+ // CK29-LABEL: define {{.+}}foo
+ void foo() {
+
+ // Region 00
+ // CK29-DAG: call i32 @__tgt_target(i32 {{[^,]+}}, i8* {{[^,]+}}, i32 4, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[4 x i{{.+}}]* [[SIZE00]], {{.+}}getelementptr {{.+}}[4 x i{{.+}}]* [[MTYPE00]]{{.+}})
+
+ // CK29-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]]
+ // CK29-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
+
+ // CK29-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
+ // CK29-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
+ // CK29-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]]
+ // CK29-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]]
+ // CK29-DAG: [[CBPVAL0]] = bitcast [[SSB]]* [[VAR0:%.+]] to i8*
+ // CK29-DAG: [[CPVAL0]] = bitcast [[SSA]]** [[VAR00:%.+]] to i8*
+ // 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: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]]
+ // CK29-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]]
+ // CK29-DAG: [[CBPVAL1]] = bitcast [[SSA]]** [[VAR00]] to i8*
+ // CK29-DAG: [[CPVAL1]] = bitcast double*** [[VAR1:%.+]] to i8*
+ // CK29-DAG: [[VAR1]] = 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: store i8* [[CBPVAL2:%[^,]+]], i8** [[BP2]]
+ // CK29-DAG: store i8* [[CPVAL2:%[^,]+]], i8** [[P2]]
+ // CK29-DAG: [[CBPVAL2]] = bitcast double*** [[VAR1]] to i8*
+ // CK29-DAG: [[CPVAL2]] = bitcast double** [[VAR2:%.+]] to i8*
+ // 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: store i8* [[CBPVAL3:%[^,]+]], i8** [[BP3]]
+ // CK29-DAG: store i8* [[CPVAL3:%[^,]+]], i8** [[P3]]
+ // CK29-DAG: [[CBPVAL3]] = bitcast double** [[VAR2]] to i8*
+ // CK29-DAG: [[CPVAL3]] = bitcast double* [[VAR3:%.+]] to i8*
+ // CK29-DAG: [[VAR3]] = getelementptr inbounds double, double* [[VAR33:%.+]], i{{.+}} 0
+ // CK29-DAG: [[VAR33]] = load double*, double** %{{.+}},
+
+ // CK29: call void [[CALL00:@.+]]([[SSB]]* {{[^,]+}})
+ #pragma omp target map(p->pr[:10])
+ {
+ p->pr++;
+ }
+
+ // Region 01
+ // CK29-DAG: call i32 @__tgt_target(i32 {{[^,]+}}, i8* {{[^,]+}}, i32 4, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[4 x i{{.+}}]* [[SIZE01]], {{.+}}getelementptr {{.+}}[4 x i{{.+}}]* [[MTYPE01]]{{.+}})
+
+ // CK29-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]]
+ // CK29-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
+
+ // CK29-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
+ // CK29-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
+ // CK29-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]]
+ // CK29-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]]
+ // CK29-DAG: [[CBPVAL0]] = bitcast [[SSB]]* [[VAR0:%.+]] to i8*
+ // CK29-DAG: [[CPVAL0]] = bitcast [[SSA]]*** [[VAR00:%.+]] to i8*
+ // CK29-DAG: [[VAR00]] = 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: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]]
+ // CK29-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]]
+ // CK29-DAG: [[CBPVAL1]] = bitcast [[SSA]]*** [[VAR00]] to i8*
+ // CK29-DAG: [[CPVAL1]] = bitcast [[SSA]]** [[VAR1:%.+]] to i8*
+ // CK29-DAG: [[VAR1]] = load [[SSA]]**, [[SSA]]*** [[VAR00]],
+
+ // CK29-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2
+ // CK29-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2
+ // CK29-DAG: store i8* [[CBPVAL2:%[^,]+]], i8** [[BP2]]
+ // CK29-DAG: store i8* [[CPVAL2:%[^,]+]], i8** [[P2]]
+ // CK29-DAG: [[CBPVAL2]] = bitcast [[SSA]]** [[VAR1]] to i8*
+ // CK29-DAG: [[CPVAL2]] = bitcast double** [[VAR2:%.+]] to i8*
+ // 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: store i8* [[CBPVAL3:%[^,]+]], i8** [[BP3]]
+ // CK29-DAG: store i8* [[CPVAL3:%[^,]+]], i8** [[P3]]
+ // CK29-DAG: [[CBPVAL3]] = bitcast double** [[VAR2]] to i8*
+ // CK29-DAG: [[CPVAL3]] = bitcast double* [[VAR3:%.+]] to i8*
+ // CK29-DAG: [[VAR3]] = getelementptr inbounds double, double* [[VAR33:%.+]], i{{.+}} 0
+ // CK29-DAG: [[VAR33]] = load double*, double** %{{.+}},
+
+ // CK29: call void [[CALL00:@.+]]([[SSB]]* {{[^,]+}})
+ #pragma omp target map(pr->p[:10])
+ {
+ pr->p++;
+ }
+
+ // Region 02
+ // CK29-DAG: call i32 @__tgt_target(i32 {{[^,]+}}, i8* {{[^,]+}}, i32 5, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[5 x i{{.+}}]* [[SIZE02]], {{.+}}getelementptr {{.+}}[5 x i{{.+}}]* [[MTYPE02]]{{.+}})
+
+ // CK29-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]]
+ // CK29-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]]
+
+ // CK29-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0
+ // CK29-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0
+ // CK29-DAG: store i8* [[CBPVAL0:%[^,]+]], i8** [[BP0]]
+ // CK29-DAG: store i8* [[CPVAL0:%[^,]+]], i8** [[P0]]
+ // CK29-DAG: [[CBPVAL0]] = bitcast [[SSB]]* [[VAR0:%.+]] to i8*
+ // CK29-DAG: [[CPVAL0]] = bitcast [[SSA]]*** [[VAR00:%.+]] to i8*
+ // CK29-DAG: [[VAR00]] = 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: store i8* [[CBPVAL1:%[^,]+]], i8** [[BP1]]
+ // CK29-DAG: store i8* [[CPVAL1:%[^,]+]], i8** [[P1]]
+ // CK29-DAG: [[CBPVAL1]] = bitcast [[SSA]]*** [[VAR00]] to i8*
+ // CK29-DAG: [[CPVAL1]] = bitcast [[SSA]]** [[VAR1:%.+]] to i8*
+ // CK29-DAG: [[VAR1]] = load [[SSA]]**, [[SSA]]*** [[VAR00]],
+
+ // CK29-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2
+ // CK29-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2
+ // CK29-DAG: store i8* [[CBPVAL2:%[^,]+]], i8** [[BP2]]
+ // CK29-DAG: store i8* [[CPVAL2:%[^,]+]], i8** [[P2]]
+ // CK29-DAG: [[CBPVAL2]] = bitcast [[SSA]]** [[VAR1]] to i8*
+ // CK29-DAG: [[CPVAL2]] = bitcast double*** [[VAR2:%.+]] to i8*
+ // 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: store i8* [[CBPVAL3:%[^,]+]], i8** [[BP3]]
+ // CK29-DAG: store i8* [[CPVAL3:%[^,]+]], i8** [[P3]]
+ // CK29-DAG: [[CBPVAL3]] = bitcast double*** [[VAR2]] to i8*
+ // CK29-DAG: [[CPVAL3]] = bitcast double** [[VAR3:%.+]] to i8*
+ // 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: store i8* [[CBPVAL4:%[^,]+]], i8** [[BP4]]
+ // CK29-DAG: store i8* [[CPVAL4:%[^,]+]], i8** [[P4]]
+ // CK29-DAG: [[CBPVAL4]] = bitcast double** [[VAR3]] to i8*
+ // CK29-DAG: [[CPVAL4]] = bitcast double* [[VAR4:%.+]] to i8*
+ // CK29-DAG: [[VAR4]] = getelementptr inbounds double, double* [[VAR44:%.+]], i{{.+}} 0
+ // CK29-DAG: [[VAR44]] = load double*, double**
+
+ // CK29: call void [[CALL00:@.+]]([[SSB]]* {{[^,]+}})
+ #pragma omp target map(pr->pr[:10])
+ {
+ pr->pr++;
+ }
+ }
+};
+
+void explicit_maps_member_pointer_references(SSA *sap) {
+ double *d;
+ SSA sa(d);
+ SSB sb(sap);
+ sb.foo();
+}
+#endif
#endif
diff --git a/test/OpenMP/target_map_messages.cpp b/test/OpenMP/target_map_messages.cpp
index f9bb9410c492..93f0216dd233 100644
--- a/test/OpenMP/target_map_messages.cpp
+++ b/test/OpenMP/target_map_messages.cpp
@@ -51,6 +51,10 @@ struct SA {
{}
#pragma omp target map(to:b,e[:])
{}
+ #pragma omp target map(b[-1:]) // expected-error {{array section must be a subset of the original array}}
+ {}
+ #pragma omp target map(b[:-1]) // expected-error {{section length is evaluated to a negative value -1}}
+ {}
#pragma omp target map(always, tofrom: c,f)
{}
@@ -343,6 +347,15 @@ public:
S5(int v):a(v) { }
};
+template <class T>
+struct S6;
+
+template<>
+struct S6<int> // expected-note {{mappable type cannot be polymorphic}}
+{
+ virtual void foo();
+};
+
S3 h;
#pragma omp threadprivate(h) // expected-note 2 {{defined as threadprivate or thread local}}
@@ -447,6 +460,7 @@ int main(int argc, char **argv) {
int i;
int &j = i;
int *k = &j;
+ S6<int> m;
int x;
int y;
int to, tofrom, always;
@@ -509,6 +523,8 @@ int main(int argc, char **argv) {
{}
#pragma omp target firstprivate(j) map(j) // expected-error {{firstprivate variable cannot be in a map clause in '#pragma omp target' directive}} expected-note {{defined as firstprivate}}
{}
+#pragma omp target map(m) // expected-error {{type 'S6<int>' is not mappable to target}}
+ {}
return tmain<int, 3>(argc)+tmain<from, 4>(argc); // expected-note {{in instantiation of function template specialization 'tmain<int, 3>' requested here}} expected-note {{in instantiation of function template specialization 'tmain<int, 4>' requested here}}
}
#endif
diff --git a/test/OpenMP/target_parallel_ast_print.cpp b/test/OpenMP/target_parallel_ast_print.cpp
index 1c0fca5ccfc0..82c9203f030f 100644
--- a/test/OpenMP/target_parallel_ast_print.cpp
+++ b/test/OpenMP/target_parallel_ast_print.cpp
@@ -1,6 +1,6 @@
-// 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 -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
// expected-no-diagnostics
#ifndef HEADER
@@ -15,18 +15,18 @@ struct S {
#pragma omp threadprivate(TS)
};
-// CHECK: template <class T = int> struct S {
+// CHECK: template <class T> struct S {
+// CHECK: static T TS;
+// CHECK-NEXT: #pragma omp threadprivate(S::TS)
+// CHECK: };
+// CHECK: template<> struct S<int> {
// CHECK: static int TS;
// CHECK-NEXT: #pragma omp threadprivate(S<int>::TS)
// CHECK-NEXT: }
-// CHECK: template <class T = char> struct S {
+// CHECK: template<> struct S<char> {
// CHECK: static char TS;
// CHECK-NEXT: #pragma omp threadprivate(S<char>::TS)
// CHECK-NEXT: }
-// CHECK: template <class T> struct S {
-// CHECK: static T TS;
-// CHECK-NEXT: #pragma omp threadprivate(S::TS)
-// CHECK: };
template <typename T, int C>
T tmain(T argc, T *argv) {
@@ -64,23 +64,23 @@ T tmain(T argc, T *argv) {
return 0;
}
-// CHECK: template <typename T = int, int C = 5> int tmain(int argc, int *argv) {
-// CHECK-NEXT: int b = argc, c, d, e, f, g;
-// CHECK-NEXT: static int h;
-// CHECK-NEXT: S<int> s;
-// CHECK-NEXT: int arr[5][10], arr1[5];
-// CHECK-NEXT: int i, j, a[20]
+// CHECK: template <typename T, int C> T tmain(T argc, T *argv) {
+// CHECK-NEXT: T b = argc, c, d, e, f, g;
+// CHECK-NEXT: static T h;
+// 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: h = 2;
-// CHECK-NEXT: #pragma omp target parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(parallel: argc > 0) num_threads(5) proc_bind(master) reduction(+: c,arr1[argc]) reduction(max: e,arr[:5][0:10])
+// 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()
-// CHECK-NEXT: #pragma omp target parallel if(5) num_threads(s) proc_bind(close) reduction(^: e,f,arr[0:5][:argc]) reduction(&&: g)
+// CHECK-NEXT: #pragma omp target parallel if(C) num_threads(s) proc_bind(close) reduction(^: e,f,arr[0:C][:argc]) reduction(&&: g)
// CHECK-NEXT: foo()
// CHECK-NEXT: #pragma omp target parallel if(target: argc > 0)
// CHECK-NEXT: foo()
// CHECK-NEXT: #pragma omp target parallel if(parallel: argc > 0)
// CHECK-NEXT: foo()
-// CHECK-NEXT: #pragma omp target parallel if(5)
+// CHECK-NEXT: #pragma omp target parallel if(C)
// CHECK-NEXT: foo()
// CHECK-NEXT: #pragma omp target parallel map(tofrom: i)
// CHECK-NEXT: foo()
@@ -96,23 +96,23 @@ T tmain(T argc, T *argv) {
// CHECK-NEXT: foo()
// CHECK-NEXT: #pragma omp target parallel defaultmap(tofrom: scalar)
// CHECK-NEXT: foo()
-// CHECK: template <typename T = char, int C = 1> char tmain(char argc, char *argv) {
-// CHECK-NEXT: char b = argc, c, d, e, f, g;
-// CHECK-NEXT: static char h;
-// CHECK-NEXT: S<char> s;
-// CHECK-NEXT: char arr[1][10], arr1[1];
-// CHECK-NEXT: char i, j, a[20]
+// CHECK: template<> int tmain<int, 5>(int argc, int *argv) {
+// CHECK-NEXT: int b = argc, c, d, e, f, g;
+// CHECK-NEXT: static int h;
+// CHECK-NEXT: S<int> s;
+// CHECK-NEXT: int arr[5][10], arr1[5];
+// CHECK-NEXT: int i, j, a[20]
// 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(1) proc_bind(master) reduction(+: c,arr1[argc]) reduction(max: e,arr[:1][0:10])
+// CHECK-NEXT: #pragma omp target parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(parallel: argc > 0) num_threads(5) proc_bind(master) reduction(+: c,arr1[argc]) reduction(max: e,arr[:5][0:10])
// CHECK-NEXT: foo()
-// CHECK-NEXT: #pragma omp target parallel if(1) num_threads(s) proc_bind(close) reduction(^: e,f,arr[0:1][:argc]) reduction(&&: g)
+// CHECK-NEXT: #pragma omp target parallel if(5) num_threads(s) proc_bind(close) reduction(^: e,f,arr[0:5][:argc]) reduction(&&: g)
// CHECK-NEXT: foo()
// CHECK-NEXT: #pragma omp target parallel if(target: argc > 0)
// CHECK-NEXT: foo()
// CHECK-NEXT: #pragma omp target parallel if(parallel: argc > 0)
// CHECK-NEXT: foo()
-// CHECK-NEXT: #pragma omp target parallel if(1)
+// CHECK-NEXT: #pragma omp target parallel if(5)
// CHECK-NEXT: foo()
// CHECK-NEXT: #pragma omp target parallel map(tofrom: i)
// CHECK-NEXT: foo()
@@ -128,23 +128,23 @@ T tmain(T argc, T *argv) {
// CHECK-NEXT: foo()
// CHECK-NEXT: #pragma omp target parallel defaultmap(tofrom: scalar)
// CHECK-NEXT: foo()
-// CHECK: template <typename T, int C> T tmain(T argc, T *argv) {
-// CHECK-NEXT: T b = argc, c, d, e, f, g;
-// CHECK-NEXT: static T h;
-// CHECK-NEXT: S<T> s;
-// CHECK-NEXT: T arr[C][10], arr1[C];
-// CHECK-NEXT: T i, j, a[20]
+// CHECK: template<> char tmain<char, 1>(char argc, char *argv) {
+// CHECK-NEXT: char b = argc, c, d, e, f, g;
+// CHECK-NEXT: static char h;
+// CHECK-NEXT: S<char> s;
+// CHECK-NEXT: char arr[1][10], arr1[1];
+// CHECK-NEXT: char i, j, a[20]
// 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: #pragma omp target parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(parallel: argc > 0) num_threads(1) proc_bind(master) reduction(+: c,arr1[argc]) reduction(max: e,arr[:1][0:10])
// CHECK-NEXT: foo()
-// CHECK-NEXT: #pragma omp target parallel if(C) num_threads(s) proc_bind(close) reduction(^: e,f,arr[0:C][:argc]) reduction(&&: g)
+// CHECK-NEXT: #pragma omp target parallel if(1) num_threads(s) proc_bind(close) reduction(^: e,f,arr[0:1][:argc]) reduction(&&: g)
// CHECK-NEXT: foo()
// CHECK-NEXT: #pragma omp target parallel if(target: argc > 0)
// CHECK-NEXT: foo()
// CHECK-NEXT: #pragma omp target parallel if(parallel: argc > 0)
// CHECK-NEXT: foo()
-// CHECK-NEXT: #pragma omp target parallel if(C)
+// CHECK-NEXT: #pragma omp target parallel if(1)
// CHECK-NEXT: foo()
// CHECK-NEXT: #pragma omp target parallel map(tofrom: i)
// CHECK-NEXT: foo()
diff --git a/test/OpenMP/target_parallel_depend_messages.cpp b/test/OpenMP/target_parallel_depend_messages.cpp
index a9300ca6adb2..fde940be1aa4 100644
--- a/test/OpenMP/target_parallel_depend_messages.cpp
+++ b/test/OpenMP/target_parallel_depend_messages.cpp
@@ -66,7 +66,7 @@ int main(int argc, char **argv, char *env[]) {
foo();
#pragma omp target parallel depend (in : argv[0:-1]) // expected-error {{section length is evaluated to a negative value -1}}
foo();
- #pragma omp target parallel depend (in : argv[-1:0]) // expected-error {{section lower bound is evaluated to a negative value -1}}
+ #pragma omp target parallel depend (in : argv[-1:0])
foo();
#pragma omp target parallel depend (in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
foo();
diff --git a/test/OpenMP/target_parallel_for_ast_print.cpp b/test/OpenMP/target_parallel_for_ast_print.cpp
index 6c551cbb9abf..d5aa055842a7 100644
--- a/test/OpenMP/target_parallel_for_ast_print.cpp
+++ b/test/OpenMP/target_parallel_for_ast_print.cpp
@@ -1,6 +1,6 @@
-// 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 -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
// expected-no-diagnostics
#ifndef HEADER
@@ -35,9 +35,9 @@ public:
}
};
-// CHECK: #pragma omp target parallel for private(this->a) private(this->a) private(this->S::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)
class S8 : public S7<S> {
S8() {}
diff --git a/test/OpenMP/target_parallel_for_depend_messages.cpp b/test/OpenMP/target_parallel_for_depend_messages.cpp
index d0e74f9cc629..cf17d7a5def2 100644
--- a/test/OpenMP/target_parallel_for_depend_messages.cpp
+++ b/test/OpenMP/target_parallel_for_depend_messages.cpp
@@ -67,7 +67,7 @@ int main(int argc, char **argv, char *env[]) {
for (i = 0; i < argc; ++i) foo();
#pragma omp target parallel for depend (in : argv[0:-1]) // expected-error {{section length is evaluated to a negative value -1}}
for (i = 0; i < argc; ++i) foo();
- #pragma omp target parallel for depend (in : argv[-1:0]) // expected-error {{section lower bound is evaluated to a negative value -1}}
+ #pragma omp target parallel for depend (in : argv[-1:0])
for (i = 0; i < argc; ++i) foo();
#pragma omp target parallel for depend (in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
for (i = 0; i < argc; ++i) foo();
diff --git a/test/OpenMP/target_parallel_for_if_messages.cpp b/test/OpenMP/target_parallel_for_if_messages.cpp
index 01173c159d57..4acf4b8d4a77 100644
--- a/test/OpenMP/target_parallel_for_if_messages.cpp
+++ b/test/OpenMP/target_parallel_for_if_messages.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 %s
void foo() {
}
diff --git a/test/OpenMP/target_parallel_for_map_messages.cpp b/test/OpenMP/target_parallel_for_map_messages.cpp
index 6b5d2e7f8204..f0019f94f493 100644
--- a/test/OpenMP/target_parallel_for_map_messages.cpp
+++ b/test/OpenMP/target_parallel_for_map_messages.cpp
@@ -80,6 +80,10 @@ T tmain(T argc) {
for (i = 0; i < argc; ++i) foo();
#pragma omp target parallel for map(x: y) // expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}}
for (i = 0; i < argc; ++i) foo();
+#pragma omp target parallel for map(l[-1:]) // expected-error 2 {{array section must be a subset of the original array}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target parallel for map(l[:-1]) // expected-error 2 {{section length is evaluated to a negative value -1}}
+ for (i = 0; i < argc; ++i) foo();
#pragma omp target parallel for map(x)
for (i = 0; i < argc; ++i) foo();
#pragma omp target parallel for map(tofrom: t[:I])
@@ -196,6 +200,10 @@ int main(int argc, char **argv) {
for (i = 0; i < argc; ++i) foo();
#pragma omp target parallel for map(x: y) // expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}}
for (i = 0; i < argc; ++i) foo();
+#pragma omp target parallel for map(l[-1:]) // expected-error {{array section must be a subset of the original array}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target parallel for map(l[:-1]) // expected-error {{section length is evaluated to a negative value -1}}
+ for (i = 0; i < argc; ++i) foo();
#pragma omp target parallel for map(x)
for (i = 0; i < argc; ++i) foo();
#pragma omp target parallel for map(to: x)
diff --git a/test/OpenMP/target_parallel_for_simd_aligned_messages.cpp b/test/OpenMP/target_parallel_for_simd_aligned_messages.cpp
index 669cafeae1ea..538d65b82b5e 100644
--- a/test/OpenMP/target_parallel_for_simd_aligned_messages.cpp
+++ b/test/OpenMP/target_parallel_for_simd_aligned_messages.cpp
@@ -121,7 +121,8 @@ template<class I, class C> int foomain(I argc, C **argv) {
for (I k = 0; k < argc; ++k) ++k;
#pragma omp target parallel for simd aligned (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
for (I k = 0; k < argc; ++k) ++k;
- #pragma omp target parallel for simd aligned (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+// FIXME: Should argc really be a pointer?
+ #pragma omp target parallel for simd aligned (*argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
for (I k = 0; k < argc; ++k) ++k;
#pragma omp target parallel for simd aligned (argc : 5) // expected-warning {{aligned clause will be ignored because the requested alignment is not a power of 2}}
for (I k = 0; k < argc; ++k) ++k;
diff --git a/test/OpenMP/target_parallel_for_simd_ast_print.cpp b/test/OpenMP/target_parallel_for_simd_ast_print.cpp
index e25f93fbaefe..82d72c3b1a4b 100644
--- a/test/OpenMP/target_parallel_for_simd_ast_print.cpp
+++ b/test/OpenMP/target_parallel_for_simd_ast_print.cpp
@@ -1,6 +1,6 @@
-// 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 -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
// expected-no-diagnostics
#ifndef HEADER
@@ -35,9 +35,9 @@ public:
}
};
-// CHECK: #pragma omp target parallel for simd private(this->a) private(this->a) private(this->S::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)
class S8 : public S7<S> {
S8() {}
diff --git a/test/OpenMP/target_parallel_for_simd_depend_messages.cpp b/test/OpenMP/target_parallel_for_simd_depend_messages.cpp
index 0504cabd0f01..a8b4de7ff755 100644
--- a/test/OpenMP/target_parallel_for_simd_depend_messages.cpp
+++ b/test/OpenMP/target_parallel_for_simd_depend_messages.cpp
@@ -67,7 +67,7 @@ int main(int argc, char **argv, char *env[]) {
for (i = 0; i < argc; ++i) foo();
#pragma omp target parallel for simd depend (in : argv[0:-1]) // expected-error {{section length is evaluated to a negative value -1}}
for (i = 0; i < argc; ++i) foo();
- #pragma omp target parallel for simd depend (in : argv[-1:0]) // expected-error {{section lower bound is evaluated to a negative value -1}}
+ #pragma omp target parallel for simd depend (in : argv[-1:0])
for (i = 0; i < argc; ++i) foo();
#pragma omp target parallel for simd depend (in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
for (i = 0; i < argc; ++i) foo();
diff --git a/test/OpenMP/target_parallel_for_simd_if_messages.cpp b/test/OpenMP/target_parallel_for_simd_if_messages.cpp
index b9e2891575b2..640e24c1eae4 100644
--- a/test/OpenMP/target_parallel_for_simd_if_messages.cpp
+++ b/test/OpenMP/target_parallel_for_simd_if_messages.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 %s
void foo() {
}
diff --git a/test/OpenMP/target_parallel_for_simd_map_messages.cpp b/test/OpenMP/target_parallel_for_simd_map_messages.cpp
index 93f0be81e31a..195b39c595c3 100644
--- a/test/OpenMP/target_parallel_for_simd_map_messages.cpp
+++ b/test/OpenMP/target_parallel_for_simd_map_messages.cpp
@@ -80,6 +80,10 @@ T tmain(T argc) {
for (i = 0; i < argc; ++i) foo();
#pragma omp target parallel for simd map(x: y) // expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}}
for (i = 0; i < argc; ++i) foo();
+#pragma omp target parallel for simd map(l[-1:]) // expected-error 2 {{array section must be a subset of the original array}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target parallel for simd map(l[:-1]) // expected-error 2 {{section length is evaluated to a negative value -1}}
+ for (i = 0; i < argc; ++i) foo();
#pragma omp target parallel for simd map(x)
for (i = 0; i < argc; ++i) foo();
#pragma omp target parallel for simd map(tofrom: t[:I])
@@ -196,6 +200,10 @@ int main(int argc, char **argv) {
for (i = 0; i < argc; ++i) foo();
#pragma omp target parallel for simd map(x: y) // expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}}
for (i = 0; i < argc; ++i) foo();
+#pragma omp target parallel map(l[-1:]) // expected-error {{array section must be a subset of the original array}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target parallel map(l[:-1]) // expected-error {{section length is evaluated to a negative value -1}}
+ for (i = 0; i < argc; ++i) foo();
#pragma omp target parallel for simd map(x)
for (i = 0; i < argc; ++i) foo();
#pragma omp target parallel for simd map(to: x)
diff --git a/test/OpenMP/target_parallel_if_messages.cpp b/test/OpenMP/target_parallel_if_messages.cpp
index e22eb8150af6..06b7a59b7e59 100644
--- a/test/OpenMP/target_parallel_if_messages.cpp
+++ b/test/OpenMP/target_parallel_if_messages.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp -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
new file mode 100644
index 000000000000..7fbddd8622ae
--- /dev/null
+++ b/test/OpenMP/target_parallel_is_device_ptr_ast_print.cpp
@@ -0,0 +1,294 @@
+// 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
+// expected-no-diagnostics
+
+#ifndef HEADER
+#define HEADER
+
+struct ST {
+ int *a;
+};
+typedef int arr[10];
+typedef ST STarr[10];
+struct SA {
+ const int da[5] = { 0 };
+ ST g[10];
+ STarr &rg = g;
+ int i;
+ int &j = i;
+ int *k = &j;
+ int *&z = k;
+ int aa[10];
+ arr &raa = aa;
+ void func(int arg) {
+#pragma omp target parallel is_device_ptr(k)
+ {}
+#pragma omp target parallel is_device_ptr(z)
+ {}
+#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(g) // OK
+ {}
+#pragma omp target parallel is_device_ptr(rg) // OK
+ {}
+#pragma omp target parallel is_device_ptr(da) // OK
+ {}
+ return;
+ }
+};
+// CHECK: struct SA
+// CHECK-NEXT: const int da[5] = {0};
+// CHECK-NEXT: ST g[10];
+// CHECK-NEXT: STarr &rg = this->g;
+// CHECK-NEXT: int i;
+// CHECK-NEXT: int &j = this->i;
+// CHECK-NEXT: int *k = &this->j;
+// CHECK-NEXT: int *&z = this->k;
+// 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: {
+// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp target parallel is_device_ptr(this->z)
+// CHECK-NEXT: {
+// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp target parallel is_device_ptr(this->aa)
+// CHECK-NEXT: {
+// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp target parallel is_device_ptr(this->raa)
+// CHECK-NEXT: {
+// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp target parallel is_device_ptr(this->g)
+// CHECK-NEXT: {
+// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp target parallel is_device_ptr(this->rg)
+// CHECK-NEXT: {
+// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp target parallel is_device_ptr(this->da)
+
+struct SB {
+ unsigned A;
+ unsigned B;
+ float Arr[100];
+ float *Ptr;
+ float *foo() {
+ return &Arr[0];
+ }
+};
+
+struct SC {
+ unsigned A : 2;
+ unsigned B : 3;
+ unsigned C;
+ unsigned D;
+ float Arr[100];
+ SB S;
+ SB ArrS[100];
+ SB *PtrS;
+ SB *&RPtrS;
+ float *Ptr;
+
+ SC(SB *&_RPtrS) : RPtrS(_RPtrS) {}
+};
+
+union SD {
+ unsigned A;
+ float B;
+};
+
+struct S1;
+extern S1 a;
+class S2 {
+ mutable int a;
+public:
+ S2():a(0) { }
+ S2(S2 &s2):a(s2.a) { }
+ static float S2s;
+ static const float S2sc;
+};
+const float S2::S2sc = 0;
+const S2 b;
+const S2 ba[5];
+class S3 {
+ int a;
+public:
+ S3():a(0) { }
+ S3(S3 &s3):a(s3.a) { }
+};
+const S3 c;
+const S3 ca[5];
+extern const int f;
+class S4 {
+ int a;
+ S4();
+ S4(const S4 &s4);
+public:
+ S4(int v):a(v) { }
+};
+class S5 {
+ int a;
+ S5():a(0) {}
+ S5(const S5 &s5):a(s5.a) { }
+public:
+ S5(int v):a(v) { }
+};
+
+S3 h;
+#pragma omp threadprivate(h)
+
+typedef struct {
+ int a;
+} S6;
+
+template <typename T>
+T tmain(T argc) {
+ const T da[5] = { 0 };
+ S6 h[10];
+ auto &rh = h;
+ T i;
+ T &j = i;
+ T *k = &j;
+ T *&z = k;
+ T aa[10];
+ auto &raa = aa;
+#pragma omp target parallel is_device_ptr(k)
+ {}
+#pragma omp target parallel is_device_ptr(z)
+ {}
+#pragma omp target parallel is_device_ptr(aa)
+ {}
+#pragma omp target parallel is_device_ptr(raa)
+ {}
+#pragma omp target parallel is_device_ptr(h)
+ {}
+#pragma omp target parallel is_device_ptr(rh)
+ {}
+#pragma omp target parallel is_device_ptr(da)
+ {}
+ return 0;
+}
+
+// CHECK: template<> int tmain<int>(int argc) {
+// CHECK-NEXT: const int da[5] = {0};
+// CHECK-NEXT: S6 h[10];
+// CHECK-NEXT: auto &rh = h;
+// CHECK-NEXT: int i;
+// CHECK-NEXT: int &j = i;
+// CHECK-NEXT: int *k = &j;
+// CHECK-NEXT: int *&z = k;
+// CHECK-NEXT: int aa[10];
+// CHECK-NEXT: auto &raa = aa;
+// CHECK-NEXT: #pragma omp target parallel is_device_ptr(k)
+// CHECK-NEXT: {
+// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp target parallel is_device_ptr(z)
+// CHECK-NEXT: {
+// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp target parallel is_device_ptr(aa)
+// CHECK-NEXT: {
+// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp target parallel is_device_ptr(raa)
+// CHECK-NEXT: {
+// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp target parallel is_device_ptr(h)
+// CHECK-NEXT: {
+// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp target parallel is_device_ptr(rh)
+// CHECK-NEXT: {
+// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp target parallel is_device_ptr(da)
+
+// CHECK: template<> int *tmain<int *>(int *argc) {
+// CHECK-NEXT: int *const da[5] = {0};
+// CHECK-NEXT: S6 h[10];
+// CHECK-NEXT: auto &rh = h;
+// CHECK-NEXT: int *i;
+// CHECK-NEXT: int *&j = i;
+// CHECK-NEXT: int **k = &j;
+// CHECK-NEXT: int **&z = k;
+// CHECK-NEXT: int *aa[10];
+// CHECK-NEXT: auto &raa = aa;
+// CHECK-NEXT: #pragma omp target parallel is_device_ptr(k)
+// CHECK-NEXT: {
+// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp target parallel is_device_ptr(z)
+// CHECK-NEXT: {
+// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp target parallel is_device_ptr(aa)
+// CHECK-NEXT: {
+// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp target parallel is_device_ptr(raa)
+// CHECK-NEXT: {
+// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp target parallel is_device_ptr(h)
+// CHECK-NEXT: {
+// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp target parallel is_device_ptr(rh)
+// CHECK-NEXT: {
+// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp target parallel is_device_ptr(da)
+
+// CHECK-LABEL: int main(int argc, char **argv) {
+int main(int argc, char **argv) {
+ const int da[5] = { 0 };
+ S6 h[10];
+ auto &rh = h;
+ int i;
+ int &j = i;
+ int *k = &j;
+ int *&z = k;
+ int aa[10];
+ auto &raa = aa;
+// CHECK-NEXT: const int da[5] = {0};
+// CHECK-NEXT: S6 h[10];
+// CHECK-NEXT: auto &rh = h;
+// CHECK-NEXT: int i;
+// CHECK-NEXT: int &j = i;
+// CHECK-NEXT: int *k = &j;
+// CHECK-NEXT: int *&z = k;
+// CHECK-NEXT: int aa[10];
+// CHECK-NEXT: auto &raa = aa;
+#pragma omp target parallel is_device_ptr(k)
+// CHECK-NEXT: #pragma omp target parallel is_device_ptr(k)
+ {}
+// CHECK-NEXT: {
+// CHECK-NEXT: }
+#pragma omp target parallel is_device_ptr(z)
+// CHECK-NEXT: #pragma omp target parallel is_device_ptr(z)
+ {}
+// CHECK-NEXT: {
+// CHECK-NEXT: }
+#pragma omp target parallel is_device_ptr(aa)
+// CHECK-NEXT: #pragma omp target parallel is_device_ptr(aa)
+ {}
+// CHECK-NEXT: {
+// CHECK-NEXT: }
+#pragma omp target parallel is_device_ptr(raa)
+// CHECK-NEXT: #pragma omp target parallel is_device_ptr(raa)
+ {}
+// CHECK-NEXT: {
+// CHECK-NEXT: }
+#pragma omp target parallel is_device_ptr(h)
+// CHECK-NEXT: #pragma omp target parallel is_device_ptr(h)
+ {}
+// CHECK-NEXT: {
+// CHECK-NEXT: }
+#pragma omp target parallel is_device_ptr(rh)
+// CHECK-NEXT: #pragma omp target parallel is_device_ptr(rh)
+ {}
+// CHECK-NEXT: {
+// CHECK-NEXT: }
+#pragma omp target parallel is_device_ptr(da)
+// CHECK-NEXT: #pragma omp target parallel is_device_ptr(da)
+ {}
+// CHECK-NEXT: {
+// CHECK-NEXT: }
+ return tmain<int>(argc) + *tmain<int *>(&argc);
+}
+
+
+#endif
diff --git a/test/OpenMP/target_parallel_is_device_ptr_messages.cpp b/test/OpenMP/target_parallel_is_device_ptr_messages.cpp
new file mode 100644
index 000000000000..d9c3ee907b61
--- /dev/null
+++ b/test/OpenMP/target_parallel_is_device_ptr_messages.cpp
@@ -0,0 +1,268 @@
+// RUN: %clang_cc1 -std=c++11 -verify -fopenmp -ferror-limit 200 %s
+struct ST {
+ int *a;
+};
+typedef int arr[10];
+typedef ST STarr[10];
+struct SA {
+ const int d = 5;
+ const int da[5] = { 0 };
+ ST e;
+ ST g[10];
+ STarr &rg = g;
+ int i;
+ int &j = i;
+ int *k = &j;
+ int *&z = k;
+ int aa[10];
+ arr &raa = aa;
+ void func(int arg) {
+#pragma omp target parallel is_device_ptr // expected-error {{expected '(' after 'is_device_ptr'}}
+ {}
+#pragma omp target parallel is_device_ptr( // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}}
+ {}
+#pragma omp target parallel is_device_ptr() // expected-error {{expected expression}}
+ {}
+#pragma omp target parallel is_device_ptr(alloc) // expected-error {{use of undeclared identifier 'alloc'}}
+ {}
+#pragma omp target parallel is_device_ptr(arg // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ {}
+#pragma omp target parallel is_device_ptr(i) // expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ {}
+#pragma omp target parallel is_device_ptr(j) // expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ {}
+#pragma omp target parallel is_device_ptr(k) // OK
+ {}
+#pragma omp target parallel is_device_ptr(z) // OK
+ {}
+#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
+ {}
+#pragma omp target parallel is_device_ptr(rg) // OK
+ {}
+#pragma omp target parallel is_device_ptr(k,i,j) // expected-error2 {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ {}
+#pragma omp target parallel is_device_ptr(d) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ {}
+#pragma omp target parallel is_device_ptr(da) // OK
+ {}
+ return;
+ }
+};
+struct SB {
+ unsigned A;
+ unsigned B;
+ float Arr[100];
+ float *Ptr;
+ float *foo() {
+ return &Arr[0];
+ }
+};
+
+struct SC {
+ unsigned A : 2;
+ unsigned B : 3;
+ unsigned C;
+ unsigned D;
+ float Arr[100];
+ SB S;
+ SB ArrS[100];
+ SB *PtrS;
+ SB *&RPtrS;
+ float *Ptr;
+
+ SC(SB *&_RPtrS) : RPtrS(_RPtrS) {}
+};
+
+union SD {
+ unsigned A;
+ float B;
+};
+
+struct S1;
+extern S1 a;
+class S2 {
+ mutable int a;
+public:
+ S2():a(0) { }
+ S2(S2 &s2):a(s2.a) { }
+ static float S2s;
+ static const float S2sc;
+};
+const float S2::S2sc = 0;
+const S2 b;
+const S2 ba[5];
+class S3 {
+ int a;
+public:
+ S3():a(0) { }
+ S3(S3 &s3):a(s3.a) { }
+};
+const S3 c;
+const S3 ca[5];
+extern const int f;
+class S4 {
+ int a;
+ S4();
+ S4(const S4 &s4);
+public:
+ S4(int v):a(v) { }
+};
+class S5 {
+ int a;
+ S5():a(0) {}
+ S5(const S5 &s5):a(s5.a) { }
+public:
+ S5(int v):a(v) { }
+};
+
+S3 h;
+#pragma omp threadprivate(h)
+
+typedef struct {
+ int a;
+} S6;
+
+template <typename T, int I>
+T tmain(T argc) {
+ const T d = 5;
+ const T da[5] = { 0 };
+ S4 e(4);
+ S5 g(5);
+ S6 h[10];
+ auto &rh = h;
+ T i;
+ T &j = i;
+ T *k = &j;
+ T *&z = k;
+ T aa[10];
+ auto &raa = aa;
+ S6 *ps;
+#pragma omp target parallel is_device_ptr // expected-error {{expected '(' after 'is_device_ptr'}}
+ {}
+#pragma omp target parallel is_device_ptr( // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}}
+ {}
+#pragma omp target parallel is_device_ptr() // expected-error {{expected expression}}
+ {}
+#pragma omp target parallel is_device_ptr(alloc) // expected-error {{use of undeclared identifier 'alloc'}}
+ {}
+#pragma omp target parallel is_device_ptr(argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ {}
+#pragma omp target parallel is_device_ptr(i) // expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ {}
+#pragma omp target parallel is_device_ptr(j) // expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ {}
+#pragma omp target parallel is_device_ptr(k) // OK
+ {}
+#pragma omp target parallel is_device_ptr(z) // OK
+ {}
+#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) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ {}
+#pragma omp target parallel is_device_ptr(h) // OK
+ {}
+#pragma omp target parallel is_device_ptr(rh) // OK
+ {}
+#pragma omp target parallel is_device_ptr(k,i,j) // expected-error2 {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ {}
+#pragma omp target parallel is_device_ptr(d) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ {}
+#pragma omp target parallel is_device_ptr(da) // OK
+ {}
+#pragma omp target parallel map(ps) is_device_ptr(ps) // expected-error{{variable already marked as mapped in current construct}} expected-note{{used here}}
+ {}
+#pragma omp target parallel is_device_ptr(ps) map(ps) // expected-error{{variable already marked as mapped in current construct}} expected-note{{used here}}
+ {}
+#pragma omp target parallel map(ps->a) is_device_ptr(ps) // expected-error{{variable already marked as mapped in current construct}} expected-note{{used here}}
+ {}
+#pragma omp target parallel is_device_ptr(ps) map(ps->a) // expected-error{{pointer cannot be mapped along with a section derived from itself}} expected-note{{used here}}
+ {}
+#pragma omp target parallel is_device_ptr(ps) firstprivate(ps) // expected-error{{firstprivate variable cannot be in a is_device_ptr clause in '#pragma omp target parallel' directive}}
+ {}
+#pragma omp target parallel firstprivate(ps) is_device_ptr(ps) // expected-error{{firstprivate variable cannot be in a is_device_ptr clause in '#pragma omp target parallel' directive}} expected-note{{defined as firstprivate}}
+ {}
+#pragma omp target parallel is_device_ptr(ps) private(ps) // expected-error{{private variable cannot be in a is_device_ptr clause in '#pragma omp target parallel' directive}}
+ {}
+#pragma omp target parallel private(ps) is_device_ptr(ps) // expected-error{{private variable cannot be in a is_device_ptr clause in '#pragma omp target parallel' directive}} expected-note{{defined as private}}
+ {}
+ return 0;
+}
+
+int main(int argc, char **argv) {
+ const int d = 5;
+ const int da[5] = { 0 };
+ S4 e(4);
+ S5 g(5);
+ S6 h[10];
+ auto &rh = h;
+ int i;
+ int &j = i;
+ int *k = &j;
+ int *&z = k;
+ int aa[10];
+ auto &raa = aa;
+ S6 *ps;
+#pragma omp target parallel is_device_ptr // expected-error {{expected '(' after 'is_device_ptr'}}
+ {}
+#pragma omp target parallel is_device_ptr( // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}}
+ {}
+#pragma omp target parallel is_device_ptr() // expected-error {{expected expression}}
+ {}
+#pragma omp target parallel is_device_ptr(alloc) // expected-error {{use of undeclared identifier 'alloc'}}
+ {}
+#pragma omp target parallel is_device_ptr(argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ {}
+#pragma omp target parallel is_device_ptr(i) // expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ {}
+#pragma omp target parallel is_device_ptr(j) // expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ {}
+#pragma omp target parallel is_device_ptr(k) // OK
+ {}
+#pragma omp target parallel is_device_ptr(z) // OK
+ {}
+#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) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ {}
+#pragma omp target parallel is_device_ptr(h) // OK
+ {}
+#pragma omp target parallel is_device_ptr(rh) // OK
+ {}
+#pragma omp target parallel is_device_ptr(k,i,j) // expected-error2 {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ {}
+#pragma omp target parallel is_device_ptr(d) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ {}
+#pragma omp target parallel is_device_ptr(da) // OK
+ {}
+#pragma omp target parallel map(ps) is_device_ptr(ps) // expected-error{{variable already marked as mapped in current construct}} expected-note{{used here}}
+ {}
+#pragma omp target parallel is_device_ptr(ps) map(ps) // expected-error{{variable already marked as mapped in current construct}} expected-note{{used here}}
+ {}
+#pragma omp target parallel map(ps->a) is_device_ptr(ps) // expected-error{{variable already marked as mapped in current construct}} expected-note{{used here}}
+ {}
+#pragma omp target parallel is_device_ptr(ps) map(ps->a) // expected-error{{pointer cannot be mapped along with a section derived from itself}} expected-note{{used here}}
+ {}
+#pragma omp target parallel is_device_ptr(ps) firstprivate(ps) // expected-error{{firstprivate variable cannot be in a is_device_ptr clause in '#pragma omp target parallel' directive}}
+ {}
+#pragma omp target parallel firstprivate(ps) is_device_ptr(ps) // expected-error{{firstprivate variable cannot be in a is_device_ptr clause in '#pragma omp target parallel' directive}} expected-note{{defined as firstprivate}}
+ {}
+#pragma omp target parallel is_device_ptr(ps) private(ps) // expected-error{{private variable cannot be in a is_device_ptr clause in '#pragma omp target parallel' directive}}
+ {}
+#pragma omp target parallel private(ps) is_device_ptr(ps) // expected-error{{private variable cannot be in a is_device_ptr clause in '#pragma omp target parallel' directive}} expected-note{{defined as private}}
+ {}
+ return tmain<int, 3>(argc); // expected-note {{in instantiation of function template specialization 'tmain<int, 3>' requested here}}
+}
diff --git a/test/OpenMP/target_parallel_map_messages.cpp b/test/OpenMP/target_parallel_map_messages.cpp
index e16801665428..ca794cecf4c5 100644
--- a/test/OpenMP/target_parallel_map_messages.cpp
+++ b/test/OpenMP/target_parallel_map_messages.cpp
@@ -80,6 +80,10 @@ T tmain(T argc) {
foo();
#pragma omp target parallel map(x: y) // expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}}
foo();
+#pragma omp target parallel map(l[-1:]) // expected-error 2 {{array section must be a subset of the original array}}
+ foo();
+#pragma omp target parallel map(l[:-1]) // expected-error 2 {{section length is evaluated to a negative value -1}}
+ foo();
#pragma omp target parallel map(x)
foo();
#pragma omp target parallel map(tofrom: t[:I])
@@ -195,6 +199,10 @@ int main(int argc, char **argv) {
foo();
#pragma omp target parallel map(x: y) // expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}}
foo();
+#pragma omp target parallel map(l[-1:]) // expected-error {{array section must be a subset of the original array}}
+ foo();
+#pragma omp target parallel map(l[:-1]) // expected-error {{section length is evaluated to a negative value -1}}
+ foo();
#pragma omp target parallel map(x)
foo();
#pragma omp target parallel map(to: x)
diff --git a/test/OpenMP/target_simd_aligned_messages.cpp b/test/OpenMP/target_simd_aligned_messages.cpp
new file mode 100644
index 000000000000..ae2859d5b61f
--- /dev/null
+++ b/test/OpenMP/target_simd_aligned_messages.cpp
@@ -0,0 +1,204 @@
+// RUN: %clang_cc1 -x c++ -std=c++11 -verify -fopenmp %s
+
+struct B {
+ static int ib[20]; // expected-note 0 {{'B::ib' declared here}}
+ static constexpr int bfoo() { return 8; }
+};
+namespace X {
+ B x; // expected-note {{'x' defined here}}
+};
+constexpr int bfoo() { return 4; }
+
+int **z;
+const int C1 = 1;
+const int C2 = 2;
+void test_aligned_colons(int *&rp)
+{
+ int *B = 0;
+ #pragma omp target simd aligned(B:bfoo())
+ for (int i = 0; i < 10; ++i) ;
+ // expected-error@+1 {{unexpected ':' in nested name specifier; did you mean '::'}}
+ #pragma omp target simd aligned(B::ib:B:bfoo())
+ for (int i = 0; i < 10; ++i) ;
+ #pragma omp target simd aligned(B:B::bfoo())
+ for (int i = 0; i < 10; ++i) ;
+ // expected-error@+1 {{unexpected ':' in nested name specifier; did you mean '::'?}}
+ #pragma omp target simd aligned(z:B:bfoo())
+ for (int i = 0; i < 10; ++i) ;
+ #pragma omp target simd aligned(B:B::bfoo())
+ for (int i = 0; i < 10; ++i) ;
+ // expected-error@+2 {{integral constant expression must have integral or unscoped enumeration type, not 'int **'}}
+ // expected-error@+1 {{argument of aligned clause should be array, pointer, reference to array or reference to pointer, not 'B'}}
+ #pragma omp target simd aligned(X::x : ::z)
+ for (int i = 0; i < 10; ++i) ;
+ // expected-error@+1 {{integral constant expression must have integral or unscoped enumeration type, not 'B'}}
+ #pragma omp target simd aligned(B,rp,::z: X::x)
+ for (int i = 0; i < 10; ++i) ;
+ #pragma omp target simd aligned(::z)
+ for (int i = 0; i < 10; ++i) ;
+ // expected-error@+1 {{expected variable name}}
+ #pragma omp target simd aligned(B::bfoo())
+ for (int i = 0; i < 10; ++i) ;
+ // expected-warning@+1 {{aligned clause will be ignored because the requested alignment is not a power of 2}}
+ #pragma omp target simd aligned(B::ib,B:C1+C2)
+ for (int i = 0; i < 10; ++i) ;
+}
+
+// expected-note@+1 {{'num' defined here}}
+template<int L, class T, class N> T test_template(T* arr, N num) {
+ N i;
+ T sum = (T)0;
+ T ind2 = - num * L;
+ // Negative number is passed as L.
+ // expected-error@+1 {{argument to 'aligned' clause must be a strictly positive integer value}}
+ #pragma omp target simd aligned(arr:L)
+ for (i = 0; i < num; ++i) {
+ T cur = arr[(int)ind2];
+ ind2 += L;
+ sum += cur;
+ }
+ // expected-error@+1 {{argument of aligned clause should be array, pointer, reference to array or reference to pointer, not 'int'}}
+ #pragma omp target simd aligned(num:4)
+ for (i = 0; i < num; ++i);
+ return T();
+}
+
+template<int LEN> int test_warn() {
+ int *ind2 = 0;
+ // expected-error@+1 {{argument to 'aligned' clause must be a strictly positive integer value}}
+ #pragma omp target simd aligned(ind2:LEN)
+ for (int i = 0; i < 100; i++) {
+ ind2 += LEN;
+ }
+ return 0;
+}
+
+struct S1; // expected-note 2 {{declared here}}
+extern S1 a; // expected-note {{'a' declared here}}
+class S2 {
+ mutable int a;
+public:
+ S2():a(0) { }
+};
+const S2 b; // expected-note 1 {{'b' defined here}}
+const S2 ba[5];
+class S3 {
+ int a;
+public:
+ S3():a(0) { }
+};
+const S3 ca[5];
+class S4 {
+ int a;
+ S4();
+public:
+ S4(int v):a(v) { }
+};
+class S5 {
+ int a;
+ S5():a(0) {}
+public:
+ S5(int v):a(v) { }
+};
+
+S3 h; // expected-note 2 {{'h' defined here}}
+#pragma omp threadprivate(h)
+
+template<class I, class C> int foomain(I argc, C **argv) {
+ I e(argc);
+ I g(argc);
+ int i; // expected-note {{declared here}} expected-note {{'i' defined here}}
+ // expected-note@+2 {{declared here}}
+ // expected-note@+1 {{reference to 'i' is not a constant expression}}
+ int &j = i;
+ #pragma omp target simd aligned // expected-error {{expected '(' after 'aligned'}}
+ for (I k = 0; k < argc; ++k) ++k;
+ #pragma omp target simd aligned ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (I k = 0; k < argc; ++k) ++k;
+ #pragma omp target simd aligned () // expected-error {{expected expression}}
+ for (I k = 0; k < argc; ++k) ++k;
+ #pragma omp target simd aligned (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (I k = 0; k < argc; ++k) ++k;
+ #pragma omp target simd aligned (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (I k = 0; k < argc; ++k) ++k;
+// FIXME: Should argc really be a pointer?
+ #pragma omp target simd aligned (*argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (I k = 0; k < argc; ++k) ++k;
+ #pragma omp target simd aligned (argc : 5) // expected-warning {{aligned clause will be ignored because the requested alignment is not a power of 2}}
+ for (I k = 0; k < argc; ++k) ++k;
+ #pragma omp target simd aligned (S1) // expected-error {{'S1' does not refer to a value}}
+ for (I k = 0; k < argc; ++k) ++k;
+ #pragma omp target simd aligned (argv[1]) // expected-error {{expected variable name}}
+ for (I k = 0; k < argc; ++k) ++k;
+ #pragma omp target simd aligned(e, g)
+ for (I k = 0; k < argc; ++k) ++k;
+ // expected-error@+1 {{argument of aligned clause should be array, pointer, reference to array or reference to pointer, not 'S3'}}
+ #pragma omp target simd aligned(h)
+ for (I k = 0; k < argc; ++k) ++k;
+ // expected-error@+1 {{argument of aligned clause should be array, pointer, reference to array or reference to pointer, not 'int'}}
+ #pragma omp target simd aligned(i)
+ for (I k = 0; k < argc; ++k) ++k;
+ #pragma omp parallel
+ {
+ int *v = 0;
+ I i;
+ #pragma omp target simd aligned(v:16)
+ for (I k = 0; k < argc; ++k) { i = k; v += 2; }
+ }
+ float *f;
+ #pragma omp target simd aligned(f)
+ for (I k = 0; k < argc; ++k) ++k;
+ int v = 0;
+ // expected-note@+2 {{initializer of 'j' is not a constant expression}}
+ // expected-error@+1 {{expression is not an integral constant expression}}
+ #pragma omp target simd aligned(f:j)
+ for (I k = 0; k < argc; ++k) { ++k; v += j; }
+ #pragma omp target simd aligned(f)
+ for (I k = 0; k < argc; ++k) ++k;
+ return 0;
+}
+
+// expected-note@+1 2 {{'argc' defined here}}
+int main(int argc, char **argv) {
+ double darr[100];
+ // expected-note@+1 {{in instantiation of function template specialization 'test_template<-4, double, int>' requested here}}
+ test_template<-4>(darr, 4);
+ test_warn<4>(); // ok
+ // expected-note@+1 {{in instantiation of function template specialization 'test_warn<0>' requested here}}
+ test_warn<0>();
+
+ int i;
+ int &j = i;
+ #pragma omp target simd aligned // expected-error {{expected '(' after 'aligned'}}
+ for (int k = 0; k < argc; ++k) ++k;
+ #pragma omp target simd aligned ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+ #pragma omp target simd aligned () // expected-error {{expected expression}}
+ for (int k = 0; k < argc; ++k) ++k;
+ #pragma omp target simd aligned (argv // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+ // expected-error@+1 {{argument of aligned clause should be array, pointer, reference to array or reference to pointer, not 'int'}}
+ #pragma omp target simd aligned (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+ #pragma omp target simd aligned (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k) ++k;
+ // expected-error@+1 {{argument of aligned clause should be array, pointer, reference to array or reference to pointer, not 'int'}}
+ #pragma omp target simd aligned (argc)
+ for (int k = 0; k < argc; ++k) ++k;
+ #pragma omp target simd aligned (S1) // expected-error {{'S1' does not refer to a value}}
+ for (int k = 0; k < argc; ++k) ++k;
+ // expected-error@+2 {{argument of aligned clause should be array, pointer, reference to array or reference to pointer, not 'S1'}}
+ // expected-error@+1 {{argument of aligned clause should be array, pointer, reference to array or reference to pointer, not 'S2'}}
+ #pragma omp target simd aligned (a, b)
+ for (int k = 0; k < argc; ++k) ++k;
+ #pragma omp target simd aligned (argv[1]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k) ++k;
+ // expected-error@+1 {{argument of aligned clause should be array, pointer, reference to array or reference to pointer, not 'S3'}}
+ #pragma omp target simd aligned(h)
+ for (int k = 0; k < argc; ++k) ++k;
+ int *pargc = &argc;
+ // expected-note@+1 {{in instantiation of function template specialization 'foomain<int *, char>' requested here}}
+ foomain<int*,char>(pargc,argv);
+ return 0;
+}
+
diff --git a/test/OpenMP/target_simd_ast_print.cpp b/test/OpenMP/target_simd_ast_print.cpp
new file mode 100644
index 000000000000..01ce1d21cfbc
--- /dev/null
+++ b/test/OpenMP/target_simd_ast_print.cpp
@@ -0,0 +1,310 @@
+// 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
+// expected-no-diagnostics
+
+#ifndef HEADER
+#define HEADER
+
+void foo() {}
+
+struct S {
+ S(): a(0) {}
+ S(int v) : a(v) {}
+ int a;
+ typedef int type;
+};
+
+template <typename T>
+class S7 : public T {
+protected:
+ T a;
+ S7() : a(0) {}
+
+public:
+ S7(typename T::type v) : a(v) {
+#pragma omp target simd private(a) private(this->a) private(T::a)
+ for (int k = 0; k < a.a; ++k)
+ ++this->a.a;
+ }
+ S7 &operator=(S7 &s) {
+#pragma omp target simd private(a) private(this->a)
+ for (int k = 0; k < s.a.a; ++k)
+ ++s.a.a;
+ return *this;
+ }
+};
+
+// 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)
+
+class S8 : public S7<S> {
+ S8() {}
+
+public:
+ S8(int v) : S7<S>(v){
+#pragma omp target simd private(a) private(this->a) private(S7<S>::a)
+ for (int k = 0; k < a.a; ++k)
+ ++this->a.a;
+ }
+ S8 &operator=(S8 &s) {
+#pragma omp target simd private(a) private(this->a)
+ for (int k = 0; k < s.a.a; ++k)
+ ++s.a.a;
+ return *this;
+ }
+};
+
+// CHECK: #pragma omp target simd private(this->a) private(this->a) private(this->S7<S>::a)
+// CHECK: #pragma omp target simd private(this->a) private(this->a)
+
+template <class T, int N>
+T tmain(T argc, T *argv) {
+ T b = argc, c, d, e, f, h;
+ T arr[N][10], arr1[N];
+ T i, j;
+ T s;
+ static T a;
+// CHECK: static T a;
+ static T g;
+ const T clen = 5;
+// CHECK: T clen = 5;
+ T *p;
+#pragma omp threadprivate(g)
+#pragma omp target simd linear(a)
+ // CHECK: #pragma omp target simd linear(a)
+ for (T i = 0; i < 2; ++i)
+ a = 2;
+// CHECK-NEXT: for (T i = 0; i < 2; ++i)
+// CHECK-NEXT: a = 2;
+#pragma omp target simd private(argc, b), firstprivate(c, d), lastprivate(d, f) collapse(N) if (target :argc) reduction(+ : h)
+ for (int i = 0; i < 2; ++i)
+ for (int j = 0; j < 2; ++j)
+ for (int j = 0; j < 2; ++j)
+ for (int j = 0; j < 2; ++j)
+ for (int j = 0; j < 2; ++j)
+ foo();
+ // CHECK-NEXT: #pragma omp target simd private(argc,b) firstprivate(c,d) lastprivate(d,f) collapse(N) if(target: argc) reduction(+: h)
+ // CHECK-NEXT: for (int i = 0; i < 2; ++i)
+ // CHECK-NEXT: for (int j = 0; j < 2; ++j)
+ // CHECK-NEXT: for (int j = 0; j < 2; ++j)
+ // CHECK-NEXT: for (int j = 0; j < 2; ++j)
+ // CHECK-NEXT: for (int j = 0; j < 2; ++j)
+ // CHECK-NEXT: foo();
+
+#pragma omp target simd private(argc,b) firstprivate(argv) if(target:argc > 0) reduction(+:c, arr1[argc]) reduction(max:e, arr[:N][0:10])
+ for (T i = 0; i < 2; ++i) {}
+ // CHECK: #pragma omp target simd private(argc,b) firstprivate(argv) if(target: argc > 0) reduction(+: c,arr1[argc]) reduction(max: e,arr[:N][0:10])
+ // CHECK-NEXT: for (T i = 0; i < 2; ++i) {
+ // CHECK-NEXT: }
+
+#pragma omp target simd if(N) reduction(^:e, f, arr[0:N][:argc]) reduction(&& : h)
+ for (T i = 0; i < 2; ++i) {}
+ // CHECK: #pragma omp target simd if(N) reduction(^: e,f,arr[0:N][:argc]) reduction(&&: h)
+ // CHECK-NEXT: for (T i = 0; i < 2; ++i) {
+ // CHECK-NEXT: }
+
+#pragma omp target simd if(target:argc > 0)
+ for (T i = 0; i < 2; ++i) {}
+ // CHECK: #pragma omp target simd if(target: argc > 0)
+ // CHECK-NEXT: for (T i = 0; i < 2; ++i) {
+ // CHECK-NEXT: }
+
+#pragma omp target simd if(N)
+ for (T i = 0; i < 2; ++i) {}
+ // CHECK: #pragma omp target simd if(N)
+ // CHECK-NEXT: for (T i = 0; i < 2; ++i) {
+ // CHECK-NEXT: }
+
+#pragma omp target simd map(i)
+ for (T i = 0; i < 2; ++i) {}
+ // CHECK: #pragma omp target simd map(tofrom: i)
+ // CHECK-NEXT: for (T i = 0; i < 2; ++i) {
+ // CHECK-NEXT: }
+
+#pragma omp target simd map(arr1[0:10], i)
+ for (T i = 0; i < 2; ++i) {}
+ // CHECK: #pragma omp target simd map(tofrom: arr1[0:10],i)
+ // CHECK-NEXT: for (T i = 0; i < 2; ++i) {
+ // CHECK-NEXT: }
+
+#pragma omp target simd map(to: i) map(from: j)
+ for (T i = 0; i < 2; ++i) {}
+ // CHECK: #pragma omp target simd map(to: i) map(from: j)
+ // CHECK-NEXT: for (T i = 0; i < 2; ++i) {
+ // CHECK-NEXT: }
+
+#pragma omp target simd map(always,alloc: i)
+ for (T i = 0; i < 2; ++i) {}
+ // CHECK: #pragma omp target simd map(always,alloc: i)
+ // CHECK-NEXT: for (T i = 0; i < 2; ++i) {
+ // CHECK-NEXT: }
+
+#pragma omp target simd nowait
+ for (T i = 0; i < 2; ++i) {}
+ // CHECK: #pragma omp target simd nowait
+ // CHECK-NEXT: for (T i = 0; i < 2; ++i) {
+ // CHECK-NEXT: }
+
+#pragma omp target simd depend(in : argc, arr[i:argc], arr1[:])
+ for (T i = 0; i < 2; ++i) {}
+ // CHECK: #pragma omp target simd depend(in : argc,arr[i:argc],arr1[:])
+ // CHECK-NEXT: for (T i = 0; i < 2; ++i) {
+ // CHECK-NEXT: }
+
+#pragma omp target simd defaultmap(tofrom: scalar)
+ for (T i = 0; i < 2; ++i) {}
+ // CHECK: #pragma omp target simd defaultmap(tofrom: scalar)
+ // CHECK-NEXT: for (T i = 0; i < 2; ++i) {
+ // CHECK-NEXT: }
+
+#pragma omp target simd safelen(clen-1)
+ for (T i = 0; i < 2; ++i) {}
+ // CHECK: #pragma omp target simd safelen(clen - 1)
+ // CHECK-NEXT: for (T i = 0; i < 2; ++i) {
+ // CHECK-NEXT: }
+
+#pragma omp target simd simdlen(clen-1)
+ for (T i = 0; i < 2; ++i) {}
+ // CHECK: #pragma omp target simd simdlen(clen - 1)
+ // CHECK-NEXT: for (T i = 0; i < 2; ++i) {
+ // CHECK-NEXT: }
+
+#pragma omp target simd aligned(arr1:N-1)
+ for (T i = 0; i < N; ++i) {}
+ // CHECK: #pragma omp target simd aligned(arr1: N - 1)
+ // CHECK-NEXT: for (T i = 0; i < N; ++i) {
+ // CHECK-NEXT: }
+
+#pragma omp target simd is_device_ptr(p)
+ for (T i = 0; i < N; ++i) {}
+ // CHECK: #pragma omp target simd is_device_ptr(p)
+ // CHECK-NEXT: for (T i = 0; i < N; ++i) {
+ // CHECK-NEXT: }
+
+ return T();
+}
+
+int main(int argc, char **argv) {
+ int b = argc, c, d, e, f, h;
+ int arr[5][10], arr1[5];
+ int i, j;
+ int s;
+ static int a;
+// CHECK: static int a;
+ const int clen = 5;
+// CHECK: int clen = 5;
+ static float g;
+#pragma omp threadprivate(g)
+ int *p;
+#pragma omp target simd linear(a)
+ // CHECK: #pragma omp target simd linear(a)
+ for (int i = 0; i < 2; ++i)
+ a = 2;
+// CHECK-NEXT: for (int i = 0; i < 2; ++i)
+// CHECK-NEXT: a = 2;
+
+#pragma omp target simd private(argc, b), firstprivate(argv, c), lastprivate(d, f) collapse(2) if (target: argc) reduction(+ : h) linear(a:-5)
+ for (int i = 0; i < 10; ++i)
+ for (int j = 0; j < 10; ++j)
+ foo();
+ // CHECK: #pragma omp target simd private(argc,b) firstprivate(argv,c) lastprivate(d,f) collapse(2) if(target: argc) reduction(+: h) linear(a: -5)
+ // CHECK-NEXT: for (int i = 0; i < 10; ++i)
+ // CHECK-NEXT: for (int j = 0; j < 10; ++j)
+ // CHECK-NEXT: foo();
+
+#pragma omp target simd private(argc,b) firstprivate(argv) if (argc > 0) reduction(+:c, arr1[argc]) reduction(max:e, arr[:5][0:10])
+ for (int i = 0; i < 2; ++i) {}
+ // CHECK: #pragma omp target simd private(argc,b) firstprivate(argv) if(argc > 0) reduction(+: c,arr1[argc]) reduction(max: e,arr[:5][0:10])
+ // CHECK-NEXT: for (int i = 0; i < 2; ++i) {
+ // CHECK-NEXT: }
+
+#pragma omp target simd if (5) reduction(^:e, f, arr[0:5][:argc]) reduction(&& : h)
+ for (int i = 0; i < 2; ++i) {}
+ // CHECK: #pragma omp target simd if(5) reduction(^: e,f,arr[0:5][:argc]) reduction(&&: h)
+ // CHECK-NEXT: for (int i = 0; i < 2; ++i) {
+ // CHECK-NEXT: }
+
+#pragma omp target simd if (target:argc > 0)
+ for (int i = 0; i < 2; ++i) {}
+ // CHECK: #pragma omp target simd if(target: argc > 0)
+ // CHECK-NEXT: for (int i = 0; i < 2; ++i) {
+ // CHECK-NEXT: }
+
+#pragma omp target simd if (5)
+ for (int i = 0; i < 2; ++i) {}
+ // CHECK: #pragma omp target simd if(5)
+ // CHECK-NEXT: for (int i = 0; i < 2; ++i) {
+ // CHECK-NEXT: }
+
+#pragma omp target simd map(i)
+ for (int i = 0; i < 2; ++i) {}
+ // CHECK: #pragma omp target simd map(tofrom: i)
+ // CHECK-NEXT: for (int i = 0; i < 2; ++i) {
+ // CHECK-NEXT: }
+
+#pragma omp target simd map(arr1[0:10], i)
+ for (int i = 0; i < 2; ++i) {}
+ // CHECK: #pragma omp target simd map(tofrom: arr1[0:10],i)
+ // CHECK-NEXT: for (int i = 0; i < 2; ++i) {
+ // CHECK-NEXT: }
+
+#pragma omp target simd map(to: i) map(from: j)
+ for (int i = 0; i < 2; ++i) {}
+ // CHECK: #pragma omp target simd map(to: i) map(from: j)
+ // CHECK-NEXT: for (int i = 0; i < 2; ++i) {
+ // CHECK-NEXT: }
+
+#pragma omp target simd map(always,alloc: i)
+ for (int i = 0; i < 2; ++i) {}
+ // CHECK: #pragma omp target simd map(always,alloc: i)
+ // CHECK-NEXT: for (int i = 0; i < 2; ++i) {
+ // CHECK-NEXT: }
+
+#pragma omp target simd nowait
+ for (int i = 0; i < 2; ++i) {}
+ // CHECK: #pragma omp target simd nowait
+ // CHECK-NEXT: for (int i = 0; i < 2; ++i) {
+ // CHECK-NEXT: }
+
+#pragma omp target simd depend(in : argc, arr[i:argc], arr1[:])
+ for (int i = 0; i < 2; ++i) {}
+ // CHECK: #pragma omp target simd depend(in : argc,arr[i:argc],arr1[:])
+ // CHECK-NEXT: for (int i = 0; i < 2; ++i) {
+ // CHECK-NEXT: }
+
+#pragma omp target simd defaultmap(tofrom: scalar)
+ for (int i = 0; i < 2; ++i) {}
+ // CHECK: #pragma omp target simd defaultmap(tofrom: scalar)
+ // CHECK-NEXT: for (int i = 0; i < 2; ++i) {
+ // CHECK-NEXT: }
+
+#pragma omp target simd safelen(clen-1)
+ for (int i = 0; i < 2; ++i) {}
+ // CHECK: #pragma omp target simd safelen(clen - 1)
+ // CHECK-NEXT: for (int i = 0; i < 2; ++i) {
+ // CHECK-NEXT: }
+
+#pragma omp target simd simdlen(clen-1)
+ for (int i = 0; i < 2; ++i) {}
+ // CHECK: #pragma omp target simd simdlen(clen - 1)
+ // CHECK-NEXT: for (int i = 0; i < 2; ++i) {
+ // CHECK-NEXT: }
+
+#pragma omp target simd aligned(arr1:4)
+ for (int i = 0; i < 2; ++i) {}
+ // CHECK: #pragma omp target simd aligned(arr1: 4)
+ // CHECK-NEXT: for (int i = 0; i < 2; ++i) {
+ // CHECK-NEXT: }
+
+#pragma omp target simd is_device_ptr(p)
+ for (int i = 0; i < 2; ++i) {}
+ // CHECK: #pragma omp target simd is_device_ptr(p)
+ // CHECK-NEXT: for (int i = 0; i < 2; ++i) {
+ // CHECK-NEXT: }
+
+ return (tmain<int, 5>(argc, &argc));
+}
+
+#endif
diff --git a/test/OpenMP/target_simd_collapse_messages.cpp b/test/OpenMP/target_simd_collapse_messages.cpp
new file mode 100644
index 000000000000..ce42273cd259
--- /dev/null
+++ b/test/OpenMP/target_simd_collapse_messages.cpp
@@ -0,0 +1,100 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+
+void foo() {
+}
+
+#if __cplusplus >= 201103L
+// expected-note@+2 4 {{declared here}}
+#endif
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}}
+
+template <class T, typename S, int N, int ST> // expected-note {{declared here}}
+T tmain(T argc, S **argv) { //expected-note 2 {{declared here}}
+ int j; // expected-note {{declared here}}
+ #pragma omp target simd collapse // expected-error {{expected '(' after 'collapse'}}
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+ #pragma omp target simd collapse ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+ #pragma omp target simd collapse () // expected-error {{expected expression}}
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+ // expected-error@+3 {{expected ')'}} expected-note@+3 {{to match this '('}}
+ // expected-error@+2 2 {{expression is not an integral constant expression}}
+ // expected-note@+1 2 {{read of non-const variable 'argc' is not allowed in a constant expression}}
+ #pragma omp target simd collapse (argc
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+ // expected-error@+1 2 {{argument to 'collapse' clause must be a strictly positive integer value}}
+ #pragma omp target simd collapse (ST // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+ #pragma omp target simd collapse (1)) // expected-warning {{extra tokens at the end of '#pragma omp target simd' are ignored}}
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+ #pragma omp target simd collapse ((ST > 0) ? 1 + ST : 2) // expected-note 2 {{as specified in 'collapse' clause}}
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST]; // expected-error 2 {{expected 2 for loops after '#pragma omp target simd', but found only 1}}
+#if __cplusplus >= 201103L
+ // expected-note@+5 2 {{non-constexpr function 'foobool' cannot be used in a constant expression}}
+#endif
+ // expected-error@+3 2 {{directive '#pragma omp target simd' cannot contain more than one 'collapse' clause}}
+ // expected-error@+2 2 {{argument to 'collapse' clause must be a strictly positive integer value}}
+ // expected-error@+1 2 {{expression is not an integral constant expression}}
+ #pragma omp target simd collapse (foobool(argc)), collapse (true), collapse (-5)
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+ #pragma omp target simd collapse (S) // expected-error {{'S' does not refer to a value}}
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+ // expected-note@+2 {{read of non-const variable 'j' is not allowed in a constant expression}}
+ // expected-error@+1 {{expression is not an integral constant expression}}
+ #pragma omp target simd collapse (j=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+ #pragma omp target simd collapse (1)
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+ #pragma omp target simd collapse (N) // expected-error {{argument to 'collapse' clause must be a strictly positive integer value}}
+ for (T i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+ #pragma omp target simd collapse (2) // expected-note {{as specified in 'collapse' clause}}
+ foo(); // expected-error {{expected 2 for loops after '#pragma omp target simd'}}
+ return argc;
+}
+
+int main(int argc, char **argv) {
+ int j; // expected-note {{declared here}}
+ #pragma omp target simd collapse // expected-error {{expected '(' after 'collapse'}}
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+ #pragma omp target simd collapse ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+ #pragma omp target simd collapse () // expected-error {{expected expression}}
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+ #pragma omp target simd collapse (4 // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-note {{as specified in 'collapse' clause}}
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4]; // expected-error {{expected 4 for loops after '#pragma omp target simd', but found only 1}}
+ #pragma omp target simd collapse (2+2)) // expected-warning {{extra tokens at the end of '#pragma omp target simd' are ignored}} expected-note {{as specified in 'collapse' clause}}
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4]; // expected-error {{expected 4 for loops after '#pragma omp target simd', but found only 1}}
+#if __cplusplus >= 201103L
+ // expected-note@+2 {{non-constexpr function 'foobool' cannot be used in a constant expression}}
+#endif
+ #pragma omp target simd collapse (foobool(1) > 0 ? 1 : 2) // expected-error {{expression is not an integral constant expression}}
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+#if __cplusplus >= 201103L
+ // expected-note@+5 {{non-constexpr function 'foobool' cannot be used in a constant expression}}
+#endif
+ // expected-error@+3 {{expression is not an integral constant expression}}
+ // expected-error@+2 2 {{directive '#pragma omp target simd' cannot contain more than one 'collapse' clause}}
+ // expected-error@+1 2 {{argument to 'collapse' clause must be a strictly positive integer value}}
+ #pragma omp target simd collapse (foobool(argc)), collapse (true), collapse (-5)
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+ #pragma omp target simd collapse (S1) // expected-error {{'S1' does not refer to a value}}
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+ // expected-note@+2 {{read of non-const variable 'j' is not allowed in a constant expression}}
+ // expected-error@+1 {{expression is not an integral constant expression}}
+ #pragma omp target simd collapse (j=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+ // expected-error@+3 {{statement after '#pragma omp target simd' must be a for loop}}
+ // expected-note@+1 {{in instantiation of function template specialization 'tmain<int, char, -1, -2>' requested here}}
+ #pragma omp target simd collapse(collapse(tmain<int, char, -1, -2>(argc, argv) // expected-error 2 {{expected ')'}} expected-note 2 {{to match this '('}}
+ foo();
+ #pragma omp target simd collapse (2) // expected-note {{as specified in 'collapse' clause}}
+ foo(); // expected-error {{expected 2 for loops after '#pragma omp target simd'}}
+ // expected-note@+1 {{in instantiation of function template specialization 'tmain<int, char, 1, 0>' requested here}}
+ return tmain<int, char, 1, 0>(argc, argv);
+}
+
diff --git a/test/OpenMP/target_simd_defaultmap_messages.cpp b/test/OpenMP/target_simd_defaultmap_messages.cpp
new file mode 100644
index 000000000000..4f622136b13e
--- /dev/null
+++ b/test/OpenMP/target_simd_defaultmap_messages.cpp
@@ -0,0 +1,58 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo() {
+}
+
+template <class T, typename S, int N, int ST>
+T tmain(T argc, S **argv) {
+ int i;
+ #pragma omp target simd defaultmap // expected-error {{expected '(' after 'defaultmap'}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd defaultmap ( // expected-error {{expected 'tofrom' in OpenMP clause 'defaultmap'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd defaultmap () // expected-error {{expected 'tofrom' in OpenMP clause 'defaultmap'}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd defaultmap (tofrom // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-warning {{missing ':' after defaultmap modifier - ignoring}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd defaultmap (tofrom: // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd defaultmap (tofrom) // expected-warning {{missing ':' after defaultmap modifier - ignoring}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd defaultmap (tofrom scalar) // expected-warning {{missing ':' after defaultmap modifier - ignoring}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd defaultmap (tofrom, // expected-error {{expected ')'}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}} expected-warning {{missing ':' after defaultmap modifier - ignoring}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd defaultmap (scalar: // expected-error {{expected ')'}} expected-error {{expected 'tofrom' in OpenMP clause 'defaultmap'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd defaultmap (tofrom, scalar // expected-error {{expected ')'}} expected-warning {{missing ':' after defaultmap modifier - ignoring}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+ return argc;
+}
+
+int main(int argc, char **argv) {
+ int i;
+ #pragma omp target simd defaultmap // expected-error {{expected '(' after 'defaultmap'}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd defaultmap ( // expected-error {{expected 'tofrom' in OpenMP clause 'defaultmap'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd defaultmap () // expected-error {{expected 'tofrom' in OpenMP clause 'defaultmap'}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd defaultmap (tofrom // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-warning {{missing ':' after defaultmap modifier - ignoring}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd defaultmap (tofrom: // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd defaultmap (tofrom) // expected-warning {{missing ':' after defaultmap modifier - ignoring}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd defaultmap (tofrom scalar) // expected-warning {{missing ':' after defaultmap modifier - ignoring}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd defaultmap (tofrom, // expected-error {{expected ')'}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}} expected-warning {{missing ':' after defaultmap modifier - ignoring}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd defaultmap (scalar: // expected-error {{expected ')'}} expected-error {{expected 'tofrom' in OpenMP clause 'defaultmap'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd defaultmap (tofrom, scalar // expected-error {{expected ')'}} expected-warning {{missing ':' after defaultmap modifier - ignoring}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+ return tmain<int, char, 1, 0>(argc, argv);
+}
+
diff --git a/test/OpenMP/target_simd_depend_messages.cpp b/test/OpenMP/target_simd_depend_messages.cpp
new file mode 100644
index 000000000000..3fc46f4c0848
--- /dev/null
+++ b/test/OpenMP/target_simd_depend_messages.cpp
@@ -0,0 +1,90 @@
+// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}}
+
+class vector {
+ public:
+ int operator[](int index) { return 0; }
+};
+
+int main(int argc, char **argv, char *env[]) {
+ vector vec;
+ typedef float V __attribute__((vector_size(16)));
+ V a;
+ auto arr = x; // expected-error {{use of undeclared identifier 'x'}}
+ int i;
+
+ #pragma omp target simd depend // expected-error {{expected '(' after 'depend'}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd depend ( // expected-error {{expected 'in', 'out' or 'inout' in OpenMP clause 'depend'}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-warning {{missing ':' after dependency type - ignoring}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd depend () // expected-error {{expected 'in', 'out' or 'inout' in OpenMP clause 'depend'}} expected-warning {{missing ':' after dependency type - ignoring}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd depend (argc // expected-error {{expected 'in', 'out' or 'inout' in OpenMP clause 'depend'}} expected-warning {{missing ':' after dependency type - ignoring}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd depend (source : argc) // expected-error {{expected 'in', 'out' or 'inout' in OpenMP clause 'depend'}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd depend (source) // expected-error {{expected expression}} expected-warning {{missing ':' after dependency type - ignoring}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd depend (in : argc)) // expected-warning {{extra tokens at the end of '#pragma omp target simd' are ignored}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd depend (out: ) // expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd depend (inout : foobool(argc)), depend (in, argc) // expected-error {{expected variable name, array element or array section}} expected-warning {{missing ':' after dependency type - ignoring}} expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd depend (out :S1) // expected-error {{'S1' does not refer to a value}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd depend(in : argv[1][1] = '2') // expected-error {{expected variable name, array element or array section}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd depend (in : vec[1]) // expected-error {{expected variable name, array element or array section}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd depend (in : argv[0])
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd depend (in : ) // expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd depend (in : main) // expected-error {{expected variable name, array element or array section}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd depend(in : a[0]) // expected-error{{expected variable name, array element or array section}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd depend (in : vec[1:2]) // expected-error {{ value is not an array or pointer}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd depend (in : argv[ // expected-error {{expected expression}} expected-error {{expected ']'}} expected-error {{expected ')'}} expected-note {{to match this '['}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd depend (in : argv[: // expected-error {{expected expression}} expected-error {{expected ']'}} expected-error {{expected ')'}} expected-note {{to match this '['}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd depend (in : argv[:] // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd depend (in : argv[argc: // expected-error {{expected expression}} expected-error {{expected ']'}} expected-error {{expected ')'}} expected-note {{to match this '['}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd depend (in : argv[argc:argc] // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd depend (in : argv[0:-1]) // expected-error {{section length is evaluated to a negative value -1}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd depend (in : argv[-1:0]) // OK
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd depend (in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd depend (in : argv[3:4:1]) // expected-error {{expected ']'}} expected-note {{to match this '['}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd depend(in:a[0:1]) // expected-error {{subscripted value is not an array or pointer}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd depend(in:argv[argv[:2]:1]) // expected-error {{OpenMP array section is not allowed here}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd depend(in:argv[0:][:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd depend(in:env[0:][:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is an array of unknown bound}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd depend(in : argv[ : argc][1 : argc - 1])
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd depend(in : arr[0])
+ for (i = 0; i < argc; ++i) foo();
+
+ return 0;
+}
diff --git a/test/OpenMP/target_simd_device_messages.cpp b/test/OpenMP/target_simd_device_messages.cpp
new file mode 100644
index 000000000000..1e9afc3bb179
--- /dev/null
+++ b/test/OpenMP/target_simd_device_messages.cpp
@@ -0,0 +1,40 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}}
+
+int main(int argc, char **argv) {
+ int i;
+ #pragma omp target simd device // expected-error {{expected '(' after 'device'}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd device ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd device () // expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd device (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd device (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target simd' are ignored}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd device (argc > 0 ? argv[1] : argv[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd device (argc + argc)
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd device (argc), device (argc+1) // expected-error {{directive '#pragma omp target simd' cannot contain more than one 'device' clause}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd device (S1) // expected-error {{'S1' does not refer to a value}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd device (-2) // expected-error {{argument to 'device' clause must be a non-negative integer value}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd device (-10u)
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd device (3.14) // expected-error {{expression must have integral or unscoped enumeration type, not 'double'}}
+ for (i = 0; i < argc; ++i) foo();
+
+ return 0;
+}
diff --git a/test/OpenMP/target_simd_firstprivate_messages.cpp b/test/OpenMP/target_simd_firstprivate_messages.cpp
new file mode 100644
index 000000000000..5bfd951ff81e
--- /dev/null
+++ b/test/OpenMP/target_simd_firstprivate_messages.cpp
@@ -0,0 +1,261 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note 2 {{declared here}} expected-note 2 {{forward declaration of 'S1'}}
+extern S1 a;
+class S2 {
+ mutable int a;
+
+public:
+ S2() : a(0) {}
+ S2(const S2 &s2) : a(s2.a) {}
+ static float S2s;
+ static const float S2sc;
+};
+const float S2::S2sc = 0;
+const S2 b;
+const S2 ba[5];
+class S3 {
+ int a;
+ S3 &operator=(const S3 &s3);
+
+public:
+ S3() : a(0) {}
+ S3(const S3 &s3) : a(s3.a) {}
+};
+const S3 c;
+const S3 ca[5];
+extern const int f;
+class S4 {
+ int a;
+ S4();
+ S4(const S4 &s4); // expected-note 2 {{implicitly declared private here}}
+
+public:
+ S4(int v) : a(v) {}
+};
+class S5 {
+ int a;
+ S5(const S5 &s5) : a(s5.a) {} // expected-note 4 {{implicitly declared private here}}
+
+public:
+ S5() : a(0) {}
+ S5(int v) : a(v) {}
+};
+class S6 {
+ int a;
+ S6() : a(0) {}
+
+public:
+ S6(const S6 &s6) : a(s6.a) {}
+ S6(int v) : a(v) {}
+};
+
+S3 h;
+#pragma omp threadprivate(h) // expected-note 2 {{defined as threadprivate or thread local}}
+
+template <class I, class C>
+int foomain(int argc, char **argv) {
+ I e(4);
+ C g(5);
+ int i;
+ int &j = i;
+#pragma omp target simd firstprivate // expected-error {{expected '(' after 'firstprivate'}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd firstprivate( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd firstprivate() // expected-error {{expected expression}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd firstprivate(argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd firstprivate(argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd firstprivate(argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd firstprivate(argc)
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd firstprivate(S1) // expected-error {{'S1' does not refer to a value}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd firstprivate(a, b) // expected-error {{firstprivate variable with incomplete type 'S1'}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd firstprivate(argv[1]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd firstprivate(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd firstprivate(h) // expected-error {{threadprivate or thread local variable cannot be firstprivate}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp parallel
+ {
+ int v = 0;
+ int i;
+#pragma omp target simd firstprivate(i)
+ for (int k = 0; k < argc; ++k) {
+ i = k;
+ v += i;
+ }
+ }
+#pragma omp parallel shared(i)
+#pragma omp parallel private(i)
+#pragma omp target simd firstprivate(j)
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd firstprivate(i)
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd lastprivate(g) firstprivate(g) // expected-error {{calling a private constructor of class 'S5'}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp parallel private(i)
+#pragma omp target simd firstprivate(i) // expected-note {{defined as firstprivate}}
+ for (i = 0; i < argc; ++i) // expected-error {{loop iteration variable in the associated loop of 'omp target simd' directive may not be firstprivate, predetermined as linear}}
+ foo();
+#pragma omp parallel reduction(+ : i)
+#pragma omp target simd firstprivate(i) // expected-note {{defined as firstprivate}}
+ for (i = 0; i < argc; ++i) // expected-error {{loop iteration variable in the associated loop of 'omp target simd' directive may not be firstprivate, predetermined as linear}}
+ foo();
+ return 0;
+}
+
+namespace A {
+double x;
+#pragma omp threadprivate(x) // expected-note {{defined as threadprivate or thread local}}
+}
+namespace B {
+using A::x;
+}
+
+int main(int argc, char **argv) {
+ const int d = 5;
+ const int da[5] = {0};
+ S4 e(4);
+ S5 g(5);
+ S3 m;
+ S6 n(2);
+ int i;
+ int &j = i;
+#pragma omp target simd firstprivate // expected-error {{expected '(' after 'firstprivate'}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd firstprivate( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd firstprivate() // expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd firstprivate(argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd firstprivate(argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd firstprivate(argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd firstprivate(argc)
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd firstprivate(S1) // expected-error {{'S1' does not refer to a value}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd firstprivate(a, b, c, d, f) // expected-error {{firstprivate variable with incomplete type 'S1'}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd firstprivate(argv[1]) // expected-error {{expected variable name}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd firstprivate(2 * 2) // expected-error {{expected variable name}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd firstprivate(ba) // OK
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd firstprivate(ca) // OK
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd firstprivate(da) // OK
+ for (i = 0; i < argc; ++i)
+ foo();
+ int xa;
+#pragma omp target simd firstprivate(xa) // OK
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd firstprivate(S2::S2s) // OK
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd firstprivate(S2::S2sc) // OK
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd safelen(5) // OK
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd firstprivate(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd firstprivate(m) // OK
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd firstprivate(h, B::x) // expected-error 2 {{threadprivate or thread local variable cannot be firstprivate}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd private(xa), firstprivate(xa) // expected-error {{private variable cannot be firstprivate}} expected-note {{defined as private}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd firstprivate(i) // expected-note {{defined as firstprivate}}
+ for (i = 0; i < argc; ++i) // expected-error {{loop iteration variable in the associated loop of 'omp target simd' directive may not be firstprivate, predetermined as linear}}
+ foo();
+#pragma omp parallel shared(xa)
+#pragma omp target simd firstprivate(xa) // OK: may be firstprivate
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd firstprivate(j)
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd lastprivate(g) firstprivate(g) // expected-error {{calling a private constructor of class 'S5'}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd lastprivate(n) firstprivate(n) // OK
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp parallel
+ {
+ int v = 0;
+ int i;
+#pragma omp target simd firstprivate(i)
+ for (int k = 0; k < argc; ++k) {
+ i = k;
+ v += i;
+ }
+ }
+#pragma omp parallel private(i)
+#pragma omp target simd firstprivate(i) // expected-note {{defined as firstprivate}}
+ for (i = 0; i < argc; ++i) // expected-error {{loop iteration variable in the associated loop of 'omp target simd' directive may not be firstprivate, predetermined as linear}}
+ foo();
+#pragma omp parallel reduction(+ : i)
+#pragma omp target simd firstprivate(i) // expected-note {{defined as firstprivate}}
+ for (i = 0; i < argc; ++i) // expected-error {{loop iteration variable in the associated loop of 'omp target simd' directive may not be firstprivate, predetermined as linear}}
+ foo();
+ static int si;
+#pragma omp target simd firstprivate(si) // OK
+ for (i = 0; i < argc; ++i)
+ si = i + 1;
+
+ return foomain<S4, S5>(argc, argv); // expected-note {{in instantiation of function template specialization 'foomain<S4, S5>' requested here}}
+}
diff --git a/test/OpenMP/target_simd_if_messages.cpp b/test/OpenMP/target_simd_if_messages.cpp
new file mode 100644
index 000000000000..ff68f6f21602
--- /dev/null
+++ b/test/OpenMP/target_simd_if_messages.cpp
@@ -0,0 +1,91 @@
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}}
+
+template <class T, class S> // expected-note {{declared here}}
+int tmain(T argc, S **argv) {
+ int i;
+ #pragma omp target simd if // expected-error {{expected '(' after 'if'}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd if ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd if () // expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd if (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd if (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target simd' are ignored}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd if (argc > 0 ? argv[1] : argv[2])
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd if (foobool(argc)), if (true) // expected-error {{directive '#pragma omp target simd' cannot contain more than one 'if' clause}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd if (S) // expected-error {{'S' does not refer to a value}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd if (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd if (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd if(argc)
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd if(target : // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd if(target : argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd if(target : argc)
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd if(target : argc) if (simd:argc) // expected-error {{directive name modifier 'simd' is not allowed for '#pragma omp target simd'}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd if(target : argc) if (target :argc) // expected-error {{directive '#pragma omp target simd' cannot contain more than one 'if' clause with 'target' name modifier}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd if(target : argc) if (argc) // expected-note {{previous clause with directive name modifier specified here}} expected-error {{no more 'if' clause is allowed}}
+ for (i = 0; i < argc; ++i) foo();
+
+ return 0;
+}
+
+int main(int argc, char **argv) {
+ int i;
+ #pragma omp target simd if // expected-error {{expected '(' after 'if'}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd if ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd if () // expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd if (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd if (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target simd' are ignored}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd if (argc > 0 ? argv[1] : argv[2])
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd if (foobool(argc)), if (true) // expected-error {{directive '#pragma omp target simd' cannot contain more than one 'if' clause}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd if (S1) // expected-error {{'S1' does not refer to a value}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd if (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd if (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd if (1 0) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd if(if(tmain(argc, argv) // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd if(target : // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd if(target : argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd if(target : argc) if (simd:argc) // expected-error {{directive name modifier 'simd' is not allowed for '#pragma omp target simd'}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd if(target : argc) if (target :argc) // expected-error {{directive '#pragma omp target simd' cannot contain more than one 'if' clause with 'target' name modifier}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd if(target : argc) if (argc) // expected-note {{previous clause with directive name modifier specified here}} expected-error {{no more 'if' clause is allowed}}
+ for (i = 0; i < argc; ++i) foo();
+
+ return tmain(argc, argv);
+}
diff --git a/test/OpenMP/target_simd_is_device_ptr_messages.cpp b/test/OpenMP/target_simd_is_device_ptr_messages.cpp
new file mode 100644
index 000000000000..02e2b326c742
--- /dev/null
+++ b/test/OpenMP/target_simd_is_device_ptr_messages.cpp
@@ -0,0 +1,288 @@
+// RUN: %clang_cc1 -std=c++11 -verify -fopenmp %s
+
+struct ST {
+ int *a;
+};
+typedef int arr[10];
+typedef ST STarr[10];
+struct SA {
+ const int d = 5;
+ const int da[5] = { 0 };
+ ST e;
+ ST g[10];
+ STarr &rg = g;
+ int i;
+ int &j = i;
+ int *k = &j;
+ int *&z = k;
+ int aa[10];
+ arr &raa = aa;
+ void func(int arg) {
+#pragma omp target simd is_device_ptr // expected-error {{expected '(' after 'is_device_ptr'}}
+ for (int ii=0; ii<10; ii++)
+ ;
+#pragma omp target simd is_device_ptr( // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}}
+ for (int ii=0; ii<10; ii++)
+ ;
+#pragma omp target simd is_device_ptr() // expected-error {{expected expression}}
+ for (int ii=0; ii<10; ii++)
+ ;
+#pragma omp target simd is_device_ptr(alloc) // expected-error {{use of undeclared identifier 'alloc'}}
+ for (int ii=0; ii<10; ii++)
+ ;
+#pragma omp target simd is_device_ptr(arg // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ for (int ii=0; ii<10; ii++)
+ ;
+#pragma omp target simd is_device_ptr(i) // expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ for (int ii=0; ii<10; ii++)
+ ;
+#pragma omp target simd is_device_ptr(j) // expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ for (int ii=0; ii<10; ii++)
+ ;
+#pragma omp target simd is_device_ptr(k) // OK
+ for (int ii=0; ii<10; ii++)
+ ;
+#pragma omp target simd is_device_ptr(z) // OK
+ for (int ii=0; ii<10; ii++)
+ ;
+#pragma omp target simd is_device_ptr(aa) // OK
+ for (int ii=0; ii<10; ii++)
+ ;
+#pragma omp target simd is_device_ptr(raa) // OK
+ for (int ii=0; ii<10; ii++)
+ ;
+#pragma omp target simd is_device_ptr(e) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ for (int ii=0; ii<10; ii++)
+ ;
+#pragma omp target simd is_device_ptr(g) // OK
+ for (int ii=0; ii<10; ii++)
+ ;
+#pragma omp target simd is_device_ptr(rg) // OK
+ for (int ii=0; ii<10; ii++)
+ ;
+#pragma omp target simd is_device_ptr(k,i,j) // expected-error2 {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ for (int ii=0; ii<10; ii++)
+ ;
+#pragma omp target simd is_device_ptr(d) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ for (int ii=0; ii<10; ii++)
+ ;
+#pragma omp target simd is_device_ptr(da) // OK
+ for (int ii=0; ii<10; ii++)
+ ;
+ return;
+ }
+};
+struct SB {
+ unsigned A;
+ unsigned B;
+ float Arr[100];
+ float *Ptr;
+ float *foo() {
+ return &Arr[0];
+ }
+};
+
+struct SC {
+ unsigned A : 2;
+ unsigned B : 3;
+ unsigned C;
+ unsigned D;
+ float Arr[100];
+ SB S;
+ SB ArrS[100];
+ SB *PtrS;
+ SB *&RPtrS;
+ float *Ptr;
+
+ SC(SB *&_RPtrS) : RPtrS(_RPtrS) {}
+};
+
+union SD {
+ unsigned A;
+ float B;
+};
+
+struct S1;
+extern S1 a;
+class S2 {
+ mutable int a;
+public:
+ S2():a(0) { }
+ S2(S2 &s2):a(s2.a) { }
+ static float S2s;
+ static const float S2sc;
+};
+const float S2::S2sc = 0;
+const S2 b;
+const S2 ba[5];
+class S3 {
+ int a;
+public:
+ S3():a(0) { }
+ S3(S3 &s3):a(s3.a) { }
+};
+const S3 c;
+const S3 ca[5];
+extern const int f;
+class S4 {
+ int a;
+ S4();
+ S4(const S4 &s4);
+public:
+ S4(int v):a(v) { }
+};
+class S5 {
+ int a;
+ S5():a(0) {}
+ S5(const S5 &s5):a(s5.a) { }
+public:
+ S5(int v):a(v) { }
+};
+
+S3 h;
+#pragma omp threadprivate(h)
+
+typedef struct {
+ int a;
+} S6;
+
+template <typename T, int I>
+T tmain(T argc) {
+ const T d = 5;
+ const T da[5] = { 0 };
+ S4 e(4);
+ S5 g(5);
+ S6 h[10];
+ auto &rh = h;
+ T i;
+ T &j = i;
+ T *k = &j;
+ T *&z = k;
+ T aa[10];
+ auto &raa = aa;
+#pragma omp target simd is_device_ptr // expected-error {{expected '(' after 'is_device_ptr'}}
+ for (int kk=0; kk<20; kk++)
+ ;
+#pragma omp target simd is_device_ptr( // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}}
+ for (int kk=0; kk<20; kk++)
+ ;
+#pragma omp target simd is_device_ptr() // expected-error {{expected expression}}
+ for (int kk=0; kk<20; kk++)
+ ;
+#pragma omp target simd is_device_ptr(alloc) // expected-error {{use of undeclared identifier 'alloc'}}
+ for (int kk=0; kk<20; kk++)
+ ;
+#pragma omp target simd is_device_ptr(argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ for (int kk=0; kk<20; kk++)
+ ;
+#pragma omp target simd is_device_ptr(i) // expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ for (int kk=0; kk<20; kk++)
+ ;
+#pragma omp target simd is_device_ptr(j) // expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ for (int kk=0; kk<20; kk++)
+ ;
+#pragma omp target simd is_device_ptr(k) // OK
+ for (int kk=0; kk<20; kk++)
+ ;
+#pragma omp target simd is_device_ptr(z) // OK
+ for (int kk=0; kk<20; kk++)
+ ;
+#pragma omp target simd is_device_ptr(aa) // OK
+ for (int kk=0; kk<20; kk++)
+ ;
+#pragma omp target simd is_device_ptr(raa) // OK
+ for (int kk=0; kk<20; kk++)
+ ;
+#pragma omp target simd is_device_ptr(e) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ for (int kk=0; kk<20; kk++)
+ ;
+#pragma omp target simd is_device_ptr(g) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ for (int kk=0; kk<20; kk++)
+ ;
+#pragma omp target simd is_device_ptr(h) // OK
+ for (int kk=0; kk<20; kk++)
+ ;
+#pragma omp target simd is_device_ptr(rh) // OK
+ for (int kk=0; kk<20; kk++)
+ ;
+#pragma omp target simd is_device_ptr(k,i,j) // expected-error2 {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ for (int kk=0; kk<20; kk++)
+ ;
+#pragma omp target simd is_device_ptr(d) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ for (int kk=0; kk<20; kk++)
+ ;
+#pragma omp target simd is_device_ptr(da) // OK
+ for (int kk=0; kk<20; kk++)
+ ;
+ return 0;
+}
+
+int main(int argc, char **argv) {
+ const int d = 5;
+ const int da[5] = { 0 };
+ S4 e(4);
+ S5 g(5);
+ S6 h[10];
+ auto &rh = h;
+ int i;
+ int &j = i;
+ int *k = &j;
+ int *&z = k;
+ int aa[10];
+ auto &raa = aa;
+#pragma omp target simd is_device_ptr // expected-error {{expected '(' after 'is_device_ptr'}}
+ for (int kk=0; kk<20; kk++)
+ ;
+#pragma omp target simd is_device_ptr( // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}}
+ for (int kk=0; kk<20; kk++)
+ ;
+#pragma omp target simd is_device_ptr() // expected-error {{expected expression}}
+ for (int kk=0; kk<20; kk++)
+ ;
+#pragma omp target simd is_device_ptr(alloc) // expected-error {{use of undeclared identifier 'alloc'}}
+ for (int kk=0; kk<20; kk++)
+ ;
+#pragma omp target simd is_device_ptr(argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ for (int kk=0; kk<20; kk++)
+ ;
+#pragma omp target simd is_device_ptr(i) // expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ for (int kk=0; kk<20; kk++)
+ ;
+#pragma omp target simd is_device_ptr(j) // expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ for (int kk=0; kk<20; kk++)
+ ;
+#pragma omp target simd is_device_ptr(k) // OK
+ for (int kk=0; kk<20; kk++)
+ ;
+#pragma omp target simd is_device_ptr(z) // OK
+ for (int kk=0; kk<20; kk++)
+ ;
+#pragma omp target simd is_device_ptr(aa) // OK
+ for (int kk=0; kk<20; kk++)
+ ;
+#pragma omp target simd is_device_ptr(raa) // OK
+ for (int kk=0; kk<20; kk++)
+ ;
+#pragma omp target simd is_device_ptr(e) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ for (int kk=0; kk<20; kk++)
+ ;
+#pragma omp target simd is_device_ptr(g) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ for (int kk=0; kk<20; kk++)
+ ;
+#pragma omp target simd is_device_ptr(h) // OK
+ for (int kk=0; kk<20; kk++)
+ ;
+#pragma omp target simd is_device_ptr(rh) // OK
+ for (int kk=0; kk<20; kk++)
+ ;
+#pragma omp target simd is_device_ptr(k,i,j) // expected-error2 {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ for (int kk=0; kk<20; kk++)
+ ;
+#pragma omp target simd is_device_ptr(d) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ for (int kk=0; kk<20; kk++)
+ ;
+#pragma omp target simd is_device_ptr(da) // OK
+ for (int kk=0; kk<20; kk++)
+ ;
+ return tmain<int, 3>(argc); // expected-note {{in instantiation of function template specialization 'tmain<int, 3>' requested here}}
+}
diff --git a/test/OpenMP/target_simd_lastprivate_messages.cpp b/test/OpenMP/target_simd_lastprivate_messages.cpp
new file mode 100644
index 000000000000..afb38d9c9222
--- /dev/null
+++ b/test/OpenMP/target_simd_lastprivate_messages.cpp
@@ -0,0 +1,238 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note 2 {{declared here}} expected-note 2 {{forward declaration of 'S1'}}
+extern S1 a;
+class S2 {
+ mutable int a;
+
+public:
+ S2() : a(0) {}
+ S2(S2 &s2) : a(s2.a) {}
+ S2 &operator=(const S2 &);
+ const S2 &operator=(const S2 &) const;
+ static float S2s; // expected-note {{static data member is predetermined as shared}}
+ static const float S2sc;
+};
+const float S2::S2sc = 0; // expected-note {{static data member is predetermined as shared}}
+const S2 b;
+const S2 ba[5];
+class S3 {
+ int a;
+ S3 &operator=(const S3 &s3); // expected-note 2 {{implicitly declared private here}}
+
+public:
+ S3() : a(0) {}
+ S3(S3 &s3) : a(s3.a) {}
+};
+const S3 c; // expected-note {{global variable is predetermined as shared}}
+const S3 ca[5]; // expected-note {{global variable is predetermined as shared}}
+extern const int f; // expected-note {{global variable is predetermined as shared}}
+class S4 {
+ int a;
+ S4(); // expected-note 3 {{implicitly declared private here}}
+ S4(const S4 &s4);
+
+public:
+ S4(int v) : a(v) {}
+};
+class S5 {
+ int a;
+ S5() : a(0) {} // expected-note {{implicitly declared private here}}
+
+public:
+ S5(const S5 &s5) : a(s5.a) {}
+ S5(int v) : a(v) {}
+};
+class S6 {
+ int a;
+ S6() : a(0) {}
+
+public:
+ S6(const S6 &s6) : a(s6.a) {}
+ S6(int v) : a(v) {}
+};
+
+S3 h;
+#pragma omp threadprivate(h) // expected-note 2 {{defined as threadprivate or thread local}}
+
+template <class I, class C>
+int foomain(int argc, char **argv) {
+ I e(4);
+ I g(5);
+ int i;
+ int &j = i;
+#pragma omp target simd lastprivate // expected-error {{expected '(' after 'lastprivate'}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd lastprivate( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd lastprivate() // expected-error {{expected expression}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd lastprivate(argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd lastprivate(argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd lastprivate(argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd lastprivate(argc)
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd lastprivate(S1) // expected-error {{'S1' does not refer to a value}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd lastprivate(a, b) // expected-error {{lastprivate variable with incomplete type 'S1'}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd lastprivate(argv[1]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd lastprivate(e, g) // expected-error 2 {{calling a private constructor of class 'S4'}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd lastprivate(h) // expected-error {{threadprivate or thread local variable cannot be lastprivate}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp parallel
+ {
+ int v = 0;
+ int i;
+#pragma omp target simd lastprivate(i)
+ for (int k = 0; k < argc; ++k) {
+ i = k;
+ v += i;
+ }
+ }
+#pragma omp parallel shared(i)
+#pragma omp parallel private(i)
+#pragma omp target simd lastprivate(j)
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd lastprivate(i)
+ for (int k = 0; k < argc; ++k)
+ ++k;
+ return 0;
+}
+
+namespace A {
+double x;
+#pragma omp threadprivate(x) // expected-note {{defined as threadprivate or thread local}}
+}
+namespace B {
+using A::x;
+}
+
+int main(int argc, char **argv) {
+ const int d = 5; // expected-note {{constant variable is predetermined as shared}}
+ const int da[5] = {0}; // expected-note {{constant variable is predetermined as shared}}
+ S4 e(4);
+ S5 g(5);
+ S3 m;
+ S6 n(2);
+ int i;
+ int &j = i;
+#pragma omp target simd lastprivate // expected-error {{expected '(' after 'lastprivate'}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd lastprivate( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd lastprivate() // expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd lastprivate(argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd lastprivate(argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd lastprivate(argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd lastprivate(argc)
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd lastprivate(S1) // expected-error {{'S1' does not refer to a value}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be lastprivate}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd lastprivate(argv[1]) // expected-error {{expected variable name}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd lastprivate(2 * 2) // expected-error {{expected variable name}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd lastprivate(ba)
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd lastprivate(ca) // expected-error {{shared variable cannot be lastprivate}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd lastprivate(da) // expected-error {{shared variable cannot be lastprivate}}
+ for (i = 0; i < argc; ++i)
+ foo();
+ int xa;
+#pragma omp target simd lastprivate(xa) // OK
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd lastprivate(S2::S2s) // expected-error {{shared variable cannot be lastprivate}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd lastprivate(S2::S2sc) // expected-error {{shared variable cannot be lastprivate}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd safelen(5) // OK
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd lastprivate(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd lastprivate(m) // expected-error {{'operator=' is a private member of 'S3'}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd lastprivate(h, B::x) // expected-error 2 {{threadprivate or thread local variable cannot be lastprivate}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd private(xa), lastprivate(xa) // expected-error {{private variable cannot be lastprivate}} expected-note {{defined as private}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd lastprivate(i) // expected-note {{defined as lastprivate}}
+ for (i = 0; i < argc; ++i) // expected-error {{loop iteration variable in the associated loop of 'omp target simd' directive may not be lastprivate, predetermined as linear}}
+ foo();
+#pragma omp parallel private(xa)
+#pragma omp target simd lastprivate(xa)
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp parallel reduction(+ : xa)
+#pragma omp target simd lastprivate(xa)
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd lastprivate(j)
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd firstprivate(m) lastprivate(m) // expected-error {{'operator=' is a private member of 'S3'}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd lastprivate(n) firstprivate(n) // OK
+ for (i = 0; i < argc; ++i)
+ foo();
+ static int si;
+#pragma omp target simd lastprivate(si) // OK
+ for (i = 0; i < argc; ++i)
+ si = i + 2;
+
+ return foomain<S4, S5>(argc, argv); // expected-note {{in instantiation of function template specialization 'foomain<S4, S5>' requested here}}
+}
diff --git a/test/OpenMP/target_simd_linear_messages.cpp b/test/OpenMP/target_simd_linear_messages.cpp
new file mode 100644
index 000000000000..6319e31b3fb2
--- /dev/null
+++ b/test/OpenMP/target_simd_linear_messages.cpp
@@ -0,0 +1,269 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+namespace X {
+int x;
+};
+
+struct B {
+ static int ib; // expected-note {{'B::ib' declared here}}
+ static int bfoo() { return 8; }
+};
+
+int bfoo() { return 4; }
+
+int z;
+const int C1 = 1;
+const int C2 = 2;
+void test_linear_colons() {
+ int B = 0;
+#pragma omp target simd linear(B : bfoo())
+ for (int i = 0; i < 10; ++i)
+ ;
+// expected-error@+1 {{unexpected ':' in nested name specifier; did you mean '::'}}
+#pragma omp target simd linear(B::ib : B : bfoo())
+ for (int i = 0; i < 10; ++i)
+ ;
+// expected-error@+1 {{use of undeclared identifier 'ib'; did you mean 'B::ib'}}
+#pragma omp target simd linear(B : ib)
+ for (int i = 0; i < 10; ++i)
+ ;
+// expected-error@+1 {{unexpected ':' in nested name specifier; did you mean '::'?}}
+#pragma omp target simd linear(z : B : ib)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target simd linear(B : B::bfoo())
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target simd linear(X::x : ::z)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target simd linear(B, ::z, X::x)
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target simd linear(::z)
+ for (int i = 0; i < 10; ++i)
+ ;
+// expected-error@+1 {{expected variable name}}
+#pragma omp target simd linear(B::bfoo())
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp target simd linear(B::ib, B : C1 + C2)
+ for (int i = 0; i < 10; ++i)
+ ;
+}
+
+template <int L, class T, class N>
+T test_template(T *arr, N num) {
+ N i;
+ T sum = (T)0;
+ T ind2 = -num * L; // expected-note {{'ind2' defined here}}
+// expected-error@+1 {{argument of a linear clause should be of integral or pointer type}}
+#pragma omp target simd linear(ind2 : L)
+ for (i = 0; i < num; ++i) {
+ T cur = arr[(int)ind2];
+ ind2 += L;
+ sum += cur;
+ }
+ return T();
+}
+
+template <int LEN>
+int test_warn() {
+ int ind2 = 0;
+// expected-warning@+1 {{zero linear step (ind2 should probably be const)}}
+#pragma omp target simd linear(ind2 : LEN)
+ for (int i = 0; i < 100; i++) {
+ ind2 += LEN;
+ }
+ return ind2;
+}
+
+struct S1; // expected-note 2 {{declared here}} expected-note 2 {{forward declaration of 'S1'}}
+extern S1 a;
+class S2 {
+ mutable int a;
+
+public:
+ S2() : a(0) {}
+};
+const S2 b; // expected-note 2 {{'b' defined here}}
+const S2 ba[5];
+class S3 {
+ int a;
+
+public:
+ S3() : a(0) {}
+};
+const S3 ca[5];
+class S4 {
+ int a;
+ S4();
+
+public:
+ S4(int v) : a(v) {}
+};
+class S5 {
+ int a;
+ S5() : a(0) {}
+
+public:
+ S5(int v) : a(v) {}
+};
+
+S3 h;
+#pragma omp threadprivate(h) // expected-note 2 {{defined as threadprivate or thread local}}
+
+template <class I, class C>
+int foomain(I argc, C **argv) {
+ I e(4);
+ I g(5);
+ int i;
+ int &j = i;
+#pragma omp target simd linear // expected-error {{expected '(' after 'linear'}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd linear( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd linear() // expected-error {{expected expression}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd linear(argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd linear(argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd linear(argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd linear(argc : 5)
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd linear(S1) // expected-error {{'S1' does not refer to a value}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+// expected-error@+2 {{linear variable with incomplete type 'S1'}}
+// expected-error@+1 {{const-qualified variable cannot be linear}}
+#pragma omp target simd linear(a, b : B::ib)
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd linear(argv[1]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd linear(e, g)
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd linear(h) // expected-error {{threadprivate or thread local variable cannot be linear}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd linear(i)
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp parallel
+ {
+ int v = 0;
+ int i;
+#pragma omp target simd linear(v : i)
+ for (int k = 0; k < argc; ++k) {
+ i = k;
+ v += i;
+ }
+ }
+#pragma omp target simd linear(j)
+ for (int k = 0; k < argc; ++k)
+ ++k;
+ int v = 0;
+#pragma omp target simd linear(v : j)
+ for (int k = 0; k < argc; ++k) {
+ ++k;
+ v += j;
+ }
+#pragma omp target simd linear(i)
+ for (int k = 0; k < argc; ++k)
+ ++k;
+ return 0;
+}
+
+namespace A {
+double x;
+#pragma omp threadprivate(x) // expected-note {{defined as threadprivate or thread local}}
+}
+namespace C {
+using A::x;
+}
+
+int main(int argc, char **argv) {
+ double darr[100];
+ // expected-note@+1 {{in instantiation of function template specialization 'test_template<-4, double, int>' requested here}}
+ test_template<-4>(darr, 4);
+ // expected-note@+1 {{in instantiation of function template specialization 'test_warn<0>' requested here}}
+ test_warn<0>();
+
+ S4 e(4); // expected-note {{'e' defined here}}
+ S5 g(5); // expected-note {{'g' defined here}}
+ int i;
+ int &j = i;
+#pragma omp target simd linear // expected-error {{expected '(' after 'linear'}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd linear( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd linear() // expected-error {{expected expression}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd linear(argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd linear(argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd linear(argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd linear(argc)
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd linear(S1) // expected-error {{'S1' does not refer to a value}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+// expected-error@+2 {{linear variable with incomplete type 'S1'}}
+// expected-error@+1 {{const-qualified variable cannot be linear}}
+#pragma omp target simd linear(a, b)
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd linear(argv[1]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+// expected-error@+2 {{argument of a linear clause should be of integral or pointer type, not 'S4'}}
+// expected-error@+1 {{argument of a linear clause should be of integral or pointer type, not 'S5'}}
+#pragma omp target simd linear(e, g)
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd linear(h, C::x) // expected-error 2 {{threadprivate or thread local variable cannot be linear}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp parallel
+ {
+ int i;
+#pragma omp target simd linear(i)
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd linear(i : 4)
+ for (int k = 0; k < argc; ++k) {
+ ++k;
+ i += 4;
+ }
+ }
+#pragma omp target simd linear(j)
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd linear(i)
+ for (int k = 0; k < argc; ++k)
+ ++k;
+
+ foomain<int, char>(argc, argv); // expected-note {{in instantiation of function template specialization 'foomain<int, char>' requested here}}
+ return 0;
+}
+
diff --git a/test/OpenMP/target_simd_loop_messages.cpp b/test/OpenMP/target_simd_loop_messages.cpp
new file mode 100644
index 000000000000..67201fb73fa7
--- /dev/null
+++ b/test/OpenMP/target_simd_loop_messages.cpp
@@ -0,0 +1,629 @@
+// RUN: %clang_cc1 -fsyntax-only -fopenmp -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s
+
+class S {
+ int a;
+ S() : a(0) {}
+
+public:
+ S(int v) : a(v) {}
+ S(const S &s) : a(s.a) {}
+};
+
+static int sii;
+// expected-note@+1 {{defined as threadprivate or thread local}}
+#pragma omp threadprivate(sii)
+static int globalii;
+
+int test_iteration_spaces() {
+ const int N = 100;
+ float a[N], b[N], c[N];
+ int ii, jj, kk;
+ float fii;
+ double dii;
+#pragma omp target simd
+ for (int i = 0; i < 10; i += 1) {
+ c[i] = a[i] + b[i];
+ }
+#pragma omp target simd
+ for (char i = 0; i < 10; i++) {
+ c[i] = a[i] + b[i];
+ }
+#pragma omp target simd
+ for (char i = 0; i < 10; i += '\1') {
+ c[i] = a[i] + b[i];
+ }
+#pragma omp target simd
+ for (long long i = 0; i < 10; i++) {
+ c[i] = a[i] + b[i];
+ }
+// expected-error@+2 {{expression must have integral or unscoped enumeration type, not 'double'}}
+#pragma omp target simd
+ for (long long i = 0; i < 10; i += 1.5) {
+ c[i] = a[i] + b[i];
+ }
+#pragma omp target simd
+ for (long long i = 0; i < 'z'; i += 1u) {
+ c[i] = a[i] + b[i];
+ }
+// expected-error@+2 {{variable must be of integer or random access iterator type}}
+#pragma omp target simd
+ for (float fi = 0; fi < 10.0; fi++) {
+ c[(int)fi] = a[(int)fi] + b[(int)fi];
+ }
+// expected-error@+2 {{variable must be of integer or random access iterator type}}
+#pragma omp target simd
+ for (double fi = 0; fi < 10.0; fi++) {
+ c[(int)fi] = a[(int)fi] + b[(int)fi];
+ }
+// expected-error@+2 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+#pragma omp target simd
+ for (int &ref = ii; ref < 10; ref++) {
+ }
+// expected-error@+2 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+#pragma omp target simd
+ for (int i; i < 10; i++)
+ c[i] = a[i];
+
+// expected-error@+2 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+#pragma omp target simd
+ for (int i = 0, j = 0; i < 10; ++i)
+ c[i] = a[i];
+
+// expected-error@+2 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+#pragma omp target simd
+ for (; ii < 10; ++ii)
+ c[ii] = a[ii];
+
+// expected-warning@+3 {{expression result unused}}
+// expected-error@+2 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+#pragma omp target simd
+ for (ii + 1; ii < 10; ++ii)
+ c[ii] = a[ii];
+
+// expected-error@+2 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+#pragma omp target simd
+ for (c[ii] = 0; ii < 10; ++ii)
+ c[ii] = a[ii];
+
+// Ok to skip parenthesises.
+#pragma omp target simd
+ for (((ii)) = 0; ii < 10; ++ii)
+ c[ii] = a[ii];
+
+// expected-error@+2 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
+#pragma omp target simd
+ for (int i = 0; i; i++)
+ c[i] = a[i];
+
+// expected-error@+3 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
+// expected-error@+2 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'i'}}
+#pragma omp target simd
+ for (int i = 0; jj < kk; ii++)
+ c[i] = a[i];
+
+// expected-error@+2 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
+#pragma omp target simd
+ for (int i = 0; !!i; i++)
+ c[i] = a[i];
+
+// expected-error@+2 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
+#pragma omp target simd
+ for (int i = 0; i != 1; i++)
+ c[i] = a[i];
+
+// expected-error@+2 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
+#pragma omp target simd
+ for (int i = 0;; i++)
+ c[i] = a[i];
+
+// Ok.
+#pragma omp target simd
+ for (int i = 11; i > 10; i--)
+ c[i] = a[i];
+
+// Ok.
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i)
+ c[i] = a[i];
+
+// Ok.
+#pragma omp target simd
+ for (ii = 0; ii < 10; ++ii)
+ c[ii] = a[ii];
+
+// expected-error@+2 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+#pragma omp target simd
+ for (ii = 0; ii < 10; ++jj)
+ c[ii] = a[jj];
+
+// expected-error@+2 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+#pragma omp target simd
+ for (ii = 0; ii < 10; ++++ii)
+ c[ii] = a[ii];
+
+// Ok but undefined behavior (in general, cannot check that incr
+// is really loop-invariant).
+#pragma omp target simd
+ for (ii = 0; ii < 10; ii = ii + ii)
+ c[ii] = a[ii];
+
+// expected-error@+2 {{expression must have integral or unscoped enumeration type, not 'float'}}
+#pragma omp target simd
+ for (ii = 0; ii < 10; ii = ii + 1.0f)
+ c[ii] = a[ii];
+
+// Ok - step was converted to integer type.
+#pragma omp target simd
+ for (ii = 0; ii < 10; ii = ii + (int)1.1f)
+ c[ii] = a[ii];
+
+// expected-error@+2 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+#pragma omp target simd
+ for (ii = 0; ii < 10; jj = ii + 2)
+ c[ii] = a[ii];
+
+// expected-warning@+3 {{relational comparison result unused}}
+// expected-error@+2 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+#pragma omp target simd
+ for (ii = 0; ii<10; jj> kk + 2)
+ c[ii] = a[ii];
+
+// expected-error@+2 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+#pragma omp target simd
+ for (ii = 0; ii < 10;)
+ c[ii] = a[ii];
+
+// expected-warning@+3 {{expression result unused}}
+// expected-error@+2 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+#pragma omp target simd
+ for (ii = 0; ii < 10; !ii)
+ c[ii] = a[ii];
+
+// expected-error@+2 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+#pragma omp target simd
+ for (ii = 0; ii < 10; ii ? ++ii : ++jj)
+ c[ii] = a[ii];
+
+// expected-error@+2 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+#pragma omp target simd
+ for (ii = 0; ii < 10; ii = ii < 10)
+ c[ii] = a[ii];
+
+// expected-note@+3 {{loop step is expected to be positive due to this condition}}
+// expected-error@+2 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}}
+#pragma omp target simd
+ for (ii = 0; ii < 10; ii = ii + 0)
+ c[ii] = a[ii];
+
+// expected-note@+3 {{loop step is expected to be positive due to this condition}}
+// expected-error@+2 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}}
+#pragma omp target simd
+ for (ii = 0; ii < 10; ii = ii + (int)(0.8 - 0.45))
+ c[ii] = a[ii];
+
+// expected-note@+3 {{loop step is expected to be positive due to this condition}}
+// expected-error@+2 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}}
+#pragma omp target simd
+ for (ii = 0; (ii) < 10; ii -= 25)
+ c[ii] = a[ii];
+
+// expected-note@+3 {{loop step is expected to be positive due to this condition}}
+// expected-error@+2 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}}
+#pragma omp target simd
+ for (ii = 0; (ii < 10); ii -= 0)
+ c[ii] = a[ii];
+
+// expected-note@+3 {{loop step is expected to be negative due to this condition}}
+// expected-error@+2 {{increment expression must cause 'ii' to decrease on each iteration of OpenMP for loop}}
+#pragma omp target simd
+ for (ii = 0; ii > 10; (ii += 0))
+ c[ii] = a[ii];
+
+// expected-note@+3 {{loop step is expected to be positive due to this condition}}
+// expected-error@+2 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}}
+#pragma omp target simd
+ for (ii = 0; ii < 10; (ii) = (1 - 1) + (ii))
+ c[ii] = a[ii];
+
+// expected-note@+3 {{loop step is expected to be negative due to this condition}}
+// expected-error@+2 {{increment expression must cause 'ii' to decrease on each iteration of OpenMP for loop}}
+#pragma omp target simd
+ for ((ii = 0); ii > 10; (ii -= 0))
+ c[ii] = a[ii];
+
+// expected-note@+3 {{loop step is expected to be positive due to this condition}}
+// expected-error@+2 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}}
+#pragma omp target simd
+ for (ii = 0; (ii < 10); (ii -= 0))
+ c[ii] = a[ii];
+
+// expected-note@+2 {{defined as firstprivate}}
+// expected-error@+2 {{loop iteration variable in the associated loop of 'omp target simd' directive may not be firstprivate, predetermined as linear}}
+#pragma omp target simd firstprivate(ii)
+ for (ii = 0; ii < 10; ii++)
+ c[ii] = a[ii];
+
+#pragma omp target simd linear(ii)
+ for (ii = 0; ii < 10; ii++)
+ c[ii] = a[ii];
+
+// expected-note@+2 {{defined as private}}
+// expected-error@+2 {{loop iteration variable in the associated loop of 'omp target simd' directive may not be private, predetermined as linear}}
+#pragma omp target simd private(ii)
+ for (ii = 0; ii < 10; ii++)
+ c[ii] = a[ii];
+
+// expected-note@+2 {{defined as lastprivate}}
+// expected-error@+2 {{loop iteration variable in the associated loop of 'omp target simd' directive may not be lastprivate, predetermined as linear}}
+#pragma omp target simd lastprivate(ii)
+ for (ii = 0; ii < 10; ii++)
+ c[ii] = a[ii];
+
+ {
+// expected-error@+2 {{loop iteration variable in the associated loop of 'omp target simd' directive may not be threadprivate or thread local, predetermined as linear}}
+#pragma omp target simd
+ for (sii = 0; sii < 10; sii += 1)
+ c[sii] = a[sii];
+ }
+
+ {
+#pragma omp target simd
+ for (globalii = 0; globalii < 10; globalii += 1)
+ c[globalii] = a[globalii];
+ }
+
+ {
+#pragma omp target simd collapse(2)
+ for (ii = 0; ii < 10; ii += 1)
+ for (globalii = 0; globalii < 10; globalii += 1)
+ c[globalii] += a[globalii] + ii;
+ }
+
+// expected-error@+2 {{statement after '#pragma omp target simd' must be a for loop}}
+#pragma omp target simd
+ for (auto &item : a) {
+ item = item + 1;
+ }
+
+// expected-note@+3 {{loop step is expected to be positive due to this condition}}
+// expected-error@+2 {{increment expression must cause 'i' to increase on each iteration of OpenMP for loop}}
+#pragma omp target simd
+ for (unsigned i = 9; i < 10; i--) {
+ c[i] = a[i] + b[i];
+ }
+
+ int(*lb)[4] = nullptr;
+#pragma omp target simd
+ for (int(*p)[4] = lb; p < lb + 8; ++p) {
+ }
+
+// expected-warning@+2 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+#pragma omp target simd
+ for (int a{0}; a < 10; ++a) {
+ }
+
+ return 0;
+}
+
+// Iterators allowed in openmp for-loops.
+namespace std {
+struct random_access_iterator_tag {};
+template <class Iter>
+struct iterator_traits {
+ typedef typename Iter::difference_type difference_type;
+ typedef typename Iter::iterator_category iterator_category;
+};
+template <class Iter>
+typename iterator_traits<Iter>::difference_type
+distance(Iter first, Iter last) { return first - last; }
+}
+class Iter0 {
+public:
+ Iter0() {}
+ Iter0(const Iter0 &) {}
+ Iter0 operator++() { return *this; }
+ Iter0 operator--() { return *this; }
+ bool operator<(Iter0 a) { return true; }
+};
+// expected-note@+2 {{candidate function not viable: no known conversion from 'GoodIter' to 'Iter0' for 1st argument}}
+// expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'Iter0' for 1st argument}}
+int operator-(Iter0 a, Iter0 b) { return 0; }
+class Iter1 {
+public:
+ Iter1(float f = 0.0f, double d = 0.0) {}
+ Iter1(const Iter1 &) {}
+ Iter1 operator++() { return *this; }
+ Iter1 operator--() { return *this; }
+ bool operator<(Iter1 a) { return true; }
+ bool operator>=(Iter1 a) { return false; }
+};
+class GoodIter {
+public:
+ GoodIter() {}
+ GoodIter(const GoodIter &) {}
+ GoodIter(int fst, int snd) {}
+ GoodIter &operator=(const GoodIter &that) { return *this; }
+ GoodIter &operator=(const Iter0 &that) { return *this; }
+ GoodIter &operator+=(int x) { return *this; }
+ GoodIter &operator-=(int x) { return *this; }
+ explicit GoodIter(void *) {}
+ GoodIter operator++() { return *this; }
+ GoodIter operator--() { return *this; }
+ bool operator!() { return true; }
+ bool operator<(GoodIter a) { return true; }
+ bool operator<=(GoodIter a) { return true; }
+ bool operator>=(GoodIter a) { return false; }
+ typedef int difference_type;
+ typedef std::random_access_iterator_tag iterator_category;
+};
+// expected-note@+2 {{candidate function not viable: no known conversion from 'const Iter0' to 'GoodIter' for 2nd argument}}
+// expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'GoodIter' for 1st argument}}
+int operator-(GoodIter a, GoodIter b) { return 0; }
+// expected-note@+1 3 {{candidate function not viable: requires single argument 'a', but 2 arguments were provided}}
+GoodIter operator-(GoodIter a) { return a; }
+// expected-note@+2 {{candidate function not viable: no known conversion from 'const Iter0' to 'int' for 2nd argument}}
+// expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'GoodIter' for 1st argument}}
+GoodIter operator-(GoodIter a, int v) { return GoodIter(); }
+// expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter0' to 'GoodIter' for 1st argument}}
+GoodIter operator+(GoodIter a, int v) { return GoodIter(); }
+// expected-note@+2 {{candidate function not viable: no known conversion from 'GoodIter' to 'int' for 1st argument}}
+// expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'int' for 1st argument}}
+GoodIter operator-(int v, GoodIter a) { return GoodIter(); }
+// expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter0' to 'int' for 1st argument}}
+GoodIter operator+(int v, GoodIter a) { return GoodIter(); }
+
+int test_with_random_access_iterator() {
+ GoodIter begin, end;
+ Iter0 begin0, end0;
+#pragma omp target simd
+ for (GoodIter I = begin; I < end; ++I)
+ ++I;
+// expected-error@+2 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+#pragma omp target simd
+ for (GoodIter &I = begin; I < end; ++I)
+ ++I;
+#pragma omp target simd
+ for (GoodIter I = begin; I >= end; --I)
+ ++I;
+// expected-warning@+2 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+#pragma omp target simd
+ for (GoodIter I(begin); I < end; ++I)
+ ++I;
+// expected-warning@+2 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+#pragma omp target simd
+ for (GoodIter I(nullptr); I < end; ++I)
+ ++I;
+// expected-warning@+2 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+#pragma omp target simd
+ for (GoodIter I(0); I < end; ++I)
+ ++I;
+// expected-warning@+2 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+#pragma omp target simd
+ for (GoodIter I(1, 2); I < end; ++I)
+ ++I;
+#pragma omp target simd
+ for (begin = GoodIter(0); begin < end; ++begin)
+ ++begin;
+// expected-error@+3 {{invalid operands to binary expression ('GoodIter' and 'const Iter0')}}
+// expected-error@+2 {{could not calculate number of iterations calling 'operator-' with upper and lower loop bounds}}
+#pragma omp target simd
+ for (begin = begin0; begin < end; ++begin)
+ ++begin;
+// expected-error@+2 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+#pragma omp target simd
+ for (++begin; begin < end; ++begin)
+ ++begin;
+#pragma omp target simd
+ for (begin = end; begin < end; ++begin)
+ ++begin;
+// expected-error@+2 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'I'}}
+#pragma omp target simd
+ for (GoodIter I = begin; I - I; ++I)
+ ++I;
+// expected-error@+2 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'I'}}
+#pragma omp target simd
+ for (GoodIter I = begin; begin < end; ++I)
+ ++I;
+// expected-error@+2 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'I'}}
+#pragma omp target simd
+ for (GoodIter I = begin; !I; ++I)
+ ++I;
+// expected-note@+3 {{loop step is expected to be negative due to this condition}}
+// expected-error@+2 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}}
+#pragma omp target simd
+ for (GoodIter I = begin; I >= end; I = I + 1)
+ ++I;
+#pragma omp target simd
+ for (GoodIter I = begin; I >= end; I = I - 1)
+ ++I;
+// expected-error@+2 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'I'}}
+#pragma omp target simd
+ for (GoodIter I = begin; I >= end; I = -I)
+ ++I;
+// expected-note@+3 {{loop step is expected to be negative due to this condition}}
+// expected-error@+2 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}}
+#pragma omp target simd
+ for (GoodIter I = begin; I >= end; I = 2 + I)
+ ++I;
+// expected-error@+2 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'I'}}
+#pragma omp target simd
+ for (GoodIter I = begin; I >= end; I = 2 - I)
+ ++I;
+// expected-error@+2 {{invalid operands to binary expression ('Iter0' and 'int')}}
+#pragma omp target simd
+ for (Iter0 I = begin0; I < end0; ++I)
+ ++I;
+// Initializer is constructor without params.
+// expected-error@+3 {{invalid operands to binary expression ('Iter0' and 'int')}}
+// expected-warning@+2 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+#pragma omp target simd
+ for (Iter0 I; I < end0; ++I)
+ ++I;
+ Iter1 begin1, end1;
+// expected-error@+3 {{invalid operands to binary expression ('Iter1' and 'Iter1')}}
+// expected-error@+2 {{could not calculate number of iterations calling 'operator-' with upper and lower loop bounds}}
+#pragma omp target simd
+ for (Iter1 I = begin1; I < end1; ++I)
+ ++I;
+// expected-note@+3 {{loop step is expected to be negative due to this condition}}
+// expected-error@+2 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}}
+#pragma omp target simd
+ for (Iter1 I = begin1; I >= end1; ++I)
+ ++I;
+// expected-error@+5 {{invalid operands to binary expression ('Iter1' and 'float')}}
+// expected-error@+4 {{could not calculate number of iterations calling 'operator-' with upper and lower loop bounds}}
+// Initializer is constructor with all default params.
+// expected-warning@+2 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+#pragma omp target simd
+ for (Iter1 I; I < end1; ++I) {
+ }
+ return 0;
+}
+
+template <typename IT, int ST>
+class TC {
+public:
+ int dotest_lt(IT begin, IT end) {
+// expected-note@+3 {{loop step is expected to be positive due to this condition}}
+// expected-error@+2 {{increment expression must cause 'I' to increase on each iteration of OpenMP for loop}}
+#pragma omp target simd
+ for (IT I = begin; I < end; I = I + ST) {
+ ++I;
+ }
+// expected-note@+3 {{loop step is expected to be positive due to this condition}}
+// expected-error@+2 {{increment expression must cause 'I' to increase on each iteration of OpenMP for loop}}
+#pragma omp target simd
+ for (IT I = begin; I <= end; I += ST) {
+ ++I;
+ }
+#pragma omp target simd
+ for (IT I = begin; I < end; ++I) {
+ ++I;
+ }
+ }
+
+ static IT step() {
+ return IT(ST);
+ }
+};
+template <typename IT, int ST = 0>
+int dotest_gt(IT begin, IT end) {
+// expected-note@+3 2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+2 2 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}}
+#pragma omp target simd
+ for (IT I = begin; I >= end; I = I + ST) {
+ ++I;
+ }
+// expected-note@+3 2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+2 2 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}}
+#pragma omp target simd
+ for (IT I = begin; I >= end; I += ST) {
+ ++I;
+ }
+
+// expected-note@+3 {{loop step is expected to be negative due to this condition}}
+// expected-error@+2 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}}
+#pragma omp target simd
+ for (IT I = begin; I >= end; ++I) {
+ ++I;
+ }
+
+#pragma omp target simd
+ for (IT I = begin; I < end; I += TC<int, ST>::step()) {
+ ++I;
+ }
+}
+
+void test_with_template() {
+ GoodIter begin, end;
+ TC<GoodIter, 100> t1;
+ TC<GoodIter, -100> t2;
+ t1.dotest_lt(begin, end);
+ t2.dotest_lt(begin, end); // expected-note {{in instantiation of member function 'TC<GoodIter, -100>::dotest_lt' requested here}}
+ dotest_gt(begin, end); // expected-note {{in instantiation of function template specialization 'dotest_gt<GoodIter, 0>' requested here}}
+ dotest_gt<unsigned, -10>(0, 100); // expected-note {{in instantiation of function template specialization 'dotest_gt<unsigned int, -10>' requested here}}
+}
+
+void test_loop_break() {
+ const int N = 100;
+ float a[N], b[N], c[N];
+#pragma omp target simd
+ for (int i = 0; i < 10; i++) {
+ c[i] = a[i] + b[i];
+ for (int j = 0; j < 10; ++j) {
+ if (a[i] > b[j])
+ break; // OK in nested loop
+ }
+ switch (i) {
+ case 1:
+ b[i]++;
+ break;
+ default:
+ break;
+ }
+ if (c[i] > 10)
+ break; // expected-error {{'break' statement cannot be used in OpenMP for loop}}
+
+ if (c[i] > 11)
+ break; // expected-error {{'break' statement cannot be used in OpenMP for loop}}
+ }
+
+#pragma omp target simd
+ for (int i = 0; i < 10; i++) {
+ for (int j = 0; j < 10; j++) {
+ c[i] = a[i] + b[i];
+ if (c[i] > 10) {
+ if (c[i] < 20) {
+ break; // OK
+ }
+ }
+ }
+ }
+}
+
+void test_loop_eh() {
+ const int N = 100;
+ float a[N], b[N], c[N];
+#pragma omp target simd
+ for (int i = 0; i < 10; i++) {
+ c[i] = a[i] + b[i];
+ try { // expected-error {{'try' statement cannot be used in OpenMP simd region}}
+ for (int j = 0; j < 10; ++j) {
+ if (a[i] > b[j])
+ throw a[i]; // expected-error {{'throw' statement cannot be used in OpenMP simd region}}
+ }
+ throw a[i]; // expected-error {{'throw' statement cannot be used in OpenMP simd region}}
+ } catch (float f) {
+ if (f > 0.1)
+ throw a[i]; // expected-error {{'throw' statement cannot be used in OpenMP simd region}}
+ return; // expected-error {{cannot return from OpenMP region}}
+ }
+ switch (i) {
+ case 1:
+ b[i]++;
+ break;
+ default:
+ break;
+ }
+ for (int j = 0; j < 10; j++) {
+ if (c[i] > 10)
+ throw c[i]; // expected-error {{'throw' statement cannot be used in OpenMP simd region}}
+ }
+ }
+ if (c[9] > 10)
+ throw c[9]; // OK
+
+#pragma omp target simd
+ for (int i = 0; i < 10; ++i) {
+ struct S {
+ void g() { throw 0; }
+ };
+ }
+}
+
+void test_loop_firstprivate_lastprivate() {
+ S s(4);
+#pragma omp target simd lastprivate(s) firstprivate(s)
+ for (int i = 0; i < 16; ++i)
+ ;
+}
diff --git a/test/OpenMP/target_simd_map_messages.cpp b/test/OpenMP/target_simd_map_messages.cpp
new file mode 100644
index 000000000000..63bbdde77255
--- /dev/null
+++ b/test/OpenMP/target_simd_map_messages.cpp
@@ -0,0 +1,273 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note 2 {{declared here}}
+extern S1 a;
+class S2 {
+ mutable int a;
+public:
+ S2():a(0) { }
+ S2(S2 &s2):a(s2.a) { }
+ static float S2s; // expected-note 4 {{mappable type cannot contain static members}}
+ static const float S2sc; // expected-note 4 {{mappable type cannot contain static members}}
+};
+const float S2::S2sc = 0;
+const S2 b;
+const S2 ba[5];
+class S3 {
+ int a;
+public:
+ S3():a(0) { }
+ S3(S3 &s3):a(s3.a) { }
+};
+const S3 c;
+const S3 ca[5];
+extern const int f;
+class S4 {
+ int a;
+ S4();
+ S4(const S4 &s4);
+public:
+ S4(int v):a(v) { }
+};
+class S5 {
+ int a;
+ S5():a(0) {}
+ S5(const S5 &s5):a(s5.a) { }
+public:
+ S5(int v):a(v) { }
+};
+
+S3 h;
+#pragma omp threadprivate(h) // expected-note 2 {{defined as threadprivate or thread local}}
+
+typedef int from;
+
+template <typename T, int I> // expected-note {{declared here}}
+T tmain(T argc) {
+ const T d = 5;
+ const T da[5] = { 0 };
+ S4 e(4);
+ S5 g(5);
+ T i, t[20];
+ T &j = i;
+ T *k = &j;
+ T x;
+ T y;
+ T to, tofrom, always;
+ const T (&l)[5] = da;
+
+
+#pragma omp target simd map // expected-error {{expected '(' after 'map'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map( // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map() // expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(alloc) // expected-error {{use of undeclared identifier 'alloc'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(to argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected ',' or ')' in 'map' clause}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(to:) // expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(from: argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(x: y) // expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(x)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(tofrom: t[:I])
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(T: a) // expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}} expected-error {{incomplete type 'S1' where a complete type is required}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(T) // expected-error {{'T' does not refer to a value}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(I) // expected-error 2 {{expected expression containing only member accesses and/or array sections based on named variables}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(S2::S2s)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(S2::S2sc)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(x)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(to: x)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(to: to)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(to)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(to, x)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(to x) // expected-error {{expected ',' or ')' in 'map' clause}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(tofrom: argc > 0 ? x : y) // expected-error 2 {{expected expression containing only member accesses and/or array sections based on named variables}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(argc)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(S1) // expected-error {{'S1' does not refer to a value}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(a, b, c, d, f) // expected-error {{incomplete type 'S1' where a complete type is required}} expected-error 2 {{type 'S2' is not mappable to target}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(ba) // expected-error 2 {{type 'S2' is not mappable to target}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(ca)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(da)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(S2::S2s)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(S2::S2sc)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(e, g)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(h) // expected-error {{threadprivate variables are not allowed in 'map' clause}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(k), map(k) // expected-error 2 {{variable already marked as mapped in current construct}} expected-note 2 {{used here}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(k), map(k[:5]) // expected-error 2 {{pointer cannot be mapped along with a section derived from itself}} expected-note 2 {{used here}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(da)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(da[:4])
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target data map(k, j, l) // expected-note 2 {{used here}}
+#pragma omp target simd map(k[:4]) // expected-error 2 {{pointer cannot be mapped along with a section derived from itself}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(j)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(l) map(l[:5]) // expected-error 2 {{variable already marked as mapped in current construct}} expected-note 2 {{used here}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target data map(k[:4], j, l[:5]) // expected-note 2 {{used here}}
+{
+#pragma omp target simd map(k) // expected-error 2 {{pointer cannot be mapped along with a section derived from itself}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(j)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(l) // OK
+ for (i = 0; i < argc; ++i) foo();
+}
+
+#pragma omp target simd map(always, tofrom: x)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(always: x) // expected-error {{missing map type}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always'}} expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(always, tofrom: always, tofrom, x)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(tofrom j) // expected-error {{expected ',' or ')' in 'map' clause}}
+ for (i = 0; i < argc; ++i) foo();
+
+ return 0;
+}
+
+int main(int argc, char **argv) {
+ const int d = 5;
+ const int da[5] = { 0 };
+ S4 e(4);
+ S5 g(5);
+ int i;
+ int &j = i;
+ int *k = &j;
+ int x;
+ int y;
+ int to, tofrom, always;
+ const int (&l)[5] = da;
+
+#pragma omp target simd map // expected-error {{expected '(' after 'map'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map( // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map() // expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(alloc) // expected-error {{use of undeclared identifier 'alloc'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(to argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected ',' or ')' in 'map' clause}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(to:) // expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(from: argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(x: y) // expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(x)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(to: x)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(to: to)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(to)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(to, x)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(to x) // expected-error {{expected ',' or ')' in 'map' clause}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(tofrom: argc > 0 ? argv[1] : argv[2]) // expected-error {{expected expression containing only member accesses and/or array sections based on named variables}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(argc)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(S1) // expected-error {{'S1' does not refer to a value}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(a, b, c, d, f) // expected-error {{incomplete type 'S1' where a complete type is required}} expected-error 2 {{type 'S2' is not mappable to target}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(argv[1])
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(ba) // expected-error 2 {{type 'S2' is not mappable to target}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(ca)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(da)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(S2::S2s)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(S2::S2sc)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(e, g)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(h) // expected-error {{threadprivate variables are not allowed in 'map' clause}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(k), map(k) // expected-error {{variable already marked as mapped in current construct}} expected-note {{used here}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(k), map(k[:5]) // expected-error {{pointer cannot be mapped along with a section derived from itself}} expected-note {{used here}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(da)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(da[:4])
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target data map(k, j, l) // expected-note {{used here}}
+#pragma omp target simd map(k[:4]) // expected-error {{pointer cannot be mapped along with a section derived from itself}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(j)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(l) map(l[:5]) // expected-error 1 {{variable already marked as mapped in current construct}} expected-note 1 {{used here}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target data map(k[:4], j, l[:5]) // expected-note 1 {{used here}}
+{
+#pragma omp target simd map(k) // expected-error {{pointer cannot be mapped along with a section derived from itself}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(j)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(l) //
+ for (i = 0; i < argc; ++i) foo();
+}
+
+#pragma omp target simd map(always, tofrom: x)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(always: x) // expected-error {{missing map type}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always'}} expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(always, tofrom: always, tofrom, x)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target simd map(tofrom j) // expected-error {{expected ',' or ')' in 'map' clause}}
+ for (i = 0; i < argc; ++i) foo();
+
+ return tmain<int, 3>(argc)+tmain<from, 4>(argc); // expected-note {{in instantiation of function template specialization 'tmain<int, 3>' requested here}} expected-note {{in instantiation of function template specialization 'tmain<int, 4>' requested here}}
+}
+
diff --git a/test/OpenMP/target_simd_messages.cpp b/test/OpenMP/target_simd_messages.cpp
new file mode 100644
index 000000000000..d1b06e3b9030
--- /dev/null
+++ b/test/OpenMP/target_simd_messages.cpp
@@ -0,0 +1,92 @@
+// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+
+void foo() {
+}
+
+static int pvt;
+#pragma omp threadprivate(pvt)
+
+#pragma omp target simd // expected-error {{unexpected OpenMP directive '#pragma omp target simd'}}
+
+int main(int argc, char **argv) {
+#pragma omp target simd { // expected-warning {{extra tokens at the end of '#pragma omp target simd' are ignored}}
+ for (int i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd ( // expected-warning {{extra tokens at the end of '#pragma omp target simd' are ignored}}
+ for (int i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd[ // expected-warning {{extra tokens at the end of '#pragma omp target simd' are ignored}}
+ for (int i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd] // expected-warning {{extra tokens at the end of '#pragma omp target simd' are ignored}}
+ for (int i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd) // expected-warning {{extra tokens at the end of '#pragma omp target simd' are ignored}}
+ for (int i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd } // expected-warning {{extra tokens at the end of '#pragma omp target simd' are ignored}}
+ for (int i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd
+ for (int i = 0; i < argc; ++i)
+ foo();
+// expected-warning@+1 {{extra tokens at the end of '#pragma omp target simd' are ignored}}
+#pragma omp target simd unknown()
+ for (int i = 0; i < argc; ++i)
+ foo();
+L1:
+ for (int i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd
+ for (int i = 0; i < argc; ++i)
+ foo();
+#pragma omp target simd
+ for (int i = 0; i < argc; ++i) {
+ goto L1; // expected-error {{use of undeclared label 'L1'}}
+ argc++;
+ }
+
+ for (int i = 0; i < 10; ++i) {
+ switch (argc) {
+ case (0):
+#pragma omp target simd
+ for (int i = 0; i < argc; ++i) {
+ foo();
+ break; // expected-error {{'break' statement cannot be used in OpenMP for loop}}
+ continue;
+ }
+ default:
+ break;
+ }
+ }
+#pragma omp target simd default(none) // expected-error {{unexpected OpenMP clause 'default' in directive '#pragma omp target simd'}}
+ for (int i = 0; i < 10; ++i)
+ ++argc;
+
+ goto L2; // expected-error {{use of undeclared label 'L2'}}
+#pragma omp target simd
+ for (int i = 0; i < argc; ++i)
+ L2:
+ foo();
+#pragma omp target simd
+ for (int i = 0; i < argc; ++i) {
+ return 1; // expected-error {{cannot return from OpenMP region}}
+ }
+
+ [[]] // expected-error {{an attribute list cannot appear here}}
+#pragma omp target simd
+ for (int n = 0; n < 100; ++n) {
+ }
+
+#pragma omp target simd copyin(pvt) // expected-error {{unexpected OpenMP clause 'copyin' in directive '#pragma omp target simd'}}
+ for (int n = 0; n < 100; ++n) {}
+
+ return 0;
+}
+
+void test_ordered() {
+#pragma omp target simd ordered // expected-error {{unexpected OpenMP clause 'ordered' in directive '#pragma omp target simd'}}
+ for (int i = 0; i < 16; ++i)
+ ;
+}
+
diff --git a/test/OpenMP/target_simd_misc_messages.c b/test/OpenMP/target_simd_misc_messages.c
new file mode 100644
index 000000000000..debe38713826
--- /dev/null
+++ b/test/OpenMP/target_simd_misc_messages.c
@@ -0,0 +1,485 @@
+// RUN: %clang_cc1 -fsyntax-only -fopenmp -verify %s
+
+// expected-error@+1 {{unexpected OpenMP directive '#pragma omp target simd'}}
+#pragma omp target simd
+
+// expected-error@+1 {{unexpected OpenMP directive '#pragma omp target simd'}}
+#pragma omp target simd foo
+
+void test_no_clause() {
+ int i;
+#pragma omp target simd
+ for (i = 0; i < 16; ++i)
+ ;
+
+// expected-error@+2 {{statement after '#pragma omp target simd' must be a for loop}}
+#pragma omp target simd
+ ++i;
+}
+
+void test_branch_protected_scope() {
+ int i = 0;
+L1:
+ ++i;
+
+ int x[24];
+
+#pragma omp target simd
+ for (i = 0; i < 16; ++i) {
+ if (i == 5)
+ goto L1; // expected-error {{use of undeclared label 'L1'}}
+ else if (i == 6)
+ return; // expected-error {{cannot return from OpenMP region}}
+ else if (i == 7)
+ goto L2;
+ else if (i == 8) {
+ L2:
+ x[i]++;
+ }
+ }
+
+ if (x[0] == 0)
+ goto L2; // expected-error {{use of undeclared label 'L2'}}
+ else if (x[1] == 1)
+ goto L1;
+}
+
+void test_invalid_clause() {
+ int i;
+// expected-warning@+1 {{extra tokens at the end of '#pragma omp target simd' are ignored}}
+#pragma omp target simd foo bar
+ for (i = 0; i < 16; ++i)
+ ;
+}
+
+void test_non_identifiers() {
+ int i, x;
+
+// expected-warning@+1 {{extra tokens at the end of '#pragma omp target simd' are ignored}}
+#pragma omp target simd;
+ for (i = 0; i < 16; ++i)
+ ;
+
+// expected-warning@+1 {{extra tokens at the end of '#pragma omp target simd' are ignored}}
+#pragma omp target simd private(x);
+ for (i = 0; i < 16; ++i)
+ ;
+
+// expected-warning@+1 {{extra tokens at the end of '#pragma omp target simd' are ignored}}
+#pragma omp target simd, private(x);
+ for (i = 0; i < 16; ++i)
+ ;
+}
+
+extern int foo();
+
+void test_collapse() {
+ int i;
+// expected-error@+1 {{expected '('}}
+#pragma omp target simd collapse
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expected expression}} expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
+#pragma omp target simd collapse(
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expected expression}}
+#pragma omp target simd collapse()
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expected expression}} expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
+#pragma omp target simd collapse(,
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expected expression}} expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
+#pragma omp target simd collapse(, )
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-warning@+2 {{extra tokens at the end of '#pragma omp target simd' are ignored}}
+// expected-error@+1 {{expected '('}}
+#pragma omp target simd collapse 4)
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+2 {{expected ')'}}
+// expected-note@+1 {{to match this '('}} expected-note@+1 {{as specified in 'collapse' clause}}
+#pragma omp target simd collapse(4
+ for (i = 0; i < 16; ++i)
+ ; // expected-error {{expected 4 for loops after '#pragma omp target simd', but found only 1}}
+// expected-error@+2 {{expected ')'}}
+// expected-note@+1 {{to match this '('}} expected-note@+1 {{as specified in 'collapse' clause}}
+#pragma omp target simd collapse(4,
+ for (i = 0; i < 16; ++i)
+ ; // expected-error {{expected 4 for loops after '#pragma omp target simd', but found only 1}}
+// expected-error@+2 {{expected ')'}}
+// expected-note@+1 {{to match this '('}} expected-note@+1 {{as specified in 'collapse' clause}}
+#pragma omp target simd collapse(4, )
+ for (i = 0; i < 16; ++i)
+ ; // expected-error {{expected 4 for loops after '#pragma omp target simd', but found only 1}}
+// expected-note@+1 {{as specified in 'collapse' clause}}
+#pragma omp target simd collapse(4)
+ for (i = 0; i < 16; ++i)
+ ; // expected-error {{expected 4 for loops after '#pragma omp target simd', but found only 1}}
+// expected-error@+2 {{expected ')'}}
+// expected-note@+1 {{to match this '('}} expected-note@+1 {{as specified in 'collapse' clause}}
+#pragma omp target simd collapse(4 4)
+ for (i = 0; i < 16; ++i)
+ ; // expected-error {{expected 4 for loops after '#pragma omp target simd', but found only 1}}
+// expected-error@+2 {{expected ')'}}
+// expected-note@+1 {{to match this '('}} expected-note@+1 {{as specified in 'collapse' clause}}
+#pragma omp target simd collapse(4, , 4)
+ for (i = 0; i < 16; ++i)
+ ; // expected-error {{expected 4 for loops after '#pragma omp target simd', but found only 1}}
+#pragma omp target simd collapse(4)
+ for (int i1 = 0; i1 < 16; ++i1)
+ for (int i2 = 0; i2 < 16; ++i2)
+ for (int i3 = 0; i3 < 16; ++i3)
+ for (int i4 = 0; i4 < 16; ++i4)
+ foo();
+// expected-error@+2 {{expected ')'}}
+// expected-note@+1 {{to match this '('}} expected-note@+1 {{as specified in 'collapse' clause}}
+#pragma omp target simd collapse(4, 8)
+ for (i = 0; i < 16; ++i)
+ ; // expected-error {{expected 4 for loops after '#pragma omp target simd', but found only 1}}
+// expected-error@+1 {{expression is not an integer constant expression}}
+#pragma omp target simd collapse(2.5)
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expression is not an integer constant expression}}
+#pragma omp target simd collapse(foo())
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{argument to 'collapse' clause must be a strictly positive integer value}}
+#pragma omp target simd collapse(-5)
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{argument to 'collapse' clause must be a strictly positive integer value}}
+#pragma omp target simd collapse(0)
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{argument to 'collapse' clause must be a strictly positive integer value}}
+#pragma omp target simd collapse(5 - 5)
+ for (i = 0; i < 16; ++i)
+ ;
+}
+
+void test_private() {
+ int i;
+// expected-error@+2 {{expected expression}}
+// expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
+#pragma omp target simd private(
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+2 {{expected ')'}} expected-note@+2 {{to match this '('}}
+// expected-error@+1 2 {{expected expression}}
+#pragma omp target simd private(,
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 2 {{expected expression}}
+#pragma omp target simd private(, )
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expected expression}}
+#pragma omp target simd private()
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expected expression}}
+#pragma omp target simd private(int)
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expected variable name}}
+#pragma omp target simd private(0)
+ for (i = 0; i < 16; ++i)
+ ;
+
+ int x, y, z;
+#pragma omp target simd private(x)
+ for (i = 0; i < 16; ++i)
+ ;
+#pragma omp target simd private(x, y)
+ for (i = 0; i < 16; ++i)
+ ;
+#pragma omp target simd private(x, y, z)
+ for (i = 0; i < 16; ++i) {
+ x = y * i + z;
+ }
+}
+
+void test_lastprivate() {
+ int i;
+// expected-error@+2 {{expected ')'}} expected-note@+2 {{to match this '('}}
+// expected-error@+1 {{expected expression}}
+#pragma omp target simd lastprivate(
+ for (i = 0; i < 16; ++i)
+ ;
+
+// expected-error@+2 {{expected ')'}} expected-note@+2 {{to match this '('}}
+// expected-error@+1 2 {{expected expression}}
+#pragma omp target simd lastprivate(,
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 2 {{expected expression}}
+#pragma omp target simd lastprivate(, )
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expected expression}}
+#pragma omp target simd lastprivate()
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expected expression}}
+#pragma omp target simd lastprivate(int)
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expected variable name}}
+#pragma omp target simd lastprivate(0)
+ for (i = 0; i < 16; ++i)
+ ;
+
+ int x, y, z;
+#pragma omp target simd lastprivate(x)
+ for (i = 0; i < 16; ++i)
+ ;
+#pragma omp target simd lastprivate(x, y)
+ for (i = 0; i < 16; ++i)
+ ;
+#pragma omp target simd lastprivate(x, y, z)
+ for (i = 0; i < 16; ++i)
+ ;
+}
+
+void test_firstprivate() {
+ int i;
+// expected-error@+2 {{expected ')'}} expected-note@+2 {{to match this '('}}
+// expected-error@+1 {{expected expression}}
+#pragma omp target simd firstprivate(
+ for (i = 0; i < 16; ++i)
+ ;
+
+// expected-error@+2 {{expected ')'}} expected-note@+2 {{to match this '('}}
+// expected-error@+1 2 {{expected expression}}
+#pragma omp target simd firstprivate(,
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 2 {{expected expression}}
+#pragma omp target simd firstprivate(, )
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expected expression}}
+#pragma omp target simd firstprivate()
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expected expression}}
+#pragma omp target simd firstprivate(int)
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expected variable name}}
+#pragma omp target simd firstprivate(0)
+ for (i = 0; i < 16; ++i)
+ ;
+
+ int x, y, z;
+#pragma omp target simd lastprivate(x) firstprivate(x)
+ for (i = 0; i < 16; ++i)
+ ;
+#pragma omp target simd lastprivate(x, y) firstprivate(x, y)
+ for (i = 0; i < 16; ++i)
+ ;
+#pragma omp target simd lastprivate(x, y, z) firstprivate(x, y, z)
+ for (i = 0; i < 16; ++i)
+ ;
+}
+
+void test_loop_messages() {
+ float a[100], b[100], c[100];
+// expected-error@+2 {{variable must be of integer or pointer type}}
+#pragma omp target simd
+ for (float fi = 0; fi < 10.0; fi++) {
+ c[(int)fi] = a[(int)fi] + b[(int)fi];
+ }
+// expected-error@+2 {{variable must be of integer or pointer type}}
+#pragma omp target simd
+ for (double fi = 0; fi < 10.0; fi++) {
+ c[(int)fi] = a[(int)fi] + b[(int)fi];
+ }
+}
+
+void test_safelen() {
+ int i;
+// expected-error@+1 {{expected '('}}
+#pragma omp target simd safelen
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expected expression}} expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
+#pragma omp target simd safelen(
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expected expression}}
+#pragma omp target simd safelen()
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expected expression}} expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
+#pragma omp target simd safelen(,
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expected expression}} expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
+#pragma omp target simd safelen(, )
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-warning@+2 {{extra tokens at the end of '#pragma omp target simd' are ignored}}
+// expected-error@+1 {{expected '('}}
+#pragma omp target simd safelen 4)
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+2 {{expected ')'}}
+// expected-note@+1 {{to match this '('}}
+#pragma omp target simd safelen(4
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+2 {{expected ')'}}
+// expected-note@+1 {{to match this '('}}
+#pragma omp target simd safelen(4,
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+2 {{expected ')'}}
+// expected-note@+1 {{to match this '('}}
+#pragma omp target simd safelen(4, )
+ for (i = 0; i < 16; ++i)
+ ;
+#pragma omp target simd safelen(4)
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+2 {{expected ')'}}
+// expected-note@+1 {{to match this '('}}
+#pragma omp target simd safelen(4 4)
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+2 {{expected ')'}}
+// expected-note@+1 {{to match this '('}}
+#pragma omp target simd safelen(4, , 4)
+ for (i = 0; i < 16; ++i)
+ ;
+#pragma omp target simd safelen(4)
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+2 {{expected ')'}}
+// expected-note@+1 {{to match this '('}}
+#pragma omp target simd safelen(4, 8)
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expression is not an integer constant expression}}
+#pragma omp target simd safelen(2.5)
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expression is not an integer constant expression}}
+#pragma omp target simd safelen(foo())
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{argument to 'safelen' clause must be a strictly positive integer value}}
+#pragma omp target simd safelen(-5)
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{argument to 'safelen' clause must be a strictly positive integer value}}
+#pragma omp target simd safelen(0)
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{argument to 'safelen' clause must be a strictly positive integer value}}
+#pragma omp target simd safelen(5 - 5)
+ for (i = 0; i < 16; ++i)
+ ;
+}
+
+void test_simdlen() {
+ int i;
+// expected-error@+1 {{expected '('}}
+#pragma omp target simd simdlen
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expected expression}} expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
+#pragma omp target simd simdlen(
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expected expression}}
+#pragma omp target simd simdlen()
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expected expression}} expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
+#pragma omp target simd simdlen(,
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expected expression}} expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
+#pragma omp target simd simdlen(, )
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-warning@+2 {{extra tokens at the end of '#pragma omp target simd' are ignored}}
+// expected-error@+1 {{expected '('}}
+#pragma omp target simd simdlen 4)
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+2 {{expected ')'}}
+// expected-note@+1 {{to match this '('}}
+#pragma omp target simd simdlen(4
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+2 {{expected ')'}}
+// expected-note@+1 {{to match this '('}}
+#pragma omp target simd simdlen(4,
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+2 {{expected ')'}}
+// expected-note@+1 {{to match this '('}}
+#pragma omp target simd simdlen(4, )
+ for (i = 0; i < 16; ++i)
+ ;
+#pragma omp target simd simdlen(4)
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+2 {{expected ')'}}
+// expected-note@+1 {{to match this '('}}
+#pragma omp target simd simdlen(4 4)
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+2 {{expected ')'}}
+// expected-note@+1 {{to match this '('}}
+#pragma omp target simd simdlen(4, , 4)
+ for (i = 0; i < 16; ++i)
+ ;
+#pragma omp target simd simdlen(4)
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+2 {{expected ')'}}
+// expected-note@+1 {{to match this '('}}
+#pragma omp target simd simdlen(4, 8)
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expression is not an integer constant expression}}
+#pragma omp target simd simdlen(2.5)
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expression is not an integer constant expression}}
+#pragma omp target simd simdlen(foo())
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{argument to 'simdlen' clause must be a strictly positive integer value}}
+#pragma omp target simd simdlen(-5)
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{argument to 'simdlen' clause must be a strictly positive integer value}}
+#pragma omp target simd simdlen(0)
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{argument to 'simdlen' clause must be a strictly positive integer value}}
+#pragma omp target simd simdlen(5 - 5)
+ for (i = 0; i < 16; ++i)
+ ;
+}
+
+void test_safelen_simdlen() {
+ int i;
+// expected-error@+1 {{the value of 'simdlen' parameter must be less than or equal to the value of the 'safelen' parameter}}
+#pragma omp target simd simdlen(6) safelen(5)
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{the value of 'simdlen' parameter must be less than or equal to the value of the 'safelen' parameter}}
+#pragma omp target simd safelen(5) simdlen(6)
+ for (i = 0; i < 16; ++i)
+ ;
+}
diff --git a/test/OpenMP/target_simd_nowait_messages.cpp b/test/OpenMP/target_simd_nowait_messages.cpp
new file mode 100644
index 000000000000..3635ce25956b
--- /dev/null
+++ b/test/OpenMP/target_simd_nowait_messages.cpp
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo() {
+}
+
+int main(int argc, char **argv) {
+ int i;
+ #pragma omp target simd nowait( // expected-warning {{extra tokens at the end of '#pragma omp target simd' are ignored}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd nowait (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target simd' are ignored}}
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd nowait device (-10u)
+ for (i = 0; i < argc; ++i) foo();
+ #pragma omp target simd nowait (3.14) device (-10u) // expected-warning {{extra tokens at the end of '#pragma omp target simd' are ignored}}
+ for (i = 0; i < argc; ++i) foo();
+
+ return 0;
+}
diff --git a/test/OpenMP/target_simd_private_messages.cpp b/test/OpenMP/target_simd_private_messages.cpp
new file mode 100644
index 000000000000..b20ff0a426a7
--- /dev/null
+++ b/test/OpenMP/target_simd_private_messages.cpp
@@ -0,0 +1,231 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note 2 {{declared here}} expected-note 2 {{forward declaration of 'S1'}}
+extern S1 a;
+class S2 {
+ mutable int a;
+
+public:
+ S2() : a(0) {}
+};
+const S2 b;
+const S2 ba[5];
+class S3 {
+ int a;
+
+public:
+ S3() : a(0) {}
+};
+const S3 ca[5];
+class S4 {
+ int a;
+ S4(); // expected-note {{implicitly declared private here}}
+
+public:
+ S4(int v) : a(v) {
+#pragma omp target simd private(a) private(this->a)
+ for (int k = 0; k < v; ++k)
+ ++this->a;
+ }
+};
+class S5 {
+ int a;
+ S5() : a(0) {} // expected-note {{implicitly declared private here}}
+
+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)
+ ++s.a;
+ return *this;
+ }
+};
+
+template <typename T>
+class S6 {
+public:
+ T a;
+
+ S6() : a(0) {}
+ S6(T v) : a(v) {
+#pragma omp target simd private(a) private(this->a)
+ for (int k = 0; k < v; ++k)
+ ++this->a;
+ }
+ S6 &operator=(S6 &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)
+ ++s.a;
+ return *this;
+ }
+};
+
+template <typename T>
+class S7 : public T {
+ T a;
+ S7() : a(0) {}
+
+public:
+ S7(T v) : a(v) {
+#pragma omp target simd private(a) private(this->a) private(T::a)
+ for (int k = 0; k < a.a; ++k)
+ ++this->a.a;
+ }
+ S7 &operator=(S7 &s) {
+#pragma omp target simd private(a) private(this->a) private(s.a) private(s.T::a) // expected-error 2 {{expected variable name or data member of current class}}
+ for (int k = 0; k < s.a.a; ++k)
+ ++s.a.a;
+ return *this;
+ }
+};
+
+S3 h;
+#pragma omp threadprivate(h) // expected-note 2 {{defined as threadprivate or thread local}}
+
+template <class I, class C>
+int foomain(I argc, C **argv) {
+ I e(4);
+ I g(5);
+ int i;
+ int &j = i;
+#pragma omp target simd private // expected-error {{expected '(' after 'private'}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd private( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd private() // expected-error {{expected expression}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd private(argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd private(argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd private(argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd private(argc)
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd private(S1) // expected-error {{'S1' does not refer to a value}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd private(a, b) // expected-error {{private variable with incomplete type 'S1'}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd private(argv[1]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd private(e, g)
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd private(h) // expected-error {{threadprivate or thread local variable cannot be private}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp parallel
+ {
+ int v = 0;
+ int i;
+#pragma omp target simd private(i)
+ for (int k = 0; k < argc; ++k) {
+ i = k;
+ v += i;
+ }
+ }
+#pragma omp parallel shared(i)
+#pragma omp parallel private(i)
+#pragma omp target simd private(j)
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd private(i)
+ for (int k = 0; k < argc; ++k)
+ ++k;
+ return 0;
+}
+
+namespace A {
+double x;
+#pragma omp threadprivate(x) // expected-note {{defined as threadprivate or thread local}}
+}
+namespace B {
+using A::x;
+}
+
+int main(int argc, char **argv) {
+ S4 e(4);
+ S5 g(5);
+ S6<float> s6(0.0) , s6_0(1.0);
+ S7<S6<float> > s7(0.0) , s7_0(1.0);
+ int i;
+ int &j = i;
+#pragma omp target simd private // expected-error {{expected '(' after 'private'}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd private( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd private() // expected-error {{expected expression}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd private(argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd private(argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd private(argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd private(argc)
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd private(S1) // expected-error {{'S1' does not refer to a value}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd private(a, b) // expected-error {{private variable with incomplete type 'S1'}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd private(argv[1]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd private(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd private(h, B::x) // expected-error 2 {{threadprivate or thread local variable cannot be private}}
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp parallel
+ {
+ int i;
+#pragma omp target simd private(i)
+ for (int k = 0; k < argc; ++k)
+ ++k;
+ }
+#pragma omp parallel shared(i)
+#pragma omp parallel private(i)
+#pragma omp target simd private(j)
+ for (int k = 0; k < argc; ++k)
+ ++k;
+#pragma omp target simd private(i)
+ for (int k = 0; k < argc; ++k)
+ ++k;
+ static int m;
+#pragma omp target simd private(m)
+ for (int k = 0; k < argc; ++k)
+ m = k + 2;
+
+ s6 = s6_0; // expected-note {{in instantiation of member function 'S6<float>::operator=' requested here}}
+ s7 = s7_0; // expected-note {{in instantiation of member function 'S7<S6<float> >::operator=' requested here}}
+ return foomain(argc, argv); // expected-note {{in instantiation of function template specialization 'foomain<int, char>' requested here}}
+}
+
diff --git a/test/OpenMP/target_simd_reduction_messages.cpp b/test/OpenMP/target_simd_reduction_messages.cpp
new file mode 100644
index 000000000000..ca14acb2293f
--- /dev/null
+++ b/test/OpenMP/target_simd_reduction_messages.cpp
@@ -0,0 +1,319 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+void foobar(int &ref) {
+#pragma omp target simd reduction(+:ref)
+ for (int i = 0; i < 10; ++i)
+ foo();
+}
+
+struct S1; // expected-note {{declared here}} expected-note 4 {{forward declaration of 'S1'}}
+extern S1 a;
+class S2 {
+ mutable int a;
+ S2 &operator+(const S2 &arg) { return (*this); } // expected-note 3 {{implicitly declared private here}}
+
+public:
+ S2() : a(0) {}
+ S2(S2 &s2) : a(s2.a) {}
+ static float S2s; // expected-note 2 {{static data member is predetermined as shared}}
+ static const float S2sc;
+};
+const float S2::S2sc = 0; // expected-note 2 {{'S2sc' defined here}}
+S2 b; // expected-note 3 {{'b' defined here}}
+const S2 ba[5]; // expected-note 2 {{'ba' defined here}}
+class S3 {
+ int a;
+
+public:
+ int b;
+ S3() : a(0) {}
+ S3(const S3 &s3) : a(s3.a) {}
+ S3 operator+(const S3 &arg1) { return arg1; }
+};
+int operator+(const S3 &arg1, const S3 &arg2) { return 5; }
+S3 c; // expected-note 3 {{'c' defined here}}
+const S3 ca[5]; // expected-note 2 {{'ca' defined here}}
+extern const int f; // expected-note 4 {{'f' declared here}}
+class S4 {
+ int a;
+ S4(); // expected-note {{implicitly declared private here}}
+ S4(const S4 &s4);
+ S4 &operator+(const S4 &arg) { return (*this); }
+
+public:
+ S4(int v) : a(v) {}
+};
+S4 &operator&=(S4 &arg1, S4 &arg2) { return arg1; }
+class S5 {
+ int a;
+ S5() : a(0) {} // expected-note {{implicitly declared private here}}
+ S5(const S5 &s5) : a(s5.a) {}
+ S5 &operator+(const S5 &arg);
+
+public:
+ S5(int v) : a(v) {}
+};
+class S6 { // expected-note 3 {{candidate function (the implicit copy assignment operator) not viable: no known conversion from 'int' to 'const S6' for 1st argument}}
+#if __cplusplus >= 201103L // C++11 or later
+// expected-note@-2 3 {{candidate function (the implicit move assignment operator) not viable}}
+#endif
+ int a;
+
+public:
+ S6() : a(6) {}
+ operator int() { return 6; }
+} o;
+
+S3 h, k;
+#pragma omp threadprivate(h) // expected-note 2 {{defined as threadprivate or thread local}}
+
+template <class T> // expected-note {{declared here}}
+T tmain(T argc) {
+ const T d = T(); // expected-note 4 {{'d' defined here}}
+ const T da[5] = {T()}; // expected-note 2 {{'da' defined here}}
+ T qa[5] = {T()};
+ T i;
+ T &j = i; // expected-note 4 {{'j' defined here}}
+ S3 &p = k; // expected-note 2 {{'p' defined here}}
+ const T &r = da[(int)i]; // expected-note 2 {{'r' defined here}}
+ T &q = qa[(int)i]; // expected-note 2 {{'q' defined here}}
+ T fl;
+#pragma omp target simd reduction // expected-error {{expected '(' after 'reduction'}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction + // expected-error {{expected '(' after 'reduction'}} expected-warning {{extra tokens at the end of '#pragma omp target simd' are ignored}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction( // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction(- // expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction() // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction(*) // expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected expression}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction(\) // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction(& : argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{invalid operands to binary expression ('float' and 'float')}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction(| : argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{invalid operands to binary expression ('float' and 'float')}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction(|| : argc ? i : argc) // expected-error 2 {{expected variable name, array element or array section}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction(foo : argc) //expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'float'}} expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'int'}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction(&& : argc)
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction(^ : T) // expected-error {{'T' does not refer to a value}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}} expected-error {{const-qualified list item cannot be reduction}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction(+ : o) // expected-error 2 {{no viable overloaded '='}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd private(i), reduction(+ : j), reduction(+ : q) // expected-error 4 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp parallel private(k)
+#pragma omp target simd reduction(+ : p), reduction(+ : p) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction(+ : p), reduction(+ : p) // expected-error 2 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 2 {{previously referenced here}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp parallel shared(i)
+#pragma omp parallel reduction(min : i)
+#pragma omp target simd reduction(max : j) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp parallel private(fl)
+#pragma omp target simd reduction(+ : fl)
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp parallel reduction(* : fl)
+#pragma omp target simd reduction(+ : fl)
+ for (int i = 0; i < 10; ++i)
+ foo();
+
+ return T();
+}
+
+namespace A {
+double x;
+#pragma omp threadprivate(x) // expected-note {{defined as threadprivate or thread local}}
+}
+namespace B {
+using A::x;
+}
+
+int main(int argc, char **argv) {
+ const int d = 5; // expected-note 2 {{'d' defined here}}
+ const int da[5] = {0}; // expected-note {{'da' defined here}}
+ int qa[5] = {0};
+ S4 e(4);
+ S5 g(5);
+ int i;
+ int &j = i; // expected-note 2 {{'j' defined here}}
+ S3 &p = k; // expected-note 2 {{'p' defined here}}
+ const int &r = da[i]; // expected-note {{'r' defined here}}
+ int &q = qa[i]; // expected-note {{'q' defined here}}
+ float fl;
+#pragma omp target simd reduction // expected-error {{expected '(' after 'reduction'}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction + // expected-error {{expected '(' after 'reduction'}} expected-warning {{extra tokens at the end of '#pragma omp target simd' are ignored}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction( // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction(- // expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction() // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction(*) // expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected expression}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction(\) // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction(foo : argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max'}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction(| : argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction(|| : argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name, array element or array section}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction(~ : argc) // expected-error {{expected unqualified-id}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction(&& : argc)
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction(^ : S1) // expected-error {{'S1' does not refer to a value}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified list item cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified list item cannot be reduction}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction(& : e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{invalid operands to binary expression ('S4' and 'S4')}} expected-error {{calling a private constructor of class 'S5'}} expected-error {{invalid operands to binary expression ('S5' and 'S5')}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction(+ : h, k, B::x) // expected-error 2 {{threadprivate or thread local variable cannot be reduction}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction(+ : o) // expected-error {{no viable overloaded '='}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd private(i), reduction(+ : j), reduction(+ : q) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp parallel private(k)
+#pragma omp target simd reduction(+ : p), reduction(+ : p) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction(+ : p), reduction(+ : p) // expected-error {{variable can appear only once in OpenMP 'reduction' clause}} expected-note {{previously referenced here}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp target simd reduction(+ : r) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp parallel shared(i)
+#pragma omp parallel reduction(min : i)
+#pragma omp target simd reduction(max : j) // expected-error {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp parallel private(fl)
+#pragma omp target simd reduction(+ : fl)
+ for (int i = 0; i < 10; ++i)
+ foo();
+#pragma omp parallel reduction(* : fl)
+#pragma omp target simd reduction(+ : fl)
+ for (int i = 0; i < 10; ++i)
+ foo();
+ static int m;
+#pragma omp target simd reduction(+ : m) // OK
+ for (int i = 0; i < 10; ++i)
+ m++;
+
+ return tmain(argc) + tmain(fl); // expected-note {{in instantiation of function template specialization 'tmain<int>' requested here}} expected-note {{in instantiation of function template specialization 'tmain<float>' requested here}}
+}
diff --git a/test/OpenMP/target_simd_safelen_messages.cpp b/test/OpenMP/target_simd_safelen_messages.cpp
new file mode 100644
index 000000000000..79bee763498e
--- /dev/null
+++ b/test/OpenMP/target_simd_safelen_messages.cpp
@@ -0,0 +1,102 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+
+void foo() {
+}
+
+#if __cplusplus >= 201103L
+// expected-note@+2 4 {{declared here}}
+#endif
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}}
+
+template <class T, typename S, int N, int ST> // expected-note {{declared here}}
+T tmain(T argc, S **argv) { //expected-note 2 {{declared here}}
+ #pragma omp target simd safelen // expected-error {{expected '(' after 'safelen'}}
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+ #pragma omp target simd safelen ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+ #pragma omp target simd safelen () // expected-error {{expected expression}}
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+ // expected-error@+3 {{expected ')'}} expected-note@+3 {{to match this '('}}
+ // expected-error@+2 2 {{expression is not an integral constant expression}}
+ // expected-note@+1 2 {{read of non-const variable 'argc' is not allowed in a constant expression}}
+ #pragma omp target simd safelen (argc
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+ // expected-error@+1 {{argument to 'safelen' clause must be a strictly positive integer value}}
+ #pragma omp target simd safelen (ST // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+ #pragma omp target simd safelen (1)) // expected-warning {{extra tokens at the end of '#pragma omp target simd' are ignored}}
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+ #pragma omp target simd safelen ((ST > 0) ? 1 + ST : 2)
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+ // expected-error@+6 2 {{directive '#pragma omp target simd' cannot contain more than one 'safelen' clause}}
+ // expected-error@+5 2 {{argument to 'safelen' clause must be a strictly positive integer value}}
+ // expected-error@+4 2 {{expression is not an integral constant expression}}
+#if __cplusplus >= 201103L
+ // expected-note@+2 2 {{non-constexpr function 'foobool' cannot be used in a constant expression}}
+#endif
+ #pragma omp target simd safelen (foobool(argc)), safelen (true), safelen (-5)
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+ #pragma omp target simd safelen (S) // expected-error {{'S' does not refer to a value}}
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+#if __cplusplus <= 199711L
+ // expected-error@+4 2 {{expression is not an integral constant expression}}
+#else
+ // expected-error@+2 2 {{integral constant expression must have integral or unscoped enumeration type, not 'char *'}}
+#endif
+ #pragma omp target simd safelen (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+ #pragma omp target simd safelen (4)
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+ #pragma omp target simd safelen (N) // expected-error {{argument to 'safelen' clause must be a strictly positive integer value}}
+ for (T i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+ return argc;
+}
+
+int main(int argc, char **argv) {
+ #pragma omp target simd safelen // expected-error {{expected '(' after 'safelen'}}
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+ #pragma omp target simd safelen ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+ #pragma omp target simd safelen () // expected-error {{expected expression}}
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+ #pragma omp target simd safelen (4 // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+ #pragma omp target simd safelen (2+2)) // expected-warning {{extra tokens at the end of '#pragma omp target simd' are ignored}}
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+ // expected-error@+4 {{expression is not an integral constant expression}}
+#if __cplusplus >= 201103L
+ // expected-note@+2 {{non-constexpr function 'foobool' cannot be used in a constant expression}}
+#endif
+ #pragma omp target simd safelen (foobool(1) > 0 ? 1 : 2)
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+ // expected-error@+6 {{expression is not an integral constant expression}}
+#if __cplusplus >= 201103L
+ // expected-note@+4 {{non-constexpr function 'foobool' cannot be used in a constant expression}}
+#endif
+ // expected-error@+2 2 {{directive '#pragma omp target simd' cannot contain more than one 'safelen' clause}}
+ // expected-error@+1 2 {{argument to 'safelen' clause must be a strictly positive integer value}}
+ #pragma omp target simd safelen (foobool(argc)), safelen (true), safelen (-5)
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+ #pragma omp target simd safelen (S1) // expected-error {{'S1' does not refer to a value}}
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+#if __cplusplus <= 199711L
+ // expected-error@+4 {{expression is not an integral constant expression}}
+#else
+ // expected-error@+2 {{integral constant expression must have integral or unscoped enumeration type, not 'char *'}}
+#endif
+ #pragma omp target simd safelen (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+ // expected-error@+3 {{statement after '#pragma omp target simd' must be a for loop}}
+ // expected-note@+1 {{in instantiation of function template specialization 'tmain<int, char, -1, -2>' requested here}}
+ #pragma omp target simd safelen(safelen(tmain<int, char, -1, -2>(argc, argv) // expected-error 2 {{expected ')'}} expected-note 2 {{to match this '('}}
+ foo();
+ // expected-note@+1 {{in instantiation of function template specialization 'tmain<int, char, 12, 4>' requested here}}
+ return tmain<int, char, 12, 4>(argc, argv);
+}
+
diff --git a/test/OpenMP/target_simd_simdlen_messages.cpp b/test/OpenMP/target_simd_simdlen_messages.cpp
new file mode 100644
index 000000000000..8a9a3dc9f9b3
--- /dev/null
+++ b/test/OpenMP/target_simd_simdlen_messages.cpp
@@ -0,0 +1,142 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+
+void foo() {
+}
+
+#if __cplusplus >= 201103L
+// expected-note@+2 4 {{declared here}}
+#endif
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}}
+
+template <class T, typename S, int N, int ST> // expected-note {{declared here}}
+T tmain(T argc, S **argv) { //expected-note 2 {{declared here}}
+#pragma omp target simd simdlen // expected-error {{expected '(' after 'simdlen'}}
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target simd simdlen ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target simd simdlen () // expected-error {{expected expression}}
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+// expected-error@+3 {{expected ')'}} expected-note@+3 {{to match this '('}}
+// expected-error@+2 2 {{expression is not an integral constant expression}}
+// expected-note@+1 2 {{read of non-const variable 'argc' is not allowed in a constant expression}}
+#pragma omp target simd simdlen (argc
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+// expected-error@+1 {{argument to 'simdlen' clause must be a strictly positive integer value}}
+#pragma omp target simd simdlen (ST // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target simd simdlen (1)) // expected-warning {{extra tokens at the end of '#pragma omp target simd' are ignored}}
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target simd simdlen ((ST > 0) ? 1 + ST : 2)
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+ // expected-error@+6 2 {{directive '#pragma omp target simd' cannot contain more than one 'simdlen' clause}}
+ // expected-error@+5 2 {{argument to 'simdlen' clause must be a strictly positive integer value}}
+ // expected-error@+4 2 {{expression is not an integral constant expression}}
+#if __cplusplus >= 201103L
+ // expected-note@+2 2 {{non-constexpr function 'foobool' cannot be used in a constant expression}}
+#endif
+#pragma omp target simd simdlen (foobool(argc)), simdlen (true), simdlen (-5)
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target simd simdlen (S) // expected-error {{'S' does not refer to a value}}
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#if __cplusplus <= 199711L
+ // expected-error@+4 2 {{expression is not an integral constant expression}}
+#else
+ // expected-error@+2 2 {{integral constant expression must have integral or unscoped enumeration type, not 'char *'}}
+#endif
+#pragma omp target simd simdlen (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+ #pragma omp target simd simdlen (4)
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+ #pragma omp target simd simdlen (N) // expected-error {{argument to 'simdlen' clause must be a strictly positive integer value}}
+ for (T i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target simd simdlen (2), safelen (4) // OK
+ for (T i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target simd simdlen (4), safelen (4) // OK
+ for (T i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target simd simdlen (8), safelen (4) // expected-error{{the value of 'simdlen' parameter must be less than or equal to the value of the 'safelen' parameter}}
+ for (T i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+ return argc;
+}
+
+int main(int argc, char **argv) {
+#pragma omp target simd simdlen // expected-error {{expected '(' after 'simdlen'}}
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target simd simdlen ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target simd simdlen () // expected-error {{expected expression}}
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target simd simdlen (4 // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target simd simdlen (2+2)) // expected-warning {{extra tokens at the end of '#pragma omp target simd' are ignored}}
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+
+ // expected-error@+4 {{expression is not an integral constant expression}}
+#if __cplusplus >= 201103L
+ // expected-note@+2 {{non-constexpr function 'foobool' cannot be used in a constant expression}}
+#endif
+#pragma omp target simd simdlen (foobool(1) > 0 ? 1 : 2)
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+
+ // expected-error@+6 {{expression is not an integral constant expression}}
+#if __cplusplus >= 201103L
+ // expected-note@+4 {{non-constexpr function 'foobool' cannot be used in a constant expression}}
+#endif
+// expected-error@+2 2 {{directive '#pragma omp target simd' cannot contain more than one 'simdlen' clause}}
+// expected-error@+1 2 {{argument to 'simdlen' clause must be a strictly positive integer value}}
+#pragma omp target simd simdlen (foobool(argc)), simdlen (true), simdlen (-5)
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target simd simdlen (S1) // expected-error {{'S1' does not refer to a value}}
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#if __cplusplus <= 199711L
+ // expected-error@+4 {{expression is not an integral constant expression}}
+#else
+ // expected-error@+2 {{integral constant expression must have integral or unscoped enumeration type, not 'char *'}}
+#endif
+#pragma omp target simd simdlen (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+
+// expected-error@+3 {{statement after '#pragma omp target simd' must be a for loop}}
+// expected-note@+1 {{in instantiation of function template specialization 'tmain<int, char, -1, -2>' requested here}}
+#pragma omp target simd simdlen(simdlen(tmain<int, char, -1, -2>(argc, argv) // expected-error 2 {{expected ')'}} expected-note 2 {{to match this '('}}
+ foo();
+
+#pragma omp target simd simdlen (2), safelen (4) // OK
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target simd simdlen (4), safelen (4) // OK
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target simd simdlen (8), safelen (4) // expected-error{{the value of 'simdlen' parameter must be less than or equal to the value of the 'safelen' parameter}}
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+
+ // expected-note@+1 {{in instantiation of function template specialization 'tmain<int, char, 12, 4>' requested here}}
+ return tmain<int, char, 12, 4>(argc, argv);
+}
+
diff --git a/test/OpenMP/target_teams_ast_print.cpp b/test/OpenMP/target_teams_ast_print.cpp
new file mode 100644
index 000000000000..a80b8d7dac83
--- /dev/null
+++ b/test/OpenMP/target_teams_ast_print.cpp
@@ -0,0 +1,98 @@
+// 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
+// expected-no-diagnostics
+
+#ifndef HEADER
+#define HEADER
+
+void foo() {}
+
+template <class T>
+struct S {
+ operator T() {return T();}
+ static T TS;
+ #pragma omp threadprivate(TS)
+};
+
+// CHECK: template <class T> struct S {
+// CHECK: static T TS;
+// CHECK-NEXT: #pragma omp threadprivate(S::TS)
+// CHECK: };
+// CHECK: template<> struct S<int> {
+// CHECK: static int TS;
+// CHECK-NEXT: #pragma omp threadprivate(S<int>::TS)
+// CHECK-NEXT: }
+// CHECK: template<> struct S<long> {
+// CHECK: static long TS;
+// CHECK-NEXT: #pragma omp threadprivate(S<long>::TS)
+// CHECK-NEXT: }
+
+template <typename T, int C>
+T tmain(T argc, T *argv) {
+ T b = argc, c, d, e, f, g;
+ static T a;
+ S<T> s;
+#pragma omp target teams
+ a=2;
+#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)
+ foo();
+#pragma omp target teams reduction(^:e, f) reduction(&& : g)
+ foo();
+ return 0;
+}
+
+// CHECK: template <typename T, int C> 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: 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()
+// CHECK-NEXT: #pragma omp target teams reduction(^: e,f) reduction(&&: g)
+// CHECK-NEXT: foo()
+// CHECK: template<> int tmain<int, 5>(int argc, int *argv) {
+// CHECK-NEXT: int b = argc, c, d, e, f, g;
+// CHECK-NEXT: static int a;
+// CHECK-NEXT: S<int> s;
+// 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(5) thread_limit(d * 5)
+// CHECK-NEXT: foo()
+// CHECK-NEXT: #pragma omp target teams reduction(^: e,f) reduction(&&: g)
+// CHECK-NEXT: foo()
+// CHECK: template<> long tmain<long, 1>(long argc, long *argv) {
+// CHECK-NEXT: long b = argc, c, d, e, f, g;
+// CHECK-NEXT: static long a;
+// CHECK-NEXT: S<long> s;
+// 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(1) thread_limit(d * 1)
+// CHECK-NEXT: foo()
+// CHECK-NEXT: #pragma omp target teams reduction(^: e,f) reduction(&&: g)
+// CHECK-NEXT: foo()
+
+enum Enum { };
+
+int main (int argc, char **argv) {
+ long x;
+ int b = argc, c, d, e, f, g;
+ static int a;
+ #pragma omp threadprivate(a)
+ Enum ee;
+// CHECK: Enum ee;
+#pragma omp target teams
+// CHECK-NEXT: #pragma omp target teams
+ a=2;
+// CHECK-NEXT: a = 2;
+#pragma omp target teams default(none), private(argc,b) num_teams(f) firstprivate(argv) reduction(| : c, d) reduction(* : e) thread_limit(f+g)
+// CHECK-NEXT: #pragma omp target teams default(none) private(argc,b) num_teams(f) firstprivate(argv) reduction(|: c,d) reduction(*: e) thread_limit(f + g)
+ foo();
+// CHECK-NEXT: foo();
+ return tmain<int, 5>(b, &b) + tmain<long, 1>(x, &x);
+}
+
+extern template int S<int>::TS;
+extern template long S<long>::TS;
+#endif
diff --git a/test/OpenMP/target_teams_default_messages.cpp b/test/OpenMP/target_teams_default_messages.cpp
new file mode 100644
index 000000000000..053463749b5a
--- /dev/null
+++ b/test/OpenMP/target_teams_default_messages.cpp
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -verify -fopenmp -o - %s
+
+void foo();
+
+int main(int argc, char **argv) {
+#pragma omp target teams default // expected-error {{expected '(' after 'default'}}
+ foo();
+#pragma omp target teams default ( // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ foo();
+#pragma omp target teams default () // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+ foo();
+#pragma omp target teams default (none // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ foo();
+#pragma omp target teams default (shared), default(shared) // expected-error {{directive '#pragma omp target teams' cannot contain more than one 'default' clause}}
+ foo();
+#pragma omp target teams default (x) // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+ foo();
+
+#pragma omp target teams default(none)
+ ++argc; // expected-error {{variable 'argc' must have explicitly specified data sharing attributes}}
+
+#pragma omp target teams default(none)
+#pragma omp parallel default(shared)
+ ++argc;
+ return 0;
+}
diff --git a/test/OpenMP/target_teams_defaultmap_messages.cpp b/test/OpenMP/target_teams_defaultmap_messages.cpp
new file mode 100644
index 000000000000..f2d30fdc87e2
--- /dev/null
+++ b/test/OpenMP/target_teams_defaultmap_messages.cpp
@@ -0,0 +1,56 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo() {
+}
+
+template <class T, typename S, int N, int ST>
+T tmain(T argc, S **argv) {
+ #pragma omp target teams defaultmap // expected-error {{expected '(' after 'defaultmap'}}
+ foo();
+ #pragma omp target teams defaultmap ( // expected-error {{expected 'tofrom' in OpenMP clause 'defaultmap'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ foo();
+ #pragma omp target teams defaultmap () // expected-error {{expected 'tofrom' in OpenMP clause 'defaultmap'}}
+ foo();
+ #pragma omp target teams defaultmap (tofrom // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-warning {{missing ':' after defaultmap modifier - ignoring}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}}
+ foo();
+ #pragma omp target teams defaultmap (tofrom: // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}}
+ foo();
+ #pragma omp target teams defaultmap (tofrom) // expected-warning {{missing ':' after defaultmap modifier - ignoring}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}}
+ foo();
+ #pragma omp target teams defaultmap (tofrom scalar) // expected-warning {{missing ':' after defaultmap modifier - ignoring}}
+ foo();
+ #pragma omp target teams defaultmap (tofrom, // expected-error {{expected ')'}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}} expected-warning {{missing ':' after defaultmap modifier - ignoring}} expected-note {{to match this '('}}
+ foo();
+ #pragma omp target teams defaultmap (scalar: // expected-error {{expected ')'}} expected-error {{expected 'tofrom' in OpenMP clause 'defaultmap'}} expected-note {{to match this '('}}
+ foo();
+ #pragma omp target teams defaultmap (tofrom, scalar // expected-error {{expected ')'}} expected-warning {{missing ':' after defaultmap modifier - ignoring}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}} expected-note {{to match this '('}}
+ foo();
+
+ return argc;
+}
+
+int main(int argc, char **argv) {
+ #pragma omp target teams defaultmap // expected-error {{expected '(' after 'defaultmap'}}
+ foo();
+ #pragma omp target teams defaultmap ( // expected-error {{expected 'tofrom' in OpenMP clause 'defaultmap'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ foo();
+ #pragma omp target teams defaultmap () // expected-error {{expected 'tofrom' in OpenMP clause 'defaultmap'}}
+ foo();
+ #pragma omp target teams defaultmap (tofrom // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-warning {{missing ':' after defaultmap modifier - ignoring}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}}
+ foo();
+ #pragma omp target teams defaultmap (tofrom: // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}}
+ foo();
+ #pragma omp target teams defaultmap (tofrom) // expected-warning {{missing ':' after defaultmap modifier - ignoring}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}}
+ foo();
+ #pragma omp target teams defaultmap (tofrom scalar) // expected-warning {{missing ':' after defaultmap modifier - ignoring}}
+ foo();
+ #pragma omp target teams defaultmap (tofrom, // expected-error {{expected ')'}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}} expected-warning {{missing ':' after defaultmap modifier - ignoring}} expected-note {{to match this '('}}
+ foo();
+ #pragma omp target teams defaultmap (scalar: // expected-error {{expected ')'}} expected-error {{expected 'tofrom' in OpenMP clause 'defaultmap'}} expected-note {{to match this '('}}
+ foo();
+ #pragma omp target teams defaultmap (tofrom, scalar // expected-error {{expected ')'}} expected-warning {{missing ':' after defaultmap modifier - ignoring}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}} expected-note {{to match this '('}}
+ foo();
+
+ return tmain<int, char, 1, 0>(argc, argv);
+}
+
diff --git a/test/OpenMP/target_teams_depend_messages.cpp b/test/OpenMP/target_teams_depend_messages.cpp
new file mode 100644
index 000000000000..9308e8972872
--- /dev/null
+++ b/test/OpenMP/target_teams_depend_messages.cpp
@@ -0,0 +1,89 @@
+// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - -std=c++11 %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}}
+
+class vector {
+ public:
+ int operator[](int index) { return 0; }
+};
+
+int main(int argc, char **argv, char *env[]) {
+ vector vec;
+ typedef float V __attribute__((vector_size(16)));
+ V a;
+ auto arr = x; // expected-error {{use of undeclared identifier 'x'}}
+
+#pragma omp target teams depend // expected-error {{expected '(' after 'depend'}}
+ foo();
+#pragma omp target teams depend ( // expected-error {{expected 'in', 'out' or 'inout' in OpenMP clause 'depend'}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-warning {{missing ':' after dependency type - ignoring}}
+ foo();
+#pragma omp target teams depend () // expected-error {{expected 'in', 'out' or 'inout' in OpenMP clause 'depend'}} expected-warning {{missing ':' after dependency type - ignoring}}
+ foo();
+#pragma omp target teams depend (argc // expected-error {{expected 'in', 'out' or 'inout' in OpenMP clause 'depend'}} expected-warning {{missing ':' after dependency type - ignoring}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ foo();
+#pragma omp target teams depend (source : argc) // expected-error {{expected 'in', 'out' or 'inout' in OpenMP clause 'depend'}}
+ foo();
+#pragma omp target teams depend (source) // expected-error {{expected expression}} expected-warning {{missing ':' after dependency type - ignoring}}
+ foo();
+#pragma omp target teams depend (in : argc)) // expected-warning {{extra tokens at the end of '#pragma omp target teams' are ignored}}
+ foo();
+#pragma omp target teams depend (out: ) // expected-error {{expected expression}}
+ foo();
+#pragma omp target teams depend (inout : foobool(argc)), depend (in, argc) // expected-error {{expected variable name, array element or array section}} expected-warning {{missing ':' after dependency type - ignoring}} expected-error {{expected expression}}
+ foo();
+#pragma omp target teams depend (out :S1) // expected-error {{'S1' does not refer to a value}}
+ foo();
+#pragma omp target teams depend(in : argv[1][1] = '2') // expected-error {{expected variable name, array element or array section}}
+ foo();
+#pragma omp target teams depend (in : vec[1]) // expected-error {{expected variable name, array element or array section}}
+ foo();
+#pragma omp target teams depend (in : argv[0])
+ foo();
+#pragma omp target teams depend (in : ) // expected-error {{expected expression}}
+ foo();
+#pragma omp target teams depend (in : main) // expected-error {{expected variable name, array element or array section}}
+ foo();
+#pragma omp target teams depend(in : a[0]) // expected-error{{expected variable name, array element or array section}}
+ foo();
+#pragma omp target teams depend (in : vec[1:2]) // expected-error {{ value is not an array or pointer}}
+ foo();
+#pragma omp target teams depend (in : argv[ // expected-error {{expected expression}} expected-error {{expected ']'}} expected-error {{expected ')'}} expected-note {{to match this '['}} expected-note {{to match this '('}}
+ foo();
+#pragma omp target teams depend (in : argv[: // expected-error {{expected expression}} expected-error {{expected ']'}} expected-error {{expected ')'}} expected-note {{to match this '['}} expected-note {{to match this '('}}
+ foo();
+#pragma omp target teams depend (in : argv[:] // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ foo();
+#pragma omp target teams depend (in : argv[argc: // expected-error {{expected expression}} expected-error {{expected ']'}} expected-error {{expected ')'}} expected-note {{to match this '['}} expected-note {{to match this '('}}
+ foo();
+#pragma omp target teams depend (in : argv[argc:argc] // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ foo();
+#pragma omp target teams depend (in : argv[0:-1]) // expected-error {{section length is evaluated to a negative value -1}}
+ foo();
+#pragma omp target teams depend (in : argv[-1:0])
+ foo();
+#pragma omp target teams depend (in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
+ foo();
+#pragma omp target teams depend (in : argv[3:4:1]) // expected-error {{expected ']'}} expected-note {{to match this '['}}
+ foo();
+#pragma omp target teams depend(in:a[0:1]) // expected-error {{subscripted value is not an array or pointer}}
+ foo();
+#pragma omp target teams depend(in:argv[argv[:2]:1]) // expected-error {{OpenMP array section is not allowed here}}
+ foo();
+#pragma omp target teams depend(in:argv[0:][:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
+ foo();
+#pragma omp target teams depend(in:env[0:][:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is an array of unknown bound}}
+ foo();
+#pragma omp target teams depend(in : argv[ : argc][1 : argc - 1])
+ foo();
+#pragma omp target teams depend(in : arr[0])
+ foo();
+
+ return 0;
+}
diff --git a/test/OpenMP/target_teams_device_messages.cpp b/test/OpenMP/target_teams_device_messages.cpp
new file mode 100644
index 000000000000..bd75da835158
--- /dev/null
+++ b/test/OpenMP/target_teams_device_messages.cpp
@@ -0,0 +1,39 @@
+// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -ferror-limit 100 -o - %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}}
+
+int main(int argc, char **argv) {
+#pragma omp target teams device // expected-error {{expected '(' after 'device'}}
+ foo();
+#pragma omp target teams device ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ foo();
+#pragma omp target teams device () // expected-error {{expected expression}}
+ foo();
+#pragma omp target teams device (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ foo();
+#pragma omp target teams device (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target teams' are ignored}}
+ foo();
+#pragma omp target teams device (argc > 0 ? argv[1] : argv[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ foo();
+#pragma omp target teams device (argc + argc)
+ foo();
+#pragma omp target teams device (argc), device (argc+1) // expected-error {{directive '#pragma omp target teams' cannot contain more than one 'device' clause}}
+ foo();
+#pragma omp target teams device (S1) // expected-error {{'S1' does not refer to a value}}
+ foo();
+#pragma omp target teams device (-2) // expected-error {{argument to 'device' clause must be a non-negative integer value}}
+ foo();
+#pragma omp target teams device (-10u)
+ foo();
+#pragma omp target teams device (3.14) // expected-error {{expression must have integral or unscoped enumeration type, not 'double'}}
+ foo();
+
+ return 0;
+}
diff --git a/test/OpenMP/target_teams_distribute_ast_print.cpp b/test/OpenMP/target_teams_distribute_ast_print.cpp
new file mode 100644
index 000000000000..ae50366aabb3
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_ast_print.cpp
@@ -0,0 +1,150 @@
+// 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
+// expected-no-diagnostics
+
+#ifndef HEADER
+#define HEADER
+
+void foo() {}
+
+struct S {
+ S(): a(0) {}
+ S(int v) : a(v) {}
+ int a;
+ typedef int type;
+};
+
+template <typename T>
+class S7 : public T {
+protected:
+ T a;
+ S7() : a(0) {}
+
+public:
+ S7(typename T::type v) : a(v) {
+#pragma omp target teams distribute private(a) private(this->a) private(T::a)
+ for (int k = 0; k < a.a; ++k)
+ ++this->a.a;
+ }
+ S7 &operator=(S7 &s) {
+#pragma omp target teams distribute private(a) private(this->a)
+ for (int k = 0; k < s.a.a; ++k)
+ ++s.a.a;
+ return *this;
+ }
+
+ void foo() {
+ int b, argv, d, c, e, f;
+#pragma omp target teams distribute default(none), private(b) firstprivate(argv) shared(d) reduction(+:c) reduction(max:e) num_teams(f) thread_limit(d)
+ for (int k = 0; k < a.a; ++k)
+ ++a.a;
+ }
+};
+// CHECK: #pragma omp target teams distribute private(this->a) private(this->a) private(T::a)
+// CHECK: #pragma omp target teams distribute private(this->a) private(this->a)
+// CHECK: #pragma omp target teams distribute default(none) private(b) firstprivate(argv) shared(d) reduction(+: c) reduction(max: e) num_teams(f) thread_limit(d)
+// CHECK: #pragma omp target teams distribute private(this->a) private(this->a) private(this->S::a)
+
+class S8 : public S7<S> {
+ S8() {}
+
+public:
+ S8(int v) : S7<S>(v){
+#pragma omp target teams distribute private(a) private(this->a) private(S7<S>::a)
+ for (int k = 0; k < a.a; ++k)
+ ++this->a.a;
+ }
+ S8 &operator=(S8 &s) {
+#pragma omp target teams distribute private(a) private(this->a)
+ for (int k = 0; k < s.a.a; ++k)
+ ++s.a.a;
+ return *this;
+ }
+
+ void bar() {
+ int b, argv, d, c, e, f;
+#pragma omp target teams distribute default(none), private(b) firstprivate(argv) shared(d) reduction(+:c) reduction(max:e) num_teams(f) thread_limit(d)
+ for (int k = 0; k < a.a; ++k)
+ ++a.a;
+ }
+};
+// CHECK: #pragma omp target teams distribute private(this->a) private(this->a) private(this->S7<S>::a)
+// CHECK: #pragma omp target teams distribute private(this->a) private(this->a)
+// CHECK: #pragma omp target teams distribute default(none) private(b) firstprivate(argv) shared(d) reduction(+: c) reduction(max: e) num_teams(f) thread_limit(d)
+
+template <class T, int N>
+T tmain(T argc) {
+ T b = argc, c, d, e, f, g;
+ static T a;
+// CHECK: static T a;
+#pragma omp target teams distribute
+ for (int i=0; i < 2; ++i)
+ a = 2;
+// 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)
+ for (int i = 0; i < 10; ++i)
+ for (int j = 0; j < 10; ++j)
+ foo();
+// CHECK: #pragma omp target teams distribute private(argc,b) firstprivate(c,d) collapse(2)
+// CHECK-NEXT: for (int i = 0; i < 10; ++i)
+// CHECK-NEXT: for (int j = 0; j < 10; ++j)
+// CHECK-NEXT: foo();
+ for (int i = 0; i < 10; ++i)
+ foo();
+// CHECK: for (int i = 0; i < 10; ++i)
+// CHECK-NEXT: foo();
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i)
+ foo();
+// CHECK: #pragma omp target teams distribute
+// CHECK-NEXT: for (int i = 0; i < 10; ++i)
+// CHECK-NEXT: foo();
+#pragma omp target teams distribute default(none), private(b) firstprivate(argc) shared(d) reduction(+:c) reduction(max:e) num_teams(f) thread_limit(d)
+ for (int k = 0; k < 10; ++k)
+ e += d + argc;
+// CHECK: #pragma omp target teams distribute default(none) private(b) firstprivate(argc) shared(d) reduction(+: c) reduction(max: e) num_teams(f) thread_limit(d)
+// CHECK-NEXT: for (int k = 0; k < 10; ++k)
+// CHECK-NEXT: e += d + argc;
+ return T();
+}
+
+int main (int argc, char **argv) {
+ int b = argc, c, d, e, f, g;
+ static int a;
+// CHECK: static int a;
+#pragma omp target teams distribute
+ for (int i=0; i < 2; ++i)
+ a = 2;
+// 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(argv, c), collapse(2)
+ for (int i = 0; i < 10; ++i)
+ for (int j = 0; j < 10; ++j)
+ foo();
+// CHECK: #pragma omp target teams distribute private(argc,b) firstprivate(argv,c) collapse(2)
+// CHECK-NEXT: for (int i = 0; i < 10; ++i)
+// CHECK-NEXT: for (int j = 0; j < 10; ++j)
+// CHECK-NEXT: foo();
+ for (int i = 0; i < 10; ++i)
+ foo();
+// CHECK: for (int i = 0; i < 10; ++i)
+// CHECK-NEXT: foo();
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i)foo();
+// CHECK: #pragma omp target teams distribute
+// CHECK-NEXT: for (int i = 0; i < 10; ++i)
+// CHECK-NEXT: foo();
+#pragma omp target teams distribute default(none), private(b) firstprivate(argc) shared(d) reduction(+:c) reduction(max:e) num_teams(f) thread_limit(d)
+ for (int k = 0; k < 10; ++k)
+ e += d + argc;
+// CHECK: #pragma omp target teams distribute default(none) private(b) firstprivate(argc) shared(d) reduction(+: c) reduction(max: e) num_teams(f) thread_limit(d)
+// CHECK-NEXT: for (int k = 0; k < 10; ++k)
+// CHECK-NEXT: e += d + argc;
+ return (0);
+}
+
+#endif
diff --git a/test/OpenMP/target_teams_distribute_collapse_messages.cpp b/test/OpenMP/target_teams_distribute_collapse_messages.cpp
new file mode 100644
index 000000000000..f646655a09e1
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_collapse_messages.cpp
@@ -0,0 +1,127 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}}
+
+template <class T, typename S, int N, int ST> // expected-note {{declared here}}
+T tmain(T argc, S **argv) { //expected-note 2 {{declared here}}
+#pragma omp target teams distribute collapse // expected-error {{expected '(' after 'collapse'}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target teams distribute collapse ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = ST; i < N; i++)
+
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+#pragma omp target teams distribute collapse () // expected-error {{expected expression}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+// expected-error@+3 {{expected ')'}} expected-note@+3 {{to match this '('}}
+// expected-error@+2 2 {{expression is not an integral constant expression}}
+// expected-note@+1 2 {{read of non-const variable 'argc' is not allowed in a constant expression}}
+#pragma omp target teams distribute collapse (argc
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+// expected-error@+1 2 {{argument to 'collapse' clause must be a strictly positive integer value}}
+#pragma omp target teams distribute collapse (ST // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target teams distribute collapse (1)) // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute' are ignored}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target teams distribute collapse ((ST > 0) ? 1 + ST : 2) // expected-note 2 {{as specified in 'collapse' clause}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST]; // expected-error 2 {{expected 2 for loops after '#pragma omp target teams distribute', but found only 1}}
+
+// expected-error@+3 2 {{directive '#pragma omp target teams distribute' cannot contain more than one 'collapse' clause}}
+// expected-error@+2 2 {{argument to 'collapse' clause must be a strictly positive integer value}}
+// expected-error@+1 2 {{expression is not an integral constant expression}}
+#pragma omp target teams distribute collapse (foobool(argc)), collapse (true), collapse (-5)
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target teams distribute collapse (S) // expected-error {{'S' does not refer to a value}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+// expected-error@+1 2 {{expression is not an integral constant expression}}
+#pragma omp target teams distribute collapse (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target teams distribute collapse (1)
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target teams distribute collapse (N) // expected-error {{argument to 'collapse' clause must be a strictly positive integer value}}
+ for (T i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target teams distribute collapse (2) // expected-note {{as specified in 'collapse' clause}}
+ foo(); // expected-error {{expected 2 for loops after '#pragma omp target teams distribute'}}
+ return argc;
+}
+
+int main(int argc, char **argv) {
+#pragma omp target teams distribute collapse // expected-error {{expected '(' after 'collapse'}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target teams distribute collapse ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target teams distribute collapse () // expected-error {{expected expression}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target teams distribute collapse (4 // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-note {{as specified in 'collapse' clause}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4]; // expected-error {{expected 4 for loops after '#pragma omp target teams distribute', but found only 1}}
+
+#pragma omp target teams distribute collapse (2+2)) // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute' are ignored}} expected-note {{as specified in 'collapse' clause}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4]; // expected-error {{expected 4 for loops after '#pragma omp target teams distribute', but found only 1}}
+
+#pragma omp target teams distribute collapse (foobool(1) > 0 ? 1 : 2) // expected-error {{expression is not an integral constant expression}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+// expected-error@+3 {{expression is not an integral constant expression}}
+// expected-error@+2 2 {{directive '#pragma omp target teams distribute' cannot contain more than one 'collapse' clause}}
+// expected-error@+1 2 {{argument to 'collapse' clause must be a strictly positive integer value}}
+#pragma omp target teams distribute collapse (foobool(argc)), collapse (true), collapse (-5)
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target teams distribute collapse (S1) // expected-error {{'S1' does not refer to a value}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+// expected-error@+1 {{expression is not an integral constant expression}}
+#pragma omp target teams distribute collapse (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+// expected-error@+3 {{statement after '#pragma omp target teams distribute' must be a for loop}}
+// expected-note@+1 {{in instantiation of function template specialization 'tmain<int, char, -1, -2>' requested here}}
+#pragma omp target teams distribute collapse(collapse(tmain<int, char, -1, -2>(argc, argv) // expected-error 2 {{expected ')'}} expected-note 2 {{to match this '('}}
+ foo();
+
+#pragma omp target teams distribute collapse (2) // expected-note {{as specified in 'collapse' clause}}
+ foo(); // expected-error {{expected 2 for loops after '#pragma omp target teams distribute'}}
+
+// expected-note@+1 {{in instantiation of function template specialization 'tmain<int, char, 1, 0>' requested here}}
+ return tmain<int, char, 1, 0>(argc, argv);
+}
+
diff --git a/test/OpenMP/target_teams_distribute_default_messages.cpp b/test/OpenMP/target_teams_distribute_default_messages.cpp
new file mode 100644
index 000000000000..1bd106769784
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_default_messages.cpp
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo();
+
+int main(int argc, char **argv) {
+ #pragma omp target teams distribute default // expected-error {{expected '(' after 'default'}}
+ for (int i=0; i<200; i++) foo();
+ #pragma omp target teams distribute default ( // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i=0; i<200; i++) foo();
+ #pragma omp target teams distribute default () // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+ for (int i=0; i<200; i++) foo();
+ #pragma omp target teams distribute default (none // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i=0; i<200; i++) foo();
+ #pragma omp target teams distribute default (shared), default(shared) // expected-error {{directive '#pragma omp target teams distribute' cannot contain more than one 'default' clause}}
+ for (int i=0; i<200; i++) foo();
+ #pragma omp target teams distribute default (x) // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+ for (int i=0; i<200; i++) foo();
+
+ #pragma omp target teams distribute default(none)
+ for (int i=0; i<200; i++) ++argc; // expected-error {{variable 'argc' must have explicitly specified data sharing attributes}}
+
+ return 0;
+}
diff --git a/test/OpenMP/target_teams_distribute_defaultmap_messages.cpp b/test/OpenMP/target_teams_distribute_defaultmap_messages.cpp
new file mode 100644
index 000000000000..6608cee3de58
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_defaultmap_messages.cpp
@@ -0,0 +1,58 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo() {
+}
+
+template <class T, typename S, int N, int ST>
+T tmain(T argc, S **argv) {
+ int i;
+#pragma omp target teams distribute defaultmap // expected-error {{expected '(' after 'defaultmap'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute defaultmap ( // expected-error {{expected 'tofrom' in OpenMP clause 'defaultmap'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute defaultmap () // expected-error {{expected 'tofrom' in OpenMP clause 'defaultmap'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute defaultmap (tofrom // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-warning {{missing ':' after defaultmap modifier - ignoring}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute defaultmap (tofrom: // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute defaultmap (tofrom) // expected-warning {{missing ':' after defaultmap modifier - ignoring}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute defaultmap (tofrom scalar) // expected-warning {{missing ':' after defaultmap modifier - ignoring}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute defaultmap (tofrom, // expected-error {{expected ')'}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}} expected-warning {{missing ':' after defaultmap modifier - ignoring}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute defaultmap (scalar: // expected-error {{expected ')'}} expected-error {{expected 'tofrom' in OpenMP clause 'defaultmap'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute defaultmap (tofrom, scalar // expected-error {{expected ')'}} expected-warning {{missing ':' after defaultmap modifier - ignoring}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+ return argc;
+}
+
+int main(int argc, char **argv) {
+ int i;
+#pragma omp target teams distribute defaultmap // expected-error {{expected '(' after 'defaultmap'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute defaultmap ( // expected-error {{expected 'tofrom' in OpenMP clause 'defaultmap'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute defaultmap () // expected-error {{expected 'tofrom' in OpenMP clause 'defaultmap'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute defaultmap (tofrom // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-warning {{missing ':' after defaultmap modifier - ignoring}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute defaultmap (tofrom: // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute defaultmap (tofrom) // expected-warning {{missing ':' after defaultmap modifier - ignoring}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute defaultmap (tofrom scalar) // expected-warning {{missing ':' after defaultmap modifier - ignoring}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute defaultmap (tofrom, // expected-error {{expected ')'}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}} expected-warning {{missing ':' after defaultmap modifier - ignoring}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute defaultmap (scalar: // expected-error {{expected ')'}} expected-error {{expected 'tofrom' in OpenMP clause 'defaultmap'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute defaultmap (tofrom, scalar // expected-error {{expected ')'}} expected-warning {{missing ':' after defaultmap modifier - ignoring}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+ return tmain<int, char, 1, 0>(argc, argv);
+}
+
diff --git a/test/OpenMP/target_teams_distribute_depend_messages.cpp b/test/OpenMP/target_teams_distribute_depend_messages.cpp
new file mode 100644
index 000000000000..b3e733141070
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_depend_messages.cpp
@@ -0,0 +1,90 @@
+// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - -std=c++11 %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}}
+
+class vector {
+ public:
+ int operator[](int index) { return 0; }
+};
+
+int main(int argc, char **argv, char *env[]) {
+ vector vec;
+ typedef float V __attribute__((vector_size(16)));
+ V a;
+ auto arr = x; // expected-error {{use of undeclared identifier 'x'}}
+ int i;
+
+#pragma omp target teams distribute depend // expected-error {{expected '(' after 'depend'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute depend ( // expected-error {{expected 'in', 'out' or 'inout' in OpenMP clause 'depend'}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-warning {{missing ':' after dependency type - ignoring}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute depend () // expected-error {{expected 'in', 'out' or 'inout' in OpenMP clause 'depend'}} expected-warning {{missing ':' after dependency type - ignoring}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute depend (argc // expected-error {{expected 'in', 'out' or 'inout' in OpenMP clause 'depend'}} expected-warning {{missing ':' after dependency type - ignoring}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute depend (source : argc) // expected-error {{expected 'in', 'out' or 'inout' in OpenMP clause 'depend'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute depend (source) // expected-error {{expected expression}} expected-warning {{missing ':' after dependency type - ignoring}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute depend (in : argc)) // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute' are ignored}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute depend (out: ) // expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute depend (inout : foobool(argc)), depend (in, argc) // expected-error {{expected variable name, array element or array section}} expected-warning {{missing ':' after dependency type - ignoring}} expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute depend (out :S1) // expected-error {{'S1' does not refer to a value}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute depend(in : argv[1][1] = '2') // expected-error {{expected variable name, array element or array section}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute depend (in : vec[1]) // expected-error {{expected variable name, array element or array section}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute depend (in : argv[0])
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute depend (in : ) // expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute depend (in : main) // expected-error {{expected variable name, array element or array section}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute depend(in : a[0]) // expected-error{{expected variable name, array element or array section}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute depend (in : vec[1:2]) // expected-error {{ value is not an array or pointer}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute depend (in : argv[ // expected-error {{expected expression}} expected-error {{expected ']'}} expected-error {{expected ')'}} expected-note {{to match this '['}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute depend (in : argv[: // expected-error {{expected expression}} expected-error {{expected ']'}} expected-error {{expected ')'}} expected-note {{to match this '['}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute depend (in : argv[:] // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute depend (in : argv[argc: // expected-error {{expected expression}} expected-error {{expected ']'}} expected-error {{expected ')'}} expected-note {{to match this '['}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute depend (in : argv[argc:argc] // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute depend (in : argv[0:-1]) // expected-error {{section length is evaluated to a negative value -1}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute depend (in : argv[-1:0])
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute depend (in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute depend (in : argv[3:4:1]) // expected-error {{expected ']'}} expected-note {{to match this '['}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute depend(in:a[0:1]) // expected-error {{subscripted value is not an array or pointer}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute depend(in:argv[argv[:2]:1]) // expected-error {{OpenMP array section is not allowed here}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute depend(in:argv[0:][:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute depend(in:env[0:][:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is an array of unknown bound}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute depend(in : argv[ : argc][1 : argc - 1])
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute depend(in : arr[0])
+ for (i = 0; i < argc; ++i) foo();
+
+ return 0;
+}
diff --git a/test/OpenMP/target_teams_distribute_device_messages.cpp b/test/OpenMP/target_teams_distribute_device_messages.cpp
new file mode 100644
index 000000000000..b35d0befce21
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_device_messages.cpp
@@ -0,0 +1,40 @@
+// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -ferror-limit 100 -o - %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}}
+
+int main(int argc, char **argv) {
+ int i;
+#pragma omp target teams distribute device // expected-error {{expected '(' after 'device'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute device ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute device () // expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute device (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute device (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute' are ignored}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute device (argc > 0 ? argv[1] : argv[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute device (argc + argc)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute device (argc), device (argc+1) // expected-error {{directive '#pragma omp target teams distribute' cannot contain more than one 'device' clause}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute device (S1) // expected-error {{'S1' does not refer to a value}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute device (-2) // expected-error {{argument to 'device' clause must be a non-negative integer value}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute device (-10u)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute device (3.14) // expected-error {{expression must have integral or unscoped enumeration type, not 'double'}}
+ for (i = 0; i < argc; ++i) foo();
+
+ return 0;
+}
diff --git a/test/OpenMP/target_teams_distribute_dist_schedule_messages.cpp b/test/OpenMP/target_teams_distribute_dist_schedule_messages.cpp
new file mode 100644
index 000000000000..87708706a69e
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_dist_schedule_messages.cpp
@@ -0,0 +1,84 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}} expected-note {{declared here}}
+
+template <class T, int N>
+T tmain(T argc) {
+ T b = argc, c, d, e, f, g;
+ char ** argv;
+ static T a;
+// CHECK: static T a;
+
+#pragma omp target teams distribute dist_schedule // expected-error {{expected '(' after 'dist_schedule'}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target teams distribute dist_schedule ( // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target teams distribute dist_schedule () // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target teams distribute dist_schedule (static // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target teams distribute dist_schedule (static, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target teams distribute dist_schedule (argc)) // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}} expected-warning {{extra tokens at the end of '#pragma omp target teams distribute' are ignored}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target teams distribute dist_schedule (static, argc > 0 ? argv[1] : argv[2]) // expected-error2 {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target teams distribute dist_schedule (static), dist_schedule (static, 1) // expected-error {{directive '#pragma omp target teams distribute' cannot contain more than one 'dist_schedule' clause}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target teams distribute dist_schedule (static, S1) // expected-error {{'S1' does not refer to a value}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target teams distribute dist_schedule (static, argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error3 {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ for (int i = 0; i < 10; ++i) foo();
+
+ return T();
+}
+
+int main(int argc, char **argv) {
+#pragma omp target teams distribute dist_schedule // expected-error {{expected '(' after 'dist_schedule'}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target teams distribute dist_schedule ( // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target teams distribute dist_schedule () // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target teams distribute dist_schedule (static // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target teams distribute dist_schedule (static, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target teams distribute dist_schedule (argc)) // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}} expected-warning {{extra tokens at the end of '#pragma omp target teams distribute' are ignored}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target teams distribute dist_schedule (static, argc > 0 ? argv[1] : argv[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target teams distribute dist_schedule (static), dist_schedule (static, 1) // expected-error {{directive '#pragma omp target teams distribute' cannot contain more than one 'dist_schedule' clause}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target teams distribute dist_schedule (static, S1) // expected-error {{'S1' does not refer to a value}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target teams distribute dist_schedule (static, argv[1]=2) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 0; i < 10; ++i) foo();
+
+ return (tmain<int, 5>(argc) + tmain<char, 1>(argv[0][0])); // expected-note {{in instantiation of function template specialization 'tmain<int, 5>' requested here}} expected-note {{in instantiation of function template specialization 'tmain<char, 1>' requested here}}
+}
diff --git a/test/OpenMP/target_teams_distribute_firstprivate_messages.cpp b/test/OpenMP/target_teams_distribute_firstprivate_messages.cpp
new file mode 100644
index 000000000000..602e039802d1
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_firstprivate_messages.cpp
@@ -0,0 +1,132 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}} expected-note{{forward declaration of 'S1'}}
+extern S1 a;
+class S2 {
+ mutable int a;
+
+public:
+ S2() : a(0) {}
+ S2(const S2 &s2) : a(s2.a) {}
+ static float S2s;
+ static const float S2sc;
+};
+const float S2::S2sc = 0;
+const S2 b;
+const S2 ba[5];
+class S3 {
+ int a;
+ S3 &operator=(const S3 &s3);
+
+public:
+ S3() : a(0) {} // expected-note 2 {{candidate constructor not viable: requires 0 arguments, but 1 was provided}}
+ S3(S3 &s3) : a(s3.a) {} // expected-note 2 {{candidate constructor not viable: 1st argument ('const S3') would lose const qualifier}}
+};
+const S3 c;
+const S3 ca[5];
+extern const int f;
+class S4 {
+ int a;
+ S4();
+ S4(const S4 &s4);
+public:
+ S4(int v):a(v) { }
+};
+class S5 {
+ int a;
+ S5():a(0) {}
+ S5(const S5 &s5):a(s5.a) { }
+public:
+ S5(int v):a(v) { }
+};
+class S6 {
+ int a;
+public:
+ S6() : a(0) { }
+};
+
+S3 h;
+#pragma omp threadprivate(h) // expected-note {{defined as threadprivate or thread local}}
+
+int main(int argc, char **argv) {
+ const int d = 5;
+ const int da[5] = { 0 };
+ S4 e(4);
+ S5 g(5);
+ S6 p;
+ int i;
+ int &j = i;
+
+#pragma omp target teams distribute firstprivate // expected-error {{expected '(' after 'firstprivate'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute firstprivate ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute firstprivate () // expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute firstprivate (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute firstprivate (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute firstprivate (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute firstprivate (argc)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute firstprivate (S1) // expected-error {{'S1' does not refer to a value}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute firstprivate (a, b, c, d, f) // expected-error {{firstprivate variable with incomplete type 'S1'}} expected-error {{no matching constructor for initialization of 'S3'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute firstprivate (argv[1]) // expected-error {{expected variable name}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute firstprivate(ba)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute firstprivate(ca) // expected-error {{no matching constructor for initialization of 'S3'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute firstprivate(da)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute firstprivate(S2::S2s)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute firstprivate(S2::S2sc)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute firstprivate(h) // expected-error {{threadprivate or thread local variable cannot be firstprivate}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute private(i), firstprivate(i) // expected-error {{private variable cannot be firstprivate}} expected-note{{defined as private}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute firstprivate(i)
+ for (j = 0; j < argc; ++j) foo();
+
+#pragma omp target teams distribute firstprivate(i) // expected-note {{defined as firstprivate}}
+ for (i = 0; i < argc; ++i) foo(); // expected-error {{loop iteration variable in the associated loop of 'omp target teams distribute' directive may not be firstprivate, predetermined as private}}
+
+#pragma omp target teams distribute firstprivate(j)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute lastprivate(argc), firstprivate(argc) // OK
+ for (i = 0; i < argc; ++i) foo();
+
+ return 0;
+}
diff --git a/test/OpenMP/target_teams_distribute_if_messages.cpp b/test/OpenMP/target_teams_distribute_if_messages.cpp
new file mode 100644
index 000000000000..c9ef03a61ba0
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_if_messages.cpp
@@ -0,0 +1,150 @@
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}}
+
+template <class T, class S> // expected-note {{declared here}}
+int tmain(T argc, S **argv) {
+ int i;
+#pragma omp target teams distribute if // expected-error {{expected '(' after 'if'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute if ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute if () // expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute if (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute if (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute' are ignored}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute if (argc > 0 ? argv[1] : argv[2])
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute if (foobool(argc)), if (true) // expected-error {{directive '#pragma omp target teams distribute' cannot contain more than one 'if' clause}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute if (S) // expected-error {{'S' does not refer to a value}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute if (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute if (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute if(argc)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute if(target : // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute if(target : argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute if(target : argc)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute if(teams: argc) // expected-error {{directive name modifier 'teams' is not allowed for '#pragma omp target teams distribute'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute if(distribute: argc) // expected-error {{directive name modifier 'distribute' is not allowed for '#pragma omp target teams distribute'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute if(argc) if(teams: argc) // expected-note {{previous clause with directive name modifier specified here}} expected-error {{directive name modifier 'teams' is not allowed for '#pragma omp target teams distribute'}} expected-error {{no more 'if' clause is allowed}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute if(argc) if(distribute: argc) // expected-note {{previous clause with directive name modifier specified here}} expected-error {{directive name modifier 'distribute' is not allowed for '#pragma omp target teams distribute'}} expected-error {{no more 'if' clause is allowed}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute if(distribute: argc) if (for:argc) // expected-error {{directive name modifier 'for' is not allowed for '#pragma omp target teams distribute'}} expected-error {{directive name modifier 'distribute' is not allowed for '#pragma omp target teams distribute'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute if(target : argc) if (target :argc) // expected-error {{directive '#pragma omp target teams distribute' cannot contain more than one 'if' clause with 'target' name modifier}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute if(target : argc) if (argc) // expected-note {{previous clause with directive name modifier specified here}} expected-error {{no more 'if' clause is allowed}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute if(target : argc) if(distribute: argc) if (argc) // expected-note 2 {{previous clause with directive name modifier specified here}} expected-error {{directive name modifier 'distribute' is not allowed for '#pragma omp target teams distribute'}} expected-error {{expected one of directive name modifiers}}
+ for (i = 0; i < argc; ++i) foo();
+
+ return 0;
+}
+
+int main(int argc, char **argv) {
+ int i;
+#pragma omp target teams distribute if // expected-error {{expected '(' after 'if'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute if ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute if () // expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute if (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute if (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute' are ignored}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute if (argc > 0 ? argv[1] : argv[2])
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute if (foobool(argc)), if (true) // expected-error {{directive '#pragma omp target teams distribute' cannot contain more than one 'if' clause}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute if (S1) // expected-error {{'S1' does not refer to a value}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute if (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute if (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute if (1 0) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute if(if(tmain(argc, argv) // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute if(target : // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute if(target : argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute if(teams : argc) // expected-error {{directive name modifier 'teams' is not allowed for '#pragma omp target teams distribute'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute if(distribute : argc) // expected-error {{directive name modifier 'distribute' is not allowed for '#pragma omp target teams distribute'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute if(target : argc) if (distribute :argc) // expected-error {{directive name modifier 'distribute' is not allowed for '#pragma omp target teams distribute'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute if(target : argc) if (target :argc) // expected-error {{directive '#pragma omp target teams distribute' cannot contain more than one 'if' clause with 'target' name modifier}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute if(target : argc) if (argc) // expected-error {{no more 'if' clause is allowed}} expected-note {{previous clause with directive name modifier specified here}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute if(argc) if(teams: argc) // expected-note {{previous clause with directive name modifier specified here}} expected-error {{directive name modifier 'teams' is not allowed for '#pragma omp target teams distribute'}} expected-error {{no more 'if' clause is allowed}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute if(argc) if(distribute: argc) // expected-note {{previous clause with directive name modifier specified here}} expected-error {{directive name modifier 'distribute' is not allowed for '#pragma omp target teams distribute'}} expected-error {{no more 'if' clause is allowed}}
+ for (i = 0; i < argc; ++i) foo();
+
+ return tmain(argc, argv);
+}
diff --git a/test/OpenMP/target_teams_distribute_lastprivate_messages.cpp b/test/OpenMP/target_teams_distribute_lastprivate_messages.cpp
new file mode 100644
index 000000000000..8d594e94b09f
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_lastprivate_messages.cpp
@@ -0,0 +1,229 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note 2 {{declared here}} expected-note 2 {{forward declaration of 'S1'}}
+extern S1 a;
+class S2 {
+ mutable int a;
+
+public:
+ S2() : a(0) {}
+ S2(S2 &s2) : a(s2.a) {}
+ const S2 &operator =(const S2&) const;
+ S2 &operator =(const S2&);
+ static float S2s; // expected-note {{static data member is predetermined as shared}}
+ static const float S2sc;
+};
+const float S2::S2sc = 0; // expected-note {{static data member is predetermined as shared}}
+const S2 b;
+const S2 ba[5];
+class S3 {
+ int a;
+ S3 &operator=(const S3 &s3); // expected-note 2 {{implicitly declared private here}}
+
+public:
+ S3() : a(0) {}
+ S3(S3 &s3) : a(s3.a) {}
+};
+const S3 c; // expected-note {{global variable is predetermined as shared}}
+const S3 ca[5]; // expected-note {{global variable is predetermined as shared}}
+extern const int f; // expected-note {{global variable is predetermined as shared}}
+class S4 {
+ int a;
+ S4(); // expected-note 3 {{implicitly declared private here}}
+ S4(const S4 &s4);
+
+public:
+ S4(int v) : a(v) {}
+};
+class S5 {
+ int a;
+ S5() : a(0) {} // expected-note {{implicitly declared private here}}
+
+public:
+ S5(const S5 &s5) : a(s5.a) {}
+ S5(int v) : a(v) {}
+};
+class S6 {
+ int a;
+ S6() : a(0) {}
+
+public:
+ S6(const S6 &s6) : a(s6.a) {}
+ S6(int v) : a(v) {}
+};
+
+S3 h;
+#pragma omp threadprivate(h) // expected-note 2 {{defined as threadprivate or thread local}}
+
+template <class I, class C>
+int foomain(int argc, char **argv) {
+ I e(4);
+ I g(5);
+ int i;
+ int &j = i;
+#pragma omp target teams distribute lastprivate // expected-error {{expected '(' after 'lastprivate'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute lastprivate( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute lastprivate() // expected-error {{expected expression}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute lastprivate(argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute lastprivate(argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute lastprivate(argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute lastprivate(argc)
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute lastprivate(S1) // expected-error {{'S1' does not refer to a value}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute lastprivate(a, b) // expected-error {{lastprivate variable with incomplete type 'S1'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute lastprivate(argv[1]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute lastprivate(e, g) // expected-error 2 {{calling a private constructor of class 'S4'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute lastprivate(h) // expected-error {{threadprivate or thread local variable cannot be lastprivate}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ int v = 0;
+#pragma omp target teams distribute lastprivate(i)
+ for (int k = 0; k < argc; ++k) {
+ i = k;
+ v += i;
+ }
+
+#pragma omp target teams distribute lastprivate(j) private(i)
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute lastprivate(i)
+ for (int k = 0; k < argc; ++k) ++k;
+
+ return 0;
+}
+
+void bar(S4 a[2]) {
+#pragma omp target teams distribute lastprivate(a)
+ for (int i = 0; i < 2; ++i) foo();
+}
+
+namespace A {
+double x;
+#pragma omp threadprivate(x) // expected-note {{defined as threadprivate or thread local}}
+}
+namespace B {
+using A::x;
+}
+
+int main(int argc, char **argv) {
+ const int d = 5; // expected-note {{constant variable is predetermined as shared}}
+ const int da[5] = {0}; // expected-note {{constant variable is predetermined as shared}}
+ S4 e(4);
+ S5 g(5);
+ S3 m;
+ S6 n(2);
+ int i;
+ int &j = i;
+#pragma omp target teams distribute lastprivate // expected-error {{expected '(' after 'lastprivate'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute lastprivate( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute lastprivate() // expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute lastprivate(argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute lastprivate(argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute lastprivate(argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute lastprivate(argc)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute lastprivate(S1) // expected-error {{'S1' does not refer to a value}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be lastprivate}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute lastprivate(argv[1]) // expected-error {{expected variable name}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute lastprivate(2 * 2) // expected-error {{expected variable name}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute lastprivate(ba)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute lastprivate(ca) // expected-error {{shared variable cannot be lastprivate}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute lastprivate(da) // expected-error {{shared variable cannot be lastprivate}}
+ for (i = 0; i < argc; ++i) foo();
+
+ int xa;
+#pragma omp target teams distribute lastprivate(xa) // OK
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute lastprivate(S2::S2s) // expected-error {{shared variable cannot be lastprivate}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute lastprivate(S2::S2sc) // expected-error {{shared variable cannot be lastprivate}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute lastprivate(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute lastprivate(m) // expected-error {{'operator=' is a private member of 'S3'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute lastprivate(h) // expected-error {{threadprivate or thread local variable cannot be lastprivate}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute lastprivate(B::x) // expected-error {{threadprivate or thread local variable cannot be lastprivate}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute private(xa), lastprivate(xa) // expected-error {{private variable cannot be lastprivate}} expected-note {{defined as private}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute lastprivate(xa)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute lastprivate(j)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute firstprivate(m) lastprivate(m) // expected-error {{'operator=' is a private member of 'S3'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute lastprivate(n) firstprivate(n) // OK
+ for (i = 0; i < argc; ++i) foo();
+
+ static int si;
+#pragma omp target teams distribute lastprivate(si) // OK
+ for (i = 0; i < argc; ++i) si = i + 1;
+
+ return foomain<S4, S5>(argc, argv); // expected-note {{in instantiation of function template specialization 'foomain<S4, S5>' requested here}}
+}
diff --git a/test/OpenMP/target_teams_distribute_loop_messages.cpp b/test/OpenMP/target_teams_distribute_loop_messages.cpp
new file mode 100644
index 000000000000..cb243a66b1ae
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_loop_messages.cpp
@@ -0,0 +1,620 @@
+// RUN: %clang_cc1 -fsyntax-only -fopenmp -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s
+
+class S {
+ int a;
+ S() : a(0) {}
+
+public:
+ S(int v) : a(v) {}
+ S(const S &s) : a(s.a) {}
+};
+
+static int sii;
+// expected-note@+1 {{defined as threadprivate or thread local}}
+#pragma omp threadprivate(sii)
+static int globalii;
+
+int test_iteration_spaces() {
+ const int N = 100;
+ float a[N], b[N], c[N];
+ int ii, jj, kk;
+ float fii;
+ double dii;
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; i += 1) {
+ c[i] = a[i] + b[i];
+ }
+#pragma omp target teams distribute
+ for (char i = 0; i < 10; i++) {
+ c[i] = a[i] + b[i];
+ }
+#pragma omp target teams distribute
+ for (char i = 0; i < 10; i += '\1') {
+ c[i] = a[i] + b[i];
+ }
+#pragma omp target teams distribute
+ for (long long i = 0; i < 10; i++) {
+ c[i] = a[i] + b[i];
+ }
+#pragma omp target teams distribute
+// expected-error@+1 {{expression must have integral or unscoped enumeration type, not 'double'}}
+ for (long long i = 0; i < 10; i += 1.5) {
+ c[i] = a[i] + b[i];
+ }
+#pragma omp target teams distribute
+ for (long long i = 0; i < 'z'; i += 1u) {
+ c[i] = a[i] + b[i];
+ }
+#pragma omp target teams distribute
+// expected-error@+1 {{variable must be of integer or random access iterator type}}
+ for (float fi = 0; fi < 10.0; fi++) {
+ c[(int)fi] = a[(int)fi] + b[(int)fi];
+ }
+#pragma omp target teams distribute
+// expected-error@+1 {{variable must be of integer or random access iterator type}}
+ for (double fi = 0; fi < 10.0; fi++) {
+ c[(int)fi] = a[(int)fi] + b[(int)fi];
+ }
+#pragma omp target teams distribute
+// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (int &ref = ii; ref < 10; ref++) {
+ }
+#pragma omp target teams distribute
+// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (int i; i < 10; i++)
+ c[i] = a[i];
+
+#pragma omp target teams distribute
+// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (int i = 0, j = 0; i < 10; ++i)
+ c[i] = a[i];
+
+#pragma omp target teams distribute
+// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (; ii < 10; ++ii)
+ c[ii] = a[ii];
+
+#pragma omp target teams distribute
+// expected-warning@+2 {{expression result unused}}
+// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (ii + 1; ii < 10; ++ii)
+ c[ii] = a[ii];
+
+#pragma omp target teams distribute
+// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (c[ii] = 0; ii < 10; ++ii)
+ c[ii] = a[ii];
+
+#pragma omp target teams distribute
+// Ok to skip parenthesises.
+ for (((ii)) = 0; ii < 10; ++ii)
+ c[ii] = a[ii];
+
+#pragma omp target teams distribute
+// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
+ for (int i = 0; i; i++)
+ c[i] = a[i];
+
+#pragma omp target teams distribute
+// expected-error@+2 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'i'}}
+ for (int i = 0; jj < kk; ii++)
+ c[i] = a[i];
+
+#pragma omp target teams distribute
+// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
+ for (int i = 0; !!i; i++)
+ c[i] = a[i];
+
+#pragma omp target teams distribute
+// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
+ for (int i = 0; i != 1; i++)
+ c[i] = a[i];
+
+#pragma omp target teams distribute
+// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
+ for (int i = 0;; i++)
+ c[i] = a[i];
+
+// Ok.
+#pragma omp target teams distribute
+ for (int i = 11; i > 10; i--)
+ c[i] = a[i];
+
+// Ok.
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i)
+ c[i] = a[i];
+
+// Ok.
+#pragma omp target teams distribute
+ for (ii = 0; ii < 10; ++ii)
+ c[ii] = a[ii];
+
+#pragma omp target teams distribute
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+ for (ii = 0; ii < 10; ++jj)
+ c[ii] = a[jj];
+
+#pragma omp target teams distribute
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+ for (ii = 0; ii < 10; ++++ii)
+ c[ii] = a[ii];
+
+// Ok but undefined behavior (in general, cannot check that incr
+// is really loop-invariant).
+#pragma omp target teams distribute
+ for (ii = 0; ii < 10; ii = ii + ii)
+ c[ii] = a[ii];
+
+#pragma omp target teams distribute
+// expected-error@+1 {{expression must have integral or unscoped enumeration type, not 'float'}}
+ for (ii = 0; ii < 10; ii = ii + 1.0f)
+ c[ii] = a[ii];
+
+// Ok - step was converted to integer type.
+#pragma omp target teams distribute
+ for (ii = 0; ii < 10; ii = ii + (int)1.1f)
+ c[ii] = a[ii];
+
+#pragma omp target teams distribute
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+ for (ii = 0; ii < 10; jj = ii + 2)
+ c[ii] = a[ii];
+
+#pragma omp target teams distribute
+// expected-warning@+2 {{relational comparison result unused}}
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+ for (ii = 0; ii<10; jj> kk + 2)
+ c[ii] = a[ii];
+
+#pragma omp target teams distribute
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+ for (ii = 0; ii < 10;)
+ c[ii] = a[ii];
+
+#pragma omp target teams distribute
+// expected-warning@+2 {{expression result unused}}
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+ for (ii = 0; ii < 10; !ii)
+ c[ii] = a[ii];
+
+#pragma omp target teams distribute
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+ for (ii = 0; ii < 10; ii ? ++ii : ++jj)
+ c[ii] = a[ii];
+
+#pragma omp target teams distribute
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+ for (ii = 0; ii < 10; ii = ii < 10)
+ c[ii] = a[ii];
+
+#pragma omp target teams distribute
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}}
+ for (ii = 0; ii < 10; ii = ii + 0)
+ c[ii] = a[ii];
+
+#pragma omp target teams distribute
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}}
+ for (ii = 0; ii < 10; ii = ii + (int)(0.8 - 0.45))
+ c[ii] = a[ii];
+
+#pragma omp target teams distribute
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}}
+ for (ii = 0; (ii) < 10; ii -= 25)
+ c[ii] = a[ii];
+
+#pragma omp target teams distribute
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}}
+ for (ii = 0; (ii < 10); ii -= 0)
+ c[ii] = a[ii];
+
+#pragma omp target teams distribute
+// expected-note@+2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+1 {{increment expression must cause 'ii' to decrease on each iteration of OpenMP for loop}}
+ for (ii = 0; ii > 10; (ii += 0))
+ c[ii] = a[ii];
+
+#pragma omp target teams distribute
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}}
+ for (ii = 0; ii < 10; (ii) = (1 - 1) + (ii))
+ c[ii] = a[ii];
+
+#pragma omp target teams distribute
+// expected-note@+2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+1 {{increment expression must cause 'ii' to decrease on each iteration of OpenMP for loop}}
+ for ((ii = 0); ii > 10; (ii -= 0))
+ c[ii] = a[ii];
+
+#pragma omp target teams distribute
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}}
+ for (ii = 0; (ii < 10); (ii -= 0))
+ c[ii] = a[ii];
+
+#pragma omp target teams distribute firstprivate(ii) // expected-note {{defined as firstprivate}}
+// expected-error@+1 {{loop iteration variable in the associated loop of 'omp target teams distribute' directive may not be firstprivate, predetermined as private}}
+ for (ii = 0; ii < 10; ii++)
+ c[ii] = a[ii];
+
+#pragma omp target teams distribute private(ii)
+// OK
+ for (ii = 0; ii < 10; ii++)
+ c[ii] = a[ii];
+
+#pragma omp target teams distribute lastprivate(ii)
+// OK
+ for (ii = 0; ii < 10; ii++)
+ c[ii] = a[ii];
+
+#pragma omp target teams distribute
+// expected-error@+1 {{loop iteration variable in the associated loop of 'omp target teams distribute' directive may not be threadprivate or thread local, predetermined as private}}
+ for (sii = 0; sii < 10; sii++)
+ c[sii] = a[sii];
+
+ {
+#pragma omp target teams distribute collapse(2)
+ for (ii = 0; ii < 10; ii += 1)
+ for (globalii = 0; globalii < 10; globalii += 1)
+ c[globalii] += a[globalii] + ii;
+ }
+
+#pragma omp target teams distribute
+// expected-error@+1 {{statement after '#pragma omp target teams distribute' must be a for loop}}
+ for (auto &item : a) {
+ item = item + 1;
+ }
+
+#pragma omp target teams distribute
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'i' to increase on each iteration of OpenMP for loop}}
+ for (unsigned i = 9; i < 10; i--) {
+ c[i] = a[i] + b[i];
+ }
+
+ int(*lb)[4] = nullptr;
+#pragma omp target teams distribute
+ for (int(*p)[4] = lb; p < lb + 8; ++p) {
+ }
+
+#pragma omp target teams distribute
+// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (int a{0}; a < 10; ++a) {
+ }
+
+ return 0;
+}
+
+// Iterators allowed in openmp for-loops.
+namespace std {
+struct random_access_iterator_tag {};
+template <class Iter>
+struct iterator_traits {
+ typedef typename Iter::difference_type difference_type;
+ typedef typename Iter::iterator_category iterator_category;
+};
+template <class Iter>
+typename iterator_traits<Iter>::difference_type
+distance(Iter first, Iter last) { return first - last; }
+}
+class Iter0 {
+public:
+ Iter0() {}
+ Iter0(const Iter0 &) {}
+ Iter0 operator++() { return *this; }
+ Iter0 operator--() { return *this; }
+ bool operator<(Iter0 a) { return true; }
+};
+// expected-note@+2 {{candidate function not viable: no known conversion from 'GoodIter' to 'Iter0' for 1st argument}}
+// expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'Iter0' for 1st argument}}
+int operator-(Iter0 a, Iter0 b) { return 0; }
+class Iter1 {
+public:
+ Iter1(float f = 0.0f, double d = 0.0) {}
+ Iter1(const Iter1 &) {}
+ Iter1 operator++() { return *this; }
+ Iter1 operator--() { return *this; }
+ bool operator<(Iter1 a) { return true; }
+ bool operator>=(Iter1 a) { return false; }
+};
+class GoodIter {
+public:
+ GoodIter() {}
+ GoodIter(const GoodIter &) {}
+ GoodIter(int fst, int snd) {}
+ GoodIter &operator=(const GoodIter &that) { return *this; }
+ GoodIter &operator=(const Iter0 &that) { return *this; }
+ GoodIter &operator+=(int x) { return *this; }
+ explicit GoodIter(void *) {}
+ GoodIter operator++() { return *this; }
+ GoodIter operator--() { return *this; }
+ bool operator!() { return true; }
+ bool operator<(GoodIter a) { return true; }
+ bool operator<=(GoodIter a) { return true; }
+ bool operator>=(GoodIter a) { return false; }
+ typedef int difference_type;
+ typedef std::random_access_iterator_tag iterator_category;
+};
+// expected-note@+2 {{candidate function not viable: no known conversion from 'const Iter0' to 'GoodIter' for 2nd argument}}
+// expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'GoodIter' for 1st argument}}
+int operator-(GoodIter a, GoodIter b) { return 0; }
+// expected-note@+1 3 {{candidate function not viable: requires single argument 'a', but 2 arguments were provided}}
+GoodIter operator-(GoodIter a) { return a; }
+// expected-note@+2 {{candidate function not viable: no known conversion from 'const Iter0' to 'int' for 2nd argument}}
+// expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'GoodIter' for 1st argument}}
+GoodIter operator-(GoodIter a, int v) { return GoodIter(); }
+// expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter0' to 'GoodIter' for 1st argument}}
+GoodIter operator+(GoodIter a, int v) { return GoodIter(); }
+// expected-note@+2 {{candidate function not viable: no known conversion from 'GoodIter' to 'int' for 1st argument}}
+// expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'int' for 1st argument}}
+GoodIter operator-(int v, GoodIter a) { return GoodIter(); }
+// expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter0' to 'int' for 1st argument}}
+GoodIter operator+(int v, GoodIter a) { return GoodIter(); }
+
+int test_with_random_access_iterator() {
+ GoodIter begin, end;
+ Iter0 begin0, end0;
+#pragma omp target teams distribute
+ for (GoodIter I = begin; I < end; ++I)
+ ++I;
+#pragma omp target teams distribute
+// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (GoodIter &I = begin; I < end; ++I)
+ ++I;
+#pragma omp target teams distribute
+ for (GoodIter I = begin; I >= end; --I)
+ ++I;
+#pragma omp target teams distribute
+// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (GoodIter I(begin); I < end; ++I)
+ ++I;
+#pragma omp target teams distribute
+// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (GoodIter I(nullptr); I < end; ++I)
+ ++I;
+#pragma omp target teams distribute
+// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (GoodIter I(0); I < end; ++I)
+ ++I;
+#pragma omp target teams distribute
+// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (GoodIter I(1, 2); I < end; ++I)
+ ++I;
+#pragma omp target teams distribute
+ for (begin = GoodIter(0); begin < end; ++begin)
+ ++begin;
+#pragma omp target teams distribute
+// expected-error@+2 {{invalid operands to binary expression ('GoodIter' and 'const Iter0')}}
+// expected-error@+1 {{could not calculate number of iterations calling 'operator-' with upper and lower loop bounds}}
+ for (begin = begin0; begin < end; ++begin)
+ ++begin;
+#pragma omp target teams distribute
+// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (++begin; begin < end; ++begin)
+ ++begin;
+#pragma omp target teams distribute
+ for (begin = end; begin < end; ++begin)
+ ++begin;
+#pragma omp target teams distribute
+// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'I'}}
+ for (GoodIter I = begin; I - I; ++I)
+ ++I;
+#pragma omp target teams distribute
+// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'I'}}
+ for (GoodIter I = begin; begin < end; ++I)
+ ++I;
+#pragma omp target teams distribute
+// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'I'}}
+ for (GoodIter I = begin; !I; ++I)
+ ++I;
+#pragma omp target teams distribute
+// expected-note@+2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+1 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}}
+ for (GoodIter I = begin; I >= end; I = I + 1)
+ ++I;
+#pragma omp target teams distribute
+ for (GoodIter I = begin; I >= end; I = I - 1)
+ ++I;
+#pragma omp target teams distribute
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'I'}}
+ for (GoodIter I = begin; I >= end; I = -I)
+ ++I;
+#pragma omp target teams distribute
+// expected-note@+2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+1 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}}
+ for (GoodIter I = begin; I >= end; I = 2 + I)
+ ++I;
+#pragma omp target teams distribute
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'I'}}
+ for (GoodIter I = begin; I >= end; I = 2 - I)
+ ++I;
+#pragma omp target teams distribute
+// expected-error@+1 {{invalid operands to binary expression ('Iter0' and 'int')}}
+ for (Iter0 I = begin0; I < end0; ++I)
+ ++I;
+#pragma omp target teams distribute
+// Initializer is constructor without params.
+// expected-error@+2 {{invalid operands to binary expression ('Iter0' and 'int')}}
+// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (Iter0 I; I < end0; ++I)
+ ++I;
+ Iter1 begin1, end1;
+#pragma omp target teams distribute
+// expected-error@+2 {{invalid operands to binary expression ('Iter1' and 'Iter1')}}
+// expected-error@+1 {{could not calculate number of iterations calling 'operator-' with upper and lower loop bounds}}
+ for (Iter1 I = begin1; I < end1; ++I)
+ ++I;
+#pragma omp target teams distribute
+// expected-note@+2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+1 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}}
+ for (Iter1 I = begin1; I >= end1; ++I)
+ ++I;
+#pragma omp target teams distribute
+// expected-error@+4 {{invalid operands to binary expression ('Iter1' and 'float')}}
+// expected-error@+3 {{could not calculate number of iterations calling 'operator-' with upper and lower loop bounds}}
+// Initializer is constructor with all default params.
+// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (Iter1 I; I < end1; ++I) {
+ }
+ return 0;
+}
+
+template <typename IT, int ST>
+class TC {
+public:
+ int dotest_lt(IT begin, IT end) {
+#pragma omp target teams distribute
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'I' to increase on each iteration of OpenMP for loop}}
+ for (IT I = begin; I < end; I = I + ST) {
+ ++I;
+ }
+#pragma omp target teams distribute
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'I' to increase on each iteration of OpenMP for loop}}
+ for (IT I = begin; I <= end; I += ST) {
+ ++I;
+ }
+#pragma omp target teams distribute
+ for (IT I = begin; I < end; ++I) {
+ ++I;
+ }
+ }
+
+ static IT step() {
+ return IT(ST);
+ }
+};
+template <typename IT, int ST = 0>
+int dotest_gt(IT begin, IT end) {
+#pragma omp target teams distribute
+// expected-note@+2 2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+1 2 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}}
+ for (IT I = begin; I >= end; I = I + ST) {
+ ++I;
+ }
+#pragma omp target teams distribute
+// expected-note@+2 2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+1 2 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}}
+ for (IT I = begin; I >= end; I += ST) {
+ ++I;
+ }
+
+#pragma omp target teams distribute
+// expected-note@+2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+1 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}}
+ for (IT I = begin; I >= end; ++I) {
+ ++I;
+ }
+
+#pragma omp target teams distribute
+ for (IT I = begin; I < end; I += TC<int, ST>::step()) {
+ ++I;
+ }
+}
+
+void test_with_template() {
+ GoodIter begin, end;
+ TC<GoodIter, 100> t1;
+ TC<GoodIter, -100> t2;
+ t1.dotest_lt(begin, end);
+ t2.dotest_lt(begin, end); // expected-note {{in instantiation of member function 'TC<GoodIter, -100>::dotest_lt' requested here}}
+ dotest_gt(begin, end); // expected-note {{in instantiation of function template specialization 'dotest_gt<GoodIter, 0>' requested here}}
+ dotest_gt<unsigned, -10>(0, 100); // expected-note {{in instantiation of function template specialization 'dotest_gt<unsigned int, -10>' requested here}}
+}
+
+void test_loop_break() {
+ const int N = 100;
+ float a[N], b[N], c[N];
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; i++) {
+ c[i] = a[i] + b[i];
+ for (int j = 0; j < 10; ++j) {
+ if (a[i] > b[j])
+ break; // OK in nested loop
+ }
+ switch (i) {
+ case 1:
+ b[i]++;
+ break;
+ default:
+ break;
+ }
+ if (c[i] > 10)
+ break; // expected-error {{'break' statement cannot be used in OpenMP for loop}}
+
+ if (c[i] > 11)
+ break; // expected-error {{'break' statement cannot be used in OpenMP for loop}}
+ }
+
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; i++) {
+ for (int j = 0; j < 10; j++) {
+ c[i] = a[i] + b[i];
+ if (c[i] > 10) {
+ if (c[i] < 20) {
+ break; // OK
+ }
+ }
+ }
+ }
+}
+
+void test_loop_eh() {
+ const int N = 100;
+ float a[N], b[N], c[N];
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; i++) {
+ c[i] = a[i] + b[i];
+ try { // OK
+ for (int j = 0; j < 10; ++j) {
+ if (a[i] > b[j])
+ throw a[i]; // OK
+ }
+ throw a[i]; // OK
+ } catch (float f) {
+ if (f > 0.1)
+ throw a[i]; // OK
+ return; // expected-error {{cannot return from OpenMP region}}
+ }
+ switch (i) {
+ case 1:
+ b[i]++;
+ break;
+ default:
+ break;
+ }
+ for (int j = 0; j < 10; j++) {
+ if (c[i] > 10)
+ throw c[i]; // OK
+ }
+ }
+ if (c[9] > 10)
+ throw c[9]; // OK
+
+#pragma omp target teams distribute
+ for (int i = 0; i < 10; ++i) {
+ struct S {
+ void g() { throw 0; }
+ };
+ }
+}
+
+void test_loop_firstprivate_lastprivate() {
+ S s(4);
+#pragma omp target teams distribute lastprivate(s) firstprivate(s)
+ for (int i = 0; i < 16; ++i)
+ ;
+}
+
+void test_ordered() {
+#pragma omp target teams distribute ordered // expected-error {{unexpected OpenMP clause 'ordered' in directive '#pragma omp target teams distribute'}}
+ for (int i = 0; i < 16; ++i)
+ ;
+}
+
diff --git a/test/OpenMP/target_teams_distribute_map_messages.cpp b/test/OpenMP/target_teams_distribute_map_messages.cpp
new file mode 100644
index 000000000000..5d815de85b04
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_map_messages.cpp
@@ -0,0 +1,281 @@
+// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note 2 {{declared here}}
+extern S1 a;
+class S2 {
+ mutable int a;
+public:
+ S2():a(0) { }
+ S2(S2 &s2):a(s2.a) { }
+ static float S2s; // expected-note 4 {{mappable type cannot contain static members}}
+ static const float S2sc; // expected-note 4 {{mappable type cannot contain static members}}
+};
+const float S2::S2sc = 0;
+const S2 b;
+const S2 ba[5];
+class S3 {
+ int a;
+public:
+ S3():a(0) { }
+ S3(S3 &s3):a(s3.a) { }
+};
+const S3 c;
+const S3 ca[5];
+extern const int f;
+class S4 {
+ int a;
+ S4();
+ S4(const S4 &s4);
+public:
+ S4(int v):a(v) { }
+};
+class S5 {
+ int a;
+ S5():a(0) {}
+ S5(const S5 &s5):a(s5.a) { }
+public:
+ S5(int v):a(v) { }
+};
+
+S3 h;
+#pragma omp threadprivate(h) // expected-note 2 {{defined as threadprivate or thread local}}
+
+typedef int from;
+
+template <typename T, int I> // expected-note {{declared here}}
+T tmain(T argc) {
+ const T d = 5;
+ const T da[5] = { 0 };
+ S4 e(4);
+ S5 g(5);
+ T i, t[20];
+ T &j = i;
+ T *k = &j;
+ T x;
+ T y;
+ T to, tofrom, always;
+ const T (&l)[5] = da;
+
+
+#pragma omp target teams distribute map // expected-error {{expected '(' after 'map'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map( // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map() // expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(alloc) // expected-error {{use of undeclared identifier 'alloc'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(to argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected ',' or ')' in 'map' clause}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(to:) // expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(from: argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(x: y) // expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(l[-1:]) // expected-error 2 {{array section must be a subset of the original array}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(l[:-1]) // expected-error 2 {{section length is evaluated to a negative value -1}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(x)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(tofrom: t[:I])
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(T: a) // expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}} expected-error {{incomplete type 'S1' where a complete type is required}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(T) // expected-error {{'T' does not refer to a value}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(I) // expected-error 2 {{expected expression containing only member accesses and/or array sections based on named variables}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(S2::S2s)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(S2::S2sc)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(x)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(to: x)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(to: to)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(to)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(to, x)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(to x) // expected-error {{expected ',' or ')' in 'map' clause}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(tofrom: argc > 0 ? x : y) // expected-error 2 {{expected expression containing only member accesses and/or array sections based on named variables}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(argc)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(S1) // expected-error {{'S1' does not refer to a value}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(a, b, c, d, f) // expected-error {{incomplete type 'S1' where a complete type is required}} expected-error 2 {{type 'S2' is not mappable to target}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(ba) // expected-error 2 {{type 'S2' is not mappable to target}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(ca)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(da)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(S2::S2s)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(S2::S2sc)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(e, g)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(h) // expected-error {{threadprivate variables are not allowed in 'map' clause}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(k), map(k) // expected-error 2 {{variable already marked as mapped in current construct}} expected-note 2 {{used here}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(k), map(k[:5]) // expected-error 2 {{pointer cannot be mapped along with a section derived from itself}} expected-note 2 {{used here}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(da)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(da[:4])
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target data map(k, j, l) // expected-note 2 {{used here}}
+#pragma omp target teams distribute map(k[:4]) // expected-error 2 {{pointer cannot be mapped along with a section derived from itself}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(j)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(l) map(l[:5]) // expected-error 2 {{variable already marked as mapped in current construct}} expected-note 2 {{used here}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target data map(k[:4], j, l[:5]) // expected-note 2 {{used here}}
+{
+#pragma omp target teams distribute map(k) // expected-error 2 {{pointer cannot be mapped along with a section derived from itself}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(j)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(l)
+ for (i = 0; i < argc; ++i) foo();
+}
+
+#pragma omp target teams distribute map(always, tofrom: x)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(always: x) // expected-error {{missing map type}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always'}} expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(always, tofrom: always, tofrom, x)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(tofrom j) // expected-error {{expected ',' or ')' in 'map' clause}}
+ for (i = 0; i < argc; ++i) foo();
+
+ return 0;
+}
+
+int main(int argc, char **argv) {
+ const int d = 5;
+ const int da[5] = { 0 };
+ S4 e(4);
+ S5 g(5);
+ int i;
+ int &j = i;
+ int *k = &j;
+ int x;
+ int y;
+ int to, tofrom, always;
+ const int (&l)[5] = da;
+
+#pragma omp target teams distribute map // expected-error {{expected '(' after 'map'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map( // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map() // expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(alloc) // expected-error {{use of undeclared identifier 'alloc'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(to argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected ',' or ')' in 'map' clause}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(to:) // expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(from: argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(x: y) // expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(l[-1:]) // expected-error {{array section must be a subset of the original array}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(l[:-1]) // expected-error {{section length is evaluated to a negative value -1}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(x)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(to: x)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(to: to)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(to)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(to, x)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(to x) // expected-error {{expected ',' or ')' in 'map' clause}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(tofrom: argc > 0 ? argv[1] : argv[2]) // expected-error {{expected expression containing only member accesses and/or array sections based on named variables}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(argc)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(S1) // expected-error {{'S1' does not refer to a value}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(a, b, c, d, f) // expected-error {{incomplete type 'S1' where a complete type is required}} expected-error 2 {{type 'S2' is not mappable to target}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(argv[1])
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(ba) // expected-error 2 {{type 'S2' is not mappable to target}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(ca)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(da)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(S2::S2s)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(S2::S2sc)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(e, g)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(h) // expected-error {{threadprivate variables are not allowed in 'map' clause}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(k), map(k) // expected-error {{variable already marked as mapped in current construct}} expected-note {{used here}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(k), map(k[:5]) // expected-error {{pointer cannot be mapped along with a section derived from itself}} expected-note {{used here}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(da)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(da[:4])
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target data map(k, j, l) // expected-note {{used here}}
+#pragma omp target teams distribute map(k[:4]) // expected-error {{pointer cannot be mapped along with a section derived from itself}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(j)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(l) map(l[:5]) // expected-error 1 {{variable already marked as mapped in current construct}} expected-note 1 {{used here}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target data map(k[:4], j, l[:5]) // expected-note {{used here}}
+{
+#pragma omp target teams distribute map(k) // expected-error {{pointer cannot be mapped along with a section derived from itself}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(j)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(l)
+ for (i = 0; i < argc; ++i) foo();
+}
+
+#pragma omp target teams distribute map(always, tofrom: x)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(always: x) // expected-error {{missing map type}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always'}} expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(always, tofrom: always, tofrom, x)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute map(tofrom j) // expected-error {{expected ',' or ')' in 'map' clause}}
+ for (i = 0; i < argc; ++i) foo();
+
+ return tmain<int, 3>(argc)+tmain<from, 4>(argc); // expected-note {{in instantiation of function template specialization 'tmain<int, 3>' requested here}} expected-note {{in instantiation of function template specialization 'tmain<int, 4>' requested here}}
+}
+
diff --git a/test/OpenMP/target_teams_distribute_messages.cpp b/test/OpenMP/target_teams_distribute_messages.cpp
new file mode 100644
index 000000000000..91f3c76a4a09
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_messages.cpp
@@ -0,0 +1,92 @@
+// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -std=c++11 -o - %s
+
+void foo() {
+}
+
+static int pvt;
+#pragma omp threadprivate(pvt)
+
+#pragma omp target teams distribute // expected-error {{unexpected OpenMP directive '#pragma omp target teams distribute'}}
+
+int main(int argc, char **argv) {
+#pragma omp target teams distribute { // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute' are ignored}}
+ for (int i = 0; i < argc; ++i)
+ foo();
+#pragma omp target teams distribute ( // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute' are ignored}}
+ for (int i = 0; i < argc; ++i)
+ foo();
+#pragma omp target teams distribute[ // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute' are ignored}}
+ for (int i = 0; i < argc; ++i)
+ foo();
+#pragma omp target teams distribute] // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute' are ignored}}
+ for (int i = 0; i < argc; ++i)
+ foo();
+#pragma omp target teams distribute) // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute' are ignored}}
+ for (int i = 0; i < argc; ++i)
+ foo();
+#pragma omp target teams distribute } // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute' are ignored}}
+ for (int i = 0; i < argc; ++i)
+ foo();
+#pragma omp target teams distribute
+ for (int i = 0; i < argc; ++i)
+ foo();
+// expected-warning@+1 {{extra tokens at the end of '#pragma omp target teams distribute' are ignored}}
+#pragma omp target teams distribute unknown()
+ for (int i = 0; i < argc; ++i)
+ foo();
+L1:
+ for (int i = 0; i < argc; ++i)
+ foo();
+#pragma omp target teams distribute
+ for (int i = 0; i < argc; ++i)
+ foo();
+#pragma omp target teams distribute
+ for (int i = 0; i < argc; ++i) {
+ goto L1; // expected-error {{use of undeclared label 'L1'}}
+ argc++;
+ }
+
+ for (int i = 0; i < 10; ++i) {
+ switch (argc) {
+ case (0):
+#pragma omp target teams distribute
+ for (int i = 0; i < argc; ++i) {
+ foo();
+ break; // expected-error {{'break' statement cannot be used in OpenMP for loop}}
+ continue;
+ }
+ default:
+ break;
+ }
+ }
+#pragma omp target teams distribute default(none)
+ for (int i = 0; i < 10; ++i)
+ ++argc; // expected-error {{variable 'argc' must have explicitly specified data sharing attributes}}
+
+ goto L2; // expected-error {{use of undeclared label 'L2'}}
+#pragma omp target teams distribute
+ for (int i = 0; i < argc; ++i)
+ L2:
+ foo();
+#pragma omp target teams distribute
+ for (int i = 0; i < argc; ++i) {
+ return 1; // expected-error {{cannot return from OpenMP region}}
+ }
+
+ [[]] // expected-error {{an attribute list cannot appear here}}
+#pragma omp target teams distribute
+ for (int n = 0; n < 100; ++n) {
+ }
+
+#pragma omp target teams distribute copyin(pvt) // expected-error {{unexpected OpenMP clause 'copyin' in directive '#pragma omp target teams distribute'}}
+ for (int n = 0; n < 100; ++n) {}
+
+ return 0;
+}
+
+void test_ordered() {
+#pragma omp target teams distribute ordered // expected-error {{unexpected OpenMP clause 'ordered' in directive '#pragma omp target teams distribute'}}
+ for (int i = 0; i < 16; ++i)
+ ;
+}
+
diff --git a/test/OpenMP/target_teams_distribute_misc_messages.c b/test/OpenMP/target_teams_distribute_misc_messages.c
new file mode 100644
index 000000000000..bf4df0894ad3
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_misc_messages.c
@@ -0,0 +1,312 @@
+// RUN: %clang_cc1 -fsyntax-only -fopenmp -verify %s
+
+// expected-error@+1 {{unexpected OpenMP directive '#pragma omp target teams distribute'}}
+#pragma omp target teams distribute
+
+// expected-error@+1 {{unexpected OpenMP directive '#pragma omp target teams distribute'}}
+#pragma omp target teams distribute foo
+
+void test_no_clause() {
+ int i;
+#pragma omp target teams distribute
+ for (i = 0; i < 16; ++i)
+ ;
+
+// expected-error@+2 {{statement after '#pragma omp target teams distribute' must be a for loop}}
+#pragma omp target teams distribute
+ ++i;
+}
+
+void test_branch_protected_scope() {
+ int i = 0;
+L1:
+ ++i;
+
+ int x[24];
+
+#pragma omp target teams distribute
+ for (i = 0; i < 16; ++i) {
+ if (i == 5)
+ goto L1; // expected-error {{use of undeclared label 'L1'}}
+ else if (i == 6)
+ return; // expected-error {{cannot return from OpenMP region}}
+ else if (i == 7)
+ goto L2;
+ else if (i == 8) {
+ L2:
+ x[i]++;
+ }
+ }
+
+ if (x[0] == 0)
+ goto L2; // expected-error {{use of undeclared label 'L2'}}
+ else if (x[1] == 1)
+ goto L1;
+}
+
+void test_invalid_clause() {
+ int i;
+// expected-warning@+1 {{extra tokens at the end of '#pragma omp target teams distribute' are ignored}}
+#pragma omp target teams distribute foo bar
+ for (i = 0; i < 16; ++i)
+ ;
+}
+
+void test_non_identifiers() {
+ int i, x;
+
+// expected-warning@+1 {{extra tokens at the end of '#pragma omp target teams distribute' are ignored}}
+#pragma omp target teams distribute;
+ for (i = 0; i < 16; ++i)
+ ;
+
+// expected-warning@+1 {{extra tokens at the end of '#pragma omp target teams distribute' are ignored}}
+#pragma omp target teams distribute private(x);
+ for (i = 0; i < 16; ++i)
+ ;
+
+// expected-warning@+1 {{extra tokens at the end of '#pragma omp target teams distribute' are ignored}}
+#pragma omp target teams distribute, private(x);
+ for (i = 0; i < 16; ++i)
+ ;
+}
+
+extern int foo();
+
+void test_collapse() {
+ int i;
+// expected-error@+1 {{expected '('}}
+#pragma omp target teams distribute collapse
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expected expression}} expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
+#pragma omp target teams distribute collapse(
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expected expression}}
+#pragma omp target teams distribute collapse()
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expected expression}} expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
+#pragma omp target teams distribute collapse(,
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expected expression}} expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
+#pragma omp target teams distribute collapse(, )
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-warning@+2 {{extra tokens at the end of '#pragma omp target teams distribute' are ignored}}
+// expected-error@+1 {{expected '('}}
+#pragma omp target teams distribute collapse 4)
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+2 {{expected ')'}}
+// expected-note@+1 {{to match this '('}} expected-note@+1 {{as specified in 'collapse' clause}}
+#pragma omp target teams distribute collapse(4
+ for (i = 0; i < 16; ++i)
+ ; // expected-error {{expected 4 for loops after '#pragma omp target teams distribute', but found only 1}}
+// expected-error@+2 {{expected ')'}}
+// expected-note@+1 {{to match this '('}} expected-note@+1 {{as specified in 'collapse' clause}}
+#pragma omp target teams distribute collapse(4,
+ for (i = 0; i < 16; ++i)
+ ; // expected-error {{expected 4 for loops after '#pragma omp target teams distribute', but found only 1}}
+// expected-error@+2 {{expected ')'}}
+// expected-note@+1 {{to match this '('}} expected-note@+1 {{as specified in 'collapse' clause}}
+#pragma omp target teams distribute collapse(4, )
+ for (i = 0; i < 16; ++i)
+ ; // expected-error {{expected 4 for loops after '#pragma omp target teams distribute', but found only 1}}
+// expected-note@+1 {{as specified in 'collapse' clause}}
+#pragma omp target teams distribute collapse(4)
+ for (i = 0; i < 16; ++i)
+ ; // expected-error {{expected 4 for loops after '#pragma omp target teams distribute', but found only 1}}
+// expected-error@+2 {{expected ')'}}
+// expected-note@+1 {{to match this '('}} expected-note@+1 {{as specified in 'collapse' clause}}
+#pragma omp target teams distribute collapse(4 4)
+ for (i = 0; i < 16; ++i)
+ ; // expected-error {{expected 4 for loops after '#pragma omp target teams distribute', but found only 1}}
+// expected-error@+2 {{expected ')'}}
+// expected-note@+1 {{to match this '('}} expected-note@+1 {{as specified in 'collapse' clause}}
+#pragma omp target teams distribute collapse(4, , 4)
+ for (i = 0; i < 16; ++i)
+ ; // expected-error {{expected 4 for loops after '#pragma omp target teams distribute', but found only 1}}
+#pragma omp target teams distribute collapse(4)
+ for (int i1 = 0; i1 < 16; ++i1)
+ for (int i2 = 0; i2 < 16; ++i2)
+ for (int i3 = 0; i3 < 16; ++i3)
+ for (int i4 = 0; i4 < 16; ++i4)
+ foo();
+// expected-error@+2 {{expected ')'}}
+// expected-note@+1 {{to match this '('}} expected-note@+1 {{as specified in 'collapse' clause}}
+#pragma omp target teams distribute collapse(4, 8)
+ for (i = 0; i < 16; ++i)
+ ; // expected-error {{expected 4 for loops after '#pragma omp target teams distribute', but found only 1}}
+// expected-error@+1 {{expression is not an integer constant expression}}
+#pragma omp target teams distribute collapse(2.5)
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expression is not an integer constant expression}}
+#pragma omp target teams distribute collapse(foo())
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{argument to 'collapse' clause must be a strictly positive integer value}}
+#pragma omp target teams distribute collapse(-5)
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{argument to 'collapse' clause must be a strictly positive integer value}}
+#pragma omp target teams distribute collapse(0)
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{argument to 'collapse' clause must be a strictly positive integer value}}
+#pragma omp target teams distribute collapse(5 - 5)
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+3 {{loop iteration variable in the associated loop of 'omp target teams distribute' directive may not be firstprivate, predetermined as private}}
+// expected-note@+1 {{defined as firstprivate}}
+#pragma omp target teams distribute collapse(2) firstprivate(i)
+ for (i = 0; i < 16; ++i)
+ for (int j = 0; j < 16; ++j)
+#pragma omp parallel for reduction(+ : i, j)
+ for (int k = 0; k < 16; ++k)
+ i += j;
+}
+
+void test_private() {
+ int i;
+// expected-error@+2 {{expected expression}}
+// expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
+#pragma omp target teams distribute private(
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+2 {{expected ')'}} expected-note@+2 {{to match this '('}}
+// expected-error@+1 2 {{expected expression}}
+#pragma omp target teams distribute private(,
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 2 {{expected expression}}
+#pragma omp target teams distribute private(, )
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expected expression}}
+#pragma omp target teams distribute private()
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expected expression}}
+#pragma omp target teams distribute private(int)
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expected variable name}}
+#pragma omp target teams distribute private(0)
+ for (i = 0; i < 16; ++i)
+ ;
+
+ int x, y, z;
+#pragma omp target teams distribute private(x)
+ for (i = 0; i < 16; ++i)
+ ;
+#pragma omp target teams distribute private(x, y)
+ for (i = 0; i < 16; ++i)
+ ;
+#pragma omp target teams distribute private(x, y, z)
+ for (i = 0; i < 16; ++i) {
+ x = y * i + z;
+ }
+}
+
+void test_lastprivate() {
+ int i;
+// expected-error@+2 {{expected ')'}} expected-note@+2 {{to match this '('}}
+// expected-error@+1 {{expected expression}}
+#pragma omp target teams distribute lastprivate(
+ for (i = 0; i < 16; ++i)
+ ;
+
+// expected-error@+2 {{expected ')'}} expected-note@+2 {{to match this '('}}
+// expected-error@+1 2 {{expected expression}}
+#pragma omp target teams distribute lastprivate(,
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 2 {{expected expression}}
+#pragma omp target teams distribute lastprivate(, )
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expected expression}}
+#pragma omp target teams distribute lastprivate()
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expected expression}}
+#pragma omp target teams distribute lastprivate(int)
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expected variable name}}
+#pragma omp target teams distribute lastprivate(0)
+ for (i = 0; i < 16; ++i)
+ ;
+
+ int x, y, z;
+#pragma omp target teams distribute lastprivate(x)
+ for (i = 0; i < 16; ++i)
+ ;
+#pragma omp target teams distribute lastprivate(x, y)
+ for (i = 0; i < 16; ++i)
+ ;
+#pragma omp target teams distribute lastprivate(x, y, z)
+ for (i = 0; i < 16; ++i)
+ ;
+}
+
+void test_firstprivate() {
+ int i;
+// expected-error@+2 {{expected ')'}} expected-note@+2 {{to match this '('}}
+// expected-error@+1 {{expected expression}}
+#pragma omp target teams distribute firstprivate(
+ for (i = 0; i < 16; ++i)
+ ;
+
+// expected-error@+2 {{expected ')'}} expected-note@+2 {{to match this '('}}
+// expected-error@+1 2 {{expected expression}}
+#pragma omp target teams distribute firstprivate(,
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 2 {{expected expression}}
+#pragma omp target teams distribute firstprivate(, )
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expected expression}}
+#pragma omp target teams distribute firstprivate()
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expected expression}}
+#pragma omp target teams distribute firstprivate(int)
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expected variable name}}
+#pragma omp target teams distribute firstprivate(0)
+ for (i = 0; i < 16; ++i)
+ ;
+
+ int x, y, z;
+#pragma omp target teams distribute lastprivate(x) firstprivate(x)
+ for (i = 0; i < 16; ++i)
+ ;
+#pragma omp target teams distribute lastprivate(x, y) firstprivate(x, y)
+ for (i = 0; i < 16; ++i)
+ ;
+#pragma omp target teams distribute lastprivate(x, y, z) firstprivate(x, y, z)
+ for (i = 0; i < 16; ++i)
+ ;
+}
+
+void test_loop_messages() {
+ float a[100], b[100], c[100];
+// expected-error@+2 {{variable must be of integer or pointer type}}
+#pragma omp target teams distribute
+ for (float fi = 0; fi < 10.0; fi++) {
+ c[(int)fi] = a[(int)fi] + b[(int)fi];
+ }
+// expected-error@+2 {{variable must be of integer or pointer type}}
+#pragma omp target teams distribute
+ for (double fi = 0; fi < 10.0; fi++) {
+ c[(int)fi] = a[(int)fi] + b[(int)fi];
+ }
+}
+
diff --git a/test/OpenMP/target_teams_distribute_nowait_messages.cpp b/test/OpenMP/target_teams_distribute_nowait_messages.cpp
new file mode 100644
index 000000000000..17aa1dcac36e
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_nowait_messages.cpp
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -verify -fopenmp -o - %s
+
+void foo() {
+}
+
+int main(int argc, char **argv) {
+ int i;
+#pragma omp target teams distribute nowait( // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute' are ignored}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute nowait (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute' are ignored}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute nowait device (-10u)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute nowait (3.14) device (-10u) // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute' are ignored}}
+ for (i = 0; i < argc; ++i) foo();
+
+ return 0;
+}
diff --git a/test/OpenMP/target_teams_distribute_num_teams_messages.cpp b/test/OpenMP/target_teams_distribute_num_teams_messages.cpp
new file mode 100644
index 000000000000..9b36e9c581f0
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_num_teams_messages.cpp
@@ -0,0 +1,85 @@
+// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 100 -o - %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note 2 {{declared here}}
+
+template <typename T, int C> // expected-note {{declared here}}
+T tmain(T argc) {
+ char **a;
+#pragma omp target teams distribute num_teams(C)
+ for (int i=0; i<100; i++) foo();
+#pragma omp target teams distribute num_teams(T) // expected-error {{'T' does not refer to a value}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target teams distribute num_teams // expected-error {{expected '(' after 'num_teams'}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target teams distribute num_teams( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target teams distribute num_teams() // expected-error {{expected expression}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target teams distribute num_teams(argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target teams distribute num_teams(argc)) // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute' are ignored}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target teams distribute num_teams(argc > 0 ? a[1] : a[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target teams distribute num_teams(argc + argc)
+ for (int i=0; i<100; i++) foo();
+#pragma omp target teams distribute num_teams(argc), num_teams (argc+1) // expected-error {{directive '#pragma omp target teams distribute' cannot contain more than one 'num_teams' clause}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target teams distribute num_teams(S1) // expected-error {{'S1' does not refer to a value}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target teams distribute num_teams(-2) // expected-error {{argument to 'num_teams' clause must be a strictly positive integer value}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target teams distribute num_teams(-10u)
+ for (int i=0; i<100; i++) foo();
+#pragma omp target teams distribute num_teams(3.14) // expected-error 2 {{expression must have integral or unscoped enumeration type, not 'double'}}
+ for (int i=0; i<100; i++) foo();
+
+ return 0;
+}
+
+int main(int argc, char **argv) {
+#pragma omp target teams distribute num_teams // expected-error {{expected '(' after 'num_teams'}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target teams distribute num_teams ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target teams distribute num_teams () // expected-error {{expected expression}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target teams distribute num_teams (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target teams distribute num_teams (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute' are ignored}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target teams distribute num_teams (argc > 0 ? argv[1] : argv[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target teams distribute num_teams (argc + argc)
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target teams distribute num_teams (argc), num_teams (argc+1) // expected-error {{directive '#pragma omp target teams distribute' cannot contain more than one 'num_teams' clause}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target teams distribute num_teams (S1) // expected-error {{'S1' does not refer to a value}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target teams distribute num_teams (-2) // expected-error {{argument to 'num_teams' clause must be a strictly positive integer value}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target teams distribute num_teams (-10u)
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target teams distribute num_teams (3.14) // expected-error {{expression must have integral or unscoped enumeration type, not 'double'}}
+ for (int i=0; i<100; i++) foo();
+
+ return tmain<int, 10>(argc); // expected-note {{in instantiation of function template specialization 'tmain<int, 10>' requested here}}
+}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_ast_print.cpp b/test/OpenMP/target_teams_distribute_parallel_for_ast_print.cpp
new file mode 100644
index 000000000000..8df3c972dce0
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_ast_print.cpp
@@ -0,0 +1,170 @@
+// 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
+// expected-no-diagnostics
+
+#ifndef HEADER
+#define HEADER
+
+void foo() {}
+
+struct S {
+ S(): a(0) {}
+ S(int v) : a(v) {}
+ int a;
+ typedef int type;
+};
+
+template <typename T>
+class S7 : public T {
+protected:
+ T a;
+ S7() : a(0) {}
+
+public:
+ S7(typename T::type v) : a(v) {
+#pragma omp target teams distribute parallel for private(a) private(this->a) private(T::a)
+ for (int k = 0; k < a.a; ++k)
+ ++this->a.a;
+ }
+ S7 &operator=(S7 &s) {
+#pragma omp target teams distribute parallel for private(a) private(this->a)
+ for (int k = 0; k < s.a.a; ++k)
+ ++s.a.a;
+
+ foo();
+ return *this;
+ }
+ void foo() {
+ int b, argv, d, c, e, f;
+#pragma omp target teams distribute parallel for default(none), private(b) firstprivate(argv) shared(d) reduction(+:c) reduction(max:e) num_teams(f) thread_limit(d)
+ for (int k = 0; k < a.a; ++k)
+ ++a.a;
+ }
+};
+// CHECK: #pragma omp target teams distribute parallel for private(this->a) private(this->a) private(T::a)
+// CHECK: #pragma omp target teams distribute parallel for private(this->a) private(this->a)
+// CHECK: #pragma omp target teams distribute parallel for default(none) private(b) firstprivate(argv) shared(d) reduction(+: c) reduction(max: e) num_teams(f) thread_limit(d)
+
+class S8 : public S7<S> {
+ S8() {}
+
+public:
+ S8(int v) : S7<S>(v){
+#pragma omp target teams distribute parallel for private(a) private(this->a) private(S7<S>::a)
+ for (int k = 0; k < a.a; ++k)
+ ++this->a.a;
+ }
+ S8 &operator=(S8 &s) {
+#pragma omp target teams distribute parallel for private(a) private(this->a)
+ for (int k = 0; k < s.a.a; ++k)
+ ++s.a.a;
+
+ bar();
+ return *this;
+ }
+ void bar() {
+ int b, argv, d, c, e, f8;
+#pragma omp target teams distribute parallel for default(none), private(b) firstprivate(argv) shared(d) reduction(+:c) reduction(max:e) num_teams(f8) thread_limit(d)
+ for (int k = 0; k < a.a; ++k)
+ ++a.a;
+ }
+};
+// CHECK: #pragma omp target teams distribute parallel for private(this->a) private(this->a) private(this->S::a)
+// CHECK: #pragma omp target teams distribute parallel for private(this->a) private(this->a) private(this->S7<S>::a)
+// CHECK: #pragma omp target teams distribute parallel for private(this->a) private(this->a)
+// CHECK: #pragma omp target teams distribute parallel for default(none) private(b) firstprivate(argv) shared(d) reduction(+: c) reduction(max: e) num_teams(f8) thread_limit(d)
+
+template <class T, int N>
+T tmain(T argc) {
+ T b = argc, c, d, e, f, g;
+ static T a;
+// CHECK: static T a;
+ const T clen = 5;
+ const T alen = 16;
+ int arr[10];
+#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-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)
+ for (int i = 0; i < 10; ++i)
+ for (int j = 0; j < 10; ++j)
+ foo();
+// CHECK: #pragma omp target teams distribute parallel for private(argc,b) firstprivate(c,d) collapse(2)
+// CHECK-NEXT: for (int i = 0; i < 10; ++i)
+// CHECK-NEXT: for (int j = 0; j < 10; ++j)
+// CHECK-NEXT: foo();
+ for (int i = 0; i < 10; ++i)
+ foo();
+// CHECK: for (int i = 0; i < 10; ++i)
+// CHECK-NEXT: foo();
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i)
+ foo();
+// CHECK: #pragma omp target teams distribute parallel for
+// CHECK-NEXT: for (int i = 0; i < 10; ++i)
+// CHECK-NEXT: foo();
+#pragma omp target teams distribute parallel for default(none), private(b) firstprivate(argc) shared(d) reduction(+:c) reduction(max:e) num_teams(f) thread_limit(d)
+ for (int k = 0; k < 10; ++k)
+ e += d + argc;
+// CHECK: #pragma omp target teams distribute parallel for default(none) private(b) firstprivate(argc) shared(d) reduction(+: c) reduction(max: e) num_teams(f) thread_limit(d)
+// CHECK-NEXT: for (int k = 0; k < 10; ++k)
+// CHECK-NEXT: e += d + argc;
+#pragma omp target teams distribute parallel for linear(d)
+ for (int k = 0; k < 10; ++k)
+ e += d + argc;
+// CHECK: #pragma omp target teams distribute parallel for linear(d)
+// CHECK-NEXT: for (int k = 0; k < 10; ++k)
+// CHECK-NEXT: e += d + argc;
+ return T();
+}
+
+int main (int argc, char **argv) {
+ int b = argc, c, d, e, f, g;
+ static int a;
+// CHECK: static int a;
+ const int clen = 5;
+ const int N = 10;
+ int arr[10];
+#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-NEXT: for (int i = 0; i < 2; ++i)
+// CHECK-NEXT: a = 2;
+#pragma omp target teams distribute parallel for private(argc,b),firstprivate(argv, c), collapse(2)
+ for (int i = 0; i < 10; ++i)
+ for (int j = 0; j < 10; ++j)
+ foo();
+// CHECK: #pragma omp target teams distribute parallel for private(argc,b) firstprivate(argv,c) collapse(2)
+// CHECK-NEXT: for (int i = 0; i < 10; ++i)
+// CHECK-NEXT: for (int j = 0; j < 10; ++j)
+// CHECK-NEXT: foo();
+ for (int i = 0; i < 10; ++i)
+ foo();
+// CHECK: for (int i = 0; i < 10; ++i)
+// CHECK-NEXT: foo();
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i)foo();
+// CHECK: #pragma omp target teams distribute parallel for
+// CHECK-NEXT: for (int i = 0; i < 10; ++i)
+// CHECK-NEXT: foo();
+#pragma omp target teams distribute parallel for default(none), private(b) firstprivate(argc) shared(d) reduction(+:c) reduction(max:e) num_teams(f) thread_limit(d)
+ for (int k = 0; k < 10; ++k)
+ e += d + argc;
+// CHECK: #pragma omp target teams distribute parallel for default(none) private(b) firstprivate(argc) shared(d) reduction(+: c) reduction(max: e) num_teams(f) thread_limit(d)
+// CHECK-NEXT: for (int k = 0; k < 10; ++k)
+// CHECK-NEXT: e += d + argc;
+#pragma omp target teams distribute parallel for linear(d)
+ for (int k = 0; k < 10; ++k)
+ e += d + argc;
+// CHECK: #pragma omp target teams distribute parallel for linear(d)
+// CHECK-NEXT: for (int k = 0; k < 10; ++k)
+// CHECK-NEXT: e += d + argc;
+ return (0);
+}
+
+#endif
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_collapse_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_collapse_messages.cpp
new file mode 100644
index 000000000000..bd94ba5205ae
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_collapse_messages.cpp
@@ -0,0 +1,149 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp %s -std=c++98
+// RUN: %clang_cc1 -verify -fopenmp %s -std=c++11
+
+void foo() {
+}
+
+#if __cplusplus >= 201103L
+// expected-note@+2 4 {{declared here}}
+#endif
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}}
+
+template <class T, typename S, int N, int ST> // expected-note {{declared here}}
+T tmain(T argc, S **argv) { //expected-note 2 {{declared here}}
+#pragma omp target teams distribute parallel for collapse // expected-error {{expected '(' after 'collapse'}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target teams distribute parallel for collapse ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = ST; i < N; i++)
+
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+#pragma omp target teams distribute parallel for collapse () // expected-error {{expected expression}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+// expected-error@+3 {{expected ')'}} expected-note@+3 {{to match this '('}}
+// expected-error@+2 2 {{expression is not an integral constant expression}}
+// expected-note@+1 2 {{read of non-const variable 'argc' is not allowed in a constant expression}}
+#pragma omp target teams distribute parallel for collapse (argc
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+// expected-error@+1 2 {{argument to 'collapse' clause must be a strictly positive integer value}}
+#pragma omp target teams distribute parallel for collapse (ST // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target teams distribute parallel for collapse (1)) // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute parallel for' are ignored}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target teams distribute parallel for collapse ((ST > 0) ? 1 + ST : 2) // expected-note 2 {{as specified in 'collapse' clause}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST]; // expected-error 2 {{expected 2 for loops after '#pragma omp target teams distribute parallel for', but found only 1}}
+
+#if __cplusplus >= 201103L
+// expected-note@+5 2 {{non-constexpr function 'foobool' cannot be used}}
+#endif
+// expected-error@+3 2 {{directive '#pragma omp target teams distribute parallel for' cannot contain more than one 'collapse' clause}}
+// expected-error@+2 2 {{argument to 'collapse' clause must be a strictly positive integer value}}
+// expected-error@+1 2 {{expression is not an integral constant expression}}
+#pragma omp target teams distribute parallel for collapse (foobool(argc)), collapse (true), collapse (-5)
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp distribute collapse (S) // expected-error {{'S' does not refer to a value}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#if __cplusplus >= 201103L
+// expected-error@+4 2 {{integral constant expression must have integral or unscoped enumeration type}}
+#else
+// expected-error@+2 2 {{expression is not an integral constant expression}}
+#endif
+#pragma omp target teams distribute parallel for collapse (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target teams distribute parallel for collapse (1)
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target teams distribute parallel for collapse (N) // expected-error {{argument to 'collapse' clause must be a strictly positive integer value}}
+ for (T i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target teams distribute parallel for collapse (2) // expected-note {{as specified in 'collapse' clause}}
+ foo(); // expected-error {{expected 2 for loops after '#pragma omp target teams distribute parallel for'}}
+ return argc;
+}
+
+int main(int argc, char **argv) {
+#pragma omp target teams distribute parallel for collapse // expected-error {{expected '(' after 'collapse'}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target teams distribute parallel for collapse ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target teams distribute parallel for collapse () // expected-error {{expected expression}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target teams distribute parallel for collapse (4 // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-note {{as specified in 'collapse' clause}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4]; // expected-error {{expected 4 for loops after '#pragma omp target teams distribute parallel for', but found only 1}}
+
+#pragma omp target teams distribute parallel for collapse (2+2)) // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute parallel for' are ignored}} expected-note {{as specified in 'collapse' clause}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4]; // expected-error {{expected 4 for loops after '#pragma omp target teams distribute parallel for', but found only 1}}
+
+#if __cplusplus >= 201103L
+// expected-note@+2 {{non-constexpr function 'foobool' cannot be used}}
+#endif
+#pragma omp target teams distribute parallel for collapse (foobool(1) > 0 ? 1 : 2) // expected-error {{expression is not an integral constant expression}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#if __cplusplus >= 201103L
+// expected-note@+5 {{non-constexpr function 'foobool' cannot be used}}
+#endif
+// expected-error@+3 {{expression is not an integral constant expression}}
+// expected-error@+2 2 {{directive '#pragma omp target teams distribute parallel for' cannot contain more than one 'collapse' clause}}
+// expected-error@+1 2 {{argument to 'collapse' clause must be a strictly positive integer value}}
+#pragma omp target teams distribute parallel for collapse (foobool(argc)), collapse (true), collapse (-5)
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target teams distribute parallel for collapse (S1) // expected-error {{'S1' does not refer to a value}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#if __cplusplus >= 201103L
+// expected-error@+4 {{integral constant expression must have integral or unscoped enumeration type}}
+#else
+// expected-error@+2 {{expression is not an integral constant expression}}
+#endif
+#pragma omp target teams distribute parallel for collapse (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+// expected-error@+3 {{statement after '#pragma omp target teams distribute parallel for' must be a for loop}}
+// expected-note@+1 {{in instantiation of function template specialization 'tmain<int, char, -1, -2>' requested here}}
+#pragma omp target teams distribute parallel for collapse(collapse(tmain<int, char, -1, -2>(argc, argv) // expected-error 2 {{expected ')'}} expected-note 2 {{to match this '('}}
+ foo();
+
+#pragma omp target teams distribute parallel for collapse (2) // expected-note {{as specified in 'collapse' clause}}
+ foo(); // expected-error {{expected 2 for loops after '#pragma omp target teams distribute parallel for'}}
+
+// expected-note@+1 {{in instantiation of function template specialization 'tmain<int, char, 1, 0>' requested here}}
+ return tmain<int, char, 1, 0>(argc, argv);
+}
+
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_default_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_default_messages.cpp
new file mode 100644
index 000000000000..db47e68a8a32
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_default_messages.cpp
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo();
+
+int main(int argc, char **argv) {
+#pragma omp target teams distribute parallel for default // expected-error {{expected '(' after 'default'}}
+ for (int i=0; i<200; i++) foo();
+ #pragma omp target teams distribute parallel for default ( // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i=0; i<200; i++) foo();
+#pragma omp target teams distribute parallel for default () // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+ for (int i=0; i<200; i++) foo();
+#pragma omp target teams distribute parallel for default (none // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i=0; i<200; i++) foo();
+#pragma omp target teams distribute parallel for default (shared), default(shared) // expected-error {{directive '#pragma omp target teams distribute parallel for' cannot contain more than one 'default' clause}}
+ for (int i=0; i<200; i++) foo();
+#pragma omp target teams distribute parallel for default (x) // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+ for (int i=0; i<200; i++) foo();
+
+#pragma omp target teams distribute parallel for default(none)
+ for (int i=0; i<200; i++) ++argc; // expected-error {{variable 'argc' must have explicitly specified data sharing attributes}}
+
+ return 0;
+}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_defaultmap_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_defaultmap_messages.cpp
new file mode 100644
index 000000000000..ad0295d461c4
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_defaultmap_messages.cpp
@@ -0,0 +1,58 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo() {
+}
+
+template <class T, typename S, int N, int ST>
+T tmain(T argc, S **argv) {
+ int i;
+#pragma omp target teams distribute parallel for defaultmap // expected-error {{expected '(' after 'defaultmap'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for defaultmap ( // expected-error {{expected 'tofrom' in OpenMP clause 'defaultmap'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for defaultmap () // expected-error {{expected 'tofrom' in OpenMP clause 'defaultmap'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for defaultmap (tofrom // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-warning {{missing ':' after defaultmap modifier - ignoring}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for defaultmap (tofrom: // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for defaultmap (tofrom) // expected-warning {{missing ':' after defaultmap modifier - ignoring}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for defaultmap (tofrom scalar) // expected-warning {{missing ':' after defaultmap modifier - ignoring}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for defaultmap (tofrom, // expected-error {{expected ')'}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}} expected-warning {{missing ':' after defaultmap modifier - ignoring}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for defaultmap (scalar: // expected-error {{expected ')'}} expected-error {{expected 'tofrom' in OpenMP clause 'defaultmap'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for defaultmap (tofrom, scalar // expected-error {{expected ')'}} expected-warning {{missing ':' after defaultmap modifier - ignoring}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+ return argc;
+}
+
+int main(int argc, char **argv) {
+ int i;
+#pragma omp target teams distribute parallel for defaultmap // expected-error {{expected '(' after 'defaultmap'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for defaultmap ( // expected-error {{expected 'tofrom' in OpenMP clause 'defaultmap'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for defaultmap () // expected-error {{expected 'tofrom' in OpenMP clause 'defaultmap'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for defaultmap (tofrom // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-warning {{missing ':' after defaultmap modifier - ignoring}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for defaultmap (tofrom: // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for defaultmap (tofrom) // expected-warning {{missing ':' after defaultmap modifier - ignoring}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for defaultmap (tofrom scalar) // expected-warning {{missing ':' after defaultmap modifier - ignoring}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for defaultmap (tofrom, // expected-error {{expected ')'}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}} expected-warning {{missing ':' after defaultmap modifier - ignoring}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for defaultmap (scalar: // expected-error {{expected ')'}} expected-error {{expected 'tofrom' in OpenMP clause 'defaultmap'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for defaultmap (tofrom, scalar // expected-error {{expected ')'}} expected-warning {{missing ':' after defaultmap modifier - ignoring}} expected-error {{expected 'scalar' in OpenMP clause 'defaultmap'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+ return tmain<int, char, 1, 0>(argc, argv);
+}
+
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_depend_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_depend_messages.cpp
new file mode 100644
index 000000000000..ca7241a16c0a
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_depend_messages.cpp
@@ -0,0 +1,90 @@
+// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - -std=c++11 %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}}
+
+class vector {
+ public:
+ int operator[](int index) { return 0; }
+};
+
+int main(int argc, char **argv, char *env[]) {
+ vector vec;
+ typedef float V __attribute__((vector_size(16)));
+ V a;
+ auto arr = x; // expected-error {{use of undeclared identifier 'x'}}
+ int i;
+
+#pragma omp target teams distribute parallel for depend // expected-error {{expected '(' after 'depend'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for depend ( // expected-error {{expected 'in', 'out' or 'inout' in OpenMP clause 'depend'}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-warning {{missing ':' after dependency type - ignoring}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for depend () // expected-error {{expected 'in', 'out' or 'inout' in OpenMP clause 'depend'}} expected-warning {{missing ':' after dependency type - ignoring}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for depend (argc // expected-error {{expected 'in', 'out' or 'inout' in OpenMP clause 'depend'}} expected-warning {{missing ':' after dependency type - ignoring}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for depend (source : argc) // expected-error {{expected 'in', 'out' or 'inout' in OpenMP clause 'depend'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for depend (source) // expected-error {{expected expression}} expected-warning {{missing ':' after dependency type - ignoring}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for depend (in : argc)) // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute parallel for' are ignored}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for depend (out: ) // expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for depend (inout : foobool(argc)), depend (in, argc) // expected-error {{expected variable name, array element or array section}} expected-warning {{missing ':' after dependency type - ignoring}} expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for depend (out :S1) // expected-error {{'S1' does not refer to a value}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for depend(in : argv[1][1] = '2') // expected-error {{expected variable name, array element or array section}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for depend (in : vec[1]) // expected-error {{expected variable name, array element or array section}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for depend (in : argv[0])
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for depend (in : ) // expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for depend (in : main) // expected-error {{expected variable name, array element or array section}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for depend(in : a[0]) // expected-error{{expected variable name, array element or array section}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for depend (in : vec[1:2]) // expected-error {{ value is not an array or pointer}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for depend (in : argv[ // expected-error {{expected expression}} expected-error {{expected ']'}} expected-error {{expected ')'}} expected-note {{to match this '['}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for depend (in : argv[: // expected-error {{expected expression}} expected-error {{expected ']'}} expected-error {{expected ')'}} expected-note {{to match this '['}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for depend (in : argv[:] // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for depend (in : argv[argc: // expected-error {{expected expression}} expected-error {{expected ']'}} expected-error {{expected ')'}} expected-note {{to match this '['}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for depend (in : argv[argc:argc] // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for depend (in : argv[0:-1]) // expected-error {{section length is evaluated to a negative value -1}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for depend (in : argv[-1:0])
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for depend (in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for depend (in : argv[3:4:1]) // expected-error {{expected ']'}} expected-note {{to match this '['}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for depend(in:a[0:1]) // expected-error {{subscripted value is not an array or pointer}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for depend(in:argv[argv[:2]:1]) // expected-error {{OpenMP array section is not allowed here}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for depend(in:argv[0:][:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for depend(in:env[0:][:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is an array of unknown bound}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for depend(in : argv[ : argc][1 : argc - 1])
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for depend(in : arr[0])
+ for (i = 0; i < argc; ++i) foo();
+
+ return 0;
+}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_device_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_device_messages.cpp
new file mode 100644
index 000000000000..b1b86cd4080b
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_device_messages.cpp
@@ -0,0 +1,40 @@
+// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -ferror-limit 100 -o - %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}}
+
+int main(int argc, char **argv) {
+ int i;
+#pragma omp target teams distribute parallel for device // expected-error {{expected '(' after 'device'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for device ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for device () // expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for device (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for device (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute parallel for' are ignored}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for device (argc > 0 ? argv[1] : argv[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for device (argc + argc)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for device (argc), device (argc+1) // expected-error {{directive '#pragma omp target teams distribute parallel for' cannot contain more than one 'device' clause}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for device (S1) // expected-error {{'S1' does not refer to a value}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for device (-2) // expected-error {{argument to 'device' clause must be a non-negative integer value}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for device (-10u)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for device (3.14) // expected-error {{expression must have integral or unscoped enumeration type, not 'double'}}
+ for (i = 0; i < argc; ++i) foo();
+
+ return 0;
+}
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
new file mode 100644
index 000000000000..d9913bc96212
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_dist_schedule_messages.cpp
@@ -0,0 +1,84 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}} expected-note {{declared here}}
+
+template <class T, int N>
+T tmain(T argc) {
+ T b = argc, c, d, e, f, g;
+ char ** argv;
+ static T a;
+// CHECK: static T a;
+
+#pragma omp target teams distribute parallel for dist_schedule // expected-error {{expected '(' after 'dist_schedule'}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target teams distribute parallel for dist_schedule ( // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target teams distribute parallel for dist_schedule () // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target teams distribute parallel for dist_schedule (static // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target teams distribute parallel for dist_schedule (static, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target teams distribute parallel for dist_schedule (argc)) // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}} expected-warning {{extra tokens at the end of '#pragma omp target teams distribute parallel for' are ignored}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target teams distribute parallel for dist_schedule (static, argc > 0 ? argv[1] : argv[2]) // expected-error2 {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target teams distribute parallel for dist_schedule (static), dist_schedule (static, 1) // expected-error {{directive '#pragma omp target teams distribute parallel for' cannot contain more than one 'dist_schedule' clause}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target teams distribute parallel for dist_schedule (static, S1) // expected-error {{'S1' does not refer to a value}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target teams distribute parallel for dist_schedule (static, argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error3 {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ for (int i = 0; i < 10; ++i) foo();
+
+ return T();
+}
+
+int main(int argc, char **argv) {
+#pragma omp target teams distribute parallel for dist_schedule // expected-error {{expected '(' after 'dist_schedule'}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target teams distribute parallel for dist_schedule ( // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target teams distribute parallel for dist_schedule () // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target teams distribute parallel for dist_schedule (static // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target teams distribute parallel for dist_schedule (static, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target teams distribute parallel for dist_schedule (argc)) // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}} expected-warning {{extra tokens at the end of '#pragma omp target teams distribute parallel for' are ignored}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target teams distribute parallel for dist_schedule (static, argc > 0 ? argv[1] : argv[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target teams distribute parallel for dist_schedule (static), dist_schedule (static, 1) // expected-error {{directive '#pragma omp target teams distribute parallel for' cannot contain more than one 'dist_schedule' clause}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target teams distribute parallel for dist_schedule (static, S1) // expected-error {{'S1' does not refer to a value}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target teams distribute parallel for dist_schedule (static, argv[1]=2) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 0; i < 10; ++i) foo();
+
+ return (tmain<int, 5>(argc) + tmain<char, 1>(argv[0][0])); // expected-note {{in instantiation of function template specialization 'tmain<int, 5>' requested here}} expected-note {{in instantiation of function template specialization 'tmain<char, 1>' requested here}}
+}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_firstprivate_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_firstprivate_messages.cpp
new file mode 100644
index 000000000000..d4e708308a02
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_firstprivate_messages.cpp
@@ -0,0 +1,131 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}} expected-note{{forward declaration of 'S1'}}
+extern S1 a;
+class S2 {
+ mutable int a;
+
+public:
+ S2() : a(0) {}
+ S2(const S2 &s2) : a(s2.a) {}
+ static float S2s;
+ static const float S2sc;
+};
+const float S2::S2sc = 0;
+const S2 b;
+const S2 ba[5];
+class S3 {
+ int a;
+ S3 &operator=(const S3 &s3);
+
+public:
+ S3() : a(0) {} // expected-note 2 {{candidate constructor not viable: requires 0 arguments, but 1 was provided}}
+ S3(S3 &s3) : a(s3.a) {} // expected-note 2 {{candidate constructor not viable: 1st argument ('const S3') would lose const qualifier}}
+};
+const S3 c;
+const S3 ca[5];
+extern const int f;
+class S4 {
+ int a;
+ S4();
+ S4(const S4 &s4);
+public:
+ S4(int v):a(v) { }
+};
+class S5 {
+ int a;
+ S5():a(0) {}
+ S5(const S5 &s5):a(s5.a) { }
+public:
+ S5(int v):a(v) { }
+};
+class S6 {
+ int a;
+public:
+ S6() : a(0) { }
+};
+
+S3 h;
+#pragma omp threadprivate(h) // expected-note {{defined as threadprivate or thread local}}
+
+int main(int argc, char **argv) {
+ const int d = 5;
+ const int da[5] = { 0 };
+ S4 e(4);
+ S5 g(5);
+ S6 p;
+ int i;
+ int &j = i;
+
+#pragma omp target teams distribute parallel for firstprivate // expected-error {{expected '(' after 'firstprivate'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute parallel for firstprivate ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute parallel for firstprivate () // expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute parallel for firstprivate (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute parallel for firstprivate (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute parallel for firstprivate (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute parallel for firstprivate (argc)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute parallel for firstprivate (S1) // expected-error {{'S1' does not refer to a value}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute parallel for firstprivate (a, b, c, d, f) // expected-error {{firstprivate variable with incomplete type 'S1'}} expected-error {{no matching constructor for initialization of 'S3'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute parallel for firstprivate (argv[1]) // expected-error {{expected variable name}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute parallel for firstprivate(ba)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute parallel for firstprivate(ca) // expected-error {{no matching constructor for initialization of 'S3'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute parallel for firstprivate(da)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute parallel for firstprivate(S2::S2s)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute parallel for firstprivate(S2::S2sc)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute parallel for firstprivate(h) // expected-error {{threadprivate or thread local variable cannot be firstprivate}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute parallel for private(i), firstprivate(i) // expected-error {{private variable cannot be firstprivate}} expected-note {{defined as private}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute parallel for firstprivate(i)
+ for (j = 0; j < argc; ++j) foo();
+
+#pragma omp target teams distribute parallel for firstprivate(i) // expected-note {{defined as firstprivate}}
+ for (i = 0; i < argc; ++i) foo(); // expected-error {{loop iteration variable in the associated loop of 'omp target teams distribute parallel for' directive may not be firstprivate, predetermined as private}}
+
+#pragma omp target teams distribute parallel for firstprivate(j)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute parallel for lastprivate(argc), firstprivate(argc) // OK
+ for (i = 0; i < argc; ++i) foo();
+
+ return 0;
+}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_if_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_if_messages.cpp
new file mode 100644
index 000000000000..82d39ac4ca8c
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_if_messages.cpp
@@ -0,0 +1,109 @@
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ferror-limit 100 %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}}
+
+template <class T, class S> // expected-note {{declared here}}
+int tmain(T argc, S **argv) {
+ T i;
+#pragma omp target teams distribute parallel for if // expected-error {{expected '(' after 'if'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for if ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for if () // expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for if (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for if (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute parallel for' are ignored}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for if (argc > 0 ? argv[1] : argv[2])
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for if (foobool(argc)), if (true) // expected-error {{directive '#pragma omp target teams distribute parallel for' cannot contain more than one 'if' clause}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for if (S) // expected-error {{'S' does not refer to a value}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for if (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for if (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for if(argc)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for if(parallel // expected-error {{use of undeclared identifier 'parallel'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for if(parallel : // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for if(parallel : argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for if(parallel : argc)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for if(parallel : argc) if (for:argc) // expected-error {{directive name modifier 'for' is not allowed for '#pragma omp target teams distribute parallel for'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for if(parallel : argc) if (parallel:argc) // expected-error {{directive '#pragma omp target teams distribute parallel for' cannot contain more than one 'if' clause with 'parallel' name modifier}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for if(target : argc) if (target:argc) // expected-error {{directive '#pragma omp target teams distribute parallel for' cannot contain more than one 'if' clause with 'target' name modifier}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for if(parallel : argc) if (argc) // expected-error {{expected 'target' directive name modifier}} expected-note {{previous clause with directive name modifier specified here}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for if(target: argc) if (argc) // expected-error {{expected 'parallel' directive name modifier}} expected-note {{previous clause with directive name modifier specified here}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for if(distribute : argc) // expected-error {{directive name modifier 'distribute' is not allowed for '#pragma omp target teams distribute parallel for'}}
+ for (i = 0; i < argc; ++i) foo();
+
+ return 0;
+}
+
+int main(int argc, char **argv) {
+ int i;
+#pragma omp target teams distribute parallel for if // expected-error {{expected '(' after 'if'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for if ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for if () // expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for if (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for if (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute parallel for' are ignored}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for if (argc > 0 ? argv[1] : argv[2])
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for if (foobool(argc)), if (true) // expected-error {{directive '#pragma omp target teams distribute parallel for' cannot contain more than one 'if' clause}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for if (S1) // expected-error {{'S1' does not refer to a value}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for if (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for if (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for if (1 0) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for if(if(tmain(argc, argv) // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for if(parallel // expected-error {{use of undeclared identifier 'parallel'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for if(parallel : // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for if(parallel : argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for if(parallel : argc)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for if(parallel : argc) if (for:argc) // expected-error {{directive name modifier 'for' is not allowed for '#pragma omp target teams distribute parallel for'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for if(parallel : argc) if (parallel:argc) // expected-error {{directive '#pragma omp target teams distribute parallel for' cannot contain more than one 'if' clause with 'parallel' name modifier}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for if(target: argc) if (target:argc) // expected-error {{directive '#pragma omp target teams distribute parallel for' cannot contain more than one 'if' clause with 'target' name modifier}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for if(parallel : argc) if (argc) // expected-note {{previous clause with directive name modifier specified here}} expected-error {{expected 'target' directive name modifier}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for if(target: argc) if (argc) // expected-note {{previous clause with directive name modifier specified here}} expected-error {{expected 'parallel' directive name modifier}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for if(distribute : argc) // expected-error {{directive name modifier 'distribute' is not allowed for '#pragma omp target teams distribute parallel for'}}
+ for (i = 0; i < argc; ++i) foo();
+
+ return tmain(argc, argv);
+}
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
new file mode 100644
index 000000000000..c566319df42d
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_is_device_ptr_ast_print.cpp
@@ -0,0 +1,318 @@
+// 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
+// expected-no-diagnostics
+
+#ifndef HEADER
+#define HEADER
+struct ST {
+ int *a;
+};
+typedef int arr[10];
+typedef ST STarr[10];
+struct SA {
+ const int da[5] = { 0 };
+ ST g[10];
+ STarr &rg = g;
+ int i;
+ int &j = i;
+ int *k = &j;
+ int *&z = k;
+ int aa[10];
+ arr &raa = aa;
+ void func(int arg) {
+#pragma omp target teams distribute parallel for is_device_ptr(k)
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(z)
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(aa) // OK
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(raa) // OK
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(g) // OK
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(rg) // OK
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(da) // OK
+ for (int i=0; i<100; i++)
+ ;
+ return;
+ }
+};
+// CHECK: struct SA
+// CHECK-NEXT: const int da[5] = {0};
+// CHECK-NEXT: ST g[10];
+// CHECK-NEXT: STarr &rg = this->g;
+// CHECK-NEXT: int i;
+// CHECK-NEXT: int &j = this->i;
+// CHECK-NEXT: int *k = &this->j;
+// CHECK-NEXT: int *&z = this->k;
+// 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: for (int i = 0; i < 100; i++)
+// CHECK-NEXT: ;
+// CHECK-NEXT: #pragma omp target teams distribute parallel for is_device_ptr(this->z)
+// CHECK-NEXT: for (int i = 0; i < 100; i++)
+// CHECK-NEXT: ;
+// CHECK-NEXT: #pragma omp target teams distribute parallel for is_device_ptr(this->aa)
+// CHECK-NEXT: for (int i = 0; i < 100; i++)
+// CHECK-NEXT: ;
+// CHECK-NEXT: #pragma omp target teams distribute parallel for is_device_ptr(this->raa)
+// CHECK-NEXT: for (int i = 0; i < 100; i++)
+// CHECK-NEXT: ;
+// CHECK-NEXT: #pragma omp target teams distribute parallel for is_device_ptr(this->g)
+// CHECK-NEXT: for (int i = 0; i < 100; i++)
+// CHECK-NEXT: ;
+// CHECK-NEXT: #pragma omp target teams distribute parallel for is_device_ptr(this->rg)
+// CHECK-NEXT: for (int i = 0; i < 100; i++)
+// CHECK-NEXT: ;
+// CHECK-NEXT: #pragma omp target teams distribute parallel for is_device_ptr(this->da)
+// CHECK-NEXT: for (int i = 0; i < 100; i++)
+// CHECK-NEXT: ;
+
+struct SB {
+ unsigned A;
+ unsigned B;
+ float Arr[100];
+ float *Ptr;
+ float *foo() {
+ return &Arr[0];
+ }
+};
+
+struct SC {
+ unsigned A : 2;
+ unsigned B : 3;
+ unsigned C;
+ unsigned D;
+ float Arr[100];
+ SB S;
+ SB ArrS[100];
+ SB *PtrS;
+ SB *&RPtrS;
+ float *Ptr;
+
+ SC(SB *&_RPtrS) : RPtrS(_RPtrS) {}
+};
+
+union SD {
+ unsigned A;
+ float B;
+};
+
+struct S1;
+extern S1 a;
+class S2 {
+ mutable int a;
+public:
+ S2():a(0) { }
+ S2(S2 &s2):a(s2.a) { }
+ static float S2s;
+ static const float S2sc;
+};
+const float S2::S2sc = 0;
+const S2 b;
+const S2 ba[5];
+class S3 {
+ int a;
+public:
+ S3():a(0) { }
+ S3(S3 &s3):a(s3.a) { }
+};
+const S3 c;
+const S3 ca[5];
+extern const int f;
+class S4 {
+ int a;
+ S4();
+ S4(const S4 &s4);
+public:
+ S4(int v):a(v) { }
+};
+class S5 {
+ int a;
+ S5():a(0) {}
+ S5(const S5 &s5):a(s5.a) { }
+public:
+ S5(int v):a(v) { }
+};
+
+S3 h;
+#pragma omp threadprivate(h)
+
+typedef struct {
+ int a;
+} S6;
+
+template <typename T>
+T tmain(T argc) {
+ const T da[5] = { 0 };
+ S6 h[10];
+ auto &rh = h;
+ T i;
+ T &j = i;
+ T *k = &j;
+ T *&z = k;
+ T aa[10];
+ auto &raa = aa;
+#pragma omp target teams distribute parallel for is_device_ptr(k)
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(z)
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(aa)
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(raa)
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(h)
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(rh)
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(da)
+ for (int i=0; i<100; i++)
+ ;
+ return 0;
+}
+
+// CHECK: template<> int tmain<int>(int argc) {
+// CHECK-NEXT: const int da[5] = {0};
+// CHECK-NEXT: S6 h[10];
+// CHECK-NEXT: auto &rh = h;
+// CHECK-NEXT: int i;
+// CHECK-NEXT: int &j = i;
+// CHECK-NEXT: int *k = &j;
+// CHECK-NEXT: int *&z = k;
+// CHECK-NEXT: int aa[10];
+// CHECK-NEXT: auto &raa = aa;
+// CHECK-NEXT: #pragma omp target teams distribute parallel for is_device_ptr(k)
+// CHECK-NEXT: for (int i = 0; i < 100; i++)
+// CHECK-NEXT: ;
+// CHECK-NEXT: #pragma omp target teams distribute parallel for is_device_ptr(z)
+// CHECK-NEXT: for (int i = 0; i < 100; i++)
+// CHECK-NEXT: ;
+// CHECK-NEXT: #pragma omp target teams distribute parallel for is_device_ptr(aa)
+// CHECK-NEXT: for (int i = 0; i < 100; i++)
+// CHECK-NEXT: ;
+// CHECK-NEXT: #pragma omp target teams distribute parallel for is_device_ptr(raa)
+// CHECK-NEXT: for (int i = 0; i < 100; i++)
+// CHECK-NEXT: ;
+// CHECK-NEXT: #pragma omp target teams distribute parallel for is_device_ptr(h)
+// CHECK-NEXT: for (int i = 0; i < 100; i++)
+// CHECK-NEXT: ;
+// CHECK-NEXT: #pragma omp target teams distribute parallel for is_device_ptr(rh)
+// CHECK-NEXT: for (int i = 0; i < 100; i++)
+// CHECK-NEXT: ;
+// CHECK-NEXT: #pragma omp target teams distribute parallel for is_device_ptr(da)
+// CHECK-NEXT: for (int i = 0; i < 100; i++)
+// CHECK-NEXT: ;
+
+// CHECK: template<> int *tmain<int *>(int *argc) {
+// CHECK-NEXT: int *const da[5] = {0};
+// CHECK-NEXT: S6 h[10];
+// CHECK-NEXT: auto &rh = h;
+// CHECK-NEXT: int *i;
+// CHECK-NEXT: int *&j = i;
+// CHECK-NEXT: int **k = &j;
+// CHECK-NEXT: int **&z = k;
+// CHECK-NEXT: int *aa[10];
+// CHECK-NEXT: auto &raa = aa;
+// CHECK-NEXT: #pragma omp target teams distribute parallel for is_device_ptr(k)
+// CHECK-NEXT: for (int i = 0; i < 100; i++)
+// CHECK-NEXT: ;
+// CHECK-NEXT: #pragma omp target teams distribute parallel for is_device_ptr(z)
+// CHECK-NEXT: for (int i = 0; i < 100; i++)
+// CHECK-NEXT: ;
+// CHECK-NEXT: #pragma omp target teams distribute parallel for is_device_ptr(aa)
+// CHECK-NEXT: for (int i = 0; i < 100; i++)
+// CHECK-NEXT: ;
+// CHECK-NEXT: #pragma omp target teams distribute parallel for is_device_ptr(raa)
+// CHECK-NEXT: for (int i = 0; i < 100; i++)
+// CHECK-NEXT: ;
+// CHECK-NEXT: #pragma omp target teams distribute parallel for is_device_ptr(h)
+// CHECK-NEXT: for (int i = 0; i < 100; i++)
+// CHECK-NEXT: ;
+// CHECK-NEXT: #pragma omp target teams distribute parallel for is_device_ptr(rh)
+// CHECK-NEXT: for (int i = 0; i < 100; i++)
+// CHECK-NEXT: ;
+// CHECK-NEXT: #pragma omp target teams distribute parallel for is_device_ptr(da)
+// CHECK-NEXT: for (int i = 0; i < 100; i++)
+// CHECK-NEXT: ;
+
+// CHECK-LABEL: int main(int argc, char **argv) {
+int main(int argc, char **argv) {
+ const int da[5] = { 0 };
+ S6 h[10];
+ auto &rh = h;
+ int i;
+ int &j = i;
+ int *k = &j;
+ int *&z = k;
+ int aa[10];
+ auto &raa = aa;
+// CHECK-NEXT: const int da[5] = {0};
+// CHECK-NEXT: S6 h[10];
+// CHECK-NEXT: auto &rh = h;
+// CHECK-NEXT: int i;
+// CHECK-NEXT: int &j = i;
+// CHECK-NEXT: int *k = &j;
+// CHECK-NEXT: int *&z = k;
+// CHECK-NEXT: int aa[10];
+// CHECK-NEXT: auto &raa = aa;
+#pragma omp target teams distribute parallel for is_device_ptr(k)
+// CHECK-NEXT: #pragma omp target teams distribute parallel for is_device_ptr(k)
+ for (int i=0; i<100; i++)
+ ;
+// CHECK-NEXT: for (int i = 0; i < 100; i++)
+// CHECK-NEXT: ;
+#pragma omp target teams distribute parallel for is_device_ptr(z)
+// CHECK-NEXT: #pragma omp target teams distribute parallel for is_device_ptr(z)
+ for (int i=0; i<100; i++)
+ ;
+// CHECK-NEXT: for (int i = 0; i < 100; i++)
+// CHECK-NEXT: ;
+#pragma omp target teams distribute parallel for is_device_ptr(aa)
+// CHECK-NEXT: #pragma omp target teams distribute parallel for is_device_ptr(aa)
+ for (int i=0; i<100; i++)
+ ;
+// CHECK-NEXT: for (int i = 0; i < 100; i++)
+// CHECK-NEXT: ;
+#pragma omp target teams distribute parallel for is_device_ptr(raa)
+// CHECK-NEXT: #pragma omp target teams distribute parallel for is_device_ptr(raa)
+ for (int i=0; i<100; i++)
+ ;
+// CHECK-NEXT: for (int i = 0; i < 100; i++)
+// CHECK-NEXT: ;
+#pragma omp target teams distribute parallel for is_device_ptr(h)
+// CHECK-NEXT: #pragma omp target teams distribute parallel for is_device_ptr(h)
+ for (int i=0; i<100; i++)
+ ;
+// CHECK-NEXT: for (int i = 0; i < 100; i++)
+// CHECK-NEXT: ;
+#pragma omp target teams distribute parallel for is_device_ptr(rh)
+// CHECK-NEXT: #pragma omp target teams distribute parallel for is_device_ptr(rh)
+ for (int i=0; i<100; i++)
+ ;
+// CHECK-NEXT: for (int i = 0; i < 100; i++)
+// CHECK-NEXT: ;
+#pragma omp target teams distribute parallel for is_device_ptr(da)
+// CHECK-NEXT: #pragma omp target teams distribute parallel for is_device_ptr(da)
+ for (int i=0; i<100; i++)
+ ;
+// CHECK-NEXT: for (int i = 0; i < 100; i++)
+// CHECK-NEXT: ;
+ return tmain<int>(argc) + *tmain<int *>(&argc);
+}
+#endif
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
new file mode 100644
index 000000000000..eaa3190a47f6
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_is_device_ptr_messages.cpp
@@ -0,0 +1,337 @@
+// RUN: %clang_cc1 -std=c++11 -verify -fopenmp %s
+struct ST {
+ int *a;
+};
+typedef int arr[10];
+typedef ST STarr[10];
+struct SA {
+ const int d = 5;
+ const int da[5] = { 0 };
+ ST e;
+ ST g[10];
+ STarr &rg = g;
+ int i;
+ int &j = i;
+ int *k = &j;
+ int *&z = k;
+ int aa[10];
+ arr &raa = aa;
+ void func(int arg) {
+#pragma omp target teams distribute parallel for is_device_ptr // expected-error {{expected '(' after 'is_device_ptr'}}
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr( // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}}
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr() // expected-error {{expected expression}}
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(alloc) // expected-error {{use of undeclared identifier 'alloc'}}
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(arg // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(i) // expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(j) // expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(k) // OK
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(z) // OK
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(aa) // OK
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(raa) // OK
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(e) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(g) // OK
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(rg) // OK
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(k,i,j) // expected-error2 {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(d) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(da) // OK
+ for (int i=0; i<100; i++)
+ ;
+ return;
+ }
+};
+struct SB {
+ unsigned A;
+ unsigned B;
+ float Arr[100];
+ float *Ptr;
+ float *foo() {
+ return &Arr[0];
+ }
+};
+
+struct SC {
+ unsigned A : 2;
+ unsigned B : 3;
+ unsigned C;
+ unsigned D;
+ float Arr[100];
+ SB S;
+ SB ArrS[100];
+ SB *PtrS;
+ SB *&RPtrS;
+ float *Ptr;
+
+ SC(SB *&_RPtrS) : RPtrS(_RPtrS) {}
+};
+
+union SD {
+ unsigned A;
+ float B;
+};
+
+struct S1;
+extern S1 a;
+class S2 {
+ mutable int a;
+public:
+ S2():a(0) { }
+ S2(S2 &s2):a(s2.a) { }
+ static float S2s;
+ static const float S2sc;
+};
+const float S2::S2sc = 0;
+const S2 b;
+const S2 ba[5];
+class S3 {
+ int a;
+public:
+ S3():a(0) { }
+ S3(S3 &s3):a(s3.a) { }
+};
+const S3 c;
+const S3 ca[5];
+extern const int f;
+class S4 {
+ int a;
+ S4();
+ S4(const S4 &s4);
+public:
+ S4(int v):a(v) { }
+};
+class S5 {
+ int a;
+ S5():a(0) {}
+ S5(const S5 &s5):a(s5.a) { }
+public:
+ S5(int v):a(v) { }
+};
+
+S3 h;
+#pragma omp threadprivate(h)
+
+typedef struct {
+ int a;
+} S6;
+
+template <typename T, int I>
+T tmain(T argc) {
+ const T d = 5;
+ const T da[5] = { 0 };
+ S4 e(4);
+ S5 g(5);
+ S6 h[10];
+ auto &rh = h;
+ T i;
+ T &j = i;
+ T *k = &j;
+ T *&z = k;
+ T aa[10];
+ auto &raa = aa;
+ S6 *ps;
+#pragma omp target teams distribute parallel for is_device_ptr // expected-error {{expected '(' after 'is_device_ptr'}}
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr( // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}}
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr() // expected-error {{expected expression}}
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(alloc) // expected-error {{use of undeclared identifier 'alloc'}}
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(i) // expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(j) // expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(k) // OK
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(z) // OK
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(aa) // OK
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(raa) // OK
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(e) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(g) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(h) // OK
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(rh) // OK
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(k,i,j) // expected-error2 {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(d) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(da) // OK
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for map(ps) is_device_ptr(ps) // expected-error{{variable already marked as mapped in current construct}} expected-note{{used here}}
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(ps) map(ps) // expected-error{{variable already marked as mapped in current construct}} expected-note{{used here}}
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for map(ps->a) is_device_ptr(ps) // expected-error{{variable already marked as mapped in current construct}} expected-note{{used here}}
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(ps) map(ps->a) // expected-error{{pointer cannot be mapped along with a section derived from itself}} expected-note{{used here}}
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(ps) firstprivate(ps) // expected-error{{firstprivate variable cannot be in a is_device_ptr clause in '#pragma omp target teams distribute parallel for' directive}}
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for firstprivate(ps) is_device_ptr(ps) // expected-error{{firstprivate variable cannot be in a is_device_ptr clause in '#pragma omp target teams distribute parallel for' directive}} expected-note{{defined as firstprivate}}
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(ps) private(ps) // expected-error{{private variable cannot be in a is_device_ptr clause in '#pragma omp target teams distribute parallel for' directive}}
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for private(ps) is_device_ptr(ps) // expected-error{{private variable cannot be in a is_device_ptr clause in '#pragma omp target teams distribute parallel for' directive}} expected-note{{defined as private}}
+ for (int i=0; i<100; i++)
+ ;
+ return 0;
+}
+
+int main(int argc, char **argv) {
+ const int d = 5;
+ const int da[5] = { 0 };
+ S4 e(4);
+ S5 g(5);
+ S6 h[10];
+ auto &rh = h;
+ int i;
+ int &j = i;
+ int *k = &j;
+ int *&z = k;
+ int aa[10];
+ auto &raa = aa;
+ S6 *ps;
+#pragma omp target teams distribute parallel for is_device_ptr // expected-error {{expected '(' after 'is_device_ptr'}}
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr( // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}}
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr() // expected-error {{expected expression}}
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(alloc) // expected-error {{use of undeclared identifier 'alloc'}}
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(i) // expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(j) // expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(k) // OK
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(z) // OK
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(aa) // OK
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(raa) // OK
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(e) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(g) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(h) // OK
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(rh) // OK
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(k,i,j) // expected-error2 {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(d) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(da) // OK
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for map(ps) is_device_ptr(ps) // expected-error{{variable already marked as mapped in current construct}} expected-note{{used here}}
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(ps) map(ps) // expected-error{{variable already marked as mapped in current construct}} expected-note{{used here}}
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for map(ps->a) is_device_ptr(ps) // expected-error{{variable already marked as mapped in current construct}} expected-note{{used here}}
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(ps) map(ps->a) // expected-error{{pointer cannot be mapped along with a section derived from itself}} expected-note{{used here}}
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(ps) firstprivate(ps) // expected-error{{firstprivate variable cannot be in a is_device_ptr clause in '#pragma omp target teams distribute parallel for' directive}}
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for firstprivate(ps) is_device_ptr(ps) // expected-error{{firstprivate variable cannot be in a is_device_ptr clause in '#pragma omp target teams distribute parallel for' directive}} expected-note{{defined as firstprivate}}
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for is_device_ptr(ps) private(ps) // expected-error{{private variable cannot be in a is_device_ptr clause in '#pragma omp target teams distribute parallel for' directive}}
+ for (int i=0; i<100; i++)
+ ;
+#pragma omp target teams distribute parallel for private(ps) is_device_ptr(ps) // expected-error{{private variable cannot be in a is_device_ptr clause in '#pragma omp target teams distribute parallel for' directive}} expected-note{{defined as private}}
+ for (int i=0; i<100; i++)
+ ;
+ return tmain<int, 3>(argc); // expected-note {{in instantiation of function template specialization 'tmain<int, 3>' requested here}}
+}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_lastprivate_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_lastprivate_messages.cpp
new file mode 100644
index 000000000000..d31acef0039d
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_lastprivate_messages.cpp
@@ -0,0 +1,233 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note 2 {{declared here}} expected-note 2 {{forward declaration of 'S1'}}
+extern S1 a;
+class S2 {
+ mutable int a;
+
+public:
+ S2() : a(0) {}
+ S2(S2 &s2) : a(s2.a) {}
+ const S2 &operator =(const S2&) const;
+ S2 &operator =(const S2&);
+ static float S2s; // expected-note {{static data member is predetermined as shared}}
+ static const float S2sc;
+};
+const float S2::S2sc = 0; // expected-note {{static data member is predetermined as shared}}
+const S2 b;
+const S2 ba[5];
+class S3 {
+ int a;
+ S3 &operator=(const S3 &s3); // expected-note 2 {{implicitly declared private here}}
+
+public:
+ S3() : a(0) {}
+ S3(S3 &s3) : a(s3.a) {}
+};
+const S3 c; // expected-note {{global variable is predetermined as shared}}
+const S3 ca[5]; // expected-note {{global variable is predetermined as shared}}
+extern const int f; // expected-note {{global variable is predetermined as shared}}
+class S4 {
+ int a;
+ S4(); // expected-note 3 {{implicitly declared private here}}
+ S4(const S4 &s4);
+
+public:
+ S4(int v) : a(v) {}
+};
+class S5 {
+ int a;
+ S5() : a(0) {} // expected-note {{implicitly declared private here}}
+
+public:
+ S5(const S5 &s5) : a(s5.a) {}
+ S5(int v) : a(v) {}
+};
+class S6 {
+ int a;
+ S6() : a(0) {}
+
+public:
+ S6(const S6 &s6) : a(s6.a) {}
+ S6(int v) : a(v) {}
+};
+
+S3 h;
+#pragma omp threadprivate(h) // expected-note 2 {{defined as threadprivate or thread local}}
+
+template <class I, class C>
+int foomain(int argc, char **argv) {
+ I e(4);
+ I g(5);
+ int i;
+ int &j = i;
+#pragma omp target teams distribute parallel for lastprivate // expected-error {{expected '(' after 'lastprivate'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for lastprivate( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for lastprivate() // expected-error {{expected expression}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for lastprivate(argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for lastprivate(argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for lastprivate(argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for lastprivate(argc)
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for lastprivate(S1) // expected-error {{'S1' does not refer to a value}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for lastprivate(a, b) // expected-error {{lastprivate variable with incomplete type 'S1'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for lastprivate(argv[1]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for lastprivate(e, g) // expected-error 2 {{calling a private constructor of class 'S4'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for lastprivate(h) // expected-error {{threadprivate or thread local variable cannot be lastprivate}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ int v = 0;
+#pragma omp target teams distribute parallel for lastprivate(i)
+ for (int k = 0; k < argc; ++k) {
+ i = k;
+ v += i;
+ }
+
+#pragma omp target teams distribute parallel for lastprivate(j) private(i)
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for lastprivate(i)
+ for (int k = 0; k < argc; ++k) ++k;
+
+ return 0;
+}
+
+void bar(S4 a[2]) {
+#pragma omp target teams distribute parallel for lastprivate(a)
+ for (int i = 0; i < 2; ++i) foo();
+}
+
+namespace A {
+double x;
+#pragma omp threadprivate(x) // expected-note {{defined as threadprivate or thread local}}
+}
+namespace B {
+using A::x;
+}
+
+int main(int argc, char **argv) {
+ const int d = 5; // expected-note {{constant variable is predetermined as shared}}
+ const int da[5] = {0}; // expected-note {{constant variable is predetermined as shared}}
+ S4 e(4);
+ S5 g(5);
+ S3 m;
+ S6 n(2);
+ int i;
+ int &j = i;
+ float k;
+#pragma omp target teams distribute parallel for lastprivate // expected-error {{expected '(' after 'lastprivate'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute parallel for lastprivate( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute parallel for lastprivate() // expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute parallel for lastprivate(argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute parallel for lastprivate(argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute parallel for lastprivate(argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute parallel for lastprivate(argc)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute parallel for lastprivate(S1) // expected-error {{'S1' does not refer to a value}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute parallel for lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be lastprivate}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute parallel for lastprivate(argv[1]) // expected-error {{expected variable name}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute parallel for lastprivate(2 * 2) // expected-error {{expected variable name}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute parallel for lastprivate(ba)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute parallel for lastprivate(ca) // expected-error {{shared variable cannot be lastprivate}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute parallel for lastprivate(da) // expected-error {{shared variable cannot be lastprivate}}
+ for (i = 0; i < argc; ++i) foo();
+
+ int xa;
+#pragma omp target teams distribute parallel for lastprivate(xa) // OK
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute parallel for lastprivate(S2::S2s) // expected-error {{shared variable cannot be lastprivate}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute parallel for lastprivate(S2::S2sc) // expected-error {{shared variable cannot be lastprivate}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute parallel for lastprivate(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute parallel for lastprivate(m) // expected-error {{'operator=' is a private member of 'S3'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute parallel for lastprivate(h) // expected-error {{threadprivate or thread local variable cannot be lastprivate}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute parallel for lastprivate(B::x) // expected-error {{threadprivate or thread local variable cannot be lastprivate}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute parallel for private(xa), lastprivate(xa) // expected-error {{private variable cannot be lastprivate}} expected-note {{defined as private}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute parallel for lastprivate(xa)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute parallel for lastprivate(j)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute parallel for firstprivate(m) lastprivate(m) // expected-error {{'operator=' is a private member of 'S3'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target teams distribute parallel for lastprivate(n) firstprivate(n) // OK
+ for (i = 0; i < argc; ++i) foo();
+
+ static int si;
+#pragma omp target teams distribute parallel for lastprivate(si) // OK
+ for (i = 0; i < argc; ++i) si = i + 1;
+
+#pragma omp target teams distribute parallel for lastprivate(k) map(k) // expected-error {{lastprivate variable cannot be in a map clause in '#pragma omp target teams distribute parallel for' directive}} expected-note {{defined as lastprivate}}
+ for (i = 0; i < argc; ++i) foo();
+
+ return foomain<S4, S5>(argc, argv); // expected-note {{in instantiation of function template specialization 'foomain<S4, S5>' requested here}}
+}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_linear_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_linear_messages.cpp
new file mode 100644
index 000000000000..82220dcf45c6
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_linear_messages.cpp
@@ -0,0 +1,248 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+namespace X {
+ int x;
+};
+
+struct B {
+ static int ib; // expected-note {{'B::ib' declared here}}
+ static int bfoo() { return 8; }
+};
+
+int bfoo() { return 4; }
+
+int z;
+const int C1 = 1;
+const int C2 = 2;
+void test_linear_colons()
+{
+ int B = 0;
+
+#pragma omp target teams distribute parallel for linear(B:bfoo())
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target teams distribute parallel for linear(B::ib:B:bfoo()) // expected-error {{unexpected ':' in nested name specifier; did you mean '::'}}
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target teams distribute parallel for linear(B:ib) // expected-error {{use of undeclared identifier 'ib'; did you mean 'B::ib'}}
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target teams distribute parallel for linear(z:B:ib) // expected-error {{unexpected ':' in nested name specifier; did you mean '::'?}}
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target teams distribute parallel for linear(B:B::bfoo())
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target teams distribute parallel for linear(X::x : ::z)
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target teams distribute parallel for linear(B,::z, X::x)
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target teams distribute parallel for linear(::z)
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target teams distribute parallel for linear(B::bfoo()) // expected-error {{expected variable name}}
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target teams distribute parallel for linear(B::ib,B:C1+C2)
+ for (int i = 0; i < 10; ++i) ;
+}
+
+template<int L, class T, class N> T test_template(T* arr, N num) {
+ N i;
+ T sum = (T)0;
+ T ind2 = - num * L; // expected-note {{'ind2' defined here}}
+
+#pragma omp target teams distribute parallel for linear(ind2:L) // expected-error {{argument of a linear clause should be of integral or pointer type}}
+ for (i = 0; i < num; ++i) {
+ T cur = arr[(int)ind2];
+ ind2 += L;
+ sum += cur;
+ }
+ return T();
+}
+
+template<int LEN> int test_warn() {
+ int ind2 = 0;
+#pragma omp target teams distribute parallel for linear(ind2:LEN) // expected-warning {{zero linear step (ind2 should probably be const)}}
+ for (int i = 0; i < 100; i++) {
+ ind2 += LEN;
+ }
+ return ind2;
+}
+
+struct S1; // expected-note 2 {{declared here}} expected-note 2 {{forward declaration of 'S1'}}
+extern S1 a;
+class S2 {
+ mutable int a;
+public:
+ S2():a(0) { }
+};
+const S2 b; // expected-note 2 {{'b' defined here}}
+const S2 ba[5];
+class S3 {
+ int a;
+public:
+ S3():a(0) { }
+};
+const S3 ca[5];
+class S4 {
+ int a;
+ S4();
+public:
+ S4(int v):a(v) { }
+};
+class S5 {
+ int a;
+ S5():a(0) {}
+public:
+ S5(int v):a(v) { }
+};
+
+S3 h;
+#pragma omp threadprivate(h) // expected-note 2 {{defined as threadprivate or thread local}}
+
+template<class I, class C> int foomain(I argc, C **argv) {
+ I e(4);
+ I g(5);
+ int i;
+ int &j = i;
+
+#pragma omp target teams distribute parallel for linear // expected-error {{expected '(' after 'linear'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for linear ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for linear () // expected-error {{expected expression}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for linear (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for linear (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for linear (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for linear (argc : 5)
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for linear (S1) // expected-error {{'S1' does not refer to a value}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for linear (a, b:B::ib) // expected-error {{linear variable with incomplete type 'S1'}} expected-error {{const-qualified variable cannot be linear}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for linear (argv[1]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for linear(e, g)
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for linear(h) // expected-error {{threadprivate or thread local variable cannot be linear}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for linear(i)
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp parallel
+ {
+ int v = 0;
+ int i;
+ #pragma omp target teams distribute parallel for linear(v:i)
+ for (int k = 0; k < argc; ++k) { i = k; v += i; }
+ }
+
+#pragma omp target teams distribute parallel for linear(j)
+ for (int k = 0; k < argc; ++k) ++k;
+
+ int v = 0;
+
+#pragma omp target teams distribute parallel for linear(v:j)
+ for (int k = 0; k < argc; ++k) { ++k; v += j; }
+
+#pragma omp target teams distribute parallel for linear(i)
+ for (int k = 0; k < argc; ++k) ++k;
+ return 0;
+}
+
+namespace A {
+double x;
+#pragma omp threadprivate(x) // expected-note {{defined as threadprivate or thread local}}
+}
+namespace C {
+using A::x;
+}
+
+int main(int argc, char **argv) {
+ double darr[100];
+ // expected-note@+1 {{in instantiation of function template specialization 'test_template<-4, double, int>' requested here}}
+ test_template<-4>(darr, 4);
+ // expected-note@+1 {{in instantiation of function template specialization 'test_warn<0>' requested here}}
+ test_warn<0>();
+
+ S4 e(4); // expected-note {{'e' defined here}}
+ S5 g(5); // expected-note {{'g' defined here}}
+ int i;
+ int &j = i;
+
+#pragma omp target teams distribute parallel for linear // expected-error {{expected '(' after 'linear'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for linear ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for linear () // expected-error {{expected expression}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for linear (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for linear (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for linear (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for linear (argc)
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for linear (S1) // expected-error {{'S1' does not refer to a value}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+
+#pragma omp target teams distribute parallel for linear (a, b) // expected-error {{linear variable with incomplete type 'S1'}} expected-error {{const-qualified variable cannot be linear}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for linear (argv[1]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for linear(e, g) // expected-error {{argument of a linear clause should be of integral or pointer type, not 'S4'}} expected-error {{argument of a linear clause should be of integral or pointer type, not 'S5'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for linear(h, C::x) // expected-error 2 {{threadprivate or thread local variable cannot be linear}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp parallel
+{
+ int i;
+#pragma omp target teams distribute parallel for linear(i)
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for linear(i : 4)
+ for (int k = 0; k < argc; ++k) { ++k; i += 4; }
+}
+
+#pragma omp target teams distribute parallel for linear(j)
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for linear(i)
+ for (int k = 0; k < argc; ++k) ++k;
+
+ foomain<int,char>(argc,argv); // expected-note {{in instantiation of function template specialization 'foomain<int, char>' requested here}}
+ return 0;
+}
+
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_loop_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_loop_messages.cpp
new file mode 100644
index 000000000000..83c78f2aac78
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_loop_messages.cpp
@@ -0,0 +1,624 @@
+// RUN: %clang_cc1 -fsyntax-only -fopenmp -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s
+
+class S {
+ int a;
+ S() : a(0) {}
+
+public:
+ S(int v) : a(v) {}
+ S(const S &s) : a(s.a) {}
+};
+
+static int sii;
+// expected-note@+1 {{defined as threadprivate or thread local}}
+#pragma omp threadprivate(sii)
+static int globalii;
+
+int test_iteration_spaces() {
+ const int N = 100;
+ float a[N], b[N], c[N];
+ int ii, jj, kk;
+ float fii;
+ double dii;
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; i += 1) {
+ c[i] = a[i] + b[i];
+ }
+#pragma omp target teams distribute parallel for
+ for (char i = 0; i < 10; i++) {
+ c[i] = a[i] + b[i];
+ }
+#pragma omp target teams distribute parallel for
+ for (char i = 0; i < 10; i += '\1') {
+ c[i] = a[i] + b[i];
+ }
+#pragma omp target teams distribute parallel for
+ for (long long i = 0; i < 10; i++) {
+ c[i] = a[i] + b[i];
+ }
+#pragma omp target teams distribute parallel for
+// expected-error@+1 {{expression must have integral or unscoped enumeration type, not 'double'}}
+ for (long long i = 0; i < 10; i += 1.5) {
+ c[i] = a[i] + b[i];
+ }
+#pragma omp target teams distribute parallel for
+ for (long long i = 0; i < 'z'; i += 1u) {
+ c[i] = a[i] + b[i];
+ }
+#pragma omp target teams distribute parallel for
+// expected-error@+1 {{variable must be of integer or random access iterator type}}
+ for (float fi = 0; fi < 10.0; fi++) {
+ c[(int)fi] = a[(int)fi] + b[(int)fi];
+ }
+#pragma omp target teams distribute parallel for
+// expected-error@+1 {{variable must be of integer or random access iterator type}}
+ for (double fi = 0; fi < 10.0; fi++) {
+ c[(int)fi] = a[(int)fi] + b[(int)fi];
+ }
+#pragma omp target teams distribute parallel for
+// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (int &ref = ii; ref < 10; ref++) {
+ }
+#pragma omp target teams distribute parallel for
+// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (int i; i < 10; i++)
+ c[i] = a[i];
+
+#pragma omp target teams distribute parallel for
+// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (int i = 0, j = 0; i < 10; ++i)
+ c[i] = a[i];
+
+#pragma omp target teams distribute parallel for
+// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (; ii < 10; ++ii)
+ c[ii] = a[ii];
+
+#pragma omp target teams distribute parallel for
+// expected-warning@+2 {{expression result unused}}
+// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (ii + 1; ii < 10; ++ii)
+ c[ii] = a[ii];
+
+#pragma omp target teams distribute parallel for
+// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (c[ii] = 0; ii < 10; ++ii)
+ c[ii] = a[ii];
+
+#pragma omp target teams distribute parallel for
+// Ok to skip parenthesises.
+ for (((ii)) = 0; ii < 10; ++ii)
+ c[ii] = a[ii];
+
+#pragma omp target teams distribute parallel for
+// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
+ for (int i = 0; i; i++)
+ c[i] = a[i];
+
+#pragma omp target teams distribute parallel for
+// expected-error@+2 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'i'}}
+ for (int i = 0; jj < kk; ii++)
+ c[i] = a[i];
+
+#pragma omp target teams distribute parallel for
+// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
+ for (int i = 0; !!i; i++)
+ c[i] = a[i];
+
+#pragma omp target teams distribute parallel for
+// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
+ for (int i = 0; i != 1; i++)
+ c[i] = a[i];
+
+#pragma omp target teams distribute parallel for
+// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
+ for (int i = 0;; i++)
+ c[i] = a[i];
+
+// Ok.
+#pragma omp target teams distribute parallel for
+ for (int i = 11; i > 10; i--)
+ c[i] = a[i];
+
+// Ok.
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i)
+ c[i] = a[i];
+
+// Ok.
+#pragma omp target teams distribute parallel for
+ for (ii = 0; ii < 10; ++ii)
+ c[ii] = a[ii];
+
+#pragma omp target teams distribute parallel for
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+ for (ii = 0; ii < 10; ++jj)
+ c[ii] = a[jj];
+
+#pragma omp target teams distribute parallel for
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+ for (ii = 0; ii < 10; ++++ii)
+ c[ii] = a[ii];
+
+// Ok but undefined behavior (in general, cannot check that incr
+// is really loop-invariant).
+#pragma omp target teams distribute parallel for
+ for (ii = 0; ii < 10; ii = ii + ii)
+ c[ii] = a[ii];
+
+#pragma omp target teams distribute parallel for
+// expected-error@+1 {{expression must have integral or unscoped enumeration type, not 'float'}}
+ for (ii = 0; ii < 10; ii = ii + 1.0f)
+ c[ii] = a[ii];
+
+// Ok - step was converted to integer type.
+#pragma omp target teams distribute parallel for
+ for (ii = 0; ii < 10; ii = ii + (int)1.1f)
+ c[ii] = a[ii];
+
+#pragma omp target teams distribute parallel for
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+ for (ii = 0; ii < 10; jj = ii + 2)
+ c[ii] = a[ii];
+
+#pragma omp target teams distribute parallel for
+// expected-warning@+2 {{relational comparison result unused}}
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+ for (ii = 0; ii<10; jj> kk + 2)
+ c[ii] = a[ii];
+
+#pragma omp target teams distribute parallel for
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+ for (ii = 0; ii < 10;)
+ c[ii] = a[ii];
+
+#pragma omp target teams distribute parallel for
+// expected-warning@+2 {{expression result unused}}
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+ for (ii = 0; ii < 10; !ii)
+ c[ii] = a[ii];
+
+#pragma omp target teams distribute parallel for
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+ for (ii = 0; ii < 10; ii ? ++ii : ++jj)
+ c[ii] = a[ii];
+
+#pragma omp target teams distribute parallel for
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+ for (ii = 0; ii < 10; ii = ii < 10)
+ c[ii] = a[ii];
+
+#pragma omp target teams distribute parallel for
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}}
+ for (ii = 0; ii < 10; ii = ii + 0)
+ c[ii] = a[ii];
+
+#pragma omp target teams distribute parallel for
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}}
+ for (ii = 0; ii < 10; ii = ii + (int)(0.8 - 0.45))
+ c[ii] = a[ii];
+
+#pragma omp target teams distribute parallel for
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}}
+ for (ii = 0; (ii) < 10; ii -= 25)
+ c[ii] = a[ii];
+
+#pragma omp target teams distribute parallel for
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}}
+ for (ii = 0; (ii < 10); ii -= 0)
+ c[ii] = a[ii];
+
+#pragma omp target teams distribute parallel for
+// expected-note@+2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+1 {{increment expression must cause 'ii' to decrease on each iteration of OpenMP for loop}}
+ for (ii = 0; ii > 10; (ii += 0))
+ c[ii] = a[ii];
+
+#pragma omp target teams distribute parallel for
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}}
+ for (ii = 0; ii < 10; (ii) = (1 - 1) + (ii))
+ c[ii] = a[ii];
+
+#pragma omp target teams distribute parallel for
+// expected-note@+2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+1 {{increment expression must cause 'ii' to decrease on each iteration of OpenMP for loop}}
+ for ((ii = 0); ii > 10; (ii -= 0))
+ c[ii] = a[ii];
+
+#pragma omp target teams distribute parallel for
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}}
+ for (ii = 0; (ii < 10); (ii -= 0))
+ c[ii] = a[ii];
+
+#pragma omp target teams distribute parallel for firstprivate(ii) // expected-note {{defined as firstprivate}}
+// expected-error@+1 {{loop iteration variable in the associated loop of 'omp target teams distribute parallel for' directive may not be firstprivate, predetermined as private}}
+ for (ii = 0; ii < 10; ii++)
+ c[ii] = a[ii];
+
+#pragma omp target teams distribute parallel for private(ii) // OK
+ for (ii = 0; ii < 10; ii++)
+ c[ii] = a[ii];
+
+#pragma omp target teams distribute parallel for lastprivate(ii) // OK
+ for (ii = 0; ii < 10; ii++)
+ c[ii] = a[ii];
+
+#pragma omp target teams distribute parallel for
+// expected-error@+1 {{loop iteration variable in the associated loop of 'omp target teams distribute parallel for' directive may not be threadprivate or thread local, predetermined as private}}
+ for (sii = 0; sii < 10; sii++)
+ c[sii] = a[sii];
+
+ {
+#pragma omp target teams distribute parallel for collapse(2)
+ for (ii = 0; ii < 10; ii += 1)
+ for (globalii = 0; globalii < 10; globalii += 1)
+ c[globalii] += a[globalii] + ii;
+ }
+
+#pragma omp target teams distribute parallel for
+// expected-error@+1 {{statement after '#pragma omp target teams distribute parallel for' must be a for loop}}
+ for (auto &item : a) {
+ item = item + 1;
+ }
+
+#pragma omp target teams distribute parallel for
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'i' to increase on each iteration of OpenMP for loop}}
+ for (unsigned i = 9; i < 10; i--) {
+ c[i] = a[i] + b[i];
+ }
+
+ int(*lb)[4] = nullptr;
+#pragma omp target teams distribute parallel for
+ for (int(*p)[4] = lb; p < lb + 8; ++p) {
+ }
+
+#pragma omp target teams distribute parallel for
+// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (int a{0}; a < 10; ++a) {
+ }
+
+ return 0;
+}
+
+// Iterators allowed in openmp for-loops.
+namespace std {
+struct random_access_iterator_tag {};
+template <class Iter>
+struct iterator_traits {
+ typedef typename Iter::difference_type difference_type;
+ typedef typename Iter::iterator_category iterator_category;
+};
+template <class Iter>
+typename iterator_traits<Iter>::difference_type
+distance(Iter first, Iter last) { return first - last; }
+}
+class Iter0 {
+public:
+ Iter0() {}
+ Iter0(const Iter0 &) {}
+ Iter0 operator++() { return *this; }
+ Iter0 operator--() { return *this; }
+ bool operator<(Iter0 a) { return true; }
+};
+// expected-note@+2 {{candidate function not viable: no known conversion from 'GoodIter' to 'Iter0' for 1st argument}}
+// expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'Iter0' for 1st argument}}
+int operator-(Iter0 a, Iter0 b) { return 0; }
+class Iter1 {
+public:
+ Iter1(float f = 0.0f, double d = 0.0) {}
+ Iter1(const Iter1 &) {}
+ Iter1 operator++() { return *this; }
+ Iter1 operator--() { return *this; }
+ bool operator<(Iter1 a) { return true; }
+ bool operator>=(Iter1 a) { return false; }
+};
+class GoodIter {
+public:
+ GoodIter() {}
+ GoodIter(const GoodIter &) {}
+ GoodIter(int fst, int snd) {}
+ GoodIter &operator=(const GoodIter &that) { return *this; }
+ GoodIter &operator=(const Iter0 &that) { return *this; }
+ GoodIter &operator+=(int x) { return *this; }
+ explicit GoodIter(void *) {}
+ GoodIter operator++() { return *this; }
+ GoodIter operator--() { return *this; }
+ bool operator!() { return true; }
+ bool operator<(GoodIter a) { return true; }
+ bool operator<=(GoodIter a) { return true; }
+ bool operator>=(GoodIter a) { return false; }
+ typedef int difference_type;
+ typedef std::random_access_iterator_tag iterator_category;
+};
+// expected-note@+2 {{candidate function not viable: no known conversion from 'const Iter0' to 'GoodIter' for 2nd argument}}
+// expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'GoodIter' for 1st argument}}
+int operator-(GoodIter a, GoodIter b) { return 0; }
+// expected-note@+1 3 {{candidate function not viable: requires single argument 'a', but 2 arguments were provided}}
+GoodIter operator-(GoodIter a) { return a; }
+// expected-note@+2 {{candidate function not viable: no known conversion from 'const Iter0' to 'int' for 2nd argument}}
+// expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'GoodIter' for 1st argument}}
+GoodIter operator-(GoodIter a, int v) { return GoodIter(); }
+// expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter0' to 'GoodIter' for 1st argument}}
+GoodIter operator+(GoodIter a, int v) { return GoodIter(); }
+// expected-note@+2 {{candidate function not viable: no known conversion from 'GoodIter' to 'int' for 1st argument}}
+// expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'int' for 1st argument}}
+GoodIter operator-(int v, GoodIter a) { return GoodIter(); }
+// expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter0' to 'int' for 1st argument}}
+GoodIter operator+(int v, GoodIter a) { return GoodIter(); }
+
+int test_with_random_access_iterator() {
+ GoodIter begin, end;
+ Iter0 begin0, end0;
+#pragma omp target teams distribute parallel for
+ for (GoodIter I = begin; I < end; ++I)
+ ++I;
+#pragma omp target teams distribute parallel for
+// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (GoodIter &I = begin; I < end; ++I)
+ ++I;
+#pragma omp target teams distribute parallel for
+ for (GoodIter I = begin; I >= end; --I)
+ ++I;
+#pragma omp target teams distribute parallel for
+// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (GoodIter I(begin); I < end; ++I)
+ ++I;
+#pragma omp target teams distribute parallel for
+// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (GoodIter I(nullptr); I < end; ++I)
+ ++I;
+#pragma omp target teams distribute parallel for
+// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (GoodIter I(0); I < end; ++I)
+ ++I;
+#pragma omp target teams distribute parallel for
+// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (GoodIter I(1, 2); I < end; ++I)
+ ++I;
+#pragma omp target teams distribute parallel for
+ for (begin = GoodIter(0); begin < end; ++begin)
+ ++begin;
+#pragma omp target teams distribute parallel for
+// expected-error@+2 {{invalid operands to binary expression ('GoodIter' and 'const Iter0')}}
+// expected-error@+1 {{could not calculate number of iterations calling 'operator-' with upper and lower loop bounds}}
+ for (begin = begin0; begin < end; ++begin)
+ ++begin;
+#pragma omp target teams distribute parallel for
+// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (++begin; begin < end; ++begin)
+ ++begin;
+#pragma omp target teams distribute parallel for
+ for (begin = end; begin < end; ++begin)
+ ++begin;
+#pragma omp target teams distribute parallel for
+// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'I'}}
+ for (GoodIter I = begin; I - I; ++I)
+ ++I;
+#pragma omp target teams distribute parallel for
+// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'I'}}
+ for (GoodIter I = begin; begin < end; ++I)
+ ++I;
+#pragma omp target teams distribute parallel for
+// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'I'}}
+ for (GoodIter I = begin; !I; ++I)
+ ++I;
+#pragma omp target teams distribute parallel for
+// expected-note@+2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+1 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}}
+ for (GoodIter I = begin; I >= end; I = I + 1)
+ ++I;
+#pragma omp target teams distribute parallel for
+ for (GoodIter I = begin; I >= end; I = I - 1)
+ ++I;
+#pragma omp target teams distribute parallel for
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'I'}}
+ for (GoodIter I = begin; I >= end; I = -I)
+ ++I;
+#pragma omp target teams distribute parallel for
+// expected-note@+2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+1 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}}
+ for (GoodIter I = begin; I >= end; I = 2 + I)
+ ++I;
+#pragma omp target teams distribute parallel for
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'I'}}
+ for (GoodIter I = begin; I >= end; I = 2 - I)
+ ++I;
+#pragma omp target teams distribute parallel for
+// expected-error@+1 {{invalid operands to binary expression ('Iter0' and 'int')}}
+ for (Iter0 I = begin0; I < end0; ++I)
+ ++I;
+#pragma omp target teams distribute parallel for
+// Initializer is constructor without params.
+// expected-error@+2 {{invalid operands to binary expression ('Iter0' and 'int')}}
+// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (Iter0 I; I < end0; ++I)
+ ++I;
+ Iter1 begin1, end1;
+#pragma omp target teams distribute parallel for
+// expected-error@+2 {{invalid operands to binary expression ('Iter1' and 'Iter1')}}
+// expected-error@+1 {{could not calculate number of iterations calling 'operator-' with upper and lower loop bounds}}
+ for (Iter1 I = begin1; I < end1; ++I)
+ ++I;
+#pragma omp target teams distribute parallel for
+// expected-note@+2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+1 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}}
+ for (Iter1 I = begin1; I >= end1; ++I)
+ ++I;
+#pragma omp target teams distribute parallel for
+// expected-error@+4 {{invalid operands to binary expression ('Iter1' and 'float')}}
+// expected-error@+3 {{could not calculate number of iterations calling 'operator-' with upper and lower loop bounds}}
+// Initializer is constructor with all default params.
+// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (Iter1 I; I < end1; ++I) {
+ }
+ return 0;
+}
+
+template <typename IT, int ST>
+class TC {
+public:
+ int dotest_lt(IT begin, IT end) {
+#pragma omp target teams distribute parallel for
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'I' to increase on each iteration of OpenMP for loop}}
+ for (IT I = begin; I < end; I = I + ST) {
+ ++I;
+ }
+#pragma omp target teams distribute parallel for
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'I' to increase on each iteration of OpenMP for loop}}
+ for (IT I = begin; I <= end; I += ST) {
+ ++I;
+ }
+#pragma omp target teams distribute parallel for
+ for (IT I = begin; I < end; ++I) {
+ ++I;
+ }
+ }
+
+ static IT step() {
+ return IT(ST);
+ }
+};
+template <typename IT, int ST = 0>
+int dotest_gt(IT begin, IT end) {
+#pragma omp target teams distribute parallel for
+// expected-note@+2 2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+1 2 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}}
+ for (IT I = begin; I >= end; I = I + ST) {
+ ++I;
+ }
+#pragma omp target teams distribute parallel for
+// expected-note@+2 2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+1 2 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}}
+ for (IT I = begin; I >= end; I += ST) {
+ ++I;
+ }
+
+#pragma omp target teams distribute parallel for
+// expected-note@+2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+1 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}}
+ for (IT I = begin; I >= end; ++I) {
+ ++I;
+ }
+
+#pragma omp target teams distribute parallel for
+ for (IT I = begin; I < end; I += TC<int, ST>::step()) {
+ ++I;
+ }
+}
+
+void test_with_template() {
+ GoodIter begin, end;
+ TC<GoodIter, 100> t1;
+ TC<GoodIter, -100> t2;
+ t1.dotest_lt(begin, end);
+ t2.dotest_lt(begin, end); // expected-note {{in instantiation of member function 'TC<GoodIter, -100>::dotest_lt' requested here}}
+ dotest_gt(begin, end); // expected-note {{in instantiation of function template specialization 'dotest_gt<GoodIter, 0>' requested here}}
+ dotest_gt<unsigned, -10>(0, 100); // expected-note {{in instantiation of function template specialization 'dotest_gt<unsigned int, -10>' requested here}}
+}
+
+void test_loop_break() {
+ const int N = 100;
+ float a[N], b[N], c[N];
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; i++) {
+ c[i] = a[i] + b[i];
+ for (int j = 0; j < 10; ++j) {
+ if (a[i] > b[j])
+ break; // OK in nested loop
+ }
+ switch (i) {
+ case 1:
+ b[i]++;
+ break;
+ default:
+ break;
+ }
+ if (c[i] > 10)
+ break; // expected-error {{'break' statement cannot be used in OpenMP for loop}}
+
+ if (c[i] > 11)
+ break; // expected-error {{'break' statement cannot be used in OpenMP for loop}}
+ }
+
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; i++) {
+ for (int j = 0; j < 10; j++) {
+ c[i] = a[i] + b[i];
+ if (c[i] > 10) {
+ if (c[i] < 20) {
+ break; // OK
+ }
+ }
+ }
+ }
+}
+
+void test_loop_eh() {
+ const int N = 100;
+ float a[N], b[N], c[N];
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; i++) {
+ c[i] = a[i] + b[i];
+ try { // OK
+ for (int j = 0; j < 10; ++j) {
+ if (a[i] > b[j])
+ throw a[i]; // OK
+ }
+ throw a[i]; // OK
+ } catch (float f) {
+ if (f > 0.1)
+ throw a[i]; // OK
+ return; // expected-error {{cannot return from OpenMP region}}
+ }
+ switch (i) {
+ case 1:
+ b[i]++;
+ break;
+ default:
+ break;
+ }
+ for (int j = 0; j < 10; j++) {
+ if (c[i] > 10)
+ throw c[i]; // OK
+ }
+ }
+ if (c[9] > 10)
+ throw c[9]; // OK
+
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+ struct S {
+ void g() { throw 0; }
+ };
+ }
+}
+
+void test_loop_firstprivate_lastprivate() {
+ S s(4);
+#pragma omp target teams distribute parallel for lastprivate(s) firstprivate(s)
+ for (int i = 0; i < 16; ++i)
+ ;
+}
+
+void test_ordered() {
+#pragma omp target teams distribute parallel for ordered // expected-error {{unexpected OpenMP clause 'ordered' in directive '#pragma omp target teams distribute parallel for'}}
+ for (int i = 0; i < 16; ++i)
+ ;
+}
+
+void test_nowait() {
+#pragma omp target teams distribute parallel for nowait nowait // expected-error {{directive '#pragma omp target teams distribute parallel for' cannot contain more than one 'nowait' clause}}
+ for (int i = 0; i < 16; ++i)
+ ;
+}
+
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_map_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_map_messages.cpp
new file mode 100644
index 000000000000..326db95f90f8
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_map_messages.cpp
@@ -0,0 +1,281 @@
+// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note 2 {{declared here}}
+extern S1 a;
+class S2 {
+ mutable int a;
+public:
+ S2():a(0) { }
+ S2(S2 &s2):a(s2.a) { }
+ static float S2s; // expected-note 4 {{mappable type cannot contain static members}}
+ static const float S2sc; // expected-note 4 {{mappable type cannot contain static members}}
+};
+const float S2::S2sc = 0;
+const S2 b;
+const S2 ba[5];
+class S3 {
+ int a;
+public:
+ S3():a(0) { }
+ S3(S3 &s3):a(s3.a) { }
+};
+const S3 c;
+const S3 ca[5];
+extern const int f;
+class S4 {
+ int a;
+ S4();
+ S4(const S4 &s4);
+public:
+ S4(int v):a(v) { }
+};
+class S5 {
+ int a;
+ S5():a(0) {}
+ S5(const S5 &s5):a(s5.a) { }
+public:
+ S5(int v):a(v) { }
+};
+
+S3 h;
+#pragma omp threadprivate(h) // expected-note 2 {{defined as threadprivate or thread local}}
+
+typedef int from;
+
+template <typename T, int I> // expected-note {{declared here}}
+T tmain(T argc) {
+ const T d = 5;
+ const T da[5] = { 0 };
+ S4 e(4);
+ S5 g(5);
+ T i, t[20];
+ T &j = i;
+ T *k = &j;
+ T x;
+ T y;
+ T to, tofrom, always;
+ const T (&l)[5] = da;
+
+
+#pragma omp target teams distribute parallel for map // expected-error {{expected '(' after 'map'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map( // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map() // expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(alloc) // expected-error {{use of undeclared identifier 'alloc'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(to argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected ',' or ')' in 'map' clause}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(to:) // expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(from: argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(x: y) // expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(l[-1:]) // expected-error 2 {{array section must be a subset of the original array}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(l[:-1]) // expected-error 2 {{section length is evaluated to a negative value -1}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(x)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(tofrom: t[:I])
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(T: a) // expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}} expected-error {{incomplete type 'S1' where a complete type is required}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(T) // expected-error {{'T' does not refer to a value}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(I) // expected-error 2 {{expected expression containing only member accesses and/or array sections based on named variables}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(S2::S2s)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(S2::S2sc)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(x)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(to: x)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(to: to)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(to)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(to, x)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(to x) // expected-error {{expected ',' or ')' in 'map' clause}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(tofrom: argc > 0 ? x : y) // expected-error 2 {{expected expression containing only member accesses and/or array sections based on named variables}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(argc)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(S1) // expected-error {{'S1' does not refer to a value}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(a, b, c, d, f) // expected-error {{incomplete type 'S1' where a complete type is required}} expected-error 2 {{type 'S2' is not mappable to target}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(ba) // expected-error 2 {{type 'S2' is not mappable to target}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(ca)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(da)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(S2::S2s)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(S2::S2sc)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(e, g)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(h) // expected-error {{threadprivate variables are not allowed in 'map' clause}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(k), map(k) // expected-error 2 {{variable already marked as mapped in current construct}} expected-note 2 {{used here}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(k), map(k[:5]) // expected-error 2 {{pointer cannot be mapped along with a section derived from itself}} expected-note 2 {{used here}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(da)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(da[:4])
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target data map(k, j, l) // expected-note 2 {{used here}}
+#pragma omp target teams distribute parallel for map(k[:4]) // expected-error 2 {{pointer cannot be mapped along with a section derived from itself}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(j)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(l) map(l[:5]) // expected-error 2 {{variable already marked as mapped in current construct}} expected-note 2 {{used here}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target data map(k[:4], j, l[:5]) // expected-note 2 {{used here}}
+{
+#pragma omp target teams distribute parallel for map(k) // expected-error 2 {{pointer cannot be mapped along with a section derived from itself}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(j)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(l)
+ for (i = 0; i < argc; ++i) foo();
+}
+
+#pragma omp target teams distribute parallel for map(always, tofrom: x)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(always: x) // expected-error {{missing map type}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always'}} expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(always, tofrom: always, tofrom, x)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(tofrom j) // expected-error {{expected ',' or ')' in 'map' clause}}
+ for (i = 0; i < argc; ++i) foo();
+
+ return 0;
+}
+
+int main(int argc, char **argv) {
+ const int d = 5;
+ const int da[5] = { 0 };
+ S4 e(4);
+ S5 g(5);
+ int i;
+ int &j = i;
+ int *k = &j;
+ int x;
+ int y;
+ int to, tofrom, always;
+ const int (&l)[5] = da;
+
+#pragma omp target teams distribute parallel for map // expected-error {{expected '(' after 'map'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map( // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map() // expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(alloc) // expected-error {{use of undeclared identifier 'alloc'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(to argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected ',' or ')' in 'map' clause}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(to:) // expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(from: argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(x: y) // expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(l[-1:]) // expected-error {{array section must be a subset of the original array}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(l[:-1]) // expected-error {{section length is evaluated to a negative value -1}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(x)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(to: x)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(to: to)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(to)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(to, x)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(to x) // expected-error {{expected ',' or ')' in 'map' clause}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(tofrom: argc > 0 ? argv[1] : argv[2]) // expected-error {{expected expression containing only member accesses and/or array sections based on named variables}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(argc)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(S1) // expected-error {{'S1' does not refer to a value}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(a, b, c, d, f) // expected-error {{incomplete type 'S1' where a complete type is required}} expected-error 2 {{type 'S2' is not mappable to target}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(argv[1])
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(ba) // expected-error 2 {{type 'S2' is not mappable to target}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(ca)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(da)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(S2::S2s)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(S2::S2sc)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(e, g)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(h) // expected-error {{threadprivate variables are not allowed in 'map' clause}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(k), map(k) // expected-error {{variable already marked as mapped in current construct}} expected-note {{used here}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(k), map(k[:5]) // expected-error {{pointer cannot be mapped along with a section derived from itself}} expected-note {{used here}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(da)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(da[:4])
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target data map(k, j, l) // expected-note {{used here}}
+#pragma omp target teams distribute parallel for map(k[:4]) // expected-error {{pointer cannot be mapped along with a section derived from itself}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(j)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(l) map(l[:5]) // expected-error 1 {{variable already marked as mapped in current construct}} expected-note 1 {{used here}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target data map(k[:4], j, l[:5]) // expected-note {{used here}}
+{
+#pragma omp target teams distribute parallel for map(k) // expected-error {{pointer cannot be mapped along with a section derived from itself}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(j)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(l)
+ for (i = 0; i < argc; ++i) foo();
+}
+
+#pragma omp target teams distribute parallel for map(always, tofrom: x)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(always: x) // expected-error {{missing map type}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always'}} expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(always, tofrom: always, tofrom, x)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for map(tofrom j) // expected-error {{expected ',' or ')' in 'map' clause}}
+ for (i = 0; i < argc; ++i) foo();
+
+ return tmain<int, 3>(argc)+tmain<from, 4>(argc); // expected-note {{in instantiation of function template specialization 'tmain<int, 3>' requested here}} expected-note {{in instantiation of function template specialization 'tmain<int, 4>' requested here}}
+}
+
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_messages.cpp
new file mode 100644
index 000000000000..cb76ef2e0124
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_messages.cpp
@@ -0,0 +1,92 @@
+// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+
+void foo() {
+}
+
+static int pvt;
+#pragma omp threadprivate(pvt)
+
+#pragma omp target teams distribute parallel for // expected-error {{unexpected OpenMP directive '#pragma omp target teams distribute parallel for'}}
+
+int main(int argc, char **argv) {
+#pragma omp target teams distribute parallel for { // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute parallel for' are ignored}}
+ for (int i = 0; i < argc; ++i)
+ foo();
+#pragma omp target teams distribute parallel for ( // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute parallel for' are ignored}}
+ for (int i = 0; i < argc; ++i)
+ foo();
+#pragma omp target teams distribute parallel for[ // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute parallel for' are ignored}}
+ for (int i = 0; i < argc; ++i)
+ foo();
+#pragma omp target teams distribute parallel for] // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute parallel for' are ignored}}
+ for (int i = 0; i < argc; ++i)
+ foo();
+#pragma omp target teams distribute parallel for) // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute parallel for' are ignored}}
+ for (int i = 0; i < argc; ++i)
+ foo();
+#pragma omp target teams distribute parallel for } // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute parallel for' are ignored}}
+ for (int i = 0; i < argc; ++i)
+ foo();
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < argc; ++i)
+ foo();
+// expected-warning@+1 {{extra tokens at the end of '#pragma omp target teams distribute parallel for' are ignored}}
+#pragma omp target teams distribute parallel for unknown()
+ for (int i = 0; i < argc; ++i)
+ foo();
+L1:
+ for (int i = 0; i < argc; ++i)
+ foo();
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < argc; ++i)
+ foo();
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < argc; ++i) {
+ goto L1; // expected-error {{use of undeclared label 'L1'}}
+ argc++;
+ }
+
+ for (int i = 0; i < 10; ++i) {
+ switch (argc) {
+ case (0):
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < argc; ++i) {
+ foo();
+ break; // expected-error {{'break' statement cannot be used in OpenMP for loop}}
+ continue;
+ }
+ default:
+ break;
+ }
+ }
+#pragma omp target teams distribute parallel for default(none)
+ for (int i = 0; i < 10; ++i)
+ ++argc; // expected-error {{ariable 'argc' must have explicitly specified data sharing attributes}}
+
+ goto L2; // expected-error {{use of undeclared label 'L2'}}
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < argc; ++i)
+ L2: foo();
+
+#pragma omp target teams distribute parallel for
+ for (int i = 0; i < argc; ++i) {
+ return 1; // expected-error {{cannot return from OpenMP region}}
+ }
+
+ [[]] // expected-error {{an attribute list cannot appear here}}
+#pragma omp target teams distribute parallel for
+ for (int n = 0; n < 100; ++n) {
+ }
+
+#pragma omp target teams distribute parallel for copyin(pvt) // expected-error {{unexpected OpenMP clause 'copyin' in directive '#pragma omp target teams distribute parallel for'}}
+ for (int n = 0; n < 100; ++n) {}
+
+ return 0;
+}
+
+void test_ordered() {
+#pragma omp target teams distribute parallel for ordered // expected-error {{unexpected OpenMP clause 'ordered' in directive '#pragma omp target teams distribute parallel for'}}
+ for (int i = 0; i < 16; ++i)
+ ;
+}
+
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_misc_messages.c b/test/OpenMP/target_teams_distribute_parallel_for_misc_messages.c
new file mode 100644
index 000000000000..769be6c10c3a
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_misc_messages.c
@@ -0,0 +1,312 @@
+// RUN: %clang_cc1 -fsyntax-only -fopenmp -verify %s
+
+// expected-error@+1 {{unexpected OpenMP directive '#pragma omp target teams distribute parallel for'}}
+#pragma omp target teams distribute parallel for
+
+// expected-error@+1 {{unexpected OpenMP directive '#pragma omp target teams distribute parallel for'}}
+#pragma omp target teams distribute parallel for foo
+
+void test_no_clause() {
+ int i;
+#pragma omp target teams distribute parallel for
+ for (i = 0; i < 16; ++i)
+ ;
+
+// expected-error@+2 {{statement after '#pragma omp target teams distribute parallel for' must be a for loop}}
+#pragma omp target teams distribute parallel for
+ ++i;
+}
+
+void test_branch_protected_scope() {
+ int i = 0;
+L1:
+ ++i;
+
+ int x[24];
+
+#pragma omp target teams distribute parallel for
+ for (i = 0; i < 16; ++i) {
+ if (i == 5)
+ goto L1; // expected-error {{use of undeclared label 'L1'}}
+ else if (i == 6)
+ return; // expected-error {{cannot return from OpenMP region}}
+ else if (i == 7)
+ goto L2;
+ else if (i == 8) {
+ L2:
+ x[i]++;
+ }
+ }
+
+ if (x[0] == 0)
+ goto L2; // expected-error {{use of undeclared label 'L2'}}
+ else if (x[1] == 1)
+ goto L1;
+}
+
+void test_invalid_clause() {
+ int i;
+// expected-warning@+1 {{extra tokens at the end of '#pragma omp target teams distribute parallel for' are ignored}}
+#pragma omp target teams distribute parallel for foo bar
+ for (i = 0; i < 16; ++i)
+ ;
+}
+
+void test_non_identifiers() {
+ int i, x;
+
+// expected-warning@+1 {{extra tokens at the end of '#pragma omp target teams distribute parallel for' are ignored}}
+#pragma omp target teams distribute parallel for;
+ for (i = 0; i < 16; ++i)
+ ;
+
+// expected-warning@+1 {{extra tokens at the end of '#pragma omp target teams distribute parallel for' are ignored}}
+#pragma omp target teams distribute parallel for private(x);
+ for (i = 0; i < 16; ++i)
+ ;
+
+// expected-warning@+1 {{extra tokens at the end of '#pragma omp target teams distribute parallel for' are ignored}}
+#pragma omp target teams distribute parallel for, private(x);
+ for (i = 0; i < 16; ++i)
+ ;
+}
+
+extern int foo();
+
+void test_collapse() {
+ int i;
+// expected-error@+1 {{expected '('}}
+#pragma omp target teams distribute parallel for collapse
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expected expression}} expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
+#pragma omp target teams distribute parallel for collapse(
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expected expression}}
+#pragma omp target teams distribute parallel for collapse()
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expected expression}} expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
+#pragma omp target teams distribute parallel for collapse(,
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expected expression}} expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
+#pragma omp target teams distribute parallel for collapse(, )
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-warning@+2 {{extra tokens at the end of '#pragma omp target teams distribute parallel for' are ignored}}
+// expected-error@+1 {{expected '('}}
+#pragma omp target teams distribute parallel for collapse 4)
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+2 {{expected ')'}}
+// expected-note@+1 {{to match this '('}} expected-note@+1 {{as specified in 'collapse' clause}}
+#pragma omp target teams distribute parallel for collapse(4
+ for (i = 0; i < 16; ++i)
+ ; // expected-error {{expected 4 for loops after '#pragma omp target teams distribute parallel for', but found only 1}}
+// expected-error@+2 {{expected ')'}}
+// expected-note@+1 {{to match this '('}} expected-note@+1 {{as specified in 'collapse' clause}}
+#pragma omp target teams distribute parallel for collapse(4,
+ for (i = 0; i < 16; ++i)
+ ; // expected-error {{expected 4 for loops after '#pragma omp target teams distribute parallel for', but found only 1}}
+// expected-error@+2 {{expected ')'}}
+// expected-note@+1 {{to match this '('}} expected-note@+1 {{as specified in 'collapse' clause}}
+#pragma omp target teams distribute parallel for collapse(4, )
+ for (i = 0; i < 16; ++i)
+ ; // expected-error {{expected 4 for loops after '#pragma omp target teams distribute parallel for', but found only 1}}
+// expected-note@+1 {{as specified in 'collapse' clause}}
+#pragma omp target teams distribute parallel for collapse(4)
+ for (i = 0; i < 16; ++i)
+ ; // expected-error {{expected 4 for loops after '#pragma omp target teams distribute parallel for', but found only 1}}
+// expected-error@+2 {{expected ')'}}
+// expected-note@+1 {{to match this '('}} expected-note@+1 {{as specified in 'collapse' clause}}
+#pragma omp target teams distribute parallel for collapse(4 4)
+ for (i = 0; i < 16; ++i)
+ ; // expected-error {{expected 4 for loops after '#pragma omp target teams distribute parallel for', but found only 1}}
+// expected-error@+2 {{expected ')'}}
+// expected-note@+1 {{to match this '('}} expected-note@+1 {{as specified in 'collapse' clause}}
+#pragma omp target teams distribute parallel for collapse(4, , 4)
+ for (i = 0; i < 16; ++i)
+ ; // expected-error {{expected 4 for loops after '#pragma omp target teams distribute parallel for', but found only 1}}
+#pragma omp target teams distribute parallel for collapse(4)
+ for (int i1 = 0; i1 < 16; ++i1)
+ for (int i2 = 0; i2 < 16; ++i2)
+ for (int i3 = 0; i3 < 16; ++i3)
+ for (int i4 = 0; i4 < 16; ++i4)
+ foo();
+// expected-error@+2 {{expected ')'}}
+// expected-note@+1 {{to match this '('}} expected-note@+1 {{as specified in 'collapse' clause}}
+#pragma omp target teams distribute parallel for collapse(4, 8)
+ for (i = 0; i < 16; ++i)
+ ; // expected-error {{expected 4 for loops after '#pragma omp target teams distribute parallel for', but found only 1}}
+// expected-error@+1 {{expression is not an integer constant expression}}
+#pragma omp target teams distribute parallel for collapse(2.5)
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expression is not an integer constant expression}}
+#pragma omp target teams distribute parallel for collapse(foo())
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{argument to 'collapse' clause must be a strictly positive integer value}}
+#pragma omp target teams distribute parallel for collapse(-5)
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{argument to 'collapse' clause must be a strictly positive integer value}}
+#pragma omp target teams distribute parallel for collapse(0)
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{argument to 'collapse' clause must be a strictly positive integer value}}
+#pragma omp target teams distribute parallel for collapse(5 - 5)
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+3 {{loop iteration variable in the associated loop of 'omp target teams distribute parallel for' directive may not be firstprivate, predetermined as private}}
+// expected-note@+1 {{defined as firstprivate}}
+#pragma omp target teams distribute parallel for collapse(2) firstprivate(i)
+ for (i = 0; i < 16; ++i)
+ for (int j = 0; j < 16; ++j)
+#pragma omp parallel for reduction(+ : i, j)
+ for (int k = 0; k < 16; ++k)
+ i += j;
+}
+
+void test_private() {
+ int i;
+// expected-error@+2 {{expected expression}}
+// expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
+#pragma omp target teams distribute parallel for private(
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+2 {{expected ')'}} expected-note@+2 {{to match this '('}}
+// expected-error@+1 2 {{expected expression}}
+#pragma omp target teams distribute parallel for private(,
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 2 {{expected expression}}
+#pragma omp target teams distribute parallel for private(, )
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expected expression}}
+#pragma omp target teams distribute parallel for private()
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expected expression}}
+#pragma omp target teams distribute parallel for private(int)
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expected variable name}}
+#pragma omp target teams distribute parallel for private(0)
+ for (i = 0; i < 16; ++i)
+ ;
+
+ int x, y, z;
+#pragma omp target teams distribute parallel for private(x)
+ for (i = 0; i < 16; ++i)
+ ;
+#pragma omp target teams distribute parallel for private(x, y)
+ for (i = 0; i < 16; ++i)
+ ;
+#pragma omp target teams distribute parallel for private(x, y, z)
+ for (i = 0; i < 16; ++i) {
+ x = y * i + z;
+ }
+}
+
+void test_lastprivate() {
+ int i;
+// expected-error@+2 {{expected ')'}} expected-note@+2 {{to match this '('}}
+// expected-error@+1 {{expected expression}}
+#pragma omp target teams distribute parallel for lastprivate(
+ for (i = 0; i < 16; ++i)
+ ;
+
+// expected-error@+2 {{expected ')'}} expected-note@+2 {{to match this '('}}
+// expected-error@+1 2 {{expected expression}}
+#pragma omp target teams distribute parallel for lastprivate(,
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 2 {{expected expression}}
+#pragma omp target teams distribute parallel for lastprivate(, )
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expected expression}}
+#pragma omp target teams distribute parallel for lastprivate()
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expected expression}}
+#pragma omp target teams distribute parallel for lastprivate(int)
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expected variable name}}
+#pragma omp target teams distribute parallel for lastprivate(0)
+ for (i = 0; i < 16; ++i)
+ ;
+
+ int x, y, z;
+#pragma omp target teams distribute parallel for lastprivate(x)
+ for (i = 0; i < 16; ++i)
+ ;
+#pragma omp target teams distribute parallel for lastprivate(x, y)
+ for (i = 0; i < 16; ++i)
+ ;
+#pragma omp target teams distribute parallel for lastprivate(x, y, z)
+ for (i = 0; i < 16; ++i)
+ ;
+}
+
+void test_firstprivate() {
+ int i;
+// expected-error@+2 {{expected ')'}} expected-note@+2 {{to match this '('}}
+// expected-error@+1 {{expected expression}}
+#pragma omp target teams distribute parallel for firstprivate(
+ for (i = 0; i < 16; ++i)
+ ;
+
+// expected-error@+2 {{expected ')'}} expected-note@+2 {{to match this '('}}
+// expected-error@+1 2 {{expected expression}}
+#pragma omp target teams distribute parallel for firstprivate(,
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 2 {{expected expression}}
+#pragma omp target teams distribute parallel for firstprivate(, )
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expected expression}}
+#pragma omp target teams distribute parallel for firstprivate()
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expected expression}}
+#pragma omp target teams distribute parallel for firstprivate(int)
+ for (i = 0; i < 16; ++i)
+ ;
+// expected-error@+1 {{expected variable name}}
+#pragma omp target teams distribute parallel for firstprivate(0)
+ for (i = 0; i < 16; ++i)
+ ;
+
+ int x, y, z;
+#pragma omp target teams distribute parallel for lastprivate(x) firstprivate(x)
+ for (i = 0; i < 16; ++i)
+ ;
+#pragma omp target teams distribute parallel for lastprivate(x, y) firstprivate(x, y)
+ for (i = 0; i < 16; ++i)
+ ;
+#pragma omp target teams distribute parallel for lastprivate(x, y, z) firstprivate(x, y, z)
+ for (i = 0; i < 16; ++i)
+ ;
+}
+
+void test_loop_messages() {
+ float a[100], b[100], c[100];
+// expected-error@+2 {{variable must be of integer or pointer type}}
+#pragma omp target teams distribute parallel for
+ for (float fi = 0; fi < 10.0; fi++) {
+ c[(int)fi] = a[(int)fi] + b[(int)fi];
+ }
+// expected-error@+2 {{variable must be of integer or pointer type}}
+#pragma omp target teams distribute parallel for
+ for (double fi = 0; fi < 10.0; fi++) {
+ c[(int)fi] = a[(int)fi] + b[(int)fi];
+ }
+}
+
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_nowait_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_nowait_messages.cpp
new file mode 100644
index 000000000000..30a622439dbf
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_nowait_messages.cpp
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -fopenmp %s
+
+void foo() {
+}
+
+int main(int argc, char **argv) {
+ int i;
+#pragma omp target teams distribute parallel for nowait( // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute parallel for' are ignored}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for nowait (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute parallel for' are ignored}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for nowait device (-10u)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for nowait (3.14) device (-10u) // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute parallel for' are ignored}}
+ for (i = 0; i < argc; ++i) foo();
+
+ return 0;
+}
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
new file mode 100644
index 000000000000..fdc2d9c25918
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_num_teams_messages.cpp
@@ -0,0 +1,85 @@
+// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 100 -o - %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note 2 {{declared here}}
+
+template <typename T, int C> // expected-note {{declared here}}
+T tmain(T argc) {
+ char **a;
+#pragma omp target teams distribute parallel for num_teams(C)
+ for (int i=0; i<100; i++) foo();
+#pragma omp target teams distribute parallel for num_teams(T) // expected-error {{'T' does not refer to a value}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target teams distribute parallel for num_teams // expected-error {{expected '(' after 'num_teams'}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target teams distribute parallel for num_teams( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target teams distribute parallel for num_teams() // expected-error {{expected expression}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target teams distribute parallel for num_teams(argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target teams distribute parallel for num_teams(argc)) // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute parallel for' are ignored}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target teams distribute parallel for num_teams(argc > 0 ? a[1] : a[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target teams distribute parallel for num_teams(argc + argc)
+ for (int i=0; i<100; i++) foo();
+#pragma omp target teams distribute parallel for num_teams(argc), num_teams (argc+1) // expected-error {{directive '#pragma omp target teams distribute parallel for' cannot contain more than one 'num_teams' clause}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target teams distribute parallel for num_teams(S1) // expected-error {{'S1' does not refer to a value}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target teams distribute parallel for num_teams(-2) // expected-error {{argument to 'num_teams' clause must be a strictly positive integer value}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target teams distribute parallel for num_teams(-10u)
+ for (int i=0; i<100; i++) foo();
+#pragma omp target teams distribute parallel for num_teams(3.14) // expected-error 2 {{expression must have integral or unscoped enumeration type, not 'double'}}
+ for (int i=0; i<100; i++) foo();
+
+ return 0;
+}
+
+int main(int argc, char **argv) {
+#pragma omp target teams distribute parallel for num_teams // expected-error {{expected '(' after 'num_teams'}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target teams distribute parallel for num_teams ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target teams distribute parallel for num_teams () // expected-error {{expected expression}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target teams distribute parallel for num_teams (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target teams distribute parallel for num_teams (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute parallel for' are ignored}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target teams distribute parallel for num_teams (argc > 0 ? argv[1] : argv[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target teams distribute parallel for num_teams (argc + argc)
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target teams distribute parallel for num_teams (argc), num_teams (argc+1) // expected-error {{directive '#pragma omp target teams distribute parallel for' cannot contain more than one 'num_teams' clause}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target teams distribute parallel for num_teams (S1) // expected-error {{'S1' does not refer to a value}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target teams distribute parallel for num_teams (-2) // expected-error {{argument to 'num_teams' clause must be a strictly positive integer value}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target teams distribute parallel for num_teams (-10u)
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target teams distribute parallel for num_teams (3.14) // expected-error {{expression must have integral or unscoped enumeration type, not 'double'}}
+ for (int i=0; i<100; i++) foo();
+
+ return tmain<int, 10>(argc); // expected-note {{in instantiation of function template specialization 'tmain<int, 10>' requested here}}
+}
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
new file mode 100644
index 000000000000..afd8c367a0dc
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_num_threads_messages.cpp
@@ -0,0 +1,65 @@
+// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}}
+
+template <class T, typename S, int N> // expected-note {{declared here}}
+T tmain(T argc, S **argv) {
+ T i;
+#pragma omp target teams distribute parallel for num_threads // expected-error {{expected '(' after 'num_threads'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for num_threads ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for num_threads () // expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for num_threads (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for num_threads (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute parallel for' are ignored}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for num_threads ((argc > 0) ? argv[1] : argv[2]) // expected-error 2 {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for num_threads (foobool(argc)), num_threads (true), num_threads (-5) // expected-error 2 {{directive '#pragma omp target teams distribute parallel for' cannot contain more than one 'num_threads' clause}} expected-error {{argument to 'num_threads' clause must be a strictly positive integer value}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for num_threads (S) // expected-error {{'S' does not refer to a value}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for num_threads (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error 2 {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for num_threads (argc)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for num_threads (N) // expected-error {{argument to 'num_threads' clause must be a strictly positive integer value}}
+ for (i = 0; i < argc; ++i) foo();
+
+ return argc;
+}
+
+int main(int argc, char **argv) {
+ int i;
+#pragma omp target teams distribute parallel for num_threads // expected-error {{expected '(' after 'num_threads'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for num_threads ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for num_threads () // expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for num_threads (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for num_threads (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute parallel for' are ignored}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for num_threads (argc > 0 ? argv[1] : argv[2]) // expected-error {{integral }}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for num_threads (foobool(argc)), num_threads (true), num_threads (-5) // expected-error 2 {{directive '#pragma omp target teams distribute parallel for' cannot contain more than one 'num_threads' clause}} expected-error {{argument to 'num_threads' clause must be a strictly positive integer value}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for num_threads (S1) // expected-error {{'S1' does not refer to a value}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for num_threads (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target teams distribute parallel for num_threads (num_threads(tmain<int, char, -1>(argc, argv) // expected-error 2 {{expected ')'}} expected-note 2 {{to match this '('}} expected-note {{in instantiation of function template specialization 'tmain<int, char, -1>' requested here}}
+ for (i = 0; i < argc; ++i) foo();
+
+ return tmain<int, char, 3>(argc, argv); // expected-note {{in instantiation of function template specialization 'tmain<int, char, 3>' requested here}}
+}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_private_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_private_messages.cpp
new file mode 100644
index 000000000000..d89cb1aa846d
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_private_messages.cpp
@@ -0,0 +1,124 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}} expected-note {{forward declaration of 'S1'}}
+extern S1 a;
+class S2 {
+ mutable int a;
+public:
+ S2():a(0) { }
+ static float S2s; // expected-note {{predetermined as shared}}
+};
+const S2 b;
+const S2 ba[5];
+class S3 {
+ int a;
+public:
+ S3():a(0) { }
+};
+const S3 c; // expected-note {{predetermined as shared}}
+const S3 ca[5]; // expected-note {{predetermined as shared}}
+extern const int f; // expected-note {{predetermined as shared}}
+class S4 {
+ int a;
+ S4(); // expected-note {{implicitly declared private here}}
+public:
+ S4(int v):a(v) { }
+};
+class S5 {
+ int a;
+ S5():a(0) {} // expected-note {{implicitly declared private here}}
+public:
+ S5(int v):a(v) { }
+};
+
+S3 h;
+#pragma omp threadprivate(h) // expected-note {{defined as threadprivate or thread local}}
+
+
+int main(int argc, char **argv) {
+ const int d = 5; // expected-note {{predetermined as shared}}
+ const int da[5] = { 0 }; // expected-note {{predetermined as shared}}
+ S4 e(4);
+ S5 g(5);
+ int i;
+ int &j = i;
+
+#pragma omp target teams distribute parallel for private // expected-error {{expected '(' after 'private'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for private ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for private () // expected-error {{expected expression}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for private (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for private (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for private (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for private (argc)
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for private (S1) // expected-error {{'S1' does not refer to a value}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for private (a, b, c, d, f) // expected-error {{private variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be private}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for private (argv[1]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for private(ba)
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for private(ca) // expected-error {{shared variable cannot be private}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for private(da) // expected-error {{shared variable cannot be private}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for private(S2::S2s) // expected-error {{shared variable cannot be private}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for private(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for private(h) // expected-error {{threadprivate or thread local variable cannot be private}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for shared(i)
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for firstprivate(i), private(i) // expected-error {{firstprivate variable cannot be private}} expected-note {{defined as firstprivate}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for private(j)
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute parallel for reduction(+:i)
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp distribute private(i)
+ for (int k = 0; k < 10; ++k) {
+#pragma omp target teams distribute parallel for private(i)
+ for (int x = 0; x < 10; ++x) foo();
+ }
+
+#pragma omp target teams distribute parallel for firstprivate(i)
+ for (int k = 0; k < 10; ++k) {
+ }
+
+ return 0;
+}
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
new file mode 100644
index 000000000000..b2bbfa8bb337
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_proc_bind_messages.cpp
@@ -0,0 +1,69 @@
+// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - %s
+
+void foo();
+
+template <class T, typename S, int N>
+T tmain(T argc, S **argv) {
+ T i;
+#pragma omp target teams distribute parallel for proc_bind // expected-error {{expected '(' after 'proc_bind'}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target teams distribute parallel for proc_bind( // expected-error {{expected 'master', 'close' or 'spread' in OpenMP clause 'proc_bind'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target teams distribute parallel for proc_bind() // expected-error {{expected 'master', 'close' or 'spread' in OpenMP clause 'proc_bind'}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target teams distribute parallel for proc_bind(master // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target teams distribute parallel for proc_bind(close), proc_bind(spread) // expected-error {{directive '#pragma omp target teams distribute parallel for' cannot contain more than one 'proc_bind' clause}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target teams distribute parallel for proc_bind(x) // expected-error {{expected 'master', 'close' or 'spread' in OpenMP clause 'proc_bind'}}
+ for (i = 0; i < argc; ++i)
+ foo();
+
+#pragma omp target teams distribute parallel for proc_bind(master)
+ for (i = 0; i < argc; ++i)
+ foo();
+
+#pragma omp parallel proc_bind(close)
+#pragma omp target teams distribute parallel for proc_bind(spread)
+ for (i = 0; i < argc; ++i)
+ foo();
+
+ return T();
+}
+
+int main(int argc, char **argv) {
+ int i;
+#pragma omp target teams distribute parallel for proc_bind // expected-error {{expected '(' after 'proc_bind'}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target teams distribute parallel for proc_bind( // expected-error {{expected 'master', 'close' or 'spread' in OpenMP clause 'proc_bind'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target teams distribute parallel for proc_bind() // expected-error {{expected 'master', 'close' or 'spread' in OpenMP clause 'proc_bind'}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target teams distribute parallel for proc_bind(master // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target teams distribute parallel for proc_bind(close), proc_bind(spread) // expected-error {{directive '#pragma omp target teams distribute parallel for' cannot contain more than one 'proc_bind' clause}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target teams distribute parallel for proc_bind(x) // expected-error {{expected 'master', 'close' or 'spread' in OpenMP clause 'proc_bind'}}
+ for (i = 0; i < argc; ++i)
+ foo();
+
+#pragma omp target teams distribute parallel for proc_bind(master)
+ for (i = 0; i < argc; ++i)
+ foo();
+
+#pragma omp parallel proc_bind(close)
+#pragma omp target teams distribute parallel for proc_bind(spread)
+ for (i = 0; i < argc; ++i)
+ foo();
+ return tmain<int, char, 3>(argc, argv);
+}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_reduction_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_reduction_messages.cpp
new file mode 100644
index 000000000000..ba9586a1cef8
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_reduction_messages.cpp
@@ -0,0 +1,241 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}} expected-note 4 {{forward declaration of 'S1'}}
+extern S1 a;
+class S2 {
+ mutable int a;
+ S2 &operator+(const S2 &arg) { return (*this); } // expected-note 3 {{implicitly declared private here}}
+
+public:
+ S2() : a(0) {}
+ S2(S2 &s2) : a(s2.a) {}
+ static float S2s; // expected-note 2 {{static data member is predetermined as shared}}
+ static const float S2sc;
+};
+const float S2::S2sc = 0; // expected-note 2 {{'S2sc' defined here}}
+S2 b; // expected-note 3 {{'b' defined here}}
+const S2 ba[5]; // expected-note 2 {{'ba' defined here}}
+class S3 {
+ int a;
+
+public:
+ int b;
+ S3() : a(0) {}
+ S3(const S3 &s3) : a(s3.a) {}
+ S3 operator+(const S3 &arg1) { return arg1; }
+};
+int operator+(const S3 &arg1, const S3 &arg2) { return 5; }
+S3 c; // expected-note 3 {{'c' defined here}}
+const S3 ca[5]; // expected-note 2 {{'ca' defined here}}
+extern const int f; // expected-note 4 {{'f' declared here}}
+class S4 {
+ int a;
+ S4(); // expected-note {{implicitly declared private here}}
+ S4(const S4 &s4);
+ S4 &operator+(const S4 &arg) { return (*this); }
+
+public:
+ S4(int v) : a(v) {}
+};
+S4 &operator&=(S4 &arg1, S4 &arg2) { return arg1; }
+class S5 {
+ int a;
+ S5() : a(0) {} // expected-note {{implicitly declared private here}}
+ S5(const S5 &s5) : a(s5.a) {}
+ S5 &operator+(const S5 &arg);
+
+public:
+ S5(int v) : a(v) {}
+};
+class S6 { // expected-note 3 {{candidate function (the implicit copy assignment operator) not viable: no known conversion from 'int' to 'const S6' for 1st argument}}
+#if __cplusplus >= 201103L // C++11 or later
+// expected-note@-2 3 {{candidate function (the implicit move assignment operator) not viable}}
+#endif
+ int a;
+
+public:
+ S6() : a(6) {}
+ operator int() { return 6; }
+} o;
+
+S3 h, k;
+#pragma omp threadprivate(h) // expected-note 2 {{defined as threadprivate or thread local}}
+
+template <class T> // expected-note {{declared here}}
+T tmain(T argc) {
+ const T d = T(); // expected-note 4 {{'d' defined here}}
+ const T da[5] = {T()}; // expected-note 2 {{'da' defined here}}
+ T qa[5] = {T()};
+ T i;
+ T &j = i; // expected-note 4 {{'j' defined here}}
+ S3 &p = k; // expected-note 2 {{'p' defined here}}
+ const T &r = da[(int)i]; // expected-note 2 {{'r' defined here}}
+ T &q = qa[(int)i]; // expected-note 2 {{'q' defined here}}
+ T fl;
+#pragma omp target teams distribute parallel for reduction // expected-error {{expected '(' after 'reduction'}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction + // expected-error {{expected '(' after 'reduction'}} expected-warning {{extra tokens at the end of '#pragma omp target teams distribute parallel for' are ignored}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction( // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction(- // expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction() // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction(*) // expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected expression}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction(\) // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction(& : argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{invalid operands to binary expression ('float' and 'float')}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction(| : argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{invalid operands to binary expression ('float' and 'float')}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction(|| : argc ? i : argc) // expected-error 2 {{expected variable name, array element or array section}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction(foo : argc) //expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'float'}} expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'int'}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction(&& : argc)
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction(^ : T) // expected-error {{'T' does not refer to a value}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}} expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction(+ : o) // expected-error 2 {{no viable overloaded '='}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for private(i), reduction(+ : j), reduction(+ : q) // expected-error 4 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp parallel private(k)
+#pragma omp target teams distribute parallel for reduction(+ : p), reduction(+ : p) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction(+ : p), reduction(+ : p) // expected-error 2 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 2 {{previously referenced here}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp parallel shared(i)
+#pragma omp parallel reduction(min : i)
+#pragma omp target teams distribute parallel for reduction(max : j) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction(+ : fl)
+ for (int j=0; j<100; j++) foo();
+
+ return T();
+}
+
+namespace A {
+double x;
+#pragma omp threadprivate(x) // expected-note {{defined as threadprivate or thread local}}
+}
+namespace B {
+using A::x;
+}
+
+int main(int argc, char **argv) {
+ const int d = 5; // expected-note 2 {{'d' defined here}}
+ const int da[5] = {0}; // expected-note {{'da' defined here}}
+ int qa[5] = {0};
+ S4 e(4);
+ S5 g(5);
+ int i;
+ int &j = i; // expected-note 2 {{'j' defined here}}
+ S3 &p = k; // expected-note 2 {{'p' defined here}}
+ const int &r = da[i]; // expected-note {{'r' defined here}}
+ int &q = qa[i]; // expected-note {{'q' defined here}}
+ float fl;
+#pragma omp target teams distribute parallel for reduction // expected-error {{expected '(' after 'reduction'}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction + // expected-error {{expected '(' after 'reduction'}} expected-warning {{extra tokens at the end of '#pragma omp target teams distribute parallel for' are ignored}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction( // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction(- // expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction() // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction(*) // expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected expression}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction(\) // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction(foo : argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max'}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction(| : argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction(|| : argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name, array element or array section}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction(~ : argc) // expected-error {{expected unqualified-id}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction(&& : argc)
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction(^ : S1) // expected-error {{'S1' does not refer to a value}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified list item cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction(& : e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{invalid operands to binary expression ('S4' and 'S4')}} expected-error {{calling a private constructor of class 'S5'}} expected-error {{invalid operands to binary expression ('S5' and 'S5')}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction(+ : h, k, B::x) // expected-error 2 {{threadprivate or thread local variable cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction(+ : o) // expected-error {{no viable overloaded '='}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for private(i), reduction(+ : j), reduction(+ : q) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp parallel private(k)
+#pragma omp target teams distribute parallel for reduction(+ : p), reduction(+ : p) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction(+ : p), reduction(+ : p) // expected-error {{variable can appear only once in OpenMP 'reduction' clause}} expected-note {{previously referenced here}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction(+ : r) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp parallel shared(i)
+#pragma omp parallel reduction(min : i)
+#pragma omp target teams distribute parallel for reduction(max : j) // expected-error {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for reduction(+ : fl)
+ for (int j=0; j<100; j++) foo();
+ static int m;
+#pragma omp target teams distribute parallel for reduction(+ : m) // OK
+ for (int j=0; j<100; j++) foo();
+
+ return tmain(argc) + tmain(fl); // expected-note {{in instantiation of function template specialization 'tmain<int>' requested here}} expected-note {{in instantiation of function template specialization 'tmain<float>' requested here}}
+}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_schedule_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_schedule_messages.cpp
new file mode 100644
index 000000000000..54e302010992
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_schedule_messages.cpp
@@ -0,0 +1,143 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}}
+
+template <class T, typename S, int N, int ST> // expected-note {{declared here}}
+T tmain(T argc, S **argv) {
+// expected-error@+1 {{expected '(' after 'schedule'}}
+#pragma omp target teams distribute parallel for schedule
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+// expected-error@+1 {{expected 'static', 'dynamic', 'guided', 'auto', 'runtime', 'monotonic', 'nonmonotonic' or 'simd' in OpenMP clause 'schedule'}} expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
+#pragma omp target teams distribute parallel for schedule (
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+// expected-error@+1 {{expected 'static', 'dynamic', 'guided', 'auto', 'runtime', 'monotonic', 'nonmonotonic' or 'simd' in OpenMP clause 'schedule'}}
+#pragma omp target teams distribute parallel for schedule ()
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+// expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
+#pragma omp target teams distribute parallel for schedule (auto
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+// expected-error@+1 {{expected 'static', 'dynamic', 'guided', 'auto', 'runtime', 'monotonic', 'nonmonotonic' or 'simd' in OpenMP clause 'schedule'}} expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
+#pragma omp target teams distribute parallel for schedule (auto_dynamic
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+// expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
+#pragma omp target teams distribute parallel for schedule (auto,
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+// expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
+#pragma omp target teams distribute parallel for schedule (runtime, 3)
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+// expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
+#pragma omp target teams distribute parallel for schedule (guided argc
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+// expected-error@+1 2 {{argument to 'schedule' clause must be a strictly positive integer value}}
+#pragma omp target teams distribute parallel for schedule (static, ST // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+// expected-warning@+1 {{extra tokens at the end of '#pragma omp target teams distribute parallel for' are ignored}}
+#pragma omp target teams distribute parallel for schedule (dynamic, 1))
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target teams distribute parallel for schedule (guided, (ST > 0) ? 1 + ST : 2)
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+// expected-error@+2 2 {{directive '#pragma omp target teams distribute parallel for' cannot contain more than one 'schedule' clause}}
+// expected-error@+1 {{argument to 'schedule' clause must be a strictly positive integer value}}
+#pragma omp target teams distribute parallel for schedule (static, foobool(argc)), schedule (dynamic, true), schedule (guided, -5)
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+// expected-error@+1 {{'S' does not refer to a value}}
+#pragma omp target teams distribute parallel for schedule (static, S)
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+// expected-error@+2 2 {{expression must have integral or unscoped enumeration type, not 'char *'}}
+// expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
+#pragma omp target teams distribute parallel for schedule (guided, argv[1]=2)
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target teams distribute parallel for schedule (dynamic, 1)
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+// expected-error@+1 {{argument to 'schedule' clause must be a strictly positive integer value}}
+#pragma omp target teams distribute parallel for schedule (static, N)
+ for (T i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+ return argc;
+}
+
+int main(int argc, char **argv) {
+// expected-error@+1 {{expected '(' after 'schedule'}}
+#pragma omp target teams distribute parallel for schedule
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+
+// expected-error@+1 {{expected 'static', 'dynamic', 'guided', 'auto', 'runtime', 'monotonic', 'nonmonotonic' or 'simd' in OpenMP clause 'schedule'}} expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
+#pragma omp target teams distribute parallel for schedule (
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+
+// expected-error@+1 {{expected 'static', 'dynamic', 'guided', 'auto', 'runtime', 'monotonic', 'nonmonotonic' or 'simd' in OpenMP clause 'schedule'}}
+#pragma omp target teams distribute parallel for schedule ()
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+
+// expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
+#pragma omp target teams distribute parallel for schedule (auto
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+
+// expected-error@+1 {{expected 'static', 'dynamic', 'guided', 'auto', 'runtime', 'monotonic', 'nonmonotonic' or 'simd' in OpenMP clause 'schedule'}} expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
+#pragma omp target teams distribute parallel for schedule (auto_dynamic
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+
+// expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
+#pragma omp target teams distribute parallel for schedule (auto,
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+
+// expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
+#pragma omp target teams distribute parallel for schedule (runtime, 3)
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+
+// expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
+#pragma omp target teams distribute parallel for schedule (guided, 4
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+
+// expected-warning@+1 {{extra tokens at the end of '#pragma omp target teams distribute parallel for' are ignored}}
+#pragma omp target teams distribute parallel for schedule (static, 2+2))
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target teams distribute parallel for schedule (dynamic, foobool(1) > 0 ? 1 : 2)
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+
+// expected-error@+2 2 {{directive '#pragma omp target teams distribute parallel for' cannot contain more than one 'schedule' clause}}
+// expected-error@+1 {{argument to 'schedule' clause must be a strictly positive integer value}}
+#pragma omp target teams distribute parallel for schedule (guided, foobool(argc)), schedule (static, true), schedule (dynamic, -5)
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+
+// expected-error@+1 {{'S1' does not refer to a value}}
+#pragma omp target teams distribute parallel for schedule (guided, S1)
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+
+// expected-error@+2 {{expected ')'}} expected-note@+2 {{to match this '('}}
+// expected-error@+1 {{expression must have integral or unscoped enumeration type, not 'char *'}}
+#pragma omp target teams distribute parallel for schedule (static, argv[1]=2)
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+
+// expected-error@+3 {{statement after '#pragma omp target teams distribute parallel for' must be a for loop}}
+// expected-note@+1 {{in instantiation of function template specialization 'tmain<int, char, -1, -2>' requested here}}
+#pragma omp target teams distribute parallel for schedule(dynamic, schedule(tmain<int, char, -1, -2>(argc, argv) // expected-error 2 {{expected ')'}} expected-note 2 {{to match this '('}}
+ foo();
+
+ // expected-note@+1 {{in instantiation of function template specialization 'tmain<int, char, 1, 0>' requested here}}
+ return tmain<int, char, 1, 0>(argc, argv);
+}
+
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_shared_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_shared_messages.cpp
new file mode 100644
index 000000000000..4f9000079630
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_shared_messages.cpp
@@ -0,0 +1,106 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}}
+extern S1 a;
+class S2 {
+ mutable int a;
+public:
+ S2():a(0) { }
+ S2(S2 &s2):a(s2.a) { }
+};
+const S2 b;
+const S2 ba[5];
+class S3 {
+ int a;
+public:
+ S3():a(0) { }
+ S3(S3 &s3):a(s3.a) { }
+};
+const S3 c;
+const S3 ca[5];
+extern const int f;
+class S4 {
+ int a;
+ S4();
+ S4(const S4 &s4);
+public:
+ S4(int v):a(v) { }
+};
+class S5 {
+ int a;
+ S5():a(0) {}
+ S5(const S5 &s5):a(s5.a) { }
+public:
+ S5(int v):a(v) { }
+};
+
+S3 h;
+#pragma omp threadprivate(h) // expected-note {{defined as threadprivate or thread local}}
+
+namespace A {
+double x;
+#pragma omp threadprivate(x) // expected-note {{defined as threadprivate or thread local}}
+}
+namespace B {
+using A::x;
+}
+
+int main(int argc, char **argv) {
+ const int d = 5;
+ const int da[5] = { 0 };
+ S4 e(4);
+ S5 g(5);
+ int i;
+ int &j = i;
+#pragma omp target teams distribute parallel for shared // expected-error {{expected '(' after 'shared'}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for shared ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for shared () // expected-error {{expected expression}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for shared (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for shared (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for shared (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for shared (argc)
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for shared (S1) // expected-error {{'S1' does not refer to a value}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for shared (a, b, c, d, f)
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for shared (argv[1]) // expected-error {{expected variable name}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for shared(ba)
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for shared(ca)
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for shared(da)
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for shared(e, g)
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for shared(h, B::x) // expected-error 2 {{threadprivate or thread local variable cannot be shared}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for private(i), shared(i) // expected-error {{private variable cannot be shared}} expected-note {{defined as private}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for firstprivate(i), shared(i) // expected-error {{firstprivate variable cannot be shared}} expected-note {{defined as firstprivate}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for private(i)
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for shared(i)
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for shared(j)
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute parallel for firstprivate(i)
+ for (int j=0; j<100; j++) foo();
+
+ return 0;
+}
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
new file mode 100644
index 000000000000..1db07262931e
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_parallel_for_thread_limit_messages.cpp
@@ -0,0 +1,98 @@
+// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note 2 {{declared here}}
+
+template <typename T, int C> // expected-note {{declared here}}
+T tmain(T argc) {
+ char **a;
+#pragma omp target teams distribute parallel for thread_limit(C)
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target teams distribute parallel for thread_limit(T) // expected-error {{'T' does not refer to a value}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target teams distribute parallel for thread_limit // expected-error {{expected '(' after 'thread_limit'}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target teams distribute parallel for thread_limit( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target teams distribute parallel for thread_limit() // expected-error {{expected expression}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target teams distribute parallel for thread_limit(argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target teams distribute parallel for thread_limit(argc)) // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute parallel for' are ignored}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target teams distribute parallel for thread_limit(argc > 0 ? a[1] : a[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target teams distribute parallel for thread_limit(argc + argc)
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target teams distribute parallel for thread_limit(argc), thread_limit (argc+1) // expected-error {{directive '#pragma omp target teams distribute parallel for' cannot contain more than one 'thread_limit' clause}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target teams distribute parallel for thread_limit(S1) // expected-error {{'S1' does not refer to a value}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target teams distribute parallel for thread_limit(-2) // expected-error {{argument to 'thread_limit' clause must be a strictly positive integer value}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target teams distribute parallel for thread_limit(-10u)
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target teams distribute parallel for thread_limit(3.14) // expected-error 2 {{expression must have integral or unscoped enumeration type, not 'double'}}
+ for (int j=0; j<100; j++) foo();
+
+ return 0;
+}
+
+int main(int argc, char **argv) {
+#pragma omp target teams distribute parallel for thread_limit // expected-error {{expected '(' after 'thread_limit'}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target teams distribute parallel for thread_limit ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target teams distribute parallel for thread_limit () // expected-error {{expected expression}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target teams distribute parallel for thread_limit (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target teams distribute parallel for thread_limit (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target teams distribute parallel for' are ignored}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target teams distribute parallel for thread_limit (argc > 0 ? argv[1] : argv[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target teams distribute parallel for thread_limit (argc + argc)
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target teams distribute parallel for thread_limit (argc), thread_limit (argc+1) // expected-error {{directive '#pragma omp target teams distribute parallel for' cannot contain more than one 'thread_limit' clause}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target teams distribute parallel for thread_limit (S1) // expected-error {{'S1' does not refer to a value}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target teams distribute parallel for thread_limit (-2) // expected-error {{argument to 'thread_limit' clause must be a strictly positive integer value}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target teams distribute parallel for thread_limit (-10u)
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target teams distribute parallel for thread_limit (3.14) // expected-error {{expression must have integral or unscoped enumeration type, not 'double'}}
+ for (int j=0; j<100; j++) foo();
+
+ return tmain<int, 10>(argc); // expected-note {{in instantiation of function template specialization 'tmain<int, 10>' requested here}}
+}
diff --git a/test/OpenMP/target_teams_distribute_private_messages.cpp b/test/OpenMP/target_teams_distribute_private_messages.cpp
new file mode 100644
index 000000000000..fcbd4f87162a
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_private_messages.cpp
@@ -0,0 +1,111 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}} expected-note {{forward declaration of 'S1'}}
+extern S1 a;
+class S2 {
+ mutable int a;
+public:
+ S2():a(0) { }
+ static float S2s; // expected-note {{predetermined as shared}}
+};
+const S2 b;
+const S2 ba[5];
+class S3 {
+ int a;
+public:
+ S3():a(0) { }
+};
+const S3 c; // expected-note {{predetermined as shared}}
+const S3 ca[5]; // expected-note {{predetermined as shared}}
+extern const int f; // expected-note {{predetermined as shared}}
+class S4 {
+ int a;
+ S4(); // expected-note {{implicitly declared private here}}
+public:
+ S4(int v):a(v) { }
+};
+class S5 {
+ int a;
+ S5():a(0) {} // expected-note {{implicitly declared private here}}
+public:
+ S5(int v):a(v) { }
+};
+
+S3 h;
+#pragma omp threadprivate(h) // expected-note {{defined as threadprivate or thread local}}
+
+
+int main(int argc, char **argv) {
+ const int d = 5; // expected-note {{predetermined as shared}}
+ const int da[5] = { 0 }; // expected-note {{predetermined as shared}}
+ S4 e(4);
+ S5 g(5);
+ int i;
+ int &j = i;
+
+#pragma omp target teams distribute private // expected-error {{expected '(' after 'private'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute private ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute private () // expected-error {{expected expression}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute private (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute private (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute private (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute private (argc)
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute private (S1) // expected-error {{'S1' does not refer to a value}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute private (a, b, c, d, f) // expected-error {{private variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be private}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute private (argv[1]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute private(ba)
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute private(ca) // expected-error {{shared variable cannot be private}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute private(da) // expected-error {{shared variable cannot be private}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute private(S2::S2s) // expected-error {{shared variable cannot be private}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute private(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute private(h) // expected-error {{threadprivate or thread local variable cannot be private}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute shared(i)
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute firstprivate(i), private(i) // expected-error {{firstprivate variable cannot be private}} expected-note {{defined as firstprivate}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target teams distribute private(j)
+ for (int k = 0; k < argc; ++k) ++k;
+
+ return 0;
+}
diff --git a/test/OpenMP/target_teams_distribute_reduction_messages.cpp b/test/OpenMP/target_teams_distribute_reduction_messages.cpp
new file mode 100644
index 000000000000..d52ee076130b
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_reduction_messages.cpp
@@ -0,0 +1,246 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+void foobar(int &ref) {
+#pragma omp target teams distribute reduction(+:ref)
+ for (int j=0; j<100; j++) foo();
+}
+
+struct S1; // expected-note {{declared here}} expected-note 4 {{forward declaration of 'S1'}}
+extern S1 a;
+class S2 {
+ mutable int a;
+ S2 &operator+(const S2 &arg) { return (*this); } // expected-note 3 {{implicitly declared private here}}
+
+public:
+ S2() : a(0) {}
+ S2(S2 &s2) : a(s2.a) {}
+ static float S2s; // expected-note 2 {{static data member is predetermined as shared}}
+ static const float S2sc;
+};
+const float S2::S2sc = 0; // expected-note 2 {{'S2sc' defined here}}
+S2 b; // expected-note 3 {{'b' defined here}}
+const S2 ba[5]; // expected-note 2 {{'ba' defined here}}
+class S3 {
+ int a;
+
+public:
+ int b;
+ S3() : a(0) {}
+ S3(const S3 &s3) : a(s3.a) {}
+ S3 operator+(const S3 &arg1) { return arg1; }
+};
+int operator+(const S3 &arg1, const S3 &arg2) { return 5; }
+S3 c; // expected-note 3 {{'c' defined here}}
+const S3 ca[5]; // expected-note 2 {{'ca' defined here}}
+extern const int f; // expected-note 4 {{'f' declared here}}
+class S4 {
+ int a;
+ S4(); // expected-note {{implicitly declared private here}}
+ S4(const S4 &s4);
+ S4 &operator+(const S4 &arg) { return (*this); }
+
+public:
+ S4(int v) : a(v) {}
+};
+S4 &operator&=(S4 &arg1, S4 &arg2) { return arg1; }
+class S5 {
+ int a;
+ S5() : a(0) {} // expected-note {{implicitly declared private here}}
+ S5(const S5 &s5) : a(s5.a) {}
+ S5 &operator+(const S5 &arg);
+
+public:
+ S5(int v) : a(v) {}
+};
+class S6 { // expected-note 3 {{candidate function (the implicit copy assignment operator) not viable: no known conversion from 'int' to 'const S6' for 1st argument}}
+#if __cplusplus >= 201103L // C++11 or later
+// expected-note@-2 3 {{candidate function (the implicit move assignment operator) not viable}}
+#endif
+ int a;
+
+public:
+ S6() : a(6) {}
+ operator int() { return 6; }
+} o;
+
+S3 h, k;
+#pragma omp threadprivate(h) // expected-note 2 {{defined as threadprivate or thread local}}
+
+template <class T> // expected-note {{declared here}}
+T tmain(T argc) {
+ const T d = T(); // expected-note 4 {{'d' defined here}}
+ const T da[5] = {T()}; // expected-note 2 {{'da' defined here}}
+ T qa[5] = {T()};
+ T i;
+ T &j = i; // expected-note 4 {{'j' defined here}}
+ S3 &p = k; // expected-note 2 {{'p' defined here}}
+ const T &r = da[(int)i]; // expected-note 2 {{'r' defined here}}
+ T &q = qa[(int)i]; // expected-note 2 {{'q' defined here}}
+ T fl;
+#pragma omp target teams distribute reduction // expected-error {{expected '(' after 'reduction'}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction + // expected-error {{expected '(' after 'reduction'}} expected-warning {{extra tokens at the end of '#pragma omp target teams distribute' are ignored}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction( // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction(- // expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction() // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction(*) // expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected expression}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction(\) // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction(& : argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{invalid operands to binary expression ('float' and 'float')}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction(| : argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{invalid operands to binary expression ('float' and 'float')}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction(|| : argc ? i : argc) // expected-error 2 {{expected variable name, array element or array section}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction(foo : argc) //expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'float'}} expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'int'}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction(&& : argc)
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction(^ : T) // expected-error {{'T' does not refer to a value}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}} expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction(+ : o) // expected-error 2 {{no viable overloaded '='}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute private(i), reduction(+ : j), reduction(+ : q) // expected-error 4 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp parallel private(k)
+#pragma omp target teams distribute reduction(+ : p), reduction(+ : p) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction(+ : p), reduction(+ : p) // expected-error 2 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 2 {{previously referenced here}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp parallel shared(i)
+#pragma omp parallel reduction(min : i)
+#pragma omp target teams distribute reduction(max : j) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction(+ : fl)
+ for (int j=0; j<100; j++) foo();
+
+ return T();
+}
+
+namespace A {
+double x;
+#pragma omp threadprivate(x) // expected-note {{defined as threadprivate or thread local}}
+}
+namespace B {
+using A::x;
+}
+
+int main(int argc, char **argv) {
+ const int d = 5; // expected-note 2 {{'d' defined here}}
+ const int da[5] = {0}; // expected-note {{'da' defined here}}
+ int qa[5] = {0};
+ S4 e(4);
+ S5 g(5);
+ int i;
+ int &j = i; // expected-note 2 {{'j' defined here}}
+ S3 &p = k; // expected-note 2 {{'p' defined here}}
+ const int &r = da[i]; // expected-note {{'r' defined here}}
+ int &q = qa[i]; // expected-note {{'q' defined here}}
+ float fl;
+#pragma omp target teams distribute reduction // expected-error {{expected '(' after 'reduction'}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction + // expected-error {{expected '(' after 'reduction'}} expected-warning {{extra tokens at the end of '#pragma omp target teams distribute' are ignored}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction( // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction(- // expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction() // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction(*) // expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected expression}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction(\) // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction(foo : argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max'}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction(| : argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction(|| : argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name, array element or array section}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction(~ : argc) // expected-error {{expected unqualified-id}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction(&& : argc)
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction(^ : S1) // expected-error {{'S1' does not refer to a value}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified list item cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction(& : e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{invalid operands to binary expression ('S4' and 'S4')}} expected-error {{calling a private constructor of class 'S5'}} expected-error {{invalid operands to binary expression ('S5' and 'S5')}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction(+ : h, k, B::x) // expected-error 2 {{threadprivate or thread local variable cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction(+ : o) // expected-error {{no viable overloaded '='}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute private(i), reduction(+ : j), reduction(+ : q) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp parallel private(k)
+#pragma omp target teams distribute reduction(+ : p), reduction(+ : p) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction(+ : p), reduction(+ : p) // expected-error {{variable can appear only once in OpenMP 'reduction' clause}} expected-note {{previously referenced here}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction(+ : r) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp parallel shared(i)
+#pragma omp parallel reduction(min : i)
+#pragma omp target teams distribute reduction(max : j) // expected-error {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute reduction(+ : fl)
+ for (int j=0; j<100; j++) foo();
+ static int m;
+#pragma omp target teams distribute reduction(+ : m) // OK
+ for (int j=0; j<100; j++) foo();
+
+ return tmain(argc) + tmain(fl); // expected-note {{in instantiation of function template specialization 'tmain<int>' requested here}} expected-note {{in instantiation of function template specialization 'tmain<float>' requested here}}
+}
diff --git a/test/OpenMP/target_teams_distribute_shared_messages.cpp b/test/OpenMP/target_teams_distribute_shared_messages.cpp
new file mode 100644
index 000000000000..13f4d471f1d1
--- /dev/null
+++ b/test/OpenMP/target_teams_distribute_shared_messages.cpp
@@ -0,0 +1,110 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}}
+extern S1 a;
+class S2 {
+ mutable int a;
+public:
+ S2():a(0) { }
+ S2(S2 &s2):a(s2.a) { }
+};
+const S2 b;
+const S2 ba[5];
+class S3 {
+ int a;
+public:
+ S3():a(0) { }
+ S3(S3 &s3):a(s3.a) { }
+};
+const S3 c;
+const S3 ca[5];
+extern const int f;
+class S4 {
+ int a;
+ S4();
+ S4(const S4 &s4);
+public:
+ S4(int v):a(v) { }
+};
+class S5 {
+ int a;
+ S5():a(0) {}
+ S5(const S5 &s5):a(s5.a) { }
+public:
+ S5(int v):a(v) { }
+};
+
+S3 h;
+#pragma omp threadprivate(h) // expected-note {{defined as threadprivate or thread local}}
+
+namespace A {
+double x;
+#pragma omp threadprivate(x) // expected-note {{defined as threadprivate or thread local}}
+}
+namespace B {
+using A::x;
+}
+
+int main(int argc, char **argv) {
+ const int d = 5;
+ const int da[5] = { 0 };
+ S4 e(4);
+ S5 g(5);
+ int i;
+ int &j = i;
+#pragma omp target teams distribute shared // expected-error {{expected '(' after 'shared'}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute shared ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute shared () // expected-error {{expected expression}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute shared (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute shared (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute shared (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute shared (argc)
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute shared (S1) // expected-error {{'S1' does not refer to a value}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute shared (a, b, c, d, f)
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute shared (argv[1]) // expected-error {{expected variable name}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute shared(ba)
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute shared(ca)
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute shared(da)
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute shared(e, g)
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute shared(h, B::x) // expected-error 2 {{threadprivate or thread local variable cannot be shared}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute private(i), shared(i) // expected-error {{private variable cannot be shared}} expected-note {{defined as private}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute firstprivate(i), shared(i) // expected-error {{firstprivate variable cannot be shared}} expected-note {{defined as firstprivate}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute private(i)
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute shared(i)
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute shared(j)
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute firstprivate(i)
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute shared(i)
+ for (int j=0; j<100; j++) foo();
+#pragma omp target teams distribute shared(j)
+ for (int j=0; j<100; j++) foo();
+
+ return 0;
+}
diff --git a/test/OpenMP/target_teams_firstprivate_messages.cpp b/test/OpenMP/target_teams_firstprivate_messages.cpp
new file mode 100644
index 000000000000..84fc4ab1063a
--- /dev/null
+++ b/test/OpenMP/target_teams_firstprivate_messages.cpp
@@ -0,0 +1,114 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}} expected-note{{forward declaration of 'S1'}}
+extern S1 a;
+class S2 {
+ mutable int a;
+
+public:
+ S2() : a(0) {}
+ S2(const S2 &s2) : a(s2.a) {}
+ static float S2s;
+ static const float S2sc;
+};
+const float S2::S2sc = 0;
+const S2 b;
+const S2 ba[5];
+class S3 {
+ int a;
+
+public:
+ S3() : a(0) {}
+ S3(const S3 &s3) : a(s3.a) {}
+};
+const S3 c;
+const S3 ca[5];
+extern const int f;
+class S4 {
+ int a;
+ S4();
+ S4(const S4 &s4); // expected-note {{implicitly declared private here}}
+public:
+ S4(int v) : a(v) {}
+};
+class S5 {
+ int a;
+ S5() : a(0) {}
+ S5(const S5 &s5) : a(s5.a) {} // expected-note {{implicitly declared private here}}
+public:
+ S5(int v) : a(v) {}
+};
+
+S3 h;
+#pragma omp threadprivate(h) // expected-note {{defined as threadprivate or thread local}}
+
+namespace A {
+double x;
+#pragma omp threadprivate(x) // expected-note {{defined as threadprivate or thread local}}
+}
+namespace B {
+using A::x;
+}
+
+int main(int argc, char **argv) {
+ const int d = 5;
+ const int da[5] = {0};
+ S4 e(4);
+ S5 g(5);
+ int i;
+ int &j = i;
+#pragma omp target teams firstprivate // expected-error {{expected '(' after 'firstprivate'}}
+ foo();
+#pragma omp target teams firstprivate( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ foo();
+#pragma omp target teams firstprivate() // expected-error {{expected expression}}
+ foo();
+#pragma omp target teams firstprivate(argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ foo();
+#pragma omp target teams firstprivate(argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ foo();
+#pragma omp target teams firstprivate(argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ foo();
+#pragma omp target teams firstprivate(argc)
+ foo();
+#pragma omp target teams firstprivate(S1) // expected-error {{'S1' does not refer to a value}}
+ foo();
+#pragma omp target teams firstprivate(a, b, c, d, f) // expected-error {{firstprivate variable with incomplete type 'S1'}}
+ foo();
+#pragma omp target teams firstprivate(argv[1]) // expected-error {{expected variable name}}
+ foo();
+#pragma omp target teams firstprivate(ba)
+ foo();
+#pragma omp target teams firstprivate(ca)
+ foo();
+#pragma omp target teams firstprivate(da)
+ foo();
+#pragma omp target teams firstprivate(S2::S2s)
+ foo();
+#pragma omp target teams firstprivate(S2::S2sc)
+ foo();
+#pragma omp target teams firstprivate(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}}
+ foo();
+#pragma omp target teams firstprivate(h, B::x) // expected-error 2 {{threadprivate or thread local variable cannot be firstprivate}}
+ foo();
+#pragma omp target teams private(i), firstprivate(i) // expected-error {{private variable cannot be firstprivate}} expected-note{{defined as private}}
+ foo();
+#pragma omp target teams shared(i)
+ foo();
+#pragma omp target teams firstprivate(i)
+ foo();
+#pragma omp target teams firstprivate(j)
+ foo();
+ static int m;
+#pragma omp target teams firstprivate(m) // OK
+ foo();
+
+ return 0;
+}
diff --git a/test/OpenMP/target_teams_if_messages.cpp b/test/OpenMP/target_teams_if_messages.cpp
new file mode 100644
index 000000000000..0ab8fc3c94e8
--- /dev/null
+++ b/test/OpenMP/target_teams_if_messages.cpp
@@ -0,0 +1,91 @@
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}}
+
+template <class T, class S> // expected-note {{declared here}}
+int tmain(T argc, S **argv) {
+#pragma omp target teams if // expected-error {{expected '(' after 'if'}}
+ foo();
+#pragma omp target teams if ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ foo();
+#pragma omp target teams if () // expected-error {{expected expression}}
+ foo();
+#pragma omp target teams if (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ foo();
+#pragma omp target teams if (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target teams' are ignored}}
+ foo();
+#pragma omp target teams if (argc > 0 ? argv[1] : argv[2])
+ foo();
+#pragma omp target teams if (foobool(argc)), if (true) // expected-error {{directive '#pragma omp target teams' cannot contain more than one 'if' clause}}
+ foo();
+#pragma omp target teams if (S) // expected-error {{'S' does not refer to a value}}
+ foo();
+#pragma omp target teams if (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ foo();
+#pragma omp target teams if (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ foo();
+#pragma omp target teams if(argc)
+ foo();
+#pragma omp target teams if(target : // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ foo();
+#pragma omp target teams if(target : argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ foo();
+#pragma omp target teams if(target : argc)
+ foo();
+#pragma omp target teams if(target : argc) if (for:argc) // expected-error {{directive name modifier 'for' is not allowed for '#pragma omp target teams'}}
+ foo();
+#pragma omp target teams if(target : argc) if (target:argc) // expected-error {{directive '#pragma omp target teams' cannot contain more than one 'if' clause with 'target' name modifier}}
+ foo();
+#pragma omp target teams if(target : argc) if (argc) // expected-error {{no more 'if' clause is allowed}} expected-note {{previous clause with directive name modifier specified here}}
+ foo();
+
+ return 0;
+}
+
+int main(int argc, char **argv) {
+#pragma omp target teams if // expected-error {{expected '(' after 'if'}}
+ foo();
+#pragma omp target teams if ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ foo();
+#pragma omp target teams if () // expected-error {{expected expression}}
+ foo();
+#pragma omp target teams if (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ foo();
+#pragma omp target teams if (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target teams' are ignored}}
+ foo();
+#pragma omp target teams if (argc > 0 ? argv[1] : argv[2])
+ foo();
+#pragma omp target teams if (foobool(argc)), if (true) // expected-error {{directive '#pragma omp target teams' cannot contain more than one 'if' clause}}
+ foo();
+#pragma omp target teams if (S1) // expected-error {{'S1' does not refer to a value}}
+ foo();
+#pragma omp target teams if (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ foo();
+#pragma omp target teams if (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ foo();
+#pragma omp target teams if (1 0) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ foo();
+#pragma omp target teams if(if(tmain(argc, argv) // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ foo();
+#pragma omp target teams if(target : // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ foo();
+#pragma omp target teams if(target : argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ foo();
+#pragma omp target teams if(target : argc)
+ foo();
+#pragma omp target teams if(target : argc) if (for:argc) // expected-error {{directive name modifier 'for' is not allowed for '#pragma omp target teams'}}
+ foo();
+#pragma omp target teams if(target : argc) if (target:argc) // expected-error {{directive '#pragma omp target teams' cannot contain more than one 'if' clause with 'target' name modifier}}
+ foo();
+#pragma omp target teams if(target : argc) if (argc) // expected-error {{no more 'if' clause is allowed}} expected-note {{previous clause with directive name modifier specified here}}
+ foo();
+
+ return tmain(argc, argv);
+}
diff --git a/test/OpenMP/target_teams_is_device_ptr_ast_print.cpp b/test/OpenMP/target_teams_is_device_ptr_ast_print.cpp
new file mode 100644
index 000000000000..3a9cee5eee19
--- /dev/null
+++ b/test/OpenMP/target_teams_is_device_ptr_ast_print.cpp
@@ -0,0 +1,291 @@
+// 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
+// expected-no-diagnostics
+
+#ifndef HEADER
+#define HEADER
+struct ST {
+ int *a;
+};
+typedef int arr[10];
+typedef ST STarr[10];
+struct SA {
+ const int da[5] = { 0 };
+ ST g[10];
+ STarr &rg = g;
+ int i;
+ int &j = i;
+ int *k = &j;
+ int *&z = k;
+ int aa[10];
+ arr &raa = aa;
+ void func(int arg) {
+#pragma omp target teams is_device_ptr(k)
+ {}
+#pragma omp target teams is_device_ptr(z)
+ {}
+#pragma omp target teams is_device_ptr(aa) // OK
+ {}
+#pragma omp target teams is_device_ptr(raa) // OK
+ {}
+#pragma omp target teams is_device_ptr(g) // OK
+ {}
+#pragma omp target teams is_device_ptr(rg) // OK
+ {}
+#pragma omp target teams is_device_ptr(da) // OK
+ {}
+ return;
+ }
+};
+// CHECK: struct SA
+// CHECK-NEXT: const int da[5] = {0};
+// CHECK-NEXT: ST g[10];
+// CHECK-NEXT: STarr &rg = this->g;
+// CHECK-NEXT: int i;
+// CHECK-NEXT: int &j = this->i;
+// CHECK-NEXT: int *k = &this->j;
+// CHECK-NEXT: int *&z = this->k;
+// 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: {
+// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp target teams is_device_ptr(this->z)
+// CHECK-NEXT: {
+// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp target teams is_device_ptr(this->aa)
+// CHECK-NEXT: {
+// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp target teams is_device_ptr(this->raa)
+// CHECK-NEXT: {
+// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp target teams is_device_ptr(this->g)
+// CHECK-NEXT: {
+// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp target teams is_device_ptr(this->rg)
+// CHECK-NEXT: {
+// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp target teams is_device_ptr(this->da)
+
+struct SB {
+ unsigned A;
+ unsigned B;
+ float Arr[100];
+ float *Ptr;
+ float *foo() {
+ return &Arr[0];
+ }
+};
+
+struct SC {
+ unsigned A : 2;
+ unsigned B : 3;
+ unsigned C;
+ unsigned D;
+ float Arr[100];
+ SB S;
+ SB ArrS[100];
+ SB *PtrS;
+ SB *&RPtrS;
+ float *Ptr;
+
+ SC(SB *&_RPtrS) : RPtrS(_RPtrS) {}
+};
+
+union SD {
+ unsigned A;
+ float B;
+};
+
+struct S1;
+extern S1 a;
+class S2 {
+ mutable int a;
+public:
+ S2():a(0) { }
+ S2(S2 &s2):a(s2.a) { }
+ static float S2s;
+ static const float S2sc;
+};
+const float S2::S2sc = 0;
+const S2 b;
+const S2 ba[5];
+class S3 {
+ int a;
+public:
+ S3():a(0) { }
+ S3(S3 &s3):a(s3.a) { }
+};
+const S3 c;
+const S3 ca[5];
+extern const int f;
+class S4 {
+ int a;
+ S4();
+ S4(const S4 &s4);
+public:
+ S4(int v):a(v) { }
+};
+class S5 {
+ int a;
+ S5():a(0) {}
+ S5(const S5 &s5):a(s5.a) { }
+public:
+ S5(int v):a(v) { }
+};
+
+S3 h;
+#pragma omp threadprivate(h)
+
+typedef struct {
+ int a;
+} S6;
+
+template <typename T>
+T tmain(T argc) {
+ const T da[5] = { 0 };
+ S6 h[10];
+ auto &rh = h;
+ T i;
+ T &j = i;
+ T *k = &j;
+ T *&z = k;
+ T aa[10];
+ auto &raa = aa;
+#pragma omp target teams is_device_ptr(k)
+ {}
+#pragma omp target teams is_device_ptr(z)
+ {}
+#pragma omp target teams is_device_ptr(aa)
+ {}
+#pragma omp target teams is_device_ptr(raa)
+ {}
+#pragma omp target teams is_device_ptr(h)
+ {}
+#pragma omp target teams is_device_ptr(rh)
+ {}
+#pragma omp target teams is_device_ptr(da)
+ {}
+ return 0;
+}
+
+// CHECK: template<> int tmain<int>(int argc) {
+// CHECK-NEXT: const int da[5] = {0};
+// CHECK-NEXT: S6 h[10];
+// CHECK-NEXT: auto &rh = h;
+// CHECK-NEXT: int i;
+// CHECK-NEXT: int &j = i;
+// CHECK-NEXT: int *k = &j;
+// CHECK-NEXT: int *&z = k;
+// CHECK-NEXT: int aa[10];
+// CHECK-NEXT: auto &raa = aa;
+// CHECK-NEXT: #pragma omp target teams is_device_ptr(k)
+// CHECK-NEXT: {
+// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp target teams is_device_ptr(z)
+// CHECK-NEXT: {
+// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp target teams is_device_ptr(aa)
+// CHECK-NEXT: {
+// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp target teams is_device_ptr(raa)
+// CHECK-NEXT: {
+// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp target teams is_device_ptr(h)
+// CHECK-NEXT: {
+// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp target teams is_device_ptr(rh)
+// CHECK-NEXT: {
+// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp target teams is_device_ptr(da)
+
+// CHECK: template<> int *tmain<int *>(int *argc) {
+// CHECK-NEXT: int *const da[5] = {0};
+// CHECK-NEXT: S6 h[10];
+// CHECK-NEXT: auto &rh = h;
+// CHECK-NEXT: int *i;
+// CHECK-NEXT: int *&j = i;
+// CHECK-NEXT: int **k = &j;
+// CHECK-NEXT: int **&z = k;
+// CHECK-NEXT: int *aa[10];
+// CHECK-NEXT: auto &raa = aa;
+// CHECK-NEXT: #pragma omp target teams is_device_ptr(k)
+// CHECK-NEXT: {
+// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp target teams is_device_ptr(z)
+// CHECK-NEXT: {
+// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp target teams is_device_ptr(aa)
+// CHECK-NEXT: {
+// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp target teams is_device_ptr(raa)
+// CHECK-NEXT: {
+// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp target teams is_device_ptr(h)
+// CHECK-NEXT: {
+// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp target teams is_device_ptr(rh)
+// CHECK-NEXT: {
+// CHECK-NEXT: }
+// CHECK-NEXT: #pragma omp target teams is_device_ptr(da)
+
+// CHECK-LABEL: int main(int argc, char **argv) {
+int main(int argc, char **argv) {
+ const int da[5] = { 0 };
+ S6 h[10];
+ auto &rh = h;
+ int i;
+ int &j = i;
+ int *k = &j;
+ int *&z = k;
+ int aa[10];
+ auto &raa = aa;
+// CHECK-NEXT: const int da[5] = {0};
+// CHECK-NEXT: S6 h[10];
+// CHECK-NEXT: auto &rh = h;
+// CHECK-NEXT: int i;
+// CHECK-NEXT: int &j = i;
+// CHECK-NEXT: int *k = &j;
+// CHECK-NEXT: int *&z = k;
+// CHECK-NEXT: int aa[10];
+// CHECK-NEXT: auto &raa = aa;
+#pragma omp target teams is_device_ptr(k)
+// CHECK-NEXT: #pragma omp target teams is_device_ptr(k)
+ {}
+// CHECK-NEXT: {
+// CHECK-NEXT: }
+#pragma omp target teams is_device_ptr(z)
+// CHECK-NEXT: #pragma omp target teams is_device_ptr(z)
+ {}
+// CHECK-NEXT: {
+// CHECK-NEXT: }
+#pragma omp target teams is_device_ptr(aa)
+// CHECK-NEXT: #pragma omp target teams is_device_ptr(aa)
+ {}
+// CHECK-NEXT: {
+// CHECK-NEXT: }
+#pragma omp target teams is_device_ptr(raa)
+// CHECK-NEXT: #pragma omp target teams is_device_ptr(raa)
+ {}
+// CHECK-NEXT: {
+// CHECK-NEXT: }
+#pragma omp target teams is_device_ptr(h)
+// CHECK-NEXT: #pragma omp target teams is_device_ptr(h)
+ {}
+// CHECK-NEXT: {
+// CHECK-NEXT: }
+#pragma omp target teams is_device_ptr(rh)
+// CHECK-NEXT: #pragma omp target teams is_device_ptr(rh)
+ {}
+// CHECK-NEXT: {
+// CHECK-NEXT: }
+#pragma omp target teams is_device_ptr(da)
+// CHECK-NEXT: #pragma omp target teams is_device_ptr(da)
+ {}
+// CHECK-NEXT: {
+// CHECK-NEXT: }
+ return tmain<int>(argc) + *tmain<int *>(&argc);
+}
+#endif
diff --git a/test/OpenMP/target_teams_is_device_ptr_messages.cpp b/test/OpenMP/target_teams_is_device_ptr_messages.cpp
new file mode 100644
index 000000000000..0f5be43aaee7
--- /dev/null
+++ b/test/OpenMP/target_teams_is_device_ptr_messages.cpp
@@ -0,0 +1,268 @@
+// RUN: %clang_cc1 -std=c++11 -verify -fopenmp -ferror-limit 200 %s
+struct ST {
+ int *a;
+};
+typedef int arr[10];
+typedef ST STarr[10];
+struct SA {
+ const int d = 5;
+ const int da[5] = { 0 };
+ ST e;
+ ST g[10];
+ STarr &rg = g;
+ int i;
+ int &j = i;
+ int *k = &j;
+ int *&z = k;
+ int aa[10];
+ arr &raa = aa;
+ void func(int arg) {
+#pragma omp target teams is_device_ptr // expected-error {{expected '(' after 'is_device_ptr'}}
+ {}
+#pragma omp target teams is_device_ptr( // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}}
+ {}
+#pragma omp target teams is_device_ptr() // expected-error {{expected expression}}
+ {}
+#pragma omp target teams is_device_ptr(alloc) // expected-error {{use of undeclared identifier 'alloc'}}
+ {}
+#pragma omp target teams is_device_ptr(arg // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ {}
+#pragma omp target teams is_device_ptr(i) // expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ {}
+#pragma omp target teams is_device_ptr(j) // expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ {}
+#pragma omp target teams is_device_ptr(k) // OK
+ {}
+#pragma omp target teams is_device_ptr(z) // OK
+ {}
+#pragma omp target teams is_device_ptr(aa) // OK
+ {}
+#pragma omp target teams is_device_ptr(raa) // OK
+ {}
+#pragma omp target teams is_device_ptr(e) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ {}
+#pragma omp target teams is_device_ptr(g) // OK
+ {}
+#pragma omp target teams is_device_ptr(rg) // OK
+ {}
+#pragma omp target teams is_device_ptr(k,i,j) // expected-error2 {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ {}
+#pragma omp target teams is_device_ptr(d) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ {}
+#pragma omp target teams is_device_ptr(da) // OK
+ {}
+ return;
+ }
+};
+struct SB {
+ unsigned A;
+ unsigned B;
+ float Arr[100];
+ float *Ptr;
+ float *foo() {
+ return &Arr[0];
+ }
+};
+
+struct SC {
+ unsigned A : 2;
+ unsigned B : 3;
+ unsigned C;
+ unsigned D;
+ float Arr[100];
+ SB S;
+ SB ArrS[100];
+ SB *PtrS;
+ SB *&RPtrS;
+ float *Ptr;
+
+ SC(SB *&_RPtrS) : RPtrS(_RPtrS) {}
+};
+
+union SD {
+ unsigned A;
+ float B;
+};
+
+struct S1;
+extern S1 a;
+class S2 {
+ mutable int a;
+public:
+ S2():a(0) { }
+ S2(S2 &s2):a(s2.a) { }
+ static float S2s;
+ static const float S2sc;
+};
+const float S2::S2sc = 0;
+const S2 b;
+const S2 ba[5];
+class S3 {
+ int a;
+public:
+ S3():a(0) { }
+ S3(S3 &s3):a(s3.a) { }
+};
+const S3 c;
+const S3 ca[5];
+extern const int f;
+class S4 {
+ int a;
+ S4();
+ S4(const S4 &s4);
+public:
+ S4(int v):a(v) { }
+};
+class S5 {
+ int a;
+ S5():a(0) {}
+ S5(const S5 &s5):a(s5.a) { }
+public:
+ S5(int v):a(v) { }
+};
+
+S3 h;
+#pragma omp threadprivate(h)
+
+typedef struct {
+ int a;
+} S6;
+
+template <typename T, int I>
+T tmain(T argc) {
+ const T d = 5;
+ const T da[5] = { 0 };
+ S4 e(4);
+ S5 g(5);
+ S6 h[10];
+ auto &rh = h;
+ T i;
+ T &j = i;
+ T *k = &j;
+ T *&z = k;
+ T aa[10];
+ auto &raa = aa;
+ S6 *ps;
+#pragma omp target teams is_device_ptr // expected-error {{expected '(' after 'is_device_ptr'}}
+ {}
+#pragma omp target teams is_device_ptr( // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}}
+ {}
+#pragma omp target teams is_device_ptr() // expected-error {{expected expression}}
+ {}
+#pragma omp target teams is_device_ptr(alloc) // expected-error {{use of undeclared identifier 'alloc'}}
+ {}
+#pragma omp target teams is_device_ptr(argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ {}
+#pragma omp target teams is_device_ptr(i) // expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ {}
+#pragma omp target teams is_device_ptr(j) // expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ {}
+#pragma omp target teams is_device_ptr(k) // OK
+ {}
+#pragma omp target teams is_device_ptr(z) // OK
+ {}
+#pragma omp target teams is_device_ptr(aa) // OK
+ {}
+#pragma omp target teams is_device_ptr(raa) // OK
+ {}
+#pragma omp target teams is_device_ptr(e) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ {}
+#pragma omp target teams is_device_ptr(g) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ {}
+#pragma omp target teams is_device_ptr(h) // OK
+ {}
+#pragma omp target teams is_device_ptr(rh) // OK
+ {}
+#pragma omp target teams is_device_ptr(k,i,j) // expected-error2 {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ {}
+#pragma omp target teams is_device_ptr(d) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ {}
+#pragma omp target teams is_device_ptr(da) // OK
+ {}
+#pragma omp target teams map(ps) is_device_ptr(ps) // expected-error{{variable already marked as mapped in current construct}} expected-note{{used here}}
+ {}
+#pragma omp target teams is_device_ptr(ps) map(ps) // expected-error{{variable already marked as mapped in current construct}} expected-note{{used here}}
+ {}
+#pragma omp target teams map(ps->a) is_device_ptr(ps) // expected-error{{variable already marked as mapped in current construct}} expected-note{{used here}}
+ {}
+#pragma omp target teams is_device_ptr(ps) map(ps->a) // expected-error{{pointer cannot be mapped along with a section derived from itself}} expected-note{{used here}}
+ {}
+#pragma omp target teams is_device_ptr(ps) firstprivate(ps) // expected-error{{firstprivate variable cannot be in a is_device_ptr clause in '#pragma omp target teams' directive}}
+ {}
+#pragma omp target teams firstprivate(ps) is_device_ptr(ps) // expected-error{{firstprivate variable cannot be in a is_device_ptr clause in '#pragma omp target teams' directive}} expected-note{{defined as firstprivate}}
+ {}
+#pragma omp target teams is_device_ptr(ps) private(ps) // expected-error{{private variable cannot be in a is_device_ptr clause in '#pragma omp target teams' directive}}
+ {}
+#pragma omp target teams private(ps) is_device_ptr(ps) // expected-error{{private variable cannot be in a is_device_ptr clause in '#pragma omp target teams' directive}} expected-note{{defined as private}}
+ {}
+ return 0;
+}
+
+int main(int argc, char **argv) {
+ const int d = 5;
+ const int da[5] = { 0 };
+ S4 e(4);
+ S5 g(5);
+ S6 h[10];
+ auto &rh = h;
+ int i;
+ int &j = i;
+ int *k = &j;
+ int *&z = k;
+ int aa[10];
+ auto &raa = aa;
+ S6 *ps;
+#pragma omp target teams is_device_ptr // expected-error {{expected '(' after 'is_device_ptr'}}
+ {}
+#pragma omp target teams is_device_ptr( // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}}
+ {}
+#pragma omp target teams is_device_ptr() // expected-error {{expected expression}}
+ {}
+#pragma omp target teams is_device_ptr(alloc) // expected-error {{use of undeclared identifier 'alloc'}}
+ {}
+#pragma omp target teams is_device_ptr(argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ {}
+#pragma omp target teams is_device_ptr(i) // expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ {}
+#pragma omp target teams is_device_ptr(j) // expected-error {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ {}
+#pragma omp target teams is_device_ptr(k) // OK
+ {}
+#pragma omp target teams is_device_ptr(z) // OK
+ {}
+#pragma omp target teams is_device_ptr(aa) // OK
+ {}
+#pragma omp target teams is_device_ptr(raa) // OK
+ {}
+#pragma omp target teams is_device_ptr(e) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ {}
+#pragma omp target teams is_device_ptr(g) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ {}
+#pragma omp target teams is_device_ptr(h) // OK
+ {}
+#pragma omp target teams is_device_ptr(rh) // OK
+ {}
+#pragma omp target teams is_device_ptr(k,i,j) // expected-error2 {{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ {}
+#pragma omp target teams is_device_ptr(d) // expected-error{{expected pointer, array, reference to pointer, or reference to array in 'is_device_ptr clause'}}
+ {}
+#pragma omp target teams is_device_ptr(da) // OK
+ {}
+#pragma omp target teams map(ps) is_device_ptr(ps) // expected-error{{variable already marked as mapped in current construct}} expected-note{{used here}}
+ {}
+#pragma omp target teams is_device_ptr(ps) map(ps) // expected-error{{variable already marked as mapped in current construct}} expected-note{{used here}}
+ {}
+#pragma omp target teams map(ps->a) is_device_ptr(ps) // expected-error{{variable already marked as mapped in current construct}} expected-note{{used here}}
+ {}
+#pragma omp target teams is_device_ptr(ps) map(ps->a) // expected-error{{pointer cannot be mapped along with a section derived from itself}} expected-note{{used here}}
+ {}
+#pragma omp target teams is_device_ptr(ps) firstprivate(ps) // expected-error{{firstprivate variable cannot be in a is_device_ptr clause in '#pragma omp target teams' directive}}
+ {}
+#pragma omp target teams firstprivate(ps) is_device_ptr(ps) // expected-error{{firstprivate variable cannot be in a is_device_ptr clause in '#pragma omp target teams' directive}} expected-note{{defined as firstprivate}}
+ {}
+#pragma omp target teams is_device_ptr(ps) private(ps) // expected-error{{private variable cannot be in a is_device_ptr clause in '#pragma omp target teams' directive}}
+ {}
+#pragma omp target teams private(ps) is_device_ptr(ps) // expected-error{{private variable cannot be in a is_device_ptr clause in '#pragma omp target teams' directive}} expected-note{{defined as private}}
+ {}
+ return tmain<int, 3>(argc); // expected-note {{in instantiation of function template specialization 'tmain<int, 3>' requested here}}
+}
diff --git a/test/OpenMP/target_teams_map_messages.cpp b/test/OpenMP/target_teams_map_messages.cpp
new file mode 100644
index 000000000000..15839b848532
--- /dev/null
+++ b/test/OpenMP/target_teams_map_messages.cpp
@@ -0,0 +1,538 @@
+// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 200 %s
+// rUN: %clang_cc1 -DCCODE -verify -fopenmp -ferror-limit 200 -x c %s
+#ifdef CCODE
+void foo(int arg) {
+ const int n = 0;
+
+ double marr[10][10][10];
+
+ #pragma omp target teams map(marr[2][0:2][0:2]) // expected-error {{array section does not specify contiguous storage}}
+ {}
+ #pragma omp target teams map(marr[:][0:][:])
+ {}
+ #pragma omp target teams map(marr[:][1:][:]) // expected-error {{array section does not specify contiguous storage}}
+ {}
+ #pragma omp target teams map(marr[:][n:][:])
+ {}
+}
+#else
+template <typename T, int I>
+struct SA {
+ static int ss;
+ #pragma omp threadprivate(ss) // expected-note {{defined as threadprivate or thread local}}
+ float a;
+ int b[12];
+ float *c;
+ T d;
+ float e[I];
+ T *f;
+ void func(int arg) {
+ #pragma omp target teams map(arg,a,d)
+ {}
+ #pragma omp target teams map(arg[2:2],a,d) // expected-error {{subscripted value is not an array or pointer}}
+ {}
+ #pragma omp target teams map(arg,a*2) // expected-error {{expected expression containing only member accesses and/or array sections based on named variables}}
+ {}
+ #pragma omp target teams map(arg,(c+1)[2]) // expected-error {{expected expression containing only member accesses and/or array sections based on named variables}}
+ {}
+ #pragma omp target teams map(arg,a[:2],d) // expected-error {{subscripted value is not an array or pointer}}
+ {}
+ #pragma omp target teams map(arg,a,d[:2]) // expected-error {{subscripted value is not an array or pointer}}
+ {}
+
+ #pragma omp target teams map(to:ss) // expected-error {{threadprivate variables are not allowed in 'map' clause}}
+ {}
+
+ #pragma omp target teams map(to:b,e)
+ {}
+ #pragma omp target teams map(to:b,e) map(to:b) // expected-error {{variable already marked as mapped in current construct}} expected-note {{used here}}
+ {}
+ #pragma omp target teams map(to:b[:2],e)
+ {}
+ #pragma omp target teams map(to:b,e[:])
+ {}
+ #pragma omp target teams map(b[-1:]) // expected-error {{array section must be a subset of the original array}}
+ {}
+ #pragma omp target teams map(b[:-1]) // expected-error {{section length is evaluated to a negative value -1}}
+ {}
+
+ #pragma omp target teams map(always, tofrom: c,f)
+ {}
+ #pragma omp target teams map(always, tofrom: c[1:2],f)
+ {}
+ #pragma omp target teams map(always, tofrom: c,f[1:2])
+ {}
+ #pragma omp target teams map(always, tofrom: c[:],f) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
+ {}
+ #pragma omp target teams map(always, tofrom: c,f[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
+ {}
+ return;
+ }
+};
+
+struct SB {
+ unsigned A;
+ unsigned B;
+ float Arr[100];
+ float *Ptr;
+ float *foo() {
+ return &Arr[0];
+ }
+};
+
+struct SC {
+ unsigned A : 2;
+ unsigned B : 3;
+ unsigned C;
+ unsigned D;
+ float Arr[100];
+ SB S;
+ SB ArrS[100];
+ SB *PtrS;
+ SB *&RPtrS;
+ float *Ptr;
+
+ SC(SB *&_RPtrS) : RPtrS(_RPtrS) {}
+};
+
+union SD {
+ unsigned A;
+ float B;
+};
+
+void SAclient(int arg) {
+ SA<int,123> s;
+ s.func(arg); // expected-note {{in instantiation of member function}}
+ double marr[10][10][10];
+ double marr2[5][10][1];
+ double mvla[5][arg][10];
+ double ***mptr;
+ const int n = 0;
+ const int m = 1;
+ double mvla2[5][arg][m+n+10];
+
+ SB *p;
+
+ SD u;
+ SC r(p),t(p);
+ #pragma omp target teams map(r)
+ {}
+ #pragma omp target teams map(marr[2][0:2][0:2]) // expected-error {{array section does not specify contiguous storage}}
+ {}
+ #pragma omp target teams map(marr[:][0:2][0:2]) // expected-error {{array section does not specify contiguous storage}}
+ {}
+ #pragma omp target teams map(marr[2][3][0:2])
+ {}
+ #pragma omp target teams map(marr[:][:][:])
+ {}
+ #pragma omp target teams map(marr[:2][:][:])
+ {}
+ #pragma omp target teams map(marr[arg:][:][:])
+ {}
+ #pragma omp target teams map(marr[arg:])
+ {}
+ #pragma omp target teams map(marr[arg:][:arg][:]) // correct if arg is the size of dimension 2
+ {}
+ #pragma omp target teams map(marr[:arg][:])
+ {}
+ #pragma omp target teams map(marr[:arg][n:])
+ {}
+ #pragma omp target teams map(marr[:][:arg][n:]) // correct if arg is the size of dimension 2
+ {}
+ #pragma omp target teams map(marr[:][:m][n:]) // expected-error {{array section does not specify contiguous storage}}
+ {}
+ #pragma omp target teams map(marr[n:m][:arg][n:])
+ {}
+ #pragma omp target teams map(marr[:2][:1][:]) // expected-error {{array section does not specify contiguous storage}}
+ {}
+ #pragma omp target teams map(marr[:2][1:][:]) // expected-error {{array section does not specify contiguous storage}}
+ {}
+ #pragma omp target teams map(marr[:2][:][:1]) // expected-error {{array section does not specify contiguous storage}}
+ {}
+ #pragma omp target teams map(marr[:2][:][1:]) // expected-error {{array section does not specify contiguous storage}}
+ {}
+ #pragma omp target teams map(marr[:1][:2][:])
+ {}
+ #pragma omp target teams map(marr[:1][0][:])
+ {}
+ #pragma omp target teams map(marr[:arg][:2][:]) // correct if arg is 1
+ {}
+ #pragma omp target teams map(marr[:1][3:1][:2])
+ {}
+ #pragma omp target teams map(marr[:1][3:arg][:2]) // correct if arg is 1
+ {}
+ #pragma omp target teams map(marr[:1][3:2][:2]) // expected-error {{array section does not specify contiguous storage}}
+ {}
+ #pragma omp target teams map(marr[:2][:10][:])
+ {}
+ #pragma omp target teams map(marr[:2][:][:5+5])
+ {}
+ #pragma omp target teams map(marr[:2][2+2-4:][0:5+5])
+ {}
+
+ #pragma omp target teams map(marr[:1][:2][0]) // expected-error {{array section does not specify contiguous storage}}
+ {}
+ #pragma omp target teams map(marr2[:1][:2][0])
+ {}
+
+ #pragma omp target teams map(mvla[:1][:][0]) // correct if the size of dimension 2 is 1.
+ {}
+ #pragma omp target teams map(mvla[:2][:arg][:]) // correct if arg is the size of dimension 2.
+ {}
+ #pragma omp target teams map(mvla[:1][:2][0]) // expected-error {{array section does not specify contiguous storage}}
+ {}
+ #pragma omp target teams map(mvla[1][2:arg][:])
+ {}
+ #pragma omp target teams map(mvla[:1][:][:])
+ {}
+ #pragma omp target teams map(mvla2[:1][:2][:11])
+ {}
+ #pragma omp target teams map(mvla2[:1][:2][:10]) // expected-error {{array section does not specify contiguous storage}}
+ {}
+
+ #pragma omp target teams map(mptr[:2][2+2-4:1][0:5+5]) // expected-error {{array section does not specify contiguous storage}}
+ {}
+ #pragma omp target teams map(mptr[:1][:2-1][2:4-3])
+ {}
+ #pragma omp target teams map(mptr[:1][:arg][2:4-3]) // correct if arg is 1.
+ {}
+ #pragma omp target teams map(mptr[:1][:2-1][0:2])
+ {}
+ #pragma omp target teams map(mptr[:1][:2][0:2]) // expected-error {{array section does not specify contiguous storage}}
+ {}
+ #pragma omp target teams map(mptr[:1][:][0:2]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
+ {}
+ #pragma omp target teams map(mptr[:2][:1][0:2]) // expected-error {{array section does not specify contiguous storage}}
+ {}
+
+ #pragma omp target teams map(r.ArrS[0].B)
+ {}
+ #pragma omp target teams map(r.ArrS[:1].B) // expected-error {{OpenMP array section is not allowed here}}
+ {}
+ #pragma omp target teams map(r.ArrS[:arg].B) // expected-error {{OpenMP array section is not allowed here}}
+ {}
+ #pragma omp target teams map(r.ArrS[0].Arr[1:23])
+ {}
+ #pragma omp target teams map(r.ArrS[0].Arr[1:arg])
+ {}
+ #pragma omp target teams map(r.ArrS[0].Arr[arg:23])
+ {}
+ #pragma omp target teams map(r.ArrS[0].Error) // expected-error {{no member named 'Error' in 'SB'}}
+ {}
+ #pragma omp target teams map(r.ArrS[0].A, r.ArrS[1].A) // expected-error {{multiple array elements associated with the same variable are not allowed in map clauses of the same construct}} expected-note {{used here}}
+ {}
+ #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.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.S.Arr[:12])
+ {}
+ #pragma omp target teams map(r.S.foo()[:12]) // expected-error {{expected expression containing only member accesses and/or array sections based on named variables}}
+ {}
+ #pragma omp target teams map(r.C, r.D)
+ {}
+ #pragma omp target teams map(r.C, r.C) // expected-error {{variable already marked as mapped in current construct}} expected-note {{used here}}
+ {}
+ #pragma omp target teams map(r.C) map(r.C) // expected-error {{variable already marked as mapped in current construct}} expected-note {{used here}}
+ {}
+ #pragma omp target teams map(r.C, r.S) // this would be an error only caught at runtime - Sema would have to make sure there is not way for the missing data between fields to be mapped somewhere else.
+ {}
+ #pragma omp target teams map(r, r.S) // expected-error {{variable already marked as mapped in current construct}} expected-note {{used here}}
+ {}
+ #pragma omp target teams map(r.C, t.C)
+ {}
+ #pragma omp target teams map(r.A) // expected-error {{bit fields cannot be used to specify storage in a 'map' clause}}
+ {}
+ #pragma omp target teams map(r.Arr)
+ {}
+ #pragma omp target teams map(r.Arr[3:5])
+ {}
+ #pragma omp target teams map(r.Ptr[3:5])
+ {}
+ #pragma omp target teams map(r.ArrS[3:5].A) // expected-error {{OpenMP array section is not allowed here}}
+ {}
+ #pragma omp target teams map(r.ArrS[3:5].Arr[6:7]) // expected-error {{OpenMP array section is not allowed here}}
+ {}
+ #pragma omp target teams map(r.ArrS[3].Arr[6:7])
+ {}
+ #pragma omp target teams map(r.S.Arr[4:5])
+ {}
+ #pragma omp target teams map(r.S.Ptr[4:5])
+ {}
+ #pragma omp target teams map(r.S.Ptr[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
+ {}
+ #pragma omp target teams map((p+1)->A) // expected-error {{expected expression containing only member accesses and/or array sections based on named variables}}
+ {}
+ #pragma omp target teams map(u.B) // expected-error {{mapped storage cannot be derived from a union}}
+ {}
+
+ #pragma omp target data map(to: r.C) //expected-note {{used here}}
+ {
+ #pragma omp target teams map(r.D) // expected-error {{original storage of expression in data environment is shared but data environment do not fully contain mapped expression storage}}
+ {}
+ }
+
+ #pragma omp target data map(to: t.Ptr) //expected-note {{used here}}
+ {
+ #pragma omp target teams map(t.Ptr[:23]) // expected-error {{pointer cannot be mapped along with a section derived from itself}}
+ {}
+ }
+
+ #pragma omp target data map(to: t.C, t.D)
+ {
+ #pragma omp target data map(to: t.C)
+ {
+ #pragma omp target teams map(t.D)
+ {}
+ }
+ }
+
+ #pragma omp target data map(to: t)
+ {
+ #pragma omp target data map(to: t.C)
+ {
+ #pragma omp target teams map(t.D)
+ {}
+ }
+ }
+}
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note 2 {{declared here}}
+extern S1 a;
+class S2 {
+ mutable int a;
+public:
+ S2():a(0) { }
+ S2(S2 &s2):a(s2.a) { }
+ static float S2s; // expected-note 4 {{mappable type cannot contain static members}}
+ static const float S2sc; // expected-note 4 {{mappable type cannot contain static members}}
+};
+const float S2::S2sc = 0;
+const S2 b;
+const S2 ba[5];
+class S3 {
+ int a;
+public:
+ S3():a(0) { }
+ S3(S3 &s3):a(s3.a) { }
+};
+const S3 c;
+const S3 ca[5];
+extern const int f;
+class S4 {
+ int a;
+ S4();
+ S4(const S4 &s4);
+public:
+ S4(int v):a(v) { }
+};
+class S5 {
+ int a;
+ S5():a(0) {}
+ S5(const S5 &s5):a(s5.a) { }
+public:
+ S5(int v):a(v) { }
+};
+
+template <class T>
+struct S6;
+
+template<>
+struct S6<int> // expected-note {{mappable type cannot be polymorphic}}
+{
+ virtual void foo();
+};
+
+S3 h;
+#pragma omp threadprivate(h) // expected-note 2 {{defined as threadprivate or thread local}}
+
+typedef int from;
+
+template <typename T, int I> // expected-note {{declared here}}
+T tmain(T argc) {
+ const T d = 5;
+ const T da[5] = { 0 };
+ S4 e(4);
+ S5 g(5);
+ T i, t[20];
+ T &j = i;
+ T *k = &j;
+ T x;
+ T y;
+ T to, tofrom, always;
+ const T (&l)[5] = da;
+#pragma omp target teams map // expected-error {{expected '(' after 'map'}}
+ {}
+#pragma omp target teams map( // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}}
+ {}
+#pragma omp target teams map() // expected-error {{expected expression}}
+ {}
+#pragma omp target teams map(alloc) // expected-error {{use of undeclared identifier 'alloc'}}
+ {}
+#pragma omp target teams map(to argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected ',' or ')' in 'map' clause}}
+ {}
+#pragma omp target teams map(to:) // expected-error {{expected expression}}
+ {}
+#pragma omp target teams map(from: argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ {}
+#pragma omp target teams map(x: y) // expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}}
+ {}
+#pragma omp target teams map(x)
+ foo();
+#pragma omp target teams map(tofrom: t[:I])
+ foo();
+#pragma omp target teams map(T: a) // expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}} expected-error {{incomplete type 'S1' where a complete type is required}}
+ foo();
+#pragma omp target teams map(T) // expected-error {{'T' does not refer to a value}}
+ foo();
+#pragma omp target teams map(I) // expected-error 2 {{expected expression containing only member accesses and/or array sections based on named variables}}
+ foo();
+#pragma omp target teams map(S2::S2s)
+ foo();
+#pragma omp target teams map(S2::S2sc)
+ foo();
+#pragma omp target teams map(x)
+ foo();
+#pragma omp target teams map(to: x)
+ foo();
+#pragma omp target teams map(to: to)
+ foo();
+#pragma omp target teams map(to)
+ foo();
+#pragma omp target teams map(to, x)
+ foo();
+
+#pragma omp target data map(to x) // expected-error {{expected ',' or ')' in 'map' clause}}
+#pragma omp target data map(tofrom: argc > 0 ? x : y) // expected-error 2 {{expected expression containing only member accesses and/or array sections based on named variables}}
+#pragma omp target data map(argc)
+#pragma omp target data map(S1) // expected-error {{'S1' does not refer to a value}}
+#pragma omp target data map(a, b, c, d, f) // expected-error {{incomplete type 'S1' where a complete type is required}} expected-error 2 {{type 'S2' is not mappable to target}}
+#pragma omp target data map(ba) // expected-error 2 {{type 'S2' is not mappable to target}}
+#pragma omp target data map(ca)
+#pragma omp target data map(da)
+#pragma omp target data map(S2::S2s)
+#pragma omp target data map(S2::S2sc)
+#pragma omp target data map(e, g)
+#pragma omp target data map(h) // expected-error {{threadprivate variables are not allowed in 'map' clause}}
+#pragma omp target data map(k) map(k) // expected-error 2 {{variable already marked as mapped in current construct}} expected-note 2 {{used here}}
+#pragma omp target teams map(k), map(k[:5]) // expected-error 2 {{pointer cannot be mapped along with a section derived from itself}} expected-note 2 {{used here}}
+ foo();
+
+#pragma omp target data map(da)
+#pragma omp target teams map(da[:4])
+ foo();
+
+#pragma omp target data map(k, j, l) // expected-note 2 {{used here}}
+#pragma omp target data map(k[:4]) // expected-error 2 {{pointer cannot be mapped along with a section derived from itself}}
+#pragma omp target data map(j)
+#pragma omp target teams map(l) map(l[:5]) // expected-error 2 {{variable already marked as mapped in current construct}} expected-note 2 {{used here}}
+ foo();
+
+#pragma omp target data map(k[:4], j, l[:5]) // expected-note 2 {{used here}}
+#pragma omp target data map(k) // expected-error 2 {{pointer cannot be mapped along with a section derived from itself}}
+#pragma omp target data map(j)
+#pragma omp target teams map(l)
+ foo();
+
+#pragma omp target data map(always, tofrom: x)
+#pragma omp target data map(always: x) // expected-error {{missing map type}}
+#pragma omp target data map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always'}} expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}}
+#pragma omp target data map(always, tofrom: always, tofrom, x)
+#pragma omp target teams map(tofrom j) // expected-error {{expected ',' or ')' in 'map' clause}}
+ foo();
+ return 0;
+}
+
+int main(int argc, char **argv) {
+ const int d = 5;
+ const int da[5] = { 0 };
+ S4 e(4);
+ S5 g(5);
+ int i;
+ int &j = i;
+ int *k = &j;
+ S6<int> m;
+ int x;
+ int y;
+ int to, tofrom, always;
+ const int (&l)[5] = da;
+#pragma omp target data map // expected-error {{expected '(' after 'map'}} expected-error {{expected at least one map clause for '#pragma omp target data'}}
+#pragma omp target data map( // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}}
+#pragma omp target data map() // expected-error {{expected expression}}
+#pragma omp target data map(alloc) // expected-error {{use of undeclared identifier 'alloc'}}
+#pragma omp target data map(to argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected ',' or ')' in 'map' clause}}
+#pragma omp target data map(to:) // expected-error {{expected expression}}
+#pragma omp target data map(from: argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp target data map(x: y) // expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}}
+#pragma omp target teams map(x)
+ foo();
+
+#pragma omp target teams map(to: x)
+ foo();
+#pragma omp target teams map(to: to)
+ foo();
+#pragma omp target teams map(to)
+ foo();
+#pragma omp target teams map(to, x)
+ foo();
+
+#pragma omp target data map(to x) // expected-error {{expected ',' or ')' in 'map' clause}}
+#pragma omp target data map(tofrom: argc > 0 ? argv[1] : argv[2]) // expected-error {{xpected expression containing only member accesses and/or array sections based on named variables}}
+#pragma omp target data map(argc)
+#pragma omp target data map(S1) // expected-error {{'S1' does not refer to a value}}
+#pragma omp target data map(a, b, c, d, f) // expected-error {{incomplete type 'S1' where a complete type is required}} expected-error 2 {{type 'S2' is not mappable to target}}
+#pragma omp target data map(argv[1])
+#pragma omp target data map(ba) // expected-error 2 {{type 'S2' is not mappable to target}}
+#pragma omp target data map(ca)
+#pragma omp target data map(da)
+#pragma omp target data map(S2::S2s)
+#pragma omp target data map(S2::S2sc)
+#pragma omp target data map(e, g)
+#pragma omp target data map(h) // expected-error {{threadprivate variables are not allowed in 'map' clause}}
+#pragma omp target data map(k), map(k) // expected-error {{variable already marked as mapped in current construct}} expected-note {{used here}}
+#pragma omp target teams map(k), map(k[:5]) // expected-error {{pointer cannot be mapped along with a section derived from itself}} expected-note {{used here}}
+ foo();
+
+#pragma omp target data map(da)
+#pragma omp target teams map(da[:4])
+ foo();
+
+#pragma omp target data map(k, j, l) // expected-note {{used here}}
+#pragma omp target data map(k[:4]) // expected-error {{pointer cannot be mapped along with a section derived from itself}}
+#pragma omp target data map(j)
+#pragma omp target teams map(l) map(l[:5]) // expected-error {{variable already marked as mapped in current construct}} expected-note {{used here}}
+ foo();
+
+#pragma omp target data map(k[:4], j, l[:5]) // expected-note {{used here}}
+#pragma omp target data map(k) // expected-error {{pointer cannot be mapped along with a section derived from itself}}
+#pragma omp target data map(j)
+#pragma omp target teams map(l)
+ foo();
+
+#pragma omp target data map(always, tofrom: x)
+#pragma omp target data map(always: x) // expected-error {{missing map type}}
+#pragma omp target data map(tofrom, always: x) // expected-error {{incorrect map type modifier, expected 'always'}} expected-error {{incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'}}
+#pragma omp target data map(always, tofrom: always, tofrom, x)
+#pragma omp target teams map(tofrom j) // expected-error {{expected ',' or ')' in 'map' clause}}
+ foo();
+
+#pragma omp target teams private(j) map(j) // expected-error {{private variable cannot be in a map clause in '#pragma omp target teams' directive}} expected-note {{defined as private}}
+ {}
+
+#pragma omp target teams firstprivate(j) map(j) // expected-error {{firstprivate variable cannot be in a map clause in '#pragma omp target teams' directive}} expected-note {{defined as firstprivate}}
+ {}
+
+#pragma omp target teams map(m) // expected-error {{type 'S6<int>' is not mappable to target}}
+ {}
+
+ return tmain<int, 3>(argc)+tmain<from, 4>(argc); // expected-note {{in instantiation of function template specialization 'tmain<int, 3>' requested here}} expected-note {{in instantiation of function template specialization 'tmain<int, 4>' requested here}}
+}
+#endif
diff --git a/test/OpenMP/target_teams_messages.cpp b/test/OpenMP/target_teams_messages.cpp
new file mode 100644
index 000000000000..7fc7d1f1aab0
--- /dev/null
+++ b/test/OpenMP/target_teams_messages.cpp
@@ -0,0 +1,65 @@
+// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -o - %s
+
+void foo() {
+}
+
+#pragma omp target teams // expected-error {{unexpected OpenMP directive '#pragma omp target teams'}}
+
+int main(int argc, char **argv) {
+#pragma omp target teams { // expected-warning {{extra tokens at the end of '#pragma omp target teams' are ignored}}
+ foo();
+#pragma omp target teams ( // expected-warning {{extra tokens at the end of '#pragma omp target teams' are ignored}}
+ foo();
+#pragma omp target teams [ // expected-warning {{extra tokens at the end of '#pragma omp target teams' are ignored}}
+ foo();
+#pragma omp target teams ] // expected-warning {{extra tokens at the end of '#pragma omp target teams' are ignored}}
+ foo();
+#pragma omp target teams ) // expected-warning {{extra tokens at the end of '#pragma omp target teams' are ignored}}
+ foo();
+#pragma omp target teams } // expected-warning {{extra tokens at the end of '#pragma omp target teams' are ignored}}
+ foo();
+#pragma omp target teams
+ foo();
+#pragma omp target teams unknown() // expected-warning {{extra tokens at the end of '#pragma omp target teams' are ignored}}
+ foo();
+ L1:
+ foo();
+#pragma omp target teams
+ ;
+#pragma omp target teams
+ {
+ goto L1; // expected-error {{use of undeclared label 'L1'}}
+ argc++;
+ }
+
+ for (int i = 0; i < 10; ++i) {
+ switch(argc) {
+ case (0):
+ #pragma omp target teams
+ {
+ foo();
+ break; // expected-error {{'break' statement not in loop or switch statement}}
+ continue; // expected-error {{'continue' statement not in loop statement}}
+ }
+ default:
+ break;
+ }
+ }
+#pragma omp target teams default(none)
+ ++argc; // expected-error {{variable 'argc' must have explicitly specified data sharing attributes}}
+
+ goto L2; // expected-error {{use of undeclared label 'L2'}}
+#pragma omp target teams
+ L2:
+ foo();
+#pragma omp target teams
+ {
+ return 1; // expected-error {{cannot return from OpenMP region}}
+ }
+
+ [[]] // expected-error {{an attribute list cannot appear here}}
+#pragma omp target teams
+ for (int n = 0; n < 100; ++n) {}
+
+ return 0;
+}
diff --git a/test/OpenMP/target_teams_nowait_messages.cpp b/test/OpenMP/target_teams_nowait_messages.cpp
new file mode 100644
index 000000000000..9cf8cc34ca06
--- /dev/null
+++ b/test/OpenMP/target_teams_nowait_messages.cpp
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -verify -fopenmp -o - %s
+
+void foo() {
+}
+
+int main(int argc, char **argv) {
+#pragma omp target teams nowait( // expected-warning {{extra tokens at the end of '#pragma omp target teams' are ignored}}
+ foo();
+#pragma omp target teams nowait (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target teams' are ignored}}
+ foo();
+#pragma omp target teams nowait device (-10u)
+ foo();
+#pragma omp target teams nowait (3.14) device (-10u) // expected-warning {{extra tokens at the end of '#pragma omp target teams' are ignored}}
+ foo();
+
+ return 0;
+}
diff --git a/test/OpenMP/target_teams_num_teams_messages.cpp b/test/OpenMP/target_teams_num_teams_messages.cpp
new file mode 100644
index 000000000000..e220fb67477d
--- /dev/null
+++ b/test/OpenMP/target_teams_num_teams_messages.cpp
@@ -0,0 +1,85 @@
+// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 100 -o - %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note 2 {{declared here}}
+
+template <typename T, int C> // expected-note {{declared here}}
+T tmain(T argc) {
+ char **a;
+#pragma omp target teams num_teams(C)
+ foo();
+#pragma omp target teams num_teams(T) // expected-error {{'T' does not refer to a value}}
+ foo();
+#pragma omp target teams num_teams // expected-error {{expected '(' after 'num_teams'}}
+ foo();
+#pragma omp target teams num_teams( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ foo();
+#pragma omp target teams num_teams() // expected-error {{expected expression}}
+ foo();
+#pragma omp target teams num_teams(argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ foo();
+#pragma omp target teams num_teams(argc)) // expected-warning {{extra tokens at the end of '#pragma omp target teams' are ignored}}
+ foo();
+#pragma omp target teams num_teams(argc > 0 ? a[1] : a[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ foo();
+#pragma omp target teams num_teams(argc + argc)
+ foo();
+#pragma omp target teams num_teams(argc), num_teams (argc+1) // expected-error {{directive '#pragma omp target teams' cannot contain more than one 'num_teams' clause}}
+ foo();
+#pragma omp target teams num_teams(S1) // expected-error {{'S1' does not refer to a value}}
+ foo();
+#pragma omp target teams num_teams(-2) // expected-error {{argument to 'num_teams' clause must be a strictly positive integer value}}
+ foo();
+#pragma omp target teams num_teams(-10u)
+ foo();
+#pragma omp target teams num_teams(3.14) // expected-error 2 {{expression must have integral or unscoped enumeration type, not 'double'}}
+ foo();
+
+ return 0;
+}
+
+int main(int argc, char **argv) {
+#pragma omp target teams num_teams // expected-error {{expected '(' after 'num_teams'}}
+ foo();
+
+#pragma omp target teams num_teams ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ foo();
+
+#pragma omp target teams num_teams () // expected-error {{expected expression}}
+ foo();
+
+#pragma omp target teams num_teams (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ foo();
+
+#pragma omp target teams num_teams (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target teams' are ignored}}
+ foo();
+
+#pragma omp target teams num_teams (argc > 0 ? argv[1] : argv[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ foo();
+
+#pragma omp target teams num_teams (argc + argc)
+ foo();
+
+#pragma omp target teams num_teams (argc), num_teams (argc+1) // expected-error {{directive '#pragma omp target teams' cannot contain more than one 'num_teams' clause}}
+ foo();
+
+#pragma omp target teams num_teams (S1) // expected-error {{'S1' does not refer to a value}}
+ foo();
+
+#pragma omp target teams num_teams (-2) // expected-error {{argument to 'num_teams' clause must be a strictly positive integer value}}
+ foo();
+
+#pragma omp target teams num_teams (-10u)
+ foo();
+
+#pragma omp target teams num_teams (3.14) // expected-error {{expression must have integral or unscoped enumeration type, not 'double'}}
+ foo();
+
+ return tmain<int, 10>(argc); // expected-note {{in instantiation of function template specialization 'tmain<int, 10>' requested here}}
+}
diff --git a/test/OpenMP/target_teams_private_messages.cpp b/test/OpenMP/target_teams_private_messages.cpp
new file mode 100644
index 000000000000..69551ff96cc0
--- /dev/null
+++ b/test/OpenMP/target_teams_private_messages.cpp
@@ -0,0 +1,109 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}} expected-note{{forward declaration of 'S1'}}
+extern S1 a;
+class S2 {
+ mutable int a;
+public:
+ S2():a(0) { }
+ static float S2s; // expected-note {{static data member is predetermined as shared}}
+};
+const S2 b;
+const S2 ba[5];
+class S3 {
+ int a;
+public:
+ S3():a(0) { }
+};
+const S3 c; // expected-note {{global variable is predetermined as shared}}
+const S3 ca[5]; // expected-note {{global variable is predetermined as shared}}
+extern const int f; // expected-note {{global variable is predetermined as shared}}
+class S4 {
+ int a;
+ S4(); // expected-note {{implicitly declared private here}}
+public:
+ S4(int v):a(v) { }
+};
+class S5 {
+ int a;
+ S5():a(0) {} // expected-note {{implicitly declared private here}}
+public:
+ S5(int v):a(v) { }
+};
+
+int threadvar;
+#pragma omp threadprivate(threadvar) // expected-note {{defined as threadprivate or thread local}}
+
+namespace A {
+double x;
+#pragma omp threadprivate(x) // expected-note {{defined as threadprivate or thread local}}
+}
+namespace B {
+using A::x;
+}
+
+int main(int argc, char **argv) {
+ const int d = 5; // expected-note {{constant variable is predetermined as shared}}
+ const int da[5] = { 0 }; // expected-note {{constant variable is predetermined as shared}}
+ S4 e(4);
+ S5 g(5);
+ int i;
+ int &j = i;
+#pragma omp target teams private // expected-error {{expected '(' after 'private'}}
+ foo();
+#pragma omp target teams private ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ foo();
+#pragma omp target teams private () // expected-error {{expected expression}}
+ foo();
+#pragma omp target teams private (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ foo();
+#pragma omp target teams private (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ foo();
+#pragma omp target teams private (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ foo();
+#pragma omp target teams private (argc argv) // expected-error {{expected ',' or ')' in 'private' clause}}
+ foo();
+#pragma omp target teams private (S1) // expected-error {{'S1' does not refer to a value}}
+ foo();
+#pragma omp target teams private (a, b, c, d, f) // expected-error {{a private variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be private}}
+ foo();
+#pragma omp target teams private (argv[1]) // expected-error {{expected variable name}}
+ foo();
+#pragma omp target teams private(ba)
+ foo();
+#pragma omp target teams private(ca) // expected-error {{shared variable cannot be private}}
+ foo();
+#pragma omp target teams private(da) // expected-error {{shared variable cannot be private}}
+ foo();
+#pragma omp target teams private(S2::S2s) // expected-error {{shared variable cannot be private}}
+ foo();
+#pragma omp target teams private(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}}
+ foo();
+#pragma omp target teams private(threadvar, B::x) // expected-error 2 {{threadprivate or thread local variable cannot be private}}
+ foo();
+#pragma omp target teams shared(i), private(i) // expected-error {{shared variable cannot be private}} expected-note {{defined as shared}}
+ foo();
+#pragma omp target teams firstprivate(i) private(i) // expected-error {{firstprivate variable cannot be private}} expected-note {{defined as firstprivate}}
+ foo();
+#pragma omp target teams private(i)
+ foo();
+#pragma omp target teams private(j)
+ foo();
+#pragma omp target teams firstprivate(i)
+ for (int k = 0; k < 10; ++k) {
+#pragma omp parallel private(i)
+ foo();
+ }
+ static int m;
+#pragma omp target teams private(m) // OK
+ foo();
+
+ return 0;
+}
diff --git a/test/OpenMP/target_teams_reduction_messages.cpp b/test/OpenMP/target_teams_reduction_messages.cpp
new file mode 100644
index 000000000000..48fa310253c8
--- /dev/null
+++ b/test/OpenMP/target_teams_reduction_messages.cpp
@@ -0,0 +1,266 @@
+// 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
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+void foobar(int &ref) {
+#pragma omp target teams reduction(+:ref)
+ foo();
+}
+
+struct S1; // expected-note {{declared here}} expected-note 4 {{forward declaration of 'S1'}}
+extern S1 a;
+class S2 {
+ mutable int a;
+ S2 &operator+(const S2 &arg) { return (*this); } // expected-note 3 {{implicitly declared private here}}
+
+public:
+ S2() : a(0) {}
+ S2(S2 &s2) : a(s2.a) {}
+ static float S2s; // expected-note 2 {{static data member is predetermined as shared}}
+ static const float S2sc;
+};
+const float S2::S2sc = 0; // expected-note 2 {{'S2sc' defined here}}
+S2 b; // expected-note 3 {{'b' defined here}}
+const S2 ba[5]; // expected-note 2 {{'ba' defined here}}
+class S3 {
+ int a;
+
+public:
+ int b;
+ S3() : a(0) {}
+ S3(const S3 &s3) : a(s3.a) {}
+ S3 operator+(const S3 &arg1) { return arg1; }
+};
+int operator+(const S3 &arg1, const S3 &arg2) { return 5; }
+S3 c; // expected-note 3 {{'c' defined here}}
+const S3 ca[5]; // expected-note 2 {{'ca' defined here}}
+extern const int f; // expected-note 4 {{'f' declared here}}
+class S4 {
+ int a;
+ S4(); // expected-note {{implicitly declared private here}}
+ S4(const S4 &s4);
+ S4 &operator+(const S4 &arg) { return (*this); }
+
+public:
+ S4(int v) : a(v) {}
+};
+S4 &operator&=(S4 &arg1, S4 &arg2) { return arg1; }
+class S5 {
+ int a;
+ S5() : a(0) {} // expected-note {{implicitly declared private here}}
+ S5(const S5 &s5) : a(s5.a) {}
+ S5 &operator+(const S5 &arg);
+
+public:
+ S5(int v) : a(v) {}
+};
+class S6 { // expected-note 3 {{candidate function (the implicit copy assignment operator) not viable: no known conversion from 'int' to 'const S6' for 1st argument}}
+#if __cplusplus >= 201103L // C++11 or later
+// expected-note@-2 3 {{candidate function (the implicit move assignment operator) not viable}}
+#endif
+ int a;
+
+public:
+ S6() : a(6) {}
+ operator int() { return 6; }
+} o;
+
+S3 h, k;
+#pragma omp threadprivate(h) // expected-note 2 {{defined as threadprivate or thread local}}
+
+template <class T> // expected-note {{declared here}}
+T tmain(T argc) {
+ const T d = T(); // expected-note 4 {{'d' defined here}}
+ const T da[5] = {T()}; // expected-note 2 {{'da' defined here}}
+ T qa[5] = {T()};
+ T i;
+ T &j = i; // expected-note 4 {{'j' defined here}}
+ S3 &p = k; // expected-note 2 {{'p' defined here}}
+ const T &r = da[(int)i]; // expected-note 2 {{'r' defined here}}
+ T &q = qa[(int)i]; // expected-note 2 {{'q' defined here}}
+ T fl;
+#pragma omp target teams reduction // expected-error {{expected '(' after 'reduction'}}
+ foo();
+#pragma omp target teams reduction + // expected-error {{expected '(' after 'reduction'}} expected-warning {{extra tokens at the end of '#pragma omp target teams' are ignored}}
+ foo();
+#pragma omp target teams reduction( // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ foo();
+#pragma omp target teams reduction(- // expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ foo();
+#pragma omp target teams reduction() // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}}
+ foo();
+#pragma omp target teams reduction(*) // expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected expression}}
+ foo();
+#pragma omp target teams reduction(\) // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}}
+ foo();
+#pragma omp target teams reduction(& : argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{invalid operands to binary expression ('float' and 'float')}}
+ foo();
+#pragma omp target teams reduction(| : argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{invalid operands to binary expression ('float' and 'float')}}
+ foo();
+#pragma omp target teams reduction(|| : argc ? i : argc) // expected-error 2 {{expected variable name, array element or array section}}
+ foo();
+#pragma omp target teams reduction(foo : argc) //expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'float'}} expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'int'}}
+ foo();
+#pragma omp target teams reduction(&& : argc)
+ foo();
+#pragma omp target teams reduction(^ : T) // expected-error {{'T' does not refer to a value}}
+ foo();
+#pragma omp target teams reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
+ foo();
+#pragma omp target teams reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
+ foo();
+#pragma omp target teams reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
+ foo();
+#pragma omp target teams reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+ foo();
+#pragma omp target teams reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+ foo();
+#pragma omp target teams reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}} expected-error {{const-qualified list item cannot be reduction}}
+ foo();
+#pragma omp target teams reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
+ foo();
+#pragma omp target teams reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
+ foo();
+#pragma omp target teams reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+ foo();
+#pragma omp target teams reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}}
+ foo();
+#pragma omp target teams reduction(+ : o) // expected-error 2 {{no viable overloaded '='}}
+ foo();
+#pragma omp target teams private(i), reduction(+ : j), reduction(+ : q) // expected-error 4 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+ foo();
+#pragma omp parallel private(k)
+#pragma omp target teams reduction(+ : p), reduction(+ : p) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+ foo();
+#pragma omp target teams reduction(+ : p), reduction(+ : p) // expected-error 2 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 2 {{previously referenced here}}
+ foo();
+#pragma omp target teams reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
+ foo();
+#pragma omp parallel shared(i)
+#pragma omp parallel reduction(min : i)
+#pragma omp target teams reduction(max : j) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+ foo();
+#pragma omp target teams
+#pragma omp parallel for private(fl)
+ for (int i = 0; i < 10; ++i)
+ {}
+#pragma omp target teams reduction(+ : fl)
+ foo();
+#pragma omp target teams
+#pragma omp parallel for reduction(- : fl)
+ for (int i = 0; i < 10; ++i)
+ {}
+#pragma omp target teams reduction(+ : fl)
+ foo();
+
+ return T();
+}
+
+namespace A {
+double x;
+#pragma omp threadprivate(x) // expected-note {{defined as threadprivate or thread local}}
+}
+namespace B {
+using A::x;
+}
+
+int main(int argc, char **argv) {
+ const int d = 5; // expected-note 2 {{'d' defined here}}
+ const int da[5] = {0}; // expected-note {{'da' defined here}}
+ int qa[5] = {0};
+ S4 e(4);
+ S5 g(5);
+ int i;
+ int &j = i; // expected-note 2 {{'j' defined here}}
+ S3 &p = k; // expected-note 2 {{'p' defined here}}
+ const int &r = da[i]; // expected-note {{'r' defined here}}
+ int &q = qa[i]; // expected-note {{'q' defined here}}
+ float fl;
+#pragma omp target teams reduction // expected-error {{expected '(' after 'reduction'}}
+ foo();
+#pragma omp target teams reduction + // expected-error {{expected '(' after 'reduction'}} expected-warning {{extra tokens at the end of '#pragma omp target teams' are ignored}}
+ foo();
+#pragma omp target teams reduction( // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ foo();
+#pragma omp target teams reduction(- // expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ foo();
+#pragma omp target teams reduction() // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}}
+ foo();
+#pragma omp target teams reduction(*) // expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected expression}}
+ foo();
+#pragma omp target teams reduction(\) // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}}
+ foo();
+#pragma omp target teams reduction(foo : argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max'}}
+ foo();
+#pragma omp target teams reduction(| : argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ foo();
+#pragma omp target teams reduction(|| : argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name, array element or array section}}
+ foo();
+#pragma omp target teams reduction(~ : argc) // expected-error {{expected unqualified-id}}
+ foo();
+#pragma omp target teams reduction(&& : argc)
+ foo();
+#pragma omp target teams reduction(^ : S1) // expected-error {{'S1' does not refer to a value}}
+ foo();
+#pragma omp target teams reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified list item cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
+ foo();
+#pragma omp target teams reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified list item cannot be reduction}}
+ foo();
+#pragma omp target teams reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
+ foo();
+#pragma omp target teams reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+ foo();
+#pragma omp target teams reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+ foo();
+#pragma omp target teams reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}}
+ foo();
+#pragma omp target teams reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
+ foo();
+#pragma omp target teams reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
+ foo();
+#pragma omp target teams reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+ foo();
+#pragma omp target teams reduction(& : e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{invalid operands to binary expression ('S4' and 'S4')}} expected-error {{calling a private constructor of class 'S5'}} expected-error {{invalid operands to binary expression ('S5' and 'S5')}}
+ foo();
+#pragma omp target teams reduction(+ : h, k, B::x) // expected-error 2 {{threadprivate or thread local variable cannot be reduction}}
+ foo();
+#pragma omp target teams reduction(+ : o) // expected-error {{no viable overloaded '='}}
+ foo();
+#pragma omp target teams private(i), reduction(+ : j), reduction(+ : q) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+ foo();
+#pragma omp parallel private(k)
+#pragma omp target teams reduction(+ : p), reduction(+ : p) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+ foo();
+#pragma omp target teams reduction(+ : p), reduction(+ : p) // expected-error {{variable can appear only once in OpenMP 'reduction' clause}} expected-note {{previously referenced here}}
+ foo();
+#pragma omp target teams reduction(+ : r) // expected-error {{const-qualified list item cannot be reduction}}
+ foo();
+#pragma omp parallel shared(i)
+#pragma omp parallel reduction(min : i)
+#pragma omp target teams reduction(max : j) // expected-error {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+ foo();
+#pragma omp target teams
+#pragma omp parallel for private(fl)
+ for (int i = 0; i < 10; ++i)
+ {}
+#pragma omp target teams reduction(+ : fl)
+ foo();
+#pragma omp target teams
+#pragma omp parallel for reduction(- : fl)
+ for (int i = 0; i < 10; ++i)
+ {}
+#pragma omp target teams reduction(+ : fl)
+ foo();
+ static int m;
+#pragma omp target teams reduction(+ : m) // OK
+ foo();
+
+ return tmain(argc) + tmain(fl); // expected-note {{in instantiation of function template specialization 'tmain<int>' requested here}} expected-note {{in instantiation of function template specialization 'tmain<float>' requested here}}
+}
diff --git a/test/OpenMP/target_teams_shared_messages.cpp b/test/OpenMP/target_teams_shared_messages.cpp
new file mode 100644
index 000000000000..84e412eb4c4b
--- /dev/null
+++ b/test/OpenMP/target_teams_shared_messages.cpp
@@ -0,0 +1,110 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}}
+extern S1 a;
+class S2 {
+ mutable int a;
+public:
+ S2():a(0) { }
+ S2(S2 &s2):a(s2.a) { }
+};
+const S2 b;
+const S2 ba[5];
+class S3 {
+ int a;
+public:
+ S3():a(0) { }
+ S3(S3 &s3):a(s3.a) { }
+};
+const S3 c;
+const S3 ca[5];
+extern const int f;
+class S4 {
+ int a;
+ S4();
+ S4(const S4 &s4);
+public:
+ S4(int v):a(v) { }
+};
+class S5 {
+ int a;
+ S5():a(0) {}
+ S5(const S5 &s5):a(s5.a) { }
+public:
+ S5(int v):a(v) { }
+};
+
+S3 h;
+#pragma omp threadprivate(h) // expected-note {{defined as threadprivate or thread local}}
+
+namespace A {
+double x;
+#pragma omp threadprivate(x) // expected-note {{defined as threadprivate or thread local}}
+}
+namespace B {
+using A::x;
+}
+
+int main(int argc, char **argv) {
+ const int d = 5;
+ const int da[5] = { 0 };
+ S4 e(4);
+ S5 g(5);
+ int i;
+ int &j = i;
+#pragma omp target teams shared // expected-error {{expected '(' after 'shared'}}
+ foo();
+#pragma omp target teams shared ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ foo();
+#pragma omp target teams shared () // expected-error {{expected expression}}
+ foo();
+#pragma omp target teams shared (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ foo();
+#pragma omp target teams shared (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ foo();
+#pragma omp target teams shared (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ foo();
+#pragma omp target teams shared (argc)
+ foo();
+#pragma omp target teams shared (S1) // expected-error {{'S1' does not refer to a value}}
+ foo();
+#pragma omp target teams shared (a, b, c, d, f)
+ foo();
+#pragma omp target teams shared (argv[1]) // expected-error {{expected variable name}}
+ foo();
+#pragma omp target teams shared(ba)
+ foo();
+#pragma omp target teams shared(ca)
+ foo();
+#pragma omp target teams shared(da)
+ foo();
+#pragma omp target teams shared(e, g)
+ foo();
+#pragma omp target teams shared(h, B::x) // expected-error 2 {{threadprivate or thread local variable cannot be shared}}
+ foo();
+#pragma omp target teams private(i), shared(i) // expected-error {{private variable cannot be shared}} expected-note {{defined as private}}
+ foo();
+#pragma omp target teams firstprivate(i), shared(i) // expected-error {{firstprivate variable cannot be shared}} expected-note {{defined as firstprivate}}
+ foo();
+#pragma omp target teams private(i)
+ foo();
+#pragma omp target teams shared(i)
+ foo();
+#pragma omp target teams shared(j)
+ foo();
+#pragma omp target teams firstprivate(i)
+ foo();
+#pragma omp target teams shared(i)
+ foo();
+#pragma omp target teams shared(j)
+ foo();
+
+ return 0;
+}
diff --git a/test/OpenMP/target_teams_thread_limit_messages.cpp b/test/OpenMP/target_teams_thread_limit_messages.cpp
new file mode 100644
index 000000000000..2685f242196c
--- /dev/null
+++ b/test/OpenMP/target_teams_thread_limit_messages.cpp
@@ -0,0 +1,85 @@
+// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 100 -o - %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note 2 {{declared here}}
+
+template <typename T, int C> // expected-note {{declared here}}
+T tmain(T argc) {
+ char **a;
+#pragma omp target teams thread_limit(C)
+ foo();
+#pragma omp target teams thread_limit(T) // expected-error {{'T' does not refer to a value}}
+ foo();
+#pragma omp target teams thread_limit // expected-error {{expected '(' after 'thread_limit'}}
+ foo();
+#pragma omp target teams thread_limit( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ foo();
+#pragma omp target teams thread_limit() // expected-error {{expected expression}}
+ foo();
+#pragma omp target teams thread_limit(argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ foo();
+#pragma omp target teams thread_limit(argc)) // expected-warning {{extra tokens at the end of '#pragma omp target teams' are ignored}}
+ foo();
+#pragma omp target teams thread_limit(argc > 0 ? a[1] : a[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ foo();
+#pragma omp target teams thread_limit(argc + argc)
+ foo();
+#pragma omp target teams thread_limit(argc), thread_limit (argc+1) // expected-error {{directive '#pragma omp target teams' cannot contain more than one 'thread_limit' clause}}
+ foo();
+#pragma omp target teams thread_limit(S1) // expected-error {{'S1' does not refer to a value}}
+ foo();
+#pragma omp target teams thread_limit(-2) // expected-error {{argument to 'thread_limit' clause must be a strictly positive integer value}}
+ foo();
+#pragma omp target teams thread_limit(-10u)
+ foo();
+#pragma omp target teams thread_limit(3.14) // expected-error 2 {{expression must have integral or unscoped enumeration type, not 'double'}}
+ foo();
+
+ return 0;
+}
+
+int main(int argc, char **argv) {
+#pragma omp target teams thread_limit // expected-error {{expected '(' after 'thread_limit'}}
+ foo();
+
+#pragma omp target teams thread_limit ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ foo();
+
+#pragma omp target teams thread_limit () // expected-error {{expected expression}}
+ foo();
+
+#pragma omp target teams thread_limit (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ foo();
+
+#pragma omp target teams thread_limit (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target teams' are ignored}}
+ foo();
+
+#pragma omp target teams thread_limit (argc > 0 ? argv[1] : argv[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ foo();
+
+#pragma omp target teams thread_limit (argc + argc)
+ foo();
+
+#pragma omp target teams thread_limit (argc), thread_limit (argc+1) // expected-error {{directive '#pragma omp target teams' cannot contain more than one 'thread_limit' clause}}
+ foo();
+
+#pragma omp target teams thread_limit (S1) // expected-error {{'S1' does not refer to a value}}
+ foo();
+
+#pragma omp target teams thread_limit (-2) // expected-error {{argument to 'thread_limit' clause must be a strictly positive integer value}}
+ foo();
+
+#pragma omp target teams thread_limit (-10u)
+ foo();
+
+#pragma omp target teams thread_limit (3.14) // expected-error {{expression must have integral or unscoped enumeration type, not 'double'}}
+ foo();
+
+ return tmain<int, 10>(argc); // expected-note {{in instantiation of function template specialization 'tmain<int, 10>' requested here}}
+}
diff --git a/test/OpenMP/target_update_ast_print.cpp b/test/OpenMP/target_update_ast_print.cpp
index 3a98f54a0770..cbff907acaee 100644
--- a/test/OpenMP/target_update_ast_print.cpp
+++ b/test/OpenMP/target_update_ast_print.cpp
@@ -18,18 +18,18 @@ T foo(T targ, U uarg) {
#pragma omp target update from(b) if(l<5) device(l-1) nowait depend(inout:l)
return a + targ + (T)b;
}
-// CHECK: static int a;
-// CHECK-NEXT: float b;
+// 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 from(b) if(l < 5) device(l - 1) nowait depend(inout : l)
-// CHECK: static char a;
+// CHECK: static int a;
// CHECK-NEXT: float 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 from(b) if(l < 5) device(l - 1) nowait depend(inout : l)
-// CHECK: static T a;
-// CHECK-NEXT: U b;
+// CHECK: static char a;
+// CHECK-NEXT: float 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 from(b) if(l < 5) device(l - 1) nowait depend(inout : l)
diff --git a/test/OpenMP/target_update_depend_messages.cpp b/test/OpenMP/target_update_depend_messages.cpp
index fe3325d80fe4..64383a049104 100644
--- a/test/OpenMP/target_update_depend_messages.cpp
+++ b/test/OpenMP/target_update_depend_messages.cpp
@@ -50,7 +50,7 @@ int tmain(T argc, S **argv, R *env[]) {
#pragma omp target update to(z) depend(in : argv[argc: // expected-error {{expected expression}} expected-error {{expected ']'}} expected-error {{expected ')'}} expected-note {{to match this '['}} expected-note {{to match this '('}}
#pragma omp target update to(z) depend(in : argv[argc:argc] // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp target update to(z) depend(in : argv[0:-1]) // expected-error {{section length is evaluated to a negative value -1}}
- #pragma omp target update to(z) depend(in : argv[-1:0]) // expected-error {{section lower bound is evaluated to a negative value -1}}
+ #pragma omp target update to(z) depend(in : argv[-1:0])
#pragma omp target update to(z) depend(in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
#pragma omp target update to(z) depend(in : argv[3:4:1]) // expected-error {{expected ']'}} expected-note {{to match this '['}}
#pragma omp target update to(z) depend(in:a[0:1]) // expected-error {{subscripted value is not an array or pointer}}
@@ -98,7 +98,7 @@ int main(int argc, char **argv, char *env[]) {
#pragma omp target update to(z) depend(in : argv[argc: // expected-error {{expected expression}} expected-error {{expected ']'}} expected-error {{expected ')'}} expected-note {{to match this '['}} expected-note {{to match this '('}}
#pragma omp target update to(z) depend(in : argv[argc:argc] // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp target update to(z) depend(in : argv[0:-1]) // expected-error {{section length is evaluated to a negative value -1}}
- #pragma omp target update to(z) depend(in : argv[-1:0]) // expected-error {{section lower bound is evaluated to a negative value -1}}
+ #pragma omp target update to(z) depend(in : argv[-1:0])
#pragma omp target update to(z) depend(in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
#pragma omp target update to(z) depend(in : argv[3:4:1]) // expected-error {{expected ']'}} expected-note {{to match this '['}}
#pragma omp target update to(z) depend(in:a[0:1]) // expected-error {{subscripted value is not an array or pointer}}
diff --git a/test/OpenMP/target_update_if_messages.cpp b/test/OpenMP/target_update_if_messages.cpp
index 97715e072422..3d076a6389d1 100644
--- a/test/OpenMP/target_update_if_messages.cpp
+++ b/test/OpenMP/target_update_if_messages.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ferror-limit 100 %s
void foo() {
}
@@ -23,7 +23,7 @@ int tmain(T argc, S **argv) {
#pragma omp target update to(n) if (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp target update from(n) if (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp target update to(n) if(argc)
-#pragma omp target update from(n) if(target update // expected-warning {{missing ':' after directive name modifier - ignoring}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp target update from(n) if(target update // expected-error {{use of undeclared identifier 'target'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp target update to(n) if(target update : // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp target update from(n) if(target update : argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp target update to(n) if(target update : argc)
@@ -47,7 +47,7 @@ int main(int argc, char **argv) {
#pragma omp target update from(m) if (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp target update to(m) if (1 0) // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp target update from(m) if(if(tmain(argc, argv) // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
-#pragma omp target update to(m) if(target update // expected-warning {{missing ':' after directive name modifier - ignoring}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp target update to(m) if(target update // expected-error {{use of undeclared identifier 'target'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp target update from(m) if(target update : // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp target update to(m) if(target update : argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp target update from(m) if(target update : argc)
diff --git a/test/OpenMP/task_ast_print.cpp b/test/OpenMP/task_ast_print.cpp
index 37e5833dec5e..9a7d64ee5462 100644
--- a/test/OpenMP/task_ast_print.cpp
+++ b/test/OpenMP/task_ast_print.cpp
@@ -1,6 +1,6 @@
-// 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 -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
// expected-no-diagnostics
#ifndef HEADER
@@ -35,9 +35,9 @@ public:
}
};
-// CHECK: #pragma omp task private(this->a) private(this->a) private(this->S1::a)
// CHECK: #pragma omp task private(this->a) private(this->a) private(T::a)
// CHECK: #pragma omp task private(this->a) private(this->a)
+// CHECK: #pragma omp task private(this->a) private(this->a) private(this->S1::a)
class S8 : public S7<S1> {
S8() {}
@@ -66,18 +66,18 @@ struct S {
#pragma omp threadprivate(TS)
};
-// CHECK: template <class T = int> struct S {
+// CHECK: template <class T> struct S {
+// CHECK: static T TS;
+// CHECK-NEXT: #pragma omp threadprivate(S::TS)
+// CHECK: };
+// CHECK: template<> struct S<int> {
// CHECK: static int TS;
// CHECK-NEXT: #pragma omp threadprivate(S<int>::TS)
// CHECK-NEXT: }
-// CHECK: template <class T = long> struct S {
+// CHECK: template<> struct S<long> {
// CHECK: static long TS;
// CHECK-NEXT: #pragma omp threadprivate(S<long>::TS)
// CHECK-NEXT: }
-// CHECK: template <class T> struct S {
-// CHECK: static T TS;
-// CHECK-NEXT: #pragma omp threadprivate(S::TS)
-// CHECK: };
template <typename T, int C>
T tmain(T argc, T *argv) {
@@ -94,7 +94,18 @@ T tmain(T argc, T *argv) {
return 0;
}
-// CHECK: template <typename T = int, int C = 5> int tmain(int argc, int *argv) {
+// CHECK: template <typename T, int C> 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: T arr[argc];
+// CHECK-NEXT: #pragma omp task untied depend(in : argc,argv[b:argc],arr[:]) if(task: argc > 0)
+// CHECK-NEXT: a = 2;
+// CHECK-NEXT: #pragma omp task default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) final(S<T>::TS > 0) priority(argc)
+// CHECK-NEXT: foo()
+// CHECK-NEXT: #pragma omp task if(C) mergeable priority(C)
+// CHECK-NEXT: foo()
+// CHECK: template<> int tmain<int, 5>(int argc, int *argv) {
// CHECK-NEXT: int b = argc, c, d, e, f, g;
// CHECK-NEXT: static int a;
// CHECK-NEXT: S<int> s;
@@ -105,7 +116,7 @@ T tmain(T argc, T *argv) {
// CHECK-NEXT: foo()
// CHECK-NEXT: #pragma omp task if(5) mergeable priority(5)
// CHECK-NEXT: foo()
-// CHECK: template <typename T = long, int C = 1> long tmain(long argc, long *argv) {
+// CHECK: template<> long tmain<long, 1>(long argc, long *argv) {
// CHECK-NEXT: long b = argc, c, d, e, f, g;
// CHECK-NEXT: static long a;
// CHECK-NEXT: S<long> s;
@@ -116,17 +127,6 @@ T tmain(T argc, T *argv) {
// CHECK-NEXT: foo()
// CHECK-NEXT: #pragma omp task if(1) mergeable priority(1)
// CHECK-NEXT: foo()
-// CHECK: template <typename T, int C> 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: T arr[argc];
-// CHECK-NEXT: #pragma omp task untied depend(in : argc,argv[b:argc],arr[:]) if(task: argc > 0)
-// CHECK-NEXT: a = 2;
-// CHECK-NEXT: #pragma omp task default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) final(S<T>::TS > 0) priority(argc)
-// CHECK-NEXT: foo()
-// CHECK-NEXT: #pragma omp task if(C) mergeable priority(C)
-// CHECK-NEXT: foo()
enum Enum {};
diff --git a/test/OpenMP/task_codegen.cpp b/test/OpenMP/task_codegen.cpp
index 08c9ce33d8e8..4743ca3dc13c 100644
--- a/test/OpenMP/task_codegen.cpp
+++ b/test/OpenMP/task_codegen.cpp
@@ -2,7 +2,6 @@
// 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
// expected-no-diagnostics
-// REQUIRES: x86-registered-target
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/task_depend_messages.cpp b/test/OpenMP/task_depend_messages.cpp
index 39bf4847890c..576738ceac46 100644
--- a/test/OpenMP/task_depend_messages.cpp
+++ b/test/OpenMP/task_depend_messages.cpp
@@ -43,7 +43,7 @@ int main(int argc, char **argv, char *env[]) {
#pragma omp task depend (in : argv[argc: // expected-error {{expected expression}} expected-error {{expected ']'}} expected-error {{expected ')'}} expected-note {{to match this '['}} expected-note {{to match this '('}}
#pragma omp task depend (in : argv[argc:argc] // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp task depend (in : argv[0:-1]) // expected-error {{section length is evaluated to a negative value -1}}
- #pragma omp task depend (in : argv[-1:0]) // expected-error {{section lower bound is evaluated to a negative value -1}}
+ #pragma omp task depend (in : argv[-1:0])
#pragma omp task depend (in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
#pragma omp task depend (in : argv[3:4:1]) // expected-error {{expected ']'}} expected-note {{to match this '['}}
#pragma omp task depend(in:a[0:1]) // expected-error {{subscripted value is not an array or pointer}}
diff --git a/test/OpenMP/task_firstprivate_codegen.cpp b/test/OpenMP/task_firstprivate_codegen.cpp
index 0d8e1c4afe4e..7c15a18e7d40 100644
--- a/test/OpenMP/task_firstprivate_codegen.cpp
+++ b/test/OpenMP/task_firstprivate_codegen.cpp
@@ -5,7 +5,6 @@
// 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
// expected-no-diagnostics
-// REQUIRES: x86-registered-target
// It doesn't pass on win32.
// REQUIRES: shell
#ifndef ARRAY
@@ -27,7 +26,7 @@ volatile double g;
// CHECK-DAG: [[KMP_TASK_T_TY:%.+]] = type { i8*, i32 (i32, i8*)*, i32, %union{{.+}}, %union{{.+}} }
// CHECK-DAG: [[S_DOUBLE_TY:%.+]] = type { double }
// CHECK-DAG: [[PRIVATES_MAIN_TY:%.+]] = type {{.?}}{ [2 x [[S_DOUBLE_TY]]], [[S_DOUBLE_TY]], i32, [2 x i32]
-// CHECK-DAG: [[CAP_MAIN_TY:%.+]] = type {{.*}}{ [2 x i32]*, i32, {{.*}}[2 x [[S_DOUBLE_TY]]]*, [[S_DOUBLE_TY]]*, i{{[0-9]+}}
+// CHECK-DAG: [[CAP_MAIN_TY:%.+]] = type {{.*}}{ [[S_DOUBLE_TY]]*, [2 x i32]*, i32, {{.*}}[2 x [[S_DOUBLE_TY]]]*, i{{[0-9]+}}
// CHECK-DAG: [[KMP_TASK_MAIN_TY:%.+]] = type { [[KMP_TASK_T_TY]], [[PRIVATES_MAIN_TY]] }
// CHECK-DAG: [[S_INT_TY:%.+]] = type { i32 }
// CHECK-DAG: [[CAP_TMAIN_TY:%.+]] = type { [2 x i32]*, i32*, [2 x [[S_INT_TY]]]*, [[S_INT_TY]]* }
@@ -150,10 +149,11 @@ int main() {
int vec[] = {1, 2};
S<double> s_arr[] = {1, 2};
S<double> var(3);
-#pragma omp task firstprivate(var, t_var, s_arr, vec, s_arr, var, sivar)
+#pragma omp task firstprivate(t_var, s_arr, vec, sivar)
{
+ var.f = 1;
vec[0] = t_var;
- s_arr[0] = var;
+ s_arr[0] = S<double>(3);
sivar = 33;
}
return tmain<int>();
@@ -173,15 +173,15 @@ int main() {
// CHECK: call {{.*}} [[S_DOUBLE_TY_COPY_CONSTR:@.+]]([[S_DOUBLE_TY]]* [[TEST]],
// Store original variables in capture struct.
-// CHECK: [[VEC_REF:%.+]] = getelementptr inbounds [[CAP_MAIN_TY]], [[CAP_MAIN_TY]]* %{{.+}}, i{{[0-9]+}} 0, i{{[0-9]+}} 0
+// CHECK: [[VAR_REF:%.+]] = getelementptr inbounds [[CAP_MAIN_TY]], [[CAP_MAIN_TY]]* %{{.+}}, i{{[0-9]+}} 0, i{{[0-9]+}} 0
+// CHECK: store [[S_DOUBLE_TY]]* [[VAR_ADDR]], [[S_DOUBLE_TY]]** [[VAR_REF]],
+// CHECK: [[VEC_REF:%.+]] = getelementptr inbounds [[CAP_MAIN_TY]], [[CAP_MAIN_TY]]* %{{.+}}, i{{[0-9]+}} 0, i{{[0-9]+}} 1
// CHECK: store [2 x i32]* [[VEC_ADDR]], [2 x i32]** [[VEC_REF]],
-// CHECK: [[T_VAR_REF:%.+]] = getelementptr inbounds [[CAP_MAIN_TY]], [[CAP_MAIN_TY]]* %{{.+}}, i{{[0-9]+}} 0, i{{[0-9]+}} 1
+// CHECK: [[T_VAR_REF:%.+]] = getelementptr inbounds [[CAP_MAIN_TY]], [[CAP_MAIN_TY]]* %{{.+}}, i{{[0-9]+}} 0, i{{[0-9]+}} 2
// CHECK: [[T_VAR:%.+]] = load i32, i32* [[T_VAR_ADDR]],
// CHECK: store i32 [[T_VAR]], i32* [[T_VAR_REF]],
-// CHECK: [[S_ARR_REF:%.+]] = getelementptr inbounds [[CAP_MAIN_TY]], [[CAP_MAIN_TY]]* %{{.+}}, i{{[0-9]+}} 0, i{{[0-9]+}} 3
+// CHECK: [[S_ARR_REF:%.+]] = getelementptr inbounds [[CAP_MAIN_TY]], [[CAP_MAIN_TY]]* %{{.+}}, i{{[0-9]+}} 0, i{{[0-9]+}} 4
// CHECK: store [2 x [[S_DOUBLE_TY]]]* [[S_ARR_ADDR]], [2 x [[S_DOUBLE_TY]]]** [[S_ARR_REF]],
-// CHECK: [[VAR_REF:%.+]] = getelementptr inbounds [[CAP_MAIN_TY]], [[CAP_MAIN_TY]]* %{{.+}}, i{{[0-9]+}} 0, i{{[0-9]+}} 4
-// CHECK: store [[S_DOUBLE_TY]]* [[VAR_ADDR]], [[S_DOUBLE_TY]]** [[VAR_REF]],
// CHECK: [[SIVAR_REF:%.+]] = getelementptr inbounds [[CAP_MAIN_TY]], [[CAP_MAIN_TY]]* %{{.+}}, i{{[0-9]+}} 0, i{{[0-9]+}} 5
// CHECK: [[SIVAR_VAL:%.+]] = load i32, i32* [[SIVAR]],
// CHECK: store i{{[0-9]+}} [[SIVAR_VAL]], i{{[0-9]+}}* [[SIVAR_REF]],
@@ -209,7 +209,7 @@ int main() {
// Constructors for s_arr and var.
// s_arr;
// CHECK: [[PRIVATE_S_ARR_REF:%.+]] = getelementptr inbounds [[PRIVATES_MAIN_TY]], [[PRIVATES_MAIN_TY]]* [[PRIVATES]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
-// CHECK: [[S_ARR_ADDR_REF:%.+]] = getelementptr inbounds [[CAP_MAIN_TY]], [[CAP_MAIN_TY]]* [[SHAREDS]], i{{.+}} 0, i{{.+}} 3
+// CHECK: [[S_ARR_ADDR_REF:%.+]] = getelementptr inbounds [[CAP_MAIN_TY]], [[CAP_MAIN_TY]]* [[SHAREDS]], i{{.+}} 0, i{{.+}} 4
// CHECK: load [2 x [[S_DOUBLE_TY]]]*, [2 x [[S_DOUBLE_TY]]]** [[S_ARR_ADDR_REF]],
// CHECK: call void [[S_DOUBLE_TY_COPY_CONSTR]]([[S_DOUBLE_TY]]* [[S_ARR_CUR:%[^,]+]],
// CHECK: getelementptr [[S_DOUBLE_TY]], [[S_DOUBLE_TY]]* [[S_ARR_CUR]], i{{.+}} 1
@@ -219,19 +219,19 @@ int main() {
// var;
// CHECK: [[PRIVATE_VAR_REF:%.+]] = getelementptr inbounds [[PRIVATES_MAIN_TY]], [[PRIVATES_MAIN_TY]]* [[PRIVATES]], i{{.+}} 0, i{{.+}} 1
-// CHECK: [[VAR_ADDR_REF:%.+]] = getelementptr inbounds [[CAP_MAIN_TY]], [[CAP_MAIN_TY]]* [[SHAREDS]], i{{.+}} 0, i{{.+}} 4
+// CHECK: [[VAR_ADDR_REF:%.+]] = getelementptr inbounds [[CAP_MAIN_TY]], [[CAP_MAIN_TY]]* [[SHAREDS]], i{{.+}} 0, i{{.+}} 0
// CHECK: [[VAR_REF:%.+]] = load [[S_DOUBLE_TY]]*, [[S_DOUBLE_TY]]** [[VAR_ADDR_REF]],
// CHECK: call void [[S_DOUBLE_TY_COPY_CONSTR]]([[S_DOUBLE_TY]]* [[PRIVATE_VAR_REF]], [[S_DOUBLE_TY]]* {{.*}}[[VAR_REF]],
// t_var;
// CHECK: [[PRIVATE_T_VAR_REF:%.+]] = getelementptr inbounds [[PRIVATES_MAIN_TY]], [[PRIVATES_MAIN_TY]]* [[PRIVATES]], i{{.+}} 0, i{{.+}} 2
-// CHECK: [[T_VAR_REF:%.+]] = getelementptr inbounds [[CAP_MAIN_TY]], [[CAP_MAIN_TY]]* [[SHAREDS]], i{{.+}} 0, i{{.+}} 1
+// CHECK: [[T_VAR_REF:%.+]] = getelementptr inbounds [[CAP_MAIN_TY]], [[CAP_MAIN_TY]]* [[SHAREDS]], i{{.+}} 0, i{{.+}} 2
// CHECK: [[T_VAR:%.+]] = load i{{.+}}, i{{.+}}* [[T_VAR_REF]],
// CHECK: store i32 [[T_VAR]], i32* [[PRIVATE_T_VAR_REF]],
// vec;
// CHECK: [[PRIVATE_VEC_REF:%.+]] = getelementptr inbounds [[PRIVATES_MAIN_TY]], [[PRIVATES_MAIN_TY]]* [[PRIVATES]], i{{.+}} 0, i{{.+}} 3
-// CHECK: [[VEC_ADDR_REF:%.+]] = getelementptr inbounds [[CAP_MAIN_TY]], [[CAP_MAIN_TY]]* [[SHAREDS]], i{{.+}} 0, i{{.+}} 0
+// CHECK: [[VEC_ADDR_REF:%.+]] = getelementptr inbounds [[CAP_MAIN_TY]], [[CAP_MAIN_TY]]* [[SHAREDS]], i{{.+}} 0, i{{.+}} 1
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(
// sivar;
@@ -259,7 +259,7 @@ int main() {
// CHECK: ret
//
-// CHECK: define internal void [[PRIVATES_MAP_FN:@.+]]([[PRIVATES_MAIN_TY]]* noalias, [[S_DOUBLE_TY]]** noalias, i32** noalias, [2 x [[S_DOUBLE_TY]]]** noalias, [2 x i32]** noalias, i32** noalias)
+// CHECK: define internal void [[PRIVATES_MAP_FN:@.+]]([[PRIVATES_MAIN_TY]]* noalias, i32** noalias, [2 x [[S_DOUBLE_TY]]]** noalias, [2 x i32]** noalias, i32** noalias, [[S_DOUBLE_TY]]** noalias)
// CHECK: [[PRIVATES:%.+]] = load [[PRIVATES_MAIN_TY]]*, [[PRIVATES_MAIN_TY]]**
// CHECK: [[PRIV_S_VAR:%.+]] = getelementptr inbounds [[PRIVATES_MAIN_TY]], [[PRIVATES_MAIN_TY]]* [[PRIVATES]], i32 0, i32 0
// CHECK: [[ARG3:%.+]] = load [2 x [[S_DOUBLE_TY]]]**, [2 x [[S_DOUBLE_TY]]]*** %{{.+}},
@@ -280,21 +280,22 @@ int main() {
// CHECK: define internal i32 [[TASK_ENTRY]](i32, [[KMP_TASK_MAIN_TY]]* noalias)
-// CHECK: [[PRIV_VAR_ADDR:%.+]] = alloca [[S_DOUBLE_TY]]*,
+// CHECK: alloca i32*,
// CHECK: [[PRIV_T_VAR_ADDR:%.+]] = alloca i32*,
// CHECK: [[PRIV_S_ARR_ADDR:%.+]] = alloca [2 x [[S_DOUBLE_TY]]]*,
// CHECK: [[PRIV_VEC_ADDR:%.+]] = alloca [2 x i32]*,
// CHECK: [[PRIV_SIVAR_ADDR:%.+]] = alloca i32*,
-// CHECK: store void (i8*, ...)* bitcast (void ([[PRIVATES_MAIN_TY]]*, [[S_DOUBLE_TY]]**, i32**, [2 x [[S_DOUBLE_TY]]]**, [2 x i32]**, i32**)* [[PRIVATES_MAP_FN]] to void (i8*, ...)*), void (i8*, ...)** [[MAP_FN_ADDR:%.+]],
+// CHECK: [[PRIV_VAR_ADDR:%.+]] = alloca [[S_DOUBLE_TY]]*,
+// CHECK: store void (i8*, ...)* bitcast (void ([[PRIVATES_MAIN_TY]]*, i32**, [2 x [[S_DOUBLE_TY]]]**, [2 x i32]**, i32**, [[S_DOUBLE_TY]]**)* [[PRIVATES_MAP_FN]] to void (i8*, ...)*), void (i8*, ...)** [[MAP_FN_ADDR:%.+]],
// CHECK: [[MAP_FN:%.+]] = load void (i8*, ...)*, void (i8*, ...)** [[MAP_FN_ADDR]],
-// CHECK: call void (i8*, ...) [[MAP_FN]](i8* %{{.+}}, [[S_DOUBLE_TY]]** [[PRIV_VAR_ADDR]], i32** [[PRIV_T_VAR_ADDR]], [2 x [[S_DOUBLE_TY]]]** [[PRIV_S_ARR_ADDR]], [2 x i32]** [[PRIV_VEC_ADDR]], i32** [[PRIV_SIVAR_ADDR]])
+// CHECK: call void (i8*, ...) [[MAP_FN]](i8* %{{.+}}, i32** [[PRIV_T_VAR_ADDR]], [2 x [[S_DOUBLE_TY]]]** [[PRIV_S_ARR_ADDR]], [2 x i32]** [[PRIV_VEC_ADDR]], i32** [[PRIV_SIVAR_ADDR]], [[S_DOUBLE_TY]]** [[PRIV_VAR_ADDR]])
-// CHECK: [[PRIV_VAR:%.+]] = load [[S_DOUBLE_TY]]*, [[S_DOUBLE_TY]]** [[PRIV_VAR_ADDR]],
// CHECK: [[PRIV_T_VAR:%.+]] = load i32*, i32** [[PRIV_T_VAR_ADDR]],
// CHECK: [[PRIV_S_ARR:%.+]] = load [2 x [[S_DOUBLE_TY]]]*, [2 x [[S_DOUBLE_TY]]]** [[PRIV_S_ARR_ADDR]],
// CHECK: [[PRIV_VEC:%.+]] = load [2 x i32]*, [2 x i32]** [[PRIV_VEC_ADDR]],
// CHECK: [[PRIV_SIVAR:%.+]] = load i32*, i32** [[PRIV_SIVAR_ADDR]],
+// CHECK: [[PRIV_VAR:%.+]] = load [[S_DOUBLE_TY]]*, [[S_DOUBLE_TY]]** [[PRIV_VAR_ADDR]],
// Privates actually are used.
// CHECK-DAG: [[PRIV_VAR]]
diff --git a/test/OpenMP/task_if_codegen.cpp b/test/OpenMP/task_if_codegen.cpp
index 4226dceda86e..5952085b6ec1 100644
--- a/test/OpenMP/task_if_codegen.cpp
+++ b/test/OpenMP/task_if_codegen.cpp
@@ -1,7 +1,6 @@
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck %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
-// REQUIRES: x86-registered-target
+// 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
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/task_if_messages.cpp b/test/OpenMP/task_if_messages.cpp
index f3f56d51673a..89b10f71d3d9 100644
--- a/test/OpenMP/task_if_messages.cpp
+++ b/test/OpenMP/task_if_messages.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ferror-limit 100 %s
void foo() {
}
diff --git a/test/OpenMP/task_private_codegen.cpp b/test/OpenMP/task_private_codegen.cpp
index 97155a73f1bd..021749912a05 100644
--- a/test/OpenMP/task_private_codegen.cpp
+++ b/test/OpenMP/task_private_codegen.cpp
@@ -5,7 +5,6 @@
// 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
// expected-no-diagnostics
-// REQUIRES: x86-registered-target
// It doesn't pass on win32. Investigating.
// REQUIRES: shell
diff --git a/test/OpenMP/taskgroup_codegen.cpp b/test/OpenMP/taskgroup_codegen.cpp
index 0f6e81b3ba0b..4b7d89e70391 100644
--- a/test/OpenMP/taskgroup_codegen.cpp
+++ b/test/OpenMP/taskgroup_codegen.cpp
@@ -3,7 +3,6 @@
// 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
// expected-no-diagnostics
-// REQUIRES: x86-registered-target
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/taskloop_ast_print.cpp b/test/OpenMP/taskloop_ast_print.cpp
index 06164ab168d9..d2fae3fe0f4f 100644
--- a/test/OpenMP/taskloop_ast_print.cpp
+++ b/test/OpenMP/taskloop_ast_print.cpp
@@ -1,6 +1,6 @@
-// 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 -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
// expected-no-diagnostics
#ifndef HEADER
@@ -48,6 +48,7 @@ T tmain(T argc) {
return T();
}
+// CHECK-LABEL: int main(int argc, char **argv) {
int main(int argc, char **argv) {
int b = argc, c, d, e, f, g;
static int a;
diff --git a/test/OpenMP/taskloop_codegen.cpp b/test/OpenMP/taskloop_codegen.cpp
index e585fcec10d5..bc7367ce0216 100644
--- a/test/OpenMP/taskloop_codegen.cpp
+++ b/test/OpenMP/taskloop_codegen.cpp
@@ -2,7 +2,6 @@
// 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
// expected-no-diagnostics
-// REQUIRES: x86-registered-target
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/taskloop_firstprivate_codegen.cpp b/test/OpenMP/taskloop_firstprivate_codegen.cpp
index 822a5c687dc7..f4358db99b8c 100644
--- a/test/OpenMP/taskloop_firstprivate_codegen.cpp
+++ b/test/OpenMP/taskloop_firstprivate_codegen.cpp
@@ -5,7 +5,6 @@
// 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
// expected-no-diagnostics
-// REQUIRES: x86-registered-target
// It doesn't pass on win32.
// REQUIRES: shell
#ifndef ARRAY
diff --git a/test/OpenMP/taskloop_lastprivate_codegen.cpp b/test/OpenMP/taskloop_lastprivate_codegen.cpp
index 8414b6f963f9..e689feba20ac 100644
--- a/test/OpenMP/taskloop_lastprivate_codegen.cpp
+++ b/test/OpenMP/taskloop_lastprivate_codegen.cpp
@@ -5,7 +5,6 @@
// 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
// expected-no-diagnostics
-// REQUIRES: x86-registered-target
// It doesn't pass on win32.
// REQUIRES: shell
#ifndef ARRAY
diff --git a/test/OpenMP/taskloop_private_codegen.cpp b/test/OpenMP/taskloop_private_codegen.cpp
index 38b20c579393..dad9a17767fc 100644
--- a/test/OpenMP/taskloop_private_codegen.cpp
+++ b/test/OpenMP/taskloop_private_codegen.cpp
@@ -5,7 +5,6 @@
// 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
// expected-no-diagnostics
-// REQUIRES: x86-registered-target
// It doesn't pass on win32. Investigating.
// REQUIRES: shell
diff --git a/test/OpenMP/taskloop_simd_aligned_messages.cpp b/test/OpenMP/taskloop_simd_aligned_messages.cpp
index b45f44fe1cf8..6085660b705e 100644
--- a/test/OpenMP/taskloop_simd_aligned_messages.cpp
+++ b/test/OpenMP/taskloop_simd_aligned_messages.cpp
@@ -121,7 +121,8 @@ template<class I, class C> int foomain(I argc, C **argv) {
for (I k = 0; k < argc; ++k) ++k;
#pragma omp taskloop simd aligned (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
for (I k = 0; k < argc; ++k) ++k;
- #pragma omp taskloop simd aligned (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+// FIXME: Should argc really be a pointer?
+ #pragma omp taskloop simd aligned (*argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
for (I k = 0; k < argc; ++k) ++k;
#pragma omp taskloop simd aligned (argc : 5) // expected-warning {{aligned clause will be ignored because the requested alignment is not a power of 2}}
for (I k = 0; k < argc; ++k) ++k;
diff --git a/test/OpenMP/taskloop_simd_ast_print.cpp b/test/OpenMP/taskloop_simd_ast_print.cpp
index 3e3b7e4bec2a..f16b470a3012 100644
--- a/test/OpenMP/taskloop_simd_ast_print.cpp
+++ b/test/OpenMP/taskloop_simd_ast_print.cpp
@@ -1,6 +1,6 @@
-// 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 -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
// expected-no-diagnostics
#ifndef HEADER
@@ -49,6 +49,7 @@ T tmain(T argc) {
return T();
}
+// CHECK-LABEL: int main(int argc, char **argv) {
int main(int argc, char **argv) {
int b = argc, c, d, e, f, g;
static int a;
diff --git a/test/OpenMP/taskloop_simd_codegen.cpp b/test/OpenMP/taskloop_simd_codegen.cpp
index dc60009ff2bd..60ba5f22129b 100644
--- a/test/OpenMP/taskloop_simd_codegen.cpp
+++ b/test/OpenMP/taskloop_simd_codegen.cpp
@@ -2,7 +2,6 @@
// 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
// expected-no-diagnostics
-// REQUIRES: x86-registered-target
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/taskloop_simd_firstprivate_codegen.cpp b/test/OpenMP/taskloop_simd_firstprivate_codegen.cpp
index 0b87ddd9acb1..230ef980e64d 100644
--- a/test/OpenMP/taskloop_simd_firstprivate_codegen.cpp
+++ b/test/OpenMP/taskloop_simd_firstprivate_codegen.cpp
@@ -5,7 +5,6 @@
// 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
// expected-no-diagnostics
-// REQUIRES: x86-registered-target
// It doesn't pass on win32.
// REQUIRES: shell
#ifndef ARRAY
diff --git a/test/OpenMP/taskloop_simd_lastprivate_codegen.cpp b/test/OpenMP/taskloop_simd_lastprivate_codegen.cpp
index e3562a8f0c62..41f04f9bdb3c 100644
--- a/test/OpenMP/taskloop_simd_lastprivate_codegen.cpp
+++ b/test/OpenMP/taskloop_simd_lastprivate_codegen.cpp
@@ -5,7 +5,6 @@
// 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
// expected-no-diagnostics
-// REQUIRES: x86-registered-target
// It doesn't pass on win32.
// REQUIRES: shell
#ifndef ARRAY
diff --git a/test/OpenMP/taskloop_simd_private_codegen.cpp b/test/OpenMP/taskloop_simd_private_codegen.cpp
index 557601e9c93e..493137ade65f 100644
--- a/test/OpenMP/taskloop_simd_private_codegen.cpp
+++ b/test/OpenMP/taskloop_simd_private_codegen.cpp
@@ -5,7 +5,6 @@
// 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
// expected-no-diagnostics
-// REQUIRES: x86-registered-target
// It doesn't pass on win32. Investigating.
// REQUIRES: shell
diff --git a/test/OpenMP/taskwait_ast_print.cpp b/test/OpenMP/taskwait_ast_print.cpp
index b5b0f0dd8d31..1a69b58a37ba 100644
--- a/test/OpenMP/taskwait_ast_print.cpp
+++ b/test/OpenMP/taskwait_ast_print.cpp
@@ -14,12 +14,12 @@ T tmain(T argc) {
#pragma omp taskwait
return a + argc;
}
+// CHECK: static T a;
+// CHECK-NEXT: #pragma omp taskwait
// CHECK: static int a;
// CHECK-NEXT: #pragma omp taskwait
// CHECK: static char a;
// CHECK-NEXT: #pragma omp taskwait
-// CHECK: static T a;
-// CHECK-NEXT: #pragma omp taskwait
int main(int argc, char **argv) {
static int a;
diff --git a/test/OpenMP/taskwait_codegen.cpp b/test/OpenMP/taskwait_codegen.cpp
index 7521709f01b6..492786eb8058 100644
--- a/test/OpenMP/taskwait_codegen.cpp
+++ b/test/OpenMP/taskwait_codegen.cpp
@@ -2,7 +2,6 @@
// 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
// expected-no-diagnostics
-// REQUIRES: x86-registered-target
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/taskyield_ast_print.cpp b/test/OpenMP/taskyield_ast_print.cpp
index 87679092d18c..1fd9b9c14d4e 100644
--- a/test/OpenMP/taskyield_ast_print.cpp
+++ b/test/OpenMP/taskyield_ast_print.cpp
@@ -14,12 +14,12 @@ T tmain(T argc) {
#pragma omp taskyield
return a + argc;
}
+// CHECK: static T a;
+// CHECK-NEXT: #pragma omp taskyield
// CHECK: static int a;
// CHECK-NEXT: #pragma omp taskyield
// CHECK: static char a;
// CHECK-NEXT: #pragma omp taskyield
-// CHECK: static T a;
-// CHECK-NEXT: #pragma omp taskyield
int main(int argc, char **argv) {
static int a;
diff --git a/test/OpenMP/taskyield_codegen.cpp b/test/OpenMP/taskyield_codegen.cpp
index 759709c33d22..80b65bff5e49 100644
--- a/test/OpenMP/taskyield_codegen.cpp
+++ b/test/OpenMP/taskyield_codegen.cpp
@@ -2,7 +2,6 @@
// 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
// expected-no-diagnostics
-// REQUIRES: x86-registered-target
#ifndef HEADER
#define HEADER
diff --git a/test/OpenMP/teams_ast_print.cpp b/test/OpenMP/teams_ast_print.cpp
index f3d577cafcd3..861b25da34a3 100644
--- a/test/OpenMP/teams_ast_print.cpp
+++ b/test/OpenMP/teams_ast_print.cpp
@@ -15,18 +15,18 @@ struct S {
#pragma omp threadprivate(TS)
};
-// CHECK: template <class T = int> struct S {
+// CHECK: template <class T> struct S {
+// CHECK: static T TS;
+// CHECK-NEXT: #pragma omp threadprivate(S::TS)
+// CHECK: };
+// CHECK: template<> struct S<int> {
// CHECK: static int TS;
// CHECK-NEXT: #pragma omp threadprivate(S<int>::TS)
// CHECK-NEXT: }
-// CHECK: template <class T = long> struct S {
+// CHECK: template<> struct S<long> {
// CHECK: static long TS;
// CHECK-NEXT: #pragma omp threadprivate(S<long>::TS)
// CHECK-NEXT: }
-// CHECK: template <class T> struct S {
-// CHECK: static T TS;
-// CHECK-NEXT: #pragma omp threadprivate(S::TS)
-// CHECK: };
template <typename T, int C>
T tmain(T argc, T *argv) {
@@ -45,41 +45,41 @@ T tmain(T argc, T *argv) {
return 0;
}
-// CHECK: template <typename T = int, int C = 5> int tmain(int argc, int *argv) {
-// CHECK-NEXT: int b = argc, c, d, e, f, g;
-// CHECK-NEXT: static int a;
-// CHECK-NEXT: S<int> s;
+// CHECK: template <typename T, int C> 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
// 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(5) thread_limit(d * 5)
+// 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)
// CHECK-NEXT: foo()
// CHECK-NEXT: #pragma omp target
// CHECK-NEXT: #pragma omp teams reduction(^: e,f) reduction(&&: g)
// CHECK-NEXT: foo()
-// CHECK: template <typename T = long, int C = 1> long tmain(long argc, long *argv) {
-// CHECK-NEXT: long b = argc, c, d, e, f, g;
-// CHECK-NEXT: static long a;
-// CHECK-NEXT: S<long> s;
+// CHECK: template<> int tmain<int, 5>(int argc, int *argv) {
+// CHECK-NEXT: int b = argc, c, d, e, f, g;
+// CHECK-NEXT: static int a;
+// CHECK-NEXT: S<int> s;
// CHECK-NEXT: #pragma omp target
// 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(1) thread_limit(d * 1)
+// CHECK-NEXT: #pragma omp teams default(none) private(argc,b) firstprivate(argv) shared(d) reduction(+: c) reduction(max: e) num_teams(5) thread_limit(d * 5)
// CHECK-NEXT: foo()
// CHECK-NEXT: #pragma omp target
// CHECK-NEXT: #pragma omp teams reduction(^: e,f) reduction(&&: g)
// CHECK-NEXT: foo()
-// CHECK: template <typename T, int C> 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: template<> long tmain<long, 1>(long argc, long *argv) {
+// CHECK-NEXT: long b = argc, c, d, e, f, g;
+// CHECK-NEXT: static long a;
+// CHECK-NEXT: S<long> s;
// CHECK-NEXT: #pragma omp target
// 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)
+// CHECK-NEXT: #pragma omp teams default(none) private(argc,b) firstprivate(argv) shared(d) reduction(+: c) reduction(max: e) num_teams(1) thread_limit(d * 1)
// CHECK-NEXT: foo()
// CHECK-NEXT: #pragma omp target
// CHECK-NEXT: #pragma omp teams reduction(^: e,f) reduction(&&: g)
diff --git a/test/OpenMP/teams_distribute_ast_print.cpp b/test/OpenMP/teams_distribute_ast_print.cpp
new file mode 100644
index 000000000000..f465c3f8e30b
--- /dev/null
+++ b/test/OpenMP/teams_distribute_ast_print.cpp
@@ -0,0 +1,179 @@
+// 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
+// expected-no-diagnostics
+
+#ifndef HEADER
+#define HEADER
+
+void foo() {}
+
+struct S {
+ S(): a(0) {}
+ S(int v) : a(v) {}
+ int a;
+ typedef int type;
+};
+
+template <typename T>
+class S7 : public T {
+protected:
+ T a;
+ S7() : a(0) {}
+
+public:
+ S7(typename T::type v) : a(v) {
+#pragma omp target
+#pragma omp teams distribute private(a) private(this->a) private(T::a)
+ for (int k = 0; k < a.a; ++k)
+ ++this->a.a;
+ }
+ S7 &operator=(S7 &s) {
+#pragma omp target
+#pragma omp teams distribute private(a) private(this->a)
+ for (int k = 0; k < s.a.a; ++k)
+ ++s.a.a;
+ return *this;
+ }
+
+ void foo() {
+ int b, argv, d, c, e, f;
+#pragma omp target
+#pragma omp teams distribute default(none), private(b) firstprivate(argv) shared(d) reduction(+:c) reduction(max:e) num_teams(f) thread_limit(d)
+ for (int k = 0; k < a.a; ++k)
+ ++a.a;
+ }
+};
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute private(this->a) private(this->a) private(T::a)
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute private(this->a) private(this->a)
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute default(none) private(b) firstprivate(argv) shared(d) reduction(+: c) reduction(max: e) num_teams(f) thread_limit(d)
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute private(this->a) private(this->a) private(this->S::a)
+
+class S8 : public S7<S> {
+ S8() {}
+
+public:
+ S8(int v) : S7<S>(v){
+#pragma omp target
+#pragma omp teams distribute private(a) private(this->a) private(S7<S>::a)
+ for (int k = 0; k < a.a; ++k)
+ ++this->a.a;
+ }
+ S8 &operator=(S8 &s) {
+#pragma omp target
+#pragma omp teams distribute private(a) private(this->a)
+ for (int k = 0; k < s.a.a; ++k)
+ ++s.a.a;
+ return *this;
+ }
+
+ void bar() {
+ int b, argv, d, c, e, f;
+#pragma omp target
+#pragma omp teams distribute default(none), private(b) firstprivate(argv) shared(d) reduction(+:c) reduction(max:e) num_teams(f) thread_limit(d)
+ for (int k = 0; k < a.a; ++k)
+ ++a.a;
+ }
+};
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute private(this->a) private(this->a) private(this->S7<S>::a)
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute private(this->a) private(this->a)
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute default(none) private(b) firstprivate(argv) shared(d) reduction(+: c) reduction(max: e) num_teams(f) thread_limit(d)
+
+template <class T, int N>
+T tmain(T argc) {
+ T b = argc, c, d, e, f, g;
+ static T a;
+// CHECK: static T a;
+#pragma omp target
+#pragma omp teams distribute
+ for (int i=0; i < 2; ++i)
+ a = 2;
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute
+// CHECK-NEXT: for (int i = 0; i < 2; ++i)
+// CHECK-NEXT: a = 2;
+#pragma omp target
+#pragma omp teams distribute private(argc, b), firstprivate(c, d), collapse(2)
+ for (int i = 0; i < 10; ++i)
+ for (int j = 0; j < 10; ++j)
+ foo();
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute private(argc,b) firstprivate(c,d) collapse(2)
+// CHECK-NEXT: for (int i = 0; i < 10; ++i)
+// CHECK-NEXT: for (int j = 0; j < 10; ++j)
+// CHECK-NEXT: foo();
+ for (int i = 0; i < 10; ++i)
+ foo();
+// CHECK: for (int i = 0; i < 10; ++i)
+// CHECK-NEXT: foo();
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i)
+ foo();
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute
+// CHECK-NEXT: for (int i = 0; i < 10; ++i)
+// CHECK-NEXT: foo();
+#pragma omp target
+#pragma omp teams distribute default(none), private(b) firstprivate(argc) shared(d) reduction(+:c) reduction(max:e) num_teams(f) thread_limit(d)
+ for (int k = 0; k < 10; ++k)
+ e += d + argc;
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute default(none) private(b) firstprivate(argc) shared(d) reduction(+: c) reduction(max: e) num_teams(f) thread_limit(d)
+// CHECK-NEXT: for (int k = 0; k < 10; ++k)
+// CHECK-NEXT: e += d + argc;
+ return T();
+}
+
+int main (int argc, char **argv) {
+ int b = argc, c, d, e, f, g;
+ static int a;
+// CHECK: static int a;
+#pragma omp target
+#pragma omp teams distribute
+ for (int i=0; i < 2; ++i)
+ a = 2;
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute
+// CHECK-NEXT: for (int i = 0; i < 2; ++i)
+// CHECK-NEXT: a = 2;
+#pragma omp target
+#pragma omp teams distribute private(argc,b),firstprivate(argv, c), collapse(2)
+ for (int i = 0; i < 10; ++i)
+ for (int j = 0; j < 10; ++j)
+ foo();
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute private(argc,b) firstprivate(argv,c) collapse(2)
+// CHECK-NEXT: for (int i = 0; i < 10; ++i)
+// CHECK-NEXT: for (int j = 0; j < 10; ++j)
+// CHECK-NEXT: foo();
+ for (int i = 0; i < 10; ++i)
+ foo();
+// CHECK: for (int i = 0; i < 10; ++i)
+// CHECK-NEXT: foo();
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i)foo();
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute
+// CHECK-NEXT: for (int i = 0; i < 10; ++i)
+// CHECK-NEXT: foo();
+#pragma omp target
+#pragma omp teams distribute default(none), private(b) firstprivate(argc) shared(d) reduction(+:c) reduction(max:e) num_teams(f) thread_limit(d)
+ for (int k = 0; k < 10; ++k)
+ e += d + argc;
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute default(none) private(b) firstprivate(argc) shared(d) reduction(+: c) reduction(max: e) num_teams(f) thread_limit(d)
+// CHECK-NEXT: for (int k = 0; k < 10; ++k)
+// CHECK-NEXT: e += d + argc;
+ return (0);
+}
+
+#endif
diff --git a/test/OpenMP/teams_distribute_collapse_messages.cpp b/test/OpenMP/teams_distribute_collapse_messages.cpp
new file mode 100644
index 000000000000..9ce58e0b0650
--- /dev/null
+++ b/test/OpenMP/teams_distribute_collapse_messages.cpp
@@ -0,0 +1,172 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp %s -std=c++98
+// RUN: %clang_cc1 -verify -fopenmp %s -std=c++11
+
+void foo() {
+}
+
+#if __cplusplus >= 201103L
+// expected-note@+2 4 {{declared here}}
+#endif
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}}
+
+template <class T, typename S, int N, int ST> // expected-note {{declared here}}
+T tmain(T argc, S **argv) { //expected-note 2 {{declared here}}
+#pragma omp target
+#pragma omp teams distribute collapse // expected-error {{expected '(' after 'collapse'}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute collapse ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = ST; i < N; i++)
+
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+#pragma omp target
+#pragma omp teams distribute collapse () // expected-error {{expected expression}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+// expected-error@+4 {{expected ')'}} expected-note@+4 {{to match this '('}}
+// expected-error@+3 2 {{expression is not an integral constant expression}}
+// expected-note@+2 2 {{read of non-const variable 'argc' is not allowed in a constant expression}}
+#pragma omp target
+#pragma omp teams distribute collapse (argc
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+// expected-error@+2 2 {{argument to 'collapse' clause must be a strictly positive integer value}}
+#pragma omp target
+#pragma omp teams distribute collapse (ST // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute collapse (1)) // expected-warning {{extra tokens at the end of '#pragma omp teams distribute' are ignored}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute collapse ((ST > 0) ? 1 + ST : 2) // expected-note 2 {{as specified in 'collapse' clause}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST]; // expected-error 2 {{expected 2 for loops after '#pragma omp teams distribute', but found only 1}}
+
+#if __cplusplus >= 201103L
+// expected-note@+6 2 {{non-constexpr function 'foobool' cannot be used}}
+#endif
+// expected-error@+4 2 {{directive '#pragma omp teams distribute' cannot contain more than one 'collapse' clause}}
+// expected-error@+3 2 {{argument to 'collapse' clause must be a strictly positive integer value}}
+// expected-error@+2 2 {{expression is not an integral constant expression}}
+#pragma omp target
+#pragma omp teams distribute collapse (foobool(argc)), collapse (true), collapse (-5)
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp distribute collapse (S) // expected-error {{'S' does not refer to a value}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#if __cplusplus >= 201103L
+// expected-error@+5 2 {{integral constant expression must have integral or unscoped enumeration type}}
+#else
+// expected-error@+3 2 {{expression is not an integral constant expression}}
+#endif
+#pragma omp target
+#pragma omp teams distribute collapse (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute collapse (1)
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute collapse (N) // expected-error {{argument to 'collapse' clause must be a strictly positive integer value}}
+ for (T i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute collapse (2) // expected-note {{as specified in 'collapse' clause}}
+ foo(); // expected-error {{expected 2 for loops after '#pragma omp teams distribute'}}
+ return argc;
+}
+
+int main(int argc, char **argv) {
+#pragma omp target
+#pragma omp teams distribute collapse // expected-error {{expected '(' after 'collapse'}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target
+#pragma omp teams distribute collapse ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target
+#pragma omp teams distribute collapse () // expected-error {{expected expression}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target
+#pragma omp teams distribute collapse (4 // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-note {{as specified in 'collapse' clause}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4]; // expected-error {{expected 4 for loops after '#pragma omp teams distribute', but found only 1}}
+
+#pragma omp target
+#pragma omp teams distribute collapse (2+2)) // expected-warning {{extra tokens at the end of '#pragma omp teams distribute' are ignored}} expected-note {{as specified in 'collapse' clause}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4]; // expected-error {{expected 4 for loops after '#pragma omp teams distribute', but found only 1}}
+
+#if __cplusplus >= 201103L
+// expected-note@+3 {{non-constexpr function 'foobool' cannot be used}}
+#endif
+#pragma omp target
+#pragma omp teams distribute collapse (foobool(1) > 0 ? 1 : 2) // expected-error {{expression is not an integral constant expression}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#if __cplusplus >= 201103L
+// expected-note@+6 {{non-constexpr function 'foobool' cannot be used}}
+#endif
+// expected-error@+4 {{expression is not an integral constant expression}}
+// expected-error@+3 2 {{directive '#pragma omp teams distribute' cannot contain more than one 'collapse' clause}}
+// expected-error@+2 2 {{argument to 'collapse' clause must be a strictly positive integer value}}
+#pragma omp target
+#pragma omp teams distribute collapse (foobool(argc)), collapse (true), collapse (-5)
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target
+#pragma omp teams distribute collapse (S1) // expected-error {{'S1' does not refer to a value}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#if __cplusplus >= 201103L
+// expected-error@+5 {{integral constant expression must have integral or unscoped enumeration type}}
+#else
+// expected-error@+3 {{expression is not an integral constant expression}}
+#endif
+#pragma omp target
+#pragma omp teams distribute collapse (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+// expected-error@+4 {{statement after '#pragma omp teams distribute' must be a for loop}}
+// expected-note@+2 {{in instantiation of function template specialization 'tmain<int, char, -1, -2>' requested here}}
+#pragma omp target
+#pragma omp teams distribute collapse(collapse(tmain<int, char, -1, -2>(argc, argv) // expected-error 2 {{expected ')'}} expected-note 2 {{to match this '('}}
+ foo();
+
+#pragma omp target
+#pragma omp teams distribute collapse (2) // expected-note {{as specified in 'collapse' clause}}
+ foo(); // expected-error {{expected 2 for loops after '#pragma omp teams distribute'}}
+
+// expected-note@+1 {{in instantiation of function template specialization 'tmain<int, char, 1, 0>' requested here}}
+ return tmain<int, char, 1, 0>(argc, argv);
+}
+
diff --git a/test/OpenMP/teams_distribute_default_messages.cpp b/test/OpenMP/teams_distribute_default_messages.cpp
new file mode 100644
index 000000000000..bf62930825d9
--- /dev/null
+++ b/test/OpenMP/teams_distribute_default_messages.cpp
@@ -0,0 +1,30 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo();
+
+int main(int argc, char **argv) {
+ #pragma omp target
+ #pragma omp teams distribute default // expected-error {{expected '(' after 'default'}}
+ for (int i=0; i<200; i++) foo();
+ #pragma omp target
+ #pragma omp teams distribute default ( // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i=0; i<200; i++) foo();
+ #pragma omp target
+ #pragma omp teams distribute default () // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+ for (int i=0; i<200; i++) foo();
+ #pragma omp target
+ #pragma omp teams distribute default (none // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i=0; i<200; i++) foo();
+ #pragma omp target
+ #pragma omp teams distribute default (shared), default(shared) // expected-error {{directive '#pragma omp teams distribute' cannot contain more than one 'default' clause}}
+ for (int i=0; i<200; i++) foo();
+ #pragma omp target
+ #pragma omp teams distribute default (x) // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+ for (int i=0; i<200; i++) foo();
+
+ #pragma omp target
+ #pragma omp teams distribute default(none)
+ for (int i=0; i<200; i++) ++argc; // expected-error {{variable 'argc' must have explicitly specified data sharing attributes}}
+
+ return 0;
+}
diff --git a/test/OpenMP/teams_distribute_dist_schedule_messages.cpp b/test/OpenMP/teams_distribute_dist_schedule_messages.cpp
new file mode 100644
index 000000000000..d86722dd277d
--- /dev/null
+++ b/test/OpenMP/teams_distribute_dist_schedule_messages.cpp
@@ -0,0 +1,104 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}} expected-note {{declared here}}
+
+template <class T, int N>
+T tmain(T argc) {
+ T b = argc, c, d, e, f, g;
+ char ** argv;
+ static T a;
+// CHECK: static T a;
+
+#pragma omp target
+#pragma omp teams distribute dist_schedule // expected-error {{expected '(' after 'dist_schedule'}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute dist_schedule ( // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute dist_schedule () // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute dist_schedule (static // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute dist_schedule (static, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute dist_schedule (argc)) // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}} expected-warning {{extra tokens at the end of '#pragma omp teams distribute' are ignored}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute dist_schedule (static, argc > 0 ? argv[1] : argv[2]) // expected-error2 {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute dist_schedule (static), dist_schedule (static, 1) // expected-error {{directive '#pragma omp teams distribute' cannot contain more than one 'dist_schedule' clause}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute dist_schedule (static, S1) // expected-error {{'S1' does not refer to a value}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute dist_schedule (static, argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error3 {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ for (int i = 0; i < 10; ++i) foo();
+
+ return T();
+}
+
+int main(int argc, char **argv) {
+#pragma omp target
+#pragma omp teams distribute dist_schedule // expected-error {{expected '(' after 'dist_schedule'}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute dist_schedule ( // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute dist_schedule () // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute dist_schedule (static // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute dist_schedule (static, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute dist_schedule (argc)) // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}} expected-warning {{extra tokens at the end of '#pragma omp teams distribute' are ignored}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute dist_schedule (static, argc > 0 ? argv[1] : argv[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute dist_schedule (static), dist_schedule (static, 1) // expected-error {{directive '#pragma omp teams distribute' cannot contain more than one 'dist_schedule' clause}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute dist_schedule (static, S1) // expected-error {{'S1' does not refer to a value}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute dist_schedule (static, argv[1]=2) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 0; i < 10; ++i) foo();
+
+ return (tmain<int, 5>(argc) + tmain<char, 1>(argv[0][0])); // expected-note {{in instantiation of function template specialization 'tmain<int, 5>' requested here}} expected-note {{in instantiation of function template specialization 'tmain<char, 1>' requested here}}
+}
diff --git a/test/OpenMP/teams_distribute_firstprivate_messages.cpp b/test/OpenMP/teams_distribute_firstprivate_messages.cpp
new file mode 100644
index 000000000000..a71080774331
--- /dev/null
+++ b/test/OpenMP/teams_distribute_firstprivate_messages.cpp
@@ -0,0 +1,152 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}} expected-note{{forward declaration of 'S1'}}
+extern S1 a;
+class S2 {
+ mutable int a;
+
+public:
+ S2() : a(0) {}
+ S2(const S2 &s2) : a(s2.a) {}
+ static float S2s;
+ static const float S2sc;
+};
+const float S2::S2sc = 0;
+const S2 b;
+const S2 ba[5];
+class S3 {
+ int a;
+ S3 &operator=(const S3 &s3);
+
+public:
+ S3() : a(0) {} // expected-note {{candidate constructor not viable: requires 0 arguments, but 1 was provided}}
+ S3(S3 &s3) : a(s3.a) {} // expected-note {{candidate constructor not viable: 1st argument ('const S3') would lose const qualifier}}
+};
+const S3 c;
+const S3 ca[5];
+extern const int f;
+class S4 {
+ int a;
+ S4();
+ S4(const S4 &s4);
+public:
+ S4(int v):a(v) { }
+};
+class S5 {
+ int a;
+ S5():a(0) {}
+ S5(const S5 &s5):a(s5.a) { }
+public:
+ S5(int v):a(v) { }
+};
+class S6 {
+ int a;
+public:
+ S6() : a(0) { }
+};
+
+S3 h;
+#pragma omp threadprivate(h) // expected-note {{defined as threadprivate or thread local}}
+
+int main(int argc, char **argv) {
+ const int d = 5;
+ const int da[5] = { 0 };
+ S4 e(4);
+ S5 g(5);
+ S6 p;
+ int i;
+ int &j = i;
+
+#pragma omp target
+#pragma omp teams distribute firstprivate // expected-error {{expected '(' after 'firstprivate'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute firstprivate ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute firstprivate () // expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute firstprivate (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute firstprivate (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute firstprivate (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute firstprivate (argc)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute firstprivate (S1) // expected-error {{'S1' does not refer to a value}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute firstprivate (a, b, c, d, f) // expected-error {{firstprivate variable with incomplete type 'S1'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute firstprivate (argv[1]) // expected-error {{expected variable name}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute firstprivate(ba)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute firstprivate(ca) // expected-error {{no matching constructor for initialization of 'S3'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute firstprivate(da)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute firstprivate(S2::S2s)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute firstprivate(S2::S2sc)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute firstprivate(h) // expected-error {{threadprivate or thread local variable cannot be firstprivate}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute private(i), firstprivate(i) // expected-error {{private variable cannot be firstprivate}} expected-note{{defined as private}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute firstprivate(i)
+ for (j = 0; j < argc; ++j) foo();
+
+#pragma omp target
+#pragma omp teams distribute firstprivate(i) // expected-note {{defined as firstprivate}}
+ for (i = 0; i < argc; ++i) foo(); // expected-error {{loop iteration variable in the associated loop of 'omp teams distribute' directive may not be firstprivate, predetermined as private}}
+
+#pragma omp target
+#pragma omp teams distribute firstprivate(j)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute lastprivate(argc), firstprivate(argc) // OK
+ for (i = 0; i < argc; ++i) foo();
+
+ return 0;
+}
diff --git a/test/OpenMP/teams_distribute_lastprivate_messages.cpp b/test/OpenMP/teams_distribute_lastprivate_messages.cpp
new file mode 100644
index 000000000000..b892141d5014
--- /dev/null
+++ b/test/OpenMP/teams_distribute_lastprivate_messages.cpp
@@ -0,0 +1,272 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note 2 {{declared here}} expected-note 2 {{forward declaration of 'S1'}}
+extern S1 a;
+class S2 {
+ mutable int a;
+
+public:
+ S2() : a(0) {}
+ S2(S2 &s2) : a(s2.a) {}
+ const S2 &operator =(const S2&) const;
+ S2 &operator =(const S2&);
+ static float S2s; // expected-note {{static data member is predetermined as shared}}
+ static const float S2sc;
+};
+const float S2::S2sc = 0; // expected-note {{static data member is predetermined as shared}}
+const S2 b;
+const S2 ba[5];
+class S3 {
+ int a;
+ S3 &operator=(const S3 &s3); // expected-note 2 {{implicitly declared private here}}
+
+public:
+ S3() : a(0) {}
+ S3(S3 &s3) : a(s3.a) {}
+};
+const S3 c; // expected-note {{global variable is predetermined as shared}}
+const S3 ca[5]; // expected-note {{global variable is predetermined as shared}}
+extern const int f; // expected-note {{global variable is predetermined as shared}}
+class S4 {
+ int a;
+ S4(); // expected-note 3 {{implicitly declared private here}}
+ S4(const S4 &s4);
+
+public:
+ S4(int v) : a(v) {}
+};
+class S5 {
+ int a;
+ S5() : a(0) {} // expected-note {{implicitly declared private here}}
+
+public:
+ S5(const S5 &s5) : a(s5.a) {}
+ S5(int v) : a(v) {}
+};
+class S6 {
+ int a;
+ S6() : a(0) {}
+
+public:
+ S6(const S6 &s6) : a(s6.a) {}
+ S6(int v) : a(v) {}
+};
+
+S3 h;
+#pragma omp threadprivate(h) // expected-note 2 {{defined as threadprivate or thread local}}
+
+template <class I, class C>
+int foomain(int argc, char **argv) {
+ I e(4);
+ I g(5);
+ int i;
+ int &j = i;
+#pragma omp target
+#pragma omp teams distribute lastprivate // expected-error {{expected '(' after 'lastprivate'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute lastprivate( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute lastprivate() // expected-error {{expected expression}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute lastprivate(argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute lastprivate(argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute lastprivate(argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute lastprivate(argc)
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute lastprivate(S1) // expected-error {{'S1' does not refer to a value}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute lastprivate(a, b) // expected-error {{lastprivate variable with incomplete type 'S1'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute lastprivate(argv[1]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute lastprivate(e, g) // expected-error 2 {{calling a private constructor of class 'S4'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute lastprivate(h) // expected-error {{threadprivate or thread local variable cannot be lastprivate}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ int v = 0;
+#pragma omp target
+#pragma omp teams distribute lastprivate(i)
+ for (int k = 0; k < argc; ++k) {
+ i = k;
+ v += i;
+ }
+
+#pragma omp target
+#pragma omp teams distribute lastprivate(j) private(i)
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute lastprivate(i)
+ for (int k = 0; k < argc; ++k) ++k;
+
+ return 0;
+}
+
+void bar(S4 a[2]) {
+#pragma omp target
+#pragma omp teams distribute lastprivate(a)
+ for (int i = 0; i < 2; ++i) foo();
+}
+
+namespace A {
+double x;
+#pragma omp threadprivate(x) // expected-note {{defined as threadprivate or thread local}}
+}
+namespace B {
+using A::x;
+}
+
+int main(int argc, char **argv) {
+ const int d = 5; // expected-note {{constant variable is predetermined as shared}}
+ const int da[5] = {0}; // expected-note {{constant variable is predetermined as shared}}
+ S4 e(4);
+ S5 g(5);
+ S3 m;
+ S6 n(2);
+ int i;
+ int &j = i;
+#pragma omp target
+#pragma omp teams distribute lastprivate // expected-error {{expected '(' after 'lastprivate'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute lastprivate( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute lastprivate() // expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute lastprivate(argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute lastprivate(argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute lastprivate(argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute lastprivate(argc)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute lastprivate(S1) // expected-error {{'S1' does not refer to a value}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be lastprivate}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute lastprivate(argv[1]) // expected-error {{expected variable name}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute lastprivate(2 * 2) // expected-error {{expected variable name}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute lastprivate(ba)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute lastprivate(ca) // expected-error {{shared variable cannot be lastprivate}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute lastprivate(da) // expected-error {{shared variable cannot be lastprivate}}
+ for (i = 0; i < argc; ++i) foo();
+
+ int xa;
+#pragma omp target
+#pragma omp teams distribute lastprivate(xa) // OK
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute lastprivate(S2::S2s) // expected-error {{shared variable cannot be lastprivate}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute lastprivate(S2::S2sc) // expected-error {{shared variable cannot be lastprivate}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute lastprivate(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute lastprivate(m) // expected-error {{'operator=' is a private member of 'S3'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute lastprivate(h) // expected-error {{threadprivate or thread local variable cannot be lastprivate}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute lastprivate(B::x) // expected-error {{threadprivate or thread local variable cannot be lastprivate}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute private(xa), lastprivate(xa) // expected-error {{private variable cannot be lastprivate}} expected-note {{defined as private}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute lastprivate(xa)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute lastprivate(j)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute firstprivate(m) lastprivate(m) // expected-error {{'operator=' is a private member of 'S3'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute lastprivate(n) firstprivate(n) // OK
+ for (i = 0; i < argc; ++i) foo();
+
+ static int si;
+#pragma omp target
+#pragma omp teams distribute lastprivate(si) // OK
+ for (i = 0; i < argc; ++i) si = i + 1;
+
+ return foomain<S4, S5>(argc, argv); // expected-note {{in instantiation of function template specialization 'foomain<S4, S5>' requested here}}
+}
diff --git a/test/OpenMP/teams_distribute_loop_messages.cpp b/test/OpenMP/teams_distribute_loop_messages.cpp
new file mode 100644
index 000000000000..dbfd9ef03cdb
--- /dev/null
+++ b/test/OpenMP/teams_distribute_loop_messages.cpp
@@ -0,0 +1,716 @@
+// RUN: %clang_cc1 -fsyntax-only -fopenmp -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s
+
+class S {
+ int a;
+ S() : a(0) {}
+
+public:
+ S(int v) : a(v) {}
+ S(const S &s) : a(s.a) {}
+};
+
+static int sii;
+// expected-note@+1 {{defined as threadprivate or thread local}}
+#pragma omp threadprivate(sii)
+static int globalii;
+
+int test_iteration_spaces() {
+ const int N = 100;
+ float a[N], b[N], c[N];
+ int ii, jj, kk;
+ float fii;
+ double dii;
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; i += 1) {
+ c[i] = a[i] + b[i];
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (char i = 0; i < 10; i++) {
+ c[i] = a[i] + b[i];
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (char i = 0; i < 10; i += '\1') {
+ c[i] = a[i] + b[i];
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (long long i = 0; i < 10; i++) {
+ c[i] = a[i] + b[i];
+ }
+#pragma omp target
+#pragma omp teams distribute
+// expected-error@+1 {{expression must have integral or unscoped enumeration type, not 'double'}}
+ for (long long i = 0; i < 10; i += 1.5) {
+ c[i] = a[i] + b[i];
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (long long i = 0; i < 'z'; i += 1u) {
+ c[i] = a[i] + b[i];
+ }
+#pragma omp target
+#pragma omp teams distribute
+// expected-error@+1 {{variable must be of integer or random access iterator type}}
+ for (float fi = 0; fi < 10.0; fi++) {
+ c[(int)fi] = a[(int)fi] + b[(int)fi];
+ }
+#pragma omp target
+#pragma omp teams distribute
+// expected-error@+1 {{variable must be of integer or random access iterator type}}
+ for (double fi = 0; fi < 10.0; fi++) {
+ c[(int)fi] = a[(int)fi] + b[(int)fi];
+ }
+#pragma omp target
+#pragma omp teams distribute
+// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (int &ref = ii; ref < 10; ref++) {
+ }
+#pragma omp target
+#pragma omp teams distribute
+// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (int i; i < 10; i++)
+ c[i] = a[i];
+
+#pragma omp target
+#pragma omp teams distribute
+// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (int i = 0, j = 0; i < 10; ++i)
+ c[i] = a[i];
+
+#pragma omp target
+#pragma omp teams distribute
+// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (; ii < 10; ++ii)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute
+// expected-warning@+2 {{expression result unused}}
+// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (ii + 1; ii < 10; ++ii)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute
+// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (c[ii] = 0; ii < 10; ++ii)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute
+// Ok to skip parenthesises.
+ for (((ii)) = 0; ii < 10; ++ii)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute
+// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
+ for (int i = 0; i; i++)
+ c[i] = a[i];
+
+#pragma omp target
+#pragma omp teams distribute
+// expected-error@+2 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'i'}}
+ for (int i = 0; jj < kk; ii++)
+ c[i] = a[i];
+
+#pragma omp target
+#pragma omp teams distribute
+// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
+ for (int i = 0; !!i; i++)
+ c[i] = a[i];
+
+#pragma omp target
+#pragma omp teams distribute
+// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
+ for (int i = 0; i != 1; i++)
+ c[i] = a[i];
+
+#pragma omp target
+#pragma omp teams distribute
+// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
+ for (int i = 0;; i++)
+ c[i] = a[i];
+
+// Ok.
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 11; i > 10; i--)
+ c[i] = a[i];
+
+// Ok.
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i)
+ c[i] = a[i];
+
+// Ok.
+#pragma omp target
+#pragma omp teams distribute
+ for (ii = 0; ii < 10; ++ii)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+ for (ii = 0; ii < 10; ++jj)
+ c[ii] = a[jj];
+
+#pragma omp target
+#pragma omp teams distribute
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+ for (ii = 0; ii < 10; ++++ii)
+ c[ii] = a[ii];
+
+// Ok but undefined behavior (in general, cannot check that incr
+// is really loop-invariant).
+#pragma omp target
+#pragma omp teams distribute
+ for (ii = 0; ii < 10; ii = ii + ii)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute
+// expected-error@+1 {{expression must have integral or unscoped enumeration type, not 'float'}}
+ for (ii = 0; ii < 10; ii = ii + 1.0f)
+ c[ii] = a[ii];
+
+// Ok - step was converted to integer type.
+#pragma omp target
+#pragma omp teams distribute
+ for (ii = 0; ii < 10; ii = ii + (int)1.1f)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+ for (ii = 0; ii < 10; jj = ii + 2)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute
+// expected-warning@+2 {{relational comparison result unused}}
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+ for (ii = 0; ii<10; jj> kk + 2)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+ for (ii = 0; ii < 10;)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute
+// expected-warning@+2 {{expression result unused}}
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+ for (ii = 0; ii < 10; !ii)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+ for (ii = 0; ii < 10; ii ? ++ii : ++jj)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+ for (ii = 0; ii < 10; ii = ii < 10)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}}
+ for (ii = 0; ii < 10; ii = ii + 0)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}}
+ for (ii = 0; ii < 10; ii = ii + (int)(0.8 - 0.45))
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}}
+ for (ii = 0; (ii) < 10; ii -= 25)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}}
+ for (ii = 0; (ii < 10); ii -= 0)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute
+// expected-note@+2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+1 {{increment expression must cause 'ii' to decrease on each iteration of OpenMP for loop}}
+ for (ii = 0; ii > 10; (ii += 0))
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}}
+ for (ii = 0; ii < 10; (ii) = (1 - 1) + (ii))
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute
+// expected-note@+2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+1 {{increment expression must cause 'ii' to decrease on each iteration of OpenMP for loop}}
+ for ((ii = 0); ii > 10; (ii -= 0))
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}}
+ for (ii = 0; (ii < 10); (ii -= 0))
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute firstprivate(ii) // expected-note {{defined as firstprivate}}
+// expected-error@+1 {{loop iteration variable in the associated loop of 'omp teams distribute' directive may not be firstprivate, predetermined as private}}
+ for (ii = 0; ii < 10; ii++)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute private(ii)
+// OK
+ for (ii = 0; ii < 10; ii++)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute lastprivate(ii)
+// OK
+ for (ii = 0; ii < 10; ii++)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute
+// expected-error@+1 {{loop iteration variable in the associated loop of 'omp teams distribute' directive may not be threadprivate or thread local, predetermined as private}}
+ for (sii = 0; sii < 10; sii++)
+ c[sii] = a[sii];
+
+ {
+#pragma omp target
+#pragma omp teams distribute collapse(2)
+ for (ii = 0; ii < 10; ii += 1)
+ for (globalii = 0; globalii < 10; globalii += 1)
+ c[globalii] += a[globalii] + ii;
+ }
+
+#pragma omp target
+#pragma omp teams distribute
+// expected-error@+1 {{statement after '#pragma omp teams distribute' must be a for loop}}
+ for (auto &item : a) {
+ item = item + 1;
+ }
+
+#pragma omp target
+#pragma omp teams distribute
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'i' to increase on each iteration of OpenMP for loop}}
+ for (unsigned i = 9; i < 10; i--) {
+ c[i] = a[i] + b[i];
+ }
+
+ int(*lb)[4] = nullptr;
+#pragma omp target
+#pragma omp teams distribute
+ for (int(*p)[4] = lb; p < lb + 8; ++p) {
+ }
+
+#pragma omp target
+#pragma omp teams distribute
+// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (int a{0}; a < 10; ++a) {
+ }
+
+ return 0;
+}
+
+// Iterators allowed in openmp for-loops.
+namespace std {
+struct random_access_iterator_tag {};
+template <class Iter>
+struct iterator_traits {
+ typedef typename Iter::difference_type difference_type;
+ typedef typename Iter::iterator_category iterator_category;
+};
+template <class Iter>
+typename iterator_traits<Iter>::difference_type
+distance(Iter first, Iter last) { return first - last; }
+}
+class Iter0 {
+public:
+ Iter0() {}
+ Iter0(const Iter0 &) {}
+ Iter0 operator++() { return *this; }
+ Iter0 operator--() { return *this; }
+ bool operator<(Iter0 a) { return true; }
+};
+// expected-note@+2 {{candidate function not viable: no known conversion from 'GoodIter' to 'Iter0' for 1st argument}}
+// expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'Iter0' for 1st argument}}
+int operator-(Iter0 a, Iter0 b) { return 0; }
+class Iter1 {
+public:
+ Iter1(float f = 0.0f, double d = 0.0) {}
+ Iter1(const Iter1 &) {}
+ Iter1 operator++() { return *this; }
+ Iter1 operator--() { return *this; }
+ bool operator<(Iter1 a) { return true; }
+ bool operator>=(Iter1 a) { return false; }
+};
+class GoodIter {
+public:
+ GoodIter() {}
+ GoodIter(const GoodIter &) {}
+ GoodIter(int fst, int snd) {}
+ GoodIter &operator=(const GoodIter &that) { return *this; }
+ GoodIter &operator=(const Iter0 &that) { return *this; }
+ GoodIter &operator+=(int x) { return *this; }
+ explicit GoodIter(void *) {}
+ GoodIter operator++() { return *this; }
+ GoodIter operator--() { return *this; }
+ bool operator!() { return true; }
+ bool operator<(GoodIter a) { return true; }
+ bool operator<=(GoodIter a) { return true; }
+ bool operator>=(GoodIter a) { return false; }
+ typedef int difference_type;
+ typedef std::random_access_iterator_tag iterator_category;
+};
+// expected-note@+2 {{candidate function not viable: no known conversion from 'const Iter0' to 'GoodIter' for 2nd argument}}
+// expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'GoodIter' for 1st argument}}
+int operator-(GoodIter a, GoodIter b) { return 0; }
+// expected-note@+1 3 {{candidate function not viable: requires single argument 'a', but 2 arguments were provided}}
+GoodIter operator-(GoodIter a) { return a; }
+// expected-note@+2 {{candidate function not viable: no known conversion from 'const Iter0' to 'int' for 2nd argument}}
+// expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'GoodIter' for 1st argument}}
+GoodIter operator-(GoodIter a, int v) { return GoodIter(); }
+// expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter0' to 'GoodIter' for 1st argument}}
+GoodIter operator+(GoodIter a, int v) { return GoodIter(); }
+// expected-note@+2 {{candidate function not viable: no known conversion from 'GoodIter' to 'int' for 1st argument}}
+// expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'int' for 1st argument}}
+GoodIter operator-(int v, GoodIter a) { return GoodIter(); }
+// expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter0' to 'int' for 1st argument}}
+GoodIter operator+(int v, GoodIter a) { return GoodIter(); }
+
+int test_with_random_access_iterator() {
+ GoodIter begin, end;
+ Iter0 begin0, end0;
+#pragma omp target
+#pragma omp teams distribute
+ for (GoodIter I = begin; I < end; ++I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute
+// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (GoodIter &I = begin; I < end; ++I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute
+ for (GoodIter I = begin; I >= end; --I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute
+// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (GoodIter I(begin); I < end; ++I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute
+// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (GoodIter I(nullptr); I < end; ++I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute
+// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (GoodIter I(0); I < end; ++I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute
+// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (GoodIter I(1, 2); I < end; ++I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute
+ for (begin = GoodIter(0); begin < end; ++begin)
+ ++begin;
+#pragma omp target
+#pragma omp teams distribute
+// expected-error@+2 {{invalid operands to binary expression ('GoodIter' and 'const Iter0')}}
+// expected-error@+1 {{could not calculate number of iterations calling 'operator-' with upper and lower loop bounds}}
+ for (begin = begin0; begin < end; ++begin)
+ ++begin;
+#pragma omp target
+#pragma omp teams distribute
+// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (++begin; begin < end; ++begin)
+ ++begin;
+#pragma omp target
+#pragma omp teams distribute
+ for (begin = end; begin < end; ++begin)
+ ++begin;
+#pragma omp target
+#pragma omp teams distribute
+// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'I'}}
+ for (GoodIter I = begin; I - I; ++I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute
+// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'I'}}
+ for (GoodIter I = begin; begin < end; ++I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute
+// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'I'}}
+ for (GoodIter I = begin; !I; ++I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute
+// expected-note@+2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+1 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}}
+ for (GoodIter I = begin; I >= end; I = I + 1)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute
+ for (GoodIter I = begin; I >= end; I = I - 1)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'I'}}
+ for (GoodIter I = begin; I >= end; I = -I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute
+// expected-note@+2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+1 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}}
+ for (GoodIter I = begin; I >= end; I = 2 + I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'I'}}
+ for (GoodIter I = begin; I >= end; I = 2 - I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute
+// expected-error@+1 {{invalid operands to binary expression ('Iter0' and 'int')}}
+ for (Iter0 I = begin0; I < end0; ++I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute
+// Initializer is constructor without params.
+// expected-error@+2 {{invalid operands to binary expression ('Iter0' and 'int')}}
+// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (Iter0 I; I < end0; ++I)
+ ++I;
+ Iter1 begin1, end1;
+#pragma omp target
+#pragma omp teams distribute
+// expected-error@+2 {{invalid operands to binary expression ('Iter1' and 'Iter1')}}
+// expected-error@+1 {{could not calculate number of iterations calling 'operator-' with upper and lower loop bounds}}
+ for (Iter1 I = begin1; I < end1; ++I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute
+// expected-note@+2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+1 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}}
+ for (Iter1 I = begin1; I >= end1; ++I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute
+// expected-error@+4 {{invalid operands to binary expression ('Iter1' and 'float')}}
+// expected-error@+3 {{could not calculate number of iterations calling 'operator-' with upper and lower loop bounds}}
+// Initializer is constructor with all default params.
+// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (Iter1 I; I < end1; ++I) {
+ }
+ return 0;
+}
+
+template <typename IT, int ST>
+class TC {
+public:
+ int dotest_lt(IT begin, IT end) {
+#pragma omp target
+#pragma omp teams distribute
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'I' to increase on each iteration of OpenMP for loop}}
+ for (IT I = begin; I < end; I = I + ST) {
+ ++I;
+ }
+#pragma omp target
+#pragma omp teams distribute
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'I' to increase on each iteration of OpenMP for loop}}
+ for (IT I = begin; I <= end; I += ST) {
+ ++I;
+ }
+#pragma omp target
+#pragma omp teams distribute
+ for (IT I = begin; I < end; ++I) {
+ ++I;
+ }
+ }
+
+ static IT step() {
+ return IT(ST);
+ }
+};
+template <typename IT, int ST = 0>
+int dotest_gt(IT begin, IT end) {
+#pragma omp target
+#pragma omp teams distribute
+// expected-note@+2 2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+1 2 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}}
+ for (IT I = begin; I >= end; I = I + ST) {
+ ++I;
+ }
+#pragma omp target
+#pragma omp teams distribute
+// expected-note@+2 2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+1 2 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}}
+ for (IT I = begin; I >= end; I += ST) {
+ ++I;
+ }
+
+#pragma omp target
+#pragma omp teams distribute
+// expected-note@+2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+1 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}}
+ for (IT I = begin; I >= end; ++I) {
+ ++I;
+ }
+
+#pragma omp target
+#pragma omp teams distribute
+ for (IT I = begin; I < end; I += TC<int, ST>::step()) {
+ ++I;
+ }
+}
+
+void test_with_template() {
+ GoodIter begin, end;
+ TC<GoodIter, 100> t1;
+ TC<GoodIter, -100> t2;
+ t1.dotest_lt(begin, end);
+ t2.dotest_lt(begin, end); // expected-note {{in instantiation of member function 'TC<GoodIter, -100>::dotest_lt' requested here}}
+ dotest_gt(begin, end); // expected-note {{in instantiation of function template specialization 'dotest_gt<GoodIter, 0>' requested here}}
+ dotest_gt<unsigned, -10>(0, 100); // expected-note {{in instantiation of function template specialization 'dotest_gt<unsigned int, -10>' requested here}}
+}
+
+void test_loop_break() {
+ const int N = 100;
+ float a[N], b[N], c[N];
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; i++) {
+ c[i] = a[i] + b[i];
+ for (int j = 0; j < 10; ++j) {
+ if (a[i] > b[j])
+ break; // OK in nested loop
+ }
+ switch (i) {
+ case 1:
+ b[i]++;
+ break;
+ default:
+ break;
+ }
+ if (c[i] > 10)
+ break; // expected-error {{'break' statement cannot be used in OpenMP for loop}}
+
+ if (c[i] > 11)
+ break; // expected-error {{'break' statement cannot be used in OpenMP for loop}}
+ }
+
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; i++) {
+ for (int j = 0; j < 10; j++) {
+ c[i] = a[i] + b[i];
+ if (c[i] > 10) {
+ if (c[i] < 20) {
+ break; // OK
+ }
+ }
+ }
+ }
+}
+
+void test_loop_eh() {
+ const int N = 100;
+ float a[N], b[N], c[N];
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; i++) {
+ c[i] = a[i] + b[i];
+ try { // OK
+ for (int j = 0; j < 10; ++j) {
+ if (a[i] > b[j])
+ throw a[i]; // OK
+ }
+ throw a[i]; // OK
+ } catch (float f) {
+ if (f > 0.1)
+ throw a[i]; // OK
+ return; // expected-error {{cannot return from OpenMP region}}
+ }
+ switch (i) {
+ case 1:
+ b[i]++;
+ break;
+ default:
+ break;
+ }
+ for (int j = 0; j < 10; j++) {
+ if (c[i] > 10)
+ throw c[i]; // OK
+ }
+ }
+ if (c[9] > 10)
+ throw c[9]; // OK
+
+#pragma omp target
+#pragma omp teams distribute
+ for (int i = 0; i < 10; ++i) {
+ struct S {
+ void g() { throw 0; }
+ };
+ }
+}
+
+void test_loop_firstprivate_lastprivate() {
+ S s(4);
+#pragma omp target
+#pragma omp teams distribute lastprivate(s) firstprivate(s)
+ for (int i = 0; i < 16; ++i)
+ ;
+}
+
+void test_ordered() {
+#pragma omp target
+#pragma omp teams distribute ordered // expected-error {{unexpected OpenMP clause 'ordered' in directive '#pragma omp teams distribute'}}
+ for (int i = 0; i < 16; ++i)
+ ;
+}
+
+void test_nowait() {
+#pragma omp target
+// expected-error@+1 2 {{unexpected OpenMP clause 'nowait' in directive '#pragma omp teams distribute'}}
+#pragma omp teams distribute nowait nowait // expected-error {{directive '#pragma omp teams distribute' cannot contain more than one 'nowait' clause}}
+ 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
new file mode 100644
index 000000000000..6086abd9200a
--- /dev/null
+++ b/test/OpenMP/teams_distribute_num_teams_messages.cpp
@@ -0,0 +1,111 @@
+// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 100 -o - %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note 2 {{declared here}}
+
+template <typename T, int C> // expected-note {{declared here}}
+T tmain(T argc) {
+ char **a;
+#pragma omp target
+#pragma omp teams distribute num_teams(C)
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute num_teams(T) // expected-error {{'T' does not refer to a value}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute num_teams // expected-error {{expected '(' after 'num_teams'}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute num_teams( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute num_teams() // expected-error {{expected expression}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute num_teams(argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute num_teams(argc)) // expected-warning {{extra tokens at the end of '#pragma omp teams distribute' are ignored}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute num_teams(argc > 0 ? a[1] : a[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute num_teams(argc + argc)
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute num_teams(argc), num_teams (argc+1) // expected-error {{directive '#pragma omp teams distribute' cannot contain more than one 'num_teams' clause}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute num_teams(S1) // expected-error {{'S1' does not refer to a value}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute num_teams(-2) // expected-error {{argument to 'num_teams' clause must be a strictly positive integer value}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute num_teams(-10u)
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute num_teams(3.14) // expected-error 2 {{expression must have integral or unscoped enumeration type, not 'double'}}
+ for (int i=0; i<100; i++) foo();
+
+ return 0;
+}
+
+int main(int argc, char **argv) {
+#pragma omp target
+#pragma omp teams distribute num_teams // expected-error {{expected '(' after 'num_teams'}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target
+#pragma omp teams distribute num_teams ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target
+#pragma omp teams distribute num_teams () // expected-error {{expected expression}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target
+#pragma omp teams distribute num_teams (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target
+#pragma omp teams distribute num_teams (argc)) // expected-warning {{extra tokens at the end of '#pragma omp teams distribute' are ignored}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target
+#pragma omp teams distribute num_teams (argc > 0 ? argv[1] : argv[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target
+#pragma omp teams distribute num_teams (argc + argc)
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target
+#pragma omp teams distribute num_teams (argc), num_teams (argc+1) // expected-error {{directive '#pragma omp teams distribute' cannot contain more than one 'num_teams' clause}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target
+#pragma omp teams distribute num_teams (S1) // expected-error {{'S1' does not refer to a value}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target
+#pragma omp teams distribute num_teams (-2) // expected-error {{argument to 'num_teams' clause must be a strictly positive integer value}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target
+#pragma omp teams distribute num_teams (-10u)
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target
+#pragma omp teams distribute num_teams (3.14) // expected-error {{expression must have integral or unscoped enumeration type, not 'double'}}
+ for (int i=0; i<100; i++) foo();
+
+ return tmain<int, 10>(argc); // expected-note {{in instantiation of function template specialization 'tmain<int, 10>' requested here}}
+}
diff --git a/test/OpenMP/teams_distribute_parallel_for_ast_print.cpp b/test/OpenMP/teams_distribute_parallel_for_ast_print.cpp
new file mode 100644
index 000000000000..ad14794116ed
--- /dev/null
+++ b/test/OpenMP/teams_distribute_parallel_for_ast_print.cpp
@@ -0,0 +1,203 @@
+// 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
+// expected-no-diagnostics
+
+#ifndef HEADER
+#define HEADER
+
+void foo() {}
+
+struct S {
+ S(): a(0) {}
+ S(int v) : a(v) {}
+ int a;
+ typedef int type;
+};
+
+template <typename T>
+class S7 : public T {
+protected:
+ T a;
+ S7() : a(0) {}
+
+public:
+ S7(typename T::type v) : a(v) {
+#pragma omp target
+#pragma omp teams distribute parallel for private(a) private(this->a) private(T::a)
+ for (int k = 0; k < a.a; ++k)
+ ++this->a.a;
+ }
+ S7 &operator=(S7 &s) {
+#pragma omp target
+#pragma omp teams distribute parallel for private(a) private(this->a)
+ for (int k = 0; k < s.a.a; ++k)
+ ++s.a.a;
+
+ foo();
+ return *this;
+ }
+ void foo() {
+ int b, argv, d, c, e, f;
+#pragma omp target
+#pragma omp teams distribute parallel for default(none), private(b) firstprivate(argv) shared(d) reduction(+:c) reduction(max:e) num_teams(f) thread_limit(d)
+ for (int k = 0; k < a.a; ++k)
+ ++a.a;
+ }
+};
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute parallel for private(this->a) private(this->a) private(T::a)
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute parallel for private(this->a) private(this->a)
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute parallel for default(none) private(b) firstprivate(argv) shared(d) reduction(+: c) reduction(max: e) num_teams(f) thread_limit(d)
+
+class S8 : public S7<S> {
+ S8() {}
+
+public:
+ S8(int v) : S7<S>(v){
+#pragma omp target
+#pragma omp teams distribute parallel for private(a) private(this->a) private(S7<S>::a)
+ for (int k = 0; k < a.a; ++k)
+ ++this->a.a;
+ }
+ S8 &operator=(S8 &s) {
+#pragma omp target
+#pragma omp teams distribute parallel for private(a) private(this->a)
+ for (int k = 0; k < s.a.a; ++k)
+ ++s.a.a;
+
+ bar();
+ return *this;
+ }
+ void bar() {
+ int b, argv, d, c, e, f8;
+#pragma omp target
+#pragma omp teams distribute parallel for default(none), private(b) firstprivate(argv) shared(d) reduction(+:c) reduction(max:e) num_teams(f8) thread_limit(d)
+ for (int k = 0; k < a.a; ++k)
+ ++a.a;
+ }
+};
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute parallel for private(this->a) private(this->a) private(this->S::a)
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute parallel for private(this->a) private(this->a) private(this->S7<S>::a)
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute parallel for private(this->a) private(this->a)
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute parallel for default(none) private(b) firstprivate(argv) shared(d) reduction(+: c) reduction(max: e) num_teams(f8) thread_limit(d)
+
+template <class T, int N>
+T tmain(T argc) {
+ T b = argc, c, d, e, f, g;
+ static T a;
+// CHECK: static T a;
+ const T clen = 5;
+ const T alen = 16;
+ int arr[10];
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i=0; i < 2; ++i)
+ a = 2;
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute parallel for
+// CHECK-NEXT: for (int i = 0; i < 2; ++i)
+// CHECK-NEXT: a = 2;
+#pragma omp target
+#pragma omp teams distribute parallel for private(argc, b), firstprivate(c, d), collapse(2)
+ for (int i = 0; i < 10; ++i)
+ for (int j = 0; j < 10; ++j)
+ foo();
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute parallel for private(argc,b) firstprivate(c,d) collapse(2)
+// CHECK-NEXT: for (int i = 0; i < 10; ++i)
+// CHECK-NEXT: for (int j = 0; j < 10; ++j)
+// CHECK-NEXT: foo();
+ for (int i = 0; i < 10; ++i)
+ foo();
+// CHECK: for (int i = 0; i < 10; ++i)
+// CHECK-NEXT: foo();
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i)
+ foo();
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute parallel for
+// CHECK-NEXT: for (int i = 0; i < 10; ++i)
+// CHECK-NEXT: foo();
+#pragma omp target
+#pragma omp teams distribute parallel for default(none), private(b) firstprivate(argc) shared(d) reduction(+:c) reduction(max:e) num_teams(f) thread_limit(d)
+ for (int k = 0; k < 10; ++k)
+ e += d + argc;
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute parallel for default(none) private(b) firstprivate(argc) shared(d) reduction(+: c) reduction(max: e) num_teams(f) thread_limit(d)
+// CHECK-NEXT: for (int k = 0; k < 10; ++k)
+// CHECK-NEXT: e += d + argc;
+#pragma omp target
+#pragma omp teams distribute parallel for linear(d)
+ for (int k = 0; k < 10; ++k)
+ e += d + argc;
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute parallel for linear(d)
+// CHECK-NEXT: for (int k = 0; k < 10; ++k)
+// CHECK-NEXT: e += d + argc;
+ return T();
+}
+
+int main (int argc, char **argv) {
+ int b = argc, c, d, e, f, g;
+ static int a;
+// CHECK: static int a;
+ const int clen = 5;
+ const int N = 10;
+ int arr[10];
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i=0; i < 2; ++i)
+ a = 2;
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute parallel for
+// CHECK-NEXT: for (int i = 0; i < 2; ++i)
+// CHECK-NEXT: a = 2;
+#pragma omp target
+#pragma omp teams distribute parallel for private(argc,b),firstprivate(argv, c), collapse(2)
+ for (int i = 0; i < 10; ++i)
+ for (int j = 0; j < 10; ++j)
+ foo();
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute parallel for private(argc,b) firstprivate(argv,c) collapse(2)
+// CHECK-NEXT: for (int i = 0; i < 10; ++i)
+// CHECK-NEXT: for (int j = 0; j < 10; ++j)
+// CHECK-NEXT: foo();
+ for (int i = 0; i < 10; ++i)
+ foo();
+// CHECK: for (int i = 0; i < 10; ++i)
+// CHECK-NEXT: foo();
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i)foo();
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute parallel for
+// CHECK-NEXT: for (int i = 0; i < 10; ++i)
+// CHECK-NEXT: foo();
+#pragma omp target
+#pragma omp teams distribute parallel for default(none), private(b) firstprivate(argc) shared(d) reduction(+:c) reduction(max:e) num_teams(f) thread_limit(d)
+ for (int k = 0; k < 10; ++k)
+ e += d + argc;
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute parallel for default(none) private(b) firstprivate(argc) shared(d) reduction(+: c) reduction(max: e) num_teams(f) thread_limit(d)
+// CHECK-NEXT: for (int k = 0; k < 10; ++k)
+// CHECK-NEXT: e += d + argc;
+#pragma omp target
+#pragma omp teams distribute parallel for linear(d)
+ for (int k = 0; k < 10; ++k)
+ e += d + argc;
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute parallel for linear(d)
+// CHECK-NEXT: for (int k = 0; k < 10; ++k)
+// CHECK-NEXT: e += d + argc;
+ return (0);
+}
+
+#endif
diff --git a/test/OpenMP/teams_distribute_parallel_for_collapse_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_collapse_messages.cpp
new file mode 100644
index 000000000000..ea4455dcc5f2
--- /dev/null
+++ b/test/OpenMP/teams_distribute_parallel_for_collapse_messages.cpp
@@ -0,0 +1,172 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp %s -std=c++98
+// RUN: %clang_cc1 -verify -fopenmp %s -std=c++11
+
+void foo() {
+}
+
+#if __cplusplus >= 201103L
+// expected-note@+2 4 {{declared here}}
+#endif
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}}
+
+template <class T, typename S, int N, int ST> // expected-note {{declared here}}
+T tmain(T argc, S **argv) { //expected-note 2 {{declared here}}
+#pragma omp target
+#pragma omp teams distribute parallel for collapse // expected-error {{expected '(' after 'collapse'}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute parallel for collapse ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = ST; i < N; i++)
+
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+#pragma omp target
+#pragma omp teams distribute parallel for collapse () // expected-error {{expected expression}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+// expected-error@+4 {{expected ')'}} expected-note@+4 {{to match this '('}}
+// expected-error@+3 2 {{expression is not an integral constant expression}}
+// expected-note@+2 2 {{read of non-const variable 'argc' is not allowed in a constant expression}}
+#pragma omp target
+#pragma omp teams distribute parallel for collapse (argc
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+// expected-error@+2 2 {{argument to 'collapse' clause must be a strictly positive integer value}}
+#pragma omp target
+#pragma omp teams distribute parallel for collapse (ST // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute parallel for collapse (1)) // expected-warning {{extra tokens at the end of '#pragma omp teams distribute parallel for' are ignored}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute parallel for collapse ((ST > 0) ? 1 + ST : 2) // expected-note 2 {{as specified in 'collapse' clause}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST]; // expected-error 2 {{expected 2 for loops after '#pragma omp teams distribute parallel for', but found only 1}}
+
+#if __cplusplus >= 201103L
+// expected-note@+6 2 {{non-constexpr function 'foobool' cannot be used}}
+#endif
+// expected-error@+4 2 {{directive '#pragma omp teams distribute parallel for' cannot contain more than one 'collapse' clause}}
+// expected-error@+3 2 {{argument to 'collapse' clause must be a strictly positive integer value}}
+// expected-error@+2 2 {{expression is not an integral constant expression}}
+#pragma omp target
+#pragma omp teams distribute parallel for collapse (foobool(argc)), collapse (true), collapse (-5)
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp distribute collapse (S) // expected-error {{'S' does not refer to a value}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#if __cplusplus >= 201103L
+// expected-error@+5 2 {{integral constant expression must have integral or unscoped enumeration type}}
+#else
+// expected-error@+3 2 {{expression is not an integral constant expression}}
+#endif
+#pragma omp target
+#pragma omp teams distribute parallel for collapse (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute parallel for collapse (1)
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute parallel for collapse (N) // expected-error {{argument to 'collapse' clause must be a strictly positive integer value}}
+ for (T i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute parallel for collapse (2) // expected-note {{as specified in 'collapse' clause}}
+ foo(); // expected-error {{expected 2 for loops after '#pragma omp teams distribute parallel for'}}
+ return argc;
+}
+
+int main(int argc, char **argv) {
+#pragma omp target
+#pragma omp teams distribute parallel for collapse // expected-error {{expected '(' after 'collapse'}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target
+#pragma omp teams distribute parallel for collapse ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target
+#pragma omp teams distribute parallel for collapse () // expected-error {{expected expression}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target
+#pragma omp teams distribute parallel for collapse (4 // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-note {{as specified in 'collapse' clause}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4]; // expected-error {{expected 4 for loops after '#pragma omp teams distribute parallel for', but found only 1}}
+
+#pragma omp target
+#pragma omp teams distribute parallel for collapse (2+2)) // expected-warning {{extra tokens at the end of '#pragma omp teams distribute parallel for' are ignored}} expected-note {{as specified in 'collapse' clause}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4]; // expected-error {{expected 4 for loops after '#pragma omp teams distribute parallel for', but found only 1}}
+
+#if __cplusplus >= 201103L
+// expected-note@+3 {{non-constexpr function 'foobool' cannot be used}}
+#endif
+#pragma omp target
+#pragma omp teams distribute parallel for collapse (foobool(1) > 0 ? 1 : 2) // expected-error {{expression is not an integral constant expression}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#if __cplusplus >= 201103L
+// expected-note@+6 {{non-constexpr function 'foobool' cannot be used}}
+#endif
+// expected-error@+4 {{expression is not an integral constant expression}}
+// expected-error@+3 2 {{directive '#pragma omp teams distribute parallel for' cannot contain more than one 'collapse' clause}}
+// expected-error@+2 2 {{argument to 'collapse' clause must be a strictly positive integer value}}
+#pragma omp target
+#pragma omp teams distribute parallel for collapse (foobool(argc)), collapse (true), collapse (-5)
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target
+#pragma omp teams distribute parallel for collapse (S1) // expected-error {{'S1' does not refer to a value}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#if __cplusplus >= 201103L
+// expected-error@+5 {{integral constant expression must have integral or unscoped enumeration type}}
+#else
+// expected-error@+3 {{expression is not an integral constant expression}}
+#endif
+#pragma omp target
+#pragma omp teams distribute parallel for collapse (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+// expected-error@+4 {{statement after '#pragma omp teams distribute parallel for' must be a for loop}}
+// expected-note@+2 {{in instantiation of function template specialization 'tmain<int, char, -1, -2>' requested here}}
+#pragma omp target
+#pragma omp teams distribute parallel for collapse(collapse(tmain<int, char, -1, -2>(argc, argv) // expected-error 2 {{expected ')'}} expected-note 2 {{to match this '('}}
+ foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for collapse (2) // expected-note {{as specified in 'collapse' clause}}
+ foo(); // expected-error {{expected 2 for loops after '#pragma omp teams distribute parallel for'}}
+
+// expected-note@+1 {{in instantiation of function template specialization 'tmain<int, char, 1, 0>' requested here}}
+ return tmain<int, char, 1, 0>(argc, argv);
+}
+
diff --git a/test/OpenMP/teams_distribute_parallel_for_default_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_default_messages.cpp
new file mode 100644
index 000000000000..4cd7e65510b1
--- /dev/null
+++ b/test/OpenMP/teams_distribute_parallel_for_default_messages.cpp
@@ -0,0 +1,30 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo();
+
+int main(int argc, char **argv) {
+ #pragma omp target
+ #pragma omp teams distribute parallel for default // expected-error {{expected '(' after 'default'}}
+ for (int i=0; i<200; i++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for default ( // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i=0; i<200; i++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for default () // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+ for (int i=0; i<200; i++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for default (none // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i=0; i<200; i++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for default (shared), default(shared) // expected-error {{directive '#pragma omp teams distribute parallel for' cannot contain more than one 'default' clause}}
+ for (int i=0; i<200; i++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for default (x) // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+ for (int i=0; i<200; i++) foo();
+
+ #pragma omp target
+ #pragma omp teams distribute parallel for default(none)
+ for (int i=0; i<200; i++) ++argc; // expected-error {{variable 'argc' must have explicitly specified data sharing attributes}}
+
+ return 0;
+}
diff --git a/test/OpenMP/teams_distribute_parallel_for_dist_schedule_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_dist_schedule_messages.cpp
new file mode 100644
index 000000000000..098abb74870b
--- /dev/null
+++ b/test/OpenMP/teams_distribute_parallel_for_dist_schedule_messages.cpp
@@ -0,0 +1,104 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}} expected-note {{declared here}}
+
+template <class T, int N>
+T tmain(T argc) {
+ T b = argc, c, d, e, f, g;
+ char ** argv;
+ static T a;
+// CHECK: static T a;
+
+#pragma omp target
+#pragma omp teams distribute parallel for dist_schedule // expected-error {{expected '(' after 'dist_schedule'}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for dist_schedule ( // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for dist_schedule () // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for dist_schedule (static // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for dist_schedule (static, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for dist_schedule (argc)) // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}} expected-warning {{extra tokens at the end of '#pragma omp teams distribute parallel for' are ignored}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for dist_schedule (static, argc > 0 ? argv[1] : argv[2]) // expected-error2 {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for dist_schedule (static), dist_schedule (static, 1) // expected-error {{directive '#pragma omp teams distribute parallel for' cannot contain more than one 'dist_schedule' clause}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for dist_schedule (static, S1) // expected-error {{'S1' does not refer to a value}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for dist_schedule (static, argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error3 {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ for (int i = 0; i < 10; ++i) foo();
+
+ return T();
+}
+
+int main(int argc, char **argv) {
+#pragma omp target
+#pragma omp teams distribute parallel for dist_schedule // expected-error {{expected '(' after 'dist_schedule'}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for dist_schedule ( // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for dist_schedule () // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for dist_schedule (static // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for dist_schedule (static, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for dist_schedule (argc)) // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}} expected-warning {{extra tokens at the end of '#pragma omp teams distribute parallel for' are ignored}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for dist_schedule (static, argc > 0 ? argv[1] : argv[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for dist_schedule (static), dist_schedule (static, 1) // expected-error {{directive '#pragma omp teams distribute parallel for' cannot contain more than one 'dist_schedule' clause}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for dist_schedule (static, S1) // expected-error {{'S1' does not refer to a value}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for dist_schedule (static, argv[1]=2) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 0; i < 10; ++i) foo();
+
+ return (tmain<int, 5>(argc) + tmain<char, 1>(argv[0][0])); // expected-note {{in instantiation of function template specialization 'tmain<int, 5>' requested here}} expected-note {{in instantiation of function template specialization 'tmain<char, 1>' requested here}}
+}
diff --git a/test/OpenMP/teams_distribute_parallel_for_firstprivate_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_firstprivate_messages.cpp
new file mode 100644
index 000000000000..e6314c210e8f
--- /dev/null
+++ b/test/OpenMP/teams_distribute_parallel_for_firstprivate_messages.cpp
@@ -0,0 +1,152 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}} expected-note{{forward declaration of 'S1'}}
+extern S1 a;
+class S2 {
+ mutable int a;
+
+public:
+ S2() : a(0) {}
+ S2(const S2 &s2) : a(s2.a) {}
+ static float S2s;
+ static const float S2sc;
+};
+const float S2::S2sc = 0;
+const S2 b;
+const S2 ba[5];
+class S3 {
+ int a;
+ S3 &operator=(const S3 &s3);
+
+public:
+ S3() : a(0) {} // expected-note {{candidate constructor not viable: requires 0 arguments, but 1 was provided}}
+ S3(S3 &s3) : a(s3.a) {} // expected-note {{candidate constructor not viable: 1st argument ('const S3') would lose const qualifier}}
+};
+const S3 c;
+const S3 ca[5];
+extern const int f;
+class S4 {
+ int a;
+ S4();
+ S4(const S4 &s4);
+public:
+ S4(int v):a(v) { }
+};
+class S5 {
+ int a;
+ S5():a(0) {}
+ S5(const S5 &s5):a(s5.a) { }
+public:
+ S5(int v):a(v) { }
+};
+class S6 {
+ int a;
+public:
+ S6() : a(0) { }
+};
+
+S3 h;
+#pragma omp threadprivate(h) // expected-note {{defined as threadprivate or thread local}}
+
+int main(int argc, char **argv) {
+ const int d = 5;
+ const int da[5] = { 0 };
+ S4 e(4);
+ S5 g(5);
+ S6 p;
+ int i;
+ int &j = i;
+
+#pragma omp target
+#pragma omp teams distribute parallel for firstprivate // expected-error {{expected '(' after 'firstprivate'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for firstprivate ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for firstprivate () // expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for firstprivate (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for firstprivate (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for firstprivate (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for firstprivate (argc)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for firstprivate (S1) // expected-error {{'S1' does not refer to a value}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for firstprivate (a, b, c, d, f) // expected-error {{firstprivate variable with incomplete type 'S1'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for firstprivate (argv[1]) // expected-error {{expected variable name}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for firstprivate(ba)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for firstprivate(ca) // expected-error {{no matching constructor for initialization of 'S3'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for firstprivate(da)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for firstprivate(S2::S2s)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for firstprivate(S2::S2sc)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for firstprivate(h) // expected-error {{threadprivate or thread local variable cannot be firstprivate}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for private(i), firstprivate(i) // expected-error {{private variable cannot be firstprivate}} expected-note {{defined as private}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for firstprivate(i)
+ for (j = 0; j < argc; ++j) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for firstprivate(i) // expected-note {{defined as firstprivate}}
+ for (i = 0; i < argc; ++i) foo(); // expected-error {{loop iteration variable in the associated loop of 'omp teams distribute parallel for' directive may not be firstprivate, predetermined as private}}
+
+#pragma omp target
+#pragma omp teams distribute parallel for firstprivate(j)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for lastprivate(argc), firstprivate(argc) // OK
+ for (i = 0; i < argc; ++i) foo();
+
+ return 0;
+}
diff --git a/test/OpenMP/teams_distribute_parallel_for_if_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_if_messages.cpp
new file mode 100644
index 000000000000..14253b89f63e
--- /dev/null
+++ b/test/OpenMP/teams_distribute_parallel_for_if_messages.cpp
@@ -0,0 +1,140 @@
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ferror-limit 100 %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}}
+
+template <class T, class S> // expected-note {{declared here}}
+int tmain(T argc, S **argv) {
+ T i;
+#pragma omp target
+#pragma omp teams distribute parallel for if // expected-error {{expected '(' after 'if'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for if ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for if () // expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for if (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for if (argc)) // expected-warning {{extra tokens at the end of '#pragma omp teams distribute parallel for' are ignored}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for if (argc > 0 ? argv[1] : argv[2])
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for if (foobool(argc)), if (true) // expected-error {{directive '#pragma omp teams distribute parallel for' cannot contain more than one 'if' clause}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for if (S) // expected-error {{'S' does not refer to a value}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for if (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for if (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for if(argc)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for if(parallel // expected-error {{use of undeclared identifier 'parallel'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for if(parallel : // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for if(parallel : argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for if(parallel : argc)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for if(parallel : argc) if (for:argc) // expected-error {{directive name modifier 'for' is not allowed for '#pragma omp teams distribute parallel for'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for if(parallel : argc) if (parallel:argc) // expected-error {{directive '#pragma omp teams distribute parallel for' cannot contain more than one 'if' clause with 'parallel' name modifier}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for if(parallel : argc) if (argc) // expected-error {{no more 'if' clause is allowed}} expected-note {{previous clause with directive name modifier specified here}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for if(distribute : argc) // expected-error {{directive name modifier 'distribute' is not allowed for '#pragma omp teams distribute parallel for'}}
+ for (i = 0; i < argc; ++i) foo();
+
+ return 0;
+}
+
+int main(int argc, char **argv) {
+ int i;
+#pragma omp target
+#pragma omp teams distribute parallel for if // expected-error {{expected '(' after 'if'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for if ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for if () // expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for if (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for if (argc)) // expected-warning {{extra tokens at the end of '#pragma omp teams distribute parallel for' are ignored}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for if (argc > 0 ? argv[1] : argv[2])
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for if (foobool(argc)), if (true) // expected-error {{directive '#pragma omp teams distribute parallel for' cannot contain more than one 'if' clause}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for if (S1) // expected-error {{'S1' does not refer to a value}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for if (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for if (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for if (1 0) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for if(if(tmain(argc, argv) // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for if(parallel // expected-error {{use of undeclared identifier 'parallel'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for if(parallel : // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for if(parallel : argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for if(parallel : argc)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for if(parallel : argc) if (for:argc) // expected-error {{directive name modifier 'for' is not allowed for '#pragma omp teams distribute parallel for'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for if(parallel : argc) if (parallel:argc) // expected-error {{directive '#pragma omp teams distribute parallel for' cannot contain more than one 'if' clause with 'parallel' name modifier}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for if(parallel : argc) if (argc) // expected-error {{no more 'if' clause is allowed}} expected-note {{previous clause with directive name modifier specified here}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for if(distribute : argc) // expected-error {{directive name modifier 'distribute' is not allowed for '#pragma omp teams distribute parallel for'}}
+ for (i = 0; i < argc; ++i) foo();
+
+ return tmain(argc, argv);
+}
diff --git a/test/OpenMP/teams_distribute_parallel_for_lastprivate_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_lastprivate_messages.cpp
new file mode 100644
index 000000000000..5691af71f7cd
--- /dev/null
+++ b/test/OpenMP/teams_distribute_parallel_for_lastprivate_messages.cpp
@@ -0,0 +1,272 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note 2 {{declared here}} expected-note 2 {{forward declaration of 'S1'}}
+extern S1 a;
+class S2 {
+ mutable int a;
+
+public:
+ S2() : a(0) {}
+ S2(S2 &s2) : a(s2.a) {}
+ const S2 &operator =(const S2&) const;
+ S2 &operator =(const S2&);
+ static float S2s; // expected-note {{static data member is predetermined as shared}}
+ static const float S2sc;
+};
+const float S2::S2sc = 0; // expected-note {{static data member is predetermined as shared}}
+const S2 b;
+const S2 ba[5];
+class S3 {
+ int a;
+ S3 &operator=(const S3 &s3); // expected-note 2 {{implicitly declared private here}}
+
+public:
+ S3() : a(0) {}
+ S3(S3 &s3) : a(s3.a) {}
+};
+const S3 c; // expected-note {{global variable is predetermined as shared}}
+const S3 ca[5]; // expected-note {{global variable is predetermined as shared}}
+extern const int f; // expected-note {{global variable is predetermined as shared}}
+class S4 {
+ int a;
+ S4(); // expected-note 3 {{implicitly declared private here}}
+ S4(const S4 &s4);
+
+public:
+ S4(int v) : a(v) {}
+};
+class S5 {
+ int a;
+ S5() : a(0) {} // expected-note {{implicitly declared private here}}
+
+public:
+ S5(const S5 &s5) : a(s5.a) {}
+ S5(int v) : a(v) {}
+};
+class S6 {
+ int a;
+ S6() : a(0) {}
+
+public:
+ S6(const S6 &s6) : a(s6.a) {}
+ S6(int v) : a(v) {}
+};
+
+S3 h;
+#pragma omp threadprivate(h) // expected-note 2 {{defined as threadprivate or thread local}}
+
+template <class I, class C>
+int foomain(int argc, char **argv) {
+ I e(4);
+ I g(5);
+ int i;
+ int &j = i;
+#pragma omp target
+#pragma omp teams distribute parallel for lastprivate // expected-error {{expected '(' after 'lastprivate'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for lastprivate( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for lastprivate() // expected-error {{expected expression}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for lastprivate(argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for lastprivate(argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for lastprivate(argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for lastprivate(argc)
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for lastprivate(S1) // expected-error {{'S1' does not refer to a value}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for lastprivate(a, b) // expected-error {{lastprivate variable with incomplete type 'S1'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for lastprivate(argv[1]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for lastprivate(e, g) // expected-error 2 {{calling a private constructor of class 'S4'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for lastprivate(h) // expected-error {{threadprivate or thread local variable cannot be lastprivate}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ int v = 0;
+#pragma omp target
+#pragma omp teams distribute parallel for lastprivate(i)
+ for (int k = 0; k < argc; ++k) {
+ i = k;
+ v += i;
+ }
+
+#pragma omp target
+#pragma omp teams distribute parallel for lastprivate(j) private(i)
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for lastprivate(i)
+ for (int k = 0; k < argc; ++k) ++k;
+
+ return 0;
+}
+
+void bar(S4 a[2]) {
+#pragma omp target
+#pragma omp teams distribute parallel for lastprivate(a)
+ for (int i = 0; i < 2; ++i) foo();
+}
+
+namespace A {
+double x;
+#pragma omp threadprivate(x) // expected-note {{defined as threadprivate or thread local}}
+}
+namespace B {
+using A::x;
+}
+
+int main(int argc, char **argv) {
+ const int d = 5; // expected-note {{constant variable is predetermined as shared}}
+ const int da[5] = {0}; // expected-note {{constant variable is predetermined as shared}}
+ S4 e(4);
+ S5 g(5);
+ S3 m;
+ S6 n(2);
+ int i;
+ int &j = i;
+#pragma omp target
+#pragma omp teams distribute parallel for lastprivate // expected-error {{expected '(' after 'lastprivate'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for lastprivate( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for lastprivate() // expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for lastprivate(argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for lastprivate(argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for lastprivate(argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for lastprivate(argc)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for lastprivate(S1) // expected-error {{'S1' does not refer to a value}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be lastprivate}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for lastprivate(argv[1]) // expected-error {{expected variable name}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for lastprivate(2 * 2) // expected-error {{expected variable name}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for lastprivate(ba)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for lastprivate(ca) // expected-error {{shared variable cannot be lastprivate}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for lastprivate(da) // expected-error {{shared variable cannot be lastprivate}}
+ for (i = 0; i < argc; ++i) foo();
+
+ int xa;
+#pragma omp target
+#pragma omp teams distribute parallel for lastprivate(xa) // OK
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for lastprivate(S2::S2s) // expected-error {{shared variable cannot be lastprivate}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for lastprivate(S2::S2sc) // expected-error {{shared variable cannot be lastprivate}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for lastprivate(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for lastprivate(m) // expected-error {{'operator=' is a private member of 'S3'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for lastprivate(h) // expected-error {{threadprivate or thread local variable cannot be lastprivate}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for lastprivate(B::x) // expected-error {{threadprivate or thread local variable cannot be lastprivate}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for private(xa), lastprivate(xa) // expected-error {{private variable cannot be lastprivate}} expected-note {{defined as private}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for lastprivate(xa)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for lastprivate(j)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for firstprivate(m) lastprivate(m) // expected-error {{'operator=' is a private member of 'S3'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for lastprivate(n) firstprivate(n) // OK
+ for (i = 0; i < argc; ++i) foo();
+
+ static int si;
+#pragma omp target
+#pragma omp teams distribute parallel for lastprivate(si) // OK
+ for (i = 0; i < argc; ++i) si = i + 1;
+
+ return foomain<S4, S5>(argc, argv); // expected-note {{in instantiation of function template specialization 'foomain<S4, S5>' requested here}}
+}
diff --git a/test/OpenMP/teams_distribute_parallel_for_linear_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_linear_messages.cpp
new file mode 100644
index 000000000000..b14fb2328b2b
--- /dev/null
+++ b/test/OpenMP/teams_distribute_parallel_for_linear_messages.cpp
@@ -0,0 +1,293 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+namespace X {
+ int x;
+};
+
+struct B {
+ static int ib; // expected-note {{'B::ib' declared here}}
+ static int bfoo() { return 8; }
+};
+
+int bfoo() { return 4; }
+
+int z;
+const int C1 = 1;
+const int C2 = 2;
+void test_linear_colons()
+{
+ int B = 0;
+
+#pragma omp target
+#pragma omp teams distribute parallel for linear(B:bfoo())
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target
+#pragma omp teams distribute parallel for linear(B::ib:B:bfoo()) // expected-error {{unexpected ':' in nested name specifier; did you mean '::'}}
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target
+#pragma omp teams distribute parallel for linear(B:ib) // expected-error {{use of undeclared identifier 'ib'; did you mean 'B::ib'}}
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target
+#pragma omp teams distribute parallel for linear(z:B:ib) // expected-error {{unexpected ':' in nested name specifier; did you mean '::'?}}
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target
+#pragma omp teams distribute parallel for linear(B:B::bfoo())
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target
+#pragma omp teams distribute parallel for linear(X::x : ::z)
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target
+#pragma omp teams distribute parallel for linear(B,::z, X::x)
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target
+#pragma omp teams distribute parallel for linear(::z)
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target
+#pragma omp teams distribute parallel for linear(B::bfoo()) // expected-error {{expected variable name}}
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target
+#pragma omp teams distribute parallel for linear(B::ib,B:C1+C2)
+ for (int i = 0; i < 10; ++i) ;
+}
+
+template<int L, class T, class N> T test_template(T* arr, N num) {
+ N i;
+ T sum = (T)0;
+ T ind2 = - num * L; // expected-note {{'ind2' defined here}}
+
+#pragma omp target
+#pragma omp teams distribute parallel for linear(ind2:L) // expected-error {{argument of a linear clause should be of integral or pointer type}}
+ for (i = 0; i < num; ++i) {
+ T cur = arr[(int)ind2];
+ ind2 += L;
+ sum += cur;
+ }
+ return T();
+}
+
+template<int LEN> int test_warn() {
+ int ind2 = 0;
+ #pragma omp target
+ #pragma omp teams distribute parallel for linear(ind2:LEN) // expected-warning {{zero linear step (ind2 should probably be const)}}
+ for (int i = 0; i < 100; i++) {
+ ind2 += LEN;
+ }
+ return ind2;
+}
+
+struct S1; // expected-note 2 {{declared here}} expected-note 2 {{forward declaration of 'S1'}}
+extern S1 a;
+class S2 {
+ mutable int a;
+public:
+ S2():a(0) { }
+};
+const S2 b; // expected-note 2 {{'b' defined here}}
+const S2 ba[5];
+class S3 {
+ int a;
+public:
+ S3():a(0) { }
+};
+const S3 ca[5];
+class S4 {
+ int a;
+ S4();
+public:
+ S4(int v):a(v) { }
+};
+class S5 {
+ int a;
+ S5():a(0) {}
+public:
+ S5(int v):a(v) { }
+};
+
+S3 h;
+#pragma omp threadprivate(h) // expected-note 2 {{defined as threadprivate or thread local}}
+
+template<class I, class C> int foomain(I argc, C **argv) {
+ I e(4);
+ I g(5);
+ int i;
+ int &j = i;
+
+#pragma omp target
+#pragma omp teams distribute parallel for linear // expected-error {{expected '(' after 'linear'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for linear ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for linear () // expected-error {{expected expression}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for linear (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for linear (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for linear (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for linear (argc : 5)
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for linear (S1) // expected-error {{'S1' does not refer to a value}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for linear (a, b:B::ib) // expected-error {{linear variable with incomplete type 'S1'}} expected-error {{const-qualified variable cannot be linear}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for linear (argv[1]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for linear(e, g)
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for linear(h) // expected-error {{threadprivate or thread local variable cannot be linear}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for linear(i)
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp parallel
+ {
+ int v = 0;
+ int i;
+ #pragma omp target
+ #pragma omp teams distribute parallel for linear(v:i)
+ for (int k = 0; k < argc; ++k) { i = k; v += i; }
+ }
+
+#pragma omp target
+#pragma omp teams distribute parallel for linear(j)
+ for (int k = 0; k < argc; ++k) ++k;
+
+ int v = 0;
+
+#pragma omp target
+#pragma omp teams distribute parallel for linear(v:j)
+ for (int k = 0; k < argc; ++k) { ++k; v += j; }
+
+#pragma omp target
+#pragma omp teams distribute parallel for linear(i)
+ for (int k = 0; k < argc; ++k) ++k;
+ return 0;
+}
+
+namespace A {
+double x;
+#pragma omp threadprivate(x) // expected-note {{defined as threadprivate or thread local}}
+}
+namespace C {
+using A::x;
+}
+
+int main(int argc, char **argv) {
+ double darr[100];
+ // expected-note@+1 {{in instantiation of function template specialization 'test_template<-4, double, int>' requested here}}
+ test_template<-4>(darr, 4);
+ // expected-note@+1 {{in instantiation of function template specialization 'test_warn<0>' requested here}}
+ test_warn<0>();
+
+ S4 e(4); // expected-note {{'e' defined here}}
+ S5 g(5); // expected-note {{'g' defined here}}
+ int i;
+ int &j = i;
+
+#pragma omp target
+#pragma omp teams distribute parallel for linear // expected-error {{expected '(' after 'linear'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for linear ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for linear () // expected-error {{expected expression}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for linear (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for linear (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for linear (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for linear (argc)
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for linear (S1) // expected-error {{'S1' does not refer to a value}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+
+#pragma omp target
+#pragma omp teams distribute parallel for linear (a, b) // expected-error {{linear variable with incomplete type 'S1'}} expected-error {{const-qualified variable cannot be linear}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for linear (argv[1]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for linear(e, g) // expected-error {{argument of a linear clause should be of integral or pointer type, not 'S4'}} expected-error {{argument of a linear clause should be of integral or pointer type, not 'S5'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for linear(h, C::x) // expected-error 2 {{threadprivate or thread local variable cannot be linear}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp parallel
+ {
+ int i;
+ #pragma omp target
+ #pragma omp teams distribute parallel for linear(i)
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute parallel for linear(i : 4)
+ for (int k = 0; k < argc; ++k) { ++k; i += 4; }
+ }
+
+#pragma omp target
+#pragma omp teams distribute parallel for linear(j)
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for linear(i)
+ for (int k = 0; k < argc; ++k) ++k;
+
+ foomain<int,char>(argc,argv); // expected-note {{in instantiation of function template specialization 'foomain<int, char>' requested here}}
+ return 0;
+}
+
diff --git a/test/OpenMP/teams_distribute_parallel_for_loop_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_loop_messages.cpp
new file mode 100644
index 000000000000..ea392fb93ed3
--- /dev/null
+++ b/test/OpenMP/teams_distribute_parallel_for_loop_messages.cpp
@@ -0,0 +1,714 @@
+// RUN: %clang_cc1 -fsyntax-only -fopenmp -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s
+
+class S {
+ int a;
+ S() : a(0) {}
+
+public:
+ S(int v) : a(v) {}
+ S(const S &s) : a(s.a) {}
+};
+
+static int sii;
+// expected-note@+1 {{defined as threadprivate or thread local}}
+#pragma omp threadprivate(sii)
+static int globalii;
+
+int test_iteration_spaces() {
+ const int N = 100;
+ float a[N], b[N], c[N];
+ int ii, jj, kk;
+ float fii;
+ double dii;
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; i += 1) {
+ c[i] = a[i] + b[i];
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (char i = 0; i < 10; i++) {
+ c[i] = a[i] + b[i];
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (char i = 0; i < 10; i += '\1') {
+ c[i] = a[i] + b[i];
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (long long i = 0; i < 10; i++) {
+ c[i] = a[i] + b[i];
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-error@+1 {{expression must have integral or unscoped enumeration type, not 'double'}}
+ for (long long i = 0; i < 10; i += 1.5) {
+ c[i] = a[i] + b[i];
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (long long i = 0; i < 'z'; i += 1u) {
+ c[i] = a[i] + b[i];
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-error@+1 {{variable must be of integer or random access iterator type}}
+ for (float fi = 0; fi < 10.0; fi++) {
+ c[(int)fi] = a[(int)fi] + b[(int)fi];
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-error@+1 {{variable must be of integer or random access iterator type}}
+ for (double fi = 0; fi < 10.0; fi++) {
+ c[(int)fi] = a[(int)fi] + b[(int)fi];
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (int &ref = ii; ref < 10; ref++) {
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (int i; i < 10; i++)
+ c[i] = a[i];
+
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (int i = 0, j = 0; i < 10; ++i)
+ c[i] = a[i];
+
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (; ii < 10; ++ii)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-warning@+2 {{expression result unused}}
+// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (ii + 1; ii < 10; ++ii)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (c[ii] = 0; ii < 10; ++ii)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute parallel for
+// Ok to skip parenthesises.
+ for (((ii)) = 0; ii < 10; ++ii)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
+ for (int i = 0; i; i++)
+ c[i] = a[i];
+
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-error@+2 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'i'}}
+ for (int i = 0; jj < kk; ii++)
+ c[i] = a[i];
+
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
+ for (int i = 0; !!i; i++)
+ c[i] = a[i];
+
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
+ for (int i = 0; i != 1; i++)
+ c[i] = a[i];
+
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
+ for (int i = 0;; i++)
+ c[i] = a[i];
+
+// Ok.
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 11; i > 10; i--)
+ c[i] = a[i];
+
+// Ok.
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i)
+ c[i] = a[i];
+
+// Ok.
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (ii = 0; ii < 10; ++ii)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+ for (ii = 0; ii < 10; ++jj)
+ c[ii] = a[jj];
+
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+ for (ii = 0; ii < 10; ++++ii)
+ c[ii] = a[ii];
+
+// Ok but undefined behavior (in general, cannot check that incr
+// is really loop-invariant).
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (ii = 0; ii < 10; ii = ii + ii)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-error@+1 {{expression must have integral or unscoped enumeration type, not 'float'}}
+ for (ii = 0; ii < 10; ii = ii + 1.0f)
+ c[ii] = a[ii];
+
+// Ok - step was converted to integer type.
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (ii = 0; ii < 10; ii = ii + (int)1.1f)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+ for (ii = 0; ii < 10; jj = ii + 2)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-warning@+2 {{relational comparison result unused}}
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+ for (ii = 0; ii<10; jj> kk + 2)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+ for (ii = 0; ii < 10;)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-warning@+2 {{expression result unused}}
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+ for (ii = 0; ii < 10; !ii)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+ for (ii = 0; ii < 10; ii ? ++ii : ++jj)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+ for (ii = 0; ii < 10; ii = ii < 10)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}}
+ for (ii = 0; ii < 10; ii = ii + 0)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}}
+ for (ii = 0; ii < 10; ii = ii + (int)(0.8 - 0.45))
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}}
+ for (ii = 0; (ii) < 10; ii -= 25)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}}
+ for (ii = 0; (ii < 10); ii -= 0)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-note@+2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+1 {{increment expression must cause 'ii' to decrease on each iteration of OpenMP for loop}}
+ for (ii = 0; ii > 10; (ii += 0))
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}}
+ for (ii = 0; ii < 10; (ii) = (1 - 1) + (ii))
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-note@+2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+1 {{increment expression must cause 'ii' to decrease on each iteration of OpenMP for loop}}
+ for ((ii = 0); ii > 10; (ii -= 0))
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}}
+ for (ii = 0; (ii < 10); (ii -= 0))
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute parallel for firstprivate(ii) // expected-note {{defined as firstprivate}}
+// expected-error@+1 {{loop iteration variable in the associated loop of 'omp teams distribute parallel for' directive may not be firstprivate, predetermined as private}}
+ for (ii = 0; ii < 10; ii++)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute parallel for private(ii) // OK
+ for (ii = 0; ii < 10; ii++)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute parallel for lastprivate(ii) // OK
+ for (ii = 0; ii < 10; ii++)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-error@+1 {{loop iteration variable in the associated loop of 'omp teams distribute parallel for' directive may not be threadprivate or thread local, predetermined as private}}
+ for (sii = 0; sii < 10; sii++)
+ c[sii] = a[sii];
+
+ {
+#pragma omp target
+#pragma omp teams distribute parallel for collapse(2)
+ for (ii = 0; ii < 10; ii += 1)
+ for (globalii = 0; globalii < 10; globalii += 1)
+ c[globalii] += a[globalii] + ii;
+ }
+
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-error@+1 {{statement after '#pragma omp teams distribute parallel for' must be a for loop}}
+ for (auto &item : a) {
+ item = item + 1;
+ }
+
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'i' to increase on each iteration of OpenMP for loop}}
+ for (unsigned i = 9; i < 10; i--) {
+ c[i] = a[i] + b[i];
+ }
+
+ int(*lb)[4] = nullptr;
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int(*p)[4] = lb; p < lb + 8; ++p) {
+ }
+
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (int a{0}; a < 10; ++a) {
+ }
+
+ return 0;
+}
+
+// Iterators allowed in openmp for-loops.
+namespace std {
+struct random_access_iterator_tag {};
+template <class Iter>
+struct iterator_traits {
+ typedef typename Iter::difference_type difference_type;
+ typedef typename Iter::iterator_category iterator_category;
+};
+template <class Iter>
+typename iterator_traits<Iter>::difference_type
+distance(Iter first, Iter last) { return first - last; }
+}
+class Iter0 {
+public:
+ Iter0() {}
+ Iter0(const Iter0 &) {}
+ Iter0 operator++() { return *this; }
+ Iter0 operator--() { return *this; }
+ bool operator<(Iter0 a) { return true; }
+};
+// expected-note@+2 {{candidate function not viable: no known conversion from 'GoodIter' to 'Iter0' for 1st argument}}
+// expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'Iter0' for 1st argument}}
+int operator-(Iter0 a, Iter0 b) { return 0; }
+class Iter1 {
+public:
+ Iter1(float f = 0.0f, double d = 0.0) {}
+ Iter1(const Iter1 &) {}
+ Iter1 operator++() { return *this; }
+ Iter1 operator--() { return *this; }
+ bool operator<(Iter1 a) { return true; }
+ bool operator>=(Iter1 a) { return false; }
+};
+class GoodIter {
+public:
+ GoodIter() {}
+ GoodIter(const GoodIter &) {}
+ GoodIter(int fst, int snd) {}
+ GoodIter &operator=(const GoodIter &that) { return *this; }
+ GoodIter &operator=(const Iter0 &that) { return *this; }
+ GoodIter &operator+=(int x) { return *this; }
+ explicit GoodIter(void *) {}
+ GoodIter operator++() { return *this; }
+ GoodIter operator--() { return *this; }
+ bool operator!() { return true; }
+ bool operator<(GoodIter a) { return true; }
+ bool operator<=(GoodIter a) { return true; }
+ bool operator>=(GoodIter a) { return false; }
+ typedef int difference_type;
+ typedef std::random_access_iterator_tag iterator_category;
+};
+// expected-note@+2 {{candidate function not viable: no known conversion from 'const Iter0' to 'GoodIter' for 2nd argument}}
+// expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'GoodIter' for 1st argument}}
+int operator-(GoodIter a, GoodIter b) { return 0; }
+// expected-note@+1 3 {{candidate function not viable: requires single argument 'a', but 2 arguments were provided}}
+GoodIter operator-(GoodIter a) { return a; }
+// expected-note@+2 {{candidate function not viable: no known conversion from 'const Iter0' to 'int' for 2nd argument}}
+// expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'GoodIter' for 1st argument}}
+GoodIter operator-(GoodIter a, int v) { return GoodIter(); }
+// expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter0' to 'GoodIter' for 1st argument}}
+GoodIter operator+(GoodIter a, int v) { return GoodIter(); }
+// expected-note@+2 {{candidate function not viable: no known conversion from 'GoodIter' to 'int' for 1st argument}}
+// expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'int' for 1st argument}}
+GoodIter operator-(int v, GoodIter a) { return GoodIter(); }
+// expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter0' to 'int' for 1st argument}}
+GoodIter operator+(int v, GoodIter a) { return GoodIter(); }
+
+int test_with_random_access_iterator() {
+ GoodIter begin, end;
+ Iter0 begin0, end0;
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (GoodIter I = begin; I < end; ++I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (GoodIter &I = begin; I < end; ++I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (GoodIter I = begin; I >= end; --I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (GoodIter I(begin); I < end; ++I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (GoodIter I(nullptr); I < end; ++I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (GoodIter I(0); I < end; ++I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (GoodIter I(1, 2); I < end; ++I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (begin = GoodIter(0); begin < end; ++begin)
+ ++begin;
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-error@+2 {{invalid operands to binary expression ('GoodIter' and 'const Iter0')}}
+// expected-error@+1 {{could not calculate number of iterations calling 'operator-' with upper and lower loop bounds}}
+ for (begin = begin0; begin < end; ++begin)
+ ++begin;
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (++begin; begin < end; ++begin)
+ ++begin;
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (begin = end; begin < end; ++begin)
+ ++begin;
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'I'}}
+ for (GoodIter I = begin; I - I; ++I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'I'}}
+ for (GoodIter I = begin; begin < end; ++I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'I'}}
+ for (GoodIter I = begin; !I; ++I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-note@+2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+1 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}}
+ for (GoodIter I = begin; I >= end; I = I + 1)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (GoodIter I = begin; I >= end; I = I - 1)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'I'}}
+ for (GoodIter I = begin; I >= end; I = -I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-note@+2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+1 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}}
+ for (GoodIter I = begin; I >= end; I = 2 + I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'I'}}
+ for (GoodIter I = begin; I >= end; I = 2 - I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-error@+1 {{invalid operands to binary expression ('Iter0' and 'int')}}
+ for (Iter0 I = begin0; I < end0; ++I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute parallel for
+// Initializer is constructor without params.
+// expected-error@+2 {{invalid operands to binary expression ('Iter0' and 'int')}}
+// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (Iter0 I; I < end0; ++I)
+ ++I;
+ Iter1 begin1, end1;
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-error@+2 {{invalid operands to binary expression ('Iter1' and 'Iter1')}}
+// expected-error@+1 {{could not calculate number of iterations calling 'operator-' with upper and lower loop bounds}}
+ for (Iter1 I = begin1; I < end1; ++I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-note@+2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+1 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}}
+ for (Iter1 I = begin1; I >= end1; ++I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-error@+4 {{invalid operands to binary expression ('Iter1' and 'float')}}
+// expected-error@+3 {{could not calculate number of iterations calling 'operator-' with upper and lower loop bounds}}
+// Initializer is constructor with all default params.
+// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (Iter1 I; I < end1; ++I) {
+ }
+ return 0;
+}
+
+template <typename IT, int ST>
+class TC {
+public:
+ int dotest_lt(IT begin, IT end) {
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'I' to increase on each iteration of OpenMP for loop}}
+ for (IT I = begin; I < end; I = I + ST) {
+ ++I;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'I' to increase on each iteration of OpenMP for loop}}
+ for (IT I = begin; I <= end; I += ST) {
+ ++I;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (IT I = begin; I < end; ++I) {
+ ++I;
+ }
+ }
+
+ static IT step() {
+ return IT(ST);
+ }
+};
+template <typename IT, int ST = 0>
+int dotest_gt(IT begin, IT end) {
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-note@+2 2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+1 2 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}}
+ for (IT I = begin; I >= end; I = I + ST) {
+ ++I;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-note@+2 2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+1 2 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}}
+ for (IT I = begin; I >= end; I += ST) {
+ ++I;
+ }
+
+#pragma omp target
+#pragma omp teams distribute parallel for
+// expected-note@+2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+1 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}}
+ for (IT I = begin; I >= end; ++I) {
+ ++I;
+ }
+
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (IT I = begin; I < end; I += TC<int, ST>::step()) {
+ ++I;
+ }
+}
+
+void test_with_template() {
+ GoodIter begin, end;
+ TC<GoodIter, 100> t1;
+ TC<GoodIter, -100> t2;
+ t1.dotest_lt(begin, end);
+ t2.dotest_lt(begin, end); // expected-note {{in instantiation of member function 'TC<GoodIter, -100>::dotest_lt' requested here}}
+ dotest_gt(begin, end); // expected-note {{in instantiation of function template specialization 'dotest_gt<GoodIter, 0>' requested here}}
+ dotest_gt<unsigned, -10>(0, 100); // expected-note {{in instantiation of function template specialization 'dotest_gt<unsigned int, -10>' requested here}}
+}
+
+void test_loop_break() {
+ const int N = 100;
+ float a[N], b[N], c[N];
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; i++) {
+ c[i] = a[i] + b[i];
+ for (int j = 0; j < 10; ++j) {
+ if (a[i] > b[j])
+ break; // OK in nested loop
+ }
+ switch (i) {
+ case 1:
+ b[i]++;
+ break;
+ default:
+ break;
+ }
+ if (c[i] > 10)
+ break; // expected-error {{'break' statement cannot be used in OpenMP for loop}}
+
+ if (c[i] > 11)
+ break; // expected-error {{'break' statement cannot be used in OpenMP for loop}}
+ }
+
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; i++) {
+ for (int j = 0; j < 10; j++) {
+ c[i] = a[i] + b[i];
+ if (c[i] > 10) {
+ if (c[i] < 20) {
+ break; // OK
+ }
+ }
+ }
+ }
+}
+
+void test_loop_eh() {
+ const int N = 100;
+ float a[N], b[N], c[N];
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; i++) {
+ c[i] = a[i] + b[i];
+ try { // OK
+ for (int j = 0; j < 10; ++j) {
+ if (a[i] > b[j])
+ throw a[i]; // OK
+ }
+ throw a[i]; // OK
+ } catch (float f) {
+ if (f > 0.1)
+ throw a[i]; // OK
+ return; // expected-error {{cannot return from OpenMP region}}
+ }
+ switch (i) {
+ case 1:
+ b[i]++;
+ break;
+ default:
+ break;
+ }
+ for (int j = 0; j < 10; j++) {
+ if (c[i] > 10)
+ throw c[i]; // OK
+ }
+ }
+ if (c[9] > 10)
+ throw c[9]; // OK
+
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < 10; ++i) {
+ struct S {
+ void g() { throw 0; }
+ };
+ }
+}
+
+void test_loop_firstprivate_lastprivate() {
+ S s(4);
+#pragma omp target
+#pragma omp teams distribute parallel for lastprivate(s) firstprivate(s)
+ for (int i = 0; i < 16; ++i)
+ ;
+}
+
+void test_ordered() {
+#pragma omp target
+#pragma omp teams distribute parallel for ordered // expected-error {{unexpected OpenMP clause 'ordered' in directive '#pragma omp teams distribute parallel for'}}
+ for (int i = 0; i < 16; ++i)
+ ;
+}
+
+void test_nowait() {
+#pragma omp target
+// expected-error@+1 2 {{unexpected OpenMP clause 'nowait' in directive '#pragma omp teams distribute parallel for'}}
+#pragma omp teams distribute parallel for nowait nowait // expected-error {{directive '#pragma omp teams distribute parallel for' cannot contain more than one 'nowait' clause}}
+ 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
new file mode 100644
index 000000000000..c3536cd86167
--- /dev/null
+++ b/test/OpenMP/teams_distribute_parallel_for_messages.cpp
@@ -0,0 +1,109 @@
+// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+
+void foo() {
+}
+
+static int pvt;
+#pragma omp threadprivate(pvt)
+
+#pragma omp teams distribute parallel for // expected-error {{unexpected OpenMP directive '#pragma omp teams distribute parallel for'}}
+
+int main(int argc, char **argv) {
+#pragma omp target
+#pragma omp teams distribute parallel for { // expected-warning {{extra tokens at the end of '#pragma omp teams distribute parallel for' are ignored}}
+ for (int i = 0; i < argc; ++i)
+ foo();
+#pragma omp target
+#pragma omp teams distribute parallel for ( // expected-warning {{extra tokens at the end of '#pragma omp teams distribute parallel for' are ignored}}
+ for (int i = 0; i < argc; ++i)
+ foo();
+#pragma omp target
+#pragma omp teams distribute parallel for[ // expected-warning {{extra tokens at the end of '#pragma omp teams distribute parallel for' are ignored}}
+ for (int i = 0; i < argc; ++i)
+ foo();
+#pragma omp target
+#pragma omp teams distribute parallel for] // expected-warning {{extra tokens at the end of '#pragma omp teams distribute parallel for' are ignored}}
+ for (int i = 0; i < argc; ++i)
+ foo();
+#pragma omp target
+#pragma omp teams distribute parallel for) // expected-warning {{extra tokens at the end of '#pragma omp teams distribute parallel for' are ignored}}
+ for (int i = 0; i < argc; ++i)
+ foo();
+#pragma omp target
+#pragma omp teams distribute parallel for } // expected-warning {{extra tokens at the end of '#pragma omp teams distribute parallel for' are ignored}}
+ for (int i = 0; i < argc; ++i)
+ foo();
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < argc; ++i)
+ foo();
+// expected-warning@+2 {{extra tokens at the end of '#pragma omp teams distribute parallel for' are ignored}}
+#pragma omp target
+#pragma omp teams distribute parallel for unknown()
+ for (int i = 0; i < argc; ++i)
+ foo();
+L1:
+ for (int i = 0; i < argc; ++i)
+ foo();
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < argc; ++i)
+ foo();
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < argc; ++i) {
+ goto L1; // expected-error {{use of undeclared label 'L1'}}
+ argc++;
+ }
+
+ for (int i = 0; i < 10; ++i) {
+ switch (argc) {
+ case (0):
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < argc; ++i) {
+ foo();
+ break; // expected-error {{'break' statement cannot be used in OpenMP for loop}}
+ continue;
+ }
+ default:
+ break;
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for default(none)
+ for (int i = 0; i < 10; ++i)
+ ++argc; // expected-error {{ariable 'argc' must have explicitly specified data sharing attributes}}
+
+ goto L2; // expected-error {{use of undeclared label 'L2'}}
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < argc; ++i)
+ L2:
+ foo();
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int i = 0; i < argc; ++i) {
+ return 1; // expected-error {{cannot return from OpenMP region}}
+ }
+
+ [[]] // expected-error {{an attribute list cannot appear here}}
+#pragma omp target
+#pragma omp teams distribute parallel for
+ for (int n = 0; n < 100; ++n) {
+ }
+
+#pragma omp target
+#pragma omp teams distribute parallel for copyin(pvt) // expected-error {{unexpected OpenMP clause 'copyin' in directive '#pragma omp teams distribute parallel for'}}
+ for (int n = 0; n < 100; ++n) {}
+
+ return 0;
+}
+
+void test_ordered() {
+#pragma omp target
+#pragma omp teams distribute parallel for ordered // expected-error {{unexpected OpenMP clause 'ordered' in directive '#pragma omp teams distribute parallel for'}}
+ for (int i = 0; i < 16; ++i)
+ ;
+}
+
diff --git a/test/OpenMP/teams_distribute_parallel_for_num_teams_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_num_teams_messages.cpp
new file mode 100644
index 000000000000..63bc91e8ec00
--- /dev/null
+++ b/test/OpenMP/teams_distribute_parallel_for_num_teams_messages.cpp
@@ -0,0 +1,111 @@
+// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 100 -o - %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note 2 {{declared here}}
+
+template <typename T, int C> // expected-note {{declared here}}
+T tmain(T argc) {
+ char **a;
+#pragma omp target
+#pragma omp teams distribute parallel for num_teams(C)
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for num_teams(T) // expected-error {{'T' does not refer to a value}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for num_teams // expected-error {{expected '(' after 'num_teams'}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for num_teams( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for num_teams() // expected-error {{expected expression}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for num_teams(argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for num_teams(argc)) // expected-warning {{extra tokens at the end of '#pragma omp teams distribute parallel for' are ignored}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for num_teams(argc > 0 ? a[1] : a[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for num_teams(argc + argc)
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for num_teams(argc), num_teams (argc+1) // expected-error {{directive '#pragma omp teams distribute parallel for' cannot contain more than one 'num_teams' clause}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for num_teams(S1) // expected-error {{'S1' does not refer to a value}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for num_teams(-2) // expected-error {{argument to 'num_teams' clause must be a strictly positive integer value}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for num_teams(-10u)
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for num_teams(3.14) // expected-error 2 {{expression must have integral or unscoped enumeration type, not 'double'}}
+ for (int i=0; i<100; i++) foo();
+
+ return 0;
+}
+
+int main(int argc, char **argv) {
+#pragma omp target
+#pragma omp teams distribute parallel for num_teams // expected-error {{expected '(' after 'num_teams'}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for num_teams ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for num_teams () // expected-error {{expected expression}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for num_teams (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for num_teams (argc)) // expected-warning {{extra tokens at the end of '#pragma omp teams distribute parallel for' are ignored}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for num_teams (argc > 0 ? argv[1] : argv[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for num_teams (argc + argc)
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for num_teams (argc), num_teams (argc+1) // expected-error {{directive '#pragma omp teams distribute parallel for' cannot contain more than one 'num_teams' clause}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for num_teams (S1) // expected-error {{'S1' does not refer to a value}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for num_teams (-2) // expected-error {{argument to 'num_teams' clause must be a strictly positive integer value}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for num_teams (-10u)
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for num_teams (3.14) // expected-error {{expression must have integral or unscoped enumeration type, not 'double'}}
+ for (int i=0; i<100; i++) foo();
+
+ return tmain<int, 10>(argc); // expected-note {{in instantiation of function template specialization 'tmain<int, 10>' requested here}}
+}
diff --git a/test/OpenMP/teams_distribute_parallel_for_private_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_private_messages.cpp
new file mode 100644
index 000000000000..6e72905d754a
--- /dev/null
+++ b/test/OpenMP/teams_distribute_parallel_for_private_messages.cpp
@@ -0,0 +1,146 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}} expected-note {{forward declaration of 'S1'}}
+extern S1 a;
+class S2 {
+ mutable int a;
+public:
+ S2():a(0) { }
+ static float S2s; // expected-note {{predetermined as shared}}
+};
+const S2 b;
+const S2 ba[5];
+class S3 {
+ int a;
+public:
+ S3():a(0) { }
+};
+const S3 c; // expected-note {{predetermined as shared}}
+const S3 ca[5]; // expected-note {{predetermined as shared}}
+extern const int f; // expected-note {{predetermined as shared}}
+class S4 {
+ int a;
+ S4(); // expected-note {{implicitly declared private here}}
+public:
+ S4(int v):a(v) { }
+};
+class S5 {
+ int a;
+ S5():a(0) {} // expected-note {{implicitly declared private here}}
+public:
+ S5(int v):a(v) { }
+};
+
+S3 h;
+#pragma omp threadprivate(h) // expected-note {{defined as threadprivate or thread local}}
+
+
+int main(int argc, char **argv) {
+ const int d = 5; // expected-note {{predetermined as shared}}
+ const int da[5] = { 0 }; // expected-note {{predetermined as shared}}
+ S4 e(4);
+ S5 g(5);
+ int i;
+ int &j = i;
+
+ #pragma omp target
+ #pragma omp teams distribute parallel for private // expected-error {{expected '(' after 'private'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute parallel for private ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute parallel for private () // expected-error {{expected expression}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute parallel for private (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute parallel for private (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute parallel for private (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute parallel for private (argc)
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute parallel for private (S1) // expected-error {{'S1' does not refer to a value}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute parallel for private (a, b, c, d, f) // expected-error {{private variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be private}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute parallel for private (argv[1]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute parallel for private(ba)
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute parallel for private(ca) // expected-error {{shared variable cannot be private}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute parallel for private(da) // expected-error {{shared variable cannot be private}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute parallel for private(S2::S2s) // expected-error {{shared variable cannot be private}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute parallel for private(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute parallel for private(h) // expected-error {{threadprivate or thread local variable cannot be private}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute parallel for shared(i)
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute parallel for firstprivate(i), private(i) // expected-error {{firstprivate variable cannot be private}} expected-note {{defined as firstprivate}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute parallel for private(j)
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute parallel for reduction(+:i)
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp distribute private(i)
+ for (int k = 0; k < 10; ++k) {
+ #pragma omp target
+ #pragma omp teams distribute parallel for private(i)
+ for (int x = 0; x < 10; ++x) foo();
+ }
+
+ #pragma omp target
+ #pragma omp teams distribute parallel for firstprivate(i)
+ for (int k = 0; k < 10; ++k) {
+ }
+
+ return 0;
+}
diff --git a/test/OpenMP/teams_distribute_parallel_for_proc_bind_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_proc_bind_messages.cpp
new file mode 100644
index 000000000000..2a7074a0bcd4
--- /dev/null
+++ b/test/OpenMP/teams_distribute_parallel_for_proc_bind_messages.cpp
@@ -0,0 +1,85 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo();
+
+template <class T, typename S, int N>
+T tmain(T argc, S **argv) {
+ T i;
+#pragma omp target
+#pragma omp teams distribute parallel for proc_bind // expected-error {{expected '(' after 'proc_bind'}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target
+#pragma omp teams distribute parallel for proc_bind( // expected-error {{expected 'master', 'close' or 'spread' in OpenMP clause 'proc_bind'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target
+#pragma omp teams distribute parallel for proc_bind() // expected-error {{expected 'master', 'close' or 'spread' in OpenMP clause 'proc_bind'}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target
+#pragma omp teams distribute parallel for proc_bind(master // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target
+#pragma omp teams distribute parallel for proc_bind(close), proc_bind(spread) // expected-error {{directive '#pragma omp teams distribute parallel for' cannot contain more than one 'proc_bind' clause}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target
+#pragma omp teams distribute parallel for proc_bind(x) // expected-error {{expected 'master', 'close' or 'spread' in OpenMP clause 'proc_bind'}}
+ for (i = 0; i < argc; ++i)
+ foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for proc_bind(master)
+ for (i = 0; i < argc; ++i)
+ foo();
+
+#pragma omp parallel proc_bind(close)
+#pragma omp target
+#pragma omp teams distribute parallel for proc_bind(spread)
+ for (i = 0; i < argc; ++i)
+ foo();
+
+ return T();
+}
+
+int main(int argc, char **argv) {
+ int i;
+#pragma omp target
+#pragma omp teams distribute parallel for proc_bind // expected-error {{expected '(' after 'proc_bind'}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target
+#pragma omp teams distribute parallel for proc_bind( // expected-error {{expected 'master', 'close' or 'spread' in OpenMP clause 'proc_bind'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target
+#pragma omp teams distribute parallel for proc_bind() // expected-error {{expected 'master', 'close' or 'spread' in OpenMP clause 'proc_bind'}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target
+#pragma omp teams distribute parallel for proc_bind(master // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target
+#pragma omp teams distribute parallel for proc_bind(close), proc_bind(spread) // expected-error {{directive '#pragma omp teams distribute parallel for' cannot contain more than one 'proc_bind' clause}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target
+#pragma omp teams distribute parallel for proc_bind(x) // expected-error {{expected 'master', 'close' or 'spread' in OpenMP clause 'proc_bind'}}
+ for (i = 0; i < argc; ++i)
+ foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for proc_bind(master)
+ for (i = 0; i < argc; ++i)
+ foo();
+
+#pragma omp parallel proc_bind(close)
+#pragma omp target
+#pragma omp teams distribute parallel for proc_bind(spread)
+ for (i = 0; i < argc; ++i)
+ foo();
+ return tmain<int, char, 3>(argc, argv);
+}
diff --git a/test/OpenMP/teams_distribute_parallel_for_reduction_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_reduction_messages.cpp
new file mode 100644
index 000000000000..73661618d20c
--- /dev/null
+++ b/test/OpenMP/teams_distribute_parallel_for_reduction_messages.cpp
@@ -0,0 +1,303 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}} expected-note 4 {{forward declaration of 'S1'}}
+extern S1 a;
+class S2 {
+ mutable int a;
+ S2 &operator+(const S2 &arg) { return (*this); } // expected-note 3 {{implicitly declared private here}}
+
+public:
+ S2() : a(0) {}
+ S2(S2 &s2) : a(s2.a) {}
+ static float S2s; // expected-note 2 {{static data member is predetermined as shared}}
+ static const float S2sc;
+};
+const float S2::S2sc = 0; // expected-note 2 {{'S2sc' defined here}}
+S2 b; // expected-note 3 {{'b' defined here}}
+const S2 ba[5]; // expected-note 2 {{'ba' defined here}}
+class S3 {
+ int a;
+
+public:
+ int b;
+ S3() : a(0) {}
+ S3(const S3 &s3) : a(s3.a) {}
+ S3 operator+(const S3 &arg1) { return arg1; }
+};
+int operator+(const S3 &arg1, const S3 &arg2) { return 5; }
+S3 c; // expected-note 3 {{'c' defined here}}
+const S3 ca[5]; // expected-note 2 {{'ca' defined here}}
+extern const int f; // expected-note 4 {{'f' declared here}}
+class S4 {
+ int a;
+ S4(); // expected-note {{implicitly declared private here}}
+ S4(const S4 &s4);
+ S4 &operator+(const S4 &arg) { return (*this); }
+
+public:
+ S4(int v) : a(v) {}
+};
+S4 &operator&=(S4 &arg1, S4 &arg2) { return arg1; }
+class S5 {
+ int a;
+ S5() : a(0) {} // expected-note {{implicitly declared private here}}
+ S5(const S5 &s5) : a(s5.a) {}
+ S5 &operator+(const S5 &arg);
+
+public:
+ S5(int v) : a(v) {}
+};
+class S6 { // expected-note 3 {{candidate function (the implicit copy assignment operator) not viable: no known conversion from 'int' to 'const S6' for 1st argument}}
+#if __cplusplus >= 201103L // C++11 or later
+// expected-note@-2 3 {{candidate function (the implicit move assignment operator) not viable}}
+#endif
+ int a;
+
+public:
+ S6() : a(6) {}
+ operator int() { return 6; }
+} o;
+
+S3 h, k;
+#pragma omp threadprivate(h) // expected-note 2 {{defined as threadprivate or thread local}}
+
+template <class T> // expected-note {{declared here}}
+T tmain(T argc) {
+ const T d = T(); // expected-note 4 {{'d' defined here}}
+ const T da[5] = {T()}; // expected-note 2 {{'da' defined here}}
+ T qa[5] = {T()};
+ T i;
+ T &j = i; // expected-note 4 {{'j' defined here}}
+ S3 &p = k; // expected-note 2 {{'p' defined here}}
+ const T &r = da[(int)i]; // expected-note 2 {{'r' defined here}}
+ T &q = qa[(int)i]; // expected-note 2 {{'q' defined here}}
+ T fl;
+#pragma omp target
+#pragma omp teams distribute parallel for reduction // expected-error {{expected '(' after 'reduction'}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction + // expected-error {{expected '(' after 'reduction'}} expected-warning {{extra tokens at the end of '#pragma omp teams distribute parallel for' are ignored}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction( // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(- // expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction() // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(*) // expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected expression}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(\) // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(& : argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{invalid operands to binary expression ('float' and 'float')}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(| : argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{invalid operands to binary expression ('float' and 'float')}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(|| : argc ? i : argc) // expected-error 2 {{expected variable name, array element or array section}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(foo : argc) //expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'float'}} expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'int'}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(&& : argc)
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(^ : T) // expected-error {{'T' does not refer to a value}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}} expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(+ : o) // expected-error 2 {{no viable overloaded '='}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for private(i), reduction(+ : j), reduction(+ : q) // expected-error 4 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp parallel private(k)
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(+ : p), reduction(+ : p) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(+ : p), reduction(+ : p) // expected-error 2 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 2 {{previously referenced here}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp parallel shared(i)
+#pragma omp parallel reduction(min : i)
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(max : j) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(+ : fl)
+ for (int j=0; j<100; j++) foo();
+
+ return T();
+}
+
+namespace A {
+double x;
+#pragma omp threadprivate(x) // expected-note {{defined as threadprivate or thread local}}
+}
+namespace B {
+using A::x;
+}
+
+int main(int argc, char **argv) {
+ const int d = 5; // expected-note 2 {{'d' defined here}}
+ const int da[5] = {0}; // expected-note {{'da' defined here}}
+ int qa[5] = {0};
+ S4 e(4);
+ S5 g(5);
+ int i;
+ int &j = i; // expected-note 2 {{'j' defined here}}
+ S3 &p = k; // expected-note 2 {{'p' defined here}}
+ const int &r = da[i]; // expected-note {{'r' defined here}}
+ int &q = qa[i]; // expected-note {{'q' defined here}}
+ float fl;
+#pragma omp target
+#pragma omp teams distribute parallel for reduction // expected-error {{expected '(' after 'reduction'}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction + // expected-error {{expected '(' after 'reduction'}} expected-warning {{extra tokens at the end of '#pragma omp teams distribute parallel for' are ignored}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction( // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(- // expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction() // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(*) // expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected expression}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(\) // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(foo : argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max'}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(| : argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(|| : argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name, array element or array section}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(~ : argc) // expected-error {{expected unqualified-id}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(&& : argc)
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(^ : S1) // expected-error {{'S1' does not refer to a value}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified list item cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(& : e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{invalid operands to binary expression ('S4' and 'S4')}} expected-error {{calling a private constructor of class 'S5'}} expected-error {{invalid operands to binary expression ('S5' and 'S5')}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(+ : h, k, B::x) // expected-error 2 {{threadprivate or thread local variable cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(+ : o) // expected-error {{no viable overloaded '='}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for private(i), reduction(+ : j), reduction(+ : q) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp parallel private(k)
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(+ : p), reduction(+ : p) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(+ : p), reduction(+ : p) // expected-error {{variable can appear only once in OpenMP 'reduction' clause}} expected-note {{previously referenced here}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(+ : r) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp parallel shared(i)
+#pragma omp parallel reduction(min : i)
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(max : j) // expected-error {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(+ : fl)
+ for (int j=0; j<100; j++) foo();
+ static int m;
+#pragma omp target
+#pragma omp teams distribute parallel for reduction(+ : m) // OK
+ for (int j=0; j<100; j++) foo();
+
+ return tmain(argc) + tmain(fl); // expected-note {{in instantiation of function template specialization 'tmain<int>' requested here}} expected-note {{in instantiation of function template specialization 'tmain<float>' requested here}}
+}
diff --git a/test/OpenMP/teams_distribute_parallel_for_schedule_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_schedule_messages.cpp
new file mode 100644
index 000000000000..477d1a0f7d34
--- /dev/null
+++ b/test/OpenMP/teams_distribute_parallel_for_schedule_messages.cpp
@@ -0,0 +1,172 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}}
+
+template <class T, typename S, int N, int ST> // expected-note {{declared here}}
+T tmain(T argc, S **argv) {
+// expected-error@+2 {{expected '(' after 'schedule'}}
+#pragma omp target
+#pragma omp teams distribute parallel for schedule
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+// expected-error@+2 {{expected 'static', 'dynamic', 'guided', 'auto', 'runtime', 'monotonic', 'nonmonotonic' or 'simd' in OpenMP clause 'schedule'}} expected-error@+2 {{expected ')'}} expected-note@+2 {{to match this '('}}
+#pragma omp target
+#pragma omp teams distribute parallel for schedule (
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+// expected-error@+2 {{expected 'static', 'dynamic', 'guided', 'auto', 'runtime', 'monotonic', 'nonmonotonic' or 'simd' in OpenMP clause 'schedule'}}
+#pragma omp target
+#pragma omp teams distribute parallel for schedule ()
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+// expected-error@+2 {{expected ')'}} expected-note@+2 {{to match this '('}}
+#pragma omp target
+#pragma omp teams distribute parallel for schedule (auto
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+// expected-error@+2 {{expected 'static', 'dynamic', 'guided', 'auto', 'runtime', 'monotonic', 'nonmonotonic' or 'simd' in OpenMP clause 'schedule'}} expected-error@+2 {{expected ')'}} expected-note@+2 {{to match this '('}}
+#pragma omp target
+#pragma omp teams distribute parallel for schedule (auto_dynamic
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+// expected-error@+2 {{expected ')'}} expected-note@+2 {{to match this '('}}
+#pragma omp target
+#pragma omp teams distribute parallel for schedule (auto,
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+// expected-error@+2 {{expected ')'}} expected-note@+2 {{to match this '('}}
+#pragma omp target
+#pragma omp teams distribute parallel for schedule (runtime, 3)
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+// expected-error@+2 {{expected ')'}} expected-note@+2 {{to match this '('}}
+#pragma omp target
+#pragma omp teams distribute parallel for schedule (guided argc
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+// expected-error@+2 2 {{argument to 'schedule' clause must be a strictly positive integer value}}
+#pragma omp target
+#pragma omp teams distribute parallel for schedule (static, ST // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+// expected-warning@+2 {{extra tokens at the end of '#pragma omp teams distribute parallel for' are ignored}}
+#pragma omp target
+#pragma omp teams distribute parallel for schedule (dynamic, 1))
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute parallel for schedule (guided, (ST > 0) ? 1 + ST : 2)
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+// expected-error@+3 2 {{directive '#pragma omp teams distribute parallel for' cannot contain more than one 'schedule' clause}}
+// expected-error@+2 {{argument to 'schedule' clause must be a strictly positive integer value}}
+#pragma omp target
+#pragma omp teams distribute parallel for schedule (static, foobool(argc)), schedule (dynamic, true), schedule (guided, -5)
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+// expected-error@+2 {{'S' does not refer to a value}}
+#pragma omp target
+#pragma omp teams distribute parallel for schedule (static, S)
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+// expected-error@+3 2 {{expression must have integral or unscoped enumeration type, not 'char *'}}
+// expected-error@+2 {{expected ')'}} expected-note@+2 {{to match this '('}}
+#pragma omp target
+#pragma omp teams distribute parallel for schedule (guided, argv[1]=2)
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute parallel for schedule (dynamic, 1)
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+// expected-error@+2 {{argument to 'schedule' clause must be a strictly positive integer value}}
+#pragma omp target
+#pragma omp teams distribute parallel for schedule (static, N)
+ for (T i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+ return argc;
+}
+
+int main(int argc, char **argv) {
+// expected-error@+2 {{expected '(' after 'schedule'}}
+#pragma omp target
+#pragma omp teams distribute parallel for schedule
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+
+// expected-error@+2 {{expected 'static', 'dynamic', 'guided', 'auto', 'runtime', 'monotonic', 'nonmonotonic' or 'simd' in OpenMP clause 'schedule'}} expected-error@+2 {{expected ')'}} expected-note@+2 {{to match this '('}}
+#pragma omp target
+#pragma omp teams distribute parallel for schedule (
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+
+// expected-error@+2 {{expected 'static', 'dynamic', 'guided', 'auto', 'runtime', 'monotonic', 'nonmonotonic' or 'simd' in OpenMP clause 'schedule'}}
+#pragma omp target
+#pragma omp teams distribute parallel for schedule ()
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+
+// expected-error@+2 {{expected ')'}} expected-note@+2 {{to match this '('}}
+#pragma omp target
+#pragma omp teams distribute parallel for schedule (auto
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+
+// expected-error@+2 {{expected 'static', 'dynamic', 'guided', 'auto', 'runtime', 'monotonic', 'nonmonotonic' or 'simd' in OpenMP clause 'schedule'}} expected-error@+2 {{expected ')'}} expected-note@+2 {{to match this '('}}
+#pragma omp target
+#pragma omp teams distribute parallel for schedule (auto_dynamic
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+
+// expected-error@+2 {{expected ')'}} expected-note@+2 {{to match this '('}}
+#pragma omp target
+#pragma omp teams distribute parallel for schedule (auto,
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+
+// expected-error@+2 {{expected ')'}} expected-note@+2 {{to match this '('}}
+#pragma omp target
+#pragma omp teams distribute parallel for schedule (runtime, 3)
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+
+// expected-error@+2 {{expected ')'}} expected-note@+2 {{to match this '('}}
+#pragma omp target
+#pragma omp teams distribute parallel for schedule (guided, 4
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+
+// expected-warning@+2 {{extra tokens at the end of '#pragma omp teams distribute parallel for' are ignored}}
+#pragma omp target
+#pragma omp teams distribute parallel for schedule (static, 2+2))
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target
+#pragma omp teams distribute parallel for schedule (dynamic, foobool(1) > 0 ? 1 : 2)
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+
+// expected-error@+3 2 {{directive '#pragma omp teams distribute parallel for' cannot contain more than one 'schedule' clause}}
+// expected-error@+2 {{argument to 'schedule' clause must be a strictly positive integer value}}
+#pragma omp target
+#pragma omp teams distribute parallel for schedule (guided, foobool(argc)), schedule (static, true), schedule (dynamic, -5)
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+
+// expected-error@+2 {{'S1' does not refer to a value}}
+#pragma omp target
+#pragma omp teams distribute parallel for schedule (guided, S1)
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+
+// expected-error@+3 {{expected ')'}} expected-note@+3 {{to match this '('}}
+// expected-error@+2 {{expression must have integral or unscoped enumeration type, not 'char *'}}
+#pragma omp target
+#pragma omp teams distribute parallel for schedule (static, argv[1]=2)
+ for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+
+// expected-error@+4 {{statement after '#pragma omp teams distribute parallel for' must be a for loop}}
+// expected-note@+2 {{in instantiation of function template specialization 'tmain<int, char, -1, -2>' requested here}}
+#pragma omp target
+#pragma omp teams distribute parallel for schedule(dynamic, schedule(tmain<int, char, -1, -2>(argc, argv) // expected-error 2 {{expected ')'}} expected-note 2 {{to match this '('}}
+ foo();
+
+ // expected-note@+1 {{in instantiation of function template specialization 'tmain<int, char, 1, 0>' requested here}}
+ return tmain<int, char, 1, 0>(argc, argv);
+}
diff --git a/test/OpenMP/teams_distribute_parallel_for_shared_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_shared_messages.cpp
new file mode 100644
index 000000000000..8edcd3664341
--- /dev/null
+++ b/test/OpenMP/teams_distribute_parallel_for_shared_messages.cpp
@@ -0,0 +1,127 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}}
+extern S1 a;
+class S2 {
+ mutable int a;
+public:
+ S2():a(0) { }
+ S2(S2 &s2):a(s2.a) { }
+};
+const S2 b;
+const S2 ba[5];
+class S3 {
+ int a;
+public:
+ S3():a(0) { }
+ S3(S3 &s3):a(s3.a) { }
+};
+const S3 c;
+const S3 ca[5];
+extern const int f;
+class S4 {
+ int a;
+ S4();
+ S4(const S4 &s4);
+public:
+ S4(int v):a(v) { }
+};
+class S5 {
+ int a;
+ S5():a(0) {}
+ S5(const S5 &s5):a(s5.a) { }
+public:
+ S5(int v):a(v) { }
+};
+
+S3 h;
+#pragma omp threadprivate(h) // expected-note {{defined as threadprivate or thread local}}
+
+namespace A {
+double x;
+#pragma omp threadprivate(x) // expected-note {{defined as threadprivate or thread local}}
+}
+namespace B {
+using A::x;
+}
+
+int main(int argc, char **argv) {
+ const int d = 5;
+ const int da[5] = { 0 };
+ S4 e(4);
+ S5 g(5);
+ int i;
+ int &j = i;
+ #pragma omp target
+ #pragma omp teams distribute parallel for shared // expected-error {{expected '(' after 'shared'}}
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for shared ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for shared () // expected-error {{expected expression}}
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for shared (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for shared (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for shared (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for shared (argc)
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for shared (S1) // expected-error {{'S1' does not refer to a value}}
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for shared (a, b, c, d, f)
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for shared (argv[1]) // expected-error {{expected variable name}}
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for shared(ba)
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for shared(ca)
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for shared(da)
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for shared(e, g)
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for shared(h, B::x) // expected-error 2 {{threadprivate or thread local variable cannot be shared}}
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for private(i), shared(i) // expected-error {{private variable cannot be shared}} expected-note {{defined as private}}
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for firstprivate(i), shared(i) // expected-error {{firstprivate variable cannot be shared}} expected-note {{defined as firstprivate}}
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for private(i)
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for shared(i)
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for shared(j)
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for firstprivate(i)
+ for (int j=0; j<100; j++) foo();
+
+ return 0;
+}
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_aligned_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_aligned_messages.cpp
new file mode 100644
index 000000000000..674057712ecf
--- /dev/null
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_aligned_messages.cpp
@@ -0,0 +1,271 @@
+// RUN: %clang_cc1 -x c++ -std=c++11 -verify -fopenmp %s
+
+struct B {
+ static int ib[20]; // expected-note 0 {{'B::ib' declared here}}
+ static constexpr int bfoo() { return 8; }
+};
+namespace X {
+ B x; // expected-note {{'x' defined here}}
+};
+constexpr int bfoo() { return 4; }
+
+int **z;
+const int C1 = 1;
+const int C2 = 2;
+void test_aligned_colons(int *&rp)
+{
+ int *B = 0;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd aligned(B:bfoo())
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd aligned(B::ib:B:bfoo()) // expected-error {{unexpected ':' in nested name specifier; did you mean '::'}}
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd aligned(B:B::bfoo())
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd aligned(z:B:bfoo()) // expected-error {{unexpected ':' in nested name specifier; did you mean '::'?}}
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd aligned(B:B::bfoo())
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd aligned(X::x : ::z) // expected-error {{integral constant expression must have integral or unscoped enumeration type, not 'int **'}} expected-error {{argument of aligned clause should be array, pointer, reference to array or reference to pointer, not 'B'}}
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd aligned(B,rp,::z: X::x) // expected-error {{integral constant expression must have integral or unscoped enumeration type, not 'B'}}
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd aligned(::z)
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd aligned(B::bfoo()) // expected-error {{expected variable name}}
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd aligned(B::ib,B:C1+C2) // expected-warning {{aligned clause will be ignored because the requested alignment is not a power of 2}}
+ for (int i = 0; i < 10; ++i) ;
+}
+
+// expected-note@+1 {{'num' defined here}}
+template<int L, class T, class N> T test_template(T* arr, N num) {
+ N i;
+ T sum = (T)0;
+ T ind2 = - num * L;
+ // Negative number is passed as L.
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd aligned(arr:L) // expected-error {{argument to 'aligned' clause must be a strictly positive integer value}}
+ for (i = 0; i < num; ++i) {
+ T cur = arr[(int)ind2];
+ ind2 += L;
+ sum += cur;
+ }
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd aligned(num:4) // expected-error {{argument of aligned clause should be array, pointer, reference to array or reference to pointer, not 'int'}}
+ for (i = 0; i < num; ++i);
+
+ return T();
+}
+
+template<int LEN> int test_warn() {
+ int *ind2 = 0;
+#pragma omp target
+#pragma omp teams distribute parallel for simd aligned(ind2:LEN) // expected-error {{argument to 'aligned' clause must be a strictly positive integer value}}
+ for (int i = 0; i < 100; i++) {
+ ind2 += LEN;
+ }
+ return 0;
+}
+
+struct S1; // expected-note 2 {{declared here}}
+extern S1 a; // expected-note {{'a' declared here}}
+class S2 {
+ mutable int a;
+public:
+ S2():a(0) { }
+};
+const S2 b; // expected-note 1 {{'b' defined here}}
+const S2 ba[5];
+class S3 {
+ int a;
+public:
+ S3():a(0) { }
+};
+const S3 ca[5];
+class S4 {
+ int a;
+ S4();
+public:
+ S4(int v):a(v) { }
+};
+class S5 {
+ int a;
+ S5():a(0) {}
+public:
+ S5(int v):a(v) { }
+};
+
+S3 h; // expected-note 2 {{'h' defined here}}
+#pragma omp threadprivate(h)
+
+template<class I, class C> int foomain(I argc, C **argv) {
+ I e(argc);
+ I g(argc);
+ int i; // expected-note {{declared here}} expected-note {{'i' defined here}}
+ // expected-note@+2 {{declared here}}
+ // expected-note@+1 {{reference to 'i' is not a constant expression}}
+ int &j = i;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd aligned // expected-error {{expected '(' after 'aligned'}}
+ for (I k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd aligned ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (I k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd aligned () // expected-error {{expected expression}}
+ for (I k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd aligned (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (I k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd aligned (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (I k = 0; k < argc; ++k) ++k;
+
+// FIXME: Should argc really be a pointer?
+#pragma omp target
+#pragma omp teams distribute parallel for simd aligned (*argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (I k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd aligned (argc : 5) // expected-warning {{aligned clause will be ignored because the requested alignment is not a power of 2}}
+ for (I k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd aligned (S1) // expected-error {{'S1' does not refer to a value}}
+ for (I k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd aligned (argv[1]) // expected-error {{expected variable name}}
+ for (I k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd aligned(e, g)
+ for (I k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd aligned(h) // expected-error {{argument of aligned clause should be array, pointer, reference to array or reference to pointer, not 'S3'}}
+ for (I k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd aligned(i) // expected-error {{argument of aligned clause should be array, pointer, reference to array or reference to pointer, not 'int'}}
+ for (I k = 0; k < argc; ++k) ++k;
+
+ #pragma omp parallel
+ {
+ int *v = 0;
+ I i;
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd aligned(v:16)
+ for (I k = 0; k < argc; ++k) { i = k; v += 2; }
+ }
+ float *f;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd aligned(f)
+ for (I k = 0; k < argc; ++k) ++k;
+
+ int v = 0;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd aligned(f:j) // expected-note {{initializer of 'j' is not a constant expression}} expected-error {{expression is not an integral constant expression}}
+
+ for (I k = 0; k < argc; ++k) { ++k; v += j; }
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd aligned(f)
+ for (I k = 0; k < argc; ++k) ++k;
+
+ return 0;
+}
+
+// expected-note@+1 2 {{'argc' defined here}}
+int main(int argc, char **argv) {
+ double darr[100];
+ // expected-note@+1 {{in instantiation of function template specialization 'test_template<-4, double, int>' requested here}}
+ test_template<-4>(darr, 4);
+ test_warn<4>(); // ok
+ // expected-note@+1 {{in instantiation of function template specialization 'test_warn<0>' requested here}}
+ test_warn<0>();
+
+ int i;
+ int &j = i;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd aligned // expected-error {{expected '(' after 'aligned'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd aligned ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd aligned () // expected-error {{expected expression}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd aligned (argv // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd aligned (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{argument of aligned clause should be array, pointer, reference to array or reference to pointer, not 'int'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute simd aligned (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute simd aligned (argc) // expected-error {{argument of aligned clause should be array, pointer, reference to array or reference to pointer, not 'int'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd aligned (S1) // expected-error {{'S1' does not refer to a value}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd aligned (a, b) // expected-error {{argument of aligned clause should be array, pointer, reference to array or reference to pointer, not 'S1'}} expected-error {{argument of aligned clause should be array, pointer, reference to array or reference to pointer, not 'S2'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd aligned (argv[1]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd aligned(h) // expected-error {{argument of aligned clause should be array, pointer, reference to array or reference to pointer, not 'S3'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ int *pargc = &argc;
+ // expected-note@+1 {{in instantiation of function template specialization 'foomain<int *, char>' requested here}}
+ foomain<int*,char>(pargc,argv);
+ return 0;
+}
+
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_ast_print.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_ast_print.cpp
new file mode 100644
index 000000000000..26cc15822943
--- /dev/null
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_ast_print.cpp
@@ -0,0 +1,245 @@
+// 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
+// expected-no-diagnostics
+
+#ifndef HEADER
+#define HEADER
+
+void foo() {}
+
+struct S {
+ S(): a(0) {}
+ S(int v) : a(v) {}
+ int a;
+ typedef int type;
+};
+
+template <typename T>
+class S7 : public T {
+protected:
+ T a;
+ S7() : a(0) {}
+
+public:
+ S7(typename T::type v) : a(v) {
+#pragma omp target
+#pragma omp teams distribute parallel for simd private(a) private(this->a) private(T::a)
+ for (int k = 0; k < a.a; ++k)
+ ++this->a.a;
+ }
+ S7 &operator=(S7 &s) {
+#pragma omp target
+#pragma omp teams distribute parallel for simd private(a) private(this->a)
+ for (int k = 0; k < s.a.a; ++k)
+ ++s.a.a;
+
+ foo();
+ bar();
+ return *this;
+ }
+ void foo() {
+ int b, argv, d, c, e, f;
+#pragma omp target
+#pragma omp teams distribute parallel for simd default(none), private(b) firstprivate(argv) shared(d) reduction(+:c) reduction(max:e) num_teams(f) thread_limit(d)
+ for (int k = 0; k < a.a; ++k)
+ ++a.a;
+ }
+ void bar() {
+ int arr[10];
+ const int alen = 16;
+ const int slen1 = 8;
+ const int slen2 = 8;
+#pragma omp target
+#pragma omp teams distribute parallel for simd simdlen(slen1) safelen(slen2) aligned(arr:alen)
+ for (int k = 0; k < a.a; ++k)
+ ++a.a;
+ }
+};
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute parallel for simd private(this->a) private(this->a) private(T::a)
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute parallel for simd private(this->a) private(this->a)
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute parallel for simd default(none) private(b) firstprivate(argv) shared(d) reduction(+: c) reduction(max: e) num_teams(f) thread_limit(d)
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute parallel for simd simdlen(slen1) safelen(slen2) aligned(arr: alen)
+
+class S8 : public S7<S> {
+ S8() {}
+
+public:
+ S8(int v) : S7<S>(v){
+#pragma omp target
+#pragma omp teams distribute parallel for simd private(a) private(this->a) private(S7<S>::a)
+ for (int k = 0; k < a.a; ++k)
+ ++this->a.a;
+ }
+ S8 &operator=(S8 &s) {
+#pragma omp target
+#pragma omp teams distribute parallel for simd private(a) private(this->a)
+ for (int k = 0; k < s.a.a; ++k)
+ ++s.a.a;
+
+ foo();
+ bar();
+ return *this;
+ }
+ void bar() {
+ int b, argv, d, c, e, f8;
+#pragma omp target
+#pragma omp teams distribute parallel for simd default(none), private(b) firstprivate(argv) shared(d) reduction(+:c) reduction(max:e) num_teams(f8) thread_limit(d)
+ for (int k = 0; k < a.a; ++k)
+ ++a.a;
+ }
+ void foo() {
+ const int alen = 16;
+ const int slen1 = 8;
+ const int slen2 = 8;
+ int arr[10];
+#pragma omp target
+#pragma omp teams distribute parallel for simd simdlen(slen1) safelen(slen2) aligned(arr:alen)
+ for (int k = 0; k < a.a; ++k)
+ ++a.a;
+ }
+};
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute parallel for simd private(this->a) private(this->a) private(this->S::a)
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute parallel for simd private(this->a) private(this->a) private(this->S7<S>::a)
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute parallel for simd private(this->a) private(this->a)
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute parallel for simd default(none) private(b) firstprivate(argv) shared(d) reduction(+: c) reduction(max: e) num_teams(f8) thread_limit(d)
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute parallel for simd simdlen(slen1) safelen(slen2) aligned(arr: alen)
+
+template <class T, int N>
+T tmain(T argc) {
+ T b = argc, c, d, e, f, g;
+ static T a;
+// CHECK: static T a;
+ const T clen = 5;
+ const T alen = 16;
+ int arr[10];
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i=0; i < 2; ++i)
+ a = 2;
+// CHECK: #pragma omp target
+// 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
+#pragma omp teams distribute parallel for simd private(argc, b), firstprivate(c, d), collapse(2)
+ for (int i = 0; i < 10; ++i)
+ for (int j = 0; j < 10; ++j)
+ foo();
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute parallel for simd private(argc,b) firstprivate(c,d) collapse(2)
+// CHECK-NEXT: for (int i = 0; i < 10; ++i)
+// CHECK-NEXT: for (int j = 0; j < 10; ++j)
+// CHECK-NEXT: foo();
+ for (int i = 0; i < 10; ++i)
+ foo();
+// CHECK: for (int i = 0; i < 10; ++i)
+// CHECK-NEXT: foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i)
+ foo();
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute parallel for simd
+// CHECK-NEXT: for (int i = 0; i < 10; ++i)
+// CHECK-NEXT: foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd default(none), private(b) firstprivate(argc) shared(d) reduction(+:c) reduction(max:e) num_teams(f) thread_limit(d)
+ for (int k = 0; k < 10; ++k)
+ e += d + argc;
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute parallel for simd default(none) private(b) firstprivate(argc) shared(d) reduction(+: c) reduction(max: e) num_teams(f) thread_limit(d)
+// CHECK-NEXT: for (int k = 0; k < 10; ++k)
+// CHECK-NEXT: e += d + argc;
+#pragma omp target
+#pragma omp teams distribute parallel for simd simdlen(clen-1) linear(d)
+ for (int k = 0; k < 10; ++k)
+ e += d + argc;
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute parallel for simd simdlen(clen - 1) linear(d)
+// CHECK-NEXT: for (int k = 0; k < 10; ++k)
+// CHECK-NEXT: e += d + argc;
+#pragma omp target
+#pragma omp teams distribute parallel for simd safelen(clen-1) aligned(arr:alen)
+ for (int k = 0; k < 10; ++k)
+ e += d + argc + arr[k];
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute parallel for simd safelen(clen - 1) aligned(arr: alen)
+// CHECK-NEXT: for (int k = 0; k < 10; ++k)
+// CHECK-NEXT: e += d + argc + arr[k];
+ return T();
+}
+
+int main (int argc, char **argv) {
+ int b = argc, c, d, e, f, g;
+ static int a;
+// CHECK: static int a;
+ const int clen = 5;
+ const int N = 10;
+ int arr[10];
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i=0; i < 2; ++i)
+ a = 2;
+// CHECK: #pragma omp target
+// 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
+#pragma omp teams distribute parallel for simd private(argc,b),firstprivate(argv, c), collapse(2)
+ for (int i = 0; i < 10; ++i)
+ for (int j = 0; j < 10; ++j)
+ foo();
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute parallel for simd private(argc,b) firstprivate(argv,c) collapse(2)
+// CHECK-NEXT: for (int i = 0; i < 10; ++i)
+// CHECK-NEXT: for (int j = 0; j < 10; ++j)
+// CHECK-NEXT: foo();
+ for (int i = 0; i < 10; ++i)
+ foo();
+// CHECK: for (int i = 0; i < 10; ++i)
+// CHECK-NEXT: foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i)foo();
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute parallel for simd
+// CHECK-NEXT: for (int i = 0; i < 10; ++i)
+// CHECK-NEXT: foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd default(none), private(b) firstprivate(argc) shared(d) reduction(+:c) reduction(max:e) num_teams(f) thread_limit(d)
+ for (int k = 0; k < 10; ++k)
+ e += d + argc;
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute parallel for simd default(none) private(b) firstprivate(argc) shared(d) reduction(+: c) reduction(max: e) num_teams(f) thread_limit(d)
+// CHECK-NEXT: for (int k = 0; k < 10; ++k)
+// CHECK-NEXT: e += d + argc;
+#pragma omp target
+#pragma omp teams distribute parallel for simd simdlen(clen-1) linear(d)
+ for (int k = 0; k < 10; ++k)
+ e += d + argc;
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute parallel for simd simdlen(clen - 1) linear(d)
+// CHECK-NEXT: for (int k = 0; k < 10; ++k)
+// CHECK-NEXT: e += d + argc;
+#pragma omp target
+#pragma omp teams distribute parallel for simd safelen(clen-1) aligned(arr:N+6)
+ for (int k = 0; k < 10; ++k)
+ e += d + argc + arr[k];
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute parallel for simd safelen(clen - 1) aligned(arr: N + 6)
+// CHECK-NEXT: for (int k = 0; k < 10; ++k)
+// CHECK-NEXT: e += d + argc + arr[k];
+ return (0);
+}
+
+#endif
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_collapse_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_collapse_messages.cpp
new file mode 100644
index 000000000000..197c5f1ad341
--- /dev/null
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_collapse_messages.cpp
@@ -0,0 +1,172 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp %s -std=c++98
+// RUN: %clang_cc1 -verify -fopenmp %s -std=c++11
+
+void foo() {
+}
+
+#if __cplusplus >= 201103L
+// expected-note@+2 4 {{declared here}}
+#endif
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}}
+
+template <class T, typename S, int N, int ST> // expected-note {{declared here}}
+T tmain(T argc, S **argv) { //expected-note 2 {{declared here}}
+#pragma omp target
+#pragma omp teams distribute parallel for simd collapse // expected-error {{expected '(' after 'collapse'}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd collapse ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd collapse () // expected-error {{expected expression}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+// expected-error@+4 {{expected ')'}} expected-note@+4 {{to match this '('}}
+// expected-error@+3 2 {{expression is not an integral constant expression}}
+// expected-note@+2 2 {{read of non-const variable 'argc' is not allowed in a constant expression}}
+#pragma omp target
+#pragma omp teams distribute parallel for simd collapse (argc
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+// expected-error@+2 2 {{argument to 'collapse' clause must be a strictly positive integer value}}
+#pragma omp target
+#pragma omp teams distribute parallel for simd collapse (ST // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd collapse (1)) // expected-warning {{extra tokens at the end of '#pragma omp teams distribute parallel for simd' are ignored}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd collapse ((ST > 0) ? 1 + ST : 2) // expected-note 2 {{as specified in 'collapse' clause}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST]; // expected-error 2 {{expected 2 for loops after '#pragma omp teams distribute parallel for simd', but found only 1}}
+
+#if __cplusplus >= 201103L
+// expected-note@+6 2 {{non-constexpr function 'foobool' cannot be used}}
+#endif
+// expected-error@+4 2 {{directive '#pragma omp teams distribute parallel for simd' cannot contain more than one 'collapse' clause}}
+// expected-error@+3 2 {{argument to 'collapse' clause must be a strictly positive integer value}}
+// expected-error@+2 2 {{expression is not an integral constant expression}}
+#pragma omp target
+#pragma omp teams distribute parallel for simd collapse (foobool(argc)), collapse (true), collapse (-5)
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp distribute collapse (S) // expected-error {{'S' does not refer to a value}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#if __cplusplus >= 201103L
+// expected-error@+5 2 {{integral constant expression must have integral or unscoped enumeration type}}
+#else
+// expected-error@+3 2 {{expression is not an integral constant expression}}
+#endif
+#pragma omp target
+#pragma omp teams distribute parallel for simd collapse (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd collapse (1)
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd collapse (N) // expected-error {{argument to 'collapse' clause must be a strictly positive integer value}}
+ for (T i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd collapse (2) // expected-note {{as specified in 'collapse' clause}}
+ foo(); // expected-error {{expected 2 for loops after '#pragma omp teams distribute parallel for simd'}}
+ return argc;
+}
+
+int main(int argc, char **argv) {
+#pragma omp target
+#pragma omp teams distribute parallel for simd collapse // expected-error {{expected '(' after 'collapse'}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd collapse ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd collapse () // expected-error {{expected expression}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd collapse (4 // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-note {{as specified in 'collapse' clause}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4]; // expected-error {{expected 4 for loops after '#pragma omp teams distribute parallel for simd', but found only 1}}
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd collapse (2+2)) // expected-warning {{extra tokens at the end of '#pragma omp teams distribute parallel for simd' are ignored}} expected-note {{as specified in 'collapse' clause}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4]; // expected-error {{expected 4 for loops after '#pragma omp teams distribute parallel for simd', but found only 1}}
+
+#if __cplusplus >= 201103L
+// expected-note@+3 {{non-constexpr function 'foobool' cannot be used}}
+#endif
+#pragma omp target
+#pragma omp teams distribute parallel for simd collapse (foobool(1) > 0 ? 1 : 2) // expected-error {{expression is not an integral constant expression}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#if __cplusplus >= 201103L
+// expected-note@+6 {{non-constexpr function 'foobool' cannot be used}}
+#endif
+// expected-error@+4 {{expression is not an integral constant expression}}
+// expected-error@+3 2 {{directive '#pragma omp teams distribute parallel for simd' cannot contain more than one 'collapse' clause}}
+// expected-error@+2 2 {{argument to 'collapse' clause must be a strictly positive integer value}}
+#pragma omp target
+#pragma omp teams distribute parallel for simd collapse (foobool(argc)), collapse (true), collapse (-5)
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd collapse (S1) // expected-error {{'S1' does not refer to a value}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#if __cplusplus >= 201103L
+// expected-error@+5 {{integral constant expression must have integral or unscoped enumeration type}}
+#else
+// expected-error@+3 {{expression is not an integral constant expression}}
+#endif
+#pragma omp target
+#pragma omp teams distribute parallel for simd collapse (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+// expected-error@+4 {{statement after '#pragma omp teams distribute parallel for simd' must be a for loop}}
+// expected-note@+2 {{in instantiation of function template specialization 'tmain<int, char, -1, -2>' requested here}}
+#pragma omp target
+#pragma omp teams distribute parallel for simd collapse(collapse(tmain<int, char, -1, -2>(argc, argv) // expected-error 2 {{expected ')'}} expected-note 2 {{to match this '('}}
+ foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd collapse (2) // expected-note {{as specified in 'collapse' clause}}
+ foo(); // expected-error {{expected 2 for loops after '#pragma omp teams distribute parallel for simd'}}
+
+// expected-note@+1 {{in instantiation of function template specialization 'tmain<int, char, 1, 0>' requested here}}
+ return tmain<int, char, 1, 0>(argc, argv);
+}
+
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_default_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_default_messages.cpp
new file mode 100644
index 000000000000..dc69acbe0b3c
--- /dev/null
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_default_messages.cpp
@@ -0,0 +1,30 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo();
+
+int main(int argc, char **argv) {
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd default // expected-error {{expected '(' after 'default'}}
+ for (int i=0; i<200; i++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd default ( // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i=0; i<200; i++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd default () // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+ for (int i=0; i<200; i++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd default (none // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i=0; i<200; i++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd default (shared), default(shared) // expected-error {{directive '#pragma omp teams distribute parallel for simd' cannot contain more than one 'default' clause}}
+ for (int i=0; i<200; i++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd default (x) // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+ for (int i=0; i<200; i++) foo();
+
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd default(none)
+ for (int i=0; i<200; i++) ++argc; // expected-error {{variable 'argc' must have explicitly specified data sharing attributes}}
+
+ return 0;
+}
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
new file mode 100644
index 000000000000..b879de749dfa
--- /dev/null
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_dist_schedule_messages.cpp
@@ -0,0 +1,104 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}} expected-note {{declared here}}
+
+template <class T, int N>
+T tmain(T argc) {
+ T b = argc, c, d, e, f, g;
+ char ** argv;
+ static T a;
+// CHECK: static T a;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd dist_schedule // expected-error {{expected '(' after 'dist_schedule'}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd dist_schedule ( // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd dist_schedule () // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd dist_schedule (static // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd dist_schedule (static, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd dist_schedule (argc)) // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}} expected-warning {{extra tokens at the end of '#pragma omp teams distribute parallel for simd' are ignored}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd dist_schedule (static, argc > 0 ? argv[1] : argv[2]) // expected-error2 {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd dist_schedule (static), dist_schedule (static, 1) // expected-error {{directive '#pragma omp teams distribute parallel for simd' cannot contain more than one 'dist_schedule' clause}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd dist_schedule (static, S1) // expected-error {{'S1' does not refer to a value}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd dist_schedule (static, argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error3 {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ for (int i = 0; i < 10; ++i) foo();
+
+ return T();
+}
+
+int main(int argc, char **argv) {
+#pragma omp target
+#pragma omp teams distribute parallel for simd dist_schedule // expected-error {{expected '(' after 'dist_schedule'}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd dist_schedule ( // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd dist_schedule () // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd dist_schedule (static // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd dist_schedule (static, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd dist_schedule (argc)) // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}} expected-warning {{extra tokens at the end of '#pragma omp teams distribute parallel for simd' are ignored}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd dist_schedule (static, argc > 0 ? argv[1] : argv[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd dist_schedule (static), dist_schedule (static, 1) // expected-error {{directive '#pragma omp teams distribute parallel for simd' cannot contain more than one 'dist_schedule' clause}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd dist_schedule (static, S1) // expected-error {{'S1' does not refer to a value}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd dist_schedule (static, argv[1]=2) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 0; i < 10; ++i) foo();
+
+ return (tmain<int, 5>(argc) + tmain<char, 1>(argv[0][0])); // expected-note {{in instantiation of function template specialization 'tmain<int, 5>' requested here}} expected-note {{in instantiation of function template specialization 'tmain<char, 1>' requested here}}
+}
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_firstprivate_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_firstprivate_messages.cpp
new file mode 100644
index 000000000000..cbbb313c06b3
--- /dev/null
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_firstprivate_messages.cpp
@@ -0,0 +1,152 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}} expected-note{{forward declaration of 'S1'}}
+extern S1 a;
+class S2 {
+ mutable int a;
+
+public:
+ S2() : a(0) {}
+ S2(const S2 &s2) : a(s2.a) {}
+ static float S2s;
+ static const float S2sc;
+};
+const float S2::S2sc = 0;
+const S2 b;
+const S2 ba[5];
+class S3 {
+ int a;
+ S3 &operator=(const S3 &s3);
+
+public:
+ S3() : a(0) {} // expected-note {{candidate constructor not viable: requires 0 arguments, but 1 was provided}}
+ S3(S3 &s3) : a(s3.a) {} // expected-note {{candidate constructor not viable: 1st argument ('const S3') would lose const qualifier}}
+};
+const S3 c;
+const S3 ca[5];
+extern const int f;
+class S4 {
+ int a;
+ S4();
+ S4(const S4 &s4);
+public:
+ S4(int v):a(v) { }
+};
+class S5 {
+ int a;
+ S5():a(0) {}
+ S5(const S5 &s5):a(s5.a) { }
+public:
+ S5(int v):a(v) { }
+};
+class S6 {
+ int a;
+public:
+ S6() : a(0) { }
+};
+
+S3 h;
+#pragma omp threadprivate(h) // expected-note {{defined as threadprivate or thread local}}
+
+int main(int argc, char **argv) {
+ const int d = 5;
+ const int da[5] = { 0 };
+ S4 e(4);
+ S5 g(5);
+ S6 p;
+ int i;
+ int &j = i;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd firstprivate // expected-error {{expected '(' after 'firstprivate'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd firstprivate ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd firstprivate () // expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd firstprivate (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd firstprivate (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd firstprivate (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd firstprivate (argc)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd firstprivate (S1) // expected-error {{'S1' does not refer to a value}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd firstprivate (a, b, c, d, f) // expected-error {{firstprivate variable with incomplete type 'S1'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd firstprivate (argv[1]) // expected-error {{expected variable name}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd firstprivate(ba)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd firstprivate(ca) // expected-error {{no matching constructor for initialization of 'S3'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd firstprivate(da)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd firstprivate(S2::S2s)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd firstprivate(S2::S2sc)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd firstprivate(h) // expected-error {{threadprivate or thread local variable cannot be firstprivate}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd private(i), firstprivate(i) // expected-error {{private variable cannot be firstprivate}} expected-note 2 {{defined as private}}
+ for (i = 0; i < argc; ++i) foo(); // expected-error {{loop iteration variable in the associated loop of 'omp teams distribute parallel for simd' directive may not be private, predetermined as linear}}
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd firstprivate(i)
+ for (j = 0; j < argc; ++j) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd firstprivate(i) // expected-note {{defined as firstprivate}}
+ for (i = 0; i < argc; ++i) foo(); // expected-error {{loop iteration variable in the associated loop of 'omp teams distribute parallel for simd' directive may not be firstprivate, predetermined as linear}}
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd firstprivate(j)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd lastprivate(argc), firstprivate(argc) // OK
+ for (i = 0; i < argc; ++i) foo();
+
+ return 0;
+}
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_if_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_if_messages.cpp
new file mode 100644
index 000000000000..01978d722226
--- /dev/null
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_if_messages.cpp
@@ -0,0 +1,140 @@
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ferror-limit 100 %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}}
+
+template <class T, class S> // expected-note {{declared here}}
+int tmain(T argc, S **argv) {
+ T i;
+#pragma omp target
+#pragma omp teams distribute parallel for simd if // expected-error {{expected '(' after 'if'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd if ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd if () // expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd if (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd if (argc)) // expected-warning {{extra tokens at the end of '#pragma omp teams distribute parallel for simd' are ignored}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd if (argc > 0 ? argv[1] : argv[2])
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd if (foobool(argc)), if (true) // expected-error {{directive '#pragma omp teams distribute parallel for simd' cannot contain more than one 'if' clause}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd if (S) // expected-error {{'S' does not refer to a value}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd if (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd if (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd if(argc)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd if(parallel // expected-error {{use of undeclared identifier 'parallel'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd if(parallel : // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd if(parallel : argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd if(parallel : argc)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd if(parallel : argc) if (for:argc) // expected-error {{directive name modifier 'for' is not allowed for '#pragma omp teams distribute parallel for simd'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd if(parallel : argc) if (parallel:argc) // expected-error {{directive '#pragma omp teams distribute parallel for simd' cannot contain more than one 'if' clause with 'parallel' name modifier}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd if(parallel : argc) if (argc) // expected-error {{no more 'if' clause is allowed}} expected-note {{previous clause with directive name modifier specified here}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd if(distribute : argc) // expected-error {{directive name modifier 'distribute' is not allowed for '#pragma omp teams distribute parallel for simd'}}
+ for (i = 0; i < argc; ++i) foo();
+
+ return 0;
+}
+
+int main(int argc, char **argv) {
+ int i;
+#pragma omp target
+#pragma omp teams distribute parallel for simd if // expected-error {{expected '(' after 'if'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd if ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd if () // expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd if (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd if (argc)) // expected-warning {{extra tokens at the end of '#pragma omp teams distribute parallel for simd' are ignored}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd if (argc > 0 ? argv[1] : argv[2])
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd if (foobool(argc)), if (true) // expected-error {{directive '#pragma omp teams distribute parallel for simd' cannot contain more than one 'if' clause}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd if (S1) // expected-error {{'S1' does not refer to a value}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd if (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd if (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd if (1 0) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd if(if(tmain(argc, argv) // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd if(parallel // expected-error {{use of undeclared identifier 'parallel'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd if(parallel : // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd if(parallel : argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd if(parallel : argc)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd if(parallel : argc) if (for:argc) // expected-error {{directive name modifier 'for' is not allowed for '#pragma omp teams distribute parallel for simd'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd if(parallel : argc) if (parallel:argc) // expected-error {{directive '#pragma omp teams distribute parallel for simd' cannot contain more than one 'if' clause with 'parallel' name modifier}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd if(parallel : argc) if (argc) // expected-error {{no more 'if' clause is allowed}} expected-note {{previous clause with directive name modifier specified here}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd if(distribute : argc) // expected-error {{directive name modifier 'distribute' is not allowed for '#pragma omp teams distribute parallel for simd'}}
+ for (i = 0; i < argc; ++i) foo();
+
+ return tmain(argc, argv);
+}
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_lastprivate_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_lastprivate_messages.cpp
new file mode 100644
index 000000000000..fce59b924f67
--- /dev/null
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_lastprivate_messages.cpp
@@ -0,0 +1,272 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note 2 {{declared here}} expected-note 2 {{forward declaration of 'S1'}}
+extern S1 a;
+class S2 {
+ mutable int a;
+
+public:
+ S2() : a(0) {}
+ S2(S2 &s2) : a(s2.a) {}
+ const S2 &operator =(const S2&) const;
+ S2 &operator =(const S2&);
+ static float S2s; // expected-note {{static data member is predetermined as shared}}
+ static const float S2sc;
+};
+const float S2::S2sc = 0; // expected-note {{static data member is predetermined as shared}}
+const S2 b;
+const S2 ba[5];
+class S3 {
+ int a;
+ S3 &operator=(const S3 &s3); // expected-note 2 {{implicitly declared private here}}
+
+public:
+ S3() : a(0) {}
+ S3(S3 &s3) : a(s3.a) {}
+};
+const S3 c; // expected-note {{global variable is predetermined as shared}}
+const S3 ca[5]; // expected-note {{global variable is predetermined as shared}}
+extern const int f; // expected-note {{global variable is predetermined as shared}}
+class S4 {
+ int a;
+ S4(); // expected-note 3 {{implicitly declared private here}}
+ S4(const S4 &s4);
+
+public:
+ S4(int v) : a(v) {}
+};
+class S5 {
+ int a;
+ S5() : a(0) {} // expected-note {{implicitly declared private here}}
+
+public:
+ S5(const S5 &s5) : a(s5.a) {}
+ S5(int v) : a(v) {}
+};
+class S6 {
+ int a;
+ S6() : a(0) {}
+
+public:
+ S6(const S6 &s6) : a(s6.a) {}
+ S6(int v) : a(v) {}
+};
+
+S3 h;
+#pragma omp threadprivate(h) // expected-note 2 {{defined as threadprivate or thread local}}
+
+template <class I, class C>
+int foomain(int argc, char **argv) {
+ I e(4);
+ I g(5);
+ int i;
+ int &j = i;
+#pragma omp target
+#pragma omp teams distribute parallel for simd lastprivate // expected-error {{expected '(' after 'lastprivate'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd lastprivate( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd lastprivate() // expected-error {{expected expression}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd lastprivate(argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd lastprivate(argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd lastprivate(argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd lastprivate(argc)
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd lastprivate(S1) // expected-error {{'S1' does not refer to a value}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd lastprivate(a, b) // expected-error {{lastprivate variable with incomplete type 'S1'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd lastprivate(argv[1]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd lastprivate(e, g) // expected-error 2 {{calling a private constructor of class 'S4'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd lastprivate(h) // expected-error {{threadprivate or thread local variable cannot be lastprivate}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ int v = 0;
+#pragma omp target
+#pragma omp teams distribute parallel for simd lastprivate(i)
+ for (int k = 0; k < argc; ++k) {
+ i = k;
+ v += i;
+ }
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd lastprivate(j) private(i)
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd lastprivate(i)
+ for (int k = 0; k < argc; ++k) ++k;
+
+ return 0;
+}
+
+void bar(S4 a[2]) {
+#pragma omp target
+#pragma omp teams distribute parallel for simd lastprivate(a)
+ for (int i = 0; i < 2; ++i) foo();
+}
+
+namespace A {
+double x;
+#pragma omp threadprivate(x) // expected-note {{defined as threadprivate or thread local}}
+}
+namespace B {
+using A::x;
+}
+
+int main(int argc, char **argv) {
+ const int d = 5; // expected-note {{constant variable is predetermined as shared}}
+ const int da[5] = {0}; // expected-note {{constant variable is predetermined as shared}}
+ S4 e(4);
+ S5 g(5);
+ S3 m;
+ S6 n(2);
+ int i;
+ int &j = i;
+#pragma omp target
+#pragma omp teams distribute parallel for simd lastprivate // expected-error {{expected '(' after 'lastprivate'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd lastprivate( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd lastprivate() // expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd lastprivate(argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd lastprivate(argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd lastprivate(argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd lastprivate(argc)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd lastprivate(S1) // expected-error {{'S1' does not refer to a value}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be lastprivate}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd lastprivate(argv[1]) // expected-error {{expected variable name}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd lastprivate(2 * 2) // expected-error {{expected variable name}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd lastprivate(ba)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd lastprivate(ca) // expected-error {{shared variable cannot be lastprivate}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd lastprivate(da) // expected-error {{shared variable cannot be lastprivate}}
+ for (i = 0; i < argc; ++i) foo();
+
+ int xa;
+#pragma omp target
+#pragma omp teams distribute parallel for simd lastprivate(xa) // OK
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd lastprivate(S2::S2s) // expected-error {{shared variable cannot be lastprivate}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd lastprivate(S2::S2sc) // expected-error {{shared variable cannot be lastprivate}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd lastprivate(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd lastprivate(m) // expected-error {{'operator=' is a private member of 'S3'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd lastprivate(h) // expected-error {{threadprivate or thread local variable cannot be lastprivate}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd lastprivate(B::x) // expected-error {{threadprivate or thread local variable cannot be lastprivate}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd private(xa), lastprivate(xa) // expected-error {{private variable cannot be lastprivate}} expected-note {{defined as private}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd lastprivate(xa)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd lastprivate(j)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd firstprivate(m) lastprivate(m) // expected-error {{'operator=' is a private member of 'S3'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd lastprivate(n) firstprivate(n) // OK
+ for (i = 0; i < argc; ++i) foo();
+
+ static int si;
+#pragma omp target
+#pragma omp teams distribute parallel for simd lastprivate(si) // OK
+ for (i = 0; i < argc; ++i) si = i + 1;
+
+ return foomain<S4, S5>(argc, argv); // expected-note {{in instantiation of function template specialization 'foomain<S4, S5>' requested here}}
+}
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_linear_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_linear_messages.cpp
new file mode 100644
index 000000000000..5b91a3c4cccc
--- /dev/null
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_linear_messages.cpp
@@ -0,0 +1,293 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+namespace X {
+ int x;
+};
+
+struct B {
+ static int ib; // expected-note {{'B::ib' declared here}}
+ static int bfoo() { return 8; }
+};
+
+int bfoo() { return 4; }
+
+int z;
+const int C1 = 1;
+const int C2 = 2;
+void test_linear_colons()
+{
+ int B = 0;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd linear(B:bfoo())
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd linear(B::ib:B:bfoo()) // expected-error {{unexpected ':' in nested name specifier; did you mean '::'}}
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd linear(B:ib) // expected-error {{use of undeclared identifier 'ib'; did you mean 'B::ib'}}
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd linear(z:B:ib) // expected-error {{unexpected ':' in nested name specifier; did you mean '::'?}}
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd linear(B:B::bfoo())
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd linear(X::x : ::z)
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd linear(B,::z, X::x)
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd linear(::z)
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd linear(B::bfoo()) // expected-error {{expected variable name}}
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd linear(B::ib,B:C1+C2)
+ for (int i = 0; i < 10; ++i) ;
+}
+
+template<int L, class T, class N> T test_template(T* arr, N num) {
+ N i;
+ T sum = (T)0;
+ T ind2 = - num * L; // expected-note {{'ind2' defined here}}
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd linear(ind2:L) // expected-error {{argument of a linear clause should be of integral or pointer type}}
+ for (i = 0; i < num; ++i) {
+ T cur = arr[(int)ind2];
+ ind2 += L;
+ sum += cur;
+ }
+ return T();
+}
+
+template<int LEN> int test_warn() {
+ int ind2 = 0;
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd linear(ind2:LEN) // expected-warning {{zero linear step (ind2 should probably be const)}}
+ for (int i = 0; i < 100; i++) {
+ ind2 += LEN;
+ }
+ return ind2;
+}
+
+struct S1; // expected-note 2 {{declared here}} expected-note 2 {{forward declaration of 'S1'}}
+extern S1 a;
+class S2 {
+ mutable int a;
+public:
+ S2():a(0) { }
+};
+const S2 b; // expected-note 2 {{'b' defined here}}
+const S2 ba[5];
+class S3 {
+ int a;
+public:
+ S3():a(0) { }
+};
+const S3 ca[5];
+class S4 {
+ int a;
+ S4();
+public:
+ S4(int v):a(v) { }
+};
+class S5 {
+ int a;
+ S5():a(0) {}
+public:
+ S5(int v):a(v) { }
+};
+
+S3 h;
+#pragma omp threadprivate(h) // expected-note 2 {{defined as threadprivate or thread local}}
+
+template<class I, class C> int foomain(I argc, C **argv) {
+ I e(4);
+ I g(5);
+ int i;
+ int &j = i;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd linear // expected-error {{expected '(' after 'linear'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd linear ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd linear () // expected-error {{expected expression}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd linear (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd linear (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd linear (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd linear (argc : 5)
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd linear (S1) // expected-error {{'S1' does not refer to a value}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd linear (a, b:B::ib) // expected-error {{linear variable with incomplete type 'S1'}} expected-error {{const-qualified variable cannot be linear}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd linear (argv[1]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd linear(e, g)
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd linear(h) // expected-error {{threadprivate or thread local variable cannot be linear}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd linear(i)
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp parallel
+ {
+ int v = 0;
+ int i;
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd linear(v:i)
+ for (int k = 0; k < argc; ++k) { i = k; v += i; }
+ }
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd linear(j)
+ for (int k = 0; k < argc; ++k) ++k;
+
+ int v = 0;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd linear(v:j)
+ for (int k = 0; k < argc; ++k) { ++k; v += j; }
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd linear(i)
+ for (int k = 0; k < argc; ++k) ++k;
+ return 0;
+}
+
+namespace A {
+double x;
+#pragma omp threadprivate(x) // expected-note {{defined as threadprivate or thread local}}
+}
+namespace C {
+using A::x;
+}
+
+int main(int argc, char **argv) {
+ double darr[100];
+ // expected-note@+1 {{in instantiation of function template specialization 'test_template<-4, double, int>' requested here}}
+ test_template<-4>(darr, 4);
+ // expected-note@+1 {{in instantiation of function template specialization 'test_warn<0>' requested here}}
+ test_warn<0>();
+
+ S4 e(4); // expected-note {{'e' defined here}}
+ S5 g(5); // expected-note {{'g' defined here}}
+ int i;
+ int &j = i;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd linear // expected-error {{expected '(' after 'linear'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd linear ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd linear () // expected-error {{expected expression}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd linear (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd linear (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd linear (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd linear (argc)
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd linear (S1) // expected-error {{'S1' does not refer to a value}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd linear (a, b) // expected-error {{linear variable with incomplete type 'S1'}} expected-error {{const-qualified variable cannot be linear}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd linear (argv[1]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd linear(e, g) // expected-error {{argument of a linear clause should be of integral or pointer type, not 'S4'}} expected-error {{argument of a linear clause should be of integral or pointer type, not 'S5'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd linear(h, C::x) // expected-error 2 {{threadprivate or thread local variable cannot be linear}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp parallel
+ {
+ int i;
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd linear(i)
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd linear(i : 4)
+ for (int k = 0; k < argc; ++k) { ++k; i += 4; }
+ }
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd linear(j)
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd linear(i)
+ for (int k = 0; k < argc; ++k) ++k;
+
+ foomain<int,char>(argc,argv); // expected-note {{in instantiation of function template specialization 'foomain<int, char>' requested here}}
+ return 0;
+}
+
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_loop_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_loop_messages.cpp
new file mode 100644
index 000000000000..675ecb407f4d
--- /dev/null
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_loop_messages.cpp
@@ -0,0 +1,716 @@
+// RUN: %clang_cc1 -fsyntax-only -fopenmp -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s
+
+class S {
+ int a;
+ S() : a(0) {}
+
+public:
+ S(int v) : a(v) {}
+ S(const S &s) : a(s.a) {}
+};
+
+static int sii;
+// expected-note@+1 {{defined as threadprivate or thread local}}
+#pragma omp threadprivate(sii)
+static int globalii;
+
+int test_iteration_spaces() {
+ const int N = 100;
+ float a[N], b[N], c[N];
+ int ii, jj, kk;
+ float fii;
+ double dii;
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; i += 1) {
+ c[i] = a[i] + b[i];
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (char i = 0; i < 10; i++) {
+ c[i] = a[i] + b[i];
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (char i = 0; i < 10; i += '\1') {
+ c[i] = a[i] + b[i];
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (long long i = 0; i < 10; i++) {
+ c[i] = a[i] + b[i];
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-error@+1 {{expression must have integral or unscoped enumeration type, not 'double'}}
+ for (long long i = 0; i < 10; i += 1.5) {
+ c[i] = a[i] + b[i];
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (long long i = 0; i < 'z'; i += 1u) {
+ c[i] = a[i] + b[i];
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-error@+1 {{variable must be of integer or random access iterator type}}
+ for (float fi = 0; fi < 10.0; fi++) {
+ c[(int)fi] = a[(int)fi] + b[(int)fi];
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-error@+1 {{variable must be of integer or random access iterator type}}
+ for (double fi = 0; fi < 10.0; fi++) {
+ c[(int)fi] = a[(int)fi] + b[(int)fi];
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (int &ref = ii; ref < 10; ref++) {
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (int i; i < 10; i++)
+ c[i] = a[i];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (int i = 0, j = 0; i < 10; ++i)
+ c[i] = a[i];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (; ii < 10; ++ii)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-warning@+2 {{expression result unused}}
+// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (ii + 1; ii < 10; ++ii)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (c[ii] = 0; ii < 10; ++ii)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// Ok to skip parenthesises.
+ for (((ii)) = 0; ii < 10; ++ii)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
+ for (int i = 0; i; i++)
+ c[i] = a[i];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-error@+2 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'i'}}
+ for (int i = 0; jj < kk; ii++)
+ c[i] = a[i];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
+ for (int i = 0; !!i; i++)
+ c[i] = a[i];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
+ for (int i = 0; i != 1; i++)
+ c[i] = a[i];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
+ for (int i = 0;; i++)
+ c[i] = a[i];
+
+// Ok.
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 11; i > 10; i--)
+ c[i] = a[i];
+
+// Ok.
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i)
+ c[i] = a[i];
+
+// Ok.
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (ii = 0; ii < 10; ++ii)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+ for (ii = 0; ii < 10; ++jj)
+ c[ii] = a[jj];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+ for (ii = 0; ii < 10; ++++ii)
+ c[ii] = a[ii];
+
+// Ok but undefined behavior (in general, cannot check that incr
+// is really loop-invariant).
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (ii = 0; ii < 10; ii = ii + ii)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-error@+1 {{expression must have integral or unscoped enumeration type, not 'float'}}
+ for (ii = 0; ii < 10; ii = ii + 1.0f)
+ c[ii] = a[ii];
+
+// Ok - step was converted to integer type.
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (ii = 0; ii < 10; ii = ii + (int)1.1f)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+ for (ii = 0; ii < 10; jj = ii + 2)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-warning@+2 {{relational comparison result unused}}
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+ for (ii = 0; ii<10; jj> kk + 2)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+ for (ii = 0; ii < 10;)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-warning@+2 {{expression result unused}}
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+ for (ii = 0; ii < 10; !ii)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+ for (ii = 0; ii < 10; ii ? ++ii : ++jj)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+ for (ii = 0; ii < 10; ii = ii < 10)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}}
+ for (ii = 0; ii < 10; ii = ii + 0)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}}
+ for (ii = 0; ii < 10; ii = ii + (int)(0.8 - 0.45))
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}}
+ for (ii = 0; (ii) < 10; ii -= 25)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}}
+ for (ii = 0; (ii < 10); ii -= 0)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-note@+2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+1 {{increment expression must cause 'ii' to decrease on each iteration of OpenMP for loop}}
+ for (ii = 0; ii > 10; (ii += 0))
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}}
+ for (ii = 0; ii < 10; (ii) = (1 - 1) + (ii))
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-note@+2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+1 {{increment expression must cause 'ii' to decrease on each iteration of OpenMP for loop}}
+ for ((ii = 0); ii > 10; (ii -= 0))
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}}
+ for (ii = 0; (ii < 10); (ii -= 0))
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd firstprivate(ii) // expected-note {{defined as firstprivate}}
+// expected-error@+1 {{loop iteration variable in the associated loop of 'omp teams distribute parallel for simd' directive may not be firstprivate, predetermined as linear}}
+ for (ii = 0; ii < 10; ii++)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd private(ii) // expected-note {{defined as private}}
+// expected-error@+1 {{loop iteration variable in the associated loop of 'omp teams distribute parallel for simd' directive may not be private, predetermined as linear}}
+ for (ii = 0; ii < 10; ii++)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd lastprivate(ii) // expected-note {{defined as lastprivate}}
+// expected-error@+1 {{loop iteration variable in the associated loop of 'omp teams distribute parallel for simd' directive may not be lastprivate, predetermined as linear}}
+ for (ii = 0; ii < 10; ii++)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-error@+1 {{loop iteration variable in the associated loop of 'omp teams distribute parallel for simd' directive may not be threadprivate or thread local, predetermined as linear}}
+ for (sii = 0; sii < 10; sii++)
+ c[sii] = a[sii];
+
+ {
+#pragma omp target
+#pragma omp teams distribute parallel for simd collapse(2)
+ for (ii = 0; ii < 10; ii += 1)
+ for (globalii = 0; globalii < 10; globalii += 1)
+ c[globalii] += a[globalii] + ii;
+ }
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-error@+1 {{statement after '#pragma omp teams distribute parallel for simd' must be a for loop}}
+ for (auto &item : a) {
+ item = item + 1;
+ }
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'i' to increase on each iteration of OpenMP for loop}}
+ for (unsigned i = 9; i < 10; i--) {
+ c[i] = a[i] + b[i];
+ }
+
+ int(*lb)[4] = nullptr;
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int(*p)[4] = lb; p < lb + 8; ++p) {
+ }
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (int a{0}; a < 10; ++a) {
+ }
+
+ return 0;
+}
+
+// Iterators allowed in openmp for-loops.
+namespace std {
+struct random_access_iterator_tag {};
+template <class Iter>
+struct iterator_traits {
+ typedef typename Iter::difference_type difference_type;
+ typedef typename Iter::iterator_category iterator_category;
+};
+template <class Iter>
+typename iterator_traits<Iter>::difference_type
+distance(Iter first, Iter last) { return first - last; }
+}
+class Iter0 {
+public:
+ Iter0() {}
+ Iter0(const Iter0 &) {}
+ Iter0 operator++() { return *this; }
+ Iter0 operator--() { return *this; }
+ bool operator<(Iter0 a) { return true; }
+};
+// expected-note@+2 {{candidate function not viable: no known conversion from 'GoodIter' to 'Iter0' for 1st argument}}
+// expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'Iter0' for 1st argument}}
+int operator-(Iter0 a, Iter0 b) { return 0; }
+class Iter1 {
+public:
+ Iter1(float f = 0.0f, double d = 0.0) {}
+ Iter1(const Iter1 &) {}
+ Iter1 operator++() { return *this; }
+ Iter1 operator--() { return *this; }
+ bool operator<(Iter1 a) { return true; }
+ bool operator>=(Iter1 a) { return false; }
+};
+class GoodIter {
+public:
+ GoodIter() {}
+ GoodIter(const GoodIter &) {}
+ GoodIter(int fst, int snd) {}
+ GoodIter &operator=(const GoodIter &that) { return *this; }
+ GoodIter &operator=(const Iter0 &that) { return *this; }
+ GoodIter &operator+=(int x) { return *this; }
+ explicit GoodIter(void *) {}
+ GoodIter operator++() { return *this; }
+ GoodIter operator--() { return *this; }
+ bool operator!() { return true; }
+ bool operator<(GoodIter a) { return true; }
+ bool operator<=(GoodIter a) { return true; }
+ bool operator>=(GoodIter a) { return false; }
+ typedef int difference_type;
+ typedef std::random_access_iterator_tag iterator_category;
+};
+// expected-note@+2 {{candidate function not viable: no known conversion from 'const Iter0' to 'GoodIter' for 2nd argument}}
+// expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'GoodIter' for 1st argument}}
+int operator-(GoodIter a, GoodIter b) { return 0; }
+// expected-note@+1 3 {{candidate function not viable: requires single argument 'a', but 2 arguments were provided}}
+GoodIter operator-(GoodIter a) { return a; }
+// expected-note@+2 {{candidate function not viable: no known conversion from 'const Iter0' to 'int' for 2nd argument}}
+// expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'GoodIter' for 1st argument}}
+GoodIter operator-(GoodIter a, int v) { return GoodIter(); }
+// expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter0' to 'GoodIter' for 1st argument}}
+GoodIter operator+(GoodIter a, int v) { return GoodIter(); }
+// expected-note@+2 {{candidate function not viable: no known conversion from 'GoodIter' to 'int' for 1st argument}}
+// expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'int' for 1st argument}}
+GoodIter operator-(int v, GoodIter a) { return GoodIter(); }
+// expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter0' to 'int' for 1st argument}}
+GoodIter operator+(int v, GoodIter a) { return GoodIter(); }
+
+int test_with_random_access_iterator() {
+ GoodIter begin, end;
+ Iter0 begin0, end0;
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (GoodIter I = begin; I < end; ++I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (GoodIter &I = begin; I < end; ++I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (GoodIter I = begin; I >= end; --I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (GoodIter I(begin); I < end; ++I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (GoodIter I(nullptr); I < end; ++I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (GoodIter I(0); I < end; ++I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (GoodIter I(1, 2); I < end; ++I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (begin = GoodIter(0); begin < end; ++begin)
+ ++begin;
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-error@+2 {{invalid operands to binary expression ('GoodIter' and 'const Iter0')}}
+// expected-error@+1 {{could not calculate number of iterations calling 'operator-' with upper and lower loop bounds}}
+ for (begin = begin0; begin < end; ++begin)
+ ++begin;
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (++begin; begin < end; ++begin)
+ ++begin;
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (begin = end; begin < end; ++begin)
+ ++begin;
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'I'}}
+ for (GoodIter I = begin; I - I; ++I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'I'}}
+ for (GoodIter I = begin; begin < end; ++I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'I'}}
+ for (GoodIter I = begin; !I; ++I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-note@+2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+1 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}}
+ for (GoodIter I = begin; I >= end; I = I + 1)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (GoodIter I = begin; I >= end; I = I - 1)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'I'}}
+ for (GoodIter I = begin; I >= end; I = -I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-note@+2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+1 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}}
+ for (GoodIter I = begin; I >= end; I = 2 + I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'I'}}
+ for (GoodIter I = begin; I >= end; I = 2 - I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-error@+1 {{invalid operands to binary expression ('Iter0' and 'int')}}
+ for (Iter0 I = begin0; I < end0; ++I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// Initializer is constructor without params.
+// expected-error@+2 {{invalid operands to binary expression ('Iter0' and 'int')}}
+// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (Iter0 I; I < end0; ++I)
+ ++I;
+ Iter1 begin1, end1;
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-error@+2 {{invalid operands to binary expression ('Iter1' and 'Iter1')}}
+// expected-error@+1 {{could not calculate number of iterations calling 'operator-' with upper and lower loop bounds}}
+ for (Iter1 I = begin1; I < end1; ++I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-note@+2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+1 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}}
+ for (Iter1 I = begin1; I >= end1; ++I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-error@+4 {{invalid operands to binary expression ('Iter1' and 'float')}}
+// expected-error@+3 {{could not calculate number of iterations calling 'operator-' with upper and lower loop bounds}}
+// Initializer is constructor with all default params.
+// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (Iter1 I; I < end1; ++I) {
+ }
+ return 0;
+}
+
+template <typename IT, int ST>
+class TC {
+public:
+ int dotest_lt(IT begin, IT end) {
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'I' to increase on each iteration of OpenMP for loop}}
+ for (IT I = begin; I < end; I = I + ST) {
+ ++I;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'I' to increase on each iteration of OpenMP for loop}}
+ for (IT I = begin; I <= end; I += ST) {
+ ++I;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (IT I = begin; I < end; ++I) {
+ ++I;
+ }
+ }
+
+ static IT step() {
+ return IT(ST);
+ }
+};
+template <typename IT, int ST = 0>
+int dotest_gt(IT begin, IT end) {
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-note@+2 2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+1 2 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}}
+ for (IT I = begin; I >= end; I = I + ST) {
+ ++I;
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-note@+2 2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+1 2 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}}
+ for (IT I = begin; I >= end; I += ST) {
+ ++I;
+ }
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+// expected-note@+2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+1 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}}
+ for (IT I = begin; I >= end; ++I) {
+ ++I;
+ }
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (IT I = begin; I < end; I += TC<int, ST>::step()) {
+ ++I;
+ }
+}
+
+void test_with_template() {
+ GoodIter begin, end;
+ TC<GoodIter, 100> t1;
+ TC<GoodIter, -100> t2;
+ t1.dotest_lt(begin, end);
+ t2.dotest_lt(begin, end); // expected-note {{in instantiation of member function 'TC<GoodIter, -100>::dotest_lt' requested here}}
+ dotest_gt(begin, end); // expected-note {{in instantiation of function template specialization 'dotest_gt<GoodIter, 0>' requested here}}
+ dotest_gt<unsigned, -10>(0, 100); // expected-note {{in instantiation of function template specialization 'dotest_gt<unsigned int, -10>' requested here}}
+}
+
+void test_loop_break() {
+ const int N = 100;
+ float a[N], b[N], c[N];
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; i++) {
+ c[i] = a[i] + b[i];
+ for (int j = 0; j < 10; ++j) {
+ if (a[i] > b[j])
+ break; // OK in nested loop
+ }
+ switch (i) {
+ case 1:
+ b[i]++;
+ break;
+ default:
+ break;
+ }
+ if (c[i] > 10)
+ break; // expected-error {{'break' statement cannot be used in OpenMP for loop}}
+
+ if (c[i] > 11)
+ break; // expected-error {{'break' statement cannot be used in OpenMP for loop}}
+ }
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; i++) {
+ for (int j = 0; j < 10; j++) {
+ c[i] = a[i] + b[i];
+ if (c[i] > 10) {
+ if (c[i] < 20) {
+ break; // OK
+ }
+ }
+ }
+ }
+}
+
+void test_loop_eh() {
+ const int N = 100;
+ float a[N], b[N], c[N];
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; i++) {
+ c[i] = a[i] + b[i];
+ try { // expected-error {{'try' statement cannot be used in OpenMP simd region}}
+ for (int j = 0; j < 10; ++j) {
+ if (a[i] > b[j])
+ throw a[i]; // expected-error {{'throw' statement cannot be used in OpenMP simd region}}
+ }
+ throw a[i]; // expected-error {{'throw' statement cannot be used in OpenMP simd region}}
+ } catch (float f) {
+ if (f > 0.1)
+ throw a[i]; // expected-error {{'throw' statement cannot be used in OpenMP simd region}}
+ return; // expected-error {{cannot return from OpenMP region}}
+ }
+ switch (i) {
+ case 1:
+ b[i]++;
+ break;
+ default:
+ break;
+ }
+ for (int j = 0; j < 10; j++) {
+ if (c[i] > 10)
+ throw c[i]; // expected-error {{'throw' statement cannot be used in OpenMP simd region}}
+ }
+ }
+ if (c[9] > 10)
+ throw c[9]; // OK
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < 10; ++i) {
+ struct S {
+ void g() { throw 0; }
+ };
+ }
+}
+
+void test_loop_firstprivate_lastprivate() {
+ S s(4);
+#pragma omp target
+#pragma omp teams distribute parallel for simd lastprivate(s) firstprivate(s)
+ for (int i = 0; i < 16; ++i)
+ ;
+}
+
+void test_ordered() {
+#pragma omp target
+#pragma omp teams distribute parallel for simd ordered // expected-error {{unexpected OpenMP clause 'ordered' in directive '#pragma omp teams distribute parallel for simd'}}
+ for (int i = 0; i < 16; ++i)
+ ;
+}
+
+void test_nowait() {
+#pragma omp target
+// expected-error@+1 2 {{unexpected OpenMP clause 'nowait' in directive '#pragma omp teams distribute parallel for simd'}}
+#pragma omp teams distribute parallel for simd nowait nowait // expected-error {{directive '#pragma omp teams distribute parallel for simd' cannot contain more than one 'nowait' clause}}
+ 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
new file mode 100644
index 000000000000..7876c38980ee
--- /dev/null
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_messages.cpp
@@ -0,0 +1,109 @@
+// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+
+void foo() {
+}
+
+static int pvt;
+#pragma omp threadprivate(pvt)
+
+#pragma omp teams distribute parallel for simd // expected-error {{unexpected OpenMP directive '#pragma omp teams distribute parallel for simd'}}
+
+int main(int argc, char **argv) {
+#pragma omp target
+#pragma omp teams distribute parallel for simd { // expected-warning {{extra tokens at the end of '#pragma omp teams distribute parallel for simd' are ignored}}
+ for (int i = 0; i < argc; ++i)
+ foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd ( // expected-warning {{extra tokens at the end of '#pragma omp teams distribute parallel for simd' are ignored}}
+ for (int i = 0; i < argc; ++i)
+ foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd[ // expected-warning {{extra tokens at the end of '#pragma omp teams distribute parallel for simd' are ignored}}
+ for (int i = 0; i < argc; ++i)
+ foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd] // expected-warning {{extra tokens at the end of '#pragma omp teams distribute parallel for simd' are ignored}}
+ for (int i = 0; i < argc; ++i)
+ foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd) // expected-warning {{extra tokens at the end of '#pragma omp teams distribute parallel for simd' are ignored}}
+ for (int i = 0; i < argc; ++i)
+ foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd } // expected-warning {{extra tokens at the end of '#pragma omp teams distribute parallel for simd' are ignored}}
+ for (int i = 0; i < argc; ++i)
+ foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < argc; ++i)
+ foo();
+// expected-warning@+2 {{extra tokens at the end of '#pragma omp teams distribute parallel for simd' are ignored}}
+#pragma omp target
+#pragma omp teams distribute parallel for simd unknown()
+ for (int i = 0; i < argc; ++i)
+ foo();
+L1:
+ for (int i = 0; i < argc; ++i)
+ foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < argc; ++i)
+ foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < argc; ++i) {
+ goto L1; // expected-error {{use of undeclared label 'L1'}}
+ argc++;
+ }
+
+ for (int i = 0; i < 10; ++i) {
+ switch (argc) {
+ case (0):
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < argc; ++i) {
+ foo();
+ break; // expected-error {{'break' statement cannot be used in OpenMP for loop}}
+ continue;
+ }
+ default:
+ break;
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute parallel for simd default(none)
+ for (int i = 0; i < 10; ++i)
+ ++argc; // expected-error {{ariable 'argc' must have explicitly specified data sharing attributes}}
+
+ goto L2; // expected-error {{use of undeclared label 'L2'}}
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < argc; ++i)
+ L2:
+ foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int i = 0; i < argc; ++i) {
+ return 1; // expected-error {{cannot return from OpenMP region}}
+ }
+
+ [[]] // expected-error {{an attribute list cannot appear here}}
+#pragma omp target
+#pragma omp teams distribute parallel for simd
+ for (int n = 0; n < 100; ++n) {
+ }
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd copyin(pvt) // expected-error {{unexpected OpenMP clause 'copyin' in directive '#pragma omp teams distribute parallel for simd'}}
+ for (int n = 0; n < 100; ++n) {}
+
+ return 0;
+}
+
+void test_ordered() {
+#pragma omp target
+#pragma omp teams distribute parallel for simd ordered // expected-error {{unexpected OpenMP clause 'ordered' in directive '#pragma omp teams distribute parallel for simd'}}
+ for (int i = 0; i < 16; ++i)
+ ;
+}
+
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
new file mode 100644
index 000000000000..7affd607b9d0
--- /dev/null
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_num_teams_messages.cpp
@@ -0,0 +1,111 @@
+// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 100 -o - %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note 2 {{declared here}}
+
+template <typename T, int C> // expected-note {{declared here}}
+T tmain(T argc) {
+ char **a;
+#pragma omp target
+#pragma omp teams distribute parallel for simd num_teams(C)
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd num_teams(T) // expected-error {{'T' does not refer to a value}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd num_teams // expected-error {{expected '(' after 'num_teams'}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd num_teams( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd num_teams() // expected-error {{expected expression}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd num_teams(argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd num_teams(argc)) // expected-warning {{extra tokens at the end of '#pragma omp teams distribute parallel for simd' are ignored}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd num_teams(argc > 0 ? a[1] : a[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd num_teams(argc + argc)
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd num_teams(argc), num_teams (argc+1) // expected-error {{directive '#pragma omp teams distribute parallel for simd' cannot contain more than one 'num_teams' clause}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd num_teams(S1) // expected-error {{'S1' does not refer to a value}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd num_teams(-2) // expected-error {{argument to 'num_teams' clause must be a strictly positive integer value}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd num_teams(-10u)
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd num_teams(3.14) // expected-error 2 {{expression must have integral or unscoped enumeration type, not 'double'}}
+ for (int i=0; i<100; i++) foo();
+
+ return 0;
+}
+
+int main(int argc, char **argv) {
+#pragma omp target
+#pragma omp teams distribute parallel for simd num_teams // expected-error {{expected '(' after 'num_teams'}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd num_teams ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd num_teams () // expected-error {{expected expression}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd num_teams (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd num_teams (argc)) // expected-warning {{extra tokens at the end of '#pragma omp teams distribute parallel for simd' are ignored}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd num_teams (argc > 0 ? argv[1] : argv[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd num_teams (argc + argc)
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd num_teams (argc), num_teams (argc+1) // expected-error {{directive '#pragma omp teams distribute parallel for simd' cannot contain more than one 'num_teams' clause}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd num_teams (S1) // expected-error {{'S1' does not refer to a value}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd num_teams (-2) // expected-error {{argument to 'num_teams' clause must be a strictly positive integer value}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd num_teams (-10u)
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd num_teams (3.14) // expected-error {{expression must have integral or unscoped enumeration type, not 'double'}}
+ for (int i=0; i<100; i++) foo();
+
+ return tmain<int, 10>(argc); // expected-note {{in instantiation of function template specialization 'tmain<int, 10>' requested here}}
+}
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
new file mode 100644
index 000000000000..fc71569e65ac
--- /dev/null
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_num_threads_messages.cpp
@@ -0,0 +1,86 @@
+// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}}
+
+template <class T, typename S, int N> // expected-note {{declared here}}
+T tmain(T argc, S **argv) {
+ T i;
+#pragma omp target
+#pragma omp teams distribute parallel for simd num_threads // expected-error {{expected '(' after 'num_threads'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd num_threads ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd num_threads () // expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd num_threads (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd num_threads (argc)) // expected-warning {{extra tokens at the end of '#pragma omp teams distribute parallel for simd' are ignored}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd num_threads ((argc > 0) ? argv[1] : argv[2]) // expected-error 2 {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd num_threads (foobool(argc)), num_threads (true), num_threads (-5) // expected-error 2 {{directive '#pragma omp teams distribute parallel for simd' cannot contain more than one 'num_threads' clause}} expected-error {{argument to 'num_threads' clause must be a strictly positive integer value}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd num_threads (S) // expected-error {{'S' does not refer to a value}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd num_threads (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error 2 {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd num_threads (argc)
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd num_threads (N) // expected-error {{argument to 'num_threads' clause must be a strictly positive integer value}}
+ for (i = 0; i < argc; ++i) foo();
+
+ return argc;
+}
+
+int main(int argc, char **argv) {
+ int i;
+#pragma omp target
+#pragma omp teams distribute parallel for simd num_threads // expected-error {{expected '(' after 'num_threads'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd num_threads ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd num_threads () // expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd num_threads (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd num_threads (argc)) // expected-warning {{extra tokens at the end of '#pragma omp teams distribute parallel for simd' are ignored}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd num_threads (argc > 0 ? argv[1] : argv[2]) // expected-error {{integral }}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd num_threads (foobool(argc)), num_threads (true), num_threads (-5) // expected-error 2 {{directive '#pragma omp teams distribute parallel for simd' cannot contain more than one 'num_threads' clause}} expected-error {{argument to 'num_threads' clause must be a strictly positive integer value}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd num_threads (S1) // expected-error {{'S1' does not refer to a value}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd num_threads (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ for (i = 0; i < argc; ++i) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd num_threads (num_threads(tmain<int, char, -1>(argc, argv) // expected-error 2 {{expected ')'}} expected-note 2 {{to match this '('}} expected-note {{in instantiation of function template specialization 'tmain<int, char, -1>' requested here}}
+ for (i = 0; i < argc; ++i) foo();
+
+ return tmain<int, char, 3>(argc, argv); // expected-note {{in instantiation of function template specialization 'tmain<int, char, 3>' requested here}}
+}
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_private_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_private_messages.cpp
new file mode 100644
index 000000000000..dc1ef5794206
--- /dev/null
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_private_messages.cpp
@@ -0,0 +1,146 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}} expected-note {{forward declaration of 'S1'}}
+extern S1 a;
+class S2 {
+ mutable int a;
+public:
+ S2():a(0) { }
+ static float S2s; // expected-note {{predetermined as shared}}
+};
+const S2 b;
+const S2 ba[5];
+class S3 {
+ int a;
+public:
+ S3():a(0) { }
+};
+const S3 c; // expected-note {{predetermined as shared}}
+const S3 ca[5]; // expected-note {{predetermined as shared}}
+extern const int f; // expected-note {{predetermined as shared}}
+class S4 {
+ int a;
+ S4(); // expected-note {{implicitly declared private here}}
+public:
+ S4(int v):a(v) { }
+};
+class S5 {
+ int a;
+ S5():a(0) {} // expected-note {{implicitly declared private here}}
+public:
+ S5(int v):a(v) { }
+};
+
+S3 h;
+#pragma omp threadprivate(h) // expected-note {{defined as threadprivate or thread local}}
+
+
+int main(int argc, char **argv) {
+ const int d = 5; // expected-note {{predetermined as shared}}
+ const int da[5] = { 0 }; // expected-note {{predetermined as shared}}
+ S4 e(4);
+ S5 g(5);
+ int i;
+ int &j = i;
+
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd private // expected-error {{expected '(' after 'private'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd private ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd private () // expected-error {{expected expression}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd private (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd private (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd private (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd private (argc)
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd private (S1) // expected-error {{'S1' does not refer to a value}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd private (a, b, c, d, f) // expected-error {{private variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be private}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd private (argv[1]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd private(ba)
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd private(ca) // expected-error {{shared variable cannot be private}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd private(da) // expected-error {{shared variable cannot be private}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd private(S2::S2s) // expected-error {{shared variable cannot be private}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd private(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd private(h) // expected-error {{threadprivate or thread local variable cannot be private}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd shared(i)
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd firstprivate(i), private(i) // expected-error {{firstprivate variable cannot be private}} expected-note {{defined as firstprivate}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd private(j)
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd reduction(+:i)
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp distribute private(i)
+ for (int k = 0; k < 10; ++k) {
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd private(i)
+ for (int x = 0; x < 10; ++x) foo();
+ }
+
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd firstprivate(i)
+ for (int k = 0; k < 10; ++k) {
+ }
+
+ return 0;
+}
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
new file mode 100644
index 000000000000..fd904299cd6d
--- /dev/null
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_proc_bind_messages.cpp
@@ -0,0 +1,85 @@
+// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - %s
+
+void foo();
+
+template <class T, typename S, int N>
+T tmain(T argc, S **argv) {
+ T i;
+#pragma omp target
+#pragma omp teams distribute parallel for simd proc_bind // expected-error {{expected '(' after 'proc_bind'}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd proc_bind( // expected-error {{expected 'master', 'close' or 'spread' in OpenMP clause 'proc_bind'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd proc_bind() // expected-error {{expected 'master', 'close' or 'spread' in OpenMP clause 'proc_bind'}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd proc_bind(master // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd proc_bind(close), proc_bind(spread) // expected-error {{directive '#pragma omp teams distribute parallel for simd' cannot contain more than one 'proc_bind' clause}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd proc_bind(x) // expected-error {{expected 'master', 'close' or 'spread' in OpenMP clause 'proc_bind'}}
+ for (i = 0; i < argc; ++i)
+ foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd proc_bind(master)
+ for (i = 0; i < argc; ++i)
+ foo();
+
+#pragma omp parallel proc_bind(close)
+#pragma omp target
+#pragma omp teams distribute parallel for simd proc_bind(spread)
+ for (i = 0; i < argc; ++i)
+ foo();
+
+ return T();
+}
+
+int main(int argc, char **argv) {
+ int i;
+#pragma omp target
+#pragma omp teams distribute parallel for simd proc_bind // expected-error {{expected '(' after 'proc_bind'}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd proc_bind( // expected-error {{expected 'master', 'close' or 'spread' in OpenMP clause 'proc_bind'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd proc_bind() // expected-error {{expected 'master', 'close' or 'spread' in OpenMP clause 'proc_bind'}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd proc_bind(master // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd proc_bind(close), proc_bind(spread) // expected-error {{directive '#pragma omp teams distribute parallel for simd' cannot contain more than one 'proc_bind' clause}}
+ for (i = 0; i < argc; ++i)
+ foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd proc_bind(x) // expected-error {{expected 'master', 'close' or 'spread' in OpenMP clause 'proc_bind'}}
+ for (i = 0; i < argc; ++i)
+ foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd proc_bind(master)
+ for (i = 0; i < argc; ++i)
+ foo();
+
+#pragma omp parallel proc_bind(close)
+#pragma omp target
+#pragma omp teams distribute parallel for simd proc_bind(spread)
+ for (i = 0; i < argc; ++i)
+ foo();
+ return tmain<int, char, 3>(argc, argv);
+}
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_reduction_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_reduction_messages.cpp
new file mode 100644
index 000000000000..47494b94ff0e
--- /dev/null
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_reduction_messages.cpp
@@ -0,0 +1,303 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}} expected-note 4 {{forward declaration of 'S1'}}
+extern S1 a;
+class S2 {
+ mutable int a;
+ S2 &operator+(const S2 &arg) { return (*this); } // expected-note 3 {{implicitly declared private here}}
+
+public:
+ S2() : a(0) {}
+ S2(S2 &s2) : a(s2.a) {}
+ static float S2s; // expected-note 2 {{static data member is predetermined as shared}}
+ static const float S2sc;
+};
+const float S2::S2sc = 0; // expected-note 2 {{'S2sc' defined here}}
+S2 b; // expected-note 3 {{'b' defined here}}
+const S2 ba[5]; // expected-note 2 {{'ba' defined here}}
+class S3 {
+ int a;
+
+public:
+ int b;
+ S3() : a(0) {}
+ S3(const S3 &s3) : a(s3.a) {}
+ S3 operator+(const S3 &arg1) { return arg1; }
+};
+int operator+(const S3 &arg1, const S3 &arg2) { return 5; }
+S3 c; // expected-note 3 {{'c' defined here}}
+const S3 ca[5]; // expected-note 2 {{'ca' defined here}}
+extern const int f; // expected-note 4 {{'f' declared here}}
+class S4 {
+ int a;
+ S4(); // expected-note {{implicitly declared private here}}
+ S4(const S4 &s4);
+ S4 &operator+(const S4 &arg) { return (*this); }
+
+public:
+ S4(int v) : a(v) {}
+};
+S4 &operator&=(S4 &arg1, S4 &arg2) { return arg1; }
+class S5 {
+ int a;
+ S5() : a(0) {} // expected-note {{implicitly declared private here}}
+ S5(const S5 &s5) : a(s5.a) {}
+ S5 &operator+(const S5 &arg);
+
+public:
+ S5(int v) : a(v) {}
+};
+class S6 { // expected-note 3 {{candidate function (the implicit copy assignment operator) not viable: no known conversion from 'int' to 'const S6' for 1st argument}}
+#if __cplusplus >= 201103L // C++11 or later
+// expected-note@-2 3 {{candidate function (the implicit move assignment operator) not viable}}
+#endif
+ int a;
+
+public:
+ S6() : a(6) {}
+ operator int() { return 6; }
+} o;
+
+S3 h, k;
+#pragma omp threadprivate(h) // expected-note 2 {{defined as threadprivate or thread local}}
+
+template <class T> // expected-note {{declared here}}
+T tmain(T argc) {
+ const T d = T(); // expected-note 4 {{'d' defined here}}
+ const T da[5] = {T()}; // expected-note 2 {{'da' defined here}}
+ T qa[5] = {T()};
+ T i;
+ T &j = i; // expected-note 4 {{'j' defined here}}
+ S3 &p = k; // expected-note 2 {{'p' defined here}}
+ const T &r = da[(int)i]; // expected-note 2 {{'r' defined here}}
+ T &q = qa[(int)i]; // expected-note 2 {{'q' defined here}}
+ T fl;
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction // expected-error {{expected '(' after 'reduction'}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction + // expected-error {{expected '(' after 'reduction'}} expected-warning {{extra tokens at the end of '#pragma omp teams distribute parallel for simd' are ignored}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction( // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(- // expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction() // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(*) // expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected expression}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(\) // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(& : argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{invalid operands to binary expression ('float' and 'float')}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(| : argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{invalid operands to binary expression ('float' and 'float')}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(|| : argc ? i : argc) // expected-error 2 {{expected variable name, array element or array section}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(foo : argc) //expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'float'}} expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'int'}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(&& : argc)
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(^ : T) // expected-error {{'T' does not refer to a value}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}} expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(+ : o) // expected-error 2 {{no viable overloaded '='}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd private(i), reduction(+ : j), reduction(+ : q) // expected-error 4 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp parallel private(k)
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(+ : p), reduction(+ : p) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(+ : p), reduction(+ : p) // expected-error 2 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 2 {{previously referenced here}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp parallel shared(i)
+#pragma omp parallel reduction(min : i)
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(max : j) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(+ : fl)
+ for (int j=0; j<100; j++) foo();
+
+ return T();
+}
+
+namespace A {
+double x;
+#pragma omp threadprivate(x) // expected-note {{defined as threadprivate or thread local}}
+}
+namespace B {
+using A::x;
+}
+
+int main(int argc, char **argv) {
+ const int d = 5; // expected-note 2 {{'d' defined here}}
+ const int da[5] = {0}; // expected-note {{'da' defined here}}
+ int qa[5] = {0};
+ S4 e(4);
+ S5 g(5);
+ int i;
+ int &j = i; // expected-note 2 {{'j' defined here}}
+ S3 &p = k; // expected-note 2 {{'p' defined here}}
+ const int &r = da[i]; // expected-note {{'r' defined here}}
+ int &q = qa[i]; // expected-note {{'q' defined here}}
+ float fl;
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction // expected-error {{expected '(' after 'reduction'}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction + // expected-error {{expected '(' after 'reduction'}} expected-warning {{extra tokens at the end of '#pragma omp teams distribute parallel for simd' are ignored}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction( // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(- // expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction() // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(*) // expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected expression}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(\) // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(foo : argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max'}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(| : argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(|| : argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name, array element or array section}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(~ : argc) // expected-error {{expected unqualified-id}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(&& : argc)
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(^ : S1) // expected-error {{'S1' does not refer to a value}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified list item cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(& : e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{invalid operands to binary expression ('S4' and 'S4')}} expected-error {{calling a private constructor of class 'S5'}} expected-error {{invalid operands to binary expression ('S5' and 'S5')}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(+ : h, k, B::x) // expected-error 2 {{threadprivate or thread local variable cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(+ : o) // expected-error {{no viable overloaded '='}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd private(i), reduction(+ : j), reduction(+ : q) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp parallel private(k)
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(+ : p), reduction(+ : p) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(+ : p), reduction(+ : p) // expected-error {{variable can appear only once in OpenMP 'reduction' clause}} expected-note {{previously referenced here}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(+ : r) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp parallel shared(i)
+#pragma omp parallel reduction(min : i)
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(max : j) // expected-error {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(+ : fl)
+ for (int j=0; j<100; j++) foo();
+ static int m;
+#pragma omp target
+#pragma omp teams distribute parallel for simd reduction(+ : m) // OK
+ for (int j=0; j<100; j++) foo();
+
+ return tmain(argc) + tmain(fl); // expected-note {{in instantiation of function template specialization 'tmain<int>' requested here}} expected-note {{in instantiation of function template specialization 'tmain<float>' requested here}}
+}
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_safelen_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_safelen_messages.cpp
new file mode 100644
index 000000000000..82fd4b0da837
--- /dev/null
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_safelen_messages.cpp
@@ -0,0 +1,155 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+
+void foo() {
+}
+
+#if __cplusplus >= 201103L
+// expected-note@+2 4 {{declared here}}
+#endif
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}}
+
+template <class T, typename S, int N, int ST> // expected-note {{declared here}}
+T tmain(T argc, S **argv) { //expected-note 2 {{declared here}}
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd safelen // expected-error {{expected '(' after 'safelen'}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd safelen ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd safelen () // expected-error {{expected expression}}
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd safelen (argc // expected-note {{to match this '('}} expected-error 2 {{expression is not an integral constant expression}} expected-note 2 {{read of non-const variable 'argc' is not allowed in a constant expression}} expected-error {{expected ')'}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd safelen (ST // expected-error {{argument to 'safelen' clause must be a strictly positive integer value}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd safelen (1)) // expected-warning {{extra tokens at the end of '#pragma omp teams distribute parallel for simd' are ignored}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd safelen ((ST > 0) ? 1 + ST : 2)
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#if __cplusplus >= 201103L
+ // expected-note@+3 2 {{non-constexpr function 'foobool' cannot be used in a constant expression}}
+#endif
+#pragma omp target
+#pragma omp teams distribute parallel for simd safelen (foobool(argc)), safelen (true), safelen (-5) // expected-error 2 {{directive '#pragma omp teams distribute parallel for simd' cannot contain more than one 'safelen' clause}} expected-error 2 {{argument to 'safelen' clause must be a strictly positive integer value}} expected-error 2 {{expression is not an integral constant expression}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd safelen (S) // expected-error {{'S' does not refer to a value}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#if __cplusplus <= 199711L
+ // expected-error@+5 2 {{expression is not an integral constant expression}}
+#else
+ // expected-error@+3 2 {{integral constant expression must have integral or unscoped enumeration type, not 'char *'}}
+#endif
+#pragma omp target
+#pragma omp teams distribute parallel for simd safelen (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd safelen (4)
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd safelen (N) // expected-error {{argument to 'safelen' clause must be a strictly positive integer value}}
+ for (T i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+ return argc;
+}
+
+int main(int argc, char **argv) {
+#pragma omp target
+#pragma omp teams distribute parallel for simd safelen // expected-error {{expected '(' after 'safelen'}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd safelen ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd safelen () // expected-error {{expected expression}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd safelen (4 // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd safelen (2+2)) // expected-warning {{extra tokens at the end of '#pragma omp teams distribute parallel for simd' are ignored}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#if __cplusplus >= 201103L
+ // expected-note@+3 {{non-constexpr function 'foobool' cannot be used in a constant expression}}
+#endif
+#pragma omp target
+#pragma omp teams distribute parallel for simd safelen (foobool(1) > 0 ? 1 : 2) // expected-error {{expression is not an integral constant expression}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#if __cplusplus >= 201103L
+ // expected-note@+3 {{non-constexpr function 'foobool' cannot be used in a constant expression}}
+#endif
+#pragma omp target
+#pragma omp teams distribute parallel for simd safelen (foobool(argc)), safelen (true), safelen (-5) // expected-error 2 {{argument to 'safelen' clause must be a strictly positive integer value}} expected-error 2 {{directive '#pragma omp teams distribute parallel for simd' cannot contain more than one 'safelen' clause}} expected-error {{expression is not an integral constant expression}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd safelen (S1) // expected-error {{'S1' does not refer to a value}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#if __cplusplus <= 199711L
+ // expected-error@+5 {{expression is not an integral constant expression}}
+#else
+ // expected-error@+3 {{integral constant expression must have integral or unscoped enumeration type, not 'char *'}}
+#endif
+#pragma omp target
+#pragma omp teams distribute parallel for simd safelen (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+ // expected-note@+2 {{in instantiation of function template specialization 'tmain<int, char, -1, -2>' requested here}}
+#pragma omp target
+#pragma omp teams distribute parallel for simd safelen(safelen(tmain<int, char, -1, -2>(argc, argv) // expected-error 2 {{expected ')'}} expected-note 2 {{to match this '('}}
+ foo(); // expected-error {{statement after '#pragma omp teams distribute parallel for simd' must be a for loop}}
+
+ // expected-note@+1 {{in instantiation of function template specialization 'tmain<int, char, 12, 4>' requested here}}
+ return tmain<int, char, 12, 4>(argc, argv);
+}
+
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_shared_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_shared_messages.cpp
new file mode 100644
index 000000000000..f13146641a38
--- /dev/null
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_shared_messages.cpp
@@ -0,0 +1,127 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}}
+extern S1 a;
+class S2 {
+ mutable int a;
+public:
+ S2():a(0) { }
+ S2(S2 &s2):a(s2.a) { }
+};
+const S2 b;
+const S2 ba[5];
+class S3 {
+ int a;
+public:
+ S3():a(0) { }
+ S3(S3 &s3):a(s3.a) { }
+};
+const S3 c;
+const S3 ca[5];
+extern const int f;
+class S4 {
+ int a;
+ S4();
+ S4(const S4 &s4);
+public:
+ S4(int v):a(v) { }
+};
+class S5 {
+ int a;
+ S5():a(0) {}
+ S5(const S5 &s5):a(s5.a) { }
+public:
+ S5(int v):a(v) { }
+};
+
+S3 h;
+#pragma omp threadprivate(h) // expected-note {{defined as threadprivate or thread local}}
+
+namespace A {
+double x;
+#pragma omp threadprivate(x) // expected-note {{defined as threadprivate or thread local}}
+}
+namespace B {
+using A::x;
+}
+
+int main(int argc, char **argv) {
+ const int d = 5;
+ const int da[5] = { 0 };
+ S4 e(4);
+ S5 g(5);
+ int i;
+ int &j = i;
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd shared // expected-error {{expected '(' after 'shared'}}
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd shared ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd shared () // expected-error {{expected expression}}
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd shared (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd shared (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd shared (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd shared (argc)
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd shared (S1) // expected-error {{'S1' does not refer to a value}}
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd shared (a, b, c, d, f)
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd shared (argv[1]) // expected-error {{expected variable name}}
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd shared(ba)
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd shared(ca)
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd shared(da)
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd shared(e, g)
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd shared(h, B::x) // expected-error 2 {{threadprivate or thread local variable cannot be shared}}
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd private(i), shared(i) // expected-error {{private variable cannot be shared}} expected-note {{defined as private}}
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd firstprivate(i), shared(i) // expected-error {{firstprivate variable cannot be shared}} expected-note {{defined as firstprivate}}
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd private(i)
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd shared(i)
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd shared(j)
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd firstprivate(i)
+ for (int j=0; j<100; j++) foo();
+
+ return 0;
+}
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_simdlen_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_simdlen_messages.cpp
new file mode 100644
index 000000000000..82fd4b0da837
--- /dev/null
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_simdlen_messages.cpp
@@ -0,0 +1,155 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+
+void foo() {
+}
+
+#if __cplusplus >= 201103L
+// expected-note@+2 4 {{declared here}}
+#endif
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}}
+
+template <class T, typename S, int N, int ST> // expected-note {{declared here}}
+T tmain(T argc, S **argv) { //expected-note 2 {{declared here}}
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd safelen // expected-error {{expected '(' after 'safelen'}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd safelen ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd safelen () // expected-error {{expected expression}}
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd safelen (argc // expected-note {{to match this '('}} expected-error 2 {{expression is not an integral constant expression}} expected-note 2 {{read of non-const variable 'argc' is not allowed in a constant expression}} expected-error {{expected ')'}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd safelen (ST // expected-error {{argument to 'safelen' clause must be a strictly positive integer value}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd safelen (1)) // expected-warning {{extra tokens at the end of '#pragma omp teams distribute parallel for simd' are ignored}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd safelen ((ST > 0) ? 1 + ST : 2)
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#if __cplusplus >= 201103L
+ // expected-note@+3 2 {{non-constexpr function 'foobool' cannot be used in a constant expression}}
+#endif
+#pragma omp target
+#pragma omp teams distribute parallel for simd safelen (foobool(argc)), safelen (true), safelen (-5) // expected-error 2 {{directive '#pragma omp teams distribute parallel for simd' cannot contain more than one 'safelen' clause}} expected-error 2 {{argument to 'safelen' clause must be a strictly positive integer value}} expected-error 2 {{expression is not an integral constant expression}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd safelen (S) // expected-error {{'S' does not refer to a value}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#if __cplusplus <= 199711L
+ // expected-error@+5 2 {{expression is not an integral constant expression}}
+#else
+ // expected-error@+3 2 {{integral constant expression must have integral or unscoped enumeration type, not 'char *'}}
+#endif
+#pragma omp target
+#pragma omp teams distribute parallel for simd safelen (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd safelen (4)
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd safelen (N) // expected-error {{argument to 'safelen' clause must be a strictly positive integer value}}
+ for (T i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+ return argc;
+}
+
+int main(int argc, char **argv) {
+#pragma omp target
+#pragma omp teams distribute parallel for simd safelen // expected-error {{expected '(' after 'safelen'}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd safelen ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd safelen () // expected-error {{expected expression}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd safelen (4 // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd safelen (2+2)) // expected-warning {{extra tokens at the end of '#pragma omp teams distribute parallel for simd' are ignored}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#if __cplusplus >= 201103L
+ // expected-note@+3 {{non-constexpr function 'foobool' cannot be used in a constant expression}}
+#endif
+#pragma omp target
+#pragma omp teams distribute parallel for simd safelen (foobool(1) > 0 ? 1 : 2) // expected-error {{expression is not an integral constant expression}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#if __cplusplus >= 201103L
+ // expected-note@+3 {{non-constexpr function 'foobool' cannot be used in a constant expression}}
+#endif
+#pragma omp target
+#pragma omp teams distribute parallel for simd safelen (foobool(argc)), safelen (true), safelen (-5) // expected-error 2 {{argument to 'safelen' clause must be a strictly positive integer value}} expected-error 2 {{directive '#pragma omp teams distribute parallel for simd' cannot contain more than one 'safelen' clause}} expected-error {{expression is not an integral constant expression}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd safelen (S1) // expected-error {{'S1' does not refer to a value}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#if __cplusplus <= 199711L
+ // expected-error@+5 {{expression is not an integral constant expression}}
+#else
+ // expected-error@+3 {{integral constant expression must have integral or unscoped enumeration type, not 'char *'}}
+#endif
+#pragma omp target
+#pragma omp teams distribute parallel for simd safelen (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+ // expected-note@+2 {{in instantiation of function template specialization 'tmain<int, char, -1, -2>' requested here}}
+#pragma omp target
+#pragma omp teams distribute parallel for simd safelen(safelen(tmain<int, char, -1, -2>(argc, argv) // expected-error 2 {{expected ')'}} expected-note 2 {{to match this '('}}
+ foo(); // expected-error {{statement after '#pragma omp teams distribute parallel for simd' must be a for loop}}
+
+ // expected-note@+1 {{in instantiation of function template specialization 'tmain<int, char, 12, 4>' requested here}}
+ return tmain<int, char, 12, 4>(argc, argv);
+}
+
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
new file mode 100644
index 000000000000..81ed9475d356
--- /dev/null
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_thread_limit_messages.cpp
@@ -0,0 +1,111 @@
+// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note 2 {{declared here}}
+
+template <typename T, int C> // expected-note {{declared here}}
+T tmain(T argc) {
+ char **a;
+#pragma omp target
+#pragma omp teams distribute parallel for simd thread_limit(C)
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd thread_limit(T) // expected-error {{'T' does not refer to a value}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd thread_limit // expected-error {{expected '(' after 'thread_limit'}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd thread_limit( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd thread_limit() // expected-error {{expected expression}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd thread_limit(argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd thread_limit(argc)) // expected-warning {{extra tokens at the end of '#pragma omp teams distribute parallel for simd' are ignored}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd thread_limit(argc > 0 ? a[1] : a[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd thread_limit(argc + argc)
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd thread_limit(argc), thread_limit (argc+1) // expected-error {{directive '#pragma omp teams distribute parallel for simd' cannot contain more than one 'thread_limit' clause}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd thread_limit(S1) // expected-error {{'S1' does not refer to a value}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd thread_limit(-2) // expected-error {{argument to 'thread_limit' clause must be a strictly positive integer value}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd thread_limit(-10u)
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for simd thread_limit(3.14) // expected-error 2 {{expression must have integral or unscoped enumeration type, not 'double'}}
+ for (int j=0; j<100; j++) foo();
+
+ return 0;
+}
+
+int main(int argc, char **argv) {
+#pragma omp target
+#pragma omp teams distribute parallel for simd thread_limit // expected-error {{expected '(' after 'thread_limit'}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd thread_limit ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd thread_limit () // expected-error {{expected expression}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd thread_limit (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd thread_limit (argc)) // expected-warning {{extra tokens at the end of '#pragma omp teams distribute parallel for simd' are ignored}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd thread_limit (argc > 0 ? argv[1] : argv[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd thread_limit (argc + argc)
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd thread_limit (argc), thread_limit (argc+1) // expected-error {{directive '#pragma omp teams distribute parallel for simd' cannot contain more than one 'thread_limit' clause}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd thread_limit (S1) // expected-error {{'S1' does not refer to a value}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd thread_limit (-2) // expected-error {{argument to 'thread_limit' clause must be a strictly positive integer value}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd thread_limit (-10u)
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for simd thread_limit (3.14) // expected-error {{expression must have integral or unscoped enumeration type, not 'double'}}
+ for (int j=0; j<100; j++) foo();
+
+ return tmain<int, 10>(argc); // expected-note {{in instantiation of function template specialization 'tmain<int, 10>' requested here}}
+}
diff --git a/test/OpenMP/teams_distribute_parallel_for_thread_limit_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_thread_limit_messages.cpp
new file mode 100644
index 000000000000..4018f3f07d0f
--- /dev/null
+++ b/test/OpenMP/teams_distribute_parallel_for_thread_limit_messages.cpp
@@ -0,0 +1,111 @@
+// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note 2 {{declared here}}
+
+template <typename T, int C> // expected-note {{declared here}}
+T tmain(T argc) {
+ char **a;
+#pragma omp target
+#pragma omp teams distribute parallel for thread_limit(C)
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for thread_limit(T) // expected-error {{'T' does not refer to a value}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for thread_limit // expected-error {{expected '(' after 'thread_limit'}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for thread_limit( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for thread_limit() // expected-error {{expected expression}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for thread_limit(argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for thread_limit(argc)) // expected-warning {{extra tokens at the end of '#pragma omp teams distribute parallel for' are ignored}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for thread_limit(argc > 0 ? a[1] : a[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for thread_limit(argc + argc)
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for thread_limit(argc), thread_limit (argc+1) // expected-error {{directive '#pragma omp teams distribute parallel for' cannot contain more than one 'thread_limit' clause}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for thread_limit(S1) // expected-error {{'S1' does not refer to a value}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for thread_limit(-2) // expected-error {{argument to 'thread_limit' clause must be a strictly positive integer value}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for thread_limit(-10u)
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute parallel for thread_limit(3.14) // expected-error 2 {{expression must have integral or unscoped enumeration type, not 'double'}}
+ for (int j=0; j<100; j++) foo();
+
+ return 0;
+}
+
+int main(int argc, char **argv) {
+#pragma omp target
+#pragma omp teams distribute parallel for thread_limit // expected-error {{expected '(' after 'thread_limit'}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for thread_limit ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for thread_limit () // expected-error {{expected expression}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for thread_limit (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for thread_limit (argc)) // expected-warning {{extra tokens at the end of '#pragma omp teams distribute parallel for' are ignored}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for thread_limit (argc > 0 ? argv[1] : argv[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for thread_limit (argc + argc)
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for thread_limit (argc), thread_limit (argc+1) // expected-error {{directive '#pragma omp teams distribute parallel for' cannot contain more than one 'thread_limit' clause}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for thread_limit (S1) // expected-error {{'S1' does not refer to a value}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for thread_limit (-2) // expected-error {{argument to 'thread_limit' clause must be a strictly positive integer value}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for thread_limit (-10u)
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target
+#pragma omp teams distribute parallel for thread_limit (3.14) // expected-error {{expression must have integral or unscoped enumeration type, not 'double'}}
+ for (int j=0; j<100; j++) foo();
+
+ return tmain<int, 10>(argc); // expected-note {{in instantiation of function template specialization 'tmain<int, 10>' requested here}}
+}
diff --git a/test/OpenMP/teams_distribute_private_messages.cpp b/test/OpenMP/teams_distribute_private_messages.cpp
new file mode 100644
index 000000000000..aff1f539894d
--- /dev/null
+++ b/test/OpenMP/teams_distribute_private_messages.cpp
@@ -0,0 +1,146 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}} expected-note {{forward declaration of 'S1'}}
+extern S1 a;
+class S2 {
+ mutable int a;
+public:
+ S2():a(0) { }
+ static float S2s; // expected-note {{predetermined as shared}}
+};
+const S2 b;
+const S2 ba[5];
+class S3 {
+ int a;
+public:
+ S3():a(0) { }
+};
+const S3 c; // expected-note {{predetermined as shared}}
+const S3 ca[5]; // expected-note {{predetermined as shared}}
+extern const int f; // expected-note {{predetermined as shared}}
+class S4 {
+ int a;
+ S4(); // expected-note {{implicitly declared private here}}
+public:
+ S4(int v):a(v) { }
+};
+class S5 {
+ int a;
+ S5():a(0) {} // expected-note {{implicitly declared private here}}
+public:
+ S5(int v):a(v) { }
+};
+
+S3 h;
+#pragma omp threadprivate(h) // expected-note {{defined as threadprivate or thread local}}
+
+
+int main(int argc, char **argv) {
+ const int d = 5; // expected-note {{predetermined as shared}}
+ const int da[5] = { 0 }; // expected-note {{predetermined as shared}}
+ S4 e(4);
+ S5 g(5);
+ int i;
+ int &j = i;
+
+ #pragma omp target
+ #pragma omp teams distribute private // expected-error {{expected '(' after 'private'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute private ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute private () // expected-error {{expected expression}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute private (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute private (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute private (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute private (argc)
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute private (S1) // expected-error {{'S1' does not refer to a value}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute private (a, b, c, d, f) // expected-error {{private variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be private}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute private (argv[1]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute private(ba)
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute private(ca) // expected-error {{shared variable cannot be private}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute private(da) // expected-error {{shared variable cannot be private}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute private(S2::S2s) // expected-error {{shared variable cannot be private}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute private(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute private(h) // expected-error {{threadprivate or thread local variable cannot be private}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute shared(i)
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute firstprivate(i), private(i) // expected-error {{firstprivate variable cannot be private}} expected-note {{defined as firstprivate}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute private(j)
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute reduction(+:i)
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp distribute private(i)
+ for (int k = 0; k < 10; ++k) {
+ #pragma omp target
+ #pragma omp teams distribute private(i)
+ for (int x = 0; x < 10; ++x) foo();
+ }
+
+ #pragma omp target
+ #pragma omp teams distribute firstprivate(i)
+ for (int k = 0; k < 10; ++k) {
+ }
+
+ return 0;
+}
diff --git a/test/OpenMP/teams_distribute_reduction_messages.cpp b/test/OpenMP/teams_distribute_reduction_messages.cpp
new file mode 100644
index 000000000000..d0a6d296c0f5
--- /dev/null
+++ b/test/OpenMP/teams_distribute_reduction_messages.cpp
@@ -0,0 +1,309 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+void foobar(int &ref) {
+#pragma omp target
+#pragma omp teams distribute reduction(+:ref)
+ for (int j=0; j<100; j++) foo();
+}
+
+struct S1; // expected-note {{declared here}} expected-note 4 {{forward declaration of 'S1'}}
+extern S1 a;
+class S2 {
+ mutable int a;
+ S2 &operator+(const S2 &arg) { return (*this); } // expected-note 3 {{implicitly declared private here}}
+
+public:
+ S2() : a(0) {}
+ S2(S2 &s2) : a(s2.a) {}
+ static float S2s; // expected-note 2 {{static data member is predetermined as shared}}
+ static const float S2sc;
+};
+const float S2::S2sc = 0; // expected-note 2 {{'S2sc' defined here}}
+S2 b; // expected-note 3 {{'b' defined here}}
+const S2 ba[5]; // expected-note 2 {{'ba' defined here}}
+class S3 {
+ int a;
+
+public:
+ int b;
+ S3() : a(0) {}
+ S3(const S3 &s3) : a(s3.a) {}
+ S3 operator+(const S3 &arg1) { return arg1; }
+};
+int operator+(const S3 &arg1, const S3 &arg2) { return 5; }
+S3 c; // expected-note 3 {{'c' defined here}}
+const S3 ca[5]; // expected-note 2 {{'ca' defined here}}
+extern const int f; // expected-note 4 {{'f' declared here}}
+class S4 {
+ int a;
+ S4(); // expected-note {{implicitly declared private here}}
+ S4(const S4 &s4);
+ S4 &operator+(const S4 &arg) { return (*this); }
+
+public:
+ S4(int v) : a(v) {}
+};
+S4 &operator&=(S4 &arg1, S4 &arg2) { return arg1; }
+class S5 {
+ int a;
+ S5() : a(0) {} // expected-note {{implicitly declared private here}}
+ S5(const S5 &s5) : a(s5.a) {}
+ S5 &operator+(const S5 &arg);
+
+public:
+ S5(int v) : a(v) {}
+};
+class S6 { // expected-note 3 {{candidate function (the implicit copy assignment operator) not viable: no known conversion from 'int' to 'const S6' for 1st argument}}
+#if __cplusplus >= 201103L // C++11 or later
+// expected-note@-2 3 {{candidate function (the implicit move assignment operator) not viable}}
+#endif
+ int a;
+
+public:
+ S6() : a(6) {}
+ operator int() { return 6; }
+} o;
+
+S3 h, k;
+#pragma omp threadprivate(h) // expected-note 2 {{defined as threadprivate or thread local}}
+
+template <class T> // expected-note {{declared here}}
+T tmain(T argc) {
+ const T d = T(); // expected-note 4 {{'d' defined here}}
+ const T da[5] = {T()}; // expected-note 2 {{'da' defined here}}
+ T qa[5] = {T()};
+ T i;
+ T &j = i; // expected-note 4 {{'j' defined here}}
+ S3 &p = k; // expected-note 2 {{'p' defined here}}
+ const T &r = da[(int)i]; // expected-note 2 {{'r' defined here}}
+ T &q = qa[(int)i]; // expected-note 2 {{'q' defined here}}
+ T fl;
+#pragma omp target
+#pragma omp teams distribute reduction // expected-error {{expected '(' after 'reduction'}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction + // expected-error {{expected '(' after 'reduction'}} expected-warning {{extra tokens at the end of '#pragma omp teams distribute' are ignored}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction( // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction(- // expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction() // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction(*) // expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected expression}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction(\) // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction(& : argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{invalid operands to binary expression ('float' and 'float')}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction(| : argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{invalid operands to binary expression ('float' and 'float')}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction(|| : argc ? i : argc) // expected-error 2 {{expected variable name, array element or array section}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction(foo : argc) //expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'float'}} expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'int'}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction(&& : argc)
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction(^ : T) // expected-error {{'T' does not refer to a value}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}} expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction(+ : o) // expected-error 2 {{no viable overloaded '='}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute private(i), reduction(+ : j), reduction(+ : q) // expected-error 4 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp parallel private(k)
+#pragma omp target
+#pragma omp teams distribute reduction(+ : p), reduction(+ : p) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction(+ : p), reduction(+ : p) // expected-error 2 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 2 {{previously referenced here}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp parallel shared(i)
+#pragma omp parallel reduction(min : i)
+#pragma omp target
+#pragma omp teams distribute reduction(max : j) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction(+ : fl)
+ for (int j=0; j<100; j++) foo();
+
+ return T();
+}
+
+namespace A {
+double x;
+#pragma omp threadprivate(x) // expected-note {{defined as threadprivate or thread local}}
+}
+namespace B {
+using A::x;
+}
+
+int main(int argc, char **argv) {
+ const int d = 5; // expected-note 2 {{'d' defined here}}
+ const int da[5] = {0}; // expected-note {{'da' defined here}}
+ int qa[5] = {0};
+ S4 e(4);
+ S5 g(5);
+ int i;
+ int &j = i; // expected-note 2 {{'j' defined here}}
+ S3 &p = k; // expected-note 2 {{'p' defined here}}
+ const int &r = da[i]; // expected-note {{'r' defined here}}
+ int &q = qa[i]; // expected-note {{'q' defined here}}
+ float fl;
+#pragma omp target
+#pragma omp teams distribute reduction // expected-error {{expected '(' after 'reduction'}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction + // expected-error {{expected '(' after 'reduction'}} expected-warning {{extra tokens at the end of '#pragma omp teams distribute' are ignored}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction( // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction(- // expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction() // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction(*) // expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected expression}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction(\) // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction(foo : argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max'}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction(| : argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction(|| : argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name, array element or array section}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction(~ : argc) // expected-error {{expected unqualified-id}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction(&& : argc)
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction(^ : S1) // expected-error {{'S1' does not refer to a value}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified list item cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction(& : e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{invalid operands to binary expression ('S4' and 'S4')}} expected-error {{calling a private constructor of class 'S5'}} expected-error {{invalid operands to binary expression ('S5' and 'S5')}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction(+ : h, k, B::x) // expected-error 2 {{threadprivate or thread local variable cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction(+ : o) // expected-error {{no viable overloaded '='}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute private(i), reduction(+ : j), reduction(+ : q) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp parallel private(k)
+#pragma omp target
+#pragma omp teams distribute reduction(+ : p), reduction(+ : p) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction(+ : p), reduction(+ : p) // expected-error {{variable can appear only once in OpenMP 'reduction' clause}} expected-note {{previously referenced here}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction(+ : r) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp parallel shared(i)
+#pragma omp parallel reduction(min : i)
+#pragma omp target
+#pragma omp teams distribute reduction(max : j) // expected-error {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute reduction(+ : fl)
+ for (int j=0; j<100; j++) foo();
+ static int m;
+#pragma omp target
+#pragma omp teams distribute reduction(+ : m) // OK
+ for (int j=0; j<100; j++) foo();
+
+ return tmain(argc) + tmain(fl); // expected-note {{in instantiation of function template specialization 'tmain<int>' requested here}} expected-note {{in instantiation of function template specialization 'tmain<float>' requested here}}
+}
diff --git a/test/OpenMP/teams_distribute_shared_messages.cpp b/test/OpenMP/teams_distribute_shared_messages.cpp
new file mode 100644
index 000000000000..b9e096ce1c24
--- /dev/null
+++ b/test/OpenMP/teams_distribute_shared_messages.cpp
@@ -0,0 +1,133 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}}
+extern S1 a;
+class S2 {
+ mutable int a;
+public:
+ S2():a(0) { }
+ S2(S2 &s2):a(s2.a) { }
+};
+const S2 b;
+const S2 ba[5];
+class S3 {
+ int a;
+public:
+ S3():a(0) { }
+ S3(S3 &s3):a(s3.a) { }
+};
+const S3 c;
+const S3 ca[5];
+extern const int f;
+class S4 {
+ int a;
+ S4();
+ S4(const S4 &s4);
+public:
+ S4(int v):a(v) { }
+};
+class S5 {
+ int a;
+ S5():a(0) {}
+ S5(const S5 &s5):a(s5.a) { }
+public:
+ S5(int v):a(v) { }
+};
+
+S3 h;
+#pragma omp threadprivate(h) // expected-note {{defined as threadprivate or thread local}}
+
+namespace A {
+double x;
+#pragma omp threadprivate(x) // expected-note {{defined as threadprivate or thread local}}
+}
+namespace B {
+using A::x;
+}
+
+int main(int argc, char **argv) {
+ const int d = 5;
+ const int da[5] = { 0 };
+ S4 e(4);
+ S5 g(5);
+ int i;
+ int &j = i;
+ #pragma omp target
+ #pragma omp teams distribute shared // expected-error {{expected '(' after 'shared'}}
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute shared ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute shared () // expected-error {{expected expression}}
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute shared (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute shared (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute shared (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute shared (argc)
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute shared (S1) // expected-error {{'S1' does not refer to a value}}
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute shared (a, b, c, d, f)
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute shared (argv[1]) // expected-error {{expected variable name}}
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute shared(ba)
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute shared(ca)
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute shared(da)
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute shared(e, g)
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute shared(h, B::x) // expected-error 2 {{threadprivate or thread local variable cannot be shared}}
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute private(i), shared(i) // expected-error {{private variable cannot be shared}} expected-note {{defined as private}}
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute firstprivate(i), shared(i) // expected-error {{firstprivate variable cannot be shared}} expected-note {{defined as firstprivate}}
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute private(i)
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute shared(i)
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute shared(j)
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute firstprivate(i)
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute shared(i)
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute shared(j)
+ for (int j=0; j<100; j++) foo();
+
+ return 0;
+}
diff --git a/test/OpenMP/teams_distribute_simd_aligned_messages.cpp b/test/OpenMP/teams_distribute_simd_aligned_messages.cpp
new file mode 100644
index 000000000000..95a85b2d0db9
--- /dev/null
+++ b/test/OpenMP/teams_distribute_simd_aligned_messages.cpp
@@ -0,0 +1,271 @@
+// RUN: %clang_cc1 -x c++ -std=c++11 -verify -fopenmp %s
+
+struct B {
+ static int ib[20]; // expected-note 0 {{'B::ib' declared here}}
+ static constexpr int bfoo() { return 8; }
+};
+namespace X {
+ B x; // expected-note {{'x' defined here}}
+};
+constexpr int bfoo() { return 4; }
+
+int **z;
+const int C1 = 1;
+const int C2 = 2;
+void test_aligned_colons(int *&rp)
+{
+ int *B = 0;
+
+#pragma omp target
+#pragma omp teams distribute simd aligned(B:bfoo())
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target
+#pragma omp teams distribute simd aligned(B::ib:B:bfoo()) // expected-error {{unexpected ':' in nested name specifier; did you mean '::'}}
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target
+#pragma omp teams distribute simd aligned(B:B::bfoo())
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target
+#pragma omp teams distribute simd aligned(z:B:bfoo()) // expected-error {{unexpected ':' in nested name specifier; did you mean '::'?}}
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target
+#pragma omp teams distribute simd aligned(B:B::bfoo())
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target
+#pragma omp teams distribute simd aligned(X::x : ::z) // expected-error {{integral constant expression must have integral or unscoped enumeration type, not 'int **'}} expected-error {{argument of aligned clause should be array, pointer, reference to array or reference to pointer, not 'B'}}
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target
+#pragma omp teams distribute simd aligned(B,rp,::z: X::x) // expected-error {{integral constant expression must have integral or unscoped enumeration type, not 'B'}}
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target
+#pragma omp teams distribute simd aligned(::z)
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target
+#pragma omp teams distribute simd aligned(B::bfoo()) // expected-error {{expected variable name}}
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target
+#pragma omp teams distribute simd aligned(B::ib,B:C1+C2) // expected-warning {{aligned clause will be ignored because the requested alignment is not a power of 2}}
+ for (int i = 0; i < 10; ++i) ;
+}
+
+// expected-note@+1 {{'num' defined here}}
+template<int L, class T, class N> T test_template(T* arr, N num) {
+ N i;
+ T sum = (T)0;
+ T ind2 = - num * L;
+ // Negative number is passed as L.
+
+#pragma omp target
+#pragma omp teams distribute simd aligned(arr:L) // expected-error {{argument to 'aligned' clause must be a strictly positive integer value}}
+ for (i = 0; i < num; ++i) {
+ T cur = arr[(int)ind2];
+ ind2 += L;
+ sum += cur;
+ }
+
+#pragma omp target
+#pragma omp teams distribute simd aligned(num:4) // expected-error {{argument of aligned clause should be array, pointer, reference to array or reference to pointer, not 'int'}}
+ for (i = 0; i < num; ++i);
+
+ return T();
+}
+
+template<int LEN> int test_warn() {
+ int *ind2 = 0;
+#pragma omp target
+#pragma omp teams distribute simd aligned(ind2:LEN) // expected-error {{argument to 'aligned' clause must be a strictly positive integer value}}
+ for (int i = 0; i < 100; i++) {
+ ind2 += LEN;
+ }
+ return 0;
+}
+
+struct S1; // expected-note 2 {{declared here}}
+extern S1 a; // expected-note {{'a' declared here}}
+class S2 {
+ mutable int a;
+public:
+ S2():a(0) { }
+};
+const S2 b; // expected-note 1 {{'b' defined here}}
+const S2 ba[5];
+class S3 {
+ int a;
+public:
+ S3():a(0) { }
+};
+const S3 ca[5];
+class S4 {
+ int a;
+ S4();
+public:
+ S4(int v):a(v) { }
+};
+class S5 {
+ int a;
+ S5():a(0) {}
+public:
+ S5(int v):a(v) { }
+};
+
+S3 h; // expected-note 2 {{'h' defined here}}
+#pragma omp threadprivate(h)
+
+template<class I, class C> int foomain(I argc, C **argv) {
+ I e(argc);
+ I g(argc);
+ int i; // expected-note {{declared here}} expected-note {{'i' defined here}}
+ // expected-note@+2 {{declared here}}
+ // expected-note@+1 {{reference to 'i' is not a constant expression}}
+ int &j = i;
+
+#pragma omp target
+#pragma omp teams distribute simd aligned // expected-error {{expected '(' after 'aligned'}}
+ for (I k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd aligned ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (I k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd aligned () // expected-error {{expected expression}}
+ for (I k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd aligned (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (I k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd aligned (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (I k = 0; k < argc; ++k) ++k;
+
+// FIXME: Should argc really be a pointer?
+#pragma omp target
+#pragma omp teams distribute simd aligned (*argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (I k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd aligned (argc : 5) // expected-warning {{aligned clause will be ignored because the requested alignment is not a power of 2}}
+ for (I k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd aligned (S1) // expected-error {{'S1' does not refer to a value}}
+ for (I k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd aligned (argv[1]) // expected-error {{expected variable name}}
+ for (I k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd aligned(e, g)
+ for (I k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd aligned(h) // expected-error {{argument of aligned clause should be array, pointer, reference to array or reference to pointer, not 'S3'}}
+ for (I k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd aligned(i) // expected-error {{argument of aligned clause should be array, pointer, reference to array or reference to pointer, not 'int'}}
+ for (I k = 0; k < argc; ++k) ++k;
+
+ #pragma omp parallel
+ {
+ int *v = 0;
+ I i;
+ #pragma omp target
+ #pragma omp teams distribute simd aligned(v:16)
+ for (I k = 0; k < argc; ++k) { i = k; v += 2; }
+ }
+ float *f;
+
+#pragma omp target
+#pragma omp teams distribute simd aligned(f)
+ for (I k = 0; k < argc; ++k) ++k;
+
+ int v = 0;
+
+#pragma omp target
+#pragma omp teams distribute simd aligned(f:j) // expected-note {{initializer of 'j' is not a constant expression}} expected-error {{expression is not an integral constant expression}}
+
+ for (I k = 0; k < argc; ++k) { ++k; v += j; }
+
+#pragma omp target
+#pragma omp teams distribute simd aligned(f)
+ for (I k = 0; k < argc; ++k) ++k;
+
+ return 0;
+}
+
+// expected-note@+1 2 {{'argc' defined here}}
+int main(int argc, char **argv) {
+ double darr[100];
+ // expected-note@+1 {{in instantiation of function template specialization 'test_template<-4, double, int>' requested here}}
+ test_template<-4>(darr, 4);
+ test_warn<4>(); // ok
+ // expected-note@+1 {{in instantiation of function template specialization 'test_warn<0>' requested here}}
+ test_warn<0>();
+
+ int i;
+ int &j = i;
+
+#pragma omp target
+#pragma omp teams distribute simd aligned // expected-error {{expected '(' after 'aligned'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd aligned ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd aligned () // expected-error {{expected expression}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd aligned (argv // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd aligned (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{argument of aligned clause should be array, pointer, reference to array or reference to pointer, not 'int'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute simd aligned (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute simd aligned (argc) // expected-error {{argument of aligned clause should be array, pointer, reference to array or reference to pointer, not 'int'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd aligned (S1) // expected-error {{'S1' does not refer to a value}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd aligned (a, b) // expected-error {{argument of aligned clause should be array, pointer, reference to array or reference to pointer, not 'S1'}} expected-error {{argument of aligned clause should be array, pointer, reference to array or reference to pointer, not 'S2'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd aligned (argv[1]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd aligned(h) // expected-error {{argument of aligned clause should be array, pointer, reference to array or reference to pointer, not 'S3'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ int *pargc = &argc;
+ // expected-note@+1 {{in instantiation of function template specialization 'foomain<int *, char>' requested here}}
+ foomain<int*,char>(pargc,argv);
+ return 0;
+}
+
diff --git a/test/OpenMP/teams_distribute_simd_ast_print.cpp b/test/OpenMP/teams_distribute_simd_ast_print.cpp
new file mode 100644
index 000000000000..aaf6745774c5
--- /dev/null
+++ b/test/OpenMP/teams_distribute_simd_ast_print.cpp
@@ -0,0 +1,239 @@
+// 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
+// expected-no-diagnostics
+
+#ifndef HEADER
+#define HEADER
+
+void foo() {}
+
+struct S {
+ S(): a(0) {}
+ S(int v) : a(v) {}
+ int a;
+ typedef int type;
+};
+
+template <typename T>
+class S7 : public T {
+protected:
+ T a;
+ S7() : a(0) {}
+
+public:
+ S7(typename T::type v) : a(v) {
+#pragma omp target
+#pragma omp teams distribute simd private(a) private(this->a) private(T::a)
+ for (int k = 0; k < a.a; ++k)
+ ++this->a.a;
+ }
+ S7 &operator=(S7 &s) {
+#pragma omp target
+#pragma omp teams distribute simd private(a) private(this->a)
+ for (int k = 0; k < s.a.a; ++k)
+ ++s.a.a;
+ return *this;
+ }
+ void foo() {
+ int b, argv, d, c, e, f;
+#pragma omp target
+#pragma omp teams distribute simd default(none), private(b) firstprivate(argv) shared(d) reduction(+:c) reduction(max:e) num_teams(f) thread_limit(d)
+ for (int k = 0; k < a.a; ++k)
+ ++a.a;
+ }
+ void bar() {
+ int arr[10];
+ const int alen = 16;
+ const int slen1 = 8;
+ const int slen2 = 8;
+#pragma omp target
+#pragma omp teams distribute simd simdlen(slen1) safelen(slen2) aligned(arr:alen)
+ for (int k = 0; k < a.a; ++k)
+ ++a.a;
+ }
+};
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute simd private(this->a) private(this->a) private(T::a)
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute simd private(this->a) private(this->a)
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute simd default(none) private(b) firstprivate(argv) shared(d) reduction(+: c) reduction(max: e) num_teams(f) thread_limit(d)
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute simd simdlen(slen1) safelen(slen2) aligned(arr: alen)
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute simd private(this->a) private(this->a) private(this->S::a)
+
+class S8 : public S7<S> {
+ S8() {}
+
+public:
+ S8(int v) : S7<S>(v){
+#pragma omp target
+#pragma omp teams distribute simd private(a) private(this->a) private(S7<S>::a)
+ for (int k = 0; k < a.a; ++k)
+ ++this->a.a;
+ }
+ S8 &operator=(S8 &s) {
+#pragma omp target
+#pragma omp teams distribute simd private(a) private(this->a)
+ for (int k = 0; k < s.a.a; ++k)
+ ++s.a.a;
+ return *this;
+ }
+ void bar() {
+ int b, argv, d, c, e, f;
+#pragma omp target
+#pragma omp teams distribute simd default(none), private(b) firstprivate(argv) shared(d) reduction(+:c) reduction(max:e) num_teams(f) thread_limit(d)
+ for (int k = 0; k < a.a; ++k)
+ ++a.a;
+ }
+ void foo() {
+ const int alen = 16;
+ const int slen1 = 8;
+ const int slen2 = 8;
+ int arr[10];
+#pragma omp target
+#pragma omp teams distribute simd simdlen(slen1) safelen(slen2) aligned(arr:alen)
+ for (int k = 0; k < a.a; ++k)
+ ++a.a;
+ }
+};
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute simd private(this->a) private(this->a) private(this->S7<S>::a)
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute simd private(this->a) private(this->a)
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute simd default(none) private(b) firstprivate(argv) shared(d) reduction(+: c) reduction(max: e) num_teams(f) thread_limit(d)
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute simd simdlen(slen1) safelen(slen2) aligned(arr: alen)
+
+template <class T, int N>
+T tmain(T argc) {
+ T b = argc, c, d, e, f, g;
+ static T a;
+// CHECK: static T a;
+ const T clen = 5;
+ const T alen = 16;
+ int arr[10];
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i=0; i < 2; ++i)
+ a = 2;
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute simd
+// CHECK-NEXT: for (int i = 0; i < 2; ++i)
+// CHECK-NEXT: a = 2;
+#pragma omp target
+#pragma omp teams distribute simd private(argc, b), firstprivate(c, d), collapse(2)
+ for (int i = 0; i < 10; ++i)
+ for (int j = 0; j < 10; ++j)
+ foo();
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute simd private(argc,b) firstprivate(c,d) collapse(2)
+// CHECK-NEXT: for (int i = 0; i < 10; ++i)
+// CHECK-NEXT: for (int j = 0; j < 10; ++j)
+// CHECK-NEXT: foo();
+ for (int i = 0; i < 10; ++i)
+ foo();
+// CHECK: for (int i = 0; i < 10; ++i)
+// CHECK-NEXT: foo();
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i)
+ foo();
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute simd
+// CHECK-NEXT: for (int i = 0; i < 10; ++i)
+// CHECK-NEXT: foo();
+#pragma omp target
+#pragma omp teams distribute simd default(none), private(b) firstprivate(argc) shared(d) reduction(+:c) reduction(max:e) num_teams(f) thread_limit(d)
+ for (int k = 0; k < 10; ++k)
+ e += d + argc;
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute simd default(none) private(b) firstprivate(argc) shared(d) reduction(+: c) reduction(max: e) num_teams(f) thread_limit(d)
+// CHECK-NEXT: for (int k = 0; k < 10; ++k)
+// CHECK-NEXT: e += d + argc;
+#pragma omp target
+#pragma omp teams distribute simd simdlen(clen-1) linear(d)
+ for (int k = 0; k < 10; ++k)
+ e += d + argc;
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute simd simdlen(clen - 1) linear(d)
+// CHECK-NEXT: for (int k = 0; k < 10; ++k)
+// CHECK-NEXT: e += d + argc;
+#pragma omp target
+#pragma omp teams distribute simd safelen(clen-1) aligned(arr:alen)
+ for (int k = 0; k < 10; ++k)
+ e += d + argc + arr[k];
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute simd safelen(clen - 1) aligned(arr: alen)
+// CHECK-NEXT: for (int k = 0; k < 10; ++k)
+// CHECK-NEXT: e += d + argc + arr[k];
+ return T();
+}
+
+int main (int argc, char **argv) {
+ int b = argc, c, d, e, f, g;
+ static int a;
+// CHECK: static int a;
+ const int clen = 5;
+ const int N = 10;
+ int arr[10];
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i=0; i < 2; ++i)
+ a = 2;
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute simd
+// CHECK-NEXT: for (int i = 0; i < 2; ++i)
+// CHECK-NEXT: a = 2;
+#pragma omp target
+#pragma omp teams distribute simd private(argc,b),firstprivate(argv, c), collapse(2)
+ for (int i = 0; i < 10; ++i)
+ for (int j = 0; j < 10; ++j)
+ foo();
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute simd private(argc,b) firstprivate(argv,c) collapse(2)
+// CHECK-NEXT: for (int i = 0; i < 10; ++i)
+// CHECK-NEXT: for (int j = 0; j < 10; ++j)
+// CHECK-NEXT: foo();
+ for (int i = 0; i < 10; ++i)
+ foo();
+// CHECK: for (int i = 0; i < 10; ++i)
+// CHECK-NEXT: foo();
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i)foo();
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute simd
+// CHECK-NEXT: for (int i = 0; i < 10; ++i)
+// CHECK-NEXT: foo();
+#pragma omp target
+#pragma omp teams distribute simd default(none), private(b) firstprivate(argc) shared(d) reduction(+:c) reduction(max:e) num_teams(f) thread_limit(d)
+ for (int k = 0; k < 10; ++k)
+ e += d + argc;
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute simd default(none) private(b) firstprivate(argc) shared(d) reduction(+: c) reduction(max: e) num_teams(f) thread_limit(d)
+// CHECK-NEXT: for (int k = 0; k < 10; ++k)
+// CHECK-NEXT: e += d + argc;
+#pragma omp target
+#pragma omp teams distribute simd simdlen(clen-1) linear(d)
+ for (int k = 0; k < 10; ++k)
+ e += d + argc;
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute simd simdlen(clen - 1) linear(d)
+// CHECK-NEXT: for (int k = 0; k < 10; ++k)
+// CHECK-NEXT: e += d + argc;
+#pragma omp target
+#pragma omp teams distribute simd safelen(clen-1) aligned(arr:N+6)
+ for (int k = 0; k < 10; ++k)
+ e += d + argc + arr[k];
+// CHECK: #pragma omp target
+// CHECK-NEXT: #pragma omp teams distribute simd safelen(clen - 1) aligned(arr: N + 6)
+// CHECK-NEXT: for (int k = 0; k < 10; ++k)
+// CHECK-NEXT: e += d + argc + arr[k];
+ return (0);
+}
+
+#endif
diff --git a/test/OpenMP/teams_distribute_simd_collapse_messages.cpp b/test/OpenMP/teams_distribute_simd_collapse_messages.cpp
new file mode 100644
index 000000000000..0f62be2861d1
--- /dev/null
+++ b/test/OpenMP/teams_distribute_simd_collapse_messages.cpp
@@ -0,0 +1,172 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+
+void foo() {
+}
+
+#if __cplusplus >= 201103L
+// expected-note@+2 4 {{declared here}}
+#endif
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}}
+
+template <class T, typename S, int N, int ST> // expected-note {{declared here}}
+T tmain(T argc, S **argv) { //expected-note 2 {{declared here}}
+#pragma omp target
+#pragma omp teams distribute simd collapse // expected-error {{expected '(' after 'collapse'}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute simd collapse ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = ST; i < N; i++)
+
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+#pragma omp target
+#pragma omp teams distribute simd collapse () // expected-error {{expected expression}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+// expected-error@+4 {{expected ')'}} expected-note@+4 {{to match this '('}}
+// expected-error@+3 2 {{expression is not an integral constant expression}}
+// expected-note@+2 2 {{read of non-const variable 'argc' is not allowed in a constant expression}}
+#pragma omp target
+#pragma omp teams distribute simd collapse (argc
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+// expected-error@+2 2 {{argument to 'collapse' clause must be a strictly positive integer value}}
+#pragma omp target
+#pragma omp teams distribute simd collapse (ST // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute simd collapse (1)) // expected-warning {{extra tokens at the end of '#pragma omp teams distribute simd' are ignored}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute simd collapse ((ST > 0) ? 1 + ST : 2) // expected-note 2 {{as specified in 'collapse' clause}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST]; // expected-error 2 {{expected 2 for loops after '#pragma omp teams distribute simd', but found only 1}}
+
+// expected-error@+7 2 {{directive '#pragma omp teams distribute simd' cannot contain more than one 'collapse' clause}}
+// expected-error@+6 2 {{argument to 'collapse' clause must be a strictly positive integer value}}
+// expected-error@+5 2 {{expression is not an integral constant expression}}
+#if __cplusplus >= 201103L
+// expected-note@+3 2 {{non-constexpr function 'foobool' cannot be used in a constant expression}}
+#endif
+#pragma omp target
+#pragma omp teams distribute simd collapse (foobool(argc)), collapse (true), collapse (-5)
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp distribute collapse (S) // expected-error {{'S' does not refer to a value}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#if __cplusplus <= 199711L
+ // expected-error@+5 2 {{expression is not an integral constant expression}}
+#else
+ // expected-error@+3 2 {{integral constant expression must have integral or unscoped enumeration type, not 'char *'}}
+#endif
+#pragma omp target
+#pragma omp teams distribute simd collapse (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute simd collapse (1)
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute simd collapse (N) // expected-error {{argument to 'collapse' clause must be a strictly positive integer value}}
+ for (T i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute simd collapse (2) // expected-note {{as specified in 'collapse' clause}}
+ foo(); // expected-error {{expected 2 for loops after '#pragma omp teams distribute simd'}}
+ return argc;
+}
+
+int main(int argc, char **argv) {
+#pragma omp target
+#pragma omp teams distribute simd collapse // expected-error {{expected '(' after 'collapse'}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target
+#pragma omp teams distribute simd collapse ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target
+#pragma omp teams distribute simd collapse () // expected-error {{expected expression}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target
+#pragma omp teams distribute simd collapse (4 // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-note {{as specified in 'collapse' clause}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4]; // expected-error {{expected 4 for loops after '#pragma omp teams distribute simd', but found only 1}}
+
+#pragma omp target
+#pragma omp teams distribute simd collapse (2+2)) // expected-warning {{extra tokens at the end of '#pragma omp teams distribute simd' are ignored}} expected-note {{as specified in 'collapse' clause}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4]; // expected-error {{expected 4 for loops after '#pragma omp teams distribute simd', but found only 1}}
+
+#if __cplusplus >= 201103L
+ // expected-note@+3 {{non-constexpr function 'foobool' cannot be used in a constant expression}}
+#endif
+#pragma omp target
+#pragma omp teams distribute simd collapse (foobool(1) > 0 ? 1 : 2) // expected-error {{expression is not an integral constant expression}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+// expected-error@+7 {{expression is not an integral constant expression}}
+// expected-error@+6 2 {{directive '#pragma omp teams distribute simd' cannot contain more than one 'collapse' clause}}
+// expected-error@+5 2 {{argument to 'collapse' clause must be a strictly positive integer value}}
+#if __cplusplus >= 201103L
+// expected-note@+3 {{non-constexpr function 'foobool' cannot be used in a constant expression}}
+#endif
+#pragma omp target
+#pragma omp teams distribute simd collapse (foobool(argc)), collapse (true), collapse (-5)
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target
+#pragma omp teams distribute simd collapse (S1) // expected-error {{'S1' does not refer to a value}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#if __cplusplus >= 201103L
+ // expected-error@+5 {{integral constant expression must have integral or unscoped enumeration type, not 'char *'}}
+#else
+ // expected-error@+3 {{expression is not an integral constant expression}}
+#endif
+#pragma omp target
+#pragma omp teams distribute simd collapse (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+// expected-error@+4 {{statement after '#pragma omp teams distribute simd' must be a for loop}}
+// expected-note@+2 {{in instantiation of function template specialization 'tmain<int, char, -1, -2>' requested here}}
+#pragma omp target
+#pragma omp teams distribute simd collapse(collapse(tmain<int, char, -1, -2>(argc, argv) // expected-error 2 {{expected ')'}} expected-note 2 {{to match this '('}}
+ foo();
+
+#pragma omp target
+#pragma omp teams distribute simd collapse (2) // expected-note {{as specified in 'collapse' clause}}
+ foo(); // expected-error {{expected 2 for loops after '#pragma omp teams distribute simd'}}
+
+// expected-note@+1 {{in instantiation of function template specialization 'tmain<int, char, 1, 0>' requested here}}
+ return tmain<int, char, 1, 0>(argc, argv);
+}
+
diff --git a/test/OpenMP/teams_distribute_simd_default_messages.cpp b/test/OpenMP/teams_distribute_simd_default_messages.cpp
new file mode 100644
index 000000000000..a6685b9202ea
--- /dev/null
+++ b/test/OpenMP/teams_distribute_simd_default_messages.cpp
@@ -0,0 +1,30 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo();
+
+int main(int argc, char **argv) {
+ #pragma omp target
+ #pragma omp teams distribute simd default // expected-error {{expected '(' after 'default'}}
+ for (int i=0; i<200; i++) foo();
+ #pragma omp target
+ #pragma omp teams distribute simd default ( // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i=0; i<200; i++) foo();
+ #pragma omp target
+ #pragma omp teams distribute simd default () // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+ for (int i=0; i<200; i++) foo();
+ #pragma omp target
+ #pragma omp teams distribute simd default (none // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i=0; i<200; i++) foo();
+ #pragma omp target
+ #pragma omp teams distribute simd default (shared), default(shared) // expected-error {{directive '#pragma omp teams distribute simd' cannot contain more than one 'default' clause}}
+ for (int i=0; i<200; i++) foo();
+ #pragma omp target
+ #pragma omp teams distribute simd default (x) // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+ for (int i=0; i<200; i++) foo();
+
+ #pragma omp target
+ #pragma omp teams distribute simd default(none)
+ for (int i=0; i<200; i++) ++argc; // expected-error {{variable 'argc' must have explicitly specified data sharing attributes}}
+
+ return 0;
+}
diff --git a/test/OpenMP/teams_distribute_simd_dist_schedule_messages.cpp b/test/OpenMP/teams_distribute_simd_dist_schedule_messages.cpp
new file mode 100644
index 000000000000..5274204b1ac6
--- /dev/null
+++ b/test/OpenMP/teams_distribute_simd_dist_schedule_messages.cpp
@@ -0,0 +1,104 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}} expected-note {{declared here}}
+
+template <class T, int N>
+T tmain(T argc) {
+ T b = argc, c, d, e, f, g;
+ char ** argv;
+ static T a;
+// CHECK: static T a;
+
+#pragma omp target
+#pragma omp teams distribute simd dist_schedule // expected-error {{expected '(' after 'dist_schedule'}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd dist_schedule ( // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd dist_schedule () // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd dist_schedule (static // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd dist_schedule (static, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd dist_schedule (argc)) // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}} expected-warning {{extra tokens at the end of '#pragma omp teams distribute simd' are ignored}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd dist_schedule (static, argc > 0 ? argv[1] : argv[2]) // expected-error2 {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd dist_schedule (static), dist_schedule (static, 1) // expected-error {{directive '#pragma omp teams distribute simd' cannot contain more than one 'dist_schedule' clause}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd dist_schedule (static, S1) // expected-error {{'S1' does not refer to a value}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd dist_schedule (static, argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error3 {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ for (int i = 0; i < 10; ++i) foo();
+
+ return T();
+}
+
+int main(int argc, char **argv) {
+#pragma omp target
+#pragma omp teams distribute simd dist_schedule // expected-error {{expected '(' after 'dist_schedule'}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd dist_schedule ( // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd dist_schedule () // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd dist_schedule (static // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd dist_schedule (static, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd dist_schedule (argc)) // expected-error {{expected 'static' in OpenMP clause 'dist_schedule'}} expected-warning {{extra tokens at the end of '#pragma omp teams distribute simd' are ignored}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd dist_schedule (static, argc > 0 ? argv[1] : argv[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd dist_schedule (static), dist_schedule (static, 1) // expected-error {{directive '#pragma omp teams distribute simd' cannot contain more than one 'dist_schedule' clause}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd dist_schedule (static, S1) // expected-error {{'S1' does not refer to a value}}
+ for (int i = 0; i < 10; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd dist_schedule (static, argv[1]=2) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 0; i < 10; ++i) foo();
+
+ return (tmain<int, 5>(argc) + tmain<char, 1>(argv[0][0])); // expected-note {{in instantiation of function template specialization 'tmain<int, 5>' requested here}} expected-note {{in instantiation of function template specialization 'tmain<char, 1>' requested here}}
+}
diff --git a/test/OpenMP/teams_distribute_simd_firstprivate_messages.cpp b/test/OpenMP/teams_distribute_simd_firstprivate_messages.cpp
new file mode 100644
index 000000000000..324672c14129
--- /dev/null
+++ b/test/OpenMP/teams_distribute_simd_firstprivate_messages.cpp
@@ -0,0 +1,152 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}} expected-note{{forward declaration of 'S1'}}
+extern S1 a;
+class S2 {
+ mutable int a;
+
+public:
+ S2() : a(0) {}
+ S2(const S2 &s2) : a(s2.a) {}
+ static float S2s;
+ static const float S2sc;
+};
+const float S2::S2sc = 0;
+const S2 b;
+const S2 ba[5];
+class S3 {
+ int a;
+ S3 &operator=(const S3 &s3);
+
+public:
+ S3() : a(0) {} // expected-note {{candidate constructor not viable: requires 0 arguments, but 1 was provided}}
+ S3(S3 &s3) : a(s3.a) {} // expected-note {{candidate constructor not viable: 1st argument ('const S3') would lose const qualifier}}
+};
+const S3 c;
+const S3 ca[5];
+extern const int f;
+class S4 {
+ int a;
+ S4();
+ S4(const S4 &s4);
+public:
+ S4(int v):a(v) { }
+};
+class S5 {
+ int a;
+ S5():a(0) {}
+ S5(const S5 &s5):a(s5.a) { }
+public:
+ S5(int v):a(v) { }
+};
+class S6 {
+ int a;
+public:
+ S6() : a(0) { }
+};
+
+S3 h;
+#pragma omp threadprivate(h) // expected-note {{defined as threadprivate or thread local}}
+
+int main(int argc, char **argv) {
+ const int d = 5;
+ const int da[5] = { 0 };
+ S4 e(4);
+ S5 g(5);
+ S6 p;
+ int i;
+ int &j = i;
+
+#pragma omp target
+#pragma omp teams distribute simd firstprivate // expected-error {{expected '(' after 'firstprivate'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd firstprivate ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd firstprivate () // expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd firstprivate (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd firstprivate (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd firstprivate (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd firstprivate (argc)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd firstprivate (S1) // expected-error {{'S1' does not refer to a value}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd firstprivate (a, b, c, d, f) // expected-error {{firstprivate variable with incomplete type 'S1'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd firstprivate (argv[1]) // expected-error {{expected variable name}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd firstprivate(ba)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd firstprivate(ca) // expected-error {{no matching constructor for initialization of 'S3'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd firstprivate(da)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd firstprivate(S2::S2s)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd firstprivate(S2::S2sc)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd firstprivate(h) // expected-error {{threadprivate or thread local variable cannot be firstprivate}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd private(i), firstprivate(i) // expected-error {{private variable cannot be firstprivate}} expected-note 2 {{defined as private}}
+ for (i = 0; i < argc; ++i) foo(); // expected-error {{loop iteration variable in the associated loop of 'omp teams distribute simd' directive may not be private, predetermined as linear}}
+
+#pragma omp target
+#pragma omp teams distribute simd firstprivate(i)
+ for (j = 0; j < argc; ++j) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd firstprivate(i) // expected-note {{defined as firstprivate}}
+ for (i = 0; i < argc; ++i) foo(); // expected-error {{loop iteration variable in the associated loop of 'omp teams distribute simd' directive may not be firstprivate, predetermined as linear}}
+
+#pragma omp target
+#pragma omp teams distribute simd firstprivate(j)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd lastprivate(argc), firstprivate(argc) // OK
+ for (i = 0; i < argc; ++i) foo();
+
+ return 0;
+}
diff --git a/test/OpenMP/teams_distribute_simd_lastprivate_messages.cpp b/test/OpenMP/teams_distribute_simd_lastprivate_messages.cpp
new file mode 100644
index 000000000000..4c715bf2ce30
--- /dev/null
+++ b/test/OpenMP/teams_distribute_simd_lastprivate_messages.cpp
@@ -0,0 +1,272 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note 2 {{declared here}} expected-note 2 {{forward declaration of 'S1'}}
+extern S1 a;
+class S2 {
+ mutable int a;
+
+public:
+ S2() : a(0) {}
+ S2(S2 &s2) : a(s2.a) {}
+ const S2 &operator =(const S2&) const;
+ S2 &operator =(const S2&);
+ static float S2s; // expected-note {{static data member is predetermined as shared}}
+ static const float S2sc;
+};
+const float S2::S2sc = 0; // expected-note {{static data member is predetermined as shared}}
+const S2 b;
+const S2 ba[5];
+class S3 {
+ int a;
+ S3 &operator=(const S3 &s3); // expected-note 2 {{implicitly declared private here}}
+
+public:
+ S3() : a(0) {}
+ S3(S3 &s3) : a(s3.a) {}
+};
+const S3 c; // expected-note {{global variable is predetermined as shared}}
+const S3 ca[5]; // expected-note {{global variable is predetermined as shared}}
+extern const int f; // expected-note {{global variable is predetermined as shared}}
+class S4 {
+ int a;
+ S4(); // expected-note 3 {{implicitly declared private here}}
+ S4(const S4 &s4);
+
+public:
+ S4(int v) : a(v) {}
+};
+class S5 {
+ int a;
+ S5() : a(0) {} // expected-note {{implicitly declared private here}}
+
+public:
+ S5(const S5 &s5) : a(s5.a) {}
+ S5(int v) : a(v) {}
+};
+class S6 {
+ int a;
+ S6() : a(0) {}
+
+public:
+ S6(const S6 &s6) : a(s6.a) {}
+ S6(int v) : a(v) {}
+};
+
+S3 h;
+#pragma omp threadprivate(h) // expected-note 2 {{defined as threadprivate or thread local}}
+
+template <class I, class C>
+int foomain(int argc, char **argv) {
+ I e(4);
+ I g(5);
+ int i;
+ int &j = i;
+#pragma omp target
+#pragma omp teams distribute simd lastprivate // expected-error {{expected '(' after 'lastprivate'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd lastprivate( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd lastprivate() // expected-error {{expected expression}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd lastprivate(argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd lastprivate(argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd lastprivate(argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd lastprivate(argc)
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd lastprivate(S1) // expected-error {{'S1' does not refer to a value}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd lastprivate(a, b) // expected-error {{lastprivate variable with incomplete type 'S1'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd lastprivate(argv[1]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd lastprivate(e, g) // expected-error 2 {{calling a private constructor of class 'S4'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd lastprivate(h) // expected-error {{threadprivate or thread local variable cannot be lastprivate}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ int v = 0;
+#pragma omp target
+#pragma omp teams distribute simd lastprivate(i)
+ for (int k = 0; k < argc; ++k) {
+ i = k;
+ v += i;
+ }
+
+#pragma omp target
+#pragma omp teams distribute simd lastprivate(j) private(i)
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd lastprivate(i)
+ for (int k = 0; k < argc; ++k) ++k;
+
+ return 0;
+}
+
+void bar(S4 a[2]) {
+#pragma omp target
+#pragma omp teams distribute simd lastprivate(a)
+ for (int i = 0; i < 2; ++i) foo();
+}
+
+namespace A {
+double x;
+#pragma omp threadprivate(x) // expected-note {{defined as threadprivate or thread local}}
+}
+namespace B {
+using A::x;
+}
+
+int main(int argc, char **argv) {
+ const int d = 5; // expected-note {{constant variable is predetermined as shared}}
+ const int da[5] = {0}; // expected-note {{constant variable is predetermined as shared}}
+ S4 e(4);
+ S5 g(5);
+ S3 m;
+ S6 n(2);
+ int i;
+ int &j = i;
+#pragma omp target
+#pragma omp teams distribute simd lastprivate // expected-error {{expected '(' after 'lastprivate'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd lastprivate( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd lastprivate() // expected-error {{expected expression}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd lastprivate(argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd lastprivate(argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd lastprivate(argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd lastprivate(argc)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd lastprivate(S1) // expected-error {{'S1' does not refer to a value}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd lastprivate(a, b, c, d, f) // expected-error {{lastprivate variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be lastprivate}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd lastprivate(argv[1]) // expected-error {{expected variable name}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd lastprivate(2 * 2) // expected-error {{expected variable name}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd lastprivate(ba)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd lastprivate(ca) // expected-error {{shared variable cannot be lastprivate}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd lastprivate(da) // expected-error {{shared variable cannot be lastprivate}}
+ for (i = 0; i < argc; ++i) foo();
+
+ int xa;
+#pragma omp target
+#pragma omp teams distribute simd lastprivate(xa) // OK
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd lastprivate(S2::S2s) // expected-error {{shared variable cannot be lastprivate}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd lastprivate(S2::S2sc) // expected-error {{shared variable cannot be lastprivate}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd lastprivate(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd lastprivate(m) // expected-error {{'operator=' is a private member of 'S3'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd lastprivate(h) // expected-error {{threadprivate or thread local variable cannot be lastprivate}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd lastprivate(B::x) // expected-error {{threadprivate or thread local variable cannot be lastprivate}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd private(xa), lastprivate(xa) // expected-error {{private variable cannot be lastprivate}} expected-note {{defined as private}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd lastprivate(xa)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd lastprivate(j)
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd firstprivate(m) lastprivate(m) // expected-error {{'operator=' is a private member of 'S3'}}
+ for (i = 0; i < argc; ++i) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd lastprivate(n) firstprivate(n) // OK
+ for (i = 0; i < argc; ++i) foo();
+
+ static int si;
+#pragma omp target
+#pragma omp teams distribute simd lastprivate(si) // OK
+ for (i = 0; i < argc; ++i) si = i + 1;
+
+ return foomain<S4, S5>(argc, argv); // expected-note {{in instantiation of function template specialization 'foomain<S4, S5>' requested here}}
+}
diff --git a/test/OpenMP/teams_distribute_simd_linear_messages.cpp b/test/OpenMP/teams_distribute_simd_linear_messages.cpp
new file mode 100644
index 000000000000..6bfdb16274a5
--- /dev/null
+++ b/test/OpenMP/teams_distribute_simd_linear_messages.cpp
@@ -0,0 +1,293 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+namespace X {
+ int x;
+};
+
+struct B {
+ static int ib; // expected-note {{'B::ib' declared here}}
+ static int bfoo() { return 8; }
+};
+
+int bfoo() { return 4; }
+
+int z;
+const int C1 = 1;
+const int C2 = 2;
+void test_linear_colons()
+{
+ int B = 0;
+
+#pragma omp target
+#pragma omp teams distribute simd linear(B:bfoo())
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target
+#pragma omp teams distribute simd linear(B::ib:B:bfoo()) // expected-error {{unexpected ':' in nested name specifier; did you mean '::'}}
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target
+#pragma omp teams distribute simd linear(B:ib) // expected-error {{use of undeclared identifier 'ib'; did you mean 'B::ib'}}
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target
+#pragma omp teams distribute simd linear(z:B:ib) // expected-error {{unexpected ':' in nested name specifier; did you mean '::'?}}
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target
+#pragma omp teams distribute simd linear(B:B::bfoo())
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target
+#pragma omp teams distribute simd linear(X::x : ::z)
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target
+#pragma omp teams distribute simd linear(B,::z, X::x)
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target
+#pragma omp teams distribute simd linear(::z)
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target
+#pragma omp teams distribute simd linear(B::bfoo()) // expected-error {{expected variable name}}
+ for (int i = 0; i < 10; ++i) ;
+
+#pragma omp target
+#pragma omp teams distribute simd linear(B::ib,B:C1+C2)
+ for (int i = 0; i < 10; ++i) ;
+}
+
+template<int L, class T, class N> T test_template(T* arr, N num) {
+ N i;
+ T sum = (T)0;
+ T ind2 = - num * L; // expected-note {{'ind2' defined here}}
+
+#pragma omp target
+#pragma omp teams distribute simd linear(ind2:L) // expected-error {{argument of a linear clause should be of integral or pointer type}}
+ for (i = 0; i < num; ++i) {
+ T cur = arr[(int)ind2];
+ ind2 += L;
+ sum += cur;
+ }
+ return T();
+}
+
+template<int LEN> int test_warn() {
+ int ind2 = 0;
+ #pragma omp target
+ #pragma omp teams distribute simd linear(ind2:LEN) // expected-warning {{zero linear step (ind2 should probably be const)}}
+ for (int i = 0; i < 100; i++) {
+ ind2 += LEN;
+ }
+ return ind2;
+}
+
+struct S1; // expected-note 2 {{declared here}} expected-note 2 {{forward declaration of 'S1'}}
+extern S1 a;
+class S2 {
+ mutable int a;
+public:
+ S2():a(0) { }
+};
+const S2 b; // expected-note 2 {{'b' defined here}}
+const S2 ba[5];
+class S3 {
+ int a;
+public:
+ S3():a(0) { }
+};
+const S3 ca[5];
+class S4 {
+ int a;
+ S4();
+public:
+ S4(int v):a(v) { }
+};
+class S5 {
+ int a;
+ S5():a(0) {}
+public:
+ S5(int v):a(v) { }
+};
+
+S3 h;
+#pragma omp threadprivate(h) // expected-note 2 {{defined as threadprivate or thread local}}
+
+template<class I, class C> int foomain(I argc, C **argv) {
+ I e(4);
+ I g(5);
+ int i;
+ int &j = i;
+
+#pragma omp target
+#pragma omp teams distribute simd linear // expected-error {{expected '(' after 'linear'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd linear ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd linear () // expected-error {{expected expression}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd linear (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd linear (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd linear (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd linear (argc : 5)
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd linear (S1) // expected-error {{'S1' does not refer to a value}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd linear (a, b:B::ib) // expected-error {{linear variable with incomplete type 'S1'}} expected-error {{const-qualified variable cannot be linear}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd linear (argv[1]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd linear(e, g)
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd linear(h) // expected-error {{threadprivate or thread local variable cannot be linear}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd linear(i)
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp parallel
+ {
+ int v = 0;
+ int i;
+ #pragma omp target
+ #pragma omp teams distribute simd linear(v:i)
+ for (int k = 0; k < argc; ++k) { i = k; v += i; }
+ }
+
+#pragma omp target
+#pragma omp teams distribute simd linear(j)
+ for (int k = 0; k < argc; ++k) ++k;
+
+ int v = 0;
+
+#pragma omp target
+#pragma omp teams distribute simd linear(v:j)
+ for (int k = 0; k < argc; ++k) { ++k; v += j; }
+
+#pragma omp target
+#pragma omp teams distribute simd linear(i)
+ for (int k = 0; k < argc; ++k) ++k;
+ return 0;
+}
+
+namespace A {
+double x;
+#pragma omp threadprivate(x) // expected-note {{defined as threadprivate or thread local}}
+}
+namespace C {
+using A::x;
+}
+
+int main(int argc, char **argv) {
+ double darr[100];
+ // expected-note@+1 {{in instantiation of function template specialization 'test_template<-4, double, int>' requested here}}
+ test_template<-4>(darr, 4);
+ // expected-note@+1 {{in instantiation of function template specialization 'test_warn<0>' requested here}}
+ test_warn<0>();
+
+ S4 e(4); // expected-note {{'e' defined here}}
+ S5 g(5); // expected-note {{'g' defined here}}
+ int i;
+ int &j = i;
+
+#pragma omp target
+#pragma omp teams distribute simd linear // expected-error {{expected '(' after 'linear'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd linear ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd linear () // expected-error {{expected expression}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd linear (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd linear (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd linear (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd linear (argc)
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd linear (S1) // expected-error {{'S1' does not refer to a value}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+
+#pragma omp target
+#pragma omp teams distribute simd linear (a, b) // expected-error {{linear variable with incomplete type 'S1'}} expected-error {{const-qualified variable cannot be linear}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd linear (argv[1]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd linear(e, g) // expected-error {{argument of a linear clause should be of integral or pointer type, not 'S4'}} expected-error {{argument of a linear clause should be of integral or pointer type, not 'S5'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd linear(h, C::x) // expected-error 2 {{threadprivate or thread local variable cannot be linear}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp parallel
+ {
+ int i;
+ #pragma omp target
+ #pragma omp teams distribute simd linear(i)
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute simd linear(i : 4)
+ for (int k = 0; k < argc; ++k) { ++k; i += 4; }
+ }
+
+#pragma omp target
+#pragma omp teams distribute simd linear(j)
+ for (int k = 0; k < argc; ++k) ++k;
+
+#pragma omp target
+#pragma omp teams distribute simd linear(i)
+ for (int k = 0; k < argc; ++k) ++k;
+
+ foomain<int,char>(argc,argv); // expected-note {{in instantiation of function template specialization 'foomain<int, char>' requested here}}
+ return 0;
+}
+
diff --git a/test/OpenMP/teams_distribute_simd_loop_messages.cpp b/test/OpenMP/teams_distribute_simd_loop_messages.cpp
new file mode 100644
index 000000000000..742bc7451e93
--- /dev/null
+++ b/test/OpenMP/teams_distribute_simd_loop_messages.cpp
@@ -0,0 +1,716 @@
+// RUN: %clang_cc1 -fsyntax-only -fopenmp -x c++ -std=c++11 -fexceptions -fcxx-exceptions -verify %s
+
+class S {
+ int a;
+ S() : a(0) {}
+
+public:
+ S(int v) : a(v) {}
+ S(const S &s) : a(s.a) {}
+};
+
+static int sii;
+// expected-note@+1 {{defined as threadprivate or thread local}}
+#pragma omp threadprivate(sii)
+static int globalii;
+
+int test_iteration_spaces() {
+ const int N = 100;
+ float a[N], b[N], c[N];
+ int ii, jj, kk;
+ float fii;
+ double dii;
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; i += 1) {
+ c[i] = a[i] + b[i];
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (char i = 0; i < 10; i++) {
+ c[i] = a[i] + b[i];
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (char i = 0; i < 10; i += '\1') {
+ c[i] = a[i] + b[i];
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (long long i = 0; i < 10; i++) {
+ c[i] = a[i] + b[i];
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-error@+1 {{expression must have integral or unscoped enumeration type, not 'double'}}
+ for (long long i = 0; i < 10; i += 1.5) {
+ c[i] = a[i] + b[i];
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (long long i = 0; i < 'z'; i += 1u) {
+ c[i] = a[i] + b[i];
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-error@+1 {{variable must be of integer or random access iterator type}}
+ for (float fi = 0; fi < 10.0; fi++) {
+ c[(int)fi] = a[(int)fi] + b[(int)fi];
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-error@+1 {{variable must be of integer or random access iterator type}}
+ for (double fi = 0; fi < 10.0; fi++) {
+ c[(int)fi] = a[(int)fi] + b[(int)fi];
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (int &ref = ii; ref < 10; ref++) {
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (int i; i < 10; i++)
+ c[i] = a[i];
+
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (int i = 0, j = 0; i < 10; ++i)
+ c[i] = a[i];
+
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (; ii < 10; ++ii)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-warning@+2 {{expression result unused}}
+// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (ii + 1; ii < 10; ++ii)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (c[ii] = 0; ii < 10; ++ii)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute simd
+// Ok to skip parenthesises.
+ for (((ii)) = 0; ii < 10; ++ii)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
+ for (int i = 0; i; i++)
+ c[i] = a[i];
+
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-error@+2 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'i'}}
+ for (int i = 0; jj < kk; ii++)
+ c[i] = a[i];
+
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
+ for (int i = 0; !!i; i++)
+ c[i] = a[i];
+
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
+ for (int i = 0; i != 1; i++)
+ c[i] = a[i];
+
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'i'}}
+ for (int i = 0;; i++)
+ c[i] = a[i];
+
+// Ok.
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 11; i > 10; i--)
+ c[i] = a[i];
+
+// Ok.
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i)
+ c[i] = a[i];
+
+// Ok.
+#pragma omp target
+#pragma omp teams distribute simd
+ for (ii = 0; ii < 10; ++ii)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+ for (ii = 0; ii < 10; ++jj)
+ c[ii] = a[jj];
+
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+ for (ii = 0; ii < 10; ++++ii)
+ c[ii] = a[ii];
+
+// Ok but undefined behavior (in general, cannot check that incr
+// is really loop-invariant).
+#pragma omp target
+#pragma omp teams distribute simd
+ for (ii = 0; ii < 10; ii = ii + ii)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-error@+1 {{expression must have integral or unscoped enumeration type, not 'float'}}
+ for (ii = 0; ii < 10; ii = ii + 1.0f)
+ c[ii] = a[ii];
+
+// Ok - step was converted to integer type.
+#pragma omp target
+#pragma omp teams distribute simd
+ for (ii = 0; ii < 10; ii = ii + (int)1.1f)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+ for (ii = 0; ii < 10; jj = ii + 2)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-warning@+2 {{relational comparison result unused}}
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+ for (ii = 0; ii<10; jj> kk + 2)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+ for (ii = 0; ii < 10;)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-warning@+2 {{expression result unused}}
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+ for (ii = 0; ii < 10; !ii)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+ for (ii = 0; ii < 10; ii ? ++ii : ++jj)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'ii'}}
+ for (ii = 0; ii < 10; ii = ii < 10)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}}
+ for (ii = 0; ii < 10; ii = ii + 0)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}}
+ for (ii = 0; ii < 10; ii = ii + (int)(0.8 - 0.45))
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}}
+ for (ii = 0; (ii) < 10; ii -= 25)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}}
+ for (ii = 0; (ii < 10); ii -= 0)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-note@+2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+1 {{increment expression must cause 'ii' to decrease on each iteration of OpenMP for loop}}
+ for (ii = 0; ii > 10; (ii += 0))
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}}
+ for (ii = 0; ii < 10; (ii) = (1 - 1) + (ii))
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-note@+2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+1 {{increment expression must cause 'ii' to decrease on each iteration of OpenMP for loop}}
+ for ((ii = 0); ii > 10; (ii -= 0))
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'ii' to increase on each iteration of OpenMP for loop}}
+ for (ii = 0; (ii < 10); (ii -= 0))
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute simd firstprivate(ii) // expected-note {{defined as firstprivate}}
+// expected-error@+1 {{loop iteration variable in the associated loop of 'omp teams distribute simd' directive may not be firstprivate, predetermined as linear}}
+ for (ii = 0; ii < 10; ii++)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute simd private(ii) // expected-note {{defined as private}}
+// expected-error@+1 {{loop iteration variable in the associated loop of 'omp teams distribute simd' directive may not be private, predetermined as linear}}
+ for (ii = 0; ii < 10; ii++)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute simd lastprivate(ii) // expected-note {{defined as lastprivate}}
+// expected-error@+1 {{loop iteration variable in the associated loop of 'omp teams distribute simd' directive may not be lastprivate, predetermined as linear}}
+ for (ii = 0; ii < 10; ii++)
+ c[ii] = a[ii];
+
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-error@+1 {{loop iteration variable in the associated loop of 'omp teams distribute simd' directive may not be threadprivate or thread local, predetermined as linear}}
+ for (sii = 0; sii < 10; sii++)
+ c[sii] = a[sii];
+
+ {
+#pragma omp target
+#pragma omp teams distribute simd collapse(2)
+ for (ii = 0; ii < 10; ii += 1)
+ for (globalii = 0; globalii < 10; globalii += 1)
+ c[globalii] += a[globalii] + ii;
+ }
+
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-error@+1 {{statement after '#pragma omp teams distribute simd' must be a for loop}}
+ for (auto &item : a) {
+ item = item + 1;
+ }
+
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'i' to increase on each iteration of OpenMP for loop}}
+ for (unsigned i = 9; i < 10; i--) {
+ c[i] = a[i] + b[i];
+ }
+
+ int(*lb)[4] = nullptr;
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int(*p)[4] = lb; p < lb + 8; ++p) {
+ }
+
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (int a{0}; a < 10; ++a) {
+ }
+
+ return 0;
+}
+
+// Iterators allowed in openmp for-loops.
+namespace std {
+struct random_access_iterator_tag {};
+template <class Iter>
+struct iterator_traits {
+ typedef typename Iter::difference_type difference_type;
+ typedef typename Iter::iterator_category iterator_category;
+};
+template <class Iter>
+typename iterator_traits<Iter>::difference_type
+distance(Iter first, Iter last) { return first - last; }
+}
+class Iter0 {
+public:
+ Iter0() {}
+ Iter0(const Iter0 &) {}
+ Iter0 operator++() { return *this; }
+ Iter0 operator--() { return *this; }
+ bool operator<(Iter0 a) { return true; }
+};
+// expected-note@+2 {{candidate function not viable: no known conversion from 'GoodIter' to 'Iter0' for 1st argument}}
+// expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'Iter0' for 1st argument}}
+int operator-(Iter0 a, Iter0 b) { return 0; }
+class Iter1 {
+public:
+ Iter1(float f = 0.0f, double d = 0.0) {}
+ Iter1(const Iter1 &) {}
+ Iter1 operator++() { return *this; }
+ Iter1 operator--() { return *this; }
+ bool operator<(Iter1 a) { return true; }
+ bool operator>=(Iter1 a) { return false; }
+};
+class GoodIter {
+public:
+ GoodIter() {}
+ GoodIter(const GoodIter &) {}
+ GoodIter(int fst, int snd) {}
+ GoodIter &operator=(const GoodIter &that) { return *this; }
+ GoodIter &operator=(const Iter0 &that) { return *this; }
+ GoodIter &operator+=(int x) { return *this; }
+ explicit GoodIter(void *) {}
+ GoodIter operator++() { return *this; }
+ GoodIter operator--() { return *this; }
+ bool operator!() { return true; }
+ bool operator<(GoodIter a) { return true; }
+ bool operator<=(GoodIter a) { return true; }
+ bool operator>=(GoodIter a) { return false; }
+ typedef int difference_type;
+ typedef std::random_access_iterator_tag iterator_category;
+};
+// expected-note@+2 {{candidate function not viable: no known conversion from 'const Iter0' to 'GoodIter' for 2nd argument}}
+// expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'GoodIter' for 1st argument}}
+int operator-(GoodIter a, GoodIter b) { return 0; }
+// expected-note@+1 3 {{candidate function not viable: requires single argument 'a', but 2 arguments were provided}}
+GoodIter operator-(GoodIter a) { return a; }
+// expected-note@+2 {{candidate function not viable: no known conversion from 'const Iter0' to 'int' for 2nd argument}}
+// expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'GoodIter' for 1st argument}}
+GoodIter operator-(GoodIter a, int v) { return GoodIter(); }
+// expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter0' to 'GoodIter' for 1st argument}}
+GoodIter operator+(GoodIter a, int v) { return GoodIter(); }
+// expected-note@+2 {{candidate function not viable: no known conversion from 'GoodIter' to 'int' for 1st argument}}
+// expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter1' to 'int' for 1st argument}}
+GoodIter operator-(int v, GoodIter a) { return GoodIter(); }
+// expected-note@+1 2 {{candidate function not viable: no known conversion from 'Iter0' to 'int' for 1st argument}}
+GoodIter operator+(int v, GoodIter a) { return GoodIter(); }
+
+int test_with_random_access_iterator() {
+ GoodIter begin, end;
+ Iter0 begin0, end0;
+#pragma omp target
+#pragma omp teams distribute simd
+ for (GoodIter I = begin; I < end; ++I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (GoodIter &I = begin; I < end; ++I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute simd
+ for (GoodIter I = begin; I >= end; --I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (GoodIter I(begin); I < end; ++I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (GoodIter I(nullptr); I < end; ++I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (GoodIter I(0); I < end; ++I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (GoodIter I(1, 2); I < end; ++I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute simd
+ for (begin = GoodIter(0); begin < end; ++begin)
+ ++begin;
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-error@+2 {{invalid operands to binary expression ('GoodIter' and 'const Iter0')}}
+// expected-error@+1 {{could not calculate number of iterations calling 'operator-' with upper and lower loop bounds}}
+ for (begin = begin0; begin < end; ++begin)
+ ++begin;
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-error@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (++begin; begin < end; ++begin)
+ ++begin;
+#pragma omp target
+#pragma omp teams distribute simd
+ for (begin = end; begin < end; ++begin)
+ ++begin;
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'I'}}
+ for (GoodIter I = begin; I - I; ++I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'I'}}
+ for (GoodIter I = begin; begin < end; ++I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', or '>=') of loop variable 'I'}}
+ for (GoodIter I = begin; !I; ++I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-note@+2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+1 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}}
+ for (GoodIter I = begin; I >= end; I = I + 1)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute simd
+ for (GoodIter I = begin; I >= end; I = I - 1)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'I'}}
+ for (GoodIter I = begin; I >= end; I = -I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-note@+2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+1 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}}
+ for (GoodIter I = begin; I >= end; I = 2 + I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-error@+1 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'I'}}
+ for (GoodIter I = begin; I >= end; I = 2 - I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-error@+1 {{invalid operands to binary expression ('Iter0' and 'int')}}
+ for (Iter0 I = begin0; I < end0; ++I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute simd
+// Initializer is constructor without params.
+// expected-error@+2 {{invalid operands to binary expression ('Iter0' and 'int')}}
+// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (Iter0 I; I < end0; ++I)
+ ++I;
+ Iter1 begin1, end1;
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-error@+2 {{invalid operands to binary expression ('Iter1' and 'Iter1')}}
+// expected-error@+1 {{could not calculate number of iterations calling 'operator-' with upper and lower loop bounds}}
+ for (Iter1 I = begin1; I < end1; ++I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-note@+2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+1 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}}
+ for (Iter1 I = begin1; I >= end1; ++I)
+ ++I;
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-error@+4 {{invalid operands to binary expression ('Iter1' and 'float')}}
+// expected-error@+3 {{could not calculate number of iterations calling 'operator-' with upper and lower loop bounds}}
+// Initializer is constructor with all default params.
+// expected-warning@+1 {{initialization clause of OpenMP for loop is not in canonical form ('var = init' or 'T var = init')}}
+ for (Iter1 I; I < end1; ++I) {
+ }
+ return 0;
+}
+
+template <typename IT, int ST>
+class TC {
+public:
+ int dotest_lt(IT begin, IT end) {
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'I' to increase on each iteration of OpenMP for loop}}
+ for (IT I = begin; I < end; I = I + ST) {
+ ++I;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-note@+2 {{loop step is expected to be positive due to this condition}}
+// expected-error@+1 {{increment expression must cause 'I' to increase on each iteration of OpenMP for loop}}
+ for (IT I = begin; I <= end; I += ST) {
+ ++I;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+ for (IT I = begin; I < end; ++I) {
+ ++I;
+ }
+ }
+
+ static IT step() {
+ return IT(ST);
+ }
+};
+template <typename IT, int ST = 0>
+int dotest_gt(IT begin, IT end) {
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-note@+2 2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+1 2 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}}
+ for (IT I = begin; I >= end; I = I + ST) {
+ ++I;
+ }
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-note@+2 2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+1 2 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}}
+ for (IT I = begin; I >= end; I += ST) {
+ ++I;
+ }
+
+#pragma omp target
+#pragma omp teams distribute simd
+// expected-note@+2 {{loop step is expected to be negative due to this condition}}
+// expected-error@+1 {{increment expression must cause 'I' to decrease on each iteration of OpenMP for loop}}
+ for (IT I = begin; I >= end; ++I) {
+ ++I;
+ }
+
+#pragma omp target
+#pragma omp teams distribute simd
+ for (IT I = begin; I < end; I += TC<int, ST>::step()) {
+ ++I;
+ }
+}
+
+void test_with_template() {
+ GoodIter begin, end;
+ TC<GoodIter, 100> t1;
+ TC<GoodIter, -100> t2;
+ t1.dotest_lt(begin, end);
+ t2.dotest_lt(begin, end); // expected-note {{in instantiation of member function 'TC<GoodIter, -100>::dotest_lt' requested here}}
+ dotest_gt(begin, end); // expected-note {{in instantiation of function template specialization 'dotest_gt<GoodIter, 0>' requested here}}
+ dotest_gt<unsigned, -10>(0, 100); // expected-note {{in instantiation of function template specialization 'dotest_gt<unsigned int, -10>' requested here}}
+}
+
+void test_loop_break() {
+ const int N = 100;
+ float a[N], b[N], c[N];
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; i++) {
+ c[i] = a[i] + b[i];
+ for (int j = 0; j < 10; ++j) {
+ if (a[i] > b[j])
+ break; // OK in nested loop
+ }
+ switch (i) {
+ case 1:
+ b[i]++;
+ break;
+ default:
+ break;
+ }
+ if (c[i] > 10)
+ break; // expected-error {{'break' statement cannot be used in OpenMP for loop}}
+
+ if (c[i] > 11)
+ break; // expected-error {{'break' statement cannot be used in OpenMP for loop}}
+ }
+
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; i++) {
+ for (int j = 0; j < 10; j++) {
+ c[i] = a[i] + b[i];
+ if (c[i] > 10) {
+ if (c[i] < 20) {
+ break; // OK
+ }
+ }
+ }
+ }
+}
+
+void test_loop_eh() {
+ const int N = 100;
+ float a[N], b[N], c[N];
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; i++) {
+ c[i] = a[i] + b[i];
+ try { // expected-error {{'try' statement cannot be used in OpenMP simd region}}
+ for (int j = 0; j < 10; ++j) {
+ if (a[i] > b[j])
+ throw a[i]; // expected-error {{throw' statement cannot be used in OpenMP simd region}}
+ }
+ throw a[i]; // expected-error {{throw' statement cannot be used in OpenMP simd region}}
+ } catch (float f) {
+ if (f > 0.1)
+ throw a[i]; // expected-error {{throw' statement cannot be used in OpenMP simd region}}
+ return; // expected-error {{cannot return from OpenMP region}}
+ }
+ switch (i) {
+ case 1:
+ b[i]++;
+ break;
+ default:
+ break;
+ }
+ for (int j = 0; j < 10; j++) {
+ if (c[i] > 10)
+ throw c[i]; // expected-error {{throw' statement cannot be used in OpenMP simd region}}
+ }
+ }
+ if (c[9] > 10)
+ throw c[9]; // OK
+
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < 10; ++i) {
+ struct S {
+ void g() { throw 0; }
+ };
+ }
+}
+
+void test_loop_firstprivate_lastprivate() {
+ S s(4);
+#pragma omp target
+#pragma omp teams distribute simd lastprivate(s) firstprivate(s)
+ for (int i = 0; i < 16; ++i)
+ ;
+}
+
+void test_ordered() {
+#pragma omp target
+#pragma omp teams distribute simd ordered // expected-error {{unexpected OpenMP clause 'ordered' in directive '#pragma omp teams distribute simd'}}
+ for (int i = 0; i < 16; ++i)
+ ;
+}
+
+void test_nowait() {
+#pragma omp target
+// expected-error@+1 2 {{unexpected OpenMP clause 'nowait' in directive '#pragma omp teams distribute simd'}}
+#pragma omp teams distribute simd nowait nowait // expected-error {{directive '#pragma omp teams distribute simd' cannot contain more than one 'nowait' clause}}
+ 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
new file mode 100644
index 000000000000..9095caf38787
--- /dev/null
+++ b/test/OpenMP/teams_distribute_simd_messages.cpp
@@ -0,0 +1,109 @@
+// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+
+void foo() {
+}
+
+static int pvt;
+#pragma omp threadprivate(pvt)
+
+#pragma omp teams distribute simd // expected-error {{unexpected OpenMP directive '#pragma omp teams distribute simd'}}
+
+int main(int argc, char **argv) {
+#pragma omp target
+#pragma omp teams distribute simd { // expected-warning {{extra tokens at the end of '#pragma omp teams distribute simd' are ignored}}
+ for (int i = 0; i < argc; ++i)
+ foo();
+#pragma omp target
+#pragma omp teams distribute simd ( // expected-warning {{extra tokens at the end of '#pragma omp teams distribute simd' are ignored}}
+ for (int i = 0; i < argc; ++i)
+ foo();
+#pragma omp target
+#pragma omp teams distribute simd[ // expected-warning {{extra tokens at the end of '#pragma omp teams distribute simd' are ignored}}
+ for (int i = 0; i < argc; ++i)
+ foo();
+#pragma omp target
+#pragma omp teams distribute simd] // expected-warning {{extra tokens at the end of '#pragma omp teams distribute simd' are ignored}}
+ for (int i = 0; i < argc; ++i)
+ foo();
+#pragma omp target
+#pragma omp teams distribute simd) // expected-warning {{extra tokens at the end of '#pragma omp teams distribute simd' are ignored}}
+ for (int i = 0; i < argc; ++i)
+ foo();
+#pragma omp target
+#pragma omp teams distribute simd } // expected-warning {{extra tokens at the end of '#pragma omp teams distribute simd' are ignored}}
+ for (int i = 0; i < argc; ++i)
+ foo();
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < argc; ++i)
+ foo();
+// expected-warning@+2 {{extra tokens at the end of '#pragma omp teams distribute simd' are ignored}}
+#pragma omp target
+#pragma omp teams distribute simd unknown()
+ for (int i = 0; i < argc; ++i)
+ foo();
+L1:
+ for (int i = 0; i < argc; ++i)
+ foo();
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < argc; ++i)
+ foo();
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < argc; ++i) {
+ goto L1; // expected-error {{use of undeclared label 'L1'}}
+ argc++;
+ }
+
+ for (int i = 0; i < 10; ++i) {
+ switch (argc) {
+ case (0):
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < argc; ++i) {
+ foo();
+ break; // expected-error {{'break' statement cannot be used in OpenMP for loop}}
+ continue;
+ }
+ default:
+ break;
+ }
+ }
+#pragma omp target
+#pragma omp teams distribute simd default(none)
+ for (int i = 0; i < 10; ++i)
+ ++argc; // expected-error {{ariable 'argc' must have explicitly specified data sharing attributes}}
+
+ goto L2; // expected-error {{use of undeclared label 'L2'}}
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < argc; ++i)
+ L2:
+ foo();
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int i = 0; i < argc; ++i) {
+ return 1; // expected-error {{cannot return from OpenMP region}}
+ }
+
+ [[]] // expected-error {{an attribute list cannot appear here}}
+#pragma omp target
+#pragma omp teams distribute simd
+ for (int n = 0; n < 100; ++n) {
+ }
+
+#pragma omp target
+#pragma omp teams distribute simd copyin(pvt) // expected-error {{unexpected OpenMP clause 'copyin' in directive '#pragma omp teams distribute simd'}}
+ for (int n = 0; n < 100; ++n) {}
+
+ return 0;
+}
+
+void test_ordered() {
+#pragma omp target
+#pragma omp teams distribute simd ordered // expected-error {{unexpected OpenMP clause 'ordered' in directive '#pragma omp teams distribute simd'}}
+ for (int i = 0; i < 16; ++i)
+ ;
+}
+
diff --git a/test/OpenMP/teams_distribute_simd_num_teams_messages.cpp b/test/OpenMP/teams_distribute_simd_num_teams_messages.cpp
new file mode 100644
index 000000000000..e65025a317ee
--- /dev/null
+++ b/test/OpenMP/teams_distribute_simd_num_teams_messages.cpp
@@ -0,0 +1,111 @@
+// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 100 -o - %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note 2 {{declared here}}
+
+template <typename T, int C> // expected-note {{declared here}}
+T tmain(T argc) {
+ char **a;
+#pragma omp target
+#pragma omp teams distribute simd num_teams(C)
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute simd num_teams(T) // expected-error {{'T' does not refer to a value}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute simd num_teams // expected-error {{expected '(' after 'num_teams'}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute simd num_teams( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute simd num_teams() // expected-error {{expected expression}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute simd num_teams(argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute simd num_teams(argc)) // expected-warning {{extra tokens at the end of '#pragma omp teams distribute simd' are ignored}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute simd num_teams(argc > 0 ? a[1] : a[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute simd num_teams(argc + argc)
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute simd num_teams(argc), num_teams (argc+1) // expected-error {{directive '#pragma omp teams distribute simd' cannot contain more than one 'num_teams' clause}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute simd num_teams(S1) // expected-error {{'S1' does not refer to a value}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute simd num_teams(-2) // expected-error {{argument to 'num_teams' clause must be a strictly positive integer value}}
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute simd num_teams(-10u)
+ for (int i=0; i<100; i++) foo();
+#pragma omp target
+#pragma omp teams distribute simd num_teams(3.14) // expected-error 2 {{expression must have integral or unscoped enumeration type, not 'double'}}
+ for (int i=0; i<100; i++) foo();
+
+ return 0;
+}
+
+int main(int argc, char **argv) {
+#pragma omp target
+#pragma omp teams distribute simd num_teams // expected-error {{expected '(' after 'num_teams'}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd num_teams ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd num_teams () // expected-error {{expected expression}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd num_teams (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd num_teams (argc)) // expected-warning {{extra tokens at the end of '#pragma omp teams distribute simd' are ignored}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd num_teams (argc > 0 ? argv[1] : argv[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd num_teams (argc + argc)
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd num_teams (argc), num_teams (argc+1) // expected-error {{directive '#pragma omp teams distribute simd' cannot contain more than one 'num_teams' clause}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd num_teams (S1) // expected-error {{'S1' does not refer to a value}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd num_teams (-2) // expected-error {{argument to 'num_teams' clause must be a strictly positive integer value}}
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd num_teams (-10u)
+ for (int i=0; i<100; i++) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd num_teams (3.14) // expected-error {{expression must have integral or unscoped enumeration type, not 'double'}}
+ for (int i=0; i<100; i++) foo();
+
+ return tmain<int, 10>(argc); // expected-note {{in instantiation of function template specialization 'tmain<int, 10>' requested here}}
+}
diff --git a/test/OpenMP/teams_distribute_simd_private_messages.cpp b/test/OpenMP/teams_distribute_simd_private_messages.cpp
new file mode 100644
index 000000000000..90442130d263
--- /dev/null
+++ b/test/OpenMP/teams_distribute_simd_private_messages.cpp
@@ -0,0 +1,146 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}} expected-note {{forward declaration of 'S1'}}
+extern S1 a;
+class S2 {
+ mutable int a;
+public:
+ S2():a(0) { }
+ static float S2s; // expected-note {{predetermined as shared}}
+};
+const S2 b;
+const S2 ba[5];
+class S3 {
+ int a;
+public:
+ S3():a(0) { }
+};
+const S3 c; // expected-note {{predetermined as shared}}
+const S3 ca[5]; // expected-note {{predetermined as shared}}
+extern const int f; // expected-note {{predetermined as shared}}
+class S4 {
+ int a;
+ S4(); // expected-note {{implicitly declared private here}}
+public:
+ S4(int v):a(v) { }
+};
+class S5 {
+ int a;
+ S5():a(0) {} // expected-note {{implicitly declared private here}}
+public:
+ S5(int v):a(v) { }
+};
+
+S3 h;
+#pragma omp threadprivate(h) // expected-note {{defined as threadprivate or thread local}}
+
+
+int main(int argc, char **argv) {
+ const int d = 5; // expected-note {{predetermined as shared}}
+ const int da[5] = { 0 }; // expected-note {{predetermined as shared}}
+ S4 e(4);
+ S5 g(5);
+ int i;
+ int &j = i;
+
+ #pragma omp target
+ #pragma omp teams distribute simd private // expected-error {{expected '(' after 'private'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute simd private ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute simd private () // expected-error {{expected expression}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute simd private (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute simd private (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute simd private (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute simd private (argc)
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute simd private (S1) // expected-error {{'S1' does not refer to a value}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute simd private (a, b, c, d, f) // expected-error {{private variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be private}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute simd private (argv[1]) // expected-error {{expected variable name}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute simd private(ba)
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute simd private(ca) // expected-error {{shared variable cannot be private}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute simd private(da) // expected-error {{shared variable cannot be private}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute simd private(S2::S2s) // expected-error {{shared variable cannot be private}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute simd private(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute simd private(h) // expected-error {{threadprivate or thread local variable cannot be private}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute simd shared(i)
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute simd firstprivate(i), private(i) // expected-error {{firstprivate variable cannot be private}} expected-note {{defined as firstprivate}}
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute simd private(j)
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp target
+ #pragma omp teams distribute simd reduction(+:i)
+ for (int k = 0; k < argc; ++k) ++k;
+
+ #pragma omp distribute private(i)
+ for (int k = 0; k < 10; ++k) {
+ #pragma omp target
+ #pragma omp teams distribute simd private(i)
+ for (int x = 0; x < 10; ++x) foo();
+ }
+
+ #pragma omp target
+ #pragma omp teams distribute simd firstprivate(i)
+ for (int k = 0; k < 10; ++k) {
+ }
+
+ return 0;
+}
diff --git a/test/OpenMP/teams_distribute_simd_reduction_messages.cpp b/test/OpenMP/teams_distribute_simd_reduction_messages.cpp
new file mode 100644
index 000000000000..879ec688dcb5
--- /dev/null
+++ b/test/OpenMP/teams_distribute_simd_reduction_messages.cpp
@@ -0,0 +1,303 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}} expected-note 4 {{forward declaration of 'S1'}}
+extern S1 a;
+class S2 {
+ mutable int a;
+ S2 &operator+(const S2 &arg) { return (*this); } // expected-note 3 {{implicitly declared private here}}
+
+public:
+ S2() : a(0) {}
+ S2(S2 &s2) : a(s2.a) {}
+ static float S2s; // expected-note 2 {{static data member is predetermined as shared}}
+ static const float S2sc;
+};
+const float S2::S2sc = 0; // expected-note 2 {{'S2sc' defined here}}
+S2 b; // expected-note 3 {{'b' defined here}}
+const S2 ba[5]; // expected-note 2 {{'ba' defined here}}
+class S3 {
+ int a;
+
+public:
+ int b;
+ S3() : a(0) {}
+ S3(const S3 &s3) : a(s3.a) {}
+ S3 operator+(const S3 &arg1) { return arg1; }
+};
+int operator+(const S3 &arg1, const S3 &arg2) { return 5; }
+S3 c; // expected-note 3 {{'c' defined here}}
+const S3 ca[5]; // expected-note 2 {{'ca' defined here}}
+extern const int f; // expected-note 4 {{'f' declared here}}
+class S4 {
+ int a;
+ S4(); // expected-note {{implicitly declared private here}}
+ S4(const S4 &s4);
+ S4 &operator+(const S4 &arg) { return (*this); }
+
+public:
+ S4(int v) : a(v) {}
+};
+S4 &operator&=(S4 &arg1, S4 &arg2) { return arg1; }
+class S5 {
+ int a;
+ S5() : a(0) {} // expected-note {{implicitly declared private here}}
+ S5(const S5 &s5) : a(s5.a) {}
+ S5 &operator+(const S5 &arg);
+
+public:
+ S5(int v) : a(v) {}
+};
+class S6 { // expected-note 3 {{candidate function (the implicit copy assignment operator) not viable: no known conversion from 'int' to 'const S6' for 1st argument}}
+#if __cplusplus >= 201103L // C++11 or later
+// expected-note@-2 3 {{candidate function (the implicit move assignment operator) not viable}}
+#endif
+ int a;
+
+public:
+ S6() : a(6) {}
+ operator int() { return 6; }
+} o;
+
+S3 h, k;
+#pragma omp threadprivate(h) // expected-note 2 {{defined as threadprivate or thread local}}
+
+template <class T> // expected-note {{declared here}}
+T tmain(T argc) {
+ const T d = T(); // expected-note 4 {{'d' defined here}}
+ const T da[5] = {T()}; // expected-note 2 {{'da' defined here}}
+ T qa[5] = {T()};
+ T i;
+ T &j = i; // expected-note 4 {{'j' defined here}}
+ S3 &p = k; // expected-note 2 {{'p' defined here}}
+ const T &r = da[(int)i]; // expected-note 2 {{'r' defined here}}
+ T &q = qa[(int)i]; // expected-note 2 {{'q' defined here}}
+ T fl;
+#pragma omp target
+#pragma omp teams distribute simd reduction // expected-error {{expected '(' after 'reduction'}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction + // expected-error {{expected '(' after 'reduction'}} expected-warning {{extra tokens at the end of '#pragma omp teams distribute simd' are ignored}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction( // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction(- // expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction() // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction(*) // expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected expression}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction(\) // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction(& : argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{invalid operands to binary expression ('float' and 'float')}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction(| : argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{invalid operands to binary expression ('float' and 'float')}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction(|| : argc ? i : argc) // expected-error 2 {{expected variable name, array element or array section}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction(foo : argc) //expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'float'}} expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'int'}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction(&& : argc)
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction(^ : T) // expected-error {{'T' does not refer to a value}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}} expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction(+ : o) // expected-error 2 {{no viable overloaded '='}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd private(i), reduction(+ : j), reduction(+ : q) // expected-error 4 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp parallel private(k)
+#pragma omp target
+#pragma omp teams distribute simd reduction(+ : p), reduction(+ : p) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction(+ : p), reduction(+ : p) // expected-error 2 {{variable can appear only once in OpenMP 'reduction' clause}} expected-note 2 {{previously referenced here}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp parallel shared(i)
+#pragma omp parallel reduction(min : i)
+#pragma omp target
+#pragma omp teams distribute simd reduction(max : j) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction(+ : fl)
+ for (int j=0; j<100; j++) foo();
+
+ return T();
+}
+
+namespace A {
+double x;
+#pragma omp threadprivate(x) // expected-note {{defined as threadprivate or thread local}}
+}
+namespace B {
+using A::x;
+}
+
+int main(int argc, char **argv) {
+ const int d = 5; // expected-note 2 {{'d' defined here}}
+ const int da[5] = {0}; // expected-note {{'da' defined here}}
+ int qa[5] = {0};
+ S4 e(4);
+ S5 g(5);
+ int i;
+ int &j = i; // expected-note 2 {{'j' defined here}}
+ S3 &p = k; // expected-note 2 {{'p' defined here}}
+ const int &r = da[i]; // expected-note {{'r' defined here}}
+ int &q = qa[i]; // expected-note {{'q' defined here}}
+ float fl;
+#pragma omp target
+#pragma omp teams distribute simd reduction // expected-error {{expected '(' after 'reduction'}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction + // expected-error {{expected '(' after 'reduction'}} expected-warning {{extra tokens at the end of '#pragma omp teams distribute simd' are ignored}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction( // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction(- // expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction() // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction(*) // expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected expression}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction(\) // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction(foo : argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max'}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction(| : argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction(|| : argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name, array element or array section}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction(~ : argc) // expected-error {{expected unqualified-id}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction(&& : argc)
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction(^ : S1) // expected-error {{'S1' does not refer to a value}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified list item cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction(& : e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{invalid operands to binary expression ('S4' and 'S4')}} expected-error {{calling a private constructor of class 'S5'}} expected-error {{invalid operands to binary expression ('S5' and 'S5')}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction(+ : h, k, B::x) // expected-error 2 {{threadprivate or thread local variable cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction(+ : o) // expected-error {{no viable overloaded '='}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd private(i), reduction(+ : j), reduction(+ : q) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp parallel private(k)
+#pragma omp target
+#pragma omp teams distribute simd reduction(+ : p), reduction(+ : p) // expected-error 2 {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction(+ : p), reduction(+ : p) // expected-error {{variable can appear only once in OpenMP 'reduction' clause}} expected-note {{previously referenced here}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction(+ : r) // expected-error {{const-qualified list item cannot be reduction}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp parallel shared(i)
+#pragma omp parallel reduction(min : i)
+#pragma omp target
+#pragma omp teams distribute simd reduction(max : j) // expected-error {{argument of OpenMP clause 'reduction' must reference the same object in all threads}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd reduction(+ : fl)
+ for (int j=0; j<100; j++) foo();
+ static int m;
+#pragma omp target
+#pragma omp teams distribute simd reduction(+ : m) // OK
+ for (int j=0; j<100; j++) foo();
+
+ return tmain(argc) + tmain(fl); // expected-note {{in instantiation of function template specialization 'tmain<int>' requested here}} expected-note {{in instantiation of function template specialization 'tmain<float>' requested here}}
+}
diff --git a/test/OpenMP/teams_distribute_simd_safelen_messages.cpp b/test/OpenMP/teams_distribute_simd_safelen_messages.cpp
new file mode 100644
index 000000000000..a323c0883c5b
--- /dev/null
+++ b/test/OpenMP/teams_distribute_simd_safelen_messages.cpp
@@ -0,0 +1,155 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+
+void foo() {
+}
+
+#if __cplusplus >= 201103L
+// expected-note@+2 4 {{declared here}}
+#endif
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}}
+
+template <class T, typename S, int N, int ST> // expected-note {{declared here}}
+T tmain(T argc, S **argv) { //expected-note 2 {{declared here}}
+
+#pragma omp target
+#pragma omp teams distribute simd safelen // expected-error {{expected '(' after 'safelen'}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute simd safelen ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute simd safelen () // expected-error {{expected expression}}
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute simd safelen (argc // expected-note {{to match this '('}} expected-error 2 {{expression is not an integral constant expression}} expected-note 2 {{read of non-const variable 'argc' is not allowed in a constant expression}} expected-error {{expected ')'}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute simd safelen (ST // expected-error {{argument to 'safelen' clause must be a strictly positive integer value}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute simd safelen (1)) // expected-warning {{extra tokens at the end of '#pragma omp teams distribute simd' are ignored}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute simd safelen ((ST > 0) ? 1 + ST : 2)
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#if __cplusplus >= 201103L
+ // expected-note@+3 2 {{non-constexpr function 'foobool' cannot be used in a constant expression}}
+#endif
+#pragma omp target
+#pragma omp teams distribute simd safelen (foobool(argc)), safelen (true), safelen (-5) // expected-error 2 {{directive '#pragma omp teams distribute simd' cannot contain more than one 'safelen' clause}} expected-error 2 {{argument to 'safelen' clause must be a strictly positive integer value}} expected-error 2 {{expression is not an integral constant expression}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute simd safelen (S) // expected-error {{'S' does not refer to a value}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#if __cplusplus <= 199711L
+ // expected-error@+5 2 {{expression is not an integral constant expression}}
+#else
+ // expected-error@+3 2 {{integral constant expression must have integral or unscoped enumeration type, not 'char *'}}
+#endif
+#pragma omp target
+#pragma omp teams distribute simd safelen (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute simd safelen (4)
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute simd safelen (N) // expected-error {{argument to 'safelen' clause must be a strictly positive integer value}}
+ for (T i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+ return argc;
+}
+
+int main(int argc, char **argv) {
+#pragma omp target
+#pragma omp teams distribute simd safelen // expected-error {{expected '(' after 'safelen'}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target
+#pragma omp teams distribute simd safelen ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target
+#pragma omp teams distribute simd safelen () // expected-error {{expected expression}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target
+#pragma omp teams distribute simd safelen (4 // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target
+#pragma omp teams distribute simd safelen (2+2)) // expected-warning {{extra tokens at the end of '#pragma omp teams distribute simd' are ignored}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#if __cplusplus >= 201103L
+ // expected-note@+3 {{non-constexpr function 'foobool' cannot be used in a constant expression}}
+#endif
+#pragma omp target
+#pragma omp teams distribute simd safelen (foobool(1) > 0 ? 1 : 2) // expected-error {{expression is not an integral constant expression}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#if __cplusplus >= 201103L
+ // expected-note@+3 {{non-constexpr function 'foobool' cannot be used in a constant expression}}
+#endif
+#pragma omp target
+#pragma omp teams distribute simd safelen (foobool(argc)), safelen (true), safelen (-5) // expected-error 2 {{argument to 'safelen' clause must be a strictly positive integer value}} expected-error 2 {{directive '#pragma omp teams distribute simd' cannot contain more than one 'safelen' clause}} expected-error {{expression is not an integral constant expression}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target
+#pragma omp teams distribute simd safelen (S1) // expected-error {{'S1' does not refer to a value}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#if __cplusplus <= 199711L
+ // expected-error@+5 {{expression is not an integral constant expression}}
+#else
+ // expected-error@+3 {{integral constant expression must have integral or unscoped enumeration type, not 'char *'}}
+#endif
+#pragma omp target
+#pragma omp teams distribute simd safelen (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+ // expected-note@+2 {{in instantiation of function template specialization 'tmain<int, char, -1, -2>' requested here}}
+#pragma omp target
+#pragma omp teams distribute simd safelen(safelen(tmain<int, char, -1, -2>(argc, argv) // expected-error 2 {{expected ')'}} expected-note 2 {{to match this '('}}
+ foo(); // expected-error {{statement after '#pragma omp teams distribute simd' must be a for loop}}
+
+ // expected-note@+1 {{in instantiation of function template specialization 'tmain<int, char, 12, 4>' requested here}}
+ return tmain<int, char, 12, 4>(argc, argv);
+}
+
diff --git a/test/OpenMP/teams_distribute_simd_shared_messages.cpp b/test/OpenMP/teams_distribute_simd_shared_messages.cpp
new file mode 100644
index 000000000000..cd963e8469a8
--- /dev/null
+++ b/test/OpenMP/teams_distribute_simd_shared_messages.cpp
@@ -0,0 +1,127 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}}
+extern S1 a;
+class S2 {
+ mutable int a;
+public:
+ S2():a(0) { }
+ S2(S2 &s2):a(s2.a) { }
+};
+const S2 b;
+const S2 ba[5];
+class S3 {
+ int a;
+public:
+ S3():a(0) { }
+ S3(S3 &s3):a(s3.a) { }
+};
+const S3 c;
+const S3 ca[5];
+extern const int f;
+class S4 {
+ int a;
+ S4();
+ S4(const S4 &s4);
+public:
+ S4(int v):a(v) { }
+};
+class S5 {
+ int a;
+ S5():a(0) {}
+ S5(const S5 &s5):a(s5.a) { }
+public:
+ S5(int v):a(v) { }
+};
+
+S3 h;
+#pragma omp threadprivate(h) // expected-note {{defined as threadprivate or thread local}}
+
+namespace A {
+double x;
+#pragma omp threadprivate(x) // expected-note {{defined as threadprivate or thread local}}
+}
+namespace B {
+using A::x;
+}
+
+int main(int argc, char **argv) {
+ const int d = 5;
+ const int da[5] = { 0 };
+ S4 e(4);
+ S5 g(5);
+ int i;
+ int &j = i;
+ #pragma omp target
+ #pragma omp teams distribute simd shared // expected-error {{expected '(' after 'shared'}}
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute simd shared ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute simd shared () // expected-error {{expected expression}}
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute simd shared (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute simd shared (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute simd shared (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute simd shared (argc)
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute simd shared (S1) // expected-error {{'S1' does not refer to a value}}
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute simd shared (a, b, c, d, f)
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute simd shared (argv[1]) // expected-error {{expected variable name}}
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute simd shared(ba)
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute simd shared(ca)
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute simd shared(da)
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute simd shared(e, g)
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute simd shared(h, B::x) // expected-error 2 {{threadprivate or thread local variable cannot be shared}}
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute simd private(i), shared(i) // expected-error {{private variable cannot be shared}} expected-note {{defined as private}}
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute simd firstprivate(i), shared(i) // expected-error {{firstprivate variable cannot be shared}} expected-note {{defined as firstprivate}}
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute simd private(i)
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute simd shared(i)
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute simd shared(j)
+ for (int j=0; j<100; j++) foo();
+ #pragma omp target
+ #pragma omp teams distribute simd firstprivate(i)
+ for (int j=0; j<100; j++) foo();
+
+ return 0;
+}
diff --git a/test/OpenMP/teams_distribute_simd_simdlen_messages.cpp b/test/OpenMP/teams_distribute_simd_simdlen_messages.cpp
new file mode 100644
index 000000000000..a323c0883c5b
--- /dev/null
+++ b/test/OpenMP/teams_distribute_simd_simdlen_messages.cpp
@@ -0,0 +1,155 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+// RUN: %clang_cc1 -verify -fopenmp -std=c++98 %s
+// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+
+void foo() {
+}
+
+#if __cplusplus >= 201103L
+// expected-note@+2 4 {{declared here}}
+#endif
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}}
+
+template <class T, typename S, int N, int ST> // expected-note {{declared here}}
+T tmain(T argc, S **argv) { //expected-note 2 {{declared here}}
+
+#pragma omp target
+#pragma omp teams distribute simd safelen // expected-error {{expected '(' after 'safelen'}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute simd safelen ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute simd safelen () // expected-error {{expected expression}}
+ for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute simd safelen (argc // expected-note {{to match this '('}} expected-error 2 {{expression is not an integral constant expression}} expected-note 2 {{read of non-const variable 'argc' is not allowed in a constant expression}} expected-error {{expected ')'}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute simd safelen (ST // expected-error {{argument to 'safelen' clause must be a strictly positive integer value}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute simd safelen (1)) // expected-warning {{extra tokens at the end of '#pragma omp teams distribute simd' are ignored}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute simd safelen ((ST > 0) ? 1 + ST : 2)
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#if __cplusplus >= 201103L
+ // expected-note@+3 2 {{non-constexpr function 'foobool' cannot be used in a constant expression}}
+#endif
+#pragma omp target
+#pragma omp teams distribute simd safelen (foobool(argc)), safelen (true), safelen (-5) // expected-error 2 {{directive '#pragma omp teams distribute simd' cannot contain more than one 'safelen' clause}} expected-error 2 {{argument to 'safelen' clause must be a strictly positive integer value}} expected-error 2 {{expression is not an integral constant expression}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute simd safelen (S) // expected-error {{'S' does not refer to a value}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#if __cplusplus <= 199711L
+ // expected-error@+5 2 {{expression is not an integral constant expression}}
+#else
+ // expected-error@+3 2 {{integral constant expression must have integral or unscoped enumeration type, not 'char *'}}
+#endif
+#pragma omp target
+#pragma omp teams distribute simd safelen (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute simd safelen (4)
+ for (int i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+#pragma omp target
+#pragma omp teams distribute simd safelen (N) // expected-error {{argument to 'safelen' clause must be a strictly positive integer value}}
+ for (T i = ST; i < N; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-ST];
+
+ return argc;
+}
+
+int main(int argc, char **argv) {
+#pragma omp target
+#pragma omp teams distribute simd safelen // expected-error {{expected '(' after 'safelen'}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target
+#pragma omp teams distribute simd safelen ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target
+#pragma omp teams distribute simd safelen () // expected-error {{expected expression}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target
+#pragma omp teams distribute simd safelen (4 // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target
+#pragma omp teams distribute simd safelen (2+2)) // expected-warning {{extra tokens at the end of '#pragma omp teams distribute simd' are ignored}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#if __cplusplus >= 201103L
+ // expected-note@+3 {{non-constexpr function 'foobool' cannot be used in a constant expression}}
+#endif
+#pragma omp target
+#pragma omp teams distribute simd safelen (foobool(1) > 0 ? 1 : 2) // expected-error {{expression is not an integral constant expression}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#if __cplusplus >= 201103L
+ // expected-note@+3 {{non-constexpr function 'foobool' cannot be used in a constant expression}}
+#endif
+#pragma omp target
+#pragma omp teams distribute simd safelen (foobool(argc)), safelen (true), safelen (-5) // expected-error 2 {{argument to 'safelen' clause must be a strictly positive integer value}} expected-error 2 {{directive '#pragma omp teams distribute simd' cannot contain more than one 'safelen' clause}} expected-error {{expression is not an integral constant expression}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#pragma omp target
+#pragma omp teams distribute simd safelen (S1) // expected-error {{'S1' does not refer to a value}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+#if __cplusplus <= 199711L
+ // expected-error@+5 {{expression is not an integral constant expression}}
+#else
+ // expected-error@+3 {{integral constant expression must have integral or unscoped enumeration type, not 'char *'}}
+#endif
+#pragma omp target
+#pragma omp teams distribute simd safelen (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int i = 4; i < 12; i++)
+ argv[0][i] = argv[0][i] - argv[0][i-4];
+
+ // expected-note@+2 {{in instantiation of function template specialization 'tmain<int, char, -1, -2>' requested here}}
+#pragma omp target
+#pragma omp teams distribute simd safelen(safelen(tmain<int, char, -1, -2>(argc, argv) // expected-error 2 {{expected ')'}} expected-note 2 {{to match this '('}}
+ foo(); // expected-error {{statement after '#pragma omp teams distribute simd' must be a for loop}}
+
+ // expected-note@+1 {{in instantiation of function template specialization 'tmain<int, char, 12, 4>' requested here}}
+ return tmain<int, char, 12, 4>(argc, argv);
+}
+
diff --git a/test/OpenMP/teams_distribute_simd_thread_limit_messages.cpp b/test/OpenMP/teams_distribute_simd_thread_limit_messages.cpp
new file mode 100644
index 000000000000..b9c8ac3e3615
--- /dev/null
+++ b/test/OpenMP/teams_distribute_simd_thread_limit_messages.cpp
@@ -0,0 +1,111 @@
+// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note 2 {{declared here}}
+
+template <typename T, int C> // expected-note {{declared here}}
+T tmain(T argc) {
+ char **a;
+#pragma omp target
+#pragma omp teams distribute simd thread_limit(C)
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd thread_limit(T) // expected-error {{'T' does not refer to a value}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd thread_limit // expected-error {{expected '(' after 'thread_limit'}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd thread_limit( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd thread_limit() // expected-error {{expected expression}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd thread_limit(argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd thread_limit(argc)) // expected-warning {{extra tokens at the end of '#pragma omp teams distribute simd' are ignored}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd thread_limit(argc > 0 ? a[1] : a[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd thread_limit(argc + argc)
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd thread_limit(argc), thread_limit (argc+1) // expected-error {{directive '#pragma omp teams distribute simd' cannot contain more than one 'thread_limit' clause}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd thread_limit(S1) // expected-error {{'S1' does not refer to a value}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd thread_limit(-2) // expected-error {{argument to 'thread_limit' clause must be a strictly positive integer value}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd thread_limit(-10u)
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute simd thread_limit(3.14) // expected-error 2 {{expression must have integral or unscoped enumeration type, not 'double'}}
+ for (int j=0; j<100; j++) foo();
+
+ return 0;
+}
+
+int main(int argc, char **argv) {
+#pragma omp target
+#pragma omp teams distribute simd thread_limit // expected-error {{expected '(' after 'thread_limit'}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd thread_limit ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd thread_limit () // expected-error {{expected expression}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd thread_limit (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd thread_limit (argc)) // expected-warning {{extra tokens at the end of '#pragma omp teams distribute simd' are ignored}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd thread_limit (argc > 0 ? argv[1] : argv[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd thread_limit (argc + argc)
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd thread_limit (argc), thread_limit (argc+1) // expected-error {{directive '#pragma omp teams distribute simd' cannot contain more than one 'thread_limit' clause}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd thread_limit (S1) // expected-error {{'S1' does not refer to a value}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd thread_limit (-2) // expected-error {{argument to 'thread_limit' clause must be a strictly positive integer value}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd thread_limit (-10u)
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target
+#pragma omp teams distribute simd thread_limit (3.14) // expected-error {{expression must have integral or unscoped enumeration type, not 'double'}}
+ for (int j=0; j<100; j++) foo();
+
+ return tmain<int, 10>(argc); // expected-note {{in instantiation of function template specialization 'tmain<int, 10>' requested here}}
+}
diff --git a/test/OpenMP/teams_distribute_thread_limit_messages.cpp b/test/OpenMP/teams_distribute_thread_limit_messages.cpp
new file mode 100644
index 000000000000..ec4ca7a05f27
--- /dev/null
+++ b/test/OpenMP/teams_distribute_thread_limit_messages.cpp
@@ -0,0 +1,111 @@
+// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note 2 {{declared here}}
+
+template <typename T, int C> // expected-note {{declared here}}
+T tmain(T argc) {
+ char **a;
+#pragma omp target
+#pragma omp teams distribute thread_limit(C)
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute thread_limit(T) // expected-error {{'T' does not refer to a value}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute thread_limit // expected-error {{expected '(' after 'thread_limit'}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute thread_limit( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute thread_limit() // expected-error {{expected expression}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute thread_limit(argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute thread_limit(argc)) // expected-warning {{extra tokens at the end of '#pragma omp teams distribute' are ignored}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute thread_limit(argc > 0 ? a[1] : a[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute thread_limit(argc + argc)
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute thread_limit(argc), thread_limit (argc+1) // expected-error {{directive '#pragma omp teams distribute' cannot contain more than one 'thread_limit' clause}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute thread_limit(S1) // expected-error {{'S1' does not refer to a value}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute thread_limit(-2) // expected-error {{argument to 'thread_limit' clause must be a strictly positive integer value}}
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute thread_limit(-10u)
+ for (int j=0; j<100; j++) foo();
+#pragma omp target
+#pragma omp teams distribute thread_limit(3.14) // expected-error 2 {{expression must have integral or unscoped enumeration type, not 'double'}}
+ for (int j=0; j<100; j++) foo();
+
+ return 0;
+}
+
+int main(int argc, char **argv) {
+#pragma omp target
+#pragma omp teams distribute thread_limit // expected-error {{expected '(' after 'thread_limit'}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target
+#pragma omp teams distribute thread_limit ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target
+#pragma omp teams distribute thread_limit () // expected-error {{expected expression}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target
+#pragma omp teams distribute thread_limit (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target
+#pragma omp teams distribute thread_limit (argc)) // expected-warning {{extra tokens at the end of '#pragma omp teams distribute' are ignored}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target
+#pragma omp teams distribute thread_limit (argc > 0 ? argv[1] : argv[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target
+#pragma omp teams distribute thread_limit (argc + argc)
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target
+#pragma omp teams distribute thread_limit (argc), thread_limit (argc+1) // expected-error {{directive '#pragma omp teams distribute' cannot contain more than one 'thread_limit' clause}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target
+#pragma omp teams distribute thread_limit (S1) // expected-error {{'S1' does not refer to a value}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target
+#pragma omp teams distribute thread_limit (-2) // expected-error {{argument to 'thread_limit' clause must be a strictly positive integer value}}
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target
+#pragma omp teams distribute thread_limit (-10u)
+ for (int j=0; j<100; j++) foo();
+
+#pragma omp target
+#pragma omp teams distribute thread_limit (3.14) // expected-error {{expression must have integral or unscoped enumeration type, not 'double'}}
+ for (int j=0; j<100; j++) foo();
+
+ return tmain<int, 10>(argc); // expected-note {{in instantiation of function template specialization 'tmain<int, 10>' requested here}}
+}
diff --git a/test/OpenMP/threadprivate_ast_print.cpp b/test/OpenMP/threadprivate_ast_print.cpp
index f789c2f277d3..5502c62134b5 100644
--- a/test/OpenMP/threadprivate_ast_print.cpp
+++ b/test/OpenMP/threadprivate_ast_print.cpp
@@ -5,7 +5,6 @@
// 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
// expected-no-diagnostics
-// REQUIRES: x86-registered-target
#ifndef HEADER
#define HEADER
@@ -44,12 +43,12 @@ template <class T> T foo() {
v = ST<T>::m;
return v;
}
-//CHECK: template <class T = int> int foo() {
-//CHECK-NEXT: static int v;
-//CHECK-NEXT: #pragma omp threadprivate(v)
//CHECK: template <class T> T foo() {
//CHECK-NEXT: static T v;
//CHECK-NEXT: #pragma omp threadprivate(v)
+//CHECK: template<> int foo<int>() {
+//CHECK-NEXT: static int v;
+//CHECK-NEXT: #pragma omp threadprivate(v)
namespace ns{
int a;
diff --git a/test/OpenMP/threadprivate_codegen.cpp b/test/OpenMP/threadprivate_codegen.cpp
index 273f0488220c..d2cbc154cc83 100644
--- a/test/OpenMP/threadprivate_codegen.cpp
+++ b/test/OpenMP/threadprivate_codegen.cpp
@@ -7,7 +7,7 @@
// 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
// expected-no-diagnostics
-// REQUIRES: x86-registered-target
+//
#ifndef HEADER
#define HEADER
// CHECK-DAG: [[IDENT:%.+]] = type { i32, i32, i32, i32, i8* }
diff --git a/test/PCH/builtin-macro.c b/test/PCH/builtin-macro.c
new file mode 100644
index 000000000000..4d0154023e46
--- /dev/null
+++ b/test/PCH/builtin-macro.c
@@ -0,0 +1,35 @@
+// Test this without pch.
+// RUN: %clang_cc1 -D__DATE__= -D__TIMESTAMP__= -include %s -Wno-builtin-macro-redefined -fsyntax-only -verify %s
+
+// Test with pch.
+// RUN: %clang_cc1 -D__DATE__= -D__TIMESTAMP__= -Wno-builtin-macro-redefined -emit-pch -o %t %s
+// RUN: %clang_cc1 -D__DATE__= -D__TIMESTAMP__= -Wno-builtin-macro-redefined -include-pch %t -fsyntax-only -verify %s
+
+#if !defined(HEADER)
+#define HEADER
+
+#define __TIME__
+
+#undef __TIMESTAMP__
+#define __TIMESTAMP__
+
+// FIXME: undefs don't work well with pchs yet, see PR31311
+// Once that's fixed, add -U__COUNTER__ to all command lines and check that
+// an attempt to use __COUNTER__ at the bottom produces an error in both non-pch
+// and pch case (works fine in the former case already).
+// Same for #undef __FILE__ right here and a use of that at the bottom.
+//#undef __FILE__
+
+// Also spot-check a predefine
+#undef __STDC_HOSTED__
+
+#else
+
+const char s[] = __DATE__ " " __TIME__ " " __TIMESTAMP__;
+
+// Check that we pick up __DATE__ from the -D flag:
+int i = __DATE__ 4;
+
+const int d = __STDC_HOSTED__; // expected-error{{use of undeclared identifier '__STDC_HOSTED__'}}
+
+#endif
diff --git a/test/PCH/cxx11-lambdas.mm b/test/PCH/cxx11-lambdas.mm
index 5d3323a02cff..1f568f05e11a 100644
--- a/test/PCH/cxx11-lambdas.mm
+++ b/test/PCH/cxx11-lambdas.mm
@@ -38,6 +38,11 @@ int init_capture(T t) {
return [&, x(t)] { return sizeof(x); };
}
+struct X {
+ template <typename T> X(T);
+};
+struct Y { Y(const X &x = [] {}); };
+
#else
// CHECK-PRINT: T add_slowly
@@ -54,4 +59,6 @@ int add(int x, int y) {
// CHECK-PRINT: init_capture
// CHECK-PRINT: [&, x(t)]
+X x = [] {};
+
#endif
diff --git a/test/PCH/cxx1y-default-initializer.cpp b/test/PCH/cxx1y-default-initializer.cpp
index 1f8d9a5d08d8..c9593a56d2e2 100644
--- a/test/PCH/cxx1y-default-initializer.cpp
+++ b/test/PCH/cxx1y-default-initializer.cpp
@@ -1,10 +1,10 @@
-// RUN: %clang_cc1 -pedantic -std=c++1y %s -o %t
-// RUN: %clang_cc1 -pedantic -std=c++1y -emit-pch %s -o %t
-// RUN: %clang_cc1 -pedantic -std=c++1y -include-pch %t -verify %s
+// RUN: %clang_cc1 -pedantic -std=c++1y -include %s -include %s -verify %s
+// RUN: %clang_cc1 -pedantic -std=c++1y -emit-pch -o %t.1 %s
+// RUN: %clang_cc1 -pedantic -std=c++1y -include-pch %t.1 -emit-pch -o %t.2 %s
+// RUN: %clang_cc1 -pedantic -std=c++1y -include-pch %t.2 -verify %s
-#ifndef HEADER_INCLUDED
-
-#define HEADER_INCLUDED
+#ifndef HEADER_1
+#define HEADER_1
struct A {
int x;
@@ -19,6 +19,20 @@ struct B {
constexpr B(int k) : z1(k) {}
};
+template<typename T> struct C {
+ constexpr C() {}
+ T c = T();
+ struct U {};
+};
+// Instantiate C<int> but not the default initializer.
+C<int>::U ciu;
+
+#elif !defined(HEADER_2)
+#define HEADER_2
+
+// Instantiate the default initializer now, should create an update record.
+C<int> ci;
+
#else
static_assert(A{}.z == 3, "");
@@ -27,5 +41,6 @@ static_assert(A{.y = 5}.z == 5, ""); // expected-warning {{C99}}
static_assert(A{3, .y = 1}.z == 4, ""); // expected-warning {{C99}}
static_assert(make<int>().z == 3, "");
static_assert(make<int>(12).z == 15, "");
+static_assert(C<int>().c == 0, "");
#endif
diff --git a/test/PCH/cxx1z-aligned-alloc.cpp b/test/PCH/cxx1z-aligned-alloc.cpp
new file mode 100644
index 000000000000..c49b910e852f
--- /dev/null
+++ b/test/PCH/cxx1z-aligned-alloc.cpp
@@ -0,0 +1,35 @@
+// No PCH:
+// RUN: %clang_cc1 -pedantic -fsized-deallocation -std=c++1z -include %s -verify %s
+//
+// With PCH:
+// RUN: %clang_cc1 -pedantic -fsized-deallocation -std=c++1z -emit-pch %s -o %t
+// RUN: %clang_cc1 -pedantic -fsized-deallocation -std=c++1z -include-pch %t -verify %s
+
+// expected-no-diagnostics
+
+#ifndef HEADER
+#define HEADER
+
+using size_t = decltype(sizeof(0));
+
+// Call the overaligned form of 'operator new'.
+struct alignas(256) Q { int n; };
+void *f() { return new Q; }
+
+// Extract the std::align_val_t type from the implicit declaration of operator delete.
+template<typename AlignValT>
+AlignValT extract(void (*)(void*, size_t, AlignValT));
+using T = decltype(extract(&operator delete));
+
+#else
+
+// ok, calls aligned allocation via placement syntax
+void *q = new (T{16}) Q;
+
+namespace std {
+ enum class align_val_t : size_t {};
+}
+
+using T = std::align_val_t; // ok, same type
+
+#endif
diff --git a/test/PCH/cxx1z-decomposition.cpp b/test/PCH/cxx1z-decomposition.cpp
new file mode 100644
index 000000000000..e033577162a6
--- /dev/null
+++ b/test/PCH/cxx1z-decomposition.cpp
@@ -0,0 +1,32 @@
+// No PCH:
+// RUN: %clang_cc1 -pedantic -std=c++1z -include %s -verify %s
+//
+// With PCH:
+// RUN: %clang_cc1 -pedantic -std=c++1z -emit-pch %s -o %t
+// RUN: %clang_cc1 -pedantic -std=c++1z -include-pch %t -verify %s
+
+#ifndef HEADER
+#define HEADER
+
+template<typename T> auto decomp(const T &t) {
+ auto &[a, b] = t;
+ return a + b;
+}
+
+struct Q { int a, b; };
+constexpr int foo(Q &&q) {
+ auto &[a, b] = q;
+ return a * 10 + b;
+}
+
+#else
+
+int arr[2];
+int k = decomp(arr);
+
+static_assert(foo({1, 2}) == 12);
+
+// expected-error@12 {{cannot decompose non-class, non-array type 'const int'}}
+int z = decomp(10); // expected-note {{instantiation of}}
+
+#endif
diff --git a/test/PCH/cxx1z-using-declaration.cpp b/test/PCH/cxx1z-using-declaration.cpp
new file mode 100644
index 000000000000..a185ff174046
--- /dev/null
+++ b/test/PCH/cxx1z-using-declaration.cpp
@@ -0,0 +1,35 @@
+// No PCH:
+// RUN: %clang_cc1 -pedantic -std=c++1z -include %s -verify %s
+//
+// With PCH:
+// RUN: %clang_cc1 -pedantic -std=c++1z -emit-pch %s -o %t
+// RUN: %clang_cc1 -pedantic -std=c++1z -include-pch %t -verify %s
+
+#ifndef HEADER
+#define HEADER
+
+template<typename ...T> struct A : T... {
+ using T::f ...;
+ template<typename ...U> void g(U ...u) { f(u...); }
+};
+
+struct X { void f(); };
+struct Y { void f(int); };
+struct Z { void f(int, int); };
+
+inline A<X, Y, Z> a;
+
+#else
+
+void test() {
+ a.g();
+ a.g(0);
+ a.g(0, 0);
+ // expected-error@13 {{no match}}
+ // expected-note@16 {{candidate}}
+ // expected-note@17 {{candidate}}
+ // expected-note@18 {{candidate}}
+ a.g(0, 0, 0); // expected-note {{instantiation of}}
+}
+
+#endif
diff --git a/test/PCH/debug-info-pch-path.c b/test/PCH/debug-info-pch-path.c
index 402d44da918d..015086f726e8 100644
--- a/test/PCH/debug-info-pch-path.c
+++ b/test/PCH/debug-info-pch-path.c
@@ -1,5 +1,3 @@
-// REQUIRES: shell
-//
// RUN: rm -rf %t
// RUN: mkdir %t
// RUN: cd %t
diff --git a/test/PCH/decl-in-prototype.c b/test/PCH/decl-in-prototype.c
new file mode 100644
index 000000000000..a291bf2df839
--- /dev/null
+++ b/test/PCH/decl-in-prototype.c
@@ -0,0 +1,27 @@
+// Test that we serialize the enum decl in the function prototype somehow.
+// These decls aren't serialized quite the same way as parameters.
+
+// Test this without pch.
+// RUN: %clang_cc1 -include %s -emit-llvm -o - %s | FileCheck %s
+
+// Test with pch.
+// RUN: %clang_cc1 -emit-pch -o %t %s
+// RUN: %clang_cc1 -include-pch %t -emit-llvm -o - %s | FileCheck %s
+
+// CHECK-LABEL: define {{.*}}i32 @main()
+// CHECK: ret i32 1
+
+#ifndef HEADER
+#define HEADER
+
+static inline __attribute__((always_inline)) f(enum { x, y } p) {
+ return y;
+}
+
+#else
+
+int main() {
+ return f(0);
+}
+
+#endif
diff --git a/test/PCH/dllexport-default-arg-closure.cpp b/test/PCH/dllexport-default-arg-closure.cpp
new file mode 100644
index 000000000000..892f1eb9bff8
--- /dev/null
+++ b/test/PCH/dllexport-default-arg-closure.cpp
@@ -0,0 +1,26 @@
+// Make sure we emit the MS ABI default ctor closure with PCH.
+//
+// Test this without pch.
+// RUN: %clang_cc1 -fms-extensions -triple x86_64-windows-msvc -std=c++11 -include %s -emit-llvm -o - %s | FileCheck %s
+
+// Test with pch.
+// RUN: %clang_cc1 -fms-extensions -triple x86_64-windows-msvc -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fms-extensions -triple x86_64-windows-msvc -std=c++11 -include-pch %t -emit-llvm -o - %s | FileCheck %s
+
+#ifndef HEADER
+#define HEADER
+
+struct __declspec(dllexport) Foo {
+ enum E { E0 } e;
+ Foo(E e = E0) : e(e) {}
+};
+
+// 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)
+
+#else
+
+
+#endif
diff --git a/test/PCH/no-validate-pch.cl b/test/PCH/no-validate-pch.cl
new file mode 100644
index 000000000000..26c5fd5cc04c
--- /dev/null
+++ b/test/PCH/no-validate-pch.cl
@@ -0,0 +1,39 @@
+// RUN: %clang_cc1 -emit-pch -D TWO=2 -D X=4 -o %t %s -triple spir-unknown-unknown
+// RUN: %clang_cc1 -include-pch %t -D THREE=3 -D X=5 -O0 -U__OPTIMIZE__ -fno-validate-pch %s -triple spir-unknown-unknown 2>&1 | FileCheck %s
+// RUN: not %clang_cc1 -include-pch %t -D THREE=3 -D X=5 -D VALIDATE -O0 -fsyntax-only %s -triple spir-unknown-unknown 2>&1 | FileCheck --check-prefix=CHECK-VAL %s
+
+#ifndef HEADER
+#define HEADER
+// Header.
+
+#define ONE 1
+
+#else
+// Using the header.
+
+// CHECK: warning: 'X' macro redefined
+// CHECK: #define X 5
+// CHECK: note: previous definition is here
+// CHECK: #define X 4
+
+// CHECK-VAL: error: __OPTIMIZE__ predefined macro was enabled in PCH file but is currently disabled
+// CHECK-VAL: error: definition of macro 'X' differs between the precompiled header ('4') and the command line ('5')
+
+void test(void) {
+ int a = ONE;
+ int b = TWO;
+ int c = THREE;
+
+#ifndef VALIDATE
+#if X != 5
+#error Definition of X is not overridden!
+#endif
+
+#ifdef __OPTIMIZE__
+#error Optimization is not off!
+#endif
+#endif
+
+}
+
+#endif
diff --git a/test/PCH/objc_container.m b/test/PCH/objc_container.m
index 2af51cbcf424..1852d5e0750c 100644
--- a/test/PCH/objc_container.m
+++ b/test/PCH/objc_container.m
@@ -21,5 +21,5 @@
// CHECK-IR: {{call.*objc_msgSend}}
// CHECK-IR: ret void
-// CHECK-IR: attributes #0 = { nounwind {{.*}} }
+// CHECK-IR: attributes #0 = { noinline nounwind {{.*}} }
// CHECK-IR: attributes #1 = { nonlazybind }
diff --git a/test/PCH/ocl_types.cl b/test/PCH/ocl_types.cl
index 21097c481182..60323e1609a7 100644
--- a/test/PCH/ocl_types.cl
+++ b/test/PCH/ocl_types.cl
@@ -1,9 +1,9 @@
// Test this without pch.
-// RUN: %clang_cc1 -include %S/ocl_types.h -fsyntax-only %s -cl-std=CL2.0 -D__OPENCL_VERSION__=200
+// RUN: %clang_cc1 -triple spir-unknown-unknown -include %S/ocl_types.h -fsyntax-only %s -cl-std=CL2.0 -D__OPENCL_VERSION__=200
// Test with pch.
-// RUN: %clang_cc1 -x cl -emit-pch -o %t %S/ocl_types.h -cl-std=CL2.0 -D__OPENCL_VERSION__=200
-// RUN: %clang_cc1 -include-pch %t -fsyntax-only %s -ast-print -cl-std=CL2.0 -D__OPENCL_VERSION__=200
+// RUN: %clang_cc1 -triple spir-unknown-unknown -x cl -emit-pch -o %t %S/ocl_types.h -cl-std=CL2.0 -D__OPENCL_VERSION__=200
+// RUN: %clang_cc1 -triple spir-unknown-unknown -include-pch %t -fsyntax-only %s -ast-print -cl-std=CL2.0 -D__OPENCL_VERSION__=200
void foo1(img1d_t img);
diff --git a/test/PCH/pragma-cuda-force-host-device.cu b/test/PCH/pragma-cuda-force-host-device.cu
new file mode 100644
index 000000000000..1eaa453ad78a
--- /dev/null
+++ b/test/PCH/pragma-cuda-force-host-device.cu
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -emit-pch %s -o %t
+// RUN: %clang_cc1 -verify -verify-ignore-unexpected=note -include-pch %t -fsyntax-only %s
+
+#ifndef HEADER
+#define HEADER
+
+#pragma clang force_cuda_host_device begin
+#pragma clang force_cuda_host_device begin
+#pragma clang force_cuda_host_device end
+
+void hd1() {}
+
+#else
+
+void hd2() {}
+
+#pragma clang force_cuda_host_device end
+
+void host_only() {}
+
+__attribute__((device)) void device() {
+ hd1();
+ hd2();
+ host_only(); // expected-error {{no matching function for call}}
+}
+
+#endif
diff --git a/test/Parser/MicrosoftExtensions.c b/test/Parser/MicrosoftExtensions.c
index 39ab51f31fa6..2af6c421bcce 100644
--- a/test/Parser/MicrosoftExtensions.c
+++ b/test/Parser/MicrosoftExtensions.c
@@ -106,3 +106,12 @@ __declspec(align(16)) struct align_before_key3 {} *align_before_key3_var;
_Static_assert(__alignof(struct align_before_key1) == 16, "");
_Static_assert(__alignof(struct align_before_key2) == 16, "");
_Static_assert(__alignof(struct align_before_key3) == 16, "");
+
+void PR28782(int i) {
+foo:
+ int n;
+ switch (i) {
+ case 0:
+ int m;
+ }
+}
diff --git a/test/Parser/MicrosoftExtensions.cpp b/test/Parser/MicrosoftExtensions.cpp
index efb9490697e7..830412ed474f 100644
--- a/test/Parser/MicrosoftExtensions.cpp
+++ b/test/Parser/MicrosoftExtensions.cpp
@@ -49,6 +49,7 @@ struct __declspec(uuid(3)) uuid_attr_bad2 { };// expected-error {{'uuid' attribu
struct __declspec(uuid("0000000-0000-0000-1234-0000500000047")) uuid_attr_bad3 { };// expected-error {{uuid attribute contains a malformed GUID}}
struct __declspec(uuid("0000000-0000-0000-Z234-000000000047")) uuid_attr_bad4 { };// expected-error {{uuid attribute contains a malformed GUID}}
struct __declspec(uuid("000000000000-0000-1234-000000000047")) uuid_attr_bad5 { };// expected-error {{uuid attribute contains a malformed GUID}}
+[uuid("000000000000-0000-1234-000000000047")] struct uuid_attr_bad6 { };// expected-error {{uuid attribute contains a malformed GUID}}
__declspec(uuid("000000A0-0000-0000-C000-000000000046")) int i; // expected-warning {{'uuid' attribute only applies to classes}}
@@ -59,9 +60,17 @@ struct struct_without_uuid { };
struct __declspec(uuid("000000A0-0000-0000-C000-000000000049"))
struct_with_uuid2;
+[uuid("000000A0-0000-0000-C000-000000000049")] struct struct_with_uuid3;
+
struct
struct_with_uuid2 {} ;
+enum __declspec(uuid("000000A0-0000-0000-C000-000000000046"))
+enum_with_uuid { };
+enum enum_without_uuid { };
+
+int __declspec(uuid("000000A0-0000-0000-C000-000000000046")) inappropriate_uuid; // expected-warning {{'uuid' attribute only applies to classes and enumerations}}
+
int uuid_sema_test()
{
struct_with_uuid var_with_uuid[1];
@@ -69,6 +78,7 @@ int uuid_sema_test()
__uuidof(struct_with_uuid);
__uuidof(struct_with_uuid2);
+ __uuidof(struct_with_uuid3);
__uuidof(struct_without_uuid); // expected-error {{cannot call operator __uuidof on a type with no GUID}}
__uuidof(struct_with_uuid*);
__uuidof(struct_without_uuid*); // expected-error {{cannot call operator __uuidof on a type with no GUID}}
@@ -77,6 +87,15 @@ int uuid_sema_test()
__uuidof(const struct_with_uuid[1][1]);
__uuidof(const struct_with_uuid*[1][1]); // expected-error {{cannot call operator __uuidof on a type with no GUID}}
+ __uuidof(enum_with_uuid);
+ __uuidof(enum_without_uuid); // expected-error {{cannot call operator __uuidof on a type with no GUID}}
+ __uuidof(enum_with_uuid*);
+ __uuidof(enum_without_uuid*); // expected-error {{cannot call operator __uuidof on a type with no GUID}}
+ __uuidof(enum_with_uuid[1]);
+ __uuidof(enum_with_uuid*[1]); // expected-error {{cannot call operator __uuidof on a type with no GUID}}
+ __uuidof(const enum_with_uuid[1][1]);
+ __uuidof(const enum_with_uuid*[1][1]); // expected-error {{cannot call operator __uuidof on a type with no GUID}}
+
__uuidof(var_with_uuid);
__uuidof(var_without_uuid);// expected-error {{cannot call operator __uuidof on a type with no GUID}}
__uuidof(var_with_uuid[1]);
diff --git a/test/Parser/backtrack-off-by-one.cpp b/test/Parser/backtrack-off-by-one.cpp
new file mode 100644
index 000000000000..efb95a5a225d
--- /dev/null
+++ b/test/Parser/backtrack-off-by-one.cpp
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -verify %s
+// RUN: %clang_cc1 -verify %s -std=c++98
+// RUN: %clang_cc1 -verify %s -std=c++11
+
+// PR25946
+// We had an off-by-one error in an assertion when annotating A<int> below. Our
+// error recovery checks if A<int> is a constructor declarator, and opens a
+// TentativeParsingAction. Then we attempt to annotate the token at the exact
+// position that we want to possibly backtrack to, and this used to crash.
+
+template <typename T> class A {};
+
+// expected-error@+1 {{expected '{' after base class list}}
+template <typename T> class B : T // not ',' or '{'
+#if __cplusplus < 201103L
+// expected-error@+4 {{expected ';' after top level declarator}}
+#endif
+// expected-error@+2 {{C++ requires a type specifier for all declarations}}
+// expected-error@+1 {{expected ';' after class}}
+A<int> {
+};
diff --git a/test/Parser/colon-colon-parentheses.cpp b/test/Parser/colon-colon-parentheses.cpp
index b3db4fbed2f1..804e4f785ee6 100644
--- a/test/Parser/colon-colon-parentheses.cpp
+++ b/test/Parser/colon-colon-parentheses.cpp
@@ -1,30 +1,36 @@
-// RUN: %clang_cc1 %s -fsyntax-only -verify -DPR21815
-// RUN: cp %s %t
-// RUN: not %clang_cc1 -x c++ -fixit %t
-// RUN: %clang_cc1 -x c++ %t
+// RUN: %clang_cc1 %s -verify -fno-spell-checking
struct S { static int a,b,c;};
-int S::(a); // expected-error{{unexpected parenthesis after '::'}}
-int S::(b; // expected-error{{unexpected parenthesis after '::'}}
+int S::(a); // expected-error{{expected unqualified-id}}
+int S::(b; // expected-error{{expected unqualified-id}}
+ );
int S::c;
-int S::(*d); // expected-error{{unexpected parenthesis after '::'}}
-int S::(*e; // expected-error{{unexpected parenthesis after '::'}}
+int S::(*d); // expected-error{{expected unqualified-id}}
+int S::(*e; // expected-error{{expected unqualified-id}}
+ );
int S::*f;
-int g = S::(a); // expected-error{{unexpected parenthesis after '::'}}
-int h = S::(b; // expected-error{{unexpected parenthesis after '::'}}
+int g = S::(a); // expected-error {{expected unqualified-id}} expected-error {{use of undeclared identifier 'a'}}
+int h = S::(b; // expected-error {{expected unqualified-id}} expected-error {{use of undeclared identifier 'b'}}
+ );
int i = S::c;
void foo() {
int a;
- a = ::(g); // expected-error{{unexpected parenthesis after '::'}}
- a = ::(h; // expected-error{{unexpected parenthesis after '::'}}
+ a = ::(g); // expected-error{{expected unqualified-id}}
+ a = ::(h; // expected-error{{expected unqualified-id}}
a = ::i;
}
-#ifdef PR21815
+// The following tests used to be crash bugs.
+
+// PR21815
// expected-error@+2{{C++ requires a type specifier for all declarations}}
// expected-error@+1{{expected unqualified-id}}
a (::( ));
::((c )); // expected-error{{expected unqualified-id}}
-#endif
+
+// PR26623
+int f1(::(B) p); // expected-error {{expected unqualified-id}} expected-error {{use of undeclared identifier 'B'}}
+
+int f2(::S::(C) p); // expected-error {{expected unqualified-id}} expected-error {{use of undeclared identifier 'C'}}
diff --git a/test/Parser/cuda-force-host-device-templates.cu b/test/Parser/cuda-force-host-device-templates.cu
new file mode 100644
index 000000000000..315de1cf67a1
--- /dev/null
+++ b/test/Parser/cuda-force-host-device-templates.cu
@@ -0,0 +1,40 @@
+// RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify -fcuda-is-device %s
+
+// Check how the force_cuda_host_device pragma interacts with template
+// instantiations.
+
+template <typename T>
+auto foo() { // expected-note {{declared here}}
+ return T();
+}
+
+template <typename T>
+struct X {
+ void foo(); // expected-note {{declared here}}
+};
+
+#pragma clang force_cuda_host_device begin
+__attribute__((host)) __attribute__((device)) void test() {
+ int n = foo<int>(); // expected-error {{reference to __host__ function 'foo<int>'}}
+ X<int>().foo(); // expected-error {{reference to __host__ function 'foo'}}
+}
+#pragma clang force_cuda_host_device end
+
+// Same thing as above, but within a force_cuda_host_device block without a
+// corresponding end.
+
+template <typename T>
+T bar() { // expected-note {{declared here}}
+ return T();
+}
+
+template <typename T>
+struct Y {
+ void bar(); // expected-note {{declared here}}
+};
+
+#pragma clang force_cuda_host_device begin
+__attribute__((host)) __attribute__((device)) void test2() {
+ int n = bar<int>(); // expected-error {{reference to __host__ function 'bar<int>'}}
+ Y<int>().bar(); // expected-error {{reference to __host__ function 'bar'}}
+}
diff --git a/test/Parser/cuda-force-host-device.cu b/test/Parser/cuda-force-host-device.cu
new file mode 100644
index 000000000000..6064708aaa3d
--- /dev/null
+++ b/test/Parser/cuda-force-host-device.cu
@@ -0,0 +1,36 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// Check the force_cuda_host_device pragma.
+
+#pragma clang force_cuda_host_device begin
+void f();
+#pragma clang force_cuda_host_device begin
+void g();
+#pragma clang force_cuda_host_device end
+void h();
+#pragma clang force_cuda_host_device end
+
+void i(); // expected-note {{not viable}}
+
+void host() {
+ f();
+ g();
+ h();
+ i();
+}
+
+__attribute__((device)) void device() {
+ f();
+ g();
+ h();
+ i(); // expected-error {{no matching function}}
+}
+
+#pragma clang force_cuda_host_device foo
+// expected-warning@-1 {{incorrect use of #pragma clang force_cuda_host_device begin|end}}
+
+#pragma clang force_cuda_host_device
+// expected-warning@-1 {{incorrect use of #pragma clang force_cuda_host_device begin|end}}
+
+#pragma clang force_cuda_host_device begin foo
+// expected-warning@-1 {{incorrect use of #pragma clang force_cuda_host_device begin|end}}
diff --git a/test/Parser/cxx-modules-import.cpp b/test/Parser/cxx-modules-import.cpp
new file mode 100644
index 000000000000..0600eddecb83
--- /dev/null
+++ b/test/Parser/cxx-modules-import.cpp
@@ -0,0 +1,58 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: echo 'module x; int a, b;' > %t/x.cppm
+// RUN: echo 'module x.y; int c;' > %t/x.y.cppm
+//
+// RUN: %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface %t/x.cppm -o %t/x.pcm
+// RUN: %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface -fmodule-file=%t/x.pcm %t/x.y.cppm -o %t/x.y.pcm
+//
+// RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \
+// RUN: -DTEST=1 -DMODULE_KIND=implementation -DMODULE_NAME=z
+// RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \
+// RUN: -DTEST=2 -DMODULE_KIND=implementation -DMODULE_NAME=x
+// RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \
+// RUN: -DTEST=3 -DMODULE_KIND= -DMODULE_NAME=z
+// RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \
+// RUN: -DTEST=4 -DMODULE_KIND=partition -DMODULE_NAME=z
+// RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \
+// RUN: -DTEST=5 -DMODULE_KIND=elderberry -DMODULE_NAME=z
+// RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \
+// RUN: -DTEST=1 -DMODULE_KIND=implementation -DMODULE_NAME='z [[]]'
+// RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \
+// RUN: -DTEST=6 -DMODULE_KIND=implementation -DMODULE_NAME='z [[fancy]]'
+// RUN: %clang_cc1 -std=c++1z -fmodules-ts -I%t -fmodule-file=%t/x.y.pcm -verify %s \
+// RUN: -DTEST=7 -DMODULE_KIND=implementation -DMODULE_NAME='z [[maybe_unused]]'
+
+module MODULE_KIND MODULE_NAME;
+#if TEST == 3
+// expected-error@-2 {{'module' declaration found while not building module interface}}
+#elif TEST == 4
+// expected-error@-4 {{'module partition' declaration found while not building module interface}}
+#elif TEST == 5
+// expected-error@-6 {{unexpected module kind 'elderberry'}}
+#elif TEST == 6
+// expected-warning@-8 {{unknown attribute 'fancy' ignored}}
+#elif TEST == 7
+// expected-error-re@-10 {{'maybe_unused' attribute cannot be applied to a module{{$}}}}
+#endif
+
+int use_1 = a;
+#if TEST != 2
+// expected-error@-2 {{declaration of 'a' must be imported from module 'x' before it is required}}
+// expected-note@x.cppm:1 {{here}}
+#endif
+
+import x;
+
+int use_2 = b; // ok
+
+import x [[]];
+import x [[foo]]; // expected-warning {{unknown attribute 'foo' ignored}}
+import x [[noreturn]]; // expected-error {{'noreturn' attribute cannot be applied to a module import}}
+import x [[blarg::noreturn]]; // expected-warning {{unknown attribute 'noreturn' ignored}}
+
+import x.y;
+import x.; // expected-error {{expected a module name after module import}}
+import .x; // expected-error {{expected a module name after module import}}
+
+import blarg; // expected-error {{module 'blarg' not found}}
diff --git a/test/Parser/cxx-modules-interface.cppm b/test/Parser/cxx-modules-interface.cppm
new file mode 100644
index 000000000000..f7835bd167b2
--- /dev/null
+++ b/test/Parser/cxx-modules-interface.cppm
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface %s -o %t.pcm -verify
+// RUN: %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface %s -o %t.pcm -verify -Dmodule=int -DERRORS
+
+module foo;
+#ifndef ERRORS
+// expected-no-diagnostics
+#else
+// expected-error@-4 {{expected module declaration at start of module interface}}
+
+// FIXME: support 'export module X;' and 'export { int n; module X; }'
+// FIXME: proclaimed-ownership-declarations?
+
+export {
+ int a;
+ int b;
+}
+export int c;
+
+namespace N {
+ export void f() {}
+}
+
+export struct T {} t;
+
+struct S {
+ export int n; // expected-error {{expected member name or ';'}}
+ export static int n; // expected-error {{expected member name or ';'}}
+};
+void f() {
+ export int n; // expected-error {{expected expression}}
+}
+#endif
diff --git a/test/Parser/cxx0x-decl.cpp b/test/Parser/cxx0x-decl.cpp
index c4f03566029a..d912e19287be 100644
--- a/test/Parser/cxx0x-decl.cpp
+++ b/test/Parser/cxx0x-decl.cpp
@@ -136,5 +136,5 @@ template<int ...N> void NoMissingSemicolonHereEither(struct S
... [N]);
// This must be at the end of the file; we used to look ahead past the EOF token here.
-// expected-error@+1 {{expected unqualified-id}}
+// expected-error@+1 {{expected unqualified-id}} expected-error@+1{{expected ';'}}
using
diff --git a/test/Parser/cxx1z-constexpr-lambdas.cpp b/test/Parser/cxx1z-constexpr-lambdas.cpp
new file mode 100644
index 000000000000..ea000e361ccb
--- /dev/null
+++ b/test/Parser/cxx1z-constexpr-lambdas.cpp
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -std=c++1z %s -verify
+// RUN: %clang_cc1 -std=c++14 %s -verify
+// RUN: %clang_cc1 -std=c++11 %s -verify
+
+
+auto XL0 = [] constexpr { }; //expected-error{{requires '()'}} expected-error{{expected body}}
+auto XL1 = [] () mutable
+ mutable //expected-error{{cannot appear multiple times}}
+ mutable { }; //expected-error{{cannot appear multiple times}}
+
+#if __cplusplus > 201402L
+auto XL2 = [] () constexpr mutable constexpr { }; //expected-error{{cannot appear multiple times}}
+auto L = []() mutable constexpr { };
+auto L2 = []() constexpr { };
+auto L4 = []() constexpr mutable { };
+auto XL16 = [] () constexpr
+ mutable
+ constexpr //expected-error{{cannot appear multiple times}}
+ mutable //expected-error{{cannot appear multiple times}}
+ mutable //expected-error{{cannot appear multiple times}}
+ constexpr //expected-error{{cannot appear multiple times}}
+ constexpr //expected-error{{cannot appear multiple times}}
+ { };
+
+#else
+auto L = []() mutable constexpr {return 0; }; //expected-warning{{is a C++1z extension}}
+auto L2 = []() constexpr { return 0;};//expected-warning{{is a C++1z extension}}
+auto L4 = []() constexpr mutable { return 0; }; //expected-warning{{is a C++1z extension}}
+#endif
+
+
diff --git a/test/Parser/cxx1z-coroutines.cpp b/test/Parser/cxx1z-coroutines.cpp
index 3e698404a600..68ef91c81727 100644
--- a/test/Parser/cxx1z-coroutines.cpp
+++ b/test/Parser/cxx1z-coroutines.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++11 -fcoroutines %s -verify
+// RUN: %clang_cc1 -std=c++11 -fcoroutines-ts %s -verify
template<typename T, typename U>
U f(T t) {
diff --git a/test/Parser/cxx1z-decomposition.cpp b/test/Parser/cxx1z-decomposition.cpp
new file mode 100644
index 000000000000..9cbe70e3c69b
--- /dev/null
+++ b/test/Parser/cxx1z-decomposition.cpp
@@ -0,0 +1,150 @@
+// RUN: %clang_cc1 -std=c++1z %s -verify -fcxx-exceptions
+
+struct S { int a, b, c; };
+
+// A simple-declaration can be a decompsition declaration.
+namespace SimpleDecl {
+ auto [a_x, b_x, c_x] = S();
+
+ void f(S s) {
+ auto [a, b, c] = S();
+ {
+ for (auto [a, b, c] = S();;) {}
+ if (auto [a, b, c] = S(); true) {}
+ switch (auto [a, b, c] = S(); 0) { case 0:; }
+ }
+ }
+}
+
+// A for-range-declaration can be a decomposition declaration.
+namespace ForRangeDecl {
+ extern S arr[10];
+ void h() {
+ for (auto [a, b, c] : arr) {
+ }
+ }
+}
+
+// Other kinds of declaration cannot.
+namespace OtherDecl {
+ // A parameter-declaration is not a simple-declaration.
+ // This parses as an array declaration.
+ void f(auto [a, b, c]); // expected-error {{'auto' not allowed in function prototype}} expected-error {{'a'}}
+
+ void g() {
+ // A condition is not a simple-declaration.
+ for (; auto [a, b, c] = S(); ) {} // expected-error {{not permitted in this context}}
+ if (auto [a, b, c] = S()) {} // expected-error {{not permitted in this context}}
+ if (int n; auto [a, b, c] = S()) {} // expected-error {{not permitted in this context}}
+ switch (auto [a, b, c] = S()) {} // expected-error {{not permitted in this context}}
+ switch (int n; auto [a, b, c] = S()) {} // expected-error {{not permitted in this context}}
+ while (auto [a, b, c] = S()) {} // expected-error {{not permitted in this context}}
+
+ // An exception-declaration is not a simple-declaration.
+ try {}
+ catch (auto [a, b, c]) {} // expected-error {{'auto' not allowed in exception declaration}} expected-error {{'a'}}
+ }
+
+ // A member-declaration is not a simple-declaration.
+ class A {
+ auto [a, b, c] = S(); // expected-error {{not permitted in this context}}
+ static auto [a, b, c] = S(); // expected-error {{not permitted in this context}}
+ };
+}
+
+namespace GoodSpecifiers {
+ void f() {
+ int n[1];
+ const volatile auto &[a] = n;
+ }
+}
+
+namespace BadSpecifiers {
+ typedef int I1[1];
+ I1 n;
+ struct S { int n; } s;
+ void f() {
+ // storage-class-specifiers
+ static auto &[a] = n; // expected-error {{cannot be declared 'static'}}
+ thread_local auto &[b] = n; // expected-error {{cannot be declared 'thread_local'}}
+ extern auto &[c] = n; // expected-error {{cannot be declared 'extern'}} expected-error {{cannot have an initializer}}
+ struct S {
+ mutable auto &[d] = n; // expected-error {{not permitted in this context}}
+
+ // function-specifiers
+ virtual auto &[e] = n; // expected-error {{not permitted in this context}}
+ explicit auto &[f] = n; // expected-error {{not permitted in this context}}
+
+ // misc decl-specifiers
+ friend auto &[g] = n; // expected-error {{'auto' not allowed}} expected-error {{friends can only be classes or functions}}
+ };
+ typedef auto &[h] = n; // expected-error {{cannot be declared 'typedef'}}
+ constexpr auto &[i] = n; // expected-error {{cannot be declared 'constexpr'}}
+
+ static constexpr thread_local auto &[j] = n; // expected-error {{cannot be declared with 'static thread_local constexpr' specifiers}}
+ }
+ inline auto &[k] = n; // expected-error {{cannot be declared 'inline'}}
+
+ const int K = 5;
+ void g() {
+ // defining-type-specifiers other than cv-qualifiers and 'auto'
+ S [a] = s; // expected-error {{cannot be declared with type 'BadSpecifiers::S'}}
+ decltype(auto) [b] = s; // expected-error {{cannot be declared with type 'decltype(auto)'}}
+ auto ([c]) = s; // expected-error {{cannot be declared with parentheses}}
+
+ // FIXME: This error is not very good.
+ auto [d]() = s; // expected-error {{expected ';'}} expected-error {{expected expression}}
+ auto [e][1] = s; // expected-error {{expected ';'}} expected-error {{requires an initializer}}
+
+ // FIXME: This should fire the 'misplaced array declarator' diagnostic.
+ int [K] arr = {0}; // expected-error {{expected ';'}} expected-error {{cannot be declared with type 'int'}} expected-error {{decomposition declaration '[K]' requires an initializer}}
+ int [5] arr = {0}; // expected-error {{place the brackets after the name}}
+
+ auto *[f] = s; // expected-error {{cannot be declared with type 'auto *'}} expected-error {{incompatible initializer}}
+ auto S::*[g] = s; // expected-error {{cannot be declared with type 'auto BadSpecifiers::S::*'}} expected-error {{incompatible initializer}}
+
+ // ref-qualifiers are OK.
+ auto &&[ok_1] = S();
+ auto &[ok_2] = s;
+
+ // attributes are OK.
+ [[]] auto [ok_3] = s;
+ alignas(S) auto [ok_4] = s;
+
+ // ... but not after the identifier or declarator.
+ // FIXME: These errors are not very good.
+ auto [bad_attr_1 [[]]] = s; // expected-error {{attribute list cannot appear here}} expected-error 2{{}}
+ auto [bad_attr_2] [[]] = s; // expected-error {{expected ';'}} expected-error {{}}
+ }
+}
+
+namespace MultiDeclarator {
+ struct S { int n; };
+ void f(S s) {
+ auto [a] = s, [b] = s; // expected-error {{must be the only declaration}}
+ auto [c] = s, d = s; // expected-error {{must be the only declaration}}
+ auto e = s, [f] = s; // expected-error {{must be the only declaration}}
+ auto g = s, h = s, i = s, [j] = s; // expected-error {{must be the only declaration}}
+ }
+}
+
+namespace Template {
+ int n[3];
+ // FIXME: There's no actual rule against this...
+ template<typename T> auto [a, b, c] = n; // expected-error {{decomposition declaration template not supported}}
+}
+
+namespace Init {
+ void f() {
+ int arr[1];
+ struct S { int n; };
+ auto &[bad1]; // expected-error {{decomposition declaration '[bad1]' requires an initializer}}
+ const auto &[bad2](S{}, S{}); // expected-error {{initializer for variable '[bad2]' with type 'const auto &' contains multiple expressions}}
+ const auto &[bad3](); // expected-error {{expected expression}}
+ auto &[good1] = arr;
+ auto &&[good2] = S{};
+ const auto &[good3](S{});
+ S [goodish3] = { 4 }; // expected-error {{cannot be declared with type 'S'}}
+ S [goodish4] { 4 }; // expected-error {{cannot be declared with type 'S'}}
+ }
+}
diff --git a/test/Parser/cxx1z-fold-expressions.cpp b/test/Parser/cxx1z-fold-expressions.cpp
index a908311ea316..030638583239 100644
--- a/test/Parser/cxx1z-fold-expressions.cpp
+++ b/test/Parser/cxx1z-fold-expressions.cpp
@@ -9,12 +9,19 @@ int k1 = (1 + ... + 2); // expected-error {{does not contain any unexpanded para
int k2 = (1 + ...); // expected-error {{does not contain any unexpanded parameter packs}}
int k3 = (... + 2); // expected-error {{does not contain any unexpanded parameter packs}}
+struct A { A(int); friend A operator+(A, A); A operator-(A); A operator()(A); A operator[](A); };
+A operator*(A, A);
+
template<int ...N> void bad1() { (N + ... + N); } // expected-error {{unexpanded parameter packs in both operands}}
// FIXME: it would be reasonable to support this as an extension.
template<int ...N> void bad2() { (2 * N + ... + 1); } // expected-error {{expression not permitted as operand}}
template<int ...N> void bad3() { (2 + N * ... * 1); } // expected-error {{expression not permitted as operand}}
template<int ...N, int ...M> void bad4(int (&...x)[N]) { (N + M * ... * 1); } // expected-error {{expression not permitted as operand}}
template<int ...N, int ...M> void fixed4(int (&...x)[N]) { ((N + M) * ... * 1); }
+template<typename ...T> void bad4a(T ...t) { (t * 2 + ... + 1); } // expected-error {{expression not permitted as operand}}
+template<int ...N> void bad4b() { (A(0) + A(N) + ...); } // expected-error {{expression not permitted as operand}}
+template<int ...N> void bad4c() { (A(0) - A(N) + ...); } // expected-error {{expression not permitted as operand}}
+template<int ...N> void bad4d() { (A(0)(A(0)) + ... + A(0)[A(N)]); }
// Parens are mandatory.
template<int ...N> void bad5() { N + ...; } // expected-error {{expected expression}} expected-error +{{}}
diff --git a/test/Parser/cxx1z-using-declaration.cpp b/test/Parser/cxx1z-using-declaration.cpp
new file mode 100644
index 000000000000..0be81677d9fb
--- /dev/null
+++ b/test/Parser/cxx1z-using-declaration.cpp
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -std=c++1z -verify %s
+
+namespace A {
+ int m, n;
+};
+
+namespace B {
+ using A::m, A::n, A::n;
+ int q = m + n;
+}
+
+struct X {
+ int x1, x2, y, z; // expected-note 2{{conflicting}}
+};
+struct Y {
+ int x1, x2, y, z; // expected-note 2{{target}}
+};
+struct Z : X, Y {
+ using X::x1,
+ blah::blah, // expected-error {{undeclared}}
+ X::x2, // expected-note {{previous}}
+ Y::y,
+ X::x2, // expected-error {{redeclaration}}
+ X::z,
+ Y::z; // expected-error {{conflicts with}}
+};
+int X::*px1 = &Z::x1;
+int X::*px2 = &Z::x2;
+int Y::*py = &Z::y;
+int X::*pz = &Z::z;
+
+template<typename ...T> struct Q : T... {
+ using T::z...; // expected-error {{conflicts}}
+};
+Q<X,Y> q; // expected-note {{instantiation of}}
diff --git a/test/Parser/gcc-__final-compatibility.cpp b/test/Parser/gcc-__final-compatibility.cpp
new file mode 100644
index 000000000000..ddd14ba79ef4
--- /dev/null
+++ b/test/Parser/gcc-__final-compatibility.cpp
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -std=c++98 -fgnu-keywords -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++11 -fgnu-keywords -fsyntax-only -verify %s
+
+struct B {
+ virtual void g();
+};
+struct D __final : B { // expected-warning {{__final is a GNU extension, consider using C++11 final}}
+ virtual void g() __final; // expected-warning {{__final is a GNU extension, consider using C++11 final}}
+};
diff --git a/test/Parser/lambda-attr.cu b/test/Parser/lambda-attr.cu
new file mode 100644
index 000000000000..d5aaf0194605
--- /dev/null
+++ b/test/Parser/lambda-attr.cu
@@ -0,0 +1,42 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -fcuda-is-device -verify %s
+
+__attribute__((device)) void device_fn() {}
+__attribute__((host, device)) void hd_fn() {}
+
+__attribute__((device)) void device_attr() {
+ ([]() __attribute__((device)) { device_fn(); })();
+ // expected-warning@-1 {{nvcc does not allow '__device__' to appear after '()' in lambdas}}
+ ([] __attribute__((device)) () { device_fn(); })();
+ ([] __attribute__((device)) { device_fn(); })();
+
+ ([&]() __attribute__((device)){ device_fn(); })();
+ // expected-warning@-1 {{nvcc does not allow '__device__' to appear after '()' in lambdas}}
+ ([&] __attribute__((device)) () { device_fn(); })();
+ ([&] __attribute__((device)) { device_fn(); })();
+
+ ([&](int) __attribute__((device)){ device_fn(); })(0);
+ // expected-warning@-1 {{nvcc does not allow '__device__' to appear after '()' in lambdas}}
+ ([&] __attribute__((device)) (int) { device_fn(); })(0);
+}
+
+__attribute__((host)) __attribute__((device)) void host_device_attrs() {
+ ([]() __attribute__((host)) __attribute__((device)){ hd_fn(); })();
+ // expected-warning@-1 {{nvcc does not allow '__host__' to appear after '()' in lambdas}}
+ // expected-warning@-2 {{nvcc does not allow '__device__' to appear after '()' in lambdas}}
+ ([] __attribute__((host)) __attribute__((device)) () { hd_fn(); })();
+ ([] __attribute__((host)) __attribute__((device)) { hd_fn(); })();
+
+ ([&]() __attribute__((host)) __attribute__((device)){ hd_fn(); })();
+ // expected-warning@-1 {{nvcc does not allow '__host__' to appear after '()' in lambdas}}
+ // expected-warning@-2 {{nvcc does not allow '__device__' to appear after '()' in lambdas}}
+ ([&] __attribute__((host)) __attribute__((device)) () { hd_fn(); })();
+ ([&] __attribute__((host)) __attribute__((device)) { hd_fn(); })();
+
+ ([&](int) __attribute__((host)) __attribute__((device)){ hd_fn(); })(0);
+ // expected-warning@-1 {{nvcc does not allow '__host__' to appear after '()' in lambdas}}
+ // expected-warning@-2 {{nvcc does not allow '__device__' to appear after '()' in lambdas}}
+ ([&] __attribute__((host)) __attribute__((device)) (int) { hd_fn(); })(0);
+}
+
+// TODO: Add tests for __attribute__((global)) once we support global lambdas.
diff --git a/test/Parser/ms-inline-asm.c b/test/Parser/ms-inline-asm.c
index e3c392406957..0170b2b84fa3 100644
--- a/test/Parser/ms-inline-asm.c
+++ b/test/Parser/ms-inline-asm.c
@@ -7,9 +7,9 @@
#define M2 int
void t1(void) { M }
-void t2(void) { __asm int 0x2c }
-void t3(void) { __asm M2 0x2c }
-void t4(void) { __asm mov eax, fs:[0x10] }
+void t2(void) { __asm int 2ch }
+void t3(void) { __asm M2 2ch }
+void t4(void) { __asm mov eax, fs:[10h] }
void t5() {
__asm {
int 0x2c ; } asm comments are fun! }{
@@ -26,7 +26,7 @@ int t6() {
void t7() {
__asm {
push ebx
- mov ebx, 0x07
+ mov ebx, 07h
pop ebx
}
}
@@ -54,7 +54,7 @@ void t12() {
__asm jmp label // expected-error {{use of undeclared label 'label'}}
}
void t13() {
- __asm m{o}v eax, ebx // expected-error {{expected identifier}} expected-error {{use of undeclared label '{o}v eax, ebx'}}
+ __asm m{o}v eax, ebx // expected-error {{unknown token in expression}}
}
int t_fail() { // expected-note {{to match this}}
diff --git a/test/Parser/ms-square-bracket-attributes.mm b/test/Parser/ms-square-bracket-attributes.mm
new file mode 100644
index 000000000000..98b2f6c2d3ea
--- /dev/null
+++ b/test/Parser/ms-square-bracket-attributes.mm
@@ -0,0 +1,174 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify -fms-extensions %s
+
+typedef struct _GUID {
+ unsigned long Data1;
+ unsigned short Data2;
+ unsigned short Data3;
+ unsigned char Data4[8];
+} GUID;
+
+namespace {
+// cl.exe supports [] attributes on decls like so:
+[uuid( "000000A0-0000-0000-C000-000000000049" )] struct struct_with_uuid;
+
+// Optionally, the uuid can be surrounded by one set of braces.
+[uuid(
+ "{000000A0-0000-0000-C000-000000000049}"
+)] struct struct_with_uuid_brace;
+
+// uuids must be ascii string literals.
+// expected-error@+1 {{uuid attribute contains a malformed GUID}}
+[uuid(u8"000000A0-0000-0000-C000-000000000049")] struct struct_with_uuid_u8;
+// expected-error@+1 {{uuid attribute contains a malformed GUID}}
+[uuid(L"000000A0-0000-0000-C000-000000000049")] struct struct_with_uuid_L;
+
+// cl.exe doesn't allow raw string literals in []-style attributes, but does
+// allow it for __declspec(uuid()) (u8 literals etc are not allowed there
+// either). Since raw string literals not being allowed seems like an
+// implementation artifact in cl and not allowing them makes the parse code
+// a bit unnatural, do allow this.
+[uuid(R"(000000A0-0000-0000-C000-000000000049)")] struct struct_with_uuid_raw;
+
+// Likewise, cl supports UCNs in declspec uuid, but not in []-style uuid.
+// clang-cl allows them in both.
+[uuid("000000A0-0000\u002D0000-C000-000000000049")] struct struct_with_uuid_ucn;
+
+// cl doesn't allow string concatenation in []-style attributes, for no good
+// reason. clang-cl allows them.
+[uuid("000000A0-00" "00-0000-C000-000000000049")] struct struct_with_uuid_split;
+
+// expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
+[uuid("{000000A0-0000-0000-C000-000000000049}", "1")] struct S {};
+// expected-error@+1 {{expected '('}}
+[uuid{"000000A0-0000-0000-C000-000000000049"}] struct T {};
+// expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
+[uuid("000000A0-0000-0000-C000-000000000049"}] struct U {};
+
+
+// In addition to uuids in string literals, cl also allows uuids that are not
+// in a string literal, only delimited by (). The contents of () are almost
+// treated like a literal (spaces there aren't ignored), but macro substitution,
+// \ newline escapes, and so on are performed.
+
+[ uuid (000000A0-0000-0000-C000-000000000049) ] struct struct_with_uuid2;
+[uuid({000000A0-0000-0000-C000-000000000049})] struct struct_with_uuid2_brace;
+
+// The non-quoted form doesn't allow any whitespace inside the parens:
+// expected-error@+1 {{uuid attribute contains a malformed GUID}}
+[uuid( 000000A0-0000-0000-C000-000000000049)] struct struct_with_uuid2;
+// expected-error@+1 {{uuid attribute contains a malformed GUID}}
+[uuid(000000A0-0000 -0000-C000-000000000049)] struct struct_with_uuid2;
+// expected-error@+2 {{uuid attribute contains a malformed GUID}}
+[uuid(000000A0-0000
+-0000-C000-000000000049)] struct struct_with_uuid2;
+// expected-error@+1 {{uuid attribute contains a malformed GUID}}
+[uuid(000000A0-0000/**/-0000-C000-000000000049)] struct struct_with_uuid2;
+// expected-error@+1 {{uuid attribute contains a malformed GUID}}
+[uuid(000000A0-0000-0000-C000-000000000049 )] struct struct_with_uuid2;
+// expected-error@+2 {{uuid attribute contains a malformed GUID}}
+[uuid(000000A0-0000-0000-C000-000000000049
+)
+] struct struct_with_uuid2;
+// expected-error@+1 {{uuid attribute contains a malformed GUID}}
+[uuid({000000A0-0000-""0000-C000-000000000049})] struct struct_with_uuid2;
+
+// Line continuations and macro substitution are fine though:
+[uuid(000000A0-0000-0000-\
+C000-000000000049)] struct struct_with_uuid2_cont;
+#define UUID 000000A0-0000-0000-C000-000000000049
+#define UUID_PART 000000A0-0000
+[uuid(UUID)] struct struct_with_uuid2_macro;
+[uuid(UUID_PART-0000-C000-000000000049)] struct struct_with_uuid2_macro_part;
+
+// Both cl and clang-cl accept trigraphs here (with /Zc:trigraphs, off by
+// default)
+// expected-warning@+1 2{{trigraph converted}}
+[uuid(??<000000A0-0000-0000-C000-000000000049??>)]
+struct struct_with_uuid2_trigraph;
+
+// UCNs cannot be used in this form because they're prohibited by C99.
+// expected-error@+1 {{character '-' cannot be specified by a universal character name}}
+[uuid(000000A0-0000\u002D0000-C000-000000000049)] struct struct_with_uuid2_ucn;
+
+// Invalid digits.
+// expected-error@+1 {{uuid attribute contains a malformed GUID}}
+[uuid(0Z0000A0-0000-0000-C000-000000000049)] struct struct_with_uuid2;
+
+struct OuterClass {
+ // [] uuids and inner classes are weird in cl.exe: It warns that uuid on
+ // nested types has undefined behavior, and errors out __uuidof() claiming
+ // that the inner type has no assigned uuid. Things work fine if __declspec()
+ // is used instead. clang-cl handles this fine.
+ [uuid(10000000-0000-0000-0000-000000000000)] class InnerClass1;
+ [uuid(10000000-0000-0000-0000-000000000000)] class InnerClass2 {} ic;
+ [uuid(10000000-0000-0000-0000-000000000000)] static class InnerClass3 {} sic;
+ // Putting `static` in front of [...] causes parse errors in both cl and clang
+
+ // This is the only syntax to declare an inner class with []-style attributes
+ // that works in cl: Declare the inner class without an attribute, and then
+ // have the []-style attribute on the definition.
+ class InnerClass;
+};
+[uuid(10000000-0000-0000-0000-000000000000)] class OuterClass::InnerClass {};
+
+void use_it() {
+ (void)__uuidof(struct_with_uuid);
+ (void)__uuidof(struct_with_uuid_brace);
+ (void)__uuidof(struct_with_uuid_raw);
+ (void)__uuidof(struct_with_uuid_ucn);
+ (void)__uuidof(struct_with_uuid_split);
+
+ (void)__uuidof(struct_with_uuid2);
+ (void)__uuidof(struct_with_uuid2_brace);
+ (void)__uuidof(struct_with_uuid2_cont);
+ (void)__uuidof(struct_with_uuid2_macro);
+ (void)__uuidof(struct_with_uuid2_macro_part);
+ (void)__uuidof(struct_with_uuid2_trigraph);
+
+ (void)__uuidof(OuterClass::InnerClass);
+ (void)__uuidof(OuterClass::InnerClass1);
+ (void)__uuidof(OuterClass::InnerClass2);
+ (void)__uuidof(OuterClass::InnerClass3);
+ (void)__uuidof(OuterClass().ic);
+ (void)__uuidof(OuterClass::sic);
+}
+
+// expected-warning@+1 {{'uuid' attribute only applies to classes}}
+[uuid("000000A0-0000-0000-C000-000000000049")] void f();
+}
+
+// clang supports these on toplevel decls, but not on local decls since this
+// syntax is ambiguous with lambdas and Objective-C message send expressions.
+// This file documents clang's shortcomings and lists a few constructs that
+// one has to keep in mind when trying to fix this. System headers only seem
+// to use these attributes on toplevel decls, so supporting this is not very
+// important.
+
+void local_class() {
+ // FIXME: MSVC accepts, but we reject due to ambiguity.
+ // expected-error@+1 {{expected body of lambda expression}}
+ [uuid("a5a7bd07-3b14-49bc-9399-de066d4d72cd")] struct Local {
+ int x;
+ };
+}
+
+void useit(int);
+int lambda() {
+ int uuid = 42;
+ [uuid]() { useit(uuid); }();
+
+ // C++14 lambda init captures:
+ [uuid(00000000-0000-0000-0000-000000000000)] { return uuid; }();
+ [uuid("00000000-0000-0000-0000-000000000000")](int n) { return uuid[n]; }(3);
+}
+
+@interface NSObject
+- (void)retain;
+@end
+int message_send(id uuid) {
+ [uuid retain];
+}
+NSObject* uuid(const char*);
+int message_send2() {
+ [uuid("a5a7bd07-3b14-49bc-9399-de066d4d72cd") retain];
+}
diff --git a/test/Parser/nullability.c b/test/Parser/nullability.c
index 7117bce4bb74..d70087df9f1f 100644
--- a/test/Parser/nullability.c
+++ b/test/Parser/nullability.c
@@ -11,6 +11,14 @@ _Nonnull int *ptr2; // no-warning
# error Nullability should always be supported
#endif
+#if !__has_feature(nullability_on_arrays)
+# error Nullability on array parameters should always be supported
+#endif
+
#if !__has_extension(nullability)
# error Nullability should always be supported as an extension
#endif
+
+#if !__has_extension(nullability_on_arrays)
+# error Nullability on array parameters should always be supported as an extension
+#endif
diff --git a/test/Parser/objc-at-directive-fixit.m b/test/Parser/objc-at-directive-fixit.m
new file mode 100644
index 000000000000..dcf695d3aaa2
--- /dev/null
+++ b/test/Parser/objc-at-directive-fixit.m
@@ -0,0 +1,28 @@
+// RUN: %clang_cc1 -fsyntax-only -triple x86_64-apple-macosx10.10.0 -verify -fobjc-exceptions %s
+// RUN: not %clang_cc1 -fsyntax-only -triple x86_64-apple-macosx10.10.0 -fdiagnostics-parseable-fixits -fobjc-exceptions %s 2>&1 | FileCheck %s
+
+// rdar://19669565
+
+void bar(int x);
+
+void f() {
+ @try { }
+ @finally { }
+ @autoreleasepool { }
+
+ // Provide a fixit when we are parsing a standalone statement
+ @tr { }; // expected-error {{unexpected '@' in program}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:4-[[@LINE-1]]:6}:"try"
+ @finaly { }; // expected-error {{unexpected '@' in program}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:4-[[@LINE-1]]:10}:"finally"
+ @autorelpool { }; // expected-error {{unexpected '@' in program}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:4-[[@LINE-1]]:15}:"autoreleasepool"
+
+ // Ensure that no fixit is given when parsing expressions
+ // CHECK-NOT: fix-it
+ id thing = @autoreleasepool { }; // expected-error {{unexpected '@' in program}}
+ (void)@tr { }; // expected-error {{unexpected '@' in program}}
+ bar(@final { }); // expected-error {{unexpected '@' in program}}
+ for(@auto;;) { } // expected-error {{unexpected '@' in program}}
+ [@try]; // expected-error {{unexpected '@' in program}}
+}
diff --git a/test/Parser/objc-available.m b/test/Parser/objc-available.m
index ca3075314435..d18ac1f13445 100644
--- a/test/Parser/objc-available.m
+++ b/test/Parser/objc-available.m
@@ -15,8 +15,6 @@ void f() {
(void)@available(erik_os 10.10, hat_os 1.0, *); // expected-error 2 {{unrecognized platform name}}
- (void)@available(ios 8, *); // expected-warning{{using '*' case here, platform macos is not accounted for}}
-
(void)@available(); // expected-error{{expected a platform name here}}
(void)@available(macos 10.10,); // expected-error{{expected a platform name here}}
(void)@available(macos); // expected-error{{expected a version}}
diff --git a/test/Parser/objc-property-syntax.m b/test/Parser/objc-property-syntax.m
index 38d12d5905c3..8e56a090018e 100644
--- a/test/Parser/objc-property-syntax.m
+++ b/test/Parser/objc-property-syntax.m
@@ -4,7 +4,7 @@
int prop;
};
@property unsigned char bufferedUTF8Bytes[4]; // expected-error {{property cannot have array or function type}}
-@property unsigned char bufferedUTFBytes:1; // expected-error {{property name cannot be a bitfield}}
+@property unsigned char bufferedUTFBytes:1; // expected-error {{property name cannot be a bit-field}}
@property(nonatomic, retain, setter=ab_setDefaultToolbarItems) MyClass *ab_defaultToolbarItems; // expected-error {{method name referenced in property setter attribute must end with ':'}}
@property int prop;
diff --git a/test/Parser/opencl-atomics-cl20.cl b/test/Parser/opencl-atomics-cl20.cl
index cd37757b97f6..65fb9d9b42a8 100644
--- a/test/Parser/opencl-atomics-cl20.cl
+++ b/test/Parser/opencl-atomics-cl20.cl
@@ -1,5 +1,6 @@
// RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify -pedantic -fsyntax-only
// RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify -fsyntax-only -cl-std=CL2.0 -DCL20
+// RUN: %clang_cc1 %s -triple spir64-unknown-unknown -verify -fsyntax-only -cl-std=CL2.0 -DCL20
// RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify -fsyntax-only -cl-std=CL2.0 -DCL20 -DEXT -Wpedantic-core-features
#ifdef EXT
@@ -47,14 +48,16 @@ void atomic_types_test() {
// expected-error@-28 {{use of type 'atomic_ulong' (aka '_Atomic(unsigned long)') requires cl_khr_int64_extended_atomics extension to be enabled}}
// expected-error@-27 {{use of type 'atomic_double' (aka '_Atomic(double)') requires cl_khr_int64_base_atomics extension to be enabled}}
// expected-error@-28 {{use of type 'atomic_double' (aka '_Atomic(double)') requires cl_khr_int64_extended_atomics extension to be enabled}}
-// expected-error-re@-27 {{use of type 'atomic_intptr_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_base_atomics extension to be enabled}}
-// expected-error-re@-28 {{use of type 'atomic_intptr_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_extended_atomics extension to be enabled}}
-// expected-error-re@-28 {{use of type 'atomic_uintptr_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_base_atomics extension to be enabled}}
-// expected-error-re@-29 {{use of type 'atomic_uintptr_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_extended_atomics extension to be enabled}}
-// expected-error-re@-29 {{use of type 'atomic_size_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_base_atomics extension to be enabled}}
-// expected-error-re@-30 {{use of type 'atomic_size_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_extended_atomics extension to be enabled}}
-// expected-error-re@-30 {{use of type 'atomic_ptrdiff_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_base_atomics extension to be enabled}}
-// expected-error-re@-31 {{use of type 'atomic_ptrdiff_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_extended_atomics extension to be enabled}}
+#if __LP64__
+// expected-error-re@-28 {{use of type 'atomic_intptr_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_base_atomics extension to be enabled}}
+// expected-error-re@-29 {{use of type 'atomic_intptr_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_extended_atomics extension to be enabled}}
+// expected-error-re@-29 {{use of type 'atomic_uintptr_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_base_atomics extension to be enabled}}
+// expected-error-re@-30 {{use of type 'atomic_uintptr_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_extended_atomics extension to be enabled}}
+// expected-error-re@-30 {{use of type 'atomic_size_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_base_atomics extension to be enabled}}
+// expected-error-re@-31 {{use of type 'atomic_size_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_extended_atomics extension to be enabled}}
+// expected-error-re@-31 {{use of type 'atomic_ptrdiff_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_base_atomics extension to be enabled}}
+// expected-error-re@-32 {{use of type 'atomic_ptrdiff_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_extended_atomics extension to be enabled}}
+#endif
#endif
#ifdef CL20
diff --git a/test/Parser/opencl-pragma.cl b/test/Parser/opencl-pragma.cl
index b002b0854a4d..02f053fb40d9 100644
--- a/test/Parser/opencl-pragma.cl
+++ b/test/Parser/opencl-pragma.cl
@@ -5,9 +5,9 @@
#pragma OPENCL EXTENSION cl_no_such_extension : disable /* expected-warning {{unknown OpenCL extension 'cl_no_such_extension' - ignoring}} */
#pragma OPENCL EXTENSION all : disable
-#pragma OPENCL EXTENSION all : enable /* expected-warning {{unknown OpenCL extension 'all' - ignoring}} */
+#pragma OPENCL EXTENSION all : enable /* expected-warning {{expected 'disable' - ignoring}} */
-#pragma OPENCL EXTENSION cl_khr_fp64 : on /* expected-warning {{expected 'enable' or 'disable' - ignoring}} */
+#pragma OPENCL EXTENSION cl_khr_fp64 : on /* expected-warning {{expected 'enable', 'disable', 'begin' or 'end' - ignoring}} */
#pragma OPENCL FP_CONTRACT ON
#pragma OPENCL FP_CONTRACT OFF
diff --git a/test/Preprocessor/aarch64-target-features.c b/test/Preprocessor/aarch64-target-features.c
index 5ec9bc685d76..aef788dd083e 100644
--- a/test/Preprocessor/aarch64-target-features.c
+++ b/test/Preprocessor/aarch64-target-features.c
@@ -94,6 +94,8 @@
// RUN: %clang -target aarch64 -mcpu=cortex-a72 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-A72 %s
// RUN: %clang -target aarch64 -mcpu=cortex-a73 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-CORTEX-A73 %s
// 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=kryo -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-KRYO %s
// RUN: %clang -target aarch64 -mcpu=vulcan -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MCPU-VULCAN %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 be235606e25a..f45c5ba07f0f 100644
--- a/test/Preprocessor/arm-target-features.c
+++ b/test/Preprocessor/arm-target-features.c
@@ -9,6 +9,15 @@
// CHECK-V8A: #define __ARM_FP16_ARGS 1
// CHECK-V8A: #define __ARM_FP16_FORMAT_IEEE 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
+// CHECK-V8R: #define __ARM_ARCH 8
+// CHECK-V8R: #define __ARM_ARCH_8R__ 1
+// 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
+
// 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
// CHECK-V7: #define __ARM_ARCH 7
@@ -380,6 +389,7 @@
// 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
// Test whether predefines are as expected when targeting krait.
// RUN: %clang -target armv7 -mcpu=krait -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=KRAIT %s
diff --git a/test/Preprocessor/cuda-approx-transcendentals.cu b/test/Preprocessor/cuda-approx-transcendentals.cu
index 8d106ea27a7f..409eabb4dac0 100644
--- a/test/Preprocessor/cuda-approx-transcendentals.cu
+++ b/test/Preprocessor/cuda-approx-transcendentals.cu
@@ -1,7 +1,7 @@
// RUN: %clang --cuda-host-only -nocudainc -target i386-unknown-linux-gnu -x cuda -E -dM -o - /dev/null | FileCheck --check-prefix HOST %s
-// RUN: %clang --cuda-device-only -nocudainc -target i386-unknown-linux-gnu -x cuda -E -dM -o - /dev/null | FileCheck --check-prefix DEVICE-NOFAST %s
-// RUN: %clang -fcuda-approx-transcendentals --cuda-device-only -nocudainc -target i386-unknown-linux-gnu -x cuda -E -dM -o - /dev/null | FileCheck --check-prefix DEVICE-FAST %s
-// RUN: %clang -ffast-math --cuda-device-only -nocudainc -target i386-unknown-linux-gnu -x cuda -E -dM -o - /dev/null | FileCheck --check-prefix DEVICE-FAST %s
+// RUN: %clang --cuda-device-only -nocudainc -nocudalib -target i386-unknown-linux-gnu -x cuda -E -dM -o - /dev/null | FileCheck --check-prefix DEVICE-NOFAST %s
+// RUN: %clang -fcuda-approx-transcendentals --cuda-device-only -nocudainc -nocudalib -target i386-unknown-linux-gnu -x cuda -E -dM -o - /dev/null | FileCheck --check-prefix DEVICE-FAST %s
+// RUN: %clang -ffast-math --cuda-device-only -nocudainc -nocudalib -target i386-unknown-linux-gnu -x cuda -E -dM -o - /dev/null | FileCheck --check-prefix DEVICE-FAST %s
// HOST-NOT: __CLANG_CUDA_APPROX_TRANSCENDENTALS__
// DEVICE-NOFAST-NOT: __CLANG_CUDA_APPROX_TRANSCENDENTALS__
diff --git a/test/Preprocessor/cuda-macos-includes.cu b/test/Preprocessor/cuda-macos-includes.cu
new file mode 100644
index 000000000000..6ef94b0e4535
--- /dev/null
+++ b/test/Preprocessor/cuda-macos-includes.cu
@@ -0,0 +1,13 @@
+// RUN: %clang -cc1 -fcuda-is-device -isysroot /var/empty \
+// RUN: -triple nvptx-nvidia-cuda -aux-triple i386-apple-macosx \
+// RUN: -E -fcuda-is-device -v -o /dev/null -x cuda %s 2>&1 | FileCheck %s
+
+// RUN: %clang -cc1 -isysroot /var/empty \
+// RUN: -triple i386-apple-macosx -aux-triple nvptx-nvidia-cuda \
+// RUN: -E -fcuda-is-device -v -o /dev/null -x cuda %s 2>&1 | FileCheck %s
+
+// Check that when we do CUDA host and device compiles on MacOS, we check for
+// includes in /System/Library/Frameworks and /Library/Frameworks.
+
+// CHECK-DAG: ignoring nonexistent directory "/var/empty/System/Library/Frameworks"
+// CHECK-DAG: ignoring nonexistent directory "/var/empty/Library/Frameworks"
diff --git a/test/Preprocessor/cuda-preprocess.cu b/test/Preprocessor/cuda-preprocess.cu
index 9751bfd6d5b3..84a7bcf2a12f 100644
--- a/test/Preprocessor/cuda-preprocess.cu
+++ b/test/Preprocessor/cuda-preprocess.cu
@@ -13,20 +13,20 @@ clang_unittest_cuda_arch __CUDA_ARCH__
// CHECK-NOT: PREPROCESSED_AWAY
-// RUN: %clang -E -target x86_64-linux-gnu --cuda-gpu-arch=sm_20 -nocudainc %s 2>&1 \
+// RUN: %clang -E -target x86_64-linux-gnu --cuda-gpu-arch=sm_20 -nocudainc -nocudalib %s 2>&1 \
// RUN: | FileCheck -check-prefix NOARCH %s
// RUN: %clang -E -target x86_64-linux-gnu --cuda-gpu-arch=sm_20 --cuda-host-only -nocudainc %s 2>&1 \
// RUN: | FileCheck -check-prefix NOARCH %s
// NOARCH: clang_unittest_no_arch
-// RUN: %clang -E -target x86_64-linux-gnu --cuda-gpu-arch=sm_20 --cuda-device-only -nocudainc %s 2>&1 \
+// RUN: %clang -E -target x86_64-linux-gnu --cuda-gpu-arch=sm_20 --cuda-device-only -nocudainc -nocudalib %s 2>&1 \
// RUN: | FileCheck -check-prefix SM20 %s
// SM20: clang_unittest_cuda_arch 200
-// RUN: %clang -E -target x86_64-linux-gnu --cuda-gpu-arch=sm_30 --cuda-device-only -nocudainc %s 2>&1 \
+// RUN: %clang -E -target x86_64-linux-gnu --cuda-gpu-arch=sm_30 --cuda-device-only -nocudainc -nocudalib %s 2>&1 \
// RUN: | FileCheck -check-prefix SM30 %s
// SM30: clang_unittest_cuda_arch 300
// RUN: %clang -E -target x86_64-linux-gnu --cuda-gpu-arch=sm_20 --cuda-gpu-arch=sm_30 \
-// RUN: --cuda-device-only -nocudainc %s 2>&1 \
+// RUN: --cuda-device-only -nocudainc -nocudalib %s 2>&1 \
// RUN: | FileCheck -check-prefix SM20 -check-prefix SM30 %s
diff --git a/test/Preprocessor/cuda-types.cu b/test/Preprocessor/cuda-types.cu
index dd8eef4aaef5..2b6160b8d6c7 100644
--- a/test/Preprocessor/cuda-types.cu
+++ b/test/Preprocessor/cuda-types.cu
@@ -1,27 +1,30 @@
-// Check that types, widths, etc. match on the host and device sides of CUDA
-// compilations. Note that we filter out long double, as this is intentionally
-// different on host and device.
+// Check that types, widths, __GCC_ATOMIC* macros, etc. match on the host and
+// device sides of CUDA compilations. Note that we filter out long double, as
+// this is intentionally different on host and device.
+//
+// FIXME: We really should make __GCC_HAVE_SYNC_COMPARE_AND_SWAP identical on
+// host and device, but architecturally this is difficult at the moment.
-// RUN: %clang --cuda-host-only -nocudainc -target i386-unknown-linux-gnu -x cuda -E -dM -o - /dev/null > %T/i386-host-defines
-// RUN: %clang --cuda-device-only -nocudainc -target i386-unknown-linux-gnu -x cuda -E -dM -o - /dev/null > %T/i386-device-defines
-// RUN: grep 'define __[^ ]*\(TYPE\|MAX\|SIZEOF|WIDTH\)' %T/i386-host-defines | grep -v '__LDBL\|_LONG_DOUBLE' > %T/i386-host-defines-filtered
-// RUN: grep 'define __[^ ]*\(TYPE\|MAX\|SIZEOF|WIDTH\)' %T/i386-device-defines | grep -v '__LDBL\|_LONG_DOUBLE' > %T/i386-device-defines-filtered
+// 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 '__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 '__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 > %T/x86_64-host-defines
-// RUN: %clang --cuda-device-only -nocudainc -target x86_64-unknown-linux-gnu -x cuda -E -dM -o - /dev/null > %T/x86_64-device-defines
-// RUN: grep 'define __[^ ]*\(TYPE\|MAX\|SIZEOF\|WIDTH\)' %T/x86_64-host-defines | grep -v '__LDBL\|_LONG_DOUBLE' > %T/x86_64-host-defines-filtered
-// RUN: grep 'define __[^ ]*\(TYPE\|MAX\|SIZEOF\|WIDTH\)' %T/x86_64-device-defines | grep -v '__LDBL\|_LONG_DOUBLE' > %T/x86_64-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 '__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 '__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 > %T/powerpc64-host-defines
-// RUN: %clang --cuda-device-only -nocudainc -target powerpc64-unknown-linux-gnu -x cuda -E -dM -o - /dev/null > %T/powerpc64-device-defines
-// RUN: grep 'define __[^ ]*\(TYPE\|MAX\|SIZEOF\|WIDTH\)' %T/powerpc64-host-defines | grep -v '__LDBL\|_LONG_DOUBLE' > %T/powerpc64-host-defines-filtered
-// RUN: grep 'define __[^ ]*\(TYPE\|MAX\|SIZEOF\|WIDTH\)' %T/powerpc64-device-defines | grep -v '__LDBL\|_LONG_DOUBLE' > %T/powerpc64-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 '__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 '__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 nvptx-nvidia-cuda -x cuda -E -dM -o - /dev/null > %T/nvptx-host-defines
-// RUN: %clang --cuda-device-only -nocudainc -target nvptx-nvidia-cuda -x cuda -E -dM -o - /dev/null > %T/nvptx-device-defines
-// RUN: grep 'define __[^ ]*\(TYPE\|MAX\|SIZEOF\|WIDTH\)' %T/nvptx-host-defines | grep -v '__LDBL\|_LONG_DOUBLE' > %T/nvptx-host-defines-filtered
-// RUN: grep 'define __[^ ]*\(TYPE\|MAX\|SIZEOF\|WIDTH\)' %T/nvptx-device-defines | grep -v '__LDBL\|_LONG_DOUBLE' > %T/nvptx-device-defines-filtered
-// RUN: diff %T/nvptx-host-defines-filtered %T/nvptx-device-defines-filtered
diff --git a/test/Preprocessor/dump_import.h b/test/Preprocessor/dump_import.h
new file mode 100644
index 000000000000..fded1e52cbbf
--- /dev/null
+++ b/test/Preprocessor/dump_import.h
@@ -0,0 +1 @@
+#define DUMP_IMPORT_TESTVAL 1
diff --git a/test/Preprocessor/dump_import.m b/test/Preprocessor/dump_import.m
new file mode 100644
index 000000000000..20424ad507bd
--- /dev/null
+++ b/test/Preprocessor/dump_import.m
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -E -dI %s -o - | FileCheck %s
+// CHECK: {{^}}#import "dump_
+
+// See also `dump_include.c` which tests other inclusion cases with `-dI`.
+
+#import "dump_import.h"
diff --git a/test/Preprocessor/dump_include.c b/test/Preprocessor/dump_include.c
new file mode 100644
index 000000000000..4d7d857d5f1b
--- /dev/null
+++ b/test/Preprocessor/dump_include.c
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -w -E -dI -isystem %S -imacros %S/dump_include.h %s -o - | FileCheck %s
+// CHECK: {{^}}#__include_macros "{{.*}}dump_
+// CHECK: {{^}}#include <dump_
+// CHECK: {{^}}#include "dump_
+// CHECK: {{^}}#include_next "dump_
+
+// See also `dump_import.m` which tests the `#import` directive with `-dI`.
+
+#include <dump_include.h>
+#include "dump_include.h"
+#include_next "dump_include.h"
diff --git a/test/Preprocessor/dump_include.h b/test/Preprocessor/dump_include.h
new file mode 100644
index 000000000000..9dafaa50b5c5
--- /dev/null
+++ b/test/Preprocessor/dump_include.h
@@ -0,0 +1,2 @@
+#pragma once
+#define DUMP_INCLUDE_TESTVAL 1
diff --git a/test/Preprocessor/header_is_main_file.c b/test/Preprocessor/header_is_main_file.c
new file mode 100644
index 000000000000..03ade13ff333
--- /dev/null
+++ b/test/Preprocessor/header_is_main_file.c
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -x c-header -ffreestanding -Eonly -verify %s
+// expected-no-diagnostics
+
+#pragma once
+#include_next "stdint.h"
+#if !__has_include_next("stdint.h")
+#error "__has_include_next failed"
+#endif
diff --git a/test/Preprocessor/init.c b/test/Preprocessor/init.c
index adf5c778767e..b003404df6ff 100644
--- a/test/Preprocessor/init.c
+++ b/test/Preprocessor/init.c
@@ -64,6 +64,9 @@
//
//
// RUN: %clang_cc1 -std=c11 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix C11 %s
+// RUN: %clang_cc1 -std=c1x -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix C11 %s
+// RUN: %clang_cc1 -std=iso9899:2011 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix C11 %s
+// RUN: %clang_cc1 -std=iso9899:201x -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix C11 %s
//
// C11:#define __STDC_UTF_16__ 1
// C11:#define __STDC_UTF_32__ 1
@@ -205,6 +208,12 @@
// O1:#define __OPTIMIZE__ 1
//
//
+// RUN: %clang_cc1 -Og -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix Og %s
+//
+// Og-NOT:#define __OPTIMIZE_SIZE__
+// Og :#define __OPTIMIZE__ 1
+//
+//
// RUN: %clang_cc1 -Os -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix Os %s
//
// Os:#define __OPTIMIZE_SIZE__ 1
@@ -247,6 +256,7 @@
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=aarch64-none-none < /dev/null | FileCheck -match-full-lines -check-prefix AARCH64 %s
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=arm64-none-none < /dev/null | FileCheck -match-full-lines -check-prefix AARCH64 %s
+// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=arm64-none-none < /dev/null | FileCheck -match-full-lines -check-prefix AARCH64 -check-prefix AARCH64-CXX %s
//
// AARCH64:#define _LP64 1
// AARCH64-NOT:#define __AARCH64EB__ 1
@@ -393,6 +403,7 @@
// AARCH64:#define __SIZE_MAX__ 18446744073709551615UL
// AARCH64:#define __SIZE_TYPE__ long unsigned int
// AARCH64:#define __SIZE_WIDTH__ 64
+// AARCH64-CXX:#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 16UL
// AARCH64:#define __UINT16_C_SUFFIX__
// AARCH64:#define __UINT16_MAX__ 65535
// AARCH64:#define __UINT16_TYPE__ unsigned short
@@ -1206,6 +1217,7 @@
// AARCH64-DARWIN: #define __aarch64__ 1
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=arm-none-none < /dev/null | FileCheck -match-full-lines -check-prefix ARM %s
+// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=arm-none-none < /dev/null | FileCheck -match-full-lines -check-prefix ARM -check-prefix ARM-CXX %s
//
// ARM-NOT:#define _LP64
// ARM:#define __APCS_32__ 1
@@ -1351,6 +1363,7 @@
// ARM:#define __SIZE_MAX__ 4294967295U
// ARM:#define __SIZE_TYPE__ unsigned int
// ARM:#define __SIZE_WIDTH__ 32
+// ARM-CXX:#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 8U
// ARM:#define __UINT16_C_SUFFIX__
// ARM:#define __UINT16_MAX__ 65535
// ARM:#define __UINT16_TYPE__ unsigned short
@@ -2431,6 +2444,7 @@
// I386:#define i386 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=i386-pc-linux-gnu -target-cpu pentium4 < /dev/null | FileCheck -match-full-lines -check-prefix I386-LINUX %s
+// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=i386-pc-linux-gnu -target-cpu pentium4 < /dev/null | FileCheck -match-full-lines -check-prefix I386-LINUX -check-prefix I386-LINUX-CXX %s
//
// I386-LINUX-NOT:#define _LP64
// I386-LINUX:#define __BIGGEST_ALIGNMENT__ 16
@@ -2572,6 +2586,7 @@
// I386-LINUX:#define __SIZE_MAX__ 4294967295U
// I386-LINUX:#define __SIZE_TYPE__ unsigned int
// I386-LINUX:#define __SIZE_WIDTH__ 32
+// I386-LINUX-CXX:#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 8U
// I386-LINUX:#define __UINT16_C_SUFFIX__
// I386-LINUX:#define __UINT16_MAX__ 65535
// I386-LINUX:#define __UINT16_TYPE__ unsigned short
@@ -2618,6 +2633,7 @@
// I386-LINUX:#define i386 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=i386-netbsd < /dev/null | FileCheck -match-full-lines -check-prefix I386-NETBSD %s
+// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=i386-netbsd < /dev/null | FileCheck -match-full-lines -check-prefix I386-NETBSD -check-prefix I386-NETBSD-CXX %s
//
// I386-NETBSD-NOT:#define _LP64
// I386-NETBSD:#define __BIGGEST_ALIGNMENT__ 16
@@ -2759,6 +2775,7 @@
// I386-NETBSD:#define __SIZE_MAX__ 4294967295U
// I386-NETBSD:#define __SIZE_TYPE__ unsigned int
// I386-NETBSD:#define __SIZE_WIDTH__ 32
+// I386-NETBSD-CXX:#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 4U
// I386-NETBSD:#define __UINT16_C_SUFFIX__
// I386-NETBSD:#define __UINT16_MAX__ 65535
// I386-NETBSD:#define __UINT16_TYPE__ unsigned short
@@ -2818,7 +2835,8 @@
// I386-DECLSPEC: #define __declspec{{.*}}
//
-// RUN: %clang_cc1 -E -dM -ffreestanding -triple=mips-none-none < /dev/null | FileCheck -match-full-lines -check-prefix MIPS32BE %s
+// RUN: %clang_cc1 -E -dM -ffreestanding -triple=mips-none-none < /dev/null | FileCheck -match-full-lines -check-prefix MIPS32BE -check-prefix MIPS32BE-C %s
+// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=mips-none-none < /dev/null | FileCheck -match-full-lines -check-prefix MIPS32BE -check-prefix MIPS32BE-CXX %s
//
// MIPS32BE:#define MIPSEB 1
// MIPS32BE:#define _ABIO32 1
@@ -2973,8 +2991,9 @@
// MIPS32BE:#define __SIZE_MAX__ 4294967295U
// MIPS32BE:#define __SIZE_TYPE__ unsigned int
// MIPS32BE:#define __SIZE_WIDTH__ 32
+// MIPS32BE-CXX:#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 8U
// MIPS32BE:#define __STDC_HOSTED__ 0
-// MIPS32BE:#define __STDC_VERSION__ 201112L
+// MIPS32BE-C:#define __STDC_VERSION__ 201112L
// MIPS32BE:#define __STDC__ 1
// MIPS32BE:#define __UINT16_C_SUFFIX__
// MIPS32BE:#define __UINT16_MAX__ 65535
@@ -3235,7 +3254,10 @@
//
// RUN: %clang_cc1 -E -dM -ffreestanding \
// RUN: -triple=mips64-none-none -target-abi n32 < /dev/null \
-// RUN: | FileCheck -match-full-lines -check-prefix MIPSN32BE %s
+// RUN: | FileCheck -match-full-lines -check-prefix MIPSN32BE -check-prefix MIPSN32BE-C %s
+// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding \
+// RUN: -triple=mips64-none-none -target-abi n32 < /dev/null \
+// RUN: | FileCheck -match-full-lines -check-prefix MIPSN32BE -check-prefix MIPSN32BE-CXX %s
//
// MIPSN32BE: #define MIPSEB 1
// MIPSN32BE: #define _ABIN32 2
@@ -3304,7 +3326,7 @@
// MIPSN32BE: #define __GCC_ATOMIC_WCHAR_T_LOCK_FREE 2
// MIPSN32BE: #define __GNUC_MINOR__ 2
// MIPSN32BE: #define __GNUC_PATCHLEVEL__ 1
-// MIPSN32BE: #define __GNUC_STDC_INLINE__ 1
+// MIPSN32BE-C: #define __GNUC_STDC_INLINE__ 1
// MIPSN32BE: #define __GNUC__ 4
// MIPSN32BE: #define __GXX_ABI_VERSION 1002
// MIPSN32BE: #define __ILP32__ 1
@@ -3424,10 +3446,11 @@
// MIPSN32BE: #define __SIZE_MAX__ 4294967295U
// MIPSN32BE: #define __SIZE_TYPE__ unsigned int
// MIPSN32BE: #define __SIZE_WIDTH__ 32
+// MIPSN32BE-CXX: #define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 16U
// MIPSN32BE: #define __STDC_HOSTED__ 0
// MIPSN32BE: #define __STDC_UTF_16__ 1
// MIPSN32BE: #define __STDC_UTF_32__ 1
-// MIPSN32BE: #define __STDC_VERSION__ 201112L
+// MIPSN32BE-C: #define __STDC_VERSION__ 201112L
// MIPSN32BE: #define __STDC__ 1
// MIPSN32BE: #define __UINT16_C_SUFFIX__
// MIPSN32BE: #define __UINT16_FMTX__ "hX"
@@ -3846,6 +3869,7 @@
// MIPSN32EL: #define mips 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=mips64-none-none < /dev/null | FileCheck -match-full-lines -check-prefix MIPS64BE %s
+// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=mips64-none-none < /dev/null | FileCheck -match-full-lines -check-prefix MIPS64BE -check-prefix MIPS64BE-CXX %s
//
// MIPS64BE:#define MIPSEB 1
// MIPS64BE:#define _ABI64 3
@@ -4001,6 +4025,7 @@
// MIPS64BE:#define __SIZE_MAX__ 18446744073709551615UL
// MIPS64BE:#define __SIZE_TYPE__ long unsigned int
// MIPS64BE:#define __SIZE_WIDTH__ 64
+// MIPS64BE-CXX:#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 16UL
// MIPS64BE:#define __UINT16_C_SUFFIX__
// MIPS64BE:#define __UINT16_MAX__ 65535
// MIPS64BE:#define __UINT16_TYPE__ unsigned short
@@ -4489,6 +4514,7 @@
// MIPS-XXR6:#define __mips_nan2008 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=msp430-none-none < /dev/null | FileCheck -match-full-lines -check-prefix MSP430 %s
+// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=msp430-none-none < /dev/null | FileCheck -match-full-lines -check-prefix MSP430 -check-prefix MSP430-CXX %s
//
// MSP430:#define MSP430 1
// MSP430-NOT:#define _LP64
@@ -4630,6 +4656,7 @@
// MSP430:#define __SIZE_MAX__ 65535U
// MSP430:#define __SIZE_TYPE__ unsigned int
// MSP430:#define __SIZE_WIDTH__ 16
+// MSP430-CXX:#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 8U
// MSP430:#define __UINT16_C_SUFFIX__ U
// MSP430:#define __UINT16_MAX__ 65535U
// MSP430:#define __UINT16_TYPE__ unsigned short
@@ -4674,6 +4701,7 @@
// MSP430:#define __clang__ 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=nvptx-none-none < /dev/null | FileCheck -match-full-lines -check-prefix NVPTX32 %s
+// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=nvptx-none-none < /dev/null | FileCheck -match-full-lines -check-prefix NVPTX32 -check-prefix NVPTX32-CXX %s
//
// NVPTX32-NOT:#define _LP64
// NVPTX32:#define __BIGGEST_ALIGNMENT__ 8
@@ -4818,6 +4846,7 @@
// NVPTX32:#define __SIZE_MAX__ 4294967295U
// NVPTX32:#define __SIZE_TYPE__ unsigned int
// NVPTX32:#define __SIZE_WIDTH__ 32
+// NVPTX32-CXX:#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 8U
// NVPTX32:#define __UINT16_C_SUFFIX__
// NVPTX32:#define __UINT16_MAX__ 65535
// NVPTX32:#define __UINT16_TYPE__ unsigned short
@@ -4861,6 +4890,7 @@
// NVPTX32:#define __WINT_WIDTH__ 32
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=nvptx64-none-none < /dev/null | FileCheck -match-full-lines -check-prefix NVPTX64 %s
+// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=nvptx64-none-none < /dev/null | FileCheck -match-full-lines -check-prefix NVPTX64 -check-prefix NVPTX64-CXX %s
//
// NVPTX64:#define _LP64 1
// NVPTX64:#define __BIGGEST_ALIGNMENT__ 8
@@ -5005,6 +5035,7 @@
// NVPTX64:#define __SIZE_MAX__ 18446744073709551615UL
// NVPTX64:#define __SIZE_TYPE__ long unsigned int
// NVPTX64:#define __SIZE_WIDTH__ 64
+// NVPTX64-CXX:#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 8UL
// NVPTX64:#define __UINT16_C_SUFFIX__
// NVPTX64:#define __UINT16_MAX__ 65535
// NVPTX64:#define __UINT16_TYPE__ unsigned short
@@ -5048,6 +5079,7 @@
// NVPTX64:#define __WINT_WIDTH__ 32
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc-none-none -target-cpu 603e < /dev/null | FileCheck -match-full-lines -check-prefix PPC603E %s
+// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=powerpc-none-none -target-cpu 603e < /dev/null | FileCheck -match-full-lines -check-prefix PPC603E-CXX %s
//
// PPC603E:#define _ARCH_603 1
// PPC603E:#define _ARCH_603E 1
@@ -5197,6 +5229,7 @@
// PPC603E:#define __SIZE_MAX__ 4294967295UL
// PPC603E:#define __SIZE_TYPE__ long unsigned int
// PPC603E:#define __SIZE_WIDTH__ 32
+// PPC603E-CXX:#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 16UL
// PPC603E:#define __UINT16_C_SUFFIX__
// PPC603E:#define __UINT16_MAX__ 65535
// PPC603E:#define __UINT16_TYPE__ unsigned short
@@ -5242,6 +5275,7 @@
// PPC603E:#define __ppc__ 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-none-none -target-cpu pwr7 -fno-signed-char < /dev/null | FileCheck -match-full-lines -check-prefix PPC64 %s
+// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=powerpc64-none-none -target-cpu pwr7 -fno-signed-char < /dev/null | FileCheck -match-full-lines -check-prefix PPC64 -check-prefix PPC64-CXX %s
//
// PPC64:#define _ARCH_PPC 1
// PPC64:#define _ARCH_PPC64 1
@@ -5397,6 +5431,7 @@
// PPC64:#define __SIZE_MAX__ 18446744073709551615UL
// PPC64:#define __SIZE_TYPE__ long unsigned int
// PPC64:#define __SIZE_WIDTH__ 64
+// PPC64-CXX:#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 16UL
// PPC64:#define __UINT16_C_SUFFIX__
// PPC64:#define __UINT16_MAX__ 65535
// PPC64:#define __UINT16_TYPE__ unsigned short
@@ -6653,6 +6688,7 @@
// RUN: %clang_cc1 -x cl -E -dM -ffreestanding -triple=amdgcn < /dev/null | FileCheck -match-full-lines -check-prefix AMDGCN --check-prefix AMDGPU %s
// RUN: %clang_cc1 -x cl -E -dM -ffreestanding -triple=r600 -target-cpu caicos < /dev/null | FileCheck -match-full-lines --check-prefix AMDGPU %s
//
+// AMDGPU:#define __ENDIAN_LITTLE__ 1
// AMDGPU:#define cl_khr_byte_addressable_store 1
// AMDGCN:#define cl_khr_fp64 1
// AMDGPU:#define cl_khr_global_int32_base_atomics 1
@@ -6661,6 +6697,7 @@
// AMDGPU:#define cl_khr_local_int32_extended_atomics 1
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=s390x-none-none -fno-signed-char < /dev/null | FileCheck -match-full-lines -check-prefix S390X %s
+// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=s390x-none-none -fno-signed-char < /dev/null | FileCheck -match-full-lines -check-prefix S390X -check-prefix S390X-CXX %s
//
// S390X:#define __BIGGEST_ALIGNMENT__ 8
// S390X:#define __CHAR16_TYPE__ unsigned short
@@ -6797,6 +6834,7 @@
// S390X:#define __SIZEOF_WINT_T__ 4
// S390X:#define __SIZE_TYPE__ long unsigned int
// S390X:#define __SIZE_WIDTH__ 64
+// S390X-CXX:#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 8UL
// S390X:#define __UINT16_C_SUFFIX__
// S390X:#define __UINT16_MAX__ 65535
// S390X:#define __UINT16_TYPE__ unsigned short
@@ -6845,6 +6883,8 @@
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=sparc-rtems-elf < /dev/null | FileCheck -match-full-lines -check-prefix SPARC -check-prefix SPARC-DEFAULT %s
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=sparc-none-netbsd < /dev/null | FileCheck -match-full-lines -check-prefix SPARC -check-prefix SPARC-NETOPENBSD %s
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=sparc-none-openbsd < /dev/null | FileCheck -match-full-lines -check-prefix SPARC -check-prefix SPARC-NETOPENBSD %s
+// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=sparc-none-none < /dev/null | FileCheck -match-full-lines -check-prefix SPARC -check-prefix SPARC-DEFAULT -check-prefix SPARC-DEFAULT-CXX %s
+// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=sparc-none-openbsd < /dev/null | FileCheck -match-full-lines -check-prefix SPARC -check-prefix SPARC-NETOPENBSD -check-prefix SPARC-NETOPENBSD-CXX %s
//
// SPARC-NOT:#define _LP64
// SPARC:#define __BIGGEST_ALIGNMENT__ 8
@@ -6882,6 +6922,7 @@
// SPARC:#define __FLT_MIN_EXP__ (-125)
// SPARC:#define __FLT_MIN__ 1.17549435e-38F
// SPARC:#define __FLT_RADIX__ 2
+// SPARC:#define __GCC_ATOMIC_LLONG_LOCK_FREE 1
// SPARC:#define __INT16_C_SUFFIX__
// SPARC:#define __INT16_FMTd__ "hd"
// SPARC:#define __INT16_FMTi__ "hi"
@@ -6992,6 +7033,8 @@
// SPARC-NETOPENBSD:#define __SIZE_MAX__ 4294967295UL
// SPARC-NETOPENBSD:#define __SIZE_TYPE__ long unsigned int
// SPARC:#define __SIZE_WIDTH__ 32
+// SPARC-DEFAULT-CXX:#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 8U
+// SPARC-NETOPENBSD-CXX:#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 8UL
// SPARC:#define __UINT16_C_SUFFIX__
// SPARC:#define __UINT16_MAX__ 65535
// SPARC:#define __UINT16_TYPE__ unsigned short
@@ -7042,6 +7085,7 @@
// SPARC:#define sparc 1
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=tce-none-none < /dev/null | FileCheck -match-full-lines -check-prefix TCE %s
+// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=tce-none-none < /dev/null | FileCheck -match-full-lines -check-prefix TCE -check-prefix TCE-CXX %s
//
// TCE-NOT:#define _LP64
// TCE:#define __BIGGEST_ALIGNMENT__ 4
@@ -7168,6 +7212,7 @@
// TCE:#define __SIZE_MAX__ 4294967295U
// TCE:#define __SIZE_TYPE__ unsigned int
// TCE:#define __SIZE_WIDTH__ 32
+// TCE-CXX:#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 4U
// TCE:#define __TCE_V1__ 1
// TCE:#define __TCE__ 1
// TCE:#define __UINT16_C_SUFFIX__
@@ -7209,6 +7254,7 @@
// TCE:#define tce 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=x86_64-none-none < /dev/null | FileCheck -match-full-lines -check-prefix X86_64 %s
+// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=x86_64-none-none < /dev/null | FileCheck -match-full-lines -check-prefix X86_64 -check-prefix X86_64-CXX %s
//
// X86_64:#define _LP64 1
// X86_64-NOT:#define _LP32 1
@@ -7357,6 +7403,7 @@
// X86_64:#define __SSE2__ 1
// X86_64:#define __SSE_MATH__ 1
// X86_64:#define __SSE__ 1
+// X86_64-CXX:#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 16UL
// X86_64:#define __UINT16_C_SUFFIX__
// X86_64:#define __UINT16_MAX__ 65535
// X86_64:#define __UINT16_TYPE__ unsigned short
@@ -7411,6 +7458,7 @@
// X86_64H:#define __x86_64h__ 1
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=x86_64-none-none-gnux32 < /dev/null | FileCheck -match-full-lines -check-prefix X32 %s
+// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=x86_64-none-none-gnux32 < /dev/null | FileCheck -match-full-lines -check-prefix X32 -check-prefix X32-CXX %s
//
// X32:#define _ILP32 1
// X32-NOT:#define _LP64 1
@@ -7559,6 +7607,7 @@
// X32:#define __SSE2__ 1
// X32:#define __SSE_MATH__ 1
// X32:#define __SSE__ 1
+// X32-CXX:#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 16U
// X32:#define __UINT16_C_SUFFIX__
// X32:#define __UINT16_MAX__ 65535
// X32:#define __UINT16_TYPE__ unsigned short
@@ -8457,11 +8506,45 @@
// NORTTI:#define __STDC__ 1
//
// RUN: %clang_cc1 -triple arm-linux-androideabi -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix ANDROID %s
+// ANDROID-NOT:#define __ANDROID_API__
// ANDROID:#define __ANDROID__ 1
//
+// RUN: %clang_cc1 -x c++ -triple i686-linux-android -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix I386-ANDROID-CXX %s
+// I386-ANDROID-CXX:#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 4U
+//
+// RUN: %clang_cc1 -x c++ -triple x86_64-linux-android -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix X86_64-ANDROID-CXX %s
+// X86_64-ANDROID-CXX:#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 16UL
+//
+// RUN: %clang_cc1 -triple arm-linux-androideabi20 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix ANDROID20 %s
+// ANDROID20:#define __ANDROID_API__ 20
+// ANDROID20:#define __ANDROID__ 1
+//
// RUN: %clang_cc1 -triple lanai-unknown-unknown -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix LANAI %s
// LANAI: #define __lanai__ 1
//
+// RUN: %clang_cc1 -E -dM -ffreestanding -triple=amd64-unknown-openbsd6.1 < /dev/null | FileCheck -match-full-lines -check-prefix OPENBSD %s
+// RUN: %clang_cc1 -E -dM -ffreestanding -triple=arm-unknown-openbsd6.1-gnueabi < /dev/null | FileCheck -match-full-lines -check-prefix OPENBSD %s
+// RUN: %clang_cc1 -E -dM -ffreestanding -triple=i386-unknown-openbsd6.1 < /dev/null | FileCheck -match-full-lines -check-prefix OPENBSD %s
+// RUN: %clang_cc1 -E -dM -ffreestanding -triple=sparc64-unknown-openbsd6.1 < /dev/null | FileCheck -match-full-lines -check-prefix OPENBSD %s
+// OPENBSD:#define __ELF__ 1
+// OPENBSD:#define __INT16_TYPE__ short
+// OPENBSD:#define __INT32_TYPE__ int
+// OPENBSD:#define __INT64_TYPE__ long long int
+// OPENBSD:#define __INT8_TYPE__ signed char
+// OPENBSD:#define __INTMAX_TYPE__ long long int
+// OPENBSD:#define __INTPTR_TYPE__ long int
+// OPENBSD:#define __OpenBSD__ 1
+// OPENBSD:#define __PTRDIFF_TYPE__ long int
+// OPENBSD:#define __SIZE_TYPE__ long unsigned int
+// OPENBSD:#define __UINT16_TYPE__ unsigned short
+// OPENBSD:#define __UINT32_TYPE__ unsigned int
+// OPENBSD:#define __UINT64_TYPE__ long long unsigned int
+// OPENBSD:#define __UINT8_TYPE__ unsigned char
+// OPENBSD:#define __UINTMAX_TYPE__ long long unsigned int
+// OPENBSD:#define __UINTPTR_TYPE__ long unsigned int
+// OPENBSD:#define __WCHAR_TYPE__ int
+// OPENBSD:#define __WINT_TYPE__ int
+//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-unknown-freebsd < /dev/null | FileCheck -match-full-lines -check-prefix PPC64-FREEBSD %s
// PPC64-FREEBSD-NOT: #define __LONG_DOUBLE_128__ 1
//
@@ -8565,10 +8648,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__ "ld"
-// WEBASSEMBLY32-NEXT:#define __INTPTR_FMTi__ "li"
-// WEBASSEMBLY32-NEXT:#define __INTPTR_MAX__ 2147483647L
-// WEBASSEMBLY32-NEXT:#define __INTPTR_TYPE__ long int
+// 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_WIDTH__ 32
// WEBASSEMBLY32-NEXT:#define __INT_FAST16_FMTd__ "hd"
// WEBASSEMBLY32-NEXT:#define __INT_FAST16_FMTi__ "hi"
@@ -8627,10 +8710,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__ "ld"
-// WEBASSEMBLY32-NEXT:#define __PTRDIFF_FMTi__ "li"
-// WEBASSEMBLY32-NEXT:#define __PTRDIFF_MAX__ 2147483647L
-// WEBASSEMBLY32-NEXT:#define __PTRDIFF_TYPE__ long int
+// 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_WIDTH__ 32
// WEBASSEMBLY32-NOT:#define __REGISTER_PREFIX__
// WEBASSEMBLY32-NEXT:#define __SCHAR_MAX__ 127
@@ -8650,12 +8733,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__ "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_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_WIDTH__ 32
// WEBASSEMBLY32-NEXT:#define __STDC_HOSTED__ 0
// WEBASSEMBLY32-NOT:#define __STDC_MB_MIGHT_NEQ_WC__
@@ -8703,12 +8786,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__ "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_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_WIDTH__ 32
// WEBASSEMBLY32-NEXT:#define __UINT_FAST16_FMTX__ "hX"
// WEBASSEMBLY32-NEXT:#define __UINT_FAST16_FMTo__ "ho"
diff --git a/test/Preprocessor/missing-include-range-check.h b/test/Preprocessor/missing-include-range-check.h
new file mode 100644
index 000000000000..6b3f7d356120
--- /dev/null
+++ b/test/Preprocessor/missing-include-range-check.h
@@ -0,0 +1,8 @@
+// RUN: env CINDEXTEST_KEEP_GOING=1 c-index-test -test-load-source all %s > /dev/null 2> %t.err
+// RUN: FileCheck < %t.err -check-prefix=CHECK-RANGE %s
+
+#include <foobar.h>
+#include "moozegnarf.h"
+
+// CHECK-RANGE: rewrite-includes-missing.c:4:10:{4:10-4:19}: fatal error: 'foobar.h' file not found
+// CHECK-RANGE: rewrite-includes-missing.c:5:10:{5:10-5:24}: fatal error: 'moozegnarf.h' file not found
diff --git a/test/Preprocessor/pragma_microsoft.c b/test/Preprocessor/pragma_microsoft.c
index 2a9e7bab35b5..b256b2bee6cf 100644
--- a/test/Preprocessor/pragma_microsoft.c
+++ b/test/Preprocessor/pragma_microsoft.c
@@ -162,3 +162,31 @@ void g() {}
// Test that runtime_checks is parsed but ignored.
#pragma runtime_checks("sc", restore) // no-warning
+
+// Test pragma intrinsic
+#pragma intrinsic(memset) // no-warning
+#pragma intrinsic(memcpy, strlen, strlen) // no-warning
+#pragma intrinsic() // no-warning
+#pragma intrinsic(asdf) // expected-warning {{'asdf' is not a recognized builtin; consider including <intrin.h>}}
+#pragma intrinsic(main) // expected-warning {{'main' is not a recognized builtin; consider including <intrin.h>}}
+#pragma intrinsic( // expected-warning {{missing ')' after}}
+#pragma intrinsic(int) // expected-warning {{missing ')' after}}
+#pragma intrinsic(strcmp) asdf // expected-warning {{extra tokens at end}}
+
+#define __INTRIN_H // there should be no notes after defining __INTRIN_H
+#pragma intrinsic(asdf) // expected-warning-re {{'asdf' is not a recognized builtin{{$}}}}
+#pragma intrinsic(memset) // no-warning
+#undef __INTRIN_H
+#pragma intrinsic(asdf) // expected-warning {{'asdf' is not a recognized builtin; consider including <intrin.h>}}
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wignored-pragma-intrinsic"
+#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 clang diagnostic push
+#pragma clang diagnostic ignored "-Wignored-pragmas"
+#pragma intrinsic(asdf) // no-warning
+#pragma clang diagnostic pop
+#pragma intrinsic(asdf) // expected-warning {{'asdf' is not a recognized builtin; consider including <intrin.h>}}
diff --git a/test/Preprocessor/predefined-arch-macros.c b/test/Preprocessor/predefined-arch-macros.c
index 18a75df66e7d..51b587e403e0 100644
--- a/test/Preprocessor/predefined-arch-macros.c
+++ b/test/Preprocessor/predefined-arch-macros.c
@@ -1865,6 +1865,12 @@
//
// 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
@@ -1921,6 +1927,8 @@
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_MYRIAD2-1 -check-prefix=CHECK_SPARCEL
// RUN: %clang -E -dM %s -o - -target sparcel-myriad -mcpu=myriad2.2 2>&1 \
// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_MYRIAD2-2 -check-prefix=CHECK_SPARCEL
+// RUN: %clang -E -dM %s -o - -target sparcel-myriad -mcpu=ma2450 2>&1 \
+// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_MYRIAD2-2 -check-prefix=CHECK_SPARCEL
// CHECK_SPARCEL: #define __LITTLE_ENDIAN__ 1
// CHECK_MYRIAD2-1: #define __myriad2 1
// CHECK_MYRIAD2-1: #define __myriad2__ 1
@@ -1928,6 +1936,7 @@
// CHECK_MYRIAD2-2: #define __myriad2__ 2
// CHECK_SPARCEL: #define __sparc 1
// CHECK_SPARCEL: #define __sparc__ 1
+// CHECK_MYRIAD2-1: #define __sparc_v8__ 1
// CHECK_SPARCEL: #define __sparcv8 1
//
// RUN: %clang -E -dM %s -o - 2>&1 \
@@ -1960,6 +1969,9 @@
// 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_ZEC12
+// 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_ZEC12
//
// CHECK_SYSTEMZ_ZEC12: #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1
// CHECK_SYSTEMZ_ZEC12: #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1
diff --git a/test/Preprocessor/x86_target_features.c b/test/Preprocessor/x86_target_features.c
index ff79a699ae8d..43cf615546b1 100644
--- a/test/Preprocessor/x86_target_features.c
+++ b/test/Preprocessor/x86_target_features.c
@@ -196,6 +196,7 @@
// RUN: %clang -target i386-unknown-unknown -march=atom -mavx512vbmi -x c -E -dM -o - %s | FileCheck -match-full-lines --check-prefix=AVX512VBMI %s
// AVX512VBMI: #define __AVX2__ 1
+// AVX512VBMI: #define __AVX512BW__ 1
// AVX512VBMI: #define __AVX512F__ 1
// AVX512VBMI: #define __AVX512VBMI__ 1
// AVX512VBMI: #define __AVX__ 1
@@ -208,6 +209,11 @@
// AVX512VBMI: #define __SSE__ 1
// AVX512VBMI: #define __SSSE3__ 1
+// RUN: %clang -target i386-unknown-unknown -march=atom -mavx512vbmi -mno-avx512bw -x c -E -dM -o - %s | FileCheck -match-full-lines --check-prefix=AVX512VBMINOAVX512BW %s
+
+// AVX512VBMINOAVX512BW-NOT: #define __AVX512BW__ 1
+// AVX512VBMINOAVX512BW-NOT: #define __AVX512VBMI__ 1
+
// RUN: %clang -target i386-unknown-unknown -march=atom -msse4.2 -x c -E -dM -o - %s | FileCheck -match-full-lines --check-prefix=SSE42POPCNT %s
// SSE42POPCNT: #define __POPCNT__ 1
diff --git a/test/Profile/c-generate.c b/test/Profile/c-generate.c
index 454f5dbf59a5..5e5b22e8c30d 100644
--- a/test/Profile/c-generate.c
+++ b/test/Profile/c-generate.c
@@ -3,9 +3,7 @@
// RUN: %clang_cc1 %s -o - -emit-llvm -fprofile-instrument=none | FileCheck %s --check-prefix=PROF-INSTR-NONE
// RUN: not %clang_cc1 %s -o - -emit-llvm -fprofile-instrument=garbage 2>&1 | FileCheck %s --check-prefix=PROF-INSTR-GARBAGE
//
-// PROF-INSTR-PATH: private constant [24 x i8] c"c-generate-test.profraw\00"
-// PROF-INSTR-PATH: call void @__llvm_profile_override_default_filename(i8* getelementptr inbounds ([24 x i8], [24 x i8]* @0, i32 0, i32 0))
-// PROF-INSTR-PATH: declare void @__llvm_profile_override_default_filename(i8*)
+// PROF-INSTR-PATH: constant [24 x i8] c"c-generate-test.profraw\00"
//
// PROF-INSTR-NONE-NOT: @__profn_main
// PROF-INSTR-GARBAGE: invalid PGO instrumentor in argument '-fprofile-instrument=garbage'
diff --git a/test/Profile/c-indirect-call.c b/test/Profile/c-indirect-call.c
index b0ace37267fd..92465495a6f6 100644
--- a/test/Profile/c-indirect-call.c
+++ b/test/Profile/c-indirect-call.c
@@ -1,16 +1,22 @@
// Check the value profiling instrinsics emitted by instrumentation.
-// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name c-indirect-call.c %s -o - -emit-llvm -fprofile-instrument=clang -mllvm -enable-value-profiling | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name c-indirect-call.c %s -o - -emit-llvm -fprofile-instrument=clang -mllvm -enable-value-profiling | FileCheck --check-prefix=NOEXT %s
+// RUN: %clang_cc1 -triple s390x-ibm-linux -main-file-name c-indirect-call.c %s -o - -emit-llvm -fprofile-instrument=clang -mllvm -enable-value-profiling | FileCheck --check-prefix=EXT %s
void (*foo)(void);
int main(void) {
-// CHECK: [[REG1:%[0-9]+]] = load void ()*, void ()** @foo, align 8
-// CHECK-NEXT: [[REG2:%[0-9]+]] = ptrtoint void ()* [[REG1]] to i64
-// CHECK-NEXT: call void @__llvm_profile_instrument_target(i64 [[REG2]], i8* bitcast ({{.*}}* @__profd_main to i8*), i32 0)
-// CHECK-NEXT: call void [[REG1]]()
+// NOEXT: [[REG1:%[0-9]+]] = load void ()*, void ()** @foo, align 8
+// NOEXT-NEXT: [[REG2:%[0-9]+]] = ptrtoint void ()* [[REG1]] to i64
+// NOEXT-NEXT: call void @__llvm_profile_instrument_target(i64 [[REG2]], i8* bitcast ({{.*}}* @__profd_main to i8*), i32 0)
+// NOEXT-NEXT: call void [[REG1]]()
+// EXT: [[REG1:%[0-9]+]] = load void ()*, void ()** @foo, align 8
+// EXT-NEXT: [[REG2:%[0-9]+]] = ptrtoint void ()* [[REG1]] to i64
+// EXT-NEXT: call void @__llvm_profile_instrument_target(i64 [[REG2]], i8* bitcast ({{.*}}* @__profd_main to i8*), i32 zeroext 0)
+// EXT-NEXT: call void [[REG1]]()
foo();
return 0;
}
-// CHECK: declare void @__llvm_profile_instrument_target(i64, i8*, i32)
+// NOEXT: declare void @__llvm_profile_instrument_target(i64, i8*, i32)
+// EXT: declare void @__llvm_profile_instrument_target(i64, i8*, i32 zeroext)
diff --git a/test/Profile/c-linkage-available_externally.c b/test/Profile/c-linkage-available_externally.c
index 8907839cb9ad..5ac777b267ab 100644
--- a/test/Profile/c-linkage-available_externally.c
+++ b/test/Profile/c-linkage-available_externally.c
@@ -3,7 +3,7 @@
// RUN: %clang_cc1 -O2 -triple x86_64-apple-macosx10.9 -main-file-name c-linkage-available_externally.c %s -o - -emit-llvm -fprofile-instrument=clang | FileCheck %s
// CHECK: @__profc_foo = linkonce_odr hidden global [1 x i64] zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8
-// CHECK: @__profd_foo = linkonce_odr hidden global {{.*}} i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_foo, i32 0, i32 0){{.*}}, section "__DATA,__llvm_prf_data", align 8
+// CHECK: @__profd_foo = linkonce_odr hidden global {{.*}} i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_foo, i32 0, i32 0){{.*}}, section "__DATA,__llvm_prf_data,regular,live_support", align 8
inline int foo(void) { return 1; }
int main(void) {
diff --git a/test/Profile/cxx-indirect-call.cpp b/test/Profile/cxx-indirect-call.cpp
index f95d1af37c79..1e739226b96f 100644
--- a/test/Profile/cxx-indirect-call.cpp
+++ b/test/Profile/cxx-indirect-call.cpp
@@ -1,6 +1,6 @@
// Check the value profiling instrinsics emitted by instrumentation.
-// RUN: %clang_cc1 %s -o - -emit-llvm -fprofile-instrument=clang -mllvm -enable-value-profiling -fexceptions -fcxx-exceptions -triple %itanium_abi_triple | FileCheck %s
+// RUN: %clang_cc1 %s -o - -emit-llvm -fprofile-instrument=clang -mllvm -enable-value-profiling -fexceptions -fcxx-exceptions -triple x86_64-apple-macosx10.9 | FileCheck %s
void (*foo) (void);
diff --git a/test/Profile/cxx-stmt-initializers.cpp b/test/Profile/cxx-stmt-initializers.cpp
new file mode 100644
index 000000000000..44f7edd276f6
--- /dev/null
+++ b/test/Profile/cxx-stmt-initializers.cpp
@@ -0,0 +1,29 @@
+// Tests for instrumentation of C++17 statement initializers
+
+// RUN: %clang_cc1 -x c++ %s -triple %itanium_abi_triple -main-file-name cxx-stmt-initializers.cpp -std=c++1z -o - -emit-llvm -fprofile-instrument=clang > %tgen
+// RUN: FileCheck --input-file=%tgen -check-prefix=CHECK -check-prefix=PGOGEN %s
+
+// PGOGEN: @[[SIC:__profc__Z11switch_initv]] = private global [3 x i64] zeroinitializer
+// PGOGEN: @[[IIC:__profc__Z7if_initv]] = private global [3 x i64] zeroinitializer
+
+// Note: We expect counters for the function entry block, the condition in the
+// switch initializer, and the switch successor block.
+//
+// CHECK-LABEL: define {{.*}}void @_Z11switch_initv()
+// PGOGEN: store {{.*}} @[[SIC]], i64 0, i64 0
+void switch_init() {
+ switch (int i = true ? 0 : 1; i) {}
+ // PGOGEN: store {{.*}} @[[SIC]], i64 0, i64 2
+ // PGOGEN: store {{.*}} @[[SIC]], i64 0, i64 1
+}
+
+// Note: We expect counters for the function entry block, the condition in the
+// if initializer, and the if successor block.
+//
+// CHECK-LABEL: define {{.*}}void @_Z7if_initv()
+// PGOGEN: store {{.*}} @[[IIC]], i64 0, i64 0
+void if_init() {
+ if (int i = true ? 0 : 1; i) {}
+ // PGOGEN: store {{.*}} @[[IIC]], i64 0, i64 2
+ // PGOGEN: store {{.*}} @[[IIC]], i64 0, i64 1
+}
diff --git a/test/Profile/func-entry.c b/test/Profile/func-entry.c
index 430ccb3806c4..4a4ca2288352 100644
--- a/test/Profile/func-entry.c
+++ b/test/Profile/func-entry.c
@@ -1,7 +1,7 @@
// Test that function entry counts are set correctly.
// RUN: llvm-profdata merge %S/Inputs/func-entry.proftext -o %t.profdata
-// RUN: %clang_cc1 %s -o - -disable-llvm-optzns -emit-llvm -fprofile-instrument-use-path=%t.profdata | FileCheck %s
+// RUN: %clang_cc1 %s -o - -disable-llvm-passes -emit-llvm -fprofile-instrument-use-path=%t.profdata | FileCheck %s
void foo(void);
diff --git a/test/Profile/gcc-flag-compatibility.c b/test/Profile/gcc-flag-compatibility.c
index 622b782c0cb3..f685f69e4ba0 100644
--- a/test/Profile/gcc-flag-compatibility.c
+++ b/test/Profile/gcc-flag-compatibility.c
@@ -7,30 +7,25 @@
// -fprofile-use=<dir> Uses the profile file <dir>/default.profdata
// -fprofile-use=<dir>/file Uses the profile file <dir>/file
-// FIXME: IRPGO shouldn't use the override API when no profraw name is given.
-// Check that -fprofile-generate overrides the default profraw.
// RUN: %clang %s -c -S -o - -emit-llvm -fprofile-generate | FileCheck -check-prefix=PROFILE-GEN %s
-// PROFILE-GEN: call void @__llvm_profile_override_default_filename
-// PROFILE-GEN: declare void @__llvm_profile_override_default_filename(i8*)
+// PROFILE-GEN: __llvm_profile_filename
// Check that -fprofile-generate=/path/to generates /path/to/default.profraw
// RUN: %clang %s -c -S -o - -emit-llvm -fprofile-generate=/path/to | FileCheck -check-prefix=PROFILE-GEN-EQ %s
-// PROFILE-GEN-EQ: private constant [25 x i8] c"/path/to{{/|\\5C}}default.profraw\00"
-// PROFILE-GEN-EQ: call void @__llvm_profile_override_default_filename(i8* getelementptr inbounds ([25 x i8], [25 x i8]* @0, i32 0, i32 0))
-// PROFILE-GEN-EQ: declare void @__llvm_profile_override_default_filename(i8*)
+// PROFILE-GEN-EQ: constant [{{.*}} x i8] c"/path/to{{/|\\5C}}{{.*}}\00"
// Check that -fprofile-use=some/path reads some/path/default.profdata
// RUN: rm -rf %t.dir
// RUN: mkdir -p %t.dir/some/path
// RUN: llvm-profdata merge %S/Inputs/gcc-flag-compatibility.proftext -o %t.dir/some/path/default.profdata
-// RUN: %clang %s -o - -mllvm -disable-llvm-optzns -emit-llvm -S -fprofile-use=%t.dir/some/path | FileCheck -check-prefix=PROFILE-USE-2 %s
+// RUN: %clang %s -o - -mllvm -disable-llvm-passes -emit-llvm -S -fprofile-use=%t.dir/some/path | FileCheck -check-prefix=PROFILE-USE-2 %s
// PROFILE-USE-2: = !{!"branch_weights", i32 101, i32 2}
// Check that -fprofile-use=some/path/file.prof reads some/path/file.prof
// RUN: rm -rf %t.dir
// RUN: mkdir -p %t.dir/some/path
// RUN: llvm-profdata merge %S/Inputs/gcc-flag-compatibility.proftext -o %t.dir/some/path/file.prof
-// RUN: %clang %s -o - -mllvm -disable-llvm-optzns -emit-llvm -S -fprofile-use=%t.dir/some/path/file.prof | FileCheck -check-prefix=PROFILE-USE-3 %s
+// RUN: %clang %s -o - -mllvm -disable-llvm-passes -emit-llvm -S -fprofile-use=%t.dir/some/path/file.prof | FileCheck -check-prefix=PROFILE-USE-3 %s
// PROFILE-USE-3: = !{!"branch_weights", i32 101, i32 2}
int X = 0;
diff --git a/test/Profile/profile-summary.c b/test/Profile/profile-summary.c
index dc3112c9d672..47fd9e85a453 100644
--- a/test/Profile/profile-summary.c
+++ b/test/Profile/profile-summary.c
@@ -1,7 +1,7 @@
// Test that profile summary is set correctly.
// RUN: llvm-profdata merge %S/Inputs/max-function-count.proftext -o %t.profdata
-// RUN: %clang_cc1 %s -o - -disable-llvm-optzns -emit-llvm -fprofile-instrument-use-path=%t.profdata | FileCheck %s
+// RUN: %clang_cc1 %s -o - -disable-llvm-passes -emit-llvm -fprofile-instrument-use-path=%t.profdata | FileCheck %s
//
int begin(int i) {
if (i)
diff --git a/test/Rewriter/modern-write-bf-abi.mm b/test/Rewriter/modern-write-bf-abi.mm
index 85db93924f7f..70e11415db96 100644
--- a/test/Rewriter/modern-write-bf-abi.mm
+++ b/test/Rewriter/modern-write-bf-abi.mm
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fms-extensions -rewrite-objc %s -o %t-modern-rw.cpp
-// RUN: %clang_cc1 -fsyntax-only -Wno-address-of-temporary -D"Class=void*" -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-modern-rw.cpp
+// RUN: %clang_cc1 -fsyntax-only -std=gnu++98 -Wno-address-of-temporary -D"Class=void*" -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-modern-rw.cpp
// rdar://13138459
// -Did="void*" -DSEL="void *" -DClass="void*"
diff --git a/test/Rewriter/objc-modern-property-bitfield.m b/test/Rewriter/objc-modern-property-bitfield.m
index 583fa3783dec..e7b565dda537 100644
--- a/test/Rewriter/objc-modern-property-bitfield.m
+++ b/test/Rewriter/objc-modern-property-bitfield.m
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fms-extensions -rewrite-objc %s -o %t-modern-rw.cpp
-// RUN: %clang_cc1 -fsyntax-only -Wno-address-of-temporary -D"Class=void*" -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-modern-rw.cpp
+// RUN: %clang_cc1 -fsyntax-only -std=gnu++98 -Wno-address-of-temporary -D"Class=void*" -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-modern-rw.cpp
// rdar://13138459
void *sel_registerName(const char *);
diff --git a/test/Rewriter/property-dot-syntax.mm b/test/Rewriter/property-dot-syntax.mm
index c3e4405ebb58..140ac4a7f331 100644
--- a/test/Rewriter/property-dot-syntax.mm
+++ b/test/Rewriter/property-dot-syntax.mm
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc -fobjc-runtime=macosx-fragile-10.5 %s -o %t-rw.cpp
-// RUN: %clang_cc1 -fsyntax-only -fblocks -Wno-address-of-temporary -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
+// RUN: %clang_cc1 -fsyntax-only -std=gnu++98 -fblocks -Wno-address-of-temporary -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
// rdar:// 8520727
void *sel_registerName(const char *);
diff --git a/test/Rewriter/rewrite-block-literal-1.mm b/test/Rewriter/rewrite-block-literal-1.mm
index 88ad5742effa..6820a07e88ed 100644
--- a/test/Rewriter/rewrite-block-literal-1.mm
+++ b/test/Rewriter/rewrite-block-literal-1.mm
@@ -1,8 +1,8 @@
// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc -fobjc-runtime=macosx-fragile-10.5 %s -o %t-rw.cpp
-// RUN: %clang_cc1 -fsyntax-only -Wno-address-of-temporary -Did="void *" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
+// RUN: %clang_cc1 -fsyntax-only -std=gnu++98 -Wno-address-of-temporary -Did="void *" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
// radar 9254348
// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc %s -o %t-modern-rw.cpp
-// RUN: %clang_cc1 -fsyntax-only -Wno-address-of-temporary -Did="void *" -D"SEL=void*" -D"__declspec(X)=" %t-modern-rw.cpp
+// RUN: %clang_cc1 -fsyntax-only -std=gnu++98 -Wno-address-of-temporary -Did="void *" -D"SEL=void*" -D"__declspec(X)=" %t-modern-rw.cpp
// rdar://11259664
// rdar://11375908
diff --git a/test/Rewriter/rewrite-block-pointer.mm b/test/Rewriter/rewrite-block-pointer.mm
index 9f3368098cad..b8a5ee8fce62 100644
--- a/test/Rewriter/rewrite-block-pointer.mm
+++ b/test/Rewriter/rewrite-block-pointer.mm
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc -fobjc-runtime=macosx-fragile-10.5 %s -o %t-rw.cpp
-// RUN: %clang_cc1 -fsyntax-only -Wno-address-of-temporary -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
+// RUN: %clang_cc1 -fsyntax-only -std=gnu++98 -Wno-address-of-temporary -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc %s -o %t-modern-rw.cpp
-// RUN: %clang_cc1 -fsyntax-only -Wno-address-of-temporary -D"SEL=void*" -D"__declspec(X)=" %t-modern-rw.cpp
+// RUN: %clang_cc1 -fsyntax-only -std=gnu++98 -Wno-address-of-temporary -D"SEL=void*" -D"__declspec(X)=" %t-modern-rw.cpp
// radar 7638400
// rdar://11375908
diff --git a/test/Rewriter/rewrite-byref-in-nested-blocks.mm b/test/Rewriter/rewrite-byref-in-nested-blocks.mm
index f416b6622f45..fce5890ad4ea 100644
--- a/test/Rewriter/rewrite-byref-in-nested-blocks.mm
+++ b/test/Rewriter/rewrite-byref-in-nested-blocks.mm
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc -fobjc-runtime=macosx-fragile-10.5 %s -o %t-rw.cpp
-// RUN: %clang_cc1 -fsyntax-only -fblocks -Wno-address-of-temporary -D"SEL=void*" -U__declspec -D"__declspec(X)=" %t-rw.cpp
+// RUN: %clang_cc1 -fsyntax-only -std=gnu++98 -fblocks -Wno-address-of-temporary -D"SEL=void*" -U__declspec -D"__declspec(X)=" %t-rw.cpp
// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc %s -o %t-modern-rw.cpp
-// RUN: %clang_cc1 -fsyntax-only -Werror -Wno-address-of-temporary -D"SEL=void*" -U__declspec -D"__declspec(X)=" %t-modern-rw.cpp
+// RUN: %clang_cc1 -fsyntax-only -std=gnu++98 -Werror -Wno-address-of-temporary -D"SEL=void*" -U__declspec -D"__declspec(X)=" %t-modern-rw.cpp
// radar 7692350
// rdar://11375908
diff --git a/test/Rewriter/rewrite-byref-vars.mm b/test/Rewriter/rewrite-byref-vars.mm
index cfc51341d736..2838c44f2f2a 100644
--- a/test/Rewriter/rewrite-byref-vars.mm
+++ b/test/Rewriter/rewrite-byref-vars.mm
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc -fobjc-runtime=macosx-fragile-10.5 %s -o %t-rw.cpp
-// RUN: %clang_cc1 -fsyntax-only -fblocks -Wno-address-of-temporary -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
+// RUN: %clang_cc1 -fsyntax-only -std=gnu++98 -fblocks -Wno-address-of-temporary -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
// radar 7540194
extern "C" __declspec(dllexport) void BreakTheRewriter(int i) {
diff --git a/test/Rewriter/rewrite-cast-ivar-modern-access.mm b/test/Rewriter/rewrite-cast-ivar-modern-access.mm
index 4a6cb3279fd5..4cea4f6eb17c 100644
--- a/test/Rewriter/rewrite-cast-ivar-modern-access.mm
+++ b/test/Rewriter/rewrite-cast-ivar-modern-access.mm
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -x objective-c++ -fblocks -fms-extensions -rewrite-objc %s -o %t-rw.cpp
-// RUN: %clang_cc1 -fsyntax-only -fblocks -Wno-address-of-temporary -D"Class=void*" -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
+// RUN: %clang_cc1 -fsyntax-only -std=gnu++98 -fblocks -Wno-address-of-temporary -D"Class=void*" -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
@interface F {
int supervar;
diff --git a/test/Rewriter/rewrite-elaborated-type.mm b/test/Rewriter/rewrite-elaborated-type.mm
index f2faa55cb5ad..c813a3b9f49a 100644
--- a/test/Rewriter/rewrite-elaborated-type.mm
+++ b/test/Rewriter/rewrite-elaborated-type.mm
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fms-extensions -rewrite-objc -fobjc-runtime=macosx-fragile-10.5 %s -o %t-rw.cpp
-// RUN: %clang_cc1 -fsyntax-only -Wno-address-of-temporary -D_Bool=bool -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
+// RUN: %clang_cc1 -fsyntax-only -std=gnu++98 -Wno-address-of-temporary -D_Bool=bool -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fms-extensions -rewrite-objc %s -o %t-modern-rw.cpp
-// RUN: %clang_cc1 -fsyntax-only -Wno-address-of-temporary -D_Bool=bool -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-modern-rw.cpp
+// RUN: %clang_cc1 -fsyntax-only -std=gnu++98 -Wno-address-of-temporary -D_Bool=bool -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-modern-rw.cpp
// radar 8143056
typedef struct objc_class *Class;
diff --git a/test/Rewriter/rewrite-foreach-in-block.mm b/test/Rewriter/rewrite-foreach-in-block.mm
index 4b2f37dc31b5..14d9d3a66f86 100644
--- a/test/Rewriter/rewrite-foreach-in-block.mm
+++ b/test/Rewriter/rewrite-foreach-in-block.mm
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc -fobjc-runtime=macosx-fragile-10.5 %s -o %t-rw.cpp
-// RUN: %clang_cc1 -fsyntax-only -Wno-address-of-temporary -D"id=struct objc_object*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
+// RUN: %clang_cc1 -fsyntax-only -std=gnu++98 -Wno-address-of-temporary -D"id=struct objc_object*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc %s -o %t-modern-rw.cpp
-// RUN: %clang_cc1 -fsyntax-only -Wno-address-of-temporary -D"id=struct objc_object*" -D"SEL=void*" -D"__declspec(X)=" %t-modern-rw.cpp
+// RUN: %clang_cc1 -fsyntax-only -std=gnu++98 -Wno-address-of-temporary -D"id=struct objc_object*" -D"SEL=void*" -D"__declspec(X)=" %t-modern-rw.cpp
// rdar:// 9878420
typedef unsigned long size_t;
diff --git a/test/Rewriter/rewrite-foreach-protocol-id.m b/test/Rewriter/rewrite-foreach-protocol-id.m
index a9491f19ae73..7f046be81f6d 100644
--- a/test/Rewriter/rewrite-foreach-protocol-id.m
+++ b/test/Rewriter/rewrite-foreach-protocol-id.m
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc -fobjc-runtime=macosx-fragile-10.5 %s -o %t-rw.cpp
-// RUN: %clang_cc1 -fsyntax-only -fblocks -Wno-address-of-temporary -D"id=struct objc_object*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
+// RUN: %clang_cc1 -fsyntax-only -std=gnu++98 -fblocks -Wno-address-of-temporary -D"id=struct objc_object*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
// rdar:// 9039342
void *sel_registerName(const char *);
diff --git a/test/Rewriter/rewrite-forward-class.m b/test/Rewriter/rewrite-forward-class.m
index 28bab9d441e0..7c2fdc21f8e1 100644
--- a/test/Rewriter/rewrite-forward-class.m
+++ b/test/Rewriter/rewrite-forward-class.m
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -x objective-c -Wno-return-type -fblocks -fms-extensions -rewrite-objc -fobjc-runtime=macosx-fragile-10.5 %s -o %t-rw.cpp
-// RUN: %clang_cc1 -fsyntax-only -fblocks -Wno-address-of-temporary -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
+// RUN: %clang_cc1 -fsyntax-only -std=gnu++98 -fblocks -Wno-address-of-temporary -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
// rdar://6969189
@class XX;
diff --git a/test/Rewriter/rewrite-forward-class.mm b/test/Rewriter/rewrite-forward-class.mm
index 3d3ef3e6c9af..05cd5702f373 100644
--- a/test/Rewriter/rewrite-forward-class.mm
+++ b/test/Rewriter/rewrite-forward-class.mm
@@ -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 -fblocks -Wno-address-of-temporary -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
+// RUN: %clang_cc1 -fsyntax-only -std=gnu++98 -fblocks -Wno-address-of-temporary -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
extern "C" {
@class XX;
diff --git a/test/Rewriter/rewrite-ivar-use.m b/test/Rewriter/rewrite-ivar-use.m
index 17bbf01af133..0b697b0ca892 100644
--- a/test/Rewriter/rewrite-ivar-use.m
+++ b/test/Rewriter/rewrite-ivar-use.m
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc -fobjc-runtime=macosx-fragile-10.5 %s -o %t-rw.cpp
-// RUN: %clang_cc1 -fsyntax-only -fblocks -Wno-address-of-temporary -D"Class=void*" -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
+// RUN: %clang_cc1 -fsyntax-only -std=gnu++98 -fblocks -Wno-address-of-temporary -D"Class=void*" -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
// radar 7490331
void *sel_registerName(const char *);
diff --git a/test/Rewriter/rewrite-modern-atautoreleasepool.mm b/test/Rewriter/rewrite-modern-atautoreleasepool.mm
index 57c08abb78e7..f5d2956925e7 100644
--- a/test/Rewriter/rewrite-modern-atautoreleasepool.mm
+++ b/test/Rewriter/rewrite-modern-atautoreleasepool.mm
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -E %s -o %t.mm
// RUN: %clang_cc1 -x objective-c++ -fblocks -fms-extensions -rewrite-objc %t.mm -o %t-rw.cpp
// RUN: FileCheck --input-file=%t-rw.cpp %s
-// RUN: %clang_cc1 -fsyntax-only -Wno-address-of-temporary -D"Class=void*" -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
+// RUN: %clang_cc1 -fsyntax-only -std=gnu++98 -Wno-address-of-temporary -D"Class=void*" -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
// radar 11474836
extern "C"
diff --git a/test/Rewriter/rewrite-modern-block-ivar-call.mm b/test/Rewriter/rewrite-modern-block-ivar-call.mm
index 1bafbdd15bab..47920df85d98 100644
--- a/test/Rewriter/rewrite-modern-block-ivar-call.mm
+++ b/test/Rewriter/rewrite-modern-block-ivar-call.mm
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -E %s -o %t.m
// RUN: %clang_cc1 -fblocks -rewrite-objc -fms-extensions %t.m -o %t-rw.cpp
// RUN: FileCheck --input-file=%t-rw.cpp %s
-// RUN: %clang_cc1 -fsyntax-only -Wno-address-of-temporary -D"Class=void*" -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
+// RUN: %clang_cc1 -fsyntax-only -std=gnu++98 -Wno-address-of-temporary -D"Class=void*" -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
@interface Foo {
void (^_block)(void);
diff --git a/test/Rewriter/rewrite-modern-class.mm b/test/Rewriter/rewrite-modern-class.mm
index b6be98a51d02..cf2143e86463 100644
--- a/test/Rewriter/rewrite-modern-class.mm
+++ b/test/Rewriter/rewrite-modern-class.mm
@@ -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 -fblocks -Wno-address-of-temporary -D"Class=void*" -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
+// RUN: %clang_cc1 -fsyntax-only -std=gnu++98 -fblocks -Wno-address-of-temporary -D"Class=void*" -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
@protocol PROTO @end
diff --git a/test/Rewriter/rewrite-modern-default-property-synthesis.mm b/test/Rewriter/rewrite-modern-default-property-synthesis.mm
index f6fe510cba4b..4a772afabd43 100644
--- a/test/Rewriter/rewrite-modern-default-property-synthesis.mm
+++ b/test/Rewriter/rewrite-modern-default-property-synthesis.mm
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -E %s -o %t.mm
// RUN: %clang_cc1 -x objective-c++ -fms-extensions -rewrite-objc %t.mm -o %t-rw.cpp
// RUN: FileCheck --input-file=%t-rw.cpp %s
-// RUN: %clang_cc1 -fsyntax-only -Werror -DSEL="void *" -Did="struct objc_object *" -Wno-attributes -Wno-address-of-temporary -U__declspec -D"__declspec(X)=" %t-rw.cpp
+// RUN: %clang_cc1 -fsyntax-only -std=gnu++98 -Werror -DSEL="void *" -Did="struct objc_object *" -Wno-attributes -Wno-address-of-temporary -U__declspec -D"__declspec(X)=" %t-rw.cpp
// rdar://11374235
extern "C" void *sel_registerName(const char *);
diff --git a/test/Rewriter/rewrite-modern-extern-c-func-decl.mm b/test/Rewriter/rewrite-modern-extern-c-func-decl.mm
index c3bfec9e228c..af8c2d6e21b0 100644
--- a/test/Rewriter/rewrite-modern-extern-c-func-decl.mm
+++ b/test/Rewriter/rewrite-modern-extern-c-func-decl.mm
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -fms-extensions -U__declspec -rewrite-objc -x objective-c++ -fblocks -o %t-rw.cpp %s
-// RUN: %clang_cc1 -fsyntax-only -Werror -Wno-address-of-temporary -Wno-attributes -D"Class=void*" -D"id=void*" -D"SEL=void*" -U__declspec -D"__declspec(X)=" %t-rw.cpp
+// RUN: %clang_cc1 -fsyntax-only -std=gnu++98 -Werror -Wno-address-of-temporary -Wno-attributes -D"Class=void*" -D"id=void*" -D"SEL=void*" -U__declspec -D"__declspec(X)=" %t-rw.cpp
// rdar://11131490
typedef unsigned long size_t;
diff --git a/test/Rewriter/rewrite-modern-ivar-use.mm b/test/Rewriter/rewrite-modern-ivar-use.mm
index ec8d2c7d6159..8e729388c5ed 100644
--- a/test/Rewriter/rewrite-modern-ivar-use.mm
+++ b/test/Rewriter/rewrite-modern-ivar-use.mm
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc %s -o %t-rw-modern.cpp
-// RUN: %clang_cc1 -fsyntax-only -fblocks -Wno-address-of-temporary -D"Class=void*" -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw-modern.cpp
+// RUN: %clang_cc1 -fsyntax-only -std=gnu++98 -fblocks -Wno-address-of-temporary -D"Class=void*" -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw-modern.cpp
void *sel_registerName(const char *);
diff --git a/test/Rewriter/rewrite-modern-ivars-2.mm b/test/Rewriter/rewrite-modern-ivars-2.mm
index 0faed5c55cc2..65ccd6242ad6 100644
--- a/test/Rewriter/rewrite-modern-ivars-2.mm
+++ b/test/Rewriter/rewrite-modern-ivars-2.mm
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -triple i386-apple-darwin9 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc %s -o %t-rw.cpp
-// RUN: %clang_cc1 -triple i386-apple-darwin9 -fsyntax-only -fblocks -Wno-address-of-temporary -D"Class=void*" -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
+// RUN: %clang_cc1 -triple i386-apple-darwin9 -fsyntax-only -std=gnu++98 -fblocks -Wno-address-of-temporary -D"Class=void*" -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
@interface B @end
diff --git a/test/Rewriter/rewrite-modern-ivars.mm b/test/Rewriter/rewrite-modern-ivars.mm
index 5e01a44e9574..217cff662992 100644
--- a/test/Rewriter/rewrite-modern-ivars.mm
+++ b/test/Rewriter/rewrite-modern-ivars.mm
@@ -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 -fblocks -Wno-address-of-temporary -D"Class=void*" -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
+// RUN: %clang_cc1 -fsyntax-only -std=gnu++98 -fblocks -Wno-address-of-temporary -D"Class=void*" -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
@protocol P @end
@protocol P1 @end
diff --git a/test/Rewriter/rewrite-modern-nested-ivar.mm b/test/Rewriter/rewrite-modern-nested-ivar.mm
index 13e31cd01ead..6e0cd3905a93 100644
--- a/test/Rewriter/rewrite-modern-nested-ivar.mm
+++ b/test/Rewriter/rewrite-modern-nested-ivar.mm
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -E %s -o %t.m
// RUN: %clang_cc1 -fblocks -rewrite-objc -fms-extensions %t.m -o %t-rw.cpp
// RUN: FileCheck --input-file=%t-rw.cpp %s
-// RUN: %clang_cc1 -fsyntax-only -Wno-address-of-temporary -D"Class=void*" -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
+// RUN: %clang_cc1 -fsyntax-only -std=gnu++98 -Wno-address-of-temporary -D"Class=void*" -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
@interface NSURLResponse {
@public
diff --git a/test/Rewriter/rewrite-modern-throw.m b/test/Rewriter/rewrite-modern-throw.m
index 1564611a3a7d..19d6b1f6d3c6 100644
--- a/test/Rewriter/rewrite-modern-throw.m
+++ b/test/Rewriter/rewrite-modern-throw.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 -fsyntax-only -std=gnu++98 -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/Rewriter/rewrite-nested-blocks-1.mm b/test/Rewriter/rewrite-nested-blocks-1.mm
index 8981777b8e95..416fd97ad668 100644
--- a/test/Rewriter/rewrite-nested-blocks-1.mm
+++ b/test/Rewriter/rewrite-nested-blocks-1.mm
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc -fobjc-runtime=macosx-fragile-10.5 %s -o %t-rw.cpp
-// RUN: %clang_cc1 -fsyntax-only -fblocks -Wno-address-of-temporary -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
+// RUN: %clang_cc1 -fsyntax-only -std=gnu++98 -fblocks -Wno-address-of-temporary -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc %s -o %t-modern-rw.cpp
-// RUN: %clang_cc1 -fsyntax-only -Wno-address-of-temporary -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-modern-rw.cpp
+// RUN: %clang_cc1 -fsyntax-only -std=gnu++98 -Wno-address-of-temporary -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-modern-rw.cpp
// radar 7696893
typedef unsigned long size_t;
diff --git a/test/Rewriter/rewrite-nested-blocks.mm b/test/Rewriter/rewrite-nested-blocks.mm
index 16a9b31415a8..da3106c295ba 100644
--- a/test/Rewriter/rewrite-nested-blocks.mm
+++ b/test/Rewriter/rewrite-nested-blocks.mm
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc -fobjc-runtime=macosx-fragile-10.5 %s -o %t-rw.cpp
-// RUN: %clang_cc1 -fsyntax-only -Wno-address-of-temporary -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
+// RUN: %clang_cc1 -fsyntax-only -std=gnu++98 -Wno-address-of-temporary -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc %s -o %t-modern-rw.cpp
-// RUN: %clang_cc1 -fsyntax-only -Wno-address-of-temporary -D"SEL=void*" -D"__declspec(X)=" %t-modern-rw.cpp
+// RUN: %clang_cc1 -fsyntax-only -std=gnu++98 -Wno-address-of-temporary -D"SEL=void*" -D"__declspec(X)=" %t-modern-rw.cpp
// radar 7682149
diff --git a/test/Rewriter/rewrite-nested-ivar.mm b/test/Rewriter/rewrite-nested-ivar.mm
index 07fc2f51b404..47504b5d7ba0 100644
--- a/test/Rewriter/rewrite-nested-ivar.mm
+++ b/test/Rewriter/rewrite-nested-ivar.mm
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc -fobjc-runtime=macosx-fragile-10.5 %s -o %t-rw.cpp
-// RUN: %clang_cc1 -fsyntax-only -fblocks -Wno-address-of-temporary -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
+// RUN: %clang_cc1 -fsyntax-only -std=gnu++98 -fblocks -Wno-address-of-temporary -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc %s -o %t-rw-modern.cpp
-// RUN: %clang_cc1 -fsyntax-only -fblocks -Wno-address-of-temporary -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw-modern.cpp
+// RUN: %clang_cc1 -fsyntax-only -std=gnu++98 -fblocks -Wno-address-of-temporary -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw-modern.cpp
// radar 7583971
diff --git a/test/Rewriter/rewrite-property-attributes.mm b/test/Rewriter/rewrite-property-attributes.mm
index 4a8b1972779c..0c7871c6d4f7 100644
--- a/test/Rewriter/rewrite-property-attributes.mm
+++ b/test/Rewriter/rewrite-property-attributes.mm
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc -fobjc-runtime=macosx-fragile-10.5 %s -o %t-rw.cpp
-// RUN: %clang_cc1 -fsyntax-only -Wno-address-of-temporary -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
+// RUN: %clang_cc1 -fsyntax-only -std=gnu++98 -Wno-address-of-temporary -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
// radar 7214439
typedef void (^void_block_t)(void);
diff --git a/test/Rewriter/rewrite-property-set-cfstring.mm b/test/Rewriter/rewrite-property-set-cfstring.mm
index 9de76428ada6..964d1a0f2022 100644
--- a/test/Rewriter/rewrite-property-set-cfstring.mm
+++ b/test/Rewriter/rewrite-property-set-cfstring.mm
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc -fobjc-runtime=macosx-fragile-10.5 %s -o %t-rw.cpp
-// RUN: %clang_cc1 -fsyntax-only -fblocks -Wno-address-of-temporary -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
+// RUN: %clang_cc1 -fsyntax-only -std=gnu++98 -fblocks -Wno-address-of-temporary -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
// rdar:// 8527018
void *sel_registerName(const char *);
diff --git a/test/Rewriter/rewrite-protocol-property.mm b/test/Rewriter/rewrite-protocol-property.mm
index c3f154c8526a..599ee8542c98 100644
--- a/test/Rewriter/rewrite-protocol-property.mm
+++ b/test/Rewriter/rewrite-protocol-property.mm
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc -fobjc-runtime=macosx-fragile-10.5 %s -o %t-rw.cpp
-// RUN: %clang_cc1 -fsyntax-only -fblocks -Wno-address-of-temporary -Did="void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
+// RUN: %clang_cc1 -fsyntax-only -std=gnu++98 -fblocks -Wno-address-of-temporary -Did="void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
// rdar:// 8558702
@class NSString;
diff --git a/test/Rewriter/rewrite-user-defined-accessors.mm b/test/Rewriter/rewrite-user-defined-accessors.mm
index 24d7b05d7aa5..4c35b5c4ef4e 100644
--- a/test/Rewriter/rewrite-user-defined-accessors.mm
+++ b/test/Rewriter/rewrite-user-defined-accessors.mm
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc -fobjc-runtime=macosx-fragile-10.5 %s -o %t-rw.cpp
-// RUN: %clang_cc1 -fsyntax-only -fblocks -Wno-address-of-temporary -Did="void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
+// RUN: %clang_cc1 -fsyntax-only -std=gnu++98 -fblocks -Wno-address-of-temporary -Did="void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
// rdar:// 8570020
@interface Foo {
diff --git a/test/Rewriter/rewrite-vararg.m b/test/Rewriter/rewrite-vararg.m
index ff7b250f809f..52aa5f9ca5a9 100644
--- a/test/Rewriter/rewrite-vararg.m
+++ b/test/Rewriter/rewrite-vararg.m
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc -fobjc-runtime=macosx-fragile-10.5 %s -o %t-rw.cpp
-// RUN: %clang_cc1 -fsyntax-only -fblocks -Wno-address-of-temporary -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
+// RUN: %clang_cc1 -fsyntax-only -std=gnu++98 -fblocks -Wno-address-of-temporary -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
// rdar://9056351
void *sel_registerName(const char *);
diff --git a/test/Sema/MicrosoftExtensions.c b/test/Sema/MicrosoftExtensions.c
index 62e5285970a7..79dba88a9903 100644
--- a/test/Sema/MicrosoftExtensions.c
+++ b/test/Sema/MicrosoftExtensions.c
@@ -28,6 +28,8 @@ struct D {
struct __declspec(uuid("00000000-0000-0000-C000-000000000046")) IUnknown {}; /* expected-error {{'uuid' attribute is not supported in C}} */
+[uuid("00000000-0000-0000-C000-000000000046")] struct IUnknown2 {}; /* expected-error {{'uuid' attribute is not supported in C}} */
+
typedef struct notnested {
long bad1;
long bad2;
diff --git a/test/Sema/aarch64-special-register.c b/test/Sema/aarch64-special-register.c
index a4fb92b5235b..1e658fd90769 100644
--- a/test/Sema/aarch64-special-register.c
+++ b/test/Sema/aarch64-special-register.c
@@ -41,7 +41,7 @@ void wsr64_2(unsigned long v) {
}
unsigned rsr_2() {
- return __builtin_arm_rsr("0:1:2:3:4");
+ return __builtin_arm_rsr("0:1:15:15:4");
}
void *rsrp_2() {
@@ -49,7 +49,7 @@ void *rsrp_2() {
}
unsigned long rsr64_2() {
- return __builtin_arm_rsr64("0:1:2:3:4");
+ return __builtin_arm_rsr64("0:1:15:15:4");
}
void wsr_3(unsigned v) {
@@ -68,6 +68,18 @@ unsigned rsr_3() {
return __builtin_arm_rsr("0:1:2"); //expected-error {{invalid special register for builtin}}
}
+unsigned rsr_4() {
+ return __builtin_arm_rsr("0:1:2:3:8"); //expected-error {{invalid special register for builtin}}
+}
+
+unsigned rsr_5() {
+ return __builtin_arm_rsr("0:8:1:2:3"); //expected-error {{invalid special register for builtin}}
+}
+
+unsigned rsr_6() {
+ return __builtin_arm_rsr("0:1:16:16:2"); //expected-error {{invalid special register for builtin}}
+}
+
void *rsrp_3() {
return __builtin_arm_rsrp("0:1:2"); //expected-error {{invalid special register for builtin}}
}
@@ -75,3 +87,15 @@ void *rsrp_3() {
unsigned long rsr64_3() {
return __builtin_arm_rsr64("0:1:2"); //expected-error {{invalid special register for builtin}}
}
+
+unsigned long rsr64_4() {
+ return __builtin_arm_rsr64("0:1:2:3:8"); //expected-error {{invalid special register for builtin}}
+}
+
+unsigned long rsr64_5() {
+ return __builtin_arm_rsr64("0:8:2:3:4"); //expected-error {{invalid special register for builtin}}
+}
+
+unsigned long rsr64_6() {
+ return __builtin_arm_rsr64("0:1:16:16:2"); //expected-error {{invalid special register for builtin}}
+}
diff --git a/test/Sema/address-packed-member-memops.c b/test/Sema/address-packed-member-memops.c
new file mode 100644
index 000000000000..220132f33298
--- /dev/null
+++ b/test/Sema/address-packed-member-memops.c
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+struct B {
+ int x, y, z, w;
+} b;
+
+struct __attribute__((packed)) A {
+ struct B b;
+} a;
+
+typedef __typeof__(sizeof(int)) size_t;
+
+void *memcpy(void *dest, const void *src, size_t n);
+int memcmp(const void *s1, const void *s2, size_t n);
+void *memmove(void *dest, const void *src, size_t n);
+void *memset(void *s, int c, size_t n);
+
+int x;
+
+void foo(void) {
+ memcpy(&a.b, &b, sizeof(b));
+ memmove(&a.b, &b, sizeof(b));
+ memset(&a.b, 0, sizeof(b));
+ x = memcmp(&a.b, &b, sizeof(b));
+}
diff --git a/test/Sema/address-packed.c b/test/Sema/address-packed.c
new file mode 100644
index 000000000000..2799e19c48f1
--- /dev/null
+++ b/test/Sema/address-packed.c
@@ -0,0 +1,331 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+#include <stdint.h>
+
+extern void f1(int *);
+extern void f2(char *);
+
+struct Ok {
+ char c;
+ int x;
+};
+
+struct __attribute__((packed)) Arguable {
+ char c0;
+ int x;
+ char c1;
+};
+
+union __attribute__((packed)) UnionArguable {
+ char c;
+ int x;
+};
+
+typedef struct Arguable ArguableT;
+
+struct Arguable *get_arguable();
+
+void to_void(void *);
+void to_intptr(intptr_t);
+
+void g0(void) {
+ {
+ struct Ok ok;
+ f1(&ok.x); // no-warning
+ f2(&ok.c); // no-warning
+ }
+ {
+ struct Arguable arguable;
+ f2(&arguable.c0); // no-warning
+ f1(&arguable.x); // expected-warning {{packed member 'x' of class or structure 'Arguable'}}
+ f2(&arguable.c1); // no-warning
+
+ f1((int *)(void *)&arguable.x); // no-warning
+ to_void(&arguable.x); // no-warning
+ void *p = &arguable.x; // no-warning
+ to_void(p);
+ to_intptr((intptr_t)p); // no-warning
+ }
+ {
+ union UnionArguable arguable;
+ f2(&arguable.c); // no-warning
+ f1(&arguable.x); // expected-warning {{packed member 'x' of class or structure 'UnionArguable'}}
+
+ f1((int *)(void *)&arguable.x); // no-warning
+ to_void(&arguable.x); // no-warning
+ to_intptr((intptr_t)&arguable.x); // no-warning
+ }
+ {
+ ArguableT arguable;
+ f2(&arguable.c0); // no-warning
+ f1(&arguable.x); // expected-warning {{packed member 'x' of class or structure 'Arguable'}}
+ f2(&arguable.c1); // no-warning
+
+ f1((int *)(void *)&arguable.x); // no-warning
+ to_void(&arguable.x); // no-warning
+ to_intptr((intptr_t)&arguable.x); // no-warning
+ }
+ {
+ struct Arguable *arguable = get_arguable();
+ f2(&arguable->c0); // no-warning
+ f1(&arguable->x); // expected-warning {{packed member 'x' of class or structure 'Arguable'}}
+ f2(&arguable->c1); // no-warning
+
+ f1((int *)(void *)&arguable->x); // no-warning
+ to_void(&arguable->c1); // no-warning
+ to_intptr((intptr_t)&arguable->c1); // no-warning
+ }
+ {
+ ArguableT *arguable = get_arguable();
+ f2(&(arguable->c0)); // no-warning
+ f1(&(arguable->x)); // expected-warning {{packed member 'x' of class or structure 'Arguable'}}
+ f2(&(arguable->c1)); // no-warning
+
+ f1((int *)(void *)&(arguable->x)); // no-warning
+ to_void(&(arguable->c1)); // no-warning
+ to_intptr((intptr_t)&(arguable->c1)); // no-warning
+ }
+}
+
+struct S1 {
+ char c;
+ int i __attribute__((packed));
+};
+
+int *g1(struct S1 *s1) {
+ return &s1->i; // expected-warning {{packed member 'i' of class or structure 'S1'}}
+}
+
+struct S2_i {
+ int i;
+};
+struct __attribute__((packed)) S2 {
+ char c;
+ struct S2_i inner;
+};
+
+int *g2(struct S2 *s2) {
+ return &s2->inner.i; // expected-warning {{packed member 'inner' of class or structure 'S2'}}
+}
+
+struct S2_a {
+ char c;
+ struct S2_i inner __attribute__((packed));
+};
+
+int *g2_a(struct S2_a *s2_a) {
+ return &s2_a->inner.i; // expected-warning {{packed member 'inner' of class or structure 'S2_a'}}
+}
+
+struct __attribute__((packed)) S3 {
+ char c;
+ struct {
+ int i;
+ } inner;
+};
+
+int *g3(struct S3 *s3) {
+ return &s3->inner.i; // expected-warning {{packed member 'inner' of class or structure 'S3'}}
+}
+
+struct S4 {
+ char c;
+ struct __attribute__((packed)) {
+ int i;
+ } inner;
+};
+
+int *g4(struct S4 *s4) {
+ return &s4->inner.i; // expected-warning {{packed member 'i' of class or structure 'S4::(anonymous)'}}
+}
+
+struct S5 {
+ char c;
+ struct {
+ char c1;
+ int i __attribute__((packed));
+ } inner;
+};
+
+int *g5(struct S5 *s5) {
+ return &s5->inner.i; // expected-warning {{packed member 'i' of class or structure 'S5::(anonymous)'}}
+}
+
+struct __attribute__((packed, aligned(2))) AlignedTo2 {
+ int x;
+};
+
+char *g6(struct AlignedTo2 *s) {
+ return (char *)&s->x; // no-warning
+}
+
+struct __attribute__((packed, aligned(2))) AlignedTo2Bis {
+ int x;
+};
+
+struct AlignedTo2Bis* g7(struct AlignedTo2 *s)
+{
+ return (struct AlignedTo2Bis*)&s->x; // no-warning
+}
+
+typedef struct {
+ char c;
+ int x;
+} __attribute__((packed)) TypedefStructArguable;
+
+typedef union {
+ char c;
+ int x;
+} __attribute((packed)) TypedefUnionArguable;
+
+typedef TypedefStructArguable TypedefStructArguableTheSecond;
+
+int *typedef1(TypedefStructArguable *s) {
+ return &s->x; // expected-warning {{packed member 'x' of class or structure 'TypedefStructArguable'}}
+}
+
+int *typedef2(TypedefStructArguableTheSecond *s) {
+ return &s->x; // expected-warning {{packed member 'x' of class or structure 'TypedefStructArguable'}}
+}
+
+int *typedef3(TypedefUnionArguable *s) {
+ return &s->x; // expected-warning {{packed member 'x' of class or structure 'TypedefUnionArguable'}}
+}
+
+struct S6 {
+ union {
+ char c;
+ int x;
+ } __attribute__((packed));
+};
+
+int *anonymousInnerUnion(struct S6 *s) {
+ return &s->x; // expected-warning {{packed member 'x' of class or structure 'S6::(anonymous)'}}
+}
+
+struct S6a {
+ int a;
+ int _;
+ int c;
+ char __;
+ int d;
+} __attribute__((packed, aligned(16))) s6;
+
+void g8()
+{
+ f1(&s6.a); // no-warning
+ f1(&s6.c); // no-warning
+ f1(&s6.d); // expected-warning {{packed member 'd' of class or structure 'S6a'}}
+}
+
+struct __attribute__((packed, aligned(1))) MisalignedContainee { double d; };
+struct __attribute__((aligned(8))) AlignedContainer { struct MisalignedContainee b; };
+
+struct AlignedContainer *p;
+double* g9() {
+ return &p->b.d; // no-warning
+}
+
+union OneUnion
+{
+ uint32_t a;
+ uint32_t b:1;
+};
+
+struct __attribute__((packed)) S7 {
+ uint8_t length;
+ uint8_t stuff;
+ uint8_t padding[2];
+ union OneUnion one_union;
+};
+
+union AnotherUnion {
+ long data;
+ struct S7 s;
+} *au;
+
+union OneUnion* get_OneUnion(void)
+{
+ return &au->s.one_union; // no-warning
+}
+
+struct __attribute__((packed)) S8 {
+ uint8_t data1;
+ uint8_t data2;
+ uint16_t wider_data;
+};
+
+#define LE_READ_2(p) \
+ ((uint16_t) \
+ ((((const uint8_t *)(p))[0] ) | \
+ (((const uint8_t *)(p))[1] << 8)))
+
+uint32_t get_wider_data(struct S8 *s)
+{
+ return LE_READ_2(&s->wider_data); // no-warning
+}
+
+struct S9 {
+ uint32_t x;
+ uint8_t y[2];
+ uint16_t z;
+} __attribute__((__packed__));
+
+typedef struct S9 __attribute__((__aligned__(16))) aligned_S9;
+
+void g10() {
+ struct S9 x;
+ struct S9 __attribute__((__aligned__(8))) y;
+ aligned_S9 z;
+
+ uint32_t *p32;
+ p32 = &x.x; // expected-warning {{packed member 'x' of class or structure 'S9'}}
+ p32 = &y.x; // no-warning
+ p32 = &z.x; // no-warning
+}
+
+typedef struct {
+ uint32_t msgh_bits;
+ uint32_t msgh_size;
+ int32_t msgh_voucher_port;
+ int32_t msgh_id;
+} S10Header;
+
+typedef struct {
+ uint32_t t;
+ uint64_t m;
+ uint32_t p;
+ union {
+ struct {
+ uint32_t a;
+ double z;
+ } __attribute__((aligned(8), packed)) a;
+ struct {
+ uint32_t b;
+ double z;
+ uint32_t a;
+ } __attribute__((aligned(8), packed)) b;
+ };
+} __attribute__((aligned(8), packed)) S10Data;
+
+typedef struct {
+ S10Header hdr;
+ uint32_t size;
+ uint8_t count;
+ S10Data data[] __attribute__((aligned(8)));
+} __attribute__((aligned(8), packed)) S10;
+
+void g11(S10Header *hdr);
+void g12(S10 *s) {
+ g11(&s->hdr); // no-warning
+}
+
+struct S11 {
+ uint32_t x;
+} __attribute__((__packed__));
+
+void g13(void) {
+ struct S11 __attribute__((__aligned__(4))) a[4];
+ uint32_t *p32;
+ p32 = &a[0].x; // no-warning
+}
diff --git a/test/Sema/alloc-size.c b/test/Sema/alloc-size.c
new file mode 100644
index 000000000000..7004a5a7d7f6
--- /dev/null
+++ b/test/Sema/alloc-size.c
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 %s -verify
+
+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 *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 *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}}
+
+int fail9(int a) __attribute__((alloc_size(1))); //expected-warning{{'alloc_size' attribute only applies to return values that are pointers}}
+
+int fail10 __attribute__((alloc_size(1))); //expected-warning{{'alloc_size' attribute only applies to functions}}
+
+void *fail11(void *a) __attribute__((alloc_size(1))); //expected-error{{'alloc_size' attribute argument may only refer to a function parameter of integer type}}
+
+void *fail12(int a) __attribute__((alloc_size("abc"))); //expected-error{{'alloc_size' attribute requires parameter 1 to be an integer constant}}
+void *fail12(int a) __attribute__((alloc_size(1, "abc"))); //expected-error{{'alloc_size' attribute requires parameter 2 to be an integer constant}}
+void *fail13(int a) __attribute__((alloc_size(1U<<31))); //expected-error{{integer constant expression evaluates to value 2147483648 that cannot be represented in a 32-bit signed integer type}}
+
+int (*PR31453)(int) __attribute__((alloc_size(1))); //expected-warning{{'alloc_size' attribute only applies to functions}}
diff --git a/test/Sema/arm-interrupt-attr.c b/test/Sema/arm-interrupt-attr.c
index e8f21ada7fc1..b9684f0b46c1 100644
--- a/test/Sema/arm-interrupt-attr.c
+++ b/test/Sema/arm-interrupt-attr.c
@@ -1,4 +1,7 @@
// RUN: %clang_cc1 %s -triple arm-apple-darwin -verify -fsyntax-only
+// RUN: %clang_cc1 %s -triple thumb-apple-darwin -verify -fsyntax-only
+// RUN: %clang_cc1 %s -triple armeb-none-eabi -verify -fsyntax-only
+// RUN: %clang_cc1 %s -triple thumbeb-none-eabi -verify -fsyntax-only
__attribute__((interrupt(IRQ))) void foo() {} // expected-error {{'interrupt' attribute requires a string}}
__attribute__((interrupt("irq"))) void foo1() {} // expected-warning {{'interrupt' attribute argument not supported: irq}}
diff --git a/test/Sema/arm-special-register.c b/test/Sema/arm-special-register.c
index 3ded628c137d..a9be80fba2ec 100644
--- a/test/Sema/arm-special-register.c
+++ b/test/Sema/arm-special-register.c
@@ -41,7 +41,7 @@ void wsr64_2(unsigned long v) {
}
unsigned rsr_2() {
- return __builtin_arm_rsr("cp0:1:c2:c3:4");
+ return __builtin_arm_rsr("cp0:1:c15:c15:4");
}
void *rsrp_2() {
@@ -73,13 +73,25 @@ void *rsrp_3() {
}
unsigned long rsr64_3() {
- return __builtin_arm_rsr64("cp0:1:c2");
+ return __builtin_arm_rsr64("cp0:1:c15");
}
unsigned rsr_4() {
return __builtin_arm_rsr("0:1:2:3:4"); //expected-error {{invalid special register for builtin}}
}
+unsigned rsr_5() {
+ return __builtin_arm_rsr("cp0:1:c2:c3:8"); //expected-error {{invalid special register for builtin}}
+}
+
+unsigned rsr_6() {
+ return __builtin_arm_rsr("cp0:8:c1:c2:3"); //expected-error {{invalid special register for builtin}}
+}
+
+unsigned rsr_7() {
+ return __builtin_arm_rsr("cp0:1:c16:c16:2"); //expected-error {{invalid special register for builtin}}
+}
+
void *rsrp_4() {
return __builtin_arm_rsrp("0:1:2:3:4"); //expected-error {{invalid special register for builtin}}
}
@@ -87,3 +99,11 @@ void *rsrp_4() {
unsigned long rsr64_4() {
return __builtin_arm_rsr64("0:1:2"); //expected-error {{invalid special register for builtin}}
}
+
+unsigned long rsr64_5() {
+ return __builtin_arm_rsr64("cp0:8:c1"); //expected-error {{invalid special register for builtin}}
+}
+
+unsigned long rsr64_6() {
+ return __builtin_arm_rsr64("cp0:1:c16"); //expected-error {{invalid special register for builtin}}
+}
diff --git a/test/Sema/asm.c b/test/Sema/asm.c
index 69c33f7ccf24..e49a1663a896 100644
--- a/test/Sema/asm.c
+++ b/test/Sema/asm.c
@@ -28,6 +28,16 @@ void clobbers() {
asm ("nop" : : : "204"); // expected-error {{unknown register name '204' in asm}}
asm ("nop" : : : "-1"); // expected-error {{unknown register name '-1' in asm}}
asm ("nop" : : : "+1"); // expected-error {{unknown register name '+1' in asm}}
+ register void *clobber_conflict asm ("%rcx");
+ register void *no_clobber_conflict asm ("%rax");
+ int a,b,c;
+ asm ("nop" : "=r" (no_clobber_conflict) : "r" (clobber_conflict) : "%rcx"); // expected-error {{asm-specifier for input or output variable conflicts with asm clobber list}}
+ asm ("nop" : "=r" (clobber_conflict) : "r" (no_clobber_conflict) : "%rcx"); // expected-error {{asm-specifier for input or output variable conflicts with asm clobber list}}
+ asm ("nop" : "=r" (clobber_conflict) : "r" (clobber_conflict) : "%rcx"); // expected-error {{asm-specifier for input or output variable conflicts with asm clobber list}}
+ asm ("nop" : "=c" (a) : "r" (no_clobber_conflict) : "%rcx"); // expected-error {{asm-specifier for input or output variable conflicts with asm clobber list}}
+ asm ("nop" : "=r" (no_clobber_conflict) : "c" (c) : "%rcx"); // expected-error {{asm-specifier for input or output variable conflicts with asm clobber list}}
+ asm ("nop" : "=r" (clobber_conflict) : "c" (c) : "%rcx"); // expected-error {{asm-specifier for input or output variable conflicts with asm clobber list}}
+ asm ("nop" : "=a" (a) : "b" (b) : "%rcx", "%rbx"); // expected-error {{asm-specifier for input or output variable conflicts with asm clobber list}}
}
// rdar://6094010
diff --git a/test/Sema/atomic-ops.c b/test/Sema/atomic-ops.c
index 05836214247c..8ebf3eaed4af 100644
--- a/test/Sema/atomic-ops.c
+++ b/test/Sema/atomic-ops.c
@@ -174,14 +174,14 @@ void f(_Atomic(int) *i, const _Atomic(int) *ci,
__atomic_fetch_or(D, 3, memory_order_seq_cst); // expected-error {{must be a pointer to integer}}
__atomic_fetch_and(s1, 3, memory_order_seq_cst); // expected-error {{must be a pointer to integer}}
- _Bool cmpexch_1 = __c11_atomic_compare_exchange_strong(i, 0, 1, memory_order_seq_cst, memory_order_seq_cst);
- _Bool cmpexch_2 = __c11_atomic_compare_exchange_strong(p, 0, (int*)1, memory_order_seq_cst, memory_order_seq_cst);
- _Bool cmpexch_3 = __c11_atomic_compare_exchange_strong(d, (int*)0, 1, memory_order_seq_cst, memory_order_seq_cst); // expected-warning {{incompatible pointer types}}
+ _Bool cmpexch_1 = __c11_atomic_compare_exchange_strong(i, I, 1, memory_order_seq_cst, memory_order_seq_cst);
+ _Bool cmpexch_2 = __c11_atomic_compare_exchange_strong(p, P, (int*)1, memory_order_seq_cst, memory_order_seq_cst);
+ _Bool cmpexch_3 = __c11_atomic_compare_exchange_strong(d, I, 1, memory_order_seq_cst, memory_order_seq_cst); // expected-warning {{incompatible pointer types}}
(void)__c11_atomic_compare_exchange_strong(i, CI, 1, memory_order_seq_cst, memory_order_seq_cst); // expected-warning {{passing 'const int *' to parameter of type 'int *' discards qualifiers}}
- _Bool cmpexchw_1 = __c11_atomic_compare_exchange_weak(i, 0, 1, memory_order_seq_cst, memory_order_seq_cst);
- _Bool cmpexchw_2 = __c11_atomic_compare_exchange_weak(p, 0, (int*)1, memory_order_seq_cst, memory_order_seq_cst);
- _Bool cmpexchw_3 = __c11_atomic_compare_exchange_weak(d, (int*)0, 1, memory_order_seq_cst, memory_order_seq_cst); // expected-warning {{incompatible pointer types}}
+ _Bool cmpexchw_1 = __c11_atomic_compare_exchange_weak(i, I, 1, memory_order_seq_cst, memory_order_seq_cst);
+ _Bool cmpexchw_2 = __c11_atomic_compare_exchange_weak(p, P, (int*)1, memory_order_seq_cst, memory_order_seq_cst);
+ _Bool cmpexchw_3 = __c11_atomic_compare_exchange_weak(d, I, 1, memory_order_seq_cst, memory_order_seq_cst); // expected-warning {{incompatible pointer types}}
(void)__c11_atomic_compare_exchange_weak(i, CI, 1, memory_order_seq_cst, memory_order_seq_cst); // expected-warning {{passing 'const int *' to parameter of type 'int *' discards qualifiers}}
_Bool cmpexch_4 = __atomic_compare_exchange_n(I, I, 5, 1, memory_order_seq_cst, memory_order_seq_cst);
@@ -503,4 +503,9 @@ 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}}
+}
diff --git a/test/Sema/attr-availability.c b/test/Sema/attr-availability.c
index 8fe6be3804ed..a4b40ff9e0c3 100644
--- a/test/Sema/attr-availability.c
+++ b/test/Sema/attr-availability.c
@@ -30,7 +30,7 @@ void test_10095131() {
ATSFontGetPostScriptName(100); // expected-error {{'ATSFontGetPostScriptName' is unavailable: obsoleted in macOS 9.0 - use ATSFontGetFullPostScriptName}}
#if defined(WARN_PARTIAL)
- // expected-warning@+2 {{is partial: introduced in macOS 10.8}} expected-note@+2 {{explicitly redeclare 'PartiallyAvailable' to silence this warning}}
+ // expected-warning@+2 {{is only available on macOS 10.8 or newer}} expected-note@+2 {{enclose 'PartiallyAvailable' in an @available check to silence this warning}}
#endif
PartiallyAvailable();
}
diff --git a/test/Sema/attr-naked.c b/test/Sema/attr-naked.c
index 6b1344a9860b..c9a3f1dbfcc1 100644
--- a/test/Sema/attr-naked.c
+++ b/test/Sema/attr-naked.c
@@ -48,3 +48,21 @@ __attribute__((naked)) void t9(int z) { // expected-note{{attribute is here}}
"r"(z) // expected-error{{parameter references not allowed in naked functions}}
);
}
+
+__attribute__((naked)) void t10() { // expected-note{{attribute is here}}
+ int a; // expected-error{{non-ASM statement in naked function is not supported}}
+}
+
+__attribute__((naked)) void t11() { // expected-note{{attribute is here}}
+ register int a asm("eax") = x; // expected-error{{non-ASM statement in naked function is not supported}}
+}
+
+__attribute__((naked)) void t12() { // expected-note{{attribute is here}}
+ register int a asm("eax"), b asm("ebx") = x; // expected-error{{non-ASM statement in naked function is not supported}}
+}
+
+__attribute__((naked)) void t13() {
+ register int a asm("eax");
+ register int b asm("ebx"), c asm("ecx");
+}
+
diff --git a/test/Sema/attr-section.c b/test/Sema/attr-section.c
index 812de067180c..c64b10d80ff6 100644
--- a/test/Sema/attr-section.c
+++ b/test/Sema/attr-section.c
@@ -10,7 +10,7 @@ int y __attribute__((section(
// PR6007
void test() {
- __attribute__((section("NEAR,x"))) int n1; // expected-error {{'section' attribute only applies to functions and global variables}}
+ __attribute__((section("NEAR,x"))) int n1; // expected-error {{'section' attribute only applies to functions, methods, properties, and global variables}}
__attribute__((section("NEAR,x"))) static int n2; // ok.
}
@@ -18,4 +18,4 @@ void test() {
void __attribute__((section("foo,zed"))) test2(void); // expected-note {{previous attribute is here}}
void __attribute__((section("bar,zed"))) test2(void) {} // expected-warning {{section does not match previous declaration}}
-enum __attribute__((section("NEAR,x"))) e { one }; // expected-error {{'section' attribute only applies to functions and global variables}}
+enum __attribute__((section("NEAR,x"))) e { one }; // expected-error {{'section' attribute only applies to functions, methods, properties, and global variables}}
diff --git a/test/Sema/attr-selectany.c b/test/Sema/attr-selectany.c
new file mode 100644
index 000000000000..01cca7d7cfa5
--- /dev/null
+++ b/test/Sema/attr-selectany.c
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -fms-compatibility -fms-extensions -verify %s
+
+extern __declspec(selectany) const int x1 = 1; // no warning, const means we need extern in C++
+
+// Should we really warn on this?
+extern __declspec(selectany) int x2 = 1; // expected-warning {{'extern' variable has an initializer}}
+
+__declspec(selectany) void foo() { } // expected-error{{'selectany' can only be applied to data items with external linkage}}
diff --git a/test/Sema/attr-swiftcall.c b/test/Sema/attr-swiftcall.c
index 3458167cf2e8..0323f059bab5 100644
--- a/test/Sema/attr-swiftcall.c
+++ b/test/Sema/attr-swiftcall.c
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple x86_64-unknown-windows -fsyntax-only -verify %s
#define SWIFTCALL __attribute__((swiftcall))
#define INDIRECT_RESULT __attribute__((swift_indirect_result))
@@ -18,13 +19,13 @@ void indirect_result_single(INDIRECT_RESULT void *out) SWIFTCALL;
void indirect_result_multiple(INDIRECT_RESULT void *out1, INDIRECT_RESULT void *out2) SWIFTCALL;
void error_result_nonswift(ERROR_RESULT void **error); // expected-error {{'swift_error_result' parameter can only be used with swiftcall calling convention}} expected-error{{'swift_error_result' parameter must follow 'swift_context' parameter}}
-void error_result_bad_position(ERROR_RESULT void **error, int last) SWIFTCALL; // expected-error {{'swift_error_result' parameter must be last parameter of function}}
void error_result_bad_position2(int first, ERROR_RESULT void **error) SWIFTCALL; // expected-error {{'swift_error_result' parameter must follow 'swift_context' parameter}}
void error_result_bad_type(CONTEXT void *context, ERROR_RESULT int error) SWIFTCALL; // expected-error {{'swift_error_result' parameter must have pointer to unqualified pointer type; type here is 'int'}}
void error_result_bad_type2(CONTEXT void *context, ERROR_RESULT int *error) SWIFTCALL; // expected-error {{'swift_error_result' parameter must have pointer to unqualified pointer type; type here is 'int *'}}
void error_result_okay(int a, int b, CONTEXT void *context, ERROR_RESULT void **error) SWIFTCALL;
+void error_result_okay2(CONTEXT void *context, ERROR_RESULT void **error, void *selfType, char **selfWitnessTable) SWIFTCALL;
void context_nonswift(CONTEXT void *context); // expected-error {{'swift_context' parameter can only be used with swiftcall calling convention}}
-void context_bad_position(CONTEXT void *context, int x) SWIFTCALL; // expected-error {{'swift_context' parameter can only be followed by 'swift_error_result' parameter}}
void context_bad_type(CONTEXT int context) SWIFTCALL; // expected-error {{'swift_context' parameter must have pointer type; type here is 'int'}}
void context_okay(CONTEXT void *context) SWIFTCALL;
+void context_okay2(CONTEXT void *context, void *selfType, char **selfWitnessTable) SWIFTCALL;
diff --git a/test/Sema/attr-unavailable-message.c b/test/Sema/attr-unavailable-message.c
index 400a2c632883..415cb2f079a2 100644
--- a/test/Sema/attr-unavailable-message.c
+++ b/test/Sema/attr-unavailable-message.c
@@ -1,6 +1,8 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
// rdar: //6734520
+void tooManyArgs() __attribute__((unavailable("a", "b"))); // expected-error {{'unavailable' attribute takes no more than 1 argument}}
+
int foo(int) __attribute__((__unavailable__("USE IFOO INSTEAD"))); // expected-note {{'foo' has been explicitly marked unavailable here}}
double dfoo(double) __attribute__((__unavailable__("NO LONGER"))); // expected-note 2 {{'dfoo' has been explicitly marked unavailable here}}
diff --git a/test/Sema/builtin-alloca-with-align.c b/test/Sema/builtin-alloca-with-align.c
new file mode 100644
index 000000000000..16d71da60080
--- /dev/null
+++ b/test/Sema/builtin-alloca-with-align.c
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+void test1(int a) {
+ __builtin_alloca_with_align(a, 32);
+}
+
+void test2(int a) {
+ __builtin_alloca_with_align(a, -32); // expected-error {{requested alignment is not a power of 2}}
+}
+
+void test3(unsigned *b) {
+ __builtin_alloca_with_align(b, 32); // expected-warning {{incompatible pointer to integer conversion passing 'unsigned int *' to parameter of type}}
+}
+
+void test4(int a) {
+ __builtin_alloca_with_align(a, 32, 0); // expected-error {{too many arguments to function call, expected 2, have 3}}
+}
+
+void test5(int a) {
+ __builtin_alloca_with_align(a, 31); // expected-error {{requested alignment is not a power of 2}}
+}
+
+void test6(int a, int j) {
+ __builtin_alloca_with_align(a, j); // expected-error {{must be a constant integer}}
+}
+
+void test7(int a) {
+ __builtin_alloca_with_align(a, 2); // expected-error {{requested alignment must be 8 or greater}}
+}
+
+void test8() {
+ __builtin_alloca_with_align(sizeof(__INT64_TYPE__), __alignof__(__INT64_TYPE__)); // expected-warning {{second argument to __builtin_alloca_with_align is supposed to be in bits}}
+}
diff --git a/test/Sema/builtin-unary-fp.c b/test/Sema/builtin-unary-fp.c
index 57568db8ae3f..2b75b10fcbe5 100644
--- a/test/Sema/builtin-unary-fp.c
+++ b/test/Sema/builtin-unary-fp.c
@@ -11,6 +11,7 @@ void a() {
check(__builtin_isnan(1,2)); // expected-error{{too many arguments}}
check(__builtin_fpclassify(0, 0, 0, 0, 0, 1.0));
check(__builtin_fpclassify(0, 0, 0, 0, 0, 1)); // expected-error{{requires argument of floating point type}}
+ check(__builtin_fpclassify(0, 1, 2, 3, 4.5, 5.0)); // expected-warning{{implicit conversion from 'double' to 'int' changes value from 4.5 to 4}}
check(__builtin_fpclassify(0, 0, 0, 0, 1)); // expected-error{{too few arguments}}
check(__builtin_fpclassify(0, 0, 0, 0, 0, 1, 0)); // expected-error{{too many arguments}}
}
diff --git a/test/Sema/builtins-x86.c b/test/Sema/builtins-x86.c
index 326d2a3a7a16..6929dcc65090 100644
--- a/test/Sema/builtins-x86.c
+++ b/test/Sema/builtins-x86.c
@@ -27,11 +27,11 @@ __m128d test__builtin_ia32_cmpsd(__m128d __a, __m128d __b) {
}
__mmask16 test__builtin_ia32_cmpps512_mask(__m512d __a, __m512d __b) {
- __builtin_ia32_cmpps512_mask(__a, __b, 32, -1, 0); // expected-error {{argument should be a value from 0 to 31}}
+ __builtin_ia32_cmpps512_mask(__a, __b, 32, -1, 4); // expected-error {{argument should be a value from 0 to 31}}
}
__mmask8 test__builtin_ia32_cmppd512_mask(__m512d __a, __m512d __b) {
- __builtin_ia32_cmppd512_mask(__a, __b, 32, -1, 0); // expected-error {{argument should be a value from 0 to 31}}
+ __builtin_ia32_cmppd512_mask(__a, __b, 32, -1, 4); // expected-error {{argument should be a value from 0 to 31}}
}
__m128i test__builtin_ia32_vpcomub(__m128i __a, __m128i __b) {
@@ -65,3 +65,7 @@ __m128i test__builtin_ia32_vpcomd(__m128i __a, __m128i __b) {
__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}}
}
+
+__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}}
+}
diff --git a/test/Sema/builtins-x86_64.c b/test/Sema/builtins-x86_64.c
new file mode 100644
index 000000000000..46227bae2493
--- /dev/null
+++ b/test/Sema/builtins-x86_64.c
@@ -0,0 +1,60 @@
+// RUN: %clang_cc1 -triple i386-unknown-unknown -fsyntax-only -fno-spell-checking -verify %s
+
+typedef int v4si __attribute__((vector_size(16)));
+typedef float v4f __attribute__((vector_size(16)));
+typedef double v2d __attribute__((vector_size(16)));
+typedef long long v2ll __attribute__((vector_size(16)));
+typedef long long v4ll __attribute__((vector_size(32)));
+typedef long long v8ll __attribute__((vector_size(64)));
+void call_x86_64_builtins(void) {
+ unsigned long long *ullp;
+ void *vp;
+ v4f vec4floats;
+ v2d vec2doubles;
+ v2ll vec2longlongs;
+ v4ll vec4longlongs;
+ v8ll vec8longlongs;
+ (void)__builtin_ia32_readeflags_u64(); // expected-error{{use of unknown builtin}}
+ (void)__builtin_ia32_writeeflags_u64(4); // expected-error{{use of unknown builtin}}
+ (void)__builtin_ia32_cvtss2si64(vec4floats); // expected-error{{use of unknown builtin}}
+ (void)__builtin_ia32_cvttss2si64(vec4floats); // expected-error{{use of unknown builtin}}
+ (void)__builtin_ia32_cvtsd2si64(vec2doubles); // expected-error{{use of unknown builtin}}
+ (void)__builtin_ia32_cvttsd2si64(vec2doubles); // expected-error{{use of unknown builtin}}
+ (void)__builtin_ia32_crc32di(4, 4); // expected-error{{use of unknown builtin}}
+ (void)__builtin_ia32_rdfsbase64(); // expected-error{{use of unknown builtin}}
+ (void)__builtin_ia32_rdgsbase64(); // expected-error{{use of unknown builtin}}
+ (void)__builtin_ia32_wrfsbase64(4); // expected-error{{use of unknown builtin}}
+ (void)__builtin_ia32_wrgsbase64(4); // expected-error{{use of unknown builtin}}
+ (void)__builtin_ia32_fxrstor64(vp); // expected-error{{use of unknown builtin}}
+ (void)__builtin_ia32_fxsave64(vp); // expected-error{{use of unknown builtin}}
+ (void)__builtin_ia32_xsave64(vp, 4); // expected-error{{use of unknown builtin}}
+ (void)__builtin_ia32_xrstor64(vp, 4); // expected-error{{use of unknown builtin}}
+ (void)__builtin_ia32_xsaveopt64(vp, 4); // expected-error{{use of unknown builtin}}
+ (void)__builtin_ia32_xrstors64(vp, 4); // expected-error{{use of unknown builtin}}
+ (void)__builtin_ia32_xsavec64(vp, 4); // expected-error{{use of unknown builtin}}
+ (void)__builtin_ia32_xsaves64(vp, 4); // expected-error{{use of unknown builtin}}
+ (void)__builtin_ia32_addcarryx_u64(4, 4, 4, ullp); // expected-error{{use of unknown builtin}}
+ (void)__builtin_ia32_addcarry_u64(4, 4, 4, ullp); // expected-error{{use of unknown builtin}}
+ (void)__builtin_ia32_subborrow_u64(4, 4, 4, ullp); // expected-error{{use of unknown builtin}}
+ (void)__builtin_ia32_rdseed64_step(ullp); // expected-error{{use of unknown builtin}}
+ (void)__builtin_ia32_bextr_u64(4, 4); // expected-error{{use of unknown builtin}}
+ (void)__builtin_ia32_bzhi_di(4, 4); // expected-error{{use of unknown builtin}}
+ (void)__builtin_ia32_pdep_di(4, 4); // expected-error{{use of unknown builtin}}
+ (void)__builtin_ia32_pext_di(4, 4); // expected-error{{use of unknown builtin}}
+ (void)__builtin_ia32_bextri_u64(4, 4); // expected-error{{use of unknown builtin}}
+ (void)__builtin_ia32_pbroadcastq512_gpr_mask(4, vec8longlongs, 4); // expected-error{{use of unknown builtin}}
+ (void)__builtin_ia32_pbroadcastq128_gpr_mask(4, vec2longlongs, 4); // expected-error{{use of unknown builtin}}
+ (void)__builtin_ia32_pbroadcastq256_gpr_mask(4, vec4longlongs, 4); // expected-error{{use of unknown builtin}}
+ (void)__builtin_ia32_vcvtsd2si64(vec2doubles, 4); // expected-error{{use of unknown builtin}}
+ (void)__builtin_ia32_vcvtsd2usi64(vec2doubles, 4); // expected-error{{use of unknown builtin}}
+ (void)__builtin_ia32_vcvtss2si64(vec4floats, 4); // expected-error{{use of unknown builtin}}
+ (void)__builtin_ia32_vcvtss2usi64(vec4floats, 4); // expected-error{{use of unknown builtin}}
+ (void)__builtin_ia32_vcvttsd2si64(vec2doubles, 4); // expected-error{{use of unknown builtin}}
+ (void)__builtin_ia32_vcvttsd2usi64(vec2doubles, 4); // expected-error{{use of unknown builtin}}
+ (void)__builtin_ia32_vcvttss2si64(vec4floats, 4); // expected-error{{use of unknown builtin}}
+ (void)__builtin_ia32_vcvttss2usi64(vec4floats, 4); // expected-error{{use of unknown builtin}}
+ (void)__builtin_ia32_cvtsi2sd64(vec2doubles, 4, 4); // expected-error{{use of unknown builtin}}
+ (void)__builtin_ia32_cvtsi2ss64(vec4floats, 4, 4); // expected-error{{use of unknown builtin}}
+ (void)__builtin_ia32_cvtusi2sd64(vec2doubles, 4, 4); // expected-error{{use of unknown builtin}}
+ (void)__builtin_ia32_cvtusi2ss64(vec4floats, 4, 4); // expected-error{{use of unknown builtin}}
+}
diff --git a/test/Sema/builtins.cl b/test/Sema/builtins.cl
index 8cde8f3d10ff..7cde5e1a9e4d 100644
--- a/test/Sema/builtins.cl
+++ b/test/Sema/builtins.cl
@@ -1,8 +1,11 @@
// RUN: %clang_cc1 %s -fsyntax-only -verify -pedantic
-// expected-no-diagnostics
kernel void test(global float *out, global float *in, global int* in2) {
out[0] = __builtin_nanf("");
__builtin_memcpy(out, in, 32);
out[0] = __builtin_frexpf(in[0], in2);
}
+
+void pr28651() {
+ __builtin_alloca(value); // expected-error{{use of undeclared identifier}}
+}
diff --git a/test/Sema/compound-literal.c b/test/Sema/compound-literal.c
index c5c0c17143fa..217dbeda8a7b 100644
--- a/test/Sema/compound-literal.c
+++ b/test/Sema/compound-literal.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -pedantic %s
+// RUN: %clang_cc1 -fsyntax-only -verify -fblocks -pedantic %s
// REQUIRES: LP64
struct foo { int a, b; };
@@ -36,3 +36,9 @@ void IncompleteFunc(unsigned x) {
// PR6080
int array[(sizeof(int[3]) == sizeof( (int[]) {0,1,2} )) ? 1 : -1];
+
+// rdar://28949016 - Constant restriction should not apply to compound literals in blocks
+int (^block)(int) = ^(int i) {
+ int *array = (int[]) {i, i + 2, i + 4};
+ return array[i];
+};
diff --git a/test/Sema/constant-conversion.c b/test/Sema/constant-conversion.c
index 203e7373897c..bf8221089d8c 100644
--- a/test/Sema/constant-conversion.c
+++ b/test/Sema/constant-conversion.c
@@ -11,7 +11,7 @@ void test_6792488(void) {
void test_7809123(void) {
struct { int i5 : 5; } a;
- a.i5 = 36; // expected-warning {{implicit truncation from 'int' to bitfield changes value from 36 to 4}}
+ a.i5 = 36; // expected-warning {{implicit truncation from 'int' to bit-field changes value from 36 to 4}}
}
void test() {
@@ -31,11 +31,11 @@ void test3() {
int bar : 2;
};
- struct A a = { 0, 10 }; // expected-warning {{implicit truncation from 'int' to bitfield changes value from 10 to -2}}
- struct A b[] = { 0, 10, 0, 0 }; // expected-warning {{implicit truncation from 'int' to bitfield changes value from 10 to -2}}
- struct A c[] = {{10, 0}}; // expected-warning {{implicit truncation from 'int' to bitfield changes value from 10 to 2}}
- struct A d = (struct A) { 10, 0 }; // expected-warning {{implicit truncation from 'int' to bitfield changes value from 10 to 2}}
- struct A e = { .foo = 10 }; // expected-warning {{implicit truncation from 'int' to bitfield changes value from 10 to 2}}
+ struct A a = { 0, 10 }; // expected-warning {{implicit truncation from 'int' to bit-field changes value from 10 to -2}}
+ struct A b[] = { 0, 10, 0, 0 }; // expected-warning {{implicit truncation from 'int' to bit-field changes value from 10 to -2}}
+ struct A c[] = {{10, 0}}; // expected-warning {{implicit truncation from 'int' to bit-field changes value from 10 to 2}}
+ struct A d = (struct A) { 10, 0 }; // expected-warning {{implicit truncation from 'int' to bit-field changes value from 10 to 2}}
+ struct A e = { .foo = 10 }; // expected-warning {{implicit truncation from 'int' to bit-field changes value from 10 to 2}}
}
void test4() {
@@ -43,7 +43,7 @@ void test4() {
char c : 2;
} a;
- a.c = 0x101; // expected-warning {{implicit truncation from 'int' to bitfield changes value from 257 to 1}}
+ a.c = 0x101; // expected-warning {{implicit truncation from 'int' to bit-field changes value from 257 to 1}}
}
void test5() {
@@ -52,7 +52,7 @@ void test5() {
} a;
// Don't warn about this implicit conversion to bool, or at least
- // don't warn about it just because it's a bitfield.
+ // don't warn about it just because it's a bit-field.
a.b = 100;
}
@@ -69,8 +69,9 @@ void test7() {
unsigned int reserved:28;
} f;
- f.twoBits1 = ~1; // expected-warning {{implicit truncation from 'int' to bitfield changes value from -2 to 2}}
- f.twoBits2 = ~2; // expected-warning {{implicit truncation from 'int' to bitfield changes value from -3 to 1}}
+ f.twoBits1 = ~0; // no-warning
+ f.twoBits1 = ~1; // no-warning
+ f.twoBits2 = ~2; // expected-warning {{implicit truncation from 'int' to bit-field changes value from -3 to 1}}
f.twoBits1 &= ~1; // no-warning
f.twoBits2 &= ~2; // no-warning
}
@@ -78,7 +79,7 @@ void test7() {
void test8() {
enum E { A, B, C };
struct { enum E x : 1; } f;
- f.x = C; // expected-warning {{implicit truncation from 'int' to bitfield changes value from 2 to 0}}
+ f.x = C; // expected-warning {{implicit truncation from 'int' to bit-field changes value from 2 to 0}}
}
void test9() {
@@ -114,6 +115,8 @@ void test9() {
char array_init[] = { 255, 127, 128, 129, 0 };
}
+#define A 1
+
void test10() {
struct S {
unsigned a : 4;
@@ -121,7 +124,10 @@ void test10() {
s.a = -1;
s.a = 15;
s.a = -8;
+ s.a = ~0;
+ s.a = ~0U;
+ s.a = ~(1<<A);
- s.a = -9; // expected-warning{{implicit truncation from 'int' to bitfield changes value from -9 to 7}}
- s.a = 16; // expected-warning{{implicit truncation from 'int' to bitfield changes value from 16 to 0}}
+ s.a = -9; // expected-warning{{implicit truncation from 'int' to bit-field changes value from -9 to 7}}
+ s.a = 16; // expected-warning{{implicit truncation from 'int' to bit-field changes value from 16 to 0}}
}
diff --git a/test/Sema/decl-in-prototype.c b/test/Sema/decl-in-prototype.c
index 3b8a3b860371..64caea6a38a8 100644
--- a/test/Sema/decl-in-prototype.c
+++ b/test/Sema/decl-in-prototype.c
@@ -1,13 +1,19 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
+#define SA(n, c) int arr##n[(c) ? 1 : -1] = {}
+
const int AA = 5;
int f1(enum {AA,BB} E) { // expected-warning {{will not be visible outside of this function}}
- return BB;
+ SA(1, AA == 0);
+ SA(2, BB == 1);
+ return BB;
}
int f2(enum {AA=7,BB} E) { // expected-warning {{will not be visible outside of this function}}
- return AA;
+ SA(1, AA == 7);
+ SA(2, BB == 8);
+ return AA;
}
struct a {
@@ -38,3 +44,52 @@ enum e19018 qq; //expected-error{{tentative definition has type 'enum e19018' th
// Only warn once, even if we create two declarations.
void f(struct q *, struct __attribute__((aligned(4))) q *); // expected-warning {{will not be visible outside}}
+
+// This enum inside the function pointer parameter shouldn't leak into the
+// function.
+enum { BB = 0 };
+void enum_in_fun_in_fun(void (*fp)(enum { AA, BB } e)) { // expected-warning {{will not be visible}}
+ SA(1, AA == 5);
+ SA(2, BB == 0);
+}
+
+void f7() {
+ extern void ext(struct S { enum E7 { a, b } o; } p); // expected-warning 2 {{will not be visible}}
+ ext(a); // expected-error {{use of undeclared identifier}}
+}
+
+int f8(struct S { enum E8 { a, b } o; } p) { // expected-warning 2 {{will not be visible}}
+ struct S o;
+ enum E8 x;
+ return a + b;
+}
+// expected-note@+1 {{forward declaration}}
+struct S o; // expected-error {{'struct S' that is never completed}}
+// expected-note@+1 {{forward declaration}}
+enum E8 x = a + b; // expected-error 2 {{undeclared identifier}} expected-error {{incomplete type 'enum E8'}}
+
+int f9(struct { enum e { a = 1 } b; } c) { // expected-warning {{will not be visible}}
+ return a;
+}
+
+int f10(
+ struct S { // expected-warning {{will not be visible}}
+ enum E10 { a, b, c } f; // expected-warning {{will not be visible}}
+ } e) {
+ return a == b;
+}
+
+int f11(
+ struct S { // expected-warning {{will not be visible}}
+ enum E11 { // expected-warning {{will not be visible}}
+ a, b, c
+ } // expected-warning {{expected ';' at end of declaration list}}
+ } // expected-error {{expected member name or ';'}}
+ e);
+
+void f12() {
+ extern int ext12(
+ struct S12 { } e // expected-warning {{will not be visible}}
+ );
+ struct S12 o; // expected-error {{incomplete type}} expected-note {{forward declaration}}
+}
diff --git a/test/Sema/dllimport.c b/test/Sema/dllimport.c
index 0728cf14a8e3..a7fb00e3f773 100644
--- a/test/Sema/dllimport.c
+++ b/test/Sema/dllimport.c
@@ -210,6 +210,10 @@ __declspec(dllimport) void redecl6();
void redecl7();
__declspec(dllimport) inline void redecl7() {}
+// PR31069: Don't crash trying to merge attributes for redeclaration of invalid decl.
+void __declspec(dllimport) redecl8(unknowntype X); // expected-error{{unknown type name 'unknowntype'}}
+void redecl8(unknowntype X) { } // expected-error{{unknown type name 'unknowntype'}}
+
// External linkage is required.
__declspec(dllimport) static int staticFunc(); // expected-error{{'staticFunc' must have external linkage when declared 'dllimport'}}
diff --git a/test/Sema/ext_vector_components.c b/test/Sema/ext_vector_components.c
index 7d3d52aa9546..3cdeb215f876 100644
--- a/test/Sema/ext_vector_components.c
+++ b/test/Sema/ext_vector_components.c
@@ -39,6 +39,33 @@ static void test() {
vec4.x = vec16.sF;
vec4p->yz = vec4p->xy;
+
+ vec2.a; // expected-error {{vector component access exceeds type 'float2'}}
+ vec2.rgba; // expected-error {{vector component access exceeds type 'float2'}}
+ vec4.rgba; // expected-warning {{expression result unused}}
+ vec4.rgbz; // expected-error {{illegal vector component name 'z'}}
+ vec4.rgbc; // expected-error {{illegal vector component name 'c'}}
+ vec4.xyzr; // expected-error {{illegal vector component name 'r'}}
+ vec4.s01b; // expected-error {{vector component access exceeds type 'float4'}}
+
+ vec3 = vec4.rgb; // legal, shorten
+ f = vec2.r; // legal, shorten
+ f = vec4.rg.r; // legal, shorten
+ vec4_2.rgba = vec4.xyzw; // legal, no intermingling
+
+ vec4_2.rgbr = vec4.rgba; // expected-error {{vector is not assignable (contains duplicate components)}}
+ vec4_2.rgbb = vec4.rgba; // expected-error {{vector is not assignable (contains duplicate components)}}
+ vec4_2.rgga = vec4.rgba; // expected-error {{vector is not assignable (contains duplicate components)}}
+ vec2.x = f;
+ vec2.rr = vec2_2.rg; // expected-error {{vector is not assignable (contains duplicate components)}}
+ vec2.gr = vec2_2.rg;
+ vec2.gr.g = vec2_2.r;
+ vec4 = (float4){ 1,2,3,4 };
+ vec4.rg.b; // expected-error {{vector component access exceeds type 'float2'}}
+ vec4.r = vec16.sf;
+ vec4.g = vec16.sF;
+
+ vec4p->gb = vec4p->rg;
}
float2 lo(float3 x) { return x.lo; }
diff --git a/test/Sema/format-strings-enum.c b/test/Sema/format-strings-enum.c
index e79f8598ab47..ba077a887e01 100644
--- a/test/Sema/format-strings-enum.c
+++ b/test/Sema/format-strings-enum.c
@@ -11,6 +11,7 @@
#endif
EXTERN_C int printf(const char *,...);
+EXTERN_C int scanf(const char *, ...);
typedef enum { Constant = 0 } TestEnum;
// Note that in C, the type of 'Constant' is 'int'. In C++ it is 'TestEnum'.
@@ -34,3 +35,18 @@ void testLong(LongEnum input) {
printf("%lu", input);
printf("%lu", LongConstant);
}
+
+#ifndef __cplusplus
+// GNU C allows forward declaring enums.
+extern enum forward_declared *fwd;
+
+void forward_enum() {
+ printf("%u", fwd); // expected-warning{{format specifies type 'unsigned int' but the argument has type 'enum forward_declared *}}
+ printf("%p", fwd);
+
+ scanf("%c", fwd); // expected-warning{{format specifies type 'char *' but the argument has type 'enum forward_declared *}}
+ scanf("%u", fwd);
+ scanf("%lu", fwd); // expected-warning{{format specifies type 'unsigned long *' but the argument has type 'enum forward_declared *}}
+ scanf("%p", fwd); // expected-warning{{format specifies type 'void **' but the argument has type 'enum forward_declared *}}
+}
+#endif
diff --git a/test/Sema/format-strings.c b/test/Sema/format-strings.c
index 5559710c6035..54651226adc5 100644
--- a/test/Sema/format-strings.c
+++ b/test/Sema/format-strings.c
@@ -156,10 +156,10 @@ void check_writeback_specifier()
void check_invalid_specifier(FILE* fp, char *buf)
{
- printf("%s%lb%d","unix",10,20); // expected-warning {{invalid conversion specifier 'b'}}
+ printf("%s%lb%d","unix",10,20); // expected-warning {{invalid conversion specifier 'b'}} expected-warning {{data argument not used by format string}}
fprintf(fp,"%%%l"); // expected-warning {{incomplete format specifier}}
sprintf(buf,"%%%%%ld%d%d", 1, 2, 3); // expected-warning{{format specifies type 'long' but the argument has type 'int'}}
- snprintf(buf, 2, "%%%%%ld%;%d", 1, 2, 3); // expected-warning{{format specifies type 'long' but the argument has type 'int'}} expected-warning {{invalid conversion specifier ';'}}
+ snprintf(buf, 2, "%%%%%ld%;%d", 1, 2, 3); // expected-warning{{format specifies type 'long' but the argument has type 'int'}} expected-warning {{invalid conversion specifier ';'}} expected-warning {{data argument not used by format string}}
}
void check_null_char_string(char* b)
@@ -251,7 +251,7 @@ void test10(int x, float f, int i, long long lli) {
printf("%**\n"); // expected-warning{{invalid conversion specifier '*'}}
printf("%d%d\n", x); // expected-warning{{more '%' conversions than data arguments}}
printf("%d\n", x, x); // expected-warning{{data argument not used by format string}}
- printf("%W%d\n", x, x); // expected-warning{{invalid conversion specifier 'W'}}
+ printf("%W%d\n", x, x); // expected-warning{{invalid conversion specifier 'W'}} expected-warning {{data argument not used by format string}}
printf("%"); // expected-warning{{incomplete format specifier}}
printf("%.d", x); // no-warning
printf("%.", x); // expected-warning{{incomplete format specifier}}
@@ -270,7 +270,7 @@ void test10(int x, float f, int i, long long lli) {
printf("%.0Lf", (long double) 1.0); // no-warning
printf("%c\n", "x"); // expected-warning{{format specifies type 'int' but the argument has type 'char *'}}
printf("%c\n", 1.23); // expected-warning{{format specifies type 'int' but the argument has type 'double'}}
- printf("Format %d, is %! %f", 1, 2, 4.4); // expected-warning{{invalid conversion specifier '!'}}
+ printf("Format %d, is %! %f", 1, 4.4); // expected-warning{{invalid conversion specifier '!'}}
}
typedef unsigned char uint8_t;
@@ -652,3 +652,43 @@ void test_format_security_pos(char* string) {
// expected-note@-1{{treat the string as an argument to avoid this}}
}
#pragma GCC diagnostic warning "-Wformat-nonliteral"
+
+void test_char_pointer_arithmetic(int b) {
+ const char s1[] = "string";
+ const char s2[] = "%s string";
+
+ printf(s1 - 1); // expected-warning {{format string is not a string literal (potentially insecure)}}
+ // expected-note@-1{{treat the string as an argument to avoid this}}
+
+ printf(s1 + 2); // no-warning
+ printf(s2 + 2); // no-warning
+
+ const char s3[] = "%s string";
+ printf((s3 + 2) - 2); // expected-warning{{more '%' conversions than data arguments}}
+ // expected-note@-2{{format string is defined here}}
+ printf(2 + s2); // no-warning
+ printf(6 + s2 - 2); // no-warning
+ printf(2 + (b ? s1 : s2)); // no-warning
+
+ const char s5[] = "string %s";
+ printf(2 + (b ? s2 : s5)); // expected-warning{{more '%' conversions than data arguments}}
+ // expected-note@-2{{format string is defined here}}
+ printf(2 + (b ? s2 : s5), ""); // no-warning
+ printf(2 + (b ? s1 : s2 - 2), ""); // no-warning
+
+ const char s6[] = "%s string";
+ printf(2 + (b ? s1 : s6 - 2)); // expected-warning{{more '%' conversions than data arguments}}
+ // expected-note@-2{{format string is defined here}}
+ printf(1 ? s2 + 2 : s2); // no-warning
+ printf(0 ? s2 : s2 + 2); // no-warning
+ printf(2 + s2 + 5 * 3 - 16, ""); // expected-warning{{data argument not used}}
+
+ const char s7[] = "%s string %s %s";
+ printf(s7 + 3, ""); // expected-warning{{more '%' conversions than data arguments}}
+ // expected-note@-2{{format string is defined here}}
+}
+
+void PR30481() {
+ // This caused crashes due to invalid casts.
+ printf(1 > 0); // expected-warning{{format string is not a string literal}} expected-warning{{incompatible integer to pointer conversion}} expected-note@format-strings.c:*{{passing argument to parameter here}} expected-note{{to avoid this}}
+}
diff --git a/test/Sema/generic-selection.c b/test/Sema/generic-selection.c
index 5c02005d0fa8..982995830573 100644
--- a/test/Sema/generic-selection.c
+++ b/test/Sema/generic-selection.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c1x -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c11 -fsyntax-only -verify %s
void g(void);
@@ -36,3 +36,11 @@ void foo(int n) {
// expression is not evaluated.
(void)_Generic(*(int *)0, int: 1);
}
+
+int __attribute__((overloadable)) test (int);
+double __attribute__((overloadable)) test (double);
+char testc(char);
+
+void PR30201(void) {
+ _Generic(4, char:testc, default:test)(4);
+}
diff --git a/test/Sema/implicit-intel-builtin-decl.c b/test/Sema/implicit-intel-builtin-decl.c
new file mode 100644
index 000000000000..e588a4b8866e
--- /dev/null
+++ b/test/Sema/implicit-intel-builtin-decl.c
@@ -0,0 +1,40 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-feature +sse2 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-feature +sse2 -fsyntax-only -verify %s -x c++
+
+void f() {
+ (void)_mm_getcsr(); // expected-warning{{implicitly declaring library function '_mm_getcsr'}} \
+ // expected-note{{include the header <xmmintrin.h> or explicitly provide a declaration for '_mm_getcsr'}}
+ _mm_setcsr(1); // expected-warning{{implicitly declaring library function '_mm_setcsr'}} \
+ // expected-note{{include the header <xmmintrin.h> or explicitly provide a declaration for '_mm_setcsr'}}
+ _mm_sfence(); // expected-warning{{implicitly declaring library function '_mm_sfence'}} \
+ // expected-note{{include the header <xmmintrin.h> or explicitly provide a declaration for '_mm_sfence'}}
+
+ _mm_clflush((void*)0); // expected-warning{{implicitly declaring library function '_mm_clflush'}} \
+ // expected-note{{include the header <emmintrin.h> or explicitly provide a declaration for '_mm_clflush'}}
+ _mm_lfence(); // expected-warning{{implicitly declaring library function '_mm_lfence'}} \
+ // expected-note{{include the header <emmintrin.h> or explicitly provide a declaration for '_mm_lfence'}}
+ _mm_mfence(); // expected-warning{{implicitly declaring library function '_mm_mfence'}} \
+ // expected-note{{include the header <emmintrin.h> or explicitly provide a declaration for '_mm_mfence'}}
+ _mm_pause(); // expected-warning{{implicitly declaring library function '_mm_pause'}} \
+ // expected-note{{include the header <emmintrin.h> or explicitly provide a declaration for '_mm_pause'}}
+}
+
+unsigned int _mm_getcsr();
+void _mm_setcsr(unsigned int);
+void _mm_sfence();
+
+void _mm_clflush(void const *);
+void _mm_lfence();
+void _mm_mfence();
+void _mm_pause();
+
+void g() {
+ (void)_mm_getcsr();
+ _mm_setcsr(1);
+ _mm_sfence();
+
+ _mm_clflush((void*)0);
+ _mm_lfence();
+ _mm_mfence();
+ _mm_pause();
+}
diff --git a/test/Sema/implicit-ms-builtin-decl.c b/test/Sema/implicit-ms-builtin-decl.c
new file mode 100644
index 000000000000..9a3e410c47d8
--- /dev/null
+++ b/test/Sema/implicit-ms-builtin-decl.c
@@ -0,0 +1,44 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify %s -fms-extensions
+// RUN: %clang_cc1 -triple i386-unknown-unknown -fsyntax-only -verify %s -fms-extensions
+
+void f() {
+ (void)_byteswap_ushort(42); // expected-warning{{implicitly declaring library function '_byteswap_ushort'}} \
+ // expected-note{{include the header <stdlib.h> or explicitly provide a declaration for '_byteswap_ushort'}}
+ (void)_byteswap_uint64(42LL); // expected-warning{{implicitly declaring library function '_byteswap_uint64'}} \
+ // expected-note{{include the header <stdlib.h> or explicitly provide a declaration for '_byteswap_uint64'}}
+}
+
+void _byteswap_ulong(); // expected-warning{{incompatible redeclaration of library function '_byteswap_ulong'}} \
+// expected-note{{'_byteswap_ulong' is a builtin}}
+
+unsigned short _byteswap_ushort(unsigned short);
+unsigned long long _byteswap_uint64(unsigned long long);
+
+void g() {
+ (void)_byteswap_ushort(42);
+ (void)_byteswap_uint64(42LL);
+}
+
+#if defined(__x86_64__)
+void h() {
+ (void)__mulh(21, 2); // expected-warning{{implicitly declaring library function '__mulh'}} \
+ // expected-note{{include the header <intrin.h> or explicitly provide a declaration for '__mulh'}}
+ (void)__umulh(21, 2); // expected-warning{{implicitly declaring library function '__umulh'}} \
+ // expected-note{{include the header <intrin.h> or explicitly provide a declaration for '__umulh'}}
+}
+
+long long __mulh(long long, long long);
+unsigned long long __umulh(unsigned long long, unsigned long long);
+
+void i() {
+ (void)__mulh(21, 2);
+ (void)__umulh(21, 2);
+}
+#endif
+
+#if defined(i386)
+void h() {
+ (void)__mulh(21LL, 2LL); // expected-warning{{implicit declaration of function '__mulh' is invalid}}
+ (void)__umulh(21ULL, 2ULL); // expected-warning{{implicit declaration of function '__umulh' is invalid}}
+}
+#endif
diff --git a/test/Sema/incompatible-function-pointer-types.c b/test/Sema/incompatible-function-pointer-types.c
new file mode 100644
index 000000000000..f0f594f8db84
--- /dev/null
+++ b/test/Sema/incompatible-function-pointer-types.c
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -fsyntax-only %s -Wincompatible-pointer-types -verify
+// RUN: %clang_cc1 -fsyntax-only %s -Wincompatible-function-pointer-types -verify
+
+// This test ensures that the subgroup of -Wincompatible-pointer-types warnings
+// that concern function pointers can be promoted (or not promoted) to an error
+// *separately* from the other -Wincompatible-pointer-type warnings.
+typedef int (*MyFnTyA)(int *, char *);
+
+int bar(char *a, int *b) { return 0; }
+int foo(MyFnTyA x) { return 0; } // expected-note {{passing argument to parameter 'x' here}}
+
+void baz() {
+ foo(&bar); // expected-warning {{incompatible function pointer types passing 'int (*)(char *, int *)' to parameter of type 'MyFnTyA' (aka 'int (*)(int *, char *)')}}
+}
diff --git a/test/Sema/initialize-noreturn.c b/test/Sema/initialize-noreturn.c
index 55578628716b..21ff29585ff9 100644
--- a/test/Sema/initialize-noreturn.c
+++ b/test/Sema/initialize-noreturn.c
@@ -4,13 +4,24 @@
typedef void (*Fn_noret)(void) __attribute__((noreturn));
typedef void (*Fn_ret)(void);
+typedef void (*Fn_noret_noproto)() __attribute__((noreturn));
+typedef void (*Fn_ret_noproto)();
+
void foo(void);
void foo_noret(void) __attribute__((noreturn));
+void foo_noproto();
+void foo_noret_noproto() __attribute__((noreturn));
+
void test() {
- Fn_noret fn2 = &foo; // expected-warning {{incompatible pointer types initializing 'Fn_noret'}}
+ Fn_noret fn2 = &foo; // expected-warning {{incompatible function pointer types initializing 'Fn_noret'}}
Fn_noret fn3 = &foo_noret;
Fn_ret fn4 = &foo_noret;
Fn_ret fn5 = &foo;
+
+ Fn_noret_noproto fn6 = &foo_noproto; // expected-warning {{incompatible function pointer types initializing 'Fn_noret_noproto'}}
+ Fn_noret_noproto fn7 = &foo_noret_noproto;
+ Fn_ret_noproto fn8 = &foo_noret_noproto;
+ Fn_ret_noproto fn9 = &foo_noproto;
}
diff --git a/test/Sema/no-warn-unused-const-variables.c b/test/Sema/no-warn-unused-const-variables.c
new file mode 100644
index 000000000000..73cfd8ea71b5
--- /dev/null
+++ b/test/Sema/no-warn-unused-const-variables.c
@@ -0,0 +1,4 @@
+// RUN: %clang_cc1 -fsyntax-only -Wunused-const-variable -x c-header -ffreestanding -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wunused-const-variable -x c++-header -ffreestanding -verify %s
+// expected-no-diagnostics
+static const int unused[] = { 2, 3, 5, 7, 11, 13 };
diff --git a/test/Sema/nullability.c b/test/Sema/nullability.c
index 71e12734d1d2..a0247e5af8b3 100644
--- a/test/Sema/nullability.c
+++ b/test/Sema/nullability.c
@@ -128,3 +128,122 @@ void nullable_to_nonnull(_Nullable int *ptr) {
accepts_nonnull_1(ptr); // expected-warning{{implicit conversion from nullable pointer 'int * _Nullable' to non-nullable pointer type 'int * _Nonnull'}}
}
+
+// Check nullability of conditional expressions.
+void conditional_expr(int c) {
+ int * _Nonnull p;
+ int * _Nonnull nonnullP;
+ int * _Nullable nullableP;
+ int * _Null_unspecified unspecifiedP;
+ int *noneP;
+
+ p = c ? nonnullP : nonnullP;
+ p = c ? nonnullP : nullableP; // expected-warning{{implicit conversion from nullable pointer 'int * _Nullable' to non-nullable pointer type 'int * _Nonnull'}}
+ p = c ? nonnullP : unspecifiedP;
+ p = c ? nonnullP : noneP;
+ p = c ? nullableP : nonnullP; // expected-warning{{implicit conversion from nullable pointer 'int * _Nullable' to non-nullable pointer type 'int * _Nonnull'}}
+ p = c ? nullableP : nullableP; // expected-warning{{implicit conversion from nullable pointer 'int * _Nullable' to non-nullable pointer type 'int * _Nonnull'}}
+ p = c ? nullableP : unspecifiedP; // expected-warning{{implicit conversion from nullable pointer 'int * _Nullable' to non-nullable pointer type 'int * _Nonnull'}}
+ p = c ? nullableP : noneP; // expected-warning{{implicit conversion from nullable pointer 'int * _Nullable' to non-nullable pointer type 'int * _Nonnull'}}
+ p = c ? unspecifiedP : nonnullP;
+ p = c ? unspecifiedP : nullableP; // expected-warning{{implicit conversion from nullable pointer 'int * _Nullable' to non-nullable pointer type 'int * _Nonnull'}}
+ p = c ? unspecifiedP : unspecifiedP;
+ p = c ? unspecifiedP : noneP;
+ p = c ? noneP : nonnullP;
+ p = c ? noneP : nullableP; // expected-warning{{implicit conversion from nullable pointer 'int * _Nullable' to non-nullable pointer type 'int * _Nonnull'}}
+ p = c ? noneP : unspecifiedP;
+ p = c ? noneP : noneP;
+
+ // Check that we don't remove all sugar when creating a new QualType for the
+ // conditional expression.
+ typedef int *IntP;
+ typedef IntP _Nonnull NonnullIntP0;
+ typedef NonnullIntP0 _Nonnull NonnullIntP1;
+ typedef IntP _Nullable NullableIntP0;
+ typedef NullableIntP0 _Nullable NullableIntP1;
+ NonnullIntP1 nonnullP2;
+ NullableIntP1 nullableP2;
+
+ p = c ? nonnullP2 : nonnullP2;
+ p = c ? nonnullP2 : nullableP2; // expected-warning{{implicit conversion from nullable pointer 'IntP _Nullable' (aka 'int *') to non-nullable pointer type 'int * _Nonnull'}}
+ p = c ? nullableP2 : nonnullP2; // expected-warning{{implicit conversion from nullable pointer 'NullableIntP1' (aka 'int *') to non-nullable pointer type 'int * _Nonnull'}}
+ p = c ? nullableP2 : nullableP2; // expected-warning{{implicit conversion from nullable pointer 'NullableIntP1' (aka 'int *') to non-nullable pointer type 'int * _Nonnull'}}
+}
+
+// Check nullability of binary conditional expressions.
+void binary_conditional_expr() {
+ int * _Nonnull p;
+ int * _Nonnull nonnullP;
+ int * _Nullable nullableP;
+ int * _Null_unspecified unspecifiedP;
+ int *noneP;
+
+ p = nonnullP ?: nonnullP;
+ p = nonnullP ?: nullableP;
+ p = nonnullP ?: unspecifiedP;
+ p = nonnullP ?: noneP;
+ p = nullableP ?: nonnullP;
+ p = nullableP ?: nullableP; // expected-warning{{implicit conversion from nullable pointer 'int * _Nullable' to non-nullable pointer type 'int * _Nonnull'}}
+ p = nullableP ?: unspecifiedP;
+ p = nullableP ?: noneP;
+ p = unspecifiedP ?: nonnullP;
+ p = unspecifiedP ?: nullableP; // expected-warning{{implicit conversion from nullable pointer 'int * _Nullable' to non-nullable pointer type 'int * _Nonnull'}}
+ p = unspecifiedP ?: unspecifiedP;
+ p = unspecifiedP ?: noneP;
+ p = noneP ?: nonnullP;
+ p = noneP ?: nullableP; // expected-warning{{implicit conversion from nullable pointer 'int * _Nullable' to non-nullable pointer type 'int * _Nonnull'}}
+ p = noneP ?: unspecifiedP;
+ p = noneP ?: noneP;
+}
+
+extern int GLOBAL_LENGTH;
+
+// Nullability can appear on arrays when the arrays are in parameter lists.
+void arrays(int ints[_Nonnull],
+ void *ptrs[_Nullable],
+ void **nestedPtrs[_Nullable],
+ void * _Null_unspecified * _Nonnull nestedPtrs2[_Nullable],
+ int fixedSize[_Nonnull 2],
+ int staticSize[_Nonnull static 2],
+ int staticSize2[static _Nonnull 2],
+ int starSize[_Nonnull *],
+ int vla[_Nonnull GLOBAL_LENGTH],
+ void ** _Nullable reference);
+void testDecayedType() {
+ int produceAnErrorMessage = arrays; // expected-warning {{incompatible pointer to integer conversion initializing 'int' with an expression of type 'void (int * _Nonnull, void ** _Nullable, void *** _Nullable, void * _Null_unspecified * _Nonnull * _Nullable, int * _Nonnull, int * _Nonnull, int * _Nonnull, int * _Nonnull, int * _Nonnull, void ** _Nullable)'}}
+}
+
+int notInFunction[_Nullable 3]; // expected-error {{nullability specifier '_Nullable' cannot be applied to non-pointer type 'int [3]'}}
+
+void nestedArrays(int x[5][_Nonnull 1]) {} // expected-error {{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'int [1]'}}
+void nestedArrays2(int x[5][_Nonnull 1][2]) {} // expected-error {{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'int [1][2]'}}
+void nestedArraysOK(int x[_Nonnull 5][1]) {} // ok
+
+void nullabilityOnBase(_Nonnull int x[1], // expected-error {{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'int'}}
+ int _Nonnull y[1]); // expected-error {{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'int'}}
+
+typedef int INTS[4];
+typedef int BAD_INTS[_Nonnull 4]; // expected-error {{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'int [4]'}}
+
+void typedefTest(INTS _Nonnull x,
+ _Nonnull INTS xx,
+ INTS _Nonnull y[2], // expected-error {{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'INTS' (aka 'int [4]')}}
+ INTS z[_Nonnull 2]);
+
+INTS _Nonnull x; // expected-error {{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'INTS' (aka 'int [4]')}}
+_Nonnull INTS x; // expected-error {{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'INTS' (aka 'int [4]')}}
+
+void arraysInBlocks() {
+ typedef int INTS[4];
+ void (^simple)(int [_Nonnull 2]) = ^(int x[_Nonnull 2]) {};
+ simple(0); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ void (^nested)(void *_Nullable x[_Nonnull 2]) = ^(void *_Nullable x[_Nonnull 2]) {};
+ nested(0); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ void (^nestedBad)(int x[2][_Nonnull 2]) = // expected-error {{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'int [2]'}}
+ ^(int x[2][_Nonnull 2]) {}; // expected-error {{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'int [2]'}}
+
+ void (^withTypedef)(INTS _Nonnull) = ^(INTS _Nonnull x) {};
+ withTypedef(0); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ void (^withTypedefBad)(INTS _Nonnull [2]) = // expected-error {{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'INTS' (aka 'int [4]')}}
+ ^(INTS _Nonnull x[2]) {}; // expected-error {{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'INTS' (aka 'int [4]')}}
+}
diff --git a/test/Sema/overloadable.c b/test/Sema/overloadable.c
index 5d95a317fa38..f5e17d211910 100644
--- a/test/Sema/overloadable.c
+++ b/test/Sema/overloadable.c
@@ -23,7 +23,7 @@ float *accept_funcptr(int (*)(int, double)) __attribute__((overloadable)); // \
void test_funcptr(int (*f1)(int, double),
int (*f2)(int, float)) {
float *fp = accept_funcptr(f1);
- accept_funcptr(f2); // expected-error{{no matching function for call to 'accept_funcptr'}}
+ accept_funcptr(f2); // expected-error{{call to 'accept_funcptr' is ambiguous}}
}
struct X { int x; float y; };
@@ -109,7 +109,7 @@ void fn_type_conversions() {
void (*ambiguous)(int *) = &foo; // expected-error{{initializing 'void (*)(int *)' with an expression of incompatible type '<overloaded function type>'}} expected-note@105{{candidate function}} expected-note@106{{candidate function}}
void *vp_ambiguous = &foo; // expected-error{{initializing 'void *' with an expression of incompatible type '<overloaded function type>'}} expected-note@105{{candidate function}} expected-note@106{{candidate function}}
- void (*specific1)(int *) = (void (*)(void *))&foo; // expected-warning{{incompatible pointer types initializing 'void (*)(int *)' with an expression of type 'void (*)(void *)'}}
+ void (*specific1)(int *) = (void (*)(void *))&foo; // expected-warning{{incompatible function pointer types initializing 'void (*)(int *)' with an expression of type 'void (*)(void *)'}}
void *specific2 = (void (*)(void *))&foo;
void disabled(void *c) __attribute__((overloadable, enable_if(0, "")));
@@ -122,3 +122,32 @@ void fn_type_conversions() {
void *specific_disabled = &disabled;
}
+
+void incompatible_pointer_type_conversions() {
+ char charbuf[1];
+ unsigned char ucharbuf[1];
+ int intbuf[1];
+
+ void foo(char *c) __attribute__((overloadable));
+ void foo(short *c) __attribute__((overloadable));
+ foo(charbuf);
+ foo(ucharbuf); // expected-error{{call to 'foo' is ambiguous}} expected-note@131{{candidate function}} expected-note@132{{candidate function}}
+ foo(intbuf); // expected-error{{call to 'foo' is ambiguous}} expected-note@131{{candidate function}} expected-note@132{{candidate function}}
+
+ void bar(unsigned char *c) __attribute__((overloadable));
+ void bar(signed char *c) __attribute__((overloadable));
+ bar(charbuf); // expected-error{{call to 'bar' is ambiguous}} expected-note@137{{candidate function}} expected-note@138{{candidate function}}
+ bar(ucharbuf);
+ bar(intbuf); // expected-error{{call to 'bar' is ambiguous}} expected-note@137{{candidate function}} expected-note@138{{candidate function}}
+}
+
+void dropping_qualifiers_is_incompatible() {
+ const char ccharbuf[1];
+ volatile char vcharbuf[1];
+
+ void foo(char *c) __attribute__((overloadable));
+ void foo(const volatile unsigned char *c) __attribute__((overloadable));
+
+ foo(ccharbuf); // expected-error{{call to 'foo' is ambiguous}} expected-note@148{{candidate function}} expected-note@149{{candidate function}}
+ foo(vcharbuf); // expected-error{{call to 'foo' is ambiguous}} expected-note@148{{candidate function}} expected-note@149{{candidate function}}
+}
diff --git a/test/Sema/pass-object-size.c b/test/Sema/pass-object-size.c
index ddfbbd5fc4e1..0745105df831 100644
--- a/test/Sema/pass-object-size.c
+++ b/test/Sema/pass-object-size.c
@@ -52,5 +52,5 @@ void FunctionPtrs() {
int P;
(&NotOverloaded)(&P); //expected-error{{cannot take address of function 'NotOverloaded' because parameter 1 has pass_object_size attribute}}
- (&IsOverloaded)(&P); //expected-error{{no matching function}} expected-note@35{{candidate address cannot be taken because parameter 1 has pass_object_size attribute}} expected-note@36{{candidate function not viable: no known conversion from 'int *' to 'char *' for 1st argument}}
+ (&IsOverloaded)(&P); //expected-warning{{incompatible pointer types passing 'int *' to parameter of type 'char *'}} expected-note@36{{passing argument to parameter 'p' here}}
}
diff --git a/test/Sema/pr30372.c b/test/Sema/pr30372.c
new file mode 100644
index 000000000000..e10fa2c84130
--- /dev/null
+++ b/test/Sema/pr30372.c
@@ -0,0 +1,12 @@
+// 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.
+
+void foo() {
+ __asm {
+ jl location
+ location:
+ ret
+ }
+}
diff --git a/test/Sema/shift.c b/test/Sema/shift.c
index 07c5fe5280ed..47744fb049fd 100644
--- a/test/Sema/shift.c
+++ b/test/Sema/shift.c
@@ -67,3 +67,14 @@ void test_shift_too_much(char x) {
(void) (x >> 80); // no-warning
(void) (x >> 80); // expected-warning {{shift count >= width of type}}
}
+
+typedef unsigned vec16 __attribute__((vector_size(16)));
+typedef unsigned vec8 __attribute__((vector_size(8)));
+
+void vect_shift_1(vec16 *x) { *x = *x << 4; }
+
+void vect_shift_2(vec16 *x, vec16 y) { *x = *x << y; }
+
+void vect_shift_3(vec16 *x, vec8 y) {
+ *x = *x << y; // expected-error {{vector operands do not have the same number of elements}}
+}
diff --git a/test/Sema/transparent-union.c b/test/Sema/transparent-union.c
index 8ef70bb1c7e3..a1a67dfd26fc 100644
--- a/test/Sema/transparent-union.c
+++ b/test/Sema/transparent-union.c
@@ -89,3 +89,12 @@ union pr15134v2 {
unsigned int u3;
} __attribute__((aligned(8)));
} __attribute__((transparent_union));
+
+union pr30520v { void b; } __attribute__((transparent_union)); // expected-error {{field has incomplete type 'void'}}
+
+union pr30520a { int b[]; } __attribute__((transparent_union)); // expected-error {{field has incomplete type 'int []'}}
+
+// expected-note@+1 2 {{forward declaration of 'struct stb'}}
+union pr30520s { struct stb b; } __attribute__((transparent_union)); // expected-error {{field has incomplete type 'struct stb'}}
+
+union pr30520s2 { int *v; struct stb b; } __attribute__((transparent_union)); // expected-error {{field has incomplete type 'struct stb'}}
diff --git a/test/Sema/varargs.c b/test/Sema/varargs.c
index 457d84c212f7..25a5c72c42e3 100644
--- a/test/Sema/varargs.c
+++ b/test/Sema/varargs.c
@@ -1,5 +1,6 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify %s -triple i386-pc-unknown
// RUN: %clang_cc1 -fsyntax-only -verify %s -triple x86_64-apple-darwin9
+// RUN: %clang_cc1 -fsyntax-only -fms-compatibility -DMS -verify %s -triple x86_64-pc-win32
void f1(int a)
{
@@ -94,3 +95,20 @@ void f12(register int i, ...) { // expected-note {{parameter of type 'int' is d
__builtin_va_start(ap, i); // expected-warning {{passing a parameter declared with the 'register' keyword to 'va_start' has undefined behavior}}
__builtin_va_end(ap);
}
+
+enum __attribute__((packed)) E1 {
+ one1
+};
+
+void f13(enum E1 e, ...) {
+ __builtin_va_list va;
+ __builtin_va_start(va, e);
+#ifndef MS
+ // In Microsoft compatibility mode, all enum types are int, but in
+ // non-ms-compatibility mode, this enumeration type will undergo default
+ // argument promotions.
+ // expected-note@-7 {{parameter of type 'enum E1' is declared here}}
+ // expected-warning@-6 {{passing an object that undergoes default argument promotion to 'va_start' has undefined behavior}}
+#endif
+ __builtin_va_end(va);
+}
diff --git a/test/Sema/vecshift.c b/test/Sema/vecshift.c
new file mode 100644
index 000000000000..7b6a30ad60dd
--- /dev/null
+++ b/test/Sema/vecshift.c
@@ -0,0 +1,99 @@
+// RUN: %clang_cc1 -fsyntax-only -DERR -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wno-error-vec-elem-size -verify %s
+// RUN: %clang_cc1 -fsyntax-only -DEXT -DERR -verify %s
+// RUN: %clang_cc1 -fsyntax-only -DEXT -Wno-error-vec-elem-size -verify %s
+
+#ifdef EXT
+typedef __attribute__((__ext_vector_type__(8))) char vector_char8;
+typedef __attribute__((__ext_vector_type__(8))) short vector_short8;
+typedef __attribute__((__ext_vector_type__(8))) int vector_int8;
+typedef __attribute__((__ext_vector_type__(8))) unsigned char vector_uchar8;
+typedef __attribute__((__ext_vector_type__(8))) unsigned short vector_ushort8;
+typedef __attribute__((__ext_vector_type__(8))) unsigned int vector_uint8;
+typedef __attribute__((__ext_vector_type__(4))) char vector_char4;
+typedef __attribute__((__ext_vector_type__(4))) short vector_short4;
+typedef __attribute__((__ext_vector_type__(4))) int vector_int4;
+typedef __attribute__((__ext_vector_type__(4))) unsigned char vector_uchar4;
+typedef __attribute__((__ext_vector_type__(4))) unsigned short vector_ushort4;
+typedef __attribute__((__ext_vector_type__(4))) unsigned int vector_uint4;
+#else
+typedef __attribute__((vector_size(8))) char vector_char8;
+typedef __attribute__((vector_size(16))) short vector_short8;
+typedef __attribute__((vector_size(32))) int vector_int8;
+typedef __attribute__((vector_size(8))) unsigned char vector_uchar8;
+typedef __attribute__((vector_size(16))) unsigned short vector_ushort8;
+typedef __attribute__((vector_size(32))) unsigned int vector_uint8;
+typedef __attribute__((vector_size(4))) char vector_char4;
+typedef __attribute__((vector_size(4))) short vector_short4;
+typedef __attribute__((vector_size(16))) int vector_int4;
+typedef __attribute__((vector_size(4))) unsigned char vector_uchar4;
+typedef __attribute__((vector_size(8))) unsigned short vector_ushort4;
+typedef __attribute__((vector_size(16))) unsigned int vector_uint4;
+#endif
+
+char c;
+short s;
+int i;
+unsigned char uc;
+unsigned short us;
+unsigned int ui;
+vector_char8 vc8;
+vector_short8 vs8;
+vector_int8 vi8;
+vector_uchar8 vuc8;
+vector_ushort8 vus8;
+vector_uint8 vui8;
+vector_char4 vc4;
+vector_short4 vs4;
+vector_int4 vi4;
+vector_uchar4 vuc4;
+vector_ushort4 vus4;
+vector_uint4 vui4;
+
+void foo() {
+ vc8 = 1 << vc8;
+ vuc8 = 1 << vuc8;
+ vi8 = 1 << vi8;
+ vui8 = 1 << vui8;
+ vs8 = 1 << vs8;
+ vus8 = 1 << vus8;
+
+ vc8 = c << vc8;
+ vuc8 = i << vuc8;
+ vi8 = uc << vi8;
+ vui8 = us << vui8;
+ vs8 = ui << vs8;
+ vus8 = 1 << vus8;
+
+ vc8 = vc8 << vc8;
+#ifdef ERR
+ vi8 = vi8 << vuc8; // expected-error {{vector operands do not have the same elements sizes}}
+ vuc8 = vuc8 << vi8; // expected-error {{vector operands do not have the same elements sizes}}
+ vus8 = vus8 << vui8; // expected-error {{vector operands do not have the same elements sizes}}
+ vui8 = vui8 << vs8; // expected-error {{vector operands do not have the same elements sizes}}
+#else
+ vi8 = vi8 << vuc8; // expected-warning {{vector operands do not have the same elements sizes}}
+ vuc8 = vuc8 << vi8; // expected-warning {{vector operands do not have the same elements sizes}}
+ vus8 = vus8 << vui8; // expected-warning {{vector operands do not have the same elements sizes}}
+ vui8 = vui8 << vs8; // expected-warning {{vector operands do not have the same elements sizes}}
+#endif
+
+ vc8 <<= vc8;
+#ifdef ERR
+ vi8 <<= vuc8; // expected-error {{vector operands do not have the same elements sizes}}
+ vuc8 <<= vi8; // expected-error {{vector operands do not have the same elements sizes}}
+ vus8 <<= vui8; // expected-error {{vector operands do not have the same elements sizes}}
+ vui8 <<= vs8; // expected-error {{vector operands do not have the same elements sizes}}
+#else
+ vi8 <<= vuc8; // expected-warning {{vector operands do not have the same elements sizes}}
+ vuc8 <<= vi8; // expected-warning {{vector operands do not have the same elements sizes}}
+ vus8 <<= vui8; // expected-warning {{vector operands do not have the same elements sizes}}
+ vui8 <<= vs8; // expected-warning {{vector operands do not have the same elements sizes}}
+#endif
+
+ c <<= vc8; // expected-error {{assigning to 'char' from incompatible type}}
+ i <<= vuc8; // expected-error {{assigning to 'int' from incompatible type}}
+ uc <<= vi8; // expected-error {{assigning to 'unsigned char' from incompatible type}}
+ us <<= vui8; // expected-error {{assigning to 'unsigned short' from incompatible type}}
+ ui <<= vs8; // expected-error {{assigning to 'unsigned int' from incompatible type}}
+}
diff --git a/test/Sema/vector-cast.c b/test/Sema/vector-cast.c
index c0382892b699..ea4acfac6a0b 100644
--- a/test/Sema/vector-cast.c
+++ b/test/Sema/vector-cast.c
@@ -53,14 +53,13 @@ void f4() {
float2 f2;
double d, a, b, c;
float64x2_t v = {0.0, 1.0};
- f2 += d;
+ // FIXME: These diagnostics are inaccurate: should complain that 'double' to vector 'float2' involves truncation
+ f2 += d; // expected-error {{cannot convert between vector values of different size ('float2' (vector of 2 'float' values) and 'double')}}
+ d += f2; // expected-error {{cannot convert between vector values of different size}}
a = 3.0 + vget_low_f64(v);
b = vget_low_f64(v) + 3.0;
c = vget_low_f64(v);
- // LAX conversions within compound assignments are not supported.
- // FIXME: This diagnostic is inaccurate.
- d += f2; // expected-error {{cannot convert between vector values of different size}}
- c -= vget_low_f64(v); // expected-error {{cannot convert between vector values of different size}}
+ c -= vget_low_f64(v);
// LAX conversions between scalar and vector types require same size and one element sized vectors.
d = f2; // expected-error {{assigning to 'double' from incompatible type 'float2'}}
d = d + f2; // expected-error {{assigning to 'double' from incompatible type 'float2'}}
diff --git a/test/Sema/vfprintf-invalid-redecl.c b/test/Sema/vfprintf-invalid-redecl.c
index cbf47a69a9a1..f06b1b6d2147 100644
--- a/test/Sema/vfprintf-invalid-redecl.c
+++ b/test/Sema/vfprintf-invalid-redecl.c
@@ -3,4 +3,4 @@
// The following declaration is not compatible with vfprintf(), but make
// sure this isn't an error: autoconf expects this to build.
-char vfprintf(); // expected-warning {{incompatible redeclaration of library function 'vfprintf'}} expected-note {{'vfprintf' is a builtin}}
+char vfprintf(); // expected-warning {{declaration of built-in function 'vfprintf'}}
diff --git a/test/Sema/vfprintf-valid-redecl.c b/test/Sema/vfprintf-valid-redecl.c
index 8ed18786ab7e..eb5c4d330718 100644
--- a/test/Sema/vfprintf-valid-redecl.c
+++ b/test/Sema/vfprintf-valid-redecl.c
@@ -1,16 +1,18 @@
// RUN: %clang_cc1 %s -fsyntax-only -pedantic -verify
// RUN: %clang_cc1 %s -fsyntax-only -pedantic -verify -DPREDECLARE
-// expected-no-diagnostics
#ifdef PREDECLARE
// PR16344
// Clang has defined 'vfprint' in builtin list. If the following line occurs before any other
// `vfprintf' in this file, and we getPreviousDecl()->getTypeSourceInfo() on it, then we will
// get a null pointer since the one in builtin list doesn't has valid TypeSourceInfo.
-int vfprintf(void) { return 0; }
+int vfprintf(void) { return 0; } // expected-warning {{requires inclusion of the header <stdio.h>}}
#endif
// PR4290
// The following declaration is compatible with vfprintf, so we shouldn't
-// warn.
+// reject.
int vfprintf();
+#ifndef PREDECLARE
+// expected-warning@-2 {{requires inclusion of the header <stdio.h>}}
+#endif
diff --git a/test/Sema/warn-cast-align.c b/test/Sema/warn-cast-align.c
index 9d64699bb5b4..e8f85bc14d8d 100644
--- a/test/Sema/warn-cast-align.c
+++ b/test/Sema/warn-cast-align.c
@@ -39,3 +39,23 @@ void test2(char *P) {
void test3(char *P) {
struct B *b = (struct B*) P;
}
+
+// Do not issue a warning. The aligned attribute changes the alignment of the
+// variables and fields.
+char __attribute__((aligned(4))) a[16];
+
+struct S0 {
+ char a[16];
+};
+
+struct S {
+ char __attribute__((aligned(4))) a[16];
+ struct S0 __attribute__((aligned(4))) s0;
+};
+
+void test4() {
+ struct S s;
+ int *i = (int *)s.a;
+ i = (int *)&s.s0;
+ i = (int *)a;
+}
diff --git a/test/Sema/warn-documentation-unknown-command.cpp b/test/Sema/warn-documentation-unknown-command.cpp
index 3674a9c68010..4328c9682f21 100644
--- a/test/Sema/warn-documentation-unknown-command.cpp
+++ b/test/Sema/warn-documentation-unknown-command.cpp
@@ -9,3 +9,7 @@ int test_unknown_comand_1;
/// \retur aaa
int test_unknown_comand_2();
+// RUN: c-index-test -test-load-source all -Wdocumentation-unknown-command %s > /dev/null 2> %t.err
+// RUN: FileCheck < %t.err -check-prefix=CHECK-RANGE %s
+// CHECK-RANGE: warn-documentation-unknown-command.cpp:5:9:{5:9-5:17}: warning: unknown command tag name
+// CHECK-RANGE: warn-documentation-unknown-command.cpp:9:5:{9:5-9:11}: warning: unknown command tag name 'retur'; did you mean 'return'?
diff --git a/test/Sema/warn-documentation.cpp b/test/Sema/warn-documentation.cpp
index 5d866359aa75..34d8f5fd2da2 100644
--- a/test/Sema/warn-documentation.cpp
+++ b/test/Sema/warn-documentation.cpp
@@ -368,6 +368,101 @@ typedef unsigned int test_not_function_like_typedef3;
/// \param aaa Meow.
typedef foo::not_a_function_wrapper<1> test_not_function_like_typedef4;
+// expected-warning@+2 {{parameter 'bbb' not found in the function declaration}} expected-note@+2 {{did you mean 'ccc'?}}
+/// \param aaa Meow.
+/// \param bbb Bbb.
+/// \returns aaa.
+using test_function_like_using1 = int (int aaa, int ccc);
+
+// expected-warning@+2 {{parameter 'bbb' not found in the function declaration}} expected-note@+2 {{did you mean 'ccc'?}}
+/// \param aaa Meow.
+/// \param bbb Bbb.
+/// \returns aaa.
+using test_function_like_using2 = int (*)(int aaa, int ccc);
+
+// expected-warning@+2 {{parameter 'bbb' not found in the function declaration}} expected-note@+2 {{did you mean 'ccc'?}}
+/// \param aaa Meow.
+/// \param bbb Bbb.
+/// \returns aaa.
+using test_function_like_using3 = int (* const)(int aaa, int ccc);
+
+// expected-warning@+2 {{parameter 'bbb' not found in the function declaration}} expected-note@+2 {{did you mean 'ccc'?}}
+/// \param aaa Meow.
+/// \param bbb Bbb.
+/// \returns aaa.
+using test_function_like_using4 = int (C::*)(int aaa, int ccc);
+
+// expected-warning@+2 {{parameter 'bbb' not found in the function declaration}} expected-note@+2 {{did you mean 'ccc'?}}
+/// \param aaa Meow.
+/// \param bbb Bbb.
+/// \returns aaa.
+using test_function_like_using5 = foo::function_wrapper<int (int aaa, int ccc)>;
+
+// expected-warning@+2 {{parameter 'bbb' not found in the function declaration}} expected-note@+2 {{did you mean 'ccc'?}}
+/// \param aaa Meow.
+/// \param bbb Bbb.
+/// \returns aaa.
+using test_function_like_using6 = foo::function_wrapper<int (int aaa, int ccc)> *;
+
+// expected-warning@+2 {{parameter 'bbb' not found in the function declaration}} expected-note@+2 {{did you mean 'ccc'?}}
+/// \param aaa Meow.
+/// \param bbb Bbb.
+/// \returns aaa.
+using test_function_like_using7 = foo::function_wrapper<int (int aaa, int ccc)> &;
+
+// expected-warning@+2 {{parameter 'bbb' not found in the function declaration}} expected-note@+2 {{did you mean 'ccc'?}}
+/// \param aaa Meow.
+/// \param bbb Bbb.
+/// \returns aaa.
+using test_function_like_using8 = foo::function_wrapper<int (int aaa, int ccc)> &&;
+
+// expected-warning@+4 {{template parameter 'U' not found in the template declaration}} expected-note@+4 {{did you mean 'T'?}}
+// expected-warning@+2 {{parameter 'bbb' not found in the function declaration}} expected-note@+2 {{did you mean 'ccc'?}}
+/// \param aaa Meow.
+/// \param bbb Bbb.
+/// \tparam U Uuu.
+template<typename T>
+using test_function_like_using9 = int(T aaa, int ccc);
+
+// expected-warning@+4 {{template parameter 'U' not found in the template declaration}} expected-note@+4 {{did you mean 'T'?}}
+// expected-warning@+2 {{parameter 'bbb' not found in the function declaration}} expected-note@+2 {{did you mean 'ccc'?}}
+/// \param aaa Meow.
+/// \param bbb Bbb.
+/// \tparam U Uuu.
+template<typename T>
+using test_function_like_using10 = int (*)(T aaa, int ccc);
+
+// expected-warning@+4 {{template parameter 'U' not found in the template declaration}} expected-note@+4 {{did you mean 'T'?}}
+// expected-warning@+2 {{parameter 'bbb' not found in the function declaration}} expected-note@+2 {{did you mean 'ccc'?}}
+/// \param aaa Meow.
+/// \param bbb Bbb.
+/// \tparam U Uuu.
+template<typename T>
+using test_function_like_using11 = foo::function_wrapper<int (T aaa, int ccc)>;
+
+// expected-warning@+4 {{template parameter 'U' not found in the template declaration}} expected-note@+4 {{did you mean 'T'?}}
+// expected-warning@+2 {{parameter 'bbb' not found in the function declaration}} expected-note@+2 {{did you mean 'ccc'?}}
+/// \param aaa Meow.
+/// \param bbb Bbb.
+/// \tparam U Uuu.
+template<typename T>
+using test_function_like_using12 = foo::function_wrapper<int (T aaa, int ccc)> *;
+
+using test_not_function_like_using1 = int (*)(int aaa);
+
+// expected-warning@+1 {{'\param' command used in a comment that is not attached to a function declaration}}
+/// \param aaa Meow.
+using test_not_function_like_using2 = test_not_function_like_using1;
+
+// Check that the diagnostic uses the same command marker as the comment.
+// expected-warning@+1 {{'@param' command used in a comment that is not attached to a function declaration}}
+/// @param aaa Meow.
+using test_not_function_like_using3 = unsigned int;
+
+// expected-warning@+1 {{'\param' command used in a comment that is not attached to a function declaration}}
+/// \param aaa Meow.
+using test_not_function_like_using4 = foo::not_a_function_wrapper<1>;
+
/// \param aaa Aaa
/// \param ... Vararg
int test_vararg_param1(int aaa, ...);
diff --git a/test/Sema/warn-main-returns-bool-literal.cpp b/test/Sema/warn-main-returns-bool-literal.cpp
new file mode 100644
index 000000000000..188f161dd324
--- /dev/null
+++ b/test/Sema/warn-main-returns-bool-literal.cpp
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -Wmain -verify %s
+
+// expected-note@+1 {{previous definition is here}}
+int main() {
+ return 0;
+} // no-warning
+
+// expected-error@+1 {{redefinition of 'main'}}
+int main() {
+ return 1.0;
+} // no-warning
+
+int main() {
+ bool b = true;
+ return b; // no-warning
+}
+
+int main() {
+ return true; // expected-warning {{bool literal returned from 'main'}}
+}
diff --git a/test/Sema/warn-strict-prototypes.c b/test/Sema/warn-strict-prototypes.c
new file mode 100644
index 000000000000..496579c1f60e
--- /dev/null
+++ b/test/Sema/warn-strict-prototypes.c
@@ -0,0 +1,62 @@
+// RUN: %clang_cc1 -fsyntax-only -Wstrict-prototypes -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wstrict-prototypes -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
+
+// function declaration with unspecified params
+void foo1(); // expected-warning {{this function declaration is not a prototype}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:11}:"void"
+// function declaration with 0 params
+void foo2(void);
+
+// function definition with 0 params(for both cases),
+// valid according to 6.7.5.3/14
+void foo1() {}
+void foo2(void) {}
+
+// function type typedef unspecified params
+typedef void foo3(); // expected-warning {{this function declaration is not a prototype}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:19-[[@LINE-1]]:19}:"void"
+
+// global fp unspecified params
+void (*foo4)(); // expected-warning {{this function declaration is not a prototype}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:14-[[@LINE-1]]:14}:"void"
+
+// struct member fp unspecified params
+struct { void (*foo5)(); } s; // expected-warning {{this function declaration is not a prototype}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:23-[[@LINE-1]]:23}:"void"
+
+// param fp unspecified params
+void bar2(void (*foo6)()) { // expected-warning {{this function declaration is not a prototype}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:24-[[@LINE-1]]:24}:"void"
+ // local fp unspecified params
+ void (*foo7)() = 0; // expected-warning {{this function declaration is not a prototype}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:16-[[@LINE-1]]:16}:"void"
+ // array fp unspecified params
+ void (*foo8[2])() = {0}; // expected-warning {{this function declaration is not a prototype}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:19-[[@LINE-1]]:19}:"void"
+}
+
+// function type cast using using an anonymous function declaration
+void bar3(void) {
+ // casting function w/out prototype to unspecified params function type
+ (void)(void(*)()) foo1; // expected-warning {{this function declaration is not a prototype}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:18-[[@LINE-1]]:18}:"void"
+ // .. specified params
+ (void)(void(*)(void)) foo1;
+}
+
+// K&R function definition not preceded by full prototype
+int foo9(a, b) // expected-warning {{old-style function definition is not preceded by a prototype}}
+ int a, b;
+{
+ return a + b;
+}
+
+// Function declaration with no types
+void foo10(); // expected-warning {{this function declaration is not a prototype}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:12-[[@LINE-1]]:12}:"void"
+// K&R function definition with incomplete param list declared
+void foo10(p, p2) void *p; {} // expected-warning {{old-style function definition is not preceded by a prototype}}
+
+// K&R function definition with previous prototype declared is not diagnosed.
+void foo11(int p, int p2);
+void foo11(p, p2) int p; int p2; {}
diff --git a/test/Sema/warn-strict-prototypes.m b/test/Sema/warn-strict-prototypes.m
new file mode 100644
index 000000000000..cbb01a1f7b21
--- /dev/null
+++ b/test/Sema/warn-strict-prototypes.m
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -fsyntax-only -Wstrict-prototypes -verify -fblocks %s
+
+@interface Foo
+
+@property (nonatomic, copy) void (^noProtoBlock)(); // expected-warning {{this function declaration is not a prototype}}
+@property (nonatomic, copy) void (^block)(void); // no warning
+
+- doStuff:(void (^)()) completionHandler; // expected-warning {{this function declaration is not a prototype}}
+- doOtherStuff:(void (^)(void)) completionHandler; // no warning
+
+@end
+
+void foo() {
+ void (^block)() = // expected-warning {{this function declaration is not a prototype}}
+ ^void(int arg) { // no warning
+ };
+ void (^block2)(void) = // no warning
+ ^void() { // expected-warning {{this function declaration is not a prototype}}
+ };
+}
diff --git a/test/SemaCUDA/Inputs/cuda.h b/test/SemaCUDA/Inputs/cuda.h
index 18cafdf96af8..4544369411f3 100644
--- a/test/SemaCUDA/Inputs/cuda.h
+++ b/test/SemaCUDA/Inputs/cuda.h
@@ -21,4 +21,11 @@ typedef struct cudaStream *cudaStream_t;
int cudaConfigureCall(dim3 gridSize, dim3 blockSize, size_t sharedSize = 0,
cudaStream_t stream = 0);
+
+// Host- and device-side placement new overloads.
+void *operator new(__SIZE_TYPE__, void *p) { return p; }
+void *operator new[](__SIZE_TYPE__, void *p) { return p; }
+__device__ void *operator new(__SIZE_TYPE__, void *p) { return p; }
+__device__ void *operator new[](__SIZE_TYPE__, void *p) { return p; }
+
#endif // !__NVCC__
diff --git a/test/SemaCUDA/add-inline-in-definition.cu b/test/SemaCUDA/add-inline-in-definition.cu
new file mode 100644
index 000000000000..33176c580d45
--- /dev/null
+++ b/test/SemaCUDA/add-inline-in-definition.cu
@@ -0,0 +1,52 @@
+// RUN: %clang_cc1 -std=c++11 -fcuda-is-device -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+
+#include "Inputs/cuda.h"
+
+#ifndef __CUDA_ARCH__
+// expected-no-diagnostics
+#endif
+
+// When compiling for device, foo()'s call to host_fn() is an error, because
+// foo() is known-emitted.
+//
+// The trickiness here comes from the fact that the FunctionDecl bar() sees
+// foo() does not have the "inline" keyword, so we might incorrectly think that
+// foo() is a priori known-emitted. This would prevent us from marking foo()
+// as known-emitted when we see the call from bar() to foo(), which would
+// prevent us from emitting an error for foo()'s call to host_fn() when we
+// eventually see it.
+
+void host_fn() {}
+#ifdef __CUDA_ARCH__
+ // expected-note@-2 {{declared here}}
+#endif
+
+__host__ __device__ void foo();
+__device__ void bar() {
+ foo();
+#ifdef __CUDA_ARCH__
+ // expected-note@-2 {{called by 'bar'}}
+#endif
+}
+inline __host__ __device__ void foo() {
+ host_fn();
+#ifdef __CUDA_ARCH__
+ // expected-error@-2 {{reference to __host__ function}}
+#endif
+}
+
+// This is similar to the above, except there's no error here. This code used
+// to trip an assertion due to us noticing, when emitting the definition of
+// boom(), that T::operator S() was (incorrectly) considered a priori
+// known-emitted.
+struct S {};
+struct T {
+ __device__ operator S() const;
+};
+__device__ inline T::operator S() const { return S(); }
+
+__device__ T t;
+__device__ void boom() {
+ S s = t;
+}
diff --git a/test/SemaCUDA/amdgpu-attrs.cu b/test/SemaCUDA/amdgpu-attrs.cu
new file mode 100644
index 000000000000..87559726869b
--- /dev/null
+++ b/test/SemaCUDA/amdgpu-attrs.cu
@@ -0,0 +1,110 @@
+// 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() {}
diff --git a/test/SemaCUDA/amdgpu-num-gpr-attr.cu b/test/SemaCUDA/amdgpu-num-gpr-attr.cu
deleted file mode 100644
index 83acbc5007ec..000000000000
--- a/test/SemaCUDA/amdgpu-num-gpr-attr.cu
+++ /dev/null
@@ -1,14 +0,0 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
-
-#include "Inputs/cuda.h"
-
-__attribute__((amdgpu_num_vgpr(64)))
-__global__ void test_num_vgpr() { } // expected-error {{'amdgpu_num_vgpr' attribute only applies to kernel functions}}
-
-__attribute__((amdgpu_num_sgpr(32)))
-__global__ void test_num_sgpr() { } // expected-error {{'amdgpu_num_sgpr' attribute only applies to kernel functions}}
-
-// fixme-expected-error@+3 {{'amdgpu_num_sgpr' attribute only applies to kernel functions}}
-// expected-error@+2 {{'amdgpu_num_vgpr' attribute only applies to kernel functions}}
-__attribute__((amdgpu_num_sgpr(32), amdgpu_num_vgpr(64)))
-__global__ void test_num_vgpr_num_sgpr() { }
diff --git a/test/SemaCUDA/bad-attributes.cu b/test/SemaCUDA/bad-attributes.cu
index 4cb43e240b04..5aaff9759673 100644
--- a/test/SemaCUDA/bad-attributes.cu
+++ b/test/SemaCUDA/bad-attributes.cu
@@ -42,6 +42,8 @@ __constant__ __shared__ int z8; // expected-error {{attributes are not compatib
__shared__ __device__ int z9;
__shared__ __constant__ int z10; // expected-error {{attributes are not compatible}}
// expected-note@-1 {{conflicting attribute is here}}
+__constant__ __shared__ int z10a; // expected-error {{attributes are not compatible}}
+// expected-note@-1 {{conflicting attribute is here}}
__global__ __device__ void z11(); // expected-error {{attributes are not compatible}}
// expected-note@-1 {{conflicting attribute is here}}
@@ -59,3 +61,12 @@ __global__ static inline void foobar() {};
#ifdef EXPECT_INLINE_WARNING
// expected-warning@-2 {{ignored 'inline' attribute on kernel function 'foobar'}}
#endif
+
+__constant__ int global_constant;
+void host_fn() {
+ __constant__ int c; // expected-error {{__constant__ variables must be global}}
+ __shared__ int s; // expected-error {{__shared__ local variables not allowed in __host__ functions}}
+}
+__device__ void device_fn() {
+ __constant__ int c; // expected-error {{__constant__ variables must be global}}
+}
diff --git a/test/SemaCUDA/bad-calls-on-same-line.cu b/test/SemaCUDA/bad-calls-on-same-line.cu
new file mode 100644
index 000000000000..67923323a94f
--- /dev/null
+++ b/test/SemaCUDA/bad-calls-on-same-line.cu
@@ -0,0 +1,40 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// The hd function template is instantiated three times.
+//
+// Two of those instantiations call a device function, which is an error when
+// compiling for host. Clang should report both errors.
+
+#include "Inputs/cuda.h"
+
+template <typename T>
+struct Selector {};
+
+template <>
+struct Selector<int> {
+ __host__ void f() {}
+};
+
+template <>
+struct Selector<float> {
+ __device__ void f() {} // expected-note {{declared here}}
+};
+
+template <>
+struct Selector<double> {
+ __device__ void f() {} // expected-note {{declared here}}
+};
+
+template <typename T>
+inline __host__ __device__ void hd() {
+ Selector<T>().f();
+ // expected-error@-1 2 {{reference to __device__ function}}
+}
+
+void host_fn() {
+ hd<int>();
+ hd<double>(); // expected-note {{function template specialization 'hd<double>'}}
+ // expected-note@-1 {{called by 'host_fn'}}
+ hd<float>(); // expected-note {{function template specialization 'hd<float>'}}
+ // expected-note@-1 {{called by 'host_fn'}}
+}
diff --git a/test/SemaCUDA/call-device-fn-from-host.cu b/test/SemaCUDA/call-device-fn-from-host.cu
new file mode 100644
index 000000000000..3ea013f3a742
--- /dev/null
+++ b/test/SemaCUDA/call-device-fn-from-host.cu
@@ -0,0 +1,85 @@
+// RUN: %clang_cc1 %s --std=c++11 -triple x86_64-unknown-linux -emit-llvm -o - \
+// RUN: -verify -verify-ignore-unexpected=note
+
+// Note: This test won't work with -fsyntax-only, because some of these errors
+// are emitted during codegen.
+
+#include "Inputs/cuda.h"
+
+__device__ void device_fn() {}
+// expected-note@-1 5 {{'device_fn' declared here}}
+
+struct S {
+ __device__ S() {}
+ // expected-note@-1 2 {{'S' declared here}}
+ __device__ ~S() { device_fn(); }
+ // expected-note@-1 {{'~S' declared here}}
+ int x;
+};
+
+struct T {
+ __host__ __device__ void hd() { device_fn(); }
+ // expected-error@-1 {{reference to __device__ function 'device_fn' in __host__ __device__ function}}
+
+ // No error; this is (implicitly) inline and is never called, so isn't
+ // codegen'ed.
+ __host__ __device__ void hd2() { device_fn(); }
+
+ __host__ __device__ void hd3();
+
+ __device__ void d() {}
+ // expected-note@-1 {{'d' declared here}}
+};
+
+__host__ __device__ void T::hd3() {
+ device_fn();
+ // expected-error@-1 {{reference to __device__ function 'device_fn' in __host__ __device__ function}}
+}
+
+template <typename T> __host__ __device__ void hd2() { device_fn(); }
+// expected-error@-1 {{reference to __device__ function 'device_fn' in __host__ __device__ function}}
+void host_fn() { hd2<int>(); }
+
+__host__ __device__ void hd() { device_fn(); }
+// expected-error@-1 {{reference to __device__ function 'device_fn' in __host__ __device__ function}}
+
+// No error because this is never instantiated.
+template <typename T> __host__ __device__ void hd3() { device_fn(); }
+
+__host__ __device__ void local_var() {
+ S s;
+ // expected-error@-1 {{reference to __device__ function 'S' in __host__ __device__ function}}
+}
+
+__host__ __device__ void placement_new(char *ptr) {
+ ::new(ptr) S();
+ // expected-error@-1 {{reference to __device__ function 'S' in __host__ __device__ function}}
+}
+
+__host__ __device__ void explicit_destructor(S *s) {
+ s->~S();
+ // expected-error@-1 {{reference to __device__ function '~S' in __host__ __device__ function}}
+}
+
+__host__ __device__ void hd_member_fn() {
+ T t;
+ // Necessary to trigger an error on T::hd. It's (implicitly) inline, so
+ // isn't codegen'ed until we call it.
+ t.hd();
+}
+
+__host__ __device__ void h_member_fn() {
+ T t;
+ t.d();
+ // expected-error@-1 {{reference to __device__ function 'd' in __host__ __device__ function}}
+}
+
+__host__ __device__ void fn_ptr() {
+ auto* ptr = &device_fn;
+ // expected-error@-1 {{reference to __device__ function 'device_fn' in __host__ __device__ function}}
+}
+
+template <typename T>
+__host__ __device__ void fn_ptr_template() {
+ auto* ptr = &device_fn; // Not an error because the template isn't instantiated.
+}
diff --git a/test/SemaCUDA/call-host-fn-from-device.cu b/test/SemaCUDA/call-host-fn-from-device.cu
new file mode 100644
index 000000000000..c727dc8cbeb7
--- /dev/null
+++ b/test/SemaCUDA/call-host-fn-from-device.cu
@@ -0,0 +1,140 @@
+// RUN: %clang_cc1 %s --std=c++11 -triple nvptx-unknown-unknown -fcuda-is-device \
+// RUN: -emit-llvm -o /dev/null -verify -verify-ignore-unexpected=note
+
+// Note: This test won't work with -fsyntax-only, because some of these errors
+// are emitted during codegen.
+
+#include "Inputs/cuda.h"
+
+extern "C" void host_fn() {}
+// expected-note@-1 7 {{'host_fn' declared here}}
+
+struct Dummy {};
+
+struct S {
+ S() {}
+ // expected-note@-1 2 {{'S' declared here}}
+ ~S() { host_fn(); }
+ // expected-note@-1 {{'~S' declared here}}
+ int x;
+};
+
+struct T {
+ __host__ __device__ void hd() { host_fn(); }
+ // expected-error@-1 {{reference to __host__ function 'host_fn' in __host__ __device__ function}}
+
+ // No error; this is (implicitly) inline and is never called, so isn't
+ // codegen'ed.
+ __host__ __device__ void hd2() { host_fn(); }
+
+ __host__ __device__ void hd3();
+
+ void h() {}
+ // expected-note@-1 {{'h' declared here}}
+
+ void operator+();
+ // expected-note@-1 {{'operator+' declared here}}
+
+ void operator-(const T&) {}
+ // expected-note@-1 {{'operator-' declared here}}
+
+ operator Dummy() { return Dummy(); }
+ // expected-note@-1 {{'operator Dummy' declared here}}
+
+ __host__ void operator delete(void*);
+ __device__ void operator delete(void*, size_t);
+};
+
+struct U {
+ __device__ void operator delete(void*, size_t) = delete;
+ __host__ __device__ void operator delete(void*);
+};
+
+__host__ __device__ void T::hd3() {
+ host_fn();
+ // expected-error@-1 {{reference to __host__ function 'host_fn' in __host__ __device__ function}}
+}
+
+template <typename T> __host__ __device__ void hd2() { host_fn(); }
+// expected-error@-1 {{reference to __host__ function 'host_fn' in __host__ __device__ function}}
+__global__ void kernel() { hd2<int>(); }
+
+__host__ __device__ void hd() { host_fn(); }
+// expected-error@-1 {{reference to __host__ function 'host_fn' in __host__ __device__ function}}
+
+template <typename T> __host__ __device__ void hd3() { host_fn(); }
+// expected-error@-1 {{reference to __host__ function 'host_fn' in __host__ __device__ function}}
+__device__ void device_fn() { hd3<int>(); }
+
+// No error because this is never instantiated.
+template <typename T> __host__ __device__ void hd4() { host_fn(); }
+
+__host__ __device__ void local_var() {
+ S s;
+ // expected-error@-1 {{reference to __host__ function 'S' in __host__ __device__ function}}
+}
+
+__host__ __device__ void placement_new(char *ptr) {
+ ::new(ptr) S();
+ // expected-error@-1 {{reference to __host__ function 'S' in __host__ __device__ function}}
+}
+
+__host__ __device__ void explicit_destructor(S *s) {
+ s->~S();
+ // expected-error@-1 {{reference to __host__ function '~S' in __host__ __device__ function}}
+}
+
+__host__ __device__ void class_specific_delete(T *t, U *u) {
+ delete t; // ok, call sized device delete even though host has preferable non-sized version
+ delete u; // ok, call non-sized HD delete rather than sized D delete
+}
+
+__host__ __device__ void hd_member_fn() {
+ T t;
+ // Necessary to trigger an error on T::hd. It's (implicitly) inline, so
+ // isn't codegen'ed until we call it.
+ t.hd();
+}
+
+__host__ __device__ void h_member_fn() {
+ T t;
+ t.h();
+ // expected-error@-1 {{reference to __host__ function 'h' in __host__ __device__ function}}
+}
+
+__host__ __device__ void fn_ptr() {
+ auto* ptr = &host_fn;
+ // expected-error@-1 {{reference to __host__ function 'host_fn' in __host__ __device__ function}}
+}
+
+template <typename T>
+__host__ __device__ void fn_ptr_template() {
+ auto* ptr = &host_fn; // Not an error because the template isn't instantiated.
+}
+
+__host__ __device__ void unaryOp() {
+ T t;
+ (void) +t; // expected-error {{reference to __host__ function 'operator+' in __host__ __device__ function}}
+}
+
+__host__ __device__ void binaryOp() {
+ T t;
+ (void) (t - t); // expected-error {{reference to __host__ function 'operator-' in __host__ __device__ function}}
+}
+
+__host__ __device__ void implicitConversion() {
+ T t;
+ Dummy d = t; // expected-error {{reference to __host__ function 'operator Dummy' in __host__ __device__ function}}
+}
+
+template <typename T>
+struct TmplStruct {
+ template <typename U> __host__ __device__ void fn() {}
+};
+
+template <>
+template <>
+__host__ __device__ void TmplStruct<int>::fn<int>() { host_fn(); }
+// expected-error@-1 {{reference to __host__ function 'host_fn' in __host__ __device__ function}}
+
+__device__ void double_specialization() { TmplStruct<int>().fn<int>(); }
diff --git a/test/SemaCUDA/call-overloaded-destructor.cu b/test/SemaCUDA/call-overloaded-destructor.cu
deleted file mode 100644
index 24b0e7d330ea..000000000000
--- a/test/SemaCUDA/call-overloaded-destructor.cu
+++ /dev/null
@@ -1,17 +0,0 @@
-// expected-no-diagnostics
-
-// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fsyntax-only -verify %s
-// RUN: %clang_cc1 -triple nvptx64-nvidia-cuda -fsyntax-only -fcuda-is-device -verify %s
-
-#include "Inputs/cuda.h"
-
-struct S {
- __host__ ~S() {}
- __device__ ~S() {}
-};
-
-__host__ __device__ void test() {
- S s;
- // This should not crash clang.
- s.~S();
-}
diff --git a/test/SemaCUDA/call-stack-for-deferred-err.cu b/test/SemaCUDA/call-stack-for-deferred-err.cu
new file mode 100644
index 000000000000..ddcaabf4ef53
--- /dev/null
+++ b/test/SemaCUDA/call-stack-for-deferred-err.cu
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -fcuda-is-device -fsyntax-only -verify %s
+
+#include "Inputs/cuda.h"
+
+// We should emit an error for hd_fn's use of a VLA. This would have been
+// legal if hd_fn were never codegen'ed on the device, so we should also print
+// out a callstack showing how we determine that hd_fn is known-emitted.
+//
+// Compare to no-call-stack-for-deferred-err.cu.
+
+inline __host__ __device__ void hd_fn(int n);
+inline __device__ void device_fn2() { hd_fn(42); } // expected-note {{called by 'device_fn2'}}
+
+__global__ void kernel() { device_fn2(); } // expected-note {{called by 'kernel'}}
+
+inline __host__ __device__ void hd_fn(int n) {
+ int vla[n]; // expected-error {{variable-length array}}
+}
diff --git a/test/SemaCUDA/cuda-builtin-vars.cu b/test/SemaCUDA/cuda-builtin-vars.cu
index 108e75cae766..27a9c5abd700 100644
--- a/test/SemaCUDA/cuda-builtin-vars.cu
+++ b/test/SemaCUDA/cuda-builtin-vars.cu
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 "-triple" "nvptx-nvidia-cuda" -fcuda-is-device -fsyntax-only -verify %s
-#include "cuda_builtin_vars.h"
+#include "__clang_cuda_builtin_vars.h"
__attribute__((global))
void kernel(int *out) {
int i = 0;
@@ -34,20 +34,20 @@ void kernel(int *out) {
out[i++] = warpSize;
warpSize = 0; // expected-error {{cannot assign to variable 'warpSize' with const-qualified type 'const int'}}
- // expected-note@cuda_builtin_vars.h:* {{variable 'warpSize' declared const here}}
+ // expected-note@__clang_cuda_builtin_vars.h:* {{variable 'warpSize' declared const here}}
// Make sure we can't construct or assign to the special variables.
__cuda_builtin_threadIdx_t x; // expected-error {{calling a private constructor of class '__cuda_builtin_threadIdx_t'}}
- // expected-note@cuda_builtin_vars.h:* {{declared private here}}
+ // expected-note@__clang_cuda_builtin_vars.h:* {{declared private here}}
__cuda_builtin_threadIdx_t y = threadIdx; // expected-error {{calling a private constructor of class '__cuda_builtin_threadIdx_t'}}
- // expected-note@cuda_builtin_vars.h:* {{declared private here}}
+ // expected-note@__clang_cuda_builtin_vars.h:* {{declared private here}}
threadIdx = threadIdx; // expected-error {{'operator=' is a private member of '__cuda_builtin_threadIdx_t'}}
- // expected-note@cuda_builtin_vars.h:* {{declared private here}}
+ // expected-note@__clang_cuda_builtin_vars.h:* {{declared private here}}
void *ptr = &threadIdx; // expected-error {{'operator&' is a private member of '__cuda_builtin_threadIdx_t'}}
- // expected-note@cuda_builtin_vars.h:* {{declared private here}}
+ // expected-note@__clang_cuda_builtin_vars.h:* {{declared private here}}
// Following line should've caused an error as one is not allowed to
// take address of a built-in variable in CUDA. Alas there's no way
diff --git a/test/SemaCUDA/device-var-init.cu b/test/SemaCUDA/device-var-init.cu
index d807a51b6535..71f2352843b2 100644
--- a/test/SemaCUDA/device-var-init.cu
+++ b/test/SemaCUDA/device-var-init.cu
@@ -207,9 +207,21 @@ __device__ void df_sema() {
// expected-error@-1 {{initialization is not supported for __shared__ variables.}}
static __device__ int ds;
- // expected-error@-1 {{Within a __device__/__global__ function, only __shared__ variables may be marked "static"}}
+ // expected-error@-1 {{within a __device__ function, only __shared__ variables may be marked 'static'}}
static __constant__ int dc;
- // expected-error@-1 {{Within a __device__/__global__ function, only __shared__ variables may be marked "static"}}
+ // expected-error@-1 {{within a __device__ function, only __shared__ variables may be marked 'static'}}
static int v;
- // expected-error@-1 {{Within a __device__/__global__ function, only __shared__ variables may be marked "static"}}
+ // expected-error@-1 {{within a __device__ function, only __shared__ variables may be marked 'static'}}
}
+
+__host__ __device__ void hd_sema() {
+ static int x = 42;
+#ifdef __CUDA_ARCH__
+ // expected-error@-2 {{within a __host__ __device__ function, only __shared__ variables may be marked 'static'}}
+#endif
+}
+
+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(); }
diff --git a/test/SemaCUDA/exceptions.cu b/test/SemaCUDA/exceptions.cu
new file mode 100644
index 000000000000..49568ecac7eb
--- /dev/null
+++ b/test/SemaCUDA/exceptions.cu
@@ -0,0 +1,55 @@
+// RUN: %clang_cc1 -fcxx-exceptions -fcuda-is-device -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fcxx-exceptions -fsyntax-only -verify %s
+
+#include "Inputs/cuda.h"
+
+void host() {
+ throw NULL;
+ try {} catch(void*) {}
+}
+__device__ void device() {
+ throw NULL;
+ // expected-error@-1 {{cannot use 'throw' in __device__ function}}
+ try {} catch(void*) {}
+ // expected-error@-1 {{cannot use 'try' in __device__ function}}
+}
+__global__ void kernel() {
+ throw NULL;
+ // expected-error@-1 {{cannot use 'throw' in __global__ function}}
+ try {} catch(void*) {}
+ // expected-error@-1 {{cannot use 'try' in __global__ function}}
+}
+
+// Check that it's an error to use 'try' and 'throw' from a __host__ __device__
+// function if and only if it's codegen'ed for device.
+
+__host__ __device__ void hd1() {
+ throw NULL;
+ try {} catch(void*) {}
+#ifdef __CUDA_ARCH__
+ // expected-error@-3 {{cannot use 'throw' in __host__ __device__ function}}
+ // expected-error@-3 {{cannot use 'try' in __host__ __device__ function}}
+#endif
+}
+
+// No error, never instantiated on device.
+inline __host__ __device__ void hd2() {
+ throw NULL;
+ try {} catch(void*) {}
+}
+void call_hd2() { hd2(); }
+
+// Error, instantiated on device.
+inline __host__ __device__ void hd3() {
+ throw NULL;
+ try {} catch(void*) {}
+#ifdef __CUDA_ARCH__
+ // expected-error@-3 {{cannot use 'throw' in __host__ __device__ function}}
+ // expected-error@-3 {{cannot use 'try' in __host__ __device__ function}}
+#endif
+}
+
+__device__ void call_hd3() { hd3(); }
+#ifdef __CUDA_ARCH__
+// expected-note@-2 {{called by 'call_hd3'}}
+#endif
diff --git a/test/SemaCUDA/extern-shared.cu b/test/SemaCUDA/extern-shared.cu
new file mode 100644
index 000000000000..9fd7bbba593c
--- /dev/null
+++ b/test/SemaCUDA/extern-shared.cu
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fcuda-is-device -verify %s
+
+#include "Inputs/cuda.h"
+
+__device__ void foo() {
+ extern __shared__ int x; // expected-error {{__shared__ variable 'x' cannot be 'extern'}}
+ extern __shared__ int arr[]; // ok
+ extern __shared__ int arr0[0]; // expected-error {{__shared__ variable 'arr0' cannot be 'extern'}}
+ extern __shared__ int arr1[1]; // expected-error {{__shared__ variable 'arr1' cannot be 'extern'}}
+ extern __shared__ int* ptr ; // expected-error {{__shared__ variable 'ptr' cannot be 'extern'}}
+}
+
+__host__ __device__ void bar() {
+ extern __shared__ int arr[]; // ok
+ extern __shared__ int arr0[0]; // expected-error {{__shared__ variable 'arr0' cannot be 'extern'}}
+ extern __shared__ int arr1[1]; // expected-error {{__shared__ variable 'arr1' cannot be 'extern'}}
+ extern __shared__ int* ptr ; // expected-error {{__shared__ variable 'ptr' cannot be 'extern'}}
+}
+
+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'}}
diff --git a/test/SemaCUDA/function-overload.cu b/test/SemaCUDA/function-overload.cu
index 3c78600b174e..3d4c29c42cee 100644
--- a/test/SemaCUDA/function-overload.cu
+++ b/test/SemaCUDA/function-overload.cu
@@ -40,21 +40,21 @@ __host__ HostReturnTy dh() { return HostReturnTy(); }
__device__ DeviceReturnTy dh() { return DeviceReturnTy(); }
// H/HD and D/HD are not allowed.
-__host__ __device__ int hdh() { return 0; } // expected-note {{previous definition is here}}
-__host__ int hdh() { return 0; } // expected-error {{redefinition of 'hdh'}}
+__host__ __device__ int hdh() { return 0; } // expected-note {{previous declaration is here}}
+__host__ int hdh() { return 0; }
+// expected-error@-1 {{__host__ function 'hdh' cannot overload __host__ __device__ function 'hdh'}}
-__host__ int hhd() { return 0; } // expected-note {{previous definition is here}}
-__host__ __device__ int hhd() { return 0; } // expected-error {{redefinition of 'hhd'}}
-// expected-warning@-1 {{attribute declaration must precede definition}}
-// expected-note@-3 {{previous definition is here}}
+__host__ int hhd() { return 0; } // expected-note {{previous declaration is here}}
+__host__ __device__ int hhd() { return 0; }
+// expected-error@-1 {{__host__ __device__ function 'hhd' cannot overload __host__ function 'hhd'}}
-__host__ __device__ int hdd() { return 0; } // expected-note {{previous definition is here}}
-__device__ int hdd() { return 0; } // expected-error {{redefinition of 'hdd'}}
+__host__ __device__ int hdd() { return 0; } // expected-note {{previous declaration is here}}
+__device__ int hdd() { return 0; }
+// expected-error@-1 {{__device__ function 'hdd' cannot overload __host__ __device__ function 'hdd'}}
-__device__ int dhd() { return 0; } // expected-note {{previous definition is here}}
-__host__ __device__ int dhd() { return 0; } // expected-error {{redefinition of 'dhd'}}
-// expected-warning@-1 {{attribute declaration must precede definition}}
-// expected-note@-3 {{previous definition is here}}
+__device__ int dhd() { return 0; } // expected-note {{previous declaration is here}}
+__host__ __device__ int dhd() { return 0; }
+// expected-error@-1 {{__host__ __device__ function 'dhd' cannot overload __device__ function 'dhd'}}
// Same tests for extern "C" functions.
extern "C" __host__ int chh() { return 0; } // expected-note {{previous definition is here}}
@@ -65,13 +65,13 @@ extern "C" __device__ DeviceReturnTy cdh() { return DeviceReturnTy(); }
extern "C" __host__ HostReturnTy cdh() { return HostReturnTy(); }
// H/HD and D/HD overloading is not allowed.
-extern "C" __host__ __device__ int chhd1() { return 0; } // expected-note {{previous definition is here}}
-extern "C" __host__ int chhd1() { return 0; } // expected-error {{redefinition of 'chhd1'}}
+extern "C" __host__ __device__ int chhd1() { return 0; } // expected-note {{previous declaration is here}}
+extern "C" __host__ int chhd1() { return 0; }
+// expected-error@-1 {{__host__ function 'chhd1' cannot overload __host__ __device__ function 'chhd1'}}
-extern "C" __host__ int chhd2() { return 0; } // expected-note {{previous definition is here}}
-extern "C" __host__ __device__ int chhd2() { return 0; } // expected-error {{redefinition of 'chhd2'}}
-// expected-warning@-1 {{attribute declaration must precede definition}}
-// expected-note@-3 {{previous definition is here}}
+extern "C" __host__ int chhd2() { return 0; } // expected-note {{previous declaration is here}}
+extern "C" __host__ __device__ int chhd2() { return 0; }
+// expected-error@-1 {{__host__ __device__ function 'chhd2' cannot overload __host__ function 'chhd2'}}
// Helper functions to verify calling restrictions.
__device__ DeviceReturnTy d() { return DeviceReturnTy(); }
@@ -170,11 +170,23 @@ __host__ __device__ void hostdevicef() {
DeviceReturnTy ret_d = d();
DeviceFnPtr fp_cd = cd;
DeviceReturnTy ret_cd = cd();
+#if !defined(__CUDA_ARCH__)
+ // expected-error@-5 {{reference to __device__ function 'd' in __host__ __device__ function}}
+ // expected-error@-5 {{reference to __device__ function 'd' in __host__ __device__ function}}
+ // expected-error@-5 {{reference to __device__ function 'cd' in __host__ __device__ function}}
+ // expected-error@-5 {{reference to __device__ function 'cd' in __host__ __device__ function}}
+#endif
HostFnPtr fp_h = h;
HostReturnTy ret_h = h();
HostFnPtr fp_ch = ch;
HostReturnTy ret_ch = ch();
+#if defined(__CUDA_ARCH__)
+ // expected-error@-5 {{reference to __host__ function 'h' in __host__ __device__ function}}
+ // expected-error@-5 {{reference to __host__ function 'h' in __host__ __device__ function}}
+ // expected-error@-5 {{reference to __host__ function 'ch' in __host__ __device__ function}}
+ // expected-error@-5 {{reference to __host__ function 'ch' in __host__ __device__ function}}
+#endif
CurrentFnPtr fp_dh = dh;
CurrentReturnTy ret_dh = dh();
@@ -185,14 +197,18 @@ __host__ __device__ void hostdevicef() {
#if defined(__CUDA_ARCH__)
// expected-error@-2 {{reference to __global__ function 'g' in __host__ __device__ function}}
#endif
+
g();
- g<<<0,0>>>();
-#if !defined(__CUDA_ARCH__)
- // expected-error@-3 {{call to global function g not configured}}
+#if defined (__CUDA_ARCH__)
+ // expected-error@-2 {{reference to __global__ function 'g' in __host__ __device__ function}}
#else
- // expected-error@-5 {{no matching function for call to 'g'}}
- // expected-error@-5 {{reference to __global__ function 'g' in __host__ __device__ function}}
-#endif // __CUDA_ARCH__
+ // expected-error@-4 {{call to global function g not configured}}
+#endif
+
+ g<<<0,0>>>();
+#if defined(__CUDA_ARCH__)
+ // expected-error@-2 {{reference to __global__ function 'g' in __host__ __device__ function}}
+#endif
}
// Test for address of overloaded function resolution in the global context.
@@ -210,44 +226,11 @@ struct d_h {
__host__ ~d_h() {} // expected-error {{destructor cannot be redeclared}}
};
-// H/D overloading is OK
-struct d_dh {
- __device__ ~d_dh() {}
- __host__ ~d_dh() {}
-};
-
// HD is OK
struct d_hd {
__host__ __device__ ~d_hd() {}
};
-// Mixing H/D and HD is not allowed.
-struct d_dhhd {
- __device__ ~d_dhhd() {}
- __host__ ~d_dhhd() {} // expected-note {{previous declaration is here}}
- __host__ __device__ ~d_dhhd() {} // expected-error {{destructor cannot be redeclared}}
-};
-
-struct d_hhd {
- __host__ ~d_hhd() {} // expected-note {{previous declaration is here}}
- __host__ __device__ ~d_hhd() {} // expected-error {{destructor cannot be redeclared}}
-};
-
-struct d_hdh {
- __host__ __device__ ~d_hdh() {} // expected-note {{previous declaration is here}}
- __host__ ~d_hdh() {} // expected-error {{destructor cannot be redeclared}}
-};
-
-struct d_dhd {
- __device__ ~d_dhd() {} // expected-note {{previous declaration is here}}
- __host__ __device__ ~d_dhd() {} // expected-error {{destructor cannot be redeclared}}
-};
-
-struct d_hdd {
- __host__ __device__ ~d_hdd() {} // expected-note {{previous declaration is here}}
- __device__ ~d_hdd() {} // expected-error {{destructor cannot be redeclared}}
-};
-
// Test overloading of member functions
struct m_h {
void operator delete(void *ptr); // expected-note {{previous declaration is here}}
@@ -267,33 +250,39 @@ struct m_hd {
struct m_hhd {
__host__ void operator delete(void *ptr) {} // expected-note {{previous declaration is here}}
- __host__ __device__ void operator delete(void *ptr) {} // expected-error {{class member cannot be redeclared}}
+ __host__ __device__ void operator delete(void *ptr) {}
+ // expected-error@-1 {{__host__ __device__ function 'operator delete' cannot overload __host__ function 'operator delete'}}
};
struct m_hdh {
__host__ __device__ void operator delete(void *ptr) {} // expected-note {{previous declaration is here}}
- __host__ void operator delete(void *ptr) {} // expected-error {{class member cannot be redeclared}}
+ __host__ void operator delete(void *ptr) {}
+ // expected-error@-1 {{__host__ function 'operator delete' cannot overload __host__ __device__ function 'operator delete'}}
};
struct m_dhd {
__device__ void operator delete(void *ptr) {} // expected-note {{previous declaration is here}}
- __host__ __device__ void operator delete(void *ptr) {} // expected-error {{class member cannot be redeclared}}
+ __host__ __device__ void operator delete(void *ptr) {}
+ // expected-error@-1 {{__host__ __device__ function 'operator delete' cannot overload __device__ function 'operator delete'}}
};
struct m_hdd {
__host__ __device__ void operator delete(void *ptr) {} // expected-note {{previous declaration is here}}
- __device__ void operator delete(void *ptr) {} // expected-error {{class member cannot be redeclared}}
+ __device__ void operator delete(void *ptr) {}
+ // expected-error@-1 {{__device__ function 'operator delete' cannot overload __host__ __device__ function 'operator delete'}}
};
// __global__ functions can't be overloaded based on attribute
// difference.
struct G {
- friend void friend_of_g(G &arg);
+ friend void friend_of_g(G &arg); // expected-note {{previous declaration is here}}
private:
- int x;
+ int x; // expected-note {{declared private here}}
};
-__global__ void friend_of_g(G &arg) { int x = arg.x; } // expected-note {{previous definition is here}}
-void friend_of_g(G &arg) { int x = arg.x; } // expected-error {{redefinition of 'friend_of_g'}}
+__global__ void friend_of_g(G &arg) { int x = arg.x; }
+// expected-error@-1 {{__global__ function 'friend_of_g' cannot overload __host__ function 'friend_of_g'}}
+// expected-error@-2 {{'x' is a private member of 'G'}}
+void friend_of_g(G &arg) { int x = arg.x; }
// HD functions are sometimes allowed to call H or D functions -- this
// is an artifact of the source-to-source splitting performed by nvcc
@@ -341,7 +330,11 @@ __device__ void test_device_calls_template_fn() {
// If we have a mix of HD and H-only or D-only candidates in the overload set,
// normal C++ overload resolution rules apply first.
-template <typename T> TemplateReturnTy template_vs_hd_function(T arg) {
+template <typename T> TemplateReturnTy template_vs_hd_function(T arg)
+#ifdef __CUDA_ARCH__
+//expected-note@-2 {{declared here}}
+#endif
+{
return TemplateReturnTy();
}
__host__ __device__ HostDeviceReturnTy template_vs_hd_function(float arg) {
@@ -351,6 +344,9 @@ __host__ __device__ HostDeviceReturnTy template_vs_hd_function(float arg) {
__host__ __device__ void test_host_device_calls_hd_template() {
HostDeviceReturnTy ret1 = template_vs_hd_function(1.0f);
TemplateReturnTy ret2 = template_vs_hd_function(1);
+#ifdef __CUDA_ARCH__
+ // expected-error@-2 {{reference to __host__ function 'template_vs_hd_function<int>' in __host__ __device__ function}}
+#endif
}
__host__ void test_host_calls_hd_template() {
@@ -370,12 +366,39 @@ __device__ void test_device_calls_hd_template() {
// side of compilation.
__device__ DeviceReturnTy device_only_function(int arg) { return DeviceReturnTy(); }
__device__ DeviceReturnTy2 device_only_function(float arg) { return DeviceReturnTy2(); }
+#ifndef __CUDA_ARCH__
+ // expected-note@-3 {{'device_only_function' declared here}}
+ // expected-note@-3 {{'device_only_function' declared here}}
+#endif
__host__ HostReturnTy host_only_function(int arg) { return HostReturnTy(); }
__host__ HostReturnTy2 host_only_function(float arg) { return HostReturnTy2(); }
+#ifdef __CUDA_ARCH__
+ // expected-note@-3 {{'host_only_function' declared here}}
+ // expected-note@-3 {{'host_only_function' declared here}}
+#endif
__host__ __device__ void test_host_device_single_side_overloading() {
DeviceReturnTy ret1 = device_only_function(1);
DeviceReturnTy2 ret2 = device_only_function(1.0f);
+#ifndef __CUDA_ARCH__
+ // expected-error@-3 {{reference to __device__ function 'device_only_function' in __host__ __device__ function}}
+ // expected-error@-3 {{reference to __device__ function 'device_only_function' in __host__ __device__ function}}
+#endif
HostReturnTy ret3 = host_only_function(1);
HostReturnTy2 ret4 = host_only_function(1.0f);
+#ifdef __CUDA_ARCH__
+ // expected-error@-3 {{reference to __host__ function 'host_only_function' in __host__ __device__ function}}
+ // expected-error@-3 {{reference to __host__ function 'host_only_function' in __host__ __device__ function}}
+#endif
+}
+
+// Verify that we allow overloading function templates.
+template <typename T> __host__ T template_overload(const T &a) { return a; };
+template <typename T> __device__ T template_overload(const T &a) { return a; };
+
+__host__ void test_host_template_overload() {
+ template_overload(1); // OK. Attribute-based overloading picks __host__ variant.
+}
+__device__ void test_device_template_overload() {
+ template_overload(1); // OK. Attribute-based overloading picks __device__ variant.
}
diff --git a/test/SemaCUDA/function-template-overload.cu b/test/SemaCUDA/function-template-overload.cu
new file mode 100644
index 000000000000..56bba653958c
--- /dev/null
+++ b/test/SemaCUDA/function-template-overload.cu
@@ -0,0 +1,113 @@
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-linux-gnu -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++11 -triple nvptx64-nvidia-cuda -fsyntax-only -fcuda-is-device -verify %s
+
+#include "Inputs/cuda.h"
+
+struct HType {}; // expected-note-re 6 {{candidate constructor {{.*}} not viable: no known conversion from 'DType'}}
+struct DType {}; // expected-note-re 6 {{candidate constructor {{.*}} not viable: no known conversion from 'HType'}}
+struct HDType {};
+
+template <typename T> __host__ HType overload_h_d(T a) { return HType(); }
+// expected-note@-1 2 {{candidate template ignored: could not match 'HType' against 'DType'}}
+// expected-note@-2 2 {{candidate template ignored: target attributes do not match}}
+template <typename T> __device__ DType overload_h_d(T a) { return DType(); }
+// expected-note@-1 2 {{candidate template ignored: could not match 'DType' against 'HType'}}
+// expected-note@-2 2 {{candidate template ignored: target attributes do not match}}
+
+// Check explicit instantiation.
+template __device__ __host__ DType overload_h_d(int a); // There's no HD template...
+// expected-error@-1 {{explicit instantiation of 'overload_h_d' does not refer to a function template, variable template, member function, member class, or static data member}}
+template __device__ __host__ HType overload_h_d(int a); // There's no HD template...
+// expected-error@-1 {{explicit instantiation of 'overload_h_d' does not refer to a function template, variable template, member function, member class, or static data member}}
+template __device__ DType overload_h_d(int a); // OK. instantiates D
+template __host__ HType overload_h_d(int a); // OK. instantiates H
+
+// Check explicit specialization.
+template <> __device__ __host__ DType overload_h_d(long a); // There's no HD template...
+// expected-error@-1 {{no function template matches function template specialization 'overload_h_d'}}
+template <> __device__ __host__ HType overload_h_d(long a); // There's no HD template...
+// expected-error@-1 {{no function template matches function template specialization 'overload_h_d'}}
+template <> __device__ DType overload_h_d(long a); // OK. instantiates D
+template <> __host__ HType overload_h_d(long a); // OK. instantiates H
+
+
+// Can't overload HD template with H or D template, though
+// non-template functions are OK.
+template <typename T> __host__ __device__ HDType overload_hd(T a) { return HDType(); }
+// expected-note@-1 {{previous declaration is here}}
+// expected-note@-2 2 {{candidate template ignored: could not match 'HDType' against 'HType'}}
+template <typename T> __device__ HDType overload_hd(T a);
+// expected-error@-1 {{__device__ function 'overload_hd' cannot overload __host__ __device__ function 'overload_hd'}}
+__device__ HDType overload_hd(int a); // OK.
+
+// Verify that target attributes are taken into account when we
+// explicitly specialize or instantiate function tempaltes.
+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);
+// expected-error@-1 {{explicit instantiation of 'overload_hd' does not refer to a function template, variable template, member function, member class, or static data member}}
+__host__ HType overload_hd(int a); // OK
+
+template <typename T> __host__ T overload_h(T a); // expected-note {{previous declaration is here}}
+template <typename T> __host__ __device__ T overload_h(T a);
+// expected-error@-1 {{__host__ __device__ function 'overload_h' cannot overload __host__ function 'overload_h'}}
+template <typename T> __device__ T overload_h(T a); // OK. D can overload H.
+
+template <typename T> __host__ HType overload_h_d2(T a) { return HType(); }
+template <typename T> __host__ __device__ HDType overload_h_d2(T a) { return HDType(); }
+template <typename T1, typename T2 = int> __device__ DType overload_h_d2(T1 a) { T1 x; T2 y; return DType(); }
+
+// constexpr functions are implicitly HD, but explicit
+// instantiation/specialization must use target attributes as written.
+template <typename T> constexpr T overload_ce_implicit_hd(T a) { return a+1; }
+// expected-note@-1 3 {{candidate template ignored: target attributes do not match}}
+
+// These will not match the template.
+template __host__ __device__ int overload_ce_implicit_hd(int a);
+// expected-error@-1 {{explicit instantiation of 'overload_ce_implicit_hd' does not refer to a function template, variable template, member function, member class, or static data member}}
+template <> __host__ __device__ long overload_ce_implicit_hd(long a);
+// expected-error@-1 {{no function template matches function template specialization 'overload_ce_implicit_hd'}}
+template <> __host__ __device__ constexpr long overload_ce_implicit_hd(long a);
+// expected-error@-1 {{no function template matches function template specialization 'overload_ce_implicit_hd'}}
+
+// These should work, because template matching ignores the implicit
+// HD attributes the compiler gives to constexpr functions/templates,
+// so 'overload_ce_implicit_hd' template will match __host__ functions
+// only.
+template __host__ int overload_ce_implicit_hd(int a);
+template <> __host__ long overload_ce_implicit_hd(long a);
+
+template float overload_ce_implicit_hd(float a);
+template <> float* overload_ce_implicit_hd(float *a);
+template <> constexpr double overload_ce_implicit_hd(double a) { return a + 3.0; };
+
+__host__ void hf() {
+ overload_hd(13);
+ overload_ce_implicit_hd('h'); // Implicitly instantiated
+ overload_ce_implicit_hd(1.0f); // Explicitly instantiated
+ overload_ce_implicit_hd(2.0); // Explicitly specialized
+
+ HType h = overload_h_d(10);
+ HType h2i = overload_h_d2<int>(11);
+ HType h2ii = overload_h_d2<int>(12);
+
+ // These should be implicitly instantiated from __host__ template returning HType.
+ DType d = overload_h_d(20); // expected-error {{no viable conversion from 'HType' to 'DType'}}
+ DType d2i = overload_h_d2<int>(21); // expected-error {{no viable conversion from 'HType' to 'DType'}}
+ DType d2ii = overload_h_d2<int>(22); // expected-error {{no viable conversion from 'HType' to 'DType'}}
+}
+__device__ void df() {
+ overload_hd(23);
+ overload_ce_implicit_hd('d'); // Implicitly instantiated
+ overload_ce_implicit_hd(1.0f); // Explicitly instantiated
+ overload_ce_implicit_hd(2.0); // Explicitly specialized
+
+ // These should be implicitly instantiated from __device__ template returning DType.
+ HType h = overload_h_d(10); // expected-error {{no viable conversion from 'DType' to 'HType'}}
+ HType h2i = overload_h_d2<int>(11); // expected-error {{no viable conversion from 'DType' to 'HType'}}
+ HType h2ii = overload_h_d2<int>(12); // expected-error {{no viable conversion from 'DType' to 'HType'}}
+
+ DType d = overload_h_d(20);
+ DType d2i = overload_h_d2<int>(21);
+ DType d2ii = overload_h_d2<int>(22);
+}
diff --git a/test/SemaCUDA/global-initializers-host.cu b/test/SemaCUDA/global-initializers-host.cu
new file mode 100644
index 000000000000..810c6b977786
--- /dev/null
+++ b/test/SemaCUDA/global-initializers-host.cu
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 %s --std=c++11 -triple x86_64-linux-unknown -fsyntax-only -o - -verify
+
+#include "Inputs/cuda.h"
+
+// Check that we get an error if we try to call a __device__ function from a
+// module initializer.
+
+struct S {
+ __device__ S() {}
+ // expected-note@-1 {{'S' declared here}}
+};
+
+S s;
+// expected-error@-1 {{reference to __device__ function 'S' in global initializer}}
+
+struct T {
+ __host__ __device__ T() {}
+};
+T t; // No error, this is OK.
+
+struct U {
+ __host__ U() {}
+ __device__ U(int) {}
+ // expected-note@-1 {{'U' declared here}}
+};
+U u(42);
+// expected-error@-1 {{reference to __device__ function 'U' in global initializer}}
+
+__device__ int device_fn() { return 42; }
+// expected-note@-1 {{'device_fn' declared here}}
+int n = device_fn();
+// expected-error@-1 {{reference to __device__ function 'device_fn' in global initializer}}
diff --git a/test/SemaCUDA/gnu-inline.cu b/test/SemaCUDA/gnu-inline.cu
new file mode 100644
index 000000000000..0ed543326be8
--- /dev/null
+++ b/test/SemaCUDA/gnu-inline.cu
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+#include "Inputs/cuda.h"
+
+// expected-no-diagnostics
+
+// Check that we can handle gnu_inline functions when compiling in CUDA mode.
+
+void foo();
+inline __attribute__((gnu_inline)) void bar() { foo(); }
diff --git a/test/SemaCUDA/implicit-device-lambda.cu b/test/SemaCUDA/implicit-device-lambda.cu
new file mode 100644
index 000000000000..8e5b7ddddb8f
--- /dev/null
+++ b/test/SemaCUDA/implicit-device-lambda.cu
@@ -0,0 +1,106 @@
+// RUN: %clang_cc1 -std=c++11 -fcuda-is-device -verify -fsyntax-only -verify-ignore-unexpected=warning -verify-ignore-unexpected=note %s
+// RUN: %clang_cc1 -std=c++11 -verify -fsyntax-only -verify-ignore-unexpected=warning -verify-ignore-unexpected=note %s
+
+#include "Inputs/cuda.h"
+
+__device__ void device_fn() {
+ auto f1 = [&] {};
+ f1(); // implicitly __device__
+
+ auto f2 = [&] __device__ {};
+ f2();
+
+ auto f3 = [&] __host__ {};
+ f3(); // expected-error {{no matching function}}
+
+ auto f4 = [&] __host__ __device__ {};
+ f4();
+
+ // Now do it all again with '()'s in the lambda declarations: This is a
+ // different parse path.
+ auto g1 = [&]() {};
+ g1(); // implicitly __device__
+
+ auto g2 = [&]() __device__ {};
+ g2();
+
+ auto g3 = [&]() __host__ {};
+ g3(); // expected-error {{no matching function}}
+
+ auto g4 = [&]() __host__ __device__ {};
+ g4();
+
+ // Once more, with the '()'s in a different place.
+ auto h1 = [&]() {};
+ h1(); // implicitly __device__
+
+ auto h2 = [&] __device__ () {};
+ h2();
+
+ auto h3 = [&] __host__ () {};
+ h3(); // expected-error {{no matching function}}
+
+ auto h4 = [&] __host__ __device__ () {};
+ h4();
+}
+
+// Behaves identically to device_fn.
+__global__ void kernel_fn() {
+ auto f1 = [&] {};
+ f1(); // implicitly __device__
+
+ auto f2 = [&] __device__ {};
+ f2();
+
+ auto f3 = [&] __host__ {};
+ f3(); // expected-error {{no matching function}}
+
+ auto f4 = [&] __host__ __device__ {};
+ f4();
+
+ // No need to re-test all the parser contortions we test in the device
+ // function.
+}
+
+__host__ void host_fn() {
+ auto f1 = [&] {};
+ f1(); // implicitly __host__ (i.e., no magic)
+
+ auto f2 = [&] __device__ {};
+ f2(); // expected-error {{no matching function}}
+
+ auto f3 = [&] __host__ {};
+ f3();
+
+ auto f4 = [&] __host__ __device__ {};
+ f4();
+}
+
+__host__ __device__ void hd_fn() {
+ auto f1 = [&] {};
+ f1(); // implicitly __host__ __device__
+
+ auto f2 = [&] __device__ {};
+ f2();
+#ifndef __CUDA_ARCH__
+ // expected-error@-2 {{reference to __device__ function}}
+#endif
+
+ auto f3 = [&] __host__ {};
+ f3();
+#ifdef __CUDA_ARCH__
+ // expected-error@-2 {{reference to __host__ function}}
+#endif
+
+ auto f4 = [&] __host__ __device__ {};
+ f4();
+}
+
+// The special treatment above only applies to lambdas.
+__device__ void foo() {
+ struct X {
+ void foo() {}
+ };
+ X x;
+ x.foo(); // expected-error {{reference to __host__ function 'foo' in __device__ function}}
+}
diff --git a/test/SemaCUDA/method-target.cu b/test/SemaCUDA/method-target.cu
index 3fabfc359b7a..8e17daa0c123 100644
--- a/test/SemaCUDA/method-target.cu
+++ b/test/SemaCUDA/method-target.cu
@@ -6,7 +6,7 @@
// Test 1: host method called from device function
struct S1 {
- void method() {}
+ void method() {} // expected-note {{'method' declared here}}
};
__device__ void foo1(S1& s) {
@@ -29,7 +29,7 @@ __device__ void foo2(S2& s, int i, float f) {
// Test 3: device method called from host function
struct S3 {
- __device__ void method() {}
+ __device__ void method() {} // expected-note {{'method' declared here}}
};
void foo3(S3& s) {
@@ -40,11 +40,11 @@ void foo3(S3& s) {
// Test 4: device method called from host&device function
struct S4 {
- __device__ void method() {}
+ __device__ void method() {} // expected-note {{'method' declared here}}
};
__host__ __device__ void foo4(S4& s) {
- s.method();
+ s.method(); // expected-error {{reference to __device__ function 'method' in __host__ __device__ function}}
}
//------------------------------------------------------------------------------
@@ -63,7 +63,7 @@ __device__ void foo5(S5& s, S5& t) {
// Test 6: call method through pointer
struct S6 {
- void method() {}
+ void method() {} // expected-note {{'method' declared here}};
};
__device__ void foo6(S6* s) {
diff --git a/test/SemaCUDA/no-call-stack-for-immediate-errs.cu b/test/SemaCUDA/no-call-stack-for-immediate-errs.cu
new file mode 100644
index 000000000000..6dc98695c1e3
--- /dev/null
+++ b/test/SemaCUDA/no-call-stack-for-immediate-errs.cu
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -fcuda-is-device -fsyntax-only -verify %s
+
+#include "Inputs/cuda.h"
+
+// Here we should dump an error about the VLA in device_fn, but we should not
+// print a callstack indicating how device_fn becomes known-emitted, because
+// it's an error to use a VLA in any __device__ function, even one that doesn't
+// get emitted.
+
+inline __device__ void device_fn(int n);
+inline __device__ void device_fn2() { device_fn(42); }
+
+__global__ void kernel() { device_fn2(); }
+
+inline __device__ void device_fn(int n) {
+ int vla[n]; // expected-error {{variable-length array}}
+}
diff --git a/test/SemaCUDA/no-destructor-overload.cu b/test/SemaCUDA/no-destructor-overload.cu
new file mode 100644
index 000000000000..aa6971ee8ca8
--- /dev/null
+++ b/test/SemaCUDA/no-destructor-overload.cu
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fcuda-is-device -fsyntax-only -verify %s
+
+#include "Inputs/cuda.h"
+
+// We don't allow destructors to be overloaded. Making this work would be a
+// giant change to clang, and the use cases seem quite limited.
+
+struct A {
+ ~A() {} // expected-note {{previous declaration is here}}
+ __device__ ~A() {} // expected-error {{destructor cannot be redeclared}}
+};
+
+struct B {
+ __host__ ~B() {} // expected-note {{previous declaration is here}}
+ __host__ __device__ ~B() {} // expected-error {{destructor cannot be redeclared}}
+};
+
+struct C {
+ __host__ __device__ ~C() {} // expected-note {{previous declaration is here}}
+ __host__ ~C() {} // expected-error {{destructor cannot be redeclared}}
+};
+
+struct D {
+ __device__ ~D() {} // expected-note {{previous declaration is here}}
+ __host__ __device__ ~D() {} // expected-error {{destructor cannot be redeclared}}
+};
+
+struct E {
+ __host__ __device__ ~E() {} // expected-note {{previous declaration is here}}
+ __device__ ~E() {} // expected-error {{destructor cannot be redeclared}}
+};
+
diff --git a/test/SemaCUDA/overloaded-delete.cu b/test/SemaCUDA/overloaded-delete.cu
index e582fedb0aa8..95a93a7a5459 100644
--- a/test/SemaCUDA/overloaded-delete.cu
+++ b/test/SemaCUDA/overloaded-delete.cu
@@ -16,10 +16,54 @@ __host__ __device__ void test(S* s) {
delete s;
}
+// Code should work with no explicit declarations/definitions of
+// allocator functions.
+__host__ __device__ void test_default_global_delete_hd(int *ptr) {
+ // Again, there should be no ambiguity between which operator delete we call.
+ ::delete ptr;
+}
+
+__device__ void test_default_global_delete(int *ptr) {
+ // Again, there should be no ambiguity between which operator delete we call.
+ ::delete ptr;
+}
+__host__ void test_default_global_delete(int *ptr) {
+ // Again, there should be no ambiguity between which operator delete we call.
+ ::delete ptr;
+}
+
+// It should work with only some of allocators (re-)declared.
+__device__ void operator delete(void *ptr);
+
+__host__ __device__ void test_partial_global_delete_hd(int *ptr) {
+ // Again, there should be no ambiguity between which operator delete we call.
+ ::delete ptr;
+}
+
+__device__ void test_partial_global_delete(int *ptr) {
+ // Again, there should be no ambiguity between which operator delete we call.
+ ::delete ptr;
+}
+__host__ void test_partial_global_delete(int *ptr) {
+ // Again, there should be no ambiguity between which operator delete we call.
+ ::delete ptr;
+}
+
+
+// We should be able to define both host and device variants.
__host__ void operator delete(void *ptr) {}
__device__ void operator delete(void *ptr) {}
-__host__ __device__ void test_global_delete(int *ptr) {
+__host__ __device__ void test_overloaded_global_delete_hd(int *ptr) {
+ // Again, there should be no ambiguity between which operator delete we call.
+ ::delete ptr;
+}
+
+__device__ void test_overloaded_global_delete(int *ptr) {
+ // Again, there should be no ambiguity between which operator delete we call.
+ ::delete ptr;
+}
+__host__ void test_overloaded_global_delete(int *ptr) {
// Again, there should be no ambiguity between which operator delete we call.
::delete ptr;
}
diff --git a/test/SemaCUDA/reference-to-kernel-fn.cu b/test/SemaCUDA/reference-to-kernel-fn.cu
new file mode 100644
index 000000000000..e502d134b086
--- /dev/null
+++ b/test/SemaCUDA/reference-to-kernel-fn.cu
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify \
+// RUN: -verify-ignore-unexpected=note %s
+// RUN: %clang_cc1 -std=c++11 -fcuda-is-device -fsyntax-only -verify \
+// RUN: -verify-ignore-unexpected=note -DDEVICE %s
+
+// Check that we can reference (get a function pointer to) a __global__
+// function from the host side, but not the device side. (We don't yet support
+// device-side kernel launches.)
+
+#include "Inputs/cuda.h"
+
+struct Dummy {};
+
+__global__ void kernel() {}
+
+typedef void (*fn_ptr_t)();
+
+__host__ __device__ fn_ptr_t get_ptr_hd() {
+ return kernel;
+#ifdef DEVICE
+ // expected-error@-2 {{reference to __global__ function}}
+#endif
+}
+__host__ fn_ptr_t get_ptr_h() {
+ return kernel;
+}
+__device__ fn_ptr_t get_ptr_d() {
+ return kernel; // expected-error {{reference to __global__ function}}
+}
diff --git a/test/SemaCUDA/trace-through-global.cu b/test/SemaCUDA/trace-through-global.cu
new file mode 100644
index 000000000000..f73570fa6645
--- /dev/null
+++ b/test/SemaCUDA/trace-through-global.cu
@@ -0,0 +1,48 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// Check that it's OK for kernels to call HD functions that call device-only
+// functions.
+
+#include "Inputs/cuda.h"
+
+__device__ void device_fn(int) {}
+// expected-note@-1 2 {{declared here}}
+
+inline __host__ __device__ int hd1() {
+ device_fn(0); // expected-error {{reference to __device__ function}}
+ return 0;
+}
+
+inline __host__ __device__ int hd2() {
+ // No error here because hd2 is only referenced from a kernel.
+ device_fn(0);
+ return 0;
+}
+
+inline __host__ __device__ void hd3(int) {
+ device_fn(0); // expected-error {{reference to __device__ function 'device_fn'}}
+}
+inline __host__ __device__ void hd3(double) {}
+
+inline __host__ __device__ void hd4(int) {}
+inline __host__ __device__ void hd4(double) {
+ device_fn(0); // No error; this function is never called.
+}
+
+__global__ void kernel(int) { hd2(); }
+
+template <typename T>
+void launch_kernel() {
+ kernel<<<0, 0>>>(T());
+
+ // Notice that these two diagnostics are different: Because the call to hd1
+ // is not dependent on T, the call to hd1 comes from 'launch_kernel', while
+ // the call to hd3, being dependent, comes from 'launch_kernel<int>'.
+ hd1(); // expected-note {{called by 'launch_kernel'}}
+ hd3(T()); // expected-note {{called by 'launch_kernel<int>'}}
+}
+
+void host_fn() {
+ launch_kernel<int>();
+ // expected-note@-1 2 {{called by 'host_fn'}}
+}
diff --git a/test/SemaCUDA/vla.cu b/test/SemaCUDA/vla.cu
new file mode 100644
index 000000000000..f0d1ba595d93
--- /dev/null
+++ b/test/SemaCUDA/vla.cu
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -fcuda-is-device -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify -DHOST %s
+
+#include "Inputs/cuda.h"
+
+void host(int n) {
+ int x[n];
+}
+
+__device__ void device(int n) {
+ int x[n]; // expected-error {{cannot use variable-length arrays in __device__ functions}}
+}
+
+__host__ __device__ void hd(int n) {
+ int x[n];
+#ifdef __CUDA_ARCH__
+ // expected-error@-2 {{cannot use variable-length arrays in __host__ __device__ functions}}
+#endif
+}
+
+// No error because never codegen'ed for device.
+__host__ __device__ inline void hd_inline(int n) {
+ int x[n];
+}
+void call_hd_inline() { hd_inline(42); }
diff --git a/test/SemaCXX/MicrosoftCompatibility.cpp b/test/SemaCXX/MicrosoftCompatibility.cpp
index fe8e8f77accb..26cd7825ee87 100644
--- a/test/SemaCXX/MicrosoftCompatibility.cpp
+++ b/test/SemaCXX/MicrosoftCompatibility.cpp
@@ -99,23 +99,39 @@ int jump_over_indirect_goto() {
namespace PR11826 {
struct pair {
pair(int v) { }
+#if _MSC_VER >= 1900
+ void operator=(pair&& rhs) { } // expected-note {{copy constructor is implicitly deleted because 'pair' has a user-declared move assignment operator}}
+#else
void operator=(pair&& rhs) { }
+#endif
};
void f() {
pair p0(3);
+#if _MSC_VER >= 1900
+ pair p = p0; // expected-error {{call to implicitly-deleted copy constructor of 'PR11826::pair'}}
+#else
pair p = p0;
+#endif
}
}
namespace PR11826_for_symmetry {
struct pair {
pair(int v) { }
+#if _MSC_VER >= 1900
+ pair(pair&& rhs) { } // expected-note {{copy assignment operator is implicitly deleted because 'pair' has a user-declared move constructor}}
+#else
pair(pair&& rhs) { }
+#endif
};
void f() {
pair p0(3);
pair p(4);
+#if _MSC_VER >= 1900
+ p = p0; // expected-error {{object of type 'PR11826_for_symmetry::pair' cannot be assigned because its copy assignment operator is implicitly deleted}}
+#else
p = p0;
+#endif
}
}
@@ -242,3 +258,14 @@ namespace IntToNullPtrConv {
template<int N> int *get_n() { return N; } // expected-warning {{expression which evaluates to zero treated as a null pointer constant}}
int *g_nullptr = get_n<0>(); // expected-note {{in instantiation of function template specialization}}
}
+
+namespace signed_hex_i64 {
+void f(long long);
+void f(int);
+void g() {
+ // This is an ambiguous call in standard C++.
+ // This calls f(long long) in Microsoft mode because LL is always signed.
+ f(0xffffffffffffffffLL);
+ f(0xffffffffffffffffi64);
+}
+}
diff --git a/test/SemaCXX/MicrosoftExtensions.cpp b/test/SemaCXX/MicrosoftExtensions.cpp
index e10deadf7c7f..e12dea1fb620 100644
--- a/test/SemaCXX/MicrosoftExtensions.cpp
+++ b/test/SemaCXX/MicrosoftExtensions.cpp
@@ -158,19 +158,16 @@ void m1() {
}
-
-
-
-void f(long long);
-void f(int);
-
-int main()
-{
- // This is an ambiguous call in standard C++.
- // This calls f(long long) in Microsoft mode because LL is always signed.
- f(0xffffffffffffffffLL);
+namespace signed_hex_i64 {
+void f(long long); // expected-note {{candidate function}}
+void f(int); // expected-note {{candidate function}}
+void g() {
+ // This used to be controlled by -fms-extensions, but it is now under
+ // -fms-compatibility.
+ f(0xffffffffffffffffLL); // expected-error {{call to 'f' is ambiguous}}
f(0xffffffffffffffffi64);
}
+}
// Enumeration types with a fixed underlying type.
const int seventeen = 17;
diff --git a/test/SemaCXX/PR25848.cpp b/test/SemaCXX/PR25848.cpp
new file mode 100644
index 000000000000..a22ac6650a06
--- /dev/null
+++ b/test/SemaCXX/PR25848.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+struct A;
+
+inline int g(); // expected-warning{{inline function 'g' is not defined}}
+
+template<int M>
+struct R {
+ friend int g() {
+ return M;
+ }
+};
+
+void m() {
+ g(); // expected-note{{used here}}
+}
diff --git a/test/SemaCXX/PR29152.cpp b/test/SemaCXX/PR29152.cpp
new file mode 100644
index 000000000000..63c9c9bed545
--- /dev/null
+++ b/test/SemaCXX/PR29152.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -fsyntax-only -Wunreachable-code -verify %s
+
+static const bool False = false;
+
+struct A {
+ ~A();
+ operator bool();
+};
+void Bar();
+
+void Foo() {
+ if (False && A()) {
+ Bar(); // expected-no-diagnostics
+ }
+}
diff --git a/test/SemaCXX/PR8755.cpp b/test/SemaCXX/PR8755.cpp
index 07778ddfc900..6818f3f0a822 100644
--- a/test/SemaCXX/PR8755.cpp
+++ b/test/SemaCXX/PR8755.cpp
@@ -7,7 +7,7 @@ struct A {
template <typename T>
void f() {
- class A <T> ::iterator foo; // expected-error{{elaborated type refers to a typedef}}
+ class A <T> ::iterator foo; // expected-error{{typedef 'iterator' cannot be referenced with a class specifier}}
}
void g() {
diff --git a/test/SemaCXX/address-packed-member-memops.cpp b/test/SemaCXX/address-packed-member-memops.cpp
new file mode 100644
index 000000000000..6614626ae65c
--- /dev/null
+++ b/test/SemaCXX/address-packed-member-memops.cpp
@@ -0,0 +1,28 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+struct B {
+ int x, y, z, w;
+} b;
+
+struct __attribute__((packed)) A {
+ struct B b;
+} a;
+
+typedef __typeof__(sizeof(int)) size_t;
+
+extern "C" {
+void *memcpy(void *dest, const void *src, size_t n);
+int memcmp(const void *s1, const void *s2, size_t n);
+void *memmove(void *dest, const void *src, size_t n);
+void *memset(void *s, int c, size_t n);
+}
+
+int x;
+
+void foo() {
+ memcpy(&a.b, &b, sizeof(b));
+ memmove(&a.b, &b, sizeof(b));
+ memset(&a.b, 0, sizeof(b));
+ x = memcmp(&a.b, &b, sizeof(b));
+}
diff --git a/test/SemaCXX/address-packed.cpp b/test/SemaCXX/address-packed.cpp
new file mode 100644
index 000000000000..308c4858cd50
--- /dev/null
+++ b/test/SemaCXX/address-packed.cpp
@@ -0,0 +1,114 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+extern void f1(int *);
+extern void f2(char *);
+
+struct __attribute__((packed)) Arguable {
+ int x;
+ char c;
+ static void foo();
+};
+
+extern void f3(void());
+
+namespace Foo {
+struct __attribute__((packed)) Arguable {
+ char c;
+ int x;
+ static void foo();
+};
+}
+
+struct Arguable *get_arguable();
+
+void f4(int &);
+
+void to_void(void *);
+
+template <typename... T>
+void sink(T...);
+
+void g0() {
+ {
+ Foo::Arguable arguable;
+ f1(&arguable.x); // expected-warning {{packed member 'x' of class or structure 'Foo::Arguable'}}
+ f2(&arguable.c); // no-warning
+ f3(&arguable.foo); // no-warning
+
+ to_void(&arguable.x); // no-warning
+ void *p1 = &arguable.x; // no-warning
+ void *p2 = static_cast<void *>(&arguable.x); // no-warning
+ void *p3 = reinterpret_cast<void *>(&arguable.x); // no-warning
+ void *p4 = (void *)&arguable.x; // no-warning
+ sink(p1, p2, p3, p4);
+ }
+ {
+ Arguable arguable1;
+ Arguable &arguable(arguable1);
+ f1(&arguable.x); // expected-warning {{packed member 'x' of class or structure 'Arguable'}}
+ f2(&arguable.c); // no-warning
+ f3(&arguable.foo); // no-warning
+ }
+ {
+ Arguable *arguable1;
+ Arguable *&arguable(arguable1);
+ f1(&arguable->x); // expected-warning {{packed member 'x' of class or structure 'Arguable'}}
+ f2(&arguable->c); // no-warning
+ f3(&arguable->foo); // no-warning
+ }
+}
+
+struct __attribute__((packed)) A {
+ int x;
+ char c;
+
+ int *f0() {
+ return &this->x; // expected-warning {{packed member 'x' of class or structure 'A'}}
+ }
+
+ int *g0() {
+ return &x; // expected-warning {{packed member 'x' of class or structure 'A'}}
+ }
+
+ char *h0() {
+ return &c; // no-warning
+ }
+};
+
+struct B : A {
+ int *f1() {
+ return &this->x; // expected-warning {{packed member 'x' of class or structure 'A'}}
+ }
+
+ int *g1() {
+ return &x; // expected-warning {{packed member 'x' of class or structure 'A'}}
+ }
+
+ char *h1() {
+ return &c; // no-warning
+ }
+};
+
+template <typename Ty>
+class __attribute__((packed)) S {
+ Ty X;
+
+public:
+ const Ty *get() const {
+ return &X; // expected-warning {{packed member 'X' of class or structure 'S<int>'}}
+ // expected-warning@-1 {{packed member 'X' of class or structure 'S<float>'}}
+ }
+};
+
+template <typename Ty>
+void h(Ty *);
+
+void g1() {
+ S<int> s1;
+ s1.get(); // expected-note {{in instantiation of member function 'S<int>::get'}}
+
+ S<char> s2;
+ s2.get();
+
+ S<float> s3;
+ s3.get(); // expected-note {{in instantiation of member function 'S<float>::get'}}
+}
diff --git a/test/SemaCXX/aggregate-init-cxx98.cpp b/test/SemaCXX/aggregate-init-cxx98.cpp
new file mode 100644
index 000000000000..332801f0822c
--- /dev/null
+++ b/test/SemaCXX/aggregate-init-cxx98.cpp
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -std=c++98 -verify %s
+
+struct A {
+ A() = default; // expected-warning {{C++11}}
+ int n;
+};
+A a = {0};
diff --git a/test/SemaCXX/aggregate-initialization.cpp b/test/SemaCXX/aggregate-initialization.cpp
index ddaf33fc1bfa..7b6abd22acc7 100644
--- a/test/SemaCXX/aggregate-initialization.cpp
+++ b/test/SemaCXX/aggregate-initialization.cpp
@@ -4,8 +4,6 @@
// Verify that using an initializer list for a non-aggregate looks for
// constructors..
-// Note that due to a (likely) standard bug, this is technically an aggregate,
-// but we do not treat it as one.
struct NonAggr1 { // expected-note 2 {{candidate constructor}}
NonAggr1(int, int) { } // expected-note {{candidate constructor}}
@@ -57,7 +55,7 @@ struct A {
A(int);
~A();
- A(const A&) = delete; // expected-note 2 {{'A' has been explicitly marked deleted here}}
+ A(const A&) = delete; // expected-note 0-2{{'A' has been explicitly marked deleted here}}
};
struct B {
@@ -70,10 +68,16 @@ struct C {
void f() {
A as1[1] = { };
- A as2[1] = { 1 }; // expected-error {{copying array element of type 'A' invokes deleted constructor}}
+ A as2[1] = { 1 };
+#if __cplusplus <= 201402L
+ // expected-error@-2 {{copying array element of type 'A' invokes deleted constructor}}
+#endif
B b1 = { };
- B b2 = { 1 }; // expected-error {{copying member subobject of type 'A' invokes deleted constructor}}
+ B b2 = { 1 };
+#if __cplusplus <= 201402L
+ // expected-error@-2 {{copying member subobject of type 'A' invokes deleted constructor}}
+#endif
C c1 = { 1 };
}
diff --git a/test/SemaCXX/ambig-user-defined-conversions.cpp b/test/SemaCXX/ambig-user-defined-conversions.cpp
index 1a3c102f034c..276c1b07b5d9 100644
--- a/test/SemaCXX/ambig-user-defined-conversions.cpp
+++ b/test/SemaCXX/ambig-user-defined-conversions.cpp
@@ -65,3 +65,8 @@ namespace rdar8876150 {
bool f(D d) { return !d; } // expected-error{{ambiguous conversion from derived class 'rdar8876150::D' to base class 'rdar8876150::A':}}
}
+
+namespace assignment {
+ struct A { operator short(); operator bool(); }; // expected-note 2{{candidate}}
+ void f(int n, A a) { n = a; } // expected-error{{ambiguous}}
+}
diff --git a/test/SemaCXX/attr-gnu.cpp b/test/SemaCXX/attr-gnu.cpp
index b4e9f4609f67..a553f0d21000 100644
--- a/test/SemaCXX/attr-gnu.cpp
+++ b/test/SemaCXX/attr-gnu.cpp
@@ -27,3 +27,19 @@ public:
void test3() __attribute__((cf_unknown_transfer)) override {} // Ok, not known to GCC.
};
}
+
+template<typename T>
+union Tu { T b; } __attribute__((transparent_union)); // expected-warning {{'transparent_union' attribute ignored}}
+
+template<typename T>
+union Tu2 { int x; T b; } __attribute__((transparent_union)); // expected-warning {{'transparent_union' attribute ignored}}
+
+union Tu3 { int x; } __attribute((transparent_union)); // expected-warning {{'transparent_union' attribute ignored}}
+
+void tuTest1(Tu<int> u); // expected-note {{candidate function not viable: no known conversion from 'int' to 'Tu<int>' for 1st argument}}
+void tuTest2(Tu3 u); // expected-note {{candidate function not viable: no known conversion from 'int' to 'Tu3' for 1st argument}}
+void tu() {
+ int x = 2;
+ tuTest1(x); // expected-error {{no matching function for call to 'tuTest1'}}
+ tuTest2(x); // expected-error {{no matching function for call to 'tuTest2'}}
+}
diff --git a/test/SemaCXX/attr-no-sanitize-address.cpp b/test/SemaCXX/attr-no-sanitize-address.cpp
index 9499742ac570..127129c948a0 100644
--- a/test/SemaCXX/attr-no-sanitize-address.cpp
+++ b/test/SemaCXX/attr-no-sanitize-address.cpp
@@ -21,9 +21,6 @@ int noanal_testfn(int y) {
return x;
}
-int noanal_test_var NO_SANITIZE_ADDRESS; // \
- // expected-error {{'no_sanitize_address' attribute only applies to functions}}
-
class NoanalFoo {
private:
int test_field NO_SANITIZE_ADDRESS; // \
diff --git a/test/SemaCXX/attr-no-sanitize.cpp b/test/SemaCXX/attr-no-sanitize.cpp
index 741f76062821..965def6f0254 100644
--- a/test/SemaCXX/attr-no-sanitize.cpp
+++ b/test/SemaCXX/attr-no-sanitize.cpp
@@ -2,8 +2,6 @@
// RUN: not %clang_cc1 -std=c++11 -ast-dump %s | FileCheck --check-prefix=DUMP %s
// RUN: not %clang_cc1 -std=c++11 -ast-print %s | FileCheck --check-prefix=PRINT %s
-int v1 __attribute__((no_sanitize("address"))); // expected-error{{'no_sanitize' attribute only applies to functions and methods}}
-
int f1() __attribute__((no_sanitize)); // expected-error{{'no_sanitize' attribute takes at least 1 argument}}
int f2() __attribute__((no_sanitize(1))); // expected-error{{'no_sanitize' attribute requires a string}}
diff --git a/test/SemaCXX/attr-noreturn.cpp b/test/SemaCXX/attr-noreturn.cpp
index 6df008dffa81..a8e71db73702 100644
--- a/test/SemaCXX/attr-noreturn.cpp
+++ b/test/SemaCXX/attr-noreturn.cpp
@@ -167,7 +167,7 @@ namespace destructor_tests {
// PR5620
void f0() __attribute__((__noreturn__));
-void f1(void (*)());
+void f1(void (*)());
void f2() { f1(f0); }
// Taking the address of a noreturn function
diff --git a/test/SemaCXX/attr-require-constant-initialization.cpp b/test/SemaCXX/attr-require-constant-initialization.cpp
new file mode 100644
index 000000000000..73f81cb1fc1d
--- /dev/null
+++ b/test/SemaCXX/attr-require-constant-initialization.cpp
@@ -0,0 +1,282 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -DTEST_ONE -std=c++03 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -DTEST_ONE -std=c++11 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -DTEST_ONE -std=c++14 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -DTEST_TWO \
+// RUN: -Wglobal-constructors -std=c++14 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -DTEST_THREE -xc %s
+
+#define ATTR __attribute__((require_constant_initialization)) // expected-note 0+ {{expanded from macro}}
+
+int ReturnInt();
+
+struct PODType {
+ int value;
+ int value2;
+};
+
+#if defined(__cplusplus)
+
+#if __cplusplus >= 201103L
+struct LitType {
+ constexpr LitType() : value(0) {}
+ constexpr LitType(int x) : value(x) {}
+ LitType(void *) : value(-1) {}
+ int value;
+};
+#endif
+
+struct NonLit {
+#if __cplusplus >= 201402L
+ constexpr NonLit() : value(0) {}
+ constexpr NonLit(int x) : value(x) {}
+#else
+ NonLit() : value(0) {}
+ NonLit(int x) : value(x) {}
+#endif
+ NonLit(void *) : value(-1) {}
+ ~NonLit() {}
+ int value;
+};
+
+struct StoresNonLit {
+#if __cplusplus >= 201402L
+ constexpr StoresNonLit() : obj() {}
+ constexpr StoresNonLit(int x) : obj(x) {}
+#else
+ StoresNonLit() : obj() {}
+ StoresNonLit(int x) : obj(x) {}
+#endif
+ StoresNonLit(void *p) : obj(p) {}
+ NonLit obj;
+};
+
+#endif // __cplusplus
+
+
+#if defined(TEST_ONE) // Test semantics of attribute
+
+// Test diagnostics when attribute is applied to non-static declarations.
+void test_func_local(ATTR int param) { // expected-error {{only applies to variables with static or thread}}
+ ATTR int x = 42; // expected-error {{only applies to variables with static or thread}}
+ ATTR extern int y;
+}
+struct ATTR class_mem { // expected-error {{only applies to variables with static or thread}}
+ ATTR int x; // expected-error {{only applies to variables with static or thread}}
+};
+
+// [basic.start.static]p2.1
+// if each full-expression (including implicit conversions) that appears in
+// the initializer of a reference with static or thread storage duration is
+// a constant expression (5.20) and the reference is bound to a glvalue
+// designating an object with static storage duration, to a temporary object
+// (see 12.2) or subobject thereof, or to a function;
+
+// Test binding to a static glvalue
+const int glvalue_int = 42;
+const int glvalue_int2 = ReturnInt();
+ATTR const int &glvalue_ref ATTR = glvalue_int;
+ATTR const int &glvalue_ref2 ATTR = glvalue_int2;
+ATTR __thread const int &glvalue_ref_tl = glvalue_int;
+
+void test_basic_start_static_2_1() {
+ const int non_global = 42;
+ ATTR static const int &local_init = non_global; // expected-error {{variable does not have a constant initializer}}
+ // expected-note@-1 {{required by 'require_constant_initializer' attribute here}}
+ ATTR static const int &global_init = glvalue_int;
+ ATTR static const int &temp_init = 42;
+}
+
+ATTR const int &temp_ref = 42;
+ATTR const int &temp_ref2 = ReturnInt(); // expected-error {{variable does not have a constant initializer}}
+// expected-note@-1 {{required by 'require_constant_initializer' attribute here}}
+ATTR const NonLit &nl_temp_ref = 42; // expected-error {{variable does not have a constant initializer}}
+// expected-note@-1 {{required by 'require_constant_initializer' attribute here}}
+
+#if __cplusplus >= 201103L
+ATTR const LitType &lit_temp_ref = 42;
+ATTR const int &subobj_ref = LitType{}.value;
+#endif
+
+ATTR const int &nl_subobj_ref = NonLit().value; // expected-error {{variable does not have a constant initializer}}
+// expected-note@-1 {{required by 'require_constant_initializer' attribute here}}
+
+struct TT1 {
+ ATTR static const int &no_init;
+ ATTR static const int &glvalue_init;
+ ATTR static const int &temp_init;
+ ATTR static const int &subobj_init;
+#if __cplusplus >= 201103L
+ ATTR static thread_local const int &tl_glvalue_init;
+ ATTR static thread_local const int &tl_temp_init; // expected-note {{required by 'require_constant_initializer' attribute here}}
+#endif
+};
+const int &TT1::glvalue_init = glvalue_int;
+const int &TT1::temp_init = 42;
+const int &TT1::subobj_init = PODType().value;
+#if __cplusplus >= 201103L
+thread_local const int &TT1::tl_glvalue_init = glvalue_int;
+thread_local const int &TT1::tl_temp_init = 42; // expected-error {{variable does not have a constant initializer}}
+#endif
+
+// [basic.start.static]p2.2
+// if an object with static or thread storage duration is initialized by a
+// constructor call, and if the initialization full-expression is a constant
+// initializer for the object;
+
+void test_basic_start_static_2_2() {
+#if __cplusplus < 201103L
+ ATTR static PODType pod;
+#else
+ ATTR static PODType pod; // expected-error {{variable does not have a constant initializer}}
+// expected-note@-1 {{required by 'require_constant_initializer' attribute here}}
+#endif
+ ATTR static PODType pot2 = {ReturnInt()}; // expected-error {{variable does not have a constant initializer}}
+ // expected-note@-1 {{required by 'require_constant_initializer' attribute here}}
+
+#if __cplusplus >= 201103L
+ constexpr LitType l;
+ ATTR static LitType static_lit = l;
+ ATTR static LitType static_lit2 = (void *)0; // expected-error {{variable does not have a constant initializer}}
+ // expected-note@-1 {{required by 'require_constant_initializer' attribute here}}
+ ATTR static LitType static_lit3 = ReturnInt(); // expected-error {{variable does not have a constant initializer}}
+ // expected-note@-1 {{required by 'require_constant_initializer' attribute here}}
+ ATTR thread_local LitType tls = 42;
+#endif
+}
+
+struct TT2 {
+ ATTR static PODType pod_noinit;
+#if __cplusplus >= 201103L
+// expected-note@-2 {{required by 'require_constant_initializer' attribute here}}
+#endif
+ ATTR static PODType pod_copy_init; // expected-note {{required by 'require_constant_initializer' attribute here}}
+#if __cplusplus >= 201402L
+ ATTR static constexpr LitType lit = {};
+ ATTR static const NonLit non_lit;
+ ATTR static const NonLit non_lit_list_init;
+ ATTR static const NonLit non_lit_copy_init; // expected-note {{required by 'require_constant_initializer' attribute here}}
+#endif
+};
+PODType TT2::pod_noinit;
+#if __cplusplus >= 201103L
+// expected-error@-2 {{variable does not have a constant initializer}}
+#endif
+PODType TT2::pod_copy_init(TT2::pod_noinit); // expected-error {{variable does not have a constant initializer}}
+#if __cplusplus >= 201402L
+const NonLit TT2::non_lit(42);
+const NonLit TT2::non_lit_list_init = {42};
+const NonLit TT2::non_lit_copy_init = 42; // expected-error {{variable does not have a constant initializer}}
+#endif
+
+#if __cplusplus >= 201103L
+ATTR LitType lit_ctor;
+ATTR LitType lit_ctor2{};
+ATTR LitType lit_ctor3 = {};
+ATTR __thread LitType lit_ctor_tl = {};
+
+#if __cplusplus >= 201402L
+ATTR NonLit nl_ctor;
+ATTR NonLit nl_ctor2{};
+ATTR NonLit nl_ctor3 = {};
+ATTR thread_local NonLit nl_ctor_tl = {};
+ATTR StoresNonLit snl;
+#else
+ATTR NonLit nl_ctor; // expected-error {{variable does not have a constant initializer}}
+// expected-note@-1 {{required by 'require_constant_initializer' attribute here}}
+ATTR NonLit nl_ctor2{}; // expected-error {{variable does not have a constant initializer}}
+// expected-note@-1 {{required by 'require_constant_initializer' attribute here}}
+ATTR NonLit nl_ctor3 = {}; // expected-error {{variable does not have a constant initializer}}
+// expected-note@-1 {{required by 'require_constant_initializer' attribute here}}
+ATTR thread_local NonLit nl_ctor_tl = {}; // expected-error {{variable does not have a constant initializer}}
+// expected-note@-1 {{required by 'require_constant_initializer' attribute here}}
+ATTR StoresNonLit snl; // expected-error {{variable does not have a constant initializer}}
+// expected-note@-1 {{required by 'require_constant_initializer' attribute here}}
+#endif
+
+// Non-literal types cannot appear in the initializer of a non-literal type.
+ATTR int nl_in_init = NonLit{42}.value; // expected-error {{variable does not have a constant initializer}}
+// expected-note@-1 {{required by 'require_constant_initializer' attribute here}}
+ATTR int lit_in_init = LitType{42}.value;
+#endif
+
+// [basic.start.static]p2.3
+// if an object with static or thread storage duration is not initialized by a
+// constructor call and if either the object is value-initialized or every
+// full-expression that appears in its initializer is a constant expression.
+void test_basic_start_static_2_3() {
+ ATTR static int static_local = 42;
+ ATTR static int static_local2; // zero-initialization takes place
+#if __cplusplus >= 201103L
+ ATTR thread_local int tl_local = 42;
+#endif
+}
+
+ATTR int no_init; // zero initialization takes place
+ATTR int arg_init = 42;
+ATTR PODType pod_init = {};
+ATTR PODType pod_missing_init = {42 /* should have second arg */};
+ATTR PODType pod_full_init = {1, 2};
+ATTR PODType pod_non_constexpr_init = {1, ReturnInt()}; // expected-error {{variable does not have a constant initializer}}
+// expected-note@-1 {{required by 'require_constant_initializer' attribute here}}
+
+#if __cplusplus >= 201103L
+ATTR int val_init{};
+ATTR int brace_init = {};
+#endif
+
+ATTR __thread int tl_init = 0;
+typedef const char *StrType;
+
+#if __cplusplus >= 201103L
+
+// Test that the validity of the selected constructor is checked, not just the
+// initializer
+struct NotC {
+ constexpr NotC(void *) {}
+ NotC(int) {}
+};
+template <class T>
+struct TestCtor {
+ constexpr TestCtor(int x) : value(x) {}
+ T value;
+};
+ATTR TestCtor<NotC> t(42); // expected-error {{variable does not have a constant initializer}}
+// expected-note@-1 {{required by 'require_constant_initializer' attribute here}}
+#endif
+
+// Test various array types
+ATTR const char *foo[] = {"abc", "def"};
+ATTR PODType bar[] = {{}, {123, 456}};
+
+#elif defined(TEST_TWO) // Test for duplicate warnings
+struct NotC {
+ constexpr NotC(void *) {}
+ NotC(int) {} // expected-note 2 {{declared here}}
+};
+template <class T>
+struct TestCtor {
+ constexpr TestCtor(int x) : value(x) {} // expected-note 2 {{non-constexpr constructor}}
+ T value;
+};
+
+ATTR LitType non_const_lit(nullptr); // expected-error {{variable does not have a constant initializer}}
+// expected-note@-1 {{required by 'require_constant_initializer' attribute here}}
+ATTR NonLit non_const(nullptr); // expected-error {{variable does not have a constant initializer}}
+// expected-warning@-1 {{declaration requires a global destructor}}
+// expected-note@-2 {{required by 'require_constant_initializer' attribute here}}
+LitType const_init_lit(nullptr); // expected-warning {{declaration requires a global constructor}}
+NonLit const_init{42}; // expected-warning {{declaration requires a global destructor}}
+constexpr TestCtor<NotC> inval_constexpr(42); // expected-error {{must be initialized by a constant expression}}
+// expected-note@-1 {{in call to 'TestCtor(42)'}}
+ATTR constexpr TestCtor<NotC> inval_constexpr2(42); // expected-error {{must be initialized by a constant expression}}
+// expected-note@-1 {{in call to 'TestCtor(42)'}}
+
+#elif defined(TEST_THREE)
+#if defined(__cplusplus)
+#error This test requires C
+#endif
+// Test that using the attribute in C results in a diagnostic
+ATTR int x = 0; // expected-warning {{attribute ignored}}
+#else
+#error No test case specified
+#endif // defined(TEST_N)
diff --git a/test/SemaCXX/attr-swiftcall.cpp b/test/SemaCXX/attr-swiftcall.cpp
index fd17aae18523..eb9538e31044 100644
--- a/test/SemaCXX/attr-swiftcall.cpp
+++ b/test/SemaCXX/attr-swiftcall.cpp
@@ -17,16 +17,16 @@ void indirect_result_single(INDIRECT_RESULT void *out) SWIFTCALL;
void indirect_result_multiple(INDIRECT_RESULT void *out1, INDIRECT_RESULT void *out2) SWIFTCALL;
void error_result_nonswift(ERROR_RESULT void **error); // expected-error {{'swift_error_result' parameter can only be used with swiftcall calling convention}} expected-error{{'swift_error_result' parameter must follow 'swift_context' parameter}}
-void error_result_bad_position(ERROR_RESULT void **error, int last) SWIFTCALL; // expected-error {{'swift_error_result' parameter must be last parameter of function}}
void error_result_bad_position2(int first, ERROR_RESULT void **error) SWIFTCALL; // expected-error {{'swift_error_result' parameter must follow 'swift_context' parameter}}
void error_result_bad_type(CONTEXT void *context, ERROR_RESULT int error) SWIFTCALL; // expected-error {{'swift_error_result' parameter must have pointer to unqualified pointer type; type here is 'int'}}
void error_result_bad_type2(CONTEXT void *context, ERROR_RESULT int *error) SWIFTCALL; // expected-error {{'swift_error_result' parameter must have pointer to unqualified pointer type; type here is 'int *'}}
void error_result_okay(int a, int b, CONTEXT void *context, ERROR_RESULT void **error) SWIFTCALL;
+void error_result_okay(CONTEXT void *context, ERROR_RESULT void **error, void *selfType, char **selfWitnessTable) SWIFTCALL;
void context_nonswift(CONTEXT void *context); // expected-error {{'swift_context' parameter can only be used with swiftcall calling convention}}
-void context_bad_position(CONTEXT void *context, int x) SWIFTCALL; // expected-error {{'swift_context' parameter can only be followed by 'swift_error_result' parameter}}
void context_bad_type(CONTEXT int context) SWIFTCALL; // expected-error {{'swift_context' parameter must have pointer type; type here is 'int'}}
void context_okay(CONTEXT void *context) SWIFTCALL;
+void context_okay(CONTEXT void *context, void *selfType, char **selfWitnessTable) SWIFTCALL;
template <class T> void indirect_result_temp_okay1(INDIRECT_RESULT T *out) SWIFTCALL;
template <class T> void indirect_result_temp_okay2(INDIRECT_RESULT T out) SWIFTCALL; // expected-note {{candidate template ignored: substitution failure [with T = int]: 'swift_indirect_result' parameter must have pointer type; type here is 'int'}}
diff --git a/test/SemaCXX/builtin-exception-spec.cpp b/test/SemaCXX/builtin-exception-spec.cpp
index 590cd3c35d4e..9845172bcd72 100644
--- a/test/SemaCXX/builtin-exception-spec.cpp
+++ b/test/SemaCXX/builtin-exception-spec.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -isystem %S/Inputs -fsyntax-only -verify %s
+// RUN: %clang_cc1 -isystem %S/Inputs -fsyntax-only -verify -std=c++1z %s
// expected-no-diagnostics
#include <malloc.h>
diff --git a/test/SemaCXX/builtins.cpp b/test/SemaCXX/builtins.cpp
index 69bdfa614517..f26931b55bdb 100644
--- a/test/SemaCXX/builtins.cpp
+++ b/test/SemaCXX/builtins.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 %s -fsyntax-only -verify -std=c++11
+// RUN: %clang_cc1 %s -fsyntax-only -verify -std=c++11 -fcxx-exceptions
+// RUN: %clang_cc1 %s -fsyntax-only -verify -std=c++1z -fcxx-exceptions
typedef const struct __CFString * CFStringRef;
#define CFSTR __builtin___CFStringMakeConstantString
@@ -44,3 +45,11 @@ void no_ms_builtins() {
__noop(1); // expected-error {{use of undeclared}}
__debugbreak(); // expected-error {{use of undeclared}}
}
+
+struct FILE;
+extern "C" int vfprintf(FILE *__restrict, const char *__restrict,
+ __builtin_va_list va);
+
+void synchronize_args() {
+ __sync_synchronize(0); // expected-error {{too many arguments}}
+}
diff --git a/test/SemaCXX/compare.cpp b/test/SemaCXX/compare.cpp
index ef0a524f92f1..0528b044fb1f 100644
--- a/test/SemaCXX/compare.cpp
+++ b/test/SemaCXX/compare.cpp
@@ -201,9 +201,10 @@ int test1(int i) {
enum E { e };
void test2(int i, void *vp) {
+ if (&i == vp) { } // ok
if (test1 == vp) { } // expected-warning{{equality comparison between function pointer and void pointer}}
if (test1 == e) { } // expected-error{{comparison between pointer and integer}}
- if (vp < 0) { }
+ if (vp < 0) { } // expected-error {{comparison between pointer and zero}}
if (test1 < e) { } // expected-error{{comparison between pointer and integer}}
}
diff --git a/test/SemaCXX/composite-pointer-type.cpp b/test/SemaCXX/composite-pointer-type.cpp
index 06fc8f43855d..dddf424caa2e 100644
--- a/test/SemaCXX/composite-pointer-type.cpp
+++ b/test/SemaCXX/composite-pointer-type.cpp
@@ -53,8 +53,8 @@ bool f(Matrix4 m1, const Matrix4 m2) {
// PR6346
bool f1(bool b, void **p, const void **q) {
- if (p == q) // expected-warning{{comparison of distinct pointer types ('void **' and 'const void **') uses non-standard composite pointer type 'const void *const *'}}
+ if (p == q)
return false;
- return b? p : q; // expected-warning{{incompatible operand types ('void **' and 'const void **') use non-standard composite pointer type 'const void *const *'}}
+ return b? p : q;
}
diff --git a/test/SemaCXX/compound-literal.cpp b/test/SemaCXX/compound-literal.cpp
index 3fc61505dfee..5480b1fef44d 100644
--- a/test/SemaCXX/compound-literal.cpp
+++ b/test/SemaCXX/compound-literal.cpp
@@ -86,3 +86,13 @@ int PR17415 = (int){PR17415}; // expected-error {{initializer element is not a c
template<unsigned> struct Value { };
template<typename T>
int &check_narrowed(Value<sizeof((T){1.1})>);
+
+#if __cplusplus >= 201103L
+// Compound literals in global lambdas have automatic storage duration
+// and are not subject to the constant-initialization rules.
+int computed_with_lambda = [] {
+ int x = 5;
+ int result = ((int[]) { x, x + 2, x + 4, x + 6 })[0];
+ return result;
+}();
+#endif
diff --git a/test/SemaCXX/conditional-expr.cpp b/test/SemaCXX/conditional-expr.cpp
index c12efc0be7ef..5025990cfd36 100644
--- a/test/SemaCXX/conditional-expr.cpp
+++ b/test/SemaCXX/conditional-expr.cpp
@@ -262,7 +262,7 @@ namespace PR6757 {
struct Foo2 { };
struct Foo3 {
- Foo3();
+ Foo3(); // expected-note{{requires 0 arguments}}
Foo3(Foo3&); // expected-note{{would lose const qualifier}}
};
diff --git a/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp
index e2b3f091f70f..581a524339e7 100644
--- a/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/test/SemaCXX/constant-expression-cxx11.cpp
@@ -279,17 +279,17 @@ static_assert(&s.x > &s.y, "false"); // expected-error {{false}}
static_assert(0 == &y, "false"); // expected-error {{false}}
static_assert(0 != &y, "");
-constexpr bool n3 = 0 <= &y; // expected-error {{must be initialized by a constant expression}}
-constexpr bool n4 = 0 >= &y; // expected-error {{must be initialized by a constant expression}}
-constexpr bool n5 = 0 < &y; // expected-error {{must be initialized by a constant expression}}
-constexpr bool n6 = 0 > &y; // expected-error {{must be initialized by a constant expression}}
+constexpr bool n3 = (int*)0 <= &y; // expected-error {{must be initialized by a constant expression}}
+constexpr bool n4 = (int*)0 >= &y; // expected-error {{must be initialized by a constant expression}}
+constexpr bool n5 = (int*)0 < &y; // expected-error {{must be initialized by a constant expression}}
+constexpr bool n6 = (int*)0 > &y; // expected-error {{must be initialized by a constant expression}}
static_assert(&x == 0, "false"); // expected-error {{false}}
static_assert(&x != 0, "");
-constexpr bool n9 = &x <= 0; // expected-error {{must be initialized by a constant expression}}
-constexpr bool n10 = &x >= 0; // expected-error {{must be initialized by a constant expression}}
-constexpr bool n11 = &x < 0; // expected-error {{must be initialized by a constant expression}}
-constexpr bool n12 = &x > 0; // expected-error {{must be initialized by a constant expression}}
+constexpr bool n9 = &x <= (int*)0; // expected-error {{must be initialized by a constant expression}}
+constexpr bool n10 = &x >= (int*)0; // expected-error {{must be initialized by a constant expression}}
+constexpr bool n11 = &x < (int*)0; // expected-error {{must be initialized by a constant expression}}
+constexpr bool n12 = &x > (int*)0; // expected-error {{must be initialized by a constant expression}}
static_assert(&x == &x, "");
static_assert(&x != &x, "false"); // expected-error {{false}}
@@ -386,6 +386,18 @@ namespace FakeInitList {
constexpr init_list_2_init_list_3_ints ils = { { { { 1, 2, 3 } }, { { 4, 5, 6 } } } };
}
+namespace ConstAddedByReference {
+ const int &r = (0);
+ constexpr int n = r;
+
+ struct A { constexpr operator int() const { return 0; }};
+ struct B { constexpr operator const int() const { return 0; }};
+ const int &ra = A();
+ const int &rb = B();
+ constexpr int na = ra;
+ constexpr int nb = rb;
+}
+
}
constexpr int strcmp_ce(const char *p, const char *q) {
@@ -554,6 +566,21 @@ struct ArrayRVal {
};
static_assert(ArrayRVal().elems[3].f() == 0, "");
+namespace CopyCtor {
+ struct A {
+ constexpr A() {}
+ constexpr A(const A &) {}
+ };
+ struct B {
+ A a;
+ int arr[10];
+ };
+ constexpr B b{{}, {1, 2, 3, 4, 5}};
+ constexpr B c = b;
+ static_assert(c.arr[2] == 3, "");
+ static_assert(c.arr[7] == 0, "");
+}
+
constexpr int selfref[2][2][2] = {
selfref[1][1][1] + 1, selfref[0][0][0] + 1,
selfref[1][0][1] + 1, selfref[0][1][0] + 1,
@@ -1156,7 +1183,7 @@ constexpr int m1b = const_cast<const int&>(n1); // expected-error {{constant exp
constexpr int m2b = const_cast<const int&>(n2); // expected-error {{constant expression}} expected-note {{read of volatile object 'n2'}}
struct T { int n; };
-const T t = { 42 }; // expected-note {{declared here}}
+const T t = { 42 };
constexpr int f(volatile int &&r) {
return r; // expected-note {{read of volatile-qualified type 'volatile int'}}
@@ -1168,7 +1195,7 @@ struct S {
int j : f(0); // expected-error {{constant expression}} expected-note {{in call to 'f(0)'}}
int k : g(0); // expected-error {{constant expression}} expected-note {{temporary created here}} expected-note {{in call to 'g(0)'}}
int l : n3; // expected-error {{constant expression}} expected-note {{read of non-const variable}}
- int m : t.n; // expected-error {{constant expression}} expected-note {{read of non-constexpr variable}}
+ int m : t.n; // expected-warning{{width of bit-field 'm' (42 bits)}} expected-warning{{expression is not an integral constant expression}} expected-note{{read of non-constexpr variable 't' is not allowed}}
};
}
@@ -1467,13 +1494,26 @@ namespace VLASizeof {
}
namespace CompoundLiteral {
- // FIXME:
- // We don't model the semantics of this correctly: the compound literal is
- // represented as a prvalue in the AST, but actually behaves like an lvalue.
- // We treat the compound literal as a temporary and refuse to produce a
- // pointer to it. This is OK: we're not required to treat this as a constant
- // in C++, and in C we model compound literals as lvalues.
- constexpr int *p = (int*)(int[1]){0}; // expected-warning {{C99}} expected-error {{constant expression}} expected-note 2{{temporary}}
+ // Matching GCC, file-scope array compound literals initialized by constants
+ // are lifetime-extended.
+ constexpr int *p = (int*)(int[1]){3}; // expected-warning {{C99}}
+ static_assert(*p == 3, "");
+ static_assert((int[2]){1, 2}[1] == 2, ""); // expected-warning {{C99}}
+
+ // Other kinds are not.
+ struct X { int a[2]; };
+ constexpr int *n = (X){1, 2}.a; // expected-warning {{C99}} expected-warning {{temporary array}}
+ // 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}}
+ // expected-error@-1 {{constant expression}}
+ // expected-note@-2 {{pointer to subobject of temporary}}
+ // expected-note@-3 {{temporary created here}}
+ static_assert((int[2]){1, 2}[1] == 2, ""); // expected-warning {{C99}}
+ }
}
namespace Vector {
@@ -1862,8 +1902,8 @@ namespace ZeroSizeTypes {
namespace BadDefaultInit {
template<int N> struct X { static const int n = N; };
- struct A {
- int k = // expected-error {{cannot use defaulted default constructor of 'A' within the class outside of member functions because 'k' has an initializer}}
+ struct A { // expected-error {{default member initializer for 'k' needed within definition of enclosing class}}
+ int k = // expected-note {{default member initializer declared here}}
X<A().k>::n; // expected-error {{not a constant expression}} expected-note {{implicit default constructor for 'BadDefaultInit::A' first required here}}
};
@@ -2066,3 +2106,33 @@ namespace InheritedCtor {
constexpr Z z(1);
static_assert(z.w == 1 && z.x == 2 && z.y == 3 && z.z == 4, "");
}
+
+
+namespace PR28366 {
+namespace ns1 {
+
+void f(char c) { //expected-note2{{declared here}}
+ struct X {
+ static constexpr char f() { //expected-error{{never produces a constant expression}}
+ return c; //expected-error{{reference to local}} expected-note{{non-const variable}}
+ }
+ };
+ int I = X::f();
+}
+
+void g() {
+ const int c = 'c';
+ static const int d = 'd';
+ struct X {
+ static constexpr int f() {
+ return c + d;
+ }
+ };
+ static_assert(X::f() == 'c' + 'd',"");
+}
+
+
+} // end ns1
+
+} //end ns PR28366
+
diff --git a/test/SemaCXX/constant-expression-cxx1y.cpp b/test/SemaCXX/constant-expression-cxx1y.cpp
index f8103224af89..dfdf50ad5484 100644
--- a/test/SemaCXX/constant-expression-cxx1y.cpp
+++ b/test/SemaCXX/constant-expression-cxx1y.cpp
@@ -957,3 +957,23 @@ namespace PR27989 {
}
static_assert(f(0) == 1, "");
}
+
+namespace const_char {
+template <int N>
+constexpr int sum(const char (&Arr)[N]) {
+ int S = 0;
+ for (unsigned I = 0; I != N; ++I)
+ S += Arr[I]; // expected-note 2{{read of non-constexpr variable 'Cs' is not allowed}}
+ return S;
+}
+
+// As an extension, we support evaluating some things that are `const` as though
+// they were `constexpr` when folding, but it should not be allowed in normal
+// constexpr evaluation.
+const char Cs[] = {'a', 'b'};
+void foo() __attribute__((enable_if(sum(Cs) == 'a' + 'b', "")));
+void run() { foo(); }
+
+static_assert(sum(Cs) == 'a' + 'b', ""); // expected-error{{not an integral constant expression}} expected-note{{in call to 'sum(Cs)'}}
+constexpr int S = sum(Cs); // expected-error{{must be initialized by a constant expression}} expected-note{{in call}}
+}
diff --git a/test/SemaCXX/constant-expression-cxx1z.cpp b/test/SemaCXX/constant-expression-cxx1z.cpp
index e84de44d374a..a48c9b11b886 100644
--- a/test/SemaCXX/constant-expression-cxx1z.cpp
+++ b/test/SemaCXX/constant-expression-cxx1z.cpp
@@ -25,3 +25,24 @@ namespace BaseClassAggregateInit {
constexpr D d5 = { __INT_MAX__ }; // expected-error {{must be initialized by a constant expression}}
// expected-note-re@-1 {{in call to 'A({{.*}})'}}
}
+
+namespace NoexceptFunctionTypes {
+ template<typename T> constexpr bool f() noexcept(true) { return true; }
+ constexpr bool (*fp)() = f<int>;
+ static_assert(f<int>());
+ static_assert(fp());
+
+ template<typename T> struct A {
+ constexpr bool f() noexcept(true) { return true; }
+ constexpr bool g() { return f(); }
+ constexpr bool operator()() const noexcept(true) { return true; }
+ };
+ static_assert(A<int>().f());
+ static_assert(A<int>().g());
+ static_assert(A<int>()());
+}
+
+namespace Cxx17CD_NB_GB19 {
+ const int &r = 0;
+ constexpr int n = r;
+}
diff --git a/test/SemaCXX/constexpr-string.cpp b/test/SemaCXX/constexpr-string.cpp
new file mode 100644
index 000000000000..944038bc163a
--- /dev/null
+++ b/test/SemaCXX/constexpr-string.cpp
@@ -0,0 +1,201 @@
+// RUN: %clang_cc1 %s -std=c++1z -fsyntax-only -verify -pedantic
+// RUN: %clang_cc1 %s -std=c++1z -fsyntax-only -verify -pedantic -fno-signed-char
+// RUN: %clang_cc1 %s -std=c++1z -fsyntax-only -verify -pedantic -fno-wchar -Dwchar_t=__WCHAR_TYPE__
+
+# 6 "/usr/include/string.h" 1 3 4
+extern "C" {
+ typedef decltype(sizeof(int)) size_t;
+
+ extern size_t strlen(const char *p);
+
+ extern int strcmp(const char *s1, const char *s2);
+ extern int strncmp(const char *s1, const char *s2, size_t n);
+ extern int memcmp(const void *s1, const void *s2, size_t n);
+
+ extern char *strchr(const char *s, int c);
+ extern void *memchr(const void *s, int c, size_t n);
+}
+# 19 "SemaCXX/constexpr-string.cpp" 2
+
+# 21 "/usr/include/wchar.h" 1 3 4
+extern "C" {
+ extern size_t wcslen(const wchar_t *p);
+
+ extern int wcscmp(const wchar_t *s1, const wchar_t *s2);
+ extern int wcsncmp(const wchar_t *s1, const wchar_t *s2, size_t n);
+ extern int wmemcmp(const wchar_t *s1, const wchar_t *s2, size_t n);
+
+ extern wchar_t *wcschr(const wchar_t *s, wchar_t c);
+ extern wchar_t *wmemchr(const wchar_t *s, wchar_t c, size_t n);
+}
+
+# 33 "SemaCXX/constexpr-string.cpp" 2
+namespace Strlen {
+ constexpr int n = __builtin_strlen("hello"); // ok
+ static_assert(n == 5);
+ constexpr int wn = __builtin_wcslen(L"hello"); // ok
+ static_assert(wn == 5);
+ constexpr int m = strlen("hello"); // expected-error {{constant expression}} expected-note {{non-constexpr function 'strlen' cannot be used in a constant expression}}
+ constexpr int wm = wcslen(L"hello"); // expected-error {{constant expression}} expected-note {{non-constexpr function 'wcslen' cannot be used in a constant expression}}
+
+ // Make sure we can evaluate a call to strlen.
+ int arr[3]; // expected-note 2{{here}}
+ int k = arr[strlen("hello")]; // expected-warning {{array index 5}}
+ int wk = arr[wcslen(L"hello")]; // expected-warning {{array index 5}}
+}
+
+namespace StrcmpEtc {
+ constexpr char kFoobar[6] = {'f','o','o','b','a','r'};
+ constexpr char kFoobazfoobar[12] = {'f','o','o','b','a','z','f','o','o','b','a','r'};
+
+ static_assert(__builtin_strcmp("abab", "abab") == 0);
+ static_assert(__builtin_strcmp("abab", "abba") == -1);
+ 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("abab\0banana", "abab") == 0);
+ static_assert(__builtin_strcmp("abab", "abab\0banana") == 0);
+ static_assert(__builtin_strcmp("abab\0banana", "abab\0canada") == 0);
+ static_assert(__builtin_strcmp(0, "abab") == 0); // expected-error {{not an integral constant}} expected-note {{dereferenced null}}
+ static_assert(__builtin_strcmp("abab", 0) == 0); // expected-error {{not an integral constant}} expected-note {{dereferenced null}}
+
+ static_assert(__builtin_strcmp(kFoobar, kFoobazfoobar) == -1); // FIXME: Should we reject this?
+ static_assert(__builtin_strcmp(kFoobar, kFoobazfoobar + 6) == 0); // expected-error {{not an integral constant}} expected-note {{dereferenced one-past-the-end}}
+
+ static_assert(__builtin_strncmp("abaa", "abba", 5) == -1);
+ static_assert(__builtin_strncmp("abaa", "abba", 4) == -1);
+ static_assert(__builtin_strncmp("abaa", "abba", 3) == -1);
+ static_assert(__builtin_strncmp("abaa", "abba", 2) == 0);
+ static_assert(__builtin_strncmp("abaa", "abba", 1) == 0);
+ static_assert(__builtin_strncmp("abaa", "abba", 0) == 0);
+ static_assert(__builtin_strncmp(0, 0, 0) == 0);
+ static_assert(__builtin_strncmp("abab\0banana", "abab\0canada", 100) == 0);
+
+ static_assert(__builtin_strncmp(kFoobar, kFoobazfoobar, 6) == -1);
+ static_assert(__builtin_strncmp(kFoobar, kFoobazfoobar, 7) == -1); // FIXME: Should we reject this?
+ static_assert(__builtin_strncmp(kFoobar, kFoobazfoobar + 6, 6) == 0);
+ static_assert(__builtin_strncmp(kFoobar, kFoobazfoobar + 6, 7) == 0); // expected-error {{not an integral constant}} expected-note {{dereferenced one-past-the-end}}
+
+ static_assert(__builtin_memcmp("abaa", "abba", 3) == -1);
+ static_assert(__builtin_memcmp("abaa", "abba", 2) == 0);
+ 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?
+ static_assert(__builtin_memcmp("abab\0banana", "abab\0canada", 7) == -1);
+ static_assert(__builtin_memcmp("abab\0banana", "abab\0canada", 6) == -1);
+ static_assert(__builtin_memcmp("abab\0banana", "abab\0canada", 5) == 0);
+
+ constexpr int a = strcmp("hello", "world"); // expected-error {{constant expression}} expected-note {{non-constexpr function 'strcmp' cannot be used in a constant expression}}
+ constexpr int b = strncmp("hello", "world", 3); // expected-error {{constant expression}} expected-note {{non-constexpr function 'strncmp' cannot be used in a constant expression}}
+ constexpr int c = memcmp("hello", "world", 3); // expected-error {{constant expression}} expected-note {{non-constexpr function 'memcmp' cannot be used in a constant expression}}
+}
+
+namespace WcscmpEtc {
+ constexpr wchar_t kFoobar[6] = {L'f',L'o',L'o',L'b',L'a',L'r'};
+ constexpr wchar_t kFoobazfoobar[12] = {L'f',L'o',L'o',L'b',L'a',L'z',L'f',L'o',L'o',L'b',L'a',L'r'};
+
+ static_assert(__builtin_wcscmp(L"abab", L"abab") == 0);
+ static_assert(__builtin_wcscmp(L"abab", L"abba") == -1);
+ static_assert(__builtin_wcscmp(L"abab", L"abaa") == 1);
+ static_assert(__builtin_wcscmp(L"ababa", L"abab") == 1);
+ static_assert(__builtin_wcscmp(L"abab", L"ababa") == -1);
+ 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);
+ 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}}
+
+ static_assert(__builtin_wcscmp(kFoobar, kFoobazfoobar) == -1); // FIXME: Should we reject this?
+ static_assert(__builtin_wcscmp(kFoobar, kFoobazfoobar + 6) == 0); // expected-error {{not an integral constant}} expected-note {{dereferenced one-past-the-end}}
+
+ static_assert(__builtin_wcsncmp(L"abaa", L"abba", 5) == -1);
+ static_assert(__builtin_wcsncmp(L"abaa", L"abba", 4) == -1);
+ static_assert(__builtin_wcsncmp(L"abaa", L"abba", 3) == -1);
+ static_assert(__builtin_wcsncmp(L"abaa", L"abba", 2) == 0);
+ static_assert(__builtin_wcsncmp(L"abaa", L"abba", 1) == 0);
+ 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);
+
+ static_assert(__builtin_wcsncmp(kFoobar, kFoobazfoobar, 6) == -1);
+ static_assert(__builtin_wcsncmp(kFoobar, kFoobazfoobar, 7) == -1); // FIXME: Should we reject this?
+ static_assert(__builtin_wcsncmp(kFoobar, kFoobazfoobar + 6, 6) == 0);
+ static_assert(__builtin_wcsncmp(kFoobar, kFoobazfoobar + 6, 7) == 0); // expected-error {{not an integral constant}} expected-note {{dereferenced one-past-the-end}}
+
+ 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);
+ 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);
+ static_assert(__builtin_wmemcmp(L"abab\0banana", L"abab\0canada", 6) == -1);
+ static_assert(__builtin_wmemcmp(L"abab\0banana", L"abab\0canada", 5) == 0);
+
+ constexpr int a = wcscmp(L"hello", L"world"); // expected-error {{constant expression}} expected-note {{non-constexpr function 'wcscmp' cannot be used in a constant expression}}
+ constexpr int b = wcsncmp(L"hello", L"world", 3); // expected-error {{constant expression}} expected-note {{non-constexpr function 'wcsncmp' cannot be used in a constant expression}}
+ constexpr int c = wmemcmp(L"hello", L"world", 3); // expected-error {{constant expression}} expected-note {{non-constexpr function 'wmemcmp' cannot be used in a constant expression}}
+}
+
+namespace StrchrEtc {
+ constexpr const char *kStr = "abca\xff\0d";
+ constexpr char kFoo[] = {'f', 'o', 'o'};
+ static_assert(__builtin_strchr(kStr, 'a') == kStr);
+ static_assert(__builtin_strchr(kStr, 'b') == kStr + 1);
+ static_assert(__builtin_strchr(kStr, 'c') == kStr + 2);
+ static_assert(__builtin_strchr(kStr, 'd') == nullptr);
+ static_assert(__builtin_strchr(kStr, 'e') == nullptr);
+ static_assert(__builtin_strchr(kStr, '\0') == kStr + 5);
+ static_assert(__builtin_strchr(kStr, 'a' + 256) == nullptr);
+ static_assert(__builtin_strchr(kStr, 'a' - 256) == nullptr);
+ static_assert(__builtin_strchr(kStr, '\xff') == kStr + 4);
+ static_assert(__builtin_strchr(kStr, '\xff' + 256) == nullptr);
+ static_assert(__builtin_strchr(kStr, '\xff' - 256) == nullptr);
+ static_assert(__builtin_strchr(kFoo, 'o') == kFoo + 1);
+ static_assert(__builtin_strchr(kFoo, 'x') == nullptr); // expected-error {{not an integral constant}} expected-note {{dereferenced one-past-the-end}}
+ static_assert(__builtin_strchr(nullptr, 'x') == nullptr); // expected-error {{not an integral constant}} expected-note {{dereferenced null}}
+
+ static_assert(__builtin_memchr(kStr, 'a', 0) == nullptr);
+ static_assert(__builtin_memchr(kStr, 'a', 1) == kStr);
+ static_assert(__builtin_memchr(kStr, '\0', 5) == nullptr);
+ static_assert(__builtin_memchr(kStr, '\0', 6) == kStr + 5);
+ static_assert(__builtin_memchr(kStr, '\xff', 8) == kStr + 4);
+ static_assert(__builtin_memchr(kStr, '\xff' + 256, 8) == kStr + 4);
+ static_assert(__builtin_memchr(kStr, '\xff' - 256, 8) == kStr + 4);
+ static_assert(__builtin_memchr(kFoo, 'x', 3) == nullptr);
+ static_assert(__builtin_memchr(kFoo, 'x', 4) == nullptr); // expected-error {{not an integral constant}} expected-note {{dereferenced one-past-the-end}}
+ static_assert(__builtin_memchr(nullptr, 'x', 3) == nullptr); // expected-error {{not an integral constant}} expected-note {{dereferenced null}}
+ static_assert(__builtin_memchr(nullptr, 'x', 0) == nullptr); // FIXME: Should we reject this?
+
+ constexpr bool a = !strchr("hello", 'h'); // expected-error {{constant expression}} expected-note {{non-constexpr function 'strchr' cannot be used in a constant expression}}
+ constexpr bool b = !memchr("hello", 'h', 3); // expected-error {{constant expression}} expected-note {{non-constexpr function 'memchr' cannot be used in a constant expression}}
+}
+
+namespace WcschrEtc {
+ constexpr const wchar_t *kStr = L"abca\xffff\0dL";
+ constexpr wchar_t kFoo[] = {L'f', L'o', L'o'};
+ static_assert(__builtin_wcschr(kStr, L'a') == kStr);
+ static_assert(__builtin_wcschr(kStr, L'b') == kStr + 1);
+ static_assert(__builtin_wcschr(kStr, L'c') == kStr + 2);
+ static_assert(__builtin_wcschr(kStr, L'd') == nullptr);
+ static_assert(__builtin_wcschr(kStr, L'e') == nullptr);
+ static_assert(__builtin_wcschr(kStr, L'\0') == kStr + 5);
+ static_assert(__builtin_wcschr(kStr, L'a' + 256) == nullptr);
+ static_assert(__builtin_wcschr(kStr, L'a' - 256) == nullptr);
+ static_assert(__builtin_wcschr(kStr, L'\xffff') == kStr + 4);
+ static_assert(__builtin_wcschr(kFoo, L'o') == kFoo + 1);
+ static_assert(__builtin_wcschr(kFoo, L'x') == nullptr); // expected-error {{not an integral constant}} expected-note {{dereferenced one-past-the-end}}
+ static_assert(__builtin_wcschr(nullptr, L'x') == nullptr); // expected-error {{not an integral constant}} expected-note {{dereferenced null}}
+
+ static_assert(__builtin_wmemchr(kStr, L'a', 0) == nullptr);
+ static_assert(__builtin_wmemchr(kStr, L'a', 1) == kStr);
+ static_assert(__builtin_wmemchr(kStr, L'\0', 5) == nullptr);
+ static_assert(__builtin_wmemchr(kStr, L'\0', 6) == kStr + 5);
+ static_assert(__builtin_wmemchr(kStr, L'\xffff', 8) == kStr + 4);
+ static_assert(__builtin_wmemchr(kFoo, L'x', 3) == nullptr);
+ static_assert(__builtin_wmemchr(kFoo, L'x', 4) == nullptr); // expected-error {{not an integral constant}} expected-note {{dereferenced one-past-the-end}}
+ static_assert(__builtin_wmemchr(nullptr, L'x', 3) == nullptr); // expected-error {{not an integral constant}} expected-note {{dereferenced null}}
+ static_assert(__builtin_wmemchr(nullptr, L'x', 0) == nullptr); // FIXME: Should we reject this?
+
+ constexpr bool a = !wcschr(L"hello", L'h'); // expected-error {{constant expression}} expected-note {{non-constexpr function 'wcschr' cannot be used in a constant expression}}
+ constexpr bool b = !wmemchr(L"hello", L'h', 3); // expected-error {{constant expression}} expected-note {{non-constexpr function 'wmemchr' cannot be used in a constant expression}}
+}
diff --git a/test/SemaCXX/constexpr-strlen.cpp b/test/SemaCXX/constexpr-strlen.cpp
deleted file mode 100644
index 5e28e7f0ce5f..000000000000
--- a/test/SemaCXX/constexpr-strlen.cpp
+++ /dev/null
@@ -1,15 +0,0 @@
-// RUN: %clang_cc1 %s -std=c++11 -fsyntax-only -verify -pedantic
-
-# 1 "/usr/include/string.h" 1 3 4
-extern "C" {
- typedef decltype(sizeof(int)) size_t;
- extern size_t strlen(const char *p);
-}
-
-# 10 "SemaCXX/constexpr-strlen.cpp" 2
-constexpr int n = __builtin_strlen("hello"); // ok
-constexpr int m = strlen("hello"); // expected-error {{constant expression}} expected-note {{non-constexpr function 'strlen' cannot be used in a constant expression}}
-
-// Make sure we can evaluate a call to strlen.
-int arr[3]; // expected-note {{here}}
-int k = arr[strlen("hello")]; // expected-warning {{array index 5}}
diff --git a/test/SemaCXX/constexpr-value-init.cpp b/test/SemaCXX/constexpr-value-init.cpp
index 3528fdcd8816..53271e0da3fa 100644
--- a/test/SemaCXX/constexpr-value-init.cpp
+++ b/test/SemaCXX/constexpr-value-init.cpp
@@ -34,4 +34,13 @@ struct V : virtual C {};
template<typename T> struct Z : T {
constexpr Z() : V() {}
};
-constexpr int n = Z<V>().c; // expected-error {{constant expression}} expected-note {{virtual base class}}
+constexpr int n = Z<V>().c; // expected-error {{constant expression}} expected-note {{non-literal type 'Z<V>'}}
+
+struct E {
+ A a[2];
+};
+constexpr E e; // ok
+static_assert(e.a[0].a == 1, "");
+static_assert(e.a[0].b == 2, "");
+static_assert(e.a[1].a == 1, "");
+static_assert(e.a[1].b == 2, "");
diff --git a/test/SemaCXX/conversion-function.cpp b/test/SemaCXX/conversion-function.cpp
index 3f494cce8ce3..c725a0d5b7c1 100644
--- a/test/SemaCXX/conversion-function.cpp
+++ b/test/SemaCXX/conversion-function.cpp
@@ -434,8 +434,12 @@ namespace PR18234 {
struct A {
operator enum E { e } (); // expected-error {{'PR18234::A::E' cannot be defined in a type specifier}}
operator struct S { int n; } (); // expected-error {{'PR18234::A::S' cannot be defined in a type specifier}}
+ // expected-note@-1 {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'struct A' to 'const PR18234::A::S &' for 1st argument}}
+#if __cplusplus >= 201103L
+ // expected-note@-3 {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'struct A' to 'PR18234::A::S &&' for 1st argument}}
+#endif
} a;
- A::S s = a;
+ A::S s = a; // expected-error {{no viable conversion from 'struct A' to 'A::S'}}
A::E e = a; // expected-note {{here}}
bool k1 = e == A::e; // expected-error {{no member named 'e'}}
bool k2 = e.n == 0;
diff --git a/test/SemaCXX/conversion.cpp b/test/SemaCXX/conversion.cpp
index 7b86cecdbcef..dcd64fa2ec8a 100644
--- a/test/SemaCXX/conversion.cpp
+++ b/test/SemaCXX/conversion.cpp
@@ -50,7 +50,7 @@ namespace test1 {
namespace test2 {
struct A {
unsigned int x : 2;
- A() : x(10) {} // expected-warning {{implicit truncation from 'int' to bitfield changes value from 10 to 2}}
+ A() : x(10) {} // expected-warning {{implicit truncation from 'int' to bit-field changes value from 10 to 2}}
};
}
diff --git a/test/SemaCXX/copy-assignment.cpp b/test/SemaCXX/copy-assignment.cpp
index 798582c149cf..d6ad6577895f 100644
--- a/test/SemaCXX/copy-assignment.cpp
+++ b/test/SemaCXX/copy-assignment.cpp
@@ -1,4 +1,11 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++98
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11
+
+#if __cplusplus >= 201103L
+// expected-note@+3 2 {{candidate constructor}}
+// expected-note@+2 {{passing argument to parameter here}}
+#endif
struct A {
};
@@ -7,6 +14,9 @@ struct ConvertibleToA {
};
struct ConvertibleToConstA {
+#if __cplusplus >= 201103L
+// expected-note@+2 {{candidate function}}
+#endif
operator const A();
};
@@ -69,6 +79,9 @@ void test() {
na = a;
na = constA;
na = convertibleToA;
+#if __cplusplus >= 201103L
+// expected-error@+2 {{no viable conversion}}
+#endif
na = convertibleToConstA;
na += a; // expected-error{{no viable overloaded '+='}}
diff --git a/test/SemaCXX/copy-initialization.cpp b/test/SemaCXX/copy-initialization.cpp
index d219ee508f03..4f6c65cf550c 100644
--- a/test/SemaCXX/copy-initialization.cpp
+++ b/test/SemaCXX/copy-initialization.cpp
@@ -30,7 +30,7 @@ void test(const foo *P) { P->bar(); } // expected-error{{'bar' not viable: 'this
namespace PR6757 {
struct Foo {
- Foo();
+ Foo(); // expected-note{{not viable}}
Foo(Foo&); // expected-note{{candidate constructor not viable}}
};
@@ -71,3 +71,12 @@ namespace DR5 {
const S b = 0;
}
}
+
+struct A {};
+struct B : A {
+ B();
+ B(B&);
+ B(A);
+ B(int);
+};
+B b = 0; // ok, calls B(int) then A(const A&) then B(A).
diff --git a/test/SemaCXX/coreturn.cpp b/test/SemaCXX/coreturn.cpp
new file mode 100644
index 000000000000..4c41ae95c513
--- /dev/null
+++ b/test/SemaCXX/coreturn.cpp
@@ -0,0 +1,73 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 %s -std=c++14 -fcoroutines-ts -fsyntax-only -Wignored-qualifiers -Wno-error=return-type -verify -fblocks -Wno-unreachable-code -Wno-unused-value
+
+struct awaitable {
+ bool await_ready();
+ void await_suspend(); // FIXME: coroutine_handle
+ void await_resume();
+} a;
+
+struct suspend_always {
+ bool await_ready() { return false; }
+ void await_suspend() {}
+ void await_resume() {}
+};
+
+struct suspend_never {
+ bool await_ready() { return true; }
+ void await_suspend() {}
+ void await_resume() {}
+};
+
+namespace std {
+namespace experimental {
+
+template <class Ret, typename... T>
+struct coroutine_traits { using promise_type = typename Ret::promise_type; };
+
+template <class Promise = void>
+struct coroutine_handle {};
+}
+}
+
+struct promise_void {
+ void get_return_object();
+ suspend_always initial_suspend();
+ suspend_always final_suspend();
+ void return_void();
+};
+
+struct promise_float {
+ float get_return_object();
+ suspend_always initial_suspend();
+ suspend_always final_suspend();
+ void return_void();
+};
+
+struct promise_int {
+ int get_return_object();
+ suspend_always initial_suspend();
+ suspend_always final_suspend();
+ void return_value(int);
+};
+
+template <typename... T>
+struct std::experimental::coroutine_traits<void, T...> { using promise_type = promise_void; };
+
+template <typename... T>
+struct std::experimental::coroutine_traits<float, T...> { using promise_type = promise_float; };
+
+template <typename... T>
+struct std::experimental::coroutine_traits<int, T...> { using promise_type = promise_int; };
+
+void test0() { co_await a; }
+float test1() { co_await a; }
+
+int test2() {
+ co_await a;
+} // expected-warning {{control reaches end of non-void coroutine}}
+
+int test3() {
+ co_await a;
+b:
+ goto b;
+}
diff --git a/test/SemaCXX/coroutines.cpp b/test/SemaCXX/coroutines.cpp
index e82cb62f12d4..a22383cd566b 100644
--- a/test/SemaCXX/coroutines.cpp
+++ b/test/SemaCXX/coroutines.cpp
@@ -1,4 +1,21 @@
-// RUN: %clang_cc1 -std=c++14 -fcoroutines -verify %s
+// RUN: %clang_cc1 -std=c++14 -fcoroutines-ts -verify %s
+
+void no_coroutine_traits_bad_arg_await() {
+ co_await a; // expected-error {{include <experimental/coroutine>}}
+ // expected-error@-1 {{use of undeclared identifier 'a'}}
+}
+
+void no_coroutine_traits_bad_arg_yield() {
+ co_yield a; // expected-error {{include <experimental/coroutine>}}
+ // expected-error@-1 {{use of undeclared identifier 'a'}}
+}
+
+
+void no_coroutine_traits_bad_arg_return() {
+ co_return a; // expected-error {{include <experimental/coroutine>}}
+ // expected-error@-1 {{use of undeclared identifier 'a'}}
+}
+
struct awaitable {
bool await_ready();
@@ -19,45 +36,64 @@ struct suspend_never {
};
void no_coroutine_traits() {
- co_await a; // expected-error {{need to include <coroutine>}}
+ co_await a; // expected-error {{need to include <experimental/coroutine>}}
}
namespace std {
- template<typename ...T> struct coroutine_traits; // expected-note {{declared here}}
-};
+namespace experimental {
+template <typename... T>
+struct coroutine_traits; // expected-note {{declared here}}
+}
+}
template<typename Promise> struct coro {};
-template<typename Promise, typename... Ps>
-struct std::coroutine_traits<coro<Promise>, Ps...> {
+template <typename Promise, typename... Ps>
+struct std::experimental::coroutine_traits<coro<Promise>, Ps...> {
using promise_type = Promise;
};
void no_specialization() {
- co_await a; // expected-error {{implicit instantiation of undefined template 'std::coroutine_traits<void>'}}
+ co_await a; // expected-error {{implicit instantiation of undefined template 'std::experimental::coroutine_traits<void>'}}
}
-template<typename ...T> struct std::coroutine_traits<int, T...> {};
+template <typename... T>
+struct std::experimental::coroutine_traits<int, T...> {};
int no_promise_type() {
- co_await a; // expected-error {{this function cannot be a coroutine: 'std::coroutine_traits<int>' has no member named 'promise_type'}}
+ co_await a; // expected-error {{this function cannot be a coroutine: 'std::experimental::coroutine_traits<int>' has no member named 'promise_type'}}
}
-template<> struct std::coroutine_traits<double, double> { typedef int promise_type; };
+template <>
+struct std::experimental::coroutine_traits<double, double> { typedef int promise_type; };
double bad_promise_type(double) {
- co_await a; // expected-error {{this function cannot be a coroutine: 'std::coroutine_traits<double, double>::promise_type' (aka 'int') is not a class}}
+ co_await a; // expected-error {{this function cannot be a coroutine: 'experimental::coroutine_traits<double, double>::promise_type' (aka 'int') is not a class}}
}
-template<> struct std::coroutine_traits<double, int> {
+template <>
+struct std::experimental::coroutine_traits<double, int> {
struct promise_type {};
};
double bad_promise_type_2(int) {
- co_yield 0; // expected-error {{no member named 'yield_value' in 'std::coroutine_traits<double, int>::promise_type'}}
+ co_yield 0; // expected-error {{no member named 'yield_value' in 'std::experimental::coroutine_traits<double, int>::promise_type'}}
}
struct promise; // expected-note 2{{forward declaration}}
-template<typename ...T> struct std::coroutine_traits<void, T...> { using promise_type = promise; };
+struct promise_void;
+struct void_tag {};
+template <typename... T>
+struct std::experimental::coroutine_traits<void, T...> { using promise_type = promise; };
+template <typename... T>
+struct std::experimental::coroutine_traits<void, void_tag, T...>
+{ using promise_type = promise_void; };
+
+namespace std {
+namespace experimental {
+template <typename Promise = void>
+struct coroutine_handle;
+}
+}
- // FIXME: This diagnostic is terrible.
+// FIXME: This diagnostic is terrible.
void undefined_promise() { // expected-error {{variable has incomplete type 'promise_type'}}
// FIXME: This diagnostic doesn't make any sense.
// expected-error@-2 {{incomplete definition of type 'promise'}}
@@ -75,10 +111,16 @@ struct promise {
awaitable yield_value(int); // expected-note 2{{candidate}}
awaitable yield_value(yielded_thing); // expected-note 2{{candidate}}
not_awaitable yield_value(void()); // expected-note 2{{candidate}}
- void return_void();
void return_value(int); // expected-note 2{{here}}
};
+struct promise_void {
+ void get_return_object();
+ suspend_always initial_suspend();
+ suspend_always final_suspend();
+ void return_void();
+};
+
void yield() {
co_yield 0;
co_yield {"foo", 1, 2};
@@ -95,10 +137,10 @@ void coreturn(int n) {
if (n == 0)
co_return 3;
if (n == 1)
- co_return {4};
+ co_return {4}; // expected-warning {{braces around scalar initializer}}
if (n == 2)
co_return "foo"; // expected-error {{cannot initialize a parameter of type 'int' with an lvalue of type 'const char [4]'}}
- co_return;
+ co_return 42;
}
void mixed_yield() {
@@ -111,11 +153,11 @@ void mixed_await() {
return; // expected-error {{not allowed in coroutine}}
}
-void only_coreturn() {
+void only_coreturn(void_tag) {
co_return; // expected-warning {{'co_return' used in a function that uses neither 'co_await' nor 'co_yield'}}
}
-void mixed_coreturn(bool b) {
+void mixed_coreturn(void_tag, bool b) {
if (b)
// expected-warning@+1 {{'co_return' used in a function that uses neither}}
co_return; // expected-note {{use of 'co_return'}}
@@ -136,7 +178,19 @@ struct CtorDtor {
}
// FIXME: The spec says this is ill-formed.
void operator=(CtorDtor&) {
- co_yield 0;
+ co_yield 0; // expected-error {{'co_yield' cannot be used in a copy assignment operator}}
+ }
+ void operator=(CtorDtor const &) {
+ co_yield 0; // expected-error {{'co_yield' cannot be used in a copy assignment operator}}
+ }
+ void operator=(CtorDtor &&) {
+ co_await a; // expected-error {{'co_await' cannot be used in a move assignment operator}}
+ }
+ void operator=(CtorDtor const &&) {
+ co_await a; // expected-error {{'co_await' cannot be used in a move assignment operator}}
+ }
+ void operator=(int) {
+ co_await a; // OK. Not a special member
}
};
@@ -149,14 +203,19 @@ void unevaluated() {
typeid(co_yield a); // expected-error {{cannot be used in an unevaluated context}}
}
-constexpr void constexpr_coroutine() {
+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}}
}
void varargs_coroutine(const char *, ...) {
co_await a; // expected-error {{'co_await' cannot be used in a varargs function}}
}
+auto deduced_return_coroutine() {
+ co_await a; // expected-error {{'co_await' cannot be used in a function with a deduced return type}}
+}
+
struct outer {};
namespace dependent_operator_co_await_lookup {
@@ -183,7 +242,8 @@ namespace dependent_operator_co_await_lookup {
}
struct yield_fn_tag {};
-template<> struct std::coroutine_traits<void, yield_fn_tag> {
+template <>
+struct std::experimental::coroutine_traits<void, yield_fn_tag> {
struct promise_type {
// FIXME: add an await_transform overload for functions
awaitable yield_value(int());
@@ -266,3 +326,52 @@ struct bad_promise_5 {
coro<bad_promise_5> bad_final_suspend() { // expected-error {{no member named 'await_ready' in 'not_awaitable'}}
co_await a;
}
+
+struct bad_promise_6 {
+ coro<bad_promise_6> get_return_object();
+ suspend_always initial_suspend();
+ suspend_always final_suspend();
+ void return_void();
+ void return_value(int) const;
+ void return_value(int);
+};
+coro<bad_promise_6> bad_implicit_return() { // expected-error {{'bad_promise_6' declares both 'return_value' and 'return_void'}}
+ co_await a;
+}
+
+struct bad_promise_7 {
+ coro<bad_promise_7> get_return_object();
+ suspend_always initial_suspend();
+ suspend_always final_suspend();
+ void return_void();
+ void set_exception(int *);
+};
+coro<bad_promise_7> no_std_current_exc() {
+ // expected-error@-1 {{you need to include <exception> before defining a coroutine that implicitly uses 'set_exception'}}
+ co_await a;
+}
+
+namespace std {
+int *current_exception();
+}
+
+struct bad_promise_8 {
+ coro<bad_promise_8> get_return_object();
+ suspend_always initial_suspend();
+ suspend_always final_suspend();
+ void return_void();
+ void set_exception(); // expected-note {{function not viable}}
+ void set_exception(int *) __attribute__((unavailable)); // expected-note {{explicitly made unavailable}}
+ void set_exception(void *); // expected-note {{candidate function}}
+};
+coro<bad_promise_8> calls_set_exception() {
+ // expected-error@-1 {{call to unavailable member function 'set_exception'}}
+ co_await a;
+}
+
+template<> struct std::experimental::coroutine_traits<int, int, const char**>
+{ using promise_type = promise; };
+
+int main(int, const char**) {
+ co_await a; // expected-error {{'co_await' cannot be used in the 'main' function}}
+}
diff --git a/test/SemaCXX/cxx0x-defaulted-functions.cpp b/test/SemaCXX/cxx0x-defaulted-functions.cpp
index 7ec9726095cb..f623dc765f88 100644
--- a/test/SemaCXX/cxx0x-defaulted-functions.cpp
+++ b/test/SemaCXX/cxx0x-defaulted-functions.cpp
@@ -87,35 +87,36 @@ namespace DefaultedFnExceptionSpec {
template<typename T>
struct Error {
- // FIXME: Type canonicalization causes all the errors to point at the first
- // declaration which has the type 'void () noexcept (T::error)'. We should
- // get one error for 'Error<int>::Error()' and one for 'Error<int>::~Error()'.
- void f() noexcept(T::error); // expected-error 2{{has no members}}
-
- Error() noexcept(T::error);
- Error(const Error&) noexcept(T::error);
- Error(Error&&) noexcept(T::error);
- Error &operator=(const Error&) noexcept(T::error);
- Error &operator=(Error&&) noexcept(T::error);
- ~Error() noexcept(T::error);
+ void f() noexcept(T::error);
+
+ Error() noexcept(T::error); // expected-error {{type 'int' cannot be used prior to '::' because it has no members}} expected-error {{type 'char'}}
+ Error(const Error&) noexcept(T::error); // expected-error {{type 'int' cannot be used prior to '::' because it has no members}}
+ Error(Error&&) noexcept(T::error); // expected-error {{type 'int' cannot be used prior to '::' because it has no members}}
+ Error &operator=(const Error&) noexcept(T::error); // expected-error {{type 'int' cannot be used prior to '::' because it has no members}} expected-error {{type 'double'}}
+ Error &operator=(Error&&) noexcept(T::error); // expected-error {{type 'int' cannot be used prior to '::' because it has no members}}
+ ~Error() noexcept(T::error); // expected-error {{type 'int' cannot be used prior to '::' because it has no members}} expected-error {{type 'char'}}
};
+ Error<char> c; // expected-note 2{{instantiation of}}
struct DelayImplicit {
- Error<int> e;
+ // FIXME: The location of this note is terrible. The instantiation was
+ // triggered by the uses of the functions in the decltype expressions below.
+ Error<int> e; // expected-note 6{{instantiation of}}
};
+ Error<float> *e;
- // Don't instantiate the exception specification here.
+ // An exception specification is needed if the exception specification for a
+ // a defaulted special member function that calls the function is needed.
+ // Use in an unevaluated operand still results in the exception spec being
+ // needed.
void test1(decltype(declval<DelayImplicit>() = DelayImplicit(DelayImplicit())));
void test2(decltype(declval<DelayImplicit>() = declval<const DelayImplicit>()));
void test3(decltype(DelayImplicit(declval<const DelayImplicit>())));
- // Any odr-use causes the exception specification to be evaluated.
- struct OdrUse { // \
- expected-note {{instantiation of exception specification for 'Error'}} \
- expected-note {{instantiation of exception specification for '~Error'}}
- Error<int> e;
- };
- OdrUse use; // expected-note {{implicit default constructor for 'DefaultedFnExceptionSpec::OdrUse' first required here}}
+ // Any odr-use needs the exception specification.
+ void f(Error<double> *p) {
+ *p = *p; // expected-note {{instantiation of}}
+ }
}
namespace PR13527 {
@@ -142,11 +143,11 @@ namespace PR13527 {
Y &operator=(Y&&) = default;
~Y() = default;
};
- Y::Y() = default; // expected-error {{definition of explicitly defaulted}}
- Y::Y(const Y&) = default; // expected-error {{definition of explicitly defaulted}}
- Y::Y(Y&&) = default; // expected-error {{definition of explicitly defaulted}}
- Y &Y::operator=(const Y&) = default; // expected-error {{definition of explicitly defaulted}}
- Y &Y::operator=(Y&&) = default; // expected-error {{definition of explicitly defaulted}}
+ Y::Y() noexcept = default; // expected-error {{definition of explicitly defaulted}}
+ Y::Y(const Y&) noexcept = default; // expected-error {{definition of explicitly defaulted}}
+ Y::Y(Y&&) noexcept = default; // expected-error {{definition of explicitly defaulted}}
+ Y &Y::operator=(const Y&) noexcept = default; // expected-error {{definition of explicitly defaulted}}
+ Y &Y::operator=(Y&&) noexcept = default; // expected-error {{definition of explicitly defaulted}}
Y::~Y() = default; // expected-error {{definition of explicitly defaulted}}
}
@@ -179,7 +180,7 @@ namespace PR14577 {
Outer<T>::Inner2<T>::~Inner2() = default; // expected-error {{nested name specifier 'Outer<T>::Inner2<T>::' for declaration does not refer into a class, class template or class template partial specialization}} expected-error {{only special member functions may be defaulted}}
}
-extern "C" {
+extern "C" { // expected-note {{extern "C" language linkage specification begins here}}
template<typename _Tp> // expected-error {{templates must have C++ linkage}}
void PR13573(const _Tp&) = delete;
}
diff --git a/test/SemaCXX/cxx0x-initializer-constructor.cpp b/test/SemaCXX/cxx0x-initializer-constructor.cpp
index 6202bf620fe3..c10bee917ac0 100644
--- a/test/SemaCXX/cxx0x-initializer-constructor.cpp
+++ b/test/SemaCXX/cxx0x-initializer-constructor.cpp
@@ -267,8 +267,11 @@ namespace PR12120 {
struct A { explicit A(int); A(float); }; // expected-note {{declared here}}
A a = { 0 }; // expected-error {{constructor is explicit}}
- struct B { explicit B(short); B(long); }; // expected-note 2 {{candidate}}
+ struct B { explicit B(short); B(long); }; // expected-note 4{{candidate}}
B b = { 0 }; // expected-error {{ambiguous}}
+
+ struct C { explicit C(short); C(long); }; // expected-note 2{{candidate}}
+ C c = {{ 0 }}; // expected-error {{ambiguous}}
}
namespace PR12498 {
diff --git a/test/SemaCXX/cxx0x-initializer-references.cpp b/test/SemaCXX/cxx0x-initializer-references.cpp
index 390047ea0752..c64511193b6e 100644
--- a/test/SemaCXX/cxx0x-initializer-references.cpp
+++ b/test/SemaCXX/cxx0x-initializer-references.cpp
@@ -72,10 +72,9 @@ namespace reference {
}
void edge_cases() {
- // FIXME: very poor error message
- int const &b({0}); // expected-error {{could not bind}}
+ int const &b({0}); // expected-error {{list-initializer for non-class type 'const int &' must not be parenthesized}}
+ const int (&arr)[3] ({1, 2, 3}); // expected-error {{list-initializer for non-class type 'const int (&)[3]' must not be parenthesized}}
}
-
}
namespace PR12182 {
diff --git a/test/SemaCXX/cxx0x-initializer-scalars.cpp b/test/SemaCXX/cxx0x-initializer-scalars.cpp
index c9d5ffd19429..65b57a5584ab 100644
--- a/test/SemaCXX/cxx0x-initializer-scalars.cpp
+++ b/test/SemaCXX/cxx0x-initializer-scalars.cpp
@@ -91,10 +91,23 @@ namespace integral {
}
void edge_cases() {
- // FIXME: very poor error message
- int a({0}); // expected-error {{cannot initialize}}
- (void) int({0}); // expected-error {{functional-style cast}}
- new int({0}); // expected-error {{cannot initialize}}
+ int a({0}); // expected-error {{list-initializer for non-class type 'int' must not be parenthesized}}
+ (void) int({0}); // expected-error {{list-initializer for non-class type 'int' must not be parenthesized}}
+ new int({0}); // expected-error {{list-initializer for non-class type 'int' must not be parenthesized}}
+
+ int *b({0}); // expected-error {{list-initializer for non-class type 'int *' must not be parenthesized}}
+ typedef int *intptr;
+ int *c = intptr({0}); // expected-error {{list-initializer for non-class type 'intptr' (aka 'int *') must not be parenthesized}}
+ }
+
+ template<typename T> void dependent_edge_cases() {
+ T a({0});
+ (void) T({0});
+ new T({0});
+
+ T *b({0});
+ typedef T *tptr;
+ T *c = tptr({0});
}
void default_argument(int i = {}) {
diff --git a/test/SemaCXX/cxx11-ast-print.cpp b/test/SemaCXX/cxx11-ast-print.cpp
index 1eeb67a3d9b3..9c617af4e95f 100644
--- a/test/SemaCXX/cxx11-ast-print.cpp
+++ b/test/SemaCXX/cxx11-ast-print.cpp
@@ -43,6 +43,14 @@ template <class C, C...> const char *operator"" _suffix();
// CHECK: const char *PR23120 = operator""_suffix<char32_t, 66615>();
const char *PR23120 = U"𐐷"_suffix;
+// PR28885
+struct A {
+ A();
+};
+struct B : A {
+ using A::A; // CHECK: using A::A;
+}; // CHECK-NEXT: };
+
// CHECK: ;
;
// CHECK-NOT: ;
diff --git a/test/SemaCXX/cxx11-inheriting-ctors.cpp b/test/SemaCXX/cxx11-inheriting-ctors.cpp
index 9c33ac05cc5f..5ce8d1aa3e0b 100644
--- a/test/SemaCXX/cxx11-inheriting-ctors.cpp
+++ b/test/SemaCXX/cxx11-inheriting-ctors.cpp
@@ -1,7 +1,5 @@
// RUN: %clang_cc1 -std=c++11 %s -verify
-// expected-no-diagnostics
-
namespace PR15757 {
struct S {
};
@@ -56,3 +54,33 @@ namespace InvalidConstruction {
template<typename T> int &f(...);
int &r = f<C>(0);
}
+
+namespace ExplicitConv {
+ struct B {}; // expected-note 2{{candidate}}
+ struct D : B { // expected-note 3{{candidate}}
+ using B::B; // expected-note 2{{inherited}}
+ };
+ struct X { explicit operator B(); } x;
+ struct Y { explicit operator D(); } y;
+
+ D dx(x); // expected-error {{no matching constructor}}
+ D dy(y);
+}
+
+namespace NestedListInit {
+ struct B { B(); } b; // expected-note 5{{candidate}}
+ struct D : B { // expected-note 3{{candidate}}
+ using B::B; // expected-note 2{{inherited}}
+ };
+ // This is a bit weird. We're allowed one pair of braces for overload
+ // resolution, and one more pair of braces due to [over.ics.list]/2.
+ B b1 = {b};
+ B b2 = {{b}};
+ B b3 = {{{b}}}; // expected-error {{no match}}
+ // This is the same, but we get one call to D's version of B::B(const B&)
+ // before the two permitted calls to D::D(D&&).
+ D d1 = {b};
+ D d2 = {{b}};
+ D d3 = {{{b}}};
+ D d4 = {{{{b}}}}; // expected-error {{no match}}
+}
diff --git a/test/SemaCXX/cxx1y-initializer-aggregates.cpp b/test/SemaCXX/cxx1y-initializer-aggregates.cpp
index 9b542403def3..3d5e7726a17e 100644
--- a/test/SemaCXX/cxx1y-initializer-aggregates.cpp
+++ b/test/SemaCXX/cxx1y-initializer-aggregates.cpp
@@ -61,3 +61,19 @@ namespace nested_aggregate_init {
};
static_assert(B(6).f() == 18, "");
}
+
+namespace use_self {
+ struct FibTree {
+ int n;
+ FibTree *l = // expected-note {{declared here}}
+ n > 1 ? new FibTree{n-1} : &fib0; // expected-error {{default member initializer for 'l' needed}}
+ FibTree *r = // expected-note {{declared here}}
+ n > 2 ? new FibTree{n-2} : &fib0; // expected-error {{default member initializer for 'r' needed}}
+ int v = l->v + r->v;
+
+ static FibTree fib0;
+ };
+ FibTree FibTree::fib0{0, nullptr, nullptr, 1};
+
+ int fib(int n) { return FibTree{n}.v; }
+}
diff --git a/test/SemaCXX/cxx1y-variable-templates_in_class.cpp b/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
index e2fbdfd69954..76f1bb9905b9 100644
--- a/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
+++ b/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
@@ -26,10 +26,10 @@ namespace out_of_line {
template<typename T, typename T0> static CONST T right = T(100);
template<typename T> static CONST T right<T,int> = T(5);
};
- template<> CONST int B0::right<int,int> = 7;
- template CONST int B0::right<int,int>;
- template<> CONST int B0::right<int,float>;
- template CONST int B0::right<int,float>;
+ template<> CONST int B0::right<int,int> = 7; // expected-note {{previous}}
+ template CONST int B0::right<int,int>; // expected-warning {{has no effect}}
+ template<> CONST int B0::right<int,float>; // expected-note {{previous}}
+ template CONST int B0::right<int,float>; // expected-warning {{has no effect}}
class B1 {
template<typename T, typename T0> static CONST T right;
diff --git a/test/SemaCXX/cxx1y-variable-templates_top_level.cpp b/test/SemaCXX/cxx1y-variable-templates_top_level.cpp
index 496ae888732f..ec3e2b6f63d1 100644
--- a/test/SemaCXX/cxx1y-variable-templates_top_level.cpp
+++ b/test/SemaCXX/cxx1y-variable-templates_top_level.cpp
@@ -264,9 +264,9 @@ namespace explicit_specialization {
template<typename T>
T pi0 = T(3.1415926535897932385); // expected-note {{variable template 'pi0' declared here}}
- template<> int pi0<int> = 10;
- template int pi0<int>;
- template float pi0<int>; // expected-error {{type 'float' of explicit instantiation of 'pi0' does not match expected type}}
+ template<> int pi0<int> = 10; // expected-note 2{{previous template specialization is here}}
+ template int pi0<int>; // expected-warning {{has no effect}}
+ template float pi0<int>; // expected-error {{type 'float' of explicit instantiation of 'pi0' does not match expected type}} expected-warning {{has no effect}}
template<typename T1, typename T2>
CONST int pi2 = 1;
diff --git a/test/SemaCXX/cxx1z-constexpr-lambdas.cpp b/test/SemaCXX/cxx1z-constexpr-lambdas.cpp
new file mode 100644
index 000000000000..90a07665cbf7
--- /dev/null
+++ b/test/SemaCXX/cxx1z-constexpr-lambdas.cpp
@@ -0,0 +1,62 @@
+// RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks %s
+// RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks -fdelayed-template-parsing %s
+// RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -fblocks %s -DCPP14_AND_EARLIER
+
+
+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}}
+#endif
+auto L = [] { };
+constexpr int foo(decltype(L) l) { return 0; }
+
+}
+
+#ifndef CPP14_AND_EARLIER
+namespace test_constexpr_checking {
+
+namespace ns1 {
+ struct NonLit { ~NonLit(); }; //expected-note{{not literal}}
+ auto L = [](NonLit NL) constexpr { }; //expected-error{{not a literal type}}
+} // end ns1
+
+namespace ns2 {
+ auto L = [](int I) constexpr { asm("non-constexpr"); }; //expected-error{{not allowed in constexpr function}}
+} // end ns1
+
+} // end ns test_constexpr_checking
+
+namespace test_constexpr_call {
+
+namespace ns1 {
+ auto L = [](int I) { return I; };
+ static_assert(L(3) == 3);
+} // end ns1
+namespace ns2 {
+ auto L = [](auto a) { return a; };
+ static_assert(L(3) == 3);
+ static_assert(L(3.14) == 3.14);
+}
+namespace ns3 {
+ auto L = [](auto a) { asm("non-constexpr"); return a; }; //expected-note{{declared here}}
+ constexpr int I = //expected-error{{must be initialized by a constant expression}}
+ L(3); //expected-note{{non-constexpr function}}
+}
+
+} // end ns test_constexpr_call
+
+namespace test_captureless_lambda {
+void f() {
+ const char c = 'c';
+ auto L = [] { return c; };
+ constexpr char C = L();
+}
+
+void f(char c) { //expected-note{{declared here}}
+ auto L = [] { return c; }; //expected-error{{cannot be implicitly captured}} expected-note{{lambda expression begins here}}
+ int I = L();
+}
+
+}
+#endif // ndef CPP14_AND_EARLIER
diff --git a/test/SemaCXX/cxx1z-copy-omission.cpp b/test/SemaCXX/cxx1z-copy-omission.cpp
new file mode 100644
index 000000000000..e2b8fd796174
--- /dev/null
+++ b/test/SemaCXX/cxx1z-copy-omission.cpp
@@ -0,0 +1,134 @@
+// RUN: %clang_cc1 -std=c++1z -verify %s
+
+struct Noncopyable {
+ Noncopyable();
+ Noncopyable(const Noncopyable &) = delete; // expected-note 1+{{deleted}}
+ virtual ~Noncopyable();
+};
+struct Derived : Noncopyable {};
+struct NoncopyableAggr {
+ Noncopyable nc;
+};
+struct Indestructible {
+ Indestructible();
+ ~Indestructible() = delete; // expected-note 1+{{deleted}}
+};
+struct Incomplete; // expected-note 1+{{declar}}
+
+Noncopyable make(int kind = 0) {
+ switch (kind) {
+ case 0: return {};
+ case 1: return Noncopyable();
+ case 2: return Noncopyable{};
+ case 3: return make();
+ }
+ __builtin_unreachable();
+}
+
+Indestructible make_indestructible();
+Incomplete make_incomplete(); // expected-note 1+{{here}}
+
+void take(Noncopyable nc) {}
+
+Noncopyable nrvo() {
+ Noncopyable nrvo;
+ return nrvo; // expected-error {{deleted constructor}}
+}
+
+Noncopyable nc1 = make();
+Noncopyable nc2 = Noncopyable();
+Noncopyable nc3 = Derived(); // expected-error {{deleted constructor}}
+
+NoncopyableAggr nca1 = NoncopyableAggr{};
+NoncopyableAggr nca2 = NoncopyableAggr{{}};
+NoncopyableAggr nca3 = NoncopyableAggr{NoncopyableAggr{Noncopyable()}};
+
+void test_expressions(bool b) {
+ auto lambda = [a = make()] {};
+
+ take({});
+ take(Noncopyable());
+ take(Noncopyable{});
+ take(make());
+
+ Noncopyable &&dc1 = dynamic_cast<Noncopyable&&>(Noncopyable());
+ Noncopyable &&dc2 = dynamic_cast<Noncopyable&&>(nc1);
+ Noncopyable &&dc3 = dynamic_cast<Noncopyable&&>(Derived());
+
+ Noncopyable sc1 = static_cast<Noncopyable>(Noncopyable());
+ Noncopyable sc2 = static_cast<Noncopyable>(nc1); // expected-error {{deleted}}
+ Noncopyable sc3 = static_cast<Noncopyable&&>(Noncopyable()); // expected-error {{deleted}}
+ Noncopyable sc4 = static_cast<Noncopyable>(static_cast<Noncopyable&&>(Noncopyable())); // expected-error {{deleted}}
+
+ Noncopyable cc1 = (Noncopyable)Noncopyable();
+ Noncopyable cc2 = (Noncopyable)Derived(); // expected-error {{deleted}}
+
+ Noncopyable fc1 = Noncopyable(Noncopyable());
+ Noncopyable fc2 = Noncopyable(Derived()); // expected-error {{deleted}}
+
+ // We must check for a complete type for every materialized temporary. (Note
+ // that in the special case of the top level of a decltype, no temporary is
+ // materialized.)
+ make_incomplete(); // expected-error {{incomplete}}
+ make_incomplete().a; // expected-error {{incomplete}}
+ make_incomplete().*(int Incomplete::*)nullptr; // expected-error {{incomplete}}
+ dynamic_cast<Incomplete&&>(make_incomplete()); // expected-error {{incomplete}}
+ const_cast<Incomplete&&>(make_incomplete()); // expected-error {{incomplete}}
+
+ sizeof(Indestructible{}); // expected-error {{deleted}}
+ sizeof(make_indestructible()); // expected-error {{deleted}}
+ sizeof(make_incomplete()); // expected-error {{incomplete}}
+ typeid(Indestructible{}); // expected-error {{deleted}}
+ typeid(make_indestructible()); // expected-error {{deleted}}
+ typeid(make_incomplete()); // expected-error {{incomplete}}
+
+ // FIXME: The first two cases here are now also valid in C++17 onwards.
+ using I = decltype(Indestructible()); // expected-error {{deleted}}
+ using I = decltype(Indestructible{}); // expected-error {{deleted}}
+ using I = decltype(make_indestructible());
+ using J = decltype(make_incomplete());
+
+ Noncopyable cond1 = b ? Noncopyable() : make();
+ Noncopyable cond2 = b ? Noncopyable() : Derived(); // expected-error {{incompatible}}
+ Noncopyable cond3 = b ? Derived() : Noncopyable(); // expected-error {{incompatible}}
+ Noncopyable cond4 = b ? Noncopyable() : nc1; // expected-error {{deleted}}
+ Noncopyable cond5 = b ? nc1 : Noncopyable(); // expected-error {{deleted}}
+ // Could convert both to an xvalue of type Noncopyable here, but we're not
+ // permitted to consider that.
+ Noncopyable &&cond6 = b ? Noncopyable() : Derived(); // expected-error {{incompatible}}
+ Noncopyable &&cond7 = b ? Derived() : Noncopyable(); // expected-error {{incompatible}}
+ // Could convert both to a const lvalue of type Noncopyable here, but we're
+ // not permitted to consider that, either.
+ const Noncopyable cnc;
+ const Noncopyable &cond8 = b ? cnc : Derived(); // expected-error {{incompatible}}
+ const Noncopyable &cond9 = b ? Derived() : cnc; // expected-error {{incompatible}}
+
+ extern const volatile Noncopyable make_cv();
+ Noncopyable cv_difference1 = make_cv();
+ const volatile Noncopyable cv_difference2 = make();
+}
+
+template<typename T> struct ConversionFunction { operator T(); };
+Noncopyable cf1 = ConversionFunction<Noncopyable>();
+Noncopyable cf2 = ConversionFunction<Noncopyable&&>(); // expected-error {{deleted}}
+Noncopyable cf3 = ConversionFunction<const volatile Noncopyable>();
+const volatile Noncopyable cf4 = ConversionFunction<Noncopyable>();
+Noncopyable cf5 = ConversionFunction<Derived>(); // expected-error {{deleted}}
+
+struct AsMember {
+ Noncopyable member;
+ AsMember() : member(make()) {}
+};
+// FIXME: DR (no number yet): we still get a copy for base or delegating construction.
+struct AsBase : Noncopyable {
+ AsBase() : Noncopyable(make()) {} // expected-error {{deleted}}
+};
+struct AsDelegating final {
+ AsDelegating(const AsDelegating &) = delete; // expected-note {{deleted}}
+ static AsDelegating make(int);
+
+ // The base constructor version of this is problematic; the complete object
+ // version would be OK. Perhaps we could allow copy omission here for final
+ // classes?
+ AsDelegating(int n) : AsDelegating(make(n)) {} // expected-error {{deleted}}
+};
diff --git a/test/SemaCXX/cxx1z-decomposition.cpp b/test/SemaCXX/cxx1z-decomposition.cpp
new file mode 100644
index 000000000000..735a9e1dfee0
--- /dev/null
+++ b/test/SemaCXX/cxx1z-decomposition.cpp
@@ -0,0 +1,68 @@
+// RUN: %clang_cc1 -std=c++1z -verify %s
+
+void use_from_own_init() {
+ auto [a] = a; // expected-error {{binding 'a' cannot appear in the initializer of its own decomposition declaration}}
+}
+
+// As a Clang extension, _Complex can be decomposed.
+float decompose_complex(_Complex float cf) {
+ static _Complex float scf;
+ auto &[sre, sim] = scf;
+ // ok, this is references initialized by constant expressions all the way down
+ static_assert(&sre == &__real scf);
+ static_assert(&sim == &__imag scf);
+
+ auto [re, im] = cf;
+ return re*re + im*im;
+}
+
+// As a Clang extension, vector types can be decomposed.
+typedef float vf3 __attribute__((ext_vector_type(3)));
+float decompose_vector(vf3 v) {
+ auto [x, y, z] = v;
+ auto *p = &x; // expected-error {{address of vector element requested}}
+ return x + y + z;
+}
+
+struct S { int a, b; };
+constexpr int f(S s) {
+ auto &[a, b] = s;
+ return a * 10 + b;
+}
+static_assert(f({1, 2}) == 12);
+
+constexpr bool g(S &&s) {
+ auto &[a, b] = s;
+ return &a == &s.a && &b == &s.b && &a != &b;
+}
+static_assert(g({1, 2}));
+
+void enclosing() {
+ struct S { int a; };
+ auto [n] = S(); // expected-note 2{{'n' declared here}}
+
+ struct Q { int f() { return n; } }; // expected-error {{reference to local binding 'n' declared in enclosing function}}
+ // FIXME: This is probably supposed to be valid, but we do not have clear rules on how it's supposed to work.
+ (void) [&] { return n; }; // expected-error {{reference to local binding 'n' declared in enclosing function}}
+ (void) [n] {}; // expected-error {{'n' in capture list does not name a variable}}
+}
+
+void bitfield() {
+ struct { int a : 3, : 4, b : 5; } a;
+ auto &[x, y] = a;
+ auto &[p, q, r] = a; // expected-error {{decomposes into 2 elements, but 3 names were provided}}
+}
+
+void for_range() {
+ int x = 1;
+ for (auto[a, b] : x) { // expected-error {{invalid range expression of type 'int'; no viable 'begin' function available}}
+ a++;
+ }
+
+ int y[5];
+ for (auto[c] : y) { // expected-error {{cannot decompose non-class, non-array type 'int'}}
+ c++;
+ }
+}
+
+// FIXME: by-value array copies
diff --git a/test/SemaCXX/cxx1z-noexcept-function-type.cpp b/test/SemaCXX/cxx1z-noexcept-function-type.cpp
new file mode 100644
index 000000000000..a3f710970456
--- /dev/null
+++ b/test/SemaCXX/cxx1z-noexcept-function-type.cpp
@@ -0,0 +1,167 @@
+// RUN: %clang_cc1 -std=c++14 -verify -fexceptions -fcxx-exceptions %s
+// RUN: %clang_cc1 -std=c++1z -verify -fexceptions -fcxx-exceptions %s -Wno-dynamic-exception-spec
+
+#if __cplusplus > 201402L
+
+template<typename T> void redecl1() noexcept(noexcept(T())) {} // expected-note {{previous}}
+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}}
+
+// These have the same canonical type, but are still different.
+template<typename A, typename B> void redecl3() throw(A); // expected-note {{previous}}
+template<typename A, typename B> void redecl3() throw(B); // expected-error {{does not match previous}}
+
+typedef int I;
+template<bool B> void redecl4(I) noexcept(B);
+template<bool B> void redecl4(I) noexcept(B); // expected-note {{failed template argument deduction}}
+
+void (*init_with_exact_type_a)(int) noexcept = redecl4<true>;
+void (*init_with_mismatched_type_a)(int) = redecl4<true>;
+auto deduce_auto_from_noexcept_function_ptr_a = redecl4<true>;
+using DeducedType_a = decltype(deduce_auto_from_noexcept_function_ptr_a);
+using DeducedType_a = void (*)(int) noexcept;
+
+void (*init_with_exact_type_b)(int) = redecl4<false>;
+void (*init_with_mismatched_type_b)(int) noexcept = redecl4<false>; // expected-error {{does not match required type}}
+auto deduce_auto_from_noexcept_function_ptr_b = redecl4<false>;
+using DeducedType_b = decltype(deduce_auto_from_noexcept_function_ptr_b);
+using DeducedType_b = void (*)(int);
+
+static_assert(noexcept(init_with_exact_type_a(0)));
+static_assert(noexcept((+init_with_exact_type_a)(0)));
+static_assert(!noexcept(init_with_exact_type_b(0)));
+static_assert(!noexcept((+init_with_exact_type_b)(0)));
+
+// Don't look through casts, use the direct type of the expression.
+// FIXME: static_cast here would be reasonable, but is not currently permitted.
+static_assert(noexcept(static_cast<decltype(init_with_exact_type_a)>(init_with_exact_type_b)(0))); // expected-error {{is not allowed}}
+static_assert(noexcept(reinterpret_cast<decltype(init_with_exact_type_a)>(init_with_exact_type_b)(0)));
+static_assert(!noexcept(static_cast<decltype(init_with_exact_type_b)>(init_with_exact_type_a)(0)));
+
+template<bool B> auto get_fn() noexcept -> void (*)() noexcept(B) {}
+static_assert(noexcept(get_fn<true>()()));
+static_assert(!noexcept(get_fn<false>()()));
+
+namespace DependentDefaultCtorExceptionSpec {
+ template<typename> struct T { static const bool value = true; };
+
+ template<class A> struct map {
+ typedef A a;
+ map() noexcept(T<a>::value) {}
+ };
+
+ template<class B> struct multimap {
+ typedef B b;
+ multimap() noexcept(T<b>::value) {}
+ };
+
+ // Don't crash here.
+ struct A { multimap<int> Map; } a;
+
+ static_assert(noexcept(A()));
+}
+
+#endif
+
+namespace CompatWarning {
+ struct X;
+
+ // These cases don't change.
+ void f0(void p() throw(int));
+ auto f0() -> void (*)() noexcept(false);
+
+ // These cases take an ABI break in C++17 because their parameter / return types change.
+ void f1(void p() noexcept);
+ void f2(void (*p)() noexcept(true));
+ void f3(void (&p)() throw());
+ void f4(void (X::*p)() throw());
+ auto f5() -> void (*)() throw();
+ auto f6() -> void (&)() throw();
+ auto f7() -> void (X::*)() throw();
+#if __cplusplus <= 201402L
+ // expected-warning@-8 {{mangled name of 'f1' will change in C++17 due to non-throwing exception specification in function signature}}
+ // expected-warning@-8 {{mangled name of 'f2' will change in C++17 due to non-throwing exception specification in function signature}}
+ // expected-warning@-8 {{mangled name of 'f3' will change in C++17 due to non-throwing exception specification in function signature}}
+ // expected-warning@-8 {{mangled name of 'f4' will change in C++17 due to non-throwing exception specification in function signature}}
+ // expected-warning@-8 {{mangled name of 'f5' will change in C++17 due to non-throwing exception specification in function signature}}
+ // expected-warning@-8 {{mangled name of 'f6' will change in C++17 due to non-throwing exception specification in function signature}}
+ // expected-warning@-8 {{mangled name of 'f7' will change in C++17 due to non-throwing exception specification in function signature}}
+#endif
+
+ // An instantiation-dependent exception specification needs to be mangled in
+ // all language modes, since it participates in SFINAE.
+ template<typename T> void g(void() throw(T)); // expected-note {{substitution failure}}
+ template<typename T> void g(...) = delete; // expected-note {{deleted}}
+ void test_g() { g<void>(nullptr); } // expected-error {{deleted}}
+
+ // An instantiation-dependent exception specification needs to be mangled in
+ // all language modes, since it participates in SFINAE.
+ template<typename T> void h(void() noexcept(T())); // expected-note {{substitution failure}}
+ template<typename T> void h(...) = delete; // expected-note {{deleted}}
+ void test_h() { h<void>(nullptr); } // expected-error {{deleted}}
+}
+
+namespace ImplicitExceptionSpec {
+ struct S {
+ ~S();
+ void f(const S &s = S());
+ };
+ S::~S() {}
+}
+
+namespace Builtins {
+ // Pick two functions that ought to have the same noexceptness.
+ extern "C" int strcmp(const char *, const char *);
+ extern "C" int strncmp(const char *, const char *, decltype(sizeof(0))) noexcept;
+
+ // Check we recognized both as builtins.
+ typedef int arr[strcmp("bar", "foo") + 4 * strncmp("foo", "bar", 4)];
+ typedef int arr[3];
+}
+
+namespace ExplicitInstantiation {
+ template<typename T> void f() noexcept {}
+ template<typename T> struct X { void f() noexcept {} };
+ template void f<int>();
+ template void X<int>::f();
+}
+
+namespace ConversionFunction {
+ struct A { template<typename T> operator T() noexcept; };
+ int a = A().operator int();
+}
+
+using size_t = decltype(sizeof(0));
+
+namespace OperatorDelete {
+ struct W {};
+ struct X {};
+ struct Y {};
+ struct Z {};
+ template<bool N, bool D> struct T {};
+}
+void *operator new(size_t, OperatorDelete::W) noexcept(false);
+void operator delete(void*, OperatorDelete::W) noexcept(false) = delete; // expected-note {{here}}
+void *operator new(size_t, OperatorDelete::X) noexcept(false);
+void operator delete(void*, OperatorDelete::X) noexcept(true) = delete; // expected-note {{here}}
+void *operator new(size_t, OperatorDelete::Y) noexcept(true);
+void operator delete(void*, OperatorDelete::Y) noexcept(false) = delete; // expected-note {{here}}
+void *operator new(size_t, OperatorDelete::Z) noexcept(true);
+void operator delete(void*, OperatorDelete::Z) noexcept(true) = delete; // expected-note {{here}}
+template<bool N, bool D> void *operator new(size_t, OperatorDelete::T<N, D>) noexcept(N);
+template<bool N, bool D> void operator delete(void*, OperatorDelete::T<N, D>) noexcept(D) = delete; // expected-note 4{{here}}
+namespace OperatorDelete {
+ struct A { A(); };
+ A *w = new (W{}) A; // expected-error {{deleted function}}
+ A *x = new (X{}) A; // expected-error {{deleted function}}
+ A *y = new (Y{}) A; // expected-error {{deleted function}}
+ A *z = new (Z{}) A; // expected-error {{deleted function}}
+
+ A *t00 = new (T<false, false>{}) A; // expected-error {{deleted function}}
+ A *t01 = new (T<false, true>{}) A; // expected-error {{deleted function}}
+ A *t10 = new (T<true, false>{}) A; // expected-error {{deleted function}}
+ A *t11 = new (T<true, true>{}) A; // expected-error {{deleted function}}
+}
diff --git a/test/SemaCXX/cxx1z-user-defined-literals.cpp b/test/SemaCXX/cxx1z-user-defined-literals.cpp
new file mode 100644
index 000000000000..978fd2fbc4b2
--- /dev/null
+++ b/test/SemaCXX/cxx1z-user-defined-literals.cpp
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -std=c++1z %s -include %s -verify
+
+#ifndef INCLUDED
+#define INCLUDED
+
+#pragma clang system_header
+namespace std {
+ using size_t = decltype(sizeof(0));
+
+ struct string_view {};
+ string_view operator""sv(const char*, size_t);
+}
+
+#else
+
+using namespace std;
+string_view s = "foo"sv;
+const char* p = "bar"sv; // expected-error {{no viable conversion}}
+char error = 'x'sv; // expected-error {{invalid suffix}} expected-error {{expected ';'}}
+
+#endif
diff --git a/test/SemaCXX/cxx98-compat-flags.cpp b/test/SemaCXX/cxx98-compat-flags.cpp
index f90ad345e975..62d687c49cf7 100644
--- a/test/SemaCXX/cxx98-compat-flags.cpp
+++ b/test/SemaCXX/cxx98-compat-flags.cpp
@@ -16,7 +16,7 @@ namespace CopyCtorIssues {
Private(const Private&); // expected-note {{declared private here}}
};
struct NoViable {
- NoViable();
+ NoViable(); // expected-note {{not viable}}
NoViable(NoViable&); // expected-note {{not viable}}
};
struct Ambiguous {
diff --git a/test/SemaCXX/cxx98-compat-pedantic.cpp b/test/SemaCXX/cxx98-compat-pedantic.cpp
index 38bc341e83ce..c72c44ad5feb 100644
--- a/test/SemaCXX/cxx98-compat-pedantic.cpp
+++ b/test/SemaCXX/cxx98-compat-pedantic.cpp
@@ -21,10 +21,6 @@ enum Enum {
Enum_value, // expected-warning {{commas at the end of enumerator lists are incompatible with C++98}}
};
-template<typename T> struct InstantiationAfterSpecialization {};
-template<> struct InstantiationAfterSpecialization<int> {}; // expected-note {{here}}
-template struct InstantiationAfterSpecialization<int>; // expected-warning {{explicit instantiation of 'InstantiationAfterSpecialization<int>' that occurs after an explicit specialization is incompatible with C++98}}
-
void *dlsym();
void (*FnPtr)() = (void(*)())dlsym(); // expected-warning {{cast between pointer-to-function and pointer-to-object is incompatible with C++98}}
void *FnVoidPtr = (void*)&dlsym; // expected-warning {{cast between pointer-to-function and pointer-to-object is incompatible with C++98}}
@@ -59,7 +55,7 @@ namespace CopyCtorIssues {
Private(const Private&); // expected-note {{declared private here}}
};
struct NoViable {
- NoViable();
+ NoViable(); // expected-note {{not viable}}
NoViable(NoViable&); // expected-note {{not viable}}
};
struct Ambiguous {
diff --git a/test/SemaCXX/cxx98-compat.cpp b/test/SemaCXX/cxx98-compat.cpp
index 25a086d9bcd3..4a9baf5100d6 100644
--- a/test/SemaCXX/cxx98-compat.cpp
+++ b/test/SemaCXX/cxx98-compat.cpp
@@ -361,7 +361,7 @@ template<typename T> T var = T(10);
// diagnosed the primary template.
template<typename T> T* var<T*> = new T();
template<> int var<int> = 10;
-template int var<int>;
+template char var<char>;
float fvar = var<float>;
class A {
@@ -391,7 +391,7 @@ template<typename T> T B::v = T();
template<typename T> T* B::v<T*> = new T();
template<> int B::v<int> = 10;
-template int B::v<int>;
+template char B::v<char>;
float fsvar = B::v<float>;
#ifdef CXX14COMPAT
diff --git a/test/SemaCXX/default-arg-closures.cpp b/test/SemaCXX/default-arg-closures.cpp
new file mode 100644
index 000000000000..e076cc05cd20
--- /dev/null
+++ b/test/SemaCXX/default-arg-closures.cpp
@@ -0,0 +1,45 @@
+// RUN: %clang_cc1 -triple x86_64-windows-msvc -fexceptions -fcxx-exceptions -fms-extensions -verify %s -std=c++11
+
+// The MS ABI has a few ways to generate constructor closures, which require
+// instantiating and checking the semantics of default arguments. Make sure we
+// do that right.
+
+// FIXME: Don't diagnose this issue twice.
+template <typename T>
+struct DependentDefaultCtorArg { // expected-note {{in instantiation of default function argument}}
+ // expected-error@+1 2 {{type 'int' cannot be used prior to '::' because it has no members}}
+ DependentDefaultCtorArg(int n = T::error);
+};
+struct
+__declspec(dllexport) // expected-note {{due to 'ExportDefaultCtorClosure' being dllexported}}
+ExportDefaultCtorClosure // expected-note {{implicit default constructor for 'ExportDefaultCtorClosure' first required here}}
+: DependentDefaultCtorArg<int> // expected-note {{in instantiation of template class}}
+{};
+
+template <typename T>
+struct DependentDefaultCopyArg {
+ DependentDefaultCopyArg() {}
+ // expected-error@+1 {{type 'int' cannot be used prior to '::' because it has no members}}
+ DependentDefaultCopyArg(const DependentDefaultCopyArg &o, int n = T::member) {}
+};
+
+struct HasMember {
+ enum { member = 0 };
+};
+void UseDependentArg() { throw DependentDefaultCopyArg<HasMember>(); }
+
+void ErrorInDependentArg() {
+ throw DependentDefaultCopyArg<int>(); // expected-note {{required here}}
+}
+
+struct HasCleanup {
+ ~HasCleanup();
+};
+
+struct Default {
+ Default(const Default &o, int d = (HasCleanup(), 42));
+};
+
+void f(const Default &d) {
+ throw d;
+}
diff --git a/test/SemaCXX/deprecated.cpp b/test/SemaCXX/deprecated.cpp
index 4ce058968742..0fd275e2cec6 100644
--- a/test/SemaCXX/deprecated.cpp
+++ b/test/SemaCXX/deprecated.cpp
@@ -7,13 +7,17 @@
#include "Inputs/register.h"
-void f() throw();
-void g() throw(int);
-void h() throw(...);
-#if __cplusplus >= 201103L
+void g() throw();
+void h() throw(int);
+void i() throw(...);
+#if __cplusplus > 201402L
// expected-warning@-4 {{dynamic exception specifications are deprecated}} expected-note@-4 {{use 'noexcept' instead}}
-// expected-warning@-4 {{dynamic exception specifications are deprecated}} expected-note@-4 {{use 'noexcept(false)' instead}}
-// expected-warning@-4 {{dynamic exception specifications are deprecated}} expected-note@-4 {{use 'noexcept(false)' instead}}
+// expected-error@-4 {{ISO C++1z does not allow dynamic exception specifications}} expected-note@-4 {{use 'noexcept(false)' instead}}
+// expected-error@-4 {{ISO C++1z does not allow dynamic exception specifications}} expected-note@-4 {{use 'noexcept(false)' instead}}
+#elif __cplusplus >= 201103L
+// expected-warning@-8 {{dynamic exception specifications are deprecated}} expected-note@-8 {{use 'noexcept' instead}}
+// expected-warning@-8 {{dynamic exception specifications are deprecated}} expected-note@-8 {{use 'noexcept(false)' instead}}
+// expected-warning@-8 {{dynamic exception specifications are deprecated}} expected-note@-8 {{use 'noexcept(false)' instead}}
#endif
void stuff() {
diff --git a/test/SemaCXX/derived-to-base-ambig.cpp b/test/SemaCXX/derived-to-base-ambig.cpp
index 93bd3619ccdf..5d1d56b76614 100644
--- a/test/SemaCXX/derived-to-base-ambig.cpp
+++ b/test/SemaCXX/derived-to-base-ambig.cpp
@@ -6,7 +6,7 @@ class D : public B, public C { };
void f(D* d) {
A* a;
- a = d; // expected-error{{ambiguous conversion from derived class 'D' to base class 'A':}} expected-error{{assigning to 'A *' from incompatible type 'D *'}}
+ a = d; // expected-error{{ambiguous conversion from derived class 'D' to base class 'A':}}
}
class Object2 { };
@@ -20,7 +20,7 @@ class F2 : public E2, public A2 { }; // expected-warning{{direct base 'A2' is in
void g(E2* e2, F2* f2) {
Object2* o2;
o2 = e2;
- o2 = f2; // expected-error{{ambiguous conversion from derived class 'F2' to base class 'Object2':}} expected-error{{assigning to 'Object2 *' from incompatible type 'F2 *'}}
+ o2 = f2; // expected-error{{ambiguous conversion from derived class 'F2' to base class 'Object2':}}
}
// Test that ambiguous/inaccessibility checking does not trigger too
diff --git a/test/SemaCXX/designated-initializers.cpp b/test/SemaCXX/designated-initializers.cpp
new file mode 100644
index 000000000000..e5b5f3c9cce2
--- /dev/null
+++ b/test/SemaCXX/designated-initializers.cpp
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -Winitializer-overrides %s
+
+template <typename T> struct Foo {
+ struct SubFoo {
+ int bar1;
+ int bar2;
+ };
+
+ static void Test() { SubFoo sf = {.bar1 = 10, .bar2 = 20}; } // Expected no warning
+};
+
+void foo() {
+ Foo<int>::Test();
+ Foo<bool>::Test();
+ Foo<float>::Test();
+}
+
+template <typename T> struct Bar {
+ struct SubFoo {
+ int bar1;
+ int bar2;
+ };
+
+ static void Test() { SubFoo sf = {.bar1 = 10, // expected-note 2 {{previous initialization is here}}
+ .bar1 = 20}; } // expected-warning 2 {{initializer overrides prior initialization of this subobject}}
+};
+
+void bar() {
+ Bar<int>::Test(); // expected-note {{in instantiation of member function 'Bar<int>::Test' requested here}}
+ Bar<bool>::Test(); // expected-note {{in instantiation of member function 'Bar<bool>::Test' requested here}}
+}
diff --git a/test/SemaCXX/elaborated-type-specifier.cpp b/test/SemaCXX/elaborated-type-specifier.cpp
index 81c5cb4eac59..3701dd7ba630 100644
--- a/test/SemaCXX/elaborated-type-specifier.cpp
+++ b/test/SemaCXX/elaborated-type-specifier.cpp
@@ -52,3 +52,12 @@ namespace test5 {
}
};
}
+
+namespace test6 {
+struct C {
+ template <typename> friend struct A; // expected-note {{'A' declared here}}
+};
+struct B {
+ struct A *p; // expected-error {{implicit declaration introduced by elaborated type conflicts with a template of the same name}}
+};
+}
diff --git a/test/SemaCXX/enable_if.cpp b/test/SemaCXX/enable_if.cpp
index 81308136c480..0f8fc9b2652a 100644
--- a/test/SemaCXX/enable_if.cpp
+++ b/test/SemaCXX/enable_if.cpp
@@ -440,3 +440,27 @@ void testFoo() {
foo(1, 0, m, 3); // expected-error{{no matching}}
}
}
+
+// Tests that we emit errors at the point of the method call, rather than the
+// beginning of the expression that happens to be a member call.
+namespace member_loc {
+ struct Foo { void bar() __attribute__((enable_if(0, ""))); }; // expected-note{{disabled}}
+ void testFoo() {
+ Foo()
+ .bar(); // expected-error{{no matching member function}}
+ }
+}
+
+// Prior bug: we wouldn't properly convert conditions to bools when
+// instantiating templates in some cases.
+namespace template_instantiation {
+template <typename T>
+struct Foo {
+ void bar(int a) __attribute__((enable_if(a, ""))); // expected-note{{disabled}}
+};
+
+void runFoo() {
+ Foo<double>().bar(0); // expected-error{{no matching}}
+ Foo<double>().bar(1);
+}
+}
diff --git a/test/SemaCXX/expression-traits.cpp b/test/SemaCXX/expression-traits.cpp
index 51bb90e8bbf9..d965d14747ae 100644
--- a/test/SemaCXX/expression-traits.cpp
+++ b/test/SemaCXX/expression-traits.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -fcxx-exceptions %s
+// RUN: %clang_cc1 -std=c++98 -fsyntax-only -verify -fcxx-exceptions %s
//
// Tests for "expression traits" intrinsics such as __is_lvalue_expr.
diff --git a/test/SemaCXX/friend.cpp b/test/SemaCXX/friend.cpp
index 4f27f4df6c90..1f64ba609b16 100644
--- a/test/SemaCXX/friend.cpp
+++ b/test/SemaCXX/friend.cpp
@@ -379,3 +379,12 @@ namespace tag_redecl {
X *q = p;
}
}
+
+namespace default_arg {
+ void f();
+ void f(void*); // expected-note {{previous}}
+ struct X {
+ friend void f(int a, int b = 0) {}
+ friend void f(void *p = 0) {} // expected-error {{must be the only}}
+ };
+}
diff --git a/test/SemaCXX/friend2.cpp b/test/SemaCXX/friend2.cpp
new file mode 100644
index 000000000000..347af0d61b1b
--- /dev/null
+++ b/test/SemaCXX/friend2.cpp
@@ -0,0 +1,172 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11
+
+// If a friend function is defined in several non-template classes,
+// it is an error.
+
+void func1(int);
+struct C1a {
+ friend void func1(int) {} // expected-note{{previous definition is here}}
+};
+struct C1b {
+ friend void func1(int) {} // expected-error{{redefinition of 'func1'}}
+};
+
+
+// If a friend function is defined in both non-template and template
+// classes it is an error only if the template is instantiated.
+
+void func2(int);
+struct C2a {
+ friend void func2(int) {}
+};
+template<typename T> struct C2b {
+ friend void func2(int) {}
+};
+
+void func3(int);
+struct C3a {
+ friend void func3(int) {} // expected-note{{previous definition is here}}
+};
+template<typename T> struct C3b {
+ friend void func3(int) {} // expected-error{{redefinition of 'func3'}}
+};
+C3b<long> c3; // expected-note{{in instantiation of template class 'C3b<long>' requested here}}
+
+
+// If a friend function is defined in several template classes it is an error
+// only if several templates are instantiated.
+
+void func4(int);
+template<typename T> struct C4a {
+ friend void func4(int) {}
+};
+template<typename T> struct C4b {
+ friend void func4(int) {}
+};
+
+
+void func5(int);
+template<typename T> struct C5a {
+ friend void func5(int) {}
+};
+template<typename T> struct C5b {
+ friend void func5(int) {}
+};
+C5a<long> c5a;
+
+void func6(int);
+template<typename T> struct C6a {
+ friend void func6(int) {} // expected-note{{previous definition is here}}
+};
+template<typename T> struct C6b {
+ friend void func6(int) {} // expected-error{{redefinition of 'func6'}}
+};
+C6a<long> c6a;
+C6b<int*> c6b; // expected-note{{in instantiation of template class 'C6b<int *>' requested here}}
+
+void func7(int);
+template<typename T> struct C7 {
+ friend void func7(int) {} // expected-error{{redefinition of 'func7'}}
+ // expected-note@-1{{previous definition is here}}
+};
+C7<long> c7a;
+C7<int*> c7b; // expected-note{{in instantiation of template class 'C7<int *>' requested here}}
+
+
+// Even if clases are not instantiated and hence friend functions defined in them are not
+// available, their declarations can be checked.
+
+void func8(int); // expected-note{{previous declaration is here}}
+template<typename T> struct C8a {
+ friend long func8(int); // expected-error{{functions that differ only in their return type cannot be overloaded}}
+};
+
+void func9(int); // expected-note{{previous declaration is here}}
+template<typename T> struct C9a {
+ friend int func9(int); // expected-error{{functions that differ only in their return type cannot be overloaded}}
+};
+
+void func10(int); // expected-note{{previous declaration is here}}
+template<typename T> struct C10a {
+ friend int func10(int); // expected-error{{functions that differ only in their return type cannot be overloaded}}
+};
+
+void func_11(); // expected-note{{previous declaration is here}}
+template<typename T> class C11 {
+ friend int func_11(); // expected-error{{functions that differ only in their return type cannot be overloaded}}
+};
+
+void func_12(int x); // expected-note{{previous declaration is here}}
+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}}
+};
+
+
+namespace pr22307 {
+
+struct t {
+ friend int leak(t);
+};
+
+template<typename v>
+struct m {
+ friend int leak(t) { return sizeof(v); } // expected-error{{redefinition of 'leak'}} expected-note{{previous definition is here}}
+};
+
+template struct m<char>;
+template struct m<short>; // expected-note{{in instantiation of template class 'pr22307::m<short>' requested here}}
+
+int main() {
+ leak(t());
+}
+
+}
+
+namespace pr17923 {
+
+void f(unsigned long long);
+
+template<typename T> struct X {
+ friend void f(unsigned long long) {
+ T t;
+ }
+};
+
+int main() { f(1234); }
+
+}
+
+namespace pr17923a {
+
+int get();
+
+template< int value >
+class set {
+ friend int get()
+ { return value; } // return 0; is OK
+};
+
+template class set< 5 >;
+
+int main() {
+ get();
+}
+
+}
+
+namespace pr8035 {
+
+void Function();
+
+int main(int argc, char* argv[]) {
+ Function();
+}
+
+template <typename T>
+struct Test {
+ friend void Function() { }
+};
+
+template class Test<int>;
+
+}
diff --git a/test/SemaCXX/function-redecl-2.cpp b/test/SemaCXX/function-redecl-2.cpp
new file mode 100644
index 000000000000..9ceeb205be88
--- /dev/null
+++ b/test/SemaCXX/function-redecl-2.cpp
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
+
+namespace redecl_in_templ {
+template<typename T> void redecl_in_templ() {
+ extern void func_1(); // expected-note {{previous declaration is here}}
+ extern int func_1(); // expected-error {{functions that differ only in their return type cannot be overloaded}}
+}
+
+void g();
+constexpr void (*p)() = g;
+
+template<bool> struct X {};
+template<> struct X<true> { typedef int type; };
+
+template<typename T> void f() {
+ extern void g();
+ X<&g == p>::type n;
+}
+}
diff --git a/test/SemaCXX/implicit-exception-spec.cpp b/test/SemaCXX/implicit-exception-spec.cpp
index ff3d685d912e..12871b8ce707 100644
--- a/test/SemaCXX/implicit-exception-spec.cpp
+++ b/test/SemaCXX/implicit-exception-spec.cpp
@@ -16,31 +16,31 @@ namespace InClassInitializers {
// Noexcept::Noexcept is not declared constexpr, therefore noexcept(Noexcept())
// is false.
bool ThrowSomething() noexcept(false);
- struct ConstExpr {
- bool b = noexcept(ConstExpr()) && ThrowSomething(); // expected-error {{cannot use defaulted default constructor of 'ConstExpr' within the class outside of member functions}}
+ struct ConstExpr { // expected-error {{default member initializer for 'b' needed}}
+ bool b = noexcept(ConstExpr()) && ThrowSomething(); // expected-note {{declared here}}
// expected-note@-1 {{implicit default constructor for 'InClassInitializers::ConstExpr' first required here}}
};
// Much more obviously broken: we can't parse the initializer without already
// knowing whether it produces a noexcept expression.
- struct TemplateArg {
- int n = ExceptionIf<noexcept(TemplateArg())>::f(); // expected-error {{cannot use defaulted default constructor of 'TemplateArg' within the class outside of member functions}}
+ struct TemplateArg { // expected-error {{default member initializer for 'n' needed}}
+ int n = ExceptionIf<noexcept(TemplateArg())>::f(); // expected-note {{declared here}}
// expected-note@-1 {{implicit default constructor for 'InClassInitializers::TemplateArg' first required here}}
};
// And within a nested class.
struct Nested { // expected-note {{implicit default constructor for 'InClassInitializers::Nested::Inner' first required here}}
- struct Inner {
- // expected-error@+1 {{cannot use defaulted default constructor of 'Inner' within 'Nested' outside of member functions}}
- int n = ExceptionIf<noexcept(Nested())>::f(); // expected-note {{implicit default constructor for 'InClassInitializers::Nested' first required here}}
+ struct Inner { // expected-error {{default member initializer for 'n' needed}}
+ int n = // expected-note {{declared here}}
+ ExceptionIf<noexcept(Nested())>::f(); // expected-note {{implicit default constructor for 'InClassInitializers::Nested' first required here}}
} inner;
};
struct Nested2 { // expected-error {{implicit default constructor for 'InClassInitializers::Nested2' must explicitly initialize the member 'inner' which does not have a default constructor}}
struct Inner;
int n = Inner().n; // expected-note {{implicit default constructor for 'InClassInitializers::Nested2::Inner' first required here}}
- struct Inner { // expected-note {{declared here}}
- // expected-error@+1 {{cannot use defaulted default constructor of 'Inner' within 'Nested2' outside of member functions}}
+ struct Inner { // expected-error {{initializer for 'n' needed}} expected-note {{declared here}}
+ // expected-note@+1 {{declared here}}
int n = ExceptionIf<noexcept(Nested2())>::f();
// expected-note@-1 {{implicit default constructor for 'InClassInitializers::Nested2' first required here}}
} inner; // expected-note {{member is declared here}}
diff --git a/test/SemaCXX/instantiate-template-fatal-error.cpp b/test/SemaCXX/instantiate-template-fatal-error.cpp
new file mode 100644
index 000000000000..9c8916e77bb0
--- /dev/null
+++ b/test/SemaCXX/instantiate-template-fatal-error.cpp
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++14 %s
+
+#pragma clang diagnostic fatal "-Wall"
+#pragma clang diagnostic fatal "-Wold-style-cast"
+
+template <class T> bool foo0(const long long *a, T* b) {
+ return a == (const long long*)b; // expected-error {{use of old-style cast}}
+}
+
+template<class T>
+struct S1 {
+};
+
+template<class T>
+struct S2 : S1<T> {
+ bool m1(const long long *a, T *b) const { return foo0(a, b); }
+};
+
+bool foo1(const long long *a, int *b) {
+ S2<int> s2;
+ return s2.m1(a, b);
+}
diff --git a/test/SemaCXX/lambda-expressions.cpp b/test/SemaCXX/lambda-expressions.cpp
index 5fffe4111783..e0ab15dc6327 100644
--- a/test/SemaCXX/lambda-expressions.cpp
+++ b/test/SemaCXX/lambda-expressions.cpp
@@ -95,6 +95,39 @@ namespace ImplicitCapture {
}
}
+namespace SpecialMembers {
+ void f() {
+ auto a = []{}; // expected-note 2{{here}} expected-note 2{{candidate}}
+ decltype(a) b; // expected-error {{no matching constructor}}
+ decltype(a) c = a;
+ decltype(a) d = static_cast<decltype(a)&&>(a);
+ a = a; // expected-error {{copy assignment operator is implicitly deleted}}
+ a = static_cast<decltype(a)&&>(a); // expected-error {{copy assignment operator is implicitly deleted}}
+ }
+ struct P {
+ P(const P&) = delete; // expected-note {{deleted here}}
+ };
+ struct Q {
+ ~Q() = delete; // expected-note {{deleted here}}
+ };
+ struct R {
+ R(const R&) = default;
+ R(R&&) = delete;
+ R &operator=(const R&) = delete;
+ R &operator=(R&&) = delete;
+ };
+ void g(P &p, Q &q, R &r) {
+ auto pp = [p]{}; // expected-error {{deleted constructor}}
+ auto qq = [q]{}; // expected-error {{deleted function}} expected-note {{because}}
+
+ auto a = [r]{}; // expected-note 2{{here}}
+ decltype(a) b = a;
+ decltype(a) c = static_cast<decltype(a)&&>(a); // ok, copies R
+ a = a; // expected-error {{copy assignment operator is implicitly deleted}}
+ a = static_cast<decltype(a)&&>(a); // expected-error {{copy assignment operator is implicitly deleted}}
+ }
+}
+
namespace PR12031 {
struct X {
template<typename T>
@@ -525,3 +558,18 @@ int func() {
decltype(a)::D b;
}
}
+
+namespace PR30566 {
+int name1; // expected-note {{'name1' declared here}}
+
+struct S1 {
+ template<class T>
+ S1(T t) { s = sizeof(t); }
+ int s;
+};
+
+void foo1() {
+ auto s0 = S1{[name=]() {}}; // expected-error 2 {{expected expression}}
+ auto s1 = S1{[name=name]() {}}; // expected-error {{use of undeclared identifier 'name'; did you mean 'name1'?}}
+}
+}
diff --git a/test/SemaCXX/libstdcxx_libcxx_less_hack.cpp b/test/SemaCXX/libstdcxx_libcxx_less_hack.cpp
new file mode 100644
index 000000000000..53b6a3b2c42d
--- /dev/null
+++ b/test/SemaCXX/libstdcxx_libcxx_less_hack.cpp
@@ -0,0 +1,67 @@
+// This is a test for a hack in Clang that works around a problem introduced by
+// DR583: it's no longer possible to compare a pointer against nullptr_t, but
+// we still want to permit those comparisons within less<> and friends.
+
+// RUN: %clang_cc1 -verify %s -std=c++14
+
+namespace std {
+ template<typename T = void> struct less {};
+ template<typename T = void> struct less_equal {};
+ template<typename T = void> struct greater {};
+ template<typename T = void> struct greater_equal {};
+
+ template<> struct less<> {
+ template <class T1, class T2>
+ auto operator()(T1 &&t, T2 &&u) const noexcept(noexcept(t < u))
+ -> decltype(t < u) {
+ return t < u;
+ }
+ };
+
+ template<> struct less_equal<> {
+ template <class T1, class T2>
+ auto operator()(T1 &&t, T2 &&u) const noexcept(noexcept(t <= u))
+ -> decltype(t <= u) {
+ return t <= u;
+ }
+ };
+
+ template<> struct greater<> {
+ template <class T1, class T2>
+ auto operator()(T1 &&t, T2 &&u) const noexcept(noexcept(t > u))
+ -> decltype(t > u) {
+ return t > u;
+ }
+ };
+
+ template<> struct greater_equal<> {
+ template <class T1, class T2>
+ auto operator()(T1 &&t, T2 &&u) const noexcept(noexcept(t >= u))
+ -> decltype(t >= u) {
+ return t >= u;
+ }
+ };
+
+ template<typename = void> struct unrelated;
+ template<> struct unrelated<> {
+ template <class T1, class T2>
+ auto operator()(T1 &&t, T2 &&u) const noexcept(noexcept(t < u)) // expected-note {{substitution failure}}
+ -> decltype(t < u) {
+ return t < u;
+ }
+ };
+};
+
+void test(int *p) {
+ using namespace std;
+ less<>()(p, nullptr);
+ less<>()(nullptr, p);
+ less_equal<>()(p, nullptr);
+ less_equal<>()(nullptr, p);
+ greater<>()(p, nullptr);
+ greater<>()(nullptr, p);
+ greater_equal<>()(p, nullptr);
+ greater_equal<>()(nullptr, p);
+
+ unrelated<>()(p, nullptr); // expected-error {{no matching function}}
+}
diff --git a/test/SemaCXX/libstdcxx_pair_swap_hack.cpp b/test/SemaCXX/libstdcxx_pair_swap_hack.cpp
index 02431e02e48d..9f9c71a50ce1 100644
--- a/test/SemaCXX/libstdcxx_pair_swap_hack.cpp
+++ b/test/SemaCXX/libstdcxx_pair_swap_hack.cpp
@@ -8,10 +8,14 @@
// affected are array, pair, priority_queue, stack, and queue.
// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=array
+// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=array -DPR28423
// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=pair
// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=priority_queue
// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=stack
// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=queue
+//
+// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=array -DNAMESPACE=__debug
+// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=array -DNAMESPACE=__profile
// MSVC's standard library uses a very similar pattern that relies on delayed
// parsing of exception specifications.
@@ -21,12 +25,23 @@
#ifdef BE_THE_HEADER
#pragma GCC system_header
+#ifdef PR28423
+using namespace std;
+#endif
+
namespace std {
template<typename T> void swap(T &, T &);
template<typename T> void do_swap(T &a, T &b) noexcept(noexcept(swap(a, b))) {
swap(a, b);
}
+#ifdef NAMESPACE
+ namespace NAMESPACE {
+#define STD_CLASS std::NAMESPACE::CLASS
+#else
+#define STD_CLASS std::CLASS
+#endif
+
template<typename A, typename B> struct CLASS {
#ifdef MSVC
void swap(CLASS &other) noexcept(noexcept(do_swap(member, other.member)));
@@ -42,6 +57,10 @@ namespace std {
// void swap(vector &other) noexcept(noexcept(do_swap(member, other.member)));
// A member;
// };
+
+#ifdef NAMESPACE
+ }
+#endif
}
#else
@@ -50,8 +69,8 @@ namespace std {
#include __FILE__
struct X {};
-using PX = std::CLASS<X, X>;
-using PI = std::CLASS<int, int>;
+using PX = STD_CLASS<X, X>;
+using PI = STD_CLASS<int, int>;
void swap(X &, X &) noexcept;
PX px;
PI pi;
@@ -64,6 +83,7 @@ namespace sad {
template<typename A, typename B> struct CLASS {
void swap(CLASS &other) noexcept(noexcept(swap(*this, other))); // expected-error {{too many arguments}} expected-note {{declared here}}
+ // expected-error@-1{{uses itself}} expected-note@-1{{in instantiation of}}
};
CLASS<int, int> pi;
diff --git a/test/SemaCXX/member-init.cpp b/test/SemaCXX/member-init.cpp
index 65c8873117ab..105c2e49822f 100644
--- a/test/SemaCXX/member-init.cpp
+++ b/test/SemaCXX/member-init.cpp
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -fcxx-exceptions -verify -std=c++11 -Wall %s
struct Bitfield {
- int n : 3 = 7; // expected-error {{bitfield member cannot have an in-class initializer}}
+ int n : 3 = 7; // expected-error {{bit-field member cannot have an in-class initializer}}
};
int a;
@@ -13,8 +13,8 @@ public:
bool b();
int k;
-struct Recurse {
- int &n = // expected-error {{cannot use defaulted default constructor of 'Recurse' within the class outside of member functions because 'n' has an initializer}}
+struct Recurse { // expected-error {{initializer for 'n' needed}}
+ int &n = // expected-note {{declared here}}
b() ?
Recurse().n : // expected-note {{implicit default constructor for 'Recurse' first required here}}
k;
@@ -87,7 +87,7 @@ namespace PR14838 {
struct thing {};
struct another {
another() : r(thing()) {}
- // expected-error@-1 {{temporary of type 'const PR14838::function' has private destructor}}
+ // 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;
@@ -128,8 +128,8 @@ A::A() {}
namespace template_default_ctor {
struct A {
template <typename T>
- struct B {
- int m1 = 0; // expected-error {{cannot use defaulted default constructor of 'B' within 'A' outside of member functions because 'm1' has an initializer}}
+ struct B { // expected-error {{initializer for 'm1' needed}}
+ int m1 = 0; // expected-note {{declared here}}
};
// expected-note@+1 {{implicit default constructor for 'template_default_ctor::A::B<int>' first required here}}
enum { NOE = noexcept(B<int>()) };
@@ -138,8 +138,8 @@ struct A {
namespace default_ctor {
struct A {
- struct B {
- int m1 = 0; // expected-error {{cannot use defaulted default constructor of 'B' within 'A' outside of member functions because 'm1' has an initializer}}
+ struct B { // expected-error {{initializer for 'm1' needed}}
+ int m1 = 0; // expected-note {{declared here}}
};
// expected-note@+1 {{implicit default constructor for 'default_ctor::A::B' first required here}}
enum { NOE = noexcept(B()) };
@@ -150,12 +150,12 @@ namespace member_template {
struct A {
template <typename T>
struct B {
- struct C {
- int m1 = 0; // expected-error {{cannot use defaulted default constructor of 'C' within 'A' outside of member functions because 'm1' has an initializer}}
+ struct C { // expected-error {{initializer for 'm1' needed}}
+ int m1 = 0; // expected-note {{declared here}}
};
template <typename U>
- struct D {
- int m1 = 0; // expected-error {{cannot use defaulted default constructor of 'D' within 'A' outside of member functions because 'm1' has an initializer}}
+ struct D { // expected-error {{initializer for 'm1' needed}}
+ int m1 = 0; // expected-note {{declared here}}
};
};
enum {
diff --git a/test/SemaCXX/member-pointer-ms.cpp b/test/SemaCXX/member-pointer-ms.cpp
index 83aeb019ca81..c8059acd6737 100644
--- a/test/SemaCXX/member-pointer-ms.cpp
+++ b/test/SemaCXX/member-pointer-ms.cpp
@@ -291,3 +291,11 @@ static_assert(sizeof(int SingleInheritanceAsVirtualBeforePragma::*) == 12, "");
#pragma pointers_to_members(single) // expected-error{{unexpected 'single'}}
#endif
+
+namespace merging {
+struct __single_inheritance S;
+struct __single_inheritance S;
+
+struct __single_inheritance M; // expected-note{{previous inheritance model specified here}}
+struct __multiple_inheritance M; // expected-error{{inheritance model does not match previous declaration}}
+}
diff --git a/test/SemaCXX/microsoft-new-delete.cpp b/test/SemaCXX/microsoft-new-delete.cpp
index b929e618a036..beba4d9dd8a4 100644
--- a/test/SemaCXX/microsoft-new-delete.cpp
+++ b/test/SemaCXX/microsoft-new-delete.cpp
@@ -16,7 +16,7 @@ void *operator new(size_t, const noncopyable&);
void *q = new (nc) int[4]; // expected-error {{calling a private constructor}}
struct bitfield { int n : 3; } bf; // expected-note {{here}}
-void *operator new[](size_t, int &);
+void *operator new[](size_t, int &); // expected-note {{passing argument to parameter here}}
void *operator new(size_t, const int &);
void *r = new (bf.n) int[4]; // expected-error {{non-const reference cannot bind to bit-field}}
diff --git a/test/SemaCXX/modules-ts.cppm b/test/SemaCXX/modules-ts.cppm
new file mode 100644
index 000000000000..71c09d3bfe6c
--- /dev/null
+++ b/test/SemaCXX/modules-ts.cppm
@@ -0,0 +1,83 @@
+// RUN: %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface %s -o %t.pcm -verify -DTEST=0
+// RUN: %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface %s -o %t.pcm -verify -Dmodule=int -DTEST=1
+// RUN: not %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface %s -fmodule-file=%t.pcm -o %t.pcm -DTEST=2 2>&1 | FileCheck %s --check-prefix=CHECK-2
+// RUN: %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface %s -fmodule-file=%t.pcm -o %t.pcm -verify -Dfoo=bar -DTEST=3
+
+#if TEST == 0
+// expected-no-diagnostics
+#endif
+
+module foo;
+#if TEST == 1
+// expected-error@-2 {{expected module declaration at start of module interface}}
+#elif TEST == 2
+// CHECK-2: error: redefinition of module 'foo'
+#endif
+
+static int m; // ok, internal linkage, so no redefinition error
+int n;
+#if TEST == 3
+// expected-error@-2 {{redefinition of '}}
+// expected-note@-3 {{previous}}
+#endif
+
+#if TEST == 0
+export {
+ int a;
+ int b;
+ constexpr int *p = &n;
+}
+export int c;
+
+namespace N {
+ export void f() {}
+}
+
+export struct T {} t;
+#elif TEST == 3
+int use_a = a; // expected-error {{declaration of 'a' must be imported from module 'foo' before it is required}}
+// expected-note@-13 {{previous}}
+
+#undef foo
+import foo;
+
+export {} // expected-error {{export declaration cannot be empty}}
+export { ; }
+export { static_assert(true); }
+
+// FIXME: These diagnostics are not very good.
+export import foo; // expected-error {{expected unqualified-id}}
+export { import foo; } // expected-error {{expected unqualified-id}}
+
+int use_b = b;
+int use_n = n; // FIXME: this should not be visible, because it is not exported
+
+extern int n;
+static_assert(&n == p); // FIXME: these are not the same entity
+#endif
+
+
+#if TEST == 1
+struct S {
+ export int n; // expected-error {{expected member name or ';'}}
+ export static int n; // expected-error {{expected member name or ';'}}
+};
+#endif
+
+// FIXME: Exports of declarations without external linkage are disallowed.
+// Exports of declarations with non-external-linkage types are disallowed.
+
+// Cannot export within another export. This isn't precisely covered by the
+// language rules right now, but (per personal correspondence between zygoloid
+// and gdr) is the intent.
+#if TEST == 1
+export {
+ extern "C++" {
+ namespace NestedExport {
+ export { // expected-error {{appears within another export}}
+ int q;
+ }
+ }
+ }
+}
+#endif
diff --git a/test/SemaCXX/ms-uuid.cpp b/test/SemaCXX/ms-uuid.cpp
new file mode 100644
index 000000000000..461e3c12ff8a
--- /dev/null
+++ b/test/SemaCXX/ms-uuid.cpp
@@ -0,0 +1,95 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -fms-extensions %s
+
+typedef struct _GUID {
+ unsigned long Data1;
+ unsigned short Data2;
+ unsigned short Data3;
+ unsigned char Data4[8];
+} GUID;
+
+namespace {
+// cl.exe's behavior with merging uuid attributes is a bit erratic:
+// * In []-style attributes, a single [] list must not list a duplicate uuid
+// (even if it's the same uuid), and only a single declaration of a class
+// must have a uuid else the compiler errors out (even if two declarations of
+// a class have the same uuid).
+// * For __declspec(uuid(...)), it's ok if several declarations of a class have
+// an uuid, as long as it's the same uuid each time. If uuids on declarations
+// don't match, the compiler errors out.
+// * If there are several __declspec(uuid(...))s on one declaration, the
+// compiler only warns about this and uses the last uuid. It even warns if
+// the uuids are the same.
+
+// 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
+// on several decls), it is an error if they don't match.
+// * Having several uuids that match is ok.
+
+// Both cl and clang-cl accept this:
+class __declspec(uuid("000000A0-0000-0000-C000-000000000049")) C1;
+class __declspec(uuid("000000a0-0000-0000-c000-000000000049")) C1;
+class __declspec(uuid("{000000a0-0000-0000-C000-000000000049}")) C1;
+class __declspec(uuid("000000A0-0000-0000-C000-000000000049")) C1 {};
+
+// Both cl and clang-cl error out on this:
+// expected-note@+1 2{{previous uuid specified here}}
+class __declspec(uuid("000000A0-0000-0000-C000-000000000049")) C2;
+// expected-error@+1 {{uuid does not match previous declaration}}
+class __declspec(uuid("110000A0-0000-0000-C000-000000000049")) C2;
+// expected-error@+1 {{uuid does not match previous declaration}}
+class __declspec(uuid("220000A0-0000-0000-C000-000000000049")) C2 {};
+
+// expected-note@+1 {{previous uuid specified here}}
+class __declspec(uuid("000000A0-0000-0000-C000-000000000049")) C2_2;
+class C2_2;
+// expected-error@+1 {{uuid does not match previous declaration}}
+class __declspec(uuid("110000A0-0000-0000-C000-000000000049")) C2_2;
+
+// clang-cl accepts this, but cl errors out:
+[uuid("000000A0-0000-0000-C000-000000000049")] class C3;
+[uuid("000000A0-0000-0000-C000-000000000049")] class C3;
+[uuid("000000A0-0000-0000-C000-000000000049")] class C3 {};
+
+// Both cl and clang-cl error out on this (but for different reasons):
+// expected-note@+1 2{{previous uuid specified here}}
+[uuid("000000A0-0000-0000-C000-000000000049")] class C4;
+// expected-error@+1 {{uuid does not match previous declaration}}
+[uuid("110000A0-0000-0000-C000-000000000049")] class C4;
+// expected-error@+1 {{uuid does not match previous declaration}}
+[uuid("220000A0-0000-0000-C000-000000000049")] class C4 {};
+
+// Both cl and clang-cl error out on this:
+// expected-note@+1 {{previous uuid specified here}}
+class __declspec(uuid("000000A0-0000-0000-C000-000000000049"))
+// expected-error@+1 {{uuid does not match previous declaration}}
+ __declspec(uuid("110000A0-0000-0000-C000-000000000049")) C5;
+
+// expected-note@+1 {{previous uuid specified here}}
+[uuid("000000A0-0000-0000-C000-000000000049"),
+// expected-error@+1 {{uuid does not match previous declaration}}
+ uuid("110000A0-0000-0000-C000-000000000049")] class C6;
+
+// cl doesn't diagnose having one uuid each as []-style attributes and as
+// __declspec, even if the uuids differ. clang-cl errors if they differ.
+[uuid("000000A0-0000-0000-C000-000000000049")]
+class __declspec(uuid("000000A0-0000-0000-C000-000000000049")) C7;
+
+// expected-note@+1 {{previous uuid specified here}}
+[uuid("000000A0-0000-0000-C000-000000000049")]
+// expected-error@+1 {{uuid does not match previous declaration}}
+class __declspec(uuid("110000A0-0000-0000-C000-000000000049")) C8;
+
+
+// cl warns on this, but clang-cl is fine with it (which is consistent with
+// e.g. specifying __multiple_inheritance several times, which cl accepts
+// without warning too).
+class __declspec(uuid("000000A0-0000-0000-C000-000000000049"))
+ __declspec(uuid("000000A0-0000-0000-C000-000000000049")) C9;
+
+// cl errors out on this, but clang-cl is fine with it (to be consistent with
+// the previous case).
+[uuid("000000A0-0000-0000-C000-000000000049"),
+ uuid("000000A0-0000-0000-C000-000000000049")] class C10;
+}
diff --git a/test/SemaCXX/new-delete-cxx0x.cpp b/test/SemaCXX/new-delete-cxx0x.cpp
index 899cb4cda87a..c55152510e1b 100644
--- a/test/SemaCXX/new-delete-cxx0x.cpp
+++ b/test/SemaCXX/new-delete-cxx0x.cpp
@@ -1,13 +1,19 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 -triple=i686-pc-linux-gnu
void ugly_news(int *ip) {
- // These are ill-formed according to one reading of C++98, and at the least
- // have undefined behavior.
- // FIXME: They're ill-formed in C++11.
- (void)new int[-1]; // expected-warning {{array size is negative}}
- (void)new int[2000000000]; // expected-warning {{array is too large}}
+ (void)new int[-1]; // expected-error {{array size is negative}}
+ (void)new int[2000000000]; // expected-error {{array is too large}}
}
+void pr22845a() {
+ constexpr int i = -1;
+ int *p = new int[i]; // expected-error {{array size is negative}}
+}
+
+void pr22845b() {
+ constexpr int i = 1;
+ int *p = new int[i]{1, 2}; // expected-error {{excess elements in array initializer}}
+}
struct S {
S(int);
@@ -15,13 +21,14 @@ struct S {
~S();
};
-struct T { // expected-note 2 {{not viable}}
- T(int); // expected-note {{not viable}}
+struct T { // expected-note 1+{{not viable}}
+ T(int); // expected-note 1+{{not viable}}
};
-void fn() {
+void fn(int n) {
(void) new int[2] {1, 2};
(void) new S[2] {1, 2};
+ (void) new S[3] {1, 2};
// C++11 [expr.new]p19:
// If the new-expression creates an object or an array of objects of class
// type, access and ambiguity control are done for the allocation function,
@@ -29,5 +36,28 @@ void fn() {
//
// Note that this happens even if the array bound is constant and the
// initializer initializes every array element.
- (void) new T[2] {1, 2}; // expected-error {{no matching constructor}} expected-note {{in implicit initialization of array element 2}}
+ //
+ // It's not clear that this is the intended interpretation, however -- we
+ // obviously don't want to check for a default constructor for 'new S(0)'.
+ // Instead, we only check for a default constructor in the case of an array
+ // new with a non-constant bound or insufficient initializers.
+ (void) new T[2] {1, 2}; // ok
+ (void) new T[3] {1, 2}; // expected-error {{no matching constructor}} expected-note {{in implicit initialization of array element 2}}
+ (void) new T[n] {1, 2}; // expected-error {{no matching constructor}} expected-note {{in implicit initialization of trailing array elements in runtime-sized array new}}
+}
+
+struct U {
+ T t; // expected-note 3{{in implicit initialization of field 't'}}
+ S s;
+};
+void g(int n) {
+ // Aggregate initialization, brace-elision, and array new combine to create
+ // this monstrosity.
+ (void) new U[2] {1, 2}; // expected-error {{no matching constructor}} expected-note {{in implicit initialization of array element 1}}
+ (void) new U[2] {1, 2, 3}; // ok
+ (void) new U[2] {1, 2, 3, 4}; // ok
+ (void) new U[2] {1, 2, 3, 4, 5}; // expected-error {{excess elements in array initializer}}
+
+ (void) new U[n] {1, 2}; // expected-error {{no matching constructor}} expected-note {{in implicit initialization of trailing array elements}}
+ (void) new U[n] {1, 2, 3}; // expected-error {{no matching constructor}} expected-note {{in implicit initialization of trailing array elements}}
}
diff --git a/test/SemaCXX/null_in_arithmetic_ops.cpp b/test/SemaCXX/null_in_arithmetic_ops.cpp
index 3b42ab44feb9..ee695ff24209 100644
--- a/test/SemaCXX/null_in_arithmetic_ops.cpp
+++ b/test/SemaCXX/null_in_arithmetic_ops.cpp
@@ -71,8 +71,8 @@ void f() {
b = a == NULL || a != NULL; // expected-warning 2{{comparison between NULL and non-pointer ('int' and NULL)}}
b = NULL == a || NULL != a; // expected-warning 2{{comparison between NULL and non-pointer (NULL and 'int')}}
- b = &a < NULL || NULL < &a || &a > NULL || NULL > &a;
- b = &a <= NULL || NULL <= &a || &a >= NULL || NULL >= &a;
+ b = &a < NULL || NULL < &a || &a > NULL || NULL > &a; // expected-error 4{{ordered comparison between pointer and zero}}
+ b = &a <= NULL || NULL <= &a || &a >= NULL || NULL >= &a; // expected-error 4{{ordered comparison between pointer and zero}}
b = &a == NULL || NULL == &a || &a != NULL || NULL != &a;
b = 0 == a;
diff --git a/test/SemaCXX/nullability.cpp b/test/SemaCXX/nullability.cpp
index c73c01a0a862..160741b1409c 100644
--- a/test/SemaCXX/nullability.cpp
+++ b/test/SemaCXX/nullability.cpp
@@ -97,3 +97,36 @@ void AssignAndInitNonNullFromFn() {
TakeNonnull(ReturnNullable()); //expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull}}
}
+
+void ConditionalExpr(bool c) {
+ struct Base {};
+ struct Derived : Base {};
+
+ Base * _Nonnull p;
+ Base * _Nonnull nonnullB;
+ Base * _Nullable nullableB;
+ Derived * _Nonnull nonnullD;
+ Derived * _Nullable nullableD;
+
+ p = c ? nonnullB : nonnullD;
+ p = c ? nonnullB : nullableD; // expected-warning{{implicit conversion from nullable pointer 'Base * _Nullable' to non-nullable pointer type 'Base * _Nonnull}}
+ p = c ? nullableB : nonnullD; // expected-warning{{implicit conversion from nullable pointer 'Base * _Nullable' to non-nullable pointer type 'Base * _Nonnull}}
+ p = c ? nullableB : nullableD; // expected-warning{{implicit conversion from nullable pointer 'Base * _Nullable' to non-nullable pointer type 'Base * _Nonnull}}
+ p = c ? nonnullD : nonnullB;
+ p = c ? nonnullD : nullableB; // expected-warning{{implicit conversion from nullable pointer 'Base * _Nullable' to non-nullable pointer type 'Base * _Nonnull}}
+ p = c ? nullableD : nonnullB; // expected-warning{{implicit conversion from nullable pointer 'Base * _Nullable' to non-nullable pointer type 'Base * _Nonnull}}
+ p = c ? nullableD : nullableB; // expected-warning{{implicit conversion from nullable pointer 'Base * _Nullable' to non-nullable pointer type 'Base * _Nonnull}}
+}
+
+void arraysInLambdas() {
+ typedef int INTS[4];
+ auto simple = [](int [_Nonnull 2]) {};
+ simple(nullptr); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ auto nested = [](void *_Nullable [_Nonnull 2]) {};
+ nested(nullptr); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ auto nestedBad = [](int [2][_Nonnull 2]) {}; // expected-error {{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'int [2]'}}
+
+ auto withTypedef = [](INTS _Nonnull) {};
+ withTypedef(nullptr); // expected-warning {{null passed to a callee that requires a non-null argument}}
+ auto withTypedefBad = [](INTS _Nonnull[2]) {}; // expected-error {{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'INTS' (aka 'int [4]')}}
+}
diff --git a/test/SemaCXX/nullptr.cpp b/test/SemaCXX/nullptr.cpp
index 7d765b482c73..9a092910b6f9 100644
--- a/test/SemaCXX/nullptr.cpp
+++ b/test/SemaCXX/nullptr.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++11 -ffreestanding -Wno-null-conversion %s
+// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++11 -ffreestanding -Wno-null-conversion -Wno-tautological-compare %s
#include <stdint.h>
typedef decltype(nullptr) nullptr_t;
@@ -32,17 +32,17 @@ nullptr_t f(nullptr_t null)
// Operators
(void)(null == nullptr);
- (void)(null <= nullptr);
+ (void)(null <= nullptr); // expected-error {{invalid operands to binary expression}}
(void)(null == 0);
(void)(null == (void*)0);
(void)((void*)0 == nullptr);
- (void)(null <= 0);
- (void)(null <= (void*)0);
- (void)((void*)0 <= nullptr);
+ (void)(null <= 0); // expected-error {{invalid operands to binary expression}}
+ (void)(null <= (void*)0); // expected-error {{invalid operands to binary expression}}
+ (void)((void*)0 <= nullptr); // expected-error {{invalid operands to binary expression}}
(void)(0 == nullptr);
(void)(nullptr == 0);
- (void)(nullptr <= 0);
- (void)(0 <= nullptr);
+ (void)(nullptr <= 0); // expected-error {{invalid operands to binary expression}}
+ (void)(0 <= nullptr); // expected-error {{invalid operands to binary expression}}
(void)(1 > nullptr); // expected-error {{invalid operands to binary expression}}
(void)(1 != nullptr); // expected-error {{invalid operands to binary expression}}
(void)(1 + nullptr); // expected-error {{invalid operands to binary expression}}
@@ -118,24 +118,24 @@ static_assert(__is_scalar(nullptr_t), "");
static_assert(__is_pod(nullptr_t), "");
static_assert(sizeof(nullptr_t) == sizeof(void*), "");
-static_assert(!(nullptr < nullptr), "");
-static_assert(!(nullptr > nullptr), "");
-static_assert( nullptr <= nullptr, "");
-static_assert( nullptr >= nullptr, "");
+static_assert(!(nullptr < nullptr), ""); // expected-error {{invalid operands to binary expression}}
+static_assert(!(nullptr > nullptr), ""); // expected-error {{invalid operands to binary expression}}
+static_assert( nullptr <= nullptr, ""); // expected-error {{invalid operands to binary expression}}
+static_assert( nullptr >= nullptr, ""); // expected-error {{invalid operands to binary expression}}
static_assert( nullptr == nullptr, "");
static_assert(!(nullptr != nullptr), "");
-static_assert(!(0 < nullptr), "");
-static_assert(!(0 > nullptr), "");
-static_assert( 0 <= nullptr, "");
-static_assert( 0 >= nullptr, "");
+static_assert(!(0 < nullptr), ""); // expected-error {{invalid operands to binary expression}}
+static_assert(!(0 > nullptr), ""); // expected-error {{invalid operands to binary expression}}
+static_assert( 0 <= nullptr, ""); // expected-error {{invalid operands to binary expression}}
+static_assert( 0 >= nullptr, ""); // expected-error {{invalid operands to binary expression}}
static_assert( 0 == nullptr, "");
static_assert(!(0 != nullptr), "");
-static_assert(!(nullptr < 0), "");
-static_assert(!(nullptr > 0), "");
-static_assert( nullptr <= 0, "");
-static_assert( nullptr >= 0, "");
+static_assert(!(nullptr < 0), ""); // expected-error {{invalid operands to binary expression}}
+static_assert(!(nullptr > 0), ""); // expected-error {{invalid operands to binary expression}}
+static_assert( nullptr <= 0, ""); // expected-error {{invalid operands to binary expression}}
+static_assert( nullptr >= 0, ""); // expected-error {{invalid operands to binary expression}}
static_assert( nullptr == 0, "");
static_assert(!(nullptr != 0), "");
@@ -154,10 +154,10 @@ namespace overloading {
void test_conversion(ConvertsToNullPtr ctn) {
(void)(ctn == ctn);
(void)(ctn != ctn);
- (void)(ctn <= ctn);
- (void)(ctn >= ctn);
- (void)(ctn < ctn);
- (void)(ctn > ctn);
+ (void)(ctn <= ctn); // expected-error {{invalid operands to binary expression}}
+ (void)(ctn >= ctn); // expected-error {{invalid operands to binary expression}}
+ (void)(ctn < ctn); // expected-error {{invalid operands to binary expression}}
+ (void)(ctn > ctn); // expected-error {{invalid operands to binary expression}}
}
}
diff --git a/test/SemaCXX/nullptr_in_arithmetic_ops.cpp b/test/SemaCXX/nullptr_in_arithmetic_ops.cpp
index 60b4670b3a5e..6273d9c42e0b 100644
--- a/test/SemaCXX/nullptr_in_arithmetic_ops.cpp
+++ b/test/SemaCXX/nullptr_in_arithmetic_ops.cpp
@@ -45,12 +45,12 @@ void foo() {
b = a == nullptr || nullptr == a; // expected-error 2{{invalid operands to binary expression}}
b = a != nullptr || nullptr != a; // expected-error 2{{invalid operands to binary expression}}
- b = &a < nullptr || nullptr < &a || &a > nullptr || nullptr > &a;
- b = &a <= nullptr || nullptr <= &a || &a >= nullptr || nullptr >= &a;
+ b = &a < nullptr || nullptr < &a || &a > nullptr || nullptr > &a; // expected-error 4{{invalid operands}}
+ b = &a <= nullptr || nullptr <= &a || &a >= nullptr || nullptr >= &a; // expected-error 4{{invalid operands}}
b = &a == nullptr || nullptr == &a || &a != nullptr || nullptr != &a;
- b = nullptr < nullptr || nullptr > nullptr;
- b = nullptr <= nullptr || nullptr >= nullptr;
+ b = nullptr < nullptr || nullptr > nullptr; // expected-error 2{{invalid operands to binary expression}}
+ b = nullptr <= nullptr || nullptr >= nullptr; // expected-error 2{{invalid operands to binary expression}}
b = nullptr == nullptr || nullptr != nullptr;
b = ((nullptr)) != a; // expected-error{{invalid operands to binary expression}}
diff --git a/test/SemaCXX/overload-call.cpp b/test/SemaCXX/overload-call.cpp
index 7eaf98b601c1..3a01bf24b31a 100644
--- a/test/SemaCXX/overload-call.cpp
+++ b/test/SemaCXX/overload-call.cpp
@@ -647,3 +647,14 @@ namespace PR20218 {
g(y); // expected-error {{ambiguous}}
}
}
+
+namespace StringLiteralToCharAmbiguity {
+ void f(char *, int);
+ void f(const char *, unsigned);
+ void g() { f("foo", 0); }
+#if __cplusplus <= 199711L
+ // expected-error@-2 {{call to 'f' is ambiguous}}
+ // expected-note@-5 {{candidate function}}
+ // expected-note@-5 {{candidate function}}
+#endif
+}
diff --git a/test/SemaCXX/pr28050.cpp b/test/SemaCXX/pr28050.cpp
new file mode 100644
index 000000000000..57e90eb75169
--- /dev/null
+++ b/test/SemaCXX/pr28050.cpp
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc -std=c++11 %s -fsyntax-only
+//
+// expected-no-diagnostics
+
+class A {
+public:
+ A(char *s) {}
+ A(A &&) = delete;
+};
+
+int main() { A a("OK"); }
diff --git a/test/SemaCXX/predefined-expr.cpp b/test/SemaCXX/predefined-expr.cpp
index f4a155da6678..8cba0d41a299 100644
--- a/test/SemaCXX/predefined-expr.cpp
+++ b/test/SemaCXX/predefined-expr.cpp
@@ -33,11 +33,10 @@ int baz() {
();
^{
- static_assert(sizeof(__func__) == 27, "___Z3bazIiEiv_block_invoke");
- static_assert(sizeof(__FUNCTION__) == 27, "___Z3bazIiEiv_block_invoke");
- static_assert(sizeof(__PRETTY_FUNCTION__) == 27, "___Z3bazIiEiv_block_invoke");
- }
- ();
+ static_assert(sizeof(__func__) == 17, "baz_block_invoke");
+ static_assert(sizeof(__FUNCTION__) == 17, "baz_block_invoke");
+ static_assert(sizeof(__PRETTY_FUNCTION__) == 33, "int baz() [T = int]_block_invoke");
+ }();
#pragma clang __debug captured
{
@@ -64,11 +63,10 @@ int main() {
();
^{
- static_assert(sizeof(__func__) == 20, "__main_block_invoke");
- static_assert(sizeof(__FUNCTION__) == 20, "__main_block_invoke");
- static_assert(sizeof(__PRETTY_FUNCTION__) == 20, "__main_block_invoke");
- }
- ();
+ static_assert(sizeof(__func__) == 18, "main_block_invoke");
+ static_assert(sizeof(__FUNCTION__) == 18, "main_block_invoke");
+ static_assert(sizeof(__PRETTY_FUNCTION__) == 24, "int main()_block_invoke");
+ }();
#pragma clang __debug captured
{
diff --git a/test/SemaCXX/reinterpret-cast.cpp b/test/SemaCXX/reinterpret-cast.cpp
index 7c88dc0302ad..6cc46d8b0d9f 100644
--- a/test/SemaCXX/reinterpret-cast.cpp
+++ b/test/SemaCXX/reinterpret-cast.cpp
@@ -125,7 +125,7 @@ void const_arrays() {
namespace PR9564 {
struct a { int a : 10; }; a x;
- int *y = &reinterpret_cast<int&>(x.a); // expected-error {{not allowed}}
+ int *y = &reinterpret_cast<int&>(x.a); // expected-error {{reinterpret_cast from bit-field lvalue to reference type 'int &'}}
__attribute((ext_vector_type(4))) typedef float v4;
float& w(v4 &a) { return reinterpret_cast<float&>(a[1]); } // expected-error {{not allowed}}
diff --git a/test/SemaCXX/rval-references.cpp b/test/SemaCXX/rval-references.cpp
index 4c2050494b69..94b09ce2cb2a 100644
--- a/test/SemaCXX/rval-references.cpp
+++ b/test/SemaCXX/rval-references.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++11 %s
typedef int&& irr;
typedef irr& ilr_c1; // Collapses to int&
@@ -30,11 +30,15 @@ void f() {
int &&virr2 = 0;
int &&virr3 = virr2; // expected-error {{rvalue reference to type 'int' cannot bind to lvalue of type 'int'}}
int i1 = 0;
+ const double d1 = 0;
+ const int ci1 = 1;
int &&virr4 = i1; // expected-error {{rvalue reference to type 'int' cannot bind to lvalue of type 'int'}}
int &&virr5 = ret_irr();
int &&virr6 = static_cast<int&&>(i1);
- (void)static_cast<not_int&&>(i1); // expected-error {{types are not compatible}}
-
+ (void)static_cast<not_int &&>(i1); // expected-error {{reference to type 'not_int' could not bind to an lvalue of type 'int'}}
+ (void)static_cast<int &&>(static_cast<int const&&>(i1)); // expected-error {{cannot cast from rvalue of type 'const int' to rvalue reference type 'int &&'}}
+ (void)static_cast<int &&>(ci1); // expected-error {{types are not compatible}}
+ (void)static_cast<int &&>(d1);
int i2 = over(i1);
not_int ni1 = over(0);
int i3 = over(virr2);
diff --git a/test/SemaCXX/switch.cpp b/test/SemaCXX/switch.cpp
index 392dcd869802..0c60ce02097b 100644
--- a/test/SemaCXX/switch.cpp
+++ b/test/SemaCXX/switch.cpp
@@ -100,3 +100,33 @@ namespace Conversion {
}
template void f(S); // expected-note {{instantiation of}}
}
+
+// rdar://29230764
+namespace OpaqueEnumWarnings {
+
+enum Opaque : int;
+enum class OpaqueClass : int;
+
+enum class Defined : int;
+enum class Defined : int { a };
+
+void test(Opaque o, OpaqueClass oc, Defined d) {
+ // Don't warn that case value is not present in opaque enums.
+ switch (o) {
+ case (Opaque)1:
+ break;
+ }
+ switch (oc) {
+ case (OpaqueClass)1:
+ break;
+ }
+
+ switch (d) {
+ case Defined::a:
+ break;
+ case (Defined)2: // expected-warning {{case value not in enumerated type 'OpaqueEnumWarnings::Defined'}}
+ break;
+ }
+}
+
+}
diff --git a/test/SemaCXX/template-ambiguous-overload.cpp b/test/SemaCXX/template-ambiguous-overload.cpp
new file mode 100644
index 000000000000..bbb7e397b844
--- /dev/null
+++ b/test/SemaCXX/template-ambiguous-overload.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+namespace n {
+template <int>
+void f(); // expected-note{{explicit instantiation candidate function 'n::f<0>' template here [with $0 = 0]}}
+
+extern template void f<0>();
+}
+
+using namespace n;
+
+template <int>
+void f() {} // expected-note{{explicit instantiation candidate function 'f<0>' template here [with $0 = 0]}}
+
+template void f<0>(); // expected-error{{partial ordering for explicit instantiation of 'f' is ambiguous}}
+
diff --git a/test/SemaCXX/type-definition-in-specifier.cpp b/test/SemaCXX/type-definition-in-specifier.cpp
index 43443a00e44b..74ba058b4f12 100644
--- a/test/SemaCXX/type-definition-in-specifier.cpp
+++ b/test/SemaCXX/type-definition-in-specifier.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fexceptions -fcxx-exceptions -verify %s
struct S0;
struct S1;
@@ -30,7 +30,7 @@ struct pr19018 {
void pr19018_1 (enum e19018_1 {qq} x); // expected-error{{cannot be defined in a parameter type}}
void pr19018_1a (enum e19018_1 {qq} x); // expected-error{{cannot be defined in a parameter type}}
-e19018_1 x2; // expected-error{{unknown type name 'e19018_1'}}
+e19018_1 x2;
void pr19018_2 (enum {qq} x); // expected-error{{cannot be defined in a parameter type}}
void pr19018_3 (struct s19018_2 {int qq;} x); // expected-error{{cannot be defined in a parameter type}}
@@ -53,14 +53,19 @@ struct pr19018a {
struct s19018b {
void func1 (enum en_2 {qq} x); // expected-error{{cannot be defined in a parameter type}}
- en_2 x1; // expected-error{{unknown type name 'en_2'}}
+ en_2 x1;
void func2 (enum en_3 {qq} x); // expected-error{{cannot be defined in a parameter type}}
- enum en_3 x2; // expected-error{{ISO C++ forbids forward references to 'enum' types}} \
- // expected-error{{field has incomplete type 'enum en_3'}} \
- // expected-note{{forward declaration of 'en_3'}}
+ enum en_3 x2;
};
struct pr18963 {
- short bar5 (struct foo4 {} bar2); // expected-error{{'foo4' cannot be defined in a parameter type}}
- long foo5 (float foo6 = foo4); // expected-error{{use of undeclared identifier 'foo4'}}
+ short bar5 (struct foo4 {} bar2); // expected-error{{'foo4' cannot be defined in a parameter type}} \
+ // expected-note{{declared here}}
+
+ long foo5 (float foo6 = foo4); // expected-error{{'foo4' does not refer to a value}}
};
+
+// expected-error@+2 {{cannot be defined in a parameter type}}
+// expected-note@+1 {{previous definition is here}}
+void func_with_eh_and_type(struct type_in_eh {} o) throw(int) {}
+struct type_in_eh {}; // expected-error {{redefinition of 'type_in_eh'}}
diff --git a/test/SemaCXX/unknown-anytype.cpp b/test/SemaCXX/unknown-anytype.cpp
index 95ad04093405..78a01ba2d358 100644
--- a/test/SemaCXX/unknown-anytype.cpp
+++ b/test/SemaCXX/unknown-anytype.cpp
@@ -56,3 +56,15 @@ namespace test5 {
(X<int>)test0(); // expected-error{{implicit instantiation of undefined template 'test5::X<int>'}}
}
}
+
+namespace test6 {
+ extern __unknown_anytype func();
+ extern __unknown_anytype var;
+ double *d;
+
+ void test() {
+ d = (double*)&func(); // expected-error{{address-of operator cannot be applied to a call to a function with unknown return type}}
+ d = (double*)&var;
+ }
+
+}
diff --git a/test/SemaCXX/using-decl-templates.cpp b/test/SemaCXX/using-decl-templates.cpp
index d766bb3ac6bf..d5cc3a08eb75 100644
--- a/test/SemaCXX/using-decl-templates.cpp
+++ b/test/SemaCXX/using-decl-templates.cpp
@@ -90,5 +90,14 @@ namespace aliastemplateinst {
template<typename T> struct A { };
template<typename T> using APtr = A<T*>; // expected-note{{previous use is here}}
- template struct APtr<int>; // expected-error{{elaborated type refers to a type alias template}}
+ template struct APtr<int>; // expected-error{{type alias template 'APtr' cannot be referenced with a struct specifier}}
}
+
+namespace DontDiagnoseInvalidTest {
+template <bool Value> struct Base {
+ static_assert(Value, ""); // expected-error {{static_assert failed}}
+};
+struct Derived : Base<false> { // expected-note {{requested here}}
+ using Base<false>::Base; // OK. Don't diagnose that 'Base' isn't a base class of Derived.
+};
+} // namespace DontDiagnoseInvalidTest
diff --git a/test/SemaCXX/vartemplate-lambda.cpp b/test/SemaCXX/vartemplate-lambda.cpp
index 9dab6da3d1e3..5b91e232e3a6 100644
--- a/test/SemaCXX/vartemplate-lambda.cpp
+++ b/test/SemaCXX/vartemplate-lambda.cpp
@@ -1,18 +1,36 @@
// RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify %s
-// expected-no-diagnostics
template <class> auto fn0 = [] {};
template <typename> void foo0() { fn0<char>(); }
template<typename T> auto fn1 = [](auto a) { return a + T(1); };
+template<typename T> auto v1 = [](int a = T(1)) { return a; }();
+
+struct S {
+ template<class T>
+ static constexpr T t = [](int f = T(7)){return f;}(); // expected-error{{constexpr variable 't<int>' must be initialized by a constant expression}} expected-error{{a lambda expression may not appear inside of a constant expression}} expected-note{{cannot be used in a constant expression}}
+};
template <typename X>
int foo2() {
X a = 0x61;
fn1<char>(a);
+ (void)v1<int>;
+ (void)S::t<int>; // expected-note{{in instantiation of static data member 'S::t<int>' requested here}}
return 0;
}
+template<class C>
+int foo3() {
+ C::m1(); // expected-error{{type 'long long' cannot be used prior to '::' because it has no members}}
+ return 1;
+}
+
+template<class C>
+auto v2 = [](int a = foo3<C>()){}; // expected-note{{in instantiation of function template specialization 'foo3<long long>' requested here}}
+
int main() {
+ v2<long long>(); // This line causes foo3<long long> to be instantiated.
+ v2<long long>(2); // This line does not.
foo2<int>();
}
diff --git a/test/SemaCXX/warn-c++1z-extensions.cpp b/test/SemaCXX/warn-c++1z-extensions.cpp
new file mode 100644
index 000000000000..9b5e1c205cf3
--- /dev/null
+++ b/test/SemaCXX/warn-c++1z-extensions.cpp
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify %s
+
+void f() {
+ if (bool b = true; b) {} // expected-warning {{'if' initialization statements are a C++1z extension}}
+ switch (int n = 5; n) { // expected-warning {{'switch' initialization statements are a C++1z extension}}
+ case 5: break;
+ }
+}
diff --git a/test/SemaCXX/warn-everthing.cpp b/test/SemaCXX/warn-everthing.cpp
index ad3dd8a24d88..ff66c78cdf97 100644
--- a/test/SemaCXX/warn-everthing.cpp
+++ b/test/SemaCXX/warn-everthing.cpp
@@ -9,5 +9,5 @@ public:
};
void testPR12271() { // expected-warning {{no previous prototype for function 'testPR12271'}}
- PR12271 a[1][1]; // expected-warning {{unused variable 'a'}}
+ PR12271 a[1][1];
}
diff --git a/test/SemaCXX/warn-logical-not-compare.cpp b/test/SemaCXX/warn-logical-not-compare.cpp
index 280ab22d7235..8b332c3c0e8a 100644
--- a/test/SemaCXX/warn-logical-not-compare.cpp
+++ b/test/SemaCXX/warn-logical-not-compare.cpp
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -fsyntax-only -Wlogical-not-parentheses -verify %s
-// RUN: %clang_cc1 -fsyntax-only -Wlogical-not-parentheses -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
+// RUN: not %clang_cc1 -fsyntax-only -Wlogical-not-parentheses -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
bool getBool();
int getInt();
@@ -189,6 +189,45 @@ bool test2 (E e) {
return ret;
}
+bool test_bitwise_op(int x) {
+ bool ret;
+
+ ret = !x & 1;
+ // expected-warning@-1 {{logical not is only applied to the left hand side of this bitwise operator}}
+ // expected-note@-2 {{add parentheses after the '!' to evaluate the bitwise operator first}}
+ // expected-note@-3 {{add parentheses around left hand side expression to silence this warning}}
+ // CHECK: warn-logical-not-compare.cpp:[[line:[0-9]*]]:9: warning
+ // CHECK: to evaluate the bitwise operator first
+ // CHECK: fix-it:"{{.*}}":{[[line]]:10-[[line]]:10}:"("
+ // CHECK: fix-it:"{{.*}}":{[[line]]:15-[[line]]:15}:")"
+ // CHECK: to silence this warning
+ // CHECK: fix-it:"{{.*}}":{[[line]]:9-[[line]]:9}:"("
+ // CHECK: fix-it:"{{.*}}":{[[line]]:11-[[line]]:11}:")"
+ ret = !(x & 1);
+ ret = (!x) & 1;
+
+ // This warning is really about !x & FOO since that's a common misspelling
+ // of the negated bit test !(x & FOO). Don't warn for | and ^, since
+ // it's at least conceivable that the user wants to use | as an
+ // alternative to || that evaluates both branches. (The warning above is
+ // only emitted if the operand to ! is not a bool, but in C that's common.)
+ // And there's no logical ^.
+ ret = !x | 1;
+ ret = !(x | 1);
+ ret = (!x) | 1;
+
+ ret = !x ^ 1;
+ ret = !(x ^ 1);
+ ret = (!x) ^ 1;
+
+ // These already err, don't also warn.
+ !x &= 1; // expected-error{{expression is not assignable}}
+ !x |= 1; // expected-error{{expression is not assignable}}
+ !x ^= 1; // expected-error{{expression is not assignable}}
+
+ return ret;
+}
+
bool PR16673(int x) {
bool ret;
// Make sure we don't emit a fixit for the left paren, but not the right paren.
diff --git a/test/SemaCXX/warn-max-unsigned-zero.cpp b/test/SemaCXX/warn-max-unsigned-zero.cpp
new file mode 100644
index 000000000000..5564b101d8ec
--- /dev/null
+++ b/test/SemaCXX/warn-max-unsigned-zero.cpp
@@ -0,0 +1,55 @@
+// RUN: %clang_cc1 -fsyntax-only -Wmax-unsigned-zero -verify %s -std=c++11
+// RUN: %clang_cc1 -fsyntax-only -Wmax-unsigned-zero %s -std=c++11 -fdiagnostics-parseable-fixits 2>&1 | FileCheck %s
+
+namespace std {
+template <typename T>
+T max(const T &, const T &);
+}
+
+void test(unsigned u) {
+ auto a = std::max(55u, 0u);
+ // expected-warning@-1{{taking the max of a value and unsigned zero is always equal to the other value}}
+ // expected-note@-2{{remove call to max function and unsigned zero argument}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:20}:""
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:24-[[@LINE-4]]:28}:""
+ auto b = std::max(u, 0u);
+ // expected-warning@-1{{taking the max of a value and unsigned zero is always equal to the other value}}
+ // expected-note@-2{{remove call to max function and unsigned zero argument}}
+ // fix-it:"/usr/local/google/home/rtrieu/clang/open/llvm/tools/clang/test/SemaCXX/warn-max-unsigned-zero.cpp":{13:12-13:20}:""
+ // fix-it:"/usr/local/google/home/rtrieu/clang/open/llvm/tools/clang/test/SemaCXX/warn-max-unsigned-zero.cpp":{13:22-13:26}:""
+ auto c = std::max(0u, 55u);
+ // expected-warning@-1{{taking the max of unsigned zero and a value is always equal to the other value}}
+ // expected-note@-2{{remove call to max function and unsigned zero argument}}
+ // fix-it:"/usr/local/google/home/rtrieu/clang/open/llvm/tools/clang/test/SemaCXX/warn-max-unsigned-zero.cpp":{16:12-16:20}:""
+ // fix-it:"/usr/local/google/home/rtrieu/clang/open/llvm/tools/clang/test/SemaCXX/warn-max-unsigned-zero.cpp":{16:21-16:24}:""
+ auto d = std::max(0u, u);
+ // expected-warning@-1{{taking the max of unsigned zero and a value is always equal to the other value}}
+ // expected-note@-2{{remove call to max function and unsigned zero argument}}
+ // fix-it:"/usr/local/google/home/rtrieu/clang/open/llvm/tools/clang/test/SemaCXX/warn-max-unsigned-zero.cpp":{19:12-19:20}:""
+ // fix-it:"/usr/local/google/home/rtrieu/clang/open/llvm/tools/clang/test/SemaCXX/warn-max-unsigned-zero.cpp":{19:21-19:24}:""
+}
+
+void negative_test(signed s) {
+ auto a = std::max(0, s);
+ auto b = std::max(s, 0);
+ auto c = std::max(22, 0);
+ auto d = std::max(0, 22);
+}
+
+template <unsigned x>
+unsigned template_test() {
+ return std::max(x, 0u);
+ // expected-warning@-1{{taking the max of a value and unsigned zero is always equal to the other value}}
+ // expected-note@-2{{remove call to max function and unsigned zero argument}}
+ // fix-it:"/usr/local/google/home/rtrieu/clang/open/llvm/tools/clang/test/SemaCXX/warn-max-unsigned-zero.cpp":{33:10-33:18}:""
+ // fix-it:"/usr/local/google/home/rtrieu/clang/open/llvm/tools/clang/test/SemaCXX/warn-max-unsigned-zero.cpp":{33:20-33:24}:""
+}
+
+int a = template_test<0>() + template_test<1>() + template_test<2>();
+
+#define comp(x,y) std::max(x, y)
+
+int b = comp(0, 1);
+int c = comp(0u, 1u);
+int d = comp(2u, 0u);
+
diff --git a/test/SemaCXX/warn-memset-bad-sizeof.cpp b/test/SemaCXX/warn-memset-bad-sizeof.cpp
index cca15fc8ef3c..0a78caa924ea 100644
--- a/test/SemaCXX/warn-memset-bad-sizeof.cpp
+++ b/test/SemaCXX/warn-memset-bad-sizeof.cpp
@@ -1,5 +1,6 @@
// RUN: %clang_cc1 -fsyntax-only -verify -Wno-sizeof-array-argument %s
//
+extern "C" void *bzero(void *, unsigned);
extern "C" void *memset(void *, int, unsigned);
extern "C" void *memmove(void *s1, const void *s2, unsigned n);
extern "C" void *memcpy(void *s1, const void *s2, unsigned n);
@@ -47,6 +48,19 @@ void f(Mat m, const Foo& const_foo, char *buffer) {
memset(heap_buffer, 0, sizeof(heap_buffer)); // \
// expected-warning {{'memset' call operates on objects of type 'char' while the size is based on a different type 'char *'}} expected-note{{did you mean to provide an explicit length?}}
+ bzero(&s, sizeof(&s)); // \
+ // expected-warning {{'bzero' call operates on objects of type 'S' while the size is based on a different type 'S *'}} expected-note{{did you mean to remove the addressof in the argument to 'sizeof' (and multiply it by the number of elements)?}}
+ bzero(ps, sizeof(ps)); // \
+ // expected-warning {{'bzero' call operates on objects of type 'S' while the size is based on a different type 'S *'}} expected-note{{did you mean to dereference the argument to 'sizeof' (and multiply it by the number of elements)?}}
+ bzero(ps2, sizeof(ps2)); // \
+ // expected-warning {{'bzero' call operates on objects of type 'S' while the size is based on a different type 'PS' (aka 'S *')}} expected-note{{did you mean to dereference the argument to 'sizeof' (and multiply it by the number of elements)?}}
+ bzero(ps2, sizeof(typeof(ps2))); // \
+ // expected-warning {{argument to 'sizeof' in 'bzero' call is the same pointer type}}
+ bzero(ps2, sizeof(PS)); // \
+ // expected-warning {{argument to 'sizeof' in 'bzero' call is the same pointer type}}
+ bzero(heap_buffer, sizeof(heap_buffer)); // \
+ // expected-warning {{'bzero' call operates on objects of type 'char' while the size is based on a different type 'char *'}} expected-note{{did you mean to provide an explicit length?}}
+
memcpy(&s, 0, sizeof(&s)); // \
// expected-warning {{'memcpy' call operates on objects of type 'S' while the size is based on a different type 'S *'}} expected-note{{did you mean to remove the addressof in the argument to 'sizeof' (and multiply it by the number of elements)?}}
memcpy(0, &s, sizeof(&s)); // \
@@ -73,6 +87,21 @@ void f(Mat m, const Foo& const_foo, char *buffer) {
memset(arr, 0, sizeof(arr));
memset(parr, 0, sizeof(parr));
+ bzero((void*)&s, sizeof(&s));
+ bzero(&s, sizeof(s));
+ bzero(&s, sizeof(S));
+ bzero(&s, sizeof(const S));
+ bzero(&s, sizeof(volatile S));
+ bzero(&s, sizeof(volatile const S));
+ bzero(&foo, sizeof(CFoo));
+ bzero(&foo, sizeof(VFoo));
+ bzero(&foo, sizeof(CVFoo));
+ bzero(ps, sizeof(*ps));
+ bzero(ps2, sizeof(*ps2));
+ bzero(ps2, sizeof(typeof(*ps2)));
+ bzero(arr, sizeof(arr));
+ bzero(parr, sizeof(parr));
+
memcpy(&foo, &const_foo, sizeof(Foo));
memcpy((void*)&s, 0, sizeof(&s));
memcpy(0, (void*)&s, sizeof(&s));
@@ -96,12 +125,17 @@ void f(Mat m, const Foo& const_foo, char *buffer) {
int iarr[14];
memset(&iarr[0], 0, sizeof iarr);
memset(iarr, 0, sizeof iarr);
+ bzero(&iarr[0], sizeof iarr);
+ bzero(iarr, sizeof iarr);
int* iparr[14];
memset(&iparr[0], 0, sizeof iparr);
memset(iparr, 0, sizeof iparr);
+ bzero(&iparr[0], sizeof iparr);
+ bzero(iparr, sizeof iparr);
memset(m, 0, sizeof(Mat));
+ bzero(m, sizeof(Mat));
// Copy to raw buffer shouldn't warn either
memcpy(&foo, &arr, sizeof(Foo));
@@ -114,12 +148,21 @@ void f(Mat m, const Foo& const_foo, char *buffer) {
for (;;) {}
&s;
}), 0, sizeof(s));
+
+ bzero(({
+ if (0) {}
+ while (0) {}
+ for (;;) {}
+ &s;
+ }), sizeof(s));
}
namespace ns {
void memset(void* s, char c, int n);
+void bzero(void* s, int n);
void f(int* i) {
memset(i, 0, sizeof(i));
+ bzero(i, sizeof(i));
}
}
diff --git a/test/SemaCXX/warn-memsize-comparison.cpp b/test/SemaCXX/warn-memsize-comparison.cpp
index 54c410e3dc0b..b5c7a9d6969c 100644
--- a/test/SemaCXX/warn-memsize-comparison.cpp
+++ b/test/SemaCXX/warn-memsize-comparison.cpp
@@ -5,7 +5,7 @@ typedef __SIZE_TYPE__ size_t;
extern "C" void *memset(void *, int, size_t);
extern "C" void *memmove(void *s1, const void *s2, size_t n);
extern "C" void *memcpy(void *s1, const void *s2, size_t n);
-extern "C" void *memcmp(void *s1, const void *s2, size_t n);
+extern "C" int memcmp(void *s1, const void *s2, size_t n);
extern "C" int strncmp(const char *s1, const char *s2, size_t n);
extern "C" int strncasecmp(const char *s1, const char *s2, size_t n);
extern "C" char *strncpy(char *dst, const char *src, size_t n);
@@ -28,11 +28,12 @@ void f() {
expected-note {{explicitly cast the argument}}
if (memmove(b1, b2, sizeof(b1)) == 0) {}
+ // FIXME: This fixit is bogus.
if (memcpy(b1, b2, sizeof(b1) < 0)) {} // \
expected-warning{{size argument in 'memcpy' call is a comparison}} \
expected-note {{did you mean to compare}} \
expected-note {{explicitly cast the argument}}
- if (memcpy(b1, b2, sizeof(b1)) < 0) {}
+ if (memcpy(b1, b2, sizeof(b1)) < 0) {} // expected-error {{ordered comparison between pointer and zero}}
if (memcmp(b1, b2, sizeof(b1) <= 0)) {} // \
expected-warning{{size argument in 'memcmp' call is a comparison}} \
@@ -58,11 +59,12 @@ void f() {
expected-note {{explicitly cast the argument}}
if (strncpy(b1, b2, sizeof(b1)) == 0 || true) {}
+ // FIXME: This fixit is bogus.
if (strncat(b1, b2, sizeof(b1) - 1 >= 0 && true)) {} // \
expected-warning{{size argument in 'strncat' call is a comparison}} \
expected-note {{did you mean to compare}} \
expected-note {{explicitly cast the argument}}
- if (strncat(b1, b2, sizeof(b1) - 1) >= 0 && true) {}
+ if (strncat(b1, b2, sizeof(b1) - 1) >= 0 && true) {} // expected-error {{ordered comparison between pointer and zero}}
if (strndup(b1, sizeof(b1) != 0)) {} // \
expected-warning{{size argument in 'strndup' call is a comparison}} \
diff --git a/test/SemaCXX/warn-missing-variable-declarations.cpp b/test/SemaCXX/warn-missing-variable-declarations.cpp
index ad23e0429bbd..5b882845f3c6 100644
--- a/test/SemaCXX/warn-missing-variable-declarations.cpp
+++ b/test/SemaCXX/warn-missing-variable-declarations.cpp
@@ -47,3 +47,8 @@ class C {
static int x = 0; // no-warn
}
};
+
+// There is also no need to use static in anonymous namespaces.
+namespace {
+ int vgood4;
+}
diff --git a/test/SemaCXX/warn-msvc-enum-bitfield.cpp b/test/SemaCXX/warn-msvc-enum-bitfield.cpp
new file mode 100644
index 000000000000..99e1669018ab
--- /dev/null
+++ b/test/SemaCXX/warn-msvc-enum-bitfield.cpp
@@ -0,0 +1,40 @@
+// RUN: %clang_cc1 -fsyntax-only -Wsigned-enum-bitfield -verify %s --std=c++11
+
+// Enums used in bitfields with no explicitly specified underlying type.
+void test0() {
+ enum E { E1, E2 };
+ enum F { F1, F2 };
+ struct { E e1 : 1; E e2; F f1 : 1; F f2; } s;
+
+ s.e1 = E1; // expected-warning {{enums in the Microsoft ABI are signed integers by default; consider giving the enum E an unsigned underlying type to make this code portable}}
+ s.f1 = F1; // expected-warning {{enums in the Microsoft ABI are signed integers by default; consider giving the enum F an unsigned underlying type to make this code portable}}
+
+ s.e2 = E2;
+ s.f2 = F2;
+}
+
+// Enums used in bitfields with an explicit signed underlying type.
+void test1() {
+ enum E : signed { E1, E2 };
+ enum F : long { F1, F2 };
+ struct { E e1 : 1; E e2; F f1 : 1; F f2; } s;
+
+ s.e1 = E1;
+ s.f1 = F1;
+
+ s.e2 = E2;
+ s.f2 = F2;
+}
+
+// Enums used in bitfields with an explicitly unsigned underlying type.
+void test3() {
+ enum E : unsigned { E1, E2 };
+ enum F : unsigned long { F1, F2 };
+ struct { E e1 : 1; E e2; F f1 : 1; F f2; } s;
+
+ s.e1 = E1;
+ s.f1 = F1;
+
+ s.e2 = E2;
+ s.f2 = F2;
+}
diff --git a/test/SemaCXX/warn-range-loop-analysis.cpp b/test/SemaCXX/warn-range-loop-analysis.cpp
index 91756b970e97..98c4a18776a1 100644
--- a/test/SemaCXX/warn-range-loop-analysis.cpp
+++ b/test/SemaCXX/warn-range-loop-analysis.cpp
@@ -29,7 +29,7 @@ struct Bar {
// test1-6 are set in pairs, the odd numbers are the non-reference returning
// versions of the even numbers.
// test7-9 use an array instead of a range object
-// tests use all four versions of the loop varaible, const &T, const T, T&, and
+// tests use all four versions of the loop variable, const &T, const T, T&, and
// T. Versions producing errors and are commented out.
//
// Conversion chart:
diff --git a/test/SemaCXX/warn-shadow-in-lambdas.cpp b/test/SemaCXX/warn-shadow-in-lambdas.cpp
new file mode 100644
index 000000000000..575664482dbe
--- /dev/null
+++ b/test/SemaCXX/warn-shadow-in-lambdas.cpp
@@ -0,0 +1,139 @@
+// RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -Wshadow -D AVOID %s
+// RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -Wshadow -Wshadow-uncaptured-local %s
+// RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -Wshadow-all %s
+
+void foo(int param) { // expected-note 1+ {{previous declaration is here}}
+ int var = 0; // expected-note 1+ {{previous declaration is here}}
+
+ // Avoid warnings for variables that aren't implicitly captured.
+ {
+#ifdef AVOID
+ auto f1 = [=] { int var = 1; }; // no warning
+ auto f2 = [&] { int var = 2; }; // no warning
+ auto f3 = [=] (int param) { ; }; // no warning
+ auto f4 = [&] (int param) { ; }; // no warning
+#else
+ auto f1 = [=] { int var = 1; }; // expected-warning {{declaration shadows a local variable}}
+ auto f2 = [&] { int var = 2; }; // expected-warning {{declaration shadows a local variable}}
+ auto f3 = [=] (int param) { ; }; // expected-warning {{declaration shadows a local variable}}
+ auto f4 = [&] (int param) { ; }; // expected-warning {{declaration shadows a local variable}}
+#endif
+ }
+
+ // Warn for variables that are implicitly captured.
+ {
+ auto f1 = [=] () {
+ {
+ int var = 1; // expected-warning {{declaration shadows a local variable}}
+ }
+ int x = var; // expected-note {{variable 'var' is captured here}}
+ };
+ auto f2 = [&]
+#ifdef AVOID
+ (int param) {
+#else
+ (int param) { // expected-warning {{declaration shadows a local variable}}
+#endif
+ int x = var; // expected-note {{variable 'var' is captured here}}
+ int var = param; // expected-warning {{declaration shadows a local variable}}
+ };
+ }
+
+ // Warn for variables that are explicitly captured when a lambda has a default
+ // capture specifier.
+ {
+ auto f1 = [=, &var] () { // expected-note {{variable 'var' is captured here}}
+ int x = param; // expected-note {{variable 'param' is captured here}}
+ int var = 0; // expected-warning {{declaration shadows a local variable}}
+ int param = 0; // expected-warning {{declaration shadows a local variable}}
+ };
+ }
+
+ // Warn normally inside of lambdas.
+ auto l1 = [] { // expected-note {{previous declaration is here}}
+ int x = 1; // expected-note {{previous declaration is here}}
+ { int x = 2; } // expected-warning {{declaration shadows a local variable}}
+ };
+ auto l2 = [] (int x) { // expected-note {{previous declaration is here}}
+ { int x = 1; } // expected-warning {{declaration shadows a local variable}}
+ };
+
+ // Avoid warnings for variables that aren't explicitly captured.
+ {
+#ifdef AVOID
+ auto f1 = [] { int var = 1; }; // no warning
+ auto f2 = [] (int param) { ; }; // no warning
+ auto f3 = [param] () { int var = 1; }; // no warning
+ auto f4 = [var] (int param) { ; }; // no warning
+#else
+ auto f1 = [] { int var = 1; }; // expected-warning {{declaration shadows a local variable}}
+ auto f2 = [] (int param) { ; }; // expected-warning {{declaration shadows a local variable}}
+ auto f3 = [param] () { int var = 1; }; // expected-warning {{declaration shadows a local variable}}
+ auto f4 = [var] (int param) { ; }; // expected-warning {{declaration shadows a local variable}}
+#endif
+ };
+
+ // Warn for variables that are explicitly captured.
+ {
+ auto f1 = [var] () { // expected-note {{variable 'var' is explicitly captured here}}
+ int var = 1; // expected-warning {{declaration shadows a local variable}}
+ };
+ auto f2 = [param] // expected-note {{variable 'param' is explicitly captured here}}
+ (int param) { ; }; // expected-warning {{declaration shadows a local variable}}
+ }
+
+ // Warn for variables defined in the capture list.
+ auto l3 = [z = var] { // expected-note {{previous declaration is here}}
+#ifdef AVOID
+ int var = 1; // no warning
+#else
+ int var = 1; // expected-warning {{declaration shadows a local variable}}
+#endif
+ { int z = 1; } // expected-warning {{declaration shadows a local variable}}
+ };
+#ifdef AVOID
+ auto l4 = [var = param] (int param) { ; }; // no warning
+#else
+ auto l4 = [var = param] (int param) { ; }; // expected-warning {{declaration shadows a local variable}}
+#endif
+
+ // Make sure that inner lambdas work as well.
+ auto l5 = [var, l1] { // expected-note {{variable 'l1' is explicitly captured here}}
+ auto l1 = [] { // expected-warning {{declaration shadows a local variable}}
+#ifdef AVOID
+ int var = 1; // no warning
+#else
+ int var = 1; // expected-warning {{declaration shadows a local variable}}
+#endif
+ };
+#ifdef AVOID
+ auto f1 = [] { int var = 1; }; // no warning
+ auto f2 = [=] { int var = 1; }; // no warning
+#else
+ auto f1 = [] { int var = 1; }; // expected-warning {{declaration shadows a local variable}}
+ auto f2 = [=] { int var = 1; }; // expected-warning {{declaration shadows a local variable}}
+#endif
+ auto f3 = [var] // expected-note {{variable 'var' is explicitly captured here}}
+ { int var = 1; }; // expected-warning {{declaration shadows a local variable}}
+ auto f4 = [&] {
+ int x = var; // expected-note {{variable 'var' is captured here}}
+ int var = 2; // expected-warning {{declaration shadows a local variable}}
+ };
+ };
+ auto l6 = [&] {
+ auto f1 = [param] { // expected-note {{variable 'param' is explicitly captured here}}
+ int param = 0; // expected-warning {{declaration shadows a local variable}}
+ };
+ };
+
+ // Generic lambda arguments should work.
+#ifdef AVOID
+ auto g1 = [](auto param) { ; }; // no warning
+ auto g2 = [=](auto param) { ; }; // no warning
+#else
+ auto g1 = [](auto param) { ; }; // expected-warning {{declaration shadows a local variable}}
+ auto g2 = [=](auto param) { ; }; // expected-warning {{declaration shadows a local variable}}
+#endif
+ auto g3 = [param] // expected-note {{variable 'param' is explicitly captured here}}
+ (auto param) { ; }; // expected-warning {{declaration shadows a local variable}}
+}
diff --git a/test/SemaCXX/warn-unused-variables.cpp b/test/SemaCXX/warn-unused-variables.cpp
index 8dcbe7271d69..d7be785b35a6 100644
--- a/test/SemaCXX/warn-unused-variables.cpp
+++ b/test/SemaCXX/warn-unused-variables.cpp
@@ -150,3 +150,47 @@ namespace ctor_with_cleanups {
}
#include "Inputs/warn-unused-variables.h"
+
+namespace arrayRecords {
+
+class NonTriviallyDestructible {
+public:
+ ~NonTriviallyDestructible() {}
+};
+
+struct Foo {
+ int x;
+ Foo(int x) : x(x) {}
+};
+
+struct Elidable {
+ Elidable();
+};
+
+void foo(int size) {
+ Elidable elidable; // no warning
+ Elidable elidableArray[2]; // no warning
+ Elidable elidableDynArray[size]; // no warning
+ Elidable elidableNestedArray[1][2][3]; // no warning
+
+ NonTriviallyDestructible scalar; // no warning
+ NonTriviallyDestructible array[2]; // no warning
+ NonTriviallyDestructible nestedArray[2][2]; // no warning
+
+ Foo fooScalar = 1; // expected-warning {{unused variable 'fooScalar'}}
+ Foo fooArray[] = {1,2}; // expected-warning {{unused variable 'fooArray'}}
+ Foo fooNested[2][2] = { {1,2}, {3,4} }; // expected-warning {{unused variable 'fooNested'}}
+}
+
+template<int N>
+void bar() {
+ NonTriviallyDestructible scaler; // no warning
+ NonTriviallyDestructible array[N]; // no warning
+}
+
+void test() {
+ foo(10);
+ bar<2>();
+}
+
+}
diff --git a/test/SemaCXX/warn-weak-vtables.cpp b/test/SemaCXX/warn-weak-vtables.cpp
index d30665387153..e678f9e461ef 100644
--- a/test/SemaCXX/warn-weak-vtables.cpp
+++ b/test/SemaCXX/warn-weak-vtables.cpp
@@ -1,5 +1,8 @@
// RUN: %clang_cc1 %s -fsyntax-only -verify -triple %itanium_abi_triple -Wweak-vtables -Wweak-template-vtables
-// RUN: %clang_cc1 %s -fsyntax-only -triple %ms_abi_triple -Werror -Wno-weak-vtables -Wno-weak-template-vtables
+//
+// Check that this warning is disabled on MS ABI targets which don't have key
+// functions.
+// RUN: %clang_cc1 %s -fsyntax-only -triple %ms_abi_triple -Werror -Wweak-vtables -Wweak-template-vtables
struct A { // expected-warning {{'A' has no out-of-line virtual method definitions; its vtable will be emitted in every translation unit}}
virtual void f() { }
diff --git a/test/SemaObjC/arc.m b/test/SemaObjC/arc.m
index c723812212e3..f463bb03b075 100644
--- a/test/SemaObjC/arc.m
+++ b/test/SemaObjC/arc.m
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -fobjc-runtime-has-weak -fsyntax-only -fobjc-arc -fblocks -verify -Wno-objc-root-class %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -fobjc-runtime-has-weak -fsyntax-only -fobjc-arc -fblocks -verify -Wno-objc-root-class -Wblock-capture-autoreleasing %s
typedef unsigned long NSUInteger;
typedef const void * CFTypeRef;
@@ -808,3 +808,10 @@ int garf() {
TKAssertEqual(object, nil);
TKAssertEqual(object, (id)nil);
}
+
+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}}
+ ^{
+ (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/assign-rvalue-message.m b/test/SemaObjC/assign-rvalue-message.m
index a90cc50cdd35..c2cc1c8274ed 100644
--- a/test/SemaObjC/assign-rvalue-message.m
+++ b/test/SemaObjC/assign-rvalue-message.m
@@ -1,5 +1,6 @@
// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify -Wno-objc-root-class %s
-// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin10 -fsyntax-only -verify -Wno-objc-root-class %s
+// RUN: %clang_cc1 -std=c++98 -x objective-c++ -triple x86_64-apple-darwin10 -fsyntax-only -verify -Wno-objc-root-class %s
+// RUN: %clang_cc1 -std=c++11 -x objective-c++ -triple x86_64-apple-darwin10 -fsyntax-only -verify -Wno-objc-root-class %s
// rdar://9005189
@interface Foo
@@ -19,6 +20,6 @@ struct Bar {
- (void)baz {
bar.x = 0;
- [self bar].x = 10; // expected-error {{assigning to 'readonly' return result of an Objective-C message not allowed}}
+ [self bar].x = 10; // expected-error-re {{{{assigning to 'readonly' return result of an Objective-C message not allowed|expression is not assignable}}}}
}
@end
diff --git a/test/SemaObjC/attr-availability.m b/test/SemaObjC/attr-availability.m
index 6cbb3cc22d2f..02b7c5c81491 100644
--- a/test/SemaObjC/attr-availability.m
+++ b/test/SemaObjC/attr-availability.m
@@ -46,16 +46,16 @@ void f(A *a, B *b) {
[b proto_method]; // expected-warning{{'proto_method' is deprecated: first deprecated in macOS 10.2}}
#if defined(WARN_PARTIAL)
- // expected-warning@+2 {{'partialMethod' is partial: introduced in macOS 10.8}} expected-note@+2 {{explicitly redeclare 'partialMethod' to silence this warning}}
+ // expected-warning@+2 {{'partialMethod' is only available on macOS 10.8 or newer}} expected-note@+2 {{enclose 'partialMethod' in an @available check to silence this warning}}
#endif
[a partialMethod];
[b partialMethod]; // no warning
#if defined(WARN_PARTIAL)
- // expected-warning@+2 {{'partial_proto_method' is partial: introduced in macOS 10.8}} expected-note@+2 {{explicitly redeclare 'partial_proto_method' to silence this warning}}
+ // expected-warning@+2 {{'partial_proto_method' is only available on macOS 10.8 or newer}} expected-note@+2 {{enclose 'partial_proto_method' in an @available check to silence this warning}}
#endif
[a partial_proto_method];
#if defined(WARN_PARTIAL)
- // expected-warning@+2 {{'partial_proto_method' is partial: introduced in macOS 10.8}} expected-note@+2 {{explicitly redeclare 'partial_proto_method' to silence this warning}}
+ // expected-warning@+2 {{'partial_proto_method' is only available on macOS 10.8 or newer}} expected-note@+2 {{enclose 'partial_proto_method' in an @available check to silence this warning}}
#endif
[b partial_proto_method];
}
@@ -163,14 +163,14 @@ void partialfun(PartialI* a) {
[a partialMethod]; // no warning
[a ipartialMethod1]; // no warning
#if defined(WARN_PARTIAL)
- // expected-warning@+2 {{'ipartialMethod2' is partial: introduced in macOS 10.8}} expected-note@+2 {{explicitly redeclare 'ipartialMethod2' to silence this warning}}
+ // expected-warning@+2 {{'ipartialMethod2' is only available on macOS 10.8 or newer}} expected-note@+2 {{enclose 'ipartialMethod2' in an @available check to silence this warning}}
#endif
[a ipartialMethod2];
[a ppartialMethod]; // no warning
[PartialI partialMethod]; // no warning
[PartialI ipartialMethod1]; // no warning
#if defined(WARN_PARTIAL)
- // expected-warning@+2 {{'ipartialMethod2' is partial: introduced in macOS 10.8}} expected-note@+2 {{explicitly redeclare 'ipartialMethod2' to silence this warning}}
+ // expected-warning@+2 {{'ipartialMethod2' is only available on macOS 10.8 or newer}} expected-note@+2 {{enclose 'ipartialMethod2' in an @available check to silence this warning}}
#endif
[PartialI ipartialMethod2];
[PartialI ppartialMethod]; // no warning
@@ -294,3 +294,39 @@ __attribute__((objc_root_class))
[obj method]; // expected-error{{'method' is unavailable}}
}
@end
+
+#if defined(WARN_PARTIAL)
+
+int fn_10_5() __attribute__((availability(macosx, introduced=10.5)));
+int fn_10_7() __attribute__((availability(macosx, introduced=10.7))); // expected-note{{marked partial here}}
+int fn_10_8() __attribute__((availability(macosx, introduced=10.8))) { // expected-note{{marked partial here}}
+ return fn_10_7();
+}
+
+__attribute__((objc_root_class))
+@interface LookupAvailabilityBase
+-(void) method1;
+@end
+
+@implementation LookupAvailabilityBase
+-(void)method1 { fn_10_7(); } // expected-warning{{only available on macOS 10.7}} expected-note{{@available}}
+@end
+
+__attribute__((availability(macosx, introduced=10.7)))
+@interface LookupAvailability : LookupAvailabilityBase
+- (void)method2;
+- (void)method3;
+- (void)method4 __attribute__((availability(macosx, introduced=10.8)));
+@end
+
+@implementation LookupAvailability
+-(void)method2 { fn_10_7(); }
+-(void)method3 { fn_10_8(); } // expected-warning{{only available on macOS 10.8}} expected-note{{@available}}
+-(void)method4 { fn_10_8(); }
+@end
+
+int old_func() __attribute__((availability(macos, introduced=10.4))) {
+ fn_10_5();
+}
+
+#endif
diff --git a/test/SemaObjC/call-super-2.m b/test/SemaObjC/call-super-2.m
index 8927f3b52864..01acff70c230 100644
--- a/test/SemaObjC/call-super-2.m
+++ b/test/SemaObjC/call-super-2.m
@@ -106,3 +106,18 @@ id objc_getClass(const char *s);
}
@end
+@class C;
+@interface A // expected-note {{receiver is instance of class declared here}}
+- (instancetype)initWithCoder:(A *)coder;
+@end
+
+@interface B : A
+@end
+
+@implementation B
+- (instancetype)initWithCoder:(C *)coder {
+ if (0 != (self = [super initWithCode:code])) // expected-error {{use of undeclared identifier 'code'}} expected-warning {{instance method '-initWithCode:' not found}}
+ return (void *)0;
+ return (void *)0;
+}
+@end
diff --git a/test/SemaObjC/check-dup-objc-decls-1.m b/test/SemaObjC/check-dup-objc-decls-1.m
index d6fa53a2f0b2..7a2cd40424d3 100644
--- a/test/SemaObjC/check-dup-objc-decls-1.m
+++ b/test/SemaObjC/check-dup-objc-decls-1.m
@@ -35,6 +35,12 @@ void Gorf() // expected-error {{redefinition of 'Gorf' as different kind of symb
@protocol PP<P> @end // expected-note {{previous definition is here}}
@protocol PP<Q> @end // expected-warning {{duplicate protocol definition of 'PP'}}
+@protocol DP<P> @end
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wduplicate-protocol"
+@protocol DP<Q> @end
+#pragma clang diagnostic pop
+
@interface A(Cat)<P> @end // expected-note {{previous definition is here}}
@interface A(Cat)<Q> @end // expected-warning {{duplicate definition of category 'Cat' on interface 'A'}}
diff --git a/test/SemaObjC/class-unavail-warning.m b/test/SemaObjC/class-unavail-warning.m
index 6a683dd349c2..268d51910b0c 100644
--- a/test/SemaObjC/class-unavail-warning.m
+++ b/test/SemaObjC/class-unavail-warning.m
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -triple x86_64-apple-darwin10 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fblocks -triple x86_64-apple-darwin10 -verify %s
// rdar://9092208
__attribute__((unavailable("not available")))
@@ -98,3 +98,26 @@ UNAVAILABLE
@end
@interface UnavailSub(cat)<SomeProto> // no error
@end
+
+int unavail_global UNAVAILABLE;
+
+UNAVAILABLE __attribute__((objc_root_class))
+@interface TestAttrContext
+-meth;
+@end
+
+@implementation TestAttrContext
+-meth {
+ unavail_global = 2; // no warn
+ (void) ^{
+ unavail_global = 4; // no warn
+ };
+}
+@end
+
+typedef int unavailable_int UNAVAILABLE;
+
+UNAVAILABLE
+@interface A
+extern unavailable_int global_unavailable; // FIXME: this should be an error!
+@end
diff --git a/test/SemaObjC/crash-on-type-args-protocols.m b/test/SemaObjC/crash-on-type-args-protocols.m
new file mode 100644
index 000000000000..f7d847851faf
--- /dev/null
+++ b/test/SemaObjC/crash-on-type-args-protocols.m
@@ -0,0 +1,40 @@
+// RUN: %clang_cc1 -DFIRST -fsyntax-only -verify %s
+// RUN: %clang_cc1 -DSECOND -fsyntax-only -verify %s
+// RUN: %clang_cc1 -DTHIRD -fsyntax-only -verify %s
+// RUN: %clang_cc1 -DFOURTH -fsyntax-only -verify %s
+
+@protocol P;
+@interface NSObject
+@end
+@protocol X
+@end
+@interface X : NSObject <X>
+@end
+
+@class A;
+
+#ifdef FIRST
+id<X> F1(id<[P> v) { // expected-error {{expected a type}} // expected-error {{use of undeclared identifier 'P'}} // expected-error {{use of undeclared identifier 'v'}} // expected-note {{to match this '('}}
+ return 0;
+}
+#endif
+
+#ifdef SECOND
+id<X> F2(id<P[X> v) { // expected-error {{unknown type name 'P'}} // expected-error {{unexpected interface name 'X': expected expression}} // expected-error {{use of undeclared identifier 'v'}} // expected-note {{to match this '('}}
+ return 0;
+}
+#endif
+
+#ifdef THIRD
+id<X> F3(id<P, P *[> v) { // expected-error {{unknown type name 'P'}} // expected-error {{expected expression}} // expected-error {{use of undeclared identifier 'v'}} // expected-note {{to match this '('}}
+ return 0;
+}
+#endif
+
+#ifdef FOURTH
+id<X> F4(id<P, P *(> v { // expected-error {{unknown type name 'P'}} // expected-error {{expected ')'}} // expected-note {{to match this '('}} // expected-note {{to match this '('}}
+ return 0;
+}
+#endif
+
+// expected-error {{expected '>'}} // expected-error {{expected parameter declarator}} // expected-error {{expected ')'}} // expected-error {{expected function body after function declarator}}
diff --git a/test/SemaObjC/format-strings-objc.m b/test/SemaObjC/format-strings-objc.m
index d81f166a6540..767d5ac6cd63 100644
--- a/test/SemaObjC/format-strings-objc.m
+++ b/test/SemaObjC/format-strings-objc.m
@@ -47,7 +47,7 @@ int printf(const char * restrict, ...) ;
void check_nslog(unsigned k) {
NSLog(@"%d%%", k); // no-warning
- NSLog(@"%s%lb%d", "unix", 10,20); // expected-warning {{invalid conversion specifier 'b'}}
+ NSLog(@"%s%lb%d", "unix", 10, 20); // expected-warning {{invalid conversion specifier 'b'}} expected-warning {{data argument not used by format string}}
}
// Check type validation
@@ -264,3 +264,41 @@ void testObjCModifierFlags() {
NSLog(@"%2$[tt]@ %1$[tt]@", @"Foo", @"Bar"); // no-warning
NSLog(@"%2$[tt]@ %1$[tt]s", @"Foo", @"Bar"); // expected-warning {{object format flags cannot be used with 's' conversion specifier}}
}
+
+// rdar://23622446
+@interface RD23622446_Tester: NSObject
+
++ (void)stringWithFormat:(const char *)format, ... __attribute__((format(__printf__, 1, 2)));
+
+@end
+
+@implementation RD23622446_Tester
+
+__attribute__ ((format_arg(1)))
+const char *rd23622446(const char *format) {
+ return format;
+}
+
++ (void)stringWithFormat:(const char *)format, ... {
+ return;
+}
+
+- (const char *)test:(const char *)format __attribute__ ((format_arg(1))) {
+ return format;
+}
+
+- (NSString *)str:(NSString *)format __attribute__ ((format_arg(1))) {
+ return format;
+}
+
+- (void)foo {
+ [RD23622446_Tester stringWithFormat:rd23622446("%u"), 1, 2]; // expected-warning {{data argument not used by format string}}
+ [RD23622446_Tester stringWithFormat:[self test: "%u"], 1, 2]; // expected-warning {{data argument not used by format string}}
+ [RD23622446_Tester stringWithFormat:[self test: "%s %s"], "name"]; // expected-warning {{more '%' conversions than data arguments}}
+ NSLog([self str: @"%@ %@"], @"name"); // expected-warning {{more '%' conversions than data arguments}}
+ [RD23622446_Tester stringWithFormat:rd23622446("%d"), 1]; // ok
+ [RD23622446_Tester stringWithFormat:[self test: "%d %d"], 1, 2]; // ok
+ NSLog([self str: @"%@"], @"string"); // ok
+}
+
+@end
diff --git a/test/SemaObjC/format-strings-oslog.m b/test/SemaObjC/format-strings-oslog.m
new file mode 100644
index 000000000000..15c88e1b3792
--- /dev/null
+++ b/test/SemaObjC/format-strings-oslog.m
@@ -0,0 +1,65 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+#include <stdarg.h>
+#include <stddef.h>
+#define __need_wint_t
+#include <stddef.h> // For wint_t and wchar_t
+
+int printf(const char *restrict, ...);
+
+@interface NSString
+@end
+
+void test_os_log_format(const char *pc, int i, void *p, void *buf) {
+ __builtin_os_log_format(buf, "");
+ __builtin_os_log_format(buf, "%d"); // expected-warning {{more '%' conversions than data arguments}}
+ __builtin_os_log_format(buf, "%d", i);
+ __builtin_os_log_format(buf, "%P", p); // expected-warning {{using '%P' format specifier without precision}}
+ __builtin_os_log_format(buf, "%.10P", p);
+ __builtin_os_log_format(buf, "%.*P", p); // expected-warning {{field precision should have type 'int', but argument has type 'void *'}}
+ __builtin_os_log_format(buf, "%.*P", i, p);
+ __builtin_os_log_format(buf, "%.*P", i, i); // expected-warning {{format specifies type 'void *' but the argument has type 'int'}}
+ __builtin_os_log_format(buf, "%n"); // expected-error {{os_log() '%n' format specifier is not allowed}}
+ __builtin_os_log_format(buf, pc); // expected-error {{os_log() format argument is not a string constant}}
+
+ printf("%{private}s", pc); // expected-warning {{using 'private' format specifier annotation outside of os_log()/os_trace()}}
+ __builtin_os_log_format(buf, "%{private}s", pc);
+
+ // <rdar://problem/23835805>
+ __builtin_os_log_format_buffer_size("no-args");
+ __builtin_os_log_format(buf, "%s", "hi");
+
+ // <rdar://problem/24828090>
+ wchar_t wc = 'a';
+ __builtin_os_log_format(buf, "%C", wc);
+ printf("%C", wc);
+ wchar_t wcs[] = {'a', 0};
+ __builtin_os_log_format(buf, "%S", wcs);
+ printf("%S", wcs);
+
+ struct { char data[0x100]; } toobig;
+ __builtin_os_log_format(buf, "%s", toobig); // expected-error {{os_log() argument 2 is too big (256 bytes, max 255)}}
+}
+
+// Test os_log_format primitive with ObjC string literal format argument.
+void test_objc(const char *pc, int i, void *p, void *buf, NSString *nss) {
+ __builtin_os_log_format(buf, @"");
+ __builtin_os_log_format(buf, @"%d"); // expected-warning {{more '%' conversions than data arguments}}
+ __builtin_os_log_format(buf, @"%d", i);
+ __builtin_os_log_format(buf, @"%P", p); // expected-warning {{using '%P' format specifier without precision}}
+ __builtin_os_log_format(buf, @"%.10P", p);
+ __builtin_os_log_format(buf, @"%.*P", p); // expected-warning {{field precision should have type 'int', but argument has type 'void *'}}
+ __builtin_os_log_format(buf, @"%.*P", i, p);
+ __builtin_os_log_format(buf, @"%.*P", i, i); // expected-warning {{format specifies type 'void *' but the argument has type 'int'}}
+
+ __builtin_os_log_format(buf, @"%{private}s", pc);
+ __builtin_os_log_format(buf, @"%@", nss);
+}
+
+// Test the os_log format attribute.
+void MyOSLog(const char *format, ...) __attribute__((format(os_log, 1, 2)));
+void test_attribute(void *p) {
+ MyOSLog("%s\n", "Hello");
+ MyOSLog("%d"); // expected-warning {{more '%' conversions than data arguments}}
+ MyOSLog("%P", p); // expected-warning {{using '%P' format specifier without precision}}
+}
diff --git a/test/SemaObjC/kindof.m b/test/SemaObjC/kindof.m
index 63ba18fe89bc..9d758d3cfb2a 100644
--- a/test/SemaObjC/kindof.m
+++ b/test/SemaObjC/kindof.m
@@ -385,7 +385,7 @@ void testNullability() {
@end
@interface NSGeneric<ObjectType> : NSObject
-- (void)test:(__kindof ObjectType)T;
+- (void)test:(__kindof ObjectType)T; // expected-note{{passing argument to parameter 'T' here}}
- (void)mapUsingBlock:(id (^)(__kindof ObjectType))block;
@end
@implementation NSGeneric
@@ -395,6 +395,14 @@ void testNullability() {
}
@end
+void testGeneric(NSGeneric<NSString*> *generic) {
+ NSObject *NSObject_obj;
+ // Assign from NSObject_obj to __kindof NSString*.
+ [generic test:NSObject_obj]; // expected-warning{{incompatible pointer types sending 'NSObject *' to parameter of type '__kindof NSString *'}}
+ NSString *NSString_str;
+ [generic test:NSString_str];
+}
+
// Check that clang doesn't crash when a type parameter is illegal.
@interface Array1<T> : NSObject
@end
diff --git a/test/SemaObjC/method-redecls-invalid-interface.m b/test/SemaObjC/method-redecls-invalid-interface.m
new file mode 100644
index 000000000000..235d6fe5e9d7
--- /dev/null
+++ b/test/SemaObjC/method-redecls-invalid-interface.m
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -Wdocumentation -Wno-objc-root-class %s
+// rdar://29220965
+
+@interface InvalidInterface { // expected-note {{previous definition is here}}
+ int *_property;
+}
+
+@end
+
+/*!
+ */
+
+@interface InvalidInterface // expected-error {{duplicate interface definition for class 'InvalidInterface'}}
+@property int *property;
+
+-(void) method;
+@end
+
+@implementation InvalidInterface
+-(void) method { }
+@end
diff --git a/test/SemaObjC/nsobject-attribute.m b/test/SemaObjC/nsobject-attribute.m
index 6bd2d5dabc4b..7c8d75d531e0 100644
--- a/test/SemaObjC/nsobject-attribute.m
+++ b/test/SemaObjC/nsobject-attribute.m
@@ -21,6 +21,8 @@ typedef struct CGColor * __attribute__((NSObject)) CGColorRefNoNSObject; // no-w
@property (nonatomic, retain) CGColorRefNoNSObject color;
// rdar://problem/12197822
@property (strong) __attribute__((NSObject)) CFTypeRef myObj; // no-warning
+//rdar://problem/27747154
+@property (strong, nullable) CGColorRefNoNSObject color2; // no-warning
@end
void setProperty(id self, id value) {
diff --git a/test/SemaObjC/nullability.m b/test/SemaObjC/nullability.m
index 36ac6b9ddea2..cbfe132d143e 100644
--- a/test/SemaObjC/nullability.m
+++ b/test/SemaObjC/nullability.m
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -fblocks -Woverriding-method-mismatch -Wno-nullability-declspec %s -verify
+// RUN: %clang_cc1 -fsyntax-only -fblocks -Woverriding-method-mismatch -Wno-nullability-declspec -Wnullable-to-nonnull-conversion %s -verify
__attribute__((objc_root_class))
@interface NSFoo
@@ -230,3 +230,52 @@ void testBlockLiterals() {
int *x = (^ _Nullable id(void) { return 0; })(); // expected-warning{{incompatible pointer types initializing 'int *' with an expression of type 'id _Nullable'}}
}
+
+// Check nullability of conditional expressions.
+void conditional_expr(int c) {
+ NSFoo * _Nonnull p;
+ NSFoo * _Nonnull nonnullP;
+ NSFoo * _Nullable nullableP;
+ NSFoo * _Null_unspecified unspecifiedP;
+ NSFoo *noneP;
+
+ p = c ? nonnullP : nonnullP;
+ p = c ? nonnullP : nullableP; // expected-warning{{implicit conversion from nullable pointer 'NSFoo * _Nullable' to non-nullable pointer type 'NSFoo * _Nonnull'}}
+ p = c ? nonnullP : unspecifiedP;
+ p = c ? nonnullP : noneP;
+ p = c ? nullableP : nonnullP; // expected-warning{{implicit conversion from nullable pointer 'NSFoo * _Nullable' to non-nullable pointer type 'NSFoo * _Nonnull'}}
+ p = c ? nullableP : nullableP; // expected-warning{{implicit conversion from nullable pointer 'NSFoo * _Nullable' to non-nullable pointer type 'NSFoo * _Nonnull'}}
+ p = c ? nullableP : unspecifiedP; // expected-warning{{implicit conversion from nullable pointer 'NSFoo * _Nullable' to non-nullable pointer type 'NSFoo * _Nonnull'}}
+ p = c ? nullableP : noneP; // expected-warning{{implicit conversion from nullable pointer 'NSFoo * _Nullable' to non-nullable pointer type 'NSFoo * _Nonnull'}}
+ p = c ? unspecifiedP : nonnullP;
+ p = c ? unspecifiedP : nullableP; // expected-warning{{implicit conversion from nullable pointer 'NSFoo * _Nullable' to non-nullable pointer type 'NSFoo * _Nonnull'}}
+ p = c ? unspecifiedP : unspecifiedP;
+ p = c ? unspecifiedP : noneP;
+ p = c ? noneP : nonnullP;
+ p = c ? noneP : nullableP; // expected-warning{{implicit conversion from nullable pointer 'NSFoo * _Nullable' to non-nullable pointer type 'NSFoo * _Nonnull'}}
+ p = c ? noneP : unspecifiedP;
+ p = c ? noneP : noneP;
+}
+
+typedef int INTS[4];
+@interface ArraysInMethods
+- (void)simple:(int [_Nonnull 2])x;
+- (void)nested:(void *_Nullable [_Nonnull 2])x;
+- (void)nestedBad:(int [2][_Nonnull 2])x; // expected-error {{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'int [2]'}}
+
+- (void)withTypedef:(INTS _Nonnull)x;
+- (void)withTypedefBad:(INTS _Nonnull[2])x; // expected-error{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'INTS' (aka 'int [4]')}}
+
+- (void)simpleSugar:(nonnull int [2])x;
+- (void)nestedSugar:(nonnull void *_Nullable [2])x; // expected-error {{nullability keyword 'nonnull' cannot be applied to multi-level pointer type 'void * _Nullable [2]'}} expected-note {{use nullability type specifier '_Nonnull' to affect the innermost pointer type of 'void * _Nullable [2]'}}
+- (void)sugarWithTypedef:(nonnull INTS)x;
+@end
+
+void test(ArraysInMethods *obj) {
+ [obj simple:0]; // expected-warning {{null passed to a callee that requires a non-null argument}}
+ [obj nested:0]; // expected-warning {{null passed to a callee that requires a non-null argument}}
+ [obj withTypedef:0]; // expected-warning {{null passed to a callee that requires a non-null argument}}
+
+ [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}}
+}
diff --git a/test/SemaObjC/objc-array-literal.m b/test/SemaObjC/objc-array-literal.m
index 281994a758b2..c0a0c67d442d 100644
--- a/test/SemaObjC/objc-array-literal.m
+++ b/test/SemaObjC/objc-array-literal.m
@@ -67,3 +67,11 @@ id radar15147688() {
x = @[ @"stuff", @"hello" "world"]; // expected-warning {{concatenated NSString literal for an NSArray expression}}
return x;
}
+
+enum XXXYYYZZZType { XXXYYYZZZTypeAny }; // expected-note {{'XXXYYYZZZTypeAny' declared here}}
+void foo() {
+ NSArray *array = @[
+ @(XXXYYYZZZTypeA), // expected-error {{use of undeclared identifier 'XXXYYYZZZTypeA'; did you mean 'XXXYYYZZZTypeAny'}}
+ @(XXXYYYZZZTypeSomethingSomething) // expected-error {{use of undeclared identifier 'XXXYYYZZZTypeSomethingSomething'}}
+ ];
+}
diff --git a/test/SemaObjC/objc-dictionary-literal.m b/test/SemaObjC/objc-dictionary-literal.m
index 1a2c29f74db0..ce301a0c73af 100644
--- a/test/SemaObjC/objc-dictionary-literal.m
+++ b/test/SemaObjC/objc-dictionary-literal.m
@@ -63,3 +63,10 @@ int main() {
return 0;
}
+enum XXXYYYZZZType { XXXYYYZZZTypeAny }; // expected-note {{'XXXYYYZZZTypeAny' declared here}}
+void foo() {
+ NSDictionary *d = @{
+ @"A" : @(XXXYYYZZZTypeA), // expected-error {{use of undeclared identifier 'XXXYYYZZZTypeA'; did you mean 'XXXYYYZZZTypeAny'}}
+ @"F" : @(XXXYYYZZZTypeSomethingSomething), // expected-error {{use of undeclared identifier 'XXXYYYZZZTypeSomethingSomething'}}
+ };
+}
diff --git a/test/SemaObjC/objcbridge-attribute-arc.m b/test/SemaObjC/objcbridge-attribute-arc.m
index 26dbce09b816..3bcfdf48e794 100644
--- a/test/SemaObjC/objcbridge-attribute-arc.m
+++ b/test/SemaObjC/objcbridge-attribute-arc.m
@@ -23,10 +23,7 @@ typedef struct __CFSetRef * CFSetRef __attribute__((objc_bridge(NSSet))); // exp
typedef union __CFUColor __attribute__((objc_bridge(NSUColor))) * CFUColorRef; // expected-error {{parameter of 'objc_bridge' attribute must be 'id' when used on a typedef}}
-// This error requires C11.
-#if __STDC_VERSION__ > 199901L
-typedef union __CFUColor __attribute__((objc_bridge(NSUColor))) * CFUColorRef; // expected-error {{parameter of 'objc_bridge' attribute must be 'id' when used on a typedef}}
-#endif
+typedef union __CFUColor __attribute__((objc_bridge(NSUColor))) * CFUColorRef; // expected-error {{parameter of 'objc_bridge' attribute must be 'id' when used on a typedef}}
typedef union __CFUColor __attribute__((objc_bridge(NSUColor))) *CFUColor1Ref; // expected-error {{parameter of 'objc_bridge' attribute must be 'id' when used on a typedef}}
diff --git a/test/SemaObjC/parameterized_classes_subst.m b/test/SemaObjC/parameterized_classes_subst.m
index f90ee9093592..da2d56f11bc8 100644
--- a/test/SemaObjC/parameterized_classes_subst.m
+++ b/test/SemaObjC/parameterized_classes_subst.m
@@ -426,3 +426,36 @@ void test_ternary_operator(NSArray<NSString *> *stringArray,
// warning about likely protocol/class name typos.
// --------------------------------------------------------------------------
typedef NSArray<NSObject> ArrayOfNSObjectWarning; // expected-warning{{parameterized class 'NSArray' already conforms to the protocols listed; did you forget a '*'?}}
+
+// rdar://25060179
+@interface MyMutableDictionary<KeyType, ObjectType> : NSObject
+- (void)setObject:(ObjectType)obj forKeyedSubscript:(KeyType <NSCopying>)key; // expected-note{{passing argument to parameter 'obj' here}} \
+ // expected-note{{passing argument to parameter 'key' here}}
+@end
+
+void bar(MyMutableDictionary<NSString *, NSString *> *stringsByString,
+ NSNumber *n1, NSNumber *n2) {
+ // We warn here when the key types do not match.
+ stringsByString[n1] = n2; // expected-warning{{incompatible pointer types sending 'NSNumber *' to parameter of type 'NSString *'}} \
+ // expected-warning{{incompatible pointer types sending 'NSNumber *' to parameter of type 'NSString<NSCopying> *'}}
+}
+
+@interface MyTest<K, V> : NSObject <NSCopying>
+- (V)test:(K)key;
+- (V)test2:(K)key; // expected-note{{previous definition is here}}
+- (void)mapUsingBlock:(id (^)(V))block;
+- (void)mapUsingBlock2:(id (^)(V))block; // expected-note{{previous definition is here}}
+@end
+
+@implementation MyTest
+- (id)test:(id)key {
+ return key;
+}
+- (int)test2:(id)key{ // expected-warning{{conflicting return type in implementation}}
+ return 0;
+}
+- (void)mapUsingBlock:(id (^)(id))block {
+}
+- (void)mapUsingBlock2:(id)block { // expected-warning{{conflicting parameter types in implementation}}
+}
+@end
diff --git a/test/SemaObjC/property-deprecated-warning.m b/test/SemaObjC/property-deprecated-warning.m
index cec376838def..8cf4f9731bc4 100644
--- a/test/SemaObjC/property-deprecated-warning.m
+++ b/test/SemaObjC/property-deprecated-warning.m
@@ -9,7 +9,7 @@ typedef signed char BOOL;
@property(nonatomic,assign) id ptarget __attribute__((availability(ios,introduced=2.0,deprecated=3.0))); // expected-note {{property 'ptarget' is declared deprecated here}} expected-note {{'ptarget' has been explicitly marked deprecated here}}
#if defined(WARN_PARTIAL)
-// expected-note@+2 {{property 'partialPtarget' is declared partial here}} expected-note@+2 {{'partialPtarget' has been explicitly marked partial here}}
+// expected-note@+2 {{'partialPtarget' has been explicitly marked partial here}}
#endif
@property(nonatomic,assign) id partialPtarget __attribute__((availability(ios,introduced=5.0)));
@end
@@ -24,7 +24,7 @@ typedef signed char BOOL;
@property(nonatomic,assign) id target __attribute__((availability(ios,introduced=2.0,deprecated=3.0))); // expected-note {{property 'target' is declared deprecated here}} expected-note {{'setTarget:' has been explicitly marked deprecated here}}
#if defined(WARN_PARTIAL)
-// expected-note@+2 {{property 'partialTarget' is declared partial here}} expected-note@+2 {{'setPartialTarget:' has been explicitly marked partial here}}
+// expected-note@+2 {{'setPartialTarget:' has been explicitly marked partial here}}
#endif
@property(nonatomic,assign) id partialTarget __attribute__((availability(ios,introduced=5.0)));
@end
@@ -40,7 +40,7 @@ typedef signed char BOOL;
// expected-note 2 {{'setDep_target:' has been explicitly marked deprecated here}}
#if defined(WARN_PARTIAL)
-// expected-note@+2 4 {{property 'partial_dep_target' is declared partial here}} expected-note@+2 2 {{'partial_dep_target' has been explicitly marked partial here}} expected-note@+2 2 {{'setPartial_dep_target:' has been explicitly marked partial here}}
+// expected-note@+2 2 {{'partial_dep_target' has been explicitly marked partial here}} expected-note@+2 2 {{'setPartial_dep_target:' has been explicitly marked partial here}}
#endif
@property(nonatomic,assign) id partial_dep_target __attribute__((availability(ios,introduced=5.0)));
@end
@@ -57,7 +57,7 @@ typedef signed char BOOL;
[self setPtarget: (id)0]; // no-warning
[self setPartialTarget: (id)0]; // no-warning
#if defined(WARN_PARTIAL)
- // expected-warning@+2 {{'partial_dep_target' is partial: introduced in iOS 5.0}} expected-warning@+2 {{'setPartial_dep_target:' is partial: introduced in iOS 5.0}} expected-note@+2 {{explicitly redeclare 'partial_dep_target' to silence this warning}} expected-note@+2 {{explicitly redeclare 'setPartial_dep_target:' to silence this warning}}
+ // expected-warning@+2 {{'partial_dep_target' is only available on iOS 5.0 or newer}} expected-warning@+2 {{'setPartial_dep_target:' is only available on iOS 5.0 or newer}} expected-note@+2 {{enclose 'partial_dep_target' in an @available check to silence this warning}} expected-note@+2 {{enclose 'setPartial_dep_target:' in an @available check to silence this warning}}
#endif
[self setPartial_dep_target: [self partial_dep_target]];
@@ -82,11 +82,11 @@ typedef signed char BOOL;
[self setPtarget: (id)0]; // no-warning
#if defined(WARN_PARTIAL)
- // expected-warning@+2 {{'setPartialTarget:' is partial: introduced in iOS 5.0}} expected-note@+2 {{explicitly redeclare 'setPartialTarget:' to silence this warning}}
+ // expected-warning@+2 {{'setPartialTarget:' is only available on iOS 5.0 or newer}} expected-note@+2 {{enclose 'setPartialTarget:' in an @available check to silence this warning}}
#endif
[self setPartialTarget: (id)0];
#if defined(WARN_PARTIAL)
- // expected-warning@+2 {{'partial_dep_target' is partial: introduced in iOS 5.0}} expected-warning@+2 {{'setPartial_dep_target:' is partial: introduced in iOS 5.0}} expected-note@+2 {{explicitly redeclare 'partial_dep_target' to silence this warning}} expected-note@+2 {{explicitly redeclare 'setPartial_dep_target:' to silence this warning}}
+ // expected-warning@+2 {{'partial_dep_target' is only available on iOS 5.0 or newer}} expected-warning@+2 {{'setPartial_dep_target:' is only available on iOS 5.0 or newer}} expected-note@+2 {{enclose 'partial_dep_target' in an @available check to silence this warning}} expected-note@+2 {{enclose 'setPartial_dep_target:' in an @available check to silence this warning}}
#endif
[self setPartial_dep_target: [self partial_dep_target]];
[self setPartialPtarget: (id)0]; // no-warning
@@ -100,12 +100,12 @@ typedef signed char BOOL;
@property(setter=setNewDelegate:,assign) id delegate __attribute__((availability(ios,introduced=2.0,deprecated=3.0))); // expected-note {{'setNewDelegate:' has been explicitly marked deprecated here}} expected-note {{property 'delegate' is declared deprecated here}}
#if defined(WARN_PARTIAL)
-// expected-note@+2 {{property 'partialEnabled' is declared partial here}} expected-note@+2 {{'partialIsEnabled' has been explicitly marked partial here}}
+// expected-note@+2 {{'partialIsEnabled' has been explicitly marked partial here}}
#endif
@property(getter=partialIsEnabled,assign) BOOL partialEnabled __attribute__((availability(ios,introduced=5.0)));
#if defined(WARN_PARTIAL)
-// expected-note@+2 {{property 'partialDelegate' is declared partial here}} expected-note@+2 {{'partialSetNewDelegate:' has been explicitly marked partial here}}
+// expected-note@+2 {{'partialSetNewDelegate:' has been explicitly marked partial here}}
#endif
@property(setter=partialSetNewDelegate:,assign) id partialDelegate __attribute__((availability(ios,introduced=5.0)));
@end
@@ -115,7 +115,7 @@ void testCustomAccessorNames(CustomAccessorNames *obj) {
[obj setNewDelegate:0]; // expected-warning {{'setNewDelegate:' is deprecated: first deprecated in iOS 3.0}}
#if defined(WARN_PARTIAL)
-// expected-warning@+2 {{'partialIsEnabled' is partial: introduced in iOS 5.0}} expected-warning@+3 {{'partialSetNewDelegate:' is partial: introduced in iOS 5.0}} expected-note@+2 {{explicitly redeclare 'partialIsEnabled' to silence this warning}} expected-note@+3 {{explicitly redeclare 'partialSetNewDelegate:' to silence this warning}}
+ // expected-warning@+2 {{'partialIsEnabled' is only available on iOS 5.0 or newer}} expected-warning@+3 {{'partialSetNewDelegate:' is only available on iOS 5.0 or newer}} expected-note@+2 {{enclose 'partialIsEnabled' in an @available check to silence this warning}} expected-note@+3 {{enclose 'partialSetNewDelegate:' in an @available check to silence this warning}}
#endif
if ([obj partialIsEnabled])
[obj partialSetNewDelegate:0];
@@ -138,7 +138,7 @@ id useDeprecatedProperty(ProtocolInCategory *obj, id<P> obj2, int flag) {
if (flag)
return [obj partialPtarget]; // no-warning
#if defined(WARN_PARTIAL)
-// expected-warning@+2 {{'partialPtarget' is partial: introduced in iOS 5.0}} expected-note@+2 {{explicitly redeclare 'partialPtarget' to silence this warning}}
+// expected-warning@+2 {{'partialPtarget' is only available on iOS 5.0 or newer}} expected-note@+2 {{enclose 'partialPtarget' in an @available check to silence this warning}}
#endif
return [obj2 partialPtarget];
}
diff --git a/test/SemaObjC/subclassing-restricted-attr.m b/test/SemaObjC/subclassing-restricted-attr.m
new file mode 100644
index 000000000000..d0db5e452f04
--- /dev/null
+++ b/test/SemaObjC/subclassing-restricted-attr.m
@@ -0,0 +1,36 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -Wno-objc-root-class %s
+// RUN: %clang_cc1 -x objective-c++ -fsyntax-only -verify -Wno-objc-root-class %s
+// rdar://16560476
+
+__attribute__((objc_subclassing_restricted))
+@interface Leaf // okay
+@end
+
+__attribute__((objc_subclassing_restricted))
+@interface SubClassOfLeaf : Leaf // expected-note {{class is declared here}}
+@end
+
+
+@interface SubClass : SubClassOfLeaf // expected-error {{cannot subclass a class that was declared with the 'objc_subclassing_restricted' attribute}}
+@end
+
+__attribute__((objc_root_class))
+@interface PlainRoot
+@end
+
+__attribute__((objc_subclassing_restricted))
+@interface Sub2Class : PlainRoot // okay
+@end
+
+// rdar://28753587
+__attribute__((objc_subclassing_restricted))
+@interface SuperImplClass // expected-note {{class is declared here}}
+@end
+@implementation SuperImplClass
+@end
+
+__attribute__((objc_subclassing_restricted))
+@interface SubImplClass : SuperImplClass
+@end
+@implementation SubImplClass // expected-error {{cannot subclass a class that was declared with the 'objc_subclassing_restricted' attribute}}
+@end
diff --git a/test/SemaObjC/typo-correction.m b/test/SemaObjC/typo-correction.m
index 58824e2edbf0..f19ec1a1fa3c 100644
--- a/test/SemaObjC/typo-correction.m
+++ b/test/SemaObjC/typo-correction.m
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -verify -fsyntax-only
+// RUN: %clang_cc1 %s -verify -fsyntax-only -fobjc-runtime=ios
@protocol P
-(id)description;
@@ -28,3 +28,26 @@ typedef int super1;
[self foo:[super description] other:someivar]; // expected-error {{use of undeclared identifier 'someivar'; did you mean '_someivar'?}}
}
@end
+
+__attribute__ (( __objc_root_class__ ))
+@interface I {
+ id _interface; // expected-note {{'_interface' declared here}}
+}
+-(void)method;
+@end
+
+@interface I () {
+ id _extension; // expected-note {{'_extension' declared here}}
+}
+@end
+
+@implementation I {
+ id _implementation; // expected-note {{'_implementation' declared here}}
+}
+-(void)method {
+ (void)self->implementation; // expected-error {{'I' does not have a member named 'implementation'; did you mean '_implementation'?}}
+ (void)self->interface; // expected-error {{'I' does not have a member named 'interface'; did you mean '_interface'?}}
+ (void)self->extension; // expected-error {{'I' does not have a member named 'extension'; did you mean '_extension'?}}
+}
+@end
+
diff --git a/test/SemaObjC/unguarded-availability.m b/test/SemaObjC/unguarded-availability.m
new file mode 100644
index 000000000000..4369a0e329d2
--- /dev/null
+++ b/test/SemaObjC/unguarded-availability.m
@@ -0,0 +1,179 @@
+// RUN: %clang_cc1 -triple x86_64-apple-macosx-10.9 -Wunguarded-availability -fblocks -fsyntax-only -verify %s
+// RUN: %clang_cc1 -xobjective-c++ -DOBJCPP -triple x86_64-apple-macosx-10.9 -Wunguarded-availability -fblocks -fsyntax-only -verify %s
+
+#define AVAILABLE_10_0 __attribute__((availability(macos, introduced = 10.0)))
+#define AVAILABLE_10_11 __attribute__((availability(macos, introduced = 10.11)))
+#define AVAILABLE_10_12 __attribute__((availability(macos, introduced = 10.12)))
+
+int func_10_11() AVAILABLE_10_11; // expected-note 4 {{'func_10_11' has been explicitly marked partial here}}
+
+#ifdef OBJCPP
+// expected-note@+2 {{marked partial here}}
+#endif
+int func_10_12() AVAILABLE_10_12; // expected-note 5 {{'func_10_12' has been explicitly marked partial here}}
+
+int func_10_0() AVAILABLE_10_0;
+
+void use_func() {
+ 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}}
+
+ if (@available(macos 10.11, *))
+ func_10_11();
+ else
+ 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 defn_10_11() AVAILABLE_10_11;
+
+void defn_10_11() {
+ func_10_11();
+}
+
+void nested_ifs() {
+ if (@available(macos 10.12, *)) {
+ if (@available(macos 10.10, *)) {
+ func_10_12();
+ } else {
+ func_10_12();
+ }
+ } else {
+ func_10_12(); // expected-warning{{'func_10_12' is only available on macOS 10.12 or newer}} expected-note{{enclose 'func_10_12' in an @available check to silence this warning}}
+ }
+}
+
+void star_case() {
+ if (@available(ios 9, *)) {
+ 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}}
+ func_10_0();
+ } else
+ 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}}
+
+ if (@available(macos 10.11, *)) {
+ if (@available(ios 8, *)) {
+ func_10_11();
+ func_10_12(); // expected-warning{{'func_10_12' is only available on macOS 10.12 or newer}} expected-note{{enclose}}
+ } else {
+ func_10_11();
+ func_10_12(); // expected-warning{{'func_10_12' is only available on macOS 10.12 or newer}} expected-note{{enclose}}
+ }
+ }
+}
+
+typedef int int_10_11 AVAILABLE_10_11; // expected-note {{'int_10_11' has been explicitly marked partial here}}
+#ifdef OBJCPP
+// expected-note@+2 {{marked partial here}}
+#endif
+typedef int int_10_12 AVAILABLE_10_12; // expected-note 2 {{'int_10_12' has been explicitly marked partial here}}
+
+void use_typedef() {
+ int_10_11 x; // expected-warning{{'int_10_11' is only available on macOS 10.11 or newer}} expected-note{{enclose 'int_10_11' in an @available check to silence this warning}}
+}
+
+__attribute__((objc_root_class))
+AVAILABLE_10_11 @interface Class_10_11 {
+ int_10_11 foo;
+ int_10_12 bar; // expected-warning {{'int_10_12' is partial: introduced in macOS 10.12}} expected-note{{redeclare}}
+}
+- (void)method1;
+- (void)method2;
+@end
+
+@implementation Class_10_11
+- (void) method1 {
+ func_10_11();
+ func_10_12(); // expected-warning{{'func_10_12' is only available on macOS 10.12 or newer}} expected-note{{enclose 'func_10_12' in an @available check to silence this warning}}
+}
+
+- (void)method2 AVAILABLE_10_12 {
+ func_10_12();
+}
+
+@end
+
+int protected_scope() {
+ if (@available(macos 10.20, *)) { // expected-note 2 {{jump enters controlled statement of if available}}
+ label1:
+ return 0;
+ } else {
+ label2:
+ goto label1; // expected-error{{cannot jump from this goto statement to its label}}
+ }
+
+ goto label2; // expected-error{{cannot jump from this goto statement to its label}}
+}
+
+struct S {
+ int m1;
+ int m2 __attribute__((availability(macos, introduced = 10.12))); // expected-note{{marked partial here}}
+
+ struct Nested {
+ int nested_member __attribute__((availability(macos, introduced = 10.12))); // expected-note{{marked partial here}}
+ } n;
+};
+
+int test_members() {
+ struct S s;
+ (void)s.m1;
+ (void)s.m2; // expected-warning{{'m2' is only available on macOS 10.12 or newer}} expected-note{{@available}}
+
+ (void)s.n.nested_member; // expected-warning{{'nested_member' is only available on macOS 10.12 or newer}} expected-note{{@available}}
+}
+
+void test_blocks() {
+ (void) ^{
+ func_10_12(); // expected-warning{{'func_10_12' is only available on macOS 10.12 or newer}} expected-note{{@available}}
+ };
+}
+
+void test_params(int_10_12 x); // expected-warning {{'int_10_12' is partial: introduced in macOS 10.12}} expected-note{{redeclare}}
+
+void test_params2(int_10_12 x) AVAILABLE_10_12; // no warn
+
+#ifdef OBJCPP
+
+int f(char) AVAILABLE_10_12;
+int f(int);
+
+template <class T> int use_f() {
+ // FIXME: We should warn here!
+ return f(T());
+}
+
+int a = use_f<int>();
+int b = use_f<char>();
+
+template <class> int use_at_available() {
+ if (@available(macos 10.12, *))
+ return func_10_12();
+ else
+ return func_10_12(); // expected-warning {{'func_10_12' is only available on macOS 10.12 or newer}} expected-note{{enclose}}
+}
+
+int instantiate_template() {
+ if (@available(macos 10.12, *)) {
+ use_at_available<char>();
+ } else {
+ use_at_available<float>();
+ }
+}
+
+template <class>
+int with_availability_attr() AVAILABLE_10_11 { // expected-note 2 {{marked partial here}}
+ return 0;
+}
+
+int instantiate_with_availability_attr() {
+ if (@available(macos 10.12, *))
+ with_availability_attr<char>();
+ else
+ with_availability_attr<int>(); // expected-warning {{'with_availability_attr<int>' is only available on macOS 10.11 or newer}} expected-note {{enclose}}
+}
+
+int instantiate_availability() {
+ if (@available(macos 10.12, *))
+ with_availability_attr<int_10_12>();
+ else
+ with_availability_attr<int_10_12>(); // expected-warning{{'with_availability_attr<int>' is only available on macOS 10.11 or newer}} expected-warning{{'int_10_12' is only available on macOS 10.12 or newer}} expected-note 2 {{enclose}}
+}
+
+#endif
diff --git a/test/SemaObjCXX/Inputs/nullability-consistency-1.h b/test/SemaObjCXX/Inputs/nullability-consistency-1.h
index 6ab48fe0cd8f..f04b5692c88d 100644
--- a/test/SemaObjCXX/Inputs/nullability-consistency-1.h
+++ b/test/SemaObjCXX/Inputs/nullability-consistency-1.h
@@ -1,17 +1,35 @@
void f1(int *ptr); // expected-warning{{pointer is missing a nullability type specifier}}
+// expected-note@-1 {{insert '_Nullable' if the pointer may be null}}
+// expected-note@-2 {{insert '_Nonnull' if the pointer should never be null}}
void f2(int * _Nonnull);
#include "nullability-consistency-2.h"
void f3(int *ptr) { // expected-warning{{pointer is missing a nullability type specifier}}
+// expected-note@-1 {{insert '_Nullable' if the pointer may be null}}
+// expected-note@-2 {{insert '_Nonnull' if the pointer should never be null}}
int *other = ptr; // shouldn't warn
}
class X {
void mf(int *ptr); // expected-warning{{pointer is missing a nullability type specifier}}
+// expected-note@-1 {{insert '_Nullable' if the pointer may be null}}
+// expected-note@-2 {{insert '_Nonnull' if the pointer should never be null}}
int X:: *memptr; // expected-warning{{member pointer is missing a nullability type specifier}}
+// expected-note@-1 {{insert '_Nullable' if the member pointer may be null}}
+// expected-note@-2 {{insert '_Nonnull' if the member pointer should never be null}}
};
+template <typename T>
+struct Typedefs {
+ typedef T *Base; // no-warning
+ typedef Base *type; // expected-warning{{pointer is missing a nullability type specifier}}
+// expected-note@-1 {{insert '_Nullable' if the pointer may be null}}
+// expected-note@-2 {{insert '_Nonnull' if the pointer should never be null}}
+};
+
+Typedefs<int> xx;
+Typedefs<void *> yy;
diff --git a/test/SemaObjCXX/Inputs/nullability-consistency-2.h b/test/SemaObjCXX/Inputs/nullability-consistency-2.h
index 5203146353ea..72f22e2ce473 100644
--- a/test/SemaObjCXX/Inputs/nullability-consistency-2.h
+++ b/test/SemaObjCXX/Inputs/nullability-consistency-2.h
@@ -1,11 +1,17 @@
void g1(int * _Nonnull);
void g2(int (^block)(int, int)); // expected-warning{{block pointer is missing a nullability type specifier}}
+// expected-note@-1 {{insert '_Nullable' if the block pointer may be null}}
+// expected-note@-2 {{insert '_Nonnull' if the block pointer should never be null}}
void g3(const
id // expected-warning{{missing a nullability type specifier}}
+// expected-note@-1 {{insert '_Nullable' if the pointer may be null}}
+// expected-note@-2 {{insert '_Nonnull' if the pointer should never be null}}
volatile
* // expected-warning{{missing a nullability type specifier}}
+// expected-note@-1 {{insert '_Nullable' if the pointer may be null}}
+// expected-note@-2 {{insert '_Nonnull' if the pointer should never be null}}
);
@interface SomeClass
@@ -14,8 +20,12 @@ void g3(const
- (nullable SomeClass *)method1;
- (void)method2:(nonnull SomeClass *)param;
@property (readonly, weak) SomeClass *property3; // expected-warning{{missing a nullability type specifier}}
+// expected-note@-1 {{insert '_Nullable' if the pointer may be null}}
+// expected-note@-2 {{insert '_Nonnull' if the pointer should never be null}}
@end
@interface SomeClass ()
@property (readonly, weak) SomeClass *property4; // expected-warning{{missing a nullability type specifier}}
+// expected-note@-1 {{insert '_Nullable' if the pointer may be null}}
+// expected-note@-2 {{insert '_Nonnull' if the pointer should never be null}}
@end
diff --git a/test/SemaObjCXX/Inputs/nullability-consistency-3.h b/test/SemaObjCXX/Inputs/nullability-consistency-3.h
index 520d1a4b3442..e188151364b5 100644
--- a/test/SemaObjCXX/Inputs/nullability-consistency-3.h
+++ b/test/SemaObjCXX/Inputs/nullability-consistency-3.h
@@ -1 +1,3 @@
void double_declarator1(int *_Nonnull *); // expected-warning{{pointer is missing a nullability type specifier (_Nonnull, _Nullable, or _Null_unspecified)}}
+// expected-note@-1 {{insert '_Nullable' if the pointer may be null}}
+// expected-note@-2 {{insert '_Nonnull' if the pointer should never be null}}
diff --git a/test/SemaObjCXX/Inputs/nullability-consistency-4.h b/test/SemaObjCXX/Inputs/nullability-consistency-4.h
index ac227a0885bf..935c09334e31 100644
--- a/test/SemaObjCXX/Inputs/nullability-consistency-4.h
+++ b/test/SemaObjCXX/Inputs/nullability-consistency-4.h
@@ -1 +1,3 @@
void double_declarator1(int * * _Nonnull); // expected-warning{{pointer is missing a nullability type specifier (_Nonnull, _Nullable, or _Null_unspecified)}}
+// expected-note@-1 {{insert '_Nullable' if the pointer may be null}}
+// expected-note@-2 {{insert '_Nonnull' if the pointer should never be null}}
diff --git a/test/SemaObjCXX/Inputs/nullability-consistency-5.h b/test/SemaObjCXX/Inputs/nullability-consistency-5.h
index 1c74ab882a17..30666c2eebba 100644
--- a/test/SemaObjCXX/Inputs/nullability-consistency-5.h
+++ b/test/SemaObjCXX/Inputs/nullability-consistency-5.h
@@ -7,6 +7,8 @@
void suppress1(SUPPRESS_NULLABILITY_WARNING(int *) ptr); // no warning
void shouldwarn5(int *ptr); //expected-warning{{missing a nullability type specifier}}
+// expected-note@-1 {{insert '_Nullable' if the pointer may be null}}
+// expected-note@-2 {{insert '_Nonnull' if the pointer should never be null}}
void trigger5(int * _Nonnull);
diff --git a/test/SemaObjCXX/Inputs/nullability-consistency-6.h b/test/SemaObjCXX/Inputs/nullability-consistency-6.h
index d1764a87dc63..e9b2f9b13b46 100644
--- a/test/SemaObjCXX/Inputs/nullability-consistency-6.h
+++ b/test/SemaObjCXX/Inputs/nullability-consistency-6.h
@@ -1,8 +1,11 @@
int *ptr; // expected-warning {{missing a nullability type specifier}}
-
+// expected-note@-1{{insert '_Nullable' if the pointer may be null}}
+// expected-note@-2{{insert '_Nonnull' if the pointer should never be null}}
#pragma clang assume_nonnull begin
extern void **blah; // expected-warning 2{{missing a nullability type specifier}}
+// expected-note@-1 2 {{insert '_Nullable' if the pointer may be null}}
+// expected-note@-2 2 {{insert '_Nonnull' if the pointer should never be null}}
__attribute__((objc_root_class))
@interface ClassWithWeakProperties
diff --git a/test/SemaObjCXX/Inputs/nullability-consistency-7.h b/test/SemaObjCXX/Inputs/nullability-consistency-7.h
index ddbdfada7991..ed61666e6e74 100644
--- a/test/SemaObjCXX/Inputs/nullability-consistency-7.h
+++ b/test/SemaObjCXX/Inputs/nullability-consistency-7.h
@@ -33,7 +33,11 @@ __attribute__((unavailable("just don't")))
@interface C : A
- (instancetype)init; // expected-warning{{pointer is missing a nullability type specifier}}
+// expected-note@-1{{insert '_Nullable' if the pointer may be null}}
+// expected-note@-2{{insert '_Nonnull' if the pointer should never be null}}
- (instancetype)initWithA:( A*)a __attribute__((objc_designated_initializer)); // expected-warning 2{{pointer is missing a nullability type specifier}}
+// expected-note@-1 2{{insert '_Nullable' if the pointer may be null}}
+// expected-note@-2 2{{insert '_Nonnull' if the pointer should never be null}}
@end
#endif
diff --git a/test/SemaObjCXX/Inputs/nullability-consistency-8.h b/test/SemaObjCXX/Inputs/nullability-consistency-8.h
index 2425a70356d9..1f7131577eb5 100644
--- a/test/SemaObjCXX/Inputs/nullability-consistency-8.h
+++ b/test/SemaObjCXX/Inputs/nullability-consistency-8.h
@@ -8,10 +8,14 @@ __attribute__((objc_root_class))
void func2(mynonnull i);
void func3(int *); // expected-warning{{pointer is missing a nullability type specifier}}
+// expected-note@-1{{insert '_Nullable' if the pointer may be null}}
+// expected-note@-2{{insert '_Nonnull' if the pointer should never be null}}
#define CF_RETURNS_NOT_RETAINED __attribute__((cf_returns_not_retained))
typedef void *CFTypeRef;
-void cf1(CFTypeRef * p CF_RETURNS_NOT_RETAINED); // expected-warning {{pointer is missing a nullability type specifier}}
+void cf1(CFTypeRef * p CF_RETURNS_NOT_RETAINED); // expected-warning{{pointer is missing a nullability type specifier}}
+// expected-note@-1{{insert '_Nullable' if the pointer may be null}}
+// expected-note@-2{{insert '_Nonnull' if the pointer should never be null}}
void cf2(CFTypeRef * _Nullable p CF_RETURNS_NOT_RETAINED);
void cf3(CFTypeRef * _Nonnull p CF_RETURNS_NOT_RETAINED);
@@ -23,5 +27,7 @@ void cf6(CFTypeRef * _Nullable CF_RETURNS_NOT_RETAINED p);
void cf7(CF_RETURNS_NOT_RETAINED CFTypeRef * _Nonnull p);
typedef CFTypeRef _Nullable *CFTypeRefPtr;
-void cfp1(CFTypeRefPtr p CF_RETURNS_NOT_RETAINED); // expected-warning {{pointer is missing a nullability type specifier}}
+void cfp1(CFTypeRefPtr p CF_RETURNS_NOT_RETAINED); // expected-warning{{pointer is missing a nullability type specifier}}
+// expected-note@-1{{insert '_Nullable' if the pointer may be null}}
+// expected-note@-2{{insert '_Nonnull' if the pointer should never be null}}
void cfp2(CFTypeRefPtr _Nonnull p CF_RETURNS_NOT_RETAINED);
diff --git a/test/SemaObjCXX/Inputs/nullability-consistency-arrays.h b/test/SemaObjCXX/Inputs/nullability-consistency-arrays.h
new file mode 100644
index 000000000000..d0d5125bff19
--- /dev/null
+++ b/test/SemaObjCXX/Inputs/nullability-consistency-arrays.h
@@ -0,0 +1,141 @@
+#include <stdarg.h>
+
+void firstThingInTheFileThatNeedsNullabilityIsAnArray(int ints[]);
+#if ARRAYS_CHECKED
+// expected-warning@-2 {{array parameter is missing a nullability type specifier}}
+// expected-note@-3 {{insert '_Nullable' if the array parameter may be null}}
+// expected-note@-4 {{insert '_Nonnull' if the array parameter should never be null}}
+#endif
+
+int *secondThingInTheFileThatNeedsNullabilityIsAPointer;
+#if !ARRAYS_CHECKED
+// expected-warning@-2 {{pointer is missing a nullability type specifier (_Nonnull, _Nullable, or _Null_unspecified)}}
+// expected-note@-3 {{insert '_Nullable' if the pointer may be null}}
+// expected-note@-4 {{insert '_Nonnull' if the pointer should never be null}}
+#endif
+
+int *_Nonnull triggerConsistencyWarnings;
+
+void test(
+ int ints[],
+#if ARRAYS_CHECKED
+// expected-warning@-2 {{array parameter is missing a nullability type specifier}}
+// expected-note@-3 {{insert '_Nullable' if the array parameter may be null}}
+// expected-note@-4 {{insert '_Nonnull' if the array parameter should never be null}}
+#endif
+ void *ptrs[], // expected-warning {{pointer is missing a nullability type specifier}}
+// expected-note@-1 {{insert '_Nullable' if the pointer may be null}}
+// expected-note@-2 {{insert '_Nonnull' if the pointer should never be null}}
+#if ARRAYS_CHECKED
+// expected-warning@-4 {{array parameter is missing a nullability type specifier}}
+// expected-note@-5 {{insert '_Nullable' if the array parameter may be null}}
+// expected-note@-6 {{insert '_Nonnull' if the array parameter should never be null}}
+#endif
+ void **nestedPtrs[]); // expected-warning 2 {{pointer is missing a nullability type specifier}}
+// expected-note@-1 2 {{insert '_Nullable' if the pointer may be null}}
+// expected-note@-2 2 {{insert '_Nonnull' if the pointer should never be null}}
+#if ARRAYS_CHECKED
+// expected-warning@-4 {{array parameter is missing a nullability type specifier}}
+// expected-note@-5 {{insert '_Nullable' if the array parameter may be null}}
+// expected-note@-6 {{insert '_Nonnull' if the array parameter should never be null}}
+#endif
+
+void testArraysOK(
+ int ints[_Nonnull],
+ void *ptrs[_Nonnull], // expected-warning {{pointer is missing a nullability type specifier}}
+// expected-note@-1 {{insert '_Nullable' if the pointer may be null}}
+// expected-note@-2 {{insert '_Nonnull' if the pointer should never be null}}
+ void **nestedPtrs[_Nonnull]); // expected-warning 2 {{pointer is missing a nullability type specifier}}
+// expected-note@-1 2 {{insert '_Nullable' if the pointer may be null}}
+// expected-note@-2 2 {{insert '_Nonnull' if the pointer should never be null}}
+void testAllOK(
+ int ints[_Nonnull],
+ void * _Nullable ptrs[_Nonnull],
+ void * _Nullable * _Nullable nestedPtrs[_Nonnull]);
+
+void testVAList(va_list ok); // no warning
+
+#if __cplusplus
+// Carefully construct a test case such that if a platform's va_list is an array
+// or pointer type, it gets tested, but otherwise it does not.
+template<class T, class F>
+struct pointer_like_or { typedef F type; };
+template<class T, class F>
+struct pointer_like_or<T*, F> { typedef T *type; };
+template<class T, class F>
+struct pointer_like_or<T* const, F> { typedef T * const type; };
+template<class T, class F>
+struct pointer_like_or<T[], F> { typedef T type[]; };
+template<class T, class F, unsigned size>
+struct pointer_like_or<T[size], F> { typedef T type[size]; };
+
+void testVAListWithNullability(
+ pointer_like_or<va_list, void*>::type _Nonnull x); // no errors
+#endif
+
+void nestedArrays(int x[5][1]) {}
+#if ARRAYS_CHECKED
+// expected-warning@-2 {{array parameter is missing a nullability type specifier}}
+// expected-note@-3 {{insert '_Nullable' if the array parameter may be null}}
+// expected-note@-4 {{insert '_Nonnull' if the array parameter should never be null}}
+#endif
+void nestedArraysOK(int x[_Nonnull 5][1]) {}
+
+#if !__cplusplus
+void staticOK(int x[static 5][1]){}
+#endif
+
+int globalArraysDoNotNeedNullability[5];
+
+typedef int INTS[4];
+
+void typedefTest(
+ INTS x,
+#if ARRAYS_CHECKED
+// expected-warning@-2 {{array parameter is missing a nullability type specifier}}
+// expected-note@-3 {{insert '_Nullable' if the array parameter may be null}}
+// expected-note@-4 {{insert '_Nonnull' if the array parameter should never be null}}
+#endif
+ INTS _Nonnull x2,
+ _Nonnull INTS x3,
+ INTS y[2],
+#if ARRAYS_CHECKED
+// expected-warning@-2 {{array parameter is missing a nullability type specifier}}
+// expected-note@-3 {{insert '_Nullable' if the array parameter may be null}}
+// expected-note@-4 {{insert '_Nonnull' if the array parameter should never be null}}
+#endif
+ INTS y2[_Nonnull 2]);
+
+
+#pragma clang assume_nonnull begin
+void testAssumeNonnull(
+ int ints[],
+#if ARRAYS_CHECKED
+// expected-warning@-2 {{array parameter is missing a nullability type specifier}}
+// expected-note@-3 {{insert '_Nullable' if the array parameter may be null}}
+// expected-note@-4 {{insert '_Nonnull' if the array parameter should never be null}}
+#endif
+ void *ptrs[],
+#if ARRAYS_CHECKED
+// expected-warning@-2 {{array parameter is missing a nullability type specifier}}
+// expected-note@-3 {{insert '_Nullable' if the array parameter may be null}}
+// expected-note@-4 {{insert '_Nonnull' if the array parameter should never be null}}
+#endif
+ void **nestedPtrs[]); // expected-warning 2 {{pointer is missing a nullability type specifier}}
+// expected-note@-1 2 {{insert '_Nullable' if the pointer may be null}}
+// expected-note@-2 2 {{insert '_Nonnull' if the pointer should never be null}}
+#if ARRAYS_CHECKED
+// expected-warning@-4 {{array parameter is missing a nullability type specifier}}
+// expected-note@-5 {{insert '_Nullable' if the array parameter may be null}}
+// expected-note@-6 {{insert '_Nonnull' if the array parameter should never be null}}
+#endif
+
+void testAssumeNonnullAllOK(
+ int ints[_Nonnull],
+ void * _Nullable ptrs[_Nonnull],
+ void * _Nullable * _Nullable nestedPtrs[_Nonnull]);
+void testAssumeNonnullAllOK2(
+ int ints[_Nonnull],
+ void * ptrs[_Nonnull], // backwards-compatibility
+ void * _Nullable * _Nullable nestedPtrs[_Nonnull]);
+#pragma clang assume_nonnull end
diff --git a/test/SemaObjCXX/Inputs/nullability-consistency-system/nullability-consistency-system.h b/test/SemaObjCXX/Inputs/nullability-consistency-system/nullability-consistency-system.h
index 9161af1cf353..43e29e086ab0 100644
--- a/test/SemaObjCXX/Inputs/nullability-consistency-system/nullability-consistency-system.h
+++ b/test/SemaObjCXX/Inputs/nullability-consistency-system/nullability-consistency-system.h
@@ -3,6 +3,8 @@
void system1(int *ptr);
#if WARN_IN_SYSTEM_HEADERS
// expected-warning@-2{{pointer is missing a nullability type specifier}}
+// expected-note@-3 {{insert '_Nullable' if the pointer may be null}}
+// expected-note@-4 {{insert '_Nonnull' if the pointer should never be null}}
#endif
void system2(int * _Nonnull);
diff --git a/test/SemaObjCXX/Inputs/nullability-pragmas-1.h b/test/SemaObjCXX/Inputs/nullability-pragmas-1.h
index 4ac813d99618..91753ca7f3ca 100644
--- a/test/SemaObjCXX/Inputs/nullability-pragmas-1.h
+++ b/test/SemaObjCXX/Inputs/nullability-pragmas-1.h
@@ -9,6 +9,8 @@ __attribute__((objc_root_class))
struct X { };
void f1(int *x); // expected-warning{{pointer is missing a nullability type specifier}}
+// expected-note@-1{{insert '_Nullable' if the pointer may be null}}
+// expected-note@-2{{insert '_Nonnull' if the pointer should never be null}}
typedef struct __attribute__((objc_bridge(NSError))) __CFError *CFErrorRef;
typedef NSError *NSErrorPtr;
@@ -39,15 +41,29 @@ int * _Null_unspecified f15(void);
A * _Null_unspecified f16(void);
void f17(CFErrorRef *error); // expected-note{{no known conversion from 'A * _Nonnull' to 'CFErrorRef _Nullable * _Nullable' (aka '__CFError **') for 1st argument}}
void f18(A **); // expected-warning 2{{pointer is missing a nullability type specifier}}
+// expected-note@-1 2 {{insert '_Nullable' if the pointer may be null}}
+// expected-note@-2 2 {{insert '_Nonnull' if the pointer should never be null}}
void f19(CFErrorRefPtr error); // expected-warning{{pointer is missing a nullability type specifier}}
+// expected-note@-1{{insert '_Nullable' if the pointer may be null}}
+// expected-note@-2{{insert '_Nonnull' if the pointer should never be null}}
void g1(int (^)(int, int));
void g2(int (^ *bp)(int, int)); // expected-warning{{block pointer is missing a nullability type specifier}}
-// expected-warning@-1{{pointer is missing a nullability type specifier}}
+// expected-note@-1{{insert '_Nullable' if the block pointer may be null}}
+// expected-note@-2{{insert '_Nonnull' if the block pointer should never be null}}
+// expected-warning@-3{{pointer is missing a nullability type specifier}}
+// expected-note@-4{{insert '_Nullable' if the pointer may be null}}
+// expected-note@-5{{insert '_Nonnull' if the pointer should never be null}}
void g3(block_ptr *bp); // expected-warning{{block pointer is missing a nullability type specifier}}
-// expected-warning@-1{{pointer is missing a nullability type specifier}}
+// expected-note@-1{{insert '_Nullable' if the block pointer may be null}}
+// expected-note@-2{{insert '_Nonnull' if the block pointer should never be null}}
+// expected-warning@-3{{pointer is missing a nullability type specifier}}
+// expected-note@-4{{insert '_Nullable' if the pointer may be null}}
+// expected-note@-5{{insert '_Nonnull' if the pointer should never be null}}
void g4(int (*fp)(int, int));
void g5(int (**fp)(int, int)); // expected-warning 2{{pointer is missing a nullability type specifier}}
+// expected-note@-1 2 {{insert '_Nullable' if the pointer may be null}}
+// expected-note@-2 2 {{insert '_Nonnull' if the pointer should never be null}}
@interface A(Pragmas1)
+ (instancetype)aWithA:(A *)a;
@@ -57,9 +73,13 @@ void g5(int (**fp)(int, int)); // expected-warning 2{{pointer is missing a nulla
- (void)method4:(NSErrorPtr *)error; // expected-note{{passing argument to parameter 'error' here}}
- (void)method5:(NSErrorPtrPtr)error;
// expected-warning@-1{{pointer is missing a nullability type specifier}}
+// expected-note@-2{{insert '_Nullable' if the pointer may be null}}
+// expected-note@-3{{insert '_Nonnull' if the pointer should never be null}}
@property A *aProp;
@property NSError **anError; // expected-warning 2{{pointer is missing a nullability type specifier}}
+// expected-note@-1 2 {{insert '_Nullable' if the pointer may be null}}
+// expected-note@-2 2 {{insert '_Nonnull' if the pointer should never be null}}
@end
int *global_int_ptr;
@@ -68,6 +88,8 @@ int *global_int_ptr;
typedef int *int_ptr_2;
typedef int * // expected-warning{{pointer is missing a nullability type specifier}}
+// expected-note@-1{{insert '_Nullable' if the pointer may be null}}
+// expected-note@-2{{insert '_Nonnull' if the pointer should never be null}}
*int_ptr_ptr;
static inline void f30(void) {
@@ -90,12 +112,22 @@ static inline void f30(void) {
#pragma clang assume_nonnull end
void f20(A *a); // expected-warning{{pointer is missing a nullability type specifier}}
+// expected-note@-1{{insert '_Nullable' if the pointer may be null}}
+// expected-note@-2{{insert '_Nonnull' if the pointer should never be null}}
void f21(int_ptr x); // expected-warning{{pointer is missing a nullability type specifier}}
+// expected-note@-1{{insert '_Nullable' if the pointer may be null}}
+// expected-note@-2{{insert '_Nonnull' if the pointer should never be null}}
void f22(A_ptr y); // expected-warning{{pointer is missing a nullability type specifier}}
+// expected-note@-1{{insert '_Nullable' if the pointer may be null}}
+// expected-note@-2{{insert '_Nonnull' if the pointer should never be null}}
void f23(int_ptr _Nullable x);
void f24(A_ptr _Nullable y);
void f25(int_ptr_2 x); // expected-warning{{pointer is missing a nullability type specifier}}
+// expected-note@-1{{insert '_Nullable' if the pointer may be null}}
+// expected-note@-2{{insert '_Nonnull' if the pointer should never be null}}
@interface A(OutsidePragmas1)
+ (instancetype)aWithInt:(int)value; // expected-warning{{pointer is missing a nullability type specifier}}
+// expected-note@-1{{insert '_Nullable' if the pointer may be null}}
+// expected-note@-2{{insert '_Nonnull' if the pointer should never be null}}
@end
diff --git a/test/SemaObjCXX/crash.mm b/test/SemaObjCXX/crash.mm
index 19cf3099828a..a9754b7bc540 100644
--- a/test/SemaObjCXX/crash.mm
+++ b/test/SemaObjCXX/crash.mm
@@ -25,3 +25,38 @@ template<typename...Ts> void f(Ts); // expected-error {{unexpanded}}
// expected-warning@-2 {{variadic templates are a C++11 extension}}
#endif
@end
+
+// rdar://20560175
+
+struct OuterType {
+ typedef int InnerType;
+};
+
+namespace ns {
+ typedef int InnerType;
+};
+
+@protocol InvalidProperties
+
+@property (nonatomic) (OuterType::InnerType) invalidTypeParens;
+// expected-error@-1 {{type name requires a specifier or qualifier}}
+// expected-error@-2 {{property requires fields to be named}}
+// expected-error@-3 {{expected ';' at end of declaration list}}
+// expected-error@-4 {{C++ requires a type specifier for all declarations}}
+// expected-error@-5 {{cannot declare variable inside @interface or @protocol}}
+
+@property (nonatomic) (ns::InnerType) invalidTypeParens2;
+// expected-error@-1 {{type name requires a specifier or qualifier}}
+// expected-error@-2 {{property requires fields to be named}}
+// expected-error@-3 {{expected ';' at end of declaration list}}
+// expected-error@-4 {{C++ requires a type specifier for all declarations}}
+// expected-error@-5 {{cannot declare variable inside @interface or @protocol}}
+
+@property (nonatomic) int OuterType::InnerType; // expected-error {{property requires fields to be named}}
+
+@property (nonatomic) int OuterType::InnerType foo; // expected-error {{property requires fields to be named}}
+// expected-error@-1 {{expected ';' at end of declaration list}}
+// expected-error@-2 {{C++ requires a type specifier for all declarations}}
+// expected-error@-3 {{cannot declare variable inside @interface or @protocol}}
+
+@end
diff --git a/test/SemaObjCXX/null_objc_pointer.mm b/test/SemaObjCXX/null_objc_pointer.mm
index e0232bf3c872..2be397e31ee9 100644
--- a/test/SemaObjCXX/null_objc_pointer.mm
+++ b/test/SemaObjCXX/null_objc_pointer.mm
@@ -1,5 +1,4 @@
// RUN: %clang_cc1 -fsyntax-only -verify -Wnull-arithmetic %s
-// expected-no-diagnostics
#define NULL __null
@interface X
@@ -8,7 +7,7 @@
void f() {
bool b;
X *d;
- b = d < NULL || NULL < d || d > NULL || NULL > d;
- b = d <= NULL || NULL <= d || d >= NULL || NULL >= d;
+ b = d < NULL || NULL < d || d > NULL || NULL > d; // expected-error 4{{ordered comparison between pointer and zero}}
+ b = d <= NULL || NULL <= d || d >= NULL || NULL >= d; // expected-error 4{{ordered comparison between pointer and zero}}
b = d == NULL || NULL == d || d != NULL || NULL != d;
}
diff --git a/test/SemaObjCXX/nullability-consistency-arrays.mm b/test/SemaObjCXX/nullability-consistency-arrays.mm
new file mode 100644
index 000000000000..dc17ce841587
--- /dev/null
+++ b/test/SemaObjCXX/nullability-consistency-arrays.mm
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -fsyntax-only -fblocks -I %S/Inputs -Wno-nullability-inferred-on-nested-type %s -D ARRAYS_CHECKED=1 -verify
+// RUN: %clang_cc1 -fsyntax-only -fblocks -I %S/Inputs -Wno-nullability-inferred-on-nested-type %s -D ARRAYS_CHECKED=0 -Wno-nullability-completeness-on-arrays -verify
+// RUN: %clang_cc1 -fsyntax-only -fblocks -I %S/Inputs -Wno-nullability-inferred-on-nested-type %s -Wno-nullability-completeness -Werror
+// RUN: %clang_cc1 -fsyntax-only -fblocks -I %S/Inputs -Wno-nullability-inferred-on-nested-type -x objective-c %s -D ARRAYS_CHECKED=1 -verify
+// RUN: %clang_cc1 -fsyntax-only -fblocks -I %S/Inputs -Wno-nullability-inferred-on-nested-type -x objective-c %s -D ARRAYS_CHECKED=0 -Wno-nullability-completeness-on-arrays -verify
+// RUN: %clang_cc1 -fsyntax-only -fblocks -I %S/Inputs -Wno-nullability-inferred-on-nested-type -x objective-c %s -Wno-nullability-completeness -Werror
+
+#include "nullability-consistency-arrays.h"
+
+void h1(int *ptr) { } // don't warn
+
+void h2(int * _Nonnull p) { }
diff --git a/test/SemaOpenCL/access-qualifier.cl b/test/SemaOpenCL/access-qualifier.cl
index 7e5c70f915f6..7bc974109f3c 100644
--- a/test/SemaOpenCL/access-qualifier.cl
+++ b/test/SemaOpenCL/access-qualifier.cl
@@ -63,7 +63,14 @@ kernel void k11(read_only write_only image1d_t i){} // expected-error{{multiple
kernel void k12(read_only read_only image1d_t i){} // expected-error{{multiple access qualifiers}}
#if __OPENCL_C_VERSION__ >= 200
-kernel void k13(read_write pipe int i){} // expected-error{{access qualifier 'read_write' can not be used for 'pipe int'}}
+kernel void k13(read_write pipe int i){} // expected-error{{access qualifier 'read_write' can not be used for 'read_only pipe int'}}
#else
kernel void k13(__read_write image1d_t i){} // expected-error{{access qualifier '__read_write' can not be used for '__read_write image1d_t' prior to OpenCL version 2.0}}
#endif
+
+#if __OPENCL_C_VERSION__ >= 200
+void myPipeWrite(write_only pipe int); // expected-note {{passing argument to parameter here}}
+kernel void k14(read_only pipe int p) {
+ myPipeWrite(p); // expected-error {{passing 'read_only pipe int' to parameter of incompatible type 'write_only pipe int'}}
+}
+#endif
diff --git a/test/SemaOpenCL/amdgpu-attrs.cl b/test/SemaOpenCL/amdgpu-attrs.cl
new file mode 100644
index 000000000000..1ba04acd0afc
--- /dev/null
+++ b/test/SemaOpenCL/amdgpu-attrs.cl
@@ -0,0 +1,66 @@
+// RUN: %clang_cc1 -triple amdgcn-- -verify -fsyntax-only %s
+
+typedef __attribute__((amdgpu_flat_work_group_size(32, 64))) struct struct_flat_work_group_size_32_64 { // expected-error {{'amdgpu_flat_work_group_size' attribute only applies to kernel functions}}
+ int x;
+ float y;
+} struct_flat_work_group_size_32_64;
+typedef __attribute__((amdgpu_waves_per_eu(2))) struct struct_waves_per_eu_2 { // expected-error {{'amdgpu_waves_per_eu' attribute only applies to kernel functions}}
+ int x;
+ float y;
+} struct_waves_per_eu_2;
+typedef __attribute__((amdgpu_waves_per_eu(2, 4))) struct struct_waves_per_eu_2_4 { // expected-error {{'amdgpu_waves_per_eu' attribute only applies to kernel functions}}
+ int x;
+ float y;
+} struct_waves_per_eu_2_4;
+typedef __attribute__((amdgpu_num_sgpr(32))) struct struct_num_sgpr_32 { // expected-error {{'amdgpu_num_sgpr' attribute only applies to kernel functions}}
+ int x;
+ float y;
+} struct_num_sgpr_32;
+typedef __attribute__((amdgpu_num_vgpr(64))) struct struct_num_vgpr_64 { // expected-error {{'amdgpu_num_vgpr' attribute only applies to kernel functions}}
+ int x;
+ float y;
+} struct_num_vgpr_64;
+
+__attribute__((amdgpu_flat_work_group_size(32, 64))) void func_flat_work_group_size_32_64() {} // expected-error {{'amdgpu_flat_work_group_size' attribute only applies to kernel functions}}
+__attribute__((amdgpu_waves_per_eu(2))) void func_waves_per_eu_2() {} // expected-error {{'amdgpu_waves_per_eu' attribute only applies to kernel functions}}
+__attribute__((amdgpu_waves_per_eu(2, 4))) void func_waves_per_eu_2_4() {} // expected-error {{'amdgpu_waves_per_eu' attribute only applies to kernel functions}}
+__attribute__((amdgpu_num_sgpr(32))) void func_num_sgpr_32() {} // expected-error {{'amdgpu_num_sgpr' attribute only applies to kernel functions}}
+__attribute__((amdgpu_num_vgpr(64))) void func_num_vgpr_64() {} // expected-error {{'amdgpu_num_vgpr' attribute only applies to kernel functions}}
+
+__attribute__((amdgpu_flat_work_group_size("ABC", "ABC"))) kernel void kernel_flat_work_group_size_ABC_ABC() {} // expected-error {{'amdgpu_flat_work_group_size' attribute requires an integer constant}}
+__attribute__((amdgpu_flat_work_group_size(32, "ABC"))) kernel void kernel_flat_work_group_size_32_ABC() {} // expected-error {{'amdgpu_flat_work_group_size' attribute requires an integer constant}}
+__attribute__((amdgpu_flat_work_group_size("ABC", 64))) kernel void kernel_flat_work_group_size_ABC_64() {} // expected-error {{'amdgpu_flat_work_group_size' attribute requires an integer constant}}
+__attribute__((amdgpu_waves_per_eu("ABC"))) kernel void kernel_waves_per_eu_ABC() {} // expected-error {{'amdgpu_waves_per_eu' attribute requires an integer constant}}
+__attribute__((amdgpu_waves_per_eu(2, "ABC"))) kernel void kernel_waves_per_eu_2_ABC() {} // expected-error {{'amdgpu_waves_per_eu' attribute requires an integer constant}}
+__attribute__((amdgpu_waves_per_eu("ABC", 4))) kernel void kernel_waves_per_eu_ABC_4() {} // expected-error {{'amdgpu_waves_per_eu' attribute requires an integer constant}}
+__attribute__((amdgpu_num_sgpr("ABC"))) kernel void kernel_num_sgpr_ABC() {} // expected-error {{'amdgpu_num_sgpr' attribute requires an integer constant}}
+__attribute__((amdgpu_num_vgpr("ABC"))) kernel void kernel_num_vgpr_ABC() {} // expected-error {{'amdgpu_num_vgpr' attribute requires an integer constant}}
+
+__attribute__((amdgpu_flat_work_group_size(4294967296, 4294967296))) kernel void kernel_flat_work_group_size_L_L() {} // expected-error {{integer constant expression evaluates to value 4294967296 that cannot be represented in a 32-bit unsigned integer type}}
+__attribute__((amdgpu_flat_work_group_size(32, 4294967296))) kernel void kernel_flat_work_group_size_32_L() {} // expected-error {{integer constant expression evaluates to value 4294967296 that cannot be represented in a 32-bit unsigned integer type}}
+__attribute__((amdgpu_flat_work_group_size(4294967296, 64))) kernel void kernel_flat_work_group_size_L_64() {} // expected-error {{integer constant expression evaluates to value 4294967296 that cannot be represented in a 32-bit unsigned integer type}}
+__attribute__((amdgpu_waves_per_eu(4294967296))) kernel void kernel_waves_per_eu_L() {} // expected-error {{integer constant expression evaluates to value 4294967296 that cannot be represented in a 32-bit unsigned integer type}}
+__attribute__((amdgpu_waves_per_eu(2, 4294967296))) kernel void kernel_waves_per_eu_2_L() {} // expected-error {{integer constant expression evaluates to value 4294967296 that cannot be represented in a 32-bit unsigned integer type}}
+__attribute__((amdgpu_waves_per_eu(4294967296, 4))) kernel void kernel_waves_per_eu_L_4() {} // expected-error {{integer constant expression evaluates to value 4294967296 that cannot be represented in a 32-bit unsigned integer type}}
+__attribute__((amdgpu_num_sgpr(4294967296))) kernel void kernel_num_sgpr_L() {} // expected-error {{integer constant expression evaluates to value 4294967296 that cannot be represented in a 32-bit unsigned integer type}}
+__attribute__((amdgpu_num_vgpr(4294967296))) kernel void kernel_num_vgpr_L() {} // expected-error {{integer constant expression evaluates to value 4294967296 that cannot be represented in a 32-bit unsigned integer type}}
+
+__attribute__((amdgpu_flat_work_group_size(0, 64))) kernel void kernel_flat_work_group_size_0_64() {} // expected-error {{'amdgpu_flat_work_group_size' attribute argument is invalid: max must be 0 since min is 0}}
+__attribute__((amdgpu_waves_per_eu(0, 4))) kernel void kernel_waves_per_eu_0_4() {} // expected-error {{'amdgpu_waves_per_eu' attribute argument is invalid: max must be 0 since min is 0}}
+
+__attribute__((amdgpu_flat_work_group_size(64, 32))) kernel void kernel_flat_work_group_size_64_32() {} // expected-error {{'amdgpu_flat_work_group_size' attribute argument is invalid: min must not be greater than max}}
+__attribute__((amdgpu_waves_per_eu(4, 2))) kernel void kernel_waves_per_eu_4_2() {} // expected-error {{'amdgpu_waves_per_eu' attribute argument is invalid: min must not be greater than max}}
+
+__attribute__((amdgpu_waves_per_eu(2, 4, 8))) kernel void kernel_waves_per_eu_2_4_8() {} // expected-error {{'amdgpu_waves_per_eu' attribute takes no more than 2 arguments}}
+
+__attribute__((amdgpu_flat_work_group_size(0, 0))) kernel void kernel_flat_work_group_size_0_0() {}
+__attribute__((amdgpu_waves_per_eu(0))) kernel void kernel_waves_per_eu_0() {}
+__attribute__((amdgpu_waves_per_eu(0, 0))) kernel void kernel_waves_per_eu_0_0() {}
+__attribute__((amdgpu_num_sgpr(0))) kernel void kernel_num_sgpr_0() {}
+__attribute__((amdgpu_num_vgpr(0))) kernel void kernel_num_vgpr_0() {}
+
+kernel __attribute__((amdgpu_flat_work_group_size(32, 64))) void kernel_flat_work_group_size_32_64() {}
+kernel __attribute__((amdgpu_waves_per_eu(2))) void kernel_waves_per_eu_2() {}
+kernel __attribute__((amdgpu_waves_per_eu(2, 4))) void kernel_waves_per_eu_2_4() {}
+kernel __attribute__((amdgpu_num_sgpr(32))) void kernel_num_sgpr_32() {}
+kernel __attribute__((amdgpu_num_vgpr(64))) void kernel_num_vgpr_64() {}
diff --git a/test/SemaOpenCL/amdgpu-num-register-attrs.cl b/test/SemaOpenCL/amdgpu-num-register-attrs.cl
deleted file mode 100644
index ec8f8c072a23..000000000000
--- a/test/SemaOpenCL/amdgpu-num-register-attrs.cl
+++ /dev/null
@@ -1,40 +0,0 @@
-// RUN: %clang_cc1 -triple r600-- -verify -fsyntax-only %s
-
-typedef __attribute__((amdgpu_num_vgpr(128))) struct FooStruct { // expected-error {{'amdgpu_num_vgpr' attribute only applies to kernel functions}}
- int x;
- float y;
-} FooStruct;
-
-
-__attribute__((amdgpu_num_vgpr("ABC"))) kernel void foo2() {} // expected-error {{'amdgpu_num_vgpr' attribute requires an integer constant}}
-__attribute__((amdgpu_num_sgpr("ABC"))) kernel void foo3() {} // expected-error {{'amdgpu_num_sgpr' attribute requires an integer constant}}
-
-
-__attribute__((amdgpu_num_vgpr(40))) void foo4() {} // expected-error {{'amdgpu_num_vgpr' attribute only applies to kernel functions}}
-__attribute__((amdgpu_num_sgpr(64))) void foo5() {} // expected-error {{'amdgpu_num_sgpr' attribute only applies to kernel functions}}
-
-__attribute__((amdgpu_num_vgpr(40))) kernel void foo7() {}
-__attribute__((amdgpu_num_sgpr(64))) kernel void foo8() {}
-__attribute__((amdgpu_num_vgpr(40), amdgpu_num_sgpr(64))) kernel void foo9() {}
-
-// Check 0 VGPR is accepted.
-__attribute__((amdgpu_num_vgpr(0))) kernel void foo10() {}
-
-// Check 0 SGPR is accepted.
-__attribute__((amdgpu_num_sgpr(0))) kernel void foo11() {}
-
-// Check both 0 SGPR and VGPR is accepted.
-__attribute__((amdgpu_num_vgpr(0), amdgpu_num_sgpr(0))) kernel void foo12() {}
-
-// Too large VGPR value.
-__attribute__((amdgpu_num_vgpr(4294967296))) kernel void foo13() {} // expected-error {{integer constant expression evaluates to value 4294967296 that cannot be represented in a 32-bit unsigned integer type}}
-
-__attribute__((amdgpu_num_sgpr(4294967296))) kernel void foo14() {} // expected-error {{integer constant expression evaluates to value 4294967296 that cannot be represented in a 32-bit unsigned integer type}}
-
-__attribute__((amdgpu_num_sgpr(4294967296), amdgpu_num_vgpr(4294967296))) kernel void foo15() {} // expected-error 2 {{integer constant expression evaluates to value 4294967296 that cannot be represented in a 32-bit unsigned integer type}}
-
-
-// Make sure it is accepted with kernel keyword before the attribute.
-kernel __attribute__((amdgpu_num_vgpr(40))) void foo16() {}
-
-kernel __attribute__((amdgpu_num_sgpr(40))) void foo17() {}
diff --git a/test/SemaOpenCL/builtin.cl b/test/SemaOpenCL/builtin.cl
index d48a0c449591..c4d3a2399fe3 100644
--- a/test/SemaOpenCL/builtin.cl
+++ b/test/SemaOpenCL/builtin.cl
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only
+// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL1.2
// expected-no-diagnostics
diff --git a/test/SemaOpenCL/builtins-amdgcn-error-f16.cl b/test/SemaOpenCL/builtins-amdgcn-error-f16.cl
new file mode 100644
index 000000000000..7fa47179cb71
--- /dev/null
+++ b/test/SemaOpenCL/builtins-amdgcn-error-f16.cl
@@ -0,0 +1,18 @@
+// REQUIRES: amdgpu-registered-target
+// RUN: %clang_cc1 -triple amdgcn-- -target-cpu tahiti -verify -S -o - %s
+
+#pragma OPENCL EXTENSION cl_khr_fp16 : enable
+
+void test_f16(global half *out, half a, half b, half c)
+{
+ *out = __builtin_amdgcn_div_fixuph(a, b, c); // expected-error {{'__builtin_amdgcn_div_fixuph' needs target feature 16-bit-insts}}
+ *out = __builtin_amdgcn_rcph(a); // expected-error {{'__builtin_amdgcn_rcph' needs target feature 16-bit-insts}}
+ *out = __builtin_amdgcn_rsqh(a); // expected-error {{'__builtin_amdgcn_rsqh' needs target feature 16-bit-insts}}
+ *out = __builtin_amdgcn_sinh(a); // expected-error {{'__builtin_amdgcn_sinh' needs target feature 16-bit-insts}}
+ *out = __builtin_amdgcn_cosh(a); // expected-error {{'__builtin_amdgcn_cosh' needs target feature 16-bit-insts}}
+ *out = __builtin_amdgcn_ldexph(a, b); // expected-error {{'__builtin_amdgcn_ldexph' needs target feature 16-bit-insts}}
+ *out = __builtin_amdgcn_frexp_manth(a); // expected-error {{'__builtin_amdgcn_frexp_manth' needs target feature 16-bit-insts}}
+ *out = __builtin_amdgcn_frexp_exph(a); // expected-error {{'__builtin_amdgcn_frexp_exph' needs target feature 16-bit-insts}}
+ *out = __builtin_amdgcn_fracth(a); // expected-error {{'__builtin_amdgcn_fracth' needs target feature 16-bit-insts}}
+ *out = __builtin_amdgcn_classh(a, b); // expected-error {{'__builtin_amdgcn_classh' needs target feature 16-bit-insts}}
+}
diff --git a/test/SemaOpenCL/builtins-amdgcn-error.cl b/test/SemaOpenCL/builtins-amdgcn-error.cl
new file mode 100644
index 000000000000..83ccbefddc6f
--- /dev/null
+++ b/test/SemaOpenCL/builtins-amdgcn-error.cl
@@ -0,0 +1,64 @@
+// REQUIRES: amdgpu-registered-target
+// RUN: %clang_cc1 -triple amdgcn-- -target-cpu tahiti -verify -S -o - %s
+
+// FIXME: We only get one error if the functions are the other order in the
+// file.
+
+#pragma OPENCL EXTENSION cl_khr_fp64 : enable
+typedef unsigned long ulong;
+typedef unsigned int uint;
+
+ulong test_s_memrealtime()
+{
+ return __builtin_amdgcn_s_memrealtime(); // expected-error {{'__builtin_amdgcn_s_memrealtime' needs target feature s-memrealtime}}
+}
+
+void test_s_sleep(int x)
+{
+ __builtin_amdgcn_s_sleep(x); // expected-error {{argument to '__builtin_amdgcn_s_sleep' must be a constant integer}}
+}
+
+void test_s_incperflevel(int x)
+{
+ __builtin_amdgcn_s_incperflevel(x); // expected-error {{argument to '__builtin_amdgcn_s_incperflevel' must be a constant integer}}
+}
+
+void test_s_decperflevel(int x)
+{
+ __builtin_amdgcn_s_decperflevel(x); // expected-error {{argument to '__builtin_amdgcn_s_decperflevel' must be a constant integer}}
+}
+
+void test_sicmp_i32(global ulong* out, int a, int b, uint c)
+{
+ *out = __builtin_amdgcn_sicmp(a, b, c); // expected-error {{argument to '__builtin_amdgcn_sicmp' must be a constant integer}}
+}
+
+void test_uicmp_i32(global ulong* out, uint a, uint b, uint c)
+{
+ *out = __builtin_amdgcn_uicmp(a, b, c); // expected-error {{argument to '__builtin_amdgcn_uicmp' must be a constant integer}}
+}
+
+void test_sicmp_i64(global ulong* out, long a, long b, uint c)
+{
+ *out = __builtin_amdgcn_sicmpl(a, b, c); // expected-error {{argument to '__builtin_amdgcn_sicmpl' must be a constant integer}}
+}
+
+void test_uicmp_i64(global ulong* out, ulong a, ulong b, uint c)
+{
+ *out = __builtin_amdgcn_uicmpl(a, b, c); // expected-error {{argument to '__builtin_amdgcn_uicmpl' must be a constant integer}}
+}
+
+void test_fcmp_f32(global ulong* out, float a, float b, uint c)
+{
+ *out = __builtin_amdgcn_fcmpf(a, b, c); // expected-error {{argument to '__builtin_amdgcn_fcmpf' must be a constant integer}}
+}
+
+void test_fcmp_f64(global ulong* out, double a, double b, uint c)
+{
+ *out = __builtin_amdgcn_fcmp(a, b, c); // expected-error {{argument to '__builtin_amdgcn_fcmp' must be a constant integer}}
+}
+
+void test_ds_swizzle(global int* out, int a, int b)
+{
+ *out = __builtin_amdgcn_ds_swizzle(a, b); // expected-error {{argument to '__builtin_amdgcn_ds_swizzle' must be a constant integer}}
+}
diff --git a/test/SemaOpenCL/cl20-device-side-enqueue.cl b/test/SemaOpenCL/cl20-device-side-enqueue.cl
index 298b8109881d..c98145c2c900 100644
--- a/test/SemaOpenCL/cl20-device-side-enqueue.cl
+++ b/test/SemaOpenCL/cl20-device-side-enqueue.cl
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 %s -cl-std=CL2.0 -verify -pedantic -fsyntax-only
-// RUN: %clang_cc1 %s -cl-std=CL2.0 -verify -pedantic -fsyntax-only -Wconversion -DWCONV
+// RUN: %clang_cc1 %s -cl-std=CL2.0 -triple "spir-unknown-unknown" -verify -pedantic -fsyntax-only -DB32
+// RUN: %clang_cc1 %s -cl-std=CL2.0 -triple "spir64-unknown-unknown" -verify -pedantic -fsyntax-only -Wconversion -DWCONV
// Diagnostic tests for different overloads of enqueue_kernel from Table 6.13.17.1 of OpenCL 2.0 Spec.
kernel void enqueue_kernel_tests() {
@@ -36,6 +36,14 @@ kernel void enqueue_kernel_tests() {
// Testing the second overload type
enqueue_kernel(default_queue, flags, ndrange, 1, &event_wait_list, &evt, ^(void) {
+ return 0;
+ });
+
+ enqueue_kernel(default_queue, flags, ndrange, 1, 0, 0, ^(void) {
+ return 0;
+ });
+
+ enqueue_kernel(default_queue, flags, ndrange, vptr, &event_wait_list, &evt, ^(void) { // expected-error{{illegal call to enqueue_kernel, expected integer argument type}}
return 0;
});
@@ -62,16 +70,35 @@ kernel void enqueue_kernel_tests() {
^(local void *a, local void *b) {
return 0;
},
- 1024, 1024L); // expected-error{{local memory sizes need to be specified as uint}}
+ 1024L, 1024);
+
+ enqueue_kernel(default_queue, flags, ndrange,
+ ^(local void *a, local void *b) {
+ return 0;
+ },
+ 1024, 4294967296L);
+#ifdef B32
+// expected-warning@-2{{implicit conversion from 'long' to 'unsigned int' changes value from 4294967296 to 0}}
+#endif
char c;
enqueue_kernel(default_queue, flags, ndrange,
^(local void *a, local void *b) {
return 0;
},
- c, 1024);
+ c, 1024L);
#ifdef WCONV
-// expected-warning@-2{{implicit conversion changes signedness: 'char' to 'unsigned int'}}
+// expected-warning-re@-2{{implicit conversion changes signedness: 'char' to 'unsigned {{int|long}}'}}
+#endif
+#define UINT_MAX 4294967295
+
+ enqueue_kernel(default_queue, flags, ndrange,
+ ^(local void *a, local void *b) {
+ return 0;
+ },
+ sizeof(int), sizeof(int) * UINT_MAX);
+#ifdef B32
+// expected-warning@-2{{implicit conversion from 'long' to 'unsigned int' changes value from 17179869180 to 4294967292}}
#endif
typedef void (^bl_A_t)(local void *);
@@ -97,10 +124,13 @@ kernel void enqueue_kernel_tests() {
^(local void *a, local void *b) {
return 0;
},
- illegal_mem_size, illegal_mem_size); // expected-error{{local memory sizes need to be specified as uint}} expected-error{{local memory sizes need to be specified as uint}}
-#ifdef WCONV
-// expected-warning@-2{{implicit conversion turns floating-point number into integer: 'float' to 'unsigned int'}} expected-warning@-2{{implicit conversion turns floating-point number into integer: 'float' to 'unsigned int'}}
-#endif
+ illegal_mem_size, illegal_mem_size); // expected-error{{illegal call to enqueue_kernel, parameter needs to be specified as integer type}} expected-error{{illegal call to enqueue_kernel, parameter needs to be specified as integer type}}
+
+ enqueue_kernel(default_queue, flags, ndrange,
+ ^(local void *a, local void *b) {
+ return 0;
+ },
+ illegal_mem_size, 1024); // expected-error{{illegal call to enqueue_kernel, parameter needs to be specified as integer type}}
// Testing the forth overload type
enqueue_kernel(default_queue, flags, ndrange, 1, event_wait_list2, &evt,
@@ -109,6 +139,12 @@ kernel void enqueue_kernel_tests() {
},
1024, 1024);
+ enqueue_kernel(default_queue, flags, ndrange, 1, 0, 0,
+ ^(local void *a, local void *b) {
+ return 0;
+ },
+ 1024, 1024);
+
enqueue_kernel(default_queue, flags, ndrange, 1, &event_wait_list, &evt, // expected-error{{mismatch in number of block parameters and local size arguments passed}}
^(local void *a, local void *b) {
return 0;
diff --git a/test/SemaOpenCL/convergent.cl b/test/SemaOpenCL/convergent.cl
new file mode 100644
index 000000000000..1b7fda41fc0c
--- /dev/null
+++ b/test/SemaOpenCL/convergent.cl
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -triple spir-unknown-unknown -fsyntax-only -verify %s
+
+void f1(void) __attribute__((convergent));
+
+void f2(void) __attribute__((convergent(1))); // expected-error {{'convergent' attribute takes no arguments}}
+
+void f3(int a __attribute__((convergent))); // expected-warning {{'convergent' attribute only applies to functions}}
+
+void f4(void) {
+ int var1 __attribute__((convergent)); // expected-warning {{'convergent' attribute only applies to functions}}
+}
+
diff --git a/test/SemaOpenCL/event_t.cl b/test/SemaOpenCL/event_t.cl
index 990c06340942..e7daf88576cc 100644
--- a/test/SemaOpenCL/event_t.cl
+++ b/test/SemaOpenCL/event_t.cl
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only
-event_t glb_evt; // expected-error {{the event_t type cannot be used to declare a program scope variable}}
+event_t glb_evt; // expected-error {{the 'event_t' type cannot be used to declare a program scope variable}}
constant struct evt_s {
event_t evt; // expected-error {{the 'event_t' type cannot be used to declare a structure or union field}}
diff --git a/test/SemaOpenCL/event_t_overload.cl b/test/SemaOpenCL/event_t_overload.cl
index bc3ec44bd297..0bc67c13c72d 100644
--- a/test/SemaOpenCL/event_t_overload.cl
+++ b/test/SemaOpenCL/event_t_overload.cl
@@ -1,11 +1,11 @@
// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only
-void __attribute__((overloadable)) foo(event_t, __local char *); // expected-note {{candidate function not viable: no known conversion from '__global int *' to '__local char *' for 2nd argument}}
-void __attribute__((overloadable)) foo(event_t, __local float *); // expected-note {{candidate function not viable: no known conversion from '__global int *' to '__local float *' for 2nd argument}}
+void __attribute__((overloadable)) foo(event_t, __local char *); // expected-note {{candidate function}}
+void __attribute__((overloadable)) foo(event_t, __local float *); // expected-note {{candidate function}}
void kernel ker(__local char *src1, __local float *src2, __global int *src3) {
event_t evt;
foo(evt, src1);
foo(0, src2);
- foo(evt, src3); // expected-error {{no matching function for call to 'foo'}}
+ foo(evt, src3); // expected-error {{call to 'foo' is ambiguous}}
}
diff --git a/test/SemaOpenCL/ext_vectors.cl b/test/SemaOpenCL/ext_vectors.cl
new file mode 100644
index 000000000000..3b2dd6d719d6
--- /dev/null
+++ b/test/SemaOpenCL/ext_vectors.cl
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL1.1
+// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL2.0
+
+typedef float float4 __attribute__((ext_vector_type(4)));
+
+void test_ext_vector_accessors(float4 V) {
+ V = V.wzyx;
+ V = V.abgr; // expected-warning {{vector component name 'a' is an OpenCL version 2.2 feature}}
+ V = V.xyzr; // expected-warning {{vector component name 'r' is an OpenCL version 2.2 feature}} \
+ // expected-error {{illegal vector component name 'r'}}
+}
diff --git a/test/SemaOpenCL/extension-begin.cl b/test/SemaOpenCL/extension-begin.cl
new file mode 100644
index 000000000000..3393458a893a
--- /dev/null
+++ b/test/SemaOpenCL/extension-begin.cl
@@ -0,0 +1,56 @@
+// Test this without pch.
+// RUN: %clang_cc1 %s -DHEADER -DHEADER_USER -triple spir-unknown-unknown -verify -pedantic -fsyntax-only
+
+// Test with pch.
+// RUN: %clang_cc1 %s -DHEADER -triple spir-unknown-unknown -emit-pch -o %t -verify -pedantic
+// RUN: %clang_cc1 %s -DHEADER_USER -triple spir-unknown-unknown -include-pch %t -fsyntax-only -verify -pedantic
+
+#if defined(HEADER) && !defined(INCLUDED)
+#define INCLUDED
+
+#pragma OPENCL EXTENSION all : begin // expected-warning {{expected 'disable' - ignoring}}
+#pragma OPENCL EXTENSION all : end // expected-warning {{expected 'disable' - ignoring}}
+
+#pragma OPENCL EXTENSION my_ext : begin
+
+struct A {
+ int a;
+};
+
+typedef struct A TypedefOfA;
+typedef const TypedefOfA* PointerOfA;
+
+void f(void);
+
+__attribute__((overloadable)) void g(long x);
+
+#pragma OPENCL EXTENSION my_ext : end
+#pragma OPENCL EXTENSION my_ext : end // expected-warning {{OpenCL extension end directive mismatches begin directive - ignoring}}
+
+__attribute__((overloadable)) void g(void);
+
+#endif // defined(HEADER) && !defined(INCLUDED)
+
+#ifdef HEADER_USER
+
+#pragma OPENCL EXTENSION my_ext : enable
+void test_f1(void) {
+ struct A test_A1;
+ f();
+ g(0);
+}
+
+#pragma OPENCL EXTENSION my_ext : disable
+void test_f2(void) {
+ struct A test_A2; // expected-error {{use of type 'struct A' requires my_ext extension to be enabled}}
+ const struct A test_A_local; // expected-error {{use of type 'struct A' requires my_ext extension to be enabled}}
+ TypedefOfA test_typedef_A; // expected-error {{use of type 'TypedefOfA' (aka 'struct A') requires my_ext extension to be enabled}}
+ PointerOfA test_A_pointer; // expected-error {{use of type 'PointerOfA' (aka 'const struct A *') requires my_ext extension to be enabled}}
+ f(); // expected-error {{use of declaration requires my_ext extension to be enabled}}
+ g(0); // expected-error {{no matching function for call to 'g'}}
+ // expected-note@-26 {{candidate disabled due to OpenCL extension}}
+ // expected-note@-22 {{candidate function not viable: requires 0 arguments, but 1 was provided}}
+}
+
+#endif // HEADER_USER
+
diff --git a/test/SemaOpenCL/extension-version.cl b/test/SemaOpenCL/extension-version.cl
index ae403aa1d193..6100346f7072 100644
--- a/test/SemaOpenCL/extension-version.cl
+++ b/test/SemaOpenCL/extension-version.cl
@@ -222,6 +222,18 @@
#pragma OPENCL EXTENSION cl_khr_egl_image: enable
#if (__OPENCL_C_VERSION__ >= 200)
+#ifndef cl_khr_mipmap_image
+#error "Missing cl_khr_mipmap_image define"
+#endif
+#else
+#ifdef cl_khr_mipmap_image
+#error "Incorrect cl_khr_mipmap_image define"
+#endif
+// expected-warning@+2{{unsupported OpenCL extension 'cl_khr_mipmap_image' - ignoring}}
+#endif
+#pragma OPENCL EXTENSION cl_khr_mipmap_image: enable
+
+#if (__OPENCL_C_VERSION__ >= 200)
#ifndef cl_khr_srgb_image_writes
#error "Missing cl_khr_srgb_image_writes define"
#endif
@@ -235,6 +247,9 @@
#error "Missing cl_khr_subgroups define"
#endif
#else
+#ifdef cl_khr_subgroups
+#error "Incorrect cl_khr_subgroups define"
+#endif
// expected-warning@+2{{unsupported OpenCL extension 'cl_khr_subgroups' - ignoring}}
#endif
#pragma OPENCL EXTENSION cl_khr_subgroups: enable
@@ -247,3 +262,14 @@
// expected-warning@+2{{unsupported OpenCL extension 'cl_khr_terminate_context' - ignoring}}
#endif
#pragma OPENCL EXTENSION cl_khr_terminate_context: enable
+
+#ifndef cl_amd_media_ops
+#error "Missing cl_amd_media_ops define"
+#endif
+#pragma OPENCL EXTENSION cl_amd_media_ops: enable
+
+#ifndef cl_amd_media_ops2
+#error "Missing cl_amd_media_ops2 define"
+#endif
+#pragma OPENCL EXTENSION cl_amd_media_ops2: enable
+
diff --git a/test/SemaOpenCL/extensions.cl b/test/SemaOpenCL/extensions.cl
index 31224e0df774..c27f3397cd79 100644
--- a/test/SemaOpenCL/extensions.cl
+++ b/test/SemaOpenCL/extensions.cl
@@ -1,19 +1,56 @@
// RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify -pedantic -fsyntax-only
// RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify -pedantic -fsyntax-only -cl-std=CL1.1
+// RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify -pedantic -fsyntax-only -cl-std=CL1.2 -DFP64
// Test with a target not supporting fp64.
-// RUN: %clang_cc1 %s -triple r600-unknown-unknown -target-cpu r600 -verify -pedantic -fsyntax-only -DNOFP64
+// RUN: %clang_cc1 %s -triple r600-unknown-unknown -target-cpu r600 -verify -pedantic -fsyntax-only -DNOFP64 -DNOFP16
+// Test with some extensions enabled or disabled by cmd-line args
+//
+// Target does not support fp64 and fp16 - override it
+// RUN: %clang_cc1 %s -triple r600-unknown-unknown -target-cpu r600 -verify -pedantic -fsyntax-only -cl-ext=+cl_khr_fp64,+cl_khr_fp16
+//
+// Disable or enable all extensions
+// RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify -pedantic -fsyntax-only -cl-ext=-all -DNOFP64 -DNOFP16
+// RUN: %clang_cc1 %s -triple r600-unknown-unknown -target-cpu r600 -verify -pedantic -fsyntax-only -cl-ext=+all
+// RUN: %clang_cc1 %s -triple r600-unknown-unknown -target-cpu r600 -verify -pedantic -fsyntax-only -cl-ext=+all,-cl_khr_fp64 -DNOFP64
+// RUN: %clang_cc1 %s -triple r600-unknown-unknown -target-cpu r600 -verify -pedantic -fsyntax-only -cl-ext=-all,+cl_khr_fp64 -DNOFP16
+//
+// Concatenating
+// RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify -pedantic -fsyntax-only -cl-ext=-cl_khr_fp64 -cl-ext=+cl_khr_fp64
+// RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify -pedantic -fsyntax-only -cl-ext=-cl_khr_fp64,+cl_khr_fp64
+// RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify -pedantic -fsyntax-only -cl-ext=-all -cl-ext=+cl_khr_fp64 -cl-ext=+cl_khr_fp16 -cl-ext=-cl_khr_fp64 -DNOFP64
+// RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify -pedantic -fsyntax-only -cl-ext=-all -cl-ext=+cl_khr_fp64,-cl_khr_fp64,+cl_khr_fp16 -DNOFP64
+
+#ifdef FP64
+// expected-no-diagnostics
+#endif
+
+#if __OPENCL_C_VERSION__ < 120
void f1(double da) { // expected-error {{type 'double' requires cl_khr_fp64 extension}}
double d; // expected-error {{type 'double' requires cl_khr_fp64 extension}}
(void) 1.0; // expected-warning {{double precision constant requires cl_khr_fp64}}
}
+#endif
+
+int isnan(float x) {
+ return __builtin_isnan(x);
+}
+
+int isfinite(float x) {
+ return __builtin_isfinite(x);
+}
#pragma OPENCL EXTENSION cl_khr_fp64 : enable
#ifdef NOFP64
// expected-warning@-2{{unsupported OpenCL extension 'cl_khr_fp64' - ignoring}}
#endif
+#pragma OPENCL EXTENSION cl_khr_fp16 : enable
+#ifdef NOFP16
+// expected-warning@-2{{unsupported OpenCL extension 'cl_khr_fp16' - ignoring}}
+#endif
+
void f2(void) {
double d;
#ifdef NOFP64
@@ -21,8 +58,9 @@ void f2(void) {
#endif
(void) 1.0;
+
#ifdef NOFP64
-// expected-warning@-2{{double precision constant requires cl_khr_fp64, casting to single precision}}
+// expected-warning@-3{{double precision constant requires cl_khr_fp64, casting to single precision}}
#endif
}
@@ -31,6 +69,8 @@ void f2(void) {
// expected-warning@-2{{unsupported OpenCL extension 'cl_khr_fp64' - ignoring}}
#endif
+#if __OPENCL_C_VERSION__ < 120
void f3(void) {
double d; // expected-error {{type 'double' requires cl_khr_fp64 extension}}
}
+#endif
diff --git a/test/SemaOpenCL/extern.cl b/test/SemaOpenCL/extern.cl
index 5f1f9f80b0fa..66efd7005836 100644
--- a/test/SemaOpenCL/extern.cl
+++ b/test/SemaOpenCL/extern.cl
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -x cl -cl-opt-disable -cl-std=CL1.2 -emit-llvm -ffake-address-space-map %s -o - -verify | FileCheck %s
// expected-no-diagnostics
-// CHECK: @foo = external addrspace(3) constant float
+// CHECK: @foo = external addrspace(2) constant float
extern constant float foo;
kernel void test(global float* buf) {
diff --git a/test/SemaOpenCL/func_ptr.cl b/test/SemaOpenCL/func.cl
index abeab73a779c..ea3bab6c514c 100644
--- a/test/SemaOpenCL/func_ptr.cl
+++ b/test/SemaOpenCL/func.cl
@@ -1,5 +1,12 @@
// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only
+// Variadic functions
+void vararg_f(int, ...); // expected-error {{invalid prototype, variadic arguments are not allowed in OpenCL}}
+void __vararg_f(int, ...);
+typedef void (*vararg_fptr_t)(int, ...); // expected-error {{invalid prototype, variadic arguments are not allowed in OpenCL}}
+int printf(__constant const char *st, ...); // expected-error {{invalid prototype, variadic arguments are not allowed in OpenCL}}
+
+//Function pointer
void foo(void*);
void bar()
diff --git a/test/SemaOpenCL/half.cl b/test/SemaOpenCL/half.cl
index dd7bb9ab8c5d..e8da3a2a2137 100644
--- a/test/SemaOpenCL/half.cl
+++ b/test/SemaOpenCL/half.cl
@@ -8,8 +8,10 @@ half half_disabled(half *p, // expected-error{{declaring function return value o
{
half a[2]; // expected-error{{declaring variable of type 'half [2]' is not allowed}}
half b; // expected-error{{declaring variable of type 'half' is not allowed}}
- *p; // expected-error{{loading directly from pointer to type 'half' is not allowed}}
- p[1]; // expected-error{{loading directly from pointer to type 'half' is not allowed}}
+ *p; // expected-error{{loading directly from pointer to type 'half' requires cl_khr_fp16. Use vector data load builtin functions instead}}
+ *p = 0; // expected-error{{assigning directly to pointer to type 'half' requires cl_khr_fp16. Use vector data store builtin functions instead}}
+ p[1]; // expected-error{{loading directly from pointer to type 'half' requires cl_khr_fp16. Use vector data load builtin functions instead}}
+ p[1] = 0; // expected-error{{assigning directly to pointer to type 'half' requires cl_khr_fp16. Use vector data store builtin functions instead}}
float c = 1.0f;
b = (half) c; // expected-error{{casting to type 'half' is not allowed}}
@@ -23,6 +25,9 @@ half half_disabled(half *p, // expected-error{{declaring function return value o
return h;
}
+kernel void half_disabled_kernel(global half *p,
+ half h); // expected-error{{declaring function parameter of type 'half' is not allowed; did you forget * ?}}
+
// Exactly the same as above but with the cl_khr_fp16 extension enabled.
#pragma OPENCL EXTENSION cl_khr_fp16 : enable
constant half a = 1.0h;
@@ -31,7 +36,9 @@ half half_enabled(half *p, half h)
half a[2];
half b;
*p;
+ *p = 0;
p[1];
+ p[1] = 0;
float c = 1.0f;
b = (half) c;
@@ -44,3 +51,7 @@ half half_enabled(half *p, half h)
return h;
}
+
+kernel void half_enabled_kernel(global half *p,
+ half h);
+
diff --git a/test/SemaOpenCL/invalid-block.cl b/test/SemaOpenCL/invalid-block.cl
index 6721d0ea234a..a9eac1c2b582 100644
--- a/test/SemaOpenCL/invalid-block.cl
+++ b/test/SemaOpenCL/invalid-block.cl
@@ -31,23 +31,30 @@ void f4() {
}
// A block with variadic argument is not allowed.
-int (^bl)(int, ...) = ^int(int I, ...) { // expected-error {{invalid block prototype, variadic arguments are not allowed in OpenCL}}
+int (^bl)(int, ...) = ^int(int I, ...) { // expected-error {{invalid prototype, variadic arguments are not allowed in OpenCL}} expected-error {{invalid prototype, variadic arguments are not allowed in OpenCL}}
return 0;
};
+typedef int (^bl1_t)(int, ...); // expected-error {{invalid prototype, variadic arguments are not allowed in OpenCL}}
// A block can't be used to declare an array
-typedef int (^bl1_t)(int);
+typedef int (^bl2_t)(int);
void f5(int i) {
- bl1_t bl1 = ^(int i) {return 1;};
- bl1_t bl2 = ^(int i) {return 2;};
- bl1_t arr[] = {bl1, bl2}; // expected-error {{array of 'bl1_t' (aka 'int (^const)(int)') type is invalid in OpenCL}}
+ bl2_t bl1 = ^(int i) {
+ return 1;
+ };
+ bl2_t bl2 = ^(int i) {
+ return 2;
+ };
+ bl2_t arr[] = {bl1, bl2}; // expected-error {{array of 'bl2_t' (aka 'int (^const)(int)') type is invalid in OpenCL}}
int tmp = i ? bl1(i) // expected-error {{block type cannot be used as expression in ternary expression in OpenCL}}
: bl2(i); // expected-error {{block type cannot be used as expression in ternary expression in OpenCL}}
}
// A block pointer type and all pointer operations are disallowed
-void f6(bl1_t * bl_ptr) { // expected-error{{pointer to type '__generic bl1_t' (aka 'int (^const __generic)(int)') is invalid in OpenCL}}
- bl1_t bl = ^(int i) {return 1;};
- bl1_t *p; // expected-error {{pointer to type '__generic bl1_t' (aka 'int (^const __generic)(int)') is invalid in OpenCL}}
- *bl; // expected-error {{invalid argument type 'bl1_t' (aka 'int (^const)(int)') to unary expression}}
- &bl; // expected-error {{invalid argument type 'bl1_t' (aka 'int (^const)(int)') to unary expression}}
+void f6(bl2_t *bl_ptr) { // expected-error{{pointer to type '__generic bl2_t' (aka 'int (^const __generic)(int)') is invalid in OpenCL}}
+ bl2_t bl = ^(int i) {
+ return 1;
+ };
+ bl2_t *p; // expected-error {{pointer to type '__generic bl2_t' (aka 'int (^const __generic)(int)') is invalid in OpenCL}}
+ *bl; // expected-error {{invalid argument type 'bl2_t' (aka 'int (^const)(int)') to unary expression}}
+ &bl; // expected-error {{invalid argument type 'bl2_t' (aka 'int (^const)(int)') to unary expression}}
}
diff --git a/test/SemaOpenCL/invalid-clk-events-cl2.0.cl b/test/SemaOpenCL/invalid-clk-events-cl2.0.cl
new file mode 100644
index 000000000000..8c8e1c617611
--- /dev/null
+++ b/test/SemaOpenCL/invalid-clk-events-cl2.0.cl
@@ -0,0 +1,3 @@
+// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL2.0
+
+global clk_event_t ce; // expected-error {{the '__global clk_event_t' type cannot be used to declare a program scope variable}}
diff --git a/test/SemaOpenCL/invalid-image.cl b/test/SemaOpenCL/invalid-image.cl
index d15746fbab91..cc7d16366350 100644
--- a/test/SemaOpenCL/invalid-image.cl
+++ b/test/SemaOpenCL/invalid-image.cl
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -verify %s
+// RUN: %clang_cc1 -verify -D=ATTR_TEST -fms-compatibility %s
void test1(image1d_t *i) {} // expected-error{{pointer to type '__read_only image1d_t' is invalid in OpenCL}}
@@ -12,3 +13,8 @@ void test2(image1d_t i) {
}
image1d_t test3() {} // expected-error{{declaring function return value of type '__read_only image1d_t' is not allowed}}
+
+#ifdef ATTR_TEST
+// Test case for an infinite loop bug.
+kernel void foob(read_only __ptr32 image2d_t i) { } // expected-error{{'__ptr32' attribute only applies to pointer arguments}}
+#endif
diff --git a/test/SemaOpenCL/invalid-kernel-parameters.cl b/test/SemaOpenCL/invalid-kernel-parameters.cl
index e2e48e83c6b9..2433c17fe022 100644
--- a/test/SemaOpenCL/invalid-kernel-parameters.cl
+++ b/test/SemaOpenCL/invalid-kernel-parameters.cl
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s -triple spir-unknown-unknown
+kernel void half_arg(half x) { } // expected-error{{declaring function parameter of type 'half' is not allowed; did you forget * ?}}
+
#pragma OPENCL EXTENSION cl_khr_fp16 : enable
@@ -11,7 +13,8 @@
kernel void bool_arg(bool x) { } // expected-error{{'bool' cannot be used as the type of a kernel parameter}}
-kernel void half_arg(half x) { } // expected-error{{'half' cannot be used as the type of a kernel parameter}}
+// half kernel argument is allowed when cl_khr_fp16 is enabled.
+kernel void half_arg(half x) { }
typedef struct ContainsBool // expected-note{{within field of type 'ContainsBool' declared here}}
{
diff --git a/test/SemaOpenCL/invalid-kernel.cl b/test/SemaOpenCL/invalid-kernel.cl
index 9a50673ecdfa..031f6061a3b9 100644
--- a/test/SemaOpenCL/invalid-kernel.cl
+++ b/test/SemaOpenCL/invalid-kernel.cl
@@ -1,10 +1,11 @@
// RUN: %clang_cc1 -verify %s
+// RUN: %clang_cc1 -cl-std=CL2.0 -verify %s
-kernel void no_ptrptr(global int **i) { } // expected-error{{kernel parameter cannot be declared as a pointer to a pointer}}
+kernel void no_ptrptr(global int * global *i) { } // expected-error{{kernel parameter cannot be declared as a pointer to a pointer}}
-__kernel void no_privateptr(__private int *i) { } // expected-error {{kernel parameter cannot be declared as a pointer to the __private address space}}
+__kernel void no_privateptr(__private int *i) { } // expected-error {{pointer arguments to kernel functions must reside in '__global', '__constant' or '__local' address space}}
-__kernel void no_privatearray(__private int i[]) { } // expected-error {{kernel parameter cannot be declared as a pointer to the __private address space}}
+__kernel void no_privatearray(__private int i[]) { } // expected-error {{pointer arguments to kernel functions must reside in '__global', '__constant' or '__local' address space}}
kernel int bar() { // expected-error {{kernel must have void return type}}
return 6;
@@ -29,3 +30,6 @@ int* local x(int* x) { // expected-error {{return value cannot be qualified with
int* constant x(int* x) { // expected-error {{return value cannot be qualified with address space}}
return x + 1;
}
+
+__kernel void testKernel(int *ptr) { // expected-error {{pointer arguments to kernel functions must reside in '__global', '__constant' or '__local' address space}}
+}
diff --git a/test/SemaOpenCL/invalid-pipes-cl2.0.cl b/test/SemaOpenCL/invalid-pipes-cl2.0.cl
index 1993df5c44d4..5db953108bef 100644
--- a/test/SemaOpenCL/invalid-pipes-cl2.0.cl
+++ b/test/SemaOpenCL/invalid-pipes-cl2.0.cl
@@ -1,5 +1,8 @@
// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL2.0
+global pipe int gp; // expected-error {{type '__global read_only pipe int' can only be used as a function parameter in OpenCL}}
+global reserve_id_t rid; // expected-error {{the '__global reserve_id_t' type cannot be used to declare a program scope variable}}
+
void test1(pipe int *p) {// expected-error {{pipes packet types cannot be of reference type}}
}
void test2(pipe p) {// expected-error {{missing actual type specifier for pipe}}
@@ -7,16 +10,30 @@ void test2(pipe p) {// expected-error {{missing actual type specifier for pipe}}
void test3(int pipe p) {// expected-error {{cannot combine with previous 'int' declaration specifier}}
}
void test4() {
- pipe int p; // expected-error {{type 'pipe int' can only be used as a function parameter}}
+ pipe int p; // expected-error {{type 'read_only pipe int' can only be used as a function parameter}}
//TODO: fix parsing of this pipe int (*p);
}
void test5(pipe int p) {
- p+p; // expected-error{{invalid operands to binary expression ('pipe int' and 'pipe int')}}
- p=p; // expected-error{{invalid operands to binary expression ('pipe int' and 'pipe int')}}
- &p; // expected-error{{invalid argument type 'pipe int' to unary expression}}
- *p; // expected-error{{invalid argument type 'pipe int' to unary expression}}
+ p+p; // expected-error{{invalid operands to binary expression ('read_only pipe int' and 'read_only pipe int')}}
+ p=p; // expected-error{{invalid operands to binary expression ('read_only pipe int' and 'read_only pipe int')}}
+ &p; // expected-error{{invalid argument type 'read_only pipe int' to unary expression}}
+ *p; // expected-error{{invalid argument type 'read_only pipe int' to unary expression}}
}
typedef pipe int pipe_int_t;
-pipe_int_t test6() {} // expected-error{{declaring function return value of type 'pipe_int_t' (aka 'pipe int') is not allowed}}
+pipe_int_t test6() {} // expected-error{{declaring function return value of type 'pipe_int_t' (aka 'read_only pipe int') is not allowed}}
+
+bool test_id_comprision(void) {
+ reserve_id_t id1, id2;
+ return (id1 == id2); // expected-error {{invalid operands to binary expression ('reserve_id_t' and 'reserve_id_t')}}
+}
+
+// Tests ASTContext::mergeTypes rejects this.
+int f(pipe int x, int y); // expected-note {{previous declaration is here}}
+int f(x, y) // expected-error {{conflicting types for 'f}}
+pipe short x;
+int y;
+{
+ return y;
+}
diff --git a/test/SemaOpenCL/null_queue.cl b/test/SemaOpenCL/null_queue.cl
new file mode 100644
index 000000000000..518f7138de6c
--- /dev/null
+++ b/test/SemaOpenCL/null_queue.cl
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 %s -cl-std=CL2.0 -verify -pedantic -fsyntax-only
+extern queue_t get_default_queue();
+
+bool compare() {
+ return 1 == get_default_queue() && // expected-error{{invalid operands to binary expression ('int' and 'queue_t')}}
+ get_default_queue() == 1; // expected-error{{invalid operands to binary expression ('queue_t' and 'int')}}
+}
+
+void init() {
+ queue_t q1 = 1; // expected-error{{initializing 'queue_t' with an expression of incompatible type 'int'}}
+ queue_t q = 0;
+}
diff --git a/test/SemaOpenCL/queue_t_overload.cl b/test/SemaOpenCL/queue_t_overload.cl
new file mode 100644
index 000000000000..0048895ac805
--- /dev/null
+++ b/test/SemaOpenCL/queue_t_overload.cl
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 %s -cl-std=CL2.0 -verify -pedantic -fsyntax-only
+
+void __attribute__((overloadable)) foo(queue_t, __local char *); // expected-note {{candidate function not viable: no known conversion from 'int' to 'queue_t' for 1st argument}} // expected-note {{candidate function}}
+void __attribute__((overloadable)) foo(queue_t, __local float *); // expected-note {{candidate function not viable: no known conversion from 'int' to 'queue_t' for 1st argument}} // expected-note {{candidate function}}
+
+void kernel ker(__local char *src1, __local float *src2, __global int *src3) {
+ queue_t q;
+ foo(q, src1);
+ foo(0, src2);
+ foo(q, src3); // expected-error {{call to 'foo' is ambiguous}}
+ foo(1, src3); // expected-error {{no matching function for call to 'foo'}}
+}
diff --git a/test/SemaOpenCL/sampler_t.cl b/test/SemaOpenCL/sampler_t.cl
index 0553db8fd662..c87b6da7c7e1 100644
--- a/test/SemaOpenCL/sampler_t.cl
+++ b/test/SemaOpenCL/sampler_t.cl
@@ -1,6 +1,34 @@
// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only
+// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -DCHECK_SAMPLER_VALUE -Wspir-compat -triple amdgcn--amdhsa
+// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -DCHECK_SAMPLER_VALUE -triple spir-unknown-unknown
-constant sampler_t glb_smp = 5;
+#define CLK_ADDRESS_CLAMP_TO_EDGE 2
+#define CLK_NORMALIZED_COORDS_TRUE 1
+#define CLK_FILTER_NEAREST 0x10
+#define CLK_FILTER_LINEAR 0x20
+
+constant sampler_t glb_smp = CLK_ADDRESS_CLAMP_TO_EDGE | CLK_NORMALIZED_COORDS_TRUE | CLK_FILTER_LINEAR;
+constant sampler_t glb_smp2; // expected-error{{variable in constant address space must be initialized}}
+global sampler_t glb_smp3 = CLK_ADDRESS_CLAMP_TO_EDGE | CLK_NORMALIZED_COORDS_TRUE | CLK_FILTER_NEAREST; // expected-error{{sampler type cannot be used with the __local and __global address space qualifiers}}
+
+constant sampler_t glb_smp4 = 0;
+#ifdef CHECK_SAMPLER_VALUE
+// expected-warning@-2{{sampler initializer has invalid Filter Mode bits}}
+#endif
+
+constant sampler_t glb_smp5 = 0x1f;
+#ifdef CHECK_SAMPLER_VALUE
+// expected-warning@-2{{sampler initializer has invalid Addressing Mode bits}}
+#endif
+
+constant sampler_t glb_smp6 = glb_smp; // expected-error{{initializer element is not a compile-time constant}}
+
+int f(void);
+constant sampler_t glb_smp7 = f(); // expected-error{{initializer element is not a compile-time constant}}
+
+constant sampler_t glb_smp8 = 1.0f; // expected-error{{initializing '__constant sampler_t' with an expression of incompatible type 'float'}}
+
+constant sampler_t glb_smp9 = 0x100000000LL; // expected-error{{sampler_t initialization requires 32-bit integer, not 'long long'}}
void foo(sampler_t);
@@ -8,24 +36,50 @@ constant struct sampler_s {
sampler_t smp; // expected-error{{the 'sampler_t' type cannot be used to declare a structure or union field}}
} sampler_str = {0};
+sampler_t bad(void); //expected-error{{declaring function return value of type 'sampler_t' is not allowed}}
+
void kernel ker(sampler_t argsmp) {
local sampler_t smp; // expected-error{{sampler type cannot be used with the __local and __global address space qualifiers}}
- const sampler_t const_smp = 7;
+ const sampler_t const_smp = CLK_ADDRESS_CLAMP_TO_EDGE | CLK_NORMALIZED_COORDS_TRUE | CLK_FILTER_LINEAR;
+ const sampler_t const_smp2;
+ const sampler_t const_smp3 = const_smp;
+ const sampler_t const_smp4 = f();
+ const sampler_t const_smp5 = 1.0f; // expected-error{{initializing 'const sampler_t' with an expression of incompatible type 'float'}}
+ const sampler_t const_smp6 = 0x100000000LL; // expected-error{{sampler_t initialization requires 32-bit integer, not 'long long'}}
+
foo(glb_smp);
+ foo(glb_smp2);
+ foo(glb_smp3);
+ foo(glb_smp4);
+ foo(glb_smp5);
+ foo(glb_smp6);
+ foo(glb_smp7);
+ foo(glb_smp8);
+ foo(glb_smp9);
+ foo(smp);
+ foo(sampler_str.smp);
foo(const_smp);
+ foo(const_smp2);
+ foo(const_smp3);
+ foo(const_smp4);
+ foo(const_smp5);
+ foo(const_smp6);
+ foo(argsmp);
foo(5); // expected-error{{sampler_t variable required - got 'int'}}
sampler_t sa[] = {argsmp, const_smp}; // expected-error {{array of 'sampler_t' type is invalid in OpenCL}}
+ foo(sa[0]);
+ foo(bad());
}
void bad(sampler_t*); // expected-error{{pointer to type 'sampler_t' is invalid in OpenCL}}
void bar() {
- sampler_t smp1 = 7;
- sampler_t smp2 = 2;
+ sampler_t smp1 = CLK_ADDRESS_CLAMP_TO_EDGE | CLK_NORMALIZED_COORDS_TRUE | CLK_FILTER_LINEAR;
+ sampler_t smp2 = CLK_ADDRESS_CLAMP_TO_EDGE | CLK_NORMALIZED_COORDS_TRUE | CLK_FILTER_NEAREST;
smp1=smp2; //expected-error{{invalid operands to binary expression ('sampler_t' and 'sampler_t')}}
smp1+1; //expected-error{{invalid operands to binary expression ('sampler_t' and 'int')}}
&smp1; //expected-error{{invalid argument type 'sampler_t' to unary expression}}
*smp2; //expected-error{{invalid argument type 'sampler_t' to unary expression}}
+ foo(smp1+1); //expected-error{{invalid operands to binary expression ('sampler_t' and 'int')}}
}
-sampler_t bad(); //expected-error{{declaring function return value of type 'sampler_t' is not allowed}}
diff --git a/test/SemaOpenCL/unroll-hint.cl b/test/SemaOpenCL/unroll-hint.cl
index 996986603695..41385c1177ca 100644
--- a/test/SemaOpenCL/unroll-hint.cl
+++ b/test/SemaOpenCL/unroll-hint.cl
@@ -1,17 +1,5 @@
-//RUN: %clang_cc1 -O0 -fsyntax-only -verify %s
-//RUN: %clang_cc1 -O0 -cl-std=CL2.0 -fsyntax-only -verify -DCL20 %s
+//RUN: %clang_cc1 -O0 -cl-std=CL2.0 -fsyntax-only -verify %s
-kernel void D (global int *x) {
- int i = 10;
-#ifndef CL20
- // expected-error@+2 {{'opencl_unroll_hint' attribute requires OpenCL version 2.0 or above}}
-#endif
- __attribute__((opencl_unroll_hint))
- do {
- } while(i--);
-}
-
-#ifdef CL20
kernel void C (global int *x) {
int I = 3;
__attribute__((opencl_unroll_hint(I))) // expected-error {{'opencl_unroll_hint' attribute requires an integer constant}}
@@ -27,4 +15,3 @@ kernel void F() {
__attribute__((opencl_unroll_hint(-1))) // expected-error {{'opencl_unroll_hint' attribute requires a positive integral compile time constant expression}}
for(int i=0; i<100; i++);
}
-#endif
diff --git a/test/SemaOpenCL/unsupported.cl b/test/SemaOpenCL/unsupported.cl
index a39a61b9542a..a5fc570e757e 100644
--- a/test/SemaOpenCL/unsupported.cl
+++ b/test/SemaOpenCL/unsupported.cl
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -verify %s
struct {
- int a : 1; // expected-error {{bitfields are not supported in OpenCL}}
+ int a : 1; // expected-error {{bit-fields are not supported in OpenCL}}
};
void no_vla(int n) {
diff --git a/test/SemaTemplate/alias-templates.cpp b/test/SemaTemplate/alias-templates.cpp
index b7078353ff1b..bcdc84e19f7e 100644
--- a/test/SemaTemplate/alias-templates.cpp
+++ b/test/SemaTemplate/alias-templates.cpp
@@ -220,6 +220,23 @@ namespace PR14858 {
template<typename ...T, typename ...U> void h(X<T...> &) {}
template<typename ...T, typename ...U> void h(X<U...> &) {} // ok, different
+
+ template<typename ...T> void i(auto (T ...t) -> int(&)[sizeof...(t)]);
+ auto mk_arr(int, int) -> int(&)[2];
+ void test_i() { i<int, int>(mk_arr); }
+
+#if 0 // FIXME: This causes clang to assert.
+ template<typename ...T> using Z = auto (T ...p) -> int (&)[sizeof...(p)];
+ template<typename ...T, typename ...U> void j(Z<T..., U...> &) {}
+ void test_j() { j<int, int>(mk_arr); }
+#endif
+
+ template<typename ...T> struct Q {
+ template<typename ...U> using V = int[sizeof...(U)];
+ template<typename ...U> void f(V<typename U::type..., typename T::type...> *);
+ };
+ struct B { typedef int type; };
+ void test_q(int (&a)[5]) { Q<B, B, B>().f<B, B>(&a); }
}
namespace redecl {
diff --git a/test/SemaTemplate/array-redeclaration.cpp b/test/SemaTemplate/array-redeclaration.cpp
new file mode 100644
index 000000000000..4edee701cfc4
--- /dev/null
+++ b/test/SemaTemplate/array-redeclaration.cpp
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+extern int array[1];
+
+template <typename>
+class C {
+ enum { D };
+public:
+ template <typename A> void foo1() {
+ extern int array[((int)C<A>::k > (int)D) ? 1 : -1];
+ }
+};
+
+template<>
+class C<int> {
+public:
+ const static int k = 2;
+};
+
+void foo2() {
+ C<char> c;
+ c.foo1<int>();
+}
+
+template<int n>
+void foo3() {
+ extern int array[n ? 1 : -1];
+}
+
+void foo4() {
+ foo3<5>();
+}
diff --git a/test/SemaTemplate/class-template-decl.cpp b/test/SemaTemplate/class-template-decl.cpp
index 63482d84df0c..2e36cae14f60 100644
--- a/test/SemaTemplate/class-template-decl.cpp
+++ b/test/SemaTemplate/class-template-decl.cpp
@@ -10,11 +10,11 @@ namespace N {
template<typename T> class C;
}
-extern "C" {
+extern "C" { // expected-note {{extern "C" language linkage specification begins here}}
template<typename T> class D; // expected-error{{templates must have C++ linkage}}
}
-extern "C" {
+extern "C" { // expected-note 2 {{extern "C" language linkage specification begins here}}
class PR17968 {
template<typename T> class D; // expected-error{{templates must have C++ linkage}}
template<typename T> void f(); // expected-error{{templates must have C++ linkage}}
@@ -148,7 +148,7 @@ namespace redecl {
}
extern "C" template <typename T> // expected-error{{templates must have C++ linkage}}
-void DontCrashOnThis() {
+void DontCrashOnThis() { // expected-note@-1 {{extern "C" language linkage specification begins here}}
T &pT = T();
pT;
}
diff --git a/test/SemaTemplate/class-template-spec.cpp b/test/SemaTemplate/class-template-spec.cpp
index 86cace19dbfb..518ec78e6f7d 100644
--- a/test/SemaTemplate/class-template-spec.cpp
+++ b/test/SemaTemplate/class-template-spec.cpp
@@ -137,12 +137,16 @@ namespace PR18009 {
A<int>::S<8, sizeof(int)> a; // ok
template <typename T> struct B {
- template <int N, int M> struct S; // expected-note {{declared here}}
- template <int N> struct S<N, sizeof(T) +
- N // expected-error {{non-type template argument depends on a template parameter of the partial specialization}}
- > {};
+ template <int N, int M> struct S;
+ template <int N> struct S<N, sizeof(T) + N> {}; // ok (dr1315)
};
- B<int>::S<8, sizeof(int) + 8> s; // expected-error {{undefined}}
+ B<int>::S<8, sizeof(int) + 8> b;
+
+ template <typename T> struct C {
+ template <int N, int M> struct S;
+ template <int N> struct S<N, N ? **(T(*)[N])0 : 0> {}; // expected-error {{depends on a template parameter of the partial specialization}}
+ };
+ C<int> c; // expected-note {{in instantiation of}}
template<int A> struct outer {
template<int B, int C> struct inner {};
@@ -167,10 +171,16 @@ namespace PR16519 {
// expected-warning@-2 {{variadic templates are a C++11 extension}}
#endif
- template<typename T, T ...N, T ...Extra> struct __make_integer_sequence_impl<integer_sequence<T, N...>, Extra...> {
+ // Note that the following seemingly-equivalent template parameter list is
+ // not OK; it would result in a partial specialization that is not more
+ // specialized than the primary template. (See NTTPTypeVsPartialOrder below.)
+ //
+ // template<typename T, T ...N, T ...Extra>
+ template<typename T, T ...N, typename integer_sequence<T, N...>::value_type ...Extra>
#if __cplusplus <= 199711L
- // expected-warning@-2 2 {{variadic templates are a C++11 extension}}
+ // expected-warning@-2 2{{variadic templates are a C++11 extension}}
#endif
+ struct __make_integer_sequence_impl<integer_sequence<T, N...>, Extra...> {
typedef integer_sequence<T, N..., sizeof...(N) + N..., Extra...> type;
};
@@ -193,13 +203,32 @@ namespace PR16519 {
#endif
}
+namespace NTTPTypeVsPartialOrder {
+ struct X { typedef int value_type; };
+ template<typename T> struct Y { typedef T value_type; };
+
+ template<typename T, typename T::value_type N> struct A; // expected-note {{template}}
+ template<int N> struct A<X, N> {};
+ template<typename T, T N> struct A<Y<T>, N> {}; // expected-error {{not more specialized}} expected-note {{'T' vs 'typename Y<type-parameter-0-0>::value_type'}}
+ A<X, 0> ax;
+ A<Y<int>, 0> ay;
+
+
+ template<int, typename T, typename T::value_type> struct B; // expected-note {{template}}
+ template<typename T, typename T::value_type N> struct B<0, T, N>; // expected-note {{matches}}
+ template<int N> struct B<0, X, N> {};
+ template<typename T, T N> struct B<0, Y<T>, N> {}; // expected-error {{not more specialized}} expected-note {{'T' vs 'typename Y<type-parameter-0-0>::value_type'}} expected-note {{matches}}
+ B<0, X, 0> bx;
+ B<0, Y<int>, 0> by; // expected-error {{ambiguous}}
+}
+
namespace DefaultArgVsPartialSpec {
// Check that the diagnostic points at the partial specialization, not just at
// the default argument.
template<typename T, int N =
- sizeof(T) // expected-note {{template parameter is used in default argument declared here}}
+ sizeof(T) // ok (dr1315)
> struct X {};
- template<typename T> struct X<T> {}; // expected-error {{non-type template argument depends on a template parameter of the partial specialization}}
+ template<typename T> struct X<T> {};
template<typename T,
T N = 0 // expected-note {{template parameter is declared here}}
diff --git a/test/SemaTemplate/cxx1z-decomposition.cpp b/test/SemaTemplate/cxx1z-decomposition.cpp
new file mode 100644
index 000000000000..779c4cf75e9d
--- /dev/null
+++ b/test/SemaTemplate/cxx1z-decomposition.cpp
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -std=c++1z -verify %s
+
+struct A { int x, y; };
+typedef int B[2];
+struct C { template<int> int get(); };
+struct D { int x, y, z; };
+struct E { int *p, n; };
+
+namespace std {
+ using size_t = decltype(sizeof(0));
+ template<typename> struct tuple_size;
+ template<size_t, typename> struct tuple_element { using type = int; };
+}
+
+template<> struct std::tuple_size<C> { enum { value = 2 }; };
+
+template<typename T> int decomp(T &t) {
+ auto &[a, b] = t; // expected-error {{type 'D' decomposes into 3 elements, but only 2 names were provided}}
+ return a + b; // expected-error {{cannot initialize return object of type 'int' with an rvalue of type 'int *'}}
+}
+
+void test() {
+ A a;
+ B b;
+ C c;
+ D d;
+ E e;
+ decomp(a);
+ decomp(b);
+ decomp(c);
+ decomp(d); // expected-note {{in instantiation of}}
+ decomp(e); // expected-note {{in instantiation of}}
+}
diff --git a/test/SemaTemplate/cxx1z-using-declaration.cpp b/test/SemaTemplate/cxx1z-using-declaration.cpp
new file mode 100644
index 000000000000..7bef36db1f47
--- /dev/null
+++ b/test/SemaTemplate/cxx1z-using-declaration.cpp
@@ -0,0 +1,230 @@
+// RUN: %clang_cc1 -std=c++1z -verify %s
+
+// Test that we cope with failure to expand a pack.
+template<typename ...T> struct Unexpanded : T... {
+ using T::f; // expected-error {{unexpanded}}
+ using typename T::type; // expected-error {{unexpanded}}
+ template<typename ...U> void g(U ...u) { f(u...); } // expected-error {{undeclared identifier 'f'}}
+ void h() {
+ Unexpanded<type...> *p; // expected-error {{undeclared identifier 'type'}}
+ }
+};
+void test_Unexpanded() {
+ struct A { void f(); }; // expected-note {{must qualify}}
+ struct B { void f(int); }; // expected-note {{must qualify}}
+ Unexpanded<A, B>().g(0); // expected-note {{instantiation of}}
+}
+
+// Test using non-type members from pack of base classes.
+template<typename ...T> struct A : T... { // expected-note 2{{candidate}}
+ using T::T ...; // expected-note 6{{inherited here}}
+ using T::operator() ...;
+ using T::operator T* ...;
+ using T::h ...;
+
+ void f(int n) { h(n); } // expected-error {{ambiguous}}
+ void f(int n, int m) { h(n, m); } // expected-error {{member using declaration 'h' instantiates to an empty pack}}
+ void g(int n) { (*this)(n); } // expected-error {{ambiguous}}
+ void g(int n, int m) { (*this)(n, m); } // expected-error {{does not provide a call operator}}
+};
+
+namespace test_A {
+ struct X { // expected-note 2{{candidate}}
+ X();
+ X(int); // expected-note {{candidate}}
+ void operator()(int); // expected-note 2{{candidate}}
+ operator X *();
+ void h(int); // expected-note {{candidate}}
+ };
+ struct Y {
+ Y();
+ Y(int, int);
+ void operator()(int, int);
+ operator Y *();
+ void h(int, int); // expected-note {{not viable}}
+ };
+ struct Z { // expected-note 2{{candidate}}
+ Z();
+ Z(int); // expected-note {{candidate}}
+ void operator()(int); // expected-note 2{{candidate}}
+ operator Z *();
+ void h(int); // expected-note {{candidate}}
+ };
+
+ void f() {
+ A<> a;
+ a.f(0, 0); // expected-note {{instantiation of}}
+ a.g(0, 0); // expected-note {{instantiation of}}
+
+ A<X, Y> axy(0);
+ A<X, Y>(0, 0);
+ axy.f(0);
+ axy.f(0, 0);
+ axy.g(0);
+ axy.g(0, 0);
+ axy(0);
+ axy(0, 0);
+
+ A<X, Y, Z>(0); // expected-error {{ambiguous}}
+ A<X, Y, Z> axyz(0, 0);
+ axyz.f(0); // expected-note {{instantiation of}}
+ axyz.f(0, 0);
+ axyz.g(0); // expected-note {{instantiation of}}
+ axyz.g(0, 0);
+ axyz(0); // expected-error {{ambiguous}}
+ axyz(0, 0);
+
+ X *x;
+ x = a; // expected-error {{incompatible}}
+ x = axy;
+ x = axyz;
+ x = a.operator X*(); // expected-error {{no member}}
+ x = axy.operator X*();
+ x = axyz.operator X*();
+
+ Z *z;
+ z = axyz;
+ z = axyz.operator Z*();
+ }
+}
+
+// Test using pack of non-type members from single base class.
+template<typename X, typename Y, typename ...T> struct B : X, Y {
+ using X::operator T* ...;
+};
+
+namespace test_B {
+ struct X { operator int*(); operator float*(); operator char*(); }; // expected-note {{candidate}}
+ struct Y { operator int*(); operator float*(); operator char*(); }; // expected-note {{candidate}}
+ B<X, Y, int, float> bif;
+ int *pi = bif;
+ float *pf = bif;
+ char *pc = bif; // expected-error {{ambiguous}}
+}
+
+// Test using type member from pack of base classes.
+template<typename ...T> struct C : T... {
+ using typename T::type ...; // expected-error {{target of using declaration conflicts}}
+ void f() { type value; } // expected-error {{member using declaration 'type' instantiates to an empty pack}}
+};
+
+namespace test_C {
+ struct X { typedef int type; };
+ struct Y { typedef int type; }; // expected-note {{conflicting}}
+ struct Z { typedef float type; }; // expected-note {{target}}
+
+ void f() {
+ C<> c;
+ c.f(); // expected-note {{instantiation of}}
+
+ C<X, Y> cxy;
+ cxy.f();
+
+ C<X, Y, Z> cxyz; // expected-note {{instantiation of}}
+ cxyz.f();
+ }
+}
+
+// Test using pack of non-types at block scope.
+template<typename ...T> int fn1() {
+ using T::e ...; // expected-error 2{{class member}} expected-note 2{{instead}}
+ // expected-error@-1 2{{produces multiple values}}
+ return e; // expected-error {{using declaration 'e' instantiates to an empty pack}}
+}
+
+namespace test_fn1 {
+ struct X { static int e; };
+ struct Y { typedef int e; };
+ inline namespace P { enum E { e }; }
+ inline namespace Q { enum F { e }; }
+ void f() {
+ fn1<>(); // expected-note {{instantiation of}}
+ fn1<X>(); // expected-note {{instantiation of}}
+ fn1<Y>(); // expected-note {{instantiation of}}
+ fn1<E>();
+ fn1<E, F>(); // expected-note {{instantiation of}}
+ fn1<E, X>(); // expected-note {{instantiation of}}
+ }
+}
+
+// Test using pack of types at block scope.
+template<typename ...T> void fn2() {
+ // This cannot ever be valid: in order for T::type to be a type, T must be a
+ // class, and a class member cannot be named by a block-scope using declaration.
+ using typename T::type ...; // expected-error {{class member}}
+ type x; // expected-error {{unknown type name 'type'}}
+}
+
+// Test partial substitution into class-scope pack.
+template<typename ...T> auto lambda1() {
+ return [](auto x) {
+ struct A : T::template X<decltype(x)>... { // expected-note 1+{{instantiation of}}
+ using T::template X<decltype(x)>::f ...;
+ using typename T::template X<decltype(x)>::type ...;
+ void g(int n) { f(n); } // expected-error {{empty pack}} expected-error {{expected 2, have 1}} expected-error {{ambiguous}}
+ void h() { type value; } // expected-error {{empty pack}}
+ };
+ return A();
+ };
+}
+
+namespace test_lambda1 {
+ struct A {
+ template<typename> struct X {
+ void f(int); // expected-note {{candidate}}
+ using type = int;
+ };
+ };
+ struct B {
+ template<typename> struct X {
+ void f(int, int); // expected-note {{declared here}} expected-note {{not viable}}
+ using type = int;
+ };
+ };
+ struct C {
+ template<typename> struct X {
+ void f(int); // expected-note {{candidate}}
+ void f(int, int); // expected-note {{not viable}}
+ using type = int;
+ };
+ };
+
+ void f() {
+ lambda1<>() // expected-note 2{{instantiation of}}
+ (0)
+ // FIXME: This is poor error recovery
+ .g(0); // expected-error {{no member named 'g'}}
+ lambda1<A>()
+ (0)
+ .g(0);
+ lambda1<B>()
+ (0) // expected-note {{instantiation of}}
+ .g(0);
+ lambda1<A, B, C>()
+ (0) // expected-note {{instantiation of}}
+ .g(0);
+ }
+}
+
+namespace p0195r2_example {
+ template<typename ...Ts>
+ struct Overloader : Ts... {
+ using Ts::operator() ...;
+ };
+
+ template<typename ...Ts>
+ constexpr auto make_overloader(Ts &&...ts) {
+ return Overloader<Ts...>{static_cast<Ts&&>(ts)...};
+ }
+
+ void test() {
+ auto o = make_overloader(
+ [&](int &r) -> int & { return r; }, // expected-note {{candidate function}}
+ [&](float &r) -> float & { return r; } // expected-note {{candidate function}}
+ );
+ int a; float f; double d;
+ int &ra = o(a);
+ float &rf = o(f);
+ double &rd = o(d); // expected-error {{no matching function}}
+ }
+}
diff --git a/test/SemaTemplate/deduction.cpp b/test/SemaTemplate/deduction.cpp
index d024c3147735..9471bac91c30 100644
--- a/test/SemaTemplate/deduction.cpp
+++ b/test/SemaTemplate/deduction.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++1z
// Template argument deduction with template template parameters.
template<typename T, template<T> class A>
@@ -264,4 +265,86 @@ int main() {
return 0;
}
} // end ns2
-} \ No newline at end of file
+}
+
+namespace multiple_deduction_different_type {
+ template<typename T, T v> struct X {};
+ template<template<typename T, T> class X, typename T, typename U, int N>
+ void f(X<T, N>, X<U, N>) {} // expected-note 2{{values of conflicting types}}
+ template<template<typename T, T> class X, typename T, typename U, const int *N>
+ void g(X<T, N>, X<U, N>) {} // expected-note 0-2{{values of conflicting types}}
+ int n;
+ void h() {
+ f(X<int, 1+1>(), X<unsigned int, 3-1>()); // expected-error {{no matching function}}
+ f(X<unsigned int, 1+1>(), X<int, 3-1>()); // expected-error {{no matching function}}
+#if __cplusplus > 201402L
+ g(X<const int*, &n>(), X<int*, &n + 1 - 1>()); // expected-error {{no matching function}}
+ g(X<int*, &n>(), X<const int*, &n + 1 - 1>()); // expected-error {{no matching function}}
+#endif
+ }
+
+ template<template<typename T, T> class X, typename T, typename U, T N>
+ void x(X<T, N>, int(*)[N], X<U, N>) {} // expected-note 1+{{candidate}}
+ template<template<typename T, T> class X, typename T, typename U, T N>
+ void x(int(*)[N], X<T, N>, X<U, N>) {} // expected-note 1+{{candidate}}
+ int arr[3];
+ void y() {
+ x(X<int, 3>(), &arr, X<int, 3>());
+ x(&arr, X<int, 3>(), X<int, 3>());
+
+ x(X<int, 3>(), &arr, X<char, 3>()); // expected-error {{no matching function}}
+ x(&arr, X<int, 3>(), X<char, 3>()); // expected-error {{no matching function}}
+
+ x(X<char, 3>(), &arr, X<char, 3>());
+ x(&arr, X<char, 3>(), X<char, 3>());
+ }
+}
+
+namespace nullptr_deduction {
+ using nullptr_t = decltype(nullptr);
+
+ template<typename T, T v> struct X {};
+ template<typename T, T v> void f(X<T, v>) {
+ static_assert(!v, "");
+ }
+ void g() {
+ f(X<int*, nullptr>());
+ f(X<nullptr_t, nullptr>());
+ }
+
+ template<template<typename T, T> class X, typename T, typename U, int *P>
+ void f1(X<T, P>, X<U, P>) {} // expected-note 2{{values of conflicting types}}
+ void h() {
+ f1(X<int*, nullptr>(), X<nullptr_t, nullptr>()); // expected-error {{no matching function}}
+ f1(X<nullptr_t, nullptr>(), X<int*, nullptr>()); // expected-error {{no matching function}}
+ }
+
+ template<template<typename T, T> class X, typename T, typename U, nullptr_t P>
+ void f2(X<T, P>, X<U, P>) {} // expected-note 2{{values of conflicting types}}
+ void i() {
+ f2(X<int*, nullptr>(), X<nullptr_t, nullptr>()); // expected-error {{no matching function}}
+ f2(X<nullptr_t, nullptr>(), X<int*, nullptr>()); // expected-error {{no matching function}}
+ }
+}
+
+namespace member_pointer {
+ struct A { void f(int); };
+ template<typename T, void (A::*F)(T)> struct B;
+ template<typename T> struct C;
+ template<typename T, void (A::*F)(T)> struct C<B<T, F>> {
+ C() { A a; T t; (a.*F)(t); }
+ };
+ C<B<int, &A::f>> c;
+}
+
+namespace deduction_substitution_failure {
+ template<typename T> struct Fail { typedef typename T::error error; }; // expected-error 2{{prior to '::'}}
+
+ template<typename T, typename U> struct A {};
+ template<typename T> struct A<T, typename Fail<T>::error> {}; // expected-note {{instantiation of}}
+ A<int, int> ai; // expected-note {{during template argument deduction for class template partial specialization 'A<T, typename Fail<T>::error>' [with T = int]}}
+
+ template<typename T, typename U> int B; // expected-warning 0-1 {{extension}}
+ template<typename T> int B<T, typename Fail<T>::error> {}; // expected-note {{instantiation of}}
+ int bi = B<char, char>; // expected-note {{during template argument deduction for variable template partial specialization 'B<T, typename Fail<T>::error>' [with T = char]}}
+}
diff --git a/test/SemaTemplate/default-expr-arguments-3.cpp b/test/SemaTemplate/default-expr-arguments-3.cpp
new file mode 100644
index 000000000000..9dc3b134300a
--- /dev/null
+++ b/test/SemaTemplate/default-expr-arguments-3.cpp
@@ -0,0 +1,55 @@
+// RUN: %clang_cc1 -std=c++14 -verify -ast-dump %s | FileCheck %s
+// expected-no-diagnostics
+
+// CHECK: FunctionDecl {{.*}} used func 'void (void)'
+// CHECK-NEXT: TemplateArgument type 'int'
+// CHECK: LambdaExpr {{.*}} 'class (lambda at
+// CHECK: ParmVarDecl {{.*}} used f 'enum foo' cinit
+// CHECK-NEXT: DeclRefExpr {{.*}} 'enum foo' EnumConstant {{.*}} 'a' 'enum foo'
+
+namespace PR28795 {
+ template<typename T>
+ void func() {
+ enum class foo { a, b };
+ auto bar = [](foo f = foo::a) { return f; };
+ bar();
+ }
+
+ void foo() {
+ func<int>();
+ }
+}
+
+// CHECK: ClassTemplateSpecializationDecl {{.*}} struct class2 definition
+// CHECK-NEXT: TemplateArgument type 'int'
+// CHECK: LambdaExpr {{.*}} 'class (lambda at
+// CHECK: ParmVarDecl {{.*}} used f 'enum foo' cinit
+// CHECK-NEXT: DeclRefExpr {{.*}} 'enum foo' EnumConstant {{.*}} 'a' 'enum foo'
+
+// Template struct case:
+template <class T> struct class2 {
+ void bar() {
+ enum class foo { a, b };
+ [](foo f = foo::a) { return f; }();
+ }
+};
+
+template struct class2<int>;
+
+// CHECK: FunctionTemplateDecl {{.*}} f1
+// CHECK-NEXT: TemplateTypeParmDecl {{.*}} typename T
+// CHECK-NEXT: FunctionDecl {{.*}} f1 'void (void)'
+// CHECK: FunctionDecl {{.*}} f1 'void (void)'
+// CHECK-NEXT: TemplateArgument type 'int'
+// CHECK: ParmVarDecl {{.*}} n 'enum foo' cinit
+// CHECK-NEXT: DeclRefExpr {{.*}} 'enum foo' EnumConstant {{.*}} 'a' 'enum foo'
+
+template<typename T>
+void f1() {
+ enum class foo { a, b };
+ struct S {
+ int g1(foo n = foo::a);
+ };
+}
+
+template void f1<int>();
diff --git a/test/SemaTemplate/dependent-type-identity.cpp b/test/SemaTemplate/dependent-type-identity.cpp
index 6b23a38f8486..c826268c864c 100644
--- a/test/SemaTemplate/dependent-type-identity.cpp
+++ b/test/SemaTemplate/dependent-type-identity.cpp
@@ -80,11 +80,20 @@ namespace PR6851 {
S< S<w>::cond && 1 > foo();
};
+ struct Arrow { Arrow *operator->(); int n; };
+ template<typename T> struct M {
+ Arrow a;
+ auto f() -> M<decltype(a->n)>;
+ };
+
struct Alien;
bool operator&&(const Alien&, const Alien&);
template <bool w>
S< S<w>::cond && 1 > N::foo() { }
+
+ template<typename T>
+ auto M<T>::f() -> M<decltype(a->n)> {}
}
namespace PR7460 {
diff --git a/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp b/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp
index 6e8323d1ee2c..c5290efafc1a 100644
--- a/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp
+++ b/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp
@@ -30,8 +30,6 @@ template<unsigned N> struct S {
// expected-error {{no member named 'recurse'}} \
// expected-note 9{{instantiation of exception spec}}
};
-decltype(S<0>::recurse()) *pVoid1 = 0; // ok, exception spec not needed
-decltype(&S<0>::recurse) pFn = 0; // ok, exception spec not needed
template<> struct S<10> {};
void (*pFn2)() noexcept = &S<0>::recurse; // expected-note {{instantiation of exception spec}} expected-error {{not superset}}
@@ -39,7 +37,7 @@ void (*pFn2)() noexcept = &S<0>::recurse; // expected-note {{instantiation of ex
namespace dr1330_example {
template <class T> struct A {
- void f(...) throw (typename T::X); // expected-error {{'int'}}
+ void f(...) throw (typename T::X);
void f(int);
};
@@ -48,16 +46,14 @@ namespace dr1330_example {
}
struct S {
- template<typename T>
- static int f() noexcept(noexcept(A<T>().f("boo!"))) { return 0; } // \
- // expected-note {{instantiation of exception spec}}
- typedef decltype(f<S>()) X;
+ template<typename T> static void f() throw(typename T::X);
+ typedef decltype(f<S>()) X; // expected-error {{exception specification is not available}}
};
- int test2() {
- S().f<S>(); // ok
- S().f<int>(); // expected-note {{instantiation of exception spec}}
- }
+ struct T {
+ template<typename T> static void f() throw(T**);
+ typedef decltype(f<S>()) X; // expected-error {{exception specification is not available}}
+ };
template<typename T>
struct U {
diff --git a/test/SemaTemplate/instantiation-default-1.cpp b/test/SemaTemplate/instantiation-default-1.cpp
index 99154a5cc460..ab9eca75e239 100644
--- a/test/SemaTemplate/instantiation-default-1.cpp
+++ b/test/SemaTemplate/instantiation-default-1.cpp
@@ -36,7 +36,7 @@ typedef int& int_ref_t;
Def2<int_ref_t> *d2; // expected-note{{in instantiation of default argument for 'Def2<int &>' required here}}
-template<> struct Def1<const int, const int> { }; // expected-error{{redefinition of 'Def1<const int>'}}
+template<> struct Def1<const int> { }; // expected-error{{redefinition of 'Def1<const int, const int>'}}
template<typename T, typename T2 = T&> struct Def3;
diff --git a/test/SemaTemplate/instantiation-depth-default.cpp b/test/SemaTemplate/instantiation-depth-default.cpp
new file mode 100644
index 000000000000..3d89aa18ca43
--- /dev/null
+++ b/test/SemaTemplate/instantiation-depth-default.cpp
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -ftemplate-backtrace-limit 2 %s
+//
+// FIXME: Disable this test when Clang was built with ASan, because ASan
+// increases our per-frame stack usage enough that this test no longer fits
+// within our normal stack space allocation.
+// REQUIRES: not_asan
+
+template<int N, typename T> struct X : X<N+1, T*> {};
+// expected-error-re@8 {{recursive template instantiation exceeded maximum depth of 1024{{$}}}}
+// expected-note@8 {{instantiation of template class}}
+// expected-note@8 {{skipping 1023 contexts in backtrace}}
+// expected-note@8 {{use -ftemplate-depth=N to increase recursive template instantiation depth}}
+
+X<0, int> x; // expected-note {{in instantiation of}}
+
+// FIXME: It crashes. Investigating.
+// UNSUPPORTED: mingw32
diff --git a/test/SemaTemplate/ms-class-specialization-class-scope.cpp b/test/SemaTemplate/ms-class-specialization-class-scope.cpp
index 3ebb1c9c555e..fc51c23a34e9 100644
--- a/test/SemaTemplate/ms-class-specialization-class-scope.cpp
+++ b/test/SemaTemplate/ms-class-specialization-class-scope.cpp
@@ -19,7 +19,7 @@ public:
X<double>::y c;
template<> struct X<float> {}; // expected-note {{previous definition is here}}
- template<> struct X<float> {}; // expected-error {{redefinition of 'A::X<float>'}}
+ template<> struct X<float> {}; // expected-error {{redefinition of 'X<float>'}}
};
A::X<void>::x axv;
diff --git a/test/SemaTemplate/temp_arg_enum_printing.cpp b/test/SemaTemplate/temp_arg_enum_printing.cpp
index a788975b20dd..bdf277d308c3 100644
--- a/test/SemaTemplate/temp_arg_enum_printing.cpp
+++ b/test/SemaTemplate/temp_arg_enum_printing.cpp
@@ -13,11 +13,11 @@ template <NamedEnum E>
void foo();
void test() {
- // CHECK: template <NamedEnumNS::NamedEnum E = NamedEnumNS::NamedEnum::Val0>
+ // CHECK: template<> void foo<NamedEnumNS::NamedEnum::Val0>()
NamedEnumNS::foo<Val0>();
- // CHECK: template <NamedEnumNS::NamedEnum E = NamedEnumNS::NamedEnum::Val1>
+ // CHECK: template<> void foo<NamedEnumNS::NamedEnum::Val1>()
NamedEnumNS::foo<(NamedEnum)1>();
- // CHECK: template <NamedEnumNS::NamedEnum E = 2>
+ // CHECK: template<> void foo<2>()
NamedEnumNS::foo<(NamedEnum)2>();
}
diff --git a/test/SemaTemplate/temp_arg_nontype.cpp b/test/SemaTemplate/temp_arg_nontype.cpp
index 91b0c6e76508..93f11b5657d0 100644
--- a/test/SemaTemplate/temp_arg_nontype.cpp
+++ b/test/SemaTemplate/temp_arg_nontype.cpp
@@ -364,3 +364,90 @@ namespace PR17696 {
b<&a::i> c; // okay
}
+
+namespace partial_order_different_types {
+ // These are unordered because the type of the final argument doesn't match.
+ template<int, int, typename T, typename, T> struct A; // expected-note {{here}}
+ template<int N, typename T, typename U, T V> struct A<0, N, T, U, V> {}; // expected-note {{matches}}
+ template<typename T, typename U, U V> struct A<0, 0, T, U, V> {}; // expected-note {{matches}}
+ // expected-error@-1 {{not more specialized than the primary}}
+ // expected-note@-2 {{deduced non-type template argument does not have the same type as the corresponding template parameter ('U' vs 'type-parameter-0-0')}}
+ A<0, 0, int, int, 0> a; // expected-error {{ambiguous partial specializations}}
+}
+
+namespace partial_order_references {
+ // FIXME: The standard does not appear to consider the second specialization
+ // to be more more specialized than the first! The problem is that deducing
+ // an 'int&' parameter from an argument 'R' results in a type mismatch,
+ // because the parameter has a reference type and the argument is an
+ // expression and thus does not have reference type. We resolve this by
+ // matching the type of an expression corresponding to the parameter rather
+ // than matching the parameter itself.
+ template <int, int, int &> struct A {};
+ template <int N, int &R> struct A<N, 0, R> {};
+ template <int &R> struct A<0, 0, R> {};
+ int N;
+ A<0, 0, N> a;
+
+ template<int, int &R> struct B; // expected-note 2{{template}}
+ template<const int &R> struct B<0, R> {};
+ // expected-error@-1 {{not more specialized than the primary}}
+ // expected-note@-2 {{'const int' vs 'int &'}}
+ B<0, N> b; // expected-error {{undefined}}
+
+ template<int, const int &R> struct C; // expected-note 2{{template}}
+ template<int &R> struct C<0, R> {};
+ // expected-error@-1 {{not more specialized than the primary}}
+ // expected-note@-2 {{'int' vs 'const int &'}}
+ C<0, N> c; // expected-error {{undefined}}
+
+ template<int, const int &R> struct D; // expected-note 2{{template}}
+ template<int N> struct D<0, N> {};
+ // expected-error@-1 {{not more specialized than the primary}}
+ // expected-note@-2 {{'int' vs 'const int &'}}
+ extern const int K = 5;
+ D<0, K> d; // expected-error {{undefined}}
+}
+
+namespace dependent_nested_partial_specialization {
+ template<typename> using X = int; // expected-warning {{C++11}}
+ template<typename T> using Y = T*; // expected-warning {{C++11}}
+ int n;
+
+ template<template<typename> class X> struct A {
+ template<typename T, X<T> N> struct B; // expected-note 2{{here}}
+ template<typename T> struct B<T, 0> {}; // expected-error {{specializes a template parameter with dependent type 'Y<T>'}}
+ };
+ A<X>::B<int, 0> ax;
+ A<Y>::B<int, &n> ay; // expected-error {{undefined}} expected-note {{instantiation of}}
+
+ template<template<typename> class X> struct C {
+ template<typename T, int N, int M> struct D; // expected-note {{here}}
+ template<typename T, X<T> N> struct D<T*, N, N + 1> {}; // expected-error {{type of specialized non-type template argument depends on}}
+ };
+ C<X>::D<int*, 0, 1> cx;
+ C<Y>::D<int*, 0, 1> cy; // expected-error {{undefined}} expected-note {{instantiation of}}
+
+ template<typename T> struct E {
+ template<typename U, U V> struct F; // expected-note {{template}}
+ template<typename W, T V> struct F<W, V> {}; // expected-error {{not more specialized than the primary}} expected-note {{does not have the same type}}
+ };
+ E<int>::F<int, 0> e1; // expected-note {{instantiation of}}
+}
+
+namespace nondependent_default_arg_ordering {
+ int n, m;
+ template<typename A, A B = &n> struct X {};
+ template<typename A> void f(X<A>); // expected-note {{candidate}}
+ template<typename A> void f(X<A, &m>); // expected-note {{candidate}}
+ template<typename A, A B> void f(X<A, B>); // expected-note 2{{candidate}}
+ template<template<typename U, U> class T, typename A, int *B> void f(T<A, B>); // expected-note 2{{candidate}}
+ void g() {
+ // FIXME: The first and second function templates above should be
+ // considered more specialized than the last two, but during partial
+ // ordering we fail to check that we actually deduced template arguments
+ // that make the deduced A identical to A.
+ X<int *, &n> x; f(x); // expected-error {{ambiguous}}
+ X<int *, &m> y; f(y); // expected-error {{ambiguous}}
+ }
+}
diff --git a/test/SemaTemplate/temp_arg_nontype_cxx11.cpp b/test/SemaTemplate/temp_arg_nontype_cxx11.cpp
index 15c9c2560a96..cfaad0cd0c96 100644
--- a/test/SemaTemplate/temp_arg_nontype_cxx11.cpp
+++ b/test/SemaTemplate/temp_arg_nontype_cxx11.cpp
@@ -23,3 +23,16 @@ namespace CanonicalNullptr {
B<int> b = MakeB<int>();
C<int> c = MakeC<int>();
}
+
+namespace Auto {
+ template<auto> struct A { }; // expected-error {{until C++1z}}
+}
+
+namespace check_conversion_early {
+ struct X {};
+ template<int> struct A {};
+ template<X &x> struct A<x> {}; // expected-error {{not implicitly convertible}}
+
+ struct Y { constexpr operator int() const { return 0; } };
+ template<Y &y> struct A<y> {}; // expected-error {{cannot be deduced}} expected-note {{'y'}}
+}
diff --git a/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp b/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp
index 548f7f8f34fb..c1fcedd58d13 100644
--- a/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp
+++ b/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp
@@ -122,13 +122,13 @@ namespace DeduceDifferentType {
int a_exp = a<3>(A<3>());
template<decltype(nullptr)> struct B {};
- template<int *P> int b(B<P>); // expected-note {{could not match}} expected-note {{not implicitly convertible}}
+ template<int *P> int b(B<P>); // expected-error {{value of type 'int *' is not implicitly convertible to 'decltype(nullptr)'}}
int b_imp = b(B<nullptr>()); // expected-error {{no matching function}}
int b_exp = b<nullptr>(B<nullptr>()); // expected-error {{no matching function}}
struct X { constexpr operator int() { return 0; } } x;
template<X &> struct C {};
- template<int N> int c(C<N>); // expected-note {{does not have the same type}} expected-note {{not implicitly convertible}}
+ template<int N> int c(C<N>); // expected-error {{value of type 'int' is not implicitly convertible to 'DeduceDifferentType::X &'}}
int c_imp = c(C<x>()); // expected-error {{no matching function}}
int c_exp = c<x>(C<x>()); // expected-error {{no matching function}}
@@ -137,7 +137,7 @@ namespace DeduceDifferentType {
struct Z { constexpr operator Y&() { return y; } } z;
constexpr Y::operator Z&() { return z; }
template<Y &> struct D {};
- template<Z &z> int d(D<z>); // expected-note {{does not have the same type}}
+ template<Z &z> int d(D<z>); // expected-note {{couldn't infer template argument 'z'}}
int d_imp = d(D<y>()); // expected-error {{no matching function}}
int d_exp = d<y>(D<y>());
}
@@ -155,3 +155,176 @@ namespace PR24921 {
template<int> void f(int);
template<> void f<e>() {}
}
+
+namespace Auto {
+ namespace Basic {
+ // simple auto
+ template<auto x> constexpr auto constant = x; // expected-note {{declared here}}
+
+ auto v1 = constant<5>;
+ auto v2 = constant<true>;
+ auto v3 = constant<'a'>;
+ auto v4 = constant<2.5>; // expected-error {{cannot have type 'double'}}
+
+ using T1 = decltype(v1);
+ using T1 = int;
+ using T2 = decltype(v2);
+ using T2 = bool;
+ using T3 = decltype(v3);
+ using T3 = char;
+
+ // pointers
+ template<auto v> class B { };
+ template<auto* p> class B<p> { }; // expected-note {{matches}}
+ template<auto** pp> class B<pp> { };
+ template<auto* p0> int &f(B<p0> b); // expected-note {{candidate}}
+ template<auto** pp0> float &f(B<pp0> b); // expected-note {{candidate}}
+
+ int a, *b = &a;
+ int &r = f(B<&a>());
+ float &s = f(B<&b>());
+
+ // pointers to members
+ template<typename T, auto *T::*p> struct B<p> {};
+ template<typename T, auto **T::*p> struct B<p> {};
+ template<typename T, auto *T::*p0> char &f(B<p0> b); // expected-note {{candidate}}
+ template<typename T, auto **T::*pp0> short &f(B<pp0> b); // expected-note {{candidate}}
+
+ struct X { int n; int *p; int **pp; typedef int a, b; };
+ auto t = f(B<&X::n>()); // expected-error {{no match}}
+ char &u = f(B<&X::p>());
+ short &v = f(B<&X::pp>());
+
+ // A case where we need to do auto-deduction, and check whether the
+ // resulting dependent types match during partial ordering. These
+ // templates are not ordered due to the mismatching function parameter.
+ template<typename T, auto *(*f)(T, typename T::a)> struct B<f> {}; // expected-note {{matches}}
+ template<typename T, auto **(*f)(T, typename T::b)> struct B<f> {}; // expected-note {{matches}}
+ int **g(X, int);
+ B<&g> bg; // expected-error {{ambiguous}}
+ }
+
+ namespace Chained {
+ // chained template argument deduction
+ template<long n> struct C { };
+ template<class T> struct D;
+ template<class T, T n> struct D<C<n>>
+ {
+ using Q = T;
+ };
+ using DQ = long;
+ using DQ = D<C<short(2)>>::Q;
+
+ // chained template argument deduction from an array bound
+ template<typename T> struct E;
+ template<typename T, T n> struct E<int[n]> {
+ using Q = T;
+ };
+ using EQ = E<int[short(42)]>::Q;
+ using EQ = decltype(sizeof 0);
+
+ template<int N> struct F;
+ template<typename T, T N> int foo(F<N> *) = delete; // expected-note {{explicitly deleted}}
+ void foo(void *); // expected-note {{candidate function}}
+ void bar(F<0> *p) {
+ foo(p); // expected-error {{deleted function}}
+ }
+ }
+
+ namespace ArrayToPointer {
+ constexpr char s[] = "test";
+ template<const auto* p> struct S { };
+ S<s> p;
+ }
+
+ namespace DecltypeAuto {
+ template<auto v> struct A { };
+ template<decltype(auto) v> struct DA { };
+ template<auto&> struct R { };
+
+ auto n = 0; // expected-note + {{declared here}}
+ A<n> a; // expected-error {{not a constant}} expected-note {{non-const variable 'n'}}
+ DA<n> da1; // expected-error {{not a constant}} expected-note {{non-const variable 'n'}}
+ DA<(n)> da2;
+ R<n> r;
+ }
+
+ namespace Decomposition {
+ // Types of deduced non-type template arguments must match exactly, so
+ // partial ordering fails in both directions here.
+ template<auto> struct Any;
+ template<int N> struct Any<N> { typedef int Int; }; // expected-note 3{{match}}
+ template<short N> struct Any<N> { typedef int Short; }; // expected-note 3{{match}}
+ Any<0>::Int is_int; // expected-error {{ambiguous}}
+ Any<(short)0>::Short is_short; // expected-error {{ambiguous}}
+ Any<(char)0>::Short is_char; // expected-error {{ambiguous}}
+
+ template<int, auto> struct NestedAny;
+ template<auto N> struct NestedAny<0, N>; // expected-note 3{{match}}
+ template<int N> struct NestedAny<0, N> { typedef int Int; }; // expected-note 3{{match}}
+ template<short N> struct NestedAny<0, N> { typedef int Short; }; // expected-note 3{{match}}
+ NestedAny<0, 0>::Int nested_int; // expected-error {{ambiguous}}
+ NestedAny<0, (short)0>::Short nested_short; // expected-error {{ambiguous}}
+ NestedAny<0, (char)0>::Short nested_char; // expected-error {{ambiguous}}
+
+ double foo(int, bool);
+ template<auto& f> struct fn_result_type;
+
+ template<class R, class... Args, R (& f)(Args...)>
+ struct fn_result_type<f>
+ {
+ using type = R;
+ };
+
+ using R1 = fn_result_type<foo>::type;
+ using R1 = double;
+
+ template<int, auto &f> struct fn_result_type_partial_order;
+ template<auto &f> struct fn_result_type_partial_order<0, f>;
+ template<class R, class... Args, R (& f)(Args...)>
+ struct fn_result_type_partial_order<0, f> {};
+ fn_result_type_partial_order<0, foo> frtpo;
+ }
+
+ namespace Variadic {
+ template<auto... vs> struct value_list { };
+
+ using size_t = decltype(sizeof 0);
+ template<size_t n, class List> struct nth_element;
+ template<size_t n, class List> constexpr auto nth_element_v = nth_element<n, List>::value;
+
+ template<size_t n, auto v0, auto... vs>
+ struct nth_element<n, value_list<v0, vs...>>
+ {
+ static constexpr auto value = nth_element<n - 1, value_list<vs...>>::value;
+ };
+ template<auto v0, auto... vs>
+ struct nth_element<0, value_list<v0, vs...>>
+ {
+ static constexpr auto value = v0;
+ };
+
+ static_assert(nth_element_v<2, value_list<'a', 27U, false>> == false, "value mismatch");
+ }
+}
+
+namespace Nested {
+ template<typename T> struct A {
+ template<auto X> struct B;
+ template<auto *P> struct B<P>;
+ template<auto **P> struct B<P> { using pointee = decltype(+**P); };
+ template<auto (*P)(T)> struct B<P> { using param = T; };
+ template<typename U, auto (*P)(T, U)> struct B<P> { using param2 = U; };
+ };
+
+ using Int = int;
+
+ int *n;
+ using Int = A<int>::B<&n>::pointee;
+
+ void f(int);
+ using Int = A<int>::B<&f>::param;
+
+ void g(int, int);
+ using Int = A<int>::B<&g>::param2;
+}
diff --git a/test/SemaTemplate/temp_arg_template.cpp b/test/SemaTemplate/temp_arg_template.cpp
index 6d93f1504a46..67cde53c928b 100644
--- a/test/SemaTemplate/temp_arg_template.cpp
+++ b/test/SemaTemplate/temp_arg_template.cpp
@@ -6,11 +6,12 @@ template<template<typename T> class X> struct A; // expected-note 2{{previous te
template<template<typename T, int I> class X> struct B; // expected-note{{previous template template parameter is here}}
-template<template<int I> class X> struct C; // expected-note{{previous non-type template parameter with type 'int' is here}}
+template<template<int I> class X> struct C; // expected-note 2{{previous non-type template parameter with type 'int' is here}}
template<class> struct X; // expected-note{{too few template parameters in template template argument}}
template<int N> struct Y; // expected-note{{template parameter has a different kind in template argument}}
template<long N> struct Ylong; // expected-note{{template non-type parameter has a different type 'long' in template argument}}
+template<const int &N> struct Yref; // expected-note{{template non-type parameter has a different type 'const int &' in template argument}}
namespace N {
template<class> struct Z;
@@ -27,6 +28,7 @@ A<TooMany> *a5; // expected-error{{template template argument has different temp
B<X> *a6; // expected-error{{template template argument has different template parameters than its corresponding template template parameter}}
C<Y> *a7;
C<Ylong> *a8; // expected-error{{template template argument has different template parameters than its corresponding template template parameter}}
+C<Yref> *a9; // expected-error{{template template argument has different template parameters than its corresponding template template parameter}}
template<typename T> void f(int);
diff --git a/test/SemaTemplate/temp_arg_template_cxx1z.cpp b/test/SemaTemplate/temp_arg_template_cxx1z.cpp
new file mode 100644
index 000000000000..b6b283b53c6b
--- /dev/null
+++ b/test/SemaTemplate/temp_arg_template_cxx1z.cpp
@@ -0,0 +1,102 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++1z -frelaxed-template-template-args %s
+
+// expected-note@temp_arg_template_cxx1z.cpp:* 1+{{}}
+
+template<template<int> typename> struct Ti;
+template<template<int...> typename> struct TPi;
+template<template<int, int...> typename> struct TiPi;
+template<template<int..., int...> typename> struct TPiPi; // FIXME: Why is this not ill-formed?
+
+template<typename T, template<T> typename> struct tT0;
+template<template<typename T, T> typename> struct Tt0;
+
+template<template<typename> typename> struct Tt;
+template<template<typename, typename...> typename> struct TtPt;
+
+template<int> struct i;
+template<int, int = 0> struct iDi;
+template<int, int> struct ii;
+template<int...> struct Pi;
+template<int, int, int...> struct iiPi;
+
+template<int, typename = int> struct iDt;
+template<int, typename> struct it;
+
+template<typename T, T v> struct t0;
+
+template<typename...> struct Pt;
+
+namespace IntParam {
+ using ok = Pt<Ti<i>,
+ Ti<iDi>,
+ Ti<Pi>,
+ Ti<iDt>>;
+ using err1 = Ti<ii>; // expected-error {{different template parameters}}
+ using err2 = Ti<iiPi>; // expected-error {{different template parameters}}
+ using err3 = Ti<t0>; // expected-error {{different template parameters}}
+ using err4 = Ti<it>; // expected-error {{different template parameters}}
+}
+
+// These are accepted by the backwards-compatibility "parameter pack in
+// parameter matches any number of parameters in arguments" rule.
+namespace IntPackParam {
+ using ok = TPi<Pi>;
+ using ok_compat = Pt<TPi<i>, TPi<iDi>, TPi<ii>, TPi<iiPi>>;
+ using err1 = TPi<t0>; // expected-error {{different template parameters}}
+ using err2 = TPi<iDt>; // expected-error {{different template parameters}}
+ using err3 = TPi<it>; // expected-error {{different template parameters}}
+}
+
+namespace IntAndPackParam {
+ using ok = TiPi<Pi>;
+ using ok_compat = Pt<TiPi<ii>, TiPi<iDi>, TiPi<iiPi>>;
+ using err = TiPi<iDi>;
+}
+
+namespace DependentType {
+ using ok = Pt<tT0<int, i>, tT0<int, iDi>>;
+ using err1 = tT0<int, ii>; // expected-error {{different template parameters}}
+ using err2 = tT0<short, i>; // FIXME: should this be OK?
+ using err2a = tT0<long long, i>; // FIXME: should this be OK (if long long is larger than int)?
+ using err2b = tT0<void*, i>; // expected-error {{different template parameters}}
+ using err3 = tT0<short, t0>; // expected-error {{different template parameters}}
+
+ using ok2 = Tt0<t0>;
+ using err4 = Tt0<it>; // expected-error {{different template parameters}}
+}
+
+namespace Auto {
+ template<template<int> typename T> struct TInt {};
+ template<template<int*> typename T> struct TIntPtr {};
+ template<template<auto> typename T> struct TAuto {};
+ template<template<auto*> typename T> struct TAutoPtr {};
+ template<auto> struct Auto;
+ template<auto*> struct AutoPtr;
+ template<int> struct Int;
+ template<int*> struct IntPtr;
+
+ TInt<Auto> ia;
+ TInt<AutoPtr> iap; // FIXME: ill-formed
+ TInt<Int> ii;
+ TInt<IntPtr> iip; // expected-error {{different template parameters}}
+
+ TIntPtr<Auto> ipa;
+ TIntPtr<AutoPtr> ipap;
+ TIntPtr<Int> ipi; // expected-error {{different template parameters}}
+ TIntPtr<IntPtr> ipip;
+
+ TAuto<Auto> aa;
+ TAuto<AutoPtr> aap; // FIXME: ill-formed
+ TAuto<Int> ai; // FIXME: ill-formed
+ TAuto<IntPtr> aip; // FIXME: ill-formed
+
+ TAutoPtr<Auto> apa;
+ TAutoPtr<AutoPtr> apap;
+ TAutoPtr<Int> api; // FIXME: ill-formed
+ TAutoPtr<IntPtr> apip; // FIXME: ill-formed
+
+ int n;
+ template<auto A, decltype(A) B = &n> struct SubstFailure;
+ TInt<SubstFailure> isf; // expected-error {{different template parameters}}
+ TIntPtr<SubstFailure> ipsf; // expected-error {{different template parameters}}
+}
diff --git a/test/SemaTemplate/temp_class_spec_neg.cpp b/test/SemaTemplate/temp_class_spec_neg.cpp
index 1c77038ab8a9..6366a528ff53 100644
--- a/test/SemaTemplate/temp_class_spec_neg.cpp
+++ b/test/SemaTemplate/temp_class_spec_neg.cpp
@@ -20,9 +20,9 @@ struct N::M::A<T*> { };
#endif
// C++ [temp.class.spec]p9
-// bullet 1
+// bullet 1, as amended by DR1315
template <int I, int J> struct A {};
-template <int I> struct A<I+5, I*2> {}; // expected-error{{depends on}}
+template <int I> struct A<I+5, I*2> {}; // expected-error{{cannot be deduced}} expected-note {{'I'}}
template <int I, int J> struct B {};
template <int I> struct B<I, I> {}; //OK
@@ -50,4 +50,4 @@ template<typename T = int, // expected-error{{default template argument}}
template<typename T> struct Test1;
template<typename T, typename U> // expected-note{{non-deducible}}
- struct Test1<T*> { }; // expected-warning{{never be used}}
+ struct Test1<T*> { }; // expected-error{{never be used}}
diff --git a/test/SemaTemplate/temp_explicit.cpp b/test/SemaTemplate/temp_explicit.cpp
index 80c90d0cfcd2..e8c9dfb5f5d2 100644
--- a/test/SemaTemplate/temp_explicit.cpp
+++ b/test/SemaTemplate/temp_explicit.cpp
@@ -26,7 +26,7 @@ template class X0<double> { }; // expected-error{{explicit specialization}}
template class X0<int, int>; // expected-error{{duplicate}}
template<> class X0<char> { }; // expected-note{{previous}}
-template class X0<char>; // expected-warning{{ignored}}
+template class X0<char>; // expected-warning{{has no effect}}
void foo(X0<short>) { }
template class X0<short>;
diff --git a/test/SemaTemplate/template-id-expr.cpp b/test/SemaTemplate/template-id-expr.cpp
index 499d289ee675..e311b5832d0d 100644
--- a/test/SemaTemplate/template-id-expr.cpp
+++ b/test/SemaTemplate/template-id-expr.cpp
@@ -100,5 +100,5 @@ template void f5<0>(); // expected-note {{in instantiation of function template
class C {};
template <template <typename> class D> // expected-note{{previous use is here}}
class E {
- template class D<C>; // expected-error {{elaborated type refers to a template template argument}}
+ template class D<C>; // expected-error {{template template argument 'D' cannot be referenced with a class specifier}}
};
diff --git a/test/Unit/lit.cfg b/test/Unit/lit.cfg
index 4fa6e78ed63b..39fad0099ceb 100644
--- a/test/Unit/lit.cfg
+++ b/test/Unit/lit.cfg
@@ -94,15 +94,16 @@ elif platform.system() == 'Darwin':
elif platform.system() == 'Windows':
shlibpath_var = 'PATH'
+# in stand-alone builds, shlibdir is clang's build tree
+# while llvm_libs_dir is installed LLVM (and possibly older clang)
+llvm_shlib_dir = getattr(config, 'shlibdir', None)
+if not llvm_shlib_dir:
+ lit_config.fatal('No shlibdir set!')
# Point the dynamic loader at dynamic libraries in 'lib'.
llvm_libs_dir = getattr(config, 'llvm_libs_dir', None)
if not llvm_libs_dir:
lit_config.fatal('No LLVM libs dir set!')
-shlibpath = os.path.pathsep.join((llvm_libs_dir,
+shlibpath = os.path.pathsep.join((llvm_shlib_dir, llvm_libs_dir,
config.environment.get(shlibpath_var,'')))
-# Win32 seeks DLLs along %PATH%.
-if sys.platform in ['win32', 'cygwin'] and os.path.isdir(config.shlibdir):
- shlibpath = os.path.pathsep.join((config.shlibdir, shlibpath))
-
config.environment[shlibpath_var] = shlibpath
diff --git a/test/VFS/Inputs/Bar.framework/Headers/A.h b/test/VFS/Inputs/Bar.framework/Headers/A.h
new file mode 100644
index 000000000000..975f1f0437bb
--- /dev/null
+++ b/test/VFS/Inputs/Bar.framework/Headers/A.h
@@ -0,0 +1 @@
+// A.h
diff --git a/test/VFS/Inputs/Bar.framework/Headers/B.h b/test/VFS/Inputs/Bar.framework/Headers/B.h
new file mode 100644
index 000000000000..761540b09cb3
--- /dev/null
+++ b/test/VFS/Inputs/Bar.framework/Headers/B.h
@@ -0,0 +1 @@
+// B.h
diff --git a/test/VFS/Inputs/Bar.framework/Headers/C.h b/test/VFS/Inputs/Bar.framework/Headers/C.h
new file mode 100644
index 000000000000..a0121d46b41f
--- /dev/null
+++ b/test/VFS/Inputs/Bar.framework/Headers/C.h
@@ -0,0 +1 @@
+// C.h
diff --git a/test/VFS/Inputs/Bar.framework/Modules/module.modulemap b/test/VFS/Inputs/Bar.framework/Modules/module.modulemap
new file mode 100644
index 000000000000..d5c759aceb74
--- /dev/null
+++ b/test/VFS/Inputs/Bar.framework/Modules/module.modulemap
@@ -0,0 +1,6 @@
+framework module Bar [extern_c] {
+ umbrella "Headers"
+ export *
+ module * { export * }
+}
+
diff --git a/test/VFS/Inputs/Nonmodular/A.h b/test/VFS/Inputs/Nonmodular/A.h
new file mode 100644
index 000000000000..975f1f0437bb
--- /dev/null
+++ b/test/VFS/Inputs/Nonmodular/A.h
@@ -0,0 +1 @@
+// A.h
diff --git a/test/VFS/Inputs/Nonmodular/Nonmodular.modulemap b/test/VFS/Inputs/Nonmodular/Nonmodular.modulemap
new file mode 100644
index 000000000000..91f16902d535
--- /dev/null
+++ b/test/VFS/Inputs/Nonmodular/Nonmodular.modulemap
@@ -0,0 +1,5 @@
+framework module Nonmodular [extern_c] {
+ umbrella header "umbrella.h"
+ export *
+ module * { export * }
+}
diff --git a/test/VFS/Inputs/Nonmodular/nonmodular-headers.yaml b/test/VFS/Inputs/Nonmodular/nonmodular-headers.yaml
new file mode 100644
index 000000000000..a04172875228
--- /dev/null
+++ b/test/VFS/Inputs/Nonmodular/nonmodular-headers.yaml
@@ -0,0 +1,34 @@
+{
+ 'version': 0,
+ 'case-sensitive': 'false',
+ 'ignore-non-existent-contents': 'true',
+ 'roots': [
+ {
+ 'type': 'directory',
+ 'name': "VDIR/Nonmodular.framework/Headers",
+ 'contents': [
+ {
+ 'type': 'file',
+ 'name': "umbrella.h",
+ 'external-contents': "IN_DIR/Inputs/Nonmodular/umbrella.h"
+ },
+ {
+ 'type': 'file',
+ 'name': "A.h",
+ 'external-contents': "IN_DIR/Inputs/Nonmodular/A.h"
+ }
+ ]
+ },
+ {
+ 'type': 'directory',
+ 'name': "VDIR/Nonmodular.framework/Modules",
+ 'contents': [
+ {
+ 'type': 'file',
+ 'name': "module.modulemap",
+ 'external-contents': "OUT_DIR/module.modulemap"
+ }
+ ]
+ }
+ ]
+}
diff --git a/test/VFS/Inputs/Nonmodular/test.c b/test/VFS/Inputs/Nonmodular/test.c
new file mode 100644
index 000000000000..62807d0264b0
--- /dev/null
+++ b/test/VFS/Inputs/Nonmodular/test.c
@@ -0,0 +1,3 @@
+// expected-no-diagnostics
+
+#include "umbrella.h"
diff --git a/test/VFS/Inputs/Nonmodular/umbrella.h b/test/VFS/Inputs/Nonmodular/umbrella.h
new file mode 100644
index 000000000000..bb79a62ec0c7
--- /dev/null
+++ b/test/VFS/Inputs/Nonmodular/umbrella.h
@@ -0,0 +1,5 @@
+#ifndef __umbrella_h__
+#define __umbrella_h__
+
+#include <Nonmodular/A.h>
+#endif
diff --git a/test/VFS/Inputs/bar-headers.yaml b/test/VFS/Inputs/bar-headers.yaml
new file mode 100644
index 000000000000..846d55cc9ece
--- /dev/null
+++ b/test/VFS/Inputs/bar-headers.yaml
@@ -0,0 +1,39 @@
+{
+ 'version': 0,
+ 'case-sensitive': 'false',
+ 'ignore-non-existent-contents': 'true',
+ 'roots': [
+ {
+ 'type': 'directory',
+ 'name': "VDIR/Bar.framework/Headers",
+ 'contents': [
+ {
+ 'type': 'file',
+ 'name': "A.h",
+ 'external-contents': "OUT_DIR/Bar.framework/Headers/A.h"
+ },
+ {
+ 'type': 'file',
+ 'name': "B.h",
+ 'external-contents': "OUT_DIR/Bar.framework/Headers/B.h"
+ },
+ {
+ 'type': 'file',
+ 'name': "C.h",
+ 'external-contents': "OUT_DIR/Bar.framework/Headers/C.h"
+ }
+ ]
+ },
+ {
+ 'type': 'directory',
+ 'name': "VDIR/Bar.framework/Modules",
+ 'contents': [
+ {
+ 'type': 'file',
+ 'name': "module.modulemap",
+ 'external-contents': "OUT_DIR/Bar.framework/Modules/module.modulemap"
+ }
+ ]
+ },
+ ]
+}
diff --git a/test/VFS/Inputs/vfsoverlay2.yaml b/test/VFS/Inputs/vfsoverlay2.yaml
index ae2a0ce4ec98..688ae643df03 100644
--- a/test/VFS/Inputs/vfsoverlay2.yaml
+++ b/test/VFS/Inputs/vfsoverlay2.yaml
@@ -1,5 +1,6 @@
{
'version': 0,
+ 'ignore-non-existent-contents': false,
'roots': [
{ 'name': 'OUT_DIR', 'type': 'directory',
'contents': [
diff --git a/test/VFS/test_nonmodular.c b/test/VFS/test_nonmodular.c
new file mode 100644
index 000000000000..cff4de751868
--- /dev/null
+++ b/test/VFS/test_nonmodular.c
@@ -0,0 +1,11 @@
+// REQUIRES: shell
+
+// RUN: rm -rf %t
+// RUN: mkdir -p %t/vdir %t/cache %t/outdir
+// We can't have module.map inside Inputs/Nonmodular.
+// RUN: cp %S/Inputs/Nonmodular/Nonmodular.modulemap %t/outdir/module.modulemap
+//
+// RUN: sed -e "s:VDIR:%t/vdir:g" -e "s:IN_DIR:%S:g" -e "s:OUT_DIR:%t/outdir:g" %S/Inputs/Nonmodular/nonmodular-headers.yaml > %t/vdir/nonmodular-headers.yaml
+// RUN: %clang_cc1 -fmodule-name=Nonmodular -fmodules -Wnon-modular-include-in-framework-module -verify -fimplicit-module-maps -fmodules-cache-path=%t/cache -ivfsoverlay %t/vdir/nonmodular-headers.yaml -I %S/Inputs -F %t/vdir -fsyntax-only %S/Inputs/Nonmodular/test.c
+
+// expected-no-diagnostics
diff --git a/test/VFS/umbrella-framework-import-skipnonexist.m b/test/VFS/umbrella-framework-import-skipnonexist.m
new file mode 100644
index 000000000000..5c7cd6d9db13
--- /dev/null
+++ b/test/VFS/umbrella-framework-import-skipnonexist.m
@@ -0,0 +1,14 @@
+// REQUIRES: crash-recovery, shell
+
+// FIXME: This XFAIL is cargo-culted from crash-report.c. Do we need it?
+// XFAIL: mingw32
+
+// RUN: rm -rf %t
+// RUN: mkdir -p %t/vdir %t/outdir %t/cache
+// RUN: cp -a %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
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -ivfsoverlay %t/vdir/bar-headers.yaml -F %t/vdir -fsyntax-only %s
+
+@import Bar;
diff --git a/test/lit.cfg b/test/lit.cfg
index e7ce8fac7c1b..7d8bebf57ff6 100644
--- a/test/lit.cfg
+++ b/test/lit.cfg
@@ -44,7 +44,7 @@ else:
config.test_format = lit.formats.ShTest(execute_external)
# suffixes: A list of file extensions to treat as test files.
-config.suffixes = ['.c', '.cpp', '.m', '.mm', '.cu', '.ll', '.cl', '.s', '.S', '.modulemap', '.test', '.rs']
+config.suffixes = ['.c', '.cpp', '.cppm', '.m', '.mm', '.cu', '.ll', '.cl', '.s', '.S', '.modulemap', '.test', '.rs']
# excludes: A list of directories to exclude from the testsuite. The 'Inputs'
# subdirectories contain auxiliary inputs for various tests in their parent
@@ -102,10 +102,15 @@ if clang_obj_root is not None:
path = os.path.pathsep.join((
clang_tools_dir, llvm_tools_dir, config.environment['PATH']))
config.environment['PATH'] = path
+ # in stand-alone builds, llvm_shlib_dir is clang's build tree
+ # while llvm_libs_dir is installed LLVM (and possibly older clang)
+ llvm_shlib_dir = getattr(config, 'llvm_shlib_dir', None)
+ if not llvm_shlib_dir:
+ lit_config.fatal('No LLVM shlib dir set!')
llvm_libs_dir = getattr(config, 'llvm_libs_dir', None)
if not llvm_libs_dir:
lit_config.fatal('No LLVM libs dir set!')
- path = os.path.pathsep.join((llvm_libs_dir,
+ path = os.path.pathsep.join((llvm_shlib_dir, llvm_libs_dir,
config.environment.get('LD_LIBRARY_PATH','')))
config.environment['LD_LIBRARY_PATH'] = path
@@ -268,6 +273,7 @@ config.substitutions.append( ('%clang', ' ' + config.clang + ' ') )
config.substitutions.append( ('%test_debuginfo', ' ' + config.llvm_src_root + '/utils/test_debuginfo.pl ') )
config.substitutions.append( ('%itanium_abi_triple', makeItaniumABITriple(config.target_triple)) )
config.substitutions.append( ('%ms_abi_triple', makeMSABITriple(config.target_triple)) )
+config.substitutions.append( ('%resource_dir', getClangBuiltinIncludeDir(config.clang)) )
# The host triple might not be set, at least if we're compiling clang from
# an already installed llvm.
@@ -343,6 +349,9 @@ for pattern in tool_patterns:
# Set available features we allow tests to conditionalize on.
#
+if config.clang_default_cxx_stdlib != '':
+ config.available_features.add('default-cxx-stdlib-set')
+
# Enabled/disabled features
if config.clang_staticanalyzer != 0:
config.available_features.add("staticanalyzer")
@@ -372,6 +381,11 @@ if platform.system() not in ['Windows']:
if platform.system() not in ['Windows']:
config.available_features.add('utf8-capable-terminal')
+# Support for libgcc runtime. Used to rule out tests that require
+# clang to run with -rtlib=libgcc.
+if platform.system() not in ['Darwin', 'Fuchsia']:
+ config.available_features.add('libgcc')
+
# Native compilation: Check if triples match.
# FIXME: Consider cases that target can be executed
# even if host_triple were different from target_triple.
diff --git a/test/lit.site.cfg.in b/test/lit.site.cfg.in
index f368c995f568..5e1471f13115 100644
--- a/test/lit.site.cfg.in
+++ b/test/lit.site.cfg.in
@@ -16,6 +16,7 @@ config.target_triple = "@TARGET_TRIPLE@"
config.llvm_use_sanitizer = "@LLVM_USE_SANITIZER@"
config.have_zlib = "@HAVE_LIBZ@"
config.clang_arcmt = @ENABLE_CLANG_ARCMT@
+config.clang_default_cxx_stdlib = "@CLANG_DEFAULT_CXX_STDLIB@"
config.clang_staticanalyzer = @ENABLE_CLANG_STATIC_ANALYZER@
config.clang_examples = @ENABLE_CLANG_EXAMPLES@
config.enable_shared = @ENABLE_SHARED@
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt
index d734493c619e..b0c97f0f1e4c 100644
--- a/tools/CMakeLists.txt
+++ b/tools/CMakeLists.txt
@@ -5,6 +5,8 @@ add_clang_subdirectory(driver)
add_clang_subdirectory(clang-format)
add_clang_subdirectory(clang-format-vs)
add_clang_subdirectory(clang-fuzzer)
+add_clang_subdirectory(clang-import-test)
+add_clang_subdirectory(clang-offload-bundler)
add_clang_subdirectory(c-index-test)
diff --git a/tools/arcmt-test/arcmt-test.cpp b/tools/arcmt-test/arcmt-test.cpp
index 900358ec1fe9..e57d69fddbe2 100644
--- a/tools/arcmt-test/arcmt-test.cpp
+++ b/tools/arcmt-test/arcmt-test.cpp
@@ -7,15 +7,17 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Frontend/PCHContainerOperations.h"
#include "clang/ARCMigrate/ARCMT.h"
-#include "clang/Frontend/ASTUnit.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/Frontend/PCHContainerOperations.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Frontend/Utils.h"
#include "clang/Frontend/VerifyDiagnosticConsumer.h"
#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/PreprocessorOptions.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
#include "llvm/Support/Signals.h"
#include <system_error>
diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c
index 007af9e252a8..dfb4b27bce61 100644
--- a/tools/c-index-test/c-index-test.c
+++ b/tools/c-index-test/c-index-test.c
@@ -838,8 +838,11 @@ static void PrintCursor(CXCursor Cursor, const char *CommentSchemaFile) {
if (Cursor.kind == CXCursor_FunctionDecl) {
/* Collect the template parameter kinds from the base template. */
- unsigned NumTemplateArgs = clang_Cursor_getNumTemplateArguments(Cursor);
- unsigned I;
+ int NumTemplateArgs = clang_Cursor_getNumTemplateArguments(Cursor);
+ int I;
+ if (NumTemplateArgs < 0) {
+ printf(" [no template arg info]");
+ }
for (I = 0; I < NumTemplateArgs; I++) {
enum CXTemplateArgumentKind TAK =
clang_Cursor_getTemplateArgumentKind(Cursor, I);
@@ -1313,6 +1316,25 @@ static enum CXVisitorResult FieldVisitor(CXCursor C,
return CXVisit_Continue;
}
+static void PrintTypeTemplateArgs(CXType T, const char *Format) {
+ int NumTArgs = clang_Type_getNumTemplateArguments(T);
+ if (NumTArgs != -1 && NumTArgs != 0) {
+ int i;
+ CXType TArg;
+ printf(Format, NumTArgs);
+ for (i = 0; i < NumTArgs; ++i) {
+ TArg = clang_Type_getTemplateArgumentAsType(T, i);
+ if (TArg.kind != CXType_Invalid) {
+ PrintTypeAndTypeKind(TArg, " [type=%s] [typekind=%s]");
+ }
+ }
+ /* Ensure that the returned type is invalid when indexing off-by-one. */
+ TArg = clang_Type_getTemplateArgumentAsType(T, i);
+ assert(TArg.kind == CXType_Invalid);
+ printf("]");
+ }
+}
+
static enum CXChildVisitResult PrintType(CXCursor cursor, CXCursor p,
CXClientData d) {
if (!clang_isInvalid(clang_getCursorKind(cursor))) {
@@ -1330,11 +1352,14 @@ static enum CXChildVisitResult PrintType(CXCursor cursor, CXCursor p,
printf(" lvalue-ref-qualifier");
if (RQ == CXRefQualifier_RValue)
printf(" rvalue-ref-qualifier");
+ /* Print the template argument types if they exist. */
+ PrintTypeTemplateArgs(T, " [templateargs/%d=");
/* Print the canonical type if it is different. */
{
CXType CT = clang_getCanonicalType(T);
if (!clang_equalTypes(T, CT)) {
PrintTypeAndTypeKind(CT, " [canonicaltype=%s] [canonicaltypekind=%s]");
+ PrintTypeTemplateArgs(CT, " [canonicaltemplateargs/%d=");
}
}
/* Print the return type if it exists. */
@@ -1359,21 +1384,6 @@ static enum CXChildVisitResult PrintType(CXCursor cursor, CXCursor p,
printf("]");
}
}
- /* Print the template argument types if they exist. */
- {
- int NumTArgs = clang_Type_getNumTemplateArguments(T);
- if (NumTArgs != -1 && NumTArgs != 0) {
- int i;
- printf(" [templateargs/%d=", NumTArgs);
- for (i = 0; i < NumTArgs; ++i) {
- CXType TArg = clang_Type_getTemplateArgumentAsType(T, i);
- if (TArg.kind != CXType_Invalid) {
- PrintTypeAndTypeKind(TArg, " [type=%s] [typekind=%s]");
- }
- }
- printf("]");
- }
- }
/* Print if this is a non-POD type. */
printf(" [isPOD=%d]", clang_isPODType(T));
/* Print the pointee type. */
@@ -2459,8 +2469,14 @@ static void display_evaluate_results(CXEvalResult result) {
switch (clang_EvalResult_getKind(result)) {
case CXEval_Int:
{
- int val = clang_EvalResult_getAsInt(result);
- printf("Kind: Int , Value: %d", val);
+ printf("Kind: Int, ");
+ if (clang_EvalResult_isUnsignedInt(result)) {
+ unsigned long long val = clang_EvalResult_getAsUnsigned(result);
+ printf("unsigned, Value: %llu", val);
+ } else {
+ long long val = clang_EvalResult_getAsLongLong(result);
+ printf("Value: %lld", val);
+ }
break;
}
case CXEval_Float:
diff --git a/tools/c-index-test/core_main.cpp b/tools/c-index-test/core_main.cpp
index e64dae726fe3..3e4052c93ef5 100644
--- a/tools/c-index-test/core_main.cpp
+++ b/tools/c-index-test/core_main.cpp
@@ -41,8 +41,7 @@ static cl::opt<ActionType>
Action(cl::desc("Action:"), cl::init(ActionType::None),
cl::values(
clEnumValN(ActionType::PrintSourceSymbols,
- "print-source-symbols", "Print symbols from source"),
- clEnumValEnd),
+ "print-source-symbols", "Print symbols from source")),
cl::cat(IndexTestCoreCategory));
static cl::extrahelp MoreHelp(
@@ -168,9 +167,9 @@ static bool printSourceSymbols(ArrayRef<const char *> Args) {
static void printSymbolInfo(SymbolInfo SymInfo, raw_ostream &OS) {
OS << getSymbolKindString(SymInfo.Kind);
- if (SymInfo.SubKinds) {
+ if (SymInfo.Properties) {
OS << '(';
- printSymbolSubKinds(SymInfo.SubKinds, OS);
+ printSymbolProperties(SymInfo.Properties, OS);
OS << ')';
}
OS << '/' << getSymbolLanguageString(SymInfo.Lang);
diff --git a/tools/clang-format-vs/.gitignore b/tools/clang-format-vs/.gitignore
new file mode 100644
index 000000000000..c9d25d96c8ec
--- /dev/null
+++ b/tools/clang-format-vs/.gitignore
@@ -0,0 +1,12 @@
+# Visual Studio files
+.vs/
+*.user
+/packages/
+/ClangFormat/obj/
+/ClangFormat/bin/
+
+# Generated and copied files
+/ClangFormat/Key.snk
+/ClangFormat/license.txt
+/ClangFormat/clang-format.exe
+/ClangFormat/source.extension.vsixmanifest
diff --git a/tools/clang-format-vs/CMakeLists.txt b/tools/clang-format-vs/CMakeLists.txt
index fd0d6b028c66..d07a4f6ed5da 100644
--- a/tools/clang-format-vs/CMakeLists.txt
+++ b/tools/clang-format-vs/CMakeLists.txt
@@ -11,15 +11,25 @@ if (BUILD_CLANG_FORMAT_VS_PLUGIN)
"${CLANG_SOURCE_DIR}/LICENSE.TXT"
"${CMAKE_CURRENT_SOURCE_DIR}/ClangFormat/license.txt")
+ # Build number added to Clang version to ensure that new VSIX can be upgraded
+ string(TIMESTAMP CLANG_FORMAT_VSIX_BUILD %y%m%d%H%M UTC)
+
if (NOT CLANG_FORMAT_VS_VERSION)
- set(CLANG_FORMAT_VS_VERSION "${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}.${LLVM_VERSION_PATCH}")
+ set(CLANG_FORMAT_VS_VERSION "${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}.${LLVM_VERSION_PATCH}.${CLANG_FORMAT_VSIX_BUILD}")
endif()
configure_file("source.extension.vsixmanifest.in"
"${CMAKE_CURRENT_SOURCE_DIR}/ClangFormat/source.extension.vsixmanifest")
+ find_program(NUGET_EXE nuget PATHS ${NUGET_EXE_DIR})
+ if (NOT NUGET_EXE)
+ message(FATAL_ERROR "Could not find nuget.exe. Download from https://www.nuget.org/nuget.exe"
+ " and add parent directory to PATH or pass it via NUGET_EXE_DIR var.")
+ endif()
+
add_custom_target(clang_format_vsix ALL
- devenv "${CMAKE_CURRENT_SOURCE_DIR}/ClangFormat.sln" /Build Release
+ COMMAND ${NUGET_EXE} restore "${CMAKE_CURRENT_SOURCE_DIR}/ClangFormat.sln"
+ COMMAND devenv "${CMAKE_CURRENT_SOURCE_DIR}/ClangFormat.sln" /Build Release
DEPENDS clang_format_exe_for_vsix "${CMAKE_CURRENT_SOURCE_DIR}/ClangFormat/source.extension.vsixmanifest"
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${CMAKE_CURRENT_SOURCE_DIR}/ClangFormat/bin/Release/ClangFormat.vsix"
diff --git a/tools/clang-format-vs/ClangFormat.sln b/tools/clang-format-vs/ClangFormat.sln
index d6b211fe506f..73bf84e02858 100644
--- a/tools/clang-format-vs/ClangFormat.sln
+++ b/tools/clang-format-vs/ClangFormat.sln
@@ -1,6 +1,8 @@

Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 2012
+# Visual Studio 14
+VisualStudioVersion = 14.0.25420.1
+MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClangFormat", "ClangFormat\ClangFormat.csproj", "{7FD1783E-2D31-4D05-BF23-6EBE1B42B608}"
EndProject
Global
diff --git a/tools/clang-format-vs/ClangFormat/ClangFormat.csproj b/tools/clang-format-vs/ClangFormat/ClangFormat.csproj
index a61e431cc0b9..5ce601d649bf 100644
--- a/tools/clang-format-vs/ClangFormat/ClangFormat.csproj
+++ b/tools/clang-format-vs/ClangFormat/ClangFormat.csproj
@@ -14,7 +14,7 @@
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>Key.snk</AssemblyOriginatorKeyFile>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
- <MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion>
+ <MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
<FileUpgradeFlags>
</FileUpgradeFlags>
<UpgradeBackupLocation>
@@ -35,6 +35,7 @@
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
+ <TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@@ -44,6 +45,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
+ <Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -53,27 +55,87 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<RunCodeAnalysis>true</RunCodeAnalysis>
+ <Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
+ <Reference Include="envdte, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+ <HintPath>..\packages\VSSDK.DTE.7.0.3\lib\net20\envdte.dll</HintPath>
+ <EmbedInteropTypes>False</EmbedInteropTypes>
+ </Reference>
<Reference Include="Microsoft.CSharp" />
- <Reference Include="Microsoft.VisualStudio.CoreUtility, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
- <Reference Include="Microsoft.VisualStudio.Editor, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
- <Reference Include="Microsoft.VisualStudio.OLE.Interop" />
- <Reference Include="Microsoft.VisualStudio.Shell.Interop" />
- <Reference Include="Microsoft.VisualStudio.Shell.Interop.8.0" />
- <Reference Include="Microsoft.VisualStudio.Shell.Interop.9.0" />
+ <Reference Include="Microsoft.VisualStudio.CoreUtility, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+ <HintPath>..\packages\VSSDK.CoreUtility.10.0.4\lib\net40\Microsoft.VisualStudio.CoreUtility.dll</HintPath>
+ <Private>False</Private>
+ </Reference>
+ <Reference Include="Microsoft.VisualStudio.Editor, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+ <HintPath>..\packages\VSSDK.Editor.10.0.4\lib\net40\Microsoft.VisualStudio.Editor.dll</HintPath>
+ <Private>False</Private>
+ </Reference>
+ <Reference Include="Microsoft.VisualStudio.OLE.Interop, Version=7.1.40304.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+ <HintPath>..\packages\VSSDK.OLE.Interop.7.0.4\lib\net20\Microsoft.VisualStudio.OLE.Interop.dll</HintPath>
+ <Private>True</Private>
+ <Private>False</Private>
+ </Reference>
+ <Reference Include="Microsoft.VisualStudio.Shell.10.0, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+ <HintPath>..\packages\VSSDK.Shell.10.10.0.3\lib\net40\Microsoft.VisualStudio.Shell.10.0.dll</HintPath>
+ <Private>False</Private>
+ </Reference>
+ <Reference Include="Microsoft.VisualStudio.Shell.Immutable.10.0, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+ <HintPath>..\packages\VSSDK.Shell.Immutable.10.10.0.3\lib\net40\Microsoft.VisualStudio.Shell.Immutable.10.0.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
+ <Reference Include="Microsoft.VisualStudio.Shell.Interop, Version=7.1.40304.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+ <HintPath>..\packages\VSSDK.Shell.Interop.7.0.4\lib\net20\Microsoft.VisualStudio.Shell.Interop.dll</HintPath>
+ <Private>True</Private>
+ <Private>False</Private>
+ </Reference>
+ <Reference Include="Microsoft.VisualStudio.Shell.Interop.8.0, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+ <HintPath>..\packages\VSSDK.Shell.Interop.8.8.0.3\lib\net20\Microsoft.VisualStudio.Shell.Interop.8.0.dll</HintPath>
+ <Private>True</Private>
+ <Private>False</Private>
+ </Reference>
<Reference Include="Microsoft.VisualStudio.Shell.Interop.10.0" />
- <Reference Include="Microsoft.VisualStudio.TextManager.Interop" />
- <Reference Include="Microsoft.VisualStudio.Shell.10.0">
- <Private>false</Private>
- </Reference>
- <Reference Include="Microsoft.VisualStudio.Text.Data, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
- <Reference Include="Microsoft.VisualStudio.Text.Logic, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
- <Reference Include="Microsoft.VisualStudio.Text.UI, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
- <Reference Include="Microsoft.VisualStudio.Text.UI.Wpf, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
- <Reference Include="Microsoft.VisualStudio.TextManager.Interop" />
- <Reference Include="Microsoft.VisualStudio.Shell.Immutable.10.0" />
+ <Reference Include="Microsoft.VisualStudio.Shell.Interop.9.0, Version=9.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+ <HintPath>..\packages\VSSDK.Shell.Interop.9.9.0.3\lib\net20\Microsoft.VisualStudio.Shell.Interop.9.0.dll</HintPath>
+ <Private>True</Private>
+ <Private>False</Private>
+ </Reference>
+ <Reference Include="Microsoft.VisualStudio.Text.Data, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+ <HintPath>..\packages\VSSDK.Text.10.0.4\lib\net40\Microsoft.VisualStudio.Text.Data.dll</HintPath>
+ <Private>False</Private>
+ </Reference>
+ <Reference Include="Microsoft.VisualStudio.Text.Logic, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+ <HintPath>..\packages\VSSDK.Text.10.0.4\lib\net40\Microsoft.VisualStudio.Text.Logic.dll</HintPath>
+ <Private>False</Private>
+ </Reference>
+ <Reference Include="Microsoft.VisualStudio.Text.UI, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+ <HintPath>..\packages\VSSDK.Text.10.0.4\lib\net40\Microsoft.VisualStudio.Text.UI.dll</HintPath>
+ <Private>False</Private>
+ </Reference>
+ <Reference Include="Microsoft.VisualStudio.Text.UI.Wpf, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+ <HintPath>..\packages\VSSDK.Text.10.0.4\lib\net40\Microsoft.VisualStudio.Text.UI.Wpf.dll</HintPath>
+ <Private>False</Private>
+ </Reference>
+ <Reference Include="Microsoft.VisualStudio.TextManager.Interop">
+ <HintPath>..\packages\VSSDK.TextManager.Interop.7.0.4\lib\net20\Microsoft.VisualStudio.TextManager.Interop.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
+ <Reference Include="Microsoft.VisualStudio.TextManager.Interop, Version=7.1.40304.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+ <Private>False</Private>
+ </Reference>
+ <Reference Include="Microsoft.VisualStudio.TextManager.Interop.8.0, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+ <HintPath>..\packages\VSSDK.TextManager.Interop.8.8.0.4\lib\net20\Microsoft.VisualStudio.TextManager.Interop.8.0.dll</HintPath>
+ <Private>True</Private>
+ <Private>False</Private>
+ </Reference>
+ <Reference Include="PresentationCore" />
+ <Reference Include="PresentationFramework" />
+ <Reference Include="stdole, Version=7.0.3300.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+ <HintPath>..\packages\VSSDK.DTE.7.0.3\lib\net20\stdole.dll</HintPath>
+ <EmbedInteropTypes>False</EmbedInteropTypes>
+ </Reference>
<Reference Include="System" />
+ <Reference Include="System.ComponentModel.Composition" />
<Reference Include="System.Core" />
<Reference Include="System.Data" />
<Reference Include="System.Design" />
@@ -81,6 +143,7 @@
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
+ <Reference Include="WindowsBase" />
</ItemGroup>
<ItemGroup>
<COMReference Include="EnvDTE">
@@ -165,6 +228,7 @@
</ItemGroup>
<ItemGroup>
<None Include="Key.snk" />
+ <None Include="packages.config" />
<None Include="source.extension.vsixmanifest">
<SubType>Designer</SubType>
</None>
@@ -219,7 +283,7 @@
<Import Project="$(VSToolsPath)\VSSDK\Microsoft.VsSDK.targets" Condition="'$(VSToolsPath)' != ''" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\VSSDK\Microsoft.VsSDK.targets" Condition="false" />
<PropertyGroup>
- <PreBuildEvent>if not exist $(ProjectDir)Key.snk ("$(FrameworkSDKDir)Bin\NETFX 4.5.1 Tools\sn.exe" -k $(ProjectDir)Key.snk)</PreBuildEvent>
+ <PreBuildEvent>if not exist $(ProjectDir)Key.snk ("$(FrameworkSDKDir)Bin\NETFX 4.6 Tools\sn.exe" -k $(ProjectDir)Key.snk)</PreBuildEvent>
</PropertyGroup>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
@@ -228,4 +292,4 @@
<Target Name="AfterBuild">
</Target>
-->
-</Project>
+</Project> \ No newline at end of file
diff --git a/tools/clang-format-vs/ClangFormat/ClangFormat.vsct b/tools/clang-format-vs/ClangFormat/ClangFormat.vsct
index 3e3e22e67d42..798957740d54 100644
--- a/tools/clang-format-vs/ClangFormat/ClangFormat.vsct
+++ b/tools/clang-format-vs/ClangFormat/ClangFormat.vsct
@@ -61,15 +61,21 @@
<CommandFlag>DynamicVisibility</CommandFlag>
If you do not want an image next to your command, remove the Icon node /> -->
- <Button guid="guidClangFormatCmdSet" id="cmdidClangFormat" priority="0x0100" type="Button">
+ <Button guid="guidClangFormatCmdSet" id="cmdidClangFormatSelection" priority="0x0100" type="Button">
<Parent guid="guidClangFormatCmdSet" id="MyMenuGroup" />
<Icon guid="guidImages" id="bmpPic1" />
<Strings>
- <ButtonText>ClangFormat</ButtonText>
+ <ButtonText>Clang Format Selection</ButtonText>
</Strings>
</Button>
-
+ <Button guid="guidClangFormatCmdSet" id="cmdidClangFormatDocument" priority="0x0101" type="Button">
+ <Parent guid="guidClangFormatCmdSet" id="MyMenuGroup" />
+ <Icon guid="guidImages" id="bmpPic2" />
+ <Strings>
+ <ButtonText>Clang Format Document</ButtonText>
+ </Strings>
+ </Button>
</Buttons>
@@ -88,7 +94,8 @@
<KeyBindings>
- <KeyBinding guid="guidClangFormatCmdSet" id="cmdidClangFormat" editor="guidTextEditor" key1="R" mod1="Control" key2="F" mod2="Control"/>
+ <KeyBinding guid="guidClangFormatCmdSet" id="cmdidClangFormatSelection" editor="guidTextEditor" key1="R" mod1="Control" key2="F" mod2="Control"/>
+ <KeyBinding guid="guidClangFormatCmdSet" id="cmdidClangFormatDocument" editor="guidTextEditor" key1="R" mod1="Control" key2="D" mod2="Control"/>
</KeyBindings>
@@ -101,7 +108,8 @@
<GuidSymbol name="guidClangFormatCmdSet" value="{e39cbab1-0f96-4022-a2bc-da5a9db7eb78}">
<IDSymbol name="MyMenuGroup" value="0x1020" />
- <IDSymbol name="cmdidClangFormat" value="0x0100" />
+ <IDSymbol name="cmdidClangFormatSelection" value="0x0100" />
+ <IDSymbol name="cmdidClangFormatDocument" value="0x0101" />
</GuidSymbol>
<GuidSymbol name="guidTextEditor" value="{8B382828-6202-11d1-8870-0000F87579D2}" />
diff --git a/tools/clang-format-vs/ClangFormat/ClangFormatPackage.cs b/tools/clang-format-vs/ClangFormat/ClangFormatPackage.cs
index 6af2fd177f0f..c7eac42211ad 100644
--- a/tools/clang-format-vs/ClangFormat/ClangFormatPackage.cs
+++ b/tools/clang-format-vs/ClangFormat/ClangFormatPackage.cs
@@ -180,15 +180,44 @@ namespace LLVM.ClangFormat
var commandService = GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
if (commandService != null)
{
- var menuCommandID = new CommandID(GuidList.guidClangFormatCmdSet, (int)PkgCmdIDList.cmdidClangFormat);
- var menuItem = new MenuCommand(MenuItemCallback, menuCommandID);
- commandService.AddCommand(menuItem);
+ {
+ var menuCommandID = new CommandID(GuidList.guidClangFormatCmdSet, (int)PkgCmdIDList.cmdidClangFormatSelection);
+ var menuItem = new MenuCommand(MenuItemCallback, menuCommandID);
+ commandService.AddCommand(menuItem);
+ }
+
+ {
+ var menuCommandID = new CommandID(GuidList.guidClangFormatCmdSet, (int)PkgCmdIDList.cmdidClangFormatDocument);
+ var menuItem = new MenuCommand(MenuItemCallback, menuCommandID);
+ commandService.AddCommand(menuItem);
+ }
}
}
#endregion
private void MenuItemCallback(object sender, EventArgs args)
{
+ var mc = sender as System.ComponentModel.Design.MenuCommand;
+ if (mc == null)
+ return;
+
+ switch (mc.CommandID.ID)
+ {
+ case (int)PkgCmdIDList.cmdidClangFormatSelection:
+ FormatSelection();
+ break;
+
+ case (int)PkgCmdIDList.cmdidClangFormatDocument:
+ FormatDocument();
+ break;
+ }
+ }
+
+ /// <summary>
+ /// Runs clang-format on the current selection
+ /// </summary>
+ private void FormatSelection()
+ {
IWpfTextView view = GetCurrentView();
if (view == null)
// We're not in a text view.
@@ -197,24 +226,40 @@ namespace LLVM.ClangFormat
int start = view.Selection.Start.Position.GetContainingLine().Start.Position;
int end = view.Selection.End.Position.GetContainingLine().End.Position;
int length = end - start;
+
// clang-format doesn't support formatting a range that starts at the end
// of the file.
if (start >= text.Length && text.Length > 0)
start = text.Length - 1;
string path = GetDocumentParent(view);
string filePath = GetDocumentPath(view);
+
+ RunClangFormatAndApplyReplacements(text, start, length, path, filePath, view);
+ }
+
+ /// <summary>
+ /// Runs clang-format on the current document
+ /// </summary>
+ private void FormatDocument()
+ {
+ IWpfTextView view = GetCurrentView();
+ if (view == null)
+ // We're not in a text view.
+ return;
+
+ string filePath = GetDocumentPath(view);
+ var path = Path.GetDirectoryName(filePath);
+ string text = view.TextBuffer.CurrentSnapshot.GetText();
+
+ RunClangFormatAndApplyReplacements(text, 0, text.Length, path, filePath, view);
+ }
+
+ private void RunClangFormatAndApplyReplacements(string text, int offset, int length, string path, string filePath, IWpfTextView view)
+ {
try
{
- var root = XElement.Parse(RunClangFormat(text, start, length, path, filePath));
- var edit = view.TextBuffer.CreateEdit();
- foreach (XElement replacement in root.Descendants("replacement"))
- {
- var span = new Span(
- int.Parse(replacement.Attribute("offset").Value),
- int.Parse(replacement.Attribute("length").Value));
- edit.Replace(span, replacement.Value);
- }
- edit.Apply();
+ string replacements = RunClangFormat(text, offset, length, path, filePath);
+ ApplyClangFormatReplacements(replacements, view);
}
catch (Exception e)
{
@@ -305,6 +350,27 @@ namespace LLVM.ClangFormat
}
/// <summary>
+ /// Applies the clang-format replacements (xml) to the current view
+ /// </summary>
+ private void ApplyClangFormatReplacements(string replacements, IWpfTextView view)
+ {
+ // clang-format returns no replacements if input text is empty
+ if (replacements.Length == 0)
+ return;
+
+ var root = XElement.Parse(replacements);
+ var edit = view.TextBuffer.CreateEdit();
+ foreach (XElement replacement in root.Descendants("replacement"))
+ {
+ var span = new Span(
+ int.Parse(replacement.Attribute("offset").Value),
+ int.Parse(replacement.Attribute("length").Value));
+ edit.Replace(span, replacement.Value);
+ }
+ edit.Apply();
+ }
+
+ /// <summary>
/// Returns the currently active view if it is a IWpfTextView.
/// </summary>
private IWpfTextView GetCurrentView()
diff --git a/tools/clang-format-vs/ClangFormat/PkgCmdID.cs b/tools/clang-format-vs/ClangFormat/PkgCmdID.cs
index bb6b4559a98d..fcc31ee95b1e 100644
--- a/tools/clang-format-vs/ClangFormat/PkgCmdID.cs
+++ b/tools/clang-format-vs/ClangFormat/PkgCmdID.cs
@@ -2,6 +2,7 @@
{
static class PkgCmdIDList
{
- public const uint cmdidClangFormat = 0x100;
+ public const uint cmdidClangFormatSelection = 0x100;
+ public const uint cmdidClangFormatDocument = 0x101;
};
} \ No newline at end of file
diff --git a/tools/clang-format-vs/ClangFormat/Resources.Designer.cs b/tools/clang-format-vs/ClangFormat/Resources.Designer.cs
index a90251771da9..e3129b3db83a 100644
--- a/tools/clang-format-vs/ClangFormat/Resources.Designer.cs
+++ b/tools/clang-format-vs/ClangFormat/Resources.Designer.cs
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
-// Runtime Version:4.0.30319.34209
+// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
diff --git a/tools/clang-format-vs/ClangFormat/packages.config b/tools/clang-format-vs/ClangFormat/packages.config
new file mode 100644
index 000000000000..38f64ed3a615
--- /dev/null
+++ b/tools/clang-format-vs/ClangFormat/packages.config
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="VSSDK.CoreUtility" version="10.0.4" targetFramework="net40" />
+ <package id="VSSDK.CoreUtility.10" version="10.0.4" targetFramework="net40" />
+ <package id="VSSDK.DTE" version="7.0.3" targetFramework="net40" />
+ <package id="VSSDK.Editor" version="10.0.4" targetFramework="net40" />
+ <package id="VSSDK.Editor.10" version="10.0.4" targetFramework="net40" />
+ <package id="VSSDK.IDE" version="7.0.4" targetFramework="net40" />
+ <package id="VSSDK.IDE.10" version="10.0.4" targetFramework="net40" />
+ <package id="VSSDK.IDE.8" version="8.0.4" targetFramework="net40" />
+ <package id="VSSDK.IDE.9" version="9.0.3" targetFramework="net40" />
+ <package id="VSSDK.OLE.Interop" version="7.0.4" targetFramework="net40" />
+ <package id="VSSDK.Shell.10" version="10.0.3" targetFramework="net40" />
+ <package id="VSSDK.Shell.Immutable.10" version="10.0.3" targetFramework="net40" />
+ <package id="VSSDK.Shell.Interop" version="7.0.4" targetFramework="net40" />
+ <package id="VSSDK.Shell.Interop.8" version="8.0.3" targetFramework="net40" />
+ <package id="VSSDK.Shell.Interop.9" version="9.0.3" targetFramework="net40" />
+ <package id="VSSDK.Text" version="10.0.4" targetFramework="net40" />
+ <package id="VSSDK.Text.10" version="10.0.4" targetFramework="net40" />
+ <package id="VSSDK.TextManager.Interop" version="7.0.4" targetFramework="net40" />
+ <package id="VSSDK.TextManager.Interop.8" version="8.0.4" targetFramework="net40" />
+</packages> \ No newline at end of file
diff --git a/tools/clang-format-vs/README.txt b/tools/clang-format-vs/README.txt
index b23355d0cebc..84e0b451f018 100644
--- a/tools/clang-format-vs/README.txt
+++ b/tools/clang-format-vs/README.txt
@@ -2,16 +2,50 @@ This directory contains a VSPackage project to generate a Visual Studio extensio
for clang-format.
Build prerequisites are:
-- Visual Studio 2013 Professional
-- Visual Studio 2013 SDK
-- Visual Studio 2010 Professional (?)
-- Visual Studio 2010 SDK (?)
+- Visual Studio 2015
+- Extensions SDK (you'll be prompted to install it if you open ClangFormat.sln)
-The extension is built using CMake by setting BUILD_CLANG_FORMAT_VS_PLUGIN=ON
-when configuring a Clang build, and building the clang_format_vsix target.
+The extension is built using CMake to generate the usual LLVM.sln by setting
+the following CMake vars:
+
+- BUILD_CLANG_FORMAT_VS_PLUGIN=ON
+
+- NUGET_EXE_PATH=path/to/nuget_dir (unless nuget.exe is already available in PATH)
+
+example:
+ cd /d C:\code\llvm
+ mkdir build & cd build
+ cmake -DBUILD_CLANG_FORMAT_VS_PLUGIN=ON -DNUGET_EXE_PATH=C:\nuget ..
+
+Once LLVM.sln is generated, build the clang_format_vsix target, which will build
+ClangFormat.sln, the C# extension application.
The CMake build will copy clang-format.exe and LICENSE.TXT into the ClangFormat/
directory so they can be bundled with the plug-in, as well as creating
ClangFormat/source.extension.vsixmanifest. Once the plug-in has been built with
CMake once, it can be built manually from the ClangFormat.sln solution in Visual
Studio.
+
+===========
+ Debugging
+===========
+
+Once you've built the clang_format_vsix project from LLVM.sln at least once,
+open ClangFormat.sln in Visual Studio, then:
+
+- Make sure the "Debug" target is selected
+- Open the ClangFormat project properties
+- Select the Debug tab
+- Set "Start external program:" to where your devenv.exe is installed. Typically
+ it's "C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\devenv.exe"
+- Set "Command line arguments" to: /rootsuffix Exp
+- You can now set breakpoints if you like
+- Press F5 to build and run with debugger
+
+If all goes well, a new instance of Visual Studio will be launched in a special
+mode where it uses the experimental hive instead of the normal configuration hive.
+By default, when you build a VSIX project in Visual Studio, it auto-registers the
+extension in the experimental hive, allowing you to test it. In the new Visual Studio
+instance, open or create a C++ solution, and you should now see the Clang Format
+entries in the Tool menu. You can test it out, and any breakpoints you set will be
+hit where you can debug as usual.
diff --git a/tools/clang-format/ClangFormat.cpp b/tools/clang-format/ClangFormat.cpp
index 27577a5a336a..6c50daf53834 100644
--- a/tools/clang-format/ClangFormat.cpp
+++ b/tools/clang-format/ClangFormat.cpp
@@ -20,9 +20,7 @@
#include "clang/Basic/Version.h"
#include "clang/Format/Format.h"
#include "clang/Rewrite/Core/Rewriter.h"
-#include "llvm/ADT/StringMap.h"
#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Debug.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Signals.h"
@@ -251,7 +249,8 @@ static bool format(StringRef FileName) {
if (fillRanges(Code.get(), Ranges))
return true;
StringRef AssumedFileName = (FileName == "-") ? AssumeFileName : FileName;
- FormatStyle FormatStyle = getStyle(Style, AssumedFileName, FallbackStyle);
+ FormatStyle FormatStyle =
+ getStyle(Style, AssumedFileName, FallbackStyle, Code->getBuffer());
if (SortIncludes.getNumOccurrences() != 0)
FormatStyle.SortIncludes = SortIncludes;
unsigned CursorPosition = Cursor;
@@ -262,23 +261,22 @@ static bool format(StringRef FileName) {
llvm::errs() << llvm::toString(ChangedCode.takeError()) << "\n";
return true;
}
- for (const auto &R : Replaces)
- Ranges.push_back({R.getOffset(), R.getLength()});
-
+ // Get new affected ranges after sorting `#includes`.
+ Ranges = tooling::calculateRangesAfterReplacements(Replaces, Ranges);
bool IncompleteFormat = false;
Replacements FormatChanges = reformat(FormatStyle, *ChangedCode, Ranges,
AssumedFileName, &IncompleteFormat);
- Replaces = tooling::mergeReplacements(Replaces, FormatChanges);
+ Replaces = Replaces.merge(FormatChanges);
if (OutputXML) {
outs() << "<?xml version='1.0'?>\n<replacements "
"xml:space='preserve' incomplete_format='"
<< (IncompleteFormat ? "true" : "false") << "'>\n";
if (Cursor.getNumOccurrences() != 0)
outs() << "<cursor>"
- << tooling::shiftedCodePosition(FormatChanges, CursorPosition)
+ << FormatChanges.getShiftedCodePosition(CursorPosition)
<< "</cursor>\n";
- outputReplacementsXML(Replaces);
+ outputReplacementsXML(Replaces);
outs() << "</replacements>\n";
} else {
IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
@@ -300,7 +298,7 @@ static bool format(StringRef FileName) {
} else {
if (Cursor.getNumOccurrences() != 0)
outs() << "{ \"Cursor\": "
- << tooling::shiftedCodePosition(FormatChanges, CursorPosition)
+ << FormatChanges.getShiftedCodePosition(CursorPosition)
<< ", \"IncompleteFormat\": "
<< (IncompleteFormat ? "true" : "false") << " }\n";
Rewrite.getEditBuffer(ID).write(outs());
diff --git a/tools/clang-format/clang-format-diff.py b/tools/clang-format/clang-format-diff.py
index 5e728f547169..ffa30e70ddc3 100755
--- a/tools/clang-format/clang-format-diff.py
+++ b/tools/clang-format/clang-format-diff.py
@@ -17,7 +17,7 @@ This script reads input from a unified diff and reformats all the changed
lines. This is useful to reformat all the lines touched by a specific patch.
Example usage for git/svn users:
- git diff -U0 HEAD^ | clang-format-diff.py -p1 -i
+ git diff -U0 --no-color HEAD^ | clang-format-diff.py -p1 -i
svn diff --diff-cmd=diff -x-U0 | clang-format-diff.py -i
"""
diff --git a/tools/clang-format/clang-format.el b/tools/clang-format/clang-format.el
index ca461444e226..0ac2da3ad29a 100644
--- a/tools/clang-format/clang-format.el
+++ b/tools/clang-format/clang-format.el
@@ -1,4 +1,4 @@
-;;; clang-format.el --- Format code using clang-format
+;;; clang-format.el --- Format code using clang-format -*- lexical-binding: t; -*-
;; Keywords: tools, c
;; Package-Requires: ((cl-lib "0.3"))
@@ -15,7 +15,7 @@
;; M-x package-install clang-format
;;
;; when ("melpa" . "http://melpa.org/packages/") is included in
-;; `package-archives'. Alternatively, ensure the directory of this
+;; `package-archives'. Alternatively, ensure the directory of this
;; file is in your `load-path' and add
;;
;; (require 'clang-format)
@@ -42,7 +42,7 @@
A string containing the name or the full path of the executable."
:group 'clang-format
- :type 'string
+ :type '(file :must-match t)
:risky t)
(defcustom clang-format-style "file"
@@ -93,15 +93,32 @@ of the buffer."
(list replacements cursor (string= incomplete-format "true"))))
(defun clang-format--replace (offset length &optional text)
- (let ((start (byte-to-position (1+ offset)))
- (end (byte-to-position (+ 1 offset length))))
+ "Replace the region defined by OFFSET and LENGTH with TEXT.
+OFFSET and LENGTH are measured in bytes, not characters. OFFSET
+is a zero-based file offset."
+ (let ((start (clang-format--filepos-to-bufferpos offset 'exact))
+ (end (clang-format--filepos-to-bufferpos (+ offset length) 'exact)))
(goto-char start)
(delete-region start end)
(when text
(insert text))))
+;; ‘bufferpos-to-filepos’ and ‘filepos-to-bufferpos’ are new in Emacs 25.1.
+;; Provide fallbacks for older versions.
+(defalias 'clang-format--bufferpos-to-filepos
+ (if (fboundp 'bufferpos-to-filepos)
+ 'bufferpos-to-filepos
+ (lambda (position &optional _quality _coding-system)
+ (1- (position-bytes position)))))
+
+(defalias 'clang-format--filepos-to-bufferpos
+ (if (fboundp 'filepos-to-bufferpos)
+ 'filepos-to-bufferpos
+ (lambda (byte &optional _quality _coding-system)
+ (byte-to-position (1+ byte)))))
+
;;;###autoload
-(defun clang-format-region (char-start char-end &optional style)
+(defun clang-format-region (start end &optional style)
"Use clang-format to format the code between START and END according to STYLE.
If called interactively uses the region or the current statement if there
is no active region. If no style is given uses `clang-format-style'."
@@ -113,51 +130,41 @@ is no active region. If no style is given uses `clang-format-style'."
(unless style
(setq style clang-format-style))
- (let ((start (1- (position-bytes char-start)))
- (end (1- (position-bytes char-end)))
- (cursor (1- (position-bytes (point))))
+ (let ((file-start (clang-format--bufferpos-to-filepos start 'approximate))
+ (file-end (clang-format--bufferpos-to-filepos end 'approximate))
+ (cursor (clang-format--bufferpos-to-filepos (point) 'exact))
(temp-buffer (generate-new-buffer " *clang-format-temp*"))
(temp-file (make-temp-file "clang-format")))
(unwind-protect
- (let (status stderr operations)
- (setq status
- (call-process-region
- (point-min) (point-max) clang-format-executable
- nil `(,temp-buffer ,temp-file) nil
-
- "-output-replacements-xml"
- "-assume-filename" (or (buffer-file-name) "")
- "-style" style
- "-offset" (number-to-string start)
- "-length" (number-to-string (- end start))
- "-cursor" (number-to-string cursor)))
- (setq stderr
- (with-temp-buffer
- (insert-file-contents temp-file)
- (when (> (point-max) (point-min))
- (insert ": "))
- (buffer-substring-no-properties
- (point-min) (line-end-position))))
-
+ (let ((status (call-process-region
+ nil nil clang-format-executable
+ nil `(,temp-buffer ,temp-file) nil
+
+ "-output-replacements-xml"
+ "-assume-filename" (or (buffer-file-name) "")
+ "-style" style
+ "-offset" (number-to-string file-start)
+ "-length" (number-to-string (- file-end file-start))
+ "-cursor" (number-to-string cursor)))
+ (stderr (with-temp-buffer
+ (unless (zerop (cadr (insert-file-contents temp-file)))
+ (insert ": "))
+ (buffer-substring-no-properties
+ (point-min) (line-end-position)))))
(cond
((stringp status)
(error "(clang-format killed by signal %s%s)" status stderr))
- ((not (equal 0 status))
+ ((not (zerop status))
(error "(clang-format failed with code %d%s)" status stderr)))
- (with-current-buffer temp-buffer
- (setq operations (clang-format--extract (car (xml-parse-region)))))
-
- (let ((replacements (nth 0 operations))
- (cursor (nth 1 operations))
- (incomplete-format (nth 2 operations)))
+ (cl-destructuring-bind (replacements cursor incomplete-format)
+ (with-current-buffer temp-buffer
+ (clang-format--extract (car (xml-parse-region))))
(save-excursion
- (mapc (lambda (rpl)
- (apply #'clang-format--replace rpl))
- replacements))
+ (dolist (rpl replacements)
+ (apply #'clang-format--replace rpl)))
(when cursor
- (goto-char (byte-to-position (1+ cursor))))
- (message "%s" incomplete-format)
+ (goto-char (clang-format--filepos-to-bufferpos cursor 'exact)))
(if incomplete-format
(message "(clang-format: incomplete (syntax errors)%s)" stderr)
(message "(clang-format: success%s)" stderr))))
diff --git a/tools/clang-format/clang-format.py b/tools/clang-format/clang-format.py
index 5cb41fcfa371..ae8a6ebf74e9 100644
--- a/tools/clang-format/clang-format.py
+++ b/tools/clang-format/clang-format.py
@@ -25,9 +25,11 @@
#
# It operates on the current, potentially unsaved buffer and does not create
# or save any files. To revert a formatting, just undo.
+from __future__ import print_function
import difflib
import json
+import platform
import subprocess
import sys
import vim
@@ -47,9 +49,15 @@ fallback_style = None
if vim.eval('exists("g:clang_format_fallback_style")') == "1":
fallback_style = vim.eval('g:clang_format_fallback_style')
+def get_buffer(encoding):
+ if platform.python_version_tuple()[0] == '3':
+ return vim.current.buffer
+ return [ line.decode(encoding) for line in vim.current.buffer ]
+
def main():
# Get the current text.
- buf = vim.current.buffer
+ encoding = vim.eval("&encoding")
+ buf = get_buffer(encoding)
text = '\n'.join(buf)
# Determine range to format.
@@ -61,7 +69,7 @@ def main():
# Determine the cursor position.
cursor = int(vim.eval('line2byte(line("."))+col(".")')) - 2
if cursor < 0:
- print 'Couldn\'t determine cursor position. Is your file empty?'
+ print('Couldn\'t determine cursor position. Is your file empty?')
return
# Avoid flashing an ugly, ugly cmd prompt on Windows when invoking clang-format.
@@ -82,25 +90,27 @@ def main():
p = subprocess.Popen(command,
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
stdin=subprocess.PIPE, startupinfo=startupinfo)
- stdout, stderr = p.communicate(input=text)
+ stdout, stderr = p.communicate(input=text.encode(encoding))
# If successful, replace buffer contents.
if stderr:
- print stderr
+ print(stderr)
if not stdout:
- print ('No output from clang-format (crashed?).\n' +
- 'Please report to bugs.llvm.org.')
+ print(
+ 'No output from clang-format (crashed?).\n'
+ 'Please report to bugs.llvm.org.'
+ )
else:
- lines = stdout.split('\n')
+ lines = stdout.decode(encoding).split('\n')
output = json.loads(lines[0])
lines = lines[1:]
- sequence = difflib.SequenceMatcher(None, vim.current.buffer, lines)
+ sequence = difflib.SequenceMatcher(None, buf, lines)
for op in reversed(sequence.get_opcodes()):
if op[0] is not 'equal':
vim.current.buffer[op[1]:op[2]] = lines[op[3]:op[4]]
if output.get('IncompleteFormat'):
- print 'clang-format: incomplete (syntax errors)'
+ print('clang-format: incomplete (syntax errors)')
vim.command('goto %d' % (output['Cursor'] + 1))
main()
diff --git a/tools/clang-format/git-clang-format b/tools/clang-format/git-clang-format
index 0c45762ea515..74fd451a847b 100755
--- a/tools/clang-format/git-clang-format
+++ b/tools/clang-format/git-clang-format
@@ -32,12 +32,15 @@ import re
import subprocess
import sys
-usage = 'git clang-format [OPTIONS] [<commit>] [--] [<file>...]'
+usage = 'git clang-format [OPTIONS] [<commit>] [<commit>] [--] [<file>...]'
desc = '''
-Run clang-format on all lines that differ between the working directory
-and <commit>, which defaults to HEAD. Changes are only applied to the working
-directory.
+If zero or one commits are given, run clang-format on all lines that differ
+between the working directory and <commit>, which defaults to HEAD. Changes are
+only applied to the working directory.
+
+If two commits are given (requires --diff), run clang-format on all lines in the
+second <commit> that differ from the first <commit>.
The following git-config settings set the default of the corresponding option:
clangFormat.binary
@@ -77,6 +80,7 @@ def main():
'cc', 'cp', 'cpp', 'c++', 'cxx', 'hpp', # C++
# Other languages that clang-format supports
'proto', 'protodevel', # Protocol Buffers
+ 'java', # Java
'js', # JavaScript
'ts', # TypeScript
])
@@ -120,8 +124,14 @@ def main():
opts.verbose -= opts.quiet
del opts.quiet
- commit, files = interpret_args(opts.args, dash_dash, opts.commit)
- changed_lines = compute_diff_and_extract_lines(commit, files)
+ commits, files = interpret_args(opts.args, dash_dash, opts.commit)
+ if len(commits) > 1:
+ if not opts.diff:
+ die('--diff is required when two commits are given')
+ else:
+ if len(commits) > 2:
+ die('at most two commits allowed; %d given' % len(commits))
+ changed_lines = compute_diff_and_extract_lines(commits, files)
if opts.verbose >= 1:
ignored_files = set(changed_lines)
filter_by_extension(changed_lines, opts.extensions.lower().split(','))
@@ -141,10 +151,17 @@ def main():
# The computed diff outputs absolute paths, so we must cd before accessing
# those files.
cd_to_toplevel()
- old_tree = create_tree_from_workdir(changed_lines)
- new_tree = run_clang_format_and_save_to_tree(changed_lines,
- binary=opts.binary,
- style=opts.style)
+ if len(commits) > 1:
+ old_tree = commits[1]
+ new_tree = run_clang_format_and_save_to_tree(changed_lines,
+ revision=commits[1],
+ binary=opts.binary,
+ style=opts.style)
+ else:
+ old_tree = create_tree_from_workdir(changed_lines)
+ new_tree = run_clang_format_and_save_to_tree(changed_lines,
+ binary=opts.binary,
+ style=opts.style)
if opts.verbose >= 1:
print 'old tree:', old_tree
print 'new tree:', new_tree
@@ -181,40 +198,41 @@ def load_git_config(non_string_options=None):
def interpret_args(args, dash_dash, default_commit):
- """Interpret `args` as "[commit] [--] [files...]" and return (commit, files).
+ """Interpret `args` as "[commits] [--] [files]" and return (commits, files).
It is assumed that "--" and everything that follows has been removed from
args and placed in `dash_dash`.
- If "--" is present (i.e., `dash_dash` is non-empty), the argument to its
- left (if present) is taken as commit. Otherwise, the first argument is
- checked if it is a commit or a file. If commit is not given,
- `default_commit` is used."""
+ If "--" is present (i.e., `dash_dash` is non-empty), the arguments to its
+ left (if present) are taken as commits. Otherwise, the arguments are checked
+ from left to right if they are commits or files. If commits are not given,
+ a list with `default_commit` is used."""
if dash_dash:
if len(args) == 0:
- commit = default_commit
- elif len(args) > 1:
- die('at most one commit allowed; %d given' % len(args))
+ commits = [default_commit]
else:
- commit = args[0]
- object_type = get_object_type(commit)
- if object_type not in ('commit', 'tag'):
- if object_type is None:
- die("'%s' is not a commit" % commit)
- else:
- die("'%s' is a %s, but a commit was expected" % (commit, object_type))
+ commits = args
+ for commit in commits:
+ object_type = get_object_type(commit)
+ if object_type not in ('commit', 'tag'):
+ if object_type is None:
+ die("'%s' is not a commit" % commit)
+ else:
+ die("'%s' is a %s, but a commit was expected" % (commit, object_type))
files = dash_dash[1:]
elif args:
- if disambiguate_revision(args[0]):
- commit = args[0]
- files = args[1:]
- else:
- commit = default_commit
- files = args
+ commits = []
+ while args:
+ if not disambiguate_revision(args[0]):
+ break
+ commits.append(args.pop(0))
+ if not commits:
+ commits = [default_commit]
+ files = args
else:
- commit = default_commit
+ commits = [default_commit]
files = []
- return commit, files
+ return commits, files
def disambiguate_revision(value):
@@ -242,9 +260,9 @@ def get_object_type(value):
return stdout.strip()
-def compute_diff_and_extract_lines(commit, files):
+def compute_diff_and_extract_lines(commits, files):
"""Calls compute_diff() followed by extract_lines()."""
- diff_process = compute_diff(commit, files)
+ diff_process = compute_diff(commits, files)
changed_lines = extract_lines(diff_process.stdout)
diff_process.stdout.close()
diff_process.wait()
@@ -254,13 +272,17 @@ def compute_diff_and_extract_lines(commit, files):
return changed_lines
-def compute_diff(commit, files):
- """Return a subprocess object producing the diff from `commit`.
+def compute_diff(commits, files):
+ """Return a subprocess object producing the diff from `commits`.
The return value's `stdin` file object will produce a patch with the
- differences between the working directory and `commit`, filtered on `files`
- (if non-empty). Zero context lines are used in the patch."""
- cmd = ['git', 'diff-index', '-p', '-U0', commit, '--']
+ differences between the working directory and the first commit if a single
+ one was specified, or the difference between both specified commits, filtered
+ on `files` (if non-empty). Zero context lines are used in the patch."""
+ git_tool = 'diff-index'
+ if len(commits) > 1:
+ git_tool = 'diff-tree'
+ cmd = ['git', git_tool, '-p', '-U0'] + commits + ['--']
cmd.extend(files)
p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
p.stdin.close()
@@ -317,15 +339,26 @@ def create_tree_from_workdir(filenames):
return create_tree(filenames, '--stdin')
-def run_clang_format_and_save_to_tree(changed_lines, binary='clang-format',
- style=None):
+def run_clang_format_and_save_to_tree(changed_lines, revision=None,
+ binary='clang-format', style=None):
"""Run clang-format on each file and save the result to a git tree.
Returns the object ID (SHA-1) of the created tree."""
def index_info_generator():
for filename, line_ranges in changed_lines.iteritems():
- mode = oct(os.stat(filename).st_mode)
- blob_id = clang_format_to_blob(filename, line_ranges, binary=binary,
+ if revision:
+ git_metadata_cmd = ['git', 'ls-tree',
+ '%s:%s' % (revision, os.path.dirname(filename)),
+ os.path.basename(filename)]
+ git_metadata = subprocess.Popen(git_metadata_cmd, stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE)
+ stdout = git_metadata.communicate()[0]
+ mode = oct(int(stdout.split()[0], 8))
+ else:
+ mode = oct(os.stat(filename).st_mode)
+ blob_id = clang_format_to_blob(filename, line_ranges,
+ revision=revision,
+ binary=binary,
style=style)
yield '%s %s\t%s' % (mode, blob_id, filename)
return create_tree(index_info_generator(), '--index-info')
@@ -351,26 +384,42 @@ def create_tree(input_lines, mode):
return tree_id
-def clang_format_to_blob(filename, line_ranges, binary='clang-format',
- style=None):
+def clang_format_to_blob(filename, line_ranges, revision=None,
+ binary='clang-format', style=None):
"""Run clang-format on the given file and save the result to a git blob.
+ Runs on the file in `revision` if not None, or on the file in the working
+ directory if `revision` is None.
+
Returns the object ID (SHA-1) of the created blob."""
- clang_format_cmd = [binary, filename]
+ clang_format_cmd = [binary]
if style:
clang_format_cmd.extend(['-style='+style])
clang_format_cmd.extend([
'-lines=%s:%s' % (start_line, start_line+line_count-1)
for start_line, line_count in line_ranges])
+ if revision:
+ clang_format_cmd.extend(['-assume-filename='+filename])
+ git_show_cmd = ['git', 'cat-file', 'blob', '%s:%s' % (revision, filename)]
+ git_show = subprocess.Popen(git_show_cmd, stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE)
+ git_show.stdin.close()
+ clang_format_stdin = git_show.stdout
+ else:
+ clang_format_cmd.extend([filename])
+ git_show = None
+ clang_format_stdin = subprocess.PIPE
try:
- clang_format = subprocess.Popen(clang_format_cmd, stdin=subprocess.PIPE,
+ clang_format = subprocess.Popen(clang_format_cmd, stdin=clang_format_stdin,
stdout=subprocess.PIPE)
+ if clang_format_stdin == subprocess.PIPE:
+ clang_format_stdin = clang_format.stdin
except OSError as e:
if e.errno == errno.ENOENT:
die('cannot find executable "%s"' % binary)
else:
raise
- clang_format.stdin.close()
+ clang_format_stdin.close()
hash_object_cmd = ['git', 'hash-object', '-w', '--path='+filename, '--stdin']
hash_object = subprocess.Popen(hash_object_cmd, stdin=clang_format.stdout,
stdout=subprocess.PIPE)
@@ -380,6 +429,8 @@ def clang_format_to_blob(filename, line_ranges, binary='clang-format',
die('`%s` failed' % ' '.join(hash_object_cmd))
if clang_format.wait() != 0:
die('`%s` failed' % ' '.join(clang_format_cmd))
+ if git_show and git_show.wait() != 0:
+ die('`%s` failed' % ' '.join(git_show_cmd))
return stdout.rstrip('\r\n')
@@ -418,7 +469,12 @@ def print_diff(old_tree, new_tree):
# We use the porcelain 'diff' and not plumbing 'diff-tree' because the output
# is expected to be viewed by the user, and only the former does nice things
# like color and pagination.
- subprocess.check_call(['git', 'diff', old_tree, new_tree, '--'])
+ #
+ # We also only print modified files since `new_tree` only contains the files
+ # that were modified, so unmodified files would show as deleted without the
+ # filter.
+ subprocess.check_call(['git', 'diff', '--diff-filter=M', old_tree, new_tree,
+ '--'])
def apply_changes(old_tree, new_tree, force=False, patch_mode=False):
@@ -426,7 +482,8 @@ def apply_changes(old_tree, new_tree, force=False, patch_mode=False):
Bails if there are local changes in those files and not `force`. If
`patch_mode`, runs `git checkout --patch` to select hunks interactively."""
- changed_files = run('git', 'diff-tree', '-r', '-z', '--name-only', old_tree,
+ changed_files = run('git', 'diff-tree', '--diff-filter=M', '-r', '-z',
+ '--name-only', old_tree,
new_tree).rstrip('\0').split('\0')
if not force:
unstaged_files = run('git', 'diff-files', '--name-status', *changed_files)
diff --git a/tools/clang-fuzzer/ClangFuzzer.cpp b/tools/clang-fuzzer/ClangFuzzer.cpp
index d07cf5027b2a..afe57d4a666c 100644
--- a/tools/clang-fuzzer/ClangFuzzer.cpp
+++ b/tools/clang-fuzzer/ClangFuzzer.cpp
@@ -16,6 +16,7 @@
#include "clang/Tooling/Tooling.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/PreprocessorOptions.h"
#include "llvm/Option/Option.h"
using namespace clang;
diff --git a/tools/clang-import-test/CMakeLists.txt b/tools/clang-import-test/CMakeLists.txt
new file mode 100644
index 000000000000..bd4919694a27
--- /dev/null
+++ b/tools/clang-import-test/CMakeLists.txt
@@ -0,0 +1,27 @@
+set(LLVM_LINK_COMPONENTS
+ core
+ support
+)
+
+if(NOT CLANG_BUILT_STANDALONE)
+ set(tablegen_deps intrinsics_gen)
+endif()
+
+add_clang_tool(clang-import-test
+ clang-import-test.cpp
+ DEPENDS
+ ${tablegen_deps}
+ )
+
+set(CLANG_IMPORT_TEST_LIB_DEPS
+ clangAST
+ clangBasic
+ clangCodeGen
+ clangFrontend
+ clangLex
+ clangParse
+ )
+
+target_link_libraries(clang-import-test
+ ${CLANG_IMPORT_TEST_LIB_DEPS}
+ )
diff --git a/tools/clang-import-test/clang-import-test.cpp b/tools/clang-import-test/clang-import-test.cpp
new file mode 100644
index 000000000000..47598fc91813
--- /dev/null
+++ b/tools/clang-import-test/clang-import-test.cpp
@@ -0,0 +1,319 @@
+//===-- import-test.cpp - ASTImporter/ExternalASTSource testbed -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTImporter.h"
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/TargetOptions.h"
+#include "clang/CodeGen/ModuleBuilder.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/TextDiagnosticBuffer.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Parse/ParseAST.h"
+
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/Host.h"
+#include "llvm/Support/Signals.h"
+
+#include <memory>
+#include <string>
+
+using namespace clang;
+
+static llvm::cl::opt<std::string> Expression(
+ "expression", llvm::cl::Required,
+ llvm::cl::desc("Path to a file containing the expression to parse"));
+
+static llvm::cl::list<std::string>
+ Imports("import", llvm::cl::ZeroOrMore,
+ llvm::cl::desc("Path to a file containing declarations to import"));
+
+static llvm::cl::list<std::string>
+ ClangArgs("Xcc", llvm::cl::ZeroOrMore,
+ llvm::cl::desc("Argument to pass to the CompilerInvocation"),
+ llvm::cl::CommaSeparated);
+
+namespace init_convenience {
+class TestDiagnosticConsumer : public DiagnosticConsumer {
+private:
+ std::unique_ptr<TextDiagnosticBuffer> Passthrough;
+ const LangOptions *LangOpts = nullptr;
+
+public:
+ TestDiagnosticConsumer()
+ : Passthrough(llvm::make_unique<TextDiagnosticBuffer>()) {}
+
+ virtual void BeginSourceFile(const LangOptions &LangOpts,
+ const Preprocessor *PP = nullptr) override {
+ this->LangOpts = &LangOpts;
+ return Passthrough->BeginSourceFile(LangOpts, PP);
+ }
+
+ virtual void EndSourceFile() override {
+ this->LangOpts = nullptr;
+ Passthrough->EndSourceFile();
+ }
+
+ virtual bool IncludeInDiagnosticCounts() const override {
+ return Passthrough->IncludeInDiagnosticCounts();
+ }
+
+private:
+ static void PrintSourceForLocation(const SourceLocation &Loc,
+ SourceManager &SM) {
+ const char *LocData = SM.getCharacterData(Loc, /*Invalid=*/nullptr);
+ unsigned LocColumn =
+ SM.getSpellingColumnNumber(Loc, /*Invalid=*/nullptr) - 1;
+ FileID FID = SM.getFileID(Loc);
+ llvm::MemoryBuffer *Buffer = SM.getBuffer(FID, Loc, /*Invalid=*/nullptr);
+
+ assert(LocData >= Buffer->getBufferStart() &&
+ LocData < Buffer->getBufferEnd());
+
+ const char *LineBegin = LocData - LocColumn;
+
+ assert(LineBegin >= Buffer->getBufferStart());
+
+ const char *LineEnd = nullptr;
+
+ for (LineEnd = LineBegin; *LineEnd != '\n' && *LineEnd != '\r' &&
+ LineEnd < Buffer->getBufferEnd();
+ ++LineEnd)
+ ;
+
+ llvm::StringRef LineString(LineBegin, LineEnd - LineBegin);
+
+ llvm::errs() << LineString << '\n';
+ llvm::errs().indent(LocColumn);
+ llvm::errs() << '^';
+ }
+
+ virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
+ const Diagnostic &Info) override {
+ if (Info.hasSourceManager() && LangOpts) {
+ SourceManager &SM = Info.getSourceManager();
+
+ if (Info.getLocation().isValid()) {
+ Info.getLocation().print(llvm::errs(), SM);
+ llvm::errs() << ": ";
+ }
+
+ SmallString<16> DiagText;
+ Info.FormatDiagnostic(DiagText);
+ llvm::errs() << DiagText << '\n';
+
+ if (Info.getLocation().isValid()) {
+ PrintSourceForLocation(Info.getLocation(), SM);
+ }
+
+ for (const CharSourceRange &Range : Info.getRanges()) {
+ bool Invalid = true;
+ StringRef Ref = Lexer::getSourceText(Range, SM, *LangOpts, &Invalid);
+ if (!Invalid) {
+ llvm::errs() << Ref << '\n';
+ }
+ }
+ }
+ DiagnosticConsumer::HandleDiagnostic(DiagLevel, Info);
+ }
+};
+
+std::unique_ptr<CompilerInstance>
+BuildCompilerInstance(ArrayRef<const char *> ClangArgv) {
+ auto Ins = llvm::make_unique<CompilerInstance>();
+ auto DC = llvm::make_unique<TestDiagnosticConsumer>();
+ const bool ShouldOwnClient = true;
+ Ins->createDiagnostics(DC.release(), ShouldOwnClient);
+
+ auto Inv = llvm::make_unique<CompilerInvocation>();
+
+ CompilerInvocation::CreateFromArgs(*Inv, ClangArgv.data(),
+ &ClangArgv.data()[ClangArgv.size()],
+ Ins->getDiagnostics());
+
+ Inv->getLangOpts()->CPlusPlus = true;
+ Inv->getLangOpts()->CPlusPlus11 = true;
+ Inv->getHeaderSearchOpts().UseLibcxx = true;
+ Inv->getLangOpts()->Bool = true;
+ Inv->getLangOpts()->WChar = true;
+ Inv->getLangOpts()->Blocks = true;
+ Inv->getLangOpts()->DebuggerSupport = true;
+ Inv->getLangOpts()->SpellChecking = false;
+ Inv->getLangOpts()->ThreadsafeStatics = false;
+ Inv->getLangOpts()->AccessControl = false;
+ Inv->getLangOpts()->DollarIdents = true;
+ Inv->getCodeGenOpts().setDebugInfo(codegenoptions::FullDebugInfo);
+ Inv->getTargetOpts().Triple = llvm::sys::getDefaultTargetTriple();
+
+ Ins->setInvocation(Inv.release());
+
+ TargetInfo *TI = TargetInfo::CreateTargetInfo(
+ Ins->getDiagnostics(), Ins->getInvocation().TargetOpts);
+ Ins->setTarget(TI);
+ Ins->getTarget().adjust(Ins->getLangOpts());
+ Ins->createFileManager();
+ Ins->createSourceManager(Ins->getFileManager());
+ Ins->createPreprocessor(TU_Complete);
+
+ return Ins;
+}
+
+std::unique_ptr<ASTContext>
+BuildASTContext(CompilerInstance &CI, SelectorTable &ST, Builtin::Context &BC) {
+ auto AST = llvm::make_unique<ASTContext>(
+ CI.getLangOpts(), CI.getSourceManager(),
+ CI.getPreprocessor().getIdentifierTable(), ST, BC);
+ AST->InitBuiltinTypes(CI.getTarget());
+ return AST;
+}
+
+std::unique_ptr<CodeGenerator> BuildCodeGen(CompilerInstance &CI,
+ llvm::LLVMContext &LLVMCtx) {
+ StringRef ModuleName("$__module");
+ return std::unique_ptr<CodeGenerator>(CreateLLVMCodeGen(
+ CI.getDiagnostics(), ModuleName, CI.getHeaderSearchOpts(),
+ CI.getPreprocessorOpts(), CI.getCodeGenOpts(), LLVMCtx));
+}
+} // end namespace
+
+namespace {
+class TestExternalASTSource : public ExternalASTSource {
+private:
+ llvm::ArrayRef<std::unique_ptr<CompilerInstance>> ImportCIs;
+ std::map<CompilerInstance *, std::unique_ptr<ASTImporter>> ForwardImporters;
+ std::map<CompilerInstance *, std::unique_ptr<ASTImporter>> ReverseImporters;
+
+public:
+ TestExternalASTSource(
+ CompilerInstance &ExpressionCI,
+ llvm::ArrayRef<std::unique_ptr<CompilerInstance>> ImportCIs)
+ : ImportCIs(ImportCIs) {
+ for (const std::unique_ptr<CompilerInstance> &ImportCI : ImportCIs) {
+ ForwardImporters[ImportCI.get()] = llvm::make_unique<ASTImporter>(
+ ExpressionCI.getASTContext(), ExpressionCI.getFileManager(),
+ ImportCI->getASTContext(), ImportCI->getFileManager(),
+ /*MinimalImport=*/true);
+ ReverseImporters[ImportCI.get()] = llvm::make_unique<ASTImporter>(
+ ImportCI->getASTContext(), ImportCI->getFileManager(),
+ ExpressionCI.getASTContext(), ExpressionCI.getFileManager(),
+ /*MinimalImport=*/true);
+ }
+ }
+
+ bool FindExternalVisibleDeclsByName(const DeclContext *DC,
+ DeclarationName Name) override {
+ llvm::SmallVector<NamedDecl *, 1> Decls;
+
+ if (isa<TranslationUnitDecl>(DC)) {
+ for (const std::unique_ptr<CompilerInstance> &I : ImportCIs) {
+ DeclarationName FromName = ReverseImporters[I.get()]->Import(Name);
+ DeclContextLookupResult Result =
+ I->getASTContext().getTranslationUnitDecl()->lookup(FromName);
+ for (NamedDecl *FromD : Result) {
+ NamedDecl *D =
+ llvm::cast<NamedDecl>(ForwardImporters[I.get()]->Import(FromD));
+ Decls.push_back(D);
+ }
+ }
+ }
+ if (Decls.empty()) {
+ return false;
+ } else {
+ SetExternalVisibleDeclsForName(DC, Name, Decls);
+ return true;
+ }
+ }
+};
+
+void AddExternalSource(
+ CompilerInstance &CI,
+ llvm::ArrayRef<std::unique_ptr<CompilerInstance>> Imports) {
+ ASTContext &AST = CI.getASTContext();
+ auto ES = llvm::make_unique<TestExternalASTSource>(CI, Imports);
+ AST.setExternalSource(ES.release());
+ AST.getTranslationUnitDecl()->setHasExternalVisibleStorage();
+}
+
+llvm::Error ParseSource(const std::string &Path, CompilerInstance &CI,
+ CodeGenerator &CG) {
+ SourceManager &SM = CI.getSourceManager();
+ const FileEntry *FE = CI.getFileManager().getFile(Path);
+ if (!FE) {
+ return llvm::make_error<llvm::StringError>(
+ llvm::Twine("Couldn't open ", Path), std::error_code());
+ }
+ SM.setMainFileID(SM.createFileID(FE, SourceLocation(), SrcMgr::C_User));
+ ParseAST(CI.getPreprocessor(), &CG, CI.getASTContext());
+ return llvm::Error::success();
+}
+
+llvm::Expected<std::unique_ptr<CompilerInstance>>
+Parse(const std::string &Path,
+ llvm::ArrayRef<std::unique_ptr<CompilerInstance>> Imports) {
+ std::vector<const char *> ClangArgv(ClangArgs.size());
+ std::transform(ClangArgs.begin(), ClangArgs.end(), ClangArgv.begin(),
+ [](const std::string &s) -> const char * { return s.data(); });
+ std::unique_ptr<CompilerInstance> CI =
+ init_convenience::BuildCompilerInstance(ClangArgv);
+ auto ST = llvm::make_unique<SelectorTable>();
+ auto BC = llvm::make_unique<Builtin::Context>();
+ std::unique_ptr<ASTContext> AST =
+ init_convenience::BuildASTContext(*CI, *ST, *BC);
+ CI->setASTContext(AST.release());
+ AddExternalSource(*CI, Imports);
+
+ auto LLVMCtx = llvm::make_unique<llvm::LLVMContext>();
+ std::unique_ptr<CodeGenerator> CG =
+ init_convenience::BuildCodeGen(*CI, *LLVMCtx);
+ CG->Initialize(CI->getASTContext());
+
+ CI->getDiagnosticClient().BeginSourceFile(CI->getLangOpts(),
+ &CI->getPreprocessor());
+ if (llvm::Error PE = ParseSource(Path, *CI, *CG)) {
+ return std::move(PE);
+ }
+ CI->getDiagnosticClient().EndSourceFile();
+ if (CI->getDiagnosticClient().getNumErrors()) {
+ return llvm::make_error<llvm::StringError>(
+ "Errors occured while parsing the expression.", std::error_code());
+ } else {
+ return std::move(CI);
+ }
+}
+} // end namespace
+
+int main(int argc, const char **argv) {
+ const bool DisableCrashReporting = true;
+ llvm::sys::PrintStackTraceOnErrorSignal(argv[0], DisableCrashReporting);
+ llvm::cl::ParseCommandLineOptions(argc, argv);
+ std::vector<std::unique_ptr<CompilerInstance>> ImportCIs;
+ for (auto I : Imports) {
+ llvm::Expected<std::unique_ptr<CompilerInstance>> ImportCI = Parse(I, {});
+ if (auto E = ImportCI.takeError()) {
+ llvm::errs() << llvm::toString(std::move(E));
+ exit(-1);
+ } else {
+ ImportCIs.push_back(std::move(*ImportCI));
+ }
+ }
+ llvm::Expected<std::unique_ptr<CompilerInstance>> ExpressionCI =
+ Parse(Expression, ImportCIs);
+ if (auto E = ExpressionCI.takeError()) {
+ llvm::errs() << llvm::toString(std::move(E));
+ exit(-1);
+ } else {
+ return 0;
+ }
+}
diff --git a/tools/clang-offload-bundler/CMakeLists.txt b/tools/clang-offload-bundler/CMakeLists.txt
new file mode 100644
index 000000000000..6161d08ae587
--- /dev/null
+++ b/tools/clang-offload-bundler/CMakeLists.txt
@@ -0,0 +1,24 @@
+set(LLVM_LINK_COMPONENTS BitWriter Core Object Support)
+
+if(NOT CLANG_BUILT_STANDALONE)
+ set(tablegen_deps intrinsics_gen)
+endif()
+
+add_clang_executable(clang-offload-bundler
+ ClangOffloadBundler.cpp
+
+ DEPENDS
+ ${tablegen_deps}
+ )
+
+set(CLANG_OFFLOAD_BUNDLER_LIB_DEPS
+ clangBasic
+ )
+
+add_dependencies(clang clang-offload-bundler)
+
+target_link_libraries(clang-offload-bundler
+ ${CLANG_OFFLOAD_BUNDLER_LIB_DEPS}
+ )
+
+install(TARGETS clang-offload-bundler RUNTIME DESTINATION bin)
diff --git a/tools/clang-offload-bundler/ClangOffloadBundler.cpp b/tools/clang-offload-bundler/ClangOffloadBundler.cpp
new file mode 100644
index 000000000000..20988b48ede1
--- /dev/null
+++ b/tools/clang-offload-bundler/ClangOffloadBundler.cpp
@@ -0,0 +1,1012 @@
+//===-- clang-offload-bundler/ClangOffloadBundler.cpp ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file 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.
+///
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/Version.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Bitcode/BitcodeWriter.h"
+#include "llvm/IR/Constant.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/GlobalVariable.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Object/Binary.h"
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Program.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Signals.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <memory>
+#include <string>
+#include <system_error>
+#include <vector>
+
+using namespace llvm;
+using namespace llvm::object;
+
+static cl::opt<bool> Help("h", cl::desc("Alias for -help"), cl::Hidden);
+
+// Mark all our options with this category, everything else (except for -version
+// and -help) will be hidden.
+static cl::OptionCategory
+ ClangOffloadBundlerCategory("clang-offload-bundler options");
+
+static cl::list<std::string>
+ InputFileNames("inputs", cl::CommaSeparated, cl::OneOrMore,
+ cl::desc("[<input file>,...]"),
+ cl::cat(ClangOffloadBundlerCategory));
+static cl::list<std::string>
+ OutputFileNames("outputs", cl::CommaSeparated, cl::OneOrMore,
+ cl::desc("[<output file>,...]"),
+ cl::cat(ClangOffloadBundlerCategory));
+static cl::list<std::string>
+ TargetNames("targets", cl::CommaSeparated, cl::OneOrMore,
+ cl::desc("[<offload kind>-<target triple>,...]"),
+ cl::cat(ClangOffloadBundlerCategory));
+static cl::opt<std::string>
+ FilesType("type", cl::Required,
+ cl::desc("Type of the files to be bundled/unbundled.\n"
+ "Current supported types are:\n"
+ " i - cpp-output\n"
+ " ii - c++-cpp-output\n"
+ " ll - llvm\n"
+ " bc - llvm-bc\n"
+ " s - assembler\n"
+ " o - object\n"
+ " gch - precompiled-header\n"
+ " ast - clang AST file"),
+ cl::cat(ClangOffloadBundlerCategory));
+static cl::opt<bool>
+ Unbundle("unbundle",
+ cl::desc("Unbundle bundled file into several output files.\n"),
+ cl::init(false), cl::cat(ClangOffloadBundlerCategory));
+
+static cl::opt<bool> PrintExternalCommands(
+ "###",
+ cl::desc("Print any external commands that are to be executed "
+ "instead of actually executing them - for testing purposes.\n"),
+ cl::init(false), cl::cat(ClangOffloadBundlerCategory));
+
+static cl::opt<bool> DumpTemporaryFiles(
+ "dump-temporary-files",
+ cl::desc("Dumps any temporary files created - for testing purposes.\n"),
+ cl::init(false), cl::cat(ClangOffloadBundlerCategory));
+
+/// Magic string that marks the existence of offloading data.
+#define OFFLOAD_BUNDLER_MAGIC_STR "__CLANG_OFFLOAD_BUNDLE__"
+
+/// The index of the host input in the list of inputs.
+static unsigned HostInputIndex = ~0u;
+
+/// Path to the current binary.
+static std::string BundlerExecutable;
+
+/// Obtain the offload kind and real machine triple out of the target
+/// information specified by the user.
+static void getOffloadKindAndTriple(StringRef Target, StringRef &OffloadKind,
+ StringRef &Triple) {
+ auto KindTriplePair = Target.split('-');
+ OffloadKind = KindTriplePair.first;
+ Triple = KindTriplePair.second;
+}
+static StringRef getTriple(StringRef Target) {
+ StringRef OffloadKind;
+ StringRef Triple;
+ getOffloadKindAndTriple(Target, OffloadKind, Triple);
+ return Triple;
+}
+static bool hasHostKind(StringRef Target) {
+ StringRef OffloadKind;
+ StringRef Triple;
+ getOffloadKindAndTriple(Target, OffloadKind, Triple);
+ return OffloadKind == "host";
+}
+
+/// Generic file handler interface.
+class FileHandler {
+public:
+ FileHandler() {}
+
+ virtual ~FileHandler() {}
+
+ /// Update the file handler with information from the header of the bundled
+ /// file
+ virtual void ReadHeader(MemoryBuffer &Input) = 0;
+
+ /// Read the marker of the next bundled to be read in the file. The triple of
+ /// the target associated with that bundle is returned. An empty string is
+ /// returned if there are no more bundles to be read.
+ virtual StringRef ReadBundleStart(MemoryBuffer &Input) = 0;
+
+ /// Read the marker that closes the current bundle.
+ virtual void ReadBundleEnd(MemoryBuffer &Input) = 0;
+
+ /// Read the current bundle and write the result into the stream \a OS.
+ virtual void ReadBundle(raw_fd_ostream &OS, MemoryBuffer &Input) = 0;
+
+ /// Write the header of the bundled file to \a OS based on the information
+ /// gathered from \a Inputs.
+ virtual void WriteHeader(raw_fd_ostream &OS,
+ ArrayRef<std::unique_ptr<MemoryBuffer>> Inputs) = 0;
+
+ /// Write the marker that initiates a bundle for the triple \a TargetTriple to
+ /// \a OS.
+ virtual void WriteBundleStart(raw_fd_ostream &OS, StringRef TargetTriple) = 0;
+
+ /// Write the marker that closes a bundle for the triple \a TargetTriple to \a
+ /// OS. Return true if any error was found.
+
+ virtual bool WriteBundleEnd(raw_fd_ostream &OS, StringRef TargetTriple) = 0;
+
+ /// Write the bundle from \a Input into \a OS.
+ virtual void WriteBundle(raw_fd_ostream &OS, MemoryBuffer &Input) = 0;
+};
+
+/// Handler for binary files. The bundled file will have the following format
+/// (all integers are stored in little-endian format):
+///
+/// "OFFLOAD_BUNDLER_MAGIC_STR" (ASCII encoding of the string)
+///
+/// NumberOfOffloadBundles (8-byte integer)
+///
+/// OffsetOfBundle1 (8-byte integer)
+/// SizeOfBundle1 (8-byte integer)
+/// NumberOfBytesInTripleOfBundle1 (8-byte integer)
+/// TripleOfBundle1 (byte length defined before)
+///
+/// ...
+///
+/// OffsetOfBundleN (8-byte integer)
+/// SizeOfBundleN (8-byte integer)
+/// NumberOfBytesInTripleOfBundleN (8-byte integer)
+/// TripleOfBundleN (byte length defined before)
+///
+/// Bundle1
+/// ...
+/// BundleN
+
+/// Read 8-byte integers from a buffer in little-endian format.
+static uint64_t Read8byteIntegerFromBuffer(StringRef Buffer, size_t pos) {
+ uint64_t Res = 0;
+ const char *Data = Buffer.data();
+
+ for (unsigned i = 0; i < 8; ++i) {
+ Res <<= 8;
+ uint64_t Char = (uint64_t)Data[pos + 7 - i];
+ Res |= 0xffu & Char;
+ }
+ return Res;
+}
+
+/// Write 8-byte integers to a buffer in little-endian format.
+static void Write8byteIntegerToBuffer(raw_fd_ostream &OS, uint64_t Val) {
+ for (unsigned i = 0; i < 8; ++i) {
+ char Char = (char)(Val & 0xffu);
+ OS.write(&Char, 1);
+ Val >>= 8;
+ }
+}
+
+class BinaryFileHandler final : public FileHandler {
+ /// Information about the bundles extracted from the header.
+ struct BundleInfo final {
+ /// Size of the bundle.
+ uint64_t Size = 0u;
+ /// Offset at which the bundle starts in the bundled file.
+ uint64_t Offset = 0u;
+
+ BundleInfo() {}
+ BundleInfo(uint64_t Size, uint64_t Offset) : Size(Size), Offset(Offset) {}
+ };
+
+ /// Map between a triple and the corresponding bundle information.
+ StringMap<BundleInfo> BundlesInfo;
+
+ /// Iterator for the bundle information that is being read.
+ StringMap<BundleInfo>::iterator CurBundleInfo;
+
+public:
+ BinaryFileHandler() : FileHandler() {}
+
+ ~BinaryFileHandler() final {}
+
+ void ReadHeader(MemoryBuffer &Input) final {
+ StringRef FC = Input.getBuffer();
+
+ // Initialize the current bundle with the end of the container.
+ CurBundleInfo = BundlesInfo.end();
+
+ // Check if buffer is smaller than magic string.
+ size_t ReadChars = sizeof(OFFLOAD_BUNDLER_MAGIC_STR) - 1;
+ if (ReadChars > FC.size())
+ return;
+
+ // Check if no magic was found.
+ StringRef Magic(FC.data(), sizeof(OFFLOAD_BUNDLER_MAGIC_STR) - 1);
+ if (!Magic.equals(OFFLOAD_BUNDLER_MAGIC_STR))
+ return;
+
+ // Read number of bundles.
+ if (ReadChars + 8 > FC.size())
+ return;
+
+ uint64_t NumberOfBundles = Read8byteIntegerFromBuffer(FC, ReadChars);
+ ReadChars += 8;
+
+ // Read bundle offsets, sizes and triples.
+ for (uint64_t i = 0; i < NumberOfBundles; ++i) {
+
+ // Read offset.
+ if (ReadChars + 8 > FC.size())
+ return;
+
+ uint64_t Offset = Read8byteIntegerFromBuffer(FC, ReadChars);
+ ReadChars += 8;
+
+ // Read size.
+ if (ReadChars + 8 > FC.size())
+ return;
+
+ uint64_t Size = Read8byteIntegerFromBuffer(FC, ReadChars);
+ ReadChars += 8;
+
+ // Read triple size.
+ if (ReadChars + 8 > FC.size())
+ return;
+
+ uint64_t TripleSize = Read8byteIntegerFromBuffer(FC, ReadChars);
+ ReadChars += 8;
+
+ // Read triple.
+ if (ReadChars + TripleSize > FC.size())
+ return;
+
+ StringRef Triple(&FC.data()[ReadChars], TripleSize);
+ ReadChars += TripleSize;
+
+ // Check if the offset and size make sense.
+ if (!Size || !Offset || Offset + Size > FC.size())
+ return;
+
+ assert(BundlesInfo.find(Triple) == BundlesInfo.end() &&
+ "Triple is duplicated??");
+ BundlesInfo[Triple] = BundleInfo(Size, Offset);
+ }
+ // Set the iterator to where we will start to read.
+ CurBundleInfo = BundlesInfo.begin();
+ }
+
+ StringRef ReadBundleStart(MemoryBuffer &Input) final {
+ if (CurBundleInfo == BundlesInfo.end())
+ return StringRef();
+
+ return CurBundleInfo->first();
+ }
+
+ void ReadBundleEnd(MemoryBuffer &Input) final {
+ assert(CurBundleInfo != BundlesInfo.end() && "Invalid reader info!");
+ ++CurBundleInfo;
+ }
+
+ void ReadBundle(raw_fd_ostream &OS, MemoryBuffer &Input) final {
+ assert(CurBundleInfo != BundlesInfo.end() && "Invalid reader info!");
+ StringRef FC = Input.getBuffer();
+ OS.write(FC.data() + CurBundleInfo->second.Offset,
+ CurBundleInfo->second.Size);
+ }
+
+ void WriteHeader(raw_fd_ostream &OS,
+ ArrayRef<std::unique_ptr<MemoryBuffer>> Inputs) final {
+ // Compute size of the header.
+ uint64_t HeaderSize = 0;
+
+ HeaderSize += sizeof(OFFLOAD_BUNDLER_MAGIC_STR) - 1;
+ HeaderSize += 8; // Number of Bundles
+
+ for (auto &T : TargetNames) {
+ HeaderSize += 3 * 8; // Bundle offset, Size of bundle and size of triple.
+ HeaderSize += T.size(); // The triple.
+ }
+
+ // Write to the buffer the header.
+ OS << OFFLOAD_BUNDLER_MAGIC_STR;
+
+ Write8byteIntegerToBuffer(OS, TargetNames.size());
+
+ unsigned Idx = 0;
+ for (auto &T : TargetNames) {
+ MemoryBuffer &MB = *Inputs[Idx++].get();
+ // Bundle offset.
+ Write8byteIntegerToBuffer(OS, HeaderSize);
+ // Size of the bundle (adds to the next bundle's offset)
+ Write8byteIntegerToBuffer(OS, MB.getBufferSize());
+ HeaderSize += MB.getBufferSize();
+ // Size of the triple
+ Write8byteIntegerToBuffer(OS, T.size());
+ // Triple
+ OS << T;
+ }
+ }
+
+ void WriteBundleStart(raw_fd_ostream &OS, StringRef TargetTriple) final {}
+
+ bool WriteBundleEnd(raw_fd_ostream &OS, StringRef TargetTriple) final {
+ return false;
+ }
+
+ void WriteBundle(raw_fd_ostream &OS, MemoryBuffer &Input) final {
+ OS.write(Input.getBufferStart(), Input.getBufferSize());
+ }
+};
+
+/// Handler for object files. The bundles are organized by sections with a
+/// designated name.
+///
+/// In order to bundle we create an IR file with the content of each section and
+/// use incremental linking to produce the resulting object. We also add section
+/// with a single byte to state the name of the component the main object file
+/// (the one we are bundling into) refers to.
+///
+/// To unbundle, we use just copy the contents of the designated section. If the
+/// requested bundle refer to the main object file, we just copy it with no
+/// changes.
+class ObjectFileHandler final : public FileHandler {
+
+ /// The object file we are currently dealing with.
+ std::unique_ptr<ObjectFile> Obj;
+
+ /// Return the input file contents.
+ StringRef getInputFileContents() const { return Obj->getData(); }
+
+ /// Return true if the provided section is an offload section and return the
+ /// triple by reference.
+ static bool IsOffloadSection(SectionRef CurSection,
+ StringRef &OffloadTriple) {
+ StringRef SectionName;
+ CurSection.getName(SectionName);
+
+ if (SectionName.empty())
+ return false;
+
+ // If it does not start with the reserved suffix, just skip this section.
+ if (!SectionName.startswith(OFFLOAD_BUNDLER_MAGIC_STR))
+ return false;
+
+ // Return the triple that is right after the reserved prefix.
+ OffloadTriple = SectionName.substr(sizeof(OFFLOAD_BUNDLER_MAGIC_STR) - 1);
+ return true;
+ }
+
+ /// Total number of inputs.
+ unsigned NumberOfInputs = 0;
+
+ /// Total number of processed inputs, i.e, inputs that were already
+ /// read from the buffers.
+ unsigned NumberOfProcessedInputs = 0;
+
+ /// LLVM context used to to create the auxiliar modules.
+ LLVMContext VMContext;
+
+ /// LLVM module used to create an object with all the bundle
+ /// components.
+ std::unique_ptr<Module> AuxModule;
+
+ /// The current triple we are working with.
+ StringRef CurrentTriple;
+
+ /// The name of the main input file.
+ StringRef MainInputFileName;
+
+ /// Iterator of the current and next section.
+ section_iterator CurrentSection;
+ section_iterator NextSection;
+
+public:
+ ObjectFileHandler(std::unique_ptr<ObjectFile> ObjIn)
+ : FileHandler(), Obj(std::move(ObjIn)),
+ CurrentSection(Obj->section_begin()),
+ NextSection(Obj->section_begin()) {}
+
+ ~ObjectFileHandler() final {}
+
+ void ReadHeader(MemoryBuffer &Input) final {}
+
+ StringRef ReadBundleStart(MemoryBuffer &Input) final {
+ while (NextSection != Obj->section_end()) {
+ CurrentSection = NextSection;
+ ++NextSection;
+
+ StringRef OffloadTriple;
+ // Check if the current section name starts with the reserved prefix. If
+ // so, return the triple.
+ if (IsOffloadSection(*CurrentSection, OffloadTriple))
+ return OffloadTriple;
+ }
+ return StringRef();
+ }
+
+ void ReadBundleEnd(MemoryBuffer &Input) final {}
+
+ void ReadBundle(raw_fd_ostream &OS, MemoryBuffer &Input) final {
+ // If the current section has size one, that means that the content we are
+ // interested in is the file itself. Otherwise it is the content of the
+ // section.
+ //
+ // TODO: Instead of copying the input file as is, deactivate the section
+ // that is no longer needed.
+
+ StringRef Content;
+ CurrentSection->getContents(Content);
+
+ if (Content.size() < 2)
+ OS.write(Input.getBufferStart(), Input.getBufferSize());
+ else
+ OS.write(Content.data(), Content.size());
+ }
+
+ void WriteHeader(raw_fd_ostream &OS,
+ ArrayRef<std::unique_ptr<MemoryBuffer>> Inputs) final {
+ assert(HostInputIndex != ~0u && "Host input index not defined.");
+
+ // Record number of inputs.
+ NumberOfInputs = Inputs.size();
+
+ // Create an LLVM module to have the content we need to bundle.
+ auto *M = new Module("clang-offload-bundle", VMContext);
+ M->setTargetTriple(getTriple(TargetNames[HostInputIndex]));
+ AuxModule.reset(M);
+ }
+
+ void WriteBundleStart(raw_fd_ostream &OS, StringRef TargetTriple) final {
+ ++NumberOfProcessedInputs;
+
+ // Record the triple we are using, that will be used to name the section we
+ // will create.
+ CurrentTriple = TargetTriple;
+ }
+
+ bool WriteBundleEnd(raw_fd_ostream &OS, StringRef TargetTriple) final {
+ assert(NumberOfProcessedInputs <= NumberOfInputs &&
+ "Processing more inputs that actually exist!");
+ assert(HostInputIndex != ~0u && "Host input index not defined.");
+
+ // If this is not the last output, we don't have to do anything.
+ if (NumberOfProcessedInputs != NumberOfInputs)
+ return false;
+
+ // Create the bitcode file name to write the resulting code to. Keep it if
+ // save-temps is active.
+ SmallString<128> BitcodeFileName;
+ if (sys::fs::createTemporaryFile("clang-offload-bundler", "bc",
+ BitcodeFileName)) {
+ errs() << "error: unable to create temporary file.\n";
+ return true;
+ }
+
+ // Dump the contents of the temporary file if that was requested.
+ if (DumpTemporaryFiles) {
+ errs() << ";\n; Object file bundler IR file.\n;\n";
+ AuxModule.get()->dump();
+ }
+
+ // Find clang in order to create the bundle binary.
+ StringRef Dir = sys::path::parent_path(BundlerExecutable);
+
+ auto ClangBinary = sys::findProgramByName("clang", Dir);
+ if (ClangBinary.getError()) {
+ // Remove bitcode file.
+ sys::fs::remove(BitcodeFileName);
+
+ errs() << "error: unable to find 'clang' in path.\n";
+ return true;
+ }
+
+ // Do the incremental linking. We write to the output file directly. So, we
+ // 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};
+
+ // 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] << "\"";
+ errs() << "\n";
+ } else {
+ // Write the bitcode contents to the temporary file.
+ {
+ std::error_code EC;
+ raw_fd_ostream BitcodeFile(BitcodeFileName, EC, sys::fs::F_None);
+ if (EC) {
+ errs() << "error: unable to open temporary file.\n";
+ return true;
+ }
+ WriteBitcodeToFile(AuxModule.get(), BitcodeFile);
+ }
+
+ bool Failed = sys::ExecuteAndWait(ClangBinary.get(), ClangArgs);
+
+ // Remove bitcode file.
+ sys::fs::remove(BitcodeFileName);
+
+ if (Failed) {
+ errs() << "error: incremental linking by external tool failed.\n";
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ void WriteBundle(raw_fd_ostream &OS, MemoryBuffer &Input) final {
+ Module *M = AuxModule.get();
+
+ // Create the new section name, it will consist of the reserved prefix
+ // concatenated with the triple.
+ std::string SectionName = OFFLOAD_BUNDLER_MAGIC_STR;
+ SectionName += CurrentTriple;
+
+ // Create the constant with the content of the section. For the input we are
+ // bundling into (the host input), this is just a place-holder, so a single
+ // byte is sufficient.
+ assert(HostInputIndex != ~0u && "Host input index undefined??");
+ Constant *Content;
+ if (NumberOfProcessedInputs == HostInputIndex + 1) {
+ uint8_t Byte[] = {0};
+ Content = ConstantDataArray::get(VMContext, Byte);
+ } else
+ Content = ConstantDataArray::get(
+ VMContext, ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(
+ Input.getBufferStart()),
+ Input.getBufferSize()));
+
+ // Create the global in the desired section. We don't want these globals in
+ // the symbol table, so we mark them private.
+ auto *GV = new GlobalVariable(*M, Content->getType(), /*IsConstant=*/true,
+ GlobalVariable::PrivateLinkage, Content);
+ GV->setSection(SectionName);
+ }
+};
+
+/// Handler for text files. The bundled file will have the following format.
+///
+/// "Comment OFFLOAD_BUNDLER_MAGIC_STR__START__ triple"
+/// Bundle 1
+/// "Comment OFFLOAD_BUNDLER_MAGIC_STR__END__ triple"
+/// ...
+/// "Comment OFFLOAD_BUNDLER_MAGIC_STR__START__ triple"
+/// Bundle N
+/// "Comment OFFLOAD_BUNDLER_MAGIC_STR__END__ triple"
+class TextFileHandler final : public FileHandler {
+ /// String that begins a line comment.
+ StringRef Comment;
+
+ /// String that initiates a bundle.
+ std::string BundleStartString;
+
+ /// String that closes a bundle.
+ std::string BundleEndString;
+
+ /// Number of chars read from input.
+ size_t ReadChars = 0u;
+
+protected:
+ void ReadHeader(MemoryBuffer &Input) final {}
+
+ StringRef ReadBundleStart(MemoryBuffer &Input) final {
+ StringRef FC = Input.getBuffer();
+
+ // Find start of the bundle.
+ ReadChars = FC.find(BundleStartString, ReadChars);
+ if (ReadChars == FC.npos)
+ return StringRef();
+
+ // Get position of the triple.
+ size_t TripleStart = ReadChars = ReadChars + BundleStartString.size();
+
+ // Get position that closes the triple.
+ size_t TripleEnd = ReadChars = FC.find("\n", ReadChars);
+ if (TripleEnd == FC.npos)
+ return StringRef();
+
+ // Next time we read after the new line.
+ ++ReadChars;
+
+ return StringRef(&FC.data()[TripleStart], TripleEnd - TripleStart);
+ }
+
+ void ReadBundleEnd(MemoryBuffer &Input) final {
+ StringRef FC = Input.getBuffer();
+
+ // Read up to the next new line.
+ assert(FC[ReadChars] == '\n' && "The bundle should end with a new line.");
+
+ size_t TripleEnd = ReadChars = FC.find("\n", ReadChars + 1);
+ if (TripleEnd == FC.npos)
+ return;
+
+ // Next time we read after the new line.
+ ++ReadChars;
+ }
+
+ void ReadBundle(raw_fd_ostream &OS, MemoryBuffer &Input) final {
+ StringRef FC = Input.getBuffer();
+ size_t BundleStart = ReadChars;
+
+ // Find end of the bundle.
+ size_t BundleEnd = ReadChars = FC.find(BundleEndString, ReadChars);
+
+ StringRef Bundle(&FC.data()[BundleStart], BundleEnd - BundleStart);
+ OS << Bundle;
+ }
+
+ void WriteHeader(raw_fd_ostream &OS,
+ ArrayRef<std::unique_ptr<MemoryBuffer>> Inputs) final {}
+
+ void WriteBundleStart(raw_fd_ostream &OS, StringRef TargetTriple) final {
+ OS << BundleStartString << TargetTriple << "\n";
+ }
+
+ bool WriteBundleEnd(raw_fd_ostream &OS, StringRef TargetTriple) final {
+ OS << BundleEndString << TargetTriple << "\n";
+ return false;
+ }
+
+ void WriteBundle(raw_fd_ostream &OS, MemoryBuffer &Input) final {
+ OS << Input.getBuffer();
+ }
+
+public:
+ TextFileHandler(StringRef Comment)
+ : FileHandler(), Comment(Comment), ReadChars(0) {
+ BundleStartString =
+ "\n" + Comment.str() + " " OFFLOAD_BUNDLER_MAGIC_STR "__START__ ";
+ BundleEndString =
+ "\n" + Comment.str() + " " OFFLOAD_BUNDLER_MAGIC_STR "__END__ ";
+ }
+};
+
+/// Return an appropriate object file handler. We use the specific object
+/// handler if we know how to deal with that format, otherwise we use a default
+/// binary file handler.
+static FileHandler *CreateObjectFileHandler(MemoryBuffer &FirstInput) {
+ // Check if the input file format is one that we know how to deal with.
+ Expected<std::unique_ptr<Binary>> BinaryOrErr = createBinary(FirstInput);
+
+ // Failed to open the input as a known binary. Use the default binary handler.
+ if (!BinaryOrErr) {
+ // We don't really care about the error (we just consume it), if we could
+ // not get a valid device binary object we use the default binary handler.
+ consumeError(BinaryOrErr.takeError());
+ return new BinaryFileHandler();
+ }
+
+ // We only support regular object files. If this is not an object file,
+ // default to the binary handler. The handler will be owned by the client of
+ // this function.
+ std::unique_ptr<ObjectFile> Obj(
+ dyn_cast<ObjectFile>(BinaryOrErr.get().release()));
+
+ if (!Obj)
+ return new BinaryFileHandler();
+
+ return new ObjectFileHandler(std::move(Obj));
+}
+
+/// Return an appropriate handler given the input files and options.
+static FileHandler *CreateFileHandler(MemoryBuffer &FirstInput) {
+ if (FilesType == "i")
+ return new TextFileHandler(/*Comment=*/"//");
+ if (FilesType == "ii")
+ return new TextFileHandler(/*Comment=*/"//");
+ if (FilesType == "ll")
+ return new TextFileHandler(/*Comment=*/";");
+ if (FilesType == "bc")
+ return new BinaryFileHandler();
+ if (FilesType == "s")
+ return new TextFileHandler(/*Comment=*/"#");
+ if (FilesType == "o")
+ return CreateObjectFileHandler(FirstInput);
+ if (FilesType == "gch")
+ return new BinaryFileHandler();
+ if (FilesType == "ast")
+ return new BinaryFileHandler();
+
+ errs() << "error: invalid file type specified.\n";
+ return nullptr;
+}
+
+/// Bundle the files. Return true if an error was found.
+static bool BundleFiles() {
+ std::error_code EC;
+
+ // Create output file.
+ raw_fd_ostream OutputFile(OutputFileNames.front(), EC, sys::fs::F_None);
+
+ if (EC) {
+ errs() << "error: Can't open file " << OutputFileNames.front() << ".\n";
+ return true;
+ }
+
+ // Open input files.
+ std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers(
+ InputFileNames.size());
+
+ unsigned Idx = 0;
+ for (auto &I : InputFileNames) {
+ ErrorOr<std::unique_ptr<MemoryBuffer>> CodeOrErr =
+ MemoryBuffer::getFileOrSTDIN(I);
+ if (std::error_code EC = CodeOrErr.getError()) {
+ errs() << "error: Can't open file " << I << ": " << EC.message() << "\n";
+ return true;
+ }
+ InputBuffers[Idx++] = std::move(CodeOrErr.get());
+ }
+
+ // Get the file handler. We use the host buffer as reference.
+ assert(HostInputIndex != ~0u && "Host input index undefined??");
+ std::unique_ptr<FileHandler> FH;
+ FH.reset(CreateFileHandler(*InputBuffers[HostInputIndex].get()));
+
+ // Quit if we don't have a handler.
+ if (!FH.get())
+ return true;
+
+ // Write header.
+ FH.get()->WriteHeader(OutputFile, InputBuffers);
+
+ // Write all bundles along with the start/end markers. If an error was found
+ // writing the end of the bundle component, abort the bundle writing.
+ auto Input = InputBuffers.begin();
+ for (auto &Triple : TargetNames) {
+ FH.get()->WriteBundleStart(OutputFile, Triple);
+ FH.get()->WriteBundle(OutputFile, *Input->get());
+ if (FH.get()->WriteBundleEnd(OutputFile, Triple))
+ return true;
+ ++Input;
+ }
+ return false;
+}
+
+// Unbundle the files. Return true if an error was found.
+static bool UnbundleFiles() {
+ // Open Input file.
+ ErrorOr<std::unique_ptr<MemoryBuffer>> CodeOrErr =
+ MemoryBuffer::getFileOrSTDIN(InputFileNames.front());
+ if (std::error_code EC = CodeOrErr.getError()) {
+ errs() << "error: Can't open file " << InputFileNames.front() << ": "
+ << EC.message() << "\n";
+ return true;
+ }
+
+ MemoryBuffer &Input = *CodeOrErr.get();
+
+ // Select the right files handler.
+ std::unique_ptr<FileHandler> FH;
+ FH.reset(CreateFileHandler(Input));
+
+ // Quit if we don't have a handler.
+ if (!FH.get())
+ return true;
+
+ // Read the header of the bundled file.
+ FH.get()->ReadHeader(Input);
+
+ // Create a work list that consist of the map triple/output file.
+ StringMap<StringRef> Worklist;
+ auto Output = OutputFileNames.begin();
+ for (auto &Triple : TargetNames) {
+ Worklist[Triple] = *Output;
+ ++Output;
+ }
+
+ // Read all the bundles that are in the work list. If we find no bundles we
+ // assume the file is meant for the host target.
+ bool FoundHostBundle = false;
+ while (!Worklist.empty()) {
+ StringRef CurTriple = FH.get()->ReadBundleStart(Input);
+
+ // We don't have more bundles.
+ if (CurTriple.empty())
+ break;
+
+ auto Output = Worklist.find(CurTriple);
+ // The file may have more bundles for other targets, that we don't care
+ // about. Therefore, move on to the next triple
+ if (Output == Worklist.end()) {
+ continue;
+ }
+
+ // Check if the output file can be opened and copy the bundle to it.
+ std::error_code EC;
+ raw_fd_ostream OutputFile(Output->second, EC, sys::fs::F_None);
+ if (EC) {
+ errs() << "error: Can't open file " << Output->second << ": "
+ << EC.message() << "\n";
+ return true;
+ }
+ FH.get()->ReadBundle(OutputFile, Input);
+ FH.get()->ReadBundleEnd(Input);
+ Worklist.erase(Output);
+
+ // Record if we found the host bundle.
+ if (hasHostKind(CurTriple))
+ FoundHostBundle = true;
+ }
+
+ // If no bundles were found, assume the input file is the host bundle and
+ // create empty files for the remaining targets.
+ if (Worklist.size() == TargetNames.size()) {
+ for (auto &E : Worklist) {
+ std::error_code EC;
+ raw_fd_ostream OutputFile(E.second, EC, sys::fs::F_None);
+ if (EC) {
+ errs() << "error: Can't open file " << E.second << ": " << EC.message()
+ << "\n";
+ return true;
+ }
+
+ // If this entry has a host kind, copy the input file to the output file.
+ if (hasHostKind(E.first()))
+ OutputFile.write(Input.getBufferStart(), Input.getBufferSize());
+ }
+ return false;
+ }
+
+ // If we found elements, we emit an error if none of those were for the host.
+ if (!FoundHostBundle) {
+ errs() << "error: Can't find bundle for the host target\n";
+ return true;
+ }
+
+ // If we still have any elements in the worklist, create empty files for them.
+ for (auto &E : Worklist) {
+ std::error_code EC;
+ raw_fd_ostream OutputFile(E.second, EC, sys::fs::F_None);
+ if (EC) {
+ errs() << "error: Can't open file " << E.second << ": " << EC.message()
+ << "\n";
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static void PrintVersion() {
+ raw_ostream &OS = outs();
+ OS << clang::getClangToolFullVersion("clang-offload-bundler") << '\n';
+}
+
+int main(int argc, const char **argv) {
+ sys::PrintStackTraceOnErrorSignal(argv[0]);
+
+ cl::HideUnrelatedOptions(ClangOffloadBundlerCategory);
+ cl::SetVersionPrinter(PrintVersion);
+ cl::ParseCommandLineOptions(
+ argc, argv,
+ "A tool to bundle several input files of the specified type <type> \n"
+ "referring to the same source file but different targets into a single \n"
+ "one. The resulting file can also be unbundled into different files by \n"
+ "this tool if -unbundle is provided.\n");
+
+ if (Help)
+ cl::PrintHelpMessage();
+
+ bool Error = false;
+ if (Unbundle) {
+ if (InputFileNames.size() != 1) {
+ Error = true;
+ errs() << "error: only one input file supported in unbundling mode.\n";
+ }
+ if (OutputFileNames.size() != TargetNames.size()) {
+ Error = true;
+ errs() << "error: number of output files and targets should match in "
+ "unbundling mode.\n";
+ }
+ } else {
+ if (OutputFileNames.size() != 1) {
+ Error = true;
+ errs() << "error: only one output file supported in bundling mode.\n";
+ }
+ if (InputFileNames.size() != TargetNames.size()) {
+ Error = true;
+ errs() << "error: number of input files and targets should match in "
+ "bundling mode.\n";
+ }
+ }
+
+ // Verify that the offload kinds and triples are known. We also check that we
+ // have exactly one host target.
+ unsigned Index = 0u;
+ unsigned HostTargetNum = 0u;
+ for (StringRef Target : TargetNames) {
+ StringRef Kind;
+ StringRef Triple;
+ getOffloadKindAndTriple(Target, Kind, Triple);
+
+ bool KindIsValid = !Kind.empty();
+ KindIsValid = KindIsValid &&
+ StringSwitch<bool>(Kind)
+ .Case("host", true)
+ .Case("openmp", true)
+ .Default(false);
+
+ bool TripleIsValid = !Triple.empty();
+ llvm::Triple T(Triple);
+ TripleIsValid &= T.getArch() != Triple::UnknownArch;
+
+ if (!KindIsValid || !TripleIsValid) {
+ Error = true;
+ errs() << "error: invalid target '" << Target << "'";
+
+ if (!KindIsValid)
+ errs() << ", unknown offloading kind '" << Kind << "'";
+ if (!TripleIsValid)
+ errs() << ", unknown target triple '" << Triple << "'";
+ errs() << ".\n";
+ }
+
+ if (KindIsValid && Kind == "host") {
+ ++HostTargetNum;
+ // Save the index of the input that refers to the host.
+ HostInputIndex = Index;
+ }
+
+ ++Index;
+ }
+
+ if (HostTargetNum != 1) {
+ Error = true;
+ errs() << "error: expecting exactly one host target but got "
+ << HostTargetNum << ".\n";
+ }
+
+ if (Error)
+ return 1;
+
+ // Save the current executable directory as it will be useful to find other
+ // tools.
+ BundlerExecutable = sys::fs::getMainExecutable(argv[0], &BundlerExecutable);
+
+ return Unbundle ? UnbundleFiles() : BundleFiles();
+}
diff --git a/tools/diagtool/DiagTool.cpp b/tools/diagtool/DiagTool.cpp
index 0e4d8088c6c2..7582d51ae4f5 100644
--- a/tools/diagtool/DiagTool.cpp
+++ b/tools/diagtool/DiagTool.cpp
@@ -12,7 +12,6 @@
//===----------------------------------------------------------------------===//
#include "DiagTool.h"
-#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringMap.h"
#include <vector>
diff --git a/tools/diagtool/TreeView.cpp b/tools/diagtool/TreeView.cpp
index 3647e393b869..07af944ffc4e 100644
--- a/tools/diagtool/TreeView.cpp
+++ b/tools/diagtool/TreeView.cpp
@@ -14,7 +14,6 @@
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "llvm/ADT/DenseSet.h"
-#include "llvm/ADT/StringMap.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/Process.h"
diff --git a/tools/driver/CMakeLists.txt b/tools/driver/CMakeLists.txt
index e03b3fa3951e..49bde947f4c6 100644
--- a/tools/driver/CMakeLists.txt
+++ b/tools/driver/CMakeLists.txt
@@ -24,10 +24,17 @@ if(CLANG_PLUGIN_SUPPORT)
set(LLVM_NO_DEAD_STRIP 1)
endif()
+if(NOT CLANG_BUILT_STANDALONE)
+ set(tablegen_deps intrinsics_gen)
+endif()
+
add_clang_tool(clang
driver.cpp
cc1_main.cpp
cc1as_main.cpp
+
+ DEPENDS
+ ${tablegen_deps}
)
target_link_libraries(clang
@@ -52,7 +59,7 @@ endif()
add_dependencies(clang clang-headers)
if(NOT CLANG_LINKS_TO_CREATE)
- set(CLANG_LINKS_TO_CREATE clang++ clang-cl)
+ set(CLANG_LINKS_TO_CREATE clang++ clang-cl clang-cpp)
if (WIN32)
list(APPEND CLANG_LINKS_TO_CREATE ../msbuild-bin/cl)
@@ -74,7 +81,7 @@ if (APPLE)
set(TOOL_INFO_UTI "${CLANG_VENDOR_UTI}")
set(TOOL_INFO_VERSION "${CLANG_VERSION}")
- set(TOOL_INFO_BUILD_VERSION "${LLVM_MAJOR_VERSION}.${LLVM_MINOR_VERSION}")
+ set(TOOL_INFO_BUILD_VERSION "${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}")
set(TOOL_INFO_PLIST_OUT "${CMAKE_CURRENT_BINARY_DIR}/${TOOL_INFO_PLIST}")
target_link_libraries(clang
@@ -101,8 +108,15 @@ if(LD64_EXECUTABLE AND CLANG_ORDER_FILE)
# This is a test to ensure the actual order file works with the linker.
check_linker_flag("-Wl,-order_file,${CLANG_ORDER_FILE}"
LINKER_ORDER_FILE_WORKS)
-
- if(LINKER_ORDER_FILE_WORKS)
+
+ # Passing an empty order file disables some linker layout optimizations.
+ # To work around this and enable workflows for re-linking when the order file
+ # changes we check during configuration if the file is empty, and make it a
+ # configuration dependency.
+ file(READ ${CLANG_ORDER_FILE} ORDER_FILE LIMIT 20)
+ if("${ORDER_FILE}" STREQUAL "\n")
+ set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${CLANG_ORDER_FILE})
+ elseif(LINKER_ORDER_FILE_WORKS)
target_link_libraries(clang "-Wl,-order_file,${CLANG_ORDER_FILE}")
set_target_properties(clang PROPERTIES LINK_DEPENDS ${CLANG_ORDER_FILE})
endif()
@@ -110,9 +124,4 @@ endif()
if(WITH_POLLY AND LINK_POLLY_INTO_TOOLS)
target_link_libraries(clang Polly)
- if(POLLY_LINK_LIBS)
- foreach(lib ${POLLY_LINK_LIBS})
- target_link_libraries(clang ${lib})
- endforeach(lib)
- endif(POLLY_LINK_LIBS)
endif(WITH_POLLY AND LINK_POLLY_INTO_TOOLS)
diff --git a/tools/driver/Info.plist.in b/tools/driver/Info.plist.in
index c938fb053d92..c2b157021df4 100644
--- a/tools/driver/Info.plist.in
+++ b/tools/driver/Info.plist.in
@@ -7,7 +7,7 @@
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
- <string>@TOOL_INFO_NAME</string>
+ <string>@TOOL_INFO_NAME@</string>
<key>CFBundleShortVersionString</key>
<string>@TOOL_INFO_VERSION@</string>
<key>CFBundleVersion</key>
diff --git a/tools/driver/cc1_main.cpp b/tools/driver/cc1_main.cpp
index d78a31e67a2f..1a16746d589d 100644
--- a/tools/driver/cc1_main.cpp
+++ b/tools/driver/cc1_main.cpp
@@ -15,6 +15,7 @@
#include "llvm/Option/Arg.h"
#include "clang/CodeGen/ObjectFilePCHContainerOperations.h"
+#include "clang/Config/config.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
#include "clang/Frontend/CompilerInstance.h"
@@ -28,6 +29,7 @@
#include "llvm/LinkAllPasses.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/OptTable.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/Signals.h"
@@ -35,6 +37,11 @@
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdio>
+
+#ifdef CLANG_HAVE_RLIMITS
+#include <sys/resource.h>
+#endif
+
using namespace clang;
using namespace llvm::opt;
@@ -64,7 +71,105 @@ 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
+ // line arguments and environment.
+ size_t Usage = 512 * 1024;
+ if (FILE *StatFile = fopen("/proc/self/stat", "r")) {
+ // We assume that the stack extends from its current address to the end of
+ // the environment space. In reality, there is another string literal (the
+ // program name) after the environment, but this is close enough (we only
+ // need to be within 100K or so).
+ unsigned long StackPtr, EnvEnd;
+ // Disable silly GCC -Wformat warning that complains about length
+ // modifiers on ignored format specifiers. We want to retain these
+ // for documentation purposes even though they have no effect.
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat"
+#endif
+ if (fscanf(StatFile,
+ "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*lu %*lu %*lu %*lu %*lu "
+ "%*lu %*ld %*ld %*ld %*ld %*ld %*ld %*llu %*lu %*ld %*lu %*lu "
+ "%*lu %*lu %lu %*lu %*lu %*lu %*lu %*lu %*llu %*lu %*lu %*d %*d "
+ "%*u %*u %*llu %*lu %*ld %*lu %*lu %*lu %*lu %*lu %*lu %lu %*d",
+ &StackPtr, &EnvEnd) == 2) {
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+ Usage = StackPtr < EnvEnd ? EnvEnd - StackPtr : StackPtr - EnvEnd;
+ }
+ fclose(StatFile);
+ }
+ return Usage;
+}
+
+#include <alloca.h>
+
+LLVM_ATTRIBUTE_NOINLINE
+static void ensureStackAddressSpace(int ExtraChunks = 0) {
+ // 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
+ // 128MiB before we reach our stack high-water mark.
+ //
+ // 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;
+ if (Curr < kTargetStack) {
+ volatile char *volatile Alloc =
+ static_cast<volatile char *>(alloca(kTargetStack - Curr));
+ Alloc[0] = 0;
+ Alloc[kTargetStack - Curr - 1] = 0;
+ }
+}
+#else
+static void ensureStackAddressSpace() {}
+#endif
+
+/// Attempt to ensure that we have at least 8MiB of usable stack space.
+static void ensureSufficientStack() {
+ struct rlimit rlim;
+ if (getrlimit(RLIMIT_STACK, &rlim) != 0)
+ return;
+
+ // Increase the soft stack limit to our desired level, if necessary and
+ // possible.
+ if (rlim.rlim_cur != RLIM_INFINITY && rlim.rlim_cur < kSufficientStack) {
+ // Try to allocate sufficient stack.
+ if (rlim.rlim_max == RLIM_INFINITY || rlim.rlim_max >= kSufficientStack)
+ rlim.rlim_cur = kSufficientStack;
+ 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)
+ return;
+ }
+
+ // We should now have a stack of size at least kSufficientStack. Ensure
+ // that we can actually use that much, if necessary.
+ ensureStackAddressSpace();
+}
+#else
+static void ensureSufficientStack() {}
+#endif
+
int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
+ ensureSufficientStack();
+
std::unique_ptr<CompilerInstance> Clang(new CompilerInstance());
IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
diff --git a/tools/driver/cc1as_main.cpp b/tools/driver/cc1as_main.cpp
index 2d17be99e2d5..263751346b80 100644
--- a/tools/driver/cc1as_main.cpp
+++ b/tools/driver/cc1as_main.cpp
@@ -77,6 +77,9 @@ struct AssemblerInvocation {
/// be a list of strings starting with '+' or '-'.
std::vector<std::string> Features;
+ /// The list of symbol definitions.
+ std::vector<std::string> SymbolDefs;
+
/// @}
/// @name Language Options
/// @{
@@ -252,6 +255,7 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
Opts.RelocationModel = Args.getLastArgValue(OPT_mrelocation_model, "pic");
Opts.IncrementalLinkerCompatible =
Args.hasArg(OPT_mincremental_linker_compatible);
+ Opts.SymbolDefs = Args.getAllArgValues(OPT_defsym);
return Success;
}
@@ -379,7 +383,8 @@ static bool ExecuteAssembler(AssemblerInvocation &Opts,
MCAsmBackend *MAB = nullptr;
if (Opts.ShowEncoding) {
CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx);
- MAB = TheTarget->createMCAsmBackend(*MRI, Opts.Triple, Opts.CPU);
+ MCTargetOptions Options;
+ MAB = TheTarget->createMCAsmBackend(*MRI, Opts.Triple, Opts.CPU, Options);
}
auto FOut = llvm::make_unique<formatted_raw_ostream>(*Out);
Str.reset(TheTarget->createAsmStreamer(
@@ -396,8 +401,9 @@ static bool ExecuteAssembler(AssemblerInvocation &Opts,
}
MCCodeEmitter *CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx);
+ MCTargetOptions Options;
MCAsmBackend *MAB = TheTarget->createMCAsmBackend(*MRI, Opts.Triple,
- Opts.CPU);
+ Opts.CPU, Options);
Triple T(Opts.Triple);
Str.reset(TheTarget->createMCObjectStreamer(
T, Ctx, *MAB, *Out, CE, *STI, Opts.RelaxAll,
@@ -418,6 +424,17 @@ static bool ExecuteAssembler(AssemblerInvocation &Opts,
if (!TAP)
Failed = Diags.Report(diag::err_target_unknown_triple) << Opts.Triple;
+ // Set values for symbols, if any.
+ for (auto &S : Opts.SymbolDefs) {
+ auto Pair = StringRef(S).split('=');
+ auto Sym = Pair.first;
+ auto Val = Pair.second;
+ int64_t Value;
+ // We have already error checked this in the driver.
+ Val.getAsInteger(0, Value);
+ Ctx.setSymbolValue(Parser->getStreamer(), Sym, Value);
+ }
+
if (!Failed) {
Parser->setTargetParser(*TAP.get());
Failed = Parser->Run(Opts.NoInitialTextSection);
diff --git a/tools/driver/driver.cpp b/tools/driver/driver.cpp
index 4d69aaffba23..61613028625b 100644
--- a/tools/driver/driver.cpp
+++ b/tools/driver/driver.cpp
@@ -12,7 +12,6 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Basic/CharInfo.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
@@ -25,7 +24,6 @@
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Frontend/Utils.h"
#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Config/llvm-config.h"
@@ -37,7 +35,6 @@
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/ManagedStatic.h"
-#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Process.h"
@@ -49,6 +46,7 @@
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
#include <memory>
+#include <set>
#include <system_error>
using namespace clang;
using namespace clang::driver;
@@ -395,7 +393,7 @@ int main(int argc_, const char **argv_) {
// Handle CL and _CL_ which permits additional command line options to be
// prepended or appended.
- if (Tokenizer == &llvm::cl::TokenizeWindowsCommandLine) {
+ if (ClangCLMode) {
// Arguments in "CL" are prepended.
llvm::Optional<std::string> OptCL = llvm::sys::Process::GetEnv("CL");
if (OptCL.hasValue()) {
diff --git a/tools/libclang/ARCMigrate.cpp b/tools/libclang/ARCMigrate.cpp
index b597383dfd2b..44a60c4e3e2c 100644
--- a/tools/libclang/ARCMigrate.cpp
+++ b/tools/libclang/ARCMigrate.cpp
@@ -32,8 +32,6 @@ struct Remap {
// libClang public APIs.
//===----------------------------------------------------------------------===//
-extern "C" {
-
CXRemapping clang_getRemappings(const char *migrate_dir_path) {
#ifndef CLANG_ENABLE_ARCMT
llvm::errs() << "error: feature not enabled in this build\n";
@@ -138,5 +136,3 @@ void clang_remap_getFilenames(CXRemapping map, unsigned index,
void clang_remap_dispose(CXRemapping map) {
delete static_cast<Remap *>(map);
}
-
-} // end: extern "C"
diff --git a/tools/libclang/BuildSystem.cpp b/tools/libclang/BuildSystem.cpp
index fe3db755eba8..99aa5b6f2ff0 100644
--- a/tools/libclang/BuildSystem.cpp
+++ b/tools/libclang/BuildSystem.cpp
@@ -16,15 +16,15 @@
#include "clang/Basic/VirtualFileSystem.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/CBindingWrapping.h"
+#include "llvm/Support/Chrono.h"
#include "llvm/Support/Path.h"
-#include "llvm/Support/TimeValue.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
using namespace llvm::sys;
unsigned long long clang_getBuildSessionTimestamp(void) {
- return llvm::sys::TimeValue::now().toEpochTime();
+ return llvm::sys::toTimeT(std::chrono::system_clock::now());
}
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(clang::vfs::YAMLVFSWriter,
diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp
index deb4cc551b8a..b26cd754128a 100644
--- a/tools/libclang/CIndex.cpp
+++ b/tools/libclang/CIndex.cpp
@@ -12,8 +12,8 @@
//
//===----------------------------------------------------------------------===//
-#include "CIndexer.h"
#include "CIndexDiagnostic.h"
+#include "CIndexer.h"
#include "CLog.h"
#include "CXCursor.h"
#include "CXSourceLocation.h"
@@ -1249,6 +1249,17 @@ bool CursorVisitor::VisitStaticAssertDecl(StaticAssertDecl *D) {
return false;
}
+bool CursorVisitor::VisitFriendDecl(FriendDecl *D) {
+ if (NamedDecl *FriendD = D->getFriendDecl()) {
+ if (Visit(MakeCXCursor(FriendD, TU, RegionOfInterest)))
+ return true;
+ } else if (TypeSourceInfo *TI = D->getFriendType()) {
+ if (Visit(TI->getTypeLoc()))
+ return true;
+ }
+ return false;
+}
+
bool CursorVisitor::VisitDeclarationNameInfo(DeclarationNameInfo Name) {
switch (Name.getName().getNameKind()) {
case clang::DeclarationName::Identifier:
@@ -1535,6 +1546,18 @@ bool CursorVisitor::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
return Visit(MakeCursorObjCClassRef(TL.getIFaceDecl(), TL.getNameLoc(), TU));
}
+bool CursorVisitor::VisitObjCTypeParamTypeLoc(ObjCTypeParamTypeLoc TL) {
+ if (Visit(MakeCursorTypeRef(TL.getDecl(), TL.getLocStart(), TU)))
+ return true;
+ for (unsigned I = 0, N = TL.getNumProtocols(); I != N; ++I) {
+ if (Visit(MakeCursorObjCProtocolRef(TL.getProtocol(I), TL.getProtocolLoc(I),
+ TU)))
+ return true;
+ }
+
+ return false;
+}
+
bool CursorVisitor::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
if (TL.hasBaseTypeAsWritten() && Visit(TL.getBaseLoc()))
return true;
@@ -1977,6 +2000,19 @@ public:
void VisitOMPDistributeSimdDirective(const OMPDistributeSimdDirective *D);
void VisitOMPTargetParallelForSimdDirective(
const OMPTargetParallelForSimdDirective *D);
+ void VisitOMPTargetSimdDirective(const OMPTargetSimdDirective *D);
+ void VisitOMPTeamsDistributeDirective(const OMPTeamsDistributeDirective *D);
+ void VisitOMPTeamsDistributeSimdDirective(
+ const OMPTeamsDistributeSimdDirective *D);
+ void VisitOMPTeamsDistributeParallelForSimdDirective(
+ const OMPTeamsDistributeParallelForSimdDirective *D);
+ void VisitOMPTeamsDistributeParallelForDirective(
+ const OMPTeamsDistributeParallelForDirective *D);
+ void VisitOMPTargetTeamsDirective(const OMPTargetTeamsDirective *D);
+ void VisitOMPTargetTeamsDistributeDirective(
+ const OMPTargetTeamsDistributeDirective *D);
+ void VisitOMPTargetTeamsDistributeParallelForDirective(
+ const OMPTargetTeamsDistributeParallelForDirective *D);
private:
void AddDeclarationNameInfo(const Stmt *S);
@@ -2756,6 +2792,46 @@ void EnqueueVisitor::VisitOMPTargetParallelForSimdDirective(
VisitOMPLoopDirective(D);
}
+void EnqueueVisitor::VisitOMPTargetSimdDirective(
+ const OMPTargetSimdDirective *D) {
+ VisitOMPLoopDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPTeamsDistributeDirective(
+ const OMPTeamsDistributeDirective *D) {
+ VisitOMPLoopDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPTeamsDistributeSimdDirective(
+ const OMPTeamsDistributeSimdDirective *D) {
+ VisitOMPLoopDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPTeamsDistributeParallelForSimdDirective(
+ const OMPTeamsDistributeParallelForSimdDirective *D) {
+ VisitOMPLoopDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPTeamsDistributeParallelForDirective(
+ const OMPTeamsDistributeParallelForDirective *D) {
+ VisitOMPLoopDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPTargetTeamsDirective(
+ const OMPTargetTeamsDirective *D) {
+ VisitOMPExecutableDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPTargetTeamsDistributeDirective(
+ const OMPTargetTeamsDistributeDirective *D) {
+ VisitOMPLoopDirective(D);
+}
+
+void EnqueueVisitor::VisitOMPTargetTeamsDistributeParallelForDirective(
+ const OMPTargetTeamsDistributeParallelForDirective *D) {
+ VisitOMPLoopDirective(D);
+}
+
void CursorVisitor::EnqueueWorkList(VisitorWorkList &WL, const Stmt *S) {
EnqueueVisitor(WL, MakeCXCursor(S, StmtParent, TU,RegionOfInterest)).Visit(S);
}
@@ -3054,7 +3130,6 @@ struct RegisterFatalErrorHandler {
static llvm::ManagedStatic<RegisterFatalErrorHandler> RegisterFatalErrorHandlerOnce;
-extern "C" {
CXIndex clang_createIndex(int excludeDeclarationsFromPCH,
int displayDiagnostics) {
// We use crash recovery to make some of our APIs more reliable, implicitly
@@ -3469,10 +3544,12 @@ static StringLiteral* getCFSTR_value(CallExpr *callExpr) {
struct ExprEvalResult {
CXEvalResultKind EvalType;
union {
- int intVal;
+ unsigned long long unsignedVal;
+ long long intVal;
double floatVal;
char *stringVal;
} EvalData;
+ bool IsUnsignedInt;
~ExprEvalResult() {
if (EvalType != CXEval_UnExposed && EvalType != CXEval_Float &&
EvalType != CXEval_Int) {
@@ -3493,10 +3570,32 @@ CXEvalResultKind clang_EvalResult_getKind(CXEvalResult E) {
}
int clang_EvalResult_getAsInt(CXEvalResult E) {
+ return clang_EvalResult_getAsLongLong(E);
+}
+
+long long clang_EvalResult_getAsLongLong(CXEvalResult E) {
if (!E) {
return 0;
}
- return ((ExprEvalResult *)E)->EvalData.intVal;
+ ExprEvalResult *Result = (ExprEvalResult*)E;
+ if (Result->IsUnsignedInt)
+ return Result->EvalData.unsignedVal;
+ return Result->EvalData.intVal;
+}
+
+unsigned clang_EvalResult_isUnsignedInt(CXEvalResult E) {
+ return ((ExprEvalResult *)E)->IsUnsignedInt;
+}
+
+unsigned long long clang_EvalResult_getAsUnsigned(CXEvalResult E) {
+ if (!E) {
+ return 0;
+ }
+
+ ExprEvalResult *Result = (ExprEvalResult*)E;
+ if (Result->IsUnsignedInt)
+ return Result->EvalData.unsignedVal;
+ return Result->EvalData.intVal;
}
double clang_EvalResult_getAsDouble(CXEvalResult E) {
@@ -3527,10 +3626,19 @@ static const ExprEvalResult* evaluateExpr(Expr *expr, CXCursor C) {
CallExpr *callExpr;
auto result = llvm::make_unique<ExprEvalResult>();
result->EvalType = CXEval_UnExposed;
+ result->IsUnsignedInt = false;
if (ER.Val.isInt()) {
result->EvalType = CXEval_Int;
- result->EvalData.intVal = ER.Val.getInt().getExtValue();
+
+ auto& val = ER.Val.getInt();
+ if (val.isUnsigned()) {
+ result->IsUnsignedInt = true;
+ result->EvalData.unsignedVal = val.getZExtValue();
+ } else {
+ result->EvalData.intVal = val.getExtValue();
+ }
+
return result.release();
}
@@ -3541,7 +3649,7 @@ static const ExprEvalResult* evaluateExpr(Expr *expr, CXCursor C) {
result->EvalType = CXEval_Float;
bool ignored;
llvm::APFloat apFloat = ER.Val.getFloat();
- apFloat.convert(llvm::APFloat::IEEEdouble,
+ apFloat.convert(llvm::APFloat::IEEEdouble(),
llvm::APFloat::rmNearestTiesToEven, &ignored);
result->EvalData.floatVal = apFloat.convertToDouble();
return result.release();
@@ -3879,13 +3987,10 @@ CXCursor clang_getTranslationUnitCursor(CXTranslationUnit TU) {
return MakeCXCursor(CXXUnit->getASTContext().getTranslationUnitDecl(), TU);
}
-} // end: extern "C"
-
//===----------------------------------------------------------------------===//
// CXFile Operations.
//===----------------------------------------------------------------------===//
-extern "C" {
CXString clang_getFileName(CXFile SFile) {
if (!SFile)
return cxstring::createNull();
@@ -3954,8 +4059,6 @@ int clang_File_isEqual(CXFile file1, CXFile file2) {
return FEnt1->getUniqueID() == FEnt2->getUniqueID();
}
-} // end: extern "C"
-
//===----------------------------------------------------------------------===//
// CXCursor Operations.
//===----------------------------------------------------------------------===//
@@ -4340,7 +4443,8 @@ CXSourceRange clang_Cursor_getSpellingNameRange(CXCursor C,
}
if (C.kind == CXCursor_CXXMethod || C.kind == CXCursor_Destructor ||
- C.kind == CXCursor_ConversionFunction) {
+ C.kind == CXCursor_ConversionFunction ||
+ C.kind == CXCursor_FunctionDecl) {
if (pieceIndex > 0)
return clang_getNullRange();
if (const FunctionDecl *FD =
@@ -4880,12 +4984,30 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
return cxstring::createRef("OMPDistributeSimdDirective");
case CXCursor_OMPTargetParallelForSimdDirective:
return cxstring::createRef("OMPTargetParallelForSimdDirective");
+ case CXCursor_OMPTargetSimdDirective:
+ return cxstring::createRef("OMPTargetSimdDirective");
+ case CXCursor_OMPTeamsDistributeDirective:
+ return cxstring::createRef("OMPTeamsDistributeDirective");
+ case CXCursor_OMPTeamsDistributeSimdDirective:
+ return cxstring::createRef("OMPTeamsDistributeSimdDirective");
+ case CXCursor_OMPTeamsDistributeParallelForSimdDirective:
+ return cxstring::createRef("OMPTeamsDistributeParallelForSimdDirective");
+ case CXCursor_OMPTeamsDistributeParallelForDirective:
+ return cxstring::createRef("OMPTeamsDistributeParallelForDirective");
+ case CXCursor_OMPTargetTeamsDirective:
+ return cxstring::createRef("OMPTargetTeamsDirective");
+ case CXCursor_OMPTargetTeamsDistributeDirective:
+ return cxstring::createRef("OMPTargetTeamsDistributeDirective");
+ case CXCursor_OMPTargetTeamsDistributeParallelForDirective:
+ return cxstring::createRef("OMPTargetTeamsDistributeParallelForDirective");
case CXCursor_OverloadCandidate:
return cxstring::createRef("OverloadCandidate");
case CXCursor_TypeAliasTemplateDecl:
return cxstring::createRef("TypeAliasTemplateDecl");
case CXCursor_StaticAssert:
return cxstring::createRef("StaticAssert");
+ case CXCursor_FriendDecl:
+ return cxstring::createRef("FriendDecl");
}
llvm_unreachable("Unhandled CXCursorKind");
@@ -5453,8 +5575,6 @@ static SourceRange getFullCursorExtent(CXCursor C, SourceManager &SrcMgr) {
return getRawCursorExtent(C);
}
-extern "C" {
-
CXSourceRange clang_getCursorExtent(CXCursor C) {
SourceRange R = getRawCursorExtent(C);
if (R.isInvalid())
@@ -5607,6 +5727,7 @@ CXCursor clang_getCursorDefinition(CXCursor C) {
case Decl::TemplateTypeParm:
case Decl::EnumConstant:
case Decl::Field:
+ case Decl::Binding:
case Decl::MSProperty:
case Decl::IndirectField:
case Decl::ObjCIvar:
@@ -5619,6 +5740,7 @@ CXCursor clang_getCursorDefinition(CXCursor C) {
case Decl::ObjCImplementation:
case Decl::AccessSpec:
case Decl::LinkageSpec:
+ case Decl::Export:
case Decl::ObjCPropertyImpl:
case Decl::FileScopeAsm:
case Decl::StaticAssert:
@@ -5634,6 +5756,7 @@ CXCursor clang_getCursorDefinition(CXCursor C) {
case Decl::BuiltinTemplate:
case Decl::PragmaComment:
case Decl::PragmaDetectMismatch:
+ case Decl::UsingPack:
return C;
// Declaration kinds that don't make any sense here, but are
@@ -5677,7 +5800,8 @@ CXCursor clang_getCursorDefinition(CXCursor C) {
case Decl::Var:
case Decl::VarTemplateSpecialization:
- case Decl::VarTemplatePartialSpecialization: {
+ case Decl::VarTemplatePartialSpecialization:
+ case Decl::Decomposition: {
// Ask the variable if it has a definition.
if (const VarDecl *Def = cast<VarDecl>(D)->getDefinition())
return MakeCXCursor(Def, TU);
@@ -5944,8 +6068,6 @@ void clang_executeOnThread(void (*fn)(void*), void *user_data,
llvm::llvm_execute_on_thread(fn, user_data, stack_size);
}
-} // end: extern "C"
-
//===----------------------------------------------------------------------===//
// Token-based Operations.
//===----------------------------------------------------------------------===//
@@ -5958,8 +6080,6 @@ void clang_executeOnThread(void (*fn)(void*), void *user_data,
* ptr_data: for identifiers and keywords, an IdentifierInfo*.
* otherwise unused.
*/
-extern "C" {
-
CXTokenKind clang_getTokenKind(CXToken CXTok) {
return static_cast<CXTokenKind>(CXTok.int_data[0]);
}
@@ -6103,7 +6223,7 @@ static void getTokens(ASTUnit *CXXUnit, SourceRange Range,
}
CXTokens.push_back(CXTok);
previousWasAt = Tok.is(tok::at);
- } while (Lex.getBufferLocation() <= EffectiveBufferEnd);
+ } while (Lex.getBufferLocation() < EffectiveBufferEnd);
}
void clang_tokenize(CXTranslationUnit TU, CXSourceRange Range,
@@ -6148,8 +6268,6 @@ void clang_disposeTokens(CXTranslationUnit TU,
free(Tokens);
}
-} // end: extern "C"
-
//===----------------------------------------------------------------------===//
// Token annotation APIs.
//===----------------------------------------------------------------------===//
@@ -6817,8 +6935,6 @@ static void clang_annotateTokensImpl(CXTranslationUnit TU, ASTUnit *CXXUnit,
}
}
-extern "C" {
-
void clang_annotateTokens(CXTranslationUnit TU,
CXToken *Tokens, unsigned NumTokens,
CXCursor *Cursors) {
@@ -6858,13 +6974,10 @@ void clang_annotateTokens(CXTranslationUnit TU,
}
}
-} // end: extern "C"
-
//===----------------------------------------------------------------------===//
// Operations for querying linkage of a cursor.
//===----------------------------------------------------------------------===//
-extern "C" {
CXLinkageKind clang_getCursorLinkage(CXCursor cursor) {
if (!clang_isDeclaration(cursor.kind))
return CXLinkage_Invalid;
@@ -6881,13 +6994,11 @@ CXLinkageKind clang_getCursorLinkage(CXCursor cursor) {
return CXLinkage_Invalid;
}
-} // end: extern "C"
//===----------------------------------------------------------------------===//
// Operations for querying visibility of a cursor.
//===----------------------------------------------------------------------===//
-extern "C" {
CXVisibilityKind clang_getCursorVisibility(CXCursor cursor) {
if (!clang_isDeclaration(cursor.kind))
return CXVisibility_Invalid;
@@ -6902,7 +7013,6 @@ CXVisibilityKind clang_getCursorVisibility(CXCursor cursor) {
return CXVisibility_Invalid;
}
-} // end: extern "C"
//===----------------------------------------------------------------------===//
// Operations for querying language of a cursor.
@@ -6958,8 +7068,6 @@ static CXLanguageKind getDeclLanguage(const Decl *D) {
return CXLanguage_C;
}
-extern "C" {
-
static CXAvailabilityKind getCursorAvailabilityForDecl(const Decl *D) {
if (isa<FunctionDecl>(D) && cast<FunctionDecl>(D)->isDeleted())
return CXAvailability_NotAvailable;
@@ -7429,14 +7537,10 @@ CXFile clang_Module_getTopLevelHeader(CXTranslationUnit TU,
return nullptr;
}
-} // end: extern "C"
-
//===----------------------------------------------------------------------===//
// C++ AST instrospection.
//===----------------------------------------------------------------------===//
-extern "C" {
-
unsigned clang_CXXConstructor_isDefaultConstructor(CXCursor C) {
if (!clang_isDeclaration(C.kind))
return 0;
@@ -7537,13 +7641,11 @@ unsigned clang_CXXMethod_isVirtual(CXCursor C) {
D ? dyn_cast_or_null<CXXMethodDecl>(D->getAsFunction()) : nullptr;
return (Method && Method->isVirtual()) ? 1 : 0;
}
-} // end: extern "C"
//===----------------------------------------------------------------------===//
// Attribute introspection.
//===----------------------------------------------------------------------===//
-extern "C" {
CXType clang_getIBOutletCollectionType(CXCursor C) {
if (C.kind != CXCursor_IBOutletCollectionAttr)
return cxtype::MakeCXType(QualType(), cxcursor::getCursorTU(C));
@@ -7553,7 +7655,6 @@ CXType clang_getIBOutletCollectionType(CXCursor C) {
return cxtype::MakeCXType(A->getInterface(), cxcursor::getCursorTU(C));
}
-} // end: extern "C"
//===----------------------------------------------------------------------===//
// Inspecting memory usage.
@@ -7568,8 +7669,6 @@ static inline void createCXTUResourceUsageEntry(MemUsageEntries &entries,
entries.push_back(entry);
}
-extern "C" {
-
const char *clang_getTUResourceUsageName(CXTUResourceUsageKind kind) {
const char *str = "";
switch (kind) {
@@ -7708,7 +7807,7 @@ CXTUResourceUsage clang_getCXTUResourceUsage(CXTranslationUnit TU) {
CXTUResourceUsage usage = { (void*) entries.get(),
(unsigned) entries->size(),
!entries->empty() ? &(*entries)[0] : nullptr };
- entries.release();
+ (void)entries.release();
return usage;
}
@@ -7756,6 +7855,33 @@ CXSourceRangeList *clang_getSkippedRanges(CXTranslationUnit TU, CXFile file) {
return skipped;
}
+CXSourceRangeList *clang_getAllSkippedRanges(CXTranslationUnit TU) {
+ CXSourceRangeList *skipped = new CXSourceRangeList;
+ skipped->count = 0;
+ skipped->ranges = nullptr;
+
+ if (isNotUsableTU(TU)) {
+ LOG_BAD_TU(TU);
+ return skipped;
+ }
+
+ ASTUnit *astUnit = cxtu::getASTUnit(TU);
+ PreprocessingRecord *ppRec = astUnit->getPreprocessor().getPreprocessingRecord();
+ if (!ppRec)
+ return skipped;
+
+ ASTContext &Ctx = astUnit->getASTContext();
+
+ const std::vector<SourceRange> &SkippedRanges = ppRec->getSkippedRanges();
+
+ skipped->count = SkippedRanges.size();
+ skipped->ranges = new CXSourceRange[skipped->count];
+ for (unsigned i = 0, ei = skipped->count; i != ei; ++i)
+ skipped->ranges[i] = cxloc::translateSourceRange(Ctx, SkippedRanges[i]);
+
+ return skipped;
+}
+
void clang_disposeSourceRangeList(CXSourceRangeList *ranges) {
if (ranges) {
delete[] ranges->ranges;
@@ -7763,8 +7889,6 @@ void clang_disposeSourceRangeList(CXSourceRangeList *ranges) {
}
}
-} // end extern "C"
-
void clang::PrintLibclangResourceUsage(CXTranslationUnit TU) {
CXTUResourceUsage Usage = clang_getCXTUResourceUsage(TU);
for (unsigned I = 0; I != Usage.numEntries; ++I)
@@ -7927,14 +8051,10 @@ cxindex::checkForMacroInMacroDefinition(const MacroInfo *MI, SourceLocation Loc,
return checkForMacroInMacroDefinition(MI, Tok, TU);
}
-extern "C" {
-
CXString clang_getClangVersion() {
return cxstring::createDup(getClangFullVersion());
}
-} // end: extern "C"
-
Logger &cxindex::Logger::operator<<(CXTranslationUnit TU) {
if (TU) {
if (ASTUnit *Unit = cxtu::getASTUnit(TU)) {
@@ -8040,4 +8160,10 @@ cxindex::Logger::~Logger() {
extern volatile int ClangTidyPluginAnchorSource;
static int LLVM_ATTRIBUTE_UNUSED ClangTidyPluginAnchorDestination =
ClangTidyPluginAnchorSource;
+
+// This anchor is used to force the linker to link the clang-include-fixer
+// plugin.
+extern volatile int ClangIncludeFixerPluginAnchorSource;
+static int LLVM_ATTRIBUTE_UNUSED ClangIncludeFixerPluginAnchorDestination =
+ ClangIncludeFixerPluginAnchorSource;
#endif
diff --git a/tools/libclang/CIndexCXX.cpp b/tools/libclang/CIndexCXX.cpp
index 78e89d94d3c1..028b64a2b2d9 100644
--- a/tools/libclang/CIndexCXX.cpp
+++ b/tools/libclang/CIndexCXX.cpp
@@ -20,8 +20,6 @@
using namespace clang;
using namespace clang::cxcursor;
-extern "C" {
-
unsigned clang_isVirtualBase(CXCursor C) {
if (C.kind != CXCursor_CXXBaseSpecifier)
return 0;
@@ -123,5 +121,3 @@ CXCursor clang_getSpecializedCursorTemplate(CXCursor C) {
return MakeCXCursor(Template, getCursorTU(C));
}
-
-} // end extern "C"
diff --git a/tools/libclang/CIndexCodeCompletion.cpp b/tools/libclang/CIndexCodeCompletion.cpp
index 344ed27021a1..12895c4a9b7a 100644
--- a/tools/libclang/CIndexCodeCompletion.cpp
+++ b/tools/libclang/CIndexCodeCompletion.cpp
@@ -53,8 +53,6 @@
using namespace clang;
using namespace clang::cxindex;
-extern "C" {
-
enum CXCompletionChunkKind
clang_getCompletionChunkKind(CXCompletionString completion_string,
unsigned chunk_number) {
@@ -346,8 +344,6 @@ AllocatedCXCodeCompleteResults::~AllocatedCXCodeCompleteResults() {
fprintf(stderr, "--- %u completion results\n",
--CodeCompletionResultObjects);
}
-
-} // end extern "C"
static unsigned long long getContextsForContextKind(
enum CodeCompletionContext::Kind kind,
@@ -794,7 +790,6 @@ clang_codeCompleteAt_Impl(CXTranslationUnit TU, const char *complete_filename,
return Results;
}
-extern "C" {
CXCodeCompleteResults *clang_codeCompleteAt(CXTranslationUnit TU,
const char *complete_filename,
unsigned complete_line,
@@ -916,8 +911,6 @@ CXString clang_codeCompleteGetObjCSelector(CXCodeCompleteResults *ResultsIn) {
return cxstring::createDup(Results->Selector);
}
-} // end extern "C"
-
/// \brief Simple utility function that appends a \p New string to the given
/// \p Old string, using the \p Buffer for storage.
///
@@ -990,9 +983,7 @@ namespace {
};
}
-extern "C" {
- void clang_sortCodeCompletionResults(CXCompletionResult *Results,
- unsigned NumResults) {
- std::stable_sort(Results, Results + NumResults, OrderCompletionResults());
- }
+void clang_sortCodeCompletionResults(CXCompletionResult *Results,
+ unsigned NumResults) {
+ std::stable_sort(Results, Results + NumResults, OrderCompletionResults());
}
diff --git a/tools/libclang/CIndexDiagnostic.cpp b/tools/libclang/CIndexDiagnostic.cpp
index 9ba36a6a0f8a..de223d3043a3 100644
--- a/tools/libclang/CIndexDiagnostic.cpp
+++ b/tools/libclang/CIndexDiagnostic.cpp
@@ -16,13 +16,11 @@
#include "CXSourceLocation.h"
#include "CXString.h"
+#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Frontend/ASTUnit.h"
-#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/DiagnosticRenderer.h"
-#include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
@@ -207,8 +205,6 @@ CXDiagnosticSetImpl *cxdiag::lazyCreateDiags(CXTranslationUnit TU,
//-----------------------------------------------------------------------------
// C Interface Routines
//-----------------------------------------------------------------------------
-extern "C" {
-
unsigned clang_getNumDiagnostics(CXTranslationUnit Unit) {
if (cxtu::isNotUsableTU(Unit)) {
LOG_BAD_TU(Unit);
@@ -479,5 +475,3 @@ unsigned clang_getNumDiagnosticsInSet(CXDiagnosticSet Diags) {
return D->getNumDiagnostics();
return 0;
}
-
-} // end extern "C"
diff --git a/tools/libclang/CIndexHigh.cpp b/tools/libclang/CIndexHigh.cpp
index d2baa13be9dd..d4666c2288c9 100644
--- a/tools/libclang/CIndexHigh.cpp
+++ b/tools/libclang/CIndexHigh.cpp
@@ -411,7 +411,7 @@ extern "C" {
CXResult clang_findReferencesInFile(CXCursor cursor, CXFile file,
CXCursorAndRangeVisitor visitor) {
- LogRef Log = Logger::make(LLVM_FUNCTION_NAME);
+ LogRef Log = Logger::make(__func__);
if (clang_Cursor_isNull(cursor)) {
if (Log)
@@ -485,7 +485,7 @@ CXResult clang_findIncludesInFile(CXTranslationUnit TU, CXFile file,
return CXResult_Invalid;
}
- LogRef Log = Logger::make(LLVM_FUNCTION_NAME);
+ LogRef Log = Logger::make(__func__);
if (!file) {
if (Log)
*Log << "Null file";
@@ -535,4 +535,3 @@ CXResult clang_findIncludesInFileWithBlock(CXTranslationUnit TU,
}
} // end: extern "C"
-
diff --git a/tools/libclang/CIndexInclusionStack.cpp b/tools/libclang/CIndexInclusionStack.cpp
index 095937453351..4b021fc4cbeb 100644
--- a/tools/libclang/CIndexInclusionStack.cpp
+++ b/tools/libclang/CIndexInclusionStack.cpp
@@ -17,8 +17,6 @@
#include "CXTranslationUnit.h"
#include "clang/AST/DeclVisitor.h"
#include "clang/Frontend/ASTUnit.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/Support/raw_ostream.h"
using namespace clang;
static void getInclusions(const SrcMgr::SLocEntry &(SourceManager::*Getter)(unsigned, bool*) const, unsigned n,
@@ -70,7 +68,6 @@ static void getInclusions(const SrcMgr::SLocEntry &(SourceManager::*Getter)(unsi
}
-extern "C" {
void clang_getInclusions(CXTranslationUnit TU, CXInclusionVisitor CB,
CXClientData clientData) {
if (cxtu::isNotUsableTU(TU)) {
@@ -98,4 +95,3 @@ void clang_getInclusions(CXTranslationUnit TU, CXInclusionVisitor CB,
getInclusions(&SourceManager::getLocalSLocEntry, n, TU, CB, clientData);
}
-} // end extern C
diff --git a/tools/libclang/CIndexUSRs.cpp b/tools/libclang/CIndexUSRs.cpp
index 69d60c9d44f2..7cd7b6f1cd9e 100644
--- a/tools/libclang/CIndexUSRs.cpp
+++ b/tools/libclang/CIndexUSRs.cpp
@@ -36,8 +36,6 @@ bool cxcursor::getDeclCursorUSR(const Decl *D, SmallVectorImpl<char> &Buf) {
return generateUSRForDecl(D, Buf);
}
-extern "C" {
-
CXString clang_getCursorUSR(CXCursor C) {
const CXCursorKind &K = clang_getCursorKind(C);
@@ -140,5 +138,3 @@ CXString clang_constructUSR_ObjCProperty(const char *property,
generateUSRForObjCProperty(property, /*isClassProp=*/false, OS);
return cxstring::createDup(OS.str());
}
-
-} // end extern "C"
diff --git a/tools/libclang/CIndexer.cpp b/tools/libclang/CIndexer.cpp
index 91154cc1c3a0..694ed606306c 100644
--- a/tools/libclang/CIndexer.cpp
+++ b/tools/libclang/CIndexer.cpp
@@ -12,22 +12,13 @@
//===----------------------------------------------------------------------===//
#include "CIndexer.h"
-#include "clang/AST/Decl.h"
-#include "clang/AST/DeclVisitor.h"
-#include "clang/AST/StmtVisitor.h"
-#include "clang/Basic/FileManager.h"
-#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/LLVM.h"
#include "clang/Basic/Version.h"
-#include "clang/Sema/CodeCompleteConsumer.h"
-#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/Config/llvm-config.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
#include "llvm/Support/Program.h"
-#include "llvm/Support/raw_ostream.h"
#include <cstdio>
-#include <sstream>
-#include <vector>
#ifdef __CYGWIN__
#include <cygwin/version.h>
diff --git a/tools/libclang/CIndexer.h b/tools/libclang/CIndexer.h
index 47e30c30ba11..b227f943f7b3 100644
--- a/tools/libclang/CIndexer.h
+++ b/tools/libclang/CIndexer.h
@@ -17,11 +17,8 @@
#include "clang-c/Index.h"
#include "clang/Frontend/PCHContainerOperations.h"
-#include "clang/Lex/ModuleLoader.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Path.h"
+#include "llvm/ADT/STLExtras.h"
#include <utility>
-#include <vector>
namespace llvm {
class CrashRecoveryContext;
diff --git a/tools/libclang/CLog.h b/tools/libclang/CLog.h
index b9309ed19239..e1d6a57e4a01 100644
--- a/tools/libclang/CLog.h
+++ b/tools/libclang/CLog.h
@@ -98,6 +98,6 @@ public:
/// \endcode
#define LOG_SECTION(NAME) \
if (clang::cxindex::LogRef Log = clang::cxindex::Logger::make(NAME))
-#define LOG_FUNC_SECTION LOG_SECTION(LLVM_FUNCTION_NAME)
+#define LOG_FUNC_SECTION LOG_SECTION(__func__)
#endif
diff --git a/tools/libclang/CMakeLists.txt b/tools/libclang/CMakeLists.txt
index 630be124660d..2dd670307636 100644
--- a/tools/libclang/CMakeLists.txt
+++ b/tools/libclang/CMakeLists.txt
@@ -50,6 +50,7 @@ endif ()
if (TARGET clangTidyPlugin)
add_definitions(-DCLANG_TOOL_EXTRA_BUILD)
list(APPEND LIBS clangTidyPlugin)
+ list(APPEND LIBS clangIncludeFixerPlugin)
endif ()
find_library(DL_LIBRARY_PATH dl)
diff --git a/tools/libclang/CXComment.cpp b/tools/libclang/CXComment.cpp
index 9cc05ed4e127..028fdf1d3a8b 100644
--- a/tools/libclang/CXComment.cpp
+++ b/tools/libclang/CXComment.cpp
@@ -11,15 +11,14 @@
//
//===----------------------------------------------------------------------===//
-#include "clang-c/Index.h"
#include "CXComment.h"
#include "CXCursor.h"
#include "CXString.h"
#include "clang-c/Documentation.h"
+#include "clang-c/Index.h"
#include "clang/AST/Decl.h"
#include "clang/Index/CommentToXML.h"
#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/ErrorHandling.h"
#include <climits>
@@ -27,8 +26,6 @@ using namespace clang;
using namespace clang::comments;
using namespace clang::cxcomment;
-extern "C" {
-
CXComment clang_Cursor_getParsedComment(CXCursor C) {
using namespace clang::cxcursor;
@@ -407,5 +404,3 @@ CXString clang_FullComment_getAsXML(CXComment CXC) {
return cxstring::createDup(XML.str());
}
-} // end extern "C"
-
diff --git a/tools/libclang/CXCompilationDatabase.cpp b/tools/libclang/CXCompilationDatabase.cpp
index 82498bf54c74..c122ec8a6db4 100644
--- a/tools/libclang/CXCompilationDatabase.cpp
+++ b/tools/libclang/CXCompilationDatabase.cpp
@@ -6,8 +6,6 @@
using namespace clang;
using namespace clang::tooling;
-extern "C" {
-
// FIXME: do something more useful with the error message
CXCompilationDatabase
clang_CompilationDatabase_fromDirectory(const char *BuildDir,
@@ -180,5 +178,3 @@ clang_CompileCommand_getMappedSourceContent(CXCompileCommand CCmd, unsigned I)
return cxstring::createRef(Cmd->MappedSources[I].second.c_str());
}
-
-} // end: extern "C"
diff --git a/tools/libclang/CXCursor.cpp b/tools/libclang/CXCursor.cpp
index 19ab0f929c85..9344bfa6a60f 100644
--- a/tools/libclang/CXCursor.cpp
+++ b/tools/libclang/CXCursor.cpp
@@ -243,6 +243,8 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent,
case Stmt::ChooseExprClass:
case Stmt::DesignatedInitExprClass:
case Stmt::DesignatedInitUpdateExprClass:
+ case Stmt::ArrayInitLoopExprClass:
+ case Stmt::ArrayInitIndexExprClass:
case Stmt::ExprWithCleanupsClass:
case Stmt::ExpressionTraitExprClass:
case Stmt::ExtVectorElementExprClass:
@@ -650,6 +652,30 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent,
case Stmt::OMPTargetParallelForSimdDirectiveClass:
K = CXCursor_OMPTargetParallelForSimdDirective;
break;
+ case Stmt::OMPTargetSimdDirectiveClass:
+ K = CXCursor_OMPTargetSimdDirective;
+ break;
+ case Stmt::OMPTeamsDistributeDirectiveClass:
+ K = CXCursor_OMPTeamsDistributeDirective;
+ break;
+ case Stmt::OMPTeamsDistributeSimdDirectiveClass:
+ K = CXCursor_OMPTeamsDistributeSimdDirective;
+ break;
+ case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
+ K = CXCursor_OMPTeamsDistributeParallelForSimdDirective;
+ break;
+ case Stmt::OMPTeamsDistributeParallelForDirectiveClass:
+ K = CXCursor_OMPTeamsDistributeParallelForDirective;
+ break;
+ case Stmt::OMPTargetTeamsDirectiveClass:
+ K = CXCursor_OMPTargetTeamsDirective;
+ break;
+ case Stmt::OMPTargetTeamsDistributeDirectiveClass:
+ K = CXCursor_OMPTargetTeamsDistributeDirective;
+ break;
+ case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
+ K = CXCursor_OMPTargetTeamsDistributeParallelForDirective;
+ break;
}
CXCursor C = { K, 0, { Parent, S, TU } };
@@ -1087,8 +1113,6 @@ bool cxcursor::isFirstInDeclGroup(CXCursor C) {
// libclang CXCursor APIs
//===----------------------------------------------------------------------===//
-extern "C" {
-
int clang_Cursor_isNull(CXCursor cursor) {
return clang_equalCursors(cursor, clang_getNullCursor());
}
@@ -1278,8 +1302,6 @@ unsigned long long clang_Cursor_getTemplateArgumentUnsignedValue(CXCursor C,
return TA.getAsIntegral().getZExtValue();
}
-} // end: extern "C"
-
//===----------------------------------------------------------------------===//
// CXCursorSet.
//===----------------------------------------------------------------------===//
@@ -1313,7 +1335,6 @@ public:
};
}
-extern "C" {
CXCursorSet clang_createCXCursorSet() {
return packCXCursorSet(new CXCursorSet_Impl());
}
@@ -1376,7 +1397,6 @@ CXCompletionString clang_getCursorCompletionString(CXCursor cursor) {
}
return nullptr;
}
-} // end: extern C.
namespace {
struct OverridenCursorsPool {
@@ -1401,7 +1421,6 @@ void cxcursor::disposeOverridenCXCursorsPool(void *pool) {
delete static_cast<OverridenCursorsPool*>(pool);
}
-extern "C" {
void clang_getOverriddenCursors(CXCursor cursor,
CXCursor **overridden,
unsigned *num_overridden) {
@@ -1523,5 +1542,3 @@ CXType clang_Cursor_getReceiverType(CXCursor C) {
return cxtype::MakeCXType(QualType(), TU);
}
-
-} // end: extern "C"
diff --git a/tools/libclang/CXIndexDataConsumer.cpp b/tools/libclang/CXIndexDataConsumer.cpp
index 59fa92bb21e2..45198dd1b168 100644
--- a/tools/libclang/CXIndexDataConsumer.cpp
+++ b/tools/libclang/CXIndexDataConsumer.cpp
@@ -478,6 +478,14 @@ void CXIndexDataConsumer::importedModule(const ImportDecl *ImportD) {
if (!Mod)
return;
+ // If the imported module is part of the top-level module that we're
+ // indexing, it doesn't correspond to an imported AST file.
+ // FIXME: This assumes that AST files and top-level modules directly
+ // correspond, which is unlikely to remain true forever.
+ if (Module *SrcMod = ImportD->getImportedOwningModule())
+ if (SrcMod->getTopLevelModule() == Mod->getTopLevelModule())
+ return;
+
CXIdxImportedASTFileInfo Info = {
static_cast<CXFile>(
const_cast<FileEntry *>(Mod->getASTFile())),
@@ -1134,7 +1142,7 @@ void CXIndexDataConsumer::translateLoc(SourceLocation Loc,
static CXIdxEntityKind getEntityKindFromSymbolKind(SymbolKind K, SymbolLanguage L);
static CXIdxEntityCXXTemplateKind
-getEntityKindFromSymbolSubKinds(SymbolSubKindSet K);
+getEntityKindFromSymbolProperties(SymbolPropertySet K);
static CXIdxEntityLanguage getEntityLangFromSymbolLang(SymbolLanguage L);
void CXIndexDataConsumer::getEntityInfo(const NamedDecl *D,
@@ -1150,7 +1158,7 @@ void CXIndexDataConsumer::getEntityInfo(const NamedDecl *D,
SymbolInfo SymInfo = getSymbolInfo(D);
EntityInfo.kind = getEntityKindFromSymbolKind(SymInfo.Kind, SymInfo.Lang);
- EntityInfo.templateKind = getEntityKindFromSymbolSubKinds(SymInfo.SubKinds);
+ EntityInfo.templateKind = getEntityKindFromSymbolProperties(SymInfo.Properties);
EntityInfo.lang = getEntityLangFromSymbolLang(SymInfo.Lang);
if (D->hasAttrs()) {
@@ -1290,12 +1298,12 @@ static CXIdxEntityKind getEntityKindFromSymbolKind(SymbolKind K, SymbolLanguage
}
static CXIdxEntityCXXTemplateKind
-getEntityKindFromSymbolSubKinds(SymbolSubKindSet K) {
- if (K & (unsigned)SymbolSubKind::TemplatePartialSpecialization)
+getEntityKindFromSymbolProperties(SymbolPropertySet K) {
+ if (K & (unsigned)SymbolProperty::TemplatePartialSpecialization)
return CXIdxEntity_TemplatePartialSpecialization;
- if (K & (unsigned)SymbolSubKind::TemplateSpecialization)
+ if (K & (unsigned)SymbolProperty::TemplateSpecialization)
return CXIdxEntity_TemplateSpecialization;
- if (K & (unsigned)SymbolSubKind::Generic)
+ if (K & (unsigned)SymbolProperty::Generic)
return CXIdxEntity_Template;
return CXIdxEntity_NonTemplate;
}
diff --git a/tools/libclang/CXIndexDataConsumer.h b/tools/libclang/CXIndexDataConsumer.h
index 308fa79488de..406831f1ddce 100644
--- a/tools/libclang/CXIndexDataConsumer.h
+++ b/tools/libclang/CXIndexDataConsumer.h
@@ -16,7 +16,6 @@
#include "clang/AST/DeclGroup.h"
#include "clang/AST/DeclObjC.h"
#include "llvm/ADT/DenseSet.h"
-#include <deque>
namespace clang {
class FileEntry;
diff --git a/tools/libclang/CXLoadedDiagnostic.cpp b/tools/libclang/CXLoadedDiagnostic.cpp
index 2c10d34844b7..36c3dcabb924 100644
--- a/tools/libclang/CXLoadedDiagnostic.cpp
+++ b/tools/libclang/CXLoadedDiagnostic.cpp
@@ -18,13 +18,11 @@
#include "clang/Basic/LLVM.h"
#include "clang/Frontend/SerializedDiagnosticReader.h"
#include "clang/Frontend/SerializedDiagnostics.h"
-#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Bitcode/BitstreamReader.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/MemoryBuffer.h"
using namespace clang;
@@ -389,11 +387,9 @@ std::error_code DiagLoader::visitDiagnosticRecord(
return std::error_code();
}
-extern "C" {
CXDiagnosticSet clang_loadDiagnostics(const char *file,
enum CXLoadDiag_Error *error,
CXString *errorString) {
DiagLoader L(error, errorString);
return L.load(file);
}
-} // end extern 'C'.
diff --git a/tools/libclang/CXLoadedDiagnostic.h b/tools/libclang/CXLoadedDiagnostic.h
index d5006a4444a4..1209d76669f8 100644
--- a/tools/libclang/CXLoadedDiagnostic.h
+++ b/tools/libclang/CXLoadedDiagnostic.h
@@ -17,7 +17,6 @@
#include "CIndexDiagnostic.h"
#include "llvm/ADT/StringRef.h"
#include "clang/Basic/LLVM.h"
-#include <string>
#include <vector>
namespace clang {
diff --git a/tools/libclang/CXSourceLocation.cpp b/tools/libclang/CXSourceLocation.cpp
index 1b7464b25af9..2e0ea4e44099 100644
--- a/tools/libclang/CXSourceLocation.cpp
+++ b/tools/libclang/CXSourceLocation.cpp
@@ -38,8 +38,6 @@ static bool isASTUnitSourceLocation(const CXSourceLocation &L) {
// Basic construction and comparison of CXSourceLocations and CXSourceRanges.
//===----------------------------------------------------------------------===//
-extern "C" {
-
CXSourceLocation clang_getNullLocation() {
CXSourceLocation Result = { { nullptr, nullptr }, 0 };
return Result;
@@ -110,14 +108,10 @@ CXSourceLocation clang_getRangeEnd(CXSourceRange range) {
return Result;
}
-} // end extern "C"
-
//===----------------------------------------------------------------------===//
// Getting CXSourceLocations and CXSourceRanges from a translation unit.
//===----------------------------------------------------------------------===//
-extern "C" {
-
CXSourceLocation clang_getLocation(CXTranslationUnit TU,
CXFile file,
unsigned line,
@@ -131,7 +125,7 @@ CXSourceLocation clang_getLocation(CXTranslationUnit TU,
if (line == 0 || column == 0)
return clang_getNullLocation();
- LogRef Log = Logger::make(LLVM_FUNCTION_NAME);
+ LogRef Log = Logger::make(__func__);
ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
ASTUnit::ConcurrencyCheck Check(*CXXUnit);
const FileEntry *File = static_cast<const FileEntry *>(file);
@@ -139,16 +133,17 @@ CXSourceLocation clang_getLocation(CXTranslationUnit TU,
if (SLoc.isInvalid()) {
if (Log)
*Log << llvm::format("(\"%s\", %d, %d) = invalid",
- File->getName(), line, column);
+ File->getName().str().c_str(), line, column);
return clang_getNullLocation();
}
CXSourceLocation CXLoc =
cxloc::translateSourceLocation(CXXUnit->getASTContext(), SLoc);
if (Log)
- *Log << llvm::format("(\"%s\", %d, %d) = ", File->getName(), line, column)
+ *Log << llvm::format("(\"%s\", %d, %d) = ", File->getName().str().c_str(),
+ line, column)
<< CXLoc;
-
+
return CXLoc;
}
@@ -173,8 +168,6 @@ CXSourceLocation clang_getLocationForOffset(CXTranslationUnit TU,
return cxloc::translateSourceLocation(CXXUnit->getASTContext(), SLoc);
}
-} // end extern "C"
-
//===----------------------------------------------------------------------===//
// Routines for expanding and manipulating CXSourceLocations, regardless
// of their origin.
@@ -204,8 +197,6 @@ static void createNullLocation(CXString *filename, unsigned *line,
*offset = 0;
}
-extern "C" {
-
int clang_Location_isInSystemHeader(CXSourceLocation location) {
const SourceLocation Loc =
SourceLocation::getFromRawEncoding(location.int_data);
@@ -381,5 +372,3 @@ void clang_getFileLocation(CXSourceLocation location,
if (offset)
*offset = FileOffset;
}
-
-} // end extern "C"
diff --git a/tools/libclang/CXStoredDiagnostic.cpp b/tools/libclang/CXStoredDiagnostic.cpp
index faaf746a1e70..f2e9c1da28f6 100644
--- a/tools/libclang/CXStoredDiagnostic.cpp
+++ b/tools/libclang/CXStoredDiagnostic.cpp
@@ -19,10 +19,7 @@
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/FrontendDiagnostic.h"
-#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Twine.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/raw_ostream.h"
using namespace clang;
using namespace clang::cxloc;
diff --git a/tools/libclang/CXString.cpp b/tools/libclang/CXString.cpp
index 1ccbed3b5c24..448603179203 100644
--- a/tools/libclang/CXString.cpp
+++ b/tools/libclang/CXString.cpp
@@ -17,7 +17,6 @@
#include "CXTranslationUnit.h"
#include "clang-c/Index.h"
#include "clang/Frontend/ASTUnit.h"
-#include "llvm/ADT/SmallString.h"
#include "llvm/Support/ErrorHandling.h"
using namespace clang;
@@ -162,7 +161,6 @@ bool isManagedByPool(CXString str) {
// libClang public APIs.
//===----------------------------------------------------------------------===//
-extern "C" {
const char *clang_getCString(CXString string) {
if (string.private_flags == (unsigned) CXS_StringBuf) {
return static_cast<const cxstring::CXStringBuf *>(string.data)->Data.data();
@@ -192,5 +190,3 @@ void clang_disposeStringSet(CXStringSet *set) {
delete set;
}
-} // end: extern "C"
-
diff --git a/tools/libclang/CXType.cpp b/tools/libclang/CXType.cpp
index 4fcd8864cd37..66caf340d195 100644
--- a/tools/libclang/CXType.cpp
+++ b/tools/libclang/CXType.cpp
@@ -143,7 +143,44 @@ static inline CXTranslationUnit GetTU(CXType CT) {
return static_cast<CXTranslationUnit>(CT.data[1]);
}
-extern "C" {
+static Optional<ArrayRef<TemplateArgument>>
+GetTemplateArguments(QualType Type) {
+ assert(!Type.isNull());
+ if (const auto *Specialization = Type->getAs<TemplateSpecializationType>())
+ return Specialization->template_arguments();
+
+ if (const auto *RecordDecl = Type->getAsCXXRecordDecl()) {
+ const auto *TemplateDecl =
+ dyn_cast<ClassTemplateSpecializationDecl>(RecordDecl);
+ if (TemplateDecl)
+ return TemplateDecl->getTemplateArgs().asArray();
+ }
+
+ return None;
+}
+
+static Optional<QualType> TemplateArgumentToQualType(const TemplateArgument &A) {
+ if (A.getKind() == TemplateArgument::Type)
+ return A.getAsType();
+ return None;
+}
+
+static Optional<QualType>
+FindTemplateArgumentTypeAt(ArrayRef<TemplateArgument> TA, unsigned index) {
+ unsigned current = 0;
+ for (const auto &A : TA) {
+ if (A.getKind() == TemplateArgument::Pack) {
+ if (index < current + A.pack_size())
+ return TemplateArgumentToQualType(A.getPackAsArray()[index - current]);
+ current += A.pack_size();
+ continue;
+ }
+ if (current == index)
+ return TemplateArgumentToQualType(A);
+ current++;
+ }
+ return None;
+}
CXType clang_getCursorType(CXCursor C) {
using namespace cxcursor;
@@ -531,6 +568,7 @@ CXCallingConv clang_getFunctionTypeCallingConv(CXType X) {
TCALLINGCONV(X86FastCall);
TCALLINGCONV(X86ThisCall);
TCALLINGCONV(X86Pascal);
+ TCALLINGCONV(X86RegCall);
TCALLINGCONV(X86VectorCall);
TCALLINGCONV(X86_64Win64);
TCALLINGCONV(X86_64SysV);
@@ -901,12 +939,11 @@ CXString clang_getDeclObjCTypeEncoding(CXCursor C) {
std::string encoding;
if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) {
- if (Ctx.getObjCEncodingForMethodDecl(OMD, encoding))
- return cxstring::createRef("?");
+ encoding = Ctx.getObjCEncodingForMethodDecl(OMD);
} else if (const ObjCPropertyDecl *OPD = dyn_cast<ObjCPropertyDecl>(D))
- Ctx.getObjCEncodingForPropertyDecl(OPD, nullptr, encoding);
+ encoding = Ctx.getObjCEncodingForPropertyDecl(OPD, nullptr);
else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
- Ctx.getObjCEncodingForFunctionDecl(FD, encoding);
+ encoding = Ctx.getObjCEncodingForFunctionDecl(FD);
else {
QualType Ty;
if (const TypeDecl *TD = dyn_cast<TypeDecl>(D))
@@ -920,38 +957,37 @@ CXString clang_getDeclObjCTypeEncoding(CXCursor C) {
return cxstring::createDup(encoding);
}
+static unsigned GetTemplateArgumentArraySize(ArrayRef<TemplateArgument> TA) {
+ unsigned size = TA.size();
+ for (const auto &Arg : TA)
+ if (Arg.getKind() == TemplateArgument::Pack)
+ size += Arg.pack_size() - 1;
+ return size;
+}
+
int clang_Type_getNumTemplateArguments(CXType CT) {
QualType T = GetQualType(CT);
if (T.isNull())
return -1;
- const CXXRecordDecl *RecordDecl = T->getAsCXXRecordDecl();
- if (!RecordDecl)
- return -1;
- const ClassTemplateSpecializationDecl *TemplateDecl =
- dyn_cast<ClassTemplateSpecializationDecl>(RecordDecl);
- if (!TemplateDecl)
+
+ auto TA = GetTemplateArguments(T);
+ if (!TA)
return -1;
- return TemplateDecl->getTemplateArgs().size();
+
+ return GetTemplateArgumentArraySize(TA.getValue());
}
-CXType clang_Type_getTemplateArgumentAsType(CXType CT, unsigned i) {
+CXType clang_Type_getTemplateArgumentAsType(CXType CT, unsigned index) {
QualType T = GetQualType(CT);
if (T.isNull())
return MakeCXType(QualType(), GetTU(CT));
- const CXXRecordDecl *RecordDecl = T->getAsCXXRecordDecl();
- if (!RecordDecl)
- return MakeCXType(QualType(), GetTU(CT));
- const ClassTemplateSpecializationDecl *TemplateDecl =
- dyn_cast<ClassTemplateSpecializationDecl>(RecordDecl);
- if (!TemplateDecl)
- return MakeCXType(QualType(), GetTU(CT));
- const TemplateArgumentList &TA = TemplateDecl->getTemplateArgs();
- if (TA.size() <= i)
- return MakeCXType(QualType(), GetTU(CT));
- const TemplateArgument &A = TA.get(i);
- if (A.getKind() != TemplateArgument::Type)
+
+ auto TA = GetTemplateArguments(T);
+ if (!TA)
return MakeCXType(QualType(), GetTU(CT));
- return MakeCXType(A.getAsType(), GetTU(CT));
+
+ Optional<QualType> QT = FindTemplateArgumentTypeAt(TA.getValue(), index);
+ return MakeCXType(QT.getValueOr(QualType()), GetTU(CT));
}
unsigned clang_Type_visitFields(CXType PT,
@@ -1000,5 +1036,3 @@ CXType clang_Type_getNamedType(CXType CT){
return MakeCXType(QualType(), GetTU(CT));
}
-
-} // end: extern "C"
diff --git a/tools/libclang/CursorVisitor.h b/tools/libclang/CursorVisitor.h
index a2dfaeedccc8..82f251a348f0 100644
--- a/tools/libclang/CursorVisitor.h
+++ b/tools/libclang/CursorVisitor.h
@@ -239,7 +239,8 @@ public:
bool VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
bool VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
bool VisitStaticAssertDecl(StaticAssertDecl *D);
-
+ bool VisitFriendDecl(FriendDecl *D);
+
// Name visitor
bool VisitDeclarationNameInfo(DeclarationNameInfo Name);
bool VisitNestedNameSpecifier(NestedNameSpecifier *NNS, SourceRange Range);
diff --git a/tools/libclang/Indexing.cpp b/tools/libclang/Indexing.cpp
index fe14cb2664af..c18b5402aa71 100644
--- a/tools/libclang/Indexing.cpp
+++ b/tools/libclang/Indexing.cpp
@@ -26,7 +26,7 @@
#include "clang/Lex/PPCallbacks.h"
#include "clang/Lex/PPConditionalDirectiveRecord.h"
#include "clang/Lex/Preprocessor.h"
-#include "clang/Sema/SemaConsumer.h"
+#include "clang/Lex/PreprocessorOptions.h"
#include "llvm/Support/CrashRecoveryContext.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Mutex.h"
@@ -687,8 +687,6 @@ static CXErrorCode clang_indexTranslationUnit_Impl(
// libclang public APIs.
//===----------------------------------------------------------------------===//
-extern "C" {
-
int clang_index_isEntityObjCContainerKind(CXIdxEntityKind K) {
return CXIdxEntity_ObjCClass <= K && K <= CXIdxEntity_ObjCCategory;
}
@@ -978,5 +976,3 @@ CXSourceLocation clang_indexLoc_getCXSourceLocation(CXIdxLoc location) {
return cxloc::translateSourceLocation(DataConsumer.getASTContext(), Loc);
}
-} // end: extern "C"
-
diff --git a/tools/libclang/libclang.exports b/tools/libclang/libclang.exports
index c8fe0a21d09d..222cb678395e 100644
--- a/tools/libclang/libclang.exports
+++ b/tools/libclang/libclang.exports
@@ -142,6 +142,7 @@ clang_findReferencesInFile
clang_findReferencesInFileWithBlock
clang_formatDiagnostic
clang_free
+clang_getAllSkippedRanges
clang_getArgType
clang_getArrayElementType
clang_getArraySize
@@ -334,6 +335,9 @@ clang_Cursor_hasAttrs
clang_Cursor_Evaluate
clang_EvalResult_getKind
clang_EvalResult_getAsInt
+clang_EvalResult_getAsLongLong
+clang_EvalResult_getAsUnsigned
+clang_EvalResult_isUnsignedInt
clang_EvalResult_getAsDouble
clang_EvalResult_getAsStr
clang_EvalResult_dispose
diff --git a/tools/scan-build-py/libscanbuild/analyze.py b/tools/scan-build-py/libscanbuild/analyze.py
index 0ed0aef83873..244c34b75837 100644
--- a/tools/scan-build-py/libscanbuild/analyze.py
+++ b/tools/scan-build-py/libscanbuild/analyze.py
@@ -269,6 +269,9 @@ def validate(parser, args, from_build_command):
""" Validation done by the parser itself, but semantic check still
needs to be done. This method is doing that. """
+ # Make plugins always a list. (It might be None when not specified.)
+ args.plugins = args.plugins if args.plugins else []
+
if args.help_checkers_verbose:
print_checkers(get_checkers(args.clang, args.plugins))
parser.exit()
diff --git a/tools/scan-build-py/libscanbuild/clang.py b/tools/scan-build-py/libscanbuild/clang.py
index 0c3454b16a76..833e77d28bbe 100644
--- a/tools/scan-build-py/libscanbuild/clang.py
+++ b/tools/scan-build-py/libscanbuild/clang.py
@@ -15,142 +15,143 @@ from libscanbuild.shell import decode
__all__ = ['get_version', 'get_arguments', 'get_checkers']
+# regex for activated checker
+ACTIVE_CHECKER_PATTERN = re.compile(r'^-analyzer-checker=(.*)$')
-def get_version(cmd):
- """ Returns the compiler version as string. """
- lines = subprocess.check_output([cmd, '-v'], stderr=subprocess.STDOUT)
- return lines.decode('ascii').splitlines()[0]
+def get_version(clang):
+ """ Returns the compiler version as string.
+
+ :param clang: the compiler we are using
+ :return: the version string printed to stderr """
+
+ output = subprocess.check_output([clang, '-v'], stderr=subprocess.STDOUT)
+ return output.decode('utf-8').splitlines()[0]
def get_arguments(command, cwd):
""" Capture Clang invocation.
- This method returns the front-end invocation that would be executed as
- a result of the given driver invocation. """
-
- def lastline(stream):
- last = None
- for line in stream:
- last = line
- if last is None:
- raise Exception("output not found")
- return last
+ :param command: the compilation command
+ :param cwd: the current working directory
+ :return: the detailed front-end invocation command """
cmd = command[:]
cmd.insert(1, '-###')
logging.debug('exec command in %s: %s', cwd, ' '.join(cmd))
- child = subprocess.Popen(cmd,
- cwd=cwd,
- universal_newlines=True,
- stdout=subprocess.PIPE,
- stderr=subprocess.STDOUT)
- line = lastline(child.stdout)
- child.stdout.close()
- child.wait()
- if child.returncode == 0:
- if re.search(r'clang(.*): error:', line):
- raise Exception(line)
- return decode(line)
- else:
- raise Exception(line)
+
+ output = subprocess.check_output(cmd, cwd=cwd, stderr=subprocess.STDOUT)
+ # The relevant information is in the last line of the output.
+ # Don't check if finding last line fails, would throw exception anyway.
+ last_line = output.decode('utf-8').splitlines()[-1]
+ if re.search(r'clang(.*): error:', last_line):
+ raise Exception(last_line)
+ return decode(last_line)
def get_active_checkers(clang, plugins):
- """ To get the default plugins we execute Clang to print how this
- compilation would be called.
+ """ Get the active checker list.
- For input file we specify stdin and pass only language information. """
+ :param clang: the compiler we are using
+ :param plugins: list of plugins which was requested by the user
+ :return: list of checker names which are active
- def checkers(language):
+ To get the default checkers we execute Clang to print how this
+ compilation would be called. And take out the enabled checker from the
+ arguments. For input file we specify stdin and pass only language
+ information. """
+
+ def get_active_checkers_for(language):
""" Returns a list of active checkers for the given language. """
- load = [elem
- for plugin in plugins
- for elem in ['-Xclang', '-load', '-Xclang', plugin]]
- cmd = [clang, '--analyze'] + load + ['-x', language, '-']
- pattern = re.compile(r'^-analyzer-checker=(.*)$')
- return [pattern.match(arg).group(1)
- for arg in get_arguments(cmd, '.') if pattern.match(arg)]
+ load_args = [arg
+ for plugin in plugins
+ for arg in ['-Xclang', '-load', '-Xclang', plugin]]
+ cmd = [clang, '--analyze'] + load_args + ['-x', language, '-']
+ return [ACTIVE_CHECKER_PATTERN.match(arg).group(1)
+ for arg in get_arguments(cmd, '.')
+ if ACTIVE_CHECKER_PATTERN.match(arg)]
result = set()
for language in ['c', 'c++', 'objective-c', 'objective-c++']:
- result.update(checkers(language))
- return result
+ result.update(get_active_checkers_for(language))
+ return frozenset(result)
-def get_checkers(clang, plugins):
- """ Get all the available checkers from default and from the plugins.
+def is_active(checkers):
+ """ Returns a method, which classifies the checker active or not,
+ based on the received checker name list. """
- clang -- the compiler we are using
- plugins -- list of plugins which was requested by the user
+ def predicate(checker):
+ """ Returns True if the given checker is active. """
- This method returns a dictionary of all available checkers and status.
+ return any(pattern.match(checker) for pattern in predicate.patterns)
- {<plugin name>: (<plugin description>, <is active by default>)} """
+ predicate.patterns = [re.compile(r'^' + a + r'(\.|$)') for a in checkers]
+ return predicate
- plugins = plugins if plugins else []
- def parse_checkers(stream):
- """ Parse clang -analyzer-checker-help output.
+def parse_checkers(stream):
+ """ Parse clang -analyzer-checker-help output.
- Below the line 'CHECKERS:' are there the name description pairs.
- Many of them are in one line, but some long named plugins has the
- name and the description in separate lines.
+ Below the line 'CHECKERS:' are there the name description pairs.
+ Many of them are in one line, but some long named checker has the
+ name and the description in separate lines.
- The plugin name is always prefixed with two space character. The
- name contains no whitespaces. Then followed by newline (if it's
- too long) or other space characters comes the description of the
- plugin. The description ends with a newline character. """
+ The checker name is always prefixed with two space character. The
+ name contains no whitespaces. Then followed by newline (if it's
+ too long) or other space characters comes the description of the
+ checker. The description ends with a newline character.
- # find checkers header
- for line in stream:
- if re.match(r'^CHECKERS:', line):
- break
- # find entries
- state = None
- for line in stream:
- if state and not re.match(r'^\s\s\S', line):
- yield (state, line.strip())
- state = None
- elif re.match(r'^\s\s\S+$', line.rstrip()):
- state = line.strip()
- else:
- pattern = re.compile(r'^\s\s(?P<key>\S*)\s*(?P<value>.*)')
- match = pattern.match(line.rstrip())
- if match:
- current = match.groupdict()
- yield (current['key'], current['value'])
+ :param stream: list of lines to parse
+ :return: generator of tuples
- def is_active(actives, entry):
- """ Returns true if plugin name is matching the active plugin names.
+ (<checker name>, <checker description>) """
- actives -- set of active plugin names (or prefixes).
- entry -- the current plugin name to judge.
+ lines = iter(stream)
+ # find checkers header
+ for line in lines:
+ if re.match(r'^CHECKERS:', line):
+ break
+ # find entries
+ state = None
+ for line in lines:
+ if state and not re.match(r'^\s\s\S', line):
+ yield (state, line.strip())
+ state = None
+ elif re.match(r'^\s\s\S+$', line.rstrip()):
+ state = line.strip()
+ else:
+ pattern = re.compile(r'^\s\s(?P<key>\S*)\s*(?P<value>.*)')
+ match = pattern.match(line.rstrip())
+ if match:
+ current = match.groupdict()
+ yield (current['key'], current['value'])
- The active plugin names are specific plugin names or prefix of some
- names. One example for prefix, when it say 'unix' and it shall match
- on 'unix.API', 'unix.Malloc' and 'unix.MallocSizeof'. """
- return any(re.match(r'^' + a + r'(\.|$)', entry) for a in actives)
+def get_checkers(clang, plugins):
+ """ Get all the available checkers from default and from the plugins.
+
+ :param clang: the compiler we are using
+ :param plugins: list of plugins which was requested by the user
+ :return: a dictionary of all available checkers and its status
- actives = get_active_checkers(clang, plugins)
+ {<checker name>: (<checker description>, <is active by default>)} """
load = [elem for plugin in plugins for elem in ['-load', plugin]]
cmd = [clang, '-cc1'] + load + ['-analyzer-checker-help']
logging.debug('exec command: %s', ' '.join(cmd))
- child = subprocess.Popen(cmd,
- universal_newlines=True,
- stdout=subprocess.PIPE,
- stderr=subprocess.STDOUT)
+ output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
+ lines = output.decode('utf-8').splitlines()
+
+ is_active_checker = is_active(get_active_checkers(clang, plugins))
+
checkers = {
- k: (v, is_active(actives, k))
- for k, v in parse_checkers(child.stdout)
+ name: (description, is_active_checker(name))
+ for name, description in parse_checkers(lines)
}
- child.stdout.close()
- child.wait()
- if child.returncode == 0 and len(checkers):
- return checkers
- else:
+ if not checkers:
raise Exception('Could not query Clang for available checkers.')
+
+ return checkers
diff --git a/tools/scan-build-py/libscanbuild/report.py b/tools/scan-build-py/libscanbuild/report.py
index 5c33319e206d..766ddef71990 100644
--- a/tools/scan-build-py/libscanbuild/report.py
+++ b/tools/scan-build-py/libscanbuild/report.py
@@ -21,6 +21,7 @@ import glob
import json
import logging
import contextlib
+import datetime
from libscanbuild import duplicate_check
from libscanbuild.clang import get_version
@@ -34,7 +35,8 @@ def report_directory(hint, keep):
hint -- could specify the parent directory of the output directory.
keep -- a boolean value to keep or delete the empty report directory. """
- stamp = time.strftime('scan-build-%Y-%m-%d-%H%M%S-', time.localtime())
+ stamp_format = 'scan-build-%Y-%m-%d-%H-%M-%S-%f-'
+ stamp = datetime.datetime.now().strftime(stamp_format)
parentdir = os.path.abspath(hint)
if not os.path.exists(parentdir):
diff --git a/tools/scan-build-py/libscanbuild/runner.py b/tools/scan-build-py/libscanbuild/runner.py
index 628ad90d627a..72d02c85fed1 100644
--- a/tools/scan-build-py/libscanbuild/runner.py
+++ b/tools/scan-build-py/libscanbuild/runner.py
@@ -205,19 +205,8 @@ def filter_debug_flags(opts, continuation=run_analyzer):
return continuation(opts)
-@require(['file', 'directory'])
-def set_file_path_relative(opts, continuation=filter_debug_flags):
- """ Set source file path to relative to the working directory.
-
- The only purpose of this function is to pass the SATestBuild.py tests. """
-
- opts.update({'file': os.path.relpath(opts['file'], opts['directory'])})
-
- return continuation(opts)
-
-
@require(['language', 'compiler', 'file', 'flags'])
-def language_check(opts, continuation=set_file_path_relative):
+def language_check(opts, continuation=filter_debug_flags):
""" Find out the language from command line parameters or file name
extension. The decision also influenced by the compiler invocation. """
diff --git a/tools/scan-build-py/tests/unit/test_clang.py b/tools/scan-build-py/tests/unit/test_clang.py
index 04414a85b828..eef8c26bbd19 100644
--- a/tools/scan-build-py/tests/unit/test_clang.py
+++ b/tools/scan-build-py/tests/unit/test_clang.py
@@ -8,9 +8,19 @@ import libear
import libscanbuild.clang as sut
import unittest
import os.path
+import sys
-class GetClangArgumentsTest(unittest.TestCase):
+class ClangGetVersion(unittest.TestCase):
+ def test_get_version_is_not_empty(self):
+ self.assertTrue(sut.get_version('clang'))
+
+ def test_get_version_throws(self):
+ with self.assertRaises(OSError):
+ sut.get_version('notexists')
+
+
+class ClangGetArgumentsTest(unittest.TestCase):
def test_get_clang_arguments(self):
with libear.TemporaryDirectory() as tmpdir:
filename = os.path.join(tmpdir, 'test.c')
@@ -25,18 +35,60 @@ class GetClangArgumentsTest(unittest.TestCase):
self.assertTrue('var="this is it"' in result)
def test_get_clang_arguments_fails(self):
- self.assertRaises(
- Exception, sut.get_arguments,
- ['clang', '-###', '-fsyntax-only', '-x', 'c', 'notexist.c'], '.')
+ with self.assertRaises(Exception):
+ sut.get_arguments(['clang', '-x', 'c', 'notexist.c'], '.')
+
+ def test_get_clang_arguments_fails_badly(self):
+ with self.assertRaises(OSError):
+ sut.get_arguments(['notexist'], '.')
-class GetCheckersTest(unittest.TestCase):
+class ClangGetCheckersTest(unittest.TestCase):
def test_get_checkers(self):
# this test is only to see is not crashing
result = sut.get_checkers('clang', [])
self.assertTrue(len(result))
+ # do check result types
+ string_type = unicode if sys.version_info < (3,) else str
+ for key, value in result.items():
+ self.assertEqual(string_type, type(key))
+ self.assertEqual(string_type, type(value[0]))
+ self.assertEqual(bool, type(value[1]))
def test_get_active_checkers(self):
# this test is only to see is not crashing
result = sut.get_active_checkers('clang', [])
self.assertTrue(len(result))
+ # do check result types
+ for value in result:
+ self.assertEqual(str, type(value))
+
+ def test_is_active(self):
+ test = sut.is_active(['a', 'b.b', 'c.c.c'])
+
+ self.assertTrue(test('a'))
+ self.assertTrue(test('a.b'))
+ self.assertTrue(test('b.b'))
+ self.assertTrue(test('b.b.c'))
+ self.assertTrue(test('c.c.c.p'))
+
+ self.assertFalse(test('ab'))
+ self.assertFalse(test('ba'))
+ self.assertFalse(test('bb'))
+ self.assertFalse(test('c.c'))
+ self.assertFalse(test('b'))
+ self.assertFalse(test('d'))
+
+ def test_parse_checkers(self):
+ lines = [
+ 'OVERVIEW: Clang Static Analyzer Checkers List',
+ '',
+ 'CHECKERS:',
+ ' checker.one Checker One description',
+ ' checker.two',
+ ' Checker Two description']
+ result = dict(sut.parse_checkers(lines))
+ self.assertTrue('checker.one' in result)
+ self.assertEqual('Checker One description', result.get('checker.one'))
+ self.assertTrue('checker.two' in result)
+ self.assertEqual('Checker Two description', result.get('checker.two'))
diff --git a/tools/scan-build-py/tests/unit/test_report.py b/tools/scan-build-py/tests/unit/test_report.py
index 3f249ce2aa0c..c82b5593e0dc 100644
--- a/tools/scan-build-py/tests/unit/test_report.py
+++ b/tools/scan-build-py/tests/unit/test_report.py
@@ -146,3 +146,16 @@ class GetPrefixFromCompilationDatabaseTest(unittest.TestCase):
def test_empty(self):
self.assertEqual(
sut.commonprefix([]), '')
+
+class ReportDirectoryTest(unittest.TestCase):
+
+ # Test that successive report directory names ascend in lexicographic
+ # order. This is required so that report directories from two runs of
+ # scan-build can be easily matched up to compare results.
+ def test_directory_name_comparison(self):
+ with libear.TemporaryDirectory() as tmpdir, \
+ sut.report_directory(tmpdir, False) as report_dir1, \
+ sut.report_directory(tmpdir, False) as report_dir2, \
+ sut.report_directory(tmpdir, False) as report_dir3:
+ self.assertLess(report_dir1, report_dir2)
+ self.assertLess(report_dir2, report_dir3)
diff --git a/tools/scan-build-py/tests/unit/test_runner.py b/tools/scan-build-py/tests/unit/test_runner.py
index b4730a1c5191..2d0906223329 100644
--- a/tools/scan-build-py/tests/unit/test_runner.py
+++ b/tools/scan-build-py/tests/unit/test_runner.py
@@ -219,20 +219,6 @@ class AnalyzerTest(unittest.TestCase):
self.assertEqual(['-DNDEBUG', '-UNDEBUG'], test(['-DNDEBUG']))
self.assertEqual(['-DSomething', '-UNDEBUG'], test(['-DSomething']))
- def test_set_file_relative_path(self):
- def test(expected, input):
- spy = Spy()
- self.assertEqual(spy.success,
- sut.set_file_path_relative(input, spy.call))
- self.assertEqual(expected, spy.arg['file'])
-
- test('source.c',
- {'file': '/home/me/source.c', 'directory': '/home/me'})
- test('me/source.c',
- {'file': '/home/me/source.c', 'directory': '/home'})
- test('../home/me/source.c',
- {'file': '/home/me/source.c', 'directory': '/tmp'})
-
def test_set_language_fall_through(self):
def language(expected, input):
spy = Spy()
diff --git a/tools/scan-build/bin/scan-build b/tools/scan-build/bin/scan-build
index 3182a29767b9..cbf3bf3d6f0b 100755
--- a/tools/scan-build/bin/scan-build
+++ b/tools/scan-build/bin/scan-build
@@ -53,6 +53,7 @@ my %Options = (
IgnoreErrors => 0, # Ignore build errors.
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
KeepEmpty => 0, # Don't remove output directory even with 0 results.
EnableCheckers => {},
DisableCheckers => {},
@@ -453,6 +454,10 @@ sub ScanFile {
push @$Index,[ $FName, $BugCategory, $BugType, $BugFile, $BugFunction, $BugLine,
$BugPathLength ];
+
+ if ($Options{ShowDescription}) {
+ push @{ $Index->[-1] }, $BugDescription
+ }
}
##----------------------------------------------------------------------------##
@@ -746,6 +751,15 @@ print OUT <<ENDTEXT;
<td>Function/Method</td>
<td class="Q">Line</td>
<td class="Q">Path Length</td>
+ENDTEXT
+
+if ($Options{ShowDescription}) {
+print OUT <<ENDTEXT;
+ <td class="Q">Description</td>
+ENDTEXT
+}
+
+print OUT <<ENDTEXT;
<td class="sorttable_nosort"></td>
<!-- REPORTBUGCOL -->
</tr></thead>
@@ -771,10 +785,10 @@ ENDTEXT
print OUT "<tr class=\"bt_$x\">";
print OUT "<td class=\"DESC\">";
- print OUT $row->[1];
+ print OUT $row->[1]; # $BugCategory
print OUT "</td>";
print OUT "<td class=\"DESC\">";
- print OUT $row->[2];
+ print OUT $row->[2]; # $BugType
print OUT "</td>";
# Update the file prefix.
@@ -802,11 +816,11 @@ ENDTEXT
print OUT "</td>";
print OUT "<td class=\"DESC\">";
- print OUT $row->[4];
+ print OUT $row->[4]; # Function
print OUT "</td>";
# Print out the quantities.
- for my $j ( 5 .. 6 ) {
+ for my $j ( 5 .. 6 ) { # Line & Path length
print OUT "<td class=\"Q\">$row->[$j]</td>";
}
@@ -1150,6 +1164,10 @@ OPTIONS:
Specify the title used on generated HTML pages. If not specified, a default
title will be used.
+ --show-description
+
+ Display the description of defects in the list
+
-plist
By default the output of scan-build is a set of HTML files. This option
@@ -1586,6 +1604,12 @@ sub ProcessArgs {
next;
}
+ if ($arg eq "--show-description") {
+ shift @$Args;
+ $Options{ShowDescription} = 1;
+ next;
+ }
+
if ($arg eq "-store") {
shift @$Args;
$Options{StoreModel} = shift @$Args;
diff --git a/unittests/AST/ASTImporterTest.cpp b/unittests/AST/ASTImporterTest.cpp
index 3cc38fb55b2e..57b41f12b0ba 100644
--- a/unittests/AST/ASTImporterTest.cpp
+++ b/unittests/AST/ASTImporterTest.cpp
@@ -71,8 +71,7 @@ testImport(const std::string &FromCode, Language FromLang,
ToCtx.getSourceManager().getFileManager().getVirtualFileSystem().get());
vfs::InMemoryFileSystem *MFS = static_cast<vfs::InMemoryFileSystem *>(
OFS->overlays_begin()->get());
- MFS->addFile(InputFileName, 0,
- llvm::MemoryBuffer::getMemBuffer(FromCode.c_str()));
+ MFS->addFile(InputFileName, 0, llvm::MemoryBuffer::getMemBuffer(FromCode));
ASTImporter Importer(ToCtx, ToAST->getFileManager(),
FromCtx, FromAST->getFileManager(), false);
@@ -456,5 +455,39 @@ TEST(ImportExpr, ImportInitListExpr) {
}
+const internal::VariadicDynCastAllOfMatcher<Expr, VAArgExpr> vaArgExpr;
+
+TEST(ImportExpr, ImportVAArgExpr) {
+ MatchVerifier<Decl> Verifier;
+ EXPECT_TRUE(
+ 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()))))))));
+}
+
+
+TEST(ImportType, ImportAtomicType) {
+ MatchVerifier<Decl> Verifier;
+ EXPECT_TRUE(testImport("void declToImport() { typedef _Atomic(int) a_int; }",
+ Lang_CXX11, "", Lang_CXX11, Verifier,
+ functionDecl(
+ hasBody(
+ compoundStmt(
+ has(
+ declStmt(
+ has(
+ typedefDecl(
+ has(atomicType()))))))))));
+}
+
+
} // end namespace ast_matchers
} // end namespace clang
diff --git a/unittests/AST/ASTTypeTraitsTest.cpp b/unittests/AST/ASTTypeTraitsTest.cpp
index 436cd7751411..722c468f30f2 100644
--- a/unittests/AST/ASTTypeTraitsTest.cpp
+++ b/unittests/AST/ASTTypeTraitsTest.cpp
@@ -163,7 +163,7 @@ TEST(DynTypedNode, StmtDump) {
TEST(DynTypedNode, DeclPrint) {
PrintVerifier Verifier;
- Verifier.expectString("void f() {\n}\n\n");
+ Verifier.expectString("void f() {\n}\n");
EXPECT_TRUE(Verifier.match("void f() {}", functionDecl()));
}
diff --git a/unittests/AST/ASTVectorTest.cpp b/unittests/AST/ASTVectorTest.cpp
index 55c06d0071fe..359d2f423259 100644
--- a/unittests/AST/ASTVectorTest.cpp
+++ b/unittests/AST/ASTVectorTest.cpp
@@ -11,7 +11,6 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/Support/Compiler.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTVector.h"
#include "clang/Basic/Builtins.h"
diff --git a/unittests/AST/CommentParser.cpp b/unittests/AST/CommentParser.cpp
index f6ef9b9b7cea..a185f73971df 100644
--- a/unittests/AST/CommentParser.cpp
+++ b/unittests/AST/CommentParser.cpp
@@ -20,7 +20,6 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Allocator.h"
#include "gtest/gtest.h"
-#include <vector>
using namespace llvm;
using namespace clang;
diff --git a/unittests/AST/DeclPrinterTest.cpp b/unittests/AST/DeclPrinterTest.cpp
index d06fbfea6f5e..e5a09a31f69f 100644
--- a/unittests/AST/DeclPrinterTest.cpp
+++ b/unittests/AST/DeclPrinterTest.cpp
@@ -45,7 +45,7 @@ public:
PrintMatch() : NumFoundDecls(0) {}
void run(const MatchFinder::MatchResult &Result) override {
- const Decl *D = Result.Nodes.getDeclAs<Decl>("id");
+ const Decl *D = Result.Nodes.getNodeAs<Decl>("id");
if (!D || D->isImplicit())
return;
NumFoundDecls++;
@@ -254,24 +254,21 @@ TEST(DeclPrinter, TestCXXRecordDecl1) {
ASSERT_TRUE(PrintedDeclCXX98Matches(
"class A { int a; };",
"A",
- "class A {\n}"));
- // Should be: with semicolon, with { ... }
+ "class A {}"));
}
TEST(DeclPrinter, TestCXXRecordDecl2) {
ASSERT_TRUE(PrintedDeclCXX98Matches(
"struct A { int a; };",
"A",
- "struct A {\n}"));
- // Should be: with semicolon, with { ... }
+ "struct A {}"));
}
TEST(DeclPrinter, TestCXXRecordDecl3) {
ASSERT_TRUE(PrintedDeclCXX98Matches(
"union A { int a; };",
"A",
- "union A {\n}"));
- // Should be: with semicolon, with { ... }
+ "union A {}"));
}
TEST(DeclPrinter, TestCXXRecordDecl4) {
@@ -279,8 +276,7 @@ TEST(DeclPrinter, TestCXXRecordDecl4) {
"class Z { int a; };"
"class A : Z { int b; };",
"A",
- "class A : Z {\n}"));
- // Should be: with semicolon, with { ... }
+ "class A : Z {}"));
}
TEST(DeclPrinter, TestCXXRecordDecl5) {
@@ -288,8 +284,7 @@ TEST(DeclPrinter, TestCXXRecordDecl5) {
"struct Z { int a; };"
"struct A : Z { int b; };",
"A",
- "struct A : Z {\n}"));
- // Should be: with semicolon, with { ... }
+ "struct A : Z {}"));
}
TEST(DeclPrinter, TestCXXRecordDecl6) {
@@ -297,8 +292,7 @@ TEST(DeclPrinter, TestCXXRecordDecl6) {
"class Z { int a; };"
"class A : public Z { int b; };",
"A",
- "class A : public Z {\n}"));
- // Should be: with semicolon, with { ... }
+ "class A : public Z {}"));
}
TEST(DeclPrinter, TestCXXRecordDecl7) {
@@ -306,8 +300,7 @@ TEST(DeclPrinter, TestCXXRecordDecl7) {
"class Z { int a; };"
"class A : protected Z { int b; };",
"A",
- "class A : protected Z {\n}"));
- // Should be: with semicolon, with { ... }
+ "class A : protected Z {}"));
}
TEST(DeclPrinter, TestCXXRecordDecl8) {
@@ -315,8 +308,7 @@ TEST(DeclPrinter, TestCXXRecordDecl8) {
"class Z { int a; };"
"class A : private Z { int b; };",
"A",
- "class A : private Z {\n}"));
- // Should be: with semicolon, with { ... }
+ "class A : private Z {}"));
}
TEST(DeclPrinter, TestCXXRecordDecl9) {
@@ -324,8 +316,7 @@ TEST(DeclPrinter, TestCXXRecordDecl9) {
"class Z { int a; };"
"class A : virtual Z { int b; };",
"A",
- "class A : virtual Z {\n}"));
- // Should be: with semicolon, with { ... }
+ "class A : virtual Z {}"));
}
TEST(DeclPrinter, TestCXXRecordDecl10) {
@@ -333,8 +324,7 @@ TEST(DeclPrinter, TestCXXRecordDecl10) {
"class Z { int a; };"
"class A : virtual public Z { int b; };",
"A",
- "class A : virtual public Z {\n}"));
- // Should be: with semicolon, with { ... }
+ "class A : virtual public Z {}"));
}
TEST(DeclPrinter, TestCXXRecordDecl11) {
@@ -343,8 +333,7 @@ TEST(DeclPrinter, TestCXXRecordDecl11) {
"class Y : virtual public Z { int b; };"
"class A : virtual public Z, private Y { int c; };",
"A",
- "class A : virtual public Z, private Y {\n}"));
- // Should be: with semicolon, with { ... }
+ "class A : virtual public Z, private Y {}"));
}
TEST(DeclPrinter, TestFunctionDecl1) {
@@ -352,7 +341,6 @@ TEST(DeclPrinter, TestFunctionDecl1) {
"void A();",
"A",
"void A()"));
- // Should be: with semicolon
}
TEST(DeclPrinter, TestFunctionDecl2) {
@@ -360,7 +348,6 @@ TEST(DeclPrinter, TestFunctionDecl2) {
"void A() {}",
"A",
"void A()"));
- // Should be: with semicolon
}
TEST(DeclPrinter, TestFunctionDecl3) {
@@ -369,7 +356,6 @@ TEST(DeclPrinter, TestFunctionDecl3) {
"void A() { Z(); }",
"A",
"void A()"));
- // Should be: with semicolon
}
TEST(DeclPrinter, TestFunctionDecl4) {
@@ -377,7 +363,6 @@ TEST(DeclPrinter, TestFunctionDecl4) {
"extern void A();",
"A",
"extern void A()"));
- // Should be: with semicolon
}
TEST(DeclPrinter, TestFunctionDecl5) {
@@ -385,7 +370,6 @@ TEST(DeclPrinter, TestFunctionDecl5) {
"static void A();",
"A",
"static void A()"));
- // Should be: with semicolon
}
TEST(DeclPrinter, TestFunctionDecl6) {
@@ -393,7 +377,6 @@ TEST(DeclPrinter, TestFunctionDecl6) {
"inline void A();",
"A",
"inline void A()"));
- // Should be: with semicolon
}
TEST(DeclPrinter, TestFunctionDecl7) {
@@ -401,7 +384,6 @@ TEST(DeclPrinter, TestFunctionDecl7) {
"constexpr int A(int a);",
"A",
"constexpr int A(int a)"));
- // Should be: with semicolon
}
TEST(DeclPrinter, TestFunctionDecl8) {
@@ -409,7 +391,6 @@ TEST(DeclPrinter, TestFunctionDecl8) {
"void A(int a);",
"A",
"void A(int a)"));
- // Should be: with semicolon
}
TEST(DeclPrinter, TestFunctionDecl9) {
@@ -417,7 +398,6 @@ TEST(DeclPrinter, TestFunctionDecl9) {
"void A(...);",
"A",
"void A(...)"));
- // Should be: with semicolon
}
TEST(DeclPrinter, TestFunctionDecl10) {
@@ -425,7 +405,6 @@ TEST(DeclPrinter, TestFunctionDecl10) {
"void A(int a, ...);",
"A",
"void A(int a, ...)"));
- // Should be: with semicolon
}
TEST(DeclPrinter, TestFunctionDecl11) {
@@ -435,7 +414,6 @@ TEST(DeclPrinter, TestFunctionDecl11) {
"void A(int a, pInt b, ssize_t c);",
"A",
"void A(int a, pInt b, ssize_t c)"));
- // Should be: with semicolon
}
TEST(DeclPrinter, TestFunctionDecl12) {
@@ -443,7 +421,6 @@ TEST(DeclPrinter, TestFunctionDecl12) {
"void A(int a, int b = 0);",
"A",
"void A(int a, int b = 0)"));
- // Should be: with semicolon
}
TEST(DeclPrinter, TestFunctionDecl13) {
@@ -451,7 +428,7 @@ TEST(DeclPrinter, TestFunctionDecl13) {
"void (*A(int a))(int b);",
"A",
"void (*A(int a))(int)"));
- // Should be: with semicolon, with parameter name (?)
+ // Should be: with parameter name (?)
}
TEST(DeclPrinter, TestFunctionDecl14) {
@@ -461,8 +438,7 @@ TEST(DeclPrinter, TestFunctionDecl14) {
"template<>"
"void A(int N) { }",
functionDecl(hasName("A"), isExplicitTemplateSpecialization()).bind("id"),
- "void A(int N)"));
- // WRONG; Should be: "template <> void A(int N);"));
+ "template<> void A<int>(int N)"));
}
@@ -555,7 +531,6 @@ TEST(DeclPrinter, TestCXXConstructorDecl10) {
"};",
cxxConstructorDecl(ofClass(hasName("A"))).bind("id"),
"A<T...>(const A<T...> &a)"));
- // WRONG; Should be: "A(const A<T...> &a);"
}
TEST(DeclPrinter, TestCXXConstructorDecl11) {
@@ -565,8 +540,7 @@ TEST(DeclPrinter, TestCXXConstructorDecl11) {
" A(T&&... ts) : T(ts)... {}"
"};",
cxxConstructorDecl(ofClass(hasName("A"))).bind("id"),
- "A<T...>(T &&...ts) : T(ts)..."));
- // WRONG; Should be: "A(T &&...ts) : T(ts)... {}"
+ "A<T...>(T &&...ts) : T(ts)... {}"));
}
TEST(DeclPrinter, TestCXXDestructorDecl1) {
@@ -623,7 +597,6 @@ TEST(DeclPrinter, TestCXXMethodDecl_AllocationFunction1) {
"};",
cxxMethodDecl(ofClass(hasName("Z"))).bind("id"),
"void *operator new(std::size_t)"));
- // Should be: with semicolon
}
TEST(DeclPrinter, TestCXXMethodDecl_AllocationFunction2) {
@@ -634,7 +607,6 @@ TEST(DeclPrinter, TestCXXMethodDecl_AllocationFunction2) {
"};",
cxxMethodDecl(ofClass(hasName("Z"))).bind("id"),
"void *operator new[](std::size_t)"));
- // Should be: with semicolon
}
TEST(DeclPrinter, TestCXXMethodDecl_AllocationFunction3) {
@@ -644,7 +616,7 @@ TEST(DeclPrinter, TestCXXMethodDecl_AllocationFunction3) {
"};",
cxxMethodDecl(ofClass(hasName("Z"))).bind("id"),
"void operator delete(void *) noexcept"));
- // Should be: with semicolon, without noexcept?
+ // Should be: without noexcept?
}
TEST(DeclPrinter, TestCXXMethodDecl_AllocationFunction4) {
@@ -654,7 +626,6 @@ TEST(DeclPrinter, TestCXXMethodDecl_AllocationFunction4) {
"};",
cxxMethodDecl(ofClass(hasName("Z"))).bind("id"),
"void operator delete(void *)"));
- // Should be: with semicolon
}
TEST(DeclPrinter, TestCXXMethodDecl_AllocationFunction5) {
@@ -664,7 +635,7 @@ TEST(DeclPrinter, TestCXXMethodDecl_AllocationFunction5) {
"};",
cxxMethodDecl(ofClass(hasName("Z"))).bind("id"),
"void operator delete[](void *) noexcept"));
- // Should be: with semicolon, without noexcept?
+ // Should be: without noexcept?
}
TEST(DeclPrinter, TestCXXMethodDecl_Operator1) {
@@ -686,7 +657,6 @@ TEST(DeclPrinter, TestCXXMethodDecl_Operator1) {
Expected.append("void operator");
Expected.append(OperatorNames[i]);
Expected.append("(Z z)");
- // Should be: with semicolon
ASSERT_TRUE(PrintedDeclCXX98Matches(
Code,
@@ -710,7 +680,6 @@ TEST(DeclPrinter, TestCXXMethodDecl_Operator2) {
Expected.append("void operator");
Expected.append(OperatorNames[i]);
Expected.append("()");
- // Should be: with semicolon
ASSERT_TRUE(PrintedDeclCXX98Matches(
Code,
@@ -726,7 +695,6 @@ TEST(DeclPrinter, TestCXXMethodDecl1) {
"};",
"A",
"void A(int a)"));
- // Should be: with semicolon
}
TEST(DeclPrinter, TestCXXMethodDecl2) {
@@ -736,7 +704,6 @@ TEST(DeclPrinter, TestCXXMethodDecl2) {
"};",
"A",
"virtual void A(int a)"));
- // Should be: with semicolon
}
TEST(DeclPrinter, TestCXXMethodDecl3) {
@@ -749,7 +716,6 @@ TEST(DeclPrinter, TestCXXMethodDecl3) {
"};",
"ZZ::A",
"void A(int a)"));
- // Should be: with semicolon
// TODO: should we print "virtual"?
}
@@ -760,7 +726,6 @@ TEST(DeclPrinter, TestCXXMethodDecl4) {
"};",
"A",
"inline void A(int a)"));
- // Should be: with semicolon
}
TEST(DeclPrinter, TestCXXMethodDecl5) {
@@ -770,7 +735,6 @@ TEST(DeclPrinter, TestCXXMethodDecl5) {
"};",
"A",
"virtual void A(int a) = 0"));
- // Should be: with semicolon
}
TEST(DeclPrinter, TestCXXMethodDecl_CVQualifier1) {
@@ -780,7 +744,6 @@ TEST(DeclPrinter, TestCXXMethodDecl_CVQualifier1) {
"};",
"A",
"void A(int a) const"));
- // Should be: with semicolon
}
TEST(DeclPrinter, TestCXXMethodDecl_CVQualifier2) {
@@ -790,7 +753,6 @@ TEST(DeclPrinter, TestCXXMethodDecl_CVQualifier2) {
"};",
"A",
"void A(int a) volatile"));
- // Should be: with semicolon
}
TEST(DeclPrinter, TestCXXMethodDecl_CVQualifier3) {
@@ -800,7 +762,6 @@ TEST(DeclPrinter, TestCXXMethodDecl_CVQualifier3) {
"};",
"A",
"void A(int a) const volatile"));
- // Should be: with semicolon
}
TEST(DeclPrinter, TestCXXMethodDecl_RefQualifier1) {
@@ -810,7 +771,6 @@ TEST(DeclPrinter, TestCXXMethodDecl_RefQualifier1) {
"};",
"A",
"void A(int a) &"));
- // Should be: with semicolon
}
TEST(DeclPrinter, TestCXXMethodDecl_RefQualifier2) {
@@ -820,7 +780,6 @@ TEST(DeclPrinter, TestCXXMethodDecl_RefQualifier2) {
"};",
"A",
"void A(int a) &&"));
- // Should be: with semicolon
}
TEST(DeclPrinter, TestFunctionDecl_ExceptionSpecification1) {
@@ -830,7 +789,6 @@ TEST(DeclPrinter, TestFunctionDecl_ExceptionSpecification1) {
"};",
"A",
"void A(int a) throw()"));
- // Should be: with semicolon
}
TEST(DeclPrinter, TestFunctionDecl_ExceptionSpecification2) {
@@ -840,7 +798,6 @@ TEST(DeclPrinter, TestFunctionDecl_ExceptionSpecification2) {
"};",
"A",
"void A(int a) throw(int)"));
- // Should be: with semicolon
}
TEST(DeclPrinter, TestFunctionDecl_ExceptionSpecification3) {
@@ -851,7 +808,6 @@ TEST(DeclPrinter, TestFunctionDecl_ExceptionSpecification3) {
"};",
"A",
"void A(int a) throw(ZZ, int)"));
- // Should be: with semicolon
}
TEST(DeclPrinter, TestFunctionDecl_ExceptionSpecification4) {
@@ -861,7 +817,6 @@ TEST(DeclPrinter, TestFunctionDecl_ExceptionSpecification4) {
"};",
"A",
"void A(int a) noexcept"));
- // Should be: with semicolon
}
TEST(DeclPrinter, TestFunctionDecl_ExceptionSpecification5) {
@@ -942,8 +897,7 @@ TEST(DeclPrinter, TestClassTemplateDecl1) {
"template<typename T>"
"struct A { T a; };",
classTemplateDecl(hasName("A")).bind("id"),
- "template <typename T> struct A {\n}"));
- // Should be: with semicolon, with { ... }
+ "template <typename T> struct A {}"));
}
TEST(DeclPrinter, TestClassTemplateDecl2) {
@@ -951,8 +905,7 @@ TEST(DeclPrinter, TestClassTemplateDecl2) {
"template<typename T = int>"
"struct A { T a; };",
classTemplateDecl(hasName("A")).bind("id"),
- "template <typename T = int> struct A {\n}"));
- // Should be: with semicolon, with { ... }
+ "template <typename T = int> struct A {}"));
}
TEST(DeclPrinter, TestClassTemplateDecl3) {
@@ -960,8 +913,7 @@ TEST(DeclPrinter, TestClassTemplateDecl3) {
"template<class T>"
"struct A { T a; };",
classTemplateDecl(hasName("A")).bind("id"),
- "template <class T> struct A {\n}"));
- // Should be: with semicolon, with { ... }
+ "template <class T> struct A {}"));
}
TEST(DeclPrinter, TestClassTemplateDecl4) {
@@ -969,8 +921,7 @@ TEST(DeclPrinter, TestClassTemplateDecl4) {
"template<typename T, typename U>"
"struct A { T a; U b; };",
classTemplateDecl(hasName("A")).bind("id"),
- "template <typename T, typename U> struct A {\n}"));
- // Should be: with semicolon, with { ... }
+ "template <typename T, typename U> struct A {}"));
}
TEST(DeclPrinter, TestClassTemplateDecl5) {
@@ -978,8 +929,7 @@ TEST(DeclPrinter, TestClassTemplateDecl5) {
"template<int N>"
"struct A { int a[N]; };",
classTemplateDecl(hasName("A")).bind("id"),
- "template <int N> struct A {\n}"));
- // Should be: with semicolon, with { ... }
+ "template <int N> struct A {}"));
}
TEST(DeclPrinter, TestClassTemplateDecl6) {
@@ -987,8 +937,7 @@ TEST(DeclPrinter, TestClassTemplateDecl6) {
"template<int N = 42>"
"struct A { int a[N]; };",
classTemplateDecl(hasName("A")).bind("id"),
- "template <int N = 42> struct A {\n}"));
- // Should be: with semicolon, with { ... }
+ "template <int N = 42> struct A {}"));
}
TEST(DeclPrinter, TestClassTemplateDecl7) {
@@ -997,16 +946,14 @@ TEST(DeclPrinter, TestClassTemplateDecl7) {
"template<MyInt N>"
"struct A { int a[N]; };",
classTemplateDecl(hasName("A")).bind("id"),
- "template <MyInt N> struct A {\n}"));
- // Should be: with semicolon, with { ... }
+ "template <MyInt N> struct A {}"));
}
TEST(DeclPrinter, TestClassTemplateDecl8) {
ASSERT_TRUE(PrintedDeclCXX98Matches(
"template<template<typename U> class T> struct A { };",
classTemplateDecl(hasName("A")).bind("id"),
- "template <template <typename U> class T> struct A {\n}"));
- // Should be: with semicolon, with { ... }
+ "template <template <typename U> class T> struct A {}"));
}
TEST(DeclPrinter, TestClassTemplateDecl9) {
@@ -1014,8 +961,7 @@ TEST(DeclPrinter, TestClassTemplateDecl9) {
"template<typename T> struct Z { };"
"template<template<typename U> class T = Z> struct A { };",
classTemplateDecl(hasName("A")).bind("id"),
- "template <template <typename U> class T> struct A {\n}"));
- // Should be: with semicolon, with { ... }
+ "template <template <typename U> class T> struct A {}"));
}
TEST(DeclPrinter, TestClassTemplateDecl10) {
@@ -1023,8 +969,7 @@ TEST(DeclPrinter, TestClassTemplateDecl10) {
"template<typename... T>"
"struct A { int a; };",
classTemplateDecl(hasName("A")).bind("id"),
- "template <typename ...T> struct A {\n}"));
- // Should be: with semicolon, with { ... }
+ "template <typename ...T> struct A {}"));
}
TEST(DeclPrinter, TestClassTemplateDecl11) {
@@ -1032,8 +977,7 @@ TEST(DeclPrinter, TestClassTemplateDecl11) {
"template<typename... T>"
"struct A : public T... { int a; };",
classTemplateDecl(hasName("A")).bind("id"),
- "template <typename ...T> struct A : public T... {\n}"));
- // Should be: with semicolon, with { ... }
+ "template <typename ...T> struct A : public T... {}"));
}
TEST(DeclPrinter, TestClassTemplatePartialSpecializationDecl1) {
@@ -1043,8 +987,7 @@ TEST(DeclPrinter, TestClassTemplatePartialSpecializationDecl1) {
"template<typename T>"
"struct A<T, int> { T a; };",
classTemplateSpecializationDecl().bind("id"),
- "struct A {\n}"));
- // WRONG; Should be: "template<typename T> struct A<T, int> { ... }"
+ "template <typename T> struct A<T, int> {}"));
}
TEST(DeclPrinter, TestClassTemplatePartialSpecializationDecl2) {
@@ -1054,7 +997,7 @@ TEST(DeclPrinter, TestClassTemplatePartialSpecializationDecl2) {
"template<typename T>"
"struct A<T *> { T a; };",
classTemplateSpecializationDecl().bind("id"),
- "struct A {\n}"));
+ "template <typename T> struct A<type-parameter-0-0 *> {}"));
// WRONG; Should be: "template<typename T> struct A<T *> { ... }"
}
@@ -1065,8 +1008,7 @@ TEST(DeclPrinter, TestClassTemplateSpecializationDecl1) {
"template<>"
"struct A<int> { int a; };",
classTemplateSpecializationDecl().bind("id"),
- "struct A {\n}"));
- // WRONG; Should be: "template<> struct A<int> { ... }"
+ "template<> struct A<int> {}"));
}
TEST(DeclPrinter, TestFunctionTemplateDecl1) {
@@ -1075,7 +1017,6 @@ TEST(DeclPrinter, TestFunctionTemplateDecl1) {
"void A(T &t);",
functionTemplateDecl(hasName("A")).bind("id"),
"template <typename T> void A(T &t)"));
- // Should be: with semicolon
}
TEST(DeclPrinter, TestFunctionTemplateDecl2) {
@@ -1084,7 +1025,6 @@ TEST(DeclPrinter, TestFunctionTemplateDecl2) {
"void A(T &t) { }",
functionTemplateDecl(hasName("A")).bind("id"),
"template <typename T> void A(T &t)"));
- // Should be: with semicolon
}
TEST(DeclPrinter, TestFunctionTemplateDecl3) {
@@ -1093,7 +1033,6 @@ TEST(DeclPrinter, TestFunctionTemplateDecl3) {
"void A(T... a);",
functionTemplateDecl(hasName("A")).bind("id"),
"template <typename ...T> void A(T ...a)"));
- // Should be: with semicolon.
}
TEST(DeclPrinter, TestFunctionTemplateDecl4) {
@@ -1101,7 +1040,6 @@ TEST(DeclPrinter, TestFunctionTemplateDecl4) {
"struct Z { template<typename T> void A(T t); };",
functionTemplateDecl(hasName("A")).bind("id"),
"template <typename T> void A(T t)"));
- // Should be: with semicolon
}
TEST(DeclPrinter, TestFunctionTemplateDecl5) {
@@ -1109,7 +1047,6 @@ TEST(DeclPrinter, TestFunctionTemplateDecl5) {
"struct Z { template<typename T> void A(T t) {} };",
functionTemplateDecl(hasName("A")).bind("id"),
"template <typename T> void A(T t)"));
- // Should be: with semicolon
}
TEST(DeclPrinter, TestFunctionTemplateDecl6) {
@@ -1119,7 +1056,6 @@ TEST(DeclPrinter, TestFunctionTemplateDecl6) {
"};",
functionTemplateDecl(hasName("A")).bind("id"),
"template <typename U> void A(U t)"));
- // Should be: with semicolon
}
TEST(DeclPrinter, TestTemplateArgumentList1) {
diff --git a/unittests/AST/ExternalASTSourceTest.cpp b/unittests/AST/ExternalASTSourceTest.cpp
index 4f42dcf10336..4b3bb3e2b69b 100644
--- a/unittests/AST/ExternalASTSourceTest.cpp
+++ b/unittests/AST/ExternalASTSourceTest.cpp
@@ -17,6 +17,7 @@
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/FrontendActions.h"
+#include "clang/Lex/PreprocessorOptions.h"
#include "gtest/gtest.h"
using namespace clang;
diff --git a/unittests/AST/PostOrderASTVisitor.cpp b/unittests/AST/PostOrderASTVisitor.cpp
index 012f63a48ade..2921f3ead50e 100644
--- a/unittests/AST/PostOrderASTVisitor.cpp
+++ b/unittests/AST/PostOrderASTVisitor.cpp
@@ -34,6 +34,11 @@ namespace {
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;
@@ -76,7 +81,7 @@ TEST(RecursiveASTVisitor, PostOrderTraversal) {
auto ASTUnit = tooling::buildASTFromCode(
"class A {"
" class B {"
- " int foo() { while(4) { int i = 9; } return (1 + 3) + 2; }"
+ " int foo() { while(4) { int i = 9; int j = -5; } return (1 + 3) + 2; }"
" };"
"};"
);
@@ -86,9 +91,9 @@ TEST(RecursiveASTVisitor, PostOrderTraversal) {
RecordingVisitor Visitor(true);
Visitor.TraverseTranslationUnitDecl(TU);
- std::vector<std::string> expected = {
- "4", "9", "i", "1", "3", "+", "2", "+", "return", "A::B::foo", "A::B", "A"
- };
+ 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());
diff --git a/unittests/AST/SourceLocationTest.cpp b/unittests/AST/SourceLocationTest.cpp
index 9fae8d862aef..add85c366024 100644
--- a/unittests/AST/SourceLocationTest.cpp
+++ b/unittests/AST/SourceLocationTest.cpp
@@ -148,6 +148,96 @@ TEST(VarDecl, VMTypeFixedVarDeclRange) {
varDecl(), Lang_C89));
}
+TEST(TypeLoc, IntRange) {
+ RangeVerifier<TypeLoc> Verifier;
+ Verifier.expectRange(1, 1, 1, 1);
+ EXPECT_TRUE(Verifier.match("int a;", typeLoc()));
+}
+
+TEST(TypeLoc, LongRange) {
+ RangeVerifier<TypeLoc> Verifier;
+ Verifier.expectRange(1, 1, 1, 1);
+ EXPECT_TRUE(Verifier.match("long a;", typeLoc()));
+}
+
+TEST(TypeLoc, LongDoubleRange) {
+ RangeVerifier<TypeLoc> Verifier;
+ Verifier.expectRange(1, 1, 1, 6);
+ EXPECT_TRUE(Verifier.match("long double a;", typeLoc()));
+}
+
+TEST(TypeLoc, DoubleLongRange) {
+ RangeVerifier<TypeLoc> Verifier;
+ Verifier.expectRange(1, 1, 1, 8);
+ EXPECT_TRUE(Verifier.match("double long a;", typeLoc()));
+}
+
+TEST(TypeLoc, LongIntRange) {
+ RangeVerifier<TypeLoc> Verifier;
+ Verifier.expectRange(1, 1, 1, 6);
+ EXPECT_TRUE(Verifier.match("long int a;", typeLoc()));
+}
+
+TEST(TypeLoc, IntLongRange) {
+ RangeVerifier<TypeLoc> Verifier;
+ Verifier.expectRange(1, 1, 1, 5);
+ EXPECT_TRUE(Verifier.match("int long a;", typeLoc()));
+}
+
+TEST(TypeLoc, UnsignedIntRange) {
+ RangeVerifier<TypeLoc> Verifier;
+ Verifier.expectRange(1, 1, 1, 10);
+ EXPECT_TRUE(Verifier.match("unsigned int a;", typeLoc()));
+}
+
+TEST(TypeLoc, IntUnsignedRange) {
+ RangeVerifier<TypeLoc> Verifier;
+ Verifier.expectRange(1, 1, 1, 5);
+ EXPECT_TRUE(Verifier.match("int unsigned a;", typeLoc()));
+}
+
+TEST(TypeLoc, LongLongRange) {
+ RangeVerifier<TypeLoc> Verifier;
+ Verifier.expectRange(1, 1, 1, 6);
+ EXPECT_TRUE(Verifier.match("long long a;", typeLoc()));
+}
+
+TEST(TypeLoc, UnsignedLongLongRange) {
+ RangeVerifier<TypeLoc> Verifier;
+ Verifier.expectRange(1, 1, 1, 15);
+ EXPECT_TRUE(Verifier.match("unsigned long long a;", typeLoc()));
+}
+
+TEST(TypeLoc, LongUnsignedLongRange) {
+ RangeVerifier<TypeLoc> Verifier;
+ Verifier.expectRange(1, 1, 1, 15);
+ EXPECT_TRUE(Verifier.match("long unsigned long a;", typeLoc()));
+}
+
+TEST(TypeLoc, LongLongUnsignedRange) {
+ RangeVerifier<TypeLoc> Verifier;
+ Verifier.expectRange(1, 1, 1, 11);
+ EXPECT_TRUE(Verifier.match("long long unsigned a;", typeLoc()));
+}
+
+TEST(TypeLoc, ConstLongLongRange) {
+ RangeVerifier<TypeLoc> Verifier;
+ Verifier.expectRange(1, 7, 1, 12);
+ EXPECT_TRUE(Verifier.match("const long long a = 0;", typeLoc()));
+}
+
+TEST(TypeLoc, LongConstLongRange) {
+ RangeVerifier<TypeLoc> Verifier;
+ Verifier.expectRange(1, 1, 1, 12);
+ EXPECT_TRUE(Verifier.match("long const long a = 0;", typeLoc()));
+}
+
+TEST(TypeLoc, LongLongConstRange) {
+ RangeVerifier<TypeLoc> Verifier;
+ Verifier.expectRange(1, 1, 1, 6);
+ EXPECT_TRUE(Verifier.match("long long const a = 0;", typeLoc()));
+}
+
TEST(CXXConstructorDecl, NoRetFunTypeLocRange) {
RangeVerifier<CXXConstructorDecl> Verifier;
Verifier.expectRange(1, 11, 1, 13);
diff --git a/unittests/AST/StmtPrinterTest.cpp b/unittests/AST/StmtPrinterTest.cpp
index bc7fd54e4ad9..12b203236c99 100644
--- a/unittests/AST/StmtPrinterTest.cpp
+++ b/unittests/AST/StmtPrinterTest.cpp
@@ -45,7 +45,7 @@ public:
PrintMatch() : NumFoundStmts(0) {}
void run(const MatchFinder::MatchResult &Result) override {
- const Stmt *S = Result.Nodes.getStmtAs<Stmt>("id");
+ const Stmt *S = Result.Nodes.getNodeAs<Stmt>("id");
if (!S)
return;
NumFoundStmts++;
diff --git a/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp b/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
index 82c5139a78f5..6037127feb52 100644
--- a/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ b/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -669,7 +669,7 @@ TEST(Matcher, VarDecl_Storage) {
TEST(Matcher, VarDecl_StorageDuration) {
std::string T =
- "void f() { int x; static int y; } int a;";
+ "void f() { int x; static int y; } int a;static int b;extern int c;";
EXPECT_TRUE(matches(T, varDecl(hasName("x"), hasAutomaticStorageDuration())));
EXPECT_TRUE(
@@ -679,6 +679,8 @@ TEST(Matcher, VarDecl_StorageDuration) {
EXPECT_TRUE(matches(T, varDecl(hasName("y"), hasStaticStorageDuration())));
EXPECT_TRUE(matches(T, varDecl(hasName("a"), hasStaticStorageDuration())));
+ EXPECT_TRUE(matches(T, varDecl(hasName("b"), hasStaticStorageDuration())));
+ EXPECT_TRUE(matches(T, varDecl(hasName("c"), hasStaticStorageDuration())));
EXPECT_TRUE(notMatches(T, varDecl(hasName("x"), hasStaticStorageDuration())));
// FIXME: It is really hard to test with thread_local itself because not all
@@ -842,6 +844,21 @@ TEST(IsExternC, MatchesExternCFunctionDeclarations) {
EXPECT_TRUE(notMatches("void f() {}", functionDecl(isExternC())));
}
+TEST(IsExternC, MatchesExternCVariableDeclarations) {
+ EXPECT_TRUE(matches("extern \"C\" int i;", varDecl(isExternC())));
+ EXPECT_TRUE(matches("extern \"C\" { int i; }", varDecl(isExternC())));
+ EXPECT_TRUE(notMatches("int i;", varDecl(isExternC())));
+}
+
+TEST(IsStaticStorageClass, MatchesStaticDeclarations) {
+ EXPECT_TRUE(
+ matches("static void f() {}", functionDecl(isStaticStorageClass())));
+ EXPECT_TRUE(matches("static int i = 1;", varDecl(isStaticStorageClass())));
+ EXPECT_TRUE(notMatches("int i = 1;", varDecl(isStaticStorageClass())));
+ EXPECT_TRUE(notMatches("extern int i;", varDecl(isStaticStorageClass())));
+ EXPECT_TRUE(notMatches("void f() {}", functionDecl(isStaticStorageClass())));
+}
+
TEST(IsDefaulted, MatchesDefaultedFunctionDeclarations) {
EXPECT_TRUE(notMatches("class A { ~A(); };",
functionDecl(hasName("~A"), isDefaulted())));
@@ -1387,6 +1404,16 @@ TEST(Member, BitFields) {
fieldDecl(isBitField(), hasBitWidth(2), hasName("a"))));
}
+TEST(Member, InClassInitializer) {
+ EXPECT_TRUE(
+ matches("class C { int a = 2; int b; };",
+ fieldDecl(hasInClassInitializer(integerLiteral(equals(2))),
+ hasName("a"))));
+ EXPECT_TRUE(
+ notMatches("class C { int a = 2; int b; };",
+ fieldDecl(hasInClassInitializer(anything()), hasName("b"))));
+}
+
TEST(Member, UnderstandsAccess) {
EXPECT_TRUE(matches(
"struct A { int i; };", fieldDecl(isPublic(), hasName("i"))));
@@ -1931,5 +1958,21 @@ TEST(NullPointerConstants, Basic) {
EXPECT_TRUE(notMatches("int i = 0;", expr(nullPointerConstant())));
}
+TEST(HasExternalFormalLinkage, Basic) {
+ EXPECT_TRUE(matches("int a = 0;", namedDecl(hasExternalFormalLinkage())));
+ EXPECT_TRUE(
+ notMatches("static int a = 0;", namedDecl(hasExternalFormalLinkage())));
+ EXPECT_TRUE(notMatches("static void f(void) { int a = 0; }",
+ namedDecl(hasExternalFormalLinkage())));
+ EXPECT_TRUE(matches("void f(void) { int a = 0; }",
+ namedDecl(hasExternalFormalLinkage())));
+
+ // Despite having internal semantic linkage, the anonymous namespace member
+ // has external linkage because the member has a unique name in all
+ // translation units.
+ EXPECT_TRUE(matches("namespace { int a = 0; }",
+ namedDecl(hasExternalFormalLinkage())));
+}
+
} // namespace ast_matchers
} // namespace clang
diff --git a/unittests/ASTMatchers/ASTMatchersNodeTest.cpp b/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
index 6c8a5e000f49..dd45ca3ced92 100644
--- a/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
+++ b/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
@@ -528,6 +528,11 @@ TEST(Matcher, ConstructorCall) {
EXPECT_TRUE(matches("class X {}; void x(int) { X x; }", Constructor));
}
+TEST(Match, ConstructorInitializers) {
+ EXPECT_TRUE(matches("class C { int i; public: C(int ii) : i(ii) {} };",
+ cxxCtorInitializer(forField(hasName("i")))));
+}
+
TEST(Matcher, ThisExpr) {
EXPECT_TRUE(
matches("struct X { int a; int f () { return a; } };", cxxThisExpr()));
@@ -589,7 +594,7 @@ TEST(MaterializeTemporaryExpr, MatchesTemporary) {
materializeTemporaryExpr()));
EXPECT_TRUE(
- notMatches(ClassString +
+ matches(ClassString +
"string GetStringByValue();"
"void run() { int k = GetStringByValue().length(); }",
materializeTemporaryExpr()));
diff --git a/unittests/ASTMatchers/ASTMatchersTest.h b/unittests/ASTMatchers/ASTMatchersTest.h
index 4b3387c0ba72..fdb273c672da 100644
--- a/unittests/ASTMatchers/ASTMatchersTest.h
+++ b/unittests/ASTMatchers/ASTMatchersTest.h
@@ -189,7 +189,7 @@ testing::AssertionResult matchesConditionallyWithCuda(
// avoid constructing a full system triple.
std::vector<std::string> Args = {
"-xcuda", "-fno-ms-extensions", "--cuda-host-only", "-nocudainc",
- "-target", "nvptx64-unknown-unknown", CompileArg};
+ "-target", "x86_64-unknown-unknown", CompileArg};
if (!runToolOnCodeWithArgs(Factory->create(),
CudaHeader + Code, Args)) {
return testing::AssertionFailure() << "Parsing error in \"" << Code << "\"";
diff --git a/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
index 4149d4fd0b11..67a4a3b2fc09 100644
--- a/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ b/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -241,6 +241,36 @@ TEST(HasDeclaration, HasDeclarationOfTemplateSpecializationType) {
hasDeclaration(namedDecl(hasName("A"))))))));
}
+TEST(HasDeclaration, HasDeclarationOfCXXNewExpr) {
+ EXPECT_TRUE(
+ matches("int *A = new int();",
+ cxxNewExpr(hasDeclaration(functionDecl(parameterCountIs(1))))));
+}
+
+TEST(HasUnqualifiedDesugaredType, DesugarsUsing) {
+ EXPECT_TRUE(
+ matches("struct A {}; using B = A; B b;",
+ varDecl(hasType(hasUnqualifiedDesugaredType(recordType())))));
+ EXPECT_TRUE(
+ matches("struct A {}; using B = A; using C = B; C b;",
+ varDecl(hasType(hasUnqualifiedDesugaredType(recordType())))));
+}
+
+TEST(HasUnderlyingDecl, Matches) {
+ EXPECT_TRUE(matches("namespace N { template <class T> void f(T t); }"
+ "template <class T> void g() { using N::f; f(T()); }",
+ unresolvedLookupExpr(hasAnyDeclaration(
+ namedDecl(hasUnderlyingDecl(hasName("::N::f")))))));
+ EXPECT_TRUE(matches(
+ "namespace N { template <class T> void f(T t); }"
+ "template <class T> void g() { N::f(T()); }",
+ unresolvedLookupExpr(hasAnyDeclaration(namedDecl(hasName("::N::f"))))));
+ EXPECT_TRUE(notMatches(
+ "namespace N { template <class T> void f(T t); }"
+ "template <class T> void g() { using N::f; f(T()); }",
+ unresolvedLookupExpr(hasAnyDeclaration(namedDecl(hasName("::N::f"))))));
+}
+
TEST(HasType, TakesQualTypeMatcherAndMatchesExpr) {
TypeMatcher ClassX = hasDeclaration(recordDecl(hasName("X")));
EXPECT_TRUE(
@@ -543,6 +573,14 @@ TEST(Matcher, MatchesTypeTemplateArgument) {
asString("int"))))));
}
+TEST(Matcher, MatchesTemplateTemplateArgument) {
+ EXPECT_TRUE(matches("template<template <typename> class S> class X {};"
+ "template<typename T> class Y {};"
+ "X<Y> xi;",
+ classTemplateSpecializationDecl(hasAnyTemplateArgument(
+ refersToTemplate(templateName())))));
+}
+
TEST(Matcher, MatchesDeclarationReferenceTemplateArgument) {
EXPECT_TRUE(matches(
"struct B { int next; };"
@@ -594,6 +632,14 @@ TEST(Matcher, MatchesSpecificArgument) {
"A<int, bool> a;",
templateSpecializationType(hasTemplateArgument(
1, refersToType(asString("int"))))));
+
+ EXPECT_TRUE(matches(
+ "template<typename T> void f() {};"
+ "void func() { f<int>(); }",
+ functionDecl(hasTemplateArgument(0, refersToType(asString("int"))))));
+ EXPECT_TRUE(notMatches(
+ "template<typename T> void f() {};",
+ functionDecl(hasTemplateArgument(0, refersToType(asString("int"))))));
}
TEST(TemplateArgument, Matches) {
@@ -603,6 +649,94 @@ TEST(TemplateArgument, Matches) {
EXPECT_TRUE(matches(
"template<typename T> struct C {}; C<int> c;",
templateSpecializationType(hasAnyTemplateArgument(templateArgument()))));
+
+ EXPECT_TRUE(matches(
+ "template<typename T> void f() {};"
+ "void func() { f<int>(); }",
+ functionDecl(hasAnyTemplateArgument(templateArgument()))));
+}
+
+TEST(TemplateTypeParmDecl, CXXMethodDecl) {
+ const char input[] =
+ "template<typename T>\n"
+ "class Class {\n"
+ " void method();\n"
+ "};\n"
+ "template<typename U>\n"
+ "void Class<U>::method() {}\n";
+ EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("T"))));
+ EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("U"))));
+}
+
+TEST(TemplateTypeParmDecl, VarDecl) {
+ const char input[] =
+ "template<typename T>\n"
+ "class Class {\n"
+ " static T pi;\n"
+ "};\n"
+ "template<typename U>\n"
+ "U Class<U>::pi = U(3.1415926535897932385);\n";
+ EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("T"))));
+ EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("U"))));
+}
+
+TEST(TemplateTypeParmDecl, VarTemplatePartialSpecializationDecl) {
+ const char input[] =
+ "template<typename T>\n"
+ "struct Struct {\n"
+ " template<typename T2> static int field;\n"
+ "};\n"
+ "template<typename U>\n"
+ "template<typename U2>\n"
+ "int Struct<U>::field<U2*> = 123;\n";
+ EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("T"))));
+ EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("T2"))));
+ EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("U"))));
+ EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("U2"))));
+}
+
+TEST(TemplateTypeParmDecl, ClassTemplatePartialSpecializationDecl) {
+ const char input[] =
+ "template<typename T>\n"
+ "class Class {\n"
+ " template<typename T2> struct Struct;\n"
+ "};\n"
+ "template<typename U>\n"
+ "template<typename U2>\n"
+ "struct Class<U>::Struct<U2*> {};\n";
+ EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("T"))));
+ EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("T2"))));
+ EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("U"))));
+ EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("U2"))));
+}
+
+TEST(TemplateTypeParmDecl, EnumDecl) {
+ const char input[] =
+ "template<typename T>\n"
+ "struct Struct {\n"
+ " enum class Enum : T;\n"
+ "};\n"
+ "template<typename U>\n"
+ "enum class Struct<U>::Enum : U {\n"
+ " e1,\n"
+ " e2\n"
+ "};\n";
+ EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("T"))));
+ EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("U"))));
+}
+
+TEST(TemplateTypeParmDecl, RecordDecl) {
+ const char input[] =
+ "template<typename T>\n"
+ "class Class {\n"
+ " struct Struct;\n"
+ "};\n"
+ "template<typename U>\n"
+ "struct Class<U>::Struct {\n"
+ " U field;\n"
+ "};\n";
+ EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("T"))));
+ EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("U"))));
}
TEST(RefersToIntegralType, Matches) {
@@ -2051,5 +2185,41 @@ TEST(Matcher, ForEachOverriden) {
EXPECT_TRUE(notMatches(Code2, ForEachOverriddenInClass("A1")));
}
+TEST(Matcher, HasAnyDeclaration) {
+ std::string Fragment = "void foo(int p1);"
+ "void foo(int *p2);"
+ "void bar(int p3);"
+ "template <typename T> void baz(T t) { foo(t); }";
+
+ EXPECT_TRUE(
+ matches(Fragment, unresolvedLookupExpr(hasAnyDeclaration(functionDecl(
+ hasParameter(0, parmVarDecl(hasName("p1"))))))));
+ EXPECT_TRUE(
+ matches(Fragment, unresolvedLookupExpr(hasAnyDeclaration(functionDecl(
+ hasParameter(0, parmVarDecl(hasName("p2"))))))));
+ EXPECT_TRUE(
+ notMatches(Fragment, unresolvedLookupExpr(hasAnyDeclaration(functionDecl(
+ hasParameter(0, parmVarDecl(hasName("p3"))))))));
+ EXPECT_TRUE(notMatches(Fragment, unresolvedLookupExpr(hasAnyDeclaration(
+ functionDecl(hasName("bar"))))));
+}
+
+TEST(SubstTemplateTypeParmType, HasReplacementType)
+{
+ std::string Fragment = "template<typename T>"
+ "double F(T t);"
+ "int i;"
+ "double j = F(i);";
+ EXPECT_TRUE(matches(Fragment, substTemplateTypeParmType(hasReplacementType(
+ qualType(asString("int"))))));
+ EXPECT_TRUE(notMatches(Fragment, substTemplateTypeParmType(hasReplacementType(
+ qualType(asString("double"))))));
+ EXPECT_TRUE(
+ notMatches("template<int N>"
+ "double F();"
+ "double j = F<5>();",
+ substTemplateTypeParmType(hasReplacementType(qualType()))));
+}
+
} // namespace ast_matchers
} // namespace clang
diff --git a/unittests/ASTMatchers/Dynamic/ParserTest.cpp b/unittests/ASTMatchers/Dynamic/ParserTest.cpp
index 553427c9a403..d241f5ba2f86 100644
--- a/unittests/ASTMatchers/Dynamic/ParserTest.cpp
+++ b/unittests/ASTMatchers/Dynamic/ParserTest.cpp
@@ -11,7 +11,6 @@
#include "clang/ASTMatchers/Dynamic/Parser.h"
#include "clang/ASTMatchers/Dynamic/Registry.h"
#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/StringMap.h"
#include "gtest/gtest.h"
#include <string>
#include <vector>
diff --git a/unittests/Analysis/CFGTest.cpp b/unittests/Analysis/CFGTest.cpp
index a8d397e9a534..e691110050a2 100644
--- a/unittests/Analysis/CFGTest.cpp
+++ b/unittests/Analysis/CFGTest.cpp
@@ -18,6 +18,41 @@ namespace clang {
namespace analysis {
namespace {
+enum BuildResult {
+ ToolFailed,
+ ToolRan,
+ SawFunctionBody,
+ BuiltCFG,
+};
+
+class CFGCallback : public ast_matchers::MatchFinder::MatchCallback {
+public:
+ BuildResult TheBuildResult = ToolRan;
+
+ void run(const ast_matchers::MatchFinder::MatchResult &Result) override {
+ const auto *Func = Result.Nodes.getNodeAs<FunctionDecl>("func");
+ Stmt *Body = Func->getBody();
+ if (!Body)
+ return;
+ TheBuildResult = SawFunctionBody;
+ if (CFG::buildCFG(nullptr, Body, Result.Context, CFG::BuildOptions()))
+ TheBuildResult = BuiltCFG;
+ }
+};
+
+BuildResult BuildCFG(const char *Code) {
+ CFGCallback Callback;
+
+ ast_matchers::MatchFinder Finder;
+ Finder.addMatcher(ast_matchers::functionDecl().bind("func"), &Callback);
+ std::unique_ptr<tooling::FrontendActionFactory> Factory(
+ tooling::newFrontendActionFactory(&Finder));
+ std::vector<std::string> Args = {"-std=c++11", "-fno-delayed-template-parsing"};
+ if (!tooling::runToolOnCodeWithArgs(Factory->create(), Code, Args))
+ return ToolFailed;
+ return Callback.TheBuildResult;
+}
+
// Constructing a CFG for a range-based for over a dependent type fails (but
// should not crash).
TEST(CFG, RangeBasedForOverDependentType) {
@@ -27,30 +62,17 @@ TEST(CFG, RangeBasedForOverDependentType) {
" for (const Foo *TheFoo : Range) {\n"
" }\n"
"}\n";
+ EXPECT_EQ(SawFunctionBody, BuildCFG(Code));
+}
- class CFGCallback : public ast_matchers::MatchFinder::MatchCallback {
- public:
- bool SawFunctionBody = false;
-
- void run(const ast_matchers::MatchFinder::MatchResult &Result) override {
- const auto *Func = Result.Nodes.getNodeAs<FunctionDecl>("func");
- Stmt *Body = Func->getBody();
- if (!Body)
- return;
- SawFunctionBody = true;
- std::unique_ptr<CFG> cfg =
- CFG::buildCFG(nullptr, Body, Result.Context, CFG::BuildOptions());
- EXPECT_EQ(nullptr, cfg);
- }
- } Callback;
-
- ast_matchers::MatchFinder Finder;
- Finder.addMatcher(ast_matchers::functionDecl().bind("func"), &Callback);
- std::unique_ptr<tooling::FrontendActionFactory> Factory(
- tooling::newFrontendActionFactory(&Finder));
- std::vector<std::string> Args = {"-std=c++11", "-fno-delayed-template-parsing"};
- ASSERT_TRUE(tooling::runToolOnCodeWithArgs(Factory->create(), Code, Args));
- EXPECT_TRUE(Callback.SawFunctionBody);
+// Constructing a CFG containing a delete expression on a dependent type should
+// not crash.
+TEST(CFG, DeleteExpressionOnDependentType) {
+ const char *Code = "template<class T>\n"
+ "void f(T t) {\n"
+ " delete t;\n"
+ "}\n";
+ EXPECT_EQ(BuiltCFG, BuildCFG(Code));
}
} // namespace
diff --git a/unittests/Basic/FileManagerTest.cpp b/unittests/Basic/FileManagerTest.cpp
index d8d85dd76c38..4cf21cd8459a 100644
--- a/unittests/Basic/FileManagerTest.cpp
+++ b/unittests/Basic/FileManagerTest.cpp
@@ -52,7 +52,7 @@ public:
}
// Implement FileSystemStatCache::getStat().
- LookupResult getStat(const char *Path, FileData &Data, bool isFile,
+ LookupResult getStat(StringRef Path, FileData &Data, bool isFile,
std::unique_ptr<vfs::File> *F,
vfs::FileSystem &FS) override {
if (StatCalls.count(Path) != 0) {
@@ -82,14 +82,14 @@ TEST_F(FileManagerTest, getVirtualFileSetsTheDirFieldCorrectly) {
const DirectoryEntry *dir = file->getDir();
ASSERT_TRUE(dir != nullptr);
- EXPECT_STREQ(".", dir->getName());
+ EXPECT_EQ(".", dir->getName());
file = manager.getVirtualFile("x/y/z.cpp", 42, 0);
ASSERT_TRUE(file != nullptr);
dir = file->getDir();
ASSERT_TRUE(dir != nullptr);
- EXPECT_STREQ("x/y", dir->getName());
+ EXPECT_EQ("x/y", dir->getName());
}
// Before any virtual file is added, no virtual directory exists.
@@ -115,11 +115,11 @@ TEST_F(FileManagerTest, getVirtualFileCreatesDirectoryEntriesForAncestors) {
const DirectoryEntry *dir = manager.getDirectory("virtual/dir");
ASSERT_TRUE(dir != nullptr);
- EXPECT_STREQ("virtual/dir", dir->getName());
+ EXPECT_EQ("virtual/dir", dir->getName());
dir = manager.getDirectory("virtual");
ASSERT_TRUE(dir != nullptr);
- EXPECT_STREQ("virtual", dir->getName());
+ EXPECT_EQ("virtual", dir->getName());
}
// getFile() returns non-NULL if a real file exists at the given path.
@@ -140,11 +140,11 @@ TEST_F(FileManagerTest, getFileReturnsValidFileEntryForExistingRealFile) {
const FileEntry *file = manager.getFile("/tmp/test");
ASSERT_TRUE(file != nullptr);
- EXPECT_STREQ("/tmp/test", file->getName());
+ EXPECT_EQ("/tmp/test", file->getName());
const DirectoryEntry *dir = file->getDir();
ASSERT_TRUE(dir != nullptr);
- EXPECT_STREQ("/tmp", dir->getName());
+ EXPECT_EQ("/tmp", dir->getName());
#ifdef LLVM_ON_WIN32
file = manager.getFile(FileName);
@@ -152,7 +152,7 @@ TEST_F(FileManagerTest, getFileReturnsValidFileEntryForExistingRealFile) {
dir = file->getDir();
ASSERT_TRUE(dir != NULL);
- EXPECT_STREQ(DirName, dir->getName());
+ EXPECT_EQ(DirName, dir->getName());
#endif
}
@@ -164,11 +164,11 @@ TEST_F(FileManagerTest, getFileReturnsValidFileEntryForExistingVirtualFile) {
manager.getVirtualFile("virtual/dir/bar.h", 100, 0);
const FileEntry *file = manager.getFile("virtual/dir/bar.h");
ASSERT_TRUE(file != nullptr);
- EXPECT_STREQ("virtual/dir/bar.h", file->getName());
+ EXPECT_EQ("virtual/dir/bar.h", file->getName());
const DirectoryEntry *dir = file->getDir();
ASSERT_TRUE(dir != nullptr);
- EXPECT_STREQ("virtual/dir", dir->getName());
+ EXPECT_EQ("virtual/dir", dir->getName());
}
// getFile() returns different FileEntries for different paths when
diff --git a/unittests/Basic/VirtualFileSystemTest.cpp b/unittests/Basic/VirtualFileSystemTest.cpp
index 3b26488a7fd9..580343d93ea1 100644
--- a/unittests/Basic/VirtualFileSystemTest.cpp
+++ b/unittests/Basic/VirtualFileSystemTest.cpp
@@ -12,7 +12,6 @@
#include "llvm/Support/Errc.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/Path.h"
#include "llvm/Support/SourceMgr.h"
#include "gtest/gtest.h"
#include <map>
@@ -116,20 +115,23 @@ public:
}
void addRegularFile(StringRef Path, sys::fs::perms Perms = sys::fs::all_all) {
- vfs::Status S(Path, UniqueID(FSID, FileID++), sys::TimeValue::now(), 0, 0,
- 1024, sys::fs::file_type::regular_file, Perms);
+ vfs::Status S(Path, UniqueID(FSID, FileID++),
+ std::chrono::system_clock::now(), 0, 0, 1024,
+ sys::fs::file_type::regular_file, Perms);
addEntry(Path, S);
}
void addDirectory(StringRef Path, sys::fs::perms Perms = sys::fs::all_all) {
- vfs::Status S(Path, UniqueID(FSID, FileID++), sys::TimeValue::now(), 0, 0,
- 0, sys::fs::file_type::directory_file, Perms);
+ vfs::Status S(Path, UniqueID(FSID, FileID++),
+ std::chrono::system_clock::now(), 0, 0, 0,
+ sys::fs::file_type::directory_file, Perms);
addEntry(Path, S);
}
void addSymlink(StringRef Path) {
- vfs::Status S(Path, UniqueID(FSID, FileID++), sys::TimeValue::now(), 0, 0,
- 0, sys::fs::file_type::symlink_file, sys::fs::all_all);
+ vfs::Status S(Path, UniqueID(FSID, FileID++),
+ std::chrono::system_clock::now(), 0, 0, 0,
+ sys::fs::file_type::symlink_file, sys::fs::all_all);
addEntry(Path, S);
}
};
diff --git a/unittests/Driver/CMakeLists.txt b/unittests/Driver/CMakeLists.txt
index 2df1eb24fd44..b9c52f7a53f9 100644
--- a/unittests/Driver/CMakeLists.txt
+++ b/unittests/Driver/CMakeLists.txt
@@ -3,6 +3,7 @@ set(LLVM_LINK_COMPONENTS
)
add_clang_unittest(ClangDriverTests
+ DistroTest.cpp
ToolChainTest.cpp
MultilibTest.cpp
)
diff --git a/unittests/Driver/DistroTest.cpp b/unittests/Driver/DistroTest.cpp
new file mode 100644
index 000000000000..e3686e498060
--- /dev/null
+++ b/unittests/Driver/DistroTest.cpp
@@ -0,0 +1,305 @@
+//===- unittests/Driver/DistroTest.cpp --- ToolChains tests ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Unit tests for Distro detection.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/Distro.h"
+#include "clang/Basic/VirtualFileSystem.h"
+#include "llvm/Support/raw_ostream.h"
+#include "gtest/gtest.h"
+using namespace clang;
+using namespace clang::driver;
+
+namespace {
+
+// The tests include all release-related files for each distribution
+// in the VFS, in order to make sure that earlier tests do not
+// accidentally result in incorrect distribution guess.
+
+TEST(DistroTest, DetectUbuntu) {
+ vfs::InMemoryFileSystem UbuntuTrustyFileSystem;
+ // Ubuntu uses Debian Sid version.
+ UbuntuTrustyFileSystem.addFile("/etc/debian_version", 0,
+ llvm::MemoryBuffer::getMemBuffer("jessie/sid\n"));
+ UbuntuTrustyFileSystem.addFile("/etc/lsb-release", 0,
+ llvm::MemoryBuffer::getMemBuffer("DISTRIB_ID=Ubuntu\n"
+ "DISTRIB_RELEASE=14.04\n"
+ "DISTRIB_CODENAME=trusty\n"
+ "DISTRIB_DESCRIPTION=\"Ubuntu 14.04 LTS\"\n"));
+ UbuntuTrustyFileSystem.addFile("/etc/os-release", 0,
+ llvm::MemoryBuffer::getMemBuffer("NAME=\"Ubuntu\"\n"
+ "VERSION=\"14.04, Trusty Tahr\"\n"
+ "ID=ubuntu\n"
+ "ID_LIKE=debian\n"
+ "PRETTY_NAME=\"Ubuntu 14.04 LTS\"\n"
+ "VERSION_ID=\"14.04\"\n"
+ "HOME_URL=\"http://www.ubuntu.com/\"\n"
+ "SUPPORT_URL=\"http://help.ubuntu.com/\"\n"
+ "BUG_REPORT_URL=\"http://bugs.launchpad.net/ubuntu/\"\n"));
+
+ Distro UbuntuTrusty{UbuntuTrustyFileSystem};
+ ASSERT_EQ(Distro(Distro::UbuntuTrusty), UbuntuTrusty);
+ ASSERT_TRUE(UbuntuTrusty.IsUbuntu());
+ ASSERT_FALSE(UbuntuTrusty.IsRedhat());
+ ASSERT_FALSE(UbuntuTrusty.IsOpenSUSE());
+ ASSERT_FALSE(UbuntuTrusty.IsDebian());
+
+ vfs::InMemoryFileSystem UbuntuYakketyFileSystem;
+ UbuntuYakketyFileSystem.addFile("/etc/debian_version", 0,
+ llvm::MemoryBuffer::getMemBuffer("stretch/sid\n"));
+ UbuntuYakketyFileSystem.addFile("/etc/lsb-release", 0,
+ llvm::MemoryBuffer::getMemBuffer("DISTRIB_ID=Ubuntu\n"
+ "DISTRIB_RELEASE=16.10\n"
+ "DISTRIB_CODENAME=yakkety\n"
+ "DISTRIB_DESCRIPTION=\"Ubuntu 16.10\"\n"));
+ UbuntuYakketyFileSystem.addFile("/etc/os-release", 0,
+ llvm::MemoryBuffer::getMemBuffer("NAME=\"Ubuntu\"\n"
+ "VERSION=\"16.10 (Yakkety Yak)\"\n"
+ "ID=ubuntu\n"
+ "ID_LIKE=debian\n"
+ "PRETTY_NAME=\"Ubuntu 16.10\"\n"
+ "VERSION_ID=\"16.10\"\n"
+ "HOME_URL=\"http://www.ubuntu.com/\"\n"
+ "SUPPORT_URL=\"http://help.ubuntu.com/\"\n"
+ "BUG_REPORT_URL=\"http://bugs.launchpad.net/ubuntu/\"\n"
+ "PRIVACY_POLICY_URL=\"http://www.ubuntu.com/legal/terms-and-policies/privacy-policy\"\n"
+ "VERSION_CODENAME=yakkety\n"
+ "UBUNTU_CODENAME=yakkety\n"));
+
+ Distro UbuntuYakkety{UbuntuYakketyFileSystem};
+ ASSERT_EQ(Distro(Distro::UbuntuYakkety), UbuntuYakkety);
+ ASSERT_TRUE(UbuntuYakkety.IsUbuntu());
+ ASSERT_FALSE(UbuntuYakkety.IsRedhat());
+ ASSERT_FALSE(UbuntuYakkety.IsOpenSUSE());
+ ASSERT_FALSE(UbuntuYakkety.IsDebian());
+}
+
+TEST(DistroTest, DetectRedhat) {
+ vfs::InMemoryFileSystem Fedora25FileSystem;
+ Fedora25FileSystem.addFile("/etc/system-release-cpe", 0,
+ llvm::MemoryBuffer::getMemBuffer("cpe:/o:fedoraproject:fedora:25\n"));
+ // Both files are symlinks to fedora-release.
+ Fedora25FileSystem.addFile("/etc/system-release", 0,
+ llvm::MemoryBuffer::getMemBuffer("Fedora release 25 (Twenty Five)\n"));
+ Fedora25FileSystem.addFile("/etc/redhat-release", 0,
+ llvm::MemoryBuffer::getMemBuffer("Fedora release 25 (Twenty Five)\n"));
+ Fedora25FileSystem.addFile("/etc/fedora-release", 0,
+ llvm::MemoryBuffer::getMemBuffer("Fedora release 25 (Twenty Five)\n"));
+ Fedora25FileSystem.addFile("/etc/os-release", 0,
+ llvm::MemoryBuffer::getMemBuffer("NAME=Fedora\n"
+ "VERSION=\"25 (Twenty Five)\"\n"
+ "ID=fedora\n"
+ "VERSION_ID=25\n"
+ "PRETTY_NAME=\"Fedora 25 (Twenty Five)\"\n"
+ "ANSI_COLOR=\"0;34\"\n"
+ "CPE_NAME=\"cpe:/o:fedoraproject:fedora:25\"\n"
+ "HOME_URL=\"https://fedoraproject.org/\"\n"
+ "BUG_REPORT_URL=\"https://bugzilla.redhat.com/\"\n"
+ "REDHAT_BUGZILLA_PRODUCT=\"Fedora\"\n"
+ "REDHAT_BUGZILLA_PRODUCT_VERSION=25\n"
+ "REDHAT_SUPPORT_PRODUCT=\"Fedora\"\n"
+ "REDHAT_SUPPORT_PRODUCT_VERSION=25\n"
+ "PRIVACY_POLICY_URL=https://fedoraproject.org/wiki/Legal:PrivacyPolicy\n"));
+ Distro Fedora25{Fedora25FileSystem};
+ ASSERT_EQ(Distro(Distro::Fedora), Fedora25);
+ ASSERT_FALSE(Fedora25.IsUbuntu());
+ ASSERT_TRUE(Fedora25.IsRedhat());
+ ASSERT_FALSE(Fedora25.IsOpenSUSE());
+ ASSERT_FALSE(Fedora25.IsDebian());
+
+ vfs::InMemoryFileSystem CentOS7FileSystem;
+ CentOS7FileSystem.addFile("/etc/system-release-cpe", 0,
+ llvm::MemoryBuffer::getMemBuffer("cpe:/o:centos:centos:7\n"));
+ // Both files are symlinks to centos-release.
+ CentOS7FileSystem.addFile("/etc/system-release", 0,
+ llvm::MemoryBuffer::getMemBuffer("CentOS Linux release 7.2.1511 (Core) \n"));
+ CentOS7FileSystem.addFile("/etc/redhat-release", 0,
+ llvm::MemoryBuffer::getMemBuffer("CentOS Linux release 7.2.1511 (Core) \n"));
+ CentOS7FileSystem.addFile("/etc/centos-release", 0,
+ llvm::MemoryBuffer::getMemBuffer("CentOS Linux release 7.2.1511 (Core) \n"));
+ CentOS7FileSystem.addFile("/etc/centos-release-upstream", 0,
+ llvm::MemoryBuffer::getMemBuffer("Derived from Red Hat Enterprise Linux 7.2 (Source)\n"));
+ CentOS7FileSystem.addFile("/etc/os-release", 0,
+ llvm::MemoryBuffer::getMemBuffer("NAME=\"CentOS Linux\"\n"
+ "VERSION=\"7 (Core)\"\n"
+ "ID=\"centos\"\n"
+ "ID_LIKE=\"rhel fedora\"\n"
+ "VERSION_ID=\"7\"\n"
+ "PRETTY_NAME=\"CentOS Linux 7 (Core)\"\n"
+ "ANSI_COLOR=\"0;31\"\n"
+ "CPE_NAME=\"cpe:/o:centos:centos:7\"\n"
+ "HOME_URL=\"https://www.centos.org/\"\n"
+ "BUG_REPORT_URL=\"https://bugs.centos.org/\"\n"
+ "\n"
+ "CENTOS_MANTISBT_PROJECT=\"CentOS-7\"\n"
+ "CENTOS_MANTISBT_PROJECT_VERSION=\"7\"\n"
+ "REDHAT_SUPPORT_PRODUCT=\"centos\"\n"
+ "REDHAT_SUPPORT_PRODUCT_VERSION=\"7\"\n"));
+
+ Distro CentOS7{CentOS7FileSystem};
+ ASSERT_EQ(Distro(Distro::RHEL7), CentOS7);
+ ASSERT_FALSE(CentOS7.IsUbuntu());
+ ASSERT_TRUE(CentOS7.IsRedhat());
+ ASSERT_FALSE(CentOS7.IsOpenSUSE());
+ ASSERT_FALSE(CentOS7.IsDebian());
+}
+
+TEST(DistroTest, DetectOpenSUSE) {
+ vfs::InMemoryFileSystem OpenSUSELeap421FileSystem;
+ OpenSUSELeap421FileSystem.addFile("/etc/SuSE-release", 0,
+ llvm::MemoryBuffer::getMemBuffer("openSUSE 42.1 (x86_64)\n"
+ "VERSION = 42.1\n"
+ "CODENAME = Malachite\n"
+ "# /etc/SuSE-release is deprecated and will be removed in the future, use /etc/os-release instead\n"));
+ OpenSUSELeap421FileSystem.addFile("/etc/os-release", 0,
+ llvm::MemoryBuffer::getMemBuffer("NAME=\"openSUSE Leap\"\n"
+ "VERSION=\"42.1\"\n"
+ "VERSION_ID=\"42.1\"\n"
+ "PRETTY_NAME=\"openSUSE Leap 42.1 (x86_64)\"\n"
+ "ID=opensuse\n"
+ "ANSI_COLOR=\"0;32\"\n"
+ "CPE_NAME=\"cpe:/o:opensuse:opensuse:42.1\"\n"
+ "BUG_REPORT_URL=\"https://bugs.opensuse.org\"\n"
+ "HOME_URL=\"https://opensuse.org/\"\n"
+ "ID_LIKE=\"suse\"\n"));
+
+ Distro OpenSUSELeap421{OpenSUSELeap421FileSystem};
+ ASSERT_EQ(Distro(Distro::OpenSUSE), OpenSUSELeap421);
+ ASSERT_FALSE(OpenSUSELeap421.IsUbuntu());
+ ASSERT_FALSE(OpenSUSELeap421.IsRedhat());
+ ASSERT_TRUE(OpenSUSELeap421.IsOpenSUSE());
+ ASSERT_FALSE(OpenSUSELeap421.IsDebian());
+
+ vfs::InMemoryFileSystem OpenSUSE132FileSystem;
+ OpenSUSE132FileSystem.addFile("/etc/SuSE-release", 0,
+ llvm::MemoryBuffer::getMemBuffer("openSUSE 13.2 (x86_64)\n"
+ "VERSION = 13.2\n"
+ "CODENAME = Harlequin\n"
+ "# /etc/SuSE-release is deprecated and will be removed in the future, use /etc/os-release instead\n"));
+ OpenSUSE132FileSystem.addFile("/etc/os-release", 0,
+ llvm::MemoryBuffer::getMemBuffer("NAME=openSUSE\n"
+ "VERSION=\"13.2 (Harlequin)\"\n"
+ "VERSION_ID=\"13.2\"\n"
+ "PRETTY_NAME=\"openSUSE 13.2 (Harlequin) (x86_64)\"\n"
+ "ID=opensuse\n"
+ "ANSI_COLOR=\"0;32\"\n"
+ "CPE_NAME=\"cpe:/o:opensuse:opensuse:13.2\"\n"
+ "BUG_REPORT_URL=\"https://bugs.opensuse.org\"\n"
+ "HOME_URL=\"https://opensuse.org/\"\n"
+ "ID_LIKE=\"suse\"\n"));
+
+ Distro OpenSUSE132{OpenSUSE132FileSystem};
+ ASSERT_EQ(Distro(Distro::OpenSUSE), OpenSUSE132);
+ ASSERT_FALSE(OpenSUSE132.IsUbuntu());
+ ASSERT_FALSE(OpenSUSE132.IsRedhat());
+ ASSERT_TRUE(OpenSUSE132.IsOpenSUSE());
+ ASSERT_FALSE(OpenSUSE132.IsDebian());
+
+ vfs::InMemoryFileSystem SLES10FileSystem;
+ SLES10FileSystem.addFile("/etc/SuSE-release", 0,
+ llvm::MemoryBuffer::getMemBuffer("SUSE Linux Enterprise Server 10 (x86_64)\n"
+ "VERSION = 10\n"
+ "PATCHLEVEL = 4\n"));
+ SLES10FileSystem.addFile("/etc/lsb_release", 0,
+ llvm::MemoryBuffer::getMemBuffer("LSB_VERSION=\"core-2.0-noarch:core-3.0-noarch:core-2.0-x86_64:core-3.0-x86_64\"\n"));
+
+ // SLES10 is unsupported and therefore evaluates to unknown
+ Distro SLES10{SLES10FileSystem};
+ ASSERT_EQ(Distro(Distro::UnknownDistro), SLES10);
+ ASSERT_FALSE(SLES10.IsUbuntu());
+ ASSERT_FALSE(SLES10.IsRedhat());
+ ASSERT_FALSE(SLES10.IsOpenSUSE());
+ ASSERT_FALSE(SLES10.IsDebian());
+}
+
+TEST(DistroTest, DetectDebian) {
+ vfs::InMemoryFileSystem DebianJessieFileSystem;
+ DebianJessieFileSystem.addFile("/etc/debian_version", 0,
+ llvm::MemoryBuffer::getMemBuffer("8.6\n"));
+ DebianJessieFileSystem.addFile("/etc/os-release", 0,
+ llvm::MemoryBuffer::getMemBuffer("PRETTY_NAME=\"Debian GNU/Linux 8 (jessie)\"\n"
+ "NAME=\"Debian GNU/Linux\"\n"
+ "VERSION_ID=\"8\"\n"
+ "VERSION=\"8 (jessie)\"\n"
+ "ID=debian\n"
+ "HOME_URL=\"http://www.debian.org/\"\n"
+ "SUPPORT_URL=\"http://www.debian.org/support\"\n"
+ "BUG_REPORT_URL=\"https://bugs.debian.org/\"\n"));
+
+ Distro DebianJessie{DebianJessieFileSystem};
+ ASSERT_EQ(Distro(Distro::DebianJessie), DebianJessie);
+ ASSERT_FALSE(DebianJessie.IsUbuntu());
+ ASSERT_FALSE(DebianJessie.IsRedhat());
+ ASSERT_FALSE(DebianJessie.IsOpenSUSE());
+ ASSERT_TRUE(DebianJessie.IsDebian());
+
+ vfs::InMemoryFileSystem DebianStretchSidFileSystem;
+ DebianStretchSidFileSystem.addFile("/etc/debian_version", 0,
+ llvm::MemoryBuffer::getMemBuffer("stretch/sid\n"));
+ DebianStretchSidFileSystem.addFile("/etc/os-release", 0,
+ llvm::MemoryBuffer::getMemBuffer("PRETTY_NAME=\"Debian GNU/Linux stretch/sid\"\n"
+ "NAME=\"Debian GNU/Linux\"\n"
+ "ID=debian\n"
+ "HOME_URL=\"http://www.debian.org/\"\n"
+ "SUPPORT_URL=\"http://www.debian.org/support\"\n"
+ "BUG_REPORT_URL=\"https://bugs.debian.org/\"\n"));
+
+ Distro DebianStretchSid{DebianStretchSidFileSystem};
+ ASSERT_EQ(Distro(Distro::DebianStretch), DebianStretchSid);
+ ASSERT_FALSE(DebianStretchSid.IsUbuntu());
+ ASSERT_FALSE(DebianStretchSid.IsRedhat());
+ ASSERT_FALSE(DebianStretchSid.IsOpenSUSE());
+ ASSERT_TRUE(DebianStretchSid.IsDebian());
+}
+
+TEST(DistroTest, DetectExherbo) {
+ vfs::InMemoryFileSystem ExherboFileSystem;
+ ExherboFileSystem.addFile("/etc/exherbo-release", 0, // (ASCII art)
+ llvm::MemoryBuffer::getMemBuffer(""));
+ ExherboFileSystem.addFile("/etc/os-release", 0,
+ llvm::MemoryBuffer::getMemBuffer("NAME=\"Exherbo\"\n"
+ "PRETTY_NAME=\"Exherbo Linux\"\n"
+ "ID=\"exherbo\"\n"
+ "ANSI_COLOR=\"0;32\"\n"
+ "HOME_URL=\"https://www.exherbo.org/\"\n"
+ "SUPPORT_URL=\"irc://irc.freenode.net/#exherbo\"\n"
+ "BUG_REPORT_URL=\"https://bugs.exherbo.org/\"\n"));
+
+ Distro Exherbo{ExherboFileSystem};
+ ASSERT_EQ(Distro(Distro::Exherbo), Exherbo);
+ ASSERT_FALSE(Exherbo.IsUbuntu());
+ ASSERT_FALSE(Exherbo.IsRedhat());
+ ASSERT_FALSE(Exherbo.IsOpenSUSE());
+ ASSERT_FALSE(Exherbo.IsDebian());
+}
+
+TEST(DistroTest, DetectArchLinux) {
+ vfs::InMemoryFileSystem ArchLinuxFileSystem;
+ ArchLinuxFileSystem.addFile("/etc/arch-release", 0, // (empty)
+ llvm::MemoryBuffer::getMemBuffer(""));
+ ArchLinuxFileSystem.addFile("/etc/os-release", 0,
+ llvm::MemoryBuffer::getMemBuffer("NAME=\"Arch Linux\"\n"
+ "ID=arch\n"
+ "PRETTY_NAME=\"Arch Linux\"\n"
+ "ANSI_COLOR=\"0;36\"\n"
+ "HOME_URL=\"https://www.archlinux.org/\"\n"
+ "SUPPORT_URL=\"https://bbs.archlinux.org/\"\n"
+ "BUG_REPORT_URL=\"https://bugs.archlinux.org/\"\n"));
+
+ Distro ArchLinux{ArchLinuxFileSystem};
+ ASSERT_EQ(Distro(Distro::ArchLinux), ArchLinux);
+ ASSERT_FALSE(ArchLinux.IsUbuntu());
+ ASSERT_FALSE(ArchLinux.IsRedhat());
+ ASSERT_FALSE(ArchLinux.IsOpenSUSE());
+ ASSERT_FALSE(ArchLinux.IsDebian());
+}
+
+} // end anonymous namespace
diff --git a/unittests/Driver/ToolChainTest.cpp b/unittests/Driver/ToolChainTest.cpp
index ef21e2d17c6c..f7ba3eeab21b 100644
--- a/unittests/Driver/ToolChainTest.cpp
+++ b/unittests/Driver/ToolChainTest.cpp
@@ -117,4 +117,29 @@ TEST(ToolChainTest, VFSGCCInstallationRelativeDir) {
S);
}
+TEST(ToolChainTest, DefaultDriverMode) {
+ IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
+
+ IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
+ struct TestDiagnosticConsumer : public DiagnosticConsumer {};
+ DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer);
+ IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
+ new vfs::InMemoryFileSystem);
+
+ Driver CCDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags,
+ InMemoryFileSystem);
+ Driver CXXDriver("/home/test/bin/clang++", "arm-linux-gnueabi", Diags,
+ InMemoryFileSystem);
+ Driver CLDriver("/home/test/bin/clang-cl", "arm-linux-gnueabi", Diags,
+ InMemoryFileSystem);
+
+ std::unique_ptr<Compilation> CC(CCDriver.BuildCompilation({"foo.cpp"}));
+ std::unique_ptr<Compilation> CXX(CXXDriver.BuildCompilation({"foo.cpp"}));
+ std::unique_ptr<Compilation> CL(CLDriver.BuildCompilation({"foo.cpp"}));
+
+ EXPECT_TRUE(CCDriver.CCCIsCC());
+ EXPECT_TRUE(CXXDriver.CCCIsCXX());
+ EXPECT_TRUE(CLDriver.IsCLMode());
+}
+
} // end anonymous namespace
diff --git a/unittests/Format/CMakeLists.txt b/unittests/Format/CMakeLists.txt
index 240be6ead2a5..eb7756a0ba56 100644
--- a/unittests/Format/CMakeLists.txt
+++ b/unittests/Format/CMakeLists.txt
@@ -7,6 +7,7 @@ add_clang_unittest(FormatTests
FormatTest.cpp
FormatTestJava.cpp
FormatTestJS.cpp
+ FormatTestObjC.cpp
FormatTestProto.cpp
FormatTestSelective.cpp
SortImportsTestJS.cpp
diff --git a/unittests/Format/CleanupTest.cpp b/unittests/Format/CleanupTest.cpp
index 5f85c53b780a..6ac5f695d437 100644
--- a/unittests/Format/CleanupTest.cpp
+++ b/unittests/Format/CleanupTest.cpp
@@ -9,11 +9,15 @@
#include "clang/Format/Format.h"
+#include "../Tooling/ReplacementTest.h"
#include "../Tooling/RewriterTestContext.h"
#include "clang/Tooling/Core/Replacement.h"
#include "gtest/gtest.h"
+using clang::tooling::ReplacementTest;
+using clang::tooling::toReplacements;
+
namespace clang {
namespace format {
namespace {
@@ -29,6 +33,15 @@ protected:
EXPECT_TRUE(static_cast<bool>(Result));
return *Result;
}
+
+ // Returns code after cleanup around \p Offsets.
+ std::string cleanupAroundOffsets(llvm::ArrayRef<unsigned> Offsets,
+ llvm::StringRef Code) {
+ std::vector<tooling::Range> Ranges;
+ for (auto Offset : Offsets)
+ Ranges.push_back(tooling::Range(Offset, 0));
+ return cleanup(Code, Ranges);
+ }
};
TEST_F(CleanupTest, DeleteEmptyNamespaces) {
@@ -43,12 +56,7 @@ TEST_F(CleanupTest, DeleteEmptyNamespaces) {
std::string Expected = "\n\n\n\n\nnamespace C {\n"
"namespace D { int i; }\n \n"
"}";
- std::vector<tooling::Range> Ranges;
- Ranges.push_back(tooling::Range(28, 0));
- Ranges.push_back(tooling::Range(91, 6));
- Ranges.push_back(tooling::Range(132, 0));
- std::string Result = cleanup(Code, Ranges);
- EXPECT_EQ(Expected, Result);
+ EXPECT_EQ(Expected, cleanupAroundOffsets({28, 91, 132}, Code));
}
TEST_F(CleanupTest, NamespaceWithSyntaxError) {
@@ -64,8 +72,7 @@ TEST_F(CleanupTest, NamespaceWithSyntaxError) {
"namespace D int i; }\n \n"
"}";
std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size()));
- std::string Result = cleanup(Code, Ranges);
- EXPECT_EQ(Expected, Result);
+ EXPECT_EQ(Expected, cleanup(Code, Ranges));
}
TEST_F(CleanupTest, EmptyNamespaceNotAffected) {
@@ -76,9 +83,7 @@ TEST_F(CleanupTest, EmptyNamespaceNotAffected) {
std::string Expected = "namespace A {\n\n"
"namespace {\n\n}}";
// Set the changed range to be the second "\n".
- std::vector<tooling::Range> Ranges(1, tooling::Range(14, 0));
- std::string Result = cleanup(Code, Ranges);
- EXPECT_EQ(Expected, Result);
+ EXPECT_EQ(Expected, cleanupAroundOffsets({14}, Code));
}
TEST_F(CleanupTest, EmptyNamespaceWithCommentsNoBreakBeforeBrace) {
@@ -114,55 +119,94 @@ TEST_F(CleanupTest, EmptyNamespaceWithCommentsBreakBeforeBrace) {
EXPECT_EQ(Expected, Result);
}
+TEST_F(CleanupTest, EmptyNamespaceAroundConditionalCompilation) {
+ std::string Code = "#ifdef A\n"
+ "int a;\n"
+ "int b;\n"
+ "#else\n"
+ "#endif\n"
+ "namespace {}";
+ std::string Expected = "#ifdef A\n"
+ "int a;\n"
+ "int b;\n"
+ "#else\n"
+ "#endif\n";
+ std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size()));
+ FormatStyle Style = getLLVMStyle();
+ std::string Result = cleanup(Code, Ranges, Style);
+ EXPECT_EQ(Expected, Result);
+}
+
TEST_F(CleanupTest, CtorInitializationSimpleRedundantComma) {
std::string Code = "class A {\nA() : , {} };";
std::string Expected = "class A {\nA() {} };";
- std::vector<tooling::Range> Ranges;
- Ranges.push_back(tooling::Range(17, 0));
- Ranges.push_back(tooling::Range(19, 0));
- std::string Result = cleanup(Code, Ranges);
- EXPECT_EQ(Expected, Result);
+ EXPECT_EQ(Expected, cleanupAroundOffsets({17, 19}, Code));
Code = "class A {\nA() : x(1), {} };";
Expected = "class A {\nA() : x(1) {} };";
- Ranges.clear();
- Ranges.push_back(tooling::Range(23, 0));
- Result = cleanup(Code, Ranges);
- EXPECT_EQ(Expected, Result);
+ EXPECT_EQ(Expected, cleanupAroundOffsets({23}, Code));
Code = "class A {\nA() :,,,,{} };";
Expected = "class A {\nA() {} };";
- Ranges.clear();
- Ranges.push_back(tooling::Range(15, 0));
- Result = cleanup(Code, Ranges);
- EXPECT_EQ(Expected, Result);
+ EXPECT_EQ(Expected, cleanupAroundOffsets({15}, Code));
}
-TEST_F(CleanupTest, ListSimpleRedundantComma) {
+TEST_F(CleanupTest, CtorInitializationSimpleRedundantColon) {
+ std::string Code = "class A {\nA() : =default; };";
+ std::string Expected = "class A {\nA() =default; };";
+ EXPECT_EQ(Expected, cleanupAroundOffsets({15}, Code));
+
+ Code = "class A {\nA() : , =default; };";
+ Expected = "class A {\nA() =default; };";
+ EXPECT_EQ(Expected, cleanupAroundOffsets({15}, Code));
+}
+
+TEST_F(CleanupTest, ListRedundantComma) {
std::string Code = "void f() { std::vector<int> v = {1,2,,,3,{4,5}}; }";
std::string Expected = "void f() { std::vector<int> v = {1,2,3,{4,5}}; }";
- std::vector<tooling::Range> Ranges;
- Ranges.push_back(tooling::Range(40, 0));
- std::string Result = cleanup(Code, Ranges);
- EXPECT_EQ(Expected, Result);
+ EXPECT_EQ(Expected, cleanupAroundOffsets({40}, Code));
Code = "int main() { f(1,,2,3,,4);}";
Expected = "int main() { f(1,2,3,4);}";
- Ranges.clear();
- Ranges.push_back(tooling::Range(17, 0));
- Ranges.push_back(tooling::Range(22, 0));
- Result = cleanup(Code, Ranges);
- EXPECT_EQ(Expected, Result);
+ EXPECT_EQ(Expected, cleanupAroundOffsets({17, 22}, Code));
+}
+
+TEST_F(CleanupTest, TrailingCommaInParens) {
+ std::string Code = "int main() { f(,1,,2,3,f(1,2,),4,,);}";
+ std::string Expected = "int main() { f(1,2,3,f(1,2),4);}";
+ EXPECT_EQ(Expected, cleanupAroundOffsets({15, 18, 29, 33}, Code));
+}
+
+TEST_F(CleanupTest, TrailingCommaInBraces) {
+ // Trainling comma is allowed in brace list.
+ // If there was trailing comma in the original code, then trailing comma is
+ // preserved. In this example, element between the last two commas is deleted
+ // causing the second-last comma to be redundant.
+ std::string Code = "void f() { std::vector<int> v = {1,2,3,,}; }";
+ std::string Expected = "void f() { std::vector<int> v = {1,2,3,}; }";
+ EXPECT_EQ(Expected, cleanupAroundOffsets({39}, Code));
+
+ // If there was no trailing comma in the original code, then trainling comma
+ // introduced by replacements should be cleaned up. In this example, the
+ // element after the last comma is deleted causing the last comma to be
+ // redundant.
+ Code = "void f() { std::vector<int> v = {1,2,3,}; }";
+ // FIXME: redundant trailing comma should be removed.
+ Expected = "void f() { std::vector<int> v = {1,2,3,}; }";
+ EXPECT_EQ(Expected, cleanupAroundOffsets({39}, Code));
+
+ // Still no trailing comma in the original code, but two elements are deleted,
+ // which makes it seems like there was trailing comma.
+ Code = "void f() { std::vector<int> v = {1, 2, 3, , }; }";
+ // FIXME: redundant trailing comma should also be removed.
+ Expected = "void f() { std::vector<int> v = {1, 2, 3, }; }";
+ EXPECT_EQ(Expected, cleanupAroundOffsets({42, 44}, Code));
}
TEST_F(CleanupTest, CtorInitializationBracesInParens) {
std::string Code = "class A {\nA() : x({1}),, {} };";
std::string Expected = "class A {\nA() : x({1}) {} };";
- std::vector<tooling::Range> Ranges;
- Ranges.push_back(tooling::Range(24, 0));
- Ranges.push_back(tooling::Range(26, 0));
- std::string Result = cleanup(Code, Ranges);
- EXPECT_EQ(Expected, Result);
+ EXPECT_EQ(Expected, cleanupAroundOffsets({24, 26}, Code));
}
TEST_F(CleanupTest, RedundantCommaNotInAffectedRanges) {
@@ -184,44 +228,35 @@ TEST_F(CleanupTest, RedundantCommaNotInAffectedRanges) {
EXPECT_EQ(Expected, Result);
}
-// FIXME: delete comments too.
-TEST_F(CleanupTest, CtorInitializationCommentAroundCommas) {
- // Remove redundant commas around comment.
- std::string Code = "class A {\nA() : x({1}), /* comment */, {} };";
- std::string Expected = "class A {\nA() : x({1}) /* comment */ {} };";
- std::vector<tooling::Range> Ranges;
- Ranges.push_back(tooling::Range(25, 0));
- Ranges.push_back(tooling::Range(40, 0));
- std::string Result = cleanup(Code, Ranges);
- EXPECT_EQ(Expected, Result);
+TEST_F(CleanupTest, RemoveCommentsAroundDeleteCode) {
+ std::string Code =
+ "class A {\nA() : x({1}), /* comment */, /* comment */ {} };";
+ std::string Expected = "class A {\nA() : x({1}) {} };";
+ EXPECT_EQ(Expected, cleanupAroundOffsets({25, 40}, Code));
- // Remove trailing comma and ignore comment.
- Code = "class A {\nA() : x({1}), // comment\n{} };";
- Expected = "class A {\nA() : x({1}) // comment\n{} };";
- Ranges = std::vector<tooling::Range>(1, tooling::Range(25, 0));
- Result = cleanup(Code, Ranges);
- EXPECT_EQ(Expected, Result);
+ Code = "class A {\nA() : x({1}), // comment\n {} };";
+ Expected = "class A {\nA() : x({1})\n {} };";
+ EXPECT_EQ(Expected, cleanupAroundOffsets({25}, Code));
- // Remove trailing comma and ignore comment.
Code = "class A {\nA() : x({1}), // comment\n , y(1),{} };";
- Expected = "class A {\nA() : x({1}), // comment\n y(1){} };";
- Ranges = std::vector<tooling::Range>(1, tooling::Range(38, 0));
- Result = cleanup(Code, Ranges);
- EXPECT_EQ(Expected, Result);
+ Expected = "class A {\nA() : x({1}), y(1){} };";
+ EXPECT_EQ(Expected, cleanupAroundOffsets({38}, Code));
- // Remove trailing comma and ignore comment.
Code = "class A {\nA() : x({1}), \n/* comment */, y(1),{} };";
- Expected = "class A {\nA() : x({1}), \n/* comment */ y(1){} };";
- Ranges = std::vector<tooling::Range>(1, tooling::Range(40, 0));
- Result = cleanup(Code, Ranges);
- EXPECT_EQ(Expected, Result);
+ Expected = "class A {\nA() : x({1}), \n y(1){} };";
+ EXPECT_EQ(Expected, cleanupAroundOffsets({40}, Code));
- // Remove trailing comma and ignore comment.
Code = "class A {\nA() : , // comment\n y(1),{} };";
Expected = "class A {\nA() : // comment\n y(1){} };";
- Ranges = std::vector<tooling::Range>(1, tooling::Range(17, 0));
- Result = cleanup(Code, Ranges);
- EXPECT_EQ(Expected, Result);
+ EXPECT_EQ(Expected, cleanupAroundOffsets({17}, Code));
+
+ Code = "class A {\nA() // comment\n : ,,{} };";
+ Expected = "class A {\nA() // comment\n {} };";
+ EXPECT_EQ(Expected, cleanupAroundOffsets({30}, Code));
+
+ Code = "class A {\nA() // comment\n : ,,=default; };";
+ Expected = "class A {\nA() // comment\n =default; };";
+ EXPECT_EQ(Expected, cleanupAroundOffsets({30}, Code));
}
TEST_F(CleanupTest, CtorInitializerInNamespace) {
@@ -241,15 +276,19 @@ TEST_F(CleanupTest, CtorInitializerInNamespace) {
EXPECT_EQ(Expected, Result);
}
-class CleanUpReplacementsTest : public ::testing::Test {
+class CleanUpReplacementsTest : public ReplacementTest {
protected:
tooling::Replacement createReplacement(unsigned Offset, unsigned Length,
StringRef Text) {
return tooling::Replacement(FileName, Offset, Length, Text);
}
- tooling::Replacement createInsertion(StringRef HeaderName) {
- return createReplacement(UINT_MAX, 0, HeaderName);
+ tooling::Replacement createInsertion(StringRef IncludeDirective) {
+ return createReplacement(UINT_MAX, 0, IncludeDirective);
+ }
+
+ tooling::Replacement createDeletion(StringRef HeaderName) {
+ return createReplacement(UINT_MAX, 1, HeaderName);
}
inline std::string apply(StringRef Code,
@@ -304,9 +343,9 @@ TEST_F(CleanUpReplacementsTest, FixOnlyAffectedCodeAfterReplacements) {
"namespace D { int i; }\n\n"
"int x= 0;"
"}";
- tooling::Replacements Replaces = {
- createReplacement(getOffset(Code, 3, 3), 6, ""),
- createReplacement(getOffset(Code, 9, 34), 6, "")};
+ tooling::Replacements Replaces =
+ toReplacements({createReplacement(getOffset(Code, 3, 3), 6, ""),
+ createReplacement(getOffset(Code, 9, 34), 6, "")});
EXPECT_EQ(Expected, formatAndApply(Code, Replaces));
}
@@ -315,7 +354,8 @@ TEST_F(CleanUpReplacementsTest, NoExistingIncludeWithoutDefine) {
std::string Code = "int main() {}";
std::string Expected = "#include \"a.h\"\n"
"int main() {}";
- tooling::Replacements Replaces = {createInsertion("#include \"a.h\"")};
+ tooling::Replacements Replaces =
+ toReplacements({createInsertion("#include \"a.h\"")});
EXPECT_EQ(Expected, apply(Code, Replaces));
}
@@ -332,7 +372,8 @@ TEST_F(CleanUpReplacementsTest, NoExistingIncludeWithDefine) {
"#define MMM 123\n"
"#endif";
- tooling::Replacements Replaces = {createInsertion("#include \"b.h\"")};
+ tooling::Replacements Replaces =
+ toReplacements({createInsertion("#include \"b.h\"")});
EXPECT_EQ(Expected, apply(Code, Replaces));
}
@@ -357,7 +398,8 @@ TEST_F(CleanUpReplacementsTest, InsertBeforeCategoryWithLowerPriority) {
"#define MMM 123\n"
"#endif";
- tooling::Replacements Replaces = {createInsertion("#include \"a.h\"")};
+ tooling::Replacements Replaces =
+ toReplacements({createInsertion("#include \"a.h\"")});
EXPECT_EQ(Expected, apply(Code, Replaces));
}
@@ -369,7 +411,8 @@ TEST_F(CleanUpReplacementsTest, InsertAfterMainHeader) {
"#include <a>\n"
"\n"
"int main() {}";
- tooling::Replacements Replaces = {createInsertion("#include <a>")};
+ tooling::Replacements Replaces =
+ toReplacements({createInsertion("#include <a>")});
Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp);
EXPECT_EQ(Expected, apply(Code, Replaces));
}
@@ -382,7 +425,8 @@ TEST_F(CleanUpReplacementsTest, InsertBeforeSystemHeaderLLVM) {
"#include <memory>\n"
"\n"
"int main() {}";
- tooling::Replacements Replaces = {createInsertion("#include \"z.h\"")};
+ tooling::Replacements Replaces =
+ toReplacements({createInsertion("#include \"z.h\"")});
EXPECT_EQ(Expected, apply(Code, Replaces));
}
@@ -394,7 +438,8 @@ TEST_F(CleanUpReplacementsTest, InsertAfterSystemHeaderGoogle) {
"#include \"z.h\"\n"
"\n"
"int main() {}";
- tooling::Replacements Replaces = {createInsertion("#include \"z.h\"")};
+ tooling::Replacements Replaces =
+ toReplacements({createInsertion("#include \"z.h\"")});
Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp);
EXPECT_EQ(Expected, apply(Code, Replaces));
}
@@ -412,8 +457,9 @@ TEST_F(CleanUpReplacementsTest, InsertOneIncludeLLVMStyle) {
"#include \"clang/Format/Format.h\"\n"
"#include \"llvm/x/y.h\"\n"
"#include <memory>\n";
- tooling::Replacements Replaces = {createInsertion("#include \"d.h\""),
- createInsertion("#include \"llvm/x/y.h\"")};
+ tooling::Replacements Replaces =
+ toReplacements({createInsertion("#include \"d.h\""),
+ createInsertion("#include \"llvm/x/y.h\"")});
EXPECT_EQ(Expected, apply(Code, Replaces));
}
@@ -430,8 +476,9 @@ TEST_F(CleanUpReplacementsTest, InsertMultipleIncludesLLVMStyle) {
"#include \"clang/Format/Format.h\"\n"
"#include <memory>\n"
"#include <list>\n";
- tooling::Replacements Replaces = {createInsertion("#include <list>"),
- createInsertion("#include \"new/new.h\"")};
+ tooling::Replacements Replaces =
+ toReplacements({createInsertion("#include <list>"),
+ createInsertion("#include \"new/new.h\"")});
EXPECT_EQ(Expected, apply(Code, Replaces));
}
@@ -447,7 +494,8 @@ TEST_F(CleanUpReplacementsTest, InsertNewSystemIncludeGoogleStyle) {
"\n"
"#include \"y/a.h\"\n"
"#include \"z/b.h\"\n";
- tooling::Replacements Replaces = {createInsertion("#include <vector>")};
+ tooling::Replacements Replaces =
+ toReplacements({createInsertion("#include <vector>")});
Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp);
EXPECT_EQ(Expected, apply(Code, Replaces));
}
@@ -467,8 +515,9 @@ TEST_F(CleanUpReplacementsTest, InsertMultipleIncludesGoogleStyle) {
"#include \"y/a.h\"\n"
"#include \"z/b.h\"\n"
"#include \"x/x.h\"\n";
- tooling::Replacements Replaces = {createInsertion("#include <list>"),
- createInsertion("#include \"x/x.h\"")};
+ tooling::Replacements Replaces =
+ toReplacements({createInsertion("#include <list>"),
+ createInsertion("#include \"x/x.h\"")});
Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp);
EXPECT_EQ(Expected, apply(Code, Replaces));
}
@@ -482,12 +531,11 @@ TEST_F(CleanUpReplacementsTest, InsertMultipleNewHeadersAndSortLLVM) {
"#include <list>\n"
"#include <vector>\n"
"int x;";
- tooling::Replacements Replaces = {createInsertion("#include \"a.h\""),
- createInsertion("#include \"c.h\""),
- createInsertion("#include \"b.h\""),
- createInsertion("#include <vector>"),
- createInsertion("#include <list>"),
- createInsertion("#include \"fix.h\"")};
+ tooling::Replacements Replaces = toReplacements(
+ {createInsertion("#include \"a.h\""), createInsertion("#include \"c.h\""),
+ createInsertion("#include \"b.h\""),
+ createInsertion("#include <vector>"), createInsertion("#include <list>"),
+ createInsertion("#include \"fix.h\"")});
EXPECT_EQ(Expected, formatAndApply(Code, Replaces));
}
@@ -500,12 +548,11 @@ TEST_F(CleanUpReplacementsTest, InsertMultipleNewHeadersAndSortGoogle) {
"#include \"b.h\"\n"
"#include \"c.h\"\n"
"int x;";
- tooling::Replacements Replaces = {createInsertion("#include \"a.h\""),
- createInsertion("#include \"c.h\""),
- createInsertion("#include \"b.h\""),
- createInsertion("#include <vector>"),
- createInsertion("#include <list>"),
- createInsertion("#include \"fix.h\"")};
+ tooling::Replacements Replaces = toReplacements(
+ {createInsertion("#include \"a.h\""), createInsertion("#include \"c.h\""),
+ createInsertion("#include \"b.h\""),
+ createInsertion("#include <vector>"), createInsertion("#include <list>"),
+ createInsertion("#include \"fix.h\"")});
Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp);
EXPECT_EQ(Expected, formatAndApply(Code, Replaces));
}
@@ -526,13 +573,12 @@ TEST_F(CleanUpReplacementsTest, FormatCorrectLineWhenHeadersAreInserted) {
"int a;\n"
"int b;\n"
"int a;";
- tooling::Replacements Replaces = {
- createReplacement(getOffset(Code, 4, 8), 1, "b"),
- createInsertion("#include <vector>"),
- createInsertion("#include <list>"),
- createInsertion("#include \"clang/x/x.h\""),
- createInsertion("#include \"y.h\""),
- createInsertion("#include \"x.h\"")};
+ tooling::Replacements Replaces = toReplacements(
+ {createReplacement(getOffset(Code, 4, 8), 1, "b"),
+ createInsertion("#include <vector>"), createInsertion("#include <list>"),
+ createInsertion("#include \"clang/x/x.h\""),
+ createInsertion("#include \"y.h\""),
+ createInsertion("#include \"x.h\"")});
EXPECT_EQ(Expected, formatAndApply(Code, Replaces));
}
@@ -544,7 +590,8 @@ TEST_F(CleanUpReplacementsTest, NotConfusedByDefine) {
"void f() {}\n"
"#define A \\\n"
" int i;";
- tooling::Replacements Replaces = {createInsertion("#include <vector>")};
+ tooling::Replacements Replaces =
+ toReplacements({createInsertion("#include <vector>")});
EXPECT_EQ(Expected, formatAndApply(Code, Replaces));
}
@@ -556,7 +603,8 @@ TEST_F(CleanUpReplacementsTest, SkippedTopComment) {
"\n"
" // comment\n"
"#include <vector>\n";
- tooling::Replacements Replaces = {createInsertion("#include <vector>")};
+ tooling::Replacements Replaces =
+ toReplacements({createInsertion("#include <vector>")});
EXPECT_EQ(Expected, apply(Code, Replaces));
}
@@ -574,7 +622,8 @@ TEST_F(CleanUpReplacementsTest, SkippedMixedComments) {
"* comment\n"
"*/\n"
"#include <vector>\n";
- tooling::Replacements Replaces = {createInsertion("#include <vector>")};
+ tooling::Replacements Replaces =
+ toReplacements({createInsertion("#include <vector>")});
EXPECT_EQ(Expected, apply(Code, Replaces));
}
@@ -592,7 +641,8 @@ TEST_F(CleanUpReplacementsTest, MultipleBlockCommentsInOneLine) {
"\n\n"
"/* c1 */ /*c2 */\n"
"#include <vector>\n";
- tooling::Replacements Replaces = {createInsertion("#include <vector>")};
+ tooling::Replacements Replaces =
+ toReplacements({createInsertion("#include <vector>")});
EXPECT_EQ(Expected, apply(Code, Replaces));
}
@@ -614,7 +664,8 @@ TEST_F(CleanUpReplacementsTest, CodeAfterComments) {
"\n"
"#include <vector>\n"
"int x;\n";
- tooling::Replacements Replaces = {createInsertion("#include <vector>")};
+ tooling::Replacements Replaces =
+ toReplacements({createInsertion("#include <vector>")});
EXPECT_EQ(Expected, apply(Code, Replaces));
}
@@ -626,7 +677,8 @@ TEST_F(CleanUpReplacementsTest, FakeHeaderGuardIfDef) {
"#include <vector>\n"
"#ifdef X\n"
"#define X\n";
- tooling::Replacements Replaces = {createInsertion("#include <vector>")};
+ tooling::Replacements Replaces =
+ toReplacements({createInsertion("#include <vector>")});
EXPECT_EQ(Expected, apply(Code, Replaces));
}
@@ -642,7 +694,8 @@ TEST_F(CleanUpReplacementsTest, RealHeaderGuardAfterComments) {
"#include <vector>\n"
"int x;\n"
"#define Y 1\n";
- tooling::Replacements Replaces = {createInsertion("#include <vector>")};
+ tooling::Replacements Replaces =
+ toReplacements({createInsertion("#include <vector>")});
EXPECT_EQ(Expected, apply(Code, Replaces));
}
@@ -656,7 +709,21 @@ TEST_F(CleanUpReplacementsTest, IfNDefWithNoDefine) {
"#ifndef X\n"
"int x;\n"
"#define Y 1\n";
- tooling::Replacements Replaces = {createInsertion("#include <vector>")};
+ 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));
}
@@ -678,23 +745,34 @@ TEST_F(CleanUpReplacementsTest, HeaderGuardWithComment) {
"#include <vector>\n"
"int x;\n"
"#define Y 1\n";
- tooling::Replacements Replaces = {createInsertion("#include <vector>")};
+ 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 = {createInsertion("#include <vector>")};
+ tooling::Replacements Replaces =
+ toReplacements({createInsertion("#include <vector>")});
EXPECT_EQ(Expected, apply(Code, Replaces));
}
-// FIXME: although this case does not crash, the insertion is wrong. A '\n'
-// should be inserted between the two #includes.
TEST_F(CleanUpReplacementsTest, NoNewLineAtTheEndOfCode) {
std::string Code = "#include <map>";
- std::string Expected = "#include <map>#include <vector>\n";
- tooling::Replacements Replaces = {createInsertion("#include <vector>")};
+ 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));
}
@@ -703,8 +781,9 @@ TEST_F(CleanUpReplacementsTest, SkipExistingHeaders) {
"#include <vector>\n";
std::string Expected = "#include \"a.h\"\n"
"#include <vector>\n";
- tooling::Replacements Replaces = {createInsertion("#include <vector>"),
- createInsertion("#include \"a.h\"")};
+ tooling::Replacements Replaces =
+ toReplacements({createInsertion("#include <vector>"),
+ createInsertion("#include \"a.h\"")});
EXPECT_EQ(Expected, apply(Code, Replaces));
}
@@ -716,8 +795,171 @@ TEST_F(CleanUpReplacementsTest, AddIncludesWithDifferentForms) {
"#include \"vector\"\n"
"#include <vector>\n"
"#include <a.h>\n";
- tooling::Replacements Replaces = {createInsertion("#include \"vector\""),
- createInsertion("#include <a.h>")};
+ 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"
+ "#include \"xyz\"\n"
+ "int x;\n";
+ std::string Expected = "#include \"xyz\"\n"
+ "int x;\n";
+ tooling::Replacements Replaces =
+ toReplacements({createDeletion("abc.h"), createDeletion("xyz.h")});
+ 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"
+ "#include <vector>\n";
+ std::string Expected = "#include \"a.h\"\n"
+ "\n"
+ "#include <map>\n";
+ tooling::Replacements Replaces = toReplacements(
+ {createDeletion("<vector>"), createInsertion("#include <map>")});
+ 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));
}
diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp
index 8d46ba6efcfe..6f9df680eef5 100644
--- a/unittests/Format/FormatTest.cpp
+++ b/unittests/Format/FormatTest.cpp
@@ -9,7 +9,7 @@
#include "clang/Format/Format.h"
-#include "../Tooling/RewriterTestContext.h"
+#include "../Tooling/ReplacementTest.h"
#include "FormatTestUtils.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
@@ -19,6 +19,9 @@
#define DEBUG_TYPE "format-test"
+using clang::tooling::ReplacementTest;
+using clang::tooling::toReplacements;
+
namespace clang {
namespace format {
namespace {
@@ -273,6 +276,30 @@ TEST_F(FormatTest, RemovesEmptyLines) {
"int i;\n"
"\n"
"} // namespace"));
+
+ FormatStyle Style = getLLVMStyle();
+ Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
+ Style.MaxEmptyLinesToKeep = 2;
+ Style.BreakBeforeBraces = FormatStyle::BS_Custom;
+ Style.BraceWrapping.AfterClass = true;
+ Style.BraceWrapping.AfterFunction = true;
+ Style.KeepEmptyLinesAtTheStartOfBlocks = false;
+
+ EXPECT_EQ("class Foo\n"
+ "{\n"
+ " Foo() {}\n"
+ "\n"
+ " void funk() {}\n"
+ "};",
+ format("class Foo\n"
+ "{\n"
+ " Foo()\n"
+ " {\n"
+ " }\n"
+ "\n"
+ " void funk() {}\n"
+ "};",
+ Style));
}
TEST_F(FormatTest, RecognizesBinaryOperatorKeywords) {
@@ -1110,6 +1137,12 @@ TEST_F(FormatTest, KeepsParameterWithTrailingCommentsOnTheirOwnLine) {
format("SomeFunction(a, // comment\n"
" b,\n"
" c); // comment"));
+ EXPECT_EQ("aaaaaaaaaa(aaaa(aaaa,\n"
+ " aaaa), //\n"
+ " aaaa, bbbbb);",
+ format("aaaaaaaaaa(aaaa(aaaa,\n"
+ "aaaa), //\n"
+ "aaaa, bbbbb);"));
}
TEST_F(FormatTest, RemovesTrailingWhitespaceOfComments) {
@@ -1934,6 +1967,10 @@ TEST_F(FormatTest, UnderstandsAccessSpecifiers) {
verifyFormat("{\n"
" signals.set(); // This needs indentation.\n"
"}");
+ verifyFormat("void f() {\n"
+ "label:\n"
+ " signals.baz();\n"
+ "}");
}
TEST_F(FormatTest, SeparatesLogicalBlocks) {
@@ -2456,42 +2493,6 @@ TEST_F(FormatTest, FormatTryCatchBraceStyles) {
Style);
}
-TEST_F(FormatTest, FormatObjCTryCatch) {
- verifyFormat("@try {\n"
- " f();\n"
- "} @catch (NSException e) {\n"
- " @throw;\n"
- "} @finally {\n"
- " exit(42);\n"
- "}");
- verifyFormat("DEBUG({\n"
- " @try {\n"
- " } @finally {\n"
- " }\n"
- "});\n");
-}
-
-TEST_F(FormatTest, FormatObjCAutoreleasepool) {
- FormatStyle Style = getLLVMStyle();
- verifyFormat("@autoreleasepool {\n"
- " f();\n"
- "}\n"
- "@autoreleasepool {\n"
- " f();\n"
- "}\n",
- Style);
- Style.BreakBeforeBraces = FormatStyle::BS_Allman;
- verifyFormat("@autoreleasepool\n"
- "{\n"
- " f();\n"
- "}\n"
- "@autoreleasepool\n"
- "{\n"
- " f();\n"
- "}\n",
- Style);
-}
-
TEST_F(FormatTest, StaticInitializers) {
verifyFormat("static SomeClass SC = {1, 'a'};");
@@ -4540,12 +4541,13 @@ TEST_F(FormatTest, ParenthesesAndOperandAlignment) {
TEST_F(FormatTest, BreaksConditionalExpressions) {
verifyFormat(
- "aaaa(aaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaaaaaaaa\n"
- " ? aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
- " : aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);");
+ "aaaa(aaaaaaaaaaaaaaaaaaaa,\n"
+ " aaaaaaaaaaaaaaaaaaaaaaaaaa ? aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
+ " : aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);");
verifyFormat(
- "aaaa(aaaaaaaaaaaaaaaaaaaa, aaaaaaa ? aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
- " : aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);");
+ "aaaa(aaaaaaaaaaaaaaaaaaaa,\n"
+ " aaaaaaa ? aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
+ " : aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);");
verifyFormat(
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaa ? aaaa(aaaaaa)\n"
" : aaaaaaaaaaaaa);");
@@ -4595,11 +4597,12 @@ TEST_F(FormatTest, BreaksConditionalExpressions) {
" ? aaaa\n"
" : bbbb;");
verifyFormat("unsigned Indent =\n"
- " format(TheLine.First, IndentForLevel[TheLine.Level] >= 0\n"
- " ? IndentForLevel[TheLine.Level]\n"
- " : TheLine * 2,\n"
+ " format(TheLine.First,\n"
+ " IndentForLevel[TheLine.Level] >= 0\n"
+ " ? IndentForLevel[TheLine.Level]\n"
+ " : TheLine * 2,\n"
" TheLine.InPPDirective, PreviousEndOfLineColumn);",
- getLLVMStyleWithColumns(70));
+ getLLVMStyleWithColumns(60));
verifyFormat("bool aaaaaa = aaaaaaaaaaaaa //\n"
" ? aaaaaaaaaaaaaaa\n"
" : bbbbbbbbbbbbbbb //\n"
@@ -4674,13 +4677,14 @@ TEST_F(FormatTest, BreaksConditionalExpressionsAfterOperator) {
Style.BreakBeforeTernaryOperators = false;
Style.ColumnLimit = 70;
verifyFormat(
- "aaaa(aaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaaaaaaaa ?\n"
- " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa :\n"
- " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);",
+ "aaaa(aaaaaaaaaaaaaaaaaaaa,\n"
+ " aaaaaaaaaaaaaaaaaaaaaaaaaa ? aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa :\n"
+ " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);",
Style);
verifyFormat(
- "aaaa(aaaaaaaaaaaaaaaaaaaa, aaaaaaa ? aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa :\n"
- " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);",
+ "aaaa(aaaaaaaaaaaaaaaaaaaa,\n"
+ " aaaaaaa ? aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa :\n"
+ " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);",
Style);
verifyFormat(
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaa ? aaaa(aaaaaa) :\n"
@@ -4736,13 +4740,13 @@ TEST_F(FormatTest, BreaksConditionalExpressionsAfterOperator) {
" b :\n"
" c);",
Style);
- verifyFormat(
- "unsigned Indent =\n"
- " format(TheLine.First, IndentForLevel[TheLine.Level] >= 0 ?\n"
- " IndentForLevel[TheLine.Level] :\n"
- " TheLine * 2,\n"
- " TheLine.InPPDirective, PreviousEndOfLineColumn);",
- Style);
+ verifyFormat("unsigned Indent =\n"
+ " format(TheLine.First,\n"
+ " IndentForLevel[TheLine.Level] >= 0 ?\n"
+ " IndentForLevel[TheLine.Level] :\n"
+ " TheLine * 2,\n"
+ " TheLine.InPPDirective, PreviousEndOfLineColumn);",
+ Style);
verifyFormat("bool aaaaaa = aaaaaaaaaaaaa ? //\n"
" aaaaaaaaaaaaaaa :\n"
" bbbbbbbbbbbbbbb ? //\n"
@@ -4795,6 +4799,8 @@ TEST_F(FormatTest, DeclarationsOfMultipleVariables) {
verifyFormat("aaaaaaaaa *a = aaaaaaaaaaaaaaaaaaa, *b = bbbbbbbbbbbbbbbbbbb,\n"
" *b = bbbbbbbbbbbbbbbbbbb, *d = ddddddddddddddddddd;",
Style);
+ verifyFormat("vector<int*> a, b;", Style);
+ verifyFormat("for (int *p, *q; p != q; p = p->next) {\n}", Style);
}
TEST_F(FormatTest, ConditionalExpressionsInBrackets) {
@@ -5086,6 +5092,9 @@ TEST_F(FormatTest, AlignsPipes) {
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa << aaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
" << aaaaaaaaaaaaaaaaaaaaaaaaaaaa;");
verifyFormat(
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa()\n"
+ " << aaaaaaaaaaaaaaaaaaaaaaaaaaaa << aaaaaaaaaaaaaaaaaaaaaaaaaaaa;");
+ verifyFormat(
"llvm::outs() << \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"\n"
" \"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\"\n"
" << \"ccccccccccccccccccccccccccccccccccccccccccccccccc\";");
@@ -5103,29 +5112,6 @@ TEST_F(FormatTest, AlignsPipes) {
"llvm::errs() << aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n"
" aaaaaaaaaaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaaaaaaaaaa);");
- verifyFormat("return out << \"somepacket = {\\n\"\n"
- " << \" aaaaaa = \" << pkt.aaaaaa << \"\\n\"\n"
- " << \" bbbb = \" << pkt.bbbb << \"\\n\"\n"
- " << \" cccccc = \" << pkt.cccccc << \"\\n\"\n"
- " << \" ddd = [\" << pkt.ddd << \"]\\n\"\n"
- " << \"}\";");
-
- verifyFormat("llvm::outs() << \"aaaaaaaaaaaaaaaa: \" << aaaaaaaaaaaaaaaa\n"
- " << \"aaaaaaaaaaaaaaaa: \" << aaaaaaaaaaaaaaaa\n"
- " << \"aaaaaaaaaaaaaaaa: \" << aaaaaaaaaaaaaaaa;");
- verifyFormat(
- "llvm::outs() << \"aaaaaaaaaaaaaaaaa = \" << aaaaaaaaaaaaaaaaa\n"
- " << \"bbbbbbbbbbbbbbbbb = \" << bbbbbbbbbbbbbbbbb\n"
- " << \"ccccccccccccccccc = \" << ccccccccccccccccc\n"
- " << \"ddddddddddddddddd = \" << ddddddddddddddddd\n"
- " << \"eeeeeeeeeeeeeeeee = \" << eeeeeeeeeeeeeeeee;");
- verifyFormat("llvm::outs() << aaaaaaaaaaaaaaaaaaaaaaaa << \"=\"\n"
- " << bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb;");
- verifyFormat(
- "void f() {\n"
- " llvm::outs() << \"aaaaaaaaaaaaaaaaaaaa: \"\n"
- " << aaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaaa);\n"
- "}");
verifyFormat("llvm::outs() << \"aaaaaaaaaaaaaaaa: \"\n"
" << aaaaaaaa.aaaaaaaaaaaa(aaa)->aaaaaaaaaaaaaa();");
verifyFormat("llvm::errs() << aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n"
@@ -5136,22 +5122,6 @@ TEST_F(FormatTest, AlignsPipes) {
" bbb)\n"
" << a << b;");
- // Breaking before the first "<<" is generally not desirable.
- verifyFormat(
- "llvm::errs()\n"
- " << \"aaaaaaaaaaaaaaaaaaa: \" << aaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
- " << \"aaaaaaaaaaaaaaaaaaa: \" << aaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
- " << \"aaaaaaaaaaaaaaaaaaa: \" << aaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
- " << \"aaaaaaaaaaaaaaaaaaa: \" << aaaaaaaaaaaaaaaaaaaaaaaaaaaa;",
- getLLVMStyleWithColumns(70));
- verifyFormat("llvm::errs() << \"aaaaaaaaaaaaaaaaaaa: \"\n"
- " << aaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
- " << \"aaaaaaaaaaaaaaaaaaa: \"\n"
- " << aaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
- " << \"aaaaaaaaaaaaaaaaaaa: \"\n"
- " << aaaaaaaaaaaaaaaaaaaaaaaaaaaa;",
- getLLVMStyleWithColumns(70));
-
// But sometimes, breaking before the first "<<" is desirable.
verifyFormat("Diag(aaaaaaaaaaaaaaaaaaaa, aaaaaaaa)\n"
" << aaaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaa);");
@@ -5197,6 +5167,65 @@ TEST_F(FormatTest, AlignsPipes) {
verifyFormat("llvm::errs() << \"\\n\" << bbbbbbbbbbbbbbbbbbbbbb << \"\\n\";");
}
+TEST_F(FormatTest, KeepStringLabelValuePairsOnALine) {
+ verifyFormat("return out << \"somepacket = {\\n\"\n"
+ " << \" aaaaaa = \" << pkt.aaaaaa << \"\\n\"\n"
+ " << \" bbbb = \" << pkt.bbbb << \"\\n\"\n"
+ " << \" cccccc = \" << pkt.cccccc << \"\\n\"\n"
+ " << \" ddd = [\" << pkt.ddd << \"]\\n\"\n"
+ " << \"}\";");
+
+ verifyFormat("llvm::outs() << \"aaaaaaaaaaaaaaaa: \" << aaaaaaaaaaaaaaaa\n"
+ " << \"aaaaaaaaaaaaaaaa: \" << aaaaaaaaaaaaaaaa\n"
+ " << \"aaaaaaaaaaaaaaaa: \" << aaaaaaaaaaaaaaaa;");
+ verifyFormat(
+ "llvm::outs() << \"aaaaaaaaaaaaaaaaa = \" << aaaaaaaaaaaaaaaaa\n"
+ " << \"bbbbbbbbbbbbbbbbb = \" << bbbbbbbbbbbbbbbbb\n"
+ " << \"ccccccccccccccccc = \" << ccccccccccccccccc\n"
+ " << \"ddddddddddddddddd = \" << ddddddddddddddddd\n"
+ " << \"eeeeeeeeeeeeeeeee = \" << eeeeeeeeeeeeeeeee;");
+ verifyFormat("llvm::outs() << aaaaaaaaaaaaaaaaaaaaaaaa << \"=\"\n"
+ " << bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb;");
+ verifyFormat(
+ "void f() {\n"
+ " llvm::outs() << \"aaaaaaaaaaaaaaaaaaaa: \"\n"
+ " << aaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaaa);\n"
+ "}");
+
+ // Breaking before the first "<<" is generally not desirable.
+ verifyFormat(
+ "llvm::errs()\n"
+ " << \"aaaaaaaaaaaaaaaaaaa: \" << aaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
+ " << \"aaaaaaaaaaaaaaaaaaa: \" << aaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
+ " << \"aaaaaaaaaaaaaaaaaaa: \" << aaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
+ " << \"aaaaaaaaaaaaaaaaaaa: \" << aaaaaaaaaaaaaaaaaaaaaaaaaaaa;",
+ getLLVMStyleWithColumns(70));
+ verifyFormat("llvm::errs() << \"aaaaaaaaaaaaaaaaaaa: \"\n"
+ " << aaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
+ " << \"aaaaaaaaaaaaaaaaaaa: \"\n"
+ " << aaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
+ " << \"aaaaaaaaaaaaaaaaaaa: \"\n"
+ " << aaaaaaaaaaaaaaaaaaaaaaaaaaaa;",
+ getLLVMStyleWithColumns(70));
+
+ verifyFormat("string v = \"aaaaaaaaaaaaaaaa: \" + aaaaaaaaaaaaaaaa +\n"
+ " \"aaaaaaaaaaaaaaaa: \" + aaaaaaaaaaaaaaaa +\n"
+ " \"aaaaaaaaaaaaaaaa: \" + aaaaaaaaaaaaaaaa;");
+ verifyFormat("string v = StrCat(\"aaaaaaaaaaaaaaaa: \", aaaaaaaaaaaaaaaa,\n"
+ " \"aaaaaaaaaaaaaaaa: \", aaaaaaaaaaaaaaaa,\n"
+ " \"aaaaaaaaaaaaaaaa: \", aaaaaaaaaaaaaaaa);");
+ verifyFormat("string v = \"aaaaaaaaaaaaaaaa: \" +\n"
+ " (aaaa + aaaa);",
+ getLLVMStyleWithColumns(40));
+ verifyFormat("string v = StrCat(\"aaaaaaaaaaaa: \" +\n"
+ " (aaaaaaa + aaaaa));",
+ getLLVMStyleWithColumns(40));
+ verifyFormat(
+ "string v = StrCat(\"aaaaaaaaaaaaaaaaaaaaaaaaaaa: \",\n"
+ " SomeFunction(aaaaaaaaaaaa, aaaaaaaa.aaaaaaa),\n"
+ " bbbbbbbbbbbbbbbbbbbbbbb);");
+}
+
TEST_F(FormatTest, UnderstandsEquals) {
verifyFormat(
"aaaaaaaaaaaaaaaaa =\n"
@@ -5492,6 +5521,18 @@ TEST_F(FormatTest, UnderstandsTemplateParameters) {
verifyFormat("< < < < < < < < < < < < < < < < < < < < < < < < < < < < < <");
}
+TEST_F(FormatTest, BitshiftOperatorWidth) {
+ EXPECT_EQ("int a = 1 << 2; /* foo\n"
+ " bar */",
+ format("int a=1<<2; /* foo\n"
+ " bar */"));
+
+ EXPECT_EQ("int b = 256 >> 1; /* foo\n"
+ " bar */",
+ format("int b =256>>1 ; /* foo\n"
+ " bar */"));
+}
+
TEST_F(FormatTest, UnderstandsBinaryOperators) {
verifyFormat("COMPARE(a, ==, b);");
verifyFormat("auto s = sizeof...(Ts) - 1;");
@@ -5628,6 +5669,9 @@ TEST_F(FormatTest, UnderstandsFunctionRefQualification) {
verifyFormat("SomeType MemberFunction(const Deleted &) && final {}");
verifyFormat("SomeType MemberFunction(const Deleted &) && override {}");
verifyFormat("SomeType MemberFunction(const Deleted &) const &;");
+ verifyFormat("template <typename T>\n"
+ "void F(T) && = delete;",
+ getGoogleStyle());
FormatStyle AlignLeft = getLLVMStyle();
AlignLeft.PointerAlignment = FormatStyle::PAS_Left;
@@ -5780,7 +5824,7 @@ TEST_F(FormatTest, UnderstandsUsesOfStarAndAmp) {
FormatStyle Left = getLLVMStyle();
Left.PointerAlignment = FormatStyle::PAS_Left;
verifyFormat("x = *a(x) = *a(y);", Left);
- verifyFormat("for (;; * = b) {\n}", Left);
+ verifyFormat("for (;; *a = b) {\n}", Left);
verifyFormat("return *this += 1;", Left);
verifyIndependentOfContext("a = *(x + y);");
@@ -5845,11 +5889,12 @@ TEST_F(FormatTest, UnderstandsUsesOfStarAndAmp) {
verifyFormat("foo<b & 1>();");
verifyFormat("decltype(*::std::declval<const T &>()) void F();");
verifyFormat(
- "template <class T, class = typename std::enable_if<\n"
- " std::is_integral<T>::value &&\n"
- " (sizeof(T) > 1 || sizeof(T) < 8)>::type>\n"
+ "template <class T,\n"
+ " class = typename std::enable_if<\n"
+ " std::is_integral<T>::value &&\n"
+ " (sizeof(T) > 1 || sizeof(T) < 8)>::type>\n"
"void F();",
- getLLVMStyleWithColumns(76));
+ getLLVMStyleWithColumns(70));
verifyFormat(
"template <class T,\n"
" class = typename ::std::enable_if<\n"
@@ -5861,6 +5906,7 @@ TEST_F(FormatTest, UnderstandsUsesOfStarAndAmp) {
verifyIndependentOfContext("MACRO(auto *a);");
verifyIndependentOfContext("MACRO(const A *a);");
verifyIndependentOfContext("MACRO('0' <= c && c <= '9');");
+ verifyFormat("void f() { f(float{1}, a * a); }");
// FIXME: Is there a way to make this work?
// verifyIndependentOfContext("MACRO(A *a);");
@@ -6481,6 +6527,19 @@ TEST_F(FormatTest, LayoutCxx11BraceInitializers) {
"};");
verifyFormat("#define A {a, a},");
+ // Cases where distinguising braced lists and blocks is hard.
+ verifyFormat("vector<int> v{12} GUARDED_BY(mutex);");
+ verifyFormat("void f() {\n"
+ " return; // comment\n"
+ "}\n"
+ "SomeType t;");
+ verifyFormat("void f() {\n"
+ " if (a) {\n"
+ " f();\n"
+ " }\n"
+ "}\n"
+ "SomeType t;");
+
// In combination with BinPackArguments = false.
FormatStyle NoBinPacking = getLLVMStyle();
NoBinPacking.BinPackArguments = false;
@@ -6595,7 +6654,7 @@ TEST_F(FormatTest, LayoutCxx11BraceInitializers) {
"std::this_thread::sleep_for(\n"
" std::chrono::nanoseconds{ std::chrono::seconds{ 1 } } / 5);",
ExtraSpaces);
- verifyFormat("std::vector<MyValues> aaaaaaaaaaaaaaaaaaa{\n"
+ verifyFormat("std::vector<MyValues> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa{\n"
" aaaaaaa,\n"
" aaaaaaaaaa,\n"
" aaaaa,\n"
@@ -6733,6 +6792,26 @@ TEST_F(FormatTest, FormatsBracedListsInColumnLayout) {
" 1, 22, 333, 4444, 55555, 666666, 7777777,\n"
" 1, 22, 333, 4444, 55555, 666666, 7777777,\n"
" 1, 22, 333, 4444, 55555, 666666, 7777777});");
+
+ // Allow "single-column" layout even if that violates the column limit. There
+ // isn't going to be a better way.
+ verifyFormat("std::vector<int> a = {\n"
+ " aaaaaaaa,\n"
+ " aaaaaaaa,\n"
+ " aaaaaaaa,\n"
+ " aaaaaaaa,\n"
+ " aaaaaaaaaa,\n"
+ " aaaaaaaa,\n"
+ " aaaaaaaaaaaaaaaaaaaaaaaaaaa};",
+ getLLVMStyleWithColumns(30));
+ verifyFormat("vector<int> aaaa = {\n"
+ " aaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
+ " aaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
+ " aaaaaa.aaaaaaa,\n"
+ " aaaaaa.aaaaaaa,\n"
+ " aaaaaa.aaaaaaa,\n"
+ " aaaaaa.aaaaaaa,\n"
+ "};");
}
TEST_F(FormatTest, PullTrivialFunctionDefinitionsIntoSingleLine) {
@@ -7170,6 +7249,30 @@ TEST_F(FormatTest, SpecialTokensAtEndOfLine) {
verifyFormat("operator");
}
+TEST_F(FormatTest, SkipsDeeplyNestedLines) {
+ // This code would be painfully slow to format if we didn't skip it.
+ std::string Code("A(A(A(A(A(A(A(A(A(A(A(A(A(A(A(A(A(A(A(A(\n" // 20x
+ "A(A(A(A(A(A(A(A(A(A(A(A(A(A(A(A(A(A(A(A(\n"
+ "A(A(A(A(A(A(A(A(A(A(A(A(A(A(A(A(A(A(A(A(\n"
+ "A(A(A(A(A(A(A(A(A(A(A(A(A(A(A(A(A(A(A(A(\n"
+ "A(A(A(A(A(A(A(A(A(A(A(A(A(A(A(A(A(A(A(A(\n"
+ "A(1, 1)\n"
+ ", 1), 1), 1), 1), 1), 1), 1), 1), 1), 1)\n" // 10x
+ ", 1), 1), 1), 1), 1), 1), 1), 1), 1), 1)\n"
+ ", 1), 1), 1), 1), 1), 1), 1), 1), 1), 1)\n"
+ ", 1), 1), 1), 1), 1), 1), 1), 1), 1), 1)\n"
+ ", 1), 1), 1), 1), 1), 1), 1), 1), 1), 1)\n"
+ ", 1), 1), 1), 1), 1), 1), 1), 1), 1), 1)\n"
+ ", 1), 1), 1), 1), 1), 1), 1), 1), 1), 1)\n"
+ ", 1), 1), 1), 1), 1), 1), 1), 1), 1), 1)\n"
+ ", 1), 1), 1), 1), 1), 1), 1), 1), 1), 1)\n"
+ ", 1), 1), 1), 1), 1), 1), 1), 1), 1), 1);\n");
+ // Deeply nested part is untouched, rest is formatted.
+ EXPECT_EQ(std::string("int i;\n") + Code + "int j;\n",
+ format(std::string("int i;\n") + Code + "int j;\n",
+ getLLVMStyle(), IC_ExpectIncomplete));
+}
+
//===----------------------------------------------------------------------===//
// Objective-C tests.
//===----------------------------------------------------------------------===//
@@ -7240,684 +7343,6 @@ TEST_F(FormatTest, FormatForObjectiveCMethodDecls) {
verifyGoogleFormat("- foo:(int)foo;");
}
-TEST_F(FormatTest, FormatObjCInterface) {
- verifyFormat("@interface Foo : NSObject <NSSomeDelegate> {\n"
- "@public\n"
- " int field1;\n"
- "@protected\n"
- " int field2;\n"
- "@private\n"
- " int field3;\n"
- "@package\n"
- " int field4;\n"
- "}\n"
- "+ (id)init;\n"
- "@end");
-
- verifyGoogleFormat("@interface Foo : NSObject<NSSomeDelegate> {\n"
- " @public\n"
- " int field1;\n"
- " @protected\n"
- " int field2;\n"
- " @private\n"
- " int field3;\n"
- " @package\n"
- " int field4;\n"
- "}\n"
- "+ (id)init;\n"
- "@end");
-
- verifyFormat("@interface /* wait for it */ Foo\n"
- "+ (id)init;\n"
- "// Look, a comment!\n"
- "- (int)answerWith:(int)i;\n"
- "@end");
-
- verifyFormat("@interface Foo\n"
- "@end\n"
- "@interface Bar\n"
- "@end");
-
- verifyFormat("@interface Foo : Bar\n"
- "+ (id)init;\n"
- "@end");
-
- verifyFormat("@interface Foo : /**/ Bar /**/ <Baz, /**/ Quux>\n"
- "+ (id)init;\n"
- "@end");
-
- verifyGoogleFormat("@interface Foo : Bar<Baz, Quux>\n"
- "+ (id)init;\n"
- "@end");
-
- verifyFormat("@interface Foo (HackStuff)\n"
- "+ (id)init;\n"
- "@end");
-
- verifyFormat("@interface Foo ()\n"
- "+ (id)init;\n"
- "@end");
-
- verifyFormat("@interface Foo (HackStuff) <MyProtocol>\n"
- "+ (id)init;\n"
- "@end");
-
- verifyGoogleFormat("@interface Foo (HackStuff)<MyProtocol>\n"
- "+ (id)init;\n"
- "@end");
-
- verifyFormat("@interface Foo {\n"
- " int _i;\n"
- "}\n"
- "+ (id)init;\n"
- "@end");
-
- verifyFormat("@interface Foo : Bar {\n"
- " int _i;\n"
- "}\n"
- "+ (id)init;\n"
- "@end");
-
- verifyFormat("@interface Foo : Bar <Baz, Quux> {\n"
- " int _i;\n"
- "}\n"
- "+ (id)init;\n"
- "@end");
-
- verifyFormat("@interface Foo (HackStuff) {\n"
- " int _i;\n"
- "}\n"
- "+ (id)init;\n"
- "@end");
-
- verifyFormat("@interface Foo () {\n"
- " int _i;\n"
- "}\n"
- "+ (id)init;\n"
- "@end");
-
- verifyFormat("@interface Foo (HackStuff) <MyProtocol> {\n"
- " int _i;\n"
- "}\n"
- "+ (id)init;\n"
- "@end");
-
- FormatStyle OnePerLine = getGoogleStyle();
- OnePerLine.BinPackParameters = false;
- verifyFormat("@interface aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ()<\n"
- " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
- " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
- " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
- " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa> {\n"
- "}",
- OnePerLine);
-}
-
-TEST_F(FormatTest, FormatObjCImplementation) {
- verifyFormat("@implementation Foo : NSObject {\n"
- "@public\n"
- " int field1;\n"
- "@protected\n"
- " int field2;\n"
- "@private\n"
- " int field3;\n"
- "@package\n"
- " int field4;\n"
- "}\n"
- "+ (id)init {\n}\n"
- "@end");
-
- verifyGoogleFormat("@implementation Foo : NSObject {\n"
- " @public\n"
- " int field1;\n"
- " @protected\n"
- " int field2;\n"
- " @private\n"
- " int field3;\n"
- " @package\n"
- " int field4;\n"
- "}\n"
- "+ (id)init {\n}\n"
- "@end");
-
- verifyFormat("@implementation Foo\n"
- "+ (id)init {\n"
- " if (true)\n"
- " return nil;\n"
- "}\n"
- "// Look, a comment!\n"
- "- (int)answerWith:(int)i {\n"
- " return i;\n"
- "}\n"
- "+ (int)answerWith:(int)i {\n"
- " return i;\n"
- "}\n"
- "@end");
-
- verifyFormat("@implementation Foo\n"
- "@end\n"
- "@implementation Bar\n"
- "@end");
-
- EXPECT_EQ("@implementation Foo : Bar\n"
- "+ (id)init {\n}\n"
- "- (void)foo {\n}\n"
- "@end",
- format("@implementation Foo : Bar\n"
- "+(id)init{}\n"
- "-(void)foo{}\n"
- "@end"));
-
- verifyFormat("@implementation Foo {\n"
- " int _i;\n"
- "}\n"
- "+ (id)init {\n}\n"
- "@end");
-
- verifyFormat("@implementation Foo : Bar {\n"
- " int _i;\n"
- "}\n"
- "+ (id)init {\n}\n"
- "@end");
-
- verifyFormat("@implementation Foo (HackStuff)\n"
- "+ (id)init {\n}\n"
- "@end");
- verifyFormat("@implementation ObjcClass\n"
- "- (void)method;\n"
- "{}\n"
- "@end");
-}
-
-TEST_F(FormatTest, FormatObjCProtocol) {
- verifyFormat("@protocol Foo\n"
- "@property(weak) id delegate;\n"
- "- (NSUInteger)numberOfThings;\n"
- "@end");
-
- verifyFormat("@protocol MyProtocol <NSObject>\n"
- "- (NSUInteger)numberOfThings;\n"
- "@end");
-
- verifyGoogleFormat("@protocol MyProtocol<NSObject>\n"
- "- (NSUInteger)numberOfThings;\n"
- "@end");
-
- verifyFormat("@protocol Foo;\n"
- "@protocol Bar;\n");
-
- verifyFormat("@protocol Foo\n"
- "@end\n"
- "@protocol Bar\n"
- "@end");
-
- verifyFormat("@protocol myProtocol\n"
- "- (void)mandatoryWithInt:(int)i;\n"
- "@optional\n"
- "- (void)optional;\n"
- "@required\n"
- "- (void)required;\n"
- "@optional\n"
- "@property(assign) int madProp;\n"
- "@end\n");
-
- verifyFormat("@property(nonatomic, assign, readonly)\n"
- " int *looooooooooooooooooooooooooooongNumber;\n"
- "@property(nonatomic, assign, readonly)\n"
- " NSString *looooooooooooooooooooooooooooongName;");
-
- verifyFormat("@implementation PR18406\n"
- "}\n"
- "@end");
-}
-
-TEST_F(FormatTest, FormatObjCMethodDeclarations) {
- verifyFormat("- (void)doSomethingWith:(GTMFoo *)theFoo\n"
- " rect:(NSRect)theRect\n"
- " interval:(float)theInterval {\n"
- "}");
- verifyFormat("- (void)shortf:(GTMFoo *)theFoo\n"
- " longKeyword:(NSRect)theRect\n"
- " longerKeyword:(float)theInterval\n"
- " error:(NSError **)theError {\n"
- "}");
- verifyFormat("- (void)shortf:(GTMFoo *)theFoo\n"
- " longKeyword:(NSRect)theRect\n"
- " evenLongerKeyword:(float)theInterval\n"
- " error:(NSError **)theError {\n"
- "}");
- verifyFormat("- (instancetype)initXxxxxx:(id<x>)x\n"
- " y:(id<yyyyyyyyyyyyyyyyyyyy>)y\n"
- " NS_DESIGNATED_INITIALIZER;",
- getLLVMStyleWithColumns(60));
-
- // Continuation indent width should win over aligning colons if the function
- // name is long.
- FormatStyle continuationStyle = getGoogleStyle();
- continuationStyle.ColumnLimit = 40;
- continuationStyle.IndentWrappedFunctionNames = true;
- verifyFormat("- (void)shortf:(GTMFoo *)theFoo\n"
- " dontAlignNamef:(NSRect)theRect {\n"
- "}",
- continuationStyle);
-
- // Make sure we don't break aligning for short parameter names.
- verifyFormat("- (void)shortf:(GTMFoo *)theFoo\n"
- " aShortf:(NSRect)theRect {\n"
- "}",
- continuationStyle);
-}
-
-TEST_F(FormatTest, FormatObjCMethodExpr) {
- verifyFormat("[foo bar:baz];");
- verifyFormat("return [foo bar:baz];");
- verifyFormat("return (a)[foo bar:baz];");
- verifyFormat("f([foo bar:baz]);");
- verifyFormat("f(2, [foo bar:baz]);");
- verifyFormat("f(2, a ? b : c);");
- verifyFormat("[[self initWithInt:4] bar:[baz quux:arrrr]];");
-
- // Unary operators.
- verifyFormat("int a = +[foo bar:baz];");
- verifyFormat("int a = -[foo bar:baz];");
- verifyFormat("int a = ![foo bar:baz];");
- verifyFormat("int a = ~[foo bar:baz];");
- verifyFormat("int a = ++[foo bar:baz];");
- verifyFormat("int a = --[foo bar:baz];");
- verifyFormat("int a = sizeof [foo bar:baz];");
- verifyFormat("int a = alignof [foo bar:baz];", getGoogleStyle());
- verifyFormat("int a = &[foo bar:baz];");
- verifyFormat("int a = *[foo bar:baz];");
- // FIXME: Make casts work, without breaking f()[4].
- // verifyFormat("int a = (int)[foo bar:baz];");
- // verifyFormat("return (int)[foo bar:baz];");
- // verifyFormat("(void)[foo bar:baz];");
- verifyFormat("return (MyType *)[self.tableView cellForRowAtIndexPath:cell];");
-
- // Binary operators.
- verifyFormat("[foo bar:baz], [foo bar:baz];");
- verifyFormat("[foo bar:baz] = [foo bar:baz];");
- verifyFormat("[foo bar:baz] *= [foo bar:baz];");
- verifyFormat("[foo bar:baz] /= [foo bar:baz];");
- verifyFormat("[foo bar:baz] %= [foo bar:baz];");
- verifyFormat("[foo bar:baz] += [foo bar:baz];");
- verifyFormat("[foo bar:baz] -= [foo bar:baz];");
- verifyFormat("[foo bar:baz] <<= [foo bar:baz];");
- verifyFormat("[foo bar:baz] >>= [foo bar:baz];");
- verifyFormat("[foo bar:baz] &= [foo bar:baz];");
- verifyFormat("[foo bar:baz] ^= [foo bar:baz];");
- verifyFormat("[foo bar:baz] |= [foo bar:baz];");
- verifyFormat("[foo bar:baz] ? [foo bar:baz] : [foo bar:baz];");
- verifyFormat("[foo bar:baz] || [foo bar:baz];");
- verifyFormat("[foo bar:baz] && [foo bar:baz];");
- verifyFormat("[foo bar:baz] | [foo bar:baz];");
- verifyFormat("[foo bar:baz] ^ [foo bar:baz];");
- verifyFormat("[foo bar:baz] & [foo bar:baz];");
- verifyFormat("[foo bar:baz] == [foo bar:baz];");
- verifyFormat("[foo bar:baz] != [foo bar:baz];");
- verifyFormat("[foo bar:baz] >= [foo bar:baz];");
- verifyFormat("[foo bar:baz] <= [foo bar:baz];");
- verifyFormat("[foo bar:baz] > [foo bar:baz];");
- verifyFormat("[foo bar:baz] < [foo bar:baz];");
- verifyFormat("[foo bar:baz] >> [foo bar:baz];");
- verifyFormat("[foo bar:baz] << [foo bar:baz];");
- verifyFormat("[foo bar:baz] - [foo bar:baz];");
- verifyFormat("[foo bar:baz] + [foo bar:baz];");
- verifyFormat("[foo bar:baz] * [foo bar:baz];");
- verifyFormat("[foo bar:baz] / [foo bar:baz];");
- verifyFormat("[foo bar:baz] % [foo bar:baz];");
- // Whew!
-
- verifyFormat("return in[42];");
- verifyFormat("for (auto v : in[1]) {\n}");
- verifyFormat("for (int i = 0; i < in[a]; ++i) {\n}");
- verifyFormat("for (int i = 0; in[a] < i; ++i) {\n}");
- verifyFormat("for (int i = 0; i < n; ++i, ++in[a]) {\n}");
- verifyFormat("for (int i = 0; i < n; ++i, in[a]++) {\n}");
- verifyFormat("for (int i = 0; i < f(in[a]); ++i, in[a]++) {\n}");
- verifyFormat("for (id foo in [self getStuffFor:bla]) {\n"
- "}");
- verifyFormat("[self aaaaa:MACRO(a, b:, c:)];");
- verifyFormat("[self aaaaa:(1 + 2) bbbbb:3];");
- verifyFormat("[self aaaaa:(Type)a bbbbb:3];");
-
- verifyFormat("[self stuffWithInt:(4 + 2) float:4.5];");
- verifyFormat("[self stuffWithInt:a ? b : c float:4.5];");
- verifyFormat("[self stuffWithInt:a ? [self foo:bar] : c];");
- verifyFormat("[self stuffWithInt:a ? (e ? f : g) : c];");
- verifyFormat("[cond ? obj1 : obj2 methodWithParam:param]");
- verifyFormat("[button setAction:@selector(zoomOut:)];");
- verifyFormat("[color getRed:&r green:&g blue:&b alpha:&a];");
-
- verifyFormat("arr[[self indexForFoo:a]];");
- verifyFormat("throw [self errorFor:a];");
- verifyFormat("@throw [self errorFor:a];");
-
- verifyFormat("[(id)foo bar:(id)baz quux:(id)snorf];");
- verifyFormat("[(id)foo bar:(id) ? baz : quux];");
- verifyFormat("4 > 4 ? (id)a : (id)baz;");
-
- // This tests that the formatter doesn't break after "backing" but before ":",
- // which would be at 80 columns.
- verifyFormat(
- "void f() {\n"
- " if ((self = [super initWithContentRect:contentRect\n"
- " styleMask:styleMask ?: otherMask\n"
- " backing:NSBackingStoreBuffered\n"
- " defer:YES]))");
-
- verifyFormat(
- "[foo checkThatBreakingAfterColonWorksOk:\n"
- " [bar ifItDoes:reduceOverallLineLengthLikeInThisCase]];");
-
- verifyFormat("[myObj short:arg1 // Force line break\n"
- " longKeyword:arg2 != nil ? arg2 : @\"longKeyword\"\n"
- " evenLongerKeyword:arg3 ?: @\"evenLongerKeyword\"\n"
- " error:arg4];");
- verifyFormat(
- "void f() {\n"
- " popup_window_.reset([[RenderWidgetPopupWindow alloc]\n"
- " initWithContentRect:NSMakeRect(origin_global.x, origin_global.y,\n"
- " pos.width(), pos.height())\n"
- " styleMask:NSBorderlessWindowMask\n"
- " backing:NSBackingStoreBuffered\n"
- " defer:NO]);\n"
- "}");
- verifyFormat(
- "void f() {\n"
- " popup_wdow_.reset([[RenderWidgetPopupWindow alloc]\n"
- " iniithContentRect:NSMakRet(origin_global.x, origin_global.y,\n"
- " pos.width(), pos.height())\n"
- " syeMask:NSBorderlessWindowMask\n"
- " bking:NSBackingStoreBuffered\n"
- " der:NO]);\n"
- "}",
- getLLVMStyleWithColumns(70));
- verifyFormat(
- "void f() {\n"
- " popup_window_.reset([[RenderWidgetPopupWindow alloc]\n"
- " initWithContentRect:NSMakeRect(origin_global.x, origin_global.y,\n"
- " pos.width(), pos.height())\n"
- " styleMask:NSBorderlessWindowMask\n"
- " backing:NSBackingStoreBuffered\n"
- " defer:NO]);\n"
- "}",
- getChromiumStyle(FormatStyle::LK_Cpp));
- verifyFormat("[contentsContainer replaceSubview:[subviews objectAtIndex:0]\n"
- " with:contentsNativeView];");
-
- verifyFormat(
- "[pboard addTypes:[NSArray arrayWithObject:kBookmarkButtonDragType]\n"
- " owner:nillllll];");
-
- verifyFormat(
- "[pboard setData:[NSData dataWithBytes:&button length:sizeof(button)]\n"
- " forType:kBookmarkButtonDragType];");
-
- verifyFormat("[defaultCenter addObserver:self\n"
- " selector:@selector(willEnterFullscreen)\n"
- " name:kWillEnterFullscreenNotification\n"
- " object:nil];");
- verifyFormat("[image_rep drawInRect:drawRect\n"
- " fromRect:NSZeroRect\n"
- " operation:NSCompositeCopy\n"
- " fraction:1.0\n"
- " respectFlipped:NO\n"
- " hints:nil];");
- verifyFormat("[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
- " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa];");
- verifyFormat("[aaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaa)\n"
- " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa];");
- verifyFormat("[aaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaa[aaaaaaaaaaaaaaaaaaaaa]\n"
- " aaaaaaaaaaaaaaaaaaaaaa];");
- verifyFormat("[call aaaaaaaa.aaaaaa.aaaaaaaa.aaaaaaaa.aaaaaaaa.aaaaaaaa\n"
- " .aaaaaaaa];", // FIXME: Indentation seems off.
- getLLVMStyleWithColumns(60));
-
- verifyFormat(
- "scoped_nsobject<NSTextField> message(\n"
- " // The frame will be fixed up when |-setMessageText:| is called.\n"
- " [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 0, 0)]);");
- verifyFormat("[self aaaaaa:bbbbbbbbbbbbb\n"
- " aaaaaaaaaa:bbbbbbbbbbbbbbbbb\n"
- " aaaaa:bbbbbbbbbbb + bbbbbbbbbbbb\n"
- " aaaa:bbb];");
- verifyFormat("[self param:function( //\n"
- " parameter)]");
- verifyFormat(
- "[self aaaaaaaaaa:aaaaaaaaaaaaaaa | aaaaaaaaaaaaaaa | aaaaaaaaaaaaaaa |\n"
- " aaaaaaaaaaaaaaa | aaaaaaaaaaaaaaa | aaaaaaaaaaaaaaa |\n"
- " aaaaaaaaaaaaaaa | aaaaaaaaaaaaaaa];");
-
- // FIXME: This violates the column limit.
- verifyFormat(
- "[aaaaaaaaaaaaaaaaaaaaaaaaa\n"
- " aaaaaaaaaaaaaaaaa:aaaaaaaa\n"
- " aaa:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa];",
- getLLVMStyleWithColumns(60));
-
- // Variadic parameters.
- verifyFormat(
- "NSArray *myStrings = [NSArray stringarray:@\"a\", @\"b\", nil];");
- verifyFormat(
- "[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);");
-}
-
-TEST_F(FormatTest, ObjCAt) {
- verifyFormat("@autoreleasepool");
- verifyFormat("@catch");
- verifyFormat("@class");
- verifyFormat("@compatibility_alias");
- verifyFormat("@defs");
- verifyFormat("@dynamic");
- verifyFormat("@encode");
- verifyFormat("@end");
- verifyFormat("@finally");
- verifyFormat("@implementation");
- verifyFormat("@import");
- verifyFormat("@interface");
- verifyFormat("@optional");
- verifyFormat("@package");
- verifyFormat("@private");
- verifyFormat("@property");
- verifyFormat("@protected");
- verifyFormat("@protocol");
- verifyFormat("@public");
- verifyFormat("@required");
- verifyFormat("@selector");
- verifyFormat("@synchronized");
- verifyFormat("@synthesize");
- verifyFormat("@throw");
- verifyFormat("@try");
-
- EXPECT_EQ("@interface", format("@ interface"));
-
- // The precise formatting of this doesn't matter, nobody writes code like
- // this.
- verifyFormat("@ /*foo*/ interface");
-}
-
-TEST_F(FormatTest, ObjCSnippets) {
- verifyFormat("@autoreleasepool {\n"
- " foo();\n"
- "}");
- verifyFormat("@class Foo, Bar;");
- verifyFormat("@compatibility_alias AliasName ExistingClass;");
- verifyFormat("@dynamic textColor;");
- verifyFormat("char *buf1 = @encode(int *);");
- verifyFormat("char *buf1 = @encode(typeof(4 * 5));");
- verifyFormat("char *buf1 = @encode(int **);");
- verifyFormat("Protocol *proto = @protocol(p1);");
- verifyFormat("SEL s = @selector(foo:);");
- verifyFormat("@synchronized(self) {\n"
- " f();\n"
- "}");
-
- verifyFormat("@synthesize dropArrowPosition = dropArrowPosition_;");
- verifyGoogleFormat("@synthesize dropArrowPosition = dropArrowPosition_;");
-
- verifyFormat("@property(assign, nonatomic) CGFloat hoverAlpha;");
- verifyFormat("@property(assign, getter=isEditable) BOOL editable;");
- verifyGoogleFormat("@property(assign, getter=isEditable) BOOL editable;");
- verifyFormat("@property (assign, getter=isEditable) BOOL editable;",
- getMozillaStyle());
- verifyFormat("@property BOOL editable;", getMozillaStyle());
- verifyFormat("@property (assign, getter=isEditable) BOOL editable;",
- getWebKitStyle());
- verifyFormat("@property BOOL editable;", getWebKitStyle());
-
- verifyFormat("@import foo.bar;\n"
- "@import baz;");
-}
-
-TEST_F(FormatTest, ObjCForIn) {
- verifyFormat("- (void)test {\n"
- " for (NSString *n in arrayOfStrings) {\n"
- " foo(n);\n"
- " }\n"
- "}");
- verifyFormat("- (void)test {\n"
- " for (NSString *n in (__bridge NSArray *)arrayOfStrings) {\n"
- " foo(n);\n"
- " }\n"
- "}");
-}
-
-TEST_F(FormatTest, ObjCLiterals) {
- verifyFormat("@\"String\"");
- verifyFormat("@1");
- verifyFormat("@+4.8");
- verifyFormat("@-4");
- verifyFormat("@1LL");
- verifyFormat("@.5");
- verifyFormat("@'c'");
- verifyFormat("@true");
-
- verifyFormat("NSNumber *smallestInt = @(-INT_MAX - 1);");
- verifyFormat("NSNumber *piOverTwo = @(M_PI / 2);");
- verifyFormat("NSNumber *favoriteColor = @(Green);");
- verifyFormat("NSString *path = @(getenv(\"PATH\"));");
-
- verifyFormat("[dictionary setObject:@(1) forKey:@\"number\"];");
-}
-
-TEST_F(FormatTest, ObjCDictLiterals) {
- verifyFormat("@{");
- verifyFormat("@{}");
- verifyFormat("@{@\"one\" : @1}");
- verifyFormat("return @{@\"one\" : @1;");
- verifyFormat("@{@\"one\" : @1}");
-
- verifyFormat("@{@\"one\" : @{@2 : @1}}");
- verifyFormat("@{\n"
- " @\"one\" : @{@2 : @1},\n"
- "}");
-
- verifyFormat("@{1 > 2 ? @\"one\" : @\"two\" : 1 > 2 ? @1 : @2}");
- verifyIncompleteFormat("[self setDict:@{}");
- verifyIncompleteFormat("[self setDict:@{@1 : @2}");
- verifyFormat("NSLog(@\"%@\", @{@1 : @2, @2 : @3}[@1]);");
- verifyFormat(
- "NSDictionary *masses = @{@\"H\" : @1.0078, @\"He\" : @4.0026};");
- verifyFormat(
- "NSDictionary *settings = @{AVEncoderKey : @(AVAudioQualityMax)};");
-
- verifyFormat("NSDictionary *d = @{\n"
- " @\"nam\" : NSUserNam(),\n"
- " @\"dte\" : [NSDate date],\n"
- " @\"processInfo\" : [NSProcessInfo processInfo]\n"
- "};");
- verifyFormat(
- "@{\n"
- " NSFontAttributeNameeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee : "
- "regularFont,\n"
- "};");
- verifyGoogleFormat(
- "@{\n"
- " NSFontAttributeNameeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee : "
- "regularFont,\n"
- "};");
- verifyFormat(
- "@{\n"
- " NSFontAttributeNameeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee :\n"
- " reeeeeeeeeeeeeeeeeeeeeeeegularFont,\n"
- "};");
-
- // We should try to be robust in case someone forgets the "@".
- verifyFormat("NSDictionary *d = {\n"
- " @\"nam\" : NSUserNam(),\n"
- " @\"dte\" : [NSDate date],\n"
- " @\"processInfo\" : [NSProcessInfo processInfo]\n"
- "};");
- verifyFormat("NSMutableDictionary *dictionary =\n"
- " [NSMutableDictionary dictionaryWithDictionary:@{\n"
- " aaaaaaaaaaaaaaaaaaaaa : aaaaaaaaaaaaa,\n"
- " bbbbbbbbbbbbbbbbbb : bbbbb,\n"
- " cccccccccccccccc : ccccccccccccccc\n"
- " }];");
-
- // Ensure that casts before the key are kept on the same line as the key.
- verifyFormat(
- "NSDictionary *d = @{\n"
- " (aaaaaaaa id)aaaaaaaaa : (aaaaaaaa id)aaaaaaaaaaaaaaaaaaaaaaaa,\n"
- " (aaaaaaaa id)aaaaaaaaaaaaaa : (aaaaaaaa id)aaaaaaaaaaaaaa,\n"
- "};");
-}
-
-TEST_F(FormatTest, ObjCArrayLiterals) {
- verifyIncompleteFormat("@[");
- verifyFormat("@[]");
- verifyFormat(
- "NSArray *array = @[ @\" Hey \", NSApp, [NSNumber numberWithInt:42] ];");
- verifyFormat("return @[ @3, @[], @[ @4, @5 ] ];");
- verifyFormat("NSArray *array = @[ [foo description] ];");
-
- verifyFormat(
- "NSArray *some_variable = @[\n"
- " aaaa == bbbbbbbbbbb ? @\"aaaaaaaaaaaa\" : @\"aaaaaaaaaaaaaa\",\n"
- " @\"aaaaaaaaaaaaaaaaa\",\n"
- " @\"aaaaaaaaaaaaaaaaa\",\n"
- " @\"aaaaaaaaaaaaaaaaa\",\n"
- "];");
- verifyFormat(
- "NSArray *some_variable = @[\n"
- " aaaa == bbbbbbbbbbb ? @\"aaaaaaaaaaaa\" : @\"aaaaaaaaaaaaaa\",\n"
- " @\"aaaaaaaaaaaaaaaa\", @\"aaaaaaaaaaaaaaaa\", @\"aaaaaaaaaaaaaaaa\"\n"
- "];");
- verifyFormat("NSArray *some_variable = @[\n"
- " @\"aaaaaaaaaaaaaaaaa\",\n"
- " @\"aaaaaaaaaaaaaaaaa\",\n"
- " @\"aaaaaaaaaaaaaaaaa\",\n"
- " @\"aaaaaaaaaaaaaaaaa\",\n"
- "];");
- verifyFormat("NSArray *array = @[\n"
- " @\"a\",\n"
- " @\"a\",\n" // Trailing comma -> one per line.
- "];");
-
- // We should try to be robust in case someone forgets the "@".
- verifyFormat("NSArray *some_variable = [\n"
- " @\"aaaaaaaaaaaaaaaaa\",\n"
- " @\"aaaaaaaaaaaaaaaaa\",\n"
- " @\"aaaaaaaaaaaaaaaaa\",\n"
- " @\"aaaaaaaaaaaaaaaaa\",\n"
- "];");
- verifyFormat(
- "- (NSAttributedString *)attributedStringForSegment:(NSUInteger)segment\n"
- " index:(NSUInteger)index\n"
- " nonDigitAttributes:\n"
- " (NSDictionary *)noDigitAttributes;");
- verifyFormat("[someFunction someLooooooooooooongParameter:@[\n"
- " NSBundle.mainBundle.infoDictionary[@\"a\"]\n"
- "]];");
-}
TEST_F(FormatTest, BreaksStringLiterals) {
EXPECT_EQ("\"some text \"\n"
@@ -10184,6 +9609,7 @@ TEST_F(FormatTest, ParsesConfigurationBools) {
CHECK_PARSE_BOOL(SpacesInContainerLiterals);
CHECK_PARSE_BOOL(SpacesInCStyleCastParentheses);
CHECK_PARSE_BOOL(SpaceAfterCStyleCast);
+ CHECK_PARSE_BOOL(SpaceAfterTemplateKeyword);
CHECK_PARSE_BOOL(SpaceBeforeAssignmentOperators);
CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterClass);
@@ -10920,6 +10346,7 @@ TEST_F(FormatTest, FormatsLambdas) {
verifyFormat("int c = [&a, &a, a] { [=, a, b, &c] { return b++; }(); }();\n");
verifyFormat("auto c = {[&a, &a, a] { [=, a, b, &c] { return b++; }(); }}\n");
verifyFormat("auto c = {[&a, &a, a] { [=, a, b, &c] {}(); }}\n");
+ verifyFormat("int x = f(*+[] {});");
verifyFormat("void f() {\n"
" other(x.begin(), x.end(), [&](int, int) { return 1; });\n"
"}\n");
@@ -11147,6 +10574,8 @@ TEST_F(FormatTest, FormatsBlocks) {
" }\n"
"});");
verifyFormat("Block b = ^int *(A *a, B *b) {}");
+ verifyFormat("BOOL (^aaa)(void) = ^BOOL {\n"
+ "};");
FormatStyle FourIndent = getLLVMStyle();
FourIndent.ObjCBlockIndentWidth = 4;
@@ -11322,6 +10751,12 @@ TEST_F(FormatTest, SpacesInAngles) {
verifyFormat("A<A<int>>();", Spaces);
}
+TEST_F(FormatTest, SpaceAfterTemplateKeyword) {
+ FormatStyle Style = getLLVMStyle();
+ Style.SpaceAfterTemplateKeyword = false;
+ verifyFormat("template<int> void foo();", Style);
+}
+
TEST_F(FormatTest, TripleAngleBrackets) {
verifyFormat("f<<<1, 1>>>();");
verifyFormat("f<<<1, 1, 1, s>>>();");
@@ -11332,6 +10767,8 @@ TEST_F(FormatTest, TripleAngleBrackets) {
EXPECT_EQ("f<param><<<1, 1>>>();", format("f< param > <<< 1, 1 >>> ();"));
verifyFormat("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaa<<<\n 1, 1>>>();");
+ verifyFormat("aaaaaaaaaaaaaaa<aaaaaaaaa, aaaaaaaaaa, aaaaaaaaaaaaaa>\n"
+ " <<<aaaaaaaaa, aaaaaaaaaa, aaaaaaaaaaaaaaaaaa>>>();");
}
TEST_F(FormatTest, MergeLessLessAtEnd) {
@@ -11483,9 +10920,25 @@ TEST_F(FormatTest, FormatsTableGenCode) {
verifyFormat("include \"a.td\"\ninclude \"b.td\"", Style);
}
-// Since this test case uses UNIX-style file path. We disable it for MS
-// compiler.
-#if !defined(_MSC_VER) && !defined(__MINGW32__)
+TEST_F(FormatTest, ArrayOfTemplates) {
+ EXPECT_EQ("auto a = new unique_ptr<int>[10];",
+ format("auto a = new unique_ptr<int > [ 10];"));
+
+ FormatStyle Spaces = getLLVMStyle();
+ Spaces.SpacesInSquareBrackets = true;
+ EXPECT_EQ("auto a = new unique_ptr<int>[ 10 ];",
+ format("auto a = new unique_ptr<int > [10];", Spaces));
+}
+
+TEST_F(FormatTest, ArrayAsTemplateType) {
+ EXPECT_EQ("auto a = unique_ptr<Foo<Bar>[10]>;",
+ format("auto a = unique_ptr < Foo < Bar>[ 10]> ;"));
+
+ FormatStyle Spaces = getLLVMStyle();
+ Spaces.SpacesInSquareBrackets = true;
+ EXPECT_EQ("auto a = unique_ptr<Foo<Bar>[ 10 ]>;",
+ format("auto a = unique_ptr < Foo < Bar>[10]> ;", Spaces));
+}
TEST(FormatStyle, GetStyleOfFile) {
vfs::InMemoryFileSystem FS;
@@ -11495,13 +10948,13 @@ TEST(FormatStyle, GetStyleOfFile) {
llvm::MemoryBuffer::getMemBuffer("BasedOnStyle: LLVM")));
ASSERT_TRUE(
FS.addFile("/a/test.cpp", 0, llvm::MemoryBuffer::getMemBuffer("int i;")));
- auto Style1 = getStyle("file", "/a/.clang-format", "Google", &FS);
+ auto Style1 = getStyle("file", "/a/.clang-format", "Google", "", &FS);
ASSERT_EQ(Style1, getLLVMStyle());
// Test 2: fallback to default.
ASSERT_TRUE(
FS.addFile("/b/test.cpp", 0, llvm::MemoryBuffer::getMemBuffer("int i;")));
- auto Style2 = getStyle("file", "/b/test.cpp", "Mozilla", &FS);
+ auto Style2 = getStyle("file", "/b/test.cpp", "Mozilla", "", &FS);
ASSERT_EQ(Style2, getMozillaStyle());
// Test 3: format file in parent directory.
@@ -11510,23 +10963,10 @@ TEST(FormatStyle, GetStyleOfFile) {
llvm::MemoryBuffer::getMemBuffer("BasedOnStyle: Google")));
ASSERT_TRUE(FS.addFile("/c/sub/sub/sub/test.cpp", 0,
llvm::MemoryBuffer::getMemBuffer("int i;")));
- auto Style3 = getStyle("file", "/c/sub/sub/sub/test.cpp", "LLVM", &FS);
+ auto Style3 = getStyle("file", "/c/sub/sub/sub/test.cpp", "LLVM", "", &FS);
ASSERT_EQ(Style3, getGoogleStyle());
}
-#endif // _MSC_VER
-
-class ReplacementTest : public ::testing::Test {
-protected:
- tooling::Replacement createReplacement(SourceLocation Start, unsigned Length,
- llvm::StringRef ReplacementText) {
- return tooling::Replacement(Context.Sources, Start, Length,
- ReplacementText);
- }
-
- RewriterTestContext Context;
-};
-
TEST_F(ReplacementTest, FormatCodeAfterReplacements) {
// Column limit is 20.
std::string Code = "Type *a =\n"
@@ -11541,15 +10981,15 @@ TEST_F(ReplacementTest, FormatCodeAfterReplacements) {
" mm);\n"
"int bad = format ;";
FileID ID = Context.createInMemoryFile("format.cpp", Code);
- tooling::Replacements Replaces;
- Replaces.insert(tooling::Replacement(
- Context.Sources, Context.getLocation(ID, 1, 1), 6, "auto "));
- Replaces.insert(tooling::Replacement(
- Context.Sources, Context.getLocation(ID, 3, 10), 1, "nullptr"));
- Replaces.insert(tooling::Replacement(
- Context.Sources, Context.getLocation(ID, 4, 3), 1, "nullptr"));
- Replaces.insert(tooling::Replacement(
- Context.Sources, Context.getLocation(ID, 4, 13), 1, "nullptr"));
+ tooling::Replacements Replaces = toReplacements(
+ {tooling::Replacement(Context.Sources, Context.getLocation(ID, 1, 1), 6,
+ "auto "),
+ tooling::Replacement(Context.Sources, Context.getLocation(ID, 3, 10), 1,
+ "nullptr"),
+ tooling::Replacement(Context.Sources, Context.getLocation(ID, 4, 3), 1,
+ "nullptr"),
+ tooling::Replacement(Context.Sources, Context.getLocation(ID, 4, 13), 1,
+ "nullptr")});
format::FormatStyle Style = format::getLLVMStyle();
Style.ColumnLimit = 20; // Set column limit to 20 to increase readibility.
@@ -11576,9 +11016,9 @@ TEST_F(ReplacementTest, SortIncludesAfterReplacement) {
" return 0;\n"
"}";
FileID ID = Context.createInMemoryFile("fix.cpp", Code);
- tooling::Replacements Replaces;
- Replaces.insert(tooling::Replacement(
- Context.Sources, Context.getLocation(ID, 1, 1), 0, "#include \"b.h\"\n"));
+ tooling::Replacements Replaces = toReplacements(
+ {tooling::Replacement(Context.Sources, Context.getLocation(ID, 1, 1), 0,
+ "#include \"b.h\"\n")});
format::FormatStyle Style = format::getLLVMStyle();
Style.SortIncludes = true;
@@ -11590,6 +11030,17 @@ TEST_F(ReplacementTest, SortIncludesAfterReplacement) {
EXPECT_EQ(Expected, *Result);
}
+TEST_F(FormatTest, AllignTrailingComments) {
+ EXPECT_EQ("#define MACRO(V) \\\n"
+ " V(Rt2) /* one more char */ \\\n"
+ " V(Rs) /* than here */ \\\n"
+ "/* comment 3 */\n",
+ format("#define MACRO(V)\\\n"
+ "V(Rt2) /* one more char */ \\\n"
+ "V(Rs) /* than here */ \\\n"
+ "/* comment 3 */ \\\n",
+ getLLVMStyleWithColumns(40)));
+}
} // end namespace
} // end namespace format
} // end namespace clang
diff --git a/unittests/Format/FormatTestJS.cpp b/unittests/Format/FormatTestJS.cpp
index 2819383a3585..6f494db71d15 100644
--- a/unittests/Format/FormatTestJS.cpp
+++ b/unittests/Format/FormatTestJS.cpp
@@ -135,6 +135,8 @@ TEST_F(FormatTestJS, ReservedWords) {
verifyFormat("x.in() = 1;");
verifyFormat("x.let() = 1;");
verifyFormat("x.var() = 1;");
+ verifyFormat("x.for() = 1;");
+ verifyFormat("x.as() = 1;");
verifyFormat("x = {\n"
" a: 12,\n"
" interface: 1,\n"
@@ -147,6 +149,21 @@ TEST_F(FormatTestJS, ReservedWords) {
verifyFormat("x = interface instanceof y;");
}
+TEST_F(FormatTestJS, ReservedWordsMethods) {
+ verifyFormat(
+ "class X {\n"
+ " delete() {\n"
+ " x();\n"
+ " }\n"
+ " interface() {\n"
+ " x();\n"
+ " }\n"
+ " let() {\n"
+ " x();\n"
+ " }\n"
+ "}\n");
+}
+
TEST_F(FormatTestJS, CppKeywords) {
// Make sure we don't mess stuff up because of C++ keywords.
verifyFormat("return operator && (aa);");
@@ -161,7 +178,11 @@ TEST_F(FormatTestJS, ES6DestructuringAssignment) {
}
TEST_F(FormatTestJS, ContainerLiterals) {
- verifyFormat("var x = {y: function(a) { return a; }};");
+ verifyFormat("var x = {\n"
+ " y: function(a) {\n"
+ " return a;\n"
+ " }\n"
+ "};");
verifyFormat("return {\n"
" link: function() {\n"
" f(); //\n"
@@ -212,7 +233,11 @@ TEST_F(FormatTestJS, ContainerLiterals) {
verifyFormat("x = foo && {a: 123};");
// Arrow functions in object literals.
- verifyFormat("var x = {y: (a) => { return a; }};");
+ verifyFormat("var x = {\n"
+ " y: (a) => {\n"
+ " return a;\n"
+ " }\n"
+ "};");
verifyFormat("var x = {y: (a) => a};");
// Computed keys.
@@ -234,6 +259,13 @@ TEST_F(FormatTestJS, ContainerLiterals) {
" b: b,\n"
" 'c': c,\n"
"};");
+
+ // Dict literals can skip the label names.
+ verifyFormat("var x = {\n"
+ " aaa,\n"
+ " aaa,\n"
+ " aaa,\n"
+ "};");
}
TEST_F(FormatTestJS, MethodsInObjectLiterals) {
@@ -324,13 +356,48 @@ TEST_F(FormatTestJS, FormatsNamespaces) {
"}\n");
}
+TEST_F(FormatTestJS, NamespacesMayNotWrap) {
+ verifyFormat("declare namespace foobarbaz {\n"
+ "}\n", getGoogleJSStyleWithColumns(18));
+ verifyFormat("declare module foobarbaz {\n"
+ "}\n", getGoogleJSStyleWithColumns(15));
+ verifyFormat("namespace foobarbaz {\n"
+ "}\n", getGoogleJSStyleWithColumns(10));
+ verifyFormat("module foobarbaz {\n"
+ "}\n", getGoogleJSStyleWithColumns(7));
+}
+
+TEST_F(FormatTestJS, AmbientDeclarations) {
+ FormatStyle NineCols = getGoogleJSStyleWithColumns(9);
+ verifyFormat(
+ "declare class\n"
+ " X {}",
+ NineCols);
+ verifyFormat(
+ "declare function\n"
+ "x();", // TODO(martinprobst): should ideally be indented.
+ NineCols);
+ verifyFormat(
+ "declare enum X {\n"
+ "}",
+ NineCols);
+ verifyFormat(
+ "declare let\n"
+ " x: number;",
+ NineCols);
+}
+
TEST_F(FormatTestJS, FormatsFreestandingFunctions) {
verifyFormat("function outer1(a, b) {\n"
- " function inner1(a, b) { return a; }\n"
+ " function inner1(a, b) {\n"
+ " return a;\n"
+ " }\n"
" inner1(a, b);\n"
"}\n"
"function outer2(a, b) {\n"
- " function inner2(a, b) { return a; }\n"
+ " function inner2(a, b) {\n"
+ " return a;\n"
+ " }\n"
" inner2(a, b);\n"
"}");
verifyFormat("function f() {}");
@@ -341,6 +408,8 @@ TEST_F(FormatTestJS, GeneratorFunctions) {
" let x = 1;\n"
" yield x;\n"
" yield* something();\n"
+ " yield [1, 2];\n"
+ " yield {a: 1};\n"
"}");
verifyFormat("function*\n"
" f() {\n"
@@ -350,8 +419,15 @@ TEST_F(FormatTestJS, GeneratorFunctions) {
" yield 1;\n"
"}\n");
verifyFormat("class X {\n"
- " * generatorMethod() { yield x; }\n"
+ " * generatorMethod() {\n"
+ " yield x;\n"
+ " }\n"
"}");
+ verifyFormat("var x = {\n"
+ " a: function*() {\n"
+ " //\n"
+ " }\n"
+ "}\n");
}
TEST_F(FormatTestJS, AsyncFunctions) {
@@ -366,7 +442,9 @@ TEST_F(FormatTestJS, AsyncFunctions) {
" return fetch(x);\n"
"}");
verifyFormat("class X {\n"
- " async asyncMethod() { return fetch(1); }\n"
+ " async asyncMethod() {\n"
+ " return fetch(1);\n"
+ " }\n"
"}");
verifyFormat("function initialize() {\n"
" // Comment.\n"
@@ -423,8 +501,10 @@ TEST_F(FormatTestJS, ColumnLayoutForArrayLiterals) {
}
TEST_F(FormatTestJS, FunctionLiterals) {
+ FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript);
+ Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
verifyFormat("doFoo(function() {});");
- verifyFormat("doFoo(function() { return 1; });");
+ verifyFormat("doFoo(function() { return 1; });", Style);
verifyFormat("var func = function() {\n"
" return 1;\n"
"};");
@@ -438,7 +518,8 @@ TEST_F(FormatTestJS, FunctionLiterals) {
" getAttribute: function(key) { return this[key]; },\n"
" style: {direction: ''}\n"
" }\n"
- "};");
+ "};",
+ Style);
verifyFormat("abc = xyz ? function() {\n"
" return 1;\n"
"} : function() {\n"
@@ -476,13 +557,6 @@ TEST_F(FormatTestJS, FunctionLiterals) {
" // code\n"
" });");
- verifyFormat("f({a: function() { return 1; }});",
- getGoogleJSStyleWithColumns(33));
- verifyFormat("f({\n"
- " a: function() { return 1; }\n"
- "});",
- getGoogleJSStyleWithColumns(32));
-
verifyFormat("return {\n"
" a: function SomeFunction() {\n"
" // ...\n"
@@ -510,6 +584,15 @@ TEST_F(FormatTestJS, FunctionLiterals) {
" .doSomethingElse(\n"
" // break\n"
" );");
+
+ Style.ColumnLimit = 33;
+ verifyFormat("f({a: function() { return 1; }});", Style);
+ Style.ColumnLimit = 32;
+ verifyFormat("f({\n"
+ " a: function() { return 1; }\n"
+ "});",
+ Style);
+
}
TEST_F(FormatTestJS, InliningFunctionLiterals) {
@@ -570,6 +653,8 @@ TEST_F(FormatTestJS, InliningFunctionLiterals) {
}
TEST_F(FormatTestJS, MultipleFunctionLiterals) {
+ FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript);
+ Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
verifyFormat("promise.then(\n"
" function success() {\n"
" doFoo();\n"
@@ -606,7 +691,8 @@ TEST_F(FormatTestJS, MultipleFunctionLiterals) {
" .thenCatch(function(error) {\n"
" body();\n"
" body();\n"
- " });");
+ " });",
+ Style);
verifyFormat("getSomeLongPromise()\n"
" .then(function(value) {\n"
" body();\n"
@@ -619,7 +705,8 @@ TEST_F(FormatTestJS, MultipleFunctionLiterals) {
verifyFormat("getSomeLongPromise()\n"
" .then(function(value) { body(); })\n"
- " .thenCatch(function(error) { body(); });");
+ " .thenCatch(function(error) { body(); });",
+ Style);
verifyFormat("return [aaaaaaaaaaaaaaaaaaaaaa]\n"
" .aaaaaaa(function() {\n"
@@ -633,7 +720,9 @@ TEST_F(FormatTestJS, ArrowFunctions) {
" return a;\n"
"};");
verifyFormat("var x = (a) => {\n"
- " function y() { return 42; }\n"
+ " function y() {\n"
+ " return 42;\n"
+ " }\n"
" return a;\n"
"};");
verifyFormat("var x = (a: type): {some: type} => {\n"
@@ -686,7 +775,9 @@ TEST_F(FormatTestJS, WrapRespectsAutomaticSemicolonInsertion) {
// would change due to automatic semicolon insertion.
// See http://www.ecma-international.org/ecma-262/5.1/#sec-7.9.1.
verifyFormat("return aaaaa;", getGoogleJSStyleWithColumns(10));
+ verifyFormat("return /* hello! */ aaaaa;", getGoogleJSStyleWithColumns(10));
verifyFormat("continue aaaaa;", getGoogleJSStyleWithColumns(10));
+ verifyFormat("continue /* hello! */ aaaaa;", getGoogleJSStyleWithColumns(10));
verifyFormat("break aaaaa;", getGoogleJSStyleWithColumns(10));
verifyFormat("throw aaaaa;", getGoogleJSStyleWithColumns(10));
verifyFormat("aaaaaaaaa++;", getGoogleJSStyleWithColumns(10));
@@ -745,6 +836,18 @@ TEST_F(FormatTestJS, AutomaticSemicolonInsertionHeuristic) {
"String");
verifyFormat("function f(@Foo bar) {}", "function f(@Foo\n"
" bar) {}");
+ verifyFormat("a = true\n"
+ "return 1",
+ "a = true\n"
+ " return 1");
+ verifyFormat("a = 's'\n"
+ "return 1",
+ "a = 's'\n"
+ " return 1");
+ verifyFormat("a = null\n"
+ "return 1",
+ "a = null\n"
+ " return 1");
}
TEST_F(FormatTestJS, ClosureStyleCasts) {
@@ -899,8 +1002,16 @@ TEST_F(FormatTestJS, TypeAnnotations) {
verifyFormat("((a: string, b: number): string => a + b);");
verifyFormat("var x: (y: number) => string;");
verifyFormat("var x: P<string, (a: number) => string>;");
- verifyFormat("var x = {y: function(): z { return 1; }};");
- verifyFormat("var x = {y: function(): {a: number} { return 1; }};");
+ verifyFormat("var x = {\n"
+ " y: function(): z {\n"
+ " return 1;\n"
+ " }\n"
+ "};");
+ verifyFormat("var x = {\n"
+ " y: function(): {a: number} {\n"
+ " return 1;\n"
+ " }\n"
+ "};");
verifyFormat("function someFunc(args: string[]):\n"
" {longReturnValue: string[]} {}",
getGoogleJSStyleWithColumns(60));
@@ -928,7 +1039,7 @@ TEST_F(FormatTestJS, ClassDeclarations) {
verifyFormat("class C {\n ['x' + 2]: string = 12;\n}");
verifyFormat("class C {\n private x: string = 12;\n}");
verifyFormat("class C {\n private static x: string = 12;\n}");
- verifyFormat("class C {\n static x(): string { return 'asd'; }\n}");
+ verifyFormat("class C {\n static x(): string {\n return 'asd';\n }\n}");
verifyFormat("class C extends P implements I {}");
verifyFormat("class C extends p.P implements i.I {}");
verifyFormat("class Test {\n"
@@ -1091,7 +1202,9 @@ TEST_F(FormatTestJS, Modules) {
verifyFormat("export default () => {};");
verifyFormat("export interface Foo { foo: number; }\n"
"export class Bar {\n"
- " blah(): string { return this.blah; };\n"
+ " blah(): string {\n"
+ " return this.blah;\n"
+ " };\n"
"}");
}
@@ -1122,7 +1235,7 @@ TEST_F(FormatTestJS, ImportWrapping) {
TEST_F(FormatTestJS, TemplateStrings) {
// Keeps any whitespace/indentation within the template string.
verifyFormat("var x = `hello\n"
- " ${ name }\n"
+ " ${name}\n"
" !`;",
"var x = `hello\n"
" ${ name }\n"
@@ -1206,6 +1319,27 @@ TEST_F(FormatTestJS, TemplateStrings) {
"var y;",
"var x = ` \\` a`;\n"
"var y;");
+ // Escaped dollar.
+ verifyFormat("var x = ` \\${foo}`;\n");
+}
+
+TEST_F(FormatTestJS, TemplateStringASI) {
+ verifyFormat("var x = `hello${world}`;", "var x = `hello${\n"
+ " world\n"
+ "}`;");
+}
+
+TEST_F(FormatTestJS, NestedTemplateStrings) {
+ verifyFormat(
+ "var x = `<ul>${xs.map(x => `<li>${x}</li>`).join('\\n')}</ul>`;");
+ verifyFormat("var x = `he${({text: 'll'}.text)}o`;");
+
+ // Crashed at some point.
+ verifyFormat("}");
+}
+
+TEST_F(FormatTestJS, TaggedTemplateStrings) {
+ verifyFormat("var x = html`<ul>`;");
}
TEST_F(FormatTestJS, CastSyntax) {
@@ -1218,6 +1352,11 @@ TEST_F(FormatTestJS, CastSyntax) {
" 1, //\n"
" 2\n"
"];");
+ verifyFormat("var x = [{x: 1} as type];");
+ verifyFormat("x = x as [a, b];");
+ verifyFormat("x = x as {a: string};");
+ verifyFormat("x = x as (string);");
+ verifyFormat("x = x! as (string);");
}
TEST_F(FormatTestJS, TypeArguments) {
@@ -1318,6 +1457,21 @@ TEST_F(FormatTestJS, RequoteStringsSingle) {
"let x = \"single\";\n");
}
+TEST_F(FormatTestJS, RequoteAndIndent) {
+ verifyFormat("let x = someVeryLongFunctionThatGoesOnAndOn(\n"
+ " 'double quoted string that needs wrapping');",
+ "let x = someVeryLongFunctionThatGoesOnAndOn("
+ "\"double quoted string that needs wrapping\");");
+
+ verifyFormat("let x =\n"
+ " 'foo\\'oo';\n"
+ "let x =\n"
+ " 'foo\\'oo';",
+ "let x=\"foo'oo\";\n"
+ "let x=\"foo'oo\";",
+ getGoogleJSStyleWithColumns(15));
+}
+
TEST_F(FormatTestJS, RequoteStringsDouble) {
FormatStyle DoubleQuotes = getGoogleStyle(FormatStyle::LK_JavaScript);
DoubleQuotes.JavaScriptQuotes = FormatStyle::JSQS_Double;
@@ -1346,6 +1500,7 @@ TEST_F(FormatTestJS, NonNullAssertionOperator) {
verifyFormat("let x = !foo;\n");
verifyFormat("let x = foo[0]!;\n");
verifyFormat("let x = (foo)!;\n");
+ verifyFormat("let x = foo! - 1;\n");
verifyFormat("let x = {foo: 1}!;\n");
}
@@ -1358,5 +1513,11 @@ TEST_F(FormatTestJS, Conditional) {
"}");
}
+TEST_F(FormatTestJS, ImportComments) {
+ verifyFormat("import {x} from 'x'; // from some location",
+ getGoogleJSStyleWithColumns(25));
+ verifyFormat("// taze: x from 'location'", getGoogleJSStyleWithColumns(10));
+}
+
} // end namespace tooling
} // end namespace clang
diff --git a/unittests/Format/FormatTestObjC.cpp b/unittests/Format/FormatTestObjC.cpp
new file mode 100644
index 000000000000..6a530f921e6d
--- /dev/null
+++ b/unittests/Format/FormatTestObjC.cpp
@@ -0,0 +1,822 @@
+//===- unittest/Format/FormatTestObjC.cpp - Formatting unit tests----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Format/Format.h"
+
+#include "../Tooling/ReplacementTest.h"
+#include "FormatTestUtils.h"
+
+#include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "gtest/gtest.h"
+
+#define DEBUG_TYPE "format-test"
+
+using clang::tooling::ReplacementTest;
+using clang::tooling::toReplacements;
+
+namespace clang {
+namespace format {
+namespace {
+
+class FormatTestObjC : public ::testing::Test {
+protected:
+ FormatTestObjC() {
+ Style = getLLVMStyle();
+ Style.Language = FormatStyle::LK_ObjC;
+ }
+
+ enum IncompleteCheck {
+ IC_ExpectComplete,
+ IC_ExpectIncomplete,
+ IC_DoNotCheck
+ };
+
+ std::string format(llvm::StringRef Code,
+ IncompleteCheck CheckIncomplete = IC_ExpectComplete) {
+ DEBUG(llvm::errs() << "---\n");
+ DEBUG(llvm::errs() << Code << "\n\n");
+ std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size()));
+ bool IncompleteFormat = false;
+ tooling::Replacements Replaces =
+ reformat(Style, Code, Ranges, "<stdin>", &IncompleteFormat);
+ if (CheckIncomplete != IC_DoNotCheck) {
+ bool ExpectedIncompleteFormat = CheckIncomplete == IC_ExpectIncomplete;
+ EXPECT_EQ(ExpectedIncompleteFormat, IncompleteFormat) << Code << "\n\n";
+ }
+ auto Result = applyAllReplacements(Code, Replaces);
+ EXPECT_TRUE(static_cast<bool>(Result));
+ DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
+ return *Result;
+ }
+
+ void verifyFormat(StringRef Code) {
+ EXPECT_EQ(Code.str(), format(test::messUp(Code)));
+ }
+
+ void verifyIncompleteFormat(StringRef Code) {
+ EXPECT_EQ(Code.str(), format(test::messUp(Code), IC_ExpectIncomplete));
+ }
+
+ FormatStyle Style;
+};
+
+TEST_F(FormatTestObjC, DetectsObjCInHeaders) {
+ Style = getStyle("LLVM", "a.h", "none", "@interface\n"
+ "- (id)init;");
+ EXPECT_EQ(FormatStyle::LK_ObjC, Style.Language);
+ Style = getStyle("LLVM", "a.h", "none", "@interface\n"
+ "+ (id)init;");
+ EXPECT_EQ(FormatStyle::LK_ObjC, Style.Language);
+
+ // No recognizable ObjC.
+ Style = getStyle("LLVM", "a.h", "none", "void f() {}");
+ EXPECT_EQ(FormatStyle::LK_Cpp, Style.Language);
+}
+
+TEST_F(FormatTestObjC, FormatObjCTryCatch) {
+ verifyFormat("@try {\n"
+ " f();\n"
+ "} @catch (NSException e) {\n"
+ " @throw;\n"
+ "} @finally {\n"
+ " exit(42);\n"
+ "}");
+ verifyFormat("DEBUG({\n"
+ " @try {\n"
+ " } @finally {\n"
+ " }\n"
+ "});\n");
+}
+
+TEST_F(FormatTestObjC, FormatObjCAutoreleasepool) {
+ verifyFormat("@autoreleasepool {\n"
+ " f();\n"
+ "}\n"
+ "@autoreleasepool {\n"
+ " f();\n"
+ "}\n");
+ Style.BreakBeforeBraces = FormatStyle::BS_Allman;
+ verifyFormat("@autoreleasepool\n"
+ "{\n"
+ " f();\n"
+ "}\n"
+ "@autoreleasepool\n"
+ "{\n"
+ " f();\n"
+ "}\n");
+}
+
+TEST_F(FormatTestObjC, FormatObjCInterface) {
+ verifyFormat("@interface Foo : NSObject <NSSomeDelegate> {\n"
+ "@public\n"
+ " int field1;\n"
+ "@protected\n"
+ " int field2;\n"
+ "@private\n"
+ " int field3;\n"
+ "@package\n"
+ " int field4;\n"
+ "}\n"
+ "+ (id)init;\n"
+ "@end");
+
+ verifyFormat("@interface /* wait for it */ Foo\n"
+ "+ (id)init;\n"
+ "// Look, a comment!\n"
+ "- (int)answerWith:(int)i;\n"
+ "@end");
+
+ verifyFormat("@interface Foo\n"
+ "@end\n"
+ "@interface Bar\n"
+ "@end");
+
+ verifyFormat("@interface Foo : Bar\n"
+ "+ (id)init;\n"
+ "@end");
+
+ verifyFormat("@interface Foo : /**/ Bar /**/ <Baz, /**/ Quux>\n"
+ "+ (id)init;\n"
+ "@end");
+
+ verifyFormat("@interface Foo (HackStuff)\n"
+ "+ (id)init;\n"
+ "@end");
+
+ verifyFormat("@interface Foo ()\n"
+ "+ (id)init;\n"
+ "@end");
+
+ verifyFormat("@interface Foo (HackStuff) <MyProtocol>\n"
+ "+ (id)init;\n"
+ "@end");
+
+ verifyFormat("@interface Foo {\n"
+ " int _i;\n"
+ "}\n"
+ "+ (id)init;\n"
+ "@end");
+
+ verifyFormat("@interface Foo : Bar {\n"
+ " int _i;\n"
+ "}\n"
+ "+ (id)init;\n"
+ "@end");
+
+ verifyFormat("@interface Foo : Bar <Baz, Quux> {\n"
+ " int _i;\n"
+ "}\n"
+ "+ (id)init;\n"
+ "@end");
+
+ verifyFormat("@interface Foo (HackStuff) {\n"
+ " int _i;\n"
+ "}\n"
+ "+ (id)init;\n"
+ "@end");
+
+ verifyFormat("@interface Foo () {\n"
+ " int _i;\n"
+ "}\n"
+ "+ (id)init;\n"
+ "@end");
+
+ verifyFormat("@interface Foo (HackStuff) <MyProtocol> {\n"
+ " int _i;\n"
+ "}\n"
+ "+ (id)init;\n"
+ "@end");
+
+ Style = getGoogleStyle(FormatStyle::LK_ObjC);
+ verifyFormat("@interface Foo : NSObject<NSSomeDelegate> {\n"
+ " @public\n"
+ " int field1;\n"
+ " @protected\n"
+ " int field2;\n"
+ " @private\n"
+ " int field3;\n"
+ " @package\n"
+ " int field4;\n"
+ "}\n"
+ "+ (id)init;\n"
+ "@end");
+ verifyFormat("@interface Foo : Bar<Baz, Quux>\n"
+ "+ (id)init;\n"
+ "@end");
+ 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"
+ "}");
+}
+
+TEST_F(FormatTestObjC, FormatObjCImplementation) {
+ verifyFormat("@implementation Foo : NSObject {\n"
+ "@public\n"
+ " int field1;\n"
+ "@protected\n"
+ " int field2;\n"
+ "@private\n"
+ " int field3;\n"
+ "@package\n"
+ " int field4;\n"
+ "}\n"
+ "+ (id)init {\n}\n"
+ "@end");
+
+ verifyFormat("@implementation Foo\n"
+ "+ (id)init {\n"
+ " if (true)\n"
+ " return nil;\n"
+ "}\n"
+ "// Look, a comment!\n"
+ "- (int)answerWith:(int)i {\n"
+ " return i;\n"
+ "}\n"
+ "+ (int)answerWith:(int)i {\n"
+ " return i;\n"
+ "}\n"
+ "@end");
+
+ verifyFormat("@implementation Foo\n"
+ "@end\n"
+ "@implementation Bar\n"
+ "@end");
+
+ EXPECT_EQ("@implementation Foo : Bar\n"
+ "+ (id)init {\n}\n"
+ "- (void)foo {\n}\n"
+ "@end",
+ format("@implementation Foo : Bar\n"
+ "+(id)init{}\n"
+ "-(void)foo{}\n"
+ "@end"));
+
+ verifyFormat("@implementation Foo {\n"
+ " int _i;\n"
+ "}\n"
+ "+ (id)init {\n}\n"
+ "@end");
+
+ verifyFormat("@implementation Foo : Bar {\n"
+ " int _i;\n"
+ "}\n"
+ "+ (id)init {\n}\n"
+ "@end");
+
+ verifyFormat("@implementation Foo (HackStuff)\n"
+ "+ (id)init {\n}\n"
+ "@end");
+ verifyFormat("@implementation ObjcClass\n"
+ "- (void)method;\n"
+ "{}\n"
+ "@end");
+
+ Style = getGoogleStyle(FormatStyle::LK_ObjC);
+ verifyFormat("@implementation Foo : NSObject {\n"
+ " @public\n"
+ " int field1;\n"
+ " @protected\n"
+ " int field2;\n"
+ " @private\n"
+ " int field3;\n"
+ " @package\n"
+ " int field4;\n"
+ "}\n"
+ "+ (id)init {\n}\n"
+ "@end");
+}
+
+TEST_F(FormatTestObjC, FormatObjCProtocol) {
+ verifyFormat("@protocol Foo\n"
+ "@property(weak) id delegate;\n"
+ "- (NSUInteger)numberOfThings;\n"
+ "@end");
+
+ verifyFormat("@protocol MyProtocol <NSObject>\n"
+ "- (NSUInteger)numberOfThings;\n"
+ "@end");
+
+ verifyFormat("@protocol Foo;\n"
+ "@protocol Bar;\n");
+
+ verifyFormat("@protocol Foo\n"
+ "@end\n"
+ "@protocol Bar\n"
+ "@end");
+
+ verifyFormat("@protocol myProtocol\n"
+ "- (void)mandatoryWithInt:(int)i;\n"
+ "@optional\n"
+ "- (void)optional;\n"
+ "@required\n"
+ "- (void)required;\n"
+ "@optional\n"
+ "@property(assign) int madProp;\n"
+ "@end\n");
+
+ verifyFormat("@property(nonatomic, assign, readonly)\n"
+ " int *looooooooooooooooooooooooooooongNumber;\n"
+ "@property(nonatomic, assign, readonly)\n"
+ " NSString *looooooooooooooooooooooooooooongName;");
+
+ verifyFormat("@implementation PR18406\n"
+ "}\n"
+ "@end");
+
+ Style = getGoogleStyle(FormatStyle::LK_ObjC);
+ verifyFormat("@protocol MyProtocol<NSObject>\n"
+ "- (NSUInteger)numberOfThings;\n"
+ "@end");
+}
+
+TEST_F(FormatTestObjC, FormatObjCMethodDeclarations) {
+ verifyFormat("- (void)doSomethingWith:(GTMFoo *)theFoo\n"
+ " rect:(NSRect)theRect\n"
+ " interval:(float)theInterval {\n"
+ "}");
+ verifyFormat("- (void)shortf:(GTMFoo *)theFoo\n"
+ " longKeyword:(NSRect)theRect\n"
+ " longerKeyword:(float)theInterval\n"
+ " error:(NSError **)theError {\n"
+ "}");
+ verifyFormat("- (void)shortf:(GTMFoo *)theFoo\n"
+ " longKeyword:(NSRect)theRect\n"
+ " evenLongerKeyword:(float)theInterval\n"
+ " error:(NSError **)theError {\n"
+ "}");
+ Style.ColumnLimit = 60;
+ verifyFormat("- (instancetype)initXxxxxx:(id<x>)x\n"
+ " y:(id<yyyyyyyyyyyyyyyyyyyy>)y\n"
+ " NS_DESIGNATED_INITIALIZER;");
+ verifyFormat("- (void)drawRectOn:(id)surface\n"
+ " ofSize:(size_t)height\n"
+ " :(size_t)width;");
+
+ // 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"
+ "}");
+
+ // Make sure we don't break aligning for short parameter names.
+ verifyFormat("- (void)shortf:(GTMFoo *)theFoo\n"
+ " aShortf:(NSRect)theRect {\n"
+ "}");
+
+ // Format pairs correctly.
+ Style.ColumnLimit = 80;
+ verifyFormat("- (void)drawRectOn:(id)surface\n"
+ " ofSize:(aaaaaaaa)height\n"
+ " :(size_t)width\n"
+ " atOrigin:(size_t)x\n"
+ " :(size_t)y\n"
+ " aaaaa:(a)yyy\n"
+ " bbb:(d)cccc;");
+ verifyFormat("- (void)drawRectOn:(id)surface ofSize:(aaa)height:(bbb)width;");
+}
+
+TEST_F(FormatTestObjC, FormatObjCMethodExpr) {
+ verifyFormat("[foo bar:baz];");
+ verifyFormat("return [foo bar:baz];");
+ verifyFormat("return (a)[foo bar:baz];");
+ verifyFormat("f([foo bar:baz]);");
+ verifyFormat("f(2, [foo bar:baz]);");
+ verifyFormat("f(2, a ? b : c);");
+ verifyFormat("[[self initWithInt:4] bar:[baz quux:arrrr]];");
+
+ // Unary operators.
+ verifyFormat("int a = +[foo bar:baz];");
+ verifyFormat("int a = -[foo bar:baz];");
+ verifyFormat("int a = ![foo bar:baz];");
+ verifyFormat("int a = ~[foo bar:baz];");
+ verifyFormat("int a = ++[foo bar:baz];");
+ verifyFormat("int a = --[foo bar:baz];");
+ verifyFormat("int a = sizeof [foo bar:baz];");
+ verifyFormat("int a = alignof [foo bar:baz];");
+ verifyFormat("int a = &[foo bar:baz];");
+ verifyFormat("int a = *[foo bar:baz];");
+ // FIXME: Make casts work, without breaking f()[4].
+ // verifyFormat("int a = (int)[foo bar:baz];");
+ // verifyFormat("return (int)[foo bar:baz];");
+ // verifyFormat("(void)[foo bar:baz];");
+ verifyFormat("return (MyType *)[self.tableView cellForRowAtIndexPath:cell];");
+
+ // Binary operators.
+ verifyFormat("[foo bar:baz], [foo bar:baz];");
+ verifyFormat("[foo bar:baz] = [foo bar:baz];");
+ verifyFormat("[foo bar:baz] *= [foo bar:baz];");
+ verifyFormat("[foo bar:baz] /= [foo bar:baz];");
+ verifyFormat("[foo bar:baz] %= [foo bar:baz];");
+ verifyFormat("[foo bar:baz] += [foo bar:baz];");
+ verifyFormat("[foo bar:baz] -= [foo bar:baz];");
+ verifyFormat("[foo bar:baz] <<= [foo bar:baz];");
+ verifyFormat("[foo bar:baz] >>= [foo bar:baz];");
+ verifyFormat("[foo bar:baz] &= [foo bar:baz];");
+ verifyFormat("[foo bar:baz] ^= [foo bar:baz];");
+ verifyFormat("[foo bar:baz] |= [foo bar:baz];");
+ verifyFormat("[foo bar:baz] ? [foo bar:baz] : [foo bar:baz];");
+ verifyFormat("[foo bar:baz] || [foo bar:baz];");
+ verifyFormat("[foo bar:baz] && [foo bar:baz];");
+ verifyFormat("[foo bar:baz] | [foo bar:baz];");
+ verifyFormat("[foo bar:baz] ^ [foo bar:baz];");
+ verifyFormat("[foo bar:baz] & [foo bar:baz];");
+ verifyFormat("[foo bar:baz] == [foo bar:baz];");
+ verifyFormat("[foo bar:baz] != [foo bar:baz];");
+ verifyFormat("[foo bar:baz] >= [foo bar:baz];");
+ verifyFormat("[foo bar:baz] <= [foo bar:baz];");
+ verifyFormat("[foo bar:baz] > [foo bar:baz];");
+ verifyFormat("[foo bar:baz] < [foo bar:baz];");
+ verifyFormat("[foo bar:baz] >> [foo bar:baz];");
+ verifyFormat("[foo bar:baz] << [foo bar:baz];");
+ verifyFormat("[foo bar:baz] - [foo bar:baz];");
+ verifyFormat("[foo bar:baz] + [foo bar:baz];");
+ verifyFormat("[foo bar:baz] * [foo bar:baz];");
+ verifyFormat("[foo bar:baz] / [foo bar:baz];");
+ verifyFormat("[foo bar:baz] % [foo bar:baz];");
+ // Whew!
+
+ verifyFormat("return in[42];");
+ verifyFormat("for (auto v : in[1]) {\n}");
+ verifyFormat("for (int i = 0; i < in[a]; ++i) {\n}");
+ verifyFormat("for (int i = 0; in[a] < i; ++i) {\n}");
+ verifyFormat("for (int i = 0; i < n; ++i, ++in[a]) {\n}");
+ verifyFormat("for (int i = 0; i < n; ++i, in[a]++) {\n}");
+ verifyFormat("for (int i = 0; i < f(in[a]); ++i, in[a]++) {\n}");
+ verifyFormat("for (id foo in [self getStuffFor:bla]) {\n"
+ "}");
+ verifyFormat("[self aaaaa:MACRO(a, b:, c:)];");
+ verifyFormat("[self aaaaa:(1 + 2) bbbbb:3];");
+ verifyFormat("[self aaaaa:(Type)a bbbbb:3];");
+
+ verifyFormat("[self stuffWithInt:(4 + 2) float:4.5];");
+ verifyFormat("[self stuffWithInt:a ? b : c float:4.5];");
+ verifyFormat("[self stuffWithInt:a ? [self foo:bar] : c];");
+ verifyFormat("[self stuffWithInt:a ? (e ? f : g) : c];");
+ verifyFormat("[cond ? obj1 : obj2 methodWithParam:param]");
+ verifyFormat("[button setAction:@selector(zoomOut:)];");
+ verifyFormat("[color getRed:&r green:&g blue:&b alpha:&a];");
+
+ verifyFormat("arr[[self indexForFoo:a]];");
+ verifyFormat("throw [self errorFor:a];");
+ verifyFormat("@throw [self errorFor:a];");
+
+ verifyFormat("[(id)foo bar:(id)baz quux:(id)snorf];");
+ verifyFormat("[(id)foo bar:(id) ? baz : quux];");
+ verifyFormat("4 > 4 ? (id)a : (id)baz;");
+
+ // This tests that the formatter doesn't break after "backing" but before ":",
+ // which would be at 80 columns.
+ verifyFormat(
+ "void f() {\n"
+ " if ((self = [super initWithContentRect:contentRect\n"
+ " styleMask:styleMask ?: otherMask\n"
+ " backing:NSBackingStoreBuffered\n"
+ " defer:YES]))");
+
+ verifyFormat(
+ "[foo checkThatBreakingAfterColonWorksOk:\n"
+ " [bar ifItDoes:reduceOverallLineLengthLikeInThisCase]];");
+
+ verifyFormat("[myObj short:arg1 // Force line break\n"
+ " longKeyword:arg2 != nil ? arg2 : @\"longKeyword\"\n"
+ " evenLongerKeyword:arg3 ?: @\"evenLongerKeyword\"\n"
+ " error:arg4];");
+ verifyFormat(
+ "void f() {\n"
+ " popup_window_.reset([[RenderWidgetPopupWindow alloc]\n"
+ " initWithContentRect:NSMakeRect(origin_global.x, origin_global.y,\n"
+ " pos.width(), pos.height())\n"
+ " styleMask:NSBorderlessWindowMask\n"
+ " backing:NSBackingStoreBuffered\n"
+ " defer:NO]);\n"
+ "}");
+ verifyFormat("[contentsContainer replaceSubview:[subviews objectAtIndex:0]\n"
+ " with:contentsNativeView];");
+
+ verifyFormat(
+ "[pboard addTypes:[NSArray arrayWithObject:kBookmarkButtonDragType]\n"
+ " owner:nillllll];");
+
+ verifyFormat(
+ "[pboard setData:[NSData dataWithBytes:&button length:sizeof(button)]\n"
+ " forType:kBookmarkButtonDragType];");
+
+ verifyFormat("[defaultCenter addObserver:self\n"
+ " selector:@selector(willEnterFullscreen)\n"
+ " name:kWillEnterFullscreenNotification\n"
+ " object:nil];");
+ verifyFormat("[image_rep drawInRect:drawRect\n"
+ " fromRect:NSZeroRect\n"
+ " operation:NSCompositeCopy\n"
+ " fraction:1.0\n"
+ " respectFlipped:NO\n"
+ " hints:nil];");
+ verifyFormat("[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
+ " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa];");
+ verifyFormat("[aaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaa)\n"
+ " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa];");
+ verifyFormat("[aaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaa[aaaaaaaaaaaaaaaaaaaaa]\n"
+ " aaaaaaaaaaaaaaaaaaaaaa];");
+
+ verifyFormat(
+ "scoped_nsobject<NSTextField> message(\n"
+ " // The frame will be fixed up when |-setMessageText:| is called.\n"
+ " [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 0, 0)]);");
+ verifyFormat("[self aaaaaa:bbbbbbbbbbbbb\n"
+ " aaaaaaaaaa:bbbbbbbbbbbbbbbbb\n"
+ " aaaaa:bbbbbbbbbbb + bbbbbbbbbbbb\n"
+ " aaaa:bbb];");
+ verifyFormat("[self param:function( //\n"
+ " parameter)]");
+ verifyFormat(
+ "[self aaaaaaaaaa:aaaaaaaaaaaaaaa | aaaaaaaaaaaaaaa | aaaaaaaaaaaaaaa |\n"
+ " aaaaaaaaaaaaaaa | aaaaaaaaaaaaaaa | aaaaaaaaaaaaaaa |\n"
+ " aaaaaaaaaaaaaaa | aaaaaaaaaaaaaaa];");
+
+ // Variadic parameters.
+ verifyFormat(
+ "NSArray *myStrings = [NSArray stringarray:@\"a\", @\"b\", nil];");
+ verifyFormat(
+ "[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];");
+
+ Style.ColumnLimit = 70;
+ verifyFormat(
+ "void f() {\n"
+ " popup_wdow_.reset([[RenderWidgetPopupWindow alloc]\n"
+ " iniithContentRect:NSMakRet(origin_global.x, origin_global.y,\n"
+ " pos.width(), pos.height())\n"
+ " syeMask:NSBorderlessWindowMask\n"
+ " bking:NSBackingStoreBuffered\n"
+ " der:NO]);\n"
+ "}");
+
+ Style.ColumnLimit = 60;
+ verifyFormat("[call aaaaaaaa.aaaaaa.aaaaaaaa.aaaaaaaa.aaaaaaaa.aaaaaaaa\n"
+ " .aaaaaaaa];"); // FIXME: Indentation seems off.
+ // FIXME: This violates the column limit.
+ verifyFormat(
+ "[aaaaaaaaaaaaaaaaaaaaaaaaa\n"
+ " aaaaaaaaaaaaaaaaa:aaaaaaaa\n"
+ " aaa:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa];");
+
+ Style = getChromiumStyle(FormatStyle::LK_ObjC);
+ Style.ColumnLimit = 80;
+ verifyFormat(
+ "void f() {\n"
+ " popup_window_.reset([[RenderWidgetPopupWindow alloc]\n"
+ " initWithContentRect:NSMakeRect(origin_global.x, origin_global.y,\n"
+ " pos.width(), pos.height())\n"
+ " styleMask:NSBorderlessWindowMask\n"
+ " backing:NSBackingStoreBuffered\n"
+ " defer:NO]);\n"
+ "}");
+}
+
+TEST_F(FormatTestObjC, ObjCAt) {
+ verifyFormat("@autoreleasepool");
+ verifyFormat("@catch");
+ verifyFormat("@class");
+ verifyFormat("@compatibility_alias");
+ verifyFormat("@defs");
+ verifyFormat("@dynamic");
+ verifyFormat("@encode");
+ verifyFormat("@end");
+ verifyFormat("@finally");
+ verifyFormat("@implementation");
+ verifyFormat("@import");
+ verifyFormat("@interface");
+ verifyFormat("@optional");
+ verifyFormat("@package");
+ verifyFormat("@private");
+ verifyFormat("@property");
+ verifyFormat("@protected");
+ verifyFormat("@protocol");
+ verifyFormat("@public");
+ verifyFormat("@required");
+ verifyFormat("@selector");
+ verifyFormat("@synchronized");
+ verifyFormat("@synthesize");
+ verifyFormat("@throw");
+ verifyFormat("@try");
+
+ EXPECT_EQ("@interface", format("@ interface"));
+
+ // The precise formatting of this doesn't matter, nobody writes code like
+ // this.
+ verifyFormat("@ /*foo*/ interface");
+}
+
+TEST_F(FormatTestObjC, ObjCSnippets) {
+ verifyFormat("@autoreleasepool {\n"
+ " foo();\n"
+ "}");
+ verifyFormat("@class Foo, Bar;");
+ verifyFormat("@compatibility_alias AliasName ExistingClass;");
+ verifyFormat("@dynamic textColor;");
+ verifyFormat("char *buf1 = @encode(int *);");
+ verifyFormat("char *buf1 = @encode(typeof(4 * 5));");
+ verifyFormat("char *buf1 = @encode(int **);");
+ verifyFormat("Protocol *proto = @protocol(p1);");
+ verifyFormat("SEL s = @selector(foo:);");
+ verifyFormat("@synchronized(self) {\n"
+ " f();\n"
+ "}");
+
+ verifyFormat("@import foo.bar;\n"
+ "@import baz;");
+
+ verifyFormat("@synthesize dropArrowPosition = dropArrowPosition_;");
+
+ verifyFormat("@property(assign, nonatomic) CGFloat hoverAlpha;");
+ verifyFormat("@property(assign, getter=isEditable) BOOL editable;");
+
+ Style = getMozillaStyle();
+ verifyFormat("@property (assign, getter=isEditable) BOOL editable;");
+ verifyFormat("@property BOOL editable;");
+
+ Style = getWebKitStyle();
+ verifyFormat("@property (assign, getter=isEditable) BOOL editable;");
+ verifyFormat("@property BOOL editable;");
+
+ Style = getGoogleStyle(FormatStyle::LK_ObjC);
+ verifyFormat("@synthesize dropArrowPosition = dropArrowPosition_;");
+ verifyFormat("@property(assign, getter=isEditable) BOOL editable;");
+}
+
+TEST_F(FormatTestObjC, ObjCForIn) {
+ verifyFormat("- (void)test {\n"
+ " for (NSString *n in arrayOfStrings) {\n"
+ " foo(n);\n"
+ " }\n"
+ "}");
+ verifyFormat("- (void)test {\n"
+ " for (NSString *n in (__bridge NSArray *)arrayOfStrings) {\n"
+ " foo(n);\n"
+ " }\n"
+ "}");
+}
+
+TEST_F(FormatTestObjC, ObjCLiterals) {
+ verifyFormat("@\"String\"");
+ verifyFormat("@1");
+ verifyFormat("@+4.8");
+ verifyFormat("@-4");
+ verifyFormat("@1LL");
+ verifyFormat("@.5");
+ verifyFormat("@'c'");
+ verifyFormat("@true");
+
+ verifyFormat("NSNumber *smallestInt = @(-INT_MAX - 1);");
+ verifyFormat("NSNumber *piOverTwo = @(M_PI / 2);");
+ verifyFormat("NSNumber *favoriteColor = @(Green);");
+ verifyFormat("NSString *path = @(getenv(\"PATH\"));");
+
+ verifyFormat("[dictionary setObject:@(1) forKey:@\"number\"];");
+}
+
+TEST_F(FormatTestObjC, ObjCDictLiterals) {
+ verifyFormat("@{");
+ verifyFormat("@{}");
+ verifyFormat("@{@\"one\" : @1}");
+ verifyFormat("return @{@\"one\" : @1;");
+ verifyFormat("@{@\"one\" : @1}");
+
+ verifyFormat("@{@\"one\" : @{@2 : @1}}");
+ verifyFormat("@{\n"
+ " @\"one\" : @{@2 : @1},\n"
+ "}");
+
+ verifyFormat("@{1 > 2 ? @\"one\" : @\"two\" : 1 > 2 ? @1 : @2}");
+ verifyIncompleteFormat("[self setDict:@{}");
+ verifyIncompleteFormat("[self setDict:@{@1 : @2}");
+ verifyFormat("NSLog(@\"%@\", @{@1 : @2, @2 : @3}[@1]);");
+ verifyFormat(
+ "NSDictionary *masses = @{@\"H\" : @1.0078, @\"He\" : @4.0026};");
+ verifyFormat(
+ "NSDictionary *settings = @{AVEncoderKey : @(AVAudioQualityMax)};");
+
+ verifyFormat("NSDictionary *d = @{\n"
+ " @\"nam\" : NSUserNam(),\n"
+ " @\"dte\" : [NSDate date],\n"
+ " @\"processInfo\" : [NSProcessInfo processInfo]\n"
+ "};");
+ verifyFormat(
+ "@{\n"
+ " NSFontAttributeNameeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee : "
+ "regularFont,\n"
+ "};");
+ verifyFormat(
+ "@{\n"
+ " NSFontAttributeNameeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee :\n"
+ " reeeeeeeeeeeeeeeeeeeeeeeegularFont,\n"
+ "};");
+
+ // We should try to be robust in case someone forgets the "@".
+ verifyFormat("NSDictionary *d = {\n"
+ " @\"nam\" : NSUserNam(),\n"
+ " @\"dte\" : [NSDate date],\n"
+ " @\"processInfo\" : [NSProcessInfo processInfo]\n"
+ "};");
+ verifyFormat("NSMutableDictionary *dictionary =\n"
+ " [NSMutableDictionary dictionaryWithDictionary:@{\n"
+ " aaaaaaaaaaaaaaaaaaaaa : aaaaaaaaaaaaa,\n"
+ " bbbbbbbbbbbbbbbbbb : bbbbb,\n"
+ " cccccccccccccccc : ccccccccccccccc\n"
+ " }];");
+
+ // Ensure that casts before the key are kept on the same line as the key.
+ verifyFormat(
+ "NSDictionary *d = @{\n"
+ " (aaaaaaaa id)aaaaaaaaa : (aaaaaaaa id)aaaaaaaaaaaaaaaaaaaaaaaa,\n"
+ " (aaaaaaaa id)aaaaaaaaaaaaaa : (aaaaaaaa id)aaaaaaaaaaaaaa,\n"
+ "};");
+
+ Style = getGoogleStyle(FormatStyle::LK_ObjC);
+ verifyFormat(
+ "@{\n"
+ " NSFontAttributeNameeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee : "
+ "regularFont,\n"
+ "};");
+}
+
+TEST_F(FormatTestObjC, ObjCArrayLiterals) {
+ verifyIncompleteFormat("@[");
+ verifyFormat("@[]");
+ verifyFormat(
+ "NSArray *array = @[ @\" Hey \", NSApp, [NSNumber numberWithInt:42] ];");
+ verifyFormat("return @[ @3, @[], @[ @4, @5 ] ];");
+ verifyFormat("NSArray *array = @[ [foo description] ];");
+
+ verifyFormat(
+ "NSArray *some_variable = @[\n"
+ " aaaa == bbbbbbbbbbb ? @\"aaaaaaaaaaaa\" : @\"aaaaaaaaaaaaaa\",\n"
+ " @\"aaaaaaaaaaaaaaaaa\",\n"
+ " @\"aaaaaaaaaaaaaaaaa\",\n"
+ " @\"aaaaaaaaaaaaaaaaa\",\n"
+ "];");
+ verifyFormat(
+ "NSArray *some_variable = @[\n"
+ " aaaa == bbbbbbbbbbb ? @\"aaaaaaaaaaaa\" : @\"aaaaaaaaaaaaaa\",\n"
+ " @\"aaaaaaaaaaaaaaaa\", @\"aaaaaaaaaaaaaaaa\", @\"aaaaaaaaaaaaaaaa\"\n"
+ "];");
+ verifyFormat("NSArray *some_variable = @[\n"
+ " @\"aaaaaaaaaaaaaaaaa\",\n"
+ " @\"aaaaaaaaaaaaaaaaa\",\n"
+ " @\"aaaaaaaaaaaaaaaaa\",\n"
+ " @\"aaaaaaaaaaaaaaaaa\",\n"
+ "];");
+ verifyFormat("NSArray *array = @[\n"
+ " @\"a\",\n"
+ " @\"a\",\n" // Trailing comma -> one per line.
+ "];");
+
+ // We should try to be robust in case someone forgets the "@".
+ verifyFormat("NSArray *some_variable = [\n"
+ " @\"aaaaaaaaaaaaaaaaa\",\n"
+ " @\"aaaaaaaaaaaaaaaaa\",\n"
+ " @\"aaaaaaaaaaaaaaaaa\",\n"
+ " @\"aaaaaaaaaaaaaaaaa\",\n"
+ "];");
+ verifyFormat(
+ "- (NSAttributedString *)attributedStringForSegment:(NSUInteger)segment\n"
+ " index:(NSUInteger)index\n"
+ " nonDigitAttributes:\n"
+ " (NSDictionary *)noDigitAttributes;");
+ verifyFormat("[someFunction someLooooooooooooongParameter:@[\n"
+ " NSBundle.mainBundle.infoDictionary[@\"a\"]\n"
+ "]];");
+}
+} // end namespace
+} // end namespace format
+} // end namespace clang
diff --git a/unittests/Format/SortImportsTestJS.cpp b/unittests/Format/SortImportsTestJS.cpp
index 77c37e337ddf..7e766e1969e1 100644
--- a/unittests/Format/SortImportsTestJS.cpp
+++ b/unittests/Format/SortImportsTestJS.cpp
@@ -70,6 +70,26 @@ TEST_F(SortImportsTestJS, BasicSorting) {
"let x = 1;");
}
+TEST_F(SortImportsTestJS, DefaultBinding) {
+ verifySort("import A from 'a';\n"
+ "import B from 'b';\n"
+ "\n"
+ "let x = 1;",
+ "import B from 'b';\n"
+ "import A from 'a';\n"
+ "let x = 1;");
+}
+
+TEST_F(SortImportsTestJS, DefaultAndNamedBinding) {
+ verifySort("import A, {a} from 'a';\n"
+ "import B, {b} from 'b';\n"
+ "\n"
+ "let x = 1;",
+ "import B, {b} from 'b';\n"
+ "import A, {a} from 'a';\n"
+ "let x = 1;");
+}
+
TEST_F(SortImportsTestJS, WrappedImportStatements) {
verifySort("import {sym1, sym2} from 'a';\n"
"import {sym} from 'b';\n"
@@ -101,6 +121,16 @@ TEST_F(SortImportsTestJS, Comments) {
"import {sym} from 'b'; // from //foo:bar\n"
"// A very important import follows.\n"
"import {sym} from 'a'; /* more comments */\n");
+ verifySort("import {sym} from 'a';\n"
+ "import {sym} from 'b';\n"
+ "\n"
+ "/** Comment on variable. */\n"
+ "const x = 1;\n",
+ "import {sym} from 'b';\n"
+ "import {sym} from 'a';\n"
+ "\n"
+ "/** Comment on variable. */\n"
+ "const x = 1;\n");
}
TEST_F(SortImportsTestJS, SortStar) {
@@ -190,40 +220,29 @@ TEST_F(SortImportsTestJS, SideEffectImports) {
}
TEST_F(SortImportsTestJS, AffectedRange) {
- // Sort excluding a suffix.
- verifySort("import {sym} from 'b';\n"
+ // Affected range inside of import statements.
+ verifySort("import {sym} from 'a';\n"
+ "import {sym} from 'b';\n"
"import {sym} from 'c';\n"
- "import {sym} from 'a';\n"
+ "\n"
"let x = 1;",
"import {sym} from 'c';\n"
"import {sym} from 'b';\n"
"import {sym} from 'a';\n"
"let x = 1;",
0, 30);
- // Sort excluding a prefix.
+ // Affected range outside of import statements.
verifySort("import {sym} from 'c';\n"
- "import {sym} from 'a';\n"
- "import {sym} from 'b';\n"
- "\n"
- "let x = 1;",
- "import {sym} from 'c';\n"
"import {sym} from 'b';\n"
"import {sym} from 'a';\n"
"\n"
"let x = 1;",
- 30, 0);
- // Sort a range within imports.
- verifySort("import {sym} from 'c';\n"
- "import {sym} from 'a';\n"
- "import {sym} from 'b';\n"
- "import {sym} from 'c';\n"
- "let x = 1;",
"import {sym} from 'c';\n"
"import {sym} from 'b';\n"
"import {sym} from 'a';\n"
- "import {sym} from 'c';\n"
+ "\n"
"let x = 1;",
- 24, 30);
+ 70, 1);
}
TEST_F(SortImportsTestJS, SortingCanShrink) {
diff --git a/unittests/Format/SortIncludesTest.cpp b/unittests/Format/SortIncludesTest.cpp
index 13a1b9adeeec..c3c56a813041 100644
--- a/unittests/Format/SortIncludesTest.cpp
+++ b/unittests/Format/SortIncludesTest.cpp
@@ -24,10 +24,11 @@ protected:
return std::vector<tooling::Range>(1, tooling::Range(0, Code.size()));
}
- std::string sort(StringRef Code, StringRef FileName = "input.cpp") {
- auto Ranges = GetCodeRange(Code);
- auto Sorted =
- applyAllReplacements(Code, sortIncludes(Style, Code, Ranges, FileName));
+ std::string sort(StringRef Code, std::vector<tooling::Range> Ranges,
+ StringRef FileName = "input.cc") {
+ auto Replaces = sortIncludes(Style, 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));
@@ -35,6 +36,10 @@ protected:
return *Result;
}
+ std::string sort(StringRef Code, StringRef FileName = "input.cpp") {
+ return sort(Code, GetCodeRange(Code), FileName);
+ }
+
unsigned newCursor(llvm::StringRef Code, unsigned Cursor) {
sortIncludes(Style, Code, GetCodeRange(Code), "input.cpp", &Cursor);
return Cursor;
@@ -51,16 +56,24 @@ TEST_F(SortIncludesTest, BasicSorting) {
sort("#include \"a.h\"\n"
"#include \"c.h\"\n"
"#include \"b.h\"\n"));
+
+ EXPECT_EQ("// comment\n"
+ "#include <a>\n"
+ "#include <b>\n",
+ sort("// comment\n"
+ "#include <b>\n"
+ "#include <a>\n",
+ {tooling::Range(25, 1)}));
}
TEST_F(SortIncludesTest, NoReplacementsForValidIncludes) {
// Identical #includes have led to a failure with an unstable sort.
std::string Code = "#include <a>\n"
"#include <b>\n"
- "#include <b>\n"
- "#include <b>\n"
- "#include <b>\n"
- "#include <c>\n";
+ "#include <c>\n"
+ "#include <d>\n"
+ "#include <e>\n"
+ "#include <f>\n";
EXPECT_TRUE(sortIncludes(Style, Code, GetCodeRange(Code), "a.cc").empty());
}
@@ -286,6 +299,82 @@ TEST_F(SortIncludesTest, CalculatesCorrectCursorPosition) {
EXPECT_EQ(10u, newCursor(Code, 43));
}
+TEST_F(SortIncludesTest, DeduplicateIncludes) {
+ EXPECT_EQ("#include <a>\n"
+ "#include <b>\n"
+ "#include <c>\n",
+ sort("#include <a>\n"
+ "#include <b>\n"
+ "#include <b>\n"
+ "#include <b>\n"
+ "#include <b>\n"
+ "#include <c>\n"));
+}
+
+TEST_F(SortIncludesTest, SortAndDeduplicateIncludes) {
+ EXPECT_EQ("#include <a>\n"
+ "#include <b>\n"
+ "#include <c>\n",
+ sort("#include <b>\n"
+ "#include <a>\n"
+ "#include <b>\n"
+ "#include <b>\n"
+ "#include <c>\n"
+ "#include <b>\n"));
+}
+
+TEST_F(SortIncludesTest, CalculatesCorrectCursorPositionAfterDeduplicate) {
+ std::string Code = "#include <b>\n" // Start of line: 0
+ "#include <a>\n" // Start of line: 13
+ "#include <b>\n" // Start of line: 26
+ "#include <b>\n" // Start of line: 39
+ "#include <c>\n" // Start of line: 52
+ "#include <b>\n"; // Start of line: 65
+ std::string Expected = "#include <a>\n" // Start of line: 0
+ "#include <b>\n" // Start of line: 13
+ "#include <c>\n"; // Start of line: 26
+ EXPECT_EQ(Expected, sort(Code));
+ // Cursor on 'i' in "#include <a>".
+ EXPECT_EQ(1u, newCursor(Code, 14));
+ // Cursor on 'b' in "#include <b>".
+ EXPECT_EQ(23u, newCursor(Code, 10));
+ EXPECT_EQ(23u, newCursor(Code, 36));
+ EXPECT_EQ(23u, newCursor(Code, 49));
+ EXPECT_EQ(23u, newCursor(Code, 36));
+ EXPECT_EQ(23u, newCursor(Code, 75));
+ // Cursor on '#' in "#include <c>".
+ EXPECT_EQ(26u, newCursor(Code, 52));
+}
+
+TEST_F(SortIncludesTest, DeduplicateLocallyInEachBlock) {
+ EXPECT_EQ("#include <a>\n"
+ "#include <b>\n"
+ "\n"
+ "#include <b>\n"
+ "#include <c>\n",
+ sort("#include <a>\n"
+ "#include <b>\n"
+ "\n"
+ "#include <c>\n"
+ "#include <b>\n"
+ "#include <b>\n"));
+}
+
+TEST_F(SortIncludesTest, ValidAffactedRangesAfterDeduplicatingIncludes) {
+ std::string Code = "#include <a>\n"
+ "#include <b>\n"
+ "#include <a>\n"
+ "#include <a>\n"
+ "\n"
+ " int x ;";
+ std::vector<tooling::Range> Ranges = {tooling::Range(0, 52)};
+ auto Replaces = sortIncludes(Style, Code, Ranges, "input.cpp");
+ Ranges = tooling::calculateRangesAfterReplacements(Replaces, Ranges);
+ EXPECT_EQ(1u, Ranges.size());
+ EXPECT_EQ(0u, Ranges[0].getOffset());
+ EXPECT_EQ(26u, Ranges[0].getLength());
+}
+
} // end namespace
} // end namespace format
} // end namespace clang
diff --git a/unittests/Frontend/CodeGenActionTest.cpp b/unittests/Frontend/CodeGenActionTest.cpp
index 71446fd4d79d..356b5130fcbe 100644
--- a/unittests/Frontend/CodeGenActionTest.cpp
+++ b/unittests/Frontend/CodeGenActionTest.cpp
@@ -11,9 +11,10 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Frontend/CompilerInstance.h"
-#include "clang/CodeGen/CodeGenAction.h"
#include "clang/CodeGen/BackendUtil.h"
+#include "clang/CodeGen/CodeGenAction.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/PreprocessorOptions.h"
#include "gtest/gtest.h"
using namespace llvm;
diff --git a/unittests/Frontend/FrontendActionTest.cpp b/unittests/Frontend/FrontendActionTest.cpp
index 90afd774f1ad..c3e6adb6324d 100644
--- a/unittests/Frontend/FrontendActionTest.cpp
+++ b/unittests/Frontend/FrontendActionTest.cpp
@@ -7,13 +7,15 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Frontend/FrontendAction.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Frontend/FrontendAction.h"
+#include "clang/Frontend/FrontendActions.h"
#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Sema/Sema.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -191,4 +193,66 @@ TEST(PreprocessorFrontendAction, EndSourceFile) {
ASSERT_TRUE(TestAction.SeenEnd);
}
+class TypoExternalSemaSource : public ExternalSemaSource {
+ CompilerInstance &CI;
+
+public:
+ TypoExternalSemaSource(CompilerInstance &CI) : CI(CI) {}
+
+ TypoCorrection CorrectTypo(const DeclarationNameInfo &Typo, int LookupKind,
+ Scope *S, CXXScopeSpec *SS,
+ CorrectionCandidateCallback &CCC,
+ DeclContext *MemberContext, bool EnteringContext,
+ const ObjCObjectPointerType *OPT) override {
+ // Generate a fake typo correction with one attached note.
+ ASTContext &Ctx = CI.getASTContext();
+ TypoCorrection TC(DeclarationName(&Ctx.Idents.get("moo")));
+ unsigned DiagID = Ctx.getDiagnostics().getCustomDiagID(
+ DiagnosticsEngine::Note, "This is a note");
+ TC.addExtraDiagnostic(PartialDiagnostic(DiagID, Ctx.getDiagAllocator()));
+ return TC;
+ }
+};
+
+struct TypoDiagnosticConsumer : public DiagnosticConsumer {
+ void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
+ const Diagnostic &Info) override {
+ // Capture errors and notes. There should be one of each.
+ if (DiagLevel == DiagnosticsEngine::Error) {
+ assert(Error.empty());
+ Info.FormatDiagnostic(Error);
+ } else {
+ assert(Note.empty());
+ Info.FormatDiagnostic(Note);
+ }
+ }
+ SmallString<32> Error;
+ SmallString<32> Note;
+};
+
+TEST(ASTFrontendAction, ExternalSemaSource) {
+ auto *Invocation = new CompilerInvocation;
+ Invocation->getLangOpts()->CPlusPlus = true;
+ Invocation->getPreprocessorOpts().addRemappedFile(
+ "test.cc", MemoryBuffer::getMemBuffer("void fooo();\n"
+ "int main() { foo(); }")
+ .release());
+ Invocation->getFrontendOpts().Inputs.push_back(
+ FrontendInputFile("test.cc", IK_CXX));
+ Invocation->getFrontendOpts().ProgramAction = frontend::ParseSyntaxOnly;
+ Invocation->getTargetOpts().Triple = "i386-unknown-linux-gnu";
+ CompilerInstance Compiler;
+ Compiler.setInvocation(Invocation);
+ auto *TDC = new TypoDiagnosticConsumer;
+ Compiler.createDiagnostics(TDC, /*ShouldOwnClient=*/true);
+ Compiler.setExternalSemaSource(new TypoExternalSemaSource(Compiler));
+
+ SyntaxOnlyAction TestAction;
+ ASSERT_TRUE(Compiler.ExecuteAction(TestAction));
+ // There should be one error correcting to 'moo' and a note attached to it.
+ EXPECT_EQ("use of undeclared identifier 'foo'; did you mean 'moo'?",
+ TDC->Error.str().str());
+ EXPECT_EQ("This is a note", TDC->Note.str().str());
+}
+
} // anonymous namespace
diff --git a/unittests/StaticAnalyzer/AnalyzerOptionsTest.cpp b/unittests/StaticAnalyzer/AnalyzerOptionsTest.cpp
index 33f1740bea8a..891c88da302e 100644
--- a/unittests/StaticAnalyzer/AnalyzerOptionsTest.cpp
+++ b/unittests/StaticAnalyzer/AnalyzerOptionsTest.cpp
@@ -14,6 +14,23 @@
namespace clang {
namespace ento {
+TEST(StaticAnalyzerOptions, getRegisteredCheckers) {
+ auto IsDebugChecker = [](StringRef CheckerName) {
+ return CheckerName.startswith("debug");
+ };
+ auto IsAlphaChecker = [](StringRef CheckerName) {
+ return CheckerName.startswith("alpha");
+ };
+ const auto &AllCheckers =
+ AnalyzerOptions::getRegisteredCheckers(/*IncludeExperimental=*/true);
+ EXPECT_FALSE(llvm::any_of(AllCheckers, IsDebugChecker));
+ EXPECT_TRUE(llvm::any_of(AllCheckers, IsAlphaChecker));
+
+ const auto &StableCheckers = AnalyzerOptions::getRegisteredCheckers();
+ EXPECT_FALSE(llvm::any_of(StableCheckers, IsDebugChecker));
+ EXPECT_FALSE(llvm::any_of(StableCheckers, IsAlphaChecker));
+}
+
TEST(StaticAnalyzerOptions, SearchInParentPackageTests) {
AnalyzerOptions Opts;
Opts.Config["Outer.Inner.CheckerOne:Option"] = "true";
diff --git a/unittests/Tooling/CMakeLists.txt b/unittests/Tooling/CMakeLists.txt
index b4b3f404e270..185f43b6a8c5 100644
--- a/unittests/Tooling/CMakeLists.txt
+++ b/unittests/Tooling/CMakeLists.txt
@@ -6,6 +6,7 @@ set(LLVM_LINK_COMPONENTS
# By default MSVC has a 2^16 limit on the number of sections in an object file,
# and this needs more than that.
if (MSVC)
+ set_source_files_properties(RecursiveASTVisitorTest.cpp PROPERTIES COMPILE_FLAGS /bigobj)
set_source_files_properties(RecursiveASTVisitorTestExprVisitor.cpp PROPERTIES COMPILE_FLAGS /bigobj)
endif()
diff --git a/unittests/Tooling/CompilationDatabaseTest.cpp b/unittests/Tooling/CompilationDatabaseTest.cpp
index 380d86fc5660..1a6fffec9392 100644
--- a/unittests/Tooling/CompilationDatabaseTest.cpp
+++ b/unittests/Tooling/CompilationDatabaseTest.cpp
@@ -7,7 +7,6 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/AST/ASTConsumer.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclGroup.h"
#include "clang/Frontend/FrontendAction.h"
@@ -22,9 +21,10 @@ namespace tooling {
static void expectFailure(StringRef JSONDatabase, StringRef Explanation) {
std::string ErrorMessage;
- EXPECT_EQ(nullptr, JSONCompilationDatabase::loadFromBuffer(JSONDatabase,
- ErrorMessage))
- << "Expected an error because of: " << Explanation.str();
+ EXPECT_EQ(nullptr,
+ JSONCompilationDatabase::loadFromBuffer(JSONDatabase, ErrorMessage,
+ JSONCommandLineSyntax::Gnu))
+ << "Expected an error because of: " << Explanation.str();
}
TEST(JSONCompilationDatabase, ErrsOnInvalidFormat) {
@@ -44,12 +44,15 @@ TEST(JSONCompilationDatabase, ErrsOnInvalidFormat) {
expectFailure("[{\"directory\":\"\",\"command\":[],\"file\":\"\"}]", "Command not string");
expectFailure("[{\"directory\":\"\",\"arguments\":[[]],\"file\":\"\"}]",
"Arguments contain non-string");
+ expectFailure("[{\"output\":[]}]", "Expected strings as value.");
}
static std::vector<std::string> getAllFiles(StringRef JSONDatabase,
- std::string &ErrorMessage) {
+ std::string &ErrorMessage,
+ JSONCommandLineSyntax Syntax) {
std::unique_ptr<CompilationDatabase> Database(
- JSONCompilationDatabase::loadFromBuffer(JSONDatabase, ErrorMessage));
+ JSONCompilationDatabase::loadFromBuffer(JSONDatabase, ErrorMessage,
+ Syntax));
if (!Database) {
ADD_FAILURE() << ErrorMessage;
return std::vector<std::string>();
@@ -57,10 +60,12 @@ static std::vector<std::string> getAllFiles(StringRef JSONDatabase,
return Database->getAllFiles();
}
-static std::vector<CompileCommand> getAllCompileCommands(StringRef JSONDatabase,
- std::string &ErrorMessage) {
+static std::vector<CompileCommand>
+getAllCompileCommands(JSONCommandLineSyntax Syntax, StringRef JSONDatabase,
+ std::string &ErrorMessage) {
std::unique_ptr<CompilationDatabase> Database(
- JSONCompilationDatabase::loadFromBuffer(JSONDatabase, ErrorMessage));
+ JSONCompilationDatabase::loadFromBuffer(JSONDatabase, ErrorMessage,
+ Syntax));
if (!Database) {
ADD_FAILURE() << ErrorMessage;
return std::vector<CompileCommand>();
@@ -71,7 +76,8 @@ static std::vector<CompileCommand> getAllCompileCommands(StringRef JSONDatabase,
TEST(JSONCompilationDatabase, GetAllFiles) {
std::string ErrorMessage;
EXPECT_EQ(std::vector<std::string>(),
- getAllFiles("[]", ErrorMessage)) << ErrorMessage;
+ getAllFiles("[]", ErrorMessage, JSONCommandLineSyntax::Gnu))
+ << ErrorMessage;
std::vector<std::string> expected_files;
SmallString<16> PathStorage;
@@ -79,54 +85,70 @@ TEST(JSONCompilationDatabase, GetAllFiles) {
expected_files.push_back(PathStorage.str());
llvm::sys::path::native("//net/dir/file2", PathStorage);
expected_files.push_back(PathStorage.str());
- EXPECT_EQ(expected_files, getAllFiles(
- "[{\"directory\":\"//net/dir\","
- "\"command\":\"command\","
- "\"file\":\"file1\"},"
- " {\"directory\":\"//net/dir\","
- "\"command\":\"command\","
- "\"file\":\"file2\"}]",
- ErrorMessage)) << ErrorMessage;
+ EXPECT_EQ(expected_files,
+ getAllFiles("[{\"directory\":\"//net/dir\","
+ "\"command\":\"command\","
+ "\"file\":\"file1\"},"
+ " {\"directory\":\"//net/dir\","
+ "\"command\":\"command\","
+ "\"file\":\"file2\"}]",
+ ErrorMessage, JSONCommandLineSyntax::Gnu))
+ << ErrorMessage;
}
TEST(JSONCompilationDatabase, GetAllCompileCommands) {
std::string ErrorMessage;
- EXPECT_EQ(0u,
- getAllCompileCommands("[]", ErrorMessage).size()) << ErrorMessage;
+ EXPECT_EQ(
+ 0u, getAllCompileCommands(JSONCommandLineSyntax::Gnu, "[]", ErrorMessage)
+ .size())
+ << ErrorMessage;
StringRef Directory1("//net/dir1");
StringRef FileName1("file1");
StringRef Command1("command1");
+ StringRef Output1("file1.o");
StringRef Directory2("//net/dir2");
StringRef FileName2("file2");
StringRef Command2("command2");
+ StringRef Output2("");
std::vector<CompileCommand> Commands = getAllCompileCommands(
- ("[{\"directory\":\"" + Directory1 + "\"," +
- "\"command\":\"" + Command1 + "\","
- "\"file\":\"" + FileName1 + "\"},"
- " {\"directory\":\"" + Directory2 + "\"," +
- "\"command\":\"" + Command2 + "\","
- "\"file\":\"" + FileName2 + "\"}]").str(),
+ JSONCommandLineSyntax::Gnu,
+ ("[{\"directory\":\"" + Directory1 + "\"," + "\"command\":\"" + Command1 +
+ "\","
+ "\"file\":\"" +
+ FileName1 + "\", \"output\":\"" +
+ Output1 + "\"},"
+ " {\"directory\":\"" +
+ Directory2 + "\"," + "\"command\":\"" + Command2 + "\","
+ "\"file\":\"" +
+ FileName2 + "\"}]")
+ .str(),
ErrorMessage);
EXPECT_EQ(2U, Commands.size()) << ErrorMessage;
EXPECT_EQ(Directory1, Commands[0].Directory) << ErrorMessage;
EXPECT_EQ(FileName1, Commands[0].Filename) << ErrorMessage;
+ EXPECT_EQ(Output1, Commands[0].Output) << ErrorMessage;
ASSERT_EQ(1u, Commands[0].CommandLine.size());
EXPECT_EQ(Command1, Commands[0].CommandLine[0]) << ErrorMessage;
EXPECT_EQ(Directory2, Commands[1].Directory) << ErrorMessage;
EXPECT_EQ(FileName2, Commands[1].Filename) << ErrorMessage;
+ EXPECT_EQ(Output2, Commands[1].Output) << ErrorMessage;
ASSERT_EQ(1u, Commands[1].CommandLine.size());
EXPECT_EQ(Command2, Commands[1].CommandLine[0]) << ErrorMessage;
// Check that order is preserved.
Commands = getAllCompileCommands(
- ("[{\"directory\":\"" + Directory2 + "\"," +
- "\"command\":\"" + Command2 + "\","
- "\"file\":\"" + FileName2 + "\"},"
- " {\"directory\":\"" + Directory1 + "\"," +
- "\"command\":\"" + Command1 + "\","
- "\"file\":\"" + FileName1 + "\"}]").str(),
+ JSONCommandLineSyntax::Gnu,
+ ("[{\"directory\":\"" + Directory2 + "\"," + "\"command\":\"" + Command2 +
+ "\","
+ "\"file\":\"" +
+ FileName2 + "\"},"
+ " {\"directory\":\"" +
+ Directory1 + "\"," + "\"command\":\"" + Command1 + "\","
+ "\"file\":\"" +
+ FileName1 + "\"}]")
+ .str(),
ErrorMessage);
EXPECT_EQ(2U, Commands.size()) << ErrorMessage;
EXPECT_EQ(Directory2, Commands[0].Directory) << ErrorMessage;
@@ -143,7 +165,8 @@ static CompileCommand findCompileArgsInJsonDatabase(StringRef FileName,
StringRef JSONDatabase,
std::string &ErrorMessage) {
std::unique_ptr<CompilationDatabase> Database(
- JSONCompilationDatabase::loadFromBuffer(JSONDatabase, ErrorMessage));
+ JSONCompilationDatabase::loadFromBuffer(JSONDatabase, ErrorMessage,
+ JSONCommandLineSyntax::Gnu));
if (!Database)
return CompileCommand();
std::vector<CompileCommand> Commands = Database->getCompileCommands(FileName);
diff --git a/unittests/Tooling/LookupTest.cpp b/unittests/Tooling/LookupTest.cpp
index d847a298fff2..cc3922d01b51 100644
--- a/unittests/Tooling/LookupTest.cpp
+++ b/unittests/Tooling/LookupTest.cpp
@@ -14,10 +14,18 @@ using namespace clang;
namespace {
struct GetDeclsVisitor : TestVisitor<GetDeclsVisitor> {
std::function<void(CallExpr *)> OnCall;
+ std::function<void(RecordTypeLoc)> OnRecordTypeLoc;
SmallVector<Decl *, 4> DeclStack;
bool VisitCallExpr(CallExpr *Expr) {
- OnCall(Expr);
+ if (OnCall)
+ OnCall(Expr);
+ return true;
+ }
+
+ bool VisitRecordTypeLoc(RecordTypeLoc Loc) {
+ if (OnRecordTypeLoc)
+ OnRecordTypeLoc(Loc);
return true;
}
@@ -29,7 +37,7 @@ struct GetDeclsVisitor : TestVisitor<GetDeclsVisitor> {
}
};
-TEST(LookupTest, replaceNestedName) {
+TEST(LookupTest, replaceNestedFunctionName) {
GetDeclsVisitor Visitor;
auto replaceCallExpr = [&](const CallExpr *Expr,
@@ -103,6 +111,55 @@ TEST(LookupTest, replaceNestedName) {
};
Visitor.runOver(
"namespace a { int foo(); }\nusing a::foo;\nauto f = foo();\n");
+
+ Visitor.OnCall = [&](CallExpr *Expr) {
+ EXPECT_EQ("c::bar", replaceCallExpr(Expr, "::a::c::bar"));
+ };
+ Visitor.runOver("namespace a { namespace b { void foo(); } }\n"
+ "namespace a { namespace b { namespace {"
+ "void f() { foo(); }"
+ "} } }\n");
+
+ Visitor.OnCall = [&](CallExpr *Expr) {
+ EXPECT_EQ("x::bar", replaceCallExpr(Expr, "::a::x::bar"));
+ };
+ Visitor.runOver("namespace a { namespace b { void foo(); } }\n"
+ "namespace a { namespace b { namespace c {"
+ "void f() { foo(); }"
+ "} } }\n");
+}
+
+TEST(LookupTest, replaceNestedClassName) {
+ GetDeclsVisitor Visitor;
+
+ auto replaceRecordTypeLoc = [&](RecordTypeLoc Loc,
+ StringRef ReplacementString) {
+ const auto *FD = cast<CXXRecordDecl>(Loc.getDecl());
+ return tooling::replaceNestedName(
+ nullptr, Visitor.DeclStack.back()->getDeclContext(), FD,
+ ReplacementString);
+ };
+
+ Visitor.OnRecordTypeLoc = [&](RecordTypeLoc Type) {
+ // Filter Types by name since there are other `RecordTypeLoc` in the test
+ // file.
+ if (Type.getDecl()->getQualifiedNameAsString() == "a::b::Foo")
+ EXPECT_EQ("x::Bar", replaceRecordTypeLoc(Type, "::a::x::Bar"));
+ };
+ Visitor.runOver("namespace a { namespace b {\n"
+ "class Foo;\n"
+ "namespace c { Foo f();; }\n"
+ "} }\n");
+
+ Visitor.OnRecordTypeLoc = [&](RecordTypeLoc Type) {
+ // Filter Types by name since there are other `RecordTypeLoc` in the test
+ // file.
+ // `a::b::Foo` in using shadow decl is not `TypeLoc`.
+ if (Type.getDecl()->getQualifiedNameAsString() == "a::b::Foo")
+ EXPECT_EQ("Bar", replaceRecordTypeLoc(Type, "::a::x::Bar"));
+ };
+ Visitor.runOver("namespace a { namespace b { class Foo {}; } }\n"
+ "namespace c { using a::b::Foo; Foo f();; }\n");
}
} // end anonymous namespace
diff --git a/unittests/Tooling/RecursiveASTVisitorTest.cpp b/unittests/Tooling/RecursiveASTVisitorTest.cpp
index 991ae8bb7f3d..7e08f9619c1c 100644
--- a/unittests/Tooling/RecursiveASTVisitorTest.cpp
+++ b/unittests/Tooling/RecursiveASTVisitorTest.cpp
@@ -133,23 +133,21 @@ TEST(RecursiveASTVisitor, AttributesAreVisited) {
"};\n"));
}
-// Check to ensure that VarDecls are visited.
-class VarDeclVisitor : public ExpectedLocationVisitor<VarDeclVisitor> {
+// Check to ensure that implicit default argument expressions are visited.
+class IntegerLiteralVisitor
+ : public ExpectedLocationVisitor<IntegerLiteralVisitor> {
public:
- bool VisitVarDecl(VarDecl *VD) {
- Match(VD->getNameAsString(), VD->getLocStart());
+ bool VisitIntegerLiteral(const IntegerLiteral *IL) {
+ Match("literal", IL->getLocation());
return true;
}
};
-TEST(RecursiveASTVisitor, ArrayInitializersAreVisited) {
- VarDeclVisitor Visitor;
- Visitor.ExpectMatch("__i0", 1, 8);
- EXPECT_TRUE(
- Visitor.runOver("struct MyClass {\n"
- " int c[1];\n"
- " static MyClass Create() { return MyClass(); }\n"
- "};\n"));
+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/RecursiveASTVisitorTestCallVisitor.cpp b/unittests/Tooling/RecursiveASTVisitorTestCallVisitor.cpp
index f8ff5bdc7879..b981585450e1 100644
--- a/unittests/Tooling/RecursiveASTVisitorTestCallVisitor.cpp
+++ b/unittests/Tooling/RecursiveASTVisitorTestCallVisitor.cpp
@@ -8,7 +8,6 @@
//===----------------------------------------------------------------------===//
#include "TestVisitor.h"
-#include <stack>
using namespace clang;
diff --git a/unittests/Tooling/RecursiveASTVisitorTestDeclVisitor.cpp b/unittests/Tooling/RecursiveASTVisitorTestDeclVisitor.cpp
index 02676a737ab1..63bfb8b2e6c1 100644
--- a/unittests/Tooling/RecursiveASTVisitorTestDeclVisitor.cpp
+++ b/unittests/Tooling/RecursiveASTVisitorTestDeclVisitor.cpp
@@ -8,7 +8,6 @@
//===----------------------------------------------------------------------===//
#include "TestVisitor.h"
-#include <stack>
using namespace clang;
diff --git a/unittests/Tooling/RecursiveASTVisitorTestExprVisitor.cpp b/unittests/Tooling/RecursiveASTVisitorTestExprVisitor.cpp
index 6af5906c3fd4..5f1dd65222ba 100644
--- a/unittests/Tooling/RecursiveASTVisitorTestExprVisitor.cpp
+++ b/unittests/Tooling/RecursiveASTVisitorTestExprVisitor.cpp
@@ -8,7 +8,6 @@
//===----------------------------------------------------------------------===//
#include "TestVisitor.h"
-#include <stack>
using namespace clang;
@@ -162,10 +161,21 @@ TEST(RecursiveASTVisitor, CanSkipImplicitMemberInitializations) {
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) {
@@ -192,6 +202,43 @@ TEST(RecursiveASTVisitor, VisitsCallExpr) {
"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;
diff --git a/unittests/Tooling/RecursiveASTVisitorTestTypeLocVisitor.cpp b/unittests/Tooling/RecursiveASTVisitorTestTypeLocVisitor.cpp
index 63e2e8b6024c..dc2adaf4da0c 100644
--- a/unittests/Tooling/RecursiveASTVisitorTestTypeLocVisitor.cpp
+++ b/unittests/Tooling/RecursiveASTVisitorTestTypeLocVisitor.cpp
@@ -8,7 +8,6 @@
//===----------------------------------------------------------------------===//
#include "TestVisitor.h"
-#include <stack>
using namespace clang;
diff --git a/unittests/Tooling/RefactoringTest.cpp b/unittests/Tooling/RefactoringTest.cpp
index df96bb159dea..c29f8d7d7123 100644
--- a/unittests/Tooling/RefactoringTest.cpp
+++ b/unittests/Tooling/RefactoringTest.cpp
@@ -7,6 +7,7 @@
//
//===----------------------------------------------------------------------===//
+#include "ReplacementTest.h"
#include "RewriterTestContext.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
@@ -18,6 +19,7 @@
#include "clang/Basic/FileManager.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Format/Format.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendAction.h"
@@ -26,22 +28,11 @@
#include "clang/Tooling/Refactoring.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/ADT/SmallString.h"
-#include "llvm/Support/Path.h"
#include "gtest/gtest.h"
namespace clang {
namespace tooling {
-class ReplacementTest : public ::testing::Test {
- protected:
- Replacement createReplacement(SourceLocation Start, unsigned Length,
- llvm::StringRef ReplacementText) {
- return Replacement(Context.Sources, Start, Length, ReplacementText);
- }
-
- RewriterTestContext Context;
-};
-
TEST_F(ReplacementTest, CanDeleteAllText) {
FileID ID = Context.createInMemoryFile("input.cpp", "text");
SourceLocation Location = Context.getLocation(ID, 1, 1);
@@ -109,62 +100,412 @@ TEST_F(ReplacementTest, ReturnsInvalidPath) {
EXPECT_TRUE(Replace2.getFilePath().empty());
}
+// Checks that an llvm::Error instance contains a ReplacementError with expected
+// error code, expected new replacement, and expected existing replacement.
+static bool checkReplacementError(
+ llvm::Error&& Error, replacement_error ExpectedErr,
+ llvm::Optional<Replacement> ExpectedExisting,
+ llvm::Optional<Replacement> ExpectedNew) {
+ if (!Error) {
+ llvm::errs() << "Error is a success.";
+ return false;
+ }
+ std::string ErrorMessage;
+ llvm::raw_string_ostream OS(ErrorMessage);
+ llvm::handleAllErrors(std::move(Error), [&](const ReplacementError &RE) {
+ llvm::errs() << "Handling error...\n";
+ if (ExpectedErr != RE.get())
+ OS << "Unexpected error code: " << int(RE.get()) << "\n";
+ if (ExpectedExisting != RE.getExistingReplacement()) {
+ OS << "Expected Existing != Actual Existing.\n";
+ if (ExpectedExisting.hasValue())
+ OS << "Expected existing replacement: " << ExpectedExisting->toString()
+ << "\n";
+ if (RE.getExistingReplacement().hasValue())
+ OS << "Actual existing replacement: "
+ << RE.getExistingReplacement()->toString() << "\n";
+ }
+ if (ExpectedNew != RE.getNewReplacement()) {
+ OS << "Expected New != Actual New.\n";
+ if (ExpectedNew.hasValue())
+ OS << "Expected new replacement: " << ExpectedNew->toString() << "\n";
+ if (RE.getNewReplacement().hasValue())
+ OS << "Actual new replacement: " << RE.getNewReplacement()->toString()
+ << "\n";
+ }
+ });
+ OS.flush();
+ if (ErrorMessage.empty()) return true;
+ llvm::errs() << ErrorMessage;
+ return false;
+}
+
+TEST_F(ReplacementTest, FailAddReplacements) {
+ Replacements Replaces;
+ Replacement Deletion("x.cc", 0, 10, "3");
+ auto Err = Replaces.add(Deletion);
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+
+ Replacement OverlappingReplacement("x.cc", 0, 2, "a");
+ Err = Replaces.add(OverlappingReplacement);
+ EXPECT_TRUE(checkReplacementError(std::move(Err),
+ replacement_error::overlap_conflict,
+ Deletion, OverlappingReplacement));
+
+ Replacement ContainedReplacement("x.cc", 2, 2, "a");
+ Err = Replaces.add(Replacement(ContainedReplacement));
+ EXPECT_TRUE(checkReplacementError(std::move(Err),
+ replacement_error::overlap_conflict,
+ Deletion, ContainedReplacement));
+
+ Replacement WrongPathReplacement("y.cc", 20, 2, "");
+ Err = Replaces.add(WrongPathReplacement);
+ EXPECT_TRUE(checkReplacementError(std::move(Err),
+ replacement_error::wrong_file_path,
+ Deletion, WrongPathReplacement));
+
+ EXPECT_EQ(1u, Replaces.size());
+ EXPECT_EQ(Deletion, *Replaces.begin());
+}
+
+TEST_F(ReplacementTest, DeletionInReplacements) {
+ Replacements Replaces;
+ Replacement R("x.cc", 0, 10, "3");
+ auto Err = Replaces.add(R);
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+ Err = Replaces.add(Replacement("x.cc", 0, 2, ""));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+ Err = Replaces.add(Replacement("x.cc", 2, 2, ""));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+ EXPECT_EQ(1u, Replaces.size());
+ EXPECT_EQ(R, *Replaces.begin());
+}
+
+TEST_F(ReplacementTest, OverlappingReplacements) {
+ Replacements Replaces;
+ auto Err = Replaces.add(Replacement("x.cc", 0, 3, "345"));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+ Err = Replaces.add(Replacement("x.cc", 2, 3, "543"));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+
+ EXPECT_EQ(1u, Replaces.size());
+ EXPECT_EQ(Replacement("x.cc", 0, 5, "34543"), *Replaces.begin());
+
+ Err = Replaces.add(Replacement("x.cc", 2, 1, "5"));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+ EXPECT_EQ(1u, Replaces.size());
+ EXPECT_EQ(Replacement("x.cc", 0, 5, "34543"), *Replaces.begin());
+}
+
+TEST_F(ReplacementTest, AddAdjacentInsertionAndReplacement) {
+ Replacements Replaces;
+ // Test adding an insertion at the offset of an existing replacement.
+ auto Err = Replaces.add(Replacement("x.cc", 10, 3, "replace"));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+ Err = Replaces.add(Replacement("x.cc", 10, 0, "insert"));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+ EXPECT_EQ(Replaces.size(), 2u);
+
+ Replaces.clear();
+ // Test overlap with an existing insertion.
+ Err = Replaces.add(Replacement("x.cc", 10, 0, "insert"));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+ Err = Replaces.add(Replacement("x.cc", 10, 3, "replace"));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+ EXPECT_EQ(Replaces.size(), 2u);
+}
+
+TEST_F(ReplacementTest, MergeNewDeletions) {
+ Replacements Replaces;
+ Replacement ContainingReplacement("x.cc", 0, 10, "");
+ auto Err = Replaces.add(ContainingReplacement);
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+
+ Err = Replaces.add(Replacement("x.cc", 5, 3, ""));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+
+ Err = Replaces.add(Replacement("x.cc", 0, 10, ""));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+
+ Err = Replaces.add(Replacement("x.cc", 5, 5, ""));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+
+ EXPECT_EQ(1u, Replaces.size());
+ EXPECT_EQ(*Replaces.begin(), ContainingReplacement);
+}
+
+TEST_F(ReplacementTest, MergeOverlappingButNotAdjacentReplacement) {
+ Replacements Replaces;
+ auto Err = Replaces.add(Replacement("x.cc", 0, 2, ""));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+
+ Err = Replaces.add(Replacement("x.cc", 5, 5, ""));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+
+ Replacement After = Replacement("x.cc", 10, 5, "");
+ Err = Replaces.add(After);
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+
+ Replacement ContainingReplacement("x.cc", 0, 10, "");
+ Err = Replaces.add(ContainingReplacement);
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+
+ EXPECT_EQ(2u, Replaces.size());
+ EXPECT_EQ(*Replaces.begin(), ContainingReplacement);
+ EXPECT_EQ(*(++Replaces.begin()), After);
+}
+
+TEST_F(ReplacementTest, InsertionBeforeMergedDeletions) {
+ Replacements Replaces;
+
+ Replacement Insertion("x.cc", 0, 0, "123");
+ auto Err = Replaces.add(Insertion);
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+
+ Err = Replaces.add(Replacement("x.cc", 5, 5, ""));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+
+ Replacement Deletion("x.cc", 0, 10, "");
+ Err = Replaces.add(Deletion);
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+
+ EXPECT_EQ(2u, Replaces.size());
+ EXPECT_EQ(*Replaces.begin(), Insertion);
+ EXPECT_EQ(*(++Replaces.begin()), Deletion);
+}
+
+TEST_F(ReplacementTest, MergeOverlappingDeletions) {
+ Replacements Replaces;
+ auto Err = Replaces.add(Replacement("x.cc", 0, 2, ""));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+
+ Err = Replaces.add(Replacement("x.cc", 0, 5, ""));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+
+ EXPECT_EQ(1u, Replaces.size());
+ EXPECT_EQ(Replacement("x.cc", 0, 5, ""), *Replaces.begin());
+
+ Err = Replaces.add(Replacement("x.cc", 1, 5, ""));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+ EXPECT_EQ(1u, Replaces.size());
+ EXPECT_EQ(Replacement("x.cc", 0, 6, ""), *Replaces.begin());
+}
+
+TEST_F(ReplacementTest, FailedMergeExistingDeletions) {
+ Replacements Replaces;
+ Replacement First("x.cc", 0, 2, "");
+ auto Err = Replaces.add(First);
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+
+ Replacement Second("x.cc", 5, 5, "");
+ Err = Replaces.add(Second);
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+
+ Err = Replaces.add(Replacement("x.cc", 1, 10, ""));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+
+ EXPECT_EQ(1u, Replaces.size());
+ EXPECT_EQ(Replacement("x.cc", 0, 11, ""), *Replaces.begin());
+}
+
+TEST_F(ReplacementTest, FailAddRegression) {
+ Replacements Replaces;
+ // Create two replacements, where the second one is an insertion of the empty
+ // string exactly at the end of the first one.
+ auto Err = Replaces.add(Replacement("x.cc", 0, 10, "1"));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+ Err = Replaces.add(Replacement("x.cc", 10, 0, ""));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+
+ // Make sure we find the overlap with the first entry when inserting a
+ // replacement that ends exactly at the seam of the existing replacements.
+ Replacement OverlappingReplacement("x.cc", 5, 5, "fail");
+ Err = Replaces.add(OverlappingReplacement);
+ EXPECT_TRUE(checkReplacementError(std::move(Err),
+ replacement_error::overlap_conflict,
+ *Replaces.begin(), OverlappingReplacement));
+
+ Err = Replaces.add(Replacement("x.cc", 10, 0, ""));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+}
+
+TEST_F(ReplacementTest, InsertAtOffsetOfReplacement) {
+ Replacements Replaces;
+ auto Err = Replaces.add(Replacement("x.cc", 10, 2, ""));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+ Err = Replaces.add(Replacement("x.cc", 10, 0, ""));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+ EXPECT_EQ(Replaces.size(), 2u);
+
+ Replaces.clear();
+ Err = Replaces.add(Replacement("x.cc", 10, 0, ""));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+ Err = Replaces.add(Replacement("x.cc", 10, 2, ""));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+ EXPECT_EQ(Replaces.size(), 2u);
+}
+
+TEST_F(ReplacementTest, AddInsertAtOtherInsertWhenOderIndependent) {
+ Replacements Replaces;
+ auto Err = Replaces.add(Replacement("x.cc", 10, 0, "a"));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+ Replacement ConflictInsertion("x.cc", 10, 0, "b");
+ Err = Replaces.add(ConflictInsertion);
+ EXPECT_TRUE(checkReplacementError(std::move(Err),
+ replacement_error::insert_conflict,
+ *Replaces.begin(), ConflictInsertion));
+
+ Replaces.clear();
+ Err = Replaces.add(Replacement("x.cc", 10, 0, "a"));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+ Err = Replaces.add(Replacement("x.cc", 10, 0, "aa"));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+ EXPECT_EQ(1u, Replaces.size());
+ EXPECT_EQ(Replacement("x.cc", 10, 0, "aaa"), *Replaces.begin());
+
+ Replaces.clear();
+ Err = Replaces.add(Replacement("x.cc", 10, 0, ""));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+ Err = Replaces.add(Replacement("x.cc", 10, 3, ""));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+ Err = Replaces.add(Replacement("x.cc", 10, 0, ""));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+ EXPECT_EQ(2u, Replaces.size());
+ EXPECT_EQ(Replacement("x.cc", 10, 0, ""), *Replaces.begin());
+ EXPECT_EQ(Replacement("x.cc", 10, 3, ""), *std::next(Replaces.begin()));
+}
+
+TEST_F(ReplacementTest, InsertBetweenAdjacentReplacements) {
+ Replacements Replaces;
+ auto Err = Replaces.add(Replacement("x.cc", 10, 5, "a"));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+ Err = Replaces.add(Replacement("x.cc", 8, 2, "a"));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+ Err = Replaces.add(Replacement("x.cc", 10, 0, "b"));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+}
+
TEST_F(ReplacementTest, CanApplyReplacements) {
FileID ID = Context.createInMemoryFile("input.cpp",
"line1\nline2\nline3\nline4");
- Replacements Replaces;
- Replaces.insert(Replacement(Context.Sources, Context.getLocation(ID, 2, 1),
- 5, "replaced"));
- Replaces.insert(Replacement(Context.Sources, Context.getLocation(ID, 3, 1),
- 5, "other"));
+ Replacements Replaces =
+ toReplacements({Replacement(Context.Sources,
+ Context.getLocation(ID, 2, 1), 5, "replaced"),
+ Replacement(Context.Sources,
+ Context.getLocation(ID, 3, 1), 5, "other")});
EXPECT_TRUE(applyAllReplacements(Replaces, Context.Rewrite));
EXPECT_EQ("line1\nreplaced\nother\nline4", Context.getRewrittenText(ID));
}
-// FIXME: Remove this test case when Replacements is implemented as std::vector
-// instead of std::set. The other ReplacementTest tests will need to be updated
-// at that point as well.
-TEST_F(ReplacementTest, VectorCanApplyReplacements) {
+// Verifies that replacement/deletion is applied before insertion at the same
+// offset.
+TEST_F(ReplacementTest, InsertAndDelete) {
FileID ID = Context.createInMemoryFile("input.cpp",
"line1\nline2\nline3\nline4");
- std::vector<Replacement> Replaces;
- Replaces.push_back(Replacement(Context.Sources, Context.getLocation(ID, 2, 1),
- 5, "replaced"));
- Replaces.push_back(
- Replacement(Context.Sources, Context.getLocation(ID, 3, 1), 5, "other"));
+ Replacements Replaces = toReplacements(
+ {Replacement(Context.Sources, Context.getLocation(ID, 2, 1), 6, ""),
+ Replacement(Context.Sources, Context.getLocation(ID, 2, 1), 0,
+ "other\n")});
EXPECT_TRUE(applyAllReplacements(Replaces, Context.Rewrite));
- EXPECT_EQ("line1\nreplaced\nother\nline4", Context.getRewrittenText(ID));
+ EXPECT_EQ("line1\nother\nline3\nline4", Context.getRewrittenText(ID));
+}
+
+TEST_F(ReplacementTest, AdjacentReplacements) {
+ FileID ID = Context.createInMemoryFile("input.cpp",
+ "ab");
+ Replacements Replaces = toReplacements(
+ {Replacement(Context.Sources, Context.getLocation(ID, 1, 1), 1, "x"),
+ Replacement(Context.Sources, Context.getLocation(ID, 1, 2), 1, "y")});
+ EXPECT_TRUE(applyAllReplacements(Replaces, Context.Rewrite));
+ EXPECT_EQ("xy", Context.getRewrittenText(ID));
}
-TEST_F(ReplacementTest, SkipsDuplicateReplacements) {
+TEST_F(ReplacementTest, AddDuplicateReplacements) {
FileID ID = Context.createInMemoryFile("input.cpp",
"line1\nline2\nline3\nline4");
- Replacements Replaces;
- Replaces.insert(Replacement(Context.Sources, Context.getLocation(ID, 2, 1),
- 5, "replaced"));
- Replaces.insert(Replacement(Context.Sources, Context.getLocation(ID, 2, 1),
- 5, "replaced"));
- Replaces.insert(Replacement(Context.Sources, Context.getLocation(ID, 2, 1),
- 5, "replaced"));
+ auto Replaces = toReplacements({Replacement(
+ Context.Sources, Context.getLocation(ID, 2, 1), 5, "replaced")});
+
+ auto Err = Replaces.add(Replacement(
+ Context.Sources, Context.getLocation(ID, 2, 1), 5, "replaced"));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+
+ Err = Replaces.add(Replacement(Context.Sources, Context.getLocation(ID, 2, 1),
+ 5, "replaced"));
+ EXPECT_TRUE(!Err);
+ llvm::consumeError(std::move(Err));
+
EXPECT_TRUE(applyAllReplacements(Replaces, Context.Rewrite));
EXPECT_EQ("line1\nreplaced\nline3\nline4", Context.getRewrittenText(ID));
}
-TEST_F(ReplacementTest, ApplyAllFailsIfOneApplyFails) {
- // This test depends on the value of the file name of an invalid source
- // location being in the range ]a, z[.
- FileID IDa = Context.createInMemoryFile("a.cpp", "text");
- FileID IDz = Context.createInMemoryFile("z.cpp", "text");
- Replacements Replaces;
- Replaces.insert(Replacement(Context.Sources, Context.getLocation(IDa, 1, 1),
- 4, "a"));
- Replaces.insert(Replacement(Context.Sources, SourceLocation(),
- 5, "2"));
- Replaces.insert(Replacement(Context.Sources, Context.getLocation(IDz, 1, 1),
- 4, "z"));
+TEST_F(ReplacementTest, FailOrderDependentReplacements) {
+ FileID ID = Context.createInMemoryFile("input.cpp",
+ "line1\nline2\nline3\nline4");
+ auto Replaces = toReplacements({Replacement(
+ Context.Sources, Context.getLocation(ID, 2, 1), 5, "other")});
+
+ Replacement ConflictReplacement(Context.Sources,
+ Context.getLocation(ID, 2, 1), 5, "rehto");
+ auto Err = Replaces.add(ConflictReplacement);
+ EXPECT_TRUE(checkReplacementError(std::move(Err),
+ replacement_error::overlap_conflict,
+ *Replaces.begin(), ConflictReplacement));
+
+ EXPECT_TRUE(applyAllReplacements(Replaces, Context.Rewrite));
+ EXPECT_EQ("line1\nother\nline3\nline4", Context.getRewrittenText(ID));
+}
+
+TEST_F(ReplacementTest, InvalidSourceLocationFailsApplyAll) {
+ Replacements Replaces =
+ toReplacements({Replacement(Context.Sources, SourceLocation(), 5, "2")});
+
EXPECT_FALSE(applyAllReplacements(Replaces, Context.Rewrite));
- EXPECT_EQ("a", Context.getRewrittenText(IDa));
- EXPECT_EQ("z", Context.getRewrittenText(IDz));
}
TEST_F(ReplacementTest, MultipleFilesReplaceAndFormat) {
@@ -180,76 +521,66 @@ TEST_F(ReplacementTest, MultipleFilesReplaceAndFormat) {
std::string Expected2 = "int x =\n"
" 1234567890123;\n"
"int y = 10;";
- FileID ID1 = Context.createInMemoryFile("format_1.cpp", Code1);
- FileID ID2 = Context.createInMemoryFile("format_2.cpp", Code2);
+ StringRef File1 = "format_1.cpp";
+ StringRef File2 = "format_2.cpp";
+ FileID ID1 = Context.createInMemoryFile(File1, Code1);
+ FileID ID2 = Context.createInMemoryFile(File2, Code2);
- tooling::Replacements Replaces;
// Scrambled the order of replacements.
- Replaces.insert(tooling::Replacement(
- Context.Sources, Context.getLocation(ID2, 1, 12), 0, "4567890123"));
- Replaces.insert(tooling::Replacement(
- Context.Sources, Context.getLocation(ID1, 1, 1), 6, "auto "));
- Replaces.insert(tooling::Replacement(
- Context.Sources, Context.getLocation(ID2, 2, 9), 1, "10"));
- Replaces.insert(tooling::Replacement(
- Context.Sources, Context.getLocation(ID1, 3, 10), 1, "12345678901"));
-
- EXPECT_TRUE(formatAndApplyAllReplacements(
- Replaces, Context.Rewrite, "{BasedOnStyle: LLVM, ColumnLimit: 20}"));
+ std::map<std::string, Replacements> FileToReplaces;
+ FileToReplaces[File1] = toReplacements(
+ {tooling::Replacement(Context.Sources, Context.getLocation(ID1, 1, 1), 6,
+ "auto "),
+ tooling::Replacement(Context.Sources, Context.getLocation(ID1, 3, 10), 1,
+ "12345678901")});
+ FileToReplaces[File2] = toReplacements(
+ {tooling::Replacement(Context.Sources, Context.getLocation(ID2, 1, 12), 0,
+ "4567890123"),
+ tooling::Replacement(Context.Sources, Context.getLocation(ID2, 2, 9), 1,
+ "10")});
+ EXPECT_TRUE(
+ formatAndApplyAllReplacements(FileToReplaces, Context.Rewrite,
+ "{BasedOnStyle: LLVM, ColumnLimit: 20}"));
EXPECT_EQ(Expected1, Context.getRewrittenText(ID1));
EXPECT_EQ(Expected2, Context.getRewrittenText(ID2));
}
TEST(ShiftedCodePositionTest, FindsNewCodePosition) {
- Replacements Replaces;
- Replaces.insert(Replacement("", 0, 1, ""));
- Replaces.insert(Replacement("", 4, 3, " "));
+ Replacements Replaces =
+ toReplacements({Replacement("", 0, 1, ""), Replacement("", 4, 3, " ")});
// Assume ' int i;' is turned into 'int i;' and cursor is located at '|'.
- EXPECT_EQ(0u, shiftedCodePosition(Replaces, 0)); // |int i;
- EXPECT_EQ(0u, shiftedCodePosition(Replaces, 1)); // |nt i;
- EXPECT_EQ(1u, shiftedCodePosition(Replaces, 2)); // i|t i;
- EXPECT_EQ(2u, shiftedCodePosition(Replaces, 3)); // in| i;
- EXPECT_EQ(3u, shiftedCodePosition(Replaces, 4)); // int| i;
- EXPECT_EQ(3u, shiftedCodePosition(Replaces, 5)); // int | i;
- EXPECT_EQ(3u, shiftedCodePosition(Replaces, 6)); // int |i;
- EXPECT_EQ(4u, shiftedCodePosition(Replaces, 7)); // int |;
- EXPECT_EQ(5u, shiftedCodePosition(Replaces, 8)); // int i|
-}
-
-// FIXME: Remove this test case when Replacements is implemented as std::vector
-// instead of std::set. The other ReplacementTest tests will need to be updated
-// at that point as well.
-TEST(ShiftedCodePositionTest, VectorFindsNewCodePositionWithInserts) {
- std::vector<Replacement> Replaces;
- Replaces.push_back(Replacement("", 0, 1, ""));
- Replaces.push_back(Replacement("", 4, 3, " "));
- // Assume ' int i;' is turned into 'int i;' and cursor is located at '|'.
- EXPECT_EQ(0u, shiftedCodePosition(Replaces, 0)); // |int i;
- EXPECT_EQ(0u, shiftedCodePosition(Replaces, 1)); // |nt i;
- EXPECT_EQ(1u, shiftedCodePosition(Replaces, 2)); // i|t i;
- EXPECT_EQ(2u, shiftedCodePosition(Replaces, 3)); // in| i;
- EXPECT_EQ(3u, shiftedCodePosition(Replaces, 4)); // int| i;
- EXPECT_EQ(3u, shiftedCodePosition(Replaces, 5)); // int | i;
- EXPECT_EQ(3u, shiftedCodePosition(Replaces, 6)); // int |i;
- EXPECT_EQ(4u, shiftedCodePosition(Replaces, 7)); // int |;
- EXPECT_EQ(5u, shiftedCodePosition(Replaces, 8)); // int i|
+ EXPECT_EQ(0u, Replaces.getShiftedCodePosition(0)); // |int i;
+ EXPECT_EQ(0u, Replaces.getShiftedCodePosition(1)); // |nt i;
+ EXPECT_EQ(1u, Replaces.getShiftedCodePosition(2)); // i|t i;
+ EXPECT_EQ(2u, Replaces.getShiftedCodePosition(3)); // in| i;
+ EXPECT_EQ(3u, Replaces.getShiftedCodePosition(4)); // int| i;
+ EXPECT_EQ(3u, Replaces.getShiftedCodePosition(5)); // int | i;
+ EXPECT_EQ(3u, Replaces.getShiftedCodePosition(6)); // int |i;
+ EXPECT_EQ(4u, Replaces.getShiftedCodePosition(7)); // int |;
+ EXPECT_EQ(5u, Replaces.getShiftedCodePosition(8)); // int i|
}
TEST(ShiftedCodePositionTest, FindsNewCodePositionWithInserts) {
- Replacements Replaces;
- Replaces.insert(Replacement("", 4, 0, "\"\n\""));
+ Replacements Replaces = toReplacements({Replacement("", 4, 0, "\"\n\"")});
// Assume '"12345678"' is turned into '"1234"\n"5678"'.
- EXPECT_EQ(3u, shiftedCodePosition(Replaces, 3)); // "123|5678"
- EXPECT_EQ(7u, shiftedCodePosition(Replaces, 4)); // "1234|678"
- EXPECT_EQ(8u, shiftedCodePosition(Replaces, 5)); // "12345|78"
+ EXPECT_EQ(3u, Replaces.getShiftedCodePosition(3)); // "123|5678"
+ EXPECT_EQ(7u, Replaces.getShiftedCodePosition(4)); // "1234|678"
+ EXPECT_EQ(8u, Replaces.getShiftedCodePosition(5)); // "12345|78"
}
TEST(ShiftedCodePositionTest, FindsNewCodePositionInReplacedText) {
- Replacements Replaces;
// Replace the first four characters with "abcd".
- Replaces.insert(Replacement("", 0, 4, "abcd"));
+ auto Replaces = toReplacements({Replacement("", 0, 4, "abcd")});
for (unsigned i = 0; i < 3; ++i)
- EXPECT_EQ(i, shiftedCodePosition(Replaces, i));
+ EXPECT_EQ(i, Replaces.getShiftedCodePosition(i));
+}
+
+TEST(ShiftedCodePositionTest, NoReplacementText) {
+ Replacements Replaces = toReplacements({Replacement("", 0, 42, "")});
+ EXPECT_EQ(0u, Replaces.getShiftedCodePosition(0));
+ EXPECT_EQ(0u, Replaces.getShiftedCodePosition(39));
+ EXPECT_EQ(3u, Replaces.getShiftedCodePosition(45));
+ EXPECT_EQ(0u, Replaces.getShiftedCodePosition(42));
}
class FlushRewrittenFilesTest : public ::testing::Test {
@@ -305,9 +636,8 @@ public:
TEST_F(FlushRewrittenFilesTest, StoresChangesOnDisk) {
FileID ID = createFile("input.cpp", "line1\nline2\nline3\nline4");
- Replacements Replaces;
- Replaces.insert(Replacement(Context.Sources, Context.getLocation(ID, 2, 1),
- 5, "replaced"));
+ Replacements Replaces = toReplacements({Replacement(
+ Context.Sources, Context.getLocation(ID, 2, 1), 5, "replaced")});
EXPECT_TRUE(applyAllReplacements(Replaces, Context.Rewrite));
EXPECT_FALSE(Context.Rewrite.overwriteChangedFiles());
EXPECT_EQ("line1\nreplaced\nline3\nline4",
@@ -455,12 +785,11 @@ TEST(Range, contains) {
TEST(Range, CalculateRangesOfReplacements) {
// Before: aaaabbbbbbz
// After : bbbbbbzzzzzzoooooooooooooooo
- Replacements Replaces;
- Replaces.insert(Replacement("foo", 0, 4, ""));
- Replaces.insert(Replacement("foo", 10, 1, "zzzzzz"));
- Replaces.insert(Replacement("foo", 11, 0, "oooooooooooooooo"));
+ Replacements Replaces = toReplacements(
+ {Replacement("foo", 0, 4, ""), Replacement("foo", 10, 1, "zzzzzz"),
+ Replacement("foo", 11, 0, "oooooooooooooooo")});
- std::vector<Range> Ranges = calculateChangedRanges(Replaces);
+ std::vector<Range> Ranges = Replaces.getAffectedRanges();
EXPECT_EQ(2ul, Ranges.size());
EXPECT_TRUE(Ranges[0].getOffset() == 0);
@@ -469,25 +798,43 @@ TEST(Range, CalculateRangesOfReplacements) {
EXPECT_TRUE(Ranges[1].getLength() == 22);
}
+TEST(Range, CalculateRangesOfInsertionAroundReplacement) {
+ Replacements Replaces = toReplacements(
+ {Replacement("foo", 0, 2, ""), Replacement("foo", 0, 0, "ba")});
+
+ std::vector<Range> Ranges = Replaces.getAffectedRanges();
+
+ EXPECT_EQ(1ul, Ranges.size());
+ EXPECT_EQ(0u, Ranges[0].getOffset());
+ EXPECT_EQ(2u, Ranges[0].getLength());
+}
+
+TEST(Range, RangesAfterEmptyReplacements) {
+ std::vector<Range> Ranges = {Range(5, 6), Range(10, 5)};
+ Replacements Replaces;
+ std::vector<Range> Expected = {Range(5, 10)};
+ EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
+}
+
TEST(Range, RangesAfterReplacements) {
std::vector<Range> Ranges = {Range(5, 2), Range(10, 5)};
- Replacements Replaces = {Replacement("foo", 0, 2, "1234")};
+ Replacements Replaces = toReplacements({Replacement("foo", 0, 2, "1234")});
std::vector<Range> Expected = {Range(0, 4), Range(7, 2), Range(12, 5)};
EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
}
TEST(Range, RangesBeforeReplacements) {
std::vector<Range> Ranges = {Range(5, 2), Range(10, 5)};
- Replacements Replaces = {Replacement("foo", 20, 2, "1234")};
+ Replacements Replaces = toReplacements({Replacement("foo", 20, 2, "1234")});
std::vector<Range> Expected = {Range(5, 2), Range(10, 5), Range(20, 4)};
EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
}
TEST(Range, NotAffectedByReplacements) {
std::vector<Range> Ranges = {Range(0, 2), Range(5, 2), Range(10, 5)};
- Replacements Replaces = {Replacement("foo", 3, 2, "12"),
- Replacement("foo", 12, 2, "12"),
- Replacement("foo", 20, 5, "")};
+ Replacements Replaces = toReplacements({Replacement("foo", 3, 2, "12"),
+ Replacement("foo", 12, 2, "12"),
+ Replacement("foo", 20, 5, "")});
std::vector<Range> Expected = {Range(0, 2), Range(3, 4), Range(10, 5),
Range(20, 0)};
EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
@@ -495,9 +842,9 @@ TEST(Range, NotAffectedByReplacements) {
TEST(Range, RangesWithNonOverlappingReplacements) {
std::vector<Range> Ranges = {Range(0, 2), Range(5, 2), Range(10, 5)};
- Replacements Replaces = {Replacement("foo", 3, 1, ""),
- Replacement("foo", 6, 1, "123"),
- Replacement("foo", 20, 2, "12345")};
+ Replacements Replaces = toReplacements({Replacement("foo", 3, 1, ""),
+ Replacement("foo", 6, 1, "123"),
+ Replacement("foo", 20, 2, "12345")});
std::vector<Range> Expected = {Range(0, 2), Range(3, 0), Range(4, 4),
Range(11, 5), Range(21, 5)};
EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
@@ -506,9 +853,9 @@ TEST(Range, RangesWithNonOverlappingReplacements) {
TEST(Range, RangesWithOverlappingReplacements) {
std::vector<Range> Ranges = {Range(0, 2), Range(5, 2), Range(15, 5),
Range(30, 5)};
- Replacements Replaces = {
- Replacement("foo", 1, 3, ""), Replacement("foo", 6, 1, "123"),
- Replacement("foo", 13, 3, "1"), Replacement("foo", 25, 15, "")};
+ Replacements Replaces = toReplacements(
+ {Replacement("foo", 1, 3, ""), Replacement("foo", 6, 1, "123"),
+ Replacement("foo", 13, 3, "1"), Replacement("foo", 25, 15, "")});
std::vector<Range> Expected = {Range(0, 1), Range(2, 4), Range(12, 5),
Range(22, 0)};
EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
@@ -516,122 +863,52 @@ TEST(Range, RangesWithOverlappingReplacements) {
TEST(Range, MergeIntoOneRange) {
std::vector<Range> Ranges = {Range(0, 2), Range(5, 2), Range(15, 5)};
- Replacements Replaces = {Replacement("foo", 1, 15, "1234567890")};
+ Replacements Replaces =
+ toReplacements({Replacement("foo", 1, 15, "1234567890")});
std::vector<Range> Expected = {Range(0, 15)};
EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
}
TEST(Range, ReplacementsStartingAtRangeOffsets) {
std::vector<Range> Ranges = {Range(0, 2), Range(5, 5), Range(15, 5)};
- Replacements Replaces = {
- Replacement("foo", 0, 2, "12"), Replacement("foo", 5, 1, "123"),
- Replacement("foo", 7, 4, "12345"), Replacement("foo", 15, 10, "12")};
+ Replacements Replaces = toReplacements(
+ {Replacement("foo", 0, 2, "12"), Replacement("foo", 5, 1, "123"),
+ Replacement("foo", 7, 4, "12345"), Replacement("foo", 15, 10, "12")});
std::vector<Range> Expected = {Range(0, 2), Range(5, 9), Range(18, 2)};
EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
}
TEST(Range, ReplacementsEndingAtRangeEnds) {
std::vector<Range> Ranges = {Range(0, 2), Range(5, 2), Range(15, 5)};
- Replacements Replaces = {Replacement("foo", 6, 1, "123"),
- Replacement("foo", 17, 3, "12")};
+ Replacements Replaces = toReplacements(
+ {Replacement("foo", 6, 1, "123"), Replacement("foo", 17, 3, "12")});
std::vector<Range> Expected = {Range(0, 2), Range(5, 4), Range(17, 4)};
EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
}
TEST(Range, AjacentReplacements) {
std::vector<Range> Ranges = {Range(0, 0), Range(15, 5)};
- Replacements Replaces = {Replacement("foo", 1, 2, "123"),
- Replacement("foo", 12, 3, "1234")};
+ Replacements Replaces = toReplacements(
+ {Replacement("foo", 1, 2, "123"), Replacement("foo", 12, 3, "1234")});
std::vector<Range> Expected = {Range(0, 0), Range(1, 3), Range(13, 9)};
EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
}
TEST(Range, MergeRangesAfterReplacements) {
std::vector<Range> Ranges = {Range(8, 0), Range(5, 2), Range(9, 0), Range(0, 1)};
- Replacements Replaces = {Replacement("foo", 1, 3, ""),
- Replacement("foo", 7, 0, "12"), Replacement("foo", 9, 2, "")};
- std::vector<Range> Expected = {Range(0, 1), Range(2, 4), Range(7, 0), Range(8, 0)};
+ Replacements Replaces = toReplacements({Replacement("foo", 1, 3, ""),
+ Replacement("foo", 7, 0, "12"),
+ Replacement("foo", 9, 2, "")});
+ std::vector<Range> Expected = {Range(0, 1), Range(2, 4), Range(7, 0),
+ Range(8, 0)};
EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
}
-TEST(DeduplicateTest, removesDuplicates) {
- std::vector<Replacement> Input;
- Input.push_back(Replacement("fileA", 50, 0, " foo "));
- Input.push_back(Replacement("fileA", 10, 3, " bar "));
- Input.push_back(Replacement("fileA", 10, 2, " bar ")); // Length differs
- Input.push_back(Replacement("fileA", 9, 3, " bar ")); // Offset differs
- Input.push_back(Replacement("fileA", 50, 0, " foo ")); // Duplicate
- Input.push_back(Replacement("fileA", 51, 3, " bar "));
- Input.push_back(Replacement("fileB", 51, 3, " bar ")); // Filename differs!
- Input.push_back(Replacement("fileB", 60, 1, " bar "));
- Input.push_back(Replacement("fileA", 60, 2, " bar "));
- Input.push_back(Replacement("fileA", 51, 3, " moo ")); // Replacement text
- // differs!
-
- std::vector<Replacement> Expected;
- Expected.push_back(Replacement("fileA", 9, 3, " bar "));
- Expected.push_back(Replacement("fileA", 10, 2, " bar "));
- Expected.push_back(Replacement("fileA", 10, 3, " bar "));
- Expected.push_back(Replacement("fileA", 50, 0, " foo "));
- Expected.push_back(Replacement("fileA", 51, 3, " bar "));
- Expected.push_back(Replacement("fileA", 51, 3, " moo "));
- Expected.push_back(Replacement("fileB", 60, 1, " bar "));
- Expected.push_back(Replacement("fileA", 60, 2, " bar "));
-
- std::vector<Range> Conflicts; // Ignored for this test
- deduplicate(Input, Conflicts);
-
- EXPECT_EQ(3U, Conflicts.size());
- EXPECT_EQ(Expected, Input);
-}
-
-TEST(DeduplicateTest, detectsConflicts) {
- {
- std::vector<Replacement> Input;
- Input.push_back(Replacement("fileA", 0, 5, " foo "));
- Input.push_back(Replacement("fileA", 0, 5, " foo ")); // Duplicate not a
- // conflict.
- Input.push_back(Replacement("fileA", 2, 6, " bar "));
- Input.push_back(Replacement("fileA", 7, 3, " moo "));
-
- std::vector<Range> Conflicts;
- deduplicate(Input, Conflicts);
-
- // One duplicate is removed and the remaining three items form one
- // conflicted range.
- ASSERT_EQ(3u, Input.size());
- ASSERT_EQ(1u, Conflicts.size());
- ASSERT_EQ(0u, Conflicts.front().getOffset());
- ASSERT_EQ(3u, Conflicts.front().getLength());
- }
- {
- std::vector<Replacement> Input;
-
- // Expected sorted order is shown. It is the sorted order to which the
- // returned conflict info refers to.
- Input.push_back(Replacement("fileA", 0, 5, " foo ")); // 0
- Input.push_back(Replacement("fileA", 5, 5, " bar ")); // 1
- Input.push_back(Replacement("fileA", 6, 0, " bar ")); // 3
- Input.push_back(Replacement("fileA", 5, 5, " moo ")); // 2
- Input.push_back(Replacement("fileA", 7, 2, " bar ")); // 4
- Input.push_back(Replacement("fileA", 15, 5, " golf ")); // 5
- Input.push_back(Replacement("fileA", 16, 5, " bag ")); // 6
- Input.push_back(Replacement("fileA", 10, 3, " club ")); // 7
-
- // #3 is special in that it is completely contained by another conflicting
- // Replacement. #4 ensures #3 hasn't messed up the conflicting range size.
-
- std::vector<Range> Conflicts;
- deduplicate(Input, Conflicts);
-
- // No duplicates
- ASSERT_EQ(8u, Input.size());
- ASSERT_EQ(2u, Conflicts.size());
- ASSERT_EQ(1u, Conflicts[0].getOffset());
- ASSERT_EQ(4u, Conflicts[0].getLength());
- ASSERT_EQ(6u, Conflicts[1].getOffset());
- ASSERT_EQ(2u, Conflicts[1].getLength());
- }
+TEST(Range, ConflictingRangesBeforeReplacements) {
+ std::vector<Range> Ranges = {Range(8, 3), Range(5, 4), Range(9, 1)};
+ Replacements Replaces = toReplacements({Replacement("foo", 1, 3, "")});
+ std::vector<Range> Expected = {Range(1, 0), Range(2, 6)};
+ EXPECT_EQ(Expected, calculateRangesAfterReplacements(Replaces, Ranges));
}
class MergeReplacementsTest : public ::testing::Test {
@@ -647,7 +924,7 @@ protected:
EXPECT_EQ(Intermediate, *AfterFirst);
EXPECT_EQ(Result, *InSequenceRewrite);
- tooling::Replacements Merged = mergeReplacements(First, Second);
+ tooling::Replacements Merged = First.merge(Second);
auto MergedRewrite = applyAllReplacements(Code, Merged);
EXPECT_TRUE(static_cast<bool>(MergedRewrite));
EXPECT_EQ(*InSequenceRewrite, *MergedRewrite);
@@ -661,7 +938,7 @@ protected:
auto AfterFirst = applyAllReplacements(Code, First);
EXPECT_TRUE(static_cast<bool>(AfterFirst));
auto InSequenceRewrite = applyAllReplacements(*AfterFirst, Second);
- tooling::Replacements Merged = mergeReplacements(First, Second);
+ tooling::Replacements Merged = First.merge(Second);
auto MergedRewrite = applyAllReplacements(Code, Merged);
EXPECT_TRUE(static_cast<bool>(MergedRewrite));
EXPECT_EQ(*InSequenceRewrite, *MergedRewrite);
@@ -674,62 +951,142 @@ protected:
TEST_F(MergeReplacementsTest, Offsets) {
mergeAndTestRewrite("aaa", "aabab", "cacabab",
- {{"", 2, 0, "b"}, {"", 3, 0, "b"}},
- {{"", 0, 0, "c"}, {"", 1, 0, "c"}});
+ toReplacements({{"", 2, 0, "b"}, {"", 3, 0, "b"}}),
+ toReplacements({{"", 0, 0, "c"}, {"", 1, 0, "c"}}));
mergeAndTestRewrite("aaa", "babaa", "babacac",
- {{"", 0, 0, "b"}, {"", 1, 0, "b"}},
- {{"", 4, 0, "c"}, {"", 5, 0, "c"}});
- mergeAndTestRewrite("aaaa", "aaa", "aac", {{"", 1, 1, ""}},
- {{"", 2, 1, "c"}});
+ toReplacements({{"", 0, 0, "b"}, {"", 1, 0, "b"}}),
+ toReplacements({{"", 4, 0, "c"}, {"", 5, 0, "c"}}));
+ mergeAndTestRewrite("aaaa", "aaa", "aac", toReplacements({{"", 1, 1, ""}}),
+ toReplacements({{"", 2, 1, "c"}}));
mergeAndTestRewrite("aa", "bbabba", "bbabcba",
- {{"", 0, 0, "bb"}, {"", 1, 0, "bb"}}, {{"", 4, 0, "c"}});
+ toReplacements({{"", 0, 0, "bb"}, {"", 1, 0, "bb"}}),
+ toReplacements({{"", 4, 0, "c"}}));
}
TEST_F(MergeReplacementsTest, Concatenations) {
// Basic concatenations. It is important to merge these into a single
// replacement to ensure the correct order.
- EXPECT_EQ((Replacements{{"", 0, 0, "ab"}}),
- mergeReplacements({{"", 0, 0, "a"}}, {{"", 1, 0, "b"}}));
- EXPECT_EQ((Replacements{{"", 0, 0, "ba"}}),
- mergeReplacements({{"", 0, 0, "a"}}, {{"", 0, 0, "b"}}));
- mergeAndTestRewrite("", "a", "ab", {{"", 0, 0, "a"}}, {{"", 1, 0, "b"}});
- mergeAndTestRewrite("", "a", "ba", {{"", 0, 0, "a"}}, {{"", 0, 0, "b"}});
+ {
+ auto First = toReplacements({{"", 0, 0, "a"}});
+ auto Second = toReplacements({{"", 1, 0, "b"}});
+ EXPECT_EQ(toReplacements({{"", 0, 0, "ab"}}), First.merge(Second));
+ }
+ {
+ auto First = toReplacements({{"", 0, 0, "a"}});
+ auto Second = toReplacements({{"", 0, 0, "b"}});
+ EXPECT_EQ(toReplacements({{"", 0, 0, "ba"}}), First.merge(Second));
+ }
+ mergeAndTestRewrite("", "a", "ab", toReplacements({{"", 0, 0, "a"}}),
+ toReplacements({{"", 1, 0, "b"}}));
+ mergeAndTestRewrite("", "a", "ba", toReplacements({{"", 0, 0, "a"}}),
+ toReplacements({{"", 0, 0, "b"}}));
}
TEST_F(MergeReplacementsTest, NotChangingLengths) {
- mergeAndTestRewrite("aaaa", "abba", "acca", {{"", 1, 2, "bb"}},
- {{"", 1, 2, "cc"}});
- mergeAndTestRewrite("aaaa", "abba", "abcc", {{"", 1, 2, "bb"}},
- {{"", 2, 2, "cc"}});
- mergeAndTestRewrite("aaaa", "abba", "ccba", {{"", 1, 2, "bb"}},
- {{"", 0, 2, "cc"}});
+ mergeAndTestRewrite("aaaa", "abba", "acca",
+ toReplacements({{"", 1, 2, "bb"}}),
+ toReplacements({{"", 1, 2, "cc"}}));
+ mergeAndTestRewrite("aaaa", "abba", "abcc",
+ toReplacements({{"", 1, 2, "bb"}}),
+ toReplacements({{"", 2, 2, "cc"}}));
+ mergeAndTestRewrite("aaaa", "abba", "ccba",
+ toReplacements({{"", 1, 2, "bb"}}),
+ toReplacements({{"", 0, 2, "cc"}}));
mergeAndTestRewrite("aaaaaa", "abbdda", "abccda",
- {{"", 1, 2, "bb"}, {"", 3, 2, "dd"}}, {{"", 2, 2, "cc"}});
+ toReplacements({{"", 1, 2, "bb"}, {"", 3, 2, "dd"}}),
+ toReplacements({{"", 2, 2, "cc"}}));
}
TEST_F(MergeReplacementsTest, OverlappingRanges) {
mergeAndTestRewrite("aaa", "bbd", "bcbcd",
- {{"", 0, 1, "bb"}, {"", 1, 2, "d"}},
- {{"", 1, 0, "c"}, {"", 2, 0, "c"}});
+ toReplacements({{"", 0, 1, "bb"}, {"", 1, 2, "d"}}),
+ toReplacements({{"", 1, 0, "c"}, {"", 2, 0, "c"}}));
- mergeAndTestRewrite("aaaa", "aabbaa", "acccca", {{"", 2, 0, "bb"}},
- {{"", 1, 4, "cccc"}});
+ mergeAndTestRewrite("aaaa", "aabbaa", "acccca",
+ toReplacements({{"", 2, 0, "bb"}}),
+ toReplacements({{"", 1, 4, "cccc"}}));
mergeAndTestRewrite("aaaa", "aababa", "acccca",
- {{"", 2, 0, "b"}, {"", 3, 0, "b"}}, {{"", 1, 4, "cccc"}});
- mergeAndTestRewrite("aaaaaa", "abbbba", "abba", {{"", 1, 4, "bbbb"}},
- {{"", 2, 2, ""}});
- mergeAndTestRewrite("aaaa", "aa", "cc", {{"", 1, 1, ""}, {"", 2, 1, ""}},
- {{"", 0, 2, "cc"}});
- mergeAndTestRewrite("aa", "abbba", "abcbcba", {{"", 1, 0, "bbb"}},
- {{"", 2, 0, "c"}, {"", 3, 0, "c"}});
-
- mergeAndTestRewrite("aaa", "abbab", "ccdd",
- {{"", 0, 1, ""}, {"", 2, 0, "bb"}, {"", 3, 0, "b"}},
- {{"", 0, 2, "cc"}, {"", 2, 3, "dd"}});
- mergeAndTestRewrite("aa", "babbab", "ccdd",
- {{"", 0, 0, "b"}, {"", 1, 0, "bb"}, {"", 2, 0, "b"}},
- {{"", 0, 3, "cc"}, {"", 3, 3, "dd"}});
+ toReplacements({{"", 2, 0, "b"}, {"", 3, 0, "b"}}),
+ toReplacements({{"", 1, 4, "cccc"}}));
+ mergeAndTestRewrite("aaaaaa", "abbbba", "abba",
+ toReplacements({{"", 1, 4, "bbbb"}}),
+ toReplacements({{"", 2, 2, ""}}));
+ mergeAndTestRewrite("aaaa", "aa", "cc",
+ toReplacements({{"", 1, 1, ""}, {"", 2, 1, ""}}),
+ toReplacements({{"", 0, 2, "cc"}}));
+ mergeAndTestRewrite("aa", "abbba", "abcbcba",
+ toReplacements({{"", 1, 0, "bbb"}}),
+ toReplacements({{"", 2, 0, "c"}, {"", 3, 0, "c"}}));
+
+ mergeAndTestRewrite(
+ "aaa", "abbab", "ccdd",
+ toReplacements({{"", 0, 1, ""}, {"", 2, 0, "bb"}, {"", 3, 0, "b"}}),
+ toReplacements({{"", 0, 2, "cc"}, {"", 2, 3, "dd"}}));
+ mergeAndTestRewrite(
+ "aa", "babbab", "ccdd",
+ toReplacements({{"", 0, 0, "b"}, {"", 1, 0, "bb"}, {"", 2, 0, "b"}}),
+ toReplacements({{"", 0, 3, "cc"}, {"", 3, 3, "dd"}}));
+}
+
+TEST(DeduplicateByFileTest, PathsWithDots) {
+ std::map<std::string, Replacements> FileToReplaces;
+ llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> VFS(
+ new vfs::InMemoryFileSystem());
+ FileManager FileMgr(FileSystemOptions(), VFS);
+#if !defined(LLVM_ON_WIN32)
+ StringRef Path1 = "a/b/.././c.h";
+ StringRef Path2 = "a/c.h";
+#else
+ StringRef Path1 = "a\\b\\..\\.\\c.h";
+ StringRef Path2 = "a\\c.h";
+#endif
+ EXPECT_TRUE(VFS->addFile(Path1, 0, llvm::MemoryBuffer::getMemBuffer("")));
+ EXPECT_TRUE(VFS->addFile(Path2, 0, llvm::MemoryBuffer::getMemBuffer("")));
+ FileToReplaces[Path1] = Replacements();
+ FileToReplaces[Path2] = Replacements();
+ FileToReplaces = groupReplacementsByFile(FileMgr, FileToReplaces);
+ EXPECT_EQ(1u, FileToReplaces.size());
+ EXPECT_EQ(Path1, FileToReplaces.begin()->first);
+}
+
+TEST(DeduplicateByFileTest, PathWithDotSlash) {
+ std::map<std::string, Replacements> FileToReplaces;
+ llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> VFS(
+ new vfs::InMemoryFileSystem());
+ FileManager FileMgr(FileSystemOptions(), VFS);
+#if !defined(LLVM_ON_WIN32)
+ StringRef Path1 = "./a/b/c.h";
+ StringRef Path2 = "a/b/c.h";
+#else
+ StringRef Path1 = ".\\a\\b\\c.h";
+ StringRef Path2 = "a\\b\\c.h";
+#endif
+ EXPECT_TRUE(VFS->addFile(Path1, 0, llvm::MemoryBuffer::getMemBuffer("")));
+ EXPECT_TRUE(VFS->addFile(Path2, 0, llvm::MemoryBuffer::getMemBuffer("")));
+ FileToReplaces[Path1] = Replacements();
+ FileToReplaces[Path2] = Replacements();
+ FileToReplaces = groupReplacementsByFile(FileMgr, FileToReplaces);
+ EXPECT_EQ(1u, FileToReplaces.size());
+ EXPECT_EQ(Path1, FileToReplaces.begin()->first);
+}
+
+TEST(DeduplicateByFileTest, NonExistingFilePath) {
+ std::map<std::string, Replacements> FileToReplaces;
+ llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> VFS(
+ new vfs::InMemoryFileSystem());
+ FileManager FileMgr(FileSystemOptions(), VFS);
+#if !defined(LLVM_ON_WIN32)
+ StringRef Path1 = "./a/b/c.h";
+ StringRef Path2 = "a/b/c.h";
+#else
+ StringRef Path1 = ".\\a\\b\\c.h";
+ StringRef Path2 = "a\\b\\c.h";
+#endif
+ FileToReplaces[Path1] = Replacements();
+ FileToReplaces[Path2] = Replacements();
+ FileToReplaces = groupReplacementsByFile(FileMgr, FileToReplaces);
+ EXPECT_TRUE(FileToReplaces.empty());
}
} // end namespace tooling
diff --git a/unittests/Tooling/ReplacementTest.h b/unittests/Tooling/ReplacementTest.h
new file mode 100644
index 000000000000..b6fe5c79b7be
--- /dev/null
+++ b/unittests/Tooling/ReplacementTest.h
@@ -0,0 +1,56 @@
+//===- unittest/Tooling/ReplacementTest.h - Replacements related test------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines utility class and function for Replacement related tests.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_UNITTESTS_TOOLING_REPLACEMENTTESTBASE_H
+#define LLVM_CLANG_UNITTESTS_TOOLING_REPLACEMENTTESTBASE_H
+
+#include "RewriterTestContext.h"
+#include "clang/Tooling/Core/Replacement.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace tooling {
+
+/// \brief Converts a set of replacements to Replacements class.
+/// \return A Replacements class containing \p Replaces on success; otherwise,
+/// an empty Replacements is returned.
+inline tooling::Replacements
+toReplacements(const std::set<tooling::Replacement> &Replaces) {
+ tooling::Replacements Result;
+ for (const auto &R : Replaces) {
+ auto Err = Result.add(R);
+ EXPECT_TRUE(!Err);
+ if (Err) {
+ llvm::errs() << llvm::toString(std::move(Err)) << "\n";
+ return tooling::Replacements();
+ }
+ }
+ return Result;
+}
+
+/// \brief A utility class for replacement related tests.
+class ReplacementTest : public ::testing::Test {
+protected:
+ tooling::Replacement createReplacement(SourceLocation Start, unsigned Length,
+ llvm::StringRef ReplacementText) {
+ return tooling::Replacement(Context.Sources, Start, Length,
+ ReplacementText);
+ }
+
+ RewriterTestContext Context;
+};
+
+} // namespace tooling
+} // namespace clang
+
+#endif // LLVM_CLANG_UNITTESTS_TOOLING_REPLACEMENTTESTBASE_H
diff --git a/unittests/Tooling/RewriterTest.cpp b/unittests/Tooling/RewriterTest.cpp
index e8afedb01174..4305d421e1cb 100644
--- a/unittests/Tooling/RewriterTest.cpp
+++ b/unittests/Tooling/RewriterTest.cpp
@@ -39,8 +39,11 @@ TEST(Rewriter, ContinuesOverwritingFilesOnError) {
TEST(Rewriter, AdjacentInsertAndDelete) {
Replacements Replaces;
- Replaces.insert(Replacement("<file>", 6, 6, ""));
- Replaces.insert(Replacement("<file>", 6, 0, "replaced\n"));
+ auto Err = Replaces.add(Replacement("<file>", 6, 6, ""));
+ EXPECT_TRUE(!Err);
+ Replaces =
+ Replaces.merge(Replacements(Replacement("<file>", 6, 0, "replaced\n")));
+
auto Rewritten = applyAllReplacements("line1\nline2\nline3\nline4", Replaces);
EXPECT_TRUE(static_cast<bool>(Rewritten));
EXPECT_EQ("line1\nreplaced\nline3\nline4", *Rewritten);
diff --git a/unittests/Tooling/TestVisitor.h b/unittests/Tooling/TestVisitor.h
index f4a00394487b..a762ec8b1453 100644
--- a/unittests/Tooling/TestVisitor.h
+++ b/unittests/Tooling/TestVisitor.h
@@ -43,6 +43,7 @@ public:
Lang_C,
Lang_CXX98,
Lang_CXX11,
+ Lang_CXX14,
Lang_OBJC,
Lang_OBJCXX11,
Lang_CXX = Lang_CXX98
@@ -55,6 +56,7 @@ public:
case Lang_C: Args.push_back("-std=c99"); break;
case Lang_CXX98: Args.push_back("-std=c++98"); break;
case Lang_CXX11: Args.push_back("-std=c++11"); break;
+ case Lang_CXX14: Args.push_back("-std=c++14"); break;
case Lang_OBJC: Args.push_back("-ObjC"); break;
case Lang_OBJCXX11:
Args.push_back("-ObjC++");
@@ -127,9 +129,12 @@ public:
/// \brief Expect 'Match' to occur at the given 'Line' and 'Column'.
///
/// Any number of expected matches can be set by calling this repeatedly.
- /// Each is expected to be matched exactly once.
- void ExpectMatch(Twine Match, unsigned Line, unsigned Column) {
- ExpectedMatches.push_back(ExpectedMatch(Match, Line, Column));
+ /// Each is expected to be matched 'Times' number of times. (This is useful in
+ /// cases in which different AST nodes can match at the same source code
+ /// location.)
+ void ExpectMatch(Twine Match, unsigned Line, unsigned Column,
+ unsigned Times = 1) {
+ ExpectedMatches.push_back(ExpectedMatch(Match, Line, Column, Times));
}
/// \brief Checks that all expected matches have been found.
@@ -200,14 +205,17 @@ protected:
};
struct ExpectedMatch {
- ExpectedMatch(Twine Name, unsigned LineNumber, unsigned ColumnNumber)
- : Candidate(Name, LineNumber, ColumnNumber), Found(false) {}
+ ExpectedMatch(Twine Name, unsigned LineNumber, unsigned ColumnNumber,
+ unsigned Times)
+ : Candidate(Name, LineNumber, ColumnNumber), TimesExpected(Times),
+ TimesSeen(0) {}
void UpdateFor(StringRef Name, FullSourceLoc Location, SourceManager &SM) {
if (Candidate.Matches(Name, Location)) {
- EXPECT_TRUE(!Found);
- Found = true;
- } else if (!Found && Candidate.PartiallyMatches(Name, Location)) {
+ EXPECT_LT(TimesSeen, TimesExpected);
+ ++TimesSeen;
+ } else if (TimesSeen < TimesExpected &&
+ Candidate.PartiallyMatches(Name, Location)) {
llvm::raw_string_ostream Stream(PartialMatches);
Stream << ", partial match: \"" << Name << "\" at ";
Location.print(Stream, SM);
@@ -215,7 +223,7 @@ protected:
}
void ExpectFound() const {
- EXPECT_TRUE(Found)
+ EXPECT_EQ(TimesExpected, TimesSeen)
<< "Expected \"" << Candidate.ExpectedName
<< "\" at " << Candidate.LineNumber
<< ":" << Candidate.ColumnNumber << PartialMatches;
@@ -223,7 +231,8 @@ protected:
MatchCandidate Candidate;
std::string PartialMatches;
- bool Found;
+ unsigned TimesExpected;
+ unsigned TimesSeen;
};
std::vector<MatchCandidate> DisallowedMatches;
diff --git a/unittests/Tooling/ToolingTest.cpp b/unittests/Tooling/ToolingTest.cpp
index 10ac0c33ed85..68b5ed21059b 100644
--- a/unittests/Tooling/ToolingTest.cpp
+++ b/unittests/Tooling/ToolingTest.cpp
@@ -18,8 +18,9 @@
#include "clang/Tooling/Tooling.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Config/llvm-config.h"
-#include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/Path.h"
#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Support/TargetSelect.h"
#include "gtest/gtest.h"
#include <algorithm>
#include <string>
@@ -331,6 +332,44 @@ TEST(runToolOnCodeWithArgs, TestNoDepFile) {
EXPECT_FALSE(llvm::sys::fs::remove(DepFilePath.str()));
}
+struct CheckColoredDiagnosticsAction : public clang::ASTFrontendAction {
+ CheckColoredDiagnosticsAction(bool ShouldShowColor)
+ : ShouldShowColor(ShouldShowColor) {}
+ std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &Compiler,
+ StringRef) override {
+ if (Compiler.getDiagnosticOpts().ShowColors != ShouldShowColor)
+ Compiler.getDiagnostics().Report(
+ Compiler.getDiagnostics().getCustomDiagID(
+ DiagnosticsEngine::Fatal,
+ "getDiagnosticOpts().ShowColors != ShouldShowColor"));
+ return llvm::make_unique<ASTConsumer>();
+ }
+
+private:
+ bool ShouldShowColor = true;
+};
+
+TEST(runToolOnCodeWithArgs, DiagnosticsColor) {
+
+ EXPECT_TRUE(runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(true), "",
+ {"-fcolor-diagnostics"}));
+ EXPECT_TRUE(runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(false),
+ "", {"-fno-color-diagnostics"}));
+ EXPECT_TRUE(
+ runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(true), "",
+ {"-fno-color-diagnostics", "-fcolor-diagnostics"}));
+ EXPECT_TRUE(
+ runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(false), "",
+ {"-fcolor-diagnostics", "-fno-color-diagnostics"}));
+ EXPECT_TRUE(runToolOnCodeWithArgs(
+ new CheckColoredDiagnosticsAction(true), "",
+ {"-fno-color-diagnostics", "-fdiagnostics-color=always"}));
+
+ // Check that this test would fail if ShowColors is not what it should.
+ EXPECT_FALSE(runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(false),
+ "", {"-fcolor-diagnostics"}));
+}
+
TEST(ClangToolTest, ArgumentAdjusters) {
FixedCompilationDatabase Compilations("/", std::vector<std::string>());
diff --git a/unittests/libclang/LibclangTest.cpp b/unittests/libclang/LibclangTest.cpp
index d5c78272af54..f2a96d6be6c1 100644
--- a/unittests/libclang/LibclangTest.cpp
+++ b/unittests/libclang/LibclangTest.cpp
@@ -14,6 +14,9 @@
#include "llvm/Support/raw_ostream.h"
#include "gtest/gtest.h"
#include <fstream>
+#include <functional>
+#include <map>
+#include <memory>
#include <set>
#define DEBUG_TYPE "libclang-test"
@@ -349,21 +352,25 @@ TEST(libclang, ModuleMapDescriptor) {
clang_ModuleMapDescriptor_dispose(MMD);
}
-class LibclangReparseTest : public ::testing::Test {
+class LibclangParseTest : public ::testing::Test {
std::set<std::string> Files;
+ typedef std::unique_ptr<std::string> fixed_addr_string;
+ std::map<fixed_addr_string, fixed_addr_string> UnsavedFileContents;
public:
std::string TestDir;
CXIndex Index;
CXTranslationUnit ClangTU;
unsigned TUFlags;
+ std::vector<CXUnsavedFile> UnsavedFiles;
void SetUp() override {
llvm::SmallString<256> Dir;
ASSERT_FALSE(llvm::sys::fs::createUniqueDirectory("libclang-test", Dir));
TestDir = Dir.str();
TUFlags = CXTranslationUnit_DetailedPreprocessingRecord |
- clang_defaultEditingTranslationUnitOptions();
+ clang_defaultEditingTranslationUnitOptions();
Index = clang_createIndex(0, 0);
+ ClangTU = nullptr;
}
void TearDown() override {
clang_disposeTranslationUnit(ClangTU);
@@ -384,6 +391,77 @@ public:
OS << Contents;
assert(OS.good());
}
+ void MapUnsavedFile(std::string Filename, const std::string &Contents) {
+ if (!llvm::sys::path::is_absolute(Filename)) {
+ llvm::SmallString<256> Path(TestDir);
+ llvm::sys::path::append(Path, Filename);
+ Filename = Path.str();
+ }
+ auto it = UnsavedFileContents.insert(std::make_pair(
+ fixed_addr_string(new std::string(Filename)),
+ fixed_addr_string(new std::string(Contents))));
+ UnsavedFiles.push_back({
+ it.first->first->c_str(), // filename
+ it.first->second->c_str(), // contents
+ it.first->second->size() // length
+ });
+ }
+ template<typename F>
+ void Traverse(const F &TraversalFunctor) {
+ CXCursor TuCursor = clang_getTranslationUnitCursor(ClangTU);
+ std::reference_wrapper<const F> FunctorRef = std::cref(TraversalFunctor);
+ clang_visitChildren(TuCursor,
+ &TraverseStateless<std::reference_wrapper<const F>>,
+ &FunctorRef);
+ }
+private:
+ template<typename TState>
+ static CXChildVisitResult TraverseStateless(CXCursor cx, CXCursor parent,
+ CXClientData data) {
+ TState *State = static_cast<TState*>(data);
+ return State->get()(cx, parent);
+ }
+};
+
+TEST_F(LibclangParseTest, AllSkippedRanges) {
+ std::string Header = "header.h", Main = "main.cpp";
+ WriteFile(Header,
+ "#ifdef MANGOS\n"
+ "printf(\"mmm\");\n"
+ "#endif");
+ WriteFile(Main,
+ "#include \"header.h\"\n"
+ "#ifdef KIWIS\n"
+ "printf(\"mmm!!\");\n"
+ "#endif");
+
+ ClangTU = clang_parseTranslationUnit(Index, Main.c_str(), nullptr, 0,
+ nullptr, 0, TUFlags);
+
+ CXSourceRangeList *Ranges = clang_getAllSkippedRanges(ClangTU);
+ EXPECT_EQ(2U, 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(4U, line);
+
+ clang_disposeSourceRangeList(Ranges);
+}
+
+class LibclangReparseTest : public LibclangParseTest {
+public:
void DisplayDiagnostics() {
unsigned NumDiagnostics = clang_getNumDiagnostics(ClangTU);
for (unsigned i = 0; i < NumDiagnostics; ++i) {
diff --git a/utils/TableGen/ClangASTNodesEmitter.cpp b/utils/TableGen/ClangASTNodesEmitter.cpp
index b17a4a374a29..b132dcbead5c 100644
--- a/utils/TableGen/ClangASTNodesEmitter.cpp
+++ b/utils/TableGen/ClangASTNodesEmitter.cpp
@@ -47,7 +47,7 @@ class ClangASTNodesEmitter {
if (&R == &Root && !BaseSuffix.empty())
return BaseSuffix;
- return R.getName() + BaseSuffix;
+ return R.getName().str() + BaseSuffix;
}
std::pair<Record *, Record *> EmitNode (const ChildMap &Tree, raw_ostream& OS,
diff --git a/utils/TableGen/ClangAttrEmitter.cpp b/utils/TableGen/ClangAttrEmitter.cpp
index 50102af33a5a..d65794e86374 100644
--- a/utils/TableGen/ClangAttrEmitter.cpp
+++ b/utils/TableGen/ClangAttrEmitter.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/STLExtras.h"
@@ -120,12 +121,8 @@ static std::string WritePCHRecord(StringRef type, StringRef name) {
// underscores. For example, __foo, foo__, __foo__ would
// become foo.
static StringRef NormalizeAttrName(StringRef AttrName) {
- if (AttrName.startswith("__"))
- AttrName = AttrName.substr(2, AttrName.size());
-
- if (AttrName.endswith("__"))
- AttrName = AttrName.substr(0, AttrName.size() - 2);
-
+ AttrName.consume_front("__");
+ AttrName.consume_back("__");
return AttrName;
}
@@ -299,7 +296,13 @@ namespace {
OS << "\" << get" << getUpperName()
<< "()->getNameInfo().getAsString() << \"";
} else if (type == "IdentifierInfo *") {
- OS << "\" << get" << getUpperName() << "()->getName() << \"";
+ OS << "\";\n";
+ if (isOptional())
+ OS << " if (get" << getUpperName() << "()) ";
+ else
+ OS << " ";
+ OS << "OS << get" << getUpperName() << "()->getName();\n";
+ OS << " OS << \"";
} else if (type == "TypeSourceInfo *") {
OS << "\" << get" << getUpperName() << "().getAsString() << \"";
} else {
@@ -717,13 +720,10 @@ namespace {
std::vector<std::string>
uniqueEnumsInOrder(const std::vector<std::string> &enums) {
std::vector<std::string> uniques;
- std::set<std::string> unique_set(enums.begin(), enums.end());
+ SmallDenseSet<StringRef, 8> unique_set;
for (const auto &i : enums) {
- auto set_i = unique_set.find(i);
- if (set_i != unique_set.end()) {
+ if (unique_set.insert(i).second)
uniques.push_back(i);
- unique_set.erase(set_i);
- }
}
return uniques;
}
@@ -835,7 +835,7 @@ namespace {
OS << " static const char *Convert" << type << "ToStr("
<< type << " Val) {\n"
<< " switch(Val) {\n";
- std::set<std::string> Uniques;
+ SmallDenseSet<StringRef, 8> Uniques;
for (size_t I = 0; I < enums.size(); ++I) {
if (Uniques.insert(enums[I]).second)
OS << " case " << getAttrName() << "Attr::" << enums[I]
@@ -943,7 +943,7 @@ namespace {
OS << " static const char *Convert" << type << "ToStr("
<< type << " Val) {\n"
<< " switch(Val) {\n";
- std::set<std::string> Uniques;
+ SmallDenseSet<StringRef, 8> Uniques;
for (size_t I = 0; I < enums.size(); ++I) {
if (Uniques.insert(enums[I]).second)
OS << " case " << getAttrName() << "Attr::" << enums[I]
@@ -1312,6 +1312,9 @@ writePrettyPrintFunction(Record &R,
} else if (Variety == "Declspec") {
Prefix = " __declspec(";
Suffix = ")";
+ } else if (Variety == "Microsoft") {
+ Prefix = "[";
+ Suffix = "]";
} else if (Variety == "Keyword") {
Prefix = " ";
Suffix = "";
@@ -1344,11 +1347,8 @@ writePrettyPrintFunction(Record &R,
// Fake arguments aren't part of the parsed form and should not be
// pretty-printed.
- bool hasNonFakeArgs = false;
- for (const auto &arg : Args) {
- if (arg->isFake()) continue;
- hasNonFakeArgs = true;
- }
+ 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
@@ -1408,18 +1408,20 @@ getSpellingListIndex(const std::vector<FlattenedSpelling> &SpellingList,
static void writeAttrAccessorDefinition(const Record &R, raw_ostream &OS) {
std::vector<Record*> Accessors = R.getValueAsListOfDefs("Accessors");
+ if (Accessors.empty())
+ return;
+
+ const std::vector<FlattenedSpelling> SpellingList = GetFlattenedSpellings(R);
+ assert(!SpellingList.empty() &&
+ "Attribute with empty spelling list can't have accessors!");
for (const auto *Accessor : Accessors) {
std::string Name = Accessor->getValueAsString("Name");
- std::vector<FlattenedSpelling> Spellings =
- GetFlattenedSpellings(*Accessor);
- std::vector<FlattenedSpelling> SpellingList = GetFlattenedSpellings(R);
- assert(!SpellingList.empty() &&
- "Attribute with empty spelling list can't have accessors!");
+ std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Accessor);
OS << " bool " << Name << "() const { return SpellingListIndex == ";
for (unsigned Index = 0; Index < Spellings.size(); ++Index) {
OS << getSpellingListIndex(SpellingList, Spellings[Index]);
- if (Index != Spellings.size() -1)
+ if (Index != Spellings.size() - 1)
OS << " ||\n SpellingListIndex == ";
else
OS << "; }\n";
@@ -1521,6 +1523,16 @@ static void emitClangAttrLateParsedList(RecordKeeper &Records, raw_ostream &OS)
OS << "#endif // CLANG_ATTR_LATE_PARSED_LIST\n\n";
}
+template <typename Fn>
+static void forEachUniqueSpelling(const Record &Attr, Fn &&F) {
+ std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
+ SmallDenseSet<StringRef, 8> Seen;
+ for (const FlattenedSpelling &S : Spellings) {
+ if (Seen.insert(S.name()).second)
+ F(S);
+ }
+}
+
/// \brief 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";
@@ -1536,12 +1548,9 @@ static void emitClangAttrTypeArgList(RecordKeeper &Records, raw_ostream &OS) {
continue;
// All these spellings take a single type argument.
- std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Attr);
- std::set<std::string> Emitted;
- for (const auto &S : Spellings) {
- if (Emitted.insert(S.name()).second)
- OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n";
- }
+ forEachUniqueSpelling(*Attr, [&](const FlattenedSpelling &S) {
+ OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n";
+ });
}
OS << "#endif // CLANG_ATTR_TYPE_ARG_LIST\n\n";
}
@@ -1558,12 +1567,9 @@ static void emitClangAttrArgContextList(RecordKeeper &Records, raw_ostream &OS)
continue;
// All these spellings take are parsed unevaluated.
- std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
- std::set<std::string> Emitted;
- for (const auto &S : Spellings) {
- if (Emitted.insert(S.name()).second)
- OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n";
- }
+ forEachUniqueSpelling(Attr, [&](const FlattenedSpelling &S) {
+ OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n";
+ });
}
OS << "#endif // CLANG_ATTR_ARG_CONTEXT_LIST\n\n";
}
@@ -1589,12 +1595,9 @@ static void emitClangAttrIdentifierArgList(RecordKeeper &Records, raw_ostream &O
continue;
// All these spellings take an identifier argument.
- std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Attr);
- std::set<std::string> Emitted;
- for (const auto &S : Spellings) {
- if (Emitted.insert(S.name()).second)
- OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n";
- }
+ forEachUniqueSpelling(*Attr, [&](const FlattenedSpelling &S) {
+ OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n";
+ });
}
OS << "#endif // CLANG_ATTR_IDENTIFIER_ARG_LIST\n\n";
}
@@ -1882,8 +1885,7 @@ static void emitAttrList(raw_ostream &OS, StringRef Class,
// Determines if an attribute has a Pragma spelling.
static bool AttrHasPragmaSpelling(const Record *R) {
std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*R);
- return std::find_if(Spellings.begin(), Spellings.end(),
- [](const FlattenedSpelling &S) {
+ return llvm::find_if(Spellings, [](const FlattenedSpelling &S) {
return S.variety() == "Pragma";
}) != Spellings.end();
}
@@ -2295,7 +2297,7 @@ void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
// Separate all of the attributes out into four group: generic, C++11, GNU,
// and declspecs. Then generate a big switch statement for each of them.
std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
- std::vector<Record *> Declspec, GNU, Pragma;
+ std::vector<Record *> Declspec, Microsoft, GNU, Pragma;
std::map<std::string, std::vector<Record *>> CXX;
// Walk over the list of all attributes, and split them out based on the
@@ -2308,6 +2310,8 @@ void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
GNU.push_back(R);
else if (Variety == "Declspec")
Declspec.push_back(R);
+ else if (Variety == "Microsoft")
+ Microsoft.push_back(R);
else if (Variety == "CXX11")
CXX[SI.nameSpace()].push_back(R);
else if (Variety == "Pragma")
@@ -2323,6 +2327,9 @@ void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
OS << "case AttrSyntax::Declspec:\n";
OS << " return llvm::StringSwitch<int>(Name)\n";
GenerateHasAttrSpellingStringSwitch(Declspec, OS, "Declspec");
+ OS << "case AttrSyntax::Microsoft:\n";
+ OS << " return llvm::StringSwitch<int>(Name)\n";
+ GenerateHasAttrSpellingStringSwitch(Microsoft, OS, "Microsoft");
OS << "case AttrSyntax::Pragma:\n";
OS << " return llvm::StringSwitch<int>(Name)\n";
GenerateHasAttrSpellingStringSwitch(Pragma, OS, "Pragma");
@@ -2361,8 +2368,9 @@ void EmitClangAttrSpellingListIndex(RecordKeeper &Records, raw_ostream &OS) {
.Case("GNU", 0)
.Case("CXX11", 1)
.Case("Declspec", 2)
- .Case("Keyword", 3)
- .Case("Pragma", 4)
+ .Case("Microsoft", 3)
+ .Case("Keyword", 4)
+ .Case("Pragma", 5)
.Default(0)
<< " && Scope == \"" << Spellings[I].nameSpace() << "\")\n"
<< " return " << I << ";\n";
@@ -2532,6 +2540,10 @@ static void emitArgInfo(const Record &R, std::stringstream &OS) {
unsigned ArgCount = 0, OptCount = 0;
bool HasVariadic = false;
for (const auto *Arg : Args) {
+ // If the arg is fake, it's the user's job to supply it: general parsing
+ // logic shouldn't need to know anything about it.
+ if (Arg->getValueAsBit("Fake"))
+ continue;
Arg->getValueAsBit("Optional") ? ++OptCount : ++ArgCount;
if (!HasVariadic && isArgVariadic(*Arg, R.getName()))
HasVariadic = true;
@@ -2675,7 +2687,7 @@ static std::string CalculateDiagnostic(const Record &S) {
}
static std::string GetSubjectWithSuffix(const Record *R) {
- std::string B = R->getName();
+ const std::string &B = R->getName();
if (B == "DeclBase")
return "Decl";
return B + "Decl";
@@ -2683,7 +2695,7 @@ static std::string GetSubjectWithSuffix(const Record *R) {
static std::string GenerateCustomAppertainsTo(const Record &Subject,
raw_ostream &OS) {
- std::string FnName = "is" + Subject.getName();
+ std::string FnName = "is" + Subject.getName().str();
// If this code has already been generated, simply return the previous
// instance of it.
@@ -2732,7 +2744,7 @@ static std::string GenerateAppertainsTo(const Record &Attr, raw_ostream &OS) {
// Otherwise, generate an appertainsTo check specific to this attribute which
// checks all of the given subjects against the Decl passed in. Return the
// name of that check to the caller.
- std::string FnName = "check" + Attr.getName() + "AppertainsTo";
+ std::string FnName = "check" + Attr.getName().str() + "AppertainsTo";
std::stringstream SS;
SS << "static bool " << FnName << "(Sema &S, const AttributeList &Attr, ";
SS << "const Decl *D) {\n";
@@ -2790,8 +2802,10 @@ static std::string GenerateLangOptRequirements(const Record &R,
std::string FnName = "check", Test;
for (auto I = LangOpts.begin(), E = LangOpts.end(); I != E; ++I) {
std::string Part = (*I)->getValueAsString("Name");
- if ((*I)->getValueAsBit("Negated"))
+ if ((*I)->getValueAsBit("Negated")) {
+ FnName += "Not";
Test += "!";
+ }
Test += "S.LangOpts." + Part;
if (I + 1 != E)
Test += " || ";
@@ -2853,7 +2867,7 @@ static std::string GenerateTargetRequirements(const Record &Attr,
if (I.first == APK) {
std::vector<std::string> DA = I.second->getValueAsDef("Target")
->getValueAsListOfStrings("Arches");
- std::copy(DA.begin(), DA.end(), std::back_inserter(Arches));
+ std::move(DA.begin(), DA.end(), std::back_inserter(Arches));
}
}
}
@@ -2901,7 +2915,7 @@ static std::string GenerateSpellingIndexToSemanticSpelling(const Record &Attr,
// Generate the enumeration we will use for the mapping.
SemanticSpellingMap SemanticToSyntacticMap;
std::string Enum = CreateSemanticSpellings(Spellings, SemanticToSyntacticMap);
- std::string Name = Attr.getName() + "AttrSpellingMap";
+ std::string Name = Attr.getName().str() + "AttrSpellingMap";
OS << "static unsigned " << Name << "(const AttributeList &Attr) {\n";
OS << Enum;
@@ -2915,12 +2929,9 @@ static std::string GenerateSpellingIndexToSemanticSpelling(const Record &Attr,
static bool IsKnownToGCC(const Record &Attr) {
// Look at the spellings for this subject; if there are any spellings which
// claim to be known to GCC, the attribute is known to GCC.
- std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
- for (const auto &I : Spellings) {
- if (I.knownToGCC())
- return true;
- }
- return false;
+ return llvm::any_of(
+ GetFlattenedSpellings(Attr),
+ [](const FlattenedSpelling &S) { return S.knownToGCC(); });
}
/// Emits the parsed attribute helpers
@@ -2982,7 +2993,8 @@ void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) {
emitSourceFileHeader("Attribute name matcher", OS);
std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
- std::vector<StringMatcher::StringPair> GNU, Declspec, CXX11, Keywords, Pragma;
+ std::vector<StringMatcher::StringPair> GNU, Declspec, Microsoft, CXX11,
+ Keywords, Pragma;
std::set<std::string> Seen;
for (const auto *A : Attrs) {
const Record &Attr = *A;
@@ -3024,6 +3036,8 @@ void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) {
Matches = &GNU;
else if (Variety == "Declspec")
Matches = &Declspec;
+ else if (Variety == "Microsoft")
+ Matches = &Microsoft;
else if (Variety == "Keyword")
Matches = &Keywords;
else if (Variety == "Pragma")
@@ -3048,6 +3062,8 @@ void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) {
StringMatcher("Name", GNU, OS).Emit();
OS << " } else if (AttributeList::AS_Declspec == Syntax) {\n";
StringMatcher("Name", Declspec, OS).Emit();
+ OS << " } else if (AttributeList::AS_Microsoft == Syntax) {\n";
+ StringMatcher("Name", Microsoft, OS).Emit();
OS << " } else if (AttributeList::AS_CXX11 == Syntax) {\n";
StringMatcher("Name", CXX11, OS).Emit();
OS << " } else if (AttributeList::AS_Keyword == Syntax || ";
@@ -3131,8 +3147,9 @@ enum SpellingKind {
GNU = 1 << 0,
CXX11 = 1 << 1,
Declspec = 1 << 2,
- Keyword = 1 << 3,
- Pragma = 1 << 4
+ Microsoft = 1 << 3,
+ Keyword = 1 << 4,
+ Pragma = 1 << 5
};
static void WriteDocumentation(const DocumentationData &Doc,
@@ -3180,6 +3197,7 @@ static void WriteDocumentation(const DocumentationData &Doc,
.Case("GNU", GNU)
.Case("CXX11", CXX11)
.Case("Declspec", Declspec)
+ .Case("Microsoft", Microsoft)
.Case("Keyword", Keyword)
.Case("Pragma", Pragma);
diff --git a/utils/TableGen/ClangDiagnosticsEmitter.cpp b/utils/TableGen/ClangDiagnosticsEmitter.cpp
index bbc2bdb065fe..cad08afd846f 100644
--- a/utils/TableGen/ClangDiagnosticsEmitter.cpp
+++ b/utils/TableGen/ClangDiagnosticsEmitter.cpp
@@ -14,14 +14,12 @@
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/PointerUnion.h"
-#include "llvm/ADT/SetVector.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/Compiler.h"
-#include "llvm/Support/Debug.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/StringToOffsetTable.h"
@@ -145,6 +143,11 @@ static bool beforeThanCompare(const Record *LHS, const Record *RHS) {
LHS->getLoc().front().getPointer() < RHS->getLoc().front().getPointer();
}
+static bool diagGroupBeforeByName(const Record *LHS, const Record *RHS) {
+ return LHS->getValueAsString("GroupName") <
+ RHS->getValueAsString("GroupName");
+}
+
static bool beforeThanCompareGroups(const GroupInfo *LHS, const GroupInfo *RHS){
assert(!LHS->DiagsInGroup.empty() && !RHS->DiagsInGroup.empty());
return beforeThanCompare(LHS->DiagsInGroup.front(),
@@ -896,4 +899,444 @@ void EmitClangDiagsIndexName(RecordKeeper &Records, raw_ostream &OS) {
OS << "DIAG_NAME_INDEX(" << R.Name << ")\n";
}
}
+
+//===----------------------------------------------------------------------===//
+// Diagnostic documentation generation
+//===----------------------------------------------------------------------===//
+
+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;
+
+ std::function<void(StringRef)> Visit = [&](StringRef GroupName) {
+ auto &GroupInfo = DiagsInGroup.find(GroupName)->second;
+ for (const Record *Diag : GroupInfo.DiagsInGroup)
+ (isRemark(*Diag) ? AnyRemarks : AnyNonRemarks) = true;
+ for (const auto &Name : GroupInfo.SubGroups)
+ Visit(Name);
+ };
+ Visit(DiagGroup->getValueAsString("GroupName"));
+
+ if (AnyRemarks && AnyNonRemarks)
+ PrintFatalError(
+ DiagGroup->getLoc(),
+ "Diagnostic group contains both remark and non-remark diagnostics");
+ return AnyRemarks;
+}
+
+std::string getDefaultSeverity(const Record *Diag) {
+ return Diag->getValueAsDef("DefaultSeverity")->getValueAsString("Name");
+}
+
+std::set<std::string>
+getDefaultSeverities(const Record *DiagGroup,
+ const std::map<std::string, GroupInfo> &DiagsInGroup) {
+ std::set<std::string> States;
+
+ std::function<void(StringRef)> Visit = [&](StringRef GroupName) {
+ auto &GroupInfo = DiagsInGroup.find(GroupName)->second;
+ for (const Record *Diag : GroupInfo.DiagsInGroup)
+ States.insert(getDefaultSeverity(Diag));
+ for (const auto &Name : GroupInfo.SubGroups)
+ Visit(Name);
+ };
+ Visit(DiagGroup->getValueAsString("GroupName"));
+ return States;
+}
+
+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) {
+ 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);
+ for (auto &Line : Out)
+ OS << Line << "\n";
+ OS << "\n";
+ }
+}
+
+} // namespace
+} // namespace docs
+
+void EmitClangDiagDocs(RecordKeeper &Records, raw_ostream &OS) {
+ using namespace docs;
+
+ // Get the documentation introduction paragraph.
+ const Record *Documentation = Records.getDef("GlobalDocumentation");
+ if (!Documentation) {
+ PrintFatalError("The Documentation top-level definition is missing, "
+ "no documentation will be generated.");
+ return;
+ }
+
+ OS << Documentation->getValueAsString("Intro") << "\n";
+
+ std::vector<Record*> Diags =
+ Records.getAllDerivedDefinitions("Diagnostic");
+ std::vector<Record*> DiagGroups =
+ Records.getAllDerivedDefinitions("DiagGroup");
+ std::sort(DiagGroups.begin(), DiagGroups.end(), diagGroupBeforeByName);
+
+ DiagGroupParentMap DGParentMap(Records);
+
+ std::map<std::string, GroupInfo> DiagsInGroup;
+ groupDiagnostics(Diags, DiagGroups, DiagsInGroup);
+
+ // Compute the set of diagnostics that are in -Wpedantic.
+ {
+ RecordSet DiagsInPedanticSet;
+ RecordSet GroupsInPedanticSet;
+ InferPedantic inferPedantic(DGParentMap, Diags, DiagGroups, DiagsInGroup);
+ inferPedantic.compute(&DiagsInPedanticSet, &GroupsInPedanticSet);
+ auto &PedDiags = DiagsInGroup["pedantic"];
+ // Put the diagnostics into a deterministic order.
+ RecordVec DiagsInPedantic(DiagsInPedanticSet.begin(),
+ DiagsInPedanticSet.end());
+ RecordVec GroupsInPedantic(GroupsInPedanticSet.begin(),
+ GroupsInPedanticSet.end());
+ std::sort(DiagsInPedantic.begin(), DiagsInPedantic.end(),
+ beforeThanCompare);
+ std::sort(GroupsInPedantic.begin(), GroupsInPedantic.end(),
+ beforeThanCompare);
+ PedDiags.DiagsInGroup.insert(PedDiags.DiagsInGroup.end(),
+ DiagsInPedantic.begin(),
+ DiagsInPedantic.end());
+ for (auto *Group : GroupsInPedantic)
+ PedDiags.SubGroups.push_back(Group->getValueAsString("GroupName"));
+ }
+
+ // FIXME: Write diagnostic categories and link to diagnostic groups in each.
+
+ // Write out the diagnostic groups.
+ for (const Record *G : DiagGroups) {
+ bool IsRemarkGroup = isRemarkGroup(G, DiagsInGroup);
+ auto &GroupInfo = DiagsInGroup[G->getValueAsString("GroupName")];
+ bool IsSynonym = GroupInfo.DiagsInGroup.empty() &&
+ GroupInfo.SubGroups.size() == 1;
+
+ writeHeader((IsRemarkGroup ? "-R" : "-W") +
+ G->getValueAsString("GroupName"),
+ OS);
+
+ if (!IsSynonym) {
+ // FIXME: Ideally, all the diagnostics in a group should have the same
+ // default state, but that is not currently the case.
+ auto DefaultSeverities = getDefaultSeverities(G, DiagsInGroup);
+ if (!DefaultSeverities.empty() && !DefaultSeverities.count("Ignored")) {
+ bool AnyNonErrors = DefaultSeverities.count("Warning") ||
+ DefaultSeverities.count("Remark");
+ if (!AnyNonErrors)
+ OS << "This diagnostic is an error by default, but the flag ``-Wno-"
+ << G->getValueAsString("GroupName") << "`` can be used to disable "
+ << "the error.\n\n";
+ else
+ OS << "This diagnostic is enabled by default.\n\n";
+ } else if (DefaultSeverities.size() > 1) {
+ OS << "Some of the diagnostics controlled by this flag are enabled "
+ << "by default.\n\n";
+ }
+ }
+
+ if (!GroupInfo.SubGroups.empty()) {
+ if (IsSynonym)
+ OS << "Synonym for ";
+ else if (GroupInfo.DiagsInGroup.empty())
+ OS << "Controls ";
+ else
+ OS << "Also controls ";
+
+ bool First = true;
+ std::sort(GroupInfo.SubGroups.begin(), GroupInfo.SubGroups.end());
+ for (const auto &Name : GroupInfo.SubGroups) {
+ if (!First) OS << ", ";
+ OS << "`" << (IsRemarkGroup ? "-R" : "-W") << Name << "`_";
+ First = false;
+ }
+ OS << ".\n\n";
+ }
+
+ if (!GroupInfo.DiagsInGroup.empty()) {
+ OS << "**Diagnostic text:**\n\n";
+ for (const Record *D : GroupInfo.DiagsInGroup) {
+ auto Severity = getDefaultSeverity(D);
+ Severity[0] = tolower(Severity[0]);
+ if (Severity == "ignored")
+ Severity = IsRemarkGroup ? "remark" : "warning";
+ writeDiagnosticText(Severity, D->getValueAsString("Text"), OS);
+ }
+ }
+
+ auto Doc = G->getValueAsString("Documentation");
+ if (!Doc.empty())
+ OS << Doc;
+ else if (GroupInfo.SubGroups.empty() && GroupInfo.DiagsInGroup.empty())
+ OS << "This diagnostic flag exists for GCC compatibility, and has no "
+ "effect in Clang.\n";
+ OS << "\n";
+ }
+}
+
} // end namespace clang
diff --git a/utils/TableGen/NeonEmitter.cpp b/utils/TableGen/NeonEmitter.cpp
index b5313a073d16..49c1edce3220 100644
--- a/utils/TableGen/NeonEmitter.cpp
+++ b/utils/TableGen/NeonEmitter.cpp
@@ -24,24 +24,32 @@
//
//===----------------------------------------------------------------------===//
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/None.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/SetTheory.h"
-#include "llvm/TableGen/TableGenBackend.h"
#include <algorithm>
+#include <cassert>
+#include <cctype>
+#include <cstddef>
+#include <cstdint>
#include <deque>
#include <map>
+#include <set>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
+
using namespace llvm;
namespace {
@@ -76,6 +84,7 @@ enum ClassKind {
/// builtins. These must be kept in sync with the flags in
/// include/clang/Basic/TargetBuiltins.h.
namespace NeonTypeFlags {
+
enum { EltTypeMask = 0xf, UnsignedFlag = 0x10, QuadFlag = 0x20 };
enum EltType {
@@ -91,12 +100,10 @@ enum EltType {
Float32,
Float64
};
-}
-class Intrinsic;
+} // end namespace NeonTypeFlags
+
class NeonEmitter;
-class Type;
-class Variable;
//===----------------------------------------------------------------------===//
// TypeSpec
@@ -192,6 +199,7 @@ public:
//
void makeUnsigned() { Signed = false; }
void makeSigned() { Signed = true; }
+
void makeInteger(unsigned ElemWidth, bool Sign) {
Float = false;
Poly = false;
@@ -199,6 +207,7 @@ public:
Immediate = false;
ElementBitwidth = ElemWidth;
}
+
void makeImmediate(unsigned ElemWidth) {
Float = false;
Poly = false;
@@ -206,18 +215,22 @@ public:
Immediate = true;
ElementBitwidth = ElemWidth;
}
+
void makeScalar() {
Bitwidth = ElementBitwidth;
NumVectors = 0;
}
+
void makeOneVector() {
assert(isVector());
NumVectors = 1;
}
+
void doubleLanes() {
assert_with_loc(Bitwidth != 128, "Can't get bigger than 128!");
Bitwidth = 128;
}
+
void halveLanes() {
assert_with_loc(Bitwidth != 64, "Can't get smaller than 64!");
Bitwidth = 64;
@@ -369,6 +382,7 @@ public:
bool hasImmediate() const {
return Proto.find('i') != std::string::npos;
}
+
/// Return the parameter index of the immediate operand.
unsigned getImmediateIdx() const {
assert(hasImmediate());
@@ -379,6 +393,7 @@ public:
/// Return true if the intrinsic takes an splat operand.
bool hasSplat() const { return Proto.find('a') != std::string::npos; }
+
/// Return the parameter index of the splat operand.
unsigned getSplatIdx() const {
assert(hasSplat());
@@ -414,7 +429,7 @@ public:
return Idx;
}
- bool hasBody() const { return Body && Body->getValues().size() > 0; }
+ bool hasBody() const { return Body && !Body->getValues().empty(); }
void setNeededEarly() { NeededEarly = true; }
@@ -487,7 +502,6 @@ private:
std::pair<Type, std::string> emitDagOp(DagInit *DI);
std::pair<Type, std::string> emitDag(DagInit *DI);
};
-
};
//===----------------------------------------------------------------------===//
@@ -1071,7 +1085,7 @@ std::string Intrinsic::mangleName(std::string Name, ClassKind LocalCK) const {
Name == "vcvt_f32_f64" || Name == "vcvt_f64_f32")
return Name;
- if (typeCode.size() > 0) {
+ if (!typeCode.empty()) {
// If the name ends with _xN (N = 2,3,4), insert the typeCode before _xN.
if (Name.size() >= 3 && isdigit(Name.back()) &&
Name[Name.length() - 2] == 'x' && Name[Name.length() - 3] == '_')
@@ -1246,7 +1260,6 @@ void Intrinsic::emitReturnReversal() {
emitReverseVariable(RetVar, RetVar);
}
-
void Intrinsic::emitShadowedArgs() {
// Macro arguments are not type-checked like inline function arguments,
// so assign them to local temporaries to get the right type checking.
@@ -1397,7 +1410,7 @@ void Intrinsic::emitBody(StringRef CallPrefix) {
emitNewLine();
}
- if (!Body || Body->getValues().size() == 0) {
+ if (!Body || Body->getValues().empty()) {
// Nothing specific to output - must output a builtin.
emitBodyAsBuiltinCall();
return;
@@ -1465,14 +1478,14 @@ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagOp(DagInit *DI) {
if (DI->getNumArgs() == 2) {
// Unary op.
std::pair<Type, std::string> R =
- emitDagArg(DI->getArg(1), DI->getArgName(1));
+ emitDagArg(DI->getArg(1), DI->getArgNameStr(1));
return std::make_pair(R.first, Op + R.second);
} else {
assert(DI->getNumArgs() == 3 && "Can only handle unary and binary ops!");
std::pair<Type, std::string> R1 =
- emitDagArg(DI->getArg(1), DI->getArgName(1));
+ emitDagArg(DI->getArg(1), DI->getArgNameStr(1));
std::pair<Type, std::string> R2 =
- emitDagArg(DI->getArg(2), DI->getArgName(2));
+ emitDagArg(DI->getArg(2), DI->getArgNameStr(2));
assert_with_loc(R1.first == R2.first, "Argument type mismatch!");
return std::make_pair(R1.first, R1.second + " " + Op + " " + R2.second);
}
@@ -1483,7 +1496,7 @@ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagCall(DagInit *DI) {
std::vector<std::string> Values;
for (unsigned I = 0; I < DI->getNumArgs() - 1; ++I) {
std::pair<Type, std::string> R =
- emitDagArg(DI->getArg(I + 1), DI->getArgName(I + 1));
+ emitDagArg(DI->getArg(I + 1), DI->getArgNameStr(I + 1));
Types.push_back(R.first);
Values.push_back(R.second);
}
@@ -1516,7 +1529,8 @@ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagCast(DagInit *DI,
bool IsBitCast){
// (cast MOD* VAL) -> cast VAL to type given by MOD.
std::pair<Type, std::string> R = emitDagArg(
- DI->getArg(DI->getNumArgs() - 1), DI->getArgName(DI->getNumArgs() - 1));
+ DI->getArg(DI->getNumArgs() - 1),
+ DI->getArgNameStr(DI->getNumArgs() - 1));
Type castToType = R.first;
for (unsigned ArgIdx = 0; ArgIdx < DI->getNumArgs() - 1; ++ArgIdx) {
@@ -1527,11 +1541,11 @@ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagCast(DagInit *DI,
// 4. The value "U" or "S" to switch the signedness.
// 5. The value "H" or "D" to half or double the bitwidth.
// 6. The value "8" to convert to 8-bit (signed) integer lanes.
- if (DI->getArgName(ArgIdx).size()) {
- assert_with_loc(Intr.Variables.find(DI->getArgName(ArgIdx)) !=
+ if (!DI->getArgNameStr(ArgIdx).empty()) {
+ assert_with_loc(Intr.Variables.find(DI->getArgNameStr(ArgIdx)) !=
Intr.Variables.end(),
"Variable not found");
- castToType = Intr.Variables[DI->getArgName(ArgIdx)].getType();
+ castToType = Intr.Variables[DI->getArgNameStr(ArgIdx)].getType();
} else {
StringInit *SI = dyn_cast<StringInit>(DI->getArg(ArgIdx));
assert_with_loc(SI, "Expected string type or $Name for cast type");
@@ -1589,6 +1603,7 @@ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagShuffle(DagInit *DI){
Elts.insert(Elts2.begin(), Elts2.begin() + (Elts2.size() / 2));
}
};
+
class HighHalf : public SetTheory::Operator {
public:
void apply(SetTheory &ST, DagInit *Expr, SetTheory::RecSet &Elts,
@@ -1598,11 +1613,13 @@ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagShuffle(DagInit *DI){
Elts.insert(Elts2.begin() + (Elts2.size() / 2), Elts2.end());
}
};
+
class Rev : public SetTheory::Operator {
unsigned ElementSize;
public:
Rev(unsigned ElementSize) : ElementSize(ElementSize) {}
+
void apply(SetTheory &ST, DagInit *Expr, SetTheory::RecSet &Elts,
ArrayRef<SMLoc> Loc) override {
SetTheory::RecSet Elts2;
@@ -1621,11 +1638,13 @@ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagShuffle(DagInit *DI){
Elts.insert(Revved.begin(), Revved.end());
}
};
+
class MaskExpander : public SetTheory::Expander {
unsigned N;
public:
MaskExpander(unsigned N) : N(N) {}
+
void expand(SetTheory &ST, Record *R, SetTheory::RecSet &Elts) override {
unsigned Addend = 0;
if (R->getName() == "mask0")
@@ -1641,9 +1660,9 @@ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagShuffle(DagInit *DI){
// (shuffle arg1, arg2, sequence)
std::pair<Type, std::string> Arg1 =
- emitDagArg(DI->getArg(0), DI->getArgName(0));
+ emitDagArg(DI->getArg(0), DI->getArgNameStr(0));
std::pair<Type, std::string> Arg2 =
- emitDagArg(DI->getArg(1), DI->getArgName(1));
+ emitDagArg(DI->getArg(1), DI->getArgNameStr(1));
assert_with_loc(Arg1.first == Arg2.first,
"Different types in arguments to shuffle!");
@@ -1685,7 +1704,8 @@ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagShuffle(DagInit *DI){
std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagDup(DagInit *DI) {
assert_with_loc(DI->getNumArgs() == 1, "dup() expects one argument");
- std::pair<Type, std::string> A = emitDagArg(DI->getArg(0), DI->getArgName(0));
+ std::pair<Type, std::string> A = emitDagArg(DI->getArg(0),
+ DI->getArgNameStr(0));
assert_with_loc(A.first.isScalar(), "dup() expects a scalar argument");
Type T = Intr.getBaseType();
@@ -1703,8 +1723,10 @@ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagDup(DagInit *DI) {
std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagSplat(DagInit *DI) {
assert_with_loc(DI->getNumArgs() == 2, "splat() expects two arguments");
- std::pair<Type, std::string> A = emitDagArg(DI->getArg(0), DI->getArgName(0));
- std::pair<Type, std::string> B = emitDagArg(DI->getArg(1), DI->getArgName(1));
+ std::pair<Type, std::string> A = emitDagArg(DI->getArg(0),
+ DI->getArgNameStr(0));
+ std::pair<Type, std::string> B = emitDagArg(DI->getArg(1),
+ DI->getArgNameStr(1));
assert_with_loc(B.first.isScalar(),
"splat() requires a scalar int as the second argument");
@@ -1720,13 +1742,15 @@ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagSplat(DagInit *DI) {
std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagSaveTemp(DagInit *DI) {
assert_with_loc(DI->getNumArgs() == 2, "save_temp() expects two arguments");
- std::pair<Type, std::string> A = emitDagArg(DI->getArg(1), DI->getArgName(1));
+ std::pair<Type, std::string> A = emitDagArg(DI->getArg(1),
+ DI->getArgNameStr(1));
assert_with_loc(!A.first.isVoid(),
"Argument to save_temp() must have non-void type!");
- std::string N = DI->getArgName(0);
- assert_with_loc(N.size(), "save_temp() expects a name as the first argument");
+ std::string N = DI->getArgNameStr(0);
+ assert_with_loc(!N.empty(),
+ "save_temp() expects a name as the first argument");
assert_with_loc(Intr.Variables.find(N) == Intr.Variables.end(),
"Variable already defined!");
@@ -1762,7 +1786,7 @@ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagLiteral(DagInit *DI){
std::pair<Type, std::string>
Intrinsic::DagEmitter::emitDagArg(Init *Arg, std::string ArgName) {
- if (ArgName.size()) {
+ if (!ArgName.empty()) {
assert_with_loc(!Arg->isComplete(),
"Arguments must either be DAGs or names, not both!");
assert_with_loc(Intr.Variables.find(ArgName) != Intr.Variables.end(),
@@ -1900,7 +1924,7 @@ Intrinsic &NeonEmitter::getIntrinsic(StringRef Name, ArrayRef<Type> Types) {
GoodVec.push_back(&I);
}
- assert_with_loc(GoodVec.size() > 0,
+ assert_with_loc(!GoodVec.empty(),
"No compatible intrinsic found - " + ErrMsg);
assert_with_loc(GoodVec.size() == 1, "Multiple overloads found - " + ErrMsg);
@@ -2157,9 +2181,9 @@ NeonEmitter::genIntrinsicRangeCheckCode(raw_ostream &OS,
OS << "case NEON::BI__builtin_neon_" << Def->getMangledName() << ": "
<< "i = " << Idx << ";";
- if (LowerBound.size())
+ if (!LowerBound.empty())
OS << " l = " << LowerBound << ";";
- if (UpperBound.size())
+ if (!UpperBound.empty())
OS << " u = " << UpperBound << ";";
OS << " break;\n";
@@ -2350,7 +2374,7 @@ void NeonEmitter::run(raw_ostream &OS) {
// 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 = "";
+ std::string InGuard;
while (!Defs.empty() && MadeProgress) {
MadeProgress = false;
@@ -2393,13 +2417,17 @@ void NeonEmitter::run(raw_ostream &OS) {
}
namespace clang {
+
void EmitNeon(RecordKeeper &Records, raw_ostream &OS) {
NeonEmitter(Records).run(OS);
}
+
void EmitNeonSema(RecordKeeper &Records, raw_ostream &OS) {
NeonEmitter(Records).runHeader(OS);
}
+
void EmitNeonTest(RecordKeeper &Records, raw_ostream &OS) {
llvm_unreachable("Neon test generation no longer implemented!");
}
-} // End namespace clang
+
+} // end namespace clang
diff --git a/utils/TableGen/TableGen.cpp b/utils/TableGen/TableGen.cpp
index 7ccd7150319e..6fb5b00c4bac 100644
--- a/utils/TableGen/TableGen.cpp
+++ b/utils/TableGen/TableGen.cpp
@@ -13,7 +13,6 @@
#include "TableGenBackends.h" // Declares all backends.
#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Signals.h"
#include "llvm/TableGen/Error.h"
@@ -53,7 +52,8 @@ enum ActionType {
GenArmNeon,
GenArmNeonSema,
GenArmNeonTest,
- GenAttrDocs
+ GenAttrDocs,
+ GenDiagDocs
};
namespace {
@@ -134,7 +134,8 @@ cl::opt<ActionType> Action(
"Generate ARM NEON tests for clang"),
clEnumValN(GenAttrDocs, "gen-attr-docs",
"Generate attribute documentation"),
- clEnumValEnd));
+ clEnumValN(GenDiagDocs, "gen-diag-docs",
+ "Generate attribute documentation")));
cl::opt<std::string>
ClangComponent("clang-component",
@@ -234,6 +235,9 @@ bool ClangTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
case GenAttrDocs:
EmitClangAttrDocs(Records, OS);
break;
+ case GenDiagDocs:
+ EmitClangDiagDocs(Records, OS);
+ break;
}
return false;
diff --git a/utils/TableGen/TableGenBackends.h b/utils/TableGen/TableGenBackends.h
index 4adf368cbd56..0305ed1c8c8f 100644
--- a/utils/TableGen/TableGenBackends.h
+++ b/utils/TableGen/TableGenBackends.h
@@ -69,6 +69,7 @@ void EmitNeonSema2(RecordKeeper &Records, raw_ostream &OS);
void EmitNeonTest2(RecordKeeper &Records, raw_ostream &OS);
void EmitClangAttrDocs(RecordKeeper &Records, raw_ostream &OS);
+void EmitClangDiagDocs(RecordKeeper &Records, raw_ostream &OS);
} // end namespace clang
diff --git a/utils/analyzer/SATestBuild.py b/utils/analyzer/SATestBuild.py
index ab68518b5ac4..18c5393988ae 100644
--- a/utils/analyzer/SATestBuild.py
+++ b/utils/analyzer/SATestBuild.py
@@ -660,11 +660,17 @@ def testProject(ID, ProjectBuildMode, IsReferenceBuild=False, Dir=None, Strictne
print "Completed tests for project %s (time: %.2f)." % \
(ID, (time.time()-TBegin))
+def isCommentCSVLine(Entries):
+ # Treat CSV lines starting with a '#' as a comment.
+ return len(Entries) > 0 and Entries[0].startswith("#")
+
def testAll(IsReferenceBuild = False, UpdateSVN = False, Strictness = 0):
PMapFile = open(getProjectMapPath(), "rb")
try:
# Validate the input.
for I in csv.reader(PMapFile):
+ if (isCommentCSVLine(I)):
+ continue
if (len(I) != 2) :
print "Error: Rows in the ProjectMapFile should have 3 entries."
raise Exception()
@@ -682,6 +688,8 @@ def testAll(IsReferenceBuild = False, UpdateSVN = False, Strictness = 0):
# Test the projects.
PMapFile.seek(0)
for I in csv.reader(PMapFile):
+ if isCommentCSVLine(I):
+ continue;
testProject(I[0], int(I[1]), IsReferenceBuild, None, Strictness)
# Add reference results to SVN.
diff --git a/utils/clang-completion-mode.el b/utils/clang-completion-mode.el
deleted file mode 100644
index 6cf5cb574519..000000000000
--- a/utils/clang-completion-mode.el
+++ /dev/null
@@ -1,249 +0,0 @@
-;;; Clang Code-Completion minor mode, for use with C/Objective-C/C++.
-
-;;; Commentary:
-
-;; This minor mode uses Clang's command line interface for code
-;; completion to provide code completion results for C, Objective-C,
-;; and C++ source files. When enabled, Clang will provide
-;; code-completion results in a secondary buffer based on the code
-;; being typed. For example, after typing "struct " (triggered via the
-;; space), Clang will provide the names of all structs visible from
-;; the current scope. After typing "p->" (triggered via the ">"),
-;; Clang will provide the names of all of the members of whatever
-;; class/struct/union "p" points to. Note that this minor mode isn't
-;; meant for serious use: it is meant to help experiment with code
-;; completion based on Clang. It needs your help to make it better!
-;;
-;; To use the Clang code completion mode, first make sure that the
-;; "clang" variable below refers to the "clang" executable,
-;; which is typically installed in libexec/. Then, place
-;; clang-completion-mode.el somewhere in your Emacs load path. You can
-;; add a new load path to Emacs by adding some like the following to
-;; your .emacs:
-;;
-;; (setq load-path (cons "~/.emacs.d" load-path))
-;;
-;; Then, use
-;;
-;; M-x load-library
-;;
-;; to load the library in your Emacs session or add the following to
-;; your .emacs to always load this mode (not recommended):
-;;
-;; (load-library "clang-completion-mode")
-;;
-;; Once you have done this, you can set various parameters with
-;;
-;; M-x customize-group RET clang-completion-mode RET
-;;
-;; Finally, to try Clang-based code completion in a particular buffer,
-;; use M-x clang-completion-mode. When "Clang" shows up in the mode
-;; line, Clang's code-completion is enabled.
-;;
-;; Clang's code completion is based on parsing the complete source
-;; file up to the point where the cursor is located. Therefore, Clang
-;; needs all of the various compilation flags (include paths, dialect
-;; options, etc.) to provide code-completion results. Currently, these
-;; need to be placed into the clang-flags variable in a format
-;; acceptable to clang. This is a hack: patches are welcome to
-;; improve the interface between this Emacs mode and Clang!
-;;
-
-;;; Code:
-;;; The clang executable
-(defcustom clang "clang"
- "The location of the Clang compiler executable"
- :type 'file
- :group 'clang-completion-mode)
-
-;;; Extra compilation flags to pass to clang.
-(defcustom clang-flags nil
- "Extra flags to pass to the Clang executable.
-This variable will typically contain include paths, e.g., -I~/MyProject."
- :type '(repeat (string :tag "Argument" ""))
- :group 'clang-completion-mode)
-
-;;; The prefix header to use with Clang code completion.
-(setq clang-completion-prefix-header "")
-
-;;; The substring we will use to filter completion results
-(setq clang-completion-substring "")
-
-;;; The current completion buffer
-(setq clang-completion-buffer nil)
-
-(setq clang-result-string "")
-
-;;; Compute the current line in the buffer
-(defun current-line ()
- "Return the vertical position of point..."
- (+ (count-lines (point-min) (point))
- (if (= (current-column) 0) 1 0)
- -1))
-
-;;; Set the Clang prefix header
-(defun clang-prefix-header ()
- (interactive)
- (setq clang-completion-prefix-header
- (read-string "Clang prefix header> " "" clang-completion-prefix-header
- "")))
-
-;; Process "filter" that keeps track of the code-completion results
-;; produced. We store all of the results in a string, then the
-;; sentinel processes the entire string at once.
-(defun clang-completion-stash-filter (proc string)
- (setq clang-result-string (concat clang-result-string string)))
-
-;; Filter the given list based on a predicate.
-(defun filter (condp lst)
- (delq nil
- (mapcar (lambda (x) (and (funcall condp x) x)) lst)))
-
-;; Determine whether FIXME: explain better
-(defun is-completion-line (line)
- (or (string-match "OVERLOAD:" line)
- (string-match (concat "COMPLETION: " clang-completion-substring) line)))
-
-
-;; re-process the completions when further input narrows the field
-(defun clang-completion-display (buffer)
- (fill-buffer buffer))
-
-(defun fill-buffer (buffer)
- (let* ((all-lines (split-string clang-result-string "\n"))
- (completion-lines (filter 'is-completion-line all-lines)))
- (if (consp completion-lines)
- (progn
- ;; Erase the process buffer.
- (let ((cur (current-buffer)))
- (set-buffer buffer)
- (goto-char (point-min))
- (erase-buffer)
- (set-buffer cur))
-
- ;; Display the process buffer.
- (display-buffer buffer)
-
- ;; Insert the code-completion string into the process buffer.
- (with-current-buffer buffer
- (insert (mapconcat 'identity completion-lines "\n")))
- ))))
-
-;; Process "sentinel" that, on successful code completion, replaces the
-;; contents of the code-completion buffer with the new code-completion results
-;; and ensures that the buffer is visible.
-(defun clang-completion-sentinel (proc event)
- (fill-buffer (process-buffer proc)))
-
-(defun clang-complete ()
- (let* ((cc-point (concat (buffer-file-name)
- ":"
- (number-to-string (+ 1 (current-line)))
- ":"
- (number-to-string (+ 1 (current-column)))))
- (cc-pch (if (equal clang-completion-prefix-header "") nil
- (list "-include-pch"
- (concat clang-completion-prefix-header ".pch"))))
- (cc-flags (if (listp clang-flags) clang-flags nil))
- (cc-command (append `(,clang "-cc1" "-fsyntax-only")
- cc-flags
- cc-pch
- `("-code-completion-at" ,cc-point)
- (list (buffer-file-name))))
- (cc-buffer-name (concat "*Clang Completion for " (buffer-name) "*")))
- ;; Start the code-completion process.
- (if (buffer-file-name)
- (progn
- ;; If there is already a code-completion process, kill it first.
- (let ((cc-proc (get-process "Clang Code-Completion")))
- (if cc-proc
- (delete-process cc-proc)))
-
- (setq clang-completion-substring "")
- (setq clang-result-string "")
- (setq clang-completion-buffer cc-buffer-name)
-
- (let ((cc-proc (apply 'start-process
- (append (list "Clang Code-Completion" cc-buffer-name)
- cc-command))))
- (set-process-filter cc-proc 'clang-completion-stash-filter)
- (set-process-sentinel cc-proc 'clang-completion-sentinel)
- )))))
-
-;; Code-completion when one of the trigger characters is typed into
-;; the buffer, e.g., '(', ',' or '.'.
-(defun clang-complete-self-insert (arg)
- (interactive "p")
- (self-insert-command arg)
- (save-buffer)
- (clang-complete))
-
-;; When the user has typed a character that requires the filter to be
-;; updated, do so (and update the display of results).
-(defun clang-update-filter ()
- (setq clang-completion-substring (thing-at-point 'symbol))
- (if (get-process "Clang Code-Completion")
- ()
- (clang-completion-display clang-completion-buffer)
- ))
-
-;; Invoked when the user types an alphanumeric character or "_" to
-;; update the filter for the currently-active code completion.
-(defun clang-filter-self-insert (arg)
- (interactive "p")
- (self-insert-command arg)
- (clang-update-filter)
- )
-
-;; Invoked when the user types the backspace key to update the filter
-;; for the currently-active code completion.
-(defun clang-backspace ()
- (interactive)
- (delete-backward-char 1)
- (clang-update-filter))
-
-;; Invoked when the user types the delete key to update the filter
-;; for the currently-active code completion.
-(defun clang-delete ()
- (interactive)
- (delete-backward-char 1)
- (clang-update-filter))
-
-;; Set up the keymap for the Clang minor mode.
-(defvar clang-completion-mode-map nil
- "Keymap for Clang Completion Mode.")
-
-(if (null clang-completion-mode-map)
- (fset 'clang-completion-mode-map
- (setq clang-completion-mode-map (make-sparse-keymap))))
-
-(if (not (assq 'clang-completion-mode minor-mode-map-alist))
- (setq minor-mode-map-alist
- (cons (cons 'clang-completion-mode clang-completion-mode-map)
- minor-mode-map-alist)))
-
-;; Punctuation characters trigger code completion.
-(dolist (char '("(" "," "." ">" ":" "=" ")" " "))
- (define-key clang-completion-mode-map char 'clang-complete-self-insert))
-
-;; Alphanumeric characters (and "_") filter the results of the
-;; currently-active code completion.
-(dolist (char '("A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M" "N" "O"
- "P" "Q" "R" "S" "T" "U" "V" "W" "X" "Y" "Z"
- "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o"
- "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z"
- "_" "0" "1" "2" "3" "4" "5" "6" "7" "8" "9"))
- (define-key clang-completion-mode-map char 'clang-filter-self-insert))
-
-;; Delete and backspace filter the results of the currently-active
-;; code completion.
-(define-key clang-completion-mode-map [(backspace)] 'clang-backspace)
-(define-key clang-completion-mode-map [(delete)] 'clang-delete)
-
-;; Set up the Clang minor mode.
-(define-minor-mode clang-completion-mode
- "Clang code-completion mode"
- nil
- " Clang"
- clang-completion-mode-map)
-
diff --git a/utils/perf-training/CMakeLists.txt b/utils/perf-training/CMakeLists.txt
index 07d90246107b..c046a1dac40b 100644
--- a/utils/perf-training/CMakeLists.txt
+++ b/utils/perf-training/CMakeLists.txt
@@ -40,7 +40,7 @@ if(LLVM_BUILD_INSTRUMENTED)
endif()
find_program(DTRACE dtrace)
-if(DTRACE)
+if(APPLE AND DTRACE)
configure_lit_site_cfg(
${CMAKE_CURRENT_SOURCE_DIR}/order-files.lit.site.cfg.in
${CMAKE_CURRENT_BINARY_DIR}/order-files/lit.site.cfg
@@ -56,6 +56,10 @@ if(DTRACE)
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/perf-helper.py clean ${CMAKE_CURRENT_BINARY_DIR} dtrace
COMMENT "Clearing old dtrace data")
+ if(NOT CLANG_ORDER_FILE)
+ message(FATAL_ERROR "Output clang order file is not set")
+ endif()
+
add_custom_target(generate-order-file
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/perf-helper.py gen-order-file --binary $<TARGET_FILE:clang> --output ${CLANG_ORDER_FILE} ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "Generating order file"
diff --git a/utils/perf-training/order-files.lit.cfg b/utils/perf-training/order-files.lit.cfg
index 75501f8c6297..e38d264595b6 100644
--- a/utils/perf-training/order-files.lit.cfg
+++ b/utils/perf-training/order-files.lit.cfg
@@ -30,6 +30,11 @@ config.suffixes = ['.c', '.cpp', '.m', '.mm', '.cu', '.ll', '.cl', '.s', '.S', '
dtrace_wrapper = '%s %s/perf-helper.py dtrace' % (config.python_exe, config.test_source_root)
dtrace_wrapper_cc1 = '%s %s/perf-helper.py dtrace --cc1' % (config.python_exe, config.test_source_root)
+if 'darwin' in config.target_triple:
+ lit_config.note('using DTrace oneshot probe')
+ dtrace_wrapper = '%s --use-oneshot' % dtrace_wrapper
+ dtrace_wrapper_cc1 = '%s --use-oneshot' % dtrace_wrapper_cc1
+
use_lit_shell = os.environ.get("LIT_USE_INTERNAL_SHELL")
config.test_format = lit.formats.ShTest(use_lit_shell == "0")
config.substitutions.append( ('%clang_cpp_skip_driver', ' %s %s --driver-mode=cpp %s ' % (dtrace_wrapper_cc1, config.clang, sysroot_flags)))
diff --git a/utils/perf-training/perf-helper.py b/utils/perf-training/perf-helper.py
index c7c4bddf8957..30b9caeffd58 100644
--- a/utils/perf-training/perf-helper.py
+++ b/utils/perf-training/perf-helper.py
@@ -75,7 +75,7 @@ def dtrace(args):
target = "oneshot$target:::entry"
else:
target = "pid$target:::entry"
- predicate = '%s/probemod=="%s"/' % (target, os.path.basename(args[0]))
+ predicate = '%s/probemod=="%s"/' % (target, os.path.basename(cmd[0]))
log_timestamp = 'printf("dtrace-TS: %d\\n", timestamp)'
if opts.use_ustack:
action = 'ustack(1);'
@@ -102,6 +102,7 @@ def dtrace(args):
start_time = time.time()
with open("%d.dtrace" % os.getpid(), "w") as f:
+ f.write("### Command: %s" % dtrace_args)
subprocess.check_call(dtrace_args, stdout=f, stderr=subprocess.PIPE)
elapsed = time.time() - start_time
diff --git a/www/analyzer/alpha_checks.html b/www/analyzer/alpha_checks.html
index 6f5e4f170801..0312d16aced4 100644
--- a/www/analyzer/alpha_checks.html
+++ b/www/analyzer/alpha_checks.html
@@ -26,13 +26,14 @@ Patches welcome!
<ul>
<li><a href="#core_alpha_checkers">Core Alpha Checkers</a></li>
<li><a href="#cplusplus_alpha_checkers">C++ Alpha Checkers</a></li>
+<li><a href="#valist_alpha_checkers">Variable Argument Alpha Checkers</a></li>
<li><a href="#deadcode_alpha_checkers">Dead Code Alpha Checkers</a></li>
<li><a href="#osx_alpha_checkers">OS X Alpha Checkers</a></li>
<li><a href="#security_alpha_checkers">Security Alpha Checkers</a></li>
<li><a href="#unix_alpha_checkers">Unix Alpha Checkers</a></li>
</ul>
-<!------------------------------ core alpha ----------------------------------->
+<!-- ============================= core alpha ============================= -->
<h3 id="core_alpha_checkers">Core Alpha Checkers</h3>
<table class="checkers">
<colgroup><col class="namedescr"><col class="example"></colgroup>
@@ -179,7 +180,7 @@ int test(struct s *p) {
</tbody></table>
-<!--------------------------- cplusplus alpha --------------------------------->
+<!-- =========================== cplusplus alpha =========================== -->
<h3 id="cplusplus_alpha_checkers">C++ Alpha Checkers</h3>
<table class="checkers">
<colgroup><col class="namedescr"><col class="example"></colgroup>
@@ -226,7 +227,76 @@ public:
</tbody></table>
-<!--------------------------- dead code alpha --------------------------------->
+
+
+<!-- =============================== va_list =============================== -->
+<h3 id="valist_alpha_checkers">Variable Argument Alpha Checkers</h3>
+<table class="checkers">
+<colgroup><col class="namedescr"><col class="example"></colgroup>
+<thead><tr><td>Name, Description</td><td>Example</td></tr></thead>
+
+<tbody>
+<tr><td><div class="namedescr expandable"><span class="name">
+alpha.valist.CopyToSelf</span><span class="lang">
+(C)</span><div class="descr">
+Calls to the <code>va_copy</code> macro should not copy onto itself.</div></div></td>
+<td><div class="exampleContainer expandable">
+<div class="example"><pre>
+#include &lt;stdarg.h&gt;
+
+void test(int x, ...) {
+ va_list args;
+ va_start(args, x);
+ va_copy(args, args); // warn
+ va_end(args);
+}
+</pre></div></div></td></tr>
+
+<tr><td><div class="namedescr expandable"><span class="name">
+alpha.valist.Uninitialized</span><span class="lang">
+(C)</span><div class="descr">
+Calls to the <code>va_arg</code>, <code>va_copy</code>, or
+<code>va_end</code> macro must happen after calling <code>va_start</code> and
+before calling <code>va_end</code>.</div></div></td>
+<td><div class="exampleContainer expandable">
+<div class="example"><pre>
+#include &lt;stdarg.h&gt;
+
+void test(int x, ...) {
+ va_list args;
+ int y = va_arg(args, int); // warn
+}
+</pre></div>
+<div class="example"><pre>
+#include &lt;stdarg.h&gt;
+
+void test(int x, ...) {
+ va_list args;
+ va_start(args, x);
+ va_end(args);
+ int z = va_arg(args, int); // warn
+}
+</pre></div></div></td></tr>
+
+<tr><td><div class="namedescr expandable"><span class="name">
+alpha.valist.Unterminated</span><span class="lang">
+(C)</span><div class="descr">
+Every <code>va_start</code> must be matched by a <code>va_end</code>. A va_list
+can only be ended once.</div></div></td>
+<td><div class="exampleContainer expandable">
+<div class="example"><pre>
+#include &lt;stdarg.h&gt;
+
+void test(int x, ...) {
+ va_list args;
+ va_start(args, x);
+ int y = x + va_arg(args, int);
+} // warn: missing va_end
+</pre></div></div></td></tr>
+
+</tbody></table>
+
+<!-- =========================== dead code alpha =========================== -->
<h3 id="deadcode_alpha_checkers">Dead Code Alpha Checkers</h3>
<table class="checkers">
<colgroup><col class="namedescr"><col class="example"></colgroup>
@@ -267,7 +337,7 @@ void test(id x) {
</pre></div></div></td></tr>
</tbody></table>
-<!---------------------------- OS X alpha -------------------------------------->
+<!-- ============================== OS X alpha ============================== -->
<h3 id="osx_alpha_checkers">OS X Alpha Checkers</h3>
<table class="checkers">
<colgroup><col class="namedescr"><col class="example"></colgroup>
@@ -433,7 +503,7 @@ invalidatable instance variables.</div></div></td>
</tbody></table>
-<!------------------------- security alpha ------------------------------------>
+<!-- =========================== security alpha =========================== -->
<h3 id="security_alpha_checkers">Security Alpha Checkers</h3>
<table class="checkers">
<colgroup><col class="namedescr"><col class="example"></colgroup>
@@ -584,7 +654,7 @@ void test() {
</tbody></table>
-<!--------------------------- unix alpha -------------------------------------->
+<!-- ============================= unix alpha ============================= -->
<h3 id="unix_alpha_checkers">Unix Alpha Checkers</h3>
<table class="checkers">
<colgroup><col class="namedescr"><col class="example"></colgroup>
diff --git a/www/analyzer/annotations.html b/www/analyzer/annotations.html
index ca6a185c1d9b..693331ae35b6 100644
--- a/www/analyzer/annotations.html
+++ b/www/analyzer/annotations.html
@@ -434,7 +434,7 @@ to the given function or method. The CoreFoundation framework defines a macro
<p>Operationally this attribute is nearly identical to 'ns_consumed' with the
main difference that the reference count decrement still occurs when using
-Objective-C garbage collection (which is import for Core Foundation types,
+Objective-C garbage collection (which is important for Core Foundation types,
which are not automatically garbage collected).</p>
<p><b>Example</b></p>
diff --git a/www/analyzer/checker_dev_manual.html b/www/analyzer/checker_dev_manual.html
index c674a74284b4..93c98913fdc2 100644
--- a/www/analyzer/checker_dev_manual.html
+++ b/www/analyzer/checker_dev_manual.html
@@ -45,7 +45,13 @@ for developer guidelines and send your questions and proposals to
<li><a href="#bugs">Bug Reports</a></li>
<li><a href="#ast">AST Visitors</a></li>
<li><a href="#testing">Testing</a></li>
- <li><a href="#commands">Useful Commands/Debugging Hints</a></li>
+ <li><a href="#commands">Useful Commands/Debugging Hints</a>
+ <ul>
+ <li><a href="#attaching">Attaching the Debugger</a></li>
+ <li><a href="#narrowing">Narrowing Down the Problem</a></li>
+ <li><a href="#visualizing">Visualizing the Analysis</a></li>
+ <li><a href="#debugprints">Debug Prints and Tricks</a></li>
+ </ul></li>
<li><a href="#additioninformation">Additional Sources of Information</a></li>
<li><a href="#links">Useful Links</a></li>
</ul>
@@ -115,6 +121,8 @@ for developer guidelines and send your questions and proposals to
</ul>
<h3 id=interaction>Interaction with Checkers</h3>
+
+ <p>
Checkers are not merely passive receivers of the analyzer core changes - they
actively participate in the <tt>ProgramState</tt> construction through the
<tt>GenericDataMap</tt> which can be used to store the checker-defined part
@@ -123,9 +131,12 @@ for developer guidelines and send your questions and proposals to
opportunity to either report a bug or modify the state. (As a rule of thumb,
the checker itself should be stateless.) The checkers are called one after another
in the predefined order; thus, calling all the checkers adds a chain to the
- <tt>ExplodedGraph</tt>.
+ <tt>ExplodedGraph</tt>.
+ </p>
<h3 id=values>Representing Values</h3>
+
+ <p>
During symbolic execution, <a href="http://clang.llvm.org/doxygen/classclang_1_1ento_1_1SVal.html">SVal</a>
objects are used to represent the semantic evaluation of expressions.
They can represent things like concrete
@@ -142,7 +153,9 @@ for developer guidelines and send your questions and proposals to
This represents a case that is outside the realm of the analyzer's reasoning
capabilities. <tt>SVals</tt> are value objects and their values can be viewed
using the <tt>.dump()</tt> method. Often they wrap persistent objects such as
- symbols or regions.
+ symbols or regions.
+ </p>
+
<p>
<a href="http://clang.llvm.org/doxygen/classclang_1_1ento_1_1SymExpr.html">SymExpr</a> (symbol)
is meant to represent abstract, but named, symbolic value. Symbols represent
@@ -150,7 +163,7 @@ for developer guidelines and send your questions and proposals to
we can associate constraints with that value as we analyze a path. For
example, we might record that the value of a symbol is greater than
<tt>0</tt>, etc.
- <p>
+ </p>
<p>
<a href="http://clang.llvm.org/doxygen/classclang_1_1ento_1_1MemRegion.html">MemRegion</a> is similar to a symbol.
@@ -163,9 +176,12 @@ for developer guidelines and send your questions and proposals to
<a href="http://clang.llvm.org/doxygen/classclang_1_1ento_1_1SymbolicRegion.html">SymbolicRegion</a>
is for. It is a <tt>MemRegion</tt> that has an associated symbol. Since the
symbol is unique and has a unique name; that symbol names the region.
+ </p>
- <P>
+ <p>
Let's see how the analyzer processes the expressions in the following example:
+ </p>
+
<p>
<pre class="code_example">
int foo(int x) {
@@ -174,6 +190,8 @@ for developer guidelines and send your questions and proposals to
...
}
</pre>
+ </p>
+
<p>
Let's look at how <tt>x*2</tt> gets evaluated. When <tt>x</tt> is evaluated,
we first construct an <tt>SVal</tt> that represents the lvalue of <tt>x</tt>, in
@@ -193,6 +211,7 @@ to the <tt>MemRegion</tt> in the symbolic store.
The second line is similar. When we evaluate <tt>x</tt> again, we do the same
dance, and create an <tt>SVal</tt> that references the symbol <tt>$0</tt>. Note, two <tt>SVals</tt>
might reference the same underlying values.
+ </p>
<p>
To summarize, MemRegions are unique names for blocks of memory. Symbols are
@@ -200,6 +219,7 @@ unique names for abstract symbolic values. Some MemRegions represents abstract
symbolic chunks of memory, and thus are also based on symbols. SVals are just
references to values, and can reference either MemRegions, Symbols, or concrete
values (e.g., the number 1).
+</p>
<!--
TODO: Add a picture.
@@ -511,75 +531,139 @@ by calling <a href = "http://clang.llvm.org/doxygen/classclang_1_1ento_1_1Checke
live in <tt>clang/test/Analysis</tt> folder. To run all of the analyzer tests,
execute the following from the <tt>clang</tt> build directory:
<pre class="code">
- $ <b>TESTDIRS=Analysis make test</b>
+ $ <b>bin/llvm-lit -sv ../llvm/tools/clang/test/Analysis</b>
</pre>
<h2 id=commands>Useful Commands/Debugging Hints</h2>
-<ul>
-<li>
-While investigating a checker-related issue, instruct the analyzer to only
+
+<h3 id=attaching>Attaching the Debugger</h3>
+
+<p>When your command contains the <tt><b>-cc1</b></tt> flag, you can attach the
+debugger to it directly:</p>
+
+<pre class="code">
+ $ <b>gdb --args clang -cc1 -analyze -analyzer-checker=core test.c</b>
+ $ <b>lldb -- clang -cc1 -analyze -analyzer-checker=core test.c</b>
+</pre>
+
+<p>
+Otherwise, if your command line contains <tt><b>--analyze</b></tt>,
+the actual clang instance would be run in a separate process. In
+order to debug it, use the <tt><b>-###</b></tt> flag for obtaining
+the command line of the child process:
+</p>
+
+<pre class="code">
+ $ <b>clang --analyze test.c -\#\#\#</b>
+</pre>
+
+<p>
+Below we describe a few useful command line arguments, all of which assume that
+you are running <tt><b>clang -cc1</b></tt>.
+</p>
+
+<h3 id=narrowing>Narrowing Down the Problem</h3>
+
+<p>While investigating a checker-related issue, instruct the analyzer to only
execute a single checker:
-<br><tt>
-$ <b>clang -cc1 -analyze -analyzer-checker=osx.KeychainAPI test.c</b>
-</tt>
-</li>
-<li>
-To dump AST:
-<br><tt>
-$ <b>clang -cc1 -ast-dump test.c</b>
-</tt>
-</li>
-<li>
-To view/dump CFG use <tt>debug.ViewCFG</tt> or <tt>debug.DumpCFG</tt> checkers:
-<br><tt>
-$ <b>clang -cc1 -analyze -analyzer-checker=debug.ViewCFG test.c</b>
-</tt>
-</li>
-<li>
-To see all available debug checkers:
-<br><tt>
-$ <b>clang -cc1 -analyzer-checker-help | grep "debug"</b>
-</tt>
-</li>
-<li>
-To see which function is failing while processing a large file use
-<tt>-analyzer-display-progress</tt> option.
-</li>
-<li>
-While debugging execute <tt>clang -cc1 -analyze -analyzer-checker=core</tt>
-instead of <tt>clang --analyze</tt>, as the later would call the compiler
-in a separate process.
-</li>
-<li>
-To view <tt>ExplodedGraph</tt> (the state graph explored by the analyzer) while
-debugging, goto a frame that has <tt>clang::ento::ExprEngine</tt> object and
-execute:
-<br><tt>
-(gdb) <b>p ViewGraph(0)</b>
-</tt>
-</li>
-<li>
-To see the <tt>ProgramState</tt> while debugging use the following command.
-<br><tt>
-(gdb) <b>p State->dump()</b>
-</tt>
-</li>
-<li>
-To see <tt>clang::Expr</tt> while debugging use the following command. If you
-pass in a SourceManager object, it will also dump the corresponding line in the
-source code.
-<br><tt>
-(gdb) <b>p E->dump()</b>
-</tt>
-</li>
-<li>
-To dump AST of a method that the current <tt>ExplodedNode</tt> belongs to:
-<br><tt>
-(gdb) <b>p C.getPredecessor()->getCodeDecl().getBody()->dump()</b>
-(gdb) <b>p C.getPredecessor()->getCodeDecl().getBody()->dump(getContext().getSourceManager())</b>
-</tt>
-</li>
-</ul>
+</p>
+<pre class="code">
+ $ <b>clang -cc1 -analyze -analyzer-checker=osx.KeychainAPI test.c</b>
+</pre>
+
+<p>If you are experiencing a crash, to see which function is failing while
+processing a large file use the <tt><b>-analyzer-display-progress</b></tt>
+option.</p>
+
+<p>You can analyze a particular function within the file, which is often useful
+because the problem is always in a certain function:</p>
+<pre class="code">
+ $ <b>clang -cc1 -analyze -analyzer-checker=core test.c -analyzer-display-progress</b>
+ ANALYZE (Syntax): test.c foo
+ ANALYZE (Syntax): test.c bar
+ ANALYZE (Path, Inline_Regular): test.c bar
+ ANALYZE (Path, Inline_Regular): test.c foo
+ $ <b>clang -cc1 -analyze -analyzer-checker=core test.c -analyzer-display-progress -analyze-function=foo</b>
+ ANALYZE (Syntax): test.c foo
+ ANALYZE (Path, Inline_Regular): test.c foo
+</pre>
+
+<p>The bug reporter mechanism removes path diagnostics inside intermediate
+function calls that have returned by the time the bug was found and contain
+no interesting pieces. Usually it is up to the checkers to produce more
+interesting pieces by adding custom <tt>BugReporterVisitor</tt> objects.
+However, you can disable path pruning while debugging with the
+<tt><b>-analyzer-config prune-paths=false</b></tt> option.
+
+<h3 id=visualizing>Visualizing the Analysis</h3>
+
+<p>To dump the AST, which often helps understanding how the program should
+behave:</p>
+<pre class="code">
+ $ <b>clang -cc1 -ast-dump test.c</b>
+</pre>
+
+<p>To view/dump CFG use <tt>debug.ViewCFG</tt> or <tt>debug.DumpCFG</tt>
+checkers:</p>
+<pre class="code">
+ $ <b>clang -cc1 -analyze -analyzer-checker=debug.ViewCFG test.c</b>
+</pre>
+
+<p><tt>ExplodedGraph</tt> (the state graph explored by the analyzer) can be
+visualized with another debug checker:</p>
+<pre class="code">
+ $ <b>clang -cc1 -analyze -analyzer-checker=debug.ViewExplodedGraph test.c</b>
+</pre>
+<p>Or, equivalently, with <tt><b>-analyzer-viz-egraph-graphviz</b></tt>
+option, which does the same thing - dumps the exploded graph in graphviz
+<tt><b>.dot</b></tt> format.</p>
+
+<p>You can convert <tt><b>.dot</b></tt> files into other formats - in
+particular, converting to <tt><b>.svg</b></tt> and viewing in your web
+browser might be more comfortable than using a <tt><b>.dot</b></tt> viewer:</p>
+<pre class="code">
+ $ <b>dot -Tsvg ExprEngine-501e2e.dot -o ExprEngine-501e2e.svg</b>
+</pre>
+
+<p>The <tt><b>-trim-egraph</b></tt> option removes all paths except those
+leading to bug reports from the exploded graph dump. This is useful
+because exploded graphs are often huge and hard to navigate.</p>
+
+<p>Viewing <tt>ExplodedGraph</tt> is your most powerful tool for understanding
+the analyzer's false positives, because it gives comprehensive information
+on every decision made by the analyzer across all analysis paths.</p>
+
+<p>There are more debug checkers available. To see all available debug checkers:
+</p>
+<pre class="code">
+ $ <b>clang -cc1 -analyzer-checker-help | grep "debug"</b>
+</pre>
+
+<h3 id=debugprints>Debug Prints and Tricks</h3>
+
+<p>To view "half-baked" <tt>ExplodedGraph</tt> while debugging, jump to a frame
+that has <tt>clang::ento::ExprEngine</tt> object and execute:</p>
+<pre class="code">
+ (gdb) <b>p ViewGraph(0)</b>
+</pre>
+
+<p>To see the <tt>ProgramState</tt> while debugging use the following command.
+<pre class="code">
+ (gdb) <b>p State->dump()</b>
+</pre>
+
+<p>To see <tt>clang::Expr</tt> while debugging use the following command. If you
+pass in a <tt>SourceManager</tt> object, it will also dump the corresponding line in the
+source code.</p>
+<pre class="code">
+ (gdb) <b>p E->dump()</b>
+</pre>
+
+<p>To dump AST of a method that the current <tt>ExplodedNode</tt> belongs
+to:</p>
+<pre class="code">
+ (gdb) <b>p C.getPredecessor()->getCodeDecl().getBody()->dump()</b>
+</pre>
<h2 id=additioninformation>Additional Sources of Information</h2>
diff --git a/www/analyzer/faq.html b/www/analyzer/faq.html
index cf3dc70035f6..516233b24bf9 100644
--- a/www/analyzer/faq.html
+++ b/www/analyzer/faq.html
@@ -29,6 +29,9 @@ null?</a></li>
<li><a href="#dead_store">How do I tell the static analyzer that I don't care about a specific dead store?</a></li>
<li><a href="#unused_ivar">How do I tell the static analyzer that I don't care about a specific unused instance variable in Objective C?</a></li>
<li><a href="#unlocalized_string">How do I tell the static analyzer that I don't care about a specific unlocalized string?</a></li>
+ <li><a href="#dealloc_mrr">How do I tell the analyzer that my instance variable does not need to be released in -dealloc under Manual Retain/Release?</a></li>
+ <li><a href="#decide_nullability">How do I decide whether a method's return type should be _Nullable or _Nonnull?</a></li>
+ <li><a href="#nullability_intentional_violation">How do I tell the analyzer that I am intentionally violating nullability?</a></li>
<li><a href="#use_assert">The analyzer assumes that a loop body is never entered. How can I tell it that the loop body will be entered at least once?</a></li>
<li><a href="#suppress_issue">How can I suppress a specific analyzer warning?</a></li>
<li><a href="#exclude_code">How can I selectively exclude code the analyzer examines?</a></li>
@@ -105,6 +108,67 @@ NSString *s = NSLocalizedString(@"Hello &lt;Do Not Localize&gt;", @"For debug pu
</pre>
</p>
+<h4 id="dealloc_mrr" class="faq">Q: How do I tell the analyzer that my instance variable does not need to be released in -dealloc under Manual Retain/Release?</h4>
+
+<p>If your class only uses an instance variable for part of its lifetime, it may
+maintain an invariant guaranteeing that the instance variable is always released
+before -dealloc. In this case, you can silence a warning about a missing release
+by either adding <tt>assert(_ivar == nil)</tt> or an explicit release
+<tt>[_ivar release]</tt> (which will be a no-op when the variable is nil) in
+-dealloc. </p>
+
+<h4 id="decide_nullability" class="faq">Q: How do I decide whether a method's return type should be _Nullable or _Nonnull?</h4>
+
+<p> Depending on the implementation of the method, this puts you in one of five situations:
+<ol>
+<li>You actually never return nil.</li>
+<li>You do return nil sometimes, and callers are supposed to handle that. This
+includes cases where your method is documented to return nil given certain
+inputs.</li>
+<li>You return nil based on some external condition (such as an out-of-memory
+error), but the client can't do anything about it either.</li>
+<li>You return nil only when the caller passes input documented to be invalid.
+That means it's the client's fault.</li>
+<li>You return nil in some totally undocumented case.</li>
+</ol>
+</p>
+
+<p>In (1) you should annotate the method as returning a <tt>_Nonnull</tt>
+object.</p>
+<p>In (2) the method should be marked <tt>_Nullable.</tt></p>
+<p>In (3) you should probably annotate the method <tt>_Nonnull</tt>. Why?
+Because no callers will actually check for nil, given that they can't do
+anything about the situation and don't know what went wrong. At this point
+things have gone so poorly that there's basically no way to recover.</p>
+<p>The least happy case is (4) because the resulting program will almost
+certainly either crash or just silently do the wrong thing.
+If this is a new method or you control the callers, you can use
+<tt>NSParameterAssert()</tt> (or the equivalent) to check the precondition and
+remove the nil return. But if you don't control the callers and they rely on
+this behavior, you should return mark the method <tt>_Nonnull</tt> and return
+nil <a href="#nullability_intentional_violation">cast to _Nonnull</a> anyway.
+(Note that (4) doesn't apply in cases where the caller can't know they passed
+bad parameters. For example,
+<tt>+[NSData dataWithContentsOfFile:options:error:]</tt> will fail if the file
+doesn't exist, but there's no way to check for that in advance. This means
+you're really in (2).)</p>
+<p>If you're in (5), document it, then figure out if you're now in (2), (3), or
+(4). :-)</p>
+
+<h4 id="nullability_intentional_violation" class="faq">Q: How do I tell the analyzer that I am intentionally violating nullability?</h4>
+
+<p>In some cases, it may make sense for methods to intentionally violate
+nullability. For example, your method may &mdash; for reasons of backward
+compatibility &mdash; chose to return nil and log an error message in a method
+with a non-null return type when the client violated a documented precondition
+rather than check the precondition with <tt>NSAssert()</tt>. In these cases, you
+can suppress the analyzer warning with a cast:
+<pre class="code_example">
+ return (id _Nonnull)nil;
+</pre>
+Note that this cast does not affect code generation.
+</p>
+
<h4 id="use_assert" class="faq">Q: The analyzer assumes that a loop body is never entered. How can I tell it that the loop body will be entered at least once?</h4>
<img src="images/example_use_assert.png" alt="example use assert">
diff --git a/www/analyzer/index.html b/www/analyzer/index.html
index 98e295e28da3..cca105a818ad 100644
--- a/www/analyzer/index.html
+++ b/www/analyzer/index.html
@@ -95,7 +95,7 @@ applications.</p>
<div style="padding:15px">
<h3 style="margin:0px;padding:0px">Mac OS X</h3>
<ul>
- <li>Latest build (10.7+):<br>
+ <li>Latest build (10.8+):<br>
<!--#include virtual="latest_checker.html.incl"-->
</li>
<li><a href="/release_notes.html">Release notes</a></li>
diff --git a/www/analyzer/latest_checker.html.incl b/www/analyzer/latest_checker.html.incl
index 0f236208dff7..439a245c8ada 100644
--- a/www/analyzer/latest_checker.html.incl
+++ b/www/analyzer/latest_checker.html.incl
@@ -1 +1 @@
-<b><a href="downloads/checker-278.tar.bz2">checker-278.tar.bz2</a></b> (built February 5, 2016)
+<b><a href="downloads/checker-279.tar.bz2">checker-279.tar.bz2</a></b> (built November 14, 2016)
diff --git a/www/analyzer/potential_checkers.html b/www/analyzer/potential_checkers.html
index 0e5fba3e02f1..2e6a201d7925 100644
--- a/www/analyzer/potential_checkers.html
+++ b/www/analyzer/potential_checkers.html
@@ -180,64 +180,6 @@ void test(A *dst, A *src) {
</table>
-<!-- =============================== va_list =============================== -->
-<h3>va_list</h3>
-<table class="checkers">
-<col class="namedescr"><col class="example"><col class="progress">
-<thead><tr><td>Name, Description</td><td>Example</td><td>Progress</td></tr></thead>
-
-<tr><td><div class="namedescr expandable"><span class="name">
-valist.Uninitialized</span><span class="lang">
-(C)</span><div class="descr">
-Calls to the <code>va_arg</code>, <code>va_copy</code>, or
-<code>va_end</code> macro must happen after calling <code>va_start</code> and
-before calling <code>va_end</code>.</div></div></td>
-<td><div class="exampleContainer expandable">
-<div class="example"><pre>
-#include &lt;stdarg.h&gt;
-
-void test(int x, ...) {
- va_list args;
- int y = va_arg(args, int); // warn
-}
-</pre></div>
-<div class="example"><pre>
-#include &lt;stdarg.h&gt;
-
-void test(int x, ...) {
- va_list args;
- va_start(args, x);
- va_end(args);
- int z = va_arg(args, int); // warn
-}
-</pre></div></div></td>
-<td class="aligned"><a href="http://llvm.org/bugs/show_bug.cgi?id=16812">
-PR16811</a></td></tr>
-
-<tr><td><div class="namedescr expandable"><span class="name">
-valist.Unterminated</span><span class="lang">
-(C)</span><div class="descr">
-Every <code>va_start</code> must be matched by a <code>va_end</code>. A va_list
-can only be ended once.
-
-<i>This should be folded into the generalized "ownership checker"
-described on the <a href="open_projects.html">
-Open Projects</a> page.</i></div></div></td>
-<td><div class="exampleContainer expandable">
-<div class="example"><pre>
-#include &lt;stdarg.h&gt;
-
-void test(int x, ...) {
- va_list args;
- va_start(args, x);
- int y = x + va_arg(args, int);
-} // warn: missing va_end
-</pre></div></div></td>
-<td class="aligned"><a href="http://llvm.org/bugs/show_bug.cgi?id=16812">
-PR16812</a></td></tr>
-
-</table>
-
<!-- ============================== exceptions ============================= -->
<h3>exceptions</h3>
<table class="checkers">
@@ -384,7 +326,8 @@ void test() {
// warn: the right operand to '-' is always 0
}
</pre></div></div></td>
-<td class="aligned">removed from alpha.deadcode.* at r198476</td></tr>
+<td class="aligned">removed from alpha.deadcode.* at
+<a href="https://reviews.llvm.org/rL198476">r198476</a></td></tr>
</table>
diff --git a/www/analyzer/release_notes.html b/www/analyzer/release_notes.html
index 85aa08f158aa..68e224b36665 100644
--- a/www/analyzer/release_notes.html
+++ b/www/analyzer/release_notes.html
@@ -14,6 +14,25 @@
<div id="content">
<h1>Release notes for <tt>checker-XXX</tt> builds</h1>
+<h4 id="checker_279">checker-279</h4>
+<p><b>built:</b> November 14, 2016</br>
+ <b>download:</b> <a href="downloads/checker-279.tar.bz2">checker-279.tar.bz2</a></p>
+ <p><b>highlights:</b></p>
+ <ul>
+ <li>The analyzer includes new checks for:
+ <ul>
+ <li>Improper instance cleanup up in Objective-C -dealloc methods under manual retain/release.</li>
+ <li>Inadvertent comparisons of NSNumber, CFNumberRef, and other number object pointers against scalar values.</li>
+ <li>Unsafe usage of dispatch_once_t predicates stored in Objective-C instance variables and other heap-allocated memory.</li>
+ <li>Issues resulting from self-assignment in C++.</li>
+ <li>Incorrect usage of MPI APIs in C and C++. This check can be enabled by passing the following command to scan-build: <br />
+ &nbsp;&nbsp;<tt>-enable-checker optin.mpi.MPI-Checker</tt></li>
+ </ul>
+ <li>The scan-build tool now supports a <tt>--force-analyze-debug-code flag</tt> that forces projects to analyze in debug mode. This flag leaves in assertions and so typically results in fewer false positives.</li>
+ <li>Additional miscellaneous improvements.</li>
+ <li>Now requires macOS 10.8 or later.</li>
+ </ul>
+
<h4 id="checker_278">checker-278</h4>
<p><b>built:</b> February 5, 2016</br>
<b>download:</b> <a href="downloads/checker-278.tar.bz2">checker-278.tar.bz2</a></p>
diff --git a/www/cxx_dr_status.html b/www/cxx_dr_status.html
index 2f679b990f35..ee8ce025eb47 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: 2016-07-27 18:41:01 +0200 (Wed, 27 Jul 2016) $</p>
+<p>Last updated: $Date: 2017-01-02 12:15:42 +0100 (Mon, 02 Jan 2017) $</p>
<h2 id="cxxdr">C++ defect report implementation status</h2>
@@ -207,7 +207,7 @@
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#28">28</a></td>
<td>CD1</td>
<td>'exit', 'signal' and static object destruction</td>
- <td class="na" align="center">N/A</td>
+ <td class="na" align="center">N/A (Library DR)</td>
</tr>
<tr id="29">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#29">29</a></td>
@@ -589,9 +589,9 @@
</tr>
<tr id="92">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#92">92</a></td>
- <td>accepted</td>
+ <td>WP</td>
<td>Should <I>exception-specification</I>s be part of the type system?</td>
- <td class="none" align="center">Unknown</td>
+ <td class="svn" align="center">SVN (C++17 onwards)</td>
</tr>
<tr id="93">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#93">93</a></td>
@@ -663,7 +663,7 @@
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#104">104</a></td>
<td>NAD</td>
<td>Destroying the exception temp when no handler is found</td>
- <td class="none" align="center">Unknown</td>
+ <td class="na" align="center">N/A (Library DR)</td>
</tr>
<tr id="105">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#105">105</a></td>
@@ -747,7 +747,7 @@
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#118">118</a></td>
<td>CD1</td>
<td>Calls via pointers to virtual member functions</td>
- <td class="none" align="center">Unknown</td>
+ <td class="full" align="center">Yes</td>
</tr>
<tr id="119">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#119">119</a></td>
@@ -813,7 +813,7 @@
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#129">129</a></td>
<td>CD3</td>
<td>Stability of uninitialized auto variables</td>
- <td class="none" align="center">Duplicate of <a href="#616">616</a></td>
+ <td class="svn" align="center">Duplicate of <a href="#616">616</a></td>
</tr>
<tr id="130">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#130">130</a></td>
@@ -987,7 +987,7 @@
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#158">158</a></td>
<td>CD1</td>
<td>Aliasing and qualification conversions</td>
- <td class="none" align="center">Unknown</td>
+ <td class="full" align="center">Yes</td>
</tr>
<tr id="159">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#159">159</a></td>
@@ -1309,8 +1309,8 @@ accessible?</td>
<td class="full" align="center">Yes</td>
</tr>
<tr id="212">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#212">212</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#212">212</a></td>
+ <td>DR</td>
<td>Implicit instantiation is not described clearly enough</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -1465,8 +1465,8 @@ accessible?</td>
<td class="full" align="center">Duplicate of <a href="#470">470</a></td>
</tr>
<tr id="238">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#238">238</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#238">238</a></td>
+ <td>DR</td>
<td>Precision and accuracy constraints on floating point</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -1480,7 +1480,7 @@ accessible?</td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#240">240</a></td>
<td>CD3</td>
<td>Uninitialized values and undefined behavior</td>
- <td class="none" align="center">Duplicate of <a href="#616">616</a></td>
+ <td class="svn" align="center">Duplicate of <a href="#616">616</a></td>
</tr>
<tr id="241">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#241">241</a></td>
@@ -1489,8 +1489,8 @@ accessible?</td>
<td class="full" align="center">Yes</td>
</tr>
<tr id="242">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#242">242</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#242">242</a></td>
+ <td>DR</td>
<td>Interpretation of old-style casts</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -1594,7 +1594,7 @@ accessible?</td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#259">259</a></td>
<td>CD1</td>
<td>Restrictions on explicit specialization and instantiation</td>
- <td class="full" align="center">Yes (C++11 onwards)</td>
+ <td class="svn" align="center">SVN</td>
</tr>
<tr class="open" id="260">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#260">260</a></td>
@@ -1913,7 +1913,7 @@ of class templates</td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#312">312</a></td>
<td>CD3</td>
<td>&#8220;use&#8221; of invalid pointer value not defined</td>
- <td class="none" align="center">Duplicate of <a href="#616">616</a></td>
+ <td class="svn" align="center">Duplicate of <a href="#616">616</a></td>
</tr>
<tr id="313">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#313">313</a></td>
@@ -1923,7 +1923,7 @@ of class templates</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>review</td>
+ <td>drafting</td>
<td><TT>template</TT> in base class specifier</td>
<td align="center">Not resolved</td>
</tr>
@@ -2097,7 +2097,7 @@ of class templates</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>review</td>
+ <td>drafting</td>
<td>Make <TT>template</TT> optional in contexts that require a type</td>
<td align="center">Not resolved</td>
</tr>
@@ -2595,7 +2595,7 @@ of class templates</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>drafting</td>
+ <td>review</td>
<td>Identically-named variables, one internally and one externally linked, allowed?</td>
<td align="center">Not resolved</td>
</tr>
@@ -3541,7 +3541,7 @@ and <I>POD class</I></td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#583">583</a></td>
<td>CD3</td>
<td>Relational pointer comparisons against the null pointer constant</td>
- <td class="none" align="center">No</td>
+ <td class="svn" align="center">SVN</td>
</tr>
<tr id="584">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#584">584</a></td>
@@ -3613,7 +3613,7 @@ and <I>POD class</I></td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#595">595</a></td>
<td>dup</td>
<td>Exception specifications in templates instantiated from class bodies</td>
- <td class="none" align="center">Duplicate of <a href="#1330">1330</a></td>
+ <td class="svn" 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>
@@ -3739,7 +3739,7 @@ and <I>POD class</I></td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#616">616</a></td>
<td>CD3</td>
<td>Definition of &#8220;indeterminate value&#8221;</td>
- <td class="none" align="center">No</td>
+ <td class="svn" align="center">SVN</td>
</tr>
<tr class="open" id="617">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#617">617</a></td>
@@ -4195,7 +4195,7 @@ and <I>POD class</I></td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#692">692</a></td>
<td>C++11</td>
<td>Partial ordering of variadic class template partial specializations</td>
- <td class="none" align="center">Unknown</td>
+ <td class="none" align="center">No</td>
</tr>
<tr id="693">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#693">693</a></td>
@@ -6139,7 +6139,7 @@ and <I>POD class</I></td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1054">1054</a></td>
<td>C++11</td>
<td>Lvalue-to-rvalue conversions in expression statements</td>
- <td class="none" align="center">Unknown</td>
+ <td class="none" align="center">No</td>
</tr>
<tr id="1055">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1055">1055</a></td>
@@ -6507,11 +6507,11 @@ and <I>POD class</I></td>
<td>C-compatible alignment specification</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="1116">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1116">1116</a></td>
- <td>drafting</td>
+ <tr id="1116">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1116">1116</a></td>
+ <td>DRWP</td>
<td>Aliasing of union members</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="1117">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1117">1117</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="none" align="center">Unknown</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>
@@ -7457,7 +7457,7 @@ and <I>POD class</I></td>
</tr>
<tr id="1274">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1274">1274</a></td>
- <td>DR</td>
+ <td>DRWP</td>
<td>Common nonterminal for <I>expression</I> and <I>braced-init-list</I></td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -7516,8 +7516,8 @@ and <I>POD class</I></td>
<td align="center">Not resolved</td>
</tr>
<tr id="1284">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1284">1284</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1284">1284</a></td>
+ <td>DR</td>
<td>Should the lifetime of an array be independent of that of its elements?</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -7585,7 +7585,7 @@ and <I>POD class</I></td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1295">1295</a></td>
<td>CD3</td>
<td>Binding a reference to an rvalue bit-field</td>
- <td class="none" align="center">Unknown</td>
+ <td class="svn" align="center">SVN</td>
</tr>
<tr id="1296">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1296">1296</a></td>
@@ -7702,10 +7702,10 @@ and <I>POD class</I></td>
<td class="none" align="center">Unknown</td>
</tr>
<tr id="1315">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1315">1315</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1315">1315</a></td>
+ <td>DR</td>
<td>Restrictions on non-type template arguments in partial specializations</td>
- <td class="none" align="center">Unknown</td>
+ <td class="partial" align="center">Partial</td>
</tr>
<tr id="1316">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#1316">1316</a></td>
@@ -7795,7 +7795,7 @@ and <I>POD class</I></td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1330">1330</a></td>
<td>CD3</td>
<td>Delayed instantiation of <TT>noexcept</TT> specifiers</td>
- <td class="none" align="center">Unknown</td>
+ <td class="svn" align="center">SVN (C++11 onwards)</td>
</tr>
<tr class="open" id="1331">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#1331">1331</a></td>
@@ -7869,11 +7869,11 @@ and <I>POD class</I></td>
<td>Order of initialization with multiple declarators</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="1343">
+ <tr id="1343">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1343">1343</a></td>
- <td>drafting</td>
+ <td>tentatively ready</td>
<td>Sequencing of non-class initialization</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="1344">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1344">1344</a></td>
@@ -8159,7 +8159,7 @@ and <I>POD class</I></td>
</tr>
<tr id="1391">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1391">1391</a></td>
- <td>DR</td>
+ <td>DRWP</td>
<td>Conversions to parameter types with non-deduced template arguments</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -8181,11 +8181,11 @@ and <I>POD class</I></td>
<td>Incomplete types as parameters of deleted functions</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="1395">
+ <tr id="1395">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1395">1395</a></td>
- <td>drafting</td>
+ <td>ready</td>
<td>Partial ordering of variadic templates reconsidered</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="1396">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1396">1396</a></td>
@@ -8785,11 +8785,11 @@ and <I>POD class</I></td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1495">1495</a></td>
<td>CD3</td>
<td>Partial specialization of variadic class template</td>
- <td class="none" align="center">Unknown</td>
+ <td class="svn" align="center">SVN</td>
</tr>
<tr id="1496">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1496">1496</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1496">1496</a></td>
+ <td>DR</td>
<td>Triviality with deleted and missing default constructors</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -8887,7 +8887,7 @@ and <I>POD class</I></td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1512">1512</a></td>
<td>CD3</td>
<td>Pointer comparison vs qualification conversions</td>
- <td class="none" align="center">Unknown</td>
+ <td class="svn" align="center">SVN</td>
</tr>
<tr class="open" id="1513">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1513">1513</a></td>
@@ -8919,11 +8919,11 @@ and <I>POD class</I></td>
<td>Unclear/missing description of behavior during construction/destruction</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="1518">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1518">1518</a></td>
- <td>review</td>
+ <tr id="1518">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1518">1518</a></td>
+ <td>DRWP</td>
<td>Explicit default constructors and copy-list-initialization</td>
- <td align="center">Not resolved</td>
+ <td class="svn" align="center">SVN</td>
</tr>
<tr id="1519">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#1519">1519</a></td>
@@ -9137,7 +9137,7 @@ and <I>POD class</I></td>
</tr>
<tr class="open" id="1554">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1554">1554</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Access and alias templates</td>
<td align="center">Not resolved</td>
</tr>
@@ -9640,10 +9640,10 @@ and <I>POD class</I></td>
<td class="none" align="center">Unknown</td>
</tr>
<tr id="1638">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1638">1638</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1638">1638</a></td>
+ <td>DR</td>
<td>Declaring an explicit specialization of a scoped enumeration</td>
- <td class="none" align="center">Unknown</td>
+ <td class="full" align="center">Yes</td>
</tr>
<tr id="1639">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1639">1639</a></td>
@@ -9683,7 +9683,7 @@ and <I>POD class</I></td>
</tr>
<tr id="1645">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1645">1645</a></td>
- <td>DR</td>
+ <td>DRWP</td>
<td>Identical inheriting constructors via default arguments</td>
<td class="full" align="center">Clang 3.9</td>
</tr>
@@ -9731,9 +9731,9 @@ and <I>POD class</I></td>
</tr>
<tr id="1653">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1653">1653</a></td>
- <td>accepted</td>
+ <td>WP</td>
<td>Removing deprecated increment of <TT>bool</TT></td>
- <td class="none" align="center">Unknown</td>
+ <td class="svn" align="center">SVN (C++17 onwards)</td>
</tr>
<tr id="1654">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#1654">1654</a></td>
@@ -10103,7 +10103,7 @@ and <I>POD class</I></td>
</tr>
<tr id="1715">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1715">1715</a></td>
- <td>DR</td>
+ <td>DRWP</td>
<td>Access and inherited constructor templates</td>
<td class="full" align="center">Clang 3.9</td>
</tr>
@@ -10145,7 +10145,7 @@ and <I>POD class</I></td>
</tr>
<tr id="1722">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1722">1722</a></td>
- <td>DR</td>
+ <td>DRWP</td>
<td>Should lambda to function pointer conversion function be <TT>noexcept</TT>?</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -10216,8 +10216,8 @@ and <I>POD class</I></td>
<td align="center">Not resolved</td>
</tr>
<tr id="1734">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1734">1734</a></td>
- <td>ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1734">1734</a></td>
+ <td>DR</td>
<td>Nontrivial deleted copy functions</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -10229,7 +10229,7 @@ and <I>POD class</I></td>
</tr>
<tr id="1736">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1736">1736</a></td>
- <td>DR</td>
+ <td>DRWP</td>
<td>Inheriting constructor templates in a local class</td>
<td class="full" align="center">Clang 3.9</td>
</tr>
@@ -10467,11 +10467,11 @@ and <I>POD class</I></td>
<td>Undefined behavior of line splice in raw string literal</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="1776">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1776">1776</a></td>
- <td>drafting</td>
+ <tr id="1776">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1776">1776</a></td>
+ <td>DRWP</td>
<td>Replacement of class objects containing reference members</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="1777">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1777">1777</a></td>
@@ -10577,7 +10577,7 @@ and <I>POD class</I></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>review</td>
+ <td>drafting</td>
<td><TT>template</TT> keyword and alias templates</td>
<td align="center">Not resolved</td>
</tr>
@@ -10661,7 +10661,7 @@ and <I>POD class</I></td>
</tr>
<tr class="open" id="1808">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1808">1808</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Constructor templates vs default constructors</td>
<td align="center">Not resolved</td>
</tr>
@@ -10685,7 +10685,7 @@ and <I>POD class</I></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>review</td>
+ <td>drafting</td>
<td>Omission of <TT>template</TT> in a <I>typename-specifier</I></td>
<td align="center">Not resolved</td>
</tr>
@@ -10761,11 +10761,11 @@ and <I>POD class</I></td>
<td>Completeness of return type vs point of instantiation</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="1825">
+ <tr id="1825">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1825">1825</a></td>
- <td>drafting</td>
+ <td>ready</td>
<td>Partial ordering between variadic and non-variadic function templates</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="1826">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#1826">1826</a></td>
@@ -10895,7 +10895,7 @@ and <I>POD class</I></td>
</tr>
<tr id="1847">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1847">1847</a></td>
- <td>DR</td>
+ <td>DRWP</td>
<td>Clarifying compatibility during partial ordering</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -10973,15 +10973,15 @@ and <I>POD class</I></td>
</tr>
<tr class="open" id="1860">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1860">1860</a></td>
- <td>drafting</td>
+ <td>review</td>
<td>What is a &#8220;direct member?&#8221;</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="1861">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1861">1861</a></td>
- <td>drafting</td>
+ <tr id="1861">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1861">1861</a></td>
+ <td>DRWP</td>
<td>Values of a bit-field</td>
- <td align="center">Not resolved</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>
@@ -10991,7 +10991,7 @@ and <I>POD class</I></td>
</tr>
<tr id="1863">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1863">1863</a></td>
- <td>DR</td>
+ <td>DRWP</td>
<td>Requirements on thrown object type to support <TT>std::current_exception()</TT></td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -11044,8 +11044,8 @@ and <I>POD class</I></td>
<td align="center">Not resolved</td>
</tr>
<tr id="1872">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1872">1872</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1872">1872</a></td>
+ <td>DR</td>
<td>Instantiations of <TT>constexpr</TT> templates that cannot appear in constant expressions</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -11161,7 +11161,7 @@ and <I>POD class</I></td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1891">1891</a></td>
<td>DRWP</td>
<td>Move constructor/assignment for closure class</td>
- <td class="full" align="center">Clang 3.6</td>
+ <td class="svn" align="center">SVN</td>
</tr>
<tr id="1892">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1892">1892</a></td>
@@ -11182,8 +11182,8 @@ and <I>POD class</I></td>
<td align="center">Not resolved</td>
</tr>
<tr id="1895">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1895">1895</a></td>
- <td>ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1895">1895</a></td>
+ <td>DR</td>
<td>Deleted conversions in conditional operator operands</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -11231,7 +11231,7 @@ and <I>POD class</I></td>
</tr>
<tr id="1903">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1903">1903</a></td>
- <td>DR</td>
+ <td>DRWP</td>
<td>What declarations are introduced by a non-member <I>using-declaration</I>?</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -11255,7 +11255,7 @@ and <I>POD class</I></td>
</tr>
<tr class="open" id="1907">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1907">1907</a></td>
- <td>open</td>
+ <td>drafting</td>
<td><I>using-declaration</I>s and default arguments</td>
<td align="center">Not resolved</td>
</tr>
@@ -11392,8 +11392,8 @@ and <I>POD class</I></td>
<td class="none" align="center">Unknown</td>
</tr>
<tr id="1930">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1930">1930</a></td>
- <td>ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1930">1930</a></td>
+ <td>DR</td>
<td><I>init-declarator-list</I> vs <I>member-declarator-list</I></td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -11404,8 +11404,8 @@ and <I>POD class</I></td>
<td align="center">Not resolved</td>
</tr>
<tr id="1932">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1932">1932</a></td>
- <td>ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1932">1932</a></td>
+ <td>DR</td>
<td>Bit-field results of conditional operators</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -11459,7 +11459,7 @@ and <I>POD class</I></td>
</tr>
<tr id="1941">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1941">1941</a></td>
- <td>DR</td>
+ <td>DRWP</td>
<td>SFINAE and inherited constructor default arguments</td>
<td class="full" align="center">Clang 3.9</td>
</tr>
@@ -11489,7 +11489,7 @@ and <I>POD class</I></td>
</tr>
<tr id="1946">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1946">1946</a></td>
- <td>accepted</td>
+ <td>WP</td>
<td><I>exception-specification</I>s vs pointer dereference</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -11507,7 +11507,7 @@ and <I>POD class</I></td>
</tr>
<tr id="1949">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1949">1949</a></td>
- <td>DR</td>
+ <td>DRWP</td>
<td>&#8220;sequenced after&#8221; instead of &#8220;sequenced before&#8221;</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -11542,8 +11542,8 @@ and <I>POD class</I></td>
<td align="center">Not resolved</td>
</tr>
<tr id="1955">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1955">1955</a></td>
- <td>ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1955">1955</a></td>
+ <td>DR</td>
<td><TT>#elif</TT> with invalid controlling expression</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -11567,7 +11567,7 @@ and <I>POD class</I></td>
</tr>
<tr id="1959">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1959">1959</a></td>
- <td>DR</td>
+ <td>DRWP</td>
<td>Inadvertently inherited copy constructor</td>
<td class="full" align="center">Clang 3.9</td>
</tr>
@@ -11577,11 +11577,11 @@ and <I>POD class</I></td>
<td>Visibility of entity named in class-scope <I>using-declaration</I></td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="1961">
+ <tr id="1961">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1961">1961</a></td>
- <td>review</td>
+ <td>ready</td>
<td>Potentially-concurrent actions within a signal handler</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="1962">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1962">1962</a></td>
@@ -11663,7 +11663,7 @@ and <I>POD class</I></td>
</tr>
<tr id="1975">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1975">1975</a></td>
- <td>DR</td>
+ <td>DRWP</td>
<td>Permissible declarations for <I>exception-specification</I>s</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -11699,7 +11699,7 @@ and <I>POD class</I></td>
</tr>
<tr id="1981">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1981">1981</a></td>
- <td>DR</td>
+ <td>DRWP</td>
<td>Implicit contextual conversions and <TT>explicit</TT></td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -11753,25 +11753,25 @@ and <I>POD class</I></td>
</tr>
<tr id="1990">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1990">1990</a></td>
- <td>DR</td>
+ <td>DRWP</td>
<td>Ambiguity due to optional <I>decl-specifier-seq</I></td>
<td class="none" align="center">Unknown</td>
</tr>
<tr id="1991">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1991">1991</a></td>
- <td>DR</td>
+ <td>DRWP</td>
<td>Inheriting constructors vs default arguments</td>
<td class="full" align="center">Clang 3.9</td>
</tr>
<tr id="1992">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1992">1992</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1992">1992</a></td>
+ <td>DR</td>
<td><TT>new (std::nothrow) int[N]</TT> can throw</td>
<td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="1993">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1993">1993</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Use of <TT>template&lt;&gt;</TT> defining member of explicit specialization</td>
<td align="center">Not resolved</td>
</tr>
@@ -11783,7 +11783,7 @@ and <I>POD class</I></td>
</tr>
<tr id="1995">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1995">1995</a></td>
- <td>accepted</td>
+ <td>WP</td>
<td><I>exception-specification</I>s and non-type template parameters</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -11813,13 +11813,13 @@ and <I>POD class</I></td>
</tr>
<tr id="2000">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2000">2000</a></td>
- <td>DR</td>
+ <td>DRWP</td>
<td><I>header-name</I> outside <TT>#include</TT> directive</td>
<td class="none" align="center">Unknown</td>
</tr>
<tr id="2001">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2001">2001</a></td>
- <td>ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2001">2001</a></td>
+ <td>DR</td>
<td><I>non-directive</I> is underspecified</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -11837,7 +11837,7 @@ and <I>POD class</I></td>
</tr>
<tr id="2004">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2004">2004</a></td>
- <td>DR</td>
+ <td>DRWP</td>
<td>Unions with mutable members in constant expressions</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -11849,7 +11849,7 @@ and <I>POD class</I></td>
</tr>
<tr id="2006">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2006">2006</a></td>
- <td>DR</td>
+ <td>DRWP</td>
<td>Cv-qualified <TT>void</TT> types</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -11860,8 +11860,8 @@ and <I>POD class</I></td>
<td align="center">Not resolved</td>
</tr>
<tr id="2008">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2008">2008</a></td>
- <td>ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2008">2008</a></td>
+ <td>DR</td>
<td>Default <I>template-argument</I>s underspecified</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -11873,19 +11873,19 @@ and <I>POD class</I></td>
</tr>
<tr id="2010">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2010">2010</a></td>
- <td>accepted</td>
+ <td>WP</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>review</td>
+ <td>drafting</td>
<td>Unclear effect of reference capture of reference</td>
<td align="center">Not resolved</td>
</tr>
<tr id="2012">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2012">2012</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2012">2012</a></td>
+ <td>DR</td>
<td>Lifetime of references</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -11903,19 +11903,19 @@ and <I>POD class</I></td>
</tr>
<tr id="2015">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2015">2015</a></td>
- <td>DR</td>
+ <td>DRWP</td>
<td>odr-use of deleted virtual functions</td>
<td class="none" align="center">Unknown</td>
</tr>
<tr id="2016">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2016">2016</a></td>
- <td>DR</td>
+ <td>DRWP</td>
<td>Confusing wording in description of conversion function</td>
<td class="none" align="center">Unknown</td>
</tr>
<tr id="2017">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2017">2017</a></td>
- <td>ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2017">2017</a></td>
+ <td>DR</td>
<td>Flowing off end is not equivalent to no-expression return</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -11927,7 +11927,7 @@ and <I>POD class</I></td>
</tr>
<tr id="2019">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2019">2019</a></td>
- <td>DR</td>
+ <td>DRWP</td>
<td>Member references omitted from description of storage duration</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -11943,11 +11943,11 @@ and <I>POD class</I></td>
<td>Function template redeclaration via alias template</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2022">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2022">2022</a></td>
- <td>drafting</td>
+ <tr id="2022">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2022">2022</a></td>
+ <td>DRWP</td>
<td>Copy elision in constant expressions</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2023">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2023">2023</a></td>
@@ -11957,7 +11957,7 @@ and <I>POD class</I></td>
</tr>
<tr id="2024">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2024">2024</a></td>
- <td>DR</td>
+ <td>DRWP</td>
<td>Dependent types and unexpanded parameter packs</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -11969,13 +11969,13 @@ and <I>POD class</I></td>
</tr>
<tr id="2026">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2026">2026</a></td>
- <td>DR</td>
+ <td>DRWP</td>
<td>Zero-initialization and <TT>constexpr</TT></td>
<td class="none" align="center">Unknown</td>
</tr>
<tr id="2027">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2027">2027</a></td>
- <td>DR</td>
+ <td>DRWP</td>
<td>Unclear requirements for multiple <TT>alignas</TT> specifiers</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -11999,19 +11999,19 @@ and <I>POD class</I></td>
</tr>
<tr id="2031">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2031">2031</a></td>
- <td>DR</td>
+ <td>DRWP</td>
<td>Missing incompatibility for <TT>&amp;&amp;</TT></td>
<td class="none" align="center">Unknown</td>
</tr>
<tr id="2032">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2032">2032</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2032">2032</a></td>
+ <td>DR</td>
<td>Default <I>template-argument</I>s of variable templates</td>
<td class="none" align="center">Unknown</td>
</tr>
<tr id="2033">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2033">2033</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2033">2033</a></td>
+ <td>DR</td>
<td>Redundant restriction on partial specialization argument</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -12021,11 +12021,11 @@ and <I>POD class</I></td>
<td>Deprecating <TT>uncaught_exception()</TT></td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2035">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2035">2035</a></td>
- <td>review</td>
+ <tr id="2035">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2035">2035</a></td>
+ <td>CD3</td>
<td>Multi-section example is confusing</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="2036">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2036">2036</a></td>
@@ -12040,32 +12040,32 @@ and <I>POD class</I></td>
<td align="center">Not resolved</td>
</tr>
<tr id="2038">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2038">2038</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2038">2038</a></td>
+ <td>DR</td>
<td>Document C++14 incompatibility of new braced deduction rule</td>
<td class="none" align="center">Unknown</td>
</tr>
<tr id="2039">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2039">2039</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2039">2039</a></td>
+ <td>DR</td>
<td>Constant conversions to <TT>bool</TT></td>
<td class="none" align="center">Unknown</td>
</tr>
<tr id="2040">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2040">2040</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2040">2040</a></td>
+ <td>DR</td>
<td><I>trailing-return-type</I> no longer ambiguous</td>
<td class="none" align="center">Unknown</td>
</tr>
<tr id="2041">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2041">2041</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2041">2041</a></td>
+ <td>DR</td>
<td>Namespace for explicit class template specialization</td>
<td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2042">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2042">2042</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Exceptions and deallocation functions</td>
<td align="center">Not resolved</td>
</tr>
@@ -12076,8 +12076,8 @@ and <I>POD class</I></td>
<td align="center">Not resolved</td>
</tr>
<tr id="2044">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2044">2044</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2044">2044</a></td>
+ <td>DR</td>
<td><TT>decltype(auto)</TT> and <TT>void</TT></td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -12094,8 +12094,8 @@ and <I>POD class</I></td>
<td align="center">Not resolved</td>
</tr>
<tr id="2047">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2047">2047</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2047">2047</a></td>
+ <td>DR</td>
<td>Coordinating &#8220;throws anything&#8221; specifications</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -12125,7 +12125,7 @@ and <I>POD class</I></td>
</tr>
<tr id="2052">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2052">2052</a></td>
- <td>DR</td>
+ <td>DRWP</td>
<td>Template argument deduction vs overloaded operators</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -12143,7 +12143,7 @@ and <I>POD class</I></td>
</tr>
<tr class="open" id="2055">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2055">2055</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Explicitly-specified non-deduced parameter packs</td>
<td align="center">Not resolved</td>
</tr>
@@ -12155,7 +12155,7 @@ and <I>POD class</I></td>
</tr>
<tr class="open" id="2057">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2057">2057</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Template template arguments with default arguments</td>
<td align="center">Not resolved</td>
</tr>
@@ -12167,7 +12167,7 @@ and <I>POD class</I></td>
</tr>
<tr class="open" id="2059">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2059">2059</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Linkage and deduced return types</td>
<td align="center">Not resolved</td>
</tr>
@@ -12178,8 +12178,8 @@ and <I>POD class</I></td>
<td class="none" align="center">Unknown</td>
</tr>
<tr id="2061">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2061">2061</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2061">2061</a></td>
+ <td>DR</td>
<td>Inline namespace after simplifications</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -12190,14 +12190,14 @@ and <I>POD class</I></td>
<td align="center">Not resolved</td>
</tr>
<tr id="2063">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2063">2063</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2063">2063</a></td>
+ <td>DR</td>
<td>Type/nontype hiding in class scope</td>
<td class="none" align="center">Unknown</td>
</tr>
<tr id="2064">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2064">2064</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2064">2064</a></td>
+ <td>DR</td>
<td>Conflicting specifications for dependent <I>decltype-specifier</I>s</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -12208,8 +12208,8 @@ and <I>POD class</I></td>
<td align="center">Not resolved</td>
</tr>
<tr id="2066">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2066">2066</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2066">2066</a></td>
+ <td>DR</td>
<td>Does type-dependent imply value-dependent?</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -12220,14 +12220,14 @@ and <I>POD class</I></td>
<td align="center">Not resolved</td>
</tr>
<tr id="2068">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2068">2068</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2068">2068</a></td>
+ <td>DR</td>
<td>When can/must a defaulted virtual destructor be defined?</td>
<td class="none" align="center">Unknown</td>
</tr>
<tr id="2069">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2069">2069</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2069">2069</a></td>
+ <td>DR</td>
<td>Do destructors have names?</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -12238,8 +12238,8 @@ and <I>POD class</I></td>
<td align="center">Not resolved</td>
</tr>
<tr id="2071">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2071">2071</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2071">2071</a></td>
+ <td>DR</td>
<td><TT>typedef</TT> with no declarator</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -12251,7 +12251,7 @@ and <I>POD class</I></td>
</tr>
<tr class="open" id="2073">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2073">2073</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Allocating memory for exception objects</td>
<td align="center">Not resolved</td>
</tr>
@@ -12263,19 +12263,19 @@ and <I>POD class</I></td>
</tr>
<tr id="2075">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2075">2075</a></td>
- <td>DR</td>
+ <td>DRWP</td>
<td>Passing short initializer lists to array reference parameters</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2076">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2076">2076</a></td>
- <td>open</td>
+ <tr id="2076">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2076">2076</a></td>
+ <td>DRWP</td>
<td>List-initialization of arguments for constructor parameters</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2077">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2077">2077</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Overload resolution and invalid rvalue-reference initialization</td>
<td align="center">Not resolved</td>
</tr>
@@ -12286,8 +12286,8 @@ and <I>POD class</I></td>
<td class="none" align="center">Unknown</td>
</tr>
<tr id="2079">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2079">2079</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2079">2079</a></td>
+ <td>DR</td>
<td><TT>[[</TT> appearing in a <I>balanced-token-seq</I></td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -12304,26 +12304,26 @@ and <I>POD class</I></td>
<td align="center">Not resolved</td>
</tr>
<tr id="2082">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2082">2082</a></td>
- <td>ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2082">2082</a></td>
+ <td>DR</td>
<td>Referring to parameters in unevaluated operands of default arguments</td>
<td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2083">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2083">2083</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Incorrect cases of odr-use</td>
<td align="center">Not resolved</td>
</tr>
<tr id="2084">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2084">2084</a></td>
- <td>ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2084">2084</a></td>
+ <td>DR</td>
<td>NSDMIs and deleted union default constructors</td>
<td class="none" align="center">Unknown</td>
</tr>
<tr id="2085">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2085">2085</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2085">2085</a></td>
+ <td>DR</td>
<td>Invalid example of adding special member function via default argument</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -12341,7 +12341,7 @@ and <I>POD class</I></td>
</tr>
<tr class="open" id="2088">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2088">2088</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Late tiebreakers in partial ordering</td>
<td align="center">Not resolved</td>
</tr>
@@ -12357,39 +12357,39 @@ and <I>POD class</I></td>
<td>Dependency via non-dependent base class</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2091">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2091">2091</a></td>
- <td>open</td>
+ <tr id="2091">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2091">2091</a></td>
+ <td>DRWP</td>
<td>Deducing reference non-type template arguments</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2092">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2092">2092</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Deduction failure and overload resolution</td>
<td align="center">Not resolved</td>
</tr>
<tr id="2093">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2093">2093</a></td>
- <td>ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2093">2093</a></td>
+ <td>DR</td>
<td>Qualification conversion for pointer-to-member handler matching</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2094">
+ <tr id="2094">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2094">2094</a></td>
- <td>open</td>
+ <td>tentatively ready</td>
<td>Trivial copy/move constructor for class with volatile member</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="2095">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2095">2095</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2095">2095</a></td>
+ <td>DR</td>
<td>Capturing rvalue references to functions by copy</td>
<td class="none" align="center">Unknown</td>
</tr>
<tr id="2096">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2096">2096</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2096">2096</a></td>
+ <td>DR</td>
<td>Constraints on literal unions</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -12400,26 +12400,26 @@ and <I>POD class</I></td>
<td align="center">Not resolved</td>
</tr>
<tr id="2098">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2098">2098</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2098">2098</a></td>
+ <td>DR</td>
<td>Is <TT>uncaught_exceptions()</TT> per-thread?</td>
<td class="none" align="center">Unknown</td>
</tr>
<tr id="2099">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2099">2099</a></td>
- <td>ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2099">2099</a></td>
+ <td>DR</td>
<td>Inferring the bound of an array static data member</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2100">
+ <tr id="2100">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2100">2100</a></td>
- <td>open</td>
+ <td>tentatively ready</td>
<td>Value-dependent address of static data member of class template</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="2101">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2101">2101</a></td>
- <td>DR</td>
+ <td>DRWP</td>
<td>Incorrect description of type- and value-dependence</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -12436,8 +12436,8 @@ and <I>POD class</I></td>
<td align="center">Not resolved</td>
</tr>
<tr id="2104">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2104">2104</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2104">2104</a></td>
+ <td>DR</td>
<td>Internal-linkage <TT>constexpr</TT> references and ODR requirements</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -12448,26 +12448,26 @@ and <I>POD class</I></td>
<td align="center">Not resolved</td>
</tr>
<tr id="2106">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2106">2106</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2106">2106</a></td>
+ <td>DR</td>
<td>Unclear restrictions on use of function-type template arguments</td>
<td class="none" align="center">Unknown</td>
</tr>
<tr id="2107">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2107">2107</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2107">2107</a></td>
+ <td>DR</td>
<td>Lifetime of temporaries for default arguments in array copying</td>
<td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2108">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2108">2108</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Conversions to non-class prvalues in reference initialization</td>
<td align="center">Not resolved</td>
</tr>
<tr id="2109">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2109">2109</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2109">2109</a></td>
+ <td>DR</td>
<td>Value dependence underspecified</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -12478,8 +12478,8 @@ and <I>POD class</I></td>
<td align="center">Not resolved</td>
</tr>
<tr class="open" id="2111">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2111">2111</a></td>
- <td>open</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2111">2111</a></td>
+ <td>extension</td>
<td>Array temporaries in reference binding</td>
<td align="center">Not resolved</td>
</tr>
@@ -12490,20 +12490,20 @@ and <I>POD class</I></td>
<td align="center">Not resolved</td>
</tr>
<tr id="2113">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2113">2113</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2113">2113</a></td>
+ <td>DR</td>
<td>Incompete specification of types for declarators</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2114">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2114">2114</a></td>
- <td>review</td>
+ <tr id="2114">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2114">2114</a></td>
+ <td>CD3</td>
<td>Missing description of incompatibility from aggregate NSDMIs</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2115">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2115">2115</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Order of implicit destruction vs release of automatic storage</td>
<td align="center">Not resolved</td>
</tr>
@@ -12533,7 +12533,7 @@ and <I>POD class</I></td>
</tr>
<tr id="2120">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2120">2120</a></td>
- <td>DR</td>
+ <td>DRWP</td>
<td>Array as first non-static data member in standard-layout class</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -12544,8 +12544,8 @@ and <I>POD class</I></td>
<td align="center">Not resolved</td>
</tr>
<tr id="2122">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2122">2122</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2122">2122</a></td>
+ <td>DR</td>
<td>Glvalues of <TT>void</TT> type</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -12556,8 +12556,8 @@ and <I>POD class</I></td>
<td align="center">Not resolved</td>
</tr>
<tr id="2124">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2124">2124</a></td>
- <td>ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2124">2124</a></td>
+ <td>DR</td>
<td>Signature of constructor template</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -12586,14 +12586,14 @@ and <I>POD class</I></td>
<td align="center">Not resolved</td>
</tr>
<tr id="2129">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2129">2129</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2129">2129</a></td>
+ <td>DR</td>
<td>Non-object prvalues and constant expressions</td>
<td class="none" align="center">Unknown</td>
</tr>
<tr id="2130">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2130">2130</a></td>
- <td>ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2130">2130</a></td>
+ <td>DR</td>
<td>Over-aligned types in <I>new-expression</I>s</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -12633,17 +12633,17 @@ and <I>POD class</I></td>
<td>Argument-dependent lookup and initializer lists</td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2137">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2137">2137</a></td>
- <td>drafting</td>
+ <tr id="2137">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2137">2137</a></td>
+ <td>DRWP</td>
<td>List-initialization from object of same type</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2138">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2138">2138</a></td>
- <td>open</td>
+ <tr id="2138">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2138">2138</a></td>
+ <td>NAD</td>
<td>Explicit member specialization vs implicit instantiation</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="2139">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2139">2139</a></td>
@@ -12652,14 +12652,14 @@ and <I>POD class</I></td>
<td class="none" align="center">Unknown</td>
</tr>
<tr id="2140">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2140">2140</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2140">2140</a></td>
+ <td>DR</td>
<td>Lvalue-to-rvalue conversion of <TT>std::nullptr_t</TT></td>
<td class="none" align="center">Unknown</td>
</tr>
<tr id="2141">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2141">2141</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2141">2141</a></td>
+ <td>DR</td>
<td>Ambiguity in <I>new-expression</I> with <I>elaborated-type-specifier</I></td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -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_active.html#2143">2143</a></td>
- <td>tentatively ready</td>
+ <td>ready</td>
<td>Value-dependency via injected-class-name</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -12681,21 +12681,21 @@ and <I>POD class</I></td>
<td>Function/variable declaration ambiguity</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2145">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2145">2145</a></td>
- <td>drafting</td>
+ <tr id="2145">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2145">2145</a></td>
+ <td>DRWP</td>
<td>Parenthesized declarator in function definition</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="2146">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2146">2146</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2146">2146</a></td>
+ <td>DR</td>
<td>Scalar object vs memory location in definition of &#8220;unsequenced&#8221;</td>
<td class="none" align="center">Unknown</td>
</tr>
<tr id="2147">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2147">2147</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2147">2147</a></td>
+ <td>DR</td>
<td>Initializer-list arguments and pack deduction</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -12711,11 +12711,11 @@ and <I>POD class</I></td>
<td>Brace elision and array length deduction</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2150">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2150">2150</a></td>
- <td>review</td>
+ <tr id="2150">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2150">2150</a></td>
+ <td>CD3</td>
<td>Initializer list array lifetime</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2151">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2151">2151</a></td>
@@ -12730,32 +12730,32 @@ and <I>POD class</I></td>
<td class="none" align="center">Unknown</td>
</tr>
<tr id="2153">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2153">2153</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2153">2153</a></td>
+ <td>DR</td>
<td><I>pure-specifier</I> in friend declaration</td>
<td class="none" align="center">Unknown</td>
</tr>
<tr id="2154">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2154">2154</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2154">2154</a></td>
+ <td>DR</td>
<td>Ambiguity of <I>pure-specifier</I></td>
<td class="none" align="center">Unknown</td>
</tr>
- <tr class="open" id="2155">
+ <tr id="2155">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2155">2155</a></td>
- <td>review</td>
+ <td>ready</td>
<td>Defining classes and enumerations via <I>using-declaration</I>s</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr id="2156">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2156">2156</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2156">2156</a></td>
+ <td>DR</td>
<td>Definition of enumeration declared by <I>using-declaration</I></td>
<td class="none" align="center">Unknown</td>
</tr>
<tr id="2157">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2157">2157</a></td>
- <td>ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2157">2157</a></td>
+ <td>DR</td>
<td>Further disambiguation of enumeration <I>elaborated-type-specifier</I></td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -12784,14 +12784,14 @@ and <I>POD class</I></td>
<td class="none" align="center">Unknown</td>
</tr>
<tr id="2162">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2162">2162</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2162">2162</a></td>
+ <td>CD3</td>
<td>Capturing <TT>this</TT> by reference</td>
<td class="none" align="center">Unknown</td>
</tr>
<tr id="2163">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2163">2163</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2163">2163</a></td>
+ <td>DR</td>
<td>Labels in <TT>constexpr</TT> functions</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -12814,8 +12814,8 @@ and <I>POD class</I></td>
<td align="center">Not resolved</td>
</tr>
<tr id="2167">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2167">2167</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2167">2167</a></td>
+ <td>DR</td>
<td>Non-member references with lifetimes within the current evaluation</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -12826,8 +12826,8 @@ and <I>POD class</I></td>
<td align="center">Not resolved</td>
</tr>
<tr class="open" id="2169">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2169">2169</a></td>
- <td>open</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2169">2169</a></td>
+ <td>extension</td>
<td>Narrowing conversions and overload resolution</td>
<td align="center">Not resolved</td>
</tr>
@@ -12837,11 +12837,11 @@ and <I>POD class</I></td>
<td>Unclear definition of odr-use for arrays</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2171">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2171">2171</a></td>
- <td>drafting</td>
+ <tr id="2171">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2171">2171</a></td>
+ <td>DRWP</td>
<td>Triviality of copy constructor with less-qualified parameter</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2172">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2172">2172</a></td>
@@ -12857,19 +12857,19 @@ and <I>POD class</I></td>
</tr>
<tr class="open" id="2174">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2174">2174</a></td>
- <td>review</td>
+ <td>drafting</td>
<td>Unclear rules for friend definitions in templates</td>
<td align="center">Not resolved</td>
</tr>
<tr id="2175">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2175">2175</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2175">2175</a></td>
+ <td>DR</td>
<td>Ambiguity with attribute in conversion operator declaration</td>
<td class="none" align="center">Unknown</td>
</tr>
<tr id="2176">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2176">2176</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2176">2176</a></td>
+ <td>DR</td>
<td>Destroying the returned object when a destructor throws</td>
<td class="none" align="center">Unknown</td>
</tr>
@@ -12879,45 +12879,45 @@ and <I>POD class</I></td>
<td>Placement <TT>operator delete</TT> and parameter copies</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2178">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2178">2178</a></td>
- <td>open</td>
+ <tr id="2178">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2178">2178</a></td>
+ <td>NAD</td>
<td>Substitution of dependent template arguments in default template arguments</td>
- <td align="center">Not resolved</td>
+ <td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2179">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2179">2179</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Required diagnostic for partial specialization after first use</td>
<td align="center">Not resolved</td>
</tr>
<tr id="2180">
- <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2180">2180</a></td>
- <td>tentatively ready</td>
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2180">2180</a></td>
+ <td>DR</td>
<td>Virtual bases in destructors and defaulted assignment operators</td>
<td class="none" align="center">Unknown</td>
</tr>
<tr class="open" id="2181">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2181">2181</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Normative requirements in an informative Annex</td>
<td align="center">Not resolved</td>
</tr>
<tr class="open" id="2182">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2182">2182</a></td>
- <td>open</td>
+ <td>drafting</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>open</td>
+ <td>review</td>
<td>Problems in description of potential exceptions</td>
<td align="center">Not resolved</td>
</tr>
<tr class="open" id="2184">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2184">2184</a></td>
- <td>open</td>
+ <td>review</td>
<td>Missing C compatibility entry for decrement of <TT>bool</TT></td>
<td align="center">Not resolved</td>
</tr>
@@ -12929,10 +12929,520 @@ and <I>POD class</I></td>
</tr>
<tr class="open" id="2186">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2186">2186</a></td>
- <td>open</td>
+ <td>drafting</td>
<td>Unclear point that &#8220;preceding initialization&#8221; must precede</td>
<td align="center">Not resolved</td>
</tr>
+ <tr class="open" id="2187">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2187">2187</a></td>
+ <td>open</td>
+ <td>Protected members and access via <I>qualified-id</I></td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2188">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2188">2188</a></td>
+ <td>open</td>
+ <td><I>empty-declaration</I> ambiguity</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2189">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2189">2189</a></td>
+ <td>open</td>
+ <td>Surrogate call template</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2190">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2190">2190</a></td>
+ <td>open</td>
+ <td>Insufficient specification of <TT>__has_include</TT></td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2191">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2191">2191</a></td>
+ <td>open</td>
+ <td>Incorrect result for <TT>noexcept(typeid(v))</TT></td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2192">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2192">2192</a></td>
+ <td>open</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>
+ <td><TT>numeric_limits&lt;int&gt;::radix</TT> and <TT>digits</TT></td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <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>open</td>
+ <td>Impossible case in list initialization</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>
+ <td>open</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>
+ <td>Zero-initialization with virtual base classes</td>
+ <td align="center">Not resolved</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>Overload resolution and deleted special member functions</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2198">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2198">2198</a></td>
+ <td>open</td>
+ <td>Linkage of enumerators</td>
+ <td align="center">Not resolved</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>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>
+ <td>Conversions in template argument deduction</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2201">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2201">2201</a></td>
+ <td>open</td>
+ <td>Cv-qualification of array types</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2202">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2202">2202</a></td>
+ <td>open</td>
+ <td>When does default argument instantiation occur?</td>
+ <td align="center">Not resolved</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>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>
+ <td>Naming delegated constructors</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2205">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2205">2205</a></td>
+ <td>open</td>
+ <td>Restrictions on use of <TT>alignas</TT></td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2206">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2206">2206</a></td>
+ <td>open</td>
+ <td>Composite type of object and function pointers</td>
+ <td align="center">Not resolved</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>Alignment of allocation function return value</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr id="2208">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2208">2208</a></td>
+ <td>NAD</td>
+ <td><I>static_assert-declaration</I> does not declare a member</td>
+ <td class="none" align="center">Unknown</td>
+ </tr>
+ <tr id="2209">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2209">2209</a></td>
+ <td>NAD</td>
+ <td>Destruction of constructed array elements</td>
+ <td class="none" align="center">Unknown</td>
+ </tr>
+ <tr id="2210">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2210">2210</a></td>
+ <td>NAD</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>
+ <td>Hiding by lambda captures and parameters</td>
+ <td align="center">Not resolved</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>
+ <td>open</td>
+ <td>Typedef changing linkage after use</td>
+ <td align="center">Not resolved</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>Forward declaration of partial specializations</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2214">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2214">2214</a></td>
+ <td>open</td>
+ <td>Missing requirement on representation of integer values</td>
+ <td align="center">Not resolved</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>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>
+ <td>Exception specifications in unevaluated contexts</td>
+ <td align="center">Not resolved</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>
+ <td><TT>constexpr</TT> constructors for non-literal types</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2218">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2218">2218</a></td>
+ <td>open</td>
+ <td>Ambiguity and namespace aliases</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2219">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2219">2219</a></td>
+ <td>open</td>
+ <td>Dynamically-unreachable handlers</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2220">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2220">2220</a></td>
+ <td>open</td>
+ <td>Hiding index variable in range-based <TT>for</TT></td>
+ <td align="center">Not resolved</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>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>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>Multiple <TT>alignas</TT> specifiers</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2224">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2224">2224</a></td>
+ <td>open</td>
+ <td>Member subobjects and base-class casts</td>
+ <td align="center">Not resolved</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>
+ <td><TT>reinterpret_cast</TT> to same floating-point type</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" 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>Xvalues vs lvalues in conditional expressions</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" 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>Destructor access and default member initializers</td>
+ <td align="center">Not resolved</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>Ambiguity resolution for cast to function type</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" 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>Volatile unnamed bit-fields</td>
+ <td align="center">Not resolved</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>
+ <td>Linkage of <TT>extern "C"</TT> function in unnamed namespace</td>
+ <td align="center">Not resolved</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>
+ <td>Class member access to static data member template</td>
+ <td align="center">Not resolved</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>
+ <td>open</td>
+ <td><TT>thread_local</TT> anonymous unions</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" 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>Function parameter packs following default arguments</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" 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>Missing rules for <I>simple-template-id</I> as <I>class-name</I></td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" 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>Partial ordering and non-dependent types</td>
+ <td align="center">Not resolved</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>When is an alias template specialization dependent?</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" 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>Can a <I>template-id</I> name a constructor?</td>
+ <td align="center">Not resolved</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>
+ <td>Contradictory alignment requirements for allocation</td>
+ <td align="center">Not resolved</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>
+ <td>Sized deallocation with a trivial destructor</td>
+ <td align="center">Not resolved</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>
+ <td>open</td>
+ <td><TT>this</TT> is not odr-used in a constant expression</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2241">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2241">2241</a></td>
+ <td>open</td>
+ <td>Overload resolution is not invoked with a single function</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2242">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2242">2242</a></td>
+ <td>drafting</td>
+ <td>ODR violation with constant initialization possibly omitted</td>
+ <td align="center">Not resolved</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>Incorrect use of implicit conversion sequence</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2244">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2244">2244</a></td>
+ <td>open</td>
+ <td>Base class access in aggregate initialization</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2245">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2245">2245</a></td>
+ <td>open</td>
+ <td>Point of instantiation of incomplete class template</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2246">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2246">2246</a></td>
+ <td>open</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>
+ <td>Lambda capture and variable argument list</td>
+ <td align="center">Not resolved</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>open</td>
+ <td>Problems with sized delete</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" 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><I>identifier</I>s and <I>id-expression</I>s</td>
+ <td align="center">Not resolved</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>
+ <td>open</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>open</td>
+ <td>Unreachable enumeration list-initialization</td>
+ <td align="center">Not resolved</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>
+ <td>open</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>
+ <td>Unnamed bit-fields and zero-initialization</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" 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>
+ </tr>
+ <tr class="open" 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>Instantiated static data member templates</td>
+ <td align="center">Not resolved</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>
+ <td>open</td>
+ <td>Lifetime of trivially-destructible objects</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2257">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2257">2257</a></td>
+ <td>open</td>
+ <td>Lifetime extension of references vs exceptions</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2258">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2258">2258</a></td>
+ <td>open</td>
+ <td>Storage deallocation during period of destruction</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2259">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2259">2259</a></td>
+ <td>open</td>
+ <td>Unclear context describing ambiguity</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" 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>Explicit specializations of deleted member functions</td>
+ <td align="center">Not resolved</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>
+ <td>open</td>
+ <td>Explicit instantiation of in-class <TT>friend</TT> definition</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2262">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2262">2262</a></td>
+ <td>open</td>
+ <td>Attributes for <I>asm-definition</I></td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2263">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2263">2263</a></td>
+ <td>open</td>
+ <td>Default argument instantiation for <TT>friend</TT>s</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2264">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2264">2264</a></td>
+ <td>open</td>
+ <td>Memberwise copying with indeterminate value</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2265">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2265">2265</a></td>
+ <td>open</td>
+ <td>Delayed pack expansion and member redeclarations</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2266">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2266">2266</a></td>
+ <td>open</td>
+ <td>Has dependent type vs is type-dependent</td>
+ <td align="center">Not resolved</td>
+ </tr>
+ <tr class="open" id="2267">
+ <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2267">2267</a></td>
+ <td>open</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>
+ <td>Unions with mutable members in constant expressions revisited</td>
+ <td align="center">Not resolved</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>
+ <td>Additional recursive references in aggregate DMIs</td>
+ <td align="center">Not resolved</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>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_active.html#2271">2271</a></td>
+ <td>ready</td>
+ <td>Aliasing <TT>this</TT></td>
+ <td class="none" align="center">Unknown</td>
+ </tr>
</table>
</div>
diff --git a/www/cxx_status.html b/www/cxx_status.html
index 70becc7dbf6b..c1dc78cf56b0 100644
--- a/www/cxx_status.html
+++ b/www/cxx_status.html
@@ -1,8 +1,7 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
- "http://www.w3.org/TR/html4/strict.dtd">
+<!DOCTYPE html>
<html>
<head>
- <META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+ <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Clang - C++1z, C++14, C++11 and C++98 Status</title>
<link type="text/css" rel="stylesheet" href="menu.css">
<link type="text/css" rel="stylesheet" href="content.css">
@@ -26,13 +25,13 @@
<!--*************************************************************************-->
<h1>C++ Support in Clang</h1>
<!--*************************************************************************-->
-<p>Last updated: $Date: 2016-07-14 02:14:59 +0200 (Thu, 14 Jul 2016) $</p>
+<p>Last updated: $Date: 2016-12-31 22:41:23 +0100 (Sat, 31 Dec 2016) $</p>
-<p>Clang fully implements all published ISO C++ standards including <a
-href="#cxx11">C++11</a>, as well as the upcoming <a
-href="#cxx14">C++14</a> standard, and some parts of the fledgling <a
-href="#cxx17">C++1z</a> standard,
-and is considered a production-quality C++ compiler.
+<p>Clang fully implements all published ISO C++ standards (<a
+href="#cxx98">C++98 / C++03</a>, <a
+href="#cxx11">C++11</a>, and <a
+href="#cxx14">C++14</a>), and most of the upcoming <a
+href="#cxx17">C++1z</a> standard.
<p>The Clang community is continually striving to improve C++ standards
compliance between releases by submitting and tracking <a
@@ -55,20 +54,17 @@ 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/iso_catalogue/catalogue_tc/catalogue_detail.htm?csnumber=50372">ISO
- C++ 2011 standard</a>. The following table describes the Clang version
- in which each feature became available.</p>
+<p>Clang 3.3 and later implement all of the <a
+ href="http://www.iso.org/iso/catalogue_detail.htm?csnumber=50372">ISO
+ C++ 2011 standard</a>.
<p>By default, Clang builds C++ code according to the C++98 standard, with many
C++11 features accepted as extensions. You can use Clang in C++11 mode with the
<code>-std=c++11</code> option. Clang's C++11 mode can be used
-with <a href="http://libcxx.llvm.org/">libc++</a> or with gcc's libstdc++, but
-patches are needed to make <a href="libstdc++4.4-clang0x.patch">libstdc++-4.4</a>
-work with Clang in C++11 mode. Patches are also needed to make
-<a href="libstdc++4.6-clang11.patch">libstdc++-4.6</a>
-and <a href="libstdc++4.7-clang11.patch">libstdc++-4.7</a> work with Clang
-releases prior to version 3.2 in C++11 mode.
+with <a href="http://libcxx.llvm.org/">libc++</a> or with gcc's libstdc++.
+
+<details>
+<summary>List of features and minimum Clang version with support</summary>
<table width="689" border="1" cellspacing="0">
<tr>
@@ -425,18 +421,20 @@ such as Clang that does not provide any extended integer types.
because changing <code>intmax_t</code> would be an ABI-incompatible
change.</span>
</p>
+</details>
<h2 id="cxx14">C++14 implementation status</h2>
-<p>Clang 3.4 and later implement all of the Draft International Standard (see <a
-href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3797.pdf">most
-recent publicly available draft</a>)
-of the upcoming C++14 language standard. The following table describes the
-Clang version in which each feature became available.</p>
+<p>Clang 3.4 and later implement all of the <a
+ href="http://www.iso.org/iso/catalogue_detail.htm?csnumber=64029">ISO
+ C++ 2014 standard</a>.
<p>You can use Clang in C++14 mode with the <code>-std=c++14</code> option
(use <code>-std=c++1y</code> in Clang 3.4 and earlier).</p>
+<details>
+<summary>List of features and minimum Clang version with support</summary>
+
<table width="689" border="1" cellspacing="0">
<tr>
<th>Language Feature</th>
@@ -518,27 +516,27 @@ added these functions in version 5.0, and <code>libc++</code> added them in
version 3.7.
</span>
</p>
+</details>
<h2 id="cxx17">C++1z implementation status</h2>
<p>Clang has <b>experimental</b> support for some proposed features of
the C++ standard following C++14, provisionally named C++1z.
-The following table describes which C++1z features
-have been implemented in Clang and in which Clang version they became
-available.</p>
-
-<p>Note that support for these features may change or be removed without notice,
-as the draft C++1z standard evolves.</p>
+Note that support for these features may change or be removed without notice,
+as the draft C++1z standard evolves.
<p>You can use Clang in C++1z mode with the <code>-std=c++1z</code> option.</p>
+<details open>
+<summary>List of features and minimum Clang version with support</summary>
+
<table width="689" border="1" cellspacing="0">
<tr>
<th>Language Feature</th>
<th>C++1z Proposal</th>
<th>Available in Clang?</th>
</tr>
- <!-- Issaquah papers -->
+ <!-- Issaquah 2014 papers -->
<tr>
<td><tt>static_assert</tt> with no message</td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3928.pdf">N3928</a></td>
@@ -578,7 +576,7 @@ as the draft C++1z standard evolves.</p>
</tr>
<tr> <!-- from Jacksonville -->
<td><a href="http://wg21.link/p0036r0">P0036R0</a></td>
- <td class="svn" align="center">SVN</td>
+ <td class="full" align="center">Clang 3.9</td>
</tr>
<tr>
<td><tt>u8</tt> character literals</td>
@@ -614,7 +612,7 @@ as the draft C++1z standard evolves.</p>
<tr>
<td>Make exception specifications part of the type system</td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0012r1.html">P0012R1</a></td>
- <td class="none" align="center">No</td>
+ <td class="svn" align="center">SVN</td>
</tr>
<tr>
<td><tt>__has_include</tt> in preprocessor conditionals</td>
@@ -624,28 +622,28 @@ as the draft C++1z standard evolves.</p>
<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="svn" align="center">SVN <a href="#p0136">(9)</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>
<td><a href="http://wg21.link/p0188r1">P0188R1</a></td>
- <td class="svn" align="center">SVN</td>
+ <td class="full" align="center">Clang 3.9</td>
</tr>
<tr>
<td><tt>[[nodiscard]]</tt> attribute</td>
<td><a href="http://wg21.link/p0189r1">P0189R1</a></td>
- <td class="svn" align="center">SVN</td>
+ <td class="full" align="center">Clang 3.9</td>
</tr>
<tr>
<td><tt>[[maybe_unused]]</tt> attribute</td>
<td><a href="http://wg21.link/p0212r1">P0212R1</a></td>
- <td class="svn" align="center">SVN</td>
+ <td class="full" align="center">Clang 3.9</td>
</tr>
<tr>
<td>Aggregate initialization of classes with base classes</td>
<td><a href="http://wg21.link/p0017r1">P0017R1</a></td>
- <td class="svn" align="center">SVN</td>
+ <td class="full" align="center">Clang 3.9</td>
</tr>
<tr>
<td><tt>constexpr</tt> lambda expressions</td>
@@ -655,17 +653,17 @@ as the draft C++1z standard evolves.</p>
<tr>
<td>Differing <tt>begin</tt> and <tt>end</tt> types in range-based <tt>for</tt></td>
<td><a href="http://wg21.link/p0184r0">P0184R0</a></td>
- <td class="svn" align="center">SVN</td>
+ <td class="full" align="center">Clang 3.9</td>
</tr>
<tr>
<td>Lambda capture of <tt>*this</tt></td>
<td><a href="http://wg21.link/p0018r3">P0018R3</a></td>
- <td class="svn" align="center">SVN</td>
+ <td class="full" align="center">Clang 3.9</td>
</tr>
<tr>
<td>Direct-list-initialization of <tt>enum</tt>s</td>
<td><a href="http://wg21.link/p0138r2">P0138R2</a></td>
- <td class="svn" align="center">SVN</td>
+ <td class="full" align="center">Clang 3.9</td>
</tr>
<tr>
<td>Hexadecimal floating-point literals</td>
@@ -676,12 +674,12 @@ as the draft C++1z standard evolves.</p>
<tr>
<td>Using attribute namespaces without repetition</td>
<td><a href="http://wg21.link/p0028r4">P0028R4</a></td>
- <td class="svn" align="center">SVN</td>
+ <td class="full" align="center">Clang 3.9</td>
</tr>
<tr>
<td>Dynamic memory allocation for over-aligned data</td>
<td><a href="http://wg21.link/p0035r4">P0035R4</a></td>
- <td class="none" align="center">No</td>
+ <td class="svn" align="center">SVN</td>
</tr>
<tr>
<td>Template argument deduction for class templates</td>
@@ -691,17 +689,17 @@ as the draft C++1z standard evolves.</p>
<tr>
<td>Non-type template parameters with <tt>auto</tt> type</td>
<td><a href="http://wg21.link/p0127r2">P0127R2</a></td>
- <td class="none" align="center">No</td>
+ <td class="svn" align="center">SVN</td>
</tr>
<tr>
<td>Guaranteed copy elision</td>
<td><a href="http://wg21.link/p0135r1">P0135R1</a></td>
- <td class="none" align="center">No</td>
+ <td class="svn" align="center">SVN</td>
</tr>
<tr>
<td rowspan=2>Stricter expression evaluation order</td>
<td><a href="http://wg21.link/p0145r3">P0145R3</a></td>
- <td class="none" align="center" rowspan=2>No</td>
+ <td class="svn" align="center" rowspan=2>SVN <a href="#p0145">(10)</a></td>
</tr>
<tr>
<td><a href="http://wg21.link/p0400r0">P0400R0</a></td>
@@ -714,21 +712,37 @@ as the draft C++1z standard evolves.</p>
<tr>
<td><tt>constexpr</tt> <em>if-statement</em>s</td>
<td><a href="http://wg21.link/p0292r2">P0292R2</a></td>
- <td class="svn" align="center">SVN</td>
+ <td class="full" align="center">Clang 3.9</td>
</tr>
<tr>
<td>Inline variables</td>
<td><a href="http://wg21.link/p0386r2">P0386R2</a></td>
- <td class="svn" align="center">SVN</td>
+ <td class="full" align="center">Clang 3.9</td>
</tr>
<tr>
<td>Structured bindings</td>
<td><a href="http://wg21.link/p0217r3">P0217R3</a></td>
- <td class="none" align="center">No</td>
+ <td class="svn" align="center">SVN</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>
+ <td class="full" align="center">Clang 3.9</td>
+ </tr>
+ <!-- Issaquah 2016 papers -->
+ <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>
+ </tr>
+ <tr>
+ <td>Removing deprecated dynamic exception specifications</td>
+ <td><a href="http://wg21.link/p0003r5">P0003R5</a></td>
+ <td class="svn" align="center">SVN</td>
+ </tr>
+ <tr>
+ <td>Pack expansions in <em>using-declarations</em></td>
+ <td><a href="http://wg21.link/p0195r2">P0195R2</a></td>
<td class="svn" align="center">SVN</td>
</tr>
</table>
@@ -741,25 +755,43 @@ 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
+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
+feature is disabled by default in all language versions, and can be enabled
+explicitly with the flag <tt>-frelaxed-template-template-args</tt>. The change
+to the standard lacks a corresponding change for template partial ordering,
+resulting in ambiguity errors for reasonable and previously-valid code. This
+issue is expected to be rectified soon.
</span>
</p>
+</details>
<h2 id="ts">Technical specifications and standing documents</h2>
<p>ISO C++ also publishes a number of documents describing additional language
-and library features that are not part of standard C++. The following table
-describes which language features have been implemented in Clang and in which
-Clang version they became available:</p>
+and library features that are not part of standard C++.</p>
+
+<details open>
+<summary>List of features and minimum Clang version with support</summary>
<table width="689" border="1" cellspacing="0">
<tr>
<th>Document</th>
<th>Latest draft</th>
+ <th>Compiler flag</th>
<th>Available in Clang?</th>
</tr>
<tr>
- <td rowspan="2">SD-6: SG10 feature test recommendations</td>
- <td rowspan="2"><a href="http://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations">SD-6</a></td>
+ <td rowspan="3">SD-6: SG10 feature test recommendations</td>
+ <td rowspan="3"><a href="http://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations">SD-6</a></td>
+ <td rowspan="3">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>
@@ -769,10 +801,15 @@ Clang version they became available:</p>
Clang 3.6 (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4200">N4200</a>)</a>
</td>
</tr>
+ <tr>
+ <td class="svn" align="center">
+ SVN (<a href="http://wg21.link/p0096r3">P0096R3</a>)</a>
+ </td>
+ </tr>
<!-- FIXME: Implement latest recommendations.
<tr>
<td class="svn" align="center">
- SVN (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0096r0">P0096R0</a>)</a>
+ SVN (<a href="http://wg21.link/p0096r3">P0096R3</a>)</a>
</td>
</tr>
-->
@@ -786,29 +823,41 @@ Clang version they became available:</p>
<tr>
<td>[TS] Concepts</td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0121r0.pdf">P0121R0</a></td>
- <td class="none" align="center">No</td>
+ <td></td>
+ <td class="none" align="center">WIP</td>
+ </tr>
+ <tr>
+ <td>[DRAFT TS] Coroutines</td>
+ <td><a href="http://wg21.link/p0057r7">P0057R7</a></td>
+ <td></td>
+ <td class="none" align="center">WIP</td>
</tr>
<tr>
<td>[TS] Library Fundamentals, Version 1 (invocation type traits)</td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4480.html">N4480</a></td>
+ <td>N/A</td>
<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://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4529.html">N4529</a></td>
+ <td><a href="http://wg21.link/n4600">N4600</a></td>
+ <td>N/A</td>
<td class="none" align="center">No</td>
</tr>
<tr>
- <td>[TS] Modules</td>
- <td><a href="http://wg21.link/p0143r2">P0143R2</a></td>
- <td class="none" align="center">No</td>
+ <td>[DRAFT TS] Modules</td>
+ <td><a href="http://wg21.link/n4592">N4592</a></td>
+ <td><tt>-fmodules-ts</tt></td>
+ <td class="none" align="center">WIP</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>
<td class="none" align="center">No</td>
</tr>
</table>
+</details>
</div>
</body>
diff --git a/www/get_started.html b/www/get_started.html
index 0039b5603013..a8fe3c717f8c 100644
--- a/www/get_started.html
+++ b/www/get_started.html
@@ -30,6 +30,8 @@ bugs in <a href="http://llvm.org/bugs/">LLVM Bugzilla</a>.</p>
<h3 id="buildNix">On Unix-like Systems</h3>
+<p>Note: as an experimental setup, you can use a <b>single checkout</b> with all the projects, and an <b>easy CMake invocation</b>, see the LLVM Doc "<a href="http://llvm.org/docs/GettingStarted.html#for-developers-to-work-with-a-git-monorepo">For developers to work with a git monorepo</a>"</p>
+
<p>If you would like to check out and build Clang, the current procedure is as
follows:</p>
@@ -118,6 +120,11 @@ follows:</p>
<li><tt>clang file.c -S -O3 -o -</tt> (output native machine code)</li>
</ul>
</li>
+ <li>Run the testsuite:
+ <ul>
+ <li><tt>make check-clang</tt></li>
+ </ul>
+ </li>
</ol>
<p>If you encounter problems while building Clang, make sure that your LLVM
diff --git a/www/make_cxx_dr_status b/www/make_cxx_dr_status
index 9a679ed9f505..48f524208a4c 100755
--- a/www/make_cxx_dr_status
+++ b/www/make_cxx_dr_status
@@ -99,6 +99,12 @@ def availability(issue):
if status.endswith(' c++11'):
status = status[:-6]
avail_suffix = ' (C++11 onwards)'
+ elif status.endswith(' c++14'):
+ status = status[:-6]
+ avail_suffix = ' (C++14 onwards)'
+ elif status.endswith(' c++17'):
+ status = status[:-6]
+ avail_suffix = ' (C++17 onwards)'
if status == 'unknown':
avail = 'Unknown'
avail_style = ' class="none"'
@@ -120,6 +126,9 @@ def availability(issue):
elif status == 'na':
avail = 'N/A'
avail_style = ' class="na"'
+ elif status == 'na lib':
+ avail = 'N/A (Library DR)'
+ avail_style = ' class="na"'
elif status.startswith('sup '):
dup = status.split(' ', 1)[1]
avail = 'Superseded by <a href="#%s">%s</a>' % (dup, dup)
@@ -161,7 +170,7 @@ for dr in drs:
<td%s align="center">%s</td>
</tr>''' % (row_style, dr.issue, dr.url, dr.issue, dr.status, dr.title, avail_style, avail)
-for status, num in count.items():
+for status, num in sorted(count.items()):
print "%s: %s" % (status, num)
print >> out_file, '''\
diff --git a/www/menu.html.incl b/www/menu.html.incl
index abbd2c1cc16a..61a44e839000 100644
--- a/www/menu.html.incl
+++ b/www/menu.html.incl
@@ -51,7 +51,7 @@
<div class="submenu">
<label>Quick Links</label>
- <a href="http://buildd-clang.debian.net/coverage/">Testing Coverage</a>
+ <a href="http://llvm.org/reports/coverage/">Testing Coverage</a>
</div>
<div class="submenu">
diff --git a/www/related.html b/www/related.html
index 560787eb2236..0772797c654f 100644
--- a/www/related.html
+++ b/www/related.html
@@ -64,7 +64,7 @@
<dd>
<p>
<b>Site:</b>
- <a href="http://code.google.com/p/include-what-you-use/">http://code.google.com/p/include-what-you-use/</a>
+ <a href="https://github.com/include-what-you-use/include-what-you-use">https://github.com/include-what-you-use/include-what-you-use</a>
</p>
<p>
Analyze #includes in C and C++ source files